summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucas Eckels <eckels@google.com>2012-08-06 15:10:42 -0700
committerLucas Eckels <eckels@google.com>2012-08-08 09:28:58 -0700
commit71163caf89862f79f6419077cf6f0b18b7725d52 (patch)
tree2ae1fe786222abb03d00ac4efdfce94bd729d862
parent497a4aa54eefdd7fcb7de77e9fd1ae5f8271cd2f (diff)
downloadfree-image-71163caf89862f79f6419077cf6f0b18b7725d52.tar.gz
Add freeimage source.
Change-Id: I6b83548e118853b41cfbac3c937d2b552e6453bb
-rw-r--r--.gitignore33
-rw-r--r--Dist/delete.me0
-rw-r--r--Examples/Generic/BatchLoad.cpp214
-rw-r--r--Examples/Generic/CloneMultiPage.cpp112
-rw-r--r--Examples/Generic/CreateAlpha.cpp181
-rw-r--r--Examples/Generic/FIFImportExport.cpp149
-rw-r--r--Examples/Generic/FIIO_Mem.cpp146
-rw-r--r--Examples/Generic/FIIO_Mem.h74
-rw-r--r--Examples/Generic/LoadFromHandle.cpp145
-rw-r--r--Examples/Generic/LoadFromMemory-classified.cpp101
-rw-r--r--Examples/Generic/LoadFromMemory.cpp113
-rw-r--r--Examples/Generic/ShowMetadata.cpp317
-rw-r--r--Examples/Linux/Makefile25
-rw-r--r--Examples/Linux/linux-gtk.c97
-rw-r--r--Examples/Linux/linux-svgalib.c96
-rw-r--r--Examples/OpenGL/TextureManager/TextureManager.cpp145
-rw-r--r--Examples/OpenGL/TextureManager/TextureManager.h51
-rw-r--r--Examples/OpenGL/TextureManager/readme.txt31
-rw-r--r--Examples/Plugin/PluginCradle.cpp253
-rw-r--r--Examples/Plugin/PluginCradle.h45
-rw-r--r--FreeImage.2003.sln118
-rw-r--r--FreeImage.2003.vcproj495
-rw-r--r--FreeImage.2005.sln103
-rw-r--r--FreeImage.2005.vcproj645
-rw-r--r--FreeImage.2008.sln76
-rw-r--r--FreeImage.2008.vcproj628
-rw-r--r--FreeImage.rc95
-rw-r--r--FreeImage.xcodeproj/project.pbxproj1016
-rw-r--r--FreeImage3130.pdfbin0 -> 1016148 bytes
-rw-r--r--Makefile34
-rw-r--r--Makefile.cygwin73
-rw-r--r--Makefile.fip73
-rw-r--r--Makefile.gnu65
-rw-r--r--Makefile.mingw123
-rw-r--r--Makefile.osx93
-rw-r--r--Makefile.solaris65
-rw-r--r--Makefile.srcs6
-rw-r--r--README.linux50
-rw-r--r--README.minGW236
-rw-r--r--README.osx44
-rw-r--r--README.solaris67
-rw-r--r--Source/CacheFile.h92
-rw-r--r--Source/DeprecationManager/Deprecated.cpp36
-rw-r--r--Source/DeprecationManager/DeprecationMgr.cpp103
-rw-r--r--Source/DeprecationManager/DeprecationMgr.h83
-rw-r--r--Source/FreeImage.h1090
-rw-r--r--Source/FreeImage/BitmapAccess.cpp1080
-rw-r--r--Source/FreeImage/CacheFile.cpp274
-rw-r--r--Source/FreeImage/ColorLookup.cpp782
-rw-r--r--Source/FreeImage/Conversion.cpp203
-rw-r--r--Source/FreeImage/Conversion16_555.cpp209
-rw-r--r--Source/FreeImage/Conversion16_565.cpp204
-rw-r--r--Source/FreeImage/Conversion24.cpp214
-rw-r--r--Source/FreeImage/Conversion32.cpp319
-rw-r--r--Source/FreeImage/Conversion4.cpp246
-rw-r--r--Source/FreeImage/Conversion8.cpp327
-rw-r--r--Source/FreeImage/ConversionRGBF.cpp179
-rw-r--r--Source/FreeImage/ConversionType.cpp687
-rw-r--r--Source/FreeImage/FreeImage.cpp226
-rw-r--r--Source/FreeImage/FreeImageC.c22
-rw-r--r--Source/FreeImage/FreeImageIO.cpp166
-rw-r--r--Source/FreeImage/GetType.cpp92
-rw-r--r--Source/FreeImage/Halftoning.cpp474
-rw-r--r--Source/FreeImage/J2KHelper.cpp493
-rw-r--r--Source/FreeImage/MemoryIO.cpp234
-rw-r--r--Source/FreeImage/MultiPage.cpp892
-rw-r--r--Source/FreeImage/NNQuantizer.cpp507
-rw-r--r--Source/FreeImage/PSDParser.cpp1526
-rw-r--r--Source/FreeImage/PSDParser.h258
-rw-r--r--Source/FreeImage/PixelAccess.cpp204
-rw-r--r--Source/FreeImage/Plugin.cpp792
-rw-r--r--Source/FreeImage/PluginBMP.cpp1381
-rw-r--r--Source/FreeImage/PluginCUT.cpp197
-rw-r--r--Source/FreeImage/PluginDDS.cpp649
-rw-r--r--Source/FreeImage/PluginEXR.cpp641
-rw-r--r--Source/FreeImage/PluginG3.cpp433
-rw-r--r--Source/FreeImage/PluginGIF.cpp1398
-rw-r--r--Source/FreeImage/PluginHDR.cpp702
-rw-r--r--Source/FreeImage/PluginICO.cpp720
-rw-r--r--Source/FreeImage/PluginIFF.cpp457
-rw-r--r--Source/FreeImage/PluginJ2K.cpp335
-rw-r--r--Source/FreeImage/PluginJP2.cpp335
-rw-r--r--Source/FreeImage/PluginJPEG.cpp1448
-rw-r--r--Source/FreeImage/PluginKOALA.cpp243
-rw-r--r--Source/FreeImage/PluginMNG.cpp316
-rw-r--r--Source/FreeImage/PluginPCD.cpp229
-rw-r--r--Source/FreeImage/PluginPCX.cpp607
-rw-r--r--Source/FreeImage/PluginPFM.cpp390
-rw-r--r--Source/FreeImage/PluginPICT.cpp1332
-rw-r--r--Source/FreeImage/PluginPNG.cpp924
-rw-r--r--Source/FreeImage/PluginPNM.cpp808
-rw-r--r--Source/FreeImage/PluginPSD.cpp125
-rw-r--r--Source/FreeImage/PluginRAS.cpp496
-rw-r--r--Source/FreeImage/PluginRAW.cpp490
-rw-r--r--Source/FreeImage/PluginSGI.cpp425
-rw-r--r--Source/FreeImage/PluginTARGA.cpp1204
-rw-r--r--Source/FreeImage/PluginTIFF.cpp2234
-rw-r--r--Source/FreeImage/PluginWBMP.cpp372
-rw-r--r--Source/FreeImage/PluginXBM.cpp399
-rw-r--r--Source/FreeImage/PluginXPM.cpp474
-rw-r--r--Source/FreeImage/TIFFLogLuv.cpp65
-rw-r--r--Source/FreeImage/ToneMapping.cpp75
-rw-r--r--Source/FreeImage/WuQuantizer.cpp537
-rw-r--r--Source/FreeImage/ZLibInterface.cpp229
-rw-r--r--Source/FreeImage/tmoColorConvert.cpp479
-rw-r--r--Source/FreeImage/tmoDrago03.cpp295
-rw-r--r--Source/FreeImage/tmoFattal02.cpp687
-rw-r--r--Source/FreeImage/tmoReinhard05.cpp260
-rw-r--r--Source/FreeImageIO.h48
-rw-r--r--Source/FreeImageLib/FreeImageLib.2003.vcproj458
-rw-r--r--Source/FreeImageLib/FreeImageLib.2005.vcproj595
-rw-r--r--Source/FreeImageLib/FreeImageLib.2008.vcproj572
-rw-r--r--Source/FreeImageToolkit/BSplineRotate.cpp728
-rw-r--r--Source/FreeImageToolkit/Background.cpp897
-rw-r--r--Source/FreeImageToolkit/Channels.cpp488
-rw-r--r--Source/FreeImageToolkit/ClassicRotate.cpp956
-rw-r--r--Source/FreeImageToolkit/Colors.cpp939
-rw-r--r--Source/FreeImageToolkit/CopyPaste.cpp747
-rw-r--r--Source/FreeImageToolkit/Display.cpp230
-rw-r--r--Source/FreeImageToolkit/Filters.h287
-rw-r--r--Source/FreeImageToolkit/Flip.cpp166
-rw-r--r--Source/FreeImageToolkit/JPEGTransform.cpp414
-rw-r--r--Source/FreeImageToolkit/MultigridPoissonSolver.cpp502
-rw-r--r--Source/FreeImageToolkit/Rescale.cpp227
-rw-r--r--Source/FreeImageToolkit/Resize.cpp646
-rw-r--r--Source/FreeImageToolkit/Resize.h145
-rw-r--r--Source/LibJPEG/LibJPEG.2003.vcproj306
-rw-r--r--Source/LibJPEG/LibJPEG.2005.vcproj413
-rw-r--r--Source/LibJPEG/LibJPEG.2008.vcproj406
-rw-r--r--Source/LibJPEG/README322
-rw-r--r--Source/LibJPEG/ansi2knr.c739
-rw-r--r--Source/LibJPEG/cderror.h132
-rw-r--r--Source/LibJPEG/cdjpeg.c181
-rw-r--r--Source/LibJPEG/cdjpeg.h187
-rw-r--r--Source/LibJPEG/change.log270
-rw-r--r--Source/LibJPEG/cjpeg.c616
-rw-r--r--Source/LibJPEG/ckconfig.c402
-rw-r--r--Source/LibJPEG/coderules.txt118
-rw-r--r--Source/LibJPEG/djpeg.c617
-rw-r--r--Source/LibJPEG/example.c433
-rw-r--r--Source/LibJPEG/filelist.txt215
-rw-r--r--Source/LibJPEG/install.txt1097
-rw-r--r--Source/LibJPEG/jaricom.c148
-rw-r--r--Source/LibJPEG/jcapimin.c282
-rw-r--r--Source/LibJPEG/jcapistd.c161
-rw-r--r--Source/LibJPEG/jcarith.c921
-rw-r--r--Source/LibJPEG/jccoefct.c453
-rw-r--r--Source/LibJPEG/jccolor.c459
-rw-r--r--Source/LibJPEG/jcdctmgr.c482
-rw-r--r--Source/LibJPEG/jchuff.c1612
-rw-r--r--Source/LibJPEG/jcinit.c65
-rw-r--r--Source/LibJPEG/jcmainct.c293
-rw-r--r--Source/LibJPEG/jcmarker.c667
-rw-r--r--Source/LibJPEG/jcmaster.c770
-rw-r--r--Source/LibJPEG/jcomapi.c106
-rw-r--r--Source/LibJPEG/jconfig.h145
-rw-r--r--Source/LibJPEG/jconfig.txt155
-rw-r--r--Source/LibJPEG/jcparam.c632
-rw-r--r--Source/LibJPEG/jcprepct.c358
-rw-r--r--Source/LibJPEG/jcsample.c545
-rw-r--r--Source/LibJPEG/jctrans.c381
-rw-r--r--Source/LibJPEG/jdapimin.c396
-rw-r--r--Source/LibJPEG/jdapistd.c275
-rw-r--r--Source/LibJPEG/jdarith.c762
-rw-r--r--Source/LibJPEG/jdatadst.c151
-rw-r--r--Source/LibJPEG/jdatasrc.c212
-rw-r--r--Source/LibJPEG/jdcoefct.c736
-rw-r--r--Source/LibJPEG/jdcolor.c396
-rw-r--r--Source/LibJPEG/jdct.h393
-rw-r--r--Source/LibJPEG/jddctmgr.c382
-rw-r--r--Source/LibJPEG/jdhuff.c1309
-rw-r--r--Source/LibJPEG/jdinput.c384
-rw-r--r--Source/LibJPEG/jdmainct.c512
-rw-r--r--Source/LibJPEG/jdmarker.c1360
-rw-r--r--Source/LibJPEG/jdmaster.c663
-rw-r--r--Source/LibJPEG/jdmerge.c400
-rw-r--r--Source/LibJPEG/jdpostct.c290
-rw-r--r--Source/LibJPEG/jdsample.c361
-rw-r--r--Source/LibJPEG/jdtrans.c136
-rw-r--r--Source/LibJPEG/jerror.c252
-rw-r--r--Source/LibJPEG/jerror.h304
-rw-r--r--Source/LibJPEG/jfdctflt.c174
-rw-r--r--Source/LibJPEG/jfdctfst.c230
-rw-r--r--Source/LibJPEG/jfdctint.c4348
-rw-r--r--Source/LibJPEG/jidctflt.c242
-rw-r--r--Source/LibJPEG/jidctfst.c368
-rw-r--r--Source/LibJPEG/jidctint.c5137
-rw-r--r--Source/LibJPEG/jinclude.h91
-rw-r--r--Source/LibJPEG/jmemansi.c167
-rw-r--r--Source/LibJPEG/jmemdos.c638
-rw-r--r--Source/LibJPEG/jmemdosa.asm379
-rw-r--r--Source/LibJPEG/jmemmac.c291
-rw-r--r--Source/LibJPEG/jmemmgr.c1118
-rw-r--r--Source/LibJPEG/jmemname.c276
-rw-r--r--Source/LibJPEG/jmemnobs.c109
-rw-r--r--Source/LibJPEG/jmemsys.h201
-rw-r--r--Source/LibJPEG/jmorecfg.h369
-rw-r--r--Source/LibJPEG/jpegint.h395
-rw-r--r--Source/LibJPEG/jpeglib.h1135
-rw-r--r--Source/LibJPEG/jpegtran.c546
-rw-r--r--Source/LibJPEG/jquant1.c856
-rw-r--r--Source/LibJPEG/jquant2.c1310
-rw-r--r--Source/LibJPEG/jutils.c179
-rw-r--r--Source/LibJPEG/jversion.h14
-rw-r--r--Source/LibJPEG/libjpeg.txt3067
-rw-r--r--Source/LibJPEG/libjpeg.xcodeproj/project.pbxproj888
-rw-r--r--Source/LibJPEG/rdbmp.c439
-rw-r--r--Source/LibJPEG/rdcolmap.c253
-rw-r--r--Source/LibJPEG/rdgif.c38
-rw-r--r--Source/LibJPEG/rdjpgcom.c515
-rw-r--r--Source/LibJPEG/rdppm.c459
-rw-r--r--Source/LibJPEG/rdrle.c387
-rw-r--r--Source/LibJPEG/rdswitch.c365
-rw-r--r--Source/LibJPEG/rdtarga.c500
-rw-r--r--Source/LibJPEG/structure.txt945
-rw-r--r--Source/LibJPEG/transupp.c1533
-rw-r--r--Source/LibJPEG/transupp.h205
-rw-r--r--Source/LibJPEG/usage.txt605
-rw-r--r--Source/LibJPEG/wizard.txt211
-rw-r--r--Source/LibJPEG/wrbmp.c442
-rw-r--r--Source/LibJPEG/wrgif.c399
-rw-r--r--Source/LibJPEG/wrjpgcom.c583
-rw-r--r--Source/LibJPEG/wrppm.c269
-rw-r--r--Source/LibJPEG/wrrle.c305
-rw-r--r--Source/LibJPEG/wrtarga.c253
-rw-r--r--Source/LibMNG/Changes1447
-rw-r--r--Source/LibMNG/LICENSE57
-rw-r--r--Source/LibMNG/LibMNG.2003.vcproj520
-rw-r--r--Source/LibMNG/LibMNG.2005.vcproj351
-rw-r--r--Source/LibMNG/LibMNG.2008.vcproj338
-rw-r--r--Source/LibMNG/README36
-rw-r--r--Source/LibMNG/README.autoconf213
-rw-r--r--Source/LibMNG/README.config104
-rw-r--r--Source/LibMNG/README.contrib95
-rw-r--r--Source/LibMNG/README.examples48
-rw-r--r--Source/LibMNG/README.footprint46
-rw-r--r--Source/LibMNG/README.packaging24
-rw-r--r--Source/LibMNG/libmng.h2932
-rw-r--r--Source/LibMNG/libmng.xcodeproj/project.pbxproj407
-rw-r--r--Source/LibMNG/libmng_callback_xs.c1239
-rw-r--r--Source/LibMNG/libmng_chunk_descr.c6090
-rw-r--r--Source/LibMNG/libmng_chunk_descr.h146
-rw-r--r--Source/LibMNG/libmng_chunk_io.c10740
-rw-r--r--Source/LibMNG/libmng_chunk_io.h415
-rw-r--r--Source/LibMNG/libmng_chunk_prc.c4452
-rw-r--r--Source/LibMNG/libmng_chunk_prc.h381
-rw-r--r--Source/LibMNG/libmng_chunk_xs.c7016
-rw-r--r--Source/LibMNG/libmng_chunks.h1026
-rw-r--r--Source/LibMNG/libmng_cms.c758
-rw-r--r--Source/LibMNG/libmng_cms.h92
-rw-r--r--Source/LibMNG/libmng_conf.h306
-rw-r--r--Source/LibMNG/libmng_data.h1029
-rw-r--r--Source/LibMNG/libmng_display.c7135
-rw-r--r--Source/LibMNG/libmng_display.h343
-rw-r--r--Source/LibMNG/libmng_dither.c58
-rw-r--r--Source/LibMNG/libmng_dither.h45
-rw-r--r--Source/LibMNG/libmng_error.c326
-rw-r--r--Source/LibMNG/libmng_error.h119
-rw-r--r--Source/LibMNG/libmng_filter.c978
-rw-r--r--Source/LibMNG/libmng_filter.h69
-rw-r--r--Source/LibMNG/libmng_hlapi.c2995
-rw-r--r--Source/LibMNG/libmng_jpeg.c1088
-rw-r--r--Source/LibMNG/libmng_jpeg.h57
-rw-r--r--Source/LibMNG/libmng_memory.h64
-rw-r--r--Source/LibMNG/libmng_object_prc.c6998
-rw-r--r--Source/LibMNG/libmng_object_prc.h690
-rw-r--r--Source/LibMNG/libmng_objects.h635
-rw-r--r--Source/LibMNG/libmng_pixels.c24610
-rw-r--r--Source/LibMNG/libmng_pixels.h1147
-rw-r--r--Source/LibMNG/libmng_prop_xs.c2799
-rw-r--r--Source/LibMNG/libmng_read.c1369
-rw-r--r--Source/LibMNG/libmng_read.h53
-rw-r--r--Source/LibMNG/libmng_trace.c1683
-rw-r--r--Source/LibMNG/libmng_trace.h1474
-rw-r--r--Source/LibMNG/libmng_types.h574
-rw-r--r--Source/LibMNG/libmng_write.c198
-rw-r--r--Source/LibMNG/libmng_write.h49
-rw-r--r--Source/LibMNG/libmng_zlib.c607
-rw-r--r--Source/LibMNG/libmng_zlib.h60
-rw-r--r--Source/LibOpenJPEG/ChangeLog553
-rw-r--r--Source/LibOpenJPEG/LibOpenJPEG.2003.vcproj527
-rw-r--r--Source/LibOpenJPEG/LibOpenJPEG.2005.vcproj688
-rw-r--r--Source/LibOpenJPEG/LibOpenJPEG.2008.vcproj616
-rw-r--r--Source/LibOpenJPEG/bio.c187
-rw-r--r--Source/LibOpenJPEG/bio.h125
-rw-r--r--Source/LibOpenJPEG/cio.c191
-rw-r--r--Source/LibOpenJPEG/cio.h86
-rw-r--r--Source/LibOpenJPEG/dwt.c825
-rw-r--r--Source/LibOpenJPEG/dwt.h113
-rw-r--r--Source/LibOpenJPEG/event.c121
-rw-r--r--Source/LibOpenJPEG/event.h58
-rw-r--r--Source/LibOpenJPEG/fix.h64
-rw-r--r--Source/LibOpenJPEG/image.c89
-rw-r--r--Source/LibOpenJPEG/image.h48
-rw-r--r--Source/LibOpenJPEG/int.h119
-rw-r--r--Source/LibOpenJPEG/j2k.c2509
-rw-r--r--Source/LibOpenJPEG/j2k.h446
-rw-r--r--Source/LibOpenJPEG/j2k_lib.c59
-rw-r--r--Source/LibOpenJPEG/j2k_lib.h54
-rw-r--r--Source/LibOpenJPEG/jp2.c711
-rw-r--r--Source/LibOpenJPEG/jp2.h177
-rw-r--r--Source/LibOpenJPEG/jpt.c155
-rw-r--r--Source/LibOpenJPEG/jpt.h75
-rw-r--r--Source/LibOpenJPEG/libopenjpeg.xcodeproj/project.pbxproj341
-rw-r--r--Source/LibOpenJPEG/license.txt30
-rw-r--r--Source/LibOpenJPEG/mct.c148
-rw-r--r--Source/LibOpenJPEG/mct.h98
-rw-r--r--Source/LibOpenJPEG/mqc.c538
-rw-r--r--Source/LibOpenJPEG/mqc.h197
-rw-r--r--Source/LibOpenJPEG/openjpeg.c334
-rw-r--r--Source/LibOpenJPEG/openjpeg.h911
-rw-r--r--Source/LibOpenJPEG/opj_includes.h134
-rw-r--r--Source/LibOpenJPEG/opj_malloc.h140
-rw-r--r--Source/LibOpenJPEG/pi.c963
-rw-r--r--Source/LibOpenJPEG/pi.h154
-rw-r--r--Source/LibOpenJPEG/raw.c87
-rw-r--r--Source/LibOpenJPEG/raw.h100
-rw-r--r--Source/LibOpenJPEG/t1.c1208
-rw-r--r--Source/LibOpenJPEG/t1.h147
-rw-r--r--Source/LibOpenJPEG/t1_generate_luts.c275
-rw-r--r--Source/LibOpenJPEG/t1_luts.h143
-rw-r--r--Source/LibOpenJPEG/t2.c787
-rw-r--r--Source/LibOpenJPEG/t2.h103
-rw-r--r--Source/LibOpenJPEG/tcd.c1516
-rw-r--r--Source/LibOpenJPEG/tcd.h285
-rw-r--r--Source/LibOpenJPEG/tgt.c213
-rw-r--r--Source/LibOpenJPEG/tgt.h114
-rw-r--r--Source/LibPNG/ANNOUNCE55
-rw-r--r--Source/LibPNG/CHANGES2785
-rw-r--r--Source/LibPNG/CMakeLists.txt284
-rw-r--r--Source/LibPNG/INSTALL143
-rw-r--r--Source/LibPNG/KNOWNBUG22
-rw-r--r--Source/LibPNG/LICENSE111
-rw-r--r--Source/LibPNG/LibPNG.2003.vcproj194
-rw-r--r--Source/LibPNG/LibPNG.2005.vcproj263
-rw-r--r--Source/LibPNG/LibPNG.2008.vcproj250
-rw-r--r--Source/LibPNG/README275
-rw-r--r--Source/LibPNG/TODO25
-rw-r--r--Source/LibPNG/Y2KINFO55
-rwxr-xr-xSource/LibPNG/config.h88
-rwxr-xr-xSource/LibPNG/configure13
-rw-r--r--Source/LibPNG/example.c832
-rw-r--r--Source/LibPNG/libpng-1.2.49.txt3234
-rw-r--r--Source/LibPNG/libpng.34510
-rw-r--r--Source/LibPNG/libpng.txt3112
-rw-r--r--Source/LibPNG/libpng.xcodeproj/project.pbxproj359
-rw-r--r--Source/LibPNG/libpngpf.3806
-rw-r--r--Source/LibPNG/png.574
-rw-r--r--Source/LibPNG/png.c1100
-rw-r--r--Source/LibPNG/png.h3808
-rw-r--r--Source/LibPNG/pngbar.jpgbin0 -> 2498 bytes
-rw-r--r--Source/LibPNG/pngbar.pngbin0 -> 2399 bytes
-rw-r--r--Source/LibPNG/pngconf.h1681
-rw-r--r--Source/LibPNG/pngerror.c396
-rw-r--r--Source/LibPNG/pnggccrd.c26
-rw-r--r--Source/LibPNG/pngget.c944
-rw-r--r--Source/LibPNG/pngmem.c641
-rw-r--r--Source/LibPNG/pngnow.pngbin0 -> 2069 bytes
-rw-r--r--Source/LibPNG/pngpread.c1241
-rw-r--r--Source/LibPNG/pngread.c1515
-rw-r--r--Source/LibPNG/pngrio.c180
-rw-r--r--Source/LibPNG/pngrtran.c4470
-rw-r--r--Source/LibPNG/pngrutil.c3386
-rw-r--r--Source/LibPNG/pngset.c1236
-rw-r--r--Source/LibPNG/pngtest.c1705
-rw-r--r--Source/LibPNG/pngtest.pngbin0 -> 8574 bytes
-rw-r--r--Source/LibPNG/pngtrans.c699
-rw-r--r--Source/LibPNG/pngvcrd.c12
-rw-r--r--Source/LibPNG/pngwio.c260
-rw-r--r--Source/LibPNG/pngwrite.c1593
-rw-r--r--Source/LibPNG/pngwtran.c582
-rw-r--r--Source/LibPNG/pngwutil.c2832
-rw-r--r--Source/LibRawLite/COPYRIGHT483
-rw-r--r--Source/LibRawLite/Changelog.txt2
-rw-r--r--Source/LibRawLite/LibRawLite.2003.vcproj187
-rw-r--r--Source/LibRawLite/LibRawLite.2005.vcproj251
-rw-r--r--Source/LibRawLite/dcraw/dcraw.c8680
-rw-r--r--Source/LibRawLite/internal/dcraw_common.cpp7449
-rw-r--r--Source/LibRawLite/internal/dcraw_fileio.cpp215
-rw-r--r--Source/LibRawLite/internal/defines.h131
-rw-r--r--Source/LibRawLite/internal/libraw_internal_funcs.h198
-rw-r--r--Source/LibRawLite/internal/var_defines.h179
-rw-r--r--Source/LibRawLite/libraw/libraw.h207
-rw-r--r--Source/LibRawLite/libraw/libraw_alloc.h96
-rw-r--r--Source/LibRawLite/libraw/libraw_const.h142
-rw-r--r--Source/LibRawLite/libraw/libraw_datastream.h300
-rw-r--r--Source/LibRawLite/libraw/libraw_internal.h234
-rw-r--r--Source/LibRawLite/libraw/libraw_types.h246
-rw-r--r--Source/LibRawLite/libraw/libraw_version.h46
-rw-r--r--Source/LibRawLite/src/libraw_c_api.cpp145
-rw-r--r--Source/LibRawLite/src/libraw_cxx.cpp1607
-rw-r--r--Source/LibTIFF/ChangeLog4371
-rw-r--r--Source/LibTIFF/LibTIFF.2003.vcproj269
-rw-r--r--Source/LibTIFF/LibTIFF.2005.vcproj363
-rw-r--r--Source/LibTIFF/LibTIFF.2008.vcproj348
-rw-r--r--Source/LibTIFF/Makefile.am143
-rw-r--r--Source/LibTIFF/Makefile.in888
-rw-r--r--Source/LibTIFF/SConstruct73
-rw-r--r--Source/LibTIFF/libtiff.xcodeproj/project.pbxproj377
-rw-r--r--Source/LibTIFF/makefile.vc102
-rw-r--r--Source/LibTIFF/mkg3states.c444
-rw-r--r--Source/LibTIFF/mkspans.c75
-rw-r--r--Source/LibTIFF/t4.h285
-rw-r--r--Source/LibTIFF/tif_acorn.c519
-rw-r--r--Source/LibTIFF/tif_apple.c274
-rw-r--r--Source/LibTIFF/tif_atari.c243
-rw-r--r--Source/LibTIFF/tif_aux.c275
-rw-r--r--Source/LibTIFF/tif_close.c119
-rw-r--r--Source/LibTIFF/tif_codec.c153
-rw-r--r--Source/LibTIFF/tif_color.c275
-rw-r--r--Source/LibTIFF/tif_compress.c288
-rw-r--r--Source/LibTIFF/tif_config.h264
-rw-r--r--Source/LibTIFF/tif_config.h-vms46
-rw-r--r--Source/LibTIFF/tif_config.h.in309
-rw-r--r--Source/LibTIFF/tif_config.vc.h56
-rw-r--r--Source/LibTIFF/tif_config.wince.h67
-rw-r--r--Source/LibTIFF/tif_dir.c1369
-rw-r--r--Source/LibTIFF/tif_dir.h202
-rw-r--r--Source/LibTIFF/tif_dirinfo.c880
-rw-r--r--Source/LibTIFF/tif_dirread.c2009
-rw-r--r--Source/LibTIFF/tif_dirwrite.c1406
-rw-r--r--Source/LibTIFF/tif_dumpmode.c119
-rw-r--r--Source/LibTIFF/tif_error.c73
-rw-r--r--Source/LibTIFF/tif_extension.c111
-rw-r--r--Source/LibTIFF/tif_fax3.c1603
-rw-r--r--Source/LibTIFF/tif_fax3.h525
-rw-r--r--Source/LibTIFF/tif_fax3sm.c1253
-rw-r--r--Source/LibTIFF/tif_flush.c67
-rw-r--r--Source/LibTIFF/tif_getimage.c2669
-rw-r--r--Source/LibTIFF/tif_jbig.c378
-rw-r--r--Source/LibTIFF/tif_jpeg.c2035
-rw-r--r--Source/LibTIFF/tif_luv.c1622
-rw-r--r--Source/LibTIFF/tif_lzw.c1122
-rw-r--r--Source/LibTIFF/tif_msdos.c186
-rw-r--r--Source/LibTIFF/tif_next.c147
-rw-r--r--Source/LibTIFF/tif_ojpeg.c2424
-rw-r--r--Source/LibTIFF/tif_open.c688
-rw-r--r--Source/LibTIFF/tif_packbits.c293
-rw-r--r--Source/LibTIFF/tif_pixarlog.c1364
-rw-r--r--Source/LibTIFF/tif_predict.c729
-rw-r--r--Source/LibTIFF/tif_predict.h70
-rw-r--r--Source/LibTIFF/tif_print.c639
-rw-r--r--Source/LibTIFF/tif_read.c741
-rw-r--r--Source/LibTIFF/tif_stream.cxx295
-rw-r--r--Source/LibTIFF/tif_strip.c363
-rw-r--r--Source/LibTIFF/tif_swab.c235
-rw-r--r--Source/LibTIFF/tif_thunder.c158
-rw-r--r--Source/LibTIFF/tif_tile.c273
-rw-r--r--Source/LibTIFF/tif_unix.c293
-rw-r--r--Source/LibTIFF/tif_version.c33
-rw-r--r--Source/LibTIFF/tif_vms.c588
-rw-r--r--Source/LibTIFF/tif_warning.c74
-rw-r--r--Source/LibTIFF/tif_win3.c225
-rw-r--r--Source/LibTIFF/tif_win32.c401
-rw-r--r--Source/LibTIFF/tif_wince.c281
-rw-r--r--Source/LibTIFF/tif_write.c711
-rw-r--r--Source/LibTIFF/tif_zip.c412
-rw-r--r--Source/LibTIFF/tiff.h647
-rw-r--r--Source/LibTIFF/tiffconf.h-vms99
-rw-r--r--Source/LibTIFF/tiffconf.h.in103
-rw-r--r--Source/LibTIFF/tiffconf.vc.h109
-rw-r--r--Source/LibTIFF/tiffconf.wince.h129
-rw-r--r--Source/LibTIFF/tiffio.h519
-rw-r--r--Source/LibTIFF/tiffio.hxx42
-rw-r--r--Source/LibTIFF/tiffiop.h338
-rw-r--r--Source/LibTIFF/tiffvers.h9
-rw-r--r--Source/LibTIFF/tiffvers.h.in9
-rw-r--r--Source/LibTIFF/uvcode.h173
-rw-r--r--Source/Metadata/Exif.cpp698
-rw-r--r--Source/Metadata/FIRational.cpp176
-rw-r--r--Source/Metadata/FIRational.h107
-rw-r--r--Source/Metadata/FreeImageTag.cpp284
-rw-r--r--Source/Metadata/FreeImageTag.h435
-rw-r--r--Source/Metadata/IPTC.cpp321
-rw-r--r--Source/Metadata/TagConversion.cpp968
-rw-r--r--Source/Metadata/TagLib.cpp1096
-rw-r--r--Source/Metadata/XTIFF.cpp404
-rw-r--r--Source/OpenEXR/Copyrights/AUTHORS41
-rw-r--r--Source/OpenEXR/Copyrights/COPYING34
-rw-r--r--Source/OpenEXR/Copyrights/ChangeLog581
-rw-r--r--Source/OpenEXR/Copyrights/LICENSE34
-rw-r--r--Source/OpenEXR/Half/Makefile.am32
-rw-r--r--Source/OpenEXR/Half/Makefile.in541
-rw-r--r--Source/OpenEXR/Half/eLut.cpp114
-rw-r--r--Source/OpenEXR/Half/eLut.h71
-rw-r--r--Source/OpenEXR/Half/half.cpp317
-rw-r--r--Source/OpenEXR/Half/half.h776
-rw-r--r--Source/OpenEXR/Half/halfFunction.h159
-rw-r--r--Source/OpenEXR/Half/halfLimits.h102
-rw-r--r--Source/OpenEXR/Half/toFloat.cpp164
-rw-r--r--Source/OpenEXR/Half/toFloat.h16391
-rw-r--r--Source/OpenEXR/Iex/Iex.h60
-rw-r--r--Source/OpenEXR/Iex/IexBaseExc.cpp129
-rw-r--r--Source/OpenEXR/Iex/IexBaseExc.h266
-rw-r--r--Source/OpenEXR/Iex/IexErrnoExc.h210
-rw-r--r--Source/OpenEXR/Iex/IexMacros.h148
-rw-r--r--Source/OpenEXR/Iex/IexMathExc.h58
-rw-r--r--Source/OpenEXR/Iex/IexThrowErrnoExc.cpp859
-rw-r--r--Source/OpenEXR/Iex/IexThrowErrnoExc.h96
-rw-r--r--Source/OpenEXR/Iex/Makefile.am16
-rw-r--r--Source/OpenEXR/Iex/Makefile.in504
-rw-r--r--Source/OpenEXR/IlmBaseConfig.h46
-rw-r--r--Source/OpenEXR/IlmImf/ImfArray.h261
-rw-r--r--Source/OpenEXR/IlmImf/ImfAttribute.cpp156
-rw-r--r--Source/OpenEXR/IlmImf/ImfAttribute.h422
-rw-r--r--Source/OpenEXR/IlmImf/ImfAutoArray.h93
-rw-r--r--Source/OpenEXR/IlmImf/ImfB44Compressor.cpp1064
-rw-r--r--Source/OpenEXR/IlmImf/ImfB44Compressor.h117
-rw-r--r--Source/OpenEXR/IlmImf/ImfBoxAttribute.cpp110
-rw-r--r--Source/OpenEXR/IlmImf/ImfBoxAttribute.h73
-rw-r--r--Source/OpenEXR/IlmImf/ImfCRgbaFile.cpp1434
-rw-r--r--Source/OpenEXR/IlmImf/ImfCRgbaFile.h467
-rw-r--r--Source/OpenEXR/IlmImf/ImfChannelList.cpp254
-rw-r--r--Source/OpenEXR/IlmImf/ImfChannelList.h411
-rw-r--r--Source/OpenEXR/IlmImf/ImfChannelListAttribute.cpp127
-rw-r--r--Source/OpenEXR/IlmImf/ImfChannelListAttribute.h67
-rw-r--r--Source/OpenEXR/IlmImf/ImfChromaticities.cpp135
-rw-r--r--Source/OpenEXR/IlmImf/ImfChromaticities.h120
-rw-r--r--Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.cpp86
-rw-r--r--Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.h72
-rw-r--r--Source/OpenEXR/IlmImf/ImfCompression.h75
-rw-r--r--Source/OpenEXR/IlmImf/ImfCompressionAttribute.cpp76
-rw-r--r--Source/OpenEXR/IlmImf/ImfCompressionAttribute.h66
-rw-r--r--Source/OpenEXR/IlmImf/ImfCompressor.cpp191
-rw-r--r--Source/OpenEXR/IlmImf/ImfCompressor.h251
-rw-r--r--Source/OpenEXR/IlmImf/ImfConvert.cpp139
-rw-r--r--Source/OpenEXR/IlmImf/ImfConvert.h104
-rw-r--r--Source/OpenEXR/IlmImf/ImfDoubleAttribute.cpp57
-rw-r--r--Source/OpenEXR/IlmImf/ImfDoubleAttribute.h63
-rw-r--r--Source/OpenEXR/IlmImf/ImfEnvmap.cpp328
-rw-r--r--Source/OpenEXR/IlmImf/ImfEnvmap.h322
-rw-r--r--Source/OpenEXR/IlmImf/ImfEnvmapAttribute.cpp75
-rw-r--r--Source/OpenEXR/IlmImf/ImfEnvmapAttribute.h65
-rw-r--r--Source/OpenEXR/IlmImf/ImfFloatAttribute.cpp57
-rw-r--r--Source/OpenEXR/IlmImf/ImfFloatAttribute.h63
-rw-r--r--Source/OpenEXR/IlmImf/ImfFrameBuffer.cpp176
-rw-r--r--Source/OpenEXR/IlmImf/ImfFrameBuffer.h368
-rw-r--r--Source/OpenEXR/IlmImf/ImfFramesPerSecond.cpp75
-rw-r--r--Source/OpenEXR/IlmImf/ImfFramesPerSecond.h88
-rw-r--r--Source/OpenEXR/IlmImf/ImfHeader.cpp1003
-rw-r--r--Source/OpenEXR/IlmImf/ImfHeader.h577
-rw-r--r--Source/OpenEXR/IlmImf/ImfHuf.cpp1072
-rw-r--r--Source/OpenEXR/IlmImf/ImfHuf.h79
-rw-r--r--Source/OpenEXR/IlmImf/ImfIO.cpp109
-rw-r--r--Source/OpenEXR/IlmImf/ImfIO.h252
-rw-r--r--Source/OpenEXR/IlmImf/ImfInputFile.cpp648
-rw-r--r--Source/OpenEXR/IlmImf/ImfInputFile.h209
-rw-r--r--Source/OpenEXR/IlmImf/ImfInt64.h52
-rw-r--r--Source/OpenEXR/IlmImf/ImfIntAttribute.cpp57
-rw-r--r--Source/OpenEXR/IlmImf/ImfIntAttribute.h63
-rw-r--r--Source/OpenEXR/IlmImf/ImfKeyCode.cpp216
-rw-r--r--Source/OpenEXR/IlmImf/ImfKeyCode.h161
-rw-r--r--Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.cpp98
-rw-r--r--Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.h72
-rw-r--r--Source/OpenEXR/IlmImf/ImfLineOrder.h64
-rw-r--r--Source/OpenEXR/IlmImf/ImfLineOrderAttribute.cpp77
-rw-r--r--Source/OpenEXR/IlmImf/ImfLineOrderAttribute.h66
-rw-r--r--Source/OpenEXR/IlmImf/ImfLut.cpp176
-rw-r--r--Source/OpenEXR/IlmImf/ImfLut.h185
-rw-r--r--Source/OpenEXR/IlmImf/ImfMatrixAttribute.cpp154
-rw-r--r--Source/OpenEXR/IlmImf/ImfMatrixAttribute.h73
-rw-r--r--Source/OpenEXR/IlmImf/ImfMisc.cpp787
-rw-r--r--Source/OpenEXR/IlmImf/ImfMisc.h255
-rw-r--r--Source/OpenEXR/IlmImf/ImfName.h146
-rw-r--r--Source/OpenEXR/IlmImf/ImfOpaqueAttribute.cpp125
-rw-r--r--Source/OpenEXR/IlmImf/ImfOpaqueAttribute.h114
-rw-r--r--Source/OpenEXR/IlmImf/ImfOutputFile.cpp1287
-rw-r--r--Source/OpenEXR/IlmImf/ImfOutputFile.h241
-rw-r--r--Source/OpenEXR/IlmImf/ImfPixelType.h61
-rw-r--r--Source/OpenEXR/IlmImf/ImfPizCompressor.cpp656
-rw-r--r--Source/OpenEXR/IlmImf/ImfPizCompressor.h112
-rw-r--r--Source/OpenEXR/IlmImf/ImfPreviewImage.cpp101
-rw-r--r--Source/OpenEXR/IlmImf/ImfPreviewImage.h131
-rw-r--r--Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.cpp102
-rw-r--r--Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.h71
-rw-r--r--Source/OpenEXR/IlmImf/ImfPxr24Compressor.cpp542
-rw-r--r--Source/OpenEXR/IlmImf/ImfPxr24Compressor.h105
-rw-r--r--Source/OpenEXR/IlmImf/ImfRational.cpp125
-rw-r--r--Source/OpenEXR/IlmImf/ImfRational.h93
-rw-r--r--Source/OpenEXR/IlmImf/ImfRationalAttribute.cpp73
-rw-r--r--Source/OpenEXR/IlmImf/ImfRationalAttribute.h70
-rw-r--r--Source/OpenEXR/IlmImf/ImfRgba.h104
-rw-r--r--Source/OpenEXR/IlmImf/ImfRgbaFile.cpp1297
-rw-r--r--Source/OpenEXR/IlmImf/ImfRgbaFile.h315
-rw-r--r--Source/OpenEXR/IlmImf/ImfRgbaYca.cpp482
-rw-r--r--Source/OpenEXR/IlmImf/ImfRgbaYca.h248
-rw-r--r--Source/OpenEXR/IlmImf/ImfRleCompressor.cpp330
-rw-r--r--Source/OpenEXR/IlmImf/ImfRleCompressor.h79
-rw-r--r--Source/OpenEXR/IlmImf/ImfScanLineInputFile.cpp1008
-rw-r--r--Source/OpenEXR/IlmImf/ImfScanLineInputFile.h172
-rw-r--r--Source/OpenEXR/IlmImf/ImfStandardAttributes.cpp116
-rw-r--r--Source/OpenEXR/IlmImf/ImfStandardAttributes.h291
-rw-r--r--Source/OpenEXR/IlmImf/ImfStdIO.cpp234
-rw-r--r--Source/OpenEXR/IlmImf/ImfStdIO.h156
-rw-r--r--Source/OpenEXR/IlmImf/ImfStringAttribute.cpp79
-rw-r--r--Source/OpenEXR/IlmImf/ImfStringAttribute.h66
-rw-r--r--Source/OpenEXR/IlmImf/ImfTestFile.cpp135
-rw-r--r--Source/OpenEXR/IlmImf/ImfTestFile.h63
-rw-r--r--Source/OpenEXR/IlmImf/ImfThreading.cpp60
-rw-r--r--Source/OpenEXR/IlmImf/ImfThreading.h92
-rw-r--r--Source/OpenEXR/IlmImf/ImfTileDescription.h102
-rw-r--r--Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.cpp85
-rw-r--r--Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.h73
-rw-r--r--Source/OpenEXR/IlmImf/ImfTileOffsets.cpp385
-rw-r--r--Source/OpenEXR/IlmImf/ImfTileOffsets.h107
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledInputFile.cpp1302
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledInputFile.h381
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledMisc.cpp301
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledMisc.h75
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledOutputFile.cpp1692
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledOutputFile.h475
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledRgbaFile.cpp1088
-rw-r--r--Source/OpenEXR/IlmImf/ImfTiledRgbaFile.h453
-rw-r--r--Source/OpenEXR/IlmImf/ImfTimeCode.cpp415
-rw-r--r--Source/OpenEXR/IlmImf/ImfTimeCode.h226
-rw-r--r--Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.cpp78
-rw-r--r--Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.h72
-rw-r--r--Source/OpenEXR/IlmImf/ImfVecAttribute.cpp160
-rw-r--r--Source/OpenEXR/IlmImf/ImfVecAttribute.h87
-rw-r--r--Source/OpenEXR/IlmImf/ImfVersion.cpp59
-rw-r--r--Source/OpenEXR/IlmImf/ImfVersion.h117
-rw-r--r--Source/OpenEXR/IlmImf/ImfWav.cpp390
-rw-r--r--Source/OpenEXR/IlmImf/ImfWav.h70
-rw-r--r--Source/OpenEXR/IlmImf/ImfXdr.h916
-rw-r--r--Source/OpenEXR/IlmImf/ImfZipCompressor.cpp230
-rw-r--r--Source/OpenEXR/IlmImf/ImfZipCompressor.h80
-rw-r--r--Source/OpenEXR/IlmImf/Makefile.am121
-rw-r--r--Source/OpenEXR/IlmImf/Makefile.in708
-rw-r--r--Source/OpenEXR/IlmImf/b44ExpLogTable.cpp136
-rw-r--r--Source/OpenEXR/IlmImf/b44ExpLogTable.h16396
-rw-r--r--Source/OpenEXR/IlmThread/IlmThread.cpp80
-rw-r--r--Source/OpenEXR/IlmThread/IlmThread.h151
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadMutex.cpp59
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadMutex.h158
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadMutexPosix.cpp85
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadMutexWin32.cpp73
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadPool.cpp456
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadPool.h156
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadPosix.cpp98
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadSemaphore.cpp60
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadSemaphore.h110
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadSemaphorePosix.cpp103
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadSemaphorePosixCompat.cpp155
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadSemaphoreWin32.cpp146
-rw-r--r--Source/OpenEXR/IlmThread/IlmThreadWin32.cpp95
-rw-r--r--Source/OpenEXR/IlmThread/Makefile.am26
-rw-r--r--Source/OpenEXR/IlmThread/Makefile.in522
-rw-r--r--Source/OpenEXR/Imath/ImathBox.cpp37
-rw-r--r--Source/OpenEXR/Imath/ImathBox.h277
-rw-r--r--Source/OpenEXR/Imath/ImathBoxAlgo.h794
-rw-r--r--Source/OpenEXR/Imath/ImathColor.h734
-rw-r--r--Source/OpenEXR/Imath/ImathColorAlgo.cpp178
-rw-r--r--Source/OpenEXR/Imath/ImathColorAlgo.h256
-rw-r--r--Source/OpenEXR/Imath/ImathEuler.h903
-rw-r--r--Source/OpenEXR/Imath/ImathExc.h70
-rw-r--r--Source/OpenEXR/Imath/ImathFrame.h190
-rw-r--r--Source/OpenEXR/Imath/ImathFrustum.h722
-rw-r--r--Source/OpenEXR/Imath/ImathFun.cpp181
-rw-r--r--Source/OpenEXR/Imath/ImathFun.h267
-rw-r--r--Source/OpenEXR/Imath/ImathGL.h159
-rw-r--r--Source/OpenEXR/Imath/ImathGLU.h54
-rw-r--r--Source/OpenEXR/Imath/ImathHalfLimits.h66
-rw-r--r--Source/OpenEXR/Imath/ImathInt64.h61
-rw-r--r--Source/OpenEXR/Imath/ImathInterval.h224
-rw-r--r--Source/OpenEXR/Imath/ImathLimits.h265
-rw-r--r--Source/OpenEXR/Imath/ImathLine.h184
-rw-r--r--Source/OpenEXR/Imath/ImathLineAlgo.h287
-rw-r--r--Source/OpenEXR/Imath/ImathMath.h208
-rw-r--r--Source/OpenEXR/Imath/ImathMatrix.h3254
-rw-r--r--Source/OpenEXR/Imath/ImathMatrixAlgo.cpp73
-rw-r--r--Source/OpenEXR/Imath/ImathMatrixAlgo.h1114
-rw-r--r--Source/OpenEXR/Imath/ImathPlane.h256
-rw-r--r--Source/OpenEXR/Imath/ImathPlatform.h92
-rw-r--r--Source/OpenEXR/Imath/ImathQuat.h736
-rw-r--r--Source/OpenEXR/Imath/ImathRandom.cpp195
-rw-r--r--Source/OpenEXR/Imath/ImathRandom.h398
-rw-r--r--Source/OpenEXR/Imath/ImathRoots.h218
-rw-r--r--Source/OpenEXR/Imath/ImathShear.cpp54
-rw-r--r--Source/OpenEXR/Imath/ImathShear.h659
-rw-r--r--Source/OpenEXR/Imath/ImathSphere.h177
-rw-r--r--Source/OpenEXR/Imath/ImathVec.cpp380
-rw-r--r--Source/OpenEXR/Imath/ImathVec.h1426
-rw-r--r--Source/OpenEXR/Imath/ImathVecAlgo.h146
-rw-r--r--Source/OpenEXR/Imath/Makefile.am34
-rw-r--r--Source/OpenEXR/Imath/Makefile.in529
-rw-r--r--Source/OpenEXR/OpenEXR.2003.vcproj737
-rw-r--r--Source/OpenEXR/OpenEXR.2005.vcproj978
-rw-r--r--Source/OpenEXR/OpenEXRConfig.h46
-rw-r--r--Source/Plugin.h138
-rw-r--r--Source/Quantizers.h225
-rw-r--r--Source/ToneMapping.h44
-rw-r--r--Source/Utilities.h353
-rw-r--r--Source/ZLib/ChangeLog855
-rw-r--r--Source/ZLib/FAQ339
-rw-r--r--Source/ZLib/INDEX51
-rw-r--r--Source/ZLib/Makefile154
-rw-r--r--Source/ZLib/Makefile.in154
-rw-r--r--Source/ZLib/README125
-rw-r--r--Source/ZLib/ZLib.2003.vcproj408
-rw-r--r--Source/ZLib/ZLib.2005.vcproj277
-rw-r--r--Source/ZLib/adler32.c149
-rw-r--r--Source/ZLib/algorithm.txt209
-rw-r--r--Source/ZLib/compress.c79
-rwxr-xr-xSource/ZLib/configure459
-rw-r--r--Source/ZLib/crc32.c423
-rw-r--r--Source/ZLib/crc32.h441
-rw-r--r--Source/ZLib/deflate.c1736
-rw-r--r--Source/ZLib/deflate.h331
-rw-r--r--Source/ZLib/example.c565
-rw-r--r--Source/ZLib/gzio.c1026
-rw-r--r--Source/ZLib/infback.c623
-rw-r--r--Source/ZLib/inffast.c318
-rw-r--r--Source/ZLib/inffast.h11
-rw-r--r--Source/ZLib/inffixed.h94
-rw-r--r--Source/ZLib/inflate.c1368
-rw-r--r--Source/ZLib/inflate.h115
-rw-r--r--Source/ZLib/inftrees.c329
-rw-r--r--Source/ZLib/inftrees.h55
-rw-r--r--Source/ZLib/minigzip.c322
-rw-r--r--Source/ZLib/trees.c1219
-rw-r--r--Source/ZLib/trees.h128
-rw-r--r--Source/ZLib/uncompr.c61
-rw-r--r--Source/ZLib/zconf.h332
-rw-r--r--Source/ZLib/zconf.in.h332
-rw-r--r--Source/ZLib/zlib.3159
-rw-r--r--Source/ZLib/zlib.h1357
-rw-r--r--Source/ZLib/zutil.c318
-rw-r--r--Source/ZLib/zutil.h269
-rw-r--r--TestAPI/GoogleTestSuite.cpp194
-rw-r--r--TestAPI/MainTestSuite.cpp100
-rw-r--r--TestAPI/Makefile8
-rw-r--r--TestAPI/Test.2003.sln21
-rw-r--r--TestAPI/Test.2003.vcproj168
-rw-r--r--TestAPI/Test.2005.sln19
-rw-r--r--TestAPI/Test.2005.vcproj245
-rw-r--r--TestAPI/Test.2008.sln70
-rw-r--r--TestAPI/Test.2008.vcproj236
-rw-r--r--TestAPI/TestSuite.h81
-rw-r--r--TestAPI/exif.jpgbin0 -> 44606 bytes
-rw-r--r--TestAPI/sample.pngbin0 -> 42913 bytes
-rw-r--r--TestAPI/testChannels.cpp131
-rw-r--r--TestAPI/testImageType.cpp506
-rw-r--r--TestAPI/testJPEG.cpp90
-rw-r--r--TestAPI/testMPage.cpp98
-rw-r--r--TestAPI/testMakeThumbnail.cpp42
-rw-r--r--TestAPI/testMemIO.cpp146
-rw-r--r--TestAPI/testPlugins.cpp38
-rw-r--r--TestAPI/testTools.cpp82
-rw-r--r--Whatsnew.txt977
-rw-r--r--Wrapper/Delphi/WhatsNew_Delphi.txt71
-rwxr-xr-xWrapper/Delphi/_clean.bat13
-rw-r--r--Wrapper/Delphi/demo/ImagePreview/ImagePreview.dpr13
-rw-r--r--Wrapper/Delphi/demo/ImagePreview/MainFrm.dfm135
-rw-r--r--Wrapper/Delphi/demo/ImagePreview/MainFrm.pas518
-rw-r--r--Wrapper/Delphi/demo/ImagePreview/Readme.txt8
-rw-r--r--Wrapper/Delphi/demo/ImagePreview/Tiger.jpgbin0 -> 64372 bytes
-rw-r--r--Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.dpr13
-rw-r--r--Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.stat10
-rw-r--r--Wrapper/Delphi/demo/MultiBitmap/mbMainForm.dfm89
-rw-r--r--Wrapper/Delphi/demo/MultiBitmap/mbMainForm.pas150
-rw-r--r--Wrapper/Delphi/demo/TargaUnit/Readme.txt22
-rw-r--r--Wrapper/Delphi/demo/TargaUnit/TargaImage.pas212
-rw-r--r--Wrapper/Delphi/demo/WinBitmap/MainDemo.dpr13
-rw-r--r--Wrapper/Delphi/demo/WinBitmap/MainForm.dfm607
-rw-r--r--Wrapper/Delphi/demo/WinBitmap/MainForm.pas227
-rw-r--r--Wrapper/Delphi/license.txt3
-rw-r--r--Wrapper/Delphi/src/FreeBitmap.pas2123
-rw-r--r--Wrapper/Delphi/src/FreeImage.pas738
-rw-r--r--Wrapper/Delphi/src/FreeUtils.pas127
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/AssemblyInfo.cpp58
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.cpp69
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.h83
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.vcproj176
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.sln21
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/ReadMe.txt27
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.cpp5
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.h6
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/app.icobin0 -> 1078 bytes
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/app.rc52
-rw-r--r--Wrapper/FreeImage.NET/cpp/FreeImageIO/resource.h3
-rw-r--r--Wrapper/FreeImage.NET/cs/Bin/delete.me1
-rw-r--r--Wrapper/FreeImage.NET/cs/Content.txt43
-rw-r--r--Wrapper/FreeImage.NET/cs/Doc/3.11.0/FreeImage.NET.shfbproj41
-rw-r--r--Wrapper/FreeImage.NET/cs/Doc/3.12.0/FreeImage.NET.shfbproj41
-rw-r--r--Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfb50
-rw-r--r--Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfbproj51
-rw-r--r--Wrapper/FreeImage.NET/cs/Doc/SHFB.txt9
-rw-r--r--Wrapper/FreeImage.NET/cs/FreeImage.NET.nunit9
-rw-r--r--Wrapper/FreeImage.NET/cs/FreeImage.NET.sln214
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageBitmap.cs4378
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageEngine.cs101
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/FreeImagePlugin.cs202
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageStreamIO.cs167
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/GifInformation.cs131
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/ImageMetadata.cs286
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/LocalPlugin.cs466
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/MemoryArray.cs828
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModel.cs941
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModels.cs6724
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/MetadataTag.cs757
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/Palette.cs422
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/PluginRepository.cs449
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/Scanline.cs50
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Classes/StreamWrapper.cs312
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Delegates.cs191
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/DisposalMethodType.cs33
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_CHANNEL.cs84
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_DEPTH.cs105
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_OPTIONS.cs68
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_TYPE.cs68
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COMPARE_FLAGS.cs65
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_DITHER.cs73
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FILTER.cs68
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FORMAT.cs192
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_JPEG_OPERATION.cs76
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_LOAD_FLAGS.cs111
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDMODEL.cs92
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDTYPE.cs105
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_METADATA_COPY.cs56
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_QUANTIZE.cs53
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_SAVE_FLAGS.cs183
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TMO.cs56
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TYPE.cs96
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/ICC_FLAGS.cs53
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Enumerations/MD_SEARCH_FLAGS.cs57
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/FreeImageStaticImports.cs2369
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/FreeImageWrapper.cs5319
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Library.csproj190
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Properties/AssemblyInfo.cs21
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/BITMAP.cs104
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFO.cs203
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFOHEADER.cs352
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB555.cs277
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB565.cs277
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FI1BIT.cs70
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FI4BIT.cs70
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIBITMAP.cs175
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FICOMPLEX.cs146
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIICCPROFILE.cs133
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIMEMORY.cs170
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIMETADATA.cs178
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIMULTIBITMAP.cs170
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIRGB16.cs267
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBA16.cs271
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBAF.cs276
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBF.cs272
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIRational.cs1011
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FITAG.cs170
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FIURational.cs1010
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/FreeImageIO.cs66
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/Plugin.cs132
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/RGBQUAD.cs342
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/RGBTRIPLE.cs295
-rw-r--r--Wrapper/FreeImage.NET/cs/Library/Structs/fi_handle.cs256
-rwxr-xr-xWrapper/FreeImage.NET/cs/Library/build.bat7
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs179
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample 01 - Loading and saving.csproj105
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample.jpgbin0 -> 125662 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Program.cs140
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Sample 02 - Multipaged bitmaps.csproj97
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/multipaged.tifbin0 -> 16380 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Program.cs74
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Sample 03 - Allocating.csproj91
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.Designer.cs205
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.cs120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.resx123
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Sample 04 - Getting bitmap informations.csproj104
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Program.cs213
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample 05 - Working with pixels.csproj100
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.jpgbin0 -> 22237 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.tifbin0 -> 24610 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.Designer.cs120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.cs177
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.resx120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample 06 - Converting.csproj109
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample.jpgbin0 -> 125662 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Program.cs73
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample 07 - ICC Profiles.csproj96
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample.jpgbin0 -> 44606 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample 08 - Creating a plugin.csproj110
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample.jpgbin0 -> 125662 bytes
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.Designer.cs119
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.cs217
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.resx120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SerializationPlugin.cs222
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Sample 09 - Working with streams.csproj105
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.Designer.cs115
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.cs147
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.resx120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.Designer.cs87
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.cs105
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.resx120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Sample 10 - Metadata.csproj103
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.Designer.cs382
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.cs412
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.resx126
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.Designer.cs63
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.cs49
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.resx120
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Sample 11 - Using the FreeImageBitmap class.csproj115
-rw-r--r--Wrapper/FreeImage.NET/cs/SourceFileMerger/FreeImage.cs.template219
-rw-r--r--Wrapper/FreeImage.NET/cs/SourceFileMerger/Program.cs122
-rw-r--r--Wrapper/FreeImage.NET/cs/SourceFileMerger/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/SourceFileMerger/SourceFileMerger.csproj97
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/FreeImage.cs30578
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/ImageManager.cs156
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/NUnit.txt14
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/Properties/AssemblyInfo.cs16
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.cs5555
-rw-r--r--Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.csproj105
-rw-r--r--Wrapper/FreeImage.NET/cs/Whats_New.NET.txt111
-rwxr-xr-xWrapper/FreeImage.NET/cs/clean.bat48
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.2003.sln21
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.2003.vcproj215
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.2005.sln19
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.2005.vcproj278
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.2008.vcproj269
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.h1577
-rw-r--r--Wrapper/FreeImagePlus/FreeImagePlus.rc95
-rw-r--r--Wrapper/FreeImagePlus/WhatsNew_FIP.txt150
-rwxr-xr-xWrapper/FreeImagePlus/clean.bat9
-rw-r--r--Wrapper/FreeImagePlus/dist/delete.me0
-rw-r--r--Wrapper/FreeImagePlus/doc/FreeImagePlus.dox222
-rw-r--r--Wrapper/FreeImagePlus/doc/footer.html7
-rw-r--r--Wrapper/FreeImagePlus/doc/freeimage.pngbin0 -> 4591 bytes
-rw-r--r--Wrapper/FreeImagePlus/doc/freeimagedoc.jpgbin0 -> 82081 bytes
-rw-r--r--Wrapper/FreeImagePlus/doc/header.html7
-rw-r--r--Wrapper/FreeImagePlus/doc/main.html18
-rw-r--r--Wrapper/FreeImagePlus/src/FreeImagePlus.cpp46
-rw-r--r--Wrapper/FreeImagePlus/src/fipImage.cpp910
-rw-r--r--Wrapper/FreeImagePlus/src/fipMemoryIO.cpp78
-rw-r--r--Wrapper/FreeImagePlus/src/fipMetadataFind.cpp54
-rw-r--r--Wrapper/FreeImagePlus/src/fipMultiPage.cpp118
-rw-r--r--Wrapper/FreeImagePlus/src/fipTag.cpp134
-rw-r--r--Wrapper/FreeImagePlus/src/fipWinImage.cpp481
-rw-r--r--Wrapper/FreeImagePlus/test/fipTest.2003.sln23
-rw-r--r--Wrapper/FreeImagePlus/test/fipTest.2003.vcproj195
-rw-r--r--Wrapper/FreeImagePlus/test/fipTest.2005.vcproj195
-rw-r--r--Wrapper/FreeImagePlus/test/fipTest.cpp66
-rw-r--r--Wrapper/FreeImagePlus/test/fipTest.h53
-rw-r--r--Wrapper/FreeImagePlus/test/fipTestMPage.cpp76
-rw-r--r--Wrapper/FreeImagePlus/test/fipTestMemIO.cpp165
-rwxr-xr-xWrapper/VB6/awk_script/genbas.sh21
-rw-r--r--Wrapper/VB6/awk_script/genbasfuncs.awk136
-rw-r--r--Wrapper/VB6/awk_script/readme.txt14
-rw-r--r--Wrapper/VB6/mfreeimage/MFreeImage.bas11766
-rw-r--r--Wrapper/VB6/mfreeimage/WhatsNew_VB.txt551
-rw-r--r--Wrapper/VB6/modFreeImage.bas512
-rw-r--r--Wrapper/VB6/test/SimpleTest.frm45
-rw-r--r--Wrapper/VB6/test/SimpleTest.vbp38
-rwxr-xr-xclean.bat59
-rwxr-xr-xclean.sh46
-rw-r--r--fipMakefile.srcs4
-rwxr-xr-xgenfipsrclist.sh23
-rwxr-xr-xgensrclist.sh26
-rw-r--r--license-fi.txt142
-rw-r--r--license-gpl.txt342
968 files changed, 545276 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c23ca65
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,33 @@
+/build
+/source/build
+*.mode1v3
+*.pbxuser
+*.pbxindex/
+!user.pbxuser
+/*.log
+*.user
+*.ncb
+*.suo
+*.pdb
+*.pdf
+*.html
+*.idb
+*.o
+*.lo
+*.a
+*.so
+*.so.0
+*.la
+.deps
+.libs
+*.pyc
+.DS_Store
+# Emacs and other editor backup files
+*~
+
+# builds on Windows
+Debug/
+Release/
+release/
+
+/Dist/FreeImage.h \ No newline at end of file
diff --git a/Dist/delete.me b/Dist/delete.me
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Dist/delete.me
diff --git a/Examples/Generic/BatchLoad.cpp b/Examples/Generic/BatchLoad.cpp
new file mode 100644
index 0000000..1612050
--- /dev/null
+++ b/Examples/Generic/BatchLoad.cpp
@@ -0,0 +1,214 @@
+// ==========================================================
+// Batch loader
+//
+// Design and implementation by
+// - Floris van den Berg
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+//
+// This example shows how to easily batch load a directory
+// full of images. Because not all formats can be identified
+// by their header (some images don't have a header or one
+// at the end of the file) we make use of the
+// FreeImage_GetFIFFromFilename function. This function
+// receives a file name, for example 'myfile.bmp', and returns
+// a FREE_IMAGE_TYPE enum which identifies that bitmap.
+//
+// Functions used in this sample :
+// FreeImage_GetFileType, FreeImage_GetFIFFromFilename, FreeImage_FIFSupportsReading,
+// FreeImage_Load, FreeImage_GetBPP, FreeImage_FIFSupportsWriting, FreeImage_GetFormatFromFIF
+// FreeImage_FIFSupportsExportBPP, FreeImage_Save, FreeImage_Unload,
+// FreeImage_SetOutputMessage, FreeImage_GetVersion, FreeImage_GetCopyrightMessage
+//
+// ==========================================================
+
+#include <assert.h>
+#include <stdio.h>
+#include <io.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/** Generic image loader
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional load flag constant
+ @return Returns the loaded dib if successful, returns NULL otherwise
+*/
+FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and deduce its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // ok, let's load the file
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
+ // unless a bad file format, we are done !
+ return dib;
+ }
+ return NULL;
+}
+
+/** Generic image writer
+ @param dib Pointer to the dib to be saved
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional save flag constant
+ @return Returns true if successful, returns false otherwise
+*/
+bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ BOOL bSuccess = FALSE;
+
+ if(dib) {
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ if(fif != FIF_UNKNOWN ) {
+ // check that the plugin has sufficient writing and export capabilities ...
+ WORD bpp = FreeImage_GetBPP(dib);
+ if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
+ // ok, we can save the file
+ bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
+ // unless an abnormal bug, we are done !
+ }
+ }
+ }
+ return (bSuccess == TRUE) ? true : false;
+}
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ printf("\n*** ");
+ if(fif != FIF_UNKNOWN) {
+ printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
+ }
+ printf(message);
+ printf(" ***\n");
+}
+
+// ----------------------------------------------------------
+
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+int
+main(int argc, char *argv[]) {
+
+ const char *input_dir = "d:\\images\\";
+ FIBITMAP *dib = NULL;
+ int id = 1;
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize your own FreeImage error handler
+
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // print version & copyright infos
+
+ printf(FreeImage_GetVersion());
+ printf("\n");
+ printf(FreeImage_GetCopyrightMessage());
+ printf("\n");
+
+ // open the log file
+
+ FILE *log_file = fopen("log_file.txt", "w");
+
+ // batch convert all supported bitmaps
+
+ _finddata_t finddata;
+ long handle;
+ char image_path[MAX_PATH];
+
+ // scan all files
+ strcpy(image_path, input_dir);
+ strcat(image_path, "*.*");
+
+ if ((handle = _findfirst(image_path, &finddata)) != -1) {
+ do {
+ // make a path to a directory
+
+ char *directory = new char[MAX_PATH];
+ strcpy(directory, input_dir);
+ strcat(directory, finddata.name);
+
+ // make a unique filename
+
+ char *unique = new char[128];
+ itoa(id, unique, 10);
+ strcat(unique, ".png");
+
+ // open and load the file using the default load option
+ dib = GenericLoader(directory, 0);
+
+ if (dib != NULL) {
+ // save the file as PNG
+ bool bSuccess = GenericWriter(dib, unique, PNG_DEFAULT);
+
+ // free the dib
+ FreeImage_Unload(dib);
+
+ if(bSuccess) {
+ fwrite(unique, strlen(unique), 1, log_file);
+ } else {
+ strcpy(unique, "FAILED");
+ fwrite(unique, strlen(unique), 1, log_file);
+ }
+ fwrite(" >> ", 4, 1, log_file);
+ fwrite(directory, strlen(directory), 1, log_file);
+ fwrite("\n", 1, 1, log_file);
+
+ id++;
+ }
+
+ delete [] unique;
+ delete [] directory;
+
+ } while (_findnext(handle, &finddata) == 0);
+
+ _findclose(handle);
+ }
+
+ fclose(log_file);
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+}
diff --git a/Examples/Generic/CloneMultiPage.cpp b/Examples/Generic/CloneMultiPage.cpp
new file mode 100644
index 0000000..2124998
--- /dev/null
+++ b/Examples/Generic/CloneMultiPage.cpp
@@ -0,0 +1,112 @@
+// ==========================================================
+// Multipage functions demonstration
+//
+// Design and implementation by
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+// This sample shows how to clone a multipage TIFF
+//
+// Functions used in this sample :
+// FreeImage_OpenMultiBitmap, FreeImage_GetPageCount, FreeImage_LockPage,
+// FreeImage_AppendPage, FreeImage_UnlockPage, FreeImage_CloseMultiBitmap;
+// FreeImage_SetOutputMessage
+//
+// ==========================================================
+
+#include <iostream.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+*/
+void MyMessageFunc(FREE_IMAGE_FORMAT fif, const char *message) {
+ cout << "\n*** " << message << " ***\n";
+ cout.flush();
+}
+
+// ----------------------------------------------------------
+
+bool CloneMultiPage(FREE_IMAGE_FORMAT fif, char *input, char *output, int output_flag) {
+
+ BOOL bMemoryCache = TRUE;
+
+ // Open src file (read-only, use memory cache)
+ FIMULTIBITMAP *src = FreeImage_OpenMultiBitmap(fif, input, FALSE, TRUE, bMemoryCache);
+
+ if(src) {
+ // Open dst file (creation, use memory cache)
+ FIMULTIBITMAP *dst = FreeImage_OpenMultiBitmap(fif, output, TRUE, FALSE, bMemoryCache);
+
+ // Get src page count
+ int count = FreeImage_GetPageCount(src);
+
+ // Clone src to dst
+ for(int page = 0; page < count; page++) {
+ // Load the bitmap at position 'page'
+ FIBITMAP *dib = FreeImage_LockPage(src, page);
+ if(dib) {
+ // add a new bitmap to dst
+ FreeImage_AppendPage(dst, dib);
+ // Unload the bitmap (do not apply any change to src)
+ FreeImage_UnlockPage(src, dib, FALSE);
+ }
+ }
+
+ // Close src
+ FreeImage_CloseMultiBitmap(src, 0);
+ // Save and close dst
+ FreeImage_CloseMultiBitmap(dst, output_flag);
+
+ return true;
+ }
+
+ return false;
+}
+
+
+int
+main(int argc, char *argv[]) {
+
+ char *input_filename = "images\\input.tif";
+ char *output_filename = "images\\clone.tif";
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize our own FreeImage error handler
+
+ FreeImage_SetOutputMessage(MyMessageFunc);
+
+ // Copy 'input.tif' to 'clone.tif'
+
+ CloneMultiPage(FIF_TIFF, input_filename, output_filename, 0);
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+}
diff --git a/Examples/Generic/CreateAlpha.cpp b/Examples/Generic/CreateAlpha.cpp
new file mode 100644
index 0000000..77bb2a2
--- /dev/null
+++ b/Examples/Generic/CreateAlpha.cpp
@@ -0,0 +1,181 @@
+// ==========================================================
+// Alpha channel manipulation example
+//
+// Design and implementation by
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+// This example shows how to create a transparent image from any input image
+// using the greyscale version of the input image as the alpha channel mask.
+// The alpha channel is set using the FreeImage_SetChannel function.
+//
+//
+// ==========================================================
+
+#include <stdio.h>
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/** Generic image loader
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional load flag constant
+ @return Returns the loaded dib if successful, returns NULL otherwise
+*/
+FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and deduce its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // ok, let's load the file
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
+ // unless a bad file format, we are done !
+ return dib;
+ }
+ return NULL;
+}
+
+/** Generic image writer
+ @param dib Pointer to the dib to be saved
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional save flag constant
+ @return Returns true if successful, returns false otherwise
+*/
+bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ BOOL bSuccess = FALSE;
+
+ if(dib) {
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ if(fif != FIF_UNKNOWN ) {
+ // check that the plugin has sufficient writing and export capabilities ...
+ WORD bpp = FreeImage_GetBPP(dib);
+ if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
+ // ok, we can save the file
+ bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
+ // unless an abnormal bug, we are done !
+ }
+ }
+ }
+ return (bSuccess == TRUE) ? true : false;
+}
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ printf("\n*** ");
+ if(fif != FIF_UNKNOWN) {
+ printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
+ }
+ printf(message);
+ printf(" ***\n");
+}
+
+// ----------------------------------------------------------
+
+
+/**
+ Creates a 32-bit transparent image using the black channel of the source image
+ @param src Source image
+ @return Returns a 32-bit transparent image
+*/
+FIBITMAP* CreateAlphaFromLightness(FIBITMAP *src) {
+ // create a 32-bit image from the source
+ FIBITMAP *dst = FreeImage_ConvertTo32Bits(src);
+
+ // create a 8-bit mask
+ FreeImage_Invert(src);
+ FIBITMAP *mask = FreeImage_ConvertTo8Bits(src);
+ FreeImage_Invert(src);
+
+ // insert the mask as an alpha channel
+ FreeImage_SetChannel(dst, mask, FICC_ALPHA);
+
+ // free the mask and return
+ FreeImage_Unload(mask);
+
+ return dst;
+}
+
+int
+main(int argc, char *argv[]) {
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize your own FreeImage error handler
+
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // print version & copyright infos
+
+ printf("FreeImage version : %s", FreeImage_GetVersion());
+ printf("\n");
+ printf(FreeImage_GetCopyrightMessage());
+ printf("\n");
+
+
+ if(argc != 3) {
+ printf("Usage : CreateAlpha <input file name> <output file name>\n");
+ return 0;
+ }
+
+ // Load the source image
+ FIBITMAP *src = GenericLoader(argv[1], 0);
+ if(src) {
+ // Create a transparent image from the lightness image of src
+ FIBITMAP *dst = CreateAlphaFromLightness(src);
+
+ if(dst) {
+ // Save the destination image
+ bool bSuccess = GenericWriter(dst, argv[2], 0);
+ if(!bSuccess) {
+ printf("\nUnable to save %s file", argv[2]);
+ printf("\nThis format does not support 32-bit images");
+ }
+
+ // Free dst
+ FreeImage_Unload(dst);
+ }
+
+ // Free src
+ FreeImage_Unload(src);
+ }
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+}
diff --git a/Examples/Generic/FIFImportExport.cpp b/Examples/Generic/FIFImportExport.cpp
new file mode 100644
index 0000000..ec791b2
--- /dev/null
+++ b/Examples/Generic/FIFImportExport.cpp
@@ -0,0 +1,149 @@
+// ==========================================================
+// Plugin functions demonstration
+//
+// Design and implementation by
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+// This example shows how to use Plugin functions to explore FreeImage capabilities.
+// Whenever an external plugin is added to the library, it is automatically loaded
+// with FreeImage and can be asked for its capabilities via the plugin functions.
+//
+// Functions used in this sample :
+// FreeImage_FIFSupportsExportBPP, FreeImage_FIFSupportsICCProfiles, FreeImage_FIFSupportsReading,
+// FreeImage_FIFSupportsWriting, FreeImage_GetFIFCount, FreeImage_GetFIFDescription,
+// FreeImage_GetFIFExtensionList, FreeImage_GetFormatFromFIF,
+// FreeImage_GetVersion, FreeImage_GetCopyrightMessage, FreeImage_SetOutputMessage
+//
+// ==========================================================
+
+#include <iostream.h>
+#include <fstream.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+*/
+void MyMessageFunc(FREE_IMAGE_FORMAT fif, const char *message) {
+ cout << "\n*** " << message << " ***\n";
+}
+
+// ----------------------------------------------------------
+
+/**
+ Print plugins import capabilities
+*/
+void PrintImportFormats(iostream& ios) {
+ int count = FreeImage_GetFIFCount();
+ if(count)
+ ios << "FORMAT;DESCRIPTION;EXTENSIONS;ICC PROFILES\n";
+ for(int i = 0; i < count; i++) {
+ FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i;
+
+ if(FreeImage_FIFSupportsReading(fif)) {
+ const char * format = FreeImage_GetFormatFromFIF(fif);
+ const char * description = FreeImage_GetFIFDescription(fif);
+ const char * ext = FreeImage_GetFIFExtensionList(fif);
+ const char * icc = "*";
+ if(FreeImage_FIFSupportsICCProfiles(fif)) {
+ ios << format << ";" << description << ";" << ext << ";" << icc << "\n";
+ } else {
+ ios << format << ";" << description << ";" << ext << "; \n";
+ }
+ }
+ }
+}
+
+/**
+ Print plugins export capabilities
+*/
+void PrintExportFormats(iostream& ios) {
+ int count = FreeImage_GetFIFCount();
+ if(count)
+ ios << "FORMAT;DESCRIPTION;EXTENSIONS;BITDEPTH;ICC PROFILES\n";
+ for(int i = 0; i < count; i++) {
+ FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i;
+
+ if(FreeImage_FIFSupportsWriting(fif)) {
+ const char * format = FreeImage_GetFormatFromFIF(fif);
+ const char * description = FreeImage_GetFIFDescription(fif);
+ const char * ext = FreeImage_GetFIFExtensionList(fif);
+ const char * icc = "*";
+
+ ios << format << ";" << description << ";" << ext << ";";
+ if(FreeImage_FIFSupportsExportBPP(fif, 1))
+ ios << "1 ";
+ if(FreeImage_FIFSupportsExportBPP(fif, 4))
+ ios << "4 ";
+ if(FreeImage_FIFSupportsExportBPP(fif, 8))
+ ios << "8 ";
+ if(FreeImage_FIFSupportsExportBPP(fif, 16))
+ ios << "16 ";
+ if(FreeImage_FIFSupportsExportBPP(fif, 24))
+ ios << "24 ";
+ if(FreeImage_FIFSupportsExportBPP(fif, 32))
+ ios << "32 ";
+ if(FreeImage_FIFSupportsICCProfiles(fif)) {
+ ios << ";" << icc;
+ } else {
+ ios << "; ";
+ }
+ ios << "\n";
+ }
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize FreeImage error handler
+
+ FreeImage_SetOutputMessage(MyMessageFunc);
+
+ // print version & copyright infos
+
+ cout << "FreeImage " << FreeImage_GetVersion() << "\n";
+ cout << FreeImage_GetCopyrightMessage() << "\n\n";
+
+ // Print input formats (including external plugins) known by the library
+ fstream importFile("fif_import.csv", ios::out);
+ PrintImportFormats(importFile);
+ importFile.close();
+
+ // Print output formats (including plugins) known by the library
+ // for each export format, supported bitdepths are given
+ fstream exportFile("fif_export.csv", ios::out);
+ PrintExportFormats(exportFile);
+ exportFile.close();
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+
+}
diff --git a/Examples/Generic/FIIO_Mem.cpp b/Examples/Generic/FIIO_Mem.cpp
new file mode 100644
index 0000000..703acb1
--- /dev/null
+++ b/Examples/Generic/FIIO_Mem.cpp
@@ -0,0 +1,146 @@
+/*--------------------------------------------------------------------------*\
+|| fiio_mem.cpp by Ryan Rubley <ryan@lostreality.org> ||
+|| ||
+|| (v1.02) 4-28-2004 ||
+|| FreeImageIO to memory ||
+|| ||
+\*--------------------------------------------------------------------------*/
+
+#include <string.h>
+#include <stdlib.h>
+#include "fiio_mem.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+FIBITMAP *
+FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags) {
+ FreeImageIO io;
+ SetMemIO(&io);
+
+ if (handle && handle->data) {
+ handle->curpos = 0;
+ return FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
+ }
+
+ return NULL;
+}
+
+BOOL
+FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags) {
+ FreeImageIO io;
+ SetMemIO(&io);
+
+ if (handle) {
+ handle->filelen = 0;
+ handle->curpos = 0;
+ return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
+ }
+
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+void
+SetMemIO(FreeImageIO *io) {
+ io->read_proc = fiio_mem_ReadProc;
+ io->seek_proc = fiio_mem_SeekProc;
+ io->tell_proc = fiio_mem_TellProc;
+ io->write_proc = fiio_mem_WriteProc;
+}
+
+// ----------------------------------------------------------
+
+#define FIIOMEM(member) (((fiio_mem_handle *)handle)->member)
+
+unsigned
+fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ unsigned x;
+ for( x=0; x<count; x++ ) {
+ //if there isnt size bytes left to read, set pos to eof and return a short count
+ if( FIIOMEM(filelen)-FIIOMEM(curpos) < (long)size ) {
+ FIIOMEM(curpos) = FIIOMEM(filelen);
+ break;
+ }
+ //copy size bytes count times
+ memcpy( buffer, (char *)FIIOMEM(data) + FIIOMEM(curpos), size );
+ FIIOMEM(curpos) += size;
+ buffer = (char *)buffer + size;
+ }
+ return x;
+}
+
+unsigned
+fiio_mem_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ void *newdata;
+ long newdatalen;
+ //double the data block size if we need to
+ while( FIIOMEM(curpos)+(long)(size*count) >= FIIOMEM(datalen) ) {
+ //if we are at or above 1G, we cant double without going negative
+ if( FIIOMEM(datalen) & 0x40000000 ) {
+ //max 2G
+ if( FIIOMEM(datalen) == 0x7FFFFFFF ) {
+ return 0;
+ }
+ newdatalen = 0x7FFFFFFF;
+ } else if( FIIOMEM(datalen) == 0 ) {
+ //default to 4K if nothing yet
+ newdatalen = 4096;
+ } else {
+ //double size
+ newdatalen = FIIOMEM(datalen) << 1;
+ }
+ newdata = realloc( FIIOMEM(data), newdatalen );
+ if( !newdata ) {
+ return 0;
+ }
+ FIIOMEM(data) = newdata;
+ FIIOMEM(datalen) = newdatalen;
+ }
+ memcpy( (char *)FIIOMEM(data) + FIIOMEM(curpos), buffer, size*count );
+ FIIOMEM(curpos) += size*count;
+ if( FIIOMEM(curpos) > FIIOMEM(filelen) ) {
+ FIIOMEM(filelen) = FIIOMEM(curpos);
+ }
+ return count;
+}
+
+int
+fiio_mem_SeekProc(fi_handle handle, long offset, int origin) {
+ switch(origin) { //0 to filelen-1 are 'inside' the file
+ default:
+ case SEEK_SET: //can fseek() to 0-7FFFFFFF always
+ if( offset >= 0 ) {
+ FIIOMEM(curpos) = offset;
+ return 0;
+ }
+ break;
+
+ case SEEK_CUR:
+ if( FIIOMEM(curpos)+offset >= 0 ) {
+ FIIOMEM(curpos) += offset;
+ return 0;
+ }
+ break;
+
+ case SEEK_END:
+ if( FIIOMEM(filelen)+offset >= 0 ) {
+ FIIOMEM(curpos) = FIIOMEM(filelen)+offset;
+ return 0;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+long
+fiio_mem_TellProc(fi_handle handle) {
+ return FIIOMEM(curpos);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Examples/Generic/FIIO_Mem.h b/Examples/Generic/FIIO_Mem.h
new file mode 100644
index 0000000..e686b1c
--- /dev/null
+++ b/Examples/Generic/FIIO_Mem.h
@@ -0,0 +1,74 @@
+/*--------------------------------------------------------------------------*\
+|| fiio_mem.h by Ryan Rubley <ryan@lostreality.org> ||
+|| ||
+|| (v1.02) 4-28-2004 ||
+|| FreeImageIO to memory ||
+|| ||
+\*--------------------------------------------------------------------------*/
+
+#ifndef _FIIO_MEM_H_
+#define _FIIO_MEM_H_
+
+#include "freeimage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct fiio_mem_handle_s {
+ long filelen,datalen,curpos;
+ void *data;
+} fiio_mem_handle;
+
+/* it is up to the user to create a fiio_mem_handle and init datalen and data
+ * filelen will be pre-set to 0 by SaveToMem
+ * curpos will be pre-set to 0 by SaveToMem and LoadFromMem
+ * IMPORTANT: data should be set to NULL and datalen to 0,
+ * unless the user wants to manually malloc a larger buffer
+ */
+FIBITMAP *FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags);
+BOOL FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags);
+
+void SetMemIO(FreeImageIO *io);
+unsigned fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
+unsigned fiio_mem_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
+int fiio_mem_SeekProc(fi_handle handle, long offset, int origin);
+long fiio_mem_TellProc(fi_handle handle);
+
+/*** Example Usage ***
+
+//variables
+FIBITMAP *bitmap, *bitmap2;
+fiio_mem_handle fmh;
+
+//important initialization
+fmh.data = NULL;
+fmh.datalen = 0;
+
+//load a regular file
+bitmap = FreeImage_Load(FIF_PNG, "sample.png");
+
+//save the file to memory
+FreeImage_SaveToMem(FIF_PNG, bitmap, &fmh, 0);
+
+//at this point, fmh.data contains the entire PNG data in memory
+//fmh.datalen is the amount of space malloc'd for the image in memory,
+//but only fmh.filelen amount of that space is actually used.
+
+//its easy load an image from memory as well
+bitmap2 = FreeImage_LoadFromMem(FIF_PNG, &fmh, 0);
+//you could also have image data in memory via some other method, and just set
+//fmh.data to point to it, and set both fmh.datalen and fmh.filelen to the
+//size of that data, then FreeImage_LoadFromMem could load the image from that
+//memory
+
+//make sure to free the data since SaveToMem will cause it to be malloc'd
+free(fmh.data);
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Examples/Generic/LoadFromHandle.cpp b/Examples/Generic/LoadFromHandle.cpp
new file mode 100644
index 0000000..45afb46
--- /dev/null
+++ b/Examples/Generic/LoadFromHandle.cpp
@@ -0,0 +1,145 @@
+// ==========================================================
+// Load From Handle Example
+//
+// Design and implementation by
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+// This example shows how to load a bitmap from a
+// user allocated FILE pointer.
+//
+// Functions used in this sample :
+// FreeImage_GetFormatFromFIF, FreeImage_GetFileTypeFromHandle, FreeImage_LoadFromHandle,
+// FreeImage_GetFIFFromFilename, FreeImage_Save, FreeImage_Unload
+// FreeImage_GetVersion, FreeImage_GetCopyrightMessage, FreeImage_SetOutputMessage
+//
+// ==========================================================
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ printf("\n*** ");
+ if(fif != FIF_UNKNOWN) {
+ printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
+ }
+ printf(message);
+ printf(" ***\n");
+}
+
+// ----------------------------------------------------------
+
+unsigned DLL_CALLCONV
+myReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ return fread(buffer, size, count, (FILE *)handle);
+}
+
+unsigned DLL_CALLCONV
+myWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ return fwrite(buffer, size, count, (FILE *)handle);
+}
+
+int DLL_CALLCONV
+mySeekProc(fi_handle handle, long offset, int origin) {
+ return fseek((FILE *)handle, offset, origin);
+}
+
+long DLL_CALLCONV
+myTellProc(fi_handle handle) {
+ return ftell((FILE *)handle);
+}
+
+// ----------------------------------------------------------
+
+int
+main(int argc, char *argv[]) {
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize your own FreeImage error handler
+
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // print version & copyright infos
+
+ printf(FreeImage_GetVersion());
+ printf("\n");
+ printf(FreeImage_GetCopyrightMessage());
+ printf("\n");
+
+
+ if(argc != 2) {
+ printf("Usage : LoadFromHandle <input file name>\n");
+ return 0;
+ }
+
+ // initialize your own IO functions
+
+ FreeImageIO io;
+
+ io.read_proc = myReadProc;
+ io.write_proc = myWriteProc;
+ io.seek_proc = mySeekProc;
+ io.tell_proc = myTellProc;
+
+ FILE *file = fopen(argv[1], "rb");
+
+ if (file != NULL) {
+ // find the buffer format
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)file, 0);
+
+ if(fif != FIF_UNKNOWN) {
+ // load from the file handle
+ FIBITMAP *dib = FreeImage_LoadFromHandle(fif, &io, (fi_handle)file, 0);
+
+ // save the bitmap as a PNG ...
+ const char *output_filename = "test.png";
+
+ // first, check the output format from the file name or file extension
+ FREE_IMAGE_FORMAT out_fif = FreeImage_GetFIFFromFilename(output_filename);
+
+ if(out_fif != FIF_UNKNOWN) {
+ // then save the file
+ FreeImage_Save(out_fif, dib, output_filename, 0);
+ }
+
+ // free the loaded FIBITMAP
+ FreeImage_Unload(dib);
+ }
+ fclose(file);
+ }
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+}
diff --git a/Examples/Generic/LoadFromMemory-classified.cpp b/Examples/Generic/LoadFromMemory-classified.cpp
new file mode 100644
index 0000000..5466f48
--- /dev/null
+++ b/Examples/Generic/LoadFromMemory-classified.cpp
@@ -0,0 +1,101 @@
+// ==========================================================
+// Classified FreeImageIO handler
+//
+// Design and implementation by
+// - schickb (schickb@hotmail.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+class MemIO : public FreeImageIO {
+public :
+ MemIO( BYTE *data ) : _start(data), _cp(data) {
+ read_proc = _ReadProc;
+ write_proc = _WriteProc;
+ tell_proc = _TellProc;
+ seek_proc = _SeekProc;
+ }
+
+ void Reset() {
+ _cp = _start;
+ }
+
+ static unsigned _ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
+ static unsigned _WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
+ static int _SeekProc(fi_handle handle, long offset, int origin);
+ static long _TellProc(fi_handle handle);
+
+private:
+ BYTE * const _start;
+ BYTE *_cp;
+};
+
+
+unsigned
+MemIO::_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ MemIO *memIO = (MemIO*)handle;
+
+ BYTE *tmp = (BYTE *)buffer;
+
+ for (unsigned c = 0; c < count; c++) {
+ memcpy(tmp, memIO->_cp, size);
+
+ memIO->_cp = memIO->_cp + size;
+
+ tmp += size;
+ }
+
+ return count;
+}
+
+unsigned
+MemIO::_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ ASSERT( false );
+ return size;
+}
+
+int
+MemIO::_SeekProc(fi_handle handle, long offset, int origin) {
+ ASSERT(origin != SEEK_END);
+
+ MemIO *memIO = (MemIO*)handle;
+
+ if (origin == SEEK_SET)
+ memIO->_cp = memIO->_start + offset;
+ else
+ memIO->_cp = memIO->_cp + offset;
+
+ return 0;
+}
+
+long
+MemIO::_TellProc(fi_handle handle) {
+ MemIO *memIO = (MemIO*)handle;
+
+ return memIO->_cp - memIO->_start;
+}
+
+// ----------------------------------------------------------
+// PSEUDOCODE... HELPS TO UNDERSTAND HOW THE MEMIO CLASS WORKS
+// ----------------------------------------------------------
+
+int
+main(int argc, char *argv[]) {
+ BYTE *data = loadimagesomehow();
+
+ MemIO memIO(data);
+
+ FIBITMAP *fbmp = FreeImage_LoadFromHandle( fif, &memIO, (fi_handle)&memIO );
+} \ No newline at end of file
diff --git a/Examples/Generic/LoadFromMemory.cpp b/Examples/Generic/LoadFromMemory.cpp
new file mode 100644
index 0000000..026ebff
--- /dev/null
+++ b/Examples/Generic/LoadFromMemory.cpp
@@ -0,0 +1,113 @@
+// ==========================================================
+// Load From Memory Example
+//
+// Design and implementation by Floris van den Berg
+//
+// This file is part of FreeImage 3
+//
+// Use at own risk!
+// ==========================================================
+//
+// This example shows how to load a bitmap from memory
+// rather than from a file. To do this we make use of the
+// FreeImage_LoadFromHandle functions where we override
+// the i/o functions to simulate FILE* access in memory.
+//
+// For seeking purposes the fi_handle passed to the i/o
+// functions contain the start of the data block where the
+// bitmap is stored.
+//
+// ==========================================================
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+fi_handle g_load_address;
+
+// ----------------------------------------------------------
+
+inline unsigned _stdcall
+_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ BYTE *tmp = (BYTE *)buffer;
+
+ for (unsigned c = 0; c < count; c++) {
+ memcpy(tmp, g_load_address, size);
+
+ g_load_address = (BYTE *)g_load_address + size;
+
+ tmp += size;
+ }
+
+ return count;
+}
+
+inline unsigned _stdcall
+_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ // there's not much use for saving the bitmap into memory now, is there?
+
+ return size;
+}
+
+inline int _stdcall
+_SeekProc(fi_handle handle, long offset, int origin) {
+ assert(origin != SEEK_END);
+
+ if (origin == SEEK_SET) {
+ g_load_address = (BYTE *)handle + offset;
+ } else {
+ g_load_address = (BYTE *)g_load_address + offset;
+ }
+
+ return 0;
+}
+
+inline long _stdcall
+_TellProc(fi_handle handle) {
+ assert((int)handle > (int)g_load_address);
+
+ return ((int)g_load_address - (int)handle);
+}
+
+// ----------------------------------------------------------
+
+int
+main(int argc, char *argv[]) {
+ FreeImageIO io;
+
+ io.read_proc = _ReadProc;
+ io.write_proc = _WriteProc;
+ io.tell_proc = _TellProc;
+ io.seek_proc = _SeekProc;
+
+ // allocate some memory for the bitmap
+
+ BYTE *test = new BYTE[159744];
+
+ if (test != NULL) {
+ // load the bitmap into memory. ofcourse you can do this any way you want
+
+ FILE *file = fopen("e:\\projects\\images\\money-256.tif", "rb");
+ fread(test, 159744, 1, file);
+ fclose(file);
+
+ // we store the load address of the bitmap for internal reasons
+
+ g_load_address = test;
+
+ // convert the bitmap
+
+ FIBITMAP *dib = FreeImage_LoadFromHandle(FIF_TIFF, &io, (fi_handle)test);
+
+ // don't forget to free the dib !
+ FreeImage_Unload(dib);
+
+ delete [] test;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/Examples/Generic/ShowMetadata.cpp b/Examples/Generic/ShowMetadata.cpp
new file mode 100644
index 0000000..95d8be1
--- /dev/null
+++ b/Examples/Generic/ShowMetadata.cpp
@@ -0,0 +1,317 @@
+// ==========================================================
+// Simple metadata reader
+//
+// Design and implementation by
+// - Hervé Drolon
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at own risk!
+// ==========================================================
+
+//
+// This example shows how to easily parse all metadata
+// contained in a JPEG, TIFF or PNG image.
+// Comments, Exif and IPTC/NAA metadata tags are written to a HTML file
+// for later reading, and Adobe XMP XML packets are written
+// in a file whose extension is '.xmp'. This file can be later
+// processed using a XML parser.
+//
+// Metadata functions showed in this sample :
+// FreeImage_GetMetadataCount, FreeImage_FindFirstMetadata, FreeImage_FindNextMetadata,
+// FreeImage_FindCloseMetadata, FreeImage_TagToString, FreeImage_GetMetadata
+//
+// ==========================================================
+
+#include <iostream>
+#include <sstream>
+#include <fstream>
+
+using namespace std;
+
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+/** Generic image loader
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional load flag constant
+ @return Returns the loaded dib if successful, returns NULL otherwise
+*/
+FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and deduce its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // ok, let's load the file
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
+ // unless a bad file format, we are done !
+ return dib;
+ }
+ return NULL;
+}
+
+/** Generic image writer
+ @param dib Pointer to the dib to be saved
+ @param lpszPathName Pointer to the full file name
+ @param flag Optional save flag constant
+ @return Returns true if successful, returns false otherwise
+*/
+bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ BOOL bSuccess = FALSE;
+
+ if(dib) {
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ if(fif != FIF_UNKNOWN ) {
+ // check that the plugin has sufficient writing and export capabilities ...
+ WORD bpp = FreeImage_GetBPP(dib);
+ if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
+ // ok, we can save the file
+ bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
+ // unless an abnormal bug, we are done !
+ }
+ }
+ }
+ return (bSuccess == TRUE) ? true : false;
+}
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ cout << "\n*** ";
+ if(fif != FIF_UNKNOWN) {
+ cout << FreeImage_GetFormatFromFIF(fif) << " Format\n";
+ }
+ cout << message;
+ cout << " ***\n";
+}
+
+// ----------------------------------------------------------
+
+/**
+Print a basic HTML header
+*/
+void PrintHTMLHeader(iostream& ios) {
+ ios << "<HTML>\n<BODY>\n<CENTER>\n";
+ ios << "<FONT FACE = \"Arial\">\n";
+}
+
+/**
+Print a HTML footer
+*/
+void PrintHTMLFooter(iostream& ios) {
+ ios << "</CENTER>\n</FONT>\n</BODY>\n</HTML>\n";
+}
+
+/**
+Print a table header
+*/
+void PrintTableHeader(iostream& ios, const char *title) {
+ ios << "<TABLE BORDER=\"1\">\n";
+ ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#CCCCCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
+}
+
+/**
+Print a table section
+*/
+void PrintTableSection(iostream& ios, const char *title) {
+ ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#FFFFCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
+ ios << "<TR><TD><B>Tag name</B></TD><TD><B>Tag value</B></TD><TD><B>Description</B></TD></TR>";
+}
+
+/**
+Print a table footer
+*/
+void PrintTableFooter(iostream& ios) {
+ ios << "</TABLE>\n";
+}
+
+
+/**
+Print the metadata tags to a HTML file
+*/
+void PrintMetadata(iostream& ios, const char *sectionTitle, FIBITMAP *dib, FREE_IMAGE_MDMODEL model) {
+ FITAG *tag = NULL;
+ FIMETADATA *mdhandle = NULL;
+
+ mdhandle = FreeImage_FindFirstMetadata(model, dib, &tag);
+
+ if(mdhandle) {
+ // Print a table section
+ PrintTableSection(ios, sectionTitle);
+
+ do {
+ // convert the tag value to a string
+ const char *value = FreeImage_TagToString(model, tag);
+
+ // print the tag
+ // note that most tags do not have a description,
+ // especially when the metadata specifications are not available
+ if(FreeImage_GetTagDescription(tag)) {
+ ios << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << FreeImage_GetTagDescription(tag) << "</TD></TR>\n";
+ } else {
+ ios << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << "&nbsp;" << "</TD></TR>\n";
+ }
+
+ } while(FreeImage_FindNextMetadata(mdhandle, &tag));
+ }
+
+ FreeImage_FindCloseMetadata(mdhandle);
+}
+
+int
+main(int argc, char *argv[]) {
+ unsigned count;
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+#endif // FREEIMAGE_LIB
+
+ // initialize your own FreeImage error handler
+
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // print version & copyright infos
+
+ cout << "FreeImage " << FreeImage_GetVersion() << "\n";
+ cout << FreeImage_GetCopyrightMessage() << "\n\n";
+
+ if(argc != 2) {
+ cout << "Usage : ShowMetadata <input file name>\n";
+ return 0;
+ }
+
+ // Load the bitmap
+
+ FIBITMAP *dib = GenericLoader(argv[1], 0);
+ if(!dib)
+ return 0;
+
+ // Create a HTML file
+ std::string html_file(strtok(argv[1], ".") + std::string(".html"));
+
+ fstream metadataFile(html_file.c_str(), ios::out);
+
+ // Print the header
+
+ PrintHTMLHeader(metadataFile);
+ PrintTableHeader(metadataFile, argv[1]);
+
+ // Parse and print metadata
+
+ if(count = FreeImage_GetMetadataCount(FIMD_COMMENTS, dib)) {
+ cout << "\nFIMD_COMMENTS (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "Comments", dib, FIMD_COMMENTS);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) {
+ cout << "\nFIMD_EXIF_MAIN (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "Exif - main info", dib, FIMD_EXIF_MAIN);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_EXIF_EXIF, dib)) {
+ cout << "\nFIMD_EXIF_EXIF (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "Exif - advanced info", dib, FIMD_EXIF_EXIF);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_EXIF_GPS, dib)) {
+ cout << "\nFIMD_EXIF_GPS (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "Exif GPS", dib, FIMD_EXIF_GPS);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_EXIF_INTEROP, dib)) {
+ cout << "\nFIMD_EXIF_INTEROP (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "Exif interoperability", dib, FIMD_EXIF_INTEROP);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAKERNOTE, dib)) {
+ cout << "\nFIMD_EXIF_MAKERNOTE (" << count << " data)\n-----------------------------------------\n";
+
+ // Get the camera model
+ FITAG *tagMake = NULL;
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake);
+
+ std::string buffer((char*)FreeImage_GetTagValue(tagMake));
+ buffer += " Makernote";
+
+ PrintMetadata(metadataFile, buffer.c_str(), dib, FIMD_EXIF_MAKERNOTE);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
+ cout << "\nFIMD_IPTC (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "IPTC/NAA", dib, FIMD_IPTC);
+ }
+ if(count = FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib)) {
+ cout << "\nFIMD_GEOTIFF (" << count << " data)\n-----------------------------------------\n";
+
+ PrintMetadata(metadataFile, "GEOTIFF", dib, FIMD_GEOTIFF);
+ }
+
+ // Print the footer
+
+ PrintTableFooter(metadataFile);
+ PrintHTMLFooter(metadataFile);
+
+ // close the HTML file
+
+ metadataFile.close();
+
+ // print XMP data
+
+ if(count = FreeImage_GetMetadataCount(FIMD_XMP, dib)) {
+ cout << "\nFIMD_XMP (" << count << " packet)\n-----------------------------------------\n";
+
+ std::string xmp_file(strtok(argv[1], ".") + std::string(".xmp"));
+ metadataFile.open(xmp_file.c_str(), ios::out);
+
+ FITAG *tag = NULL;
+ FreeImage_GetMetadata(FIMD_XMP, dib, "XMLPacket", &tag);
+ if(tag) {
+ metadataFile << (char*)FreeImage_GetTagValue(tag);
+ }
+
+ metadataFile.close();
+ }
+
+
+ // Unload the bitmap
+
+ FreeImage_Unload(dib);
+
+
+ // call this ONLY when linking with FreeImage as a static library
+#ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+#endif // FREEIMAGE_LIB
+
+ return 0;
+}
+
+
+
diff --git a/Examples/Linux/Makefile b/Examples/Linux/Makefile
new file mode 100644
index 0000000..48f9b7a
--- /dev/null
+++ b/Examples/Linux/Makefile
@@ -0,0 +1,25 @@
+CC = gcc
+CPP = g++
+COMPILERFLAGS = -O3
+INCLUDE = -I../../Dist -I/usr/include/asm
+VGALIBRARIES = -lfreeimage -lvga
+GTKLIBRARIES = -lfreeimage -lgtk -lgdk
+GTKINCLUDE = -I/usr/lib/glib/include
+CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
+
+
+
+all: default
+
+default: linux-svgalib linux-gtk
+
+linux-svgalib: linux-svgalib.c
+ $(CC) $(CFLAGS) $< -o $@ $(VGALIBRARIES)
+ strip $@
+
+linux-gtk: linux-gtk.c
+ $(CC) $(CFLAGS) $< -o $@ $(GTKLIBRARIES) $(GTKINCLUDE)
+ strip $@
+
+clean:
+ rm -f core linux-svgalib linux-gtk
diff --git a/Examples/Linux/linux-gtk.c b/Examples/Linux/linux-gtk.c
new file mode 100644
index 0000000..d7296ac
--- /dev/null
+++ b/Examples/Linux/linux-gtk.c
@@ -0,0 +1,97 @@
+#include <gtk/gtk.h>
+#include "FreeImage.h"
+
+void destroy(GtkWidget * widget, gpointer data) {
+ gtk_main_quit();
+}
+
+int main(int argc, char *argv[])
+{
+ GtkWidget *window, *imagebox;
+ GdkVisual *visual;
+ GdkImage *image;
+ FIBITMAP *dib;
+ int y;
+
+ // initialize the FreeImage library
+ FreeImage_Initialise();
+
+ dib = FreeImage_Load(FIF_PNG, "freeimage.png", PNG_DEFAULT);
+
+ gtk_init(&argc, &argv);
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect(GTK_OBJECT(window), "destroy",
+ GTK_SIGNAL_FUNC(destroy), NULL);
+
+ visual = gdk_visual_get_system();
+
+ image = gdk_image_new(GDK_IMAGE_NORMAL,visual,
+ FreeImage_GetWidth(dib),FreeImage_GetHeight(dib));
+
+ g_print("picture: %d bpp\n"
+ "system: %d bpp byteorder: %d\n"
+ " redbits: %d greenbits: %d bluebits: %d\n"
+ "image: %d bpp %d bytes/pixel\n",
+ FreeImage_GetBPP(dib),
+ visual->depth,visual->byte_order,
+ visual->red_prec,visual->green_prec,visual->blue_prec,
+ image->depth,image->bpp );
+
+ if (FreeImage_GetBPP(dib) != (image->bpp << 3)) {
+ FIBITMAP *ptr;
+
+ switch (image->bpp) {
+ case 1:
+ ptr = FreeImage_ConvertTo8Bits(dib);
+ break;
+
+ case 2:
+ if (image->depth == 15) {
+ ptr = FreeImage_ConvertTo16Bits555(dib);
+ } else {
+ ptr = FreeImage_ConvertTo16Bits565(dib);
+ }
+
+ break;
+ case 3:
+ ptr = FreeImage_ConvertTo24Bits(dib);
+ break;
+
+ default:
+ case 4:
+ ptr = FreeImage_ConvertTo32Bits(dib);
+ break;
+ }
+
+ FreeImage_Unload(dib);
+ dib = ptr;
+ }
+
+//makes it upside down :(
+// memcpy(image->mem, FreeImage_GetBits(dib), image->bpl * image->height);
+
+ BYTE *ptr = FreeImage_GetBits(dib);
+
+ for (y = 0; y < image->height; y++) {
+ memcpy(image->mem + (y * image->bpl),
+ ptr + ((image->height - y - 1) * image->bpl),
+ image->bpl);
+ }
+
+ FreeImage_Unload(dib);
+
+ imagebox = gtk_image_new(image, NULL);
+ gtk_container_add(GTK_CONTAINER(window), imagebox);
+
+ gtk_widget_show(imagebox);
+ gtk_widget_show(window);
+
+ gtk_main();
+
+ // release the FreeImage library
+ FreeImage_DeInitialise();
+
+ return 0;
+}
diff --git a/Examples/Linux/linux-svgalib.c b/Examples/Linux/linux-svgalib.c
new file mode 100644
index 0000000..f0eb68c
--- /dev/null
+++ b/Examples/Linux/linux-svgalib.c
@@ -0,0 +1,96 @@
+#include <vga.h>
+#include "FreeImage.h"
+
+int main(void)
+{
+ FIBITMAP *dib,*ptr;
+ vga_modeinfo *inf;
+ int length,height,bpp,y;
+
+ // initialize the FreeImage library
+ FreeImage_Initialise();
+
+ dib = FreeImage_Load(FIF_PNG, "freeimage.png", PNG_DEFAULT);
+
+ vga_init();
+ vga_setmode(vga_getdefaultmode());
+
+ inf = vga_getmodeinfo(vga_getcurrentmode());
+
+ switch(inf->colors) {
+ default:
+ printf("Must be at least 256 color mode!\n");
+ return;
+
+ case 1 << 8:
+ bpp = 8;
+ break;
+
+ case 1 << 15:
+ bpp = 15;
+ break;
+
+ case 1 << 16:
+ bpp = 16;
+ break;
+
+ case 1 << 24:
+ if( inf->bytesperpixel == 3 ) {
+ bpp = 24;
+ } else {
+ bpp = 32;
+ }
+ break;
+ }
+
+ if(FreeImage_GetBPP(dib) != bpp) {
+ switch(bpp) {
+ case 8:
+ ptr = FreeImage_ConvertTo8Bits(dib);
+ break;
+
+ case 15:
+ ptr = FreeImage_ConvertTo16Bits555(dib);
+ break;
+
+ case 16:
+ ptr = FreeImage_ConvertTo16Bits565(dib);
+ break;
+
+ case 24:
+ ptr = FreeImage_ConvertTo24Bits(dib);
+ break;
+
+ default:
+ case 32:
+ ptr = FreeImage_ConvertTo32Bits(dib);
+ break;
+ }
+
+ FreeImage_Unload(dib);
+ dib = ptr;
+ }
+
+ length = FreeImage_GetWidth(dib);
+ if( inf->width < length ) {
+ length = inf->width;
+ }
+ height = FreeImage_GetHeight(dib);
+ if( inf->height < height ) {
+ height = inf->height;
+ }
+
+ for(y = 0; y < height; y++) {
+ vga_drawscansegment(FreeImage_GetScanLine(dib, y), 0, y, length);
+ }
+
+ FreeImage_Unload(dib);
+
+ vga_getch();
+ vga_setmode(TEXT);
+
+ // release the FreeImage library
+ FreeImage_DeInitialise();
+
+ return 0;
+}
diff --git a/Examples/OpenGL/TextureManager/TextureManager.cpp b/Examples/OpenGL/TextureManager/TextureManager.cpp
new file mode 100644
index 0000000..cbd69a0
--- /dev/null
+++ b/Examples/OpenGL/TextureManager/TextureManager.cpp
@@ -0,0 +1,145 @@
+//**********************************************
+//Singleton Texture Manager class
+//Written by Ben English
+//benjamin.english@oit.edu
+//
+//For use with OpenGL and the FreeImage library
+//**********************************************
+
+#include "TextureManager.h"
+
+TextureManager* TextureManager::m_inst(0);
+
+TextureManager* TextureManager::Inst()
+{
+ if(!m_inst)
+ m_inst = new TextureManager();
+
+ return m_inst;
+}
+
+TextureManager::TextureManager()
+{
+ // call this ONLY when linking with FreeImage as a static library
+ #ifdef FREEIMAGE_LIB
+ FreeImage_Initialise();
+ #endif
+}
+
+//these should never be called
+//TextureManager::TextureManager(const TextureManager& tm){}
+//TextureManager& TextureManager::operator=(const TextureManager& tm){}
+
+TextureManager::~TextureManager()
+{
+ // call this ONLY when linking with FreeImage as a static library
+ #ifdef FREEIMAGE_LIB
+ FreeImage_DeInitialise();
+ #endif
+
+ UnloadAllTextures();
+ m_inst = 0;
+}
+
+bool TextureManager::LoadTexture(const char* filename, const unsigned int texID, GLenum image_format, GLint internal_format, GLint level, GLint border)
+{
+ //image format
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ //pointer to the image, once loaded
+ FIBITMAP *dib(0);
+ //pointer to the image data
+ BYTE* bits(0);
+ //image width and height
+ unsigned int width(0), height(0);
+ //OpenGL's image ID to map to
+ GLuint gl_texID;
+
+ //check the file signature and deduce its format
+ fif = FreeImage_GetFileType(filename, 0);
+ //if still unknown, try to guess the file format from the file extension
+ if(fif == FIF_UNKNOWN)
+ fif = FreeImage_GetFIFFromFilename(filename);
+ //if still unkown, return failure
+ if(fif == FIF_UNKNOWN)
+ return false;
+
+ //check that the plugin has reading capabilities and load the file
+ if(FreeImage_FIFSupportsReading(fif))
+ dib = FreeImage_Load(fif, filename);
+ //if the image failed to load, return failure
+ if(!dib)
+ return false;
+
+ //retrieve the image data
+ bits = FreeImage_GetBits(dib);
+ //get the image width and height
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ //if this somehow one of these failed (they shouldn't), return failure
+ if((bits == 0) || (width == 0) || (height == 0))
+ return false;
+
+ //if this texture ID is in use, unload the current texture
+ if(m_texID.find(texID) != m_texID.end())
+ glDeleteTextures(1, &(m_texID[texID]));
+
+ //generate an OpenGL texture ID for this texture
+ glGenTextures(1, &gl_texID);
+ //store the texture ID mapping
+ m_texID[texID] = gl_texID;
+ //bind to the new texture ID
+ glBindTexture(GL_TEXTURE_2D, gl_texID);
+ //store the texture data for OpenGL use
+ glTexImage2D(GL_TEXTURE_2D, level, internal_format, width, height,
+ border, image_format, GL_UNSIGNED_BYTE, bits);
+
+ //Free FreeImage's copy of the data
+ FreeImage_Unload(dib);
+
+ //return success
+ return true;
+}
+
+bool TextureManager::UnloadTexture(const unsigned int texID)
+{
+ bool result(true);
+ //if this texture ID mapped, unload it's texture, and remove it from the map
+ if(m_texID.find(texID) != m_texID.end())
+ {
+ glDeleteTextures(1, &(m_texID[texID]));
+ m_texID.erase(texID);
+ }
+ //otherwise, unload failed
+ else
+ {
+ result = false;
+ }
+
+ return result;
+}
+
+bool TextureManager::BindTexture(const unsigned int texID)
+{
+ bool result(true);
+ //if this texture ID mapped, bind it's texture as current
+ if(m_texID.find(texID) != m_texID.end())
+ glBindTexture(GL_TEXTURE_2D, m_texID[texID]);
+ //otherwise, binding failed
+ else
+ result = false;
+
+ return result;
+}
+
+void TextureManager::UnloadAllTextures()
+{
+ //start at the begginning of the texture map
+ std::map<unsigned int, GLuint>::iterator i = m_texID.begin();
+
+ //Unload the textures untill the end of the texture map is found
+ while(i != m_texID.end())
+ UnloadTexture(i->first);
+
+ //clear the texture map
+ m_texID.clear();
+} \ No newline at end of file
diff --git a/Examples/OpenGL/TextureManager/TextureManager.h b/Examples/OpenGL/TextureManager/TextureManager.h
new file mode 100644
index 0000000..0afa4b1
--- /dev/null
+++ b/Examples/OpenGL/TextureManager/TextureManager.h
@@ -0,0 +1,51 @@
+//**********************************************
+//Singleton Texture Manager class
+//Written by Ben English
+//benjamin.english@oit.edu
+//
+//For use with OpenGL and the FreeImage library
+//**********************************************
+
+#ifndef TextureManager_H
+#define TextureManager_H
+
+#include <windows.h>
+#include <gl/gl.h>
+#include "FreeImage.h"
+#include <map>
+
+class TextureManager
+{
+public:
+ static TextureManager* Inst();
+ virtual ~TextureManager();
+
+ //load a texture an make it the current texture
+ //if texID is already in use, it will be unloaded and replaced with this texture
+ bool LoadTexture(const char* filename, //where to load the file from
+ const unsigned int texID, //arbitrary id you will reference the texture by
+ //does not have to be generated with glGenTextures
+ GLenum image_format = GL_RGB, //format the image is in
+ GLint internal_format = GL_RGB, //format to store the image in
+ GLint level = 0, //mipmapping level
+ GLint border = 0); //border size
+
+ //free the memory for a texture
+ bool UnloadTexture(const unsigned int texID);
+
+ //set the current texture
+ bool BindTexture(const unsigned int texID);
+
+ //free all texture memory
+ void UnloadAllTextures();
+
+protected:
+ TextureManager();
+ TextureManager(const TextureManager& tm);
+ TextureManager& operator=(const TextureManager& tm);
+
+ static TextureManager* m_inst;
+ std::map<unsigned int, GLuint> m_texID;
+};
+
+#endif \ No newline at end of file
diff --git a/Examples/OpenGL/TextureManager/readme.txt b/Examples/OpenGL/TextureManager/readme.txt
new file mode 100644
index 0000000..9cbd7f7
--- /dev/null
+++ b/Examples/OpenGL/TextureManager/readme.txt
@@ -0,0 +1,31 @@
+Hello everyone, this is my 2D texture manager class for OpenGL using the FreeImage Library.
+
+Requirements:
+--------------------
+OpenGL
+STL map class
+FreeImage (included)
+
+
+Usage
+--------------------
+To load a texture, simply call the LoadTexture function:
+
+TextureManager::Inst()->LoadTexture("img\\bg.jpg", BACKGROUND_IMAGE_ID);
+
+This also binds the loaded texture as the current texture, so after calling it you may make any calls to glTexParameter you may need to specify the properties of the texture.
+
+When you are rendering, just call the TextureManager's BindImage function instead of glBindImage:
+
+TextureManager::Inst()->BindImage(BACKGROUND_IMAGE_ID);
+
+and then do your rendering as normal.
+--------------------
+
+
+Feel free to distribute this as you like, but mind the FreeImage licence included in license-fi.txt, and please don't take credit for my code. If you modify it, be sure to mention me (Ben English) somewhere.
+
+Please send any comments or suggestions to me at benjamin.english@oit.edu
+
+
+Thanks to Herve Drolon for the FreeImage library, I've found it to be very useful! \ No newline at end of file
diff --git a/Examples/Plugin/PluginCradle.cpp b/Examples/Plugin/PluginCradle.cpp
new file mode 100644
index 0000000..5dcdbd0
--- /dev/null
+++ b/Examples/Plugin/PluginCradle.cpp
@@ -0,0 +1,253 @@
+// ==========================================================
+// Loader/Saver Plugin Cradle
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include <windows.h>
+#include <stdlib.h>
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH :
+ case DLL_PROCESS_DETACH :
+ case DLL_THREAD_ATTACH :
+ case DLL_THREAD_DETACH :
+ break;
+ }
+
+ return TRUE;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+/**
+ Returns the format string for the plugin. Each plugin,
+ both internal in the DLL and external in a .fip file, must have
+ a unique format string to be addressable.
+*/
+
+static const char * DLL_CALLCONV
+Format() {
+ return "CRADLE";
+}
+
+/**
+ Returns a description string for the plugin. Though a
+ description is not necessary per-se,
+ it is advised to return an unique string in order to tell the
+ user what type of bitmaps this plugin will read and/or write.
+*/
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Here comes the description for your image loader/saver";
+}
+
+/**
+ Returns a comma separated list of file extensions indicating
+ what files this plugin can open. no spaces or whatsoever are allowed.
+ The list, being used by FreeImage_GetFIFFromFilename, is usually
+ used as a last resort in finding the type of the bitmap we
+ are dealing with. Best is to check the first few bytes on
+ the low-level bits level first and compare them with a known
+ signature . If this fails, FreeImage_GetFIFFromFilename can be
+ used.
+*/
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "ext1,ext2";
+}
+
+/**
+ RegExpr is only needed for the Qt wrapper
+ It allows the Qt mechanism for loading bitmaps to identify the bitmap
+*/
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+/**
+ Returns a MIME content type string for that format (MIME stands
+ for Multipurpose Internet Mail Extension).
+*/
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/myformat";
+}
+
+/**
+ FreeImage's internal way of seeing if a bitmap is of the desired type.
+ When the type of a bitmap is to be retrieved, FreeImage runs Validate
+ for each registered plugin until one returns true. If a plugin doesn't
+ have a validate function, a return value of false is assumed.
+
+ You can always force to use a particular plugin by directly specifying
+ it on the command line, but this can result in a dead DLL if the plugin
+ was not made for the bitmap.
+*/
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO &io, fi_handle handle) {
+ return FALSE;
+}
+
+/**
+ SupportsExportDepth is the first in a possible range of new plugin functions
+ to ask specific information to that plugin. This function returns TRUE if it
+ can save a bitmap in the required bitdepth. If it can't the bitmap has to be
+ converted by the user or another plugin has to be chosen.
+*/
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+/**
+ Returns TRUE if the plugin belonging to the given FREE_IMAGE_FORMAT can save a
+ bitmap in the desired data type, returns FALSE otherwise. Currently, TIFF is the only plugin
+ able to save all non-standard images. The PNG plugin is able to save unsigned 16-bit
+ images.
+*/
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+/**
+ SupportsICCProfiles informs FreeImage that a plugin supports ICC profiles.
+ This function returns TRUE if the plugin can load and save a profile.
+ ICC profile information is accessed via freeimage->get_icc_profile_proc(dib)
+*/
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return FALSE;
+}
+
+
+// ----------------------------------------------------------
+
+/**
+ Loads a bitmap into memory. On entry it is assumed that
+ the bitmap to be loaded is of the correct type. If the bitmap
+ is of an incorrect type, the plugin might not gracefully fail but
+ crash or enter an endless loop. It is also assumed that all
+ the bitmap data is available at one time. If the bitmap is not complete,
+ for example because it is being downloaded while loaded, the plugin
+ might also not gracefully fail.
+
+ The Load function has the following parameters:
+
+ The first parameter (FreeImageIO *io) is a structure providing
+ function pointers in order to make use of FreeImage's IO redirection. Using
+ FreeImage's file i/o functions instead of standard ones it is garantueed
+ that all bitmap types, both current and future ones, can be loaded from
+ memory, file cabinets, the internet and more. The second parameter (fi_handle handle)
+ is a companion of FreeImageIO and can be best compared with the standard FILE* type,
+ in a generalized form.
+
+ The third parameter (int page) indicates wether we will be loading a certain page
+ in the bitmap or if we will load the default one. This parameter is only used if
+ the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series
+ of images or pages. If the plugin does support multi-paging, the page parameter
+ can contain either a number higher or equal to 0 to load a certain page, or -1 to
+ load the default page. If the plugin does not support multi-paging,
+ the page parameter is always -1.
+
+ The fourth parameter (int flags) manipulates the load function to load a bitmap
+ in a certain way. Every plugin has a different flag parameter with different meanings.
+
+ The last parameter (void *data) can contain a special data block used when
+ the file is read multi-paged. Because not every plugin supports multi-paging
+ not every plugin will use the data parameter and it will be set to NULL.However,
+ when the plugin does support multi-paging the parameter contains a pointer to a
+ block of data allocated by the Open function.
+*/
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+/**
+ Initialises the plugin. The first parameter (Plugin *plugin)
+ contains a pointer to a pre-allocated Plugin structure
+ wherein pointers to the available plugin functions
+ has to be stored. The second parameter (int format_id) is an identification
+ number that the plugin may use to show plugin specific warning messages
+ or other information to the user. The plugin number
+ is generated by FreeImage and can differ everytime the plugin is
+ initialised.
+
+ If you want to create your own plugin you have to take some
+ rules into account. Plugin functions have to be compiled
+ __stdcall using the multithreaded c runtime libraries. Throwing
+ exceptions in plugin functions is allowed, as long as those exceptions
+ are being caught inside the same plugin. It is forbidden for a plugin
+ function to directly call FreeImage functions or to allocate memory
+ and pass it to the main DLL. Exception to this rule is the special file data
+ block that may be allocated the Open function. Allocating a FIBITMAP inside a
+ plugin can be using the function allocate_proc in the FreeImage structure,
+ which will allocate the memory using the DLL's c runtime library.
+*/
+
+void DLL_CALLCONV
+Init(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Examples/Plugin/PluginCradle.h b/Examples/Plugin/PluginCradle.h
new file mode 100644
index 0000000..b049efb
--- /dev/null
+++ b/Examples/Plugin/PluginCradle.h
@@ -0,0 +1,45 @@
+// ==========================================================
+// JBIG Plugin
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef PLUGINCRADLE_H
+#define PLUGINCRADLE_H
+
+#ifdef PLUGINCRADLE_EXPORTS
+#define PLUGIN_API __declspec(dllexport)
+#else
+#define PLUGIN_API __declspec(dllimport)
+#endif
+
+// ----------------------------------------------------------
+
+struct Plugin;
+
+// ----------------------------------------------------------
+
+#define DLL_CALLCONV __stdcall
+
+// ----------------------------------------------------------
+
+extern "C" {
+ PLUGIN_API void DLL_CALLCONV Init(Plugin *plugin, int format_id);
+}
+
+#endif
diff --git a/FreeImage.2003.sln b/FreeImage.2003.sln
new file mode 100644
index 0000000..0c34340
--- /dev/null
+++ b/FreeImage.2003.sln
@@ -0,0 +1,118 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImage", "FreeImage.2003.vcproj", "{B39ED2B3-D53A-4077-B957-930979A3577D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937} = {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF} = {17A4874B-0606-4687-90B6-F91F8CB3B8AF}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52} = {33134F61-C1AD-4B6F-9CEA-503A9F140C52}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImageLib", "SOURCE\FreeImageLib\FreeImageLib.2003.vcproj", "{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937} = {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF} = {17A4874B-0606-4687-90B6-F91F8CB3B8AF}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52} = {33134F61-C1AD-4B6F-9CEA-503A9F140C52}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImagePlus", "Wrapper\FreeImagePlus\FreeImagePlus.2003.vcproj", "{12AAE1F1-E982-49D3-B24E-63FD677FCE77}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B39ED2B3-D53A-4077-B957-930979A3577D} = {B39ED2B3-D53A-4077-B957-930979A3577D}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibJPEG", "Source\LibJPEG\LibJPEG.2003.vcproj", "{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMNG", "Source\LibMNG\LibMNG.2003.vcproj", "{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibPNG", "Source\LibPNG\LibPNG.2003.vcproj", "{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibTIFF", "Source\LibTIFF\LibTIFF.2003.vcproj", "{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZLib", "Source\ZLib\ZLib.2003.vcproj", "{33134F61-C1AD-4B6F-9CEA-503A9F140C52}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenEXR", "Source\OpenEXR\OpenEXR.2003.vcproj", "{17A4874B-0606-4687-90B6-F91F8CB3B8AF}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibOpenJPEG", "Source\LibOpenJPEG\LibOpenJPEG.2003.vcproj", "{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibRawLite", "Source\LibRawLite\LibRawLite.2003.vcproj", "{1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug.ActiveCfg = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug.Build.0 = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release.ActiveCfg = Release|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release.Build.0 = Release|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Debug.ActiveCfg = Debug|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Release.ActiveCfg = Release|Win32
+ {12AAE1F1-E982-49D3-B24E-63FD677FCE77}.Debug.ActiveCfg = Debug|Win32
+ {12AAE1F1-E982-49D3-B24E-63FD677FCE77}.Debug.Build.0 = Debug|Win32
+ {12AAE1F1-E982-49D3-B24E-63FD677FCE77}.Release.ActiveCfg = Release|Win32
+ {12AAE1F1-E982-49D3-B24E-63FD677FCE77}.Release.Build.0 = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug.ActiveCfg = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug.Build.0 = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release.ActiveCfg = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release.Build.0 = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug.ActiveCfg = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug.Build.0 = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release.ActiveCfg = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release.Build.0 = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug.ActiveCfg = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug.Build.0 = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release.ActiveCfg = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release.Build.0 = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug.ActiveCfg = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug.Build.0 = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release.ActiveCfg = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release.Build.0 = Release|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Debug.ActiveCfg = Debug|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Debug.Build.0 = Debug|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Release.ActiveCfg = Release|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Release.Build.0 = Release|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Debug.ActiveCfg = Debug|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Debug.Build.0 = Debug|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Release.ActiveCfg = Release|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Release.Build.0 = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug.ActiveCfg = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug.Build.0 = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release.ActiveCfg = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release.Build.0 = Release|Win32
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}.Debug.ActiveCfg = Debug|Win32
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}.Debug.Build.0 = Debug|Win32
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}.Release.ActiveCfg = Release|Win32
+ {1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/FreeImage.2003.vcproj b/FreeImage.2003.vcproj
new file mode 100644
index 0000000..c9beacb
--- /dev/null
+++ b/FreeImage.2003.vcproj
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="FreeImage"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;LIBRAW_NODLL;FREEIMAGE_EXPORTS;_SECURE_NO_DEPRECATE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ TreatWChar_tAsBuiltInType="TRUE"
+ PrecompiledHeaderFile=".\Release/FreeImage.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="2"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/FreeImage.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/FreeImage.pdb"
+ ImportLibrary=".\Release/FreeImage.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImage.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImage.dll Dist
+copy Release\FreeImage.lib Dist
+copy Source\FreeImage.h Dist
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;FREEIMAGE_EXPORTS;_SECURE_NO_DEPRECATE;LIBRAW_NODLL"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ TreatWChar_tAsBuiltInType="TRUE"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="2"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="Debug/FreeImaged.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/FreeImaged.pdb"
+ ImportLibrary=".\Debug/FreeImaged.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImage.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImaged.dll Dist
+copy Debug\FreeImaged.lib Dist
+copy Source\FreeImage.h Dist
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="Source\FreeImage\BitmapAccess.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ColorLookup.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImage.cpp">
+ </File>
+ <File
+ RelativePath="FreeImage.rc">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageC.c">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageIO.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\GetType.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MemoryIO.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PixelAccess.cpp">
+ </File>
+ <Filter
+ Name="Plugins"
+ Filter="">
+ <File
+ RelativePath=".\source\FreeImage\J2KHelper.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Plugin.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginBMP.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginCUT.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginDDS.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginEXR.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginG3.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginGIF.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginHDR.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginICO.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginIFF.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJ2K.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJP2.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginJPEG.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginKOALA.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginMNG.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCD.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCX.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginPFM.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginPICT.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNG.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNM.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPSD.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginRAS.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginRAW.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginSGI.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTARGA.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTIFF.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginWBMP.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXBM.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXPM.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PSDParser.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\TIFFLogLuv.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ Filter="">
+ <File
+ RelativePath="Source\FreeImage\Conversion.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_555.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_565.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion24.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion32.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion4.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion8.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionRGBF.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionType.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Halftoning.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoColorConvert.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoDrago03.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\tmoFattal02.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ WarningLevel="4"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoReinhard05.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ToneMapping.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Quantizers"
+ Filter="">
+ <File
+ RelativePath="Source\FreeImage\NNQuantizer.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\WuQuantizer.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ Filter="">
+ <File
+ RelativePath=".\source\DeprecationManager\Deprecated.cpp">
+ </File>
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ Filter="">
+ <File
+ RelativePath="Source\FreeImage\CacheFile.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MultiPage.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ZLibInterface.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ Filter="">
+ <File
+ RelativePath="Source\Metadata\Exif.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\IPTC.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagConversion.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagLib.cpp">
+ </File>
+ <File
+ RelativePath="Source\Metadata\XTIFF.cpp">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="Source\CacheFile.h">
+ </File>
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.h">
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.h">
+ </File>
+ <File
+ RelativePath="Source\FreeImage.h">
+ </File>
+ <File
+ RelativePath="Source\FreeImageIO.h">
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.h">
+ </File>
+ <File
+ RelativePath="Source\Plugin.h">
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PSDParser.h">
+ </File>
+ <File
+ RelativePath="Source\Quantizers.h">
+ </File>
+ <File
+ RelativePath="Source\ToneMapping.h">
+ </File>
+ <File
+ RelativePath="Source\Utilities.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ Filter="">
+ <File
+ RelativePath=".\source\FreeImageToolkit\Background.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\BSplineRotate.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Channels.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\ClassicRotate.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Colors.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\CopyPaste.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Display.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Flip.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\JPEGTransform.cpp">
+ </File>
+ <File
+ RelativePath=".\source\FreeImageToolkit\MultigridPoissonSolver.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Rescale.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.cpp">
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.h">
+ </File>
+ </Filter>
+ <File
+ RelativePath="Todo.txt">
+ </File>
+ <File
+ RelativePath="Whatsnew.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/FreeImage.2005.sln b/FreeImage.2005.sln
new file mode 100644
index 0000000..8de2196
--- /dev/null
+++ b/FreeImage.2005.sln
@@ -0,0 +1,103 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImage", "FreeImage.2005.vcproj", "{B39ED2B3-D53A-4077-B957-930979A3577D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF} = {17A4874B-0606-4687-90B6-F91F8CB3B8AF}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52} = {33134F61-C1AD-4B6F-9CEA-503A9F140C52}
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A} = {07F662C1-1323-42AB-B6AF-FBFD34A7437A}
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImageLib", "Source\FreeImageLib\FreeImageLib.2005.vcproj", "{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF} = {17A4874B-0606-4687-90B6-F91F8CB3B8AF}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52} = {33134F61-C1AD-4B6F-9CEA-503A9F140C52}
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A} = {07F662C1-1323-42AB-B6AF-FBFD34A7437A}
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImagePlus", "Wrapper\FreeImagePlus\FreeImagePlus.2005.vcproj", "{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B39ED2B3-D53A-4077-B957-930979A3577D} = {B39ED2B3-D53A-4077-B957-930979A3577D}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibJPEG", "Source\LibJPEG\LibJPEG.2005.vcproj", "{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMNG", "Source\LibMNG\LibMNG.2005.vcproj", "{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibPNG", "Source\LibPNG\LibPNG.2005.vcproj", "{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibTIFF", "Source\LibTIFF\LibTIFF.2005.vcproj", "{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZLib", "Source\ZLib\ZLib.2005.vcproj", "{33134F61-C1AD-4B6F-9CEA-503A9F140C52}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenEXR", "Source\OpenEXR\OpenEXR.2005.vcproj", "{17A4874B-0606-4687-90B6-F91F8CB3B8AF}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibOpenJPEG", "Source\LibOpenJPEG\LibOpenJPEG.2005.vcproj", "{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibRawLite", "Source\LibRawLite\LibRawLite.2005.vcproj", "{07F662C1-1323-42AB-B6AF-FBFD34A7437A}"
+ ProjectSection(ProjectDependencies) = postProject
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug|Win32.Build.0 = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release|Win32.ActiveCfg = Release|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release|Win32.Build.0 = Release|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Release|Win32.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.Build.0 = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.Build.0 = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.Build.0 = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.ActiveCfg = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.Build.0 = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.Build.0 = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.ActiveCfg = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.Build.0 = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.Build.0 = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.ActiveCfg = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.Build.0 = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.Build.0 = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.ActiveCfg = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.Build.0 = Release|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Debug|Win32.ActiveCfg = Debug|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Debug|Win32.Build.0 = Debug|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Release|Win32.ActiveCfg = Release|Win32
+ {33134F61-C1AD-4B6F-9CEA-503A9F140C52}.Release|Win32.Build.0 = Release|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Debug|Win32.ActiveCfg = Debug|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Debug|Win32.Build.0 = Debug|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Release|Win32.ActiveCfg = Release|Win32
+ {17A4874B-0606-4687-90B6-F91F8CB3B8AF}.Release|Win32.Build.0 = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.Build.0 = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.ActiveCfg = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.Build.0 = Release|Win32
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A}.Debug|Win32.ActiveCfg = Debug|Win32
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A}.Debug|Win32.Build.0 = Debug|Win32
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A}.Release|Win32.ActiveCfg = Release|Win32
+ {07F662C1-1323-42AB-B6AF-FBFD34A7437A}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/FreeImage.2005.vcproj b/FreeImage.2005.vcproj
new file mode 100644
index 0000000..d05f3c9
--- /dev/null
+++ b/FreeImage.2005.vcproj
@@ -0,0 +1,645 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="FreeImage"
+ ProjectGUID="{B39ED2B3-D53A-4077-B957-930979A3577D}"
+ RootNamespace="FreeImage"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImage.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;LIBRAW_NODLL"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ PrecompiledHeaderFile=".\Release/FreeImage.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/FreeImage.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Release/FreeImage.pdb"
+ ImportLibrary=".\Release/FreeImage.lib"
+ TargetMachine="1"
+ Profile="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImage.dll Dist&#x0D;&#x0A;copy Release\FreeImage.lib Dist&#x0D;&#x0A;copy Source\FreeImage.h Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImage.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_DEPRECATE;LIBRAW_NODLL"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/FreeImage.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="Debug/FreeImaged.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/FreeImaged.pdb"
+ ImportLibrary=".\Debug/FreeImaged.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImaged.dll Dist&#x0D;&#x0A;copy Debug\FreeImaged.lib Dist&#x0D;&#x0A;copy Source\FreeImage.h Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="Source\FreeImage\BitmapAccess.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ColorLookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="FreeImage.rc"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageC.c"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\GetType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PixelAccess.cpp"
+ >
+ </File>
+ <Filter
+ Name="Plugins"
+ >
+ <File
+ RelativePath=".\source\FreeImage\J2KHelper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Plugin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginCUT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginDDS.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginEXR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginG3.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginGIF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginHDR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginICO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJ2K.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJP2.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginKOALA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginMNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCX.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginPFM.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginPICT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPSD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginRAS.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginRAW.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginSGI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTARGA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginWBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXBM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXPM.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PSDParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\TIFFLogLuv.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ >
+ <File
+ RelativePath="Source\FreeImage\Conversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_555.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_565.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion24.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion32.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion4.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion8.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionRGBF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Halftoning.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoColorConvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoDrago03.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\tmoFattal02.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoReinhard05.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ToneMapping.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Quantizers"
+ >
+ <File
+ RelativePath="Source\FreeImage\NNQuantizer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\WuQuantizer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ >
+ <File
+ RelativePath=".\source\DeprecationManager\Deprecated.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ >
+ <File
+ RelativePath="Source\FreeImage\CacheFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ZLibInterface.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ >
+ <File
+ RelativePath="Source\Metadata\Exif.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\IPTC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagConversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagLib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\XTIFF.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="Source\CacheFile.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageIO.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Plugin.h"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PSDParser.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Quantizers.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\ToneMapping.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Utilities.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ >
+ <File
+ RelativePath=".\source\FreeImageToolkit\Background.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\BSplineRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Channels.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\ClassicRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Colors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\CopyPaste.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Display.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Flip.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\JPEGTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImageToolkit\MultigridPoissonSolver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Rescale.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="Todo.txt"
+ >
+ </File>
+ <File
+ RelativePath="Whatsnew.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/FreeImage.2008.sln b/FreeImage.2008.sln
new file mode 100644
index 0000000..39db41d
--- /dev/null
+++ b/FreeImage.2008.sln
@@ -0,0 +1,76 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImage", "FreeImage.2008.vcproj", "{B39ED2B3-D53A-4077-B957-930979A3577D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImageLib", "Source\FreeImageLib\FreeImageLib.2008.vcproj", "{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImagePlus", "Wrapper\FreeImagePlus\FreeImagePlus.2008.vcproj", "{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ ProjectSection(ProjectDependencies) = postProject
+ {B39ED2B3-D53A-4077-B957-930979A3577D} = {B39ED2B3-D53A-4077-B957-930979A3577D}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibJPEG", "Source\LibJPEG\LibJPEG.2008.vcproj", "{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMNG", "Source\LibMNG\LibMNG.2008.vcproj", "{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibPNG", "Source\LibPNG\LibPNG.2008.vcproj", "{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibTIFF", "Source\LibTIFF\LibTIFF.2008.vcproj", "{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibOpenJPEG", "Source\LibOpenJPEG\LibOpenJPEG.2008.vcproj", "{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Debug|Win32.Build.0 = Debug|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release|Win32.ActiveCfg = Release|Win32
+ {B39ED2B3-D53A-4077-B957-930979A3577D}.Release|Win32.Build.0 = Release|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Release|Win32.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.Build.0 = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.Build.0 = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.Build.0 = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.ActiveCfg = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.Build.0 = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.Build.0 = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.ActiveCfg = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.Build.0 = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.Build.0 = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.ActiveCfg = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.Build.0 = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.Build.0 = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.ActiveCfg = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.Build.0 = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.Build.0 = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.ActiveCfg = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/FreeImage.2008.vcproj b/FreeImage.2008.vcproj
new file mode 100644
index 0000000..fc8b89d
--- /dev/null
+++ b/FreeImage.2008.vcproj
@@ -0,0 +1,628 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="FreeImage"
+ ProjectGUID="{B39ED2B3-D53A-4077-B957-930979A3577D}"
+ RootNamespace="FreeImage"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImage.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+
+ BufferSecurityCheck="false"
+
+
+ PrecompiledHeaderFile=".\Release/FreeImage.pch"
+
+
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile=".\Release/FreeImage.dll"
+
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Release/FreeImage.pdb"
+
+
+ ImportLibrary=".\Release/FreeImage.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImage.dll Dist&#x0D;&#x0A;copy Release\FreeImage.lib Dist&#x0D;&#x0A;copy Source\FreeImage.h Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImage.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ AdditionalIncludeDirectories="Source;Source\ZLib;Source\DeprecationManager;Source\OpenEXR\Half;Source\OpenEXR\Iex;Source\OpenEXR\IlmImf;Source\OpenEXR\Imath;Source\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPJ_STATIC;FREEIMAGE_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+
+
+
+ PrecompiledHeaderFile=".\Debug/FreeImage.pch"
+
+
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="Debug/FreeImaged.dll"
+
+ SuppressStartupBanner="true"
+
+ ProgramDatabaseFile=".\Debug/FreeImaged.pdb"
+
+
+ ImportLibrary=".\Debug/FreeImaged.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImaged.dll Dist&#x0D;&#x0A;copy Debug\FreeImaged.lib Dist&#x0D;&#x0A;copy Source\FreeImage.h Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="Source\FreeImage\BitmapAccess.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ColorLookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="FreeImage.rc"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageC.c"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\FreeImageIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\GetType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PixelAccess.cpp"
+ >
+ </File>
+ <Filter
+ Name="Plugins"
+ >
+ <File
+ RelativePath=".\source\FreeImage\J2KHelper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Plugin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginCUT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginDDS.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginEXR.cpp"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginG3.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginGIF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginHDR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginICO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJ2K.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\PluginJP2.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginKOALA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginMNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPCX.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPNM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginPSD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginRAS.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginSGI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTARGA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginTIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginWBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXBM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\PluginXPM.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\TIFFLogLuv.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ >
+ <File
+ RelativePath="Source\FreeImage\Conversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_555.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion16_565.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion24.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion32.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion4.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Conversion8.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionRGBF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ConversionType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\Halftoning.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoColorConvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoDrago03.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImage\tmoFattal02.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="Source\FreeImage\tmoReinhard05.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ToneMapping.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Quantizers"
+ >
+ <File
+ RelativePath="Source\FreeImage\NNQuantizer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\WuQuantizer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ >
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ >
+ <File
+ RelativePath="Source\FreeImage\CacheFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\MultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage\ZLibInterface.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ >
+ <File
+ RelativePath="Source\Metadata\Exif.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\IPTC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagConversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\TagLib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\XTIFF.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="Source\CacheFile.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\DeprecationManager\DeprecationMgr.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FIRational.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageIO.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Metadata\FreeImageTag.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Quantizers.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\ToneMapping.h"
+ >
+ </File>
+ <File
+ RelativePath="Source\Utilities.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ >
+ <File
+ RelativePath="Source\FreeImageToolkit\BSplineRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Channels.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\ClassicRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Colors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\CopyPaste.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Display.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Flip.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\JPEGTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\source\FreeImageToolkit\MultigridPoissonSolver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Rescale.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="Source\FreeImageToolkit\Resize.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="Whatsnew.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/FreeImage.rc b/FreeImage.rc
new file mode 100644
index 0000000..a2b15ee
--- /dev/null
+++ b/FreeImage.rc
@@ -0,0 +1,95 @@
+//Microsoft Developer Studio generated resource script.
+//
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,13,0,0
+ PRODUCTVERSION 3,13,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e2"
+ BEGIN
+ VALUE "Comments", "FreeImage is an Open Source library project for developers who would like to support popular graphics image formats like PNG, BMP, JPEG, TIFF and others as needed by today's multimedia applications.\0"
+ VALUE "CompanyName", "FreeImage\0"
+ VALUE "FileDescription", "FreeImage library\0"
+ VALUE "FileVersion", "3, 13, 0, 0\0"
+ VALUE "InternalName", "FreeImage\0"
+ VALUE "LegalCopyright", "Copyright © 2003-2009 by FreeImage\0"
+ VALUE "LegalTrademarks", "See http://freeimage.sourceforge.net\0"
+ VALUE "OriginalFilename", "FreeImage.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "FreeImage\0"
+ VALUE "ProductVersion", "3, 13, 0, 0\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1250
+ END
+END
+
+#endif // !_MAC
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/FreeImage.xcodeproj/project.pbxproj b/FreeImage.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..1757875
--- /dev/null
+++ b/FreeImage.xcodeproj/project.pbxproj
@@ -0,0 +1,1016 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D7066BBC0E2BD03600ED8BBE /* BitmapAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B840E2BD03600ED8BBE /* BitmapAccess.cpp */; };
+ D7066BBD0E2BD03600ED8BBE /* CacheFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B850E2BD03600ED8BBE /* CacheFile.cpp */; };
+ D7066BBE0E2BD03600ED8BBE /* ColorLookup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B860E2BD03600ED8BBE /* ColorLookup.cpp */; };
+ D7066BBF0E2BD03600ED8BBE /* Conversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B870E2BD03600ED8BBE /* Conversion.cpp */; };
+ D7066BC00E2BD03600ED8BBE /* Conversion4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B880E2BD03600ED8BBE /* Conversion4.cpp */; };
+ D7066BC10E2BD03600ED8BBE /* Conversion8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B890E2BD03600ED8BBE /* Conversion8.cpp */; };
+ D7066BC20E2BD03600ED8BBE /* Conversion16_555.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8A0E2BD03600ED8BBE /* Conversion16_555.cpp */; };
+ D7066BC30E2BD03600ED8BBE /* Conversion16_565.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8B0E2BD03600ED8BBE /* Conversion16_565.cpp */; };
+ D7066BC40E2BD03600ED8BBE /* Conversion24.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8C0E2BD03600ED8BBE /* Conversion24.cpp */; };
+ D7066BC50E2BD03600ED8BBE /* Conversion32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8D0E2BD03600ED8BBE /* Conversion32.cpp */; };
+ D7066BC60E2BD03600ED8BBE /* ConversionRGBF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8E0E2BD03600ED8BBE /* ConversionRGBF.cpp */; };
+ D7066BC70E2BD03600ED8BBE /* ConversionType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B8F0E2BD03600ED8BBE /* ConversionType.cpp */; };
+ D7066BC80E2BD03600ED8BBE /* FreeImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B900E2BD03600ED8BBE /* FreeImage.cpp */; };
+ D7066BC90E2BD03600ED8BBE /* FreeImageC.c in Sources */ = {isa = PBXBuildFile; fileRef = D7066B910E2BD03600ED8BBE /* FreeImageC.c */; };
+ D7066BCA0E2BD03600ED8BBE /* FreeImageIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B920E2BD03600ED8BBE /* FreeImageIO.cpp */; };
+ D7066BCB0E2BD03600ED8BBE /* GetType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B930E2BD03600ED8BBE /* GetType.cpp */; };
+ D7066BCC0E2BD03600ED8BBE /* Halftoning.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B940E2BD03600ED8BBE /* Halftoning.cpp */; };
+ D7066BCD0E2BD03600ED8BBE /* J2KHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B950E2BD03600ED8BBE /* J2KHelper.cpp */; };
+ D7066BCE0E2BD03600ED8BBE /* MemoryIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B960E2BD03600ED8BBE /* MemoryIO.cpp */; };
+ D7066BCF0E2BD03600ED8BBE /* MultiPage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B970E2BD03600ED8BBE /* MultiPage.cpp */; };
+ D7066BD00E2BD03600ED8BBE /* NNQuantizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B980E2BD03600ED8BBE /* NNQuantizer.cpp */; };
+ D7066BD10E2BD03600ED8BBE /* PixelAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B990E2BD03600ED8BBE /* PixelAccess.cpp */; };
+ D7066BD20E2BD03600ED8BBE /* Plugin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B9A0E2BD03600ED8BBE /* Plugin.cpp */; };
+ D7066BD30E2BD03600ED8BBE /* PluginBMP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B9B0E2BD03600ED8BBE /* PluginBMP.cpp */; };
+ D7066BD40E2BD03600ED8BBE /* PluginCUT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B9C0E2BD03600ED8BBE /* PluginCUT.cpp */; };
+ D7066BD50E2BD03600ED8BBE /* PluginDDS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B9D0E2BD03600ED8BBE /* PluginDDS.cpp */; };
+ D7066BD70E2BD03600ED8BBE /* PluginG3.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066B9F0E2BD03600ED8BBE /* PluginG3.cpp */; };
+ D7066BD80E2BD03600ED8BBE /* PluginGIF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA00E2BD03600ED8BBE /* PluginGIF.cpp */; };
+ D7066BD90E2BD03600ED8BBE /* PluginHDR.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA10E2BD03600ED8BBE /* PluginHDR.cpp */; };
+ D7066BDA0E2BD03600ED8BBE /* PluginICO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA20E2BD03600ED8BBE /* PluginICO.cpp */; };
+ D7066BDB0E2BD03600ED8BBE /* PluginIFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA30E2BD03600ED8BBE /* PluginIFF.cpp */; };
+ D7066BDC0E2BD03600ED8BBE /* PluginJ2K.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA40E2BD03600ED8BBE /* PluginJ2K.cpp */; };
+ D7066BDD0E2BD03600ED8BBE /* PluginJP2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA50E2BD03600ED8BBE /* PluginJP2.cpp */; };
+ D7066BDE0E2BD03600ED8BBE /* PluginJPEG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA60E2BD03600ED8BBE /* PluginJPEG.cpp */; };
+ D7066BDF0E2BD03600ED8BBE /* PluginKOALA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA70E2BD03600ED8BBE /* PluginKOALA.cpp */; };
+ D7066BE00E2BD03600ED8BBE /* PluginMNG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA80E2BD03600ED8BBE /* PluginMNG.cpp */; };
+ D7066BE10E2BD03600ED8BBE /* PluginPCD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BA90E2BD03600ED8BBE /* PluginPCD.cpp */; };
+ D7066BE20E2BD03600ED8BBE /* PluginPCX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAA0E2BD03600ED8BBE /* PluginPCX.cpp */; };
+ D7066BE30E2BD03600ED8BBE /* PluginPNG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAB0E2BD03600ED8BBE /* PluginPNG.cpp */; };
+ D7066BE40E2BD03600ED8BBE /* PluginPNM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAC0E2BD03600ED8BBE /* PluginPNM.cpp */; };
+ D7066BE50E2BD03600ED8BBE /* PluginPSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAD0E2BD03600ED8BBE /* PluginPSD.cpp */; };
+ D7066BE60E2BD03600ED8BBE /* PluginRAS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAE0E2BD03600ED8BBE /* PluginRAS.cpp */; };
+ D7066BE70E2BD03600ED8BBE /* PluginSGI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BAF0E2BD03600ED8BBE /* PluginSGI.cpp */; };
+ D7066BE80E2BD03600ED8BBE /* PluginTARGA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB00E2BD03600ED8BBE /* PluginTARGA.cpp */; };
+ D7066BE90E2BD03600ED8BBE /* PluginTIFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB10E2BD03600ED8BBE /* PluginTIFF.cpp */; };
+ D7066BEA0E2BD03600ED8BBE /* PluginWBMP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB20E2BD03600ED8BBE /* PluginWBMP.cpp */; };
+ D7066BEB0E2BD03600ED8BBE /* PluginXBM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB30E2BD03600ED8BBE /* PluginXBM.cpp */; };
+ D7066BEC0E2BD03600ED8BBE /* PluginXPM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB40E2BD03600ED8BBE /* PluginXPM.cpp */; };
+ D7066BED0E2BD03600ED8BBE /* tmoColorConvert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB50E2BD03600ED8BBE /* tmoColorConvert.cpp */; };
+ D7066BEE0E2BD03600ED8BBE /* tmoDrago03.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB60E2BD03600ED8BBE /* tmoDrago03.cpp */; };
+ D7066BEF0E2BD03600ED8BBE /* tmoFattal02.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB70E2BD03600ED8BBE /* tmoFattal02.cpp */; };
+ D7066BF00E2BD03600ED8BBE /* tmoReinhard05.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB80E2BD03600ED8BBE /* tmoReinhard05.cpp */; };
+ D7066BF10E2BD03600ED8BBE /* ToneMapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BB90E2BD03600ED8BBE /* ToneMapping.cpp */; };
+ D7066BF20E2BD03600ED8BBE /* WuQuantizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BBA0E2BD03600ED8BBE /* WuQuantizer.cpp */; };
+ D7066BF30E2BD03600ED8BBE /* ZLibInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BBB0E2BD03600ED8BBE /* ZLibInterface.cpp */; };
+ D7066BF70E2BD04E00ED8BBE /* DeprecationMgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BF50E2BD04E00ED8BBE /* DeprecationMgr.cpp */; };
+ D7066BF80E2BD04E00ED8BBE /* DeprecationMgr.h in Headers */ = {isa = PBXBuildFile; fileRef = D7066BF60E2BD04E00ED8BBE /* DeprecationMgr.h */; };
+ D7066C110E2BD07800ED8BBE /* BSplineRotate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFA0E2BD07800ED8BBE /* BSplineRotate.cpp */; };
+ D7066C120E2BD07800ED8BBE /* Channels.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFB0E2BD07800ED8BBE /* Channels.cpp */; };
+ D7066C130E2BD07800ED8BBE /* ClassicRotate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFC0E2BD07800ED8BBE /* ClassicRotate.cpp */; };
+ D7066C140E2BD07800ED8BBE /* Colors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFD0E2BD07800ED8BBE /* Colors.cpp */; };
+ D7066C150E2BD07800ED8BBE /* CopyPaste.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFE0E2BD07800ED8BBE /* CopyPaste.cpp */; };
+ D7066C160E2BD07800ED8BBE /* Display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066BFF0E2BD07800ED8BBE /* Display.cpp */; };
+ D7066C170E2BD07800ED8BBE /* Filters.h in Headers */ = {isa = PBXBuildFile; fileRef = D7066C000E2BD07800ED8BBE /* Filters.h */; };
+ D7066C180E2BD07800ED8BBE /* Flip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C010E2BD07800ED8BBE /* Flip.cpp */; };
+ D7066C190E2BD07800ED8BBE /* JPEGTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C020E2BD07800ED8BBE /* JPEGTransform.cpp */; };
+ D7066C1A0E2BD07800ED8BBE /* MultigridPoissonSolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C030E2BD07800ED8BBE /* MultigridPoissonSolver.cpp */; };
+ D7066C1B0E2BD07800ED8BBE /* Rescale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C040E2BD07800ED8BBE /* Rescale.cpp */; };
+ D7066C1C0E2BD07800ED8BBE /* Resize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C050E2BD07800ED8BBE /* Resize.cpp */; };
+ D7066C1D0E2BD07800ED8BBE /* Resize.h in Headers */ = {isa = PBXBuildFile; fileRef = D7066C060E2BD07800ED8BBE /* Resize.h */; };
+ D7066C1E0E2BD07800ED8BBE /* Exif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C080E2BD07800ED8BBE /* Exif.cpp */; };
+ D7066C1F0E2BD07800ED8BBE /* FIRational.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C090E2BD07800ED8BBE /* FIRational.cpp */; };
+ D7066C200E2BD07800ED8BBE /* FIRational.h in Headers */ = {isa = PBXBuildFile; fileRef = D7066C0A0E2BD07800ED8BBE /* FIRational.h */; };
+ D7066C210E2BD07800ED8BBE /* FreeImageTag.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C0B0E2BD07800ED8BBE /* FreeImageTag.cpp */; };
+ D7066C220E2BD07800ED8BBE /* FreeImageTag.h in Headers */ = {isa = PBXBuildFile; fileRef = D7066C0C0E2BD07800ED8BBE /* FreeImageTag.h */; };
+ D7066C230E2BD07800ED8BBE /* IPTC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C0D0E2BD07800ED8BBE /* IPTC.cpp */; };
+ D7066C240E2BD07800ED8BBE /* TagConversion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C0E0E2BD07800ED8BBE /* TagConversion.cpp */; };
+ D7066C250E2BD07800ED8BBE /* TagLib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C0F0E2BD07800ED8BBE /* TagLib.cpp */; };
+ D7066C260E2BD07800ED8BBE /* XTIFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7066C100E2BD07800ED8BBE /* XTIFF.cpp */; };
+ D706FA2C0EA41A3F00F3F6B1 /* TIFFLogLuv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D706FA2B0EA41A3F00F3F6B1 /* TIFFLogLuv.cpp */; };
+ D76E028F10D06BA500F2706E /* PSDParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D76E028D10D06BA500F2706E /* PSDParser.cpp */; };
+ D76E029010D06BA500F2706E /* PSDParser.h in Headers */ = {isa = PBXBuildFile; fileRef = D76E028E10D06BA500F2706E /* PSDParser.h */; };
+ D7A1E5980E2BD25800010CB8 /* CacheFile.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5910E2BD25800010CB8 /* CacheFile.h */; };
+ D7A1E5990E2BD25800010CB8 /* FreeImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5920E2BD25800010CB8 /* FreeImage.h */; };
+ D7A1E59A0E2BD25800010CB8 /* FreeImageIO.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5930E2BD25800010CB8 /* FreeImageIO.h */; };
+ D7A1E59B0E2BD25800010CB8 /* Plugin.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5940E2BD25800010CB8 /* Plugin.h */; };
+ D7A1E59C0E2BD25800010CB8 /* Quantizers.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5950E2BD25800010CB8 /* Quantizers.h */; };
+ D7A1E59D0E2BD25800010CB8 /* ToneMapping.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5960E2BD25800010CB8 /* ToneMapping.h */; };
+ D7A1E59E0E2BD25800010CB8 /* Utilities.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5970E2BD25800010CB8 /* Utilities.h */; };
+ D7A1E5AD0E2BD38A00010CB8 /* zutil.h in Headers */ = {isa = PBXBuildFile; fileRef = D7A1E5AC0E2BD38A00010CB8 /* zutil.h */; };
+ D7A5F2960E2BD46200DA164A /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7A5F25D0E2BD40100DA164A /* libjpeg.a */; };
+ D7A5F2970E2BD46300DA164A /* libmng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7A5F2700E2BD41300DA164A /* libmng.a */; };
+ D7A5F2980E2BD46300DA164A /* libopenjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7A5F27B0E2BD43200DA164A /* libopenjpeg.a */; };
+ D7A5F29A0E2BD46400DA164A /* libtiff.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7A5F2950E2BD44F00DA164A /* libtiff.a */; };
+ D7F881390E2BD55D007CA12F /* testMemIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881310E2BD55D007CA12F /* testMemIO.cpp */; };
+ D7F8813A0E2BD55D007CA12F /* testJPEG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881320E2BD55D007CA12F /* testJPEG.cpp */; };
+ D7F8813B0E2BD55D007CA12F /* testMPage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881330E2BD55D007CA12F /* testMPage.cpp */; };
+ D7F8813C0E2BD55D007CA12F /* MainTestSuite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881340E2BD55D007CA12F /* MainTestSuite.cpp */; };
+ D7F8813D0E2BD55D007CA12F /* testPlugins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881360E2BD55D007CA12F /* testPlugins.cpp */; };
+ D7F8813E0E2BD55D007CA12F /* testImageType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881370E2BD55D007CA12F /* testImageType.cpp */; };
+ D7F8813F0E2BD55D007CA12F /* testTools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D7F881380E2BD55D007CA12F /* testTools.cpp */; };
+ D7F8815C0E2BD677007CA12F /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7F8815B0E2BD677007CA12F /* Carbon.framework */; };
+ D7F8822A0E2BD7BE007CA12F /* libFreeImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libFreeImage.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ D7A5F25C0E2BD40100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = libjpeg;
+ };
+ D7A5F25E0E2BD40100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D76557550E0AE4150038F973;
+ remoteInfo = cjpeg;
+ };
+ D7A5F2600E2BD40100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D725A6F70E0AFB5F008C767D;
+ remoteInfo = djpeg;
+ };
+ D7A5F2620E2BD40100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D7EFF6010E0AFC7D0025E981;
+ remoteInfo = jpegtran;
+ };
+ D7A5F2640E2BD40100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D778786D0E0AFF7B00C99215;
+ remoteInfo = tests;
+ };
+ D7A5F26F0E2BD41300DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F2660E2BD41300DA164A /* libmng.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = libmng;
+ };
+ D7A5F27A0E2BD43200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F2710E2BD43200DA164A /* libopenjpeg.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = libopenjpeg;
+ };
+ D7A5F2870E2BD44100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = libpng;
+ };
+ D7A5F2890E2BD44100DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D74E47BA0E0AD22000402A94;
+ remoteInfo = pngtest;
+ };
+ D7A5F2940E2BD44F00DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F28B0E2BD44F00DA164A /* libtiff.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = D2AAC046055464E500DB518D;
+ remoteInfo = libtiff;
+ };
+ D7A5F29B0E2BD47200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libjpeg;
+ };
+ D7A5F29D0E2BD47200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libpng;
+ };
+ D7A5F29F0E2BD47200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F2710E2BD43200DA164A /* libopenjpeg.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libopenjpeg;
+ };
+ D7A5F2A10E2BD47200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F2660E2BD41300DA164A /* libmng.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libmng;
+ };
+ D7A5F2A30E2BD47200DA164A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = D7A5F28B0E2BD44F00DA164A /* libtiff.xcodeproj */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libtiff;
+ };
+ D7F881410E2BD57F007CA12F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = FreeImage;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libFreeImage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libFreeImage.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D7066B840E2BD03600ED8BBE /* BitmapAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BitmapAccess.cpp; path = Source/FreeImage/BitmapAccess.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B850E2BD03600ED8BBE /* CacheFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CacheFile.cpp; path = Source/FreeImage/CacheFile.cpp; sourceTree = "<group>"; };
+ D7066B860E2BD03600ED8BBE /* ColorLookup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColorLookup.cpp; path = Source/FreeImage/ColorLookup.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B870E2BD03600ED8BBE /* Conversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion.cpp; path = Source/FreeImage/Conversion.cpp; sourceTree = "<group>"; };
+ D7066B880E2BD03600ED8BBE /* Conversion4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion4.cpp; path = Source/FreeImage/Conversion4.cpp; sourceTree = "<group>"; };
+ D7066B890E2BD03600ED8BBE /* Conversion8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion8.cpp; path = Source/FreeImage/Conversion8.cpp; sourceTree = "<group>"; };
+ D7066B8A0E2BD03600ED8BBE /* Conversion16_555.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion16_555.cpp; path = Source/FreeImage/Conversion16_555.cpp; sourceTree = "<group>"; };
+ D7066B8B0E2BD03600ED8BBE /* Conversion16_565.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion16_565.cpp; path = Source/FreeImage/Conversion16_565.cpp; sourceTree = "<group>"; };
+ D7066B8C0E2BD03600ED8BBE /* Conversion24.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion24.cpp; path = Source/FreeImage/Conversion24.cpp; sourceTree = "<group>"; };
+ D7066B8D0E2BD03600ED8BBE /* Conversion32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Conversion32.cpp; path = Source/FreeImage/Conversion32.cpp; sourceTree = "<group>"; };
+ D7066B8E0E2BD03600ED8BBE /* ConversionRGBF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConversionRGBF.cpp; path = Source/FreeImage/ConversionRGBF.cpp; sourceTree = "<group>"; };
+ D7066B8F0E2BD03600ED8BBE /* ConversionType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConversionType.cpp; path = Source/FreeImage/ConversionType.cpp; sourceTree = "<group>"; };
+ D7066B900E2BD03600ED8BBE /* FreeImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeImage.cpp; path = Source/FreeImage/FreeImage.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B910E2BD03600ED8BBE /* FreeImageC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = FreeImageC.c; path = Source/FreeImage/FreeImageC.c; sourceTree = SOURCE_ROOT; };
+ D7066B920E2BD03600ED8BBE /* FreeImageIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeImageIO.cpp; path = Source/FreeImage/FreeImageIO.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B930E2BD03600ED8BBE /* GetType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GetType.cpp; path = Source/FreeImage/GetType.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B940E2BD03600ED8BBE /* Halftoning.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Halftoning.cpp; path = Source/FreeImage/Halftoning.cpp; sourceTree = "<group>"; };
+ D7066B950E2BD03600ED8BBE /* J2KHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = J2KHelper.cpp; path = Source/FreeImage/J2KHelper.cpp; sourceTree = "<group>"; };
+ D7066B960E2BD03600ED8BBE /* MemoryIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MemoryIO.cpp; path = Source/FreeImage/MemoryIO.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B970E2BD03600ED8BBE /* MultiPage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MultiPage.cpp; path = Source/FreeImage/MultiPage.cpp; sourceTree = "<group>"; };
+ D7066B980E2BD03600ED8BBE /* NNQuantizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NNQuantizer.cpp; path = Source/FreeImage/NNQuantizer.cpp; sourceTree = "<group>"; };
+ D7066B990E2BD03600ED8BBE /* PixelAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PixelAccess.cpp; path = Source/FreeImage/PixelAccess.cpp; sourceTree = SOURCE_ROOT; };
+ D7066B9A0E2BD03600ED8BBE /* Plugin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Plugin.cpp; path = Source/FreeImage/Plugin.cpp; sourceTree = "<group>"; };
+ D7066B9B0E2BD03600ED8BBE /* PluginBMP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginBMP.cpp; path = Source/FreeImage/PluginBMP.cpp; sourceTree = "<group>"; };
+ D7066B9C0E2BD03600ED8BBE /* PluginCUT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginCUT.cpp; path = Source/FreeImage/PluginCUT.cpp; sourceTree = "<group>"; };
+ D7066B9D0E2BD03600ED8BBE /* PluginDDS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginDDS.cpp; path = Source/FreeImage/PluginDDS.cpp; sourceTree = "<group>"; };
+ D7066B9F0E2BD03600ED8BBE /* PluginG3.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginG3.cpp; path = Source/FreeImage/PluginG3.cpp; sourceTree = "<group>"; };
+ D7066BA00E2BD03600ED8BBE /* PluginGIF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginGIF.cpp; path = Source/FreeImage/PluginGIF.cpp; sourceTree = "<group>"; };
+ D7066BA10E2BD03600ED8BBE /* PluginHDR.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginHDR.cpp; path = Source/FreeImage/PluginHDR.cpp; sourceTree = "<group>"; };
+ D7066BA20E2BD03600ED8BBE /* PluginICO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginICO.cpp; path = Source/FreeImage/PluginICO.cpp; sourceTree = "<group>"; };
+ D7066BA30E2BD03600ED8BBE /* PluginIFF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginIFF.cpp; path = Source/FreeImage/PluginIFF.cpp; sourceTree = "<group>"; };
+ D7066BA40E2BD03600ED8BBE /* PluginJ2K.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginJ2K.cpp; path = Source/FreeImage/PluginJ2K.cpp; sourceTree = "<group>"; };
+ D7066BA50E2BD03600ED8BBE /* PluginJP2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginJP2.cpp; path = Source/FreeImage/PluginJP2.cpp; sourceTree = "<group>"; };
+ D7066BA60E2BD03600ED8BBE /* PluginJPEG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginJPEG.cpp; path = Source/FreeImage/PluginJPEG.cpp; sourceTree = "<group>"; };
+ D7066BA70E2BD03600ED8BBE /* PluginKOALA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginKOALA.cpp; path = Source/FreeImage/PluginKOALA.cpp; sourceTree = "<group>"; };
+ D7066BA80E2BD03600ED8BBE /* PluginMNG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginMNG.cpp; path = Source/FreeImage/PluginMNG.cpp; sourceTree = "<group>"; };
+ D7066BA90E2BD03600ED8BBE /* PluginPCD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginPCD.cpp; path = Source/FreeImage/PluginPCD.cpp; sourceTree = "<group>"; };
+ D7066BAA0E2BD03600ED8BBE /* PluginPCX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginPCX.cpp; path = Source/FreeImage/PluginPCX.cpp; sourceTree = "<group>"; };
+ D7066BAB0E2BD03600ED8BBE /* PluginPNG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginPNG.cpp; path = Source/FreeImage/PluginPNG.cpp; sourceTree = "<group>"; };
+ D7066BAC0E2BD03600ED8BBE /* PluginPNM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginPNM.cpp; path = Source/FreeImage/PluginPNM.cpp; sourceTree = "<group>"; };
+ D7066BAD0E2BD03600ED8BBE /* PluginPSD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginPSD.cpp; path = Source/FreeImage/PluginPSD.cpp; sourceTree = "<group>"; };
+ D7066BAE0E2BD03600ED8BBE /* PluginRAS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginRAS.cpp; path = Source/FreeImage/PluginRAS.cpp; sourceTree = "<group>"; };
+ D7066BAF0E2BD03600ED8BBE /* PluginSGI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginSGI.cpp; path = Source/FreeImage/PluginSGI.cpp; sourceTree = "<group>"; };
+ D7066BB00E2BD03600ED8BBE /* PluginTARGA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginTARGA.cpp; path = Source/FreeImage/PluginTARGA.cpp; sourceTree = "<group>"; };
+ D7066BB10E2BD03600ED8BBE /* PluginTIFF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginTIFF.cpp; path = Source/FreeImage/PluginTIFF.cpp; sourceTree = "<group>"; };
+ D7066BB20E2BD03600ED8BBE /* PluginWBMP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginWBMP.cpp; path = Source/FreeImage/PluginWBMP.cpp; sourceTree = "<group>"; };
+ D7066BB30E2BD03600ED8BBE /* PluginXBM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginXBM.cpp; path = Source/FreeImage/PluginXBM.cpp; sourceTree = "<group>"; };
+ D7066BB40E2BD03600ED8BBE /* PluginXPM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginXPM.cpp; path = Source/FreeImage/PluginXPM.cpp; sourceTree = "<group>"; };
+ D7066BB50E2BD03600ED8BBE /* tmoColorConvert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tmoColorConvert.cpp; path = Source/FreeImage/tmoColorConvert.cpp; sourceTree = "<group>"; };
+ D7066BB60E2BD03600ED8BBE /* tmoDrago03.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tmoDrago03.cpp; path = Source/FreeImage/tmoDrago03.cpp; sourceTree = "<group>"; };
+ D7066BB70E2BD03600ED8BBE /* tmoFattal02.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tmoFattal02.cpp; path = Source/FreeImage/tmoFattal02.cpp; sourceTree = "<group>"; };
+ D7066BB80E2BD03600ED8BBE /* tmoReinhard05.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tmoReinhard05.cpp; path = Source/FreeImage/tmoReinhard05.cpp; sourceTree = "<group>"; };
+ D7066BB90E2BD03600ED8BBE /* ToneMapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToneMapping.cpp; path = Source/FreeImage/ToneMapping.cpp; sourceTree = "<group>"; };
+ D7066BBA0E2BD03600ED8BBE /* WuQuantizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WuQuantizer.cpp; path = Source/FreeImage/WuQuantizer.cpp; sourceTree = "<group>"; };
+ D7066BBB0E2BD03600ED8BBE /* ZLibInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ZLibInterface.cpp; path = Source/FreeImage/ZLibInterface.cpp; sourceTree = "<group>"; };
+ D7066BF50E2BD04E00ED8BBE /* DeprecationMgr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeprecationMgr.cpp; path = Source/DeprecationManager/DeprecationMgr.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BF60E2BD04E00ED8BBE /* DeprecationMgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DeprecationMgr.h; path = Source/DeprecationManager/DeprecationMgr.h; sourceTree = SOURCE_ROOT; };
+ D7066BFA0E2BD07800ED8BBE /* BSplineRotate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BSplineRotate.cpp; path = Source/FreeImageToolkit/BSplineRotate.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BFB0E2BD07800ED8BBE /* Channels.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Channels.cpp; path = Source/FreeImageToolkit/Channels.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BFC0E2BD07800ED8BBE /* ClassicRotate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClassicRotate.cpp; path = Source/FreeImageToolkit/ClassicRotate.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BFD0E2BD07800ED8BBE /* Colors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Colors.cpp; path = Source/FreeImageToolkit/Colors.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BFE0E2BD07800ED8BBE /* CopyPaste.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CopyPaste.cpp; path = Source/FreeImageToolkit/CopyPaste.cpp; sourceTree = SOURCE_ROOT; };
+ D7066BFF0E2BD07800ED8BBE /* Display.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Display.cpp; path = Source/FreeImageToolkit/Display.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C000E2BD07800ED8BBE /* Filters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Filters.h; path = Source/FreeImageToolkit/Filters.h; sourceTree = SOURCE_ROOT; };
+ D7066C010E2BD07800ED8BBE /* Flip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Flip.cpp; path = Source/FreeImageToolkit/Flip.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C020E2BD07800ED8BBE /* JPEGTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JPEGTransform.cpp; path = Source/FreeImageToolkit/JPEGTransform.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C030E2BD07800ED8BBE /* MultigridPoissonSolver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MultigridPoissonSolver.cpp; path = Source/FreeImageToolkit/MultigridPoissonSolver.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C040E2BD07800ED8BBE /* Rescale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Rescale.cpp; path = Source/FreeImageToolkit/Rescale.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C050E2BD07800ED8BBE /* Resize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Resize.cpp; path = Source/FreeImageToolkit/Resize.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C060E2BD07800ED8BBE /* Resize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Resize.h; path = Source/FreeImageToolkit/Resize.h; sourceTree = SOURCE_ROOT; };
+ D7066C080E2BD07800ED8BBE /* Exif.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exif.cpp; path = Source/Metadata/Exif.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C090E2BD07800ED8BBE /* FIRational.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FIRational.cpp; path = Source/Metadata/FIRational.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C0A0E2BD07800ED8BBE /* FIRational.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FIRational.h; path = Source/Metadata/FIRational.h; sourceTree = SOURCE_ROOT; };
+ D7066C0B0E2BD07800ED8BBE /* FreeImageTag.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FreeImageTag.cpp; path = Source/Metadata/FreeImageTag.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C0C0E2BD07800ED8BBE /* FreeImageTag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeImageTag.h; path = Source/Metadata/FreeImageTag.h; sourceTree = SOURCE_ROOT; };
+ D7066C0D0E2BD07800ED8BBE /* IPTC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IPTC.cpp; path = Source/Metadata/IPTC.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C0E0E2BD07800ED8BBE /* TagConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TagConversion.cpp; path = Source/Metadata/TagConversion.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C0F0E2BD07800ED8BBE /* TagLib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TagLib.cpp; path = Source/Metadata/TagLib.cpp; sourceTree = SOURCE_ROOT; };
+ D7066C100E2BD07800ED8BBE /* XTIFF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = XTIFF.cpp; path = Source/Metadata/XTIFF.cpp; sourceTree = SOURCE_ROOT; };
+ D706FA2B0EA41A3F00F3F6B1 /* TIFFLogLuv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TIFFLogLuv.cpp; path = Source/FreeImage/TIFFLogLuv.cpp; sourceTree = SOURCE_ROOT; };
+ D76E028D10D06BA500F2706E /* PSDParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PSDParser.cpp; path = Source/FreeImage/PSDParser.cpp; sourceTree = SOURCE_ROOT; };
+ D76E028E10D06BA500F2706E /* PSDParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PSDParser.h; path = Source/FreeImage/PSDParser.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5910E2BD25800010CB8 /* CacheFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CacheFile.h; path = Source/CacheFile.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5920E2BD25800010CB8 /* FreeImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeImage.h; path = Source/FreeImage.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5930E2BD25800010CB8 /* FreeImageIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FreeImageIO.h; path = Source/FreeImageIO.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5940E2BD25800010CB8 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = Source/Plugin.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5950E2BD25800010CB8 /* Quantizers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Quantizers.h; path = Source/Quantizers.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5960E2BD25800010CB8 /* ToneMapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ToneMapping.h; path = Source/ToneMapping.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5970E2BD25800010CB8 /* Utilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Utilities.h; path = Source/Utilities.h; sourceTree = SOURCE_ROOT; };
+ D7A1E5AC0E2BD38A00010CB8 /* zutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = zutil.h; path = "../zlib-1.2.3/zutil.h"; sourceTree = SOURCE_ROOT; };
+ D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libjpeg.xcodeproj; path = Source/LibJPEG/libjpeg.xcodeproj; sourceTree = SOURCE_ROOT; };
+ D7A5F2660E2BD41300DA164A /* libmng.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libmng.xcodeproj; path = Source/LibMNG/libmng.xcodeproj; sourceTree = SOURCE_ROOT; };
+ D7A5F2710E2BD43200DA164A /* libopenjpeg.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libopenjpeg.xcodeproj; path = Source/LibOpenJPEG/libopenjpeg.xcodeproj; sourceTree = SOURCE_ROOT; };
+ D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libpng.xcodeproj; path = Source/LibPNG/libpng.xcodeproj; sourceTree = SOURCE_ROOT; };
+ D7A5F28B0E2BD44F00DA164A /* libtiff.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = libtiff.xcodeproj; path = Source/LibTIFF/libtiff.xcodeproj; sourceTree = SOURCE_ROOT; };
+ D7EFF2FE0E2BCDF800C97412 /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D7EFF2FF0E2BCDF800C97412 /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D7F8812A0E2BD519007CA12F /* FreeImageTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FreeImageTest; sourceTree = BUILT_PRODUCTS_DIR; };
+ D7F881310E2BD55D007CA12F /* testMemIO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testMemIO.cpp; path = TestAPI/testMemIO.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881320E2BD55D007CA12F /* testJPEG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testJPEG.cpp; path = TestAPI/testJPEG.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881330E2BD55D007CA12F /* testMPage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testMPage.cpp; path = TestAPI/testMPage.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881340E2BD55D007CA12F /* MainTestSuite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MainTestSuite.cpp; path = TestAPI/MainTestSuite.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881350E2BD55D007CA12F /* TestSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestSuite.h; path = TestAPI/TestSuite.h; sourceTree = SOURCE_ROOT; };
+ D7F881360E2BD55D007CA12F /* testPlugins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testPlugins.cpp; path = TestAPI/testPlugins.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881370E2BD55D007CA12F /* testImageType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testImageType.cpp; path = TestAPI/testImageType.cpp; sourceTree = SOURCE_ROOT; };
+ D7F881380E2BD55D007CA12F /* testTools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testTools.cpp; path = TestAPI/testTools.cpp; sourceTree = SOURCE_ROOT; };
+ D7F8815B0E2BD677007CA12F /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7A5F2970E2BD46300DA164A /* libmng.a in Frameworks */,
+ D7A5F2980E2BD46300DA164A /* libopenjpeg.a in Frameworks */,
+ D7A5F29A0E2BD46400DA164A /* libtiff.a in Frameworks */,
+ D7A5F2960E2BD46200DA164A /* libjpeg.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D7F881280E2BD519007CA12F /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7F8822A0E2BD7BE007CA12F /* libFreeImage.a in Frameworks */,
+ D7F8815C0E2BD677007CA12F /* Carbon.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* FreeImage */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */,
+ D7A5F2660E2BD41300DA164A /* libmng.xcodeproj */,
+ D7A5F2710E2BD43200DA164A /* libopenjpeg.xcodeproj */,
+ D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */,
+ D7A5F28B0E2BD44F00DA164A /* libtiff.xcodeproj */,
+ D7EFF2FE0E2BCDF800C97412 /* MacConfigExternalRelease.xcconfig */,
+ D7EFF2FF0E2BCDF800C97412 /* MacConfigExternalDebug.xcconfig */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ D7F881240E2BD4E2007CA12F /* Source (test only) */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = FreeImage;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D7066C280E2BD0C100ED8BBE /* Conversion */,
+ D7066BF40E2BD04E00ED8BBE /* DeprecationManager */,
+ D7066C070E2BD07800ED8BBE /* Metadata */,
+ D7066C290E2BD0FE00ED8BBE /* MultiPaging */,
+ D7066C270E2BD08A00ED8BBE /* Plugins */,
+ D7066C2A0E2BD16600ED8BBE /* Quantizers */,
+ D7066BF90E2BD07800ED8BBE /* Toolkit */,
+ D7A1E5910E2BD25800010CB8 /* CacheFile.h */,
+ D7A1E5920E2BD25800010CB8 /* FreeImage.h */,
+ D7A1E5930E2BD25800010CB8 /* FreeImageIO.h */,
+ D7A1E5940E2BD25800010CB8 /* Plugin.h */,
+ D7A1E5950E2BD25800010CB8 /* Quantizers.h */,
+ D7A1E5960E2BD25800010CB8 /* ToneMapping.h */,
+ D7A1E5970E2BD25800010CB8 /* Utilities.h */,
+ D7A1E5AC0E2BD38A00010CB8 /* zutil.h */,
+ D7066B840E2BD03600ED8BBE /* BitmapAccess.cpp */,
+ D7066B860E2BD03600ED8BBE /* ColorLookup.cpp */,
+ D7066B900E2BD03600ED8BBE /* FreeImage.cpp */,
+ D7066B910E2BD03600ED8BBE /* FreeImageC.c */,
+ D7066B920E2BD03600ED8BBE /* FreeImageIO.cpp */,
+ D7066B930E2BD03600ED8BBE /* GetType.cpp */,
+ D7066B960E2BD03600ED8BBE /* MemoryIO.cpp */,
+ D7066B990E2BD03600ED8BBE /* PixelAccess.cpp */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libFreeImage.a */,
+ D7F8812A0E2BD519007CA12F /* FreeImageTest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7066BF40E2BD04E00ED8BBE /* DeprecationManager */ = {
+ isa = PBXGroup;
+ children = (
+ D7066BF50E2BD04E00ED8BBE /* DeprecationMgr.cpp */,
+ D7066BF60E2BD04E00ED8BBE /* DeprecationMgr.h */,
+ );
+ name = DeprecationManager;
+ path = Source/DeprecationManager;
+ sourceTree = SOURCE_ROOT;
+ };
+ D7066BF90E2BD07800ED8BBE /* Toolkit */ = {
+ isa = PBXGroup;
+ children = (
+ D7066BFA0E2BD07800ED8BBE /* BSplineRotate.cpp */,
+ D7066BFB0E2BD07800ED8BBE /* Channels.cpp */,
+ D7066BFC0E2BD07800ED8BBE /* ClassicRotate.cpp */,
+ D7066BFD0E2BD07800ED8BBE /* Colors.cpp */,
+ D7066BFE0E2BD07800ED8BBE /* CopyPaste.cpp */,
+ D7066BFF0E2BD07800ED8BBE /* Display.cpp */,
+ D7066C000E2BD07800ED8BBE /* Filters.h */,
+ D7066C010E2BD07800ED8BBE /* Flip.cpp */,
+ D7066C020E2BD07800ED8BBE /* JPEGTransform.cpp */,
+ D7066C030E2BD07800ED8BBE /* MultigridPoissonSolver.cpp */,
+ D7066C040E2BD07800ED8BBE /* Rescale.cpp */,
+ D7066C050E2BD07800ED8BBE /* Resize.cpp */,
+ D7066C060E2BD07800ED8BBE /* Resize.h */,
+ );
+ name = Toolkit;
+ path = Source/FreeImageToolkit;
+ sourceTree = SOURCE_ROOT;
+ };
+ D7066C070E2BD07800ED8BBE /* Metadata */ = {
+ isa = PBXGroup;
+ children = (
+ D7066C080E2BD07800ED8BBE /* Exif.cpp */,
+ D7066C090E2BD07800ED8BBE /* FIRational.cpp */,
+ D7066C0A0E2BD07800ED8BBE /* FIRational.h */,
+ D7066C0B0E2BD07800ED8BBE /* FreeImageTag.cpp */,
+ D7066C0C0E2BD07800ED8BBE /* FreeImageTag.h */,
+ D7066C0D0E2BD07800ED8BBE /* IPTC.cpp */,
+ D7066C0E0E2BD07800ED8BBE /* TagConversion.cpp */,
+ D7066C0F0E2BD07800ED8BBE /* TagLib.cpp */,
+ D7066C100E2BD07800ED8BBE /* XTIFF.cpp */,
+ );
+ name = Metadata;
+ path = Source/Metadata;
+ sourceTree = SOURCE_ROOT;
+ };
+ D7066C270E2BD08A00ED8BBE /* Plugins */ = {
+ isa = PBXGroup;
+ children = (
+ D76E028D10D06BA500F2706E /* PSDParser.cpp */,
+ D76E028E10D06BA500F2706E /* PSDParser.h */,
+ D706FA2B0EA41A3F00F3F6B1 /* TIFFLogLuv.cpp */,
+ D7066B950E2BD03600ED8BBE /* J2KHelper.cpp */,
+ D7066B9A0E2BD03600ED8BBE /* Plugin.cpp */,
+ D7066B9B0E2BD03600ED8BBE /* PluginBMP.cpp */,
+ D7066B9C0E2BD03600ED8BBE /* PluginCUT.cpp */,
+ D7066B9D0E2BD03600ED8BBE /* PluginDDS.cpp */,
+ D7066B9F0E2BD03600ED8BBE /* PluginG3.cpp */,
+ D7066BA00E2BD03600ED8BBE /* PluginGIF.cpp */,
+ D7066BA10E2BD03600ED8BBE /* PluginHDR.cpp */,
+ D7066BA20E2BD03600ED8BBE /* PluginICO.cpp */,
+ D7066BA30E2BD03600ED8BBE /* PluginIFF.cpp */,
+ D7066BA40E2BD03600ED8BBE /* PluginJ2K.cpp */,
+ D7066BA50E2BD03600ED8BBE /* PluginJP2.cpp */,
+ D7066BA60E2BD03600ED8BBE /* PluginJPEG.cpp */,
+ D7066BA70E2BD03600ED8BBE /* PluginKOALA.cpp */,
+ D7066BA80E2BD03600ED8BBE /* PluginMNG.cpp */,
+ D7066BA90E2BD03600ED8BBE /* PluginPCD.cpp */,
+ D7066BAA0E2BD03600ED8BBE /* PluginPCX.cpp */,
+ D7066BAB0E2BD03600ED8BBE /* PluginPNG.cpp */,
+ D7066BAC0E2BD03600ED8BBE /* PluginPNM.cpp */,
+ D7066BAD0E2BD03600ED8BBE /* PluginPSD.cpp */,
+ D7066BAE0E2BD03600ED8BBE /* PluginRAS.cpp */,
+ D7066BAF0E2BD03600ED8BBE /* PluginSGI.cpp */,
+ D7066BB00E2BD03600ED8BBE /* PluginTARGA.cpp */,
+ D7066BB10E2BD03600ED8BBE /* PluginTIFF.cpp */,
+ D7066BB20E2BD03600ED8BBE /* PluginWBMP.cpp */,
+ D7066BB30E2BD03600ED8BBE /* PluginXBM.cpp */,
+ D7066BB40E2BD03600ED8BBE /* PluginXPM.cpp */,
+ );
+ name = Plugins;
+ sourceTree = "<group>";
+ };
+ D7066C280E2BD0C100ED8BBE /* Conversion */ = {
+ isa = PBXGroup;
+ children = (
+ D7066B870E2BD03600ED8BBE /* Conversion.cpp */,
+ D7066B880E2BD03600ED8BBE /* Conversion4.cpp */,
+ D7066B890E2BD03600ED8BBE /* Conversion8.cpp */,
+ D7066B8A0E2BD03600ED8BBE /* Conversion16_555.cpp */,
+ D7066B8B0E2BD03600ED8BBE /* Conversion16_565.cpp */,
+ D7066B8C0E2BD03600ED8BBE /* Conversion24.cpp */,
+ D7066B8D0E2BD03600ED8BBE /* Conversion32.cpp */,
+ D7066B8E0E2BD03600ED8BBE /* ConversionRGBF.cpp */,
+ D7066B8F0E2BD03600ED8BBE /* ConversionType.cpp */,
+ D7066B940E2BD03600ED8BBE /* Halftoning.cpp */,
+ D7066BB50E2BD03600ED8BBE /* tmoColorConvert.cpp */,
+ D7066BB60E2BD03600ED8BBE /* tmoDrago03.cpp */,
+ D7066BB70E2BD03600ED8BBE /* tmoFattal02.cpp */,
+ D7066BB80E2BD03600ED8BBE /* tmoReinhard05.cpp */,
+ D7066BB90E2BD03600ED8BBE /* ToneMapping.cpp */,
+ );
+ name = Conversion;
+ sourceTree = "<group>";
+ };
+ D7066C290E2BD0FE00ED8BBE /* MultiPaging */ = {
+ isa = PBXGroup;
+ children = (
+ D7066B850E2BD03600ED8BBE /* CacheFile.cpp */,
+ D7066B970E2BD03600ED8BBE /* MultiPage.cpp */,
+ D7066BBB0E2BD03600ED8BBE /* ZLibInterface.cpp */,
+ );
+ name = MultiPaging;
+ sourceTree = "<group>";
+ };
+ D7066C2A0E2BD16600ED8BBE /* Quantizers */ = {
+ isa = PBXGroup;
+ children = (
+ D7066B980E2BD03600ED8BBE /* NNQuantizer.cpp */,
+ D7066BBA0E2BD03600ED8BBE /* WuQuantizer.cpp */,
+ );
+ name = Quantizers;
+ sourceTree = "<group>";
+ };
+ D7A5F2550E2BD40100DA164A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F25D0E2BD40100DA164A /* libjpeg.a */,
+ D7A5F25F0E2BD40100DA164A /* cjpeg */,
+ D7A5F2610E2BD40100DA164A /* djpeg */,
+ D7A5F2630E2BD40100DA164A /* jpegtran */,
+ D7A5F2650E2BD40100DA164A /* tests */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7A5F26C0E2BD41300DA164A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F2700E2BD41300DA164A /* libmng.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7A5F2770E2BD43200DA164A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F27B0E2BD43200DA164A /* libopenjpeg.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7A5F2830E2BD44100DA164A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F2880E2BD44100DA164A /* libpng.a */,
+ D7A5F28A0E2BD44100DA164A /* pngtest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7A5F2910E2BD44F00DA164A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D7A5F2950E2BD44F00DA164A /* libtiff.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D7F881240E2BD4E2007CA12F /* Source (test only) */ = {
+ isa = PBXGroup;
+ children = (
+ D7F8815B0E2BD677007CA12F /* Carbon.framework */,
+ D7F881310E2BD55D007CA12F /* testMemIO.cpp */,
+ D7F881320E2BD55D007CA12F /* testJPEG.cpp */,
+ D7F881330E2BD55D007CA12F /* testMPage.cpp */,
+ D7F881340E2BD55D007CA12F /* MainTestSuite.cpp */,
+ D7F881350E2BD55D007CA12F /* TestSuite.h */,
+ D7F881360E2BD55D007CA12F /* testPlugins.cpp */,
+ D7F881370E2BD55D007CA12F /* testImageType.cpp */,
+ D7F881380E2BD55D007CA12F /* testTools.cpp */,
+ );
+ name = "Source (test only)";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7066BF80E2BD04E00ED8BBE /* DeprecationMgr.h in Headers */,
+ D7066C170E2BD07800ED8BBE /* Filters.h in Headers */,
+ D7066C1D0E2BD07800ED8BBE /* Resize.h in Headers */,
+ D7066C200E2BD07800ED8BBE /* FIRational.h in Headers */,
+ D7066C220E2BD07800ED8BBE /* FreeImageTag.h in Headers */,
+ D7A1E5980E2BD25800010CB8 /* CacheFile.h in Headers */,
+ D7A1E5990E2BD25800010CB8 /* FreeImage.h in Headers */,
+ D7A1E59A0E2BD25800010CB8 /* FreeImageIO.h in Headers */,
+ D7A1E59B0E2BD25800010CB8 /* Plugin.h in Headers */,
+ D7A1E59C0E2BD25800010CB8 /* Quantizers.h in Headers */,
+ D7A1E59D0E2BD25800010CB8 /* ToneMapping.h in Headers */,
+ D7A1E59E0E2BD25800010CB8 /* Utilities.h in Headers */,
+ D7A1E5AD0E2BD38A00010CB8 /* zutil.h in Headers */,
+ D76E029010D06BA500F2706E /* PSDParser.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* FreeImage */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "FreeImage" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D7A5F29C0E2BD47200DA164A /* PBXTargetDependency */,
+ D7A5F29E0E2BD47200DA164A /* PBXTargetDependency */,
+ D7A5F2A00E2BD47200DA164A /* PBXTargetDependency */,
+ D7A5F2A20E2BD47200DA164A /* PBXTargetDependency */,
+ D7A5F2A40E2BD47200DA164A /* PBXTargetDependency */,
+ );
+ name = FreeImage;
+ productName = FreeImage;
+ productReference = D2AAC046055464E500DB518D /* libFreeImage.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ D7F881290E2BD519007CA12F /* FreeImageTest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D7F881300E2BD527007CA12F /* Build configuration list for PBXNativeTarget "FreeImageTest" */;
+ buildPhases = (
+ D7F881270E2BD519007CA12F /* Sources */,
+ D7F881280E2BD519007CA12F /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D7F881420E2BD57F007CA12F /* PBXTargetDependency */,
+ );
+ name = FreeImageTest;
+ productName = FreeImageTest;
+ productReference = D7F8812A0E2BD519007CA12F /* FreeImageTest */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "FreeImage" */;
+ compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ Japanese,
+ French,
+ German,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* FreeImage */;
+ projectDirPath = "";
+ projectReferences = (
+ {
+ ProductGroup = D7A5F2550E2BD40100DA164A /* Products */;
+ ProjectRef = D7A5F24B0E2BD40100DA164A /* libjpeg.xcodeproj */;
+ },
+ {
+ ProductGroup = D7A5F26C0E2BD41300DA164A /* Products */;
+ ProjectRef = D7A5F2660E2BD41300DA164A /* libmng.xcodeproj */;
+ },
+ {
+ ProductGroup = D7A5F2770E2BD43200DA164A /* Products */;
+ ProjectRef = D7A5F2710E2BD43200DA164A /* libopenjpeg.xcodeproj */;
+ },
+ {
+ ProductGroup = D7A5F2830E2BD44100DA164A /* Products */;
+ ProjectRef = D7A5F27C0E2BD44100DA164A /* libpng.xcodeproj */;
+ },
+ {
+ ProductGroup = D7A5F2910E2BD44F00DA164A /* Products */;
+ ProjectRef = D7A5F28B0E2BD44F00DA164A /* libtiff.xcodeproj */;
+ },
+ );
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* FreeImage */,
+ D7F881290E2BD519007CA12F /* FreeImageTest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXReferenceProxy section */
+ D7A5F25D0E2BD40100DA164A /* libjpeg.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libjpeg.a;
+ remoteRef = D7A5F25C0E2BD40100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F25F0E2BD40100DA164A /* cjpeg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = cjpeg;
+ remoteRef = D7A5F25E0E2BD40100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2610E2BD40100DA164A /* djpeg */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = djpeg;
+ remoteRef = D7A5F2600E2BD40100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2630E2BD40100DA164A /* jpegtran */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = jpegtran;
+ remoteRef = D7A5F2620E2BD40100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2650E2BD40100DA164A /* tests */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = tests;
+ remoteRef = D7A5F2640E2BD40100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2700E2BD41300DA164A /* libmng.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libmng.a;
+ remoteRef = D7A5F26F0E2BD41300DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F27B0E2BD43200DA164A /* libopenjpeg.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libopenjpeg.a;
+ remoteRef = D7A5F27A0E2BD43200DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2880E2BD44100DA164A /* libpng.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libpng.a;
+ remoteRef = D7A5F2870E2BD44100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F28A0E2BD44100DA164A /* pngtest */ = {
+ isa = PBXReferenceProxy;
+ fileType = "compiled.mach-o.executable";
+ path = pngtest;
+ remoteRef = D7A5F2890E2BD44100DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ D7A5F2950E2BD44F00DA164A /* libtiff.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libtiff.a;
+ remoteRef = D7A5F2940E2BD44F00DA164A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+/* End PBXReferenceProxy section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7066BBC0E2BD03600ED8BBE /* BitmapAccess.cpp in Sources */,
+ D7066BBD0E2BD03600ED8BBE /* CacheFile.cpp in Sources */,
+ D7066BBE0E2BD03600ED8BBE /* ColorLookup.cpp in Sources */,
+ D7066BBF0E2BD03600ED8BBE /* Conversion.cpp in Sources */,
+ D7066BC00E2BD03600ED8BBE /* Conversion4.cpp in Sources */,
+ D7066BC10E2BD03600ED8BBE /* Conversion8.cpp in Sources */,
+ D7066BC20E2BD03600ED8BBE /* Conversion16_555.cpp in Sources */,
+ D7066BC30E2BD03600ED8BBE /* Conversion16_565.cpp in Sources */,
+ D7066BC40E2BD03600ED8BBE /* Conversion24.cpp in Sources */,
+ D7066BC50E2BD03600ED8BBE /* Conversion32.cpp in Sources */,
+ D7066BC60E2BD03600ED8BBE /* ConversionRGBF.cpp in Sources */,
+ D7066BC70E2BD03600ED8BBE /* ConversionType.cpp in Sources */,
+ D7066BC80E2BD03600ED8BBE /* FreeImage.cpp in Sources */,
+ D7066BC90E2BD03600ED8BBE /* FreeImageC.c in Sources */,
+ D7066BCA0E2BD03600ED8BBE /* FreeImageIO.cpp in Sources */,
+ D7066BCB0E2BD03600ED8BBE /* GetType.cpp in Sources */,
+ D7066BCC0E2BD03600ED8BBE /* Halftoning.cpp in Sources */,
+ D7066BCD0E2BD03600ED8BBE /* J2KHelper.cpp in Sources */,
+ D7066BCE0E2BD03600ED8BBE /* MemoryIO.cpp in Sources */,
+ D7066BCF0E2BD03600ED8BBE /* MultiPage.cpp in Sources */,
+ D7066BD00E2BD03600ED8BBE /* NNQuantizer.cpp in Sources */,
+ D7066BD10E2BD03600ED8BBE /* PixelAccess.cpp in Sources */,
+ D7066BD20E2BD03600ED8BBE /* Plugin.cpp in Sources */,
+ D7066BD30E2BD03600ED8BBE /* PluginBMP.cpp in Sources */,
+ D7066BD40E2BD03600ED8BBE /* PluginCUT.cpp in Sources */,
+ D7066BD50E2BD03600ED8BBE /* PluginDDS.cpp in Sources */,
+ D7066BD70E2BD03600ED8BBE /* PluginG3.cpp in Sources */,
+ D7066BD80E2BD03600ED8BBE /* PluginGIF.cpp in Sources */,
+ D7066BD90E2BD03600ED8BBE /* PluginHDR.cpp in Sources */,
+ D7066BDA0E2BD03600ED8BBE /* PluginICO.cpp in Sources */,
+ D7066BDB0E2BD03600ED8BBE /* PluginIFF.cpp in Sources */,
+ D7066BDC0E2BD03600ED8BBE /* PluginJ2K.cpp in Sources */,
+ D7066BDD0E2BD03600ED8BBE /* PluginJP2.cpp in Sources */,
+ D7066BDE0E2BD03600ED8BBE /* PluginJPEG.cpp in Sources */,
+ D7066BDF0E2BD03600ED8BBE /* PluginKOALA.cpp in Sources */,
+ D7066BE00E2BD03600ED8BBE /* PluginMNG.cpp in Sources */,
+ D7066BE10E2BD03600ED8BBE /* PluginPCD.cpp in Sources */,
+ D7066BE20E2BD03600ED8BBE /* PluginPCX.cpp in Sources */,
+ D7066BE30E2BD03600ED8BBE /* PluginPNG.cpp in Sources */,
+ D7066BE40E2BD03600ED8BBE /* PluginPNM.cpp in Sources */,
+ D7066BE50E2BD03600ED8BBE /* PluginPSD.cpp in Sources */,
+ D7066BE60E2BD03600ED8BBE /* PluginRAS.cpp in Sources */,
+ D7066BE70E2BD03600ED8BBE /* PluginSGI.cpp in Sources */,
+ D7066BE80E2BD03600ED8BBE /* PluginTARGA.cpp in Sources */,
+ D7066BE90E2BD03600ED8BBE /* PluginTIFF.cpp in Sources */,
+ D7066BEA0E2BD03600ED8BBE /* PluginWBMP.cpp in Sources */,
+ D7066BEB0E2BD03600ED8BBE /* PluginXBM.cpp in Sources */,
+ D7066BEC0E2BD03600ED8BBE /* PluginXPM.cpp in Sources */,
+ D7066BED0E2BD03600ED8BBE /* tmoColorConvert.cpp in Sources */,
+ D7066BEE0E2BD03600ED8BBE /* tmoDrago03.cpp in Sources */,
+ D7066BEF0E2BD03600ED8BBE /* tmoFattal02.cpp in Sources */,
+ D7066BF00E2BD03600ED8BBE /* tmoReinhard05.cpp in Sources */,
+ D7066BF10E2BD03600ED8BBE /* ToneMapping.cpp in Sources */,
+ D7066BF20E2BD03600ED8BBE /* WuQuantizer.cpp in Sources */,
+ D7066BF30E2BD03600ED8BBE /* ZLibInterface.cpp in Sources */,
+ D7066BF70E2BD04E00ED8BBE /* DeprecationMgr.cpp in Sources */,
+ D7066C110E2BD07800ED8BBE /* BSplineRotate.cpp in Sources */,
+ D7066C120E2BD07800ED8BBE /* Channels.cpp in Sources */,
+ D7066C130E2BD07800ED8BBE /* ClassicRotate.cpp in Sources */,
+ D7066C140E2BD07800ED8BBE /* Colors.cpp in Sources */,
+ D7066C150E2BD07800ED8BBE /* CopyPaste.cpp in Sources */,
+ D7066C160E2BD07800ED8BBE /* Display.cpp in Sources */,
+ D7066C180E2BD07800ED8BBE /* Flip.cpp in Sources */,
+ D7066C190E2BD07800ED8BBE /* JPEGTransform.cpp in Sources */,
+ D7066C1A0E2BD07800ED8BBE /* MultigridPoissonSolver.cpp in Sources */,
+ D7066C1B0E2BD07800ED8BBE /* Rescale.cpp in Sources */,
+ D7066C1C0E2BD07800ED8BBE /* Resize.cpp in Sources */,
+ D7066C1E0E2BD07800ED8BBE /* Exif.cpp in Sources */,
+ D7066C1F0E2BD07800ED8BBE /* FIRational.cpp in Sources */,
+ D7066C210E2BD07800ED8BBE /* FreeImageTag.cpp in Sources */,
+ D7066C230E2BD07800ED8BBE /* IPTC.cpp in Sources */,
+ D7066C240E2BD07800ED8BBE /* TagConversion.cpp in Sources */,
+ D7066C250E2BD07800ED8BBE /* TagLib.cpp in Sources */,
+ D7066C260E2BD07800ED8BBE /* XTIFF.cpp in Sources */,
+ D706FA2C0EA41A3F00F3F6B1 /* TIFFLogLuv.cpp in Sources */,
+ D76E028F10D06BA500F2706E /* PSDParser.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D7F881270E2BD519007CA12F /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7F881390E2BD55D007CA12F /* testMemIO.cpp in Sources */,
+ D7F8813A0E2BD55D007CA12F /* testJPEG.cpp in Sources */,
+ D7F8813B0E2BD55D007CA12F /* testMPage.cpp in Sources */,
+ D7F8813C0E2BD55D007CA12F /* MainTestSuite.cpp in Sources */,
+ D7F8813D0E2BD55D007CA12F /* testPlugins.cpp in Sources */,
+ D7F8813E0E2BD55D007CA12F /* testImageType.cpp in Sources */,
+ D7F8813F0E2BD55D007CA12F /* testTools.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ D7A5F29C0E2BD47200DA164A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = libjpeg;
+ targetProxy = D7A5F29B0E2BD47200DA164A /* PBXContainerItemProxy */;
+ };
+ D7A5F29E0E2BD47200DA164A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = libpng;
+ targetProxy = D7A5F29D0E2BD47200DA164A /* PBXContainerItemProxy */;
+ };
+ D7A5F2A00E2BD47200DA164A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = libopenjpeg;
+ targetProxy = D7A5F29F0E2BD47200DA164A /* PBXContainerItemProxy */;
+ };
+ D7A5F2A20E2BD47200DA164A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = libmng;
+ targetProxy = D7A5F2A10E2BD47200DA164A /* PBXContainerItemProxy */;
+ };
+ D7A5F2A40E2BD47200DA164A /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ name = libtiff;
+ targetProxy = D7A5F2A30E2BD47200DA164A /* PBXContainerItemProxy */;
+ };
+ D7F881420E2BD57F007CA12F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC045055464E500DB518D /* FreeImage */;
+ targetProxy = D7F881410E2BD57F007CA12F /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = FreeImage;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = FreeImage;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D7EFF2FF0E2BCDF800C97412 /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D7EFF2FE0E2BCDF800C97412 /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ D7F8812C0E2BD51A007CA12F /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = FreeImageTest;
+ };
+ name = Debug;
+ };
+ D7F8812D0E2BD51A007CA12F /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = FreeImageTest;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "FreeImage" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "FreeImage" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D7F881300E2BD527007CA12F /* Build configuration list for PBXNativeTarget "FreeImageTest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D7F8812C0E2BD51A007CA12F /* Debug */,
+ D7F8812D0E2BD51A007CA12F /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/FreeImage3130.pdf b/FreeImage3130.pdf
new file mode 100644
index 0000000..23657ca
--- /dev/null
+++ b/FreeImage3130.pdf
Binary files differ
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e11423
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,34 @@
+# Entry point for FreeImage makefiles
+# Default to 'make -f Makefile.gnu' for Linux and for unknown OS.
+#
+OS = $(shell uname)
+MAKEFILE = gnu
+
+ifeq ($(OS), Darwin)
+ MAKEFILE = osx
+endif
+ifeq ($(OS), Cygwin)
+ MAKEFILE = cygwin
+endif
+ifeq ($(OS), Solaris)
+ MAKEFILE = solaris
+endif
+ifeq ($(OS), windows32)
+ MAKEFILE = mingw
+endif
+
+default:
+ $(MAKE) -f Makefile.$(MAKEFILE)
+
+all:
+ $(MAKE) -f Makefile.$(MAKEFILE) all
+
+dist:
+ $(MAKE) -f Makefile.$(MAKEFILE) dist
+
+install:
+ $(MAKE) -f Makefile.$(MAKEFILE) install
+
+clean:
+ $(MAKE) -f Makefile.$(MAKEFILE) clean
+
diff --git a/Makefile.cygwin b/Makefile.cygwin
new file mode 100644
index 0000000..124f612
--- /dev/null
+++ b/Makefile.cygwin
@@ -0,0 +1,73 @@
+# Cygwin makefile for FreeImage
+
+# This file can be generated by ./gensrclist.sh
+include Makefile.srcs
+
+# General configuration variables:
+CC = gcc
+CXX = g++
+AR = ar
+
+INSTALLDIR = /usr
+
+# Converts cr/lf to just lf
+DOS2UNIX = dos2unix
+
+COMPILERFLAGS = -O3 -DNO_LCMS
+LIBRARIES = -lstdc++
+
+MODULES = $(SRCS:.c=.o)
+MODULES := $(MODULES:.cpp=.o)
+CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
+CXXFLAGS = $(COMPILERFLAGS) -Wno-ctor-dtor-privacy $(INCLUDE)
+
+TARGET = freeimage
+STATICLIB = lib$(TARGET).a
+SHAREDLIB = cyg$(TARGET)-$(VER_MAJOR).$(VER_MINOR).dll
+LIBNAME = lib$(TARGET).dll.a
+HEADER = Source/FreeImage.h
+
+
+default: all
+
+all: dist
+
+dist: FreeImage
+ cp *.a Dist
+ cp *.dll Dist
+ cp *.dll.a Dist
+ cp $(HEADER) Dist
+
+dos2unix:
+ @$(DOS2UNIX) $(SRCS) $(INCLS)
+
+FreeImage: $(STATICLIB) $(SHAREDLIB)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(STATICLIB): $(MODULES)
+ $(AR) r $@ $(MODULES)
+
+$(SHAREDLIB): $(MODULES)
+ $(CC) -s -shared -o $@ \
+ -Wl,--out-implib=$(LIBNAME) \
+ -Wl,--export-all-symbols \
+ -Wl,--enable-auto-import \
+ -Wl,--enable-auto-image-base \
+ -Wl,--whole-archive $(STATICLIB) \
+ -Wl,--no-whole-archive $(LIBRARIES)
+
+
+install:
+ install -m 644 $(STATICLIB) $(INSTALLDIR)/lib
+ install -m 644 $(LIBNAME) $(INSTALLDIR)/lib
+ install -m 755 $(SHAREDLIB) $(INSTALLDIR)/bin
+ install -m 644 $(HEADER) $(INSTALLDIR)/include
+
+clean:
+ rm -f core Dist/*.* u2dtmp* $(MODULES) $(STATICLIB) $(SHAREDLIB) $(LIBNAME)
+
diff --git a/Makefile.fip b/Makefile.fip
new file mode 100644
index 0000000..216ea55
--- /dev/null
+++ b/Makefile.fip
@@ -0,0 +1,73 @@
+# Linux makefile for FreeImagePlus
+
+# This file can be generated by ./genfipsrclist.sh
+include fipMakefile.srcs
+
+# General configuration variables:
+DESTDIR ?= /
+INCDIR ?= $(DESTDIR)/usr/include
+INSTALLDIR ?= $(DESTDIR)/usr/lib
+
+# Converts cr/lf to just lf
+DOS2UNIX = dos2unix
+
+LIBRARIES = -lstdc++
+
+MODULES = $(SRCS:.c=.o)
+MODULES := $(MODULES:.cpp=.o)
+CFLAGS ?= -O3 -fPIC -fexceptions -fvisibility=hidden -DNO_LCMS
+CFLAGS += $(INCLUDE)
+CXXFLAGS ?= -O3 -fPIC -fexceptions -fvisibility=hidden -Wno-ctor-dtor-privacy
+CXXFLAGS += $(INCLUDE)
+
+ifeq ($(shell sh -c 'uname -m 2>/dev/null || echo not'),x86_64)
+ CFLAGS += -fPIC
+ CXXFLAGS += -fPIC
+endif
+
+TARGET = freeimageplus
+STATICLIB = lib$(TARGET).a
+SHAREDLIB = lib$(TARGET)-$(VER_MAJOR).$(VER_MINOR).so
+LIBNAME = lib$(TARGET).so
+VERLIBNAME = $(LIBNAME).$(VER_MAJOR)
+HEADER = Source/FreeImage.h
+HEADERFIP = Wrapper/FreeImagePlus/FreeImagePlus.h
+
+
+default: all
+
+all: dist
+
+dist: FreeImage
+ cp *.a Dist
+ cp *.so Dist
+ cp Source/FreeImage.h Dist
+ cp Wrapper/FreeImagePlus/FreeImagePlus.h Dist
+
+dos2unix:
+ @$(DOS2UNIX) $(SRCS)
+
+FreeImage: $(STATICLIB) $(SHAREDLIB)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(STATICLIB): $(MODULES)
+ $(AR) r $@ $(MODULES)
+
+$(SHAREDLIB): $(MODULES)
+ $(CC) -shared -Wl,-soname,$(VERLIBNAME) $(LDFLAGS) -o $@ $(MODULES) $(LIBRARIES)
+
+install:
+ install -d $(INCDIR) $(INSTALLDIR)
+ install -m 644 -o root -g root $(HEADER) $(INCDIR)
+ install -m 644 -o root -g root $(HEADERFIP) $(INCDIR)
+ install -m 644 -o root -g root $(STATICLIB) $(INSTALLDIR)
+ install -m 755 -o root -g root $(SHAREDLIB) $(INSTALLDIR)
+
+clean:
+ rm -f core Dist/*.* u2dtmp* $(MODULES) $(STATICLIB) $(SHAREDLIB) $(LIBNAME)
+
diff --git a/Makefile.gnu b/Makefile.gnu
new file mode 100644
index 0000000..3a13339
--- /dev/null
+++ b/Makefile.gnu
@@ -0,0 +1,65 @@
+# Linux makefile for FreeImage
+
+# This file can be generated by ./gensrclist.sh
+include Makefile.srcs
+
+# General configuration variables:
+DESTDIR ?= /
+INCDIR ?= $(DESTDIR)/usr/include
+INSTALLDIR ?= $(DESTDIR)/usr/lib
+
+# Converts cr/lf to just lf
+DOS2UNIX = dos2unix
+
+LIBRARIES = -lstdc++
+
+MODULES = $(SRCS:.c=.o)
+MODULES := $(MODULES:.cpp=.o)
+CFLAGS ?= -O3 -fPIC -fexceptions -fvisibility=hidden -DNO_LCMS -m32
+CFLAGS += $(INCLUDE)
+CXXFLAGS ?= -O3 -fPIC -fexceptions -fvisibility=hidden -Wno-ctor-dtor-privacy -m32
+CXXFLAGS += $(INCLUDE)
+
+#ifeq ($(shell sh -c 'uname -m 2>/dev/null || echo not'),x86_64)
+ #CFLAGS += -fPIC
+ #CXXFLAGS += -fPIC
+#endif
+
+TARGET = freeimage
+STATICLIB = lib$(TARGET).a
+VERLIBNAME = $(LIBNAME).$(VER_MAJOR)
+HEADER = Source/FreeImage.h
+
+
+
+default: all
+
+all: dist
+
+dist: FreeImage
+ cp *.a Dist
+ cp Source/FreeImage.h Dist
+
+dos2unix:
+ @$(DOS2UNIX) $(SRCS) $(INCLS)
+
+FreeImage: $(STATICLIB)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(STATICLIB): $(MODULES)
+ $(AR) r $@ $(MODULES)
+
+install:
+ install -d $(INCDIR) $(INSTALLDIR)
+ install -m 644 -o root -g root $(HEADER) $(INCDIR)
+ install -m 644 -o root -g root $(STATICLIB) $(INSTALLDIR)
+ install -m 755 -o root -g root $(SHAREDLIB) $(INSTALLDIR)
+
+clean:
+ rm -f core Dist/*.* u2dtmp* $(MODULES) $(STATICLIB) $(SHAREDLIB) $(LIBNAME)
+
diff --git a/Makefile.mingw b/Makefile.mingw
new file mode 100644
index 0000000..576ecad
--- /dev/null
+++ b/Makefile.mingw
@@ -0,0 +1,123 @@
+# MinGW makefile for FreeImage
+
+# This file can be generated by ./gensrclist.sh
+include Makefile.srcs
+
+# General configuration variables:
+DESTDIR ?= $(SystemRoot)
+INSTALLDIR ?= $(DESTDIR)/system32
+DISTDIR ?= Dist
+SRCDIR ?= Source
+HEADER = FreeImage.h
+RCFILE = FreeImage.rc
+
+# Uncomment this variable to make a static library. This may
+# also be specified as an environment variable and can hold
+# any of STATIC and SHARED and must be in uppercase letters.
+# Default: SHARED
+#FREEIMAGE_LIBRARY_TYPE = STATIC
+
+# Redefine the compiler (CC defaults to ´cc´ for MinGW's make, however
+# there's only ´gcc´ available with MinGW)
+CC = gcc
+
+# Redefine the linker (we use ´g++´ for linking, since MinGW's ´ld´ comes with
+# wrong (Linux) standard library search paths)
+LD = g++
+
+#Define the dlltool
+DLLTOOL = dlltool
+
+#Define the resource compiler
+RC = windres
+
+# Define the copy command
+CP = cp
+
+# Define the mkdir command
+MD = mkdir
+
+# Define additional libraries needed:
+# libstdc++ is included by default with MinGW, however for
+# WIN32 based builds, LibRawLite needs the winsock libraries.
+LIBRARIES = -lwsock32 -lws2_32
+
+# Define some additional symboles only needed for WIN32 based builds:
+WIN32_CFLAGS = $(LIB_TYPE_FLAGS) -DOPJ_STATIC
+WIN32_CXXFLAGS = $(WIN32_CFLAGS) -DLIBRAW_NODLL -DLIBRAW_LIBRARY_BUILD
+
+WIN32_STATIC_FLAGS = -DFREEIMAGE_LIB
+WIN32_SHARED_FLAGS = -DFREEIMAGE_EXPORTS
+
+MODULES = $(SRCS:.c=.o)
+MODULES := $(MODULES:.cpp=.o)
+RESOURCE = $(RCFILE:.rc=.coff)
+CFLAGS ?= -O3 -fexceptions -DNDEBUG $(WIN32_CFLAGS)
+CFLAGS += $(INCLUDE)
+CXXFLAGS ?= -O3 -fexceptions -Wno-ctor-dtor-privacy -DNDEBUG $(WIN32_CXXFLAGS) -DNO_LCMS
+CXXFLAGS += $(INCLUDE)
+RCFLAGS ?= -DNDEBUG
+LDFLAGS = -s -shared -static -Wl,-soname,$(SOLIBNAME)
+DLLTOOLFLAGS = --add-stdcall-underscore
+
+TARGET = FreeImage
+STATICLIB = $(TARGET).a
+SHAREDLIB = $(TARGET).dll
+IMPORTLIB = $(TARGET).lib
+EXPORTLIB = $(TARGET).exp
+SOLIBNAME = $(SHAREDLIB).$(VER_MAJOR)
+
+DISTSHARED = $(addprefix $(DISTDIR)/, $(SHAREDLIB) $(IMPORTLIB) $(HEADER))
+DISTSTATIC = $(addprefix $(DISTDIR)/, $(STATICLIB) $(HEADER))
+
+# The FreeImage library type defaults to SHARED
+FREEIMAGE_LIBRARY_TYPE ?= SHARED
+
+TARGETLIB = $($(FREEIMAGE_LIBRARY_TYPE)LIB)
+TARGETDIST = $(DIST$(FREEIMAGE_LIBRARY_TYPE))
+LIB_TYPE_FLAGS = $(WIN32_$(FREEIMAGE_LIBRARY_TYPE)_FLAGS)
+
+default: all
+
+all: mkdist
+
+rebuild: clean all
+
+mkdist: FreeImage $(TARGETDIST)
+
+FreeImage: $(TARGETLIB)
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+%.o: %.cpp
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+%.coff: %.rc
+ $(RC) $(RCFLAGS) -o $@ $<
+
+$(DISTDIR)/%: %
+ $(CP) $< $@
+
+$(DISTDIR)/%: $(SRCDIR)/%
+ $(CP) $< $@
+
+$(STATICLIB): $(MODULES)
+ $(AR) rs $@ $(MODULES)
+
+$(IMPORTLIB) $(EXPORTLIB): $(MODULES)
+ $(DLLTOOL) -e $(EXPORTLIB) -l $(IMPORTLIB) -D $(SHAREDLIB) $(DLLTOOLFLAGS) $(MODULES)
+
+$(SHAREDLIB): $(EXPORTLIB) $(RESOURCE)
+ $(LD) $(LDFLAGS) -o $@ $(EXPORTLIB) $(MODULES) $(RESOURCE) $(LIBRARIES)
+
+$(DISTDIR):
+ $(MD) $(DISTDIR)
+
+$(TARGETDIST): $(DISTDIR)
+
+install:
+ $(CP) $(SHAREDLIB) $(INSTALLDIR)
+
+clean:
+ $(RM) core $(DISTDIR)/*.* $(MODULES) $(RESOURCE) $(STATICLIB) $(SHAREDLIB) $(IMPORTLIB) $(EXPORTLIB)
diff --git a/Makefile.osx b/Makefile.osx
new file mode 100644
index 0000000..369d977
--- /dev/null
+++ b/Makefile.osx
@@ -0,0 +1,93 @@
+# -*- Makefile -*-
+# Mac OSX makefile for FreeImage
+
+# This file can be generated by ./gensrclist.sh
+include Makefile.srcs
+
+# General configuration variables:
+CC_PPC = gcc-4.0
+CC_I386 = gcc-4.0
+CPP_PPC = g++-4.0
+CPP_I386 = g++-4.0
+COMPILERFLAGS = -Os -fexceptions -fvisibility=hidden -DNO_LCMS
+COMPILERFLAGS_PPC = -arch ppc
+COMPILERFLAGS_I386 = -arch i386
+COMPILERPPFLAGS = -Wno-ctor-dtor-privacy
+INCLUDE +=
+INCLUDE_PPC = -isysroot /Developer/SDKs/MacOSX10.3.9.sdk
+INCLUDE_I386 = -isysroot /Developer/SDKs/MacOSX10.4u.sdk
+CFLAGS_PPC = $(COMPILERFLAGS) $(COMPILERFLAGS_PPC) $(INCLUDE) $(INCLUDE_PPC)
+CFLAGS_I386 = $(COMPILERFLAGS) $(COMPILERFLAGS_I386) $(INCLUDE) $(INCLUDE_I386)
+CPPFLAGS_PPC = $(COMPILERPPFLAGS) $(CFLAGS_PPC)
+CPPFLAGS_I386 = $(COMPILERPPFLAGS) $(CFLAGS_I386)
+LIBRARIES_PPC = -Wl
+LIBRARIES_I386 = -Wl
+LIBTOOL = libtool
+LIPO = lipo
+
+TARGET = freeimage
+STATICLIB = lib$(TARGET).a
+SHAREDLIB = lib$(TARGET)-$(VER_MAJOR).$(VER_MINOR).dylib
+LIBNAME = lib$(TARGET).$(VER_MAJOR).dylib
+HEADER = Source/FreeImage.h
+
+.SUFFIXES: .o-ppc .o-i386
+MODULES_PPC = $(SRCS:.c=.o-ppc)
+MODULES_I386 = $(SRCS:.c=.o-i386)
+MODULES_PPC := $(MODULES_PPC:.cpp=.o-ppc)
+MODULES_I386 := $(MODULES_I386:.cpp=.o-i386)
+
+PREFIX = /usr/local
+INSTALLDIR = $(PREFIX)/lib
+INCDIR = $(PREFIX)/include
+
+default: all
+
+all: dist
+
+dist: FreeImage
+ cp *.a Dist
+ cp *.dylib Dist
+ cp Source/FreeImage.h Dist
+
+FreeImage: $(STATICLIB) $(SHAREDLIB)
+
+$(STATICLIB): $(STATICLIB)-ppc $(STATICLIB)-i386
+ $(LIPO) -create $(STATICLIB)-ppc $(STATICLIB)-i386 -output $(STATICLIB)
+
+$(STATICLIB)-ppc: $(MODULES_PPC)
+ $(LIBTOOL) -arch_only ppc -o $@ $(MODULES_PPC)
+
+$(STATICLIB)-i386: $(MODULES_I386)
+ $(LIBTOOL) -arch_only i386 -o $@ $(MODULES_I386)
+
+$(SHAREDLIB): $(SHAREDLIB)-ppc $(SHAREDLIB)-i386
+ $(LIPO) -create $(SHAREDLIB)-ppc $(SHAREDLIB)-i386 -output $(SHAREDLIB)
+
+$(SHAREDLIB)-ppc: $(MODULES_PPC)
+ $(CPP_PPC) -arch ppc -dynamiclib $(LIBRARIES_PPC) -o $@ $(MODULES_PPC)
+
+$(SHAREDLIB)-i386: $(MODULES_I386)
+ $(CPP_I386) -arch i386 -dynamiclib $(LIBRARIES_I386) -o $@ $(MODULES_I386)
+
+.c.o-ppc:
+ $(CC_PPC) $(CFLAGS_PPC) -c $< -o $@
+
+.c.o-i386:
+ $(CC_I386) $(CFLAGS_I386) -c $< -o $@
+
+.cpp.o-ppc:
+ $(CPP_PPC) $(CPPFLAGS_PPC) -c $< -o $@
+
+.cpp.o-i386:
+ $(CPP_I386) $(CPPFLAGS_I386) -c $< -o $@
+
+install:
+ install -d -m 755 -o root -g wheel $(INCDIR) $(INSTALLDIR)
+ install -m 644 -o root -g wheel $(HEADER) $(INCDIR)
+ install -m 644 -o root -g wheel $(SHAREDLIB) $(STATICLIB) $(INSTALLDIR)
+ ranlib -sf $(INSTALLDIR)/$(STATICLIB)
+ ln -sf $(SHAREDLIB) $(INSTALLDIR)/$(LIBNAME)
+
+clean:
+ rm -f core Dist/*.* u2dtmp* $(MODULES_PPC) $(MODULES_I386) $(STATICLIB) $(STATICLIB)-ppc $(STATICLIB)-i386 $(SHAREDLIB) $(SHAREDLIB)-ppc $(SHAREDLIB)-i386
diff --git a/Makefile.solaris b/Makefile.solaris
new file mode 100644
index 0000000..a17c68e
--- /dev/null
+++ b/Makefile.solaris
@@ -0,0 +1,65 @@
+# Solaris9 makefile for FreeImage. Tested on Solaris9 with tools from
+# Sunfreeware.com.
+
+# This file can be generated by ./gensrclist.sh
+include Makefile.srcs
+
+# General configuration variables:
+CC = gcc
+CPP = g++
+AR = ar
+
+INSTALLDIR = /usr/local
+
+# Converts cr/lf to just lf
+DOS2UNIX = dos2unix
+
+COMPILERFLAGS = -O3
+LIBRARIES = -lstdc++
+
+MODULES = $(SRCS:.c=.o)
+MODULES := $(MODULES:.cpp=.o)
+CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
+CPPFLAGS = $(COMPILERFLAGS) -Wno-ctor-dtor-privacy $(INCLUDE)
+
+TARGET = freeimage
+STATICLIB = lib$(TARGET).a
+SHAREDLIB = lib$(TARGET)-$(VER_MAJOR).$(VER_MINOR).so
+LIBNAME = lib$(TARGET).so.$(VER_MAJOR)
+
+
+
+default: all
+
+all: dist
+
+dist: FreeImage
+ cp *.a Dist
+ cp *.so Dist
+ cp Source/FreeImage.h Dist
+
+dos2unix:
+ @$(DOS2UNIX) $(SRCS) $(INCLS)
+
+FreeImage: $(STATICLIB) $(SHAREDLIB)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $< -o $@
+
+.cpp.o:
+ $(CPP) $(CPPFLAGS) -c $< -o $@
+
+$(STATICLIB): $(MODULES)
+ $(AR) r $@ $(MODULES)
+
+$(SHAREDLIB): $(MODULES)
+ $(CC) -s -G -Wl,-soname=$(LIBNAME) -o $@ $(MODULES) $(LIBRARIES)
+
+install:
+ install -m 644 -o root -g root Source/FreeImage.h $(INSTALLDIR)/include
+ install -m 644 -o root -g root $(STATICLIB) $(INSTALLDIR)/lib
+ install -m 755 -o root -g root $(SHAREDLIB) $(INSTALLDIR)/lib
+ ln -sf $(SHAREDLIB) $(INSTALLDIR)/lib/$(LIBNAME)
+
+clean:
+ rm -rf core Dist/*.* u2dtmp* $(MODULES) $(STATICLIB) $(SHAREDLIB) $(LIBNAME)
diff --git a/Makefile.srcs b/Makefile.srcs
new file mode 100644
index 0000000..daaa43d
--- /dev/null
+++ b/Makefile.srcs
@@ -0,0 +1,6 @@
+VER_MAJOR = 3
+VER_MINOR = 13.0
+SRCS = ./Source/FreeImage/BitmapAccess.cpp ./Source/FreeImage/ColorLookup.cpp ./Source/FreeImage/FreeImage.cpp ./Source/FreeImage/FreeImageC.c ./Source/FreeImage/FreeImageIO.cpp ./Source/FreeImage/GetType.cpp ./Source/FreeImage/MemoryIO.cpp ./Source/FreeImage/PixelAccess.cpp ././Source/FreeImage/J2KHelper.cpp ./Source/FreeImage/Plugin.cpp ./Source/FreeImage/PluginBMP.cpp ./Source/FreeImage/PluginCUT.cpp ./Source/FreeImage/PluginDDS.cpp ././Source/FreeImage/PluginEXR.cpp ./Source/FreeImage/PluginG3.cpp ./Source/FreeImage/PluginGIF.cpp ./Source/FreeImage/PluginHDR.cpp ./Source/FreeImage/PluginICO.cpp ./Source/FreeImage/PluginIFF.cpp ././Source/FreeImage/PluginJ2K.cpp ././Source/FreeImage/PluginJP2.cpp ./Source/FreeImage/PluginJPEG.cpp ./Source/FreeImage/PluginKOALA.cpp ./Source/FreeImage/PluginMNG.cpp ./Source/FreeImage/PluginPCD.cpp ./Source/FreeImage/PluginPCX.cpp ././Source/FreeImage/PluginPFM.cpp ././Source/FreeImage/PluginPICT.cpp ./Source/FreeImage/PluginPNG.cpp ./Source/FreeImage/PluginPNM.cpp ./Source/FreeImage/PluginPSD.cpp ./Source/FreeImage/PluginRAS.cpp ././Source/FreeImage/PluginRAW.cpp ./Source/FreeImage/PluginSGI.cpp ./Source/FreeImage/PluginTARGA.cpp ./Source/FreeImage/PluginTIFF.cpp ./Source/FreeImage/PluginWBMP.cpp ./Source/FreeImage/PluginXBM.cpp ./Source/FreeImage/PluginXPM.cpp ././Source/FreeImage/PSDParser.cpp ././Source/FreeImage/TIFFLogLuv.cpp ./Source/FreeImage/Conversion.cpp ./Source/FreeImage/Conversion16_555.cpp ./Source/FreeImage/Conversion16_565.cpp ./Source/FreeImage/Conversion24.cpp ./Source/FreeImage/Conversion32.cpp ./Source/FreeImage/Conversion4.cpp ./Source/FreeImage/Conversion8.cpp ./Source/FreeImage/ConversionRGBF.cpp ./Source/FreeImage/ConversionType.cpp ./Source/FreeImage/Halftoning.cpp ./Source/FreeImage/tmoColorConvert.cpp ./Source/FreeImage/tmoDrago03.cpp ././Source/FreeImage/tmoFattal02.cpp ./Source/FreeImage/tmoReinhard05.cpp ./Source/FreeImage/ToneMapping.cpp ./Source/FreeImage/NNQuantizer.cpp ./Source/FreeImage/WuQuantizer.cpp ././Source/DeprecationManager/Deprecated.cpp ./Source/DeprecationManager/DeprecationMgr.cpp ./Source/FreeImage/CacheFile.cpp ./Source/FreeImage/MultiPage.cpp ./Source/FreeImage/ZLibInterface.cpp ./Source/Metadata/Exif.cpp ./Source/Metadata/FIRational.cpp ./Source/Metadata/FreeImageTag.cpp ./Source/Metadata/IPTC.cpp ./Source/Metadata/TagConversion.cpp ./Source/Metadata/TagLib.cpp ./Source/Metadata/XTIFF.cpp ././Source/FreeImageToolkit/Background.cpp ./Source/FreeImageToolkit/BSplineRotate.cpp ./Source/FreeImageToolkit/Channels.cpp ./Source/FreeImageToolkit/ClassicRotate.cpp ./Source/FreeImageToolkit/Colors.cpp ./Source/FreeImageToolkit/CopyPaste.cpp ./Source/FreeImageToolkit/Display.cpp ./Source/FreeImageToolkit/Flip.cpp ./Source/FreeImageToolkit/JPEGTransform.cpp ././Source/FreeImageToolkit/MultigridPoissonSolver.cpp ./Source/FreeImageToolkit/Rescale.cpp ./Source/FreeImageToolkit/Resize.cpp Source/LibJPEG/./jaricom.c Source/LibJPEG/jcapimin.c Source/LibJPEG/jcapistd.c Source/LibJPEG/./jcarith.c Source/LibJPEG/jccoefct.c Source/LibJPEG/jccolor.c Source/LibJPEG/jcdctmgr.c Source/LibJPEG/jchuff.c Source/LibJPEG/jcinit.c Source/LibJPEG/jcmainct.c Source/LibJPEG/jcmarker.c Source/LibJPEG/jcmaster.c Source/LibJPEG/jcomapi.c Source/LibJPEG/jcparam.c Source/LibJPEG/jcprepct.c Source/LibJPEG/jcsample.c Source/LibJPEG/jctrans.c Source/LibJPEG/jdapimin.c Source/LibJPEG/jdapistd.c Source/LibJPEG/./jdarith.c Source/LibJPEG/jdatadst.c Source/LibJPEG/jdatasrc.c Source/LibJPEG/jdcoefct.c Source/LibJPEG/jdcolor.c Source/LibJPEG/jddctmgr.c Source/LibJPEG/jdhuff.c Source/LibJPEG/jdinput.c Source/LibJPEG/jdmainct.c Source/LibJPEG/jdmarker.c Source/LibJPEG/jdmaster.c Source/LibJPEG/jdmerge.c Source/LibJPEG/jdpostct.c Source/LibJPEG/jdsample.c Source/LibJPEG/jdtrans.c Source/LibJPEG/jerror.c Source/LibJPEG/jfdctflt.c Source/LibJPEG/jfdctfst.c Source/LibJPEG/jfdctint.c Source/LibJPEG/jidctflt.c Source/LibJPEG/jidctfst.c Source/LibJPEG/jidctint.c Source/LibJPEG/jmemmgr.c Source/LibJPEG/jmemnobs.c Source/LibJPEG/jquant1.c Source/LibJPEG/jquant2.c Source/LibJPEG/jutils.c Source/LibJPEG/transupp.c Source/LibMNG/libmng_callback_xs.c Source/LibMNG/libmng_chunk_descr.c Source/LibMNG/libmng_chunk_io.c Source/LibMNG/libmng_chunk_prc.c Source/LibMNG/libmng_chunk_xs.c Source/LibMNG/libmng_cms.c Source/LibMNG/libmng_display.c Source/LibMNG/libmng_dither.c Source/LibMNG/libmng_error.c Source/LibMNG/libmng_filter.c Source/LibMNG/libmng_hlapi.c Source/LibMNG/libmng_jpeg.c Source/LibMNG/libmng_object_prc.c Source/LibMNG/libmng_pixels.c Source/LibMNG/libmng_prop_xs.c Source/LibMNG/libmng_read.c Source/LibMNG/libmng_trace.c Source/LibMNG/libmng_write.c Source/LibMNG/libmng_zlib.c Source/LibPNG/png.c Source/LibPNG/pngerror.c Source/LibPNG/pnggccrd.c Source/LibPNG/pngget.c Source/LibPNG/pngmem.c Source/LibPNG/pngpread.c Source/LibPNG/pngread.c Source/LibPNG/pngrio.c Source/LibPNG/pngrtran.c Source/LibPNG/pngrutil.c Source/LibPNG/pngset.c Source/LibPNG/pngtrans.c Source/LibPNG/pngvcrd.c Source/LibPNG/pngwio.c Source/LibPNG/pngwrite.c Source/LibPNG/pngwtran.c Source/LibPNG/pngwutil.c Source/LibTIFF/tif_aux.c Source/LibTIFF/tif_close.c Source/LibTIFF/tif_codec.c Source/LibTIFF/tif_color.c Source/LibTIFF/tif_compress.c Source/LibTIFF/tif_dir.c Source/LibTIFF/tif_dirinfo.c Source/LibTIFF/tif_dirread.c Source/LibTIFF/tif_dirwrite.c Source/LibTIFF/tif_dumpmode.c Source/LibTIFF/tif_error.c Source/LibTIFF/tif_extension.c Source/LibTIFF/tif_fax3.c Source/LibTIFF/tif_fax3sm.c Source/LibTIFF/tif_flush.c Source/LibTIFF/tif_getimage.c Source/LibTIFF/tif_jpeg.c Source/LibTIFF/tif_luv.c Source/LibTIFF/tif_lzw.c Source/LibTIFF/tif_next.c Source/LibTIFF/tif_open.c Source/LibTIFF/tif_packbits.c Source/LibTIFF/tif_pixarlog.c Source/LibTIFF/tif_predict.c Source/LibTIFF/tif_print.c Source/LibTIFF/tif_read.c Source/LibTIFF/tif_strip.c Source/LibTIFF/tif_swab.c Source/LibTIFF/tif_thunder.c Source/LibTIFF/tif_tile.c Source/LibTIFF/tif_version.c Source/LibTIFF/tif_warning.c Source/LibTIFF/tif_write.c Source/LibTIFF/tif_zip.c Source/ZLib/adler32.c Source/ZLib/compress.c Source/ZLib/crc32.c Source/ZLib/deflate.c Source/ZLib/gzio.c Source/ZLib/infback.c Source/ZLib/inffast.c Source/ZLib/inflate.c Source/ZLib/inftrees.c Source/ZLib/trees.c Source/ZLib/uncompr.c Source/ZLib/zutil.c Source/LibOpenJPEG/bio.c Source/LibOpenJPEG/cio.c Source/LibOpenJPEG/dwt.c Source/LibOpenJPEG/event.c Source/LibOpenJPEG/image.c Source/LibOpenJPEG/j2k.c Source/LibOpenJPEG/j2k_lib.c Source/LibOpenJPEG/jp2.c Source/LibOpenJPEG/jpt.c Source/LibOpenJPEG/mct.c Source/LibOpenJPEG/mqc.c Source/LibOpenJPEG/openjpeg.c Source/LibOpenJPEG/pi.c Source/LibOpenJPEG/raw.c Source/LibOpenJPEG/t1.c Source/LibOpenJPEG/t2.c Source/LibOpenJPEG/tcd.c Source/LibOpenJPEG/tgt.c Source/OpenEXR/./IlmImf/ImfAttribute.cpp Source/OpenEXR/./IlmImf/ImfB44Compressor.cpp Source/OpenEXR/./IlmImf/ImfBoxAttribute.cpp Source/OpenEXR/./IlmImf/ImfChannelList.cpp Source/OpenEXR/./IlmImf/ImfChannelListAttribute.cpp Source/OpenEXR/./IlmImf/ImfChromaticities.cpp Source/OpenEXR/./IlmImf/ImfChromaticitiesAttribute.cpp Source/OpenEXR/./IlmImf/ImfCompressionAttribute.cpp Source/OpenEXR/./IlmImf/ImfCompressor.cpp Source/OpenEXR/./IlmImf/ImfConvert.cpp Source/OpenEXR/./IlmImf/ImfCRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfDoubleAttribute.cpp Source/OpenEXR/./IlmImf/ImfEnvmap.cpp Source/OpenEXR/./IlmImf/ImfEnvmapAttribute.cpp Source/OpenEXR/./IlmImf/ImfFloatAttribute.cpp Source/OpenEXR/./IlmImf/ImfFrameBuffer.cpp Source/OpenEXR/./IlmImf/ImfFramesPerSecond.cpp Source/OpenEXR/./IlmImf/ImfHeader.cpp Source/OpenEXR/./IlmImf/ImfHuf.cpp Source/OpenEXR/./IlmImf/ImfInputFile.cpp Source/OpenEXR/./IlmImf/ImfIntAttribute.cpp Source/OpenEXR/./IlmImf/ImfIO.cpp Source/OpenEXR/./IlmImf/ImfKeyCode.cpp Source/OpenEXR/./IlmImf/ImfKeyCodeAttribute.cpp Source/OpenEXR/./IlmImf/ImfLineOrderAttribute.cpp Source/OpenEXR/./IlmImf/ImfLut.cpp Source/OpenEXR/./IlmImf/ImfMatrixAttribute.cpp Source/OpenEXR/./IlmImf/ImfMisc.cpp Source/OpenEXR/./IlmImf/ImfOpaqueAttribute.cpp Source/OpenEXR/./IlmImf/ImfOutputFile.cpp Source/OpenEXR/./IlmImf/ImfPizCompressor.cpp Source/OpenEXR/./IlmImf/ImfPreviewImage.cpp Source/OpenEXR/./IlmImf/ImfPreviewImageAttribute.cpp Source/OpenEXR/./IlmImf/ImfPxr24Compressor.cpp Source/OpenEXR/./IlmImf/ImfRational.cpp Source/OpenEXR/./IlmImf/ImfRationalAttribute.cpp Source/OpenEXR/./IlmImf/ImfRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfRgbaYca.cpp Source/OpenEXR/./IlmImf/ImfRleCompressor.cpp Source/OpenEXR/./IlmImf/ImfScanLineInputFile.cpp Source/OpenEXR/./IlmImf/ImfStandardAttributes.cpp Source/OpenEXR/./IlmImf/ImfStdIO.cpp Source/OpenEXR/./IlmImf/ImfStringAttribute.cpp Source/OpenEXR/./IlmImf/ImfTestFile.cpp Source/OpenEXR/./IlmImf/ImfThreading.cpp Source/OpenEXR/./IlmImf/ImfTileDescriptionAttribute.cpp Source/OpenEXR/./IlmImf/ImfTiledInputFile.cpp Source/OpenEXR/./IlmImf/ImfTiledMisc.cpp Source/OpenEXR/./IlmImf/ImfTiledOutputFile.cpp Source/OpenEXR/./IlmImf/ImfTiledRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfTileOffsets.cpp Source/OpenEXR/./IlmImf/ImfTimeCode.cpp Source/OpenEXR/./IlmImf/ImfTimeCodeAttribute.cpp Source/OpenEXR/./IlmImf/ImfVecAttribute.cpp Source/OpenEXR/./IlmImf/ImfVersion.cpp Source/OpenEXR/./IlmImf/ImfWav.cpp Source/OpenEXR/./IlmImf/ImfZipCompressor.cpp Source/OpenEXR/./Imath/ImathBox.cpp Source/OpenEXR/./Imath/ImathColorAlgo.cpp Source/OpenEXR/./Imath/ImathFun.cpp Source/OpenEXR/./Imath/ImathMatrixAlgo.cpp Source/OpenEXR/./Imath/ImathRandom.cpp Source/OpenEXR/./Imath/ImathShear.cpp Source/OpenEXR/./Imath/ImathVec.cpp Source/OpenEXR/./Iex/IexBaseExc.cpp Source/OpenEXR/./Iex/IexThrowErrnoExc.cpp Source/OpenEXR/./Half/half.cpp Source/OpenEXR/./IlmThread/IlmThread.cpp Source/OpenEXR/./IlmThread/IlmThreadMutex.cpp Source/OpenEXR/./IlmThread/IlmThreadPool.cpp Source/OpenEXR/./IlmThread/IlmThreadSemaphore.cpp Source/LibRawLite/./internal/dcraw_common.cpp Source/LibRawLite/./internal/dcraw_fileio.cpp Source/LibRawLite/./src/libraw_c_api.cpp Source/LibRawLite/./src/libraw_cxx.cpp
+INCLS = ./Source/FreeImage.h ./Source/OpenEXR/Half/halfFunction.h ./Source/OpenEXR/Half/toFloat.h ./Source/OpenEXR/Half/halfLimits.h ./Source/OpenEXR/Half/eLut.h ./Source/OpenEXR/Half/half.h ./Source/OpenEXR/IlmImf/ImfRationalAttribute.h ./Source/OpenEXR/IlmImf/b44ExpLogTable.h ./Source/OpenEXR/IlmImf/ImfTiledOutputFile.h ./Source/OpenEXR/IlmImf/ImfName.h ./Source/OpenEXR/IlmImf/ImfHeader.h ./Source/OpenEXR/IlmImf/ImfKeyCode.h ./Source/OpenEXR/IlmImf/ImfTileDescription.h ./Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.h ./Source/OpenEXR/IlmImf/ImfLineOrder.h ./Source/OpenEXR/IlmImf/ImfVecAttribute.h ./Source/OpenEXR/IlmImf/ImfPxr24Compressor.h ./Source/OpenEXR/IlmImf/ImfStdIO.h ./Source/OpenEXR/IlmImf/ImfTestFile.h ./Source/OpenEXR/IlmImf/ImfScanLineInputFile.h ./Source/OpenEXR/IlmImf/ImfRleCompressor.h ./Source/OpenEXR/IlmImf/ImfPixelType.h ./Source/OpenEXR/IlmImf/ImfRgbaYca.h ./Source/OpenEXR/IlmImf/ImfTileOffsets.h ./Source/OpenEXR/IlmImf/ImfLut.h ./Source/OpenEXR/IlmImf/ImfCompressionAttribute.h ./Source/OpenEXR/IlmImf/ImfStringAttribute.h ./Source/OpenEXR/IlmImf/ImfTiledMisc.h ./Source/OpenEXR/IlmImf/ImfPreviewImage.h ./Source/OpenEXR/IlmImf/ImfCompression.h ./Source/OpenEXR/IlmImf/ImfOutputFile.h ./Source/OpenEXR/IlmImf/ImfStandardAttributes.h ./Source/OpenEXR/IlmImf/ImfVersion.h ./Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.h ./Source/OpenEXR/IlmImf/ImfTiledInputFile.h ./Source/OpenEXR/IlmImf/ImfLineOrderAttribute.h ./Source/OpenEXR/IlmImf/ImfBoxAttribute.h ./Source/OpenEXR/IlmImf/ImfEnvmapAttribute.h ./Source/OpenEXR/IlmImf/ImfRgbaFile.h ./Source/OpenEXR/IlmImf/ImfMatrixAttribute.h ./Source/OpenEXR/IlmImf/ImfEnvmap.h ./Source/OpenEXR/IlmImf/ImfChannelList.h ./Source/OpenEXR/IlmImf/ImfInputFile.h ./Source/OpenEXR/IlmImf/ImfFramesPerSecond.h ./Source/OpenEXR/IlmImf/ImfAttribute.h ./Source/OpenEXR/IlmImf/ImfTiledRgbaFile.h ./Source/OpenEXR/IlmImf/ImfFrameBuffer.h ./Source/OpenEXR/IlmImf/ImfChromaticities.h ./Source/OpenEXR/IlmImf/ImfCompressor.h ./Source/OpenEXR/IlmImf/ImfMisc.h ./Source/OpenEXR/IlmImf/ImfOpaqueAttribute.h ./Source/OpenEXR/IlmImf/ImfIO.h ./Source/OpenEXR/IlmImf/ImfThreading.h ./Source/OpenEXR/IlmImf/ImfInt64.h ./Source/OpenEXR/IlmImf/ImfIntAttribute.h ./Source/OpenEXR/IlmImf/ImfPizCompressor.h ./Source/OpenEXR/IlmImf/ImfWav.h ./Source/OpenEXR/IlmImf/ImfFloatAttribute.h ./Source/OpenEXR/IlmImf/ImfAutoArray.h ./Source/OpenEXR/IlmImf/ImfRgba.h ./Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.h ./Source/OpenEXR/IlmImf/ImfXdr.h ./Source/OpenEXR/IlmImf/ImfArray.h ./Source/OpenEXR/IlmImf/ImfChannelListAttribute.h ./Source/OpenEXR/IlmImf/ImfConvert.h ./Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.h ./Source/OpenEXR/IlmImf/ImfZipCompressor.h ./Source/OpenEXR/IlmImf/ImfB44Compressor.h ./Source/OpenEXR/IlmImf/ImfRational.h ./Source/OpenEXR/IlmImf/ImfDoubleAttribute.h ./Source/OpenEXR/IlmImf/ImfTimeCode.h ./Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.h ./Source/OpenEXR/IlmImf/ImfHuf.h ./Source/OpenEXR/IlmImf/ImfCRgbaFile.h ./Source/OpenEXR/OpenEXRConfig.h ./Source/OpenEXR/Iex/IexMacros.h ./Source/OpenEXR/Iex/IexMathExc.h ./Source/OpenEXR/Iex/Iex.h ./Source/OpenEXR/Iex/IexThrowErrnoExc.h ./Source/OpenEXR/Iex/IexErrnoExc.h ./Source/OpenEXR/Iex/IexBaseExc.h ./Source/OpenEXR/Imath/ImathBoxAlgo.h ./Source/OpenEXR/Imath/ImathMath.h ./Source/OpenEXR/Imath/ImathPlane.h ./Source/OpenEXR/Imath/ImathRandom.h ./Source/OpenEXR/Imath/ImathInterval.h ./Source/OpenEXR/Imath/ImathLine.h ./Source/OpenEXR/Imath/ImathLimits.h ./Source/OpenEXR/Imath/ImathShear.h ./Source/OpenEXR/Imath/ImathPlatform.h ./Source/OpenEXR/Imath/ImathBox.h ./Source/OpenEXR/Imath/ImathFrustum.h ./Source/OpenEXR/Imath/ImathGL.h ./Source/OpenEXR/Imath/ImathRoots.h ./Source/OpenEXR/Imath/ImathLineAlgo.h ./Source/OpenEXR/Imath/ImathMatrixAlgo.h ./Source/OpenEXR/Imath/ImathVec.h ./Source/OpenEXR/Imath/ImathVecAlgo.h ./Source/OpenEXR/Imath/ImathSphere.h ./Source/OpenEXR/Imath/ImathGLU.h ./Source/OpenEXR/Imath/ImathFun.h ./Source/OpenEXR/Imath/ImathMatrix.h ./Source/OpenEXR/Imath/ImathExc.h ./Source/OpenEXR/Imath/ImathHalfLimits.h ./Source/OpenEXR/Imath/ImathColor.h ./Source/OpenEXR/Imath/ImathInt64.h ./Source/OpenEXR/Imath/ImathFrame.h ./Source/OpenEXR/Imath/ImathQuat.h ./Source/OpenEXR/Imath/ImathColorAlgo.h ./Source/OpenEXR/Imath/ImathEuler.h ./Source/OpenEXR/IlmThread/IlmThread.h ./Source/OpenEXR/IlmThread/IlmThreadMutex.h ./Source/OpenEXR/IlmThread/IlmThreadSemaphore.h ./Source/OpenEXR/IlmThread/IlmThreadPool.h ./Source/OpenEXR/IlmBaseConfig.h ./Source/CacheFile.h ./Source/LibOpenJPEG/bio.h ./Source/LibOpenJPEG/tgt.h ./Source/LibOpenJPEG/t1.h ./Source/LibOpenJPEG/fix.h ./Source/LibOpenJPEG/j2k.h ./Source/LibOpenJPEG/t1_luts.h ./Source/LibOpenJPEG/j2k_lib.h ./Source/LibOpenJPEG/cio.h ./Source/LibOpenJPEG/pi.h ./Source/LibOpenJPEG/event.h ./Source/LibOpenJPEG/opj_includes.h ./Source/LibOpenJPEG/int.h ./Source/LibOpenJPEG/opj_malloc.h ./Source/LibOpenJPEG/image.h ./Source/LibOpenJPEG/jpt.h ./Source/LibOpenJPEG/raw.h ./Source/LibOpenJPEG/mct.h ./Source/LibOpenJPEG/jp2.h ./Source/LibOpenJPEG/t2.h ./Source/LibOpenJPEG/mqc.h ./Source/LibOpenJPEG/tcd.h ./Source/LibOpenJPEG/openjpeg.h ./Source/LibOpenJPEG/dwt.h ./Source/FreeImageToolkit/Filters.h ./Source/FreeImageToolkit/Resize.h ./Source/Utilities.h ./Source/LibRawLite/libraw/libraw_types.h ./Source/LibRawLite/libraw/libraw_version.h ./Source/LibRawLite/libraw/libraw_const.h ./Source/LibRawLite/libraw/libraw_alloc.h ./Source/LibRawLite/libraw/libraw_datastream.h ./Source/LibRawLite/libraw/libraw_internal.h ./Source/LibRawLite/libraw/libraw.h ./Source/LibRawLite/internal/defines.h ./Source/LibRawLite/internal/var_defines.h ./Source/LibRawLite/internal/libraw_internal_funcs.h ./Source/LibJPEG/jversion.h ./Source/LibJPEG/jmorecfg.h ./Source/LibJPEG/transupp.h ./Source/LibJPEG/jmemsys.h ./Source/LibJPEG/jdct.h ./Source/LibJPEG/jconfig.h ./Source/LibJPEG/jinclude.h ./Source/LibJPEG/jpeglib.h ./Source/LibJPEG/cderror.h ./Source/LibJPEG/jpegint.h ./Source/LibJPEG/cdjpeg.h ./Source/LibJPEG/jerror.h ./Source/LibMNG/libmng_display.h ./Source/LibMNG/libmng_dither.h ./Source/LibMNG/libmng_trace.h ./Source/LibMNG/libmng_chunks.h ./Source/LibMNG/libmng_filter.h ./Source/LibMNG/libmng_read.h ./Source/LibMNG/libmng_objects.h ./Source/LibMNG/libmng_cms.h ./Source/LibMNG/libmng_chunk_io.h ./Source/LibMNG/libmng_jpeg.h ./Source/LibMNG/libmng_memory.h ./Source/LibMNG/libmng_zlib.h ./Source/LibMNG/libmng_object_prc.h ./Source/LibMNG/libmng_write.h ./Source/LibMNG/libmng_data.h ./Source/LibMNG/libmng_conf.h ./Source/LibMNG/libmng_types.h ./Source/LibMNG/libmng_chunk_descr.h ./Source/LibMNG/libmng_pixels.h ./Source/LibMNG/libmng_chunk_prc.h ./Source/LibMNG/libmng_error.h ./Source/LibMNG/libmng.h ./Source/LibPNG/png.h ./Source/LibPNG/pngconf.h ./Source/Plugin.h ./Source/Quantizers.h ./Source/FreeImageIO.h ./Source/LibTIFF/tiff.h ./Source/LibTIFF/tif_config.vc.h ./Source/LibTIFF/tiffvers.h ./Source/LibTIFF/tif_dir.h ./Source/LibTIFF/tif_predict.h ./Source/LibTIFF/tif_config.wince.h ./Source/LibTIFF/tiffconf.vc.h ./Source/LibTIFF/tiffconf.wince.h ./Source/LibTIFF/t4.h ./Source/LibTIFF/tiffiop.h ./Source/LibTIFF/uvcode.h ./Source/LibTIFF/tiffio.h ./Source/LibTIFF/tif_config.h ./Source/LibTIFF/tif_fax3.h ./Source/ZLib/inflate.h ./Source/ZLib/trees.h ./Source/ZLib/zconf.h ./Source/ZLib/zlib.h ./Source/ZLib/crc32.h ./Source/ZLib/inftrees.h ./Source/ZLib/zutil.h ./Source/ZLib/inffixed.h ./Source/ZLib/inffast.h ./Source/ZLib/zconf.in.h ./Source/ZLib/deflate.h ./Source/FreeImage/PSDParser.h ./Source/ToneMapping.h ./Source/DeprecationManager/DeprecationMgr.h ./Source/Metadata/FIRational.h ./Source/Metadata/FreeImageTag.h ./Wrapper/FreeImage.NET/cpp/FreeImageIO/resource.h ./Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.h ./Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.h ./Wrapper/FreeImagePlus/test/fipTest.h ./Wrapper/FreeImagePlus/FreeImagePlus.h ./Examples/Generic/FIIO_Mem.h ./Examples/OpenGL/TextureManager/TextureManager.h ./Examples/Plugin/PluginCradle.h ./TestAPI/TestSuite.h
+
+INCLUDE = -I. -ISource -ISource/Metadata -ISource/FreeImageToolkit -ISource/LibJPEG -ISource/LibMNG -ISource/LibPNG -ISource/LibTIFF -ISource/ZLib -ISource/LibOpenJPEG -ISource/OpenEXR -ISource/OpenEXR/Half -ISource/OpenEXR/Iex -ISource/OpenEXR/IlmImf -ISource/OpenEXR/IlmThread -ISource/OpenEXR/Imath -ISource/LibRawLite -ISource/LibRawLite/dcraw -ISource/LibRawLite/internal -ISource/LibRawLite/libraw -ISource/LibRawLite/src
diff --git a/README.linux b/README.linux
new file mode 100644
index 0000000..0e8659e
--- /dev/null
+++ b/README.linux
@@ -0,0 +1,50 @@
+Release Notes
+--------------
+This version of the library has been tested under the following OS:
+- RedHat Linux 7.3, 8.0 and 9.0
+- Fedora Core 2
+- SuSE Linux Enterprise 8 and SuSE 9.0.
+- Debian 4
+
+You *do not* need to have any other third party library (libjpeg, libpng, libtiff, libmng and zlib)
+installed on your /usr/lib directory in order to compile and use the library.
+FreeImage uses its own versions of these libraries. This way, you can be sure that FreeImage will
+always use the latest version of each third party library.
+
+The FreeImage makefile makes use of the gcc "-fvisibility=hidden" in order to avoid incompatibilities between
+internal third party libraries and the OS libraries. You may have to remove this option if you're running an
+old version of gcc. See also http://gcc.gnu.org/wiki/Visibility
+
+You should be able to link progams with the -lfreeimage option after the library is compiled and installed.
+You can also statically link with libfreeimage.a.
+If you use a really old version of gcc and it chokes on the CRs in the file, you can type 'make dos2unix'
+to run all of the files through dos2unix which converts CRLF to LF. This no longer appears to be required
+for RedHat 7.3 or 9.
+
+Please let me know how this works for you under other Linux distributions or any other *nix.
+
+Herve Drolon
+FreeImage Project Manager
+
+Installation
+------------
+Note: You will need to have root privileges in order to install the library in the /usr/lib directory.
+The installation process is as simple as this :
+1) Enter the FreeImage directory
+2) Build the distribution :
+make
+make install
+3) Clean all files produced during the build process
+make clean
+
+Compiling FreeImagePlus
+-----------------------
+FreeImagePlus is a C++ wrapper for FreeImage.
+To compile FreeImage as a C++ library, follow these steps :
+1) Enter the FreeImage directory
+2) Build the distribution :
+make -f Makefile.fip
+make -f Makefile.fip install
+3) Clean all files produced during the build process
+make -f Makefile.fip clean
+
diff --git a/README.minGW b/README.minGW
new file mode 100644
index 0000000..30195c3
--- /dev/null
+++ b/README.minGW
@@ -0,0 +1,236 @@
+=====================================================================
+Using the FreeImage library with the MinGW Compiler Suite
+=====================================================================
+
+This file describes how to use the precompiled FreeImage library
+FreeImage.dll with the MinGW port of the GNU Compiler Collection
+(GCC), how to build this library from source using MinGW and how
+to use this MinGW-built library with Microsoft Visual Studio.
+
+Contents:
+
+I. Prerequisites
+
+1. Using the precompiled FreeImage library with MinGW
+
+2. Building the FreeImage library with MinGW
+
+3. Using the MinGW FreeImage library with Microsoft Visual Studio
+
+4. Useful links
+
+
+---------------------------------------------------------------------
+I. Prerequisites
+=====================================================================
+
+The procedures described in this document have been developed and
+tested using the following free tools:
+
+1. MinGW GCC Version 4.4.0 (Core and C++ including required libs)
+2. MinGW GNU Binutils Version 2.19.1
+3. MinGW GNU Make Version 3.81-20080326-3
+4. MinGW Runtime Version 3.15.2
+5. MinGW API for MS-Windows Version 3.13
+6. GnuWin32 Package CoreUtils Version 5.3.0 (only for building)
+7. GnuWin32 Package Sed Version 4.2 (only for creating the GCC
+ import library)*
+
+* Sed is only needed to create a GCC-native import library from
+ the MSVC import library FreeImage.lib. However, since MinGW now
+ supports linking against MSVC lib files, this process seems to
+ be obsolete. See section 1.
+
+Basically, no version dependent capabilities are used so, this
+should also work with older versions of the tools mentioned above.
+Similarly, the GnuWin32 packages (which I just prefer over MSYS)
+could likely be replaced by a properly installed MSYS environment.
+
+Furthermore, the following preconditions should be met:
+
+1. The folders 'bin' under both the MinGW and the GnuWin32
+ installation directory should have been added to the PATH
+ environment variable. Likely it is best adding these
+ directories permanently to PATH through the System
+ Properties dialog on the Control Panel.
+
+2. The MinGW Make package only provides a 'mingw32-make.exe'
+ executable. There is no alias 'make.exe'. However, make is
+ preconfigured to use 'make' as the default $(MAKE) command.
+ This seems to be a bug in the MinGW GNU Make distribution.
+ Thus, a copy of 'mingw32-make.exe' named 'make.exe' should
+ be placed into MinGW's 'bin' directory.
+
+
+
+---------------------------------------------------------------------
+1. Using the precompiled FreeImage library with MinGW
+=====================================================================
+
+When using functions from C/C++, that reside in a DLL, the linker
+needs a so called import library, which specifies, how to
+dynamically link these external functions during runtime. However,
+different linkers use different types or formats of these import
+libraries.
+
+Since the precompiled FreeImage library was build with Microsoft
+Visual Studio, in the past, some extra work was required to use it
+from MinGW. An import library, that was compatible with GNU ld,
+must have been created first.
+
+However, for several MinGW versions, the GNU linker ld also
+supports linking against Microsoft Visual C++ import libraries
+directly. So, this effectively makes any circulating HOWTO's on
+how to create a GCC-compatible import library from a MSVC lib file
+more or less obsolete. Additionally, MinGW does not require the
+GCC/Linux usual lib prefix for libraries, so linking with MinGW
+against the precompiled FreeImage DLL is as easy as with MSVC:
+
+1.) Open a DOS shell (run application cmd.exe)
+
+2.) Ensure, that the 'bin' folder of MinGW is added to the PATH
+ environment variable (see Prerequisites).
+
+3.) Link directly against the supplied lib file:
+
+ C:\>gcc -oFreeImageTest.exe FreeImageTest.c -lFreeImage
+
+Nonetheless, for the sake of completeness, the following steps
+describe how to create a native GCC import library:
+
+1.) Open a DOS shell (run application cmd.exe)
+
+2.) Ensure, that the 'bin' folders of both MinGW and GnuWin32 are
+ added to the PATH environment variable (see Prerequisites).
+
+3.) Create a .def file 'libfreeimage.def', that contains all symbols
+ exported by the FreeImage library:
+
+ C:\>pexports FreeImage.dll | sed "s/^_//" > libfreeimage.def
+
+4.) Create the GCC compatible import library 'libfreeimage.a':
+
+ C:\>dlltool --add-underscore -d libfreeimage.def -l libfreeimage.a
+
+5.) Use this library to link against with GCC:
+
+ C:\>gcc -oFreeImageTest.exe FreeImageTest.c -lfreeimage
+
+
+
+---------------------------------------------------------------------
+2. Building the FreeImage library with MinGW
+=====================================================================
+
+You *do not* need to have any other third party library (like
+libjpeg, libpng, libtiff, libmng and zlib and others) installed on
+your system in order to compile and use the library. FreeImage uses
+its own versions of these libraries. This way, you can be sure that
+FreeImage will always use the latest and properly tested versions
+of of these third party libraries.
+
+In order to build the FreeImage library under Windows with MinGW
+(GCC), ensure that all the prerequisites mentioned above are met.
+The MinGW makefile aims to build a Windows DLL, that differs as
+least as possible from the precompiled library that comes with the
+FreeImage distribution. Thus, the build process also includes the
+DLL version resource as well as the __stdcall attribute for all the
+exported functions, including the MSVC-like function decorations
+_FuncName@nn.
+
+When building the FreeImage DLL, of course, an import library is
+generated, too. However, this input library is not in GCC's native
+format, but in MSVC lib format, which makes it usable from both
+MinGW and Microsoft Visual Studio with no further processing.
+
+The MinGW makefile can also be used to build a static library.
+However, due to the different function export attributes needed
+for both the dynamic and the shared library (DLL), this requires
+a separate invocation of make, which in turn needs to rebuild every
+source file after switching from dynamic to static and vice versa.
+So, a 'make clean' is required each time, the library type is
+changed.
+
+The type of library to build is specified by a variable named
+FREEIMAGE_LIBRARY_TYPE, which may either be set directly in the
+Makefile.mingw near line 18 or may be specified as an environment
+variable. This variable may either take SHARED or STATIC to build
+a dynamic link library (DLL) or a static library respectively.
+Since this value is used to dynamically form the actual make target
+internally, only uppercase values are valid. Defaults to SHARED.
+
+The MinGW makefile also supports the 'install' target. However,
+this only copies the FreeImage dynamic link library (DLL) from the
+Dist folder into the %SystemRoot%\system32 folder. So, invoking this
+target only makes sense, if the DLL has been built before.
+
+Since there is neither a common system wide 'include' nor a 'lib'
+directory available under Windows, the FreeImage header file
+FreeImage.h as well as both the static library and the DLL import
+library FreeImage.lib just remain in the 'Dist' folder.
+
+The following procedure creates the FreeImage dynamic link library
+(DLL) from the sources, installs it and also creates a static
+FreeImage library:
+
+1.) Open a DOS shell (run application cmd.exe)
+
+2.) Ensure, that the 'bin' folders of both MinGW and GnuWin32 are
+ added to the PATH environment variable (see Prerequisites).
+
+3.) Create the FreeImage dynamic link library (DLL):
+
+ C:\>make
+
+4.) Install the FreeImage dynamic link library (DLL):
+
+ C:\>make install
+
+5.) Clean all files produced by the recent build process:
+
+ C:\>make clean
+
+6.) Create a static FreeImage library:
+
+ C:\>set FREEIMAGE_LIBRARY_TYPE=STATIC
+ C:\>make
+
+You should be able to link progams with the -lFreeImage option
+after the shared library is compiled and installed. You can also
+link statically against FreeImage.a from MinGW.
+
+
+
+---------------------------------------------------------------------
+3. Using the MinGW FreeImage library with Microsoft Visual Studio
+=====================================================================
+
+Since the MinGW makefile creates an import library in MSVC's lib
+format, the produced shared library (DLL) can be used from both
+MinGW and Microsoft Visual Studio with no further adaption. Just
+link to the import library FreeImage.lib from either MinGW or
+Microsoft Visual Studio.
+
+
+
+---------------------------------------------------------------------
+4. Useful links
+=====================================================================
+
+- The MinGW homepage:
+ http://www.mingw.org/
+
+- The GnuWin32 homepage:
+ http://gnuwin32.sourceforge.net/
+
+- The GCC homepage and online documentation:
+ http://gcc.gnu.org/
+ http://gcc.gnu.org/onlinedocs/
+
+- The GNU Binutils homepage and online documentation:
+ http://www.gnu.org/software/binutils/
+ http://sourceware.org/binutils/docs-2.19/
+
+- The GNU Make homepage and online documentation:
+ http://www.gnu.org/software/make/
+ http://www.gnu.org/software/make/manual/make.html
diff --git a/README.osx b/README.osx
new file mode 100644
index 0000000..16aba34
--- /dev/null
+++ b/README.osx
@@ -0,0 +1,44 @@
+Release Notes
+--------------
+This version of the library has been tested under OSX 10.3.9 PPC and OSX 10.4.8 Intel.
+
+While the makefiles will make a .dylib and a .a, it is recommended to simply staticly link with the .a file.
+
+FreeImage is now built as a Universal Binary and targets the 10.3.9 SDK for PPC and the 10.4u SDK for i386.
+This means that you must have both of these SDKs installed and that you must be running on OSX 10.4+ to build FreeImage.
+The library will run on 10.3 PPC, but probably not 10.2 or below anymore. wchar.h did not exist on 10.2.
+
+FreeImage is now built with gcc 4.0 and will thus only run on 10.3.9 or above (some libraries may not exist on 10.3.8 and below).
+
+The FreeImage makefile makes use of the gcc "-fvisibility=hidden" in order to avoid incompatibilities between
+internal third party libraries and the OS libraries. This feature is available with gcc 4 or greater.
+
+
+Ryan Rubley
+
+Building the Library
+--------------------
+Makefile detects the environment by calling 'uname'. Assuming this reports 'Darwin' on your system, Makefile will automatically
+defer commands to Makefile.osx. If this doesn't work, type 'make -f Makefile.osx' in place of just 'make'
+
+The build process is as simple as this:
+1) Enter the FreeImage directory
+2) Build the distribution:
+make
+3) The libraries and header will be in the Dist directory when the build is finished
+
+To install FreeImage in the /usr/local/lib and /usr/local/include directories (not recommended):
+make install
+
+To clean all files produced during the build process:
+make clean
+
+
+Additional notes
+----------------
+
+Building on Mac OS X Leopard :
+
+Install the xcode dev tools from the Leopard disk.
+When installing the dev tools make sure to have installed 10.3.9 SDK (it's not selected by default).
+
diff --git a/README.solaris b/README.solaris
new file mode 100644
index 0000000..bf6431c
--- /dev/null
+++ b/README.solaris
@@ -0,0 +1,67 @@
+Release Notes
+--------------
+Hey folks,
+
+I just went through the process of building and using the freeimage library
+on Solaris 9. Things don't work out of the box so I thought I would share my
+experiences in case someone else wants to do the same.
+
+I'm using Solaris 9, and I have installed all the development libraries, make,
+and the gcc 3.3.2 found on sunfreeware.com.
+
+You have to use the make from sunfreeware because the Solaris 9 make program
+chokes hard on FreeImages makefiles.
+
+First thing I had to do was modify the main FreeImage makefile:
+
+1. go to the $(SHAREDLIB): line and replace the $(CC) line with the following.
+(there are 2 corrections)
+
+$(CC) -s -G -Wl,-soname=$(LIBNAME) -o $@ $(MODULES) $(LIBRARIES)
+
+The two changes are -G instead of -shared, and the = sign instead of a comma
+after the -soname.
+
+2. change INSTALLDIR = /usr/lib to INSTALLDIR = /usr/local/lib
+
+This is because the sunfreeware tools assume the libs being built will reside
+in /usr/local/lib and thus set the default linker search paths to that. Another
+solution for this would be to use the -R and -L linker options, but I chose
+the easy way :)
+
+That's it! You can now use freeimage.
+
+Also, if you have an autoconf/automake project that links against FreeImage,
+you can use the following in your configure.in, it works rather well for me:
+
+AC_CHECK_LIB(freeimage-3.5.0, FreeImage_Initialise, [],
+ [AC_MSG_ERROR([libfreeimage-3.5.0.so required and missing. See
+http://freeimage.sourceforge.net.]) ])
+
+the AC_CHECK_LIB macro will not only find the library, it will automatically
+link against it as well so you dont have to add it to your Makefile.am.
+
+I hope this helps someone!
+
+---
+ogtharox at users.sourceforge.net
+
+
+Installation
+------------
+Note: You will need to have root privileges in order to install the library in the /usr/local/lib directory.
+The installation process is as simple as this :
+1) Enter the FreeImage directory
+2) Build the distribution :
+make -f Makefile.solaris
+make -f Makefile.solaris install
+3) Clean all files produced during the build process
+make -f Makefile.solaris clean
+
+Release Notes for Solaris/Sparc
+--------------------------------
+Under Solaris/Sparc, you will need to modify the following line :
+COMPILERFLAGS = -O3
+modified into
+COMPILERFLAGS = -O3 -DBYTE_ORDER=BIG_ENDIAN -D__BIG_ENDIAN__
+
diff --git a/Source/CacheFile.h b/Source/CacheFile.h
new file mode 100644
index 0000000..eaf82d8
--- /dev/null
+++ b/Source/CacheFile.h
@@ -0,0 +1,92 @@
+// ==========================================================
+// Multi-Page functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef CACHEFILE_H
+#define CACHEFILE_H
+
+// ----------------------------------------------------------
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+
+static const int CACHE_SIZE = 32;
+static const int BLOCK_SIZE = (64 * 1024) - 8;
+
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif // _WIN32
+
+struct Block {
+ unsigned nr;
+ unsigned next;
+ BYTE *data;
+};
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif // _WIN32
+
+// ----------------------------------------------------------
+
+class CacheFile {
+ typedef std::list<Block *> PageCache;
+ typedef std::list<Block *>::iterator PageCacheIt;
+ typedef std::map<int, PageCacheIt> PageMap;
+ typedef std::map<int, PageCacheIt>::iterator PageMapIt;
+
+public :
+ CacheFile(const char *filename, BOOL keep_in_memory);
+ ~CacheFile();
+
+ BOOL open();
+ void close();
+ BOOL readFile(BYTE *data, int nr, int size);
+ int writeFile(BYTE *data, int size);
+ void deleteFile(int nr);
+
+private :
+ void cleanupMemCache();
+ int allocateBlock();
+ Block *lockBlock(int nr);
+ BOOL unlockBlock(int nr);
+ BOOL deleteBlock(int nr);
+
+private :
+ FILE *m_file;
+ std::string m_filename;
+ std::list<int> m_free_pages;
+ PageCache m_page_cache_mem;
+ PageCache m_page_cache_disk;
+ PageMap m_page_map;
+ int m_page_count;
+ Block *m_current_block;
+ BOOL m_keep_in_memory;
+};
+
+#endif // CACHEFILE_H
diff --git a/Source/DeprecationManager/Deprecated.cpp b/Source/DeprecationManager/Deprecated.cpp
new file mode 100644
index 0000000..8ca5e71
--- /dev/null
+++ b/Source/DeprecationManager/Deprecated.cpp
@@ -0,0 +1,36 @@
+// ==========================================================
+// Deprecated functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+
+#include "../DeprecationManager/DeprecationMgr.h"
+
+// ----------------------------------------------------------
+
+FIBITMAP *DLL_CALLCONV
+FreeImage_RotateClassic(FIBITMAP *dib, double angle) {
+#ifdef _WIN32
+ DEPRECATE("FreeImage_RotateClassic()", "FreeImage_Rotate()")
+#endif // _WIN32
+ return FreeImage_Rotate(dib, angle, NULL);
+}
+
diff --git a/Source/DeprecationManager/DeprecationMgr.cpp b/Source/DeprecationManager/DeprecationMgr.cpp
new file mode 100644
index 0000000..bf82dfa
--- /dev/null
+++ b/Source/DeprecationManager/DeprecationMgr.cpp
@@ -0,0 +1,103 @@
+// ==========================================================
+// Deprecation Manager
+//
+// Design and implementation by
+// - Noel Llopis (Game Programming Gems II)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "DeprecationMgr.h"
+
+// ==========================================================
+
+DeprecationMgr::DeprecationMgr() {
+}
+
+DeprecationMgr::~DeprecationMgr() {
+#ifdef _WIN32
+ if (!m_functions.empty()) {
+ OutputDebugString( "*************************************************************************************\n" );
+ OutputDebugString( "This is a warning, because you use one or more deprecated functions.\nContinuing to use these functions might eventually render your program uncompilable.\nThe following functions are deprecated:\n\n" );
+
+ for (std::map<const char *, DeprecatedFunction>::iterator i = m_functions.begin(); i != m_functions.end(); ++i) {
+ DeprecatedFunction *function = &((*i).second);
+
+ char txt[255];
+
+ sprintf(txt, " * %s called from %i different places. Instead use %s.\n", function->old_function_name, function->called_from.size(), function->new_function_name);
+
+ OutputDebugString(txt);
+ }
+
+ OutputDebugString( "*************************************************************************************\n" );
+
+ m_functions.clear();
+ }
+#endif // _WIN32
+}
+
+// ==========================================================
+
+DeprecationMgr *
+DeprecationMgr::GetInstance() {
+ static DeprecationMgr Instance;
+ return &Instance;
+}
+
+// ==========================================================
+
+void
+DeprecationMgr::AddDeprecatedFunction(const char *old_function_name, const char *new_function_name, const void *frame_ptr) {
+#ifdef _WIN32
+ int *preturn = (int *)frame_ptr + 1; // usual return address @ [ebp+4]
+ int called_from = IsBadReadPtr(preturn, 4) ? 0 : *preturn;
+
+ // check if this function was already listed as deprecated
+ // if it wasn't, make a new entry for it
+ // if it was, keep track of where it's called from.
+
+ std::map<const char *, DeprecatedFunction>::iterator existing_function = m_functions.find(old_function_name);
+
+ if (existing_function == m_functions.end()) {
+ DeprecatedFunction function;
+
+ function.old_function_name = old_function_name;
+ function.new_function_name = new_function_name;
+ function.called_from.insert(called_from);
+
+ m_functions[old_function_name] = function;
+ } else {
+ // since we're keeping track of the addresses this function
+ // was called from in a set, we don't need to check whether we've
+ // already added the address.
+
+ DeprecatedFunction *function = &((*existing_function).second);
+
+ function->called_from.insert(called_from);
+ }
+#endif // _WIN32
+}
+
+
diff --git a/Source/DeprecationManager/DeprecationMgr.h b/Source/DeprecationManager/DeprecationMgr.h
new file mode 100644
index 0000000..9141f23
--- /dev/null
+++ b/Source/DeprecationManager/DeprecationMgr.h
@@ -0,0 +1,83 @@
+// ==========================================================
+// Deprecation Manager
+//
+// Design and implementation by
+// - Noel Llopis (Game Programming Gems II)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef DEPRECATIONMGR_H
+#define DEPRECATIONMGR_H
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4786 ) // identifier was truncated to 'number' characters
+#endif
+
+#include "Utilities.h"
+
+// ==========================================================
+
+#if !defined(_M_X64) && defined(_MSC_VER)
+ #define DEPRECATE(a,b) \
+ { \
+ void *fptr; \
+ _asm { mov fptr, ebp } \
+ DeprecationMgr::GetInstance()->AddDeprecatedFunction(a, b, fptr); \
+ }
+
+#elif defined(__i386__) && defined(__GNUC__)
+ #define DEPRECATE(a,b) \
+ { \
+ void *fptr; \
+ __asm__("movl %%ebp, %0" : "=m" (fptr)); \
+ DeprecationMgr::GetInstance()->AddDeprecatedFunction(a, b, fptr); \
+ }
+
+#else
+ // default fallback case, which does not use the ebp register's content
+ #define DEPRECATE(a,b) \
+ { \
+ void *fptr = NULL; \
+ DeprecationMgr::GetInstance()->AddDeprecatedFunction(a, b, fptr); \
+ }
+#endif
+
+// ==========================================================
+
+class DeprecationMgr {
+#if (_MSC_VER == 1100) // VC 5.0 need to look into the docs for the compiler for the value of each version
+public:
+#else
+private:
+#endif
+
+ struct DeprecatedFunction {
+ const char *old_function_name;
+ const char *new_function_name;
+ std::set<int> called_from;
+ };
+
+ std::map<const char *, DeprecatedFunction> m_functions;
+
+public:
+ DeprecationMgr();
+ ~DeprecationMgr();
+
+ static DeprecationMgr * GetInstance ( void );
+ void AddDeprecatedFunction(const char *old_function_name, const char *new_function_name, const void *frame_ptr);
+};
+
+#endif //DEPRECATIONMGR_H
diff --git a/Source/FreeImage.h b/Source/FreeImage.h
new file mode 100644
index 0000000..c9f643a
--- /dev/null
+++ b/Source/FreeImage.h
@@ -0,0 +1,1090 @@
+// ==========================================================
+// FreeImage 3
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// Contributors:
+// - Adam Gates (radad@xoasis.com)
+// - Alex Kwak
+// - Alexander Dymerets (sashad@te.net.ua)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+// - Jan L. Nauta (jln@magentammt.com)
+// - Jani Kajala (janik@remedy.fi)
+// - Juergen Riecker (j.riecker@gmx.de)
+// - Karl-Heinz Bussian (khbussian@moss.de)
+// - Laurent Rocher (rocherl@club-internet.fr)
+// - Luca Piergentili (l.pierge@terra.es)
+// - Machiel ten Brinke (brinkem@uni-one.nl)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Martin Weber (martweb@gmx.net)
+// - Matthias Wandel (mwandel@rim.net)
+// - Michal Novotny (michal@etc.cz)
+// - Petr Pytelka (pyta@lightcomp.com)
+// - Riley McNiff (rmcniff@marexgroup.com)
+// - Ryan Rubley (ryan@lostreality.org)
+// - Volker Gärtner (volkerg@gmx.at)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FREEIMAGE_H
+#define FREEIMAGE_H
+
+// Version information ------------------------------------------------------
+
+#define FREEIMAGE_MAJOR_VERSION 3
+#define FREEIMAGE_MINOR_VERSION 13
+#define FREEIMAGE_RELEASE_SERIAL 0
+
+// Compiler options ---------------------------------------------------------
+
+#include <wchar.h> // needed for UNICODE functions
+
+#if defined(FREEIMAGE_LIB)
+ #define DLL_API
+ #define DLL_CALLCONV
+#else
+ #if defined(_WIN32) || defined(__WIN32__)
+ #define DLL_CALLCONV __stdcall
+ // The following ifdef block is the standard way of creating macros which make exporting
+ // from a DLL simpler. All files within this DLL are compiled with the FREEIMAGE_EXPORTS
+ // symbol defined on the command line. this symbol should not be defined on any project
+ // that uses this DLL. This way any other project whose source files include this file see
+ // DLL_API functions as being imported from a DLL, wheras this DLL sees symbols
+ // defined with this macro as being exported.
+ #ifdef FREEIMAGE_EXPORTS
+ #define DLL_API __declspec(dllexport)
+ #else
+ #define DLL_API __declspec(dllimport)
+ #endif // FREEIMAGE_EXPORTS
+ #else
+ // try the gcc visibility support (see http://gcc.gnu.org/wiki/Visibility)
+ #if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ #ifndef GCC_HASCLASSVISIBILITY
+ #define GCC_HASCLASSVISIBILITY
+ #endif
+ #endif // __GNUC__
+ #define DLL_CALLCONV
+ #if defined(GCC_HASCLASSVISIBILITY)
+ #define DLL_API __attribute__ ((visibility("default")))
+ #else
+ #define DLL_API
+ #endif
+ #endif // WIN32 / !WIN32
+#endif // FREEIMAGE_LIB
+
+// Some versions of gcc may have BYTE_ORDER or __BYTE_ORDER defined
+// If your big endian system isn't being detected, add an OS specific check
+#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \
+ (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \
+ defined(__BIG_ENDIAN__)
+#define FREEIMAGE_BIGENDIAN
+#endif // BYTE_ORDER
+
+// This really only affects 24 and 32 bit formats, the rest are always RGB order.
+#define FREEIMAGE_COLORORDER_BGR 0
+#define FREEIMAGE_COLORORDER_RGB 1
+#if defined(FREEIMAGE_BIGENDIAN)
+#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_RGB
+#else
+#define FREEIMAGE_COLORORDER FREEIMAGE_COLORORDER_BGR
+#endif
+
+// Ensure 4-byte enums if we're using Borland C++ compilers
+#if defined(__BORLANDC__)
+#pragma option push -b
+#endif
+
+// For C compatibility --------------------------------------------------------
+
+#ifdef __cplusplus
+#define FI_DEFAULT(x) = x
+#define FI_ENUM(x) enum x
+#define FI_STRUCT(x) struct x
+#else
+#define FI_DEFAULT(x)
+#define FI_ENUM(x) typedef int x; enum x
+#define FI_STRUCT(x) typedef struct x x; struct x
+#endif
+
+// Bitmap types -------------------------------------------------------------
+
+FI_STRUCT (FIBITMAP) { void *data; };
+FI_STRUCT (FIMULTIBITMAP) { void *data; };
+
+// Types used in the library (directly copied from Windows) -----------------
+
+#if defined(__MINGW32__) && defined(_WINDOWS_H)
+#define _WINDOWS_ // prevent a bug in MinGW32
+#endif // __MINGW32__
+
+#ifndef _WINDOWS_
+#define _WINDOWS_
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+#ifndef _MSC_VER
+// define portable types for 32-bit / 64-bit OS
+#include <inttypes.h>
+typedef int32_t BOOL;
+typedef uint8_t BYTE;
+typedef uint16_t WORD;
+typedef uint32_t DWORD;
+typedef int32_t LONG;
+#else
+// MS is not C99 ISO compliant
+typedef long BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef long LONG;
+#endif // _MSC_VER
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif // WIN32
+
+typedef struct tagRGBQUAD {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ BYTE rgbBlue;
+ BYTE rgbGreen;
+ BYTE rgbRed;
+#else
+ BYTE rgbRed;
+ BYTE rgbGreen;
+ BYTE rgbBlue;
+#endif // FREEIMAGE_COLORORDER
+ BYTE rgbReserved;
+} RGBQUAD;
+
+typedef struct tagRGBTRIPLE {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ BYTE rgbtBlue;
+ BYTE rgbtGreen;
+ BYTE rgbtRed;
+#else
+ BYTE rgbtRed;
+ BYTE rgbtGreen;
+ BYTE rgbtBlue;
+#endif // FREEIMAGE_COLORORDER
+} RGBTRIPLE;
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif // WIN32
+
+typedef struct tagBITMAPINFOHEADER{
+ DWORD biSize;
+ LONG biWidth;
+ LONG biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+ DWORD biCompression;
+ DWORD biSizeImage;
+ LONG biXPelsPerMeter;
+ LONG biYPelsPerMeter;
+ DWORD biClrUsed;
+ DWORD biClrImportant;
+} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
+
+typedef struct tagBITMAPINFO {
+ BITMAPINFOHEADER bmiHeader;
+ RGBQUAD bmiColors[1];
+} BITMAPINFO, *PBITMAPINFO;
+
+#endif // _WINDOWS_
+
+// Types used in the library (specific to FreeImage) ------------------------
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif // WIN32
+
+/** 48-bit RGB
+*/
+typedef struct tagFIRGB16 {
+ WORD red;
+ WORD green;
+ WORD blue;
+} FIRGB16;
+
+/** 64-bit RGBA
+*/
+typedef struct tagFIRGBA16 {
+ WORD red;
+ WORD green;
+ WORD blue;
+ WORD alpha;
+} FIRGBA16;
+
+/** 96-bit RGB Float
+*/
+typedef struct tagFIRGBF {
+ float red;
+ float green;
+ float blue;
+} FIRGBF;
+
+/** 128-bit RGBA Float
+*/
+typedef struct tagFIRGBAF {
+ float red;
+ float green;
+ float blue;
+ float alpha;
+} FIRGBAF;
+
+/** Data structure for COMPLEX type (complex number)
+*/
+typedef struct tagFICOMPLEX {
+ /// real part
+ double r;
+ /// imaginary part
+ double i;
+} FICOMPLEX;
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif // WIN32
+
+// Indexes for byte arrays, masks and shifts for treating pixels as words ---
+// These coincide with the order of RGBQUAD and RGBTRIPLE -------------------
+
+#ifndef FREEIMAGE_BIGENDIAN
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+// Little Endian (x86 / MS Windows, Linux) : BGR(A) order
+#define FI_RGBA_RED 2
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 0
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x00FF0000
+#define FI_RGBA_GREEN_MASK 0x0000FF00
+#define FI_RGBA_BLUE_MASK 0x000000FF
+#define FI_RGBA_ALPHA_MASK 0xFF000000
+#define FI_RGBA_RED_SHIFT 16
+#define FI_RGBA_GREEN_SHIFT 8
+#define FI_RGBA_BLUE_SHIFT 0
+#define FI_RGBA_ALPHA_SHIFT 24
+#else
+// Little Endian (x86 / MaxOSX) : RGB(A) order
+#define FI_RGBA_RED 0
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 2
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x000000FF
+#define FI_RGBA_GREEN_MASK 0x0000FF00
+#define FI_RGBA_BLUE_MASK 0x00FF0000
+#define FI_RGBA_ALPHA_MASK 0xFF000000
+#define FI_RGBA_RED_SHIFT 0
+#define FI_RGBA_GREEN_SHIFT 8
+#define FI_RGBA_BLUE_SHIFT 16
+#define FI_RGBA_ALPHA_SHIFT 24
+#endif // FREEIMAGE_COLORORDER
+#else
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+// Big Endian (PPC / none) : BGR(A) order
+#define FI_RGBA_RED 2
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 0
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0x0000FF00
+#define FI_RGBA_GREEN_MASK 0x00FF0000
+#define FI_RGBA_BLUE_MASK 0xFF000000
+#define FI_RGBA_ALPHA_MASK 0x000000FF
+#define FI_RGBA_RED_SHIFT 8
+#define FI_RGBA_GREEN_SHIFT 16
+#define FI_RGBA_BLUE_SHIFT 24
+#define FI_RGBA_ALPHA_SHIFT 0
+#else
+// Big Endian (PPC / Linux, MaxOSX) : RGB(A) order
+#define FI_RGBA_RED 0
+#define FI_RGBA_GREEN 1
+#define FI_RGBA_BLUE 2
+#define FI_RGBA_ALPHA 3
+#define FI_RGBA_RED_MASK 0xFF000000
+#define FI_RGBA_GREEN_MASK 0x00FF0000
+#define FI_RGBA_BLUE_MASK 0x0000FF00
+#define FI_RGBA_ALPHA_MASK 0x000000FF
+#define FI_RGBA_RED_SHIFT 24
+#define FI_RGBA_GREEN_SHIFT 16
+#define FI_RGBA_BLUE_SHIFT 8
+#define FI_RGBA_ALPHA_SHIFT 0
+#endif // FREEIMAGE_COLORORDER
+#endif // FREEIMAGE_BIGENDIAN
+
+#define FI_RGBA_RGB_MASK (FI_RGBA_RED_MASK|FI_RGBA_GREEN_MASK|FI_RGBA_BLUE_MASK)
+
+// The 16bit macros only include masks and shifts, since each color element is not byte aligned
+
+#define FI16_555_RED_MASK 0x7C00
+#define FI16_555_GREEN_MASK 0x03E0
+#define FI16_555_BLUE_MASK 0x001F
+#define FI16_555_RED_SHIFT 10
+#define FI16_555_GREEN_SHIFT 5
+#define FI16_555_BLUE_SHIFT 0
+#define FI16_565_RED_MASK 0xF800
+#define FI16_565_GREEN_MASK 0x07E0
+#define FI16_565_BLUE_MASK 0x001F
+#define FI16_565_RED_SHIFT 11
+#define FI16_565_GREEN_SHIFT 5
+#define FI16_565_BLUE_SHIFT 0
+
+// ICC profile support ------------------------------------------------------
+
+#define FIICC_DEFAULT 0x00
+#define FIICC_COLOR_IS_CMYK 0x01
+
+FI_STRUCT (FIICCPROFILE) {
+ WORD flags; // info flag
+ DWORD size; // profile's size measured in bytes
+ void *data; // points to a block of contiguous memory containing the profile
+};
+
+// Important enums ----------------------------------------------------------
+
+/** I/O image format identifiers.
+*/
+FI_ENUM(FREE_IMAGE_FORMAT) {
+ FIF_UNKNOWN = -1,
+ FIF_BMP = 0,
+ FIF_ICO = 1,
+ FIF_JPEG = 2,
+ FIF_JNG = 3,
+ FIF_KOALA = 4,
+ FIF_LBM = 5,
+ FIF_IFF = FIF_LBM,
+ FIF_MNG = 6,
+ FIF_PBM = 7,
+ FIF_PBMRAW = 8,
+ FIF_PCD = 9,
+ FIF_PCX = 10,
+ FIF_PGM = 11,
+ FIF_PGMRAW = 12,
+ FIF_PNG = 13,
+ FIF_PPM = 14,
+ FIF_PPMRAW = 15,
+ FIF_RAS = 16,
+ FIF_TARGA = 17,
+ FIF_TIFF = 18,
+ FIF_WBMP = 19,
+ FIF_PSD = 20,
+ FIF_CUT = 21,
+ FIF_XBM = 22,
+ FIF_XPM = 23,
+ FIF_DDS = 24,
+ FIF_GIF = 25,
+ FIF_HDR = 26,
+ FIF_FAXG3 = 27,
+ FIF_SGI = 28,
+ FIF_EXR = 29,
+ FIF_J2K = 30,
+ FIF_JP2 = 31,
+ FIF_PFM = 32,
+ FIF_PICT = 33,
+ FIF_RAW = 34
+};
+
+/** Image type used in FreeImage.
+*/
+FI_ENUM(FREE_IMAGE_TYPE) {
+ FIT_UNKNOWN = 0, // unknown type
+ FIT_BITMAP = 1, // standard image : 1-, 4-, 8-, 16-, 24-, 32-bit
+ FIT_UINT16 = 2, // array of unsigned short : unsigned 16-bit
+ FIT_INT16 = 3, // array of short : signed 16-bit
+ FIT_UINT32 = 4, // array of unsigned long : unsigned 32-bit
+ FIT_INT32 = 5, // array of long : signed 32-bit
+ FIT_FLOAT = 6, // array of float : 32-bit IEEE floating point
+ FIT_DOUBLE = 7, // array of double : 64-bit IEEE floating point
+ FIT_COMPLEX = 8, // array of FICOMPLEX : 2 x 64-bit IEEE floating point
+ FIT_RGB16 = 9, // 48-bit RGB image : 3 x 16-bit
+ FIT_RGBA16 = 10, // 64-bit RGBA image : 4 x 16-bit
+ FIT_RGBF = 11, // 96-bit RGB float image : 3 x 32-bit IEEE floating point
+ FIT_RGBAF = 12 // 128-bit RGBA float image : 4 x 32-bit IEEE floating point
+};
+
+/** Image color type used in FreeImage.
+*/
+FI_ENUM(FREE_IMAGE_COLOR_TYPE) {
+ FIC_MINISWHITE = 0, // min value is white
+ FIC_MINISBLACK = 1, // min value is black
+ FIC_RGB = 2, // RGB color model
+ FIC_PALETTE = 3, // color map indexed
+ FIC_RGBALPHA = 4, // RGB color model with alpha channel
+ FIC_CMYK = 5 // CMYK color model
+};
+
+/** Color quantization algorithms.
+Constants used in FreeImage_ColorQuantize.
+*/
+FI_ENUM(FREE_IMAGE_QUANTIZE) {
+ FIQ_WUQUANT = 0, // Xiaolin Wu color quantization algorithm
+ FIQ_NNQUANT = 1 // NeuQuant neural-net quantization algorithm by Anthony Dekker
+};
+
+/** Dithering algorithms.
+Constants used in FreeImage_Dither.
+*/
+FI_ENUM(FREE_IMAGE_DITHER) {
+ FID_FS = 0, // Floyd & Steinberg error diffusion
+ FID_BAYER4x4 = 1, // Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+ FID_BAYER8x8 = 2, // Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+ FID_CLUSTER6x6 = 3, // Ordered clustered dot dithering (order 3 - 6x6 matrix)
+ FID_CLUSTER8x8 = 4, // Ordered clustered dot dithering (order 4 - 8x8 matrix)
+ FID_CLUSTER16x16= 5, // Ordered clustered dot dithering (order 8 - 16x16 matrix)
+ FID_BAYER16x16 = 6 // Bayer ordered dispersed dot dithering (order 4 dithering matrix)
+};
+
+/** Lossless JPEG transformations
+Constants used in FreeImage_JPEGTransform
+*/
+FI_ENUM(FREE_IMAGE_JPEG_OPERATION) {
+ FIJPEG_OP_NONE = 0, // no transformation
+ FIJPEG_OP_FLIP_H = 1, // horizontal flip
+ FIJPEG_OP_FLIP_V = 2, // vertical flip
+ FIJPEG_OP_TRANSPOSE = 3, // transpose across UL-to-LR axis
+ FIJPEG_OP_TRANSVERSE = 4, // transpose across UR-to-LL axis
+ FIJPEG_OP_ROTATE_90 = 5, // 90-degree clockwise rotation
+ FIJPEG_OP_ROTATE_180 = 6, // 180-degree rotation
+ FIJPEG_OP_ROTATE_270 = 7 // 270-degree clockwise (or 90 ccw)
+};
+
+/** Tone mapping operators.
+Constants used in FreeImage_ToneMapping.
+*/
+FI_ENUM(FREE_IMAGE_TMO) {
+ FITMO_DRAGO03 = 0, // Adaptive logarithmic mapping (F. Drago, 2003)
+ FITMO_REINHARD05 = 1, // Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+ FITMO_FATTAL02 = 2 // Gradient domain high dynamic range compression (R. Fattal, 2002)
+};
+
+/** Upsampling / downsampling filters.
+Constants used in FreeImage_Rescale.
+*/
+FI_ENUM(FREE_IMAGE_FILTER) {
+ FILTER_BOX = 0, // Box, pulse, Fourier window, 1st order (constant) b-spline
+ FILTER_BICUBIC = 1, // Mitchell & Netravali's two-param cubic filter
+ FILTER_BILINEAR = 2, // Bilinear filter
+ FILTER_BSPLINE = 3, // 4th order (cubic) b-spline
+ FILTER_CATMULLROM = 4, // Catmull-Rom spline, Overhauser spline
+ FILTER_LANCZOS3 = 5 // Lanczos3 filter
+};
+
+/** Color channels.
+Constants used in color manipulation routines.
+*/
+FI_ENUM(FREE_IMAGE_COLOR_CHANNEL) {
+ FICC_RGB = 0, // Use red, green and blue channels
+ FICC_RED = 1, // Use red channel
+ FICC_GREEN = 2, // Use green channel
+ FICC_BLUE = 3, // Use blue channel
+ FICC_ALPHA = 4, // Use alpha channel
+ FICC_BLACK = 5, // Use black channel
+ FICC_REAL = 6, // Complex images: use real part
+ FICC_IMAG = 7, // Complex images: use imaginary part
+ FICC_MAG = 8, // Complex images: use magnitude
+ FICC_PHASE = 9 // Complex images: use phase
+};
+
+// Metadata support ---------------------------------------------------------
+
+/**
+ Tag data type information (based on TIFF specifications)
+
+ Note: RATIONALs are the ratio of two 32-bit integer values.
+*/
+FI_ENUM(FREE_IMAGE_MDTYPE) {
+ FIDT_NOTYPE = 0, // placeholder
+ FIDT_BYTE = 1, // 8-bit unsigned integer
+ FIDT_ASCII = 2, // 8-bit bytes w/ last byte null
+ FIDT_SHORT = 3, // 16-bit unsigned integer
+ FIDT_LONG = 4, // 32-bit unsigned integer
+ FIDT_RATIONAL = 5, // 64-bit unsigned fraction
+ FIDT_SBYTE = 6, // 8-bit signed integer
+ FIDT_UNDEFINED = 7, // 8-bit untyped data
+ FIDT_SSHORT = 8, // 16-bit signed integer
+ FIDT_SLONG = 9, // 32-bit signed integer
+ FIDT_SRATIONAL = 10, // 64-bit signed fraction
+ FIDT_FLOAT = 11, // 32-bit IEEE floating point
+ FIDT_DOUBLE = 12, // 64-bit IEEE floating point
+ FIDT_IFD = 13, // 32-bit unsigned integer (offset)
+ FIDT_PALETTE = 14 // 32-bit RGBQUAD
+};
+
+/**
+ Metadata models supported by FreeImage
+*/
+FI_ENUM(FREE_IMAGE_MDMODEL) {
+ FIMD_NODATA = -1,
+ FIMD_COMMENTS = 0, // single comment or keywords
+ FIMD_EXIF_MAIN = 1, // Exif-TIFF metadata
+ FIMD_EXIF_EXIF = 2, // Exif-specific metadata
+ FIMD_EXIF_GPS = 3, // Exif GPS metadata
+ FIMD_EXIF_MAKERNOTE = 4, // Exif maker note metadata
+ FIMD_EXIF_INTEROP = 5, // Exif interoperability metadata
+ FIMD_IPTC = 6, // IPTC/NAA metadata
+ FIMD_XMP = 7, // Abobe XMP metadata
+ FIMD_GEOTIFF = 8, // GeoTIFF metadata
+ FIMD_ANIMATION = 9, // Animation metadata
+ FIMD_CUSTOM = 10 // Used to attach other metadata types to a dib
+};
+
+/**
+ Handle to a metadata model
+*/
+FI_STRUCT (FIMETADATA) { void *data; };
+
+/**
+ Handle to a FreeImage tag
+*/
+FI_STRUCT (FITAG) { void *data; };
+
+// File IO routines ---------------------------------------------------------
+
+#ifndef FREEIMAGE_IO
+#define FREEIMAGE_IO
+
+typedef void* fi_handle;
+typedef unsigned (DLL_CALLCONV *FI_ReadProc) (void *buffer, unsigned size, unsigned count, fi_handle handle);
+typedef unsigned (DLL_CALLCONV *FI_WriteProc) (void *buffer, unsigned size, unsigned count, fi_handle handle);
+typedef int (DLL_CALLCONV *FI_SeekProc) (fi_handle handle, long offset, int origin);
+typedef long (DLL_CALLCONV *FI_TellProc) (fi_handle handle);
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif // WIN32
+
+FI_STRUCT(FreeImageIO) {
+ FI_ReadProc read_proc; // pointer to the function used to read data
+ FI_WriteProc write_proc; // pointer to the function used to write data
+ FI_SeekProc seek_proc; // pointer to the function used to seek
+ FI_TellProc tell_proc; // pointer to the function used to aquire the current position
+};
+
+#if (defined(_WIN32) || defined(__WIN32__))
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif // WIN32
+
+/**
+Handle to a memory I/O stream
+*/
+FI_STRUCT (FIMEMORY) { void *data; };
+
+#endif // FREEIMAGE_IO
+
+// Plugin routines ----------------------------------------------------------
+
+#ifndef PLUGINS
+#define PLUGINS
+
+typedef const char *(DLL_CALLCONV *FI_FormatProc)(void);
+typedef const char *(DLL_CALLCONV *FI_DescriptionProc)(void);
+typedef const char *(DLL_CALLCONV *FI_ExtensionListProc)(void);
+typedef const char *(DLL_CALLCONV *FI_RegExprProc)(void);
+typedef void *(DLL_CALLCONV *FI_OpenProc)(FreeImageIO *io, fi_handle handle, BOOL read);
+typedef void (DLL_CALLCONV *FI_CloseProc)(FreeImageIO *io, fi_handle handle, void *data);
+typedef int (DLL_CALLCONV *FI_PageCountProc)(FreeImageIO *io, fi_handle handle, void *data);
+typedef int (DLL_CALLCONV *FI_PageCapabilityProc)(FreeImageIO *io, fi_handle handle, void *data);
+typedef FIBITMAP *(DLL_CALLCONV *FI_LoadProc)(FreeImageIO *io, fi_handle handle, int page, int flags, void *data);
+typedef BOOL (DLL_CALLCONV *FI_SaveProc)(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data);
+typedef BOOL (DLL_CALLCONV *FI_ValidateProc)(FreeImageIO *io, fi_handle handle);
+typedef const char *(DLL_CALLCONV *FI_MimeProc)(void);
+typedef BOOL (DLL_CALLCONV *FI_SupportsExportBPPProc)(int bpp);
+typedef BOOL (DLL_CALLCONV *FI_SupportsExportTypeProc)(FREE_IMAGE_TYPE type);
+typedef BOOL (DLL_CALLCONV *FI_SupportsICCProfilesProc)(void);
+
+FI_STRUCT (Plugin) {
+ FI_FormatProc format_proc;
+ FI_DescriptionProc description_proc;
+ FI_ExtensionListProc extension_proc;
+ FI_RegExprProc regexpr_proc;
+ FI_OpenProc open_proc;
+ FI_CloseProc close_proc;
+ FI_PageCountProc pagecount_proc;
+ FI_PageCapabilityProc pagecapability_proc;
+ FI_LoadProc load_proc;
+ FI_SaveProc save_proc;
+ FI_ValidateProc validate_proc;
+ FI_MimeProc mime_proc;
+ FI_SupportsExportBPPProc supports_export_bpp_proc;
+ FI_SupportsExportTypeProc supports_export_type_proc;
+ FI_SupportsICCProfilesProc supports_icc_profiles_proc;
+};
+
+typedef void (DLL_CALLCONV *FI_InitProc)(Plugin *plugin, int format_id);
+
+#endif // PLUGINS
+
+
+// Load / Save flag constants -----------------------------------------------
+
+#define BMP_DEFAULT 0
+#define BMP_SAVE_RLE 1
+#define CUT_DEFAULT 0
+#define DDS_DEFAULT 0
+#define EXR_DEFAULT 0 // save data as half with piz-based wavelet compression
+#define EXR_FLOAT 0x0001 // save data as float instead of as half (not recommended)
+#define EXR_NONE 0x0002 // save with no compression
+#define EXR_ZIP 0x0004 // save with zlib compression, in blocks of 16 scan lines
+#define EXR_PIZ 0x0008 // save with piz-based wavelet compression
+#define EXR_PXR24 0x0010 // save with lossy 24-bit float compression
+#define EXR_B44 0x0020 // save with lossy 44% float compression - goes to 22% when combined with EXR_LC
+#define EXR_LC 0x0040 // save images with one luminance and two chroma channels, rather than as RGB (lossy compression)
+#define FAXG3_DEFAULT 0
+#define GIF_DEFAULT 0
+#define GIF_LOAD256 1 // Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color
+#define GIF_PLAYBACK 2 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+#define HDR_DEFAULT 0
+#define ICO_DEFAULT 0
+#define ICO_MAKEALPHA 1 // convert to 32bpp and create an alpha channel from the AND-mask when loading
+#define IFF_DEFAULT 0
+#define J2K_DEFAULT 0 // save with a 16:1 rate
+#define JP2_DEFAULT 0 // save with a 16:1 rate
+#define JPEG_DEFAULT 0 // loading (see JPEG_FAST); saving (see JPEG_QUALITYGOOD|JPEG_SUBSAMPLING_420)
+#define JPEG_FAST 0x0001 // load the file as fast as possible, sacrificing some quality
+#define JPEG_ACCURATE 0x0002 // load the file with the best quality, sacrificing some speed
+#define JPEG_CMYK 0x0004 // load separated CMYK "as is" (use | to combine with other load flags)
+#define JPEG_EXIFROTATE 0x0008 // load and rotate according to Exif 'Orientation' tag if available
+#define JPEG_QUALITYSUPERB 0x80 // save with superb quality (100:1)
+#define JPEG_QUALITYGOOD 0x0100 // save with good quality (75:1)
+#define JPEG_QUALITYNORMAL 0x0200 // save with normal quality (50:1)
+#define JPEG_QUALITYAVERAGE 0x0400 // save with average quality (25:1)
+#define JPEG_QUALITYBAD 0x0800 // save with bad quality (10:1)
+#define JPEG_PROGRESSIVE 0x2000 // save as a progressive-JPEG (use | to combine with other save flags)
+#define JPEG_SUBSAMPLING_411 0x1000 // save with high 4x1 chroma subsampling (4:1:1)
+#define JPEG_SUBSAMPLING_420 0x4000 // save with medium 2x2 medium chroma subsampling (4:2:0) - default value
+#define JPEG_SUBSAMPLING_422 0x8000 // save with low 2x1 chroma subsampling (4:2:2)
+#define JPEG_SUBSAMPLING_444 0x10000 // save with no chroma subsampling (4:4:4)
+#define KOALA_DEFAULT 0
+#define LBM_DEFAULT 0
+#define MNG_DEFAULT 0
+#define PCD_DEFAULT 0
+#define PCD_BASE 1 // load the bitmap sized 768 x 512
+#define PCD_BASEDIV4 2 // load the bitmap sized 384 x 256
+#define PCD_BASEDIV16 3 // load the bitmap sized 192 x 128
+#define PCX_DEFAULT 0
+#define PFM_DEFAULT 0
+#define PICT_DEFAULT 0
+#define PNG_DEFAULT 0
+#define PNG_IGNOREGAMMA 1 // loading: avoid gamma correction
+#define PNG_Z_BEST_SPEED 0x0001 // save using ZLib level 1 compression flag (default value is 6)
+#define PNG_Z_DEFAULT_COMPRESSION 0x0006 // save using ZLib level 6 compression flag (default recommended value)
+#define PNG_Z_BEST_COMPRESSION 0x0009 // save using ZLib level 9 compression flag (default value is 6)
+#define PNG_Z_NO_COMPRESSION 0x0100 // save without ZLib compression
+#define PNG_INTERLACED 0x0200 // save using Adam7 interlacing (use | to combine with other save flags)
+#define PNM_DEFAULT 0
+#define PNM_SAVE_RAW 0 // If set the writer saves in RAW format (i.e. P4, P5 or P6)
+#define PNM_SAVE_ASCII 1 // If set the writer saves in ASCII format (i.e. P1, P2 or P3)
+#define PSD_DEFAULT 0
+#define RAS_DEFAULT 0
+#define RAW_DEFAULT 0 // load the file as linear RGB 48-bit
+#define RAW_PREVIEW 1 // try to load the embedded JPEG preview with included Exif Data or default to RGB 24-bit
+#define RAW_DISPLAY 2 // load the file as RGB 24-bit
+#define SGI_DEFAULT 0
+#define TARGA_DEFAULT 0
+#define TARGA_LOAD_RGB888 1 // If set the loader converts RGB555 and ARGB8888 -> RGB888.
+#define TIFF_DEFAULT 0
+#define TIFF_CMYK 0x0001 // reads/stores tags for separated CMYK (use | to combine with compression flags)
+#define TIFF_PACKBITS 0x0100 // save using PACKBITS compression
+#define TIFF_DEFLATE 0x0200 // save using DEFLATE compression (a.k.a. ZLIB compression)
+#define TIFF_ADOBE_DEFLATE 0x0400 // save using ADOBE DEFLATE compression
+#define TIFF_NONE 0x0800 // save without any compression
+#define TIFF_CCITTFAX3 0x1000 // save using CCITT Group 3 fax encoding
+#define TIFF_CCITTFAX4 0x2000 // save using CCITT Group 4 fax encoding
+#define TIFF_LZW 0x4000 // save using LZW compression
+#define TIFF_JPEG 0x8000 // save using JPEG compression
+#define WBMP_DEFAULT 0
+#define XBM_DEFAULT 0
+#define XPM_DEFAULT 0
+
+// Background filling options ---------------------------------------------------------
+// Constants used in FreeImage_FillBackground and FreeImage_EnlargeCanvas
+
+#define FI_COLOR_IS_RGB_COLOR 0x00 // RGBQUAD color is a RGB color (contains no valid alpha channel)
+#define FI_COLOR_IS_RGBA_COLOR 0x01 // RGBQUAD color is a RGBA color (contains a valid alpha channel)
+#define FI_COLOR_FIND_EQUAL_COLOR 0x02 // For palettized images: lookup equal RGB color from palette
+#define FI_COLOR_ALPHA_IS_INDEX 0x04 // The color's rgbReserved member (alpha) contains the palette index to be used
+#define FI_COLOR_PALETTE_SEARCH_MASK (FI_COLOR_FIND_EQUAL_COLOR | FI_COLOR_ALPHA_IS_INDEX) // No color lookup is performed
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Init / Error routines ----------------------------------------------------
+
+DLL_API void DLL_CALLCONV FreeImage_Initialise(BOOL load_local_plugins_only FI_DEFAULT(FALSE));
+DLL_API void DLL_CALLCONV FreeImage_DeInitialise(void);
+
+// Version routines ---------------------------------------------------------
+
+DLL_API const char *DLL_CALLCONV FreeImage_GetVersion(void);
+DLL_API const char *DLL_CALLCONV FreeImage_GetCopyrightMessage(void);
+
+// Message output functions -------------------------------------------------
+
+typedef void (*FreeImage_OutputMessageFunction)(FREE_IMAGE_FORMAT fif, const char *msg);
+typedef void (DLL_CALLCONV *FreeImage_OutputMessageFunctionStdCall)(FREE_IMAGE_FORMAT fif, const char *msg);
+
+DLL_API void DLL_CALLCONV FreeImage_SetOutputMessageStdCall(FreeImage_OutputMessageFunctionStdCall omf);
+DLL_API void DLL_CALLCONV FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf);
+DLL_API void DLL_CALLCONV FreeImage_OutputMessageProc(int fif, const char *fmt, ...);
+
+// Allocate / Clone / Unload routines ---------------------------------------
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp FI_DEFAULT(8), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
+DLL_API FIBITMAP * DLL_CALLCONV FreeImage_Clone(FIBITMAP *dib);
+DLL_API void DLL_CALLCONV FreeImage_Unload(FIBITMAP *dib);
+
+// Load / Save routines -----------------------------------------------------
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0));
+DLL_API BOOL DLL_CALLCONV FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags FI_DEFAULT(0));
+DLL_API BOOL DLL_CALLCONV FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags FI_DEFAULT(0));
+DLL_API BOOL DLL_CALLCONV FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0));
+
+// Memory I/O stream routines -----------------------------------------------
+
+DLL_API FIMEMORY *DLL_CALLCONV FreeImage_OpenMemory(BYTE *data FI_DEFAULT(0), DWORD size_in_bytes FI_DEFAULT(0));
+DLL_API void DLL_CALLCONV FreeImage_CloseMemory(FIMEMORY *stream);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags FI_DEFAULT(0));
+DLL_API BOOL DLL_CALLCONV FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags FI_DEFAULT(0));
+DLL_API long DLL_CALLCONV FreeImage_TellMemory(FIMEMORY *stream);
+DLL_API BOOL DLL_CALLCONV FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin);
+DLL_API BOOL DLL_CALLCONV FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes);
+DLL_API unsigned DLL_CALLCONV FreeImage_ReadMemory(void *buffer, unsigned size, unsigned count, FIMEMORY *stream);
+DLL_API unsigned DLL_CALLCONV FreeImage_WriteMemory(const void *buffer, unsigned size, unsigned count, FIMEMORY *stream);
+DLL_API FIMULTIBITMAP *DLL_CALLCONV FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags FI_DEFAULT(0));
+
+// Plugin Interface ---------------------------------------------------------
+
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0));
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_RegisterExternalPlugin(const char *path, const char *format FI_DEFAULT(0), const char *description FI_DEFAULT(0), const char *extension FI_DEFAULT(0), const char *regexpr FI_DEFAULT(0));
+DLL_API int DLL_CALLCONV FreeImage_GetFIFCount(void);
+DLL_API int DLL_CALLCONV FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable);
+DLL_API int DLL_CALLCONV FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif);
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFormat(const char *format);
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromMime(const char *mime);
+DLL_API const char *DLL_CALLCONV FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif);
+DLL_API const char *DLL_CALLCONV FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif);
+DLL_API const char *DLL_CALLCONV FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif);
+DLL_API const char *DLL_CALLCONV FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif);
+DLL_API const char *DLL_CALLCONV FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif);
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilename(const char *filename);
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFIFFromFilenameU(const wchar_t *filename);
+DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif);
+DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif);
+DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int bpp);
+DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type);
+DLL_API BOOL DLL_CALLCONV FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif);
+
+// Multipaging interface ----------------------------------------------------
+
+DLL_API FIMULTIBITMAP * DLL_CALLCONV FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory FI_DEFAULT(FALSE), int flags FI_DEFAULT(0));
+DLL_API FIMULTIBITMAP * DLL_CALLCONV FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags FI_DEFAULT(0));
+DLL_API BOOL DLL_CALLCONV FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags FI_DEFAULT(0));
+DLL_API int DLL_CALLCONV FreeImage_GetPageCount(FIMULTIBITMAP *bitmap);
+DLL_API void DLL_CALLCONV FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data);
+DLL_API void DLL_CALLCONV FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data);
+DLL_API void DLL_CALLCONV FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page);
+DLL_API FIBITMAP * DLL_CALLCONV FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page);
+DLL_API void DLL_CALLCONV FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *data, BOOL changed);
+DLL_API BOOL DLL_CALLCONV FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source);
+DLL_API BOOL DLL_CALLCONV FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count);
+
+// Filetype request routines ------------------------------------------------
+
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileType(const char *filename, int size FI_DEFAULT(0));
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeU(const wchar_t *filename, int size FI_DEFAULT(0));
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size FI_DEFAULT(0));
+DLL_API FREE_IMAGE_FORMAT DLL_CALLCONV FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size FI_DEFAULT(0));
+
+// Image type request routine -----------------------------------------------
+
+DLL_API FREE_IMAGE_TYPE DLL_CALLCONV FreeImage_GetImageType(FIBITMAP *dib);
+
+// FreeImage helper routines ------------------------------------------------
+
+DLL_API BOOL DLL_CALLCONV FreeImage_IsLittleEndian(void);
+DLL_API BOOL DLL_CALLCONV FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue);
+DLL_API BOOL DLL_CALLCONV FreeImage_LookupSVGColor(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue);
+
+// Pixel access routines ----------------------------------------------------
+
+DLL_API BYTE *DLL_CALLCONV FreeImage_GetBits(FIBITMAP *dib);
+DLL_API BYTE *DLL_CALLCONV FreeImage_GetScanLine(FIBITMAP *dib, int scanline);
+
+DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value);
+DLL_API BOOL DLL_CALLCONV FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value);
+
+// DIB info routines --------------------------------------------------------
+
+DLL_API unsigned DLL_CALLCONV FreeImage_GetColorsUsed(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetBPP(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetWidth(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetHeight(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetLine(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetPitch(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetDIBSize(FIBITMAP *dib);
+DLL_API RGBQUAD *DLL_CALLCONV FreeImage_GetPalette(FIBITMAP *dib);
+
+DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterX(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetDotsPerMeterY(FIBITMAP *dib);
+DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res);
+DLL_API void DLL_CALLCONV FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res);
+
+DLL_API BITMAPINFOHEADER *DLL_CALLCONV FreeImage_GetInfoHeader(FIBITMAP *dib);
+DLL_API BITMAPINFO *DLL_CALLCONV FreeImage_GetInfo(FIBITMAP *dib);
+DLL_API FREE_IMAGE_COLOR_TYPE DLL_CALLCONV FreeImage_GetColorType(FIBITMAP *dib);
+
+DLL_API unsigned DLL_CALLCONV FreeImage_GetRedMask(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetGreenMask(FIBITMAP *dib);
+DLL_API unsigned DLL_CALLCONV FreeImage_GetBlueMask(FIBITMAP *dib);
+
+DLL_API unsigned DLL_CALLCONV FreeImage_GetTransparencyCount(FIBITMAP *dib);
+DLL_API BYTE * DLL_CALLCONV FreeImage_GetTransparencyTable(FIBITMAP *dib);
+DLL_API void DLL_CALLCONV FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled);
+DLL_API void DLL_CALLCONV FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count);
+DLL_API BOOL DLL_CALLCONV FreeImage_IsTransparent(FIBITMAP *dib);
+DLL_API void DLL_CALLCONV FreeImage_SetTransparentIndex(FIBITMAP *dib, int index);
+DLL_API int DLL_CALLCONV FreeImage_GetTransparentIndex(FIBITMAP *dib);
+
+DLL_API BOOL DLL_CALLCONV FreeImage_HasBackgroundColor(FIBITMAP *dib);
+DLL_API BOOL DLL_CALLCONV FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor);
+
+
+// ICC profile routines -----------------------------------------------------
+
+DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_GetICCProfile(FIBITMAP *dib);
+DLL_API FIICCPROFILE *DLL_CALLCONV FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size);
+DLL_API void DLL_CALLCONV FreeImage_DestroyICCProfile(FIBITMAP *dib);
+
+// Line conversion routines -------------------------------------------------
+
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_565_To16_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16_555_To16_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To16_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To16_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels);
+DLL_API void DLL_CALLCONV FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels);
+
+// Smart conversion routines ------------------------------------------------
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo4Bits(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo8Bits(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToGreyscale(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits555(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo16Bits565(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo24Bits(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertTo32Bits(FIBITMAP *dib);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantize(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize FI_DEFAULT(FIQ_WUQUANT), int PaletteSize FI_DEFAULT(256), int ReserveSize FI_DEFAULT(0), RGBQUAD *ReservePalette FI_DEFAULT(NULL));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Threshold(FIBITMAP *dib, BYTE T);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm);
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertFromRawBits(BYTE *bits, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE));
+DLL_API void DLL_CALLCONV FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown FI_DEFAULT(FALSE));
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToRGBF(FIBITMAP *dib);
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear FI_DEFAULT(TRUE));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear FI_DEFAULT(TRUE));
+
+// tone mapping operators
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_ToneMapping(FIBITMAP *dib, FREE_IMAGE_TMO tmo, double first_param FI_DEFAULT(0), double second_param FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoDrago03(FIBITMAP *src, double gamma FI_DEFAULT(2.2), double exposure FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoReinhard05(FIBITMAP *src, double intensity FI_DEFAULT(0), double contrast FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoReinhard05Ex(FIBITMAP *src, double intensity FI_DEFAULT(0), double contrast FI_DEFAULT(0), double adaptation FI_DEFAULT(1), double color_correction FI_DEFAULT(0));
+
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_TmoFattal02(FIBITMAP *src, double color_saturation FI_DEFAULT(0.5), double attenuation FI_DEFAULT(0.85));
+
+// ZLib interface -----------------------------------------------------------
+
+DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size);
+DLL_API DWORD DLL_CALLCONV FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size);
+DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size);
+DLL_API DWORD DLL_CALLCONV FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size);
+DLL_API DWORD DLL_CALLCONV FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size);
+
+// --------------------------------------------------------------------------
+// Metadata routines --------------------------------------------------------
+// --------------------------------------------------------------------------
+
+// tag creation / destruction
+DLL_API FITAG *DLL_CALLCONV FreeImage_CreateTag(void);
+DLL_API void DLL_CALLCONV FreeImage_DeleteTag(FITAG *tag);
+DLL_API FITAG *DLL_CALLCONV FreeImage_CloneTag(FITAG *tag);
+
+// tag getters and setters
+DLL_API const char *DLL_CALLCONV FreeImage_GetTagKey(FITAG *tag);
+DLL_API const char *DLL_CALLCONV FreeImage_GetTagDescription(FITAG *tag);
+DLL_API WORD DLL_CALLCONV FreeImage_GetTagID(FITAG *tag);
+DLL_API FREE_IMAGE_MDTYPE DLL_CALLCONV FreeImage_GetTagType(FITAG *tag);
+DLL_API DWORD DLL_CALLCONV FreeImage_GetTagCount(FITAG *tag);
+DLL_API DWORD DLL_CALLCONV FreeImage_GetTagLength(FITAG *tag);
+DLL_API const void *DLL_CALLCONV FreeImage_GetTagValue(FITAG *tag);
+
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagKey(FITAG *tag, const char *key);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagDescription(FITAG *tag, const char *description);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagID(FITAG *tag, WORD id);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagCount(FITAG *tag, DWORD count);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagLength(FITAG *tag, DWORD length);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetTagValue(FITAG *tag, const void *value);
+
+// iterator
+DLL_API FIMETADATA *DLL_CALLCONV FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag);
+DLL_API BOOL DLL_CALLCONV FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag);
+DLL_API void DLL_CALLCONV FreeImage_FindCloseMetadata(FIMETADATA *mdhandle);
+
+// metadata setter and getter
+DLL_API BOOL DLL_CALLCONV FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag);
+DLL_API BOOL DLL_CALLCONV FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag);
+
+// helpers
+DLL_API unsigned DLL_CALLCONV FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib);
+DLL_API BOOL DLL_CALLCONV FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src);
+
+// tag to C string conversion
+DLL_API const char* DLL_CALLCONV FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make FI_DEFAULT(NULL));
+
+// --------------------------------------------------------------------------
+// Image manipulation toolkit -----------------------------------------------
+// --------------------------------------------------------------------------
+
+// rotation and flipping
+/// @deprecated see FreeImage_Rotate
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateClassic(FIBITMAP *dib, double angle);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor FI_DEFAULT(NULL));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask);
+DLL_API BOOL DLL_CALLCONV FreeImage_FlipHorizontal(FIBITMAP *dib);
+DLL_API BOOL DLL_CALLCONV FreeImage_FlipVertical(FIBITMAP *dib);
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect FI_DEFAULT(FALSE));
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGTransformU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect FI_DEFAULT(FALSE));
+
+// upsampling / downsampling
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Rescale(FIBITMAP *dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert FI_DEFAULT(TRUE));
+
+// color manipulation routines (point operations)
+DLL_API BOOL DLL_CALLCONV FreeImage_AdjustCurve(FIBITMAP *dib, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel);
+DLL_API BOOL DLL_CALLCONV FreeImage_AdjustGamma(FIBITMAP *dib, double gamma);
+DLL_API BOOL DLL_CALLCONV FreeImage_AdjustBrightness(FIBITMAP *dib, double percentage);
+DLL_API BOOL DLL_CALLCONV FreeImage_AdjustContrast(FIBITMAP *dib, double percentage);
+DLL_API BOOL DLL_CALLCONV FreeImage_Invert(FIBITMAP *dib);
+DLL_API BOOL DLL_CALLCONV FreeImage_GetHistogram(FIBITMAP *dib, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel FI_DEFAULT(FICC_BLACK));
+DLL_API int DLL_CALLCONV FreeImage_GetAdjustColorsLookupTable(BYTE *LUT, double brightness, double contrast, double gamma, BOOL invert);
+DLL_API BOOL DLL_CALLCONV FreeImage_AdjustColors(FIBITMAP *dib, double brightness, double contrast, double gamma, BOOL invert FI_DEFAULT(FALSE));
+DLL_API unsigned DLL_CALLCONV FreeImage_ApplyColorMapping(FIBITMAP *dib, RGBQUAD *srccolors, RGBQUAD *dstcolors, unsigned count, BOOL ignore_alpha, BOOL swap);
+DLL_API unsigned DLL_CALLCONV FreeImage_SwapColors(FIBITMAP *dib, RGBQUAD *color_a, RGBQUAD *color_b, BOOL ignore_alpha);
+DLL_API unsigned DLL_CALLCONV FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices, BYTE *dstindices, unsigned count, BOOL swap);
+DLL_API unsigned DLL_CALLCONV FreeImage_SwapPaletteIndices(FIBITMAP *dib, BYTE *index_a, BYTE *index_b);
+
+// channel processing routines
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetChannel(FIBITMAP *dib, FREE_IMAGE_COLOR_CHANNEL channel);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetChannel(FIBITMAP *dib, FIBITMAP *dib8, FREE_IMAGE_COLOR_CHANNEL channel);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel);
+DLL_API BOOL DLL_CALLCONV FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel);
+
+// copy / paste / composite routines
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Copy(FIBITMAP *dib, int left, int top, int right, int bottom);
+DLL_API BOOL DLL_CALLCONV FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha);
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg FI_DEFAULT(FALSE), RGBQUAD *appBkColor FI_DEFAULT(NULL), FIBITMAP *bg FI_DEFAULT(NULL));
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom);
+DLL_API BOOL DLL_CALLCONV FreeImage_JPEGCropU(const wchar_t *src_file, const wchar_t *dst_file, int left, int top, int right, int bottom);
+DLL_API BOOL DLL_CALLCONV FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib);
+
+// background filling routines
+DLL_API BOOL DLL_CALLCONV FreeImage_FillBackground(FIBITMAP *dib, const void *color, int options FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_EnlargeCanvas(FIBITMAP *src, int left, int top, int right, int bottom, const void *color, int options FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_AllocateEx(int width, int height, int bpp, const RGBQUAD *color, int options FI_DEFAULT(0), const RGBQUAD *palette FI_DEFAULT(NULL), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_AllocateExT(FREE_IMAGE_TYPE type, int width, int height, int bpp, const void *color, int options FI_DEFAULT(0), const RGBQUAD *palette FI_DEFAULT(NULL), unsigned red_mask FI_DEFAULT(0), unsigned green_mask FI_DEFAULT(0), unsigned blue_mask FI_DEFAULT(0));
+
+// miscellaneous algorithms
+DLL_API FIBITMAP *DLL_CALLCONV FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle FI_DEFAULT(3));
+
+// restore the borland-specific enum size option
+#if defined(__BORLANDC__)
+#pragma option pop
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // FREEIMAGE_H
diff --git a/Source/FreeImage/BitmapAccess.cpp b/Source/FreeImage/BitmapAccess.cpp
new file mode 100644
index 0000000..9106ad2
--- /dev/null
+++ b/Source/FreeImage/BitmapAccess.cpp
@@ -0,0 +1,1080 @@
+// ==========================================================
+// FreeImage implementation
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+// - Petr Supina (psup@centrum.cz)
+// - Carsten Klein (c.klein@datagis.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include <stdlib.h>
+#if defined(_WIN32) || defined(_WIN64) || defined(__MINGW32__)
+#include <malloc.h>
+#endif // _WIN32 || _WIN64 || __MINGW32__
+
+#include "FreeImage.h"
+#include "FreeImageIO.h"
+#include "Utilities.h"
+
+#include "../Metadata/FreeImageTag.h"
+
+// ----------------------------------------------------------
+// Metadata definitions
+// ----------------------------------------------------------
+
+// helper for map<key, value> where value is a pointer to a FreeImage tag
+typedef std::map<std::string, FITAG*> TAGMAP;
+
+// helper for map<FREE_IMAGE_MDMODEL, TAGMAP*>
+typedef std::map<int, TAGMAP*> METADATAMAP;
+
+// helper for metadata iterator
+FI_STRUCT (METADATAHEADER) {
+ long pos; // current position when iterating the map
+ TAGMAP *tagmap; // pointer to the tag map
+};
+
+// ----------------------------------------------------------
+// FIBITMAP definition
+// ----------------------------------------------------------
+
+FI_STRUCT (FREEIMAGEHEADER) {
+ FREE_IMAGE_TYPE type; // data type - bitmap, array of long, double, complex, etc
+
+ unsigned red_mask; // bit layout of the red components
+ unsigned green_mask; // bit layout of the green components
+ unsigned blue_mask; // bit layout of the blue components
+
+ RGBQUAD bkgnd_color; // background color used for RGB transparency
+
+ BOOL transparent; // why another table? for easy transparency table retrieval!
+ int transparency_count; // transparency could be stored in the palette, which is better
+ BYTE transparent_table[256]; // overall, but it requires quite some changes and it will render
+ // FreeImage_GetTransparencyTable obsolete in its current form;
+ FIICCPROFILE iccProfile; // space to hold ICC profile
+
+ METADATAMAP *metadata; // contains a list of metadata models attached to the bitmap
+
+ //BYTE filler[1]; // fill to 32-bit alignment
+};
+
+// ----------------------------------------------------------
+// Memory allocation on a specified alignment boundary
+// ----------------------------------------------------------
+
+#if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
+
+void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
+ assert(alignment == FIBITMAP_ALIGNMENT);
+ return _aligned_malloc(amount, alignment);
+}
+
+void FreeImage_Aligned_Free(void* mem) {
+ _aligned_free(mem);
+}
+
+#elif defined (__MINGW32__)
+
+void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
+ assert(alignment == FIBITMAP_ALIGNMENT);
+ return __mingw_aligned_malloc (amount, alignment);
+}
+
+void FreeImage_Aligned_Free(void* mem) {
+ __mingw_aligned_free (mem);
+}
+
+#else
+
+void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment) {
+ assert(alignment == FIBITMAP_ALIGNMENT);
+ /*
+ In some rare situations, the malloc routines can return misaligned memory.
+ The routine FreeImage_Aligned_Malloc allocates a bit more memory to do
+ aligned writes. Normally, it *should* allocate "alignment" extra memory and then writes
+ one dword back the true pointer. But if the memory manager returns a
+ misaligned block that is less than a dword from the next alignment,
+ then the writing back one dword will corrupt memory.
+
+ For example, suppose that alignment is 16 and malloc returns the address 0xFFFF.
+
+ 16 - 0xFFFF % 16 + 0xFFFF = 16 - 15 + 0xFFFF = 0x10000.
+
+ Now, you subtract one dword from that and write and that will corrupt memory.
+
+ That's why the code below allocates *two* alignments instead of one.
+ */
+ void* mem_real = malloc(amount + 2 * alignment);
+ if(!mem_real) return NULL;
+ char* mem_align = (char*)((unsigned long)(2 * alignment - (unsigned long)mem_real % (unsigned long)alignment) + (unsigned long)mem_real);
+ *((long*)mem_align - 1) = (long)mem_real;
+ return mem_align;
+}
+
+void FreeImage_Aligned_Free(void* mem) {
+ free((void*)*((long*)mem - 1));
+}
+
+#endif // _WIN32 || _WIN64
+
+// ----------------------------------------------------------
+// DIB information functions
+// ----------------------------------------------------------
+
+/**
+Calculate the size of a FreeImage image.
+Align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary.
+*/
+static unsigned
+FreeImage_GetImageSize(int width, int height, int bpp) {
+ unsigned dib_size = sizeof(FREEIMAGEHEADER);
+ dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);
+ dib_size += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
+ dib_size += sizeof(BITMAPINFOHEADER);
+ // palette is aligned on a 16 bytes boundary
+ dib_size += sizeof(RGBQUAD) * CalculateUsedPaletteEntries(bpp);
+ dib_size += (dib_size % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - dib_size % FIBITMAP_ALIGNMENT : 0);
+ // pixels are aligned on a 16 bytes boundary
+ dib_size += CalculatePitch(CalculateLine(width, bpp)) * height;
+
+ return dib_size;
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_Allocate(int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
+ return FreeImage_AllocateT(FIT_BITMAP, width, height, bpp, red_mask, green_mask, blue_mask);
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
+ FIBITMAP *bitmap = (FIBITMAP *)malloc(sizeof(FIBITMAP));
+
+ if (bitmap != NULL) {
+ height = abs(height);
+
+ // check pixel bit depth
+ switch(type) {
+ case FIT_BITMAP:
+ switch(bpp) {
+ case 1:
+ case 4:
+ case 8:
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ bpp = 8;
+ break;
+ }
+ break;
+ case FIT_UINT16:
+ bpp = 8 * sizeof(unsigned short);
+ break;
+ case FIT_INT16:
+ bpp = 8 * sizeof(short);
+ break;
+ case FIT_UINT32:
+ bpp = 8 * sizeof(unsigned long);
+ break;
+ case FIT_INT32:
+ bpp = 8 * sizeof(long);
+ break;
+ case FIT_FLOAT:
+ bpp = 8 * sizeof(float);
+ break;
+ case FIT_DOUBLE:
+ bpp = 8 * sizeof(double);
+ break;
+ case FIT_COMPLEX:
+ bpp = 8 * sizeof(FICOMPLEX);
+ break;
+ case FIT_RGB16:
+ bpp = 8 * sizeof(FIRGB16);
+ break;
+ case FIT_RGBA16:
+ bpp = 8 * sizeof(FIRGBA16);
+ break;
+ case FIT_RGBF:
+ bpp = 8 * sizeof(FIRGBF);
+ break;
+ case FIT_RGBAF:
+ bpp = 8 * sizeof(FIRGBAF);
+ break;
+ default:
+ free(bitmap);
+ return NULL;
+ }
+
+ // calculate the size of a FreeImage image
+ // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
+ // palette is aligned on a 16 bytes boundary
+ // pixels are aligned on a 16 bytes boundary
+
+ unsigned dib_size = FreeImage_GetImageSize(width, height, bpp);
+
+ bitmap->data = (BYTE *)FreeImage_Aligned_Malloc(dib_size * sizeof(BYTE), FIBITMAP_ALIGNMENT);
+
+ if (bitmap->data != NULL) {
+ memset(bitmap->data, 0, dib_size);
+
+ // write out the FREEIMAGEHEADER
+
+ FREEIMAGEHEADER *fih = (FREEIMAGEHEADER *)bitmap->data;
+ fih->type = type;
+
+ fih->red_mask = red_mask;
+ fih->green_mask = green_mask;
+ fih->blue_mask = blue_mask;
+
+ memset(&fih->bkgnd_color, 0, sizeof(RGBQUAD));
+
+ fih->transparent = FALSE;
+ fih->transparency_count = 0;
+ memset(fih->transparent_table, 0xff, 256);
+
+ // initialize FIICCPROFILE link
+
+ FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(bitmap);
+ iccProfile->size = 0;
+ iccProfile->data = 0;
+ iccProfile->flags = 0;
+
+ // initialize metadata models list
+
+ fih->metadata = new METADATAMAP;
+
+ // write out the BITMAPINFOHEADER
+
+ BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(bitmap);
+ bih->biSize = sizeof(BITMAPINFOHEADER);
+ bih->biWidth = width;
+ bih->biHeight = height;
+ bih->biPlanes = 1;
+ bih->biCompression = 0;
+ bih->biBitCount = (WORD)bpp;
+ bih->biClrUsed = CalculateUsedPaletteEntries(bpp);
+ bih->biClrImportant = bih->biClrUsed;
+ bih->biXPelsPerMeter = 2835; // 72 dpi
+ bih->biYPelsPerMeter = 2835; // 72 dpi
+
+ return bitmap;
+ }
+
+ free(bitmap);
+ }
+
+ return NULL;
+}
+
+void DLL_CALLCONV
+FreeImage_Unload(FIBITMAP *dib) {
+ if (NULL != dib) {
+ if (NULL != dib->data) {
+ // delete possible icc profile ...
+ if (FreeImage_GetICCProfile(dib)->data)
+ free(FreeImage_GetICCProfile(dib)->data);
+
+ // delete metadata models
+ METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+
+ for(METADATAMAP::iterator i = (*metadata).begin(); i != (*metadata).end(); i++) {
+ TAGMAP *tagmap = (*i).second;
+
+ if(tagmap) {
+ for(TAGMAP::iterator j = tagmap->begin(); j != tagmap->end(); j++) {
+ FITAG *tag = (*j).second;
+ FreeImage_DeleteTag(tag);
+ }
+
+ delete tagmap;
+ }
+ }
+
+ delete metadata;
+
+ // delete bitmap ...
+ FreeImage_Aligned_Free(dib->data);
+ }
+ free(dib); // ... and the wrapper
+ }
+}
+
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_Clone(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned bpp = FreeImage_GetBPP(dib);
+
+ // allocate a new dib
+ FIBITMAP *new_dib = FreeImage_AllocateT(FreeImage_GetImageType(dib), width, height, bpp,
+ FreeImage_GetRedMask(dib), FreeImage_GetGreenMask(dib), FreeImage_GetBlueMask(dib));
+
+ if (new_dib) {
+ // save ICC profile links
+ FIICCPROFILE *src_iccProfile = FreeImage_GetICCProfile(dib);
+ FIICCPROFILE *dst_iccProfile = FreeImage_GetICCProfile(new_dib);
+
+ // save metadata links
+ METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+ METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)new_dib->data)->metadata;
+
+ // calculate the size of a FreeImage image
+ // align the palette and the pixels on a FIBITMAP_ALIGNMENT bytes alignment boundary
+ // palette is aligned on a 16 bytes boundary
+ // pixels are aligned on a 16 bytes boundary
+
+ unsigned dib_size = FreeImage_GetImageSize(width, height, bpp);
+
+ // copy the bitmap + internal pointers (remember to restore new_dib internal pointers later)
+ memcpy(new_dib->data, dib->data, dib_size);
+
+ // reset ICC profile link for new_dib
+ memset(dst_iccProfile, 0, sizeof(FIICCPROFILE));
+
+ // restore metadata link for new_dib
+ ((FREEIMAGEHEADER *)new_dib->data)->metadata = dst_metadata;
+
+ // copy possible ICC profile
+ FreeImage_CreateICCProfile(new_dib, src_iccProfile->data, src_iccProfile->size);
+ dst_iccProfile->flags = src_iccProfile->flags;
+
+ // copy metadata models
+ for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
+ int model = (*i).first;
+ TAGMAP *src_tagmap = (*i).second;
+
+ if(src_tagmap) {
+ // create a metadata model
+ TAGMAP *dst_tagmap = new TAGMAP();
+
+ // fill the model
+ for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
+ std::string dst_key = (*j).first;
+ FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
+
+ // assign key and tag value
+ (*dst_tagmap)[dst_key] = dst_tag;
+ }
+
+ // assign model and tagmap
+ (*dst_metadata)[model] = dst_tagmap;
+ }
+ }
+
+ return new_dib;
+ }
+
+ return NULL;
+}
+
+// ----------------------------------------------------------
+
+FREE_IMAGE_COLOR_TYPE DLL_CALLCONV
+FreeImage_GetColorType(FIBITMAP *dib) {
+ RGBQUAD *rgb;
+
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ // special bitmap type
+ if(image_type != FIT_BITMAP) {
+ switch(image_type) {
+ case FIT_RGB16:
+ case FIT_RGBF:
+ return FIC_RGB;
+ case FIT_RGBA16:
+ case FIT_RGBAF:
+ return FIC_RGBALPHA;
+ }
+
+ return FIC_MINISBLACK;
+ }
+
+ // standard image type
+ switch (FreeImage_GetBPP(dib)) {
+ case 1:
+ {
+ rgb = FreeImage_GetPalette(dib);
+
+ if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0)) {
+ rgb++;
+
+ if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255))
+ return FIC_MINISBLACK;
+ }
+
+ if ((rgb->rgbRed == 255) && (rgb->rgbGreen == 255) && (rgb->rgbBlue == 255)) {
+ rgb++;
+
+ if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && (rgb->rgbBlue == 0))
+ return FIC_MINISWHITE;
+ }
+
+ return FIC_PALETTE;
+ }
+
+ case 4:
+ case 8: // Check if the DIB has a color or a greyscale palette
+ {
+ int ncolors = FreeImage_GetColorsUsed(dib);
+ int minisblack = 1;
+ rgb = FreeImage_GetPalette(dib);
+
+ for (int i = 0; i < ncolors; i++) {
+ if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue))
+ return FIC_PALETTE;
+
+ // The DIB has a color palette if the greyscale isn't a linear ramp
+ // Take care of reversed grey images
+ if (rgb->rgbRed != i) {
+ if ((ncolors-i-1) != rgb->rgbRed)
+ return FIC_PALETTE;
+ else
+ minisblack = 0;
+ }
+
+ rgb++;
+ }
+
+ return minisblack ? FIC_MINISBLACK : FIC_MINISWHITE;
+ }
+
+ case 16:
+ case 24:
+ return FIC_RGB;
+
+ case 32:
+ {
+ if (FreeImage_GetICCProfile(dib)->flags & FIICC_COLOR_IS_CMYK)
+ return FIC_CMYK;
+
+ for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ rgb = (RGBQUAD *)FreeImage_GetScanLine(dib, y);
+
+ for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++)
+ if (rgb[x].rgbReserved != 0xFF)
+ return FIC_RGBALPHA;
+ }
+
+ return FIC_RGB;
+ }
+
+ default :
+ return FIC_MINISBLACK;
+ }
+}
+
+// ----------------------------------------------------------
+
+FREE_IMAGE_TYPE DLL_CALLCONV
+FreeImage_GetImageType(FIBITMAP *dib) {
+ return (dib != NULL) ? ((FREEIMAGEHEADER *)dib->data)->type : FIT_UNKNOWN;
+}
+
+// ----------------------------------------------------------
+
+unsigned DLL_CALLCONV
+FreeImage_GetRedMask(FIBITMAP *dib) {
+ return dib ? ((FREEIMAGEHEADER *)dib->data)->red_mask : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetGreenMask(FIBITMAP *dib) {
+ return dib ? ((FREEIMAGEHEADER *)dib->data)->green_mask : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetBlueMask(FIBITMAP *dib) {
+ return dib ? ((FREEIMAGEHEADER *)dib->data)->blue_mask : 0;
+}
+
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_HasBackgroundColor(FIBITMAP *dib) {
+ if(dib) {
+ RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
+ return (bkgnd_color->rgbReserved != 0) ? TRUE : FALSE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_GetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) {
+ if(dib && bkcolor) {
+ if(FreeImage_HasBackgroundColor(dib)) {
+ // get the background color
+ RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
+ memcpy(bkcolor, bkgnd_color, sizeof(RGBQUAD));
+ // get the background index
+ if(FreeImage_GetBPP(dib) == 8) {
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++) {
+ if(bkgnd_color->rgbRed == pal[i].rgbRed) {
+ if(bkgnd_color->rgbGreen == pal[i].rgbGreen) {
+ if(bkgnd_color->rgbBlue == pal[i].rgbBlue) {
+ bkcolor->rgbReserved = (BYTE)i;
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+
+ bkcolor->rgbReserved = 0;
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetBackgroundColor(FIBITMAP *dib, RGBQUAD *bkcolor) {
+ if(dib) {
+ RGBQUAD *bkgnd_color = &((FREEIMAGEHEADER *)dib->data)->bkgnd_color;
+ if(bkcolor) {
+ // set the background color
+ memcpy(bkgnd_color, bkcolor, sizeof(RGBQUAD));
+ // enable the file background color
+ bkgnd_color->rgbReserved = 1;
+ } else {
+ // clear and disable the file background color
+ memset(bkgnd_color, 0, sizeof(RGBQUAD));
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_IsTransparent(FIBITMAP *dib) {
+ if(dib) {
+ if(FreeImage_GetBPP(dib) == 32) {
+ if(FreeImage_GetColorType(dib) == FIC_RGBALPHA) {
+ return TRUE;
+ }
+ } else {
+ return ((FREEIMAGEHEADER *)dib->data)->transparent ? TRUE : FALSE;
+ }
+ }
+ return FALSE;
+}
+
+BYTE * DLL_CALLCONV
+FreeImage_GetTransparencyTable(FIBITMAP *dib) {
+ return dib ? ((FREEIMAGEHEADER *)dib->data)->transparent_table : NULL;
+}
+
+void DLL_CALLCONV
+FreeImage_SetTransparent(FIBITMAP *dib, BOOL enabled) {
+ if (dib) {
+ if ((FreeImage_GetBPP(dib) <= 8) || (FreeImage_GetBPP(dib) == 32)) {
+ ((FREEIMAGEHEADER *)dib->data)->transparent = enabled;
+ } else {
+ ((FREEIMAGEHEADER *)dib->data)->transparent = FALSE;
+ }
+ }
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetTransparencyCount(FIBITMAP *dib) {
+ return dib ? ((FREEIMAGEHEADER *)dib->data)->transparency_count : 0;
+}
+
+void DLL_CALLCONV
+FreeImage_SetTransparencyTable(FIBITMAP *dib, BYTE *table, int count) {
+ if (dib) {
+ if (FreeImage_GetBPP(dib) <= 8) {
+ ((FREEIMAGEHEADER *)dib->data)->transparent = TRUE;
+ ((FREEIMAGEHEADER *)dib->data)->transparency_count = count;
+
+ if (table) {
+ memcpy(((FREEIMAGEHEADER *)dib->data)->transparent_table, table, count);
+ } else {
+ memset(((FREEIMAGEHEADER *)dib->data)->transparent_table, 0xff, count);
+ }
+ }
+ }
+}
+
+/** @brief Sets the index of the palette entry to be used as transparent color
+ for the image specified. Does nothing on high color images.
+
+ This method sets the index of the palette entry to be used as single transparent
+ color for the image specified. This works on palletised images only and does
+ nothing for high color images.
+
+ Although it is possible for palletised images to have more than one transparent
+ color, this method sets the palette entry specified as the single transparent
+ color for the image. All other colors will be set to be non-transparent by this
+ method.
+
+ As with FreeImage_SetTransparencyTable(), this method also sets the image's
+ transparency property to TRUE (as it is set and obtained by
+ FreeImage_SetTransparent() and FreeImage_IsTransparent() respectively) for
+ palletised images.
+
+ @param dib Input image, whose transparent color is to be set.
+ @param index The index of the palette entry to be set as transparent color.
+ */
+void DLL_CALLCONV
+FreeImage_SetTransparentIndex(FIBITMAP *dib, int index) {
+ if (dib) {
+ int count = FreeImage_GetColorsUsed(dib);
+ if (count) {
+ BYTE *new_tt = (BYTE *)malloc(count * sizeof(BYTE));
+ memset(new_tt, 0xFF, count);
+ if ((index >= 0) && (index < count)) {
+ new_tt[index] = 0x00;
+ }
+ FreeImage_SetTransparencyTable(dib, new_tt, count);
+ free(new_tt);
+ }
+ }
+}
+
+/** @brief Returns the palette entry used as transparent color for the image
+ specified. Works for palletised images only and returns -1 for high color
+ images or if the image has no color set to be transparent.
+
+ Although it is possible for palletised images to have more than one transparent
+ color, this function always returns the index of the first palette entry, set
+ to be transparent.
+
+ @param dib Input image, whose transparent color is to be returned.
+ @return Returns the index of the palette entry used as transparent color for
+ the image specified or -1 if there is no transparent color found (e.g. the image
+ is a high color image).
+ */
+int DLL_CALLCONV
+FreeImage_GetTransparentIndex(FIBITMAP *dib) {
+ int count = FreeImage_GetTransparencyCount(dib);
+ BYTE *tt = FreeImage_GetTransparencyTable(dib);
+ for (int i = 0; i < count; i++) {
+ if (tt[i] == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+// ----------------------------------------------------------
+
+FIICCPROFILE * DLL_CALLCONV
+FreeImage_GetICCProfile(FIBITMAP *dib) {
+ FIICCPROFILE *profile = (dib) ? (FIICCPROFILE *)&((FREEIMAGEHEADER *)dib->data)->iccProfile : NULL;
+ return profile;
+}
+
+FIICCPROFILE * DLL_CALLCONV
+FreeImage_CreateICCProfile(FIBITMAP *dib, void *data, long size) {
+ // clear the profile but preserve profile->flags
+ FreeImage_DestroyICCProfile(dib);
+ // create the new profile
+ FIICCPROFILE *profile = FreeImage_GetICCProfile(dib);
+ if(size && profile) {
+ profile->data = malloc(size);
+ if(profile->data) {
+ memcpy(profile->data, data, profile->size = size);
+ }
+ }
+ return profile;
+}
+
+void DLL_CALLCONV
+FreeImage_DestroyICCProfile(FIBITMAP *dib) {
+ FIICCPROFILE *profile = FreeImage_GetICCProfile(dib);
+ if(profile) {
+ if (profile->data) {
+ free (profile->data);
+ }
+ // clear the profile but preserve profile->flags
+ profile->data = NULL;
+ profile->size = 0;
+ }
+}
+
+// ----------------------------------------------------------
+
+unsigned DLL_CALLCONV
+FreeImage_GetWidth(FIBITMAP *dib) {
+ return dib ? FreeImage_GetInfoHeader(dib)->biWidth : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetHeight(FIBITMAP *dib) {
+ return (dib) ? FreeImage_GetInfoHeader(dib)->biHeight : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetBPP(FIBITMAP *dib) {
+ return dib ? FreeImage_GetInfoHeader(dib)->biBitCount : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetLine(FIBITMAP *dib) {
+ return dib ? ((FreeImage_GetWidth(dib) * FreeImage_GetBPP(dib)) + 7) / 8 : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetPitch(FIBITMAP *dib) {
+ return dib ? FreeImage_GetLine(dib) + 3 & ~3 : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetColorsUsed(FIBITMAP *dib) {
+ return dib ? FreeImage_GetInfoHeader(dib)->biClrUsed : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetDIBSize(FIBITMAP *dib) {
+ return (dib) ? sizeof(BITMAPINFOHEADER) + (FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD)) + (FreeImage_GetPitch(dib) * FreeImage_GetHeight(dib)) : 0;
+}
+
+RGBQUAD * DLL_CALLCONV
+FreeImage_GetPalette(FIBITMAP *dib) {
+ return (dib && FreeImage_GetBPP(dib) < 16) ? (RGBQUAD *)(((BYTE *)FreeImage_GetInfoHeader(dib)) + sizeof(BITMAPINFOHEADER)) : NULL;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetDotsPerMeterX(FIBITMAP *dib) {
+ return (dib) ? FreeImage_GetInfoHeader(dib)->biXPelsPerMeter : 0;
+}
+
+unsigned DLL_CALLCONV
+FreeImage_GetDotsPerMeterY(FIBITMAP *dib) {
+ return (dib) ? FreeImage_GetInfoHeader(dib)->biYPelsPerMeter : 0;
+}
+
+void DLL_CALLCONV
+FreeImage_SetDotsPerMeterX(FIBITMAP *dib, unsigned res) {
+ if(dib) {
+ FreeImage_GetInfoHeader(dib)->biXPelsPerMeter = res;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_SetDotsPerMeterY(FIBITMAP *dib, unsigned res) {
+ if(dib) {
+ FreeImage_GetInfoHeader(dib)->biYPelsPerMeter = res;
+ }
+}
+
+BITMAPINFOHEADER * DLL_CALLCONV
+FreeImage_GetInfoHeader(FIBITMAP *dib) {
+ if(!dib) return NULL;
+ size_t lp = (size_t)dib->data + sizeof(FREEIMAGEHEADER);
+ lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0);
+ lp += FIBITMAP_ALIGNMENT - sizeof(BITMAPINFOHEADER) % FIBITMAP_ALIGNMENT;
+ return (BITMAPINFOHEADER *)lp;
+}
+
+BITMAPINFO * DLL_CALLCONV
+FreeImage_GetInfo(FIBITMAP *dib) {
+ return (BITMAPINFO *)FreeImage_GetInfoHeader(dib);
+}
+
+// ----------------------------------------------------------
+// Metadata routines
+// ----------------------------------------------------------
+
+FIMETADATA * DLL_CALLCONV
+FreeImage_FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, FITAG **tag) {
+ if(!dib)
+ return NULL;
+
+ // get the metadata model
+ METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+ TAGMAP *tagmap = NULL;
+ if( (*metadata).find(model) != (*metadata).end() ) {
+ tagmap = (*metadata)[model];
+ }
+ if(tagmap) {
+ // allocate a handle
+ FIMETADATA *handle = (FIMETADATA *)malloc(sizeof(FIMETADATA));
+ if(handle) {
+ // calculate the size of a METADATAHEADER
+ int header_size = sizeof(METADATAHEADER);
+
+ handle->data = (BYTE *)malloc(header_size * sizeof(BYTE));
+
+ if(handle->data) {
+ memset(handle->data, 0, header_size * sizeof(BYTE));
+
+ // write out the METADATAHEADER
+ METADATAHEADER *mdh = (METADATAHEADER *)handle->data;
+
+ mdh->pos = 1;
+ mdh->tagmap = tagmap;
+
+ // get the first element
+ TAGMAP::iterator i = tagmap->begin();
+ *tag = (*i).second;
+
+ return handle;
+ }
+
+ free(handle);
+ }
+ }
+
+ return NULL;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FindNextMetadata(FIMETADATA *mdhandle, FITAG **tag) {
+ if(!mdhandle)
+ return FALSE;
+
+ METADATAHEADER *mdh = (METADATAHEADER *)mdhandle->data;
+ TAGMAP *tagmap = mdh->tagmap;
+
+ int current_pos = mdh->pos;
+ int mapsize = (int)tagmap->size();
+
+ if(current_pos < mapsize) {
+ // get the tag element at position pos
+ int count = 0;
+
+ for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
+ if(count == current_pos) {
+ *tag = (*i).second;
+ mdh->pos++;
+ break;
+ }
+ count++;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void DLL_CALLCONV
+FreeImage_FindCloseMetadata(FIMETADATA *mdhandle) {
+ if (NULL != mdhandle) { // delete the handle
+ if (NULL != mdhandle->data) {
+ free(mdhandle->data);
+ }
+ free(mdhandle); // ... and the wrapper
+ }
+}
+
+
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_CloneMetadata(FIBITMAP *dst, FIBITMAP *src) {
+ if(!src || !dst) return FALSE;
+
+ // get metadata links
+ METADATAMAP *src_metadata = ((FREEIMAGEHEADER *)src->data)->metadata;
+ METADATAMAP *dst_metadata = ((FREEIMAGEHEADER *)dst->data)->metadata;
+
+ // copy metadata models, *except* the FIMD_ANIMATION model
+ for(METADATAMAP::iterator i = (*src_metadata).begin(); i != (*src_metadata).end(); i++) {
+ int model = (*i).first;
+ if(model == (int)FIMD_ANIMATION) {
+ continue;
+ }
+ TAGMAP *src_tagmap = (*i).second;
+
+ if(src_tagmap) {
+ if( dst_metadata->find(model) != dst_metadata->end() ) {
+ // destroy dst model
+ FreeImage_SetMetadata((FREE_IMAGE_MDMODEL)model, dst, NULL, NULL);
+ }
+
+ // create a metadata model
+ TAGMAP *dst_tagmap = new TAGMAP();
+
+ // fill the model
+ for(TAGMAP::iterator j = src_tagmap->begin(); j != src_tagmap->end(); j++) {
+ std::string dst_key = (*j).first;
+ FITAG *dst_tag = FreeImage_CloneTag( (*j).second );
+
+ // assign key and tag value
+ (*dst_tagmap)[dst_key] = dst_tag;
+ }
+
+ // assign model and tagmap
+ (*dst_metadata)[model] = dst_tagmap;
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG *tag) {
+ if(!dib)
+ return FALSE;
+
+ TAGMAP *tagmap = NULL;
+
+ // get the metadata model
+ METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+ METADATAMAP::iterator model_iterator = metadata->find(model);
+ if (model_iterator != metadata->end()) {
+ tagmap = model_iterator->second;
+ }
+
+ if(key != NULL) {
+
+ if(!tagmap) {
+ // this model, doesn't exist: create it
+ tagmap = new TAGMAP();
+ (*metadata)[model] = tagmap;
+ }
+
+ if(tag) {
+ // first check the tag
+ if(FreeImage_GetTagKey(tag) == NULL) {
+ FreeImage_SetTagKey(tag, key);
+ } else if(strcmp(key, FreeImage_GetTagKey(tag)) != 0) {
+ // set the tag key
+ FreeImage_SetTagKey(tag, key);
+ }
+ if(FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth((WORD)FreeImage_GetTagType(tag)) != FreeImage_GetTagLength(tag)) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Invalid data count for tag '%s'", key);
+ return FALSE;
+ }
+
+ // fill the tag ID if possible and if it's needed
+ TagLib& tag_lib = TagLib::instance();
+ switch(model) {
+ case FIMD_IPTC:
+ {
+ int id = tag_lib.getTagID(TagLib::IPTC, key);
+ /*
+ if(id == -1) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "IPTC: Invalid key '%s'", key);
+ }
+ */
+ FreeImage_SetTagID(tag, (WORD)id);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // delete existing tag
+ FITAG *old_tag = (*tagmap)[key];
+ if(old_tag) {
+ FreeImage_DeleteTag(old_tag);
+ }
+
+ // create a new tag
+ (*tagmap)[key] = FreeImage_CloneTag(tag);
+ }
+ else {
+ // delete existing tag
+ TAGMAP::iterator i = tagmap->find(key);
+ if(i != tagmap->end()) {
+ FITAG *old_tag = (*i).second;
+ FreeImage_DeleteTag(old_tag);
+ tagmap->erase(key);
+ }
+ }
+ }
+ else {
+ // destroy the metadata model
+ if(tagmap) {
+ for(TAGMAP::iterator i = tagmap->begin(); i != tagmap->end(); i++) {
+ FITAG *tag = (*i).second;
+ FreeImage_DeleteTag(tag);
+ }
+
+ delete tagmap;
+ metadata->erase(model_iterator);
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FITAG **tag) {
+ if(!dib || !key || !tag)
+ return FALSE;
+
+ TAGMAP *tagmap = NULL;
+ *tag = NULL;
+
+ // get the metadata model
+ METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+ if(!(*metadata).empty()) {
+ METADATAMAP::iterator model_iterator = metadata->find(model);
+ if (model_iterator != metadata->end() ) {
+ // this model exists : try to get the requested tag
+ tagmap = model_iterator->second;
+ TAGMAP::iterator tag_iterator = tagmap->find(key);
+ if (tag_iterator != tagmap->end() ) {
+ // get the requested tag
+ *tag = tag_iterator->second;
+ }
+ }
+ }
+
+ return (*tag != NULL) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+unsigned DLL_CALLCONV
+FreeImage_GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP *dib) {
+ if(!dib)
+ return FALSE;
+
+ TAGMAP *tagmap = NULL;
+
+ // get the metadata model
+ METADATAMAP *metadata = ((FREEIMAGEHEADER *)dib->data)->metadata;
+ if( (*metadata).find(model) != (*metadata).end() ) {
+ tagmap = (*metadata)[model];
+ }
+ if(!tagmap) {
+ // this model, doesn't exist: return
+ return 0;
+ }
+
+ // get the tag count
+ return (unsigned)tagmap->size();
+}
+
+// ----------------------------------------------------------
+
+
diff --git a/Source/FreeImage/CacheFile.cpp b/Source/FreeImage/CacheFile.cpp
new file mode 100644
index 0000000..16f0531
--- /dev/null
+++ b/Source/FreeImage/CacheFile.cpp
@@ -0,0 +1,274 @@
+// ==========================================================
+// Multi-Page functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - checkered (checkered@users.sourceforge.net)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "CacheFile.h"
+
+// ----------------------------------------------------------
+
+CacheFile::CacheFile(const char *filename, BOOL keep_in_memory) :
+m_file(NULL),
+m_filename(),
+m_free_pages(),
+m_page_cache_mem(),
+m_page_cache_disk(),
+m_page_map(),
+m_page_count(0),
+m_current_block(NULL),
+m_keep_in_memory(keep_in_memory) {
+ if (filename) {
+ m_filename = filename;
+ }
+}
+
+CacheFile::~CacheFile() {
+}
+
+BOOL
+CacheFile::open() {
+ if ((!m_filename.empty()) && (!m_keep_in_memory)) {
+ m_file = fopen(m_filename.c_str(), "w+b");
+ return (m_file != NULL);
+ }
+
+ return (m_keep_in_memory == TRUE);
+}
+
+void
+CacheFile::close() {
+ // dispose the cache entries
+
+ while (!m_page_cache_disk.empty()) {
+ Block *block = *m_page_cache_disk.begin();
+ m_page_cache_disk.pop_front();
+ delete [] block->data;
+ delete block;
+ }
+ while (!m_page_cache_mem.empty()) {
+ Block *block = *m_page_cache_mem.begin();
+ m_page_cache_mem.pop_front();
+ delete [] block->data;
+ delete block;
+ }
+
+ if (m_file) {
+ // close the file
+
+ fclose(m_file);
+
+ // delete the file
+
+ remove(m_filename.c_str());
+ }
+}
+
+void
+CacheFile::cleanupMemCache() {
+ if (!m_keep_in_memory) {
+ if (m_page_cache_mem.size() > CACHE_SIZE) {
+ // flush the least used block to file
+
+ Block *old_block = m_page_cache_mem.back();
+ fseek(m_file, old_block->nr * BLOCK_SIZE, SEEK_SET);
+ fwrite(old_block->data, BLOCK_SIZE, 1, m_file);
+
+ // remove the data
+
+ delete [] old_block->data;
+ old_block->data = NULL;
+
+ // move the block to another list
+
+ m_page_cache_disk.splice(m_page_cache_disk.begin(), m_page_cache_mem, --m_page_cache_mem.end());
+ m_page_map[old_block->nr] = m_page_cache_disk.begin();
+ }
+ }
+}
+
+int
+CacheFile::allocateBlock() {
+ Block *block = new Block;
+ block->data = new BYTE[BLOCK_SIZE];
+ block->next = 0;
+
+ if (!m_free_pages.empty()) {
+ block->nr = *m_free_pages.begin();
+ m_free_pages.pop_front();
+ } else {
+ block->nr = m_page_count++;
+ }
+
+ m_page_cache_mem.push_front(block);
+ m_page_map[block->nr] = m_page_cache_mem.begin();
+
+ cleanupMemCache();
+
+ return block->nr;
+}
+
+Block *
+CacheFile::lockBlock(int nr) {
+ if (m_current_block == NULL) {
+ PageMapIt it = m_page_map.find(nr);
+
+ if (it != m_page_map.end()) {
+ m_current_block = *(it->second);
+
+ // the block is swapped out to disc. load it back
+ // and remove the block from the cache. it might get cached
+ // again as soon as the memory buffer fills up
+
+ if (m_current_block->data == NULL) {
+ m_current_block->data = new BYTE[BLOCK_SIZE];
+
+ fseek(m_file, m_current_block->nr * BLOCK_SIZE, SEEK_SET);
+ fread(m_current_block->data, BLOCK_SIZE, 1, m_file);
+
+ m_page_cache_mem.splice(m_page_cache_mem.begin(), m_page_cache_disk, it->second);
+ m_page_map[nr] = m_page_cache_mem.begin();
+ }
+
+ // if the memory cache size is too large, swap an item to disc
+
+ cleanupMemCache();
+
+ // return the current block
+
+ return m_current_block;
+ }
+ }
+
+ return NULL;
+}
+
+BOOL
+CacheFile::unlockBlock(int nr) {
+ if (m_current_block) {
+ m_current_block = NULL;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL
+CacheFile::deleteBlock(int nr) {
+ if (!m_current_block) {
+ PageMapIt it = m_page_map.find(nr);
+
+ // remove block from cache
+
+ if (it != m_page_map.end())
+ m_page_map.erase(nr);
+
+ // add block to free page list
+
+ m_free_pages.push_back(nr);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL
+CacheFile::readFile(BYTE *data, int nr, int size) {
+ if ((data) && (size > 0)) {
+ int s = 0;
+ int block_nr = nr;
+
+ do {
+ int copy_nr = block_nr;
+
+ Block *block = lockBlock(copy_nr);
+
+ block_nr = block->next;
+
+ memcpy(data + s, block->data, (s + BLOCK_SIZE > size) ? size - s : BLOCK_SIZE);
+
+ unlockBlock(copy_nr);
+
+ s += BLOCK_SIZE;
+ } while (block_nr != 0);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int
+CacheFile::writeFile(BYTE *data, int size) {
+ if ((data) && (size > 0)) {
+ int nr_blocks_required = 1 + (size / BLOCK_SIZE);
+ int count = 0;
+ int s = 0;
+ int stored_alloc;
+ int alloc;
+
+ stored_alloc = alloc = allocateBlock();
+
+ do {
+ int copy_alloc = alloc;
+
+ Block *block = lockBlock(copy_alloc);
+
+ block->next = 0;
+
+ memcpy(block->data, data + s, (s + BLOCK_SIZE > size) ? size - s : BLOCK_SIZE);
+
+ if (count + 1 < nr_blocks_required)
+ alloc = block->next = allocateBlock();
+
+ unlockBlock(copy_alloc);
+
+ s += BLOCK_SIZE;
+ } while (++count < nr_blocks_required);
+
+ return stored_alloc;
+ }
+
+ return 0;
+}
+
+void
+CacheFile::deleteFile(int nr) {
+ do {
+ Block *block = lockBlock(nr);
+
+ if (block == NULL)
+ break;
+
+ int next = block->next;
+
+ unlockBlock(nr);
+
+ deleteBlock(nr);
+
+ nr = next;
+ } while (nr != 0);
+}
+
diff --git a/Source/FreeImage/ColorLookup.cpp b/Source/FreeImage/ColorLookup.cpp
new file mode 100644
index 0000000..9e9d779
--- /dev/null
+++ b/Source/FreeImage/ColorLookup.cpp
@@ -0,0 +1,782 @@
+// ==========================================================
+// X11 and SVG Color name lookup
+//
+// Design and implementation by
+// - Karl-Heinz Bussian (khbussian@moss.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// RGB color names ---------------------------------------------------------
+
+typedef struct tagNamedColor {
+ char *name; // color name
+ BYTE r; // red value
+ BYTE g; // green value
+ BYTE b; // blue value
+} NamedColor;
+
+// --------------------------------------------------------------------------
+
+/**
+Helper function : perform a binary search on a color array
+@param name Color name
+@param color_array Color array
+@param n Length of the color array
+@return Returns the color index in the array if successful, returns -1 otherwise
+*/
+static int
+binsearch(const char *name, const NamedColor *color_array, int n) {
+ int cond, low, mid, high;
+
+ low = 0;
+ high = n - 1;
+ while (low <= high) {
+ mid = (low + high) / 2;
+ if ((cond = strcmp(name, color_array[mid].name)) < 0)
+ high = mid - 1;
+ else if (cond > 0)
+ low = mid + 1;
+ else
+ return mid;
+ }
+ return -1;
+}
+
+/**
+Perform a binary search on a color array
+@param szColor Color name
+@param color_array Color array
+@param ncolors Length of the color array
+@return Returns the color index in the array if successful, returns -1 otherwise
+*/
+static int
+FreeImage_LookupNamedColor(const char *szColor, const NamedColor *color_array, int ncolors) {
+ int i;
+ char color[64];
+
+ // make lower case name, squezze white space
+
+ for (i = 0; szColor[i] && i < sizeof(color) - 1; i++) {
+ if (isspace(szColor[i]))
+ continue;
+ if (isupper(szColor[i]))
+ color[i] = (char)tolower(szColor[i]);
+ else
+ color[i] = szColor[i];
+ }
+ color[i] = 0;
+
+ return (binsearch(color, color_array, ncolors));
+}
+
+// ==========================================================
+// X11 Color name lookup
+
+/**
+ This big list of color names was formed from the file: /usr/X11R6/lib/X11/rgb.txt
+ found on a standard Linux installation.
+*/
+
+static NamedColor X11ColorMap[] = {
+ { "aliceblue", 240, 248, 255 },
+ { "antiquewhite", 250, 235, 215 },
+ { "antiquewhite1", 255, 239, 219 },
+ { "antiquewhite2", 238, 223, 204 },
+ { "antiquewhite3", 205, 192, 176 },
+ { "antiquewhite4", 139, 131, 120 },
+ { "aquamarine", 127, 255, 212 },
+ { "aquamarine1", 127, 255, 212 },
+ { "aquamarine2", 118, 238, 198 },
+ { "aquamarine3", 102, 205, 170 },
+ { "aquamarine4", 69, 139, 116 },
+ { "azure", 240, 255, 255 },
+ { "azure1", 240, 255, 255 },
+ { "azure2", 224, 238, 238 },
+ { "azure3", 193, 205, 205 },
+ { "azure4", 131, 139, 139 },
+ { "beige", 245, 245, 220 },
+ { "bisque", 255, 228, 196 },
+ { "bisque1", 255, 228, 196 },
+ { "bisque2", 238, 213, 183 },
+ { "bisque3", 205, 183, 158 },
+ { "bisque4", 139, 125, 107 },
+ { "black", 0, 0, 0 },
+ { "blanchedalmond", 255, 235, 205 },
+ { "blue", 0, 0, 255 },
+ { "blue1", 0, 0, 255 },
+ { "blue2", 0, 0, 238 },
+ { "blue3", 0, 0, 205 },
+ { "blue4", 0, 0, 139 },
+ { "blueviolet", 138, 43, 226 },
+ { "brown", 165, 42, 42 },
+ { "brown1", 255, 64, 64 },
+ { "brown2", 238, 59, 59 },
+ { "brown3", 205, 51, 51 },
+ { "brown4", 139, 35, 35 },
+ { "burlywood", 222, 184, 135 },
+ { "burlywood1", 255, 211, 155 },
+ { "burlywood2", 238, 197, 145 },
+ { "burlywood3", 205, 170, 125 },
+ { "burlywood4", 139, 115, 85 },
+ { "cadetblue", 95, 158, 160 },
+ { "cadetblue1", 152, 245, 255 },
+ { "cadetblue2", 142, 229, 238 },
+ { "cadetblue3", 122, 197, 205 },
+ { "cadetblue4", 83, 134, 139 },
+ { "chartreuse", 127, 255, 0 },
+ { "chartreuse1", 127, 255, 0 },
+ { "chartreuse2", 118, 238, 0 },
+ { "chartreuse3", 102, 205, 0 },
+ { "chartreuse4", 69, 139, 0 },
+ { "chocolate", 210, 105, 30 },
+ { "chocolate1", 255, 127, 36 },
+ { "chocolate2", 238, 118, 33 },
+ { "chocolate3", 205, 102, 29 },
+ { "chocolate4", 139, 69, 19 },
+ { "coral", 255, 127, 80 },
+ { "coral1", 255, 114, 86 },
+ { "coral2", 238, 106, 80 },
+ { "coral3", 205, 91, 69 },
+ { "coral4", 139, 62, 47 },
+ { "cornflowerblue", 100, 149, 237 },
+ { "cornsilk", 255, 248, 220 },
+ { "cornsilk1", 255, 248, 220 },
+ { "cornsilk2", 238, 232, 205 },
+ { "cornsilk3", 205, 200, 177 },
+ { "cornsilk4", 139, 136, 120 },
+ { "cyan", 0, 255, 255 },
+ { "cyan1", 0, 255, 255 },
+ { "cyan2", 0, 238, 238 },
+ { "cyan3", 0, 205, 205 },
+ { "cyan4", 0, 139, 139 },
+ { "darkblue", 0, 0, 139 },
+ { "darkcyan", 0, 139, 139 },
+ { "darkgoldenrod", 184, 134, 11 },
+ { "darkgoldenrod1", 255, 185, 15 },
+ { "darkgoldenrod2", 238, 173, 14 },
+ { "darkgoldenrod3", 205, 149, 12 },
+ { "darkgoldenrod4", 139, 101, 8 },
+ { "darkgreen", 0, 100, 0 },
+ { "darkkhaki", 189, 183, 107 },
+ { "darkmagenta", 139, 0, 139 },
+ { "darkolivegreen", 85, 107, 47 },
+ { "darkolivegreen1", 202, 255, 112 },
+ { "darkolivegreen2", 188, 238, 104 },
+ { "darkolivegreen3", 162, 205, 90 },
+ { "darkolivegreen4", 110, 139, 61 },
+ { "darkorange", 255, 140, 0 },
+ { "darkorange1", 255, 127, 0 },
+ { "darkorange2", 238, 118, 0 },
+ { "darkorange3", 205, 102, 0 },
+ { "darkorange4", 139, 69, 0 },
+ { "darkorchid", 153, 50, 204 },
+ { "darkorchid1", 191, 62, 255 },
+ { "darkorchid2", 178, 58, 238 },
+ { "darkorchid3", 154, 50, 205 },
+ { "darkorchid4", 104, 34, 139 },
+ { "darkred", 139, 0, 0 },
+ { "darksalmon", 233, 150, 122 },
+ { "darkseagreen", 143, 188, 143 },
+ { "darkseagreen1", 193, 255, 193 },
+ { "darkseagreen2", 180, 238, 180 },
+ { "darkseagreen3", 155, 205, 155 },
+ { "darkseagreen4", 105, 139, 105 },
+ { "darkslateblue", 72, 61, 139 },
+ { "darkslategray", 47, 79, 79 },
+ { "darkslategray1", 151, 255, 255 },
+ { "darkslategray2", 141, 238, 238 },
+ { "darkslategray3", 121, 205, 205 },
+ { "darkslategray4", 82, 139, 139 },
+ { "darkslategrey", 47, 79, 79 },
+ { "darkturquoise", 0, 206, 209 },
+ { "darkviolet", 148, 0, 211 },
+ { "deeppink", 255, 20, 147 },
+ { "deeppink1", 255, 20, 147 },
+ { "deeppink2", 238, 18, 137 },
+ { "deeppink3", 205, 16, 118 },
+ { "deeppink4", 139, 10, 80 },
+ { "deepskyblue", 0, 191, 255 },
+ { "deepskyblue1", 0, 191, 255 },
+ { "deepskyblue2", 0, 178, 238 },
+ { "deepskyblue3", 0, 154, 205 },
+ { "deepskyblue4", 0, 104, 139 },
+ { "dimgray", 105, 105, 105 },
+ { "dimgrey", 105, 105, 105 },
+ { "dodgerblue", 30, 144, 255 },
+ { "dodgerblue1", 30, 144, 255 },
+ { "dodgerblue2", 28, 134, 238 },
+ { "dodgerblue3", 24, 116, 205 },
+ { "dodgerblue4", 16, 78, 139 },
+ { "firebrick", 178, 34, 34 },
+ { "firebrick1", 255, 48, 48 },
+ { "firebrick2", 238, 44, 44 },
+ { "firebrick3", 205, 38, 38 },
+ { "firebrick4", 139, 26, 26 },
+ { "floralwhite", 255, 250, 240 },
+ { "forestgreen", 176, 48, 96 },
+ { "gainsboro", 220, 220, 220 },
+ { "ghostwhite", 248, 248, 255 },
+ { "gold", 255, 215, 0 },
+ { "gold1", 255, 215, 0 },
+ { "gold2", 238, 201, 0 },
+ { "gold3", 205, 173, 0 },
+ { "gold4", 139, 117, 0 },
+ { "goldenrod", 218, 165, 32 },
+ { "goldenrod1", 255, 193, 37 },
+ { "goldenrod2", 238, 180, 34 },
+ { "goldenrod3", 205, 155, 29 },
+ { "goldenrod4", 139, 105, 20 },
+ { "gray", 190, 190, 190 },
+ { "green", 0, 255, 0 },
+ { "green1", 0, 255, 0 },
+ { "green2", 0, 238, 0 },
+ { "green3", 0, 205, 0 },
+ { "green4", 0, 139, 0 },
+ { "greenyellow", 173, 255, 47 },
+ { "grey", 190, 190, 190 },
+ { "honeydew", 240, 255, 240 },
+ { "honeydew1", 240, 255, 240 },
+ { "honeydew2", 224, 238, 224 },
+ { "honeydew3", 193, 205, 193 },
+ { "honeydew4", 131, 139, 131 },
+ { "hotpink", 255, 105, 180 },
+ { "hotpink1", 255, 110, 180 },
+ { "hotpink2", 238, 106, 167 },
+ { "hotpink3", 205, 96, 144 },
+ { "hotpink4", 139, 58, 98 },
+ { "indianred", 205, 92, 92 },
+ { "indianred1", 255, 106, 106 },
+ { "indianred2", 238, 99, 99 },
+ { "indianred3", 205, 85, 85 },
+ { "indianred4", 139, 58, 58 },
+ { "ivory", 255, 255, 240 },
+ { "ivory1", 255, 255, 240 },
+ { "ivory2", 238, 238, 224 },
+ { "ivory3", 205, 205, 193 },
+ { "ivory4", 139, 139, 131 },
+ { "khaki", 240, 230, 140 },
+ { "khaki1", 255, 246, 143 },
+ { "khaki2", 238, 230, 133 },
+ { "khaki3", 205, 198, 115 },
+ { "khaki4", 139, 134, 78 },
+ { "lavender", 230, 230, 250 },
+ { "lavenderblush", 255, 240, 245 },
+ { "lavenderblush1", 255, 240, 245 },
+ { "lavenderblush2", 238, 224, 229 },
+ { "lavenderblush3", 205, 193, 197 },
+ { "lavenderblush4", 139, 131, 134 },
+ { "lawngreen", 124, 252, 0 },
+ { "lemonchiffon", 255, 250, 205 },
+ { "lemonchiffon1", 255, 250, 205 },
+ { "lemonchiffon2", 238, 233, 191 },
+ { "lemonchiffon3", 205, 201, 165 },
+ { "lemonchiffon4", 139, 137, 112 },
+ { "lightblue", 173, 216, 230 },
+ { "lightblue1", 191, 239, 255 },
+ { "lightblue2", 178, 223, 238 },
+ { "lightblue3", 154, 192, 205 },
+ { "lightblue4", 104, 131, 139 },
+ { "lightcoral", 240, 128, 128 },
+ { "lightcyan", 224, 255, 255 },
+ { "lightcyan1", 224, 255, 255 },
+ { "lightcyan2", 209, 238, 238 },
+ { "lightcyan3", 180, 205, 205 },
+ { "lightcyan4", 122, 139, 139 },
+ { "lightgoldenrod", 238, 221, 130 },
+ { "lightgoldenrod1", 255, 236, 139 },
+ { "lightgoldenrod2", 238, 220, 130 },
+ { "lightgoldenrod3", 205, 190, 112 },
+ { "lightgoldenrod4", 139, 129, 76 },
+ { "lightgoldenrodyellow", 250, 250, 210 },
+ { "lightgray", 211, 211, 211 },
+ { "lightgreen", 144, 238, 144 },
+ { "lightgrey", 211, 211, 211 },
+ { "lightpink", 255, 182, 193 },
+ { "lightpink1", 255, 174, 185 },
+ { "lightpink2", 238, 162, 173 },
+ { "lightpink3", 205, 140, 149 },
+ { "lightpink4", 139, 95, 101 },
+ { "lightsalmon", 255, 160, 122 },
+ { "lightsalmon1", 255, 160, 122 },
+ { "lightsalmon2", 238, 149, 114 },
+ { "lightsalmon3", 205, 129, 98 },
+ { "lightsalmon4", 139, 87, 66 },
+ { "lightseagreen", 32, 178, 170 },
+ { "lightskyblue", 135, 206, 250 },
+ { "lightskyblue1", 176, 226, 255 },
+ { "lightskyblue2", 164, 211, 238 },
+ { "lightskyblue3", 141, 182, 205 },
+ { "lightskyblue4", 96, 123, 139 },
+ { "lightslateblue", 132, 112, 255 },
+ { "lightslategray", 119, 136, 153 },
+ { "lightslategrey", 119, 136, 153 },
+ { "lightsteelblue", 176, 196, 222 },
+ { "lightsteelblue1", 202, 225, 255 },
+ { "lightsteelblue2", 188, 210, 238 },
+ { "lightsteelblue3", 162, 181, 205 },
+ { "lightsteelblue4", 110, 123, 139 },
+ { "lightyellow", 255, 255, 224 },
+ { "lightyellow1", 255, 255, 224 },
+ { "lightyellow2", 238, 238, 209 },
+ { "lightyellow3", 205, 205, 180 },
+ { "lightyellow4", 139, 139, 122 },
+ { "limegreen", 50, 205, 50 },
+ { "linen", 250, 240, 230 },
+ { "magenta", 255, 0, 255 },
+ { "magenta1", 255, 0, 255 },
+ { "magenta2", 238, 0, 238 },
+ { "magenta3", 205, 0, 205 },
+ { "magenta4", 139, 0, 139 },
+ { "maroon", 0, 255, 255 },
+ { "maroon1", 255, 52, 179 },
+ { "maroon2", 238, 48, 167 },
+ { "maroon3", 205, 41, 144 },
+ { "maroon4", 139, 28, 98 },
+ { "mediumaquamarine", 102, 205, 170 },
+ { "mediumblue", 0, 0, 205 },
+ { "mediumorchid", 186, 85, 211 },
+ { "mediumorchid1", 224, 102, 255 },
+ { "mediumorchid2", 209, 95, 238 },
+ { "mediumorchid3", 180, 82, 205 },
+ { "mediumorchid4", 122, 55, 139 },
+ { "mediumpurple", 147, 112, 219 },
+ { "mediumpurple1", 171, 130, 255 },
+ { "mediumpurple2", 159, 121, 238 },
+ { "mediumpurple3", 137, 104, 205 },
+ { "mediumpurple4", 93, 71, 139 },
+ { "mediumseagreen", 60, 179, 113 },
+ { "mediumslateblue", 123, 104, 238 },
+ { "mediumspringgreen", 0, 250, 154 },
+ { "mediumturquoise", 72, 209, 204 },
+ { "mediumvioletred", 199, 21, 133 },
+ { "midnightblue", 25, 25, 112 },
+ { "mintcream", 245, 255, 250 },
+ { "mistyrose", 255, 228, 225 },
+ { "mistyrose1", 255, 228, 225 },
+ { "mistyrose2", 238, 213, 210 },
+ { "mistyrose3", 205, 183, 181 },
+ { "mistyrose4", 139, 125, 123 },
+ { "moccasin", 255, 228, 181 },
+ { "navajowhite", 255, 222, 173 },
+ { "navajowhite1", 255, 222, 173 },
+ { "navajowhite2", 238, 207, 161 },
+ { "navajowhite3", 205, 179, 139 },
+ { "navajowhite4", 139, 121, 94 },
+ { "navy", 0, 0, 128 },
+ { "navyblue", 0, 0, 128 },
+ { "oldlace", 253, 245, 230 },
+ { "olivedrab", 107, 142, 35 },
+ { "olivedrab1", 192, 255, 62 },
+ { "olivedrab2", 179, 238, 58 },
+ { "olivedrab3", 154, 205, 50 },
+ { "olivedrab4", 105, 139, 34 },
+ { "orange", 255, 165, 0 },
+ { "orange1", 255, 165, 0 },
+ { "orange2", 238, 154, 0 },
+ { "orange3", 205, 133, 0 },
+ { "orange4", 139, 90, 0 },
+ { "orangered", 255, 69, 0 },
+ { "orangered1", 255, 69, 0 },
+ { "orangered2", 238, 64, 0 },
+ { "orangered3", 205, 55, 0 },
+ { "orangered4", 139, 37, 0 },
+ { "orchid", 218, 112, 214 },
+ { "orchid1", 255, 131, 250 },
+ { "orchid2", 238, 122, 233 },
+ { "orchid3", 205, 105, 201 },
+ { "orchid4", 139, 71, 137 },
+ { "palegoldenrod", 238, 232, 170 },
+ { "palegreen", 152, 251, 152 },
+ { "palegreen1", 154, 255, 154 },
+ { "palegreen2", 144, 238, 144 },
+ { "palegreen3", 124, 205, 124 },
+ { "palegreen4", 84, 139, 84 },
+ { "paleturquoise", 175, 238, 238 },
+ { "paleturquoise1", 187, 255, 255 },
+ { "paleturquoise2", 174, 238, 238 },
+ { "paleturquoise3", 150, 205, 205 },
+ { "paleturquoise4", 102, 139, 139 },
+ { "palevioletred", 219, 112, 147 },
+ { "palevioletred1", 255, 130, 171 },
+ { "palevioletred2", 238, 121, 159 },
+ { "palevioletred3", 205, 104, 137 },
+ { "palevioletred4", 139, 71, 93 },
+ { "papayawhip", 255, 239, 213 },
+ { "peachpuff", 255, 218, 185 },
+ { "peachpuff1", 255, 218, 185 },
+ { "peachpuff2", 238, 203, 173 },
+ { "peachpuff3", 205, 175, 149 },
+ { "peachpuff4", 139, 119, 101 },
+ { "peru", 205, 133, 63 },
+ { "pink", 255, 192, 203 },
+ { "pink1", 255, 181, 197 },
+ { "pink2", 238, 169, 184 },
+ { "pink3", 205, 145, 158 },
+ { "pink4", 139, 99, 108 },
+ { "plum", 221, 160, 221 },
+ { "plum1", 255, 187, 255 },
+ { "plum2", 238, 174, 238 },
+ { "plum3", 205, 150, 205 },
+ { "plum4", 139, 102, 139 },
+ { "powderblue", 176, 224, 230 },
+ { "purple", 160, 32, 240 },
+ { "purple1", 155, 48, 255 },
+ { "purple2", 145, 44, 238 },
+ { "purple3", 125, 38, 205 },
+ { "purple4", 85, 26, 139 },
+ { "red", 255, 0, 0 },
+ { "red1", 255, 0, 0 },
+ { "red2", 238, 0, 0 },
+ { "red3", 205, 0, 0 },
+ { "red4", 139, 0, 0 },
+ { "rosybrown", 188, 143, 143 },
+ { "rosybrown1", 255, 193, 193 },
+ { "rosybrown2", 238, 180, 180 },
+ { "rosybrown3", 205, 155, 155 },
+ { "rosybrown4", 139, 105, 105 },
+ { "royalblue", 65, 105, 225 },
+ { "royalblue1", 72, 118, 255 },
+ { "royalblue2", 67, 110, 238 },
+ { "royalblue3", 58, 95, 205 },
+ { "royalblue4", 39, 64, 139 },
+ { "saddlebrown", 139, 69, 19 },
+ { "salmon", 250, 128, 114 },
+ { "salmon1", 255, 140, 105 },
+ { "salmon2", 238, 130, 98 },
+ { "salmon3", 205, 112, 84 },
+ { "salmon4", 139, 76, 57 },
+ { "sandybrown", 244, 164, 96 },
+ { "seagreen", 46, 139, 87 },
+ { "seagreen1", 84, 255, 159 },
+ { "seagreen2", 78, 238, 148 },
+ { "seagreen3", 67, 205, 128 },
+ { "seagreen4", 46, 139, 87 },
+ { "seashell", 255, 245, 238 },
+ { "seashell1", 255, 245, 238 },
+ { "seashell2", 238, 229, 222 },
+ { "seashell3", 205, 197, 191 },
+ { "seashell4", 139, 134, 130 },
+ { "sienna", 160, 82, 45 },
+ { "sienna1", 255, 130, 71 },
+ { "sienna2", 238, 121, 66 },
+ { "sienna3", 205, 104, 57 },
+ { "sienna4", 139, 71, 38 },
+ { "skyblue", 135, 206, 235 },
+ { "skyblue1", 135, 206, 255 },
+ { "skyblue2", 126, 192, 238 },
+ { "skyblue3", 108, 166, 205 },
+ { "skyblue4", 74, 112, 139 },
+ { "slateblue", 106, 90, 205 },
+ { "slateblue1", 131, 111, 255 },
+ { "slateblue2", 122, 103, 238 },
+ { "slateblue3", 105, 89, 205 },
+ { "slateblue4", 71, 60, 139 },
+ { "slategray", 112, 128, 144 },
+ { "slategray1", 198, 226, 255 },
+ { "slategray2", 185, 211, 238 },
+ { "slategray3", 159, 182, 205 },
+ { "slategray4", 108, 123, 139 },
+ { "slategrey", 112, 128, 144 },
+ { "snow", 255, 250, 250 },
+ { "snow1", 255, 250, 250 },
+ { "snow2", 238, 233, 233 },
+ { "snow3", 205, 201, 201 },
+ { "snow4", 139, 137, 137 },
+ { "springgreen", 0, 255, 127 },
+ { "springgreen1", 0, 255, 127 },
+ { "springgreen2", 0, 238, 118 },
+ { "springgreen3", 0, 205, 102 },
+ { "springgreen4", 0, 139, 69 },
+ { "steelblue", 70, 130, 180 },
+ { "steelblue1", 99, 184, 255 },
+ { "steelblue2", 92, 172, 238 },
+ { "steelblue3", 79, 148, 205 },
+ { "steelblue4", 54, 100, 139 },
+ { "tan", 210, 180, 140 },
+ { "tan1", 255, 165, 79 },
+ { "tan2", 238, 154, 73 },
+ { "tan3", 205, 133, 63 },
+ { "tan4", 139, 90, 43 },
+ { "thistle", 216, 191, 216 },
+ { "thistle1", 255, 225, 255 },
+ { "thistle2", 238, 210, 238 },
+ { "thistle3", 205, 181, 205 },
+ { "thistle4", 139, 123, 139 },
+ { "tomato", 255, 99, 71 },
+ { "tomato1", 255, 99, 71 },
+ { "tomato2", 238, 92, 66 },
+ { "tomato3", 205, 79, 57 },
+ { "tomato4", 139, 54, 38 },
+ { "turquoise", 64, 224, 208 },
+ { "turquoise1", 0, 245, 255 },
+ { "turquoise2", 0, 229, 238 },
+ { "turquoise3", 0, 197, 205 },
+ { "turquoise4", 0, 134, 139 },
+ { "violet", 238, 130, 238 },
+ { "violetred", 208, 32, 144 },
+ { "violetred1", 255, 62, 150 },
+ { "violetred2", 238, 58, 140 },
+ { "violetred3", 205, 50, 120 },
+ { "violetred4", 139, 34, 82 },
+ { "wheat", 245, 222, 179 },
+ { "wheat1", 255, 231, 186 },
+ { "wheat2", 238, 216, 174 },
+ { "wheat3", 205, 186, 150 },
+ { "wheat4", 139, 126, 102 },
+ { "white", 255, 255, 255 },
+ { "whitesmoke", 245, 245, 245 },
+ { "yellow", 255, 255, 0 },
+ { "yellow1", 255, 255, 0 },
+ { "yellow2", 238, 238, 0 },
+ { "yellow3", 205, 205, 0 },
+ { "yellow4", 139, 139, 0 },
+ { "yellowgreen", 154, 205, 50 }
+};
+
+
+BOOL DLL_CALLCONV
+FreeImage_LookupX11Color(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue) {
+ int i;
+
+ // lookup color
+ i = FreeImage_LookupNamedColor(szColor, X11ColorMap, sizeof(X11ColorMap)/sizeof(X11ColorMap[0]));
+ if (i >= 0) {
+ *nRed = X11ColorMap[i].r;
+ *nGreen = X11ColorMap[i].g;
+ *nBlue = X11ColorMap[i].b;
+ return TRUE;
+ }
+
+ // not found, try for grey color with attached percent value
+ if ( (szColor[0] == 'g' || szColor[0] == 'G') &&
+ (szColor[1] == 'r' || szColor[1] == 'R') &&
+ (szColor[2] == 'e' || szColor[2] == 'E' || szColor[2] == 'a' || szColor[2] == 'A' ) &&
+ (szColor[3] == 'y' || szColor[3] == 'Y' ) ) {
+
+ // grey<num>, or gray<num>, num 1...100
+ i = strtol(szColor+4, NULL, 10);
+ *nRed = (BYTE)(255.0/100.0 * i);
+ *nGreen = *nRed;
+ *nBlue = *nRed;
+
+ return TRUE;
+ }
+
+ // not found at all
+ *nRed = 0;
+ *nGreen = 0;
+ *nBlue = 0;
+
+ return FALSE;
+}
+
+// ==========================================================
+// SVG Color name lookup
+
+/**
+ These are the colors defined in the SVG standard (I haven't checked
+ the final recommendation for changes)
+*/
+static NamedColor SVGColorMap[] = {
+ { "aliceblue", 240, 248, 255 },
+ { "antiquewhite", 250, 235, 215 },
+ { "aqua", 0, 255, 255 },
+ { "aquamarine", 127, 255, 212 },
+ { "azure", 240, 255, 255 },
+ { "beige", 245, 245, 220 },
+ { "bisque", 255, 228, 196 },
+ { "black", 0, 0, 0 },
+ { "blanchedalmond", 255, 235, 205 },
+ { "blue", 0, 0, 255 },
+ { "blueviolet", 138, 43, 226 },
+ { "brown", 165, 42, 42 },
+ { "burlywood", 222, 184, 135 },
+ { "cadetblue", 95, 158, 160 },
+ { "chartreuse", 127, 255, 0 },
+ { "chocolate", 210, 105, 30 },
+ { "coral", 255, 127, 80 },
+ { "cornflowerblue", 100, 149, 237 },
+ { "cornsilk", 255, 248, 220 },
+ { "crimson", 220, 20, 60 },
+ { "cyan", 0, 255, 255 },
+ { "darkblue", 0, 0, 139 },
+ { "darkcyan", 0, 139, 139 },
+ { "darkgoldenrod", 184, 134, 11 },
+ { "darkgray", 169, 169, 169 },
+ { "darkgreen", 0, 100, 0 },
+ { "darkgrey", 169, 169, 169 },
+ { "darkkhaki", 189, 183, 107 },
+ { "darkmagenta", 139, 0, 139 },
+ { "darkolivegreen", 85, 107, 47 },
+ { "darkorange", 255, 140, 0 },
+ { "darkorchid", 153, 50, 204 },
+ { "darkred", 139, 0, 0 },
+ { "darksalmon", 233, 150, 122 },
+ { "darkseagreen", 143, 188, 143 },
+ { "darkslateblue", 72, 61, 139 },
+ { "darkslategray", 47, 79, 79 },
+ { "darkslategrey", 47, 79, 79 },
+ { "darkturquoise", 0, 206, 209 },
+ { "darkviolet", 148, 0, 211 },
+ { "deeppink", 255, 20, 147 },
+ { "deepskyblue", 0, 191, 255 },
+ { "dimgray", 105, 105, 105 },
+ { "dimgrey", 105, 105, 105 },
+ { "dodgerblue", 30, 144, 255 },
+ { "firebrick", 178, 34, 34 },
+ { "floralwhite", 255, 250, 240 },
+ { "forestgreen", 34, 139, 34 },
+ { "fuchsia", 255, 0, 255 },
+ { "gainsboro", 220, 220, 220 },
+ { "ghostwhite", 248, 248, 255 },
+ { "gold", 255, 215, 0 },
+ { "goldenrod", 218, 165, 32 },
+ { "gray", 128, 128, 128 },
+ { "grey", 128, 128, 128 },
+ { "green", 0, 128, 0 },
+ { "greenyellow", 173, 255, 47 },
+ { "honeydew", 240, 255, 240 },
+ { "hotpink", 255, 105, 180 },
+ { "indianred", 205, 92, 92 },
+ { "indigo", 75, 0, 130 },
+ { "ivory", 255, 255, 240 },
+ { "khaki", 240, 230, 140 },
+ { "lavender", 230, 230, 250 },
+ { "lavenderblush", 255, 240, 245 },
+ { "lawngreen", 124, 252, 0 },
+ { "lemonchiffon", 255, 250, 205 },
+ { "lightblue", 173, 216, 230 },
+ { "lightcoral", 240, 128, 128 },
+ { "lightcyan", 224, 255, 255 },
+ { "lightgoldenrodyellow", 250, 250, 210 },
+ { "lightgray", 211, 211, 211 },
+ { "lightgreen", 144, 238, 144 },
+ { "lightgrey", 211, 211, 211 },
+ { "lightpink", 255, 182, 193 },
+ { "lightsalmon", 255, 160, 122 },
+ { "lightseagreen", 32, 178, 170 },
+ { "lightskyblue", 135, 206, 250 },
+ { "lightslategray", 119, 136, 153 },
+ { "lightslategrey", 119, 136, 153 },
+ { "lightsteelblue", 176, 196, 222 },
+ { "lightyellow", 255, 255, 224 },
+ { "lime", 0, 255, 0 },
+ { "limegreen", 50, 205, 50 },
+ { "linen", 250, 240, 230 },
+ { "magenta", 255, 0, 255 },
+ { "maroon", 128, 0, 0 },
+ { "mediumaquamarine", 102, 205, 170 },
+ { "mediumblue", 0, 0, 205 },
+ { "mediumorchid", 186, 85, 211 },
+ { "mediumpurple", 147, 112, 219 },
+ { "mediumseagreen", 60, 179, 113 },
+ { "mediumslateblue", 123, 104, 238 },
+ { "mediumspringgreen", 0, 250, 154 },
+ { "mediumturquoise", 72, 209, 204 },
+ { "mediumvioletred", 199, 21, 133 },
+ { "midnightblue", 25, 25, 112 },
+ { "mintcream", 245, 255, 250 },
+ { "mistyrose", 255, 228, 225 },
+ { "moccasin", 255, 228, 181 },
+ { "navajowhite", 255, 222, 173 },
+ { "navy", 0, 0, 128 },
+ { "oldlace", 253, 245, 230 },
+ { "olive", 128, 128, 0 },
+ { "olivedrab", 107, 142, 35 },
+ { "orange", 255, 165, 0 },
+ { "orangered", 255, 69, 0 },
+ { "orchid", 218, 112, 214 },
+ { "palegoldenrod", 238, 232, 170 },
+ { "palegreen", 152, 251, 152 },
+ { "paleturquoise", 175, 238, 238 },
+ { "palevioletred", 219, 112, 147 },
+ { "papayawhip", 255, 239, 213 },
+ { "peachpuff", 255, 218, 185 },
+ { "peru", 205, 133, 63 },
+ { "pink", 255, 192, 203 },
+ { "plum", 221, 160, 221 },
+ { "powderblue", 176, 224, 230 },
+ { "purple", 128, 0, 128 },
+ { "red", 255, 0, 0 },
+ { "rosybrown", 188, 143, 143 },
+ { "royalblue", 65, 105, 225 },
+ { "saddlebrown", 139, 69, 19 },
+ { "salmon", 250, 128, 114 },
+ { "sandybrown", 244, 164, 96 },
+ { "seagreen", 46, 139, 87 },
+ { "seashell", 255, 245, 238 },
+ { "sienna", 160, 82, 45 },
+ { "silver", 192, 192, 192 },
+ { "skyblue", 135, 206, 235 },
+ { "slateblue", 106, 90, 205 },
+ { "slategray", 112, 128, 144 },
+ { "slategrey", 112, 128, 144 },
+ { "snow", 255, 250, 250 },
+ { "springgreen", 0, 255, 127 },
+ { "steelblue", 70, 130, 180 },
+ { "tan", 210, 180, 140 },
+ { "teal", 0, 128, 128 },
+ { "thistle", 216, 191, 216 },
+ { "tomato", 255, 99, 71 },
+ { "turquoise", 64, 224, 208 },
+ { "violet", 238, 130, 238 },
+ { "wheat", 245, 222, 179 },
+ { "white", 255, 255, 255 },
+ { "whitesmoke", 245, 245, 245 },
+ { "yellow", 255, 255, 0 },
+ { "yellowgreen", 154, 205, 50 }
+};
+
+
+BOOL DLL_CALLCONV
+FreeImage_LookupSVGColor(const char *szColor, BYTE *nRed, BYTE *nGreen, BYTE *nBlue) {
+ int i;
+
+ // lookup color
+ i = FreeImage_LookupNamedColor(szColor, SVGColorMap, sizeof(SVGColorMap)/sizeof(SVGColorMap[0]));
+ if (i >= 0) {
+ *nRed = SVGColorMap[i].r;
+ *nGreen = SVGColorMap[i].g;
+ *nBlue = SVGColorMap[i].b;
+ return TRUE;
+ }
+
+ // not found, try for grey color with attached percent value
+ if ( (szColor[0] == 'g' || szColor[0] == 'G') &&
+ (szColor[1] == 'r' || szColor[1] == 'R') &&
+ (szColor[2] == 'e' || szColor[2] == 'E' || szColor[2] == 'a' || szColor[2] == 'A' ) &&
+ (szColor[3] == 'y' || szColor[3] == 'Y' ) ) {
+
+ // grey<num>, or gray<num>, num 1...100
+ i = strtol(szColor+4, NULL, 10);
+ *nRed = (BYTE)(255.0/100.0 * i);
+ *nGreen = *nRed;
+ *nBlue = *nRed;
+ return TRUE;
+ }
+
+ // not found at all
+ *nRed = 0;
+ *nGreen = 0;
+ *nBlue = 0;
+
+ return FALSE;
+}
+
diff --git a/Source/FreeImage/Conversion.cpp b/Source/FreeImage/Conversion.cpp
new file mode 100644
index 0000000..513dbee
--- /dev/null
+++ b/Source/FreeImage/Conversion.cpp
@@ -0,0 +1,203 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "Quantizers.h"
+
+// ----------------------------------------------------------
+
+#define CONVERT(from, to) case to : FreeImage_ConvertLine##from##To##to(bits, scanline, FreeImage_GetWidth(dib)); break;
+#define CONVERTWITHPALETTE(from, to) case to : FreeImage_ConvertLine##from##To##to(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); break;
+
+#define CONVERTTO16(from) \
+ case 16 : \
+ if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { \
+ FreeImage_ConvertLine##from##To16_555(bits, scanline, FreeImage_GetWidth(dib)); \
+ } else { \
+ FreeImage_ConvertLine##from##To16_565(bits, scanline, FreeImage_GetWidth(dib)); \
+ } \
+ break;
+
+#define CONVERTTO16WITHPALETTE(from) \
+ case 16 : \
+ if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) { \
+ FreeImage_ConvertLine##from##To16_555(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); \
+ } else { \
+ FreeImage_ConvertLine##from##To16_565(bits, scanline, FreeImage_GetWidth(dib), FreeImage_GetPalette(dib)); \
+ } \
+ break;
+
+// ==========================================================
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ColorQuantize(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize) {
+ return FreeImage_ColorQuantizeEx(dib, quantize);
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ColorQuantizeEx(FIBITMAP *dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette) {
+ if( PaletteSize < 2 ) PaletteSize = 2;
+ if( PaletteSize > 256 ) PaletteSize = 256;
+ if( ReserveSize < 0 ) ReserveSize = 0;
+ if( ReserveSize > PaletteSize ) ReserveSize = PaletteSize;
+ if (dib) {
+ if (FreeImage_GetBPP(dib) == 24) {
+ switch(quantize) {
+ case FIQ_WUQUANT :
+ {
+ try {
+ WuQuantizer Q (dib);
+ FIBITMAP *dst = Q.Quantize(PaletteSize, ReserveSize, ReservePalette);
+ if(dst) {
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+ }
+ return dst;
+ } catch (const char *) {
+ return NULL;
+ }
+ }
+ case FIQ_NNQUANT :
+ {
+ // sampling factor in range 1..30.
+ // 1 => slower (but better), 30 => faster. Default value is 1
+ const int sampling = 1;
+
+ NNQuantizer Q(PaletteSize);
+ FIBITMAP *dst = Q.Quantize(dib, ReserveSize, ReservePalette, sampling);
+ if(dst) {
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+ }
+ return dst;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertFromRawBits(BYTE *bits, int width, int height, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown) {
+ FIBITMAP *dib = FreeImage_Allocate(width, height, bpp, red_mask, green_mask, blue_mask);
+
+ if (dib != NULL) {
+ if (topdown) {
+ for (int i = height - 1; i >= 0; --i) {
+ memcpy(FreeImage_GetScanLine(dib, i), bits, FreeImage_GetLine(dib));
+ bits += pitch;
+ }
+ } else {
+ for (int i = 0; i < height; ++i) {
+ memcpy(FreeImage_GetScanLine(dib, i), bits, FreeImage_GetLine(dib));
+ bits += pitch;
+ }
+ }
+ }
+
+ return dib;
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertToRawBits(BYTE *bits, FIBITMAP *dib, int pitch, unsigned bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask, BOOL topdown) {
+ if ((dib != NULL) && (bits != NULL)) {
+ for (unsigned i = 0; i < FreeImage_GetHeight(dib); ++i) {
+ BYTE *scanline = FreeImage_GetScanLine(dib, topdown ? (FreeImage_GetHeight(dib) - i - 1) : i);
+
+ if ((bpp == 16) && (FreeImage_GetBPP(dib) == 16)) {
+ // convert 555 to 565 or vice versa
+
+ if ((red_mask == FI16_555_RED_MASK) && (green_mask == FI16_555_GREEN_MASK) && (blue_mask == FI16_555_BLUE_MASK)) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ FreeImage_ConvertLine16_565_To16_555(bits, scanline, FreeImage_GetWidth(dib));
+ } else {
+ memcpy(bits, scanline, FreeImage_GetLine(dib));
+ }
+ } else {
+ if ((FreeImage_GetRedMask(dib) == FI16_555_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_555_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_555_BLUE_MASK)) {
+ FreeImage_ConvertLine16_555_To16_565(bits, scanline, FreeImage_GetWidth(dib));
+ } else {
+ memcpy(bits, scanline, FreeImage_GetLine(dib));
+ }
+ }
+ } else if (FreeImage_GetBPP(dib) != bpp) {
+ switch(FreeImage_GetBPP(dib)) {
+ case 1 :
+ switch(bpp) {
+ CONVERT(1, 8)
+ CONVERTTO16WITHPALETTE(1)
+ CONVERTWITHPALETTE(1, 24)
+ CONVERTWITHPALETTE(1, 32)
+ };
+
+ break;
+
+ case 4 :
+ switch(bpp) {
+ CONVERT(4, 8)
+ CONVERTTO16WITHPALETTE(4)
+ CONVERTWITHPALETTE(4, 24)
+ CONVERTWITHPALETTE(4, 32)
+ };
+
+ break;
+
+ case 8 :
+ switch(bpp) {
+ CONVERTTO16WITHPALETTE(8)
+ CONVERTWITHPALETTE(8, 24)
+ CONVERTWITHPALETTE(8, 32)
+ };
+
+ break;
+
+ case 24 :
+ switch(bpp) {
+ CONVERT(24, 8)
+ CONVERTTO16(24)
+ CONVERT(24, 32)
+ };
+
+ break;
+
+ case 32 :
+ switch(bpp) {
+ CONVERT(32, 8)
+ CONVERTTO16(32)
+ CONVERT(32, 24)
+ };
+
+ break;
+ };
+ } else {
+ memcpy(bits, scanline, FreeImage_GetLine(dib));
+ }
+
+ bits += pitch;
+ }
+ }
+}
diff --git a/Source/FreeImage/Conversion16_555.cpp b/Source/FreeImage/Conversion16_555.cpp
new file mode 100644
index 0000000..da30db6
--- /dev/null
+++ b/Source/FreeImage/Conversion16_555.cpp
@@ -0,0 +1,209 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+
+#define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT))
+
+// ----------------------------------------------------------
+// internal conversions X to 16 bits (555)
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ int index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0;
+
+ new_bits[cols] = RGB555(palette[index].rgbBlue, palette[index].rgbGreen, palette[index].rgbRed);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine4To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+ BOOL lonibble = FALSE;
+ int x = 0;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ RGBQUAD *grab_palette;
+
+ if (lonibble) {
+ grab_palette = palette + LOWNIBBLE(source[x++]);
+ } else {
+ grab_palette = palette + (HINIBBLE(source[x]) >> 4);
+ }
+
+ new_bits[cols] = RGB555(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed);
+
+ lonibble = !lonibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine8To16_555(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ RGBQUAD *grab_palette = palette + source[cols];
+
+ new_bits[cols] = RGB555(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16_565_To16_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *src_bits = (WORD *)source;
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB555((((src_bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F,
+ (((src_bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
+ (((src_bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine24To16_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB555(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]);
+
+ source += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine32To16_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB555(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]);
+
+ source += 4;
+ }
+}
+
+// ----------------------------------------------------------
+// smart convert X to 16 bits
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo16Bits555(FIBITMAP *dib) {
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) return NULL;
+
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ const int bpp = FreeImage_GetBPP(dib);
+
+ if(bpp == 16) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ // RGB 565
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine16_565_To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ return new_dib;
+ } else {
+ // RGB 555
+ return FreeImage_Clone(dib);
+ }
+ }
+ else {
+ // other bpp cases => convert to RGB 555
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ switch (bpp) {
+ case 1 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 4 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 8 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 24 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine24To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ return new_dib;
+ }
+
+ case 32 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine32To16_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ return new_dib;
+ }
+
+ default :
+ // unreachable code ...
+ FreeImage_Unload(new_dib);
+ break;
+
+ }
+ }
+
+ return NULL;
+}
diff --git a/Source/FreeImage/Conversion16_565.cpp b/Source/FreeImage/Conversion16_565.cpp
new file mode 100644
index 0000000..367bc4a
--- /dev/null
+++ b/Source/FreeImage/Conversion16_565.cpp
@@ -0,0 +1,204 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// internal conversions X to 16 bits (565)
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ int index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0;
+
+ new_bits[cols] = RGB565(palette[index].rgbBlue, palette[index].rgbGreen, palette[index].rgbRed);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine4To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+ BOOL lonibble = FALSE;
+ int x = 0;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ RGBQUAD *grab_palette;
+
+ if (lonibble) {
+ grab_palette = palette + LOWNIBBLE(source[x++]);
+ } else {
+ grab_palette = palette + (HINIBBLE(source[x]) >> 4);
+ }
+
+ new_bits[cols] = RGB565(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed);
+
+ lonibble = !lonibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine8To16_565(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ RGBQUAD *grab_palette = palette + source[cols];
+
+ new_bits[cols] = RGB565(grab_palette->rgbBlue, grab_palette->rgbGreen, grab_palette->rgbRed);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16_555_To16_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *src_bits = (WORD *)source;
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB565((((src_bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F,
+ (((src_bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
+ (((src_bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine24To16_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB565(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]);
+
+ source += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine32To16_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *new_bits = (WORD *)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ new_bits[cols] = RGB565(source[FI_RGBA_BLUE], source[FI_RGBA_GREEN], source[FI_RGBA_RED]);
+
+ source += 4;
+ }
+}
+
+// ----------------------------------------------------------
+// smart convert X to 16 bits (565)
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo16Bits565(FIBITMAP *dib) {
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP)) return NULL;
+
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ const int bpp = FreeImage_GetBPP(dib);
+
+ if(bpp == 16) {
+ if ((FreeImage_GetRedMask(dib) == FI16_555_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_555_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_555_BLUE_MASK)) {
+ // RGB 555
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine16_555_To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ return new_dib;
+ } else {
+ // RGB 565
+ return FreeImage_Clone(dib);
+ }
+ }
+ else {
+ // other bpp cases => convert to RGB 565
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 16, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ switch (bpp) {
+ case 1 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 4 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 8 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+
+ return new_dib;
+ }
+
+ case 24 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine24To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ return new_dib;
+ }
+
+ case 32 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine32To16_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ return new_dib;
+ }
+
+ default :
+ // unreachable code ...
+ FreeImage_Unload(new_dib);
+ break;
+ }
+ }
+
+ return NULL;
+}
diff --git a/Source/FreeImage/Conversion24.cpp b/Source/FreeImage/Conversion24.cpp
new file mode 100644
index 0000000..8e18864
--- /dev/null
+++ b/Source/FreeImage/Conversion24.cpp
@@ -0,0 +1,214 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Dale Larson (dlarson@norsesoft.com)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// internal conversions X to 24 bits
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ BYTE index = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0;
+
+ target[FI_RGBA_BLUE] = palette[index].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[index].rgbGreen;
+ target[FI_RGBA_RED] = palette[index].rgbRed;
+
+ target += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine4To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ BOOL low_nibble = FALSE;
+ int x = 0;
+
+ for (int cols = 0; cols < width_in_pixels; ++cols ) {
+ if (low_nibble) {
+ target[FI_RGBA_BLUE] = palette[LOWNIBBLE(source[x])].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[LOWNIBBLE(source[x])].rgbGreen;
+ target[FI_RGBA_RED] = palette[LOWNIBBLE(source[x])].rgbRed;
+
+ x++;
+ } else {
+ target[FI_RGBA_BLUE] = palette[HINIBBLE(source[x]) >> 4].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[HINIBBLE(source[x]) >> 4].rgbGreen;
+ target[FI_RGBA_RED] = palette[HINIBBLE(source[x]) >> 4].rgbRed;
+ }
+
+ low_nibble = !low_nibble;
+
+ target += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine8To24(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_BLUE] = palette[source[cols]].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[source[cols]].rgbGreen;
+ target[FI_RGBA_RED] = palette[source[cols]].rgbRed;
+
+ target += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To24_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+
+ target += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To24_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F);
+ target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
+
+ target += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine32To24(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_BLUE] = source[FI_RGBA_BLUE];
+ target[FI_RGBA_GREEN] = source[FI_RGBA_GREEN];
+ target[FI_RGBA_RED] = source[FI_RGBA_RED];
+
+ target += 3;
+ source += 4;
+ }
+}
+
+// ----------------------------------------------------------
+// smart convert X to 24 bits
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo24Bits(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ const unsigned bpp = FreeImage_GetBPP(dib);
+
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if((image_type != FIT_BITMAP) && (image_type != FIT_RGB16)) {
+ return NULL;
+ }
+
+ if (bpp != 24) {
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ switch(bpp) {
+ case 1 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+ return new_dib;
+ }
+
+ case 4 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+ return new_dib;
+ }
+
+ case 8 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+ return new_dib;
+ }
+
+ case 16 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ FreeImage_ConvertLine16To24_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ } else {
+ // includes case where all the masks are 0
+ FreeImage_ConvertLine16To24_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ }
+ return new_dib;
+ }
+
+ case 32 :
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine32To24(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 48:
+ {
+ const unsigned src_pitch = FreeImage_GetPitch(dib);
+ const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
+ const BYTE *src_bits = FreeImage_GetBits(dib);
+ BYTE *dst_bits = FreeImage_GetBits(new_dib);
+ for (int rows = 0; rows < height; rows++) {
+ const FIRGB16 *src_pixel = (FIRGB16*)src_bits;
+ RGBTRIPLE *dst_pixel = (RGBTRIPLE*)dst_bits;
+ for(int cols = 0; cols < width; cols++) {
+ dst_pixel[cols].rgbtRed = (BYTE)(src_pixel[cols].red >> 8);
+ dst_pixel[cols].rgbtGreen = (BYTE)(src_pixel[cols].green >> 8);
+ dst_pixel[cols].rgbtBlue = (BYTE)(src_pixel[cols].blue >> 8);
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+ return new_dib;
+ }
+ }
+ }
+
+ return FreeImage_Clone(dib);
+}
diff --git a/Source/FreeImage/Conversion32.cpp b/Source/FreeImage/Conversion32.cpp
new file mode 100644
index 0000000..30a4310
--- /dev/null
+++ b/Source/FreeImage/Conversion32.cpp
@@ -0,0 +1,319 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// internal conversions X to 32 bits
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ int index = (source[cols>>3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0;
+
+ target[FI_RGBA_BLUE] = palette[index].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[index].rgbGreen;
+ target[FI_RGBA_RED] = palette[index].rgbRed;
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine4To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ BOOL low_nibble = FALSE;
+ int x = 0;
+
+ for (int cols = 0 ; cols < width_in_pixels ; ++cols) {
+ if (low_nibble) {
+ target[FI_RGBA_BLUE] = palette[LOWNIBBLE(source[x])].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[LOWNIBBLE(source[x])].rgbGreen;
+ target[FI_RGBA_RED] = palette[LOWNIBBLE(source[x])].rgbRed;
+
+ x++;
+ } else {
+ target[FI_RGBA_BLUE] = palette[HINIBBLE(source[x]) >> 4].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[HINIBBLE(source[x]) >> 4].rgbGreen;
+ target[FI_RGBA_RED] = palette[HINIBBLE(source[x]) >> 4].rgbRed;
+ }
+
+ low_nibble = !low_nibble;
+
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine8To32(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_BLUE] = palette[source[cols]].rgbBlue;
+ target[FI_RGBA_GREEN] = palette[source[cols]].rgbGreen;
+ target[FI_RGBA_RED] = palette[source[cols]].rgbRed;
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To32_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To32_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_RED] = (BYTE)((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_GREEN] = (BYTE)((((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F);
+ target[FI_RGBA_BLUE] = (BYTE)((((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ }
+}
+/*
+void DLL_CALLCONV
+FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ *(DWORD *)target = (*(DWORD *) source & FI_RGBA_RGB_MASK) | FI_RGBA_ALPHA_MASK;
+ target += 4;
+ source += 3;
+ }
+}
+*/
+/**
+This unoptimized version of the conversion function avoid an undetermined bug with VC++ SP6.
+The bug occurs in release mode only, when the image height is equal to 537
+(try e.g. a size of 432x537 to reproduce the bug with the optimized function).
+*/
+void DLL_CALLCONV
+FreeImage_ConvertLine24To32(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[FI_RGBA_RED] = source[FI_RGBA_RED];
+ target[FI_RGBA_GREEN] = source[FI_RGBA_GREEN];
+ target[FI_RGBA_BLUE] = source[FI_RGBA_BLUE];
+ target[FI_RGBA_ALPHA] = 0xFF;
+ target += 4;
+ source += 3;
+ }
+}
+// ----------------------------------------------------------
+
+static void DLL_CALLCONV
+MapTransparentTableToAlpha1(RGBQUAD *target, BYTE *source, BYTE *table, int transparent_pixels, int width_in_pixels) {
+ for (int cols = 0 ; cols < width_in_pixels ; cols++) {
+ int index = (source[cols>>3] & (0x80 >> (cols & 0x07))) != 0 ? 1 : 0;
+ target[cols].rgbReserved = (index < transparent_pixels) ? table[index] : 255;
+ }
+}
+
+static void DLL_CALLCONV
+MapTransparentTableToAlpha4(RGBQUAD *target, BYTE *source, BYTE *table, int transparent_pixels, int width_in_pixels) {
+ BOOL low_nibble = FALSE;
+ int x = 0;
+
+ for (int cols = 0 ; cols < width_in_pixels ; ++cols) {
+ int index;
+ if (low_nibble) {
+ index = LOWNIBBLE(source[x]);
+ x++;
+ } else {
+ index = HINIBBLE(source[x]) >> 4;
+ }
+ target[cols].rgbReserved = (index < transparent_pixels) ? table[index] : 255;
+ low_nibble = !low_nibble;
+ }
+}
+
+static void DLL_CALLCONV
+MapTransparentTableToAlpha8(RGBQUAD *target, BYTE *source, BYTE *table, int transparent_pixels, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[cols].rgbReserved = (source[cols] < transparent_pixels) ? table[source[cols]] : 255;
+ }
+}
+
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo32Bits(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ const int bpp = FreeImage_GetBPP(dib);
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ if((image_type != FIT_BITMAP) && (image_type != FIT_RGB16) && (image_type != FIT_RGBA16)) {
+ return NULL;
+ }
+
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+
+ if(image_type == FIT_BITMAP) {
+
+ if(bpp == 32) {
+ return FreeImage_Clone(dib);
+ }
+
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ switch(bpp) {
+ case 1:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+
+ if (FreeImage_IsTransparent(dib)) {
+ MapTransparentTableToAlpha1((RGBQUAD *)FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 4:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+
+ if (FreeImage_IsTransparent(dib)) {
+ MapTransparentTableToAlpha4((RGBQUAD *)FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 8:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+
+ if (FreeImage_IsTransparent(dib)) {
+ MapTransparentTableToAlpha8((RGBQUAD *)FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 16:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ FreeImage_ConvertLine16To32_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ } else {
+ // includes case where all the masks are 0
+ FreeImage_ConvertLine16To32_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 24:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine24To32(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+
+ return new_dib;
+ }
+ }
+
+ } else if(image_type == FIT_RGB16) {
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ const unsigned src_pitch = FreeImage_GetPitch(dib);
+ const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
+ const BYTE *src_bits = FreeImage_GetBits(dib);
+ BYTE *dst_bits = FreeImage_GetBits(new_dib);
+ for (int rows = 0; rows < height; rows++) {
+ const FIRGB16 *src_pixel = (FIRGB16*)src_bits;
+ RGBQUAD *dst_pixel = (RGBQUAD*)dst_bits;
+ for(int cols = 0; cols < width; cols++) {
+ dst_pixel[cols].rgbRed = (BYTE)(src_pixel[cols].red >> 8);
+ dst_pixel[cols].rgbGreen = (BYTE)(src_pixel[cols].green >> 8);
+ dst_pixel[cols].rgbBlue = (BYTE)(src_pixel[cols].blue >> 8);
+ dst_pixel[cols].rgbReserved = (BYTE)0xFF;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+
+ return new_dib;
+
+ } else if(image_type == FIT_RGBA16) {
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ const unsigned src_pitch = FreeImage_GetPitch(dib);
+ const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
+ const BYTE *src_bits = FreeImage_GetBits(dib);
+ BYTE *dst_bits = FreeImage_GetBits(new_dib);
+ for (int rows = 0; rows < height; rows++) {
+ const FIRGBA16 *src_pixel = (FIRGBA16*)src_bits;
+ RGBQUAD *dst_pixel = (RGBQUAD*)dst_bits;
+ for(int cols = 0; cols < width; cols++) {
+ dst_pixel[cols].rgbRed = (BYTE)(src_pixel[cols].red >> 8);
+ dst_pixel[cols].rgbGreen = (BYTE)(src_pixel[cols].green >> 8);
+ dst_pixel[cols].rgbBlue = (BYTE)(src_pixel[cols].blue >> 8);
+ dst_pixel[cols].rgbReserved = (BYTE)(src_pixel[cols].alpha >> 8);
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+
+ return new_dib;
+ }
+
+ return NULL;
+}
diff --git a/Source/FreeImage/Conversion4.cpp b/Source/FreeImage/Conversion4.cpp
new file mode 100644
index 0000000..46b194d
--- /dev/null
+++ b/Source/FreeImage/Conversion4.cpp
@@ -0,0 +1,246 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Riley McNiff (rmcniff@marexgroup.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// internal conversions X to 4 bits
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To4(BYTE *target, BYTE *source, int width_in_pixels) {
+ BOOL hinibble = TRUE;
+ for (int cols = 0; cols < width_in_pixels; cols++){
+ if (hinibble == TRUE){
+ target[cols >> 1] = ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0) << 4;
+ }
+ else {
+ target[cols >> 1] |= ((source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 15 : 0);
+ }
+
+ hinibble = !hinibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine8To4(BYTE *target, BYTE *source, int width_in_pixels, RGBQUAD *palette) {
+ BOOL hinibble = TRUE;
+ BYTE index;
+
+ for (int cols = 0; cols < width_in_pixels; cols++){
+ index = GREY(palette[source[cols]].rgbRed, palette[source[cols]].rgbGreen, palette[source[cols]].rgbBlue);
+ if (hinibble) {
+ target[cols >> 1] = (index & 0xF0);
+ } else {
+ target[cols >> 1] |= (index >> 4);
+ }
+
+ hinibble = !hinibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To4_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ if (hinibble) {
+ target[cols >> 1] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F)
+ & 0xF0;
+ } else {
+ target[cols >> 1] |= GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F)
+ >> 4;
+ }
+
+ hinibble = !hinibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To4_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ if (hinibble) {
+ target[cols >> 1] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
+ (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F)
+ & 0xF0;
+ } else {
+ target[cols >> 1] |= GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
+ (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F)
+ >> 4;
+ }
+
+ hinibble = !hinibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine24To4(BYTE *target, BYTE *source, int width_in_pixels) {
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ if (hinibble) {
+ target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0;
+ } else {
+ target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4;
+ }
+
+ source += 3;
+ hinibble = !hinibble;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine32To4(BYTE *target, BYTE *source, int width_in_pixels) {
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ if (hinibble) {
+ target[cols >> 1] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) & 0xF0;
+ } else {
+ target[cols >> 1] |= GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]) >> 4;
+ }
+
+ source += 4;
+ hinibble = !hinibble;
+ }
+}
+
+// ----------------------------------------------------------
+// smart convert X to 4 bits
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo4Bits(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ const int bpp = FreeImage_GetBPP(dib);
+
+ if(bpp != 4) {
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 4);
+
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ // Build a greyscale palette (*always* needed for image processing)
+
+ RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
+
+ for(int i = 0; i < 16; i++) {
+ new_pal[i].rgbRed = (BYTE)((i << 4) + i);
+ new_pal[i].rgbGreen = (BYTE)((i << 4) + i);
+ new_pal[i].rgbBlue = (BYTE)((i << 4) + i);
+ }
+
+ switch(bpp) {
+ case 1:
+ {
+ if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
+
+ // Copy the palette
+
+ RGBQUAD *old_pal = FreeImage_GetPalette(dib);
+ memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD));
+ memcpy(&new_pal[15], &old_pal[1], sizeof(RGBQUAD));
+
+ }
+ else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) {
+
+ // Reverse the grayscale palette
+
+ for(int i = 0; i < 16; i++) {
+ new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - ((i << 4) + i));
+ }
+ }
+
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 8 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ }
+ return new_dib;
+ }
+
+ case 16 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ FreeImage_ConvertLine16To4_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ } else {
+ FreeImage_ConvertLine16To4_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 24 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine24To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 32 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine32To4(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+ }
+ }
+
+ return FreeImage_Clone(dib);
+}
diff --git a/Source/FreeImage/Conversion8.cpp b/Source/FreeImage/Conversion8.cpp
new file mode 100644
index 0000000..17d0e61
--- /dev/null
+++ b/Source/FreeImage/Conversion8.cpp
@@ -0,0 +1,327 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jani Kajala (janik@remedy.fi)
+// - Karl-Heinz Bussian (khbussian@moss.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// internal conversions X to 8 bits
+// ----------------------------------------------------------
+
+void DLL_CALLCONV
+FreeImage_ConvertLine1To8(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++)
+ target[cols] = (source[cols >> 3] & (0x80 >> (cols & 0x07))) != 0 ? 255 : 0;
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine4To8(BYTE *target, BYTE *source, int width_in_pixels) {
+ int count_new = 0;
+ int count_org = 0;
+ BOOL hinibble = TRUE;
+
+ while (count_new < width_in_pixels) {
+ if (hinibble) {
+ target[count_new] = (source[count_org] & 0xF0) >> 4;
+ } else {
+ target[count_new] = (source[count_org] & 0x0F);
+
+ count_org++;
+ }
+
+ hinibble = !hinibble;
+
+ count_new++;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To8_555(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[cols] = GREY((((bits[cols] & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine16To8_565(BYTE *target, BYTE *source, int width_in_pixels) {
+ WORD *bits = (WORD *)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++)
+ target[cols] = GREY((((bits[cols] & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F,
+ (((bits[cols] & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F,
+ (((bits[cols] & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine24To8(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
+
+ source += 3;
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_ConvertLine32To8(BYTE *target, BYTE *source, int width_in_pixels) {
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ target[cols] = GREY(source[FI_RGBA_RED], source[FI_RGBA_GREEN], source[FI_RGBA_BLUE]);
+
+ source += 4;
+ }
+}
+
+// ----------------------------------------------------------
+// smart convert X to 8 bits
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertTo8Bits(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ const int bpp = FreeImage_GetBPP(dib);
+
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if((image_type != FIT_BITMAP) && (image_type != FIT_UINT16)) {
+ return NULL;
+ }
+
+ if(bpp != 8) {
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
+
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ // Build a greyscale palette (*always* needed for image processing)
+
+ RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
+
+ for(int i = 0; i < 256; i++) {
+ new_pal[i].rgbRed = (BYTE)i;
+ new_pal[i].rgbGreen = (BYTE)i;
+ new_pal[i].rgbBlue = (BYTE)i;
+ }
+
+ if(image_type == FIT_BITMAP) {
+
+ switch(bpp) {
+ case 1:
+ {
+ if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
+
+ // Copy the palette
+
+ RGBQUAD *old_pal = FreeImage_GetPalette(dib);
+ memcpy(&new_pal[0], &old_pal[0], sizeof(RGBQUAD));
+ memcpy(&new_pal[255], &old_pal[1], sizeof(RGBQUAD));
+
+ }
+ else if(FreeImage_GetColorType(dib) == FIC_MINISWHITE) {
+
+ // Reverse the grayscale palette
+
+ for(int i = 0; i < 256; i++) {
+ new_pal[i].rgbRed = new_pal[i].rgbGreen = new_pal[i].rgbBlue = (BYTE)(255 - i);
+ }
+ }
+
+
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 4 :
+ {
+ if(FreeImage_GetColorType(dib) == FIC_PALETTE) {
+
+ // Copy the palette
+
+ RGBQUAD *old_pal = FreeImage_GetPalette(dib);
+
+ for (int i = 0; i < 16; i++) {
+ new_pal[i].rgbRed = old_pal[i].rgbRed;
+ new_pal[i].rgbGreen = old_pal[i].rgbGreen;
+ new_pal[i].rgbBlue = old_pal[i].rgbBlue;
+ }
+ }
+
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 16 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ if ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ FreeImage_ConvertLine16To8_565(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ } else {
+ FreeImage_ConvertLine16To8_555(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ }
+
+ return new_dib;
+ }
+
+ case 24 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+
+ case 32 :
+ {
+ // Expand and copy the bitmap data
+
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine32To8(FreeImage_GetScanLine(new_dib, rows), FreeImage_GetScanLine(dib, rows), width);
+ }
+ return new_dib;
+ }
+ }
+
+ } else if(image_type == FIT_UINT16) {
+
+ const unsigned src_pitch = FreeImage_GetPitch(dib);
+ const unsigned dst_pitch = FreeImage_GetPitch(new_dib);
+ const BYTE *src_bits = FreeImage_GetBits(dib);
+ BYTE *dst_bits = FreeImage_GetBits(new_dib);
+ for (int rows = 0; rows < height; rows++) {
+ const WORD *src_pixel = (WORD*)src_bits;
+ BYTE *dst_pixel = (BYTE*)dst_bits;
+ for(int cols = 0; cols < width; cols++) {
+ dst_pixel[cols] = (BYTE)(src_pixel[cols] >> 8);
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+
+ return new_dib;
+
+ }
+
+ } // bpp != 8
+
+ return FreeImage_Clone(dib);
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertToGreyscale(FIBITMAP *dib) {
+ if(!dib) return NULL;
+
+ const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
+ const int bpp = FreeImage_GetBPP(dib);
+
+ if((color_type == FIC_PALETTE) || (color_type == FIC_MINISWHITE)) {
+ const int width = FreeImage_GetWidth(dib);
+ const int height = FreeImage_GetHeight(dib);
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
+
+ if(new_dib == NULL) {
+ return NULL;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ // Build a greyscale palette
+
+ RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
+
+ for(int i = 0; i < 256; i++) {
+ new_pal[i].rgbRed = (BYTE)i;
+ new_pal[i].rgbGreen = (BYTE)i;
+ new_pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // allocate a 24-bit buffer
+
+ BYTE *buffer = (BYTE*)malloc( CalculatePitch(CalculateLine(width, 24)) );
+ if(NULL == buffer) {
+ FreeImage_Unload(new_dib);
+ return NULL;
+ }
+
+ // Convert the palette to 24-bit, then to 8-bit
+
+ switch(bpp) {
+ case 1:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine1To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
+ }
+ }
+ break;
+
+ case 4:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine4To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
+ }
+ }
+ break;
+
+ case 8:
+ {
+ for (int rows = 0; rows < height; rows++) {
+ FreeImage_ConvertLine8To24(buffer, FreeImage_GetScanLine(dib, rows), width, FreeImage_GetPalette(dib));
+ FreeImage_ConvertLine24To8(FreeImage_GetScanLine(new_dib, rows), buffer, width);
+ }
+ }
+ break;
+
+ }
+ free(buffer);
+
+ return new_dib;
+
+ }
+
+ // Convert the bitmap to 8-bit greyscale
+ return FreeImage_ConvertTo8Bits(dib);
+}
diff --git a/Source/FreeImage/ConversionRGBF.cpp b/Source/FreeImage/ConversionRGBF.cpp
new file mode 100644
index 0000000..eac73f0
--- /dev/null
+++ b/Source/FreeImage/ConversionRGBF.cpp
@@ -0,0 +1,179 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// smart convert X to RGBF
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_ConvertToRGBF(FIBITMAP *dib) {
+ FIBITMAP *src = NULL;
+ FIBITMAP *dst = NULL;
+
+ const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(dib);
+
+ // check for allowed conversions
+ switch(src_type) {
+ case FIT_BITMAP:
+ {
+ // allow conversion from 24- and 32-bit
+ const FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
+ if((color_type != FIC_RGB) && (color_type != FIC_RGBALPHA)) {
+ src = FreeImage_ConvertTo24Bits(dib);
+ if(!src) return NULL;
+ } else {
+ src = dib;
+ }
+ break;
+ }
+ case FIT_RGB16:
+ // allow conversion from 48-bit
+ src = dib;
+ break;
+ case FIT_RGBAF:
+ // allow conversion from 128-bit
+ src = dib;
+ break;
+ case FIT_RGBF:
+ // RGBF type : clone the src
+ return FreeImage_Clone(dib);
+ break;
+ default:
+ return NULL;
+ }
+
+ // allocate dst image
+
+ const unsigned width = FreeImage_GetWidth(src);
+ const unsigned height = FreeImage_GetHeight(src);
+
+ dst = FreeImage_AllocateT(FIT_RGBF, width, height);
+ if(!dst) return NULL;
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ // convert from src type to RGBF
+
+ const unsigned src_pitch = FreeImage_GetPitch(src);
+ const unsigned dst_pitch = FreeImage_GetPitch(dst);
+
+ switch(src_type) {
+ case FIT_BITMAP:
+ {
+ // calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
+ const unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const BYTE *src_pixel = (BYTE*)src_bits;
+ FIRGBF *dst_pixel = (FIRGBF*)dst_bits;
+ for(unsigned x = 0; x < width; x++) {
+ // convert and scale to the range [0..1]
+ dst_pixel->red = (float)(src_pixel[FI_RGBA_RED]) / 255;
+ dst_pixel->green = (float)(src_pixel[FI_RGBA_GREEN]) / 255;
+ dst_pixel->blue = (float)(src_pixel[FI_RGBA_BLUE]) / 255;
+
+ src_pixel += bytespp;
+ dst_pixel ++;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+ }
+ break;
+
+ case FIT_RGB16:
+ {
+ const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGB16 *src_pixel = (FIRGB16*) src_bits;
+ FIRGBF *dst_pixel = (FIRGBF*) dst_bits;
+
+ for(unsigned x = 0; x < width; x++) {
+ // convert and scale to the range [0..1]
+ dst_pixel[x].red = (float)(src_pixel[x].red) / 65535;
+ dst_pixel[x].green = (float)(src_pixel[x].green) / 65535;
+ dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+ }
+ break;
+
+ case FIT_RGBA16:
+ {
+ const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGBA16 *src_pixel = (FIRGBA16*) src_bits;
+ FIRGBF *dst_pixel = (FIRGBF*) dst_bits;
+
+ for(unsigned x = 0; x < width; x++) {
+ // convert and scale to the range [0..1]
+ dst_pixel[x].red = (float)(src_pixel[x].red) / 65535;
+ dst_pixel[x].green = (float)(src_pixel[x].green) / 65535;
+ dst_pixel[x].blue = (float)(src_pixel[x].blue) / 65535;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+ }
+ break;
+
+ case FIT_RGBAF:
+ {
+ const BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGBAF *src_pixel = (FIRGBAF*) src_bits;
+ FIRGBF *dst_pixel = (FIRGBF*) dst_bits;
+
+ for(unsigned x = 0; x < width; x++) {
+ // convert and skip alpha channel
+ dst_pixel[x].red = src_pixel[x].red;
+ dst_pixel[x].green = src_pixel[x].green;
+ dst_pixel[x].blue = src_pixel[x].blue;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+ }
+ break;
+ }
+
+ if(src != dib) {
+ FreeImage_Unload(src);
+ }
+
+ return dst;
+}
+
diff --git a/Source/FreeImage/ConversionType.cpp b/Source/FreeImage/ConversionType.cpp
new file mode 100644
index 0000000..1952333
--- /dev/null
+++ b/Source/FreeImage/ConversionType.cpp
@@ -0,0 +1,687 @@
+// ==========================================================
+// Bitmap conversion routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+
+/** Convert a greyscale image of type Tsrc to type Tdst.
+ Conversion is done using standard C language casting convention.
+*/
+template<class Tdst, class Tsrc>
+class CONVERT_TYPE
+{
+public:
+ FIBITMAP* convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type);
+};
+
+template<class Tdst, class Tsrc> FIBITMAP*
+CONVERT_TYPE<Tdst, Tsrc>::convert(FIBITMAP *src, FREE_IMAGE_TYPE dst_type) {
+
+ FIBITMAP *dst = NULL;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ unsigned bpp = FreeImage_GetBPP(src);
+
+ // allocate dst image
+
+ dst = FreeImage_AllocateT(dst_type, width, height, bpp,
+ FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src));
+ if(!dst) return NULL;
+
+ // convert from src_type to dst_type
+
+ for(unsigned y = 0; y < height; y++) {
+ const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
+ Tdst *dst_bits = reinterpret_cast<Tdst*>(FreeImage_GetScanLine(dst, y));
+
+ for(unsigned x = 0; x < width; x++) {
+ *dst_bits++ = static_cast<Tdst>(*src_bits++);
+ }
+ }
+
+ return dst;
+}
+
+
+/** Convert a greyscale image of type Tsrc to a 8-bit grayscale dib.
+ Conversion is done using either a linear scaling from [min, max] to [0, 255]
+ or a rounding from src_pixel to (BYTE) MIN(255, MAX(0, q)) where int q = int(src_pixel + 0.5);
+*/
+template<class Tsrc>
+class CONVERT_TO_BYTE
+{
+public:
+ FIBITMAP* convert(FIBITMAP *src, BOOL scale_linear);
+};
+
+template<class Tsrc> FIBITMAP*
+CONVERT_TO_BYTE<Tsrc>::convert(FIBITMAP *src, BOOL scale_linear) {
+ FIBITMAP *dst = NULL;
+ unsigned x, y;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ // allocate a 8-bit dib
+
+ dst = FreeImage_AllocateT(FIT_BITMAP, width, height, 8, 0, 0, 0);
+ if(!dst) return NULL;
+
+ // build a greyscale palette
+ RGBQUAD *pal = FreeImage_GetPalette(dst);
+ for(int i = 0; i < 256; i++) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // convert the src image to dst
+ // (FIBITMAP are stored upside down)
+ if(scale_linear) {
+ Tsrc max, min;
+ double scale;
+
+ // find the min and max value of the image
+ Tsrc l_min, l_max;
+ min = 255, max = 0;
+ for(y = 0; y < height; y++) {
+ Tsrc *bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
+ MAXMIN(bits, width, l_max, l_min);
+ if(l_max > max) max = l_max;
+ if(l_min < min) min = l_min;
+ }
+ if(max == min) {
+ max = 255; min = 0;
+ }
+
+ // compute the scaling factor
+ scale = 255 / (double)(max - min);
+
+ // scale to 8-bit
+ for(y = 0; y < height; y++) {
+ Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ dst_bits[x] = (BYTE)( scale * (src_bits[x] - min) + 0.5);
+ }
+ }
+ } else {
+ for(y = 0; y < height; y++) {
+ Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ // rounding
+ int q = int(src_bits[x] + 0.5);
+ dst_bits[x] = (BYTE) MIN(255, MAX(0, q));
+ }
+ }
+ }
+
+ return dst;
+}
+
+/** Convert a greyscale image of type Tsrc to a FICOMPLEX dib.
+*/
+template<class Tsrc>
+class CONVERT_TO_COMPLEX
+{
+public:
+ FIBITMAP* convert(FIBITMAP *src);
+};
+
+template<class Tsrc> FIBITMAP*
+CONVERT_TO_COMPLEX<Tsrc>::convert(FIBITMAP *src) {
+ FIBITMAP *dst = NULL;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ // allocate dst image
+
+ dst = FreeImage_AllocateT(FIT_COMPLEX, width, height);
+ if(!dst) return NULL;
+
+ // convert from src_type to FIT_COMPLEX
+
+ for(unsigned y = 0; y < height; y++) {
+ const Tsrc *src_bits = reinterpret_cast<Tsrc*>(FreeImage_GetScanLine(src, y));
+ FICOMPLEX *dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y);
+
+ for(unsigned x = 0; x < width; x++) {
+ dst_bits[x].r = (double)src_bits[x];
+ dst_bits[x].i = 0;
+ }
+ }
+
+ return dst;
+}
+
+// ----------------------------------------------------------
+
+// Convert from type BYTE to type X
+CONVERT_TYPE<unsigned short, BYTE> convertByteToUShort;
+CONVERT_TYPE<short, BYTE> convertByteToShort;
+CONVERT_TYPE<unsigned long, BYTE> convertByteToULong;
+CONVERT_TYPE<long, BYTE> convertByteToLong;
+CONVERT_TYPE<float, BYTE> convertByteToFloat;
+CONVERT_TYPE<double, BYTE> convertByteToDouble;
+
+// Convert from type X to type BYTE
+CONVERT_TO_BYTE<unsigned short> convertUShortToByte;
+CONVERT_TO_BYTE<short> convertShortToByte;
+CONVERT_TO_BYTE<unsigned long> convertULongToByte;
+CONVERT_TO_BYTE<long> convertLongToByte;
+CONVERT_TO_BYTE<float> convertFloatToByte;
+CONVERT_TO_BYTE<double> convertDoubleToByte;
+
+// Convert from type X to type float
+CONVERT_TYPE<float, unsigned short> convertUShortToFloat;
+CONVERT_TYPE<float, short> convertShortToFloat;
+CONVERT_TYPE<float, unsigned long> convertULongToFloat;
+CONVERT_TYPE<float, long> convertLongToFloat;
+
+// Convert from type X to type double
+CONVERT_TYPE<double, unsigned short> convertUShortToDouble;
+CONVERT_TYPE<double, short> convertShortToDouble;
+CONVERT_TYPE<double, unsigned long> convertULongToDouble;
+CONVERT_TYPE<double, long> convertLongToDouble;
+CONVERT_TYPE<double, float> convertFloatToDouble;
+
+// Convert from type X to type FICOMPLEX
+CONVERT_TO_COMPLEX<BYTE> convertByteToComplex;
+CONVERT_TO_COMPLEX<unsigned short> convertUShortToComplex;
+CONVERT_TO_COMPLEX<short> convertShortToComplex;
+CONVERT_TO_COMPLEX<unsigned long> convertULongToComplex;
+CONVERT_TO_COMPLEX<long> convertLongToComplex;
+CONVERT_TO_COMPLEX<float> convertFloatToComplex;
+CONVERT_TO_COMPLEX<double> convertDoubleToComplex;
+
+// ----------------------------------------------------------
+
+// ----------------------------------------------------------
+// smart convert X to standard FIBITMAP
+// ----------------------------------------------------------
+
+/** Convert image of any type to a standard 8-bit greyscale image.
+For standard images, a clone of the input image is returned.
+When the scale_linear parameter is TRUE, conversion is done by scaling linearly
+each pixel to an integer value between [0..255]. When it is FALSE, conversion is done
+by rounding each float pixel to an integer between [0..255].
+For complex images, the magnitude is extracted as a double image, then converted according to the scale parameter.
+@param image Image to convert
+@param scale_linear Linear scaling / rounding switch
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_ConvertToStandardType(FIBITMAP *src, BOOL scale_linear) {
+ FIBITMAP *dst = NULL;
+
+ if(!src) return NULL;
+
+ // convert from src_type to FIT_BITMAP
+
+ const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src);
+
+ switch(src_type) {
+ case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
+ dst = FreeImage_Clone(src);
+ break;
+ case FIT_UINT16: // array of unsigned short: unsigned 16-bit
+ dst = convertUShortToByte.convert(src, scale_linear);
+ break;
+ case FIT_INT16: // array of short: signed 16-bit
+ dst = convertShortToByte.convert(src, scale_linear);
+ break;
+ case FIT_UINT32: // array of unsigned long: unsigned 32-bit
+ dst = convertULongToByte.convert(src, scale_linear);
+ break;
+ case FIT_INT32: // array of long: signed 32-bit
+ dst = convertLongToByte.convert(src, scale_linear);
+ break;
+ case FIT_FLOAT: // array of float: 32-bit
+ dst = convertFloatToByte.convert(src, scale_linear);
+ break;
+ case FIT_DOUBLE: // array of double: 64-bit
+ dst = convertDoubleToByte.convert(src, scale_linear);
+ break;
+ case FIT_COMPLEX: // array of FICOMPLEX: 2 x 64-bit
+ {
+ // Convert to type FIT_DOUBLE
+ FIBITMAP *dib_double = FreeImage_GetComplexChannel(src, FICC_MAG);
+ if(dib_double) {
+ // Convert to a standard bitmap (linear scaling)
+ dst = convertDoubleToByte.convert(dib_double, scale_linear);
+ // Free image of type FIT_DOUBLE
+ FreeImage_Unload(dib_double);
+ }
+ }
+ break;
+ case FIT_RGB16: // 48-bit RGB image: 3 x 16-bit
+ break;
+ case FIT_RGBA16: // 64-bit RGBA image: 4 x 16-bit
+ break;
+ case FIT_RGBF: // 96-bit RGB float image: 3 x 32-bit IEEE floating point
+ break;
+ case FIT_RGBAF: // 128-bit RGBA float image: 4 x 32-bit IEEE floating point
+ break;
+ }
+
+ if(NULL == dst) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, FIT_BITMAP);
+ } else {
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+ }
+
+ return dst;
+}
+
+
+
+// ----------------------------------------------------------
+// smart convert X to Y
+// ----------------------------------------------------------
+
+FIBITMAP* DLL_CALLCONV
+FreeImage_ConvertToType(FIBITMAP *src, FREE_IMAGE_TYPE dst_type, BOOL scale_linear) {
+ FIBITMAP *dst = NULL;
+
+ if(!src) return NULL;
+
+ // convert from src_type to dst_type
+
+ const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src);
+
+ if(src_type == dst_type) {
+ return FreeImage_Clone(src);
+ }
+ if(src_type == FIT_BITMAP) {
+ const unsigned src_bpp = FreeImage_GetBPP(src);
+ if(((src_bpp == 24) || (src_bpp == 32)) && (dst_type != FIT_RGBF)) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Only 24-/32-bit dib can be converted to type %d.", dst_type);
+ return NULL;
+ }
+ else if(src_bpp != 8) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Only 8-bit dib can be converted to type %d.", dst_type);
+ return NULL;
+ }
+ }
+
+ switch(src_type) {
+ case FIT_BITMAP:
+ switch(dst_type) {
+ case FIT_UINT16:
+ dst = convertByteToUShort.convert(src, dst_type);
+ break;
+ case FIT_INT16:
+ dst = convertByteToShort.convert(src, dst_type);
+ break;
+ case FIT_UINT32:
+ dst = convertByteToULong.convert(src, dst_type);
+ break;
+ case FIT_INT32:
+ dst = convertByteToLong.convert(src, dst_type);
+ break;
+ case FIT_FLOAT:
+ dst = convertByteToFloat.convert(src, dst_type);
+ break;
+ case FIT_DOUBLE:
+ dst = convertByteToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertByteToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ dst = FreeImage_ConvertToRGBF(src);
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_UINT16:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ dst = convertUShortToFloat.convert(src, dst_type);
+ break;
+ case FIT_DOUBLE:
+ dst = convertUShortToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertUShortToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_INT16:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ dst = convertShortToFloat.convert(src, dst_type);
+ break;
+ case FIT_DOUBLE:
+ dst = convertShortToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertShortToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_UINT32:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ dst = convertULongToFloat.convert(src, dst_type);
+ break;
+ case FIT_DOUBLE:
+ dst = convertULongToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertULongToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_INT32:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_FLOAT:
+ dst = convertLongToFloat.convert(src, dst_type);
+ break;
+ case FIT_DOUBLE:
+ dst = convertLongToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertLongToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_FLOAT:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_DOUBLE:
+ dst = convertFloatToDouble.convert(src, dst_type);
+ break;
+ case FIT_COMPLEX:
+ dst = convertFloatToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_DOUBLE:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertToStandardType(src, scale_linear);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_COMPLEX:
+ dst = convertDoubleToComplex.convert(src);
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_COMPLEX:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_DOUBLE:
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_RGB16:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertTo24Bits(src);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_DOUBLE:
+ break;
+ case FIT_COMPLEX:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ dst = FreeImage_ConvertToRGBF(src);
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_RGBA16:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ dst = FreeImage_ConvertTo32Bits(src);
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_DOUBLE:
+ break;
+ case FIT_COMPLEX:
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBF:
+ dst = FreeImage_ConvertToRGBF(src);
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_RGBF:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_DOUBLE:
+ break;
+ case FIT_COMPLEX:
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBAF:
+ break;
+ }
+ break;
+ case FIT_RGBAF:
+ switch(dst_type) {
+ case FIT_BITMAP:
+ break;
+ case FIT_UINT16:
+ break;
+ case FIT_INT16:
+ break;
+ case FIT_UINT32:
+ break;
+ case FIT_INT32:
+ break;
+ case FIT_FLOAT:
+ break;
+ case FIT_DOUBLE:
+ break;
+ case FIT_COMPLEX:
+ break;
+ case FIT_RGB16:
+ break;
+ case FIT_RGBA16:
+ break;
+ case FIT_RGBF:
+ dst = FreeImage_ConvertToRGBF(src);
+ break;
+ }
+ break;
+ }
+
+ if(NULL == dst) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "FREE_IMAGE_TYPE: Unable to convert from type %d to type %d.\n No such conversion exists.", src_type, dst_type);
+ } else {
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+ }
+
+ return dst;
+}
diff --git a/Source/FreeImage/FreeImage.cpp b/Source/FreeImage/FreeImage.cpp
new file mode 100644
index 0000000..f30a54b
--- /dev/null
+++ b/Source/FreeImage/FreeImage.cpp
@@ -0,0 +1,226 @@
+// ==========================================================
+// FreeImage implementation
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Karl-Heinz Bussian (khbussian@moss.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+//----------------------------------------------------------------------
+
+static const char *s_copyright = "This program uses FreeImage, a free, open source image library supporting all common bitmap formats. See http://freeimage.sourceforge.net for details";
+
+//----------------------------------------------------------------------
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+#ifndef FREEIMAGE_LIB
+
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH :
+ FreeImage_Initialise(FALSE);
+ break;
+
+ case DLL_PROCESS_DETACH :
+ FreeImage_DeInitialise();
+ break;
+
+ case DLL_THREAD_ATTACH :
+ case DLL_THREAD_DETACH :
+ break;
+ }
+
+ return TRUE;
+}
+
+#endif // FREEIMAGE_LIB
+
+#else // !_WIN32
+#ifndef FREEIMAGE_LIB
+
+void FreeImage_SO_Initialise() __attribute__((constructor));
+void FreeImage_SO_DeInitialise() __attribute__((destructor));
+
+void FreeImage_SO_Initialise() {
+ FreeImage_Initialise(FALSE);
+}
+
+void FreeImage_SO_DeInitialise() {
+ FreeImage_DeInitialise();
+}
+#endif // FREEIMAGE_LIB
+
+#endif // _WIN32
+
+//----------------------------------------------------------------------
+
+const char * DLL_CALLCONV
+FreeImage_GetVersion() {
+ static char s_version[16];
+ sprintf(s_version, "%d.%d.%d", FREEIMAGE_MAJOR_VERSION, FREEIMAGE_MINOR_VERSION, FREEIMAGE_RELEASE_SERIAL);
+ return s_version;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetCopyrightMessage() {
+ return s_copyright;
+}
+
+//----------------------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_IsLittleEndian() {
+ union {
+ long i;
+ char c[4];
+ } u;
+ u.i = 1;
+ return (u.c[0] != 0);
+}
+
+//----------------------------------------------------------------------
+
+static FreeImage_OutputMessageFunction freeimage_outputmessage_proc = NULL;
+static FreeImage_OutputMessageFunctionStdCall freeimage_outputmessagestdcall_proc = NULL;
+
+void DLL_CALLCONV
+FreeImage_SetOutputMessage(FreeImage_OutputMessageFunction omf) {
+ freeimage_outputmessage_proc = omf;
+}
+
+void DLL_CALLCONV
+FreeImage_SetOutputMessageStdCall(FreeImage_OutputMessageFunctionStdCall omf) {
+ freeimage_outputmessagestdcall_proc = omf;
+}
+
+void DLL_CALLCONV
+FreeImage_OutputMessageProc(int fif, const char *fmt, ...) {
+ const int MSG_SIZE = 512; // 512 bytes should be more than enough for a short message
+
+ if ((fmt != NULL) && ((freeimage_outputmessage_proc != NULL) || (freeimage_outputmessagestdcall_proc != NULL))) {
+ char message[MSG_SIZE];
+ memset(message, 0, MSG_SIZE);
+
+ // initialize the optional parameter list
+
+ va_list arg;
+ va_start(arg, fmt);
+
+ // check the length of the format string
+
+ int str_length = (int)( (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt) );
+
+ // parse the format string and put the result in 'message'
+
+ for (int i = 0, j = 0; i < str_length; ++i) {
+ if (fmt[i] == '%') {
+ if (i + 1 < str_length) {
+ switch(tolower(fmt[i + 1])) {
+ case '%' :
+ message[j++] = '%';
+ break;
+
+ case 'o' : // octal numbers
+ {
+ char tmp[16];
+
+ _itoa(va_arg(arg, int), tmp, 8);
+
+ strcat(message, tmp);
+
+ j += (int)strlen(tmp);
+
+ ++i;
+
+ break;
+ }
+
+ case 'i' : // decimal numbers
+ case 'd' :
+ {
+ char tmp[16];
+
+ _itoa(va_arg(arg, int), tmp, 10);
+
+ strcat(message, tmp);
+
+ j += (int)strlen(tmp);
+
+ ++i;
+
+ break;
+ }
+
+ case 'x' : // hexadecimal numbers
+ {
+ char tmp[16];
+
+ _itoa(va_arg(arg, int), tmp, 16);
+
+ strcat(message, tmp);
+
+ j += (int)strlen(tmp);
+
+ ++i;
+
+ break;
+ }
+
+ case 's' : // strings
+ {
+ char *tmp = va_arg(arg, char*);
+
+ strcat(message, tmp);
+
+ j += (int)strlen(tmp);
+
+ ++i;
+
+ break;
+ }
+ };
+ } else {
+ message[j++] = fmt[i];
+ }
+ } else {
+ message[j++] = fmt[i];
+ };
+ }
+
+ // deinitialize the optional parameter list
+
+ va_end(arg);
+
+ // output the message to the user program
+
+ if (freeimage_outputmessage_proc != NULL)
+ freeimage_outputmessage_proc((FREE_IMAGE_FORMAT)fif, message);
+
+ if (freeimage_outputmessagestdcall_proc != NULL)
+ freeimage_outputmessagestdcall_proc((FREE_IMAGE_FORMAT)fif, message);
+ }
+}
diff --git a/Source/FreeImage/FreeImageC.c b/Source/FreeImage/FreeImageC.c
new file mode 100644
index 0000000..9e81259
--- /dev/null
+++ b/Source/FreeImage/FreeImageC.c
@@ -0,0 +1,22 @@
+// ==========================================================
+// Use from c compiler test file
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
diff --git a/Source/FreeImage/FreeImageIO.cpp b/Source/FreeImage/FreeImageIO.cpp
new file mode 100644
index 0000000..90f32d9
--- /dev/null
+++ b/Source/FreeImage/FreeImageIO.cpp
@@ -0,0 +1,166 @@
+// ==========================================================
+// Input/Output functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageIO.h"
+
+// ----------------------------------------------------------
+
+unsigned DLL_CALLCONV
+_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ return (unsigned)fread(buffer, size, count, (FILE *)handle);
+}
+
+unsigned DLL_CALLCONV
+_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ return (unsigned)fwrite(buffer, size, count, (FILE *)handle);
+}
+
+int DLL_CALLCONV
+_SeekProc(fi_handle handle, long offset, int origin) {
+ return fseek((FILE *)handle, offset, origin);
+}
+
+long DLL_CALLCONV
+_TellProc(fi_handle handle) {
+ return ftell((FILE *)handle);
+}
+
+// ----------------------------------------------------------
+
+void
+SetDefaultIO(FreeImageIO *io) {
+ io->read_proc = _ReadProc;
+ io->seek_proc = _SeekProc;
+ io->tell_proc = _TellProc;
+ io->write_proc = _WriteProc;
+}
+
+// =====================================================================
+// Memory IO functions
+// =====================================================================
+
+unsigned DLL_CALLCONV
+_MemoryReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ unsigned x;
+
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
+
+ for(x = 0; x < count; x++) {
+ //if there isnt size bytes left to read, set pos to eof and return a short count
+ if( (mem_header->filelen - mem_header->curpos) < (long)size ) {
+ mem_header->curpos = mem_header->filelen;
+ break;
+ }
+ //copy size bytes count times
+ memcpy( buffer, (char *)mem_header->data + mem_header->curpos, size );
+ mem_header->curpos += size;
+ buffer = (char *)buffer + size;
+ }
+ return x;
+}
+
+unsigned DLL_CALLCONV
+_MemoryWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
+ void *newdata;
+ long newdatalen;
+
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
+
+ //double the data block size if we need to
+ while( (mem_header->curpos + (long)(size*count)) >= mem_header->datalen ) {
+ //if we are at or above 1G, we cant double without going negative
+ if( mem_header->datalen & 0x40000000 ) {
+ //max 2G
+ if( mem_header->datalen == 0x7FFFFFFF ) {
+ return 0;
+ }
+ newdatalen = 0x7FFFFFFF;
+ } else if( mem_header->datalen == 0 ) {
+ //default to 4K if nothing yet
+ newdatalen = 4096;
+ } else {
+ //double size
+ newdatalen = mem_header->datalen << 1;
+ }
+ newdata = realloc( mem_header->data, newdatalen );
+ if( !newdata ) {
+ return 0;
+ }
+ mem_header->data = newdata;
+ mem_header->datalen = newdatalen;
+ }
+ memcpy( (char *)mem_header->data + mem_header->curpos, buffer, size*count );
+ mem_header->curpos += size*count;
+ if( mem_header->curpos > mem_header->filelen ) {
+ mem_header->filelen = mem_header->curpos;
+ }
+ return count;
+}
+
+int DLL_CALLCONV
+_MemorySeekProc(fi_handle handle, long offset, int origin) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
+
+ switch(origin) { //0 to filelen-1 are 'inside' the file
+ default:
+ case SEEK_SET: //can fseek() to 0-7FFFFFFF always
+ if( offset >= 0 ) {
+ mem_header->curpos = offset;
+ return 0;
+ }
+ break;
+
+ case SEEK_CUR:
+ if( mem_header->curpos + offset >= 0 ) {
+ mem_header->curpos += offset;
+ return 0;
+ }
+ break;
+
+ case SEEK_END:
+ if( mem_header->filelen + offset >= 0 ) {
+ mem_header->curpos = mem_header->filelen + offset;
+ return 0;
+ }
+ break;
+ }
+
+ return -1;
+}
+
+long DLL_CALLCONV
+_MemoryTellProc(fi_handle handle) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)handle)->data);
+
+ return mem_header->curpos;
+}
+
+// ----------------------------------------------------------
+
+void
+SetMemoryIO(FreeImageIO *io) {
+ io->read_proc = _MemoryReadProc;
+ io->seek_proc = _MemorySeekProc;
+ io->tell_proc = _MemoryTellProc;
+ io->write_proc = _MemoryWriteProc;
+}
diff --git a/Source/FreeImage/GetType.cpp b/Source/FreeImage/GetType.cpp
new file mode 100644
index 0000000..76edc7f
--- /dev/null
+++ b/Source/FreeImage/GetType.cpp
@@ -0,0 +1,92 @@
+// ==========================================================
+// GetType
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageIO.h"
+#include "Plugin.h"
+#include "../DeprecationManager/DeprecationMgr.h"
+
+// ----------------------------------------------------------
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFileTypeFromHandle(FreeImageIO *io, fi_handle handle, int size) {
+ if (handle != NULL) {
+ int fif_count = FreeImage_GetFIFCount();
+
+ for (int i = 0; i < fif_count; ++i) {
+ FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i;
+ if (FreeImage_Validate(fif, io, handle)) {
+ if(fif == FIF_TIFF) {
+ // many camera raw files use a TIFF signature ...
+ // ... try to revalidate against FIF_RAW (even if it breaks the code genericity)
+ if (FreeImage_Validate(FIF_RAW, io, handle)) {
+ return FIF_RAW;
+ }
+ }
+ return fif;
+ }
+ }
+ }
+
+ return FIF_UNKNOWN;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFileType(const char *filename, int size) {
+ FreeImageIO io;
+ SetDefaultIO(&io);
+
+ FILE *handle = fopen(filename, "rb");
+
+ if (handle != NULL) {
+ FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)handle, size);
+
+ fclose(handle);
+
+ return format;
+ }
+
+ return FIF_UNKNOWN;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFileTypeU(const wchar_t *filename, int size) {
+#ifdef _WIN32
+ FreeImageIO io;
+ SetDefaultIO(&io);
+ FILE *handle = _wfopen(filename, L"rb");
+
+ if (handle != NULL) {
+ FREE_IMAGE_FORMAT format = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)handle, size);
+
+ fclose(handle);
+
+ return format;
+ }
+#endif
+ return FIF_UNKNOWN;
+}
+
diff --git a/Source/FreeImage/Halftoning.cpp b/Source/FreeImage/Halftoning.cpp
new file mode 100644
index 0000000..11de6fa
--- /dev/null
+++ b/Source/FreeImage/Halftoning.cpp
@@ -0,0 +1,474 @@
+// ==========================================================
+// Bitmap conversion routines
+// Thresholding and halftoning functions
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Dennis Lim (dlkj@users.sourceforge.net)
+// - Thomas Chmielewski (Chmielewski.Thomas@oce.de)
+//
+// Main reference : Ulichney, R., Digital Halftoning, The MIT Press, Cambridge, MA, 1987
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+static const int WHITE = 255;
+static const int BLACK = 0;
+
+// Floyd & Steinberg error diffusion dithering
+// This algorithm use the following filter
+// * 7
+// 3 5 1 (1/16)
+static FIBITMAP* FloydSteinberg(FIBITMAP *dib) {
+
+#define RAND(RN) (((seed = 1103515245 * seed + 12345) >> 12) % (RN))
+#define INITERR(X, Y) (((int) X) - (((int) Y) ? WHITE : BLACK) + ((WHITE/2)-((int)X)) / 2)
+
+ int seed = 0;
+ int x, y, p, pixel, threshold, error;
+ int width, height, pitch;
+ BYTE *bits, *new_bits;
+ FIBITMAP *new_dib = NULL;
+
+ // allocate a 8-bit DIB
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ pitch = FreeImage_GetPitch(dib);
+ new_dib = FreeImage_Allocate(width, height, 8);
+ if(NULL == new_dib) return NULL;
+
+ // allocate space for error arrays
+ int *lerr = (int*)malloc (width * sizeof(int));
+ int *cerr = (int*)malloc (width * sizeof(int));
+ memset(lerr, 0, width * sizeof(int));
+ memset(cerr, 0, width * sizeof(int));
+
+ // left border
+ error = 0;
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(dib, y);
+ new_bits = FreeImage_GetScanLine(new_dib, y);
+
+ threshold = (WHITE / 2 + RAND(129) - 64);
+ pixel = bits[0] + error;
+ p = (pixel > threshold) ? WHITE : BLACK;
+ error = pixel - p;
+ new_bits[0] = (BYTE)p;
+ }
+ // right border
+ error = 0;
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(dib, y);
+ new_bits = FreeImage_GetScanLine(new_dib, y);
+
+ threshold = (WHITE / 2 + RAND(129) - 64);
+ pixel = bits[width-1] + error;
+ p = (pixel > threshold) ? WHITE : BLACK;
+ error = pixel - p;
+ new_bits[width-1] = (BYTE)p;
+ }
+ // top border
+ bits = FreeImage_GetBits(dib);
+ new_bits = FreeImage_GetBits(new_dib);
+ error = 0;
+ for(x = 0; x < width; x++) {
+ threshold = (WHITE / 2 + RAND(129) - 64);
+ pixel = bits[x] + error;
+ p = (pixel > threshold) ? WHITE : BLACK;
+ error = pixel - p;
+ new_bits[x] = (BYTE)p;
+ lerr[x] = INITERR(bits[x], p);
+ }
+
+ // interior bits
+ for(y = 1; y < height; y++) {
+ // scan left to right
+ bits = FreeImage_GetScanLine(dib, y);
+ new_bits = FreeImage_GetScanLine(new_dib, y);
+
+ cerr[0] = INITERR(bits[0], new_bits[0]);
+ for(x = 1; x < width - 1; x++) {
+ error = (lerr[x-1] + 5 * lerr[x] + 3 * lerr[x+1] + 7 * cerr[x-1]) / 16;
+ pixel = bits[x] + error;
+ if(pixel > (WHITE / 2)) {
+ new_bits[x] = WHITE;
+ cerr[x] = pixel - WHITE;
+ } else {
+ new_bits[x] = BLACK;
+ cerr[x] = pixel - BLACK;
+ }
+ }
+ // set errors for ends of the row
+ cerr[0] = INITERR (bits[0], new_bits[0]);
+ cerr[width - 1] = INITERR (bits[width - 1], new_bits[width - 1]);
+
+ // swap error buffers
+ int *terr = lerr; lerr = cerr; cerr = terr;
+ }
+
+ free(lerr);
+ free(cerr);
+
+ return new_dib;
+}
+
+// ==========================================================
+// Bayer ordered dispersed dot dithering
+//
+
+// Function taken from "Ordered Dithering, Stephen Hawley, Graphics Gems, Academic Press, 1990"
+// This function is used to generate a Bayer dithering matrice whose dimension are 2^size by 2^size
+//
+static int dithervalue(int x, int y, int size) {
+ int d = 0;
+ /*
+ * calculate the dither value at a particular
+ * (x, y) over the size of the matrix.
+ */
+ while (size-->0) {
+ /* Think of d as the density. At every iteration,
+ * d is shifted left one and a new bit is put in the
+ * low bit based on x and y. If x is odd and y is even,
+ * or x is even and y is odd, a bit is put in. This
+ * generates the checkerboard seen in dithering.
+ * This quantity is shifted left again and the low bit of
+ * y is added in.
+ * This whole thing interleaves a checkerboard bit pattern
+ * and y's bits, which is the value you want.
+ */
+ d = (d <<1 | (x&1 ^ y&1))<<1 | y&1;
+ x >>= 1;
+ y >>= 1;
+ }
+ return d;
+}
+
+// Ordered dithering with a Bayer matrix of size 2^order by 2^order
+//
+static FIBITMAP* OrderedDispersedDot(FIBITMAP *dib, int order) {
+ int x, y;
+ int width, height;
+ BYTE *bits, *new_bits;
+ FIBITMAP *new_dib = NULL;
+
+ // allocate a 8-bit DIB
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ new_dib = FreeImage_Allocate(width, height, 8);
+ if(NULL == new_dib) return NULL;
+
+ // build the dithering matrix
+ int l = (1 << order); // square of dither matrix order; the dimensions of the matrix
+ BYTE *matrix = (BYTE*)malloc(l*l * sizeof(BYTE));
+ for(int i = 0; i < l*l; i++) {
+ // according to "Purdue University: Digital Image Processing Laboratory: Image Halftoning, April 30th, 2006
+ matrix[i] = (BYTE)( 255 * (((double)dithervalue(i / l, i % l, order) + 0.5) / (l*l)) );
+ }
+
+ // perform the dithering
+ for(y = 0; y < height; y++) {
+ // scan left to right
+ bits = FreeImage_GetScanLine(dib, y);
+ new_bits = FreeImage_GetScanLine(new_dib, y);
+ for(x = 0; x < width; x++) {
+ if(bits[x] > matrix[(x % l) + l * (y % l)]) {
+ new_bits[x] = WHITE;
+ } else {
+ new_bits[x] = BLACK;
+ }
+ }
+ }
+
+ free(matrix);
+
+ return new_dib;
+}
+
+// ==========================================================
+// Ordered clustered dot dithering
+//
+
+// NB : The predefined dither matrices are the same as matrices used in
+// the Netpbm package (http://netpbm.sourceforge.net) and are defined in Ulichney's book.
+// See also : The newsprint web site at http://www.cl.cam.ac.uk/~and1000/newsprint/
+// for more technical info on this dithering technique
+//
+static FIBITMAP* OrderedClusteredDot(FIBITMAP *dib, int order) {
+ // Order-3 clustered dithering matrix.
+ int cluster3[] = {
+ 9,11,10, 8, 6, 7,
+ 12,17,16, 5, 0, 1,
+ 13,14,15, 4, 3, 2,
+ 8, 6, 7, 9,11,10,
+ 5, 0, 1,12,17,16,
+ 4, 3, 2,13,14,15
+ };
+
+ // Order-4 clustered dithering matrix.
+ int cluster4[] = {
+ 18,20,19,16,13,11,12,15,
+ 27,28,29,22, 4, 3, 2, 9,
+ 26,31,30,21, 5, 0, 1,10,
+ 23,25,24,17, 8, 6, 7,14,
+ 13,11,12,15,18,20,19,16,
+ 4, 3, 2, 9,27,28,29,22,
+ 5, 0, 1,10,26,31,30,21,
+ 8, 6, 7,14,23,25,24,17
+ };
+
+ // Order-8 clustered dithering matrix.
+ int cluster8[] = {
+ 64, 69, 77, 87, 86, 76, 68, 67, 63, 58, 50, 40, 41, 51, 59, 60,
+ 70, 94,100,109,108, 99, 93, 75, 57, 33, 27, 18, 19, 28, 34, 52,
+ 78,101,114,116,115,112, 98, 83, 49, 26, 13, 11, 12, 15, 29, 44,
+ 88,110,123,124,125,118,107, 85, 39, 17, 4, 3, 2, 9, 20, 42,
+ 89,111,122,127,126,117,106, 84, 38, 16, 5, 0, 1, 10, 21, 43,
+ 79,102,119,121,120,113, 97, 82, 48, 25, 8, 6, 7, 14, 30, 45,
+ 71, 95,103,104,105, 96, 92, 74, 56, 32, 24, 23, 22, 31, 35, 53,
+ 65, 72, 80, 90, 91, 81, 73, 66, 62, 55, 47, 37, 36, 46, 54, 61,
+ 63, 58, 50, 40, 41, 51, 59, 60, 64, 69, 77, 87, 86, 76, 68, 67,
+ 57, 33, 27, 18, 19, 28, 34, 52, 70, 94,100,109,108, 99, 93, 75,
+ 49, 26, 13, 11, 12, 15, 29, 44, 78,101,114,116,115,112, 98, 83,
+ 39, 17, 4, 3, 2, 9, 20, 42, 88,110,123,124,125,118,107, 85,
+ 38, 16, 5, 0, 1, 10, 21, 43, 89,111,122,127,126,117,106, 84,
+ 48, 25, 8, 6, 7, 14, 30, 45, 79,102,119,121,120,113, 97, 82,
+ 56, 32, 24, 23, 22, 31, 35, 53, 71, 95,103,104,105, 96, 92, 74,
+ 62, 55, 47, 37, 36, 46, 54, 61, 65, 72, 80, 90, 91, 81, 73, 66
+ };
+
+ int x, y, pixel;
+ int width, height;
+ BYTE *bits, *new_bits;
+ FIBITMAP *new_dib = NULL;
+
+ // allocate a 8-bit DIB
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ new_dib = FreeImage_Allocate(width, height, 8);
+ if(NULL == new_dib) return NULL;
+
+ // select the dithering matrix
+ int *matrix = NULL;
+ switch(order) {
+ case 3:
+ matrix = &cluster3[0];
+ break;
+ case 4:
+ matrix = &cluster4[0];
+ break;
+ case 8:
+ matrix = &cluster8[0];
+ break;
+ default:
+ return NULL;
+ }
+
+ // scale the dithering matrix
+ int l = 2 * order;
+ int scale = 256 / (l * order);
+ for(y = 0; y < l; y++) {
+ for(x = 0; x < l; x++) {
+ matrix[y*l + x] *= scale;
+ }
+ }
+
+ // perform the dithering
+ for(y = 0; y < height; y++) {
+ // scan left to right
+ bits = FreeImage_GetScanLine(dib, y);
+ new_bits = FreeImage_GetScanLine(new_dib, y);
+ for(x = 0; x < width; x++) {
+ pixel = bits[x];
+ if(pixel >= matrix[(y % l) + l * (x % l)]) {
+ new_bits[x] = WHITE;
+ } else {
+ new_bits[x] = BLACK;
+ }
+ }
+ }
+
+ return new_dib;
+}
+
+
+// ==========================================================
+// Halftoning function
+//
+FIBITMAP * DLL_CALLCONV
+FreeImage_Dither(FIBITMAP *dib, FREE_IMAGE_DITHER algorithm) {
+ FIBITMAP *input = NULL, *dib8 = NULL;
+
+ if(NULL == dib) return NULL;
+
+ const unsigned bpp = FreeImage_GetBPP(dib);
+
+ if(bpp == 1) {
+ // Just clone the dib and adjust the palette if needed
+ FIBITMAP *new_dib = FreeImage_Clone(dib);
+ if(NULL == new_dib) return NULL;
+ if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) {
+ // Build a monochrome palette
+ RGBQUAD *pal = FreeImage_GetPalette(new_dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ }
+ return new_dib;
+ }
+
+ // Convert the input dib to a 8-bit greyscale dib
+ //
+ switch(bpp) {
+ case 8:
+ if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
+ input = dib;
+ } else {
+ input = FreeImage_ConvertToGreyscale(dib);
+ }
+ break;
+ case 4:
+ case 16:
+ case 24:
+ case 32:
+ input = FreeImage_ConvertToGreyscale(dib);
+ break;
+ }
+ if(NULL == input) return NULL;
+
+ // Apply the dithering algorithm
+ switch(algorithm) {
+ case FID_FS:
+ dib8 = FloydSteinberg(input);
+ break;
+ case FID_BAYER4x4:
+ dib8 = OrderedDispersedDot(input, 2);
+ break;
+ case FID_BAYER8x8:
+ dib8 = OrderedDispersedDot(input, 3);
+ break;
+ case FID_BAYER16x16:
+ dib8 = OrderedDispersedDot(input, 4);
+ break;
+ case FID_CLUSTER6x6:
+ dib8 = OrderedClusteredDot(input, 3);
+ break;
+ case FID_CLUSTER8x8:
+ dib8 = OrderedClusteredDot(input, 4);
+ break;
+ case FID_CLUSTER16x16:
+ dib8 = OrderedClusteredDot(input, 8);
+ break;
+ }
+ if(input != dib) {
+ FreeImage_Unload(input);
+ }
+
+ // Build a greyscale palette (needed by threshold)
+ RGBQUAD *grey_pal = FreeImage_GetPalette(dib8);
+ for(int i = 0; i < 256; i++) {
+ grey_pal[i].rgbRed = (BYTE)i;
+ grey_pal[i].rgbGreen = (BYTE)i;
+ grey_pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // Convert to 1-bit
+ FIBITMAP *new_dib = FreeImage_Threshold(dib8, 128);
+ FreeImage_Unload(dib8);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ return new_dib;
+}
+
+// ==========================================================
+// Thresholding function
+//
+FIBITMAP * DLL_CALLCONV
+FreeImage_Threshold(FIBITMAP *dib, BYTE T) {
+ FIBITMAP *dib8 = NULL;
+
+ if(NULL == dib) return NULL;
+
+ const unsigned bpp = FreeImage_GetBPP(dib);
+
+ if(bpp == 1) {
+ // Just clone the dib and adjust the palette if needed
+ FIBITMAP *new_dib = FreeImage_Clone(dib);
+ if(NULL == new_dib) return NULL;
+ if(FreeImage_GetColorType(new_dib) == FIC_PALETTE) {
+ // Build a monochrome palette
+ RGBQUAD *pal = FreeImage_GetPalette(new_dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ }
+ return new_dib;
+ }
+
+ // Convert the input dib to a 8-bit greyscale dib
+ //
+ switch(bpp) {
+ case 8:
+ if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
+ dib8 = dib;
+ } else {
+ dib8 = FreeImage_ConvertToGreyscale(dib);
+ }
+ break;
+ case 4:
+ case 16:
+ case 24:
+ case 32:
+ dib8 = FreeImage_ConvertToGreyscale(dib);
+ break;
+ }
+ if(NULL == dib8) return NULL;
+
+ // Allocate a new 1-bit DIB
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 1);
+ if(NULL == new_dib) return NULL;
+ // Build a monochrome palette
+ RGBQUAD *pal = FreeImage_GetPalette(new_dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+
+ // Perform the thresholding
+ //
+ for(int y = 0; y < height; y++) {
+ BYTE *bits8 = FreeImage_GetScanLine(dib8, y);
+ BYTE *bits1 = FreeImage_GetScanLine(new_dib, y);
+ for(int x = 0; x < width; x++) {
+ if(bits8[x] < T) {
+ // Set bit(x, y) to 0
+ bits1[x >> 3] &= (0xFF7F >> (x & 0x7));
+ } else {
+ // Set bit(x, y) to 1
+ bits1[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ }
+ }
+ if(dib8 != dib) {
+ FreeImage_Unload(dib8);
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(new_dib, dib);
+
+ return new_dib;
+}
+
diff --git a/Source/FreeImage/J2KHelper.cpp b/Source/FreeImage/J2KHelper.cpp
new file mode 100644
index 0000000..786eccb
--- /dev/null
+++ b/Source/FreeImage/J2KHelper.cpp
@@ -0,0 +1,493 @@
+// ==========================================================
+// JPEG2000 helpers
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../LibOpenJPEG/openjpeg.h"
+
+/**
+Divide an integer by a power of 2 and round upwards
+@return Returns a divided by 2^b
+*/
+static int int_ceildivpow2(int a, int b) {
+ return (a + (1 << b) - 1) >> b;
+}
+
+/**
+Convert a OpenJPEG image to a FIBITMAP
+@param format_id Plugin ID
+@param image OpenJPEG image
+@return Returns the converted image if successful, returns NULL otherwise
+*/
+FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ // compute image width and height
+
+ //int w = int_ceildiv(image->x1 - image->x0, image->comps[0].dx);
+ int wr = image->comps[0].w;
+ int wrr = int_ceildivpow2(image->comps[0].w, image->comps[0].factor);
+
+ //int h = int_ceildiv(image->y1 - image->y0, image->comps[0].dy);
+ //int hr = image->comps[0].h;
+ int hrr = int_ceildivpow2(image->comps[0].h, image->comps[0].factor);
+
+ // check the number of components
+
+ int numcomps = image->numcomps;
+
+ BOOL bIsValid = TRUE;
+ for(int c = 0; c < numcomps - 1; c++) {
+ if( (image->comps[c].dx == image->comps[c+1].dx) &&
+ (image->comps[c].dy == image->comps[c+1].dy) &&
+ (image->comps[c].prec == image->comps[c+1].prec) ) {
+ continue;
+ } else {
+ bIsValid = FALSE;
+ break;
+ }
+ }
+ bIsValid &= ((numcomps == 1) || (numcomps == 3) || (numcomps == 4));
+ if(!bIsValid) {
+ if(numcomps) {
+ FreeImage_OutputMessageProc(format_id, "Warning: image contains %d greyscale components. Only the first will be loaded.\n", numcomps);
+ numcomps = 1;
+ } else {
+ // unknown type
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+ }
+
+ // create a new DIB
+
+ if(image->comps[0].prec <= 8) {
+ switch(numcomps) {
+ case 1:
+ dib = FreeImage_Allocate(wrr, hrr, 8);
+ break;
+ case 3:
+ dib = FreeImage_Allocate(wrr, hrr, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ break;
+ case 4:
+ dib = FreeImage_Allocate(wrr, hrr, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ break;
+ }
+ } else if(image->comps[0].prec <= 16) {
+ switch(numcomps) {
+ case 1:
+ dib = FreeImage_AllocateT(FIT_UINT16, wrr, hrr);
+ break;
+ case 3:
+ dib = FreeImage_AllocateT(FIT_RGB16, wrr, hrr);
+ break;
+ case 4:
+ dib = FreeImage_AllocateT(FIT_RGBA16, wrr, hrr);
+ break;
+ }
+ } else {
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ if(image->comps[0].prec <= 8) {
+ if(numcomps == 1) {
+ // 8-bit greyscale
+ // ----------------------------------------------------------
+
+ // build a greyscale palette
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for (int i = 0; i < 256; i++) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int index = image->comps[0].data[pixel_pos];
+ index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ bits[x] = (BYTE)index;
+
+ pixel_count++;
+ }
+ }
+ }
+ else if(numcomps == 3) {
+
+ // 24-bit RGB
+ // ----------------------------------------------------------
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int r = image->comps[0].data[pixel_pos];
+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ int g = image->comps[1].data[pixel_pos];
+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+
+ int b = image->comps[2].data[pixel_pos];
+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ bits[FI_RGBA_RED] = (BYTE)r;
+ bits[FI_RGBA_GREEN] = (BYTE)g;
+ bits[FI_RGBA_BLUE] = (BYTE)b;
+ bits += 3;
+
+ pixel_count++;
+ }
+ }
+ }
+ else if(numcomps == 4) {
+
+ // 32-bit RGBA
+ // ----------------------------------------------------------
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int r = image->comps[0].data[pixel_pos];
+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ int g = image->comps[1].data[pixel_pos];
+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+
+ int b = image->comps[2].data[pixel_pos];
+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ int a = image->comps[3].data[pixel_pos];
+ a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
+
+ bits[FI_RGBA_RED] = (BYTE)r;
+ bits[FI_RGBA_GREEN] = (BYTE)g;
+ bits[FI_RGBA_BLUE] = (BYTE)b;
+ bits[FI_RGBA_ALPHA] = (BYTE)a;
+ bits += 4;
+
+ pixel_count++;
+ }
+ }
+ }
+ }
+ else if(image->comps[0].prec <= 16) {
+ if(numcomps == 1) {
+ // 16-bit greyscale
+ // ----------------------------------------------------------
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ unsigned short *bits = (unsigned short*)FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int index = image->comps[0].data[pixel_pos];
+ index += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ bits[x] = (unsigned short)index;
+
+ pixel_count++;
+ }
+ }
+ }
+ else if(numcomps == 3) {
+
+ // 48-bit RGB
+ // ----------------------------------------------------------
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int r = image->comps[0].data[pixel_pos];
+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ int g = image->comps[1].data[pixel_pos];
+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+
+ int b = image->comps[2].data[pixel_pos];
+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ bits[x].red = (WORD)r;
+ bits[x].green = (WORD)g;
+ bits[x].blue = (WORD)b;
+
+ pixel_count++;
+ }
+ }
+ }
+ else if(numcomps == 4) {
+
+ // 64-bit RGBA
+ // ----------------------------------------------------------
+
+ // load pixel data
+
+ unsigned pixel_count = 0;
+
+ for(int y = 0; y < hrr; y++) {
+ FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, hrr - 1 - y);
+
+ for(int x = 0; x < wrr; x++) {
+ const unsigned pixel_pos = pixel_count / wrr * wr + pixel_count % wrr;
+
+ int r = image->comps[0].data[pixel_pos];
+ r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0);
+
+ int g = image->comps[1].data[pixel_pos];
+ g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0);
+
+ int b = image->comps[2].data[pixel_pos];
+ b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0);
+
+ int a = image->comps[3].data[pixel_pos];
+ a += (image->comps[3].sgnd ? 1 << (image->comps[3].prec - 1) : 0);
+
+ bits[x].red = (WORD)r;
+ bits[x].green = (WORD)g;
+ bits[x].blue = (WORD)b;
+ bits[x].alpha = (WORD)a;
+
+ pixel_count++;
+ }
+ }
+ }
+ }
+
+ return dib;
+
+ } catch(const char *text) {
+ if(dib) FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(format_id, text);
+ return NULL;
+ }
+
+}
+
+/**
+Convert a FIBITMAP to a OpenJPEG image
+@param format_id Plugin ID
+@param dib FreeImage image
+@param parameters Compression parameters
+@return Returns the converted image if successful, returns NULL otherwise
+*/
+opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters) {
+ int prec, numcomps, x, y, index;
+ OPJ_COLOR_SPACE color_space;
+ opj_image_cmptparm_t cmptparm[4]; // maximum of 4 components
+ opj_image_t *image = NULL; // image to encode
+
+ try {
+ int w = FreeImage_GetWidth(dib);
+ int h = FreeImage_GetHeight(dib);
+
+ // get image characteristics
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ if(image_type == FIT_BITMAP) {
+ // standard image ...
+ prec = 8;
+ switch(FreeImage_GetColorType(dib)) {
+ case FIC_MINISBLACK:
+ numcomps = 1;
+ color_space = CLRSPC_GRAY;
+ break;
+ case FIC_RGB:
+ numcomps = 3;
+ color_space = CLRSPC_SRGB;
+ break;
+ case FIC_RGBALPHA:
+ numcomps = 4;
+ color_space = CLRSPC_SRGB;
+ break;
+ default:
+ return NULL;
+ }
+ } else {
+ // HDR image ...
+ prec = 16;
+ switch(image_type) {
+ case FIT_UINT16:
+ numcomps = 1;
+ color_space = CLRSPC_GRAY;
+ break;
+ case FIT_RGB16:
+ numcomps = 3;
+ color_space = CLRSPC_SRGB;
+ break;
+ case FIT_RGBA16:
+ numcomps = 4;
+ color_space = CLRSPC_SRGB;
+ break;
+ default:
+ return NULL;
+ }
+ }
+
+ // initialize image components
+ memset(&cmptparm[0], 0, 4 * sizeof(opj_image_cmptparm_t));
+ for(int i = 0; i < numcomps; i++) {
+ cmptparm[i].dx = parameters->subsampling_dx;
+ cmptparm[i].dy = parameters->subsampling_dy;
+ cmptparm[i].w = w;
+ cmptparm[i].h = h;
+ cmptparm[i].prec = prec;
+ cmptparm[i].bpp = prec;
+ cmptparm[i].sgnd = 0;
+ }
+ // create the image
+ image = opj_image_create(numcomps, &cmptparm[0], color_space);
+ if(!image) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set image offset and reference grid
+ image->x0 = parameters->image_offset_x0;
+ image->y0 = parameters->image_offset_y0;
+ image->x1 = parameters->image_offset_x0 + (w - 1) * parameters->subsampling_dx + 1;
+ image->y1 = parameters->image_offset_y0 + (h - 1) * parameters->subsampling_dy + 1;
+
+ // set image data
+ if(prec == 8) {
+ switch(numcomps) {
+ case 1:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[x];
+ index++;
+ }
+ }
+ break;
+ case 3:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[FI_RGBA_RED];
+ image->comps[1].data[index] = bits[FI_RGBA_GREEN];
+ image->comps[2].data[index] = bits[FI_RGBA_BLUE];
+ bits += 3;
+ index++;
+ }
+ }
+ break;
+ case 4:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[FI_RGBA_RED];
+ image->comps[1].data[index] = bits[FI_RGBA_GREEN];
+ image->comps[2].data[index] = bits[FI_RGBA_BLUE];
+ image->comps[3].data[index] = bits[FI_RGBA_ALPHA];
+ bits += 4;
+ index++;
+ }
+ }
+ break;
+ }
+ }
+ else if(prec == 16) {
+ switch(numcomps) {
+ case 1:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ WORD *bits = (WORD*)FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[x];
+ index++;
+ }
+ }
+ break;
+ case 3:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[x].red;
+ image->comps[1].data[index] = bits[x].green;
+ image->comps[2].data[index] = bits[x].blue;
+ index++;
+ }
+ }
+ break;
+ case 4:
+ index = 0;
+ for(y = 0; y < h; y++) {
+ FIRGBA16 *bits = (FIRGBA16*)FreeImage_GetScanLine(dib, h - 1 - y);
+ for(x = 0; x < w; x++) {
+ image->comps[0].data[index] = bits[x].red;
+ image->comps[1].data[index] = bits[x].green;
+ image->comps[2].data[index] = bits[x].blue;
+ image->comps[3].data[index] = bits[x].alpha;
+ index++;
+ }
+ }
+ break;
+ }
+ }
+
+ return image;
+
+ } catch (const char *text) {
+ if(image) opj_image_destroy(image);
+ FreeImage_OutputMessageProc(format_id, text);
+ return NULL;
+ }
+}
diff --git a/Source/FreeImage/MemoryIO.cpp b/Source/FreeImage/MemoryIO.cpp
new file mode 100644
index 0000000..1d6a002
--- /dev/null
+++ b/Source/FreeImage/MemoryIO.cpp
@@ -0,0 +1,234 @@
+// ==========================================================
+// Memory Input/Output functions
+//
+// Design and implementation by
+// - Ryan Rubley <ryan@lostreality.org>
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageIO.h"
+
+// =====================================================================
+
+
+// =====================================================================
+// Open and close a memory handle
+// =====================================================================
+
+FIMEMORY * DLL_CALLCONV
+FreeImage_OpenMemory(BYTE *data, DWORD size_in_bytes) {
+ // allocate a memory handle
+ FIMEMORY *stream = (FIMEMORY*)malloc(sizeof(FIMEMORY));
+ if(stream) {
+ stream->data = (BYTE*)malloc(sizeof(FIMEMORYHEADER));
+
+ if(stream->data) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data);
+
+ // initialize the memory header
+ memset(mem_header, 0, sizeof(FIMEMORYHEADER));
+
+ if(data && size_in_bytes) {
+ // wrap a user buffer
+ mem_header->delete_me = FALSE;
+ mem_header->data = (BYTE*)data;
+ mem_header->datalen = mem_header->filelen = size_in_bytes;
+ } else {
+ mem_header->delete_me = TRUE;
+ }
+
+ return stream;
+ }
+ free(stream);
+ }
+
+ return NULL;
+}
+
+
+void DLL_CALLCONV
+FreeImage_CloseMemory(FIMEMORY *stream) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data);
+ if(mem_header->delete_me)
+ free(mem_header->data);
+ free(mem_header);
+ free(stream);
+}
+
+// =====================================================================
+// Memory stream load/save functions
+// =====================================================================
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) {
+ if (stream && stream->data) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ return FreeImage_LoadFromHandle(fif, &io, (fi_handle)stream, flags);
+ }
+
+ return NULL;
+}
+
+
+BOOL DLL_CALLCONV
+FreeImage_SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FIMEMORY *stream, int flags) {
+ if (stream) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data);
+
+ if(mem_header->delete_me == TRUE) {
+ return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)stream, flags);
+ } else {
+ // do not save in a user buffer
+ FreeImage_OutputMessageProc(fif, "Memory buffer is read only");
+ }
+ }
+
+ return FALSE;
+}
+
+// =====================================================================
+// Memory stream buffer access
+// =====================================================================
+
+BOOL DLL_CALLCONV
+FreeImage_AcquireMemory(FIMEMORY *stream, BYTE **data, DWORD *size_in_bytes) {
+ if (stream) {
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(stream->data);
+
+ *data = (BYTE*)mem_header->data;
+ *size_in_bytes = mem_header->filelen;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// =====================================================================
+// Memory stream file type access
+// =====================================================================
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFileTypeFromMemory(FIMEMORY *stream, int size) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ if (stream != NULL) {
+ return FreeImage_GetFileTypeFromHandle(&io, (fi_handle)stream, size);
+ }
+
+ return FIF_UNKNOWN;
+}
+
+// =====================================================================
+// Seeking in Memory stream
+// =====================================================================
+
+/**
+Moves the memory pointer to a specified location
+@param stream Pointer to FIMEMORY structure
+@param offset Number of bytes from origin
+@param origin Initial position
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+BOOL DLL_CALLCONV
+FreeImage_SeekMemory(FIMEMORY *stream, long offset, int origin) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ if (stream != NULL) {
+ int success = io.seek_proc((fi_handle)stream, offset, origin);
+ return (success == 0) ? TRUE : FALSE;
+ }
+
+ return FALSE;
+}
+
+/**
+Gets the current position of a memory pointer
+@param stream Target FIMEMORY structure
+@return Returns the current file position if successful, -1 otherwise
+*/
+long DLL_CALLCONV
+FreeImage_TellMemory(FIMEMORY *stream) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ if (stream != NULL) {
+ return io.tell_proc((fi_handle)stream);
+ }
+
+ return -1L;
+}
+
+// =====================================================================
+// Reading or Writing in Memory stream
+// =====================================================================
+
+/**
+Reads data from a memory stream
+@param buffer Storage location for data
+@param size Item size in bytes
+@param count Maximum number of items to be read
+@param stream Pointer to FIMEMORY structure
+@return Returns the number of full items actually read, which may be less than count if an error occurs
+*/
+unsigned DLL_CALLCONV
+FreeImage_ReadMemory(void *buffer, unsigned size, unsigned count, FIMEMORY *stream) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ if (stream != NULL) {
+ return io.read_proc(buffer, size, count, stream);
+ }
+
+ return 0;
+}
+
+/**
+Writes data to a memory stream.
+@param buffer Pointer to data to be written
+@param size Item size in bytes
+@param count Maximum number of items to be written
+@param stream Pointer to FIMEMORY structure
+@return Returns the number of full items actually written, which may be less than count if an error occurs
+*/
+unsigned DLL_CALLCONV
+FreeImage_WriteMemory(const void *buffer, unsigned size, unsigned count, FIMEMORY *stream) {
+ if (stream != NULL) {
+ FreeImageIO io;
+ SetMemoryIO(&io);
+
+ FIMEMORYHEADER *mem_header = (FIMEMORYHEADER*)(((FIMEMORY*)stream)->data);
+
+ if(mem_header->delete_me == TRUE) {
+ return io.write_proc((void *)buffer, size, count, stream);
+ } else {
+ // do not write in a user buffer
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Memory buffer is read only");
+ }
+ }
+
+ return 0;
+}
+
diff --git a/Source/FreeImage/MultiPage.cpp b/Source/FreeImage/MultiPage.cpp
new file mode 100644
index 0000000..9e09527
--- /dev/null
+++ b/Source/FreeImage/MultiPage.cpp
@@ -0,0 +1,892 @@
+// ==========================================================
+// Multi-Page functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Laurent Rocher (rocherl@club-internet.fr)
+// - Steve Johnson (steve@parisgroup.net)
+// - Petr Pytelka (pyta@lightcomp.com)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Vadim Alexandrov (vadimalexandrov@users.sourceforge.net
+// - Martin Dyring-Andersen (mda@spamfighter.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "CacheFile.h"
+#include "FreeImageIO.h"
+#include "Plugin.h"
+#include "Utilities.h"
+#include "FreeImage.h"
+
+// ----------------------------------------------------------
+
+enum BlockType { BLOCK_CONTINUEUS, BLOCK_REFERENCE };
+
+// ----------------------------------------------------------
+
+struct BlockTypeS {
+ BlockType m_type;
+
+ BlockTypeS(BlockType type) : m_type(type) {
+ }
+};
+
+struct BlockContinueus : public BlockTypeS {
+ int m_start;
+ int m_end;
+
+ BlockContinueus(int s, int e) : BlockTypeS(BLOCK_CONTINUEUS),
+ m_start(s),
+ m_end(e) {
+ }
+};
+
+struct BlockReference : public BlockTypeS {
+ int m_reference;
+ int m_size;
+
+ BlockReference(int r, int size) : BlockTypeS(BLOCK_REFERENCE),
+ m_reference(r),
+ m_size(size) {
+ }
+};
+
+// ----------------------------------------------------------
+
+typedef std::list<BlockTypeS *> BlockList;
+typedef std::list<BlockTypeS *>::iterator BlockListIterator;
+
+// ----------------------------------------------------------
+
+FI_STRUCT (MULTIBITMAPHEADER) {
+ PluginNode *node;
+ FREE_IMAGE_FORMAT fif;
+ FreeImageIO *io;
+ fi_handle handle;
+ CacheFile *m_cachefile;
+ std::map<FIBITMAP *, int> locked_pages;
+ BOOL changed;
+ int page_count;
+ BlockList m_blocks;
+ char *m_filename;
+ BOOL read_only;
+ FREE_IMAGE_FORMAT cache_fif;
+ int load_flags;
+};
+
+// =====================================================================
+// Internal Multipage functions
+// =====================================================================
+
+inline MULTIBITMAPHEADER *
+FreeImage_GetMultiBitmapHeader(FIMULTIBITMAP *bitmap) {
+ return (MULTIBITMAPHEADER *)bitmap->data;
+}
+
+static BlockListIterator DLL_CALLCONV
+FreeImage_FindBlock(FIMULTIBITMAP *bitmap, int position) {
+ assert(NULL != bitmap);
+
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ // step 1: find the block that matches the given position
+
+ int prev_count = 0;
+ int count = 0;
+ BlockListIterator i;
+ BlockTypeS *current_block = NULL;
+
+ for (i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) {
+ prev_count = count;
+
+ switch((*i)->m_type) {
+ case BLOCK_CONTINUEUS :
+ count += ((BlockContinueus *)(*i))->m_end - ((BlockContinueus *)(*i))->m_start + 1;
+ break;
+
+ case BLOCK_REFERENCE :
+ count++;
+ break;
+ }
+
+ current_block = *i;
+
+ if (count > position)
+ break;
+ }
+
+ // step 2: make sure we found the node. from here it gets a little complicated:
+ // * if the block is there, just return it
+ // * if the block is a series of blocks, split it in max 3 new blocks
+ // and return the splitted block
+
+ if ((current_block) && (count > position)) {
+ switch(current_block->m_type) {
+ case BLOCK_REFERENCE :
+ return i;
+
+ case BLOCK_CONTINUEUS :
+ {
+ BlockContinueus *block = (BlockContinueus *)current_block;
+
+ if (block->m_start != block->m_end) {
+ int item = block->m_start + (position - prev_count);
+
+ // left part
+
+ if (item != block->m_start) {
+ BlockContinueus *block_a = new BlockContinueus(block->m_start, item - 1);
+ header->m_blocks.insert(i, (BlockTypeS *)block_a);
+ }
+
+ // middle part
+
+ BlockContinueus *block_b = new BlockContinueus(item, item);
+ BlockListIterator block_target = header->m_blocks.insert(i, (BlockTypeS *)block_b);
+
+ // right part
+
+ if (item != block->m_end) {
+ BlockContinueus *block_c = new BlockContinueus(item + 1, block->m_end);
+ header->m_blocks.insert(i, (BlockTypeS *)block_c);
+ }
+
+ // remove the old block that was just splitted
+
+ header->m_blocks.remove((BlockTypeS *)block);
+ delete block;
+
+ // return the splitted block
+
+ return block_target;
+ }
+
+ return i;
+ }
+ }
+ }
+ // we should never go here ...
+ assert(false);
+ return header->m_blocks.end();
+}
+
+int DLL_CALLCONV
+FreeImage_InternalGetPageCount(FIMULTIBITMAP *bitmap) {
+ if (bitmap) {
+ if (((MULTIBITMAPHEADER *)bitmap->data)->handle) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ header->io->seek_proc(header->handle, 0, SEEK_SET);
+
+ void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE);
+
+ int page_count = (header->node->m_plugin->pagecount_proc != NULL) ? header->node->m_plugin->pagecount_proc(header->io, header->handle, data) : 1;
+
+ FreeImage_Close(header->node, header->io, header->handle, data);
+
+ return page_count;
+ }
+ }
+
+ return 0;
+}
+
+// =====================================================================
+// Multipage functions
+// =====================================================================
+
+FIMULTIBITMAP * DLL_CALLCONV
+FreeImage_LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY *stream, int flags) {
+ // retrieve the plugin list to find the node belonging to this plugin
+
+ PluginList *list = FreeImage_GetPluginList();
+
+ if (list) {
+ PluginNode *node = list->FindNodeFromFIF(fif);
+
+ if (node) {
+ FreeImageIO *io = new FreeImageIO;
+
+ if (io) {
+ SetMemoryIO(io);
+
+ FIMULTIBITMAP *bitmap = new FIMULTIBITMAP;
+
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = new MULTIBITMAPHEADER;
+
+ header->m_filename = NULL;
+ header->node = node;
+ header->fif = fif;
+ header->io = io;
+ header->handle = (fi_handle)stream;
+ header->changed = FALSE;
+ header->read_only = TRUE;
+ header->m_cachefile = NULL;
+ header->cache_fif = fif;
+ header->load_flags = flags;
+
+ if (header) {
+ // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure
+
+ bitmap->data = header;
+
+ // cache the page count
+
+ header->page_count = FreeImage_InternalGetPageCount(bitmap);
+
+ // allocate a continueus block to describe the bitmap
+
+ header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1));
+
+ // set up the cache
+
+ return bitmap;
+ }
+
+ return NULL;
+ }
+ }
+
+ delete io;
+ }
+ }
+
+ return NULL;
+}
+
+FIMULTIBITMAP * DLL_CALLCONV
+FreeImage_OpenMultiBitmap(FREE_IMAGE_FORMAT fif, const char *filename, BOOL create_new, BOOL read_only, BOOL keep_cache_in_memory, int flags) {
+ // sanity check on the parameters
+
+ if (create_new)
+ read_only = FALSE;
+
+ // retrieve the plugin list to find the node belonging to this plugin
+
+ PluginList *list = FreeImage_GetPluginList();
+
+ if (list) {
+ PluginNode *node = list->FindNodeFromFIF(fif);
+
+ if (node) {
+ FreeImageIO *io = new FreeImageIO;
+
+ if (io) {
+ SetDefaultIO(io);
+
+ BOOL cont = TRUE;
+
+ FILE *handle = NULL;
+
+ if (!create_new) {
+ handle = fopen(filename, "rb");
+
+ if (handle == NULL) {
+ cont = FALSE;
+ }
+ }
+
+ if (cont) {
+ FIMULTIBITMAP *bitmap = new FIMULTIBITMAP;
+
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = new MULTIBITMAPHEADER;
+
+ header->m_filename = new char[strlen(filename) + 1];
+ strcpy(header->m_filename, filename);
+ header->node = node;
+ header->fif = fif;
+ header->io = io;
+ header->handle = handle;
+ header->changed = FALSE;
+ header->read_only = read_only;
+ header->m_cachefile = NULL;
+ header->cache_fif = fif;
+ header->load_flags = flags;
+
+ if (header) {
+ // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure
+
+ bitmap->data = header;
+
+ // cache the page count
+
+ header->page_count = FreeImage_InternalGetPageCount(bitmap);
+
+ // allocate a continueus block to describe the bitmap
+
+ if (!create_new)
+ header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1));
+
+ // set up the cache
+
+ if (!read_only) {
+ char cache_name[256];
+ ReplaceExtension(cache_name, filename, "ficache");
+
+ CacheFile *cache_file = new CacheFile(cache_name, keep_cache_in_memory);
+
+ if (cache_file->open()) {
+ header->m_cachefile = cache_file;
+
+ // return the multibitmap
+
+ return bitmap;
+ }
+
+ delete cache_file;
+ delete header;
+ }
+
+ return bitmap;
+ }
+
+ return NULL;
+ }
+ }
+ }
+
+ delete io;
+ }
+ }
+
+ return NULL;
+}
+
+FIMULTIBITMAP * DLL_CALLCONV
+FreeImage_OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) {
+
+ if (io && handle) {
+
+ // retrieve the plugin list to find the node belonging to this plugin
+ PluginList *list = FreeImage_GetPluginList();
+
+ if (list) {
+ PluginNode *node = list->FindNodeFromFIF(fif);
+
+ if (node) {
+ FIMULTIBITMAP *bitmap = new FIMULTIBITMAP;
+
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = new MULTIBITMAPHEADER;
+
+ if (header) {
+ header->io = new FreeImageIO;
+
+ if (header->io) {
+
+ header->m_filename = NULL;
+ header->node = node;
+ header->fif = fif;
+ *header->io = *io;
+ header->handle = handle;
+ header->changed = FALSE;
+ header->read_only = TRUE;
+ header->m_cachefile = NULL;
+ header->cache_fif = fif;
+ header->load_flags = flags;
+
+ // store the MULTIBITMAPHEADER in the surrounding FIMULTIBITMAP structure
+
+ bitmap->data = header;
+
+ // cache the page count
+
+ header->page_count = FreeImage_InternalGetPageCount(bitmap);
+
+ // allocate a continueus block to describe the bitmap
+
+ header->m_blocks.push_back((BlockTypeS *)new BlockContinueus(0, header->page_count - 1));
+
+ return bitmap;
+ }
+ delete header;
+ }
+ delete bitmap;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_CloseMultiBitmap(FIMULTIBITMAP *bitmap, int flags) {
+ if (bitmap) {
+ BOOL success = TRUE;
+
+ if (bitmap->data) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if (header->changed) {
+ // open a temp file
+
+ char spool_name[256];
+
+ ReplaceExtension(spool_name, header->m_filename, "fispool");
+
+ // open the spool file and the source file
+
+ FILE *f = fopen(spool_name, "w+b");
+
+ void *data = FreeImage_Open(header->node, header->io, (fi_handle)f, FALSE);
+ void *data_read = NULL;
+
+ if (header->handle) {
+ header->io->seek_proc(header->handle, 0, SEEK_SET);
+
+ data_read = FreeImage_Open(header->node, header->io, header->handle, TRUE);
+ }
+
+ // write all the pages to the temp file
+
+ int count = 0;
+
+ for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); i++) {
+ if (success) {
+ switch((*i)->m_type) {
+ case BLOCK_CONTINUEUS :
+ {
+ BlockContinueus *block = (BlockContinueus *)(*i);
+
+ for (int j = block->m_start; j <= block->m_end; j++) {
+ FIBITMAP *dib = header->node->m_plugin->load_proc(header->io, header->handle, j, header->load_flags, data_read);
+
+ success = header->node->m_plugin->save_proc(header->io, dib, (fi_handle)f, count, flags, data);
+ count++;
+
+ FreeImage_Unload(dib);
+ }
+
+ break;
+ }
+
+ case BLOCK_REFERENCE :
+ {
+ BlockReference *ref = (BlockReference *)(*i);
+
+ // read the compressed data
+
+ BYTE *compressed_data = (BYTE*)malloc(ref->m_size * sizeof(BYTE));
+
+ header->m_cachefile->readFile((BYTE *)compressed_data, ref->m_reference, ref->m_size);
+
+ // uncompress the data
+
+ FIMEMORY *hmem = FreeImage_OpenMemory(compressed_data, ref->m_size);
+ FIBITMAP *dib = FreeImage_LoadFromMemory(header->cache_fif, hmem, 0);
+ FreeImage_CloseMemory(hmem);
+
+ // get rid of the buffer
+ free(compressed_data);
+
+ // save the data
+
+ success = header->node->m_plugin->save_proc(header->io, dib, (fi_handle)f, count, flags, data);
+ count++;
+
+ // unload the dib
+
+ FreeImage_Unload(dib);
+
+ break;
+ }
+ }
+ } else {
+ break;
+ }
+ }
+
+ // close the files
+
+ FreeImage_Close(header->node, header->io, (fi_handle)f, data);
+
+ fclose(f);
+
+ if (header->handle) {
+ FreeImage_Close(header->node, header->io, header->handle, data_read);
+
+ fclose((FILE *)header->handle);
+ }
+
+ if (success) {
+ remove(header->m_filename);
+
+ rename(spool_name, header->m_filename);
+ } else {
+ remove(spool_name);
+ }
+ } else {
+ if (header->handle && header->m_filename) {
+ fclose((FILE *)header->handle);
+ }
+ }
+
+ // clear the blocks list
+
+ for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i)
+ delete *i;
+
+ // flush and dispose the cache
+
+ if (header->m_cachefile) {
+ header->m_cachefile->close();
+
+ delete header->m_cachefile;
+ }
+
+ // delete the last open bitmaps
+
+ while (!header->locked_pages.empty()) {
+ FreeImage_Unload(header->locked_pages.begin()->first);
+
+ header->locked_pages.erase(header->locked_pages.begin()->first);
+ }
+
+ // get rid of the IO structure
+
+ delete header->io;
+
+ // delete the filename
+
+ if(header->m_filename)
+ delete[] header->m_filename;
+
+ // delete the FIMULTIBITMAPHEADER
+
+ delete header;
+ }
+
+ delete bitmap;
+
+ return success;
+ }
+
+ return FALSE;
+}
+
+int DLL_CALLCONV
+FreeImage_GetPageCount(FIMULTIBITMAP *bitmap) {
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if (header->page_count == -1) {
+ header->page_count = 0;
+
+ for (BlockListIterator i = header->m_blocks.begin(); i != header->m_blocks.end(); ++i) {
+ switch((*i)->m_type) {
+ case BLOCK_CONTINUEUS :
+ header->page_count += ((BlockContinueus *)(*i))->m_end - ((BlockContinueus *)(*i))->m_start + 1;
+ break;
+
+ case BLOCK_REFERENCE :
+ header->page_count++;
+ break;
+ }
+ }
+ }
+
+ return header->page_count;
+ }
+
+ return 0;
+}
+
+void DLL_CALLCONV
+FreeImage_AppendPage(FIMULTIBITMAP *bitmap, FIBITMAP *data) {
+ if ((bitmap) && (data)) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if ((!header->read_only) && (header->locked_pages.empty())) {
+ DWORD compressed_size = 0;
+ BYTE *compressed_data = NULL;
+
+ // compress the bitmap data
+
+ // open a memory handle
+ FIMEMORY *hmem = FreeImage_OpenMemory();
+ // save the file to memory
+ FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0);
+ // get the buffer from the memory stream
+ FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size);
+
+ // write the compressed data to the cache
+
+ int ref = header->m_cachefile->writeFile(compressed_data, compressed_size);
+
+ BlockReference *block = new BlockReference(ref, compressed_size);
+
+ // get rid of the compressed data
+
+ FreeImage_CloseMemory(hmem);
+
+ // add the block
+
+ header->m_blocks.push_back((BlockTypeS *)block);
+ header->changed = TRUE;
+ header->page_count = -1;
+ }
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_InsertPage(FIMULTIBITMAP *bitmap, int page, FIBITMAP *data) {
+ if ((bitmap) && (data)) {
+ if (page < FreeImage_GetPageCount(bitmap)) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if ((!header->read_only) && (header->locked_pages.empty())) {
+ DWORD compressed_size = 0;
+ BYTE *compressed_data = NULL;
+
+ // compress the bitmap data
+
+ // open a memory handle
+ FIMEMORY *hmem = FreeImage_OpenMemory();
+ // save the file to memory
+ FreeImage_SaveToMemory(header->cache_fif, data, hmem, 0);
+ // get the buffer from the memory stream
+ FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size);
+
+ // write the compressed data to the cache
+
+ int ref = header->m_cachefile->writeFile(compressed_data, compressed_size);
+
+ // add a block
+
+ if (page > 0) {
+ BlockListIterator block_source = FreeImage_FindBlock(bitmap, page);
+
+ BlockReference *block = new BlockReference(ref, compressed_size);
+
+ header->m_blocks.insert(block_source, (BlockTypeS *)block);
+ } else {
+ BlockReference *block = new BlockReference(ref, compressed_size);
+
+ header->m_blocks.push_front((BlockTypeS *)block);
+ }
+
+ // get rid of the compressed buffer
+
+ FreeImage_CloseMemory(hmem);
+
+ header->changed = TRUE;
+ header->page_count = -1;
+ }
+ }
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_DeletePage(FIMULTIBITMAP *bitmap, int page) {
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if ((!header->read_only) && (header->locked_pages.empty())) {
+ if (FreeImage_GetPageCount(bitmap) > 1) {
+ BlockListIterator i = FreeImage_FindBlock(bitmap, page);
+
+ if (i != header->m_blocks.end()) {
+ switch((*i)->m_type) {
+ case BLOCK_CONTINUEUS :
+ header->m_blocks.erase(i);
+ break;
+
+ case BLOCK_REFERENCE :
+ header->m_cachefile->deleteFile(((BlockReference *)(*i))->m_reference);
+ header->m_blocks.erase(i);
+ break;
+ }
+
+ header->changed = TRUE;
+ header->page_count = -1;
+ }
+ }
+ }
+ }
+}
+
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_LockPage(FIMULTIBITMAP *bitmap, int page) {
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ // only lock if the page wasn't locked before...
+
+ for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) {
+ if (i->second == page) {
+ return NULL;
+ }
+ }
+
+ // open the bitmap
+
+ header->io->seek_proc(header->handle, 0, SEEK_SET);
+
+ void *data = FreeImage_Open(header->node, header->io, header->handle, TRUE);
+
+ // load the bitmap data
+
+ if (data != NULL) {
+ FIBITMAP *dib = (header->node->m_plugin->load_proc != NULL) ? header->node->m_plugin->load_proc(header->io, header->handle, page, header->load_flags, data) : NULL;
+
+ // close the file
+
+ FreeImage_Close(header->node, header->io, header->handle, data);
+
+ // if there was still another bitmap open, get rid of it
+
+ if (dib) {
+ header->locked_pages[dib] = page;
+
+ return dib;
+ }
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+void DLL_CALLCONV
+FreeImage_UnlockPage(FIMULTIBITMAP *bitmap, FIBITMAP *page, BOOL changed) {
+ if ((bitmap) && (page)) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ // find out if the page we try to unlock is actually locked...
+
+ if (header->locked_pages.find(page) != header->locked_pages.end()) {
+ // store the bitmap compressed in the cache for later writing
+
+ if (changed && !header->read_only) {
+ header->changed = TRUE;
+
+ // cut loose the block from the rest
+
+ BlockListIterator i = FreeImage_FindBlock(bitmap, header->locked_pages[page]);
+
+ // compress the data
+
+ DWORD compressed_size = 0;
+ BYTE *compressed_data = NULL;
+
+ // open a memory handle
+ FIMEMORY *hmem = FreeImage_OpenMemory();
+ // save the page to memory
+ FreeImage_SaveToMemory(header->cache_fif, page, hmem, 0);
+ // get the buffer from the memory stream
+ FreeImage_AcquireMemory(hmem, &compressed_data, &compressed_size);
+
+ // write the data to the cache
+
+ switch ((*i)->m_type) {
+ case BLOCK_CONTINUEUS :
+ {
+ int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);
+
+ delete (*i);
+
+ *i = (BlockTypeS *)new BlockReference(iPage, compressed_size);
+
+ break;
+ }
+
+ case BLOCK_REFERENCE :
+ {
+ BlockReference *reference = (BlockReference *)(*i);
+
+ header->m_cachefile->deleteFile(reference->m_reference);
+
+ delete (*i);
+
+ int iPage = header->m_cachefile->writeFile(compressed_data, compressed_size);
+
+ *i = (BlockTypeS *)new BlockReference(iPage, compressed_size);
+
+ break;
+ }
+ }
+
+ // get rid of the compressed data
+
+ FreeImage_CloseMemory(hmem);
+ }
+
+ // reset the locked page so that another page can be locked
+
+ FreeImage_Unload(page);
+
+ header->locked_pages.erase(page);
+ }
+ }
+}
+
+BOOL DLL_CALLCONV
+FreeImage_MovePage(FIMULTIBITMAP *bitmap, int target, int source) {
+ if (bitmap) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if ((!header->read_only) && (header->locked_pages.empty())) {
+ if ((target != source) && ((target >= 0) && (target < FreeImage_GetPageCount(bitmap))) && ((source >= 0) && (source < FreeImage_GetPageCount(bitmap)))) {
+ BlockListIterator block_source = FreeImage_FindBlock(bitmap, target);
+ BlockListIterator block_target = FreeImage_FindBlock(bitmap, source);
+
+ header->m_blocks.insert(block_target, *block_source);
+ header->m_blocks.erase(block_source);
+
+ header->changed = TRUE;
+
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_GetLockedPageNumbers(FIMULTIBITMAP *bitmap, int *pages, int *count) {
+ if ((bitmap) && (count)) {
+ MULTIBITMAPHEADER *header = FreeImage_GetMultiBitmapHeader(bitmap);
+
+ if ((pages == NULL) || (*count == 0)) {
+ *count = (int)header->locked_pages.size();
+ } else {
+ int c = 0;
+
+ for (std::map<FIBITMAP *, int>::iterator i = header->locked_pages.begin(); i != header->locked_pages.end(); ++i) {
+ pages[c] = i->second;
+
+ c++;
+
+ if (c == *count)
+ break;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/Source/FreeImage/NNQuantizer.cpp b/Source/FreeImage/NNQuantizer.cpp
new file mode 100644
index 0000000..f907c41
--- /dev/null
+++ b/Source/FreeImage/NNQuantizer.cpp
@@ -0,0 +1,507 @@
+// NeuQuant Neural-Net Quantization Algorithm
+// ------------------------------------------
+//
+// Copyright (c) 1994 Anthony Dekker
+//
+// NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
+// See "Kohonen neural networks for optimal colour quantization"
+// in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
+// for a discussion of the algorithm.
+//
+// Any party obtaining a copy of these files from the author, directly or
+// indirectly, is granted, free of charge, a full and unrestricted irrevocable,
+// world-wide, paid up, royalty-free, nonexclusive right and license to deal
+// in this software and documentation files (the "Software"), including without
+// limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons who receive
+// copies from any such party to do so, with the only requirement being
+// that this copyright notice remain intact.
+
+///////////////////////////////////////////////////////////////////////
+// History
+// -------
+// January 2001: Adaptation of the Neural-Net Quantization Algorithm
+// for the FreeImage 2 library
+// Author: Hervé Drolon (drolon@infonie.fr)
+// March 2004: Adaptation for the FreeImage 3 library (port to big endian processors)
+// Author: Hervé Drolon (drolon@infonie.fr)
+// April 2004: Algorithm rewritten as a C++ class.
+// Fixed a bug in the algorithm with handling of 4-byte boundary alignment.
+// Author: Hervé Drolon (drolon@infonie.fr)
+///////////////////////////////////////////////////////////////////////
+
+#include "Quantizers.h"
+#include "FreeImage.h"
+#include "Utilities.h"
+
+
+// Four primes near 500 - assume no image has a length so large
+// that it is divisible by all four primes
+// ==========================================================
+
+#define prime1 499
+#define prime2 491
+#define prime3 487
+#define prime4 503
+
+// ----------------------------------------------------------------
+
+NNQuantizer::NNQuantizer(int PaletteSize)
+{
+ netsize = PaletteSize;
+ maxnetpos = netsize - 1;
+ initrad = netsize < 8 ? 1 : (netsize >> 3);
+ initradius = (initrad * radiusbias);
+
+ network = NULL;
+
+ network = (pixel *)malloc(netsize * sizeof(pixel));
+ bias = (int *)malloc(netsize * sizeof(int));
+ freq = (int *)malloc(netsize * sizeof(int));
+ radpower = (int *)malloc(initrad * sizeof(int));
+
+ if( !network || !bias || !freq || !radpower ) {
+ if(network) free(network);
+ if(bias) free(bias);
+ if(freq) free(freq);
+ if(radpower) free(radpower);
+ throw FI_MSG_ERROR_MEMORY;
+ }
+}
+
+NNQuantizer::~NNQuantizer()
+{
+ if(network) free(network);
+ if(bias) free(bias);
+ if(freq) free(freq);
+ if(radpower) free(radpower);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Initialise network in range (0,0,0) to (255,255,255) and set parameters
+// -----------------------------------------------------------------------
+
+void NNQuantizer::initnet() {
+ int i, *p;
+
+ for (i = 0; i < netsize; i++) {
+ p = network[i];
+ p[FI_RGBA_BLUE] = p[FI_RGBA_GREEN] = p[FI_RGBA_RED] = (i << (netbiasshift+8))/netsize;
+ freq[i] = intbias/netsize; /* 1/netsize */
+ bias[i] = 0;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+// Unbias network to give byte values 0..255 and record position i to prepare for sort
+// ------------------------------------------------------------------------------------
+
+void NNQuantizer::unbiasnet() {
+ int i, j, temp;
+
+ for (i = 0; i < netsize; i++) {
+ for (j = 0; j < 3; j++) {
+ // OLD CODE: network[i][j] >>= netbiasshift;
+ // Fix based on bug report by Juergen Weigert jw@suse.de
+ temp = (network[i][j] + (1 << (netbiasshift - 1))) >> netbiasshift;
+ if (temp > 255) temp = 255;
+ network[i][j] = temp;
+ }
+ network[i][3] = i; // record colour no
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+// Insertion sort of network and building of netindex[0..255] (to do after unbias)
+// -------------------------------------------------------------------------------
+
+void NNQuantizer::inxbuild() {
+ int i,j,smallpos,smallval;
+ int *p,*q;
+ int previouscol,startpos;
+
+ previouscol = 0;
+ startpos = 0;
+ for (i = 0; i < netsize; i++) {
+ p = network[i];
+ smallpos = i;
+ smallval = p[FI_RGBA_GREEN]; // index on g
+ // find smallest in i..netsize-1
+ for (j = i+1; j < netsize; j++) {
+ q = network[j];
+ if (q[FI_RGBA_GREEN] < smallval) { // index on g
+ smallpos = j;
+ smallval = q[FI_RGBA_GREEN]; // index on g
+ }
+ }
+ q = network[smallpos];
+ // swap p (i) and q (smallpos) entries
+ if (i != smallpos) {
+ j = q[FI_RGBA_BLUE]; q[FI_RGBA_BLUE] = p[FI_RGBA_BLUE]; p[FI_RGBA_BLUE] = j;
+ j = q[FI_RGBA_GREEN]; q[FI_RGBA_GREEN] = p[FI_RGBA_GREEN]; p[FI_RGBA_GREEN] = j;
+ j = q[FI_RGBA_RED]; q[FI_RGBA_RED] = p[FI_RGBA_RED]; p[FI_RGBA_RED] = j;
+ j = q[3]; q[3] = p[3]; p[3] = j;
+ }
+ // smallval entry is now in position i
+ if (smallval != previouscol) {
+ netindex[previouscol] = (startpos+i)>>1;
+ for (j = previouscol+1; j < smallval; j++)
+ netindex[j] = i;
+ previouscol = smallval;
+ startpos = i;
+ }
+ }
+ netindex[previouscol] = (startpos+maxnetpos)>>1;
+ for (j = previouscol+1; j < 256; j++)
+ netindex[j] = maxnetpos; // really 256
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Search for BGR values 0..255 (after net is unbiased) and return colour index
+// ----------------------------------------------------------------------------
+
+int NNQuantizer::inxsearch(int b, int g, int r) {
+ int i, j, dist, a, bestd;
+ int *p;
+ int best;
+
+ bestd = 1000; // biggest possible dist is 256*3
+ best = -1;
+ i = netindex[g]; // index on g
+ j = i-1; // start at netindex[g] and work outwards
+
+ while ((i < netsize) || (j >= 0)) {
+ if (i < netsize) {
+ p = network[i];
+ dist = p[FI_RGBA_GREEN] - g; // inx key
+ if (dist >= bestd)
+ i = netsize; // stop iter
+ else {
+ i++;
+ if (dist < 0)
+ dist = -dist;
+ a = p[FI_RGBA_BLUE] - b;
+ if (a < 0)
+ a = -a;
+ dist += a;
+ if (dist < bestd) {
+ a = p[FI_RGBA_RED] - r;
+ if (a<0)
+ a = -a;
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ best = p[3];
+ }
+ }
+ }
+ }
+ if (j >= 0) {
+ p = network[j];
+ dist = g - p[FI_RGBA_GREEN]; // inx key - reverse dif
+ if (dist >= bestd)
+ j = -1; // stop iter
+ else {
+ j--;
+ if (dist < 0)
+ dist = -dist;
+ a = p[FI_RGBA_BLUE] - b;
+ if (a<0)
+ a = -a;
+ dist += a;
+ if (dist < bestd) {
+ a = p[FI_RGBA_RED] - r;
+ if (a<0)
+ a = -a;
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ best = p[3];
+ }
+ }
+ }
+ }
+ }
+ return best;
+}
+
+///////////////////////////////
+// Search for biased BGR values
+// ----------------------------
+
+int NNQuantizer::contest(int b, int g, int r) {
+ // finds closest neuron (min dist) and updates freq
+ // finds best neuron (min dist-bias) and returns position
+ // for frequently chosen neurons, freq[i] is high and bias[i] is negative
+ // bias[i] = gamma*((1/netsize)-freq[i])
+
+ int i,dist,a,biasdist,betafreq;
+ int bestpos,bestbiaspos,bestd,bestbiasd;
+ int *p,*f, *n;
+
+ bestd = ~(((int) 1)<<31);
+ bestbiasd = bestd;
+ bestpos = -1;
+ bestbiaspos = bestpos;
+ p = bias;
+ f = freq;
+
+ for (i = 0; i < netsize; i++) {
+ n = network[i];
+ dist = n[FI_RGBA_BLUE] - b;
+ if (dist < 0)
+ dist = -dist;
+ a = n[FI_RGBA_GREEN] - g;
+ if (a < 0)
+ a = -a;
+ dist += a;
+ a = n[FI_RGBA_RED] - r;
+ if (a < 0)
+ a = -a;
+ dist += a;
+ if (dist < bestd) {
+ bestd = dist;
+ bestpos = i;
+ }
+ biasdist = dist - ((*p)>>(intbiasshift-netbiasshift));
+ if (biasdist < bestbiasd) {
+ bestbiasd = biasdist;
+ bestbiaspos = i;
+ }
+ betafreq = (*f >> betashift);
+ *f++ -= betafreq;
+ *p++ += (betafreq << gammashift);
+ }
+ freq[bestpos] += beta;
+ bias[bestpos] -= betagamma;
+ return bestbiaspos;
+}
+
+///////////////////////////////////////////////////////
+// Move neuron i towards biased (b,g,r) by factor alpha
+// ----------------------------------------------------
+
+void NNQuantizer::altersingle(int alpha, int i, int b, int g, int r) {
+ int *n;
+
+ n = network[i]; // alter hit neuron
+ n[FI_RGBA_BLUE] -= (alpha * (n[FI_RGBA_BLUE] - b)) / initalpha;
+ n[FI_RGBA_GREEN] -= (alpha * (n[FI_RGBA_GREEN] - g)) / initalpha;
+ n[FI_RGBA_RED] -= (alpha * (n[FI_RGBA_RED] - r)) / initalpha;
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]
+// ---------------------------------------------------------------------------------
+
+void NNQuantizer::alterneigh(int rad, int i, int b, int g, int r) {
+ int j, k, lo, hi, a;
+ int *p, *q;
+
+ lo = i - rad; if (lo < -1) lo = -1;
+ hi = i + rad; if (hi > netsize) hi = netsize;
+
+ j = i+1;
+ k = i-1;
+ q = radpower;
+ while ((j < hi) || (k > lo)) {
+ a = (*(++q));
+ if (j < hi) {
+ p = network[j];
+ p[FI_RGBA_BLUE] -= (a * (p[FI_RGBA_BLUE] - b)) / alpharadbias;
+ p[FI_RGBA_GREEN] -= (a * (p[FI_RGBA_GREEN] - g)) / alpharadbias;
+ p[FI_RGBA_RED] -= (a * (p[FI_RGBA_RED] - r)) / alpharadbias;
+ j++;
+ }
+ if (k > lo) {
+ p = network[k];
+ p[FI_RGBA_BLUE] -= (a * (p[FI_RGBA_BLUE] - b)) / alpharadbias;
+ p[FI_RGBA_GREEN] -= (a * (p[FI_RGBA_GREEN] - g)) / alpharadbias;
+ p[FI_RGBA_RED] -= (a * (p[FI_RGBA_RED] - r)) / alpharadbias;
+ k--;
+ }
+ }
+}
+
+/////////////////////
+// Main Learning Loop
+// ------------------
+
+/**
+ Get a pixel sample at position pos. Handle 4-byte boundary alignment.
+ @param pos pixel position in a WxHx3 pixel buffer
+ @param b blue pixel component
+ @param g green pixel component
+ @param r red pixel component
+*/
+void NNQuantizer::getSample(long pos, int *b, int *g, int *r) {
+ // get equivalent pixel coordinates
+ // - assume it's a 24-bit image -
+ int x = pos % img_line;
+ int y = pos / img_line;
+
+ BYTE *bits = FreeImage_GetScanLine(dib_ptr, y) + x;
+
+ *b = bits[FI_RGBA_BLUE] << netbiasshift;
+ *g = bits[FI_RGBA_GREEN] << netbiasshift;
+ *r = bits[FI_RGBA_RED] << netbiasshift;
+}
+
+void NNQuantizer::learn(int sampling_factor) {
+ int i, j, b, g, r;
+ int radius, rad, alpha, step, delta, samplepixels;
+ int alphadec; // biased by 10 bits
+ long pos, lengthcount;
+
+ // image size as viewed by the scan algorithm
+ lengthcount = img_width * img_height * 3;
+
+ // number of samples used for the learning phase
+ samplepixels = lengthcount / (3 * sampling_factor);
+
+ // decrease learning rate after delta pixel presentations
+ delta = samplepixels / ncycles;
+ if(delta == 0) {
+ // avoid a 'divide by zero' error with very small images
+ delta = 1;
+ }
+
+ // initialize learning parameters
+ alphadec = 30 + ((sampling_factor - 1) / 3);
+ alpha = initalpha;
+ radius = initradius;
+
+ rad = radius >> radiusbiasshift;
+ if (rad <= 1) rad = 0;
+ for (i = 0; i < rad; i++)
+ radpower[i] = alpha*(((rad*rad - i*i)*radbias)/(rad*rad));
+
+ // initialize pseudo-random scan
+ if ((lengthcount % prime1) != 0)
+ step = 3*prime1;
+ else {
+ if ((lengthcount % prime2) != 0)
+ step = 3*prime2;
+ else {
+ if ((lengthcount % prime3) != 0)
+ step = 3*prime3;
+ else
+ step = 3*prime4;
+ }
+ }
+
+ i = 0; // iteration
+ pos = 0; // pixel position
+
+ while (i < samplepixels) {
+ // get next learning sample
+ getSample(pos, &b, &g, &r);
+
+ // find winning neuron
+ j = contest(b, g, r);
+
+ // alter winner
+ altersingle(alpha, j, b, g, r);
+
+ // alter neighbours
+ if (rad) alterneigh(rad, j, b, g, r);
+
+ // next sample
+ pos += step;
+ while (pos >= lengthcount) pos -= lengthcount;
+
+ i++;
+ if (i % delta == 0) {
+ // decrease learning rate and also the neighborhood
+ alpha -= alpha / alphadec;
+ radius -= radius / radiusdec;
+ rad = radius >> radiusbiasshift;
+ if (rad <= 1) rad = 0;
+ for (j = 0; j < rad; j++)
+ radpower[j] = alpha * (((rad*rad - j*j) * radbias) / (rad*rad));
+ }
+ }
+
+}
+
+//////////////
+// Quantizer
+// -----------
+
+FIBITMAP* NNQuantizer::Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette, int sampling) {
+
+ if ((!dib) || (FreeImage_GetBPP(dib) != 24)) {
+ return NULL;
+ }
+
+ // 1) Select a sampling factor in range 1..30 (input parameter 'sampling')
+ // 1 => slower, 30 => faster. Default value is 1
+
+
+ // 2) Get DIB parameters
+
+ dib_ptr = dib;
+
+ img_width = FreeImage_GetWidth(dib); // DIB width
+ img_height = FreeImage_GetHeight(dib); // DIB height
+ img_line = FreeImage_GetLine(dib); // DIB line length in bytes (should be equal to 3 x W)
+
+ // For small images, adjust the sampling factor to avoid a 'divide by zero' error later
+ // (see delta in learn() routine)
+ int adjust = (img_width * img_height) / ncycles;
+ if(sampling >= adjust)
+ sampling = 1;
+
+
+ // 3) Initialize the network and apply the learning algorithm
+
+ if( netsize > ReserveSize ) {
+ netsize -= ReserveSize;
+ initnet();
+ learn(sampling);
+ unbiasnet();
+ netsize += ReserveSize;
+ }
+
+ // 3.5) Overwrite the last few palette entries with the reserved ones
+ for (int i = 0; i < ReserveSize; i++) {
+ network[netsize - ReserveSize + i][FI_RGBA_BLUE] = ReservePalette[i].rgbBlue;
+ network[netsize - ReserveSize + i][FI_RGBA_GREEN] = ReservePalette[i].rgbGreen;
+ network[netsize - ReserveSize + i][FI_RGBA_RED] = ReservePalette[i].rgbRed;
+ network[netsize - ReserveSize + i][3] = netsize - ReserveSize + i;
+ }
+
+ // 4) Allocate a new 8-bit DIB
+
+ FIBITMAP *new_dib = FreeImage_Allocate(img_width, img_height, 8);
+
+ if (new_dib == NULL)
+ return NULL;
+
+ // 5) Write the quantized palette
+
+ RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
+
+ for (int j = 0; j < netsize; j++) {
+ new_pal[j].rgbBlue = (BYTE)network[j][FI_RGBA_BLUE];
+ new_pal[j].rgbGreen = (BYTE)network[j][FI_RGBA_GREEN];
+ new_pal[j].rgbRed = (BYTE)network[j][FI_RGBA_RED];
+ }
+
+ inxbuild();
+
+ // 6) Write output image using inxsearch(b,g,r)
+
+ for (WORD rows = 0; rows < img_height; rows++) {
+ BYTE *new_bits = FreeImage_GetScanLine(new_dib, rows);
+ BYTE *bits = FreeImage_GetScanLine(dib_ptr, rows);
+
+ for (WORD cols = 0; cols < img_width; cols++) {
+ new_bits[cols] = (BYTE)inxsearch(bits[FI_RGBA_BLUE], bits[FI_RGBA_GREEN], bits[FI_RGBA_RED]);
+
+ bits += 3;
+ }
+ }
+
+ return (FIBITMAP*) new_dib;
+}
diff --git a/Source/FreeImage/PSDParser.cpp b/Source/FreeImage/PSDParser.cpp
new file mode 100644
index 0000000..8bcc123
--- /dev/null
+++ b/Source/FreeImage/PSDParser.cpp
@@ -0,0 +1,1526 @@
+// ==========================================================
+// Photoshop Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "PSDParser.h"
+
+// PSD signature (= '8BPS')
+#define PSD_SIGNATURE 0x38425053
+// Image resource block signature (= '8BIM')
+#define PSD_RESOURCE 0x3842494D
+
+// PSD color modes
+#define PSD_BITMAP 0
+#define PSD_GRAYSCALE 1
+#define PSD_INDEXED 2
+#define PSD_RGB 3
+#define PSD_CMYK 4
+#define PSD_MULTICHANNEL 7
+#define PSD_DUOTONE 8
+#define PSD_LAB 9
+
+// PSD compression schemes
+#define PSD_COMPRESSION_NONE 0 // Raw data
+#define PSD_COMPRESSION_RLE 1 // RLE compression (same as TIFF packed bits)
+
+#define SAFE_DELETE_ARRAY(_p_) { if (NULL != (_p_)) { delete [] (_p_); (_p_) = NULL; } }
+
+// --------------------------------------------------------------------------
+
+static inline int
+psdGetValue(const BYTE * iprBuffer, const int iBytes) {
+ int v = iprBuffer[0];
+ for (int i=1; i<iBytes; ++i) {
+ v = (v << 8) | iprBuffer[i];
+ }
+ return v;
+}
+
+// --------------------------------------------------------------------------
+
+psdHeaderInfo::psdHeaderInfo() : _Channels(-1), _Height(-1), _Width(-1), _BitsPerPixel(-1), _ColourMode(-1) {
+}
+
+psdHeaderInfo::~psdHeaderInfo() {
+}
+
+bool psdHeaderInfo::Read(FreeImageIO *io, fi_handle handle) {
+ bool bSuccess = false;
+ psdHeader header;
+
+ const int n = (int)io->read_proc(&header, sizeof(header), 1, handle);
+ if(!n) {
+ return false;
+ }
+
+ // check the signature
+ int nSignature = psdGetValue(header.Signature, sizeof(header.Signature));
+ if (PSD_SIGNATURE == nSignature) {
+ // check the version
+ int nVersion = psdGetValue( header.Version, sizeof(header.Version) );
+ if (1 == nVersion) {
+ // header.Reserved must be zero
+ unsigned i = 0;
+ bool bOK = true;
+ while ( (i < 6) && bOK ) {
+ if ( '\0' != header.Reserved[i] ) {
+ bOK = false;
+ break;
+ }
+ i++;
+ }
+ bSuccess = bOK;
+ if (bSuccess) {
+ // read the header
+ _Channels = (short)psdGetValue( header.Channels, sizeof(header.Channels) );
+ _Height = psdGetValue( header.Rows, sizeof(header.Rows) );
+ _Width = psdGetValue( header.Columns, sizeof(header.Columns) );
+ _BitsPerPixel = (short)psdGetValue( header.Depth, sizeof(header.Depth) );
+ _ColourMode = (short)psdGetValue( header.Mode, sizeof(header.Mode) );
+ }
+ }
+ }
+
+ return bSuccess;
+}
+
+// --------------------------------------------------------------------------
+
+psdColourModeData::psdColourModeData() : _Length(-1), _plColourData(NULL) {
+}
+
+psdColourModeData::~psdColourModeData() {
+ SAFE_DELETE_ARRAY(_plColourData);
+}
+
+bool psdColourModeData::Read(FreeImageIO *io, fi_handle handle) {
+ if (0 < _Length) {
+ SAFE_DELETE_ARRAY(_plColourData);
+ }
+
+ BYTE Length[4];
+ io->read_proc(&Length, sizeof(Length), 1, handle);
+
+ _Length = psdGetValue( Length, sizeof(_Length) );
+ if (0 < _Length) {
+ _plColourData = new BYTE[_Length];
+ io->read_proc(_plColourData, _Length, 1, handle);
+ }
+
+ return true;
+}
+
+bool psdColourModeData::FillPalette(FIBITMAP *dib) {
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if(pal) {
+ for (int i = 0; i < 256; i++) {
+ pal[i].rgbRed = _plColourData[i + 0*256];
+ pal[i].rgbGreen = _plColourData[i + 1*256];
+ pal[i].rgbBlue = _plColourData[i + 2*256];
+ }
+ return true;
+ }
+ return false;
+}
+
+// --------------------------------------------------------------------------
+
+psdImageResource::psdImageResource() : _plName (0) {
+ Reset();
+}
+
+psdImageResource::~psdImageResource() {
+ SAFE_DELETE_ARRAY(_plName);
+}
+
+void psdImageResource::Reset() {
+ _Length = -1;
+ memset( _OSType, '\0', sizeof(_OSType) );
+ _ID = -1;
+ SAFE_DELETE_ARRAY(_plName);
+ _Size = -1;
+}
+
+// --------------------------------------------------------------------------
+
+psdResolutionInfo::psdResolutionInfo() : _widthUnit(-1), _heightUnit(-1), _hRes(-1), _vRes(-1), _hResUnit(-1), _vResUnit(-1) {
+}
+
+psdResolutionInfo::~psdResolutionInfo() {
+}
+
+int psdResolutionInfo::Read(FreeImageIO *io, fi_handle handle) {
+ BYTE IntValue[4], ShortValue[2];
+ int nBytes=0, n;
+
+ // Horizontal resolution in pixels per inch.
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _hRes = (short)psdGetValue(ShortValue, sizeof(_hRes) );
+ // 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm.
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _hResUnit = psdGetValue(IntValue, sizeof(_hResUnit) );
+ // Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _widthUnit = (short)psdGetValue(ShortValue, sizeof(_widthUnit) );
+ // Vertical resolution in pixels per inch.
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _vRes = (short)psdGetValue(ShortValue, sizeof(_vRes) );
+ // 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm.
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _vResUnit = psdGetValue(IntValue, sizeof(_vResUnit) );
+ // Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _heightUnit = (short)psdGetValue(ShortValue, sizeof(_heightUnit) );
+
+ return nBytes;
+}
+
+void psdResolutionInfo::GetResolutionInfo(unsigned &res_x, unsigned &res_y) {
+ if(_hResUnit == 1) {
+ // convert pixels / inch to pixel / m
+ res_x = (unsigned) (_hRes / 0.0254000 + 0.5);
+ } else if(_hResUnit == 2) {
+ // convert pixels / cm to pixel / m
+ res_x = (unsigned) (_hRes * 100.0 + 0.5);
+ }
+ if(_vResUnit == 1) {
+ // convert pixels / inch to pixel / m
+ res_y = (unsigned) (_vRes / 0.0254000 + 0.5);
+ } else if(_vResUnit == 2) {
+ // convert pixels / cm to pixel / m
+ res_y = (unsigned) (_vRes * 100.0 + 0.5);
+ }
+}
+
+// --------------------------------------------------------------------------
+
+psdResolutionInfo_v2::psdResolutionInfo_v2() {
+ _Channels = _Rows = _Columns = _Depth = _Mode = -1;
+}
+
+psdResolutionInfo_v2::~psdResolutionInfo_v2() {
+}
+
+int psdResolutionInfo_v2::Read(FreeImageIO *io, fi_handle handle) {
+ BYTE ShortValue[2];
+ int nBytes=0, n;
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Channels = (short)psdGetValue(ShortValue, sizeof(_Channels) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Rows = (short)psdGetValue(ShortValue, sizeof(_Rows) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Columns = (short)psdGetValue(ShortValue, sizeof(_Columns) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Depth = (short)psdGetValue(ShortValue, sizeof(_Depth) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Mode = (short)psdGetValue(ShortValue, sizeof(_Mode) );
+
+ return nBytes;
+}
+
+// --------------------------------------------------------------------------
+
+psdDisplayInfo::psdDisplayInfo() {
+ _Opacity = _ColourSpace = -1;
+ for (unsigned n = 0; n < 4; ++n) {
+ _Colour[n] = 0;
+ }
+ _Kind = 0;
+ _padding = '0';
+}
+
+psdDisplayInfo::~psdDisplayInfo() {
+}
+
+int psdDisplayInfo::Read(FreeImageIO *io, fi_handle handle) {
+ BYTE ShortValue[2];
+ int nBytes=0, n;
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _ColourSpace = (short)psdGetValue(ShortValue, sizeof(_ColourSpace) );
+
+ for (unsigned i = 0; i < 4; ++i) {
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Colour[i] = (short)psdGetValue(ShortValue, sizeof(_Colour[i]) );
+ }
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Opacity = (short)psdGetValue(ShortValue, sizeof(_Opacity) );
+ assert( 0 <= _Opacity );
+ assert( 100 >= _Opacity );
+
+ BYTE c[1];
+ n = (int)io->read_proc(&c, sizeof(c), 1, handle);
+ nBytes += n * sizeof(c);
+ _Kind = (BYTE)psdGetValue(c, sizeof(c));
+
+ n = (int)io->read_proc(&c, sizeof(c), 1, handle);
+ nBytes += n * sizeof(c);
+ _padding = (BYTE)psdGetValue(c, sizeof(c));
+ assert( 0 == _padding );
+
+ return nBytes;
+}
+
+// --------------------------------------------------------------------------
+
+psdThumbnail::psdThumbnail() :
+_Format(-1), _Width(-1), _Height(-1), _WidthBytes(-1), _Size(-1), _CompressedSize(-1), _BitPerPixel(-1), _Planes(-1), _plData(NULL) {
+}
+
+psdThumbnail::~psdThumbnail() {
+ SAFE_DELETE_ARRAY(_plData);
+}
+
+int psdThumbnail::Read(FreeImageIO *io, fi_handle handle, int iTotalData, bool isBGR) {
+ BYTE c[1], ShortValue[2], IntValue[4];
+ int nBytes=0, n;
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _Format = psdGetValue(IntValue, sizeof(_Format) );
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _Width = psdGetValue(IntValue, sizeof(_Width) );
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _Height = psdGetValue(IntValue, sizeof(_Height) );
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _WidthBytes = psdGetValue(IntValue, sizeof(_WidthBytes) );
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _Size = psdGetValue(IntValue, sizeof(_Size) );
+
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _CompressedSize = psdGetValue(IntValue, sizeof(_CompressedSize) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _BitPerPixel = (short)psdGetValue(ShortValue, sizeof(_BitPerPixel) );
+
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _Planes = (short)psdGetValue(ShortValue, sizeof(_Planes) );
+
+ _plData = new BYTE[iTotalData];
+
+ if (isBGR) {
+ // In BGR format
+ for (int i=0; i<iTotalData; i+=3 ) {
+ n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle);
+ nBytes += n * sizeof(BYTE);
+ _plData[i+2] = (BYTE)psdGetValue(c, sizeof(BYTE) );
+
+ n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle);
+ nBytes += n * sizeof(BYTE);
+ _plData[i+1] = (BYTE)psdGetValue(c, sizeof(BYTE) );
+
+ n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle);
+ nBytes += n * sizeof(BYTE);
+ _plData[i+0] = (BYTE)psdGetValue(c, sizeof(BYTE) );
+ }
+ } else {
+ // In RGB format
+ for (int i=0; i<iTotalData; ++i) {
+ n = (int)io->read_proc(&c, sizeof(BYTE), 1, handle);
+ nBytes += n * sizeof(BYTE);
+ _plData[i] = (BYTE)psdGetValue(c, sizeof(BYTE) );
+ }
+ }
+
+ return nBytes;
+}
+
+//---------------------------------------------------------------------------
+
+psdICCProfile::psdICCProfile() : _ProfileSize(0), _ProfileData(NULL) {
+}
+
+psdICCProfile::~psdICCProfile() {
+ SAFE_DELETE_ARRAY(_ProfileData);
+}
+
+int psdICCProfile::Read(FreeImageIO *io, fi_handle handle, int size) {
+ int nBytes = 0, n;
+
+ SAFE_DELETE_ARRAY(_ProfileData);
+ _ProfileData = new BYTE[size];
+ if(NULL != _ProfileData) {
+ n = (int)io->read_proc(_ProfileData, 1, size, handle);
+ _ProfileSize = size;
+ nBytes += n * sizeof(BYTE);
+ }
+
+ return nBytes;
+}
+
+//---------------------------------------------------------------------------
+
+static inline int d2i(double value) {
+ return (int)floor(value + 0.5);
+}
+
+/**
+CMYK to RGB 8-bit conversion
+*/
+static void CMYKToRGB8(float iC, float iM, float iY, float iK, RGBTRIPLE *rgb) {
+ int r = d2i( ( 1.f - (iC *(1.f - iK) + iK ) ) * 255.f );
+ int g = d2i( ( 1.f - (iM *(1.f - iK) + iK ) ) * 255.f );
+ int b = d2i( ( 1.f - (iY *(1.f - iK) + iK ) ) * 255.f );
+
+ if (r < 0) r = 0; else if (r > 255) r = 255;
+ if (g < 0) g = 0; else if (g > 255) g = 255;
+ if (b < 0) b = 0; else if (b > 255) b = 255;
+
+ rgb->rgbtRed = (BYTE)r;
+ rgb->rgbtGreen = (BYTE)g;
+ rgb->rgbtBlue = (BYTE)b;
+}
+
+/**
+CMYK to RGB 16-bit conversion
+*/
+static void CMYKToRGB16(float iC, float iM, float iY, float iK, FIRGB16 *rgb) {
+ int r = d2i( ( 1.f - (iC *(1.f - iK) + iK ) ) * 65535.f );
+ int g = d2i( ( 1.f - (iM *(1.f - iK) + iK ) ) * 65535.f );
+ int b = d2i( ( 1.f - (iY *(1.f - iK) + iK ) ) * 65535.f );
+
+ if (r < 0) r = 0; else if (r > 65535) r = 65535;
+ if (g < 0) g = 0; else if (g > 65535) g = 65535;
+ if (b < 0) b = 0; else if (b > 65535) b = 65535;
+
+ rgb->red = (WORD)r;
+ rgb->green = (WORD)g;
+ rgb->blue = (WORD)b;
+}
+
+#define PSD_CLAMP(v, min, max) ((v < min) ? min : (v > max) ? max : v)
+
+/**
+CIELab -> XYZ conversion from http://www.easyrgb.com/
+*/
+static void CIELabToXYZ(float L, float a, float b, float *X, float *Y, float *Z) {
+ float pow_3;
+
+ // CIELab -> XYZ conversion
+ // ------------------------
+ float var_Y = (L + 16.F ) / 116.F;
+ float var_X = a / 500.F + var_Y;
+ float var_Z = var_Y - b / 200.F;
+
+ pow_3 = powf(var_Y, 3);
+ if(pow_3 > 0.008856F) {
+ var_Y = pow_3;
+ } else {
+ var_Y = ( var_Y - 16.F / 116.F ) / 7.787F;
+ }
+ pow_3 = powf(var_X, 3);
+ if(pow_3 > 0.008856F) {
+ var_X = pow_3;
+ } else {
+ var_X = ( var_X - 16.F / 116.F ) / 7.787F;
+ }
+ pow_3 = powf(var_Z, 3);
+ if(pow_3 > 0.008856F) {
+ var_Z = pow_3;
+ } else {
+ var_Z = ( var_Z - 16.F / 116.F ) / 7.787F;
+ }
+
+ static const float ref_X = 95.047F;
+ static const float ref_Y = 100.000F;
+ static const float ref_Z = 108.883F;
+
+ *X = ref_X * var_X; // ref_X = 95.047 (Observer= 2°, Illuminant= D65)
+ *Y = ref_Y * var_Y; // ref_Y = 100.000
+ *Z = ref_Z * var_Z; // ref_Z = 108.883
+}
+
+/**
+XYZ -> RGB conversion from http://www.easyrgb.com/
+*/
+static void XYZToRGB(float X, float Y, float Z, float *R, float *G, float *B) {
+ float var_X = X / 100; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
+ float var_Y = Y / 100; //Y from 0 to 100.000
+ float var_Z = Z / 100; //Z from 0 to 108.883
+
+ float var_R = var_X * 3.2406F + var_Y * -1.5372F + var_Z * -0.4986F;
+ float var_G = var_X * -0.9689F + var_Y * 1.8758F + var_Z * 0.0415F;
+ float var_B = var_X * 0.0557F + var_Y * -0.2040F + var_Z * 1.0570F;
+
+ float exponent = 1.F / 2.4F;
+
+ if(var_R > 0.0031308F) {
+ var_R = 1.055F * powf(var_R, exponent) - 0.055F;
+ } else {
+ var_R = 12.92F * var_R;
+ }
+ if(var_G > 0.0031308F) {
+ var_G = 1.055F * powf(var_G, exponent) - 0.055F;
+ } else {
+ var_G = 12.92F * var_G;
+ }
+ if(var_B > 0.0031308F) {
+ var_B = 1.055F * powf(var_B, exponent) - 0.055F;
+ } else {
+ var_B = 12.92F * var_B;
+ }
+
+ *R = var_R;
+ *G = var_G;
+ *B = var_B;
+}
+
+static void CIELabToRGB16(float L, float a, float b, FIRGB16 *rgb) {
+ float X, Y, Z;
+ float R, G, B;
+ const float max_value = 65535.0F;
+
+ CIELabToXYZ(L, a, b, &X, &Y, &Z);
+ XYZToRGB(X, Y, Z, &R, &G, &B);
+ rgb->red = (WORD)PSD_CLAMP(R * max_value, 0, max_value);
+ rgb->green = (WORD)PSD_CLAMP(G * max_value, 0, max_value);
+ rgb->blue = (WORD)PSD_CLAMP(B * max_value, 0, max_value);
+}
+
+static void CIELabToRGB8(float L, float a, float b, RGBTRIPLE *rgb) {
+ float X, Y, Z;
+ float R, G, B;
+ const float max_value = 255.0F;
+
+ CIELabToXYZ(L, a, b, &X, &Y, &Z);
+ XYZToRGB(X, Y, Z, &R, &G, &B);
+ rgb->rgbtRed = (BYTE)PSD_CLAMP(R * max_value, 0, max_value);
+ rgb->rgbtGreen = (BYTE)PSD_CLAMP(G * max_value, 0, max_value);
+ rgb->rgbtBlue = (BYTE)PSD_CLAMP(B * max_value, 0, max_value);
+}
+
+//---------------------------------------------------------------------------
+
+psdParser::psdParser() {
+ _bThumbnailFilled = false;
+ _bDisplayInfoFilled = false;
+ _bResolutionInfoFilled = false;
+ _bResolutionInfoFilled_v2 = false;
+ _bCopyright = false;
+ _GlobalAngle = 30;
+ _ColourCount = -1;
+ _TransparentIndex = -1;
+}
+
+psdParser::~psdParser() {
+}
+
+bool psdParser::ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle) {
+ bool bSuccess = false;
+
+ BYTE DataLength[4];
+ int nBytes = 0;
+ int n = (int)io->read_proc(&DataLength, sizeof(DataLength), 1, handle);
+ int nTotalBytes = psdGetValue( DataLength, sizeof(DataLength) );
+
+ BYTE data[1];
+ while( n && ( nBytes < nTotalBytes ) ) {
+ data[0] = '\0';
+ n = (int)io->read_proc(&data, sizeof(data), 1, handle);
+ nBytes += n * sizeof(data);
+ }
+
+ assert( nBytes == nTotalBytes );
+ if ( nBytes == nTotalBytes ) {
+ bSuccess = true;
+ }
+
+ return bSuccess;
+}
+
+bool psdParser::ReadImageResource(FreeImageIO *io, fi_handle handle) {
+ psdImageResource oResource;
+ bool bSuccess = false;
+
+ BYTE Length[4];
+ int n = (int)io->read_proc(&Length, sizeof(Length), 1, handle);
+
+ oResource._Length = psdGetValue( Length, sizeof(oResource._Length) );
+
+ int nBytes = 0;
+ int nTotalBytes = oResource._Length;
+
+ while(nBytes < nTotalBytes) {
+ n = 0;
+ oResource.Reset();
+
+ n = (int)io->read_proc(&oResource._OSType, sizeof(oResource._OSType), 1, handle);
+ nBytes += n * sizeof(oResource._OSType);
+ assert( 0 == (nBytes % 2) );
+
+ int nOSType = psdGetValue((BYTE*)&oResource._OSType, sizeof(oResource._OSType));
+
+ if ( PSD_RESOURCE == nOSType ) {
+ BYTE ID[2];
+ n = (int)io->read_proc(&ID, sizeof(ID), 1, handle);
+ nBytes += n * sizeof(ID);
+
+ oResource._ID = (short)psdGetValue( ID, sizeof(ID) );
+
+ BYTE SizeOfName;
+ n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle);
+ nBytes += n * sizeof(SizeOfName);
+
+ int nSizeOfName = psdGetValue( &SizeOfName, sizeof(SizeOfName) );
+ if ( 0 < nSizeOfName ) {
+ oResource._plName = new BYTE[nSizeOfName];
+ n = (int)io->read_proc(oResource._plName, nSizeOfName, 1, handle);
+ nBytes += n * nSizeOfName;
+ }
+
+ if ( 0 == (nSizeOfName % 2) ) {
+ n = (int)io->read_proc(&SizeOfName, sizeof(SizeOfName), 1, handle);
+ nBytes += n * sizeof(SizeOfName);
+ }
+
+ BYTE Size[4];
+ n = (int)io->read_proc(&Size, sizeof(Size), 1, handle);
+ nBytes += n * sizeof(Size);
+
+ oResource._Size = psdGetValue( Size, sizeof(oResource._Size) );
+
+ if ( 0 != (oResource._Size % 2) ) {
+ // resource data must be even
+ oResource._Size++;
+ }
+ if ( 0 < oResource._Size ) {
+ BYTE IntValue[4];
+ BYTE ShortValue[2];
+
+ switch( oResource._ID ) {
+ case 1000:
+ // Obsolete - Photoshop 2.0
+ _bResolutionInfoFilled_v2 = true;
+ nBytes += _resolutionInfo_v2.Read(io, handle);
+ break;
+
+ // ResolutionInfo structure
+ case 1005:
+ _bResolutionInfoFilled = true;
+ nBytes += _resolutionInfo.Read(io, handle);
+ break;
+
+ // DisplayInfo structure
+ case 1007:
+ _bDisplayInfoFilled = true;
+ nBytes += _displayInfo.Read(io, handle);
+ break;
+
+ // (Photoshop 4.0) Copyright flag
+ // Boolean indicating whether image is copyrighted. Can be set via Property suite or by user in File Info...
+ case 1034:
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _bCopyright = (1 == psdGetValue(ShortValue, sizeof(ShortValue)));
+ break;
+
+ // (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only
+ case 1033:
+ // (Photoshop 5.0) Thumbnail resource (supersedes resource 1033)
+ case 1036:
+ {
+ _bThumbnailFilled = true;
+ bool bBGR = (1033==oResource._ID);
+ int nTotalData = oResource._Size - 28; // header
+ nBytes += _thumbnail.Read(io, handle, nTotalData, bBGR);
+ break;
+ }
+
+ // (Photoshop 5.0) Global Angle
+ // 4 bytes that contain an integer between 0 and 359, which is the global
+ // lighting angle for effects layer. If not present, assumed to be 30.
+ case 1037:
+ n = (int)io->read_proc(&IntValue, sizeof(IntValue), 1, handle);
+ nBytes += n * sizeof(IntValue);
+ _GlobalAngle = psdGetValue(IntValue, sizeof(_GlobalAngle) );
+ break;
+
+ // ICC profile
+ case 1039:
+ nBytes += _iccProfile.Read(io, handle, oResource._Size);
+ break;
+
+ // (Photoshop 6.0) Indexed Color Table Count
+ // 2 bytes for the number of colors in table that are actually defined
+ case 1046:
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _ColourCount = (short)psdGetValue(ShortValue, sizeof(ShortValue) );
+ break;
+
+ // (Photoshop 6.0) Transparency Index.
+ // 2 bytes for the index of transparent color, if any.
+ case 1047:
+ n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ nBytes += n * sizeof(ShortValue);
+ _TransparentIndex = (short)psdGetValue(ShortValue, sizeof(ShortValue) );
+ break;
+
+ default:
+ {
+ // skip resource
+ BYTE c[1];
+ for(int i=0; i<oResource._Size; ++i) {
+ n = (int)io->read_proc(&c, sizeof(c), 1, handle);
+ nBytes += n * sizeof(c);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ assert(nBytes == nTotalBytes);
+ if (nBytes == nTotalBytes) {
+ bSuccess = true;
+ }
+
+ return bSuccess;
+
+}
+
+FIBITMAP* psdParser::ProcessBuffer(BYTE * iprData) {
+ assert(NULL != iprData);
+
+ FIBITMAP *Bitmap = NULL;
+ int nHeight = _headerInfo._Height;
+ int nWidth = _headerInfo._Width;
+ unsigned bytes = _headerInfo._BitsPerPixel / 8;
+ int nChannels = _headerInfo._Channels;
+
+ switch (_headerInfo._ColourMode) {
+ case PSD_BITMAP: // Bitmap
+ {
+ // monochrome 1-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 1);
+ if (NULL != dib) {
+ // fill the palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if(pal) {
+ for (int i = 0; i < 2; i++) {
+ BYTE val = i ? 0x0 : 0xFF;
+ pal[i].rgbRed = val;
+ pal[i].rgbGreen = val;
+ pal[i].rgbBlue = val;
+ }
+ }
+ // copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = (nWidth + 7) / 8;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ }
+ Bitmap = dib;
+ }
+ break;
+
+ case PSD_GRAYSCALE: // Grayscale
+ case PSD_DUOTONE: // Duotone
+ case PSD_RGB: // RGB
+ {
+ // 16-bit / channel
+ // --------------------------------------------------------------
+ if (16 == _headerInfo._BitsPerPixel) {
+ if (1 == nChannels) {
+ // L 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_UINT16, nWidth, nHeight);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (2 == nChannels) {
+ // LA 16-bit : convert to RGBA 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBA16, nWidth, nHeight);
+ if (NULL != dib) {
+ unsigned short *src_bits = (unsigned short*)iprData;
+ FIRGBA16 *dst_bits = (FIRGBA16*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned pitch = FreeImage_GetPitch(dib) / sizeof(FIRGBA16);
+ for(int y = 0; y < nHeight; y++) {
+ for(int x = 0; x < nWidth; x++) {
+ dst_bits[x].red = src_bits[0];
+ dst_bits[x].green = src_bits[0];
+ dst_bits[x].blue = src_bits[0];
+ dst_bits[x].alpha = src_bits[1];
+ src_bits += nChannels;
+ }
+ dst_bits -= pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (3 == nChannels) {
+ // RGB 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (4 == nChannels) {
+ // RGBA 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBA16, nWidth, nHeight);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ }
+ // 8-bit / channel
+ // --------------------------------------------------------------
+ else if (8 == _headerInfo._BitsPerPixel) {
+ if (1 == nChannels) {
+ // L 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 8);
+ if (NULL != dib) {
+ // build a greyscale palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for (int i = 0; i < 256; i++) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (2 == nChannels) {
+ // LA 8-bit : convert to RGBA 32-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 32);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *p_src = src_bits;
+ BYTE *p_dst = dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ p_dst[FI_RGBA_RED] = p_src[0];
+ p_dst[FI_RGBA_GREEN] = p_src[0];
+ p_dst[FI_RGBA_BLUE] = p_src[0];
+ p_dst[FI_RGBA_ALPHA] = p_src[1];
+ p_src += nChannels;
+ p_dst += 4;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (3 == nChannels) {
+ // RGB 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *p_src = src_bits;
+ BYTE *p_dst = dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ p_dst[FI_RGBA_RED] = p_src[0];
+ p_dst[FI_RGBA_GREEN] = p_src[1];
+ p_dst[FI_RGBA_BLUE] = p_src[2];
+ p_src += nChannels;
+ p_dst += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else if (4 == nChannels) {
+ // RGBA 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 32);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *p_src = src_bits;
+ BYTE *p_dst = dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ p_dst[FI_RGBA_RED] = p_src[0];
+ p_dst[FI_RGBA_GREEN] = p_src[1];
+ p_dst[FI_RGBA_BLUE] = p_src[2];
+ p_dst[FI_RGBA_ALPHA] = p_src[3];
+ p_src += nChannels;
+ p_dst += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else {
+ assert(false);// do nothing
+ }
+ }
+ // 32-bit / channel => undocumented HDR
+ // --------------------------------------------------------------
+ else if (32 == _headerInfo._BitsPerPixel) {
+ if (3 == nChannels) {
+ // RGBF 32-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGBF, nWidth, nHeight);
+ if (NULL != dib) {
+ // just copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ }
+ }
+ break;
+
+ case PSD_INDEXED: // Indexed
+ {
+ // iprData holds the indices of loop through the palette
+ assert(0 != _colourModeData._plColourData);
+ assert(768 == _colourModeData._Length);
+ assert(0 < _ColourCount);
+
+ // grey or palettised 8 bits
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 8);
+ if (NULL != dib) {
+ // get the palette
+ if (_colourModeData.FillPalette(dib)) {
+ // copy buffer
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ memcpy(dst_bits, src_bits, src_pitch);
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ }
+ }
+ Bitmap = dib;
+ }
+ break;
+
+ case PSD_CMYK: // CMYK
+ {
+ float C, M, Y, K;
+ float s = 1.f / pow( 2.0f, _headerInfo._BitsPerPixel);
+
+ if (16 == _headerInfo._BitsPerPixel) {
+ // CMYK 16-bit : convert to RGB 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ unsigned short *src_line = (unsigned short*)src_bits;
+ FIRGB16 *dst_line = (FIRGB16*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s );
+ M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s );
+ Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s );
+ K = (1.f - (float)psdGetValue((BYTE*)&src_line[3], bytes ) * s );
+ CMYKToRGB16(C, M, Y, K, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else {
+ // CMYK 8-bit : convert to RGB 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *src_line = (BYTE*)src_bits;
+ RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s );
+ M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s );
+ Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s );
+ K = (1.f - (float)psdGetValue((BYTE*)&src_line[3], bytes ) * s );
+ CMYKToRGB8(C, M, Y, K, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ }
+ break;
+
+ case PSD_MULTICHANNEL: // Multichannel
+ {
+ // assume format is in either CMY or CMYK
+ assert(3 <= nChannels);
+ float C, M, Y, K;
+ float s = 1.f / pow( 2.0f, _headerInfo._BitsPerPixel);
+
+ if (16 == _headerInfo._BitsPerPixel) {
+ // CMY(K) 16-bit : convert to RGB 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ unsigned short *src_line = (unsigned short*)src_bits;
+ FIRGB16 *dst_line = (FIRGB16*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s );
+ M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s );
+ Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s );
+ K = (4 <= nChannels) ? (1.f - (float)psdGetValue((BYTE*)&src_line[nChannels], bytes )*s ) : 0;
+ CMYKToRGB16(C, M, Y, K, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ else {
+ // CMY(K) 8-bit : convert to RGB 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *src_line = (BYTE*)src_bits;
+ RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ C = (1.f - (float)psdGetValue((BYTE*)&src_line[0], bytes ) * s );
+ M = (1.f - (float)psdGetValue((BYTE*)&src_line[1], bytes ) * s );
+ Y = (1.f - (float)psdGetValue((BYTE*)&src_line[2], bytes ) * s );
+ K = (4 <= nChannels) ? (1.f - (float)psdGetValue((BYTE*)&src_line[nChannels], bytes )*s ) : 0;
+ CMYKToRGB8(C, M, Y, K, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ }
+ break;
+
+ case PSD_LAB: // Lab
+ {
+ const unsigned dMaxColours = 1 << _headerInfo._BitsPerPixel;
+ const float sL = 100.F / dMaxColours;
+ const float sa = 256.F / dMaxColours;
+ const float sb = 256.F / dMaxColours;
+ float L, a, b;
+
+ if (16 == _headerInfo._BitsPerPixel) {
+ // CIE Lab 16-bit : convert to RGB 16-bit
+ FIBITMAP *dib = FreeImage_AllocateT(FIT_RGB16, nWidth, nHeight);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ unsigned short *src_line = (unsigned short*)src_bits;
+ FIRGB16 *dst_line = (FIRGB16*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ L = (float)psdGetValue((BYTE*)&src_line[0], bytes ) * sL;
+ a = (float)psdGetValue((BYTE*)&src_line[1], bytes ) * sa - 128.F;
+ b = (float)psdGetValue((BYTE*)&src_line[2], bytes ) * sb - 128.F;
+ CIELabToRGB16(L, a, b, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ } else {
+ // CIE Lab 8-bit : convert to RGB 8-bit
+ FIBITMAP *dib = FreeImage_Allocate(nWidth, nHeight, 24);
+ if (NULL != dib) {
+ BYTE *src_bits = (BYTE*)iprData;
+ BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, nHeight-1);
+ unsigned src_pitch = nChannels * nWidth * bytes;
+ unsigned dst_pitch = FreeImage_GetPitch(dib);
+ for(int y = 0; y < nHeight; y++) {
+ BYTE *src_line = (BYTE*)src_bits;
+ RGBTRIPLE *dst_line = (RGBTRIPLE*)dst_bits;
+ for(int x = 0; x < nWidth; x++) {
+ L = (float)psdGetValue((BYTE*)&src_line[0], bytes ) * sL;
+ a = (float)psdGetValue((BYTE*)&src_line[1], bytes ) * sa - 128.F;
+ b = (float)psdGetValue((BYTE*)&src_line[2], bytes ) * sb - 128.F;
+ CIELabToRGB8(L, a, b, &dst_line[x]);
+ src_line += nChannels;
+ }
+ src_bits += src_pitch;
+ dst_bits -= dst_pitch;
+ }
+ Bitmap = dib;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return Bitmap;
+}
+
+FIBITMAP* psdParser::ReadImageData(FreeImageIO *io, fi_handle handle) {
+ FIBITMAP *Bitmap = NULL;
+
+ if(handle != NULL) {
+ BYTE ShortValue[2];
+ int n = (int)io->read_proc(&ShortValue, sizeof(ShortValue), 1, handle);
+ short nCompression = (short)psdGetValue( ShortValue, sizeof(ShortValue) );
+
+ switch ( nCompression ) {
+ case PSD_COMPRESSION_NONE: // raw data
+ {
+ int nWidth = _headerInfo._Width;
+ int nHeight = _headerInfo._Height;
+ int bytes = _headerInfo._BitsPerPixel / 8;
+
+ int nPixels = nWidth * nHeight;
+ int nTotalBytes = nPixels * bytes * _headerInfo._Channels;
+
+ if(_headerInfo._BitsPerPixel == 1) {
+ // special case for PSD_BITMAP mode
+ bytes = 1;
+ nWidth = (nWidth + 7) / 8;
+ nWidth = ( nWidth > 0 ) ? nWidth : 1;
+ nPixels = nWidth * nHeight;
+ nTotalBytes = nWidth * nHeight;
+ }
+
+ BYTE * plData = 0;
+ BYTE * plPixel = 0;
+
+ int nBytes = 0;
+
+ switch (_headerInfo._ColourMode) {
+ case PSD_BITMAP:
+ {
+ plData = new BYTE [nTotalBytes];
+ plPixel = new BYTE [bytes];
+
+ while(nBytes < nTotalBytes) {
+ n = (int)io->read_proc(plPixel, bytes, 1, handle);
+ memcpy(plData+nBytes, plPixel, bytes );
+ nBytes += n * bytes;
+ }
+ SAFE_DELETE_ARRAY(plPixel);
+ }
+ break;
+
+ case PSD_INDEXED: // Indexed
+ {
+ assert( (-1 != _ColourCount) && (0 < _ColourCount) );
+ assert( NULL != _colourModeData._plColourData );
+
+ plData = new BYTE [nTotalBytes];
+ plPixel = new BYTE [bytes];
+
+ while(nBytes < nTotalBytes) {
+ n = (int)io->read_proc(plPixel, bytes, 1, handle);
+ memcpy(plData+nBytes, plPixel, bytes );
+ nBytes += n * bytes;
+ }
+ SAFE_DELETE_ARRAY(plPixel);
+ }
+ break;
+
+ case PSD_GRAYSCALE: // Grayscale
+ case PSD_DUOTONE: // Duotone
+ case PSD_RGB: // RGB
+ {
+ plData = new BYTE [nTotalBytes];
+ plPixel = new BYTE [bytes];
+ int nPixelCounter = 0;
+ int nChannels = _headerInfo._Channels;
+
+ for(int c = 0; c < nChannels; c++) {
+ nPixelCounter = c * bytes;
+ for(int nPos = 0; nPos < nPixels; ++nPos) {
+ n = (int)io->read_proc(plPixel, bytes, 1, handle);
+ if(n == 0) {
+ break;
+ }
+ if(2 == bytes) {
+ // swap for uint16
+ SwapShort((WORD*)&plPixel[0]);
+ } else if(4 == bytes) {
+ // swap for float
+ SwapLong((DWORD*)&plPixel[0]);
+ }
+ memcpy( plData + nPixelCounter, plPixel, bytes );
+ nBytes += n * bytes;
+ nPixelCounter += nChannels*bytes;
+ }
+ }
+ SAFE_DELETE_ARRAY(plPixel);
+ }
+ break;
+
+ case PSD_CMYK: // CMYK
+ case PSD_MULTICHANNEL: // Multichannel
+ {
+ plPixel = new BYTE[bytes];
+ plData = new BYTE[nTotalBytes];
+
+ int nPixelCounter = 0;
+ for (int c=0; c<_headerInfo._Channels; c++) {
+ nPixelCounter = c*bytes;
+ for ( int nPos = 0; nPos < nPixels; ++nPos ) {
+ n = (int)io->read_proc(plPixel, bytes, 1, handle);
+ if(n == 0) {
+ break;
+ }
+ memcpy(plData + nPixelCounter, plPixel, bytes );
+ nBytes += n * bytes;
+
+ nPixelCounter += _headerInfo._Channels*bytes;
+ }
+ }
+ SAFE_DELETE_ARRAY(plPixel);
+ }
+ break;
+
+ case PSD_LAB: // Lab
+ {
+ plPixel = new BYTE[bytes];
+ plData = new BYTE[nTotalBytes];
+ int nPixelCounter = 0;
+ for(int c = 0; c < 3; c++) {
+ nPixelCounter = c*bytes;
+ for ( int nPos = 0; nPos < nPixels; ++nPos ) {
+ n = (int)io->read_proc(plPixel, bytes, 1, handle);
+ if(n == 0) {
+ break;
+ }
+ memcpy(plData + nPixelCounter, plPixel, bytes);
+ nBytes += n * bytes;
+ nPixelCounter += 3*bytes;
+ }
+ }
+ SAFE_DELETE_ARRAY(plPixel);
+ }
+ break;
+ }
+
+ assert( nBytes == nTotalBytes );
+ if (nBytes == nTotalBytes) {
+ if (plData) {
+ switch (_headerInfo._BitsPerPixel) {
+ case 1:
+ case 8:
+ case 16:
+ case 32:
+ Bitmap = ProcessBuffer(plData);
+ break;
+
+ default: // Unsupported
+ break;
+ }
+ }
+ }
+
+ SAFE_DELETE_ARRAY(plData);
+ }
+ break;
+
+
+ case PSD_COMPRESSION_RLE: // RLE compression
+ {
+ int nWidth = _headerInfo._Width;
+ int nHeight = _headerInfo._Height;
+ int bytes = _headerInfo._BitsPerPixel / 8;
+
+ int nPixels = nWidth * nHeight;
+ int nTotalBytes = nPixels * bytes * _headerInfo._Channels;
+
+ if(_headerInfo._BitsPerPixel == 1) {
+ // special case for PSD_BITMAP mode
+ bytes = 1;
+ nWidth = (nWidth + 7) / 8;
+ nWidth = ( nWidth > 0 ) ? nWidth : 1;
+ nPixels = nWidth * nHeight;
+ nTotalBytes = nWidth * nHeight;
+ }
+
+ BYTE * plData = new BYTE[nTotalBytes];
+ BYTE * p = plData;
+ int nValue = 0;
+
+ BYTE ByteValue[1];
+
+ int Count = 0;
+
+ // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
+ // which we're going to just skip.
+ io->seek_proc(handle, nHeight * _headerInfo._Channels * 2, SEEK_CUR);
+
+ for (int channel = 0; channel < _headerInfo._Channels; channel++) {
+ // Read the RLE data.
+ Count = 0;
+ while (Count < nPixels) {
+ io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle);
+
+ int len = psdGetValue( ByteValue, sizeof(ByteValue) );
+ if ( 128 > len ) {
+ len++;
+ Count += len;
+
+ while (len) {
+ io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle);
+ nValue = psdGetValue( ByteValue, sizeof(ByteValue) );
+ *p = (BYTE)nValue;
+ p += sizeof(ByteValue);
+ len--;
+ }
+ }
+ else if ( 128 < len ) {
+ // Next -len+1 bytes in the dest are replicated from next source byte.
+ // (Interpret len as a negative 8-bit int.)
+ len ^= 0x0FF;
+ len += 2;
+ io->read_proc(&ByteValue, sizeof(ByteValue), 1, handle);
+
+ nValue = psdGetValue( ByteValue, sizeof(ByteValue) );
+ Count += len;
+ while (len) {
+ *p = (BYTE)nValue;
+ p += sizeof(ByteValue);
+ len--;
+ }
+ }
+ else if ( 128 == len ) {
+ // Do nothing
+ }
+ }
+ }
+
+ BYTE * prSource = plData;
+ BYTE * plDest = new BYTE[nTotalBytes];
+ memset(plDest, 254, nTotalBytes);
+
+ int nPixelCounter = 0;
+ for(int c=0; c<_headerInfo._Channels; c++) {
+ nPixelCounter = c*bytes;
+ for (int nPos = 0; nPos<nPixels; ++nPos) {
+ memcpy( plDest + nPixelCounter, prSource, bytes );
+ prSource++;
+ nPixelCounter += _headerInfo._Channels*bytes;
+ }
+ }
+ SAFE_DELETE_ARRAY(plData);
+
+ if (plDest) {
+ switch (_headerInfo._BitsPerPixel) {
+ case 1:
+ case 8:
+ case 16:
+ Bitmap = ProcessBuffer(plDest);
+ break;
+
+ default: // Unsupported format
+ break;
+ }
+ }
+ SAFE_DELETE_ARRAY(plDest);
+ }
+ break;
+
+ case 2: // ZIP without prediction, no specification
+ break;
+
+ case 3: // ZIP with prediction, no specification
+ break;
+
+ default: // Unknown format
+ break;
+ }
+ }
+
+ return Bitmap;
+
+}
+
+FIBITMAP* psdParser::Load(FreeImageIO *io, fi_handle handle, int s_format_id) {
+ FIBITMAP *Bitmap = NULL;
+
+ try {
+ if (NULL == handle) {
+ throw("Cannot open file");
+ }
+
+ if (!_headerInfo.Read(io, handle)) {
+ throw("Error in header");
+ }
+
+ if (!_colourModeData.Read(io, handle)) {
+ throw("Error in ColourMode Data");
+ }
+
+ if (!ReadImageResource(io, handle)) {
+ throw("Error in Image Resource");
+ }
+
+ if (!ReadLayerAndMaskInfoSection(io, handle)) {
+ throw("Error in Mask Info");
+ }
+
+ Bitmap = ReadImageData(io, handle);
+ if (NULL == Bitmap) {
+ throw("Error in Image Data");
+ }
+
+ // set resolution info
+ if(NULL != Bitmap) {
+ unsigned res_x = 2835; // 72 dpi
+ unsigned res_y = 2835; // 72 dpi
+ if (_bResolutionInfoFilled) {
+ _resolutionInfo.GetResolutionInfo(res_x, res_y);
+ }
+ FreeImage_SetDotsPerMeterX(Bitmap, res_x);
+ FreeImage_SetDotsPerMeterY(Bitmap, res_y);
+ }
+
+ // set ICC profile
+ if(NULL != _iccProfile._ProfileData) {
+ FreeImage_CreateICCProfile(Bitmap, _iccProfile._ProfileData, _iccProfile._ProfileSize);
+ }
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+
+ return Bitmap;
+}
diff --git a/Source/FreeImage/PSDParser.h b/Source/FreeImage/PSDParser.h
new file mode 100644
index 0000000..4ef2782
--- /dev/null
+++ b/Source/FreeImage/PSDParser.h
@@ -0,0 +1,258 @@
+// ==========================================================
+// Photoshop Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef PSDPARSER_H
+#define PSDPARSER_H
+
+/**
+Table 2-12: File header section.
+The file header contains the basic properties of the image.
+*/
+typedef struct psdHeader {
+ BYTE Signature[4]; //! Always equal 8BPS, do not try to read the file if the signature does not match this value.
+ BYTE Version[2]; //! Always equal 1, do not read file if the version does not match this value.
+ char Reserved[6]; //! Must be zero.
+ BYTE Channels[2]; //! Numer of channels including any alpha channels, supported range is 1 to 24.
+ BYTE Rows[4]; //! The height of the image in pixels. Supported range is 1 to 30,000.
+ BYTE Columns[4]; //! The width of the image in pixels. Supported range is 1 to 30,000.
+ BYTE Depth[2]; //! The number of bits per channel. Supported values are 1, 8, and 16.
+ BYTE Mode[2]; //! Colour mode of the file, Bitmap=0, Grayscale=1, Indexed=2, RGB=3, CMYK=4, Multichannel=7, Duotone=8, Lab=9.
+} psdHeader;
+
+/**
+Table 2-12: HeaderInfo Color spaces
+@see psdHeader
+*/
+class psdHeaderInfo {
+public:
+ short _Channels; //! Numer of channels including any alpha channels, supported range is 1 to 24.
+ int _Height; //! The height of the image in pixels. Supported range is 1 to 30,000.
+ int _Width; //! The width of the image in pixels. Supported range is 1 to 30,000.
+ short _BitsPerPixel;//! The number of bits per channel. Supported values are 1, 8, and 16.
+ short _ColourMode; //! Colour mode of the file, Bitmap=0, Grayscale=1, Indexed=2, RGB=3, CMYK=4, Multichannel=7, Duotone=8, Lab=9.
+
+public:
+ psdHeaderInfo();
+ ~psdHeaderInfo();
+ /**
+ @return Returns the number of bytes read
+ */
+ bool Read(FreeImageIO *io, fi_handle handle);
+};
+
+/**
+Table 2-13 Color mode data section
+
+Only indexed color and duotone have color mode data. For all other modes,
+this section is just 4 bytes: the length field, which is set to zero.
+For indexed color images, the length will be equal to 768, and the color data
+will contain the color table for the image, in non–interleaved order.
+For duotone images, the color data will contain the duotone specification,
+the format of which is not documented. Other applications that read
+Photoshop files can treat a duotone image as a grayscale image, and just
+preserve the contents of the duotone information when reading and writing
+the file.
+*/
+class psdColourModeData {
+public:
+ int _Length; //! The length of the following color data
+ BYTE * _plColourData; //! The color data
+
+public:
+ psdColourModeData();
+ ~psdColourModeData();
+ /**
+ @return Returns the number of bytes read
+ */
+ bool Read(FreeImageIO *io, fi_handle handle);
+ bool FillPalette(FIBITMAP *dib);
+};
+
+/**
+Table 2–1: Image resource block
+NB: Resource data is padded to make size even
+*/
+class psdImageResource {
+public:
+ int _Length;
+ char _OSType[4]; //! Photoshop always uses its signature, 8BIM
+ short _ID; //! Unique identifier. Image resource IDs on page 8
+ BYTE * _plName; //! A pascal string, padded to make size even (a null name consists of two bytes of 0)
+ int _Size; //! Actual size of resource data. This does not include the Type, ID, Name or Size fields.
+
+public:
+ psdImageResource();
+ ~psdImageResource();
+ void Reset();
+};
+
+/**
+Table A-6: ResolutionInfo structure
+This structure contains information about the resolution of an image. It is
+written as an image resource. See the Document file formats chapter for more
+details.
+*/
+class psdResolutionInfo {
+public:
+ short _widthUnit; //! Display width as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ short _heightUnit; //! Display height as 1=inches; 2=cm; 3=points; 4=picas; 5=columns.
+ short _hRes; //! Horizontal resolution in pixels per inch.
+ short _vRes; //! Vertical resolution in pixels per inch.
+ int _hResUnit; //! 1=display horizontal resolution in pixels per inch; 2=display horizontal resolution in pixels per cm.
+ int _vResUnit; //! 1=display vertical resolution in pixels per inch; 2=display vertical resolution in pixels per cm.
+
+public:
+ psdResolutionInfo();
+ ~psdResolutionInfo();
+ /**
+ @return Returns the number of bytes read
+ */
+ int Read(FreeImageIO *io, fi_handle handle);
+ /**
+ @param res_x [out] X resolution in pixels/meter
+ @param res_y [out] Y resolution in pixels/meter
+ */
+ void GetResolutionInfo(unsigned &res_x, unsigned &res_y);
+};
+
+// Obsolete - Photoshop 2.0
+class psdResolutionInfo_v2 {
+public:
+ short _Channels;
+ short _Rows;
+ short _Columns;
+ short _Depth;
+ short _Mode;
+
+public:
+ psdResolutionInfo_v2();
+ ~psdResolutionInfo_v2();
+ /**
+ @return Returns the number of bytes read
+ */
+ int Read(FreeImageIO *io, fi_handle handle);
+};
+
+/**
+Table A-7: DisplayInfo Color spaces
+This structure contains display information about each channel. It is written as an image resource.
+*/
+class psdDisplayInfo {
+public:
+ short _ColourSpace;
+ short _Colour[4];
+ short _Opacity; //! 0..100
+ BYTE _Kind; //! selected = 0, protected = 1
+ BYTE _padding; //! should be zero
+
+public:
+ psdDisplayInfo();
+ ~psdDisplayInfo();
+ /**
+ @return Returns the number of bytes read
+ */
+ int Read(FreeImageIO *io, fi_handle handle);
+};
+
+/**
+Table 2–5: Thumbnail resource header
+Adobe Photoshop 5.0 and later stores thumbnail information for preview
+display in an image resource block. These resource blocks consist of an initial
+28 byte header, followed by a JFIF thumbnail in RGB (red, green, blue) order
+for both Macintosh and Windows. Adobe Photoshop 4.0 stored the
+thumbnail information in the same format except the data section is BGR
+(blue, green, red). The Adobe Photoshop 4.0 format is at resource ID 1033
+and the Adobe Photoshop 5.0 format is at resource ID 1036.
+*/
+class psdThumbnail {
+public:
+ int _Format; //! = 1 (kJpegRGB). Also supports kRawRGB (0).
+ int _Width; //! Width of thumbnail in pixels.
+ int _Height; //! Height of thumbnail in pixels.
+ int _WidthBytes; //! Padded row bytes as (width * bitspixel + 31) / 32 * 4.
+ int _Size; //! Total size as widthbytes * height * planes
+ int _CompressedSize; //! Size after compression. Used for consistentcy check.
+ short _BitPerPixel; //! = 24. Bits per pixel.
+ short _Planes; //! = 1. Number of planes.
+ BYTE * _plData; //! JFIF data in RGB format. Note: For resource ID 1033 the data is in BGR format.
+
+public:
+ psdThumbnail();
+ ~psdThumbnail();
+ /**
+ @return Returns the number of bytes read
+ */
+ int Read(FreeImageIO *io, fi_handle handle, int iTotalData, bool isBGR);
+};
+
+class psdICCProfile {
+public:
+ int _ProfileSize;
+ BYTE * _ProfileData;
+public:
+ psdICCProfile();
+ ~psdICCProfile();
+ /**
+ @return Returns the number of bytes read
+ */
+ int Read(FreeImageIO *io, fi_handle handle, int size);
+};
+
+/**
+PSD loader
+*/
+class psdParser {
+private:
+ psdHeaderInfo _headerInfo;
+ psdColourModeData _colourModeData;
+ psdResolutionInfo _resolutionInfo;
+ psdResolutionInfo_v2 _resolutionInfo_v2;
+ psdDisplayInfo _displayInfo;
+ psdThumbnail _thumbnail;
+ psdICCProfile _iccProfile;
+
+ short _ColourCount;
+ short _TransparentIndex;
+ int _GlobalAngle;
+ bool _bResolutionInfoFilled;
+ bool _bResolutionInfoFilled_v2;
+ bool _bDisplayInfoFilled;
+ bool _bThumbnailFilled;
+ bool _bCopyright;
+
+private:
+ bool ReadImageResource(FreeImageIO *io, fi_handle handle);
+ /** Actually ignore it */
+ bool ReadLayerAndMaskInfoSection(FreeImageIO *io, fi_handle handle);
+ FIBITMAP* ReadImageData(FreeImageIO *io, fi_handle handle);
+ FIBITMAP* ProcessBuffer(BYTE * iprData);
+
+public:
+ psdParser();
+ ~psdParser();
+ FIBITMAP* Load(FreeImageIO *io, fi_handle handle, int s_format_id);
+
+};
+
+#endif // PSDPARSER_H
+
diff --git a/Source/FreeImage/PixelAccess.cpp b/Source/FreeImage/PixelAccess.cpp
new file mode 100644
index 0000000..4baa32e
--- /dev/null
+++ b/Source/FreeImage/PixelAccess.cpp
@@ -0,0 +1,204 @@
+// ==========================================================
+// Pixel access functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Ryan Rubley (ryan@lostreality.org)
+// - Riley McNiff (rmcniff@marexgroup.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+
+BYTE * DLL_CALLCONV
+FreeImage_GetBits(FIBITMAP *dib) {
+ if(!dib) return NULL;
+ // returns the pixels aligned on a FIBITMAP_ALIGNMENT bytes alignment boundary
+ size_t lp = (size_t)FreeImage_GetInfoHeader(dib);
+ lp += sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * FreeImage_GetColorsUsed(dib);
+ lp += (lp % FIBITMAP_ALIGNMENT ? FIBITMAP_ALIGNMENT - lp % FIBITMAP_ALIGNMENT : 0);
+ return (BYTE *)lp;
+}
+
+BYTE * DLL_CALLCONV
+FreeImage_GetScanLine(FIBITMAP *dib, int scanline) {
+ return (dib) ? CalculateScanLine(FreeImage_GetBits(dib), FreeImage_GetPitch(dib), scanline) : NULL;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_GetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) {
+ BYTE shift;
+
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP))
+ return FALSE;
+
+ if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ switch(FreeImage_GetBPP(dib)) {
+ case 1:
+ *value = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
+ break;
+ case 4:
+ shift = (BYTE)((1 - x % 2) << 2);
+ *value = (bits[x >> 1] & (0x0F << shift)) >> shift;
+ break;
+ case 8:
+ *value = bits[x];
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_GetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) {
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP))
+ return FALSE;
+
+ if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ switch(FreeImage_GetBPP(dib)) {
+ case 16:
+ {
+ bits += 2*x;
+ WORD *pixel = (WORD *)bits;
+ if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ value->rgbBlue = (BYTE)((((*pixel & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) * 0xFF) / 0x1F);
+ value->rgbGreen = (BYTE)((((*pixel & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) * 0xFF) / 0x3F);
+ value->rgbRed = (BYTE)((((*pixel & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) * 0xFF) / 0x1F);
+ value->rgbReserved = 0;
+ } else {
+ value->rgbBlue = (BYTE)((((*pixel & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ value->rgbGreen = (BYTE)((((*pixel & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ value->rgbRed = (BYTE)((((*pixel & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ value->rgbReserved = 0;
+ }
+ break;
+ }
+ case 24:
+ bits += 3*x;
+ value->rgbBlue = bits[FI_RGBA_BLUE]; // B
+ value->rgbGreen = bits[FI_RGBA_GREEN]; // G
+ value->rgbRed = bits[FI_RGBA_RED]; // R
+ value->rgbReserved = 0;
+ break;
+ case 32:
+ bits += 4*x;
+ value->rgbBlue = bits[FI_RGBA_BLUE]; // B
+ value->rgbGreen = bits[FI_RGBA_GREEN]; // G
+ value->rgbRed = bits[FI_RGBA_RED]; // R
+ value->rgbReserved = bits[FI_RGBA_ALPHA]; // A
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetPixelIndex(FIBITMAP *dib, unsigned x, unsigned y, BYTE *value) {
+ BYTE shift;
+
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP))
+ return FALSE;
+
+ if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ switch(FreeImage_GetBPP(dib)) {
+ case 1:
+ *value ? bits[x >> 3] |= (0x80 >> (x & 0x7)) : bits[x >> 3] &= (0xFF7F >> (x & 0x7));
+ break;
+ case 4:
+ shift = (BYTE)((1 - x % 2) << 2);
+ bits[x >> 1] &= ~(0x0F << shift);
+ bits[x >> 1] |= ((*value & 0x0F) << shift);
+ break;
+ case 8:
+ bits[x] = *value;
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetPixelColor(FIBITMAP *dib, unsigned x, unsigned y, RGBQUAD *value) {
+ if(!dib || (FreeImage_GetImageType(dib) != FIT_BITMAP))
+ return FALSE;
+
+ if((x < FreeImage_GetWidth(dib)) && (y < FreeImage_GetHeight(dib))) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ switch(FreeImage_GetBPP(dib)) {
+ case 16:
+ {
+ bits += 2*x;
+ WORD *pixel = (WORD *)bits;
+ if((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK)) {
+ *pixel = ((value->rgbBlue >> 3) << FI16_565_BLUE_SHIFT) |
+ ((value->rgbGreen >> 2) << FI16_565_GREEN_SHIFT) |
+ ((value->rgbRed >> 3) << FI16_565_RED_SHIFT);
+ } else {
+ *pixel = ((value->rgbBlue >> 3) << FI16_555_BLUE_SHIFT) |
+ ((value->rgbGreen >> 3) << FI16_555_GREEN_SHIFT) |
+ ((value->rgbRed >> 3) << FI16_555_RED_SHIFT);
+ }
+ break;
+ }
+ case 24:
+ bits += 3*x;
+ bits[FI_RGBA_BLUE] = value->rgbBlue; // B
+ bits[FI_RGBA_GREEN] = value->rgbGreen; // G
+ bits[FI_RGBA_RED] = value->rgbRed; // R
+ break;
+ case 32:
+ bits += 4*x;
+ bits[FI_RGBA_BLUE] = value->rgbBlue; // B
+ bits[FI_RGBA_GREEN] = value->rgbGreen; // G
+ bits[FI_RGBA_RED] = value->rgbRed; // R
+ bits[FI_RGBA_ALPHA] = value->rgbReserved; // A
+ break;
+ default:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/Source/FreeImage/Plugin.cpp b/Source/FreeImage/Plugin.cpp
new file mode 100644
index 0000000..cf8e1a8
--- /dev/null
+++ b/Source/FreeImage/Plugin.cpp
@@ -0,0 +1,792 @@
+// =====================================================================
+// FreeImage Plugin Interface
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Rui Lopes (ruiglopes@yahoo.com)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+// - Petr Pytelka (pyta@lightcomp.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// =====================================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#include <io.h>
+#else
+#include <ctype.h>
+#endif // _WIN32
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageIO.h"
+#include "Plugin.h"
+
+// =====================================================================
+
+using namespace std;
+
+// =====================================================================
+// Plugin search list
+// =====================================================================
+
+const char *
+s_search_list[] = {
+ "",
+ "plugins\\",
+};
+
+static int s_search_list_size = sizeof(s_search_list) / sizeof(char *);
+static PluginList *s_plugins = NULL;
+static int s_plugin_reference_count = 0;
+
+
+// =====================================================================
+// Reimplementation of stricmp (it is not supported on some systems)
+// =====================================================================
+
+int
+FreeImage_stricmp(const char *s1, const char *s2) {
+ int c1, c2;
+
+ do {
+ c1 = tolower(*s1++);
+ c2 = tolower(*s2++);
+ } while (c1 && c1 == c2);
+
+ return c1 - c2;
+}
+
+// =====================================================================
+// Implementation of PluginList
+// =====================================================================
+
+PluginList::PluginList() :
+m_plugin_map(),
+m_node_count(0) {
+}
+
+FREE_IMAGE_FORMAT
+PluginList::AddNode(FI_InitProc init_proc, void *instance, const char *format, const char *description, const char *extension, const char *regexpr) {
+ if (init_proc != NULL) {
+ PluginNode *node = new PluginNode;
+ Plugin *plugin = new Plugin;
+
+ memset(plugin, 0, sizeof(Plugin));
+
+ // fill-in the plugin structure
+
+ init_proc(plugin, (int)m_plugin_map.size());
+
+ // get the format string (two possible ways)
+
+ const char *the_format = NULL;
+
+ if (format != NULL)
+ the_format = format;
+ else if (plugin->format_proc != NULL)
+ the_format = plugin->format_proc();
+
+ // add the node if it wasn't there already
+
+ if (the_format != NULL) {
+ if (FindNodeFromFormat(the_format) == NULL) {
+ node->m_id = (int)m_plugin_map.size();
+ node->m_instance = instance;
+ node->m_plugin = plugin;
+ node->m_format = format;
+ node->m_description = description;
+ node->m_extension = extension;
+ node->m_regexpr = regexpr;
+ node->m_next = NULL;
+ node->m_enabled = TRUE;
+
+ m_plugin_map[(const int)m_plugin_map.size()] = node;
+
+ return (FREE_IMAGE_FORMAT)node->m_id;
+ }
+ }
+
+ // something went wrong while allocating the plugin... cleanup
+
+ delete plugin;
+ delete node;
+ }
+
+ return FIF_UNKNOWN;
+}
+
+PluginNode *
+PluginList::FindNodeFromFormat(const char *format) {
+ int count = 0;
+
+ for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
+ const char *the_format = ((*i).second->m_format != NULL) ? (*i).second->m_format : (*i).second->m_plugin->format_proc();
+
+ if (FreeImage_stricmp(the_format, format) == 0)
+ return (*i).second;
+
+ count++;
+ }
+
+ return NULL;
+}
+
+PluginNode *
+PluginList::FindNodeFromMime(const char *mime) {
+ int count = 0;
+
+ for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
+ const char *the_mime = ((*i).second->m_plugin->mime_proc != NULL) ? (*i).second->m_plugin->mime_proc() : "";
+
+ if ((the_mime != NULL) && (strcmp(the_mime, mime) == 0))
+ return (*i).second;
+
+ count++;
+ }
+
+ return NULL;
+}
+
+PluginNode *
+PluginList::FindNodeFromFIF(int node_id) {
+ map<int, PluginNode *>::iterator i = m_plugin_map.find(node_id);
+
+ if (i != m_plugin_map.end())
+ return (*i).second;
+
+ return NULL;
+}
+
+int
+PluginList::Size() const {
+ return (int)m_plugin_map.size();
+}
+
+BOOL
+PluginList::IsEmpty() const {
+ return m_plugin_map.empty();
+}
+
+PluginList::~PluginList() {
+ for (map<int, PluginNode *>::iterator i = m_plugin_map.begin(); i != m_plugin_map.end(); ++i) {
+#ifdef _WIN32
+ if ((*i).second->m_instance != NULL)
+ FreeLibrary((HINSTANCE)(*i).second->m_instance);
+#endif
+ delete (*i).second->m_plugin;
+ delete ((*i).second);
+ }
+}
+
+// =====================================================================
+// Retrieve a pointer to the plugin list container
+// =====================================================================
+
+PluginList * DLL_CALLCONV
+FreeImage_GetPluginList() {
+ return s_plugins;
+}
+
+// =====================================================================
+// Plugin System Initialization
+// =====================================================================
+
+void DLL_CALLCONV
+FreeImage_Initialise(BOOL load_local_plugins_only) {
+ if (s_plugin_reference_count++ == 0) {
+
+ // internal plugin initialization
+
+ s_plugins = new PluginList;
+
+ if (s_plugins) {
+ /* NOTE :
+ The order used to initialize internal plugins below MUST BE the same order
+ as the one used to define the FREE_IMAGE_FORMAT enum.
+ */
+ s_plugins->AddNode(InitBMP);
+ s_plugins->AddNode(InitICO);
+ s_plugins->AddNode(InitJPEG);
+ s_plugins->AddNode(InitMNG, NULL, "JNG", "JPEG Network Graphics", "jng", "");
+ s_plugins->AddNode(InitKOALA);
+ s_plugins->AddNode(InitIFF);
+ s_plugins->AddNode(InitMNG);
+ s_plugins->AddNode(InitPNM, NULL, "PBM", "Portable Bitmap (ASCII)", "pbm", "^P1");
+ s_plugins->AddNode(InitPNM, NULL, "PBMRAW", "Portable Bitmap (RAW)", "pbm", "^P4");
+ s_plugins->AddNode(InitPCD);
+ s_plugins->AddNode(InitPCX);
+ s_plugins->AddNode(InitPNM, NULL, "PGM", "Portable Greymap (ASCII)", "pgm", "^P2");
+ s_plugins->AddNode(InitPNM, NULL, "PGMRAW", "Portable Greymap (RAW)", "pgm", "^P5");
+ s_plugins->AddNode(InitPNG);
+ s_plugins->AddNode(InitPNM, NULL, "PPM", "Portable Pixelmap (ASCII)", "ppm", "^P3");
+ s_plugins->AddNode(InitPNM, NULL, "PPMRAW", "Portable Pixelmap (RAW)", "ppm", "^P6");
+ s_plugins->AddNode(InitRAS);
+ s_plugins->AddNode(InitTARGA);
+ s_plugins->AddNode(InitTIFF);
+ s_plugins->AddNode(InitWBMP);
+ s_plugins->AddNode(InitPSD);
+ s_plugins->AddNode(InitCUT);
+ s_plugins->AddNode(InitXBM);
+ s_plugins->AddNode(InitXPM);
+ s_plugins->AddNode(InitDDS);
+ s_plugins->AddNode(InitGIF);
+ s_plugins->AddNode(InitHDR);
+ s_plugins->AddNode(InitG3);
+ s_plugins->AddNode(InitSGI);
+#ifndef NO_EXR_PLUGIN
+ s_plugins->AddNode(InitEXR);
+#endif
+ s_plugins->AddNode(InitJ2K);
+ s_plugins->AddNode(InitJP2);
+#if 0 // Unused by TPN
+ s_plugins->AddNode(InitPFM);
+ s_plugins->AddNode(InitPICT);
+ s_plugins->AddNode(InitRAW);
+#endif
+
+ // external plugin initialization
+
+#ifdef _WIN32
+ if (!load_local_plugins_only) {
+ int count = 0;
+ char buffer[MAX_PATH + 200];
+ char current_dir[2 * _MAX_PATH], module[2 * _MAX_PATH];
+ BOOL bOk = FALSE;
+
+ // store the current directory. then set the directory to the application location
+
+ if (GetCurrentDirectory(2 * _MAX_PATH, current_dir) != 0) {
+ if (GetModuleFileName(NULL, module, 2 * _MAX_PATH) != 0) {
+ char *last_point = strrchr(module, '\\');
+
+ if (last_point) {
+ *last_point = '\0';
+
+ bOk = SetCurrentDirectory(module);
+ }
+ }
+ }
+
+ // search for plugins
+
+ while (count < s_search_list_size) {
+ _finddata_t find_data;
+ long find_handle;
+
+ strcpy(buffer, s_search_list[count]);
+ strcat(buffer, "*.fip");
+
+ if ((find_handle = (long)_findfirst(buffer, &find_data)) != -1L) {
+ do {
+ strcpy(buffer, s_search_list[count]);
+ strncat(buffer, find_data.name, MAX_PATH + 200);
+
+ HINSTANCE instance = LoadLibrary(buffer);
+
+ if (instance != NULL) {
+ FARPROC proc_address = GetProcAddress(instance, "_Init@8");
+
+ if (proc_address != NULL)
+ s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance);
+ else
+ FreeLibrary(instance);
+ }
+ } while (_findnext(find_handle, &find_data) != -1L);
+
+ _findclose(find_handle);
+ }
+
+ count++;
+ }
+
+ // restore the current directory
+
+ if (bOk)
+ SetCurrentDirectory(current_dir);
+ }
+#endif // _WIN32
+ }
+ }
+}
+
+void DLL_CALLCONV
+FreeImage_DeInitialise() {
+ --s_plugin_reference_count;
+
+ if (s_plugin_reference_count == 0) {
+ delete s_plugins;
+ }
+}
+
+// =====================================================================
+// Open and close a bitmap
+// =====================================================================
+
+void * DLL_CALLCONV
+FreeImage_Open(PluginNode *node, FreeImageIO *io, fi_handle handle, BOOL open_for_reading) {
+ if (node->m_plugin->open_proc != NULL)
+ return node->m_plugin->open_proc(io, handle, open_for_reading);
+
+ return NULL;
+};
+
+void DLL_CALLCONV
+FreeImage_Close(PluginNode *node, FreeImageIO *io, fi_handle handle, void *data) {
+ if (node->m_plugin->close_proc != NULL)
+ node->m_plugin->close_proc(io, handle, data);
+};
+
+// =====================================================================
+// Plugin System Load/Save Functions
+// =====================================================================
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_LoadFromHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flags) {
+ if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ if (node != NULL) {
+ if (node->m_enabled) {
+ if(node->m_plugin->load_proc != NULL) {
+ FIBITMAP *bitmap = NULL;
+
+ void *data = FreeImage_Open(node, io, handle, TRUE);
+
+ bitmap = node->m_plugin->load_proc(io, handle, -1, flags, data);
+
+ FreeImage_Close(node, io, handle, data);
+
+ return bitmap;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_Load(FREE_IMAGE_FORMAT fif, const char *filename, int flags) {
+ FreeImageIO io;
+ SetDefaultIO(&io);
+
+ FILE *handle = fopen(filename, "rb");
+
+ if (handle) {
+ FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
+
+ fclose(handle);
+
+ return bitmap;
+ } else {
+ FreeImage_OutputMessageProc((int)fif, "FreeImage_Load: failed to open file %s", filename);
+ }
+
+ return NULL;
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_LoadU(FREE_IMAGE_FORMAT fif, const wchar_t *filename, int flags) {
+ FreeImageIO io;
+ SetDefaultIO(&io);
+#ifdef _WIN32
+ FILE *handle = _wfopen(filename, L"rb");
+
+ if (handle) {
+ FIBITMAP *bitmap = FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
+
+ fclose(handle);
+
+ return bitmap;
+ } else {
+ FreeImage_OutputMessageProc((int)fif, "FreeImage_LoadU: failed to open input file");
+ }
+#endif
+ return NULL;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, FreeImageIO *io, fi_handle handle, int flags) {
+ if ((fif >= 0) && (fif < FreeImage_GetFIFCount())) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ if (node) {
+ if (node->m_enabled) {
+ if(node->m_plugin->save_proc != NULL) {
+ BOOL result = FALSE;
+
+ void *data = FreeImage_Open(node, io, handle, FALSE);
+
+ result = node->m_plugin->save_proc(io, dib, handle, -1, flags, data);
+
+ FreeImage_Close(node, io, handle, data);
+
+ return result;
+ }
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+BOOL DLL_CALLCONV
+FreeImage_Save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const char *filename, int flags) {
+ FreeImageIO io;
+ SetDefaultIO(&io);
+
+ FILE *handle = fopen(filename, "w+b");
+
+ if (handle) {
+ BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
+
+ fclose(handle);
+
+ return success;
+ } else {
+ FreeImage_OutputMessageProc((int)fif, "FreeImage_Save: failed to open file %s", filename);
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, const wchar_t *filename, int flags) {
+ FreeImageIO io;
+ SetDefaultIO(&io);
+#ifdef _WIN32
+ FILE *handle = _wfopen(filename, L"w+b");
+
+ if (handle) {
+ BOOL success = FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
+
+ fclose(handle);
+
+ return success;
+ } else {
+ FreeImage_OutputMessageProc((int)fif, "FreeImage_SaveU: failed to open output file");
+ }
+#endif
+ return FALSE;
+}
+
+// =====================================================================
+// Plugin construction + enable/disable functions
+// =====================================================================
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_RegisterLocalPlugin(FI_InitProc proc_address, const char *format, const char *description, const char *extension, const char *regexpr) {
+ return s_plugins->AddNode(proc_address, NULL, format, description, extension, regexpr);
+}
+
+#ifdef _WIN32
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_RegisterExternalPlugin(const char *path, const char *format, const char *description, const char *extension, const char *regexpr) {
+ if (path != NULL) {
+ HINSTANCE instance = LoadLibrary(path);
+
+ if (instance != NULL) {
+ FARPROC proc_address = GetProcAddress(instance, "_Init@8");
+
+ FREE_IMAGE_FORMAT result = s_plugins->AddNode((FI_InitProc)proc_address, (void *)instance, format, description, extension, regexpr);
+
+ if (result == FIF_UNKNOWN)
+ FreeLibrary(instance);
+
+ return result;
+ }
+ }
+
+ return FIF_UNKNOWN;
+}
+#endif // _WIN32
+
+int DLL_CALLCONV
+FreeImage_SetPluginEnabled(FREE_IMAGE_FORMAT fif, BOOL enable) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ if (node != NULL) {
+ BOOL previous_state = node->m_enabled;
+
+ node->m_enabled = enable;
+
+ return previous_state;
+ }
+ }
+
+ return -1;
+}
+
+int DLL_CALLCONV
+FreeImage_IsPluginEnabled(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? node->m_enabled : FALSE;
+ }
+
+ return -1;
+}
+
+// =====================================================================
+// Plugin Access Functions
+// =====================================================================
+
+int DLL_CALLCONV
+FreeImage_GetFIFCount() {
+ return (s_plugins != NULL) ? s_plugins->Size() : 0;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFIFFromFormat(const char *format) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFormat(format);
+
+ return (node != NULL) ? (node->m_enabled) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN : FIF_UNKNOWN;
+ }
+
+ return FIF_UNKNOWN;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFIFFromMime(const char *mime) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromMime(mime);
+
+ return (node != NULL) ? (node->m_enabled) ? (FREE_IMAGE_FORMAT)node->m_id : FIF_UNKNOWN : FIF_UNKNOWN;
+ }
+
+ return FIF_UNKNOWN;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetFormatFromFIF(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? (node->m_format != NULL) ? node->m_format : node->m_plugin->format_proc() : NULL;
+ }
+
+ return NULL;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetFIFMimeType(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? (node->m_plugin != NULL) ? ( node->m_plugin->mime_proc != NULL )? node->m_plugin->mime_proc() : NULL : NULL : NULL;
+ }
+
+ return NULL;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetFIFExtensionList(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? (node->m_extension != NULL) ? node->m_extension : (node->m_plugin->extension_proc != NULL) ? node->m_plugin->extension_proc() : NULL : NULL;
+ }
+
+ return NULL;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetFIFDescription(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? (node->m_description != NULL) ? node->m_description : (node->m_plugin->description_proc != NULL) ? node->m_plugin->description_proc() : NULL : NULL;
+ }
+
+ return NULL;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetFIFRegExpr(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? (node->m_regexpr != NULL) ? node->m_regexpr : (node->m_plugin->regexpr_proc != NULL) ? node->m_plugin->regexpr_proc() : NULL : NULL;
+ }
+
+ return NULL;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FIFSupportsReading(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? node->m_plugin->load_proc != NULL : FALSE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FIFSupportsWriting(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ? node->m_plugin->save_proc != NULL : FALSE ;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int depth) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ?
+ (node->m_plugin->supports_export_bpp_proc != NULL) ?
+ node->m_plugin->supports_export_bpp_proc(depth) : FALSE : FALSE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ?
+ (node->m_plugin->supports_export_type_proc != NULL) ?
+ node->m_plugin->supports_export_type_proc(type) : FALSE : FALSE;
+ }
+
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif) {
+ if (s_plugins != NULL) {
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ return (node != NULL) ?
+ (node->m_plugin->supports_icc_profiles_proc != NULL) ?
+ node->m_plugin->supports_icc_profiles_proc() : FALSE : FALSE;
+ }
+
+ return FALSE;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFIFFromFilename(const char *filename) {
+ if (filename != NULL) {
+ const char *extension;
+
+ // get the proper extension if we received a filename
+
+ char *place = strrchr((char *)filename, '.');
+ extension = (place != NULL) ? ++place : filename;
+
+ // look for the extension in the plugin table
+
+ for (int i = 0; i < FreeImage_GetFIFCount(); ++i) {
+
+ if (s_plugins->FindNodeFromFIF(i)->m_enabled) {
+
+ // compare the format id with the extension
+
+ if (FreeImage_stricmp(FreeImage_GetFormatFromFIF((FREE_IMAGE_FORMAT)i), extension) == 0) {
+ return (FREE_IMAGE_FORMAT)i;
+ } else {
+ // make a copy of the extension list and split it
+
+ char *copy = (char *)malloc(strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1);
+ memset(copy, 0, strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)) + 1);
+ memcpy(copy, FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i), strlen(FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)i)));
+
+ // get the first token
+
+ char *token = strtok(copy, ",");
+
+ while (token != NULL) {
+ if (FreeImage_stricmp(token, extension) == 0) {
+ free(copy);
+
+ return (FREE_IMAGE_FORMAT)i;
+ }
+
+ token = strtok(NULL, ",");
+ }
+
+ // free the copy of the extension list
+
+ free(copy);
+ }
+ }
+ }
+ }
+
+ return FIF_UNKNOWN;
+}
+
+FREE_IMAGE_FORMAT DLL_CALLCONV
+FreeImage_GetFIFFromFilenameU(const wchar_t *filename) {
+#ifdef _WIN32
+ if (filename == NULL) return FIF_UNKNOWN;
+
+ // get the proper extension if we received a filename
+ wchar_t *place = wcsrchr((wchar_t *)filename, '.');
+ if (place == NULL) return FIF_UNKNOWN;
+ // convert to single character - no national chars in extensions
+ char *extension = (char *)malloc(wcslen(place)+1);
+ unsigned int i=0;
+ for(; i < wcslen(place); i++) // convert 16-bit to 8-bit
+ extension[i] = (char)(place[i] & 0x00FF);
+ // set terminating 0
+ extension[i]=0;
+ FREE_IMAGE_FORMAT fRet = FreeImage_GetFIFFromFilename(extension);
+ free(extension);
+
+ return fRet;
+#else
+ return FIF_UNKNOWN;
+#endif // _WIN32
+}
+
+BOOL DLL_CALLCONV
+FreeImage_Validate(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle) {
+ if (s_plugins != NULL) {
+ BOOL validated = FALSE;
+
+ PluginNode *node = s_plugins->FindNodeFromFIF(fif);
+
+ if (node) {
+ long tell = io->tell_proc(handle);
+
+ validated = (node != NULL) ? (node->m_enabled) ? (node->m_plugin->validate_proc != NULL) ? node->m_plugin->validate_proc(io, handle) : FALSE : FALSE : FALSE;
+
+ io->seek_proc(handle, tell, SEEK_SET);
+ }
+
+ return validated;
+ }
+
+ return FALSE;
+}
diff --git a/Source/FreeImage/PluginBMP.cpp b/Source/FreeImage/PluginBMP.cpp
new file mode 100644
index 0000000..4ea82e9
--- /dev/null
+++ b/Source/FreeImage/PluginBMP.cpp
@@ -0,0 +1,1381 @@
+// ==========================================================
+// BMP Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Martin Weber (martweb@gmx.net)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Michal Novotny (michal@etc.cz)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+static const BYTE RLE_COMMAND = 0;
+static const BYTE RLE_ENDOFLINE = 0;
+static const BYTE RLE_ENDOFBITMAP = 1;
+static const BYTE RLE_DELTA = 2;
+
+static const BYTE BI_RGB = 0;
+static const BYTE BI_RLE8 = 1;
+static const BYTE BI_RLE4 = 2;
+static const BYTE BI_BITFIELDS = 3;
+
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagBITMAPCOREHEADER {
+ DWORD bcSize;
+ WORD bcWidth;
+ WORD bcHeight;
+ WORD bcPlanes;
+ WORD bcBitCnt;
+} BITMAPCOREHEADER, *PBITMAPCOREHEADER;
+
+typedef struct tagBITMAPINFOOS2_1X_HEADER {
+ DWORD biSize;
+ WORD biWidth;
+ WORD biHeight;
+ WORD biPlanes;
+ WORD biBitCount;
+} BITMAPINFOOS2_1X_HEADER, *PBITMAPINFOOS2_1X_HEADER;
+
+typedef struct tagBITMAPFILEHEADER {
+ WORD bfType;
+ DWORD bfSize;
+ WORD bfReserved1;
+ WORD bfReserved2;
+ DWORD bfOffBits;
+} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+#ifdef FREEIMAGE_BIGENDIAN
+static void
+SwapInfoHeader(BITMAPINFOHEADER *header) {
+ SwapLong(&header->biSize);
+ SwapLong((DWORD *)&header->biWidth);
+ SwapLong((DWORD *)&header->biHeight);
+ SwapShort(&header->biPlanes);
+ SwapShort(&header->biBitCount);
+ SwapLong(&header->biCompression);
+ SwapLong(&header->biSizeImage);
+ SwapLong((DWORD *)&header->biXPelsPerMeter);
+ SwapLong((DWORD *)&header->biYPelsPerMeter);
+ SwapLong(&header->biClrUsed);
+ SwapLong(&header->biClrImportant);
+}
+
+static void
+SwapCoreHeader(BITMAPCOREHEADER *header) {
+ SwapLong(&header->bcSize);
+ SwapShort(&header->bcWidth);
+ SwapShort(&header->bcHeight);
+ SwapShort(&header->bcPlanes);
+ SwapShort(&header->bcBitCnt);
+}
+
+static void
+SwapOS21XHeader(BITMAPINFOOS2_1X_HEADER *header) {
+ SwapLong(&header->biSize);
+ SwapShort(&header->biWidth);
+ SwapShort(&header->biHeight);
+ SwapShort(&header->biPlanes);
+ SwapShort(&header->biBitCount);
+}
+
+static void
+SwapFileHeader(BITMAPFILEHEADER *header) {
+ SwapShort(&header->bfType);
+ SwapLong(&header->bfSize);
+ SwapShort(&header->bfReserved1);
+ SwapShort(&header->bfReserved2);
+ SwapLong(&header->bfOffBits);
+}
+#endif
+
+// --------------------------------------------------------------------------
+
+/**
+Load uncompressed image pixels for 1-, 4-, 8-, 16-, 24- and 32-bit dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param dib Image to be loaded
+@param height Image height
+@param pitch Image pitch
+@param bit_count Image bit-depth (1-, 4-, 8-, 16-, 24- or 32-bit)
+*/
+static void
+LoadPixelData(FreeImageIO *io, fi_handle handle, FIBITMAP *dib, int height, int pitch, int bit_count) {
+ // Load pixel data
+ // NB: height can be < 0 for BMP data
+ if (height > 0) {
+ io->read_proc((void *)FreeImage_GetBits(dib), height * pitch, 1, handle);
+ } else {
+ int positiveHeight = abs(height);
+ for (int c = 0; c < positiveHeight; ++c) {
+ io->read_proc((void *)FreeImage_GetScanLine(dib, positiveHeight - c - 1), pitch, 1, handle);
+ }
+ }
+
+ // swap as needed
+#ifdef FREEIMAGE_BIGENDIAN
+ if (bit_count == 16) {
+ for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
+ for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ SwapShort(pixel);
+ pixel++;
+ }
+ }
+ }
+#endif
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if (bit_count == 24 || bit_count == 32) {
+ for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *pixel = FreeImage_GetScanLine(dib, y);
+ for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ INPLACESWAP(pixel[0], pixel[2]);
+ pixel += (bit_count >> 3);
+ }
+ }
+ }
+#endif
+}
+
+/**
+Load image pixels for 4-bit RLE compressed dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param width Image width
+@param height Image height
+@param dib Image to be loaded
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+LoadPixelDataRLE4(FreeImageIO *io, fi_handle handle, int width, int height, FIBITMAP *dib) {
+ int status_byte = 0;
+ BYTE second_byte = 0;
+ int bits = 0;
+
+ BYTE *pixels = NULL; // temporary 8-bit buffer
+
+ try {
+ height = abs(height);
+
+ pixels = (BYTE*)malloc(width * height * sizeof(BYTE));
+ if(!pixels) throw(1);
+ memset(pixels, 0, width * height * sizeof(BYTE));
+
+ BYTE *q = pixels;
+ BYTE *end = pixels + height * width;
+
+ for (int scanline = 0; scanline < height; ) {
+ if (q < pixels || q >= end) {
+ break;
+ }
+ if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ if (status_byte != 0) {
+ status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q));
+ // Encoded mode
+ if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ for (int i = 0; i < status_byte; i++) {
+ *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ }
+ bits += status_byte;
+ }
+ else {
+ // Escape mode
+ if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ switch (status_byte) {
+ case RLE_ENDOFLINE:
+ {
+ // End of line
+ bits = 0;
+ scanline++;
+ q = pixels + scanline*width;
+ }
+ break;
+
+ case RLE_ENDOFBITMAP:
+ // End of bitmap
+ q = end;
+ break;
+
+ case RLE_DELTA:
+ {
+ // read the delta values
+
+ BYTE delta_x = 0;
+ BYTE delta_y = 0;
+
+ if(io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ if(io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+
+ // apply them
+
+ bits += delta_x;
+ scanline += delta_y;
+ q = pixels + scanline*width+bits;
+ }
+ break;
+
+ default:
+ {
+ // Absolute mode
+ status_byte = (int)MIN((size_t)status_byte, (size_t)(end - q));
+ for (int i = 0; i < status_byte; i++) {
+ if ((i & 0x01) == 0) {
+ if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ }
+ *q++=(BYTE)((i & 0x01) ? (second_byte & 0x0f) : ((second_byte >> 4) & 0x0f));
+ }
+ bits += status_byte;
+ // Read pad byte
+ if (((status_byte & 0x03) == 1) || ((status_byte & 0x03) == 2)) {
+ BYTE padding = 0;
+ if(io->read_proc(&padding, sizeof(BYTE), 1, handle) != 1) {
+ throw(1);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ {
+ // Convert to 4-bit
+ for(int y = 0; y < height; y++) {
+ const BYTE *src = (BYTE*)pixels + y * width;
+ BYTE *dst = FreeImage_GetScanLine(dib, y);
+
+ BOOL hinibble = TRUE;
+
+ for (int cols = 0; cols < width; cols++){
+ if (hinibble) {
+ dst[cols >> 1] = (src[cols] << 4);
+ } else {
+ dst[cols >> 1] |= src[cols];
+ }
+
+ hinibble = !hinibble;
+ }
+ }
+ }
+
+ free(pixels);
+
+ return TRUE;
+
+ } catch(int) {
+ if(pixels) free(pixels);
+ return FALSE;
+ }
+}
+
+/**
+Load image pixels for 8-bit RLE compressed dib
+@param io FreeImage IO
+@param handle FreeImage IO handle
+@param width Image width
+@param height Image height
+@param dib Image to be loaded
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+LoadPixelDataRLE8(FreeImageIO *io, fi_handle handle, int width, int height, FIBITMAP *dib) {
+ BYTE status_byte = 0;
+ BYTE second_byte = 0;
+ int scanline = 0;
+ int bits = 0;
+
+ for (;;) {
+ if( io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ switch (status_byte) {
+ case RLE_COMMAND :
+ if(io->read_proc(&status_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ switch (status_byte) {
+ case RLE_ENDOFLINE :
+ bits = 0;
+ scanline++;
+ break;
+
+ case RLE_ENDOFBITMAP :
+ return TRUE;
+
+ case RLE_DELTA :
+ {
+ // read the delta values
+
+ BYTE delta_x = 0;
+ BYTE delta_y = 0;
+
+ if(io->read_proc(&delta_x, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ if(io->read_proc(&delta_y, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ // apply them
+
+ bits += delta_x;
+ scanline += delta_y;
+
+ break;
+ }
+
+ default :
+ {
+ if(scanline >= abs(height)) {
+ return TRUE;
+ }
+
+ int count = MIN((int)status_byte, width - bits);
+
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+
+ if(io->read_proc((void *)(sline + bits), sizeof(BYTE) * count, 1, handle) != 1) {
+ return FALSE;
+ }
+
+ // align run length to even number of bytes
+
+ if ((status_byte & 1) == 1) {
+ if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+ }
+
+ bits += status_byte;
+
+ break;
+ }
+ }
+
+ break;
+
+ default :
+ {
+ if(scanline >= abs(height)) {
+ return TRUE;
+ }
+
+ int count = MIN((int)status_byte, width - bits);
+
+ BYTE *sline = FreeImage_GetScanLine(dib, scanline);
+
+ if(io->read_proc(&second_byte, sizeof(BYTE), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ for (int i = 0; i < count; i++) {
+ *(sline + bits) = second_byte;
+
+ bits++;
+ }
+
+ break;
+ }
+ }
+ }
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *
+LoadWindowsBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ // load the info header
+
+ BITMAPINFOHEADER bih;
+
+ io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bih);
+#endif
+
+ // keep some general information about the bitmap
+
+ int used_colors = bih.biClrUsed;
+ int width = bih.biWidth;
+ int height = bih.biHeight; // WARNING: height can be < 0 => check each call using 'height' as a parameter
+ int bit_count = bih.biBitCount;
+ int compression = bih.biCompression;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count)))
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette
+
+ dib = FreeImage_Allocate(width, height, bit_count);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load the palette
+
+ io->read_proc(FreeImage_GetPalette(dib), used_colors * sizeof(RGBQUAD), 1, handle);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for(int i = 0; i < used_colors; i++) {
+ INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue);
+ }
+#endif
+
+ // seek to the actual pixel data.
+ // this is needed because sometimes the palette is larger than the entries it contains predicts
+
+ if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * sizeof(RGBQUAD))))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ switch (compression) {
+ case BI_RGB :
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+ return dib;
+
+ case BI_RLE4 :
+ if( LoadPixelDataRLE4(io, handle, width, height, dib) ) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE4 BMP data";
+ }
+ break;
+
+ case BI_RLE8 :
+ if( LoadPixelDataRLE8(io, handle, width, height, dib) ) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE8 BMP data";
+ }
+ break;
+
+ default :
+ throw FI_MSG_ERROR_UNSUPPORTED_COMPRESSION;
+ }
+ }
+ break; // 1-, 4-, 8-bit
+
+ case 16 :
+ {
+ if (bih.biCompression == BI_BITFIELDS) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]);
+ } else {
+ dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+ break; // 16-bit
+
+ case 24 :
+ case 32 :
+ {
+ if (bih.biCompression == BI_BITFIELDS) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]);
+ } else {
+ if( bit_count == 32 ) {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ if (FreeImage_GetColorsUsed(dib) > 0) {
+ io->seek_proc(handle, FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD), SEEK_CUR);
+ } else if ((bih.biCompression != BI_BITFIELDS) && (bitmap_bits_offset > sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))) {
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+ }
+
+ // read in the bitmap bits
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));
+
+ return dib;
+ }
+ break; // 24-, 32-bit
+ }
+ } catch(const char *message) {
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
+ if(message) {
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *
+LoadOS22XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ // load the info header
+
+ BITMAPINFOHEADER bih;
+
+ io->read_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bih);
+#endif
+
+ // keep some general information about the bitmap
+
+ int used_colors = bih.biClrUsed;
+ int width = bih.biWidth;
+ int height = bih.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter
+ int bit_count = bih.biBitCount;
+ int compression = bih.biCompression;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ if ((used_colors <= 0) || (used_colors > CalculateUsedPaletteEntries(bit_count)))
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette
+
+ dib = FreeImage_Allocate(width, height, bit_count);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // load the palette
+
+ io->seek_proc(handle, sizeof(BITMAPFILEHEADER) + bih.biSize, SEEK_SET);
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ for (int count = 0; count < used_colors; count++) {
+ FILE_BGR bgr;
+
+ io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
+
+ pal[count].rgbRed = bgr.r;
+ pal[count].rgbGreen = bgr.g;
+ pal[count].rgbBlue = bgr.b;
+ }
+
+ // seek to the actual pixel data.
+ // this is needed because sometimes the palette is larger than the entries it contains predicts
+
+ if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ switch (compression) {
+ case BI_RGB :
+ // load pixel data
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+ return dib;
+
+ case BI_RLE4 :
+ if( LoadPixelDataRLE4(io, handle, width, height, dib) ) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE4 BMP data";
+ }
+ break;
+
+ case BI_RLE8 :
+ if( LoadPixelDataRLE8(io, handle, width, height, dib) ) {
+ return dib;
+ } else {
+ throw "Error encountered while decoding RLE8 BMP data";
+ }
+ break;
+
+ default :
+ throw FI_MSG_ERROR_UNSUPPORTED_COMPRESSION;
+ }
+ }
+
+ case 16 :
+ {
+ if (bih.biCompression == 3) {
+ DWORD bitfields[3];
+
+ io->read_proc(bitfields, 3 * sizeof(DWORD), 1, handle);
+
+ dib = FreeImage_Allocate(width, height, bit_count, bitfields[0], bitfields[1], bitfields[2]);
+ } else {
+ dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3))) {
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+ }
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 24 :
+ case 32 :
+ {
+ if( bit_count == 32 ) {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information
+ FreeImage_SetDotsPerMeterX(dib, bih.biXPelsPerMeter);
+ FreeImage_SetDotsPerMeterY(dib, bih.biYPelsPerMeter);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ if (bitmap_bits_offset > (sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (used_colors * 3)))
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read in the bitmap bits
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));
+
+ return dib;
+ }
+ }
+ } catch(const char *message) {
+ if(dib)
+ FreeImage_Unload(dib);
+
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+
+ return NULL;
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP *
+LoadOS21XBMP(FreeImageIO *io, fi_handle handle, int flags, unsigned bitmap_bits_offset) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ BITMAPINFOOS2_1X_HEADER bios2_1x;
+
+ io->read_proc(&bios2_1x, sizeof(BITMAPINFOOS2_1X_HEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapOS21XHeader(&bios2_1x);
+#endif
+ // keep some general information about the bitmap
+
+ int used_colors = 0;
+ int width = bios2_1x.biWidth;
+ int height = bios2_1x.biHeight; // WARNING: height can be < 0 => check each read_proc using 'height' as a parameter
+ int bit_count = bios2_1x.biBitCount;
+ int pitch = CalculatePitch(CalculateLine(width, bit_count));
+
+ switch (bit_count) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ used_colors = CalculateUsedPaletteEntries(bit_count);
+
+ // allocate enough memory to hold the bitmap (header, palette, pixels) and read the palette
+
+ dib = FreeImage_Allocate(width, height, bit_count);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // load the palette
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ for (int count = 0; count < used_colors; count++) {
+ FILE_BGR bgr;
+
+ io->read_proc(&bgr, sizeof(FILE_BGR), 1, handle);
+
+ pal[count].rgbRed = bgr.r;
+ pal[count].rgbGreen = bgr.g;
+ pal[count].rgbBlue = bgr.b;
+ }
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ io->seek_proc(handle, bitmap_bits_offset, SEEK_SET);
+
+ // read the pixel data
+
+ // load pixel data
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 16 :
+ {
+ dib = FreeImage_Allocate(width, height, bit_count, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ return dib;
+ }
+
+ case 24 :
+ case 32 :
+ {
+ if( bit_count == 32 ) {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate(width, height, bit_count, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // set resolution information to default values (72 dpi in english units)
+ FreeImage_SetDotsPerMeterX(dib, 2835);
+ FreeImage_SetDotsPerMeterY(dib, 2835);
+
+ // Skip over the optional palette
+ // A 24 or 32 bit DIB may contain a palette for faster color reduction
+
+ // load pixel data and swap as needed if OS is Big Endian
+ LoadPixelData(io, handle, dib, height, pitch, bit_count);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ FreeImage_SetTransparent(dib, (FreeImage_GetColorType(dib) == FIC_RGBALPHA));
+
+ return dib;
+ }
+ }
+ } catch(const char *message) {
+ if(dib)
+ FreeImage_Unload(dib);
+
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "BMP";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Windows or OS/2 Bitmap";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "bmp";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^BM";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/bmp";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE bmp_signature1[] = { 0x42, 0x4D };
+ BYTE bmp_signature2[] = { 0x42, 0x41 };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(bmp_signature1), handle);
+
+ if (memcmp(bmp_signature1, signature, sizeof(bmp_signature1)) == 0)
+ return TRUE;
+
+ if (memcmp(bmp_signature2, signature, sizeof(bmp_signature2)) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1) ||
+ (depth == 4) ||
+ (depth == 8) ||
+ (depth == 16) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle != NULL) {
+ BITMAPFILEHEADER bitmapfileheader;
+ DWORD type = 0;
+ BYTE magic[2];
+
+ // we use this offset value to make seemingly absolute seeks relative in the file
+
+ long offset_in_file = io->tell_proc(handle);
+
+ // read the magic
+
+ io->read_proc(&magic, sizeof(magic), 1, handle);
+
+ // compare the magic with the number we know
+
+ // somebody put a comment here explaining the purpose of this loop
+ while (memcmp(&magic, "BA", 2) == 0) {
+ io->read_proc(&bitmapfileheader.bfSize, sizeof(DWORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfReserved1, sizeof(WORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfReserved2, sizeof(WORD), 1, handle);
+ io->read_proc(&bitmapfileheader.bfOffBits, sizeof(DWORD), 1, handle);
+ io->read_proc(&magic, sizeof(magic), 1, handle);
+ }
+
+ // read the fileheader
+
+ io->seek_proc(handle, 0 - sizeof(magic), SEEK_CUR);
+ io->read_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapFileHeader(&bitmapfileheader);
+#endif
+
+ // read the first byte of the infoheader
+
+ io->read_proc(&type, sizeof(DWORD), 1, handle);
+ io->seek_proc(handle, 0 - sizeof(DWORD), SEEK_CUR);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ // call the appropriate load function for the found bitmap type
+
+ if (type == 40)
+ return LoadWindowsBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ if (type == 12)
+ return LoadOS21XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ if (type <= 64)
+ return LoadOS22XBMP(io, handle, flags, offset_in_file + bitmapfileheader.bfOffBits);
+
+ FreeImage_OutputMessageProc(s_format_id, "unknown bmp subtype with id %d", type);
+ }
+
+ return NULL;
+}
+
+// ----------------------------------------------------------
+
+/**
+Encode a 8-bit source buffer into a 8-bit target buffer using a RLE compression algorithm.
+The size of the target buffer must be equal to the size of the source buffer.
+On return, the function will return the real size of the target buffer, which should be less that or equal to the source buffer size.
+@param target 8-bit Target buffer
+@param source 8-bit Source buffer
+@param size Source/Target input buffer size
+@return Returns the target buffer size
+*/
+static int
+RLEEncodeLine(BYTE *target, BYTE *source, int size) {
+ BYTE buffer[256];
+ int buffer_size = 0;
+ int target_pos = 0;
+
+ for (int i = 0; i < size; ++i) {
+ if ((i < size - 1) && (source[i] == source[i + 1])) {
+ // find a solid block of same bytes
+
+ int j = i + 1;
+ int jmax = 254 + i;
+
+ while ((j < size - 1) && (j < jmax) && (source[j] == source[j + 1]))
+ ++j;
+
+ // if the block is larger than 3 bytes, use it
+ // else put the data into the larger pool
+
+ if (((j - i) + 1) > 3) {
+ // don't forget to write what we already have in the buffer
+
+ switch(buffer_size) {
+ case 0 :
+ break;
+
+ case RLE_DELTA :
+ target[target_pos++] = 1;
+ target[target_pos++] = buffer[0];
+ target[target_pos++] = 1;
+ target[target_pos++] = buffer[1];
+ break;
+
+ case RLE_ENDOFBITMAP :
+ target[target_pos++] = (BYTE)buffer_size;
+ target[target_pos++] = buffer[0];
+ break;
+
+ default :
+ target[target_pos++] = RLE_COMMAND;
+ target[target_pos++] = (BYTE)buffer_size;
+ memcpy(target + target_pos, buffer, buffer_size);
+
+ // prepare for next run
+
+ target_pos += buffer_size;
+
+ if ((buffer_size & 1) == 1)
+ target_pos++;
+
+ break;
+ }
+
+ // write the continuous data
+
+ target[target_pos++] = (BYTE)((j - i) + 1);
+ target[target_pos++] = source[i];
+
+ buffer_size = 0;
+ } else {
+ for (int k = 0; k < (j - i) + 1; ++k) {
+ buffer[buffer_size++] = source[i + k];
+
+ if (buffer_size == 254) {
+ // write what we have
+
+ target[target_pos++] = RLE_COMMAND;
+ target[target_pos++] = (BYTE)buffer_size;
+ memcpy(target + target_pos, buffer, buffer_size);
+
+ // prepare for next run
+
+ target_pos += buffer_size;
+ buffer_size = 0;
+ }
+ }
+ }
+
+ i = j;
+ } else {
+ buffer[buffer_size++] = source[i];
+ }
+
+ // write the buffer if it's full
+
+ if (buffer_size == 254) {
+ target[target_pos++] = RLE_COMMAND;
+ target[target_pos++] = (BYTE)buffer_size;
+ memcpy(target + target_pos, buffer, buffer_size);
+
+ // prepare for next run
+
+ target_pos += buffer_size;
+ buffer_size = 0;
+ }
+ }
+
+ // write the last bytes
+
+ switch(buffer_size) {
+ case 0 :
+ break;
+
+ case RLE_DELTA :
+ target[target_pos++] = 1;
+ target[target_pos++] = buffer[0];
+ target[target_pos++] = 1;
+ target[target_pos++] = buffer[1];
+ break;
+
+ case RLE_ENDOFBITMAP :
+ target[target_pos++] = (BYTE)buffer_size;
+ target[target_pos++] = buffer[0];
+ break;
+
+ default :
+ target[target_pos++] = RLE_COMMAND;
+ target[target_pos++] = (BYTE)buffer_size;
+ memcpy(target + target_pos, buffer, buffer_size);
+
+ // prepare for next run
+
+ target_pos += buffer_size;
+
+ if ((buffer_size & 1) == 1)
+ target_pos++;
+
+ break;
+ }
+
+ // write the END_OF_LINE marker
+
+ target[target_pos++] = RLE_COMMAND;
+ target[target_pos++] = RLE_ENDOFLINE;
+
+ // return the written size
+
+ return target_pos;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib != NULL) && (handle != NULL)) {
+ // write the file header
+
+ BITMAPFILEHEADER bitmapfileheader;
+ bitmapfileheader.bfType = 0x4D42;
+ bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + FreeImage_GetColorsUsed(dib) * sizeof(RGBQUAD);
+ bitmapfileheader.bfSize = bitmapfileheader.bfOffBits + FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib);
+ bitmapfileheader.bfReserved1 = 0;
+ bitmapfileheader.bfReserved2 = 0;
+
+ // take care of the bit fields data of any
+
+ bool bit_fields = (FreeImage_GetBPP(dib) == 16);
+
+ if (bit_fields) {
+ bitmapfileheader.bfSize += 3 * sizeof(DWORD);
+ bitmapfileheader.bfOffBits += 3 * sizeof(DWORD);
+ }
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapFileHeader(&bitmapfileheader);
+#endif
+ if (io->write_proc(&bitmapfileheader, sizeof(BITMAPFILEHEADER), 1, handle) != 1)
+ return FALSE;
+
+ // update the bitmap info header
+
+ BITMAPINFOHEADER bih;
+ memcpy(&bih, FreeImage_GetInfoHeader(dib), sizeof(BITMAPINFOHEADER));
+
+ if (bit_fields)
+ bih.biCompression = BI_BITFIELDS;
+ else if ((bih.biBitCount == 8) && (flags & BMP_SAVE_RLE))
+ bih.biCompression = BI_RLE8;
+ else
+ bih.biCompression = BI_RGB;
+
+ // write the bitmap info header
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bih);
+#endif
+ if (io->write_proc(&bih, sizeof(BITMAPINFOHEADER), 1, handle) != 1)
+ return FALSE;
+
+ // write the bit fields when we are dealing with a 16 bit BMP
+
+ if (bit_fields) {
+ DWORD d;
+
+ d = FreeImage_GetRedMask(dib);
+
+ if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
+ return FALSE;
+
+ d = FreeImage_GetGreenMask(dib);
+
+ if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
+ return FALSE;
+
+ d = FreeImage_GetBlueMask(dib);
+
+ if (io->write_proc(&d, sizeof(DWORD), 1, handle) != 1)
+ return FALSE;
+ }
+
+ // write the palette
+
+ if (FreeImage_GetPalette(dib) != NULL) {
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ FILE_BGRA bgra;
+ for(unsigned i = 0; i < FreeImage_GetColorsUsed(dib); i++ ) {
+ bgra.b = pal[i].rgbBlue;
+ bgra.g = pal[i].rgbGreen;
+ bgra.r = pal[i].rgbRed;
+ bgra.a = pal[i].rgbReserved;
+ if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
+ return FALSE;
+ }
+ }
+
+ // write the bitmap data... if RLE compression is enable, use it
+
+ unsigned bpp = FreeImage_GetBPP(dib);
+ if ((bpp == 8) && (flags & BMP_SAVE_RLE)) {
+ BYTE *buffer = new BYTE[FreeImage_GetPitch(dib) * 2];
+
+ for (DWORD i = 0; i < FreeImage_GetHeight(dib); ++i) {
+ int size = RLEEncodeLine(buffer, FreeImage_GetScanLine(dib, i), FreeImage_GetLine(dib));
+
+ if (io->write_proc(buffer, size, 1, handle) != 1) {
+ delete [] buffer;
+ return FALSE;
+ }
+ }
+
+ buffer[0] = RLE_COMMAND;
+ buffer[1] = RLE_ENDOFBITMAP;
+
+ if (io->write_proc(buffer, 2, 1, handle) != 1) {
+ delete [] buffer;
+ return FALSE;
+ }
+
+ delete [] buffer;
+#ifdef FREEIMAGE_BIGENDIAN
+ } else if (bpp == 16) {
+ int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(WORD);
+ WORD pad = 0;
+ WORD pixel;
+ for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
+ pixel = ((WORD *)line)[x];
+ SwapShort(&pixel);
+ if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1)
+ return FALSE;
+ }
+ if(padding != 0) {
+ if(io->write_proc(&pad, padding, 1, handle) != 1) {
+ return FALSE;
+ }
+ }
+ }
+#endif
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ } else if (bpp == 24) {
+ int padding = FreeImage_GetPitch(dib) - FreeImage_GetWidth(dib) * sizeof(FILE_BGR);
+ DWORD pad = 0;
+ FILE_BGR bgr;
+ for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
+ RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
+ bgr.b = triple->rgbtBlue;
+ bgr.g = triple->rgbtGreen;
+ bgr.r = triple->rgbtRed;
+ if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
+ return FALSE;
+ }
+ if(padding != 0) {
+ if(io->write_proc(&pad, padding, 1, handle) != 1) {
+ return FALSE;
+ }
+ }
+ }
+ } else if (bpp == 32) {
+ FILE_BGRA bgra;
+ for(int y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(dib); x++) {
+ RGBQUAD *quad = ((RGBQUAD *)line)+x;
+ bgra.b = quad->rgbBlue;
+ bgra.g = quad->rgbGreen;
+ bgra.r = quad->rgbRed;
+ bgra.a = quad->rgbReserved;
+ if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
+ return FALSE;
+ }
+ }
+#endif
+ } else if (io->write_proc(FreeImage_GetBits(dib), FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib), 1, handle) != 1) {
+ return FALSE;
+ }
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitBMP(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
+}
diff --git a/Source/FreeImage/PluginCUT.cpp b/Source/FreeImage/PluginCUT.cpp
new file mode 100644
index 0000000..ed57d60
--- /dev/null
+++ b/Source/FreeImage/PluginCUT.cpp
@@ -0,0 +1,197 @@
+// ==========================================================
+// CUT Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagCUTHEADER {
+ short width;
+ short height;
+ int dummy;
+} CUTHEADER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "CUT";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Dr. Halo";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "cut";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-cut";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle != NULL) {
+ CUTHEADER header;
+ FIBITMAP *dib;
+
+ // read the cut header
+
+ io->read_proc(&header, 1, sizeof(CUTHEADER), handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort((WORD *)&header.width);
+ SwapShort((WORD *)&header.height);
+#endif
+
+ if ((header.width == 0) || (header.height == 0))
+ return NULL;
+
+ // allocate a new bitmap
+
+ dib = FreeImage_Allocate(header.width, header.height, 8);
+
+ if (dib == NULL)
+ return NULL;
+
+ // stuff it with a palette
+
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+
+ for (int j = 0; j < 256; ++j)
+ palette[j].rgbBlue = palette[j].rgbGreen = palette[j].rgbRed = (BYTE)j;
+
+ // unpack the RLE bitmap bits
+
+ BYTE *bits = FreeImage_GetScanLine(dib, header.height - 1);
+
+ int i = 0, k = 0;
+ int pitch = FreeImage_GetPitch(dib);
+ int size = header.width * header.height;
+ BYTE count = 0, run = 0;
+
+ while (i < size) {
+ io->read_proc(&count, 1, sizeof(BYTE), handle);
+
+ if (count == 0) {
+ k = 0;
+ bits -= pitch;
+
+ // paint shop pro adds two useless bytes here...
+
+ io->read_proc(&count, 1, sizeof(BYTE), handle);
+ io->read_proc(&count, 1, sizeof(BYTE), handle);
+
+ continue;
+ }
+
+ if (count & 0x80) {
+ count &= ~(0x80);
+
+ io->read_proc(&run, 1, sizeof(BYTE), handle);
+
+ memset(bits + k, run, count);
+ } else {
+ io->read_proc(&bits[k], count, sizeof(BYTE), handle);
+ }
+
+ k += count;
+ i += count;
+ }
+
+ return dib;
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitCUT(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginDDS.cpp b/Source/FreeImage/PluginDDS.cpp
new file mode 100644
index 0000000..1e08f53
--- /dev/null
+++ b/Source/FreeImage/PluginDDS.cpp
@@ -0,0 +1,649 @@
+// ==========================================================
+// DDS Loader
+//
+// Design and implementation by
+// - Volker Gärtner (volkerg@gmx.at)
+// - Sherman Wilcox
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Definitions for the DDS format
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagDDPIXELFORMAT {
+ DWORD dwSize; // size of this structure (must be 32)
+ DWORD dwFlags; // see DDPF_*
+ DWORD dwFourCC;
+ DWORD dwRGBBitCount; // Total number of bits for RGB formats
+ DWORD dwRBitMask;
+ DWORD dwGBitMask;
+ DWORD dwBBitMask;
+ DWORD dwRGBAlphaBitMask;
+} DDPIXELFORMAT;
+
+// DIRECTDRAW PIXELFORMAT FLAGS
+enum {
+ DDPF_ALPHAPIXELS = 0x00000001l, // surface has alpha channel
+ DDPF_ALPHA = 0x00000002l, // alpha only
+ DDPF_FOURCC = 0x00000004l, // FOURCC available
+ DDPF_RGB = 0x00000040l // RGB(A) bitmap
+};
+
+typedef struct tagDDCAPS2 {
+ DWORD dwCaps1; // Zero or more of the DDSCAPS_* members
+ DWORD dwCaps2; // Zero or more of the DDSCAPS2_* members
+ DWORD dwReserved[2];
+} DDCAPS2;
+
+// DIRECTDRAWSURFACE CAPABILITY FLAGS
+enum {
+ DDSCAPS_ALPHA = 0x00000002l, // alpha only surface
+ DDSCAPS_COMPLEX = 0x00000008l, // complex surface structure
+ DDSCAPS_TEXTURE = 0x00001000l, // used as texture (should always be set)
+ DDSCAPS_MIPMAP = 0x00400000l // Mipmap present
+};
+
+enum {
+ DDSCAPS2_CUBEMAP = 0x00000200L,
+ DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400L,
+ DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800L,
+ DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000L,
+ DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000L,
+ DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000L,
+ DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000L,
+ DDSCAPS2_VOLUME = 0x00200000L
+};
+
+typedef struct tagDDSURFACEDESC2 {
+ DWORD dwSize; // size of this structure (must be 124)
+ DWORD dwFlags; // combination of the DDSS_* flags
+ DWORD dwHeight;
+ DWORD dwWidth;
+ DWORD dwPitchOrLinearSize;
+ DWORD dwDepth; // Depth of a volume texture
+ DWORD dwMipMapCount;
+ DWORD dwReserved1[11];
+ DDPIXELFORMAT ddpfPixelFormat;
+ DDCAPS2 ddsCaps;
+ DWORD dwReserved2;
+} DDSURFACEDESC2;
+
+enum {
+ DDSD_CAPS = 0x00000001l,
+ DDSD_HEIGHT = 0x00000002l,
+ DDSD_WITH = 0x00000004l,
+ DDSD_PITCH = 0x00000008l,
+ DDSD_ALPHABITDEPTH = 0x00000080l,
+ DDSD_PIXELFORMAT = 0x00001000l,
+ DDSD_MIPMAPCOUNT = 0x00020000l,
+ DDSD_LINEARSIZE = 0x00080000l,
+ DDSD_DEPTH = 0x00800000l
+};
+
+typedef struct tagDDSHEADER {
+ DWORD dwMagic; // FOURCC: "DDS "
+ DDSURFACEDESC2 surfaceDesc;
+} DDSHEADER;
+
+#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
+ ((DWORD)(BYTE)(ch0) | ((DWORD)(BYTE)(ch1) << 8) | \
+ ((DWORD)(BYTE)(ch2) << 16) | ((DWORD)(BYTE)(ch3) << 24 ))
+
+#define FOURCC_DXT1 MAKEFOURCC('D','X','T','1')
+#define FOURCC_DXT2 MAKEFOURCC('D','X','T','2')
+#define FOURCC_DXT3 MAKEFOURCC('D','X','T','3')
+#define FOURCC_DXT4 MAKEFOURCC('D','X','T','4')
+#define FOURCC_DXT5 MAKEFOURCC('D','X','T','5')
+
+// ----------------------------------------------------------
+// Structures used by DXT textures
+// ----------------------------------------------------------
+
+typedef struct tagColor8888 {
+ BYTE b;
+ BYTE g;
+ BYTE r;
+ BYTE a;
+} Color8888;
+
+typedef struct tagColor565 {
+ WORD b : 5;
+ WORD g : 6;
+ WORD r : 5;
+} Color565;
+
+typedef struct tagDXTColBlock {
+ Color565 colors[2];
+ BYTE row[4];
+} DXTColBlock;
+
+typedef struct tagDXTAlphaBlockExplicit {
+ WORD row[4];
+} DXTAlphaBlockExplicit;
+
+typedef struct tagDXTAlphaBlock3BitLinear {
+ BYTE alpha[2];
+ BYTE data[6];
+} DXTAlphaBlock3BitLinear;
+
+typedef struct tagDXT1Block
+{
+ DXTColBlock color;
+} DXT1Block;
+
+typedef struct tagDXT3Block { // also used by dxt2
+ DXTAlphaBlockExplicit alpha;
+ DXTColBlock color;
+} DXT3Block;
+
+typedef struct tagDXT5Block { // also used by dxt4
+ DXTAlphaBlock3BitLinear alpha;
+ DXTColBlock color;
+} DXT5Block;
+
+#ifdef _WIN32
+# pragma pack(pop)
+#else
+# pragma pack()
+#endif
+
+// ----------------------------------------------------------
+// Internal functions
+// ----------------------------------------------------------
+#ifdef FREEIMAGE_BIGENDIAN
+static void
+SwapHeader(DDSHEADER *header) {
+ SwapLong(&header->dwMagic);
+ SwapLong(&header->surfaceDesc.dwSize);
+ SwapLong(&header->surfaceDesc.dwFlags);
+ SwapLong(&header->surfaceDesc.dwHeight);
+ SwapLong(&header->surfaceDesc.dwWidth);
+ SwapLong(&header->surfaceDesc.dwPitchOrLinearSize);
+ SwapLong(&header->surfaceDesc.dwDepth);
+ SwapLong(&header->surfaceDesc.dwMipMapCount);
+ for(int i=0; i<11; i++) {
+ SwapLong(&header->surfaceDesc.dwReserved1[i]);
+ }
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwSize);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFlags);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFourCC);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBBitCount);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRBitMask);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwGBitMask);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwBBitMask);
+ SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask);
+ SwapLong(&header->surfaceDesc.ddsCaps.dwCaps1);
+ SwapLong(&header->surfaceDesc.ddsCaps.dwCaps2);
+ SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[0]);
+ SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[1]);
+ SwapLong(&header->surfaceDesc.dwReserved2);
+}
+#endif
+
+// ==========================================================
+
+// Get the 4 possible colors for a block
+//
+static void
+GetBlockColors (const DXTColBlock &block, Color8888 colors[4], bool isDXT1) {
+ int i;
+ // expand from 565 to 888
+ for (i = 0; i < 2; i++) {
+ colors[i].a = 0xff;
+ /*
+ colors[i].r = (BYTE)(block.colors[i].r * 0xff / 0x1f);
+ colors[i].g = (BYTE)(block.colors[i].g * 0xff / 0x3f);
+ colors[i].b = (BYTE)(block.colors[i].b * 0xff / 0x1f);
+ */
+ colors[i].r = (BYTE)((block.colors[i].r << 3U) | (block.colors[i].r >> 2U));
+ colors[i].g = (BYTE)((block.colors[i].g << 2U) | (block.colors[i].g >> 4U));
+ colors[i].b = (BYTE)((block.colors[i].b << 3U) | (block.colors[i].b >> 2U));
+ }
+
+ WORD *wCol = (WORD *)block.colors;
+ if (wCol[0] > wCol[1] || !isDXT1) {
+ // 4 color block
+ for (i = 0; i < 2; i++) {
+ colors[i + 2].a = 0xff;
+ colors[i + 2].r = (BYTE)((WORD (colors[0].r) * (2 - i) + WORD (colors[1].r) * (1 + i)) / 3);
+ colors[i + 2].g = (BYTE)((WORD (colors[0].g) * (2 - i) + WORD (colors[1].g) * (1 + i)) / 3);
+ colors[i + 2].b = (BYTE)((WORD (colors[0].b) * (2 - i) + WORD (colors[1].b) * (1 + i)) / 3);
+ }
+ }
+ else {
+ // 3 color block, number 4 is transparent
+ colors[2].a = 0xff;
+ colors[2].r = (BYTE)((WORD (colors[0].r) + WORD (colors[1].r)) / 2);
+ colors[2].g = (BYTE)((WORD (colors[0].g) + WORD (colors[1].g)) / 2);
+ colors[2].b = (BYTE)((WORD (colors[0].b) + WORD (colors[1].b)) / 2);
+
+ colors[3].a = 0x00;
+ colors[3].g = 0x00;
+ colors[3].b = 0x00;
+ colors[3].r = 0x00;
+ }
+}
+
+struct DXT_INFO_1 {
+ typedef DXT1Block Block;
+ enum {
+ isDXT1 = 1,
+ bytesPerBlock = 8
+ };
+};
+
+struct DXT_INFO_3 {
+ typedef DXT3Block Block;
+ enum {
+ isDXT1 = 1,
+ bytesPerBlock = 16
+ };
+};
+
+struct DXT_INFO_5 {
+ typedef DXT5Block Block;
+ enum
+ {
+ isDXT1 = 1,
+ bytesPerBlock = 16
+ };
+};
+
+template <class INFO> class DXT_BLOCKDECODER_BASE {
+protected:
+ Color8888 m_colors[4];
+ const typename INFO::Block *m_pBlock;
+ unsigned m_colorRow;
+
+public:
+ void Setup (const BYTE *pBlock) {
+ m_pBlock = (const typename INFO::Block *)pBlock;
+ GetBlockColors (m_pBlock->color, m_colors, INFO::isDXT1);
+ }
+
+ void SetY (int y) {
+ m_colorRow = m_pBlock->color.row[y];
+ }
+
+ void GetColor (int x, int y, Color8888 &color) {
+ unsigned bits = (m_colorRow >> (x * 2)) & 3;
+ color = m_colors[bits];
+ }
+};
+
+class DXT_BLOCKDECODER_1 : public DXT_BLOCKDECODER_BASE <DXT_INFO_1> {
+public:
+ typedef DXT_INFO_1 INFO;
+};
+
+class DXT_BLOCKDECODER_3 : public DXT_BLOCKDECODER_BASE <DXT_INFO_3> {
+public:
+ typedef DXT_BLOCKDECODER_BASE <DXT_INFO_3> base;
+ typedef DXT_INFO_3 INFO;
+
+protected:
+ unsigned m_alphaRow;
+
+public:
+ void SetY (int y) {
+ base::SetY (y);
+ m_alphaRow = m_pBlock->alpha.row[y];
+ }
+
+ void GetColor (int x, int y, Color8888 &color) {
+ base::GetColor (x, y, color);
+ const unsigned bits = (m_alphaRow >> (x * 4)) & 0xF;
+ color.a = (BYTE)((bits * 0xFF) / 0xF);
+ }
+};
+
+class DXT_BLOCKDECODER_5 : public DXT_BLOCKDECODER_BASE <DXT_INFO_5> {
+public:
+ typedef DXT_BLOCKDECODER_BASE <DXT_INFO_5> base;
+ typedef DXT_INFO_5 INFO;
+
+protected:
+ unsigned m_alphas[8];
+ unsigned m_alphaBits;
+ int m_offset;
+
+public:
+ void Setup (const BYTE *pBlock) {
+ base::Setup (pBlock);
+
+ const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
+ m_alphas[0] = block.alpha[0];
+ m_alphas[1] = block.alpha[1];
+ if (m_alphas[0] > m_alphas[1]) {
+ // 8 alpha block
+ for (int i = 0; i < 6; i++) {
+ m_alphas[i + 2] = ((6 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 3) / 7;
+ }
+ }
+ else {
+ // 6 alpha block
+ for (int i = 0; i < 4; i++) {
+ m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
+ }
+ m_alphas[6] = 0;
+ m_alphas[7] = 0xFF;
+ }
+
+ }
+
+ void SetY (int y) {
+ base::SetY (y);
+ int i = y / 2;
+ const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
+ m_alphaBits = unsigned(block.data[0 + i * 3]) | (unsigned(block.data[1 + i * 3]) << 8)
+ | (unsigned(block.data[2 + i * 3]) << 16);
+ m_offset = (y & 1) * 12;
+ }
+
+ void GetColor (int x, int y, Color8888 &color) {
+ base::GetColor (x, y, color);
+ unsigned bits = (m_alphaBits >> (x * 3 + m_offset)) & 7;
+ color.a = (BYTE)m_alphas[bits];
+ }
+};
+
+template <class DECODER> void DecodeDXTBlock (BYTE *dstData, const BYTE *srcBlock, long dstPitch, int bw, int bh) {
+ DECODER decoder;
+ decoder.Setup (srcBlock);
+ for (int y = 0; y < bh; y++) {
+ BYTE *dst = dstData - y * dstPitch;
+ decoder.SetY (y);
+ for (int x = 0; x < bw; x++) {
+ decoder.GetColor (x, y, (Color8888 &)*dst);
+ dst += 4;
+ }
+ }
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static FIBITMAP *
+LoadRGB (DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ int width = (int)desc.dwWidth & ~3;
+ int height = (int)desc.dwHeight & ~3;
+ int bpp = (int)desc.ddpfPixelFormat.dwRGBBitCount;
+
+ // allocate a new dib
+ FIBITMAP *dib = FreeImage_Allocate (width, height, bpp, desc.ddpfPixelFormat.dwRBitMask,
+ desc.ddpfPixelFormat.dwGBitMask, desc.ddpfPixelFormat.dwBBitMask);
+ if (dib == NULL)
+ return NULL;
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ // Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
+ int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
+#endif
+
+ // read the file
+ int line = CalculateLine(width, bpp);
+ int filePitch = (desc.dwFlags & DDSD_PITCH) ? (int)desc.dwPitchOrLinearSize : line;
+ long delta = (long)filePitch - (long)line;
+ for (int i = 0; i < height; i++) {
+ BYTE *pixels = FreeImage_GetScanLine(dib, height - i - 1);
+ io->read_proc (pixels, 1, line, handle);
+ io->seek_proc (handle, delta, SEEK_CUR);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ for(int x = 0; x < width; x++) {
+ INPLACESWAP(pixels[FI_RGBA_RED],pixels[FI_RGBA_BLUE]);
+ pixels += bytespp;
+ }
+#endif
+ }
+
+ // enable transparency
+ FreeImage_SetTransparent (dib, (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? TRUE : FALSE);
+
+ if (!(desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && bpp == 32) {
+ // no transparency: convert to 24-bit
+ FIBITMAP *old = dib;
+ dib = FreeImage_ConvertTo24Bits (old);
+ FreeImage_Unload (old);
+ }
+ return dib;
+}
+
+template <class DECODER> static void
+LoadDXT_Helper (FreeImageIO *io, fi_handle handle, int page, int flags, void *data, FIBITMAP *dib, int width, int height, int line) {
+ typedef typename DECODER::INFO INFO;
+ typedef typename INFO::Block Block;
+
+ Block *input_buffer = new Block[(width + 3) / 4];
+ int widthRest = (int) width & 3;
+ int heightRest = (int) height & 3;
+ int inputLine = (width + 3) / 4;
+ int y = 0;
+
+ if (height >= 4) {
+ for (; y < height; y += 4) {
+ io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
+ // TODO: probably need some endian work here
+ BYTE *pbSrc = (BYTE *)input_buffer;
+ BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
+
+ if (width >= 4) {
+ for (int x = 0; x < width; x += 4) {
+ DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, 4);
+ pbSrc += INFO::bytesPerBlock;
+ pbDst += 4 * 4;
+ }
+ }
+ if (widthRest) {
+ DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, 4);
+ }
+ }
+ }
+ if (heightRest) {
+ io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
+ // TODO: probably need some endian work here
+ BYTE *pbSrc = (BYTE *)input_buffer;
+ BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
+
+ if (width >= 4) {
+ for (int x = 0; x < width; x += 4) {
+ DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, heightRest);
+ pbSrc += INFO::bytesPerBlock;
+ pbDst += 4 * 4;
+ }
+ }
+ if (widthRest) {
+ DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, heightRest);
+ }
+
+ }
+
+ delete [] input_buffer;
+}
+
+static FIBITMAP *
+LoadDXT (int type, DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ int width = (int)desc.dwWidth & ~3;
+ int height = (int)desc.dwHeight & ~3;
+
+ // allocate a 32-bit dib
+ FIBITMAP *dib = FreeImage_Allocate (width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if (dib == NULL)
+ return NULL;
+
+ int bpp = FreeImage_GetBPP (dib);
+ int line = CalculateLine (width, bpp);
+ BYTE *bits = FreeImage_GetBits (dib);
+
+ // select the right decoder
+ switch (type) {
+ case 1:
+ LoadDXT_Helper <DXT_BLOCKDECODER_1> (io, handle, page, flags, data, dib, width, height, line);
+ break;
+ case 3:
+ LoadDXT_Helper <DXT_BLOCKDECODER_3> (io, handle, page, flags, data, dib, width, height, line);
+ break;
+ case 5:
+ LoadDXT_Helper <DXT_BLOCKDECODER_5> (io, handle, page, flags, data, dib, width, height, line);
+ break;
+ }
+
+ return dib;
+}
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "DDS";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "DirectX Surface";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "dds";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-dds";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ DDSHEADER header;
+ memset(&header, 0, sizeof(header));
+ io->read_proc(&header, 1, sizeof(header), handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+ if (header.dwMagic != MAKEFOURCC ('D','D','S',' '))
+ return FALSE;
+ if (header.surfaceDesc.dwSize != sizeof (header.surfaceDesc) ||
+ header.surfaceDesc.ddpfPixelFormat.dwSize != sizeof (header.surfaceDesc.ddpfPixelFormat))
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ return NULL;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ DDSHEADER header;
+ FIBITMAP *dib = NULL;
+
+ memset(&header, 0, sizeof(header));
+ io->read_proc(&header, 1, sizeof(header), handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+ if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB) {
+ dib = LoadRGB (header.surfaceDesc, io, handle, page, flags, data);
+ }
+ else if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
+ switch (header.surfaceDesc.ddpfPixelFormat.dwFourCC) {
+ case FOURCC_DXT1:
+ dib = LoadDXT (1, header.surfaceDesc, io, handle, page, flags, data);
+ break;
+ case FOURCC_DXT3:
+ dib = LoadDXT (3, header.surfaceDesc, io, handle, page, flags, data);
+ break;
+ case FOURCC_DXT5:
+ dib = LoadDXT (5, header.surfaceDesc, io, handle, page, flags, data);
+ break;
+ }
+ }
+ return dib;
+}
+
+/*
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ return FALSE;
+}
+*/
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitDDS(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL; //Save; // not implemented (yet?)
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginEXR.cpp b/Source/FreeImage/PluginEXR.cpp
new file mode 100644
index 0000000..d1d974d
--- /dev/null
+++ b/Source/FreeImage/PluginEXR.cpp
@@ -0,0 +1,641 @@
+#if 0 // Unused by TPN
+// ==========================================================
+// EXR Loader and writer
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../OpenEXR/IlmImf/ImfIO.h"
+#include "../OpenEXR/Iex/Iex.h"
+#include "../OpenEXR/IlmImf/ImfOutputFile.h"
+#include "../OpenEXR/IlmImf/ImfInputFile.h"
+#include "../OpenEXR/IlmImf/ImfRgbaFile.h"
+#include "../OpenEXR/IlmImf/ImfChannelList.h"
+#include "../OpenEXR/IlmImf/ImfRgba.h"
+#include "../OpenEXR/IlmImf/ImfArray.h"
+#include "../OpenEXR/Half/half.h"
+
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ----------------------------------------------------------
+
+/**
+FreeImage input stream wrapper
+*/
+class C_IStream: public Imf::IStream {
+public:
+ C_IStream (FreeImageIO *io, fi_handle handle):
+ IStream(""), _io (io), _handle(handle) {}
+
+ virtual bool read (char c[/*n*/], int n);
+ virtual Imf::Int64 tellg ();
+ virtual void seekg (Imf::Int64 pos);
+ virtual void clear () {};
+
+private:
+ FreeImageIO *_io;
+ fi_handle _handle;
+};
+
+
+/**
+FreeImage output stream wrapper
+*/
+class C_OStream: public Imf::OStream {
+public:
+ C_OStream (FreeImageIO *io, fi_handle handle):
+ OStream(""), _io (io), _handle(handle) {}
+
+ virtual void write (const char c[/*n*/], int n);
+ virtual Imf::Int64 tellp ();
+ virtual void seekp (Imf::Int64 pos);
+
+private:
+ FreeImageIO *_io;
+ fi_handle _handle;
+};
+
+
+bool
+C_IStream::read (char c[/*n*/], int n) {
+ return ((unsigned)n != _io->read_proc(c, 1, n, _handle));
+}
+
+Imf::Int64
+C_IStream::tellg () {
+ return _io->tell_proc(_handle);
+}
+
+void
+C_IStream::seekg (Imf::Int64 pos) {
+ _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
+}
+
+void
+C_OStream::write (const char c[/*n*/], int n) {
+ if((unsigned)n != _io->write_proc((void*)&c[0], 1, n, _handle)) {
+ Iex::throwErrnoExc();
+ }
+}
+
+Imf::Int64
+C_OStream::tellp () {
+ return _io->tell_proc(_handle);
+}
+
+void
+C_OStream::seekp (Imf::Int64 pos) {
+ _io->seek_proc(_handle, (unsigned)pos, SEEK_SET);
+}
+
+// ----------------------------------------------------------
+
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "EXR";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "ILM OpenEXR";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "exr";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/exr";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE exr_signature[] = { 0x76, 0x2F, 0x31, 0x01 };
+ BYTE signature[] = { 0, 0, 0, 0 };
+
+ io->read_proc(signature, 1, 4, handle);
+ return (memcmp(exr_signature, signature, 4) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_FLOAT) ||
+ (type == FIT_RGBF) ||
+ (type == FIT_RGBAF)
+ );
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ bool bUseRgbaInterface = false;
+ FIBITMAP *dib = NULL;
+
+ if(handle) {
+ try {
+ // save the stream starting point
+ long stream_start = io->tell_proc(handle);
+
+ // wrap the FreeImage IO stream
+ C_IStream istream(io, handle);
+
+ // open the file
+ Imf::InputFile file(istream);
+
+ // get file info
+ const Imath::Box2i &dataWindow = file.header().dataWindow();
+ int width = dataWindow.max.x - dataWindow.min.x + 1;
+ int height = dataWindow.max.y - dataWindow.min.y + 1;
+
+ //const Imf::Compression &compression = file.header().compression();
+
+ if((dataWindow.min.x > 0) || (dataWindow.min.x < 0) || (dataWindow.min.y > 0) || (dataWindow.min.y < 0)) {
+ THROW (Iex::InputExc, "Invalid data window " <<
+ "[" << dataWindow.min.x << "," << dataWindow.min.y << "," << dataWindow.max.x << "," << dataWindow.max.y << "]");
+ }
+
+ const Imf::ChannelList &channels = file.header().channels();
+
+ // check the number of components and check for a coherent format
+
+ std::string exr_color_model;
+ Imf::PixelType pixel_type = Imf::HALF;
+ FREE_IMAGE_TYPE image_type = FIT_UNKNOWN;
+ int components = 0;
+ bool bMixedComponents = false;
+
+ for (Imf::ChannelList::ConstIterator i = channels.begin(); i != channels.end(); ++i) {
+ components++;
+ if(components == 1) {
+ exr_color_model += i.name();
+ pixel_type = i.channel().type;
+ } else {
+ exr_color_model += "/";
+ exr_color_model += i.name();
+ if (i.channel().type != pixel_type) {
+ bMixedComponents = true;
+ }
+ }
+ }
+ if(bMixedComponents) {
+ bool bHandled = false;
+ // we may have a RGBZ or RGBAZ image ...
+ if(components > 4) {
+ if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B") && channels.findChannel("A")) {
+ std::string msg = "Warning: converting color model " + exr_color_model + " to RGBA color model";
+ FreeImage_OutputMessageProc(s_format_id, msg.c_str());
+ bHandled = true;
+ }
+ }
+ else if(components > 3) {
+ if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) {
+ std::string msg = "Warning: converting color model " + exr_color_model + " to RGB color model";
+ FreeImage_OutputMessageProc(s_format_id, msg.c_str());
+ bHandled = true;
+ }
+ }
+ if(!bHandled) {
+ THROW (Iex::InputExc, "Unable to handle mixed component types (color model = " << exr_color_model << ")");
+ }
+ }
+ switch(pixel_type) {
+ case Imf::UINT:
+ THROW (Iex::InputExc, "Unsupported format: UINT");
+ break;
+ case Imf::HALF:
+ case Imf::FLOAT:
+ default:
+ break;
+ }
+ // check for supported image color models
+ if((components == 1) || (components == 2)) {
+ // if the image is gray-alpha (YA), ignore the alpha channel
+ if(channels.findChannel("Y")) {
+ image_type = FIT_FLOAT;
+ components = 1;
+ } else if(components == 1) {
+ std::string msg = "Warning: loading color model " + exr_color_model + " as Y color model";
+ FreeImage_OutputMessageProc(s_format_id, msg.c_str());
+ image_type = FIT_FLOAT;
+ }
+ } else if(components == 3) {
+ if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B")) {
+ image_type = FIT_RGBF;
+ }
+ else if(channels.findChannel("BY") && channels.findChannel("RY") && channels.findChannel("Y")) {
+ image_type = FIT_RGBF;
+ bUseRgbaInterface = true;
+ }
+ } else if(components >= 4) {
+ if(channels.findChannel("R") && channels.findChannel("G") && channels.findChannel("B") && channels.findChannel("A")) {
+ image_type = FIT_RGBAF;
+ // ignore other layers if there is more than one alpha layer
+ components = 4;
+ }
+ }
+ if(image_type == FIT_UNKNOWN) {
+ THROW (Iex::InputExc, "Unsupported color model: " << exr_color_model);
+ }
+
+ // allocate a new dib
+ dib = FreeImage_AllocateT(image_type, width, height);
+ if(!dib) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);
+
+ BYTE *bits = FreeImage_GetBits(dib); // pointer to our pixel buffer
+ size_t bytespp = sizeof(float) * components; // size of our pixel in bytes
+ unsigned pitch = FreeImage_GetPitch(dib); // size of our yStride in bytes
+
+ Imf::PixelType pixelType = Imf::FLOAT; // load as float data type;
+
+ if(bUseRgbaInterface) {
+ // use the RGBA interface
+
+ const int chunk_size = 16;
+
+ BYTE *scanline = (BYTE*)bits;
+
+ // re-open using the RGBA interface
+ io->seek_proc(handle, stream_start, SEEK_SET);
+ Imf::RgbaInputFile rgbaFile(istream);
+
+ // read the file in chunks
+ Imath::Box2i dw = dataWindow;
+ Imf::Array2D<Imf::Rgba> chunk(chunk_size, width);
+ while (dw.min.y <= dw.max.y) {
+ // read a chunk
+ rgbaFile.setFrameBuffer (&chunk[0][0] - dw.min.x - dw.min.y * width, 1, width);
+ rgbaFile.readPixels (dw.min.y, MIN(dw.min.y + chunk_size - 1, dw.max.y));
+ // fill the dib
+ const int y_max = ((dw.max.y - dw.min.y) <= chunk_size) ? (dw.max.y - dw.min.y) : chunk_size;
+ for(int y = 0; y < y_max; y++) {
+ FIRGBF *pixel = (FIRGBF*)scanline;
+ const Imf::Rgba *half_rgba = chunk[y];
+ for(int x = 0; x < width; x++) {
+ // convert from half to float
+ pixel[x].red = half_rgba[x].r;
+ pixel[x].green = half_rgba[x].g;
+ pixel[x].blue = half_rgba[x].b;
+ }
+ // next line
+ scanline += pitch;
+ }
+ // next chunk
+ dw.min.y += chunk_size;
+ }
+
+ } else {
+ // use the low level interface
+
+ // build a frame buffer (i.e. what we want on output)
+ Imf::FrameBuffer frameBuffer;
+
+ if(components == 1) {
+ frameBuffer.insert ("Y", // name
+ Imf::Slice (pixelType, // type
+ (char*)(bits), // base
+ bytespp, // xStride
+ pitch, // yStride
+ 1, 1, // x/y sampling
+ 0.0)); // fillValue
+ } else if((components == 3) || (components == 4)) {
+ const char *channel_name[4] = { "R", "G", "B", "A" };
+
+ for(int c = 0; c < components; c++) {
+ frameBuffer.insert (
+ channel_name[c], // name
+ Imf::Slice (pixelType, // type
+ (char*)(bits + c * sizeof(float)), // base
+ bytespp, // xStride
+ pitch, // yStride
+ 1, 1, // x/y sampling
+ 0.0)); // fillValue
+ }
+ }
+
+ // read the file
+ file.setFrameBuffer(frameBuffer);
+ file.readPixels(dataWindow.min.y, dataWindow.max.y);
+ }
+
+ // lastly, flip dib lines
+ FreeImage_FlipVertical(dib);
+
+ }
+ catch(Iex::BaseExc & e) {
+ if(dib != NULL) {
+ FreeImage_Unload(dib);
+ }
+ FreeImage_OutputMessageProc(s_format_id, e.what());
+ return NULL;
+ }
+ }
+
+ return dib;
+}
+
+
+/**
+Save using EXR_LC compression (works only with RGB[A]F images)
+*/
+static BOOL
+SaveAsEXR_LC(C_OStream& ostream, FIBITMAP *dib, Imf::Header& header, int width, int height) {
+ int x, y;
+ Imf::RgbaChannels rgbaChannels;
+
+ try {
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ // convert from float to half
+ Imf::Array2D<Imf::Rgba> pixels(height, width);
+ switch(image_type) {
+ case FIT_RGBF:
+ rgbaChannels = Imf::WRITE_YC;
+ for(y = 0; y < height; y++) {
+ FIRGBF *src_bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
+ for(x = 0; x < width; x++) {
+ Imf::Rgba &dst_bits = pixels[y][x];
+ dst_bits.r = src_bits[x].red;
+ dst_bits.g = src_bits[x].green;
+ dst_bits.b = src_bits[x].blue;
+ }
+ }
+ break;
+ case FIT_RGBAF:
+ rgbaChannels = Imf::WRITE_YCA;
+ for(y = 0; y < height; y++) {
+ FIRGBAF *src_bits = (FIRGBAF*)FreeImage_GetScanLine(dib, height - 1 - y);
+ for(x = 0; x < width; x++) {
+ Imf::Rgba &dst_bits = pixels[y][x];
+ dst_bits.r = src_bits[x].red;
+ dst_bits.g = src_bits[x].green;
+ dst_bits.b = src_bits[x].blue;
+ dst_bits.a = src_bits[x].alpha;
+ }
+ }
+ break;
+ default:
+ THROW (Iex::IoExc, "Bad image type");
+ break;
+ }
+
+ // write the data
+ Imf::RgbaOutputFile file(ostream, header, rgbaChannels);
+ file.setFrameBuffer (&pixels[0][0], 1, width);
+ file.writePixels (height);
+
+ return TRUE;
+
+ } catch(Iex::BaseExc & e) {
+ FreeImage_OutputMessageProc(s_format_id, e.what());
+
+ return FALSE;
+ }
+
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ const char *channel_name[4] = { "R", "G", "B", "A" };
+ BOOL bIsFlipped = FALSE;
+ half *halfData = NULL;
+
+ if(!dib || !handle) return FALSE;
+
+ try {
+ // check for EXR_LC compression and verify that the format is RGB
+ if((flags & EXR_LC) == EXR_LC) {
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if(((image_type != FIT_RGBF) && (image_type != FIT_RGBAF)) || ((flags & EXR_FLOAT) == EXR_FLOAT)) {
+ THROW (Iex::IoExc, "EXR_LC compression is only available with RGB[A]F images");
+ }
+ if((FreeImage_GetWidth(dib) % 2) || (FreeImage_GetHeight(dib) % 2)) {
+ THROW (Iex::IoExc, "EXR_LC compression only works when the width and height are a multiple of 2");
+ }
+ }
+
+ // wrap the FreeImage IO stream
+ C_OStream ostream(io, handle);
+
+ // compression
+ Imf::Compression compress;
+ if((flags & EXR_NONE) == EXR_NONE) {
+ // no compression
+ compress = Imf::NO_COMPRESSION;
+ } else if((flags & EXR_ZIP) == EXR_ZIP) {
+ // zlib compression, in blocks of 16 scan lines
+ compress = Imf::ZIP_COMPRESSION;
+ } else if((flags & EXR_PIZ) == EXR_PIZ) {
+ // piz-based wavelet compression
+ compress = Imf::PIZ_COMPRESSION;
+ } else if((flags & EXR_PXR24) == EXR_PXR24) {
+ // lossy 24-bit float compression
+ compress = Imf::PXR24_COMPRESSION;
+ } else if((flags & EXR_B44) == EXR_B44) {
+ // lossy 44% float compression
+ compress = Imf::B44_COMPRESSION;
+ } else {
+ // default value
+ compress = Imf::PIZ_COMPRESSION;
+ }
+
+ // create the header
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+ int dx = 0, dy = 0;
+
+ Imath::Box2i dataWindow (Imath::V2i (0, 0), Imath::V2i (width - 1, height - 1));
+ Imath::Box2i displayWindow (Imath::V2i (-dx, -dy), Imath::V2i (width - dx - 1, height - dy - 1));
+
+ Imf::Header header = Imf::Header(displayWindow, dataWindow, 1,
+ Imath::V2f(0,0), 1,
+ Imf::INCREASING_Y, compress);
+
+ // check for EXR_LC compression
+ if((flags & EXR_LC) == EXR_LC) {
+ return SaveAsEXR_LC(ostream, dib, header, width, height);
+ }
+
+ // output pixel type
+ Imf::PixelType pixelType;
+ if((flags & EXR_FLOAT) == EXR_FLOAT) {
+ pixelType = Imf::FLOAT; // save as float data type
+ } else {
+ // default value
+ pixelType = Imf::HALF; // save as half data type
+ }
+
+ // check the data type and number of channels
+ int components = 0;
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ switch(image_type) {
+ case FIT_FLOAT:
+ components = 1;
+ // insert luminance channel
+ header.channels().insert ("Y", Imf::Channel(pixelType));
+ break;
+ case FIT_RGBF:
+ components = 3;
+ for(int c = 0; c < components; c++) {
+ // insert R, G and B channels
+ header.channels().insert (channel_name[c], Imf::Channel(pixelType));
+ }
+ break;
+ case FIT_RGBAF:
+ components = 4;
+ for(int c = 0; c < components; c++) {
+ // insert R, G, B and A channels
+ header.channels().insert (channel_name[c], Imf::Channel(pixelType));
+ }
+ break;
+ default:
+ THROW (Iex::ArgExc, "Cannot save: invalid data type.\nConvert the image to float before saving as OpenEXR.");
+ }
+
+ // build a frame buffer (i.e. what we have on input)
+ Imf::FrameBuffer frameBuffer;
+
+ BYTE *bits = NULL; // pointer to our pixel buffer
+ size_t bytespp = 0; // size of our pixel in bytes
+ size_t bytespc = 0; // size of our pixel component in bytes
+ unsigned pitch = 0; // size of our yStride in bytes
+
+
+ if(pixelType == Imf::HALF) {
+ // convert from float to half
+ halfData = new half[width * height * components];
+ if(!halfData) THROW (Iex::NullExc, FI_MSG_ERROR_MEMORY);
+ for(int y = 0; y < height; y++) {
+ float *src_bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
+ half *dst_bits = halfData + y * width * components;
+ for(int x = 0; x < width; x++) {
+ for(int c = 0; c < components; c++) {
+ dst_bits[c] = src_bits[c];
+ }
+ src_bits += components;
+ dst_bits += components;
+ }
+ }
+ bits = (BYTE*)halfData;
+ bytespc = sizeof(half);
+ bytespp = sizeof(half) * components;
+ pitch = sizeof(half) * width * components;
+ } else if(pixelType == Imf::FLOAT) {
+ // invert dib scanlines
+ bIsFlipped = FreeImage_FlipVertical(dib);
+
+ bits = FreeImage_GetBits(dib);
+ bytespc = sizeof(float);
+ bytespp = sizeof(float) * components;
+ pitch = FreeImage_GetPitch(dib);
+ }
+
+ if(image_type == FIT_FLOAT) {
+ frameBuffer.insert ("Y", // name
+ Imf::Slice (pixelType, // type
+ (char*)(bits), // base
+ bytespp, // xStride
+ pitch)); // yStride
+ } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) {
+ for(int c = 0; c < components; c++) {
+ char *channel_base = (char*)(bits) + c*bytespc;
+ frameBuffer.insert (channel_name[c],// name
+ Imf::Slice (pixelType, // type
+ channel_base, // base
+ bytespp, // xStride
+ pitch)); // yStride
+ }
+ }
+
+ // write the data
+ Imf::OutputFile file (ostream, header);
+ file.setFrameBuffer (frameBuffer);
+ file.writePixels (height);
+
+ if(halfData != NULL) delete[] halfData;
+ if(bIsFlipped) {
+ // invert dib scanlines
+ FreeImage_FlipVertical(dib);
+ }
+
+ return TRUE;
+
+ } catch(Iex::BaseExc & e) {
+ if(halfData != NULL) delete[] halfData;
+ if(bIsFlipped) {
+ // invert dib scanlines
+ FreeImage_FlipVertical(dib);
+ }
+
+ FreeImage_OutputMessageProc(s_format_id, e.what());
+
+ return FALSE;
+ }
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitEXR(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
+#endif
diff --git a/Source/FreeImage/PluginG3.cpp b/Source/FreeImage/PluginG3.cpp
new file mode 100644
index 0000000..a20df3c
--- /dev/null
+++ b/Source/FreeImage/PluginG3.cpp
@@ -0,0 +1,433 @@
+// ==========================================================
+// G3 Fax Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Petr Pytelka (pyta@lightcomp.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "../LibTIFF/tiffiop.h"
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Constant/Macro declarations
+// ==========================================================
+
+#define G3_DEFAULT_WIDTH 1728
+
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+
+// ==========================================================
+// libtiff interface
+// ==========================================================
+
+static tsize_t
+_g3ReadProc(thandle_t fd, tdata_t buf, tsize_t size) {
+ // returns an error when reading the TIFF header
+ return 0;
+}
+
+static tsize_t
+_g3WriteProc(thandle_t fd, tdata_t buf, tsize_t size) {
+ // returns ok when writing the TIFF header
+ return size;
+}
+
+static toff_t
+_g3SeekProc(thandle_t fd, toff_t off, int whence) {
+ return 0;
+}
+
+static int
+_g3CloseProc(thandle_t fd) {
+ return 0;
+}
+
+static toff_t
+_g3SizeProc(thandle_t fd) {
+ return 0;
+}
+
+static int
+_g3MapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) {
+ return 0;
+}
+
+static void
+_g3UnmapProc(thandle_t fd, tdata_t base, toff_t size) {
+}
+
+// --------------------------------------------------------------
+
+static toff_t
+G3GetFileSize(FreeImageIO *io, fi_handle handle) {
+ long currentPos = io->tell_proc(handle);
+ io->seek_proc(handle, 0, SEEK_END);
+ long fileSize = io->tell_proc(handle);
+ io->seek_proc(handle, currentPos, SEEK_SET);
+ return fileSize;
+}
+
+static BOOL
+G3ReadFile(FreeImageIO *io, fi_handle handle, tidata_t tif_rawdata, tsize_t tif_rawdatasize) {
+ return ((tsize_t)(io->read_proc(tif_rawdata, tif_rawdatasize, 1, handle) * tif_rawdatasize) == tif_rawdatasize);
+}
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static int
+copyFaxFile(FreeImageIO *io, fi_handle handle, TIFF* tifin, uint32 xsize, int stretch, FIMEMORY *memory) {
+ BYTE *rowbuf = NULL;
+ BYTE *refbuf = NULL;
+ uint32 row;
+ uint16 badrun;
+ uint16 badfaxrun;
+ uint32 badfaxlines;
+ int ok;
+
+ try {
+
+ uint32 linesize = TIFFhowmany8(xsize);
+ rowbuf = (BYTE*) _TIFFmalloc(linesize);
+ refbuf = (BYTE*) _TIFFmalloc(linesize);
+ if (rowbuf == NULL || refbuf == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ tifin->tif_rawdatasize = G3GetFileSize(io, handle);
+ tifin->tif_rawdata = (tidata_t) _TIFFmalloc(tifin->tif_rawdatasize);
+ if (tifin->tif_rawdata == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ if(!G3ReadFile(io, handle, tifin->tif_rawdata, tifin->tif_rawdatasize)) {
+ throw "Read error at scanline 0";
+ }
+ tifin->tif_rawcp = tifin->tif_rawdata;
+ tifin->tif_rawcc = tifin->tif_rawdatasize;
+
+ (*tifin->tif_setupdecode)(tifin);
+ (*tifin->tif_predecode)(tifin, (tsample_t) 0);
+ tifin->tif_row = 0;
+ badfaxlines = 0;
+ badfaxrun = 0;
+
+ _TIFFmemset(refbuf, 0, linesize);
+ row = 0;
+ badrun = 0; // current run of bad lines
+ while (tifin->tif_rawcc > 0) {
+ ok = (*tifin->tif_decoderow)(tifin, rowbuf, linesize, 0);
+ if (!ok) {
+ badfaxlines++;
+ badrun++;
+ // regenerate line from previous good line
+ _TIFFmemcpy(rowbuf, refbuf, linesize);
+ } else {
+ if (badrun > badfaxrun)
+ badfaxrun = badrun;
+ badrun = 0;
+ _TIFFmemcpy(refbuf, rowbuf, linesize);
+ }
+ tifin->tif_row++;
+
+ FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
+ row++;
+ if (stretch) {
+ FreeImage_WriteMemory(rowbuf, linesize, 1, memory);
+ row++;
+ }
+ }
+ if (badrun > badfaxrun)
+ badfaxrun = badrun;
+
+ _TIFFfree(tifin->tif_rawdata);
+ tifin->tif_rawdata = NULL;
+
+ _TIFFfree(rowbuf);
+ _TIFFfree(refbuf);
+
+ /*
+ if (verbose) {
+ fprintf(stderr, "%d rows in input\n", rows);
+ fprintf(stderr, "%ld total bad rows\n", (long) badfaxlines);
+ fprintf(stderr, "%d max consecutive bad rows\n", badfaxrun);
+ }
+ */
+
+ } catch(const char *message) {
+ if(rowbuf) _TIFFfree(rowbuf);
+ if(refbuf) _TIFFfree(refbuf);
+ if(tifin->tif_rawdata) {
+ _TIFFfree(tifin->tif_rawdata);
+ tifin->tif_rawdata = NULL;
+ }
+ FreeImage_OutputMessageProc(s_format_id, message);
+
+ return -1;
+ }
+
+ return (row);
+}
+
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "G3";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Raw fax format CCITT G.3";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "g3";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL; // there is now reasonable regexp for raw G3
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/fax-g3";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ TIFF *faxTIFF = NULL;
+ FIBITMAP *dib = NULL;
+ FIMEMORY *memory = NULL;
+
+ //int verbose = 0;
+ int stretch = 0;
+ int rows;
+ float resX = 204.0;
+ float resY = 196.0;
+
+ uint32 xsize = G3_DEFAULT_WIDTH;
+ int compression_in = COMPRESSION_CCITTFAX3;
+ int fillorder_in = FILLORDER_LSB2MSB;
+ uint32 group3options_in = 0; // 1d-encoded
+ uint32 group4options_in = 0; // compressed
+ int photometric_in = PHOTOMETRIC_MINISWHITE;
+
+ if(handle==NULL) return NULL;
+
+ try {
+ // set default load options
+
+ compression_in = COMPRESSION_CCITTFAX3; // input is g3-encoded
+ group3options_in &= ~GROUP3OPT_2DENCODING; // input is 1d-encoded (g3 only)
+ fillorder_in = FILLORDER_MSB2LSB; // input has msb-to-lsb fillorder
+
+ /*
+ Original input-related fax2tiff options
+
+ while ((c = getopt(argc, argv, "R:X:o:1234ABLMPUW5678abcflmprsuvwz?")) != -1) {
+ switch (c) {
+ // input-related options
+ case '3': // input is g3-encoded
+ compression_in = COMPRESSION_CCITTFAX3;
+ break;
+ case '4': // input is g4-encoded
+ compression_in = COMPRESSION_CCITTFAX4;
+ break;
+ case 'U': // input is uncompressed (g3 and g4)
+ group3options_in |= GROUP3OPT_UNCOMPRESSED;
+ group4options_in |= GROUP4OPT_UNCOMPRESSED;
+ break;
+ case '1': // input is 1d-encoded (g3 only)
+ group3options_in &= ~GROUP3OPT_2DENCODING;
+ break;
+ case '2': // input is 2d-encoded (g3 only)
+ group3options_in |= GROUP3OPT_2DENCODING;
+ break;
+ case 'P': // input has not-aligned EOL (g3 only)
+ group3options_in &= ~GROUP3OPT_FILLBITS;
+ break;
+ case 'A': // input has aligned EOL (g3 only)
+ group3options_in |= GROUP3OPT_FILLBITS;
+ break;
+ case 'W': // input has 0 mean white
+ photometric_in = PHOTOMETRIC_MINISWHITE;
+ break;
+ case 'B': // input has 0 mean black
+ photometric_in = PHOTOMETRIC_MINISBLACK;
+ break;
+ case 'L': // input has lsb-to-msb fillorder
+ fillorder_in = FILLORDER_LSB2MSB;
+ break;
+ case 'M': // input has msb-to-lsb fillorder
+ fillorder_in = FILLORDER_MSB2LSB;
+ break;
+ case 'R': // input resolution
+ resY = (float) atof(optarg);
+ break;
+ case 'X': // input width
+ xsize = (uint32) atoi(optarg);
+ break;
+
+ // output-related options
+ case 's': // stretch image by dup'ng scanlines
+ stretch = 1;
+ break;
+ case 'v': // -v for info
+ verbose++;
+ break;
+ }
+ }
+
+ */
+
+ // open a temporary memory buffer to save decoded scanlines
+ memory = FreeImage_OpenMemory();
+ if(!memory) throw FI_MSG_ERROR_MEMORY;
+
+ // wrap the raw fax file
+ faxTIFF = TIFFClientOpen("(FakeInput)", "w",
+ // TIFFClientOpen() fails if we don't set existing value here
+ NULL,
+ _g3ReadProc, _g3WriteProc,
+ _g3SeekProc, _g3CloseProc,
+ _g3SizeProc, _g3MapProc,
+ _g3UnmapProc);
+
+ if (faxTIFF == NULL) {
+ throw "Can not create fake input file";
+ }
+ TIFFSetMode(faxTIFF, O_RDONLY);
+ TIFFSetField(faxTIFF, TIFFTAG_IMAGEWIDTH, xsize);
+ TIFFSetField(faxTIFF, TIFFTAG_SAMPLESPERPIXEL, 1);
+ TIFFSetField(faxTIFF, TIFFTAG_BITSPERSAMPLE, 1);
+ TIFFSetField(faxTIFF, TIFFTAG_FILLORDER, fillorder_in);
+ TIFFSetField(faxTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+ TIFFSetField(faxTIFF, TIFFTAG_PHOTOMETRIC, photometric_in);
+ TIFFSetField(faxTIFF, TIFFTAG_YRESOLUTION, resY);
+ TIFFSetField(faxTIFF, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
+
+ // NB: this must be done after directory info is setup
+ TIFFSetField(faxTIFF, TIFFTAG_COMPRESSION, compression_in);
+ if (compression_in == COMPRESSION_CCITTFAX3)
+ TIFFSetField(faxTIFF, TIFFTAG_GROUP3OPTIONS, group3options_in);
+ else if (compression_in == COMPRESSION_CCITTFAX4)
+ TIFFSetField(faxTIFF, TIFFTAG_GROUP4OPTIONS, group4options_in);
+
+ resX = 204;
+ if (!stretch) {
+ TIFFGetField(faxTIFF, TIFFTAG_YRESOLUTION, &resY);
+ } else {
+ resY = 196;
+ }
+
+ // decode the raw fax data
+ rows = copyFaxFile(io, handle, faxTIFF, xsize, stretch, memory);
+ if(rows <= 0) throw "Error when decoding raw fax file : check the decoder options";
+
+
+ // allocate the output dib
+ dib = FreeImage_Allocate(xsize, rows, 1);
+ unsigned pitch = FreeImage_GetPitch(dib);
+ uint32 linesize = TIFFhowmany8(xsize);
+
+ // fill the bitmap structure ...
+ // ... palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if(photometric_in == PHOTOMETRIC_MINISWHITE) {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
+ } else {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ }
+ // ... resolution
+ FreeImage_SetDotsPerMeterX(dib, (unsigned)(resX/0.0254000 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned)(resY/0.0254000 + 0.5));
+
+ // read the decoded scanline and fill the bitmap data
+ FreeImage_SeekMemory(memory, 0, SEEK_SET);
+ BYTE *bits = FreeImage_GetScanLine(dib, rows - 1);
+ for(int k = 0; k < rows; k++) {
+ FreeImage_ReadMemory(bits, linesize, 1, memory);
+ bits -= pitch;
+ }
+
+ // free the TIFF wrapper
+ TIFFClose(faxTIFF);
+
+ // free the memory buffer
+ FreeImage_CloseMemory(memory);
+
+ } catch(const char *message) {
+ if(memory) FreeImage_CloseMemory(memory);
+ if(faxTIFF) TIFFClose(faxTIFF);
+ if(dib) FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(s_format_id, message);
+ return NULL;
+ }
+
+ return dib;
+
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitG3(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = NULL;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginGIF.cpp b/Source/FreeImage/PluginGIF.cpp
new file mode 100644
index 0000000..4189e5b
--- /dev/null
+++ b/Source/FreeImage/PluginGIF.cpp
@@ -0,0 +1,1398 @@
+// ==========================================================
+// GIF Loader and Writer
+//
+// Design and implementation by
+// - Ryan Rubley <ryan@lostreality.org>
+// - Raphaël Gaquer <raphael.gaquer@alcer.com>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../Metadata/FreeImageTag.h"
+
+// ==========================================================
+// Metadata declarations
+// ==========================================================
+
+#define GIF_DISPOSAL_UNSPECIFIED 0
+#define GIF_DISPOSAL_LEAVE 1
+#define GIF_DISPOSAL_BACKGROUND 2
+#define GIF_DISPOSAL_PREVIOUS 3
+
+// ==========================================================
+// Constant/Typedef declarations
+// ==========================================================
+
+
+struct GIFinfo {
+ BOOL read;
+ //only really used when reading
+ size_t global_color_table_offset;
+ int global_color_table_size;
+ BYTE background_color;
+ std::vector<size_t> application_extension_offsets;
+ std::vector<size_t> comment_extension_offsets;
+ std::vector<size_t> graphic_control_extension_offsets;
+ std::vector<size_t> image_descriptor_offsets;
+
+ GIFinfo() : read(0), global_color_table_offset(0), global_color_table_size(0), background_color(0)
+ {
+ }
+};
+
+struct PageInfo {
+ PageInfo(int d, int l, int t, int w, int h) {
+ disposal_method = d; left = (WORD)l; top = (WORD)t; width = (WORD)w; height = (WORD)h;
+ }
+ int disposal_method;
+ WORD left, top, width, height;
+};
+
+//GIF defines a max of 12 bits per code
+#define MAX_LZW_CODE 4096
+
+class StringTable
+{
+public:
+ StringTable();
+ ~StringTable();
+ void Initialize(int minCodeSize);
+ BYTE *FillInputBuffer(int len);
+ void CompressStart(int bpp, int width);
+ int CompressEnd(BYTE *buf); //0-4 bytes
+ bool Compress(BYTE *buf, int *len);
+ bool Decompress(BYTE *buf, int *len);
+ void Done(void);
+
+protected:
+ bool m_done;
+
+ int m_minCodeSize, m_clearCode, m_endCode, m_nextCode;
+
+ int m_bpp, m_slack; //Compressor information
+
+ int m_prefix; //Compressor state variable
+ int m_codeSize, m_codeMask; //Compressor/Decompressor state variables
+ int m_oldCode; //Decompressor state variable
+ int m_partial, m_partialSize; //Compressor/Decompressor bit buffer
+
+ int firstPixelPassed; // A specific flag that indicates if the first pixel
+ // of the whole image had already been read
+
+ std::string m_strings[MAX_LZW_CODE]; //This is what is really the "string table" data for the Decompressor
+ int* m_strmap;
+
+ //input buffer
+ BYTE *m_buffer;
+ int m_bufferSize, m_bufferRealSize, m_bufferPos, m_bufferShift;
+
+ void ClearCompressorTable(void);
+ void ClearDecompressorTable(void);
+};
+
+#define GIF_PACKED_LSD_HAVEGCT 0x80
+#define GIF_PACKED_LSD_COLORRES 0x70
+#define GIF_PACKED_LSD_GCTSORTED 0x08
+#define GIF_PACKED_LSD_GCTSIZE 0x07
+#define GIF_PACKED_ID_HAVELCT 0x80
+#define GIF_PACKED_ID_INTERLACED 0x40
+#define GIF_PACKED_ID_LCTSORTED 0x20
+#define GIF_PACKED_ID_RESERVED 0x18
+#define GIF_PACKED_ID_LCTSIZE 0x07
+#define GIF_PACKED_GCE_RESERVED 0xE0
+#define GIF_PACKED_GCE_DISPOSAL 0x1C
+#define GIF_PACKED_GCE_WAITINPUT 0x02
+#define GIF_PACKED_GCE_HAVETRANS 0x01
+
+#define GIF_BLOCK_IMAGE_DESCRIPTOR 0x2C
+#define GIF_BLOCK_EXTENSION 0x21
+#define GIF_BLOCK_TRAILER 0x3B
+
+#define GIF_EXT_PLAINTEXT 0x01
+#define GIF_EXT_GRAPHIC_CONTROL 0xF9
+#define GIF_EXT_COMMENT 0xFE
+#define GIF_EXT_APPLICATION 0xFF
+
+#define GIF_INTERLACE_PASSES 4
+static int g_GifInterlaceOffset[GIF_INTERLACE_PASSES] = {0, 4, 2, 1};
+static int g_GifInterlaceIncrement[GIF_INTERLACE_PASSES] = {8, 8, 4, 2};
+
+// ==========================================================
+// Helpers Functions
+// ==========================================================
+
+static BOOL
+FreeImage_SetMetadataEx(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, WORD id, FREE_IMAGE_MDTYPE type, DWORD count, DWORD length, const void *value)
+{
+ BOOL bResult = FALSE;
+ FITAG *tag = FreeImage_CreateTag();
+ if(tag) {
+ FreeImage_SetTagKey(tag, key);
+ FreeImage_SetTagID(tag, id);
+ FreeImage_SetTagType(tag, type);
+ FreeImage_SetTagCount(tag, count);
+ FreeImage_SetTagLength(tag, length);
+ FreeImage_SetTagValue(tag, value);
+ if(model == FIMD_ANIMATION) {
+ TagLib& s = TagLib::instance();
+ // get the tag description
+ const char *description = s.getTagDescription(TagLib::ANIMATION, id);
+ FreeImage_SetTagDescription(tag, description);
+ }
+ // store the tag
+ bResult = FreeImage_SetMetadata(model, dib, key, tag);
+ FreeImage_DeleteTag(tag);
+ }
+ return bResult;
+}
+
+static BOOL
+FreeImage_GetMetadataEx(FREE_IMAGE_MDMODEL model, FIBITMAP *dib, const char *key, FREE_IMAGE_MDTYPE type, FITAG **tag)
+{
+ if( FreeImage_GetMetadata(model, dib, key, tag) ) {
+ if( FreeImage_GetTagType(*tag) == type ) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+StringTable::StringTable()
+{
+ m_buffer = NULL;
+ firstPixelPassed = 0; // Still no pixel read
+ // Maximum number of entries in the map is MAX_LZW_CODE * 256
+ // (aka 2**12 * 2**8 => a 20 bits key)
+ // This Map could be optmized to only handle MAX_LZW_CODE * 2**(m_bpp)
+ m_strmap = (int*)new int[1<<20];
+}
+
+StringTable::~StringTable()
+{
+ if( m_buffer != NULL ) {
+ delete [] m_buffer;
+ }
+ if( m_strmap != NULL ) {
+ delete [] m_strmap;
+ m_strmap = NULL;
+ }
+}
+
+void StringTable::Initialize(int minCodeSize)
+{
+ m_done = false;
+
+ m_bpp = 8;
+ m_minCodeSize = minCodeSize;
+ m_clearCode = 1 << m_minCodeSize;
+ if(m_clearCode > MAX_LZW_CODE) {
+ m_clearCode = MAX_LZW_CODE;
+ }
+ m_endCode = m_clearCode + 1;
+
+ m_partial = 0;
+ m_partialSize = 0;
+
+ m_bufferSize = 0;
+ ClearCompressorTable();
+ ClearDecompressorTable();
+}
+
+BYTE *StringTable::FillInputBuffer(int len)
+{
+ if( m_buffer == NULL ) {
+ m_buffer = new BYTE[len];
+ m_bufferRealSize = len;
+ } else if( len > m_bufferRealSize ) {
+ delete [] m_buffer;
+ m_buffer = new BYTE[len];
+ m_bufferRealSize = len;
+ }
+ m_bufferSize = len;
+ m_bufferPos = 0;
+ m_bufferShift = 8 - m_bpp;
+ return m_buffer;
+}
+
+void StringTable::CompressStart(int bpp, int width)
+{
+ m_bpp = bpp;
+ m_slack = (8 - ((width * bpp) % 8)) % 8;
+
+ m_partial |= m_clearCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ ClearCompressorTable();
+}
+
+int StringTable::CompressEnd(BYTE *buf)
+{
+ int len = 0;
+
+ //output code for remaining prefix
+ m_partial |= m_prefix << m_partialSize;
+ m_partialSize += m_codeSize;
+ while( m_partialSize >= 8 ) {
+ *buf++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ len++;
+ }
+
+ //add the end of information code and flush the entire buffer out
+ m_partial |= m_endCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ while( m_partialSize > 0 ) {
+ *buf++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ len++;
+ }
+
+ //most this can be is 4 bytes. 7 bits in m_partial to start + 12 for the
+ //last code + 12 for the end code = 31 bits total.
+ return len;
+}
+
+bool StringTable::Compress(BYTE *buf, int *len)
+{
+ if( m_bufferSize == 0 || m_done ) {
+ return false;
+ }
+
+ int mask = (1 << m_bpp) - 1;
+ BYTE *bufpos = buf;
+ while( m_bufferPos < m_bufferSize ) {
+ //get the current pixel value
+ char ch = (char)((m_buffer[m_bufferPos] >> m_bufferShift) & mask);
+
+ // The next prefix is :
+ // <the previous LZW code (on 12 bits << 8)> | <the code of the current pixel (on 8 bits)>
+ int nextprefix = (((m_prefix)<<8)&0xFFF00) + (ch & 0x000FF);
+ if(firstPixelPassed) {
+
+ if( m_strmap[nextprefix] > 0) {
+ m_prefix = m_strmap[nextprefix];
+ } else {
+ m_partial |= m_prefix << m_partialSize;
+ m_partialSize += m_codeSize;
+ //grab full bytes for the output buffer
+ while( m_partialSize >= 8 && bufpos - buf < *len ) {
+ *bufpos++ = (BYTE)m_partial;
+ m_partial >>= 8;
+ m_partialSize -= 8;
+ }
+
+ //add the code to the "table map"
+ m_strmap[nextprefix] = m_nextCode;
+
+ //increment the next highest valid code, increase the code size
+ if( m_nextCode == (1 << m_codeSize) ) {
+ m_codeSize++;
+ }
+ m_nextCode++;
+
+ //if we're out of codes, restart the string table
+ if( m_nextCode == MAX_LZW_CODE ) {
+ m_partial |= m_clearCode << m_partialSize;
+ m_partialSize += m_codeSize;
+ ClearCompressorTable();
+ }
+
+ // Only keep the 8 lowest bits (prevent problems with "negative chars")
+ m_prefix = ch & 0x000FF;
+ }
+
+ //increment to the next pixel
+ if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) {
+ m_bufferShift -= m_bpp;
+ } else {
+ m_bufferPos++;
+ m_bufferShift = 8 - m_bpp;
+ }
+
+ //jump out here if the output buffer is full
+ if( bufpos - buf == *len ) {
+ return true;
+ }
+
+ } else {
+ // Specific behavior for the first pixel of the whole image
+
+ firstPixelPassed=1;
+ // Only keep the 8 lowest bits (prevent problems with "negative chars")
+ m_prefix = ch & 0x000FF;
+
+ //increment to the next pixel
+ if( m_bufferShift > 0 && !(m_bufferPos + 1 == m_bufferSize && m_bufferShift <= m_slack) ) {
+ m_bufferShift -= m_bpp;
+ } else {
+ m_bufferPos++;
+ m_bufferShift = 8 - m_bpp;
+ }
+
+ //jump out here if the output buffer is full
+ if( bufpos - buf == *len ) {
+ return true;
+ }
+ }
+ }
+
+ m_bufferSize = 0;
+ *len = (int)(bufpos - buf);
+
+ return true;
+}
+
+bool StringTable::Decompress(BYTE *buf, int *len)
+{
+ if( m_bufferSize == 0 || m_done ) {
+ return false;
+ }
+
+ BYTE *bufpos = buf;
+ for( ; m_bufferPos < m_bufferSize; m_bufferPos++ ) {
+ m_partial |= (int)m_buffer[m_bufferPos] << m_partialSize;
+ m_partialSize += 8;
+ while( m_partialSize >= m_codeSize ) {
+ int code = m_partial & m_codeMask;
+ m_partial >>= m_codeSize;
+ m_partialSize -= m_codeSize;
+
+ if( code > m_nextCode || (m_nextCode == MAX_LZW_CODE && code != m_clearCode) || code == m_endCode ) {
+ m_done = true;
+ *len = (int)(bufpos - buf);
+ return true;
+ }
+ if( code == m_clearCode ) {
+ ClearDecompressorTable();
+ continue;
+ }
+
+ //add new string to string table, if not the first pass since a clear code
+ if( m_oldCode != MAX_LZW_CODE ) {
+ m_strings[m_nextCode] = m_strings[m_oldCode] + m_strings[code == m_nextCode ? m_oldCode : code][0];
+ }
+
+ if( (int)m_strings[code].size() > *len - (bufpos - buf) ) {
+ //out of space, stuff the code back in for next time
+ m_partial <<= m_codeSize;
+ m_partialSize += m_codeSize;
+ m_partial |= code;
+ m_bufferPos++;
+ *len = (int)(bufpos - buf);
+ return true;
+ }
+
+ //output the string into the buffer
+ memcpy(bufpos, m_strings[code].data(), m_strings[code].size());
+ bufpos += m_strings[code].size();
+
+ //increment the next highest valid code, add a bit to the mask if we need to increase the code size
+ if( m_oldCode != MAX_LZW_CODE && m_nextCode < MAX_LZW_CODE ) {
+ if( ++m_nextCode < MAX_LZW_CODE ) {
+ if( (m_nextCode & m_codeMask) == 0 ) {
+ m_codeSize++;
+ m_codeMask |= m_nextCode;
+ }
+ }
+ }
+
+ m_oldCode = code;
+ }
+ }
+
+ m_bufferSize = 0;
+ *len = (int)(bufpos - buf);
+
+ return true;
+}
+
+void StringTable::Done(void)
+{
+ m_done = true;
+}
+
+void StringTable::ClearCompressorTable(void)
+{
+ if(m_strmap) {
+ memset(m_strmap, 0xFF, sizeof(unsigned int)*(1<<20));
+ }
+ m_nextCode = m_endCode + 1;
+
+ m_prefix = 0;
+ m_codeSize = m_minCodeSize + 1;
+}
+
+void StringTable::ClearDecompressorTable(void)
+{
+ for( int i = 0; i < m_clearCode; i++ ) {
+ m_strings[i].resize(1);
+ m_strings[i][0] = (char)i;
+ }
+ m_nextCode = m_endCode + 1;
+
+ m_codeSize = m_minCodeSize + 1;
+ m_codeMask = (1 << m_codeSize) - 1;
+ m_oldCode = MAX_LZW_CODE;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "GIF";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Graphics Interchange Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "gif";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^GIF";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/gif";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ char buf[6];
+ if( io->read_proc(buf, 6, 1, handle) < 1 ) {
+ return FALSE;
+ }
+
+ BOOL bResult = FALSE;
+ if( !strncmp(buf, "GIF", 3) ) {
+ if( buf[3] >= '0' && buf[3] <= '9' && buf[4] >= '0' && buf[4] <= '9' && buf[5] >= 'a' && buf[5] <= 'z' ) {
+ bResult = TRUE;
+ }
+ }
+
+ io->seek_proc(handle, -6, SEEK_CUR);
+
+ return bResult;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (depth == 1) ||
+ (depth == 4) ||
+ (depth == 8);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static void *DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ GIFinfo *info = new GIFinfo;
+ if( info == NULL ) {
+ return NULL;
+ }
+
+ // 25/02/2008 MDA: Not safe to memset GIFinfo structure with VS 2008 (safe iterators),
+ // perform initialization in constructor instead.
+ // memset(info, 0, sizeof(GIFinfo));
+
+ info->read = read;
+ if( read ) {
+ try {
+ //Header
+ if( !Validate(io, handle) ) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+ io->seek_proc(handle, 6, SEEK_CUR);
+
+ //Logical Screen Descriptor
+ io->seek_proc(handle, 4, SEEK_CUR);
+ BYTE packed;
+ if( io->read_proc(&packed, 1, 1, handle) < 1 ) {
+ throw "EOF reading Logical Screen Descriptor";
+ }
+ if( io->read_proc(&info->background_color, 1, 1, handle) < 1 ) {
+ throw "EOF reading Logical Screen Descriptor";
+ }
+ io->seek_proc(handle, 1, SEEK_CUR);
+
+ //Global Color Table
+ if( packed & GIF_PACKED_LSD_HAVEGCT ) {
+ info->global_color_table_offset = io->tell_proc(handle);
+ info->global_color_table_size = 2 << (packed & GIF_PACKED_LSD_GCTSIZE);
+ io->seek_proc(handle, 3 * info->global_color_table_size, SEEK_CUR);
+ }
+
+ //Scan through all the rest of the blocks, saving offsets
+ size_t gce_offset = 0;
+ BYTE block = 0;
+ while( block != GIF_BLOCK_TRAILER ) {
+ if( io->read_proc(&block, 1, 1, handle) < 1 ) {
+ throw "EOF reading blocks";
+ }
+ if( block == GIF_BLOCK_IMAGE_DESCRIPTOR ) {
+ info->image_descriptor_offsets.push_back(io->tell_proc(handle));
+ //GCE may be 0, meaning no GCE preceded this ID
+ info->graphic_control_extension_offsets.push_back(gce_offset);
+ gce_offset = 0;
+
+ io->seek_proc(handle, 8, SEEK_CUR);
+ if( io->read_proc(&packed, 1, 1, handle) < 1 ) {
+ throw "EOF reading Image Descriptor";
+ }
+
+ //Local Color Table
+ if( packed & GIF_PACKED_ID_HAVELCT ) {
+ io->seek_proc(handle, 3 * (2 << (packed & GIF_PACKED_ID_LCTSIZE)), SEEK_CUR);
+ }
+
+ //LZW Minimum Code Size
+ io->seek_proc(handle, 1, SEEK_CUR);
+ } else if( block == GIF_BLOCK_EXTENSION ) {
+ BYTE ext;
+ if( io->read_proc(&ext, 1, 1, handle) < 1 ) {
+ throw "EOF reading extension";
+ }
+
+ if( ext == GIF_EXT_GRAPHIC_CONTROL ) {
+ //overwrite previous offset if more than one GCE found before an ID
+ gce_offset = io->tell_proc(handle);
+ } else if( ext == GIF_EXT_COMMENT ) {
+ info->comment_extension_offsets.push_back(io->tell_proc(handle));
+ } else if( ext == GIF_EXT_APPLICATION ) {
+ info->application_extension_offsets.push_back(io->tell_proc(handle));
+ }
+ } else if( block == GIF_BLOCK_TRAILER ) {
+ continue;
+ } else {
+ throw "Invalid GIF block found";
+ }
+
+ //Data Sub-blocks
+ BYTE len;
+ if( io->read_proc(&len, 1, 1, handle) < 1 ) {
+ throw "EOF reading sub-block";
+ }
+ while( len != 0 ) {
+ io->seek_proc(handle, len, SEEK_CUR);
+ if( io->read_proc(&len, 1, 1, handle) < 1 ) {
+ throw "EOF reading sub-block";
+ }
+ }
+ }
+ } catch (const char *msg) {
+ FreeImage_OutputMessageProc(s_format_id, msg);
+ delete info;
+ return NULL;
+ }
+ } else {
+ //Header
+ io->write_proc((void *)"GIF89a", 6, 1, handle);
+ }
+
+ return info;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+ if( data == NULL ) {
+ return;
+ }
+ GIFinfo *info = (GIFinfo *)data;
+
+ if( !info->read ) {
+ //Trailer
+ BYTE b = GIF_BLOCK_TRAILER;
+ io->write_proc(&b, 1, 1, handle);
+ }
+
+ delete info;
+}
+
+static int DLL_CALLCONV
+PageCount(FreeImageIO *io, fi_handle handle, void *data) {
+ if( data == NULL ) {
+ return 0;
+ }
+ GIFinfo *info = (GIFinfo *)data;
+
+ return (int) info->image_descriptor_offsets.size();
+}
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if( data == NULL ) {
+ return NULL;
+ }
+ GIFinfo *info = (GIFinfo *)data;
+
+ if( page == -1 ) {
+ page = 0;
+ }
+ if( page < 0 || page >= (int)info->image_descriptor_offsets.size() ) {
+ return NULL;
+ }
+
+ FIBITMAP *dib = NULL;
+ try {
+ bool have_transparent = false, no_local_palette = false, interlaced = false;
+ int disposal_method = GIF_DISPOSAL_LEAVE, delay_time = 0, transparent_color = 0;
+ WORD left, top, width, height;
+ BYTE packed, b;
+ WORD w;
+
+ //playback pages to generate what the user would see for this frame
+ if( (flags & GIF_PLAYBACK) == GIF_PLAYBACK ) {
+ //Logical Screen Descriptor
+ io->seek_proc(handle, 6, SEEK_SET);
+ WORD logicalwidth, logicalheight;
+ io->read_proc(&logicalwidth, 2, 1, handle);
+ io->read_proc(&logicalheight, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&logicalwidth);
+ SwapShort(&logicalheight);
+#endif
+ //set the background color with 0 alpha
+ RGBQUAD background;
+ if( info->global_color_table_offset != 0 && info->background_color < info->global_color_table_size ) {
+ io->seek_proc(handle, (long)(info->global_color_table_offset + (info->background_color * 3)), SEEK_SET);
+ io->read_proc(&background.rgbRed, 1, 1, handle);
+ io->read_proc(&background.rgbGreen, 1, 1, handle);
+ io->read_proc(&background.rgbBlue, 1, 1, handle);
+ } else {
+ background.rgbRed = 0;
+ background.rgbGreen = 0;
+ background.rgbBlue = 0;
+ }
+ background.rgbReserved = 0;
+
+ //allocate entire logical area
+ dib = FreeImage_Allocate(logicalwidth, logicalheight, 32);
+ if( dib == NULL ) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ //fill with background color to start
+ int x, y;
+ RGBQUAD *scanline;
+ for( y = 0; y < logicalheight; y++ ) {
+ scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, y);
+ for( x = 0; x < logicalwidth; x++ ) {
+ *scanline++ = background;
+ }
+ }
+
+ //cache some info about each of the pages so we can avoid decoding as many of them as possible
+ std::vector<PageInfo> pageinfo;
+ int start = page, end = page;
+ while( start >= 0 ) {
+ //Graphic Control Extension
+ io->seek_proc(handle, (long)(info->graphic_control_extension_offsets[start] + 1), SEEK_SET);
+ io->read_proc(&packed, 1, 1, handle);
+ have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false;
+ disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2;
+ //Image Descriptor
+ io->seek_proc(handle, (long)(info->image_descriptor_offsets[start]), SEEK_SET);
+ io->read_proc(&left, 2, 1, handle);
+ io->read_proc(&top, 2, 1, handle);
+ io->read_proc(&width, 2, 1, handle);
+ io->read_proc(&height, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&left);
+ SwapShort(&top);
+ SwapShort(&width);
+ SwapShort(&height);
+#endif
+
+ pageinfo.push_back(PageInfo(disposal_method, left, top, width, height));
+
+ if( start != end ) {
+ if( left == 0 && top == 0 && width == logicalwidth && height == logicalheight ) {
+ if( disposal_method == GIF_DISPOSAL_BACKGROUND ) {
+ pageinfo.pop_back();
+ start++;
+ break;
+ } else if( disposal_method != GIF_DISPOSAL_PREVIOUS ) {
+ if( !have_transparent ) {
+ break;
+ }
+ }
+ }
+ }
+ start--;
+ }
+ if( start < 0 ) {
+ start = 0;
+ }
+
+ //draw each page into the logical area
+ delay_time = 0;
+ for( page = start; page <= end; page++ ) {
+ PageInfo &info = pageinfo[end - page];
+ //things we can skip having to decode
+ if( page != end ) {
+ if( info.disposal_method == GIF_DISPOSAL_PREVIOUS ) {
+ continue;
+ }
+ if( info.disposal_method == GIF_DISPOSAL_BACKGROUND ) {
+ for( y = 0; y < info.height; y++ ) {
+ scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
+ for( x = 0; x < info.width; x++ ) {
+ *scanline++ = background;
+ }
+ }
+ continue;
+ }
+ }
+
+ //decode page
+ FIBITMAP *pagedib = Load(io, handle, page, GIF_LOAD256, data);
+ if( pagedib != NULL ) {
+ RGBQUAD *pal = FreeImage_GetPalette(pagedib);
+ have_transparent = false;
+ if( FreeImage_IsTransparent(pagedib) ) {
+ int count = FreeImage_GetTransparencyCount(pagedib);
+ BYTE *table = FreeImage_GetTransparencyTable(pagedib);
+ for( int i = 0; i < count; i++ ) {
+ if( table[i] == 0 ) {
+ have_transparent = true;
+ transparent_color = i;
+ break;
+ }
+ }
+ }
+ //copy page data into logical buffer, with full alpha opaqueness
+ for( y = 0; y < info.height; y++ ) {
+ scanline = (RGBQUAD *)FreeImage_GetScanLine(dib, logicalheight - (y + info.top) - 1) + info.left;
+ BYTE *pageline = FreeImage_GetScanLine(pagedib, info.height - y - 1);
+ for( x = 0; x < info.width; x++ ) {
+ if( !have_transparent || *pageline != transparent_color ) {
+ *scanline = pal[*pageline];
+ scanline->rgbReserved = 255;
+ }
+ scanline++;
+ pageline++;
+ }
+ }
+ //copy frame time
+ if( page == end ) {
+ FITAG *tag;
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, pagedib, "FrameTime", FIDT_LONG, &tag) ) {
+ delay_time = *(LONG *)FreeImage_GetTagValue(tag);
+ }
+ }
+ FreeImage_Unload(pagedib);
+ }
+ }
+
+ //setup frame time
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", ANIMTAG_FRAMETIME, FIDT_LONG, 1, 4, &delay_time);
+ return dib;
+ }
+
+ //get the actual frame image data for a single frame
+
+ //Image Descriptor
+ io->seek_proc(handle, (long)info->image_descriptor_offsets[page], SEEK_SET);
+ io->read_proc(&left, 2, 1, handle);
+ io->read_proc(&top, 2, 1, handle);
+ io->read_proc(&width, 2, 1, handle);
+ io->read_proc(&height, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&left);
+ SwapShort(&top);
+ SwapShort(&width);
+ SwapShort(&height);
+#endif
+ io->read_proc(&packed, 1, 1, handle);
+ interlaced = (packed & GIF_PACKED_ID_INTERLACED) ? true : false;
+ no_local_palette = (packed & GIF_PACKED_ID_HAVELCT) ? false : true;
+
+ int bpp = 8;
+ if( (flags & GIF_LOAD256) == 0 ) {
+ if( !no_local_palette ) {
+ int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);
+ if( size <= 2 ) bpp = 1;
+ else if( size <= 16 ) bpp = 4;
+ } else if( info->global_color_table_offset != 0 ) {
+ if( info->global_color_table_size <= 2 ) bpp = 1;
+ else if( info->global_color_table_size <= 16 ) bpp = 4;
+ }
+ }
+ dib = FreeImage_Allocate(width, height, bpp);
+ if( dib == NULL ) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", ANIMTAG_FRAMELEFT, FIDT_SHORT, 1, 2, &left);
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", ANIMTAG_FRAMETOP, FIDT_SHORT, 1, 2, &top);
+ b = no_local_palette ? 1 : 0;
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", ANIMTAG_NOLOCALPALETTE, FIDT_BYTE, 1, 1, &b);
+ b = interlaced ? 1 : 0;
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", ANIMTAG_INTERLACED, FIDT_BYTE, 1, 1, &b);
+
+ //Palette
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ if( !no_local_palette ) {
+ int size = 2 << (packed & GIF_PACKED_ID_LCTSIZE);
+
+ int i = 0;
+ while( i < size ) {
+ io->read_proc(&pal[i].rgbRed, 1, 1, handle);
+ io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
+ i++;
+ }
+ } else if( info->global_color_table_offset != 0 ) {
+ long pos = io->tell_proc(handle);
+ io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET);
+
+ int i = 0;
+ while( i < info->global_color_table_size ) {
+ io->read_proc(&pal[i].rgbRed, 1, 1, handle);
+ io->read_proc(&pal[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&pal[i].rgbBlue, 1, 1, handle);
+ i++;
+ }
+
+ io->seek_proc(handle, pos, SEEK_SET);
+ } else {
+ //its legal to have no palette, but we're going to generate *something*
+ for( int i = 0; i < 256; i++ ) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+ }
+
+ //LZW Minimum Code Size
+ io->read_proc(&b, 1, 1, handle);
+ StringTable *stringtable = new StringTable;
+ stringtable->Initialize(b);
+
+ //Image Data Sub-blocks
+ int x = 0, xpos = 0, y = 0, shift = 8 - bpp, mask = (1 << bpp) - 1, interlacepass = 0;
+ BYTE *scanline = FreeImage_GetScanLine(dib, height - 1);
+ BYTE buf[4096];
+ io->read_proc(&b, 1, 1, handle);
+ while( b ) {
+ io->read_proc(stringtable->FillInputBuffer(b), b, 1, handle);
+ int size = sizeof(buf);
+ while( stringtable->Decompress(buf, &size) ) {
+ for( int i = 0; i < size; i++ ) {
+ scanline[xpos] |= (buf[i] & mask) << shift;
+ if( shift > 0 ) {
+ shift -= bpp;
+ } else {
+ xpos++;
+ shift = 8 - bpp;
+ }
+ if( ++x >= width ) {
+ if( interlaced ) {
+ y += g_GifInterlaceIncrement[interlacepass];
+ if( y >= height && ++interlacepass < GIF_INTERLACE_PASSES ) {
+ y = g_GifInterlaceOffset[interlacepass];
+ }
+ } else {
+ y++;
+ }
+ if( y >= height ) {
+ stringtable->Done();
+ break;
+ }
+ x = xpos = 0;
+ shift = 8 - bpp;
+ scanline = FreeImage_GetScanLine(dib, height - y - 1);
+ }
+ }
+ size = sizeof(buf);
+ }
+ io->read_proc(&b, 1, 1, handle);
+ }
+
+ if( page == 0 ) {
+ size_t idx;
+
+ //Logical Screen Descriptor
+ io->seek_proc(handle, 6, SEEK_SET);
+ WORD logicalwidth, logicalheight;
+ io->read_proc(&logicalwidth, 2, 1, handle);
+ io->read_proc(&logicalheight, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&logicalwidth);
+ SwapShort(&logicalheight);
+#endif
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", ANIMTAG_LOGICALWIDTH, FIDT_SHORT, 1, 2, &logicalwidth);
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", ANIMTAG_LOGICALHEIGHT, FIDT_SHORT, 1, 2, &logicalheight);
+
+ //Global Color Table
+ if( info->global_color_table_offset != 0 ) {
+ RGBQUAD globalpalette[256];
+ io->seek_proc(handle, (long)info->global_color_table_offset, SEEK_SET);
+ int i = 0;
+ while( i < info->global_color_table_size ) {
+ io->read_proc(&globalpalette[i].rgbRed, 1, 1, handle);
+ io->read_proc(&globalpalette[i].rgbGreen, 1, 1, handle);
+ io->read_proc(&globalpalette[i].rgbBlue, 1, 1, handle);
+ globalpalette[i].rgbReserved = 0;
+ i++;
+ }
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", ANIMTAG_GLOBALPALETTE, FIDT_PALETTE, info->global_color_table_size, info->global_color_table_size * 4, globalpalette);
+ //background color
+ if( info->background_color < info->global_color_table_size ) {
+ FreeImage_SetBackgroundColor(dib, &globalpalette[info->background_color]);
+ }
+ }
+
+ //Application Extension
+ LONG loop = 1; //If no AE with a loop count is found, the default must be 1
+ for( idx = 0; idx < info->application_extension_offsets.size(); idx++ ) {
+ io->seek_proc(handle, (long)info->application_extension_offsets[idx], SEEK_SET);
+ io->read_proc(&b, 1, 1, handle);
+ if( b == 11 ) { //All AEs start with an 11 byte sub-block to determine what type of AE it is
+ char buf[11];
+ io->read_proc(buf, 11, 1, handle);
+ if( !memcmp(buf, "NETSCAPE2.0", 11) || !memcmp(buf, "ANIMEXTS1.0", 11) ) { //Not everybody recognizes ANIMEXTS1.0 but it is valid
+ io->read_proc(&b, 1, 1, handle);
+ if( b == 3 ) { //we're supposed to have a 3 byte sub-block now
+ io->read_proc(&b, 1, 1, handle); //this should be 0x01 but isn't really important
+ io->read_proc(&w, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ loop = w;
+ if( loop > 0 ) loop++;
+ break;
+ }
+ }
+ }
+ }
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "Loop", ANIMTAG_LOOP, FIDT_LONG, 1, 4, &loop);
+
+ //Comment Extension
+ for( idx = 0; idx < info->comment_extension_offsets.size(); idx++ ) {
+ io->seek_proc(handle, (long)info->comment_extension_offsets[idx], SEEK_SET);
+ std::string comment;
+ char buf[255];
+ io->read_proc(&b, 1, 1, handle);
+ while( b ) {
+ io->read_proc(buf, b, 1, handle);
+ comment.append(buf, b);
+ io->read_proc(&b, 1, 1, handle);
+ }
+ comment.append(1, '\0');
+ sprintf(buf, "Comment%d", idx);
+ DWORD comment_size = (DWORD)comment.size();
+ FreeImage_SetMetadataEx(FIMD_COMMENTS, dib, buf, 1, FIDT_ASCII, comment_size, comment_size, comment.c_str());
+ }
+ }
+
+ //Graphic Control Extension
+ if( info->graphic_control_extension_offsets[page] != 0 ) {
+ io->seek_proc(handle, (long)(info->graphic_control_extension_offsets[page] + 1), SEEK_SET);
+ io->read_proc(&packed, 1, 1, handle);
+ io->read_proc(&w, 2, 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ io->read_proc(&b, 1, 1, handle);
+ have_transparent = (packed & GIF_PACKED_GCE_HAVETRANS) ? true : false;
+ disposal_method = (packed & GIF_PACKED_GCE_DISPOSAL) >> 2;
+ delay_time = w * 10; //convert cs to ms
+ transparent_color = b;
+ if( have_transparent ) {
+ int size = 1 << bpp;
+ if( transparent_color <= size ) {
+ BYTE table[256];
+ memset(table, 0xFF, size);
+ table[transparent_color] = 0;
+ FreeImage_SetTransparencyTable(dib, table, size);
+ }
+ }
+ }
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", ANIMTAG_FRAMETIME, FIDT_LONG, 1, 4, &delay_time);
+ b = (BYTE)disposal_method;
+ FreeImage_SetMetadataEx(FIMD_ANIMATION, dib, "DisposalMethod", ANIMTAG_DISPOSALMETHOD, FIDT_BYTE, 1, 1, &b);
+
+ delete stringtable;
+
+ } catch (const char *msg) {
+ if( dib != NULL ) {
+ FreeImage_Unload(dib);
+ }
+ FreeImage_OutputMessageProc(s_format_id, msg);
+ return NULL;
+ }
+
+ return dib;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if( data == NULL ) {
+ return FALSE;
+ }
+ //GIFinfo *info = (GIFinfo *)data;
+
+ if( page == -1 ) {
+ page = 0;
+ }
+
+ try {
+ BYTE packed, b;
+ WORD w;
+ FITAG *tag;
+
+ int bpp = FreeImage_GetBPP(dib);
+ if( bpp != 1 && bpp != 4 && bpp != 8 ) {
+ throw "Only 1, 4, or 8 bpp images supported";
+ }
+
+ bool have_transparent = false, no_local_palette = false, interlaced = false;
+ int disposal_method = GIF_DISPOSAL_BACKGROUND, delay_time = 100, transparent_color = 0;
+ WORD left = 0, top = 0, width = (WORD)FreeImage_GetWidth(dib), height = (WORD)FreeImage_GetHeight(dib);
+ WORD output_height = height;
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameLeft", FIDT_SHORT, &tag) ) {
+ left = *(WORD *)FreeImage_GetTagValue(tag);
+ }
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameTop", FIDT_SHORT, &tag) ) {
+ top = *(WORD *)FreeImage_GetTagValue(tag);
+ }
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "NoLocalPalette", FIDT_BYTE, &tag) ) {
+ no_local_palette = *(BYTE *)FreeImage_GetTagValue(tag) ? true : false;
+ }
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "Interlaced", FIDT_BYTE, &tag) ) {
+ interlaced = *(BYTE *)FreeImage_GetTagValue(tag) ? true : false;
+ }
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "FrameTime", FIDT_LONG, &tag) ) {
+ delay_time = *(LONG *)FreeImage_GetTagValue(tag);
+ }
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "DisposalMethod", FIDT_BYTE, &tag) ) {
+ disposal_method = *(BYTE *)FreeImage_GetTagValue(tag);
+ }
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&left);
+ SwapShort(&top);
+ SwapShort(&width);
+ SwapShort(&height);
+#endif
+
+ if( page == 0 ) {
+ //gather some info
+ WORD logicalwidth = width; // width has already been swapped...
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "LogicalWidth", FIDT_SHORT, &tag) ) {
+ logicalwidth = *(WORD *)FreeImage_GetTagValue(tag);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&logicalwidth);
+#endif
+ }
+ WORD logicalheight = height; // height has already been swapped...
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "LogicalHeight", FIDT_SHORT, &tag) ) {
+ logicalheight = *(WORD *)FreeImage_GetTagValue(tag);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&logicalheight);
+#endif
+ }
+ RGBQUAD *globalpalette = NULL;
+ int globalpalette_size = 0;
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "GlobalPalette", FIDT_PALETTE, &tag) ) {
+ globalpalette_size = FreeImage_GetTagCount(tag);
+ if( globalpalette_size >= 2 ) {
+ globalpalette = (RGBQUAD *)FreeImage_GetTagValue(tag);
+ }
+ }
+
+ //Logical Screen Descriptor
+ io->write_proc(&logicalwidth, 2, 1, handle);
+ io->write_proc(&logicalheight, 2, 1, handle);
+ packed = GIF_PACKED_LSD_COLORRES;
+ b = 0;
+ RGBQUAD background_color;
+ if( globalpalette != NULL ) {
+ packed |= GIF_PACKED_LSD_HAVEGCT;
+ if( globalpalette_size < 4 ) {
+ globalpalette_size = 2;
+ packed |= 0 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 8 ) {
+ globalpalette_size = 4;
+ packed |= 1 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 16 ) {
+ globalpalette_size = 8;
+ packed |= 2 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 32 ) {
+ globalpalette_size = 16;
+ packed |= 3 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 64 ) {
+ globalpalette_size = 32;
+ packed |= 4 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 128 ) {
+ globalpalette_size = 64;
+ packed |= 5 & GIF_PACKED_LSD_GCTSIZE;
+ } else if( globalpalette_size < 256 ) {
+ globalpalette_size = 128;
+ packed |= 6 & GIF_PACKED_LSD_GCTSIZE;
+ } else {
+ globalpalette_size = 256;
+ packed |= 7 & GIF_PACKED_LSD_GCTSIZE;
+ }
+ if( FreeImage_GetBackgroundColor(dib, &background_color) ) {
+ for( int i = 0; i < globalpalette_size; i++ ) {
+ if( background_color.rgbRed == globalpalette[i].rgbRed &&
+ background_color.rgbGreen == globalpalette[i].rgbGreen &&
+ background_color.rgbBlue == globalpalette[i].rgbBlue ) {
+
+ b = (BYTE)i;
+ break;
+ }
+ }
+ }
+ } else {
+ packed |= (bpp - 1) & GIF_PACKED_LSD_GCTSIZE;
+ }
+ io->write_proc(&packed, 1, 1, handle);
+ io->write_proc(&b, 1, 1, handle);
+ b = 0;
+ io->write_proc(&b, 1, 1, handle);
+
+ //Global Color Table
+ if( globalpalette != NULL ) {
+ int i = 0;
+ while( i < globalpalette_size ) {
+ io->write_proc(&globalpalette[i].rgbRed, 1, 1, handle);
+ io->write_proc(&globalpalette[i].rgbGreen, 1, 1, handle);
+ io->write_proc(&globalpalette[i].rgbBlue, 1, 1, handle);
+ i++;
+ }
+ }
+
+ //Application Extension
+ LONG loop = 0;
+ if( FreeImage_GetMetadataEx(FIMD_ANIMATION, dib, "Loop", FIDT_LONG, &tag) ) {
+ loop = *(LONG *)FreeImage_GetTagValue(tag);
+ }
+ if( loop != 1 ) {
+ //the Netscape extension is really "repeats" not "loops"
+ if( loop > 1 ) loop--;
+ if( loop > 0xFFFF ) loop = 0xFFFF;
+ w = (WORD)loop;
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ io->write_proc((void *)"\x21\xFF\x0BNETSCAPE2.0\x03\x01", 16, 1, handle);
+ io->write_proc(&w, 2, 1, handle);
+ b = 0;
+ io->write_proc(&b, 1, 1, handle);
+ }
+
+ //Comment Extension
+ FIMETADATA *mdhandle = NULL;
+ FITAG *tag = NULL;
+ mdhandle = FreeImage_FindFirstMetadata(FIMD_COMMENTS, dib, &tag);
+ if( mdhandle ) {
+ do {
+ if( FreeImage_GetTagType(tag) == FIDT_ASCII ) {
+ int length = FreeImage_GetTagLength(tag) - 1;
+ char *value = (char *)FreeImage_GetTagValue(tag);
+ io->write_proc((void *)"\x21\xFE", 2, 1, handle);
+ while( length > 0 ) {
+ b = (BYTE)(length >= 255 ? 255 : length);
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(value, b, 1, handle);
+ value += b;
+ length -= b;
+ }
+ b = 0;
+ io->write_proc(&b, 1, 1, handle);
+ }
+ } while(FreeImage_FindNextMetadata(mdhandle, &tag));
+
+ FreeImage_FindCloseMetadata(mdhandle);
+ }
+ }
+
+ //Graphic Control Extension
+ if( FreeImage_IsTransparent(dib) ) {
+ int count = FreeImage_GetTransparencyCount(dib);
+ BYTE *table = FreeImage_GetTransparencyTable(dib);
+ for( int i = 0; i < count; i++ ) {
+ if( table[i] == 0 ) {
+ have_transparent = true;
+ transparent_color = i;
+ break;
+ }
+ }
+ }
+ io->write_proc((void *)"\x21\xF9\x04", 3, 1, handle);
+ b = (BYTE)((disposal_method << 2) & GIF_PACKED_GCE_DISPOSAL);
+ if( have_transparent ) b |= GIF_PACKED_GCE_HAVETRANS;
+ io->write_proc(&b, 1, 1, handle);
+ //Notes about delay time for GIFs:
+ //IE5/IE6 have a minimum and default of 100ms
+ //Mozilla/Firefox/Netscape 6+/Opera have a minimum of 20ms and a default of 100ms if <20ms is specified or the GCE is absent
+ //Netscape 4 has a minimum of 10ms if 0ms is specified, but will use 0ms if the GCE is absent
+ w = (WORD)(delay_time / 10); //convert ms to cs
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&w);
+#endif
+ io->write_proc(&w, 2, 1, handle);
+ b = (BYTE)transparent_color;
+ io->write_proc(&b, 1, 1, handle);
+ b = 0;
+ io->write_proc(&b, 1, 1, handle);
+
+ //Image Descriptor
+ b = GIF_BLOCK_IMAGE_DESCRIPTOR;
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(&left, 2, 1, handle);
+ io->write_proc(&top, 2, 1, handle);
+ io->write_proc(&width, 2, 1, handle);
+ io->write_proc(&height, 2, 1, handle);
+ packed = 0;
+ if( !no_local_palette ) packed |= GIF_PACKED_ID_HAVELCT | ((bpp - 1) & GIF_PACKED_ID_LCTSIZE);
+ if( interlaced ) packed |= GIF_PACKED_ID_INTERLACED;
+ io->write_proc(&packed, 1, 1, handle);
+
+ //Local Color Table
+ if( !no_local_palette ) {
+ int palsize = 1 << bpp;
+ for( int i = 0; i < palsize; i++ ) {
+ io->write_proc(&pal[i].rgbRed, 1, 1, handle);
+ io->write_proc(&pal[i].rgbGreen, 1, 1, handle);
+ io->write_proc(&pal[i].rgbBlue, 1, 1, handle);
+ }
+ }
+
+
+ //LZW Minimum Code Size
+ b = (BYTE)(bpp == 1 ? 2 : bpp);
+ io->write_proc(&b, 1, 1, handle);
+ StringTable *stringtable = new StringTable;
+ stringtable->Initialize(b);
+ stringtable->CompressStart(bpp, width);
+
+ //Image Data Sub-blocks
+ int y = 0, interlacepass = 0, line = FreeImage_GetLine(dib);
+ BYTE buf[255], *bufptr = buf; //255 is the max sub-block length
+ int size = sizeof(buf);
+ b = sizeof(buf);
+ while( y < output_height ) {
+ memcpy(stringtable->FillInputBuffer(line), FreeImage_GetScanLine(dib, output_height - y - 1), line);
+ while( stringtable->Compress(bufptr, &size) ) {
+ bufptr += size;
+ if( bufptr - buf == sizeof(buf) ) {
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(buf, sizeof(buf), 1, handle);
+ size = sizeof(buf);
+ bufptr = buf;
+ } else {
+ size = (int)(sizeof(buf) - (bufptr - buf));
+ }
+ }
+ if( interlaced ) {
+ y += g_GifInterlaceIncrement[interlacepass];
+ if( y >= output_height && ++interlacepass < GIF_INTERLACE_PASSES ) {
+ y = g_GifInterlaceOffset[interlacepass];
+ }
+ } else {
+ y++;
+ }
+ }
+ size = (int)(bufptr - buf);
+ BYTE last[4];
+ w = (WORD)stringtable->CompressEnd(last);
+ if( size + w >= sizeof(buf) ) {
+ //one last full size sub-block
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(buf, size, 1, handle);
+ io->write_proc(last, sizeof(buf) - size, 1, handle);
+ //and possibly a tiny additional sub-block
+ b = (BYTE)(w - (sizeof(buf) - size));
+ if( b > 0 ) {
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(last, b, 1, handle);
+ }
+ } else {
+ //last sub-block less than full size
+ b = (BYTE)(size + w);
+ io->write_proc(&b, 1, 1, handle);
+ io->write_proc(buf, size, 1, handle);
+ io->write_proc(last, w, 1, handle);
+ }
+
+ //Block Terminator
+ b = 0;
+ io->write_proc(&b, 1, 1, handle);
+
+ delete stringtable;
+
+ } catch (const char *msg) {
+ FreeImage_OutputMessageProc(s_format_id, msg);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitGIF(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = PageCount;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginHDR.cpp b/Source/FreeImage/PluginHDR.cpp
new file mode 100644
index 0000000..2eef446
--- /dev/null
+++ b/Source/FreeImage/PluginHDR.cpp
@@ -0,0 +1,702 @@
+// ==========================================================
+// HDR Loader and writer
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// RGBE library
+// ==========================================================
+
+// ----------------------------------------------------------
+
+// maximum size of a line in the header
+#define HDR_MAXLINE 256
+
+// flags indicating which fields in an rgbeHeaderInfo are valid
+#define RGBE_VALID_PROGRAMTYPE 0x01
+#define RGBE_VALID_COMMENT 0x02
+#define RGBE_VALID_GAMMA 0x04
+#define RGBE_VALID_EXPOSURE 0x08
+
+// offsets to red, green, and blue components in a data (float) pixel
+#define RGBE_DATA_RED 0
+#define RGBE_DATA_GREEN 1
+#define RGBE_DATA_BLUE 2
+
+// ----------------------------------------------------------
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagHeaderInfo {
+ int valid; // indicate which fields are valid
+ char programtype[16]; // listed at beginning of file to identify it after "#?". defaults to "RGBE"
+ char comment[HDR_MAXLINE]; // comment beginning with "# "
+ float gamma; // image has already been gamma corrected with given gamma. defaults to 1.0 (no correction)
+ float exposure; // a value of 1.0 in an image corresponds to <exposure> watts/steradian/m^2. defaults to 1.0
+} rgbeHeaderInfo;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+typedef enum {
+ rgbe_read_error,
+ rgbe_write_error,
+ rgbe_format_error,
+ rgbe_memory_error,
+} rgbe_error_code;
+
+// ----------------------------------------------------------
+// Prototypes
+// ----------------------------------------------------------
+
+static BOOL rgbe_Error(rgbe_error_code error_code, const char *msg);
+static BOOL rgbe_GetLine(FreeImageIO *io, fi_handle handle, char *buffer, int length);
+static inline void rgbe_FloatToRGBE(BYTE rgbe[4], FIRGBF *rgbf);
+static inline void rgbe_RGBEToFloat(FIRGBF *rgbf, BYTE rgbe[4]);
+static BOOL rgbe_ReadHeader(FreeImageIO *io, fi_handle handle, unsigned *width, unsigned *height, rgbeHeaderInfo *header_info);
+static BOOL rgbe_WriteHeader(FreeImageIO *io, fi_handle handle, unsigned width, unsigned height, rgbeHeaderInfo *info);
+static BOOL rgbe_ReadPixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels);
+static BOOL rgbe_WritePixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels);
+static BOOL rgbe_ReadPixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, int scanline_width, unsigned num_scanlines);
+static BOOL rgbe_WriteBytes_RLE(FreeImageIO *io, fi_handle handle, BYTE *data, int numbytes);
+static BOOL rgbe_WritePixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned scanline_width, unsigned num_scanlines);
+static BOOL rgbe_ReadMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info);
+static BOOL rgbe_WriteMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info);
+
+// ----------------------------------------------------------
+
+/**
+Default error routine. change this to change error handling
+*/
+static BOOL
+rgbe_Error(rgbe_error_code error_code, const char *msg) {
+ switch (error_code) {
+ case rgbe_read_error:
+ FreeImage_OutputMessageProc(s_format_id, "RGBE read error");
+ break;
+ case rgbe_write_error:
+ FreeImage_OutputMessageProc(s_format_id, "RGBE write error");
+ break;
+ case rgbe_format_error:
+ FreeImage_OutputMessageProc(s_format_id, "RGBE bad file format: %s\n", msg);
+ break;
+ default:
+ case rgbe_memory_error:
+ FreeImage_OutputMessageProc(s_format_id, "RGBE error: %s\n",msg);
+ }
+
+ return FALSE;
+}
+
+/**
+Get a line from a ASCII io stream
+*/
+static BOOL
+rgbe_GetLine(FreeImageIO *io, fi_handle handle, char *buffer, int length) {
+ int i;
+ memset(buffer, 0, length);
+ for(i = 0; i < length; i++) {
+ if(!io->read_proc(&buffer[i], 1, 1, handle))
+ return FALSE;
+ if(buffer[i] == 0x0A)
+ break;
+ }
+
+ return (i < length) ? TRUE : FALSE;
+}
+
+/**
+Standard conversion from float pixels to rgbe pixels.
+Note: you can remove the "inline"s if your compiler complains about it
+*/
+static inline void
+rgbe_FloatToRGBE(BYTE rgbe[4], FIRGBF *rgbf) {
+ float v;
+ int e;
+
+ v = rgbf->red;
+ if (rgbf->green > v) v = rgbf->green;
+ if (rgbf->blue > v) v = rgbf->blue;
+ if (v < 1e-32) {
+ rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
+ }
+ else {
+ v = (float)(frexp(v, &e) * 256.0 / v);
+ rgbe[0] = (BYTE) (rgbf->red * v);
+ rgbe[1] = (BYTE) (rgbf->green * v);
+ rgbe[2] = (BYTE) (rgbf->blue * v);
+ rgbe[3] = (BYTE) (e + 128);
+ }
+}
+
+/**
+Standard conversion from rgbe to float pixels.
+Note: Ward uses ldexp(col+0.5,exp-(128+8)).
+However we wanted pixels in the range [0,1] to map back into the range [0,1].
+*/
+static inline void
+rgbe_RGBEToFloat(FIRGBF *rgbf, BYTE rgbe[4]) {
+ if (rgbe[3]) { // nonzero pixel
+ float f = (float)(ldexp(1.0, rgbe[3] - (int)(128+8)));
+ rgbf->red = rgbe[0] * f;
+ rgbf->green = rgbe[1] * f;
+ rgbf->blue = rgbe[2] * f;
+
+ }
+ else {
+ rgbf->red = rgbf->green = rgbf->blue = 0;
+ }
+}
+
+/**
+Minimal header reading. Modify if you want to parse more information
+*/
+static BOOL
+rgbe_ReadHeader(FreeImageIO *io, fi_handle handle, unsigned *width, unsigned *height, rgbeHeaderInfo *header_info) {
+ char buf[HDR_MAXLINE];
+ float tempf;
+ int i;
+ BOOL bFormatFound = FALSE;
+ BOOL bHeaderFound = FALSE;
+
+ header_info->valid = 0;
+ header_info->programtype[0] = 0;
+ header_info->gamma = 1.0;
+ header_info->exposure = 1.0;
+
+ // get the first line
+ if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE))
+ return rgbe_Error(rgbe_read_error, NULL);
+
+ // check the signature
+
+ if ((buf[0] != '#')||(buf[1] != '?')) {
+ // if you don't want to require the magic token then comment the next line
+ return rgbe_Error(rgbe_format_error,"bad initial token");
+ }
+ else {
+ header_info->valid |= RGBE_VALID_PROGRAMTYPE;
+ for(i = 0; i < sizeof(header_info->programtype) - 1; i++) {
+ if((buf[i+2] == 0) || isspace(buf[i+2]))
+ break;
+ header_info->programtype[i] = buf[i+2];
+ }
+ header_info->programtype[i] = 0;
+ }
+
+ for(;;) {
+ // get next line
+ if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE))
+ return rgbe_Error(rgbe_read_error, NULL);
+
+ if((buf[0] == 0) || (buf[0] == '\n')) {
+ // end of header so break out of loop
+ bHeaderFound = TRUE;
+ break;
+ }
+ else if(strcmp(buf,"FORMAT=32-bit_rle_rgbe\n") == 0) {
+ bFormatFound = TRUE;
+ }
+ else if(sscanf(buf, "GAMMA=%g", &tempf) == 1) {
+ header_info->gamma = tempf;
+ header_info->valid |= RGBE_VALID_GAMMA;
+ }
+ else if(sscanf(buf,"EXPOSURE=%g",&tempf) == 1) {
+ header_info->exposure = tempf;
+ header_info->valid |= RGBE_VALID_EXPOSURE;
+ }
+ else if((buf[0] == '#') && (buf[1] == 0x20)) {
+ header_info->valid |= RGBE_VALID_COMMENT;
+ strcpy(header_info->comment, buf);
+ }
+ }
+ if(!bHeaderFound || !bFormatFound) {
+ return rgbe_Error(rgbe_format_error, "invalid header");
+ }
+
+ // get next line
+ if(!rgbe_GetLine(io, handle, buf, HDR_MAXLINE))
+ return rgbe_Error(rgbe_read_error, NULL);
+
+ // get the image width & height
+ if(sscanf(buf,"-Y %d +X %d", height, width) < 2) {
+ if(sscanf(buf,"+X %d +Y %d", height, width) < 2) {
+ return rgbe_Error(rgbe_format_error, "missing image size specifier");
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ default minimal header. modify if you want more information in header
+*/
+static BOOL
+rgbe_WriteHeader(FreeImageIO *io, fi_handle handle, unsigned width, unsigned height, rgbeHeaderInfo *info) {
+ char buffer[HDR_MAXLINE];
+
+ char *programtype = "RADIANCE";
+
+ if(info && (info->valid & RGBE_VALID_PROGRAMTYPE)) {
+ programtype = info->programtype;
+ }
+ // The #? is to identify file type, the programtype is optional
+ sprintf(buffer, "#?%s\n", programtype);
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ sprintf(buffer, "%s\n", info->comment);
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ sprintf(buffer, "FORMAT=32-bit_rle_rgbe\n");
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ if(info && (info->valid & RGBE_VALID_GAMMA)) {
+ sprintf(buffer, "GAMMA=%g\n", info->gamma);
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ }
+ if(info && (info->valid & RGBE_VALID_EXPOSURE)) {
+ sprintf(buffer,"EXPOSURE=%g\n", info->exposure);
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ }
+ sprintf(buffer, "\n-Y %d +X %d\n", height, width);
+ if(io->write_proc(buffer, 1, (unsigned int)strlen(buffer), handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+
+ return TRUE;
+}
+
+static BOOL
+rgbe_ReadMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info) {
+ return TRUE;
+}
+static BOOL
+rgbe_WriteMetadata(FIBITMAP *dib, rgbeHeaderInfo *header_info) {
+ header_info->gamma = 1;
+ header_info->valid |= RGBE_VALID_GAMMA;
+ header_info->exposure = 0;
+ header_info->valid |= RGBE_VALID_EXPOSURE;
+
+ return TRUE;
+}
+
+/**
+Simple read routine. Will not correctly handle run length encoding
+*/
+static BOOL
+rgbe_ReadPixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels) {
+ BYTE rgbe[4];
+
+ for(unsigned x = 0; x < numpixels; x++) {
+ if(io->read_proc(rgbe, 1, sizeof(rgbe), handle) < 1) {
+ return rgbe_Error(rgbe_read_error, NULL);
+ }
+ rgbe_RGBEToFloat(&data[x], rgbe);
+ }
+
+ return TRUE;
+}
+
+/**
+ Simple write routine that does not use run length encoding.
+ These routines can be made faster by allocating a larger buffer and
+ fread-ing and fwrite-ing the data in larger chunks.
+*/
+static BOOL
+rgbe_WritePixels(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned numpixels) {
+ BYTE rgbe[4];
+
+ for(unsigned x = 0; x < numpixels; x++) {
+ rgbe_FloatToRGBE(rgbe, &data[x]);
+ if(io->write_proc(rgbe, sizeof(rgbe), 1, handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ }
+
+ return TRUE;
+}
+
+static BOOL
+rgbe_ReadPixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, int scanline_width, unsigned num_scanlines) {
+ BYTE rgbe[4], *scanline_buffer, *ptr, *ptr_end;
+ int i, count;
+ BYTE buf[2];
+
+ if ((scanline_width < 8)||(scanline_width > 0x7fff)) {
+ // run length encoding is not allowed so read flat
+ return rgbe_ReadPixels(io, handle, data, scanline_width * num_scanlines);
+ }
+ scanline_buffer = NULL;
+ // read in each successive scanline
+ while(num_scanlines > 0) {
+ if(io->read_proc(rgbe, 1, sizeof(rgbe), handle) < 1) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_read_error,NULL);
+ }
+ if((rgbe[0] != 2) || (rgbe[1] != 2) || (rgbe[2] & 0x80)) {
+ // this file is not run length encoded
+ rgbe_RGBEToFloat(data, rgbe);
+ data ++;
+ free(scanline_buffer);
+ return rgbe_ReadPixels(io, handle, data, scanline_width * num_scanlines - 1);
+ }
+ if((((int)rgbe[2]) << 8 | rgbe[3]) != scanline_width) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_format_error,"wrong scanline width");
+ }
+ if(scanline_buffer == NULL) {
+ scanline_buffer = (BYTE*)malloc(sizeof(BYTE) * 4 * scanline_width);
+ if(scanline_buffer == NULL) {
+ return rgbe_Error(rgbe_memory_error, "unable to allocate buffer space");
+ }
+ }
+
+ ptr = &scanline_buffer[0];
+ // read each of the four channels for the scanline into the buffer
+ for(i = 0; i < 4; i++) {
+ ptr_end = &scanline_buffer[(i+1)*scanline_width];
+ while(ptr < ptr_end) {
+ if(io->read_proc(buf, 1, 2 * sizeof(BYTE), handle) < 1) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_read_error, NULL);
+ }
+ if(buf[0] > 128) {
+ // a run of the same value
+ count = buf[0] - 128;
+ if((count == 0) || (count > ptr_end - ptr)) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_format_error, "bad scanline data");
+ }
+ while(count-- > 0)
+ *ptr++ = buf[1];
+ }
+ else {
+ // a non-run
+ count = buf[0];
+ if((count == 0) || (count > ptr_end - ptr)) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_format_error, "bad scanline data");
+ }
+ *ptr++ = buf[1];
+ if(--count > 0) {
+ if(io->read_proc(ptr, 1, sizeof(BYTE) * count, handle) < 1) {
+ free(scanline_buffer);
+ return rgbe_Error(rgbe_read_error, NULL);
+ }
+ ptr += count;
+ }
+ }
+ }
+ }
+ // now convert data from buffer into floats
+ for(i = 0; i < scanline_width; i++) {
+ rgbe[0] = scanline_buffer[i];
+ rgbe[1] = scanline_buffer[i+scanline_width];
+ rgbe[2] = scanline_buffer[i+2*scanline_width];
+ rgbe[3] = scanline_buffer[i+3*scanline_width];
+ rgbe_RGBEToFloat(data, rgbe);
+ data ++;
+ }
+
+ num_scanlines--;
+ }
+
+ free(scanline_buffer);
+
+ return TRUE;
+}
+
+/**
+ The code below is only needed for the run-length encoded files.
+ Run length encoding adds considerable complexity but does
+ save some space. For each scanline, each channel (r,g,b,e) is
+ encoded separately for better compression.
+ @return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+rgbe_WriteBytes_RLE(FreeImageIO *io, fi_handle handle, BYTE *data, int numbytes) {
+ static const int MINRUNLENGTH = 4;
+ int cur, beg_run, run_count, old_run_count, nonrun_count;
+ BYTE buf[2];
+
+ cur = 0;
+ while(cur < numbytes) {
+ beg_run = cur;
+ // find next run of length at least 4 if one exists
+ run_count = old_run_count = 0;
+ while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) {
+ beg_run += run_count;
+ old_run_count = run_count;
+ run_count = 1;
+ while((data[beg_run] == data[beg_run + run_count]) && (beg_run + run_count < numbytes) && (run_count < 127))
+ run_count++;
+ }
+ // if data before next big run is a short run then write it as such
+ if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) {
+ buf[0] = (BYTE)(128 + old_run_count); // write short run
+ buf[1] = data[cur];
+ if(io->write_proc(buf, 2 * sizeof(BYTE), 1, handle) < 1)
+ return rgbe_Error(rgbe_write_error, NULL);
+ cur = beg_run;
+ }
+ // write out bytes until we reach the start of the next run
+ while(cur < beg_run) {
+ nonrun_count = beg_run - cur;
+ if (nonrun_count > 128)
+ nonrun_count = 128;
+ buf[0] = (BYTE)nonrun_count;
+ if(io->write_proc(buf, sizeof(buf[0]), 1, handle) < 1)
+ return rgbe_Error(rgbe_write_error,NULL);
+ if(io->write_proc(&data[cur], sizeof(data[0]) * nonrun_count, 1, handle) < 1)
+ return rgbe_Error(rgbe_write_error,NULL);
+ cur += nonrun_count;
+ }
+ // write out next run if one was found
+ if (run_count >= MINRUNLENGTH) {
+ buf[0] = (BYTE)(128 + run_count);
+ buf[1] = data[beg_run];
+ if(io->write_proc(buf, sizeof(buf[0]) * 2, 1, handle) < 1)
+ return rgbe_Error(rgbe_write_error,NULL);
+ cur += run_count;
+ }
+ }
+
+ return TRUE;
+}
+
+static BOOL
+rgbe_WritePixels_RLE(FreeImageIO *io, fi_handle handle, FIRGBF *data, unsigned scanline_width, unsigned num_scanlines) {
+ BYTE rgbe[4];
+ BYTE *buffer;
+
+ if ((scanline_width < 8)||(scanline_width > 0x7fff)) {
+ // run length encoding is not allowed so write flat
+ return rgbe_WritePixels(io, handle, data, scanline_width * num_scanlines);
+ }
+ buffer = (BYTE*)malloc(sizeof(BYTE) * 4 * scanline_width);
+ if (buffer == NULL) {
+ // no buffer space so write flat
+ return rgbe_WritePixels(io, handle, data, scanline_width * num_scanlines);
+ }
+ while(num_scanlines-- > 0) {
+ rgbe[0] = (BYTE)2;
+ rgbe[1] = (BYTE)2;
+ rgbe[2] = (BYTE)(scanline_width >> 8);
+ rgbe[3] = (BYTE)(scanline_width & 0xFF);
+ if(io->write_proc(rgbe, sizeof(rgbe), 1, handle) < 1) {
+ free(buffer);
+ return rgbe_Error(rgbe_write_error, NULL);
+ }
+ for(unsigned x = 0; x < scanline_width; x++) {
+ rgbe_FloatToRGBE(rgbe, data);
+ buffer[x] = rgbe[0];
+ buffer[x+scanline_width] = rgbe[1];
+ buffer[x+2*scanline_width] = rgbe[2];
+ buffer[x+3*scanline_width] = rgbe[3];
+ data ++;
+ }
+ // write out each of the four channels separately run length encoded
+ // first red, then green, then blue, then exponent
+ for(int i = 0; i < 4; i++) {
+ BOOL bOK = rgbe_WriteBytes_RLE(io, handle, &buffer[i*scanline_width], scanline_width);
+ if(!bOK) {
+ free(buffer);
+ return bOK;
+ }
+ }
+ }
+ free(buffer);
+
+ return TRUE;
+}
+
+
+// ----------------------------------------------------------
+
+
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "HDR";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "High Dynamic Range Image";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "hdr";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-hdr";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE hdr_signature[] = { '#', '?' };
+ BYTE signature[] = { 0, 0 };
+
+ io->read_proc(signature, 1, 2, handle);
+
+ return (memcmp(hdr_signature, signature, 2) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (depth == 96);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_RGBF) ? TRUE : FALSE;
+}
+
+// --------------------------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ FIBITMAP *dib = NULL;
+
+ if(handle) {
+ try {
+
+ rgbeHeaderInfo header_info;
+ unsigned width, height;
+
+ // Read the header
+ if(rgbe_ReadHeader(io, handle, &width, &height, &header_info) == FALSE)
+ return NULL;
+
+ // allocate a RGBF image
+ dib = FreeImage_AllocateT(FIT_RGBF, width, height);
+ if(!dib) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // read the image pixels and fill the dib
+
+ for(unsigned y = 0; y < height; y++) {
+ FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
+ if(!rgbe_ReadPixels_RLE(io, handle, scanline, width, 1)) {
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+ }
+
+ // set the metadata as comments
+ rgbe_ReadMetadata(dib, &header_info);
+
+ }
+ catch(const char *text) {
+ if(dib != NULL) {
+ FreeImage_Unload(dib);
+ }
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+ }
+
+ return dib;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if(!dib) return FALSE;
+
+ if(FreeImage_GetImageType(dib) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+
+ // write the header
+
+ rgbeHeaderInfo header_info;
+ memset(&header_info, 0, sizeof(rgbeHeaderInfo));
+ // fill the header with correct gamma and exposure
+ rgbe_WriteMetadata(dib, &header_info);
+ // fill a comment
+ sprintf(header_info.comment, "# Made with FreeImage %s", FreeImage_GetVersion());
+ if(!rgbe_WriteHeader(io, handle, width, height, &header_info)) {
+ return FALSE;
+ }
+
+ // write each scanline
+
+ for(unsigned y = 0; y < height; y++) {
+ FIRGBF *scanline = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
+ if(!rgbe_WritePixels_RLE(io, handle, scanline, width, 1)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitHDR(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginICO.cpp b/Source/FreeImage/PluginICO.cpp
new file mode 100644
index 0000000..1daa264
--- /dev/null
+++ b/Source/FreeImage/PluginICO.cpp
@@ -0,0 +1,720 @@
+// ==========================================================
+// ICO Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+// These next two structs represent how the icon information is stored
+// in an ICO file.
+
+typedef struct tagICONHEADER {
+ WORD idReserved; // reserved
+ WORD idType; // resource type (1 for icons)
+ WORD idCount; // how many images?
+} ICONHEADER;
+
+typedef struct tagICONDIRECTORYENTRY {
+ BYTE bWidth; // width of the image
+ BYTE bHeight; // height of the image (times 2)
+ BYTE bColorCount; // number of colors in image (0 if >=8bpp)
+ BYTE bReserved; // reserved
+ WORD wPlanes; // color Planes
+ WORD wBitCount; // bits per pixel
+ DWORD dwBytesInRes; // how many bytes in this resource?
+ DWORD dwImageOffset; // where in the file is this image
+} ICONDIRENTRY;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ==========================================================
+// Static helpers
+// ==========================================================
+
+/** How wide, in bytes, would this many bits be, DWORD aligned ?
+*/
+static int
+WidthBytes(int bits) {
+ return ((((bits) + 31)>>5)<<2);
+}
+
+/** Calculates the size of a single icon image
+@return Returns the size for that image
+*/
+static DWORD
+CalculateImageSize(FIBITMAP* icon_dib) {
+ DWORD dwNumBytes = 0;
+
+ unsigned colors = FreeImage_GetColorsUsed(icon_dib);
+ unsigned width = FreeImage_GetWidth(icon_dib);
+ unsigned height = FreeImage_GetHeight(icon_dib);
+ unsigned pitch = FreeImage_GetPitch(icon_dib);
+
+ dwNumBytes = sizeof( BITMAPINFOHEADER ); // header
+ dwNumBytes += colors * sizeof(RGBQUAD); // palette
+ dwNumBytes += height * pitch; // XOR mask
+ dwNumBytes += height * WidthBytes(width); // AND mask
+
+ return dwNumBytes;
+}
+
+/** Calculates the file offset for an icon image
+@return Returns the file offset for that image
+*/
+static DWORD
+CalculateImageOffset(std::vector<FIBITMAP*>& vPages, int nIndex ) {
+ DWORD dwSize;
+
+ // calculate the ICO header size
+ dwSize = sizeof(ICONHEADER);
+ // add the ICONDIRENTRY's
+ dwSize += (DWORD)( vPages.size() * sizeof(ICONDIRENTRY) );
+ // add the sizes of the previous images
+ for(int k = 0; k < nIndex; k++) {
+ FIBITMAP *icon_dib = (FIBITMAP*)vPages[k];
+ dwSize += CalculateImageSize(icon_dib);
+ }
+
+ return dwSize;
+}
+
+#ifdef FREEIMAGE_BIGENDIAN
+static void
+SwapInfoHeader(BITMAPINFOHEADER *header) {
+ SwapLong(&header->biSize);
+ SwapLong((DWORD *)&header->biWidth);
+ SwapLong((DWORD *)&header->biHeight);
+ SwapShort(&header->biPlanes);
+ SwapShort(&header->biBitCount);
+ SwapLong(&header->biCompression);
+ SwapLong(&header->biSizeImage);
+ SwapLong((DWORD *)&header->biXPelsPerMeter);
+ SwapLong((DWORD *)&header->biYPelsPerMeter);
+ SwapLong(&header->biClrUsed);
+ SwapLong(&header->biClrImportant);
+}
+
+static void
+SwapIconHeader(ICONHEADER *header) {
+ SwapShort(&header->idReserved);
+ SwapShort(&header->idType);
+ SwapShort(&header->idCount);
+}
+
+static void
+SwapIconDirEntries(ICONDIRENTRY *ent, int num) {
+ while(num) {
+ SwapShort(&ent->wPlanes);
+ SwapShort(&ent->wBitCount);
+ SwapLong(&ent->dwBytesInRes);
+ SwapLong(&ent->dwImageOffset);
+ num--;
+ ent++;
+ }
+}
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "ICO";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Windows Icon";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "ico";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-icon";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ ICONHEADER icon_header;
+
+ io->read_proc(&icon_header, sizeof(ICONHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconHeader(&icon_header);
+#endif
+
+ return ((icon_header.idReserved == 0) && (icon_header.idType == 1) && (icon_header.idCount > 0));
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1) ||
+ (depth == 4) ||
+ (depth == 8) ||
+ (depth == 16) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ ICONHEADER *lpIH = NULL;
+
+ // Allocate memory for the header structure
+ if((lpIH = (ICONHEADER*)malloc( sizeof(ICONHEADER) )) == NULL)
+ return NULL;
+
+ if (read) {
+ // Read in the header
+ io->read_proc(lpIH, 1, sizeof(ICONHEADER), handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconHeader(lpIH);
+#endif
+
+ if(!(lpIH->idReserved == 0) || !(lpIH->idType == 1)) {
+ // Not an ICO file
+ free(lpIH);
+ return NULL;
+ }
+ }
+ else {
+ // Fill the header
+ lpIH->idReserved = 0;
+ lpIH->idType = 1;
+ lpIH->idCount = 0;
+ }
+ return lpIH;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+ // free the header structure
+ ICONHEADER *lpIH = (ICONHEADER*)data;
+ free(lpIH);
+}
+
+// ----------------------------------------------------------
+
+static int DLL_CALLCONV
+PageCount(FreeImageIO *io, fi_handle handle, void *data) {
+ ICONHEADER *lpIH = (ICONHEADER*)data;
+
+ if(lpIH) {
+ return lpIH->idCount;
+ }
+ return 1;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (page == -1)
+ page = 0;
+
+ if (handle != NULL) {
+ FIBITMAP *dib = NULL;
+
+ // get the icon header
+ ICONHEADER *icon_header = (ICONHEADER*)data;
+
+ if (icon_header) {
+ // load the icon descriptions
+ ICONDIRENTRY *icon_list = (ICONDIRENTRY*)malloc(icon_header->idCount * sizeof(ICONDIRENTRY));
+ io->seek_proc(handle, sizeof(ICONHEADER), SEEK_SET);
+ io->read_proc(icon_list, icon_header->idCount * sizeof(ICONDIRENTRY), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconDirEntries(icon_list, icon_header->idCount);
+#endif
+
+ // load the requested icon
+ if (page < icon_header->idCount) {
+ // seek to the start of the bitmap data for the icon
+ io->seek_proc(handle, 0, SEEK_SET);
+ io->seek_proc(handle, icon_list[page].dwImageOffset, SEEK_CUR);
+
+ // Vista icon support
+ if((icon_list[page].bWidth == 0) && (icon_list[page].bHeight == 0)) {
+ dib = FreeImage_LoadFromHandle(FIF_PNG, io, handle, 0);
+ free(icon_list);
+ return dib;
+ }
+
+ free(icon_list);
+
+ // load the BITMAPINFOHEADER
+ BITMAPINFOHEADER bmih;
+ io->read_proc(&bmih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(&bmih);
+#endif
+
+ // allocate the bitmap
+ int width = bmih.biWidth;
+ int height = bmih.biHeight / 2; // height == xor + and mask
+ int bit_count = bmih.biBitCount;
+ int line = CalculateLine(width, bit_count);
+ int pitch = CalculatePitch(line);
+
+ // allocate memory for one icon
+
+ dib = FreeImage_Allocate(width, height, bit_count);
+
+ if (dib == NULL) {
+ return NULL;
+ }
+
+ if( bmih.biBitCount <= 8 ) {
+ // read the palette data
+ io->read_proc(FreeImage_GetPalette(dib), CalculateUsedPaletteEntries(bit_count) * sizeof(RGBQUAD), 1, handle);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ for(int i = 0; i < CalculateUsedPaletteEntries(bit_count); i++) {
+ INPLACESWAP(pal[i].rgbRed, pal[i].rgbBlue);
+ }
+#endif
+ }
+
+ // read the icon
+ io->read_proc(FreeImage_GetBits(dib), height * pitch, 1, handle);
+
+#ifdef FREEIMAGE_BIGENDIAN
+ if (bit_count == 16) {
+ for(int y = 0; y < height; y++) {
+ WORD *pixel = (WORD *)FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < width; x++) {
+ SwapShort(pixel);
+ pixel++;
+ }
+ }
+ }
+#endif
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if (bit_count == 24 || bit_count == 32) {
+ for(int y = 0; y < height; y++) {
+ BYTE *pixel = FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < width; x++) {
+ INPLACESWAP(pixel[0], pixel[2]);
+ pixel += (bit_count>>3);
+ }
+ }
+ }
+#endif
+ // bitmap has been loaded successfully!
+
+ // convert to 32bpp and generate an alpha channel
+ if((flags & ICO_MAKEALPHA) == ICO_MAKEALPHA) {
+ FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(dib);
+ FreeImage_Unload(dib);
+
+ if (dib32 == NULL) {
+ return NULL;
+ }
+
+ int width_and = WidthBytes(width);
+ BYTE *line_and = (BYTE *)malloc(width_and);
+
+ if( line_and == NULL ) {
+ FreeImage_Unload(dib32);
+ return NULL;
+ }
+
+ //loop through each line of the AND-mask generating the alpha channel, invert XOR-mask
+ for(int y = 0; y < height; y++) {
+ RGBQUAD *quad = (RGBQUAD *)FreeImage_GetScanLine(dib32, y);
+ io->read_proc(line_and, width_and, 1, handle);
+ for(int x = 0; x < width; x++) {
+ quad->rgbReserved = (line_and[x>>3] & (0x80 >> (x & 0x07))) != 0 ? 0 : 0xFF;
+ if( quad->rgbReserved == 0 ) {
+ quad->rgbBlue ^= 0xFF;
+ quad->rgbGreen ^= 0xFF;
+ quad->rgbRed ^= 0xFF;
+ }
+ quad++;
+ }
+ }
+ free(line_and);
+
+ return dib32;
+ }
+
+ return (FIBITMAP *)dib;
+
+ } else {
+ free(icon_list);
+ FreeImage_OutputMessageProc(s_format_id, "Page doesn't exist");
+ }
+ } else {
+ FreeImage_OutputMessageProc(s_format_id, "File is not an ICO file");
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ int k;
+
+ if(dib) {
+ // check format limits
+ int w = FreeImage_GetWidth(dib);
+ int h = FreeImage_GetHeight(dib);
+ if((w < 16) || (w > 128) || (h < 16) || (h > 128)) {
+ FreeImage_OutputMessageProc(s_format_id, "Unsupported icon size");
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+
+ if (page == -1)
+ page = 0;
+
+ // get the icon header
+ ICONHEADER *icon_header = (ICONHEADER*)data;
+
+ if(icon_header) {
+
+ std::vector<FIBITMAP*> vPages;
+ FIBITMAP *icon_dib = NULL;
+
+ // load all icons
+ for(k = 0; k < icon_header->idCount; k++) {
+ icon_dib = Load(io, handle, k, flags, data);
+ vPages.push_back(icon_dib);
+ }
+
+ // add the page
+ icon_dib = FreeImage_Clone(dib);
+ vPages.push_back(icon_dib);
+ icon_header->idCount++;
+
+ // write the header
+ io->seek_proc(handle, 0, SEEK_SET);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconHeader(icon_header);
+#endif
+ io->write_proc(icon_header, sizeof(ICONHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconHeader(icon_header);
+#endif
+
+ // write all icons
+ // ...
+
+ // save the icon descriptions
+ ICONDIRENTRY *icon_list = (ICONDIRENTRY *)malloc(icon_header->idCount * sizeof(ICONDIRENTRY));
+ memset(icon_list, 0, icon_header->idCount * sizeof(ICONDIRENTRY));
+ BITMAPINFOHEADER *bmih;
+ for(k = 0; k < icon_header->idCount; k++) {
+ icon_dib = (FIBITMAP*)vPages[k];
+
+ // convert internal format to ICONDIRENTRY
+ bmih = FreeImage_GetInfoHeader(icon_dib);
+ icon_list[k].bWidth = (BYTE)bmih->biWidth;
+ icon_list[k].bHeight = (BYTE)bmih->biHeight;
+ icon_list[k].bReserved = 0;
+ icon_list[k].wPlanes = bmih->biPlanes;
+ icon_list[k].wBitCount = bmih->biBitCount;
+ if( (icon_list[k].wPlanes * icon_list[k].wBitCount) >= 8 ) {
+ icon_list[k].bColorCount = 0;
+ } else {
+ icon_list[k].bColorCount = (BYTE)(1 << (icon_list[k].wPlanes * icon_list[k].wBitCount));
+ }
+ icon_list[k].dwBytesInRes = CalculateImageSize(icon_dib);
+ icon_list[k].dwImageOffset = CalculateImageOffset(vPages, k);
+ }
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapIconDirEntries(icon_list, icon_header->idCount);
+#endif
+ io->write_proc(icon_list, sizeof(ICONDIRENTRY) * icon_header->idCount, 1, handle);
+ free(icon_list);
+
+ // write the image bits for each image
+ for(k = 0; k < icon_header->idCount; k++) {
+ icon_dib = (FIBITMAP*)vPages[k];
+
+ // write the BITMAPINFOHEADER
+ bmih = FreeImage_GetInfoHeader(icon_dib);
+ bmih->biHeight *= 2; // height == xor + and mask
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(bmih);
+#endif
+ io->write_proc(bmih, sizeof(BITMAPINFOHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapInfoHeader(bmih);
+#endif
+ bmih->biHeight /= 2;
+
+ // write the palette data
+ if (FreeImage_GetPalette(icon_dib) != NULL) {
+ RGBQUAD *pal = FreeImage_GetPalette(icon_dib);
+ FILE_BGRA bgra;
+ for(unsigned i = 0; i < FreeImage_GetColorsUsed(icon_dib); i++) {
+ bgra.b = pal[i].rgbBlue;
+ bgra.g = pal[i].rgbGreen;
+ bgra.r = pal[i].rgbRed;
+ bgra.a = pal[i].rgbReserved;
+ io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle);
+ }
+ }
+
+ // write the bits
+ int width = bmih->biWidth;
+ int height = bmih->biHeight;
+ int bit_count = bmih->biBitCount;
+ int line = CalculateLine(width, bit_count);
+ int pitch = CalculatePitch(line);
+ int size_xor = height * pitch;
+ int size_and = height * WidthBytes(width);
+
+ // XOR mask
+#ifdef FREEIMAGE_BIGENDIAN
+ if (bit_count == 16) {
+ WORD pixel;
+ for(int y = 0; y < FreeImage_GetHeight(icon_dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(icon_dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(icon_dib); x++) {
+ pixel = ((WORD *)line)[x];
+ SwapShort(&pixel);
+ if (io->write_proc(&pixel, sizeof(WORD), 1, handle) != 1)
+ return FALSE;
+ }
+ }
+ } else
+#endif
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if (bit_count == 24) {
+ FILE_BGR bgr;
+ for(int y = 0; y < FreeImage_GetHeight(icon_dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(icon_dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(icon_dib); x++) {
+ RGBTRIPLE *triple = ((RGBTRIPLE *)line)+x;
+ bgr.b = triple->rgbtBlue;
+ bgr.g = triple->rgbtGreen;
+ bgr.r = triple->rgbtRed;
+ if (io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle) != 1)
+ return FALSE;
+ }
+ }
+ } else if (bit_count == 32) {
+ FILE_BGRA bgra;
+ for(int y = 0; y < FreeImage_GetHeight(icon_dib); y++) {
+ BYTE *line = FreeImage_GetScanLine(icon_dib, y);
+ for(int x = 0; x < FreeImage_GetWidth(icon_dib); x++) {
+ RGBQUAD *quad = ((RGBQUAD *)line)+x;
+ bgra.b = quad->rgbBlue;
+ bgra.g = quad->rgbGreen;
+ bgra.r = quad->rgbRed;
+ bgra.a = quad->rgbReserved;
+ if (io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle) != 1)
+ return FALSE;
+ }
+ }
+ } else
+#endif
+#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ {
+#endif
+ BYTE *xor_mask = FreeImage_GetBits(icon_dib);
+ io->write_proc(xor_mask, size_xor, 1, handle);
+#if defined(FREEIMAGE_BIGENDIAN) || FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ }
+#endif
+ // AND mask
+ BYTE *and_mask = (BYTE*)malloc(size_and);
+
+ if(FreeImage_IsTransparent(dib)) {
+
+ if(bit_count == 32) {
+ // create the AND mask from the alpha channel
+
+ int width_and = WidthBytes(width);
+ BYTE *and_bits = and_mask;
+
+ // clear the mask
+ memset(and_mask, 0, size_and);
+
+ for(int y = 0; y < height; y++) {
+ RGBQUAD *bits = (RGBQUAD*)FreeImage_GetScanLine(dib, y);
+
+ for(int x = 0; x < width; x++) {
+ if(bits[x].rgbReserved != 0xFF) {
+ // set any transparent color to full transparency
+ and_bits[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ }
+
+ and_bits += width_and;
+ }
+ }
+ else if(bit_count <= 8) {
+ // create the AND mask from the transparency table
+
+ BYTE *trns = FreeImage_GetTransparencyTable(dib);
+
+ int width_and = WidthBytes(width);
+ BYTE *and_bits = and_mask;
+
+ // clear the mask
+ memset(and_mask, 0, size_and);
+
+ switch(FreeImage_GetBPP(dib)) {
+ case 1:
+ {
+ for(int y = 0; y < height; y++) {
+ BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < width; x++) {
+ // get pixel at (x, y)
+ BYTE index = (bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
+ if(trns[index] != 0xFF) {
+ // set any transparent color to full transparency
+ and_bits[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ }
+ and_bits += width_and;
+ }
+ }
+ break;
+
+ case 4:
+ {
+ for(int y = 0; y < height; y++) {
+ BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < width; x++) {
+ // get pixel at (x, y)
+ BYTE shift = (BYTE)((1 - x % 2) << 2);
+ BYTE index = (bits[x >> 1] & (0x0F << shift)) >> shift;
+ if(trns[index] != 0xFF) {
+ // set any transparent color to full transparency
+ and_bits[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ }
+ and_bits += width_and;
+ }
+ }
+ break;
+
+ case 8:
+ {
+ for(int y = 0; y < height; y++) {
+ BYTE *bits = (BYTE*)FreeImage_GetScanLine(dib, y);
+ for(int x = 0; x < width; x++) {
+ // get pixel at (x, y)
+ BYTE index = bits[x];
+ if(trns[index] != 0xFF) {
+ // set any transparent color to full transparency
+ and_bits[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ }
+ and_bits += width_and;
+ }
+ }
+ break;
+
+ }
+ }
+ }
+ else {
+ // empty AND mask
+ memset(and_mask, 0, size_and);
+ }
+
+ io->write_proc(and_mask, size_and, 1, handle);
+ free(and_mask);
+
+ }
+
+ // free the vector class
+ for(k = 0; k < icon_header->idCount; k++) {
+ icon_dib = (FIBITMAP*)vPages[k];
+ FreeImage_Unload(icon_dib);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitICO(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = PageCount;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginIFF.cpp b/Source/FreeImage/PluginIFF.cpp
new file mode 100644
index 0000000..0fa074c
--- /dev/null
+++ b/Source/FreeImage/PluginIFF.cpp
@@ -0,0 +1,457 @@
+// ==========================================================
+// Deluxe Paint Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Mark Sibly (marksibly@blitzbasic.com)
+// - Aaron Shumate (trek@startreker.com)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Internal typedefs and structures
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct {
+ WORD w, h; /* raster width & height in pixels */
+ WORD x, y; /* position for this image */
+ BYTE nPlanes; /* # source bitplanes */
+ BYTE masking; /* masking technique */
+ BYTE compression; /* compression algorithm */
+ BYTE pad1; /* UNUSED. For consistency, put 0 here.*/
+ WORD transparentColor; /* transparent "color number" */
+ BYTE xAspect, yAspect; /* aspect ratio, a rational number x/y */
+ WORD pageWidth, pageHeight; /* source "page" size in pixels */
+} BMHD;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+#ifndef FREEIMAGE_BIGENDIAN
+static void
+SwapHeader(BMHD *header) {
+ SwapShort(&header->w);
+ SwapShort(&header->h);
+ SwapShort(&header->x);
+ SwapShort(&header->y);
+ SwapShort(&header->transparentColor);
+ SwapShort(&header->pageWidth);
+ SwapShort(&header->pageHeight);
+}
+#endif
+
+// ----------------------------------------------------------
+
+/* IFF chunk IDs */
+
+typedef DWORD IFF_ID;
+
+#define MAKE_ID(a, b, c, d) ((IFF_ID)(a)<<24 | (IFF_ID)(b)<<16 | (IFF_ID)(c)<<8 | (IFF_ID)(d))
+
+#define ID_FORM MAKE_ID('F', 'O', 'R', 'M') /* EA IFF 85 group identifier */
+#define ID_CAT MAKE_ID('C', 'A', 'T', ' ') /* EA IFF 85 group identifier */
+#define ID_LIST MAKE_ID('L', 'I', 'S', 'T') /* EA IFF 85 group identifier */
+#define ID_PROP MAKE_ID('P', 'R', 'O', 'P') /* EA IFF 85 group identifier */
+#define ID_END MAKE_ID('E', 'N', 'D', ' ') /* unofficial END-of-FORM identifier (see Amiga RKM Devices Ed.3 page 376) */
+
+#define ID_ILBM MAKE_ID('I', 'L', 'B', 'M') /* EA IFF 85 raster bitmap form */
+#define ID_DEEP MAKE_ID('D', 'E', 'E', 'P') /* Chunky pixel image files (Used in TV Paint) */
+#define ID_RGB8 MAKE_ID('R', 'G', 'B', '8') /* RGB image forms, Turbo Silver (Impulse) */
+#define ID_RGBN MAKE_ID('R', 'G', 'B', 'N') /* RGB image forms, Turbo Silver (Impulse) */
+#define ID_PBM MAKE_ID('P', 'B', 'M', ' ') /* 256-color chunky format (DPaint 2 ?) */
+#define ID_ACBM MAKE_ID('A', 'C', 'B', 'M') /* Amiga Contiguous Bitmap (AmigaBasic) */
+/* generic */
+#define ID_FVER MAKE_ID('F', 'V', 'E', 'R') /* AmigaOS version string */
+#define ID_JUNK MAKE_ID('J', 'U', 'N', 'K') /* always ignore this chunk */
+#define ID_ANNO MAKE_ID('A', 'N', 'N', 'O') /* EA IFF 85 Generic Annotation chunk */
+#define ID_AUTH MAKE_ID('A', 'U', 'T', 'H') /* EA IFF 85 Generic Author chunk */
+#define ID_CHRS MAKE_ID('C', 'H', 'R', 'S') /* EA IFF 85 Generic character string chunk */
+#define ID_NAME MAKE_ID('N', 'A', 'M', 'E') /* EA IFF 85 Generic Name of art, music, etc. chunk */
+#define ID_TEXT MAKE_ID('T', 'E', 'X', 'T') /* EA IFF 85 Generic unformatted ASCII text chunk */
+#define ID_copy MAKE_ID('(', 'c', ')', ' ') /* EA IFF 85 Generic Copyright text chunk */
+/* ILBM chunks */
+#define ID_BMHD MAKE_ID('B', 'M', 'H', 'D') /* ILBM BitmapHeader */
+#define ID_CMAP MAKE_ID('C', 'M', 'A', 'P') /* ILBM 8bit RGB colormap */
+#define ID_GRAB MAKE_ID('G', 'R', 'A', 'B') /* ILBM "hotspot" coordiantes */
+#define ID_DEST MAKE_ID('D', 'E', 'S', 'T') /* ILBM destination image info */
+#define ID_SPRT MAKE_ID('S', 'P', 'R', 'T') /* ILBM sprite identifier */
+#define ID_CAMG MAKE_ID('C', 'A', 'M', 'G') /* Amiga viewportmodes */
+#define ID_BODY MAKE_ID('B', 'O', 'D', 'Y') /* ILBM image data */
+#define ID_CRNG MAKE_ID('C', 'R', 'N', 'G') /* color cycling */
+#define ID_CCRT MAKE_ID('C', 'C', 'R', 'T') /* color cycling */
+#define ID_CLUT MAKE_ID('C', 'L', 'U', 'T') /* Color Lookup Table chunk */
+#define ID_DPI MAKE_ID('D', 'P', 'I', ' ') /* Dots per inch chunk */
+#define ID_DPPV MAKE_ID('D', 'P', 'P', 'V') /* DPaint perspective chunk (EA) */
+#define ID_DRNG MAKE_ID('D', 'R', 'N', 'G') /* DPaint IV enhanced color cycle chunk (EA) */
+#define ID_EPSF MAKE_ID('E', 'P', 'S', 'F') /* Encapsulated Postscript chunk */
+#define ID_CMYK MAKE_ID('C', 'M', 'Y', 'K') /* Cyan, Magenta, Yellow, & Black color map (Soft-Logik) */
+#define ID_CNAM MAKE_ID('C', 'N', 'A', 'M') /* Color naming chunk (Soft-Logik) */
+#define ID_PCHG MAKE_ID('P', 'C', 'H', 'G') /* Line by line palette control information (Sebastiano Vigna) */
+#define ID_PRVW MAKE_ID('P', 'R', 'V', 'W') /* A mini duplicate ILBM used for preview (Gary Bonham) */
+#define ID_XBMI MAKE_ID('X', 'B', 'M', 'I') /* eXtended BitMap Information (Soft-Logik) */
+#define ID_CTBL MAKE_ID('C', 'T', 'B', 'L') /* Newtek Dynamic Ham color chunk */
+#define ID_DYCP MAKE_ID('D', 'Y', 'C', 'P') /* Newtek Dynamic Ham chunk */
+#define ID_SHAM MAKE_ID('S', 'H', 'A', 'M') /* Sliced HAM color chunk */
+#define ID_ABIT MAKE_ID('A', 'B', 'I', 'T') /* ACBM body chunk */
+#define ID_DCOL MAKE_ID('D', 'C', 'O', 'L') /* unofficial direct color */
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "IFF";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "IFF Interleaved Bitmap";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "iff,lbm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-iff";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ DWORD type = 0;
+
+ // read chunk type
+ io->read_proc(&type, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ if(type != ID_FORM)
+ return FALSE;
+
+ // skip 4 bytes
+ io->read_proc(&type, 4, 1, handle);
+
+ // read chunk type
+ io->read_proc(&type, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ // File format : ID_PBM = Packed Bitmap, ID_ILBM = Interleaved Bitmap
+ return (type == ID_ILBM) || (type == ID_PBM);
+}
+
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle != NULL) {
+ FIBITMAP *dib = NULL;
+
+ DWORD type, size;
+
+ io->read_proc(&type, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ if(type != ID_FORM)
+ return NULL;
+
+ io->read_proc(&size, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&size);
+#endif
+
+ io->read_proc(&type, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&type);
+#endif
+
+ if((type != ID_ILBM) && (type != ID_PBM))
+ return NULL;
+
+ size -= 4;
+
+ unsigned width = 0, height = 0, planes = 0, depth = 0, comp = 0;
+
+ while (size) {
+ DWORD ch_type,ch_size;
+
+ io->read_proc(&ch_type, 4, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&ch_type);
+#endif
+
+ io->read_proc(&ch_size,4,1,handle );
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapLong(&ch_size);
+#endif
+
+ unsigned ch_end = io->tell_proc(handle) + ch_size;
+
+ if (ch_type == ID_BMHD) { // Bitmap Header
+ if (dib)
+ FreeImage_Unload(dib);
+
+ BMHD bmhd;
+
+ io->read_proc(&bmhd, sizeof(bmhd), 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapHeader(&bmhd);
+#endif
+
+ width = bmhd.w;
+ height = bmhd.h;
+ planes = bmhd.nPlanes;
+ comp = bmhd.compression;
+
+ if(bmhd.masking & 1)
+ planes++; // there is a mask ( 'stencil' )
+
+ if (planes > 8 && planes != 24)
+ return NULL;
+
+ depth = planes > 8 ? 24 : 8;
+
+ if( depth == 24 ) {
+ dib = FreeImage_Allocate(width, height, depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate(width, height, depth);
+ }
+ } else if (ch_type == ID_CMAP) { // Palette (Color Map)
+ if (!dib)
+ return NULL;
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ for (unsigned k = 0; k < ch_size / 3; k++) {
+ io->read_proc(&pal[k].rgbRed, 1, 1, handle );
+ io->read_proc(&pal[k].rgbGreen, 1, 1, handle );
+ io->read_proc(&pal[k].rgbBlue, 1, 1, handle );
+ }
+ } else if (ch_type == ID_BODY) {
+ if (!dib)
+ return NULL;
+
+ if (type == ID_PBM) {
+ // NON INTERLACED (LBM)
+
+ unsigned line = FreeImage_GetLine(dib) + 1 & ~1;
+
+ for (unsigned i = 0; i < FreeImage_GetHeight(dib); i++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - i - 1);
+
+ if (comp == 1) {
+ // use RLE compression
+
+ DWORD number_of_bytes_written = 0;
+ BYTE rle_count;
+ BYTE byte;
+
+ while (number_of_bytes_written < line) {
+ io->read_proc(&rle_count, 1, 1, handle);
+
+ if (rle_count < 128) {
+ for (int k = 0; k < rle_count + 1; k++) {
+ io->read_proc(&byte, 1, 1, handle);
+
+ bits[number_of_bytes_written++] += byte;
+ }
+ } else if (rle_count > 128) {
+ io->read_proc(&byte, 1, 1, handle);
+
+ for (int k = 0; k < 257 - rle_count; k++) {
+ bits[number_of_bytes_written++] += byte;
+ }
+ }
+ }
+ } else {
+ // don't use compression
+
+ io->read_proc(bits, line, 1, handle);
+ }
+ }
+
+ return dib;
+ } else {
+ // INTERLACED (ILBM)
+
+ unsigned pixel_size = depth/8;
+ unsigned n_width=(width+15)&~15;
+ unsigned plane_size = n_width/8;
+ unsigned src_size = plane_size * planes;
+ BYTE *src = (BYTE*)malloc(src_size);
+ BYTE *dest = FreeImage_GetBits(dib);
+
+ dest += FreeImage_GetPitch(dib) * height;
+
+ for (unsigned y = 0; y < height; y++) {
+ dest -= FreeImage_GetPitch(dib);
+
+ // read all planes in one hit,
+ // 'coz PSP compresses across planes...
+
+ if (comp) {
+ // unpacker algorithm
+
+ for(unsigned x = 0; x < src_size;) {
+ // read the next source byte into t
+ signed char t = 0;
+ io->read_proc(&t, 1, 1, handle);
+
+ if (t >= 0) {
+ // t = [0..127] => copy the next t+1 bytes literally
+ unsigned size_to_read = t + 1;
+
+ if((size_to_read + x) > src_size) {
+ // sanity check for buffer overruns
+ size_to_read = src_size - x;
+ io->read_proc(src + x, size_to_read, 1, handle);
+ x += (t + 1);
+ } else {
+ io->read_proc(src + x, size_to_read, 1, handle);
+ x += size_to_read;
+ }
+ } else if (t != -128) {
+ // t = [-1..-127] => replicate the next byte -t+1 times
+ BYTE b = 0;
+ io->read_proc(&b, 1, 1, handle);
+ unsigned size_to_copy = (unsigned)(-(int)t + 1);
+
+ if((size_to_copy + x) > src_size) {
+ // sanity check for buffer overruns
+ size_to_copy = src_size - x;
+ memset(src + x, b, size_to_copy);
+ x += (unsigned)(-(int)t + 1);
+ } else {
+ memset(src + x, b, size_to_copy);
+ x += size_to_copy;
+ }
+ }
+ // t = -128 => noop
+ }
+ } else {
+ io->read_proc(src, src_size, 1, handle);
+ }
+
+ // lazy planar->chunky...
+
+ for (unsigned x = 0; x < width; x++) {
+ for (unsigned n = 0; n < planes; n++) {
+ BYTE bit = (BYTE)( src[n * plane_size + (x / 8)] >> ((x^7) & 7) );
+
+ dest[x * pixel_size + (n / 8)] |= (bit & 1) << (n & 7);
+ }
+ }
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ if (depth == 24) {
+ for (unsigned x = 0; x < width; ++x){
+ INPLACESWAP(dest[x * 3], dest[x * 3 + 2]);
+ }
+ }
+#endif
+ }
+
+ free(src);
+
+ return dib;
+ }
+ }
+
+ // Every odd-length chunk is followed by a 0 pad byte. This pad
+ // byte is not counted in ch_size.
+ if (ch_size & 1) {
+ ch_size++;
+ ch_end++;
+ }
+
+ io->seek_proc(handle, ch_end - io->tell_proc(handle), SEEK_CUR);
+
+ size -= ch_size + 8;
+ }
+
+ if (dib)
+ FreeImage_Unload(dib);
+ }
+
+ return 0;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitIFF(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginJ2K.cpp b/Source/FreeImage/PluginJ2K.cpp
new file mode 100644
index 0000000..b986c56
--- /dev/null
+++ b/Source/FreeImage/PluginJ2K.cpp
@@ -0,0 +1,335 @@
+// ==========================================================
+// JPEG2000 J2K codestream Loader and Writer
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../LibOpenJPEG/openjpeg.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Helper functions (see J2KHelper.cpp)
+// ==========================================================
+
+FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image);
+opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters);
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+/**
+OpenJPEG Error callback
+*/
+static void j2k_error_callback(const char *msg, void *client_data) {
+ FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg);
+}
+/**
+OpenJPEG Warning callback
+*/
+static void j2k_warning_callback(const char *msg, void *client_data) {
+ FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg);
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "J2K";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "JPEG-2000 codestream";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "j2k,j2c";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/j2k";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE jpc_signature[] = { 0xFF, 0x4F };
+ BYTE signature[2] = { 0, 0 };
+
+ long tell = io->tell_proc(handle);
+ io->read_proc(signature, 1, sizeof(jpc_signature), handle);
+ io->seek_proc(handle, tell, SEEK_SET);
+
+ return (memcmp(jpc_signature, signature, sizeof(jpc_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 8) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_BITMAP) ||
+ (type == FIT_UINT16) ||
+ (type == FIT_RGB16) ||
+ (type == FIT_RGBA16)
+ );
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ return NULL;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle) {
+ opj_dparameters_t parameters; // decompression parameters
+ opj_event_mgr_t event_mgr; // event manager
+ opj_image_t *image = NULL; // decoded image
+
+ BYTE *src = NULL;
+ long file_length;
+
+ opj_dinfo_t* dinfo = NULL; // handle to a decompressor
+ opj_cio_t *cio = NULL;
+
+ FIBITMAP *dib = NULL;
+
+ // check the file format
+ if(!Validate(io, handle)) {
+ return NULL;
+ }
+
+ // configure the event callbacks
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = j2k_error_callback;
+ event_mgr.warning_handler = j2k_warning_callback;
+ event_mgr.info_handler = NULL;
+
+ // set decoding parameters to default values
+ opj_set_default_decoder_parameters(&parameters);
+
+ try {
+ // read the input file and put it in memory
+
+ long start_pos = io->tell_proc(handle);
+ io->seek_proc(handle, 0, SEEK_END);
+ file_length = io->tell_proc(handle) - start_pos;
+ io->seek_proc(handle, start_pos, SEEK_SET);
+ src = (BYTE*)malloc(file_length * sizeof(BYTE));
+ if(!src) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ if(io->read_proc(src, 1, file_length, handle) < 1) {
+ throw "Error while reading input stream";
+ }
+
+ // decode the JPEG-2000 codestream
+
+ // get a decoder handle
+ dinfo = opj_create_decompress(CODEC_J2K);
+
+ // catch events using our callbacks
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
+
+ // setup the decoder decoding parameters using user parameters
+ opj_setup_decoder(dinfo, &parameters);
+
+ // open a byte stream
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+
+ // decode the stream and fill the image structure
+ image = opj_decode(dinfo, cio);
+ if(!image) {
+ throw "Failed to decode image!\n";
+ }
+
+ // close the byte stream
+ opj_cio_close(cio);
+ cio = NULL;
+
+ // free the memory containing the code-stream
+ free(src);
+ src = NULL;
+
+ // free the codec context
+ opj_destroy_decompress(dinfo);
+
+ // create output image
+ dib = J2KImageToFIBITMAP(s_format_id, image);
+ if(!dib) throw "Failed to import JPEG2000 image";
+
+ // free image data structure
+ opj_image_destroy(image);
+
+ return dib;
+
+ } catch (const char *text) {
+ if(src) free(src);
+ if(dib) FreeImage_Unload(dib);
+ // free remaining structures
+ opj_destroy_decompress(dinfo);
+ opj_image_destroy(image);
+ // close the byte stream
+ if(cio) opj_cio_close(cio);
+
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib) && (handle)) {
+ BOOL bSuccess;
+ opj_cparameters_t parameters; // compression parameters
+ opj_event_mgr_t event_mgr; // event manager
+ opj_image_t *image = NULL; // image to encode
+ opj_cinfo_t* cinfo = NULL; // codec context
+ opj_cio_t *cio = NULL; // memory byte stream
+
+ // configure the event callbacks
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = j2k_error_callback;
+ event_mgr.warning_handler = j2k_warning_callback;
+ event_mgr.info_handler = NULL;
+
+ // set encoding parameters to default values
+ opj_set_default_encoder_parameters(&parameters);
+
+ // if no rate entered, apply a 16:1 rate by default
+ if(flags == J2K_DEFAULT) {
+ parameters.tcp_rates[0] = (float)16;
+ } else {
+ // for now, the flags parameter is only used to specify the rate
+ parameters.tcp_rates[0] = (float)flags;
+ }
+ parameters.tcp_numlayers++;
+ parameters.cp_disto_alloc = 1;
+
+ try {
+ // convert the dib to a OpenJPEG image
+ image = FIBITMAPToJ2KImage(s_format_id, dib, &parameters);
+ if(!image) return FALSE;
+
+ // encode the destination image
+
+ // get a J2K compressor handle
+ cinfo = opj_create_compress(CODEC_J2K);
+
+ // catch events using our callbacks
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, NULL);
+
+ // setup the encoder parameters using the current image and using user parameters
+ opj_setup_encoder(cinfo, &parameters, image);
+
+ // open a byte stream for writing, allocate memory for all tiles
+ cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
+
+ // encode the image
+ bSuccess = opj_encode(cinfo, cio, image, NULL/*parameters.index*/);
+ if (!bSuccess) {
+ throw "Failed to encode image";
+ }
+ int codestream_length = cio_tell(cio);
+
+ // write the buffer to user's IO handle
+ io->write_proc(cio->buffer, 1, codestream_length, handle);
+
+ // close and free the byte stream
+ opj_cio_close(cio);
+
+ // free remaining compression structures
+ opj_destroy_compress(cinfo);
+
+ // free image data
+ opj_image_destroy(image);
+
+ return TRUE;
+
+ } catch (const char *text) {
+ if(cio) opj_cio_close(cio);
+ if(cinfo) opj_destroy_compress(cinfo);
+ if(image) opj_image_destroy(image);
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitJ2K(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginJP2.cpp b/Source/FreeImage/PluginJP2.cpp
new file mode 100644
index 0000000..2a22d5a
--- /dev/null
+++ b/Source/FreeImage/PluginJP2.cpp
@@ -0,0 +1,335 @@
+// ==========================================================
+// JPEG2000 JP2 file format Loader and Writer
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../LibOpenJPEG/openjpeg.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Helper functions (see J2KHelper.cpp)
+// ==========================================================
+
+FIBITMAP* J2KImageToFIBITMAP(int format_id, const opj_image_t *image);
+opj_image_t* FIBITMAPToJ2KImage(int format_id, FIBITMAP *dib, const opj_cparameters_t *parameters);
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+/**
+OpenJPEG Error callback
+*/
+static void jp2_error_callback(const char *msg, void *client_data) {
+ FreeImage_OutputMessageProc(s_format_id, "Error: %s", msg);
+}
+/**
+OpenJPEG Warning callback
+*/
+static void jp2_warning_callback(const char *msg, void *client_data) {
+ FreeImage_OutputMessageProc(s_format_id, "Warning: %s", msg);
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "JP2";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "JPEG-2000 File Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "jp2";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/jp2";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE jp2_signature[] = { 0x00, 0x00, 0x00, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
+ BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ long tell = io->tell_proc(handle);
+ io->read_proc(signature, 1, sizeof(jp2_signature), handle);
+ io->seek_proc(handle, tell, SEEK_SET);
+
+ return (memcmp(jp2_signature, signature, sizeof(jp2_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 8) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_BITMAP) ||
+ (type == FIT_UINT16) ||
+ (type == FIT_RGB16) ||
+ (type == FIT_RGBA16)
+ );
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ return NULL;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle) {
+ opj_dparameters_t parameters; // decompression parameters
+ opj_event_mgr_t event_mgr; // event manager
+ opj_image_t *image = NULL; // decoded image
+
+ BYTE *src = NULL;
+ long file_length;
+
+ opj_dinfo_t* dinfo = NULL; // handle to a decompressor
+ opj_cio_t *cio = NULL;
+
+ FIBITMAP *dib = NULL;
+
+ // check the file format
+ if(!Validate(io, handle)) {
+ return NULL;
+ }
+
+ // configure the event callbacks
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = jp2_error_callback;
+ event_mgr.warning_handler = jp2_warning_callback;
+ event_mgr.info_handler = NULL;
+
+ // set decoding parameters to default values
+ opj_set_default_decoder_parameters(&parameters);
+
+ try {
+ // read the input file and put it in memory
+
+ long start_pos = io->tell_proc(handle);
+ io->seek_proc(handle, 0, SEEK_END);
+ file_length = io->tell_proc(handle) - start_pos;
+ io->seek_proc(handle, start_pos, SEEK_SET);
+ src = (BYTE*)malloc(file_length * sizeof(BYTE));
+ if(!src) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ if(io->read_proc(src, 1, file_length, handle) < 1) {
+ throw "Error while reading input stream";
+ }
+
+ // decode the JPEG-2000 file
+
+ // get a decoder handle
+ dinfo = opj_create_decompress(CODEC_JP2);
+
+ // catch events using our callbacks
+ opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, NULL);
+
+ // setup the decoder decoding parameters using user parameters
+ opj_setup_decoder(dinfo, &parameters);
+
+ // open a byte stream
+ cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+
+ // decode the stream and fill the image structure
+ image = opj_decode(dinfo, cio);
+ if(!image) {
+ throw "Failed to decode image!\n";
+ }
+
+ // close the byte stream
+ opj_cio_close(cio);
+ cio = NULL;
+
+ // free the memory containing the code-stream
+ free(src);
+ src = NULL;
+
+ // free the codec context
+ opj_destroy_decompress(dinfo);
+
+ // create output image
+ dib = J2KImageToFIBITMAP(s_format_id, image);
+ if(!dib) throw "Failed to import JPEG2000 image";
+
+ // free image data structure
+ opj_image_destroy(image);
+
+ return dib;
+
+ } catch (const char *text) {
+ if(src) free(src);
+ if(dib) FreeImage_Unload(dib);
+ // free remaining structures
+ opj_destroy_decompress(dinfo);
+ opj_image_destroy(image);
+ // close the byte stream
+ if(cio) opj_cio_close(cio);
+
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib) && (handle)) {
+ BOOL bSuccess;
+ opj_cparameters_t parameters; // compression parameters
+ opj_event_mgr_t event_mgr; // event manager
+ opj_image_t *image = NULL; // image to encode
+ opj_cinfo_t* cinfo = NULL; // codec context
+ opj_cio_t *cio = NULL; // memory byte stream
+
+ // configure the event callbacks
+ memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
+ event_mgr.error_handler = jp2_error_callback;
+ event_mgr.warning_handler = jp2_warning_callback;
+ event_mgr.info_handler = NULL;
+
+ // set encoding parameters to default values
+ opj_set_default_encoder_parameters(&parameters);
+
+ // if no rate entered, apply a 16:1 rate by default
+ if(flags == JP2_DEFAULT) {
+ parameters.tcp_rates[0] = (float)16;
+ } else {
+ // for now, the flags parameter is only used to specify the rate
+ parameters.tcp_rates[0] = (float)flags;
+ }
+ parameters.tcp_numlayers++;
+ parameters.cp_disto_alloc = 1;
+
+ try {
+ // convert the dib to a OpenJPEG image
+ image = FIBITMAPToJ2KImage(s_format_id, dib, &parameters);
+ if(!image) return FALSE;
+
+ // encode the destination image
+
+ // get a J2K compressor handle
+ cinfo = opj_create_compress(CODEC_JP2);
+
+ // catch events using our callbacks
+ opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, NULL);
+
+ // setup the encoder parameters using the current image and using user parameters
+ opj_setup_encoder(cinfo, &parameters, image);
+
+ // open a byte stream for writing, allocate memory for all tiles
+ cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
+
+ // encode the image
+ bSuccess = opj_encode(cinfo, cio, image, NULL/*parameters.index*/);
+ if (!bSuccess) {
+ throw "Failed to encode image";
+ }
+ int codestream_length = cio_tell(cio);
+
+ // write the buffer to user's IO handle
+ io->write_proc(cio->buffer, 1, codestream_length, handle);
+
+ // close and free the byte stream
+ opj_cio_close(cio);
+
+ // free remaining compression structures
+ opj_destroy_compress(cinfo);
+
+ // free image data
+ opj_image_destroy(image);
+
+ return TRUE;
+
+ } catch (const char *text) {
+ if(cio) opj_cio_close(cio);
+ if(cinfo) opj_destroy_compress(cinfo);
+ if(image) opj_image_destroy(image);
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitJP2(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginJPEG.cpp b/Source/FreeImage/PluginJPEG.cpp
new file mode 100644
index 0000000..36115cd
--- /dev/null
+++ b/Source/FreeImage/PluginJPEG.cpp
@@ -0,0 +1,1448 @@
+// ==========================================================
+// JPEG Loader and writer
+// Based on code developed by The Independent JPEG Group
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Jan L. Nauta (jln@magentammt.com)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Karl-Heinz Bussian (khbussian@moss.de)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jascha Wetzel (jascha@mainia.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+extern "C" {
+#define XMD_H
+#undef FAR
+#include <setjmp.h>
+
+#include "../LibJPEG/jinclude.h"
+#include "../LibJPEG/jpeglib.h"
+#include "../LibJPEG/jerror.h"
+}
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+#include "../Metadata/FreeImageTag.h"
+
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ----------------------------------------------------------
+// Constant declarations
+// ----------------------------------------------------------
+
+#define INPUT_BUF_SIZE 4096 // choose an efficiently fread'able size
+#define OUTPUT_BUF_SIZE 4096 // choose an efficiently fwrite'able size
+
+#define EXIF_MARKER (JPEG_APP0+1) // EXIF marker / Adobe XMP marker
+#define ICC_MARKER (JPEG_APP0+2) // ICC profile marker
+#define IPTC_MARKER (JPEG_APP0+13) // IPTC marker / BIM marker
+
+#define ICC_HEADER_SIZE 14 // size of non-profile data in APP2
+#define MAX_BYTES_IN_MARKER 65533L // maximum data length of a JPEG marker
+#define MAX_DATA_BYTES_IN_MARKER 65519L // maximum data length of a JPEG APP2 marker
+
+// ----------------------------------------------------------
+// Typedef declarations
+// ----------------------------------------------------------
+
+typedef struct tagErrorManager {
+ /// "public" fields
+ struct jpeg_error_mgr pub;
+ /// for return to caller
+ jmp_buf setjmp_buffer;
+} ErrorManager;
+
+typedef struct tagSourceManager {
+ /// public fields
+ struct jpeg_source_mgr pub;
+ /// source stream
+ fi_handle infile;
+ FreeImageIO *m_io;
+ /// start of buffer
+ JOCTET * buffer;
+ /// have we gotten any data yet ?
+ boolean start_of_file;
+} SourceManager;
+
+typedef struct tagDestinationManager {
+ /// public fields
+ struct jpeg_destination_mgr pub;
+ /// destination stream
+ fi_handle outfile;
+ FreeImageIO *m_io;
+ /// start of buffer
+ JOCTET * buffer;
+} DestinationManager;
+
+typedef SourceManager* freeimage_src_ptr;
+typedef DestinationManager* freeimage_dst_ptr;
+typedef ErrorManager* freeimage_error_ptr;
+
+// ----------------------------------------------------------
+// Error handling
+// ----------------------------------------------------------
+
+/**
+ Receives control for a fatal error. Information sufficient to
+ generate the error message has been stored in cinfo->err; call
+ output_message to display it. Control must NOT return to the caller;
+ generally this routine will exit() or longjmp() somewhere.
+*/
+METHODDEF(void)
+jpeg_error_exit (j_common_ptr cinfo) {
+ // always display the message
+ (*cinfo->err->output_message)(cinfo);
+
+ // allow JPEG with a premature end of file
+ if((cinfo)->err->msg_parm.i[0] != 13) {
+
+ // let the memory manager delete any temp files before we die
+ jpeg_destroy(cinfo);
+
+ throw s_format_id;
+ }
+}
+
+/**
+ Actual output of any JPEG message. Note that this method does not know
+ how to generate a message, only where to send it.
+*/
+METHODDEF(void)
+jpeg_output_message (j_common_ptr cinfo) {
+ char buffer[JMSG_LENGTH_MAX];
+
+ // create the message
+ (*cinfo->err->format_message)(cinfo, buffer);
+ // send it to user's message proc
+ FreeImage_OutputMessageProc(s_format_id, buffer);
+}
+
+// ----------------------------------------------------------
+// Destination manager
+// ----------------------------------------------------------
+
+/**
+ Initialize destination. This is called by jpeg_start_compress()
+ before any data is actually written. It must initialize
+ next_output_byte and free_in_buffer. free_in_buffer must be
+ initialized to a positive value.
+*/
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo) {
+ freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
+
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+/**
+ This is called whenever the buffer has filled (free_in_buffer
+ reaches zero). In typical applications, it should write out the
+ *entire* buffer (use the saved start address and buffer length;
+ ignore the current state of next_output_byte and free_in_buffer).
+ Then reset the pointer & count to the start of the buffer, and
+ return TRUE indicating that the buffer has been dumped.
+ free_in_buffer must be set to a positive value when TRUE is
+ returned. A FALSE return should only be used when I/O suspension is
+ desired.
+*/
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo) {
+ freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
+
+ if (dest->m_io->write_proc(dest->buffer, 1, OUTPUT_BUF_SIZE, dest->outfile) != OUTPUT_BUF_SIZE)
+ throw(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+/**
+ Terminate destination --- called by jpeg_finish_compress() after all
+ data has been written. In most applications, this must flush any
+ data remaining in the buffer. Use either next_output_byte or
+ free_in_buffer to determine how much data is in the buffer.
+*/
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo) {
+ freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
+
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ // write any data remaining in the buffer
+
+ if (datacount > 0) {
+ if (dest->m_io->write_proc(dest->buffer, 1, (unsigned int)datacount, dest->outfile) != datacount)
+ throw(cinfo, JERR_FILE_WRITE);
+ }
+}
+
+// ----------------------------------------------------------
+// Source manager
+// ----------------------------------------------------------
+
+/**
+ Initialize source. This is called by jpeg_read_header() before any
+ data is actually read. Unlike init_destination(), it may leave
+ bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
+ will occur immediately).
+*/
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo) {
+ freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+
+ src->start_of_file = TRUE;
+}
+
+/**
+ This is called whenever bytes_in_buffer has reached zero and more
+ data is wanted. In typical applications, it should read fresh data
+ into the buffer (ignoring the current state of next_input_byte and
+ bytes_in_buffer), reset the pointer & count to the start of the
+ buffer, and return TRUE indicating that the buffer has been reloaded.
+ It is not necessary to fill the buffer entirely, only to obtain at
+ least one more byte. bytes_in_buffer MUST be set to a positive value
+ if TRUE is returned. A FALSE return should only be used when I/O
+ suspension is desired.
+*/
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo) {
+ freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
+
+ size_t nbytes = src->m_io->read_proc(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ throw(cinfo, JERR_INPUT_EMPTY);
+
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+
+ /* Insert a fake EOI marker */
+
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+
+ return TRUE;
+}
+
+/**
+ Skip num_bytes worth of data. The buffer pointer and count should
+ be advanced over num_bytes input bytes, refilling the buffer as
+ needed. This is used to skip over a potentially large amount of
+ uninteresting data (such as an APPn marker). In some applications
+ it may be possible to optimize away the reading of the skipped data,
+ but it's not clear that being smart is worth much trouble; large
+ skips are uncommon. bytes_in_buffer may be zero on return.
+ A zero or negative skip count should be treated as a no-op.
+*/
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
+ freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+
+ (void) fill_input_buffer(cinfo);
+
+ /* note we assume that fill_input_buffer will never return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+/**
+ Terminate source --- called by jpeg_finish_decompress
+ after all data has been read. Often a no-op.
+
+ NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ application must deal with any cleanup that should happen even
+ for error exit.
+*/
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo) {
+ // no work necessary here
+}
+
+// ----------------------------------------------------------
+// Source manager & Destination manager setup
+// ----------------------------------------------------------
+
+/**
+ Prepare for input from a stdio stream.
+ The caller must have already opened the stream, and is responsible
+ for closing it after finishing decompression.
+*/
+GLOBAL(void)
+jpeg_freeimage_src (j_decompress_ptr cinfo, fi_handle infile, FreeImageIO *io) {
+ freeimage_src_ptr src;
+
+ // allocate memory for the buffer. is released automatically in the end
+
+ if (cinfo->src == NULL) {
+ cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(SourceManager));
+
+ src = (freeimage_src_ptr) cinfo->src;
+
+ src->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * SIZEOF(JOCTET));
+ }
+
+ // initialize the jpeg pointer struct with pointers to functions
+
+ src = (freeimage_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->m_io = io;
+ src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
+ src->pub.next_input_byte = NULL; // until buffer loaded
+}
+
+/**
+ Prepare for output to a stdio stream.
+ The caller must have already opened the stream, and is responsible
+ for closing it after finishing compression.
+*/
+GLOBAL(void)
+jpeg_freeimage_dst (j_compress_ptr cinfo, fi_handle outfile, FreeImageIO *io) {
+ freeimage_dst_ptr dest;
+
+ if (cinfo->dest == NULL) {
+ cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(DestinationManager));
+ }
+
+ dest = (freeimage_dst_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+ dest->m_io = io;
+}
+
+// ----------------------------------------------------------
+// Special markers read functions
+// ----------------------------------------------------------
+
+/**
+ Read JPEG_COM marker (comment)
+*/
+static BOOL
+jpeg_read_comment(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ size_t length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ // read the comment
+ char *value = (char*)malloc((length + 1) * sizeof(char));
+ if(value == NULL) return FALSE;
+ memcpy(value, profile, length);
+ value[length] = '\0';
+
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(tag) {
+ unsigned int count = (unsigned int)length + 1; // includes the null value
+
+ FreeImage_SetTagID(tag, JPEG_COM);
+ FreeImage_SetTagKey(tag, "Comment");
+ FreeImage_SetTagLength(tag, count);
+ FreeImage_SetTagCount(tag, count);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, value);
+
+ // store the tag
+ FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
+
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+ }
+
+ free(value);
+
+ return TRUE;
+}
+
+/**
+ Read JPEG_APP2 marker (ICC profile)
+*/
+
+/**
+Handy subroutine to test whether a saved marker is an ICC profile marker.
+*/
+static BOOL
+marker_is_icc(jpeg_saved_marker_ptr marker) {
+ // marker identifying string "ICC_PROFILE" (null-terminated)
+ const BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 };
+
+ if(marker->marker == ICC_MARKER) {
+ // verify the identifying string
+ if(marker->data_length >= ICC_HEADER_SIZE) {
+ if(memcmp(icc_signature, marker->data, sizeof(icc_signature)) == 0) {
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ See if there was an ICC profile in the JPEG file being read;
+ if so, reassemble and return the profile data.
+
+ TRUE is returned if an ICC profile was found, FALSE if not.
+ If TRUE is returned, *icc_data_ptr is set to point to the
+ returned data, and *icc_data_len is set to its length.
+
+ IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
+ and must be freed by the caller with free() when the caller no longer
+ needs it. (Alternatively, we could write this routine to use the
+ IJG library's memory allocator, so that the data would be freed implicitly
+ at jpeg_finish_decompress() time. But it seems likely that many apps
+ will prefer to have the data stick around after decompression finishes.)
+
+ NOTE: if the file contains invalid ICC APP2 markers, we just silently
+ return FALSE. You might want to issue an error message instead.
+*/
+static BOOL
+jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned *icc_data_len) {
+ jpeg_saved_marker_ptr marker;
+ int num_markers = 0;
+ int seq_no;
+ JOCTET *icc_data;
+ unsigned total_length;
+
+ const int MAX_SEQ_NO = 255; // sufficient since marker numbers are bytes
+ BYTE marker_present[MAX_SEQ_NO+1]; // 1 if marker found
+ unsigned data_length[MAX_SEQ_NO+1]; // size of profile data in marker
+ unsigned data_offset[MAX_SEQ_NO+1]; // offset for data in marker
+
+ *icc_data_ptr = NULL; // avoid confusion if FALSE return
+ *icc_data_len = 0;
+
+ /**
+ this first pass over the saved markers discovers whether there are
+ any ICC markers and verifies the consistency of the marker numbering.
+ */
+
+ memset(marker_present, 0, (MAX_SEQ_NO + 1));
+
+ for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (marker_is_icc(marker)) {
+ if (num_markers == 0) {
+ // number of markers
+ num_markers = GETJOCTET(marker->data[13]);
+ }
+ else if (num_markers != GETJOCTET(marker->data[13])) {
+ return FALSE; // inconsistent num_markers fields
+ }
+ // sequence number
+ seq_no = GETJOCTET(marker->data[12]);
+ if (seq_no <= 0 || seq_no > num_markers) {
+ return FALSE; // bogus sequence number
+ }
+ if (marker_present[seq_no]) {
+ return FALSE; // duplicate sequence numbers
+ }
+ marker_present[seq_no] = 1;
+ data_length[seq_no] = marker->data_length - ICC_HEADER_SIZE;
+ }
+ }
+
+ if (num_markers == 0)
+ return FALSE;
+
+ /**
+ check for missing markers, count total space needed,
+ compute offset of each marker's part of the data.
+ */
+
+ total_length = 0;
+ for(seq_no = 1; seq_no <= num_markers; seq_no++) {
+ if (marker_present[seq_no] == 0) {
+ return FALSE; // missing sequence number
+ }
+ data_offset[seq_no] = total_length;
+ total_length += data_length[seq_no];
+ }
+
+ if (total_length <= 0)
+ return FALSE; // found only empty markers ?
+
+ // allocate space for assembled data
+ icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
+ if (icc_data == NULL)
+ return FALSE; // out of memory
+
+ // and fill it in
+ for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (marker_is_icc(marker)) {
+ JOCTET FAR *src_ptr;
+ JOCTET *dst_ptr;
+ unsigned length;
+ seq_no = GETJOCTET(marker->data[12]);
+ dst_ptr = icc_data + data_offset[seq_no];
+ src_ptr = marker->data + ICC_HEADER_SIZE;
+ length = data_length[seq_no];
+ while (length--) {
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ }
+
+ *icc_data_ptr = icc_data;
+ *icc_data_len = total_length;
+
+ return TRUE;
+}
+
+/**
+ Read JPEG_APPD marker (IPTC or Adobe Photoshop profile)
+*/
+BOOL
+jpeg_read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ return read_iptc_profile(dib, dataptr, datalen);
+}
+
+/**
+ Read JPEG_APP1 marker (XMP profile)
+ @param dib Input FIBITMAP
+ @param dataptr Pointer to the APP1 marker
+ @param datalen APP1 marker length
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+jpeg_read_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ // marker identifying string for XMP (null terminated)
+ char *xmp_signature = "http://ns.adobe.com/xap/1.0/";
+
+ size_t length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ // verify the identifying string
+
+ if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) {
+ // XMP profile
+
+ size_t offset = strlen(xmp_signature) + 1;
+ profile += offset;
+ length -= offset;
+
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(tag) {
+ FreeImage_SetTagID(tag, JPEG_APP0+1); // 0xFFE1
+ FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
+ FreeImage_SetTagLength(tag, (DWORD)length);
+ FreeImage_SetTagCount(tag, (DWORD)length);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, profile);
+
+ // store the tag
+ FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
+
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Read JPEG special markers
+*/
+static BOOL
+read_markers(j_decompress_ptr cinfo, FIBITMAP *dib) {
+ jpeg_saved_marker_ptr marker;
+
+ for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
+ switch(marker->marker) {
+ case JPEG_COM:
+ // JPEG comment
+ jpeg_read_comment(dib, marker->data, marker->data_length);
+ break;
+ case EXIF_MARKER:
+ // Exif or Adobe XMP profile
+ jpeg_read_exif_profile(dib, marker->data, marker->data_length);
+ jpeg_read_xmp_profile(dib, marker->data, marker->data_length);
+ break;
+ case IPTC_MARKER:
+ // IPTC/NAA or Adobe Photoshop profile
+ jpeg_read_iptc_profile(dib, marker->data, marker->data_length);
+ break;
+ }
+ }
+
+ // ICC profile
+ BYTE *icc_profile = NULL;
+ unsigned icc_length = 0;
+
+ if( jpeg_read_icc_profile(cinfo, &icc_profile, &icc_length) ) {
+ // copy ICC profile data
+ FreeImage_CreateICCProfile(dib, icc_profile, icc_length);
+ // clean up
+ free(icc_profile);
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// Special markers write functions
+// ----------------------------------------------------------
+
+/**
+ Write JPEG_COM marker (comment)
+*/
+static BOOL
+jpeg_write_comment(j_compress_ptr cinfo, FIBITMAP *dib) {
+ FITAG *tag = NULL;
+
+ // write user comment as a JPEG_COM marker
+ FreeImage_GetMetadata(FIMD_COMMENTS, dib, "Comment", &tag);
+ if(tag) {
+ const char *tag_value = (char*)FreeImage_GetTagValue(tag);
+
+ if(NULL != tag_value) {
+ for(long i = 0; i < (long)strlen(tag_value); i+= MAX_BYTES_IN_MARKER) {
+ jpeg_write_marker(cinfo, JPEG_COM, (BYTE*)tag_value + i, MIN((long)strlen(tag_value + i), MAX_BYTES_IN_MARKER));
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Write JPEG_APP2 marker (ICC profile)
+*/
+static BOOL
+jpeg_write_icc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
+ // marker identifying string "ICC_PROFILE" (null-terminated)
+ BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 };
+
+ FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
+
+ if (iccProfile->size && iccProfile->data) {
+ // ICC_HEADER_SIZE: ICC signature is 'ICC_PROFILE' + 2 bytes
+
+ BYTE *profile = (BYTE*)malloc((iccProfile->size + ICC_HEADER_SIZE) * sizeof(BYTE));
+ if(profile == NULL) return FALSE;
+ memcpy(profile, icc_signature, 12);
+
+ for(long i = 0; i < (long)iccProfile->size; i += MAX_DATA_BYTES_IN_MARKER) {
+ unsigned length = MIN((long)(iccProfile->size - i), MAX_DATA_BYTES_IN_MARKER);
+ // sequence number
+ profile[12] = (BYTE) ((i / MAX_DATA_BYTES_IN_MARKER) + 1);
+ // number of markers
+ profile[13] = (BYTE) (iccProfile->size / MAX_DATA_BYTES_IN_MARKER + 1);
+
+ memcpy(profile + ICC_HEADER_SIZE, (BYTE*)iccProfile->data + i, length);
+ jpeg_write_marker(cinfo, ICC_MARKER, profile, (length + ICC_HEADER_SIZE));
+ }
+
+ free(profile);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Write JPEG_APPD marker (IPTC or Adobe Photoshop profile)
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+jpeg_write_iptc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
+ //const char *ps_header = "Photoshop 3.0\x08BIM\x04\x04\x0\x0\x0\x0";
+ const unsigned tag_length = 26;
+
+ if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
+ BYTE *profile = NULL;
+ unsigned profile_size = 0;
+
+ // create a binary profile
+ if(write_iptc_profile(dib, &profile, &profile_size)) {
+
+ // write the profile
+ for(long i = 0; i < (long)profile_size; i += 65517L) {
+ unsigned length = MIN((long)profile_size - i, 65517L);
+ unsigned roundup = length & 0x01; // needed for Photoshop
+ BYTE *iptc_profile = (BYTE*)malloc(length + roundup + tag_length);
+ if(iptc_profile == NULL) break;
+ // Photoshop identification string
+ memcpy(&iptc_profile[0], "Photoshop 3.0\x0", 14);
+ // 8BIM segment type
+ memcpy(&iptc_profile[14], "8BIM\x04\x04\x0\x0\x0\x0", 10);
+ // segment size
+ iptc_profile[24] = (BYTE)(length >> 8);
+ iptc_profile[25] = (BYTE)(length & 0xFF);
+ // segment data
+ memcpy(&iptc_profile[tag_length], &profile[i], length);
+ if(roundup)
+ iptc_profile[length + tag_length] = 0;
+ jpeg_write_marker(cinfo, IPTC_MARKER, iptc_profile, length + roundup + tag_length);
+ free(iptc_profile);
+ }
+
+ // release profile
+ free(profile);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Write JPEG_APP1 marker (XMP profile)
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+jpeg_write_xmp_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
+ // marker identifying string for XMP (null terminated)
+ char *xmp_signature = "http://ns.adobe.com/xap/1.0/";
+
+ FITAG *tag_xmp = NULL;
+ FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
+
+ if(tag_xmp) {
+ const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_xmp);
+
+ if(NULL != tag_value) {
+ // XMP signature is 29 bytes long
+ unsigned int xmp_header_size = (unsigned int)strlen(xmp_signature) + 1;
+
+ DWORD tag_length = FreeImage_GetTagLength(tag_xmp);
+
+ BYTE *profile = (BYTE*)malloc((tag_length + xmp_header_size) * sizeof(BYTE));
+ if(profile == NULL) return FALSE;
+ memcpy(profile, xmp_signature, xmp_header_size);
+
+ for(DWORD i = 0; i < tag_length; i += 65504L) {
+ unsigned length = MIN((long)(tag_length - i), 65504L);
+
+ memcpy(profile + xmp_header_size, tag_value + i, length);
+ jpeg_write_marker(cinfo, EXIF_MARKER, profile, (length + xmp_header_size));
+ }
+
+ free(profile);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Write JPEG special markers
+*/
+static BOOL
+write_markers(j_compress_ptr cinfo, FIBITMAP *dib) {
+
+ // write user comment as a JPEG_COM marker
+ jpeg_write_comment(cinfo, dib);
+
+ // write ICC profile
+ jpeg_write_icc_profile(cinfo, dib);
+
+ // write IPTC profile
+ jpeg_write_iptc_profile(cinfo, dib);
+
+ // write Adobe XMP profile
+ jpeg_write_xmp_profile(cinfo, dib);
+
+ return TRUE;
+}
+
+// ------------------------------------------------------------
+// Keep original size info when using scale option on loading
+// ------------------------------------------------------------
+static void
+store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) {
+ char buffer[256];
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(tag) {
+ size_t length = 0;
+ // set the original width
+ sprintf(buffer, "%d", (int)width);
+ length = strlen(buffer) + 1; // include the NULL/0 value
+ FreeImage_SetTagKey(tag, "OriginalJPEGWidth");
+ FreeImage_SetTagLength(tag, (DWORD)length);
+ FreeImage_SetTagCount(tag, (DWORD)length);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, buffer);
+ FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
+ // set the original height
+ sprintf(buffer, "%d", (int)height);
+ length = strlen(buffer) + 1; // include the NULL/0 value
+ FreeImage_SetTagKey(tag, "OriginalJPEGHeight");
+ FreeImage_SetTagLength(tag, (DWORD)length);
+ FreeImage_SetTagCount(tag, (DWORD)length);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, buffer);
+ FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+ }
+}
+
+// ------------------------------------------------------------
+// Rotate a dib according to Exif info
+// ------------------------------------------------------------
+
+static void
+rotate_exif(FIBITMAP **dib) {
+ // check for Exif rotation
+ if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, *dib)) {
+ FIBITMAP *rotated = NULL;
+ // process Exif rotation
+ FITAG *tag = NULL;
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, *dib, "Orientation", &tag);
+ if(tag != NULL) {
+ if(FreeImage_GetTagID(tag) == TAG_ORIENTATION) {
+ unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (orientation) {
+ case 1: // "top, left side" => 0°
+ break;
+ case 2: // "top, right side" => flip left-right
+ FreeImage_FlipHorizontal(*dib);
+ break;
+ case 3: // "bottom, right side"; => -180°
+ rotated = FreeImage_Rotate(*dib, 180);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ case 4: // "bottom, left side" => flip up-down
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 5: // "left side, top" => +90° + flip up-down
+ rotated = FreeImage_Rotate(*dib, 90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 6: // "right side, top" => -90°
+ rotated = FreeImage_Rotate(*dib, -90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ case 7: // "right side, bottom" => -90° + flip up-down
+ rotated = FreeImage_Rotate(*dib, -90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ FreeImage_FlipVertical(*dib);
+ break;
+ case 8: // "left side, bottom" => +90°
+ rotated = FreeImage_Rotate(*dib, 90);
+ FreeImage_Unload(*dib);
+ *dib = rotated;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "JPEG";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "JPEG - JFIF Compliant";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "jpg,jif,jpeg,jpe";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^\377\330\377";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/jpeg";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE jpeg_signature[] = { 0xFF, 0xD8 };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(jpeg_signature), handle);
+
+ return (memcmp(jpeg_signature, signature, sizeof(jpeg_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 8) ||
+ (depth == 24)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle) {
+ FIBITMAP *dib = NULL;
+
+ try {
+ // set up the jpeglib structures
+
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ // step 1: allocate and initialize JPEG decompression object
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jerr.error_exit = jpeg_error_exit;
+ jerr.output_message = jpeg_output_message;
+
+ jpeg_create_decompress(&cinfo);
+
+ // step 2a: specify data source (eg, a handle)
+
+ jpeg_freeimage_src(&cinfo, handle, io);
+
+ // step 2b: save special markers for later reading
+
+ jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
+ for(int m = 0; m < 16; m++) {
+ jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF);
+ }
+
+ // step 3: read handle parameters with jpeg_read_header()
+
+ jpeg_read_header(&cinfo, TRUE);
+
+ // step 4: set parameters for decompression
+
+ unsigned int scale_denom = 1; // fraction by which to scale image
+ int requested_size = flags >> 16; // requested user size in pixels
+ if(requested_size > 0) {
+ // the JPEG codec can perform x2, x4 or x8 scaling on loading
+ // try to find the more appropriate scaling according to user's need
+ double scale = MAX((double)cinfo.image_width, (double)cinfo.image_height) / (double)requested_size;
+ if(scale >= 8) {
+ scale_denom = 8;
+ } else if(scale >= 4) {
+ scale_denom = 4;
+ } else if(scale >= 2) {
+ scale_denom = 2;
+ }
+ }
+ cinfo.scale_num = 1;
+ cinfo.scale_denom = scale_denom;
+
+ if ((flags & JPEG_ACCURATE) != JPEG_ACCURATE) {
+ cinfo.dct_method = JDCT_IFAST;
+ cinfo.do_fancy_upsampling = FALSE;
+ }
+
+ // step 5a: start decompressor and calculate output width and height
+
+ jpeg_start_decompress(&cinfo);
+
+ // step 5b: allocate dib and init header
+
+ if((cinfo.num_components == 4) && (cinfo.out_color_space == JCS_CMYK)) {
+ // CMYK image
+ if((flags & JPEG_CMYK) == JPEG_CMYK) {
+ // load as CMYK
+ dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(!dib) return NULL;
+ FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
+ } else {
+ // load as CMYK and convert to RGB
+ dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(!dib) return NULL;
+ }
+ } else {
+ // RGB or greyscale image
+ dib = FreeImage_Allocate(cinfo.output_width, cinfo.output_height, 8 * cinfo.num_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(!dib) return NULL;
+
+ if (cinfo.num_components == 1) {
+ // build a greyscale palette
+ RGBQUAD *colors = FreeImage_GetPalette(dib);
+
+ for (int i = 0; i < 256; i++) {
+ colors[i].rgbRed = (BYTE)i;
+ colors[i].rgbGreen = (BYTE)i;
+ colors[i].rgbBlue = (BYTE)i;
+ }
+ }
+ }
+ if(scale_denom != 1) {
+ // store original size info if a scaling was requested
+ store_size_info(dib, cinfo.image_width, cinfo.image_height);
+ }
+
+ // step 5c: handle metrices
+
+ if (cinfo.density_unit == 1) {
+ // dots/inch
+ FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)cinfo.X_density) / 0.0254000 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)cinfo.Y_density) / 0.0254000 + 0.5));
+ } else if (cinfo.density_unit == 2) {
+ // dots/cm
+ FreeImage_SetDotsPerMeterX(dib, (unsigned) (cinfo.X_density * 100));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned) (cinfo.Y_density * 100));
+ }
+
+ // step 6a: while (scan lines remain to be read) jpeg_read_scanlines(...);
+
+ if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) != JPEG_CMYK)) {
+ // convert from CMYK to RGB
+
+ JSAMPARRAY buffer; // output row buffer
+ unsigned row_stride; // physical row width in output buffer
+
+ // JSAMPLEs per row in output buffer
+ row_stride = cinfo.output_width * cinfo.output_components;
+ // make a one-row-high sample array that will go away when done with image
+ buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ JSAMPROW src = buffer[0];
+ JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
+
+ jpeg_read_scanlines(&cinfo, buffer, 1);
+
+ for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ WORD K = (WORD)src[3];
+ dst[FI_RGBA_RED] = (BYTE)((K * src[0]) / 255);
+ dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255);
+ dst[FI_RGBA_BLUE] = (BYTE)((K * src[2]) / 255);
+ src += 4;
+ dst += 3;
+ }
+ }
+ } else {
+ // normal case (RGB or greyscale image)
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
+
+ jpeg_read_scanlines(&cinfo, &dst, 1);
+ }
+
+ // step 6b: swap red and blue components (see LibJPEG/jmorecfg.h: #define RGB_RED, ...)
+ // The default behavior of the JPEG library is kept "as is" because LibTIFF uses
+ // LibJPEG "as is".
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ if(cinfo.num_components == 3) {
+ for(unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ BYTE *target = FreeImage_GetScanLine(dib, y);
+ for(unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ INPLACESWAP(target[0], target[2]);
+ target += 3;
+ }
+ }
+ }
+#endif
+ }
+
+ // step 7: read special markers
+
+ read_markers(&cinfo, dib);
+
+ // step 8: finish decompression
+
+ jpeg_finish_decompress(&cinfo);
+
+ // step 9: release JPEG decompression object
+
+ jpeg_destroy_decompress(&cinfo);
+
+ // check for automatic Exif rotation
+ if((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE) {
+ rotate_exif(&dib);
+ }
+
+ // everything went well. return the loaded dib
+
+ return (FIBITMAP *)dib;
+ } catch (...) {
+ if(NULL != dib) {
+ FreeImage_Unload(dib);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib) && (handle)) {
+ try {
+ // Check dib format
+
+ const char *sError = "only 24-bit highcolor or 8-bit greyscale/palette bitmaps can be saved as JPEG";
+
+ FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
+ WORD bpp = (WORD)FreeImage_GetBPP(dib);
+
+ if ((bpp != 24) && (bpp != 8))
+ throw sError;
+
+ if(bpp == 8) {
+ // allow grey, reverse grey and palette
+ if ((color_type != FIC_MINISBLACK) && (color_type != FIC_MINISWHITE) && (color_type != FIC_PALETTE))
+ throw sError;
+ }
+
+
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ // Step 1: allocate and initialize JPEG compression object
+
+ cinfo.err = jpeg_std_error(&jerr);
+
+ jerr.error_exit = jpeg_error_exit;
+ jerr.output_message = jpeg_output_message;
+
+ // Now we can initialize the JPEG compression object
+
+ jpeg_create_compress(&cinfo);
+
+ // Step 2: specify data destination (eg, a file)
+
+ jpeg_freeimage_dst(&cinfo, handle, io);
+
+ // Step 3: set parameters for compression
+
+ cinfo.image_width = FreeImage_GetWidth(dib);
+ cinfo.image_height = FreeImage_GetHeight(dib);
+
+ switch(color_type) {
+ case FIC_MINISBLACK :
+ case FIC_MINISWHITE :
+ cinfo.in_color_space = JCS_GRAYSCALE;
+ cinfo.input_components = 1;
+ break;
+
+ default :
+ cinfo.in_color_space = JCS_RGB;
+ cinfo.input_components = 3;
+ break;
+ }
+
+ jpeg_set_defaults(&cinfo);
+
+ // progressive-JPEG support
+ if((flags & JPEG_PROGRESSIVE) == JPEG_PROGRESSIVE) {
+ jpeg_simple_progression(&cinfo);
+ }
+
+ // Set JFIF density parameters from the DIB data
+
+ cinfo.X_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
+ cinfo.Y_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
+ cinfo.density_unit = 1; // dots / inch
+
+ // set subsampling options if required
+
+ if(cinfo.in_color_space == JCS_RGB) {
+ if((flags & JPEG_SUBSAMPLING_411) == JPEG_SUBSAMPLING_411) {
+ // 4:1:1 (4x1 1x1 1x1) - CrH 25% - CbH 25% - CrV 100% - CbV 100%
+ // the horizontal color resolution is quartered
+ cinfo.comp_info[0].h_samp_factor = 4; // Y
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1; // Cb
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1; // Cr
+ cinfo.comp_info[2].v_samp_factor = 1;
+ } else if((flags & JPEG_SUBSAMPLING_420) == JPEG_SUBSAMPLING_420) {
+ // 4:2:0 (2x2 1x1 1x1) - CrH 50% - CbH 50% - CrV 50% - CbV 50%
+ // the chrominance resolution in both the horizontal and vertical directions is cut in half
+ cinfo.comp_info[0].h_samp_factor = 2; // Y
+ cinfo.comp_info[0].v_samp_factor = 2;
+ cinfo.comp_info[1].h_samp_factor = 1; // Cb
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1; // Cr
+ cinfo.comp_info[2].v_samp_factor = 1;
+ } else if((flags & JPEG_SUBSAMPLING_422) == JPEG_SUBSAMPLING_422){ //2x1 (low)
+ // 4:2:2 (2x1 1x1 1x1) - CrH 50% - CbH 50% - CrV 100% - CbV 100%
+ // half of the horizontal resolution in the chrominance is dropped (Cb & Cr),
+ // while the full resolution is retained in the vertical direction, with respect to the luminance
+ cinfo.comp_info[0].h_samp_factor = 2; // Y
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1; // Cb
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1; // Cr
+ cinfo.comp_info[2].v_samp_factor = 1;
+ }
+ else if((flags & JPEG_SUBSAMPLING_444) == JPEG_SUBSAMPLING_444){ //1x1 (no subsampling)
+ // 4:4:4 (1x1 1x1 1x1) - CrH 100% - CbH 100% - CrV 100% - CbV 100%
+ // the resolution of chrominance information (Cb & Cr) is preserved
+ // at the same rate as the luminance (Y) information
+ cinfo.comp_info[0].h_samp_factor = 1; // Y
+ cinfo.comp_info[0].v_samp_factor = 1;
+ cinfo.comp_info[1].h_samp_factor = 1; // Cb
+ cinfo.comp_info[1].v_samp_factor = 1;
+ cinfo.comp_info[2].h_samp_factor = 1; // Cr
+ cinfo.comp_info[2].v_samp_factor = 1;
+ }
+ }
+
+ // Step 4: set quality
+ // the first 7 bits are reserved for low level quality settings
+ // the other bits are high level (i.e. enum-ish)
+
+ int quality;
+
+ if ((flags & JPEG_QUALITYBAD) == JPEG_QUALITYBAD) {
+ quality = 10;
+ } else if ((flags & JPEG_QUALITYAVERAGE) == JPEG_QUALITYAVERAGE) {
+ quality = 25;
+ } else if ((flags & JPEG_QUALITYNORMAL) == JPEG_QUALITYNORMAL) {
+ quality = 50;
+ } else if ((flags & JPEG_QUALITYGOOD) == JPEG_QUALITYGOOD) {
+ quality = 75;
+ } else if ((flags & JPEG_QUALITYSUPERB) == JPEG_QUALITYSUPERB) {
+ quality = 100;
+ } else {
+ if ((flags & 0x7F) == 0) {
+ quality = 75;
+ } else {
+ quality = flags & 0x7F;
+ }
+ }
+
+ jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
+
+ // Step 5: Start compressor
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // Step 6: Write special markers
+
+ write_markers(&cinfo, dib);
+
+ // Step 7: while (scan lines remain to be written)
+
+ if(color_type == FIC_RGB) {
+ // 24-bit RGB image : need to swap red and blue channels
+ unsigned pitch = FreeImage_GetPitch(dib);
+ BYTE *target = (BYTE*)malloc(pitch * sizeof(BYTE));
+ if (target == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ // get a copy of the scanline
+ memcpy(target, FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1), pitch);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // swap R and B channels
+ BYTE *target_p = target;
+ for(unsigned x = 0; x < cinfo.image_width; x++) {
+ INPLACESWAP(target_p[0], target_p[2]);
+ target_p += 3;
+ }
+#endif
+ // write the scanline
+ jpeg_write_scanlines(&cinfo, &target, 1);
+ }
+ free(target);
+ }
+ else if(color_type == FIC_MINISBLACK) {
+ // 8-bit standard greyscale images
+ while (cinfo.next_scanline < cinfo.image_height) {
+ JSAMPROW b = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
+
+ jpeg_write_scanlines(&cinfo, &b, 1);
+ }
+ }
+ else if(color_type == FIC_PALETTE) {
+ // 8-bit palettized images are converted to 24-bit images
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+ BYTE *target = (BYTE*)malloc(cinfo.image_width * 3);
+ if (target == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
+ FreeImage_ConvertLine8To24(target, source, cinfo.image_width, palette);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // swap R and B channels
+ BYTE *target_p = target;
+ for(unsigned x = 0; x < cinfo.image_width; x++) {
+ INPLACESWAP(target_p[0], target_p[2]);
+ target_p += 3;
+ }
+#endif
+
+
+ jpeg_write_scanlines(&cinfo, &target, 1);
+ }
+
+ free(target);
+ }
+ else if(color_type == FIC_MINISWHITE) {
+ // reverse 8-bit greyscale image, so reverse grey value on the fly
+ unsigned i;
+ BYTE reverse[256];
+ BYTE *target = (BYTE *)malloc(cinfo.image_width);
+ if (target == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ for(i = 0; i < 256; i++) {
+ reverse[i] = (BYTE)(255 - i);
+ }
+
+ while(cinfo.next_scanline < cinfo.image_height) {
+ BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
+ for(i = 0; i < cinfo.image_width; i++) {
+ target[i] = reverse[ source[i] ];
+ }
+ jpeg_write_scanlines(&cinfo, &target, 1);
+ }
+
+ free(target);
+ }
+
+ // Step 8: Finish compression
+
+ jpeg_finish_compress(&cinfo);
+
+ // Step 9: release JPEG compression object
+
+ jpeg_destroy_compress(&cinfo);
+
+ return TRUE;
+
+ } catch (const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return FALSE;
+ } catch (FREE_IMAGE_FORMAT) {
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitJPEG(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Source/FreeImage/PluginKOALA.cpp b/Source/FreeImage/PluginKOALA.cpp
new file mode 100644
index 0000000..784e36f
--- /dev/null
+++ b/Source/FreeImage/PluginKOALA.cpp
@@ -0,0 +1,243 @@
+// ==========================================================
+// KOALA Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagKOALA {
+ BYTE image[8000]; // pixmap image
+ BYTE colour1[1000]; // first colourmap (colour 1 and 2)
+ BYTE colour2[1000]; // second colourmap (colour 3)
+ BYTE background; // background colour
+} koala_t;
+
+struct colour_t {
+ int r;
+ int g;
+ int b;
+};
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ----------------------------------------------------------
+
+#define CBM_WIDTH 320
+#define CBM_HEIGHT 200
+
+// ----------------------------------------------------------
+
+const colour_t c64colours[16] = {
+ { 0, 0, 0 }, // Black
+ { 255, 255, 255 }, // White
+ { 170, 17, 17 }, // Red
+ { 12, 204, 204 }, // Cyan
+ { 221, 51, 221 }, // Purple
+ { 0, 187, 0 }, // Green
+ { 0, 0, 204 }, // Blue
+ { 255, 255, 140 }, // Yellow
+ { 204, 119, 34 }, // Orange
+ { 136, 68, 0 }, // Brown
+ { 255, 153, 136 }, // Light red
+ { 92, 92, 92 }, // Gray 1
+ { 170, 170, 170 }, // Gray 2
+ { 140, 255, 178 }, // Light green
+ { 39, 148, 255 }, // Light blue
+ { 196, 196, 196 } // Gray 3
+};
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+const char * DLL_CALLCONV
+Format() {
+ return "KOALA";
+}
+
+const char * DLL_CALLCONV
+Description() {
+ return "C64 Koala Graphics";
+}
+
+const char * DLL_CALLCONV
+Extension() {
+ return "koa";
+}
+
+const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-koala";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE koala_signature[] = { 0x00, 0x60 };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(koala_signature), handle);
+
+ return (memcmp(koala_signature, signature, sizeof(koala_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle) {
+ koala_t image;
+
+ // read the load address
+
+ unsigned char load_address[2]; // highbit, lowbit
+
+ io->read_proc(&load_address, 1, 2, handle);
+
+ // if the load address is correct, skip it. otherwise ignore the load address
+
+ if ((load_address[0] != 0x00) || (load_address[1] != 0x60)) {
+ ((BYTE *)&image)[0] = load_address[0];
+ ((BYTE *)&image)[1] = load_address[1];
+
+ io->read_proc((BYTE *)&image + 2, 1, 10001 - 2, handle);
+ } else {
+ io->read_proc(&image, 1, 10001, handle);
+ }
+
+ // build DIB in memory
+
+ FIBITMAP *dib = FreeImage_Allocate(CBM_WIDTH, CBM_HEIGHT, 4);
+
+ if (dib) {
+ // write out the commodore 64 color palette
+
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+
+ for (int i = 0; i < 16; i++) {
+ palette[i].rgbBlue = (BYTE)c64colours[i].b;
+ palette[i].rgbGreen = (BYTE)c64colours[i].g;
+ palette[i].rgbRed = (BYTE)c64colours[i].r;
+ }
+
+ // write out bitmap data
+
+ BYTE pixel_mask[4] = { 0xc0, 0x30, 0x0c, 0x03 };
+ BYTE pixel_displacement[4] = { 6, 4, 2, 0 };
+ int pixel, index, colourindex;
+ unsigned char found_color = 0;
+
+ for (int y = 0; y < 200; y++) {
+ for (int x = 0; x < 160; x++) {
+ // Get value of pixel at (x,y)
+
+ index = (x / 4) * 8 + (y % 8) + (y / 8) * CBM_WIDTH;
+ colourindex = (x / 4) + (y / 8) * 40;
+ pixel = (image.image[index] & pixel_mask[x % 4]) >> pixel_displacement[x % 4];
+
+ // Retrieve RGB values
+
+ switch (pixel) {
+ case 0: // Background
+ found_color = image.background;
+ break;
+
+ case 1: // Colour 1
+ found_color = image.colour1[colourindex] >> 4;
+ break;
+
+ case 2: // Colour 2
+ found_color = image.colour1[colourindex] & 0xf;
+ break;
+
+ case 3: // Colour 3
+ found_color = image.colour2[colourindex] & 0xf;
+ break;
+ };
+
+ *(FreeImage_GetScanLine(dib, CBM_HEIGHT - y - 1) + x) = (found_color << 4) | found_color;
+ }
+ }
+
+ return dib;
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitKOALA(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginMNG.cpp b/Source/FreeImage/PluginMNG.cpp
new file mode 100644
index 0000000..137de4c
--- /dev/null
+++ b/Source/FreeImage/PluginMNG.cpp
@@ -0,0 +1,316 @@
+// ==========================================================
+// MNG Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef WIN32 // Needs to happen before zlib.h inclusion or things get messed up
+#include <windows.h>
+#define XMD_H // mocks up X11 header to avoid compilation error
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+#include "../LibMNG/libmng.h"
+#include "../LibMNG/libmng_data.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+typedef struct {
+ FIBITMAP *bitmap; // pointer to the bitmap data
+ FreeImageIO *io; // pointer to the io functions
+ fi_handle file; // pointer to the file we're decoding
+} mngstuff;
+
+// ----------------------------------------------------------
+// Callbacks for the mng decoder
+// ----------------------------------------------------------
+
+mng_ptr
+mymngalloc(mng_size_t size) {
+ return (mng_ptr)calloc(1, size);
+}
+
+void
+mymngfree(mng_ptr p, mng_size_t size) {
+ free(p);
+}
+
+mng_bool
+mymngopenstream(mng_handle mng) {
+ // since the user is responsible for opening and closing the file,
+ // we leave the default implementation open
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngclosestream(mng_handle mng) {
+ // since the user is responsible for opening and closing the file,
+ // we leave the default implementation open
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) {
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+
+ *bytesread = mymng->io->read_proc(buffer, 1, size, mymng->file);
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height) {
+ mngstuff *client_data = (mngstuff *)mng_get_userdata(mng);
+ BYTE bHasAlpha = mng_get_alphadepth(mng);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if(bHasAlpha) {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
+ } else {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
+ }
+#else
+ if(bHasAlpha) {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
+ } else {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_BGR8);
+ }
+#endif // FREEIMAGE_COLORORDER_RGB
+
+ return client_data->bitmap ? MNG_TRUE : MNG_FALSE;
+}
+
+mng_ptr
+mymnggetcanvasline(mng_handle mng, mng_uint32 line) {
+ FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(mng))->bitmap;
+
+ return FreeImage_GetScanLine(bitmap, FreeImage_GetHeight(bitmap) - line - 1);
+}
+
+mng_bool
+mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) {
+ return MNG_TRUE;
+}
+
+mng_uint32
+mymnggetticks(mng_handle mng) {
+ return 0;
+}
+
+mng_bool
+mymngsettimer(mng_handle mng, mng_uint32 msecs) {
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngerror(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text) {
+ char msg[256];
+ if((code == MNG_SEQUENCEERROR) && (chunktype == MNG_UINT_TERM)) {
+ // ignore sequence error for TERM
+ return MNG_TRUE;
+ }
+ if(text) {
+ // text can be null depending on compiler options
+ sprintf(msg, "Error reported by libmng (%d)\r\n\r\n%s", code, text);
+ } else {
+ sprintf(msg, "Error %d reported by libmng", code);
+ }
+ FreeImage_OutputMessageProc(s_format_id, msg);
+ return MNG_FALSE;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "MNG";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Multiple Network Graphics";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "mng";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "video/x-mng";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ mngstuff *mymng = (mngstuff *)calloc(1, sizeof(*mymng));
+ mymng->io = io;
+ mymng->file = handle;
+
+ return mymng;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+ free((mngstuff *)data);
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ mng_handle hmng = NULL;
+
+ if (handle != NULL) {
+ try {
+ // allocate our stream data structure
+ mngstuff *mymng = (mngstuff *)data;
+
+ // set up the mng decoder for our stream
+ hmng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL);
+
+ if (hmng == MNG_NULL) {
+ throw "could not initialize libmng";
+ }
+
+ // set the colorprofile, lcms uses this
+ mng_set_srgb(hmng, MNG_TRUE );
+ // set white as background color
+ WORD wRed, wGreen, wBlue;
+ wRed = wGreen = wBlue = (255 << 8) + 255;
+ mng_set_bgcolor(hmng, wRed, wGreen, wBlue);
+ // if PNG Background is available, use it
+ mng_set_usebkgd(hmng, MNG_TRUE );
+ // no need to store chunks
+ mng_set_storechunks(hmng, MNG_FALSE);
+ // no need to wait: straight reading
+ mng_set_suspensionmode(hmng, MNG_FALSE);
+
+ // set the callbacks
+ mng_setcb_errorproc(hmng, mymngerror);
+ mng_setcb_openstream(hmng, mymngopenstream);
+ mng_setcb_closestream(hmng, mymngclosestream);
+ mng_setcb_readdata(hmng, mymngreadstream);
+ mng_setcb_processheader(hmng, mymngprocessheader);
+ mng_setcb_getcanvasline(hmng, mymnggetcanvasline);
+ mng_setcb_refresh(hmng, mymngrefresh);
+ mng_setcb_gettickcount(hmng, mymnggetticks);
+ mng_setcb_settimer(hmng, mymngsettimer);
+
+ // read in the bitmap
+ mng_readdisplay(hmng);
+
+ // read all bitmaps
+ int retval = MNG_NOERROR;
+ mng_datap pData = (mng_datap)hmng;
+ while(pData->bReading) {
+ retval = mng_display_resume(hmng);
+ }
+
+ // temp store the newly created bitmap
+ FIBITMAP *bitmap = mymng->bitmap;
+
+ // cleanup and return the temp stored bitmap
+ mng_cleanup(&hmng);
+
+ return bitmap;
+
+ } catch (const char *message) {
+ FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(hmng))->bitmap;
+ if(bitmap) {
+ FreeImage_Unload(bitmap);
+ }
+ mng_cleanup(&hmng);
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitMNG(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
+}
diff --git a/Source/FreeImage/PluginPCD.cpp b/Source/FreeImage/PluginPCD.cpp
new file mode 100644
index 0000000..7c38b67
--- /dev/null
+++ b/Source/FreeImage/PluginPCD.cpp
@@ -0,0 +1,229 @@
+// ==========================================================
+// Kodak PhotoCD Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// Based on pascal code developed by Alex Kwak
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static int
+clamp(double x) {
+ int a = (int)floor(x + 0.5);
+ return (a < 0) ? 0 : (a > 255) ? 255 : a;
+}
+
+static void
+YUV2RGB(int y, int cb, int cr, int &r, int &g, int &b) {
+ double c11 = 0.0054980 * 256.0;
+ double c12 = 0.0000001 * 256.0;
+ double c13 = 0.0051681 * 256.0;
+ double c21 = 0.0054980 * 256.0;
+ double c22 = -0.0015446 * 256.0;
+ double c23 = -0.0026325 * 256.0;
+ double c31 = 0.0054980 * 256.0;
+ double c32 = 0.0079533 * 256.0;
+ double c33 = 0.0000001 * 256.0;
+
+ r = clamp(c11 * y + c12 * (cb - 156) + c13 * (cr - 137));
+ g = clamp(c21 * y + c22 * (cb - 156) + c23 * (cr - 137));
+ b = clamp(c31 * y + c32 * (cb - 156) + c33 * (cr - 137));
+}
+
+static BOOL
+VerticalOrientation(FreeImageIO *io, fi_handle handle) {
+ char buffer[128];
+
+ io->read_proc(buffer, 128, 1, handle);
+
+ return (buffer[72] & 63) == 8;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PCD";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Kodak PhotoCD";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "pcd";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-photo-cd";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ int width;
+ int height;
+ int line;
+ int pitch;
+ int bpp = 24;
+ int scan_line_add = 1;
+ int start_scan_line = 0;
+
+ // to make absolute seeks possible we store the current position in the file
+
+ long offset_in_file = io->tell_proc(handle);
+ long seek = 0;
+
+ // decide which bitmap in the cabinet to load
+
+ switch (flags) {
+ case PCD_BASEDIV4 :
+ seek = 0x2000;
+ width = 192;
+ height = 128;
+ break;
+
+ case PCD_BASEDIV16 :
+ seek = 0xB800;
+ width = 384;
+ height = 256;
+ break;
+
+ default :
+ seek = 0x30000;
+ width = 768;
+ height = 512;
+ break;
+ }
+
+ // calculate line and pitch based on the selected bitmap size
+
+ line = CalculateLine(width, bpp);
+ pitch = CalculatePitch(line);
+
+ // allocate the dib and write out the header
+
+ FIBITMAP *dib = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ // check if the PCD is bottom-up
+
+ if (VerticalOrientation(io, handle)) {
+ scan_line_add = -1;
+ start_scan_line = height - 1;
+ }
+
+ // temporary stuff to load PCD
+
+ BYTE *y1 = new BYTE[width];
+ BYTE *y2 = new BYTE[width];
+ BYTE *cbcr = new BYTE[width];
+ BYTE *yl[] = { y1, y2 };
+
+ // seek to the part where the bitmap data begins
+
+ io->seek_proc(handle, offset_in_file, SEEK_SET);
+ io->seek_proc(handle, seek, SEEK_CUR);
+
+ // read the data
+
+ for (int y = 0; y < height / 2; ++y) {
+ io->read_proc(y1, width, 1, handle);
+ io->read_proc(y2, width, 1, handle);
+ io->read_proc(cbcr, width, 1, handle);
+
+ for (int i = 0; i < 2; ++i) {
+ BYTE *img = FreeImage_GetScanLine(dib, start_scan_line);
+ for (int x = 0; x < width; ++x) {
+ int r, g, b;
+
+ YUV2RGB(yl[i][x], cbcr[x / 2], cbcr[(width / 2) + (x / 2)], r, g, b);
+
+ img[FI_RGBA_BLUE] = (BYTE)b;
+ img[FI_RGBA_GREEN] = (BYTE)g;
+ img[FI_RGBA_RED] = (BYTE)r;
+ img += 3;
+ }
+
+ start_scan_line += scan_line_add;
+ }
+ }
+
+ delete [] cbcr;
+ delete [] y2;
+ delete [] y1;
+
+ return dib;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPCD(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginPCX.cpp b/Source/FreeImage/PluginPCX.cpp
new file mode 100644
index 0000000..66a8189
--- /dev/null
+++ b/Source/FreeImage/PluginPCX.cpp
@@ -0,0 +1,607 @@
+// ==========================================================
+// PCX Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Jani Kajala (janik@remedy.fi)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Juergen Riecker (j.riecker@gmx.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#define IO_BUF_SIZE 2048
+
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagPCXHEADER {
+ BYTE manufacturer; // Magic number (0x0A = ZSoft Z)
+ BYTE version; // Version 0 == 2.5
+ // 2 == 2.8 with palette info
+ // 3 == 2.8 without palette info
+ // 5 == 3.0 with palette info
+ BYTE encoding; // Encoding: 0 = uncompressed, 1 = PCX rle compressed
+ BYTE bpp; // Bits per pixel per plane (only 1 or 8)
+ WORD window[4]; // left, upper, right,lower pixel coord.
+ WORD hdpi; // Horizontal resolution
+ WORD vdpi; // Vertical resolution
+ BYTE color_map[48]; // Colormap for 16-color images
+ BYTE reserved;
+ BYTE planes; // Number of planes (1, 3 or 4)
+ WORD bytes_per_line; // Bytes per row (always even)
+ WORD palette_info; // Palette information (1 = color or b&w; 2 = gray scale)
+ WORD h_screen_size;
+ WORD v_screen_size;
+ BYTE filler[54]; // Reserved filler
+} PCXHEADER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static WORD
+readline(FreeImageIO &io, fi_handle handle, BYTE *buffer, WORD length, BOOL rle, BYTE * ReadBuf, int * ReadPos) {
+ // -----------------------------------------------------------//
+ // Read either run-length encoded or normal image data //
+ // //
+ // THIS IS HOW RUNTIME LENGTH ENCODING WORKS IN PCX: //
+ // //
+ // 1) If the upper 2 bits of a byte are set, //
+ // the lower 6 bits specify the count for the next byte //
+ // //
+ // 2) If the upper 2 bits of the byte are clear, //
+ // the byte is actual data with a count of 1 //
+ // //
+ // Note that a scanline always has an even number of bytes //
+ // -------------------------------------------------------------
+
+ BYTE count = 0, value = 0;
+ WORD written = 0;
+
+ if (rle) {
+ // run-length encoded read
+
+ while (length--) {
+ if (count == 0) {
+ if (*ReadPos >= IO_BUF_SIZE - 1 ) {
+ if (*ReadPos == IO_BUF_SIZE - 1) {
+ // we still have one BYTE, copy it to the start pos
+
+ *ReadBuf = ReadBuf[IO_BUF_SIZE - 1];
+
+ io.read_proc(ReadBuf + 1, 1, IO_BUF_SIZE - 1, handle);
+ } else {
+ // read the complete buffer
+
+ io.read_proc(ReadBuf, 1, IO_BUF_SIZE, handle);
+ }
+
+ *ReadPos = 0;
+ }
+
+ value = *(ReadBuf + (*ReadPos)++);
+
+ if ((value & 0xC0) == 0xC0) {
+ count = value & 0x3F;
+
+ value = *(ReadBuf + (*ReadPos)++); // $JR
+ } else {
+ count = 1;
+ }
+ }
+
+ count--;
+
+ *(buffer + written++) = value;
+ }
+
+ } else {
+ // normal read
+
+ written = (WORD)io.read_proc(buffer, length, 1, handle);
+ }
+
+ return written;
+}
+
+#ifdef FREEIMAGE_BIGENDIAN
+static void
+SwapHeader(PCXHEADER *header) {
+ SwapShort(&header->window[0]);
+ SwapShort(&header->window[1]);
+ SwapShort(&header->window[2]);
+ SwapShort(&header->window[3]);
+ SwapShort(&header->hdpi);
+ SwapShort(&header->vdpi);
+ SwapShort(&header->bytes_per_line);
+ SwapShort(&header->palette_info);
+ SwapShort(&header->h_screen_size);
+ SwapShort(&header->v_screen_size);
+}
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+/*!
+ Returns the format string for the plugin. Each plugin,
+ both internal in the DLL and external in a .fip file, must have
+ a unique format string to be addressable.
+*/
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PCX";
+}
+
+/*!
+ Returns a description string for the plugin. Though a
+ description is not necessary per-se,
+ it is advised to return an unique string in order to tell the
+ user what type of bitmaps this plugin will read and/or write.
+*/
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Zsoft Paintbrush";
+}
+
+/*!
+ Returns a comma separated list of file
+ extensions indicating what files this plugin can open. The
+ list, being used by FreeImage_GetFIFFromFilename, is usually
+ used as a last resort in finding the type of the bitmap we
+ are dealing with. Best is to check the first few bytes on
+ the low-level bits level first and compare them with a known
+ signature . If this fails, FreeImage_GetFIFFromFilename can be
+ used.
+*/
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "pcx";
+}
+
+/*!
+ Returns an (optional) regular expression to help
+ software identifying a bitmap type. The
+ expression can be applied to the first few bytes (header) of
+ the bitmap. FreeImage is not capable of processing regular expression itself,
+ but FreeImageQt, the FreeImage Trolltech support library, can. If RegExpr
+ returns NULL, FreeImageQt will automatically bypass Trolltech's regular
+ expression support and use its internal functions to find the bitmap type.
+*/
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-pcx";
+}
+
+/*!
+ Validates a bitmap by reading the first few bytes
+ and comparing them with a known bitmap signature.
+ TRUE is returned if the bytes match the signature, FALSE otherwise.
+ The Validate function is used by using FreeImage_GetFileType.
+
+ Note: a plugin can safely read data any data from the bitmap without seeking back
+ to the original entry point; the entry point is stored prior to calling this
+ function and restored after.
+
+ Note: because of FreeImage's io redirection support, the header for the bitmap
+ must be on the start of the bitmap or at least on a known part in the bitmap. It is
+ forbidden to seek to the end of the bitmap or to a point relative to the end of a bitmap,
+ because the end of the bitmap is not always known.
+*/
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE pcx_signature = 0x0A;
+ BYTE signature = 0;
+
+ io->read_proc(&signature, 1, 1, handle);
+
+ return (pcx_signature == signature);
+}
+
+/*!
+ This function is used to 'ask' the plugin if it can write
+ a bitmap in a certain bitdepth. Different bitmap types have different
+ capabilities, for example not all formats allow writing in palettized mode.
+ This function is there provide an uniform interface to the plugin's
+ capabilities. SupportsExportDepth returns TRUE if the plugin support writing
+ in the asked bitdepth, or FALSE if it doesn't. The function also
+ returns FALSE if bitmap saving is not supported by the plugin at all.
+*/
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+/*!
+ Loads a bitmap into memory. On entry it is assumed that
+ the bitmap to be loaded is of the correct type. If the bitmap
+ is of an incorrect type, the plugin might not gracefully fail but
+ crash or enter an endless loop. It is also assumed that all
+ the bitmap data is available at one time. If the bitmap is not complete,
+ for example because it is being downloaded while loaded, the plugin
+ might also not gracefully fail.
+
+ The Load function has the following parameters:
+
+ The first parameter (FreeImageIO *io) is a structure providing
+ function pointers in order to make use of FreeImage's IO redirection. Using
+ FreeImage's file i/o functions instead of standard ones it is garantueed
+ that all bitmap types, both current and future ones, can be loaded from
+ memory, file cabinets, the internet and more. The second parameter (fi_handle handle)
+ is a companion of FreeImageIO and can be best compared with the standard FILE* type,
+ in a generalized form.
+
+ The third parameter (int page) indicates wether we will be loading a certain page
+ in the bitmap or if we will load the default one. This parameter is only used if
+ the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series
+ of images or pages. If the plugin does support multi-paging, the page parameter
+ can contain either a number higher or equal to 0 to load a certain page, or -1 to
+ load the default page. If the plugin does not support multi-paging,
+ the page parameter is always -1.
+
+ The fourth parameter (int flags) manipulates the load function to load a bitmap
+ in a certain way. Every plugin has a different flag parameter with different meanings.
+
+ The last parameter (void *data) can contain a special data block used when
+ the file is read multi-paged. Because not every plugin supports multi-paging
+ not every plugin will use the data parameter and it will be set to NULL.However,
+ when the plugin does support multi-paging the parameter contains a pointer to a
+ block of data allocated by the Open function.
+*/
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ FIBITMAP *dib = NULL;
+ BYTE *bits; // Pointer to dib data
+ RGBQUAD *pal; // Pointer to dib palette
+ BYTE *line = NULL; // PCX raster line
+ BYTE *ReadBuf = NULL; // buffer;
+ WORD linelength; // Length of raster line in bytes
+ WORD pitch; // Length of DIB line in bytes
+ BOOL rle; // True if the file is run-length encoded
+
+ if (handle) {
+ try {
+ // process the header
+
+ PCXHEADER header;
+
+ io->read_proc(&header, sizeof(PCXHEADER), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+
+ // check PCX identifier
+
+ if ((header.manufacturer != 0x0A) || (header.version > 5))
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+
+ // allocate a new DIB
+
+ WORD width = header.window[2] - header.window[0] + 1;
+ WORD height = header.window[3] - header.window[1] + 1;
+ WORD bitcount = header.bpp * header.planes;
+
+ if (bitcount == 24)
+ dib = FreeImage_Allocate(width, height, bitcount, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ else
+ dib = FreeImage_Allocate(width, height, bitcount);
+
+ // if the dib couldn't be allocated, throw an error
+
+ if (!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // metrics handling code
+
+ FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)header.hdpi) / 0.0254000 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)header.vdpi) / 0.0254000 + 0.5));
+
+ // Set up the palette if needed
+ // ----------------------------
+
+ switch(bitcount) {
+ case 1:
+ {
+ pal = FreeImage_GetPalette(dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ break;
+ }
+
+ case 4:
+ {
+ pal = FreeImage_GetPalette(dib);
+
+ BYTE *pColormap = &header.color_map[0];
+
+ for (int i = 0; i < 16; i++) {
+ pal[i].rgbRed = pColormap[0];
+ pal[i].rgbGreen = pColormap[1];
+ pal[i].rgbBlue = pColormap[2];
+ pColormap += 3;
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ BYTE palette_id;
+
+ io->seek_proc(handle, -769L, SEEK_END);
+ io->read_proc(&palette_id, 1, 1, handle);
+
+ if (palette_id == 0x0C) {
+ BYTE *cmap = (BYTE*)malloc(768 * sizeof(BYTE));
+ io->read_proc(cmap, 768, 1, handle);
+
+ pal = FreeImage_GetPalette(dib);
+ BYTE *pColormap = &cmap[0];
+
+ for(int i = 0; i < 256; i++) {
+ pal[i].rgbRed = pColormap[0];
+ pal[i].rgbGreen = pColormap[1];
+ pal[i].rgbBlue = pColormap[2];
+ pColormap += 3;
+ }
+
+ free(cmap);
+ }
+
+ // wrong palette ID, perhaps a gray scale is needed ?
+
+ else if (header.palette_info == 2) {
+ pal = FreeImage_GetPalette(dib);
+
+ for(int i = 0; i < 256; i++) {
+ pal[i].rgbRed = (BYTE)i;
+ pal[i].rgbGreen = (BYTE)i;
+ pal[i].rgbBlue = (BYTE)i;
+ }
+ }
+
+ io->seek_proc(handle, (long)sizeof(PCXHEADER), SEEK_SET);
+ }
+ break;
+ }
+
+ // calculate the line length for the PCX and the DIB
+
+ linelength = header.bytes_per_line * header.planes;
+ pitch = (WORD)FreeImage_GetPitch(dib);
+
+ // run-length encoding ?
+
+ rle = (header.encoding == 1) ? TRUE : FALSE;
+
+ // load image data
+ // ---------------
+
+ line = new BYTE[linelength];
+ bits = FreeImage_GetScanLine(dib, height - 1);
+ ReadBuf = new BYTE[IO_BUF_SIZE];
+
+ int ReadPos = IO_BUF_SIZE;
+
+ if ((header.planes == 1) && ((header.bpp == 1) || (header.bpp == 8))) {
+ BYTE skip;
+ WORD written;
+
+ for (WORD y = 0; y < height; y++) {
+ written = readline(*io, handle, bits, linelength, rle, ReadBuf, &ReadPos);
+
+ // skip trailing garbage at the end of the scanline
+
+ for (int count = written; count < linelength; count++) {
+ if (ReadPos < IO_BUF_SIZE) {
+ ReadPos++;
+ } else {
+ io->read_proc(&skip, sizeof(BYTE), 1, handle);
+ }
+ }
+
+ bits -= pitch;
+ }
+ } else if ((header.planes == 4) && (header.bpp == 1)) {
+ BYTE bit, mask, skip;
+ WORD index;
+ BYTE *buffer;
+ WORD x, y, written;
+
+ buffer = new BYTE[width];
+
+ for (y = 0; y < height; y++) {
+ written = readline(*io, handle, line, linelength, rle, ReadBuf, &ReadPos);
+
+ // build a nibble using the 4 planes
+
+ memset(buffer, 0, width * sizeof(BYTE));
+
+ for(int plane = 0; plane < 4; plane++) {
+ bit = (BYTE)(1 << plane);
+
+ for (x = 0; x < width; x++) {
+ index = (WORD)((x / 8) + plane * header.bytes_per_line);
+ mask = (BYTE)(0x80 >> (x & 0x07));
+ buffer[x] |= (line[index] & mask) ? bit : 0;
+ }
+ }
+
+ // then write the DIB row
+
+ for (x = 0; x < width / 2; x++)
+ bits[x] = (buffer[2*x] << 4) | buffer[2*x+1];
+
+ // skip trailing garbage at the end of the scanline
+
+ for (int count = written; count < linelength; count++) {
+ if (ReadPos < IO_BUF_SIZE) {
+ ReadPos++;
+ } else {
+ io->read_proc(&skip, sizeof(BYTE), 1, handle);
+ }
+ }
+
+ bits -= pitch;
+ }
+
+ delete [] buffer;
+ } else if((header.planes == 3) && (header.bpp == 8)) {
+ BYTE *pline;
+
+ for (WORD y = 0; y < height; y++) {
+ readline(*io, handle, line, linelength, rle, ReadBuf, &ReadPos);
+
+ // convert the plane stream to BGR (RRRRGGGGBBBB -> BGRBGRBGRBGR)
+ // well, now with the FI_RGBA_x macros, on BIGENDIAN we convert to RGB
+
+ pline = line;
+ WORD x;
+
+ for (x = 0; x < width; x++)
+ bits[x * 3 + FI_RGBA_RED] = pline[x];
+ pline += header.bytes_per_line;
+
+ for (x = 0; x < width; x++)
+ bits[x * 3 + FI_RGBA_GREEN] = pline[x];
+ pline += header.bytes_per_line;
+
+ for (x = 0; x < width; x++)
+ bits[x * 3 + FI_RGBA_BLUE] = pline[x];
+ pline += header.bytes_per_line;
+
+ bits -= pitch;
+ }
+ } else {
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ delete [] line;
+ delete [] ReadBuf;
+ return dib;
+ } catch (const char *text) {
+ // free allocated memory
+
+ if (dib != NULL)
+ FreeImage_Unload(dib);
+
+ if (line != NULL)
+ delete [] line;
+
+ if (ReadBuf != NULL)
+ delete [] ReadBuf;
+
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+/*!
+ Initialises the plugin. The first parameter (Plugin *plugin)
+ contains a pointer to a pre-allocated Plugin structure
+ wherein pointers to the available plugin functions
+ has to be stored. The second parameter (int format_id) is an identification
+ number that the plugin may use to show plugin specific warning messages
+ or other information to the user. The plugin number
+ is generated by FreeImage and can differ everytime the plugin is
+ initialised.
+
+ If you want to create your own plugin you have to take some
+ rules into account. Plugin functions have to be compiled
+ __stdcall using the multithreaded c runtime libraries. Throwing
+ exceptions in plugin functions is allowed, as long as those exceptions
+ are being caught inside the same plugin. It is forbidden for a plugin
+ function to directly call FreeImage functions or to allocate memory
+ and pass it to the main DLL. Exception to this rule is the special file data
+ block that may be allocated the Open function. Allocating a FIBITMAP inside a
+ plugin can be using the function allocate_proc in the FreeImage structure,
+ which will allocate the memory using the DLL's c runtime library.
+*/
+
+void DLL_CALLCONV
+InitPCX(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginPFM.cpp b/Source/FreeImage/PluginPFM.cpp
new file mode 100644
index 0000000..4b30dd7
--- /dev/null
+++ b/Source/FreeImage/PluginPFM.cpp
@@ -0,0 +1,390 @@
+#if 0 // Unused by TPN
+// ==========================================================
+// PFM Loader and Writer
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+/** maximum size of a line in the header */
+#define PFM_MAXLINE 256
+
+/** Big endian / Little endian float conversion */
+#define REVERSEBYTES(source, dest) \
+{ \
+ char *j = (char *) source; \
+ char *dj = (char *) dest; \
+ dj[0] = j[3]; \
+ dj[1] = j[2]; \
+ dj[2] = j[1]; \
+ dj[3] = j[0]; \
+}
+
+/**
+Get a line from a ASCII io stream
+*/
+static BOOL
+pfm_get_line(FreeImageIO *io, fi_handle handle, char *buffer, int length) {
+ int i;
+ memset(buffer, 0, length);
+ for(i = 0; i < length; i++) {
+ if(!io->read_proc(&buffer[i], 1, 1, handle))
+ return FALSE;
+ if(buffer[i] == 0x0A)
+ break;
+ }
+
+ return (i < length) ? TRUE : FALSE;
+}
+
+/**
+Get an integer value from the actual position pointed by handle
+*/
+static int
+pfm_get_int(FreeImageIO *io, fi_handle handle) {
+ char c = 0;
+ BOOL firstchar;
+
+ // skip forward to start of next number
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ while (1) {
+ // eat comments
+
+ if (c == '#') {
+ // if we're at a comment, read to end of line
+
+ firstchar = TRUE;
+
+ while (1) {
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ if (firstchar && c == ' ') {
+ // loop off 1 sp after #
+
+ firstchar = FALSE;
+ } else if (c == '\n') {
+ break;
+ }
+ }
+ }
+
+ if (c >= '0' && c <='9') {
+ // we've found what we were looking for
+
+ break;
+ }
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ }
+
+ // we're at the start of a number, continue until we hit a non-number
+
+ int i = 0;
+
+ while (1) {
+ i = (i * 10) + (c - '0');
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ if (c < '0' || c > '9')
+ break;
+ }
+
+ return i;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PFM";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Portable floatmap";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "pfm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-pfm";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE pfm_id1[] = { 0x50, 0x46 };
+ BYTE pfm_id2[] = { 0x50, 0x66 };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(pfm_id1), handle);
+
+ if (memcmp(pfm_id1, signature, sizeof(pfm_id1)) == 0)
+ return TRUE;
+
+ if (memcmp(pfm_id2, signature, sizeof(pfm_id2)) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_FLOAT) ||
+ (type == FIT_RGBF)
+ );
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ char line_buffer[PFM_MAXLINE];
+ char id_one = 0, id_two = 0;
+ FIBITMAP *dib = NULL;
+ float *lineBuffer = NULL;
+
+ if (!handle)
+ return NULL;
+
+ try {
+ FREE_IMAGE_TYPE image_type = FIT_UNKNOWN;
+
+ // Read the first two bytes of the file to determine the file format
+ // "PF" = color image
+ // "Pf" = greyscale image
+
+ io->read_proc(&id_one, 1, 1, handle);
+ io->read_proc(&id_two, 1, 1, handle);
+
+ if(id_one == 'P') {
+ if(id_two == 'F') {
+ image_type = FIT_RGBF;
+ } else if(id_two == 'f') {
+ image_type = FIT_FLOAT;
+ }
+ }
+ if(image_type == FIT_UNKNOWN) {
+ // signature error
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // Read the header information: width, height and the scale value
+ unsigned width = (unsigned) pfm_get_int(io, handle);
+ unsigned height = (unsigned) pfm_get_int(io, handle);
+ float scalefactor = 1;
+
+ BOOL bResult = pfm_get_line(io, handle, line_buffer, PFM_MAXLINE);
+ if(bResult) {
+ bResult = (sscanf(line_buffer, "%f", &scalefactor) == 1) ? TRUE : FALSE;
+ }
+ if(!bResult) {
+ throw "Read error: invalid PFM header";
+ }
+
+ // Create a new DIB
+ dib = FreeImage_AllocateT(image_type, width, height);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // Read the image...
+
+ if(image_type == FIT_RGBF) {
+ const unsigned lineWidth = 3 * width;
+ lineBuffer = (float*)malloc(lineWidth * sizeof(float));
+ if(!lineBuffer) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ for (unsigned y = 0; y < height; y++) {
+ FIRGBF *bits = (FIRGBF*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
+ throw "Read error";
+ }
+ float *channel = lineBuffer;
+ if(scalefactor > 0) {
+ // MSB
+ for (unsigned x = 0; x < width; x++) {
+ REVERSEBYTES(channel++, &bits[x].red);
+ REVERSEBYTES(channel++, &bits[x].green);
+ REVERSEBYTES(channel++, &bits[x].blue);
+ }
+ } else {
+ // LSB
+ for (unsigned x = 0; x < width; x++) {
+ bits[x].red = *channel++;
+ bits[x].green = *channel++;
+ bits[x].blue = *channel++;
+ }
+ }
+ }
+
+ free(lineBuffer);
+ lineBuffer = NULL;
+
+ } else if(image_type == FIT_FLOAT) {
+ const unsigned lineWidth = width;
+ lineBuffer = (float*)malloc(lineWidth * sizeof(float));
+ if(!lineBuffer) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ for (unsigned y = 0; y < height; y++) {
+ float *bits = (float*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ if(io->read_proc(lineBuffer, sizeof(float), lineWidth, handle) != lineWidth) {
+ throw "Read error";
+ }
+ float *channel = lineBuffer;
+ if(scalefactor > 0) {
+ // MSB - File is Big endian
+ for (unsigned x = 0; x < width; x++) {
+ REVERSEBYTES(channel++, &bits[x]);
+ }
+ } else {
+ // LSB - File is Little Endian
+ for (unsigned x = 0; x < width; x++) {
+ bits[x] = *channel++;
+ }
+ }
+ }
+
+ free(lineBuffer);
+ lineBuffer = NULL;
+ }
+
+ return dib;
+
+ } catch (const char *text) {
+ if(lineBuffer) free(lineBuffer);
+ if(dib) FreeImage_Unload(dib);
+
+ if(NULL != text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+
+ return NULL;
+ }
+
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if(!dib || !handle) return FALSE;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if((image_type != FIT_RGBF) && (image_type != FIT_FLOAT)) {
+ return FALSE;
+ }
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned lineWidth = FreeImage_GetLine(dib);
+
+ // save image as Little Endian
+ const float scalefactor = -1.0F;
+
+ char buffer[PFM_MAXLINE]; // temporary buffer whose size should be enough for what we need
+
+ // Find the appropriate magic number for this file type
+
+ char magic = 0;
+
+ switch(image_type) {
+ case FIT_RGBF:
+ magic = 'F'; // RGBF
+ break;
+ case FIT_FLOAT:
+ magic = 'f'; // float greyscale
+ break;
+ default:
+ return FALSE;
+ }
+
+ // Write the header info
+
+ sprintf(buffer, "P%c\n%d %d\n%f\n", magic, width, height, scalefactor);
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ // Write the image data
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+ io->write_proc(bits, 1, lineWidth, handle);
+ }
+
+ return TRUE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPFM(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
+#endif \ No newline at end of file
diff --git a/Source/FreeImage/PluginPICT.cpp b/Source/FreeImage/PluginPICT.cpp
new file mode 100644
index 0000000..7e4f0cd
--- /dev/null
+++ b/Source/FreeImage/PluginPICT.cpp
@@ -0,0 +1,1332 @@
+// ==========================================================
+// Apple Macintosh QuickDraw/PICT Loader
+//
+// Design and implementation by
+// - Amir Ebrahimi (amir@unity3d.com)
+//
+// Based on PICT loading code from paintlib (http://www.paintlib.de/paintlib/).
+//
+// Paintlib License:
+// The paintlib source code and all documentation are copyright (c) 1996-2002
+// Ulrich von Zadow and other contributors.
+//
+// The paintlib source code is supplied "AS IS". Ulrich von Zadow and other
+// contributors disclaim all warranties, expressed or implied, including, without
+// limitation, the warranties of merchantability and of fitness for any purpose.
+// The authors assume no liability for direct, indirect, incidental, special,
+// exemplary, or consequential damages, which may result from the use of paintlib,
+// even if advised of the possibility of such damage.
+//
+// Permission is hereby granted to use, copy, modify, and distribute this source
+// code, or portions hereof, for any purpose, without fee, subject to the following
+// restrictions:
+//
+// 1. The origin of this source code must not be misrepresented.
+// 2. Altered versions must be plainly marked as such and must not be misrepresented
+// as being the original source.
+// 3. This Copyright notice may not be removed or altered from any source or altered
+// source distribution.
+// 4. Executables containing paintlib or parts of it must state that the software
+// "contains paintlib code. paintlib is copyright (c) 1996-2002 Ulrich von Zadow
+// and other contributors.". This notice must be displayed in at least one place
+// where the copyright for the software itself is displayed. The documentation must
+// also contain this notice.
+//
+// Bug fixes were made to the original code to support version 2 PICT files
+// properly.
+//
+// Additional resources:
+// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-458.html
+// http://www.fileformat.info/format/macpict/egff.htm
+//
+// Notes (http://lists.apple.com/archives/java-dev/2006/Apr/msg00588.html):
+// There are three main types of PICT files:
+// - Version 1
+// - Version 2
+// - Extended Version 2
+//
+// Some things to look out for:
+// - The bounds and target DPI are stored in a different place in all three.
+// - Some of the values are fixed-point shorts ( short / 65536f )
+// - Values are big endian
+// - All of this may be *preceded* by a 512 byte header--sometimes it is
+// there, and sometimes it isn't. You just have to check for the magic
+// values in both places.
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+static int s_format_id;
+
+static const int outputMessageSize = 256;
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static unsigned
+Read8(FreeImageIO *io, fi_handle handle) {
+ unsigned char i = 0;
+ io->read_proc(&i, 1, 1, handle);
+ return i;
+}
+
+static unsigned
+Read16(FreeImageIO *io, fi_handle handle) {
+ // reads a two-byte big-endian integer from the given file and returns its value.
+ // assumes unsigned.
+
+ unsigned hi = Read8(io, handle);
+ unsigned lo = Read8(io, handle);
+ return lo + (hi << 8);
+}
+
+static unsigned
+Read32(FreeImageIO *io, fi_handle handle) {
+ // reads a four-byte big-endian integer from the given file and returns its value.
+ // assumes unsigned.
+
+ unsigned b3 = Read8(io, handle);
+ unsigned b2 = Read8(io, handle);
+ unsigned b1 = Read8(io, handle);
+ unsigned b0 = Read8(io, handle);
+ return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
+}
+
+// ----------------------------------------------------------
+
+struct OpDef
+{
+ char * name;
+ int len;
+ char * description;
+};
+
+// for reserved opcodes
+#define res(length) { "reserved", (length), "reserved for Apple use" }
+#define RGB_LEN 6
+#define WORD_LEN -1
+#define NA 0
+
+static OpDef optable[] =
+{
+/* 0x00 */ { "NOP", 0, "nop" },
+/* 0x01 */ { "Clip", NA, "clip" },
+/* 0x02 */ { "BkPat", 8, "background pattern" },
+/* 0x03 */ { "TxFont", 2, "text font (word)" },
+/* 0x04 */ { "TxFace", 1, "text face (byte)" },
+/* 0x05 */ { "TxMode", 2, "text mode (word)" },
+/* 0x06 */ { "SpExtra", 4, "space extra (fixed point)" },
+/* 0x07 */ { "PnSize", 4, "pen size (point)" },
+/* 0x08 */ { "PnMode", 2, "pen mode (word)" },
+/* 0x09 */ { "PnPat", 8, "pen pattern" },
+/* 0x0a */ { "FillPat", 8, "fill pattern" },
+/* 0x0b */ { "OvSize", 4, "oval size (point)" },
+/* 0x0c */ { "Origin", 4, "dh, dv (word)" },
+/* 0x0d */ { "TxSize", 2, "text size (word)" },
+/* 0x0e */ { "FgColor", 4, "foreground color (longword)" },
+/* 0x0f */ { "BkColor", 4, "background color (longword)" },
+/* 0x10 */ { "TxRatio", 8, "numerator (point), denominator (point)" },
+/* 0x11 */ { "Version", 1, "version (byte)" },
+/* 0x12 */ { "BkPixPat", NA, "color background pattern" },
+/* 0x13 */ { "PnPixPat", NA, "color pen pattern" },
+/* 0x14 */ { "FillPixPat", NA, "color fill pattern" },
+/* 0x15 */ { "PnLocHFrac", 2, "fractional pen position" },
+/* 0x16 */ { "ChExtra", 2, "extra for each character" },
+/* 0x17 */ res(0),
+/* 0x18 */ res(0),
+/* 0x19 */ res(0),
+/* 0x1a */ { "RGBFgCol", RGB_LEN, "RGB foreColor" },
+/* 0x1b */ { "RGBBkCol", RGB_LEN, "RGB backColor" },
+/* 0x1c */ { "HiliteMode", 0, "hilite mode flag" },
+/* 0x1d */ { "HiliteColor", RGB_LEN, "RGB hilite color" },
+/* 0x1e */ { "DefHilite", 0, "Use default hilite color" },
+/* 0x1f */ { "OpColor", 6, "RGB OpColor for arithmetic modes" },
+/* 0x20 */ { "Line", 8, "pnLoc (point), newPt (point)" },
+/* 0x21 */ { "LineFrom", 4, "newPt (point)" },
+/* 0x22 */ { "ShortLine", 6, "pnLoc (point, dh, dv (-128 .. 127))" },
+/* 0x23 */ { "ShortLineFrom", 2, "dh, dv (-128 .. 127)" },
+/* 0x24 */ res(WORD_LEN),
+/* 0x25 */ res(WORD_LEN),
+/* 0x26 */ res(WORD_LEN),
+/* 0x27 */ res(WORD_LEN),
+/* 0x28 */ { "LongText", NA, "txLoc (point), count (0..255), text" },
+/* 0x29 */ { "DHText", NA, "dh (0..255), count (0..255), text" },
+/* 0x2a */ { "DVText", NA, "dv (0..255), count (0..255), text" },
+/* 0x2b */ { "DHDVText", NA, "dh, dv (0..255), count (0..255), text" },
+/* 0x2c */ res(WORD_LEN),
+/* 0x2d */ res(WORD_LEN),
+/* 0x2e */ res(WORD_LEN),
+/* 0x2f */ res(WORD_LEN),
+/* 0x30 */ { "frameRect", 8, "rect" },
+/* 0x31 */ { "paintRect", 8, "rect" },
+/* 0x32 */ { "eraseRect", 8, "rect" },
+/* 0x33 */ { "invertRect", 8, "rect" },
+/* 0x34 */ { "fillRect", 8, "rect" },
+/* 0x35 */ res(8),
+/* 0x36 */ res(8),
+/* 0x37 */ res(8),
+/* 0x38 */ { "frameSameRect", 0, "rect" },
+/* 0x39 */ { "paintSameRect", 0, "rect" },
+/* 0x3a */ { "eraseSameRect", 0, "rect" },
+/* 0x3b */ { "invertSameRect", 0, "rect" },
+/* 0x3c */ { "fillSameRect", 0, "rect" },
+/* 0x3d */ res(0),
+/* 0x3e */ res(0),
+/* 0x3f */ res(0),
+/* 0x40 */ { "frameRRect", 8, "rect" },
+/* 0x41 */ { "paintRRect", 8, "rect" },
+/* 0x42 */ { "eraseRRect", 8, "rect" },
+/* 0x43 */ { "invertRRect", 8, "rect" },
+/* 0x44 */ { "fillRRrect", 8, "rect" },
+/* 0x45 */ res(8),
+/* 0x46 */ res(8),
+/* 0x47 */ res(8),
+/* 0x48 */ { "frameSameRRect", 0, "rect" },
+/* 0x49 */ { "paintSameRRect", 0, "rect" },
+/* 0x4a */ { "eraseSameRRect", 0, "rect" },
+/* 0x4b */ { "invertSameRRect", 0, "rect" },
+/* 0x4c */ { "fillSameRRect", 0, "rect" },
+/* 0x4d */ res(0),
+/* 0x4e */ res(0),
+/* 0x4f */ res(0),
+/* 0x50 */ { "frameOval", 8, "rect" },
+/* 0x51 */ { "paintOval", 8, "rect" },
+/* 0x52 */ { "eraseOval", 8, "rect" },
+/* 0x53 */ { "invertOval", 8, "rect" },
+/* 0x54 */ { "fillOval", 8, "rect" },
+/* 0x55 */ res(8),
+/* 0x56 */ res(8),
+/* 0x57 */ res(8),
+/* 0x58 */ { "frameSameOval", 0, "rect" },
+/* 0x59 */ { "paintSameOval", 0, "rect" },
+/* 0x5a */ { "eraseSameOval", 0, "rect" },
+/* 0x5b */ { "invertSameOval", 0, "rect" },
+/* 0x5c */ { "fillSameOval", 0, "rect" },
+/* 0x5d */ res(0),
+/* 0x5e */ res(0),
+/* 0x5f */ res(0),
+/* 0x60 */ { "frameArc", 12, "rect, startAngle, arcAngle" },
+/* 0x61 */ { "paintArc", 12, "rect, startAngle, arcAngle" },
+/* 0x62 */ { "eraseArc", 12, "rect, startAngle, arcAngle" },
+/* 0x63 */ { "invertArc", 12, "rect, startAngle, arcAngle" },
+/* 0x64 */ { "fillArc", 12, "rect, startAngle, arcAngle" },
+/* 0x65 */ res(12),
+/* 0x66 */ res(12),
+/* 0x67 */ res(12),
+/* 0x68 */ { "frameSameArc", 4, "rect, startAngle, arcAngle" },
+/* 0x69 */ { "paintSameArc", 4, "rect, startAngle, arcAngle" },
+/* 0x6a */ { "eraseSameArc", 4, "rect, startAngle, arcAngle" },
+/* 0x6b */ { "invertSameArc", 4, "rect, startAngle, arcAngle" },
+/* 0x6c */ { "fillSameArc", 4, "rect, startAngle, arcAngle" },
+/* 0x6d */ res(4),
+/* 0x6e */ res(4),
+/* 0x6f */ res(4),
+/* 0x70 */ { "framePoly", NA, "poly" },
+/* 0x71 */ { "paintPoly", NA, "poly" },
+/* 0x72 */ { "erasePoly", NA, "poly" },
+/* 0x73 */ { "invertPoly", NA, "poly" },
+/* 0x74 */ { "fillPoly", NA, "poly" },
+/* 0x75 */ res(NA),
+/* 0x76 */ res(NA),
+/* 0x77 */ res(NA),
+/* 0x78 */ { "frameSamePoly", 0, "poly (NYI)" },
+/* 0x79 */ { "paintSamePoly", 0, "poly (NYI)" },
+/* 0x7a */ { "eraseSamePoly", 0, "poly (NYI)" },
+/* 0x7b */ { "invertSamePoly", 0, "poly (NYI)" },
+/* 0x7c */ { "fillSamePoly", 0, "poly (NYI)" },
+/* 0x7d */ res(0),
+/* 0x7e */ res(0),
+/* 0x7f */ res(0),
+/* 0x80 */ { "frameRgn", NA, "region" },
+/* 0x81 */ { "paintRgn", NA, "region" },
+/* 0x82 */ { "eraseRgn", NA, "region" },
+/* 0x83 */ { "invertRgn", NA, "region" },
+/* 0x84 */ { "fillRgn", NA, "region" },
+/* 0x85 */ res(NA),
+/* 0x86 */ res(NA),
+/* 0x87 */ res(NA),
+/* 0x88 */ { "frameSameRgn", 0, "region (NYI)" },
+/* 0x89 */ { "paintSameRgn", 0, "region (NYI)" },
+/* 0x8a */ { "eraseSameRgn", 0, "region (NYI)" },
+/* 0x8b */ { "invertSameRgn", 0, "region (NYI)" },
+/* 0x8c */ { "fillSameRgn", 0, "region (NYI)" },
+/* 0x8d */ res(0),
+/* 0x8e */ res(0),
+/* 0x8f */ res(0),
+/* 0x90 */ { "BitsRect", NA, "copybits, rect clipped" },
+/* 0x91 */ { "BitsRgn", NA, "copybits, rgn clipped" },
+/* 0x92 */ res(WORD_LEN),
+/* 0x93 */ res(WORD_LEN),
+/* 0x94 */ res(WORD_LEN),
+/* 0x95 */ res(WORD_LEN),
+/* 0x96 */ res(WORD_LEN),
+/* 0x97 */ res(WORD_LEN),
+/* 0x98 */ { "PackBitsRect", NA, "packed copybits, rect clipped" },
+/* 0x99 */ { "PackBitsRgn", NA, "packed copybits, rgn clipped" },
+/* 0x9a */ { "Opcode_9A", NA, "the mysterious opcode 9A" },
+/* 0x9b */ res(WORD_LEN),
+/* 0x9c */ res(WORD_LEN),
+/* 0x9d */ res(WORD_LEN),
+/* 0x9e */ res(WORD_LEN),
+/* 0x9f */ res(WORD_LEN),
+/* 0xa0 */ { "ShortComment", 2, "kind (word)" },
+/* 0xa1 */ { "LongComment", NA, "kind (word), size (word), data" }
+};
+
+// ----------------------------------------------------------
+
+struct MacRect
+{
+ WORD top;
+ WORD left;
+ WORD bottom;
+ WORD right;
+};
+
+struct MacpixMap
+{
+ // Ptr baseAddr // Not used in file.
+ // short rowBytes // read in seperatly.
+ struct MacRect Bounds;
+ WORD version;
+ WORD packType;
+ LONG packSize;
+ LONG hRes;
+ LONG vRes;
+ WORD pixelType;
+ WORD pixelSize;
+ WORD cmpCount;
+ WORD cmpSize;
+ LONG planeBytes;
+ LONG pmTable;
+ LONG pmReserved;
+};
+
+struct MacRGBColour
+{
+ WORD red;
+ WORD green;
+ WORD blue;
+};
+
+struct MacPoint
+{
+ WORD x;
+ WORD y;
+};
+
+struct MacPattern // Klaube
+{
+ BYTE pix[64];
+};
+
+// ----------------------------------------------------------
+
+static void
+ReadRect( FreeImageIO *io, fi_handle handle, MacRect* rect ) {
+ rect->top = Read16( io, handle );
+ rect->left = Read16( io, handle );
+ rect->bottom = Read16( io, handle );
+ rect->right = Read16( io, handle );
+}
+
+static void
+ReadPixmap( FreeImageIO *io, fi_handle handle, MacpixMap* pPixMap ) {
+ pPixMap->version = Read16( io, handle );
+ pPixMap->packType = Read16( io, handle );
+ pPixMap->packSize = Read32( io, handle );
+ pPixMap->hRes = Read16( io, handle );
+ Read16( io, handle );
+ pPixMap->vRes = Read16( io, handle );
+ Read16( io, handle );
+ pPixMap->pixelType = Read16( io, handle );
+ pPixMap->pixelSize = Read16( io, handle );
+ pPixMap->cmpCount = Read16( io, handle );
+ pPixMap->cmpSize = Read16( io, handle );
+ pPixMap->planeBytes = Read32( io, handle );
+ pPixMap->pmTable = Read32( io, handle );
+ pPixMap->pmReserved = Read32( io, handle );
+}
+
+/**
+Reads a mac color table into a bitmap palette.
+*/
+static void
+ReadColorTable( FreeImageIO *io, fi_handle handle, WORD* pNumColors, RGBQUAD* pPal ) {
+ LONG ctSeed;
+ WORD ctFlags;
+ WORD val;
+ int i;
+
+ ctSeed = Read32( io, handle );
+ ctFlags = Read16( io, handle );
+ WORD numColors = Read16( io, handle )+1;
+ *pNumColors = numColors;
+
+ for (i = 0; i < numColors; i++) {
+ val = Read16( io, handle );
+ if (ctFlags & 0x8000) {
+ // The indicies in a device colour table are bogus and
+ // usually == 0, so I assume we allocate up the list of
+ // colours in order.
+ val = i;
+ }
+ if (val >= numColors) {
+ throw "pixel value greater than color table size.";
+ }
+ // Mac colour tables contain 16-bit values for R, G, and B...
+ pPal[val].rgbRed = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
+ pPal[val].rgbGreen = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
+ pPal[val].rgbBlue = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
+ }
+}
+
+/**
+skips unneeded packbits.
+pixelSize == Source bits per pixel.
+*/
+static void
+SkipBits( FreeImageIO *io, fi_handle handle, MacRect* bounds, WORD rowBytes, int pixelSize ) {
+ int i;
+ WORD pixwidth; // bytes per row when uncompressed.
+
+ int height = bounds->bottom - bounds->top;
+ int width = bounds->right - bounds->left;
+
+ // High bit of rowBytes is flag.
+ if (pixelSize <= 8) {
+ rowBytes &= 0x7fff;
+ }
+ pixwidth = width;
+
+ if (pixelSize == 16) {
+ pixwidth *= 2;
+ }
+ if (rowBytes == 0) {
+ rowBytes = pixwidth;
+ }
+ if (rowBytes < 8) {
+ io->seek_proc( handle, rowBytes*height, SEEK_CUR );
+ }
+ else {
+ for (i = 0; i < height; i++) {
+ int lineLen; // length of source line in bytes.
+ if (rowBytes > 250) {
+ lineLen = Read16( io, handle );
+ } else {
+ lineLen = Read8( io, handle );
+ }
+ io->seek_proc( handle, lineLen, SEEK_CUR );
+ }
+ }
+}
+
+/**
+Skip polygon or region
+*/
+static void
+SkipPolyOrRegion( FreeImageIO *io, fi_handle handle ) {
+ WORD len = Read16( io, handle ) - 2;
+ io->seek_proc(handle, len, SEEK_CUR);
+}
+
+/**
+Width in bytes for 8 bpp or less.
+Width in pixels for 16 bpp.
+Expands Width units to 32-bit pixel data.
+*/
+static void
+expandBuf( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst ) {
+ switch (bpp) {
+ case 16:
+ for ( int i=0; i<width; i++) {
+ WORD src = Read16( io, handle );
+ dst[ FI_RGBA_BLUE ] = (src & 31)*8; // Blue
+ dst[ FI_RGBA_GREEN ] = ((src >> 5) & 31)*8; // Green
+ dst[ FI_RGBA_RED ] = ((src >> 10) & 31)*8; // Red
+ dst[ FI_RGBA_ALPHA ] = 0xFF; // Alpha
+ dst += 4;
+ }
+ break;
+ default:
+ throw "Bad bits per pixel in expandBuf.";
+ }
+}
+
+/**
+Expands Width units to 8-bit pixel data.
+Max. 8 bpp source format.
+*/
+static void
+expandBuf8( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst )
+{
+ switch (bpp) {
+ case 8:
+ io->read_proc( dst, width, 1, handle );
+ break;
+ case 4:
+ for (int i = 0; i < width; i++) {
+ WORD src = Read8( io, handle );
+ *dst = (src >> 4) & 15;
+ *(dst+1) = (src & 15);
+ dst += 2;
+ }
+ if (width & 1) { // Odd Width?
+ WORD src = Read8( io, handle );
+ *dst = (src >> 4) & 15;
+ dst++;
+ }
+ break;
+ case 2:
+ for (int i = 0; i < width; i++) {
+ WORD src = Read8( io, handle );
+ *dst = (src >> 6) & 3;
+ *(dst+1) = (src >> 4) & 3;
+ *(dst+2) = (src >> 2) & 3;
+ *(dst+3) = (src & 3);
+ dst += 4;
+ }
+ if (width & 3) { // Check for leftover pixels
+ for (int i = 6; i > 8 - (width & 3) * 2; i -= 2) {
+ WORD src = Read8( io, handle );
+ *dst = (src >> i) & 3;
+ dst++;
+ }
+ }
+ break;
+ case 1:
+ for (int i = 0; i < width; i++) {
+ WORD src = Read8( io, handle );
+ *dst = (src >> 7) & 1;
+ *(dst+1) = (src >> 6) & 1;
+ *(dst+2) = (src >> 5) & 1;
+ *(dst+3) = (src >> 4) & 1;
+ *(dst+4) = (src >> 3) & 1;
+ *(dst+5) = (src >> 2) & 1;
+ *(dst+6) = (src >> 1) & 1;
+ *(dst+7) = (src & 1);
+ dst += 8;
+ }
+ if (width & 7) { // Check for leftover pixels
+ for (int i = 7; i > (8-width & 7); i--) {
+ WORD src = Read8( io, handle );
+ *dst = (src >> i) & 1;
+ dst++;
+ }
+ }
+ break;
+ default:
+ throw "Bad bits per pixel in expandBuf8.";
+ }
+}
+
+static BYTE*
+UnpackPictRow( FreeImageIO *io, fi_handle handle, BYTE* pLineBuf, int width, int rowBytes, int srcBytes ) {
+ if (rowBytes < 8) { // Ah-ha! The bits aren't actually packed. This will be easy.
+ io->read_proc( pLineBuf, rowBytes, 1, handle );
+ }
+ else {
+ BYTE* pCurPixel = pLineBuf;
+
+ // Unpack RLE. The data is packed bytewise.
+ for (int j = 0; j < srcBytes; ) {
+ BYTE FlagCounter = Read8( io, handle );
+ if (FlagCounter & 0x80) {
+ if (FlagCounter == 0x80) {
+ // Special case: repeat value of 0.
+ // Apple says ignore.
+ j++;
+ } else {
+ // Packed data.
+ int len = ((FlagCounter ^ 255) & 255) + 2;
+ BYTE p = Read8( io, handle );
+ memset( pCurPixel, p, len);
+ pCurPixel += len;
+ j += 2;
+ }
+ }
+ else {
+ // Unpacked data
+ int len = (FlagCounter & 255) + 1;
+ io->read_proc( pCurPixel, len, 1, handle );
+ pCurPixel += len;
+ j += len + 1;
+ }
+ }
+ }
+
+ return pLineBuf;
+}
+
+/**
+This routine decompresses BitsRects with a packType of 4 (and 32 bits per pixel).
+In this format, each line is separated into 8-bit-bitplanes and then compressed via RLE.
+To decode, the routine decompresses each line & then juggles the bytes around to get pixel-oriented data.
+NumBitPlanes == 3 if RGB, 4 if RGBA
+*/
+static void
+Unpack32Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int numPlanes ) {
+ int height = bounds->bottom - bounds->top;
+ int width = bounds->right - bounds->left;
+
+ if (rowBytes == 0) {
+ rowBytes = width*4;
+ }
+
+ BYTE* pLineBuf = (BYTE*)malloc( rowBytes ); // Let's allocate enough for 4 bit planes
+ if ( pLineBuf ) {
+ try {
+ for ( int i = 0; i < height; i++ ) {
+ // for each line do...
+ int linelen; // length of source line in bytes.
+ if (rowBytes > 250) {
+ linelen = Read16( io, handle );
+ } else {
+ linelen = Read8( io, handle);
+ }
+
+ BYTE* pBuf = UnpackPictRow( io, handle, pLineBuf, width, rowBytes, linelen );
+
+ // Convert plane-oriented data into pixel-oriented data &
+ // copy into destination bitmap.
+ BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
+
+ if ( numPlanes == 3 ) {
+ for ( int j = 0; j < width; j++ ) {
+ // For each pixel in line...
+ dst[ FI_RGBA_BLUE ] = (*(pBuf+width*2)); // Blue
+ dst[ FI_RGBA_GREEN ] = (*(pBuf+width)); // Green
+ dst[ FI_RGBA_RED ] = (*pBuf); // Red
+ dst[ FI_RGBA_ALPHA ] = (0xFF);
+ dst += 4;
+ pBuf++;
+ }
+ } else {
+ for ( int j = 0; j < width; j++ ) {
+ // For each pixel in line...
+ dst[ FI_RGBA_BLUE ] = (*(pBuf+width*3)); // Blue
+ dst[ FI_RGBA_GREEN ] = (*(pBuf+width*2)); // Green
+ dst[ FI_RGBA_RED ] = (*(pBuf+width)); // Red
+ dst[ FI_RGBA_ALPHA ] = (*pBuf);
+ dst += 4;
+ pBuf++;
+ }
+ }
+ }
+ }
+ catch( ... ) {
+ free( pLineBuf );
+ throw;
+ }
+ }
+ free( pLineBuf );
+}
+
+/**
+Decompression routine for 8 bpp.
+rowBytes is the number of bytes each source row would take if it were uncompressed.
+This _isn't_ equal to the number of pixels in the row - it seems apple pads the data to a word boundary and then compresses it.
+Of course, we have to decompress the excess data and then throw it away.
+*/
+static void
+Unpack8Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes ) {
+ int height = bounds->bottom - bounds->top;
+ int width = bounds->right - bounds->left;
+
+ // High bit of rowBytes is flag.
+ rowBytes &= 0x7fff;
+
+ if (rowBytes == 0) {
+ rowBytes = width;
+ }
+
+ for ( int i = 0; i < height; i++ ) {
+ int linelen; // length of source line in bytes.
+ if (rowBytes > 250) {
+ linelen = Read16( io, handle );
+ } else {
+ linelen = Read8( io, handle );
+ }
+ BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
+ dst = UnpackPictRow( io, handle, dst, width, rowBytes, linelen );
+ }
+}
+
+/**
+Decompression routine for everything but 8 & 32 bpp.
+This routine is slower than the two routines above since it has to deal with a lot of special cases :-(.
+It's also a bit chaotic because of these special cases...
+unpack8bits is basically a dumber version of unpackbits.
+pixelSize == Source bits per pixel.
+*/
+static void
+UnpackBits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int pixelSize ) {
+ WORD pixwidth; // bytes per row when uncompressed.
+ int pkpixsize;
+ int PixelPerRLEUnit;
+
+ char outputMessage[ outputMessageSize ] = "";
+
+ int height = bounds->bottom - bounds->top;
+ int width = bounds->right - bounds->left;
+
+ // High bit of rowBytes is flag.
+ if (pixelSize <= 8) {
+ rowBytes &= 0x7fff;
+ }
+
+ pixwidth = width;
+ pkpixsize = 1; // RLE unit: one byte for everything...
+ if (pixelSize == 16) { // ...except 16 bpp.
+ pkpixsize = 2;
+ pixwidth *= 2;
+ }
+
+ if (rowBytes == 0) {
+ rowBytes = pixwidth;
+ }
+
+ {
+ // I allocate the temporary line buffer here. I allocate too
+ // much memory to compensate for sloppy (& hence fast) decompression.
+ switch (pixelSize) {
+ case 1:
+ PixelPerRLEUnit = 8;
+ break;
+ case 2:
+ PixelPerRLEUnit = 4;
+ break;
+ case 4:
+ PixelPerRLEUnit = 2;
+ break;
+ case 8:
+ PixelPerRLEUnit = 1;
+ break;
+ case 16:
+ PixelPerRLEUnit = 1;
+ break;
+ default:
+ sprintf( outputMessage, "Illegal bpp value in unpackbits: %d\n", pixelSize );
+ throw outputMessage;
+ }
+
+ if (rowBytes < 8) {
+ // ah-ha! The bits aren't actually packed. This will be easy.
+ for ( int i = 0; i < height; i++ ) {
+ BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
+ if (pixelSize == 16) {
+ expandBuf( io, handle, width, pixelSize, dst );
+ } else {
+ expandBuf8( io, handle, width, pixelSize, dst );
+ }
+ }
+ }
+ else {
+ for ( int i = 0; i < height; i++ ) {
+ // For each line do...
+ int linelen; // length of source line in bytes.
+ if (rowBytes > 250) {
+ linelen = Read16( io, handle );
+ } else {
+ linelen = Read8( io, handle );
+ }
+
+ BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
+ BYTE FlagCounter;
+
+ // Unpack RLE. The data is packed bytewise - except for
+ // 16 bpp data, which is packed per pixel :-(.
+ for ( int j = 0; j < linelen; ) {
+ FlagCounter = Read8( io, handle );
+ if (FlagCounter & 0x80) {
+ if (FlagCounter == 0x80) {
+ // Special case: repeat value of 0.
+ // Apple says ignore.
+ j++;
+ }
+ else {
+ // Packed data.
+ int len = ((FlagCounter ^ 255) & 255) + 2;
+
+ // This is slow for some formats...
+ if (pixelSize == 16) {
+ expandBuf( io, handle, 1, pixelSize, dst );
+ for ( int k = 1; k < len; k++ ) {
+ // Repeat the pixel len times.
+ memcpy( dst+(k*4*PixelPerRLEUnit), dst, 4*PixelPerRLEUnit);
+ }
+ dst += len*4*PixelPerRLEUnit;
+ }
+ else {
+ expandBuf8( io, handle, 1, pixelSize, dst );
+ for ( int k = 1; k < len; k++ ) {
+ // Repeat the expanded byte len times.
+ memcpy( dst+(k*PixelPerRLEUnit), dst, PixelPerRLEUnit);
+ }
+ dst += len*PixelPerRLEUnit;
+ }
+ j += pkpixsize + 1;
+ }
+ }
+ else {
+ // Unpacked data
+ int len = (FlagCounter & 255) + 1;
+ if (pixelSize == 16) {
+ expandBuf( io, handle, len, pixelSize, dst );
+ dst += len*4*PixelPerRLEUnit;
+ }
+ else {
+ expandBuf8( io, handle, len, pixelSize, dst );
+ dst += len*PixelPerRLEUnit;
+ }
+ j += ( len * pkpixsize ) + 1;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+DecodeOp9a( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacpixMap* pixMap ) {
+ // Do the actual unpacking.
+ switch ( pixMap->pixelSize ) {
+ case 32:
+ Unpack32Bits( io, handle, dib, &pixMap->Bounds, 0, pixMap->cmpCount );
+ break;
+ case 8:
+ Unpack8Bits( io, handle, dib, &pixMap->Bounds, 0 );
+ break;
+ default:
+ UnpackBits( io, handle, dib, &pixMap->Bounds, 0, pixMap->pixelSize );
+ }
+}
+
+static void
+DecodeBitmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacRect* bounds, WORD rowBytes ) {
+ WORD mode = Read16( io, handle );
+
+ if ( isRegion ) {
+ SkipPolyOrRegion( io, handle );
+ }
+
+ RGBQUAD* pal = FreeImage_GetPalette( dib );
+ if ( !pal ) {
+ throw "No palette for bitmap!";
+ }
+
+ for (int i = 0; i < 2; i++) {
+ unsigned char val = i ? 0xFF : 0x0;
+ pal[i].rgbRed = val;
+ pal[i].rgbGreen = val;
+ pal[i].rgbBlue = val;
+ }
+
+ UnpackBits( io, handle, dib, bounds, rowBytes, 1 );
+}
+
+static void
+DecodePixmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacpixMap* pixMap, WORD rowBytes ) {
+ // Read mac colour table into windows palette.
+ WORD numColors; // Palette size.
+ RGBQUAD ct[256];
+
+ ReadColorTable( io, handle, &numColors, ct );
+ if ( FreeImage_GetBPP( dib ) == 8 ) {
+ RGBQUAD* pal = FreeImage_GetPalette( dib );
+ if ( !pal ) {
+ throw "No palette for bitmap!";
+ }
+
+ for (int i = 0; i < numColors; i++) {
+ pal[i].rgbRed = ct[ i ].rgbRed;
+ pal[i].rgbGreen = ct[ i ].rgbGreen;
+ pal[i].rgbBlue = ct[ i ].rgbBlue;
+ }
+ }
+
+ // Ignore source & destination rectangle as well as transfer mode.
+ MacRect tempRect;
+ ReadRect( io, handle, &tempRect );
+ ReadRect( io, handle, &tempRect );
+ WORD mode = Read16( io, handle );
+
+ if ( isRegion) {
+ SkipPolyOrRegion( io, handle );
+ }
+
+ switch ( pixMap->pixelSize ) {
+ case 32:
+ Unpack32Bits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->cmpCount );
+ break;
+ case 8:
+ Unpack8Bits( io, handle, dib, &pixMap->Bounds, rowBytes );
+ break;
+ default:
+ UnpackBits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->pixelSize );
+ }
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PICT";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Macintosh PICT";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "pct,pict,pic";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-pict";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ if(io->seek_proc(handle, 522, SEEK_SET) == 0) {
+ BYTE pict_signature[] = { 0x00, 0x11, 0x02, 0xFF, 0x0C, 0X00 };
+ BYTE signature[6];
+
+ if(io->read_proc(signature, 1, sizeof(pict_signature), handle)) {
+ // v1.0 files have 0x11 (version operator) followed by 0x01 (version number)
+ // v2.0 files have 0x0011 (version operator) followed by 0x02ff (version number)
+ // and additionally 0x0c00 as a header opcode
+ // Currently, we are only supporting v2.0
+ return (memcmp(pict_signature, signature, sizeof(pict_signature)) == 0);
+ } else {
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return FALSE;
+}
+
+/**
+This plugin decodes macintosh PICT files with 1,2,4,8,16 and 32 bits per pixel as well as PICT/JPEG.
+If an alpha channel is present in a 32-bit-PICT, it is decoded as well.
+The PICT format is a general picture file format and can contain a lot of other elements besides bitmaps.
+These elements are ignored.
+*/
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ char outputMessage[ outputMessageSize ] = "";
+ FIBITMAP* dib = NULL;
+ try {
+ // Skip empty 512 byte header.
+ if ( !io->seek_proc(handle, 512, SEEK_CUR) == 0 )
+ return NULL;
+
+ // Read PICT header
+ Read16( io, handle ); // Skip version 1 picture size
+
+ MacRect frame;
+ ReadRect( io, handle, &frame );
+
+ BYTE b = 0;
+ while ((b = Read8(io, handle)) == 0);
+ if ( b != 0x11 ) {
+ throw "invalid header: version number missing.";
+ }
+
+ int version = Read8( io, handle );
+ if ( version == 2 && Read8( io, handle ) != 0xff ) {
+ throw "invalid header: illegal version number.";
+ }
+
+ enum PICTType {none, op9a, jpeg, pixmap, bitmap};
+ PICTType pictType = none;
+
+ MacRect bounds;
+ MacpixMap pixMap;
+ int hRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
+ int vRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
+ WORD rowBytes = 0;
+ BOOL isRegion = FALSE;
+ BOOL done = FALSE;
+ while ( !done ) {
+ WORD opcode = 0;
+
+ if ((version == 1) || ((io->tell_proc( handle ) % 2) != 0)) {
+ // align to word for version 2
+ opcode = Read8( io, handle );
+ }
+ if (version == 2) {
+ opcode = Read16( io, handle );
+ }
+
+ if (opcode == 0xFF || opcode == 0xFFFF) {
+ done = TRUE;
+ throw "PICT contained only vector data!";
+ }
+ else if (opcode < 0xa2) {
+ switch (opcode) {
+ case 0x01:
+ {
+ // skip clipping rectangle
+ MacRect clipRect;
+ WORD len = Read16( io, handle );
+
+ if (len == 0x000a) {
+ /* null rgn */
+ ReadRect( io, handle, &clipRect );
+ } else {
+ io->seek_proc(handle, len - 2, SEEK_CUR);
+ }
+ break;
+ }
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ {
+ // skip pattern definition
+ WORD patType;
+ WORD rowBytes;
+ MacpixMap p;
+ WORD numColors;
+
+ patType = Read16( io, handle );
+
+ switch( patType ) {
+ case 2:
+ io->seek_proc(handle, 8, SEEK_CUR);
+ io->seek_proc(handle, 5, SEEK_CUR);
+ break;
+ case 1:
+ {
+ io->seek_proc(handle, 8, SEEK_CUR);
+ rowBytes = Read16( io, handle );
+ ReadRect( io, handle, &p.Bounds );
+ ReadPixmap( io, handle, &p);
+
+ RGBQUAD ct[256];
+ ReadColorTable(io, handle, &numColors, ct );
+ SkipBits( io, handle, &p.Bounds, rowBytes, p.pixelSize );
+ break;
+ }
+ default:
+ throw "Unknown pattern type.";
+ }
+
+ break;
+ }
+ case 0x70:
+ case 0x71:
+ case 0x72:
+ case 0x73:
+ case 0x74:
+ case 0x75:
+ case 0x76:
+ case 0x77:
+ {
+ SkipPolyOrRegion( io, handle );
+ break;
+ }
+ case 0x90:
+ case 0x98:
+ {
+ // Bitmap/pixmap data clipped by a rectangle.
+ rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed.
+ isRegion = FALSE;
+
+ if ( rowBytes & 0x8000) {
+ pictType = pixmap;
+ } else {
+ pictType = bitmap;
+ }
+ done = TRUE;
+ break;
+ }
+ case 0x91:
+ case 0x99:
+ {
+ // Bitmap/pixmap data clipped by a region.
+ rowBytes = Read16( io, handle ); // Bytes per row in source when uncompressed.
+ isRegion = TRUE;
+
+ if ( rowBytes & 0x8000) {
+ pictType = pixmap;
+ } else {
+ pictType = bitmap;
+ }
+ done = TRUE;
+ break;
+ }
+ case 0x9a:
+ {
+ // DirectBitsRect.
+ Read32( io, handle ); // Skip fake len and fake EOF.
+ Read16( io, handle ); // bogus row bytes.
+
+ // Read in the PixMap fields.
+ ReadRect( io, handle, &pixMap.Bounds );
+ ReadPixmap( io, handle, &pixMap );
+
+ // Ignore source & destination rectangle as well as transfer mode.
+ MacRect dummy;
+ ReadRect( io, handle, &dummy );
+ ReadRect( io, handle, &dummy );
+ WORD mode = Read16( io, handle );
+
+ pictType=op9a;
+ done = TRUE;
+ break;
+ }
+ case 0xa1:
+ {
+ // long comment
+ WORD type;
+ WORD len;
+
+ type = Read16( io, handle );
+ len = Read16( io, handle);
+ if (len > 0) {
+ io->seek_proc(handle, len, SEEK_CUR);
+ }
+ break;
+ }
+ default:
+ // No function => skip to next opcode
+ if (optable[opcode].len == WORD_LEN) {
+ WORD len = Read16( io, handle );
+ io->seek_proc(handle, len, SEEK_CUR);
+ } else {
+ io->seek_proc(handle, optable[opcode].len, SEEK_CUR);
+ }
+ break;
+ }
+ }
+ else if (opcode == 0xc00) {
+ // version 2 header (26 bytes)
+ WORD minorVersion = Read16( io, handle ); // always FFFE (-2) for extended version 2
+ Read16( io, handle ); // reserved
+ hRes = Read32( io, handle ); // original horizontal resolution in pixels/inch
+ vRes = Read32( io, handle ); // original horizontal resolution in pixels/inch
+ MacRect dummy;
+ ReadRect( io, handle, &dummy ); // frame bounds at original resolution
+ Read32( io, handle ); // reserved
+ }
+ else if (opcode == 0x8200) {
+ // jpeg
+ long opLen = Read32( io, handle );
+ BOOL found = FALSE;
+ int i = 0;
+
+ // skip to JPEG header.
+ while ( !found && i < opLen ) {
+// io->seek_proc( handle, 24, SEEK_CUR );
+// MacRect dummy;
+// ReadRect( io, handle, &dummy );
+// io->seek_proc( handle, 122, SEEK_CUR );
+// found = TRUE;
+ BYTE data[ 2 ];
+ if( io->read_proc( data, 2, 1, handle ) ) {
+ io->seek_proc( handle, -2, SEEK_CUR );
+
+ if ( data[0] == 0xFF && data[1] == 0xD8 ) {
+ found = TRUE;
+ } else {
+ Read8( io, handle );
+ i++;
+ }
+ }
+ }
+
+ if ( found ) {
+ // Pass the data to the JPEG decoder.
+ pictType = jpeg;
+ } else {
+ throw "PICT file contains unrecognized quicktime data.";
+ }
+ done = TRUE;
+ }
+ else if (opcode >= 0xa2 && opcode <= 0xaf) {
+ // reserved
+ WORD len = Read16( io, handle );
+ io->seek_proc(handle, len, SEEK_CUR);
+ }
+ else if ((opcode >= 0xb0 && opcode <= 0xcf) || (opcode >= 0x8000 && opcode <= 0x80ff)) {
+ // just a reserved opcode, no data
+ }
+ else if ((opcode >= 0xd0 && opcode <= 0xfe) || opcode >= 8100) {
+ // reserved
+ LONG len = Read32( io, handle );
+ io->seek_proc(handle, len, SEEK_CUR);
+ }
+ else if (opcode >= 0x100 && opcode <= 0x7fff) {
+ // reserved
+ io->seek_proc(handle, ((opcode >> 7) & 255), SEEK_CUR);
+ }
+ else {
+ sprintf( outputMessage, "Can't handle opcode %x.\n", opcode );
+ throw outputMessage;
+ }
+ }
+
+ switch ( pictType ) {
+ case op9a:
+ {
+ bounds = pixMap.Bounds;
+ int width = bounds.right - bounds.left;
+ int height = bounds.bottom - bounds.top;
+
+ if ( pixMap.pixelSize > 8 ) {
+ dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate( width, height, 8);
+ }
+ hRes = pixMap.hRes << 16;
+ vRes = pixMap.vRes << 16;
+ break;
+ }
+
+ case jpeg:
+ {
+ dib = FreeImage_LoadFromHandle( FIF_JPEG, io, handle );
+ break;
+ }
+
+ case pixmap:
+ {
+ // Decode version 2 pixmap
+ ReadRect( io, handle, &pixMap.Bounds );
+ ReadPixmap( io, handle, &pixMap );
+
+ bounds = pixMap.Bounds;
+ int width = bounds.right - bounds.left;
+ int height = bounds.bottom - bounds.top;
+
+ if ( pixMap.pixelSize > 8 ) {
+ dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate( width, height, 8);
+ }
+ hRes = pixMap.hRes << 16;
+ vRes = pixMap.vRes << 16;
+ break;
+ }
+
+ case bitmap:
+ {
+ // Decode version 1 bitmap: 1 bpp.
+ MacRect srcRect;
+ MacRect dstRect;
+ WORD width; // Width in pixels
+ WORD height; // Height in pixels
+
+ ReadRect( io, handle, &bounds );
+ ReadRect( io, handle, &srcRect );
+ ReadRect( io, handle, &dstRect );
+
+ width = bounds.right - bounds.left;
+ height = bounds.bottom - bounds.top;
+
+ dib = FreeImage_Allocate(width, height, 8);
+ break;
+ }
+ }
+
+ if ( dib ) {
+ // need to convert resolution figures from fixed point, pixels/inch
+ // to floating point, pixels/meter.
+ float hres_ppm = hRes * ((float)39.4 / (float)65536.0);
+ float vres_ppm = vRes * ((float)39.4 / (float)65536.0);
+
+ FreeImage_SetDotsPerMeterX( dib, (LONG)hres_ppm );
+ FreeImage_SetDotsPerMeterY( dib, (LONG)vres_ppm );
+
+ switch( pictType ) {
+ case op9a:
+ DecodeOp9a( io, handle, dib, &pixMap );
+ break;
+ case jpeg:
+ // Already decoded if the embedded format was valid.
+ break;
+ case pixmap:
+ DecodePixmap( io, handle, dib, isRegion, &pixMap, rowBytes );
+ break;
+ case bitmap:
+ DecodeBitmap( io, handle, dib, isRegion, &bounds, rowBytes );
+ break;
+ default:
+ throw "invalid pict type";
+ }
+ }
+
+ return dib;
+ }
+ catch(const char *message) {
+ FreeImage_Unload( dib );
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPICT(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = NULL;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Source/FreeImage/PluginPNG.cpp b/Source/FreeImage/PluginPNG.cpp
new file mode 100644
index 0000000..b6cc5c1
--- /dev/null
+++ b/Source/FreeImage/PluginPNG.cpp
@@ -0,0 +1,924 @@
+// ==========================================================
+// PNG Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Herve Drolon (drolon@infonie.fr)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+// - Aaron Shumate (trek@startreker.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#ifdef WIN32 // Needs to happen before zlib.h inclusion or things get messed up
+#include <windows.h>
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+#include "../Metadata/FreeImageTag.h"
+
+// ----------------------------------------------------------
+
+#define PNG_BYTES_TO_CHECK 8
+
+// ----------------------------------------------------------
+
+#include "../LibPNG/png.h"
+
+// ----------------------------------------------------------
+
+typedef struct {
+ FreeImageIO *s_io;
+ fi_handle s_handle;
+} fi_ioStructure, *pfi_ioStructure;
+
+/////////////////////////////////////////////////////////////////////////////
+// libpng interface
+//
+
+static void
+_ReadProc(png_structp png_ptr, unsigned char *data, png_size_t size) {
+ pfi_ioStructure pfio = (pfi_ioStructure)png_get_io_ptr(png_ptr);
+ unsigned n = pfio->s_io->read_proc(data, (unsigned int)size, 1, pfio->s_handle);
+ if(size && (n == 0)) {
+ throw "Read error: invalid or corrupted PNG file";
+ }
+}
+
+static void
+_WriteProc(png_structp png_ptr, unsigned char *data, png_size_t size) {
+ pfi_ioStructure pfio = (pfi_ioStructure)png_get_io_ptr(png_ptr);
+ pfio->s_io->write_proc(data, (unsigned int)size, 1, pfio->s_handle);
+}
+
+static void
+_FlushProc(png_structp png_ptr) {
+ // empty flush implementation
+}
+
+static void
+error_handler(png_structp png_ptr, const char *error) {
+ throw error;
+}
+
+// in FreeImage warnings disabled
+
+static void
+warning_handler(png_structp png_ptr, const char *warning) {
+}
+
+// ==========================================================
+// Metadata routines
+// ==========================================================
+
+static BOOL
+ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
+ // XMP keyword
+ char *g_png_xmp_keyword = "XML:com.adobe.xmp";
+
+ FITAG *tag = NULL;
+ png_textp text_ptr = NULL;
+ int num_text = 0;
+
+ // iTXt/tEXt/zTXt chuncks
+ if(png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) {
+ for(int i = 0; i < num_text; i++) {
+
+ DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length);
+
+ // sanity check the tag in case of corruption (ESL/TPN) issue Mantis 1344
+ if((text_ptr[i].key == NULL) || (tag_length > 255))
+ return FALSE;
+
+ // create a tag
+ tag = FreeImage_CreateTag();
+ if(!tag) return FALSE;
+
+ FreeImage_SetTagLength(tag, tag_length);
+ FreeImage_SetTagCount(tag, tag_length);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, text_ptr[i].text);
+
+ if(strcmp(text_ptr[i].key, g_png_xmp_keyword) == 0) {
+ // store the tag as XMP
+ FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
+ FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
+ } else {
+ // store the tag as a comment
+ FreeImage_SetTagKey(tag, text_ptr[i].key);
+ FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
+ }
+
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+ }
+ }
+
+ return TRUE;
+}
+
+static BOOL
+WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
+ // XMP keyword
+ char *g_png_xmp_keyword = "XML:com.adobe.xmp";
+
+ FITAG *tag = NULL;
+ FIMETADATA *mdhandle = NULL;
+ BOOL bResult = TRUE;
+
+ png_text text_metadata;
+
+ // set the 'Comments' metadata as iTXt chuncks
+
+ mdhandle = FreeImage_FindFirstMetadata(FIMD_COMMENTS, dib, &tag);
+
+ if(mdhandle) {
+ do {
+ memset(&text_metadata, 0, sizeof(png_text));
+ text_metadata.compression = 1; // iTXt, none
+ text_metadata.key = (char*)FreeImage_GetTagKey(tag); // keyword, 1-79 character description of "text"
+ text_metadata.text = (char*)FreeImage_GetTagValue(tag); // comment, may be an empty string (ie "")
+ text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string
+ text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string
+ text_metadata.lang = 0; // language code, 0-79 characters or a NULL pointer
+ text_metadata.lang_key = 0; // keyword translated UTF-8 string, 0 or more chars or a NULL pointer
+
+ // set the tag
+ png_set_text(png_ptr, info_ptr, &text_metadata, 1);
+
+ } while(FreeImage_FindNextMetadata(mdhandle, &tag));
+
+ FreeImage_FindCloseMetadata(mdhandle);
+ bResult &= TRUE;
+ }
+
+ // set the 'XMP' metadata as iTXt chuncks
+ tag = NULL;
+ FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag);
+ if(tag && FreeImage_GetTagLength(tag)) {
+ memset(&text_metadata, 0, sizeof(png_text));
+ text_metadata.compression = 1; // iTXt, none
+ text_metadata.key = g_png_xmp_keyword; // keyword, 1-79 character description of "text"
+ text_metadata.text = (char*)FreeImage_GetTagValue(tag); // comment, may be an empty string (ie "")
+ text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string
+ text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string
+ text_metadata.lang = 0; // language code, 0-79 characters or a NULL pointer
+ text_metadata.lang_key = 0; // keyword translated UTF-8 string, 0 or more chars or a NULL pointer
+
+ // set the tag
+ png_set_text(png_ptr, info_ptr, &text_metadata, 1);
+ bResult &= TRUE;
+ }
+
+ return bResult;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PNG";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Portable Network Graphics";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "png";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^.PNG\r";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/png";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
+ BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ io->read_proc(&signature, 1, 8, handle);
+
+ return (memcmp(png_signature, signature, 8) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1) ||
+ (depth == 4) ||
+ (depth == 8) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_BITMAP) ||
+ (type == FIT_UINT16) ||
+ (type == FIT_RGB16) ||
+ (type == FIT_RGBA16)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ png_structp png_ptr = NULL;
+ png_infop info_ptr;
+ png_uint_32 width, height;
+ png_colorp png_palette = NULL;
+ int color_type, palette_entries = 0;
+ int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels
+
+ FIBITMAP *dib = NULL;
+ RGBQUAD *palette = NULL; // pointer to dib palette
+ png_bytepp row_pointers = NULL;
+ int i;
+
+ fi_ioStructure fio;
+ fio.s_handle = handle;
+ fio.s_io = io;
+
+ if (handle) {
+ try {
+ // check to see if the file is in fact a PNG file
+
+ BYTE png_check[PNG_BYTES_TO_CHECK];
+
+ io->read_proc(png_check, PNG_BYTES_TO_CHECK, 1, handle);
+
+ if (png_sig_cmp(png_check, (png_size_t)0, PNG_BYTES_TO_CHECK) != 0)
+ return NULL; // Bad signature
+
+ // create the chunk manage structure
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);
+
+ if (!png_ptr)
+ return NULL;
+
+ // create the info structure
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return NULL;
+ }
+
+ // init the IO
+
+ png_set_read_fn(png_ptr, &fio, _ReadProc);
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ return NULL;
+ }
+
+ // because we have already read the signature...
+
+ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
+
+ // read the IHDR chunk
+
+ png_read_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL);
+ pixel_depth = info_ptr->pixel_depth;
+
+ // get image data type (assume standard image type)
+
+ FREE_IMAGE_TYPE image_type = FIT_BITMAP;
+ if (bit_depth == 16) {
+ if ((pixel_depth == 16) && (color_type == PNG_COLOR_TYPE_GRAY)) {
+ image_type = FIT_UINT16;
+ }
+ else if ((pixel_depth == 48) && (color_type == PNG_COLOR_TYPE_RGB)) {
+ image_type = FIT_RGB16;
+ }
+ else if ((pixel_depth == 64) && (color_type == PNG_COLOR_TYPE_RGB_ALPHA)) {
+ image_type = FIT_RGBA16;
+ } else {
+ // tell libpng to strip 16 bit/color files down to 8 bits/color
+ png_set_strip_16(png_ptr);
+ bit_depth = 8;
+ }
+ }
+
+#ifndef FREEIMAGE_BIGENDIAN
+ if((image_type == FIT_UINT16) || (image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
+ // turn on 16 bit byte swapping
+ png_set_swap(png_ptr);
+ }
+#endif
+
+ // set some additional flags
+
+ switch(color_type) {
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // flip the RGB pixels to BGR (or RGBA to BGRA)
+
+ if(image_type == FIT_BITMAP)
+ png_set_bgr(png_ptr);
+#endif
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ // expand palette images to the full 8 bits from 2 bits/pixel
+
+ if (pixel_depth == 2) {
+ png_set_packing(png_ptr);
+ pixel_depth = 8;
+ }
+
+ break;
+
+ case PNG_COLOR_TYPE_GRAY:
+ // expand grayscale images to the full 8 bits from 2 bits/pixel
+
+ if (pixel_depth == 2) {
+ png_set_expand(png_ptr);
+ pixel_depth = 8;
+ }
+
+ break;
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ // expand 8-bit greyscale + 8-bit alpha to 32-bit
+
+ png_set_gray_to_rgb(png_ptr);
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // flip the RGBA pixels to BGRA
+
+ png_set_bgr(png_ptr);
+#endif
+ pixel_depth = 32;
+
+ break;
+
+ default:
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // Get the background color to draw transparent and alpha images over.
+ // Note that even if the PNG file supplies a background, you are not required to
+ // use it - you should use the (solid) application background if it has one.
+
+ png_color_16p image_background = NULL;
+ RGBQUAD rgbBkColor;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
+ rgbBkColor.rgbRed = (BYTE)image_background->red;
+ rgbBkColor.rgbGreen = (BYTE)image_background->green;
+ rgbBkColor.rgbBlue = (BYTE)image_background->blue;
+ rgbBkColor.rgbReserved = 0;
+ }
+
+ // unlike the example in the libpng documentation, we have *no* idea where
+ // this file may have come from--so if it doesn't have a file gamma, don't
+ // do any correction ("do no harm")
+
+ double gamma = 0;
+ double screen_gamma = 2.2;
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma) && ( flags & PNG_IGNOREGAMMA ) != PNG_IGNOREGAMMA)
+ png_set_gamma(png_ptr, screen_gamma, gamma);
+
+ // all transformations have been registered; now update info_ptr data
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ // color type may have changed, due to our transformations
+
+ color_type = png_get_color_type(png_ptr,info_ptr);
+
+ // create a DIB and write the bitmap header
+ // set up the DIB palette, if needed
+
+ switch (color_type) {
+ case PNG_COLOR_TYPE_RGB:
+ png_set_invert_alpha(png_ptr);
+
+ if(image_type == FIT_BITMAP) {
+ dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
+ }
+ break;
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ if(image_type == FIT_BITMAP) {
+ dib = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
+ }
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ dib = FreeImage_Allocate(width, height, pixel_depth);
+
+ png_get_PLTE(png_ptr,info_ptr, &png_palette,&palette_entries);
+
+ palette = FreeImage_GetPalette(dib);
+
+ // store the palette
+
+ for (i = 0; i < palette_entries; i++) {
+ palette[i].rgbRed = png_palette[i].red;
+ palette[i].rgbGreen = png_palette[i].green;
+ palette[i].rgbBlue = png_palette[i].blue;
+ }
+
+ // store the transparency table
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ int num_trans = 0;
+ png_bytep trans = NULL;
+ png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
+ FreeImage_SetTransparencyTable(dib, (BYTE *)trans, num_trans);
+ }
+
+ break;
+
+ case PNG_COLOR_TYPE_GRAY:
+ dib = FreeImage_AllocateT(image_type, width, height, pixel_depth);
+
+ if(pixel_depth <= 8) {
+ palette = FreeImage_GetPalette(dib);
+ palette_entries = 1 << pixel_depth;
+
+ for (i = 0; i < palette_entries; i++) {
+ palette[i].rgbRed =
+ palette[i].rgbGreen =
+ palette[i].rgbBlue = (BYTE)((i * 255) / (palette_entries - 1));
+ }
+ }
+
+ // store the transparency table
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ png_color_16p trans_values = NULL;
+ png_get_tRNS(png_ptr, info_ptr, NULL, NULL, &trans_values);
+ if(trans_values) {
+ if (trans_values->gray < palette_entries) {
+ BYTE table[256];
+ memset(table, 0xFF, palette_entries);
+ table[trans_values->gray] = 0;
+ FreeImage_SetTransparencyTable(dib, table, palette_entries);
+ }
+ }
+ }
+
+ break;
+
+ default:
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // store the background color
+ if(image_background) {
+ FreeImage_SetBackgroundColor(dib, &rgbBkColor);
+ }
+
+ // get physical resolution
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
+ png_uint_32 res_x, res_y;
+
+ // we'll overload this var and use 0 to mean no phys data,
+ // since if it's not in meters we can't use it anyway
+
+ int res_unit_type = 0;
+
+ png_get_pHYs(png_ptr,info_ptr,&res_x,&res_y,&res_unit_type);
+
+ if (res_unit_type == 1) {
+ FreeImage_SetDotsPerMeterX(dib, res_x);
+ FreeImage_SetDotsPerMeterY(dib, res_y);
+ }
+ }
+
+ // get possible ICC profile
+
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP)) {
+ png_charp profile_name = NULL;
+ png_charp profile_data = NULL;
+ png_uint_32 profile_length = 0;
+ int compression_type;
+
+ png_get_iCCP(png_ptr, info_ptr, &profile_name, &compression_type, &profile_data, &profile_length);
+
+ // copy ICC profile data (must be done after FreeImage_Allocate)
+
+ FreeImage_CreateICCProfile(dib, profile_data, profile_length);
+ }
+
+
+ // set the individual row_pointers to point at the correct offsets
+
+ row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep));
+
+ if (!row_pointers) {
+ if (palette)
+ png_free(png_ptr, palette);
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ // read in the bitmap bits via the pointer table
+
+ for (png_uint_32 k = 0; k < height; k++)
+ row_pointers[height - 1 - k] = FreeImage_GetScanLine(dib, k);
+
+ png_read_image(png_ptr, row_pointers);
+
+ // check if the bitmap contains transparency, if so enable it in the header
+
+ if (FreeImage_GetBPP(dib) == 32)
+ if (FreeImage_GetColorType(dib) == FIC_RGBALPHA)
+ FreeImage_SetTransparent(dib, TRUE);
+ else
+ FreeImage_SetTransparent(dib, FALSE);
+
+ // cleanup
+
+ if (row_pointers) {
+ free(row_pointers);
+ row_pointers = NULL;
+ }
+
+ // read the rest of the file, getting any additional chunks in info_ptr
+
+ png_read_end(png_ptr, info_ptr);
+
+ // get possible metadata (it can be located both before and after the image data)
+
+ ReadMetadata(png_ptr, info_ptr, dib);
+
+ if (png_ptr) {
+ // clean up after the read, and free any memory allocated - REQUIRED
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ }
+
+ return dib;
+ } catch (const char *text) {
+ if (png_ptr)
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ if (row_pointers)
+ free(row_pointers);
+
+ if (dib)
+ FreeImage_Unload(dib);
+
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_colorp palette = NULL;
+ png_uint_32 width, height;
+ BOOL has_alpha_channel = FALSE;
+
+ RGBQUAD *pal; // pointer to dib palette
+ int bit_depth, pixel_depth; // pixel_depth = bit_depth * channels
+ int palette_entries;
+ int interlace_type;
+
+ fi_ioStructure fio;
+ fio.s_handle = handle;
+ fio.s_io = io;
+
+ if ((dib) && (handle)) {
+ try {
+ // create the chunk manage structure
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, error_handler, warning_handler);
+
+ if (!png_ptr) {
+ return FALSE;
+ }
+
+ // allocate/initialize the image information data.
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (!info_ptr) {
+ png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
+ return FALSE;
+ }
+
+ // Set error handling. REQUIRED if you aren't supplying your own
+ // error handling functions in the png_create_write_struct() call.
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ // if we get here, we had a problem reading the file
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return FALSE;
+ }
+
+ // init the IO
+
+ png_set_write_fn(png_ptr, &fio, _WriteProc, _FlushProc);
+
+ // set physical resolution
+
+ png_uint_32 res_x = (png_uint_32)FreeImage_GetDotsPerMeterX(dib);
+ png_uint_32 res_y = (png_uint_32)FreeImage_GetDotsPerMeterY(dib);
+
+ if ((res_x > 0) && (res_y > 0)) {
+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y, 1);
+ }
+
+ // Set the image information here. Width and height are up to 2^31,
+ // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ pixel_depth = FreeImage_GetBPP(dib);
+
+ BOOL bInterlaced = FALSE;
+ if( (flags & PNG_INTERLACED) == PNG_INTERLACED) {
+ interlace_type = PNG_INTERLACE_ADAM7;
+ bInterlaced = TRUE;
+ } else {
+ interlace_type = PNG_INTERLACE_NONE;
+ }
+
+ // set the ZLIB compression level or default to PNG default compression level (ZLIB level = 6)
+ int zlib_level = flags & 0x0F;
+ if((zlib_level >= 1) && (zlib_level <= 9)) {
+ png_set_compression_level(png_ptr, zlib_level);
+ } else if((flags & PNG_Z_NO_COMPRESSION) == PNG_Z_NO_COMPRESSION) {
+ png_set_compression_level(png_ptr, Z_NO_COMPRESSION);
+ }
+
+ // filtered strategy works better for high color images
+ if(pixel_depth >= 16){
+ png_set_compression_strategy(png_ptr, Z_FILTERED);
+ png_set_filter(png_ptr, 0, PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_PAETH);
+ } else {
+ png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
+ }
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if(image_type == FIT_BITMAP) {
+ // standard image type
+ bit_depth = (pixel_depth > 8) ? 8 : pixel_depth;
+ } else {
+ // 16-bit greyscale or 16-bit RGB(A)
+ bit_depth = 16;
+ }
+
+ switch (FreeImage_GetColorType(dib)) {
+ case FIC_MINISWHITE:
+ // Invert monochrome files to have 0 as black and 1 as white (no break here)
+ png_set_invert_mono(png_ptr);
+
+ case FIC_MINISBLACK:
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+ PNG_COLOR_TYPE_GRAY, interlace_type,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ break;
+
+ case FIC_PALETTE:
+ {
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+ PNG_COLOR_TYPE_PALETTE, interlace_type,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ // set the palette
+
+ palette_entries = 1 << bit_depth;
+ palette = (png_colorp)png_malloc(png_ptr, palette_entries * sizeof (png_color));
+ pal = FreeImage_GetPalette(dib);
+
+ for (int i = 0; i < palette_entries; i++) {
+ palette[i].red = pal[i].rgbRed;
+ palette[i].green = pal[i].rgbGreen;
+ palette[i].blue = pal[i].rgbBlue;
+ }
+
+ png_set_PLTE(png_ptr, info_ptr, palette, palette_entries);
+
+ // You must not free palette here, because png_set_PLTE only makes a link to
+ // the palette that you malloced. Wait until you are about to destroy
+ // the png structure.
+
+ break;
+ }
+
+ case FIC_RGBALPHA :
+ has_alpha_channel = TRUE;
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+ PNG_COLOR_TYPE_RGBA, interlace_type,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // flip BGR pixels to RGB
+ if(image_type == FIT_BITMAP)
+ png_set_bgr(png_ptr);
+#endif
+ break;
+
+ case FIC_RGB:
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+ PNG_COLOR_TYPE_RGB, interlace_type,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ // flip BGR pixels to RGB
+ if(image_type == FIT_BITMAP)
+ png_set_bgr(png_ptr);
+#endif
+ break;
+
+ case FIC_CMYK:
+ break;
+ }
+
+ // write possible ICC profile
+
+ FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
+ if (iccProfile->size && iccProfile->data) {
+ png_set_iCCP(png_ptr, info_ptr, "Embedded Profile", 0, (png_charp)iccProfile->data, iccProfile->size);
+ }
+
+ // write metadata
+
+ WriteMetadata(png_ptr, info_ptr, dib);
+
+ // Optional gamma chunk is strongly suggested if you have any guess
+ // as to the correct gamma of the image.
+ // png_set_gAMA(png_ptr, info_ptr, gamma);
+
+ // set the transparency table
+
+ if ((pixel_depth == 8) && (FreeImage_IsTransparent(dib)) && (FreeImage_GetTransparencyCount(dib) > 0)) {
+ png_set_tRNS(png_ptr, info_ptr, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib), NULL);
+ }
+
+ // set the background color
+
+ if(FreeImage_HasBackgroundColor(dib)) {
+ png_color_16 image_background;
+ RGBQUAD rgbBkColor;
+
+ FreeImage_GetBackgroundColor(dib, &rgbBkColor);
+ memset(&image_background, 0, sizeof(png_color_16));
+ image_background.blue = rgbBkColor.rgbBlue;
+ image_background.green = rgbBkColor.rgbGreen;
+ image_background.red = rgbBkColor.rgbRed;
+ image_background.index = rgbBkColor.rgbReserved;
+
+ png_set_bKGD(png_ptr, info_ptr, &image_background);
+ }
+
+ // Write the file header information.
+
+ png_write_info(png_ptr, info_ptr);
+
+ // write out the image data
+
+#ifndef FREEIMAGE_BIGENDIAN
+ if (bit_depth == 16) {
+ // turn on 16 bit byte swapping
+ png_set_swap(png_ptr);
+ }
+#endif
+
+ int number_passes = 1;
+ if (bInterlaced) {
+ number_passes = png_set_interlace_handling(png_ptr);
+ }
+
+ if ((pixel_depth == 32) && (!has_alpha_channel)) {
+ BYTE *buffer = (BYTE *)malloc(width * 3);
+
+ // transparent conversion to 24-bit
+ // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
+ for (int pass = 0; pass < number_passes; pass++) {
+ for (png_uint_32 k = 0; k < height; k++) {
+ FreeImage_ConvertLine32To24(buffer, FreeImage_GetScanLine(dib, height - k - 1), width);
+ png_write_row(png_ptr, buffer);
+ }
+ }
+ free(buffer);
+ } else {
+ // the number of passes is either 1 for non-interlaced images, or 7 for interlaced images
+ for (int pass = 0; pass < number_passes; pass++) {
+ for (png_uint_32 k = 0; k < height; k++) {
+ png_write_row(png_ptr, FreeImage_GetScanLine(dib, height - k - 1));
+ }
+ }
+ }
+
+ // It is REQUIRED to call this to finish writing the rest of the file
+ // Bug with png_flush
+
+ png_write_end(png_ptr, info_ptr);
+
+ // clean up after the write, and free any memory allocated
+ if (palette) {
+ png_free(png_ptr, palette);
+ }
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return TRUE;
+ } catch (const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPNG(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Source/FreeImage/PluginPNM.cpp b/Source/FreeImage/PluginPNM.cpp
new file mode 100644
index 0000000..4b4096d
--- /dev/null
+++ b/Source/FreeImage/PluginPNM.cpp
@@ -0,0 +1,808 @@
+// ==========================================================
+// PNM (PPM, PGM, PBM) Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+/**
+Get an integer value from the actual position pointed by handle
+*/
+static int
+GetInt(FreeImageIO *io, fi_handle handle) {
+ char c = 0;
+ BOOL firstchar;
+
+ // skip forward to start of next number
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ while (1) {
+ // eat comments
+
+ if (c == '#') {
+ // if we're at a comment, read to end of line
+
+ firstchar = TRUE;
+
+ while (1) {
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ if (firstchar && c == ' ') {
+ // loop off 1 sp after #
+
+ firstchar = FALSE;
+ } else if (c == '\n') {
+ break;
+ }
+ }
+ }
+
+ if (c >= '0' && c <='9') {
+ // we've found what we were looking for
+
+ break;
+ }
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+ }
+
+ // we're at the start of a number, continue until we hit a non-number
+
+ int i = 0;
+
+ while (1) {
+ i = (i * 10) + (c - '0');
+
+ if(!io->read_proc(&c, 1, 1, handle)) throw FI_MSG_ERROR_PARSING;
+
+ if (c < '0' || c > '9')
+ break;
+ }
+
+ return i;
+}
+
+/**
+Read a WORD value taking into account the endianess issue
+*/
+static inline WORD
+ReadWord(FreeImageIO *io, fi_handle handle) {
+ WORD level = 0;
+ io->read_proc(&level, 2, 1, handle);
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapShort(&level); // PNM uses the big endian convention
+#endif
+ return level;
+}
+
+/**
+Write a WORD value taking into account the endianess issue
+*/
+static inline void
+WriteWord(FreeImageIO *io, fi_handle handle, const WORD value) {
+ WORD level = value;
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapShort(&level); // PNM uses the big endian convention
+#endif
+ io->write_proc(&level, 2, 1, handle);
+}
+
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PNM";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Portable Network Media";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "pbm,pgm,ppm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-pnm";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE pbm_id1[] = { 0x50, 0x31 };
+ BYTE pbm_id2[] = { 0x50, 0x34 };
+ BYTE pgm_id1[] = { 0x50, 0x32 };
+ BYTE pgm_id2[] = { 0x50, 0x35 };
+ BYTE ppm_id1[] = { 0x50, 0x33 };
+ BYTE ppm_id2[] = { 0x50, 0x36 };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(pbm_id1), handle);
+
+ if (memcmp(pbm_id1, signature, sizeof(pbm_id1)) == 0)
+ return TRUE;
+
+ if (memcmp(pbm_id2, signature, sizeof(pbm_id2)) == 0)
+ return TRUE;
+
+ if (memcmp(pgm_id1, signature, sizeof(pgm_id1)) == 0)
+ return TRUE;
+
+ if (memcmp(pgm_id2, signature, sizeof(pgm_id2)) == 0)
+ return TRUE;
+
+ if (memcmp(ppm_id1, signature, sizeof(ppm_id1)) == 0)
+ return TRUE;
+
+ if (memcmp(ppm_id2, signature, sizeof(ppm_id2)) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1) ||
+ (depth == 8) ||
+ (depth == 24)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_BITMAP) ||
+ (type == FIT_UINT16) ||
+ (type == FIT_RGB16)
+ );
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ char id_one = 0, id_two = 0;
+ int x, y;
+ FIBITMAP *dib = NULL;
+ RGBQUAD *pal; // pointer to dib palette
+ int i;
+
+ if (!handle)
+ return NULL;
+
+ try {
+ FREE_IMAGE_TYPE image_type = FIT_BITMAP; // standard image: 1-, 8-, 24-bit
+
+ // Read the first two bytes of the file to determine the file format
+ // "P1" = ascii bitmap, "P2" = ascii greymap, "P3" = ascii pixmap,
+ // "P4" = raw bitmap, "P5" = raw greymap, "P6" = raw pixmap
+
+ io->read_proc(&id_one, 1, 1, handle);
+ io->read_proc(&id_two, 1, 1, handle);
+
+ if ((id_one != 'P') || (id_two < '1') || (id_two > '6')) {
+ // signature error
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // Read the header information: width, height and the 'max' value if any
+
+ int width = GetInt(io, handle);
+ int height = GetInt(io, handle);
+ int maxval = 1;
+
+ if((id_two == '2') || (id_two == '5') || (id_two == '3') || (id_two == '6')) {
+ maxval = GetInt(io, handle);
+ if((maxval <= 0) || (maxval > 65535)) {
+ FreeImage_OutputMessageProc(s_format_id, "Invalid max value : %d", maxval);
+ throw (const char*)NULL;
+ }
+ }
+
+ // Create a new DIB
+
+ switch (id_two) {
+ case '1':
+ case '4':
+ // 1-bit
+ dib = FreeImage_Allocate(width, height, 1);
+ break;
+
+ case '2':
+ case '5':
+ if(maxval > 255) {
+ // 16-bit greyscale
+ image_type = FIT_UINT16;
+ dib = FreeImage_AllocateT(image_type, width, height);
+ } else {
+ // 8-bit greyscale
+ dib = FreeImage_Allocate(width, height, 8);
+ }
+ break;
+
+ case '3':
+ case '6':
+ if(maxval > 255) {
+ // 48-bit RGB
+ image_type = FIT_RGB16;
+ dib = FreeImage_AllocateT(image_type, width, height);
+ } else {
+ // 24-bit RGB
+ dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ break;
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // Read the image...
+
+ switch(id_two) {
+ case '1':
+ case '4':
+ // write the palette data
+
+ pal = FreeImage_GetPalette(dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+
+ // write the bitmap data
+
+ if (id_two == '1') { // ASCII bitmap
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ if (GetInt(io, handle) == 0)
+ bits[x >> 3] |= (0x80 >> (x & 0x7));
+ else
+ bits[x >> 3] &= (0xFF7F >> (x & 0x7));
+ }
+ }
+ } else { // Raw bitmap
+ int line = CalculateLine(width, 1);
+
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < line; x++) {
+ io->read_proc(&bits[x], 1, 1, handle);
+
+ bits[x] = ~bits[x];
+ }
+ }
+ }
+
+ return dib;
+
+ case '2':
+ case '5':
+ if(image_type == FIT_BITMAP) {
+ // Build a greyscale palette
+
+ pal = FreeImage_GetPalette(dib);
+
+ for (i = 0; i < 256; i++) {
+ pal[i].rgbRed =
+ pal[i].rgbGreen =
+ pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // write the bitmap data
+
+ if(id_two == '2') { // ASCII greymap
+ int level = 0;
+
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = GetInt(io, handle);
+ bits[x] = (BYTE)((255 * level) / maxval);
+ }
+ }
+ } else { // Raw greymap
+ BYTE level = 0;
+
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ io->read_proc(&level, 1, 1, handle);
+ bits[x] = (BYTE)((255 * (int)level) / maxval);
+ }
+ }
+ }
+ }
+ else if(image_type == FIT_UINT16) {
+ // write the bitmap data
+
+ if(id_two == '2') { // ASCII greymap
+ int level = 0;
+
+ for (y = 0; y < height; y++) {
+ WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = GetInt(io, handle);
+ bits[x] = (WORD)((65535 * (double)level) / maxval);
+ }
+ }
+ } else { // Raw greymap
+ WORD level = 0;
+
+ for (y = 0; y < height; y++) {
+ WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = ReadWord(io, handle);
+ bits[x] = (WORD)((65535 * (double)level) / maxval);
+ }
+ }
+ }
+ }
+
+ return dib;
+
+ case '3':
+ case '6':
+ if(image_type == FIT_BITMAP) {
+ // write the bitmap data
+
+ if (id_two == '3') { // ASCII pixmap
+ int level = 0;
+
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = GetInt(io, handle);
+ bits[FI_RGBA_RED] = (BYTE)((255 * level) / maxval); // R
+ level = GetInt(io, handle);
+ bits[FI_RGBA_GREEN] = (BYTE)((255 * level) / maxval); // G
+ level = GetInt(io, handle);
+ bits[FI_RGBA_BLUE] = (BYTE)((255 * level) / maxval); // B
+
+ bits += 3;
+ }
+ }
+ } else { // Raw pixmap
+ BYTE level = 0;
+
+ for (y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ io->read_proc(&level, 1, 1, handle);
+ bits[FI_RGBA_RED] = (BYTE)((255 * (int)level) / maxval); // R
+
+ io->read_proc(&level, 1, 1, handle);
+ bits[FI_RGBA_GREEN] = (BYTE)((255 * (int)level) / maxval); // G
+
+ io->read_proc(&level, 1, 1, handle);
+ bits[FI_RGBA_BLUE] = (BYTE)((255 * (int)level) / maxval); // B
+
+ bits += 3;
+ }
+ }
+ }
+ }
+ else if(image_type == FIT_RGB16) {
+ // write the bitmap data
+
+ if (id_two == '3') { // ASCII pixmap
+ int level = 0;
+
+ for (y = 0; y < height; y++) {
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = GetInt(io, handle);
+ bits[x].red = (WORD)((65535 * (double)level) / maxval); // R
+ level = GetInt(io, handle);
+ bits[x].green = (WORD)((65535 * (double)level) / maxval); // G
+ level = GetInt(io, handle);
+ bits[x].blue = (WORD)((65535 * (double)level) / maxval); // B
+ }
+ }
+ } else { // Raw pixmap
+ WORD level = 0;
+
+ for (y = 0; y < height; y++) {
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ level = ReadWord(io, handle);
+ bits[x].red = (WORD)((65535 * (double)level) / maxval); // R
+ level = ReadWord(io, handle);
+ bits[x].green = (WORD)((65535 * (double)level) / maxval); // G
+ level = ReadWord(io, handle);
+ bits[x].blue = (WORD)((65535 * (double)level) / maxval); // B
+ }
+ }
+ }
+ }
+
+ return dib;
+ }
+
+ } catch (const char *text) {
+ if(dib) FreeImage_Unload(dib);
+
+ if(NULL != text) {
+ switch(id_two) {
+ case '1':
+ case '4':
+ FreeImage_OutputMessageProc(s_format_id, text);
+ break;
+
+ case '2':
+ case '5':
+ FreeImage_OutputMessageProc(s_format_id, text);
+ break;
+
+ case '3':
+ case '6':
+ FreeImage_OutputMessageProc(s_format_id, text);
+ break;
+ }
+ }
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ // ----------------------------------------------------------
+ // PNM Saving
+ // ----------------------------------------------------------
+ //
+ // Output format :
+ //
+ // Bit depth flags file format
+ // ------------- -------------- -----------
+ // 1-bit / pixel PNM_SAVE_ASCII PBM (P1)
+ // 1-bit / pixel PNM_SAVE_RAW PBM (P4)
+ // 8-bit / pixel PNM_SAVE_ASCII PGM (P2)
+ // 8-bit / pixel PNM_SAVE_RAW PGM (P5)
+ // 24-bit / pixel PNM_SAVE_ASCII PPM (P3)
+ // 24-bit / pixel PNM_SAVE_RAW PPM (P6)
+ // ----------------------------------------------------------
+
+ int x, y;
+
+ char buffer[256]; // temporary buffer whose size should be enough for what we need
+
+ if(!dib || !handle) return FALSE;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ int bpp = FreeImage_GetBPP(dib);
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+
+ // Find the appropriate magic number for this file type
+
+ int magic = 0;
+ int maxval = 255;
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ switch (bpp) {
+ case 1 :
+ magic = 1; // PBM file (B & W)
+ break;
+ case 8 :
+ magic = 2; // PGM file (Greyscale)
+ break;
+
+ case 24 :
+ magic = 3; // PPM file (RGB)
+ break;
+
+ default:
+ return FALSE; // Invalid bit depth
+ }
+ break;
+
+ case FIT_UINT16:
+ magic = 2; // PGM file (Greyscale)
+ maxval = 65535;
+ break;
+
+ case FIT_RGB16:
+ magic = 3; // PPM file (RGB)
+ maxval = 65535;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+
+ if (flags == PNM_SAVE_RAW)
+ magic += 3;
+
+ // Write the header info
+
+ sprintf(buffer, "P%d\n%d %d\n", magic, width, height);
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ if (bpp != 1) {
+ sprintf(buffer, "%d\n", maxval);
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ }
+
+ // Write the image data
+ ///////////////////////
+
+ if(image_type == FIT_BITMAP) {
+ switch(bpp) {
+ case 24 : // 24-bit RGB, 3 bytes per pixel
+ {
+ if (flags == PNM_SAVE_RAW) {
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ io->write_proc(&bits[FI_RGBA_RED], 1, 1, handle); // R
+ io->write_proc(&bits[FI_RGBA_GREEN], 1, 1, handle); // G
+ io->write_proc(&bits[FI_RGBA_BLUE], 1, 1, handle); // B
+
+ bits += 3;
+ }
+ }
+ } else {
+ int length = 0;
+
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ sprintf(buffer, "%3d %3d %3d ", bits[FI_RGBA_RED], bits[FI_RGBA_GREEN], bits[FI_RGBA_BLUE]);
+
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ length += 12;
+
+ if(length > 58) {
+ // No line should be longer than 70 characters
+ sprintf(buffer, "\n");
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ length = 0;
+ }
+
+ bits += 3;
+ }
+ }
+
+ }
+ }
+ break;
+
+ case 8: // 8-bit greyscale
+ {
+ if (flags == PNM_SAVE_RAW) {
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ io->write_proc(&bits[x], 1, 1, handle);
+ }
+ }
+ } else {
+ int length = 0;
+
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ sprintf(buffer, "%3d ", bits[x]);
+
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ length += 4;
+
+ if (length > 66) {
+ // No line should be longer than 70 characters
+ sprintf(buffer, "\n");
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ length = 0;
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case 1: // 1-bit B & W
+ {
+ int color;
+
+ if (flags == PNM_SAVE_RAW) {
+ for(y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for(x = 0; x < (int)FreeImage_GetLine(dib); x++)
+ io->write_proc(&bits[x], 1, 1, handle);
+ }
+ } else {
+ int length = 0;
+
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < (int)FreeImage_GetLine(dib) * 8; x++) {
+ color = (bits[x>>3] & (0x80 >> (x & 0x07))) != 0;
+
+ sprintf(buffer, "%c ", color ? '1':'0');
+
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ length += 2;
+
+ if (length > 68) {
+ // No line should be longer than 70 characters
+ sprintf(buffer, "\n");
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ length = 0;
+ }
+ }
+ }
+ }
+ }
+
+ break;
+ }
+ } // if(FIT_BITMAP)
+
+ else if(image_type == FIT_UINT16) { // 16-bit greyscale
+ if (flags == PNM_SAVE_RAW) {
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ WriteWord(io, handle, bits[x]);
+ }
+ }
+ } else {
+ int length = 0;
+
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ WORD *bits = (WORD*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ sprintf(buffer, "%5d ", bits[x]);
+
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ length += 6;
+
+ if (length > 64) {
+ // No line should be longer than 70 characters
+ sprintf(buffer, "\n");
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ length = 0;
+ }
+ }
+ }
+ }
+ }
+
+ else if(image_type == FIT_RGB16) { // 48-bit RGB
+ if (flags == PNM_SAVE_RAW) {
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ WriteWord(io, handle, bits[x].red); // R
+ WriteWord(io, handle, bits[x].green); // G
+ WriteWord(io, handle, bits[x].blue); // B
+ }
+ }
+ } else {
+ int length = 0;
+
+ for (y = 0; y < height; y++) {
+ // write the scanline to disc
+ FIRGB16 *bits = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < width; x++) {
+ sprintf(buffer, "%5d %5d %5d ", bits[x].red, bits[x].green, bits[x].blue);
+
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+
+ length += 18;
+
+ if(length > 52) {
+ // No line should be longer than 70 characters
+ sprintf(buffer, "\n");
+ io->write_proc(&buffer, (unsigned int)strlen(buffer), 1, handle);
+ length = 0;
+ }
+ }
+ }
+
+ }
+ }
+
+ return TRUE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPNM(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginPSD.cpp b/Source/FreeImage/PluginPSD.cpp
new file mode 100644
index 0000000..e89407d
--- /dev/null
+++ b/Source/FreeImage/PluginPSD.cpp
@@ -0,0 +1,125 @@
+// ==========================================================
+// Photoshop Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// Based on LGPL code created and published by http://sourceforge.net/projects/elynx/
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "PSDParser.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "PSD";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Adobe Photoshop";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "psd";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/psd";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE psd_id[] = { 0x38, 0x42, 0x50, 0x53 };
+ BYTE signature[4] = { 0, 0, 0, 0 };
+
+ io->read_proc(signature, 1, 4, handle);
+
+ if(memcmp(psd_id, signature, 4) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return TRUE;
+}
+
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if(handle) {
+ psdParser parser;
+
+ FIBITMAP *dib = parser.Load(io, handle, s_format_id);
+
+ return dib;
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitPSD(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = NULL;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Source/FreeImage/PluginRAS.cpp b/Source/FreeImage/PluginRAS.cpp
new file mode 100644
index 0000000..49687a7
--- /dev/null
+++ b/Source/FreeImage/PluginRAS.cpp
@@ -0,0 +1,496 @@
+// ==========================================================
+// Sun rasterfile Loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagSUNHEADER {
+ DWORD magic; // Magic number
+ DWORD width; // Image width in pixels
+ DWORD height; // Image height in pixels
+ DWORD depth; // Depth (1, 8, 24 or 32 bits) of each pixel
+ DWORD length; // Image length (in bytes)
+ DWORD type; // Format of file (see RT_* below)
+ DWORD maptype; // Type of colormap (see RMT_* below)
+ DWORD maplength; // Length of colormap (in bytes)
+} SUNHEADER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ----------------------------------------------------------
+
+// Following the header is the colormap, for maplength bytes (unless maplength is zero),
+// then the image. Each row of the image is rounded to 2 bytes.
+
+#define RAS_MAGIC 0x59A66A95 // Magic number for Sun rasterfiles
+
+// Sun supported type's
+
+#define RT_OLD 0 // Old format (raw image in 68000 byte order)
+#define RT_STANDARD 1 // Raw image in 68000 byte order
+#define RT_BYTE_ENCODED 2 // Run-length encoding of bytes
+#define RT_FORMAT_RGB 3 // XRGB or RGB instead of XBGR or BGR
+#define RT_FORMAT_TIFF 4 // TIFF <-> standard rasterfile
+#define RT_FORMAT_IFF 5 // IFF (TAAC format) <-> standard rasterfile
+
+#define RT_EXPERIMENTAL 0xffff // Reserved for testing
+
+// These are the possible colormap types.
+// if it's in RGB format, the map is made up of three byte arrays
+// (red, green, then blue) that are each 1/3 of the colormap length.
+
+#define RMT_NONE 0 // maplength is expected to be 0
+#define RMT_EQUAL_RGB 1 // red[maplength/3], green[maplength/3], blue[maplength/3]
+#define RMT_RAW 2 // Raw colormap
+#define RESC 128 // Run-length encoding escape character
+
+// ----- NOTES -----
+// Each line of the image is rounded out to a multiple of 16 bits.
+// This corresponds to the rounding convention used by the memory pixrect
+// package (/usr/include/pixrect/memvar.h) of the SunWindows system.
+// The ras_encoding field (always set to 0 by Sun's supported software)
+// was renamed to ras_length in release 2.0. As a result, rasterfiles
+// of type 0 generated by the old software claim to have 0 length; for
+// compatibility, code reading rasterfiles must be prepared to compute the
+// TRUE length from the width, height, and depth fields.
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static void
+ReadData(FreeImageIO *io, fi_handle handle, BYTE *buf, DWORD length, BOOL rle) {
+ // Read either Run-Length Encoded or normal image data
+
+ static BYTE repchar, remaining= 0;
+
+ if (rle) {
+ // Run-length encoded read
+
+ while(length--) {
+ if (remaining) {
+ remaining--;
+ *(buf++)= repchar;
+ } else {
+ io->read_proc(&repchar, 1, 1, handle);
+
+ if (repchar == RESC) {
+ io->read_proc(&remaining, 1, 1, handle);
+
+ if (remaining == 0) {
+ *(buf++)= RESC;
+ } else {
+ io->read_proc(&repchar, 1, 1, handle);
+
+ *(buf++)= repchar;
+ }
+ } else {
+ *(buf++)= repchar;
+ }
+ }
+ }
+ } else {
+ // Normal read
+
+ io->read_proc(buf, length, 1, handle);
+ }
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "RAS";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Sun Raster Image";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "ras";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-cmu-raster";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE ras_signature[] = { 0x59, 0xA6, 0x6A, 0x95 };
+ BYTE signature[4] = { 0, 0, 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(ras_signature), handle);
+
+ return (memcmp(ras_signature, signature, sizeof(ras_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ SUNHEADER header; // Sun file header
+ WORD linelength; // Length of raster line in bytes
+ WORD fill; // Number of fill bytes per raster line
+ BOOL rle; // TRUE if RLE file
+ BOOL isRGB; // TRUE if file type is RT_FORMAT_RGB
+ BYTE fillchar;
+
+ FIBITMAP *dib = NULL;
+ BYTE *bits; // Pointer to dib data
+ WORD x, y;
+
+ if (handle) {
+ try {
+ // Read SUN raster header
+
+ io->read_proc(&header, sizeof(SUNHEADER), 1, handle);
+
+#ifndef FREEIMAGE_BIGENDIAN
+ // SUN rasterfiles are big endian only
+
+ SwapLong(&header.magic);
+ SwapLong(&header.width);
+ SwapLong(&header.height);
+ SwapLong(&header.depth);
+ SwapLong(&header.length);
+ SwapLong(&header.type);
+ SwapLong(&header.maptype);
+ SwapLong(&header.maplength);
+#endif
+
+ // Verify SUN identifier
+
+ if (header.magic != RAS_MAGIC) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // Allocate a new DIB
+
+ switch(header.depth) {
+ case 1:
+ case 8:
+ dib = FreeImage_Allocate(header.width, header.height, header.depth);
+ break;
+
+ case 24:
+ dib = FreeImage_Allocate(header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ break;
+
+ case 32:
+ dib = FreeImage_Allocate(header.width, header.height, header.depth, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ break;
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // Check the file format
+
+ rle = FALSE;
+ isRGB = FALSE;
+
+ switch(header.type) {
+ case RT_OLD:
+ case RT_STANDARD:
+ case RT_FORMAT_TIFF: // I don't even know what these format are...
+ case RT_FORMAT_IFF: //The TIFF and IFF format types indicate that the raster
+ //file was originally converted from either of these file formats.
+ //so lets at least try to process them as RT_STANDARD
+ break;
+
+ case RT_BYTE_ENCODED:
+ rle = TRUE;
+ break;
+
+ case RT_FORMAT_RGB:
+ isRGB = TRUE;
+ break;
+
+ default:
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // set up the colormap if needed
+
+ switch(header.maptype) {
+ case RMT_NONE :
+ {
+ if (header.depth < 24) {
+ // Create linear color ramp
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ int numcolors = 1 << header.depth;
+
+ for (int i = 0; i < numcolors; i++) {
+ pal[i].rgbRed = (BYTE)((255 * i) / (numcolors - 1));
+ pal[i].rgbGreen = (BYTE)((255 * i) / (numcolors - 1));
+ pal[i].rgbBlue = (BYTE)((255 * i) / (numcolors - 1));
+ }
+ }
+
+ break;
+ }
+
+ case RMT_EQUAL_RGB:
+ {
+ BYTE *r, *g, *b;
+
+ // Read SUN raster colormap
+
+ int numcolors = 1 << header.depth;
+ if((DWORD)(3 * numcolors) > header.maplength) {
+ // some RAS may have less colors than the full palette
+ numcolors = header.maplength / 3;
+ } else {
+ throw "Invalid palette";
+ }
+
+ r = (BYTE*)malloc(3 * numcolors * sizeof(BYTE));
+ g = r + numcolors;
+ b = g + numcolors;
+
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ io->read_proc(r, 3 * numcolors, 1, handle);
+
+ for (int i = 0; i < numcolors; i++) {
+ pal[i].rgbRed = r[i];
+ pal[i].rgbGreen = g[i];
+ pal[i].rgbBlue = b[i];
+ }
+
+ free(r);
+ break;
+ }
+
+ case RMT_RAW:
+ {
+ BYTE *colormap;
+
+ // Read (skip) SUN raster colormap.
+
+ colormap = (BYTE *)malloc(header.maplength * sizeof(BYTE));
+
+ io->read_proc(colormap, header.maplength, 1, handle);
+
+ free(colormap);
+ break;
+ }
+ }
+
+ // Calculate the line + pitch
+ // Each row is multiple of 16 bits (2 bytes).
+
+ if (header.depth == 1)
+ linelength = (WORD)((header.width / 8) + (header.width % 8 ? 1 : 0));
+ else
+ linelength = (WORD)header.width;
+
+ fill = (linelength % 2) ? 1 : 0;
+
+ int pitch = FreeImage_GetPitch(dib);
+
+ // Read the image data
+
+ switch(header.depth) {
+ case 1:
+ case 8:
+ {
+ bits = FreeImage_GetBits(dib) + (header.height - 1) * pitch;
+
+ for (y = 0; y < header.height; y++) {
+ ReadData(io, handle, bits, linelength, rle);
+
+ bits -= pitch;
+
+ if (fill)
+ ReadData(io, handle, &fillchar, fill, rle);
+ }
+
+ break;
+ }
+
+ case 24:
+ {
+ BYTE *buf, *bp;
+
+ buf = (BYTE*)malloc(header.width * 3);
+
+ for (y = 0; y < header.height; y++) {
+ bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch;
+
+ ReadData(io, handle, buf, header.width * 3, rle);
+
+ bp = buf;
+
+ if (isRGB) {
+ for (x = 0; x < header.width; x++) {
+ bits[FI_RGBA_RED] = *(bp++); // red
+ bits[FI_RGBA_GREEN] = *(bp++); // green
+ bits[FI_RGBA_BLUE] = *(bp++); // blue
+
+ bits += 3;
+ }
+ } else {
+ for (x = 0; x < header.width; x++) {
+ bits[FI_RGBA_RED] = *(bp + 2); // red
+ bits[FI_RGBA_GREEN] = *(bp + 1);// green
+ bits[FI_RGBA_BLUE] = *bp; // blue
+
+ bits += 3; bp += 3;
+ }
+ }
+
+ if (fill)
+ ReadData(io, handle, &fillchar, fill, rle);
+ }
+
+ free(buf);
+ break;
+ }
+
+ case 32:
+ {
+ BYTE *buf, *bp;
+
+ buf = (BYTE*)malloc(header.width * 4);
+
+ for (y = 0; y < header.height; y++) {
+ bits = FreeImage_GetBits(dib) + (header.height - 1 - y) * pitch;
+
+ ReadData(io, handle, buf, header.width * 4, rle);
+
+ bp = buf;
+
+ if (isRGB) {
+ for (x = 0; x < header.width; x++) {
+ bits[FI_RGBA_ALPHA] = *(bp++); // alpha
+ bits[FI_RGBA_RED] = *(bp++); // red
+ bits[FI_RGBA_GREEN] = *(bp++); // green
+ bits[FI_RGBA_BLUE] = *(bp++); // blue
+
+ bits += 4;
+ }
+ }
+ else {
+ for (x = 0; x < header.width; x++) {
+ bits[FI_RGBA_RED] = *(bp + 3); // red
+ bits[FI_RGBA_GREEN] = *(bp + 2); // green
+ bits[FI_RGBA_BLUE] = *(bp + 1); // blue
+ bits[FI_RGBA_ALPHA] = *bp; // alpha
+
+ bits += 4;
+ bp += 4;
+ }
+ }
+
+ if (fill)
+ ReadData(io, handle, &fillchar, fill, rle);
+ }
+
+ free(buf);
+ break;
+ }
+ }
+
+ return dib;
+
+ } catch (const char *text) {
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitRAS(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginRAW.cpp b/Source/FreeImage/PluginRAW.cpp
new file mode 100644
index 0000000..7e0aad1
--- /dev/null
+++ b/Source/FreeImage/PluginRAW.cpp
@@ -0,0 +1,490 @@
+// ==========================================================
+// RAW camera image loader
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../Metadata/FreeImageTag.h"
+
+#include "../LibRawLite/libraw/libraw.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+// ----------------------------------------------------------
+// FreeImage datastream wrapper
+// ----------------------------------------------------------
+
+class LibRaw_freeimage_datastream : public LibRaw_abstract_datastream {
+private:
+ FreeImageIO *_io;
+ fi_handle _handle;
+ long _eof;
+
+public:
+ LibRaw_freeimage_datastream(FreeImageIO *io, fi_handle handle) : _io(io), _handle(handle) {
+ long start_pos = io->tell_proc(handle);
+ io->seek_proc(handle, 0, SEEK_END);
+ _eof = io->tell_proc(handle);
+ io->seek_proc(handle, start_pos, SEEK_SET);
+ }
+ ~LibRaw_freeimage_datastream() {
+ }
+ virtual int valid() {
+ return (_io && _handle);
+ }
+ virtual int read(void *buffer, size_t size, size_t count) {
+ if(substream) return substream->read(buffer, size, count);
+ return _io->read_proc(buffer, (unsigned)size, (unsigned)count, _handle);
+ }
+ virtual int eof() {
+ if(substream) return substream->eof();
+ return (_io->tell_proc(_handle) >= _eof);
+ }
+ virtual int seek(off_t offset, int origin) {
+ if(substream) return substream->seek(offset, origin);
+ return _io->seek_proc(_handle, offset, origin);
+ }
+ virtual int tell() {
+ if(substream) return substream->tell();
+ return _io->tell_proc(_handle);
+ }
+ virtual int get_char() {
+ int c = 0;
+ if(substream) return substream->get_char();
+ if(!_io->read_proc(&c, 1, 1, _handle)) return -1;
+ return c;
+ }
+ virtual char* gets(char *buffer, int length) {
+ if (substream) return substream->gets(buffer, length);
+ memset(buffer, 0, length);
+ for(int i = 0; i < length; i++) {
+ if(!_io->read_proc(&buffer[i], 1, 1, _handle))
+ return NULL;
+ if(buffer[i] == 0x0A)
+ break;
+ }
+ return buffer;
+ }
+ virtual int scanf_one(const char *fmt, void* val) {
+ std::string buffer;
+ char element = 0;
+ bool bDone = false;
+ if(substream) return substream->scanf_one(fmt,val);
+ do {
+ if(_io->read_proc(&element, 1, 1, _handle) == 1) {
+ switch(element) {
+ case '0':
+ case '\n':
+ case ' ':
+ case '\t':
+ bDone = true;
+ break;
+ default:
+ break;
+ }
+ buffer.append(&element, 1);
+ } else {
+ return 0;
+ }
+ } while(!bDone);
+
+ return sscanf(buffer.c_str(), fmt, val);
+ }
+};
+
+// ----------------------------------------------------------
+
+/**
+Convert a processed raw data array to a FIBITMAP
+@param image Processed raw image
+@return Returns the converted dib if successfull, returns NULL otherwise
+*/
+static FIBITMAP *
+libraw_ConvertToDib(libraw_processed_image_t *image) {
+ FIBITMAP *dib = NULL;
+ try {
+ unsigned width = image->width;
+ unsigned height = image->height;
+ unsigned bpp = image->bits;
+ if(bpp == 16) {
+ // allocate output dib
+ dib = FreeImage_AllocateT(FIT_RGB16, width, height);
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+ // write data
+ unsigned short *raw_data = (unsigned short*)image->data;
+ for(unsigned y = 0; y < height; y++) {
+ FIRGB16 *output = (FIRGB16*)FreeImage_GetScanLine(dib, height - 1 - y);
+ for(unsigned x = 0; x < width; x++) {
+ output[x].red = raw_data[0];
+ output[x].green = raw_data[1];
+ output[x].blue = raw_data[2];
+ raw_data += 3;
+ }
+ }
+ } else if(bpp == 8) {
+ // allocate output dib
+ dib = FreeImage_AllocateT(FIT_BITMAP, width, height, 24);
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+ // write data
+ BYTE *raw_data = (BYTE*)image->data;
+ for(unsigned y = 0; y < height; y++) {
+ RGBTRIPLE *output = (RGBTRIPLE*)FreeImage_GetScanLine(dib, height - 1 - y);
+ for(unsigned x = 0; x < width; x++) {
+ output[x].rgbtRed = raw_data[0];
+ output[x].rgbtGreen = raw_data[1];
+ output[x].rgbtBlue = raw_data[2];
+ raw_data += 3;
+ }
+ }
+ }
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+
+ return dib;
+}
+
+/**
+Get the embedded JPEG preview image from RAW picture with included Exif Data.
+@param RawProcessor Libraw handle
+@return Returns the loaded dib if successfull, returns NULL otherwise
+*/
+static FIBITMAP *
+libraw_LoadEmbeddedPreview(LibRaw& RawProcessor) {
+ FIBITMAP *dib = NULL;
+ libraw_processed_image_t *thumb_image = NULL;
+
+ try {
+ // unpack data
+ if(RawProcessor.unpack_thumb() != LIBRAW_SUCCESS) {
+ throw (char*)NULL; // run silently "LibRaw : failed to run unpack_thumb"
+ }
+
+ // retrieve thumb image
+ int error_code = 0;
+ thumb_image = RawProcessor.dcraw_make_mem_thumb(&error_code);
+ if(thumb_image) {
+ if(thumb_image->type != LIBRAW_IMAGE_BITMAP) {
+ int flags = 0;
+ // attach the binary data to a memory stream
+ FIMEMORY *hmem = FreeImage_OpenMemory((BYTE*)thumb_image->data, (DWORD)thumb_image->data_size);
+ // get the file type
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
+ if(fif == FIF_JPEG) {
+ // rotate according to Exif orientation
+ flags |= JPEG_EXIFROTATE;
+ }
+ // load an image from the memory stream
+ dib = FreeImage_LoadFromMemory(fif, hmem, flags);
+ // close the stream
+ FreeImage_CloseMemory(hmem);
+ } else {
+ // convert processed data to output dib
+ dib = libraw_ConvertToDib(thumb_image);
+ }
+ } else {
+ throw "LibRaw : failed to run dcraw_make_mem_thumb";
+ }
+
+ // clean-up and return
+ free(thumb_image);
+
+ return dib;
+
+ } catch(const char *text) {
+ // clean-up and return
+ if(thumb_image) {
+ free(thumb_image);
+ }
+ if(text != NULL) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+ }
+
+ return NULL;
+}
+/**
+Load raw data and convert to FIBITMAP
+@param RawProcessor Libraw handle
+@param bitspersample Output bitdepth (8- or 16-bit)
+@return Returns the loaded dib if successfull, returns NULL otherwise
+*/
+static FIBITMAP *
+libraw_LoadRawData(LibRaw& RawProcessor, int bitspersample) {
+ FIBITMAP *dib = NULL;
+ libraw_processed_image_t *processed_image = NULL;
+
+ try {
+ // set decoding parameters
+ // -----------------------
+
+ // (-4) Linear 16-bit or 8-bit
+ RawProcessor.imgdata.params.output_bps = bitspersample;
+ // (-w) Use camera white balance, if possible
+ RawProcessor.imgdata.params.use_camera_wb = 1;
+ // (-a) Average the whole image for white balance
+ RawProcessor.imgdata.params.use_auto_wb = 1;
+ // (-q 3) Adaptive homogeneity-directed demosaicing algorithm (AHD)
+ RawProcessor.imgdata.params.user_qual = 3;
+
+ // -----------------------
+
+ // unpack data
+ if(RawProcessor.unpack() != LIBRAW_SUCCESS) {
+ throw "LibRaw : failed to unpack data";
+ }
+
+ // process data (... most consuming task ...)
+ if(RawProcessor.dcraw_process() != LIBRAW_SUCCESS) {
+ throw "LibRaw : failed to process data";
+ }
+
+ // retrieve processed image
+ int error_code = 0;
+ processed_image = RawProcessor.dcraw_make_mem_image(&error_code);
+ if(processed_image) {
+ // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check
+ if(processed_image->type != LIBRAW_IMAGE_BITMAP) {
+ throw "invalid image type";
+ }
+ // only 3-color images supported...
+ if(processed_image->colors != 3) {
+ throw "only 3-color images supported";
+ }
+ } else {
+ throw "LibRaw : failed to run dcraw_make_mem_image";
+ }
+
+ // convert processed data to output dib
+ dib = libraw_ConvertToDib(processed_image);
+
+ // clean-up and return
+ free(processed_image);
+
+ return dib;
+
+ } catch(const char *text) {
+ // clean-up and return
+ if(processed_image) {
+ free(processed_image);
+ }
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "RAW";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "RAW camera image";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ static const char *raw_extensions =
+ "bay," // Casio Digital Camera Raw File Format.
+ "bmq," // NuCore Raw Image File.
+ "cr2," // Canon Digital Camera RAW Image Format version 2.0. These images are based on the TIFF image standard.
+ "crw," // Canon Digital Camera RAW Image Format version 1.0.
+ "cs1," // Capture Shop Raw Image File.
+ "dc2," // Kodak DC25 Digital Camera File.
+ "dcr," // Kodak Digital Camera Raw Image Format for these models: Kodak DSC Pro SLR/c, Kodak DSC Pro SLR/n, Kodak DSC Pro 14N, Kodak DSC PRO 14nx.
+ "dng," // Adobe Digital Negative: DNG is publicly available archival format for the raw files generated by digital cameras. By addressing the lack of an open standard for the raw files created by individual camera models, DNG helps ensure that photographers will be able to access their files in the future.
+ "erf," // Epson Digital Camera Raw Image Format.
+ "fff," // Imacon Digital Camera Raw Image Format.
+ "hdr," // Leaf Raw Image File.
+ "k25," // Kodak DC25 Digital Camera Raw Image Format.
+ "kdc," // Kodak Digital Camera Raw Image Format.
+ "mdc," // Minolta RD175 Digital Camera Raw Image Format.
+ "mos," // Mamiya Digital Camera Raw Image Format.
+ "mrw," // Minolta Dimage Digital Camera Raw Image Format.
+ "nef," // Nikon Digital Camera Raw Image Format.
+ "orf," // Olympus Digital Camera Raw Image Format.
+ "pef," // Pentax Digital Camera Raw Image Format.
+ "pxn," // Logitech Digital Camera Raw Image Format.
+ "raf," // Fuji Digital Camera Raw Image Format.
+ "raw," // Panasonic Digital Camera Image Format.
+ "rdc," // Digital Foto Maker Raw Image File.
+ "sr2," // Sony Digital Camera Raw Image Format.
+ "srf," // Sony Digital Camera Raw Image Format for DSC-F828 8 megapixel digital camera or Sony DSC-R1
+// "x3f," // Sigma Digital Camera Raw Image Format for devices based on Foveon X3 direct image sensor.
+ "arw," // Sony Digital Camera Raw Image Format for Alpha devices.
+ "3fr," // Hasselblad Digital Camera Raw Image Format.
+ "cine," // Phantom Software Raw Image File.
+ "ia," // Sinar Raw Image File.
+ "kc2," // Kodak DCS200 Digital Camera Raw Image Format.
+ "mef," // Mamiya Digital Camera Raw Image Format.
+ "nrw," // Nikon Digital Camera Raw Image Format.
+ "qtk," // Apple Quicktake 100/150 Digital Camera Raw Image Format.
+ "rw2," // Panasonic LX3 Digital Camera Raw Image Format.
+ "sti," // Sinar Capture Shop Raw Image File.
+ "drf," // Kodak Digital Camera Raw Image Format.
+ "dsc," // Kodak Digital Camera Raw Image Format.
+ "ptx," // Pentax Digital Camera Raw Image Format.
+ "cap," // Phase One Digital Camera Raw Image Format.
+ "iiq," // Phase One Digital Camera Raw Image Format.
+ "rwz"; // Rawzor Digital Camera Raw Image Format.
+ return raw_extensions;
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-raw";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ LibRaw RawProcessor;
+
+ try {
+ // wrap the input datastream
+ LibRaw_freeimage_datastream datastream(io, handle);
+
+ // open the datastream
+ if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
+ throw(1); // LibRaw : failed to open input stream (unknown format)
+ }
+
+ // clean-up internal memory allocations
+ RawProcessor.recycle();
+
+ return TRUE;
+
+ } catch(int) {
+ // clean-up and return
+ RawProcessor.recycle();
+ }
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ FIBITMAP *dib = NULL;
+ LibRaw RawProcessor;
+
+ try {
+ // wrap the input datastream
+ LibRaw_freeimage_datastream datastream(io, handle);
+
+ // open the datastream
+ if(RawProcessor.open_datastream(&datastream) != LIBRAW_SUCCESS) {
+ throw "LibRaw : failed to open input stream (unknown format)";
+ }
+
+ if((flags & RAW_PREVIEW) == RAW_PREVIEW) {
+ // try to get the embedded JPEG
+ dib = libraw_LoadEmbeddedPreview(RawProcessor);
+ if(!dib) {
+ // no JPEG preview: try to load as 8-bit
+ dib = libraw_LoadRawData(RawProcessor, 8);
+ }
+ } else if((flags & RAW_DISPLAY) == RAW_DISPLAY) {
+ // load raw data as RGB 24-bit
+ dib = libraw_LoadRawData(RawProcessor, 8);
+ } else {
+ // default: load raw data as linear 16-bit
+ dib = libraw_LoadRawData(RawProcessor, 16);
+ }
+
+ // save ICC profile if present
+ if(NULL != RawProcessor.imgdata.color.profile) {
+ FreeImage_CreateICCProfile(dib, RawProcessor.imgdata.color.profile, RawProcessor.imgdata.color.profile_length);
+ }
+
+ // clean-up internal memory allocations
+ RawProcessor.recycle();
+
+ return dib;
+
+ } catch(const char *text) {
+ if(dib) {
+ FreeImage_Unload(dib);
+ }
+ RawProcessor.recycle();
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitRAW(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginSGI.cpp b/Source/FreeImage/PluginSGI.cpp
new file mode 100644
index 0000000..9b61cb8
--- /dev/null
+++ b/Source/FreeImage/PluginSGI.cpp
@@ -0,0 +1,425 @@
+// ==========================================================
+// SGI Loader
+//
+// Design and implementation by
+// - Sherman Wilcox
+// - Noam Gat
+//
+// References :
+// ------------
+// - The SGI Image File Format, Version 1.0
+// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
+// - SGI RGB Image Format
+// http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/
+//
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagSGIHeader {
+ /** IRIS image file magic number. This should be decimal 474. */
+ WORD magic;
+ /** Storage format: 0 for uncompressed, 1 for RLE compression. */
+ BYTE storage;
+ /** Number of bytes per pixel channel. Legally 1 or 2. */
+ BYTE bpc;
+ /**
+ Number of dimensions. Legally 1, 2, or 3.
+ 1 means a single row, XSIZE long
+ 2 means a single 2D image
+ 3 means multiple 2D images
+ */
+ WORD dimension;
+ /** X size in pixels */
+ WORD xsize;
+ /** Y size in pixels */
+ WORD ysize;
+ /**
+ Number of channels.
+ 1 indicates greyscale
+ 3 indicates RGB
+ 4 indicates RGB and Alpha
+ */
+ WORD zsize;
+ /** Minimum pixel value. This is the lowest pixel value in the image.*/
+ LONG pixmin;
+ /** Maximum pixel value. This is the highest pixel value in the image.*/
+ LONG pixmax;
+ /** Ignored. Normally set to 0. */
+ char dummy[4];
+ /** Image name. Must be null terminated, therefore at most 79 bytes. */
+ char imagename[80];
+ /**
+ Colormap ID.
+ 0 - normal mode
+ 1 - dithered, 3 mits for red and green, 2 for blue, obsolete
+ 2 - index colour, obsolete
+ 3 - not an image but a colourmap
+ */
+ LONG colormap;
+ /** Ignored. Should be set to 0, makes the header 512 bytes. */
+ char reserved[404];
+} SGIHeader;
+
+typedef struct tagRLEStatus {
+ int cnt;
+ int val;
+} RLEStatus;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+static const char *SGI_LESS_THAN_HEADER_LENGTH = "Incorrect header size";
+static const char *SGI_16_BIT_COMPONENTS_NOT_SUPPORTED = "No 16 bit support";
+static const char *SGI_COLORMAPS_NOT_SUPPORTED = "No colormap support";
+static const char *SGI_EOF_IN_RLE_INDEX = "EOF in run length encoding";
+static const char *SGI_EOF_IN_IMAGE_DATA = "EOF in image data";
+static const char *SGI_INVALID_CHANNEL_COUNT = "Invalid channel count";
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+#ifndef FREEIMAGE_BIGENDIAN
+static void
+SwapHeader(SGIHeader *header) {
+ SwapShort(&header->magic);
+ SwapShort(&header->dimension);
+ SwapShort(&header->xsize);
+ SwapShort(&header->ysize);
+ SwapShort(&header->zsize);
+ SwapLong((DWORD*)&header->pixmin);
+ SwapLong((DWORD*)&header->pixmax);
+ SwapLong((DWORD*)&header->colormap);
+}
+#endif
+
+static int
+get_rlechar(FreeImageIO *io, fi_handle handle, RLEStatus *pstatus) {
+ if (!pstatus->cnt) {
+ int cnt = 0;
+ while (0 == cnt) {
+ BYTE packed = 0;
+ if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
+ return EOF;
+ }
+ cnt = packed;
+ }
+ if (cnt == EOF) {
+ return EOF;
+ }
+ pstatus->cnt = cnt & 0x7F;
+ if (cnt & 0x80) {
+ pstatus->val = -1;
+ } else {
+ BYTE packed = 0;
+ if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
+ return EOF;
+ }
+ pstatus->val = packed;
+ }
+ }
+ pstatus->cnt--;
+ if (pstatus->val == -1) {
+ BYTE packed = 0;
+ if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
+ return EOF;
+ }
+ return packed;
+ }
+ else {
+ return pstatus->val;
+ }
+}
+
+static const char * DLL_CALLCONV
+Format() {
+ return "SGI";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "SGI Image Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "sgi";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/sgi";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE sgi_signature[2] = { 0x01, 0xDA };
+ BYTE signature[2] = { 0, 0 };
+
+ io->read_proc(signature, 1, sizeof(sgi_signature), handle);
+
+ return (memcmp(sgi_signature, signature, sizeof(sgi_signature)) == 0);
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ int width = 0, height = 0, zsize = 0;
+ int i, dim;
+ int bitcount;
+ SGIHeader sgiHeader;
+ RLEStatus my_rle_status;
+ FIBITMAP *dib = NULL;
+ LONG *pRowIndex = NULL;
+
+ try {
+ // read the header
+ memset(&sgiHeader, 0, sizeof(SGIHeader));
+ if(io->read_proc(&sgiHeader, 1, sizeof(SGIHeader), handle) < sizeof(SGIHeader)) {
+ throw SGI_LESS_THAN_HEADER_LENGTH;
+ }
+#ifndef FREEIMAGE_BIGENDIAN
+ SwapHeader(&sgiHeader);
+#endif
+ if(sgiHeader.magic != 474) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ BOOL bIsRLE = (sgiHeader.storage == 1) ? TRUE : FALSE;
+
+ // check for unsupported image types
+ if (sgiHeader.bpc != 1) {
+ // Expected one byte per color component
+ throw SGI_16_BIT_COMPONENTS_NOT_SUPPORTED;
+ }
+ if (sgiHeader.colormap != 0) {
+ // Indexed or dithered images not supported
+ throw SGI_COLORMAPS_NOT_SUPPORTED;
+ }
+
+ // get the width & height
+ dim = sgiHeader.dimension;
+ width = sgiHeader.xsize;
+ if (dim < 3) {
+ zsize = 1;
+ } else {
+ zsize = sgiHeader.zsize;
+ }
+
+ if (dim < 2) {
+ height = 1;
+ } else {
+ height = sgiHeader.ysize;
+ }
+
+ if(bIsRLE) {
+ // read the Offset Tables
+ int index_len = height * zsize;
+ pRowIndex = (LONG*)malloc(index_len * sizeof(LONG));
+ if(!pRowIndex) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ if ((unsigned)index_len != io->read_proc(pRowIndex, sizeof(LONG), index_len, handle)) {
+ throw SGI_EOF_IN_RLE_INDEX;
+ }
+
+#ifndef FREEIMAGE_BIGENDIAN
+ // Fix byte order in index
+ for (i = 0; i < index_len; i++) {
+ SwapLong((DWORD*)&pRowIndex[i]);
+ }
+#endif
+ // Discard row size index
+ for (i = 0; i < (int)(index_len * sizeof(LONG)); i++) {
+ BYTE packed = 0;
+ if( io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1 ) {
+ throw SGI_EOF_IN_RLE_INDEX;
+ }
+ }
+ }
+
+ switch(zsize) {
+ case 1:
+ bitcount = 8;
+ break;
+ case 2:
+ //Grayscale+Alpha. Need to fake RGBA
+ bitcount = 32;
+ break;
+ case 3:
+ bitcount = 24;
+ break;
+ case 4:
+ bitcount = 32;
+ break;
+ default:
+ throw SGI_INVALID_CHANNEL_COUNT;
+ }
+
+ dib = FreeImage_Allocate(width, height, bitcount);
+ if(!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ if (bitcount == 8) {
+ // 8-bit SGI files are grayscale images, so we'll generate
+ // a grayscale palette.
+ RGBQUAD *pclrs = FreeImage_GetPalette(dib);
+ for (i = 0; i < 256; i++) {
+ pclrs[i].rgbRed = (BYTE)i;
+ pclrs[i].rgbGreen = (BYTE)i;
+ pclrs[i].rgbBlue = (BYTE)i;
+ pclrs[i].rgbReserved = 0;
+ }
+ }
+
+ // decode the image
+
+ memset(&my_rle_status, 0, sizeof(RLEStatus));
+
+ int ns = FreeImage_GetPitch(dib);
+ BYTE *pStartRow = FreeImage_GetScanLine(dib, 0);
+ int offset_table[] = { 2, 1, 0, 3 };
+ int numChannels = zsize;
+ if (zsize < 3) {
+ offset_table[0] = 0;
+ }
+ if (zsize == 2)
+ {
+ //This is how faked grayscale+alpha works.
+ //First channel goes into first
+ //second channel goes into alpha (4th channel)
+ //Two channels are left empty and will be copied later
+ offset_table[1] = 3;
+ numChannels = 4;
+ }
+
+ LONG *pri = pRowIndex;
+ for (i = 0; i < zsize; i++) {
+ BYTE *pRow = pStartRow + offset_table[i];
+ for (int j = 0; j < height; j++, pRow += ns, pri++) {
+ BYTE *p = pRow;
+ if (bIsRLE) {
+ my_rle_status.cnt = 0;
+ io->seek_proc(handle, *pri, SEEK_SET);
+ }
+ for (int k = 0; k < width; k++, p += numChannels) {
+ int ch;
+ BYTE packed = 0;
+ if (bIsRLE) {
+ ch = get_rlechar(io, handle, &my_rle_status);
+ packed = (BYTE)ch;
+ }
+ else {
+ ch = io->read_proc(&packed, sizeof(BYTE), 1, handle);
+ }
+ if (ch == EOF) {
+ throw SGI_EOF_IN_IMAGE_DATA;
+ }
+ *p = packed;
+ }
+ }
+ }
+
+ if (zsize == 2)
+ {
+ BYTE *pRow = pStartRow;
+ //If faking RGBA from grayscale + alpha, copy first channel to second and third
+ for (int i=0; i<height; i++, pRow += ns)
+ {
+ BYTE *pPixel = pRow;
+ for (int j=0; j<width; j++)
+ {
+ pPixel[2] = pPixel[1] = pPixel[0];
+ pPixel += 4;
+ }
+ }
+ }
+ if(pRowIndex)
+ free(pRowIndex);
+
+ return dib;
+
+ } catch(const char *text) {
+ if(pRowIndex) free(pRowIndex);
+ if(dib) FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
+ }
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitSGI(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
+
diff --git a/Source/FreeImage/PluginTARGA.cpp b/Source/FreeImage/PluginTARGA.cpp
new file mode 100644
index 0000000..5075330
--- /dev/null
+++ b/Source/FreeImage/PluginTARGA.cpp
@@ -0,0 +1,1204 @@
+// ==========================================================
+// TARGA Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Jani Kajala (janik@remedy.fi)
+// - Martin Weber (martweb@gmx.net)
+// - Machiel ten Brinke (brinkem@uni-one.nl)
+// - Peter Lemmens (peter.lemmens@planetinternet.be)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagTGAHEADER {
+ BYTE id_length; // ID length
+ BYTE color_map_type; // color map type
+ BYTE image_type; // image type
+
+ WORD cm_first_entry; // first entry index
+ WORD cm_length; // color map length
+ BYTE cm_size; // color map entry size, in bits
+
+ WORD is_xorigin; // X-origin of image
+ WORD is_yorigin; // Y-origin of image
+ WORD is_width; // image width
+ WORD is_height; // image height
+ BYTE is_pixel_depth; // pixel depth
+ BYTE is_image_descriptor; // image descriptor
+} TGAHEADER;
+
+typedef struct tagTGAFOOTER {
+ DWORD extension_offset; // extension area offset
+ DWORD developer_offset; // developer directory offset
+ char signature[18]; // signature string
+} TGAFOOTER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// ----------------------------------------------------------
+// Image type
+//
+#define TGA_NULL 0 // no image data included
+#define TGA_CMAP 1 // uncompressed, color-mapped image
+#define TGA_RGB 2 // uncompressed, true-color image
+#define TGA_MONO 3 // uncompressed, black-and-white image
+#define TGA_RLECMAP 9 // run-length encoded, color-mapped image
+#define TGA_RLERGB 10 // run-length encoded, true-color image
+#define TGA_RLEMONO 11 // run-length encoded, black-and-white image
+#define TGA_CMPCMAP 32 // compressed (Huffman/Delta/RLE) color-mapped image (e.g., VDA/D) - Obsolete
+#define TGA_CMPCMAP4 33 // compressed (Huffman/Delta/RLE) color-mapped four pass image (e.g., VDA/D) - Obsolete
+
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+/**
+This struct is used only when loading RLE compressed images.
+It is needed because it is (really) hard to determine the size of a
+compressed line in the file (and allocate line cache as usual, refilling it at line change).
+We use an arbitrary size instead and access it through this struct, it takes care to refill when needed.
+NOTE: access must be *fast*, so safety measures are minimal.
+*/
+typedef struct tagCacheIO {
+ BYTE *ptr;
+ BYTE *home;
+ BYTE *end;
+ size_t size;
+ FreeImageIO *io; // not necessary, but
+ fi_handle handle; // passing them as args is slower
+} CacheIO;
+
+/**
+Returns TRUE on success and FAlSE if malloc fails
+Note however that I do not use this returned value in the code.
+Allocating line cache even for a 100 000 wide 32bit bitmap will take under
+half a megabyte. Out of Mem is really not an issue!
+*/
+static BOOL
+cacheIO_alloc(CacheIO *ch, FreeImageIO *io, fi_handle handle, size_t size) {
+ ch->home = NULL;
+ ch->home = (BYTE*)malloc(size);
+ if(ch->home == NULL) {
+ return FALSE;
+ }
+ ch->end = ch->home + size;
+ ch->size = size;
+ ch->io = io;
+ ch->handle = handle;
+ ch->ptr = ch->end; //will force refill on first access
+
+ return TRUE;
+}
+
+static void
+cacheIO_free(CacheIO *ch) {
+ if(ch->home != NULL) {
+ free(ch->home);
+ }
+}
+
+inline static BYTE
+cacheIO_getByte(CacheIO *ch) {
+ if(ch->ptr >= ch->end) {
+ ch->ptr = ch->home;
+ ch->io->read_proc(ch->ptr, sizeof(BYTE), (unsigned)ch->size, ch->handle);//### EOF - no problem?
+ }
+ BYTE result = *ch->ptr;
+ ch->ptr++;
+
+ return result;
+}
+
+inline static BYTE*
+cacheIO_getBytes(CacheIO *ch, size_t count /*must be < ch.size!*/) {
+ if(ch->ptr + count >= ch->end) {
+ // 'count' bytes might span two cache bounds, SEEK back to add them in the new cache
+ long read = (long)(ch->ptr - ch->home);
+ ch->io->seek_proc(ch->handle, -(((long)ch->size - read)), SEEK_CUR);
+ ch->ptr = ch->home;
+ ch->io->read_proc(ch->ptr, sizeof(BYTE), (unsigned)ch->size, ch->handle);//### EOF - no problem?
+ }
+ BYTE *result = ch->ptr;
+ ch->ptr += count;
+
+ return result;
+}
+
+static BYTE *
+Internal_GetScanLine(FIBITMAP *dib, int scanline, int flipvert) {
+ //assert ((scanline >= 0) && (scanline < (int)FreeImage_GetHeight(dib)));
+
+ if (flipvert) {
+ return FreeImage_GetScanLine(dib, scanline);
+ } else {
+ return FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - scanline - 1);
+ }
+}
+
+#ifdef FREEIMAGE_BIGENDIAN
+static void
+SwapHeader(TGAHEADER *header) {
+ SwapShort(&header->cm_first_entry);
+ SwapShort(&header->cm_length);
+ SwapShort(&header->is_xorigin);
+ SwapShort(&header->is_yorigin);
+ SwapShort(&header->is_width);
+ SwapShort(&header->is_height);
+}
+
+static void
+SwapFooter(TGAFOOTER *footer) {
+ SwapLong(&footer->extension_offset);
+ SwapLong(&footer->developer_offset);
+}
+#endif
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "TARGA";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Truevision Targa";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "tga,targa";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/freeimage-tga";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ TGAHEADER header;
+ char extra[256]; // 256 temporary bytes (only 255 will be used though)
+
+ // try to read the header in a whole
+ if(io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle) != 1)
+ return FALSE;
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+
+ // The Color Map Type should be a 0 or a 1...
+ // NOTE: are other values possible?
+ // NO, according to http://cvs.sf.net/viewcvs.py/eifogl/eifogl/utility/tga/tga_file.e?rev=1.3
+ // and it seems that the current Targa implementation for FreeImage
+ // assumes that anything other than 0 means that there is a Color Map
+ if(header.color_map_type != 0 && header.color_map_type != 1) {
+ return FALSE;
+ }
+
+ // If the Color Map Type is 1 then we validate the map entry information...
+ // NOTA: let's stay compatible with the current FreeImage Targa implementation
+ // and check against Type 0 instead against Type 1
+ if(header.color_map_type != 0) {
+ // It doesn't make any sense if the first entry is larger than the Color Map Table
+ if(header.cm_first_entry >= header.cm_length)
+ return FALSE;
+
+ // NOTE : maybe we should check header.cm_size for known values?
+ // for now, don't allow 0 or anything bigger than 32
+ if(header.cm_size <= 0 || header.cm_size > 32)
+ return FALSE;
+ }
+ else {
+ // I have disabled this because I'm not really sure
+ // but can one assume that if there is no Color Map
+ // than all 3 related values are zeroed?
+ // NOTE: atleast in my test files that seems to be the case...
+ /*
+ if(header.cm_first_entry != 0 || header.cm_length != 0 || header.cm_size != 0)
+ return FALSE;
+ */
+ }
+
+ // the width/height shouldn't be 0, right?
+ if(header.is_width == 0 || header.is_height == 0) {
+ return FALSE;
+ }
+
+ // the extra data (following after the header) should be there
+ if(io->read_proc(extra, 1, header.id_length, handle) != header.id_length)
+ return FALSE;
+
+ // let's now verify all the types that are supported by FreeImage
+ // NOTE : this is our final verification
+ switch(header.is_pixel_depth) {
+ case 8:
+ switch(header.image_type) {
+ case TGA_CMAP:
+ case TGA_MONO:
+ case TGA_RLECMAP:
+ case TGA_RLEMONO: return TRUE;
+ }
+ break;
+ case 15:
+ case 16:
+ case 24:
+ case 32:
+ switch(header.image_type) {
+ case TGA_RGB:
+ case TGA_RLERGB: return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 8) ||
+ (depth == 16) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if (handle) {
+ try {
+ // remember the start offset
+ long start_offset = io->tell_proc(handle);
+
+ // remember end-of-file (used for RLE cache)
+ io->seek_proc(handle, 0, SEEK_END);
+ long eof = io->tell_proc(handle);
+ io->seek_proc(handle, start_offset, SEEK_SET );
+
+ // read and process the bitmap's header
+
+ FIBITMAP *dib = NULL;
+ TGAHEADER header;
+
+ io->read_proc(&header, sizeof(tagTGAHEADER), 1, handle);
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+
+ int line = CalculateLine(header.is_width, header.is_pixel_depth);
+ int pitch = CalculatePitch(line);
+ // It seems this ALWAYS is: 8 for 32bit, 1 for 16bit, 0 for 24bit
+ int alphabits = header.is_image_descriptor & 0x0f;
+ int fliphoriz = (header.is_image_descriptor & 0x10) ? 0 : 1; //currently FreeImage improperly treats this as flipvert also
+ int flipvert = (header.is_image_descriptor & 0x20) ? 1 : 0;
+
+ // skip comment
+ io->seek_proc(handle, header.id_length, SEEK_CUR);
+
+ switch (header.is_pixel_depth) {
+ case 8 :
+ {
+ dib = FreeImage_Allocate(header.is_width, header.is_height, 8);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // read the palette
+
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+
+ if (header.color_map_type == 0) {
+ // no color-map data is included with this image ...
+ // build a greyscale palette
+ for (unsigned i = 0; i < 256; i++) {
+ palette[i].rgbRed = (BYTE)i;
+ palette[i].rgbGreen = (BYTE)i;
+ palette[i].rgbBlue = (BYTE)i;
+ }
+ }
+ else {
+ unsigned count, csize;
+
+ // calculate the color map size
+ csize = header.cm_length * header.cm_size / 8;
+ BYTE *cmap = (BYTE*)malloc(csize * sizeof(BYTE));
+
+ io->read_proc(cmap, sizeof(BYTE), csize, handle);
+
+ // build the palette
+ switch(header.cm_size) {
+ case 16:
+ {
+ WORD *rgb555 = (WORD*)&cmap[0];
+ for (count = header.cm_first_entry; count < header.cm_length; count++) {
+ palette[count].rgbRed = (BYTE)((((*rgb555 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ palette[count].rgbGreen = (BYTE)((((*rgb555 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ palette[count].rgbBlue = (BYTE)((((*rgb555 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ rgb555++;
+ }
+ }
+ break;
+
+ case 24:
+ {
+ FILE_BGR *bgr = (FILE_BGR*)&cmap[0];
+ for (count = header.cm_first_entry; count < header.cm_length; count++) {
+ palette[count].rgbBlue = bgr->b;
+ palette[count].rgbGreen = bgr->g;
+ palette[count].rgbRed = bgr->r;
+ bgr++;
+ }
+ }
+ break;
+
+ case 32:
+ {
+ BYTE trns[256];
+
+ // clear the transparency table
+ memset(trns, 0xFF, 256);
+
+ FILE_BGRA *bgra = (FILE_BGRA*)&cmap[0];
+ for (count = header.cm_first_entry; count < header.cm_length; count++) {
+ palette[count].rgbBlue = bgra->b;
+ palette[count].rgbGreen = bgra->g;
+ palette[count].rgbRed = bgra->r;
+ // alpha
+ trns[count] = bgra->a;
+ bgra++;
+ }
+
+ // set the tranparency table
+ FreeImage_SetTransparencyTable(dib, trns, 256);
+ }
+ break;
+ }
+
+ free(cmap);
+ }
+
+ // read in the bitmap bits
+
+ switch (header.image_type) {
+ case TGA_CMAP:
+ case TGA_MONO:
+ {
+ BYTE *bits = NULL;
+
+ if (fliphoriz) {
+ for (unsigned count = 0; count < header.is_height; count++) {
+ bits = Internal_GetScanLine(dib, header.is_height - count - 1, flipvert);
+ io->read_proc(bits, sizeof(BYTE), line, handle);
+ }
+ }
+ else {
+ for (unsigned count = 0; count < header.is_height; count++) {
+ bits = Internal_GetScanLine(dib, count, flipvert);
+ io->read_proc(bits, sizeof(BYTE), line, handle);
+ }
+ }
+
+ break;
+ }
+
+ case TGA_RLECMAP:
+ case TGA_RLEMONO: //(8 bit)
+ {
+ BYTE rle = 0;
+ BYTE *bits;
+
+ // Compute the *rough* size of a line...
+ long pixels_offset = io->tell_proc(handle);
+ long sz = ((eof - pixels_offset) / header.is_height);
+
+ // ...and allocate cache of this size (yields best results)
+ CacheIO cache;
+ cacheIO_alloc(&cache, io, handle, sz);
+
+ int y = 0, x = 0;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+
+ while(y < header.is_height) {
+
+ rle = cacheIO_getByte(&cache);
+
+ BOOL has_rle = rle & 0x80;
+ rle &= ~0x80; // remove type-bit
+
+ BYTE rle_count = rle + 1;
+
+ if (has_rle) {
+
+ BYTE val = cacheIO_getByte(&cache);
+
+ for(int ix = 0; ix < rle_count; ix++) {
+ bits[x++] = val;
+
+ if(x >= line){
+ x = 0;
+ y++;
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+ }
+
+ } else { // !has_rle
+
+ for(int ix = 0; ix < rle_count; ix++) {
+
+ BYTE val = cacheIO_getByte(&cache);
+ bits[x++] = val;
+ if(x >= line){
+ x=0;
+ y++;
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+ }//< rle_count
+ }//< has_rle
+ }//< while y
+
+ cacheIO_free(&cache);
+ break;
+ }
+
+ default :
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ break;
+ }
+
+ case 15 :
+ case 16 :
+ {
+ int pixel_bits;
+
+ // allocate the dib
+
+ if (TARGA_LOAD_RGB888 & flags) {
+ pixel_bits = 24;
+ dib = FreeImage_Allocate(header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ pixel_bits = 16;
+ dib = FreeImage_Allocate(header.is_width, header.is_height, pixel_bits, FI16_555_RED_MASK, FI16_555_GREEN_MASK, FI16_555_BLUE_MASK);
+ }
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ int line = CalculateLine(header.is_width, pixel_bits);
+
+ const unsigned pixel_size = unsigned(pixel_bits) / 8;
+
+ // note header.cm_size is a misleading name, it should be seen as header.cm_bits
+ // ignore current position in file and set filepointer explicitly from the beginning of the file
+
+ int garblen = 0;
+
+ if (header.color_map_type != 0) {
+ garblen = (int)((header.cm_size + 7) / 8) * header.cm_length; /* should byte align */
+ } else {
+ garblen = 0;
+ }
+
+ io->seek_proc(handle, start_offset, SEEK_SET);
+ io->seek_proc(handle, sizeof(tagTGAHEADER) + header.id_length + garblen, SEEK_SET);
+
+ // read in the bitmap bits
+
+ switch (header.image_type) {
+ case TGA_RGB: //(16 bit)
+ {
+ // in(put)_line cache
+ WORD *in_line = (WORD*)malloc(header.is_width * sizeof(WORD));
+ if(!in_line) throw FI_MSG_ERROR_MEMORY;
+
+ const int h = header.is_height;
+ for (int y = 0; y < h; y++) {
+ BYTE *bits;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, h - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ io->read_proc(in_line, sizeof(WORD), header.is_width, handle);
+
+ WORD *pixel = in_line;
+ for (int x = 0; x < line; x += pixel_size) {
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(pixel);
+#endif
+
+ if (TARGA_LOAD_RGB888 & flags) {
+ bits[x + FI_RGBA_BLUE] = (BYTE)((((*pixel & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_GREEN] = (BYTE)((((*pixel & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_RED] = (BYTE)((((*pixel & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ } else {
+ *reinterpret_cast<WORD*>(bits + x) = 0x7FFF & *pixel;
+ }
+ pixel++;
+ }
+ }
+
+ free(in_line);
+ break;
+ }
+
+ case TGA_RLERGB: //(16 bit)
+ {
+ BYTE rle;
+ BYTE *bits;
+
+ // Compute the *rough* size of a line...
+ long pixels_offset = io->tell_proc(handle);
+ long sz = ((eof - pixels_offset) / header.is_height);
+
+ // ...and allocate cache of this size (yields best results)
+ CacheIO cache;
+ cacheIO_alloc(&cache, io, handle, sz);
+
+ int y = 0, x = 0;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+
+ while( y < header.is_height) {
+ rle = cacheIO_getByte(&cache);
+
+ BOOL has_rle = rle & 0x80;
+ rle &= ~0x80; //remove type-bit
+
+ int rle_count = rle + 1;
+
+ if (has_rle) {
+
+ WORD *val = (WORD*)cacheIO_getBytes(&cache, sizeof(WORD));
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(val);
+#endif
+ for (int ix = 0; ix < rle_count; ix++) {
+ if (TARGA_LOAD_RGB888 & flags) {
+ bits[x + FI_RGBA_BLUE] = (BYTE)((((*val & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_GREEN] = (BYTE)((((*val & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_RED] = (BYTE)((((*val & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ } else {
+ *reinterpret_cast<WORD *>(bits + x) = 0x7FFF & *val;
+ }
+
+ x += pixel_size;
+
+ if(x >= line){
+ x = 0;
+ y++;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+ }
+
+ } else {
+
+ for (int ix = 0; ix < rle_count; ix++) {
+ WORD *val = (WORD*)cacheIO_getBytes(&cache, sizeof(WORD));
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(val);
+#endif
+
+ if (TARGA_LOAD_RGB888 & flags) {
+ bits[x + FI_RGBA_BLUE] = (BYTE)((((*val & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_GREEN] = (BYTE)((((*val & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) * 0xFF) / 0x1F);
+ bits[x + FI_RGBA_RED] = (BYTE)((((*val & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) * 0xFF) / 0x1F);
+ } else {
+ *reinterpret_cast<WORD *>(bits + x) = 0x7FFF & *val;
+ }
+
+ x += pixel_size;
+
+ if(x >= line){
+ x = 0;
+ y++;
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+
+ }//< rle_count
+ }//< has_rle
+ }//< while
+
+ cacheIO_free(&cache);
+ break;
+ }
+
+ default :
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ break;
+ }
+
+ case 24 :
+ {
+ dib = FreeImage_Allocate(header.is_width, header.is_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // read in the bitmap bits
+
+ switch (header.image_type) {
+ case TGA_RGB://(24 bit)
+ {
+ FILE_BGR* bgr_line = (FILE_BGR*)malloc(header.is_width * sizeof(FILE_BGR));
+ if(!bgr_line) throw FI_MSG_ERROR_MEMORY;
+
+ if (fliphoriz) {
+ for (unsigned count = header.is_height; count > 0; count--) {
+ BYTE *bits = Internal_GetScanLine(dib, count-1, flipvert);
+ io->read_proc(bgr_line, sizeof(FILE_BGR), header.is_width, handle);
+
+ FILE_BGR *bgr = bgr_line;
+ for (int x = 0; x < line; x += 3) {
+ bits[x + FI_RGBA_BLUE] = bgr->b;
+ bits[x + FI_RGBA_GREEN] = bgr->g;
+ bits[x + FI_RGBA_RED] = bgr->r;
+ bgr++;
+ }
+ }
+
+ } else {
+ for (unsigned count = 0; count < header.is_height; count++) {
+ BYTE *bits = Internal_GetScanLine(dib, count, flipvert);
+ io->read_proc(bgr_line, sizeof(FILE_BGR), header.is_width, handle);
+
+ FILE_BGR *bgr = bgr_line;
+ for (int x = 0; x < line; x += 3) {
+ bits[x + FI_RGBA_BLUE] = bgr->b;
+ bits[x + FI_RGBA_GREEN] = bgr->g;
+ bits[x + FI_RGBA_RED] = bgr->r;
+ bgr++;
+ }
+ }
+ }
+
+ free(bgr_line);
+ break;
+ }
+
+ case TGA_RLERGB://(24 bit)
+ {
+
+ BYTE rle;
+ BYTE *bits;
+
+ // Compute the *rough* size of a line...
+ long pixels_offset = io->tell_proc(handle);
+ long sz = ((eof - pixels_offset) / header.is_height);
+
+ // ...and allocate cache of this size (yields best results)
+ CacheIO cache;
+ cacheIO_alloc(&cache, io, handle, sz);
+
+ int x = 0, y = 0;
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+
+ while( y < header.is_height) {
+ rle = cacheIO_getByte(&cache);
+
+ BOOL has_rle = rle & 0x80;
+ rle &= ~0x80; //remove type-bit
+
+ BYTE rle_count = rle + 1;
+
+ if (has_rle) {
+
+ FILE_BGR *val = (FILE_BGR*)cacheIO_getBytes(&cache, sizeof(FILE_BGR));
+
+ for (int ix = 0; ix < rle_count; ix++) {
+ bits[x + FI_RGBA_BLUE] = val->b;
+ bits[x + FI_RGBA_GREEN] = val->g;
+ bits[x + FI_RGBA_RED] = val->r;
+
+ x += 3;
+
+ if(x >= line){
+ x = 0;
+ y++;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+ }//<rle_count
+ } else { //<!has_rle
+
+ for (int ix = 0; ix < rle_count; ix++) {
+ FILE_BGR *val = (FILE_BGR*)cacheIO_getBytes(&cache, sizeof(FILE_BGR));
+
+ bits[x + FI_RGBA_BLUE] = val->b;
+ bits[x + FI_RGBA_GREEN] = val->g;
+ bits[x + FI_RGBA_RED] = val->r;
+
+ x += 3;
+
+ if(x >= line){
+ x = 0;
+ y++;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+
+ }//< rle_count
+ }//< has_rle
+ }//< while
+
+ cacheIO_free(&cache);
+ break;
+ }
+
+ default :
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ break;
+ }
+
+ case 32 :
+ {
+ int pixel_bits;
+
+ if (TARGA_LOAD_RGB888 & flags) {
+ pixel_bits = 24;
+ } else {
+ pixel_bits = 32;
+ }
+
+ const unsigned pixel_size = unsigned (pixel_bits) / 8;
+
+ // Allocate the DIB
+ dib = FreeImage_Allocate(header.is_width, header.is_height, pixel_bits, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // read in the bitmap bits
+
+ switch (header.image_type) {
+ case TGA_RGB://(32 bit)
+ {
+ // uncompressed
+
+ // in_line cache
+ FILE_BGRA* in_line = (FILE_BGRA*)malloc(header.is_width * 4);
+ if(!in_line) throw FI_MSG_ERROR_MEMORY;
+
+ const int w = header.is_width; // yes, it does make a (minor) difference
+ const int h = header.is_height; // to move these outside
+
+ for (int y = 0; y < h; y++) {
+ BYTE *bits;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, h - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+
+ io->read_proc(in_line, 4, w, handle);
+
+ FILE_BGRA *bgra = in_line;
+ for (int x = 0; x < w; x++) {
+ bits[FI_RGBA_BLUE] = bgra->b;
+ bits[FI_RGBA_GREEN] = bgra->g;
+ bits[FI_RGBA_RED] = bgra->r;
+
+ if ((TARGA_LOAD_RGB888 & flags) != TARGA_LOAD_RGB888) {
+ bits[FI_RGBA_ALPHA] = bgra->a;
+ }
+
+ bgra++;
+ bits += pixel_size;
+ }
+ }
+
+ free(in_line);
+ break;
+ }
+ case TGA_RLERGB://(32 bit)
+ {
+ BYTE rle;
+ BYTE *bits;
+
+ // Compute the *rough* size of a line...
+ long pixels_offset = io->tell_proc(handle);
+ long sz = ((eof - pixels_offset) / header.is_height);
+
+ // ...and allocate cache of this size (yields best results)
+ CacheIO cache;
+ cacheIO_alloc(&cache, io, handle, sz);
+
+ int x = 0, y = 0;
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+
+ while( y < header.is_height) {
+
+ rle = cacheIO_getByte(&cache);
+
+ BOOL has_rle = rle & 0x80;
+ rle &= ~0x80; // remove type-bit
+
+ BYTE rle_count = rle + 1;
+
+ if (has_rle) {
+
+ FILE_BGRA *val = (FILE_BGRA*)cacheIO_getBytes(&cache, sizeof(FILE_BGRA));
+
+ for (int ix = 0; ix < rle_count; ix++) {
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ *(reinterpret_cast<unsigned*>(bits+x)) = *(reinterpret_cast<unsigned*> (val));
+#else // NOTE This is faster then doing reinterpret_cast + INPLACESWAP for RGB!
+ bits[x + FI_RGBA_BLUE] = val->b;
+ bits[x + FI_RGBA_GREEN] = val->g;
+ bits[x + FI_RGBA_RED] = val->r;
+ bits[x + FI_RGBA_ALPHA] = val->a;
+#endif
+ x += 4;
+
+ if(x >= line) {
+ x = 0;
+ y++;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+ }
+ } else {//<!has_rle
+
+ for (int ix = 0; ix < rle_count; ix++) {
+ FILE_BGRA *val = (FILE_BGRA*)cacheIO_getBytes(&cache, sizeof(FILE_BGRA));
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ *(reinterpret_cast<unsigned*>(bits+x)) = *(reinterpret_cast<unsigned*> (val));
+#else
+ bits[x + FI_RGBA_BLUE] = val->b;
+ bits[x + FI_RGBA_GREEN] = val->g;
+ bits[x + FI_RGBA_RED] = val->r;
+ bits[x + FI_RGBA_ALPHA] = val->a;
+#endif
+ x += 4;
+
+ if(x >= line){
+ x = 0;
+ y++;
+
+ if (fliphoriz) {
+ bits = Internal_GetScanLine(dib, header.is_height - y - 1, flipvert);
+ } else {
+ bits = Internal_GetScanLine(dib, y, flipvert);
+ }
+ }
+
+ }//< rle_count
+ }//< has_rle
+ }//< while y
+
+ cacheIO_free(&cache);
+ break;
+ }
+
+ default :
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ break;
+ }
+ }
+
+ return (FIBITMAP *)dib;
+
+ } catch(const char *message) {
+ FreeImage_OutputMessageProc(s_format_id, message);
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib != NULL) && (handle != NULL)) {
+ RGBQUAD *palette = FreeImage_GetPalette(dib);
+ int bpp = FreeImage_GetBPP(dib);
+
+ // write the file header
+
+ TGAHEADER header;
+ header.id_length = 0;
+ header.cm_first_entry = 0;
+ header.is_xorigin = 0;
+ header.is_yorigin = 0;
+ header.is_width = (WORD)FreeImage_GetWidth(dib);
+ header.is_height = (WORD)FreeImage_GetHeight(dib);
+ header.is_pixel_depth = (BYTE)bpp;
+ header.is_image_descriptor = 0;
+
+ if (palette) {
+ header.color_map_type = 1;
+ header.image_type = TGA_CMAP;
+ header.cm_length = (WORD)(1 << bpp);
+ if(FreeImage_IsTransparent(dib)) {
+ header.cm_size = 32;
+ } else {
+ header.cm_size = 24;
+ }
+ } else {
+ header.color_map_type = 0;
+ header.image_type = TGA_RGB;
+ header.cm_length = 0;
+ header.cm_size = 0;
+ }
+
+ // write the header
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+ io->write_proc(&header, sizeof(header), 1, handle);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapHeader(&header);
+#endif
+
+ // write the palette
+
+ if (palette) {
+ if(FreeImage_IsTransparent(dib)) {
+ FILE_BGRA *bgra_pal = (FILE_BGRA*)malloc(header.cm_length * sizeof(FILE_BGRA));
+
+ // get the transparency table
+ BYTE *trns = FreeImage_GetTransparencyTable(dib);
+
+ for(unsigned i = 0; i < header.cm_length; i++) {
+ bgra_pal[i].b = palette[i].rgbBlue;
+ bgra_pal[i].g = palette[i].rgbGreen;
+ bgra_pal[i].r = palette[i].rgbRed;
+ bgra_pal[i].a = trns[i];
+ }
+
+ io->write_proc(bgra_pal, sizeof(FILE_BGRA), header.cm_length, handle);
+
+ free(bgra_pal);
+
+ } else {
+ FILE_BGR *bgr_pal = (FILE_BGR*)malloc(header.cm_length * sizeof(FILE_BGR));
+
+ for(unsigned i = 0; i < header.cm_length; i++) {
+ bgr_pal[i].b = palette[i].rgbBlue;
+ bgr_pal[i].g = palette[i].rgbGreen;
+ bgr_pal[i].r = palette[i].rgbRed;
+ }
+
+ io->write_proc(bgr_pal, sizeof(FILE_BGR), header.cm_length, handle);
+
+ free(bgr_pal);
+ }
+ }
+
+ // write the data bits
+
+ for (unsigned y = 0; y < header.is_height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ switch(bpp) {
+ case 8:
+ {
+ io->write_proc(bits, header.is_width, 1, handle);
+ break;
+ }
+ case 16:
+ {
+ WORD pixel;
+ for(unsigned x = 0; x < header.is_width; x++) {
+ pixel = *(((WORD *)bits) + x);
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapShort(&pixel);
+#endif
+ io->write_proc(&pixel, sizeof(WORD), 1, handle);
+ }
+ break;
+ }
+ case 24:
+ {
+ FILE_BGR bgr;
+ RGBTRIPLE *trip;
+ for(unsigned x = 0; x < header.is_width; x++) {
+ trip = ((RGBTRIPLE *)bits) + x;
+ bgr.b = trip->rgbtBlue;
+ bgr.g = trip->rgbtGreen;
+ bgr.r = trip->rgbtRed;
+ io->write_proc(&bgr, sizeof(FILE_BGR), 1, handle);
+ }
+ break;
+ }
+ case 32:
+ {
+ FILE_BGRA bgra;
+ RGBQUAD *quad;
+ for(unsigned x = 0; x < header.is_width; x++) {
+ quad = ((RGBQUAD *)bits) + x;
+ bgra.b = quad->rgbBlue;
+ bgra.g = quad->rgbGreen;
+ bgra.r = quad->rgbRed;
+ bgra.a = quad->rgbReserved;
+ io->write_proc(&bgra, sizeof(FILE_BGRA), 1, handle);
+ }
+ break;
+ }
+ }
+ }
+
+ // write the TARGA signature
+
+ TGAFOOTER footer;
+ footer.developer_offset = 0;
+ footer.extension_offset = 0;
+ strcpy(footer.signature, "TRUEVISION-XFILE.");
+
+#ifdef FREEIMAGE_BIGENDIAN
+ SwapFooter(&footer);
+#endif
+ io->write_proc(&footer, sizeof(footer), 1, handle);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitTARGA(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginTIFF.cpp b/Source/FreeImage/PluginTIFF.cpp
new file mode 100644
index 0000000..7babf76
--- /dev/null
+++ b/Source/FreeImage/PluginTIFF.cpp
@@ -0,0 +1,2234 @@
+// ==========================================================
+// TIFF Loader and Writer
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Markus Loibl (markus.loibl@epost.de)
+// - Luca Piergentili (l.pierge@terra.es)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#ifdef unix
+#undef unix
+#endif
+#ifdef __unix
+#undef __unix
+#endif
+
+#include "../LibTIFF/tiffiop.h"
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "../Metadata/FreeImageTag.h"
+
+// ----------------------------------------------------------
+// geotiff interface (see XTIFF.cpp)
+// ----------------------------------------------------------
+
+// Extended TIFF Directory GEO Tag Support
+void XTIFFInitialize();
+
+// GeoTIFF profile
+void tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib);
+void tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib);
+
+// ----------------------------------------------------------
+// exif interface (see XTIFF.cpp)
+// ----------------------------------------------------------
+
+// TIFF Exif profile
+BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib);
+
+// ----------------------------------------------------------
+// LogLuv conversion functions interface (see TIFFLogLuv.cpp)
+// ----------------------------------------------------------
+
+void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels);
+void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels);
+
+// ----------------------------------------------------------
+
+/** Supported loading methods */
+typedef enum {
+ LoadAsRBGA = 0,
+ LoadAsCMYK = 1,
+ LoadAs8BitTrns = 2,
+ LoadAsGenericStrip = 3,
+ LoadAsTiled = 4,
+ LoadAsRGBF = 5
+} TIFFLoadMethod;
+
+// ----------------------------------------------------------
+// local prototypes
+// ----------------------------------------------------------
+
+static tsize_t _tiffReadProc(thandle_t handle, tdata_t buf, tsize_t size);
+static tsize_t _tiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size);
+static toff_t _tiffSeekProc(thandle_t handle, toff_t off, int whence);
+static int _tiffCloseProc(thandle_t fd);
+static int _tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize);
+static void _tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size);
+
+static uint16 CheckColormap(int n, uint16* r, uint16* g, uint16* b);
+static uint16 GetPhotometric(FIBITMAP *dib);
+
+static void ReadResolution(TIFF *tiff, FIBITMAP *dib);
+static void WriteResolution(TIFF *tiff, FIBITMAP *dib);
+
+static void ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib);
+
+static FIBITMAP* CreateImageType(FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel);
+static FREE_IMAGE_TYPE ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel);
+static void WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit);
+
+static void WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags);
+
+static BOOL tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib);
+static BOOL tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib);
+static BOOL tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib);
+static void ReadMetadata(TIFF *tiff, FIBITMAP *dib);
+
+static BOOL tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib);
+static BOOL tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib);
+static void WriteMetadata(TIFF *tiff, FIBITMAP *dib);
+
+static TIFFLoadMethod FindLoadMethod(TIFF *tif, uint16 photometric, uint16 bitspersample, uint16 samplesperpixel, FREE_IMAGE_TYPE image_type, int flags);
+
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+typedef struct {
+ FreeImageIO *io;
+ fi_handle handle;
+ TIFF *tif;
+} fi_TIFFIO;
+
+// ----------------------------------------------------------
+// libtiff interface
+// ----------------------------------------------------------
+
+static tsize_t
+_tiffReadProc(thandle_t handle, tdata_t buf, tsize_t size) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)handle;
+ return fio->io->read_proc(buf, size, 1, fio->handle) * size;
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t handle, tdata_t buf, tsize_t size) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)handle;
+ return fio->io->write_proc(buf, size, 1, fio->handle) * size;
+}
+
+static toff_t
+_tiffSeekProc(thandle_t handle, toff_t off, int whence) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)handle;
+ fio->io->seek_proc(fio->handle, off, whence);
+ return fio->io->tell_proc(fio->handle);
+}
+
+static int
+_tiffCloseProc(thandle_t fd) {
+ return 0;
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t handle) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)handle;
+ long currPos = fio->io->tell_proc(fio->handle);
+ fio->io->seek_proc(fio->handle, 0, SEEK_END);
+ long fileSize = fio->io->tell_proc(fio->handle);
+ fio->io->seek_proc(fio->handle, currPos, SEEK_SET);
+ return fileSize;
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize) {
+ return 0;
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size) {
+}
+
+// ----------------------------------------------------------
+// Open a TIFF file descriptor for read/writing.
+// ----------------------------------------------------------
+
+TIFF *
+TIFFFdOpen(thandle_t handle, const char *name, const char *mode) {
+ TIFF *tif;
+
+ // Set up the callback for extended TIFF directory tag support
+ // (see XTIFF.cpp)
+ XTIFFInitialize();
+
+ // Open the file; the callback will set everything up
+ tif = TIFFClientOpen(name, mode, handle,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+
+ // Warning: tif_fd is declared as 'int' currently (see libTIFF),
+ // may result in incorrect file pointers inside libTIFF on
+ // 64bit machines (sizeof(int) != sizeof(long)).
+ // Needs to be fixed within libTIFF.
+ if (tif)
+ tif->tif_fd = (long)handle;
+
+ return tif;
+}
+
+// ----------------------------------------------------------
+// Open a TIFF file for read/writing.
+// ----------------------------------------------------------
+
+TIFF*
+TIFFOpen(const char* name, const char* mode) {
+ return 0;
+}
+
+// ----------------------------------------------------------
+// TIFF library FreeImage-specific routines.
+// ----------------------------------------------------------
+
+tdata_t
+_TIFFmalloc(tsize_t s) {
+ return malloc(s);
+}
+
+void
+_TIFFfree(tdata_t p) {
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s) {
+ return realloc(p, s);
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c) {
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c) {
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c) {
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+// ----------------------------------------------------------
+// in FreeImage warnings and errors are disabled
+// ----------------------------------------------------------
+
+static void
+msdosWarningHandler(const char* module, const char* fmt, va_list ap) {
+}
+
+TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler;
+
+static void
+msdosErrorHandler(const char* module, const char* fmt, va_list ap) {
+
+ // use this for diagnostic only (do not use otherwise, even in DEBUG mode)
+ /*
+ if (module != NULL) {
+ char msg[1024];
+ vsprintf(msg, fmt, ap);
+ FreeImage_OutputMessageProc(s_format_id, "%s: %s", module, msg);
+ }
+ */
+}
+
+TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler;
+
+// ----------------------------------------------------------
+
+#define CVT(x) (((x) * 255L) / ((1L<<16)-1))
+#define SCALE(x) (((x)*((1L<<16)-1))/255)
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static uint16
+CheckColormap(int n, uint16* r, uint16* g, uint16* b) {
+ while (n-- > 0) {
+ if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256) {
+ return 16;
+ }
+ }
+
+ return 8;
+}
+
+/**
+Get the TIFFTAG_PHOTOMETRIC value from the dib
+*/
+static uint16
+GetPhotometric(FIBITMAP *dib) {
+ FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
+ switch(color_type) {
+ case FIC_MINISWHITE: // min value is white
+ return PHOTOMETRIC_MINISWHITE;
+ case FIC_MINISBLACK: // min value is black
+ return PHOTOMETRIC_MINISBLACK;
+ case FIC_PALETTE: // color map indexed
+ return PHOTOMETRIC_PALETTE;
+ case FIC_RGB: // RGB color model
+ case FIC_RGBALPHA: // RGB color model with alpha channel
+ return PHOTOMETRIC_RGB;
+ case FIC_CMYK: // CMYK color model
+ return PHOTOMETRIC_RGB; // default to RGB unless the save flag is set to TIFF_CMYK
+ default:
+ return PHOTOMETRIC_MINISBLACK;
+ }
+}
+
+/**
+Get the resolution from the TIFF and fill the dib with universal units
+*/
+static void
+ReadResolution(TIFF *tiff, FIBITMAP *dib) {
+ float fResX = 300.0;
+ float fResY = 300.0;
+ uint16 resUnit = RESUNIT_INCH;
+
+ TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit);
+ TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &fResX);
+ TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &fResY);
+
+ // If we don't have a valid resolution unit and valid resolution is specified then assume inch
+ if (resUnit == RESUNIT_NONE && fResX > 0.0 && fResY > 0.0) {
+ resUnit = RESUNIT_INCH;
+ }
+ if (resUnit == RESUNIT_INCH) {
+ FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX/0.0254000 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY/0.0254000 + 0.5));
+ } else if(resUnit == RESUNIT_CENTIMETER) {
+ FreeImage_SetDotsPerMeterX(dib, (unsigned) (fResX*100.0 + 0.5));
+ FreeImage_SetDotsPerMeterY(dib, (unsigned) (fResY*100.0 + 0.5));
+ }
+}
+
+/**
+Set the resolution to the TIFF using english units
+*/
+static void
+WriteResolution(TIFF *tiff, FIBITMAP *dib) {
+ double res;
+
+ TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH);
+
+ res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
+ TIFFSetField(tiff, TIFFTAG_XRESOLUTION, res);
+
+ res = (unsigned long) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
+ TIFFSetField(tiff, TIFFTAG_YRESOLUTION, res);
+}
+
+/**
+Fill the dib palette according to the TIFF photometric
+*/
+static void
+ReadPalette(TIFF *tiff, uint16 photometric, uint16 bitspersample, FIBITMAP *dib) {
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ switch(photometric) {
+ case PHOTOMETRIC_MINISBLACK: // bitmap and greyscale image types
+ case PHOTOMETRIC_MINISWHITE:
+ // Monochrome image
+
+ if (bitspersample == 1) {
+ if (photometric == PHOTOMETRIC_MINISWHITE) {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 255;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 0;
+ } else {
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+ }
+
+ } else if ((bitspersample == 4) ||(bitspersample == 8)) {
+ // need to build the scale for greyscale images
+ int ncolors = FreeImage_GetColorsUsed(dib);
+
+ if (photometric == PHOTOMETRIC_MINISBLACK) {
+ for (int i = 0; i < ncolors; i++) {
+ pal[i].rgbRed =
+ pal[i].rgbGreen =
+ pal[i].rgbBlue = (BYTE)(i*(255/(ncolors-1)));
+ }
+ } else {
+ for (int i = 0; i < ncolors; i++) {
+ pal[i].rgbRed =
+ pal[i].rgbGreen =
+ pal[i].rgbBlue = (BYTE)(255-i*(255/(ncolors-1)));
+ }
+ }
+ }
+
+ break;
+
+ case PHOTOMETRIC_PALETTE: // color map indexed
+ uint16 *red;
+ uint16 *green;
+ uint16 *blue;
+
+ TIFFGetField(tiff, TIFFTAG_COLORMAP, &red, &green, &blue);
+
+ // load the palette in the DIB
+
+ if (CheckColormap(1<<bitspersample, red, green, blue) == 16) {
+ for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
+ pal[i].rgbRed =(BYTE) CVT(red[i]);
+ pal[i].rgbGreen = (BYTE) CVT(green[i]);
+ pal[i].rgbBlue = (BYTE) CVT(blue[i]);
+ }
+ } else {
+ for (int i = (1 << bitspersample) - 1; i >= 0; i--) {
+ pal[i].rgbRed = (BYTE) red[i];
+ pal[i].rgbGreen = (BYTE) green[i];
+ pal[i].rgbBlue = (BYTE) blue[i];
+ }
+ }
+
+ break;
+ }
+}
+
+/**
+Allocate a FIBITMAP
+@param fit Image type
+@param width Image width in pixels
+@param height Image height in pixels
+@param bitspersample # bits per sample
+@param samplesperpixel # samples per pixel
+@return Returns the allocated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+CreateImageType(FREE_IMAGE_TYPE fit, int width, int height, uint16 bitspersample, uint16 samplesperpixel) {
+ FIBITMAP *dib = NULL;
+
+ uint16 bpp = bitspersample * samplesperpixel;
+
+ if(fit == FIT_BITMAP) {
+ // standard bitmap type
+
+ if(bitspersample == 16) {
+ if(samplesperpixel == 1) {
+ // 16-bit greyscale -> convert to 8-bit
+ dib = FreeImage_Allocate(width, height, 8);
+ }
+ else if(samplesperpixel == 3) {
+ // 48-bit RGB -> convert to 24-bit RGB
+ dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ }
+ else if(bpp == 16) {
+ if((samplesperpixel == 2) && (bitspersample == 8)) {
+ // 8-bit indexed + 8-bit alpha channel -> convert to 8-bit transparent
+ dib = FreeImage_Allocate(width, height, 8);
+ } else {
+ // 16-bit RGB -> expect it to be 565
+ dib = FreeImage_Allocate(width, height, bpp, FI16_565_RED_MASK, FI16_565_GREEN_MASK, FI16_565_BLUE_MASK);
+ }
+ }
+ else if(bpp == 24) {
+ // BGR
+ dib = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ else if(bpp == 32) {
+ // BGRA
+ dib = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ else {
+ // anything else <= 8-bit
+ dib = FreeImage_Allocate(width, height, bpp);
+ }
+ } else {
+ // other bitmap types
+
+ dib = FreeImage_AllocateT(fit, width, height, bpp);
+ }
+
+ return dib;
+}
+
+/**
+Read the TIFFTAG_SAMPLEFORMAT tag and convert to FREE_IMAGE_TYPE
+@param tiff LibTIFF TIFF Handle
+@param bitspersample # bit per sample
+@param samplesperpixel # samples per pixel
+@return Returns the image type as a FREE_IMAGE_TYPE value
+*/
+static FREE_IMAGE_TYPE
+ReadImageType(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel) {
+ uint16 sampleformat = 0;
+ FREE_IMAGE_TYPE fit = FIT_BITMAP;
+
+ uint16 bpp = bitspersample * samplesperpixel;
+
+ // try the sampleformat tag
+ if(TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleformat)) {
+
+ switch (sampleformat) {
+ case SAMPLEFORMAT_UINT:
+ switch (bpp) {
+ case 1:
+ case 4:
+ case 8:
+ case 24:
+ fit = FIT_BITMAP;
+ break;
+ case 16:
+ // 8-bit + alpha or 16-bit greyscale
+ if(samplesperpixel == 2) {
+ fit = FIT_BITMAP;
+ } else {
+ fit = FIT_UINT16;
+ }
+ break;
+ case 32:
+ if(samplesperpixel == 4) {
+ fit = FIT_BITMAP;
+ } else {
+ fit = FIT_UINT32;
+ }
+ break;
+ case 48:
+ if(samplesperpixel == 3) {
+ fit = FIT_RGB16;
+ }
+ break;
+ case 64:
+ if(samplesperpixel == 4) {
+ fit = FIT_RGBA16;
+ }
+ break;
+ }
+ break;
+
+ case SAMPLEFORMAT_INT:
+ switch (bpp) {
+ case 16:
+ if(samplesperpixel == 3) {
+ fit = FIT_BITMAP;
+ } else {
+ fit = FIT_INT16;
+ }
+ break;
+ case 32:
+ fit = FIT_INT32;
+ break;
+ }
+ break;
+
+ case SAMPLEFORMAT_IEEEFP:
+ switch (bpp) {
+ case 32:
+ fit = FIT_FLOAT;
+ break;
+ case 64:
+ fit = FIT_DOUBLE;
+ break;
+ case 96:
+ fit = FIT_RGBF;
+ break;
+ }
+ break;
+ case SAMPLEFORMAT_COMPLEXIEEEFP:
+ switch (bpp) {
+ case 64:
+ break;
+ case 128:
+ fit = FIT_COMPLEX;
+ break;
+ }
+ break;
+
+ }
+ }
+ // no sampleformat tag : assume SAMPLEFORMAT_UINT
+ else {
+ if(samplesperpixel == 1) {
+ switch (bpp) {
+ case 16:
+ fit = FIT_UINT16;
+ break;
+
+ case 32:
+ fit = FIT_UINT32;
+ break;
+ }
+ }
+ else if(samplesperpixel == 3) {
+ if(bpp == 48) fit = FIT_RGB16;
+ }
+ else if(samplesperpixel == 4) {
+ if(bpp == 64) fit = FIT_RGBA16;
+ }
+
+ }
+
+ return fit;
+}
+
+/**
+Convert FREE_IMAGE_TYPE and write TIFFTAG_SAMPLEFORMAT
+@param tiff LibTIFF TIFF Handle
+@param fit Image type as a FREE_IMAGE_TYPE value
+*/
+static void
+WriteImageType(TIFF *tiff, FREE_IMAGE_TYPE fit) {
+ switch(fit) {
+ case FIT_BITMAP: // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
+ case FIT_UINT16: // array of unsigned short : unsigned 16-bit
+ case FIT_UINT32: // array of unsigned long : unsigned 32-bit
+ case FIT_RGB16: // 48-bit RGB image : 3 x 16-bit
+ case FIT_RGBA16: // 64-bit RGBA image : 4 x 16-bit
+ TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+ break;
+
+ case FIT_INT16: // array of short : signed 16-bit
+ case FIT_INT32: // array of long : signed 32-bit
+ TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
+ break;
+
+ case FIT_FLOAT: // array of float : 32-bit
+ case FIT_DOUBLE: // array of double : 64-bit
+ case FIT_RGBF: // 96-bit RGB float image : 3 x 32-bit IEEE floating point
+ case FIT_RGBAF: // 128-bit RGBA float image : 4 x 32-bit IEEE floating point
+ TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
+ break;
+
+ case FIT_COMPLEX: // array of COMPLEX : 2 x 64-bit
+ TIFFSetField(tiff, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_COMPLEXIEEEFP);
+ break;
+ }
+}
+
+/**
+Select the compression algorithm
+@param tiff LibTIFF TIFF Handle
+@param
+*/
+static void
+WriteCompression(TIFF *tiff, uint16 bitspersample, uint16 samplesperpixel, uint16 photometric, int flags) {
+ uint16 compression;
+ uint16 bitsperpixel = bitspersample * samplesperpixel;
+
+ if(photometric == PHOTOMETRIC_LOGLUV) {
+ compression = COMPRESSION_SGILOG;
+ } else if ((flags & TIFF_PACKBITS) == TIFF_PACKBITS) {
+ compression = COMPRESSION_PACKBITS;
+ } else if ((flags & TIFF_DEFLATE) == TIFF_DEFLATE) {
+ compression = COMPRESSION_DEFLATE;
+ } else if ((flags & TIFF_ADOBE_DEFLATE) == TIFF_ADOBE_DEFLATE) {
+ compression = COMPRESSION_ADOBE_DEFLATE;
+ } else if ((flags & TIFF_NONE) == TIFF_NONE) {
+ compression = COMPRESSION_NONE;
+ } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX3) == TIFF_CCITTFAX3)) {
+ compression = COMPRESSION_CCITTFAX3;
+ } else if ((bitsperpixel == 1) && ((flags & TIFF_CCITTFAX4) == TIFF_CCITTFAX4)) {
+ compression = COMPRESSION_CCITTFAX4;
+ } else if ((flags & TIFF_LZW) == TIFF_LZW) {
+ compression = COMPRESSION_LZW;
+ } else if ((flags & TIFF_JPEG) == TIFF_JPEG) {
+ if(((bitsperpixel == 8) && (photometric != PHOTOMETRIC_PALETTE)) || (bitsperpixel == 24)) {
+ compression = COMPRESSION_JPEG;
+ // RowsPerStrip must be multiple of 8 for JPEG
+ uint32 rowsperstrip = (uint32) -1;
+ rowsperstrip = TIFFDefaultStripSize(tiff, rowsperstrip);
+ rowsperstrip = rowsperstrip + (8 - (rowsperstrip % 8));
+ // overwrite previous RowsPerStrip
+ TIFFSetField(tiff, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+ } else {
+ // default to LZW
+ compression = COMPRESSION_LZW;
+ }
+ }
+ else {
+ // default compression scheme
+
+ switch(bitsperpixel) {
+ case 1 :
+ compression = COMPRESSION_CCITTFAX4;
+ break;
+
+ case 4 :
+ case 8 :
+ case 16 :
+ case 24 :
+ case 32 :
+ compression = COMPRESSION_LZW;
+ break;
+ case 48:
+ case 64 :
+ case 128:
+ compression = COMPRESSION_LZW;
+ break;
+
+ default :
+ compression = COMPRESSION_NONE;
+ break;
+ }
+ }
+
+ TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression);
+
+ if(compression == COMPRESSION_LZW) {
+ // This option is only meaningful with LZW compression: a predictor value of 2
+ // causes each scanline of the output image to undergo horizontal differencing
+ // before it is encoded; a value of 1 forces each scanline to be encoded without differencing.
+
+ // Found on LibTIFF mailing list :
+ // LZW without differencing works well for 1-bit images, 4-bit grayscale images,
+ // and many palette-color images. But natural 24-bit color images and some 8-bit
+ // grayscale images do much better with differencing.
+
+ if((bitspersample == 8) || (bitspersample == 16)) {
+ if ((bitsperpixel >= 8) && (photometric != PHOTOMETRIC_PALETTE))
+ TIFFSetField(tiff, TIFFTAG_PREDICTOR, 2);
+ else
+ TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1);
+ } else {
+ TIFFSetField(tiff, TIFFTAG_PREDICTOR, 1);
+ }
+ }
+ else if(compression == COMPRESSION_CCITTFAX3) {
+ // try to be compliant with the TIFF Class F specification
+ // that documents the TIFF tags specific to FAX applications
+ // see http://palimpsest.stanford.edu/bytopic/imaging/std/tiff-f.html
+ uint32 group3options = GROUP3OPT_2DENCODING | GROUP3OPT_FILLBITS;
+ TIFFSetField(tiff, TIFFTAG_GROUP3OPTIONS, group3options); // 2d-encoded, has aligned EOL
+ TIFFSetField(tiff, TIFFTAG_FILLORDER, FILLORDER_LSB2MSB); // lsb-to-msb fillorder
+ }
+}
+
+// ==========================================================
+// TIFF metadata routines
+// ==========================================================
+
+/**
+ Read the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile)
+*/
+static BOOL
+tiff_read_iptc_profile(TIFF *tiff, FIBITMAP *dib) {
+ BYTE *profile = NULL;
+ uint32 profile_size = 0;
+
+ if(TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC, &profile_size, &profile) == 1) {
+ if (TIFFIsByteSwapped(tiff) != 0)
+ TIFFSwabArrayOfLong((uint32 *) profile, (unsigned long)profile_size);
+
+ return read_iptc_profile(dib, profile, 4 * profile_size);
+ }
+
+ return FALSE;
+}
+
+/**
+ Read the TIFFTAG_XMLPACKET tag (XMP profile)
+ @param dib Input FIBITMAP
+ @param tiff LibTIFF TIFF handle
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+tiff_read_xmp_profile(TIFF *tiff, FIBITMAP *dib) {
+ BYTE *profile = NULL;
+ uint32 profile_size = 0;
+
+ if (TIFFGetField(tiff, TIFFTAG_XMLPACKET, &profile_size, &profile) == 1) {
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(!tag) return FALSE;
+
+ FreeImage_SetTagID(tag, TIFFTAG_XMLPACKET); // 700
+ FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
+ FreeImage_SetTagLength(tag, profile_size);
+ FreeImage_SetTagCount(tag, profile_size);
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagValue(tag, profile);
+
+ // store the tag
+ FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
+
+ // destroy the tag
+ FreeImage_DeleteTag(tag);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Read the Exif profile embedded in a TIFF
+ @param dib Input FIBITMAP
+ @param tiff LibTIFF TIFF handle
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+tiff_read_exif_profile(TIFF *tiff, FIBITMAP *dib) {
+ uint32 exif_offset = 0;
+
+ // read EXIF-TIFF tags
+ tiff_read_exif_tags(tiff, TagLib::EXIF_MAIN, dib);
+
+ // get the IFD offset
+ if(TIFFGetField(tiff, TIFFTAG_EXIFIFD, &exif_offset)) {
+ // read EXIF tags
+ if(!TIFFReadEXIFDirectory(tiff, exif_offset))
+ return FALSE;
+
+ return tiff_read_exif_tags(tiff, TagLib::EXIF_EXIF, dib);
+ }
+
+ return FALSE;
+}
+
+/**
+Read TIFF special profiles
+*/
+static void
+ReadMetadata(TIFF *tiff, FIBITMAP *dib) {
+
+ // IPTC/NAA
+ tiff_read_iptc_profile(tiff, dib);
+
+ // Adobe XMP
+ tiff_read_xmp_profile(tiff, dib);
+
+ // GeoTIFF
+ tiff_read_geotiff_profile(tiff, dib);
+
+ // Exif-TIFF
+ tiff_read_exif_profile(tiff, dib);
+}
+
+// ----------------------------------------------------------
+
+/**
+ Write the TIFFTAG_RICHTIFFIPTC tag (IPTC/NAA or Adobe Photoshop profile)
+*/
+static BOOL
+tiff_write_iptc_profile(TIFF *tiff, FIBITMAP *dib) {
+ if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
+ BYTE *profile = NULL;
+ uint32 profile_size = 0;
+ // create a binary profile
+ if(write_iptc_profile(dib, &profile, &profile_size)) {
+ uint32 iptc_size = profile_size;
+ iptc_size += (4-(iptc_size & 0x03)); // Round up for long word alignment
+ BYTE *iptc_profile = (BYTE*)malloc(iptc_size);
+ if(!iptc_profile) {
+ free(profile);
+ return FALSE;
+ }
+ memset(iptc_profile, 0, iptc_size);
+ memcpy(iptc_profile, profile, profile_size);
+ if (TIFFIsByteSwapped(tiff))
+ TIFFSwabArrayOfLong((uint32 *) iptc_profile, (unsigned long)iptc_size/4);
+ // Tag is type TIFF_LONG so byte length is divided by four
+ TIFFSetField(tiff, TIFFTAG_RICHTIFFIPTC, iptc_size/4, iptc_profile);
+ // release the profile data
+ free(iptc_profile);
+ free(profile);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Write the TIFFTAG_XMLPACKET tag (XMP profile)
+ @param dib Input FIBITMAP
+ @param tiff LibTIFF TIFF handle
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+static BOOL
+tiff_write_xmp_profile(TIFF *tiff, FIBITMAP *dib) {
+ FITAG *tag_xmp = NULL;
+ FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
+
+ if(tag_xmp && (NULL != FreeImage_GetTagValue(tag_xmp))) {
+
+ TIFFSetField(tiff, TIFFTAG_XMLPACKET, (uint32)FreeImage_GetTagLength(tag_xmp), (BYTE*)FreeImage_GetTagValue(tag_xmp));
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+Write TIFF special profiles
+*/
+static void
+WriteMetadata(TIFF *tiff, FIBITMAP *dib) {
+ // IPTC
+ tiff_write_iptc_profile(tiff, dib);
+
+ // Adobe XMP
+ tiff_write_xmp_profile(tiff, dib);
+
+ // GeoTIFF tags
+ tiff_write_geotiff_profile(tiff, dib);
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "TIFF";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Tagged Image File Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "tif,tiff";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^[MI][MI][\\x01*][\\x01*]";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/tiff";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ BYTE tiff_id1[] = { 0x49, 0x49, 0x2A, 0x00 };
+ BYTE tiff_id2[] = { 0x4D, 0x4D, 0x00, 0x2A };
+ BYTE signature[4] = { 0, 0, 0, 0 };
+
+ io->read_proc(signature, 1, 4, handle);
+
+ if(memcmp(tiff_id1, signature, 4) == 0)
+ return TRUE;
+
+ if(memcmp(tiff_id2, signature, 4) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1) ||
+ (depth == 4) ||
+ (depth == 8) ||
+ (depth == 24) ||
+ (depth == 32)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (
+ (type == FIT_BITMAP) ||
+ (type == FIT_UINT16) ||
+ (type == FIT_INT16) ||
+ (type == FIT_UINT32) ||
+ (type == FIT_INT32) ||
+ (type == FIT_FLOAT) ||
+ (type == FIT_DOUBLE) ||
+ (type == FIT_COMPLEX) ||
+ (type == FIT_RGB16) ||
+ (type == FIT_RGBA16) ||
+ (type == FIT_RGBF)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsICCProfiles() {
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ // wrapper for TIFF I/O
+ fi_TIFFIO *fio = (fi_TIFFIO*)malloc(sizeof(fi_TIFFIO));
+ if(!fio) return NULL;
+ fio->io = io;
+ fio->handle = handle;
+
+ if (read) {
+ fio->tif = TIFFFdOpen((thandle_t)fio, "", "r");
+ } else {
+ fio->tif = TIFFFdOpen((thandle_t)fio, "", "w");
+ }
+ if(fio->tif == NULL) {
+ free(fio);
+ FreeImage_OutputMessageProc(s_format_id, "Error while opening TIFF: data is invalid");
+ return NULL;
+ }
+ return fio;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+ if(data) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)data;
+ TIFFClose(fio->tif);
+ free(fio);
+ }
+}
+
+// ----------------------------------------------------------
+
+static int DLL_CALLCONV
+PageCount(FreeImageIO *io, fi_handle handle, void *data) {
+ if(data) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)data;
+ TIFF *tif = (TIFF *)fio->tif;
+ int nr_ifd = 0;
+
+ do {
+ nr_ifd++;
+ } while (TIFFReadDirectory(tif));
+
+ return nr_ifd;
+ }
+
+ return 0;
+}
+
+// ----------------------------------------------------------
+
+/**
+check for uncommon bitspersample values (e.g. 10, 12, ...)
+@param photometric TIFFTAG_PHOTOMETRIC tiff tag
+@param bitspersample TIFFTAG_BITSPERSAMPLE tiff tag
+@return Returns FALSE if a uncommon bit-depth is encountered, returns TRUE otherwise
+*/
+static BOOL IsValidBitsPerSample(uint16 photometric, uint16 bitspersample) {
+ switch(bitspersample) {
+ case 1:
+ case 4:
+ if((photometric == PHOTOMETRIC_MINISWHITE) || (photometric == PHOTOMETRIC_MINISBLACK) || (photometric == PHOTOMETRIC_PALETTE)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 8:
+ return TRUE;
+ case 16:
+ if(photometric != PHOTOMETRIC_PALETTE) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ break;
+ case 32:
+ return TRUE;
+ case 64:
+ case 128:
+ if(photometric == PHOTOMETRIC_MINISBLACK) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ break;
+ default:
+ return FALSE;
+ }
+}
+
+static TIFFLoadMethod
+FindLoadMethod(TIFF *tif, FREE_IMAGE_TYPE image_type, int flags) {
+ uint16 bitspersample;
+ uint16 samplesperpixel;
+ uint16 photometric;
+ uint16 planar_config;
+
+ TIFFLoadMethod loadMethod = LoadAsGenericStrip;
+
+ TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
+ TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
+ TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
+
+ BOOL bIsTiled = (TIFFIsTiled(tif) == 0) ? FALSE:TRUE;
+
+ switch(photometric) {
+ // convert to 24 or 32 bits RGB if the image is full color
+ case PHOTOMETRIC_RGB:
+ if((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
+ // load 48-bit RGB and 64-bit RGBA without conversion
+ loadMethod = LoadAsGenericStrip;
+ } else if(bitspersample >= 8) {
+ loadMethod = LoadAsRBGA;
+ }
+ break;
+ case PHOTOMETRIC_YCBCR:
+ case PHOTOMETRIC_CIELAB:
+ case PHOTOMETRIC_ICCLAB:
+ case PHOTOMETRIC_ITULAB:
+ loadMethod = LoadAsRBGA;
+ break;
+ case PHOTOMETRIC_LOGLUV:
+ loadMethod = LoadAsRGBF;
+ break;
+ case PHOTOMETRIC_SEPARATED:
+ if(planar_config == PLANARCONFIG_CONTIG) {
+ // if image is PHOTOMETRIC_SEPARATED _and_ comes with an ICC profile,
+ // then the image should preserve its original (CMYK) colour model and
+ // should be read as CMYK (to keep the match of pixel and profile and
+ // to avoid multiple conversions. Conversion can be done by changing
+ // the profile from it's original CMYK to an RGB profile with an
+ // apropriate color management system. Works with non-tiled TIFFs.
+ if((((flags & TIFF_CMYK) == TIFF_CMYK) || samplesperpixel > 4) && !bIsTiled) {
+ loadMethod = LoadAsCMYK;
+ } else {
+ loadMethod = LoadAsRBGA;
+ }
+ } else if(planar_config == PLANARCONFIG_SEPARATE) {
+ // TIFFReadRGBAImage doesn't support this case ...
+ loadMethod = LoadAsCMYK;
+ }
+ break;
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ case PHOTOMETRIC_PALETTE:
+ // When samplesperpixel = 2 and bitspersample = 8, set the image as a
+ // 8-bit indexed image + 8-bit alpha layer image
+ // and convert to a 8-bit image with a transparency table
+ if((samplesperpixel == 2) && (bitspersample == 8)) {
+ loadMethod = LoadAs8BitTrns;
+ } else {
+ loadMethod = LoadAsGenericStrip;
+ }
+ break;
+ default:
+ loadMethod = LoadAsGenericStrip;
+ break;
+ }
+
+ if((loadMethod == LoadAsGenericStrip) && bIsTiled) {
+ loadMethod = LoadAsTiled;
+ }
+
+ return loadMethod;
+}
+
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ if ((handle != NULL) && (data != NULL)) {
+ TIFF *tif = NULL;
+ uint32 height = 0;
+ uint32 width = 0;
+ uint16 bitspersample = 1;
+ uint16 samplesperpixel = 1;
+ uint32 rowsperstrip;
+ uint16 photometric = PHOTOMETRIC_MINISWHITE;
+ uint16 compression = COMPRESSION_NONE;
+ uint16 planar_config;
+
+ FIBITMAP *dib = NULL;
+ uint32 iccSize = 0; // ICC profile length
+ void *iccBuf = NULL; // ICC profile data
+
+ try {
+ fi_TIFFIO *fio = (fi_TIFFIO*)data;
+ tif = fio->tif;
+
+ if (page != -1) {
+ if (!tif || !TIFFSetDirectory(tif, (tdir_t)page)) {
+ throw "Error encountered while opening TIFF file";
+ }
+ }
+
+ // first, get the photometric, the compression and basic metadata
+ // ---------------------------------------------------------------------------------
+
+ TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
+ TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
+
+ // check for HDR formats
+ // ---------------------------------------------------------------------------------
+
+ if(photometric == PHOTOMETRIC_LOGLUV) {
+ // check the compression
+ if(compression != COMPRESSION_SGILOG && compression != COMPRESSION_SGILOG24) {
+ throw "Only support SGILOG compressed LogLuv data";
+ }
+ // set decoder to output in IEEE 32-bit float XYZ values
+ TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
+ }
+
+ // ---------------------------------------------------------------------------------
+
+ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
+ TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
+ TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
+ TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
+ TIFFGetField(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ TIFFGetField(tif, TIFFTAG_ICCPROFILE, &iccSize, &iccBuf);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planar_config);
+
+ // check for unsupported formats
+ // ---------------------------------------------------------------------------------
+
+ if (compression == COMPRESSION_OJPEG)
+ throw "6.0 JPEG encoding is not supported";
+
+ if((photometric == PHOTOMETRIC_SEPARATED) && (bitspersample == 16))
+ throw "Unable to handle 16-bit CMYK TIFF";
+
+ if(IsValidBitsPerSample(photometric, bitspersample) == FALSE) {
+ FreeImage_OutputMessageProc(s_format_id,
+ "Unable to handle this format: bitspersample = %d, samplesperpixel = %d, photometric = %d",
+ (int)bitspersample, (int)samplesperpixel, (int)photometric);
+ throw (char*)NULL;
+ }
+
+ // ---------------------------------------------------------------------------------
+
+ // get image data type
+
+ FREE_IMAGE_TYPE image_type = ReadImageType(tif, bitspersample, samplesperpixel);
+
+ // get the most appropriate loading method
+
+ TIFFLoadMethod loadMethod = FindLoadMethod(tif, image_type, flags);
+
+ // ---------------------------------------------------------------------------------
+
+ if(loadMethod == LoadAsRBGA) {
+ // ---------------------------------------------------------------------------------
+ // RGB[A] loading using the TIFFReadRGBAImage() API
+ // ---------------------------------------------------------------------------------
+
+ BOOL has_alpha = FALSE;
+
+ // Read the whole image into one big RGBA buffer and then
+ // convert it to a DIB. This is using the traditional
+ // TIFFReadRGBAImage() API that we trust.
+
+ uint32 *raster = (uint32*)_TIFFmalloc(width * height * sizeof(uint32));
+ if (raster == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // read the image in one chunk into an RGBA array
+
+ if (!TIFFReadRGBAImage(tif, width, height, raster, 0)) {
+ _TIFFfree(raster);
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // TIFFReadRGBAImage always deliveres 3 or 4 samples per pixel images
+ // (RGB or RGBA, see below). Cut-off possibly present channels (additional
+ // alpha channels) from e.g. Photoshop. Any CMYK(A..) is now treated as RGB,
+ // any additional alpha channel on RGB(AA..) is lost on conversion to RGB(A)
+
+ if(samplesperpixel > 4) {
+ FreeImage_OutputMessageProc(s_format_id, "Warning: %d additional alpha channel(s) ignored", samplesperpixel-4);
+ samplesperpixel = 4;
+ }
+
+ // create a new DIB (take care of different samples-per-pixel in case
+ // of converted CMYK image (RGB conversion is on sample per pixel less)
+
+ if (photometric == PHOTOMETRIC_SEPARATED && samplesperpixel == 4) {
+ samplesperpixel = 3;
+ }
+
+ dib = CreateImageType(image_type, width, height, bitspersample, samplesperpixel);
+ if (dib == NULL) {
+ // free the raster pointer and output an error if allocation failed
+
+ _TIFFfree(raster);
+
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // read the raster lines and save them in the DIB
+ // with RGB mode, we have to change the order of the 3 samples RGB
+ // We use macros for extracting components from the packed ABGR
+ // form returned by TIFFReadRGBAImage.
+
+ uint32 *row = &raster[0];
+
+ if (samplesperpixel == 4) {
+ // 32-bit RGBA
+ for (uint32 y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (uint32 x = 0; x < width; x++) {
+ bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]);
+ bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]);
+ bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]);
+ bits[FI_RGBA_ALPHA] = (BYTE)TIFFGetA(row[x]);
+
+ if (bits[FI_RGBA_ALPHA] != 0)
+ has_alpha = TRUE;
+
+ bits += 4;
+ }
+ row += width;
+ }
+ } else {
+ // 24-bit RGB
+ for (uint32 y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (uint32 x = 0; x < width; x++) {
+ bits[FI_RGBA_BLUE] = (BYTE)TIFFGetB(row[x]);
+ bits[FI_RGBA_GREEN] = (BYTE)TIFFGetG(row[x]);
+ bits[FI_RGBA_RED] = (BYTE)TIFFGetR(row[x]);
+
+ bits += 3;
+ }
+ row += width;
+ }
+ }
+
+ _TIFFfree(raster);
+
+ FreeImage_SetTransparent(dib, has_alpha);
+
+ } else if(loadMethod == LoadAs8BitTrns) {
+ // ---------------------------------------------------------------------------------
+ // 8-bit + 8-bit alpha layer loading
+ // ---------------------------------------------------------------------------------
+
+ // create a new 8-bit DIB
+ dib = CreateImageType(image_type, width, height, bitspersample, samplesperpixel);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // set up the colormap based on photometric
+
+ ReadPalette(tif, photometric, bitspersample, dib);
+
+ // calculate the line + pitch (separate for scr & dest)
+
+ tsize_t src_line = TIFFScanlineSize(tif);
+ // here, the pitch is 2x less than the original as we only keep the first layer
+ int dst_pitch = FreeImage_GetPitch(dib);
+
+ // transparency table for 8-bit + 8-bit alpha images
+
+ BYTE trns[256];
+ // clear the transparency table
+ memset(trns, 0xFF, 256 * sizeof(BYTE));
+
+
+ // In the tiff file the lines are save from up to down
+ // In a DIB the lines must be saved from down to up
+
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
+
+ // read the tiff lines and save them in the DIB
+
+ if(planar_config == PLANARCONFIG_CONTIG) {
+
+ BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+ for (int l = 0; l < nrow; l++) {
+ BYTE *p = bits;
+ BYTE *b = buf + l * src_line;
+
+ for(uint32 x = 0; x < (uint32)(src_line / samplesperpixel); x++) {
+ // copy the 8-bit layer
+ *p = b[0];
+ // convert the 8-bit alpha layer to a trns table
+ trns[ b[0] ] = b[1];
+
+ p++;
+ b += samplesperpixel;
+ }
+ bits -= dst_pitch;
+ }
+ }
+
+ free(buf);
+ }
+ else if(planar_config == PLANARCONFIG_SEPARATE) {
+ tsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE);
+ BYTE *buf = (BYTE*)malloc(2 * stripsize);
+ BYTE *grey = buf;
+ BYTE *alpha = buf + stripsize;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), grey, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 1), alpha, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+
+ for (int l = 0; l < nrow; l++) {
+ BYTE *p = bits;
+ BYTE *g = grey + l * src_line;
+ BYTE *a = alpha + l * src_line;
+
+ for(uint32 x = 0; x < (uint32)(src_line); x++) {
+ // copy the 8-bit layer
+ *p = g[0];
+ // convert the 8-bit alpha layer to a trns table
+ trns[ g[0] ] = a[0];
+
+ p++;
+ g++;
+ a++;
+ }
+ bits -= dst_pitch;
+ }
+ }
+
+ free(buf);
+
+ }
+
+ FreeImage_SetTransparencyTable(dib, &trns[0], 256);
+ FreeImage_SetTransparent(dib, TRUE);
+
+ } else if(loadMethod == LoadAsCMYK) {
+ // ---------------------------------------------------------------------------------
+ // CMYK loading
+ // ---------------------------------------------------------------------------------
+
+ BOOL has_alpha = FALSE;
+
+ // At this place, samplesperpixel could be > 4, esp. when a CMYK(A) format
+ // is recognized. Where all other formats are handled straight-forward, this
+ // format has to be handled special
+
+ BOOL isCMYKA = (photometric == PHOTOMETRIC_SEPARATED) && (samplesperpixel > 4);
+ uint16 spp = MIN(samplesperpixel, (uint16)4);
+ if((planar_config == PLANARCONFIG_SEPARATE) && !isCMYKA && ((flags & TIFF_CMYK) != TIFF_CMYK)) {
+ // CMYK picture => convert to RGB 24-bit
+ spp = 3;
+ }
+
+ // create a new DIB
+ dib = CreateImageType(image_type, width, height, bitspersample, spp);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // calculate the line + pitch (separate for scr & dest)
+
+ tsize_t src_line = TIFFScanlineSize(tif);
+ int dst_pitch = FreeImage_GetPitch(dib);
+
+ // In the tiff file the lines are save from up to down
+ // In a DIB the lines must be saved from down to up
+
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
+
+ // read the tiff lines and save them in the DIB
+
+ if(planar_config == PLANARCONFIG_CONTIG) {
+ BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+ if(isCMYKA) {
+ // CMYKA picture
+ for (int l = 0; l < nrow; l++) {
+ // Here we know: samples-per-pixel was >= 5 on CMYKA picture
+ // This should be converted to RGBA or CMYK, depending on
+ // TIFF_CMYK is given. The resulting image always has 32bpp.
+
+ BYTE *p = bits;
+ BYTE *b = buf + l * src_line;
+
+ for (uint32 x = 0; x < (uint32)(src_line / samplesperpixel); x++) {
+ if ((flags & TIFF_CMYK) == TIFF_CMYK) {
+ memcpy(p, b, spp);
+ } else {
+ BYTE k = 255 - b[3];
+ p[FI_RGBA_RED] = (k*(255-b[0]))/255;
+ p[FI_RGBA_GREEN] = (k*(255-b[1]))/255;
+ p[FI_RGBA_BLUE] = (k*(255-b[2]))/255;
+ if ((p[FI_RGBA_ALPHA] = b[4]) != 0)
+ has_alpha = TRUE;
+ }
+ b += samplesperpixel;
+ p += spp;
+ }
+ bits -= dst_pitch;
+ }
+ }
+ else {
+ // CMYK picture: just copy
+ for (int l = 0; l < nrow; l++) {
+ BYTE *b = buf + l * src_line;
+ memcpy(bits, b, src_line);
+ bits -= dst_pitch;
+ }
+ }
+ }
+
+ free(buf);
+ }
+ else if(planar_config == PLANARCONFIG_SEPARATE) {
+ uint16 sample;
+ BYTE *channel;
+ tsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE);
+ BYTE *buf = (BYTE*)malloc(samplesperpixel * stripsize);
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ // read all separated strips
+ channel = buf;
+ for(sample = 0; sample < samplesperpixel; sample++) {
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), channel, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+ channel += stripsize;
+ }
+ if ((flags & TIFF_CMYK) == TIFF_CMYK) {
+ // CMYK or CMYKA picture: load as 32-bit CMYK, skipping possibly present alpha channel(s)
+ for (int l = 0; l < nrow; l++) {
+ channel = buf;
+ for(sample = 0; sample < spp; sample++) {
+ BYTE *src_bits = channel + l * src_line;
+ BYTE *dst_bits = bits;
+ for (uint32 x = 0; x < (uint32)(src_line); x++) {
+ dst_bits[sample] = src_bits[x];
+ dst_bits += spp;
+ }
+ channel += stripsize;
+ }
+ bits -= dst_pitch;
+ }
+ }
+ else if(isCMYKA) {
+ // CMYKA picture: convert to RGBA, skipping possibly some alpha channel(s)
+ for (int l = 0; l < nrow; l++) {
+ BYTE *c_channel = buf + l * src_line;
+ BYTE *m_channel = buf + stripsize + l * src_line;
+ BYTE *y_channel = buf + 2*stripsize + l * src_line;
+ BYTE *k_channel = buf + 3*stripsize + l * src_line;
+ BYTE *a_channel = buf + 4*stripsize + l * src_line;
+ BYTE *dst_bits = bits;
+ for (uint32 x = 0; x < (uint32)(src_line); x++) {
+ BYTE k = 255 - k_channel[x];
+ dst_bits[FI_RGBA_RED] = (k*(255-c_channel[x]))/255;
+ dst_bits[FI_RGBA_GREEN] = (k*(255-m_channel[x]))/255;
+ dst_bits[FI_RGBA_BLUE] = (k*(255-y_channel[x]))/255;
+ if ((dst_bits[FI_RGBA_ALPHA] = a_channel[x]) != 0)
+ has_alpha = TRUE;
+ dst_bits += spp;
+ }
+ bits -= dst_pitch;
+ }
+ }
+ else {
+ // CMYK picture: convert to RGB
+ for (int l = 0; l < nrow; l++) {
+ BYTE *c_channel = buf + l * src_line;
+ BYTE *m_channel = buf + stripsize + l * src_line;
+ BYTE *y_channel = buf + 2*stripsize + l * src_line;
+ BYTE *k_channel = buf + 3*stripsize + l * src_line;
+ BYTE *dst_bits = bits;
+ for (uint32 x = 0; x < (uint32)(src_line); x++) {
+ BYTE k = 255 - k_channel[x];
+ dst_bits[FI_RGBA_RED] = (k*(255-c_channel[x]))/255;
+ dst_bits[FI_RGBA_GREEN] = (k*(255-m_channel[x]))/255;
+ dst_bits[FI_RGBA_BLUE] = (k*(255-y_channel[x]))/255;
+ dst_bits += spp;
+ }
+ bits -= dst_pitch;
+ }
+ }
+ }
+
+ free(buf);
+ }
+
+ FreeImage_SetTransparent(dib, has_alpha);
+
+ } else if(loadMethod == LoadAsGenericStrip) {
+ // ---------------------------------------------------------------------------------
+ // Generic loading
+ // ---------------------------------------------------------------------------------
+
+ // create a new DIB
+ dib = CreateImageType(image_type, width, height, bitspersample, samplesperpixel);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // set up the colormap based on photometric
+
+ ReadPalette(tif, photometric, bitspersample, dib);
+
+ // calculate the line + pitch (separate for scr & dest)
+
+ tsize_t src_line = TIFFScanlineSize(tif);
+ int dst_pitch = FreeImage_GetPitch(dib);
+
+ // In the tiff file the lines are save from up to down
+ // In a DIB the lines must be saved from down to up
+
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
+
+ // read the tiff lines and save them in the DIB
+
+ if(planar_config == PLANARCONFIG_CONTIG) {
+ BOOL bThrowMessage = FALSE;
+ BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
+ // ignore errors as they can be frequent and not really valid errors, especially with fax images
+ bThrowMessage = TRUE;
+ /*
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ */
+ }
+ // color/greyscale picture (1-, 4-, 8-bit) or special type (int, long, double, ...)
+ // ... just copy
+ for (int l = 0; l < nrow; l++) {
+ memcpy(bits, buf + l * src_line, src_line);
+ bits -= dst_pitch;
+ }
+ }
+
+ free(buf);
+
+ if(bThrowMessage) {
+ FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !");
+ }
+ }
+ else if(planar_config == PLANARCONFIG_SEPARATE) {
+ BOOL bThrowMessage = FALSE;
+ uint16 sample;
+ BYTE *channel;
+ tsize_t stripsize = TIFFStripSize(tif) * sizeof(BYTE);
+ BYTE *buf = (BYTE*)malloc(samplesperpixel * stripsize);
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ int bytespersample = bitspersample / 8;
+ int bytesperpixel = bytespersample * samplesperpixel;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ // read all separated strips
+ channel = buf;
+ for(sample = 0; sample < samplesperpixel; sample++) {
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, sample), channel, nrow * src_line) == -1) {
+ // ignore errors as they can be frequent and not really valid errors, especially with fax images
+ bThrowMessage = TRUE;
+ /*
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ */
+ }
+ channel += stripsize;
+ }
+
+ // reconstruct the picture
+ for (int l = 0; l < nrow; l++) {
+ channel = buf;
+ for(sample = 0; sample < samplesperpixel; sample++) {
+ BYTE *src_bits = channel + l * src_line;
+ BYTE *dst_bits = bits + sample * bytespersample;
+ for (uint32 x = 0; x < (uint32)(src_line / bytespersample); x++) {
+ memcpy(dst_bits, src_bits, bytespersample);
+ src_bits += bytespersample;
+ dst_bits += bytesperpixel;
+ }
+ channel += stripsize;
+ }
+ bits -= dst_pitch;
+ }
+ }
+
+ free(buf);
+
+ if(bThrowMessage) {
+ FreeImage_OutputMessageProc(s_format_id, "Warning: parsing error. Image may be incomplete or contain invalid data !");
+ }
+ }
+
+ } else if(loadMethod == LoadAsTiled) {
+ // ---------------------------------------------------------------------------------
+ // Tiled image loading
+ // ---------------------------------------------------------------------------------
+
+ uint32 tileWidth, tileHeight;
+ uint32 src_line = 0;
+
+ // create a new DIB
+ dib = CreateImageType(image_type, width, height, bitspersample, samplesperpixel);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // set up the colormap based on photometric
+
+ ReadPalette(tif, photometric, bitspersample, dib);
+
+ // get the tile geometry
+ if(!TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth) || !TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight)) {
+ throw "Invalid tiled TIFF image";
+ }
+
+ // get the maximum number of bytes required to contain a tile
+ tsize_t tileSize = TIFFTileSize(tif);
+
+ // allocate tile buffer
+ BYTE *tileBuffer = (BYTE*)malloc(tileSize * sizeof(BYTE));
+ if(tileBuffer == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ // calculate src line and dst pitch
+ int dst_pitch = FreeImage_GetPitch(dib);
+ int tileRowSize = TIFFTileRowSize(tif);
+ int imageRowSize = TIFFScanlineSize(tif);
+
+
+ // In the tiff file the lines are save from up to down
+ // In a DIB the lines must be saved from down to up
+
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
+
+ // read the tiff lines and save them in the DIB
+
+ if(planar_config == PLANARCONFIG_CONTIG) {
+ uint32 x, y, rowSize;
+ for (y = 0; y < height; y += tileHeight) {
+ int32 nrows = (y + tileHeight > height ? height - y : tileHeight);
+
+ for (x = 0, rowSize = 0; x < width; x += tileWidth, rowSize += tileRowSize) {
+ memset(tileBuffer, 0, tileSize);
+
+ // read one tile
+ if (TIFFReadTile(tif, tileBuffer, x, y, 0, 0) < 0) {
+ free(tileBuffer);
+ throw "Corrupted tiled TIFF file";
+ }
+ // convert to strip
+ if(x + tileWidth > width) {
+ src_line = imageRowSize - rowSize;
+ } else {
+ src_line = tileRowSize;
+ }
+ BYTE *src_bits = tileBuffer;
+ BYTE *dst_bits = bits + rowSize;
+ for(int k = 0; k < nrows; k++) {
+ memcpy(dst_bits, src_bits, src_line);
+ src_bits += tileRowSize;
+ dst_bits -= dst_pitch;
+ }
+ }
+
+ bits -= nrows * dst_pitch;
+ }
+
+ }
+ else if(planar_config == PLANARCONFIG_SEPARATE) {
+ free(tileBuffer);
+ throw "Separated tiled TIFF images are not supported";
+ }
+
+ free(tileBuffer);
+
+ } else if(loadMethod == LoadAsRGBF) {
+ // ---------------------------------------------------------------------------------
+ // RGBF loading
+ // ---------------------------------------------------------------------------------
+
+ double stonits; // input conversion to nits
+ if (!TIFFGetField(tif, TIFFTAG_STONITS, &stonits)) {
+ stonits = 1;
+ }
+
+ // create a new DIB
+ dib = CreateImageType(image_type, width, height, bitspersample, samplesperpixel);
+ if (dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // fill in the resolution (english or universal)
+
+ ReadResolution(tif, dib);
+
+ // calculate the line + pitch (separate for scr & dest)
+
+ tsize_t src_line = TIFFScanlineSize(tif);
+ int dst_pitch = FreeImage_GetPitch(dib);
+
+ // In the tiff file the lines are save from up to down
+ // In a DIB the lines must be saved from down to up
+
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1);
+
+ // read the tiff lines and save them in the DIB
+
+ if(planar_config == PLANARCONFIG_CONTIG) {
+ BYTE *buf = (BYTE*)malloc(TIFFStripSize(tif) * sizeof(BYTE));
+ if(buf == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (uint32 y = 0; y < height; y += rowsperstrip) {
+ int32 nrow = (y + rowsperstrip > height ? height - y : rowsperstrip);
+
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, y, 0), buf, nrow * src_line) == -1) {
+ free(buf);
+ throw FI_MSG_ERROR_PARSING;
+ }
+ // convert from XYZ to RGB
+ for (int l = 0; l < nrow; l++) {
+ tiff_ConvertLineXYZToRGB(bits, buf + l * src_line, stonits, width);
+ bits -= dst_pitch;
+ }
+ }
+
+ free(buf);
+ }
+ else if(planar_config == PLANARCONFIG_SEPARATE) {
+ // this cannot happend according to the LogLuv specification
+ throw "Unable to handle PLANARCONFIG_SEPARATE LogLuv images";
+ }
+
+ } else {
+ // ---------------------------------------------------------------------------------
+ // Unknown or unsupported format
+ // ---------------------------------------------------------------------------------
+
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // copy ICC profile data (must be done after FreeImage_Allocate)
+
+ FreeImage_CreateICCProfile(dib, iccBuf, iccSize);
+ if (photometric == PHOTOMETRIC_SEPARATED && ((flags & TIFF_CMYK) == TIFF_CMYK)) {
+ FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
+ }
+
+ // copy TIFF metadata (must be done after FreeImage_Allocate)
+
+ ReadMetadata(tif, dib);
+
+ return (FIBITMAP *)dib;
+
+ } catch (const char *message) {
+ if(dib) FreeImage_Unload(dib);
+ if(message) FreeImage_OutputMessageProc(s_format_id, message);
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib != NULL) && (handle != NULL) && (data != NULL)) {
+ fi_TIFFIO *fio = (fi_TIFFIO*)data;
+ TIFF *out = fio->tif;
+
+ int32 height;
+ int32 width;
+ uint32 rowsperstrip = (uint32) -1;
+ uint16 bitsperpixel;
+ uint16 bitspersample;
+ uint16 samplesperpixel;
+ uint16 photometric;
+ uint16 pitch;
+ int32 x, y;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ bitsperpixel = (uint16)FreeImage_GetBPP(dib);
+
+ FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
+
+ if(image_type == FIT_BITMAP) {
+ // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
+
+ samplesperpixel = ((bitsperpixel == 24) ? 3 : ((bitsperpixel == 32) ? 4 : 1));
+ bitspersample = bitsperpixel / samplesperpixel;
+ photometric = GetPhotometric(dib);
+
+ if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) {
+ // 8-bit transparent picture : convert later to 8-bit + 8-bit alpha
+ samplesperpixel = 2;
+ bitspersample = 8;
+ }
+ else if(bitsperpixel == 32) {
+ // 32-bit images : check for CMYK or alpha transparency
+
+ if((((iccProfile->flags & FIICC_COLOR_IS_CMYK) == FIICC_COLOR_IS_CMYK) || ((flags & TIFF_CMYK) == TIFF_CMYK))) {
+ // CMYK support
+ photometric = PHOTOMETRIC_SEPARATED;
+ TIFFSetField(out, TIFFTAG_INKSET, INKSET_CMYK);
+ TIFFSetField(out, TIFFTAG_NUMBEROFINKS, 4);
+ }
+ else if(photometric == PHOTOMETRIC_RGB) {
+ // transparency mask support
+ uint16 sampleinfo[1];
+ // unassociated alpha data is transparency information
+ sampleinfo[0] = EXTRASAMPLE_UNASSALPHA;
+ TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo);
+ }
+ }
+ } else if(image_type == FIT_RGB16) {
+ // 48-bit RGB
+
+ samplesperpixel = 3;
+ bitspersample = bitsperpixel / samplesperpixel;
+ photometric = PHOTOMETRIC_RGB;
+ } else if(image_type == FIT_RGBA16) {
+ // 64-bit RGBA
+
+ samplesperpixel = 4;
+ bitspersample = bitsperpixel / samplesperpixel;
+ photometric = PHOTOMETRIC_RGB;
+ // transparency mask support
+ uint16 sampleinfo[1];
+ // unassociated alpha data is transparency information
+ sampleinfo[0] = EXTRASAMPLE_UNASSALPHA;
+ TIFFSetField(out, TIFFTAG_EXTRASAMPLES, 1, sampleinfo);
+ } else if(image_type == FIT_RGBF) {
+ // 96-bit RGBF => store with a LogLuv encoding
+
+ samplesperpixel = 3;
+ bitspersample = bitsperpixel / samplesperpixel;
+ photometric = PHOTOMETRIC_LOGLUV;
+ // the library converts to and from floating-point XYZ CIE values
+ TIFFSetField(out, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_FLOAT);
+ // TIFFSetField(out, TIFFTAG_STONITS, 1.0); // assume unknown
+ } else {
+ // special image type (int, long, double, ...)
+
+ samplesperpixel = 1;
+ bitspersample = bitsperpixel;
+ photometric = PHOTOMETRIC_MINISBLACK;
+ }
+
+ // set image data type
+
+ WriteImageType(out, image_type);
+
+ // write possible ICC profile
+
+ if (iccProfile->size && iccProfile->data) {
+ TIFFSetField(out, TIFFTAG_ICCPROFILE, iccProfile->size, iccProfile->data);
+ }
+
+ // handle standard width/height/bpp stuff
+
+ TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);
+ TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);
+ TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, samplesperpixel);
+ TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitspersample);
+ TIFFSetField(out, TIFFTAG_PHOTOMETRIC, photometric);
+ TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); // single image plane
+ TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
+ TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, rowsperstrip));
+
+ // handle metrics
+
+ WriteResolution(out, dib);
+
+ // multi-paging
+
+ if (page >= 0) {
+ char page_number[20];
+ sprintf(page_number, "Page %d", page);
+
+ TIFFSetField(out, TIFFTAG_SUBFILETYPE, FILETYPE_PAGE);
+ TIFFSetField(out, TIFFTAG_PAGENUMBER, page);
+ TIFFSetField(out, TIFFTAG_PAGENAME, page_number);
+ } else {
+ TIFFSetField(out, TIFFTAG_SUBFILETYPE, 0);
+ }
+
+ // palettes (image colormaps are automatically scaled to 16-bits)
+
+ if (photometric == PHOTOMETRIC_PALETTE) {
+ uint16 *r, *g, *b;
+ uint16 nColors = (uint16)FreeImage_GetColorsUsed(dib);
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+
+ r = (uint16 *) _TIFFmalloc(sizeof(uint16) * 3 * nColors);
+ if(r == NULL) throw FI_MSG_ERROR_MEMORY;
+ g = r + nColors;
+ b = g + nColors;
+
+ for (int i = nColors - 1; i >= 0; i--) {
+ r[i] = SCALE((uint16)pal[i].rgbRed);
+ g[i] = SCALE((uint16)pal[i].rgbGreen);
+ b[i] = SCALE((uint16)pal[i].rgbBlue);
+ }
+
+ TIFFSetField(out, TIFFTAG_COLORMAP, r, g, b);
+
+ _TIFFfree(r);
+ }
+
+ // compression
+
+ WriteCompression(out, bitspersample, samplesperpixel, photometric, flags);
+
+ // metadata
+
+ WriteMetadata(out, dib);
+
+
+ // read the DIB lines from bottom to top
+ // and save them in the TIF
+ // -------------------------------------
+
+ pitch = (uint16)FreeImage_GetPitch(dib);
+
+ if(image_type == FIT_BITMAP) {
+ // standard bitmap type
+
+ switch(bitsperpixel) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ if((bitsperpixel == 8) && FreeImage_IsTransparent(dib)) {
+ // 8-bit transparent picture : convert to 8-bit + 8-bit alpha
+
+ // get the transparency table
+ BYTE *trns = FreeImage_GetTransparencyTable(dib);
+
+ BYTE *buffer = (BYTE *)malloc(2 * width * sizeof(BYTE));
+ if(buffer == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (y = height - 1; y >= 0; y--) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+
+ BYTE *p = bits, *b = buffer;
+
+ for(x = 0; x < width; x++) {
+ // copy the 8-bit layer
+ b[0] = *p;
+ // convert the trns table to a 8-bit alpha layer
+ b[1] = trns[ b[0] ];
+
+ p++;
+ b += samplesperpixel;
+ }
+
+ // write the scanline to disc
+
+ TIFFWriteScanline(out, buffer, height - y - 1, 0);
+ }
+
+ free(buffer);
+ }
+ else {
+ // other cases
+ BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
+ if(buffer == NULL) throw FI_MSG_ERROR_MEMORY;
+ for (y = 0; y < height; y++) {
+ // get a copy of the scanline
+ memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
+ // write the scanline to disc
+ TIFFWriteScanline(out, buffer, y, 0);
+ }
+ free(buffer);
+ }
+
+ break;
+ }
+
+ case 24:
+ case 32:
+ {
+ BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
+ if(buffer == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (y = 0; y < height; y++) {
+ // get a copy of the scanline
+
+ memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
+ if (photometric != PHOTOMETRIC_SEPARATED) {
+ // TIFFs store color data RGB(A) instead of BGR(A)
+
+ BYTE *pBuf = buffer;
+
+ for (x = 0; x < width; x++) {
+ INPLACESWAP(pBuf[0], pBuf[2]);
+ pBuf += samplesperpixel;
+ }
+ }
+#endif
+ // write the scanline to disc
+
+ TIFFWriteScanline(out, buffer, y, 0);
+ }
+
+ free(buffer);
+
+ break;
+ }
+ }
+
+ } else if(image_type == FIT_RGBF) {
+ // RGBF image => store as XYZ using a LogLuv encoding
+
+ BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
+ if(buffer == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (y = 0; y < height; y++) {
+ // get a copy of the scanline and convert from RGB to XYZ
+ tiff_ConvertLineRGBToXYZ(buffer, FreeImage_GetScanLine(dib, height - y - 1), width);
+ // write the scanline to disc
+ TIFFWriteScanline(out, buffer, y, 0);
+ }
+ free(buffer);
+ } else {
+ // special bitmap type (int, long, double, etc.)
+
+ switch(bitsperpixel) {
+ case 16:
+ case 32:
+ case 48:
+ case 64:
+ case 128:
+ {
+ BYTE *buffer = (BYTE *)malloc(pitch * sizeof(BYTE));
+ if(buffer == NULL) throw FI_MSG_ERROR_MEMORY;
+
+ for (y = 0; y < height; y++) {
+ // get a copy of the scanline
+ memcpy(buffer, FreeImage_GetScanLine(dib, height - y - 1), pitch);
+ // write the scanline to disc
+ TIFFWriteScanline(out, buffer, y, 0);
+ }
+ free(buffer);
+ }
+ break;
+ }
+ }
+
+ // write out the directory tag if we wrote a page other than -1
+
+ if (page >= 0)
+ TIFFWriteDirectory(out);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitTIFF(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = Open;
+ plugin->close_proc = Close;
+ plugin->pagecount_proc = PageCount;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = SupportsICCProfiles;
+}
diff --git a/Source/FreeImage/PluginWBMP.cpp b/Source/FreeImage/PluginWBMP.cpp
new file mode 100644
index 0000000..2ff8f02
--- /dev/null
+++ b/Source/FreeImage/PluginWBMP.cpp
@@ -0,0 +1,372 @@
+// ==========================================================
+// Wireless Bitmap Format Loader and Writer
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Wireless Bitmap Format
+// ----------------------
+// The WBMP format enables graphical information to be sent to a variety of handsets.
+// The WBMP format is terminal independent and describes only graphical information.
+
+// IMPLEMENTATION NOTES:
+// ------------------------
+// The WBMP format is configured according to a type field value (TypeField below),
+// which maps to all relevant image encoding information, such as:
+// · Pixel organisation and encoding
+// · Palette organisation and encoding
+// · Compression characteristics
+// · Animation encoding
+// For each TypeField value, all relevant image characteristics are
+// fully specified as part of the WAP documentation.
+// Currently, a simple compact, monochrome image format is defined
+// within the WBMP type space :
+//
+// Image Type Identifier, multi-byte integer 0
+// Image Format description 0 B/W, no compression
+// -------------------------------------------------------------------------------
+
+// WBMP Header
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif
+
+typedef struct tagWBMPHEADER {
+ WORD TypeField; // Image type identifier of multi-byte length
+ BYTE FixHeaderField; // Octet of general header information
+ BYTE ExtHeaderFields; // Zero or more extension header fields
+ WORD Width; // Multi-byte width field
+ WORD Height; // Multi-byte height field
+} WBMPHEADER;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+
+// The extension headers may be of type binary 00 through binary 11, defined as follows.
+
+// - Type 00 indicates a multi-byte bitfield used to specify additional header information.
+// The first bit is set if a type 00, extension header is set if more data follows.
+// The other bits are reserved for future use.
+// - Type 01 - reserved for future use.
+// - Type 10 - reserved for future use.
+// - Type 11 indicates a sequence of parameter/value pairs. These can be used for
+// optimisations and special purpose extensions, eg, animation image formats.
+// The parameter size tells the length (1-8 bytes) of the following parameter name.
+// The value size gives the length (1-16 bytes) of the following parameter value.
+// The concatenation flag indicates whether another parameter/value pair will follow
+// after reading the specified bytes of data.
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+static DWORD
+multiByteRead(FreeImageIO *io, fi_handle handle) {
+ // Multi-byte encoding / decoding
+ // -------------------------------
+ // A multi-byte integer consists of a series of octets, where the most significant bit
+ // is the continuation flag, and the remaining seven bits are a scalar value.
+ // The continuation flag is used to indicate that an octet is not the end of the multi-byte
+ // sequence.
+
+ DWORD Out = 0;
+ BYTE In = 0;
+
+ while (io->read_proc(&In, 1, 1, handle)) {
+ Out += (In & 0x7F);
+
+ if ((In & 0x80) == 0x00)
+ break;
+
+ Out <<= 7;
+ }
+
+ return Out;
+}
+
+static void
+multiByteWrite(FreeImageIO *io, fi_handle handle, DWORD In) {
+ BYTE Out, k = 1;
+
+ while (In & (0x7F << 7*k))
+ k++;
+
+ while (k > 1) {
+ k--;
+
+ Out = (BYTE)(0x80 | (In >> 7*k) & 0xFF);
+
+ io->write_proc(&Out, 1, 1, handle);
+ }
+
+ Out = (BYTE)(In & 0x7F);
+
+ io->write_proc(&Out, 1, 1, handle);
+}
+
+static void
+readExtHeader(FreeImageIO *io, fi_handle handle, BYTE b) {
+ // Extension header fields
+ // ------------------------
+ // Read the extension header fields
+ // (since we don't use them for the moment, we skip them).
+
+ switch (b & 0x60) {
+ // Type 00: read multi-byte bitfield
+
+ case 0x00:
+ {
+ DWORD info = multiByteRead(io, handle);
+ break;
+ }
+
+ // Type 11: read a sequence of parameter/value pairs.
+
+ case 0x60:
+ {
+ BYTE sizeParamIdent = (b & 0x70) >> 4; // Size of Parameter Identifier (in bytes)
+ BYTE sizeParamValue = (b & 0x0F); // Size of Parameter Value (in bytes)
+
+ BYTE *Ident = (BYTE*)malloc(sizeParamIdent * sizeof(BYTE));
+ BYTE *Value = (BYTE*)malloc(sizeParamValue * sizeof(BYTE));
+
+ io->read_proc(Ident, sizeParamIdent, 1, handle);
+ io->read_proc(Value, sizeParamValue, 1, handle);
+
+ free(Ident);
+ free(Value);
+ break;
+ }
+
+ // reserved for future use
+
+ case 0x20: // Type 01
+ case 0x40: // Type 10
+ break;
+ }
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "WBMP";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Wireless Bitmap";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "wap,wbmp,wbm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/vnd.wap.wbmp";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 1)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ WORD x, y, width, height;
+ FIBITMAP *dib;
+ BYTE *bits; // pointer to dib data
+ RGBQUAD *pal; // pointer to dib palette
+
+ WBMPHEADER header;
+
+ if (handle) {
+ try {
+ // Read header information
+ // -----------------------
+
+ // Type
+
+ header.TypeField = (WORD)multiByteRead(io, handle);
+
+ if (header.TypeField != 0) {
+ throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
+ }
+
+ // FixHeaderField
+
+ io->read_proc(&header.FixHeaderField, 1, 1, handle);
+
+ // ExtHeaderFields
+ // 1 = more will follow, 0 = last octet
+
+ if (header.FixHeaderField & 0x80) {
+ header.ExtHeaderFields = 0x80;
+
+ while(header.ExtHeaderFields & 0x80) {
+ io->read_proc(&header.ExtHeaderFields, 1, 1, handle);
+
+ readExtHeader(io, handle, header.ExtHeaderFields);
+ }
+ }
+
+ // width & height
+
+ width = (WORD)multiByteRead(io, handle);
+ height = (WORD)multiByteRead(io, handle);
+
+ // Allocate a new dib
+
+ dib = FreeImage_Allocate(width, height, 1);
+ if (!dib) {
+ throw FI_MSG_ERROR_DIB_MEMORY;
+ }
+
+ // write the palette data
+
+ pal = FreeImage_GetPalette(dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+
+ // read the bitmap data
+
+ int line = FreeImage_GetLine(dib);
+
+ for (y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for (x = 0; x < line; x++) {
+ io->read_proc(&bits[x], 1, 1, handle);
+ }
+ }
+
+ return dib;
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ return NULL;
+ }
+
+ }
+
+ return NULL;
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ BYTE *bits; // pointer to dib data
+
+ if ((dib) && (handle)) {
+ try {
+ if (FreeImage_GetBPP(dib) != 1)
+ throw "Only 1-bit depth bitmaps can be saved as WBMP";
+
+ // write the header
+
+ WBMPHEADER header;
+ header.TypeField = 0; // Type 0: B/W, no compression
+ header.FixHeaderField = 0; // No ExtHeaderField
+ header.Width = (WORD)FreeImage_GetWidth(dib); // Image width
+ header.Height = (WORD)FreeImage_GetHeight(dib); // Image height
+
+ multiByteWrite(io, handle, header.TypeField);
+
+ io->write_proc(&header.FixHeaderField, 1, 1, handle);
+
+ multiByteWrite(io, handle, header.Width);
+ multiByteWrite(io, handle, header.Height);
+
+ // write the bitmap data
+
+ WORD linelength = (WORD)FreeImage_GetLine(dib);
+
+ for (WORD y = 0; y < header.Height; y++) {
+ bits = FreeImage_GetScanLine(dib, header.Height - 1 - y);
+
+ io->write_proc(&bits[0], linelength, 1, handle);
+ }
+
+ return TRUE;
+
+ } catch (const char* text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+ }
+ }
+
+ return FALSE;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitWBMP(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
diff --git a/Source/FreeImage/PluginXBM.cpp b/Source/FreeImage/PluginXBM.cpp
new file mode 100644
index 0000000..0aac48c
--- /dev/null
+++ b/Source/FreeImage/PluginXBM.cpp
@@ -0,0 +1,399 @@
+// ==========================================================
+// XBM Loader
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+// part of the code adapted from the netPBM package (xbmtopbm.c)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+//
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+#define MAX_LINE 512
+
+static const char *ERR_XBM_SYNTAX = "Syntax error";
+static const char *ERR_XBM_LINE = "Line too long";
+static const char *ERR_XBM_DECL = "Unable to find a line in the file containing the start of C array declaration (\"static char\" or whatever)";
+static const char *ERR_XBM_EOFREAD = "EOF / read error";
+static const char *ERR_XBM_WIDTH = "Invalid width";
+static const char *ERR_XBM_HEIGHT = "Invalid height";
+static const char *ERR_XBM_MEMORY = "Out of memory";
+
+/**
+Get a string from a stream.
+Read the string from the current stream to the first newline character.
+The result stored in str is appended with a null character.
+@param str Storage location for data
+@param n Maximum number of characters to read
+@param io Pointer to the FreeImageIO structure
+@param handle Handle to the stream
+@return Returns str. NULL is returned to indicate an error or an end-of-file condition.
+*/
+static char*
+readLine(char *str, int n, FreeImageIO *io, fi_handle handle) {
+ char c;
+ int count, i = 0;
+ do {
+ count = io->read_proc(&c, 1, 1, handle);
+ str[i++] = c;
+ } while((c != '\n') && (i < n));
+ if(count <= 0)
+ return NULL;
+ str[i] = '\0';
+ return str;
+}
+
+/**
+Get a char from the stream
+@param io Pointer to the FreeImageIO structure
+@param handle Handle to the stream
+@return Returns the next character in the stream
+*/
+static int
+readChar(FreeImageIO *io, fi_handle handle) {
+ BYTE c;
+ io->read_proc(&c, 1, 1, handle);
+ return c;
+}
+
+/**
+Read an XBM file into a buffer
+@param io Pointer to the FreeImageIO structure
+@param handle Handle to the stream
+@param widthP (return value) Pointer to the bitmap width
+@param heightP (return value) Pointer to the bitmap height
+@param dataP (return value) Pointer to the bitmap buffer
+@return Returns NULL if OK, returns an error message otherwise
+*/
+static const char*
+readXBMFile(FreeImageIO *io, fi_handle handle, int *widthP, int *heightP, char **dataP) {
+ char line[MAX_LINE], name_and_type[MAX_LINE];
+ char* ptr;
+ char* t;
+ int version = 0;
+ int raster_length, v;
+ int bytes, bytes_per_line, padding;
+ int c1, c2, value1, value2;
+ int hex_table[256];
+ BOOL found_declaration;
+ /* in scanning through the bitmap file, we have found the first
+ line of the C declaration of the array (the "static char ..."
+ or whatever line)
+ */
+ BOOL eof; // we've encountered end of file while searching file
+
+ *widthP = *heightP = -1;
+
+ found_declaration = FALSE; // haven't found it yet; haven't even looked
+ eof = FALSE; // haven't encountered end of file yet
+
+ while(!found_declaration && !eof) {
+
+ if( readLine(line, MAX_LINE, io, handle) == NULL) {
+ eof = TRUE;
+ }
+ else {
+ if( strlen( line ) == MAX_LINE - 1 )
+ return( ERR_XBM_LINE );
+ if( sscanf(line, "#define %s %d", name_and_type, &v) == 2 ) {
+ if( ( t = strrchr( name_and_type, '_' ) ) == NULL )
+ t = name_and_type;
+ else
+ t++;
+ if ( ! strcmp( "width", t ) )
+ *widthP = v;
+ else if ( ! strcmp( "height", t ) )
+ *heightP = v;
+ continue;
+ }
+
+ if( sscanf( line, "static short %s = {", name_and_type ) == 1 ) {
+ version = 10;
+ found_declaration = TRUE;
+ }
+ else if( sscanf( line, "static char %s = {", name_and_type ) == 1 ) {
+ version = 11;
+ found_declaration = TRUE;
+ }
+ else if(sscanf(line, "static unsigned char %s = {", name_and_type ) == 1 ) {
+ version = 11;
+ found_declaration = TRUE;
+ }
+ }
+ }
+
+ if(!found_declaration)
+ return( ERR_XBM_DECL );
+
+ if(*widthP == -1 )
+ return( ERR_XBM_WIDTH );
+ if( *heightP == -1 )
+ return( ERR_XBM_HEIGHT );
+
+ padding = 0;
+ if ( ((*widthP % 16) >= 1) && ((*widthP % 16) <= 8) && (version == 10) )
+ padding = 1;
+
+ bytes_per_line = (*widthP + 7) / 8 + padding;
+
+ raster_length = bytes_per_line * *heightP;
+ *dataP = (char*) malloc( raster_length );
+ if ( *dataP == (char*) 0 )
+ return( ERR_XBM_MEMORY );
+
+ // initialize hex_table
+ for ( c1 = 0; c1 < 256; c1++ ) {
+ hex_table[c1] = 256;
+ }
+ hex_table['0'] = 0;
+ hex_table['1'] = 1;
+ hex_table['2'] = 2;
+ hex_table['3'] = 3;
+ hex_table['4'] = 4;
+ hex_table['5'] = 5;
+ hex_table['6'] = 6;
+ hex_table['7'] = 7;
+ hex_table['8'] = 8;
+ hex_table['9'] = 9;
+ hex_table['A'] = 10;
+ hex_table['B'] = 11;
+ hex_table['C'] = 12;
+ hex_table['D'] = 13;
+ hex_table['E'] = 14;
+ hex_table['F'] = 15;
+ hex_table['a'] = 10;
+ hex_table['b'] = 11;
+ hex_table['c'] = 12;
+ hex_table['d'] = 13;
+ hex_table['e'] = 14;
+ hex_table['f'] = 15;
+
+ if(version == 10) {
+ for( bytes = 0, ptr = *dataP; bytes < raster_length; bytes += 2 ) {
+ while( ( c1 = readChar(io, handle) ) != 'x' ) {
+ if ( c1 == EOF )
+ return( ERR_XBM_EOFREAD );
+ }
+
+ c1 = readChar(io, handle);
+ c2 = readChar(io, handle);
+ if( c1 == EOF || c2 == EOF )
+ return( ERR_XBM_EOFREAD );
+ value1 = ( hex_table[c1] << 4 ) + hex_table[c2];
+ if ( value1 >= 256 )
+ return( ERR_XBM_SYNTAX );
+ c1 = readChar(io, handle);
+ c2 = readChar(io, handle);
+ if( c1 == EOF || c2 == EOF )
+ return( ERR_XBM_EOFREAD );
+ value2 = ( hex_table[c1] << 4 ) + hex_table[c2];
+ if ( value2 >= 256 )
+ return( ERR_XBM_SYNTAX );
+ *ptr++ = (char)value2;
+ if ( ( ! padding ) || ( ( bytes + 2 ) % bytes_per_line ) )
+ *ptr++ = (char)value1;
+ }
+ }
+ else {
+ for(bytes = 0, ptr = *dataP; bytes < raster_length; bytes++ ) {
+ /*
+ ** skip until digit is found
+ */
+ for( ; ; ) {
+ c1 = readChar(io, handle);
+ if ( c1 == EOF )
+ return( ERR_XBM_EOFREAD );
+ value1 = hex_table[c1];
+ if ( value1 != 256 )
+ break;
+ }
+ /*
+ ** loop on digits
+ */
+ for( ; ; ) {
+ c2 = readChar(io, handle);
+ if ( c2 == EOF )
+ return( ERR_XBM_EOFREAD );
+ value2 = hex_table[c2];
+ if ( value2 != 256 ) {
+ value1 = (value1 << 4) | value2;
+ if ( value1 >= 256 )
+ return( ERR_XBM_SYNTAX );
+ }
+ else if ( c2 == 'x' || c2 == 'X' ) {
+ if ( value1 == 0 )
+ continue;
+ else return( ERR_XBM_SYNTAX );
+ }
+ else break;
+ }
+ *ptr++ = (char)value1;
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "XBM";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "X11 Bitmap Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "xbm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/x-xbitmap";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ char magic[8];
+ if(readLine(magic, 7, io, handle)) {
+ if(strcmp(magic, "#define") == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ char *buffer = NULL;
+ int width, height;
+ FIBITMAP *dib = NULL;
+
+ try {
+
+ // load the bitmap data
+ const char* error = readXBMFile(io, handle, &width, &height, &buffer);
+ // Microsoft doesn't implement throw between functions :(
+ if(error) throw (char*)error;
+
+
+ // allocate a new dib
+ dib = FreeImage_Allocate(width, height, 1);
+ if(!dib) throw (char*)ERR_XBM_MEMORY;
+
+ // write the palette data
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ pal[0].rgbRed = pal[0].rgbGreen = pal[0].rgbBlue = 0;
+ pal[1].rgbRed = pal[1].rgbGreen = pal[1].rgbBlue = 255;
+
+ // copy the bitmap
+ BYTE *bP = (BYTE*)buffer;
+ for(int y = 0; y < height; y++) {
+ BYTE count = 0;
+ BYTE mask = 1;
+ BYTE *bits = FreeImage_GetScanLine(dib, height - 1 - y);
+
+ for(int x = 0; x < width; x++) {
+ if(count >= 8) {
+ bP++;
+ count = 0;
+ mask = 1;
+ }
+ if(*bP & mask) {
+ // Set bit(x, y) to 0
+ bits[x >> 3] &= (0xFF7F >> (x & 0x7));
+ } else {
+ // Set bit(x, y) to 1
+ bits[x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ count++;
+ mask <<= 1;
+ }
+ bP++;
+ }
+
+ free(buffer);
+ return dib;
+
+ } catch(const char *text) {
+ if(buffer) free(buffer);
+ if(dib) FreeImage_Unload(dib);
+ FreeImage_OutputMessageProc(s_format_id, text);
+ return NULL;
+ }
+}
+
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitXBM(Plugin *plugin, int format_id) {
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = NULL;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
+
diff --git a/Source/FreeImage/PluginXPM.cpp b/Source/FreeImage/PluginXPM.cpp
new file mode 100644
index 0000000..c9838c9
--- /dev/null
+++ b/Source/FreeImage/PluginXPM.cpp
@@ -0,0 +1,474 @@
+// ==========================================================
+// XPM Loader and Writer
+//
+// Design and implementation by
+// - Ryan Rubley (ryan@lostreality.org)
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+// IMPLEMENTATION NOTES:
+// ------------------------
+// Initial design and implementation by
+// - Karl-Heinz Bussian (khbussian@moss.de)
+// - Hervé Drolon (drolon@infonie.fr)
+// Completely rewritten from scratch by Ryan Rubley (ryan@lostreality.org)
+// in order to address the following major fixes:
+// * Supports any number of chars per pixel (not just 1 or 2)
+// * Files with 2 chars per pixel but <= 256colors are loaded as 256 color (not 24bit)
+// * Loads much faster, uses much less memory
+// * supports #rgb #rrrgggbbb and #rrrrggggbbbb colors (not just #rrggbb)
+// * supports symbolic color names
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+static int s_format_id;
+
+// ==========================================================
+// Internal Functions
+// ==========================================================
+
+// read in and skip all junk until we find a certain char
+static BOOL
+FindChar(FreeImageIO *io, fi_handle handle, BYTE look_for) {
+ BYTE c;
+ io->read_proc(&c, sizeof(BYTE), 1, handle);
+ while(c != look_for) {
+ if( io->read_proc(&c, sizeof(BYTE), 1, handle) != 1 )
+ return FALSE;
+ }
+ return TRUE;
+}
+
+// find start of string, read data until ending quote found, allocate memory and return a string
+static char *
+ReadString(FreeImageIO *io, fi_handle handle) {
+ if( !FindChar(io, handle,'"') )
+ return NULL;
+ BYTE c;
+ std::string s;
+ io->read_proc(&c, sizeof(BYTE), 1, handle);
+ while(c != '"') {
+ s += c;
+ if( io->read_proc(&c, sizeof(BYTE), 1, handle) != 1 )
+ return NULL;
+ }
+ char *cstr = (char *)malloc(s.length()+1);
+ strcpy(cstr,s.c_str());
+ return cstr;
+}
+
+static char *
+Base92(unsigned int num) {
+ static char b92[16]; //enough for more then 64 bits
+ static char digit[] = " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
+ b92[15] = '\0';
+ int i = 14;
+ do {
+ b92[i--] = digit[num % 92];
+ num /= 92;
+ } while( num && i >= 0 );
+ return b92+i+1;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "XPM";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "X11 Pixmap Format";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "xpm";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return "^[ \\t]*/\\* XPM \\*/[ \\t]$";
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "image/xpm";
+}
+
+static BOOL DLL_CALLCONV
+Validate(FreeImageIO *io, fi_handle handle) {
+ char buffer[256];
+
+ // checks the first 256 characters for the magic string
+ int count = io->read_proc(buffer, 1, 256, handle);
+ if(count <= 9) return FALSE;
+ for(int i = 0; i < (count - 9); i++) {
+ if(strncmp(&buffer[i], "/* XPM */", 9) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return (
+ (depth == 8) ||
+ (depth == 24)
+ );
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return (type == FIT_BITMAP) ? TRUE : FALSE;
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ char msg[256];
+ FIBITMAP *dib = NULL;
+
+ if (!handle) return NULL;
+
+ try {
+ char *str;
+
+ //find the starting brace
+ if( !FindChar(io, handle,'{') )
+ throw "Could not find starting brace";
+
+ //read info string
+ str = ReadString(io, handle);
+ if(!str)
+ throw "Error reading info string";
+
+ int width, height, colors, cpp;
+ if( sscanf(str, "%d %d %d %d", &width, &height, &colors, &cpp) != 4 ) {
+ free(str);
+ throw "Improperly formed info string";
+ }
+ free(str);
+
+ if (colors > 256) {
+ dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dib = FreeImage_Allocate(width, height, 8);
+ }
+
+ //build a map of color chars to rgb values
+ std::map<std::string,FILE_RGBA> rawpal; //will store index in Alpha if 8bpp
+ for(int i = 0; i < colors; i++ ) {
+ FILE_RGBA rgba;
+
+ str = ReadString(io, handle);
+ if(!str)
+ throw "Error reading color strings";
+
+ std::string chrs(str,cpp); //create a string for the color chars using the first cpp chars
+ char *keys = str + cpp; //the color keys for these chars start after the first cpp chars
+
+ //translate all the tabs to spaces
+ char *tmp = keys;
+ while( strchr(tmp,'\t') ) {
+ tmp = strchr(tmp,'\t');
+ *tmp++ = ' ';
+ }
+
+ //prefer the color visual
+ if( strstr(keys," c ") ) {
+ char *clr = strstr(keys," c ") + 3;
+ while( *clr == ' ' ) clr++; //find the start of the hex rgb value
+ if( *clr == '#' ) {
+ int red = 0, green = 0, blue = 0, n;
+ clr++;
+ //end string at first space, if any found
+ if( strchr(clr,' ') )
+ *(strchr(clr,' ')) = '\0';
+ //parse hex color, it can be #rgb #rrggbb #rrrgggbbb or #rrrrggggbbbb
+ switch( strlen(clr) ) {
+ case 3: n = sscanf(clr,"%01x%01x%01x",&red,&green,&blue);
+ red |= (red << 4);
+ green |= (green << 4);
+ blue |= (blue << 4);
+ break;
+ case 6: n = sscanf(clr,"%02x%02x%02x",&red,&green,&blue);
+ break;
+ case 9: n = sscanf(clr,"%03x%03x%03x",&red,&green,&blue);
+ red >>= 4;
+ green >>= 4;
+ blue >>= 4;
+ break;
+ case 12: n = sscanf(clr,"%04x%04x%04x",&red,&green,&blue);
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ break;
+ default:
+ n = 0;
+ break;
+ }
+ if( n != 3 ) {
+ free(str);
+ throw "Improperly formed hex color value";
+ }
+ rgba.r = (BYTE)red;
+ rgba.g = (BYTE)green;
+ rgba.b = (BYTE)blue;
+ } else if( !strncmp(clr,"None",4) || !strncmp(clr,"none",4) ) {
+ rgba.r = rgba.g = rgba.b = 0xFF;
+ } else {
+ char *tmp = clr;
+
+ //scan forward for each space, if its " x " or " xx " end the string there
+ //this means its probably some other visual data beyond that point and not
+ //part of the color name. How many named color end with a 1 or 2 character
+ //word? Probably none in our list at least.
+ while( (tmp = strchr(tmp,' ')) != NULL ) {
+ if( tmp[1] != ' ' ) {
+ if( (tmp[2] == ' ') || (tmp[2] != ' ' && tmp[3] == ' ') ) {
+ tmp[0] = '\0';
+ break;
+ }
+ }
+ tmp++;
+ }
+
+ //remove any trailing spaces
+ tmp = clr+strlen(clr)-1;
+ while( *tmp == ' ' ) {
+ *tmp = '\0';
+ tmp--;
+ }
+
+ if (!FreeImage_LookupX11Color(clr, &rgba.r, &rgba.g, &rgba.b)) {
+ sprintf(msg, "Unknown color name '%s'", str);
+ free(str);
+ throw msg;
+ }
+ }
+ } else {
+ free(str);
+ throw "Only color visuals are supported";
+ }
+
+ //add color to map
+ rgba.a = (BYTE)((colors > 256) ? 0 : i);
+ rawpal[chrs] = rgba;
+
+ //build palette if needed
+ if( colors <= 256 ) {
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ pal[i].rgbBlue = rgba.b;
+ pal[i].rgbGreen = rgba.g;
+ pal[i].rgbRed = rgba.r;
+ }
+
+ free(str);
+ }
+ //done parsing color map
+
+ //read in pixel data
+ for(int y = 0; y < height; y++ ) {
+ BYTE *line = FreeImage_GetScanLine(dib, height - y - 1);
+ str = ReadString(io, handle);
+ if(!str)
+ throw "Error reading pixel strings";
+ char *pixel_ptr = str;
+
+ for(int x = 0; x < width; x++ ) {
+ //locate the chars in the color map
+ std::string chrs(pixel_ptr,cpp);
+ FILE_RGBA rgba = rawpal[chrs];
+
+ if( colors > 256 ) {
+ line[FI_RGBA_BLUE] = rgba.b;
+ line[FI_RGBA_GREEN] = rgba.g;
+ line[FI_RGBA_RED] = rgba.r;
+ line += 3;
+ } else {
+ *line = rgba.a;
+ line++;
+ }
+
+ pixel_ptr += cpp;
+ }
+
+ free(str);
+ }
+ //done reading pixel data
+
+ return dib;
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(s_format_id, text);
+
+ if( dib != NULL )
+ FreeImage_Unload(dib);
+
+ return NULL;
+ }
+}
+
+static BOOL DLL_CALLCONV
+Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
+ if ((dib != NULL) && (handle != NULL)) {
+ char header[] = "/* XPM */\nstatic char *freeimage[] = {\n/* width height num_colors chars_per_pixel */\n\"",
+ start_colors[] = "\",\n/* colors */\n\"",
+ start_pixels[] = "\",\n/* pixels */\n\"",
+ new_line[] = "\",\n\"",
+ footer[] = "\"\n};\n",
+ buf[256]; //256 is more then enough to sprintf 4 ints into, or the base-92 chars and #rrggbb line
+
+ if( io->write_proc(header, (unsigned int)strlen(header), 1, handle) != 1 )
+ return FALSE;
+
+ int width = FreeImage_GetWidth(dib), height = FreeImage_GetHeight(dib), bpp = FreeImage_GetBPP(dib);
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ int x,y;
+
+ //map base92 chrs to the rgb value to create the palette
+ std::map<DWORD,FILE_RGB> chrs2color;
+ //map 8bpp index or 24bpp rgb value to the base92 chrs to create pixel data
+ typedef union {
+ DWORD index;
+ FILE_RGBA rgba;
+ } DWORDRGBA;
+ std::map<DWORD,std::string> color2chrs;
+
+ //loop thru entire dib, if new color, inc num_colors and add to both maps
+ int num_colors = 0;
+ for(y = 0; y < height; y++ ) {
+ BYTE *line = FreeImage_GetScanLine(dib, height - y - 1);
+ for(x = 0; x < width; x++ ) {
+ FILE_RGB rgb;
+ DWORDRGBA u;
+ if( bpp > 8 ) {
+ u.rgba.b = rgb.b = line[FI_RGBA_BLUE];
+ u.rgba.g = rgb.g = line[FI_RGBA_GREEN];
+ u.rgba.r = rgb.r = line[FI_RGBA_RED];
+ u.rgba.a = 0;
+ line += 3;
+ } else {
+ u.index = *line;
+ rgb.b = pal[u.index].rgbBlue;
+ rgb.g = pal[u.index].rgbGreen;
+ rgb.r = pal[u.index].rgbRed;
+ line++;
+ }
+ if( color2chrs.find(u.index) == color2chrs.end() ) { //new color
+ std::string chrs(Base92(num_colors));
+ color2chrs[u.index] = chrs;
+ chrs2color[num_colors] = rgb;
+ num_colors++;
+ }
+ }
+ }
+
+ int cpp = (int)(log((double)num_colors)/log(92.0)) + 1;
+
+ sprintf(buf, "%d %d %d %d", FreeImage_GetWidth(dib), FreeImage_GetHeight(dib), num_colors, cpp );
+ if( io->write_proc(buf, (unsigned int)strlen(buf), 1, handle) != 1 )
+ return FALSE;
+
+ if( io->write_proc(start_colors, (unsigned int)strlen(start_colors), 1, handle) != 1 )
+ return FALSE;
+
+ //write colors, using map of chrs->rgb
+ for(x = 0; x < num_colors; x++ ) {
+ sprintf(buf, "%*s c #%02x%02x%02x", cpp, Base92(x), chrs2color[x].r, chrs2color[x].g, chrs2color[x].b );
+ if( io->write_proc(buf, (unsigned int)strlen(buf), 1, handle) != 1 )
+ return FALSE;
+ if( x == num_colors - 1 ) {
+ if( io->write_proc(start_pixels, (unsigned int)strlen(start_pixels), 1, handle) != 1 )
+ return FALSE;
+ } else {
+ if( io->write_proc(new_line, (unsigned int)strlen(new_line), 1, handle) != 1 )
+ return FALSE;
+ }
+ }
+
+
+ //write pixels, using map of rgb(if 24bpp) or index(if 8bpp)->chrs
+ for(y = 0; y < height; y++ ) {
+ BYTE *line = FreeImage_GetScanLine(dib, height - y - 1);
+ for(x = 0; x < width; x++ ) {
+ DWORDRGBA u;
+ if( bpp > 8 ) {
+ u.rgba.b = line[FI_RGBA_BLUE];
+ u.rgba.g = line[FI_RGBA_GREEN];
+ u.rgba.r = line[FI_RGBA_RED];
+ u.rgba.a = 0;
+ line += 3;
+ } else {
+ u.index = *line;
+ line++;
+ }
+ sprintf(buf, "%*s", cpp, (char *)color2chrs[u.index].c_str());
+ if( io->write_proc(buf, cpp, 1, handle) != 1 )
+ return FALSE;
+ }
+ if( y == height - 1 ) {
+ if( io->write_proc(footer, (unsigned int)strlen(footer), 1, handle) != 1 )
+ return FALSE;
+ } else {
+ if( io->write_proc(new_line, (unsigned int)strlen(new_line), 1, handle) != 1 )
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitXPM(Plugin *plugin, int format_id)
+{
+ s_format_id = format_id;
+
+ plugin->format_proc = Format;
+ plugin->description_proc = Description;
+ plugin->extension_proc = Extension;
+ plugin->regexpr_proc = RegExpr;
+ plugin->open_proc = NULL;
+ plugin->close_proc = NULL;
+ plugin->pagecount_proc = NULL;
+ plugin->pagecapability_proc = NULL;
+ plugin->load_proc = Load;
+ plugin->save_proc = Save;
+ plugin->validate_proc = Validate;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL;
+}
+
diff --git a/Source/FreeImage/TIFFLogLuv.cpp b/Source/FreeImage/TIFFLogLuv.cpp
new file mode 100644
index 0000000..124b25f
--- /dev/null
+++ b/Source/FreeImage/TIFFLogLuv.cpp
@@ -0,0 +1,65 @@
+// ==========================================================
+// XYZ to RGB TIFF conversion routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+void tiff_ConvertLineXYZToRGB(BYTE *target, BYTE *source, double stonits, int width_in_pixels) {
+ FIRGBF *rgbf = (FIRGBF*)target;
+ float *xyz = (float*)source;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ // assume CCIR-709 primaries (matrix from tif_luv.c)
+ // LOG Luv XYZ (D65) -> sRGB (CIE Illuminant E)
+ rgbf->red = (float)( 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]);
+ rgbf->green = (float)(-1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]);
+ rgbf->blue = (float)( 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]);
+
+ /*
+ if (stonits != 0.0) {
+ rgbf->red = (float)(rgbf->red * stonits);
+ rgbf->green = (float)(rgbf->green * stonits);
+ rgbf->blue = (float)(rgbf->blue * stonits);
+ }
+ */
+
+ rgbf++;
+ xyz += 3;
+ }
+}
+
+void tiff_ConvertLineRGBToXYZ(BYTE *target, BYTE *source, int width_in_pixels) {
+ FIRGBF *rgbf = (FIRGBF*)source;
+ float *xyz = (float*)target;
+
+ for (int cols = 0; cols < width_in_pixels; cols++) {
+ // assume CCIR-709 primaries, whitepoint x = 1/3 y = 1/3 (D_E)
+ // "The LogLuv Encoding for Full Gamut, High Dynamic Range Images" <G.Ward>
+ // sRGB ( CIE Illuminant E ) -> LOG Luv XYZ (D65)
+ xyz[0] = (float)(0.497*rgbf->red + 0.339*rgbf->green + 0.164*rgbf->blue);
+ xyz[1] = (float)(0.256*rgbf->red + 0.678*rgbf->green + 0.066*rgbf->blue);
+ xyz[2] = (float)(0.023*rgbf->red + 0.113*rgbf->green + 0.864*rgbf->blue);
+
+ rgbf++;
+ xyz += 3;
+ }
+}
+
diff --git a/Source/FreeImage/ToneMapping.cpp b/Source/FreeImage/ToneMapping.cpp
new file mode 100644
index 0000000..8119b9d
--- /dev/null
+++ b/Source/FreeImage/ToneMapping.cpp
@@ -0,0 +1,75 @@
+// ==========================================================
+// Tone mapping operators
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+/**
+Performs a tone mapping on a 48-bit RGB or a 96-bit RGBF image and returns a 24-bit image.
+The meaning of the parameters depends on the choosen algorithm.
+When both parameters are set to zero, a default set of parameters is used.
+@param dib Input RGB/RGBF image
+@param tmo Tone mapping operator
+@param first_param First parameter of the algorithm
+@param second_param Second parameter of the algorithm
+return Returns a 24-bit tone mapped image if successful, returns NULL otherwise
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_ToneMapping(FIBITMAP *dib, FREE_IMAGE_TMO tmo, double first_param, double second_param) {
+ if(dib) {
+ switch(tmo) {
+ // Adaptive logarithmic mapping (F. Drago, 2003)
+ case FITMO_DRAGO03:
+ if((first_param == 0) && (second_param == 0)) {
+ // use default values (gamma = 2.2, exposure = 0)
+ return FreeImage_TmoDrago03(dib, 2.2, 0);
+ } else {
+ // use user's value
+ return FreeImage_TmoDrago03(dib, first_param, second_param);
+ }
+ break;
+ // Dynamic range reduction inspired by photoreceptor phhysiology (E. Reinhard, 2005)
+ case FITMO_REINHARD05:
+ if((first_param == 0) && (second_param == 0)) {
+ // use default values by setting intensity to 0 and contrast to 0
+ return FreeImage_TmoReinhard05(dib, 0, 0);
+ } else {
+ // use user's value
+ return FreeImage_TmoReinhard05(dib, first_param, second_param);
+ }
+ break;
+ // Gradient Domain HDR Compression (R. Fattal, 2002)
+ case FITMO_FATTAL02:
+ if((first_param == 0) && (second_param == 0)) {
+ // use default values by setting color saturation to 0.5 and attenuation to 0.85
+ return FreeImage_TmoFattal02(dib, 0.5, 0.85);
+ } else {
+ // use user's value
+ return FreeImage_TmoFattal02(dib, first_param, second_param);
+ }
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+
diff --git a/Source/FreeImage/WuQuantizer.cpp b/Source/FreeImage/WuQuantizer.cpp
new file mode 100644
index 0000000..86c8991
--- /dev/null
+++ b/Source/FreeImage/WuQuantizer.cpp
@@ -0,0 +1,537 @@
+///////////////////////////////////////////////////////////////////////
+// C Implementation of Wu's Color Quantizer (v. 2)
+// (see Graphics Gems vol. II, pp. 126-133)
+//
+// Author: Xiaolin Wu
+// Dept. of Computer Science
+// Univ. of Western Ontario
+// London, Ontario N6A 5B7
+// wu@csd.uwo.ca
+//
+// Algorithm: Greedy orthogonal bipartition of RGB space for variance
+// minimization aided by inclusion-exclusion tricks.
+// For speed no nearest neighbor search is done. Slightly
+// better performance can be expected by more sophisticated
+// but more expensive versions.
+//
+// The author thanks Tom Lane at Tom_Lane@G.GP.CS.CMU.EDU for much of
+// additional documentation and a cure to a previous bug.
+//
+// Free to distribute, comments and suggestions are appreciated.
+///////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////
+// History
+// -------
+// July 2000: C++ Implementation of Wu's Color Quantizer
+// and adaptation for the FreeImage 2 Library
+// Author: Hervé Drolon (drolon@infonie.fr)
+// March 2004: Adaptation for the FreeImage 3 library (port to big endian processors)
+// Author: Hervé Drolon (drolon@infonie.fr)
+///////////////////////////////////////////////////////////////////////
+
+#include "Quantizers.h"
+#include "FreeImage.h"
+#include "Utilities.h"
+
+///////////////////////////////////////////////////////////////////////
+
+// 3D array indexation
+
+#define INDEX(r, g, b) ((r << 10) + (r << 6) + r + (g << 5) + g + b)
+
+#define MAXCOLOR 256
+
+// Constructor / Destructor
+
+WuQuantizer::WuQuantizer(FIBITMAP *dib) {
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+ pitch = FreeImage_GetPitch(dib);
+ m_dib = dib;
+
+ gm2 = NULL;
+ wt = mr = mg = mb = NULL;
+ Qadd = NULL;
+
+ // Allocate 3D arrays
+ gm2 = (float*)malloc(33 * 33 * 33 * sizeof(float));
+ wt = (LONG*)malloc(33 * 33 * 33 * sizeof(LONG));
+ mr = (LONG*)malloc(33 * 33 * 33 * sizeof(LONG));
+ mg = (LONG*)malloc(33 * 33 * 33 * sizeof(LONG));
+ mb = (LONG*)malloc(33 * 33 * 33 * sizeof(LONG));
+
+ // Allocate Qadd
+ Qadd = (WORD *)malloc(sizeof(WORD) * width * height);
+
+ if(!gm2 || !wt || !mr || !mg || !mb || !Qadd) {
+ if(gm2) free(gm2);
+ if(wt) free(wt);
+ if(mr) free(mr);
+ if(mg) free(mg);
+ if(mb) free(mb);
+ if(Qadd) free(Qadd);
+ throw FI_MSG_ERROR_MEMORY;
+ }
+ memset(gm2, 0, 35937 * sizeof(float));
+ memset(wt, 0, 35937 * sizeof(LONG));
+ memset(mr, 0, 35937 * sizeof(LONG));
+ memset(mg, 0, 35937 * sizeof(LONG));
+ memset(mb, 0, 35937 * sizeof(LONG));
+ memset(Qadd, 0, sizeof(WORD) * width * height);
+}
+
+WuQuantizer::~WuQuantizer() {
+ if(gm2) free(gm2);
+ if(wt) free(wt);
+ if(mr) free(mr);
+ if(mg) free(mg);
+ if(mb) free(mb);
+ if(Qadd) free(Qadd);
+}
+
+
+// Histogram is in elements 1..HISTSIZE along each axis,
+// element 0 is for base or marginal value
+// NB: these must start out 0!
+
+// Build 3-D color histogram of counts, r/g/b, c^2
+void
+WuQuantizer::Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int ReserveSize, RGBQUAD *ReservePalette) {
+ int ind = 0;
+ int inr, ing, inb, table[256];
+ int i;
+ WORD y, x;
+
+ for(i = 0; i < 256; i++)
+ table[i] = i * i;
+
+ for(y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(m_dib, y);
+
+ for(x = 0; x < width; x++) {
+ inr = (bits[FI_RGBA_RED] >> 3) + 1;
+ ing = (bits[FI_RGBA_GREEN] >> 3) + 1;
+ inb = (bits[FI_RGBA_BLUE] >> 3) + 1;
+ ind = INDEX(inr, ing, inb);
+ Qadd[y*width + x] = (WORD)ind;
+ // [inr][ing][inb]
+ vwt[ind]++;
+ vmr[ind] += bits[FI_RGBA_RED];
+ vmg[ind] += bits[FI_RGBA_GREEN];
+ vmb[ind] += bits[FI_RGBA_BLUE];
+ m2[ind] += (float)(table[bits[FI_RGBA_RED]] + table[bits[FI_RGBA_GREEN]] + table[bits[FI_RGBA_BLUE]]);
+ bits += 3;
+ }
+ }
+
+ if( ReserveSize > 0 ) {
+ int max = 0;
+ for(i = 0; i < 35937; i++) {
+ if( vwt[ind] > max ) max = vwt[ind];
+ }
+ max++;
+ for(i = 0; i < ReserveSize; i++) {
+ inr = (ReservePalette[i].rgbRed >> 3) + 1;
+ ing = (ReservePalette[i].rgbGreen >> 3) + 1;
+ inb = (ReservePalette[i].rgbBlue >> 3) + 1;
+ ind = INDEX(inr, ing, inb);
+ wt[ind] = max;
+ mr[ind] = max * ReservePalette[i].rgbRed;
+ mg[ind] = max * ReservePalette[i].rgbGreen;
+ mb[ind] = max * ReservePalette[i].rgbBlue;
+ gm2[ind] = (float)max * (float)(table[ReservePalette[i].rgbRed] + table[ReservePalette[i].rgbGreen] + table[ReservePalette[i].rgbBlue]);
+ }
+ }
+}
+
+
+// At conclusion of the histogram step, we can interpret
+// wt[r][g][b] = sum over voxel of P(c)
+// mr[r][g][b] = sum over voxel of r*P(c) , similarly for mg, mb
+// m2[r][g][b] = sum over voxel of c^2*P(c)
+// Actually each of these should be divided by 'ImageSize' to give the usual
+// interpretation of P() as ranging from 0 to 1, but we needn't do that here.
+
+
+// We now convert histogram into moments so that we can rapidly calculate
+// the sums of the above quantities over any desired box.
+
+// Compute cumulative moments
+void
+WuQuantizer::M3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2) {
+ WORD ind1, ind2;
+ BYTE i, r, g, b;
+ LONG line, line_r, line_g, line_b;
+ LONG area[33], area_r[33], area_g[33], area_b[33];
+ float line2, area2[33];
+
+ for(r = 1; r <= 32; r++) {
+ for(i = 0; i <= 32; i++) {
+ area2[i] = 0;
+ area[i] = area_r[i] = area_g[i] = area_b[i] = 0;
+ }
+ for(g = 1; g <= 32; g++) {
+ line2 = 0;
+ line = line_r = line_g = line_b = 0;
+ for(b = 1; b <= 32; b++) {
+ ind1 = INDEX(r, g, b); // [r][g][b]
+ line += vwt[ind1];
+ line_r += vmr[ind1];
+ line_g += vmg[ind1];
+ line_b += vmb[ind1];
+ line2 += m2[ind1];
+ area[b] += line;
+ area_r[b] += line_r;
+ area_g[b] += line_g;
+ area_b[b] += line_b;
+ area2[b] += line2;
+ ind2 = ind1 - 1089; // [r-1][g][b]
+ vwt[ind1] = vwt[ind2] + area[b];
+ vmr[ind1] = vmr[ind2] + area_r[b];
+ vmg[ind1] = vmg[ind2] + area_g[b];
+ vmb[ind1] = vmb[ind2] + area_b[b];
+ m2[ind1] = m2[ind2] + area2[b];
+ }
+ }
+ }
+}
+
+// Compute sum over a box of any given statistic
+LONG
+WuQuantizer::Vol( Box *cube, LONG *mmt ) {
+ return( mmt[INDEX(cube->r1, cube->g1, cube->b1)]
+ - mmt[INDEX(cube->r1, cube->g1, cube->b0)]
+ - mmt[INDEX(cube->r1, cube->g0, cube->b1)]
+ + mmt[INDEX(cube->r1, cube->g0, cube->b0)]
+ - mmt[INDEX(cube->r0, cube->g1, cube->b1)]
+ + mmt[INDEX(cube->r0, cube->g1, cube->b0)]
+ + mmt[INDEX(cube->r0, cube->g0, cube->b1)]
+ - mmt[INDEX(cube->r0, cube->g0, cube->b0)] );
+}
+
+// The next two routines allow a slightly more efficient calculation
+// of Vol() for a proposed subbox of a given box. The sum of Top()
+// and Bottom() is the Vol() of a subbox split in the given direction
+// and with the specified new upper bound.
+
+
+// Compute part of Vol(cube, mmt) that doesn't depend on r1, g1, or b1
+// (depending on dir)
+
+LONG
+WuQuantizer::Bottom(Box *cube, BYTE dir, LONG *mmt) {
+ switch(dir)
+ {
+ case FI_RGBA_RED:
+ return( - mmt[INDEX(cube->r0, cube->g1, cube->b1)]
+ + mmt[INDEX(cube->r0, cube->g1, cube->b0)]
+ + mmt[INDEX(cube->r0, cube->g0, cube->b1)]
+ - mmt[INDEX(cube->r0, cube->g0, cube->b0)] );
+ break;
+ case FI_RGBA_GREEN:
+ return( - mmt[INDEX(cube->r1, cube->g0, cube->b1)]
+ + mmt[INDEX(cube->r1, cube->g0, cube->b0)]
+ + mmt[INDEX(cube->r0, cube->g0, cube->b1)]
+ - mmt[INDEX(cube->r0, cube->g0, cube->b0)] );
+ break;
+ case FI_RGBA_BLUE:
+ return( - mmt[INDEX(cube->r1, cube->g1, cube->b0)]
+ + mmt[INDEX(cube->r1, cube->g0, cube->b0)]
+ + mmt[INDEX(cube->r0, cube->g1, cube->b0)]
+ - mmt[INDEX(cube->r0, cube->g0, cube->b0)] );
+ break;
+ }
+
+ return 0;
+}
+
+
+// Compute remainder of Vol(cube, mmt), substituting pos for
+// r1, g1, or b1 (depending on dir)
+
+LONG
+WuQuantizer::Top(Box *cube, BYTE dir, int pos, LONG *mmt) {
+ switch(dir)
+ {
+ case FI_RGBA_RED:
+ return( mmt[INDEX(pos, cube->g1, cube->b1)]
+ -mmt[INDEX(pos, cube->g1, cube->b0)]
+ -mmt[INDEX(pos, cube->g0, cube->b1)]
+ +mmt[INDEX(pos, cube->g0, cube->b0)] );
+ break;
+ case FI_RGBA_GREEN:
+ return( mmt[INDEX(cube->r1, pos, cube->b1)]
+ -mmt[INDEX(cube->r1, pos, cube->b0)]
+ -mmt[INDEX(cube->r0, pos, cube->b1)]
+ +mmt[INDEX(cube->r0, pos, cube->b0)] );
+ break;
+ case FI_RGBA_BLUE:
+ return( mmt[INDEX(cube->r1, cube->g1, pos)]
+ -mmt[INDEX(cube->r1, cube->g0, pos)]
+ -mmt[INDEX(cube->r0, cube->g1, pos)]
+ +mmt[INDEX(cube->r0, cube->g0, pos)] );
+ break;
+ }
+
+ return 0;
+}
+
+// Compute the weighted variance of a box
+// NB: as with the raw statistics, this is really the variance * ImageSize
+
+float
+WuQuantizer::Var(Box *cube) {
+ float dr = (float) Vol(cube, mr);
+ float dg = (float) Vol(cube, mg);
+ float db = (float) Vol(cube, mb);
+ float xx = gm2[INDEX(cube->r1, cube->g1, cube->b1)]
+ -gm2[INDEX(cube->r1, cube->g1, cube->b0)]
+ -gm2[INDEX(cube->r1, cube->g0, cube->b1)]
+ +gm2[INDEX(cube->r1, cube->g0, cube->b0)]
+ -gm2[INDEX(cube->r0, cube->g1, cube->b1)]
+ +gm2[INDEX(cube->r0, cube->g1, cube->b0)]
+ +gm2[INDEX(cube->r0, cube->g0, cube->b1)]
+ -gm2[INDEX(cube->r0, cube->g0, cube->b0)];
+
+ return (xx - (dr*dr+dg*dg+db*db)/(float)Vol(cube,wt));
+}
+
+// We want to minimize the sum of the variances of two subboxes.
+// The sum(c^2) terms can be ignored since their sum over both subboxes
+// is the same (the sum for the whole box) no matter where we split.
+// The remaining terms have a minus sign in the variance formula,
+// so we drop the minus sign and MAXIMIZE the sum of the two terms.
+
+float
+WuQuantizer::Maximize(Box *cube, BYTE dir, int first, int last , int *cut, LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w) {
+ LONG half_r, half_g, half_b, half_w;
+ int i;
+ float temp;
+
+ LONG base_r = Bottom(cube, dir, mr);
+ LONG base_g = Bottom(cube, dir, mg);
+ LONG base_b = Bottom(cube, dir, mb);
+ LONG base_w = Bottom(cube, dir, wt);
+
+ float max = 0.0;
+
+ *cut = -1;
+
+ for (i = first; i < last; i++) {
+ half_r = base_r + Top(cube, dir, i, mr);
+ half_g = base_g + Top(cube, dir, i, mg);
+ half_b = base_b + Top(cube, dir, i, mb);
+ half_w = base_w + Top(cube, dir, i, wt);
+
+ // now half_x is sum over lower half of box, if split at i
+
+ if (half_w == 0) { // subbox could be empty of pixels!
+ continue; // never split into an empty box
+ } else {
+ temp = ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w;
+ }
+
+ half_r = whole_r - half_r;
+ half_g = whole_g - half_g;
+ half_b = whole_b - half_b;
+ half_w = whole_w - half_w;
+
+ if (half_w == 0) { // subbox could be empty of pixels!
+ continue; // never split into an empty box
+ } else {
+ temp += ((float)half_r*half_r + (float)half_g*half_g + (float)half_b*half_b)/half_w;
+ }
+
+ if (temp > max) {
+ max=temp;
+ *cut=i;
+ }
+ }
+
+ return max;
+}
+
+bool
+WuQuantizer::Cut(Box *set1, Box *set2) {
+ BYTE dir;
+ int cutr, cutg, cutb;
+
+ LONG whole_r = Vol(set1, mr);
+ LONG whole_g = Vol(set1, mg);
+ LONG whole_b = Vol(set1, mb);
+ LONG whole_w = Vol(set1, wt);
+
+ float maxr = Maximize(set1, FI_RGBA_RED, set1->r0+1, set1->r1, &cutr, whole_r, whole_g, whole_b, whole_w);
+ float maxg = Maximize(set1, FI_RGBA_GREEN, set1->g0+1, set1->g1, &cutg, whole_r, whole_g, whole_b, whole_w);
+ float maxb = Maximize(set1, FI_RGBA_BLUE, set1->b0+1, set1->b1, &cutb, whole_r, whole_g, whole_b, whole_w);
+
+ if ((maxr >= maxg) && (maxr >= maxb)) {
+ dir = FI_RGBA_RED;
+
+ if (cutr < 0) {
+ return false; // can't split the box
+ }
+ } else if ((maxg >= maxr) && (maxg>=maxb)) {
+ dir = FI_RGBA_GREEN;
+ } else {
+ dir = FI_RGBA_BLUE;
+ }
+
+ set2->r1 = set1->r1;
+ set2->g1 = set1->g1;
+ set2->b1 = set1->b1;
+
+ switch (dir) {
+ case FI_RGBA_RED:
+ set2->r0 = set1->r1 = cutr;
+ set2->g0 = set1->g0;
+ set2->b0 = set1->b0;
+ break;
+
+ case FI_RGBA_GREEN:
+ set2->g0 = set1->g1 = cutg;
+ set2->r0 = set1->r0;
+ set2->b0 = set1->b0;
+ break;
+
+ case FI_RGBA_BLUE:
+ set2->b0 = set1->b1 = cutb;
+ set2->r0 = set1->r0;
+ set2->g0 = set1->g0;
+ break;
+ }
+
+ set1->vol = (set1->r1-set1->r0)*(set1->g1-set1->g0)*(set1->b1-set1->b0);
+ set2->vol = (set2->r1-set2->r0)*(set2->g1-set2->g0)*(set2->b1-set2->b0);
+
+ return true;
+}
+
+
+void
+WuQuantizer::Mark(Box *cube, int label, BYTE *tag) {
+ for (int r = cube->r0 + 1; r <= cube->r1; r++) {
+ for (int g = cube->g0 + 1; g <= cube->g1; g++) {
+ for (int b = cube->b0 + 1; b <= cube->b1; b++) {
+ tag[INDEX(r, g, b)] = (BYTE)label;
+ }
+ }
+ }
+}
+
+// Wu Quantization algorithm
+FIBITMAP *
+WuQuantizer::Quantize(int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette) {
+ BYTE *tag = NULL;
+
+ try {
+ Box cube[MAXCOLOR];
+ int next;
+ LONG i, weight;
+ int k;
+ float vv[MAXCOLOR], temp;
+
+ // Compute 3D histogram
+
+ Hist3D(wt, mr, mg, mb, gm2, ReserveSize, ReservePalette);
+
+ // Compute moments
+
+ M3D(wt, mr, mg, mb, gm2);
+
+ cube[0].r0 = cube[0].g0 = cube[0].b0 = 0;
+ cube[0].r1 = cube[0].g1 = cube[0].b1 = 32;
+ next = 0;
+
+ for (i = 1; i < PaletteSize; i++) {
+ if(Cut(&cube[next], &cube[i])) {
+ // volume test ensures we won't try to cut one-cell box
+ vv[next] = (cube[next].vol > 1) ? Var(&cube[next]) : 0;
+ vv[i] = (cube[i].vol > 1) ? Var(&cube[i]) : 0;
+ } else {
+ vv[next] = 0.0; // don't try to split this box again
+ i--; // didn't create box i
+ }
+
+ next = 0; temp = vv[0];
+
+ for (k = 1; k <= i; k++) {
+ if (vv[k] > temp) {
+ temp = vv[k]; next = k;
+ }
+ }
+
+ if (temp <= 0.0) {
+ PaletteSize = i + 1;
+
+ // Error: "Only got 'PaletteSize' boxes"
+
+ break;
+ }
+ }
+
+ // Partition done
+
+ // the space for array gm2 can be freed now
+
+ free(gm2);
+
+ gm2 = NULL;
+
+ // Allocate a new dib
+
+ FIBITMAP *new_dib = FreeImage_Allocate(width, height, 8);
+
+ if (new_dib == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ // create an optimized palette
+
+ RGBQUAD *new_pal = FreeImage_GetPalette(new_dib);
+
+ tag = (BYTE*) malloc(33 * 33 * 33 * sizeof(BYTE));
+ memset(tag, 0, 33 * 33 * 33 * sizeof(BYTE));
+
+ if (tag == NULL) {
+ throw FI_MSG_ERROR_MEMORY;
+ }
+
+ for (k = 0; k < PaletteSize ; k++) {
+ Mark(&cube[k], k, tag);
+ weight = Vol(&cube[k], wt);
+
+ if (weight) {
+ new_pal[k].rgbRed = (BYTE)(((float)Vol(&cube[k], mr) / (float)weight) + 0.5f);
+ new_pal[k].rgbGreen = (BYTE)(((float)Vol(&cube[k], mg) / (float)weight) + 0.5f);
+ new_pal[k].rgbBlue = (BYTE)(((float)Vol(&cube[k], mb) / (float)weight) + 0.5f);
+ } else {
+ // Error: bogus box 'k'
+
+ new_pal[k].rgbRed = new_pal[k].rgbGreen = new_pal[k].rgbBlue = 0;
+ }
+ }
+
+ int npitch = FreeImage_GetPitch(new_dib);
+
+ for (WORD y = 0; y < height; y++) {
+ BYTE *new_bits = FreeImage_GetBits(new_dib) + (y * npitch);
+
+ for (WORD x = 0; x < width; x++) {
+ new_bits[x] = tag[Qadd[y*width + x]];
+ }
+ }
+
+ // output 'new_pal' as color look-up table contents,
+ // 'new_bits' as the quantized image (array of table addresses).
+
+ free(tag);
+
+ return (FIBITMAP*) new_dib;
+ } catch(...) {
+ free(tag);
+ }
+
+ return NULL;
+}
diff --git a/Source/FreeImage/ZLibInterface.cpp b/Source/FreeImage/ZLibInterface.cpp
new file mode 100644
index 0000000..5a147df
--- /dev/null
+++ b/Source/FreeImage/ZLibInterface.cpp
@@ -0,0 +1,229 @@
+// ==========================================================
+// ZLib library interface
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include <zlib.h>
+#include "FreeImage.h"
+#include "Utilities.h"
+#ifdef __APPLE__
+#include "zutil.h"
+#elif defined(WIN32) || defined(_WIN32)
+#include <zutil.h> /* must be the last header because of error C3163 in VS2008 (_vsnprintf defined in stdio.h) */
+#else
+#include "../../../zlib-1.2.3/zutil.h"
+#endif
+
+/**
+Compresses a source buffer into a target buffer, using the ZLib library.
+Upon entry, target_size is the total size of the destination buffer,
+which must be at least 0.1% larger than source_size plus 12 bytes.
+
+@param target Destination buffer
+@param target_size Size of the destination buffer, in bytes
+@param source Source buffer
+@param source_size Size of the source buffer, in bytes
+@return Returns the actual size of the compressed buffer, returns 0 if an error occured
+@see FreeImage_ZLibUncompress
+*/
+DWORD DLL_CALLCONV
+FreeImage_ZLibCompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
+ uLongf dest_len = (uLongf)target_size;
+
+ int zerr = compress(target, &dest_len, source, source_size);
+ switch(zerr) {
+ case Z_MEM_ERROR: // not enough memory
+ case Z_BUF_ERROR: // not enough room in the output buffer
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
+ return 0;
+ case Z_OK:
+ return dest_len;
+ }
+
+ return 0;
+}
+
+/**
+Decompresses a source buffer into a target buffer, using the ZLib library.
+Upon entry, target_size is the total size of the destination buffer,
+which must be large enough to hold the entire uncompressed data.
+The size of the uncompressed data must have been saved previously by the compressor
+and transmitted to the decompressor by some mechanism outside the scope of this
+compression library.
+
+@param target Destination buffer
+@param target_size Size of the destination buffer, in bytes
+@param source Source buffer
+@param source_size Size of the source buffer, in bytes
+@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
+@see FreeImage_ZLibCompress
+*/
+DWORD DLL_CALLCONV
+FreeImage_ZLibUncompress(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
+ uLongf dest_len = (uLongf)target_size;
+
+ int zerr = uncompress(target, &dest_len, source, source_size);
+ switch(zerr) {
+ case Z_MEM_ERROR: // not enough memory
+ case Z_BUF_ERROR: // not enough room in the output buffer
+ case Z_DATA_ERROR: // input data was corrupted
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
+ return 0;
+ case Z_OK:
+ return dest_len;
+ }
+
+ return 0;
+}
+
+/**
+Compresses a source buffer into a target buffer, using the ZLib library.
+On success, the target buffer contains a GZIP compatible layout.
+Upon entry, target_size is the total size of the destination buffer,
+which must be at least 0.1% larger than source_size plus 24 bytes.
+
+@param target Destination buffer
+@param target_size Size of the destination buffer, in bytes
+@param source Source buffer
+@param source_size Size of the source buffer, in bytes
+@return Returns the actual size of the compressed buffer, returns 0 if an error occured
+@see FreeImage_ZLibCompress
+*/
+DWORD DLL_CALLCONV
+FreeImage_ZLibGZip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
+ uLongf dest_len = (uLongf)target_size - 12;
+ DWORD crc = crc32(0L, NULL, 0);
+
+ // set up header (stolen from zlib/gzio.c)
+ sprintf((char *)target, "%c%c%c%c%c%c%c%c", 0x1f, 0x8b,
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/);
+ int zerr = compress2(target + 8, &dest_len, source, source_size, Z_BEST_COMPRESSION);
+ switch(zerr) {
+ case Z_MEM_ERROR: // not enough memory
+ case Z_BUF_ERROR: // not enough room in the output buffer
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
+ return 0;
+ case Z_OK: {
+ // patch header, setup crc and length (stolen from mod_trace_output)
+ BYTE *p = target + 8; *p++ = 2; *p = OS_CODE; // xflags, os_code
+ crc = crc32(crc, source, source_size);
+ memcpy(target + 4 + dest_len, &crc, 4);
+ memcpy(target + 8 + dest_len, &source_size, 4);
+ return dest_len + 12;
+ }
+ }
+ return 0;
+}
+
+/**
+Decompresses a gzipped source buffer into a target buffer, using the ZLib library.
+Upon entry, target_size is the total size of the destination buffer,
+which must be large enough to hold the entire uncompressed data.
+The size of the uncompressed data must have been saved previously by the compressor
+and transmitted to the decompressor by some mechanism outside the scope of this
+compression library.
+
+@param target Destination buffer
+@param target_size Size of the destination buffer, in bytes
+@param source Source buffer
+@param source_size Size of the source buffer, in bytes
+@return Returns the actual size of the uncompressed buffer, returns 0 if an error occured
+@see FreeImage_ZLibGZip
+*/
+
+static int get_byte(z_stream *stream) {
+ if (stream->avail_in <= 0) return EOF;
+ stream->avail_in--;
+ return *(stream->next_in)++;
+}
+
+static int checkheader(z_stream *stream) {
+ int flags, c;
+ DWORD len;
+
+ if (get_byte(stream) != 0x1f || get_byte(stream) != 0x8b)
+ return Z_DATA_ERROR;
+ if (get_byte(stream) != Z_DEFLATED || ((flags = get_byte(stream)) & 0xE0) != 0)
+ return Z_DATA_ERROR;
+ for (len = 0; len < 6; len++) (void)get_byte(stream);
+
+ if ((flags & 0x04) != 0) { /* skip the extra field */
+ len = (DWORD)get_byte(stream);
+ len += ((DWORD)get_byte(stream)) << 8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(stream) != EOF) ;
+ }
+ if ((flags & 0x08) != 0) { /* skip the original file name */
+ while ((c = get_byte(stream)) != 0 && c != EOF) ;
+ }
+ if ((flags & 0x10) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(stream)) != 0 && c != EOF) ;
+ }
+ if ((flags & 0x02) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(stream);
+ }
+ return Z_OK;
+}
+
+DWORD DLL_CALLCONV
+FreeImage_ZLibGUnzip(BYTE *target, DWORD target_size, BYTE *source, DWORD source_size) {
+ DWORD src_len = source_size;
+ DWORD dest_len = target_size;
+ int zerr = Z_DATA_ERROR;
+
+ if (src_len > 0) {
+ z_stream stream;
+ memset(&stream, 0, sizeof (stream));
+ if ((zerr = inflateInit2(&stream, -MAX_WBITS)) == Z_OK) {
+ stream.next_in = source;
+ stream.avail_in = source_size;
+
+ stream.next_out = target;
+ stream.avail_out = target_size;
+
+ if ((zerr = checkheader(&stream)) == Z_OK) {
+ zerr = inflate (&stream, Z_NO_FLUSH);
+ dest_len = target_size - stream.avail_out;
+
+ if (zerr == Z_OK || zerr == Z_STREAM_END)
+ inflateEnd(&stream);
+ }
+ }
+ }
+ if (zerr != Z_OK && zerr != Z_STREAM_END) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Zlib error : %s", zError(zerr));
+ return 0;
+ }
+ return dest_len;
+}
+
+/**
+Update a running crc from source and return the updated crc, using the ZLib library.
+If source is NULL, this function returns the required initial value for the crc.
+
+@param crc Running crc value
+@param source Source buffer
+@param source_size Size of the source buffer, in bytes
+@return Returns the new crc value
+*/
+DWORD DLL_CALLCONV
+FreeImage_ZLibCRC32(DWORD crc, BYTE *source, DWORD source_size) {
+
+ return crc32(crc, source, source_size);
+}
diff --git a/Source/FreeImage/tmoColorConvert.cpp b/Source/FreeImage/tmoColorConvert.cpp
new file mode 100644
index 0000000..ae8dcda
--- /dev/null
+++ b/Source/FreeImage/tmoColorConvert.cpp
@@ -0,0 +1,479 @@
+// ==========================================================
+// High Dynamic Range bitmap conversion routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "ToneMapping.h"
+
+// ----------------------------------------------------------
+// Convert RGB to and from Yxy, same as in Reinhard et al. SIGGRAPH 2002
+// References :
+// [1] Radiance Home Page [Online] http://radsite.lbl.gov/radiance/HOME.html
+// [2] E. Reinhard, M. Stark, P. Shirley, and J. Ferwerda,
+// Photographic Tone Reproduction for Digital Images, ACM Transactions on Graphics,
+// 21(3):267-276, 2002 (Proceedings of SIGGRAPH 2002).
+// [3] J. Tumblin and H.E. Rushmeier,
+// Tone Reproduction for Realistic Images. IEEE Computer Graphics and Applications,
+// 13(6):42-48, 1993.
+// ----------------------------------------------------------
+
+/**
+nominal CRT primaries
+*/
+/*
+static const float CIE_x_r = 0.640F;
+static const float CIE_y_r = 0.330F;
+static const float CIE_x_g = 0.290F;
+static const float CIE_y_g = 0.600F;
+static const float CIE_x_b = 0.150F;
+static const float CIE_y_b = 0.060F;
+static const float CIE_x_w = 0.3333F; // use true white
+static const float CIE_y_w = 0.3333F;
+*/
+/**
+sRGB primaries
+*/
+static const float CIE_x_r = 0.640F;
+static const float CIE_y_r = 0.330F;
+static const float CIE_x_g = 0.300F;
+static const float CIE_y_g = 0.600F;
+static const float CIE_x_b = 0.150F;
+static const float CIE_y_b = 0.060F;
+static const float CIE_x_w = 0.3127F; // Illuminant D65
+static const float CIE_y_w = 0.3290F;
+
+static const float CIE_D = ( CIE_x_r*(CIE_y_g - CIE_y_b) + CIE_x_g*(CIE_y_b - CIE_y_r) + CIE_x_b*(CIE_y_r - CIE_y_g) );
+static const float CIE_C_rD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_g - CIE_y_b) - CIE_y_w*(CIE_x_g - CIE_x_b) + CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) );
+static const float CIE_C_gD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_b - CIE_y_r) - CIE_y_w*(CIE_x_b - CIE_x_r) - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) );
+static const float CIE_C_bD = ( (1/CIE_y_w) * ( CIE_x_w*(CIE_y_r - CIE_y_g) - CIE_y_w*(CIE_x_r - CIE_x_g) + CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) );
+
+/**
+RGB to XYZ (no white balance)
+*/
+static const float RGB2XYZ[3][3] = {
+ { CIE_x_r*CIE_C_rD / CIE_D,
+ CIE_x_g*CIE_C_gD / CIE_D,
+ CIE_x_b*CIE_C_bD / CIE_D
+ },
+ { CIE_y_r*CIE_C_rD / CIE_D,
+ CIE_y_g*CIE_C_gD / CIE_D,
+ CIE_y_b*CIE_C_bD / CIE_D
+ },
+ { (1 - CIE_x_r-CIE_y_r)*CIE_C_rD / CIE_D,
+ (1 - CIE_x_g-CIE_y_g)*CIE_C_gD / CIE_D,
+ (1 - CIE_x_b-CIE_y_b)*CIE_C_bD / CIE_D
+ }
+};
+
+/**
+XYZ to RGB (no white balance)
+*/
+static const float XYZ2RGB[3][3] = {
+ {(CIE_y_g - CIE_y_b - CIE_x_b*CIE_y_g + CIE_y_b*CIE_x_g) / CIE_C_rD,
+ (CIE_x_b - CIE_x_g - CIE_x_b*CIE_y_g + CIE_x_g*CIE_y_b) / CIE_C_rD,
+ (CIE_x_g*CIE_y_b - CIE_x_b*CIE_y_g) / CIE_C_rD
+ },
+ {(CIE_y_b - CIE_y_r - CIE_y_b*CIE_x_r + CIE_y_r*CIE_x_b) / CIE_C_gD,
+ (CIE_x_r - CIE_x_b - CIE_x_r*CIE_y_b + CIE_x_b*CIE_y_r) / CIE_C_gD,
+ (CIE_x_b*CIE_y_r - CIE_x_r*CIE_y_b) / CIE_C_gD
+ },
+ {(CIE_y_r - CIE_y_g - CIE_y_r*CIE_x_g + CIE_y_g*CIE_x_r) / CIE_C_bD,
+ (CIE_x_g - CIE_x_r - CIE_x_g*CIE_y_r + CIE_x_r*CIE_y_g) / CIE_C_bD,
+ (CIE_x_r*CIE_y_g - CIE_x_g*CIE_y_r) / CIE_C_bD
+ }
+};
+
+/**
+This gives approximately the following matrices :
+
+static const float RGB2XYZ[3][3] = {
+ { 0.41239083F, 0.35758433F, 0.18048081F },
+ { 0.21263903F, 0.71516865F, 0.072192319F },
+ { 0.019330820F, 0.11919473F, 0.95053220F }
+};
+static const float XYZ2RGB[3][3] = {
+ { 3.2409699F, -1.5373832F, -0.49861079F },
+ { -0.96924376F, 1.8759676F, 0.041555084F },
+ { 0.055630036F, -0.20397687F, 1.0569715F }
+};
+*/
+
+// ----------------------------------------------------------
+
+static const float EPSILON = 1e-06F;
+static const float INF = 1e+10F;
+
+/**
+Convert in-place floating point RGB data to Yxy.<br>
+On output, pixel->red == Y, pixel->green == x, pixel->blue == y
+@param dib Input RGBF / Output Yxy image
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+BOOL
+ConvertInPlaceRGBFToYxy(FIBITMAP *dib) {
+ float result[3];
+
+ if(FreeImage_GetImageType(dib) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned pitch = FreeImage_GetPitch(dib);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(dib);
+ for(unsigned y = 0; y < height; y++) {
+ FIRGBF *pixel = (FIRGBF*)bits;
+ for(unsigned x = 0; x < width; x++) {
+ result[0] = result[1] = result[2] = 0;
+ for (int i = 0; i < 3; i++) {
+ result[i] += RGB2XYZ[i][0] * pixel[x].red;
+ result[i] += RGB2XYZ[i][1] * pixel[x].green;
+ result[i] += RGB2XYZ[i][2] * pixel[x].blue;
+ }
+ float W = result[0] + result[1] + result[2];
+ float Y = result[1];
+ if(W > 0) {
+ pixel[x].red = Y; // Y
+ pixel[x].green = result[0] / W; // x
+ pixel[x].blue = result[1] / W; // y
+ } else {
+ pixel[x].red = pixel[x].green = pixel[x].blue = 0;
+ }
+ }
+ // next line
+ bits += pitch;
+ }
+
+ return TRUE;
+}
+
+/**
+Convert in-place Yxy image to floating point RGB data.<br>
+On input, pixel->red == Y, pixel->green == x, pixel->blue == y
+@param dib Input Yxy / Output RGBF image
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+BOOL
+ConvertInPlaceYxyToRGBF(FIBITMAP *dib) {
+ float result[3];
+ float X, Y, Z;
+
+ if(FreeImage_GetImageType(dib) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned pitch = FreeImage_GetPitch(dib);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(dib);
+ for(unsigned y = 0; y < height; y++) {
+ FIRGBF *pixel = (FIRGBF*)bits;
+ for(unsigned x = 0; x < width; x++) {
+ Y = pixel[x].red; // Y
+ result[1] = pixel[x].green; // x
+ result[2] = pixel[x].blue; // y
+ if ((Y > EPSILON) && (result[1] > EPSILON) && (result[2] > EPSILON)) {
+ X = (result[1] * Y) / result[2];
+ Z = (X / result[1]) - X - Y;
+ } else {
+ X = Z = EPSILON;
+ }
+ pixel[x].red = X;
+ pixel[x].green = Y;
+ pixel[x].blue = Z;
+ result[0] = result[1] = result[2] = 0;
+ for (int i = 0; i < 3; i++) {
+ result[i] += XYZ2RGB[i][0] * pixel[x].red;
+ result[i] += XYZ2RGB[i][1] * pixel[x].green;
+ result[i] += XYZ2RGB[i][2] * pixel[x].blue;
+ }
+ pixel[x].red = result[0]; // R
+ pixel[x].green = result[1]; // G
+ pixel[x].blue = result[2]; // B
+ }
+ // next line
+ bits += pitch;
+ }
+
+ return TRUE;
+}
+
+/**
+Get the maximum, minimum and average luminance.<br>
+On input, pixel->red == Y, pixel->green == x, pixel->blue == y
+@param Yxy Source Yxy image to analyze
+@param maxLum Maximum luminance
+@param minLum Minimum luminance
+@param worldLum Average luminance (world adaptation luminance)
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+BOOL
+LuminanceFromYxy(FIBITMAP *Yxy, float *maxLum, float *minLum, float *worldLum) {
+ if(FreeImage_GetImageType(Yxy) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(Yxy);
+ unsigned height = FreeImage_GetHeight(Yxy);
+ unsigned pitch = FreeImage_GetPitch(Yxy);
+
+ float max_lum = 0, min_lum = 0;
+ double sum = 0;
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(Yxy);
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGBF *pixel = (FIRGBF*)bits;
+ for(unsigned x = 0; x < width; x++) {
+ const float Y = pixel[x].red;
+ max_lum = (max_lum < Y) ? Y : max_lum; // max Luminance in the scene
+ min_lum = (min_lum < Y) ? min_lum : Y; // min Luminance in the scene
+ sum += log(2.3e-5 + Y); // contrast constant in Tumblin paper
+ }
+ // next line
+ bits += pitch;
+ }
+ // maximum luminance
+ *maxLum = max_lum;
+ // minimum luminance
+ *minLum = min_lum;
+ // average log luminance
+ double avgLogLum = (sum / (width * height));
+ // world adaptation luminance
+ *worldLum = (float)exp(avgLogLum);
+
+ return TRUE;
+}
+
+/**
+Clamp RGBF image highest values to display white,
+then convert to 24-bit RGB
+*/
+FIBITMAP*
+ClampConvertRGBFTo24(FIBITMAP *src) {
+ if(FreeImage_GetImageType(src) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ FIBITMAP *dst = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(!dst) return NULL;
+
+ unsigned src_pitch = FreeImage_GetPitch(src);
+ unsigned dst_pitch = FreeImage_GetPitch(dst);
+
+ BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGBF *src_pixel = (FIRGBF*)src_bits;
+ BYTE *dst_pixel = (BYTE*)dst_bits;
+ for(unsigned x = 0; x < width; x++) {
+ const float red = (src_pixel[x].red > 1) ? 1 : src_pixel[x].red;
+ const float green = (src_pixel[x].green > 1) ? 1 : src_pixel[x].green;
+ const float blue = (src_pixel[x].blue > 1) ? 1 : src_pixel[x].blue;
+
+ dst_pixel[FI_RGBA_RED] = (BYTE)(255 * red + 0.5);
+ dst_pixel[FI_RGBA_GREEN] = (BYTE)(255 * green + 0.5);
+ dst_pixel[FI_RGBA_BLUE] = (BYTE)(255 * blue + 0.5);
+ dst_pixel += 3;
+ }
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+
+ return dst;
+}
+
+/**
+Extract the luminance channel L from a RGBF image.
+Luminance is calculated from the sRGB model (RGB2XYZ matrix)
+using a D65 white point :
+L = ( 0.2126 * r ) + ( 0.7152 * g ) + ( 0.0722 * b )
+Reference :
+A Standard Default Color Space for the Internet - sRGB.
+[online] http://www.w3.org/Graphics/Color/sRGB
+*/
+FIBITMAP*
+ConvertRGBFToY(FIBITMAP *src) {
+ if(FreeImage_GetImageType(src) != FIT_RGBF)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height);
+ if(!dst) return NULL;
+
+ unsigned src_pitch = FreeImage_GetPitch(src);
+ unsigned dst_pitch = FreeImage_GetPitch(dst);
+
+
+ BYTE *src_bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *dst_bits = (BYTE*)FreeImage_GetBits(dst);
+
+ for(unsigned y = 0; y < height; y++) {
+ const FIRGBF *src_pixel = (FIRGBF*)src_bits;
+ float *dst_pixel = (float*)dst_bits;
+ for(unsigned x = 0; x < width; x++) {
+ float L = 0.2126F * src_pixel[x].red + 0.7152F * src_pixel[x].green + 0.0722F * src_pixel[x].blue;
+ dst_pixel[x] = (L > 0) ? L : 0;
+ }
+ // next line
+ src_bits += src_pitch;
+ dst_bits += dst_pitch;
+ }
+
+ return dst;
+}
+
+/**
+Get the maximum, minimum, average luminance and log average luminance from a Y image
+@param dib Source Y image to analyze
+@param maxLum Maximum luminance
+@param minLum Minimum luminance
+@param Lav Average luminance
+@param Llav Log average luminance (also known as 'world adaptation luminance')
+@return Returns TRUE if successful, returns FALSE otherwise
+@see ConvertRGBFToY, FreeImage_TmoReinhard05Ex
+*/
+BOOL
+LuminanceFromY(FIBITMAP *dib, float *maxLum, float *minLum, float *Lav, float *Llav) {
+ if(FreeImage_GetImageType(dib) != FIT_FLOAT)
+ return FALSE;
+
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned pitch = FreeImage_GetPitch(dib);
+
+ float max_lum = -1e20F, min_lum = 1e20F;
+ double sumLum = 0, sumLogLum = 0;
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(dib);
+ for(unsigned y = 0; y < height; y++) {
+ const float *pixel = (float*)bits;
+ for(unsigned x = 0; x < width; x++) {
+ const float Y = pixel[x];
+ max_lum = (max_lum < Y) ? Y : max_lum; // max Luminance in the scene
+ min_lum = ((Y > 0) && (min_lum < Y)) ? min_lum : Y; // min Luminance in the scene
+ sumLum += Y; // average luminance
+ sumLogLum += log(2.3e-5 + Y); // contrast constant in Tumblin paper
+ }
+ // next line
+ bits += pitch;
+ }
+
+ // maximum luminance
+ *maxLum = max_lum;
+ // minimum luminance
+ *minLum = min_lum;
+ // average luminance
+ *Lav = (float)(sumLum / (width * height));
+ // average log luminance, a.k.a. world adaptation luminance
+ *Llav = (float)exp(sumLogLum / (width * height));
+
+ return TRUE;
+}
+// --------------------------------------------------------------------------
+
+static void findMaxMinPercentile(FIBITMAP *Y, float minPrct, float *minLum, float maxPrct, float *maxLum) {
+ int x, y;
+ int width = FreeImage_GetWidth(Y);
+ int height = FreeImage_GetHeight(Y);
+ int pitch = FreeImage_GetPitch(Y);
+
+ std::vector<float> vY(width * height);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
+ for(y = 0; y < height; y++) {
+ float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ if(pixel[x] != 0) {
+ vY.push_back(pixel[x]);
+ }
+ }
+ bits += pitch;
+ }
+
+ std::sort(vY.begin(), vY.end());
+
+ *minLum = vY.at( int(minPrct * vY.size()) );
+ *maxLum = vY.at( int(maxPrct * vY.size()) );
+}
+
+/**
+Clipping function<br>
+Remove any extremely bright and/or extremely dark pixels
+and normalize between 0 and 1.
+@param Y Input/Output image
+@param minPrct Minimum percentile
+@param maxPrct Maximum percentile
+*/
+void
+NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct) {
+ int x, y;
+ float maxLum, minLum;
+
+ if(minPrct > maxPrct) {
+ // swap values
+ float t = minPrct; minPrct = maxPrct; maxPrct = t;
+ }
+ if(minPrct < 0) minPrct = 0;
+ if(maxPrct > 1) maxPrct = 1;
+
+ int width = FreeImage_GetWidth(Y);
+ int height = FreeImage_GetHeight(Y);
+ int pitch = FreeImage_GetPitch(Y);
+
+ // find max & min luminance values
+ if((minPrct > 0) || (maxPrct < 1)) {
+ maxLum = 0, minLum = 0;
+ findMaxMinPercentile(Y, minPrct, &minLum, maxPrct, &maxLum);
+ } else {
+ maxLum = -1e20F, minLum = 1e20F;
+ BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
+ for(y = 0; y < height; y++) {
+ const float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ const float value = pixel[x];
+ maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene
+ minLum = (minLum < value) ? minLum : value; // min Luminance in the scene
+ }
+ // next line
+ bits += pitch;
+ }
+ }
+ if(maxLum == minLum) return;
+
+ // normalize to range 0..1
+ const float divider = maxLum - minLum;
+ BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
+ for(y = 0; y < height; y++) {
+ float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ pixel[x] = (pixel[x] - minLum) / divider;
+ if(pixel[x] <= 0) pixel[x] = EPSILON;
+ if(pixel[x] > 1) pixel[x] = 1;
+ }
+ // next line
+ bits += pitch;
+ }
+}
diff --git a/Source/FreeImage/tmoDrago03.cpp b/Source/FreeImage/tmoDrago03.cpp
new file mode 100644
index 0000000..0433795
--- /dev/null
+++ b/Source/FreeImage/tmoDrago03.cpp
@@ -0,0 +1,295 @@
+// ==========================================================
+// Tone mapping operator (Drago, 2003)
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "ToneMapping.h"
+
+// ----------------------------------------------------------
+// Logarithmic mapping operator
+// Reference:
+// [1] F. Drago, K. Myszkowski, T. Annen, and N. Chiba,
+// Adaptive Logarithmic Mapping for Displaying High Contrast Scenes,
+// Eurographics 2003.
+// ----------------------------------------------------------
+
+/**
+Bias function
+*/
+static inline double
+biasFunction(const double b, const double x) {
+ return pow (x, b); // pow(x, log(bias)/log(0.5)
+}
+
+/**
+Padé approximation of log(x + 1)
+x(6+x)/(6+4x) good if x < 1
+x*(6 + 0.7662x)/(5.9897 + 3.7658x) between 1 and 2
+See http://www.nezumi.demon.co.uk/consult/logx.htm
+*/
+static inline double
+pade_log(const double x) {
+ if(x < 1) {
+ return (x * (6 + x) / (6 + 4 * x));
+ } else if(x < 2) {
+ return (x * (6 + 0.7662 * x) / (5.9897 + 3.7658 * x));
+ }
+ return log(x + 1);
+}
+
+/**
+Log mapping operator
+@param dib Input / Output Yxy image
+@param maxLum Maximum luminance
+@param avgLum Average luminance (world adaptation luminance)
+@param biasParam Bias parameter (a zero value default to 0.85)
+@param exposure Exposure parameter (default to 0)
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+ToneMappingDrago03(FIBITMAP *dib, const float maxLum, const float avgLum, float biasParam, const float exposure) {
+ const float LOG05 = -0.693147F; // log(0.5)
+
+ double Lmax, divider, interpol, biasP;
+ unsigned x, y;
+ double L;
+
+ if(FreeImage_GetImageType(dib) != FIT_RGBF)
+ return FALSE;
+
+ const unsigned width = FreeImage_GetWidth(dib);
+ const unsigned height = FreeImage_GetHeight(dib);
+ const unsigned pitch = FreeImage_GetPitch(dib);
+
+
+ // arbitrary Bias Parameter
+ if(biasParam == 0)
+ biasParam = 0.85F;
+
+ // normalize maximum luminance by average luminance
+ Lmax = maxLum / avgLum;
+
+ divider = log10(Lmax+1);
+ biasP = log(biasParam)/LOG05;
+
+#if !defined(DRAGO03_FAST)
+
+ /**
+ Normal tone mapping of every pixel
+ further acceleration is obtained by a Padé approximation of log(x + 1)
+ */
+ BYTE *bits = (BYTE*)FreeImage_GetBits(dib);
+ for(y = 0; y < height; y++) {
+ FIRGBF *pixel = (FIRGBF*)bits;
+ for(x = 0; x < width; x++) {
+ double Yw = pixel[x].red / avgLum;
+ Yw *= exposure;
+ interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8);
+ L = pade_log(Yw);// log(Yw + 1)
+ pixel[x].red = (float)((L / interpol) / divider);
+ }
+ // next line
+ bits += pitch;
+ }
+
+#else
+ unsigned index;
+ int i, j;
+
+ unsigned max_width = width - (width % 3);
+ unsigned max_height = height - (height % 3);
+ unsigned fpitch = pitch / sizeof(FIRGBF);
+
+ /**
+ fast tone mapping
+ split the image into 3x3 pixel tiles and perform the computation for each group of 9 pixels
+ further acceleration is obtained by a Padé approximation of log(x + 1)
+ => produce artifacts and not so faster, so the code has been disabled
+ */
+#define PIXEL(x, y) image[y*fpitch + x].red
+
+ FIRGBF *image = (FIRGBF*)FreeImage_GetBits(dib);
+ for(y = 0; y < max_height; y += 3) {
+ for(x = 0; x < max_width; x += 3) {
+ double average = 0;
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 3; j++) {
+ index = (y + i)*fpitch + (x + j);
+ image[index].red /= (float)avgLum;
+ image[index].red *= exposure;
+ average += image[index].red;
+ }
+ }
+ average = average / 9 - PIXEL(x, y);
+ if(average > -1 && average < 1) {
+ interpol = log(2 + pow(PIXEL(x + 1, y + 1) / Lmax, biasP) * 8);
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 3; j++) {
+ index = (y + i)*fpitch + (x + j);
+ L = pade_log(image[index].red);// log(image[index].red + 1)
+ image[index].red = (float)((L / interpol) / divider);
+ }
+ }
+ }
+ else {
+ for(i = 0; i < 3; i++) {
+ for(j = 0; j < 3; j++) {
+ index = (y + i)*fpitch + (x + j);
+ interpol = log(2 + pow(image[index].red / Lmax, biasP) * 8);
+ L = pade_log(image[index].red);// log(image[index].red + 1)
+ image[index].red = (float)((L / interpol) / divider);
+ }
+ }
+ }
+ } //x
+ } // y
+
+ /**
+ Normal tone mapping of every pixel for the remaining right and bottom bands
+ */
+ BYTE *bits;
+
+ // right band
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ for(y = 0; y < height; y++) {
+ FIRGBF *pixel = (FIRGBF*)bits;
+ for(x = max_width; x < width; x++) {
+ double Yw = pixel[x].red / avgLum;
+ Yw *= exposure;
+ interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8);
+ L = pade_log(Yw);// log(Yw + 1)
+ pixel[x].red = (float)((L / interpol) / divider);
+ }
+ // next line
+ bits += pitch;
+ }
+ // bottom band
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ for(y = max_height; y < height; y++) {
+ FIRGBF *pixel = (FIRGBF*)bits;
+ for(x = 0; x < max_width; x++) {
+ double Yw = pixel[x].red / avgLum;
+ Yw *= exposure;
+ interpol = log(2 + biasFunction(biasP, Yw / Lmax) * 8);
+ L = pade_log(Yw);// log(Yw + 1)
+ pixel[x].red = (float)((L / interpol) / divider);
+ }
+ // next line
+ bits += pitch;
+ }
+
+#endif // DRAGO03_FAST
+
+ return TRUE;
+}
+
+/**
+Custom gamma correction based on the ITU-R BT.709 standard
+@param dib RGBF image to be corrected
+@param gammaval Gamma value (2.2 is a good default value)
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL
+REC709GammaCorrection(FIBITMAP *dib, const float gammaval) {
+ if(FreeImage_GetImageType(dib) != FIT_RGBF)
+ return FALSE;
+
+ float slope = 4.5F;
+ float start = 0.018F;
+
+ const float fgamma = (float)((0.45 / gammaval) * 2);
+ if(gammaval >= 2.1F) {
+ start = (float)(0.018 / ((gammaval - 2) * 7.5));
+ slope = (float)(4.5 * ((gammaval - 2) * 7.5));
+ } else if (gammaval <= 1.9F) {
+ start = (float)(0.018 * ((2 - gammaval) * 7.5));
+ slope = (float)(4.5 / ((2 - gammaval) * 7.5));
+ }
+
+ const unsigned width = FreeImage_GetWidth(dib);
+ const unsigned height = FreeImage_GetHeight(dib);
+ const unsigned pitch = FreeImage_GetPitch(dib);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(dib);
+ for(unsigned y = 0; y < height; y++) {
+ float *pixel = (float*)bits;
+ for(unsigned x = 0; x < width; x++) {
+ for(int i = 0; i < 3; i++) {
+ *pixel = (*pixel <= start) ? *pixel * slope : (float)(1.099 * pow(*pixel, fgamma) - 0.099);
+ pixel++;
+ }
+ }
+ bits += pitch;
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// Main algorithm
+// ----------------------------------------------------------
+
+/**
+Apply the Adaptive Logarithmic Mapping operator to a HDR image and convert to 24-bit RGB
+@param src Input RGB16 or RGB[A]F image
+@param gamma Gamma correction (gamma > 0). 1 means no correction, 2.2 in the original paper.
+@param exposure Exposure parameter (0 means no correction, 0 in the original paper)
+@return Returns a 24-bit RGB image if successful, returns NULL otherwise
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_TmoDrago03(FIBITMAP *src, double gamma, double exposure) {
+ float maxLum, minLum, avgLum;
+
+ if(!src) return NULL;
+
+ // working RGBF variable
+ FIBITMAP *dib = NULL;
+
+ dib = FreeImage_ConvertToRGBF(src);
+ if(!dib) return NULL;
+
+ // default algorithm parameters
+ const float biasParam = 0.85F;
+ const float expoParam = (float)pow(2.0, exposure); //default exposure is 1, 2^0
+
+ // convert to Yxy
+ ConvertInPlaceRGBFToYxy(dib);
+ // get the luminance
+ LuminanceFromYxy(dib, &maxLum, &minLum, &avgLum);
+ // perform the tone mapping
+ ToneMappingDrago03(dib, maxLum, avgLum, biasParam, expoParam);
+ // convert back to RGBF
+ ConvertInPlaceYxyToRGBF(dib);
+ if(gamma != 1) {
+ // perform gamma correction
+ REC709GammaCorrection(dib, (float)gamma);
+ }
+ // clamp image highest values to display white, then convert to 24-bit RGB
+ FIBITMAP *dst = ClampConvertRGBFTo24(dib);
+
+ // clean-up and return
+ FreeImage_Unload(dib);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+}
diff --git a/Source/FreeImage/tmoFattal02.cpp b/Source/FreeImage/tmoFattal02.cpp
new file mode 100644
index 0000000..5975a35
--- /dev/null
+++ b/Source/FreeImage/tmoFattal02.cpp
@@ -0,0 +1,687 @@
+// ==========================================================
+// Tone mapping operator (Fattal, 2002)
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "ToneMapping.h"
+
+// ----------------------------------------------------------
+// Gradient domain HDR compression
+// Reference:
+// [1] R. Fattal, D. Lischinski, and M.Werman,
+// Gradient domain high dynamic range compression,
+// ACM Transactions on Graphics, special issue on Proc. of ACM SIGGRAPH 2002,
+// San Antonio, Texas, vol. 21(3), pp. 257-266, 2002.
+// ----------------------------------------------------------
+
+static const float EPSILON = 1e-4F;
+
+/**
+Performs a 5 by 5 gaussian filtering using two 1D convolutions,
+followed by a subsampling by 2.
+@param dib Input image
+@return Returns a blurred image of size SIZE(dib)/2
+@see GaussianPyramid
+*/
+static FIBITMAP* GaussianLevel5x5(FIBITMAP *dib) {
+ int x, y, width, height, pitch;
+ FIBITMAP *h_dib = NULL, *v_dib = NULL, *dst = NULL;
+ float *src_pixel, *dst_pixel;
+
+ try {
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+ if(image_type != FIT_FLOAT) throw(1);
+
+ width = FreeImage_GetWidth(dib);
+ height = FreeImage_GetHeight(dib);
+
+ h_dib = FreeImage_AllocateT(image_type, width, height);
+ v_dib = FreeImage_AllocateT(image_type, width, height);
+ if(!h_dib || !v_dib) throw(1);
+
+ pitch = FreeImage_GetPitch(dib) / sizeof(float);
+
+ // horizontal convolution dib -> h_dib
+ src_pixel = (float*)FreeImage_GetBits(dib);
+ dst_pixel = (float*)FreeImage_GetBits(h_dib);
+ for(y = 0; y < height; y++) {
+ // work on line y
+ for(x = 2; x < width - 2; x++) {
+ dst_pixel[x] = src_pixel[x-2] + src_pixel[x+2] + 4 * (src_pixel[x-1] + src_pixel[x+1]) + 6 * src_pixel[x];
+ dst_pixel[x] /= 16;
+ }
+ // boundary mirroring
+ dst_pixel[0] = (2 * src_pixel[2] + 8 * src_pixel[1] + 6 * src_pixel[0]) / 16;
+ dst_pixel[1] = (src_pixel[3] + 4 * (src_pixel[0] + src_pixel[2]) + 7 * src_pixel[1]) / 16;
+ dst_pixel[width-2] = (src_pixel[width-4] + 5 * src_pixel[width-1] + 4 * src_pixel[width-3] + 6 * src_pixel[width-2]) / 16;
+ dst_pixel[width-1] = (src_pixel[width-3] + 5 * src_pixel[width-2] + 10 * src_pixel[width-1]) / 16;
+
+ // next line
+ src_pixel += pitch;
+ dst_pixel += pitch;
+ }
+ // vertical convolution h_dib -> v_dib
+ src_pixel = (float*)FreeImage_GetBits(h_dib);
+ dst_pixel = (float*)FreeImage_GetBits(v_dib);
+ for(x = 0; x < width; x++) {
+ // work on column x
+ for(y = 2; y < height - 2; y++) {
+ const int index = y*pitch + x;
+ dst_pixel[index] = src_pixel[index-2*pitch] + src_pixel[index+2*pitch] + 4 * (src_pixel[index-pitch] + src_pixel[index+pitch]) + 6 * src_pixel[index];
+ dst_pixel[index] /= 16;
+ }
+ // boundary mirroring
+ dst_pixel[x] = (2 * src_pixel[x+2*pitch] + 8 * src_pixel[x+pitch] + 6 * src_pixel[x]) / 16;
+ dst_pixel[x+pitch] = (src_pixel[x+3*pitch] + 4 * (src_pixel[x] + src_pixel[x+2*pitch]) + 7 * src_pixel[x+pitch]) / 16;
+ dst_pixel[(height-2)*pitch+x] = (src_pixel[(height-4)*pitch+x] + 5 * src_pixel[(height-1)*pitch+x] + 4 * src_pixel[(height-3)*pitch+x] + 6 * src_pixel[(height-2)*pitch+x]) / 16;
+ dst_pixel[(height-1)*pitch+x] = (src_pixel[(height-3)*pitch+x] + 5 * src_pixel[(height-2)*pitch+x] + 10 * src_pixel[(height-1)*pitch+x]) / 16;
+ }
+
+ FreeImage_Unload(h_dib); h_dib = NULL;
+
+ // perform downsampling
+
+ dst = FreeImage_Rescale(v_dib, width/2, height/2, FILTER_BILINEAR);
+
+ FreeImage_Unload(v_dib);
+
+ return dst;
+
+ } catch(int) {
+ if(h_dib) FreeImage_Unload(h_dib);
+ if(v_dib) FreeImage_Unload(v_dib);
+ if(dst) FreeImage_Unload(dst);
+ return NULL;
+ }
+}
+
+/**
+Compute a Gaussian pyramid using the specified number of levels.
+@param H Original bitmap
+@param pyramid Resulting pyramid array
+@param nlevels Number of resolution levels
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL GaussianPyramid(FIBITMAP *H, FIBITMAP **pyramid, int nlevels) {
+ try {
+ // first level is the original image
+ pyramid[0] = FreeImage_Clone(H);
+ if(pyramid[0] == NULL) throw(1);
+ // compute next levels
+ for(int k = 1; k < nlevels; k++) {
+ pyramid[k] = GaussianLevel5x5(pyramid[k-1]);
+ if(pyramid[k] == NULL) throw(1);
+ }
+ return TRUE;
+ } catch(int) {
+ for(int k = 0; k < nlevels; k++) {
+ if(pyramid[k] != NULL) {
+ FreeImage_Unload(pyramid[k]);
+ pyramid[k] = NULL;
+ }
+ }
+ return FALSE;
+ }
+}
+
+/**
+Compute the gradient magnitude of an input image H using central differences,
+and returns the average gradient.
+@param H Input image
+@param avgGrad [out] Average gradient
+@param k Level number
+@return Returns the gradient magnitude if successful, returns NULL otherwise
+@see GradientPyramid
+*/
+static FIBITMAP* GradientLevel(FIBITMAP *H, float *avgGrad, int k) {
+ int x, y, width, height, pitch;
+ FIBITMAP *G = NULL;
+
+ try {
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H);
+ if(image_type != FIT_FLOAT) throw(1);
+
+ width = FreeImage_GetWidth(H);
+ height = FreeImage_GetHeight(H);
+
+ G = FreeImage_AllocateT(image_type, width, height);
+ if(!G) throw(1);
+
+ pitch = FreeImage_GetPitch(H) / sizeof(float);
+
+ const float divider = (float)(1 << (k + 1));
+ float average = 0;
+
+ float *src_pixel = (float*)FreeImage_GetBits(H);
+ float *dst_pixel = (float*)FreeImage_GetBits(G);
+ for(y = 0; y < height; y++) {
+ const int n = (y == 0 ? 0 : y-1);
+ const int s = (y+1 == height ? y : y+1);
+ for(x = 0; x < width; x++) {
+ const int w = (x == 0 ? 0 : x-1);
+ const int e = (x+1 == width ? x : x+1);
+ // central difference
+ float gx = (src_pixel[y*pitch+e] - src_pixel[y*pitch+w]) / divider; // [Hk(x+1, y) - Hk(x-1, y)] / 2**(k+1)
+ float gy = (src_pixel[s*pitch+x] - src_pixel[n*pitch+x]) / divider; // [Hk(x, y+1) - Hk(x, y-1)] / 2**(k+1)
+ // gradient
+ dst_pixel[x] = sqrt(gx*gx + gy*gy);
+ // average gradient
+ average += dst_pixel[x];
+ }
+ // next line
+ dst_pixel += pitch;
+ }
+
+ *avgGrad = average / (width * height);
+
+ return G;
+ } catch(int) {
+ if(G) FreeImage_Unload(G);
+ return NULL;
+ }
+}
+
+/**
+Calculate gradient magnitude and its average value on each pyramid level
+@param pyramid Gaussian pyramid (nlevels levels)
+@param nlevels Number of levels
+@param gradients [out] Gradient pyramid (nlevels levels)
+@param avgGrad [out] Average gradient on each level (array of size nlevels)
+@return Returns TRUE if successful, returns FALSE otherwise
+*/
+static BOOL GradientPyramid(FIBITMAP **pyramid, int nlevels, FIBITMAP **gradients, float *avgGrad) {
+ try {
+ for(int k = 0; k < nlevels; k++) {
+ FIBITMAP *Hk = pyramid[k];
+ gradients[k] = GradientLevel(Hk, &avgGrad[k], k);
+ if(gradients[k] == NULL) throw(1);
+ }
+ return TRUE;
+ } catch(int) {
+ for(int k = 0; k < nlevels; k++) {
+ if(gradients[k] != NULL) {
+ FreeImage_Unload(gradients[k]);
+ gradients[k] = NULL;
+ }
+ }
+ return FALSE;
+ }
+}
+
+/**
+Compute the gradient attenuation function PHI(x, y)
+@param gradients Gradient pyramid (nlevels levels)
+@param avgGrad Average gradient on each level (array of size nlevels)
+@param nlevels Number of levels
+@param alpha Parameter alpha in the paper
+@param beta Parameter beta in the paper
+@return Returns the attenuation matrix Phi if successful, returns NULL otherwise
+*/
+static FIBITMAP* PhiMatrix(FIBITMAP **gradients, float *avgGrad, int nlevels, float alpha, float beta) {
+ int x, y, width, height, pitch;
+ float *src_pixel, *dst_pixel;
+ FIBITMAP **phi = NULL;
+
+ try {
+ phi = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
+ if(!phi) throw(1);
+ memset(phi, 0, nlevels * sizeof(FIBITMAP*));
+
+ for(int k = nlevels-1; k >= 0; k--) {
+ // compute phi(k)
+
+ FIBITMAP *Gk = gradients[k];
+
+ width = FreeImage_GetWidth(Gk);
+ height = FreeImage_GetHeight(Gk);
+ pitch = FreeImage_GetPitch(Gk) / sizeof(float);
+
+ // parameter alpha is 0.1 times the average gradient magnitude
+ // also, note the factor of 2**k in the denominator;
+ // that is there to correct for the fact that an average gradient avgGrad(H) over 2**k pixels
+ // in the original image will appear as a gradient grad(Hk) = 2**k*avgGrad(H) over a single pixel in Hk.
+ float ALPHA = alpha * avgGrad[k] * (float)((int)1 << k);
+ if(ALPHA == 0) ALPHA = EPSILON;
+
+ phi[k] = FreeImage_AllocateT(FIT_FLOAT, width, height);
+ if(!phi[k]) throw(1);
+
+ src_pixel = (float*)FreeImage_GetBits(Gk);
+ dst_pixel = (float*)FreeImage_GetBits(phi[k]);
+ for(y = 0; y < height; y++) {
+ for(x = 0; x < width; x++) {
+ // compute (alpha / grad) * (grad / alpha) ** beta
+ const float v = src_pixel[x] / ALPHA;
+ const float value = (float)pow((float)v, (float)(beta-1));
+ dst_pixel[x] = (value > 1) ? 1 : value;
+ }
+ // next line
+ src_pixel += pitch;
+ dst_pixel += pitch;
+ }
+
+ if(k < nlevels-1) {
+ // compute PHI(k) = L( PHI(k+1) ) * phi(k)
+ FIBITMAP *L = FreeImage_Rescale(phi[k+1], width, height, FILTER_BILINEAR);
+ if(!L) throw(1);
+
+ src_pixel = (float*)FreeImage_GetBits(L);
+ dst_pixel = (float*)FreeImage_GetBits(phi[k]);
+ for(y = 0; y < height; y++) {
+ for(x = 0; x < width; x++) {
+ dst_pixel[x] *= src_pixel[x];
+ }
+ // next line
+ src_pixel += pitch;
+ dst_pixel += pitch;
+ }
+
+ FreeImage_Unload(L);
+
+ // PHI(k+1) is no longer needed
+ FreeImage_Unload(phi[k+1]);
+ phi[k+1] = NULL;
+ }
+
+ // next level
+ }
+
+ // get the final result and return
+ FIBITMAP *dst = phi[0];
+
+ free(phi);
+
+ return dst;
+
+ } catch(int) {
+ if(phi) {
+ for(int k = nlevels-1; k >= 0; k--) {
+ if(phi[k]) FreeImage_Unload(phi[k]);
+ }
+ free(phi);
+ }
+ return NULL;
+ }
+}
+
+/**
+Compute gradients in x and y directions, attenuate them with the attenuation matrix,
+then compute the divergence div G from the attenuated gradient.
+@param H Normalized luminance
+@param PHI Attenuation matrix
+@return Returns the divergence matrix if successful, returns NULL otherwise
+*/
+static FIBITMAP* Divergence(FIBITMAP *H, FIBITMAP *PHI) {
+ int x, y, width, height, pitch;
+ FIBITMAP *Gx = NULL, *Gy = NULL, *divG = NULL;
+ float *phi, *h, *gx, *gy, *divg;
+
+ try {
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(H);
+ if(image_type != FIT_FLOAT) throw(1);
+
+ width = FreeImage_GetWidth(H);
+ height = FreeImage_GetHeight(H);
+
+ Gx = FreeImage_AllocateT(image_type, width, height);
+ if(!Gx) throw(1);
+ Gy = FreeImage_AllocateT(image_type, width, height);
+ if(!Gy) throw(1);
+
+ pitch = FreeImage_GetPitch(H) / sizeof(float);
+
+ // perform gradient attenuation
+
+ phi = (float*)FreeImage_GetBits(PHI);
+ h = (float*)FreeImage_GetBits(H);
+ gx = (float*)FreeImage_GetBits(Gx);
+ gy = (float*)FreeImage_GetBits(Gy);
+
+ for(y = 0; y < height; y++) {
+ const int s = (y+1 == height ? y : y+1);
+ for(x = 0; x < width; x++) {
+ const int e = (x+1 == width ? x : x+1);
+ // forward difference
+ const int index = y*pitch+x;
+ const float phi_xy = phi[index];
+ const float h_xy = h[index];
+ gx[x] = (h[y*pitch+e] - h_xy) * phi_xy; // [H(x+1, y) - H(x, y)] * PHI(x, y)
+ gy[x] = (h[s*pitch+x] - h_xy) * phi_xy; // [H(x, y+1) - H(x, y)] * PHI(x, y)
+ }
+ // next line
+ gx += pitch;
+ gy += pitch;
+ }
+
+ // calculate the divergence
+
+ divG = FreeImage_AllocateT(image_type, width, height);
+ if(!divG) throw(1);
+
+ gx = (float*)FreeImage_GetBits(Gx);
+ gy = (float*)FreeImage_GetBits(Gy);
+ divg = (float*)FreeImage_GetBits(divG);
+
+ for(y = 0; y < height; y++) {
+ for(x = 0; x < width; x++) {
+ // backward difference approximation
+ // divG = Gx(x, y) - Gx(x-1, y) + Gy(x, y) - Gy(x, y-1)
+ const int index = y*pitch+x;
+ divg[index] = gx[index] + gy[index];
+ if(x > 0) divg[index] -= gx[index-1];
+ if(y > 0) divg[index] -= gy[index-pitch];
+ }
+ }
+
+ // no longer needed ...
+ FreeImage_Unload(Gx);
+ FreeImage_Unload(Gy);
+
+ // return the divergence
+ return divG;
+
+ } catch(int) {
+ if(Gx) FreeImage_Unload(Gx);
+ if(Gy) FreeImage_Unload(Gy);
+ if(divG) FreeImage_Unload(divG);
+ return NULL;
+ }
+}
+
+/**
+Given the luminance channel, find max & min luminance values,
+normalize to range 0..100 and take the logarithm.
+@param Y Image luminance
+@return Returns the normalized luminance H if successful, returns NULL otherwise
+*/
+static FIBITMAP* LogLuminance(FIBITMAP *Y) {
+ int x, y, width, height, pitch;
+ FIBITMAP *H = NULL;
+
+ try {
+ // get the luminance channel
+ FIBITMAP *H = FreeImage_Clone(Y);
+ if(!H) throw(1);
+
+ width = FreeImage_GetWidth(H);
+ height = FreeImage_GetHeight(H);
+ pitch = FreeImage_GetPitch(H);
+
+ // find max & min luminance values
+ float maxLum = -1e20F, minLum = 1e20F;
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(H);
+ for(y = 0; y < height; y++) {
+ const float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ const float value = pixel[x];
+ maxLum = (maxLum < value) ? value : maxLum; // max Luminance in the scene
+ minLum = (minLum < value) ? minLum : value; // min Luminance in the scene
+ }
+ // next line
+ bits += pitch;
+ }
+ if(maxLum == minLum) throw(1);
+
+ // normalize to range 0..100 and take the logarithm
+ const float scale = 100.F / (maxLum - minLum);
+ bits = (BYTE*)FreeImage_GetBits(H);
+ for(y = 0; y < height; y++) {
+ float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ const float value = (pixel[x] - minLum) * scale;
+ pixel[x] = log(value + EPSILON);
+ }
+ // next line
+ bits += pitch;
+ }
+
+ return H;
+
+ } catch(int) {
+ if(H) FreeImage_Unload(H);
+ return NULL;
+ }
+}
+
+/**
+Given a normalized luminance, perform exponentiation and recover the log compressed image
+@param Y Input/Output luminance image
+*/
+static void ExpLuminance(FIBITMAP *Y) {
+ int x, y;
+ int width = FreeImage_GetWidth(Y);
+ int height = FreeImage_GetHeight(Y);
+ int pitch = FreeImage_GetPitch(Y);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(Y);
+ for(y = 0; y < height; y++) {
+ float *pixel = (float*)bits;
+ for(x = 0; x < width; x++) {
+ pixel[x] = exp(pixel[x]) - EPSILON;
+ }
+ bits += pitch;
+ }
+}
+
+// --------------------------------------------------------------------------
+
+/**
+Gradient Domain HDR tone mapping operator
+@param Y Image luminance values
+@param alpha Parameter alpha of the paper (suggested value is 0.1)
+@param beta Parameter beta of the paper (suggested value is between 0.8 and 0.9)
+@return returns the tone mapped luminance
+*/
+static FIBITMAP* tmoFattal02(FIBITMAP *Y, float alpha, float beta) {
+ const int MIN_PYRAMID_SIZE = 32; // minimun size (width or height) of the coarsest level of the pyramid
+
+ FIBITMAP *H = NULL;
+ FIBITMAP **pyramid = NULL;
+ FIBITMAP **gradients = NULL;
+ FIBITMAP *phy = NULL;
+ FIBITMAP *divG = NULL;
+ FIBITMAP *U = NULL;
+ float *avgGrad = NULL;
+
+ int k;
+ int nlevels = 0;
+
+ try {
+ // get the normalized luminance
+ FIBITMAP *H = LogLuminance(Y);
+ if(!H) throw(1);
+
+ // get the number of levels for the pyramid
+ int width = FreeImage_GetWidth(H);
+ int height = FreeImage_GetHeight(H);
+ int minsize = MIN(width, height);
+ while(minsize >= MIN_PYRAMID_SIZE) {
+ nlevels++;
+ minsize /= 2;
+ }
+
+ // create the Gaussian pyramid
+ pyramid = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
+ if(!pyramid) throw(1);
+ memset(pyramid, 0, nlevels * sizeof(FIBITMAP*));
+
+ if(!GaussianPyramid(H, pyramid, nlevels)) throw(1);
+
+ // calculate gradient magnitude and its average value on each pyramid level
+ gradients = (FIBITMAP**)malloc(nlevels * sizeof(FIBITMAP*));
+ if(!gradients) throw(1);
+ memset(gradients, 0, nlevels * sizeof(FIBITMAP*));
+ avgGrad = (float*)malloc(nlevels * sizeof(float));
+ if(!avgGrad) throw(1);
+
+ if(!GradientPyramid(pyramid, nlevels, gradients, avgGrad)) throw(1);
+
+ // free the Gaussian pyramid
+ for(k = 0; k < nlevels; k++) {
+ if(pyramid[k]) FreeImage_Unload(pyramid[k]);
+ }
+ free(pyramid); pyramid = NULL;
+
+ // compute the gradient attenuation function PHI(x, y)
+ phy = PhiMatrix(gradients, avgGrad, nlevels, alpha, beta);
+ if(!phy) throw(1);
+
+ // free the gradient pyramid
+ for(k = 0; k < nlevels; k++) {
+ if(gradients[k]) FreeImage_Unload(gradients[k]);
+ }
+ free(gradients); gradients = NULL;
+ free(avgGrad); avgGrad = NULL;
+
+ // compute gradients in x and y directions, attenuate them with the attenuation matrix,
+ // then compute the divergence div G from the attenuated gradient.
+ divG = Divergence(H, phy);
+ if(!divG) throw(1);
+
+ // H & phy no longer needed
+ FreeImage_Unload(H); H = NULL;
+ FreeImage_Unload(phy); phy = NULL;
+
+ // solve the PDE (Poisson equation) using a multigrid solver and 3 cycles
+ FIBITMAP *U = FreeImage_MultigridPoissonSolver(divG, 3);
+ if(!U) throw(1);
+
+ FreeImage_Unload(divG);
+
+ // perform exponentiation and recover the log compressed image
+ ExpLuminance(U);
+
+ return U;
+
+ } catch(int) {
+ if(H) FreeImage_Unload(H);
+ if(pyramid) {
+ for(int i = 0; i < nlevels; i++) {
+ if(pyramid[i]) FreeImage_Unload(pyramid[i]);
+ }
+ free(pyramid);
+ }
+ if(gradients) {
+ for(int i = 0; i < nlevels; i++) {
+ if(gradients[i]) FreeImage_Unload(gradients[i]);
+ }
+ free(gradients);
+ }
+ if(avgGrad) free(avgGrad);
+ if(phy) FreeImage_Unload(phy);
+ if(divG) FreeImage_Unload(divG);
+ if(U) FreeImage_Unload(U);
+
+ return NULL;
+ }
+}
+
+// ----------------------------------------------------------
+// Main algorithm
+// ----------------------------------------------------------
+
+/**
+Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB
+@param dib Input RGBF / RGB16 image
+@param color_saturation Color saturation (s parameter in the paper) in [0.4..0.6]
+@param attenuation Atenuation factor (beta parameter in the paper) in [0.8..0.9]
+@return Returns a 24-bit RGB image if successful, returns NULL otherwise
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_TmoFattal02(FIBITMAP *dib, double color_saturation, double attenuation) {
+ const float alpha = 0.1F; // parameter alpha = 0.1
+ const float beta = (float)MAX(0.8, MIN(0.9, attenuation)); // parameter beta = [0.8..0.9]
+ const float s = (float)MAX(0.4, MIN(0.6, color_saturation));// exponent s controls color saturation = [0.4..0.6]
+
+ FIBITMAP *src = NULL;
+ FIBITMAP *Yin = NULL;
+ FIBITMAP *Yout = NULL;
+ FIBITMAP *dst = NULL;
+
+ try {
+ int x, y;
+
+ // convert to RGBF
+ src = FreeImage_ConvertToRGBF(dib);
+ if(!src) throw(1);
+
+ // get the luminance channel
+ Yin = ConvertRGBFToY(src);
+ if(!Yin) throw(1);
+
+ // perform the tone mapping
+ Yout = tmoFattal02(Yin, alpha, beta);
+ if(!Yout) throw(1);
+
+ // clip low and high values and normalize to [0..1]
+ //NormalizeY(Yout, 0.001F, 0.995F);
+ NormalizeY(Yout, 0, 1);
+
+ // compress the dynamic range
+
+ int width = FreeImage_GetWidth(src);
+ int height = FreeImage_GetHeight(src);
+
+ int rgb_pitch = FreeImage_GetPitch(src);
+ int y_pitch = FreeImage_GetPitch(Yin);
+
+ BYTE *bits = (BYTE*)FreeImage_GetBits(src);
+ BYTE *bits_yin = (BYTE*)FreeImage_GetBits(Yin);
+ BYTE *bits_yout = (BYTE*)FreeImage_GetBits(Yout);
+
+ for(y = 0; y < height; y++) {
+ float *Lin = (float*)bits_yin;
+ float *Lout = (float*)bits_yout;
+ float *color = (float*)bits;
+ for(x = 0; x < width; x++) {
+ for(int c = 0; c < 3; c++) {
+ *color = (Lin[x] > 0) ? pow(*color/Lin[x], s) * Lout[x] : 0;
+ color++;
+ }
+ }
+ bits += rgb_pitch;
+ bits_yin += y_pitch;
+ bits_yout += y_pitch;
+ }
+
+ // not needed anymore
+ FreeImage_Unload(Yin); Yin = NULL;
+ FreeImage_Unload(Yout); Yout = NULL;
+
+ // clamp image highest values to display white, then convert to 24-bit RGB
+ dst = ClampConvertRGBFTo24(src);
+
+ // clean-up and return
+ FreeImage_Unload(src); src = NULL;
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+
+ return dst;
+
+ } catch(int) {
+ if(src) FreeImage_Unload(src);
+ if(Yin) FreeImage_Unload(Yin);
+ if(Yout) FreeImage_Unload(Yout);
+ return NULL;
+ }
+}
diff --git a/Source/FreeImage/tmoReinhard05.cpp b/Source/FreeImage/tmoReinhard05.cpp
new file mode 100644
index 0000000..5fa8602
--- /dev/null
+++ b/Source/FreeImage/tmoReinhard05.cpp
@@ -0,0 +1,260 @@
+// ==========================================================
+// Tone mapping operator (Reinhard, 2005)
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "ToneMapping.h"
+
+// ----------------------------------------------------------
+// Global and/or local tone mapping operator
+// References:
+// [1] Erik Reinhard and Kate Devlin, 'Dynamic Range Reduction Inspired by Photoreceptor Physiology',
+// IEEE Transactions on Visualization and Computer Graphics, 11(1), Jan/Feb 2005.
+// [2] Erik Reinhard, 'Parameter estimation for photographic tone reproduction',
+// Journal of Graphics Tools, vol. 7, no. 1, pp. 45–51, 2003.
+// ----------------------------------------------------------
+
+/**
+Tone mapping operator
+@param dib Input / Output RGBF image
+@param Y Input luminance image version of dib
+@param f Overall intensity in range [-8:8] : default to 0
+@param m Contrast in range [0.3:1) : default to 0
+@param a Adaptation in range [0:1] : default to 1
+@param c Color correction in range [0:1] : default to 0
+@return Returns TRUE if successful, returns FALSE otherwise
+@see LuminanceFromY
+*/
+static BOOL
+ToneMappingReinhard05(FIBITMAP *dib, FIBITMAP *Y, float f, float m, float a, float c) {
+ float Cav[3]; // channel average
+ float Lav = 0; // average luminance
+ float Llav = 0; // log average luminance
+ float minLum = 1; // min luminance
+ float maxLum = 1; // max luminance
+
+ float L; // pixel luminance
+ float I_g, I_l; // global and local light adaptation
+ float I_a; // interpolated pixel light adaptation
+ float k; // key (low-key means overall dark image, high-key means overall light image)
+
+ // check input parameters
+
+ if((FreeImage_GetImageType(dib) != FIT_RGBF) || (FreeImage_GetImageType(Y) != FIT_FLOAT)) {
+ return FALSE;
+ }
+
+ if(f < -8) f = -8; if(f > 8) f = 8;
+ if(m < 0) m = 0; if(m > 1) m = 1;
+ if(a < 0) a = 0; if(a > 1) a = 1;
+ if(c < 0) c = 0; if(c > 1) c = 1;
+
+ const unsigned width = FreeImage_GetWidth(dib);
+ const unsigned height = FreeImage_GetHeight(dib);
+
+ const unsigned dib_pitch = FreeImage_GetPitch(dib);
+ const unsigned y_pitch = FreeImage_GetPitch(Y);
+
+ int i;
+ unsigned x, y;
+ BYTE *bits = NULL, *Ybits = NULL;
+
+ // get statistics about the data (but only if its really needed)
+
+ f = exp(-f);
+ if((m == 0) || (a != 1) && (c != 1)) {
+ // avoid these calculations if its not needed after ...
+ LuminanceFromY(Y, &maxLum, &minLum, &Lav, &Llav);
+ k = (log(maxLum) - Llav) / (log(maxLum) - log(minLum));
+ if(k < 0) {
+ // pow(k, 1.4F) is undefined ...
+ // there's an ambiguity about the calculation of Llav between Reinhard papers and the various implementations ...
+ // try another world adaptation luminance formula using instead 'worldLum = log(Llav)'
+ k = (log(maxLum) - log(Llav)) / (log(maxLum) - log(minLum));
+ if(k < 0) m = 0.3F;
+ }
+ }
+ m = (m > 0) ? m : (float)(0.3 + 0.7 * pow(k, 1.4F));
+
+ float max_color = -1e6F;
+ float min_color = +1e6F;
+
+ // tone map image
+
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ Ybits = (BYTE*)FreeImage_GetBits(Y);
+
+ if((a == 1) && (c == 0)) {
+ // when using default values, use a fastest code
+
+ for(y = 0; y < height; y++) {
+ float *Y = (float*)Ybits;
+ float *color = (float*)bits;
+
+ for(x = 0; x < width; x++) {
+ I_a = Y[x]; // luminance(x, y)
+ for (i = 0; i < 3; i++) {
+ *color /= ( *color + pow(f * I_a, m) );
+
+ max_color = (*color > max_color) ? *color : max_color;
+ min_color = (*color < min_color) ? *color : min_color;
+
+ color++;
+ }
+ }
+ // next line
+ bits += dib_pitch;
+ Ybits += y_pitch;
+ }
+ } else {
+ // complete algorithm
+
+ // channel averages
+
+ Cav[0] = Cav[1] = Cav[2] = 0;
+ if((a != 1) && (c != 0)) {
+ // channel averages are not needed when (a == 1) or (c == 0)
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ for(y = 0; y < height; y++) {
+ float *color = (float*)bits;
+ for(x = 0; x < width; x++) {
+ for(i = 0; i < 3; i++) {
+ Cav[i] += *color;
+ color++;
+ }
+ }
+ // next line
+ bits += dib_pitch;
+ }
+ const float image_size = (float)width * height;
+ for(i = 0; i < 3; i++) {
+ Cav[i] /= image_size;
+ }
+ }
+
+ // perform tone mapping
+
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ for(y = 0; y < height; y++) {
+ const float *Y = (float*)Ybits;
+ float *color = (float*)bits;
+
+ for(x = 0; x < width; x++) {
+ L = Y[x]; // luminance(x, y)
+ for (i = 0; i < 3; i++) {
+ I_l = c * *color + (1-c) * L;
+ I_g = c * Cav[i] + (1-c) * Lav;
+ I_a = a * I_l + (1-a) * I_g;
+ *color /= ( *color + pow(f * I_a, m) );
+
+ max_color = (*color > max_color) ? *color : max_color;
+ min_color = (*color < min_color) ? *color : min_color;
+
+ color++;
+ }
+ }
+ // next line
+ bits += dib_pitch;
+ Ybits += y_pitch;
+ }
+ }
+
+ // normalize intensities
+
+ if(max_color != min_color) {
+ bits = (BYTE*)FreeImage_GetBits(dib);
+ const float range = max_color - min_color;
+ for(y = 0; y < height; y++) {
+ float *color = (float*)bits;
+ for(x = 0; x < width; x++) {
+ for(i = 0; i < 3; i++) {
+ *color = (*color - min_color) / range;
+ color++;
+ }
+ }
+ // next line
+ bits += dib_pitch;
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// Main algorithm
+// ----------------------------------------------------------
+
+/**
+Apply the global/local tone mapping operator to a RGBF image and convert to 24-bit RGB<br>
+User parameters control intensity, contrast, and level of adaptation
+@param src Input RGBF image
+@param intensity Overall intensity in range [-8:8] : default to 0
+@param contrast Contrast in range [0.3:1) : default to 0
+@param adaptation Adaptation in range [0:1] : default to 1
+@param color_correction Color correction in range [0:1] : default to 0
+@return Returns a 24-bit RGB image if successful, returns NULL otherwise
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_TmoReinhard05Ex(FIBITMAP *src, double intensity, double contrast, double adaptation, double color_correction) {
+ if(!src) return NULL;
+
+ // working RGBF variable
+ FIBITMAP *dib = NULL, *Y = NULL;
+
+ dib = FreeImage_ConvertToRGBF(src);
+ if(!dib) return NULL;
+
+ // get the Luminance channel
+ Y = ConvertRGBFToY(dib);
+ if(!Y) {
+ FreeImage_Unload(dib);
+ return NULL;
+ }
+
+ // perform the tone mapping
+ ToneMappingReinhard05(dib, Y, (float)intensity, (float)contrast, (float)adaptation, (float)color_correction);
+ // not needed anymore
+ FreeImage_Unload(Y);
+ // clamp image highest values to display white, then convert to 24-bit RGB
+ FIBITMAP *dst = ClampConvertRGBFTo24(dib);
+
+ // clean-up and return
+ FreeImage_Unload(dib);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+}
+
+/**
+Apply the global tone mapping operator to a RGBF image and convert to 24-bit RGB<br>
+User parameters control intensity and contrast
+@param src Input RGBF image
+@param intensity Overall intensity in range [-8:8] : default to 0
+@param contrast Contrast in range [0.3:1) : default to 0
+@return Returns a 24-bit RGB image if successful, returns NULL otherwise
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_TmoReinhard05(FIBITMAP *src, double intensity, double contrast) {
+ return FreeImage_TmoReinhard05Ex(src, intensity, contrast, 1, 0);
+}
diff --git a/Source/FreeImageIO.h b/Source/FreeImageIO.h
new file mode 100644
index 0000000..b251d47
--- /dev/null
+++ b/Source/FreeImageIO.h
@@ -0,0 +1,48 @@
+// ==========================================================
+// Input/Output functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FREEIMAGEIO_H
+#define FREEIMAGEIO_H
+
+#ifndef FREEIMAGE_H
+#include "FreeImage.h"
+#endif
+
+// ----------------------------------------------------------
+
+FI_STRUCT (FIMEMORYHEADER) {
+ /// remember to delete the buffer
+ BOOL delete_me;
+ /// file length
+ long filelen;
+ /// buffer size
+ long datalen;
+ /// current position
+ long curpos;
+ /// start buffer address
+ void *data;
+};
+
+void SetDefaultIO(FreeImageIO *io);
+
+void SetMemoryIO(FreeImageIO *io);
+
+#endif // !FREEIMAGEIO_H
diff --git a/Source/FreeImageLib/FreeImageLib.2003.vcproj b/Source/FreeImageLib/FreeImageLib.2003.vcproj
new file mode 100644
index 0000000..65e49f9
--- /dev/null
+++ b/Source/FreeImageLib/FreeImageLib.2003.vcproj
@@ -0,0 +1,458 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="FreeImageLib"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\;..\ZLib;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;OPJ_STATIC;FREEIMAGE_LIB;_SECURE_NO_DEPRECATE"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ TreatWChar_tAsBuiltInType="TRUE"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="2"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="Debug\FreeImaged.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImaged.lib ..\..\Dist
+copy ..\FreeImage.h ..\..\Dist
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1043"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="..\;..\ZLib;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;OPJ_STATIC;FREEIMAGE_LIB;_SECURE_NO_DEPRECATE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ TreatWChar_tAsBuiltInType="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/FreeImageLib.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="2"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="Release\FreeImage.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImage.lib ..\..\Dist
+copy ..\FreeImage.h ..\..\Dist
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="..\FreeImage\BitmapAccess.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\ColorLookup.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImage.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImageIO.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\GetType.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\MemoryIO.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PixelAccess.cpp">
+ </File>
+ <Filter
+ Name="Quantizers"
+ Filter="">
+ <File
+ RelativePath="..\FreeImage\NNQuantizer.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\WuQuantizer.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ Filter="">
+ <File
+ RelativePath="..\FreeImage\Conversion.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_555.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_565.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion24.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion32.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion4.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion8.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionRGBF.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionType.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Halftoning.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoColorConvert.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoDrago03.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoFattal02.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoReinhard05.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\ToneMapping.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Plugins"
+ Filter="">
+ <File
+ RelativePath="..\FreeImage\J2KHelper.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\Plugin.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginBMP.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginCUT.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginDDS.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginEXR.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginG3.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginGIF.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginHDR.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginICO.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginIFF.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJ2K.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJP2.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJPEG.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginKOALA.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginMNG.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCD.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCX.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPFM.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPICT.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNG.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNM.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPSD.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginRAS.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginRAW.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginSGI.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTARGA.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTIFF.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginWBMP.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXBM.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXPM.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PSDParser.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\TIFFLogLuv.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ Filter="">
+ <File
+ RelativePath="..\DeprecationManager\Deprecated.cpp">
+ </File>
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ Filter="">
+ <File
+ RelativePath="..\FreeImage\CacheFile.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\MultiPage.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImage\ZLibInterface.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ Filter="">
+ <File
+ RelativePath="..\Metadata\Exif.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\IPTC.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\TagConversion.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\TagLib.cpp">
+ </File>
+ <File
+ RelativePath="..\Metadata\XTIFF.cpp">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="..\CacheFile.h">
+ </File>
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.h">
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.h">
+ </File>
+ <File
+ RelativePath="..\FreeImage.h">
+ </File>
+ <File
+ RelativePath="..\FreeImageIO.h">
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.h">
+ </File>
+ <File
+ RelativePath="..\Plugin.h">
+ </File>
+ <File
+ RelativePath="..\PoissonSolver.h">
+ </File>
+ <File
+ RelativePath="..\FreeImage\PSDParser.h">
+ </File>
+ <File
+ RelativePath="..\Quantizers.h">
+ </File>
+ <File
+ RelativePath="..\ToneMapping.h">
+ </File>
+ <File
+ RelativePath="..\Utilities.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ Filter="">
+ <File
+ RelativePath="..\FreeImageToolkit\Background.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\BSplineRotate.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Channels.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\ClassicRotate.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Colors.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\CopyPaste.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Display.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Flip.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\JPEGTransform.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\MultigridPoissonSolver.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Rescale.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.cpp">
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.h">
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\Whatsnew.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/FreeImageLib/FreeImageLib.2005.vcproj b/Source/FreeImageLib/FreeImageLib.2005.vcproj
new file mode 100644
index 0000000..70dc267
--- /dev/null
+++ b/Source/FreeImageLib/FreeImageLib.2005.vcproj
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="FreeImageLib"
+ ProjectGUID="{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ RootNamespace="FreeImageLib"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\;..\ZLib;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;OPJ_STATIC;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE;LIBRAW_NODLL"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/FreeImageLib.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="Debug\FreeImaged.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImaged.lib ..\..\Dist&#x0D;&#x0A;copy ..\FreeImage.h ..\..\Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\;..\ZLib;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;OPJ_STATIC;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE;LIBRAW_NODLL"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/FreeImageLib.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="true"
+ OutputFile="Release\FreeImage.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImage.lib ..\..\Dist&#x0D;&#x0A;copy ..\FreeImage.h ..\..\Dist&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\FreeImage\BitmapAccess.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ColorLookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImageIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\GetType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\MemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PixelAccess.cpp"
+ >
+ </File>
+ <Filter
+ Name="Quantizers"
+ >
+ <File
+ RelativePath="..\FreeImage\NNQuantizer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\WuQuantizer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ >
+ <File
+ RelativePath="..\FreeImage\Conversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_555.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_565.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion24.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion32.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion4.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion8.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionRGBF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Halftoning.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoColorConvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoDrago03.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoFattal02.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoReinhard05.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ToneMapping.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Plugins"
+ >
+ <File
+ RelativePath="..\FreeImage\J2KHelper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Plugin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginCUT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginDDS.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginEXR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginG3.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginGIF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginHDR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginICO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJ2K.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJP2.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginKOALA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginMNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCX.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPFM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPICT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPSD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginRAS.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginRAW.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginSGI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTARGA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginWBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXBM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXPM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PSDParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\TIFFLogLuv.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ >
+ <File
+ RelativePath="..\DeprecationManager\Deprecated.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ >
+ <File
+ RelativePath="..\FreeImage\CacheFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\MultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ZLibInterface.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ >
+ <File
+ RelativePath="..\Metadata\Exif.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\IPTC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\TagConversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\TagLib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\XTIFF.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\CacheFile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.h"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageIO.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PSDParser.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Quantizers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ToneMapping.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Utilities.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ >
+ <File
+ RelativePath="..\FreeImageToolkit\Background.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\BSplineRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Channels.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\ClassicRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Colors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\CopyPaste.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Display.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Flip.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\JPEGTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\MultigridPoissonSolver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Rescale.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\Whatsnew.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/FreeImageLib/FreeImageLib.2008.vcproj b/Source/FreeImageLib/FreeImageLib.2008.vcproj
new file mode 100644
index 0000000..5952a24
--- /dev/null
+++ b/Source/FreeImageLib/FreeImageLib.2008.vcproj
@@ -0,0 +1,572 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="FreeImageLib"
+ ProjectGUID="{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ RootNamespace="FreeImageLib"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\;&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;OPJ_STATIC;FREEIMAGE_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ PrecompiledHeaderFile=".\Debug/FreeImageLib.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="..\;&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;;..\DeprecationManager;..\OpenEXR\Half;..\OpenEXR\Iex;..\OpenEXR\IlmImf;..\OpenEXR\Imath;..\OpenEXR\IlmThread"
+ PreprocessorDefinitions="WIN32;NDEBUG;OPJ_STATIC;FREEIMAGE_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ PrecompiledHeaderFile=".\Release/FreeImageLib.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\FreeImage\BitmapAccess.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ColorLookup.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\FreeImageIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\GetType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\MemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PixelAccess.cpp"
+ >
+ </File>
+ <Filter
+ Name="Quantizers"
+ >
+ <File
+ RelativePath="..\FreeImage\NNQuantizer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\WuQuantizer.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Conversion"
+ >
+ <File
+ RelativePath="..\FreeImage\Conversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_555.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion16_565.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion24.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion32.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion4.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Conversion8.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionRGBF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ConversionType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Halftoning.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoColorConvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoDrago03.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoFattal02.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\tmoReinhard05.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ToneMapping.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Plugins"
+ >
+ <File
+ RelativePath="..\FreeImage\J2KHelper.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\Plugin.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginCUT.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginDDS.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginEXR.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginG3.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginGIF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginHDR.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginICO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJ2K.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJP2.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginKOALA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginMNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPCX.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPFM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPNM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginPSD.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginRAS.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginSGI.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTARGA.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginTIFF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginWBMP.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXBM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PluginXPM.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\PSDParser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\TIFFLogLuv.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="DeprecationMgr"
+ >
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="MultiPaging"
+ >
+ <File
+ RelativePath="..\FreeImage\CacheFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\MultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage\ZLibInterface.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Metadata"
+ >
+ <File
+ RelativePath="..\Metadata\Exif.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\IPTC.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\TagConversion.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\TagLib.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\XTIFF.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="..\CacheFile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\DeprecationManager\DeprecationMgr.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FIRational.h"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageIO.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Metadata\FreeImageTag.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Plugin.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Quantizers.h"
+ >
+ </File>
+ <File
+ RelativePath="..\ToneMapping.h"
+ >
+ </File>
+ <File
+ RelativePath="..\Utilities.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Toolkit Files"
+ >
+ <File
+ RelativePath="..\FreeImageToolkit\BSplineRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Channels.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\ClassicRotate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Colors.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\CopyPaste.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Display.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Flip.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\JPEGTransform.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\MultigridPoissonSolver.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Rescale.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\FreeImageToolkit\Resize.h"
+ >
+ </File>
+ </Filter>
+ <File
+ RelativePath="..\..\Whatsnew.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/FreeImageToolkit/BSplineRotate.cpp b/Source/FreeImageToolkit/BSplineRotate.cpp
new file mode 100644
index 0000000..b88821b
--- /dev/null
+++ b/Source/FreeImageToolkit/BSplineRotate.cpp
@@ -0,0 +1,728 @@
+// ==========================================================
+// Bitmap rotation using B-Splines
+//
+// Design and implementation by
+// - Philippe Thévenaz (philippe.thevenaz@epfl.ch)
+// Adaptation for FreeImage by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+/*
+==========================================================
+This code was taken and adapted from the following reference :
+
+[1] Philippe Thévenaz, Spline interpolation, a C source code
+implementation. http://bigwww.epfl.ch/thevenaz/
+
+It implements ideas described in the following papers :
+
+[2] Unser M., Splines: A Perfect Fit for Signal and Image Processing.
+IEEE Signal Processing Magazine, vol. 16, no. 6, pp. 22-38, November 1999.
+
+[3] Unser M., Aldroubi A., Eden M., B-Spline Signal Processing: Part I--Theory.
+IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-832, February 1993.
+
+[4] Unser M., Aldroubi A., Eden M., B-Spline Signal Processing: Part II--Efficient Design and Applications.
+IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 834-848, February 1993.
+
+==========================================================
+*/
+
+
+#include <float.h>
+#include "FreeImage.h"
+#include "Utilities.h"
+
+#define PI ((double)3.14159265358979323846264338327950288419716939937510)
+
+#define ROTATE_QUADRATIC 2L // Use B-splines of degree 2 (quadratic interpolation)
+#define ROTATE_CUBIC 3L // Use B-splines of degree 3 (cubic interpolation)
+#define ROTATE_QUARTIC 4L // Use B-splines of degree 4 (quartic interpolation)
+#define ROTATE_QUINTIC 5L // Use B-splines of degree 5 (quintic interpolation)
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Prototypes definition
+
+static void ConvertToInterpolationCoefficients(double *c, long DataLength, double *z, long NbPoles, double Tolerance);
+static double InitialCausalCoefficient(double *c, long DataLength, double z, double Tolerance);
+static void GetColumn(double *Image, long Width, long x, double *Line, long Height);
+static void GetRow(double *Image, long y, double *Line, long Width);
+static double InitialAntiCausalCoefficient(double *c, long DataLength, double z);
+static void PutColumn(double *Image, long Width, long x, double *Line, long Height);
+static void PutRow(double *Image, long y, double *Line, long Width);
+static bool SamplesToCoefficients(double *Image, long Width, long Height, long spline_degree);
+static double InterpolatedValue(double *Bcoeff, long Width, long Height, double x, double y, long spline_degree);
+
+static FIBITMAP * Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask);
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Coefficients routines
+
+/**
+ ConvertToInterpolationCoefficients
+
+ @param c Input samples --> output coefficients
+ @param DataLength Number of samples or coefficients
+ @param z Poles
+ @param NbPoles Number of poles
+ @param Tolerance Admissible relative error
+*/
+static void
+ConvertToInterpolationCoefficients(double *c, long DataLength, double *z, long NbPoles, double Tolerance) {
+ double Lambda = 1;
+ long n, k;
+
+ // special case required by mirror boundaries
+ if(DataLength == 1L) {
+ return;
+ }
+ // compute the overall gain
+ for(k = 0L; k < NbPoles; k++) {
+ Lambda = Lambda * (1.0 - z[k]) * (1.0 - 1.0 / z[k]);
+ }
+ // apply the gain
+ for (n = 0L; n < DataLength; n++) {
+ c[n] *= Lambda;
+ }
+ // loop over all poles
+ for (k = 0L; k < NbPoles; k++) {
+ // causal initialization
+ c[0] = InitialCausalCoefficient(c, DataLength, z[k], Tolerance);
+ // causal recursion
+ for (n = 1L; n < DataLength; n++) {
+ c[n] += z[k] * c[n - 1L];
+ }
+ // anticausal initialization
+ c[DataLength - 1L] = InitialAntiCausalCoefficient(c, DataLength, z[k]);
+ // anticausal recursion
+ for (n = DataLength - 2L; 0 <= n; n--) {
+ c[n] = z[k] * (c[n + 1L] - c[n]);
+ }
+ }
+}
+
+/**
+ InitialCausalCoefficient
+
+ @param c Coefficients
+ @param DataLength Number of coefficients
+ @param z Actual pole
+ @param Tolerance Admissible relative error
+ @return
+*/
+static double
+InitialCausalCoefficient(double *c, long DataLength, double z, double Tolerance) {
+ double Sum, zn, z2n, iz;
+ long n, Horizon;
+
+ // this initialization corresponds to mirror boundaries
+ Horizon = DataLength;
+ if(Tolerance > 0) {
+ Horizon = (long)ceil(log(Tolerance) / log(fabs(z)));
+ }
+ if(Horizon < DataLength) {
+ // accelerated loop
+ zn = z;
+ Sum = c[0];
+ for (n = 1L; n < Horizon; n++) {
+ Sum += zn * c[n];
+ zn *= z;
+ }
+ return(Sum);
+ }
+ else {
+ // full loop
+ zn = z;
+ iz = 1.0 / z;
+ z2n = pow(z, (double)(DataLength - 1L));
+ Sum = c[0] + z2n * c[DataLength - 1L];
+ z2n *= z2n * iz;
+ for (n = 1L; n <= DataLength - 2L; n++) {
+ Sum += (zn + z2n) * c[n];
+ zn *= z;
+ z2n *= iz;
+ }
+ return(Sum / (1.0 - zn * zn));
+ }
+}
+
+/**
+ GetColumn
+
+ @param Image Input image array
+ @param Width Width of the image
+ @param x x coordinate of the selected line
+ @param Line Output linear array
+ @param Height Length of the line
+*/
+static void
+GetColumn(double *Image, long Width, long x, double *Line, long Height) {
+ long y;
+
+ Image = Image + x;
+ for(y = 0L; y < Height; y++) {
+ Line[y] = (double)*Image;
+ Image += Width;
+ }
+}
+
+/**
+ GetRow
+
+ @param Image Input image array
+ @param y y coordinate of the selected line
+ @param Line Output linear array
+ @param Width Length of the line
+*/
+static void
+GetRow(double *Image, long y, double *Line, long Width) {
+ long x;
+
+ Image = Image + (y * Width);
+ for(x = 0L; x < Width; x++) {
+ Line[x] = (double)*Image++;
+ }
+}
+
+/**
+ InitialAntiCausalCoefficient
+
+ @param c Coefficients
+ @param DataLength Number of samples or coefficients
+ @param z Actual pole
+ @return
+*/
+static double
+InitialAntiCausalCoefficient(double *c, long DataLength, double z) {
+ // this initialization corresponds to mirror boundaries
+ return((z / (z * z - 1.0)) * (z * c[DataLength - 2L] + c[DataLength - 1L]));
+}
+
+/**
+ PutColumn
+
+ @param Image Output image array
+ @param Width Width of the image
+ @param x x coordinate of the selected line
+ @param Line Input linear array
+ @param Height Length of the line and height of the image
+*/
+static void
+PutColumn(double *Image, long Width, long x, double *Line, long Height) {
+ long y;
+
+ Image = Image + x;
+ for(y = 0L; y < Height; y++) {
+ *Image = (double)Line[y];
+ Image += Width;
+ }
+}
+
+/**
+ PutRow
+
+ @param Image Output image array
+ @param y y coordinate of the selected line
+ @param Line Input linear array
+ @param Width length of the line and width of the image
+*/
+static void
+PutRow(double *Image, long y, double *Line, long Width) {
+ long x;
+
+ Image = Image + (y * Width);
+ for(x = 0L; x < Width; x++) {
+ *Image++ = (double)Line[x];
+ }
+}
+
+/**
+ SamplesToCoefficients.<br>
+ Implement the algorithm that converts the image samples into B-spline coefficients.
+ This efficient procedure essentially relies on the three papers cited above;
+ data are processed in-place.
+ Even though this algorithm is robust with respect to quantization,
+ we advocate the use of a floating-point format for the data.
+
+ @param Image Input / Output image (in-place processing)
+ @param Width Width of the image
+ @param Height Height of the image
+ @param spline_degree Degree of the spline model
+ @return Returns true if success, false otherwise
+*/
+static bool
+SamplesToCoefficients(double *Image, long Width, long Height, long spline_degree) {
+ double *Line;
+ double Pole[2];
+ long NbPoles;
+ long x, y;
+
+ // recover the poles from a lookup table
+ switch (spline_degree) {
+ case 2L:
+ NbPoles = 1L;
+ Pole[0] = sqrt(8.0) - 3.0;
+ break;
+ case 3L:
+ NbPoles = 1L;
+ Pole[0] = sqrt(3.0) - 2.0;
+ break;
+ case 4L:
+ NbPoles = 2L;
+ Pole[0] = sqrt(664.0 - sqrt(438976.0)) + sqrt(304.0) - 19.0;
+ Pole[1] = sqrt(664.0 + sqrt(438976.0)) - sqrt(304.0) - 19.0;
+ break;
+ case 5L:
+ NbPoles = 2L;
+ Pole[0] = sqrt(135.0 / 2.0 - sqrt(17745.0 / 4.0)) + sqrt(105.0 / 4.0)
+ - 13.0 / 2.0;
+ Pole[1] = sqrt(135.0 / 2.0 + sqrt(17745.0 / 4.0)) - sqrt(105.0 / 4.0)
+ - 13.0 / 2.0;
+ break;
+ default:
+ // Invalid spline degree
+ return false;
+ }
+
+ // convert the image samples into interpolation coefficients
+
+ // in-place separable process, along x
+ Line = (double *)malloc(Width * sizeof(double));
+ if (Line == NULL) {
+ // Row allocation failed
+ return false;
+ }
+ for (y = 0L; y < Height; y++) {
+ GetRow(Image, y, Line, Width);
+ ConvertToInterpolationCoefficients(Line, Width, Pole, NbPoles, DBL_EPSILON);
+ PutRow(Image, y, Line, Width);
+ }
+ free(Line);
+
+ // in-place separable process, along y
+ Line = (double *)malloc(Height * sizeof(double));
+ if (Line == NULL) {
+ // Column allocation failed
+ return false;
+ }
+ for (x = 0L; x < Width; x++) {
+ GetColumn(Image, Width, x, Line, Height);
+ ConvertToInterpolationCoefficients(Line, Height, Pole, NbPoles, DBL_EPSILON);
+ PutColumn(Image, Width, x, Line, Height);
+ }
+ free(Line);
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interpolation routines
+
+/**
+Perform the bidimensional interpolation of an image.
+Given an array of spline coefficients, return the value of
+the underlying continuous spline model, sampled at the location (x, y).
+The model degree can be 2 (quadratic), 3 (cubic), 4 (quartic), or 5 (quintic).
+
+@param Bcoeff Input B-spline array of coefficients
+@param Width Width of the image
+@param Height Height of the image
+@param x x coordinate where to interpolate
+@param y y coordinate where to interpolate
+@param spline_degree Degree of the spline model
+@return Returns the value of the underlying continuous spline model,
+sampled at the location (x, y)
+*/
+static double
+InterpolatedValue(double *Bcoeff, long Width, long Height, double x, double y, long spline_degree) {
+ double *p;
+ double xWeight[6], yWeight[6];
+ double interpolated;
+ double w, w2, w4, t, t0, t1;
+ long xIndex[6], yIndex[6];
+ long Width2 = 2L * Width - 2L, Height2 = 2L * Height - 2L;
+ long i, j, k;
+
+ // compute the interpolation indexes
+ if (spline_degree & 1L) {
+ i = (long)floor(x) - spline_degree / 2L;
+ j = (long)floor(y) - spline_degree / 2L;
+ for(k = 0; k <= spline_degree; k++) {
+ xIndex[k] = i++;
+ yIndex[k] = j++;
+ }
+ }
+ else {
+ i = (long)floor(x + 0.5) - spline_degree / 2L;
+ j = (long)floor(y + 0.5) - spline_degree / 2L;
+ for (k = 0; k <= spline_degree; k++) {
+ xIndex[k] = i++;
+ yIndex[k] = j++;
+ }
+ }
+
+ // compute the interpolation weights
+ switch (spline_degree) {
+ case 2L:
+ /* x */
+ w = x - (double)xIndex[1];
+ xWeight[1] = 3.0 / 4.0 - w * w;
+ xWeight[2] = (1.0 / 2.0) * (w - xWeight[1] + 1.0);
+ xWeight[0] = 1.0 - xWeight[1] - xWeight[2];
+ /* y */
+ w = y - (double)yIndex[1];
+ yWeight[1] = 3.0 / 4.0 - w * w;
+ yWeight[2] = (1.0 / 2.0) * (w - yWeight[1] + 1.0);
+ yWeight[0] = 1.0 - yWeight[1] - yWeight[2];
+ break;
+ case 3L:
+ /* x */
+ w = x - (double)xIndex[1];
+ xWeight[3] = (1.0 / 6.0) * w * w * w;
+ xWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - xWeight[3];
+ xWeight[2] = w + xWeight[0] - 2.0 * xWeight[3];
+ xWeight[1] = 1.0 - xWeight[0] - xWeight[2] - xWeight[3];
+ /* y */
+ w = y - (double)yIndex[1];
+ yWeight[3] = (1.0 / 6.0) * w * w * w;
+ yWeight[0] = (1.0 / 6.0) + (1.0 / 2.0) * w * (w - 1.0) - yWeight[3];
+ yWeight[2] = w + yWeight[0] - 2.0 * yWeight[3];
+ yWeight[1] = 1.0 - yWeight[0] - yWeight[2] - yWeight[3];
+ break;
+ case 4L:
+ /* x */
+ w = x - (double)xIndex[2];
+ w2 = w * w;
+ t = (1.0 / 6.0) * w2;
+ xWeight[0] = 1.0 / 2.0 - w;
+ xWeight[0] *= xWeight[0];
+ xWeight[0] *= (1.0 / 24.0) * xWeight[0];
+ t0 = w * (t - 11.0 / 24.0);
+ t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
+ xWeight[1] = t1 + t0;
+ xWeight[3] = t1 - t0;
+ xWeight[4] = xWeight[0] + t0 + (1.0 / 2.0) * w;
+ xWeight[2] = 1.0 - xWeight[0] - xWeight[1] - xWeight[3] - xWeight[4];
+ /* y */
+ w = y - (double)yIndex[2];
+ w2 = w * w;
+ t = (1.0 / 6.0) * w2;
+ yWeight[0] = 1.0 / 2.0 - w;
+ yWeight[0] *= yWeight[0];
+ yWeight[0] *= (1.0 / 24.0) * yWeight[0];
+ t0 = w * (t - 11.0 / 24.0);
+ t1 = 19.0 / 96.0 + w2 * (1.0 / 4.0 - t);
+ yWeight[1] = t1 + t0;
+ yWeight[3] = t1 - t0;
+ yWeight[4] = yWeight[0] + t0 + (1.0 / 2.0) * w;
+ yWeight[2] = 1.0 - yWeight[0] - yWeight[1] - yWeight[3] - yWeight[4];
+ break;
+ case 5L:
+ /* x */
+ w = x - (double)xIndex[2];
+ w2 = w * w;
+ xWeight[5] = (1.0 / 120.0) * w * w2 * w2;
+ w2 -= w;
+ w4 = w2 * w2;
+ w -= 1.0 / 2.0;
+ t = w2 * (w2 - 3.0);
+ xWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - xWeight[5];
+ t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
+ t1 = (-1.0 / 12.0) * w * (t + 4.0);
+ xWeight[2] = t0 + t1;
+ xWeight[3] = t0 - t1;
+ t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
+ t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
+ xWeight[1] = t0 + t1;
+ xWeight[4] = t0 - t1;
+ /* y */
+ w = y - (double)yIndex[2];
+ w2 = w * w;
+ yWeight[5] = (1.0 / 120.0) * w * w2 * w2;
+ w2 -= w;
+ w4 = w2 * w2;
+ w -= 1.0 / 2.0;
+ t = w2 * (w2 - 3.0);
+ yWeight[0] = (1.0 / 24.0) * (1.0 / 5.0 + w2 + w4) - yWeight[5];
+ t0 = (1.0 / 24.0) * (w2 * (w2 - 5.0) + 46.0 / 5.0);
+ t1 = (-1.0 / 12.0) * w * (t + 4.0);
+ yWeight[2] = t0 + t1;
+ yWeight[3] = t0 - t1;
+ t0 = (1.0 / 16.0) * (9.0 / 5.0 - t);
+ t1 = (1.0 / 24.0) * w * (w4 - w2 - 5.0);
+ yWeight[1] = t0 + t1;
+ yWeight[4] = t0 - t1;
+ break;
+ default:
+ // Invalid spline degree
+ return 0;
+ }
+
+ // apply the mirror boundary conditions
+ for(k = 0; k <= spline_degree; k++) {
+ xIndex[k] = (Width == 1L) ? (0L) : ((xIndex[k] < 0L) ?
+ (-xIndex[k] - Width2 * ((-xIndex[k]) / Width2))
+ : (xIndex[k] - Width2 * (xIndex[k] / Width2)));
+ if (Width <= xIndex[k]) {
+ xIndex[k] = Width2 - xIndex[k];
+ }
+ yIndex[k] = (Height == 1L) ? (0L) : ((yIndex[k] < 0L) ?
+ (-yIndex[k] - Height2 * ((-yIndex[k]) / Height2))
+ : (yIndex[k] - Height2 * (yIndex[k] / Height2)));
+ if (Height <= yIndex[k]) {
+ yIndex[k] = Height2 - yIndex[k];
+ }
+ }
+
+ // perform interpolation
+ interpolated = 0.0;
+ for(j = 0; j <= spline_degree; j++) {
+ p = Bcoeff + (yIndex[j] * Width);
+ w = 0.0;
+ for(i = 0; i <= spline_degree; i++) {
+ w += xWeight[i] * p[xIndex[i]];
+ }
+ interpolated += yWeight[j] * w;
+ }
+
+ return interpolated;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// FreeImage implementation
+
+
+/**
+ Image translation and rotation using B-Splines.
+
+ @param dib Input 8-bit greyscale image
+ @param angle Output image rotation in degree
+ @param x_shift Output image horizontal shift
+ @param y_shift Output image vertical shift
+ @param x_origin Output origin of the x-axis
+ @param y_origin Output origin of the y-axis
+ @param spline_degree Output degree of the B-spline model
+ @param use_mask Whether or not to mask the image
+ @return Returns the translated & rotated dib if successful, returns NULL otherwise
+*/
+static FIBITMAP *
+Rotate8Bit(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, long spline_degree, BOOL use_mask) {
+ double *ImageRasterArray;
+ double p;
+ double a11, a12, a21, a22;
+ double x0, y0, x1, y1;
+ long x, y;
+ long spline;
+ bool bResult;
+
+ int bpp = FreeImage_GetBPP(dib);
+ if(bpp != 8) {
+ return NULL;
+ }
+
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+ switch(spline_degree) {
+ case ROTATE_QUADRATIC:
+ spline = 2L; // Use splines of degree 2 (quadratic interpolation)
+ break;
+ case ROTATE_CUBIC:
+ spline = 3L; // Use splines of degree 3 (cubic interpolation)
+ break;
+ case ROTATE_QUARTIC:
+ spline = 4L; // Use splines of degree 4 (quartic interpolation)
+ break;
+ case ROTATE_QUINTIC:
+ spline = 5L; // Use splines of degree 5 (quintic interpolation)
+ break;
+ default:
+ spline = 3L;
+ }
+
+ // allocate output image
+ FIBITMAP *dst = FreeImage_Allocate(width, height, bpp);
+ if(!dst)
+ return NULL;
+ // buid a grey scale palette
+ RGBQUAD *pal = FreeImage_GetPalette(dst);
+ for(int i = 0; i < 256; i++) {
+ pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = (BYTE)i;
+ }
+
+ // allocate a temporary array
+ ImageRasterArray = (double*)malloc(width * height * sizeof(double));
+ if(!ImageRasterArray) {
+ FreeImage_Unload(dst);
+ return NULL;
+ }
+ // copy data samples
+ for(y = 0; y < height; y++) {
+ double *pImage = &ImageRasterArray[y*width];
+ BYTE *src_bits = FreeImage_GetScanLine(dib, height-1-y);
+
+ for(x = 0; x < width; x++) {
+ pImage[x] = (double)src_bits[x];
+ }
+ }
+
+ // convert between a representation based on image samples
+ // and a representation based on image B-spline coefficients
+ bResult = SamplesToCoefficients(ImageRasterArray, width, height, spline);
+ if(!bResult) {
+ FreeImage_Unload(dst);
+ free(ImageRasterArray);
+ return NULL;
+ }
+
+ // prepare the geometry
+ angle *= PI / 180.0;
+ a11 = cos(angle);
+ a12 = -sin(angle);
+ a21 = sin(angle);
+ a22 = cos(angle);
+ x0 = a11 * (x_shift + x_origin) + a12 * (y_shift + y_origin);
+ y0 = a21 * (x_shift + x_origin) + a22 * (y_shift + y_origin);
+ x_shift = x_origin - x0;
+ y_shift = y_origin - y0;
+
+ // visit all pixels of the output image and assign their value
+ for(y = 0; y < height; y++) {
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, height-1-y);
+
+ x0 = a12 * (double)y + x_shift;
+ y0 = a22 * (double)y + y_shift;
+
+ for(x = 0; x < width; x++) {
+ x1 = x0 + a11 * (double)x;
+ y1 = y0 + a21 * (double)x;
+ if(use_mask) {
+ if((x1 <= -0.5) || (((double)width - 0.5) <= x1) || (y1 <= -0.5) || (((double)height - 0.5) <= y1)) {
+ p = 0;
+ }
+ else {
+ p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline);
+ }
+ }
+ else {
+ p = (double)InterpolatedValue(ImageRasterArray, width, height, x1, y1, spline);
+ }
+ // clamp and convert to BYTE
+ dst_bits[x] = (BYTE)MIN(MAX((int)0, (int)(p + 0.5)), (int)255);
+ }
+ }
+
+ // free working array and return
+ free(ImageRasterArray);
+
+ return dst;
+}
+
+/**
+ Image rotation using a 3rd order (cubic) B-Splines.
+
+ @param dib Input dib (8, 24 or 32-bit)
+ @param angle Output image rotation
+ @param x_shift Output image horizontal shift
+ @param y_shift Output image vertical shift
+ @param x_origin Output origin of the x-axis
+ @param y_origin Output origin of the y-axis
+ @param use_mask Whether or not to mask the image
+ @return Returns the translated & rotated dib if successful, returns NULL otherwise
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_RotateEx(FIBITMAP *dib, double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask) {
+
+ int x, y, bpp;
+ int channel, nb_channels;
+ BYTE *src_bits, *dst_bits;
+ FIBITMAP *src8 = NULL, *dst8 = NULL, *dst = NULL;
+
+ try {
+
+ bpp = FreeImage_GetBPP(dib);
+
+ if(bpp == 8) {
+ FIBITMAP *dst_8 = Rotate8Bit(dib, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask);
+ if(dst_8) {
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst_8, dib);
+ }
+ return dst_8;
+ }
+ if((bpp == 24) || (bpp == 32)) {
+ // allocate dst image
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+ if( bpp == 24 ) {
+ dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ } else {
+ dst = FreeImage_Allocate(width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+ if(!dst) throw(1);
+
+ // allocate a temporary 8-bit dib (no need to build a palette)
+ src8 = FreeImage_Allocate(width, height, 8);
+ if(!src8) throw(1);
+
+ // process each channel separately
+ // -------------------------------
+ nb_channels = (bpp / 8);
+
+ for(channel = 0; channel < nb_channels; channel++) {
+ // extract channel from source dib
+ for(y = 0; y < height; y++) {
+ src_bits = FreeImage_GetScanLine(dib, y);
+ dst_bits = FreeImage_GetScanLine(src8, y);
+ for(x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[channel];
+ src_bits += nb_channels;
+ }
+ }
+
+ // process channel
+ dst8 = Rotate8Bit(src8, angle, x_shift, y_shift, x_origin, y_origin, ROTATE_CUBIC, use_mask);
+ if(!dst8) throw(1);
+
+ // insert channel to destination dib
+ for(y = 0; y < height; y++) {
+ src_bits = FreeImage_GetScanLine(dst8, y);
+ dst_bits = FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ dst_bits[channel] = src_bits[x];
+ dst_bits += nb_channels;
+ }
+ }
+
+ FreeImage_Unload(dst8);
+ }
+
+ FreeImage_Unload(src8);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+
+ return dst;
+ }
+ } catch(int) {
+ if(src8) FreeImage_Unload(src8);
+ if(dst8) FreeImage_Unload(dst8);
+ if(dst) FreeImage_Unload(dst);
+ }
+
+ return NULL;
+}
diff --git a/Source/FreeImageToolkit/Background.cpp b/Source/FreeImageToolkit/Background.cpp
new file mode 100644
index 0000000..4de2176
--- /dev/null
+++ b/Source/FreeImageToolkit/Background.cpp
@@ -0,0 +1,897 @@
+// ==========================================================
+// Background filling routines
+//
+// Design and implementation by
+// - Carsten Klein (c.klein@datagis.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+/** @brief Determines, whether a palletized image is visually greyscale or not.
+
+ Unlike with FreeImage_GetColorType, which returns either FIC_MINISBLACK or
+ FIC_MINISWHITE for a greyscale image with a linear ramp palette, the return
+ value of this function does not depend on the palette's order, but only on the
+ palette's individual colors.
+ @param dib The image to be tested.
+ @return Returns TRUE if the palette of the image specified contains only
+ greyscales, FALSE otherwise.
+ */
+static BOOL
+IsVisualGreyscaleImage(FIBITMAP *dib) {
+
+ switch (FreeImage_GetBPP(dib)) {
+ case 1:
+ case 4:
+ case 8: {
+ unsigned ncolors = FreeImage_GetColorsUsed(dib);
+ RGBQUAD *rgb = FreeImage_GetPalette(dib);
+ for (unsigned i = 0; i< ncolors; i++) {
+ if ((rgb->rgbRed != rgb->rgbGreen) || (rgb->rgbRed != rgb->rgbBlue)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+ default: {
+ return (FreeImage_GetColorType(dib) == FIC_MINISBLACK);
+ }
+ }
+}
+
+/** @brief Looks up a specified color in a FIBITMAP's palette and returns the color's
+ palette index or -1 if the color was not found.
+
+ Unlike with FreeImage_GetColorType, which returns either FIC_MINISBLACK or
+ FIC_MINISWHITE for a greyscale image with a linear ramp palette, the return
+ value of this function does not depend on the palette's order, but only on the
+ palette's individual colors.
+ @param dib The image, whose palette should be searched through.
+ @param color The color to be searched in the palette.
+ @param options Options that affect the color search process.
+ @param color_type A pointer, that optionally specifies the image's color type as
+ returned by FreeImage_GetColorType. If invalid or NULL, this function determines the
+ color type with FreeImage_GetColorType.
+ @return Returns the specified color's palette index, the color's rgbReserved member
+ if option FI_COLOR_ALPHA_IS_INDEX was specified or -1, if the color was not found
+ in the image's palette or if the specified image is non-palletized.
+ */
+static int
+GetPaletteIndex(FIBITMAP *dib, const RGBQUAD *color, int options, FREE_IMAGE_COLOR_TYPE *color_type) {
+
+ int result = -1;
+
+ if ((!dib) || (!color)) {
+ return result;
+ }
+
+ int bpp = FreeImage_GetBPP(dib);
+
+ // First check trivial case: return color->rgbReserved if only
+ // FI_COLOR_ALPHA_IS_INDEX is set.
+ if ((options & FI_COLOR_ALPHA_IS_INDEX) == FI_COLOR_ALPHA_IS_INDEX) {
+ if (bpp == 1) {
+ return color->rgbReserved & 0x01;
+ } else if (bpp == 4) {
+ return color->rgbReserved & 0x0F;
+ }
+ return color->rgbReserved;
+ }
+
+ if (bpp == 8) {
+ FREE_IMAGE_COLOR_TYPE ct =
+ (color_type == NULL || *color_type < 0) ?
+ FreeImage_GetColorType(dib) : *color_type;
+ if (ct == FIC_MINISBLACK) {
+ return GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
+ }
+ if (ct == FIC_MINISWHITE) {
+ return 255 - GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
+ }
+ } else if (bpp > 8) {
+ // for palettized images only
+ return result;
+ }
+
+ if (options & FI_COLOR_FIND_EQUAL_COLOR) {
+
+ // Option FI_COLOR_ALPHA_IS_INDEX is implicit here so, set
+ // index to color->rgbReserved
+ result = color->rgbReserved;
+ if (bpp == 1) {
+ result &= 0x01;
+ } else if (bpp == 4) {
+ result &= 0x0F;
+ }
+
+ unsigned ucolor;
+ if (!IsVisualGreyscaleImage(dib)) {
+ ucolor = (*((unsigned *)color)) & 0xFFFFFF;
+ } else {
+ ucolor = GREY(color->rgbRed, color->rgbGreen, color->rgbBlue) * 0x010101;
+ //ucolor = (ucolor | (ucolor << 8) | (ucolor << 16));
+ }
+ unsigned ncolors = FreeImage_GetColorsUsed(dib);
+ unsigned *palette = (unsigned *)FreeImage_GetPalette(dib);
+ for (unsigned i = 0; i < ncolors; i++) {
+ if ((palette[i] & 0xFFFFFF) == ucolor) {
+ result = i;
+ break;
+ }
+ }
+ } else {
+ unsigned minimum = UINT_MAX;
+ unsigned ncolors = FreeImage_GetColorsUsed(dib);
+ BYTE *palette = (BYTE *)FreeImage_GetPalette(dib);
+ BYTE red, green, blue;
+ if (!IsVisualGreyscaleImage(dib)) {
+ red = color->rgbRed;
+ green = color->rgbGreen;
+ blue = color->rgbBlue;
+ } else {
+ red = GREY(color->rgbRed, color->rgbGreen, color->rgbBlue);
+ green = blue = red;
+ }
+ for (unsigned i = 0; i < ncolors; i++) {
+ unsigned m = abs(palette[FI_RGBA_BLUE] - blue)
+ + abs(palette[FI_RGBA_GREEN] - green)
+ + abs(palette[FI_RGBA_RED] - red);
+ if (m < minimum) {
+ minimum = m;
+ result = i;
+ if (m == 0) {
+ break;
+ }
+ }
+ palette += sizeof(RGBQUAD);
+ }
+ }
+ return result;
+}
+
+/** @brief Blends an alpha-transparent foreground color over an opaque background
+ color.
+
+ This function blends the alpha-transparent foreground color fgcolor over the
+ background color bgcolor. The background color is considered fully opaque,
+ whatever it's alpha value contains, whereas the foreground color is considered
+ to be a real RGBA color with an alpha value, which is used for the blend
+ operation. The resulting color is returned through the blended parameter.
+ @param bgcolor The background color for the blend operation.
+ @param fgcolor The foreground color for the blend operation. This color's alpha
+ value, stored in the rgbReserved member, is the alpha value used for the blend
+ operation.
+ @param blended This out parameter takes the blended color and so, returns it to
+ the caller. This color's alpha value will be 0xFF (255) so, the blended color
+ itself has no transparency. The this argument is not changed, if the function
+ fails.
+ @return Returns TRUE on success, FALSE otherwise. This function fails if any of
+ the color arguments is a null pointer.
+ */
+static BOOL
+GetAlphaBlendedColor(const RGBQUAD *bgcolor, const RGBQUAD *fgcolor, RGBQUAD *blended) {
+
+ if ((!bgcolor) || (!fgcolor) || (!blended)) {
+ return FALSE;
+ }
+
+ BYTE alpha = fgcolor->rgbReserved;
+ BYTE not_alpha = ~alpha;
+
+ blended->rgbRed = (BYTE)( ((WORD)fgcolor->rgbRed * alpha + not_alpha * (WORD)bgcolor->rgbRed) >> 8 );
+ blended->rgbGreen = (BYTE)( ((WORD)fgcolor->rgbGreen * alpha + not_alpha * (WORD)bgcolor->rgbGreen) >> 8) ;
+ blended->rgbBlue = (BYTE)( ((WORD)fgcolor->rgbRed * alpha + not_alpha * (WORD)bgcolor->rgbBlue) >> 8 );
+ blended->rgbReserved = 0xFF;
+
+ return TRUE;
+}
+
+/** @brief Fills a FIT_BITMAP image with the specified color.
+
+ This function does the dirty work for FreeImage_FillBackground for FIT_BITMAP
+ images.
+ @param dib The image to be filled.
+ @param color The color, the specified image should be filled with.
+ @param options Options that affect the color search process for palletized images.
+ @return Returns TRUE on success, FALSE otherwise. This function fails if any of
+ the dib and color is NULL or the provided image is not a FIT_BITMAP image.
+ */
+static BOOL
+FillBackgroundBitmap(FIBITMAP *dib, const RGBQUAD *color, int options) {
+
+ if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
+ return FALSE;;
+ }
+
+ if (!color) {
+ return FALSE;
+ }
+
+ const RGBQUAD *color_intl = color;
+ unsigned bpp = FreeImage_GetBPP(dib);
+ unsigned width = FreeImage_GetWidth(dib);
+ unsigned height = FreeImage_GetHeight(dib);
+
+ FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
+
+ // get a pointer to the first scanline (bottom line)
+ BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
+ BYTE *dst_bits = src_bits;
+
+ BOOL supports_alpha = ((bpp >= 24) || ((bpp == 8) && (color_type != FIC_PALETTE)));
+
+ // Check for RGBA case if bitmap supports alpha
+ // blending (8-bit greyscale, 24- or 32-bit images)
+ if (supports_alpha && (options & FI_COLOR_IS_RGBA_COLOR)) {
+
+ if (color->rgbReserved == 0) {
+ // the fill color is fully transparent; we are done
+ return TRUE;
+ }
+
+ // Only if the fill color is NOT fully opaque, draw it with
+ // the (much) slower FreeImage_DrawLine function and return.
+ // Since we do not have the FreeImage_DrawLine function in this
+ // release, just assume to have an unicolor background and fill
+ // all with an 'alpha-blended' color.
+ if (color->rgbReserved < 255) {
+
+ // If we will draw on an unicolor background, it's
+ // faster to draw opaque with an alpha blended color.
+ // So, first get the color from the first pixel in the
+ // image (bottom-left pixel).
+ RGBQUAD bgcolor;
+ if (bpp == 8) {
+ bgcolor = FreeImage_GetPalette(dib)[*src_bits];
+ } else {
+ bgcolor.rgbBlue = src_bits[FI_RGBA_BLUE];
+ bgcolor.rgbGreen = src_bits[FI_RGBA_GREEN];
+ bgcolor.rgbRed = src_bits[FI_RGBA_RED];
+ bgcolor.rgbReserved = 0xFF;
+ }
+ RGBQUAD blend;
+ GetAlphaBlendedColor(&bgcolor, color_intl, &blend);
+ color_intl = &blend;
+ }
+ }
+
+ int index = (bpp <= 8) ? GetPaletteIndex(dib, color_intl, options, &color_type) : 0;
+ if (index == -1) {
+ // No palette index found for a palletized
+ // image. This should never happen...
+ return FALSE;
+ }
+
+ // first, build the first scanline (line 0)
+ switch (bpp) {
+ case 1: {
+ unsigned bytes = (width / 8);
+ memset(dst_bits, ((index == 1) ? 0xFF : 0x00), bytes);
+ //int n = width % 8;
+ int n = width & 7;
+ if (n) {
+ if (index == 1) {
+ // set n leftmost bits
+ dst_bits[bytes] |= (0xFF << (8 - n));
+ } else {
+ // clear n leftmost bits
+ dst_bits[bytes] &= (0xFF >> n);
+ }
+ }
+ break;
+ }
+ case 4: {
+ unsigned bytes = (width / 2);
+ memset(dst_bits, (index | (index << 4)), bytes);
+ //if (bytes % 2) {
+ if (bytes & 1) {
+ dst_bits[bytes] &= 0x0F;
+ dst_bits[bytes] |= (index << 4);
+ }
+ break;
+ }
+ case 8: {
+ memset(dst_bits, index, FreeImage_GetLine(dib));
+ break;
+ }
+ case 16: {
+ WORD wcolor = RGBQUAD_TO_WORD(dib, color_intl);
+ for (unsigned x = 0; x < width; x++) {
+ ((WORD *)dst_bits)[x] = wcolor;
+ }
+ break;
+ }
+ case 24: {
+ RGBTRIPLE rgbt = *((RGBTRIPLE *)color_intl);
+ for (unsigned x = 0; x < width; x++) {
+ ((RGBTRIPLE *)dst_bits)[x] = rgbt;
+ }
+ break;
+ }
+ case 32: {
+ RGBQUAD rgbq;
+ rgbq.rgbBlue = ((RGBTRIPLE *)color_intl)->rgbtBlue;
+ rgbq.rgbGreen = ((RGBTRIPLE *)color_intl)->rgbtGreen;
+ rgbq.rgbRed = ((RGBTRIPLE *)color_intl)->rgbtRed;
+ rgbq.rgbReserved = 0xFF;
+ for (unsigned x = 0; x < width; x++) {
+ ((RGBQUAD *)dst_bits)[x] = rgbq;
+ }
+ break;
+ }
+ default:
+ return FALSE;
+ }
+
+ // Then, copy the first scanline into all following scanlines.
+ // 'src_bits' is a pointer to the first scanline and is already
+ // set up correctly.
+ if (src_bits) {
+ unsigned pitch = FreeImage_GetPitch(dib);
+ unsigned bytes = FreeImage_GetLine(dib);
+ dst_bits = src_bits + pitch;
+ for (unsigned y = 1; y < height; y++) {
+ memcpy(dst_bits, src_bits, bytes);
+ dst_bits += pitch;
+ }
+ }
+ return TRUE;
+}
+
+/** @brief Fills an image with the specified color.
+
+ This function sets all pixels of an image to the color provided through the color
+ parameter. Since this should work for all image types supported by FreeImage, the
+ pointer color must point to a memory location, which is at least as large as the
+ image's color value, if this size is greater than 4 bytes. As the color is specified
+ by an RGBQUAD structure for all images of type FIT_BITMAP (including all palletized
+ images), the smallest possible size of this memory is the size of the RGBQUAD structure,
+ which uses 4 bytes.
+
+ So, color must point to a double, if the image to be filled is of type FIT_DOUBLE and
+ point to a RGBF structure if the image is of type FIT_RGBF and so on.
+
+ However, the fill color is always specified through a RGBQUAD structure for all images
+ of type FIT_BITMAP. So, for 32- and 24-bit images, the red, green and blue members of
+ the RGBQUAD structure are directly used for the image's red, green and blue channel
+ respectively. Although alpha transparent RGBQUAD colors are supported, the alpha channel
+ of a 32-bit image never gets modified by this function. A fill color with an alpha value
+ smaller than 255 gets blended with the image's actual background color, which is determined
+ from the image's bottom-left pixel. So, currently using alpha enabled colors, assumes the
+ image to be unicolor before the fill operation. However, the RGBQUAD's rgbReserved member is
+ only taken into account, if option FI_COLOR_IS_RGBA_COLOR has been specified.
+
+ For 16-bit images, the red-, green- and blue components of the specified color are
+ transparently translated into either the 16-bit 555 or 565 representation. This depends
+ on the image's actual red- green- and blue masks.
+
+ Special attention must be payed for palletized images. Generally, the RGB color specified
+ is looked up in the image's palette. The found palette index is then used to fill the image.
+ There are some option flags, that affect this lookup process:
+
+ no option specified (0x00) Uses the color, that is nearest to the specified color.
+ This is the default behavior and should always find a
+ color in the palette. However, the visual result may
+ far from what was expected and mainly depends on the
+ image's palette.
+
+ FI_COLOR_FIND_EQUAL_COLOR (0x02) Searches the image's palette for the specified color
+ but only uses the returned palette index, if the specified
+ color exactly matches the palette entry. Of course,
+ depending on the image's actual palette entries, this
+ operation may fail. In this case, the function falls back
+ to option FI_COLOR_ALPHA_IS_INDEX and uses the RGBQUAD's
+ rgbReserved member (or its low nibble for 4-bit images
+ or its least significant bit (LSB) for 1-bit images) as
+ the palette index used for the fill operation.
+
+ FI_COLOR_ALPHA_IS_INDEX (0x04) Does not perform any color lookup from the palette, but
+ uses the RGBQUAD's alpha channel member rgbReserved as
+ the palette index to be used for the fill operation.
+ However, for 4-bit images, only the low nibble of the
+ rgbReserved member are used and for 1-bit images, only
+ the least significant bit (LSB) is used.
+
+ This function fails if any of dib and color is NULL.
+
+ @param dib The image to be filled.
+ @param color A pointer to the color value to be used for filling the image. The
+ memory pointed to by this pointer is always assumed to be at least as large as the
+ image's color value, but never smaller than the size of an RGBQUAD structure.
+ @param options Options that affect the color search process for palletized images.
+ @return Returns TRUE on success, FALSE otherwise. This function fails if any of
+ dib and color is NULL.
+ */
+BOOL DLL_CALLCONV
+FreeImage_FillBackground(FIBITMAP *dib, const void *color, int options) {
+
+ if (!dib) {
+ return FALSE;
+ }
+
+ if (!color) {
+ return FALSE;
+ }
+
+ // handle FIT_BITMAP images with FreeImage_FillBackground()
+ if (FreeImage_GetImageType(dib) == FIT_BITMAP) {
+ return FillBackgroundBitmap(dib, (RGBQUAD *)color, options);
+ }
+
+ // first, construct the first scanline (bottom line)
+ unsigned bytespp = (FreeImage_GetBPP(dib) / 8);
+ BYTE *src_bits = FreeImage_GetScanLine(dib, 0);
+ BYTE *dst_bits = src_bits;
+ for (unsigned x = 0; x < FreeImage_GetWidth(dib); x++) {
+ memcpy(dst_bits, color, bytespp);
+ dst_bits += bytespp;
+ }
+
+ // then, copy the first scanline into all following scanlines
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned pitch = FreeImage_GetPitch(dib);
+ unsigned bytes = FreeImage_GetLine(dib);
+ dst_bits = src_bits + pitch;
+ for (unsigned y = 1; y < height; y++) {
+ memcpy(dst_bits, src_bits, bytes);
+ dst_bits += pitch;
+ }
+ return TRUE;
+}
+
+/** @brief Allocates a new image of the specified type, width, height and bit depth and
+ optionally fills it with the specified color.
+
+ This function is an extension to FreeImage_AllocateT, which additionally supports specifying
+ a palette to be set for the newly create image, as well as specifying a background color,
+ the newly created image should initially be filled with.
+
+ Basically, this function internally relies on function FreeImage_AllocateT, followed by a
+ call to FreeImage_FillBackground. This is why both parameters color and options behave the
+ same as it is documented for function FreeImage_FillBackground. So, please refer to the
+ documentation of FreeImage_FillBackground to learn more about parameters color and options.
+
+ The palette specified through parameter palette is only copied to the newly created
+ image, if its image type is FIT_BITMAP and the desired bit depth is smaller than or equal
+ to 8 bits per pixel. In other words, the palette parameter is only taken into account for
+ palletized images. However, if the preceding conditions match and if palette is not NULL,
+ the memory pointed to by the palette pointer is assumed to be at least as large as size
+ of a fully populated palette for the desired bit depth. So, for an 8-bit image, this size
+ is 256 x sizeof(RGBQUAD), for an 4-bit image it is 16 x sizeof(RGBQUAD) and it is
+ 2 x sizeof(RGBQUAD) for a 1-bit image. In other words, this function does not support
+ partial palettes.
+
+ However, specifying a palette is not necessarily needed, even for palletized images. This
+ function is capable of implicitly creating a palette, if parameter palette is NULL. If the
+ specified background color is a greyscale value (red = green = blue) or if option
+ FI_COLOR_ALPHA_IS_INDEX is specified, a greyscale palette is created. For a 1-bit image, only
+ if the specified background color is either black or white, a monochrome palette, consisting
+ of black and white only is created. In any case, the darker colors are stored at the smaller
+ palette indices.
+
+ If the specified background color is not a greyscale value, or is neither black nor white
+ for a 1-bit image, solely this single color is injected into the otherwise black-initialized
+ palette. For this operation, option FI_COLOR_ALPHA_IS_INDEX is implicit, so the specified
+ color is applied to the palette entry, specified by the background color's rgbReserved
+ member. The image is then filled with this palette index.
+
+ This function returns a newly created image as function FreeImage_AllocateT does, if both
+ parameters color and palette are NULL. If only color is NULL, the palette pointed to by
+ parameter palette is initially set for the new image, if a palletized image of type
+ FIT_BITMAP is created. However, in the latter case, this function returns an image, whose
+ pixels are all initialized with zeros so, the image will be filled with the color of the
+ first palette entry.
+
+ @param type Specifies the image type of the new image.
+ @param width The desired width in pixels of the new image.
+ @param height The desired height in pixels of the new image.
+ @param bpp The desired bit depth of the new image.
+ @param color A pointer to the color value to be used for filling the image. The
+ memory pointed to by this pointer is always assumed to be at least as large as the
+ image's color value but never smaller than the size of an RGBQUAD structure.
+ @param options Options that affect the color search process for palletized images.
+ @param red_mask Specifies the bits used to store the red components of a pixel.
+ @param green_mask Specifies the bits used to store the green components of a pixel.
+ @param blue_mask Specifies the bits used to store the blue components of a pixel.
+ @return Returns a pointer to a newly allocated image on success, NULL otherwise.
+ */
+FIBITMAP * DLL_CALLCONV
+FreeImage_AllocateExT(FREE_IMAGE_TYPE type, int width, int height, int bpp, const void *color, int options, const RGBQUAD *palette, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
+
+ FIBITMAP *bitmap = FreeImage_AllocateT(type, width, height, bpp, red_mask, green_mask, blue_mask);
+
+ if (!color) {
+ if ((palette) && (type == FIT_BITMAP) && (bpp <= 8)) {
+ memcpy(FreeImage_GetPalette(bitmap), palette, FreeImage_GetColorsUsed(bitmap) * sizeof(RGBQUAD));
+ }
+ return bitmap;
+ }
+
+ if (bitmap != NULL) {
+
+ // Only fill the new bitmap if the specified color
+ // differs from "black", that is not all bytes of the
+ // color are equal to zero.
+ switch (bpp) {
+ case 1: {
+ // although 1-bit implies FIT_BITMAP, better get an unsigned
+ // color and palette
+ unsigned *urgb = (unsigned *)color;
+ unsigned *upal = (unsigned *)FreeImage_GetPalette(bitmap);
+ RGBQUAD rgbq = RGBQUAD();
+
+ if (palette != NULL) {
+ // clone the specified palette
+ memcpy(FreeImage_GetPalette(bitmap), palette, 2 * sizeof(RGBQUAD));
+ } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
+ CREATE_GREYSCALE_PALETTE(upal, 2);
+ } else {
+ // check, whether the specified color is either black or white
+ if ((*urgb & 0xFFFFFF) == 0x000000) {
+ // in any case build a FIC_MINISBLACK palette
+ CREATE_GREYSCALE_PALETTE(upal, 2);
+ color = &rgbq;
+ } else if ((*urgb & 0xFFFFFF) == 0xFFFFFF) {
+ // in any case build a FIC_MINISBLACK palette
+ CREATE_GREYSCALE_PALETTE(upal, 2);
+ rgbq.rgbReserved = 1;
+ color = &rgbq;
+ } else {
+ // Otherwise inject the specified color into the so far
+ // black-only palette. We use color->rgbReserved as the
+ // desired palette index.
+ BYTE index = ((RGBQUAD *)color)->rgbReserved & 0x01;
+ upal[index] = *urgb & 0x00FFFFFF;
+ }
+ options |= FI_COLOR_ALPHA_IS_INDEX;
+ }
+ // and defer to FreeImage_FillBackground
+ FreeImage_FillBackground(bitmap, color, options);
+ break;
+ }
+ case 4: {
+ // 4-bit implies FIT_BITMAP so, get a RGBQUAD color
+ RGBQUAD *rgb = (RGBQUAD *)color;
+ RGBQUAD *pal = FreeImage_GetPalette(bitmap);
+ RGBQUAD rgbq = RGBQUAD();
+
+ if (palette != NULL) {
+ // clone the specified palette
+ memcpy(pal, palette, 16 * sizeof(RGBQUAD));
+ } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
+ CREATE_GREYSCALE_PALETTE(pal, 16);
+ } else {
+ // check, whether the specified color is a grey one
+ if ((rgb->rgbRed == rgb->rgbGreen) && (rgb->rgbRed == rgb->rgbBlue)) {
+ // if so, build a greyscale palette
+ CREATE_GREYSCALE_PALETTE(pal, 16);
+ rgbq.rgbReserved = rgb->rgbRed >> 4;
+ color = &rgbq;
+ } else {
+ // Otherwise inject the specified color into the so far
+ // black-only palette. We use color->rgbReserved as the
+ // desired palette index.
+ BYTE index = (rgb->rgbReserved & 0x0F);
+ ((unsigned *)pal)[index] = *((unsigned *)rgb) & 0x00FFFFFF;
+ }
+ options |= FI_COLOR_ALPHA_IS_INDEX;
+ }
+ // and defer to FreeImage_FillBackground
+ FreeImage_FillBackground(bitmap, color, options);
+ break;
+ }
+ case 8: {
+ // 8-bit implies FIT_BITMAP so, get a RGBQUAD color
+ RGBQUAD *rgb = (RGBQUAD *)color;
+ RGBQUAD *pal = FreeImage_GetPalette(bitmap);
+ RGBQUAD rgbq;
+
+ if (palette != NULL) {
+ // clone the specified palette
+ memcpy(pal, palette, 256 * sizeof(RGBQUAD));
+ } else if (options & FI_COLOR_ALPHA_IS_INDEX) {
+ CREATE_GREYSCALE_PALETTE(pal, 256);
+ } else {
+ // check, whether the specified color is a grey one
+ if ((rgb->rgbRed == rgb->rgbGreen) && (rgb->rgbRed == rgb->rgbBlue)) {
+ // if so, build a greyscale palette
+ CREATE_GREYSCALE_PALETTE(pal, 256);
+ rgbq.rgbReserved = rgb->rgbRed;
+ color = &rgbq;
+ } else {
+ // Otherwise inject the specified color into the so far
+ // black-only palette. We use color->rgbReserved as the
+ // desired palette index.
+ BYTE index = rgb->rgbReserved;
+ ((unsigned *)pal)[index] = *((unsigned *)rgb) & 0x00FFFFFF;
+ }
+ options |= FI_COLOR_ALPHA_IS_INDEX;
+ }
+ // and defer to FreeImage_FillBackground
+ FreeImage_FillBackground(bitmap, color, options);
+ break;
+ }
+ case 16: {
+ WORD wcolor = (type == FIT_BITMAP) ?
+ RGBQUAD_TO_WORD(bitmap, ((RGBQUAD *)color)) : *((WORD *)color);
+ if (wcolor != 0) {
+ FreeImage_FillBackground(bitmap, color, options);
+ }
+ break;
+ }
+ default: {
+ int bytespp = bpp / 8;
+ for (int i = 0; i < bytespp; i++) {
+ if (((BYTE *)color)[i] != 0) {
+ FreeImage_FillBackground(bitmap, color, options);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return bitmap;
+}
+
+/** @brief Allocates a new image of the specified width, height and bit depth and optionally
+ fills it with the specified color.
+
+ This function is an extension to FreeImage_Allocate, which additionally supports specifying
+ a palette to be set for the newly create image, as well as specifying a background color,
+ the newly created image should initially be filled with.
+
+ Basically, this function internally relies on function FreeImage_Allocate, followed by a
+ call to FreeImage_FillBackground. This is why both parameters color and options behave the
+ same as it is documented for function FreeImage_FillBackground. So, please refer to the
+ documentation of FreeImage_FillBackground to learn more about parameters color and options.
+
+ The palette specified through parameter palette is only copied to the newly created
+ image, if the desired bit depth is smaller than or equal to 8 bits per pixel. In other words,
+ the palette parameter is only taken into account for palletized images. However, if the
+ image to be created is a palletized image and if palette is not NULL, the memory pointed to
+ by the palette pointer is assumed to be at least as large as size of a fully populated
+ palette for the desired bit depth. So, for an 8-bit image, this size is 256 x sizeof(RGBQUAD),
+ for an 4-bit image it is 16 x sizeof(RGBQUAD) and it is 2 x sizeof(RGBQUAD) for a 1-bit
+ image. In other words, this function does not support partial palettes.
+
+ However, specifying a palette is not necessarily needed, even for palletized images. This
+ function is capable of implicitly creating a palette, if parameter palette is NULL. If the
+ specified background color is a greyscale value (red = green = blue) or if option
+ FI_COLOR_ALPHA_IS_INDEX is specified, a greyscale palette is created. For a 1-bit image, only
+ if the specified background color is either black or white, a monochrome palette, consisting
+ of black and white only is created. In any case, the darker colors are stored at the smaller
+ palette indices.
+
+ If the specified background color is not a greyscale value, or is neither black nor white
+ for a 1-bit image, solely this single color is injected into the otherwise black-initialized
+ palette. For this operation, option FI_COLOR_ALPHA_IS_INDEX is implicit, so the specified
+ color is applied to the palette entry, specified by the background color's rgbReserved
+ member. The image is then filled with this palette index.
+
+ This function returns a newly created image as function FreeImage_Allocate does, if both
+ parameters color and palette are NULL. If only color is NULL, the palette pointed to by
+ parameter palette is initially set for the new image, if a palletized image of type
+ FIT_BITMAP is created. However, in the latter case, this function returns an image, whose
+ pixels are all initialized with zeros so, the image will be filled with the color of the
+ first palette entry.
+
+ @param width The desired width in pixels of the new image.
+ @param height The desired height in pixels of the new image.
+ @param bpp The desired bit depth of the new image.
+ @param color A pointer to an RGBQUAD structure, that provides the color to be used for
+ filling the image.
+ @param options Options that affect the color search process for palletized images.
+ @param red_mask Specifies the bits used to store the red components of a pixel.
+ @param green_mask Specifies the bits used to store the green components of a pixel.
+ @param blue_mask Specifies the bits used to store the blue components of a pixel.
+ @return Returns a pointer to a newly allocated image on success, NULL otherwise.
+ */
+FIBITMAP * DLL_CALLCONV
+FreeImage_AllocateEx(int width, int height, int bpp, const RGBQUAD *color, int options, const RGBQUAD *palette, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
+ return FreeImage_AllocateExT(FIT_BITMAP, width, height, bpp, ((void *)color), options, palette, red_mask, green_mask, blue_mask);
+}
+
+/** @brief Enlarges or shrinks an image selectively per side and fills newly added areas
+ with the specified background color.
+
+ This function enlarges or shrinks an image selectively per side. The main purpose of this
+ function is to add borders to an image. To add a border to any of the image's sides, a
+ positive integer value must be passed in any of the parameters left, top, right or bottom.
+ This value represents the border's width in pixels. Newly created parts of the image (the
+ border areas) are filled with the specified color. Specifying a negative integer value for
+ a certain side, will shrink or crop the image on this side. Consequently, specifying zero
+ for a certain side will not change the image's extension on that side.
+
+ So, calling this function with all parameters left, top, right and bottom set to zero, is
+ effectively the same as calling function FreeImage_Clone; setting all parameters left, top,
+ right and bottom to value equal to or smaller than zero, my easily be substituted by a call
+ to function FreeImage_Copy. Both these cases produce a new image, which is guaranteed not to
+ be larger than the input image. Thus, since the specified color is not needed in these cases,
+ the pointer color may be NULL.
+
+ Both parameters color and options work according to function FreeImage_FillBackground. So,
+ please refer to the documentation of FreeImage_FillBackground to learn more about parameters
+ color and options. For palletized images, the palette of the input image src is
+ transparently copied to the newly created enlarged or shrunken image, so any color
+ look-ups are performed on this palette.
+
+ Here are some examples, that illustrate, how to use the parameters left, top, right and
+ bottom:
+
+ // create a white color
+ RGBQUAD c;
+ c.rgbRed = 0xFF;
+ c.rgbGreen = 0xFF;
+ c.rgbBlue = 0xFF;
+ c.rgbReserved = 0x00;
+
+ // add a white, symmetric 10 pixel wide border to the image
+ dib2 = FreeImage_EnlargeCanvas(dib, 10, 10, 10, 10, &c, FI_COLOR_IS_RGB_COLOR);
+
+ // add white, 20 pixel wide stripes to the top and bottom side of the image
+ dib3 = FreeImage_EnlargeCanvas(dib, 0, 20, 0, 20, &c, FI_COLOR_IS_RGB_COLOR);
+
+ // add white, 30 pixel wide stripes to the right side of the image and
+ // cut off the 40 leftmost pixel columns
+ dib3 = FreeImage_EnlargeCanvas(dib, -40, 0, 30, 0, &c, FI_COLOR_IS_RGB_COLOR);
+
+ This function fails if either the input image is NULL or the pointer to the color is
+ NULL, while at least on of left, top, right and bottom is greater than zero. This
+ function also returns NULL, if the new image's size will be negative in either x- or
+ y-direction.
+
+ @param dib The image to be enlarged or shrunken.
+ @param left The number of pixels, the image should be enlarged on its left side. Negative
+ values shrink the image on its left side.
+ @param top The number of pixels, the image should be enlarged on its top side. Negative
+ values shrink the image on its top side.
+ @param right The number of pixels, the image should be enlarged on its right side. Negative
+ values shrink the image on its right side.
+ @param bottom The number of pixels, the image should be enlarged on its bottom side. Negative
+ values shrink the image on its bottom side.
+ @param color The color, the enlarged sides of the image should be filled with.
+ @param options Options that affect the color search process for palletized images.
+ @return Returns a pointer to a newly allocated enlarged or shrunken image on success,
+ NULL otherwise. This function fails if either the input image is NULL or the pointer to the
+ color is NULL, while at least on of left, top, right and bottom is greater than zero. This
+ function also returns NULL, if the new image's size will be negative in either x- or
+ y-direction.
+ */
+FIBITMAP * DLL_CALLCONV
+FreeImage_EnlargeCanvas(FIBITMAP *src, int left, int top, int right, int bottom, const void *color, int options) {
+
+ if (!src) {
+ return NULL;
+ }
+
+ // Just return a clone of the image, if left, top, right and bottom are
+ // all zero.
+ if ((left == 0) && (right == 0) && (top == 0) && (bottom == 0)) {
+ return FreeImage_Clone(src);
+ }
+
+ int width = FreeImage_GetWidth(src);
+ int height = FreeImage_GetHeight(src);
+
+ // Relay on FreeImage_Copy, if all parameters left, top, right and
+ // bottom are smaller than or equal zero. The color pointer may be
+ // NULL in this case.
+ if ((left <= 0) && (right <= 0) && (top <= 0) && (bottom <= 0)) {
+ return FreeImage_Copy(src, -left, -top, width - 1 + top, height - 1 + bottom);
+ }
+
+ // From here, we need a valid color, since the image will be enlarged on
+ // at least one side. So, fail if we don't have a valid color pointer.
+ if (!color) {
+ return NULL;
+ }
+
+ if (((left < 0) && (-left >= width)) || ((right < 0) && (-right >= width)) ||
+ ((top < 0) && (-top >= height)) || ((bottom < 0) && (-bottom >= height))) {
+ return NULL;
+ }
+
+ unsigned newWidth = width + left + right;
+ unsigned newHeight = height + top + bottom;
+
+ FREE_IMAGE_TYPE type = FreeImage_GetImageType(src);
+ unsigned bpp = FreeImage_GetBPP(src);
+
+ FIBITMAP *dst = FreeImage_AllocateExT(
+ type, newWidth, newHeight, bpp, color, options,
+ FreeImage_GetPalette(src),
+ FreeImage_GetRedMask(src),
+ FreeImage_GetGreenMask(src),
+ FreeImage_GetBlueMask(src));
+
+ if (!dst) {
+ return NULL;
+ }
+
+ if ((type == FIT_BITMAP) && (bpp <= 4)) {
+ FIBITMAP *copy = FreeImage_Copy(src,
+ ((left >= 0) ? 0 : -left),
+ ((top >= 0) ? 0 : -top),
+ width - 1 - ((right >= 0) ? 0 : -top),
+ height - 1 - ((bottom >= 0) ? 0 : -bottom));
+
+ if (!copy) {
+ FreeImage_Unload(dst);
+ return NULL;
+ }
+
+ if (!FreeImage_Paste(dst, copy,
+ ((left <= 0) ? 0 : left),
+ ((top <= 0) ? 0 : top), 256)) {
+ FreeImage_Unload(copy);
+ FreeImage_Unload(dst);
+ return NULL;
+ }
+
+ FreeImage_Unload(copy);
+
+ } else {
+
+ int bytespp = bpp / 8;
+ BYTE *srcPtr = FreeImage_GetScanLine(src, height - 1 - ((top >= 0) ? 0 : -top));
+ BYTE *dstPtr = FreeImage_GetScanLine(dst, newHeight - 1 - ((top <= 0) ? 0 : top));
+
+ unsigned srcPitch = FreeImage_GetPitch(src);
+ unsigned dstPitch = FreeImage_GetPitch(dst);
+
+ int lineWidth = bytespp * (width + MIN(0, left) + MIN(0, right));
+ int lines = height + MIN(0, top) + MIN(0, bottom);
+
+ if (left <= 0) {
+ srcPtr += (-left * bytespp);
+ } else {
+ dstPtr += (left * bytespp);
+ }
+
+ for (int i = 0; i < lines; i++) {
+ memcpy(dstPtr, srcPtr, lineWidth);
+ srcPtr -= srcPitch;
+ dstPtr -= dstPitch;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ // copy transparency table
+ FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src));
+
+ // copy background color
+ RGBQUAD bkcolor;
+ if( FreeImage_GetBackgroundColor(src, &bkcolor) ) {
+ FreeImage_SetBackgroundColor(dst, &bkcolor);
+ }
+
+ // clone resolution
+ FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
+ FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
+
+ // clone ICC profile
+ FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src);
+ FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size);
+ dst_profile->flags = src_profile->flags;
+
+ return dst;
+}
+
diff --git a/Source/FreeImageToolkit/Channels.cpp b/Source/FreeImageToolkit/Channels.cpp
new file mode 100644
index 0000000..0ac22e7
--- /dev/null
+++ b/Source/FreeImageToolkit/Channels.cpp
@@ -0,0 +1,488 @@
+// ==========================================================
+// Channel processing support
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+
+/** @brief Retrieves the red, green, blue or alpha channel of a BGR[A] image.
+@param src Input image to be processed.
+@param channel Color channel to extract
+@return Returns the extracted channel if successful, returns NULL otherwise.
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_GetChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) {
+
+ if(!src) return NULL;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+ unsigned bpp = FreeImage_GetBPP(src);
+
+ // 24- or 32-bit
+ if(image_type == FIT_BITMAP && ((bpp == 24) || (bpp == 32))) {
+ int c;
+
+ // select the channel to extract
+ switch(channel) {
+ case FICC_BLUE:
+ c = FI_RGBA_BLUE;
+ break;
+ case FICC_GREEN:
+ c = FI_RGBA_GREEN;
+ break;
+ case FICC_RED:
+ c = FI_RGBA_RED;
+ break;
+ case FICC_ALPHA:
+ if(bpp != 32) return NULL;
+ c = FI_RGBA_ALPHA;
+ break;
+ default:
+ return NULL;
+ }
+
+ // allocate a 8-bit dib
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ FIBITMAP *dst = FreeImage_Allocate(width, height, 8) ;
+ if(!dst) return NULL;
+ // build a greyscale palette
+ RGBQUAD *pal = FreeImage_GetPalette(dst);
+ for(int i = 0; i < 256; i++) {
+ pal[i].rgbBlue = pal[i].rgbGreen = pal[i].rgbRed = (BYTE)i;
+ }
+
+ // perform extraction
+
+ int bytespp = bpp / 8; // bytes / pixel
+
+ for(unsigned y = 0; y < height; y++) {
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[c];
+ src_bits += bytespp;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+ }
+
+ // 48-bit RGB or 64-bit RGBA images
+ if((image_type == FIT_RGB16) || (image_type == FIT_RGBA16)) {
+ int c;
+
+ // select the channel to extract (always RGB[A])
+ switch(channel) {
+ case FICC_BLUE:
+ c = 2;
+ break;
+ case FICC_GREEN:
+ c = 1;
+ break;
+ case FICC_RED:
+ c = 0;
+ break;
+ case FICC_ALPHA:
+ if(bpp != 64) return NULL;
+ c = 3;
+ break;
+ default:
+ return NULL;
+ }
+
+ // allocate a greyscale dib
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ FIBITMAP *dst = FreeImage_AllocateT(FIT_UINT16, width, height) ;
+ if(!dst) return NULL;
+
+ // perform extraction
+
+ int bytespp = bpp / 16; // words / pixel
+
+ for(unsigned y = 0; y < height; y++) {
+ unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y);
+ unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[c];
+ src_bits += bytespp;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+ }
+
+ // 96-bit RGBF or 128-bit RGBAF images
+ if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF)) {
+ int c;
+
+ // select the channel to extract (always RGB[A])
+ switch(channel) {
+ case FICC_BLUE:
+ c = 2;
+ break;
+ case FICC_GREEN:
+ c = 1;
+ break;
+ case FICC_RED:
+ c = 0;
+ break;
+ case FICC_ALPHA:
+ if(bpp != 128) return NULL;
+ c = 3;
+ break;
+ default:
+ return NULL;
+ }
+
+ // allocate a greyscale dib
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ FIBITMAP *dst = FreeImage_AllocateT(FIT_FLOAT, width, height) ;
+ if(!dst) return NULL;
+
+ // perform extraction
+
+ int bytespp = bpp / 32; // floats / pixel
+
+ for(unsigned y = 0; y < height; y++) {
+ float *src_bits = (float*)FreeImage_GetScanLine(src, y);
+ float *dst_bits = (float*)FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[c];
+ src_bits += bytespp;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+ }
+
+ return NULL;
+}
+
+/** @brief Insert a greyscale dib into a RGB[A] image.
+Both src and dst must have the same width and height.
+@param dst Image to modify (RGB or RGBA)
+@param src Input greyscale image to insert
+@param channel Color channel to modify
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_SetChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) {
+ int c;
+
+ if(!src || !dst) return FALSE;
+
+ // src and dst images should have the same width and height
+ unsigned src_width = FreeImage_GetWidth(src);
+ unsigned src_height = FreeImage_GetHeight(src);
+ unsigned dst_width = FreeImage_GetWidth(dst);
+ unsigned dst_height = FreeImage_GetHeight(dst);
+ if((src_width != dst_width) || (src_height != dst_height))
+ return FALSE;
+
+ // src image should be grayscale, dst image should be RGB or RGBA
+ FREE_IMAGE_COLOR_TYPE src_type = FreeImage_GetColorType(src);
+ FREE_IMAGE_COLOR_TYPE dst_type = FreeImage_GetColorType(dst);
+ if((dst_type != FIC_RGB) && (dst_type != FIC_RGBALPHA) || (src_type != FIC_MINISBLACK)) {
+ return FALSE;
+ }
+
+ FREE_IMAGE_TYPE src_image_type = FreeImage_GetImageType(src);
+ FREE_IMAGE_TYPE dst_image_type = FreeImage_GetImageType(dst);
+
+ if((dst_image_type == FIT_BITMAP) && (src_image_type == FIT_BITMAP)) {
+
+ // src image should be grayscale, dst image should be 24- or 32-bit
+ unsigned src_bpp = FreeImage_GetBPP(src);
+ unsigned dst_bpp = FreeImage_GetBPP(dst);
+ if((src_bpp != 8) || (dst_bpp != 24) && (dst_bpp != 32))
+ return FALSE;
+
+
+ // select the channel to modify
+ switch(channel) {
+ case FICC_BLUE:
+ c = FI_RGBA_BLUE;
+ break;
+ case FICC_GREEN:
+ c = FI_RGBA_GREEN;
+ break;
+ case FICC_RED:
+ c = FI_RGBA_RED;
+ break;
+ case FICC_ALPHA:
+ if(dst_bpp != 32) return FALSE;
+ c = FI_RGBA_ALPHA;
+ break;
+ default:
+ return FALSE;
+ }
+
+ // perform insertion
+
+ int bytespp = dst_bpp / 8; // bytes / pixel
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < dst_width; x++) {
+ dst_bits[c] = src_bits[x];
+ dst_bits += bytespp;
+ }
+ }
+
+ return TRUE;
+ }
+
+ if(((dst_image_type == FIT_RGB16) || (dst_image_type == FIT_RGBA16)) && (src_image_type == FIT_UINT16)) {
+
+ // src image should be grayscale, dst image should be 48- or 64-bit
+ unsigned src_bpp = FreeImage_GetBPP(src);
+ unsigned dst_bpp = FreeImage_GetBPP(dst);
+ if((src_bpp != 16) || (dst_bpp != 48) && (dst_bpp != 64))
+ return FALSE;
+
+
+ // select the channel to modify (always RGB[A])
+ switch(channel) {
+ case FICC_BLUE:
+ c = 2;
+ break;
+ case FICC_GREEN:
+ c = 1;
+ break;
+ case FICC_RED:
+ c = 0;
+ break;
+ case FICC_ALPHA:
+ if(dst_bpp != 64) return FALSE;
+ c = 3;
+ break;
+ default:
+ return FALSE;
+ }
+
+ // perform insertion
+
+ int bytespp = dst_bpp / 16; // words / pixel
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ unsigned short *src_bits = (unsigned short*)FreeImage_GetScanLine(src, y);
+ unsigned short *dst_bits = (unsigned short*)FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < dst_width; x++) {
+ dst_bits[c] = src_bits[x];
+ dst_bits += bytespp;
+ }
+ }
+
+ return TRUE;
+ }
+
+ if(((dst_image_type == FIT_RGBF) || (dst_image_type == FIT_RGBAF)) && (src_image_type == FIT_FLOAT)) {
+
+ // src image should be grayscale, dst image should be 96- or 128-bit
+ unsigned src_bpp = FreeImage_GetBPP(src);
+ unsigned dst_bpp = FreeImage_GetBPP(dst);
+ if((src_bpp != 32) || (dst_bpp != 96) && (dst_bpp != 128))
+ return FALSE;
+
+
+ // select the channel to modify (always RGB[A])
+ switch(channel) {
+ case FICC_BLUE:
+ c = 2;
+ break;
+ case FICC_GREEN:
+ c = 1;
+ break;
+ case FICC_RED:
+ c = 0;
+ break;
+ case FICC_ALPHA:
+ if(dst_bpp != 128) return FALSE;
+ c = 3;
+ break;
+ default:
+ return FALSE;
+ }
+
+ // perform insertion
+
+ int bytespp = dst_bpp / 32; // floats / pixel
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ float *src_bits = (float*)FreeImage_GetScanLine(src, y);
+ float *dst_bits = (float*)FreeImage_GetScanLine(dst, y);
+ for(unsigned x = 0; x < dst_width; x++) {
+ dst_bits[c] = src_bits[x];
+ dst_bits += bytespp;
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** @brief Retrieves the real part, imaginary part, magnitude or phase of a complex image.
+@param src Input image to be processed.
+@param channel Channel to extract
+@return Returns the extracted channel if successful, returns NULL otherwise.
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_GetComplexChannel(FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) {
+ unsigned x, y;
+ double mag, phase;
+ FICOMPLEX *src_bits = NULL;
+ double *dst_bits = NULL;
+ FIBITMAP *dst = NULL;
+
+ if(!src) return NULL;
+
+ if(FreeImage_GetImageType(src) == FIT_COMPLEX) {
+ // allocate a dib of type FIT_DOUBLE
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ dst = FreeImage_AllocateT(FIT_DOUBLE, width, height) ;
+ if(!dst) return NULL;
+
+ // perform extraction
+
+ switch(channel) {
+ case FICC_REAL: // real part
+ for(y = 0; y < height; y++) {
+ src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y);
+ dst_bits = (double *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[x].r;
+ }
+ }
+ break;
+
+ case FICC_IMAG: // imaginary part
+ for(y = 0; y < height; y++) {
+ src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y);
+ dst_bits = (double *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ dst_bits[x] = src_bits[x].i;
+ }
+ }
+ break;
+
+ case FICC_MAG: // magnitude
+ for(y = 0; y < height; y++) {
+ src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y);
+ dst_bits = (double *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ mag = src_bits[x].r * src_bits[x].r + src_bits[x].i * src_bits[x].i;
+ dst_bits[x] = sqrt(mag);
+ }
+ }
+ break;
+
+ case FICC_PHASE: // phase
+ for(y = 0; y < height; y++) {
+ src_bits = (FICOMPLEX *)FreeImage_GetScanLine(src, y);
+ dst_bits = (double *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < width; x++) {
+ if((src_bits[x].r == 0) && (src_bits[x].i == 0)) {
+ phase = 0;
+ } else {
+ phase = atan2(src_bits[x].i, src_bits[x].r);
+ }
+ dst_bits[x] = phase;
+ }
+ }
+ break;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+}
+
+/** @brief Set the real or imaginary part of a complex image.
+Both src and dst must have the same width and height.
+@param dst Image to modify (image of type FIT_COMPLEX)
+@param src Input image of type FIT_DOUBLE
+@param channel Channel to modify
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_SetComplexChannel(FIBITMAP *dst, FIBITMAP *src, FREE_IMAGE_COLOR_CHANNEL channel) {
+ unsigned x, y;
+ double *src_bits = NULL;
+ FICOMPLEX *dst_bits = NULL;
+
+ if(!src || !dst) return FALSE;
+
+ // src image should be of type FIT_DOUBLE, dst image should be of type FIT_COMPLEX
+ const FREE_IMAGE_TYPE src_type = FreeImage_GetImageType(src);
+ const FREE_IMAGE_TYPE dst_type = FreeImage_GetImageType(dst);
+ if((src_type != FIT_DOUBLE) || (dst_type != FIT_COMPLEX))
+ return FALSE;
+
+ // src and dst images should have the same width and height
+ unsigned src_width = FreeImage_GetWidth(src);
+ unsigned src_height = FreeImage_GetHeight(src);
+ unsigned dst_width = FreeImage_GetWidth(dst);
+ unsigned dst_height = FreeImage_GetHeight(dst);
+ if((src_width != dst_width) || (src_height != dst_height))
+ return FALSE;
+
+ // select the channel to modify
+ switch(channel) {
+ case FICC_REAL: // real part
+ for(y = 0; y < dst_height; y++) {
+ src_bits = (double *)FreeImage_GetScanLine(src, y);
+ dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < dst_width; x++) {
+ dst_bits[x].r = src_bits[x];
+ }
+ }
+ break;
+ case FICC_IMAG: // imaginary part
+ for(y = 0; y < dst_height; y++) {
+ src_bits = (double *)FreeImage_GetScanLine(src, y);
+ dst_bits = (FICOMPLEX *)FreeImage_GetScanLine(dst, y);
+ for(x = 0; x < dst_width; x++) {
+ dst_bits[x].i = src_bits[x];
+ }
+ }
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/Source/FreeImageToolkit/ClassicRotate.cpp b/Source/FreeImageToolkit/ClassicRotate.cpp
new file mode 100644
index 0000000..98fd6a4
--- /dev/null
+++ b/Source/FreeImageToolkit/ClassicRotate.cpp
@@ -0,0 +1,956 @@
+// ==========================================================
+// Bitmap rotation by means of 3 shears.
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Thorsten Radde (support@IdealSoftware.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+/*
+ ============================================================
+ References :
+ [1] Paeth A., A Fast Algorithm for General Raster Rotation.
+ Graphics Gems, p. 179, Andrew Glassner editor, Academic Press, 1990.
+ [2] Yariv E., High quality image rotation (rotate by shear).
+ [Online] http://www.codeproject.com/bitmap/rotatebyshear.asp
+ [3] Treskunov A., Fast and high quality true-color bitmap rotation function.
+ [Online] http://anton.treskunov.net/Software/doc/fast_and_high_quality_true_color_bitmap_rotation_function.html
+ ============================================================
+*/
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+#define RBLOCK 64 // image blocks of RBLOCK*RBLOCK pixels
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Prototypes definition
+
+static void HorizontalSkew(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double dWeight, const void *bkcolor);
+static void VerticalSkew(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double dWeight, const void *bkcolor);
+static FIBITMAP* Rotate90(FIBITMAP *src);
+static FIBITMAP* Rotate180(FIBITMAP *src);
+static FIBITMAP* Rotate270(FIBITMAP *src);
+static FIBITMAP* Rotate45(FIBITMAP *src, double dAngle, const void *bkcolor);
+static FIBITMAP* RotateAny(FIBITMAP *src, double dAngle, const void *bkcolor);
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Skews a row horizontally (with filtered weights).
+Limited to 45 degree skewing only. Filters two adjacent pixels.
+Parameter T can be BYTE, WORD of float.
+@param src Pointer to source image to rotate
+@param dst Pointer to destination image
+@param row Row index
+@param iOffset Skew offset
+@param dWeight Relative weight of right pixel
+@param bkcolor Background color
+*/
+template <class T> void
+HorizontalSkewT(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double weight, const void *bkcolor = NULL) {
+ unsigned i, j;
+ int iXPos;
+
+ unsigned src_width = FreeImage_GetWidth(src);
+ unsigned dst_width = FreeImage_GetWidth(dst);
+
+ T pxlSrc[4], pxlLeft[4], pxlOldLeft[4]; // 4 = 4*sizeof(T) max
+
+ // background
+ const T pxlBlack[4] = {0, 0, 0, 0 };
+ const T *pxlBkg = static_cast<const T*>(bkcolor); // assume at least bytespp and 4*sizeof(T) max
+ if(!pxlBkg) {
+ // default background color is black
+ pxlBkg = pxlBlack;
+ }
+
+ // calculate the number of bytes per pixel
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+ // calculate the number of samples per pixel
+ unsigned samples = bytespp / sizeof(T);
+
+ BYTE *src_bits = FreeImage_GetScanLine(src, row);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, row);
+
+ // fill gap left of skew with background
+ if(bkcolor) {
+ for(int k = 0; k < iOffset; k++) {
+ memcpy(&dst_bits[k * bytespp], bkcolor, bytespp);
+ }
+ memcpy(&pxlOldLeft[0], bkcolor, bytespp);
+ } else {
+ if(iOffset > 0) {
+ memset(dst_bits, 0, iOffset * bytespp);
+ }
+ memset(&pxlOldLeft[0], 0, bytespp);
+ }
+
+ for(i = 0; i < src_width; i++) {
+ // loop through row pixels
+ memcpy(&pxlSrc[0], src_bits, bytespp);
+ // calculate weights
+ for(j = 0; j < samples; j++) {
+ pxlLeft[j] = static_cast<T>(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5);
+ }
+ // check boundaries
+ iXPos = i + iOffset;
+ if((iXPos >= 0) && (iXPos < (int)dst_width)) {
+ // update left over on source
+ for(j = 0; j < samples; j++) {
+ pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]);
+ }
+ memcpy(&dst_bits[iXPos*bytespp], &pxlSrc[0], bytespp);
+ }
+ // save leftover for next pixel in scan
+ memcpy(&pxlOldLeft[0], &pxlLeft[0], bytespp);
+
+ // next pixel in scan
+ src_bits += bytespp;
+ }
+
+ // go to rightmost point of skew
+ iXPos = src_width + iOffset;
+
+ if((iXPos >= 0) && (iXPos < (int)dst_width)) {
+ dst_bits = FreeImage_GetScanLine(dst, row) + iXPos * bytespp;
+
+ // If still in image bounds, put leftovers there
+ memcpy(dst_bits, &pxlOldLeft[0], bytespp);
+
+ // clear to the right of the skewed line with background
+ dst_bits += bytespp;
+ if(bkcolor) {
+ for(i = 0; i < dst_width - iXPos - 1; i++) {
+ memcpy(&dst_bits[i * bytespp], bkcolor, bytespp);
+ }
+ } else {
+ memset(dst_bits, 0, bytespp * (dst_width - iXPos - 1));
+ }
+
+ }
+}
+
+/**
+Skews a row horizontally (with filtered weights).
+Limited to 45 degree skewing only. Filters two adjacent pixels.
+@param src Pointer to source image to rotate
+@param dst Pointer to destination image
+@param row Row index
+@param iOffset Skew offset
+@param dWeight Relative weight of right pixel
+@param bkcolor Background color
+*/
+static void
+HorizontalSkew(FIBITMAP *src, FIBITMAP *dst, int row, int iOffset, double dWeight, const void *bkcolor) {
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ switch(FreeImage_GetBPP(src)) {
+ case 8:
+ case 24:
+ case 32:
+ HorizontalSkewT<BYTE>(src, dst, row, iOffset, dWeight, bkcolor);
+ break;
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ HorizontalSkewT<WORD>(src, dst, row, iOffset, dWeight, bkcolor);
+ break;
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ HorizontalSkewT<float>(src, dst, row, iOffset, dWeight, bkcolor);
+ break;
+ }
+}
+
+/**
+Skews a column vertically (with filtered weights).
+Limited to 45 degree skewing only. Filters two adjacent pixels.
+Parameter T can be BYTE, WORD of float.
+@param src Pointer to source image to rotate
+@param dst Pointer to destination image
+@param col Column index
+@param iOffset Skew offset
+@param dWeight Relative weight of upper pixel
+@param bkcolor Background color
+*/
+template <class T> void
+VerticalSkewT(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double weight, const void *bkcolor = NULL) {
+ unsigned i, j;
+ int iYPos;
+
+ unsigned src_height = FreeImage_GetHeight(src);
+ unsigned dst_height = FreeImage_GetHeight(dst);
+
+ T pxlSrc[4], pxlLeft[4], pxlOldLeft[4]; // 4 = 4*sizeof(T) max
+
+ // background
+ const T pxlBlack[4] = {0, 0, 0, 0 };
+ const T *pxlBkg = static_cast<const T*>(bkcolor); // assume at least bytespp and 4*sizeof(T) max
+ if(!pxlBkg) {
+ // default background color is black
+ pxlBkg = pxlBlack;
+ }
+
+ // calculate the number of bytes per pixel
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+ // calculate the number of samples per pixel
+ unsigned samples = bytespp / sizeof(T);
+
+ unsigned src_pitch = FreeImage_GetPitch(src);
+ unsigned dst_pitch = FreeImage_GetPitch(dst);
+ unsigned index = col * bytespp;
+
+ BYTE *src_bits = FreeImage_GetBits(src) + index;
+ BYTE *dst_bits = FreeImage_GetBits(dst) + index;
+
+ // fill gap above skew with background
+ if(bkcolor) {
+ for(int k = 0; k < iOffset; k++) {
+ memcpy(dst_bits, bkcolor, bytespp);
+ dst_bits += dst_pitch;
+ }
+ memcpy(&pxlOldLeft[0], bkcolor, bytespp);
+ } else {
+ for(int k = 0; k < iOffset; k++) {
+ memset(dst_bits, 0, bytespp);
+ dst_bits += dst_pitch;
+ }
+ memset(&pxlOldLeft[0], 0, bytespp);
+ }
+
+ for(i = 0; i < src_height; i++) {
+ // loop through column pixels
+ memcpy(&pxlSrc[0], src_bits, bytespp);
+ // calculate weights
+ for(j = 0; j < samples; j++) {
+ pxlLeft[j] = static_cast<T>(pxlBkg[j] + (pxlSrc[j] - pxlBkg[j]) * weight + 0.5);
+ }
+ // check boundaries
+ iYPos = i + iOffset;
+ if((iYPos >= 0) && (iYPos < (int)dst_height)) {
+ // update left over on source
+ for(j = 0; j < samples; j++) {
+ pxlSrc[j] = pxlSrc[j] - (pxlLeft[j] - pxlOldLeft[j]);
+ }
+ dst_bits = FreeImage_GetScanLine(dst, iYPos) + index;
+ memcpy(dst_bits, &pxlSrc[0], bytespp);
+ }
+ // save leftover for next pixel in scan
+ memcpy(&pxlOldLeft[0], &pxlLeft[0], bytespp);
+
+ // next pixel in scan
+ src_bits += src_pitch;
+ }
+ // go to bottom point of skew
+ iYPos = src_height + iOffset;
+
+ if((iYPos >= 0) && (iYPos < (int)dst_height)) {
+ dst_bits = FreeImage_GetScanLine(dst, iYPos) + index;
+
+ // if still in image bounds, put leftovers there
+ memcpy(dst_bits, &pxlOldLeft[0], bytespp);
+
+ // clear below skewed line with background
+ if(bkcolor) {
+ while(++iYPos < (int)dst_height) {
+ dst_bits += dst_pitch;
+ memcpy(dst_bits, bkcolor, bytespp);
+ }
+ } else {
+ while(++iYPos < (int)dst_height) {
+ dst_bits += dst_pitch;
+ memset(dst_bits, 0, bytespp);
+ }
+ }
+ }
+}
+
+/**
+Skews a column vertically (with filtered weights).
+Limited to 45 degree skewing only. Filters two adjacent pixels.
+@param src Pointer to source image to rotate
+@param dst Pointer to destination image
+@param col Column index
+@param iOffset Skew offset
+@param dWeight Relative weight of upper pixel
+@param bkcolor Background color
+*/
+static void
+VerticalSkew(FIBITMAP *src, FIBITMAP *dst, int col, int iOffset, double dWeight, const void *bkcolor) {
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ switch(FreeImage_GetBPP(src)) {
+ case 8:
+ case 24:
+ case 32:
+ VerticalSkewT<BYTE>(src, dst, col, iOffset, dWeight, bkcolor);
+ break;
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ VerticalSkewT<WORD>(src, dst, col, iOffset, dWeight, bkcolor);
+ break;
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ VerticalSkewT<float>(src, dst, col, iOffset, dWeight, bkcolor);
+ break;
+ }
+}
+
+/**
+Rotates an image by 90 degrees (counter clockwise).
+Precise rotation, no filters required.<br>
+Code adapted from CxImage (http://www.xdp.it/cximage.htm)
+@param src Pointer to source image to rotate
+@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+Rotate90(FIBITMAP *src) {
+ int x, y, y2;
+
+ int bpp = FreeImage_GetBPP(src);
+
+ int src_width = FreeImage_GetWidth(src);
+ int src_height = FreeImage_GetHeight(src);
+ int dst_width = src_height;
+ int dst_height = src_width;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ // allocate and clear dst image
+ FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp);
+ if(NULL == dst) return NULL;
+
+ // get src and dst scan width
+ int src_pitch = FreeImage_GetPitch(src);
+ int dst_pitch = FreeImage_GetPitch(dst);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(bpp == 1) {
+ // speedy rotate for BW images
+
+ BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow, *srcdisp;
+ div_t div_r;
+
+ BYTE *bsrc = FreeImage_GetBits(src);
+ BYTE *bdest = FreeImage_GetBits(dst);
+ dbitsmax = bdest + dst_height * dst_pitch - 1;
+
+ for(y = 0; y < src_height; y++) {
+ // figure out the column we are going to be copying to
+ div_r = div(y, 8);
+ // set bit pos of src column byte
+ bitpos = (BYTE)(128 >> div_r.rem);
+ srcdisp = bsrc + y * src_pitch;
+ for (x = 0; x < src_pitch; x++) {
+ // get source bits
+ sbits = srcdisp + x;
+ // get destination column
+ nrow = bdest + (dst_height - 1 - (x * 8)) * dst_pitch + div_r.quot;
+ for (int z = 0; z < 8; z++) {
+ // get destination byte
+ dbits = nrow - z * dst_pitch;
+ if ((dbits < bdest) || (dbits > dbitsmax)) break;
+ if (*sbits & (128 >> z)) *dbits |= bitpos;
+ }
+ }
+ }
+ }
+ else if((bpp == 8) || (bpp == 24) || (bpp == 32)) {
+ // anything other than BW :
+ // This optimized version of rotation rotates image by smaller blocks. It is quite
+ // a bit faster than obvious algorithm, because it produces much less CPU cache misses.
+ // This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current
+ // CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase
+ // speed somehow, but once you drop out of CPU's cache, things will slow down drastically.
+ // For older CPUs with less cache, lower value would yield better results.
+
+ int xs, ys; // x-segment and y-segment
+ BYTE *bsrc = FreeImage_GetBits(src); // source pixels
+ BYTE *bdest = FreeImage_GetBits(dst); // destination pixels
+
+ // calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(xs = 0; xs < dst_width; xs += RBLOCK) { // for all image blocks of RBLOCK*RBLOCK pixels
+ for(ys = 0; ys < dst_height; ys += RBLOCK) {
+ for(y = ys; y < MIN(dst_height, ys + RBLOCK); y++) { // do rotation
+ y2 = dst_height - y - 1;
+ // point to src pixel at (y2, xs)
+ BYTE *src_bits = bsrc + (xs * src_pitch) + (y2 * bytespp);
+ // point to dst pixel at (xs, y)
+ BYTE *dst_bits = bdest + (y * dst_pitch) + (xs * bytespp);
+ for (x = xs; x < MIN(dst_width, xs + RBLOCK); x++) {
+ // dst.SetPixel(x, y, src.GetPixel(y2, x));
+ for(int j = 0; j < bytespp; j++) {
+ dst_bits[j] = src_bits[j];
+ }
+ dst_bits += bytespp;
+ src_bits += src_pitch;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ BYTE *bsrc = FreeImage_GetBits(src); // source pixels
+ BYTE *bdest = FreeImage_GetBits(dst); // destination pixels
+
+ // calculate the number of bytes per pixel
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(y = 0; y < dst_height; y++) {
+ BYTE *src_bits = bsrc + (src_width - 1 - y) * bytespp;
+ BYTE *dst_bits = bdest + (y * dst_pitch);
+ for(x = 0; x < dst_width; x++) {
+ for(int j = 0; j < bytespp; j++) {
+ dst_bits[j] = src_bits[j];
+ }
+ src_bits += src_pitch;
+ dst_bits += bytespp;
+ }
+ }
+ }
+ break;
+ }
+
+ return dst;
+}
+
+/**
+Rotates an image by 180 degrees (counter clockwise).
+Precise rotation, no filters required.
+@param src Pointer to source image to rotate
+@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+Rotate180(FIBITMAP *src) {
+ int x, y, k, pos;
+
+ int bpp = FreeImage_GetBPP(src);
+
+ int src_width = FreeImage_GetWidth(src);
+ int src_height = FreeImage_GetHeight(src);
+ int dst_width = src_width;
+ int dst_height = src_height;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp);
+ if(NULL == dst) return NULL;
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(bpp == 1) {
+ for(int y = 0; y < src_height; y++) {
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1);
+ for(int x = 0; x < src_width; x++) {
+ // get bit at (x, y)
+ k = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
+ // set bit at (dst_width - x - 1, dst_height - y - 1)
+ pos = dst_width - x - 1;
+ k ? dst_bits[pos >> 3] |= (0x80 >> (pos & 0x7)) : dst_bits[pos >> 3] &= (0xFF7F >> (pos & 0x7));
+ }
+ }
+ }
+ else if((bpp == 8) || (bpp == 24) || (bpp == 32)) {
+ // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(y = 0; y < src_height; y++) {
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1) + (dst_width - 1) * bytespp;
+ for(x = 0; x < src_width; x++) {
+ // get pixel at (x, y)
+ // set pixel at (dst_width - x - 1, dst_height - y - 1)
+ for(k = 0; k < bytespp; k++) {
+ dst_bits[k] = src_bits[k];
+ }
+ src_bits += bytespp;
+ dst_bits -= bytespp;
+ }
+ }
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ // Calculate the number of bytes per pixel
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(y = 0; y < src_height; y++) {
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, dst_height - y - 1) + (dst_width - 1) * bytespp;
+ for(x = 0; x < src_width; x++) {
+ // get pixel at (x, y)
+ // set pixel at (dst_width - x - 1, dst_height - y - 1)
+ for(k = 0; k < bytespp; k++) {
+ dst_bits[k] = src_bits[k];
+ }
+ src_bits += bytespp;
+ dst_bits -= bytespp;
+ }
+ }
+ }
+ break;
+ }
+
+ return dst;
+}
+
+/**
+Rotates an image by 270 degrees (counter clockwise).
+Precise rotation, no filters required.<br>
+Code adapted from CxImage (http://www.xdp.it/cximage.htm)
+@param src Pointer to source image to rotate
+@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+Rotate270(FIBITMAP *src) {
+ int x, x2, y, dlineup;
+
+ int bpp = FreeImage_GetBPP(src);
+
+ int src_width = FreeImage_GetWidth(src);
+ int src_height = FreeImage_GetHeight(src);
+ int dst_width = src_height;
+ int dst_height = src_width;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ // allocate and clear dst image
+ FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp);
+ if(NULL == dst) return NULL;
+
+ // get src and dst scan width
+ int src_pitch = FreeImage_GetPitch(src);
+ int dst_pitch = FreeImage_GetPitch(dst);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(bpp == 1) {
+ // speedy rotate for BW images
+
+ BYTE *sbits, *dbits, *dbitsmax, bitpos, *nrow, *srcdisp;
+ div_t div_r;
+
+ BYTE *bsrc = FreeImage_GetBits(src);
+ BYTE *bdest = FreeImage_GetBits(dst);
+ dbitsmax = bdest + dst_height * dst_pitch - 1;
+ dlineup = 8 * dst_pitch - dst_width;
+
+ for(y = 0; y < src_height; y++) {
+ // figure out the column we are going to be copying to
+ div_r = div(y + dlineup, 8);
+ // set bit pos of src column byte
+ bitpos = (BYTE)(1 << div_r.rem);
+ srcdisp = bsrc + y * src_pitch;
+ for (x = 0; x < src_pitch; x++) {
+ // get source bits
+ sbits = srcdisp + x;
+ // get destination column
+ nrow = bdest + (x * 8) * dst_pitch + dst_pitch - 1 - div_r.quot;
+ for (int z = 0; z < 8; z++) {
+ // get destination byte
+ dbits = nrow + z * dst_pitch;
+ if ((dbits < bdest) || (dbits > dbitsmax)) break;
+ if (*sbits & (128 >> z)) *dbits |= bitpos;
+ }
+ }
+ }
+ }
+ else if((bpp == 8) || (bpp == 24) || (bpp == 32)) {
+ // anything other than BW :
+ // This optimized version of rotation rotates image by smaller blocks. It is quite
+ // a bit faster than obvious algorithm, because it produces much less CPU cache misses.
+ // This optimization can be tuned by changing block size (RBLOCK). 96 is good value for current
+ // CPUs (tested on Athlon XP and Celeron D). Larger value (if CPU has enough cache) will increase
+ // speed somehow, but once you drop out of CPU's cache, things will slow down drastically.
+ // For older CPUs with less cache, lower value would yield better results.
+
+ int xs, ys; // x-segment and y-segment
+ BYTE *bsrc = FreeImage_GetBits(src); // source pixels
+ BYTE *bdest = FreeImage_GetBits(dst); // destination pixels
+
+ // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(xs = 0; xs < dst_width; xs += RBLOCK) { // for all image blocks of RBLOCK*RBLOCK pixels
+ for(ys = 0; ys < dst_height; ys += RBLOCK) {
+ for(x = xs; x < MIN(dst_width, xs + RBLOCK); x++) { // do rotation
+ x2 = dst_width - x - 1;
+ // point to src pixel at (ys, x2)
+ BYTE *src_bits = bsrc + (x2 * src_pitch) + (ys * bytespp);
+ // point to dst pixel at (x, ys)
+ BYTE *dst_bits = bdest + (ys * dst_pitch) + (x * bytespp);
+ for (y = ys; y < MIN(dst_height, ys + RBLOCK); y++) {
+ // dst.SetPixel(x, y, src.GetPixel(y, x2));
+ for(int j = 0; j < bytespp; j++) {
+ dst_bits[j] = src_bits[j];
+ }
+ src_bits += bytespp;
+ dst_bits += dst_pitch;
+ }
+ }
+ }
+ }
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ BYTE *bsrc = FreeImage_GetBits(src); // source pixels
+ BYTE *bdest = FreeImage_GetBits(dst); // destination pixels
+
+ // calculate the number of bytes per pixel
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(y = 0; y < dst_height; y++) {
+ BYTE *src_bits = bsrc + (src_height - 1) * src_pitch + y * bytespp;
+ BYTE *dst_bits = bdest + (y * dst_pitch);
+ for(x = 0; x < dst_width; x++) {
+ for(int j = 0; j < bytespp; j++) {
+ dst_bits[j] = src_bits[j];
+ }
+ src_bits -= src_pitch;
+ dst_bits += bytespp;
+ }
+ }
+ }
+ break;
+ }
+
+ return dst;
+}
+
+/**
+Rotates an image by a given degree in range [-45 .. +45] (counter clockwise)
+using the 3-shear technique.
+@param src Pointer to source image to rotate
+@param dAngle Rotation angle
+@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+Rotate45(FIBITMAP *src, double dAngle, const void *bkcolor) {
+ const double ROTATE_PI = double(3.1415926535897932384626433832795);
+
+ unsigned u;
+
+ unsigned bpp = FreeImage_GetBPP(src);
+
+ double dRadAngle = dAngle * ROTATE_PI / double(180); // Angle in radians
+ double dSinE = sin(dRadAngle);
+ double dTan = tan(dRadAngle / 2);
+
+ unsigned src_width = FreeImage_GetWidth(src);
+ unsigned src_height = FreeImage_GetHeight(src);
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ // Calc first shear (horizontal) destination image dimensions
+ unsigned width_1 = src_width + unsigned((double)src_height * fabs(dTan) + 0.5);
+ unsigned height_1 = src_height;
+
+ // Perform 1st shear (horizontal)
+ // ----------------------------------------------------------------------
+
+ // Allocate image for 1st shear
+ FIBITMAP *dst1 = FreeImage_AllocateT(image_type, width_1, height_1, bpp);
+ if(NULL == dst1) {
+ return NULL;
+ }
+
+ for(u = 0; u < height_1; u++) {
+ double dShear;
+
+ if(dTan >= 0) {
+ // Positive angle
+ dShear = (u + 0.5) * dTan;
+ }
+ else {
+ // Negative angle
+ dShear = (double(u) - height_1 + 0.5) * dTan;
+ }
+ int iShear = int(floor(dShear));
+ HorizontalSkew(src, dst1, u, iShear, dShear - double(iShear), bkcolor);
+ }
+
+ // Perform 2nd shear (vertical)
+ // ----------------------------------------------------------------------
+
+ // Calc 2nd shear (vertical) destination image dimensions
+ unsigned width_2 = width_1;
+ unsigned height_2 = unsigned((double)src_width * fabs(dSinE) + (double)src_height * cos(dRadAngle) + 0.5) + 1;
+
+ // Allocate image for 2nd shear
+ FIBITMAP *dst2 = FreeImage_AllocateT(image_type, width_2, height_2, bpp);
+ if(NULL == dst2) {
+ FreeImage_Unload(dst1);
+ return NULL;
+ }
+
+ double dOffset; // Variable skew offset
+ if(dSinE > 0) {
+ // Positive angle
+ dOffset = (src_width - 1.0) * dSinE;
+ }
+ else {
+ // Negative angle
+ dOffset = -dSinE * (double(src_width) - width_2);
+ }
+
+ for(u = 0; u < width_2; u++, dOffset -= dSinE) {
+ int iShear = int(floor(dOffset));
+ VerticalSkew(dst1, dst2, u, iShear, dOffset - double(iShear), bkcolor);
+ }
+
+ // Perform 3rd shear (horizontal)
+ // ----------------------------------------------------------------------
+
+ // Free result of 1st shear
+ FreeImage_Unload(dst1);
+
+ // Calc 3rd shear (horizontal) destination image dimensions
+ unsigned width_3 = unsigned(double(src_height) * fabs(dSinE) + double(src_width) * cos(dRadAngle) + 0.5) + 1;
+ unsigned height_3 = height_2;
+
+ // Allocate image for 3rd shear
+ FIBITMAP *dst3 = FreeImage_AllocateT(image_type, width_3, height_3, bpp);
+ if(NULL == dst3) {
+ FreeImage_Unload(dst2);
+ return NULL;
+ }
+
+ if(dSinE >= 0) {
+ // Positive angle
+ dOffset = (src_width - 1.0) * dSinE * -dTan;
+ }
+ else {
+ // Negative angle
+ dOffset = dTan * ( (src_width - 1.0) * -dSinE + (1.0 - height_3) );
+ }
+ for(u = 0; u < height_3; u++, dOffset += dTan) {
+ int iShear = int(floor(dOffset));
+ HorizontalSkew(dst2, dst3, u, iShear, dOffset - double(iShear), bkcolor);
+ }
+ // Free result of 2nd shear
+ FreeImage_Unload(dst2);
+
+ // Return result of 3rd shear
+ return dst3;
+}
+
+/**
+Rotates a 1-, 8-, 24- or 32-bit image by a given angle (given in degree).
+Angle is unlimited, except for 1-bit images (limited to integer multiples of 90 degree).
+3-shears technique is used.
+@param src Pointer to source image to rotate
+@param dAngle Rotation angle
+@return Returns a pointer to a newly allocated rotated image if successful, returns NULL otherwise
+*/
+static FIBITMAP*
+RotateAny(FIBITMAP *src, double dAngle, const void *bkcolor) {
+ if(NULL == src) {
+ return NULL;
+ }
+
+ FIBITMAP *image = src;
+
+ while(dAngle >= 360) {
+ // Bring angle to range of (-INF .. 360)
+ dAngle -= 360;
+ }
+ while(dAngle < 0) {
+ // Bring angle to range of [0 .. 360)
+ dAngle += 360;
+ }
+ if((dAngle > 45) && (dAngle <= 135)) {
+ // Angle in (45 .. 135]
+ // Rotate image by 90 degrees into temporary image,
+ // so it requires only an extra rotation angle
+ // of -45 .. +45 to complete rotation.
+ image = Rotate90(src);
+ dAngle -= 90;
+ }
+ else if((dAngle > 135) && (dAngle <= 225)) {
+ // Angle in (135 .. 225]
+ // Rotate image by 180 degrees into temporary image,
+ // so it requires only an extra rotation angle
+ // of -45 .. +45 to complete rotation.
+ image = Rotate180(src);
+ dAngle -= 180;
+ }
+ else if((dAngle > 225) && (dAngle <= 315)) {
+ // Angle in (225 .. 315]
+ // Rotate image by 270 degrees into temporary image,
+ // so it requires only an extra rotation angle
+ // of -45 .. +45 to complete rotation.
+ image = Rotate270(src);
+ dAngle -= 270;
+ }
+
+ // If we got here, angle is in (-45 .. +45]
+
+ if(NULL == image) {
+ // Failed to allocate middle image
+ return NULL;
+ }
+
+ if(0 == dAngle) {
+ if(image == src) {
+ // Nothing to do ...
+ return FreeImage_Clone(src);
+ } else {
+ // No more rotation needed
+ return image;
+ }
+ }
+ else {
+ // Perform last rotation
+ FIBITMAP *dst = Rotate45(image, dAngle, bkcolor);
+
+ if(src != image) {
+ // Middle image was required, free it now.
+ FreeImage_Unload(image);
+ }
+
+ return dst;
+ }
+}
+
+// ==========================================================
+
+FIBITMAP *DLL_CALLCONV
+FreeImage_Rotate(FIBITMAP *dib, double angle, const void *bkcolor) {
+ if(!dib) return NULL;
+
+ if(0 == angle) {
+ return FreeImage_Clone(dib);
+ }
+ // DIB are stored upside down ...
+ angle *= -1;
+
+ try {
+ unsigned bpp = FreeImage_GetBPP(dib);
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(bpp == 1) {
+ // only rotate for integer multiples of 90 degree
+ if(fmod(angle, 90) != 0)
+ return NULL;
+
+ // perform the rotation
+ FIBITMAP *dst = RotateAny(dib, angle, bkcolor);
+ if(!dst) throw(1);
+
+ // build a greyscale palette
+ RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
+ if(FreeImage_GetColorType(dib) == FIC_MINISBLACK) {
+ dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 0;
+ dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 255;
+ } else {
+ dst_pal[0].rgbRed = dst_pal[0].rgbGreen = dst_pal[0].rgbBlue = 255;
+ dst_pal[1].rgbRed = dst_pal[1].rgbGreen = dst_pal[1].rgbBlue = 0;
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+
+ return dst;
+ }
+ else if((bpp == 8) || (bpp == 24) || (bpp == 32)) {
+ FIBITMAP *dst = RotateAny(dib, angle, bkcolor);
+ if(!dst) throw(1);
+
+ if(bpp == 8) {
+ // copy original palette to rotated bitmap
+ RGBQUAD *src_pal = FreeImage_GetPalette(dib);
+ RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
+ memcpy(&dst_pal[0], &src_pal[0], 256 * sizeof(RGBQUAD));
+
+ // copy transparency table
+ FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(dib), FreeImage_GetTransparencyCount(dib));
+
+ // copy background color
+ RGBQUAD bkcolor;
+ if( FreeImage_GetBackgroundColor(dib, &bkcolor) ) {
+ FreeImage_SetBackgroundColor(dst, &bkcolor);
+ }
+
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+
+ return dst;
+ }
+ break;
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ FIBITMAP *dst = RotateAny(dib, angle, bkcolor);
+ if(!dst) throw(1);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, dib);
+
+ return dst;
+ }
+ break;
+ }
+
+ } catch(int) {
+ return NULL;
+ }
+
+ return NULL;
+}
+
diff --git a/Source/FreeImageToolkit/Colors.cpp b/Source/FreeImageToolkit/Colors.cpp
new file mode 100644
index 0000000..dd87c20
--- /dev/null
+++ b/Source/FreeImageToolkit/Colors.cpp
@@ -0,0 +1,939 @@
+// ==========================================================
+// Color manipulation routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Carsten Klein (c.klein@datagis.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Macros + structures
+// ----------------------------------------------------------
+
+#define GET_HI_NIBBLE(byte) ((byte) >> 4)
+#define SET_HI_NIBBLE(byte, n) byte &= 0x0F, byte |= ((n) << 4)
+#define GET_LO_NIBBLE(byte) ((byte) & 0x0F)
+#define SET_LO_NIBBLE(byte, n) byte &= 0xF0, byte |= ((n) & 0x0F)
+#define GET_NIBBLE(cn, byte) ((cn) ? (GET_HI_NIBBLE(byte)) : (GET_LO_NIBBLE(byte)))
+#define SET_NIBBLE(cn, byte, n) if (cn) SET_HI_NIBBLE(byte, n); else SET_LO_NIBBLE(byte, n)
+
+// ----------------------------------------------------------
+
+
+/** @brief Inverts each pixel data.
+
+@param src Input image to be processed.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_Invert(FIBITMAP *src) {
+ unsigned i, x, y, k;
+ BYTE *bits;
+
+ if (!src) return FALSE;
+
+ int bpp = FreeImage_GetBPP(src);
+
+ switch(bpp) {
+ case 1 :
+ case 4 :
+ case 8 :
+ {
+ // if the dib has a colormap, just invert it
+ // else, keep the linear grayscale
+
+ if (FreeImage_GetColorType(src) == FIC_PALETTE) {
+ RGBQUAD *pal = FreeImage_GetPalette(src);
+
+ for(i = 0; i < FreeImage_GetColorsUsed(src); i++) {
+ pal[i].rgbRed = 255 - pal[i].rgbRed;
+ pal[i].rgbGreen = 255 - pal[i].rgbGreen;
+ pal[i].rgbBlue = 255 - pal[i].rgbBlue;
+ }
+ } else {
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+
+ for (x = 0; x < FreeImage_GetLine(src); x++) {
+ bits[x] = ~bits[x];
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 24 :
+ case 32 :
+ {
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ for(k = 0; k < bytespp; k++) {
+ bits[k] = ~bits[k];
+ }
+ bits += bytespp;
+ }
+ }
+
+ break;
+ }
+
+ }
+ return TRUE;
+}
+
+/** @brief Perfoms an histogram transformation on a 8, 24 or 32-bit image
+according to the values of a lookup table (LUT).
+
+The transformation is done as follows.<br>
+Image 8-bit : if the image has a color palette, the LUT is applied to this palette,
+otherwise, it is applied to the grey values.<br>
+Image 24-bit & 32-bit : if channel == FICC_RGB, the same LUT is applied to each color
+plane (R,G, and B). Otherwise, the LUT is applied to the specified channel only.
+@param src Input image to be processed.
+@param LUT Lookup table. <b>The size of 'LUT' is assumed to be 256.</b>
+@param channel The color channel to be processed (only used with 24 & 32-bit DIB).
+@return Returns TRUE if successful, FALSE otherwise.
+@see FREE_IMAGE_COLOR_CHANNEL
+*/
+BOOL DLL_CALLCONV
+FreeImage_AdjustCurve(FIBITMAP *src, BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) {
+ unsigned x, y;
+ BYTE *bits = NULL;
+
+ if(!src || !LUT || (FreeImage_GetImageType(src) != FIT_BITMAP))
+ return FALSE;
+
+ int bpp = FreeImage_GetBPP(src);
+ if((bpp != 8) && (bpp != 24) && (bpp != 32))
+ return FALSE;
+
+ // apply the LUT
+ switch(bpp) {
+
+ case 8 :
+ {
+ // if the dib has a colormap, apply the LUT to it
+ // else, apply the LUT to pixel values
+
+ if(FreeImage_GetColorType(src) == FIC_PALETTE) {
+ RGBQUAD *rgb = FreeImage_GetPalette(src);
+ for (unsigned pal = 0; pal < FreeImage_GetColorsUsed(src); pal++) {
+ rgb->rgbRed = LUT[rgb->rgbRed];
+ rgb->rgbGreen = LUT[rgb->rgbGreen];
+ rgb->rgbBlue = LUT[rgb->rgbBlue];
+ rgb++;
+ }
+ }
+ else {
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[x] = LUT[ bits[x] ];
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 24 :
+ case 32 :
+ {
+ int bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ switch(channel) {
+ case FICC_RGB :
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B
+ bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G
+ bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R
+
+ bits += bytespp;
+ }
+ }
+ break;
+
+ case FICC_BLUE :
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[FI_RGBA_BLUE] = LUT[ bits[FI_RGBA_BLUE] ]; // B
+
+ bits += bytespp;
+ }
+ }
+ break;
+
+ case FICC_GREEN :
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[FI_RGBA_GREEN] = LUT[ bits[FI_RGBA_GREEN] ]; // G
+
+ bits += bytespp;
+ }
+ }
+ break;
+
+ case FICC_RED :
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[FI_RGBA_RED] = LUT[ bits[FI_RGBA_RED] ]; // R
+
+ bits += bytespp;
+ }
+ }
+ break;
+
+ case FICC_ALPHA :
+ if(32 == bpp) {
+ for(y = 0; y < FreeImage_GetHeight(src); y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < FreeImage_GetWidth(src); x++) {
+ bits[FI_RGBA_ALPHA] = LUT[ bits[FI_RGBA_ALPHA] ]; // A
+
+ bits += bytespp;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+/** @brief Performs gamma correction on a 8, 24 or 32-bit image.
+
+@param src Input image to be processed.
+@param gamma Gamma value to use. A value of 1.0 leaves the image alone,
+less than one darkens it, and greater than one lightens it.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_AdjustGamma(FIBITMAP *src, double gamma) {
+ BYTE LUT[256]; // Lookup table
+
+ if(!src || (gamma <= 0))
+ return FALSE;
+
+ // Build the lookup table
+
+ double exponent = 1 / gamma;
+ double v = 255.0 * (double)pow((double)255, -exponent);
+ for(int i = 0; i < 256; i++) {
+ double color = (double)pow((double)i, exponent) * v;
+ if(color > 255)
+ color = 255;
+ LUT[i] = (BYTE)floor(color + 0.5);
+ }
+
+ // Apply the gamma correction
+ return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
+}
+
+/** @brief Adjusts the brightness of a 8, 24 or 32-bit image by a certain amount.
+
+@param src Input image to be processed.
+@param percentage Where -100 <= percentage <= 100<br>
+A value 0 means no change, less than 0 will make the image darker
+and greater than 0 will make the image brighter.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_AdjustBrightness(FIBITMAP *src, double percentage) {
+ BYTE LUT[256]; // Lookup table
+ double value;
+
+ if(!src)
+ return FALSE;
+
+ // Build the lookup table
+ const double scale = (100 + percentage) / 100;
+ for(int i = 0; i < 256; i++) {
+ value = i * scale;
+ value = MAX(0.0, MIN(value, 255.0));
+ LUT[i] = (BYTE)floor(value + 0.5);
+ }
+ return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
+}
+
+/** @brief Adjusts the contrast of a 8, 24 or 32-bit image by a certain amount.
+
+@param src Input image to be processed.
+@param percentage Where -100 <= percentage <= 100<br>
+A value 0 means no change, less than 0 will decrease the contrast
+and greater than 0 will increase the contrast of the image.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_AdjustContrast(FIBITMAP *src, double percentage) {
+ BYTE LUT[256]; // Lookup table
+ double value;
+
+ if(!src)
+ return FALSE;
+
+ // Build the lookup table
+ const double scale = (100 + percentage) / 100;
+ for(int i = 0; i < 256; i++) {
+ value = 128 + (i - 128) * scale;
+ value = MAX(0.0, MIN(value, 255.0));
+ LUT[i] = (BYTE)floor(value + 0.5);
+ }
+ return FreeImage_AdjustCurve(src, LUT, FICC_RGB);
+}
+
+/** @brief Computes image histogram
+
+For 24-bit and 32-bit images, histogram can be computed from red, green, blue and
+black channels. For 8-bit images, histogram is computed from the black channel. Other
+bit depth is not supported (nothing is done).
+@param src Input image to be processed.
+@param histo Histogram array to fill. <b>The size of 'histo' is assumed to be 256.</b>
+@param channel Color channel to use
+@return Returns TRUE if succesful, returns FALSE if the image bit depth isn't supported.
+*/
+BOOL DLL_CALLCONV
+FreeImage_GetHistogram(FIBITMAP *src, DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel) {
+ BYTE pixel;
+ BYTE *bits = NULL;
+ unsigned x, y;
+
+ if(!src || !histo) return FALSE;
+
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+ unsigned bpp = FreeImage_GetBPP(src);
+
+ if(bpp == 8) {
+ // clear histogram array
+ memset(histo, 0, 256 * sizeof(DWORD));
+ // compute histogram for black channel
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < width; x++) {
+ // get pixel value
+ pixel = bits[x];
+ histo[pixel]++;
+ }
+ }
+ return TRUE;
+ }
+ else if((bpp == 24) || (bpp == 32)) {
+ int bytespp = bpp / 8; // bytes / pixel
+
+ // clear histogram array
+ memset(histo, 0, 256 * sizeof(DWORD));
+
+ switch(channel) {
+ case FICC_RED:
+ // compute histogram for red channel
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < width; x++) {
+ pixel = bits[FI_RGBA_RED]; // R
+ histo[pixel]++;
+ bits += bytespp;
+ }
+ }
+ return TRUE;
+
+ case FICC_GREEN:
+ // compute histogram for green channel
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < width; x++) {
+ pixel = bits[FI_RGBA_GREEN]; // G
+ histo[pixel]++;
+ bits += bytespp;
+ }
+ }
+ return TRUE;
+
+ case FICC_BLUE:
+ // compute histogram for blue channel
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < width; x++) {
+ pixel = bits[FI_RGBA_BLUE]; // B
+ histo[pixel]++;
+ bits += bytespp;
+ }
+ }
+ return TRUE;
+
+ case FICC_BLACK:
+ case FICC_RGB:
+ // compute histogram for black channel
+ for(y = 0; y < height; y++) {
+ bits = FreeImage_GetScanLine(src, y);
+ for(x = 0; x < width; x++) {
+ // RGB to GREY conversion
+ pixel = GREY(bits[FI_RGBA_RED], bits[FI_RGBA_GREEN], bits[FI_RGBA_BLUE]);
+ histo[pixel]++;
+ bits += bytespp;
+ }
+ }
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+
+/** @brief Creates a lookup table to be used with FreeImage_AdjustCurve() which
+ may adjust brightness and contrast, correct gamma and invert the image with a
+ single call to FreeImage_AdjustCurve().
+
+ This function creates a lookup table to be used with FreeImage_AdjustCurve()
+ which may adjust brightness and contrast, correct gamma and invert the image
+ with a single call to FreeImage_AdjustCurve(). If more than one of these image
+ display properties need to be adjusted, using a combined lookup table should be
+ preferred over calling each adjustment function separately. That's particularly
+ true for huge images or if performance is an issue. Then, the expensive process
+ of iterating over all pixels of an image is performed only once and not up to
+ four times.
+
+ Furthermore, the lookup table created does not depend on the order, in which
+ each single adjustment operation is performed. Due to rounding and byte casting
+ issues, it actually matters in which order individual adjustment operations
+ are performed. Both of the following snippets most likely produce different
+ results:
+
+ // snippet 1: contrast, brightness
+ FreeImage_AdjustContrast(dib, 15.0);
+ FreeImage_AdjustBrightness(dib, 50.0);
+
+ // snippet 2: brightness, contrast
+ FreeImage_AdjustBrightness(dib, 50.0);
+ FreeImage_AdjustContrast(dib, 15.0);
+
+ Better and even faster would be snippet 3:
+
+ // snippet 3:
+ BYTE LUT[256];
+ FreeImage_GetAdjustColorsLookupTable(LUT, 50.0, 15.0, 1.0, FALSE);
+ FreeImage_AdjustCurve(dib, LUT, FICC_RGB);
+
+ This function is also used internally by FreeImage_AdjustColors(), which does
+ not return the lookup table, but uses it to call FreeImage_AdjustCurve() on the
+ passed image.
+
+ @param LUT Output lookup table to be used with FreeImage_AdjustCurve(). <b>The
+ size of 'LUT' is assumed to be 256.</b>
+ @param brightness Percentage brightness value where -100 <= brightness <= 100<br>
+ A value of 0 means no change, less than 0 will make the image darker and greater
+ than 0 will make the image brighter.
+ @param contrast Percentage contrast value where -100 <= contrast <= 100<br>
+ A value of 0 means no change, less than 0 will decrease the contrast
+ and greater than 0 will increase the contrast of the image.
+ @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves
+ the image alone, less than one darkens it, and greater than one lightens it.
+ This parameter must not be zero or smaller than zero. If so, it will be ignored
+ and no gamma correction will be performed using the lookup table created.
+ @param invert If set to TRUE, the image will be inverted.
+ @return Returns the number of adjustments applied to the resulting lookup table
+ compared to a blind lookup table.
+ */
+int DLL_CALLCONV
+FreeImage_GetAdjustColorsLookupTable(BYTE *LUT, double brightness, double contrast, double gamma, BOOL invert) {
+ double dblLUT[256];
+ double value;
+ int result = 0;
+
+ if ((brightness == 0.0) && (contrast == 0.0) && (gamma == 1.0) && (!invert)) {
+ // nothing to do, if all arguments have their default values
+ // return a blind LUT
+ for (int i = 0; i < 256; i++) {
+ LUT[i] = (BYTE)i;
+ }
+ return 0;
+ }
+
+ // first, create a blind LUT, which does nothing to the image
+ for (int i = 0; i < 256; i++) {
+ dblLUT[i] = i;
+ }
+
+ if (contrast != 0.0) {
+ // modify lookup table with contrast adjustment data
+ const double v = (100.0 + contrast) / 100.0;
+ for (int i = 0; i < 256; i++) {
+ value = 128 + (dblLUT[i] - 128) * v;
+ dblLUT[i] = MAX(0.0, MIN(value, 255.0));
+ }
+ result++;
+ }
+
+ if (brightness != 0.0) {
+ // modify lookup table with brightness adjustment data
+ const double v = (100.0 + brightness) / 100.0;
+ for (int i = 0; i < 256; i++) {
+ value = dblLUT[i] * v;
+ dblLUT[i] = MAX(0.0, MIN(value, 255.0));
+ }
+ result++;
+ }
+
+ if ((gamma > 0) && (gamma != 1.0)) {
+ // modify lookup table with gamma adjustment data
+ double exponent = 1 / gamma;
+ const double v = 255.0 * (double)pow((double)255, -exponent);
+ for (int i = 0; i < 256; i++) {
+ value = pow(dblLUT[i], exponent) * v;
+ dblLUT[i] = MAX(0.0, MIN(value, 255.0));
+ }
+ result++;
+ }
+
+ if (!invert) {
+ for (int i = 0; i < 256; i++) {
+ LUT[i] = (BYTE)floor(dblLUT[i] + 0.5);
+ }
+ } else {
+ for (int i = 0; i < 256; i++) {
+ LUT[i] = 255 - (BYTE)floor(dblLUT[i] + 0.5);
+ }
+ result++;
+ }
+ // return the number of adjustments made
+ return result;
+}
+
+/** @brief Adjusts an image's brightness, contrast and gamma as well as it may
+ optionally invert the image within a single operation.
+
+ This function adjusts an image's brightness, contrast and gamma as well as it
+ may optionally invert the image within a single operation. If more than one of
+ these image display properties need to be adjusted, using this function should
+ be preferred over calling each adjustment function separately. That's
+ particularly true for huge images or if performance is an issue.
+
+ This function relies on FreeImage_GetAdjustColorsLookupTable(), which creates a
+ single lookup table, that combines all adjustment operations requested.
+
+ Furthermore, the lookup table created by FreeImage_GetAdjustColorsLookupTable()
+ does not depend on the order, in which each single adjustment operation is
+ performed. Due to rounding and byte casting issues, it actually matters in which
+ order individual adjustment operations are performed. Both of the following
+ snippets most likely produce different results:
+
+ // snippet 1: contrast, brightness
+ FreeImage_AdjustContrast(dib, 15.0);
+ FreeImage_AdjustBrightness(dib, 50.0);
+
+ // snippet 2: brightness, contrast
+ FreeImage_AdjustBrightness(dib, 50.0);
+ FreeImage_AdjustContrast(dib, 15.0);
+
+ Better and even faster would be snippet 3:
+
+ // snippet 3:
+ FreeImage_AdjustColors(dib, 50.0, 15.0, 1.0, FALSE);
+
+ @param dib Input/output image to be processed.
+ @param brightness Percentage brightness value where -100 <= brightness <= 100<br>
+ A value of 0 means no change, less than 0 will make the image darker and greater
+ than 0 will make the image brighter.
+ @param contrast Percentage contrast value where -100 <= contrast <= 100<br>
+ A value of 0 means no change, less than 0 will decrease the contrast
+ and greater than 0 will increase the contrast of the image.
+ @param gamma Gamma value to be used for gamma correction. A value of 1.0 leaves
+ the image alone, less than one darkens it, and greater than one lightens it.<br>
+ This parameter must not be zero or smaller than zero. If so, it will be ignored
+ and no gamma correction will be performed on the image.
+ @param invert If set to TRUE, the image will be inverted.
+ @return Returns TRUE on success, FALSE otherwise (e.g. when the bitdeph of the
+ source dib cannot be handled).
+ */
+BOOL DLL_CALLCONV
+FreeImage_AdjustColors(FIBITMAP *dib, double brightness, double contrast, double gamma, BOOL invert) {
+ BYTE LUT[256];
+
+ if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
+ return FALSE;
+ }
+
+ int bpp = FreeImage_GetBPP(dib);
+ if ((bpp != 8) && (bpp != 24) && (bpp != 32)) {
+ return FALSE;
+ }
+
+ if (FreeImage_GetAdjustColorsLookupTable(LUT, brightness, contrast, gamma, invert)) {
+ return FreeImage_AdjustCurve(dib, LUT, FICC_RGB);
+ }
+ return FALSE;
+}
+
+/** @brief Applies color mapping for one or several colors on a 1-, 4- or 8-bit
+ palletized or a 16-, 24- or 32-bit high color image.
+
+ This function maps up to <i>count</i> colors specified in <i>srccolors</i> to
+ these specified in <i>dstcolors</i>. Thereby, color <i>srccolors[N]</i>,
+ if found in the image, will be replaced by color <i>dstcolors[N]</i>. If
+ parameter <i>swap</i> is TRUE, additionally all colors specified in
+ <i>dstcolors</i> are also mapped to these specified in <i>srccolors</i>. For
+ high color images, the actual image data will be modified whereas, for
+ palletized images only the palette will be changed.<br>
+
+ The function returns the number of pixels changed or zero, if no pixels were
+ changed.
+
+ Both arrays <i>srccolors</i> and <i>dstcolors</i> are assumed not to hold less
+ than <i>count</i> colors.<br>
+
+ For 16-bit images, all colors specified are transparently converted to their
+ proper 16-bit representation (either in RGB555 or RGB565 format, which is
+ determined by the image's red- green- and blue-mask).<br>
+
+ <b>Note, that this behaviour is different from what FreeImage_ApplyPaletteIndexMapping()
+ does, which modifies the actual image data on palletized images.</b>
+
+ @param dib Input/output image to be processed.
+ @param srccolors Array of colors to be used as the mapping source.
+ @param dstcolors Array of colors to be used as the mapping destination.
+ @param count The number of colors to be mapped. This is the size of both
+ <i>srccolors</i> and <i>dstcolors</i>.
+ @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit.
+ @param swap If TRUE, source and destination colors are swapped, that is,
+ each destination color is also mapped to the corresponding source color.
+ @return Returns the total number of pixels changed.
+ */
+unsigned DLL_CALLCONV
+FreeImage_ApplyColorMapping(FIBITMAP *dib, RGBQUAD *srccolors, RGBQUAD *dstcolors, unsigned count, BOOL ignore_alpha, BOOL swap) {
+ unsigned result = 0;
+
+ if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
+ return 0;
+ }
+
+ // validate parameters
+ if ((!srccolors) || (!dstcolors)|| (count < 1)) {
+ return 0;
+ }
+
+ int bpp = FreeImage_GetBPP(dib);
+ switch (bpp) {
+ case 1:
+ case 4:
+ case 8: {
+ unsigned size = FreeImage_GetColorsUsed(dib);
+ RGBQUAD *pal = FreeImage_GetPalette(dib);
+ RGBQUAD *a, *b;
+ for (unsigned x = 0; x < size; x++) {
+ for (unsigned j = 0; j < count; j++) {
+ a = srccolors;
+ b = dstcolors;
+ for (int i = (swap ? 0 : 1); i < 2; i++) {
+ if ((pal[x].rgbBlue == a[j].rgbBlue)&&(pal[x].rgbGreen == a[j].rgbGreen) &&(pal[x].rgbRed== a[j].rgbRed)) {
+ pal[x].rgbBlue = b[j].rgbBlue;
+ pal[x].rgbGreen = b[j].rgbGreen;
+ pal[x].rgbRed = b[j].rgbRed;
+ result++;
+ j = count;
+ break;
+ }
+ a = dstcolors;
+ b = srccolors;
+ }
+ }
+ }
+ return result;
+ }
+ case 16: {
+ WORD *src16 = (WORD *)malloc(sizeof(WORD) * count);
+ if (NULL == src16) {
+ return 0;
+ }
+
+ WORD *dst16 = (WORD *)malloc(sizeof(WORD) * count);
+ if (NULL == dst16) {
+ free(src16);
+ return 0;
+ }
+
+ for (unsigned j = 0; j < count; j++) {
+ src16[j] = RGBQUAD_TO_WORD(dib, (srccolors + j));
+ dst16[j] = RGBQUAD_TO_WORD(dib, (dstcolors + j));
+ }
+
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned width = FreeImage_GetWidth(dib);
+ WORD *a, *b;
+ for (unsigned y = 0; y < height; y++) {
+ WORD *bits = (WORD *)FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < width; x++, bits++) {
+ for (unsigned j = 0; j < count; j++) {
+ a = src16;
+ b = dst16;
+ for (int i = (swap ? 0 : 1); i < 2; i++) {
+ if (*bits == a[j]) {
+ *bits = b[j];
+ result++;
+ j = count;
+ break;
+ }
+ a = dst16;
+ b = src16;
+ }
+ }
+ }
+ }
+ free(src16);
+ free(dst16);
+ return result;
+ }
+ case 24: {
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned width = FreeImage_GetWidth(dib);
+ RGBQUAD *a, *b;
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < width; x++, bits += 3) {
+ for (unsigned j = 0; j < count; j++) {
+ a = srccolors;
+ b = dstcolors;
+ for (int i = (swap ? 0 : 1); i < 2; i++) {
+ if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) && (bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed)) {
+ bits[FI_RGBA_BLUE] = b[j].rgbBlue;
+ bits[FI_RGBA_GREEN] = b[j].rgbGreen;
+ bits[FI_RGBA_RED] = b[j].rgbRed;
+ result++;
+ j = count;
+ break;
+ }
+ a = dstcolors;
+ b = srccolors;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ case 32: {
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned width = FreeImage_GetWidth(dib);
+ RGBQUAD *a, *b;
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < width; x++, bits += 4) {
+ for (unsigned j = 0; j < count; j++) {
+ a = srccolors;
+ b = dstcolors;
+ for (int i = (swap ? 0 : 1); i < 2; i++) {
+ if ((bits[FI_RGBA_BLUE] == a[j].rgbBlue) &&(bits[FI_RGBA_GREEN] == a[j].rgbGreen) &&(bits[FI_RGBA_RED] == a[j].rgbRed)
+ &&((ignore_alpha) || (bits[FI_RGBA_ALPHA] == a[j].rgbReserved))) {
+ bits[FI_RGBA_BLUE] = b[j].rgbBlue;
+ bits[FI_RGBA_GREEN] = b[j].rgbGreen;
+ bits[FI_RGBA_RED] = b[j].rgbRed;
+ if (!ignore_alpha) {
+ bits[FI_RGBA_ALPHA] = b[j].rgbReserved;
+ }
+ result++;
+ j = count;
+ break;
+ }
+ a = dstcolors;
+ b = srccolors;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
+/** @brief Swaps two specified colors on a 1-, 4- or 8-bit palletized
+ or a 16-, 24- or 32-bit high color image.
+
+ This function swaps the two specified colors <i>color_a</i> and <i>color_b</i>
+ on a palletized or high color image. For high color images, the actual image
+ data will be modified whereas, for palletized images only the palette will be
+ changed.<br>
+
+ <b>Note, that this behaviour is different from what FreeImage_SwapPaletteIndices()
+ does, which modifies the actual image data on palletized images.</b><br>
+
+ This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:<br>
+ <i>return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE);</i>
+
+ @param dib Input/output image to be processed.
+ @param color_a On of the two colors to be swapped.
+ @param color_b The other of the two colors to be swapped.
+ @param ignore_alpha If TRUE, 32-bit images and colors are treated as 24-bit.
+ @return Returns the total number of pixels changed.
+ */
+unsigned DLL_CALLCONV
+FreeImage_SwapColors(FIBITMAP *dib, RGBQUAD *color_a, RGBQUAD *color_b, BOOL ignore_alpha) {
+ return FreeImage_ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, TRUE);
+}
+
+/** @brief Applies palette index mapping for one or several indices on a 1-, 4-
+ or 8-bit palletized image.
+
+ This function maps up to <i>count</i> palette indices specified in
+ <i>srcindices</i> to these specified in <i>dstindices</i>. Thereby, index
+ <i>srcindices[N]</i>, if present in the image, will be replaced by index
+ <i>dstindices[N]</i>. If parameter <i>swap</i> is TRUE, additionally all indices
+ specified in <i>dstindices</i> are also mapped to these specified in
+ <i>srcindices</i>.<br>
+
+ The function returns the number of pixels changed or zero, if no pixels were
+ changed.
+
+ Both arrays <i>srcindices</i> and <i>dstindices</i> are assumed not to hold less
+ than <i>count</i> indices.<br>
+
+ <b>Note, that this behaviour is different from what FreeImage_ApplyColorMapping()
+ does, which modifies the actual image data on palletized images.</b>
+
+ @param dib Input/output image to be processed.
+ @param srcindices Array of palette indices to be used as the mapping source.
+ @param dstindices Array of palette indices to be used as the mapping destination.
+ @param count The number of palette indices to be mapped. This is the size of both
+ <i>srcindices</i> and <i>dstindices</i>.
+ @param swap If TRUE, source and destination palette indices are swapped, that is,
+ each destination index is also mapped to the corresponding source index.
+ @return Returns the total number of pixels changed.
+ */
+unsigned DLL_CALLCONV
+FreeImage_ApplyPaletteIndexMapping(FIBITMAP *dib, BYTE *srcindices, BYTE *dstindices, unsigned count, BOOL swap) {
+ unsigned result = 0;
+
+ if ((!dib) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
+ return 0;
+ }
+
+ // validate parameters
+ if ((!srcindices) || (!dstindices)|| (count < 1)) {
+ return 0;
+ }
+
+ unsigned height = FreeImage_GetHeight(dib);
+ unsigned width = FreeImage_GetLine(dib);
+ BYTE *a, *b;
+
+ int bpp = FreeImage_GetBPP(dib);
+ switch (bpp) {
+ case 1: {
+
+ return result;
+ }
+ case 4: {
+ int skip_last = (FreeImage_GetWidth(dib) & 0x01);
+ unsigned max_x = width - 1;
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < width; x++) {
+ int start = ((skip_last) && (x == max_x)) ? 1 : 0;
+ for (int cn = start; cn < 2; cn++) {
+ for (unsigned j = 0; j < count; j++) {
+ a = srcindices;
+ b = dstindices;
+ for (int i = ((swap) ? 0 : 1); i < 2; i++) {
+ if (GET_NIBBLE(cn, bits[x]) == (a[j] & 0x0F)) {
+ SET_NIBBLE(cn, bits[x], b[j]);
+ result++;
+ j = count;
+ break;
+ }
+ a = dstindices;
+ b = srcindices;
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+ case 8: {
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (unsigned x = 0; x < width; x++) {
+ for (unsigned j = 0; j < count; j++) {
+ a = srcindices;
+ b = dstindices;
+ for (int i = ((swap) ? 0 : 1); i < 2; i++) {
+ if (bits[x] == a[j]) {
+ bits[x] = b[j];
+ result++;
+ j = count;
+ break;
+ }
+ a = dstindices;
+ b = srcindices;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
+/** @brief Swaps two specified palette indices on a 1-, 4- or 8-bit palletized
+ image.
+
+ This function swaps the two specified palette indices <i>index_a</i> and
+ <i>index_b</i> on a palletized image. Therefore, not the palette, but the
+ actual image data will be modified.<br>
+
+ <b>Note, that this behaviour is different from what FreeImage_SwapColors() does
+ on palletized images, which only swaps the colors in the palette.</b><br>
+
+ This is just a thin wrapper for FreeImage_ApplyColorMapping() and resolves to:<br>
+ <i>return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE);</i>
+
+ @param dib Input/output image to be processed.
+ @param index_a On of the two palette indices to be swapped.
+ @param index_b The other of the two palette indices to be swapped.
+ @return Returns the total number of pixels changed.
+ */
+unsigned DLL_CALLCONV
+FreeImage_SwapPaletteIndices(FIBITMAP *dib, BYTE *index_a, BYTE *index_b) {
+ return FreeImage_ApplyPaletteIndexMapping(dib, index_a, index_b, 1, TRUE);
+}
+
diff --git a/Source/FreeImageToolkit/CopyPaste.cpp b/Source/FreeImageToolkit/CopyPaste.cpp
new file mode 100644
index 0000000..e8e9430
--- /dev/null
+++ b/Source/FreeImageToolkit/CopyPaste.cpp
@@ -0,0 +1,747 @@
+// ==========================================================
+// Copy / paste routines
+//
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Alexander Dymerets (sashad@te.net.ua)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Manfred Tausch (manfred.tausch@t-online.de)
+// - Riley McNiff (rmcniff@marexgroup.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------
+
+/////////////////////////////////////////////////////////////
+// Alpha blending / combine functions
+
+// ----------------------------------------------------------
+/// 1-bit
+static BOOL Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 4-bit
+static BOOL Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 8-bit
+static BOOL Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 16-bit 555
+static BOOL Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 16-bit 565
+static BOOL Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 24-bit
+static BOOL Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+/// 32- bit
+static BOOL Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha);
+// ----------------------------------------------------------
+
+// ----------------------------------------------------------
+// 1-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine1(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ BOOL value;
+
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 1) || (FreeImage_GetBPP(src_dib) != 1)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib));
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ // combine images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for(unsigned cols = 0; cols < FreeImage_GetWidth(src_dib); cols++) {
+ // get bit at (rows, cols) in src image
+ value = (src_bits[cols >> 3] & (0x80 >> (cols & 0x07))) != 0;
+ // set bit at (rows, x+cols) in dst image
+ value ? dst_bits[(x + cols) >> 3] |= (0x80 >> ((x + cols) & 0x7)) : dst_bits[(x + cols) >> 3] &= (0xFF7F >> ((x + cols) & 0x7));
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// 4-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine4(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+
+ int swapTable[16];
+ BOOL bOddStart, bOddEnd;
+
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 4) || (FreeImage_GetBPP(src_dib) != 4)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ // get src and dst palettes
+ RGBQUAD *src_pal = FreeImage_GetPalette(src_dib);
+ RGBQUAD *dst_pal = FreeImage_GetPalette(dst_dib);
+ if (src_pal == NULL || dst_pal == NULL) {
+ return FALSE;
+ }
+
+ // build a swap table for the closest color match from the source palette to the destination palette
+
+ for (int i = 0; i < 16; i++) {
+ WORD min_diff = (WORD)-1;
+
+ for (int j = 0; j < 16; j++) {
+ // calculates the color difference using a Manhattan distance
+ WORD abs_diff = (WORD)(
+ abs(src_pal[i].rgbBlue - dst_pal[j].rgbBlue)
+ + abs(src_pal[i].rgbGreen - dst_pal[j].rgbGreen)
+ + abs(src_pal[i].rgbRed - dst_pal[j].rgbRed)
+ );
+
+ if (abs_diff < min_diff) {
+ swapTable[i] = j;
+ min_diff = abs_diff;
+ if (abs_diff == 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x >> 1);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ // combine images
+
+ // allocate space for our temporary row
+ unsigned src_line = FreeImage_GetLine(src_dib);
+ unsigned src_width = FreeImage_GetWidth(src_dib);
+ unsigned src_height = FreeImage_GetHeight(src_dib);
+
+ BYTE *buffer = (BYTE *)malloc(src_line * sizeof(BYTE));
+ if (buffer == NULL) {
+ return FALSE;
+ }
+
+ bOddStart = (x & 0x01) ? TRUE : FALSE;
+
+ if ((bOddStart && !(src_width & 0x01)) || (!bOddStart && (src_width & 0x01))) {
+ bOddEnd = TRUE;
+ }
+ else {
+ bOddEnd = FALSE;
+ }
+
+ for(unsigned rows = 0; rows < src_height; rows++) {
+ memcpy(buffer, src_bits, src_line);
+
+ // change the values in the temp row to be those from the swap table
+
+ for (unsigned cols = 0; cols < src_line; cols++) {
+ buffer[cols] = (BYTE)((swapTable[HINIBBLE(buffer[cols]) >> 4] << 4) + swapTable[LOWNIBBLE(buffer[cols])]);
+ }
+
+ if (bOddStart) {
+ buffer[0] = HINIBBLE(dst_bits[0]) + LOWNIBBLE(buffer[0]);
+ }
+
+ if (bOddEnd) {
+ buffer[src_line - 1] = HINIBBLE(buffer[src_line - 1]) + LOWNIBBLE(dst_bits[src_line - 1]);
+ }
+
+ memcpy(dst_bits, buffer, src_line);
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+
+ free(buffer);
+
+ return TRUE;
+
+}
+
+// ----------------------------------------------------------
+// 8-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine8(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 8) || (FreeImage_GetBPP(src_dib) != 8)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ if(alpha > 255) {
+ // combine images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ } else {
+ // alpha blend images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
+ dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// 16-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine16_555(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ if (alpha > 255) {
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ } else {
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) {
+ RGBTRIPLE color_s;
+ RGBTRIPLE color_t;
+
+ WORD *tmp1 = (WORD *)&dst_bits[cols];
+ WORD *tmp2 = (WORD *)&src_bits[cols];
+
+ // convert 16-bit colors to 24-bit
+
+ color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3);
+ color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3);
+ color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3);
+
+ color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_555_RED_MASK) >> FI16_555_RED_SHIFT) << 3);
+ color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_555_GREEN_MASK) >> FI16_555_GREEN_SHIFT) << 3);
+ color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_555_BLUE_MASK) >> FI16_555_BLUE_SHIFT) << 3);
+
+ // alpha blend
+
+ color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8);
+ color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8);
+ color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8);
+
+ // convert 24-bit color back to 16-bit
+
+ *tmp1 = RGB555(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue);
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ }
+
+ return TRUE;
+}
+
+static BOOL
+Combine16_565(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 16) || (FreeImage_GetBPP(src_dib) != 16)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 2);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ if (alpha > 255) {
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ } else {
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols += 2) {
+ RGBTRIPLE color_s;
+ RGBTRIPLE color_t;
+
+ WORD *tmp1 = (WORD *)&dst_bits[cols];
+ WORD *tmp2 = (WORD *)&src_bits[cols];
+
+ // convert 16-bit colors to 24-bit
+
+ color_s.rgbtRed = (BYTE)(((*tmp1 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3);
+ color_s.rgbtGreen = (BYTE)(((*tmp1 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2);
+ color_s.rgbtBlue = (BYTE)(((*tmp1 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3);
+
+ color_t.rgbtRed = (BYTE)(((*tmp2 & FI16_565_RED_MASK) >> FI16_565_RED_SHIFT) << 3);
+ color_t.rgbtGreen = (BYTE)(((*tmp2 & FI16_565_GREEN_MASK) >> FI16_565_GREEN_SHIFT) << 2);
+ color_t.rgbtBlue = (BYTE)(((*tmp2 & FI16_565_BLUE_MASK) >> FI16_565_BLUE_SHIFT) << 3);
+
+ // alpha blend
+
+ color_s.rgbtRed = (BYTE)(((color_t.rgbtRed - color_s.rgbtRed) * alpha + (color_s.rgbtRed << 8)) >> 8);
+ color_s.rgbtGreen = (BYTE)(((color_t.rgbtGreen - color_s.rgbtGreen) * alpha + (color_s.rgbtGreen << 8)) >> 8);
+ color_s.rgbtBlue = (BYTE)(((color_t.rgbtBlue - color_s.rgbtBlue) * alpha + (color_s.rgbtBlue << 8)) >> 8);
+
+ // convert 24-bit color back to 16-bit
+
+ *tmp1 = RGB565(color_s.rgbtRed, color_s.rgbtGreen, color_s.rgbtBlue);
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// 24-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine24(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 24) || (FreeImage_GetBPP(src_dib) != 24)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 3);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ if(alpha > 255) {
+ // combine images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ } else {
+ // alpha blend images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for (unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
+ dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// 32-bit
+// ----------------------------------------------------------
+
+static BOOL
+Combine32(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y, unsigned alpha) {
+ // check the bit depth of src and dst images
+ if((FreeImage_GetBPP(dst_dib) != 32) || (FreeImage_GetBPP(src_dib) != 32)) {
+ return FALSE;
+ }
+
+ // check the size of src image
+ if((x + FreeImage_GetWidth(src_dib) > FreeImage_GetWidth(dst_dib)) || (y + FreeImage_GetHeight(src_dib) > FreeImage_GetHeight(dst_dib))) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((FreeImage_GetHeight(dst_dib) - FreeImage_GetHeight(src_dib) - y) * FreeImage_GetPitch(dst_dib)) + (x * 4);
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ if (alpha > 255) {
+ // combine images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ memcpy(dst_bits, src_bits, FreeImage_GetLine(src_dib));
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ } else {
+ // alpha blend images
+ for(unsigned rows = 0; rows < FreeImage_GetHeight(src_dib); rows++) {
+ for(unsigned cols = 0; cols < FreeImage_GetLine(src_dib); cols++) {
+ dst_bits[cols] = (BYTE)(((src_bits[cols] - dst_bits[cols]) * alpha + (dst_bits[cols] << 8)) >> 8);
+ }
+
+ dst_bits += FreeImage_GetPitch(dst_dib);
+ src_bits += FreeImage_GetPitch(src_dib);
+ }
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// Any type other than FIBITMAP
+// ----------------------------------------------------------
+
+static BOOL
+CombineSameType(FIBITMAP *dst_dib, FIBITMAP *src_dib, unsigned x, unsigned y) {
+ // check the bit depth of src and dst images
+ if(FreeImage_GetImageType(dst_dib) != FreeImage_GetImageType(src_dib)) {
+ return FALSE;
+ }
+
+ unsigned src_width = FreeImage_GetWidth(src_dib);
+ unsigned src_height = FreeImage_GetHeight(src_dib);
+ unsigned src_pitch = FreeImage_GetPitch(src_dib);
+ unsigned src_line = FreeImage_GetLine(src_dib);
+ unsigned dst_width = FreeImage_GetWidth(dst_dib);
+ unsigned dst_height = FreeImage_GetHeight(dst_dib);
+ unsigned dst_pitch = FreeImage_GetPitch(dst_dib);
+
+ // check the size of src image
+ if((x + src_width > dst_width) || (y + src_height > dst_height)) {
+ return FALSE;
+ }
+
+ BYTE *dst_bits = FreeImage_GetBits(dst_dib) + ((dst_height - src_height - y) * dst_pitch) + (x * (src_line / src_width));
+ BYTE *src_bits = FreeImage_GetBits(src_dib);
+
+ // combine images
+ for(unsigned rows = 0; rows < src_height; rows++) {
+ memcpy(dst_bits, src_bits, src_line);
+
+ dst_bits += dst_pitch;
+ src_bits += src_pitch;
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// FreeImage interface
+// ----------------------------------------------------------
+
+/**
+Copy a sub part of the current image and returns it as a FIBITMAP*.
+Works with any bitmap type.
+@param left Specifies the left position of the cropped rectangle.
+@param top Specifies the top position of the cropped rectangle.
+@param right Specifies the right position of the cropped rectangle.
+@param bottom Specifies the bottom position of the cropped rectangle.
+@return Returns the subimage if successful, NULL otherwise.
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_Copy(FIBITMAP *src, int left, int top, int right, int bottom) {
+
+ if(!src)
+ return NULL;
+
+ // normalize the rectangle
+ if(right < left) {
+ INPLACESWAP(left, right);
+ }
+ if(bottom < top) {
+ INPLACESWAP(top, bottom);
+ }
+ // check the size of the sub image
+ int src_width = FreeImage_GetWidth(src);
+ int src_height = FreeImage_GetHeight(src);
+ if((left < 0) || (right > src_width) || (top < 0) || (bottom > src_height)) {
+ return NULL;
+ }
+
+ // allocate the sub image
+ unsigned bpp = FreeImage_GetBPP(src);
+ int dst_width = (right - left);
+ int dst_height = (bottom - top);
+
+ FIBITMAP *dst =
+ FreeImage_AllocateT(FreeImage_GetImageType(src),
+ dst_width,
+ dst_height,
+ bpp,
+ FreeImage_GetRedMask(src), FreeImage_GetGreenMask(src), FreeImage_GetBlueMask(src));
+
+ if(NULL == dst) return NULL;
+
+ // get the dimensions
+ int dst_line = FreeImage_GetLine(dst);
+ int dst_pitch = FreeImage_GetPitch(dst);
+ int src_pitch = FreeImage_GetPitch(src);
+
+ // get the pointers to the bits and such
+
+ BYTE *src_bits = FreeImage_GetScanLine(src, src_height - top - dst_height);
+ switch(bpp) {
+ case 1:
+ // point to x = 0
+ break;
+
+ case 4:
+ // point to x = 0
+ break;
+
+ default:
+ {
+ // calculate the number of bytes per pixel
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+ // point to x = left
+ src_bits += left * bytespp;
+ }
+ break;
+ }
+
+ // point to x = 0
+ BYTE *dst_bits = FreeImage_GetBits(dst);
+
+ // copy the palette
+
+ memcpy(FreeImage_GetPalette(dst), FreeImage_GetPalette(src), FreeImage_GetColorsUsed(src) * sizeof(RGBQUAD));
+
+ // copy the bits
+ if(bpp == 1) {
+ BOOL value;
+ unsigned y_src, y_dst;
+
+ for(int y = 0; y < dst_height; y++) {
+ y_src = y * src_pitch;
+ y_dst = y * dst_pitch;
+ for(int x = 0; x < dst_width; x++) {
+ // get bit at (y, x) in src image
+ value = (src_bits[y_src + ((left+x) >> 3)] & (0x80 >> ((left+x) & 0x07))) != 0;
+ // set bit at (y, x) in dst image
+ value ? dst_bits[y_dst + (x >> 3)] |= (0x80 >> (x & 0x7)) : dst_bits[y_dst + (x >> 3)] &= (0xff7f >> (x & 0x7));
+ }
+ }
+ }
+
+ else if(bpp == 4) {
+ BYTE shift, value;
+ unsigned y_src, y_dst;
+
+ for(int y = 0; y < dst_height; y++) {
+ y_src = y * src_pitch;
+ y_dst = y * dst_pitch;
+ for(int x = 0; x < dst_width; x++) {
+ // get nibble at (y, x) in src image
+ shift = (BYTE)((1 - (left+x) % 2) << 2);
+ value = (src_bits[y_src + ((left+x) >> 1)] & (0x0F << shift)) >> shift;
+ // set nibble at (y, x) in dst image
+ shift = (BYTE)((1 - x % 2) << 2);
+ dst_bits[y_dst + (x >> 1)] &= ~(0x0F << shift);
+ dst_bits[y_dst + (x >> 1)] |= ((value & 0x0F) << shift);
+ }
+ }
+ }
+
+ else if(bpp >= 8) {
+ for(int y = 0; y < dst_height; y++) {
+ memcpy(dst_bits + (y * dst_pitch), src_bits + (y * src_pitch), dst_line);
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ // copy transparency table
+ FreeImage_SetTransparencyTable(dst, FreeImage_GetTransparencyTable(src), FreeImage_GetTransparencyCount(src));
+
+ // copy background color
+ RGBQUAD bkcolor;
+ if( FreeImage_GetBackgroundColor(src, &bkcolor) ) {
+ FreeImage_SetBackgroundColor(dst, &bkcolor);
+ }
+
+ // clone resolution
+ FreeImage_SetDotsPerMeterX(dst, FreeImage_GetDotsPerMeterX(src));
+ FreeImage_SetDotsPerMeterY(dst, FreeImage_GetDotsPerMeterY(src));
+
+ // clone ICC profile
+ FIICCPROFILE *src_profile = FreeImage_GetICCProfile(src);
+ FIICCPROFILE *dst_profile = FreeImage_CreateICCProfile(dst, src_profile->data, src_profile->size);
+ dst_profile->flags = src_profile->flags;
+
+ return dst;
+}
+
+/**
+Alpha blend or combine a sub part image with the current image.
+The bit depth of dst bitmap must be greater than or equal to the bit depth of src.
+Upper promotion of src is done internally. Supported bit depth equals to 1, 4, 8, 16, 24 or 32.
+@param src Source subimage
+@param left Specifies the left position of the sub image.
+@param top Specifies the top position of the sub image.
+@param alpha Alpha blend factor. The source and destination images are alpha blended if
+alpha = 0..255. If alpha > 255, then the source image is combined to the destination image.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_Paste(FIBITMAP *dst, FIBITMAP *src, int left, int top, int alpha) {
+ BOOL bResult = FALSE;
+
+ if(!src || !dst) return FALSE;
+
+ // check the size of src image
+ if((left < 0) || (top < 0)) {
+ return FALSE;
+ }
+ if((left + FreeImage_GetWidth(src) > FreeImage_GetWidth(dst)) || (top + FreeImage_GetHeight(src) > FreeImage_GetHeight(dst))) {
+ return FALSE;
+ }
+
+ // check data type
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dst);
+ if(image_type != FreeImage_GetImageType(src)) {
+ // no conversion between data type is done
+ return FALSE;
+ }
+
+ if(image_type == FIT_BITMAP) {
+ FIBITMAP *clone = NULL;
+
+ // check the bit depth of src and dst images
+ unsigned bpp_src = FreeImage_GetBPP(src);
+ unsigned bpp_dst = FreeImage_GetBPP(dst);
+ BOOL isRGB565 = FALSE;
+
+ if ((FreeImage_GetRedMask(dst) == FI16_565_RED_MASK) && (FreeImage_GetGreenMask(dst) == FI16_565_GREEN_MASK) && (FreeImage_GetBlueMask(dst) == FI16_565_BLUE_MASK)) {
+ isRGB565 = TRUE;
+ } else {
+ // includes case where all the masks are 0
+ isRGB565 = FALSE;
+ }
+
+ // perform promotion if needed
+ if(bpp_dst == bpp_src) {
+ clone = src;
+ } else if(bpp_dst > bpp_src) {
+ // perform promotion
+ switch(bpp_dst) {
+ case 4:
+ clone = FreeImage_ConvertTo4Bits(src);
+ break;
+ case 8:
+ clone = FreeImage_ConvertTo8Bits(src);
+ break;
+ case 16:
+ if (isRGB565) {
+ clone = FreeImage_ConvertTo16Bits565(src);
+ } else {
+ // includes case where all the masks are 0
+ clone = FreeImage_ConvertTo16Bits555(src);
+ }
+ break;
+ case 24:
+ clone = FreeImage_ConvertTo24Bits(src);
+ break;
+ case 32:
+ clone = FreeImage_ConvertTo32Bits(src);
+ break;
+ default:
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+
+ if(!clone) return FALSE;
+
+ // paste src to dst
+ switch(FreeImage_GetBPP(dst)) {
+ case 1:
+ bResult = Combine1(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ break;
+ case 4:
+ bResult = Combine4(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ break;
+ case 8:
+ bResult = Combine8(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ break;
+ case 16:
+ if (isRGB565) {
+ bResult = Combine16_565(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ } else {
+ // includes case where all the masks are 0
+ bResult = Combine16_555(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ }
+ break;
+ case 24:
+ bResult = Combine24(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ break;
+ case 32:
+ bResult = Combine32(dst, clone, (unsigned)left, (unsigned)top, (unsigned)alpha);
+ break;
+ }
+
+ if(clone != src)
+ FreeImage_Unload(clone);
+
+ }
+ else { // any type other than FITBITMAP
+ bResult = CombineSameType(dst, src, (unsigned)left, (unsigned)top);
+ }
+
+ return bResult;
+}
+
+
diff --git a/Source/FreeImageToolkit/Display.cpp b/Source/FreeImageToolkit/Display.cpp
new file mode 100644
index 0000000..88a57a6
--- /dev/null
+++ b/Source/FreeImageToolkit/Display.cpp
@@ -0,0 +1,230 @@
+// ==========================================================
+// Display routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+
+/**
+@brief Composite a foreground image against a background color or a background image.
+
+The equation for computing a composited sample value is:<br>
+output = alpha * foreground + (1-alpha) * background<br>
+where alpha and the input and output sample values are expressed as fractions in the range 0 to 1.
+For colour images, the computation is done separately for R, G, and B samples.
+
+@param fg Foreground image
+@param useFileBkg If TRUE and a file background is present, use it as the background color
+@param appBkColor If not equal to NULL, and useFileBkg is FALSE, use this color as the background color
+@param bg If not equal to NULL and useFileBkg is FALSE and appBkColor is NULL, use this as the background image
+@return Returns the composite image if successful, returns NULL otherwise
+@see FreeImage_IsTransparent, FreeImage_HasBackgroundColor
+*/
+FIBITMAP * DLL_CALLCONV
+FreeImage_Composite(FIBITMAP *fg, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) {
+ if(!fg) return NULL;
+
+ int width = FreeImage_GetWidth(fg);
+ int height = FreeImage_GetHeight(fg);
+ int bpp = FreeImage_GetBPP(fg);
+
+ if((bpp != 8) && (bpp != 32))
+ return NULL;
+
+ if(bg) {
+ int bg_width = FreeImage_GetWidth(bg);
+ int bg_height = FreeImage_GetHeight(bg);
+ int bg_bpp = FreeImage_GetBPP(bg);
+ if((bg_width != width) || (bg_height != height) || (bg_bpp != 24))
+ return NULL;
+ }
+
+ int bytespp = (bpp == 8) ? 1 : 4;
+
+
+ int x, y, c;
+ BYTE alpha = 0, not_alpha;
+ BYTE index;
+ RGBQUAD fgc; // foreground color
+ RGBQUAD bkc; // background color
+
+ memset(&fgc, 0, sizeof(RGBQUAD));
+ memset(&bkc, 0, sizeof(RGBQUAD));
+
+ // allocate the composite image
+ FIBITMAP *composite = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ if(!composite) return NULL;
+
+ // get the palette
+ RGBQUAD *pal = FreeImage_GetPalette(fg);
+
+ // retrieve the alpha table from the foreground image
+ BOOL bIsTransparent = FreeImage_IsTransparent(fg);
+ BYTE *trns = FreeImage_GetTransparencyTable(fg);
+
+ // retrieve the background color from the foreground image
+ BOOL bHasBkColor = FALSE;
+
+ if(useFileBkg && FreeImage_HasBackgroundColor(fg)) {
+ FreeImage_GetBackgroundColor(fg, &bkc);
+ bHasBkColor = TRUE;
+ } else {
+ // no file background color
+ // use application background color ?
+ if(appBkColor) {
+ memcpy(&bkc, appBkColor, sizeof(RGBQUAD));
+ bHasBkColor = TRUE;
+ }
+ // use background image ?
+ else if(bg) {
+ bHasBkColor = FALSE;
+ }
+ }
+
+ for(y = 0; y < height; y++) {
+ // foreground
+ BYTE *fg_bits = FreeImage_GetScanLine(fg, y);
+ // background
+ BYTE *bg_bits = FreeImage_GetScanLine(bg, y);
+ // composite image
+ BYTE *cp_bits = FreeImage_GetScanLine(composite, y);
+
+ for(x = 0; x < width; x++) {
+
+ // foreground color + alpha
+
+ if(bpp == 8) {
+ // get the foreground color
+ index = fg_bits[0];
+ memcpy(&fgc, &pal[index], sizeof(RGBQUAD));
+ // get the alpha
+ if(bIsTransparent) {
+ alpha = trns[index];
+ } else {
+ alpha = 255;
+ }
+ }
+ else if(bpp == 32) {
+ // get the foreground color
+ fgc.rgbBlue = fg_bits[FI_RGBA_BLUE];
+ fgc.rgbGreen = fg_bits[FI_RGBA_GREEN];
+ fgc.rgbRed = fg_bits[FI_RGBA_RED];
+ // get the alpha
+ alpha = fg_bits[FI_RGBA_ALPHA];
+ }
+
+ // background color
+
+ if(!bHasBkColor) {
+ if(bg) {
+ // get the background color from the background image
+ bkc.rgbBlue = bg_bits[FI_RGBA_BLUE];
+ bkc.rgbGreen = bg_bits[FI_RGBA_GREEN];
+ bkc.rgbRed = bg_bits[FI_RGBA_RED];
+ }
+ else {
+ // use a checkerboard pattern
+ c = (((y & 0x8) == 0) ^ ((x & 0x8) == 0)) * 192;
+ c = c ? c : 255;
+ bkc.rgbBlue = (BYTE)c;
+ bkc.rgbGreen = (BYTE)c;
+ bkc.rgbRed = (BYTE)c;
+ }
+ }
+
+ // composition
+
+ if(alpha == 0) {
+ // output = background
+ cp_bits[FI_RGBA_BLUE] = bkc.rgbBlue;
+ cp_bits[FI_RGBA_GREEN] = bkc.rgbGreen;
+ cp_bits[FI_RGBA_RED] = bkc.rgbRed;
+ }
+ else if(alpha == 255) {
+ // output = foreground
+ cp_bits[FI_RGBA_BLUE] = fgc.rgbBlue;
+ cp_bits[FI_RGBA_GREEN] = fgc.rgbGreen;
+ cp_bits[FI_RGBA_RED] = fgc.rgbRed;
+ }
+ else {
+ // output = alpha * foreground + (1-alpha) * background
+ not_alpha = (BYTE)~alpha;
+ cp_bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)fgc.rgbBlue + not_alpha * (WORD)bkc.rgbBlue) >> 8);
+ cp_bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)fgc.rgbGreen + not_alpha * (WORD)bkc.rgbGreen) >> 8);
+ cp_bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)fgc.rgbRed + not_alpha * (WORD)bkc.rgbRed) >> 8);
+ }
+
+ fg_bits += bytespp;
+ bg_bits += 3;
+ cp_bits += 3;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(composite, fg);
+
+ return composite;
+}
+
+/**
+Pre-multiplies a 32-bit image's red-, green- and blue channels with it's alpha channel
+for to be used with e.g. the Windows GDI function AlphaBlend().
+The transformation changes the red-, green- and blue channels according to the following equation:
+channel(x, y) = channel(x, y) * alpha_channel(x, y) / 255
+@param dib Input/Output dib to be premultiplied
+@return Returns TRUE on success, FALSE otherwise (e.g. when the bitdepth of the source dib cannot be handled).
+*/
+BOOL DLL_CALLCONV
+FreeImage_PreMultiplyWithAlpha(FIBITMAP *dib) {
+ if (!dib) return FALSE;
+
+ if ((FreeImage_GetBPP(dib) != 32) || (FreeImage_GetImageType(dib) != FIT_BITMAP)) {
+ return FALSE;
+ }
+
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+
+ for(int y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, bits += 4) {
+ const BYTE alpha = bits[FI_RGBA_ALPHA];
+ // slightly faster: care for two special cases
+ if(alpha == 0x00) {
+ // special case for alpha == 0x00
+ // color * 0x00 / 0xFF = 0x00
+ bits[FI_RGBA_BLUE] = 0x00;
+ bits[FI_RGBA_GREEN] = 0x00;
+ bits[FI_RGBA_RED] = 0x00;
+ } else if(alpha == 0xFF) {
+ // nothing to do for alpha == 0xFF
+ // color * 0xFF / 0xFF = color
+ continue;
+ } else {
+ bits[FI_RGBA_BLUE] = (BYTE)((alpha * (WORD)bits[FI_RGBA_BLUE]) / 255);
+ bits[FI_RGBA_GREEN] = (BYTE)((alpha * (WORD)bits[FI_RGBA_GREEN]) / 255);
+ bits[FI_RGBA_RED] = (BYTE)((alpha * (WORD)bits[FI_RGBA_RED]) / 255);
+ }
+ }
+ }
+ return TRUE;
+}
+
diff --git a/Source/FreeImageToolkit/Filters.h b/Source/FreeImageToolkit/Filters.h
new file mode 100644
index 0000000..7a45c49
--- /dev/null
+++ b/Source/FreeImageToolkit/Filters.h
@@ -0,0 +1,287 @@
+// ==========================================================
+// Upsampling / downsampling filters
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef _FILTERS_H_
+#define _FILTERS_H_
+
+/**
+ CGenericFilter is a generic abstract filter class used to access to the filter library.<br>
+ Filters used in this library have been mainly taken from the following references : <br>
+<b>Main reference</b> : <br>
+Paul Heckbert, C code to zoom raster images up or down, with nice filtering.
+UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html
+
+<b>Heckbert references</b> : <br>
+<ul>
+<li>Oppenheim A.V., Schafer R.W., Digital Signal Processing, Prentice-Hall, 1975
+<li>Hamming R.W., Digital Filters, Prentice-Hall, Englewood Cliffs, NJ, 1983
+<li>Pratt W.K., Digital Image Processing, John Wiley and Sons, 1978
+<li>Hou H.S., Andrews H.C., "Cubic Splines for Image Interpolation and Digital Filtering",
+IEEE Trans. Acoustics, Speech, and Signal Proc., vol. ASSP-26, no. 6, pp. 508-517, Dec. 1978.
+</ul>
+
+*/
+class CGenericFilter
+{
+protected:
+
+ #define FILTER_PI double (3.1415926535897932384626433832795)
+ #define FILTER_2PI double (2.0 * 3.1415926535897932384626433832795)
+ #define FILTER_4PI double (4.0 * 3.1415926535897932384626433832795)
+
+ /// Filter support
+ double m_dWidth;
+
+public:
+
+ /// Constructor
+ CGenericFilter (double dWidth) : m_dWidth (dWidth) {}
+ /// Destructor
+ virtual ~CGenericFilter() {}
+
+ /// Returns the filter support
+ double GetWidth() { return m_dWidth; }
+ /// Change the filter suport
+ void SetWidth (double dWidth) { m_dWidth = dWidth; }
+
+ /// Returns F(dVal) where F is the filter's impulse response
+ virtual double Filter (double dVal) = 0;
+};
+
+// -----------------------------------------------------------------------------------
+// Filters library
+// All filters are centered on 0
+// -----------------------------------------------------------------------------------
+
+/**
+ Box filter<br>
+ Box, pulse, Fourier window, 1st order (constant) b-spline.<br><br>
+
+ <b>Reference</b> : <br>
+ Glassner A.S., Principles of digital image synthesis. Morgan Kaufmann Publishers, Inc, San Francisco, Vol. 2, 1995
+*/
+class CBoxFilter : public CGenericFilter
+{
+public:
+ /**
+ Constructor<br>
+ Default fixed width = 0.5
+ */
+ CBoxFilter() : CGenericFilter(0.5) {}
+ virtual ~CBoxFilter() {}
+
+ double Filter (double dVal) { return (fabs(dVal) <= m_dWidth ? 1.0 : 0.0); }
+};
+
+/** Bilinear filter
+*/
+class CBilinearFilter : public CGenericFilter
+{
+public:
+
+ CBilinearFilter () : CGenericFilter(1) {}
+ virtual ~CBilinearFilter() {}
+
+ double Filter (double dVal) {
+ dVal = fabs(dVal);
+ return (dVal < m_dWidth ? m_dWidth - dVal : 0.0);
+ }
+};
+
+
+/**
+ Mitchell & Netravali's two-param cubic filter<br>
+
+ The parameters b and c can be used to adjust the properties of the cubic.
+ They are sometimes referred to as "blurring" and "ringing" respectively.
+ The default is b = 1/3 and c = 1/3, which were the values recommended by
+ Mitchell and Netravali as yielding the most visually pleasing results in subjective tests of human beings.
+ Larger values of b and c can produce interesting op-art effects--for example, try b = 0 and c = -5. <br><br>
+
+ <b>Reference</b> : <br>
+ Don P. Mitchell and Arun N. Netravali, Reconstruction filters in computer graphics.
+ In John Dill, editor, Computer Graphics (SIGGRAPH '88 Proceedings), Vol. 22, No. 4, August 1988, pp. 221-228.
+*/
+class CBicubicFilter : public CGenericFilter
+{
+protected:
+ // data for parameterized Mitchell filter
+ double p0, p2, p3;
+ double q0, q1, q2, q3;
+
+public:
+ /**
+ Constructor<br>
+ Default fixed width = 2
+ @param b Filter parameter (default value is 1/3)
+ @param c Filter parameter (default value is 1/3)
+ */
+ CBicubicFilter (double b = (1/(double)3), double c = (1/(double)3)) : CGenericFilter(2) {
+ p0 = (6 - 2*b) / 6;
+ p2 = (-18 + 12*b + 6*c) / 6;
+ p3 = (12 - 9*b - 6*c) / 6;
+ q0 = (8*b + 24*c) / 6;
+ q1 = (-12*b - 48*c) / 6;
+ q2 = (6*b + 30*c) / 6;
+ q3 = (-b - 6*c) / 6;
+ }
+ virtual ~CBicubicFilter() {}
+
+ double Filter(double dVal) {
+ dVal = fabs(dVal);
+ if(dVal < 1)
+ return (p0 + dVal*dVal*(p2 + dVal*p3));
+ if(dVal < 2)
+ return (q0 + dVal*(q1 + dVal*(q2 + dVal*q3)));
+ return 0;
+ }
+};
+
+/**
+ Catmull-Rom spline, Overhauser spline<br>
+
+ When using CBicubicFilter filters, you have to set parameters b and c such that <br>
+ b + 2 * c = 1<br>
+ in order to use the numerically most accurate filter.<br>
+ This gives for b = 0 the maximum value for c = 0.5, which is the Catmull-Rom
+ spline and a good suggestion for sharpness.<br><br>
+
+
+ <b>References</b> : <br>
+ <ul>
+ <li>Mitchell Don P., Netravali Arun N., Reconstruction filters in computer graphics.
+ In John Dill, editor, Computer Graphics (SIGGRAPH '88 Proceedings), Vol. 22, No. 4, August 1988, pp. 221-228.
+ <li>Keys R.G., Cubic Convolution Interpolation for Digital Image Processing.
+ IEEE Trans. Acoustics, Speech, and Signal Processing, vol. 29, no. 6, pp. 1153-1160, Dec. 1981.
+ </ul>
+
+*/
+class CCatmullRomFilter : public CGenericFilter
+{
+public:
+
+ /**
+ Constructor<br>
+ Default fixed width = 2
+ */
+ CCatmullRomFilter() : CGenericFilter(2) {}
+ virtual ~CCatmullRomFilter() {}
+
+ double Filter(double dVal) {
+ if(dVal < -2) return 0;
+ if(dVal < -1) return (0.5*(4 + dVal*(8 + dVal*(5 + dVal))));
+ if(dVal < 0) return (0.5*(2 + dVal*dVal*(-5 - 3*dVal)));
+ if(dVal < 1) return (0.5*(2 + dVal*dVal*(-5 + 3*dVal)));
+ if(dVal < 2) return (0.5*(4 + dVal*(-8 + dVal*(5 - dVal))));
+ return 0;
+ }
+};
+
+/**
+ Lanczos-windowed sinc filter<br>
+
+ Lanczos3 filter is an alternative to CBicubicFilter with high values of c about 0.6 ... 0.75
+ which produces quite strong sharpening. It usually offers better quality (fewer artifacts) and a sharp image.<br><br>
+
+*/
+class CLanczos3Filter : public CGenericFilter
+{
+public:
+ /**
+ Constructor<br>
+ Default fixed width = 3
+ */
+ CLanczos3Filter() : CGenericFilter(3) {}
+ virtual ~CLanczos3Filter() {}
+
+ double Filter(double dVal) {
+ dVal = fabs(dVal);
+ if(dVal < m_dWidth) {
+ return (sinc(dVal) * sinc(dVal / m_dWidth));
+ }
+ return 0;
+ }
+
+private:
+ double sinc(double value) {
+ if(value != 0) {
+ value *= FILTER_PI;
+ return (sin(value) / value);
+ }
+ return 1;
+ }
+};
+
+/**
+ 4th order (cubic) b-spline<br>
+
+*/
+class CBSplineFilter : public CGenericFilter
+{
+public:
+
+ /**
+ Constructor<br>
+ Default fixed width = 2
+ */
+ CBSplineFilter() : CGenericFilter(2) {}
+ virtual ~CBSplineFilter() {}
+
+ double Filter(double dVal) {
+
+ dVal = fabs(dVal);
+ if(dVal < 1) return (4 + dVal*dVal*(-6 + 3*dVal)) / 6;
+ if(dVal < 2) {
+ double t = 2 - dVal;
+ return (t*t*t / 6);
+ }
+ return 0;
+ }
+};
+
+// -----------------------------------------------------------------------------------
+// Window function library
+// -----------------------------------------------------------------------------------
+
+/**
+ Blackman window
+*/
+class CBlackmanFilter : public CGenericFilter
+{
+public:
+ /**
+ Constructor<br>
+ Default width = 0.5
+ */
+ CBlackmanFilter (double dWidth = double(0.5)) : CGenericFilter(dWidth) {}
+ virtual ~CBlackmanFilter() {}
+
+ double Filter (double dVal) {
+ if(fabs (dVal) > m_dWidth) {
+ return 0;
+ }
+ double dN = 2 * m_dWidth + 1;
+ dVal /= (dN - 1);
+ return 0.42 + 0.5*cos(FILTER_2PI*dVal) + 0.08*cos(FILTER_4PI*dVal);
+ }
+};
+
+#endif // _FILTERS_H_
diff --git a/Source/FreeImageToolkit/Flip.cpp b/Source/FreeImageToolkit/Flip.cpp
new file mode 100644
index 0000000..954f1c2
--- /dev/null
+++ b/Source/FreeImageToolkit/Flip.cpp
@@ -0,0 +1,166 @@
+// ==========================================================
+// Flipping routines
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon (drolon@infonie.fr)
+// - Jim Keir (jimkeir@users.sourceforge.net)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+/**
+Flip the image horizontally along the vertical axis.
+@param src Input image to be processed.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+BOOL DLL_CALLCONV
+FreeImage_FlipHorizontal(FIBITMAP *src) {
+ if (!src) return FALSE;
+
+ unsigned line = FreeImage_GetLine(src);
+ unsigned width = FreeImage_GetWidth(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ // copy between aligned memories
+ BYTE *new_bits = (BYTE*)FreeImage_Aligned_Malloc(line * sizeof(BYTE), FIBITMAP_ALIGNMENT);
+ if (!new_bits) return FALSE;
+
+ // mirror the buffer
+
+ for (unsigned y = 0; y < height; y++) {
+ BYTE *bits = FreeImage_GetScanLine(src, y);
+ memcpy(new_bits, bits, line);
+
+ switch (FreeImage_GetBPP(src)) {
+ case 1 :
+ {
+ for(unsigned x = 0; x < width; x++) {
+ // get pixel at (x, y)
+ BOOL value = (new_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
+ // set pixel at (new_x, y)
+ unsigned new_x = width - 1 - x;
+ value ? bits[new_x >> 3] |= (0x80 >> (new_x & 0x7)) : bits[new_x >> 3] &= (0xff7f >> (new_x & 0x7));
+ }
+ }
+ break;
+
+ case 4 :
+ {
+ for(unsigned c = 0; c < line; c++) {
+ bits[c] = new_bits[line - c - 1];
+
+ BYTE nibble = (bits[c] & 0xF0) >> 4;
+
+ bits[c] = bits[c] << 4;
+ bits[c] |= nibble;
+ }
+ }
+ break;
+
+ case 8:
+ {
+ BYTE *dst_data = (BYTE*) bits;
+ BYTE *src_data = (BYTE*) (new_bits + line - bytespp);
+ for(unsigned c = 0; c < width; c++) {
+ *dst_data++ = *src_data--;
+ }
+ }
+ break;
+
+ case 16:
+ {
+ WORD *dst_data = (WORD*) bits;
+ WORD *src_data = (WORD*) (new_bits + line - bytespp);
+ for(unsigned c = 0; c < width; c++) {
+ *dst_data++ = *src_data--;
+ }
+ }
+ break;
+
+ case 24 :
+ case 32 :
+ case 48:
+ case 64:
+ case 96:
+ case 128:
+ {
+ BYTE *dst_data = (BYTE*) bits;
+ BYTE *src_data = (BYTE*) (new_bits + line - bytespp);
+ for(unsigned c = 0; c < width; c++) {
+ for(unsigned k = 0; k < bytespp; k++) {
+ *dst_data++ = src_data[k];
+ }
+ src_data -= bytespp;
+ }
+ }
+ break;
+
+ }
+ }
+
+ FreeImage_Aligned_Free(new_bits);
+
+ return TRUE;
+}
+
+
+/**
+Flip the image vertically along the horizontal axis.
+@param src Input image to be processed.
+@return Returns TRUE if successful, FALSE otherwise.
+*/
+
+BOOL DLL_CALLCONV
+FreeImage_FlipVertical(FIBITMAP *src) {
+ BYTE *From, *Mid;
+
+ if (!src) return FALSE;
+
+ // swap the buffer
+
+ unsigned pitch = FreeImage_GetPitch(src);
+ unsigned height = FreeImage_GetHeight(src);
+
+ // copy between aligned memories
+ Mid = (BYTE*)FreeImage_Aligned_Malloc(pitch * sizeof(BYTE), FIBITMAP_ALIGNMENT);
+ if (!Mid) return FALSE;
+
+ From = FreeImage_GetBits(src);
+
+ unsigned line_s = 0;
+ unsigned line_t = (height-1) * pitch;
+
+ for(unsigned y = 0; y < height/2; y++) {
+
+ memcpy(Mid, From + line_s, pitch);
+ memcpy(From + line_s, From + line_t, pitch);
+ memcpy(From + line_t, Mid, pitch);
+
+ line_s += pitch;
+ line_t -= pitch;
+
+ }
+
+ FreeImage_Aligned_Free(Mid);
+
+ return TRUE;
+}
+
diff --git a/Source/FreeImageToolkit/JPEGTransform.cpp b/Source/FreeImageToolkit/JPEGTransform.cpp
new file mode 100644
index 0000000..e644b61
--- /dev/null
+++ b/Source/FreeImageToolkit/JPEGTransform.cpp
@@ -0,0 +1,414 @@
+// ==========================================================
+// JPEG lossless transformations
+//
+// Design and implementation by
+// - Petr Pytelka (pyta@lightcomp.com)
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+extern "C" {
+#define XMD_H
+#undef FAR
+#include <setjmp.h>
+
+#include "../LibJPEG/jinclude.h"
+#include "../LibJPEG/jpeglib.h"
+#include "../LibJPEG/jerror.h"
+#include "../LibJPEG/transupp.h"
+}
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ----------------------------------------------------------
+// IO filename handling
+// ----------------------------------------------------------
+
+typedef struct tagFilenameIO {
+ const char *src_file;
+ const char *dst_file;
+ const wchar_t *wsrc_file;
+ const wchar_t *wdst_file;
+} FilenameIO;
+
+// ----------------------------------------------------------
+// Error handling
+// ----------------------------------------------------------
+
+/**
+ Receives control for a fatal error. Information sufficient to
+ generate the error message has been stored in cinfo->err; call
+ output_message to display it. Control must NOT return to the caller;
+ generally this routine will exit() or longjmp() somewhere.
+*/
+METHODDEF(void)
+ls_jpeg_error_exit (j_common_ptr cinfo) {
+ // always display the message
+ (*cinfo->err->output_message)(cinfo);
+
+ // allow JPEG with a premature end of file
+ if((cinfo)->err->msg_parm.i[0] != 13) {
+
+ // let the memory manager delete any temp files before we die
+ jpeg_destroy(cinfo);
+
+ throw FIF_JPEG;
+ }
+}
+
+/**
+ Actual output of any JPEG message. Note that this method does not know
+ how to generate a message, only where to send it.
+*/
+METHODDEF(void)
+ls_jpeg_output_message (j_common_ptr cinfo) {
+ char buffer[JMSG_LENGTH_MAX];
+
+ // create the message
+ (*cinfo->err->format_message)(cinfo, buffer);
+ // send it to user's message proc
+ FreeImage_OutputMessageProc(FIF_JPEG, buffer);
+}
+
+// ----------------------------------------------------------
+// Main program
+// ----------------------------------------------------------
+
+static BOOL
+LosslessTransform(const FilenameIO *filenameIO, FREE_IMAGE_JPEG_OPERATION operation, const char *crop, BOOL perfect) {
+ // We assume all-in-memory processing and can therefore use only a
+ // single file pointer for sequential input and output operation
+ FILE *fp = NULL;
+
+ // check for UNICODE filenames - previous structure filling was done before
+ bool bUseUnicode = filenameIO && filenameIO->wsrc_file && filenameIO->wdst_file;
+
+ // Set up the jpeglib structures
+ jpeg_decompress_struct srcinfo;
+ jpeg_compress_struct dstinfo;
+ jpeg_error_mgr jsrcerr, jdsterr;
+ jvirt_barray_ptr *src_coef_arrays = NULL;
+ jvirt_barray_ptr *dst_coef_arrays = NULL;
+ // Support for copying optional markers from source to destination file
+ JCOPY_OPTION copyoption;
+ // Image transformation options
+ jpeg_transform_info transfoptions;
+
+ // Initialize structures
+ memset(&srcinfo, 0, sizeof(srcinfo));
+ memset(&jsrcerr, 0, sizeof(jsrcerr));
+ memset(&jdsterr, 0, sizeof(jdsterr));
+ memset(&dstinfo, 0, sizeof(dstinfo));
+ memset(&transfoptions, 0, sizeof(transfoptions));
+
+ // Copy all extra markers from source file
+ copyoption = JCOPYOPT_ALL;
+
+ // Set up default JPEG parameters
+ transfoptions.force_grayscale = FALSE;
+ transfoptions.crop = FALSE;
+
+ // Select the transform option
+ switch(operation) {
+ case FIJPEG_OP_FLIP_H: // horizontal flip
+ transfoptions.transform = JXFORM_FLIP_H;
+ break;
+ case FIJPEG_OP_FLIP_V: // vertical flip
+ transfoptions.transform = JXFORM_FLIP_V;
+ break;
+ case FIJPEG_OP_TRANSPOSE: // transpose across UL-to-LR axis
+ transfoptions.transform = JXFORM_TRANSPOSE;
+ break;
+ case FIJPEG_OP_TRANSVERSE: // transpose across UR-to-LL axis
+ transfoptions.transform = JXFORM_TRANSVERSE;
+ break;
+ case FIJPEG_OP_ROTATE_90: // 90-degree clockwise rotation
+ transfoptions.transform = JXFORM_ROT_90;
+ break;
+ case FIJPEG_OP_ROTATE_180: // 180-degree rotation
+ transfoptions.transform = JXFORM_ROT_180;
+ break;
+ case FIJPEG_OP_ROTATE_270: // 270-degree clockwise (or 90 ccw)
+ transfoptions.transform = JXFORM_ROT_270;
+ break;
+ default:
+ case FIJPEG_OP_NONE: // no transformation
+ transfoptions.transform = JXFORM_NONE;
+ break;
+ }
+ // (perfect == TRUE) ==> fail if there is non-transformable edge blocks
+ transfoptions.perfect = (perfect == TRUE) ? TRUE : FALSE;
+ // Drop non-transformable edge blocks: trim off any partial edge MCUs that the transform can't handle.
+ transfoptions.trim = TRUE;
+
+ try {
+
+ // Initialize the JPEG decompression object with default error handling
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+ srcinfo.err->error_exit = ls_jpeg_error_exit;
+ srcinfo.err->output_message = ls_jpeg_output_message;
+ jpeg_create_decompress(&srcinfo);
+
+ // Initialize the JPEG compression object with default error handling
+ dstinfo.err = jpeg_std_error(&jdsterr);
+ dstinfo.err->error_exit = ls_jpeg_error_exit;
+ dstinfo.err->output_message = ls_jpeg_output_message;
+ jpeg_create_compress(&dstinfo);
+
+ // crop option
+ if(crop != NULL) {
+ if(!jtransform_parse_crop_spec(&transfoptions, crop)) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Bogus crop argument %s", crop);
+ throw(1);
+ }
+ }
+
+ // Open the input file
+ if(bUseUnicode) {
+#ifdef _WIN32
+ if((fp = _wfopen(filenameIO->wsrc_file, L"rb")) == NULL) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open input file for reading");
+ }
+#else
+ fp = NULL;
+#endif // _WIN32
+ } else {
+ if((fp = fopen(filenameIO->src_file, "rb")) == NULL) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for reading", filenameIO->src_file);
+ }
+ }
+ if(fp == NULL) {
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_destroy_decompress(&srcinfo);
+ return FALSE;
+ }
+
+ // Specify data source for decompression
+ jpeg_stdio_src(&srcinfo, fp);
+
+ // Enable saving of extra markers that we want to copy
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ // Read the file header
+ jpeg_read_header(&srcinfo, TRUE);
+
+ // Any space needed by a transform option must be requested before
+ // jpeg_read_coefficients so that memory allocation will be done right
+
+ // Fails right away if perfect flag is TRUE and transformation is not perfect
+ if(transfoptions.perfect &&
+ !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height,
+ srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE,
+ transfoptions.transform)) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Transformation is not perfect");
+ throw(1);
+ }
+ // Prepare transformation workspace
+ jtransform_request_workspace(&srcinfo, &transfoptions);
+
+ // Read source file as DCT coefficients
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+
+ // Initialize destination compression parameters from source values
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ // Adjust destination parameters if required by transform options;
+ // also find out which set of coefficient arrays will hold the output
+ dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
+
+ // Close the input file.
+ // Note: we assume that jpeg_read_coefficients consumed all input
+ // until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
+ // only consume more while (! cinfo->inputctl->eoi_reached).
+ // We cannot call jpeg_finish_decompress here since we still need the
+ // virtual arrays allocated from the source object for processing.
+ fclose(fp);
+
+ // Open the output file
+ if(bUseUnicode) {
+#ifdef _WIN32
+ if((fp = _wfopen(filenameIO->wdst_file, L"wb")) == NULL) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open output file for writing");
+ }
+#else
+ fp = NULL;
+#endif // _WIN32
+ } else {
+ if((fp = fopen(filenameIO->dst_file, "wb")) == NULL) {
+ FreeImage_OutputMessageProc(FIF_JPEG, "Cannot open %s for writing", filenameIO->dst_file);
+ }
+ }
+ if(fp == NULL) {
+ throw(1);
+ }
+
+ // Specify data destination for compression
+ jpeg_stdio_dest(&dstinfo, fp);
+
+ // Start compressor (note no image data is actually written here)
+ jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
+
+ // Copy to the output file any extra markers that we want to preserve
+ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
+
+ // Execute image transformation, if any
+ jtransform_execute_transformation(&srcinfo, &dstinfo, src_coef_arrays, &transfoptions);
+
+ // Finish compression and release memory
+ jpeg_finish_compress(&dstinfo);
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_finish_decompress(&srcinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ // Close output file and return
+ fclose(fp);
+ }
+ catch(...) {
+ if(fp) fclose(fp);
+ jpeg_destroy_compress(&dstinfo);
+ jpeg_destroy_decompress(&srcinfo);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------
+// FreeImage interface
+// ----------------------------------------------------------
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransform(const char *src_file, const char *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
+ try {
+ // check the src file format
+ if(FreeImage_GetFileType(src_file) != FIF_JPEG) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // setup IO
+ FilenameIO filenameIO;
+ memset(&filenameIO, 0, sizeof(FilenameIO));
+ filenameIO.src_file = src_file;
+ filenameIO.dst_file = dst_file;
+
+ // perform the transformation
+ return LosslessTransform(&filenameIO, operation, NULL, perfect);
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(FIF_JPEG, text);
+ return FALSE;
+ }
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGCrop(const char *src_file, const char *dst_file, int left, int top, int right, int bottom) {
+ char crop[64];
+
+ try {
+ // check the src file format
+ if(FreeImage_GetFileType(src_file) != FIF_JPEG) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // normalize the rectangle
+ if(right < left) {
+ INPLACESWAP(left, right);
+ }
+ if(bottom < top) {
+ INPLACESWAP(top, bottom);
+ }
+
+ // build the crop option
+ sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top);
+
+ // setup IO
+ FilenameIO filenameIO;
+ memset(&filenameIO, 0, sizeof(FilenameIO));
+ filenameIO.src_file = src_file;
+ filenameIO.dst_file = dst_file;
+
+ // perform the transformation
+ return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE);
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(FIF_JPEG, text);
+ return FALSE;
+ }
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGTransformU(const wchar_t *src_file, const wchar_t *dst_file, FREE_IMAGE_JPEG_OPERATION operation, BOOL perfect) {
+#ifdef _WIN32
+ try {
+ // check the src file format
+ if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // setup IO
+ FilenameIO filenameIO;
+ memset(&filenameIO, 0, sizeof(FilenameIO));
+ filenameIO.wsrc_file = src_file;
+ filenameIO.wdst_file = dst_file;
+
+ // perform the transformation
+ return LosslessTransform(&filenameIO, operation, NULL, perfect);
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(FIF_JPEG, text);
+ }
+#endif /// _WIN32
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_JPEGCropU(const wchar_t *src_file, const wchar_t *dst_file, int left, int top, int right, int bottom) {
+#ifdef _WIN32
+ char crop[64];
+
+ try {
+ // check the src file format
+ if(FreeImage_GetFileTypeU(src_file) != FIF_JPEG) {
+ throw FI_MSG_ERROR_MAGIC_NUMBER;
+ }
+
+ // normalize the rectangle
+ if(right < left) {
+ INPLACESWAP(left, right);
+ }
+ if(bottom < top) {
+ INPLACESWAP(top, bottom);
+ }
+
+ // build the crop option
+ sprintf(crop, "%dx%d+%d+%d", right - left, bottom - top, left, top);
+
+ // setup IO
+ FilenameIO filenameIO;
+ memset(&filenameIO, 0, sizeof(FilenameIO));
+ filenameIO.wsrc_file = src_file;
+ filenameIO.wdst_file = dst_file;
+
+ // perform the transformation
+ return LosslessTransform(&filenameIO, FIJPEG_OP_NONE, crop, FALSE);
+
+ } catch(const char *text) {
+ FreeImage_OutputMessageProc(FIF_JPEG, text);
+ }
+#endif // _WIN32
+ return FALSE;
+}
diff --git a/Source/FreeImageToolkit/MultigridPoissonSolver.cpp b/Source/FreeImageToolkit/MultigridPoissonSolver.cpp
new file mode 100644
index 0000000..6f661b8
--- /dev/null
+++ b/Source/FreeImageToolkit/MultigridPoissonSolver.cpp
@@ -0,0 +1,502 @@
+// ==========================================================
+// Poisson solver based on a full multigrid algorithm
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// Reference:
+// PRESS, W. H., TEUKOLSKY, S. A., VETTERLING, W. T., AND FLANNERY, B. P.
+// 1992. Numerical Recipes in C: The Art of Scientific Computing, 2nd ed. Cambridge University Press.
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "ToneMapping.h"
+
+static const int NPRE = 1; // Number of relaxation sweeps before ...
+static const int NPOST = 1; // ... and after the coarse-grid correction is computed
+static const int NGMAX = 15; // Maximum number of grids
+
+/**
+Copy src into dst
+*/
+static inline void fmg_copyArray(FIBITMAP *dst, FIBITMAP *src) {
+ memcpy(FreeImage_GetBits(dst), FreeImage_GetBits(src), FreeImage_GetHeight(dst) * FreeImage_GetPitch(dst));
+}
+
+/**
+Fills src with zeros
+*/
+static inline void fmg_fillArrayWithZeros(FIBITMAP *src) {
+ memset(FreeImage_GetBits(src), 0, FreeImage_GetHeight(src) * FreeImage_GetPitch(src));
+}
+
+/**
+Half-weighting restriction. nc is the coarse-grid dimension. The fine-grid solution is input in
+uf[0..2*nc-2][0..2*nc-2], the coarse-grid solution is returned in uc[0..nc-1][0..nc-1].
+*/
+static void fmg_restrict(FIBITMAP *UC, FIBITMAP *UF, int nc) {
+ int row_uc, row_uf, col_uc, col_uf;
+
+ const int uc_pitch = FreeImage_GetPitch(UC) / sizeof(float);
+ const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float);
+
+ float *uc_bits = (float*)FreeImage_GetBits(UC);
+ const float *uf_bits = (float*)FreeImage_GetBits(UF);
+
+ // interior points
+ {
+ float *uc_scan = uc_bits + uc_pitch;
+ for (row_uc = 1, row_uf = 2; row_uc < nc-1; row_uc++, row_uf += 2) {
+ const float *uf_scan = uf_bits + row_uf * uf_pitch;
+ for (col_uc = 1, col_uf = 2; col_uc < nc-1; col_uc++, col_uf += 2) {
+ // calculate
+ // UC(row_uc, col_uc) =
+ // 0.5 * UF(row_uf, col_uf) + 0.125 * [ UF(row_uf+1, col_uf) + UF(row_uf-1, col_uf) + UF(row_uf, col_uf+1) + UF(row_uf, col_uf-1) ]
+ float *uc_pixel = uc_scan + col_uc;
+ const float *uf_center = uf_scan + col_uf;
+ *uc_pixel = 0.5F * *uf_center + 0.125F * ( *(uf_center + uf_pitch) + *(uf_center - uf_pitch) + *(uf_center + 1) + *(uf_center - 1) );
+ }
+ uc_scan += uc_pitch;
+ }
+ }
+ // boundary points
+ const int ncc = 2*nc-1;
+ {
+ /*
+ calculate the following:
+ for (row_uc = 0, row_uf = 0; row_uc < nc; row_uc++, row_uf += 2) {
+ UC(row_uc, 0) = UF(row_uf, 0);
+ UC(row_uc, nc-1) = UF(row_uf, ncc-1);
+ }
+ */
+ float *uc_scan = uc_bits;
+ for (row_uc = 0, row_uf = 0; row_uc < nc; row_uc++, row_uf += 2) {
+ const float *uf_scan = uf_bits + row_uf * uf_pitch;
+ uc_scan[0] = uf_scan[0];
+ uc_scan[nc-1] = uf_scan[ncc-1];
+ uc_scan += uc_pitch;
+ }
+ }
+ {
+ /*
+ calculate the following:
+ for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) {
+ UC(0, col_uc) = UF(0, col_uf);
+ UC(nc-1, col_uc) = UF(ncc-1, col_uf);
+ }
+ */
+ float *uc_scan_top = uc_bits;
+ float *uc_scan_bottom = uc_bits + (nc-1)*uc_pitch;
+ const float *uf_scan_top = uf_bits + (ncc-1)*uf_pitch;
+ const float *uf_scan_bottom = uf_bits;
+ for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) {
+ uc_scan_top[col_uc] = uf_scan_top[col_uf];
+ uc_scan_bottom[col_uc] = uf_scan_bottom[col_uf];
+ }
+ }
+}
+
+/**
+Solution of the model problem on the coarsest grid, where h = 1/2 .
+The right-hand side is input
+in rhs[0..2][0..2] and the solution is returned in u[0..2][0..2].
+*/
+static void fmg_solve(FIBITMAP *U, FIBITMAP *RHS) {
+ // fill U with zeros
+ fmg_fillArrayWithZeros(U);
+ // calculate U(1, 1) = -h*h*RHS(1, 1)/4.0 where h = 1/2
+ float *u_scan = (float*)FreeImage_GetScanLine(U, 1);
+ const float *rhs_scan = (float*)FreeImage_GetScanLine(RHS, 1);
+ u_scan[1] = -rhs_scan[1] / 16;
+}
+
+/**
+Coarse-to-fine prolongation by bilinear interpolation. nf is the fine-grid dimension. The coarsegrid
+solution is input as uc[0..nc-1][0..nc-1], where nc = nf/2 + 1. The fine-grid solution is
+returned in uf[0..nf-1][0..nf-1].
+*/
+static void fmg_prolongate(FIBITMAP *UF, FIBITMAP *UC, int nf) {
+ int row_uc, row_uf, col_uc, col_uf;
+
+ const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float);
+ const int uc_pitch = FreeImage_GetPitch(UC) / sizeof(float);
+
+ float *uf_bits = (float*)FreeImage_GetBits(UF);
+ const float *uc_bits = (float*)FreeImage_GetBits(UC);
+
+ // do elements that are copies
+ {
+ const int nc = nf/2 + 1;
+
+ float *uf_scan = uf_bits;
+ const float *uc_scan = uc_bits;
+ for (row_uc = 0; row_uc < nc; row_uc++) {
+ for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) {
+ // calculate UF(2*row_uc, col_uf) = UC(row_uc, col_uc);
+ uf_scan[col_uf] = uc_scan[col_uc];
+ }
+ uc_scan += uc_pitch;
+ uf_scan += 2 * uf_pitch;
+ }
+ }
+ // do odd-numbered columns, interpolating vertically
+ {
+ for(row_uf = 1; row_uf < nf-1; row_uf += 2) {
+ float *uf_scan = uf_bits + row_uf * uf_pitch;
+ for (col_uf = 0; col_uf < nf; col_uf += 2) {
+ // calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf+1, col_uf) + UF(row_uf-1, col_uf) )
+ uf_scan[col_uf] = 0.5F * ( *(uf_scan + uf_pitch + col_uf) + *(uf_scan - uf_pitch + col_uf) );
+ }
+ }
+ }
+ // do even-numbered columns, interpolating horizontally
+ {
+ float *uf_scan = uf_bits;
+ for(row_uf = 0; row_uf < nf; row_uf++) {
+ for (col_uf = 1; col_uf < nf-1; col_uf += 2) {
+ // calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf, col_uf+1) + UF(row_uf, col_uf-1) )
+ uf_scan[col_uf] = 0.5F * ( uf_scan[col_uf + 1] + uf_scan[col_uf - 1] );
+ }
+ uf_scan += uf_pitch;
+ }
+ }
+}
+
+/**
+Red-black Gauss-Seidel relaxation for model problem. Updates the current value of the solution
+u[0..n-1][0..n-1], using the right-hand side function rhs[0..n-1][0..n-1].
+*/
+static void fmg_relaxation(FIBITMAP *U, FIBITMAP *RHS, int n) {
+ int row, col, ipass, isw, jsw;
+ const float h = 1.0F / (n - 1);
+ const float h2 = h*h;
+
+ const int u_pitch = FreeImage_GetPitch(U) / sizeof(float);
+ const int rhs_pitch = FreeImage_GetPitch(RHS) / sizeof(float);
+
+ float *u_bits = (float*)FreeImage_GetBits(U);
+ const float *rhs_bits = (float*)FreeImage_GetBits(RHS);
+
+ for (ipass = 0, jsw = 1; ipass < 2; ipass++, jsw = 3-jsw) { // Red and black sweeps
+ float *u_scan = u_bits + u_pitch;
+ const float *rhs_scan = rhs_bits + rhs_pitch;
+ for (row = 1, isw = jsw; row < n-1; row++, isw = 3-isw) {
+ for (col = isw; col < n-1; col += 2) {
+ // Gauss-Seidel formula
+ // calculate U(row, col) =
+ // 0.25 * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - h2 * RHS(row, col) ]
+ float *u_center = u_scan + col;
+ const float *rhs_center = rhs_scan + col;
+ *u_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1);
+ *u_center -= h2 * *rhs_center;
+ *u_center *= 0.25F;
+ }
+ u_scan += u_pitch;
+ rhs_scan += rhs_pitch;
+ }
+ }
+}
+
+/**
+Returns minus the residual for the model problem. Input quantities are u[0..n-1][0..n-1] and
+rhs[0..n-1][0..n-1], while res[0..n-1][0..n-1] is returned.
+*/
+static void fmg_residual(FIBITMAP *RES, FIBITMAP *U, FIBITMAP *RHS, int n) {
+ int row, col;
+
+ const float h = 1.0F / (n-1);
+ const float h2i = 1.0F / (h*h);
+
+ const int res_pitch = FreeImage_GetPitch(RES) / sizeof(float);
+ const int u_pitch = FreeImage_GetPitch(U) / sizeof(float);
+ const int rhs_pitch = FreeImage_GetPitch(RHS) / sizeof(float);
+
+ float *res_bits = (float*)FreeImage_GetBits(RES);
+ const float *u_bits = (float*)FreeImage_GetBits(U);
+ const float *rhs_bits = (float*)FreeImage_GetBits(RHS);
+
+ // interior points
+ {
+ float *res_scan = res_bits + res_pitch;
+ const float *u_scan = u_bits + u_pitch;
+ const float *rhs_scan = rhs_bits + rhs_pitch;
+ for (row = 1; row < n-1; row++) {
+ for (col = 1; col < n-1; col++) {
+ // calculate RES(row, col) =
+ // -h2i * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - 4 * U(row, col) ] + RHS(row, col);
+ float *res_center = res_scan + col;
+ const float *u_center = u_scan + col;
+ const float *rhs_center = rhs_scan + col;
+ *res_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1) - 4 * *u_center;
+ *res_center *= -h2i;
+ *res_center += *rhs_center;
+ }
+ res_scan += res_pitch;
+ u_scan += u_pitch;
+ rhs_scan += rhs_pitch;
+ }
+ }
+
+ // boundary points
+ {
+ memset(FreeImage_GetScanLine(RES, 0), 0, FreeImage_GetPitch(RES));
+ memset(FreeImage_GetScanLine(RES, n-1), 0, FreeImage_GetPitch(RES));
+ float *left = res_bits;
+ float *right = res_bits + (n-1);
+ for(int k = 0; k < n; k++) {
+ *left = 0;
+ *right = 0;
+ left += res_pitch;
+ right += res_pitch;
+ }
+ }
+}
+
+/**
+Does coarse-to-fine interpolation and adds result to uf. nf is the fine-grid dimension. The
+coarse-grid solution is input as uc[0..nc-1][0..nc-1], where nc = nf/2+1. The fine-grid solution
+is returned in uf[0..nf-1][0..nf-1]. res[0..nf-1][0..nf-1] is used for temporary storage.
+*/
+static void fmg_addint(FIBITMAP *UF, FIBITMAP *UC, FIBITMAP *RES, int nf) {
+ fmg_prolongate(RES, UC, nf);
+
+ const int uf_pitch = FreeImage_GetPitch(UF) / sizeof(float);
+ const int res_pitch = FreeImage_GetPitch(RES) / sizeof(float);
+
+ float *uf_bits = (float*)FreeImage_GetBits(UF);
+ const float *res_bits = (float*)FreeImage_GetBits(RES);
+
+ for(int row = 0; row < nf; row++) {
+ for(int col = 0; col < nf; col++) {
+ // calculate UF(row, col) = UF(row, col) + RES(row, col);
+ uf_bits[col] += res_bits[col];
+ }
+ uf_bits += uf_pitch;
+ res_bits += res_pitch;
+ }
+}
+
+/**
+Full Multigrid Algorithm for solution of linear elliptic equation, here the model problem (19.0.6).
+On input u[0..n-1][0..n-1] contains the right-hand side ñ, while on output it returns the solution.
+The dimension n must be of the form 2^j + 1 for some integer j. (j is actually the number of
+grid levels used in the solution, called ng below.) ncycle is the number of V-cycles to be
+used at each level.
+*/
+static BOOL fmg_mglin(FIBITMAP *U, int n, int ncycle) {
+ int j, jcycle, jj, jpost, jpre, nf, ngrid;
+
+ FIBITMAP **IRHO = NULL;
+ FIBITMAP **IU = NULL;
+ FIBITMAP **IRHS = NULL;
+ FIBITMAP **IRES = NULL;
+
+ int ng = 0; // number of allocated grids
+
+// --------------------------------------------------------------------------
+
+#define _CREATE_ARRAY_GRID_(array, array_size) \
+ array = (FIBITMAP**)malloc(array_size * sizeof(FIBITMAP*));\
+ if(!array) throw(1);\
+ memset(array, 0, array_size * sizeof(FIBITMAP*))
+
+#define _FREE_ARRAY_GRID_(array, array_size) \
+ if(NULL != array) {\
+ for(int k = 0; k < array_size; k++) {\
+ if(NULL != array[k]) {\
+ FreeImage_Unload(array[k]); array[k] = NULL;\
+ }\
+ }\
+ free(array);\
+ }
+
+// --------------------------------------------------------------------------
+
+ try {
+ int nn = n;
+ // check grid size and grid levels
+ while (nn >>= 1) ng++;
+ if (n != 1 + (1L << ng)) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Multigrid algorithm: n = %d, while n-1 must be a power of 2.", n);
+ throw(1);
+ }
+ if (ng > NGMAX) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Multigrid algorithm: ng = %d while NGMAX = %d, increase NGMAX.", ng, NGMAX);
+ throw(1);
+ }
+ // allocate grid arrays
+ {
+ _CREATE_ARRAY_GRID_(IRHO, ng);
+ _CREATE_ARRAY_GRID_(IU, ng);
+ _CREATE_ARRAY_GRID_(IRHS, ng);
+ _CREATE_ARRAY_GRID_(IRES, ng);
+ }
+
+ nn = n/2 + 1;
+ ngrid = ng - 2;
+
+ // allocate storage for r.h.s. on grid (ng - 2) ...
+ IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IRHO[ngrid]) throw(1);
+
+ // ... and fill it by restricting from the fine grid
+ fmg_restrict(IRHO[ngrid], U, nn);
+
+ // similarly allocate storage and fill r.h.s. on all coarse grids.
+ while (nn > 3) {
+ nn = nn/2 + 1;
+ ngrid--;
+ IRHO[ngrid] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IRHO[ngrid]) throw(1);
+ fmg_restrict(IRHO[ngrid], IRHO[ngrid+1], nn);
+ }
+
+ nn = 3;
+
+ IU[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IU[0]) throw(1);
+ IRHS[0] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IRHS[0]) throw(1);
+
+ // initial solution on coarsest grid
+ fmg_solve(IU[0], IRHO[0]);
+ // irho[0] no longer needed ...
+ FreeImage_Unload(IRHO[0]); IRHO[0] = NULL;
+
+ ngrid = ng;
+
+ // nested iteration loop
+ for (j = 1; j < ngrid; j++) {
+ nn = 2*nn - 1;
+
+ IU[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IU[j]) throw(1);
+ IRHS[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IRHS[j]) throw(1);
+ IRES[j] = FreeImage_AllocateT(FIT_FLOAT, nn, nn);
+ if(!IRES[j]) throw(1);
+
+ fmg_prolongate(IU[j], IU[j-1], nn);
+
+ // interpolate from coarse grid to next finer grid
+
+ // set up r.h.s.
+ fmg_copyArray(IRHS[j], j != (ngrid - 1) ? IRHO[j] : U);
+
+ // V-cycle loop
+ for (jcycle = 0; jcycle < ncycle; jcycle++) {
+ nf = nn;
+ // downward stoke of the V
+ for (jj = j; jj >= 1; jj--) {
+ // pre-smoothing
+ for (jpre = 0; jpre < NPRE; jpre++) {
+ fmg_relaxation(IU[jj], IRHS[jj], nf);
+ }
+ fmg_residual(IRES[jj], IU[jj], IRHS[jj], nf);
+ nf = nf/2 + 1;
+ // restriction of the residual is the next r.h.s.
+ fmg_restrict(IRHS[jj-1], IRES[jj], nf);
+ // zero for initial guess in next relaxation
+ fmg_fillArrayWithZeros(IU[jj-1]);
+ }
+ // bottom of V: solve on coarsest grid
+ fmg_solve(IU[0], IRHS[0]);
+ nf = 3;
+ // upward stroke of V.
+ for (jj = 1; jj <= j; jj++) {
+ nf = 2*nf - 1;
+ // use res for temporary storage inside addint
+ fmg_addint(IU[jj], IU[jj-1], IRES[jj], nf);
+ // post-smoothing
+ for (jpost = 0; jpost < NPOST; jpost++) {
+ fmg_relaxation(IU[jj], IRHS[jj], nf);
+ }
+ }
+ }
+ }
+
+ // return solution in U
+ fmg_copyArray(U, IU[ngrid-1]);
+
+ // delete allocated arrays
+ _FREE_ARRAY_GRID_(IRES, ng);
+ _FREE_ARRAY_GRID_(IRHS, ng);
+ _FREE_ARRAY_GRID_(IU, ng);
+ _FREE_ARRAY_GRID_(IRHO, ng);
+
+ return TRUE;
+
+ } catch(int) {
+ // delete allocated arrays
+ _FREE_ARRAY_GRID_(IRES, ng);
+ _FREE_ARRAY_GRID_(IRHS, ng);
+ _FREE_ARRAY_GRID_(IU, ng);
+ _FREE_ARRAY_GRID_(IRHO, ng);
+
+ return FALSE;
+ }
+}
+
+// --------------------------------------------------------------------------
+
+/**
+Poisson solver based on a multigrig algorithm.
+This routine solves a Poisson equation, remap result pixels to [0..1] and returns the solution.
+NB: The input image is first stored inside a square image whose size is (2^j + 1)x(2^j + 1) for some integer j,
+where j is such that 2^j is the nearest larger dimension corresponding to MAX(image width, image height).
+@param Laplacian Laplacian image
+@param ncycle Number of cycles in the multigrid algorithm (usually 2 or 3)
+@return Returns the solved PDE equations if successful, returns NULL otherwise
+*/
+FIBITMAP* DLL_CALLCONV
+FreeImage_MultigridPoissonSolver(FIBITMAP *Laplacian, int ncycle) {
+ if(!Laplacian) return NULL;
+
+ int width = FreeImage_GetWidth(Laplacian);
+ int height = FreeImage_GetHeight(Laplacian);
+
+ // get nearest larger dimension length that is acceptable by the algorithm
+ int n = MAX(width, height);
+ int size = 0;
+ while((n >>= 1) > 0) size++;
+ // size must be of the form 2^j + 1 for some integer j
+ size = 1 + (1 << (size + 1));
+
+ // allocate a temporary square image I
+ FIBITMAP *I = FreeImage_AllocateT(FIT_FLOAT, size, size);
+ if(!I) return NULL;
+
+ // copy Laplacian into I and shift pixels to create a boundary
+ FreeImage_Paste(I, Laplacian, 1, 1, 255);
+
+ // solve the PDE equation
+ fmg_mglin(I, size, ncycle);
+
+ // shift pixels back
+ FIBITMAP *U = FreeImage_Copy(I, 1, 1, width + 1, height + 1);
+ FreeImage_Unload(I);
+
+ // remap pixels to [0..1]
+ NormalizeY(U, 0, 1);
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(U, Laplacian);
+
+ // return the integrated image
+ return U;
+}
+
diff --git a/Source/FreeImageToolkit/Rescale.cpp b/Source/FreeImageToolkit/Rescale.cpp
new file mode 100644
index 0000000..5dc90ba
--- /dev/null
+++ b/Source/FreeImageToolkit/Rescale.cpp
@@ -0,0 +1,227 @@
+// ==========================================================
+// Upsampling / downsampling routine
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "Resize.h"
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_Rescale(FIBITMAP *src, int dst_width, int dst_height, FREE_IMAGE_FILTER filter) {
+ FIBITMAP *dst = NULL;
+
+ if (!src || (dst_width <= 0) || (dst_height <= 0) || (FreeImage_GetWidth(src) <= 0) || (FreeImage_GetHeight(src) <= 0)) {
+ return NULL;
+ }
+
+ // select the filter
+ CGenericFilter *pFilter = NULL;
+ switch(filter) {
+ case FILTER_BOX:
+ pFilter = new CBoxFilter();
+ break;
+ case FILTER_BICUBIC:
+ pFilter = new CBicubicFilter();
+ break;
+ case FILTER_BILINEAR:
+ pFilter = new CBilinearFilter();
+ break;
+ case FILTER_BSPLINE:
+ pFilter = new CBSplineFilter();
+ break;
+ case FILTER_CATMULLROM:
+ pFilter = new CCatmullRomFilter();
+ break;
+ case FILTER_LANCZOS3:
+ pFilter = new CLanczos3Filter();
+ break;
+ }
+
+ CResizeEngine Engine(pFilter);
+
+ // perform upsampling or downsampling
+
+ if((FreeImage_GetBPP(src) == 4) || (FreeImage_GetColorType(src) == FIC_PALETTE)) {
+ // special case for 4-bit images or color map indexed images ...
+ if(FreeImage_IsTransparent(src) == FALSE) {
+ FIBITMAP *src24 = NULL;
+ FIBITMAP *dst24 = NULL;
+ try {
+ // transparent conversion to 24-bit (any transparency table will be destroyed)
+ src24 = FreeImage_ConvertTo24Bits(src);
+ if(!src24) throw(1);
+ // perform upsampling or downsampling
+ dst24 = Engine.scale(src24, dst_width, dst_height);
+ if(!dst24) throw(1);
+ // color quantize to 8-bit
+ dst = FreeImage_ColorQuantize(dst24, FIQ_NNQUANT);
+ // free and return
+ FreeImage_Unload(src24);
+ FreeImage_Unload(dst24);
+ } catch(int) {
+ if(src24) FreeImage_Unload(src24);
+ if(dst24) FreeImage_Unload(dst24);
+ }
+ } else {
+ FIBITMAP *src32 = NULL;
+ try {
+ // transparent conversion to 32-bit (keep transparency)
+ src32 = FreeImage_ConvertTo32Bits(src);
+ if(!src32) throw(1);
+ // perform upsampling or downsampling
+ dst = Engine.scale(src32, dst_width, dst_height);
+ if(!dst) throw(1);
+ // free and return
+ FreeImage_Unload(src32);
+ } catch(int) {
+ if(src32) FreeImage_Unload(src32);
+ if(dst) FreeImage_Unload(dst);
+ }
+ }
+ }
+ else if((FreeImage_GetBPP(src) == 16) && (FreeImage_GetImageType(src) == FIT_BITMAP)) {
+ // convert 16-bit RGB to 24-bit
+ FIBITMAP *src24 = NULL;
+ try {
+ // transparent conversion to 24-bit (any transparency table will be destroyed)
+ src24 = FreeImage_ConvertTo24Bits(src);
+ if(!src24) throw(1);
+ // perform upsampling or downsampling
+ dst = Engine.scale(src24, dst_width, dst_height);
+ if(!dst) throw(1);
+ // free and return
+ FreeImage_Unload(src24);
+ } catch(int) {
+ if(src24) FreeImage_Unload(src24);
+ if(dst) FreeImage_Unload(dst);
+ }
+ }
+ else {
+ // normal case :
+ // 1- or 8-bit greyscale, 24- or 32-bit RGB(A) images
+ // 16-bit greyscale, 48- or 64-bit RGB(A) images
+ // 32-bit float, 96- or 128-bit RGB(A) float images
+ dst = Engine.scale(src, dst_width, dst_height);
+ }
+
+
+ delete pFilter;
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(dst, src);
+
+ return dst;
+}
+
+FIBITMAP * DLL_CALLCONV
+FreeImage_MakeThumbnail(FIBITMAP *dib, int max_pixel_size, BOOL convert) {
+ FIBITMAP *thumbnail = NULL;
+ int new_width, new_height;
+
+ if(!dib || (max_pixel_size <= 0)) return NULL;
+
+ int width = FreeImage_GetWidth(dib);
+ int height = FreeImage_GetHeight(dib);
+
+ if(max_pixel_size == 0) max_pixel_size = 1;
+
+ if((width < max_pixel_size) && (height < max_pixel_size)) {
+ // image is smaller than the requested thumbnail
+ return FreeImage_Clone(dib);
+ }
+
+ if(width > height) {
+ new_width = max_pixel_size;
+ // change image height with the same ratio
+ double ratio = ((double)new_width / (double)width);
+ new_height = (int)(height * ratio + 0.5);
+ if(new_height == 0) new_height = 1;
+ } else {
+ new_height = max_pixel_size;
+ // change image width with the same ratio
+ double ratio = ((double)new_height / (double)height);
+ new_width = (int)(width * ratio + 0.5);
+ if(new_width == 0) new_width = 1;
+ }
+
+ const FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
+
+ // perform downsampling using a bilinear interpolation
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ FREE_IMAGE_FILTER filter = FILTER_BILINEAR;
+ thumbnail = FreeImage_Rescale(dib, new_width, new_height, filter);
+ }
+ break;
+
+ case FIT_INT16:
+ case FIT_UINT32:
+ case FIT_INT32:
+ case FIT_DOUBLE:
+ case FIT_COMPLEX:
+ default:
+ // cannot rescale this kind of image
+ thumbnail = NULL;
+ break;
+ }
+
+ if((thumbnail != NULL) && (image_type != FIT_BITMAP) && convert) {
+ // convert to a standard bitmap
+ FIBITMAP *bitmap = NULL;
+ switch(image_type) {
+ case FIT_UINT16:
+ bitmap = FreeImage_ConvertTo8Bits(thumbnail);
+ break;
+ case FIT_RGB16:
+ bitmap = FreeImage_ConvertTo24Bits(thumbnail);
+ break;
+ case FIT_RGBA16:
+ bitmap = FreeImage_ConvertTo32Bits(thumbnail);
+ break;
+ case FIT_FLOAT:
+ bitmap = FreeImage_ConvertToStandardType(thumbnail, TRUE);
+ break;
+ case FIT_RGBF:
+ bitmap = FreeImage_ToneMapping(thumbnail, FITMO_DRAGO03);
+ break;
+ case FIT_RGBAF:
+ // no way to keep the transparency yet ...
+ FIBITMAP *rgbf = FreeImage_ConvertToRGBF(thumbnail);
+ bitmap = FreeImage_ToneMapping(rgbf, FITMO_DRAGO03);
+ FreeImage_Unload(rgbf);
+ break;
+ }
+ if(bitmap != NULL) {
+ FreeImage_Unload(thumbnail);
+ thumbnail = bitmap;
+ }
+ }
+
+ // copy metadata from src to dst
+ FreeImage_CloneMetadata(thumbnail, dib);
+
+ return thumbnail;
+}
diff --git a/Source/FreeImageToolkit/Resize.cpp b/Source/FreeImageToolkit/Resize.cpp
new file mode 100644
index 0000000..790611f
--- /dev/null
+++ b/Source/FreeImageToolkit/Resize.cpp
@@ -0,0 +1,646 @@
+// ==========================================================
+// Upsampling / downsampling classes
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "Resize.h"
+
+/**
+ Filter weights table.
+ This class stores contribution information for an entire line (row or column).
+*/
+CWeightsTable::CWeightsTable(CGenericFilter *pFilter, DWORD uDstSize, DWORD uSrcSize) {
+ DWORD u;
+ double dWidth;
+ double dFScale = 1.0;
+ double dFilterWidth = pFilter->GetWidth();
+
+ // scale factor
+ double dScale = double(uDstSize) / double(uSrcSize);
+
+ if(dScale < 1.0) {
+ // minification
+ dWidth = dFilterWidth / dScale;
+ dFScale = dScale;
+ } else {
+ // magnification
+ dWidth= dFilterWidth;
+ }
+
+ // allocate a new line contributions structure
+ //
+ // window size is the number of sampled pixels
+ m_WindowSize = 2 * (int)ceil(dWidth) + 1;
+ m_LineLength = uDstSize;
+ // allocate list of contributions
+ m_WeightTable = (Contribution*)malloc(m_LineLength * sizeof(Contribution));
+ for(u = 0 ; u < m_LineLength ; u++) {
+ // allocate contributions for every pixel
+ m_WeightTable[u].Weights = (double*)malloc(m_WindowSize * sizeof(double));
+ }
+
+ // offset for discrete to continuous coordinate conversion
+ double dOffset = (0.5 / dScale) - 0.5;
+
+
+ for(u = 0; u < m_LineLength; u++) {
+ // scan through line of contributions
+ double dCenter = (double)u / dScale + dOffset; // reverse mapping
+ // find the significant edge points that affect the pixel
+ int iLeft = MAX (0, (int)floor (dCenter - dWidth));
+ int iRight = MIN ((int)ceil (dCenter + dWidth), int(uSrcSize) - 1);
+
+ // cut edge points to fit in filter window in case of spill-off
+ if((iRight - iLeft + 1) > int(m_WindowSize)) {
+ if(iLeft < (int(uSrcSize) - 1 / 2)) {
+ iLeft++;
+ } else {
+ iRight--;
+ }
+ }
+
+ m_WeightTable[u].Left = iLeft;
+ m_WeightTable[u].Right = iRight;
+
+ int iSrc = 0;
+ double dTotalWeight = 0; // zero sum of weights
+ for(iSrc = iLeft; iSrc <= iRight; iSrc++) {
+ // calculate weights
+ double weight = dFScale * pFilter->Filter(dFScale * (dCenter - (double)iSrc));
+ m_WeightTable[u].Weights[iSrc-iLeft] = weight;
+ dTotalWeight += weight;
+ }
+ if((dTotalWeight > 0) && (dTotalWeight != 1)) {
+ // normalize weight of neighbouring points
+ for(iSrc = iLeft; iSrc <= iRight; iSrc++) {
+ // normalize point
+ m_WeightTable[u].Weights[iSrc-iLeft] /= dTotalWeight;
+ }
+ // simplify the filter, discarding null weights at the right
+ iSrc = iRight - iLeft;
+ while(m_WeightTable[u].Weights[iSrc] == 0){
+ m_WeightTable[u].Right--;
+ iSrc--;
+ if(m_WeightTable[u].Right == m_WeightTable[u].Left)
+ break;
+ }
+
+ }
+ }
+}
+
+CWeightsTable::~CWeightsTable() {
+ for(DWORD u = 0; u < m_LineLength; u++) {
+ // free contributions for every pixel
+ free(m_WeightTable[u].Weights);
+ }
+ // free list of pixels contributions
+ free(m_WeightTable);
+}
+
+// ---------------------------------------------
+
+/**
+ CResizeEngine<br>
+ This class performs filtered zoom. It scales an image to the desired dimensions with
+ any of the CGenericFilter derived filter class.<br>
+ It works with 8-, 24- and 32-bit buffers.<br><br>
+
+ <b>References</b> : <br>
+ [1] Paul Heckbert, C code to zoom raster images up or down, with nice filtering.
+ UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html
+ [2] Eran Yariv, Two Pass Scaling using Filters. The Code Project, December 1999.
+ [online] http://www.codeproject.com/bitmap/2_pass_scaling.asp
+
+*/
+
+FIBITMAP* CResizeEngine::scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height) {
+ DWORD src_width = FreeImage_GetWidth(src);
+ DWORD src_height = FreeImage_GetHeight(src);
+
+ unsigned redMask = FreeImage_GetRedMask(src);
+ unsigned greenMask = FreeImage_GetGreenMask(src);
+ unsigned blueMask = FreeImage_GetBlueMask(src);
+
+ unsigned bpp = FreeImage_GetBPP(src);
+ if(bpp == 1) {
+ // convert output to 8-bit
+ bpp = 8;
+ }
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(src);
+
+ // allocate the dst image
+ FIBITMAP *dst = FreeImage_AllocateT(image_type, dst_width, dst_height, bpp, redMask, greenMask, blueMask);
+ if(!dst) return NULL;
+
+ if(bpp == 8) {
+ if(FreeImage_GetColorType(src) == FIC_MINISWHITE) {
+ // build an inverted greyscale palette
+ RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
+ for(int i = 0; i < 256; i++) {
+ dst_pal[i].rgbRed = dst_pal[i].rgbGreen =
+ dst_pal[i].rgbBlue = (BYTE)(255 - i);
+ }
+ } else {
+ // build a greyscale palette
+ RGBQUAD *dst_pal = FreeImage_GetPalette(dst);
+ for(int i = 0; i < 256; i++) {
+ dst_pal[i].rgbRed = dst_pal[i].rgbGreen =
+ dst_pal[i].rgbBlue = (BYTE)i;
+ }
+ }
+ }
+
+ // decide which filtering order (xy or yx) is faster for this mapping by
+ // counting convolution multiplies
+
+ if(dst_width*src_height <= dst_height*src_width) {
+ // xy filtering
+ // -------------
+
+ // allocate a temporary image
+ FIBITMAP *tmp = FreeImage_AllocateT(image_type, dst_width, src_height, bpp, redMask, greenMask, blueMask);
+ if(!tmp) {
+ FreeImage_Unload(dst);
+ return NULL;
+ }
+
+ // scale source image horizontally into temporary image
+ horizontalFilter(src, src_width, src_height, tmp, dst_width, src_height);
+
+ // scale temporary image vertically into result image
+ verticalFilter(tmp, dst_width, src_height, dst, dst_width, dst_height);
+
+ // free temporary image
+ FreeImage_Unload(tmp);
+
+ } else {
+ // yx filtering
+ // -------------
+
+ // allocate a temporary image
+ FIBITMAP *tmp = FreeImage_AllocateT(image_type, src_width, dst_height, bpp, redMask, greenMask, blueMask);
+ if(!tmp) {
+ FreeImage_Unload(dst);
+ return NULL;
+ }
+
+ // scale source image vertically into temporary image
+ verticalFilter(src, src_width, src_height, tmp, src_width, dst_height);
+
+ // scale temporary image horizontally into result image
+ horizontalFilter(tmp, src_width, dst_height, dst, dst_width, dst_height);
+
+ // free temporary image
+ FreeImage_Unload(tmp);
+ }
+
+ return dst;
+}
+
+
+/// Performs horizontal image filtering
+void CResizeEngine::horizontalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height) {
+ if(dst_width == src_width) {
+ // no scaling required, just copy
+ switch(FreeImage_GetBPP(src)) {
+ case 1:
+ {
+ if(FreeImage_GetBPP(dst) != 8) break;
+ for(unsigned y = 0; y < dst_height; y++) {
+ // convert each row
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ FreeImage_ConvertLine1To8(dst_bits, src_bits, dst_width);
+ }
+ }
+ break;
+
+ default:
+ {
+ BYTE *src_bits = FreeImage_GetBits(src);
+ BYTE *dst_bits = FreeImage_GetBits(dst);
+ memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst));
+ }
+ break;
+ }
+ }
+ else {
+ unsigned index; // pixel index
+
+ // allocate and calculate the contributions
+ CWeightsTable weightsTable(m_pFilter, dst_width, src_width);
+
+ // step through rows
+ switch(FreeImage_GetImageType(src)) {
+ case FIT_BITMAP:
+ {
+ switch(FreeImage_GetBPP(src)) {
+ case 1:
+ {
+ // scale and convert to 8-bit
+ if(FreeImage_GetBPP(dst) != 8) break;
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ // scale each row
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ // loop through row
+ double value = 0;
+ int iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(x, i-iLeft);
+
+ BYTE pixel = (src_bits[i >> 3] & (0x80 >> (i & 0x07))) != 0;
+ value += (weight * (double)pixel);
+ }
+ value *= 255;
+
+ // clamp and place result in destination pixel
+ dst_bits[x] = (BYTE)MIN(MAX((int)0, (int)(value + 0.5)), (int)255);
+ }
+ }
+ }
+ break;
+
+ case 8:
+ case 24:
+ case 32:
+ {
+ // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ // scale each row
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ // loop through row
+ double value[4] = {0, 0, 0, 0}; // 4 = 32bpp max
+ int iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(x, i-iLeft);
+
+ index = i * bytespp;
+ for (unsigned j = 0; j < bytespp; j++) {
+ value[j] += (weight * (double)src_bits[index++]);
+ }
+ }
+
+ // clamp and place result in destination pixel
+ for (unsigned j = 0; j < bytespp; j++) {
+ dst_bits[j] = (BYTE)MIN(MAX((int)0, (int)(value[j] + 0.5)), (int)255);
+ }
+
+ dst_bits += bytespp;
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ {
+ // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit)
+ unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD);
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ // scale each row
+ WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, y);
+ WORD *dst_bits = (WORD*)FreeImage_GetScanLine(dst, y);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ // loop through row
+ double value[4] = {0, 0, 0, 0}; // 4 = 64bpp max
+ int iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(x, i-iLeft);
+
+ index = i * wordspp;
+ for (unsigned j = 0; j < wordspp; j++) {
+ value[j] += (weight * (double)src_bits[index++]);
+ }
+ }
+
+ // clamp and place result in destination pixel
+ for (unsigned j = 0; j < wordspp; j++) {
+ dst_bits[j] = (WORD)MIN(MAX((int)0, (int)(value[j] + 0.5)), (int)0xFFFF);
+ }
+
+ dst_bits += wordspp;
+ }
+ }
+ }
+ break;
+
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ // Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit)
+ unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float);
+
+ for(unsigned y = 0; y < dst_height; y++) {
+ // scale each row
+ float *src_bits = (float*)FreeImage_GetScanLine(src, y);
+ float *dst_bits = (float*)FreeImage_GetScanLine(dst, y);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ // loop through row
+ double value[4] = {0, 0, 0, 0}; // 4 = 64bpp max
+ int iLeft = weightsTable.getLeftBoundary(x); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(x); // retrieve right boundary
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(x, i-iLeft);
+
+ index = i * floatspp;
+ for (unsigned j = 0; j < floatspp; j++) {
+ value[j] += (weight * (double)src_bits[index++]);
+ }
+ }
+
+ // place result in destination pixel
+ for (unsigned j = 0; j < floatspp; j++) {
+ dst_bits[j] = (float)value[j];
+ }
+
+ dst_bits += floatspp;
+ }
+ }
+ }
+ break;
+
+ }
+ }
+}
+
+/// Performs vertical image filtering
+void CResizeEngine::verticalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height) {
+ if(src_height == dst_height) {
+ // no scaling required, just copy
+ switch(FreeImage_GetBPP(src)) {
+ case 1:
+ {
+ if(FreeImage_GetBPP(dst) != 8) break;
+ for(unsigned y = 0; y < dst_height; y++) {
+ // convert each row
+ BYTE *src_bits = FreeImage_GetScanLine(src, y);
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, y);
+ FreeImage_ConvertLine1To8(dst_bits, src_bits, dst_width);
+ }
+ }
+ break;
+
+ default:
+ {
+ BYTE *src_bits = FreeImage_GetBits(src);
+ BYTE *dst_bits = FreeImage_GetBits(dst);
+ memcpy(dst_bits, src_bits, dst_height * FreeImage_GetPitch(dst));
+ }
+ break;
+ }
+
+ }
+ else {
+ unsigned index; // pixel index
+
+ // allocate and calculate the contributions
+ CWeightsTable weightsTable(m_pFilter, dst_height, src_height);
+
+
+ // step through columns
+ switch(FreeImage_GetImageType(src)) {
+ case FIT_BITMAP:
+ {
+ switch(FreeImage_GetBPP(src)) {
+ case 1:
+ {
+ // scale and convert to 8-bit
+ if(FreeImage_GetBPP(dst) != 8) break;
+
+ unsigned src_pitch = FreeImage_GetPitch(src);
+ unsigned dst_pitch = FreeImage_GetPitch(dst);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+
+ // work on column x in dst
+ BYTE *dst_bits = FreeImage_GetBits(dst) + x;
+
+ // scale each column
+ for(unsigned y = 0; y < dst_height; y++) {
+ // loop through column
+ double value = 0;
+ int iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(y); // retrieve right boundary
+
+ BYTE *src_bits = FreeImage_GetScanLine(src, iLeft);
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(y, i-iLeft);
+
+ BYTE pixel = (src_bits[x >> 3] & (0x80 >> (x & 0x07))) != 0;
+ value += (weight * (double)pixel);
+
+ src_bits += src_pitch;
+ }
+ value *= 255;
+
+ // clamp and place result in destination pixel
+ *dst_bits = (BYTE)MIN(MAX((int)0, (int)(value + 0.5)), (int)255);
+
+ dst_bits += dst_pitch;
+ }
+ }
+ }
+ break;
+
+ case 8:
+ case 24:
+ case 32:
+ {
+ // Calculate the number of bytes per pixel (1 for 8-bit, 3 for 24-bit or 4 for 32-bit)
+ unsigned bytespp = FreeImage_GetLine(src) / FreeImage_GetWidth(src);
+
+ unsigned src_pitch = FreeImage_GetPitch(src);
+ unsigned dst_pitch = FreeImage_GetPitch(dst);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ index = x * bytespp;
+
+ // work on column x in dst
+ BYTE *dst_bits = FreeImage_GetBits(dst) + index;
+
+ // scale each column
+ for(unsigned y = 0; y < dst_height; y++) {
+ // loop through column
+ double value[4] = {0, 0, 0, 0}; // 4 = 32bpp max
+ int iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(y); // retrieve right boundary
+
+ BYTE *src_bits = FreeImage_GetScanLine(src, iLeft) + index;
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(y, i-iLeft);
+ for (unsigned j = 0; j < bytespp; j++) {
+ value[j] += (weight * (double)src_bits[j]);
+ }
+
+ src_bits += src_pitch;
+ }
+
+ // clamp and place result in destination pixel
+ for (unsigned j = 0; j < bytespp; j++) {
+ dst_bits[j] = (BYTE)MIN(MAX((int)0, (int)(value[j] + 0.5)), (int)255);
+ }
+
+ dst_bits += dst_pitch;
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ {
+ // Calculate the number of words per pixel (1 for 16-bit, 3 for 48-bit or 4 for 64-bit)
+ unsigned wordspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(WORD);
+
+ unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(WORD);
+ unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(WORD);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ index = x * wordspp;
+
+ // work on column x in dst
+ WORD *dst_bits = (WORD*)FreeImage_GetBits(dst) + index;
+
+ // scale each column
+ for(unsigned y = 0; y < dst_height; y++) {
+ // loop through column
+ double value[4] = {0, 0, 0, 0}; // 4 = 64bpp max
+ int iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(y); // retrieve right boundary
+
+ WORD *src_bits = (WORD*)FreeImage_GetScanLine(src, iLeft) + index;
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(y, i-iLeft);
+ for (unsigned j = 0; j < wordspp; j++) {
+ value[j] += (weight * (double)src_bits[j]);
+ }
+
+ src_bits += src_pitch;
+ }
+
+ // clamp and place result in destination pixel
+ for (unsigned j = 0; j < wordspp; j++) {
+ dst_bits[j] = (WORD)MIN(MAX((int)0, (int)(value[j] + 0.5)), (int)0xFFFF);
+ }
+
+ dst_bits += dst_pitch;
+ }
+ }
+ }
+ break;
+
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ {
+ // Calculate the number of floats per pixel (1 for 32-bit, 3 for 96-bit or 4 for 128-bit)
+ unsigned floatspp = (FreeImage_GetLine(src) / FreeImage_GetWidth(src)) / sizeof(float);
+
+ unsigned src_pitch = FreeImage_GetPitch(src) / sizeof(float);
+ unsigned dst_pitch = FreeImage_GetPitch(dst) / sizeof(float);
+
+ for(unsigned x = 0; x < dst_width; x++) {
+ index = x * floatspp;
+
+ // work on column x in dst
+ float *dst_bits = (float*)FreeImage_GetBits(dst) + index;
+
+ // scale each column
+ for(unsigned y = 0; y < dst_height; y++) {
+ // loop through column
+ double value[4] = {0, 0, 0, 0}; // 4 = 64bpp max
+ int iLeft = weightsTable.getLeftBoundary(y); // retrieve left boundary
+ int iRight = weightsTable.getRightBoundary(y); // retrieve right boundary
+
+ float *src_bits = (float*)FreeImage_GetScanLine(src, iLeft) + index;
+
+ for(int i = iLeft; i <= iRight; i++) {
+ // scan between boundaries
+ // accumulate weighted effect of each neighboring pixel
+ double weight = weightsTable.getWeight(y, i-iLeft);
+ for (unsigned j = 0; j < floatspp; j++) {
+ value[j] += (weight * (double)src_bits[j]);
+ }
+
+ src_bits += src_pitch;
+ }
+
+ // clamp and place result in destination pixel
+ for (unsigned j = 0; j < floatspp; j++) {
+ dst_bits[j] = (float)value[j];
+ }
+
+ dst_bits += dst_pitch;
+ }
+ }
+ }
+ break;
+
+ }
+ }
+}
+
diff --git a/Source/FreeImageToolkit/Resize.h b/Source/FreeImageToolkit/Resize.h
new file mode 100644
index 0000000..2584efd
--- /dev/null
+++ b/Source/FreeImageToolkit/Resize.h
@@ -0,0 +1,145 @@
+// ==========================================================
+// Upsampling / downsampling classes
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Detlev Vendt (detlev.vendt@brillit.de)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef _RESIZE_H_
+#define _RESIZE_H_
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "Filters.h"
+
+/**
+ Filter weights table.<br>
+ This class stores contribution information for an entire line (row or column).
+*/
+class CWeightsTable
+{
+/**
+ Sampled filter weight table.<br>
+ Contribution information for a single pixel
+*/
+typedef struct {
+ /// Normalized weights of neighboring pixels
+ double *Weights;
+ /// Bounds of source pixels window
+ int Left, Right;
+} Contribution;
+
+private:
+ /// Row (or column) of contribution weights
+ Contribution *m_WeightTable;
+ /// Filter window size (of affecting source pixels)
+ DWORD m_WindowSize;
+ /// Length of line (no. of rows / cols)
+ DWORD m_LineLength;
+
+public:
+ /**
+ Constructor<br>
+ Allocate and compute the weights table
+ @param pFilter Filter used for upsampling or downsampling
+ @param uLineSize Length (in pixels) of the destination line buffer
+ @param uSrcSize Length (in pixels) of the source line buffer
+ */
+ CWeightsTable(CGenericFilter *pFilter, DWORD uDstSize, DWORD uSrcSize);
+
+ /**
+ Destructor<br>
+ Destroy the weights table
+ */
+ ~CWeightsTable();
+
+ /** Retrieve a filter weight, given source and destination positions
+ @param dst_pos Pixel position in destination line buffer
+ @param src_pos Pixel position in source line buffer
+ @return Returns the filter weight
+ */
+ double getWeight(int dst_pos, int src_pos) {
+ return m_WeightTable[dst_pos].Weights[src_pos];
+ }
+
+ /** Retrieve left boundary of source line buffer
+ @param dst_pos Pixel position in destination line buffer
+ @return Returns the left boundary of source line buffer
+ */
+ int getLeftBoundary(int dst_pos) {
+ return m_WeightTable[dst_pos].Left;
+ }
+
+ /** Retrieve right boundary of source line buffer
+ @param dst_pos Pixel position in destination line buffer
+ @return Returns the right boundary of source line buffer
+ */
+ int getRightBoundary(int dst_pos) {
+ return m_WeightTable[dst_pos].Right;
+ }
+};
+
+// ---------------------------------------------
+
+/**
+ CResizeEngine<br>
+ This class performs filtered zoom. It scales an image to the desired dimensions with
+ any of the CGenericFilter derived filter class.<br>
+ It works with 8-, 24- and 32-bit buffers.<br><br>
+
+ <b>References</b> : <br>
+ [1] Paul Heckbert, C code to zoom raster images up or down, with nice filtering.
+ UC Berkeley, August 1989. [online] http://www-2.cs.cmu.edu/afs/cs.cmu.edu/Web/People/ph/heckbert.html
+ [2] Eran Yariv, Two Pass Scaling using Filters. The Code Project, December 1999.
+ [online] http://www.codeproject.com/bitmap/2_pass_scaling.asp
+
+*/
+class CResizeEngine
+{
+private:
+ /// Pointer to the FIR / IIR filter
+ CGenericFilter* m_pFilter;
+
+public:
+
+ /// Constructor
+ CResizeEngine(CGenericFilter* filter):m_pFilter(filter) {}
+
+ /// Destructor
+ virtual ~CResizeEngine() {}
+
+ /** Scale an image to the desired dimensions
+ @param src Pointer to the source image
+ @param dst_width Destination image width
+ @param dst_height Destination image height
+ @return Returns the scaled image if successful, returns NULL otherwise
+ */
+ FIBITMAP* scale(FIBITMAP *src, unsigned dst_width, unsigned dst_height);
+
+private:
+
+ /// Performs horizontal image filtering
+ void horizontalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height);
+
+ /// Performs vertical image filtering
+ void verticalFilter(FIBITMAP *src, unsigned src_width, unsigned src_height, FIBITMAP *dst, unsigned dst_width, unsigned dst_height);
+};
+
+
+
+#endif // _RESIZE_H_
diff --git a/Source/LibJPEG/LibJPEG.2003.vcproj b/Source/LibJPEG/LibJPEG.2003.vcproj
new file mode 100644
index 0000000..b071bfd
--- /dev/null
+++ b/Source/LibJPEG/LibJPEG.2003.vcproj
@@ -0,0 +1,306 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="LibJPEG"
+ SccProjectName="&quot;$/FreeImage/LibJPEG&quot;, IHAAAAAA"
+ SccLocalPath=".">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/LibJPEG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibJPEG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/LibJPEG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibJPEG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\jaricom.c">
+ </File>
+ <File
+ RelativePath="jcapimin.c">
+ </File>
+ <File
+ RelativePath="jcapistd.c">
+ </File>
+ <File
+ RelativePath=".\jcarith.c">
+ </File>
+ <File
+ RelativePath="jccoefct.c">
+ </File>
+ <File
+ RelativePath="jccolor.c">
+ </File>
+ <File
+ RelativePath="jcdctmgr.c">
+ </File>
+ <File
+ RelativePath="jchuff.c">
+ </File>
+ <File
+ RelativePath="jcinit.c">
+ </File>
+ <File
+ RelativePath="jcmainct.c">
+ </File>
+ <File
+ RelativePath="jcmarker.c">
+ </File>
+ <File
+ RelativePath="jcmaster.c">
+ </File>
+ <File
+ RelativePath="jcomapi.c">
+ </File>
+ <File
+ RelativePath="jcparam.c">
+ </File>
+ <File
+ RelativePath="jcprepct.c">
+ </File>
+ <File
+ RelativePath="jcsample.c">
+ </File>
+ <File
+ RelativePath="jctrans.c">
+ </File>
+ <File
+ RelativePath="jdapimin.c">
+ </File>
+ <File
+ RelativePath="jdapistd.c">
+ </File>
+ <File
+ RelativePath=".\jdarith.c">
+ </File>
+ <File
+ RelativePath="jdatadst.c">
+ </File>
+ <File
+ RelativePath="jdatasrc.c">
+ </File>
+ <File
+ RelativePath="jdcoefct.c">
+ </File>
+ <File
+ RelativePath="jdcolor.c">
+ </File>
+ <File
+ RelativePath="jddctmgr.c">
+ </File>
+ <File
+ RelativePath="jdhuff.c">
+ </File>
+ <File
+ RelativePath="jdinput.c">
+ </File>
+ <File
+ RelativePath="jdmainct.c">
+ </File>
+ <File
+ RelativePath="jdmarker.c">
+ </File>
+ <File
+ RelativePath="jdmaster.c">
+ </File>
+ <File
+ RelativePath="jdmerge.c">
+ </File>
+ <File
+ RelativePath="jdpostct.c">
+ </File>
+ <File
+ RelativePath="jdsample.c">
+ </File>
+ <File
+ RelativePath="jdtrans.c">
+ </File>
+ <File
+ RelativePath="jerror.c">
+ </File>
+ <File
+ RelativePath="jfdctflt.c">
+ </File>
+ <File
+ RelativePath="jfdctfst.c">
+ </File>
+ <File
+ RelativePath="jfdctint.c">
+ </File>
+ <File
+ RelativePath="jidctflt.c">
+ </File>
+ <File
+ RelativePath="jidctfst.c">
+ </File>
+ <File
+ RelativePath="jidctint.c">
+ </File>
+ <File
+ RelativePath="jmemmgr.c">
+ </File>
+ <File
+ RelativePath="jmemnobs.c">
+ </File>
+ <File
+ RelativePath="jquant1.c">
+ </File>
+ <File
+ RelativePath="jquant2.c">
+ </File>
+ <File
+ RelativePath="jutils.c">
+ </File>
+ <File
+ RelativePath="transupp.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="jconfig.h">
+ </File>
+ <File
+ RelativePath="jdct.h">
+ </File>
+ <File
+ RelativePath="jerror.h">
+ </File>
+ <File
+ RelativePath="jinclude.h">
+ </File>
+ <File
+ RelativePath="jmemsys.h">
+ </File>
+ <File
+ RelativePath="jmorecfg.h">
+ </File>
+ <File
+ RelativePath="jpegint.h">
+ </File>
+ <File
+ RelativePath="jpeglib.h">
+ </File>
+ <File
+ RelativePath="jversion.h">
+ </File>
+ <File
+ RelativePath="transupp.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibJPEG/LibJPEG.2005.vcproj b/Source/LibJPEG/LibJPEG.2005.vcproj
new file mode 100644
index 0000000..a963a73
--- /dev/null
+++ b/Source/LibJPEG/LibJPEG.2005.vcproj
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibJPEG"
+ ProjectGUID="{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+ RootNamespace="LibJPEG"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/LibJPEG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibJPEG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/LibJPEG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibJPEG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\jaricom.c"
+ >
+ </File>
+ <File
+ RelativePath="jcapimin.c"
+ >
+ </File>
+ <File
+ RelativePath="jcapistd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jcarith.c"
+ >
+ </File>
+ <File
+ RelativePath="jccoefct.c"
+ >
+ </File>
+ <File
+ RelativePath="jccolor.c"
+ >
+ </File>
+ <File
+ RelativePath="jcdctmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jchuff.c"
+ >
+ </File>
+ <File
+ RelativePath="jcinit.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmainct.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmarker.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmaster.c"
+ >
+ </File>
+ <File
+ RelativePath="jcomapi.c"
+ >
+ </File>
+ <File
+ RelativePath="jcparam.c"
+ >
+ </File>
+ <File
+ RelativePath="jcprepct.c"
+ >
+ </File>
+ <File
+ RelativePath="jcsample.c"
+ >
+ </File>
+ <File
+ RelativePath="jctrans.c"
+ >
+ </File>
+ <File
+ RelativePath="jdapimin.c"
+ >
+ </File>
+ <File
+ RelativePath="jdapistd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jdarith.c"
+ >
+ </File>
+ <File
+ RelativePath="jdatadst.c"
+ >
+ </File>
+ <File
+ RelativePath="jdatasrc.c"
+ >
+ </File>
+ <File
+ RelativePath="jdcoefct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdcolor.c"
+ >
+ </File>
+ <File
+ RelativePath="jddctmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jdhuff.c"
+ >
+ </File>
+ <File
+ RelativePath="jdinput.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmainct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmarker.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmaster.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmerge.c"
+ >
+ </File>
+ <File
+ RelativePath="jdpostct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdsample.c"
+ >
+ </File>
+ <File
+ RelativePath="jdtrans.c"
+ >
+ </File>
+ <File
+ RelativePath="jerror.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctflt.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctfst.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctint.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctflt.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctfst.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctint.c"
+ >
+ </File>
+ <File
+ RelativePath="jmemmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jmemnobs.c"
+ >
+ </File>
+ <File
+ RelativePath="jquant1.c"
+ >
+ </File>
+ <File
+ RelativePath="jquant2.c"
+ >
+ </File>
+ <File
+ RelativePath="jutils.c"
+ >
+ </File>
+ <File
+ RelativePath="transupp.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="jconfig.h"
+ >
+ </File>
+ <File
+ RelativePath="jdct.h"
+ >
+ </File>
+ <File
+ RelativePath="jerror.h"
+ >
+ </File>
+ <File
+ RelativePath="jinclude.h"
+ >
+ </File>
+ <File
+ RelativePath="jmemsys.h"
+ >
+ </File>
+ <File
+ RelativePath="jmorecfg.h"
+ >
+ </File>
+ <File
+ RelativePath="jpegint.h"
+ >
+ </File>
+ <File
+ RelativePath="jpeglib.h"
+ >
+ </File>
+ <File
+ RelativePath="jversion.h"
+ >
+ </File>
+ <File
+ RelativePath="transupp.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibJPEG/LibJPEG.2008.vcproj b/Source/LibJPEG/LibJPEG.2008.vcproj
new file mode 100644
index 0000000..34de487
--- /dev/null
+++ b/Source/LibJPEG/LibJPEG.2008.vcproj
@@ -0,0 +1,406 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibJPEG"
+ ProjectGUID="{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+ RootNamespace="LibJPEG"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ PrecompiledHeaderFile=".\Debug/LibJPEG.pch"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ PrecompiledHeaderFile=".\Release/LibJPEG.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\jaricom.c"
+ >
+ </File>
+ <File
+ RelativePath="jcapimin.c"
+ >
+ </File>
+ <File
+ RelativePath="jcapistd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jcarith.c"
+ >
+ </File>
+ <File
+ RelativePath="jccoefct.c"
+ >
+ </File>
+ <File
+ RelativePath="jccolor.c"
+ >
+ </File>
+ <File
+ RelativePath="jcdctmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jchuff.c"
+ >
+ </File>
+ <File
+ RelativePath="jcinit.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmainct.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmarker.c"
+ >
+ </File>
+ <File
+ RelativePath="jcmaster.c"
+ >
+ </File>
+ <File
+ RelativePath="jcomapi.c"
+ >
+ </File>
+ <File
+ RelativePath="jcparam.c"
+ >
+ </File>
+ <File
+ RelativePath="jcprepct.c"
+ >
+ </File>
+ <File
+ RelativePath="jcsample.c"
+ >
+ </File>
+ <File
+ RelativePath="jctrans.c"
+ >
+ </File>
+ <File
+ RelativePath="jdapimin.c"
+ >
+ </File>
+ <File
+ RelativePath="jdapistd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\jdarith.c"
+ >
+ </File>
+ <File
+ RelativePath="jdatadst.c"
+ >
+ </File>
+ <File
+ RelativePath="jdatasrc.c"
+ >
+ </File>
+ <File
+ RelativePath="jdcoefct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdcolor.c"
+ >
+ </File>
+ <File
+ RelativePath="jddctmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jdhuff.c"
+ >
+ </File>
+ <File
+ RelativePath="jdinput.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmainct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmarker.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmaster.c"
+ >
+ </File>
+ <File
+ RelativePath="jdmerge.c"
+ >
+ </File>
+ <File
+ RelativePath="jdpostct.c"
+ >
+ </File>
+ <File
+ RelativePath="jdsample.c"
+ >
+ </File>
+ <File
+ RelativePath="jdtrans.c"
+ >
+ </File>
+ <File
+ RelativePath="jerror.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctflt.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctfst.c"
+ >
+ </File>
+ <File
+ RelativePath="jfdctint.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctflt.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctfst.c"
+ >
+ </File>
+ <File
+ RelativePath="jidctint.c"
+ >
+ </File>
+ <File
+ RelativePath="jmemmgr.c"
+ >
+ </File>
+ <File
+ RelativePath="jmemnobs.c"
+ >
+ </File>
+ <File
+ RelativePath="jquant1.c"
+ >
+ </File>
+ <File
+ RelativePath="jquant2.c"
+ >
+ </File>
+ <File
+ RelativePath="jutils.c"
+ >
+ </File>
+ <File
+ RelativePath="transupp.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="jchuff.h"
+ >
+ </File>
+ <File
+ RelativePath="jconfig.h"
+ >
+ </File>
+ <File
+ RelativePath="jdct.h"
+ >
+ </File>
+ <File
+ RelativePath="jdhuff.h"
+ >
+ </File>
+ <File
+ RelativePath="jerror.h"
+ >
+ </File>
+ <File
+ RelativePath="jinclude.h"
+ >
+ </File>
+ <File
+ RelativePath="jmemsys.h"
+ >
+ </File>
+ <File
+ RelativePath="jmorecfg.h"
+ >
+ </File>
+ <File
+ RelativePath="jpegint.h"
+ >
+ </File>
+ <File
+ RelativePath="jpeglib.h"
+ >
+ </File>
+ <File
+ RelativePath="jversion.h"
+ >
+ </File>
+ <File
+ RelativePath="transupp.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibJPEG/README b/Source/LibJPEG/README
new file mode 100644
index 0000000..b504d74
--- /dev/null
+++ b/Source/LibJPEG/README
@@ -0,0 +1,322 @@
+The Independent JPEG Group's JPEG software
+==========================================
+
+README for release 7 of 27-Jun-2009
+===================================
+
+This distribution contains the seventh public release of the Independent JPEG
+Group's free JPEG software. You are welcome to redistribute this software and
+to use it for any purpose, subject to the conditions under LEGAL ISSUES, below.
+
+This software is the work of Tom Lane, Guido Vollbeding, Philip Gladstone,
+Bill Allombert, Jim Boucher, Lee Crocker, Bob Friesenhahn, Ben Jackson,
+Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, Ge' Weijers,
+and other members of the Independent JPEG Group.
+
+IJG is not affiliated with the official ISO JPEG standards committee.
+
+
+DOCUMENTATION ROADMAP
+=====================
+
+This file contains the following sections:
+
+OVERVIEW General description of JPEG and the IJG software.
+LEGAL ISSUES Copyright, lack of warranty, terms of distribution.
+REFERENCES Where to learn more about JPEG.
+ARCHIVE LOCATIONS Where to find newer versions of this software.
+ACKNOWLEDGMENTS Special thanks.
+FILE FORMAT WARS Software *not* to get.
+TO DO Plans for future IJG releases.
+
+Other documentation files in the distribution are:
+
+User documentation:
+ install.txt How to configure and install the IJG software.
+ usage.txt Usage instructions for cjpeg, djpeg, jpegtran,
+ rdjpgcom, and wrjpgcom.
+ *.1 Unix-style man pages for programs (same info as usage.txt).
+ wizard.txt Advanced usage instructions for JPEG wizards only.
+ change.log Version-to-version change highlights.
+Programmer and internal documentation:
+ libjpeg.txt How to use the JPEG library in your own programs.
+ example.c Sample code for calling the JPEG library.
+ structure.txt Overview of the JPEG library's internal structure.
+ filelist.txt Road map of IJG files.
+ coderules.txt Coding style rules --- please read if you contribute code.
+
+Please read at least the files install.txt and usage.txt. Some information
+can also be found in the JPEG FAQ (Frequently Asked Questions) article. See
+ARCHIVE LOCATIONS below to find out where to obtain the FAQ article.
+
+If you want to understand how the JPEG code works, we suggest reading one or
+more of the REFERENCES, then looking at the documentation files (in roughly
+the order listed) before diving into the code.
+
+
+OVERVIEW
+========
+
+This package contains C software to implement JPEG image encoding, decoding,
+and transcoding. JPEG (pronounced "jay-peg") is a standardized compression
+method for full-color and gray-scale images.
+
+This software implements JPEG baseline, extended-sequential, and progressive
+compression processes. Provision is made for supporting all variants of these
+processes, although some uncommon parameter settings aren't implemented yet.
+We have made no provision for supporting the hierarchical or lossless
+processes defined in the standard.
+
+We provide a set of library routines for reading and writing JPEG image files,
+plus two sample applications "cjpeg" and "djpeg", which use the library to
+perform conversion between JPEG and some other popular image file formats.
+The library is intended to be reused in other applications.
+
+In order to support file conversion and viewing software, we have included
+considerable functionality beyond the bare JPEG coding/decoding capability;
+for example, the color quantization modules are not strictly part of JPEG
+decoding, but they are essential for output to colormapped file formats or
+colormapped displays. These extra functions can be compiled out of the
+library if not required for a particular application.
+
+We have also included "jpegtran", a utility for lossless transcoding between
+different JPEG processes, and "rdjpgcom" and "wrjpgcom", two simple
+applications for inserting and extracting textual comments in JFIF files.
+
+The emphasis in designing this software has been on achieving portability and
+flexibility, while also making it fast enough to be useful. In particular,
+the software is not intended to be read as a tutorial on JPEG. (See the
+REFERENCES section for introductory material.) Rather, it is intended to
+be reliable, portable, industrial-strength code. We do not claim to have
+achieved that goal in every aspect of the software, but we strive for it.
+
+We welcome the use of this software as a component of commercial products.
+No royalty is required, but we do ask for an acknowledgement in product
+documentation, as described under LEGAL ISSUES.
+
+
+LEGAL ISSUES
+============
+
+In plain English:
+
+1. We don't promise that this software works. (But if you find any bugs,
+ please let us know!)
+2. You can use this software for whatever you want. You don't have to pay us.
+3. You may not pretend that you wrote this software. If you use it in a
+ program, you must acknowledge somewhere in your documentation that
+ you've used the IJG code.
+
+In legalese:
+
+The authors make NO WARRANTY or representation, either express or implied,
+with respect to this software, its quality, accuracy, merchantability, or
+fitness for a particular purpose. This software is provided "AS IS", and you,
+its user, assume the entire risk as to its quality and accuracy.
+
+This software is copyright (C) 1991-2009, Thomas G. Lane, Guido Vollbeding.
+All Rights Reserved except as specified below.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+software (or portions thereof) for any purpose, without fee, subject to these
+conditions:
+(1) If any part of the source code for this software is distributed, then this
+README file must be included, with this copyright and no-warranty notice
+unaltered; and any additions, deletions, or changes to the original files
+must be clearly indicated in accompanying documentation.
+(2) If only executable code is distributed, then the accompanying
+documentation must state that "this software is based in part on the work of
+the Independent JPEG Group".
+(3) Permission for use of this software is granted only if the user accepts
+full responsibility for any undesirable consequences; the authors accept
+NO LIABILITY for damages of any kind.
+
+These conditions apply to any software derived from or based on the IJG code,
+not just to the unmodified library. If you use our work, you ought to
+acknowledge us.
+
+Permission is NOT granted for the use of any IJG author's name or company name
+in advertising or publicity relating to this software or products derived from
+it. This software may be referred to only as "the Independent JPEG Group's
+software".
+
+We specifically permit and encourage the use of this software as the basis of
+commercial products, provided that all warranty or liability claims are
+assumed by the product vendor.
+
+
+ansi2knr.c is included in this distribution by permission of L. Peter Deutsch,
+sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA.
+ansi2knr.c is NOT covered by the above copyright and conditions, but instead
+by the usual distribution terms of the Free Software Foundation; principally,
+that you must include source code if you redistribute it. (See the file
+ansi2knr.c for full details.) However, since ansi2knr.c is not needed as part
+of any program generated from the IJG code, this does not limit you more than
+the foregoing paragraphs do.
+
+The Unix configuration script "configure" was produced with GNU Autoconf.
+It is copyright by the Free Software Foundation but is freely distributable.
+The same holds for its supporting scripts (config.guess, config.sub,
+ltmain.sh). Another support script, install-sh, is copyright by X Consortium
+but is also freely distributable.
+
+The IJG distribution formerly included code to read and write GIF files.
+To avoid entanglement with the Unisys LZW patent, GIF reading support has
+been removed altogether, and the GIF writer has been simplified to produce
+"uncompressed GIFs". This technique does not use the LZW algorithm; the
+resulting GIF files are larger than usual, but are readable by all standard
+GIF decoders.
+
+We are required to state that
+ "The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated."
+
+
+REFERENCES
+==========
+
+We recommend reading one or more of these references before trying to
+understand the innards of the JPEG software.
+
+The best short technical introduction to the JPEG compression algorithm is
+ Wallace, Gregory K. "The JPEG Still Picture Compression Standard",
+ Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44.
+(Adjacent articles in that issue discuss MPEG motion picture compression,
+applications of JPEG, and related topics.) If you don't have the CACM issue
+handy, a PostScript file containing a revised version of Wallace's article is
+available at http://www.ijg.org/files/wallace.ps.gz. The file (actually
+a preprint for an article that appeared in IEEE Trans. Consumer Electronics)
+omits the sample images that appeared in CACM, but it includes corrections
+and some added material. Note: the Wallace article is copyright ACM and IEEE,
+and it may not be used for commercial purposes.
+
+A somewhat less technical, more leisurely introduction to JPEG can be found in
+"The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by
+M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1. This book provides
+good explanations and example C code for a multitude of compression methods
+including JPEG. It is an excellent source if you are comfortable reading C
+code but don't know much about data compression in general. The book's JPEG
+sample code is far from industrial-strength, but when you are ready to look
+at a full implementation, you've got one here...
+
+The best currently available description of JPEG is the textbook "JPEG Still
+Image Data Compression Standard" by William B. Pennebaker and Joan L.
+Mitchell, published by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.
+Price US$59.95, 638 pp. The book includes the complete text of the ISO JPEG
+standards (DIS 10918-1 and draft DIS 10918-2).
+Although this is by far the most detailed and comprehensive exposition of
+JPEG publicly available, we point out that it is still missing an explanation
+of the most essential properties and algorithms of the underlying DCT
+technology.
+If you think that you know about DCT-based JPEG after reading this book,
+then you are in delusion. The real fundamentals and corresponding potential
+of DCT-based JPEG are not publicly known so far, and that is the reason for
+all the mistaken developments taking place in the image coding domain.
+
+The original JPEG standard is divided into two parts, Part 1 being the actual
+specification, while Part 2 covers compliance testing methods. Part 1 is
+titled "Digital Compression and Coding of Continuous-tone Still Images,
+Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS
+10918-1, ITU-T T.81. Part 2 is titled "Digital Compression and Coding of
+Continuous-tone Still Images, Part 2: Compliance testing" and has document
+numbers ISO/IEC IS 10918-2, ITU-T T.83.
+
+The JPEG standard does not specify all details of an interchangeable file
+format. For the omitted details we follow the "JFIF" conventions, revision
+1.02. A copy of the JFIF spec is available from:
+ Literature Department
+ C-Cube Microsystems, Inc.
+ 1778 McCarthy Blvd.
+ Milpitas, CA 95035
+ phone (408) 944-6300, fax (408) 944-6314
+A PostScript version of this document is available at
+http://www.ijg.org/files/jfif.ps.gz. There is also a plain text version at
+http://www.ijg.org/files/jfif.txt.gz, but it is missing the figures.
+
+The TIFF 6.0 file format specification can be obtained by FTP from
+ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz. The JPEG incorporation scheme
+found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems.
+IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6).
+Instead, we recommend the JPEG design proposed by TIFF Technical Note #2
+(Compression tag 7). Copies of this Note can be obtained from
+http://www.ijg.org/files/. It is expected that the next revision
+of the TIFF spec will replace the 6.0 JPEG design with the Note's design.
+Although IJG's own code does not support TIFF/JPEG, the free libtiff library
+uses our library to implement TIFF/JPEG per the Note.
+
+
+ARCHIVE LOCATIONS
+=================
+
+The "official" archive site for this software is www.ijg.org.
+The most recent released version can always be found there in
+directory "files". This particular version will be archived as
+http://www.ijg.org/files/jpegsrc.v7.tar.gz, and in Windows-compatible
+"zip" archive format as http://www.ijg.org/files/jpegsr7.zip.
+
+The JPEG FAQ (Frequently Asked Questions) article is a source of some
+general information about JPEG.
+It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/
+and other news.answers archive sites, including the official news.answers
+archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/.
+If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu
+with body
+ send usenet/news.answers/jpeg-faq/part1
+ send usenet/news.answers/jpeg-faq/part2
+
+
+ACKNOWLEDGMENTS
+===============
+
+Thank to Juergen Bruder of the Georg-Cantor-Organization at the
+Martin-Luther-University Halle for providing me with a copy of the common
+DCT algorithm article, only to find out that I had come to the same result
+in a more direct and comprehensible way with a more generative approach.
+
+Thank to Istvan Sebestyen and Joan L. Mitchell for inviting me to the
+ITU JPEG (Study Group 16) meeting in Geneva, Switzerland.
+
+Thank to Thomas Wiegand and Gary Sullivan for inviting me to the
+Joint Video Team (MPEG & ITU) meeting in Geneva, Switzerland.
+
+Thank to John Korejwa and Massimo Ballerini for inviting me to
+fruitful consultations in Boston, MA and Milan, Italy.
+
+Thank to Hendrik Elstner, Roland Fassauer, and Simone Zuck for
+corresponding business development.
+
+Thank to Nico Zschach and Dirk Stelling of the technical support team
+at the Digital Images company in Halle for providing me with extra
+equipment for configuration tests.
+
+Thank to Richard F. Lyon (then of Foveon Inc.) for fruitful
+communication about JPEG configuration in Sigma Photo Pro software.
+
+Last but not least special thank to Thomas G. Lane for the original
+design and development of this singular software package.
+
+
+FILE FORMAT WARS
+================
+
+The ISO JPEG standards committee actually promotes different formats like
+JPEG-2000 or JPEG-XR which are incompatible with original DCT-based JPEG
+and which are based on faulty technologies. IJG therefore does not and
+will not support such momentary mistakes (see REFERENCES).
+We have little or no sympathy for the promotion of these formats. Indeed,
+one of the original reasons for developing this free software was to help
+force convergence on common, interoperable format standards for JPEG files.
+Don't use an incompatible file format!
+(In any case, our decoder will remain capable of reading existing JPEG
+image files indefinitely.)
+
+
+TO DO
+=====
+
+v7 is basically just a necessary interim release, paving the way for a
+major breakthrough in image coding technology with the next v8 package
+which is scheduled for release in the year 2010.
+
+Please send bug reports, offers of help, etc. to jpeg-info@jpegclub.org.
diff --git a/Source/LibJPEG/ansi2knr.c b/Source/LibJPEG/ansi2knr.c
new file mode 100644
index 0000000..7b7882b
--- /dev/null
+++ b/Source/LibJPEG/ansi2knr.c
@@ -0,0 +1,739 @@
+/* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. */
+
+/*$Id: ansi2knr.c,v 1.2 2009/08/15 16:20:11 drolon Exp $*/
+/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
+
+/*
+ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone for the
+consequences of using it or for whether it serves any particular purpose or
+works at all, unless he says so in writing. Refer to the GNU General Public
+License (the "GPL") for full details.
+
+Everyone is granted permission to copy, modify and redistribute ansi2knr,
+but only under the conditions described in the GPL. A copy of this license
+is supposed to have been given to you along with ansi2knr so you can know
+your rights and responsibilities. It should be in a file named COPYLEFT,
+or, if there is no file named COPYLEFT, a file named COPYING. Among other
+things, the copyright notice and this notice must be preserved on all
+copies.
+
+We explicitly state here what we believe is already implied by the GPL: if
+the ansi2knr program is distributed as a separate set of sources and a
+separate executable file which are aggregated on a storage medium together
+with another program, this in itself does not bring the other program under
+the GPL, nor does the mere fact that such a program or the procedures for
+constructing it invoke the ansi2knr executable bring any other part of the
+program under the GPL.
+*/
+
+/*
+ * Usage:
+ ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]
+ * --filename provides the file name for the #line directive in the output,
+ * overriding input_file (if present).
+ * If no input_file is supplied, input is read from stdin.
+ * If no output_file is supplied, output goes to stdout.
+ * There are no error messages.
+ *
+ * ansi2knr recognizes function definitions by seeing a non-keyword
+ * identifier at the left margin, followed by a left parenthesis, with a
+ * right parenthesis as the last character on the line, and with a left
+ * brace as the first token on the following line (ignoring possible
+ * intervening comments and/or preprocessor directives), except that a line
+ * consisting of only
+ * identifier1(identifier2)
+ * will not be considered a function definition unless identifier2 is
+ * the word "void", and a line consisting of
+ * identifier1(identifier2, <<arbitrary>>)
+ * will not be considered a function definition.
+ * ansi2knr will recognize a multi-line header provided that no intervening
+ * line ends with a left or right brace or a semicolon. These algorithms
+ * ignore whitespace, comments, and preprocessor directives, except that
+ * the function name must be the first thing on the line. The following
+ * constructs will confuse it:
+ * - Any other construct that starts at the left margin and
+ * follows the above syntax (such as a macro or function call).
+ * - Some macros that tinker with the syntax of function headers.
+ */
+
+/*
+ * The original and principal author of ansi2knr is L. Peter Deutsch
+ * <ghost@aladdin.com>. Other authors are noted in the change history
+ * that follows (in reverse chronological order):
+
+ lpd 2000-04-12 backs out Eggert's changes because of bugs:
+ - concatlits didn't declare the type of its bufend argument;
+ - concatlits didn't recognize when it was inside a comment;
+ - scanstring could scan backward past the beginning of the string; when
+ - the check for \ + newline in scanstring was unnecessary.
+
+ 2000-03-05 Paul Eggert <eggert@twinsun.com>
+
+ Add support for concatenated string literals.
+ * ansi2knr.c (concatlits): New decl.
+ (main): Invoke concatlits to concatenate string literals.
+ (scanstring): Handle backslash-newline correctly. Work with
+ character constants. Fix bug when scanning backwards through
+ backslash-quote. Check for unterminated strings.
+ (convert1): Parse character constants, too.
+ (appendline, concatlits): New functions.
+ * ansi2knr.1: Document this.
+
+ lpd 1999-08-17 added code to allow preprocessor directives
+ wherever comments are allowed
+ lpd 1999-04-12 added minor fixes from Pavel Roskin
+ <pavel_roskin@geocities.com> for clean compilation with
+ gcc -W -Wall
+ lpd 1999-03-22 added hack to recognize lines consisting of
+ identifier1(identifier2, xxx) as *not* being procedures
+ lpd 1999-02-03 made indentation of preprocessor commands consistent
+ lpd 1999-01-28 fixed two bugs: a '/' in an argument list caused an
+ endless loop; quoted strings within an argument list
+ confused the parser
+ lpd 1999-01-24 added a check for write errors on the output,
+ suggested by Jim Meyering <meyering@ascend.com>
+ lpd 1998-11-09 added further hack to recognize identifier(void)
+ as being a procedure
+ lpd 1998-10-23 added hack to recognize lines consisting of
+ identifier1(identifier2) as *not* being procedures
+ lpd 1997-12-08 made input_file optional; only closes input and/or
+ output file if not stdin or stdout respectively; prints
+ usage message on stderr rather than stdout; adds
+ --filename switch (changes suggested by
+ <ceder@lysator.liu.se>)
+ lpd 1996-01-21 added code to cope with not HAVE_CONFIG_H and with
+ compilers that don't understand void, as suggested by
+ Tom Lane
+ lpd 1996-01-15 changed to require that the first non-comment token
+ on the line following a function header be a left brace,
+ to reduce sensitivity to macros, as suggested by Tom Lane
+ <tgl@sss.pgh.pa.us>
+ lpd 1995-06-22 removed #ifndefs whose sole purpose was to define
+ undefined preprocessor symbols as 0; changed all #ifdefs
+ for configuration symbols to #ifs
+ lpd 1995-04-05 changed copyright notice to make it clear that
+ including ansi2knr in a program does not bring the entire
+ program under the GPL
+ lpd 1994-12-18 added conditionals for systems where ctype macros
+ don't handle 8-bit characters properly, suggested by
+ Francois Pinard <pinard@iro.umontreal.ca>;
+ removed --varargs switch (this is now the default)
+ lpd 1994-10-10 removed CONFIG_BROKETS conditional
+ lpd 1994-07-16 added some conditionals to help GNU `configure',
+ suggested by Francois Pinard <pinard@iro.umontreal.ca>;
+ properly erase prototype args in function parameters,
+ contributed by Jim Avera <jima@netcom.com>;
+ correct error in writeblanks (it shouldn't erase EOLs)
+ lpd 1989-xx-xx original version
+ */
+
+/* Most of the conditionals here are to make ansi2knr work with */
+/* or without the GNU configure machinery. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if HAVE_CONFIG_H
+
+/*
+ For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
+ This will define HAVE_CONFIG_H and so, activate the following lines.
+ */
+
+# if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+#else /* not HAVE_CONFIG_H */
+
+/* Otherwise do it the hard way */
+
+# ifdef BSD
+# include <strings.h>
+# else
+# ifdef VMS
+ extern int strlen(), strncmp();
+# else
+# include <string.h>
+# endif
+# endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+/*
+ malloc and free should be declared in stdlib.h,
+ but if you've got a K&R compiler, they probably aren't.
+ */
+# ifdef MSDOS
+# include <malloc.h>
+# else
+# ifdef VMS
+ extern char *malloc();
+ extern void free();
+# else
+ extern char *malloc();
+ extern int free();
+# endif
+# endif
+
+#endif
+
+/* Define NULL (for *very* old compilers). */
+#ifndef NULL
+# define NULL (0)
+#endif
+
+/*
+ * The ctype macros don't always handle 8-bit characters correctly.
+ * Compensate for this here.
+ */
+#ifdef isascii
+# undef HAVE_ISASCII /* just in case */
+# define HAVE_ISASCII 1
+#else
+#endif
+#if STDC_HEADERS || !HAVE_ISASCII
+# define is_ascii(c) 1
+#else
+# define is_ascii(c) isascii(c)
+#endif
+
+#define is_space(c) (is_ascii(c) && isspace(c))
+#define is_alpha(c) (is_ascii(c) && isalpha(c))
+#define is_alnum(c) (is_ascii(c) && isalnum(c))
+
+/* Scanning macros */
+#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
+#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
+
+/* Forward references */
+char *ppdirforward();
+char *ppdirbackward();
+char *skipspace();
+char *scanstring();
+int writeblanks();
+int test1();
+int convert1();
+
+/* The main program */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{ FILE *in = stdin;
+ FILE *out = stdout;
+ char *filename = 0;
+ char *program_name = argv[0];
+ char *output_name = 0;
+#define bufsize 5000 /* arbitrary size */
+ char *buf;
+ char *line;
+ char *more;
+ char *usage =
+ "Usage: ansi2knr [--filename FILENAME] [INPUT_FILE [OUTPUT_FILE]]\n";
+ /*
+ * In previous versions, ansi2knr recognized a --varargs switch.
+ * If this switch was supplied, ansi2knr would attempt to convert
+ * a ... argument to va_alist and va_dcl; if this switch was not
+ * supplied, ansi2knr would simply drop any such arguments.
+ * Now, ansi2knr always does this conversion, and we only
+ * check for this switch for backward compatibility.
+ */
+ int convert_varargs = 1;
+ int output_error;
+
+ while ( argc > 1 && argv[1][0] == '-' ) {
+ if ( !strcmp(argv[1], "--varargs") ) {
+ convert_varargs = 1;
+ argc--;
+ argv++;
+ continue;
+ }
+ if ( !strcmp(argv[1], "--filename") && argc > 2 ) {
+ filename = argv[2];
+ argc -= 2;
+ argv += 2;
+ continue;
+ }
+ fprintf(stderr, "%s: Unrecognized switch: %s\n", program_name,
+ argv[1]);
+ fprintf(stderr, usage);
+ exit(1);
+ }
+ switch ( argc )
+ {
+ default:
+ fprintf(stderr, usage);
+ exit(0);
+ case 3:
+ output_name = argv[2];
+ out = fopen(output_name, "w");
+ if ( out == NULL ) {
+ fprintf(stderr, "%s: Cannot open output file %s\n",
+ program_name, output_name);
+ exit(1);
+ }
+ /* falls through */
+ case 2:
+ in = fopen(argv[1], "r");
+ if ( in == NULL ) {
+ fprintf(stderr, "%s: Cannot open input file %s\n",
+ program_name, argv[1]);
+ exit(1);
+ }
+ if ( filename == 0 )
+ filename = argv[1];
+ /* falls through */
+ case 1:
+ break;
+ }
+ if ( filename )
+ fprintf(out, "#line 1 \"%s\"\n", filename);
+ buf = malloc(bufsize);
+ if ( buf == NULL )
+ {
+ fprintf(stderr, "Unable to allocate read buffer!\n");
+ exit(1);
+ }
+ line = buf;
+ while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
+ {
+test: line += strlen(line);
+ switch ( test1(buf) )
+ {
+ case 2: /* a function header */
+ convert1(buf, out, 1, convert_varargs);
+ break;
+ case 1: /* a function */
+ /* Check for a { at the start of the next line. */
+ more = ++line;
+f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
+ goto wl;
+ if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
+ goto wl;
+ switch ( *skipspace(ppdirforward(more), 1) )
+ {
+ case '{':
+ /* Definitely a function header. */
+ convert1(buf, out, 0, convert_varargs);
+ fputs(more, out);
+ break;
+ case 0:
+ /* The next line was blank or a comment: */
+ /* keep scanning for a non-comment. */
+ line += strlen(line);
+ goto f;
+ default:
+ /* buf isn't a function header, but */
+ /* more might be. */
+ fputs(buf, out);
+ strcpy(buf, more);
+ line = buf;
+ goto test;
+ }
+ break;
+ case -1: /* maybe the start of a function */
+ if ( line != buf + (bufsize - 1) ) /* overflow check */
+ continue;
+ /* falls through */
+ default: /* not a function */
+wl: fputs(buf, out);
+ break;
+ }
+ line = buf;
+ }
+ if ( line != buf )
+ fputs(buf, out);
+ free(buf);
+ if ( output_name ) {
+ output_error = ferror(out);
+ output_error |= fclose(out);
+ } else { /* out == stdout */
+ fflush(out);
+ output_error = ferror(out);
+ }
+ if ( output_error ) {
+ fprintf(stderr, "%s: error writing to %s\n", program_name,
+ (output_name ? output_name : "stdout"));
+ exit(1);
+ }
+ if ( in != stdin )
+ fclose(in);
+ return 0;
+}
+
+/*
+ * Skip forward or backward over one or more preprocessor directives.
+ */
+char *
+ppdirforward(p)
+ char *p;
+{
+ for (; *p == '#'; ++p) {
+ for (; *p != '\r' && *p != '\n'; ++p)
+ if (*p == 0)
+ return p;
+ if (*p == '\r' && p[1] == '\n')
+ ++p;
+ }
+ return p;
+}
+char *
+ppdirbackward(p, limit)
+ char *p;
+ char *limit;
+{
+ char *np = p;
+
+ for (;; p = --np) {
+ if (*np == '\n' && np[-1] == '\r')
+ --np;
+ for (; np > limit && np[-1] != '\r' && np[-1] != '\n'; --np)
+ if (np[-1] == 0)
+ return np;
+ if (*np != '#')
+ return p;
+ }
+}
+
+/*
+ * Skip over whitespace, comments, and preprocessor directives,
+ * in either direction.
+ */
+char *
+skipspace(p, dir)
+ char *p;
+ int dir; /* 1 for forward, -1 for backward */
+{
+ for ( ; ; ) {
+ while ( is_space(*p) )
+ p += dir;
+ if ( !(*p == '/' && p[dir] == '*') )
+ break;
+ p += dir; p += dir;
+ while ( !(*p == '*' && p[dir] == '/') ) {
+ if ( *p == 0 )
+ return p; /* multi-line comment?? */
+ p += dir;
+ }
+ p += dir; p += dir;
+ }
+ return p;
+}
+
+/* Scan over a quoted string, in either direction. */
+char *
+scanstring(p, dir)
+ char *p;
+ int dir;
+{
+ for (p += dir; ; p += dir)
+ if (*p == '"' && p[-dir] != '\\')
+ return p + dir;
+}
+
+/*
+ * Write blanks over part of a string.
+ * Don't overwrite end-of-line characters.
+ */
+int
+writeblanks(start, end)
+ char *start;
+ char *end;
+{ char *p;
+ for ( p = start; p < end; p++ )
+ if ( *p != '\r' && *p != '\n' )
+ *p = ' ';
+ return 0;
+}
+
+/*
+ * Test whether the string in buf is a function definition.
+ * The string may contain and/or end with a newline.
+ * Return as follows:
+ * 0 - definitely not a function definition;
+ * 1 - definitely a function definition;
+ * 2 - definitely a function prototype (NOT USED);
+ * -1 - may be the beginning of a function definition,
+ * append another line and look again.
+ * The reason we don't attempt to convert function prototypes is that
+ * Ghostscript's declaration-generating macros look too much like
+ * prototypes, and confuse the algorithms.
+ */
+int
+test1(buf)
+ char *buf;
+{ char *p = buf;
+ char *bend;
+ char *endfn;
+ int contin;
+
+ if ( !isidfirstchar(*p) )
+ return 0; /* no name at left margin */
+ bend = skipspace(ppdirbackward(buf + strlen(buf) - 1, buf), -1);
+ switch ( *bend )
+ {
+ case ';': contin = 0 /*2*/; break;
+ case ')': contin = 1; break;
+ case '{': return 0; /* not a function */
+ case '}': return 0; /* not a function */
+ default: contin = -1;
+ }
+ while ( isidchar(*p) )
+ p++;
+ endfn = p;
+ p = skipspace(p, 1);
+ if ( *p++ != '(' )
+ return 0; /* not a function */
+ p = skipspace(p, 1);
+ if ( *p == ')' )
+ return 0; /* no parameters */
+ /* Check that the apparent function name isn't a keyword. */
+ /* We only need to check for keywords that could be followed */
+ /* by a left parenthesis (which, unfortunately, is most of them). */
+ { static char *words[] =
+ { "asm", "auto", "case", "char", "const", "double",
+ "extern", "float", "for", "if", "int", "long",
+ "register", "return", "short", "signed", "sizeof",
+ "static", "switch", "typedef", "unsigned",
+ "void", "volatile", "while", 0
+ };
+ char **key = words;
+ char *kp;
+ unsigned len = endfn - buf;
+
+ while ( (kp = *key) != 0 )
+ { if ( strlen(kp) == len && !strncmp(kp, buf, len) )
+ return 0; /* name is a keyword */
+ key++;
+ }
+ }
+ {
+ char *id = p;
+ int len;
+ /*
+ * Check for identifier1(identifier2) and not
+ * identifier1(void), or identifier1(identifier2, xxxx).
+ */
+
+ while ( isidchar(*p) )
+ p++;
+ len = p - id;
+ p = skipspace(p, 1);
+ if (*p == ',' ||
+ (*p == ')' && (len != 4 || strncmp(id, "void", 4)))
+ )
+ return 0; /* not a function */
+ }
+ /*
+ * If the last significant character was a ), we need to count
+ * parentheses, because it might be part of a formal parameter
+ * that is a procedure.
+ */
+ if (contin > 0) {
+ int level = 0;
+
+ for (p = skipspace(buf, 1); *p; p = skipspace(p + 1, 1))
+ level += (*p == '(' ? 1 : *p == ')' ? -1 : 0);
+ if (level > 0)
+ contin = -1;
+ }
+ return contin;
+}
+
+/* Convert a recognized function definition or header to K&R syntax. */
+int
+convert1(buf, out, header, convert_varargs)
+ char *buf;
+ FILE *out;
+ int header; /* Boolean */
+ int convert_varargs; /* Boolean */
+{ char *endfn;
+ char *p;
+ /*
+ * The breaks table contains pointers to the beginning and end
+ * of each argument.
+ */
+ char **breaks;
+ unsigned num_breaks = 2; /* for testing */
+ char **btop;
+ char **bp;
+ char **ap;
+ char *vararg = 0;
+
+ /* Pre-ANSI implementations don't agree on whether strchr */
+ /* is called strchr or index, so we open-code it here. */
+ for ( endfn = buf; *(endfn++) != '('; )
+ ;
+top: p = endfn;
+ breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
+ if ( breaks == NULL )
+ { /* Couldn't allocate break table, give up */
+ fprintf(stderr, "Unable to allocate break table!\n");
+ fputs(buf, out);
+ return -1;
+ }
+ btop = breaks + num_breaks * 2 - 2;
+ bp = breaks;
+ /* Parse the argument list */
+ do
+ { int level = 0;
+ char *lp = NULL;
+ char *rp = NULL;
+ char *end = NULL;
+
+ if ( bp >= btop )
+ { /* Filled up break table. */
+ /* Allocate a bigger one and start over. */
+ free((char *)breaks);
+ num_breaks <<= 1;
+ goto top;
+ }
+ *bp++ = p;
+ /* Find the end of the argument */
+ for ( ; end == NULL; p++ )
+ { switch(*p)
+ {
+ case ',':
+ if ( !level ) end = p;
+ break;
+ case '(':
+ if ( !level ) lp = p;
+ level++;
+ break;
+ case ')':
+ if ( --level < 0 ) end = p;
+ else rp = p;
+ break;
+ case '/':
+ if (p[1] == '*')
+ p = skipspace(p, 1) - 1;
+ break;
+ case '"':
+ p = scanstring(p, 1) - 1;
+ break;
+ default:
+ ;
+ }
+ }
+ /* Erase any embedded prototype parameters. */
+ if ( lp && rp )
+ writeblanks(lp + 1, rp);
+ p--; /* back up over terminator */
+ /* Find the name being declared. */
+ /* This is complicated because of procedure and */
+ /* array modifiers. */
+ for ( ; ; )
+ { p = skipspace(p - 1, -1);
+ switch ( *p )
+ {
+ case ']': /* skip array dimension(s) */
+ case ')': /* skip procedure args OR name */
+ { int level = 1;
+ while ( level )
+ switch ( *--p )
+ {
+ case ']': case ')':
+ level++;
+ break;
+ case '[': case '(':
+ level--;
+ break;
+ case '/':
+ if (p > buf && p[-1] == '*')
+ p = skipspace(p, -1) + 1;
+ break;
+ case '"':
+ p = scanstring(p, -1) + 1;
+ break;
+ default: ;
+ }
+ }
+ if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
+ { /* We found the name being declared */
+ while ( !isidfirstchar(*p) )
+ p = skipspace(p, 1) + 1;
+ goto found;
+ }
+ break;
+ default:
+ goto found;
+ }
+ }
+found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
+ { if ( convert_varargs )
+ { *bp++ = "va_alist";
+ vararg = p-2;
+ }
+ else
+ { p++;
+ if ( bp == breaks + 1 ) /* sole argument */
+ writeblanks(breaks[0], p);
+ else
+ writeblanks(bp[-1] - 1, p);
+ bp--;
+ }
+ }
+ else
+ { while ( isidchar(*p) ) p--;
+ *bp++ = p+1;
+ }
+ p = end;
+ }
+ while ( *p++ == ',' );
+ *bp = p;
+ /* Make a special check for 'void' arglist */
+ if ( bp == breaks+2 )
+ { p = skipspace(breaks[0], 1);
+ if ( !strncmp(p, "void", 4) )
+ { p = skipspace(p+4, 1);
+ if ( p == breaks[2] - 1 )
+ { bp = breaks; /* yup, pretend arglist is empty */
+ writeblanks(breaks[0], p + 1);
+ }
+ }
+ }
+ /* Put out the function name and left parenthesis. */
+ p = buf;
+ while ( p != endfn ) putc(*p, out), p++;
+ /* Put out the declaration. */
+ if ( header )
+ { fputs(");", out);
+ for ( p = breaks[0]; *p; p++ )
+ if ( *p == '\r' || *p == '\n' )
+ putc(*p, out);
+ }
+ else
+ { for ( ap = breaks+1; ap < bp; ap += 2 )
+ { p = *ap;
+ while ( isidchar(*p) )
+ putc(*p, out), p++;
+ if ( ap < bp - 1 )
+ fputs(", ", out);
+ }
+ fputs(") ", out);
+ /* Put out the argument declarations */
+ for ( ap = breaks+2; ap <= bp; ap += 2 )
+ (*ap)[-1] = ';';
+ if ( vararg != 0 )
+ { *vararg = 0;
+ fputs(breaks[0], out); /* any prior args */
+ fputs("va_dcl", out); /* the final arg */
+ fputs(bp[0], out);
+ }
+ else
+ fputs(breaks[0], out);
+ }
+ free((char *)breaks);
+ return 0;
+}
diff --git a/Source/LibJPEG/cderror.h b/Source/LibJPEG/cderror.h
new file mode 100644
index 0000000..70435e1
--- /dev/null
+++ b/Source/LibJPEG/cderror.h
@@ -0,0 +1,132 @@
+/*
+ * cderror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the cjpeg/djpeg
+ * applications. These strings are not needed as part of the JPEG library
+ * proper.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef CDERROR_H
+#define CDERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* CDERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */
+
+#ifdef BMP_SUPPORTED
+JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format")
+JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported")
+JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length")
+JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1")
+JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB")
+JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported")
+JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM")
+JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image")
+JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image")
+JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image")
+JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image")
+#endif /* BMP_SUPPORTED */
+
+#ifdef GIF_SUPPORTED
+JMESSAGE(JERR_GIF_BUG, "GIF output got confused")
+JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d")
+JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB")
+JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file")
+JMESSAGE(JERR_GIF_NOT, "Not a GIF file")
+JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image")
+JMESSAGE(JTRC_GIF_BADVERSION,
+ "Warning: unexpected GIF version number '%c%c%c'")
+JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x")
+JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input")
+JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file")
+JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring")
+JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image")
+JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits")
+#endif /* GIF_SUPPORTED */
+
+#ifdef PPM_SUPPORTED
+JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB")
+JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file")
+JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file")
+JMESSAGE(JTRC_PGM, "%ux%u PGM image")
+JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image")
+JMESSAGE(JTRC_PPM, "%ux%u PPM image")
+JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image")
+#endif /* PPM_SUPPORTED */
+
+#ifdef RLE_SUPPORTED
+JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library")
+JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB")
+JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE")
+JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file")
+JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header")
+JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header")
+JMESSAGE(JERR_RLE_NOT, "Not an RLE file")
+JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE")
+JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup")
+JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file")
+JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file")
+JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d")
+JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d")
+#endif /* RLE_SUPPORTED */
+
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format")
+JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file")
+JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB")
+JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image")
+JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image")
+JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image")
+#else
+JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled")
+#endif /* TARGA_SUPPORTED */
+
+JMESSAGE(JERR_BAD_CMAP_FILE,
+ "Color map file is invalid or of unsupported format")
+JMESSAGE(JERR_TOO_MANY_COLORS,
+ "Output file format cannot handle %d colormap entries")
+JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed")
+#ifdef TARGA_SUPPORTED
+JMESSAGE(JERR_UNKNOWN_FORMAT,
+ "Unrecognized input file format --- perhaps you need -targa")
+#else
+JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format")
+#endif
+JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTADDONCODE
+} ADDON_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
diff --git a/Source/LibJPEG/cdjpeg.c b/Source/LibJPEG/cdjpeg.c
new file mode 100644
index 0000000..b6250ff
--- /dev/null
+++ b/Source/LibJPEG/cdjpeg.c
@@ -0,0 +1,181 @@
+/*
+ * cdjpeg.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains common support routines used by the IJG application
+ * programs (cjpeg, djpeg, jpegtran).
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include <ctype.h> /* to declare isupper(), tolower() */
+#ifdef NEED_SIGNAL_CATCHER
+#include <signal.h> /* to declare signal() */
+#endif
+#ifdef USE_SETMODE
+#include <fcntl.h> /* to declare setmode()'s parameter macros */
+/* If you have setmode() but not <io.h>, just delete this line: */
+#include <io.h> /* to declare setmode() */
+#endif
+
+
+/*
+ * Signal catcher to ensure that temporary files are removed before aborting.
+ * NB: for Amiga Manx C this is actually a global routine named _abort();
+ * we put "#define signal_catcher _abort" in jconfig.h. Talk about bogus...
+ */
+
+#ifdef NEED_SIGNAL_CATCHER
+
+static j_common_ptr sig_cinfo;
+
+void /* must be global for Manx C */
+signal_catcher (int signum)
+{
+ if (sig_cinfo != NULL) {
+ if (sig_cinfo->err != NULL) /* turn off trace output */
+ sig_cinfo->err->trace_level = 0;
+ jpeg_destroy(sig_cinfo); /* clean up memory allocation & temp files */
+ }
+ exit(EXIT_FAILURE);
+}
+
+
+GLOBAL(void)
+enable_signal_catcher (j_common_ptr cinfo)
+{
+ sig_cinfo = cinfo;
+#ifdef SIGINT /* not all systems have SIGINT */
+ signal(SIGINT, signal_catcher);
+#endif
+#ifdef SIGTERM /* not all systems have SIGTERM */
+ signal(SIGTERM, signal_catcher);
+#endif
+}
+
+#endif
+
+
+/*
+ * Optional progress monitor: display a percent-done figure on stderr.
+ */
+
+#ifdef PROGRESS_REPORT
+
+METHODDEF(void)
+progress_monitor (j_common_ptr cinfo)
+{
+ cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress;
+ int total_passes = prog->pub.total_passes + prog->total_extra_passes;
+ int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit);
+
+ if (percent_done != prog->percent_done) {
+ prog->percent_done = percent_done;
+ if (total_passes > 1) {
+ fprintf(stderr, "\rPass %d/%d: %3d%% ",
+ prog->pub.completed_passes + prog->completed_extra_passes + 1,
+ total_passes, percent_done);
+ } else {
+ fprintf(stderr, "\r %3d%% ", percent_done);
+ }
+ fflush(stderr);
+ }
+}
+
+
+GLOBAL(void)
+start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress)
+{
+ /* Enable progress display, unless trace output is on */
+ if (cinfo->err->trace_level == 0) {
+ progress->pub.progress_monitor = progress_monitor;
+ progress->completed_extra_passes = 0;
+ progress->total_extra_passes = 0;
+ progress->percent_done = -1;
+ cinfo->progress = &progress->pub;
+ }
+}
+
+
+GLOBAL(void)
+end_progress_monitor (j_common_ptr cinfo)
+{
+ /* Clear away progress display */
+ if (cinfo->err->trace_level == 0) {
+ fprintf(stderr, "\r \r");
+ fflush(stderr);
+ }
+}
+
+#endif
+
+
+/*
+ * Case-insensitive matching of possibly-abbreviated keyword switches.
+ * keyword is the constant keyword (must be lower case already),
+ * minchars is length of minimum legal abbreviation.
+ */
+
+GLOBAL(boolean)
+keymatch (char * arg, const char * keyword, int minchars)
+{
+ register int ca, ck;
+ register int nmatched = 0;
+
+ while ((ca = *arg++) != '\0') {
+ if ((ck = *keyword++) == '\0')
+ return FALSE; /* arg longer than keyword, no good */
+ if (isupper(ca)) /* force arg to lcase (assume ck is already) */
+ ca = tolower(ca);
+ if (ca != ck)
+ return FALSE; /* no good */
+ nmatched++; /* count matched characters */
+ }
+ /* reached end of argument; fail if it's too short for unique abbrev */
+ if (nmatched < minchars)
+ return FALSE;
+ return TRUE; /* A-OK */
+}
+
+
+/*
+ * Routines to establish binary I/O mode for stdin and stdout.
+ * Non-Unix systems often require some hacking to get out of text mode.
+ */
+
+GLOBAL(FILE *)
+read_stdin (void)
+{
+ FILE * input_file = stdin;
+
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdin), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
+ fprintf(stderr, "Cannot reopen stdin\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+ return input_file;
+}
+
+
+GLOBAL(FILE *)
+write_stdout (void)
+{
+ FILE * output_file = stdout;
+
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdout), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "Cannot reopen stdout\n");
+ exit(EXIT_FAILURE);
+ }
+#endif
+ return output_file;
+}
diff --git a/Source/LibJPEG/cdjpeg.h b/Source/LibJPEG/cdjpeg.h
new file mode 100644
index 0000000..ed024ac
--- /dev/null
+++ b/Source/LibJPEG/cdjpeg.h
@@ -0,0 +1,187 @@
+/*
+ * cdjpeg.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains common declarations for the sample applications
+ * cjpeg and djpeg. It is NOT used by the core JPEG library.
+ */
+
+#define JPEG_CJPEG_DJPEG /* define proper options in jconfig.h */
+#define JPEG_INTERNAL_OPTIONS /* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h" /* get library error codes too */
+#include "cderror.h" /* get application-specific error codes */
+
+
+/*
+ * Object interface for cjpeg's source file decoding modules
+ */
+
+typedef struct cjpeg_source_struct * cjpeg_source_ptr;
+
+struct cjpeg_source_struct {
+ JMETHOD(void, start_input, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+ JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+ JMETHOD(void, finish_input, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+
+ FILE *input_file;
+
+ JSAMPARRAY buffer;
+ JDIMENSION buffer_height;
+};
+
+
+/*
+ * Object interface for djpeg's output file encoding modules
+ */
+
+typedef struct djpeg_dest_struct * djpeg_dest_ptr;
+
+struct djpeg_dest_struct {
+ /* start_output is called after jpeg_start_decompress finishes.
+ * The color map will be ready at this time, if one is needed.
+ */
+ JMETHOD(void, start_output, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo));
+ /* Emit the specified number of pixel rows from the buffer. */
+ JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied));
+ /* Finish up at the end of the image. */
+ JMETHOD(void, finish_output, (j_decompress_ptr cinfo,
+ djpeg_dest_ptr dinfo));
+
+ /* Target file spec; filled in by djpeg.c after object is created. */
+ FILE * output_file;
+
+ /* Output pixel-row buffer. Created by module init or start_output.
+ * Width is cinfo->output_width * cinfo->output_components;
+ * height is buffer_height.
+ */
+ JSAMPARRAY buffer;
+ JDIMENSION buffer_height;
+};
+
+
+/*
+ * cjpeg/djpeg may need to perform extra passes to convert to or from
+ * the source/destination file format. The JPEG library does not know
+ * about these passes, but we'd like them to be counted by the progress
+ * monitor. We use an expanded progress monitor object to hold the
+ * additional pass count.
+ */
+
+struct cdjpeg_progress_mgr {
+ struct jpeg_progress_mgr pub; /* fields known to JPEG library */
+ int completed_extra_passes; /* extra passes completed */
+ int total_extra_passes; /* total extra */
+ /* last printed percentage stored here to avoid multiple printouts */
+ int percent_done;
+};
+
+typedef struct cdjpeg_progress_mgr * cd_progress_ptr;
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_read_bmp jIRdBMP
+#define jinit_write_bmp jIWrBMP
+#define jinit_read_gif jIRdGIF
+#define jinit_write_gif jIWrGIF
+#define jinit_read_ppm jIRdPPM
+#define jinit_write_ppm jIWrPPM
+#define jinit_read_rle jIRdRLE
+#define jinit_write_rle jIWrRLE
+#define jinit_read_targa jIRdTarga
+#define jinit_write_targa jIWrTarga
+#define read_quant_tables RdQTables
+#define read_scan_script RdScnScript
+#define set_quality_ratings SetQRates
+#define set_quant_slots SetQSlots
+#define set_sample_factors SetSFacts
+#define read_color_map RdCMap
+#define enable_signal_catcher EnSigCatcher
+#define start_progress_monitor StProgMon
+#define end_progress_monitor EnProgMon
+#define read_stdin RdStdin
+#define write_stdout WrStdout
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Module selection routines for I/O modules. */
+
+EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo,
+ boolean is_os2));
+EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo));
+EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo));
+EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo));
+
+/* cjpeg support routines (in rdswitch.c) */
+
+EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename,
+ boolean force_baseline));
+EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename));
+EXTERN(boolean) set_quality_ratings JPP((j_compress_ptr cinfo, char *arg,
+ boolean force_baseline));
+EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg));
+EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg));
+
+/* djpeg support routines (in rdcolmap.c) */
+
+EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* common support routines (in cdjpeg.c) */
+
+EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo));
+EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo,
+ cd_progress_ptr progress));
+EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo));
+EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars));
+EXTERN(FILE *) read_stdin JPP((void));
+EXTERN(FILE *) write_stdout JPP((void));
+
+/* miscellaneous useful macros */
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#else
+#ifdef VMS /* VMS is very nonstandard */
+#define READ_BINARY "rb", "ctx=stm"
+#define WRITE_BINARY "wb", "ctx=stm"
+#else /* standard ANSI-compliant case */
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#endif
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#ifdef VMS
+#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
+#else
+#define EXIT_SUCCESS 0
+#endif
+#endif
+#ifndef EXIT_WARNING
+#ifdef VMS
+#define EXIT_WARNING 1 /* VMS is very nonstandard */
+#else
+#define EXIT_WARNING 2
+#endif
+#endif
diff --git a/Source/LibJPEG/change.log b/Source/LibJPEG/change.log
new file mode 100644
index 0000000..85c0084
--- /dev/null
+++ b/Source/LibJPEG/change.log
@@ -0,0 +1,270 @@
+CHANGE LOG for Independent JPEG Group's JPEG software
+
+
+Version 7 27-Jun-2009
+----------------------
+
+New scaled DCTs implemented.
+djpeg now supports scalings N/8 with all N from 1 to 16.
+cjpeg now supports scalings 8/N with all N from 1 to 16.
+Scaled DCTs with size larger than 8 are now also used for resolving the
+common 2x2 chroma subsampling case without additional spatial resampling.
+Separate spatial resampling for those kind of files is now only necessary
+for N>8 scaling cases.
+Furthermore, separate scaled DCT functions are provided for direct resolving
+of the common asymmetric subsampling cases (2x1 and 1x2) without additional
+spatial resampling.
+
+cjpeg -quality option has been extended for support of separate quality
+settings for luminance and chrominance (or in general, for every provided
+quantization table slot).
+New API function jpeg_default_qtables() and q_scale_factor array in library.
+
+Added -nosmooth option to cjpeg, complementary to djpeg.
+New variable "do_fancy_downsampling" in library, complement to fancy
+upsampling. Fancy upsampling now uses direct DCT scaling with sizes
+larger than 8. The old method is not reversible and has been removed.
+
+Support arithmetic entropy encoding and decoding.
+Added files jaricom.c, jcarith.c, jdarith.c.
+
+Straighten the file structure:
+Removed files jidctred.c, jcphuff.c, jchuff.h, jdphuff.c, jdhuff.h.
+
+jpegtran has a new "lossless" cropping feature.
+
+Implement -perfect option in jpegtran, new API function
+jtransform_perfect_transform() in transupp. (DP 204_perfect.dpatch)
+
+Better error messages for jpegtran fopen failure.
+(DP 203_jpegtran_errmsg.dpatch)
+
+Fix byte order issue with 16bit PPM/PGM files in rdppm.c/wrppm.c:
+according to Netpbm, the de facto standard implementation of the PNM formats,
+the most significant byte is first. (DP 203_rdppm.dpatch)
+
+Add -raw option to rdjpgcom not to mangle the output.
+(DP 205_rdjpgcom_raw.dpatch)
+
+Make rdjpgcom locale aware. (DP 201_rdjpgcom_locale.dpatch)
+
+Add extern "C" to jpeglib.h.
+This avoids the need to put extern "C" { ... } around #include "jpeglib.h"
+in your C++ application. Defining the symbol DONT_USE_EXTERN_C in the
+configuration prevents this. (DP 202_jpeglib.h_c++.dpatch)
+
+
+Version 6b 27-Mar-1998
+-----------------------
+
+jpegtran has new features for lossless image transformations (rotation
+and flipping) as well as "lossless" reduction to grayscale.
+
+jpegtran now copies comments by default; it has a -copy switch to enable
+copying all APPn blocks as well, or to suppress comments. (Formerly it
+always suppressed comments and APPn blocks.) jpegtran now also preserves
+JFIF version and resolution information.
+
+New decompressor library feature: COM and APPn markers found in the input
+file can be saved in memory for later use by the application. (Before,
+you had to code this up yourself with a custom marker processor.)
+
+There is an unused field "void * client_data" now in compress and decompress
+parameter structs; this may be useful in some applications.
+
+JFIF version number information is now saved by the decoder and accepted by
+the encoder. jpegtran uses this to copy the source file's version number,
+to ensure "jpegtran -copy all" won't create bogus files that contain JFXX
+extensions but claim to be version 1.01. Applications that generate their
+own JFXX extension markers also (finally) have a supported way to cause the
+encoder to emit JFIF version number 1.02.
+
+djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather
+than as unknown APP0 markers.
+
+In -verbose mode, djpeg and rdjpgcom will try to print the contents of
+APP12 markers as text. Some digital cameras store useful text information
+in APP12 markers.
+
+Handling of truncated data streams is more robust: blocks beyond the one in
+which the error occurs will be output as uniform gray, or left unchanged
+if decoding a progressive JPEG. The appearance no longer depends on the
+Huffman tables being used.
+
+Huffman tables are checked for validity much more carefully than before.
+
+To avoid the Unisys LZW patent, djpeg's GIF output capability has been
+changed to produce "uncompressed GIFs", and cjpeg's GIF input capability
+has been removed altogether. We're not happy about it either, but there
+seems to be no good alternative.
+
+The configure script now supports building libjpeg as a shared library
+on many flavors of Unix (all the ones that GNU libtool knows how to
+build shared libraries for). Use "./configure --enable-shared" to
+try this out.
+
+New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio.
+Also, a jconfig file and a build script for Metrowerks CodeWarrior
+on Apple Macintosh. makefile.dj has been updated for DJGPP v2, and there
+are miscellaneous other minor improvements in the makefiles.
+
+jmemmac.c now knows how to create temporary files following Mac System 7
+conventions.
+
+djpeg's -map switch is now able to read raw-format PPM files reliably.
+
+cjpeg -progressive -restart no longer generates any unnecessary DRI markers.
+
+Multiple calls to jpeg_simple_progression for a single JPEG object
+no longer leak memory.
+
+
+Version 6a 7-Feb-96
+--------------------
+
+Library initialization sequence modified to detect version mismatches
+and struct field packing mismatches between library and calling application.
+This change requires applications to be recompiled, but does not require
+any application source code change.
+
+All routine declarations changed to the style "GLOBAL(type) name ...",
+that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the
+routine's return type as an argument. This makes it possible to add
+Microsoft-style linkage keywords to all the routines by changing just
+these macros. Note that any application code that was using these macros
+will have to be changed.
+
+DCT coefficient quantization tables are now stored in normal array order
+rather than zigzag order. Application code that calls jpeg_add_quant_table,
+or otherwise manipulates quantization tables directly, will need to be
+changed. If you need to make such code work with either older or newer
+versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is
+recommended.
+
+djpeg's trace capability now dumps DQT tables in natural order, not zigzag
+order. This allows the trace output to be made into a "-qtables" file
+more easily.
+
+New system-dependent memory manager module for use on Apple Macintosh.
+
+Fix bug in cjpeg's -smooth option: last one or two scanlines would be
+duplicates of the prior line unless the image height mod 16 was 1 or 2.
+
+Repair minor problems in VMS, BCC, MC6 makefiles.
+
+New configure script based on latest GNU Autoconf.
+
+Correct the list of include files needed by MetroWerks C for ccommand().
+
+Numerous small documentation updates.
+
+
+Version 6 2-Aug-95
+-------------------
+
+Progressive JPEG support: library can read and write full progressive JPEG
+files. A "buffered image" mode supports incremental decoding for on-the-fly
+display of progressive images. Simply recompiling an existing IJG-v5-based
+decoder with v6 should allow it to read progressive files, though of course
+without any special progressive display.
+
+New "jpegtran" application performs lossless transcoding between different
+JPEG formats; primarily, it can be used to convert baseline to progressive
+JPEG and vice versa. In support of jpegtran, the library now allows lossless
+reading and writing of JPEG files as DCT coefficient arrays. This ability
+may be of use in other applications.
+
+Notes for programmers:
+* We changed jpeg_start_decompress() to be able to suspend; this makes all
+decoding modes available to suspending-input applications. However,
+existing applications that use suspending input will need to be changed
+to check the return value from jpeg_start_decompress(). You don't need to
+do anything if you don't use a suspending data source.
+* We changed the interface to the virtual array routines: access_virt_array
+routines now take a count of the number of rows to access this time. The
+last parameter to request_virt_array routines is now interpreted as the
+maximum number of rows that may be accessed at once, but not necessarily
+the height of every access.
+
+
+Version 5b 15-Mar-95
+---------------------
+
+Correct bugs with grayscale images having v_samp_factor > 1.
+
+jpeg_write_raw_data() now supports output suspension.
+
+Correct bugs in "configure" script for case of compiling in
+a directory other than the one containing the source files.
+
+Repair bug in jquant1.c: sometimes didn't use as many colors as it could.
+
+Borland C makefile and jconfig file work under either MS-DOS or OS/2.
+
+Miscellaneous improvements to documentation.
+
+
+Version 5a 7-Dec-94
+--------------------
+
+Changed color conversion roundoff behavior so that grayscale values are
+represented exactly. (This causes test image files to change.)
+
+Make ordered dither use 16x16 instead of 4x4 pattern for a small quality
+improvement.
+
+New configure script based on latest GNU Autoconf.
+Fix configure script to handle CFLAGS correctly.
+Rename *.auto files to *.cfg, so that configure script still works if
+file names have been truncated for DOS.
+
+Fix bug in rdbmp.c: didn't allow for extra data between header and image.
+
+Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data.
+
+Fix several bugs in rdrle.c.
+
+NEED_SHORT_EXTERNAL_NAMES option was broken.
+
+Revise jerror.h/jerror.c for more flexibility in message table.
+
+Repair oversight in jmemname.c NO_MKTEMP case: file could be there
+but unreadable.
+
+
+Version 5 24-Sep-94
+--------------------
+
+Version 5 represents a nearly complete redesign and rewrite of the IJG
+software. Major user-visible changes include:
+ * Automatic configuration simplifies installation for most Unix systems.
+ * A range of speed vs. image quality tradeoffs are supported.
+ This includes resizing of an image during decompression: scaling down
+ by a factor of 1/2, 1/4, or 1/8 is handled very efficiently.
+ * New programs rdjpgcom and wrjpgcom allow insertion and extraction
+ of text comments in a JPEG file.
+
+The application programmer's interface to the library has changed completely.
+Notable improvements include:
+ * We have eliminated the use of callback routines for handling the
+ uncompressed image data. The application now sees the library as a
+ set of routines that it calls to read or write image data on a
+ scanline-by-scanline basis.
+ * The application image data is represented in a conventional interleaved-
+ pixel format, rather than as a separate array for each color channel.
+ This can save a copying step in many programs.
+ * The handling of compressed data has been cleaned up: the application can
+ supply routines to source or sink the compressed data. It is possible to
+ suspend processing on source/sink buffer overrun, although this is not
+ supported in all operating modes.
+ * All static state has been eliminated from the library, so that multiple
+ instances of compression or decompression can be active concurrently.
+ * JPEG abbreviated datastream formats are supported, ie, quantization and
+ Huffman tables can be stored separately from the image data.
+ * And not only that, but the documentation of the library has improved
+ considerably!
+
+
+The last widely used release before the version 5 rewrite was version 4A of
+18-Feb-93. Change logs before that point have been discarded, since they
+are not of much interest after the rewrite.
diff --git a/Source/LibJPEG/cjpeg.c b/Source/LibJPEG/cjpeg.c
new file mode 100644
index 0000000..b9d57eb
--- /dev/null
+++ b/Source/LibJPEG/cjpeg.c
@@ -0,0 +1,616 @@
+/*
+ * cjpeg.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * Modified 2003-2008 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for the JPEG compressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ * cjpeg [options] inputfile outputfile
+ * cjpeg [options] [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program. Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes. Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ * To simplify script writing, the "-outfile" switch is provided. The syntax
+ * cjpeg [options] -outfile outputfile inputfile
+ * works regardless of which command line style is used.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include "jversion.h" /* for version message */
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string) string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+ NULL
+};
+
+
+/*
+ * This routine determines what format the input file is,
+ * and selects the appropriate input-reading module.
+ *
+ * To determine which family of input formats the file belongs to,
+ * we may look only at the first byte of the file, since C does not
+ * guarantee that more than one character can be pushed back with ungetc.
+ * Looking at additional bytes would require one of these approaches:
+ * 1) assume we can fseek() the input file (fails for piped input);
+ * 2) assume we can push back more than one character (works in
+ * some C implementations, but unportable);
+ * 3) provide our own buffering (breaks input readers that want to use
+ * stdio directly, such as the RLE library);
+ * or 4) don't put back the data, and modify the input_init methods to assume
+ * they start reading after the start of file (also breaks RLE library).
+ * #1 is attractive for MS-DOS but is untenable on Unix.
+ *
+ * The most portable solution for file types that can't be identified by their
+ * first byte is to make the user tell us what they are. This is also the
+ * only approach for "raw" file types that contain only arbitrary values.
+ * We presently apply this method for Targa files. Most of the time Targa
+ * files start with 0x00, so we recognize that case. Potentially, however,
+ * a Targa file could start with any byte value (byte 0 is the length of the
+ * seldom-used ID field), so we provide a switch to force Targa input mode.
+ */
+
+static boolean is_targa; /* records user -targa switch */
+
+
+LOCAL(cjpeg_source_ptr)
+select_file_type (j_compress_ptr cinfo, FILE * infile)
+{
+ int c;
+
+ if (is_targa) {
+#ifdef TARGA_SUPPORTED
+ return jinit_read_targa(cinfo);
+#else
+ ERREXIT(cinfo, JERR_TGA_NOTCOMP);
+#endif
+ }
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ if (ungetc(c, infile) == EOF)
+ ERREXIT(cinfo, JERR_UNGETC_FAILED);
+
+ switch (c) {
+#ifdef BMP_SUPPORTED
+ case 'B':
+ return jinit_read_bmp(cinfo);
+#endif
+#ifdef GIF_SUPPORTED
+ case 'G':
+ return jinit_read_gif(cinfo);
+#endif
+#ifdef PPM_SUPPORTED
+ case 'P':
+ return jinit_read_ppm(cinfo);
+#endif
+#ifdef RLE_SUPPORTED
+ case 'R':
+ return jinit_read_rle(cinfo);
+#endif
+#ifdef TARGA_SUPPORTED
+ case 0x00:
+ return jinit_read_targa(cinfo);
+#endif
+ default:
+ ERREXIT(cinfo, JERR_UNKNOWN_FORMAT);
+ break;
+ }
+
+ return NULL; /* suppress compiler warnings */
+}
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ * The main program in this file doesn't actually use this capability...
+ */
+
+
+static const char * progname; /* program name for error messages */
+static char * outfilename; /* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -quality N[,...] Compression quality (0..100; 5-95 is useful range)\n");
+ fprintf(stderr, " -grayscale Create monochrome JPEG file\n");
+#ifdef ENTROPY_OPT_SUPPORTED
+ fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
+#endif
+#ifdef C_PROGRESSIVE_SUPPORTED
+ fprintf(stderr, " -progressive Create progressive JPEG file\n");
+#endif
+#ifdef DCT_SCALING_SUPPORTED
+ fprintf(stderr, " -scale M/N Scale image by fraction M/N, eg, 1/2\n");
+#endif
+#ifdef TARGA_SUPPORTED
+ fprintf(stderr, " -targa Input file is Targa format (usually not needed)\n");
+#endif
+ fprintf(stderr, "Switches for advanced users:\n");
+#ifdef DCT_ISLOW_SUPPORTED
+ fprintf(stderr, " -dct int Use integer DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
+ (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+ fprintf(stderr, " -nosmooth Don't use high-quality downsampling\n");
+ fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ fprintf(stderr, " -smooth N Smooth dithered input (N=1..100 is strength)\n");
+#endif
+ fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
+ fprintf(stderr, " -outfile name Specify name for output file\n");
+ fprintf(stderr, " -verbose or -debug Emit debug output\n");
+ fprintf(stderr, "Switches for wizards:\n");
+#ifdef C_ARITH_CODING_SUPPORTED
+ fprintf(stderr, " -arithmetic Use arithmetic coding\n");
+#endif
+ fprintf(stderr, " -baseline Force baseline quantization tables\n");
+ fprintf(stderr, " -qtables file Use quantization tables given in file\n");
+ fprintf(stderr, " -qslots N[,...] Set component quantization tables\n");
+ fprintf(stderr, " -sample HxV[,...] Set component sampling factors\n");
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
+#endif
+ exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_compress_ptr cinfo, int argc, char **argv,
+ int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+ int argn;
+ char * arg;
+ boolean force_baseline;
+ boolean simple_progressive;
+ char * qualityarg = NULL; /* saves -quality parm if any */
+ char * qtablefile = NULL; /* saves -qtables filename if any */
+ char * qslotsarg = NULL; /* saves -qslots parm if any */
+ char * samplearg = NULL; /* saves -sample parm if any */
+ char * scansarg = NULL; /* saves -scans parm if any */
+
+ /* Set up default JPEG parameters. */
+
+ force_baseline = FALSE; /* by default, allow 16-bit quantizers */
+ simple_progressive = FALSE;
+ is_targa = FALSE;
+ outfilename = NULL;
+ cinfo->err->trace_level = 0;
+
+ /* Scan command line options, adjust parameters */
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Not a switch, must be a file name argument */
+ if (argn <= last_file_arg_seen) {
+ outfilename = NULL; /* -outfile applies to just one input file */
+ continue; /* ignore this name if previously processed */
+ }
+ break; /* else done parsing switches */
+ }
+ arg++; /* advance past switch marker character */
+
+ if (keymatch(arg, "arithmetic", 1)) {
+ /* Use arithmetic coding. */
+#ifdef C_ARITH_CODING_SUPPORTED
+ cinfo->arith_code = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "baseline", 1)) {
+ /* Force baseline-compatible output (8-bit quantizer values). */
+ force_baseline = TRUE;
+
+ } else if (keymatch(arg, "dct", 2)) {
+ /* Select DCT algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "int", 1)) {
+ cinfo->dct_method = JDCT_ISLOW;
+ } else if (keymatch(argv[argn], "fast", 2)) {
+ cinfo->dct_method = JDCT_IFAST;
+ } else if (keymatch(argv[argn], "float", 2)) {
+ cinfo->dct_method = JDCT_FLOAT;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+ /* Enable debug printouts. */
+ /* On first -d, print version identification */
+ static boolean printed_version = FALSE;
+
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's CJPEG, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+
+ } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+ /* Force a monochrome JPEG file to be generated. */
+ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+
+ } else if (keymatch(arg, "maxmemory", 3)) {
+ /* Maximum memory in Kb (or Mb with 'm'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (ch == 'm' || ch == 'M')
+ lval *= 1000L;
+ cinfo->mem->max_memory_to_use = lval * 1000L;
+
+ } else if (keymatch(arg, "nosmooth", 3)) {
+ /* Suppress fancy downsampling */
+ cinfo->do_fancy_downsampling = FALSE;
+
+ } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
+ /* Enable entropy parm optimization. */
+#ifdef ENTROPY_OPT_SUPPORTED
+ cinfo->optimize_coding = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "outfile", 4)) {
+ /* Set output file name. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ outfilename = argv[argn]; /* save it away for later use */
+
+ } else if (keymatch(arg, "progressive", 1)) {
+ /* Select simple progressive mode. */
+#ifdef C_PROGRESSIVE_SUPPORTED
+ simple_progressive = TRUE;
+ /* We must postpone execution until num_components is known. */
+#else
+ fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "quality", 1)) {
+ /* Quality ratings (quantization table scaling factors). */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ qualityarg = argv[argn];
+
+ } else if (keymatch(arg, "qslots", 2)) {
+ /* Quantization table slot numbers. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ qslotsarg = argv[argn];
+ /* Must delay setting qslots until after we have processed any
+ * colorspace-determining switches, since jpeg_set_colorspace sets
+ * default quant table numbers.
+ */
+
+ } else if (keymatch(arg, "qtables", 2)) {
+ /* Quantization tables fetched from file. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ qtablefile = argv[argn];
+ /* We postpone actually reading the file in case -quality comes later. */
+
+ } else if (keymatch(arg, "restart", 1)) {
+ /* Restart interval in MCU rows (or in MCUs with 'b'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (lval < 0 || lval > 65535L)
+ usage();
+ if (ch == 'b' || ch == 'B') {
+ cinfo->restart_interval = (unsigned int) lval;
+ cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
+ } else {
+ cinfo->restart_in_rows = (int) lval;
+ /* restart_interval will be computed during startup */
+ }
+
+ } else if (keymatch(arg, "sample", 2)) {
+ /* Set sampling factors. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ samplearg = argv[argn];
+ /* Must delay setting sample factors until after we have processed any
+ * colorspace-determining switches, since jpeg_set_colorspace sets
+ * default sampling factors.
+ */
+
+ } else if (keymatch(arg, "scale", 4)) {
+ /* Scale the image by a fraction M/N. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d/%d",
+ &cinfo->scale_num, &cinfo->scale_denom) != 2)
+ usage();
+
+ } else if (keymatch(arg, "scans", 4)) {
+ /* Set scan script. */
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ scansarg = argv[argn];
+ /* We must postpone reading the file in case -progressive appears. */
+#else
+ fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "smooth", 2)) {
+ /* Set input smoothing factor. */
+ int val;
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d", &val) != 1)
+ usage();
+ if (val < 0 || val > 100)
+ usage();
+ cinfo->smoothing_factor = val;
+
+ } else if (keymatch(arg, "targa", 1)) {
+ /* Input file is Targa format. */
+ is_targa = TRUE;
+
+ } else {
+ usage(); /* bogus switch */
+ }
+ }
+
+ /* Post-switch-scanning cleanup */
+
+ if (for_real) {
+
+ /* Set quantization tables for selected quality. */
+ /* Some or all may be overridden if -qtables is present. */
+ if (qualityarg != NULL) /* process -quality if it was present */
+ if (! set_quality_ratings(cinfo, qualityarg, force_baseline))
+ usage();
+
+ if (qtablefile != NULL) /* process -qtables if it was present */
+ if (! read_quant_tables(cinfo, qtablefile, force_baseline))
+ usage();
+
+ if (qslotsarg != NULL) /* process -qslots if it was present */
+ if (! set_quant_slots(cinfo, qslotsarg))
+ usage();
+
+ if (samplearg != NULL) /* process -sample if it was present */
+ if (! set_sample_factors(cinfo, samplearg))
+ usage();
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+ if (simple_progressive) /* process -progressive; -scans can override */
+ jpeg_simple_progression(cinfo);
+#endif
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (scansarg != NULL) /* process -scans if it was present */
+ if (! read_scan_script(cinfo, scansarg))
+ usage();
+#endif
+ }
+
+ return argn; /* return index of next arg (file name) */
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+#ifdef PROGRESS_REPORT
+ struct cdjpeg_progress_mgr progress;
+#endif
+ int file_index;
+ cjpeg_source_ptr src_mgr;
+ FILE * input_file;
+ FILE * output_file;
+ JDIMENSION num_scanlines;
+
+ /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+ argc = ccommand(&argv);
+#endif
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "cjpeg"; /* in case C library doesn't provide it */
+
+ /* Initialize the JPEG compression object with default error handling. */
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ /* Add some application-specific error messages (from cderror.h) */
+ jerr.addon_message_table = cdjpeg_message_table;
+ jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+ jerr.last_addon_message = JMSG_LASTADDONCODE;
+
+ /* Now safe to enable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+ enable_signal_catcher((j_common_ptr) &cinfo);
+#endif
+
+ /* Initialize JPEG parameters.
+ * Much of this may be overridden later.
+ * In particular, we don't yet know the input file's color space,
+ * but we need to provide some value for jpeg_set_defaults() to work.
+ */
+
+ cinfo.in_color_space = JCS_RGB; /* arbitrary guess */
+ jpeg_set_defaults(&cinfo);
+
+ /* Scan command line to find file names.
+ * It is convenient to use just one switch-parsing routine, but the switch
+ * values read here are ignored; we will rescan the switches after opening
+ * the input file.
+ */
+
+ file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
+
+#ifdef TWO_FILE_COMMANDLINE
+ /* Must have either -outfile switch or explicit output file name */
+ if (outfilename == NULL) {
+ if (file_index != argc-2) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ outfilename = argv[file_index+1];
+ } else {
+ if (file_index != argc-1) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ }
+#else
+ /* Unix style: expect zero or one file name */
+ if (file_index < argc-1) {
+ fprintf(stderr, "%s: only one input file\n", progname);
+ usage();
+ }
+#endif /* TWO_FILE_COMMANDLINE */
+
+ /* Open the input file. */
+ if (file_index < argc) {
+ if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default input file is stdin */
+ input_file = read_stdin();
+ }
+
+ /* Open the output file. */
+ if (outfilename != NULL) {
+ if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default output file is stdout */
+ output_file = write_stdout();
+ }
+
+#ifdef PROGRESS_REPORT
+ start_progress_monitor((j_common_ptr) &cinfo, &progress);
+#endif
+
+ /* Figure out the input file format, and set up to read it. */
+ src_mgr = select_file_type(&cinfo, input_file);
+ src_mgr->input_file = input_file;
+
+ /* Read the input file header to obtain file size & colorspace. */
+ (*src_mgr->start_input) (&cinfo, src_mgr);
+
+ /* Now that we know input colorspace, fix colorspace-dependent defaults */
+ jpeg_default_colorspace(&cinfo);
+
+ /* Adjust default compression parameters by re-parsing the options */
+ file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
+
+ /* Specify data destination for compression */
+ jpeg_stdio_dest(&cinfo, output_file);
+
+ /* Start compressor */
+ jpeg_start_compress(&cinfo, TRUE);
+
+ /* Process data */
+ while (cinfo.next_scanline < cinfo.image_height) {
+ num_scanlines = (*src_mgr->get_pixel_rows) (&cinfo, src_mgr);
+ (void) jpeg_write_scanlines(&cinfo, src_mgr->buffer, num_scanlines);
+ }
+
+ /* Finish compression and release memory */
+ (*src_mgr->finish_input) (&cinfo, src_mgr);
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ /* Close files, if we opened them */
+ if (input_file != stdin)
+ fclose(input_file);
+ if (output_file != stdout)
+ fclose(output_file);
+
+#ifdef PROGRESS_REPORT
+ end_progress_monitor((j_common_ptr) &cinfo);
+#endif
+
+ /* All done. */
+ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
+ return 0; /* suppress no-return-value warnings */
+}
diff --git a/Source/LibJPEG/ckconfig.c b/Source/LibJPEG/ckconfig.c
new file mode 100644
index 0000000..e658623
--- /dev/null
+++ b/Source/LibJPEG/ckconfig.c
@@ -0,0 +1,402 @@
+/*
+ * ckconfig.c
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ */
+
+/*
+ * This program is intended to help you determine how to configure the JPEG
+ * software for installation on a particular system. The idea is to try to
+ * compile and execute this program. If your compiler fails to compile the
+ * program, make changes as indicated in the comments below. Once you can
+ * compile the program, run it, and it will produce a "jconfig.h" file for
+ * your system.
+ *
+ * As a general rule, each time you try to compile this program,
+ * pay attention only to the *first* error message you get from the compiler.
+ * Many C compilers will issue lots of spurious error messages once they
+ * have gotten confused. Go to the line indicated in the first error message,
+ * and read the comments preceding that line to see what to change.
+ *
+ * Almost all of the edits you may need to make to this program consist of
+ * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL",
+ * or vice versa. This is called defining or undefining that symbol.
+ */
+
+
+/* First we must see if your system has the include files we need.
+ * We start out with the assumption that your system has all the ANSI-standard
+ * include files. If you get any error trying to include one of these files,
+ * undefine the corresponding HAVE_xxx symbol.
+ */
+
+#define HAVE_STDDEF_H /* replace 'define' by 'undef' if error here */
+#ifdef HAVE_STDDEF_H /* next line will be skipped if you undef... */
+#include <stddef.h>
+#endif
+
+#define HAVE_STDLIB_H /* same thing for stdlib.h */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h> /* If you ain't got this, you ain't got C. */
+
+/* We have to see if your string functions are defined by
+ * strings.h (old BSD convention) or string.h (everybody else).
+ * We try the non-BSD convention first; define NEED_BSD_STRINGS
+ * if the compiler says it can't find string.h.
+ */
+
+#undef NEED_BSD_STRINGS
+
+#ifdef NEED_BSD_STRINGS
+#include <strings.h>
+#else
+#include <string.h>
+#endif
+
+/* On some systems (especially older Unix machines), type size_t is
+ * defined only in the include file <sys/types.h>. If you get a failure
+ * on the size_t test below, try defining NEED_SYS_TYPES_H.
+ */
+
+#undef NEED_SYS_TYPES_H /* start by assuming we don't need it */
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+
+/* Usually type size_t is defined in one of the include files we've included
+ * above. If not, you'll get an error on the "typedef size_t my_size_t;" line.
+ * In that case, first try defining NEED_SYS_TYPES_H just above.
+ * If that doesn't work, you'll have to search through your system library
+ * to figure out which include file defines "size_t". Look for a line that
+ * says "typedef something-or-other size_t;". Then, change the line below
+ * that says "#include <someincludefile.h>" to instead include the file
+ * you found size_t in, and define NEED_SPECIAL_INCLUDE. If you can't find
+ * type size_t anywhere, try replacing "#include <someincludefile.h>" with
+ * "typedef unsigned int size_t;".
+ */
+
+#undef NEED_SPECIAL_INCLUDE /* assume we DON'T need it, for starters */
+
+#ifdef NEED_SPECIAL_INCLUDE
+#include <someincludefile.h>
+#endif
+
+typedef size_t my_size_t; /* The payoff: do we have size_t now? */
+
+
+/* The next question is whether your compiler supports ANSI-style function
+ * prototypes. You need to know this in order to choose between using
+ * makefile.ansi and using makefile.unix.
+ * The #define line below is set to assume you have ANSI function prototypes.
+ * If you get an error in this group of lines, undefine HAVE_PROTOTYPES.
+ */
+
+#define HAVE_PROTOTYPES
+
+#ifdef HAVE_PROTOTYPES
+int testfunction (int arg1, int * arg2); /* check prototypes */
+
+struct methods_struct { /* check method-pointer declarations */
+ int (*error_exit) (char *msgtext);
+ int (*trace_message) (char *msgtext);
+ int (*another_method) (void);
+};
+
+int testfunction (int arg1, int * arg2) /* check definitions */
+{
+ return arg2[arg1];
+}
+
+int test2function (void) /* check void arg list */
+{
+ return 0;
+}
+#endif
+
+
+/* Now we want to find out if your compiler knows what "unsigned char" means.
+ * If you get an error on the "unsigned char un_char;" line,
+ * then undefine HAVE_UNSIGNED_CHAR.
+ */
+
+#define HAVE_UNSIGNED_CHAR
+
+#ifdef HAVE_UNSIGNED_CHAR
+unsigned char un_char;
+#endif
+
+
+/* Now we want to find out if your compiler knows what "unsigned short" means.
+ * If you get an error on the "unsigned short un_short;" line,
+ * then undefine HAVE_UNSIGNED_SHORT.
+ */
+
+#define HAVE_UNSIGNED_SHORT
+
+#ifdef HAVE_UNSIGNED_SHORT
+unsigned short un_short;
+#endif
+
+
+/* Now we want to find out if your compiler understands type "void".
+ * If you get an error anywhere in here, undefine HAVE_VOID.
+ */
+
+#define HAVE_VOID
+
+#ifdef HAVE_VOID
+/* Caution: a C++ compiler will insist on complete prototypes */
+typedef void * void_ptr; /* check void * */
+#ifdef HAVE_PROTOTYPES /* check ptr to function returning void */
+typedef void (*void_func) (int a, int b);
+#else
+typedef void (*void_func) ();
+#endif
+
+#ifdef HAVE_PROTOTYPES /* check void function result */
+void test3function (void_ptr arg1, void_func arg2)
+#else
+void test3function (arg1, arg2)
+ void_ptr arg1;
+ void_func arg2;
+#endif
+{
+ char * locptr = (char *) arg1; /* check casting to and from void * */
+ arg1 = (void *) locptr;
+ (*arg2) (1, 2); /* check call of fcn returning void */
+}
+#endif
+
+
+/* Now we want to find out if your compiler knows what "const" means.
+ * If you get an error here, undefine HAVE_CONST.
+ */
+
+#define HAVE_CONST
+
+#ifdef HAVE_CONST
+static const int carray[3] = {1, 2, 3};
+
+#ifdef HAVE_PROTOTYPES
+int test4function (const int arg1)
+#else
+int test4function (arg1)
+ const int arg1;
+#endif
+{
+ return carray[arg1];
+}
+#endif
+
+
+/* If you get an error or warning about this structure definition,
+ * define INCOMPLETE_TYPES_BROKEN.
+ */
+
+#undef INCOMPLETE_TYPES_BROKEN
+
+#ifndef INCOMPLETE_TYPES_BROKEN
+typedef struct undefined_structure * undef_struct_ptr;
+#endif
+
+
+/* If you get an error about duplicate names,
+ * define NEED_SHORT_EXTERNAL_NAMES.
+ */
+
+#undef NEED_SHORT_EXTERNAL_NAMES
+
+#ifndef NEED_SHORT_EXTERNAL_NAMES
+
+int possibly_duplicate_function ()
+{
+ return 0;
+}
+
+int possibly_dupli_function ()
+{
+ return 1;
+}
+
+#endif
+
+
+
+/************************************************************************
+ * OK, that's it. You should not have to change anything beyond this
+ * point in order to compile and execute this program. (You might get
+ * some warnings, but you can ignore them.)
+ * When you run the program, it will make a couple more tests that it
+ * can do automatically, and then it will create jconfig.h and print out
+ * any additional suggestions it has.
+ ************************************************************************
+ */
+
+
+#ifdef HAVE_PROTOTYPES
+int is_char_signed (int arg)
+#else
+int is_char_signed (arg)
+ int arg;
+#endif
+{
+ if (arg == 189) { /* expected result for unsigned char */
+ return 0; /* type char is unsigned */
+ }
+ else if (arg != -67) { /* expected result for signed char */
+ printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n");
+ printf("I fear the JPEG software will not work at all.\n\n");
+ }
+ return 1; /* assume char is signed otherwise */
+}
+
+
+#ifdef HAVE_PROTOTYPES
+int is_shifting_signed (long arg)
+#else
+int is_shifting_signed (arg)
+ long arg;
+#endif
+/* See whether right-shift on a long is signed or not. */
+{
+ long res = arg >> 4;
+
+ if (res == -0x7F7E80CL) { /* expected result for signed shift */
+ return 1; /* right shift is signed */
+ }
+ /* see if unsigned-shift hack will fix it. */
+ /* we can't just test exact value since it depends on width of long... */
+ res |= (~0L) << (32-4);
+ if (res == -0x7F7E80CL) { /* expected result now? */
+ return 0; /* right shift is unsigned */
+ }
+ printf("Right shift isn't acting as I expect it to.\n");
+ printf("I fear the JPEG software will not work at all.\n\n");
+ return 0; /* try it with unsigned anyway */
+}
+
+
+#ifdef HAVE_PROTOTYPES
+int main (int argc, char ** argv)
+#else
+int main (argc, argv)
+ int argc;
+ char ** argv;
+#endif
+{
+ char signed_char_check = (char) (-67);
+ FILE *outfile;
+
+ /* Attempt to write jconfig.h */
+ if ((outfile = fopen("jconfig.h", "w")) == NULL) {
+ printf("Failed to write jconfig.h\n");
+ return 1;
+ }
+
+ /* Write out all the info */
+ fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n");
+ fprintf(outfile, "/* see jconfig.txt for explanations */\n\n");
+#ifdef HAVE_PROTOTYPES
+ fprintf(outfile, "#define HAVE_PROTOTYPES\n");
+#else
+ fprintf(outfile, "#undef HAVE_PROTOTYPES\n");
+#endif
+#ifdef HAVE_UNSIGNED_CHAR
+ fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n");
+#else
+ fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n");
+#endif
+#ifdef HAVE_UNSIGNED_SHORT
+ fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n");
+#else
+ fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n");
+#endif
+#ifdef HAVE_VOID
+ fprintf(outfile, "/* #define void char */\n");
+#else
+ fprintf(outfile, "#define void char\n");
+#endif
+#ifdef HAVE_CONST
+ fprintf(outfile, "/* #define const */\n");
+#else
+ fprintf(outfile, "#define const\n");
+#endif
+ if (is_char_signed((int) signed_char_check))
+ fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n");
+ else
+ fprintf(outfile, "#define CHAR_IS_UNSIGNED\n");
+#ifdef HAVE_STDDEF_H
+ fprintf(outfile, "#define HAVE_STDDEF_H\n");
+#else
+ fprintf(outfile, "#undef HAVE_STDDEF_H\n");
+#endif
+#ifdef HAVE_STDLIB_H
+ fprintf(outfile, "#define HAVE_STDLIB_H\n");
+#else
+ fprintf(outfile, "#undef HAVE_STDLIB_H\n");
+#endif
+#ifdef NEED_BSD_STRINGS
+ fprintf(outfile, "#define NEED_BSD_STRINGS\n");
+#else
+ fprintf(outfile, "#undef NEED_BSD_STRINGS\n");
+#endif
+#ifdef NEED_SYS_TYPES_H
+ fprintf(outfile, "#define NEED_SYS_TYPES_H\n");
+#else
+ fprintf(outfile, "#undef NEED_SYS_TYPES_H\n");
+#endif
+ fprintf(outfile, "#undef NEED_FAR_POINTERS\n");
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+ fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n");
+#else
+ fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n");
+#endif
+#ifdef INCOMPLETE_TYPES_BROKEN
+ fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n");
+#else
+ fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n");
+#endif
+ fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n");
+ if (is_shifting_signed(-0x7F7E80B1L))
+ fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n");
+ else
+ fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n");
+ fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n");
+ fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n");
+ fprintf(outfile, "#define BMP_SUPPORTED /* BMP image file format */\n");
+ fprintf(outfile, "#define GIF_SUPPORTED /* GIF image file format */\n");
+ fprintf(outfile, "#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */\n");
+ fprintf(outfile, "#undef RLE_SUPPORTED /* Utah RLE image file format */\n");
+ fprintf(outfile, "#define TARGA_SUPPORTED /* Targa image file format */\n\n");
+ fprintf(outfile, "#undef TWO_FILE_COMMANDLINE /* You may need this on non-Unix systems */\n");
+ fprintf(outfile, "#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */\n");
+ fprintf(outfile, "#undef DONT_USE_B_MODE\n");
+ fprintf(outfile, "/* #define PROGRESS_REPORT */ /* optional */\n");
+ fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n");
+
+ /* Close the jconfig.h file */
+ fclose(outfile);
+
+ /* User report */
+ printf("Configuration check for Independent JPEG Group's software done.\n");
+ printf("\nI have written the jconfig.h file for you.\n\n");
+#ifdef HAVE_PROTOTYPES
+ printf("You should use makefile.ansi as the starting point for your Makefile.\n");
+#else
+ printf("You should use makefile.unix as the starting point for your Makefile.\n");
+#endif
+
+#ifdef NEED_SPECIAL_INCLUDE
+ printf("\nYou'll need to change jconfig.h to include the system include file\n");
+ printf("that you found type size_t in, or add a direct definition of type\n");
+ printf("size_t if that's what you used. Just add it to the end.\n");
+#endif
+
+ return 0;
+}
diff --git a/Source/LibJPEG/coderules.txt b/Source/LibJPEG/coderules.txt
new file mode 100644
index 0000000..357929f
--- /dev/null
+++ b/Source/LibJPEG/coderules.txt
@@ -0,0 +1,118 @@
+IJG JPEG LIBRARY: CODING RULES
+
+Copyright (C) 1991-1996, Thomas G. Lane.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+Since numerous people will be contributing code and bug fixes, it's important
+to establish a common coding style. The goal of using similar coding styles
+is much more important than the details of just what that style is.
+
+In general we follow the recommendations of "Recommended C Style and Coding
+Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and
+Brader). This document is available in the IJG FTP archive (see
+jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl).
+
+Block comments should be laid out thusly:
+
+/*
+ * Block comments in this style.
+ */
+
+We indent statements in K&R style, e.g.,
+ if (test) {
+ then-part;
+ } else {
+ else-part;
+ }
+with two spaces per indentation level. (This indentation convention is
+handled automatically by GNU Emacs and many other text editors.)
+
+Multi-word names should be written in lower case with underscores, e.g.,
+multi_word_name (not multiWordName). Preprocessor symbols and enum constants
+are similar but upper case (MULTI_WORD_NAME). Names should be unique within
+the first fifteen characters. (On some older systems, global names must be
+unique within six characters. We accommodate this without cluttering the
+source code by using macros to substitute shorter names.)
+
+We use function prototypes everywhere; we rely on automatic source code
+transformation to feed prototype-less C compilers. Transformation is done
+by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript).
+ansi2knr is not very bright, so it imposes a format requirement on function
+declarations: the function name MUST BEGIN IN COLUMN 1. Thus all functions
+should be written in the following style:
+
+LOCAL(int *)
+function_name (int a, char *b)
+{
+ code...
+}
+
+Note that each function definition must begin with GLOBAL(type), LOCAL(type),
+or METHODDEF(type). These macros expand to "static type" or just "type" as
+appropriate. They provide a readable indication of the routine's usage and
+can readily be changed for special needs. (For instance, special linkage
+keywords can be inserted for use in Windows DLLs.)
+
+ansi2knr does not transform method declarations (function pointers in
+structs). We handle these with a macro JMETHOD, defined as
+ #ifdef HAVE_PROTOTYPES
+ #define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+ #else
+ #define JMETHOD(type,methodname,arglist) type (*methodname) ()
+ #endif
+which is used like this:
+ struct function_pointers {
+ JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp));
+ JMETHOD(void, term_entropy_encoder, (void));
+ };
+Note the set of parentheses surrounding the parameter list.
+
+A similar solution is used for forward and external function declarations
+(see the EXTERN and JPP macros).
+
+If the code is to work on non-ANSI compilers, we cannot rely on a prototype
+declaration to coerce actual parameters into the right types. Therefore, use
+explicit casts on actual parameters whenever the actual parameter type is not
+identical to the formal parameter. Beware of implicit conversions to "int".
+
+It seems there are some non-ANSI compilers in which the sizeof() operator
+is defined to return int, yet size_t is defined as long. Needless to say,
+this is brain-damaged. Always use the SIZEOF() macro in place of sizeof(),
+so that the result is guaranteed to be of type size_t.
+
+
+The JPEG library is intended to be used within larger programs. Furthermore,
+we want it to be reentrant so that it can be used by applications that process
+multiple images concurrently. The following rules support these requirements:
+
+1. Avoid direct use of file I/O, "malloc", error report printouts, etc;
+pass these through the common routines provided.
+
+2. Minimize global namespace pollution. Functions should be declared static
+wherever possible. (Note that our method-based calling conventions help this
+a lot: in many modules only the initialization function will ever need to be
+called directly, so only that function need be externally visible.) All
+global function names should begin with "jpeg_", and should have an
+abbreviated name (unique in the first six characters) substituted by macro
+when NEED_SHORT_EXTERNAL_NAMES is set.
+
+3. Don't use global variables; anything that must be used in another module
+should be in the common data structures.
+
+4. Don't use static variables except for read-only constant tables. Variables
+that should be private to a module can be placed into private structures (see
+the system architecture document, structure.txt).
+
+5. Source file names should begin with "j" for files that are part of the
+library proper; source files that are not part of the library, such as cjpeg.c
+and djpeg.c, do not begin with "j". Keep source file names to eight
+characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers. Keep
+compression and decompression code in separate source files --- some
+applications may want only one half of the library.
+
+Note: these rules (particularly #4) are not followed religiously in the
+modules that are used in cjpeg/djpeg but are not part of the JPEG library
+proper. Those modules are not really intended to be used in other
+applications.
diff --git a/Source/LibJPEG/djpeg.c b/Source/LibJPEG/djpeg.c
new file mode 100644
index 0000000..bc544dc
--- /dev/null
+++ b/Source/LibJPEG/djpeg.c
@@ -0,0 +1,617 @@
+/*
+ * djpeg.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for the JPEG decompressor.
+ * It should work on any system with Unix- or MS-DOS-style command lines.
+ *
+ * Two different command line styles are permitted, depending on the
+ * compile-time switch TWO_FILE_COMMANDLINE:
+ * djpeg [options] inputfile outputfile
+ * djpeg [options] [inputfile]
+ * In the second style, output is always to standard output, which you'd
+ * normally redirect to a file or pipe to some other program. Input is
+ * either from a named file or from standard input (typically redirected).
+ * The second style is convenient on Unix but is unhelpful on systems that
+ * don't support pipes. Also, you MUST use the first style if your system
+ * doesn't do binary I/O to stdin/stdout.
+ * To simplify script writing, the "-outfile" switch is provided. The syntax
+ * djpeg [options] -outfile outputfile inputfile
+ * works regardless of which command line style is used.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include "jversion.h" /* for version message */
+
+#include <ctype.h> /* to declare isprint() */
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+
+/* Create the add-on message string table. */
+
+#define JMESSAGE(code,string) string ,
+
+static const char * const cdjpeg_message_table[] = {
+#include "cderror.h"
+ NULL
+};
+
+
+/*
+ * This list defines the known output image formats
+ * (not all of which need be supported by a given version).
+ * You can change the default output format by defining DEFAULT_FMT;
+ * indeed, you had better do so if you undefine PPM_SUPPORTED.
+ */
+
+typedef enum {
+ FMT_BMP, /* BMP format (Windows flavor) */
+ FMT_GIF, /* GIF format */
+ FMT_OS2, /* BMP format (OS/2 flavor) */
+ FMT_PPM, /* PPM/PGM (PBMPLUS formats) */
+ FMT_RLE, /* RLE format */
+ FMT_TARGA, /* Targa format */
+ FMT_TIFF /* TIFF format */
+} IMAGE_FORMATS;
+
+#ifndef DEFAULT_FMT /* so can override from CFLAGS in Makefile */
+#define DEFAULT_FMT FMT_PPM
+#endif
+
+static IMAGE_FORMATS requested_fmt;
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ * The main program in this file doesn't actually use this capability...
+ */
+
+
+static const char * progname; /* program name for error messages */
+static char * outfilename; /* for -outfile switch */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -colors N Reduce image to no more than N colors\n");
+ fprintf(stderr, " -fast Fast, low-quality processing\n");
+ fprintf(stderr, " -grayscale Force grayscale output\n");
+#ifdef IDCT_SCALING_SUPPORTED
+ fprintf(stderr, " -scale M/N Scale output image by fraction M/N, eg, 1/8\n");
+#endif
+#ifdef BMP_SUPPORTED
+ fprintf(stderr, " -bmp Select BMP output format (Windows style)%s\n",
+ (DEFAULT_FMT == FMT_BMP ? " (default)" : ""));
+#endif
+#ifdef GIF_SUPPORTED
+ fprintf(stderr, " -gif Select GIF output format%s\n",
+ (DEFAULT_FMT == FMT_GIF ? " (default)" : ""));
+#endif
+#ifdef BMP_SUPPORTED
+ fprintf(stderr, " -os2 Select BMP output format (OS/2 style)%s\n",
+ (DEFAULT_FMT == FMT_OS2 ? " (default)" : ""));
+#endif
+#ifdef PPM_SUPPORTED
+ fprintf(stderr, " -pnm Select PBMPLUS (PPM/PGM) output format%s\n",
+ (DEFAULT_FMT == FMT_PPM ? " (default)" : ""));
+#endif
+#ifdef RLE_SUPPORTED
+ fprintf(stderr, " -rle Select Utah RLE output format%s\n",
+ (DEFAULT_FMT == FMT_RLE ? " (default)" : ""));
+#endif
+#ifdef TARGA_SUPPORTED
+ fprintf(stderr, " -targa Select Targa output format%s\n",
+ (DEFAULT_FMT == FMT_TARGA ? " (default)" : ""));
+#endif
+ fprintf(stderr, "Switches for advanced users:\n");
+#ifdef DCT_ISLOW_SUPPORTED
+ fprintf(stderr, " -dct int Use integer DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_ISLOW ? " (default)" : ""));
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ fprintf(stderr, " -dct fast Use fast integer DCT (less accurate)%s\n",
+ (JDCT_DEFAULT == JDCT_IFAST ? " (default)" : ""));
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ fprintf(stderr, " -dct float Use floating-point DCT method%s\n",
+ (JDCT_DEFAULT == JDCT_FLOAT ? " (default)" : ""));
+#endif
+ fprintf(stderr, " -dither fs Use F-S dithering (default)\n");
+ fprintf(stderr, " -dither none Don't use dithering in quantization\n");
+ fprintf(stderr, " -dither ordered Use ordered dither (medium speed, quality)\n");
+#ifdef QUANT_2PASS_SUPPORTED
+ fprintf(stderr, " -map FILE Map to colors used in named image file\n");
+#endif
+ fprintf(stderr, " -nosmooth Don't use high-quality upsampling\n");
+#ifdef QUANT_1PASS_SUPPORTED
+ fprintf(stderr, " -onepass Use 1-pass quantization (fast, low quality)\n");
+#endif
+ fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
+ fprintf(stderr, " -outfile name Specify name for output file\n");
+ fprintf(stderr, " -verbose or -debug Emit debug output\n");
+ exit(EXIT_FAILURE);
+}
+
+
+LOCAL(int)
+parse_switches (j_decompress_ptr cinfo, int argc, char **argv,
+ int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+ int argn;
+ char * arg;
+
+ /* Set up default JPEG parameters. */
+ requested_fmt = DEFAULT_FMT; /* set default output file format */
+ outfilename = NULL;
+ cinfo->err->trace_level = 0;
+
+ /* Scan command line options, adjust parameters */
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Not a switch, must be a file name argument */
+ if (argn <= last_file_arg_seen) {
+ outfilename = NULL; /* -outfile applies to just one input file */
+ continue; /* ignore this name if previously processed */
+ }
+ break; /* else done parsing switches */
+ }
+ arg++; /* advance past switch marker character */
+
+ if (keymatch(arg, "bmp", 1)) {
+ /* BMP output format. */
+ requested_fmt = FMT_BMP;
+
+ } else if (keymatch(arg, "colors", 1) || keymatch(arg, "colours", 1) ||
+ keymatch(arg, "quantize", 1) || keymatch(arg, "quantise", 1)) {
+ /* Do color quantization. */
+ int val;
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d", &val) != 1)
+ usage();
+ cinfo->desired_number_of_colors = val;
+ cinfo->quantize_colors = TRUE;
+
+ } else if (keymatch(arg, "dct", 2)) {
+ /* Select IDCT algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "int", 1)) {
+ cinfo->dct_method = JDCT_ISLOW;
+ } else if (keymatch(argv[argn], "fast", 2)) {
+ cinfo->dct_method = JDCT_IFAST;
+ } else if (keymatch(argv[argn], "float", 2)) {
+ cinfo->dct_method = JDCT_FLOAT;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "dither", 2)) {
+ /* Select dithering algorithm. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "fs", 2)) {
+ cinfo->dither_mode = JDITHER_FS;
+ } else if (keymatch(argv[argn], "none", 2)) {
+ cinfo->dither_mode = JDITHER_NONE;
+ } else if (keymatch(argv[argn], "ordered", 2)) {
+ cinfo->dither_mode = JDITHER_ORDERED;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+ /* Enable debug printouts. */
+ /* On first -d, print version identification */
+ static boolean printed_version = FALSE;
+
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's DJPEG, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+
+ } else if (keymatch(arg, "fast", 1)) {
+ /* Select recommended processing options for quick-and-dirty output. */
+ cinfo->two_pass_quantize = FALSE;
+ cinfo->dither_mode = JDITHER_ORDERED;
+ if (! cinfo->quantize_colors) /* don't override an earlier -colors */
+ cinfo->desired_number_of_colors = 216;
+ cinfo->dct_method = JDCT_FASTEST;
+ cinfo->do_fancy_upsampling = FALSE;
+
+ } else if (keymatch(arg, "gif", 1)) {
+ /* GIF output format. */
+ requested_fmt = FMT_GIF;
+
+ } else if (keymatch(arg, "grayscale", 2) || keymatch(arg, "greyscale",2)) {
+ /* Force monochrome output. */
+ cinfo->out_color_space = JCS_GRAYSCALE;
+
+ } else if (keymatch(arg, "map", 3)) {
+ /* Quantize to a color map taken from an input file. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (for_real) { /* too expensive to do twice! */
+#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
+ FILE * mapfile;
+
+ if ((mapfile = fopen(argv[argn], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ read_color_map(cinfo, mapfile);
+ fclose(mapfile);
+ cinfo->quantize_colors = TRUE;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+
+ } else if (keymatch(arg, "maxmemory", 3)) {
+ /* Maximum memory in Kb (or Mb with 'm'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (ch == 'm' || ch == 'M')
+ lval *= 1000L;
+ cinfo->mem->max_memory_to_use = lval * 1000L;
+
+ } else if (keymatch(arg, "nosmooth", 3)) {
+ /* Suppress fancy upsampling */
+ cinfo->do_fancy_upsampling = FALSE;
+
+ } else if (keymatch(arg, "onepass", 3)) {
+ /* Use fast one-pass quantization. */
+ cinfo->two_pass_quantize = FALSE;
+
+ } else if (keymatch(arg, "os2", 3)) {
+ /* BMP output format (OS/2 flavor). */
+ requested_fmt = FMT_OS2;
+
+ } else if (keymatch(arg, "outfile", 4)) {
+ /* Set output file name. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ outfilename = argv[argn]; /* save it away for later use */
+
+ } else if (keymatch(arg, "pnm", 1) || keymatch(arg, "ppm", 1)) {
+ /* PPM/PGM output format. */
+ requested_fmt = FMT_PPM;
+
+ } else if (keymatch(arg, "rle", 1)) {
+ /* RLE output format. */
+ requested_fmt = FMT_RLE;
+
+ } else if (keymatch(arg, "scale", 1)) {
+ /* Scale the output image by a fraction M/N. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%d/%d",
+ &cinfo->scale_num, &cinfo->scale_denom) < 1)
+ usage();
+
+ } else if (keymatch(arg, "targa", 1)) {
+ /* Targa output format. */
+ requested_fmt = FMT_TARGA;
+
+ } else {
+ usage(); /* bogus switch */
+ }
+ }
+
+ return argn; /* return index of next arg (file name) */
+}
+
+
+/*
+ * Marker processor for COM and interesting APPn markers.
+ * This replaces the library's built-in processor, which just skips the marker.
+ * We want to print out the marker as text, to the extent possible.
+ * Note this code relies on a non-suspending data source.
+ */
+
+LOCAL(unsigned int)
+jpeg_getc (j_decompress_ptr cinfo)
+/* Read next byte */
+{
+ struct jpeg_source_mgr * datasrc = cinfo->src;
+
+ if (datasrc->bytes_in_buffer == 0) {
+ if (! (*datasrc->fill_input_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+ datasrc->bytes_in_buffer--;
+ return GETJOCTET(*datasrc->next_input_byte++);
+}
+
+
+METHODDEF(boolean)
+print_text_marker (j_decompress_ptr cinfo)
+{
+ boolean traceit = (cinfo->err->trace_level >= 1);
+ INT32 length;
+ unsigned int ch;
+ unsigned int lastch = 0;
+
+ length = jpeg_getc(cinfo) << 8;
+ length += jpeg_getc(cinfo);
+ length -= 2; /* discount the length word itself */
+
+ if (traceit) {
+ if (cinfo->unread_marker == JPEG_COM)
+ fprintf(stderr, "Comment, length %ld:\n", (long) length);
+ else /* assume it is an APPn otherwise */
+ fprintf(stderr, "APP%d, length %ld:\n",
+ cinfo->unread_marker - JPEG_APP0, (long) length);
+ }
+
+ while (--length >= 0) {
+ ch = jpeg_getc(cinfo);
+ if (traceit) {
+ /* Emit the character in a readable form.
+ * Nonprintables are converted to \nnn form,
+ * while \ is converted to \\.
+ * Newlines in CR, CR/LF, or LF form will be printed as one newline.
+ */
+ if (ch == '\r') {
+ fprintf(stderr, "\n");
+ } else if (ch == '\n') {
+ if (lastch != '\r')
+ fprintf(stderr, "\n");
+ } else if (ch == '\\') {
+ fprintf(stderr, "\\\\");
+ } else if (isprint(ch)) {
+ putc(ch, stderr);
+ } else {
+ fprintf(stderr, "\\%03o", ch);
+ }
+ lastch = ch;
+ }
+ }
+
+ if (traceit)
+ fprintf(stderr, "\n");
+
+ return TRUE;
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+#ifdef PROGRESS_REPORT
+ struct cdjpeg_progress_mgr progress;
+#endif
+ int file_index;
+ djpeg_dest_ptr dest_mgr = NULL;
+ FILE * input_file;
+ FILE * output_file;
+ JDIMENSION num_scanlines;
+
+ /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+ argc = ccommand(&argv);
+#endif
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "djpeg"; /* in case C library doesn't provide it */
+
+ /* Initialize the JPEG decompression object with default error handling. */
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+ /* Add some application-specific error messages (from cderror.h) */
+ jerr.addon_message_table = cdjpeg_message_table;
+ jerr.first_addon_message = JMSG_FIRSTADDONCODE;
+ jerr.last_addon_message = JMSG_LASTADDONCODE;
+
+ /* Insert custom marker processor for COM and APP12.
+ * APP12 is used by some digital camera makers for textual info,
+ * so we provide the ability to display it as text.
+ * If you like, additional APPn marker types can be selected for display,
+ * but don't try to override APP0 or APP14 this way (see libjpeg.doc).
+ */
+ jpeg_set_marker_processor(&cinfo, JPEG_COM, print_text_marker);
+ jpeg_set_marker_processor(&cinfo, JPEG_APP0+12, print_text_marker);
+
+ /* Now safe to enable signal catcher. */
+#ifdef NEED_SIGNAL_CATCHER
+ enable_signal_catcher((j_common_ptr) &cinfo);
+#endif
+
+ /* Scan command line to find file names. */
+ /* It is convenient to use just one switch-parsing routine, but the switch
+ * values read here are ignored; we will rescan the switches after opening
+ * the input file.
+ * (Exception: tracing level set here controls verbosity for COM markers
+ * found during jpeg_read_header...)
+ */
+
+ file_index = parse_switches(&cinfo, argc, argv, 0, FALSE);
+
+#ifdef TWO_FILE_COMMANDLINE
+ /* Must have either -outfile switch or explicit output file name */
+ if (outfilename == NULL) {
+ if (file_index != argc-2) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ outfilename = argv[file_index+1];
+ } else {
+ if (file_index != argc-1) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ }
+#else
+ /* Unix style: expect zero or one file name */
+ if (file_index < argc-1) {
+ fprintf(stderr, "%s: only one input file\n", progname);
+ usage();
+ }
+#endif /* TWO_FILE_COMMANDLINE */
+
+ /* Open the input file. */
+ if (file_index < argc) {
+ if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[file_index]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default input file is stdin */
+ input_file = read_stdin();
+ }
+
+ /* Open the output file. */
+ if (outfilename != NULL) {
+ if ((output_file = fopen(outfilename, WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, outfilename);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default output file is stdout */
+ output_file = write_stdout();
+ }
+
+#ifdef PROGRESS_REPORT
+ start_progress_monitor((j_common_ptr) &cinfo, &progress);
+#endif
+
+ /* Specify data source for decompression */
+ jpeg_stdio_src(&cinfo, input_file);
+
+ /* Read file header, set default decompression parameters */
+ (void) jpeg_read_header(&cinfo, TRUE);
+
+ /* Adjust default decompression parameters by re-parsing the options */
+ file_index = parse_switches(&cinfo, argc, argv, 0, TRUE);
+
+ /* Initialize the output module now to let it override any crucial
+ * option settings (for instance, GIF wants to force color quantization).
+ */
+ switch (requested_fmt) {
+#ifdef BMP_SUPPORTED
+ case FMT_BMP:
+ dest_mgr = jinit_write_bmp(&cinfo, FALSE);
+ break;
+ case FMT_OS2:
+ dest_mgr = jinit_write_bmp(&cinfo, TRUE);
+ break;
+#endif
+#ifdef GIF_SUPPORTED
+ case FMT_GIF:
+ dest_mgr = jinit_write_gif(&cinfo);
+ break;
+#endif
+#ifdef PPM_SUPPORTED
+ case FMT_PPM:
+ dest_mgr = jinit_write_ppm(&cinfo);
+ break;
+#endif
+#ifdef RLE_SUPPORTED
+ case FMT_RLE:
+ dest_mgr = jinit_write_rle(&cinfo);
+ break;
+#endif
+#ifdef TARGA_SUPPORTED
+ case FMT_TARGA:
+ dest_mgr = jinit_write_targa(&cinfo);
+ break;
+#endif
+ default:
+ ERREXIT(&cinfo, JERR_UNSUPPORTED_FORMAT);
+ break;
+ }
+ dest_mgr->output_file = output_file;
+
+ /* Start decompressor */
+ (void) jpeg_start_decompress(&cinfo);
+
+ /* Write output file header */
+ (*dest_mgr->start_output) (&cinfo, dest_mgr);
+
+ /* Process data */
+ while (cinfo.output_scanline < cinfo.output_height) {
+ num_scanlines = jpeg_read_scanlines(&cinfo, dest_mgr->buffer,
+ dest_mgr->buffer_height);
+ (*dest_mgr->put_pixel_rows) (&cinfo, dest_mgr, num_scanlines);
+ }
+
+#ifdef PROGRESS_REPORT
+ /* Hack: count final pass as done in case finish_output does an extra pass.
+ * The library won't have updated completed_passes.
+ */
+ progress.pub.completed_passes = progress.pub.total_passes;
+#endif
+
+ /* Finish decompression and release memory.
+ * I must do it in this order because output module has allocated memory
+ * of lifespan JPOOL_IMAGE; it needs to finish before releasing memory.
+ */
+ (*dest_mgr->finish_output) (&cinfo, dest_mgr);
+ (void) jpeg_finish_decompress(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+
+ /* Close files, if we opened them */
+ if (input_file != stdin)
+ fclose(input_file);
+ if (output_file != stdout)
+ fclose(output_file);
+
+#ifdef PROGRESS_REPORT
+ end_progress_monitor((j_common_ptr) &cinfo);
+#endif
+
+ /* All done. */
+ exit(jerr.num_warnings ? EXIT_WARNING : EXIT_SUCCESS);
+ return 0; /* suppress no-return-value warnings */
+}
diff --git a/Source/LibJPEG/example.c b/Source/LibJPEG/example.c
new file mode 100644
index 0000000..1d6f6cc
--- /dev/null
+++ b/Source/LibJPEG/example.c
@@ -0,0 +1,433 @@
+/*
+ * example.c
+ *
+ * This file illustrates how to use the IJG code as a subroutine library
+ * to read or write JPEG image files. You should look at this code in
+ * conjunction with the documentation file libjpeg.txt.
+ *
+ * This code will not do anything useful as-is, but it may be helpful as a
+ * skeleton for constructing routines that call the JPEG library.
+ *
+ * We present these routines in the same coding style used in the JPEG code
+ * (ANSI function definitions, etc); but you are of course free to code your
+ * routines in a different style if you prefer.
+ */
+
+#include <stdio.h>
+
+/*
+ * Include file for users of JPEG library.
+ * You will need to have included system headers that define at least
+ * the typedefs FILE and size_t before you can include jpeglib.h.
+ * (stdio.h is sufficient on ANSI-conforming systems.)
+ * You may also wish to include "jerror.h".
+ */
+
+#include "jpeglib.h"
+
+/*
+ * <setjmp.h> is used for the optional error recovery mechanism shown in
+ * the second part of the example.
+ */
+
+#include <setjmp.h>
+
+
+
+/******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/
+
+/* This half of the example shows how to feed data into the JPEG compressor.
+ * We present a minimal version that does not worry about refinements such
+ * as error recovery (the JPEG code will just exit() if it gets an error).
+ */
+
+
+/*
+ * IMAGE DATA FORMATS:
+ *
+ * The standard input image format is a rectangular array of pixels, with
+ * each pixel having the same number of "component" values (color channels).
+ * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars).
+ * If you are working with color data, then the color values for each pixel
+ * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit
+ * RGB color.
+ *
+ * For this example, we'll assume that this data structure matches the way
+ * our application has stored the image in memory, so we can just pass a
+ * pointer to our image buffer. In particular, let's say that the image is
+ * RGB color and is described by:
+ */
+
+extern JSAMPLE * image_buffer; /* Points to large array of R,G,B-order data */
+extern int image_height; /* Number of rows in image */
+extern int image_width; /* Number of columns in image */
+
+
+/*
+ * Sample routine for JPEG compression. We assume that the target file name
+ * and a compression quality factor are passed in.
+ */
+
+GLOBAL(void)
+write_JPEG_file (char * filename, int quality)
+{
+ /* This struct contains the JPEG compression parameters and pointers to
+ * working space (which is allocated as needed by the JPEG library).
+ * It is possible to have several such structures, representing multiple
+ * compression/decompression processes, in existence at once. We refer
+ * to any one struct (and its associated working data) as a "JPEG object".
+ */
+ struct jpeg_compress_struct cinfo;
+ /* This struct represents a JPEG error handler. It is declared separately
+ * because applications often want to supply a specialized error handler
+ * (see the second half of this file for an example). But here we just
+ * take the easy way out and use the standard error handler, which will
+ * print a message on stderr and call exit() if compression fails.
+ * Note that this struct must live as long as the main JPEG parameter
+ * struct, to avoid dangling-pointer problems.
+ */
+ struct jpeg_error_mgr jerr;
+ /* More stuff */
+ FILE * outfile; /* target file */
+ JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
+ int row_stride; /* physical row width in image buffer */
+
+ /* Step 1: allocate and initialize JPEG compression object */
+
+ /* We have to set up the error handler first, in case the initialization
+ * step fails. (Unlikely, but it could happen if you are out of memory.)
+ * This routine fills in the contents of struct jerr, and returns jerr's
+ * address which we place into the link field in cinfo.
+ */
+ cinfo.err = jpeg_std_error(&jerr);
+ /* Now we can initialize the JPEG compression object. */
+ jpeg_create_compress(&cinfo);
+
+ /* Step 2: specify data destination (eg, a file) */
+ /* Note: steps 2 and 3 can be done in either order. */
+
+ /* Here we use the library-supplied code to send compressed data to a
+ * stdio stream. You can also write your own code to do something else.
+ * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+ * requires it in order to write binary files.
+ */
+ if ((outfile = fopen(filename, "wb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", filename);
+ exit(1);
+ }
+ jpeg_stdio_dest(&cinfo, outfile);
+
+ /* Step 3: set parameters for compression */
+
+ /* First we supply a description of the input image.
+ * Four fields of the cinfo struct must be filled in:
+ */
+ cinfo.image_width = image_width; /* image width and height, in pixels */
+ cinfo.image_height = image_height;
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ /* Now use the library's routine to set default compression parameters.
+ * (You must set at least cinfo.in_color_space before calling this,
+ * since the defaults depend on the source color space.)
+ */
+ jpeg_set_defaults(&cinfo);
+ /* Now you can set any non-default parameters you wish to.
+ * Here we just illustrate the use of quality (quantization table) scaling:
+ */
+ jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+
+ /* Step 4: Start compressor */
+
+ /* TRUE ensures that we will write a complete interchange-JPEG file.
+ * Pass TRUE unless you are very sure of what you're doing.
+ */
+ jpeg_start_compress(&cinfo, TRUE);
+
+ /* Step 5: while (scan lines remain to be written) */
+ /* jpeg_write_scanlines(...); */
+
+ /* Here we use the library's state variable cinfo.next_scanline as the
+ * loop counter, so that we don't have to keep track ourselves.
+ * To keep things simple, we pass one scanline per call; you can pass
+ * more if you wish, though.
+ */
+ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ /* jpeg_write_scanlines expects an array of pointers to scanlines.
+ * Here the array is only one element long, but you could pass
+ * more than one scanline at a time if that's more convenient.
+ */
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ /* Step 6: Finish compression */
+
+ jpeg_finish_compress(&cinfo);
+ /* After finish_compress, we can close the output file. */
+ fclose(outfile);
+
+ /* Step 7: release JPEG compression object */
+
+ /* This is an important step since it will release a good deal of memory. */
+ jpeg_destroy_compress(&cinfo);
+
+ /* And we're done! */
+}
+
+
+/*
+ * SOME FINE POINTS:
+ *
+ * In the above loop, we ignored the return value of jpeg_write_scanlines,
+ * which is the number of scanlines actually written. We could get away
+ * with this because we were only relying on the value of cinfo.next_scanline,
+ * which will be incremented correctly. If you maintain additional loop
+ * variables then you should be careful to increment them properly.
+ * Actually, for output to a stdio stream you needn't worry, because
+ * then jpeg_write_scanlines will write all the lines passed (or else exit
+ * with a fatal error). Partial writes can only occur if you use a data
+ * destination module that can demand suspension of the compressor.
+ * (If you don't know what that's for, you don't need it.)
+ *
+ * If the compressor requires full-image buffers (for entropy-coding
+ * optimization or a multi-scan JPEG file), it will create temporary
+ * files for anything that doesn't fit within the maximum-memory setting.
+ * (Note that temp files are NOT needed if you use the default parameters.)
+ * On some systems you may need to set up a signal handler to ensure that
+ * temporary files are deleted if the program is interrupted. See libjpeg.txt.
+ *
+ * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG
+ * files to be compatible with everyone else's. If you cannot readily read
+ * your data in that order, you'll need an intermediate array to hold the
+ * image. See rdtarga.c or rdbmp.c for examples of handling bottom-to-top
+ * source data using the JPEG code's internal virtual-array mechanisms.
+ */
+
+
+
+/******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
+
+/* This half of the example shows how to read data from the JPEG decompressor.
+ * It's a bit more refined than the above, in that we show:
+ * (a) how to modify the JPEG library's standard error-reporting behavior;
+ * (b) how to allocate workspace using the library's memory manager.
+ *
+ * Just to make this example a little different from the first one, we'll
+ * assume that we do not intend to put the whole image into an in-memory
+ * buffer, but to send it line-by-line someplace else. We need a one-
+ * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG
+ * memory manager allocate it for us. This approach is actually quite useful
+ * because we don't need to remember to deallocate the buffer separately: it
+ * will go away automatically when the JPEG object is cleaned up.
+ */
+
+
+/*
+ * ERROR HANDLING:
+ *
+ * The JPEG library's standard error handler (jerror.c) is divided into
+ * several "methods" which you can override individually. This lets you
+ * adjust the behavior without duplicating a lot of code, which you might
+ * have to update with each future release.
+ *
+ * Our example here shows how to override the "error_exit" method so that
+ * control is returned to the library's caller when a fatal error occurs,
+ * rather than calling exit() as the standard error_exit method does.
+ *
+ * We use C's setjmp/longjmp facility to return control. This means that the
+ * routine which calls the JPEG library must first execute a setjmp() call to
+ * establish the return point. We want the replacement error_exit to do a
+ * longjmp(). But we need to make the setjmp buffer accessible to the
+ * error_exit routine. To do this, we make a private extension of the
+ * standard JPEG error handler object. (If we were using C++, we'd say we
+ * were making a subclass of the regular error handler.)
+ *
+ * Here's the extended error handler struct:
+ */
+
+struct my_error_mgr {
+ struct jpeg_error_mgr pub; /* "public" fields */
+
+ jmp_buf setjmp_buffer; /* for return to caller */
+};
+
+typedef struct my_error_mgr * my_error_ptr;
+
+/*
+ * Here's the routine that will replace the standard error_exit method:
+ */
+
+METHODDEF(void)
+my_error_exit (j_common_ptr cinfo)
+{
+ /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
+ my_error_ptr myerr = (my_error_ptr) cinfo->err;
+
+ /* Always display the message. */
+ /* We could postpone this until after returning, if we chose. */
+ (*cinfo->err->output_message) (cinfo);
+
+ /* Return control to the setjmp point */
+ longjmp(myerr->setjmp_buffer, 1);
+}
+
+
+/*
+ * Sample routine for JPEG decompression. We assume that the source file name
+ * is passed in. We want to return 1 on success, 0 on error.
+ */
+
+
+GLOBAL(int)
+read_JPEG_file (char * filename)
+{
+ /* This struct contains the JPEG decompression parameters and pointers to
+ * working space (which is allocated as needed by the JPEG library).
+ */
+ struct jpeg_decompress_struct cinfo;
+ /* We use our private extension JPEG error handler.
+ * Note that this struct must live as long as the main JPEG parameter
+ * struct, to avoid dangling-pointer problems.
+ */
+ struct my_error_mgr jerr;
+ /* More stuff */
+ FILE * infile; /* source file */
+ JSAMPARRAY buffer; /* Output row buffer */
+ int row_stride; /* physical row width in output buffer */
+
+ /* In this example we want to open the input file before doing anything else,
+ * so that the setjmp() error recovery below can assume the file is open.
+ * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
+ * requires it in order to read binary files.
+ */
+
+ if ((infile = fopen(filename, "rb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", filename);
+ return 0;
+ }
+
+ /* Step 1: allocate and initialize JPEG decompression object */
+
+ /* We set up the normal JPEG error routines, then override error_exit. */
+ cinfo.err = jpeg_std_error(&jerr.pub);
+ jerr.pub.error_exit = my_error_exit;
+ /* Establish the setjmp return context for my_error_exit to use. */
+ if (setjmp(jerr.setjmp_buffer)) {
+ /* If we get here, the JPEG code has signaled an error.
+ * We need to clean up the JPEG object, close the input file, and return.
+ */
+ jpeg_destroy_decompress(&cinfo);
+ fclose(infile);
+ return 0;
+ }
+ /* Now we can initialize the JPEG decompression object. */
+ jpeg_create_decompress(&cinfo);
+
+ /* Step 2: specify data source (eg, a file) */
+
+ jpeg_stdio_src(&cinfo, infile);
+
+ /* Step 3: read file parameters with jpeg_read_header() */
+
+ (void) jpeg_read_header(&cinfo, TRUE);
+ /* We can ignore the return value from jpeg_read_header since
+ * (a) suspension is not possible with the stdio data source, and
+ * (b) we passed TRUE to reject a tables-only JPEG file as an error.
+ * See libjpeg.txt for more info.
+ */
+
+ /* Step 4: set parameters for decompression */
+
+ /* In this example, we don't need to change any of the defaults set by
+ * jpeg_read_header(), so we do nothing here.
+ */
+
+ /* Step 5: Start decompressor */
+
+ (void) jpeg_start_decompress(&cinfo);
+ /* We can ignore the return value since suspension is not possible
+ * with the stdio data source.
+ */
+
+ /* We may need to do some setup of our own at this point before reading
+ * the data. After jpeg_start_decompress() we have the correct scaled
+ * output image dimensions available, as well as the output colormap
+ * if we asked for color quantization.
+ * In this example, we need to make an output work buffer of the right size.
+ */
+ /* JSAMPLEs per row in output buffer */
+ row_stride = cinfo.output_width * cinfo.output_components;
+ /* Make a one-row-high sample array that will go away when done with image */
+ buffer = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+
+ /* Step 6: while (scan lines remain to be read) */
+ /* jpeg_read_scanlines(...); */
+
+ /* Here we use the library's state variable cinfo.output_scanline as the
+ * loop counter, so that we don't have to keep track ourselves.
+ */
+ while (cinfo.output_scanline < cinfo.output_height) {
+ /* jpeg_read_scanlines expects an array of pointers to scanlines.
+ * Here the array is only one element long, but you could ask for
+ * more than one scanline at a time if that's more convenient.
+ */
+ (void) jpeg_read_scanlines(&cinfo, buffer, 1);
+ /* Assume put_scanline_someplace wants a pointer and sample count. */
+ put_scanline_someplace(buffer[0], row_stride);
+ }
+
+ /* Step 7: Finish decompression */
+
+ (void) jpeg_finish_decompress(&cinfo);
+ /* We can ignore the return value since suspension is not possible
+ * with the stdio data source.
+ */
+
+ /* Step 8: Release JPEG decompression object */
+
+ /* This is an important step since it will release a good deal of memory. */
+ jpeg_destroy_decompress(&cinfo);
+
+ /* After finish_decompress, we can close the input file.
+ * Here we postpone it until after no more JPEG errors are possible,
+ * so as to simplify the setjmp error logic above. (Actually, I don't
+ * think that jpeg_destroy can do an error exit, but why assume anything...)
+ */
+ fclose(infile);
+
+ /* At this point you may want to check to see whether any corrupt-data
+ * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
+ */
+
+ /* And we're done! */
+ return 1;
+}
+
+
+/*
+ * SOME FINE POINTS:
+ *
+ * In the above code, we ignored the return value of jpeg_read_scanlines,
+ * which is the number of scanlines actually read. We could get away with
+ * this because we asked for only one line at a time and we weren't using
+ * a suspending data source. See libjpeg.txt for more info.
+ *
+ * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress();
+ * we should have done it beforehand to ensure that the space would be
+ * counted against the JPEG max_memory setting. In some systems the above
+ * code would risk an out-of-memory error. However, in general we don't
+ * know the output image dimensions before jpeg_start_decompress(), unless we
+ * call jpeg_calc_output_dimensions(). See libjpeg.txt for more about this.
+ *
+ * Scanlines are returned in the same order as they appear in the JPEG file,
+ * which is standardly top-to-bottom. If you must emit data bottom-to-top,
+ * you can use one of the virtual arrays provided by the JPEG memory manager
+ * to invert the data. See wrbmp.c for an example.
+ *
+ * As with compression, some operating modes may require temporary files.
+ * On some systems you may need to set up a signal handler to ensure that
+ * temporary files are deleted if the program is interrupted. See libjpeg.txt.
+ */
diff --git a/Source/LibJPEG/filelist.txt b/Source/LibJPEG/filelist.txt
new file mode 100644
index 0000000..64f2d92
--- /dev/null
+++ b/Source/LibJPEG/filelist.txt
@@ -0,0 +1,215 @@
+IJG JPEG LIBRARY: FILE LIST
+
+Copyright (C) 1994-2009, Thomas G. Lane, Guido Vollbeding.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+Here is a road map to the files in the IJG JPEG distribution. The
+distribution includes the JPEG library proper, plus two application
+programs ("cjpeg" and "djpeg") which use the library to convert JPEG
+files to and from some other popular image formats. A third application
+"jpegtran" uses the library to do lossless conversion between different
+variants of JPEG. There are also two stand-alone applications,
+"rdjpgcom" and "wrjpgcom".
+
+
+THE JPEG LIBRARY
+================
+
+Include files:
+
+jpeglib.h JPEG library's exported data and function declarations.
+jconfig.h Configuration declarations. Note: this file is not present
+ in the distribution; it is generated during installation.
+jmorecfg.h Additional configuration declarations; need not be changed
+ for a standard installation.
+jerror.h Declares JPEG library's error and trace message codes.
+jinclude.h Central include file used by all IJG .c files to reference
+ system include files.
+jpegint.h JPEG library's internal data structures.
+jdct.h Private declarations for forward & reverse DCT subsystems.
+jmemsys.h Private declarations for memory management subsystem.
+jversion.h Version information.
+
+Applications using the library should include jpeglib.h (which in turn
+includes jconfig.h and jmorecfg.h). Optionally, jerror.h may be included
+if the application needs to reference individual JPEG error codes. The
+other include files are intended for internal use and would not normally
+be included by an application program. (cjpeg/djpeg/etc do use jinclude.h,
+since its function is to improve portability of the whole IJG distribution.
+Most other applications will directly include the system include files they
+want, and hence won't need jinclude.h.)
+
+
+C source code files:
+
+These files contain most of the functions intended to be called directly by
+an application program:
+
+jcapimin.c Application program interface: core routines for compression.
+jcapistd.c Application program interface: standard compression.
+jdapimin.c Application program interface: core routines for decompression.
+jdapistd.c Application program interface: standard decompression.
+jcomapi.c Application program interface routines common to compression
+ and decompression.
+jcparam.c Compression parameter setting helper routines.
+jctrans.c API and library routines for transcoding compression.
+jdtrans.c API and library routines for transcoding decompression.
+
+Compression side of the library:
+
+jcinit.c Initialization: determines which other modules to use.
+jcmaster.c Master control: setup and inter-pass sequencing logic.
+jcmainct.c Main buffer controller (preprocessor => JPEG compressor).
+jcprepct.c Preprocessor buffer controller.
+jccoefct.c Buffer controller for DCT coefficient buffer.
+jccolor.c Color space conversion.
+jcsample.c Downsampling.
+jcdctmgr.c DCT manager (DCT implementation selection & control).
+jfdctint.c Forward DCT using slow-but-accurate integer method.
+jfdctfst.c Forward DCT using faster, less accurate integer method.
+jfdctflt.c Forward DCT using floating-point arithmetic.
+jchuff.c Huffman entropy coding.
+jcarith.c Arithmetic entropy coding.
+jcmarker.c JPEG marker writing.
+jdatadst.c Data destination manager for stdio output.
+
+Decompression side of the library:
+
+jdmaster.c Master control: determines which other modules to use.
+jdinput.c Input controller: controls input processing modules.
+jdmainct.c Main buffer controller (JPEG decompressor => postprocessor).
+jdcoefct.c Buffer controller for DCT coefficient buffer.
+jdpostct.c Postprocessor buffer controller.
+jdmarker.c JPEG marker reading.
+jdhuff.c Huffman entropy decoding.
+jdarith.c Arithmetic entropy decoding.
+jddctmgr.c IDCT manager (IDCT implementation selection & control).
+jidctint.c Inverse DCT using slow-but-accurate integer method.
+jidctfst.c Inverse DCT using faster, less accurate integer method.
+jidctflt.c Inverse DCT using floating-point arithmetic.
+jdsample.c Upsampling.
+jdcolor.c Color space conversion.
+jdmerge.c Merged upsampling/color conversion (faster, lower quality).
+jquant1.c One-pass color quantization using a fixed-spacing colormap.
+jquant2.c Two-pass color quantization using a custom-generated colormap.
+ Also handles one-pass quantization to an externally given map.
+jdatasrc.c Data source manager for stdio input.
+
+Support files for both compression and decompression:
+
+jaricom.c Tables for common use in arithmetic entropy encoding and
+ decoding routines.
+jerror.c Standard error handling routines (application replaceable).
+jmemmgr.c System-independent (more or less) memory management code.
+jutils.c Miscellaneous utility routines.
+
+jmemmgr.c relies on a system-dependent memory management module. The IJG
+distribution includes the following implementations of the system-dependent
+module:
+
+jmemnobs.c "No backing store": assumes adequate virtual memory exists.
+jmemansi.c Makes temporary files with ANSI-standard routine tmpfile().
+jmemname.c Makes temporary files with program-generated file names.
+jmemdos.c Custom implementation for MS-DOS (16-bit environment only):
+ can use extended and expanded memory as well as temp files.
+jmemmac.c Custom implementation for Apple Macintosh.
+
+Exactly one of the system-dependent modules should be configured into an
+installed JPEG library (see install.txt for hints about which one to use).
+On unusual systems you may find it worthwhile to make a special
+system-dependent memory manager.
+
+
+Non-C source code files:
+
+jmemdosa.asm 80x86 assembly code support for jmemdos.c; used only in
+ MS-DOS-specific configurations of the JPEG library.
+
+
+CJPEG/DJPEG/JPEGTRAN
+====================
+
+Include files:
+
+cdjpeg.h Declarations shared by cjpeg/djpeg/jpegtran modules.
+cderror.h Additional error and trace message codes for cjpeg et al.
+transupp.h Declarations for jpegtran support routines in transupp.c.
+
+C source code files:
+
+cjpeg.c Main program for cjpeg.
+djpeg.c Main program for djpeg.
+jpegtran.c Main program for jpegtran.
+cdjpeg.c Utility routines used by all three programs.
+rdcolmap.c Code to read a colormap file for djpeg's "-map" switch.
+rdswitch.c Code to process some of cjpeg's more complex switches.
+ Also used by jpegtran.
+transupp.c Support code for jpegtran: lossless image manipulations.
+
+Image file reader modules for cjpeg:
+
+rdbmp.c BMP file input.
+rdgif.c GIF file input (now just a stub).
+rdppm.c PPM/PGM file input.
+rdrle.c Utah RLE file input.
+rdtarga.c Targa file input.
+
+Image file writer modules for djpeg:
+
+wrbmp.c BMP file output.
+wrgif.c GIF file output (a mere shadow of its former self).
+wrppm.c PPM/PGM file output.
+wrrle.c Utah RLE file output.
+wrtarga.c Targa file output.
+
+
+RDJPGCOM/WRJPGCOM
+=================
+
+C source code files:
+
+rdjpgcom.c Stand-alone rdjpgcom application.
+wrjpgcom.c Stand-alone wrjpgcom application.
+
+These programs do not depend on the IJG library. They do use
+jconfig.h and jinclude.h, only to improve portability.
+
+
+ADDITIONAL FILES
+================
+
+Documentation (see README for a guide to the documentation files):
+
+README Master documentation file.
+*.txt Other documentation files.
+*.1 Documentation in Unix man page format.
+change.log Version-to-version change highlights.
+example.c Sample code for calling JPEG library.
+
+Configuration/installation files and programs (see install.txt for more info):
+
+configure Unix shell script to perform automatic configuration.
+configure.ac Source file for use with Autoconf to generate configure.
+ltmain.sh Support scripts for configure (from GNU libtool).
+config.guess
+config.sub
+depcomp
+missing
+install-sh Install shell script for those Unix systems lacking one.
+Makefile.in Makefile input for configure.
+Makefile.am Source file for use with Automake to generate Makefile.in.
+ckconfig.c Program to generate jconfig.h on non-Unix systems.
+jconfig.txt Template for making jconfig.h by hand.
+mak*.* Sample makefiles for particular systems.
+jconfig.* Sample jconfig.h for particular systems.
+libjpeg.map Script to generate shared library with versioned symbols.
+aclocal.m4 M4 macro definitions for use with Autoconf.
+ansi2knr.c De-ANSIfier for pre-ANSI C compilers (courtesy of
+ L. Peter Deutsch and Aladdin Enterprises).
+
+Test files (see install.txt for test procedure):
+
+test*.* Source and comparison files for confidence test.
+ These are binary image files, NOT text files.
diff --git a/Source/LibJPEG/install.txt b/Source/LibJPEG/install.txt
new file mode 100644
index 0000000..b91df40
--- /dev/null
+++ b/Source/LibJPEG/install.txt
@@ -0,0 +1,1097 @@
+INSTALLATION INSTRUCTIONS for the Independent JPEG Group's JPEG software
+
+Copyright (C) 1991-2009, Thomas G. Lane, Guido Vollbeding.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file explains how to configure and install the IJG software. We have
+tried to make this software extremely portable and flexible, so that it can be
+adapted to almost any environment. The downside of this decision is that the
+installation process is complicated. We have provided shortcuts to simplify
+the task on common systems. But in any case, you will need at least a little
+familiarity with C programming and program build procedures for your system.
+
+If you are only using this software as part of a larger program, the larger
+program's installation procedure may take care of configuring the IJG code.
+For example, Ghostscript's installation script will configure the IJG code.
+You don't need to read this file if you just want to compile Ghostscript.
+
+If you are on a Unix machine, you may not need to read this file at all.
+Try doing
+ ./configure
+ make
+ make test
+If that doesn't complain, do
+ make install
+(better do "make -n install" first to see if the makefile will put the files
+where you want them). Read further if you run into snags or want to customize
+the code for your system.
+
+
+TABLE OF CONTENTS
+-----------------
+
+Before you start
+Configuring the software:
+ using the automatic "configure" script
+ using one of the supplied jconfig and makefile files
+ by hand
+Building the software
+Testing the software
+Installing the software
+Optional stuff
+Optimization
+Hints for specific systems
+
+
+BEFORE YOU START
+================
+
+Before installing the software you must unpack the distributed source code.
+Since you are reading this file, you have probably already succeeded in this
+task. However, there is a potential for error if you needed to convert the
+files to the local standard text file format (for example, if you are on
+MS-DOS you may have converted LF end-of-line to CR/LF). You must apply
+such conversion to all the files EXCEPT those whose names begin with "test".
+The test files contain binary data; if you change them in any way then the
+self-test will give bad results.
+
+Please check the last section of this file to see if there are hints for the
+specific machine or compiler you are using.
+
+
+CONFIGURING THE SOFTWARE
+========================
+
+To configure the IJG code for your system, you need to create two files:
+ * jconfig.h: contains values for system-dependent #define symbols.
+ * Makefile: controls the compilation process.
+(On a non-Unix machine, you may create "project files" or some other
+substitute for a Makefile. jconfig.h is needed in any environment.)
+
+We provide three different ways to generate these files:
+ * On a Unix system, you can just run the "configure" script.
+ * We provide sample jconfig files and makefiles for popular machines;
+ if your machine matches one of the samples, just copy the right sample
+ files to jconfig.h and Makefile.
+ * If all else fails, read the instructions below and make your own files.
+
+
+Configuring the software using the automatic "configure" script
+---------------------------------------------------------------
+
+If you are on a Unix machine, you can just type
+ ./configure
+and let the configure script construct appropriate configuration files.
+If you're using "csh" on an old version of System V, you might need to type
+ sh configure
+instead to prevent csh from trying to execute configure itself.
+Expect configure to run for a few minutes, particularly on slower machines;
+it works by compiling a series of test programs.
+
+Configure was created with GNU Autoconf and it follows the usual conventions
+for GNU configure scripts. It makes a few assumptions that you may want to
+override. You can do this by providing optional switches to configure:
+
+* Configure will build both static and shared libraries, if possible.
+If you want to build libjpeg only as a static library, say
+ ./configure --disable-shared
+If you want to build libjpeg only as a shared library, say
+ ./configure --disable-static
+Configure uses GNU libtool to take care of system-dependent shared library
+building methods.
+
+* Configure will use gcc (GNU C compiler) if it's available, otherwise cc.
+To force a particular compiler to be selected, use the CC option, for example
+ ./configure CC='cc'
+The same method can be used to include any unusual compiler switches.
+For example, on HP-UX you probably want to say
+ ./configure CC='cc -Aa'
+to get HP's compiler to run in ANSI mode.
+
+* The default CFLAGS setting is "-g" for non-gcc compilers, "-g -O2" for gcc.
+You can override this by saying, for example,
+ ./configure CFLAGS='-O2'
+if you want to compile without debugging support.
+
+* Configure will set up the makefile so that "make install" will install files
+into /usr/local/bin, /usr/local/man, etc. You can specify an installation
+prefix other than "/usr/local" by giving configure the option "--prefix=PATH".
+
+* If you don't have a lot of swap space, you may need to enable the IJG
+software's internal virtual memory mechanism. To do this, give the option
+"--enable-maxmem=N" where N is the default maxmemory limit in megabytes.
+This is discussed in more detail under "Selecting a memory manager", below.
+You probably don't need to worry about this on reasonably-sized Unix machines,
+unless you plan to process very large images.
+
+Configure has some other features that are useful if you are cross-compiling
+or working in a network of multiple machine types; but if you need those
+features, you probably already know how to use them.
+
+
+Configuring the software using one of the supplied jconfig and makefile files
+-----------------------------------------------------------------------------
+
+If you have one of these systems, you can just use the provided configuration
+files:
+
+Makefile jconfig file System and/or compiler
+
+makefile.manx jconfig.manx Amiga, Manx Aztec C
+makefile.sas jconfig.sas Amiga, SAS C
+makeproj.mac jconfig.mac Apple Macintosh, Metrowerks CodeWarrior
+mak*jpeg.st jconfig.st Atari ST/STE/TT, Pure C or Turbo C
+makefile.bcc jconfig.bcc MS-DOS or OS/2, Borland C
+makefile.dj jconfig.dj MS-DOS, DJGPP (Delorie's port of GNU C)
+makefile.mc6 jconfig.mc6 MS-DOS, Microsoft C (16-bit only)
+makefile.wat jconfig.wat MS-DOS, OS/2, or Windows NT, Watcom C
+makefile.vc jconfig.vc Windows NT/95, MS Visual C++
+make*.vc6 jconfig.vc Windows NT/95, MS Visual C++ 6
+make*.vc9 jconfig.vc Windows NT/95, MS Visual C++ 2008 (v9)
+makefile.mms jconfig.vms Digital VMS, with MMS software
+makefile.vms jconfig.vms Digital VMS, without MMS software
+
+Copy the proper jconfig file to jconfig.h and the makefile to Makefile (or
+whatever your system uses as the standard makefile name). For more info see
+the appropriate system-specific hints section near the end of this file.
+
+
+Configuring the software by hand
+--------------------------------
+
+First, generate a jconfig.h file. If you are moderately familiar with C,
+the comments in jconfig.txt should be enough information to do this; just
+copy jconfig.txt to jconfig.h and edit it appropriately. Otherwise, you may
+prefer to use the ckconfig.c program. You will need to compile and execute
+ckconfig.c by hand --- we hope you know at least enough to do that.
+ckconfig.c may not compile the first try (in fact, the whole idea is for it
+to fail if anything is going to). If you get compile errors, fix them by
+editing ckconfig.c according to the directions given in ckconfig.c. Once
+you get it to run, it will write a suitable jconfig.h file, and will also
+print out some advice about which makefile to use.
+
+You may also want to look at the canned jconfig files, if there is one for a
+system similar to yours.
+
+Second, select a makefile and copy it to Makefile (or whatever your system
+uses as the standard makefile name). The most generic makefiles we provide
+are
+ makefile.ansi: if your C compiler supports function prototypes
+ makefile.unix: if not.
+(You have function prototypes if ckconfig.c put "#define HAVE_PROTOTYPES"
+in jconfig.h.) You may want to start from one of the other makefiles if
+there is one for a system similar to yours.
+
+Look over the selected Makefile and adjust options as needed. In particular
+you may want to change the CC and CFLAGS definitions. For instance, if you
+are using GCC, set CC=gcc. If you had to use any compiler switches to get
+ckconfig.c to work, make sure the same switches are in CFLAGS.
+
+If you are on a system that doesn't use makefiles, you'll need to set up
+project files (or whatever you do use) to compile all the source files and
+link them into executable files cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom.
+See the file lists in any of the makefiles to find out which files go into
+each program. Note that the provided makefiles all make a "library" file
+libjpeg first, but you don't have to do that if you don't want to; the file
+lists identify which source files are actually needed for compression,
+decompression, or both. As a last resort, you can make a batch script that
+just compiles everything and links it all together; makefile.vms is an example
+of this (it's for VMS systems that have no make-like utility).
+
+Here are comments about some specific configuration decisions you'll
+need to make:
+
+Command line style
+------------------
+
+These programs can use a Unix-like command line style which supports
+redirection and piping, like this:
+ cjpeg inputfile >outputfile
+ cjpeg <inputfile >outputfile
+ source program | cjpeg >outputfile
+The simpler "two file" command line style is just
+ cjpeg inputfile outputfile
+You may prefer the two-file style, particularly if you don't have pipes.
+
+You MUST use two-file style on any system that doesn't cope well with binary
+data fed through stdin/stdout; this is true for some MS-DOS compilers, for
+example. If you're not on a Unix system, it's safest to assume you need
+two-file style. (But if your compiler provides either the Posix-standard
+fdopen() library routine or a Microsoft-compatible setmode() routine, you
+can safely use the Unix command line style, by defining USE_FDOPEN or
+USE_SETMODE respectively.)
+
+To use the two-file style, make jconfig.h say "#define TWO_FILE_COMMANDLINE".
+
+Selecting a memory manager
+--------------------------
+
+The IJG code is capable of working on images that are too big to fit in main
+memory; data is swapped out to temporary files as necessary. However, the
+code to do this is rather system-dependent. We provide five different
+memory managers:
+
+* jmemansi.c This version uses the ANSI-standard library routine tmpfile(),
+ which not all non-ANSI systems have. On some systems
+ tmpfile() may put the temporary file in a non-optimal
+ location; if you don't like what it does, use jmemname.c.
+
+* jmemname.c This version creates named temporary files. For anything
+ except a Unix machine, you'll need to configure the
+ select_file_name() routine appropriately; see the comments
+ near the head of jmemname.c. If you use this version, define
+ NEED_SIGNAL_CATCHER in jconfig.h to make sure the temp files
+ are removed if the program is aborted.
+
+* jmemnobs.c (That stands for No Backing Store :-).) This will compile on
+ almost any system, but it assumes you have enough main memory
+ or virtual memory to hold the biggest images you work with.
+
+* jmemdos.c This should be used with most 16-bit MS-DOS compilers.
+ See the system-specific notes about MS-DOS for more info.
+ IMPORTANT: if you use this, define USE_MSDOS_MEMMGR in
+ jconfig.h, and include the assembly file jmemdosa.asm in the
+ programs. The supplied makefiles and jconfig files for
+ 16-bit MS-DOS compilers already do both.
+
+* jmemmac.c Custom version for Apple Macintosh; see the system-specific
+ notes for Macintosh for more info.
+
+To use a particular memory manager, change the SYSDEPMEM variable in your
+makefile to equal the corresponding object file name (for example, jmemansi.o
+or jmemansi.obj for jmemansi.c).
+
+If you have plenty of (real or virtual) main memory, just use jmemnobs.c.
+"Plenty" means about ten bytes for every pixel in the largest images
+you plan to process, so a lot of systems don't meet this criterion.
+If yours doesn't, try jmemansi.c first. If that doesn't compile, you'll have
+to use jmemname.c; be sure to adjust select_file_name() for local conditions.
+You may also need to change unlink() to remove() in close_backing_store().
+
+Except with jmemnobs.c or jmemmac.c, you need to adjust the DEFAULT_MAX_MEM
+setting to a reasonable value for your system (either by adding a #define for
+DEFAULT_MAX_MEM to jconfig.h, or by adding a -D switch to the Makefile).
+This value limits the amount of data space the program will attempt to
+allocate. Code and static data space isn't counted, so the actual memory
+needs for cjpeg or djpeg are typically 100 to 150Kb more than the max-memory
+setting. Larger max-memory settings reduce the amount of I/O needed to
+process a large image, but too large a value can result in "insufficient
+memory" failures. On most Unix machines (and other systems with virtual
+memory), just set DEFAULT_MAX_MEM to several million and forget it. At the
+other end of the spectrum, for MS-DOS machines you probably can't go much
+above 300K to 400K. (On MS-DOS the value refers to conventional memory only.
+Extended/expanded memory is handled separately by jmemdos.c.)
+
+
+BUILDING THE SOFTWARE
+=====================
+
+Now you should be able to compile the software. Just say "make" (or
+whatever's necessary to start the compilation). Have a cup of coffee.
+
+Here are some things that could go wrong:
+
+If your compiler complains about undefined structures, you should be able to
+shut it up by putting "#define INCOMPLETE_TYPES_BROKEN" in jconfig.h.
+
+If you have trouble with missing system include files or inclusion of the
+wrong ones, read jinclude.h. This shouldn't happen if you used configure
+or ckconfig.c to set up jconfig.h.
+
+There are a fair number of routines that do not use all of their parameters;
+some compilers will issue warnings about this, which you can ignore. There
+are also a few configuration checks that may give "unreachable code" warnings.
+Any other warning deserves investigation.
+
+If you don't have a getenv() library routine, define NO_GETENV.
+
+Also see the system-specific hints, below.
+
+
+TESTING THE SOFTWARE
+====================
+
+As a quick test of functionality we've included a small sample image in
+several forms:
+ testorig.jpg Starting point for the djpeg tests.
+ testimg.ppm The output of djpeg testorig.jpg
+ testimg.bmp The output of djpeg -bmp -colors 256 testorig.jpg
+ testimg.jpg The output of cjpeg testimg.ppm
+ testprog.jpg Progressive-mode equivalent of testorig.jpg.
+ testimgp.jpg The output of cjpeg -progressive -optimize testimg.ppm
+(The first- and second-generation .jpg files aren't identical since JPEG is
+lossy.) If you can generate duplicates of the testimg* files then you
+probably have working programs.
+
+With most of the makefiles, "make test" will perform the necessary
+comparisons.
+
+If you're using a makefile that doesn't provide the test option, run djpeg
+and cjpeg by hand and compare the output files to testimg* with whatever
+binary file comparison tool you have. The files should be bit-for-bit
+identical.
+
+If the programs complain "MAX_ALLOC_CHUNK is wrong, please fix", then you
+need to reduce MAX_ALLOC_CHUNK to a value that fits in type size_t.
+Try adding "#define MAX_ALLOC_CHUNK 65520L" to jconfig.h. A less likely
+configuration error is "ALIGN_TYPE is wrong, please fix": defining ALIGN_TYPE
+as long should take care of that one.
+
+If the cjpeg test run fails with "Missing Huffman code table entry", it's a
+good bet that you needed to define RIGHT_SHIFT_IS_UNSIGNED. Go back to the
+configuration step and run ckconfig.c. (This is a good plan for any other
+test failure, too.)
+
+If you are using Unix (one-file) command line style on a non-Unix system,
+it's a good idea to check that binary I/O through stdin/stdout actually
+works. You should get the same results from "djpeg <testorig.jpg >out.ppm"
+as from "djpeg -outfile out.ppm testorig.jpg". Note that the makefiles all
+use the latter style and therefore do not exercise stdin/stdout! If this
+check fails, try recompiling with USE_SETMODE or USE_FDOPEN defined.
+If it still doesn't work, better use two-file style.
+
+If you chose a memory manager other than jmemnobs.c, you should test that
+temporary-file usage works. Try "djpeg -bmp -colors 256 -max 0 testorig.jpg"
+and make sure its output matches testimg.bmp. If you have any really large
+images handy, try compressing them with -optimize and/or decompressing with
+-colors 256 to make sure your DEFAULT_MAX_MEM setting is not too large.
+
+NOTE: this is far from an exhaustive test of the JPEG software; some modules,
+such as 1-pass color quantization, are not exercised at all. It's just a
+quick test to give you some confidence that you haven't missed something
+major.
+
+
+INSTALLING THE SOFTWARE
+=======================
+
+Once you're done with the above steps, you can install the software by
+copying the executable files (cjpeg, djpeg, jpegtran, rdjpgcom, and wrjpgcom)
+to wherever you normally install programs. On Unix systems, you'll also want
+to put the man pages (cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1)
+in the man-page directory. The pre-fab makefiles don't support this step
+since there's such a wide variety of installation procedures on different
+systems.
+
+If you generated a Makefile with the "configure" script, you can just say
+ make install
+to install the programs and their man pages into the standard places.
+(You'll probably need to be root to do this.) We recommend first saying
+ make -n install
+to see where configure thought the files should go. You may need to edit
+the Makefile, particularly if your system's conventions for man page
+filenames don't match what configure expects.
+
+If you want to install the IJG library itself, for use in compiling other
+programs besides ours, then you need to put the four include files
+ jpeglib.h jerror.h jconfig.h jmorecfg.h
+into your include-file directory, and put the library file libjpeg.a
+(extension may vary depending on system) wherever library files go.
+If you generated a Makefile with "configure", it will do what it thinks
+is the right thing if you say
+ make install-lib
+
+
+OPTIONAL STUFF
+==============
+
+Progress monitor:
+
+If you like, you can #define PROGRESS_REPORT (in jconfig.h) to enable display
+of percent-done progress reports. The routine provided in cdjpeg.c merely
+prints percentages to stderr, but you can customize it to do something
+fancier.
+
+Utah RLE file format support:
+
+We distribute the software with support for RLE image files (Utah Raster
+Toolkit format) disabled, because the RLE support won't compile without the
+Utah library. If you have URT version 3.1 or later, you can enable RLE
+support as follows:
+ 1. #define RLE_SUPPORTED in jconfig.h.
+ 2. Add a -I option to CFLAGS in the Makefile for the directory
+ containing the URT .h files (typically the "include"
+ subdirectory of the URT distribution).
+ 3. Add -L... -lrle to LDLIBS in the Makefile, where ... specifies
+ the directory containing the URT "librle.a" file (typically the
+ "lib" subdirectory of the URT distribution).
+
+Support for 12-bit-deep pixel data:
+
+The JPEG standard allows either 8-bit or 12-bit data precision. (For color,
+this means 8 or 12 bits per channel, of course.) If you need to work with
+deeper than 8-bit data, you can compile the IJG code for 12-bit operation.
+To do so:
+ 1. In jmorecfg.h, define BITS_IN_JSAMPLE as 12 rather than 8.
+ 2. In jconfig.h, undefine BMP_SUPPORTED, RLE_SUPPORTED, and TARGA_SUPPORTED,
+ because the code for those formats doesn't handle 12-bit data and won't
+ even compile. (The PPM code does work, as explained below. The GIF
+ code works too; it scales 8-bit GIF data to and from 12-bit depth
+ automatically.)
+ 3. Compile. Don't expect "make test" to pass, since the supplied test
+ files are for 8-bit data.
+
+Currently, 12-bit support does not work on 16-bit-int machines.
+
+Note that a 12-bit version will not read 8-bit JPEG files, nor vice versa;
+so you'll want to keep around a regular 8-bit compilation as well.
+(Run-time selection of data depth, to allow a single copy that does both,
+is possible but would probably slow things down considerably; it's very low
+on our to-do list.)
+
+The PPM reader (rdppm.c) can read 12-bit data from either text-format or
+binary-format PPM and PGM files. Binary-format PPM/PGM files which have a
+maxval greater than 255 are assumed to use 2 bytes per sample, MSB first
+(big-endian order). As of early 1995, 2-byte binary format is not
+officially supported by the PBMPLUS library, but it is expected that a
+future release of PBMPLUS will support it. Note that the PPM reader will
+read files of any maxval regardless of the BITS_IN_JSAMPLE setting; incoming
+data is automatically rescaled to either maxval=255 or maxval=4095 as
+appropriate for the cjpeg bit depth.
+
+The PPM writer (wrppm.c) will normally write 2-byte binary PPM or PGM
+format, maxval 4095, when compiled with BITS_IN_JSAMPLE=12. Since this
+format is not yet widely supported, you can disable it by compiling wrppm.c
+with PPM_NORAWWORD defined; then the data is scaled down to 8 bits to make a
+standard 1-byte/sample PPM or PGM file. (Yes, this means still another copy
+of djpeg to keep around. But hopefully you won't need it for very long.
+Poskanzer's supposed to get that new PBMPLUS release out Real Soon Now.)
+
+Of course, if you are working with 12-bit data, you probably have it stored
+in some other, nonstandard format. In that case you'll probably want to
+write your own I/O modules to read and write your format.
+
+Note that a 12-bit version of cjpeg always runs in "-optimize" mode, in
+order to generate valid Huffman tables. This is necessary because our
+default Huffman tables only cover 8-bit data.
+
+Removing code:
+
+If you need to make a smaller version of the JPEG software, some optional
+functions can be removed at compile time. See the xxx_SUPPORTED #defines in
+jconfig.h and jmorecfg.h. If at all possible, we recommend that you leave in
+decoder support for all valid JPEG files, to ensure that you can read anyone's
+output. Taking out support for image file formats that you don't use is the
+most painless way to make the programs smaller. Another possibility is to
+remove some of the DCT methods: in particular, the "IFAST" method may not be
+enough faster than the others to be worth keeping on your machine. (If you
+do remove ISLOW or IFAST, be sure to redefine JDCT_DEFAULT or JDCT_FASTEST
+to a supported method, by adding a #define in jconfig.h.)
+
+
+OPTIMIZATION
+============
+
+Unless you own a Cray, you'll probably be interested in making the JPEG
+software go as fast as possible. This section covers some machine-dependent
+optimizations you may want to try. We suggest that before trying any of
+this, you first get the basic installation to pass the self-test step.
+Repeat the self-test after any optimization to make sure that you haven't
+broken anything.
+
+The integer DCT routines perform a lot of multiplications. These
+multiplications must yield 32-bit results, but none of their input values
+are more than 16 bits wide. On many machines, notably the 680x0 and 80x86
+CPUs, a 16x16=>32 bit multiply instruction is faster than a full 32x32=>32
+bit multiply. Unfortunately there is no portable way to specify such a
+multiplication in C, but some compilers can generate one when you use the
+right combination of casts. See the MULTIPLYxxx macro definitions in
+jdct.h. If your compiler makes "int" be 32 bits and "short" be 16 bits,
+defining SHORTxSHORT_32 is fairly likely to work. When experimenting with
+alternate definitions, be sure to test not only whether the code still works
+(use the self-test), but also whether it is actually faster --- on some
+compilers, alternate definitions may compute the right answer, yet be slower
+than the default. Timing cjpeg on a large PGM (grayscale) input file is the
+best way to check this, as the DCT will be the largest fraction of the runtime
+in that mode. (Note: some of the distributed compiler-specific jconfig files
+already contain #define switches to select appropriate MULTIPLYxxx
+definitions.)
+
+If your machine has sufficiently fast floating point hardware, you may find
+that the float DCT method is faster than the integer DCT methods, even
+after tweaking the integer multiply macros. In that case you may want to
+make the float DCT be the default method. (The only objection to this is
+that float DCT results may vary slightly across machines.) To do that, add
+"#define JDCT_DEFAULT JDCT_FLOAT" to jconfig.h. Even if you don't change
+the default, you should redefine JDCT_FASTEST, which is the method selected
+by djpeg's -fast switch. Don't forget to update the documentation files
+(usage.txt and/or cjpeg.1, djpeg.1) to agree with what you've done.
+
+If access to "short" arrays is slow on your machine, it may be a win to
+define type JCOEF as int rather than short. This will cost a good deal of
+memory though, particularly in some multi-pass modes, so don't do it unless
+you have memory to burn and short is REALLY slow.
+
+If your compiler can compile function calls in-line, make sure the INLINE
+macro in jmorecfg.h is defined as the keyword that marks a function
+inline-able. Some compilers have a switch that tells the compiler to inline
+any function it thinks is profitable (e.g., -finline-functions for gcc).
+Enabling such a switch is likely to make the compiled code bigger but faster.
+
+In general, it's worth trying the maximum optimization level of your compiler,
+and experimenting with any optional optimizations such as loop unrolling.
+(Unfortunately, far too many compilers have optimizer bugs ... be prepared to
+back off if the code fails self-test.) If you do any experimentation along
+these lines, please report the optimal settings to jpeg-info@jpegclub.org so
+we can mention them in future releases. Be sure to specify your machine and
+compiler version.
+
+
+HINTS FOR SPECIFIC SYSTEMS
+==========================
+
+We welcome reports on changes needed for systems not mentioned here. Submit
+'em to jpeg-info@jpegclub.org. Also, if configure or ckconfig.c is wrong
+about how to configure the JPEG software for your system, please let us know.
+
+
+Acorn RISC OS:
+
+(Thanks to Simon Middleton for these hints on compiling with Desktop C.)
+After renaming the files according to Acorn conventions, take a copy of
+makefile.ansi, change all occurrences of 'libjpeg.a' to 'libjpeg.o' and
+change these definitions as indicated:
+
+CFLAGS= -throwback -IC: -Wn
+LDLIBS=C:o.Stubs
+SYSDEPMEM=jmemansi.o
+LN=Link
+AR=LibFile -c -o
+
+Also add a new line '.c.o:; $(cc) $< $(cflags) -c -o $@'. Remove the
+lines '$(RM) libjpeg.o' and '$(AR2) libjpeg.o' and the 'jconfig.h'
+dependency section.
+
+Copy jconfig.txt to jconfig.h. Edit jconfig.h to define TWO_FILE_COMMANDLINE
+and CHAR_IS_UNSIGNED.
+
+Run the makefile using !AMU not !Make. If you want to use the 'clean' and
+'test' makefile entries then you will have to fiddle with the syntax a bit
+and rename the test files.
+
+
+Amiga:
+
+SAS C 6.50 reportedly is too buggy to compile the IJG code properly.
+A patch to update to 6.51 is available from SAS or AmiNet FTP sites.
+
+The supplied config files are set up to use jmemname.c as the memory
+manager, with temporary files being created on the device named by
+"JPEGTMP:".
+
+
+Atari ST/STE/TT:
+
+Copy the project files makcjpeg.st, makdjpeg.st, maktjpeg.st, and makljpeg.st
+to cjpeg.prj, djpeg.prj, jpegtran.prj, and libjpeg.prj respectively. The
+project files should work as-is with Pure C. For Turbo C, change library
+filenames "pc..." to "tc..." in each project file. Note that libjpeg.prj
+selects jmemansi.c as the recommended memory manager. You'll probably want to
+adjust the DEFAULT_MAX_MEM setting --- you want it to be a couple hundred K
+less than your normal free memory. Put "#define DEFAULT_MAX_MEM nnnn" into
+jconfig.h to do this.
+
+To use the 68881/68882 coprocessor for the floating point DCT, add the
+compiler option "-8" to the project files and replace pcfltlib.lib with
+pc881lib.lib in cjpeg.prj and djpeg.prj. Or if you don't have a
+coprocessor, you may prefer to remove the float DCT code by undefining
+DCT_FLOAT_SUPPORTED in jmorecfg.h (since without a coprocessor, the float
+code will be too slow to be useful). In that case, you can delete
+pcfltlib.lib from the project files.
+
+Note that you must make libjpeg.lib before making cjpeg.ttp, djpeg.ttp,
+or jpegtran.ttp. You'll have to perform the self-test by hand.
+
+We haven't bothered to include project files for rdjpgcom and wrjpgcom.
+Those source files should just be compiled by themselves; they don't
+depend on the JPEG library. You can use the default.prj project file
+of the Pure C distribution to make the programs.
+
+There is a bug in some older versions of the Turbo C library which causes the
+space used by temporary files created with "tmpfile()" not to be freed after
+an abnormal program exit. If you check your disk afterwards, you will find
+cluster chains that are allocated but not used by a file. This should not
+happen in cjpeg/djpeg/jpegtran, since we enable a signal catcher to explicitly
+close temp files before exiting. But if you use the JPEG library with your
+own code, be sure to supply a signal catcher, or else use a different
+system-dependent memory manager.
+
+
+Cray:
+
+Should you be so fortunate as to be running JPEG on a Cray YMP, there is a
+compiler bug in old versions of Cray's Standard C (prior to 3.1). If you
+still have an old compiler, you'll need to insert a line reading
+"#pragma novector" just before the loop
+ for (i = 1; i <= (int) htbl->bits[l]; i++)
+ huffsize[p++] = (char) l;
+in fix_huff_tbl (in V5beta1, line 204 of jchuff.c and line 176 of jdhuff.c).
+[This bug may or may not still occur with the current IJG code, but it's
+probably a dead issue anyway...]
+
+
+HP-UX:
+
+If you have HP-UX 7.05 or later with the "software development" C compiler,
+you should run the compiler in ANSI mode. If using the configure script,
+say
+ ./configure CC='cc -Aa'
+(or -Ae if you prefer). If configuring by hand, use makefile.ansi and add
+"-Aa" to the CFLAGS line in the makefile.
+
+If you have a pre-7.05 system, or if you are using the non-ANSI C compiler
+delivered with a minimum HP-UX system, then you must use makefile.unix
+(and do NOT add -Aa); or just run configure without the CC option.
+
+On HP 9000 series 800 machines, the HP C compiler is buggy in revisions prior
+to A.08.07. If you get complaints about "not a typedef name", you'll have to
+use makefile.unix, or run configure without the CC option.
+
+
+Macintosh, generic comments:
+
+The supplied user-interface files (cjpeg.c, djpeg.c, etc) are set up to
+provide a Unix-style command line interface. You can use this interface on
+the Mac by means of the ccommand() library routine provided by Metrowerks
+CodeWarrior or Think C. This is only appropriate for testing the library,
+however; to make a user-friendly equivalent of cjpeg/djpeg you'd really want
+to develop a Mac-style user interface. There isn't a complete example
+available at the moment, but there are some helpful starting points:
+1. Sam Bushell's free "To JPEG" applet provides drag-and-drop conversion to
+JPEG under System 7 and later. This only illustrates how to use the
+compression half of the library, but it does a very nice job of that part.
+The CodeWarrior source code is available from http://www.pobox.com/~jsam.
+2. Jim Brunner prepared a Mac-style user interface for both compression and
+decompression. Unfortunately, it hasn't been updated since IJG v4, and
+the library's API has changed considerably since then. Still it may be of
+some help, particularly as a guide to compiling the IJG code under Think C.
+Jim's code is available from the Info-Mac archives, at sumex-aim.stanford.edu
+or mirrors thereof; see file /info-mac/dev/src/jpeg-convert-c.hqx.
+
+jmemmac.c is the recommended memory manager back end for Macintosh. It uses
+NewPtr/DisposePtr instead of malloc/free, and has a Mac-specific
+implementation of jpeg_mem_available(). It also creates temporary files that
+follow Mac conventions. (That part of the code relies on System-7-or-later OS
+functions. See the comments in jmemmac.c if you need to run it on System 6.)
+NOTE that USE_MAC_MEMMGR must be defined in jconfig.h to use jmemmac.c.
+
+You can also use jmemnobs.c, if you don't care about handling images larger
+than available memory. If you use any memory manager back end other than
+jmemmac.c, we recommend replacing "malloc" and "free" by "NewPtr" and
+"DisposePtr", because Mac C libraries often have peculiar implementations of
+malloc/free. (For instance, free() may not return the freed space to the
+Mac Memory Manager. This is undesirable for the IJG code because jmemmgr.c
+already clumps space requests.)
+
+
+Macintosh, Metrowerks CodeWarrior:
+
+The Unix-command-line-style interface can be used by defining USE_CCOMMAND.
+You'll also need to define TWO_FILE_COMMANDLINE to avoid stdin/stdout.
+This means that when using the cjpeg/djpeg programs, you'll have to type the
+input and output file names in the "Arguments" text-edit box, rather than
+using the file radio buttons. (Perhaps USE_FDOPEN or USE_SETMODE would
+eliminate the problem, but I haven't heard from anyone who's tried it.)
+
+On 680x0 Macs, Metrowerks defines type "double" as a 10-byte IEEE extended
+float. jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power
+of 2. Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
+
+The supplied configuration file jconfig.mac can be used for your jconfig.h;
+it includes all the recommended symbol definitions. If you have AppleScript
+installed, you can run the supplied script makeproj.mac to create CodeWarrior
+project files for the library and the testbed applications, then build the
+library and applications. (Thanks to Dan Sears and Don Agro for this nifty
+hack, which saves us from trying to maintain CodeWarrior project files as part
+of the IJG distribution...)
+
+
+Macintosh, Think C:
+
+The documentation in Jim Brunner's "JPEG Convert" source code (see above)
+includes detailed build instructions for Think C; it's probably somewhat
+out of date for the current release, but may be helpful.
+
+If you want to build the minimal command line version, proceed as follows.
+You'll have to prepare project files for the programs; we don't include any
+in the distribution since they are not text files. Use the file lists in
+any of the supplied makefiles as a guide. Also add the ANSI and Unix C
+libraries in a separate segment. You may need to divide the JPEG files into
+more than one segment; we recommend dividing compression and decompression
+modules. Define USE_CCOMMAND in jconfig.h so that the ccommand() routine is
+called. You must also define TWO_FILE_COMMANDLINE because stdin/stdout
+don't handle binary data correctly.
+
+On 680x0 Macs, Think C defines type "double" as a 12-byte IEEE extended float.
+jmemmgr.c won't like this: it wants sizeof(ALIGN_TYPE) to be a power of 2.
+Add "#define ALIGN_TYPE long" to jconfig.h to eliminate the complaint.
+
+jconfig.mac should work as a jconfig.h configuration file for Think C,
+but the makeproj.mac AppleScript script is specific to CodeWarrior. Sorry.
+
+
+MIPS R3000:
+
+MIPS's cc version 1.31 has a rather nasty optimization bug. Don't use -O
+if you have that compiler version. (Use "cc -V" to check the version.)
+Note that the R3000 chip is found in workstations from DEC and others.
+
+
+MS-DOS, generic comments for 16-bit compilers:
+
+The IJG code is designed to work well in 80x86 "small" or "medium" memory
+models (i.e., data pointers are 16 bits unless explicitly declared "far";
+code pointers can be either size). You may be able to use small model to
+compile cjpeg or djpeg by itself, but you will probably have to use medium
+model for any larger application. This won't make much difference in
+performance. You *will* take a noticeable performance hit if you use a
+large-data memory model, and you should avoid "huge" model if at all
+possible. Be sure that NEED_FAR_POINTERS is defined in jconfig.h if you use
+a small-data memory model; be sure it is NOT defined if you use a large-data
+model. (The supplied makefiles and jconfig files for Borland and Microsoft C
+compile in medium model and define NEED_FAR_POINTERS.)
+
+The DOS-specific memory manager, jmemdos.c, should be used if possible.
+It needs some assembly-code routines which are in jmemdosa.asm; make sure
+your makefile assembles that file and includes it in the library. If you
+don't have a suitable assembler, you can get pre-assembled object files for
+jmemdosa by FTP from ftp.uu.net:/graphics/jpeg/jdosaobj.zip. (DOS-oriented
+distributions of the IJG source code often include these object files.)
+
+When using jmemdos.c, jconfig.h must define USE_MSDOS_MEMMGR and must set
+MAX_ALLOC_CHUNK to less than 64K (65520L is a typical value). If your
+C library's far-heap malloc() can't allocate blocks that large, reduce
+MAX_ALLOC_CHUNK to whatever it can handle.
+
+If you can't use jmemdos.c for some reason --- for example, because you
+don't have an assembler to assemble jmemdosa.asm --- you'll have to fall
+back to jmemansi.c or jmemname.c. You'll probably still need to set
+MAX_ALLOC_CHUNK in jconfig.h, because most DOS C libraries won't malloc()
+more than 64K at a time. IMPORTANT: if you use jmemansi.c or jmemname.c,
+you will have to compile in a large-data memory model in order to get the
+right stdio library. Too bad.
+
+wrjpgcom needs to be compiled in large model, because it malloc()s a 64KB
+work area to hold the comment text. If your C library's malloc can't
+handle that, reduce MAX_COM_LENGTH as necessary in wrjpgcom.c.
+
+Most MS-DOS compilers treat stdin/stdout as text files, so you must use
+two-file command line style. But if your compiler has either fdopen() or
+setmode(), you can use one-file style if you like. To do this, define
+USE_SETMODE or USE_FDOPEN so that stdin/stdout will be set to binary mode.
+(USE_SETMODE seems to work with more DOS compilers than USE_FDOPEN.) You
+should test that I/O through stdin/stdout produces the same results as I/O
+to explicitly named files... the "make test" procedures in the supplied
+makefiles do NOT use stdin/stdout.
+
+
+MS-DOS, generic comments for 32-bit compilers:
+
+None of the above comments about memory models apply if you are using a
+32-bit flat-memory-space environment, such as DJGPP or Watcom C. (And you
+should use one if you have it, as performance will be much better than
+8086-compatible code!) For flat-memory-space compilers, do NOT define
+NEED_FAR_POINTERS, and do NOT use jmemdos.c. Use jmemnobs.c if the
+environment supplies adequate virtual memory, otherwise use jmemansi.c or
+jmemname.c.
+
+You'll still need to be careful about binary I/O through stdin/stdout.
+See the last paragraph of the previous section.
+
+
+MS-DOS, Borland C:
+
+Be sure to convert all the source files to DOS text format (CR/LF newlines).
+Although Borland C will often work OK with unmodified Unix (LF newlines)
+source files, sometimes it will give bogus compile errors.
+"Illegal character '#'" is the most common such error. (This is true with
+Borland C 3.1, but perhaps is fixed in newer releases.)
+
+If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
+jconfig.bcc already includes #define USE_SETMODE to make this work.
+(fdopen does not work correctly.)
+
+
+MS-DOS, Microsoft C:
+
+makefile.mc6 works with Microsoft C, DOS Visual C++, etc. It should only
+be used if you want to build a 16-bit (small or medium memory model) program.
+
+If you want one-file command line style, just undefine TWO_FILE_COMMANDLINE.
+jconfig.mc6 already includes #define USE_SETMODE to make this work.
+(fdopen does not work correctly.)
+
+Note that this makefile assumes that the working copy of itself is called
+"makefile". If you want to call it something else, say "makefile.mak",
+be sure to adjust the dependency line that reads "$(RFILE) : makefile".
+Otherwise the make will fail because it doesn't know how to create "makefile".
+Worse, some releases of Microsoft's make utilities give an incorrect error
+message in this situation.
+
+Old versions of MS C fail with an "out of macro expansion space" error
+because they can't cope with the macro TRACEMS8 (defined in jerror.h).
+If this happens to you, the easiest solution is to change TRACEMS8 to
+expand to nothing. You'll lose the ability to dump out JPEG coefficient
+tables with djpeg -debug -debug, but at least you can compile.
+
+Original MS C 6.0 is very buggy; it compiles incorrect code unless you turn
+off optimization entirely (remove -O from CFLAGS). 6.00A is better, but it
+still generates bad code if you enable loop optimizations (-Ol or -Ox).
+
+MS C 8.0 crashes when compiling jquant1.c with optimization switch /Oo ...
+which is on by default. To work around this bug, compile that one file
+with /Oo-.
+
+
+Microsoft Windows (all versions), generic comments:
+
+Some Windows system include files define typedef boolean as "unsigned char".
+The IJG code also defines typedef boolean, but we make it "int" by default.
+This doesn't affect the IJG programs because we don't import those Windows
+include files. But if you use the JPEG library in your own program, and some
+of your program's files import one definition of boolean while some import the
+other, you can get all sorts of mysterious problems. A good preventive step
+is to make the IJG library use "unsigned char" for boolean. To do that,
+add something like this to your jconfig.h file:
+ /* Define "boolean" as unsigned char, not int, per Windows custom */
+ #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+ typedef unsigned char boolean;
+ #endif
+ #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+(This is already in jconfig.vc, by the way.)
+
+windef.h contains the declarations
+ #define far
+ #define FAR far
+Since jmorecfg.h tries to define FAR as empty, you may get a compiler
+warning if you include both jpeglib.h and windef.h (which windows.h
+includes). To suppress the warning, you can put "#ifndef FAR"/"#endif"
+around the line "#define FAR" in jmorecfg.h.
+(Something like this is already in jmorecfg.h, by the way.)
+
+When using the library in a Windows application, you will almost certainly
+want to modify or replace the error handler module jerror.c, since our
+default error handler does a couple of inappropriate things:
+ 1. it tries to write error and warning messages on stderr;
+ 2. in event of a fatal error, it exits by calling exit().
+
+A simple stopgap solution for problem 1 is to replace the line
+ fprintf(stderr, "%s\n", buffer);
+(in output_message in jerror.c) with
+ MessageBox(GetActiveWindow(),buffer,"JPEG Error",MB_OK|MB_ICONERROR);
+It's highly recommended that you at least do that much, since otherwise
+error messages will disappear into nowhere. (Beginning with IJG v6b, this
+code is already present in jerror.c; just define USE_WINDOWS_MESSAGEBOX in
+jconfig.h to enable it.)
+
+The proper solution for problem 2 is to return control to your calling
+application after a library error. This can be done with the setjmp/longjmp
+technique discussed in libjpeg.txt and illustrated in example.c. (NOTE:
+some older Windows C compilers provide versions of setjmp/longjmp that
+don't actually work under Windows. You may need to use the Windows system
+functions Catch and Throw instead.)
+
+The recommended memory manager under Windows is jmemnobs.c; in other words,
+let Windows do any virtual memory management needed. You should NOT use
+jmemdos.c nor jmemdosa.asm under Windows.
+
+For Windows 3.1, we recommend compiling in medium or large memory model;
+for newer Windows versions, use a 32-bit flat memory model. (See the MS-DOS
+sections above for more info about memory models.) In the 16-bit memory
+models only, you'll need to put
+ #define MAX_ALLOC_CHUNK 65520L /* Maximum request to malloc() */
+into jconfig.h to limit allocation chunks to 64Kb. (Without that, you'd
+have to use huge memory model, which slows things down unnecessarily.)
+jmemnobs.c works without modification in large or flat memory models, but to
+use medium model, you need to modify its jpeg_get_large and jpeg_free_large
+routines to allocate far memory. In any case, you might like to replace
+its calls to malloc and free with direct calls on Windows memory allocation
+functions.
+
+You may also want to modify jdatasrc.c and jdatadst.c to use Windows file
+operations rather than fread/fwrite. This is only necessary if your C
+compiler doesn't provide a competent implementation of C stdio functions.
+
+You might want to tweak the RGB_xxx macros in jmorecfg.h so that the library
+will accept or deliver color pixels in BGR sample order, not RGB; BGR order
+is usually more convenient under Windows. Note that this change will break
+the sample applications cjpeg/djpeg, but the library itself works fine.
+
+
+Many people want to convert the IJG library into a DLL. This is reasonably
+straightforward, but watch out for the following:
+
+ 1. Don't try to compile as a DLL in small or medium memory model; use
+large model, or even better, 32-bit flat model. Many places in the IJG code
+assume the address of a local variable is an ordinary (not FAR) pointer;
+that isn't true in a medium-model DLL.
+
+ 2. Microsoft C cannot pass file pointers between applications and DLLs.
+(See Microsoft Knowledge Base, PSS ID Number Q50336.) So jdatasrc.c and
+jdatadst.c don't work if you open a file in your application and then pass
+the pointer to the DLL. One workaround is to make jdatasrc.c/jdatadst.c
+part of your main application rather than part of the DLL.
+
+ 3. You'll probably need to modify the macros GLOBAL() and EXTERN() to
+attach suitable linkage keywords to the exported routine names. Similarly,
+you'll want to modify METHODDEF() and JMETHOD() to ensure function pointers
+are declared in a way that lets application routines be called back through
+the function pointers. These macros are in jmorecfg.h. Typical definitions
+for a 16-bit DLL are:
+ #define GLOBAL(type) type _far _pascal _loadds _export
+ #define EXTERN(type) extern type _far _pascal _loadds
+ #define METHODDEF(type) static type _far _pascal
+ #define JMETHOD(type,methodname,arglist) \
+ type (_far _pascal *methodname) arglist
+For a 32-bit DLL you may want something like
+ #define GLOBAL(type) __declspec(dllexport) type
+ #define EXTERN(type) extern __declspec(dllexport) type
+Although not all the GLOBAL routines are actually intended to be called by
+the application, the performance cost of making them all DLL entry points is
+negligible.
+
+The unmodified IJG library presents a very C-specific application interface,
+so the resulting DLL is only usable from C or C++ applications. There has
+been some talk of writing wrapper code that would present a simpler interface
+usable from other languages, such as Visual Basic. This is on our to-do list
+but hasn't been very high priority --- any volunteers out there?
+
+
+Microsoft Windows, Borland C:
+
+The provided jconfig.bcc should work OK in a 32-bit Windows environment,
+but you'll need to tweak it in a 16-bit environment (you'd need to define
+NEED_FAR_POINTERS and MAX_ALLOC_CHUNK). Beware that makefile.bcc will need
+alteration if you want to use it for Windows --- in particular, you should
+use jmemnobs.c not jmemdos.c under Windows.
+
+Borland C++ 4.5 fails with an internal compiler error when trying to compile
+jdmerge.c in 32-bit mode. If enough people complain, perhaps Borland will fix
+it. In the meantime, the simplest known workaround is to add a redundant
+definition of the variable range_limit in h2v1_merged_upsample(), at the head
+of the block that handles odd image width (about line 268 in v6 jdmerge.c):
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ register JSAMPLE * range_limit = cinfo->sample_range_limit; /* ADD THIS */
+ cb = GETJSAMPLE(*inptr1);
+Pretty bizarre, especially since the very similar routine h2v2_merged_upsample
+doesn't trigger the bug.
+Recent reports suggest that this bug does not occur with "bcc32a" (the
+Pentium-optimized version of the compiler).
+
+Another report from a user of Borland C 4.5 was that incorrect code (leading
+to a color shift in processed images) was produced if any of the following
+optimization switch combinations were used:
+ -Ot -Og
+ -Ot -Op
+ -Ot -Om
+So try backing off on optimization if you see such a problem. (Are there
+several different releases all numbered "4.5"??)
+
+
+Microsoft Windows, Microsoft Visual C++:
+
+jconfig.vc should work OK with any Microsoft compiler for a 32-bit memory
+model. makefile.vc is intended for command-line use. (If you are using
+the Developer Studio environment, you may prefer the DevStudio project
+files; see below.)
+
+v7 adds extern "C" to jpeglib.h. This avoids the need to put extern "C"
+{ ... } around #include "jpeglib.h" in your C++ application.
+You can also force VC++ to treat the library as C++ code by renaming
+all the *.c files to *.cpp (and adjusting the makefile to match).
+In this case you also need to define the symbol DONT_USE_EXTERN_C in
+the configuration to prevent jpeglib.h from using extern "C".
+
+
+Microsoft Windows, Microsoft Visual C++ 6 Developer Studio:
+
+We include makefiles that should work as project files in DevStudio 6.0 or
+later. There is a library makefile that builds the IJG library as a static
+Win32 library, and application makefiles that build the sample applications
+as Win32 console applications. (Even if you only want the library, we
+recommend building the applications so that you can run the self-test.)
+
+To use:
+1. Copy jconfig.vc to jconfig.h, makejdsw.vc6 to jpeg.dsw,
+ makeadsw.vc6 to apps.dsw, makejmak.vc6 to jpeg.mak,
+ makejdep.vc6 to jpeg.dep, makejdsp.vc6 to jpeg.dsp,
+ makecmak.vc6 to cjpeg.mak, makecdep.vc6 to cjpeg.dep,
+ makecdsp.vc6 to cjpeg.dsp, makedmak.vc6 to djpeg.mak,
+ makeddep.vc6 to djpeg.dep, makeddsp.vc6 to djpeg.dsp,
+ maketmak.vc6 to jpegtran.mak, maketdep.vc6 to jpegtran.dep,
+ maketdsp.vc6 to jpegtran.dsp, makermak.vc6 to rdjpgcom.mak,
+ makerdep.vc6 to rdjpgcom.dep, makerdsp.vc6 to rdjpgcom.dsp,
+ makewmak.vc6 to wrjpgcom.mak, makewdep.vc6 to wrjpgcom.dep, and
+ makewdsp.vc6 to wrjpgcom.dsp. (Note that the renaming is critical!)
+2. Click on jpeg.dsw and apps.dsw to load the project workspaces.
+ (If you are using DevStudio more recent than 6.0, you'll probably
+ get a message saying that the project files are being updated.)
+3. Build the library project, then the applications project.
+4. Move the application .exe files from `app`\Release to an
+ appropriate location on your path.
+5. To perform the self-test, execute the command line
+ NMAKE /f makefile.vc test
+
+
+Microsoft Windows, Microsoft Visual C++ 2008 Developer Studio (v9):
+
+We include makefiles that should work as project files in Visual Studio
+2008 or later. There is a library makefile that builds the IJG library
+as a static Win32 library, and application makefiles that build the sample
+applications as Win32 console applications. (Even if you only want the
+library, we recommend building the applications so that you can run the
+self-test.)
+
+To use:
+1. Copy jconfig.vc to jconfig.h, makejsln.vc9 to jpeg.sln,
+ makeasln.vc9 to apps.sln, makejvcp.vc9 to jpeg.vcproj,
+ makecvcp.vc9 to cjpeg.vcproj, makedvcp.vc9 to djpeg.vcproj,
+ maketvcp.vc9 to jpegtran.vcproj, makervcp.vc9 to rdjpgcom.vcproj, and
+ makewvcp.vc9 to wrjpgcom.vcproj. (Note that the renaming is critical!)
+2. Click on jpeg.sln and apps.sln to load the project solutions.
+ (If you are using Visual Studio more recent than 2008 (v9), you'll
+ probably get a message saying that the project files are being
+ updated.)
+3. Build the library project, then the applications project.
+4. Move the application .exe files from `app`\Release to an
+ appropriate location on your path.
+5. To perform the self-test, execute the command line
+ NMAKE /f makefile.vc test
+
+
+OS/2, Borland C++:
+
+Watch out for optimization bugs in older Borland compilers; you may need
+to back off the optimization switch settings. See the comments in
+makefile.bcc.
+
+
+SGI:
+
+On some SGI systems, you may need to set "AR2= ar -ts" in the Makefile.
+If you are using configure, you can do this by saying
+ ./configure RANLIB='ar -ts'
+This change is not needed on all SGIs. Use it only if the make fails at the
+stage of linking the completed programs.
+
+On the MIPS R4000 architecture (Indy, etc.), the compiler option "-mips2"
+reportedly speeds up the float DCT method substantially, enough to make it
+faster than the default int method (but still slower than the fast int
+method). If you use -mips2, you may want to alter the default DCT method to
+be float. To do this, put "#define JDCT_DEFAULT JDCT_FLOAT" in jconfig.h.
+
+
+VMS:
+
+On an Alpha/VMS system with MMS, be sure to use the "/Marco=Alpha=1"
+qualifier with MMS when building the JPEG package.
+
+VAX/VMS v5.5-1 may have problems with the test step of the build procedure
+reporting differences when it compares the original and test images. If the
+error points to the last block of the files, it is most likely bogus and may
+be safely ignored. It seems to be because the files are Stream_LF and
+Backup/Compare has difficulty with the (presumably) null padded files.
+This problem was not observed on VAX/VMS v6.1 or AXP/VMS v6.1.
diff --git a/Source/LibJPEG/jaricom.c b/Source/LibJPEG/jaricom.c
new file mode 100644
index 0000000..9e51ed5
--- /dev/null
+++ b/Source/LibJPEG/jaricom.c
@@ -0,0 +1,148 @@
+/*
+ * jaricom.c
+ *
+ * Developed 1997 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains probability estimation tables for common use in
+ * arithmetic entropy encoding and decoding routines.
+ *
+ * This data represents Table D.2 in the JPEG spec (ISO/IEC IS 10918-1
+ * and CCITT Recommendation ITU-T T.81) and Table 24 in the JBIG spec
+ * (ISO/IEC IS 11544 and CCITT Recommendation ITU-T T.82).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+/* The following #define specifies the packing of the four components
+ * into the compact INT32 representation.
+ * Note that this formula must match the actual arithmetic encoder
+ * and decoder implementation. The implementation has to be changed
+ * if this formula is changed.
+ * The current organization is leaned on Markus Kuhn's JBIG
+ * implementation (jbig_tab.c).
+ */
+
+#define V(a,b,c,d) (((INT32)a << 16) | ((INT32)c << 8) | ((INT32)d << 7) | b)
+
+const INT32 jaritab[113] = {
+/*
+ * Index, Qe_Value, Next_Index_LPS, Next_Index_MPS, Switch_MPS
+ */
+/* 0 */ V( 0x5a1d, 1, 1, 1 ),
+/* 1 */ V( 0x2586, 14, 2, 0 ),
+/* 2 */ V( 0x1114, 16, 3, 0 ),
+/* 3 */ V( 0x080b, 18, 4, 0 ),
+/* 4 */ V( 0x03d8, 20, 5, 0 ),
+/* 5 */ V( 0x01da, 23, 6, 0 ),
+/* 6 */ V( 0x00e5, 25, 7, 0 ),
+/* 7 */ V( 0x006f, 28, 8, 0 ),
+/* 8 */ V( 0x0036, 30, 9, 0 ),
+/* 9 */ V( 0x001a, 33, 10, 0 ),
+/* 10 */ V( 0x000d, 35, 11, 0 ),
+/* 11 */ V( 0x0006, 9, 12, 0 ),
+/* 12 */ V( 0x0003, 10, 13, 0 ),
+/* 13 */ V( 0x0001, 12, 13, 0 ),
+/* 14 */ V( 0x5a7f, 15, 15, 1 ),
+/* 15 */ V( 0x3f25, 36, 16, 0 ),
+/* 16 */ V( 0x2cf2, 38, 17, 0 ),
+/* 17 */ V( 0x207c, 39, 18, 0 ),
+/* 18 */ V( 0x17b9, 40, 19, 0 ),
+/* 19 */ V( 0x1182, 42, 20, 0 ),
+/* 20 */ V( 0x0cef, 43, 21, 0 ),
+/* 21 */ V( 0x09a1, 45, 22, 0 ),
+/* 22 */ V( 0x072f, 46, 23, 0 ),
+/* 23 */ V( 0x055c, 48, 24, 0 ),
+/* 24 */ V( 0x0406, 49, 25, 0 ),
+/* 25 */ V( 0x0303, 51, 26, 0 ),
+/* 26 */ V( 0x0240, 52, 27, 0 ),
+/* 27 */ V( 0x01b1, 54, 28, 0 ),
+/* 28 */ V( 0x0144, 56, 29, 0 ),
+/* 29 */ V( 0x00f5, 57, 30, 0 ),
+/* 30 */ V( 0x00b7, 59, 31, 0 ),
+/* 31 */ V( 0x008a, 60, 32, 0 ),
+/* 32 */ V( 0x0068, 62, 33, 0 ),
+/* 33 */ V( 0x004e, 63, 34, 0 ),
+/* 34 */ V( 0x003b, 32, 35, 0 ),
+/* 35 */ V( 0x002c, 33, 9, 0 ),
+/* 36 */ V( 0x5ae1, 37, 37, 1 ),
+/* 37 */ V( 0x484c, 64, 38, 0 ),
+/* 38 */ V( 0x3a0d, 65, 39, 0 ),
+/* 39 */ V( 0x2ef1, 67, 40, 0 ),
+/* 40 */ V( 0x261f, 68, 41, 0 ),
+/* 41 */ V( 0x1f33, 69, 42, 0 ),
+/* 42 */ V( 0x19a8, 70, 43, 0 ),
+/* 43 */ V( 0x1518, 72, 44, 0 ),
+/* 44 */ V( 0x1177, 73, 45, 0 ),
+/* 45 */ V( 0x0e74, 74, 46, 0 ),
+/* 46 */ V( 0x0bfb, 75, 47, 0 ),
+/* 47 */ V( 0x09f8, 77, 48, 0 ),
+/* 48 */ V( 0x0861, 78, 49, 0 ),
+/* 49 */ V( 0x0706, 79, 50, 0 ),
+/* 50 */ V( 0x05cd, 48, 51, 0 ),
+/* 51 */ V( 0x04de, 50, 52, 0 ),
+/* 52 */ V( 0x040f, 50, 53, 0 ),
+/* 53 */ V( 0x0363, 51, 54, 0 ),
+/* 54 */ V( 0x02d4, 52, 55, 0 ),
+/* 55 */ V( 0x025c, 53, 56, 0 ),
+/* 56 */ V( 0x01f8, 54, 57, 0 ),
+/* 57 */ V( 0x01a4, 55, 58, 0 ),
+/* 58 */ V( 0x0160, 56, 59, 0 ),
+/* 59 */ V( 0x0125, 57, 60, 0 ),
+/* 60 */ V( 0x00f6, 58, 61, 0 ),
+/* 61 */ V( 0x00cb, 59, 62, 0 ),
+/* 62 */ V( 0x00ab, 61, 63, 0 ),
+/* 63 */ V( 0x008f, 61, 32, 0 ),
+/* 64 */ V( 0x5b12, 65, 65, 1 ),
+/* 65 */ V( 0x4d04, 80, 66, 0 ),
+/* 66 */ V( 0x412c, 81, 67, 0 ),
+/* 67 */ V( 0x37d8, 82, 68, 0 ),
+/* 68 */ V( 0x2fe8, 83, 69, 0 ),
+/* 69 */ V( 0x293c, 84, 70, 0 ),
+/* 70 */ V( 0x2379, 86, 71, 0 ),
+/* 71 */ V( 0x1edf, 87, 72, 0 ),
+/* 72 */ V( 0x1aa9, 87, 73, 0 ),
+/* 73 */ V( 0x174e, 72, 74, 0 ),
+/* 74 */ V( 0x1424, 72, 75, 0 ),
+/* 75 */ V( 0x119c, 74, 76, 0 ),
+/* 76 */ V( 0x0f6b, 74, 77, 0 ),
+/* 77 */ V( 0x0d51, 75, 78, 0 ),
+/* 78 */ V( 0x0bb6, 77, 79, 0 ),
+/* 79 */ V( 0x0a40, 77, 48, 0 ),
+/* 80 */ V( 0x5832, 80, 81, 1 ),
+/* 81 */ V( 0x4d1c, 88, 82, 0 ),
+/* 82 */ V( 0x438e, 89, 83, 0 ),
+/* 83 */ V( 0x3bdd, 90, 84, 0 ),
+/* 84 */ V( 0x34ee, 91, 85, 0 ),
+/* 85 */ V( 0x2eae, 92, 86, 0 ),
+/* 86 */ V( 0x299a, 93, 87, 0 ),
+/* 87 */ V( 0x2516, 86, 71, 0 ),
+/* 88 */ V( 0x5570, 88, 89, 1 ),
+/* 89 */ V( 0x4ca9, 95, 90, 0 ),
+/* 90 */ V( 0x44d9, 96, 91, 0 ),
+/* 91 */ V( 0x3e22, 97, 92, 0 ),
+/* 92 */ V( 0x3824, 99, 93, 0 ),
+/* 93 */ V( 0x32b4, 99, 94, 0 ),
+/* 94 */ V( 0x2e17, 93, 86, 0 ),
+/* 95 */ V( 0x56a8, 95, 96, 1 ),
+/* 96 */ V( 0x4f46, 101, 97, 0 ),
+/* 97 */ V( 0x47e5, 102, 98, 0 ),
+/* 98 */ V( 0x41cf, 103, 99, 0 ),
+/* 99 */ V( 0x3c3d, 104, 100, 0 ),
+/* 100 */ V( 0x375e, 99, 93, 0 ),
+/* 101 */ V( 0x5231, 105, 102, 0 ),
+/* 102 */ V( 0x4c0f, 106, 103, 0 ),
+/* 103 */ V( 0x4639, 107, 104, 0 ),
+/* 104 */ V( 0x415e, 103, 99, 0 ),
+/* 105 */ V( 0x5627, 105, 106, 1 ),
+/* 106 */ V( 0x50e7, 108, 107, 0 ),
+/* 107 */ V( 0x4b85, 109, 103, 0 ),
+/* 108 */ V( 0x5597, 110, 109, 0 ),
+/* 109 */ V( 0x504f, 111, 107, 0 ),
+/* 110 */ V( 0x5a10, 110, 111, 1 ),
+/* 111 */ V( 0x5522, 112, 109, 0 ),
+/* 112 */ V( 0x59eb, 112, 111, 1 )
+};
diff --git a/Source/LibJPEG/jcapimin.c b/Source/LibJPEG/jcapimin.c
new file mode 100644
index 0000000..563ab42
--- /dev/null
+++ b/Source/LibJPEG/jcapimin.c
@@ -0,0 +1,282 @@
+/*
+ * jcapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-compression case or the transcoding-only
+ * case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jcapistd.c. But also see jcparam.c for
+ * parameter-setup helper routines, jcomapi.c for routines shared by
+ * compression and decompression, and jctrans.c for the transcoding case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG compression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_compress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_compress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = FALSE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->dest = NULL;
+
+ cinfo->comp_info = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ cinfo->quant_tbl_ptrs[i] = NULL;
+ cinfo->q_scale_factor[i] = 100;
+ }
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ cinfo->script_space = NULL;
+
+ cinfo->input_gamma = 1.0; /* in case application forgets */
+
+ /* OK, I'm ready */
+ cinfo->global_state = CSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG compression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_compress (j_compress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG compression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_compress (j_compress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Forcibly suppress or un-suppress all quantization and Huffman tables.
+ * Marks all currently defined tables as already written (if suppress)
+ * or not written (if !suppress). This will control whether they get emitted
+ * by a subsequent jpeg_start_compress call.
+ *
+ * This routine is exported for use by applications that want to produce
+ * abbreviated JPEG datastreams. It logically belongs in jcparam.c, but
+ * since it is called by jpeg_start_compress, we put it here --- otherwise
+ * jcparam.o would be linked whether the application used it or not.
+ */
+
+GLOBAL(void)
+jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress)
+{
+ int i;
+ JQUANT_TBL * qtbl;
+ JHUFF_TBL * htbl;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL)
+ qtbl->sent_table = suppress;
+ }
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL)
+ htbl->sent_table = suppress;
+ }
+}
+
+
+/*
+ * Finish JPEG compression.
+ *
+ * If a multipass operating mode was selected, this may do a great deal of
+ * work including most of the actual output.
+ */
+
+GLOBAL(void)
+jpeg_finish_compress (j_compress_ptr cinfo)
+{
+ JDIMENSION iMCU_row;
+
+ if (cinfo->global_state == CSTATE_SCANNING ||
+ cinfo->global_state == CSTATE_RAW_OK) {
+ /* Terminate first pass */
+ if (cinfo->next_scanline < cinfo->image_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_pass) (cinfo);
+ } else if (cinfo->global_state != CSTATE_WRCOEFS)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any remaining passes */
+ while (! cinfo->master->is_last_pass) {
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) {
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) iMCU_row;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* We bypass the main controller and invoke coef controller directly;
+ * all work is being done from the coefficient buffer.
+ */
+ if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+ (*cinfo->master->finish_pass) (cinfo);
+ }
+ /* Write EOI, do final cleanup */
+ (*cinfo->marker->write_file_trailer) (cinfo);
+ (*cinfo->dest->term_destination) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+}
+
+
+/*
+ * Write a special marker.
+ * This is only recommended for writing COM or APPn markers.
+ * Must be called after jpeg_start_compress() and before
+ * first call to jpeg_write_scanlines() or jpeg_write_raw_data().
+ */
+
+GLOBAL(void)
+jpeg_write_marker (j_compress_ptr cinfo, int marker,
+ const JOCTET *dataptr, unsigned int datalen)
+{
+ JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val));
+
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+ write_marker_byte = cinfo->marker->write_marker_byte; /* copy for speed */
+ while (datalen--) {
+ (*write_marker_byte) (cinfo, *dataptr);
+ dataptr++;
+ }
+}
+
+/* Same, but piecemeal. */
+
+GLOBAL(void)
+jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+{
+ if (cinfo->next_scanline != 0 ||
+ (cinfo->global_state != CSTATE_SCANNING &&
+ cinfo->global_state != CSTATE_RAW_OK &&
+ cinfo->global_state != CSTATE_WRCOEFS))
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ (*cinfo->marker->write_marker_header) (cinfo, marker, datalen);
+}
+
+GLOBAL(void)
+jpeg_write_m_byte (j_compress_ptr cinfo, int val)
+{
+ (*cinfo->marker->write_marker_byte) (cinfo, val);
+}
+
+
+/*
+ * Alternate compression function: just write an abbreviated table file.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * To produce a pair of files containing abbreviated tables and abbreviated
+ * image data, one would proceed as follows:
+ *
+ * initialize JPEG object
+ * set JPEG parameters
+ * set destination to table file
+ * jpeg_write_tables(cinfo);
+ * set destination to image file
+ * jpeg_start_compress(cinfo, FALSE);
+ * write data...
+ * jpeg_finish_compress(cinfo);
+ *
+ * jpeg_write_tables has the side effect of marking all tables written
+ * (same as jpeg_suppress_tables(..., TRUE)). Thus a subsequent start_compress
+ * will not re-emit the tables unless it is passed write_all_tables=TRUE.
+ */
+
+GLOBAL(void)
+jpeg_write_tables (j_compress_ptr cinfo)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Initialize the marker writer ... bit of a crock to do it here. */
+ jinit_marker_writer(cinfo);
+ /* Write them tables! */
+ (*cinfo->marker->write_tables_only) (cinfo);
+ /* And clean up. */
+ (*cinfo->dest->term_destination) (cinfo);
+ /*
+ * In library releases up through v6a, we called jpeg_abort() here to free
+ * any working memory allocated by the destination manager and marker
+ * writer. Some applications had a problem with that: they allocated space
+ * of their own from the library memory manager, and didn't want it to go
+ * away during write_tables. So now we do nothing. This will cause a
+ * memory leak if an app calls write_tables repeatedly without doing a full
+ * compression cycle or otherwise resetting the JPEG object. However, that
+ * seems less bad than unexpectedly freeing memory in the normal case.
+ * An app that prefers the old behavior can call jpeg_abort for itself after
+ * each call to jpeg_write_tables().
+ */
+}
diff --git a/Source/LibJPEG/jcapistd.c b/Source/LibJPEG/jcapistd.c
new file mode 100644
index 0000000..c0320b1
--- /dev/null
+++ b/Source/LibJPEG/jcapistd.c
@@ -0,0 +1,161 @@
+/*
+ * jcapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the compression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-compression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_compress, it will end up linking in the entire compressor.
+ * We thus must separate this file from jcapimin.c to avoid linking the
+ * whole compression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Compression initialization.
+ * Before calling this, all parameters and a data destination must be set up.
+ *
+ * We require a write_all_tables parameter as a failsafe check when writing
+ * multiple datastreams from the same compression object. Since prior runs
+ * will have left all the tables marked sent_table=TRUE, a subsequent run
+ * would emit an abbreviated stream (no tables) by default. This may be what
+ * is wanted, but for safety's sake it should not be the default behavior:
+ * programmers should have to make a deliberate choice to emit abbreviated
+ * images. Therefore the documentation and examples should encourage people
+ * to pass write_all_tables=TRUE; then it will take active thought to do the
+ * wrong thing.
+ */
+
+GLOBAL(void)
+jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (write_all_tables)
+ jpeg_suppress_tables(cinfo, FALSE); /* mark all tables to be written */
+
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ jinit_compress_master(cinfo);
+ /* Set up for the first pass */
+ (*cinfo->master->prepare_for_pass) (cinfo);
+ /* Ready for application to drive first pass through jpeg_write_scanlines
+ * or jpeg_write_raw_data.
+ */
+ cinfo->next_scanline = 0;
+ cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING);
+}
+
+
+/*
+ * Write some scanlines of data to the JPEG compressor.
+ *
+ * The return value will be the number of lines actually written.
+ * This should be less than the supplied num_lines only in case that
+ * the data destination module has requested suspension of the compressor,
+ * or if more than image_height scanlines are passed in.
+ *
+ * Note: we warn about excess calls to jpeg_write_scanlines() since
+ * this likely signals an application programmer error. However,
+ * excess scanlines passed in the last valid call are *silently* ignored,
+ * so that the application need not adjust num_lines for end-of-image
+ * when using a multiple-scanline buffer.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION num_lines)
+{
+ JDIMENSION row_ctr, rows_left;
+
+ if (cinfo->global_state != CSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height)
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_scanlines. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_scanlines.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Ignore any extra scanlines at bottom of image. */
+ rows_left = cinfo->image_height - cinfo->next_scanline;
+ if (num_lines > rows_left)
+ num_lines = rows_left;
+
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines);
+ cinfo->next_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to write raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION num_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != CSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->next_scanline >= cinfo->image_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->next_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->image_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Give master control module another chance if this is first call to
+ * jpeg_write_raw_data. This lets output of the frame/scan headers be
+ * delayed so that application can write COM, etc, markers between
+ * jpeg_start_compress and jpeg_write_raw_data.
+ */
+ if (cinfo->master->call_pass_startup)
+ (*cinfo->master->pass_startup) (cinfo);
+
+ /* Verify that at least one iMCU row has been passed. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE;
+ if (num_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Directly compress the row. */
+ if (! (*cinfo->coef->compress_data) (cinfo, data)) {
+ /* If compressor did not consume the whole row, suspend processing. */
+ return 0;
+ }
+
+ /* OK, we processed one iMCU row. */
+ cinfo->next_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
diff --git a/Source/LibJPEG/jcarith.c b/Source/LibJPEG/jcarith.c
new file mode 100644
index 0000000..945a817
--- /dev/null
+++ b/Source/LibJPEG/jcarith.c
@@ -0,0 +1,921 @@
+/*
+ * jcarith.c
+ *
+ * Developed 1997 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains portable arithmetic entropy encoding routines for JPEG
+ * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ *
+ * Both sequential and progressive modes are supported in this single module.
+ *
+ * Suspension is not currently supported in this module.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Expanded entropy encoder object for arithmetic encoding. */
+
+typedef struct {
+ struct jpeg_entropy_encoder pub; /* public fields */
+
+ INT32 c; /* C register, base of coding interval, layout as in sec. D.1.3 */
+ INT32 a; /* A register, normalized size of coding interval */
+ INT32 sc; /* counter for stacked 0xFF values which might overflow */
+ INT32 zc; /* counter for pending 0x00 output values which might *
+ * be discarded at the end ("Pacman" termination) */
+ int ct; /* bit shift counter, determines when next byte will be written */
+ int buffer; /* buffer for most recent output byte != 0xFF */
+
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+ int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */
+
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Pointers to statistics areas (these workspaces have image lifespan) */
+ unsigned char * dc_stats[NUM_ARITH_TBLS];
+ unsigned char * ac_stats[NUM_ARITH_TBLS];
+} arith_entropy_encoder;
+
+typedef arith_entropy_encoder * arith_entropy_ptr;
+
+/* The following two definitions specify the allocation chunk size
+ * for the statistics area.
+ * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least
+ * 49 statistics bins for DC, and 245 statistics bins for AC coding.
+ * Note that we use one additional AC bin for codings with fixed
+ * probability (0.5), thus the minimum number for AC is 246.
+ *
+ * We use a compact representation with 1 byte per statistics bin,
+ * thus the numbers directly represent byte sizes.
+ * This 1 byte per statistics bin contains the meaning of the MPS
+ * (more probable symbol) in the highest bit (mask 0x80), and the
+ * index into the probability estimation state machine table
+ * in the lower bits (mask 0x7F).
+ */
+
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
+
+/* NOTE: Uncomment the following #define if you want to use the
+ * given formula for calculating the AC conditioning parameter Kx
+ * for spectral selection progressive coding in section G.1.3.2
+ * of the spec (Kx = Kmin + SRL (8 + Se - Kmin) 4).
+ * Although the spec and P&M authors claim that this "has proven
+ * to give good results for 8 bit precision samples", I'm not
+ * convinced yet that this is really beneficial.
+ * Early tests gave only very marginal compression enhancements
+ * (a few - around 5 or so - bytes even for very large files),
+ * which would turn out rather negative if we'd suppress the
+ * DAC (Define Arithmetic Conditioning) marker segments for
+ * the default parameters in the future.
+ * Note that currently the marker writing module emits 12-byte
+ * DAC segments for a full-component scan in a color image.
+ * This is not worth worrying about IMHO. However, since the
+ * spec defines the default values to be used if the tables
+ * are omitted (unlike Huffman tables, which are required
+ * anyway), one might optimize this behaviour in the future,
+ * and then it would be disadvantageous to use custom tables if
+ * they don't provide sufficient gain to exceed the DAC size.
+ *
+ * On the other hand, I'd consider it as a reasonable result
+ * that the conditioning has no significant influence on the
+ * compression performance. This means that the basic
+ * statistical model is already rather stable.
+ *
+ * Thus, at the moment, we use the default conditioning values
+ * anyway, and do not use the custom formula.
+ *
+#define CALCULATE_SPECTRAL_CONDITIONING
+ */
+
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
+ * We assume that int right shift is unsigned if INT32 right shift is,
+ * which should be safe.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS int ishift_temp;
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+LOCAL(void)
+emit_byte (int val, j_compress_ptr cinfo)
+/* Write next output byte; we do not support suspension in this module. */
+{
+ struct jpeg_destination_mgr * dest = cinfo->dest;
+
+ *dest->next_output_byte++ = (JOCTET) val;
+ if (--dest->free_in_buffer == 0)
+ if (! (*dest->empty_output_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+}
+
+
+/*
+ * Finish up at the end of an arithmetic-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass (j_compress_ptr cinfo)
+{
+ arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ INT32 temp;
+
+ /* Section D.1.8: Termination of encoding */
+
+ /* Find the e->c in the coding interval with the largest
+ * number of trailing zero bits */
+ if ((temp = (e->a - 1 + e->c) & 0xFFFF0000L) < e->c)
+ e->c = temp + 0x8000L;
+ else
+ e->c = temp;
+ /* Send remaining bytes to output */
+ e->c <<= e->ct;
+ if (e->c & 0xF8000000L) {
+ /* One final overflow has to be handled */
+ if (e->buffer >= 0) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ emit_byte(e->buffer + 1, cinfo);
+ if (e->buffer + 1 == 0xFF)
+ emit_byte(0x00, cinfo);
+ }
+ e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */
+ e->sc = 0;
+ } else {
+ if (e->buffer == 0)
+ ++e->zc;
+ else if (e->buffer >= 0) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ emit_byte(e->buffer, cinfo);
+ }
+ if (e->sc) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ do {
+ emit_byte(0xFF, cinfo);
+ emit_byte(0x00, cinfo);
+ } while (--e->sc);
+ }
+ }
+ /* Output final bytes only if they are not 0x00 */
+ if (e->c & 0x7FFF800L) {
+ if (e->zc) /* output final pending zero bytes */
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ emit_byte((e->c >> 19) & 0xFF, cinfo);
+ if (((e->c >> 19) & 0xFF) == 0xFF)
+ emit_byte(0x00, cinfo);
+ if (e->c & 0x7F800L) {
+ emit_byte((e->c >> 11) & 0xFF, cinfo);
+ if (((e->c >> 11) & 0xFF) == 0xFF)
+ emit_byte(0x00, cinfo);
+ }
+ }
+}
+
+
+/*
+ * The core arithmetic encoding routine (common in JPEG and JBIG).
+ * This needs to go as fast as possible.
+ * Machine-dependent optimization facilities
+ * are not utilized in this portable implementation.
+ * However, this code should be fairly efficient and
+ * may be a good base for further optimizations anyway.
+ *
+ * Parameter 'val' to be encoded may be 0 or 1 (binary decision).
+ *
+ * Note: I've added full "Pacman" termination support to the
+ * byte output routines, which is equivalent to the optional
+ * Discard_final_zeros procedure (Figure D.15) in the spec.
+ * Thus, we always produce the shortest possible output
+ * stream compliant to the spec (no trailing zero bytes,
+ * except for FF stuffing).
+ *
+ * I've also introduced a new scheme for accessing
+ * the probability estimation state machine table,
+ * derived from Markus Kuhn's JBIG implementation.
+ */
+
+LOCAL(void)
+arith_encode (j_compress_ptr cinfo, unsigned char *st, int val)
+{
+ extern const INT32 jaritab[];
+ register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register unsigned char nl, nm;
+ register INT32 qe, temp;
+ register int sv;
+
+ /* Fetch values from our compact representation of Table D.2:
+ * Qe values and probability estimation state machine
+ */
+ sv = *st;
+ qe = jaritab[sv & 0x7F]; /* => Qe_Value */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+
+ /* Encode & estimation procedures per sections D.1.4 & D.1.5 */
+ e->a -= qe;
+ if (val != (sv >> 7)) {
+ /* Encode the less probable symbol */
+ if (e->a >= qe) {
+ /* If the interval size (qe) for the less probable symbol (LPS)
+ * is larger than the interval size for the MPS, then exchange
+ * the two symbols for coding efficiency, otherwise code the LPS
+ * as usual: */
+ e->c += e->a;
+ e->a = qe;
+ }
+ *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */
+ } else {
+ /* Encode the more probable symbol */
+ if (e->a >= 0x8000L)
+ return; /* A >= 0x8000 -> ready, no renormalization required */
+ if (e->a < qe) {
+ /* If the interval size (qe) for the less probable symbol (LPS)
+ * is larger than the interval size for the MPS, then exchange
+ * the two symbols for coding efficiency: */
+ e->c += e->a;
+ e->a = qe;
+ }
+ *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */
+ }
+
+ /* Renormalization & data output per section D.1.6 */
+ do {
+ e->a <<= 1;
+ e->c <<= 1;
+ if (--e->ct == 0) {
+ /* Another byte is ready for output */
+ temp = e->c >> 19;
+ if (temp > 0xFF) {
+ /* Handle overflow over all stacked 0xFF bytes */
+ if (e->buffer >= 0) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ emit_byte(e->buffer + 1, cinfo);
+ if (e->buffer + 1 == 0xFF)
+ emit_byte(0x00, cinfo);
+ }
+ e->zc += e->sc; /* carry-over converts stacked 0xFF bytes to 0x00 */
+ e->sc = 0;
+ /* Note: The 3 spacer bits in the C register guarantee
+ * that the new buffer byte can't be 0xFF here
+ * (see page 160 in the P&M JPEG book). */
+ e->buffer = temp & 0xFF; /* new output byte, might overflow later */
+ } else if (temp == 0xFF) {
+ ++e->sc; /* stack 0xFF byte (which might overflow later) */
+ } else {
+ /* Output all stacked 0xFF bytes, they will not overflow any more */
+ if (e->buffer == 0)
+ ++e->zc;
+ else if (e->buffer >= 0) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ emit_byte(e->buffer, cinfo);
+ }
+ if (e->sc) {
+ if (e->zc)
+ do emit_byte(0x00, cinfo);
+ while (--e->zc);
+ do {
+ emit_byte(0xFF, cinfo);
+ emit_byte(0x00, cinfo);
+ } while (--e->sc);
+ }
+ e->buffer = temp & 0xFF; /* new output byte (can still overflow) */
+ }
+ e->c &= 0x7FFFFL;
+ e->ct += 8;
+ }
+ } while (e->a < 0x8000L);
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(void)
+emit_restart (j_compress_ptr cinfo, int restart_num)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ int ci;
+ jpeg_component_info * compptr;
+
+ finish_pass(cinfo);
+
+ emit_byte(0xFF, cinfo);
+ emit_byte(JPEG_RST0 + restart_num, cinfo);
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Re-initialize statistics areas */
+ if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+ MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS);
+ /* Reset DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ entropy->dc_context[ci] = 0;
+ }
+ if (cinfo->progressive_mode == 0 || cinfo->Ss) {
+ MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS);
+ }
+ }
+
+ /* Reset arithmetic encoding variables */
+ entropy->c = 0;
+ entropy->a = 0x10000L;
+ entropy->sc = 0;
+ entropy->zc = 0;
+ entropy->ct = 11;
+ entropy->buffer = -1; /* empty */
+}
+
+
+/*
+ * MCU encoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ unsigned char *st;
+ int blkn, ci, tbl;
+ int v, v2, m;
+ ISHIFT_TEMPS
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ emit_restart(cinfo, entropy->next_restart_num);
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ tbl = cinfo->cur_comp_info[ci]->dc_tbl_no;
+
+ /* Compute the DC value after the required point transform by Al.
+ * This is simply an arithmetic right shift.
+ */
+ m = IRIGHT_SHIFT((int) ((*block)[0]), cinfo->Al);
+
+ /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */
+
+ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */
+ st = entropy->dc_stats[tbl] + entropy->dc_context[ci];
+
+ /* Figure F.4: Encode_DC_DIFF */
+ if ((v = m - entropy->last_dc_val[ci]) == 0) {
+ arith_encode(cinfo, st, 0);
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ } else {
+ entropy->last_dc_val[ci] = m;
+ arith_encode(cinfo, st, 1);
+ /* Figure F.6: Encoding nonzero value v */
+ /* Figure F.7: Encoding the sign of v */
+ if (v > 0) {
+ arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */
+ st += 2; /* Table F.4: SP = S0 + 2 */
+ entropy->dc_context[ci] = 4; /* small positive diff category */
+ } else {
+ v = -v;
+ arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */
+ st += 3; /* Table F.4: SN = S0 + 3 */
+ entropy->dc_context[ci] = 8; /* small negative diff category */
+ }
+ /* Figure F.8: Encoding the magnitude category of v */
+ m = 0;
+ if (v -= 1) {
+ arith_encode(cinfo, st, 1);
+ m = 1;
+ v2 = v;
+ st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
+ while (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st += 1;
+ }
+ }
+ arith_encode(cinfo, st, 0);
+ /* Section F.1.4.4.1.2: Establish dc_context conditioning category */
+ if (m < (int) (((INT32) 1 << cinfo->arith_dc_L[tbl]) >> 1))
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ else if (m > (int) (((INT32) 1 << cinfo->arith_dc_U[tbl]) >> 1))
+ entropy->dc_context[ci] += 8; /* large diff category */
+ /* Figure F.9: Encoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ arith_encode(cinfo, st, (m & v) ? 1 : 0);
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ unsigned char *st;
+ int tbl, k, ke;
+ int v, v2, m;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ emit_restart(cinfo, entropy->next_restart_num);
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+ tbl = cinfo->cur_comp_info[0]->ac_tbl_no;
+
+ /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */
+
+ /* Establish EOB (end-of-block) index */
+ for (ke = cinfo->Se + 1; ke > 1; ke--)
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value.
+ */
+ if ((v = (*block)[jpeg_natural_order[ke - 1]]) >= 0) {
+ if (v >>= cinfo->Al) break;
+ } else {
+ v = -v;
+ if (v >>= cinfo->Al) break;
+ }
+
+ /* Figure F.5: Encode_AC_Coefficients */
+ for (k = cinfo->Ss; k < ke; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ arith_encode(cinfo, st, 0); /* EOB decision */
+ entropy->ac_stats[tbl][245] = 0;
+ for (;;) {
+ if ((v = (*block)[jpeg_natural_order[k]]) >= 0) {
+ if (v >>= cinfo->Al) {
+ arith_encode(cinfo, st + 1, 1);
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 0);
+ break;
+ }
+ } else {
+ v = -v;
+ if (v >>= cinfo->Al) {
+ arith_encode(cinfo, st + 1, 1);
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 1);
+ break;
+ }
+ }
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ }
+ st += 2;
+ /* Figure F.8: Encoding the magnitude category of v */
+ m = 0;
+ if (v -= 1) {
+ arith_encode(cinfo, st, 1);
+ m = 1;
+ v2 = v;
+ if (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st = entropy->ac_stats[tbl] +
+ (k <= cinfo->arith_ac_K[tbl] ? 189 : 217);
+ while (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st += 1;
+ }
+ }
+ }
+ arith_encode(cinfo, st, 0);
+ /* Figure F.9: Encoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ arith_encode(cinfo, st, (m & v) ? 1 : 0);
+ }
+ /* Encode EOB decision only if k <= cinfo->Se */
+ if (k <= cinfo->Se) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ arith_encode(cinfo, st, 1);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for DC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ unsigned char st[4];
+ int Al, blkn;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ emit_restart(cinfo, entropy->next_restart_num);
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ Al = cinfo->Al;
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ st[0] = 0; /* use fixed probability estimation */
+ /* We simply emit the Al'th bit of the DC coefficient value. */
+ arith_encode(cinfo, st, (MCU_data[blkn][0][0] >> Al) & 1);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ unsigned char *st;
+ int tbl, k, ke, kex;
+ int v;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ emit_restart(cinfo, entropy->next_restart_num);
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+ tbl = cinfo->cur_comp_info[0]->ac_tbl_no;
+
+ /* Section G.1.3.3: Encoding of AC coefficients */
+
+ /* Establish EOB (end-of-block) index */
+ for (ke = cinfo->Se + 1; ke > 1; ke--)
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value.
+ */
+ if ((v = (*block)[jpeg_natural_order[ke - 1]]) >= 0) {
+ if (v >>= cinfo->Al) break;
+ } else {
+ v = -v;
+ if (v >>= cinfo->Al) break;
+ }
+
+ /* Establish EOBx (previous stage end-of-block) index */
+ for (kex = ke; kex > 1; kex--)
+ if ((v = (*block)[jpeg_natural_order[kex - 1]]) >= 0) {
+ if (v >>= cinfo->Ah) break;
+ } else {
+ v = -v;
+ if (v >>= cinfo->Ah) break;
+ }
+
+ /* Figure G.10: Encode_AC_Coefficients_SA */
+ for (k = cinfo->Ss; k < ke; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ if (k >= kex)
+ arith_encode(cinfo, st, 0); /* EOB decision */
+ entropy->ac_stats[tbl][245] = 0;
+ for (;;) {
+ if ((v = (*block)[jpeg_natural_order[k]]) >= 0) {
+ if (v >>= cinfo->Al) {
+ if (v >> 1) /* previously nonzero coef */
+ arith_encode(cinfo, st + 2, (v & 1));
+ else { /* newly nonzero coef */
+ arith_encode(cinfo, st + 1, 1);
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 0);
+ }
+ break;
+ }
+ } else {
+ v = -v;
+ if (v >>= cinfo->Al) {
+ if (v >> 1) /* previously nonzero coef */
+ arith_encode(cinfo, st + 2, (v & 1));
+ else { /* newly nonzero coef */
+ arith_encode(cinfo, st + 1, 1);
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 1);
+ }
+ break;
+ }
+ }
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ }
+ }
+ /* Encode EOB decision only if k <= cinfo->Se */
+ if (k <= cinfo->Se) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ arith_encode(cinfo, st, 1);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Encode and output one MCU's worth of arithmetic-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+encode_mcu (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ jpeg_component_info * compptr;
+ JBLOCKROW block;
+ unsigned char *st;
+ int blkn, ci, tbl, k, ke;
+ int v, v2, m;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ emit_restart(cinfo, entropy->next_restart_num);
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+
+ /* Sections F.1.4.1 & F.1.4.4.1: Encoding of DC coefficients */
+
+ tbl = compptr->dc_tbl_no;
+
+ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */
+ st = entropy->dc_stats[tbl] + entropy->dc_context[ci];
+
+ /* Figure F.4: Encode_DC_DIFF */
+ if ((v = (*block)[0] - entropy->last_dc_val[ci]) == 0) {
+ arith_encode(cinfo, st, 0);
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ } else {
+ entropy->last_dc_val[ci] = (*block)[0];
+ arith_encode(cinfo, st, 1);
+ /* Figure F.6: Encoding nonzero value v */
+ /* Figure F.7: Encoding the sign of v */
+ if (v > 0) {
+ arith_encode(cinfo, st + 1, 0); /* Table F.4: SS = S0 + 1 */
+ st += 2; /* Table F.4: SP = S0 + 2 */
+ entropy->dc_context[ci] = 4; /* small positive diff category */
+ } else {
+ v = -v;
+ arith_encode(cinfo, st + 1, 1); /* Table F.4: SS = S0 + 1 */
+ st += 3; /* Table F.4: SN = S0 + 3 */
+ entropy->dc_context[ci] = 8; /* small negative diff category */
+ }
+ /* Figure F.8: Encoding the magnitude category of v */
+ m = 0;
+ if (v -= 1) {
+ arith_encode(cinfo, st, 1);
+ m = 1;
+ v2 = v;
+ st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
+ while (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st += 1;
+ }
+ }
+ arith_encode(cinfo, st, 0);
+ /* Section F.1.4.4.1.2: Establish dc_context conditioning category */
+ if (m < (int) (((INT32) 1 << cinfo->arith_dc_L[tbl]) >> 1))
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ else if (m > (int) (((INT32) 1 << cinfo->arith_dc_U[tbl]) >> 1))
+ entropy->dc_context[ci] += 8; /* large diff category */
+ /* Figure F.9: Encoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ arith_encode(cinfo, st, (m & v) ? 1 : 0);
+ }
+
+ /* Sections F.1.4.2 & F.1.4.4.2: Encoding of AC coefficients */
+
+ tbl = compptr->ac_tbl_no;
+
+ /* Establish EOB (end-of-block) index */
+ for (ke = DCTSIZE2; ke > 1; ke--)
+ if ((*block)[jpeg_natural_order[ke - 1]]) break;
+
+ /* Figure F.5: Encode_AC_Coefficients */
+ for (k = 1; k < ke; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ arith_encode(cinfo, st, 0); /* EOB decision */
+ while ((v = (*block)[jpeg_natural_order[k]]) == 0) {
+ arith_encode(cinfo, st + 1, 0); st += 3; k++;
+ }
+ arith_encode(cinfo, st + 1, 1);
+ /* Figure F.6: Encoding nonzero value v */
+ /* Figure F.7: Encoding the sign of v */
+ entropy->ac_stats[tbl][245] = 0;
+ if (v > 0) {
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 0);
+ } else {
+ v = -v;
+ arith_encode(cinfo, entropy->ac_stats[tbl] + 245, 1);
+ }
+ st += 2;
+ /* Figure F.8: Encoding the magnitude category of v */
+ m = 0;
+ if (v -= 1) {
+ arith_encode(cinfo, st, 1);
+ m = 1;
+ v2 = v;
+ if (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st = entropy->ac_stats[tbl] +
+ (k <= cinfo->arith_ac_K[tbl] ? 189 : 217);
+ while (v2 >>= 1) {
+ arith_encode(cinfo, st, 1);
+ m <<= 1;
+ st += 1;
+ }
+ }
+ }
+ arith_encode(cinfo, st, 0);
+ /* Figure F.9: Encoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ arith_encode(cinfo, st, (m & v) ? 1 : 0);
+ }
+ /* Encode EOB decision only if k < DCTSIZE2 */
+ if (k < DCTSIZE2) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ arith_encode(cinfo, st, 1);
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Initialize for an arithmetic-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+
+ if (gather_statistics)
+ /* Make sure to avoid that in the master control logic!
+ * We are fully adaptive here and need no extra
+ * statistics gathering pass!
+ */
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+
+ /* We assume jcmaster.c already validated the progressive scan parameters. */
+
+ /* Select execution routines */
+ if (cinfo->progressive_mode) {
+ if (cinfo->Ah == 0) {
+ if (cinfo->Ss == 0)
+ entropy->pub.encode_mcu = encode_mcu_DC_first;
+ else
+ entropy->pub.encode_mcu = encode_mcu_AC_first;
+ } else {
+ if (cinfo->Ss == 0)
+ entropy->pub.encode_mcu = encode_mcu_DC_refine;
+ else
+ entropy->pub.encode_mcu = encode_mcu_AC_refine;
+ }
+ } else
+ entropy->pub.encode_mcu = encode_mcu;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Allocate & initialize requested statistics areas */
+ if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+ tbl = compptr->dc_tbl_no;
+ if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
+ ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
+ if (entropy->dc_stats[tbl] == NULL)
+ entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
+ /* Initialize DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ entropy->dc_context[ci] = 0;
+ }
+ if (cinfo->progressive_mode == 0 || cinfo->Ss) {
+ tbl = compptr->ac_tbl_no;
+ if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
+ ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
+ if (entropy->ac_stats[tbl] == NULL)
+ entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
+#ifdef CALCULATE_SPECTRAL_CONDITIONING
+ if (cinfo->progressive_mode)
+ /* Section G.1.3.2: Set appropriate arithmetic conditioning value Kx */
+ cinfo->arith_ac_K[tbl] = cinfo->Ss + ((8 + cinfo->Se - cinfo->Ss) >> 4);
+#endif
+ }
+ }
+
+ /* Initialize arithmetic encoding variables */
+ entropy->c = 0;
+ entropy->a = 0x10000L;
+ entropy->sc = 0;
+ entropy->zc = 0;
+ entropy->ct = 11;
+ entropy->buffer = -1; /* empty */
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/*
+ * Module initialization routine for arithmetic entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_arith_encoder (j_compress_ptr cinfo)
+{
+ arith_entropy_ptr entropy;
+ int i;
+
+ entropy = (arith_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(arith_entropy_encoder));
+ cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ entropy->pub.start_pass = start_pass;
+ entropy->pub.finish_pass = finish_pass;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ entropy->dc_stats[i] = NULL;
+ entropy->ac_stats[i] = NULL;
+ }
+}
diff --git a/Source/LibJPEG/jccoefct.c b/Source/LibJPEG/jccoefct.c
new file mode 100644
index 0000000..d775313
--- /dev/null
+++ b/Source/LibJPEG/jccoefct.c
@@ -0,0 +1,453 @@
+/*
+ * jccoefct.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for compression.
+ * This controller is the top level of the JPEG compressor proper.
+ * The coefficient buffer lies between forward-DCT and entropy encoding steps.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* We use a full-image coefficient buffer when doing Huffman optimization,
+ * and also for writing multiple-scan JPEG files. In all cases, the DCT
+ * step is run during the first pass, and subsequent passes need only read
+ * the buffered coefficients.
+ */
+#ifdef ENTROPY_OPT_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#else
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+#define FULL_COEF_BUFFER_SUPPORTED
+#endif
+#endif
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_coef_controller pub; /* public fields */
+
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* For single-pass compression, it's sufficient to buffer just one MCU
+ * (although this may prove a bit slow in practice). We allocate a
+ * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each
+ * MCU constructed and sent. (On 80x86, the workspace is FAR even though
+ * it's not really very big; this is to keep the module interfaces unchanged
+ * when a large coefficient buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays.
+ */
+ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
+
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+
+/* Forward declarations */
+METHODDEF(boolean) compress_data
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+METHODDEF(boolean) compress_first_pass
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+METHODDEF(boolean) compress_output
+ JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (coef->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_data;
+ break;
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_first_pass;
+ break;
+ case JBUF_CRANK_DEST:
+ if (coef->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ coef->pub.compress_data = compress_output;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data in the single-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(boolean)
+compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, bi, ci, yindex, yoffset, blockcnt;
+ JDIMENSION ypos, xpos;
+ jpeg_component_info *compptr;
+ forward_DCT_ptr forward_DCT;
+
+ /* Loop to write as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Determine where data comes from in input_buf and do the DCT thing.
+ * Each call on forward_DCT processes a horizontal row of DCT blocks
+ * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks
+ * sequentially. Dummy blocks at the right or bottom edge are filled in
+ * specially. The data in them does not matter for image reconstruction,
+ * so we fill them with values that will encode to the smallest amount of
+ * data, viz: all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. (Thanks to Thomas Kinsman for this idea.)
+ */
+ blkn = 0;
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ forward_DCT = cinfo->fdct->forward_DCT[compptr->component_index];
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ xpos = MCU_col_num * compptr->MCU_sample_width;
+ ypos = yoffset * compptr->DCT_v_scaled_size;
+ /* ypos == (yoffset+yindex) * DCTSIZE */
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ (*forward_DCT) (cinfo, compptr,
+ input_buf[compptr->component_index],
+ coef->MCU_buffer[blkn],
+ ypos, xpos, (JDIMENSION) blockcnt);
+ if (blockcnt < compptr->MCU_width) {
+ /* Create some dummy blocks at the right edge of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt],
+ (compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK));
+ for (bi = blockcnt; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0];
+ }
+ }
+ } else {
+ /* Create a row of dummy blocks at the bottom of the image. */
+ jzero_far((void FAR *) coef->MCU_buffer[blkn],
+ compptr->MCU_width * SIZEOF(JBLOCK));
+ for (bi = 0; bi < compptr->MCU_width; bi++) {
+ coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0];
+ }
+ }
+ blkn += compptr->MCU_width;
+ ypos += compptr->DCT_v_scaled_size;
+ }
+ }
+ /* Try to write the MCU. In event of a suspension failure, we will
+ * re-DCT the MCU on restart (a bit inefficient, could be fixed...)
+ */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+
+/*
+ * Process some data in the first pass of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the image.
+ * This amount of data is read from the source buffer, DCT'd and quantized,
+ * and saved into the virtual arrays. We also generate suitable dummy blocks
+ * as needed at the right and lower edges. (The dummy blocks are constructed
+ * in the virtual arrays, which have been padded appropriately.) This makes
+ * it possible for subsequent passes not to worry about real vs. dummy blocks.
+ *
+ * We must also emit the data to the entropy encoder. This is conveniently
+ * done by calling compress_output() after we've loaded the current strip
+ * of the virtual arrays.
+ *
+ * NB: input_buf contains a plane for each component in image. All
+ * components are DCT'd and loaded into the virtual arrays in this pass.
+ * However, it may be that only a subset of the components are emitted to
+ * the entropy encoder during this first pass; be careful about looking
+ * at the scan-dependent variables (MCU dimensions, etc).
+ */
+
+METHODDEF(boolean)
+compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION blocks_across, MCUs_across, MCUindex;
+ int bi, ci, h_samp_factor, block_row, block_rows, ndummy;
+ JCOEF lastDC;
+ jpeg_component_info *compptr;
+ JBLOCKARRAY buffer;
+ JBLOCKROW thisblockrow, lastblockrow;
+ forward_DCT_ptr forward_DCT;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (coef->iMCU_row_num < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here, since may not be set! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ blocks_across = compptr->width_in_blocks;
+ h_samp_factor = compptr->h_samp_factor;
+ /* Count number of dummy blocks to be added at the right margin. */
+ ndummy = (int) (blocks_across % h_samp_factor);
+ if (ndummy > 0)
+ ndummy = h_samp_factor - ndummy;
+ forward_DCT = cinfo->fdct->forward_DCT[ci];
+ /* Perform DCT for all non-dummy blocks in this iMCU row. Each call
+ * on forward_DCT processes a complete horizontal row of DCT blocks.
+ */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ thisblockrow = buffer[block_row];
+ (*forward_DCT) (cinfo, compptr, input_buf[ci], thisblockrow,
+ (JDIMENSION) (block_row * compptr->DCT_v_scaled_size),
+ (JDIMENSION) 0, blocks_across);
+ if (ndummy > 0) {
+ /* Create dummy blocks at the right edge of the image. */
+ thisblockrow += blocks_across; /* => first dummy block */
+ jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK));
+ lastDC = thisblockrow[-1][0];
+ for (bi = 0; bi < ndummy; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ }
+ }
+ /* If at end of image, create dummy block rows as needed.
+ * The tricky part here is that within each MCU, we want the DC values
+ * of the dummy blocks to match the last real block's DC value.
+ * This squeezes a few more bytes out of the resulting file...
+ */
+ if (coef->iMCU_row_num == last_iMCU_row) {
+ blocks_across += ndummy; /* include lower right corner */
+ MCUs_across = blocks_across / h_samp_factor;
+ for (block_row = block_rows; block_row < compptr->v_samp_factor;
+ block_row++) {
+ thisblockrow = buffer[block_row];
+ lastblockrow = buffer[block_row-1];
+ jzero_far((void FAR *) thisblockrow,
+ (size_t) (blocks_across * SIZEOF(JBLOCK)));
+ for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) {
+ lastDC = lastblockrow[h_samp_factor-1][0];
+ for (bi = 0; bi < h_samp_factor; bi++) {
+ thisblockrow[bi][0] = lastDC;
+ }
+ thisblockrow += h_samp_factor; /* advance to next MCU in row */
+ lastblockrow += h_samp_factor;
+ }
+ }
+ }
+ }
+ /* NB: compress_output will increment iMCU_row_num if successful.
+ * A suspension return will result in redoing all the work above next time.
+ */
+
+ /* Emit data to the entropy encoder, sharing code with subsequent passes */
+ return compress_output(cinfo, input_buf);
+}
+
+
+/*
+ * Process some data in subsequent passes of a multi-pass case.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan.
+ * NB: during first pass, this is safe only because the buffers will
+ * already be aligned properly, so jmemmgr.c won't need to do any I/O.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+#endif /* FULL_COEF_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_coef_ptr coef;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ coef->pub.start_pass = start_pass_coef;
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef FULL_COEF_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ int ci;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) compptr->v_samp_factor);
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ coef->whole_image[0] = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/Source/LibJPEG/jccolor.c b/Source/LibJPEG/jccolor.c
new file mode 100644
index 0000000..0a8a4b5
--- /dev/null
+++ b/Source/LibJPEG/jccolor.c
@@ -0,0 +1,459 @@
+/*
+ * jccolor.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_converter pub; /* public fields */
+
+ /* Private state for RGB->YCC conversion */
+ INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
+} my_color_converter;
+
+typedef my_color_converter * my_cconvert_ptr;
+
+
+/**************** RGB -> YCbCr conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
+ * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
+ * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
+ * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
+ * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
+ * were not represented exactly. Now we sacrifice exact representation of
+ * maximum red and maximum blue in order to get exact grayscales.
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times R,G,B for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
+ * in the tables to save adding them separately in the inner loop.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+/* We allocate one big table and divide it up into eight parts, instead of
+ * doing eight alloc_small requests. This lets us use a single table base
+ * address, which can be held in a register in the inner loops on many
+ * machines (more than can hold all eight addresses, anyway).
+ */
+
+#define R_Y_OFF 0 /* offset to R => Y section */
+#define G_Y_OFF (1*(MAXJSAMPLE+1)) /* offset to G => Y section */
+#define B_Y_OFF (2*(MAXJSAMPLE+1)) /* etc. */
+#define R_CB_OFF (3*(MAXJSAMPLE+1))
+#define G_CB_OFF (4*(MAXJSAMPLE+1))
+#define B_CB_OFF (5*(MAXJSAMPLE+1))
+#define R_CR_OFF B_CB_OFF /* B=>Cb, R=>Cr are the same */
+#define G_CR_OFF (6*(MAXJSAMPLE+1))
+#define B_CR_OFF (7*(MAXJSAMPLE+1))
+#define TABLE_SIZE (8*(MAXJSAMPLE+1))
+
+
+/*
+ * Initialize for RGB->YCC colorspace conversion.
+ */
+
+METHODDEF(void)
+rgb_ycc_start (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ INT32 * rgb_ycc_tab;
+ INT32 i;
+
+ /* Allocate and fill in the conversion tables. */
+ cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (TABLE_SIZE * SIZEOF(INT32)));
+
+ for (i = 0; i <= MAXJSAMPLE; i++) {
+ rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
+ rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
+ rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
+ rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
+ rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
+ /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
+ * This ensures that the maximum output will round to MAXJSAMPLE
+ * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
+ */
+ rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+/* B=>Cb and R=>Cr tables are the same
+ rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
+*/
+ rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
+ rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ *
+ * Note that we change from the application's interleaved-pixel format
+ * to our internal noninterleaved, one-plane-per-component format.
+ * The input buffer is therefore three times as wide as the output buffer.
+ *
+ * A starting row offset is provided only for the output buffer. The caller
+ * can easily adjust the passed input_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+rgb_ycc_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/**************** Cases other than RGB -> YCbCr **************/
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles RGB->grayscale conversion, which is the same
+ * as the RGB->Y portion of RGB->YCbCr.
+ * We assume rgb_ycc_start has been called (we only use the Y tables).
+ */
+
+METHODDEF(void)
+rgb_gray_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = GETJSAMPLE(inptr[RGB_RED]);
+ g = GETJSAMPLE(inptr[RGB_GREEN]);
+ b = GETJSAMPLE(inptr[RGB_BLUE]);
+ inptr += RGB_PIXELSIZE;
+ /* Y */
+ outptr[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles Adobe-style CMYK->YCCK conversion,
+ * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume rgb_ycc_start has been called.
+ */
+
+METHODDEF(void)
+cmyk_ycck_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int r, g, b;
+ register INT32 * ctab = cconvert->rgb_ycc_tab;
+ register JSAMPROW inptr;
+ register JSAMPROW outptr0, outptr1, outptr2, outptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr0 = output_buf[0][output_row];
+ outptr1 = output_buf[1][output_row];
+ outptr2 = output_buf[2][output_row];
+ outptr3 = output_buf[3][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
+ g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
+ b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
+ /* K passes through as-is */
+ outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
+ inptr += 4;
+ /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
+ * must be too; we do not need an explicit range-limiting operation.
+ * Hence the value being shifted is never negative, and we don't
+ * need the general RIGHT_SHIFT macro.
+ */
+ /* Y */
+ outptr0[col] = (JSAMPLE)
+ ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+ >> SCALEBITS);
+ /* Cb */
+ outptr1[col] = (JSAMPLE)
+ ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
+ >> SCALEBITS);
+ /* Cr */
+ outptr2[col] = (JSAMPLE)
+ ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
+ >> SCALEBITS);
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles grayscale output with no conversion.
+ * The source can be either plain grayscale or YCbCr (since Y == gray).
+ */
+
+METHODDEF(void)
+grayscale_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->image_width;
+ int instride = cinfo->input_components;
+
+ while (--num_rows >= 0) {
+ inptr = *input_buf++;
+ outptr = output_buf[0][output_row];
+ output_row++;
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
+ inptr += instride;
+ }
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the JPEG colorspace.
+ * This version handles multi-component colorspaces without conversion.
+ * We assume input_components == num_components.
+ */
+
+METHODDEF(void)
+null_convert (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows)
+{
+ register JSAMPROW inptr;
+ register JSAMPROW outptr;
+ register JDIMENSION col;
+ register int ci;
+ int nc = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->image_width;
+
+ while (--num_rows >= 0) {
+ /* It seems fastest to make a separate pass for each component. */
+ for (ci = 0; ci < nc; ci++) {
+ inptr = *input_buf;
+ outptr = output_buf[ci][output_row];
+ for (col = 0; col < num_cols; col++) {
+ outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
+ inptr += nc;
+ }
+ }
+ input_buf++;
+ output_row++;
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+null_method (j_compress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for input colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_converter (j_compress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_converter));
+ cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
+ /* set start_pass to null method until we find out differently */
+ cconvert->pub.start_pass = null_method;
+
+ /* Make sure input_components agrees with in_color_space */
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->input_components != 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ if (cinfo->input_components != RGB_PIXELSIZE)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+#endif /* else share code with YCbCr */
+
+ case JCS_YCbCr:
+ if (cinfo->input_components != 3)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->input_components != 4)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->input_components < 1)
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ break;
+ }
+
+ /* Check num_components, set conversion method based on requested space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_GRAYSCALE)
+ cconvert->pub.color_convert = grayscale_convert;
+ else if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_gray_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = grayscale_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_RGB) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = rgb_ycc_convert;
+ } else if (cinfo->in_color_space == JCS_YCbCr)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ if (cinfo->in_color_space == JCS_CMYK) {
+ cconvert->pub.start_pass = rgb_ycc_start;
+ cconvert->pub.color_convert = cmyk_ycck_convert;
+ } else if (cinfo->in_color_space == JCS_YCCK)
+ cconvert->pub.color_convert = null_convert;
+ else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default: /* allow null conversion of JCS_UNKNOWN */
+ if (cinfo->jpeg_color_space != cinfo->in_color_space ||
+ cinfo->num_components != cinfo->input_components)
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ cconvert->pub.color_convert = null_convert;
+ break;
+ }
+}
diff --git a/Source/LibJPEG/jcdctmgr.c b/Source/LibJPEG/jcdctmgr.c
new file mode 100644
index 0000000..0bbdbb6
--- /dev/null
+++ b/Source/LibJPEG/jcdctmgr.c
@@ -0,0 +1,482 @@
+/*
+ * jcdctmgr.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the forward-DCT management logic.
+ * This code selects a particular DCT implementation to be used,
+ * and it performs related housekeeping chores including coefficient
+ * quantization.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ struct jpeg_forward_dct pub; /* public fields */
+
+ /* Pointer to the DCT routine actually in use */
+ forward_DCT_method_ptr do_dct[MAX_COMPONENTS];
+
+ /* The actual post-DCT divisors --- not identical to the quant table
+ * entries, because of scaling (especially for an unnormalized DCT).
+ * Each table is given in normal array order.
+ */
+ DCTELEM * divisors[NUM_QUANT_TBLS];
+
+#ifdef DCT_FLOAT_SUPPORTED
+ /* Same as above for the floating-point case. */
+ float_DCT_method_ptr do_float_dct[MAX_COMPONENTS];
+ FAST_FLOAT * float_divisors[NUM_QUANT_TBLS];
+#endif
+} my_fdct_controller;
+
+typedef my_fdct_controller * my_fdct_ptr;
+
+
+/* The current scaled-DCT routines require ISLOW-style divisor tables,
+ * so be sure to compile that code if either ISLOW or SCALING is requested.
+ */
+#ifdef DCT_ISLOW_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#else
+#ifdef DCT_SCALING_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#endif
+#endif
+
+
+/*
+ * Perform forward DCT on one or more blocks of a component.
+ *
+ * The input samples are taken from the sample_data[] array starting at
+ * position start_row/start_col, and moving to the right for any additional
+ * blocks. The quantized coefficients are returned in coef_blocks[].
+ */
+
+METHODDEF(void)
+forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for integer DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ forward_DCT_method_ptr do_dct = fdct->do_dct[compptr->component_index];
+ DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no];
+ DCTELEM workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) {
+ /* Perform the DCT */
+ (*do_dct) (workspace, sample_data, start_col);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register DCTELEM temp, qval;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ qval = divisors[i];
+ temp = workspace[i];
+ /* Divide the coefficient value by qval, ensuring proper rounding.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ *
+ * In most files, at least half of the output values will be zero
+ * (at default quantization settings, more like three-quarters...)
+ * so we should ensure that this case is fast. On many machines,
+ * a comparison is enough cheaper than a divide to make a special test
+ * a win. Since both inputs will be nonnegative, we need only test
+ * for a < b to discover whether a/b is 0.
+ * If your machine's division is fast enough, define FAST_DIVIDE.
+ */
+#ifdef FAST_DIVIDE
+#define DIVIDE_BY(a,b) a /= b
+#else
+#define DIVIDE_BY(a,b) if (a >= b) a /= b; else a = 0
+#endif
+ if (temp < 0) {
+ temp = -temp;
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ temp = -temp;
+ } else {
+ temp += qval>>1; /* for rounding */
+ DIVIDE_BY(temp, qval);
+ }
+ output_ptr[i] = (JCOEF) temp;
+ }
+ }
+ }
+}
+
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+METHODDEF(void)
+forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks)
+/* This version is used for floating-point DCT implementations. */
+{
+ /* This routine is heavily used, so it's worth coding it tightly. */
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ float_DCT_method_ptr do_dct = fdct->do_float_dct[compptr->component_index];
+ FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no];
+ FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */
+ JDIMENSION bi;
+
+ sample_data += start_row; /* fold in the vertical offset once */
+
+ for (bi = 0; bi < num_blocks; bi++, start_col += compptr->DCT_h_scaled_size) {
+ /* Perform the DCT */
+ (*do_dct) (workspace, sample_data, start_col);
+
+ /* Quantize/descale the coefficients, and store into coef_blocks[] */
+ { register FAST_FLOAT temp;
+ register int i;
+ register JCOEFPTR output_ptr = coef_blocks[bi];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* Apply the quantization and scaling factor */
+ temp = workspace[i] * divisors[i];
+ /* Round to nearest integer.
+ * Since C does not specify the direction of rounding for negative
+ * quotients, we have to force the dividend positive for portability.
+ * The maximum coefficient size is +-16K (for 12-bit data), so this
+ * code should work for either 16-bit or 32-bit ints.
+ */
+ output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384);
+ }
+ }
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
+
+
+/*
+ * Initialize for a processing pass.
+ * Verify that all referenced Q-tables are present, and set up
+ * the divisor table for each one.
+ * In the current implementation, DCT of all components is done during
+ * the first pass, even if only some components will be output in the
+ * first scan. Hence all components should be examined here.
+ */
+
+METHODDEF(void)
+start_pass_fdctmgr (j_compress_ptr cinfo)
+{
+ my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct;
+ int ci, qtblno, i;
+ jpeg_component_info *compptr;
+ int method = 0;
+ JQUANT_TBL * qtbl;
+ DCTELEM * dtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Select the proper DCT routine for this component's scaling */
+ switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) {
+#ifdef DCT_SCALING_SUPPORTED
+ case ((1 << 8) + 1):
+ fdct->do_dct[ci] = jpeg_fdct_1x1;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((2 << 8) + 2):
+ fdct->do_dct[ci] = jpeg_fdct_2x2;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((3 << 8) + 3):
+ fdct->do_dct[ci] = jpeg_fdct_3x3;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((4 << 8) + 4):
+ fdct->do_dct[ci] = jpeg_fdct_4x4;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((5 << 8) + 5):
+ fdct->do_dct[ci] = jpeg_fdct_5x5;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((6 << 8) + 6):
+ fdct->do_dct[ci] = jpeg_fdct_6x6;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((7 << 8) + 7):
+ fdct->do_dct[ci] = jpeg_fdct_7x7;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((9 << 8) + 9):
+ fdct->do_dct[ci] = jpeg_fdct_9x9;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((10 << 8) + 10):
+ fdct->do_dct[ci] = jpeg_fdct_10x10;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((11 << 8) + 11):
+ fdct->do_dct[ci] = jpeg_fdct_11x11;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((12 << 8) + 12):
+ fdct->do_dct[ci] = jpeg_fdct_12x12;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((13 << 8) + 13):
+ fdct->do_dct[ci] = jpeg_fdct_13x13;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((14 << 8) + 14):
+ fdct->do_dct[ci] = jpeg_fdct_14x14;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((15 << 8) + 15):
+ fdct->do_dct[ci] = jpeg_fdct_15x15;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((16 << 8) + 16):
+ fdct->do_dct[ci] = jpeg_fdct_16x16;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((16 << 8) + 8):
+ fdct->do_dct[ci] = jpeg_fdct_16x8;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((14 << 8) + 7):
+ fdct->do_dct[ci] = jpeg_fdct_14x7;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((12 << 8) + 6):
+ fdct->do_dct[ci] = jpeg_fdct_12x6;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((10 << 8) + 5):
+ fdct->do_dct[ci] = jpeg_fdct_10x5;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((8 << 8) + 4):
+ fdct->do_dct[ci] = jpeg_fdct_8x4;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((6 << 8) + 3):
+ fdct->do_dct[ci] = jpeg_fdct_6x3;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((4 << 8) + 2):
+ fdct->do_dct[ci] = jpeg_fdct_4x2;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((2 << 8) + 1):
+ fdct->do_dct[ci] = jpeg_fdct_2x1;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((8 << 8) + 16):
+ fdct->do_dct[ci] = jpeg_fdct_8x16;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((7 << 8) + 14):
+ fdct->do_dct[ci] = jpeg_fdct_7x14;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((6 << 8) + 12):
+ fdct->do_dct[ci] = jpeg_fdct_6x12;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((5 << 8) + 10):
+ fdct->do_dct[ci] = jpeg_fdct_5x10;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((4 << 8) + 8):
+ fdct->do_dct[ci] = jpeg_fdct_4x8;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((3 << 8) + 6):
+ fdct->do_dct[ci] = jpeg_fdct_3x6;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((2 << 8) + 4):
+ fdct->do_dct[ci] = jpeg_fdct_2x4;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+ case ((1 << 8) + 2):
+ fdct->do_dct[ci] = jpeg_fdct_1x2;
+ method = JDCT_ISLOW; /* jfdctint uses islow-style table */
+ break;
+#endif
+ case ((DCTSIZE << 8) + DCTSIZE):
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ fdct->do_dct[ci] = jpeg_fdct_islow;
+ method = JDCT_ISLOW;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ fdct->do_dct[ci] = jpeg_fdct_ifast;
+ method = JDCT_IFAST;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ fdct->do_float_dct[ci] = jpeg_fdct_float;
+ method = JDCT_FLOAT;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ break;
+ default:
+ ERREXIT2(cinfo, JERR_BAD_DCTSIZE,
+ compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size);
+ break;
+ }
+ qtblno = compptr->quant_tbl_no;
+ /* Make sure specified quantization table is present */
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ qtbl = cinfo->quant_tbl_ptrs[qtblno];
+ /* Compute divisors for this quant table */
+ /* We may do this more than once for same table, but it's not a big deal */
+ switch (method) {
+#ifdef PROVIDE_ISLOW_TABLES
+ case JDCT_ISLOW:
+ /* For LL&M IDCT method, divisors are equal to raw quantization
+ * coefficients multiplied by 8 (to counteract scaling).
+ */
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3;
+ }
+ fdct->pub.forward_DCT[ci] = forward_DCT;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ */
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ if (fdct->divisors[qtblno] == NULL) {
+ fdct->divisors[qtblno] = (DCTELEM *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(DCTELEM));
+ }
+ dtbl = fdct->divisors[qtblno];
+ for (i = 0; i < DCTSIZE2; i++) {
+ dtbl[i] = (DCTELEM)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-3);
+ }
+ }
+ fdct->pub.forward_DCT[ci] = forward_DCT;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, divisors are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * We apply a further scale factor of 8.
+ * What's actually stored is 1/divisor so that the inner loop can
+ * use a multiplication rather than a division.
+ */
+ FAST_FLOAT * fdtbl;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ if (fdct->float_divisors[qtblno] == NULL) {
+ fdct->float_divisors[qtblno] = (FAST_FLOAT *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ DCTSIZE2 * SIZEOF(FAST_FLOAT));
+ }
+ fdtbl = fdct->float_divisors[qtblno];
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fdtbl[i] = (FAST_FLOAT)
+ (1.0 / (((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col] * 8.0)));
+ i++;
+ }
+ }
+ }
+ fdct->pub.forward_DCT[ci] = forward_DCT_float;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Initialize FDCT manager.
+ */
+
+GLOBAL(void)
+jinit_forward_dct (j_compress_ptr cinfo)
+{
+ my_fdct_ptr fdct;
+ int i;
+
+ fdct = (my_fdct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_fdct_controller));
+ cinfo->fdct = (struct jpeg_forward_dct *) fdct;
+ fdct->pub.start_pass = start_pass_fdctmgr;
+
+ /* Mark divisor tables unallocated */
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ fdct->divisors[i] = NULL;
+#ifdef DCT_FLOAT_SUPPORTED
+ fdct->float_divisors[i] = NULL;
+#endif
+ }
+}
diff --git a/Source/LibJPEG/jchuff.c b/Source/LibJPEG/jchuff.c
new file mode 100644
index 0000000..0fd578e
--- /dev/null
+++ b/Source/LibJPEG/jchuff.c
@@ -0,0 +1,1612 @@
+/*
+ * jchuff.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2006-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy encoding routines.
+ * Both sequential and progressive modes are supported in this single module.
+ *
+ * Much of the complexity here has to do with supporting output suspension.
+ * If the data destination module demands suspension, we want to be able to
+ * back up to the start of the current MCU. To do this, we copy state
+ * variables into local working storage, and update them back to the
+ * permanent JPEG objects only upon successful completion of an MCU.
+ *
+ * We do not support output suspension for the progressive JPEG mode, since
+ * the library currently does not allow multiple-scan files to be written
+ * with output suspension.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* The legal range of a DCT coefficient is
+ * -1024 .. +1023 for 8-bit data;
+ * -16384 .. +16383 for 12-bit data.
+ * Hence the magnitude should always fit in 10 or 14 bits respectively.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MAX_COEF_BITS 10
+#else
+#define MAX_COEF_BITS 14
+#endif
+
+/* Derived data constructed for each Huffman table */
+
+typedef struct {
+ unsigned int ehufco[256]; /* code for each symbol */
+ char ehufsi[256]; /* length of code for each symbol */
+ /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */
+} c_derived_tbl;
+
+
+/* Expanded entropy encoder object for Huffman encoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ INT32 put_buffer; /* current bit-accumulation buffer */
+ int put_bits; /* # of bits now in it */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).put_buffer = (src).put_buffer, \
+ (dest).put_bits = (src).put_bits, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ struct jpeg_entropy_encoder pub; /* public fields */
+
+ savable_state saved; /* Bit buffer & DC state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+ int next_restart_num; /* next restart number to write (0-7) */
+
+ /* Following four fields used only in sequential mode */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+ /* Statistics tables for optimization */
+ long * dc_count_ptrs[NUM_HUFF_TBLS];
+ long * ac_count_ptrs[NUM_HUFF_TBLS];
+
+ /* Following fields used only in progressive mode */
+
+ /* Mode flag: TRUE for optimization, FALSE for actual data output */
+ boolean gather_statistics;
+
+ /* next_output_byte/free_in_buffer are local copies of cinfo->dest fields.
+ */
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ j_compress_ptr cinfo; /* link to cinfo (needed for dump_buffer) */
+
+ /* Coding status for AC components */
+ int ac_tbl_no; /* the table number of the single component */
+ unsigned int EOBRUN; /* run length of EOBs */
+ unsigned int BE; /* # of buffered correction bits before MCU */
+ char * bit_buffer; /* buffer for correction bits (1 per char) */
+ /* packing correction bits tightly would save some space but cost time... */
+
+ /* Pointers to derived tables (these workspaces have image lifespan).
+ * Since any one scan in progressive mode codes only DC or only AC,
+ * we only need one set of tables, not one for DC and one for AC.
+ */
+ c_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ /* Statistics tables for optimization; again, one set is enough */
+ long * count_ptrs[NUM_HUFF_TBLS];
+} huff_entropy_encoder;
+
+typedef huff_entropy_encoder * huff_entropy_ptr;
+
+/* Working state while writing an MCU (sequential mode).
+ * This struct contains all the fields that are needed by subroutines.
+ */
+
+typedef struct {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+ savable_state cur; /* Current bit buffer & DC state */
+ j_compress_ptr cinfo; /* dump_buffer needs access to this */
+} working_state;
+
+/* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
+ * buffer can hold. Larger sizes may slightly improve compression, but
+ * 1000 is already well into the realm of overkill.
+ * The minimum safe size is 64 bits.
+ */
+
+#define MAX_CORR_BITS 1000 /* Max # of correction bits I can buffer */
+
+/* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
+ * We assume that int right shift is unsigned if INT32 right shift is,
+ * which should be safe.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS int ishift_temp;
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+LOCAL(void)
+jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno,
+ c_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ c_derived_tbl *dtbl;
+ int p, i, l, lastp, si, maxsymbol;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (c_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(c_derived_tbl));
+ dtbl = *pdtbl;
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ lastp = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure C.3: generate encoding tables */
+ /* These are code and size indexed by symbol value */
+
+ /* Set all codeless symbols to have code length 0;
+ * this lets us detect duplicate VAL entries here, and later
+ * allows emit_bits to detect any attempt to emit such symbols.
+ */
+ MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi));
+
+ /* This is also a convenient place to check for out-of-range
+ * and duplicated VAL entries. We allow 0..255 for AC symbols
+ * but only 0..15 for DC. (We could constrain them further
+ * based on data depth and mode, but this seems enough.)
+ */
+ maxsymbol = isDC ? 15 : 255;
+
+ for (p = 0; p < lastp; p++) {
+ i = htbl->huffval[p];
+ if (i < 0 || i > maxsymbol || dtbl->ehufsi[i])
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ dtbl->ehufco[i] = huffcode[p];
+ dtbl->ehufsi[i] = huffsize[p];
+ }
+}
+
+
+/* Outputting bytes to the file.
+ * NB: these must be called only when actually outputting,
+ * that is, entropy->gather_statistics == FALSE.
+ */
+
+/* Emit a byte, taking 'action' if must suspend. */
+#define emit_byte_s(state,val,action) \
+ { *(state)->next_output_byte++ = (JOCTET) (val); \
+ if (--(state)->free_in_buffer == 0) \
+ if (! dump_buffer_s(state)) \
+ { action; } }
+
+/* Emit a byte */
+#define emit_byte_e(entropy,val) \
+ { *(entropy)->next_output_byte++ = (JOCTET) (val); \
+ if (--(entropy)->free_in_buffer == 0) \
+ dump_buffer_e(entropy); }
+
+
+LOCAL(boolean)
+dump_buffer_s (working_state * state)
+/* Empty the output buffer; return TRUE if successful, FALSE if must suspend */
+{
+ struct jpeg_destination_mgr * dest = state->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (state->cinfo))
+ return FALSE;
+ /* After a successful buffer dump, must reset buffer pointers */
+ state->next_output_byte = dest->next_output_byte;
+ state->free_in_buffer = dest->free_in_buffer;
+ return TRUE;
+}
+
+
+LOCAL(void)
+dump_buffer_e (huff_entropy_ptr entropy)
+/* Empty the output buffer; we do not support suspension in this case. */
+{
+ struct jpeg_destination_mgr * dest = entropy->cinfo->dest;
+
+ if (! (*dest->empty_output_buffer) (entropy->cinfo))
+ ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND);
+ /* After a successful buffer dump, must reset buffer pointers */
+ entropy->next_output_byte = dest->next_output_byte;
+ entropy->free_in_buffer = dest->free_in_buffer;
+}
+
+
+/* Outputting bits to the file */
+
+/* Only the right 24 bits of put_buffer are used; the valid bits are
+ * left-justified in this part. At most 16 bits can be passed to emit_bits
+ * in one call, and we never retain more than 7 bits in put_buffer
+ * between calls, so 24 bits are sufficient.
+ */
+
+INLINE
+LOCAL(boolean)
+emit_bits_s (working_state * state, unsigned int code, int size)
+/* Emit some bits; return TRUE if successful, FALSE if must suspend */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = state->cur.put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE);
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte_s(state, c, return FALSE);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte_s(state, 0, return FALSE);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ state->cur.put_buffer = put_buffer; /* update state variables */
+ state->cur.put_bits = put_bits;
+
+ return TRUE;
+}
+
+
+INLINE
+LOCAL(void)
+emit_bits_e (huff_entropy_ptr entropy, unsigned int code, int size)
+/* Emit some bits, unless we are in gather mode */
+{
+ /* This routine is heavily used, so it's worth coding tightly. */
+ register INT32 put_buffer = (INT32) code;
+ register int put_bits = entropy->saved.put_bits;
+
+ /* if size is 0, caller used an invalid Huffman table entry */
+ if (size == 0)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ if (entropy->gather_statistics)
+ return; /* do nothing if we're only getting stats */
+
+ put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */
+
+ put_bits += size; /* new number of bits in buffer */
+
+ put_buffer <<= 24 - put_bits; /* align incoming bits */
+
+ /* and merge with old buffer contents */
+ put_buffer |= entropy->saved.put_buffer;
+
+ while (put_bits >= 8) {
+ int c = (int) ((put_buffer >> 16) & 0xFF);
+
+ emit_byte_e(entropy, c);
+ if (c == 0xFF) { /* need to stuff a zero byte? */
+ emit_byte_e(entropy, 0);
+ }
+ put_buffer <<= 8;
+ put_bits -= 8;
+ }
+
+ entropy->saved.put_buffer = put_buffer; /* update variables */
+ entropy->saved.put_bits = put_bits;
+}
+
+
+LOCAL(boolean)
+flush_bits_s (working_state * state)
+{
+ if (! emit_bits_s(state, 0x7F, 7)) /* fill any partial byte with ones */
+ return FALSE;
+ state->cur.put_buffer = 0; /* and reset bit-buffer to empty */
+ state->cur.put_bits = 0;
+ return TRUE;
+}
+
+
+LOCAL(void)
+flush_bits_e (huff_entropy_ptr entropy)
+{
+ emit_bits_e(entropy, 0x7F, 7); /* fill any partial byte with ones */
+ entropy->saved.put_buffer = 0; /* and reset bit-buffer to empty */
+ entropy->saved.put_bits = 0;
+}
+
+
+/*
+ * Emit (or just count) a Huffman symbol.
+ */
+
+INLINE
+LOCAL(void)
+emit_symbol (huff_entropy_ptr entropy, int tbl_no, int symbol)
+{
+ if (entropy->gather_statistics)
+ entropy->count_ptrs[tbl_no][symbol]++;
+ else {
+ c_derived_tbl * tbl = entropy->derived_tbls[tbl_no];
+ emit_bits_e(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]);
+ }
+}
+
+
+/*
+ * Emit bits from a correction bit buffer.
+ */
+
+LOCAL(void)
+emit_buffered_bits (huff_entropy_ptr entropy, char * bufstart,
+ unsigned int nbits)
+{
+ if (entropy->gather_statistics)
+ return; /* no real work */
+
+ while (nbits > 0) {
+ emit_bits_e(entropy, (unsigned int) (*bufstart), 1);
+ bufstart++;
+ nbits--;
+ }
+}
+
+
+/*
+ * Emit any pending EOBRUN symbol.
+ */
+
+LOCAL(void)
+emit_eobrun (huff_entropy_ptr entropy)
+{
+ register int temp, nbits;
+
+ if (entropy->EOBRUN > 0) { /* if there is any pending EOBRUN */
+ temp = entropy->EOBRUN;
+ nbits = 0;
+ while ((temp >>= 1))
+ nbits++;
+ /* safety check: shouldn't happen given limited correction-bit buffer */
+ if (nbits > 14)
+ ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE);
+
+ emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4);
+ if (nbits)
+ emit_bits_e(entropy, entropy->EOBRUN, nbits);
+
+ entropy->EOBRUN = 0;
+
+ /* Emit any buffered correction bits */
+ emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE);
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * Emit a restart marker & resynchronize predictions.
+ */
+
+LOCAL(boolean)
+emit_restart_s (working_state * state, int restart_num)
+{
+ int ci;
+
+ if (! flush_bits_s(state))
+ return FALSE;
+
+ emit_byte_s(state, 0xFF, return FALSE);
+ emit_byte_s(state, JPEG_RST0 + restart_num, return FALSE);
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < state->cinfo->comps_in_scan; ci++)
+ state->cur.last_dc_val[ci] = 0;
+
+ /* The restart counter is not updated until we successfully write the MCU. */
+
+ return TRUE;
+}
+
+
+LOCAL(void)
+emit_restart_e (huff_entropy_ptr entropy, int restart_num)
+{
+ int ci;
+
+ emit_eobrun(entropy);
+
+ if (! entropy->gather_statistics) {
+ flush_bits_e(entropy);
+ emit_byte_e(entropy, 0xFF);
+ emit_byte_e(entropy, JPEG_RST0 + restart_num);
+ }
+
+ if (entropy->cinfo->Ss == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ } else {
+ /* Re-initialize all AC-related fields to 0 */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+ }
+}
+
+
+/*
+ * MCU encoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ register int temp, temp2;
+ register int nbits;
+ int blkn, ci;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ jpeg_component_info * compptr;
+ ISHIFT_TEMPS
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart_e(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+
+ /* Compute the DC value after the required point transform by Al.
+ * This is simply an arithmetic right shift.
+ */
+ temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al);
+
+ /* DC differences are figured on the point-transformed values. */
+ temp = temp2 - entropy->saved.last_dc_val[ci];
+ entropy->saved.last_dc_val[ci] = temp2;
+
+ /* Encode the DC coefficient difference per section G.1.2.1 */
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit the Huffman-coded symbol for the number of bits */
+ emit_symbol(entropy, compptr->dc_tbl_no, nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ emit_bits_e(entropy, (unsigned int) temp2, nbits);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ register int temp, temp2;
+ register int nbits;
+ register int r, k;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart_e(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = (*block)[jpeg_natural_order[k]]) == 0) {
+ r++;
+ continue;
+ }
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value; so the code is
+ * interwoven with finding the abs value (temp) and output bits (temp2).
+ */
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ /* For a negative coef, want temp2 = bitwise complement of abs(coef) */
+ temp2 = ~temp;
+ } else {
+ temp >>= Al; /* apply the point transform */
+ temp2 = temp;
+ }
+ /* Watch out for case that nonzero coef is zero after point transform */
+ if (temp == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any pending EOBRUN */
+ if (entropy->EOBRUN > 0)
+ emit_eobrun(entropy);
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits);
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ emit_bits_e(entropy, (unsigned int) temp2, nbits);
+
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ if (entropy->EOBRUN == 0x7FFF)
+ emit_eobrun(entropy); /* force it out to avoid overflow */
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ register int temp;
+ int blkn;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart_e(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* We simply emit the Al'th bit of the DC coefficient value. */
+ temp = (*block)[0];
+ emit_bits_e(entropy, (unsigned int) (temp >> Al), 1);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU encoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ register int temp;
+ register int r, k;
+ int EOB;
+ char *BR_buffer;
+ unsigned int BR;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ JBLOCKROW block;
+ int absvalues[DCTSIZE2];
+
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval)
+ if (entropy->restarts_to_go == 0)
+ emit_restart_e(entropy, entropy->next_restart_num);
+
+ /* Encode the MCU data block */
+ block = MCU_data[0];
+
+ /* It is convenient to make a pre-pass to determine the transformed
+ * coefficients' absolute values and the EOB position.
+ */
+ EOB = 0;
+ for (k = cinfo->Ss; k <= Se; k++) {
+ temp = (*block)[jpeg_natural_order[k]];
+ /* We must apply the point transform by Al. For AC coefficients this
+ * is an integer division with rounding towards 0. To do this portably
+ * in C, we shift after obtaining the absolute value.
+ */
+ if (temp < 0)
+ temp = -temp; /* temp is abs value of input */
+ temp >>= Al; /* apply the point transform */
+ absvalues[k] = temp; /* save abs value for main pass */
+ if (temp == 1)
+ EOB = k; /* EOB = index of last newly-nonzero coef */
+ }
+
+ /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */
+
+ r = 0; /* r = run length of zeros */
+ BR = 0; /* BR = count of buffered bits added now */
+ BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ if ((temp = absvalues[k]) == 0) {
+ r++;
+ continue;
+ }
+
+ /* Emit any required ZRLs, but not if they can be folded into EOB */
+ while (r > 15 && k <= EOB) {
+ /* emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+ /* Emit ZRL */
+ emit_symbol(entropy, entropy->ac_tbl_no, 0xF0);
+ r -= 16;
+ /* Emit buffered correction bits that must be associated with ZRL */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ }
+
+ /* If the coef was previously nonzero, it only needs a correction bit.
+ * NOTE: a straight translation of the spec's figure G.7 would suggest
+ * that we also need to test r > 15. But if r > 15, we can only get here
+ * if k > EOB, which implies that this coefficient is not 1.
+ */
+ if (temp > 1) {
+ /* The correction bit is the next bit of the absolute value. */
+ BR_buffer[BR++] = (char) (temp & 1);
+ continue;
+ }
+
+ /* Emit any pending EOBRUN and the BE correction bits */
+ emit_eobrun(entropy);
+
+ /* Count/emit Huffman symbol for run length / number of bits */
+ emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1);
+
+ /* Emit output bit for newly-nonzero coef */
+ temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1;
+ emit_bits_e(entropy, (unsigned int) temp, 1);
+
+ /* Emit buffered correction bits that must be associated with this code */
+ emit_buffered_bits(entropy, BR_buffer, BR);
+ BR_buffer = entropy->bit_buffer; /* BE bits are gone now */
+ BR = 0;
+ r = 0; /* reset zero run length */
+ }
+
+ if (r > 0 || BR > 0) { /* If there are trailing zeroes, */
+ entropy->EOBRUN++; /* count an EOB */
+ entropy->BE += BR; /* concat my correction bits to older ones */
+ /* We force out the EOB if we risk either:
+ * 1. overflow of the EOB counter;
+ * 2. overflow of the correction bit buffer during the next MCU.
+ */
+ if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1))
+ emit_eobrun(entropy);
+ }
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/* Encode a single block's worth of coefficients */
+
+LOCAL(boolean)
+encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val,
+ c_derived_tbl *dctbl, c_derived_tbl *actbl)
+{
+ register int temp, temp2;
+ register int nbits;
+ register int k, r, i;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = temp2 = block[0] - last_dc_val;
+
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* For a negative input, want temp2 = bitwise complement of abs(input) */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit the Huffman-coded symbol for the number of bits */
+ if (! emit_bits_s(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (nbits) /* emit_bits rejects calls with size 0 */
+ if (! emit_bits_s(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ if (! emit_bits_s(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0]))
+ return FALSE;
+ r -= 16;
+ }
+
+ temp2 = temp;
+ if (temp < 0) {
+ temp = -temp; /* temp is abs value of input */
+ /* This code assumes we are on a two's complement machine */
+ temp2--;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(state->cinfo, JERR_BAD_DCT_COEF);
+
+ /* Emit Huffman symbol for run length / number of bits */
+ i = (r << 4) + nbits;
+ if (! emit_bits_s(state, actbl->ehufco[i], actbl->ehufsi[i]))
+ return FALSE;
+
+ /* Emit that number of bits of the value, if positive, */
+ /* or the complement of its magnitude, if negative. */
+ if (! emit_bits_s(state, (unsigned int) temp2, nbits))
+ return FALSE;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ if (! emit_bits_s(state, actbl->ehufco[0], actbl->ehufsi[0]))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Encode and output one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ working_state state;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Load up working state */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Emit restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! emit_restart_s(&state, entropy->next_restart_num))
+ return FALSE;
+ }
+
+ /* Encode the MCU data blocks */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ if (! encode_one_block(&state,
+ MCU_data[blkn][0], state.cur.last_dc_val[ci],
+ entropy->dc_derived_tbls[compptr->dc_tbl_no],
+ entropy->ac_derived_tbls[compptr->ac_tbl_no]))
+ return FALSE;
+ /* Update last_dc_val */
+ state.cur.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ /* Completed MCU, so update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+
+ /* Update restart-interval state too */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num++;
+ entropy->next_restart_num &= 7;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Finish up at the end of a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+finish_pass_huff (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ working_state state;
+
+ if (cinfo->progressive_mode) {
+ entropy->next_output_byte = cinfo->dest->next_output_byte;
+ entropy->free_in_buffer = cinfo->dest->free_in_buffer;
+
+ /* Flush out any buffered data */
+ emit_eobrun(entropy);
+ flush_bits_e(entropy);
+
+ cinfo->dest->next_output_byte = entropy->next_output_byte;
+ cinfo->dest->free_in_buffer = entropy->free_in_buffer;
+ } else {
+ /* Load up working state ... flush_bits needs it */
+ state.next_output_byte = cinfo->dest->next_output_byte;
+ state.free_in_buffer = cinfo->dest->free_in_buffer;
+ ASSIGN_STATE(state.cur, entropy->saved);
+ state.cinfo = cinfo;
+
+ /* Flush out the last data */
+ if (! flush_bits_s(&state))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+ /* Update state */
+ cinfo->dest->next_output_byte = state.next_output_byte;
+ cinfo->dest->free_in_buffer = state.free_in_buffer;
+ ASSIGN_STATE(entropy->saved, state.cur);
+ }
+}
+
+
+/*
+ * Huffman coding optimization.
+ *
+ * We first scan the supplied data and count the number of uses of each symbol
+ * that is to be Huffman-coded. (This process MUST agree with the code above.)
+ * Then we build a Huffman coding tree for the observed counts.
+ * Symbols which are not needed at all for the particular image are not
+ * assigned any code, which saves space in the DHT marker as well as in
+ * the compressed data.
+ */
+
+
+/* Process a single block's worth of coefficients */
+
+LOCAL(void)
+htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val,
+ long dc_counts[], long ac_counts[])
+{
+ register int temp;
+ register int nbits;
+ register int k, r;
+
+ /* Encode the DC coefficient difference per section F.1.2.1 */
+
+ temp = block[0] - last_dc_val;
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 0;
+ while (temp) {
+ nbits++;
+ temp >>= 1;
+ }
+ /* Check for out-of-range coefficient values.
+ * Since we're encoding a difference, the range limit is twice as much.
+ */
+ if (nbits > MAX_COEF_BITS+1)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count the Huffman symbol for the number of bits */
+ dc_counts[nbits]++;
+
+ /* Encode the AC coefficients per section F.1.2.2 */
+
+ r = 0; /* r = run length of zeros */
+
+ for (k = 1; k < DCTSIZE2; k++) {
+ if ((temp = block[jpeg_natural_order[k]]) == 0) {
+ r++;
+ } else {
+ /* if run length > 15, must emit special run-length-16 codes (0xF0) */
+ while (r > 15) {
+ ac_counts[0xF0]++;
+ r -= 16;
+ }
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ if (temp < 0)
+ temp = -temp;
+
+ /* Find the number of bits needed for the magnitude of the coefficient */
+ nbits = 1; /* there must be at least one 1 bit */
+ while ((temp >>= 1))
+ nbits++;
+ /* Check for out-of-range coefficient values */
+ if (nbits > MAX_COEF_BITS)
+ ERREXIT(cinfo, JERR_BAD_DCT_COEF);
+
+ /* Count Huffman symbol for run length / number of bits */
+ ac_counts[(r << 4) + nbits]++;
+
+ r = 0;
+ }
+ }
+
+ /* If the last coef(s) were zero, emit an end-of-block code */
+ if (r > 0)
+ ac_counts[0]++;
+}
+
+
+/*
+ * Trial-encode one MCU's worth of Huffman-compressed coefficients.
+ * No data is actually output, so no suspension return is possible.
+ */
+
+METHODDEF(boolean)
+encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int blkn, ci;
+ jpeg_component_info * compptr;
+
+ /* Take care of restart intervals if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0) {
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Update restart state */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ }
+ entropy->restarts_to_go--;
+ }
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci],
+ entropy->dc_count_ptrs[compptr->dc_tbl_no],
+ entropy->ac_count_ptrs[compptr->ac_tbl_no]);
+ entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0];
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Generate the best Huffman code table for the given counts, fill htbl.
+ *
+ * The JPEG standard requires that no symbol be assigned a codeword of all
+ * one bits (so that padding bits added at the end of a compressed segment
+ * can't look like a valid code). Because of the canonical ordering of
+ * codewords, this just means that there must be an unused slot in the
+ * longest codeword length category. Section K.2 of the JPEG spec suggests
+ * reserving such a slot by pretending that symbol 256 is a valid symbol
+ * with count 1. In theory that's not optimal; giving it count zero but
+ * including it in the symbol set anyway should give a better Huffman code.
+ * But the theoretically better code actually seems to come out worse in
+ * practice, because it produces more all-ones bytes (which incur stuffed
+ * zero bytes in the final file). In any case the difference is tiny.
+ *
+ * The JPEG standard requires Huffman codes to be no more than 16 bits long.
+ * If some symbols have a very small but nonzero probability, the Huffman tree
+ * must be adjusted to meet the code length restriction. We currently use
+ * the adjustment method suggested in JPEG section K.2. This method is *not*
+ * optimal; it may not choose the best possible limited-length code. But
+ * typically only very-low-frequency symbols will be given less-than-optimal
+ * lengths, so the code is almost optimal. Experimental comparisons against
+ * an optimal limited-length-code algorithm indicate that the difference is
+ * microscopic --- usually less than a hundredth of a percent of total size.
+ * So the extra complexity of an optimal algorithm doesn't seem worthwhile.
+ */
+
+LOCAL(void)
+jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])
+{
+#define MAX_CLEN 32 /* assumed maximum initial code length */
+ UINT8 bits[MAX_CLEN+1]; /* bits[k] = # of symbols with code length k */
+ int codesize[257]; /* codesize[k] = code length of symbol k */
+ int others[257]; /* next symbol in current branch of tree */
+ int c1, c2;
+ int p, i, j;
+ long v;
+
+ /* This algorithm is explained in section K.2 of the JPEG standard */
+
+ MEMZERO(bits, SIZEOF(bits));
+ MEMZERO(codesize, SIZEOF(codesize));
+ for (i = 0; i < 257; i++)
+ others[i] = -1; /* init links to empty */
+
+ freq[256] = 1; /* make sure 256 has a nonzero count */
+ /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
+ * that no real symbol is given code-value of all ones, because 256
+ * will be placed last in the largest codeword category.
+ */
+
+ /* Huffman's basic algorithm to assign optimal code lengths to symbols */
+
+ for (;;) {
+ /* Find the smallest nonzero frequency, set c1 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c1 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v) {
+ v = freq[i];
+ c1 = i;
+ }
+ }
+
+ /* Find the next smallest nonzero frequency, set c2 = its symbol */
+ /* In case of ties, take the larger symbol number */
+ c2 = -1;
+ v = 1000000000L;
+ for (i = 0; i <= 256; i++) {
+ if (freq[i] && freq[i] <= v && i != c1) {
+ v = freq[i];
+ c2 = i;
+ }
+ }
+
+ /* Done if we've merged everything into one frequency */
+ if (c2 < 0)
+ break;
+
+ /* Else merge the two counts/trees */
+ freq[c1] += freq[c2];
+ freq[c2] = 0;
+
+ /* Increment the codesize of everything in c1's tree branch */
+ codesize[c1]++;
+ while (others[c1] >= 0) {
+ c1 = others[c1];
+ codesize[c1]++;
+ }
+
+ others[c1] = c2; /* chain c2 onto c1's tree branch */
+
+ /* Increment the codesize of everything in c2's tree branch */
+ codesize[c2]++;
+ while (others[c2] >= 0) {
+ c2 = others[c2];
+ codesize[c2]++;
+ }
+ }
+
+ /* Now count the number of symbols of each code length */
+ for (i = 0; i <= 256; i++) {
+ if (codesize[i]) {
+ /* The JPEG standard seems to think that this can't happen, */
+ /* but I'm paranoid... */
+ if (codesize[i] > MAX_CLEN)
+ ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW);
+
+ bits[codesize[i]]++;
+ }
+ }
+
+ /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+ * Huffman procedure assigned any such lengths, we must adjust the coding.
+ * Here is what the JPEG spec says about how this next bit works:
+ * Since symbols are paired for the longest Huffman code, the symbols are
+ * removed from this length category two at a time. The prefix for the pair
+ * (which is one bit shorter) is allocated to one of the pair; then,
+ * skipping the BITS entry for that prefix length, a code word from the next
+ * shortest nonzero BITS entry is converted into a prefix for two code words
+ * one bit longer.
+ */
+
+ for (i = MAX_CLEN; i > 16; i--) {
+ while (bits[i] > 0) {
+ j = i - 2; /* find length of new prefix to be used */
+ while (bits[j] == 0)
+ j--;
+
+ bits[i] -= 2; /* remove two symbols */
+ bits[i-1]++; /* one goes in this length */
+ bits[j+1] += 2; /* two new symbols in this length */
+ bits[j]--; /* symbol of this length is now a prefix */
+ }
+ }
+
+ /* Remove the count for the pseudo-symbol 256 from the largest codelength */
+ while (bits[i] == 0) /* find largest codelength still in use */
+ i--;
+ bits[i]--;
+
+ /* Return final symbol counts (only for lengths 0..16) */
+ MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits));
+
+ /* Return a list of the symbols sorted by code length */
+ /* It's not real clear to me why we don't need to consider the codelength
+ * changes made above, but the JPEG spec seems to think this works.
+ */
+ p = 0;
+ for (i = 1; i <= MAX_CLEN; i++) {
+ for (j = 0; j <= 255; j++) {
+ if (codesize[j] == i) {
+ htbl->huffval[p] = (UINT8) j;
+ p++;
+ }
+ }
+ }
+
+ /* Set sent_table FALSE so updated table will be written to JPEG file. */
+ htbl->sent_table = FALSE;
+}
+
+
+/*
+ * Finish up a statistics-gathering pass and create the new Huffman tables.
+ */
+
+METHODDEF(void)
+finish_pass_gather (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, dctbl, actbl, tbl;
+ jpeg_component_info * compptr;
+ JHUFF_TBL **htblptr;
+ boolean did_dc[NUM_HUFF_TBLS];
+ boolean did_ac[NUM_HUFF_TBLS];
+ boolean did[NUM_HUFF_TBLS];
+
+ /* It's important not to apply jpeg_gen_optimal_table more than once
+ * per table, because it clobbers the input frequency counts!
+ */
+ if (cinfo->progressive_mode) {
+ /* Flush out buffered data (all we care about is counting the EOB symbol) */
+ emit_eobrun(entropy);
+
+ MEMZERO(did, SIZEOF(did));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ tbl = compptr->ac_tbl_no;
+ }
+ if (! did[tbl]) {
+ if (cinfo->Ss == 0)
+ htblptr = & cinfo->dc_huff_tbl_ptrs[tbl];
+ else
+ htblptr = & cinfo->ac_huff_tbl_ptrs[tbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]);
+ did[tbl] = TRUE;
+ }
+ }
+ } else {
+ MEMZERO(did_dc, SIZEOF(did_dc));
+ MEMZERO(did_ac, SIZEOF(did_ac));
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (! did_dc[dctbl]) {
+ htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]);
+ did_dc[dctbl] = TRUE;
+ }
+ if (! did_ac[actbl]) {
+ htblptr = & cinfo->ac_huff_tbl_ptrs[actbl];
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+ jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]);
+ did_ac[actbl] = TRUE;
+ }
+ }
+ }
+}
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ * If gather_statistics is TRUE, we do not output anything during the scan,
+ * just count the Huffman symbols used and generate Huffman code tables.
+ */
+
+METHODDEF(void)
+start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, dctbl, actbl, tbl;
+ jpeg_component_info * compptr;
+
+ if (gather_statistics)
+ entropy->pub.finish_pass = finish_pass_gather;
+ else
+ entropy->pub.finish_pass = finish_pass_huff;
+
+ if (cinfo->progressive_mode) {
+ entropy->cinfo = cinfo;
+ entropy->gather_statistics = gather_statistics;
+
+ /* We assume jcmaster.c already validated the scan parameters. */
+
+ /* Select execution routine */
+ if (cinfo->Ah == 0) {
+ if (cinfo->Ss == 0)
+ entropy->pub.encode_mcu = encode_mcu_DC_first;
+ else
+ entropy->pub.encode_mcu = encode_mcu_AC_first;
+ } else {
+ if (cinfo->Ss == 0)
+ entropy->pub.encode_mcu = encode_mcu_DC_refine;
+ else {
+ entropy->pub.encode_mcu = encode_mcu_AC_refine;
+ /* AC refinement needs a correction bit buffer */
+ if (entropy->bit_buffer == NULL)
+ entropy->bit_buffer = (char *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ MAX_CORR_BITS * SIZEOF(char));
+ }
+ }
+
+ /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
+ * for AC coefficients.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Get table index */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah != 0) /* DC refinement needs no table */
+ continue;
+ tbl = compptr->dc_tbl_no;
+ } else {
+ entropy->ac_tbl_no = tbl = compptr->ac_tbl_no;
+ }
+ if (gather_statistics) {
+ /* Check for invalid table index */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (tbl < 0 || tbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->count_ptrs[tbl] == NULL)
+ entropy->count_ptrs[tbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long));
+ } else {
+ /* Compute derived values for Huffman table */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, cinfo->Ss == 0, tbl,
+ & entropy->derived_tbls[tbl]);
+ }
+ }
+
+ /* Initialize AC stuff */
+ entropy->EOBRUN = 0;
+ entropy->BE = 0;
+ } else {
+ if (gather_statistics)
+ entropy->pub.encode_mcu = encode_mcu_gather;
+ else
+ entropy->pub.encode_mcu = encode_mcu_huff;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ if (gather_statistics) {
+ /* Check for invalid table indexes */
+ /* (make_c_derived_tbl does this in the other path) */
+ if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl);
+ if (actbl < 0 || actbl >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl);
+ /* Allocate and zero the statistics tables */
+ /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */
+ if (entropy->dc_count_ptrs[dctbl] == NULL)
+ entropy->dc_count_ptrs[dctbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long));
+ if (entropy->ac_count_ptrs[actbl] == NULL)
+ entropy->ac_count_ptrs[actbl] = (long *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 257 * SIZEOF(long));
+ MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long));
+ } else {
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_c_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+ }
+
+ /* Initialize bit buffer to empty */
+ entropy->saved.put_buffer = 0;
+ entropy->saved.put_bits = 0;
+
+ /* Initialize restart stuff */
+ entropy->restarts_to_go = cinfo->restart_interval;
+ entropy->next_restart_num = 0;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy encoding.
+ */
+
+GLOBAL(void)
+jinit_huff_encoder (j_compress_ptr cinfo)
+{
+ huff_entropy_ptr entropy;
+ int i;
+
+ entropy = (huff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(huff_entropy_encoder));
+ cinfo->entropy = (struct jpeg_entropy_encoder *) entropy;
+ entropy->pub.start_pass = start_pass_huff;
+
+ if (cinfo->progressive_mode) {
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ entropy->count_ptrs[i] = NULL;
+ }
+ entropy->bit_buffer = NULL; /* needed only in AC refinement scan */
+ } else {
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+ entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL;
+ }
+ }
+}
diff --git a/Source/LibJPEG/jcinit.c b/Source/LibJPEG/jcinit.c
new file mode 100644
index 0000000..0ba310f
--- /dev/null
+++ b/Source/LibJPEG/jcinit.c
@@ -0,0 +1,65 @@
+/*
+ * jcinit.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains initialization logic for the JPEG compressor.
+ * This routine is in charge of selecting the modules to be executed and
+ * making an initialization call to each one.
+ *
+ * Logically, this code belongs in jcmaster.c. It's split out because
+ * linking this routine implies linking the entire compression library.
+ * For a transcoding-only application, we want to be able to use jcmaster.c
+ * without linking in the whole library.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Master selection of compression modules.
+ * This is done once at the start of processing an image. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ */
+
+GLOBAL(void)
+jinit_compress_master (j_compress_ptr cinfo)
+{
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, FALSE /* full compression */);
+
+ /* Preprocessing */
+ if (! cinfo->raw_data_in) {
+ jinit_color_converter(cinfo);
+ jinit_downsampler(cinfo);
+ jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */);
+ }
+ /* Forward DCT */
+ jinit_forward_dct(cinfo);
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code)
+ jinit_arith_encoder(cinfo);
+ else {
+ jinit_huff_encoder(cinfo);
+ }
+
+ /* Need a full-image coefficient buffer in any multi-pass mode. */
+ jinit_c_coef_controller(cinfo,
+ (boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding));
+ jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
diff --git a/Source/LibJPEG/jcmainct.c b/Source/LibJPEG/jcmainct.c
new file mode 100644
index 0000000..7de75d1
--- /dev/null
+++ b/Source/LibJPEG/jcmainct.c
@@ -0,0 +1,293 @@
+/*
+ * jcmainct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for compression.
+ * The main buffer lies between the pre-processor and the JPEG
+ * compressor proper; it holds downsampled data in the JPEG colorspace.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Note: currently, there is no operating mode in which a full-image buffer
+ * is needed at this step. If there were, that mode could not be used with
+ * "raw data" input, since this module is bypassed in that case. However,
+ * we've left the code here for possible use in special applications.
+ */
+#undef FULL_MAIN_BUFFER_SUPPORTED
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_main_controller pub; /* public fields */
+
+ JDIMENSION cur_iMCU_row; /* number of current iMCU row */
+ JDIMENSION rowgroup_ctr; /* counts row groups received in iMCU row */
+ boolean suspended; /* remember if we suspended output */
+ J_BUF_MODE pass_mode; /* current operating mode */
+
+ /* If using just a strip buffer, this points to the entire set of buffers
+ * (we allocate one for each component). In the full-image case, this
+ * points to the currently accessible strips of the virtual arrays.
+ */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* If using full-image storage, this array holds pointers to virtual-array
+ * control blocks for each component. Unused if not full-image storage.
+ */
+ jvirt_sarray_ptr whole_image[MAX_COMPONENTS];
+#endif
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+METHODDEF(void) process_data_buffer_main
+ JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Do nothing in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ main->cur_iMCU_row = 0; /* initialize counters */
+ main->rowgroup_ctr = 0;
+ main->suspended = FALSE;
+ main->pass_mode = pass_mode; /* save mode for use by process_data */
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ if (main->whole_image[0] != NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ main->pub.process_data = process_data_simple_main;
+ break;
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ case JBUF_SAVE_SOURCE:
+ case JBUF_CRANK_DEST:
+ case JBUF_SAVE_AND_PASS:
+ if (main->whole_image[0] == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ main->pub.process_data = process_data_buffer_main;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This routine handles the simple pass-through mode,
+ * where we have only a strip buffer.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Read input data if we haven't filled the main buffer yet */
+ if (main->rowgroup_ctr < (JDIMENSION) cinfo->min_DCT_v_scaled_size)
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) cinfo->min_DCT_v_scaled_size);
+
+ /* If we don't have a full iMCU row buffered, return to application for
+ * more data. Note that preprocessor will always pad to fill the iMCU row
+ * at the bottom of the image.
+ */
+ if (main->rowgroup_ctr != (JDIMENSION) cinfo->min_DCT_v_scaled_size)
+ return;
+
+ /* Send the completed row to the compressor */
+ if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+
+/*
+ * Process some data.
+ * This routine handles all of the modes that use a full-size buffer.
+ */
+
+METHODDEF(void)
+process_data_buffer_main (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci;
+ jpeg_component_info *compptr;
+ boolean writing = (main->pass_mode != JBUF_CRANK_DEST);
+
+ while (main->cur_iMCU_row < cinfo->total_iMCU_rows) {
+ /* Realign the virtual buffers if at the start of an iMCU row. */
+ if (main->rowgroup_ctr == 0) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, main->whole_image[ci],
+ main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE),
+ (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing);
+ }
+ /* In a read pass, pretend we just read some source data. */
+ if (! writing) {
+ *in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE;
+ main->rowgroup_ctr = DCTSIZE;
+ }
+ }
+
+ /* If a write pass, read input data until the current iMCU row is full. */
+ /* Note: preprocessor will pad if necessary to fill the last iMCU row. */
+ if (writing) {
+ (*cinfo->prep->pre_process_data) (cinfo,
+ input_buf, in_row_ctr, in_rows_avail,
+ main->buffer, &main->rowgroup_ctr,
+ (JDIMENSION) DCTSIZE);
+ /* Return to application if we need more data to fill the iMCU row. */
+ if (main->rowgroup_ctr < DCTSIZE)
+ return;
+ }
+
+ /* Emit data, unless this is a sink-only pass. */
+ if (main->pass_mode != JBUF_SAVE_SOURCE) {
+ if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) {
+ /* If compressor did not consume the whole row, then we must need to
+ * suspend processing and return to the application. In this situation
+ * we pretend we didn't yet consume the last input row; otherwise, if
+ * it happened to be the last row of the image, the application would
+ * think we were done.
+ */
+ if (! main->suspended) {
+ (*in_row_ctr)--;
+ main->suspended = TRUE;
+ }
+ return;
+ }
+ /* We did finish the row. Undo our little suspension hack if a previous
+ * call suspended; then mark the main buffer empty.
+ */
+ if (main->suspended) {
+ (*in_row_ctr)++;
+ main->suspended = FALSE;
+ }
+ }
+
+ /* If get here, we are done with this iMCU row. Mark buffer empty. */
+ main->rowgroup_ctr = 0;
+ main->cur_iMCU_row++;
+ }
+}
+
+#endif /* FULL_MAIN_BUFFER_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci;
+ jpeg_component_info *compptr;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_c_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ /* We don't need to create a buffer in raw-data mode. */
+ if (cinfo->raw_data_in)
+ return;
+
+ /* Create the buffer. It holds downsampled data, so each component
+ * may be of a different size.
+ */
+ if (need_full_buffer) {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ /* Allocate a full-image virtual array for each component */
+ /* Note we pad the bottom to a multiple of the iMCU height */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->whole_image[ci] = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ compptr->width_in_blocks * compptr->DCT_h_scaled_size,
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor) * DCTSIZE,
+ (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size));
+ }
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif
+ } else {
+#ifdef FULL_MAIN_BUFFER_SUPPORTED
+ main->whole_image[0] = NULL; /* flag for no virtual arrays */
+#endif
+ /* Allocate a strip buffer for each component */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_blocks * compptr->DCT_h_scaled_size,
+ (JDIMENSION) (compptr->v_samp_factor * compptr->DCT_v_scaled_size));
+ }
+ }
+}
diff --git a/Source/LibJPEG/jcmarker.c b/Source/LibJPEG/jcmarker.c
new file mode 100644
index 0000000..54d109a
--- /dev/null
+++ b/Source/LibJPEG/jcmarker.c
@@ -0,0 +1,667 @@
+/*
+ * jcmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write JPEG datastream markers.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_writer pub; /* public fields */
+
+ unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */
+} my_marker_writer;
+
+typedef my_marker_writer * my_marker_ptr;
+
+
+/*
+ * Basic output routines.
+ *
+ * Note that we do not support suspension while writing a marker.
+ * Therefore, an application using suspension must ensure that there is
+ * enough buffer space for the initial markers (typ. 600-700 bytes) before
+ * calling jpeg_start_compress, and enough space to write the trailing EOI
+ * (a few bytes) before calling jpeg_finish_compress. Multipass compression
+ * modes are not supported at all with suspension, so those two are the only
+ * points where markers will be written.
+ */
+
+LOCAL(void)
+emit_byte (j_compress_ptr cinfo, int val)
+/* Emit a byte */
+{
+ struct jpeg_destination_mgr * dest = cinfo->dest;
+
+ *(dest->next_output_byte)++ = (JOCTET) val;
+ if (--dest->free_in_buffer == 0) {
+ if (! (*dest->empty_output_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ }
+}
+
+
+LOCAL(void)
+emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark)
+/* Emit a marker code */
+{
+ emit_byte(cinfo, 0xFF);
+ emit_byte(cinfo, (int) mark);
+}
+
+
+LOCAL(void)
+emit_2bytes (j_compress_ptr cinfo, int value)
+/* Emit a 2-byte integer; these are always MSB first in JPEG files */
+{
+ emit_byte(cinfo, (value >> 8) & 0xFF);
+ emit_byte(cinfo, value & 0xFF);
+}
+
+
+/*
+ * Routines to write specific marker types.
+ */
+
+LOCAL(int)
+emit_dqt (j_compress_ptr cinfo, int index)
+/* Emit a DQT marker */
+/* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */
+{
+ JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index];
+ int prec;
+ int i;
+
+ if (qtbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index);
+
+ prec = 0;
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (qtbl->quantval[i] > 255)
+ prec = 1;
+ }
+
+ if (! qtbl->sent_table) {
+ emit_marker(cinfo, M_DQT);
+
+ emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2);
+
+ emit_byte(cinfo, index + (prec<<4));
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ /* The table entries must be emitted in zigzag order. */
+ unsigned int qval = qtbl->quantval[jpeg_natural_order[i]];
+ if (prec)
+ emit_byte(cinfo, (int) (qval >> 8));
+ emit_byte(cinfo, (int) (qval & 0xFF));
+ }
+
+ qtbl->sent_table = TRUE;
+ }
+
+ return prec;
+}
+
+
+LOCAL(void)
+emit_dht (j_compress_ptr cinfo, int index, boolean is_ac)
+/* Emit a DHT marker */
+{
+ JHUFF_TBL * htbl;
+ int length, i;
+
+ if (is_ac) {
+ htbl = cinfo->ac_huff_tbl_ptrs[index];
+ index += 0x10; /* output index has AC bit set */
+ } else {
+ htbl = cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index);
+
+ if (! htbl->sent_table) {
+ emit_marker(cinfo, M_DHT);
+
+ length = 0;
+ for (i = 1; i <= 16; i++)
+ length += htbl->bits[i];
+
+ emit_2bytes(cinfo, length + 2 + 1 + 16);
+ emit_byte(cinfo, index);
+
+ for (i = 1; i <= 16; i++)
+ emit_byte(cinfo, htbl->bits[i]);
+
+ for (i = 0; i < length; i++)
+ emit_byte(cinfo, htbl->huffval[i]);
+
+ htbl->sent_table = TRUE;
+ }
+}
+
+
+LOCAL(void)
+emit_dac (j_compress_ptr cinfo)
+/* Emit a DAC marker */
+/* Since the useful info is so small, we want to emit all the tables in */
+/* one DAC marker. Therefore this routine does its own scan of the table. */
+{
+#ifdef C_ARITH_CODING_SUPPORTED
+ char dc_in_use[NUM_ARITH_TBLS];
+ char ac_in_use[NUM_ARITH_TBLS];
+ int length, i;
+ jpeg_component_info *compptr;
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ dc_in_use[i] = ac_in_use[i] = 0;
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ dc_in_use[compptr->dc_tbl_no] = 1;
+ ac_in_use[compptr->ac_tbl_no] = 1;
+ }
+
+ length = 0;
+ for (i = 0; i < NUM_ARITH_TBLS; i++)
+ length += dc_in_use[i] + ac_in_use[i];
+
+ emit_marker(cinfo, M_DAC);
+
+ emit_2bytes(cinfo, length*2 + 2);
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ if (dc_in_use[i]) {
+ emit_byte(cinfo, i);
+ emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4));
+ }
+ if (ac_in_use[i]) {
+ emit_byte(cinfo, i + 0x10);
+ emit_byte(cinfo, cinfo->arith_ac_K[i]);
+ }
+ }
+#endif /* C_ARITH_CODING_SUPPORTED */
+}
+
+
+LOCAL(void)
+emit_dri (j_compress_ptr cinfo)
+/* Emit a DRI marker */
+{
+ emit_marker(cinfo, M_DRI);
+
+ emit_2bytes(cinfo, 4); /* fixed length */
+
+ emit_2bytes(cinfo, (int) cinfo->restart_interval);
+}
+
+
+LOCAL(void)
+emit_sof (j_compress_ptr cinfo, JPEG_MARKER code)
+/* Emit a SOF marker */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, code);
+
+ emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */
+
+ /* Make sure image isn't bigger than SOF field can handle */
+ if ((long) cinfo->jpeg_height > 65535L ||
+ (long) cinfo->jpeg_width > 65535L)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535);
+
+ emit_byte(cinfo, cinfo->data_precision);
+ emit_2bytes(cinfo, (int) cinfo->jpeg_height);
+ emit_2bytes(cinfo, (int) cinfo->jpeg_width);
+
+ emit_byte(cinfo, cinfo->num_components);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ emit_byte(cinfo, compptr->component_id);
+ emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor);
+ emit_byte(cinfo, compptr->quant_tbl_no);
+ }
+}
+
+
+LOCAL(void)
+emit_sos (j_compress_ptr cinfo)
+/* Emit a SOS marker */
+{
+ int i, td, ta;
+ jpeg_component_info *compptr;
+
+ emit_marker(cinfo, M_SOS);
+
+ emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */
+
+ emit_byte(cinfo, cinfo->comps_in_scan);
+
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ emit_byte(cinfo, compptr->component_id);
+ td = compptr->dc_tbl_no;
+ ta = compptr->ac_tbl_no;
+ if (cinfo->progressive_mode) {
+ /* Progressive mode: only DC or only AC tables are used in one scan;
+ * furthermore, Huffman coding of DC refinement uses no table at all.
+ * We emit 0 for unused field(s); this is recommended by the P&M text
+ * but does not seem to be specified in the standard.
+ */
+ if (cinfo->Ss == 0) {
+ ta = 0; /* DC scan */
+ if (cinfo->Ah != 0 && !cinfo->arith_code)
+ td = 0; /* no DC table either */
+ } else {
+ td = 0; /* AC scan */
+ }
+ }
+ emit_byte(cinfo, (td << 4) + ta);
+ }
+
+ emit_byte(cinfo, cinfo->Ss);
+ emit_byte(cinfo, cinfo->Se);
+ emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al);
+}
+
+
+LOCAL(void)
+emit_jfif_app0 (j_compress_ptr cinfo)
+/* Emit a JFIF-compliant APP0 marker */
+{
+ /*
+ * Length of APP0 block (2 bytes)
+ * Block ID (4 bytes - ASCII "JFIF")
+ * Zero byte (1 byte to terminate the ID string)
+ * Version Major, Minor (2 bytes - major first)
+ * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm)
+ * Xdpu (2 bytes - dots per unit horizontal)
+ * Ydpu (2 bytes - dots per unit vertical)
+ * Thumbnail X size (1 byte)
+ * Thumbnail Y size (1 byte)
+ */
+
+ emit_marker(cinfo, M_APP0);
+
+ emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */
+
+ emit_byte(cinfo, 0x4A); /* Identifier: ASCII "JFIF" */
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0x49);
+ emit_byte(cinfo, 0x46);
+ emit_byte(cinfo, 0);
+ emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */
+ emit_byte(cinfo, cinfo->JFIF_minor_version);
+ emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */
+ emit_2bytes(cinfo, (int) cinfo->X_density);
+ emit_2bytes(cinfo, (int) cinfo->Y_density);
+ emit_byte(cinfo, 0); /* No thumbnail image */
+ emit_byte(cinfo, 0);
+}
+
+
+LOCAL(void)
+emit_adobe_app14 (j_compress_ptr cinfo)
+/* Emit an Adobe APP14 marker */
+{
+ /*
+ * Length of APP14 block (2 bytes)
+ * Block ID (5 bytes - ASCII "Adobe")
+ * Version Number (2 bytes - currently 100)
+ * Flags0 (2 bytes - currently 0)
+ * Flags1 (2 bytes - currently 0)
+ * Color transform (1 byte)
+ *
+ * Although Adobe TN 5116 mentions Version = 101, all the Adobe files
+ * now in circulation seem to use Version = 100, so that's what we write.
+ *
+ * We write the color transform byte as 1 if the JPEG color space is
+ * YCbCr, 2 if it's YCCK, 0 otherwise. Adobe's definition has to do with
+ * whether the encoder performed a transformation, which is pretty useless.
+ */
+
+ emit_marker(cinfo, M_APP14);
+
+ emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */
+
+ emit_byte(cinfo, 0x41); /* Identifier: ASCII "Adobe" */
+ emit_byte(cinfo, 0x64);
+ emit_byte(cinfo, 0x6F);
+ emit_byte(cinfo, 0x62);
+ emit_byte(cinfo, 0x65);
+ emit_2bytes(cinfo, 100); /* Version */
+ emit_2bytes(cinfo, 0); /* Flags0 */
+ emit_2bytes(cinfo, 0); /* Flags1 */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_YCbCr:
+ emit_byte(cinfo, 1); /* Color transform = 1 */
+ break;
+ case JCS_YCCK:
+ emit_byte(cinfo, 2); /* Color transform = 2 */
+ break;
+ default:
+ emit_byte(cinfo, 0); /* Color transform = 0 */
+ break;
+ }
+}
+
+
+/*
+ * These routines allow writing an arbitrary marker with parameters.
+ * The only intended use is to emit COM or APPn markers after calling
+ * write_file_header and before calling write_frame_header.
+ * Other uses are not guaranteed to produce desirable results.
+ * Counting the parameter bytes properly is the caller's responsibility.
+ */
+
+METHODDEF(void)
+write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen)
+/* Emit an arbitrary marker header */
+{
+ if (datalen > (unsigned int) 65533) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ emit_marker(cinfo, (JPEG_MARKER) marker);
+
+ emit_2bytes(cinfo, (int) (datalen + 2)); /* total length */
+}
+
+METHODDEF(void)
+write_marker_byte (j_compress_ptr cinfo, int val)
+/* Emit one byte of marker parameters following write_marker_header */
+{
+ emit_byte(cinfo, val);
+}
+
+
+/*
+ * Write datastream header.
+ * This consists of an SOI and optional APPn markers.
+ * We recommend use of the JFIF marker, but not the Adobe marker,
+ * when using YCbCr or grayscale data. The JFIF marker should NOT
+ * be used for any other JPEG colorspace. The Adobe marker is helpful
+ * to distinguish RGB, CMYK, and YCCK colorspaces.
+ * Note that an application can write additional header markers after
+ * jpeg_start_compress returns.
+ */
+
+METHODDEF(void)
+write_file_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ emit_marker(cinfo, M_SOI); /* first the SOI */
+
+ /* SOI is defined to reset restart interval to 0 */
+ marker->last_restart_interval = 0;
+
+ if (cinfo->write_JFIF_header) /* next an optional JFIF APP0 */
+ emit_jfif_app0(cinfo);
+ if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */
+ emit_adobe_app14(cinfo);
+}
+
+
+/*
+ * Write frame header.
+ * This consists of DQT and SOFn markers.
+ * Note that we do not emit the SOF until we have emitted the DQT(s).
+ * This avoids compatibility problems with incorrect implementations that
+ * try to error-check the quant table numbers as soon as they see the SOF.
+ */
+
+METHODDEF(void)
+write_frame_header (j_compress_ptr cinfo)
+{
+ int ci, prec;
+ boolean is_baseline;
+ jpeg_component_info *compptr;
+
+ /* Emit DQT for each quantization table.
+ * Note that emit_dqt() suppresses any duplicate tables.
+ */
+ prec = 0;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prec += emit_dqt(cinfo, compptr->quant_tbl_no);
+ }
+ /* now prec is nonzero iff there are any 16-bit quant tables. */
+
+ /* Check for a non-baseline specification.
+ * Note we assume that Huffman table numbers won't be changed later.
+ */
+ if (cinfo->arith_code || cinfo->progressive_mode ||
+ cinfo->data_precision != 8) {
+ is_baseline = FALSE;
+ } else {
+ is_baseline = TRUE;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1)
+ is_baseline = FALSE;
+ }
+ if (prec && is_baseline) {
+ is_baseline = FALSE;
+ /* If it's baseline except for quantizer size, warn the user */
+ TRACEMS(cinfo, 0, JTRC_16BIT_TABLES);
+ }
+ }
+
+ /* Emit the proper SOF marker */
+ if (cinfo->arith_code) {
+ if (cinfo->progressive_mode)
+ emit_sof(cinfo, M_SOF10); /* SOF code for progressive arithmetic */
+ else
+ emit_sof(cinfo, M_SOF9); /* SOF code for sequential arithmetic */
+ } else {
+ if (cinfo->progressive_mode)
+ emit_sof(cinfo, M_SOF2); /* SOF code for progressive Huffman */
+ else if (is_baseline)
+ emit_sof(cinfo, M_SOF0); /* SOF code for baseline implementation */
+ else
+ emit_sof(cinfo, M_SOF1); /* SOF code for non-baseline Huffman file */
+ }
+}
+
+
+/*
+ * Write scan header.
+ * This consists of DHT or DAC markers, optional DRI, and SOS.
+ * Compressed data will be written following the SOS.
+ */
+
+METHODDEF(void)
+write_scan_header (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ int i;
+ jpeg_component_info *compptr;
+
+ if (cinfo->arith_code) {
+ /* Emit arith conditioning info. We may have some duplication
+ * if the file has multiple scans, but it's so small it's hardly
+ * worth worrying about.
+ */
+ emit_dac(cinfo);
+ } else {
+ /* Emit Huffman tables.
+ * Note that emit_dht() suppresses any duplicate tables.
+ */
+ for (i = 0; i < cinfo->comps_in_scan; i++) {
+ compptr = cinfo->cur_comp_info[i];
+ if (cinfo->progressive_mode) {
+ /* Progressive mode: only DC or only AC tables are used in one scan */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah == 0) /* DC needs no table for refinement scan */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ } else {
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ } else {
+ /* Sequential mode: need both DC and AC tables */
+ emit_dht(cinfo, compptr->dc_tbl_no, FALSE);
+ emit_dht(cinfo, compptr->ac_tbl_no, TRUE);
+ }
+ }
+ }
+
+ /* Emit DRI if required --- note that DRI value could change for each scan.
+ * We avoid wasting space with unnecessary DRIs, however.
+ */
+ if (cinfo->restart_interval != marker->last_restart_interval) {
+ emit_dri(cinfo);
+ marker->last_restart_interval = cinfo->restart_interval;
+ }
+
+ emit_sos(cinfo);
+}
+
+
+/*
+ * Write datastream trailer.
+ */
+
+METHODDEF(void)
+write_file_trailer (j_compress_ptr cinfo)
+{
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Write an abbreviated table-specification datastream.
+ * This consists of SOI, DQT and DHT tables, and EOI.
+ * Any table that is defined and not marked sent_table = TRUE will be
+ * emitted. Note that all tables will be marked sent_table = TRUE at exit.
+ */
+
+METHODDEF(void)
+write_tables_only (j_compress_ptr cinfo)
+{
+ int i;
+
+ emit_marker(cinfo, M_SOI);
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++) {
+ if (cinfo->quant_tbl_ptrs[i] != NULL)
+ (void) emit_dqt(cinfo, i);
+ }
+
+ if (! cinfo->arith_code) {
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ if (cinfo->dc_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, FALSE);
+ if (cinfo->ac_huff_tbl_ptrs[i] != NULL)
+ emit_dht(cinfo, i, TRUE);
+ }
+ }
+
+ emit_marker(cinfo, M_EOI);
+}
+
+
+/*
+ * Initialize the marker writer module.
+ */
+
+GLOBAL(void)
+jinit_marker_writer (j_compress_ptr cinfo)
+{
+ my_marker_ptr marker;
+
+ /* Create the subobject */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_marker_writer));
+ cinfo->marker = (struct jpeg_marker_writer *) marker;
+ /* Initialize method pointers */
+ marker->pub.write_file_header = write_file_header;
+ marker->pub.write_frame_header = write_frame_header;
+ marker->pub.write_scan_header = write_scan_header;
+ marker->pub.write_file_trailer = write_file_trailer;
+ marker->pub.write_tables_only = write_tables_only;
+ marker->pub.write_marker_header = write_marker_header;
+ marker->pub.write_marker_byte = write_marker_byte;
+ /* Initialize private state */
+ marker->last_restart_interval = 0;
+}
diff --git a/Source/LibJPEG/jcmaster.c b/Source/LibJPEG/jcmaster.c
new file mode 100644
index 0000000..db3e61a
--- /dev/null
+++ b/Source/LibJPEG/jcmaster.c
@@ -0,0 +1,770 @@
+/*
+ * jcmaster.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2003-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG compressor.
+ * These routines are concerned with parameter validation, initial setup,
+ * and inter-pass control (determining the number of passes and the work
+ * to be done in each pass).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef enum {
+ main_pass, /* input data, also do first output step */
+ huff_opt_pass, /* Huffman code optimization pass */
+ output_pass /* data output pass */
+} c_pass_type;
+
+typedef struct {
+ struct jpeg_comp_master pub; /* public fields */
+
+ c_pass_type pass_type; /* the type of the current pass */
+
+ int pass_number; /* # of passes completed */
+ int total_passes; /* total # of passes needed */
+
+ int scan_number; /* current index in scan_info[] */
+} my_comp_master;
+
+typedef my_comp_master * my_master_ptr;
+
+
+/*
+ * Support routines that do various essential calculations.
+ */
+
+/*
+ * Compute JPEG image dimensions and related values.
+ * NOTE: this is exported for possible use by application.
+ * Hence it mustn't do anything that can't be done twice.
+ */
+
+GLOBAL(void)
+jpeg_calc_jpeg_dimensions (j_compress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+#ifdef DCT_SCALING_SUPPORTED
+
+ /* Compute actual JPEG image dimensions and DCT scaling choices. */
+ if (cinfo->scale_num >= cinfo->scale_denom * 8) {
+ /* Provide 8/1 scaling */
+ cinfo->jpeg_width = cinfo->image_width << 3;
+ cinfo->jpeg_height = cinfo->image_height << 3;
+ cinfo->min_DCT_h_scaled_size = 1;
+ cinfo->min_DCT_v_scaled_size = 1;
+ } else if (cinfo->scale_num >= cinfo->scale_denom * 4) {
+ /* Provide 4/1 scaling */
+ cinfo->jpeg_width = cinfo->image_width << 2;
+ cinfo->jpeg_height = cinfo->image_height << 2;
+ cinfo->min_DCT_h_scaled_size = 2;
+ cinfo->min_DCT_v_scaled_size = 2;
+ } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 8) {
+ /* Provide 8/3 scaling */
+ cinfo->jpeg_width = (cinfo->image_width << 1) + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 2, 3L);
+ cinfo->jpeg_height = (cinfo->image_height << 1) + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 2, 3L);
+ cinfo->min_DCT_h_scaled_size = 3;
+ cinfo->min_DCT_v_scaled_size = 3;
+ } else if (cinfo->scale_num >= cinfo->scale_denom * 2) {
+ /* Provide 2/1 scaling */
+ cinfo->jpeg_width = cinfo->image_width << 1;
+ cinfo->jpeg_height = cinfo->image_height << 1;
+ cinfo->min_DCT_h_scaled_size = 4;
+ cinfo->min_DCT_v_scaled_size = 4;
+ } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * 8) {
+ /* Provide 8/5 scaling */
+ cinfo->jpeg_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 3, 5L);
+ cinfo->jpeg_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 3, 5L);
+ cinfo->min_DCT_h_scaled_size = 5;
+ cinfo->min_DCT_v_scaled_size = 5;
+ } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 4) {
+ /* Provide 4/3 scaling */
+ cinfo->jpeg_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 3L);
+ cinfo->jpeg_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 3L);
+ cinfo->min_DCT_h_scaled_size = 6;
+ cinfo->min_DCT_v_scaled_size = 6;
+ } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * 8) {
+ /* Provide 8/7 scaling */
+ cinfo->jpeg_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 7L);
+ cinfo->jpeg_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 7L);
+ cinfo->min_DCT_h_scaled_size = 7;
+ cinfo->min_DCT_v_scaled_size = 7;
+ } else if (cinfo->scale_num >= cinfo->scale_denom) {
+ /* Provide 1/1 scaling */
+ cinfo->jpeg_width = cinfo->image_width;
+ cinfo->jpeg_height = cinfo->image_height;
+ cinfo->min_DCT_h_scaled_size = DCTSIZE;
+ cinfo->min_DCT_v_scaled_size = DCTSIZE;
+ } else if (cinfo->scale_num * 9 >= cinfo->scale_denom * 8) {
+ /* Provide 8/9 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 8, 9L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 8, 9L);
+ cinfo->min_DCT_h_scaled_size = 9;
+ cinfo->min_DCT_v_scaled_size = 9;
+ } else if (cinfo->scale_num * 5 >= cinfo->scale_denom * 4) {
+ /* Provide 4/5 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 4, 5L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 4, 5L);
+ cinfo->min_DCT_h_scaled_size = 10;
+ cinfo->min_DCT_v_scaled_size = 10;
+ } else if (cinfo->scale_num * 11 >= cinfo->scale_denom * 8) {
+ /* Provide 8/11 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 8, 11L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 8, 11L);
+ cinfo->min_DCT_h_scaled_size = 11;
+ cinfo->min_DCT_v_scaled_size = 11;
+ } else if (cinfo->scale_num * 3 >= cinfo->scale_denom * 2) {
+ /* Provide 2/3 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 2, 3L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 2, 3L);
+ cinfo->min_DCT_h_scaled_size = 12;
+ cinfo->min_DCT_v_scaled_size = 12;
+ } else if (cinfo->scale_num * 13 >= cinfo->scale_denom * 8) {
+ /* Provide 8/13 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 8, 13L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 8, 13L);
+ cinfo->min_DCT_h_scaled_size = 13;
+ cinfo->min_DCT_v_scaled_size = 13;
+ } else if (cinfo->scale_num * 7 >= cinfo->scale_denom * 4) {
+ /* Provide 4/7 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 4, 7L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 4, 7L);
+ cinfo->min_DCT_h_scaled_size = 14;
+ cinfo->min_DCT_v_scaled_size = 14;
+ } else if (cinfo->scale_num * 15 >= cinfo->scale_denom * 8) {
+ /* Provide 8/15 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 8, 15L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 8, 15L);
+ cinfo->min_DCT_h_scaled_size = 15;
+ cinfo->min_DCT_v_scaled_size = 15;
+ } else {
+ /* Provide 1/2 scaling */
+ cinfo->jpeg_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 2L);
+ cinfo->jpeg_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 2L);
+ cinfo->min_DCT_h_scaled_size = 16;
+ cinfo->min_DCT_v_scaled_size = 16;
+ }
+
+#else /* !DCT_SCALING_SUPPORTED */
+
+ /* Hardwire it to "no scaling" */
+ cinfo->jpeg_width = cinfo->image_width;
+ cinfo->jpeg_height = cinfo->image_height;
+ cinfo->min_DCT_h_scaled_size = DCTSIZE;
+ cinfo->min_DCT_v_scaled_size = DCTSIZE;
+
+#endif /* DCT_SCALING_SUPPORTED */
+}
+
+
+LOCAL(void)
+initial_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+ int ci, ssize;
+ jpeg_component_info *compptr;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ jpeg_calc_jpeg_dimensions(cinfo);
+
+ /* Sanity check on image dimensions */
+ if (cinfo->jpeg_height <= 0 || cinfo->jpeg_width <= 0
+ || cinfo->num_components <= 0 || cinfo->input_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->jpeg_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->jpeg_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ /* Width of an input scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Fill in the correct component_index value; don't rely on application */
+ compptr->component_index = ci;
+ /* In selecting the actual DCT scaling for each component, we try to
+ * scale down the chroma components via DCT scaling rather than downsampling.
+ * This saves time if the downsampler gets to use 1:1 scaling.
+ * Note this code adapts subsampling ratios which are powers of 2.
+ */
+ ssize = 1;
+#ifdef DCT_SCALING_SUPPORTED
+ while (cinfo->min_DCT_h_scaled_size * ssize <=
+ (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) &&
+ (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) {
+ ssize = ssize * 2;
+ }
+#endif
+ compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize;
+ ssize = 1;
+#ifdef DCT_SCALING_SUPPORTED
+ while (cinfo->min_DCT_v_scaled_size * ssize <=
+ (cinfo->do_fancy_downsampling ? DCTSIZE : DCTSIZE / 2) &&
+ (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) {
+ ssize = ssize * 2;
+ }
+#endif
+ compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize;
+
+ /* We don't support DCT ratios larger than 2. */
+ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2)
+ compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2;
+ else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2)
+ compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2;
+
+ /* Size in DCT blocks */
+ compptr->width_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->height_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_width *
+ (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size),
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_height *
+ (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size),
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* Mark component needed (this flag isn't actually used for compression) */
+ compptr->component_needed = TRUE;
+ }
+
+ /* Compute number of fully interleaved MCU rows (number of times that
+ * main controller will call coefficient controller).
+ */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+}
+
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+
+LOCAL(void)
+validate_script (j_compress_ptr cinfo)
+/* Verify that the scan script in cinfo->scan_info[] is valid; also
+ * determine whether it uses progressive JPEG, and set cinfo->progressive_mode.
+ */
+{
+ const jpeg_scan_info * scanptr;
+ int scanno, ncomps, ci, coefi, thisi;
+ int Ss, Se, Ah, Al;
+ boolean component_sent[MAX_COMPONENTS];
+#ifdef C_PROGRESSIVE_SUPPORTED
+ int * last_bitpos_ptr;
+ int last_bitpos[MAX_COMPONENTS][DCTSIZE2];
+ /* -1 until that coefficient has been seen; then last Al for it */
+#endif
+
+ if (cinfo->num_scans <= 0)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0);
+
+ /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
+ * for progressive JPEG, no scan can have this.
+ */
+ scanptr = cinfo->scan_info;
+ if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ cinfo->progressive_mode = TRUE;
+ last_bitpos_ptr = & last_bitpos[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (coefi = 0; coefi < DCTSIZE2; coefi++)
+ *last_bitpos_ptr++ = -1;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->progressive_mode = FALSE;
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ component_sent[ci] = FALSE;
+ }
+
+ for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) {
+ /* Validate component indexes */
+ ncomps = scanptr->comps_in_scan;
+ if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN);
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (thisi < 0 || thisi >= cinfo->num_components)
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ /* Components must appear in SOF order within each scan */
+ if (ci > 0 && thisi <= scanptr->component_index[ci-1])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ }
+ /* Validate progression parameters */
+ Ss = scanptr->Ss;
+ Se = scanptr->Se;
+ Ah = scanptr->Ah;
+ Al = scanptr->Al;
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
+ * seems wrong: the upper bound ought to depend on data precision.
+ * Perhaps they really meant 0..N+1 for N-bit precision.
+ * Here we allow 0..10 for 8-bit data; Al larger than 10 results in
+ * out-of-range reconstructed DC values during the first DC scan,
+ * which might cause problems for some decoders.
+ */
+#if BITS_IN_JSAMPLE == 8
+#define MAX_AH_AL 10
+#else
+#define MAX_AH_AL 13
+#endif
+ if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 ||
+ Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ if (Ss == 0) {
+ if (Se != 0) /* DC and AC together not OK */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ if (ncomps != 1) /* AC scans must be for only one component */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ for (ci = 0; ci < ncomps; ci++) {
+ last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0];
+ if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ for (coefi = Ss; coefi <= Se; coefi++) {
+ if (last_bitpos_ptr[coefi] < 0) {
+ /* first scan of this coefficient */
+ if (Ah != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ } else {
+ /* not first scan */
+ if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ }
+ last_bitpos_ptr[coefi] = Al;
+ }
+ }
+#endif
+ } else {
+ /* For sequential JPEG, all progression parameters must be these: */
+ if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0)
+ ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno);
+ /* Make sure components are not sent twice */
+ for (ci = 0; ci < ncomps; ci++) {
+ thisi = scanptr->component_index[ci];
+ if (component_sent[thisi])
+ ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno);
+ component_sent[thisi] = TRUE;
+ }
+ }
+ }
+
+ /* Now verify that everything got sent. */
+ if (cinfo->progressive_mode) {
+#ifdef C_PROGRESSIVE_SUPPORTED
+ /* For progressive mode, we only check that at least some DC data
+ * got sent for each component; the spec does not require that all bits
+ * of all coefficients be transmitted. Would it be wiser to enforce
+ * transmission of all coefficient bits??
+ */
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (last_bitpos[ci][0] < 0)
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+#endif
+ } else {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ if (! component_sent[ci])
+ ERREXIT(cinfo, JERR_MISSING_DATA);
+ }
+ }
+}
+
+#endif /* C_MULTISCAN_FILES_SUPPORTED */
+
+
+LOCAL(void)
+select_scan_parameters (j_compress_ptr cinfo)
+/* Set up the scan parameters for the current scan */
+{
+ int ci;
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (cinfo->scan_info != NULL) {
+ /* Prepare for current scan --- the script is already validated */
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number;
+
+ cinfo->comps_in_scan = scanptr->comps_in_scan;
+ for (ci = 0; ci < scanptr->comps_in_scan; ci++) {
+ cinfo->cur_comp_info[ci] =
+ &cinfo->comp_info[scanptr->component_index[ci]];
+ }
+ cinfo->Ss = scanptr->Ss;
+ cinfo->Se = scanptr->Se;
+ cinfo->Ah = scanptr->Ah;
+ cinfo->Al = scanptr->Al;
+ }
+ else
+#endif
+ {
+ /* Prepare for single sequential-JPEG scan containing all components */
+ if (cinfo->num_components > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPS_IN_SCAN);
+ cinfo->comps_in_scan = cinfo->num_components;
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci];
+ }
+ cinfo->Ss = 0;
+ cinfo->Se = DCTSIZE2-1;
+ cinfo->Ah = 0;
+ cinfo->Al = 0;
+ }
+}
+
+
+LOCAL(void)
+per_scan_setup (j_compress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_blocks;
+ cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
+
+ /* For noninterleaved scan, always one block per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_blocks = 1;
+ compptr->MCU_sample_width = compptr->DCT_h_scaled_size;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of block rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->blocks_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_width,
+ (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->jpeg_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ cinfo->blocks_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of blocks of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size;
+ /* Figure number of non-dummy blocks in last MCU column & row */
+ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_blocks;
+ if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+ }
+ }
+
+ }
+
+ /* Convert restart specified in rows to actual MCU count. */
+ /* Note that count must fit in 16 bits, so we provide limiting. */
+ if (cinfo->restart_in_rows > 0) {
+ long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row;
+ cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L);
+ }
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each pass. We determine which modules
+ * will be active during this pass and give them appropriate start_pass calls.
+ * We also set is_last_pass to indicate whether any more passes will be
+ * required.
+ */
+
+METHODDEF(void)
+prepare_for_pass (j_compress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ switch (master->pass_type) {
+ case main_pass:
+ /* Initial pass: will collect input data, and do either Huffman
+ * optimization or data output for the first scan.
+ */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if (! cinfo->raw_data_in) {
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->downsample->start_pass) (cinfo);
+ (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ (*cinfo->fdct->start_pass) (cinfo);
+ (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding);
+ (*cinfo->coef->start_pass) (cinfo,
+ (master->total_passes > 1 ?
+ JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ if (cinfo->optimize_coding) {
+ /* No immediate data output; postpone writing frame/scan headers */
+ master->pub.call_pass_startup = FALSE;
+ } else {
+ /* Will write frame/scan headers at first jpeg_write_scanlines call */
+ master->pub.call_pass_startup = TRUE;
+ }
+ break;
+#ifdef ENTROPY_OPT_SUPPORTED
+ case huff_opt_pass:
+ /* Do Huffman optimization for a scan after the first one. */
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ if (cinfo->Ss != 0 || cinfo->Ah == 0) {
+ (*cinfo->entropy->start_pass) (cinfo, TRUE);
+ (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ }
+ /* Special case: Huffman DC refinement scans need no Huffman table
+ * and therefore we can skip the optimization pass for them.
+ */
+ master->pass_type = output_pass;
+ master->pass_number++;
+ /*FALLTHROUGH*/
+#endif
+ case output_pass:
+ /* Do a data-output pass. */
+ /* We need not repeat per-scan setup if prior optimization pass did it. */
+ if (! cinfo->optimize_coding) {
+ select_scan_parameters(cinfo);
+ per_scan_setup(cinfo);
+ }
+ (*cinfo->entropy->start_pass) (cinfo, FALSE);
+ (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST);
+ /* We emit frame/scan headers now */
+ if (master->scan_number == 0)
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+ master->pub.call_pass_startup = FALSE;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ }
+
+ master->pub.is_last_pass = (master->pass_number == master->total_passes-1);
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->total_passes;
+ }
+}
+
+
+/*
+ * Special start-of-pass hook.
+ * This is called by jpeg_write_scanlines if call_pass_startup is TRUE.
+ * In single-pass processing, we need this hook because we don't want to
+ * write frame/scan headers during jpeg_start_compress; we want to let the
+ * application write COM markers etc. between jpeg_start_compress and the
+ * jpeg_write_scanlines loop.
+ * In multi-pass processing, this routine is not used.
+ */
+
+METHODDEF(void)
+pass_startup (j_compress_ptr cinfo)
+{
+ cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */
+
+ (*cinfo->marker->write_frame_header) (cinfo);
+ (*cinfo->marker->write_scan_header) (cinfo);
+}
+
+
+/*
+ * Finish up at end of pass.
+ */
+
+METHODDEF(void)
+finish_pass_master (j_compress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* The entropy coder always needs an end-of-pass call,
+ * either to analyze statistics or to flush its output buffer.
+ */
+ (*cinfo->entropy->finish_pass) (cinfo);
+
+ /* Update state for next pass */
+ switch (master->pass_type) {
+ case main_pass:
+ /* next pass is either output of scan 0 (after optimization)
+ * or output of scan 1 (if no optimization).
+ */
+ master->pass_type = output_pass;
+ if (! cinfo->optimize_coding)
+ master->scan_number++;
+ break;
+ case huff_opt_pass:
+ /* next pass is always output of current scan */
+ master->pass_type = output_pass;
+ break;
+ case output_pass:
+ /* next pass is either optimization or output of next scan */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ master->scan_number++;
+ break;
+ }
+
+ master->pass_number++;
+}
+
+
+/*
+ * Initialize master compression control.
+ */
+
+GLOBAL(void)
+jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_comp_master));
+ cinfo->master = (struct jpeg_comp_master *) master;
+ master->pub.prepare_for_pass = prepare_for_pass;
+ master->pub.pass_startup = pass_startup;
+ master->pub.finish_pass = finish_pass_master;
+ master->pub.is_last_pass = FALSE;
+
+ /* Validate parameters, determine derived values */
+ initial_setup(cinfo);
+
+ if (cinfo->scan_info != NULL) {
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ validate_script(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ cinfo->progressive_mode = FALSE;
+ cinfo->num_scans = 1;
+ }
+
+ if (cinfo->progressive_mode && cinfo->arith_code == 0) /* TEMPORARY HACK ??? */
+ cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */
+
+ /* Initialize my private state */
+ if (transcode_only) {
+ /* no main pass in transcoding */
+ if (cinfo->optimize_coding)
+ master->pass_type = huff_opt_pass;
+ else
+ master->pass_type = output_pass;
+ } else {
+ /* for normal compression, first pass is always this type: */
+ master->pass_type = main_pass;
+ }
+ master->scan_number = 0;
+ master->pass_number = 0;
+ if (cinfo->optimize_coding)
+ master->total_passes = cinfo->num_scans * 2;
+ else
+ master->total_passes = cinfo->num_scans;
+}
diff --git a/Source/LibJPEG/jcomapi.c b/Source/LibJPEG/jcomapi.c
new file mode 100644
index 0000000..9b1fa75
--- /dev/null
+++ b/Source/LibJPEG/jcomapi.c
@@ -0,0 +1,106 @@
+/*
+ * jcomapi.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface routines that are used for both
+ * compression and decompression.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Abort processing of a JPEG compression or decompression operation,
+ * but don't destroy the object itself.
+ *
+ * For this, we merely clean up all the nonpermanent memory pools.
+ * Note that temp files (virtual arrays) are not allowed to belong to
+ * the permanent pool, so we will be able to close all temp files here.
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_abort (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Do nothing if called on a not-initialized or destroyed JPEG object. */
+ if (cinfo->mem == NULL)
+ return;
+
+ /* Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) {
+ (*cinfo->mem->free_pool) (cinfo, pool);
+ }
+
+ /* Reset overall state for possible reuse of object */
+ if (cinfo->is_decompressor) {
+ cinfo->global_state = DSTATE_START;
+ /* Try to keep application from accessing now-deleted marker list.
+ * A bit kludgy to do it here, but this is the most central place.
+ */
+ ((j_decompress_ptr) cinfo)->marker_list = NULL;
+ } else {
+ cinfo->global_state = CSTATE_START;
+ }
+}
+
+
+/*
+ * Destruction of a JPEG object.
+ *
+ * Everything gets deallocated except the master jpeg_compress_struct itself
+ * and the error manager struct. Both of these are supplied by the application
+ * and must be freed, if necessary, by the application. (Often they are on
+ * the stack and so don't need to be freed anyway.)
+ * Closing a data source or destination, if necessary, is the application's
+ * responsibility.
+ */
+
+GLOBAL(void)
+jpeg_destroy (j_common_ptr cinfo)
+{
+ /* We need only tell the memory manager to release everything. */
+ /* NB: mem pointer is NULL if memory mgr failed to initialize. */
+ if (cinfo->mem != NULL)
+ (*cinfo->mem->self_destruct) (cinfo);
+ cinfo->mem = NULL; /* be safe if jpeg_destroy is called twice */
+ cinfo->global_state = 0; /* mark it destroyed */
+}
+
+
+/*
+ * Convenience routines for allocating quantization and Huffman tables.
+ * (Would jutils.c be a more reasonable place to put these?)
+ */
+
+GLOBAL(JQUANT_TBL *)
+jpeg_alloc_quant_table (j_common_ptr cinfo)
+{
+ JQUANT_TBL *tbl;
+
+ tbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
+
+
+GLOBAL(JHUFF_TBL *)
+jpeg_alloc_huff_table (j_common_ptr cinfo)
+{
+ JHUFF_TBL *tbl;
+
+ tbl = (JHUFF_TBL *)
+ (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL));
+ tbl->sent_table = FALSE; /* make sure this is false in any new table */
+ return tbl;
+}
diff --git a/Source/LibJPEG/jconfig.h b/Source/LibJPEG/jconfig.h
new file mode 100644
index 0000000..1bd0e62
--- /dev/null
+++ b/Source/LibJPEG/jconfig.h
@@ -0,0 +1,145 @@
+
+#ifdef WIN32
+/* jconfig.vc --- jconfig.h for Microsoft Visual C++ on Windows 95 or NT. */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+/* #define void char */
+/* #define const */
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H
+#ifndef HAVE_STDLIB_H
+#define HAVE_STDLIB_H
+#endif
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS /* we presume a 32-bit flat memory model */
+#undef NEED_SHORT_EXTERNAL_NAMES
+#undef INCOMPLETE_TYPES_BROKEN
+
+/* Define "boolean" as unsigned char, not int, per Windows custom */
+#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+typedef unsigned char boolean;
+#endif
+#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+#define TWO_FILE_COMMANDLINE /* optional */
+#define USE_SETMODE /* Microsoft has setmode() */
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+#undef PROGRESS_REPORT /* optional */
+
+#endif /* JPEG_CJPEG_DJPEG */
+
+#elif defined (__APPLE__)
+
+/* jconfig.mac --- jconfig.h for Macintosh PPC and Intel */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+/* #define void char */
+/* #define const */
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS
+#undef NEED_SHORT_EXTERNAL_NAMES
+#undef INCOMPLETE_TYPES_BROKEN
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+#define USE_MAC_MEMMGR /* Define this if you use jmemmac.c */
+
+#define ALIGN_TYPE long /* Needed for 680x0 Macs */
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+/* #define USE_CCOMMAND => does not work with XCode, maybe for comes from MetroWerks, was: Command line reader for Macintosh */
+/* #define TWO_FILE_COMMANDLINE => I would be surprised if that is still true in the Mac today, was: Binary I/O thru stdin/stdout doesn't work */
+
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+#undef PROGRESS_REPORT /* optional */
+
+#endif /* JPEG_CJPEG_DJPEG */
+
+#else // Linux case by default
+
+/* jconfig.h. Generated automatically by configure. */
+/* jconfig.cfg --- source file edited by configure script */
+/* see jconfig.doc for explanations */
+
+#define HAVE_PROTOTYPES
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+#undef void
+#undef const
+#undef CHAR_IS_UNSIGNED
+#define HAVE_STDDEF_H
+#define HAVE_STDLIB_H
+#undef NEED_BSD_STRINGS
+#undef NEED_SYS_TYPES_H
+#undef NEED_FAR_POINTERS
+#undef NEED_SHORT_EXTERNAL_NAMES
+/* Define this if you get warnings about undefined structures. */
+#undef INCOMPLETE_TYPES_BROKEN
+
+#ifdef JPEG_INTERNALS
+
+#undef RIGHT_SHIFT_IS_UNSIGNED
+#define INLINE __inline__
+/* These are for configuring the JPEG memory manager. */
+#undef DEFAULT_MAX_MEM
+#undef NO_MKTEMP
+
+#endif /* JPEG_INTERNALS */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+#undef TWO_FILE_COMMANDLINE
+#undef NEED_SIGNAL_CATCHER
+#undef DONT_USE_B_MODE
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg. */
+#undef PROGRESS_REPORT
+
+#endif /* JPEG_CJPEG_DJPEG */
+
+#endif
diff --git a/Source/LibJPEG/jconfig.txt b/Source/LibJPEG/jconfig.txt
new file mode 100644
index 0000000..8819e79
--- /dev/null
+++ b/Source/LibJPEG/jconfig.txt
@@ -0,0 +1,155 @@
+/*
+ * jconfig.txt
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file documents the configuration options that are required to
+ * customize the JPEG software for a particular system.
+ *
+ * The actual configuration options for a particular installation are stored
+ * in jconfig.h. On many machines, jconfig.h can be generated automatically
+ * or copied from one of the "canned" jconfig files that we supply. But if
+ * you need to generate a jconfig.h file by hand, this file tells you how.
+ *
+ * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING.
+ * EDIT A COPY NAMED JCONFIG.H.
+ */
+
+
+/*
+ * These symbols indicate the properties of your machine or compiler.
+ * #define the symbol if yes, #undef it if no.
+ */
+
+/* Does your compiler support function prototypes?
+ * (If not, you also need to use ansi2knr, see install.txt)
+ */
+#define HAVE_PROTOTYPES
+
+/* Does your compiler support the declaration "unsigned char" ?
+ * How about "unsigned short" ?
+ */
+#define HAVE_UNSIGNED_CHAR
+#define HAVE_UNSIGNED_SHORT
+
+/* Define "void" as "char" if your compiler doesn't know about type void.
+ * NOTE: be sure to define void such that "void *" represents the most general
+ * pointer type, e.g., that returned by malloc().
+ */
+/* #define void char */
+
+/* Define "const" as empty if your compiler doesn't know the "const" keyword.
+ */
+/* #define const */
+
+/* Define this if an ordinary "char" type is unsigned.
+ * If you're not sure, leaving it undefined will work at some cost in speed.
+ * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal.
+ */
+#undef CHAR_IS_UNSIGNED
+
+/* Define this if your system has an ANSI-conforming <stddef.h> file.
+ */
+#define HAVE_STDDEF_H
+
+/* Define this if your system has an ANSI-conforming <stdlib.h> file.
+ */
+#define HAVE_STDLIB_H
+
+/* Define this if your system does not have an ANSI/SysV <string.h>,
+ * but does have a BSD-style <strings.h>.
+ */
+#undef NEED_BSD_STRINGS
+
+/* Define this if your system does not provide typedef size_t in any of the
+ * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in
+ * <sys/types.h> instead.
+ */
+#undef NEED_SYS_TYPES_H
+
+/* For 80x86 machines, you need to define NEED_FAR_POINTERS,
+ * unless you are using a large-data memory model or 80386 flat-memory mode.
+ * On less brain-damaged CPUs this symbol must not be defined.
+ * (Defining this symbol causes large data structures to be referenced through
+ * "far" pointers and to be allocated with a special version of malloc.)
+ */
+#undef NEED_FAR_POINTERS
+
+/* Define this if your linker needs global names to be unique in less
+ * than the first 15 characters.
+ */
+#undef NEED_SHORT_EXTERNAL_NAMES
+
+/* Although a real ANSI C compiler can deal perfectly well with pointers to
+ * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI
+ * and pseudo-ANSI compilers get confused. To keep one of these bozos happy,
+ * define INCOMPLETE_TYPES_BROKEN. This is not recommended unless you
+ * actually get "missing structure definition" warnings or errors while
+ * compiling the JPEG code.
+ */
+#undef INCOMPLETE_TYPES_BROKEN
+
+
+/*
+ * The following options affect code selection within the JPEG library,
+ * but they don't need to be visible to applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+
+/* Define this if your compiler implements ">>" on signed values as a logical
+ * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift,
+ * which is the normal and rational definition.
+ */
+#undef RIGHT_SHIFT_IS_UNSIGNED
+
+
+#endif /* JPEG_INTERNALS */
+
+
+/*
+ * The remaining options do not affect the JPEG library proper,
+ * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c).
+ * Other applications can ignore these.
+ */
+
+#ifdef JPEG_CJPEG_DJPEG
+
+/* These defines indicate which image (non-JPEG) file formats are allowed. */
+
+#define BMP_SUPPORTED /* BMP image file format */
+#define GIF_SUPPORTED /* GIF image file format */
+#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
+#undef RLE_SUPPORTED /* Utah RLE image file format */
+#define TARGA_SUPPORTED /* Targa image file format */
+
+/* Define this if you want to name both input and output files on the command
+ * line, rather than using stdout and optionally stdin. You MUST do this if
+ * your system can't cope with binary I/O to stdin/stdout. See comments at
+ * head of cjpeg.c or djpeg.c.
+ */
+#undef TWO_FILE_COMMANDLINE
+
+/* Define this if your system needs explicit cleanup of temporary files.
+ * This is crucial under MS-DOS, where the temporary "files" may be areas
+ * of extended memory; on most other systems it's not as important.
+ */
+#undef NEED_SIGNAL_CATCHER
+
+/* By default, we open image files with fopen(...,"rb") or fopen(...,"wb").
+ * This is necessary on systems that distinguish text files from binary files,
+ * and is harmless on most systems that don't. If you have one of the rare
+ * systems that complains about the "b" spec, define this symbol.
+ */
+#undef DONT_USE_B_MODE
+
+/* Define this if you want percent-done progress reports from cjpeg/djpeg.
+ */
+#undef PROGRESS_REPORT
+
+
+#endif /* JPEG_CJPEG_DJPEG */
diff --git a/Source/LibJPEG/jcparam.c b/Source/LibJPEG/jcparam.c
new file mode 100644
index 0000000..c5e85dd
--- /dev/null
+++ b/Source/LibJPEG/jcparam.c
@@ -0,0 +1,632 @@
+/*
+ * jcparam.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * Modified 2003-2008 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains optional default-setting code for the JPEG compressor.
+ * Applications do not have to use this file, but those that don't use it
+ * must know a lot more about the innards of the JPEG code.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Quantization table setup routines
+ */
+
+GLOBAL(void)
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline)
+/* Define a quantization table equal to the basic_table times
+ * a scale factor (given as a percentage).
+ * If force_baseline is TRUE, the computed quantization table entries
+ * are limited to 1..255 for JPEG baseline compatibility.
+ */
+{
+ JQUANT_TBL ** qtblptr;
+ int i;
+ long temp;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl);
+
+ qtblptr = & cinfo->quant_tbl_ptrs[which_tbl];
+
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
+ /* limit the values to the valid range */
+ if (temp <= 0L) temp = 1L;
+ if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */
+ if (force_baseline && temp > 255L)
+ temp = 255L; /* limit to baseline range if requested */
+ (*qtblptr)->quantval[i] = (UINT16) temp;
+ }
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*qtblptr)->sent_table = FALSE;
+}
+
+
+/* These are the sample quantization tables given in JPEG spec section K.1.
+ * The spec says that the values given produce "good" quality, and
+ * when divided by 2, "very good" quality.
+ */
+static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = {
+ 16, 11, 10, 16, 24, 40, 51, 61,
+ 12, 12, 14, 19, 26, 58, 60, 55,
+ 14, 13, 16, 24, 40, 57, 69, 56,
+ 14, 17, 22, 29, 51, 87, 80, 62,
+ 18, 22, 37, 56, 68, 109, 103, 77,
+ 24, 35, 55, 64, 81, 104, 113, 92,
+ 49, 64, 78, 87, 103, 121, 120, 101,
+ 72, 92, 95, 98, 112, 100, 103, 99
+};
+static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = {
+ 17, 18, 24, 47, 99, 99, 99, 99,
+ 18, 21, 26, 66, 99, 99, 99, 99,
+ 24, 26, 56, 99, 99, 99, 99, 99,
+ 47, 66, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+};
+
+
+GLOBAL(void)
+jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables
+ * and straight percentage-scaling quality scales.
+ * This entry point allows different scalings for luminance and chrominance.
+ */
+{
+ /* Set up two quantization tables using the specified scaling */
+ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
+ cinfo->q_scale_factor[0], force_baseline);
+ jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
+ cinfo->q_scale_factor[1], force_baseline);
+}
+
+
+GLOBAL(void)
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables
+ * and a straight percentage-scaling quality scale. In most cases it's better
+ * to use jpeg_set_quality (below); this entry point is provided for
+ * applications that insist on a linear percentage scaling.
+ */
+{
+ /* Set up two quantization tables using the specified scaling */
+ jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl,
+ scale_factor, force_baseline);
+ jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl,
+ scale_factor, force_baseline);
+}
+
+
+GLOBAL(int)
+jpeg_quality_scaling (int quality)
+/* Convert a user-specified quality rating to a percentage scaling factor
+ * for an underlying quantization table, using our recommended scaling curve.
+ * The input 'quality' factor should be 0 (terrible) to 100 (very good).
+ */
+{
+ /* Safety limit on quality factor. Convert 0 to 1 to avoid zero divide. */
+ if (quality <= 0) quality = 1;
+ if (quality > 100) quality = 100;
+
+ /* The basic table is used as-is (scaling 100) for a quality of 50.
+ * Qualities 50..100 are converted to scaling percentage 200 - 2*Q;
+ * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table
+ * to make all the table entries 1 (hence, minimum quantization loss).
+ * Qualities 1..50 are converted to scaling percentage 5000/Q.
+ */
+ if (quality < 50)
+ quality = 5000 / quality;
+ else
+ quality = 200 - quality*2;
+
+ return quality;
+}
+
+
+GLOBAL(void)
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+/* Set or change the 'quality' (quantization) setting, using default tables.
+ * This is the standard quality-adjusting entry point for typical user
+ * interfaces; only those who want detailed control over quantization tables
+ * would use the preceding three routines directly.
+ */
+{
+ /* Convert user 0-100 rating to percentage scaling */
+ quality = jpeg_quality_scaling(quality);
+
+ /* Set up standard quality tables */
+ jpeg_set_linear_quality(cinfo, quality, force_baseline);
+}
+
+
+/*
+ * Huffman table setup routines
+ */
+
+LOCAL(void)
+add_huff_table (j_compress_ptr cinfo,
+ JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val)
+/* Define a Huffman table */
+{
+ int nsymbols, len;
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ /* Copy the number-of-symbols-of-each-code-length counts */
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+
+ /* Validate the counts. We do this here mainly so we can copy the right
+ * number of symbols from the val[] array, without risking marching off
+ * the end of memory. jchuff.c will do a more thorough test later.
+ */
+ nsymbols = 0;
+ for (len = 1; len <= 16; len++)
+ nsymbols += bits[len];
+ if (nsymbols < 1 || nsymbols > 256)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8));
+
+ /* Initialize sent_table FALSE so table will be written to JPEG file. */
+ (*htblptr)->sent_table = FALSE;
+}
+
+
+LOCAL(void)
+std_huff_tables (j_compress_ptr cinfo)
+/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */
+/* IMPORTANT: these are only valid for 8-bit data precision! */
+{
+ static const UINT8 bits_dc_luminance[17] =
+ { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_luminance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_dc_chrominance[17] =
+ { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 };
+ static const UINT8 val_dc_chrominance[] =
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
+
+ static const UINT8 bits_ac_luminance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d };
+ static const UINT8 val_ac_luminance[] =
+ { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ static const UINT8 bits_ac_chrominance[17] =
+ { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 };
+ static const UINT8 val_ac_chrominance[] =
+ { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa };
+
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0],
+ bits_dc_luminance, val_dc_luminance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0],
+ bits_ac_luminance, val_ac_luminance);
+ add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1],
+ bits_dc_chrominance, val_dc_chrominance);
+ add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1],
+ bits_ac_chrominance, val_ac_chrominance);
+}
+
+
+/*
+ * Default parameter setup for compression.
+ *
+ * Applications that don't choose to use this routine must do their
+ * own setup of all these parameters. Alternately, you can call this
+ * to establish defaults and then alter parameters selectively. This
+ * is the recommended approach since, if we add any new parameters,
+ * your code will still work (they'll be set to reasonable defaults).
+ */
+
+GLOBAL(void)
+jpeg_set_defaults (j_compress_ptr cinfo)
+{
+ int i;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Allocate comp_info array large enough for maximum component count.
+ * Array is made permanent in case application wants to compress
+ * multiple images at same param settings.
+ */
+ if (cinfo->comp_info == NULL)
+ cinfo->comp_info = (jpeg_component_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ MAX_COMPONENTS * SIZEOF(jpeg_component_info));
+
+ /* Initialize everything not dependent on the color space */
+
+ cinfo->scale_num = 1; /* 1:1 scaling */
+ cinfo->scale_denom = 1;
+ cinfo->data_precision = BITS_IN_JSAMPLE;
+ /* Set up two quantization tables using default quality of 75 */
+ jpeg_set_quality(cinfo, 75, TRUE);
+ /* Set up two Huffman tables */
+ std_huff_tables(cinfo);
+
+ /* Initialize default arithmetic coding conditioning */
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+
+ /* Default is no multiple-scan output */
+ cinfo->scan_info = NULL;
+ cinfo->num_scans = 0;
+
+ /* Expect normal source image, not raw downsampled data */
+ cinfo->raw_data_in = FALSE;
+
+ /* Use Huffman coding, not arithmetic coding, by default */
+ cinfo->arith_code = FALSE;
+
+ /* By default, don't do extra passes to optimize entropy coding */
+ cinfo->optimize_coding = FALSE;
+ /* The standard Huffman tables are only valid for 8-bit data precision.
+ * If the precision is higher, force optimization on so that usable
+ * tables will be computed. This test can be removed if default tables
+ * are supplied that are valid for the desired precision.
+ */
+ if (cinfo->data_precision > 8)
+ cinfo->optimize_coding = TRUE;
+
+ /* By default, use the simpler non-cosited sampling alignment */
+ cinfo->CCIR601_sampling = FALSE;
+
+ /* By default, apply fancy downsampling */
+ cinfo->do_fancy_downsampling = TRUE;
+
+ /* No input smoothing */
+ cinfo->smoothing_factor = 0;
+
+ /* DCT algorithm preference */
+ cinfo->dct_method = JDCT_DEFAULT;
+
+ /* No restart markers */
+ cinfo->restart_interval = 0;
+ cinfo->restart_in_rows = 0;
+
+ /* Fill in default JFIF marker parameters. Note that whether the marker
+ * will actually be written is determined by jpeg_set_colorspace.
+ *
+ * By default, the library emits JFIF version code 1.01.
+ * An application that wants to emit JFIF 1.02 extension markers should set
+ * JFIF_minor_version to 2. We could probably get away with just defaulting
+ * to 1.02, but there may still be some decoders in use that will complain
+ * about that; saying 1.01 should minimize compatibility problems.
+ */
+ cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0; /* Pixel size is unknown by default */
+ cinfo->X_density = 1; /* Pixel aspect ratio is square by default */
+ cinfo->Y_density = 1;
+
+ /* Choose JPEG colorspace based on input space, set defaults accordingly */
+
+ jpeg_default_colorspace(cinfo);
+}
+
+
+/*
+ * Select an appropriate JPEG colorspace for in_color_space.
+ */
+
+GLOBAL(void)
+jpeg_default_colorspace (j_compress_ptr cinfo)
+{
+ switch (cinfo->in_color_space) {
+ case JCS_GRAYSCALE:
+ jpeg_set_colorspace(cinfo, JCS_GRAYSCALE);
+ break;
+ case JCS_RGB:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_YCbCr:
+ jpeg_set_colorspace(cinfo, JCS_YCbCr);
+ break;
+ case JCS_CMYK:
+ jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */
+ break;
+ case JCS_YCCK:
+ jpeg_set_colorspace(cinfo, JCS_YCCK);
+ break;
+ case JCS_UNKNOWN:
+ jpeg_set_colorspace(cinfo, JCS_UNKNOWN);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
+ }
+}
+
+
+/*
+ * Set the JPEG colorspace, and choose colorspace-dependent default values.
+ */
+
+GLOBAL(void)
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+{
+ jpeg_component_info * compptr;
+ int ci;
+
+#define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl) \
+ (compptr = &cinfo->comp_info[index], \
+ compptr->component_id = (id), \
+ compptr->h_samp_factor = (hsamp), \
+ compptr->v_samp_factor = (vsamp), \
+ compptr->quant_tbl_no = (quant), \
+ compptr->dc_tbl_no = (dctbl), \
+ compptr->ac_tbl_no = (actbl) )
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* For all colorspaces, we use Q and Huff tables 0 for luminance components,
+ * tables 1 for chrominance components.
+ */
+
+ cinfo->jpeg_color_space = colorspace;
+
+ cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */
+ cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */
+
+ switch (colorspace) {
+ case JCS_GRAYSCALE:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 1;
+ /* JFIF specifies component ID 1 */
+ SET_COMP(0, 1, 1,1, 0, 0,0);
+ break;
+ case JCS_RGB:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */
+ cinfo->num_components = 3;
+ SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCbCr:
+ cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */
+ cinfo->num_components = 3;
+ /* JFIF specifies component IDs 1,2,3 */
+ /* We default to 2x2 subsamples of chrominance */
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ break;
+ case JCS_CMYK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */
+ cinfo->num_components = 4;
+ SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0);
+ SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0);
+ SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0);
+ SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0);
+ break;
+ case JCS_YCCK:
+ cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */
+ cinfo->num_components = 4;
+ SET_COMP(0, 1, 2,2, 0, 0,0);
+ SET_COMP(1, 2, 1,1, 1, 1,1);
+ SET_COMP(2, 3, 1,1, 1, 1,1);
+ SET_COMP(3, 4, 2,2, 0, 0,0);
+ break;
+ case JCS_UNKNOWN:
+ cinfo->num_components = cinfo->input_components;
+ if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ SET_COMP(ci, ci, 1,1, 0, 0,0);
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ }
+}
+
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+
+LOCAL(jpeg_scan_info *)
+fill_a_scan (jpeg_scan_info * scanptr, int ci,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for specified component */
+{
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_scans (jpeg_scan_info * scanptr, int ncomps,
+ int Ss, int Se, int Ah, int Al)
+/* Support routine: generate one scan for each component */
+{
+ int ci;
+
+ for (ci = 0; ci < ncomps; ci++) {
+ scanptr->comps_in_scan = 1;
+ scanptr->component_index[0] = ci;
+ scanptr->Ss = Ss;
+ scanptr->Se = Se;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ }
+ return scanptr;
+}
+
+LOCAL(jpeg_scan_info *)
+fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al)
+/* Support routine: generate interleaved DC scan if possible, else N scans */
+{
+ int ci;
+
+ if (ncomps <= MAX_COMPS_IN_SCAN) {
+ /* Single interleaved DC scan */
+ scanptr->comps_in_scan = ncomps;
+ for (ci = 0; ci < ncomps; ci++)
+ scanptr->component_index[ci] = ci;
+ scanptr->Ss = scanptr->Se = 0;
+ scanptr->Ah = Ah;
+ scanptr->Al = Al;
+ scanptr++;
+ } else {
+ /* Noninterleaved DC scan for each component */
+ scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al);
+ }
+ return scanptr;
+}
+
+
+/*
+ * Create a recommended progressive-JPEG script.
+ * cinfo->num_components and cinfo->jpeg_color_space must be correct.
+ */
+
+GLOBAL(void)
+jpeg_simple_progression (j_compress_ptr cinfo)
+{
+ int ncomps = cinfo->num_components;
+ int nscans;
+ jpeg_scan_info * scanptr;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ /* Figure space needed for script. Calculation must match code below! */
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ nscans = 10;
+ } else {
+ /* All-purpose script for other color spaces. */
+ if (ncomps > MAX_COMPS_IN_SCAN)
+ nscans = 6 * ncomps; /* 2 DC + 4 AC scans per component */
+ else
+ nscans = 2 + 4 * ncomps; /* 2 DC scans; 4 AC scans per component */
+ }
+
+ /* Allocate space for script.
+ * We need to put it in the permanent pool in case the application performs
+ * multiple compressions without changing the settings. To avoid a memory
+ * leak if jpeg_simple_progression is called repeatedly for the same JPEG
+ * object, we try to re-use previously allocated space, and we allocate
+ * enough space to handle YCbCr even if initially asked for grayscale.
+ */
+ if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) {
+ cinfo->script_space_size = MAX(nscans, 10);
+ cinfo->script_space = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ cinfo->script_space_size * SIZEOF(jpeg_scan_info));
+ }
+ scanptr = cinfo->script_space;
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = nscans;
+
+ if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) {
+ /* Custom script for YCbCr color images. */
+ /* Initial DC scan */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ /* Initial AC scan: get some luma data out in a hurry */
+ scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2);
+ /* Chroma data is too small to be worth expending many scans on */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1);
+ /* Complete spectral selection for luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2);
+ /* Refine next bit of luma AC */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1);
+ /* Finish DC successive approximation */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ /* Finish AC successive approximation */
+ scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0);
+ scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0);
+ /* Luma bottom bit comes last since it's usually largest scan */
+ scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0);
+ } else {
+ /* All-purpose script for other color spaces. */
+ /* Successive approximation first pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 0, 1);
+ scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2);
+ scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2);
+ /* Successive approximation second pass */
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1);
+ /* Successive approximation final pass */
+ scanptr = fill_dc_scans(scanptr, ncomps, 1, 0);
+ scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0);
+ }
+}
+
+#endif /* C_PROGRESSIVE_SUPPORTED */
diff --git a/Source/LibJPEG/jcprepct.c b/Source/LibJPEG/jcprepct.c
new file mode 100644
index 0000000..be44cc4
--- /dev/null
+++ b/Source/LibJPEG/jcprepct.c
@@ -0,0 +1,358 @@
+/*
+ * jcprepct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the compression preprocessing controller.
+ * This controller manages the color conversion, downsampling,
+ * and edge expansion steps.
+ *
+ * Most of the complexity here is associated with buffering input rows
+ * as required by the downsampler. See the comments at the head of
+ * jcsample.c for the downsampler's needs.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* At present, jcsample.c can request context rows only for smoothing.
+ * In the future, we might also need context rows for CCIR601 sampling
+ * or other more-complex downsampling procedures. The code to support
+ * context rows should be compiled only if needed.
+ */
+#ifdef INPUT_SMOOTHING_SUPPORTED
+#define CONTEXT_ROWS_SUPPORTED
+#endif
+
+
+/*
+ * For the simple (no-context-row) case, we just need to buffer one
+ * row group's worth of pixels for the downsampling step. At the bottom of
+ * the image, we pad to a full row group by replicating the last pixel row.
+ * The downsampler's last output row is then replicated if needed to pad
+ * out to a full iMCU row.
+ *
+ * When providing context rows, we must buffer three row groups' worth of
+ * pixels. Three row groups are physically allocated, but the row pointer
+ * arrays are made five row groups high, with the extra pointers above and
+ * below "wrapping around" to point to the last and first real row groups.
+ * This allows the downsampler to access the proper context rows.
+ * At the top and bottom of the image, we create dummy context rows by
+ * copying the first or last real pixel row. This copying could be avoided
+ * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the
+ * trouble on the compression side.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_prep_controller pub; /* public fields */
+
+ /* Downsampling input buffer. This buffer holds color-converted data
+ * until we have enough to do a downsample step.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ JDIMENSION rows_to_go; /* counts rows remaining in source image */
+ int next_buf_row; /* index of next row to store in color_buf */
+
+#ifdef CONTEXT_ROWS_SUPPORTED /* only needed for context case */
+ int this_row_group; /* starting row index of group to process */
+ int next_buf_stop; /* downsample when we reach this index */
+#endif
+} my_prep_controller;
+
+typedef my_prep_controller * my_prep_ptr;
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+
+ if (pass_mode != JBUF_PASS_THRU)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Initialize total-height counter for detecting bottom of image */
+ prep->rows_to_go = cinfo->image_height;
+ /* Mark the conversion buffer empty */
+ prep->next_buf_row = 0;
+#ifdef CONTEXT_ROWS_SUPPORTED
+ /* Preset additional state variables for context mode.
+ * These aren't used in non-context mode, so we needn't test which mode.
+ */
+ prep->this_row_group = 0;
+ /* Set next_buf_stop to stop after two row groups have been read in. */
+ prep->next_buf_stop = 2 * cinfo->max_v_samp_factor;
+#endif
+}
+
+
+/*
+ * Expand an image vertically from height input_rows to height output_rows,
+ * by duplicating the bottom row.
+ */
+
+LOCAL(void)
+expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols,
+ int input_rows, int output_rows)
+{
+ register int row;
+
+ for (row = input_rows; row < output_rows; row++) {
+ jcopy_sample_rows(image_data, input_rows-1, image_data, row,
+ 1, num_cols);
+ }
+}
+
+
+/*
+ * Process some data in the simple no-context case.
+ *
+ * Preprocessor output data is counted in "row groups". A row group
+ * is defined to be v_samp_factor sample rows of each component.
+ * Downsampling will produce this much data from each max_v_samp_factor
+ * input rows.
+ */
+
+METHODDEF(void)
+pre_process_data (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ JDIMENSION inrows;
+ jpeg_component_info * compptr;
+
+ while (*in_row_ctr < in_rows_avail &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = cinfo->max_v_samp_factor - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ /* If at bottom of image, pad to fill the conversion buffer. */
+ if (prep->rows_to_go == 0 &&
+ prep->next_buf_row < cinfo->max_v_samp_factor) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, cinfo->max_v_samp_factor);
+ }
+ prep->next_buf_row = cinfo->max_v_samp_factor;
+ }
+ /* If we've filled the conversion buffer, empty it. */
+ if (prep->next_buf_row == cinfo->max_v_samp_factor) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf, (JDIMENSION) 0,
+ output_buf, *out_row_group_ctr);
+ prep->next_buf_row = 0;
+ (*out_row_group_ctr)++;
+ }
+ /* If at bottom of image, pad the output to a full iMCU height.
+ * Note we assume the caller is providing a one-iMCU-height output buffer!
+ */
+ if (prep->rows_to_go == 0 &&
+ *out_row_group_ctr < out_row_groups_avail) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ numrows = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size;
+ expand_bottom_edge(output_buf[ci],
+ compptr->width_in_blocks * compptr->DCT_h_scaled_size,
+ (int) (*out_row_group_ctr * numrows),
+ (int) (out_row_groups_avail * numrows));
+ }
+ *out_row_group_ctr = out_row_groups_avail;
+ break; /* can exit outer loop without test */
+ }
+ }
+}
+
+
+#ifdef CONTEXT_ROWS_SUPPORTED
+
+/*
+ * Process some data in the context case.
+ */
+
+METHODDEF(void)
+pre_process_context (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int numrows, ci;
+ int buf_height = cinfo->max_v_samp_factor * 3;
+ JDIMENSION inrows;
+
+ while (*out_row_group_ctr < out_row_groups_avail) {
+ if (*in_row_ctr < in_rows_avail) {
+ /* Do color conversion to fill the conversion buffer. */
+ inrows = in_rows_avail - *in_row_ctr;
+ numrows = prep->next_buf_stop - prep->next_buf_row;
+ numrows = (int) MIN((JDIMENSION) numrows, inrows);
+ (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr,
+ prep->color_buf,
+ (JDIMENSION) prep->next_buf_row,
+ numrows);
+ /* Pad at top of image, if first time through */
+ if (prep->rows_to_go == cinfo->image_height) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ int row;
+ for (row = 1; row <= cinfo->max_v_samp_factor; row++) {
+ jcopy_sample_rows(prep->color_buf[ci], 0,
+ prep->color_buf[ci], -row,
+ 1, cinfo->image_width);
+ }
+ }
+ }
+ *in_row_ctr += numrows;
+ prep->next_buf_row += numrows;
+ prep->rows_to_go -= numrows;
+ } else {
+ /* Return for more data, unless we are at the bottom of the image. */
+ if (prep->rows_to_go != 0)
+ break;
+ /* When at bottom of image, pad to fill the conversion buffer. */
+ if (prep->next_buf_row < prep->next_buf_stop) {
+ for (ci = 0; ci < cinfo->num_components; ci++) {
+ expand_bottom_edge(prep->color_buf[ci], cinfo->image_width,
+ prep->next_buf_row, prep->next_buf_stop);
+ }
+ prep->next_buf_row = prep->next_buf_stop;
+ }
+ }
+ /* If we've gotten enough data, downsample a row group. */
+ if (prep->next_buf_row == prep->next_buf_stop) {
+ (*cinfo->downsample->downsample) (cinfo,
+ prep->color_buf,
+ (JDIMENSION) prep->this_row_group,
+ output_buf, *out_row_group_ctr);
+ (*out_row_group_ctr)++;
+ /* Advance pointers with wraparound as necessary. */
+ prep->this_row_group += cinfo->max_v_samp_factor;
+ if (prep->this_row_group >= buf_height)
+ prep->this_row_group = 0;
+ if (prep->next_buf_row >= buf_height)
+ prep->next_buf_row = 0;
+ prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor;
+ }
+ }
+}
+
+
+/*
+ * Create the wrapped-around downsampling input buffer needed for context mode.
+ */
+
+LOCAL(void)
+create_context_buffer (j_compress_ptr cinfo)
+{
+ my_prep_ptr prep = (my_prep_ptr) cinfo->prep;
+ int rgroup_height = cinfo->max_v_samp_factor;
+ int ci, i;
+ jpeg_component_info * compptr;
+ JSAMPARRAY true_buffer, fake_buffer;
+
+ /* Grab enough space for fake row pointers for all the components;
+ * we need five row groups' worth of pointers for each component.
+ */
+ fake_buffer = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (cinfo->num_components * 5 * rgroup_height) *
+ SIZEOF(JSAMPROW));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate the actual buffer space (3 row groups) for this component.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ true_buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_blocks *
+ cinfo->min_DCT_h_scaled_size *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) (3 * rgroup_height));
+ /* Copy true buffer row pointers into the middle of the fake row array */
+ MEMCOPY(fake_buffer + rgroup_height, true_buffer,
+ 3 * rgroup_height * SIZEOF(JSAMPROW));
+ /* Fill in the above and below wraparound pointers */
+ for (i = 0; i < rgroup_height; i++) {
+ fake_buffer[i] = true_buffer[2 * rgroup_height + i];
+ fake_buffer[4 * rgroup_height + i] = true_buffer[i];
+ }
+ prep->color_buf[ci] = fake_buffer + rgroup_height;
+ fake_buffer += 5 * rgroup_height; /* point to space for next component */
+ }
+}
+
+#endif /* CONTEXT_ROWS_SUPPORTED */
+
+
+/*
+ * Initialize preprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer)
+{
+ my_prep_ptr prep;
+ int ci;
+ jpeg_component_info * compptr;
+
+ if (need_full_buffer) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ prep = (my_prep_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_prep_controller));
+ cinfo->prep = (struct jpeg_c_prep_controller *) prep;
+ prep->pub.start_pass = start_pass_prep;
+
+ /* Allocate the color conversion buffer.
+ * We make the buffer wide enough to allow the downsampler to edge-expand
+ * horizontally within the buffer, if it so chooses.
+ */
+ if (cinfo->downsample->need_context_rows) {
+ /* Set up to provide context rows */
+#ifdef CONTEXT_ROWS_SUPPORTED
+ prep->pub.pre_process_data = pre_process_context;
+ create_context_buffer(cinfo);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* No context, just make it tall enough for one row group */
+ prep->pub.pre_process_data = pre_process_data;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ prep->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (((long) compptr->width_in_blocks *
+ cinfo->min_DCT_h_scaled_size *
+ cinfo->max_h_samp_factor) / compptr->h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/Source/LibJPEG/jcsample.c b/Source/LibJPEG/jcsample.c
new file mode 100644
index 0000000..4d36f85
--- /dev/null
+++ b/Source/LibJPEG/jcsample.c
@@ -0,0 +1,545 @@
+/*
+ * jcsample.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains downsampling routines.
+ *
+ * Downsampling input data is counted in "row groups". A row group
+ * is defined to be max_v_samp_factor pixel rows of each component,
+ * from which the downsampler produces v_samp_factor sample rows.
+ * A single row group is processed in each call to the downsampler module.
+ *
+ * The downsampler is responsible for edge-expansion of its output data
+ * to fill an integral number of DCT blocks horizontally. The source buffer
+ * may be modified if it is helpful for this purpose (the source buffer is
+ * allocated wide enough to correspond to the desired output width).
+ * The caller (the prep controller) is responsible for vertical padding.
+ *
+ * The downsampler may request "context rows" by setting need_context_rows
+ * during startup. In this case, the input arrays will contain at least
+ * one row group's worth of pixels above and below the passed-in data;
+ * the caller will create dummy rows at image top and bottom by replicating
+ * the first or last real pixel row.
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ *
+ * The downsampling algorithm used here is a simple average of the source
+ * pixels covered by the output pixel. The hi-falutin sampling literature
+ * refers to this as a "box filter". In general the characteristics of a box
+ * filter are not very good, but for the specific cases we normally use (1:1
+ * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not
+ * nearly so bad. If you intend to use other sampling ratios, you'd be well
+ * advised to improve this code.
+ *
+ * A simple input-smoothing capability is provided. This is mainly intended
+ * for cleaning up color-dithered GIF input files (if you find it inadequate,
+ * we suggest using an external filtering program such as pnmconvol). When
+ * enabled, each input pixel P is replaced by a weighted sum of itself and its
+ * eight neighbors. P's weight is 1-8*SF and each neighbor's weight is SF,
+ * where SF = (smoothing_factor / 1024).
+ * Currently, smoothing is only supported for 2h2v sampling factors.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to downsample a single component */
+typedef JMETHOD(void, downsample1_ptr,
+ (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_downsampler pub; /* public fields */
+
+ /* Downsampling method pointers, one per component */
+ downsample1_ptr methods[MAX_COMPONENTS];
+
+ /* Height of an output row group for each component. */
+ int rowgroup_height[MAX_COMPONENTS];
+
+ /* These arrays save pixel expansion factors so that int_downsample need not
+ * recompute them each time. They are unused for other downsampling methods.
+ */
+ UINT8 h_expand[MAX_COMPONENTS];
+ UINT8 v_expand[MAX_COMPONENTS];
+} my_downsampler;
+
+typedef my_downsampler * my_downsample_ptr;
+
+
+/*
+ * Initialize for a downsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_downsample (j_compress_ptr cinfo)
+{
+ /* no work for now */
+}
+
+
+/*
+ * Expand a component horizontally from width input_cols to width output_cols,
+ * by duplicating the rightmost samples.
+ */
+
+LOCAL(void)
+expand_right_edge (JSAMPARRAY image_data, int num_rows,
+ JDIMENSION input_cols, JDIMENSION output_cols)
+{
+ register JSAMPROW ptr;
+ register JSAMPLE pixval;
+ register int count;
+ int row;
+ int numcols = (int) (output_cols - input_cols);
+
+ if (numcols > 0) {
+ for (row = 0; row < num_rows; row++) {
+ ptr = image_data[row] + input_cols;
+ pixval = ptr[-1]; /* don't need GETJSAMPLE() here */
+ for (count = numcols; count > 0; count--)
+ *ptr++ = pixval;
+ }
+ }
+}
+
+
+/*
+ * Do downsampling for a whole row group (all components).
+ *
+ * In this version we simply downsample each component independently.
+ */
+
+METHODDEF(void)
+sep_downsample (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf, JDIMENSION out_row_group_index)
+{
+ my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JSAMPARRAY in_ptr, out_ptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ in_ptr = input_buf[ci] + in_row_index;
+ out_ptr = output_buf[ci] +
+ (out_row_group_index * downsample->rowgroup_height[ci]);
+ (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr);
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * One row group is processed per call.
+ * This version handles arbitrary integral sampling ratios, without smoothing.
+ * Note that this version is not actually used for customary sampling ratios.
+ */
+
+METHODDEF(void)
+int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample;
+ int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v;
+ JDIMENSION outcol, outcol_h; /* outcol_h == outcol*h_expand */
+ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
+ JSAMPROW inptr, outptr;
+ INT32 outvalue;
+
+ h_expand = downsample->h_expand[compptr->component_index];
+ v_expand = downsample->v_expand[compptr->component_index];
+ numpix = h_expand * v_expand;
+ numpix2 = numpix/2;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * h_expand);
+
+ inrow = outrow = 0;
+ while (inrow < cinfo->max_v_samp_factor) {
+ outptr = output_data[outrow];
+ for (outcol = 0, outcol_h = 0; outcol < output_cols;
+ outcol++, outcol_h += h_expand) {
+ outvalue = 0;
+ for (v = 0; v < v_expand; v++) {
+ inptr = input_data[inrow+v] + outcol_h;
+ for (h = 0; h < h_expand; h++) {
+ outvalue += (INT32) GETJSAMPLE(*inptr++);
+ }
+ }
+ *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix);
+ }
+ inrow += v_expand;
+ outrow++;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ /* Copy the data */
+ jcopy_sample_rows(input_data, 0, output_data, 0,
+ cinfo->max_v_samp_factor, cinfo->image_width);
+ /* Edge-expand */
+ expand_right_edge(output_data, cinfo->max_v_samp_factor, cinfo->image_width,
+ compptr->width_in_blocks * compptr->DCT_h_scaled_size);
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the common case of 2:1 horizontal and 1:1 vertical,
+ * without smoothing.
+ *
+ * A note about the "bias" calculations: when rounding fractional values to
+ * integer, we do not want to always round 0.5 up to the next integer.
+ * If we did that, we'd introduce a noticeable bias towards larger values.
+ * Instead, this code is arranged so that 0.5 will be rounded up or down at
+ * alternate pixel locations (a simple ordered dither pattern).
+ */
+
+METHODDEF(void)
+h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
+ register JSAMPROW inptr, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ outptr = output_data[inrow];
+ inptr = input_data[inrow];
+ bias = 0; /* bias = 0,1,0,1,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1])
+ + bias) >> 1);
+ bias ^= 1; /* 0=>1, 1=>0 */
+ inptr += 2;
+ }
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * without smoothing.
+ */
+
+METHODDEF(void)
+h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION outcol;
+ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
+ register JSAMPROW inptr0, inptr1, outptr;
+ register int bias;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data, cinfo->max_v_samp_factor,
+ cinfo->image_width, output_cols * 2);
+
+ inrow = outrow = 0;
+ while (inrow < cinfo->max_v_samp_factor) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ bias = 1; /* bias = 1,2,1,2,... for successive samples */
+ for (outcol = 0; outcol < output_cols; outcol++) {
+ *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1])
+ + bias) >> 2);
+ bias ^= 3; /* 1=>2, 2=>1 */
+ inptr0 += 2; inptr1 += 2;
+ }
+ inrow += 2;
+ outrow++;
+ }
+}
+
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the standard case of 2:1 horizontal and 2:1 vertical,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow, outrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
+ register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols * 2);
+
+ /* We don't bother to form the individual "smoothed" input pixel values;
+ * we can directly compute the output which is the average of the four
+ * smoothed values. Each of the four member pixels contributes a fraction
+ * (1-8*SF) to its own smoothed image and a fraction SF to each of the three
+ * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final
+ * output. The four corner-adjacent neighbor pixels contribute a fraction
+ * SF to just one smoothed pixel, or SF/4 to the final output; while the
+ * eight edge-adjacent neighbors contribute SF to each of two smoothed
+ * pixels, or SF/2 overall. In order to use integer arithmetic, these
+ * factors are scaled by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */
+ neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */
+
+ inrow = outrow = 0;
+ while (inrow < cinfo->max_v_samp_factor) {
+ outptr = output_data[outrow];
+ inptr0 = input_data[inrow];
+ inptr1 = input_data[inrow+1];
+ above_ptr = input_data[inrow-1];
+ below_ptr = input_data[inrow+2];
+
+ /* Special case for first column: pretend column -1 is same as column 0 */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ /* sum of pixels directly mapped to this output element */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ /* sum of edge-neighbor pixels */
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]);
+ /* The edge-neighbors count twice as much as corner-neighbors */
+ neighsum += neighsum;
+ /* Add in the corner-neighbors */
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]);
+ /* form final output scaled up by 2^16 */
+ membersum = membersum * memberscale + neighsum * neighscale;
+ /* round, descale and output it */
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]);
+ neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) +
+ GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) +
+ GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]);
+ neighsum += neighsum;
+ neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) +
+ GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]);
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ inrow += 2;
+ outrow++;
+ }
+}
+
+
+/*
+ * Downsample pixel values of a single component.
+ * This version handles the special case of a full-size component,
+ * with smoothing. One row of context is required.
+ */
+
+METHODDEF(void)
+fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr,
+ JSAMPARRAY input_data, JSAMPARRAY output_data)
+{
+ int inrow;
+ JDIMENSION colctr;
+ JDIMENSION output_cols = compptr->width_in_blocks * compptr->DCT_h_scaled_size;
+ register JSAMPROW inptr, above_ptr, below_ptr, outptr;
+ INT32 membersum, neighsum, memberscale, neighscale;
+ int colsum, lastcolsum, nextcolsum;
+
+ /* Expand input data enough to let all the output samples be generated
+ * by the standard loop. Special-casing padded output would be more
+ * efficient.
+ */
+ expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2,
+ cinfo->image_width, output_cols);
+
+ /* Each of the eight neighbor pixels contributes a fraction SF to the
+ * smoothed pixel, while the main pixel contributes (1-8*SF). In order
+ * to use integer arithmetic, these factors are multiplied by 2^16 = 65536.
+ * Also recall that SF = smoothing_factor / 1024.
+ */
+
+ memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */
+ neighscale = cinfo->smoothing_factor * 64; /* scaled SF */
+
+ for (inrow = 0; inrow < cinfo->max_v_samp_factor; inrow++) {
+ outptr = output_data[inrow];
+ inptr = input_data[inrow];
+ above_ptr = input_data[inrow-1];
+ below_ptr = input_data[inrow+1];
+
+ /* Special case for first column */
+ colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) +
+ GETJSAMPLE(*inptr);
+ membersum = GETJSAMPLE(*inptr++);
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = colsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+
+ for (colctr = output_cols - 2; colctr > 0; colctr--) {
+ membersum = GETJSAMPLE(*inptr++);
+ above_ptr++; below_ptr++;
+ nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) +
+ GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + nextcolsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16);
+ lastcolsum = colsum; colsum = nextcolsum;
+ }
+
+ /* Special case for last column */
+ membersum = GETJSAMPLE(*inptr);
+ neighsum = lastcolsum + (colsum - membersum) + colsum;
+ membersum = membersum * memberscale + neighsum * neighscale;
+ *outptr = (JSAMPLE) ((membersum + 32768) >> 16);
+
+ }
+}
+
+#endif /* INPUT_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Module initialization routine for downsampling.
+ * Note that we must select a routine for each component.
+ */
+
+GLOBAL(void)
+jinit_downsampler (j_compress_ptr cinfo)
+{
+ my_downsample_ptr downsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean smoothok = TRUE;
+ int h_in_group, v_in_group, h_out_group, v_out_group;
+
+ downsample = (my_downsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_downsampler));
+ cinfo->downsample = (struct jpeg_downsampler *) downsample;
+ downsample->pub.start_pass = start_pass_downsample;
+ downsample->pub.downsample = sep_downsample;
+ downsample->pub.need_context_rows = FALSE;
+
+ if (cinfo->CCIR601_sampling)
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* Verify we can handle the sampling factors, and set up method pointers */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Compute size of an "output group" for DCT scaling. This many samples
+ * are to be converted from max_h_samp_factor * max_v_samp_factor pixels.
+ */
+ h_out_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) /
+ cinfo->min_DCT_h_scaled_size;
+ v_out_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size;
+ h_in_group = cinfo->max_h_samp_factor;
+ v_in_group = cinfo->max_v_samp_factor;
+ downsample->rowgroup_height[ci] = v_out_group; /* save for use later */
+ if (h_in_group == h_out_group && v_in_group == v_out_group) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = fullsize_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = fullsize_downsample;
+ } else if (h_in_group == h_out_group * 2 &&
+ v_in_group == v_out_group) {
+ smoothok = FALSE;
+ downsample->methods[ci] = h2v1_downsample;
+ } else if (h_in_group == h_out_group * 2 &&
+ v_in_group == v_out_group * 2) {
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor) {
+ downsample->methods[ci] = h2v2_smooth_downsample;
+ downsample->pub.need_context_rows = TRUE;
+ } else
+#endif
+ downsample->methods[ci] = h2v2_downsample;
+ } else if ((h_in_group % h_out_group) == 0 &&
+ (v_in_group % v_out_group) == 0) {
+ smoothok = FALSE;
+ downsample->methods[ci] = int_downsample;
+ downsample->h_expand[ci] = (UINT8) (h_in_group / h_out_group);
+ downsample->v_expand[ci] = (UINT8) (v_in_group / v_out_group);
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ }
+
+#ifdef INPUT_SMOOTHING_SUPPORTED
+ if (cinfo->smoothing_factor && !smoothok)
+ TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL);
+#endif
+}
diff --git a/Source/LibJPEG/jctrans.c b/Source/LibJPEG/jctrans.c
new file mode 100644
index 0000000..74bb12c
--- /dev/null
+++ b/Source/LibJPEG/jctrans.c
@@ -0,0 +1,381 @@
+/*
+ * jctrans.c
+ *
+ * Copyright (C) 1995-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding compression,
+ * that is, writing raw DCT coefficient arrays to an output JPEG file.
+ * The routines in jcapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(void) transencode_master_selection
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+LOCAL(void) transencode_coef_controller
+ JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays));
+
+
+/*
+ * Compression initialization for writing raw-coefficient data.
+ * Before calling this, all parameters and a data destination must be set up.
+ * Call jpeg_finish_compress() to actually write the data.
+ *
+ * The number of passed virtual arrays must match cinfo->num_components.
+ * Note that the virtual arrays need not be filled or even realized at
+ * the time write_coefficients is called; indeed, if the virtual arrays
+ * were requested from this compression object's memory manager, they
+ * typically will be realized during this routine and filled afterwards.
+ */
+
+GLOBAL(void)
+jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)
+{
+ if (cinfo->global_state != CSTATE_START)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Mark all tables to be written */
+ jpeg_suppress_tables(cinfo, FALSE);
+ /* (Re)initialize error mgr and destination modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->dest->init_destination) (cinfo);
+ /* Perform master selection of active modules */
+ transencode_master_selection(cinfo, coef_arrays);
+ /* Wait for jpeg_finish_compress() call */
+ cinfo->next_scanline = 0; /* so jpeg_write_marker works */
+ cinfo->global_state = CSTATE_WRCOEFS;
+}
+
+
+/*
+ * Initialize the compression object with default parameters,
+ * then copy from the source object all parameters needed for lossless
+ * transcoding. Parameters that can be varied without loss (such as
+ * scan script and Huffman optimization) are left in their default states.
+ */
+
+GLOBAL(void)
+jpeg_copy_critical_parameters (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo)
+{
+ JQUANT_TBL ** qtblptr;
+ jpeg_component_info *incomp, *outcomp;
+ JQUANT_TBL *c_quant, *slot_quant;
+ int tblno, ci, coefi;
+
+ /* Safety check to ensure start_compress not called yet. */
+ if (dstinfo->global_state != CSTATE_START)
+ ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state);
+ /* Copy fundamental image dimensions */
+ dstinfo->image_width = srcinfo->image_width;
+ dstinfo->image_height = srcinfo->image_height;
+ dstinfo->input_components = srcinfo->num_components;
+ dstinfo->in_color_space = srcinfo->jpeg_color_space;
+ /* Initialize all parameters to default values */
+ jpeg_set_defaults(dstinfo);
+ /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
+ * Fix it to get the right header markers for the image colorspace.
+ */
+ jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space);
+ dstinfo->data_precision = srcinfo->data_precision;
+ dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling;
+ /* Copy the source's quantization tables. */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ if (srcinfo->quant_tbl_ptrs[tblno] != NULL) {
+ qtblptr = & dstinfo->quant_tbl_ptrs[tblno];
+ if (*qtblptr == NULL)
+ *qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo);
+ MEMCOPY((*qtblptr)->quantval,
+ srcinfo->quant_tbl_ptrs[tblno]->quantval,
+ SIZEOF((*qtblptr)->quantval));
+ (*qtblptr)->sent_table = FALSE;
+ }
+ }
+ /* Copy the source's per-component info.
+ * Note we assume jpeg_set_defaults has allocated the dest comp_info array.
+ */
+ dstinfo->num_components = srcinfo->num_components;
+ if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components,
+ MAX_COMPONENTS);
+ for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info;
+ ci < dstinfo->num_components; ci++, incomp++, outcomp++) {
+ outcomp->component_id = incomp->component_id;
+ outcomp->h_samp_factor = incomp->h_samp_factor;
+ outcomp->v_samp_factor = incomp->v_samp_factor;
+ outcomp->quant_tbl_no = incomp->quant_tbl_no;
+ /* Make sure saved quantization table for component matches the qtable
+ * slot. If not, the input file re-used this qtable slot.
+ * IJG encoder currently cannot duplicate this.
+ */
+ tblno = outcomp->quant_tbl_no;
+ if (tblno < 0 || tblno >= NUM_QUANT_TBLS ||
+ srcinfo->quant_tbl_ptrs[tblno] == NULL)
+ ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno);
+ slot_quant = srcinfo->quant_tbl_ptrs[tblno];
+ c_quant = incomp->quant_table;
+ if (c_quant != NULL) {
+ for (coefi = 0; coefi < DCTSIZE2; coefi++) {
+ if (c_quant->quantval[coefi] != slot_quant->quantval[coefi])
+ ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno);
+ }
+ }
+ /* Note: we do not copy the source's Huffman table assignments;
+ * instead we rely on jpeg_set_colorspace to have made a suitable choice.
+ */
+ }
+ /* Also copy JFIF version and resolution information, if available.
+ * Strictly speaking this isn't "critical" info, but it's nearly
+ * always appropriate to copy it if available. In particular,
+ * if the application chooses to copy JFIF 1.02 extension markers from
+ * the source file, we need to copy the version to make sure we don't
+ * emit a file that has 1.02 extensions but a claimed version of 1.01.
+ * We will *not*, however, copy version info from mislabeled "2.01" files.
+ */
+ if (srcinfo->saw_JFIF_marker) {
+ if (srcinfo->JFIF_major_version == 1) {
+ dstinfo->JFIF_major_version = srcinfo->JFIF_major_version;
+ dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version;
+ }
+ dstinfo->density_unit = srcinfo->density_unit;
+ dstinfo->X_density = srcinfo->X_density;
+ dstinfo->Y_density = srcinfo->Y_density;
+ }
+}
+
+
+/*
+ * Master selection of compression modules for transcoding.
+ * This substitutes for jcinit.c's initialization of the full compressor.
+ */
+
+LOCAL(void)
+transencode_master_selection (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ /* Although we don't actually use input_components for transcoding,
+ * jcmaster.c's initial_setup will complain if input_components is 0.
+ */
+ cinfo->input_components = 1;
+ /* Initialize master control (includes parameter checking/processing) */
+ jinit_c_master_control(cinfo, TRUE /* transcode only */);
+
+ /* Entropy encoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ jinit_arith_encoder(cinfo);
+ } else {
+ jinit_huff_encoder(cinfo);
+ }
+
+ /* We need a special coefficient buffer controller. */
+ transencode_coef_controller(cinfo, coef_arrays);
+
+ jinit_marker_writer(cinfo);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Write the datastream header (SOI, JFIF) immediately.
+ * Frame and scan headers are postponed till later.
+ * This lets application insert special markers after the SOI.
+ */
+ (*cinfo->marker->write_file_header) (cinfo);
+}
+
+
+/*
+ * The rest of this file is a special implementation of the coefficient
+ * buffer controller. This is similar to jccoefct.c, but it handles only
+ * output from presupplied virtual arrays. Furthermore, we generate any
+ * dummy padding blocks on-the-fly rather than expecting them to be present
+ * in the arrays.
+ */
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_c_coef_controller pub; /* public fields */
+
+ JDIMENSION iMCU_row_num; /* iMCU row # within image */
+ JDIMENSION mcu_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* Virtual block array for each component. */
+ jvirt_barray_ptr * whole_image;
+
+ /* Workspace for constructing dummy blocks at right/bottom edges. */
+ JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU];
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+
+LOCAL(void)
+start_iMCU_row (j_compress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->mcu_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ if (pass_mode != JBUF_CRANK_DEST)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ coef->iMCU_row_num = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Process some data.
+ * We process the equivalent of one fully interleaved MCU row ("iMCU" row)
+ * per call, ie, v_samp_factor block rows for each component in the scan.
+ * The data is obtained from the virtual arrays and fed to the entropy coder.
+ * Returns TRUE if the iMCU row is completed, FALSE if suspended.
+ *
+ * NB: input_buf is ignored; it is likely to be a NULL pointer.
+ */
+
+METHODDEF(boolean)
+compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, blockcnt;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ coef->iMCU_row_num * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (coef->iMCU_row_num < last_iMCU_row ||
+ yindex+yoffset < compptr->last_row_height) {
+ /* Fill in pointers to real blocks in this row */
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < blockcnt; xindex++)
+ MCU_buffer[blkn++] = buffer_ptr++;
+ } else {
+ /* At bottom of image, need a whole row of dummy blocks */
+ xindex = 0;
+ }
+ /* Fill in any dummy blocks needed in this row.
+ * Dummy blocks are filled in the same way as in jccoefct.c:
+ * all zeroes in the AC entries, DC entries equal to previous
+ * block's DC value. The init routine has already zeroed the
+ * AC entries, so we need only set the DC entries correctly.
+ */
+ for (; xindex < compptr->MCU_width; xindex++) {
+ MCU_buffer[blkn] = coef->dummy_buffer[blkn];
+ MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0];
+ blkn++;
+ }
+ }
+ }
+ /* Try to write the MCU. */
+ if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->mcu_ctr = MCU_col_num;
+ return FALSE;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->mcu_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ coef->iMCU_row_num++;
+ start_iMCU_row(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Initialize coefficient buffer controller.
+ *
+ * Each passed coefficient array must be the right size for that
+ * coefficient: width_in_blocks wide and height_in_blocks high,
+ * with unitheight at least v_samp_factor.
+ */
+
+LOCAL(void)
+transencode_coef_controller (j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays)
+{
+ my_coef_ptr coef;
+ JBLOCKROW buffer;
+ int i;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_c_coef_controller *) coef;
+ coef->pub.start_pass = start_pass_coef;
+ coef->pub.compress_data = compress_output;
+
+ /* Save pointer to virtual arrays */
+ coef->whole_image = coef_arrays;
+
+ /* Allocate and pre-zero space for dummy DCT blocks. */
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) {
+ coef->dummy_buffer[i] = buffer + i;
+ }
+}
diff --git a/Source/LibJPEG/jdapimin.c b/Source/LibJPEG/jdapimin.c
new file mode 100644
index 0000000..a55498f
--- /dev/null
+++ b/Source/LibJPEG/jdapimin.c
@@ -0,0 +1,396 @@
+/*
+ * jdapimin.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * Modified 2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "minimum" API routines that may be
+ * needed in either the normal full-decompression case or the
+ * transcoding-only case.
+ *
+ * Most of the routines intended to be called directly by an application
+ * are in this file or in jdapistd.c. But also see jcomapi.c for routines
+ * shared by compression and decompression, and jdtrans.c for the transcoding
+ * case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * Initialization of a JPEG decompression object.
+ * The error manager must already be set up (in case memory manager fails).
+ */
+
+GLOBAL(void)
+jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize)
+{
+ int i;
+
+ /* Guard against version mismatches between library and caller. */
+ cinfo->mem = NULL; /* so jpeg_destroy knows mem mgr not called */
+ if (version != JPEG_LIB_VERSION)
+ ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version);
+ if (structsize != SIZEOF(struct jpeg_decompress_struct))
+ ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,
+ (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize);
+
+ /* For debugging purposes, we zero the whole master structure.
+ * But the application has already set the err pointer, and may have set
+ * client_data, so we have to save and restore those fields.
+ * Note: if application hasn't set client_data, tools like Purify may
+ * complain here.
+ */
+ {
+ struct jpeg_error_mgr * err = cinfo->err;
+ void * client_data = cinfo->client_data; /* ignore Purify complaint here */
+ MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct));
+ cinfo->err = err;
+ cinfo->client_data = client_data;
+ }
+ cinfo->is_decompressor = TRUE;
+
+ /* Initialize a memory manager instance for this object */
+ jinit_memory_mgr((j_common_ptr) cinfo);
+
+ /* Zero out pointers to permanent structures. */
+ cinfo->progress = NULL;
+ cinfo->src = NULL;
+
+ for (i = 0; i < NUM_QUANT_TBLS; i++)
+ cinfo->quant_tbl_ptrs[i] = NULL;
+
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ cinfo->dc_huff_tbl_ptrs[i] = NULL;
+ cinfo->ac_huff_tbl_ptrs[i] = NULL;
+ }
+
+ /* Initialize marker processor so application can override methods
+ * for COM, APPn markers before calling jpeg_read_header.
+ */
+ cinfo->marker_list = NULL;
+ jinit_marker_reader(cinfo);
+
+ /* And initialize the overall input controller. */
+ jinit_input_controller(cinfo);
+
+ /* OK, I'm ready */
+ cinfo->global_state = DSTATE_START;
+}
+
+
+/*
+ * Destruction of a JPEG decompression object
+ */
+
+GLOBAL(void)
+jpeg_destroy_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_destroy((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Abort processing of a JPEG decompression operation,
+ * but don't destroy the object itself.
+ */
+
+GLOBAL(void)
+jpeg_abort_decompress (j_decompress_ptr cinfo)
+{
+ jpeg_abort((j_common_ptr) cinfo); /* use common routine */
+}
+
+
+/*
+ * Set default decompression parameters.
+ */
+
+LOCAL(void)
+default_decompress_parms (j_decompress_ptr cinfo)
+{
+ /* Guess the input colorspace, and set output colorspace accordingly. */
+ /* (Wish JPEG committee had provided a real way to specify this...) */
+ /* Note application may override our guesses. */
+ switch (cinfo->num_components) {
+ case 1:
+ cinfo->jpeg_color_space = JCS_GRAYSCALE;
+ cinfo->out_color_space = JCS_GRAYSCALE;
+ break;
+
+ case 3:
+ if (cinfo->saw_JFIF_marker) {
+ cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */
+ } else if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_RGB;
+ break;
+ case 1:
+ cinfo->jpeg_color_space = JCS_YCbCr;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ break;
+ }
+ } else {
+ /* Saw no special markers, try to guess from the component IDs */
+ int cid0 = cinfo->comp_info[0].component_id;
+ int cid1 = cinfo->comp_info[1].component_id;
+ int cid2 = cinfo->comp_info[2].component_id;
+
+ if (cid0 == 1 && cid1 == 2 && cid2 == 3)
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */
+ else if (cid0 == 82 && cid1 == 71 && cid2 == 66)
+ cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */
+ else {
+ TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2);
+ cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */
+ }
+ }
+ /* Always guess RGB is proper output colorspace. */
+ cinfo->out_color_space = JCS_RGB;
+ break;
+
+ case 4:
+ if (cinfo->saw_Adobe_marker) {
+ switch (cinfo->Adobe_transform) {
+ case 0:
+ cinfo->jpeg_color_space = JCS_CMYK;
+ break;
+ case 2:
+ cinfo->jpeg_color_space = JCS_YCCK;
+ break;
+ default:
+ WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform);
+ cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */
+ break;
+ }
+ } else {
+ /* No special markers, assume straight CMYK. */
+ cinfo->jpeg_color_space = JCS_CMYK;
+ }
+ cinfo->out_color_space = JCS_CMYK;
+ break;
+
+ default:
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->out_color_space = JCS_UNKNOWN;
+ break;
+ }
+
+ /* Set defaults for other decompression parameters. */
+ cinfo->scale_num = DCTSIZE; /* 1:1 scaling */
+ cinfo->scale_denom = DCTSIZE;
+ cinfo->output_gamma = 1.0;
+ cinfo->buffered_image = FALSE;
+ cinfo->raw_data_out = FALSE;
+ cinfo->dct_method = JDCT_DEFAULT;
+ cinfo->do_fancy_upsampling = TRUE;
+ cinfo->do_block_smoothing = TRUE;
+ cinfo->quantize_colors = FALSE;
+ /* We set these in case application only sets quantize_colors. */
+ cinfo->dither_mode = JDITHER_FS;
+#ifdef QUANT_2PASS_SUPPORTED
+ cinfo->two_pass_quantize = TRUE;
+#else
+ cinfo->two_pass_quantize = FALSE;
+#endif
+ cinfo->desired_number_of_colors = 256;
+ cinfo->colormap = NULL;
+ /* Initialize for no mode change in buffered-image mode. */
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+}
+
+
+/*
+ * Decompression startup: read start of JPEG datastream to see what's there.
+ * Need only initialize JPEG object and supply a data source before calling.
+ *
+ * This routine will read as far as the first SOS marker (ie, actual start of
+ * compressed data), and will save all tables and parameters in the JPEG
+ * object. It will also initialize the decompression parameters to default
+ * values, and finally return JPEG_HEADER_OK. On return, the application may
+ * adjust the decompression parameters and then call jpeg_start_decompress.
+ * (Or, if the application only wanted to determine the image parameters,
+ * the data need not be decompressed. In that case, call jpeg_abort or
+ * jpeg_destroy to release any temporary space.)
+ * If an abbreviated (tables only) datastream is presented, the routine will
+ * return JPEG_HEADER_TABLES_ONLY upon reaching EOI. The application may then
+ * re-use the JPEG object to read the abbreviated image datastream(s).
+ * It is unnecessary (but OK) to call jpeg_abort in this case.
+ * The JPEG_SUSPENDED return code only occurs if the data source module
+ * requests suspension of the decompressor. In this case the application
+ * should load more source data and then re-call jpeg_read_header to resume
+ * processing.
+ * If a non-suspending data source is used and require_image is TRUE, then the
+ * return code need not be inspected since only JPEG_HEADER_OK is possible.
+ *
+ * This routine is now just a front end to jpeg_consume_input, with some
+ * extra error checking.
+ */
+
+GLOBAL(int)
+jpeg_read_header (j_decompress_ptr cinfo, boolean require_image)
+{
+ int retcode;
+
+ if (cinfo->global_state != DSTATE_START &&
+ cinfo->global_state != DSTATE_INHEADER)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ retcode = jpeg_consume_input(cinfo);
+
+ switch (retcode) {
+ case JPEG_REACHED_SOS:
+ retcode = JPEG_HEADER_OK;
+ break;
+ case JPEG_REACHED_EOI:
+ if (require_image) /* Complain if application wanted an image */
+ ERREXIT(cinfo, JERR_NO_IMAGE);
+ /* Reset to start state; it would be safer to require the application to
+ * call jpeg_abort, but we can't change it now for compatibility reasons.
+ * A side effect is to free any temporary memory (there shouldn't be any).
+ */
+ jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */
+ retcode = JPEG_HEADER_TABLES_ONLY;
+ break;
+ case JPEG_SUSPENDED:
+ /* no work */
+ break;
+ }
+
+ return retcode;
+}
+
+
+/*
+ * Consume data in advance of what the decompressor requires.
+ * This can be called at any time once the decompressor object has
+ * been created and a data source has been set up.
+ *
+ * This routine is essentially a state machine that handles a couple
+ * of critical state-transition actions, namely initial setup and
+ * transition from header scanning to ready-for-start_decompress.
+ * All the actual input is done via the input controller's consume_input
+ * method.
+ */
+
+GLOBAL(int)
+jpeg_consume_input (j_decompress_ptr cinfo)
+{
+ int retcode = JPEG_SUSPENDED;
+
+ /* NB: every possible DSTATE value should be listed in this switch */
+ switch (cinfo->global_state) {
+ case DSTATE_START:
+ /* Start-of-datastream actions: reset appropriate modules */
+ (*cinfo->inputctl->reset_input_controller) (cinfo);
+ /* Initialize application's data source module */
+ (*cinfo->src->init_source) (cinfo);
+ cinfo->global_state = DSTATE_INHEADER;
+ /*FALLTHROUGH*/
+ case DSTATE_INHEADER:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */
+ /* Set up default parameters based on header data */
+ default_decompress_parms(cinfo);
+ /* Set global state: ready for start_decompress */
+ cinfo->global_state = DSTATE_READY;
+ }
+ break;
+ case DSTATE_READY:
+ /* Can't advance past first SOS until start_decompress is called */
+ retcode = JPEG_REACHED_SOS;
+ break;
+ case DSTATE_PRELOAD:
+ case DSTATE_PRESCAN:
+ case DSTATE_SCANNING:
+ case DSTATE_RAW_OK:
+ case DSTATE_BUFIMAGE:
+ case DSTATE_BUFPOST:
+ case DSTATE_STOPPING:
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ break;
+ default:
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ return retcode;
+}
+
+
+/*
+ * Have we finished reading the input file?
+ */
+
+GLOBAL(boolean)
+jpeg_input_complete (j_decompress_ptr cinfo)
+{
+ /* Check for valid jpeg object */
+ if (cinfo->global_state < DSTATE_START ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->eoi_reached;
+}
+
+
+/*
+ * Is there more than one scan?
+ */
+
+GLOBAL(boolean)
+jpeg_has_multiple_scans (j_decompress_ptr cinfo)
+{
+ /* Only valid after jpeg_read_header completes */
+ if (cinfo->global_state < DSTATE_READY ||
+ cinfo->global_state > DSTATE_STOPPING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return cinfo->inputctl->has_multiple_scans;
+}
+
+
+/*
+ * Finish JPEG decompression.
+ *
+ * This will normally just verify the file trailer and release temp storage.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_decompress (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) {
+ /* Terminate final pass of non-buffered mode */
+ if (cinfo->output_scanline < cinfo->output_height)
+ ERREXIT(cinfo, JERR_TOO_LITTLE_DATA);
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state == DSTATE_BUFIMAGE) {
+ /* Finishing after a buffered-image operation */
+ cinfo->global_state = DSTATE_STOPPING;
+ } else if (cinfo->global_state != DSTATE_STOPPING) {
+ /* STOPPING = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read until EOI */
+ while (! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ /* Do final cleanup */
+ (*cinfo->src->term_source) (cinfo);
+ /* We can use jpeg_abort to release memory and reset global_state */
+ jpeg_abort((j_common_ptr) cinfo);
+ return TRUE;
+}
diff --git a/Source/LibJPEG/jdapistd.c b/Source/LibJPEG/jdapistd.c
new file mode 100644
index 0000000..9d74537
--- /dev/null
+++ b/Source/LibJPEG/jdapistd.c
@@ -0,0 +1,275 @@
+/*
+ * jdapistd.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains application interface code for the decompression half
+ * of the JPEG library. These are the "standard" API routines that are
+ * used in the normal full-decompression case. They are not used by a
+ * transcoding-only application. Note that if an application links in
+ * jpeg_start_decompress, it will end up linking in the entire decompressor.
+ * We thus must separate this file from jdapimin.c to avoid linking the
+ * whole decompression library into a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Decompression initialization.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * If a multipass operating mode was selected, this will do all but the
+ * last pass, and thus may take a great deal of time.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_start_decompress (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize master control, select active modules */
+ jinit_master_decompress(cinfo);
+ if (cinfo->buffered_image) {
+ /* No more work here; expecting jpeg_start_output next */
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+ }
+ cinfo->global_state = DSTATE_PRELOAD;
+ }
+ if (cinfo->global_state == DSTATE_PRELOAD) {
+ /* If file has multiple scans, absorb them all into the coef buffer */
+ if (cinfo->inputctl->has_multiple_scans) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return FALSE;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* jdmaster underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+ }
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ } else if (cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Perform any dummy output passes, and set up for the final pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Set up for an output pass, and perform any dummy pass(es) needed.
+ * Common subroutine for jpeg_start_decompress and jpeg_start_output.
+ * Entry: global_state = DSTATE_PRESCAN only if previously suspended.
+ * Exit: If done, returns TRUE and sets global_state for proper output mode.
+ * If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.
+ */
+
+LOCAL(boolean)
+output_pass_setup (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state != DSTATE_PRESCAN) {
+ /* First call: do pass setup */
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+ cinfo->global_state = DSTATE_PRESCAN;
+ }
+ /* Loop over any required dummy passes */
+ while (cinfo->master->is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Crank through the dummy pass */
+ while (cinfo->output_scanline < cinfo->output_height) {
+ JDIMENSION last_scanline;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+ /* Process some data */
+ last_scanline = cinfo->output_scanline;
+ (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,
+ &cinfo->output_scanline, (JDIMENSION) 0);
+ if (cinfo->output_scanline == last_scanline)
+ return FALSE; /* No progress made, must suspend */
+ }
+ /* Finish up dummy pass, and set up for another one */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ (*cinfo->master->prepare_for_output_pass) (cinfo);
+ cinfo->output_scanline = 0;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ }
+ /* Ready for application to drive output pass through
+ * jpeg_read_scanlines or jpeg_read_raw_data.
+ */
+ cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;
+ return TRUE;
+}
+
+
+/*
+ * Read some scanlines of data from the JPEG decompressor.
+ *
+ * The return value will be the number of lines actually read.
+ * This may be less than the number requested in several cases,
+ * including bottom of image, data source suspension, and operating
+ * modes that emit multiple scanlines at a time.
+ *
+ * Note: we warn about excess calls to jpeg_read_scanlines() since
+ * this likely signals an application programmer error. However,
+ * an oversize buffer (max_lines > scanlines remaining) is not an error.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,
+ JDIMENSION max_lines)
+{
+ JDIMENSION row_ctr;
+
+ if (cinfo->global_state != DSTATE_SCANNING)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Process some data */
+ row_ctr = 0;
+ (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);
+ cinfo->output_scanline += row_ctr;
+ return row_ctr;
+}
+
+
+/*
+ * Alternate entry point to read raw data.
+ * Processes exactly one iMCU row per call, unless suspended.
+ */
+
+GLOBAL(JDIMENSION)
+jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,
+ JDIMENSION max_lines)
+{
+ JDIMENSION lines_per_iMCU_row;
+
+ if (cinfo->global_state != DSTATE_RAW_OK)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ if (cinfo->output_scanline >= cinfo->output_height) {
+ WARNMS(cinfo, JWRN_TOO_MUCH_DATA);
+ return 0;
+ }
+
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->pass_counter = (long) cinfo->output_scanline;
+ cinfo->progress->pass_limit = (long) cinfo->output_height;
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ }
+
+ /* Verify that at least one iMCU row can be returned. */
+ lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_v_scaled_size;
+ if (max_lines < lines_per_iMCU_row)
+ ERREXIT(cinfo, JERR_BUFFER_SIZE);
+
+ /* Decompress directly into user's buffer. */
+ if (! (*cinfo->coef->decompress_data) (cinfo, data))
+ return 0; /* suspension forced, can do nothing more */
+
+ /* OK, we processed one iMCU row. */
+ cinfo->output_scanline += lines_per_iMCU_row;
+ return lines_per_iMCU_row;
+}
+
+
+/* Additional entry points for buffered-image mode. */
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Initialize for an output pass in buffered-image mode.
+ */
+
+GLOBAL(boolean)
+jpeg_start_output (j_decompress_ptr cinfo, int scan_number)
+{
+ if (cinfo->global_state != DSTATE_BUFIMAGE &&
+ cinfo->global_state != DSTATE_PRESCAN)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ /* Limit scan number to valid range */
+ if (scan_number <= 0)
+ scan_number = 1;
+ if (cinfo->inputctl->eoi_reached &&
+ scan_number > cinfo->input_scan_number)
+ scan_number = cinfo->input_scan_number;
+ cinfo->output_scan_number = scan_number;
+ /* Perform any dummy output passes, and set up for the real pass */
+ return output_pass_setup(cinfo);
+}
+
+
+/*
+ * Finish up after an output pass in buffered-image mode.
+ *
+ * Returns FALSE if suspended. The return value need be inspected only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(boolean)
+jpeg_finish_output (j_decompress_ptr cinfo)
+{
+ if ((cinfo->global_state == DSTATE_SCANNING ||
+ cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {
+ /* Terminate this pass. */
+ /* We do not require the whole pass to have been completed. */
+ (*cinfo->master->finish_output_pass) (cinfo);
+ cinfo->global_state = DSTATE_BUFPOST;
+ } else if (cinfo->global_state != DSTATE_BUFPOST) {
+ /* BUFPOST = repeat call after a suspension, anything else is error */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ }
+ /* Read markers looking for SOS or EOI */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)
+ return FALSE; /* Suspend, come back later */
+ }
+ cinfo->global_state = DSTATE_BUFIMAGE;
+ return TRUE;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
diff --git a/Source/LibJPEG/jdarith.c b/Source/LibJPEG/jdarith.c
new file mode 100644
index 0000000..702950f
--- /dev/null
+++ b/Source/LibJPEG/jdarith.c
@@ -0,0 +1,762 @@
+/*
+ * jdarith.c
+ *
+ * Developed 1997 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains portable arithmetic entropy decoding routines for JPEG
+ * (implementing the ISO/IEC IS 10918-1 and CCITT Recommendation ITU-T T.81).
+ *
+ * Both sequential and progressive modes are supported in this single module.
+ *
+ * Suspension is not currently supported in this module.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Expanded entropy decoder object for arithmetic decoding. */
+
+typedef struct {
+ struct jpeg_entropy_decoder pub; /* public fields */
+
+ INT32 c; /* C register, base of coding interval + input bit buffer */
+ INT32 a; /* A register, normalized size of coding interval */
+ int ct; /* bit shift counter, # of bits left in bit buffer part of C */
+ /* init: ct = -16 */
+ /* run: ct = 0..7 */
+ /* error: ct = -1 */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+ int dc_context[MAX_COMPS_IN_SCAN]; /* context index for DC conditioning */
+
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Pointers to statistics areas (these workspaces have image lifespan) */
+ unsigned char * dc_stats[NUM_ARITH_TBLS];
+ unsigned char * ac_stats[NUM_ARITH_TBLS];
+} arith_entropy_decoder;
+
+typedef arith_entropy_decoder * arith_entropy_ptr;
+
+/* The following two definitions specify the allocation chunk size
+ * for the statistics area.
+ * According to sections F.1.4.4.1.3 and F.1.4.4.2, we need at least
+ * 49 statistics bins for DC, and 245 statistics bins for AC coding.
+ * Note that we use one additional AC bin for codings with fixed
+ * probability (0.5), thus the minimum number for AC is 246.
+ *
+ * We use a compact representation with 1 byte per statistics bin,
+ * thus the numbers directly represent byte sizes.
+ * This 1 byte per statistics bin contains the meaning of the MPS
+ * (more probable symbol) in the highest bit (mask 0x80), and the
+ * index into the probability estimation state machine table
+ * in the lower bits (mask 0x7F).
+ */
+
+#define DC_STAT_BINS 64
+#define AC_STAT_BINS 256
+
+
+LOCAL(int)
+get_byte (j_decompress_ptr cinfo)
+/* Read next input byte; we do not support suspension in this module. */
+{
+ struct jpeg_source_mgr * src = cinfo->src;
+
+ if (src->bytes_in_buffer == 0)
+ if (! (*src->fill_input_buffer) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+ src->bytes_in_buffer--;
+ return GETJOCTET(*src->next_input_byte++);
+}
+
+
+/*
+ * The core arithmetic decoding routine (common in JPEG and JBIG).
+ * This needs to go as fast as possible.
+ * Machine-dependent optimization facilities
+ * are not utilized in this portable implementation.
+ * However, this code should be fairly efficient and
+ * may be a good base for further optimizations anyway.
+ *
+ * Return value is 0 or 1 (binary decision).
+ *
+ * Note: I've changed the handling of the code base & bit
+ * buffer register C compared to other implementations
+ * based on the standards layout & procedures.
+ * While it also contains both the actual base of the
+ * coding interval (16 bits) and the next-bits buffer,
+ * the cut-point between these two parts is floating
+ * (instead of fixed) with the bit shift counter CT.
+ * Thus, we also need only one (variable instead of
+ * fixed size) shift for the LPS/MPS decision, and
+ * we can get away with any renormalization update
+ * of C (except for new data insertion, of course).
+ *
+ * I've also introduced a new scheme for accessing
+ * the probability estimation state machine table,
+ * derived from Markus Kuhn's JBIG implementation.
+ */
+
+LOCAL(int)
+arith_decode (j_decompress_ptr cinfo, unsigned char *st)
+{
+ extern const INT32 jaritab[];
+ register arith_entropy_ptr e = (arith_entropy_ptr) cinfo->entropy;
+ register unsigned char nl, nm;
+ register INT32 qe, temp;
+ register int sv, data;
+
+ /* Renormalization & data input per section D.2.6 */
+ while (e->a < 0x8000L) {
+ if (--e->ct < 0) {
+ /* Need to fetch next data byte */
+ if (cinfo->unread_marker)
+ data = 0; /* stuff zero data */
+ else {
+ data = get_byte(cinfo); /* read next input byte */
+ if (data == 0xFF) { /* zero stuff or marker code */
+ do data = get_byte(cinfo);
+ while (data == 0xFF); /* swallow extra 0xFF bytes */
+ if (data == 0)
+ data = 0xFF; /* discard stuffed zero byte */
+ else {
+ /* Note: Different from the Huffman decoder, hitting
+ * a marker while processing the compressed data
+ * segment is legal in arithmetic coding.
+ * The convention is to supply zero data
+ * then until decoding is complete.
+ */
+ cinfo->unread_marker = data;
+ data = 0;
+ }
+ }
+ }
+ e->c = (e->c << 8) | data; /* insert data into C register */
+ if ((e->ct += 8) < 0) /* update bit shift counter */
+ /* Need more initial bytes */
+ if (++e->ct == 0)
+ /* Got 2 initial bytes -> re-init A and exit loop */
+ e->a = 0x8000L; /* => e->a = 0x10000L after loop exit */
+ }
+ e->a <<= 1;
+ }
+
+ /* Fetch values from our compact representation of Table D.2:
+ * Qe values and probability estimation state machine
+ */
+ sv = *st;
+ qe = jaritab[sv & 0x7F]; /* => Qe_Value */
+ nl = qe & 0xFF; qe >>= 8; /* Next_Index_LPS + Switch_MPS */
+ nm = qe & 0xFF; qe >>= 8; /* Next_Index_MPS */
+
+ /* Decode & estimation procedures per sections D.2.4 & D.2.5 */
+ temp = e->a - qe;
+ e->a = temp;
+ temp <<= e->ct;
+ if (e->c >= temp) {
+ e->c -= temp;
+ /* Conditional LPS (less probable symbol) exchange */
+ if (e->a < qe) {
+ e->a = qe;
+ *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */
+ } else {
+ e->a = qe;
+ *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */
+ sv ^= 0x80; /* Exchange LPS/MPS */
+ }
+ } else if (e->a < 0x8000L) {
+ /* Conditional MPS (more probable symbol) exchange */
+ if (e->a < qe) {
+ *st = (sv & 0x80) ^ nl; /* Estimate_after_LPS */
+ sv ^= 0x80; /* Exchange LPS/MPS */
+ } else {
+ *st = (sv & 0x80) ^ nm; /* Estimate_after_MPS */
+ }
+ }
+
+ return sv >> 7;
+}
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ */
+
+LOCAL(void)
+process_restart (j_decompress_ptr cinfo)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ int ci;
+ jpeg_component_info * compptr;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ ERREXIT(cinfo, JERR_CANT_SUSPEND);
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Re-initialize statistics areas */
+ if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+ MEMZERO(entropy->dc_stats[compptr->dc_tbl_no], DC_STAT_BINS);
+ /* Reset DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ entropy->dc_context[ci] = 0;
+ }
+ if (cinfo->progressive_mode == 0 || cinfo->Ss) {
+ MEMZERO(entropy->ac_stats[compptr->ac_tbl_no], AC_STAT_BINS);
+ }
+ }
+
+ /* Reset arithmetic decoding variables */
+ entropy->c = 0;
+ entropy->a = 0;
+ entropy->ct = -16; /* force reading 2 initial bytes to fill C */
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Arithmetic MCU decoding.
+ * Each of these routines decodes and returns one MCU's worth of
+ * arithmetic-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
+ */
+
+/*
+ * MCU decoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ unsigned char *st;
+ int blkn, ci, tbl, sign;
+ int v, m;
+
+ /* Process restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ process_restart(cinfo);
+ entropy->restarts_to_go--;
+ }
+
+ if (entropy->ct == -1) return TRUE; /* if error do nothing */
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ tbl = cinfo->cur_comp_info[ci]->dc_tbl_no;
+
+ /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */
+
+ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */
+ st = entropy->dc_stats[tbl] + entropy->dc_context[ci];
+
+ /* Figure F.19: Decode_DC_DIFF */
+ if (arith_decode(cinfo, st) == 0)
+ entropy->dc_context[ci] = 0;
+ else {
+ /* Figure F.21: Decoding nonzero value v */
+ /* Figure F.22: Decoding the sign of v */
+ sign = arith_decode(cinfo, st + 1);
+ st += 2; st += sign;
+ /* Figure F.23: Decoding the magnitude category of v */
+ if ((m = arith_decode(cinfo, st)) != 0) {
+ st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
+ while (arith_decode(cinfo, st)) {
+ if ((m <<= 1) == 0x8000) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* magnitude overflow */
+ return TRUE;
+ }
+ st += 1;
+ }
+ }
+ /* Section F.1.4.4.1.2: Establish dc_context conditioning category */
+ if (m < (int) (((INT32) 1 << cinfo->arith_dc_L[tbl]) >> 1))
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ else if (m > (int) (((INT32) 1 << cinfo->arith_dc_U[tbl]) >> 1))
+ entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
+ else
+ entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
+ v = m;
+ /* Figure F.24: Decoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ if (arith_decode(cinfo, st)) v |= m;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] += v;
+ }
+
+ /* Scale and output the DC coefficient (assumes jpeg_natural_order[0]=0) */
+ (*block)[0] = (JCOEF) (entropy->last_dc_val[ci] << cinfo->Al);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ unsigned char *st;
+ int tbl, sign, k;
+ int v, m;
+
+ /* Process restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ process_restart(cinfo);
+ entropy->restarts_to_go--;
+ }
+
+ if (entropy->ct == -1) return TRUE; /* if error do nothing */
+
+ /* There is always only one block per MCU */
+ block = MCU_data[0];
+ tbl = cinfo->cur_comp_info[0]->ac_tbl_no;
+
+ /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
+
+ /* Figure F.20: Decode_AC_coefficients */
+ for (k = cinfo->Ss; k <= cinfo->Se; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ if (arith_decode(cinfo, st)) break; /* EOB flag */
+ while (arith_decode(cinfo, st + 1) == 0) {
+ st += 3; k++;
+ if (k > cinfo->Se) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* spectral overflow */
+ return TRUE;
+ }
+ }
+ /* Figure F.21: Decoding nonzero value v */
+ /* Figure F.22: Decoding the sign of v */
+ entropy->ac_stats[tbl][245] = 0;
+ sign = arith_decode(cinfo, entropy->ac_stats[tbl] + 245);
+ st += 2;
+ /* Figure F.23: Decoding the magnitude category of v */
+ if ((m = arith_decode(cinfo, st)) != 0) {
+ if (arith_decode(cinfo, st)) {
+ m <<= 1;
+ st = entropy->ac_stats[tbl] +
+ (k <= cinfo->arith_ac_K[tbl] ? 189 : 217);
+ while (arith_decode(cinfo, st)) {
+ if ((m <<= 1) == 0x8000) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* magnitude overflow */
+ return TRUE;
+ }
+ st += 1;
+ }
+ }
+ }
+ v = m;
+ /* Figure F.24: Decoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ if (arith_decode(cinfo, st)) v |= m;
+ v += 1; if (sign) v = -v;
+ /* Scale and output coefficient in natural (dezigzagged) order */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) (v << cinfo->Al);
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for DC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ unsigned char st[4];
+ int p1, blkn;
+
+ /* Process restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ process_restart(cinfo);
+ entropy->restarts_to_go--;
+ }
+
+ p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ st[0] = 0; /* use fixed probability estimation */
+ /* Encoded data is simply the next bit of the two's-complement DC value */
+ if (arith_decode(cinfo, st))
+ MCU_data[blkn][0][0] |= p1;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ JBLOCKROW block;
+ JCOEFPTR thiscoef;
+ unsigned char *st;
+ int tbl, k, kex;
+ int p1, m1;
+
+ /* Process restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ process_restart(cinfo);
+ entropy->restarts_to_go--;
+ }
+
+ if (entropy->ct == -1) return TRUE; /* if error do nothing */
+
+ /* There is always only one block per MCU */
+ block = MCU_data[0];
+ tbl = cinfo->cur_comp_info[0]->ac_tbl_no;
+
+ p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
+
+ /* Establish EOBx (previous stage end-of-block) index */
+ for (kex = cinfo->Se + 1; kex > 1; kex--)
+ if ((*block)[jpeg_natural_order[kex - 1]]) break;
+
+ for (k = cinfo->Ss; k <= cinfo->Se; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ if (k >= kex)
+ if (arith_decode(cinfo, st)) break; /* EOB flag */
+ for (;;) {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef) { /* previously nonzero coef */
+ if (arith_decode(cinfo, st + 2)) {
+ if (*thiscoef < 0)
+ *thiscoef += m1;
+ else
+ *thiscoef += p1;
+ }
+ break;
+ }
+ if (arith_decode(cinfo, st + 1)) { /* newly nonzero coef */
+ entropy->ac_stats[tbl][245] = 0;
+ if (arith_decode(cinfo, entropy->ac_stats[tbl] + 245))
+ *thiscoef = m1;
+ else
+ *thiscoef = p1;
+ break;
+ }
+ st += 3; k++;
+ if (k > cinfo->Se) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* spectral overflow */
+ return TRUE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Decode one MCU's worth of arithmetic-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ jpeg_component_info * compptr;
+ JBLOCKROW block;
+ unsigned char *st;
+ int blkn, ci, tbl, sign, k;
+ int v, m;
+
+ /* Process restart marker if needed */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ process_restart(cinfo);
+ entropy->restarts_to_go--;
+ }
+
+ if (entropy->ct == -1) return TRUE; /* if error do nothing */
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+
+ /* Sections F.2.4.1 & F.1.4.4.1: Decoding of DC coefficients */
+
+ tbl = compptr->dc_tbl_no;
+
+ /* Table F.4: Point to statistics bin S0 for DC coefficient coding */
+ st = entropy->dc_stats[tbl] + entropy->dc_context[ci];
+
+ /* Figure F.19: Decode_DC_DIFF */
+ if (arith_decode(cinfo, st) == 0)
+ entropy->dc_context[ci] = 0;
+ else {
+ /* Figure F.21: Decoding nonzero value v */
+ /* Figure F.22: Decoding the sign of v */
+ sign = arith_decode(cinfo, st + 1);
+ st += 2; st += sign;
+ /* Figure F.23: Decoding the magnitude category of v */
+ if ((m = arith_decode(cinfo, st)) != 0) {
+ st = entropy->dc_stats[tbl] + 20; /* Table F.4: X1 = 20 */
+ while (arith_decode(cinfo, st)) {
+ if ((m <<= 1) == 0x8000) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* magnitude overflow */
+ return TRUE;
+ }
+ st += 1;
+ }
+ }
+ /* Section F.1.4.4.1.2: Establish dc_context conditioning category */
+ if (m < (int) (((INT32) 1 << cinfo->arith_dc_L[tbl]) >> 1))
+ entropy->dc_context[ci] = 0; /* zero diff category */
+ else if (m > (int) (((INT32) 1 << cinfo->arith_dc_U[tbl]) >> 1))
+ entropy->dc_context[ci] = 12 + (sign * 4); /* large diff category */
+ else
+ entropy->dc_context[ci] = 4 + (sign * 4); /* small diff category */
+ v = m;
+ /* Figure F.24: Decoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ if (arith_decode(cinfo, st)) v |= m;
+ v += 1; if (sign) v = -v;
+ entropy->last_dc_val[ci] += v;
+ }
+
+ (*block)[0] = (JCOEF) entropy->last_dc_val[ci];
+
+ /* Sections F.2.4.2 & F.1.4.4.2: Decoding of AC coefficients */
+
+ tbl = compptr->ac_tbl_no;
+
+ /* Figure F.20: Decode_AC_coefficients */
+ for (k = 1; k < DCTSIZE2; k++) {
+ st = entropy->ac_stats[tbl] + 3 * (k - 1);
+ if (arith_decode(cinfo, st)) break; /* EOB flag */
+ while (arith_decode(cinfo, st + 1) == 0) {
+ st += 3; k++;
+ if (k >= DCTSIZE2) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* spectral overflow */
+ return TRUE;
+ }
+ }
+ /* Figure F.21: Decoding nonzero value v */
+ /* Figure F.22: Decoding the sign of v */
+ entropy->ac_stats[tbl][245] = 0;
+ sign = arith_decode(cinfo, entropy->ac_stats[tbl] + 245);
+ st += 2;
+ /* Figure F.23: Decoding the magnitude category of v */
+ if ((m = arith_decode(cinfo, st)) != 0) {
+ if (arith_decode(cinfo, st)) {
+ m <<= 1;
+ st = entropy->ac_stats[tbl] +
+ (k <= cinfo->arith_ac_K[tbl] ? 189 : 217);
+ while (arith_decode(cinfo, st)) {
+ if ((m <<= 1) == 0x8000) {
+ WARNMS(cinfo, JWRN_ARITH_BAD_CODE);
+ entropy->ct = -1; /* magnitude overflow */
+ return TRUE;
+ }
+ st += 1;
+ }
+ }
+ }
+ v = m;
+ /* Figure F.24: Decoding the magnitude bit pattern of v */
+ st += 14;
+ while (m >>= 1)
+ if (arith_decode(cinfo, st)) v |= m;
+ v += 1; if (sign) v = -v;
+ (*block)[jpeg_natural_order[k]] = (JCOEF) v;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Initialize for an arithmetic-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass (j_decompress_ptr cinfo)
+{
+ arith_entropy_ptr entropy = (arith_entropy_ptr) cinfo->entropy;
+ int ci, tbl;
+ jpeg_component_info * compptr;
+
+ if (cinfo->progressive_mode) {
+ /* Validate progressive scan parameters */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Se != 0)
+ goto bad;
+ } else {
+ /* need not check Ss/Se < 0 since they came from unsigned bytes */
+ if (cinfo->Se < cinfo->Ss || cinfo->Se >= DCTSIZE2)
+ goto bad;
+ /* AC scans may have only one component */
+ if (cinfo->comps_in_scan != 1)
+ goto bad;
+ }
+ if (cinfo->Ah != 0) {
+ /* Successive approximation refinement scan: must have Al = Ah-1. */
+ if (cinfo->Ah-1 != cinfo->Al)
+ goto bad;
+ }
+ if (cinfo->Al > 13) { /* need not check for < 0 */
+ bad:
+ ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
+ cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+ }
+ /* Update progression status, and verify that scan order is legal.
+ * Note that inter-scan inconsistencies are treated as warnings
+ * not fatal errors ... not clear if this is right way to behave.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ int coefi, cindex = cinfo->cur_comp_info[ci]->component_index;
+ int *coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+ for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
+ int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+ if (cinfo->Ah != expected)
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+ coef_bit_ptr[coefi] = cinfo->Al;
+ }
+ }
+ /* Select MCU decoding routine */
+ if (cinfo->Ah == 0) {
+ if (cinfo->Ss == 0)
+ entropy->pub.decode_mcu = decode_mcu_DC_first;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_first;
+ } else {
+ if (cinfo->Ss == 0)
+ entropy->pub.decode_mcu = decode_mcu_DC_refine;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_refine;
+ }
+ } else {
+ /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+ * This ought to be an error condition, but we make it a warning because
+ * there are some baseline files out there with all zeroes in these bytes.
+ */
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ cinfo->Ah != 0 || cinfo->Al != 0)
+ WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+ /* Select MCU decoding routine */
+ entropy->pub.decode_mcu = decode_mcu;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Allocate & initialize requested statistics areas */
+ if (cinfo->progressive_mode == 0 || (cinfo->Ss == 0 && cinfo->Ah == 0)) {
+ tbl = compptr->dc_tbl_no;
+ if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
+ ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
+ if (entropy->dc_stats[tbl] == NULL)
+ entropy->dc_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, DC_STAT_BINS);
+ MEMZERO(entropy->dc_stats[tbl], DC_STAT_BINS);
+ /* Initialize DC predictions to 0 */
+ entropy->last_dc_val[ci] = 0;
+ entropy->dc_context[ci] = 0;
+ }
+ if (cinfo->progressive_mode == 0 || cinfo->Ss) {
+ tbl = compptr->ac_tbl_no;
+ if (tbl < 0 || tbl >= NUM_ARITH_TBLS)
+ ERREXIT1(cinfo, JERR_NO_ARITH_TABLE, tbl);
+ if (entropy->ac_stats[tbl] == NULL)
+ entropy->ac_stats[tbl] = (unsigned char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, AC_STAT_BINS);
+ MEMZERO(entropy->ac_stats[tbl], AC_STAT_BINS);
+ }
+ }
+
+ /* Initialize arithmetic decoding variables */
+ entropy->c = 0;
+ entropy->a = 0;
+ entropy->ct = -16; /* force reading 2 initial bytes to fill C */
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Module initialization routine for arithmetic entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_arith_decoder (j_decompress_ptr cinfo)
+{
+ arith_entropy_ptr entropy;
+ int i;
+
+ entropy = (arith_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(arith_entropy_decoder));
+ cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ entropy->pub.start_pass = start_pass;
+
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ entropy->dc_stats[i] = NULL;
+ entropy->ac_stats[i] = NULL;
+ }
+
+ if (cinfo->progressive_mode) {
+ /* Create progression status table */
+ int *coef_bit_ptr, ci;
+ cinfo->coef_bits = (int (*)[DCTSIZE2])
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components*DCTSIZE2*SIZEOF(int));
+ coef_bit_ptr = & cinfo->coef_bits[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (i = 0; i < DCTSIZE2; i++)
+ *coef_bit_ptr++ = -1;
+ }
+}
diff --git a/Source/LibJPEG/jdatadst.c b/Source/LibJPEG/jdatadst.c
new file mode 100644
index 0000000..a8f6fb0
--- /dev/null
+++ b/Source/LibJPEG/jdatadst.c
@@ -0,0 +1,151 @@
+/*
+ * jdatadst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains compression data destination routines for the case of
+ * emitting JPEG data to a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * destination manager.
+ * IMPORTANT: we assume that fwrite() will correctly transcribe an array of
+ * JOCTETs into 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data destination object for stdio output */
+
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ FILE * outfile; /* target stream */
+ JOCTET * buffer; /* start of buffer */
+} my_destination_mgr;
+
+typedef my_destination_mgr * my_dest_ptr;
+
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
+
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+
+METHODDEF(void)
+init_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ /* Allocate the output buffer --- it will be released when done with image */
+ dest->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ OUTPUT_BUF_SIZE * SIZEOF(JOCTET));
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines). The
+ * application should resume compression after it has made more room in the
+ * output buffer. Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+
+METHODDEF(boolean)
+empty_output_buffer (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+
+ if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) !=
+ (size_t) OUTPUT_BUF_SIZE)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ dest->pub.next_output_byte = dest->buffer;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written. Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_destination (j_compress_ptr cinfo)
+{
+ my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ }
+ fflush(dest->outfile);
+ /* Make sure we wrote the output file OK */
+ if (ferror(dest->outfile))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile)
+{
+ my_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_destination_mgr));
+ }
+
+ dest = (my_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outfile = outfile;
+}
diff --git a/Source/LibJPEG/jdatasrc.c b/Source/LibJPEG/jdatasrc.c
new file mode 100644
index 0000000..edc752b
--- /dev/null
+++ b/Source/LibJPEG/jdatasrc.c
@@ -0,0 +1,212 @@
+/*
+ * jdatasrc.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains decompression data source routines for the case of
+ * reading JPEG data from a file (or any stdio stream). While these routines
+ * are sufficient for most applications, some will want to use a different
+ * source manager.
+ * IMPORTANT: we assume that fread() will correctly transcribe an array of
+ * JOCTETs from 8-bit-wide elements on external storage. If char is wider
+ * than 8 bits on your machine, you may need to do some tweaking.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jerror.h"
+
+
+/* Expanded data source object for stdio input */
+
+typedef struct {
+ struct jpeg_source_mgr pub; /* public fields */
+
+ FILE * infile; /* source stream */
+ JOCTET * buffer; /* start of buffer */
+ boolean start_of_file; /* have we gotten any data yet? */
+} my_source_mgr;
+
+typedef my_source_mgr * my_src_ptr;
+
+#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
+
+
+/*
+ * Initialize source --- called by jpeg_read_header
+ * before any data is actually read.
+ */
+
+METHODDEF(void)
+init_source (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* We reset the empty-input-file flag for each image,
+ * but we don't clear the input buffer.
+ * This is correct behavior for reading a series of images from one source.
+ */
+ src->start_of_file = TRUE;
+}
+
+
+/*
+ * Fill the input buffer --- called whenever buffer is emptied.
+ *
+ * In typical applications, this should read fresh data into the buffer
+ * (ignoring the current state of next_input_byte & bytes_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been reloaded. It is not necessary to
+ * fill the buffer entirely, only to obtain at least one more byte.
+ *
+ * There is no such thing as an EOF return. If the end of the file has been
+ * reached, the routine has a choice of ERREXIT() or inserting fake data into
+ * the buffer. In most cases, generating a warning message and inserting a
+ * fake EOI marker is the best course of action --- this will allow the
+ * decompressor to output however much of the image is there. However,
+ * the resulting error message is misleading if the real problem is an empty
+ * input file, so we handle that case specially.
+ *
+ * In applications that need to be able to suspend compression due to input
+ * not being available yet, a FALSE return indicates that no more data can be
+ * obtained right now, but more may be forthcoming later. In this situation,
+ * the decompressor will return to its caller (with an indication of the
+ * number of scanlines it has read, if any). The application should resume
+ * decompression after it has loaded more data into the input buffer. Note
+ * that there are substantial restrictions on the use of suspension --- see
+ * the documentation.
+ *
+ * When suspending, the decompressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point must be rescanned after resumption, so move it to
+ * the front of the buffer rather than discarding it.
+ */
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+ size_t nbytes;
+
+ nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
+
+ if (nbytes <= 0) {
+ if (src->start_of_file) /* Treat empty input file as fatal error */
+ ERREXIT(cinfo, JERR_INPUT_EMPTY);
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* Insert a fake EOI marker */
+ src->buffer[0] = (JOCTET) 0xFF;
+ src->buffer[1] = (JOCTET) JPEG_EOI;
+ nbytes = 2;
+ }
+
+ src->pub.next_input_byte = src->buffer;
+ src->pub.bytes_in_buffer = nbytes;
+ src->start_of_file = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Skip data --- used to skip over a potentially large amount of
+ * uninteresting data (such as an APPn marker).
+ *
+ * Writers of suspendable-input applications must note that skip_input_data
+ * is not granted the right to give a suspension return. If the skip extends
+ * beyond the data currently in the buffer, the buffer can be marked empty so
+ * that the next read will cause a fill_input_buffer call that can suspend.
+ * Arranging for additional bytes to be discarded before reloading the input
+ * buffer is the application writer's problem.
+ */
+
+METHODDEF(void)
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+{
+ my_src_ptr src = (my_src_ptr) cinfo->src;
+
+ /* Just a dumb implementation for now. Could use fseek() except
+ * it doesn't work on pipes. Not clear that being smart is worth
+ * any trouble anyway --- large skips are infrequent.
+ */
+ if (num_bytes > 0) {
+ while (num_bytes > (long) src->pub.bytes_in_buffer) {
+ num_bytes -= (long) src->pub.bytes_in_buffer;
+ (void) fill_input_buffer(cinfo);
+ /* note we assume that fill_input_buffer will never return FALSE,
+ * so suspension need not be handled.
+ */
+ }
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+
+/*
+ * An additional method that can be provided by data source modules is the
+ * resync_to_restart method for error recovery in the presence of RST markers.
+ * For the moment, this source module just uses the default resync method
+ * provided by the JPEG library. That method assumes that no backtracking
+ * is possible.
+ */
+
+
+/*
+ * Terminate source --- called by jpeg_finish_decompress
+ * after all data has been read. Often a no-op.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+
+METHODDEF(void)
+term_source (j_decompress_ptr cinfo)
+{
+ /* no work necessary here */
+}
+
+
+/*
+ * Prepare for input from a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing decompression.
+ */
+
+GLOBAL(void)
+jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
+{
+ my_src_ptr src;
+
+ /* The source object and input buffer are made permanent so that a series
+ * of JPEG images can be read from the same file by calling jpeg_stdio_src
+ * only before the first one. (If we discarded the buffer at the end of
+ * one image, we'd likely lose the start of the next one.)
+ * This makes it unsafe to use this manager and a different source
+ * manager serially with the same JPEG object. Caveat programmer.
+ */
+ if (cinfo->src == NULL) { /* first time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_source_mgr));
+ src = (my_src_ptr) cinfo->src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ INPUT_BUF_SIZE * SIZEOF(JOCTET));
+ }
+
+ src = (my_src_ptr) cinfo->src;
+ src->pub.init_source = init_source;
+ src->pub.fill_input_buffer = fill_input_buffer;
+ src->pub.skip_input_data = skip_input_data;
+ src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
+ src->pub.term_source = term_source;
+ src->infile = infile;
+ src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
+ src->pub.next_input_byte = NULL; /* until buffer loaded */
+}
diff --git a/Source/LibJPEG/jdcoefct.c b/Source/LibJPEG/jdcoefct.c
new file mode 100644
index 0000000..462e92c
--- /dev/null
+++ b/Source/LibJPEG/jdcoefct.c
@@ -0,0 +1,736 @@
+/*
+ * jdcoefct.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the coefficient buffer controller for decompression.
+ * This controller is the top level of the JPEG decompressor proper.
+ * The coefficient buffer lies between entropy decoding and inverse-DCT steps.
+ *
+ * In buffered-image mode, this controller is the interface between
+ * input-oriented processing and output-oriented processing.
+ * Also, the input side (only) is used when reading a file for transcoding.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+/* Block smoothing is only applicable for progressive JPEG, so: */
+#ifndef D_PROGRESSIVE_SUPPORTED
+#undef BLOCK_SMOOTHING_SUPPORTED
+#endif
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_coef_controller pub; /* public fields */
+
+ /* These variables keep track of the current location of the input side. */
+ /* cinfo->input_iMCU_row is also used for this. */
+ JDIMENSION MCU_ctr; /* counts MCUs processed in current row */
+ int MCU_vert_offset; /* counts MCU rows within iMCU row */
+ int MCU_rows_per_iMCU_row; /* number of such rows needed */
+
+ /* The output side's location is represented by cinfo->output_iMCU_row. */
+
+ /* In single-pass modes, it's sufficient to buffer just one MCU.
+ * We allocate a workspace of D_MAX_BLOCKS_IN_MCU coefficient blocks,
+ * and let the entropy decoder write into that workspace each time.
+ * (On 80x86, the workspace is FAR even though it's not really very big;
+ * this is to keep the module interfaces unchanged when a large coefficient
+ * buffer is necessary.)
+ * In multi-pass modes, this array points to the current MCU's blocks
+ * within the virtual arrays; it is used only by the input side.
+ */
+ JBLOCKROW MCU_buffer[D_MAX_BLOCKS_IN_MCU];
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* In multi-pass modes, we need a virtual block array for each component. */
+ jvirt_barray_ptr whole_image[MAX_COMPONENTS];
+#endif
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* When doing block smoothing, we latch coefficient Al values here */
+ int * coef_bits_latch;
+#define SAVED_COEFS 6 /* we save coef_bits[0..5] */
+#endif
+} my_coef_controller;
+
+typedef my_coef_controller * my_coef_ptr;
+
+/* Forward declarations */
+METHODDEF(int) decompress_onepass
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+METHODDEF(int) decompress_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+LOCAL(boolean) smoothing_ok JPP((j_decompress_ptr cinfo));
+METHODDEF(int) decompress_smooth_data
+ JPP((j_decompress_ptr cinfo, JSAMPIMAGE output_buf));
+#endif
+
+
+LOCAL(void)
+start_iMCU_row (j_decompress_ptr cinfo)
+/* Reset within-iMCU-row counters for a new row (input side) */
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* In an interleaved scan, an MCU row is the same as an iMCU row.
+ * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows.
+ * But at the bottom of the image, process only what's left.
+ */
+ if (cinfo->comps_in_scan > 1) {
+ coef->MCU_rows_per_iMCU_row = 1;
+ } else {
+ if (cinfo->input_iMCU_row < (cinfo->total_iMCU_rows-1))
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor;
+ else
+ coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height;
+ }
+
+ coef->MCU_ctr = 0;
+ coef->MCU_vert_offset = 0;
+}
+
+
+/*
+ * Initialize for an input processing pass.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->input_iMCU_row = 0;
+ start_iMCU_row(cinfo);
+}
+
+
+/*
+ * Initialize for an output processing pass.
+ */
+
+METHODDEF(void)
+start_output_pass (j_decompress_ptr cinfo)
+{
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+
+ /* If multipass, check to see whether to use block smoothing on this pass */
+ if (coef->pub.coef_arrays != NULL) {
+ if (cinfo->do_block_smoothing && smoothing_ok(cinfo))
+ coef->pub.decompress_data = decompress_smooth_data;
+ else
+ coef->pub.decompress_data = decompress_data;
+ }
+#endif
+ cinfo->output_iMCU_row = 0;
+}
+
+
+/*
+ * Decompress and return some data in the single-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Input and output must run in lockstep since we have only a one-MCU buffer.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image,
+ * which we index according to the component's SOF position.
+ */
+
+METHODDEF(int)
+decompress_onepass (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ int blkn, ci, xindex, yindex, yoffset, useful_width;
+ JSAMPARRAY output_ptr;
+ JDIMENSION start_col, output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Loop to process as much as one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
+ MCU_col_num++) {
+ /* Try to fetch an MCU. Entropy decoder expects buffer to be zeroed. */
+ jzero_far((void FAR *) coef->MCU_buffer[0],
+ (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
+ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ /* Determine where data should go in output_buf and do the IDCT thing.
+ * We skip dummy blocks at the right and bottom edges (but blkn gets
+ * incremented past them!). Note the inner loop relies on having
+ * allocated the MCU_buffer[] blocks sequentially.
+ */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed) {
+ blkn += compptr->MCU_blocks;
+ continue;
+ }
+ inverse_DCT = cinfo->idct->inverse_DCT[compptr->component_index];
+ useful_width = (MCU_col_num < last_MCU_col) ? compptr->MCU_width
+ : compptr->last_col_width;
+ output_ptr = output_buf[compptr->component_index] +
+ yoffset * compptr->DCT_v_scaled_size;
+ start_col = MCU_col_num * compptr->MCU_sample_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ if (cinfo->input_iMCU_row < last_iMCU_row ||
+ yoffset+yindex < compptr->last_row_height) {
+ output_col = start_col;
+ for (xindex = 0; xindex < useful_width; xindex++) {
+ (*inverse_DCT) (cinfo, compptr,
+ (JCOEFPTR) coef->MCU_buffer[blkn+xindex],
+ output_ptr, output_col);
+ output_col += compptr->DCT_h_scaled_size;
+ }
+ }
+ blkn += compptr->MCU_width;
+ output_ptr += compptr->DCT_v_scaled_size;
+ }
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ cinfo->output_iMCU_row++;
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Dummy consume-input routine for single-pass operation.
+ */
+
+METHODDEF(int)
+dummy_consume_data (j_decompress_ptr cinfo)
+{
+ return JPEG_SUSPENDED; /* Always indicate nothing was done */
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Consume input data and store it in the full-image coefficient buffer.
+ * We read as much as one fully interleaved MCU row ("iMCU" row) per call,
+ * ie, v_samp_factor block rows for each component in the scan.
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ */
+
+METHODDEF(int)
+consume_data (j_decompress_ptr cinfo)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION MCU_col_num; /* index of current MCU within row */
+ int blkn, ci, xindex, yindex, yoffset;
+ JDIMENSION start_col;
+ JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN];
+ JBLOCKROW buffer_ptr;
+ jpeg_component_info *compptr;
+
+ /* Align the virtual buffers for the components used in this scan. */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ buffer[ci] = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index],
+ cinfo->input_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ /* Note: entropy decoder expects buffer to be zeroed,
+ * but this is handled automatically by the memory manager
+ * because we requested a pre-zeroed array.
+ */
+ }
+
+ /* Loop to process one whole iMCU row */
+ for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
+ yoffset++) {
+ for (MCU_col_num = coef->MCU_ctr; MCU_col_num < cinfo->MCUs_per_row;
+ MCU_col_num++) {
+ /* Construct list of pointers to DCT blocks belonging to this MCU */
+ blkn = 0; /* index of current DCT block within MCU */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ start_col = MCU_col_num * compptr->MCU_width;
+ for (yindex = 0; yindex < compptr->MCU_height; yindex++) {
+ buffer_ptr = buffer[ci][yindex+yoffset] + start_col;
+ for (xindex = 0; xindex < compptr->MCU_width; xindex++) {
+ coef->MCU_buffer[blkn++] = buffer_ptr++;
+ }
+ }
+ }
+ /* Try to fetch the MCU. */
+ if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
+ /* Suspension forced; update state counters and exit */
+ coef->MCU_vert_offset = yoffset;
+ coef->MCU_ctr = MCU_col_num;
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* Completed an MCU row, but perhaps not an iMCU row */
+ coef->MCU_ctr = 0;
+ }
+ /* Completed the iMCU row, advance counters for next one */
+ if (++(cinfo->input_iMCU_row) < cinfo->total_iMCU_rows) {
+ start_iMCU_row(cinfo);
+ return JPEG_ROW_COMPLETED;
+ }
+ /* Completed the scan */
+ (*cinfo->inputctl->finish_input_pass) (cinfo);
+ return JPEG_SCAN_COMPLETED;
+}
+
+
+/*
+ * Decompress and return some data in the multi-pass case.
+ * Always attempts to emit one fully interleaved MCU row ("iMCU" row).
+ * Return value is JPEG_ROW_COMPLETED, JPEG_SCAN_COMPLETED, or JPEG_SUSPENDED.
+ *
+ * NB: output_buf contains a plane for each component in image.
+ */
+
+METHODDEF(int)
+decompress_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num;
+ int ci, block_row, block_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number < cinfo->output_scan_number ||
+ (cinfo->input_scan_number == cinfo->output_scan_number &&
+ cinfo->input_iMCU_row <= cinfo->output_iMCU_row)) {
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Align the virtual buffer for this component. */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ cinfo->output_iMCU_row * compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row)
+ block_rows = compptr->v_samp_factor;
+ else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ }
+ inverse_DCT = cinfo->idct->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ output_col = 0;
+ for (block_num = 0; block_num < compptr->width_in_blocks; block_num++) {
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) buffer_ptr,
+ output_ptr, output_col);
+ buffer_ptr++;
+ output_col += compptr->DCT_h_scaled_size;
+ }
+ output_ptr += compptr->DCT_v_scaled_size;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+
+/*
+ * This code applies interblock smoothing as described by section K.8
+ * of the JPEG standard: the first 5 AC coefficients are estimated from
+ * the DC values of a DCT block and its 8 neighboring blocks.
+ * We apply smoothing only for progressive JPEG decoding, and only if
+ * the coefficients it can estimate are not yet known to full precision.
+ */
+
+/* Natural-order array positions of the first 5 zigzag-order coefficients */
+#define Q01_POS 1
+#define Q10_POS 8
+#define Q20_POS 16
+#define Q11_POS 9
+#define Q02_POS 2
+
+/*
+ * Determine whether block smoothing is applicable and safe.
+ * We also latch the current states of the coef_bits[] entries for the
+ * AC coefficients; otherwise, if the input side of the decompressor
+ * advances into a new scan, we might think the coefficients are known
+ * more accurately than they really are.
+ */
+
+LOCAL(boolean)
+smoothing_ok (j_decompress_ptr cinfo)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ boolean smoothing_useful = FALSE;
+ int ci, coefi;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtable;
+ int * coef_bits;
+ int * coef_bits_latch;
+
+ if (! cinfo->progressive_mode || cinfo->coef_bits == NULL)
+ return FALSE;
+
+ /* Allocate latch area if not already done */
+ if (coef->coef_bits_latch == NULL)
+ coef->coef_bits_latch = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components *
+ (SAVED_COEFS * SIZEOF(int)));
+ coef_bits_latch = coef->coef_bits_latch;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* All components' quantization values must already be latched. */
+ if ((qtable = compptr->quant_table) == NULL)
+ return FALSE;
+ /* Verify DC & first 5 AC quantizers are nonzero to avoid zero-divide. */
+ if (qtable->quantval[0] == 0 ||
+ qtable->quantval[Q01_POS] == 0 ||
+ qtable->quantval[Q10_POS] == 0 ||
+ qtable->quantval[Q20_POS] == 0 ||
+ qtable->quantval[Q11_POS] == 0 ||
+ qtable->quantval[Q02_POS] == 0)
+ return FALSE;
+ /* DC values must be at least partly known for all components. */
+ coef_bits = cinfo->coef_bits[ci];
+ if (coef_bits[0] < 0)
+ return FALSE;
+ /* Block smoothing is helpful if some AC coefficients remain inaccurate. */
+ for (coefi = 1; coefi <= 5; coefi++) {
+ coef_bits_latch[coefi] = coef_bits[coefi];
+ if (coef_bits[coefi] != 0)
+ smoothing_useful = TRUE;
+ }
+ coef_bits_latch += SAVED_COEFS;
+ }
+
+ return smoothing_useful;
+}
+
+
+/*
+ * Variant of decompress_data for use when doing block smoothing.
+ */
+
+METHODDEF(int)
+decompress_smooth_data (j_decompress_ptr cinfo, JSAMPIMAGE output_buf)
+{
+ my_coef_ptr coef = (my_coef_ptr) cinfo->coef;
+ JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1;
+ JDIMENSION block_num, last_block_column;
+ int ci, block_row, block_rows, access_rows;
+ JBLOCKARRAY buffer;
+ JBLOCKROW buffer_ptr, prev_block_row, next_block_row;
+ JSAMPARRAY output_ptr;
+ JDIMENSION output_col;
+ jpeg_component_info *compptr;
+ inverse_DCT_method_ptr inverse_DCT;
+ boolean first_row, last_row;
+ JBLOCK workspace;
+ int *coef_bits;
+ JQUANT_TBL *quanttbl;
+ INT32 Q00,Q01,Q02,Q10,Q11,Q20, num;
+ int DC1,DC2,DC3,DC4,DC5,DC6,DC7,DC8,DC9;
+ int Al, pred;
+
+ /* Force some input to be done if we are getting ahead of the input. */
+ while (cinfo->input_scan_number <= cinfo->output_scan_number &&
+ ! cinfo->inputctl->eoi_reached) {
+ if (cinfo->input_scan_number == cinfo->output_scan_number) {
+ /* If input is working on current scan, we ordinarily want it to
+ * have completed the current row. But if input scan is DC,
+ * we want it to keep one row ahead so that next block row's DC
+ * values are up to date.
+ */
+ JDIMENSION delta = (cinfo->Ss == 0) ? 1 : 0;
+ if (cinfo->input_iMCU_row > cinfo->output_iMCU_row+delta)
+ break;
+ }
+ if ((*cinfo->inputctl->consume_input)(cinfo) == JPEG_SUSPENDED)
+ return JPEG_SUSPENDED;
+ }
+
+ /* OK, output from the virtual arrays. */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Don't bother to IDCT an uninteresting component. */
+ if (! compptr->component_needed)
+ continue;
+ /* Count non-dummy DCT block rows in this iMCU row. */
+ if (cinfo->output_iMCU_row < last_iMCU_row) {
+ block_rows = compptr->v_samp_factor;
+ access_rows = block_rows * 2; /* this and next iMCU row */
+ last_row = FALSE;
+ } else {
+ /* NB: can't use last_row_height here; it is input-side-dependent! */
+ block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (block_rows == 0) block_rows = compptr->v_samp_factor;
+ access_rows = block_rows; /* this iMCU row only */
+ last_row = TRUE;
+ }
+ /* Align the virtual buffer for this component. */
+ if (cinfo->output_iMCU_row > 0) {
+ access_rows += compptr->v_samp_factor; /* prior iMCU row too */
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (cinfo->output_iMCU_row - 1) * compptr->v_samp_factor,
+ (JDIMENSION) access_rows, FALSE);
+ buffer += compptr->v_samp_factor; /* point to current iMCU row */
+ first_row = FALSE;
+ } else {
+ buffer = (*cinfo->mem->access_virt_barray)
+ ((j_common_ptr) cinfo, coef->whole_image[ci],
+ (JDIMENSION) 0, (JDIMENSION) access_rows, FALSE);
+ first_row = TRUE;
+ }
+ /* Fetch component-dependent info */
+ coef_bits = coef->coef_bits_latch + (ci * SAVED_COEFS);
+ quanttbl = compptr->quant_table;
+ Q00 = quanttbl->quantval[0];
+ Q01 = quanttbl->quantval[Q01_POS];
+ Q10 = quanttbl->quantval[Q10_POS];
+ Q20 = quanttbl->quantval[Q20_POS];
+ Q11 = quanttbl->quantval[Q11_POS];
+ Q02 = quanttbl->quantval[Q02_POS];
+ inverse_DCT = cinfo->idct->inverse_DCT[ci];
+ output_ptr = output_buf[ci];
+ /* Loop over all DCT blocks to be processed. */
+ for (block_row = 0; block_row < block_rows; block_row++) {
+ buffer_ptr = buffer[block_row];
+ if (first_row && block_row == 0)
+ prev_block_row = buffer_ptr;
+ else
+ prev_block_row = buffer[block_row-1];
+ if (last_row && block_row == block_rows-1)
+ next_block_row = buffer_ptr;
+ else
+ next_block_row = buffer[block_row+1];
+ /* We fetch the surrounding DC values using a sliding-register approach.
+ * Initialize all nine here so as to do the right thing on narrow pics.
+ */
+ DC1 = DC2 = DC3 = (int) prev_block_row[0][0];
+ DC4 = DC5 = DC6 = (int) buffer_ptr[0][0];
+ DC7 = DC8 = DC9 = (int) next_block_row[0][0];
+ output_col = 0;
+ last_block_column = compptr->width_in_blocks - 1;
+ for (block_num = 0; block_num <= last_block_column; block_num++) {
+ /* Fetch current DCT block into workspace so we can modify it. */
+ jcopy_block_row(buffer_ptr, (JBLOCKROW) workspace, (JDIMENSION) 1);
+ /* Update DC values */
+ if (block_num < last_block_column) {
+ DC3 = (int) prev_block_row[1][0];
+ DC6 = (int) buffer_ptr[1][0];
+ DC9 = (int) next_block_row[1][0];
+ }
+ /* Compute coefficient estimates per K.8.
+ * An estimate is applied only if coefficient is still zero,
+ * and is not known to be fully accurate.
+ */
+ /* AC01 */
+ if ((Al=coef_bits[1]) != 0 && workspace[1] == 0) {
+ num = 36 * Q00 * (DC4 - DC6);
+ if (num >= 0) {
+ pred = (int) (((Q01<<7) + num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q01<<7) - num) / (Q01<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[1] = (JCOEF) pred;
+ }
+ /* AC10 */
+ if ((Al=coef_bits[2]) != 0 && workspace[8] == 0) {
+ num = 36 * Q00 * (DC2 - DC8);
+ if (num >= 0) {
+ pred = (int) (((Q10<<7) + num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q10<<7) - num) / (Q10<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[8] = (JCOEF) pred;
+ }
+ /* AC20 */
+ if ((Al=coef_bits[3]) != 0 && workspace[16] == 0) {
+ num = 9 * Q00 * (DC2 + DC8 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q20<<7) + num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q20<<7) - num) / (Q20<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[16] = (JCOEF) pred;
+ }
+ /* AC11 */
+ if ((Al=coef_bits[4]) != 0 && workspace[9] == 0) {
+ num = 5 * Q00 * (DC1 - DC3 - DC7 + DC9);
+ if (num >= 0) {
+ pred = (int) (((Q11<<7) + num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q11<<7) - num) / (Q11<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[9] = (JCOEF) pred;
+ }
+ /* AC02 */
+ if ((Al=coef_bits[5]) != 0 && workspace[2] == 0) {
+ num = 9 * Q00 * (DC4 + DC6 - 2*DC5);
+ if (num >= 0) {
+ pred = (int) (((Q02<<7) + num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ } else {
+ pred = (int) (((Q02<<7) - num) / (Q02<<8));
+ if (Al > 0 && pred >= (1<<Al))
+ pred = (1<<Al)-1;
+ pred = -pred;
+ }
+ workspace[2] = (JCOEF) pred;
+ }
+ /* OK, do the IDCT */
+ (*inverse_DCT) (cinfo, compptr, (JCOEFPTR) workspace,
+ output_ptr, output_col);
+ /* Advance for next column */
+ DC1 = DC2; DC2 = DC3;
+ DC4 = DC5; DC5 = DC6;
+ DC7 = DC8; DC8 = DC9;
+ buffer_ptr++, prev_block_row++, next_block_row++;
+ output_col += compptr->DCT_h_scaled_size;
+ }
+ output_ptr += compptr->DCT_v_scaled_size;
+ }
+ }
+
+ if (++(cinfo->output_iMCU_row) < cinfo->total_iMCU_rows)
+ return JPEG_ROW_COMPLETED;
+ return JPEG_SCAN_COMPLETED;
+}
+
+#endif /* BLOCK_SMOOTHING_SUPPORTED */
+
+
+/*
+ * Initialize coefficient buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_coef_ptr coef;
+
+ coef = (my_coef_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_coef_controller));
+ cinfo->coef = (struct jpeg_d_coef_controller *) coef;
+ coef->pub.start_input_pass = start_input_pass;
+ coef->pub.start_output_pass = start_output_pass;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ coef->coef_bits_latch = NULL;
+#endif
+
+ /* Create the coefficient buffer. */
+ if (need_full_buffer) {
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* Allocate a full-image virtual array for each component, */
+ /* padded to a multiple of samp_factor DCT blocks in each direction. */
+ /* Note we ask for a pre-zeroed array. */
+ int ci, access_rows;
+ jpeg_component_info *compptr;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ access_rows = compptr->v_samp_factor;
+#ifdef BLOCK_SMOOTHING_SUPPORTED
+ /* If block smoothing could be used, need a bigger window */
+ if (cinfo->progressive_mode)
+ access_rows *= 3;
+#endif
+ coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
+ (JDIMENSION) jround_up((long) compptr->width_in_blocks,
+ (long) compptr->h_samp_factor),
+ (JDIMENSION) jround_up((long) compptr->height_in_blocks,
+ (long) compptr->v_samp_factor),
+ (JDIMENSION) access_rows);
+ }
+ coef->pub.consume_data = consume_data;
+ coef->pub.decompress_data = decompress_data;
+ coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ /* We only need a single-MCU buffer. */
+ JBLOCKROW buffer;
+ int i;
+
+ buffer = (JBLOCKROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
+ for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
+ coef->MCU_buffer[i] = buffer + i;
+ }
+ coef->pub.consume_data = dummy_consume_data;
+ coef->pub.decompress_data = decompress_onepass;
+ coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
+ }
+}
diff --git a/Source/LibJPEG/jdcolor.c b/Source/LibJPEG/jdcolor.c
new file mode 100644
index 0000000..6c04dfe
--- /dev/null
+++ b/Source/LibJPEG/jdcolor.c
@@ -0,0 +1,396 @@
+/*
+ * jdcolor.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains output colorspace conversion routines.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_deconverter pub; /* public fields */
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+} my_color_deconverter;
+
+typedef my_color_deconverter * my_cconvert_ptr;
+
+
+/**************** YCbCr -> RGB conversion: most common case **************/
+
+/*
+ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
+ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
+ * The conversion equations to be implemented are therefore
+ * R = Y + 1.40200 * Cr
+ * G = Y - 0.34414 * Cb - 0.71414 * Cr
+ * B = Y + 1.77200 * Cb
+ * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
+ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
+ *
+ * To avoid floating-point arithmetic, we represent the fractional constants
+ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
+ * the products by 2^16, with appropriate rounding, to get the correct answer.
+ * Notice that Y, being an integral input, does not contribute any fraction
+ * so it need not participate in the rounding.
+ *
+ * For even more speed, we avoid doing any multiplications in the inner loop
+ * by precalculating the constants times Cb and Cr for all possible values.
+ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
+ * for 12-bit samples it is still acceptable. It's not very reasonable for
+ * 16-bit samples, but if you want lossless storage you shouldn't be changing
+ * colorspace anyway.
+ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
+ * values for the G calculation are left scaled up, since we must add them
+ * together before rounding.
+ */
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ cconvert->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ cconvert->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ cconvert->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ cconvert->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ cconvert->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Convert some rows of samples to the output colorspace.
+ *
+ * Note that we change from noninterleaved, one-plane-per-component format
+ * to interleaved-pixel format. The output buffer is therefore three times
+ * as wide as the input buffer.
+ * A starting row offset is provided only for the input buffer. The caller
+ * can easily adjust the passed output_buf value to accommodate any row
+ * offset required on that side.
+ */
+
+METHODDEF(void)
+ycc_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[RGB_RED] = range_limit[y + Crrtab[cr]];
+ outptr[RGB_GREEN] = range_limit[y +
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS))];
+ outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/**************** Cases other than YCbCr -> RGB **************/
+
+
+/*
+ * Color conversion for no colorspace change: just copy the data,
+ * converting from separate-planes to interleaved representation.
+ */
+
+METHODDEF(void)
+null_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION count;
+ register int num_components = cinfo->num_components;
+ JDIMENSION num_cols = cinfo->output_width;
+ int ci;
+
+ while (--num_rows >= 0) {
+ for (ci = 0; ci < num_components; ci++) {
+ inptr = input_buf[ci][input_row];
+ outptr = output_buf[0] + ci;
+ for (count = num_cols; count > 0; count--) {
+ *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */
+ outptr += num_components;
+ }
+ }
+ input_row++;
+ output_buf++;
+ }
+}
+
+
+/*
+ * Color conversion for grayscale: just copy the data.
+ * This also works for YCbCr -> grayscale conversion, in which
+ * we just copy the Y (luminance) component and ignore chrominance.
+ */
+
+METHODDEF(void)
+grayscale_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
+ num_rows, cinfo->output_width);
+}
+
+
+/*
+ * Convert grayscale to RGB: just duplicate the graylevel three times.
+ * This is provided to support applications that don't want to cope
+ * with grayscale as a separate case.
+ */
+
+METHODDEF(void)
+gray_rgb_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+
+ while (--num_rows >= 0) {
+ inptr = input_buf[0][input_row++];
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ /* We can dispense with GETJSAMPLE() here */
+ outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
+ outptr += RGB_PIXELSIZE;
+ }
+ }
+}
+
+
+/*
+ * Adobe-style YCCK->CMYK conversion.
+ * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
+ * conversion as above, while passing K (black) unchanged.
+ * We assume build_ycc_rgb_table has been called.
+ */
+
+METHODDEF(void)
+ycck_cmyk_convert (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+ register int y, cb, cr;
+ register JSAMPROW outptr;
+ register JSAMPROW inptr0, inptr1, inptr2, inptr3;
+ register JDIMENSION col;
+ JDIMENSION num_cols = cinfo->output_width;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ register int * Crrtab = cconvert->Cr_r_tab;
+ register int * Cbbtab = cconvert->Cb_b_tab;
+ register INT32 * Crgtab = cconvert->Cr_g_tab;
+ register INT32 * Cbgtab = cconvert->Cb_g_tab;
+ SHIFT_TEMPS
+
+ while (--num_rows >= 0) {
+ inptr0 = input_buf[0][input_row];
+ inptr1 = input_buf[1][input_row];
+ inptr2 = input_buf[2][input_row];
+ inptr3 = input_buf[3][input_row];
+ input_row++;
+ outptr = *output_buf++;
+ for (col = 0; col < num_cols; col++) {
+ y = GETJSAMPLE(inptr0[col]);
+ cb = GETJSAMPLE(inptr1[col]);
+ cr = GETJSAMPLE(inptr2[col]);
+ /* Range-limiting is essential due to noise introduced by DCT losses. */
+ outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */
+ outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
+ ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
+ SCALEBITS)))];
+ outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */
+ /* K passes through unchanged */
+ outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
+ outptr += 4;
+ }
+ }
+}
+
+
+/*
+ * Empty method for start_pass.
+ */
+
+METHODDEF(void)
+start_pass_dcolor (j_decompress_ptr cinfo)
+{
+ /* no work needed */
+}
+
+
+/*
+ * Module initialization routine for output colorspace conversion.
+ */
+
+GLOBAL(void)
+jinit_color_deconverter (j_decompress_ptr cinfo)
+{
+ my_cconvert_ptr cconvert;
+ int ci;
+
+ cconvert = (my_cconvert_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_color_deconverter));
+ cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
+ cconvert->pub.start_pass = start_pass_dcolor;
+
+ /* Make sure num_components agrees with jpeg_color_space */
+ switch (cinfo->jpeg_color_space) {
+ case JCS_GRAYSCALE:
+ if (cinfo->num_components != 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_RGB:
+ case JCS_YCbCr:
+ if (cinfo->num_components != 3)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ case JCS_CMYK:
+ case JCS_YCCK:
+ if (cinfo->num_components != 4)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+
+ default: /* JCS_UNKNOWN can be anything */
+ if (cinfo->num_components < 1)
+ ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
+ break;
+ }
+
+ /* Set out_color_components and conversion method based on requested space.
+ * Also clear the component_needed flags for any unused components,
+ * so that earlier pipeline stages can avoid useless computation.
+ */
+
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
+ cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = grayscale_convert;
+ /* For color->grayscale conversion, only the Y (0) component is needed */
+ for (ci = 1; ci < cinfo->num_components; ci++)
+ cinfo->comp_info[ci].component_needed = FALSE;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_RGB:
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ if (cinfo->jpeg_color_space == JCS_YCbCr) {
+ cconvert->pub.color_convert = ycc_rgb_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
+ cconvert->pub.color_convert = gray_rgb_convert;
+ } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ case JCS_CMYK:
+ cinfo->out_color_components = 4;
+ if (cinfo->jpeg_color_space == JCS_YCCK) {
+ cconvert->pub.color_convert = ycck_cmyk_convert;
+ build_ycc_rgb_table(cinfo);
+ } else if (cinfo->jpeg_color_space == JCS_CMYK) {
+ cconvert->pub.color_convert = null_convert;
+ } else
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+
+ default:
+ /* Permit null conversion to same output space */
+ if (cinfo->out_color_space == cinfo->jpeg_color_space) {
+ cinfo->out_color_components = cinfo->num_components;
+ cconvert->pub.color_convert = null_convert;
+ } else /* unsupported non-null conversion */
+ ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
+ break;
+ }
+
+ if (cinfo->quantize_colors)
+ cinfo->output_components = 1; /* single colormapped output component */
+ else
+ cinfo->output_components = cinfo->out_color_components;
+}
diff --git a/Source/LibJPEG/jdct.h b/Source/LibJPEG/jdct.h
new file mode 100644
index 0000000..360dec8
--- /dev/null
+++ b/Source/LibJPEG/jdct.h
@@ -0,0 +1,393 @@
+/*
+ * jdct.h
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file contains common declarations for the forward and
+ * inverse DCT modules. These declarations are private to the DCT managers
+ * (jcdctmgr.c, jddctmgr.c) and the individual DCT algorithms.
+ * The individual DCT algorithms are kept in separate files to ease
+ * machine-dependent tuning (e.g., assembly coding).
+ */
+
+
+/*
+ * A forward DCT routine is given a pointer to an input sample array and
+ * a pointer to a work area of type DCTELEM[]; the DCT is to be performed
+ * in-place in that buffer. Type DCTELEM is int for 8-bit samples, INT32
+ * for 12-bit samples. (NOTE: Floating-point DCT implementations use an
+ * array of type FAST_FLOAT, instead.)
+ * The input data is to be fetched from the sample array starting at a
+ * specified column. (Any row offset needed will be applied to the array
+ * pointer before it is passed to the FDCT code.)
+ * Note that the number of samples fetched by the FDCT routine is
+ * DCT_h_scaled_size * DCT_v_scaled_size.
+ * The DCT outputs are returned scaled up by a factor of 8; they therefore
+ * have a range of +-8K for 8-bit data, +-128K for 12-bit data. This
+ * convention improves accuracy in integer implementations and saves some
+ * work in floating-point ones.
+ * Quantization of the output coefficients is done by jcdctmgr.c.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef int DCTELEM; /* 16 or 32 bits is fine */
+#else
+typedef INT32 DCTELEM; /* must have 32 bits */
+#endif
+
+typedef JMETHOD(void, forward_DCT_method_ptr, (DCTELEM * data,
+ JSAMPARRAY sample_data,
+ JDIMENSION start_col));
+typedef JMETHOD(void, float_DCT_method_ptr, (FAST_FLOAT * data,
+ JSAMPARRAY sample_data,
+ JDIMENSION start_col));
+
+
+/*
+ * An inverse DCT routine is given a pointer to the input JBLOCK and a pointer
+ * to an output sample array. The routine must dequantize the input data as
+ * well as perform the IDCT; for dequantization, it uses the multiplier table
+ * pointed to by compptr->dct_table. The output data is to be placed into the
+ * sample array starting at a specified column. (Any row offset needed will
+ * be applied to the array pointer before it is passed to the IDCT code.)
+ * Note that the number of samples emitted by the IDCT routine is
+ * DCT_h_scaled_size * DCT_v_scaled_size.
+ */
+
+/* typedef inverse_DCT_method_ptr is declared in jpegint.h */
+
+/*
+ * Each IDCT routine has its own ideas about the best dct_table element type.
+ */
+
+typedef MULTIPLIER ISLOW_MULT_TYPE; /* short or int, whichever is faster */
+#if BITS_IN_JSAMPLE == 8
+typedef MULTIPLIER IFAST_MULT_TYPE; /* 16 bits is OK, use short if faster */
+#define IFAST_SCALE_BITS 2 /* fractional bits in scale factors */
+#else
+typedef INT32 IFAST_MULT_TYPE; /* need 32 bits for scaled quantizers */
+#define IFAST_SCALE_BITS 13 /* fractional bits in scale factors */
+#endif
+typedef FAST_FLOAT FLOAT_MULT_TYPE; /* preferred floating type */
+
+
+/*
+ * Each IDCT routine is responsible for range-limiting its results and
+ * converting them to unsigned form (0..MAXJSAMPLE). The raw outputs could
+ * be quite far out of range if the input data is corrupt, so a bulletproof
+ * range-limiting step is required. We use a mask-and-table-lookup method
+ * to do the combined operations quickly. See the comments with
+ * prepare_range_limit_table (in jdmaster.c) for more info.
+ */
+
+#define IDCT_range_limit(cinfo) ((cinfo)->sample_range_limit + CENTERJSAMPLE)
+
+#define RANGE_MASK (MAXJSAMPLE * 4 + 3) /* 2 bits wider than legal samples */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_fdct_islow jFDislow
+#define jpeg_fdct_ifast jFDifast
+#define jpeg_fdct_float jFDfloat
+#define jpeg_fdct_7x7 jFD7x7
+#define jpeg_fdct_6x6 jFD6x6
+#define jpeg_fdct_5x5 jFD5x5
+#define jpeg_fdct_4x4 jFD4x4
+#define jpeg_fdct_3x3 jFD3x3
+#define jpeg_fdct_2x2 jFD2x2
+#define jpeg_fdct_1x1 jFD1x1
+#define jpeg_fdct_9x9 jFD9x9
+#define jpeg_fdct_10x10 jFD10x10
+#define jpeg_fdct_11x11 jFD11x11
+#define jpeg_fdct_12x12 jFD12x12
+#define jpeg_fdct_13x13 jFD13x13
+#define jpeg_fdct_14x14 jFD14x14
+#define jpeg_fdct_15x15 jFD15x15
+#define jpeg_fdct_16x16 jFD16x16
+#define jpeg_fdct_16x8 jFD16x8
+#define jpeg_fdct_14x7 jFD14x7
+#define jpeg_fdct_12x6 jFD12x6
+#define jpeg_fdct_10x5 jFD10x5
+#define jpeg_fdct_8x4 jFD8x4
+#define jpeg_fdct_6x3 jFD6x3
+#define jpeg_fdct_4x2 jFD4x2
+#define jpeg_fdct_2x1 jFD2x1
+#define jpeg_fdct_8x16 jFD8x16
+#define jpeg_fdct_7x14 jFD7x14
+#define jpeg_fdct_6x12 jFD6x12
+#define jpeg_fdct_5x10 jFD5x10
+#define jpeg_fdct_4x8 jFD4x8
+#define jpeg_fdct_3x6 jFD3x6
+#define jpeg_fdct_2x4 jFD2x4
+#define jpeg_fdct_1x2 jFD1x2
+#define jpeg_idct_islow jRDislow
+#define jpeg_idct_ifast jRDifast
+#define jpeg_idct_float jRDfloat
+#define jpeg_idct_7x7 jRD7x7
+#define jpeg_idct_6x6 jRD6x6
+#define jpeg_idct_5x5 jRD5x5
+#define jpeg_idct_4x4 jRD4x4
+#define jpeg_idct_3x3 jRD3x3
+#define jpeg_idct_2x2 jRD2x2
+#define jpeg_idct_1x1 jRD1x1
+#define jpeg_idct_9x9 jRD9x9
+#define jpeg_idct_10x10 jRD10x10
+#define jpeg_idct_11x11 jRD11x11
+#define jpeg_idct_12x12 jRD12x12
+#define jpeg_idct_13x13 jRD13x13
+#define jpeg_idct_14x14 jRD14x14
+#define jpeg_idct_15x15 jRD15x15
+#define jpeg_idct_16x16 jRD16x16
+#define jpeg_idct_16x8 jRD16x8
+#define jpeg_idct_14x7 jRD14x7
+#define jpeg_idct_12x6 jRD12x6
+#define jpeg_idct_10x5 jRD10x5
+#define jpeg_idct_8x4 jRD8x4
+#define jpeg_idct_6x3 jRD6x3
+#define jpeg_idct_4x2 jRD4x2
+#define jpeg_idct_2x1 jRD2x1
+#define jpeg_idct_8x16 jRD8x16
+#define jpeg_idct_7x14 jRD7x14
+#define jpeg_idct_6x12 jRD6x12
+#define jpeg_idct_5x10 jRD5x10
+#define jpeg_idct_4x8 jRD4x8
+#define jpeg_idct_3x6 jRD3x8
+#define jpeg_idct_2x4 jRD2x4
+#define jpeg_idct_1x2 jRD1x2
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+/* Extern declarations for the forward and inverse DCT routines. */
+
+EXTERN(void) jpeg_fdct_islow
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_ifast
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_float
+ JPP((FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_7x7
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_6x6
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_5x5
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_4x4
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_3x3
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_2x2
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_1x1
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_9x9
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_10x10
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_11x11
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_12x12
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_13x13
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_14x14
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_15x15
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_16x16
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_16x8
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_14x7
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_12x6
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_10x5
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_8x4
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_6x3
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_4x2
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_2x1
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_8x16
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_7x14
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_6x12
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_5x10
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_4x8
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_3x6
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_2x4
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+EXTERN(void) jpeg_fdct_1x2
+ JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
+
+EXTERN(void) jpeg_idct_islow
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_ifast
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_float
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_7x7
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_6x6
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_5x5
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x4
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_3x3
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x2
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_1x1
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_9x9
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_10x10
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_11x11
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_12x12
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_13x13
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_14x14
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_15x15
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_16x16
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_16x8
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_14x7
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_12x6
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_10x5
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_8x4
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_6x3
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x2
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x1
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_8x16
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_7x14
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_6x12
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_5x10
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_4x8
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_3x6
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_2x4
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+EXTERN(void) jpeg_idct_1x2
+ JPP((j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block, JSAMPARRAY output_buf, JDIMENSION output_col));
+
+
+/*
+ * Macros for handling fixed-point arithmetic; these are used by many
+ * but not all of the DCT/IDCT modules.
+ *
+ * All values are expected to be of type INT32.
+ * Fractional constants are scaled left by CONST_BITS bits.
+ * CONST_BITS is defined within each module using these macros,
+ * and may differ from one module to the next.
+ */
+
+#define ONE ((INT32) 1)
+#define CONST_SCALE (ONE << CONST_BITS)
+
+/* Convert a positive real constant to an integer scaled by CONST_SCALE.
+ * Caution: some C compilers fail to reduce "FIX(constant)" at compile time,
+ * thus causing a lot of useless floating-point operations at run time.
+ */
+
+#define FIX(x) ((INT32) ((x) * CONST_SCALE + 0.5))
+
+/* Descale and correctly round an INT32 value that's scaled by N bits.
+ * We assume RIGHT_SHIFT rounds towards minus infinity, so adding
+ * the fudge factor is correct for either sign of X.
+ */
+
+#define DESCALE(x,n) RIGHT_SHIFT((x) + (ONE << ((n)-1)), n)
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * This macro is used only when the two inputs will actually be no more than
+ * 16 bits wide, so that a 16x16->32 bit multiply can be used instead of a
+ * full 32x32 multiply. This provides a useful speedup on many machines.
+ * Unfortunately there is no way to specify a 16x16->32 multiply portably
+ * in C, but some C compilers will do the right thing if you provide the
+ * correct combination of casts.
+ */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT16) (const)))
+#endif
+#ifdef SHORTxLCONST_32 /* known to work with Microsoft C 6.0 */
+#define MULTIPLY16C16(var,const) (((INT16) (var)) * ((INT32) (const)))
+#endif
+
+#ifndef MULTIPLY16C16 /* default definition */
+#define MULTIPLY16C16(var,const) ((var) * (const))
+#endif
+
+/* Same except both inputs are variables. */
+
+#ifdef SHORTxSHORT_32 /* may work if 'int' is 32 bits */
+#define MULTIPLY16V16(var1,var2) (((INT16) (var1)) * ((INT16) (var2)))
+#endif
+
+#ifndef MULTIPLY16V16 /* default definition */
+#define MULTIPLY16V16(var1,var2) ((var1) * (var2))
+#endif
diff --git a/Source/LibJPEG/jddctmgr.c b/Source/LibJPEG/jddctmgr.c
new file mode 100644
index 0000000..bdbde34
--- /dev/null
+++ b/Source/LibJPEG/jddctmgr.c
@@ -0,0 +1,382 @@
+/*
+ * jddctmgr.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the inverse-DCT management logic.
+ * This code selects a particular IDCT implementation to be used,
+ * and it performs related housekeeping chores. No code in this file
+ * is executed per IDCT step, only during output pass setup.
+ *
+ * Note that the IDCT routines are responsible for performing coefficient
+ * dequantization as well as the IDCT proper. This module sets up the
+ * dequantization multiplier table needed by the IDCT routine.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+
+/*
+ * The decompressor input side (jdinput.c) saves away the appropriate
+ * quantization table for each component at the start of the first scan
+ * involving that component. (This is necessary in order to correctly
+ * decode files that reuse Q-table slots.)
+ * When we are ready to make an output pass, the saved Q-table is converted
+ * to a multiplier table that will actually be used by the IDCT routine.
+ * The multiplier table contents are IDCT-method-dependent. To support
+ * application changes in IDCT method between scans, we can remake the
+ * multiplier tables if necessary.
+ * In buffered-image mode, the first output pass may occur before any data
+ * has been seen for some components, and thus before their Q-tables have
+ * been saved away. To handle this case, multiplier tables are preset
+ * to zeroes; the result of the IDCT will be a neutral gray level.
+ */
+
+
+/* Private subobject for this module */
+
+typedef struct {
+ struct jpeg_inverse_dct pub; /* public fields */
+
+ /* This array contains the IDCT method code that each multiplier table
+ * is currently set up for, or -1 if it's not yet set up.
+ * The actual multiplier tables are pointed to by dct_table in the
+ * per-component comp_info structures.
+ */
+ int cur_method[MAX_COMPONENTS];
+} my_idct_controller;
+
+typedef my_idct_controller * my_idct_ptr;
+
+
+/* Allocated multiplier tables: big enough for any supported variant */
+
+typedef union {
+ ISLOW_MULT_TYPE islow_array[DCTSIZE2];
+#ifdef DCT_IFAST_SUPPORTED
+ IFAST_MULT_TYPE ifast_array[DCTSIZE2];
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ FLOAT_MULT_TYPE float_array[DCTSIZE2];
+#endif
+} multiplier_table;
+
+
+/* The current scaled-IDCT routines require ISLOW-style multiplier tables,
+ * so be sure to compile that code if either ISLOW or SCALING is requested.
+ */
+#ifdef DCT_ISLOW_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#else
+#ifdef IDCT_SCALING_SUPPORTED
+#define PROVIDE_ISLOW_TABLES
+#endif
+#endif
+
+
+/*
+ * Prepare for an output pass.
+ * Here we select the proper IDCT routine for each component and build
+ * a matching multiplier table.
+ */
+
+METHODDEF(void)
+start_pass (j_decompress_ptr cinfo)
+{
+ my_idct_ptr idct = (my_idct_ptr) cinfo->idct;
+ int ci, i;
+ jpeg_component_info *compptr;
+ int method = 0;
+ inverse_DCT_method_ptr method_ptr = NULL;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Select the proper IDCT routine for this component's scaling */
+ switch ((compptr->DCT_h_scaled_size << 8) + compptr->DCT_v_scaled_size) {
+#ifdef IDCT_SCALING_SUPPORTED
+ case ((1 << 8) + 1):
+ method_ptr = jpeg_idct_1x1;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((2 << 8) + 2):
+ method_ptr = jpeg_idct_2x2;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((3 << 8) + 3):
+ method_ptr = jpeg_idct_3x3;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((4 << 8) + 4):
+ method_ptr = jpeg_idct_4x4;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((5 << 8) + 5):
+ method_ptr = jpeg_idct_5x5;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((6 << 8) + 6):
+ method_ptr = jpeg_idct_6x6;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((7 << 8) + 7):
+ method_ptr = jpeg_idct_7x7;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((9 << 8) + 9):
+ method_ptr = jpeg_idct_9x9;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((10 << 8) + 10):
+ method_ptr = jpeg_idct_10x10;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((11 << 8) + 11):
+ method_ptr = jpeg_idct_11x11;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((12 << 8) + 12):
+ method_ptr = jpeg_idct_12x12;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((13 << 8) + 13):
+ method_ptr = jpeg_idct_13x13;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((14 << 8) + 14):
+ method_ptr = jpeg_idct_14x14;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((15 << 8) + 15):
+ method_ptr = jpeg_idct_15x15;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((16 << 8) + 16):
+ method_ptr = jpeg_idct_16x16;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((16 << 8) + 8):
+ method_ptr = jpeg_idct_16x8;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((14 << 8) + 7):
+ method_ptr = jpeg_idct_14x7;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((12 << 8) + 6):
+ method_ptr = jpeg_idct_12x6;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((10 << 8) + 5):
+ method_ptr = jpeg_idct_10x5;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((8 << 8) + 4):
+ method_ptr = jpeg_idct_8x4;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((6 << 8) + 3):
+ method_ptr = jpeg_idct_6x3;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((4 << 8) + 2):
+ method_ptr = jpeg_idct_4x2;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((2 << 8) + 1):
+ method_ptr = jpeg_idct_2x1;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((8 << 8) + 16):
+ method_ptr = jpeg_idct_8x16;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((7 << 8) + 14):
+ method_ptr = jpeg_idct_7x14;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((6 << 8) + 12):
+ method_ptr = jpeg_idct_6x12;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((5 << 8) + 10):
+ method_ptr = jpeg_idct_5x10;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((4 << 8) + 8):
+ method_ptr = jpeg_idct_4x8;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((3 << 8) + 6):
+ method_ptr = jpeg_idct_3x6;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((2 << 8) + 4):
+ method_ptr = jpeg_idct_2x4;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+ case ((1 << 8) + 2):
+ method_ptr = jpeg_idct_1x2;
+ method = JDCT_ISLOW; /* jidctint uses islow-style table */
+ break;
+#endif
+ case ((DCTSIZE << 8) + DCTSIZE):
+ switch (cinfo->dct_method) {
+#ifdef DCT_ISLOW_SUPPORTED
+ case JDCT_ISLOW:
+ method_ptr = jpeg_idct_islow;
+ method = JDCT_ISLOW;
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ method_ptr = jpeg_idct_ifast;
+ method = JDCT_IFAST;
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ method_ptr = jpeg_idct_float;
+ method = JDCT_FLOAT;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ break;
+ default:
+ ERREXIT2(cinfo, JERR_BAD_DCTSIZE,
+ compptr->DCT_h_scaled_size, compptr->DCT_v_scaled_size);
+ break;
+ }
+ idct->pub.inverse_DCT[ci] = method_ptr;
+ /* Create multiplier table from quant table.
+ * However, we can skip this if the component is uninteresting
+ * or if we already built the table. Also, if no quant table
+ * has yet been saved for the component, we leave the
+ * multiplier table all-zero; we'll be reading zeroes from the
+ * coefficient controller's buffer anyway.
+ */
+ if (! compptr->component_needed || idct->cur_method[ci] == method)
+ continue;
+ qtbl = compptr->quant_table;
+ if (qtbl == NULL) /* happens if no data yet for component */
+ continue;
+ idct->cur_method[ci] = method;
+ switch (method) {
+#ifdef PROVIDE_ISLOW_TABLES
+ case JDCT_ISLOW:
+ {
+ /* For LL&M IDCT method, multipliers are equal to raw quantization
+ * coefficients, but are stored as ints to ensure access efficiency.
+ */
+ ISLOW_MULT_TYPE * ismtbl = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ for (i = 0; i < DCTSIZE2; i++) {
+ ismtbl[i] = (ISLOW_MULT_TYPE) qtbl->quantval[i];
+ }
+ }
+ break;
+#endif
+#ifdef DCT_IFAST_SUPPORTED
+ case JDCT_IFAST:
+ {
+ /* For AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ * For integer operation, the multiplier table is to be scaled by
+ * IFAST_SCALE_BITS.
+ */
+ IFAST_MULT_TYPE * ifmtbl = (IFAST_MULT_TYPE *) compptr->dct_table;
+#define CONST_BITS 14
+ static const INT16 aanscales[DCTSIZE2] = {
+ /* precomputed values scaled up by 14 bits */
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
+ 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
+ 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
+ 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
+ 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
+ 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
+ 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
+ };
+ SHIFT_TEMPS
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ ifmtbl[i] = (IFAST_MULT_TYPE)
+ DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i],
+ (INT32) aanscales[i]),
+ CONST_BITS-IFAST_SCALE_BITS);
+ }
+ }
+ break;
+#endif
+#ifdef DCT_FLOAT_SUPPORTED
+ case JDCT_FLOAT:
+ {
+ /* For float AA&N IDCT method, multipliers are equal to quantization
+ * coefficients scaled by scalefactor[row]*scalefactor[col], where
+ * scalefactor[0] = 1
+ * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
+ */
+ FLOAT_MULT_TYPE * fmtbl = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ int row, col;
+ static const double aanscalefactor[DCTSIZE] = {
+ 1.0, 1.387039845, 1.306562965, 1.175875602,
+ 1.0, 0.785694958, 0.541196100, 0.275899379
+ };
+
+ i = 0;
+ for (row = 0; row < DCTSIZE; row++) {
+ for (col = 0; col < DCTSIZE; col++) {
+ fmtbl[i] = (FLOAT_MULT_TYPE)
+ ((double) qtbl->quantval[i] *
+ aanscalefactor[row] * aanscalefactor[col]);
+ i++;
+ }
+ }
+ }
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+ }
+}
+
+
+/*
+ * Initialize IDCT manager.
+ */
+
+GLOBAL(void)
+jinit_inverse_dct (j_decompress_ptr cinfo)
+{
+ my_idct_ptr idct;
+ int ci;
+ jpeg_component_info *compptr;
+
+ idct = (my_idct_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_idct_controller));
+ cinfo->idct = (struct jpeg_inverse_dct *) idct;
+ idct->pub.start_pass = start_pass;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Allocate and pre-zero a multiplier table for each component */
+ compptr->dct_table =
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(multiplier_table));
+ MEMZERO(compptr->dct_table, SIZEOF(multiplier_table));
+ /* Mark multiplier table not yet set up for any method */
+ idct->cur_method[ci] = -1;
+ }
+}
diff --git a/Source/LibJPEG/jdhuff.c b/Source/LibJPEG/jdhuff.c
new file mode 100644
index 0000000..a5d679e
--- /dev/null
+++ b/Source/LibJPEG/jdhuff.c
@@ -0,0 +1,1309 @@
+/*
+ * jdhuff.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2006-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains Huffman entropy decoding routines.
+ * Both sequential and progressive modes are supported in this single module.
+ *
+ * Much of the complexity here has to do with supporting input suspension.
+ * If the data source module demands suspension, we want to be able to back
+ * up to the start of the current MCU. To do this, we copy state variables
+ * into local working storage, and update them back to the permanent
+ * storage only upon successful completion of an MCU.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Derived data constructed for each Huffman table */
+
+#define HUFF_LOOKAHEAD 8 /* # of bits of lookahead */
+
+typedef struct {
+ /* Basic tables: (element [0] of each array is unused) */
+ INT32 maxcode[18]; /* largest code of length k (-1 if none) */
+ /* (maxcode[17] is a sentinel to ensure jpeg_huff_decode terminates) */
+ INT32 valoffset[17]; /* huffval[] offset for codes of length k */
+ /* valoffset[k] = huffval[] index of 1st symbol of code length k, less
+ * the smallest code of length k; so given a code of length k, the
+ * corresponding symbol is huffval[code + valoffset[k]]
+ */
+
+ /* Link to public Huffman table (needed only in jpeg_huff_decode) */
+ JHUFF_TBL *pub;
+
+ /* Lookahead tables: indexed by the next HUFF_LOOKAHEAD bits of
+ * the input data stream. If the next Huffman code is no more
+ * than HUFF_LOOKAHEAD bits long, we can obtain its length and
+ * the corresponding symbol directly from these tables.
+ */
+ int look_nbits[1<<HUFF_LOOKAHEAD]; /* # bits, or 0 if too long */
+ UINT8 look_sym[1<<HUFF_LOOKAHEAD]; /* symbol, or unused */
+} d_derived_tbl;
+
+
+/*
+ * Fetching the next N bits from the input stream is a time-critical operation
+ * for the Huffman decoders. We implement it with a combination of inline
+ * macros and out-of-line subroutines. Note that N (the number of bits
+ * demanded at one time) never exceeds 15 for JPEG use.
+ *
+ * We read source bytes into get_buffer and dole out bits as needed.
+ * If get_buffer already contains enough bits, they are fetched in-line
+ * by the macros CHECK_BIT_BUFFER and GET_BITS. When there aren't enough
+ * bits, jpeg_fill_bit_buffer is called; it will attempt to fill get_buffer
+ * as full as possible (not just to the number of bits needed; this
+ * prefetching reduces the overhead cost of calling jpeg_fill_bit_buffer).
+ * Note that jpeg_fill_bit_buffer may return FALSE to indicate suspension.
+ * On TRUE return, jpeg_fill_bit_buffer guarantees that get_buffer contains
+ * at least the requested number of bits --- dummy zeroes are inserted if
+ * necessary.
+ */
+
+typedef INT32 bit_buf_type; /* type of bit-extraction buffer */
+#define BIT_BUF_SIZE 32 /* size of buffer in bits */
+
+/* If long is > 32 bits on your machine, and shifting/masking longs is
+ * reasonably fast, making bit_buf_type be long and setting BIT_BUF_SIZE
+ * appropriately should be a win. Unfortunately we can't define the size
+ * with something like #define BIT_BUF_SIZE (sizeof(bit_buf_type)*8)
+ * because not all machines measure sizeof in 8-bit bytes.
+ */
+
+typedef struct { /* Bitreading state saved across MCUs */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+} bitread_perm_state;
+
+typedef struct { /* Bitreading working state within an MCU */
+ /* Current data source location */
+ /* We need a copy, rather than munging the original, in case of suspension */
+ const JOCTET * next_input_byte; /* => next byte to read from source */
+ size_t bytes_in_buffer; /* # of bytes remaining in source buffer */
+ /* Bit input buffer --- note these values are kept in register variables,
+ * not in this struct, inside the inner loops.
+ */
+ bit_buf_type get_buffer; /* current bit-extraction buffer */
+ int bits_left; /* # of unused bits in it */
+ /* Pointer needed by jpeg_fill_bit_buffer. */
+ j_decompress_ptr cinfo; /* back link to decompress master record */
+} bitread_working_state;
+
+/* Macros to declare and load/save bitread local variables. */
+#define BITREAD_STATE_VARS \
+ register bit_buf_type get_buffer; \
+ register int bits_left; \
+ bitread_working_state br_state
+
+#define BITREAD_LOAD_STATE(cinfop,permstate) \
+ br_state.cinfo = cinfop; \
+ br_state.next_input_byte = cinfop->src->next_input_byte; \
+ br_state.bytes_in_buffer = cinfop->src->bytes_in_buffer; \
+ get_buffer = permstate.get_buffer; \
+ bits_left = permstate.bits_left;
+
+#define BITREAD_SAVE_STATE(cinfop,permstate) \
+ cinfop->src->next_input_byte = br_state.next_input_byte; \
+ cinfop->src->bytes_in_buffer = br_state.bytes_in_buffer; \
+ permstate.get_buffer = get_buffer; \
+ permstate.bits_left = bits_left
+
+/*
+ * These macros provide the in-line portion of bit fetching.
+ * Use CHECK_BIT_BUFFER to ensure there are N bits in get_buffer
+ * before using GET_BITS, PEEK_BITS, or DROP_BITS.
+ * The variables get_buffer and bits_left are assumed to be locals,
+ * but the state struct might not be (jpeg_huff_decode needs this).
+ * CHECK_BIT_BUFFER(state,n,action);
+ * Ensure there are N bits in get_buffer; if suspend, take action.
+ * val = GET_BITS(n);
+ * Fetch next N bits.
+ * val = PEEK_BITS(n);
+ * Fetch next N bits without removing them from the buffer.
+ * DROP_BITS(n);
+ * Discard next N bits.
+ * The value N should be a simple variable, not an expression, because it
+ * is evaluated multiple times.
+ */
+
+#define CHECK_BIT_BUFFER(state,nbits,action) \
+ { if (bits_left < (nbits)) { \
+ if (! jpeg_fill_bit_buffer(&(state),get_buffer,bits_left,nbits)) \
+ { action; } \
+ get_buffer = (state).get_buffer; bits_left = (state).bits_left; } }
+
+#define GET_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left -= (nbits)))) & BIT_MASK(nbits))
+
+#define PEEK_BITS(nbits) \
+ (((int) (get_buffer >> (bits_left - (nbits)))) & BIT_MASK(nbits))
+
+#define DROP_BITS(nbits) \
+ (bits_left -= (nbits))
+
+
+/*
+ * Code for extracting next Huffman-coded symbol from input bit stream.
+ * Again, this is time-critical and we make the main paths be macros.
+ *
+ * We use a lookahead table to process codes of up to HUFF_LOOKAHEAD bits
+ * without looping. Usually, more than 95% of the Huffman codes will be 8
+ * or fewer bits long. The few overlength codes are handled with a loop,
+ * which need not be inline code.
+ *
+ * Notes about the HUFF_DECODE macro:
+ * 1. Near the end of the data segment, we may fail to get enough bits
+ * for a lookahead. In that case, we do it the hard way.
+ * 2. If the lookahead table contains no entry, the next code must be
+ * more than HUFF_LOOKAHEAD bits long.
+ * 3. jpeg_huff_decode returns -1 if forced to suspend.
+ */
+
+#define HUFF_DECODE(result,state,htbl,failaction,slowlabel) \
+{ register int nb, look; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ if (! jpeg_fill_bit_buffer(&state,get_buffer,bits_left, 0)) {failaction;} \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ if (bits_left < HUFF_LOOKAHEAD) { \
+ nb = 1; goto slowlabel; \
+ } \
+ } \
+ look = PEEK_BITS(HUFF_LOOKAHEAD); \
+ if ((nb = htbl->look_nbits[look]) != 0) { \
+ DROP_BITS(nb); \
+ result = htbl->look_sym[look]; \
+ } else { \
+ nb = HUFF_LOOKAHEAD+1; \
+slowlabel: \
+ if ((result=jpeg_huff_decode(&state,get_buffer,bits_left,htbl,nb)) < 0) \
+ { failaction; } \
+ get_buffer = state.get_buffer; bits_left = state.bits_left; \
+ } \
+}
+
+
+/*
+ * Expanded entropy decoder object for Huffman decoding.
+ *
+ * The savable_state subrecord contains fields that change within an MCU,
+ * but must not be updated permanently until we complete the MCU.
+ */
+
+typedef struct {
+ unsigned int EOBRUN; /* remaining EOBs in EOBRUN */
+ int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */
+} savable_state;
+
+/* This macro is to work around compilers with missing or broken
+ * structure assignment. You'll need to fix this code if you have
+ * such a compiler and you change MAX_COMPS_IN_SCAN.
+ */
+
+#ifndef NO_STRUCT_ASSIGN
+#define ASSIGN_STATE(dest,src) ((dest) = (src))
+#else
+#if MAX_COMPS_IN_SCAN == 4
+#define ASSIGN_STATE(dest,src) \
+ ((dest).EOBRUN = (src).EOBRUN, \
+ (dest).last_dc_val[0] = (src).last_dc_val[0], \
+ (dest).last_dc_val[1] = (src).last_dc_val[1], \
+ (dest).last_dc_val[2] = (src).last_dc_val[2], \
+ (dest).last_dc_val[3] = (src).last_dc_val[3])
+#endif
+#endif
+
+
+typedef struct {
+ struct jpeg_entropy_decoder pub; /* public fields */
+
+ /* These fields are loaded into local variables at start of each MCU.
+ * In case of suspension, we exit WITHOUT updating them.
+ */
+ bitread_perm_state bitstate; /* Bit buffer at start of MCU */
+ savable_state saved; /* Other state at start of MCU */
+
+ /* These fields are NOT loaded into local working state. */
+ unsigned int restarts_to_go; /* MCUs left in this restart interval */
+
+ /* Following two fields used only in progressive mode */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * derived_tbls[NUM_HUFF_TBLS];
+
+ d_derived_tbl * ac_derived_tbl; /* active table during an AC scan */
+
+ /* Following fields used only in sequential mode */
+
+ /* Pointers to derived tables (these workspaces have image lifespan) */
+ d_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS];
+ d_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS];
+
+ /* Precalculated info set up by start_pass for use in decode_mcu: */
+
+ /* Pointers to derived tables to be used for each block within an MCU */
+ d_derived_tbl * dc_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+ d_derived_tbl * ac_cur_tbls[D_MAX_BLOCKS_IN_MCU];
+ /* Whether we care about the DC and AC coefficient values for each block */
+ int coef_limit[D_MAX_BLOCKS_IN_MCU];
+} huff_entropy_decoder;
+
+typedef huff_entropy_decoder * huff_entropy_ptr;
+
+
+static const int jpeg_zigzag_order[8][8] = {
+ { 0, 1, 5, 6, 14, 15, 27, 28 },
+ { 2, 4, 7, 13, 16, 26, 29, 42 },
+ { 3, 8, 12, 17, 25, 30, 41, 43 },
+ { 9, 11, 18, 24, 31, 40, 44, 53 },
+ { 10, 19, 23, 32, 39, 45, 52, 54 },
+ { 20, 22, 33, 38, 46, 51, 55, 60 },
+ { 21, 34, 37, 47, 50, 56, 59, 61 },
+ { 35, 36, 48, 49, 57, 58, 62, 63 }
+};
+
+
+/*
+ * Compute the derived values for a Huffman table.
+ * This routine also performs some validation checks on the table.
+ */
+
+LOCAL(void)
+jpeg_make_d_derived_tbl (j_decompress_ptr cinfo, boolean isDC, int tblno,
+ d_derived_tbl ** pdtbl)
+{
+ JHUFF_TBL *htbl;
+ d_derived_tbl *dtbl;
+ int p, i, l, si, numsymbols;
+ int lookbits, ctr;
+ char huffsize[257];
+ unsigned int huffcode[257];
+ unsigned int code;
+
+ /* Note that huffsize[] and huffcode[] are filled in code-length order,
+ * paralleling the order of the symbols themselves in htbl->huffval[].
+ */
+
+ /* Find the input Huffman table */
+ if (tblno < 0 || tblno >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+ htbl =
+ isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno];
+ if (htbl == NULL)
+ ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno);
+
+ /* Allocate a workspace if we haven't already done so. */
+ if (*pdtbl == NULL)
+ *pdtbl = (d_derived_tbl *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(d_derived_tbl));
+ dtbl = *pdtbl;
+ dtbl->pub = htbl; /* fill in back link */
+
+ /* Figure C.1: make table of Huffman code length for each symbol */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ i = (int) htbl->bits[l];
+ if (i < 0 || p + i > 256) /* protect against table overrun */
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ while (i--)
+ huffsize[p++] = (char) l;
+ }
+ huffsize[p] = 0;
+ numsymbols = p;
+
+ /* Figure C.2: generate the codes themselves */
+ /* We also validate that the counts represent a legal Huffman code tree. */
+
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while (((int) huffsize[p]) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ /* code is now 1 more than the last code used for codelength si; but
+ * it must still fit in si bits, since no code is allowed to be all ones.
+ */
+ if (((INT32) code) >= (((INT32) 1) << si))
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ code <<= 1;
+ si++;
+ }
+
+ /* Figure F.15: generate decoding tables for bit-sequential decoding */
+
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ if (htbl->bits[l]) {
+ /* valoffset[l] = huffval[] index of 1st symbol of code length l,
+ * minus the minimum code of length l
+ */
+ dtbl->valoffset[l] = (INT32) p - (INT32) huffcode[p];
+ p += htbl->bits[l];
+ dtbl->maxcode[l] = huffcode[p-1]; /* maximum code of length l */
+ } else {
+ dtbl->maxcode[l] = -1; /* -1 if no codes of this length */
+ }
+ }
+ dtbl->maxcode[17] = 0xFFFFFL; /* ensures jpeg_huff_decode terminates */
+
+ /* Compute lookahead tables to speed up decoding.
+ * First we set all the table entries to 0, indicating "too long";
+ * then we iterate through the Huffman codes that are short enough and
+ * fill in all the entries that correspond to bit sequences starting
+ * with that code.
+ */
+
+ MEMZERO(dtbl->look_nbits, SIZEOF(dtbl->look_nbits));
+
+ p = 0;
+ for (l = 1; l <= HUFF_LOOKAHEAD; l++) {
+ for (i = 1; i <= (int) htbl->bits[l]; i++, p++) {
+ /* l = current code's length, p = its index in huffcode[] & huffval[]. */
+ /* Generate left-justified code followed by all possible bit sequences */
+ lookbits = huffcode[p] << (HUFF_LOOKAHEAD-l);
+ for (ctr = 1 << (HUFF_LOOKAHEAD-l); ctr > 0; ctr--) {
+ dtbl->look_nbits[lookbits] = l;
+ dtbl->look_sym[lookbits] = htbl->huffval[p];
+ lookbits++;
+ }
+ }
+ }
+
+ /* Validate symbols as being reasonable.
+ * For AC tables, we make no check, but accept all byte values 0..255.
+ * For DC tables, we require the symbols to be in range 0..15.
+ * (Tighter bounds could be applied depending on the data depth and mode,
+ * but this is sufficient to ensure safe decoding.)
+ */
+ if (isDC) {
+ for (i = 0; i < numsymbols; i++) {
+ int sym = htbl->huffval[i];
+ if (sym < 0 || sym > 15)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+ }
+ }
+}
+
+
+/*
+ * Out-of-line code for bit fetching.
+ * Note: current values of get_buffer and bits_left are passed as parameters,
+ * but are returned in the corresponding fields of the state struct.
+ *
+ * On most machines MIN_GET_BITS should be 25 to allow the full 32-bit width
+ * of get_buffer to be used. (On machines with wider words, an even larger
+ * buffer could be used.) However, on some machines 32-bit shifts are
+ * quite slow and take time proportional to the number of places shifted.
+ * (This is true with most PC compilers, for instance.) In this case it may
+ * be a win to set MIN_GET_BITS to the minimum value of 15. This reduces the
+ * average shift distance at the cost of more calls to jpeg_fill_bit_buffer.
+ */
+
+#ifdef SLOW_SHIFT_32
+#define MIN_GET_BITS 15 /* minimum allowable value */
+#else
+#define MIN_GET_BITS (BIT_BUF_SIZE-7)
+#endif
+
+
+LOCAL(boolean)
+jpeg_fill_bit_buffer (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ int nbits)
+/* Load up the bit buffer to a depth of at least nbits */
+{
+ /* Copy heavily used state fields into locals (hopefully registers) */
+ register const JOCTET * next_input_byte = state->next_input_byte;
+ register size_t bytes_in_buffer = state->bytes_in_buffer;
+ j_decompress_ptr cinfo = state->cinfo;
+
+ /* Attempt to load at least MIN_GET_BITS bits into get_buffer. */
+ /* (It is assumed that no request will be for more than that many bits.) */
+ /* We fail to do so only if we hit a marker or are forced to suspend. */
+
+ if (cinfo->unread_marker == 0) { /* cannot advance past a marker */
+ while (bits_left < MIN_GET_BITS) {
+ register int c;
+
+ /* Attempt to read a byte */
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+
+ /* If it's 0xFF, check and discard stuffed zero byte */
+ if (c == 0xFF) {
+ /* Loop here to discard any padding FF's on terminating marker,
+ * so that we can save a valid unread_marker value. NOTE: we will
+ * accept multiple FF's followed by a 0 as meaning a single FF data
+ * byte. This data pattern is not valid according to the standard.
+ */
+ do {
+ if (bytes_in_buffer == 0) {
+ if (! (*cinfo->src->fill_input_buffer) (cinfo))
+ return FALSE;
+ next_input_byte = cinfo->src->next_input_byte;
+ bytes_in_buffer = cinfo->src->bytes_in_buffer;
+ }
+ bytes_in_buffer--;
+ c = GETJOCTET(*next_input_byte++);
+ } while (c == 0xFF);
+
+ if (c == 0) {
+ /* Found FF/00, which represents an FF data byte */
+ c = 0xFF;
+ } else {
+ /* Oops, it's actually a marker indicating end of compressed data.
+ * Save the marker code for later use.
+ * Fine point: it might appear that we should save the marker into
+ * bitread working state, not straight into permanent state. But
+ * once we have hit a marker, we cannot need to suspend within the
+ * current MCU, because we will read no more bytes from the data
+ * source. So it is OK to update permanent state right away.
+ */
+ cinfo->unread_marker = c;
+ /* See if we need to insert some fake zero bits. */
+ goto no_more_bytes;
+ }
+ }
+
+ /* OK, load c into get_buffer */
+ get_buffer = (get_buffer << 8) | c;
+ bits_left += 8;
+ } /* end while */
+ } else {
+ no_more_bytes:
+ /* We get here if we've read the marker that terminates the compressed
+ * data segment. There should be enough bits in the buffer register
+ * to satisfy the request; if so, no problem.
+ */
+ if (nbits > bits_left) {
+ /* Uh-oh. Report corrupted data to user and stuff zeroes into
+ * the data stream, so that we can produce some kind of image.
+ * We use a nonvolatile flag to ensure that only one warning message
+ * appears per data segment.
+ */
+ if (! cinfo->entropy->insufficient_data) {
+ WARNMS(cinfo, JWRN_HIT_MARKER);
+ cinfo->entropy->insufficient_data = TRUE;
+ }
+ /* Fill the buffer with zero bits */
+ get_buffer <<= MIN_GET_BITS - bits_left;
+ bits_left = MIN_GET_BITS;
+ }
+ }
+
+ /* Unload the local registers */
+ state->next_input_byte = next_input_byte;
+ state->bytes_in_buffer = bytes_in_buffer;
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ return TRUE;
+}
+
+
+/*
+ * Figure F.12: extend sign bit.
+ * On some machines, a shift and sub will be faster than a table lookup.
+ */
+
+#ifdef AVOID_TABLES
+
+#define BIT_MASK(nbits) ((1<<(nbits))-1)
+#define HUFF_EXTEND(x,s) ((x) < (1<<((s)-1)) ? (x) - ((1<<(s))-1) : (x))
+
+#else
+
+#define BIT_MASK(nbits) bmask[nbits]
+#define HUFF_EXTEND(x,s) ((x) <= bmask[(s) - 1] ? (x) - bmask[s] : (x))
+
+static const int bmask[16] = /* bmask[n] is mask for n rightmost bits */
+ { 0, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF };
+
+#endif /* AVOID_TABLES */
+
+
+/*
+ * Out-of-line code for Huffman code decoding.
+ */
+
+LOCAL(int)
+jpeg_huff_decode (bitread_working_state * state,
+ register bit_buf_type get_buffer, register int bits_left,
+ d_derived_tbl * htbl, int min_bits)
+{
+ register int l = min_bits;
+ register INT32 code;
+
+ /* HUFF_DECODE has determined that the code is at least min_bits */
+ /* bits long, so fetch that many bits in one swoop. */
+
+ CHECK_BIT_BUFFER(*state, l, return -1);
+ code = GET_BITS(l);
+
+ /* Collect the rest of the Huffman code one bit at a time. */
+ /* This is per Figure F.16 in the JPEG spec. */
+
+ while (code > htbl->maxcode[l]) {
+ code <<= 1;
+ CHECK_BIT_BUFFER(*state, 1, return -1);
+ code |= GET_BITS(1);
+ l++;
+ }
+
+ /* Unload the local registers */
+ state->get_buffer = get_buffer;
+ state->bits_left = bits_left;
+
+ /* With garbage input we may reach the sentinel value l = 17. */
+
+ if (l > 16) {
+ WARNMS(state->cinfo, JWRN_HUFF_BAD_CODE);
+ return 0; /* fake a zero as the safest result */
+ }
+
+ return htbl->pub->huffval[ (int) (code + htbl->valoffset[l]) ];
+}
+
+
+/*
+ * Check for a restart marker & resynchronize decoder.
+ * Returns FALSE if must suspend.
+ */
+
+LOCAL(boolean)
+process_restart (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci;
+
+ /* Throw away any unused bits remaining in bit buffer; */
+ /* include any full bytes in next_marker's count of discarded bytes */
+ cinfo->marker->discarded_bytes += entropy->bitstate.bits_left / 8;
+ entropy->bitstate.bits_left = 0;
+
+ /* Advance past the RSTn marker */
+ if (! (*cinfo->marker->read_restart_marker) (cinfo))
+ return FALSE;
+
+ /* Re-initialize DC predictions to 0 */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++)
+ entropy->saved.last_dc_val[ci] = 0;
+ /* Re-init EOB run count, too */
+ entropy->saved.EOBRUN = 0;
+
+ /* Reset restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+
+ /* Reset out-of-data flag, unless read_restart_marker left us smack up
+ * against a marker. In that case we will end up treating the next data
+ * segment as empty, and we can avoid producing bogus output pixels by
+ * leaving the flag set.
+ */
+ if (cinfo->unread_marker == 0)
+ entropy->pub.insufficient_data = FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * Huffman MCU decoding.
+ * Each of these routines decodes and returns one MCU's worth of
+ * Huffman-compressed coefficients.
+ * The coefficients are reordered from zigzag order into natural array order,
+ * but are not dequantized.
+ *
+ * The i'th block of the MCU is stored into the block pointed to by
+ * MCU_data[i]. WE ASSUME THIS AREA IS INITIALLY ZEROED BY THE CALLER.
+ * (Wholesale zeroing is usually a little faster than retail...)
+ *
+ * We return FALSE if data source requested suspension. In that case no
+ * changes have been made to permanent state. (Exception: some output
+ * coefficients may already have been assigned. This is harmless for
+ * spectral selection, since we'll just re-assign them on the next call.
+ * Successive approximation AC refinement has to be more careful, however.)
+ */
+
+/*
+ * MCU decoding for DC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int Al = cinfo->Al;
+ register int s, r;
+ int blkn, ci;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ savable_state state;
+ d_derived_tbl * tbl;
+ jpeg_component_info * compptr;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ tbl = entropy->derived_tbls[compptr->dc_tbl_no];
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label1);
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+
+ /* Convert DC difference to actual value, update last_dc_val */
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Scale and output the coefficient (assumes jpeg_natural_order[0]=0) */
+ (*block)[0] = (JCOEF) (s << Al);
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC initial scan (either spectral selection,
+ * or first pass of successive approximation).
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_first (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int Se = cinfo->Se;
+ int Al = cinfo->Al;
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state.
+ * We can avoid loading/saving bitread state if in an EOB run.
+ */
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+
+ if (EOBRUN > 0) /* if it's a band of zeroes... */
+ EOBRUN--; /* ...process it now (we do nothing) */
+ else {
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ for (k = cinfo->Ss; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, return FALSE, label2);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Scale and output coefficient in natural (dezigzagged) order */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) (s << Al);
+ } else {
+ if (r == 15) { /* ZRL */
+ k += 15; /* skip 15 zeroes in band */
+ } else { /* EOBr, run length is 2^r + appended bits */
+ EOBRUN = 1 << r;
+ if (r) { /* EOBr, r > 0 */
+ CHECK_BIT_BUFFER(br_state, r, return FALSE);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ EOBRUN--; /* this band is processed at this moment */
+ break; /* force end-of-band */
+ }
+ }
+ }
+
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ }
+
+ /* Completed MCU, so update state */
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for DC successive approximation refinement scan.
+ * Note: we assume such scans can be multi-component, although the spec
+ * is not very clear on the point.
+ */
+
+METHODDEF(boolean)
+decode_mcu_DC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int blkn;
+ JBLOCKROW block;
+ BITREAD_STATE_VARS;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* Not worth the cycles to check insufficient_data here,
+ * since we will not change the data anyway if we read zeroes.
+ */
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ block = MCU_data[blkn];
+
+ /* Encoded data is simply the next bit of the two's-complement DC value */
+ CHECK_BIT_BUFFER(br_state, 1, return FALSE);
+ if (GET_BITS(1))
+ (*block)[0] |= p1;
+ /* Note: since we use |=, repeating the assignment later is safe */
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * MCU decoding for AC successive approximation refinement scan.
+ */
+
+METHODDEF(boolean)
+decode_mcu_AC_refine (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int Se = cinfo->Se;
+ int p1 = 1 << cinfo->Al; /* 1 in the bit position being coded */
+ int m1 = (-1) << cinfo->Al; /* -1 in the bit position being coded */
+ register int s, k, r;
+ unsigned int EOBRUN;
+ JBLOCKROW block;
+ JCOEFPTR thiscoef;
+ BITREAD_STATE_VARS;
+ d_derived_tbl * tbl;
+ int num_newnz;
+ int newnz_pos[DCTSIZE2];
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, don't modify the MCU.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ EOBRUN = entropy->saved.EOBRUN; /* only part of saved state we need */
+
+ /* There is always only one block per MCU */
+ block = MCU_data[0];
+ tbl = entropy->ac_derived_tbl;
+
+ /* If we are forced to suspend, we must undo the assignments to any newly
+ * nonzero coefficients in the block, because otherwise we'd get confused
+ * next time about which coefficients were already nonzero.
+ * But we need not undo addition of bits to already-nonzero coefficients;
+ * instead, we can test the current bit to see if we already did it.
+ */
+ num_newnz = 0;
+
+ /* initialize coefficient loop counter to start of band */
+ k = cinfo->Ss;
+
+ if (EOBRUN == 0) {
+ for (; k <= Se; k++) {
+ HUFF_DECODE(s, br_state, tbl, goto undoit, label3);
+ r = s >> 4;
+ s &= 15;
+ if (s) {
+ if (s != 1) /* size of new coef should always be 1 */
+ WARNMS(cinfo, JWRN_HUFF_BAD_CODE);
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1))
+ s = p1; /* newly nonzero coef is positive */
+ else
+ s = m1; /* newly nonzero coef is negative */
+ } else {
+ if (r != 15) {
+ EOBRUN = 1 << r; /* EOBr, run length is 2^r + appended bits */
+ if (r) {
+ CHECK_BIT_BUFFER(br_state, r, goto undoit);
+ r = GET_BITS(r);
+ EOBRUN += r;
+ }
+ break; /* rest of block is handled by EOB logic */
+ }
+ /* note s = 0 for processing ZRL */
+ }
+ /* Advance over already-nonzero coefs and r still-zero coefs,
+ * appending correction bits to the nonzeroes. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ do {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already set it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ } else {
+ if (--r < 0)
+ break; /* reached target zero coefficient */
+ }
+ k++;
+ } while (k <= Se);
+ if (s) {
+ int pos = jpeg_natural_order[k];
+ /* Output newly nonzero coefficient */
+ (*block)[pos] = (JCOEF) s;
+ /* Remember its position in case we have to suspend */
+ newnz_pos[num_newnz++] = pos;
+ }
+ }
+ }
+
+ if (EOBRUN > 0) {
+ /* Scan any remaining coefficient positions after the end-of-band
+ * (the last newly nonzero coefficient, if any). Append a correction
+ * bit to each already-nonzero coefficient. A correction bit is 1
+ * if the absolute value of the coefficient must be increased.
+ */
+ for (; k <= Se; k++) {
+ thiscoef = *block + jpeg_natural_order[k];
+ if (*thiscoef != 0) {
+ CHECK_BIT_BUFFER(br_state, 1, goto undoit);
+ if (GET_BITS(1)) {
+ if ((*thiscoef & p1) == 0) { /* do nothing if already changed it */
+ if (*thiscoef >= 0)
+ *thiscoef += p1;
+ else
+ *thiscoef += m1;
+ }
+ }
+ }
+ }
+ /* Count one block completed in EOB run */
+ EOBRUN--;
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ entropy->saved.EOBRUN = EOBRUN; /* only part of saved state we need */
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+
+undoit:
+ /* Re-zero any output coefficients that we made newly nonzero */
+ while (num_newnz > 0)
+ (*block)[newnz_pos[--num_newnz]] = 0;
+
+ return FALSE;
+}
+
+
+/*
+ * Decode one MCU's worth of Huffman-compressed coefficients.
+ */
+
+METHODDEF(boolean)
+decode_mcu (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int blkn;
+ BITREAD_STATE_VARS;
+ savable_state state;
+
+ /* Process restart marker if needed; may have to suspend */
+ if (cinfo->restart_interval) {
+ if (entropy->restarts_to_go == 0)
+ if (! process_restart(cinfo))
+ return FALSE;
+ }
+
+ /* If we've run out of data, just leave the MCU set to zeroes.
+ * This way, we return uniform gray for the remainder of the segment.
+ */
+ if (! entropy->pub.insufficient_data) {
+
+ /* Load up working state */
+ BITREAD_LOAD_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(state, entropy->saved);
+
+ /* Outer loop handles each block in the MCU */
+
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ JBLOCKROW block = MCU_data[blkn];
+ d_derived_tbl * htbl;
+ register int s, k, r;
+ int coef_limit, ci;
+
+ /* Decode a single block's worth of coefficients */
+
+ /* Section F.2.2.1: decode the DC coefficient difference */
+ htbl = entropy->dc_cur_tbls[blkn];
+ HUFF_DECODE(s, br_state, htbl, return FALSE, label1);
+
+ htbl = entropy->ac_cur_tbls[blkn];
+ k = 1;
+ coef_limit = entropy->coef_limit[blkn];
+ if (coef_limit) {
+ /* Convert DC difference to actual value, update last_dc_val */
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ }
+ ci = cinfo->MCU_membership[blkn];
+ s += state.last_dc_val[ci];
+ state.last_dc_val[ci] = s;
+ /* Output the DC coefficient */
+ (*block)[0] = (JCOEF) s;
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* Since zeroes are skipped, output area must be cleared beforehand */
+ for (; k < coef_limit; k++) {
+ HUFF_DECODE(s, br_state, htbl, return FALSE, label2);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ r = GET_BITS(s);
+ s = HUFF_EXTEND(r, s);
+ /* Output coefficient in natural (dezigzagged) order.
+ * Note: the extra entries in jpeg_natural_order[] will save us
+ * if k >= DCTSIZE2, which could happen if the data is corrupted.
+ */
+ (*block)[jpeg_natural_order[k]] = (JCOEF) s;
+ } else {
+ if (r != 15)
+ goto EndOfBlock;
+ k += 15;
+ }
+ }
+ } else {
+ if (s) {
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ DROP_BITS(s);
+ }
+ }
+
+ /* Section F.2.2.2: decode the AC coefficients */
+ /* In this path we just discard the values */
+ for (; k < DCTSIZE2; k++) {
+ HUFF_DECODE(s, br_state, htbl, return FALSE, label3);
+
+ r = s >> 4;
+ s &= 15;
+
+ if (s) {
+ k += r;
+ CHECK_BIT_BUFFER(br_state, s, return FALSE);
+ DROP_BITS(s);
+ } else {
+ if (r != 15)
+ break;
+ k += 15;
+ }
+ }
+
+ EndOfBlock: ;
+ }
+
+ /* Completed MCU, so update state */
+ BITREAD_SAVE_STATE(cinfo,entropy->bitstate);
+ ASSIGN_STATE(entropy->saved, state);
+ }
+
+ /* Account for restart interval (no-op if not using restarts) */
+ entropy->restarts_to_go--;
+
+ return TRUE;
+}
+
+
+/*
+ * Initialize for a Huffman-compressed scan.
+ */
+
+METHODDEF(void)
+start_pass_huff_decoder (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy;
+ int ci, blkn, dctbl, actbl, i;
+ jpeg_component_info * compptr;
+
+ if (cinfo->progressive_mode) {
+ /* Validate progressive scan parameters */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Se != 0)
+ goto bad;
+ } else {
+ /* need not check Ss/Se < 0 since they came from unsigned bytes */
+ if (cinfo->Se < cinfo->Ss || cinfo->Se >= DCTSIZE2)
+ goto bad;
+ /* AC scans may have only one component */
+ if (cinfo->comps_in_scan != 1)
+ goto bad;
+ }
+ if (cinfo->Ah != 0) {
+ /* Successive approximation refinement scan: must have Al = Ah-1. */
+ if (cinfo->Ah-1 != cinfo->Al)
+ goto bad;
+ }
+ if (cinfo->Al > 13) { /* need not check for < 0 */
+ /* Arguably the maximum Al value should be less than 13 for 8-bit precision,
+ * but the spec doesn't say so, and we try to be liberal about what we
+ * accept. Note: large Al values could result in out-of-range DC
+ * coefficients during early scans, leading to bizarre displays due to
+ * overflows in the IDCT math. But we won't crash.
+ */
+ bad:
+ ERREXIT4(cinfo, JERR_BAD_PROGRESSION,
+ cinfo->Ss, cinfo->Se, cinfo->Ah, cinfo->Al);
+ }
+ /* Update progression status, and verify that scan order is legal.
+ * Note that inter-scan inconsistencies are treated as warnings
+ * not fatal errors ... not clear if this is right way to behave.
+ */
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ int coefi, cindex = cinfo->cur_comp_info[ci]->component_index;
+ int *coef_bit_ptr = & cinfo->coef_bits[cindex][0];
+ if (cinfo->Ss && coef_bit_ptr[0] < 0) /* AC without prior DC scan */
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, 0);
+ for (coefi = cinfo->Ss; coefi <= cinfo->Se; coefi++) {
+ int expected = (coef_bit_ptr[coefi] < 0) ? 0 : coef_bit_ptr[coefi];
+ if (cinfo->Ah != expected)
+ WARNMS2(cinfo, JWRN_BOGUS_PROGRESSION, cindex, coefi);
+ coef_bit_ptr[coefi] = cinfo->Al;
+ }
+ }
+
+ /* Select MCU decoding routine */
+ if (cinfo->Ah == 0) {
+ if (cinfo->Ss == 0)
+ entropy->pub.decode_mcu = decode_mcu_DC_first;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_first;
+ } else {
+ if (cinfo->Ss == 0)
+ entropy->pub.decode_mcu = decode_mcu_DC_refine;
+ else
+ entropy->pub.decode_mcu = decode_mcu_AC_refine;
+ }
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Make sure requested tables are present, and compute derived tables.
+ * We may build same derived table more than once, but it's not expensive.
+ */
+ if (cinfo->Ss == 0) {
+ if (cinfo->Ah == 0) { /* DC refinement needs no table */
+ i = compptr->dc_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, TRUE, i,
+ & entropy->derived_tbls[i]);
+ }
+ } else {
+ i = compptr->ac_tbl_no;
+ jpeg_make_d_derived_tbl(cinfo, FALSE, i,
+ & entropy->derived_tbls[i]);
+ /* remember the single active table */
+ entropy->ac_derived_tbl = entropy->derived_tbls[i];
+ }
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Initialize private state variables */
+ entropy->saved.EOBRUN = 0;
+ } else {
+ /* Check that the scan parameters Ss, Se, Ah/Al are OK for sequential JPEG.
+ * This ought to be an error condition, but we make it a warning because
+ * there are some baseline files out there with all zeroes in these bytes.
+ */
+ if (cinfo->Ss != 0 || cinfo->Se != DCTSIZE2-1 ||
+ cinfo->Ah != 0 || cinfo->Al != 0)
+ WARNMS(cinfo, JWRN_NOT_SEQUENTIAL);
+
+ /* Select MCU decoding routine */
+ entropy->pub.decode_mcu = decode_mcu;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ dctbl = compptr->dc_tbl_no;
+ actbl = compptr->ac_tbl_no;
+ /* Compute derived values for Huffman tables */
+ /* We may do this more than once for a table, but it's not expensive */
+ jpeg_make_d_derived_tbl(cinfo, TRUE, dctbl,
+ & entropy->dc_derived_tbls[dctbl]);
+ jpeg_make_d_derived_tbl(cinfo, FALSE, actbl,
+ & entropy->ac_derived_tbls[actbl]);
+ /* Initialize DC predictions to 0 */
+ entropy->saved.last_dc_val[ci] = 0;
+ }
+
+ /* Precalculate decoding info for each block in an MCU of this scan */
+ for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) {
+ ci = cinfo->MCU_membership[blkn];
+ compptr = cinfo->cur_comp_info[ci];
+ /* Precalculate which table to use for each block */
+ entropy->dc_cur_tbls[blkn] = entropy->dc_derived_tbls[compptr->dc_tbl_no];
+ entropy->ac_cur_tbls[blkn] = entropy->ac_derived_tbls[compptr->ac_tbl_no];
+ /* Decide whether we really care about the coefficient values */
+ if (compptr->component_needed) {
+ ci = compptr->DCT_v_scaled_size;
+ if (ci <= 0 || ci > 8) ci = 8;
+ i = compptr->DCT_h_scaled_size;
+ if (i <= 0 || i > 8) i = 8;
+ entropy->coef_limit[blkn] = 1 + jpeg_zigzag_order[ci - 1][i - 1];
+ } else {
+ entropy->coef_limit[blkn] = 0;
+ }
+ }
+ }
+
+ /* Initialize bitread state variables */
+ entropy->bitstate.bits_left = 0;
+ entropy->bitstate.get_buffer = 0; /* unnecessary, but keeps Purify quiet */
+ entropy->pub.insufficient_data = FALSE;
+
+ /* Initialize restart counter */
+ entropy->restarts_to_go = cinfo->restart_interval;
+}
+
+
+/*
+ * Module initialization routine for Huffman entropy decoding.
+ */
+
+GLOBAL(void)
+jinit_huff_decoder (j_decompress_ptr cinfo)
+{
+ huff_entropy_ptr entropy;
+ int i;
+
+ entropy = (huff_entropy_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(huff_entropy_decoder));
+ cinfo->entropy = (struct jpeg_entropy_decoder *) entropy;
+ entropy->pub.start_pass = start_pass_huff_decoder;
+
+ if (cinfo->progressive_mode) {
+ /* Create progression status table */
+ int *coef_bit_ptr, ci;
+ cinfo->coef_bits = (int (*)[DCTSIZE2])
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components*DCTSIZE2*SIZEOF(int));
+ coef_bit_ptr = & cinfo->coef_bits[0][0];
+ for (ci = 0; ci < cinfo->num_components; ci++)
+ for (i = 0; i < DCTSIZE2; i++)
+ *coef_bit_ptr++ = -1;
+
+ /* Mark derived tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->derived_tbls[i] = NULL;
+ }
+ } else {
+ /* Mark tables unallocated */
+ for (i = 0; i < NUM_HUFF_TBLS; i++) {
+ entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL;
+ }
+ }
+}
diff --git a/Source/LibJPEG/jdinput.c b/Source/LibJPEG/jdinput.c
new file mode 100644
index 0000000..08a9b37
--- /dev/null
+++ b/Source/LibJPEG/jdinput.c
@@ -0,0 +1,384 @@
+/*
+ * jdinput.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2002-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains input control logic for the JPEG decompressor.
+ * These routines are concerned with controlling the decompressor's input
+ * processing (marker reading and coefficient decoding). The actual input
+ * reading is done in jdmarker.c, jdhuff.c, and jdarith.c.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_input_controller pub; /* public fields */
+
+ boolean inheaders; /* TRUE until first SOS is reached */
+} my_input_controller;
+
+typedef my_input_controller * my_inputctl_ptr;
+
+
+/* Forward declarations */
+METHODDEF(int) consume_markers JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Routines to calculate various quantities related to the size of the image.
+ */
+
+LOCAL(void)
+initial_setup (j_decompress_ptr cinfo)
+/* Called once, when first SOS marker is reached */
+{
+ int ci;
+ jpeg_component_info *compptr;
+
+ /* Make sure image isn't bigger than I can handle */
+ if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION ||
+ (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION)
+ ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION);
+
+ /* For now, precision must match compiled-in value... */
+ if (cinfo->data_precision != BITS_IN_JSAMPLE)
+ ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision);
+
+ /* Check that number of components won't exceed internal array sizes */
+ if (cinfo->num_components > MAX_COMPONENTS)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components,
+ MAX_COMPONENTS);
+
+ /* Compute maximum sampling factors; check factor validity */
+ cinfo->max_h_samp_factor = 1;
+ cinfo->max_v_samp_factor = 1;
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR ||
+ compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR)
+ ERREXIT(cinfo, JERR_BAD_SAMPLING);
+ cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor,
+ compptr->h_samp_factor);
+ cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor,
+ compptr->v_samp_factor);
+ }
+
+ /* We initialize DCT_scaled_size and min_DCT_scaled_size to DCTSIZE.
+ * In the full decompressor, this will be overridden by jdmaster.c;
+ * but in the transcoder, jdmaster.c is not used, so we must do it here.
+ */
+ cinfo->min_DCT_h_scaled_size = DCTSIZE;
+ cinfo->min_DCT_v_scaled_size = DCTSIZE;
+
+ /* Compute dimensions of components */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->DCT_h_scaled_size = DCTSIZE;
+ compptr->DCT_v_scaled_size = DCTSIZE;
+ /* Size in DCT blocks */
+ compptr->width_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->height_in_blocks = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ /* downsampled_width and downsampled_height will also be overridden by
+ * jdmaster.c if we are doing full decompression. The transcoder library
+ * doesn't use these values, but the calling application might.
+ */
+ /* Size in samples */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor,
+ (long) cinfo->max_h_samp_factor);
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor,
+ (long) cinfo->max_v_samp_factor);
+ /* Mark component needed, until color conversion says otherwise */
+ compptr->component_needed = TRUE;
+ /* Mark no quantization table yet saved for component */
+ compptr->quant_table = NULL;
+ }
+
+ /* Compute number of fully interleaved MCU rows. */
+ cinfo->total_iMCU_rows = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ /* Decide whether file contains multiple scans */
+ if (cinfo->comps_in_scan < cinfo->num_components || cinfo->progressive_mode)
+ cinfo->inputctl->has_multiple_scans = TRUE;
+ else
+ cinfo->inputctl->has_multiple_scans = FALSE;
+}
+
+
+LOCAL(void)
+per_scan_setup (j_decompress_ptr cinfo)
+/* Do computations that are needed before processing a JPEG scan */
+/* cinfo->comps_in_scan and cinfo->cur_comp_info[] were set from SOS marker */
+{
+ int ci, mcublks, tmp;
+ jpeg_component_info *compptr;
+
+ if (cinfo->comps_in_scan == 1) {
+
+ /* Noninterleaved (single-component) scan */
+ compptr = cinfo->cur_comp_info[0];
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = compptr->width_in_blocks;
+ cinfo->MCU_rows_in_scan = compptr->height_in_blocks;
+
+ /* For noninterleaved scan, always one block per MCU */
+ compptr->MCU_width = 1;
+ compptr->MCU_height = 1;
+ compptr->MCU_blocks = 1;
+ compptr->MCU_sample_width = compptr->DCT_h_scaled_size;
+ compptr->last_col_width = 1;
+ /* For noninterleaved scans, it is convenient to define last_row_height
+ * as the number of block rows present in the last iMCU row.
+ */
+ tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor);
+ if (tmp == 0) tmp = compptr->v_samp_factor;
+ compptr->last_row_height = tmp;
+
+ /* Prepare array describing MCU composition */
+ cinfo->blocks_in_MCU = 1;
+ cinfo->MCU_membership[0] = 0;
+
+ } else {
+
+ /* Interleaved (multi-component) scan */
+ if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN)
+ ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan,
+ MAX_COMPS_IN_SCAN);
+
+ /* Overall image size in MCUs */
+ cinfo->MCUs_per_row = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width,
+ (long) (cinfo->max_h_samp_factor*DCTSIZE));
+ cinfo->MCU_rows_in_scan = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height,
+ (long) (cinfo->max_v_samp_factor*DCTSIZE));
+
+ cinfo->blocks_in_MCU = 0;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* Sampling factors give # of blocks of component in each MCU */
+ compptr->MCU_width = compptr->h_samp_factor;
+ compptr->MCU_height = compptr->v_samp_factor;
+ compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height;
+ compptr->MCU_sample_width = compptr->MCU_width * compptr->DCT_h_scaled_size;
+ /* Figure number of non-dummy blocks in last MCU column & row */
+ tmp = (int) (compptr->width_in_blocks % compptr->MCU_width);
+ if (tmp == 0) tmp = compptr->MCU_width;
+ compptr->last_col_width = tmp;
+ tmp = (int) (compptr->height_in_blocks % compptr->MCU_height);
+ if (tmp == 0) tmp = compptr->MCU_height;
+ compptr->last_row_height = tmp;
+ /* Prepare array describing MCU composition */
+ mcublks = compptr->MCU_blocks;
+ if (cinfo->blocks_in_MCU + mcublks > D_MAX_BLOCKS_IN_MCU)
+ ERREXIT(cinfo, JERR_BAD_MCU_SIZE);
+ while (mcublks-- > 0) {
+ cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci;
+ }
+ }
+
+ }
+}
+
+
+/*
+ * Save away a copy of the Q-table referenced by each component present
+ * in the current scan, unless already saved during a prior scan.
+ *
+ * In a multiple-scan JPEG file, the encoder could assign different components
+ * the same Q-table slot number, but change table definitions between scans
+ * so that each component uses a different Q-table. (The IJG encoder is not
+ * currently capable of doing this, but other encoders might.) Since we want
+ * to be able to dequantize all the components at the end of the file, this
+ * means that we have to save away the table actually used for each component.
+ * We do this by copying the table at the start of the first scan containing
+ * the component.
+ * The JPEG spec prohibits the encoder from changing the contents of a Q-table
+ * slot between scans of a component using that slot. If the encoder does so
+ * anyway, this decoder will simply use the Q-table values that were current
+ * at the start of the first scan for the component.
+ *
+ * The decompressor output side looks only at the saved quant tables,
+ * not at the current Q-table slots.
+ */
+
+LOCAL(void)
+latch_quant_tables (j_decompress_ptr cinfo)
+{
+ int ci, qtblno;
+ jpeg_component_info *compptr;
+ JQUANT_TBL * qtbl;
+
+ for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+ compptr = cinfo->cur_comp_info[ci];
+ /* No work if we already saved Q-table for this component */
+ if (compptr->quant_table != NULL)
+ continue;
+ /* Make sure specified quantization table is present */
+ qtblno = compptr->quant_tbl_no;
+ if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
+ cinfo->quant_tbl_ptrs[qtblno] == NULL)
+ ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
+ /* OK, save away the quantization table */
+ qtbl = (JQUANT_TBL *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(JQUANT_TBL));
+ MEMCOPY(qtbl, cinfo->quant_tbl_ptrs[qtblno], SIZEOF(JQUANT_TBL));
+ compptr->quant_table = qtbl;
+ }
+}
+
+
+/*
+ * Initialize the input modules to read a scan of compressed data.
+ * The first call to this is done by jdmaster.c after initializing
+ * the entire decompressor (during jpeg_start_decompress).
+ * Subsequent calls come from consume_markers, below.
+ */
+
+METHODDEF(void)
+start_input_pass (j_decompress_ptr cinfo)
+{
+ per_scan_setup(cinfo);
+ latch_quant_tables(cinfo);
+ (*cinfo->entropy->start_pass) (cinfo);
+ (*cinfo->coef->start_input_pass) (cinfo);
+ cinfo->inputctl->consume_input = cinfo->coef->consume_data;
+}
+
+
+/*
+ * Finish up after inputting a compressed-data scan.
+ * This is called by the coefficient controller after it's read all
+ * the expected data of the scan.
+ */
+
+METHODDEF(void)
+finish_input_pass (j_decompress_ptr cinfo)
+{
+ cinfo->inputctl->consume_input = consume_markers;
+}
+
+
+/*
+ * Read JPEG markers before, between, or after compressed-data scans.
+ * Change state as necessary when a new scan is reached.
+ * Return value is JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ *
+ * The consume_input method pointer points either here or to the
+ * coefficient controller's consume_data routine, depending on whether
+ * we are reading a compressed data segment or inter-segment markers.
+ */
+
+METHODDEF(int)
+consume_markers (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+ int val;
+
+ if (inputctl->pub.eoi_reached) /* After hitting EOI, read no further */
+ return JPEG_REACHED_EOI;
+
+ val = (*cinfo->marker->read_markers) (cinfo);
+
+ switch (val) {
+ case JPEG_REACHED_SOS: /* Found SOS */
+ if (inputctl->inheaders) { /* 1st SOS */
+ initial_setup(cinfo);
+ inputctl->inheaders = FALSE;
+ /* Note: start_input_pass must be called by jdmaster.c
+ * before any more input can be consumed. jdapimin.c is
+ * responsible for enforcing this sequencing.
+ */
+ } else { /* 2nd or later SOS marker */
+ if (! inputctl->pub.has_multiple_scans)
+ ERREXIT(cinfo, JERR_EOI_EXPECTED); /* Oops, I wasn't expecting this! */
+ start_input_pass(cinfo);
+ }
+ break;
+ case JPEG_REACHED_EOI: /* Found EOI */
+ inputctl->pub.eoi_reached = TRUE;
+ if (inputctl->inheaders) { /* Tables-only datastream, apparently */
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_NO_SOS);
+ } else {
+ /* Prevent infinite loop in coef ctlr's decompress_data routine
+ * if user set output_scan_number larger than number of scans.
+ */
+ if (cinfo->output_scan_number > cinfo->input_scan_number)
+ cinfo->output_scan_number = cinfo->input_scan_number;
+ }
+ break;
+ case JPEG_SUSPENDED:
+ break;
+ }
+
+ return val;
+}
+
+
+/*
+ * Reset state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl = (my_inputctl_ptr) cinfo->inputctl;
+
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+ /* Reset other modules */
+ (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo);
+ (*cinfo->marker->reset_marker_reader) (cinfo);
+ /* Reset progression state -- would be cleaner if entropy decoder did this */
+ cinfo->coef_bits = NULL;
+}
+
+
+/*
+ * Initialize the input controller module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_input_controller (j_decompress_ptr cinfo)
+{
+ my_inputctl_ptr inputctl;
+
+ /* Create subobject in permanent pool */
+ inputctl = (my_inputctl_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_input_controller));
+ cinfo->inputctl = (struct jpeg_input_controller *) inputctl;
+ /* Initialize method pointers */
+ inputctl->pub.consume_input = consume_markers;
+ inputctl->pub.reset_input_controller = reset_input_controller;
+ inputctl->pub.start_input_pass = start_input_pass;
+ inputctl->pub.finish_input_pass = finish_input_pass;
+ /* Initialize state: can't use reset_input_controller since we don't
+ * want to try to reset other modules yet.
+ */
+ inputctl->pub.has_multiple_scans = FALSE; /* "unknown" would be better */
+ inputctl->pub.eoi_reached = FALSE;
+ inputctl->inheaders = TRUE;
+}
diff --git a/Source/LibJPEG/jdmainct.c b/Source/LibJPEG/jdmainct.c
new file mode 100644
index 0000000..02723ca
--- /dev/null
+++ b/Source/LibJPEG/jdmainct.c
@@ -0,0 +1,512 @@
+/*
+ * jdmainct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the main buffer controller for decompression.
+ * The main buffer lies between the JPEG decompressor proper and the
+ * post-processor; it holds downsampled data in the JPEG colorspace.
+ *
+ * Note that this code is bypassed in raw-data mode, since the application
+ * supplies the equivalent of the main buffer in that case.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * In the current system design, the main buffer need never be a full-image
+ * buffer; any full-height buffers will be found inside the coefficient or
+ * postprocessing controllers. Nonetheless, the main controller is not
+ * trivial. Its responsibility is to provide context rows for upsampling/
+ * rescaling, and doing this in an efficient fashion is a bit tricky.
+ *
+ * Postprocessor input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * DCT_scaled_size / min_DCT_scaled_size)
+ * sample rows of each component. (We require DCT_scaled_size values to be
+ * chosen such that these numbers are integers. In practice DCT_scaled_size
+ * values will likely be powers of two, so we actually have the stronger
+ * condition that DCT_scaled_size / min_DCT_scaled_size is an integer.)
+ * Upsampling will typically produce max_v_samp_factor pixel rows from each
+ * row group (times any additional scale factor that the upsampler is
+ * applying).
+ *
+ * The coefficient controller will deliver data to us one iMCU row at a time;
+ * each iMCU row contains v_samp_factor * DCT_scaled_size sample rows, or
+ * exactly min_DCT_scaled_size row groups. (This amount of data corresponds
+ * to one row of MCUs when the image is fully interleaved.) Note that the
+ * number of sample rows varies across components, but the number of row
+ * groups does not. Some garbage sample rows may be included in the last iMCU
+ * row at the bottom of the image.
+ *
+ * Depending on the vertical scaling algorithm used, the upsampler may need
+ * access to the sample row(s) above and below its current input row group.
+ * The upsampler is required to set need_context_rows TRUE at global selection
+ * time if so. When need_context_rows is FALSE, this controller can simply
+ * obtain one iMCU row at a time from the coefficient controller and dole it
+ * out as row groups to the postprocessor.
+ *
+ * When need_context_rows is TRUE, this controller guarantees that the buffer
+ * passed to postprocessing contains at least one row group's worth of samples
+ * above and below the row group(s) being processed. Note that the context
+ * rows "above" the first passed row group appear at negative row offsets in
+ * the passed buffer. At the top and bottom of the image, the required
+ * context rows are manufactured by duplicating the first or last real sample
+ * row; this avoids having special cases in the upsampling inner loops.
+ *
+ * The amount of context is fixed at one row group just because that's a
+ * convenient number for this controller to work with. The existing
+ * upsamplers really only need one sample row of context. An upsampler
+ * supporting arbitrary output rescaling might wish for more than one row
+ * group of context when shrinking the image; tough, we don't handle that.
+ * (This is justified by the assumption that downsizing will be handled mostly
+ * by adjusting the DCT_scaled_size values, so that the actual scale factor at
+ * the upsample step needn't be much less than one.)
+ *
+ * To provide the desired context, we have to retain the last two row groups
+ * of one iMCU row while reading in the next iMCU row. (The last row group
+ * can't be processed until we have another row group for its below-context,
+ * and so we have to save the next-to-last group too for its above-context.)
+ * We could do this most simply by copying data around in our buffer, but
+ * that'd be very slow. We can avoid copying any data by creating a rather
+ * strange pointer structure. Here's how it works. We allocate a workspace
+ * consisting of M+2 row groups (where M = min_DCT_scaled_size is the number
+ * of row groups per iMCU row). We create two sets of redundant pointers to
+ * the workspace. Labeling the physical row groups 0 to M+1, the synthesized
+ * pointer lists look like this:
+ * M+1 M-1
+ * master pointer --> 0 master pointer --> 0
+ * 1 1
+ * ... ...
+ * M-3 M-3
+ * M-2 M
+ * M-1 M+1
+ * M M-2
+ * M+1 M-1
+ * 0 0
+ * We read alternate iMCU rows using each master pointer; thus the last two
+ * row groups of the previous iMCU row remain un-overwritten in the workspace.
+ * The pointer lists are set up so that the required context rows appear to
+ * be adjacent to the proper places when we pass the pointer lists to the
+ * upsampler.
+ *
+ * The above pictures describe the normal state of the pointer lists.
+ * At top and bottom of the image, we diddle the pointer lists to duplicate
+ * the first or last sample row as necessary (this is cheaper than copying
+ * sample rows around).
+ *
+ * This scheme breaks down if M < 2, ie, min_DCT_scaled_size is 1. In that
+ * situation each iMCU row provides only one row group so the buffering logic
+ * must be different (eg, we must read two iMCU rows before we can emit the
+ * first row group). For now, we simply do not support providing context
+ * rows when min_DCT_scaled_size is 1. That combination seems unlikely to
+ * be worth providing --- if someone wants a 1/8th-size preview, they probably
+ * want it quick and dirty, so a context-free upsampler is sufficient.
+ */
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_main_controller pub; /* public fields */
+
+ /* Pointer to allocated workspace (M or M+2 row groups). */
+ JSAMPARRAY buffer[MAX_COMPONENTS];
+
+ boolean buffer_full; /* Have we gotten an iMCU row from decoder? */
+ JDIMENSION rowgroup_ctr; /* counts row groups output to postprocessor */
+
+ /* Remaining fields are only used in the context case. */
+
+ /* These are the master pointers to the funny-order pointer lists. */
+ JSAMPIMAGE xbuffer[2]; /* pointers to weird pointer lists */
+
+ int whichptr; /* indicates which pointer set is now in use */
+ int context_state; /* process_data state machine status */
+ JDIMENSION rowgroups_avail; /* row groups available to postprocessor */
+ JDIMENSION iMCU_row_ctr; /* counts iMCU rows to detect image top/bot */
+} my_main_controller;
+
+typedef my_main_controller * my_main_ptr;
+
+/* context_state values: */
+#define CTX_PREPARE_FOR_IMCU 0 /* need to prepare for MCU row */
+#define CTX_PROCESS_IMCU 1 /* feeding iMCU to postprocessor */
+#define CTX_POSTPONED_ROW 2 /* feeding postponed row group */
+
+
+/* Forward declarations */
+METHODDEF(void) process_data_simple_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+METHODDEF(void) process_data_context_main
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) process_data_crank_post
+ JPP((j_decompress_ptr cinfo, JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr, JDIMENSION out_rows_avail));
+#endif
+
+
+LOCAL(void)
+alloc_funny_pointers (j_decompress_ptr cinfo)
+/* Allocate space for the funny pointer lists.
+ * This is done only once, not once per pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, rgroup;
+ int M = cinfo->min_DCT_v_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ /* Get top-level space for component array pointers.
+ * We alloc both arrays with one call to save a few cycles.
+ */
+ main->xbuffer[0] = (JSAMPIMAGE)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * 2 * SIZEOF(JSAMPARRAY));
+ main->xbuffer[1] = main->xbuffer[0] + cinfo->num_components;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size; /* height of a row group of component */
+ /* Get space for pointer lists --- M+4 row groups in each list.
+ * We alloc both pointer lists with one call to save a few cycles.
+ */
+ xbuf = (JSAMPARRAY)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ 2 * (rgroup * (M + 4)) * SIZEOF(JSAMPROW));
+ xbuf += rgroup; /* want one row group at negative offsets */
+ main->xbuffer[0][ci] = xbuf;
+ xbuf += rgroup * (M + 4);
+ main->xbuffer[1][ci] = xbuf;
+ }
+}
+
+
+LOCAL(void)
+make_funny_pointers (j_decompress_ptr cinfo)
+/* Create the funny pointer lists discussed in the comments above.
+ * The actual workspace is already allocated (in main->buffer),
+ * and the space for the pointer lists is allocated too.
+ * This routine just fills in the curiously ordered lists.
+ * This will be repeated at the beginning of each pass.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_DCT_v_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY buf, xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ /* First copy the workspace pointers as-is */
+ buf = main->buffer[ci];
+ for (i = 0; i < rgroup * (M + 2); i++) {
+ xbuf0[i] = xbuf1[i] = buf[i];
+ }
+ /* In the second list, put the last four row groups in swapped order */
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf1[rgroup*(M-2) + i] = buf[rgroup*M + i];
+ xbuf1[rgroup*M + i] = buf[rgroup*(M-2) + i];
+ }
+ /* The wraparound pointers at top and bottom will be filled later
+ * (see set_wraparound_pointers, below). Initially we want the "above"
+ * pointers to duplicate the first actual data line. This only needs
+ * to happen in xbuffer[0].
+ */
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[0];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_wraparound_pointers (j_decompress_ptr cinfo)
+/* Set up the "wraparound" pointers at top and bottom of the pointer lists.
+ * This changes the pointer list state from top-of-image to the normal state.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup;
+ int M = cinfo->min_DCT_v_scaled_size;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf0, xbuf1;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size; /* height of a row group of component */
+ xbuf0 = main->xbuffer[0][ci];
+ xbuf1 = main->xbuffer[1][ci];
+ for (i = 0; i < rgroup; i++) {
+ xbuf0[i - rgroup] = xbuf0[rgroup*(M+1) + i];
+ xbuf1[i - rgroup] = xbuf1[rgroup*(M+1) + i];
+ xbuf0[rgroup*(M+2) + i] = xbuf0[i];
+ xbuf1[rgroup*(M+2) + i] = xbuf1[i];
+ }
+ }
+}
+
+
+LOCAL(void)
+set_bottom_pointers (j_decompress_ptr cinfo)
+/* Change the pointer lists to duplicate the last sample row at the bottom
+ * of the image. whichptr indicates which xbuffer holds the final iMCU row.
+ * Also sets rowgroups_avail to indicate number of nondummy row groups in row.
+ */
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ int ci, i, rgroup, iMCUheight, rows_left;
+ jpeg_component_info *compptr;
+ JSAMPARRAY xbuf;
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Count sample rows in one iMCU row and in one row group */
+ iMCUheight = compptr->v_samp_factor * compptr->DCT_v_scaled_size;
+ rgroup = iMCUheight / cinfo->min_DCT_v_scaled_size;
+ /* Count nondummy sample rows remaining for this component */
+ rows_left = (int) (compptr->downsampled_height % (JDIMENSION) iMCUheight);
+ if (rows_left == 0) rows_left = iMCUheight;
+ /* Count nondummy row groups. Should get same answer for each component,
+ * so we need only do it once.
+ */
+ if (ci == 0) {
+ main->rowgroups_avail = (JDIMENSION) ((rows_left-1) / rgroup + 1);
+ }
+ /* Duplicate the last real sample row rgroup*2 times; this pads out the
+ * last partial rowgroup and ensures at least one full rowgroup of context.
+ */
+ xbuf = main->xbuffer[main->whichptr][ci];
+ for (i = 0; i < rgroup * 2; i++) {
+ xbuf[rows_left + i] = xbuf[rows_left-1];
+ }
+ }
+}
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_main (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->upsample->need_context_rows) {
+ main->pub.process_data = process_data_context_main;
+ make_funny_pointers(cinfo); /* Create the xbuffer[] lists */
+ main->whichptr = 0; /* Read first iMCU row into xbuffer[0] */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ main->iMCU_row_ctr = 0;
+ } else {
+ /* Simple case with no context needed */
+ main->pub.process_data = process_data_simple_main;
+ }
+ main->buffer_full = FALSE; /* Mark buffer empty */
+ main->rowgroup_ctr = 0;
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_CRANK_DEST:
+ /* For last pass of 2-pass quantization, just crank the postprocessor */
+ main->pub.process_data = process_data_crank_post;
+ break;
+#endif
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the simple case where no context is required.
+ */
+
+METHODDEF(void)
+process_data_simple_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+ JDIMENSION rowgroups_avail;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->coef->decompress_data) (cinfo, main->buffer))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ }
+
+ /* There are always min_DCT_scaled_size row groups in an iMCU row. */
+ rowgroups_avail = (JDIMENSION) cinfo->min_DCT_v_scaled_size;
+ /* Note: at the bottom of the image, we may pass extra garbage row groups
+ * to the postprocessor. The postprocessor has to check for bottom
+ * of image anyway (at row resolution), so no point in us doing it too.
+ */
+
+ /* Feed the postprocessor */
+ (*cinfo->post->post_process_data) (cinfo, main->buffer,
+ &main->rowgroup_ctr, rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+
+ /* Has postprocessor consumed all the data yet? If so, mark buffer empty */
+ if (main->rowgroup_ctr >= rowgroups_avail) {
+ main->buffer_full = FALSE;
+ main->rowgroup_ctr = 0;
+ }
+}
+
+
+/*
+ * Process some data.
+ * This handles the case where context rows must be provided.
+ */
+
+METHODDEF(void)
+process_data_context_main (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_main_ptr main = (my_main_ptr) cinfo->main;
+
+ /* Read input data if we haven't filled the main buffer yet */
+ if (! main->buffer_full) {
+ if (! (*cinfo->coef->decompress_data) (cinfo,
+ main->xbuffer[main->whichptr]))
+ return; /* suspension forced, can do nothing more */
+ main->buffer_full = TRUE; /* OK, we have an iMCU row to work with */
+ main->iMCU_row_ctr++; /* count rows received */
+ }
+
+ /* Postprocessor typically will not swallow all the input data it is handed
+ * in one call (due to filling the output buffer first). Must be prepared
+ * to exit and restart. This switch lets us keep track of how far we got.
+ * Note that each case falls through to the next on successful completion.
+ */
+ switch (main->context_state) {
+ case CTX_POSTPONED_ROW:
+ /* Call postprocessor using previously set pointers for postponed row */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ main->context_state = CTX_PREPARE_FOR_IMCU;
+ if (*out_row_ctr >= out_rows_avail)
+ return; /* Postprocessor exactly filled output buf */
+ /*FALLTHROUGH*/
+ case CTX_PREPARE_FOR_IMCU:
+ /* Prepare to process first M-1 row groups of this iMCU row */
+ main->rowgroup_ctr = 0;
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size - 1);
+ /* Check for bottom of image: if so, tweak pointers to "duplicate"
+ * the last sample row, and adjust rowgroups_avail to ignore padding rows.
+ */
+ if (main->iMCU_row_ctr == cinfo->total_iMCU_rows)
+ set_bottom_pointers(cinfo);
+ main->context_state = CTX_PROCESS_IMCU;
+ /*FALLTHROUGH*/
+ case CTX_PROCESS_IMCU:
+ /* Call postprocessor using previously set pointers */
+ (*cinfo->post->post_process_data) (cinfo, main->xbuffer[main->whichptr],
+ &main->rowgroup_ctr, main->rowgroups_avail,
+ output_buf, out_row_ctr, out_rows_avail);
+ if (main->rowgroup_ctr < main->rowgroups_avail)
+ return; /* Need to suspend */
+ /* After the first iMCU, change wraparound pointers to normal state */
+ if (main->iMCU_row_ctr == 1)
+ set_wraparound_pointers(cinfo);
+ /* Prepare to load new iMCU row using other xbuffer list */
+ main->whichptr ^= 1; /* 0=>1 or 1=>0 */
+ main->buffer_full = FALSE;
+ /* Still need to process last row group of this iMCU row, */
+ /* which is saved at index M+1 of the other xbuffer */
+ main->rowgroup_ctr = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 1);
+ main->rowgroups_avail = (JDIMENSION) (cinfo->min_DCT_v_scaled_size + 2);
+ main->context_state = CTX_POSTPONED_ROW;
+ }
+}
+
+
+/*
+ * Process some data.
+ * Final pass of two-pass quantization: just call the postprocessor.
+ * Source data will be the postprocessor controller's internal buffer.
+ */
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+METHODDEF(void)
+process_data_crank_post (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ (*cinfo->post->post_process_data) (cinfo, (JSAMPIMAGE) NULL,
+ (JDIMENSION *) NULL, (JDIMENSION) 0,
+ output_buf, out_row_ctr, out_rows_avail);
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize main buffer controller.
+ */
+
+GLOBAL(void)
+jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_main_ptr main;
+ int ci, rgroup, ngroups;
+ jpeg_component_info *compptr;
+
+ main = (my_main_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_main_controller));
+ cinfo->main = (struct jpeg_d_main_controller *) main;
+ main->pub.start_pass = start_pass_main;
+
+ if (need_full_buffer) /* shouldn't happen */
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+
+ /* Allocate the workspace.
+ * ngroups is the number of row groups we need.
+ */
+ if (cinfo->upsample->need_context_rows) {
+ if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
+ ngroups = cinfo->min_DCT_v_scaled_size + 2;
+ } else {
+ ngroups = cinfo->min_DCT_v_scaled_size;
+ }
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size; /* height of a row group of component */
+ main->buffer[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ compptr->width_in_blocks * compptr->DCT_h_scaled_size,
+ (JDIMENSION) (rgroup * ngroups));
+ }
+}
diff --git a/Source/LibJPEG/jdmarker.c b/Source/LibJPEG/jdmarker.c
new file mode 100644
index 0000000..f4cca8c
--- /dev/null
+++ b/Source/LibJPEG/jdmarker.c
@@ -0,0 +1,1360 @@
+/*
+ * jdmarker.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to decode JPEG datastream markers.
+ * Most of the complexity arises from our desire to support input
+ * suspension: if not all of the data for a marker is available,
+ * we must exit back to the application. On resumption, we reprocess
+ * the marker.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+typedef enum { /* JPEG marker codes */
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_DHT = 0xc4,
+
+ M_DAC = 0xcc,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_TEM = 0x01,
+
+ M_ERROR = 0x100
+} JPEG_MARKER;
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_marker_reader pub; /* public fields */
+
+ /* Application-overridable marker processing methods */
+ jpeg_marker_parser_method process_COM;
+ jpeg_marker_parser_method process_APPn[16];
+
+ /* Limit on marker data length to save for each marker type */
+ unsigned int length_limit_COM;
+ unsigned int length_limit_APPn[16];
+
+ /* Status of COM/APPn marker saving */
+ jpeg_saved_marker_ptr cur_marker; /* NULL if not processing a marker */
+ unsigned int bytes_read; /* data bytes read so far in marker */
+ /* Note: cur_marker is not linked into marker_list until it's all read. */
+} my_marker_reader;
+
+typedef my_marker_reader * my_marker_ptr;
+
+
+/*
+ * Macros for fetching data from the data source module.
+ *
+ * At all times, cinfo->src->next_input_byte and ->bytes_in_buffer reflect
+ * the current restart point; we update them only when we have reached a
+ * suitable place to restart if a suspension occurs.
+ */
+
+/* Declare and initialize local copies of input pointer/count */
+#define INPUT_VARS(cinfo) \
+ struct jpeg_source_mgr * datasrc = (cinfo)->src; \
+ const JOCTET * next_input_byte = datasrc->next_input_byte; \
+ size_t bytes_in_buffer = datasrc->bytes_in_buffer
+
+/* Unload the local copies --- do this only at a restart boundary */
+#define INPUT_SYNC(cinfo) \
+ ( datasrc->next_input_byte = next_input_byte, \
+ datasrc->bytes_in_buffer = bytes_in_buffer )
+
+/* Reload the local copies --- used only in MAKE_BYTE_AVAIL */
+#define INPUT_RELOAD(cinfo) \
+ ( next_input_byte = datasrc->next_input_byte, \
+ bytes_in_buffer = datasrc->bytes_in_buffer )
+
+/* Internal macro for INPUT_BYTE and INPUT_2BYTES: make a byte available.
+ * Note we do *not* do INPUT_SYNC before calling fill_input_buffer,
+ * but we must reload the local copies after a successful fill.
+ */
+#define MAKE_BYTE_AVAIL(cinfo,action) \
+ if (bytes_in_buffer == 0) { \
+ if (! (*datasrc->fill_input_buffer) (cinfo)) \
+ { action; } \
+ INPUT_RELOAD(cinfo); \
+ }
+
+/* Read a byte into variable V.
+ * If must suspend, take the specified action (typically "return FALSE").
+ */
+#define INPUT_BYTE(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = GETJOCTET(*next_input_byte++); )
+
+/* As above, but read two bytes interpreted as an unsigned 16-bit integer.
+ * V should be declared unsigned int or perhaps INT32.
+ */
+#define INPUT_2BYTES(cinfo,V,action) \
+ MAKESTMT( MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \
+ MAKE_BYTE_AVAIL(cinfo,action); \
+ bytes_in_buffer--; \
+ V += GETJOCTET(*next_input_byte++); )
+
+
+/*
+ * Routines to process JPEG markers.
+ *
+ * Entry condition: JPEG marker itself has been read and its code saved
+ * in cinfo->unread_marker; input restart point is just after the marker.
+ *
+ * Exit: if return TRUE, have read and processed any parameters, and have
+ * updated the restart point to point after the parameters.
+ * If return FALSE, was forced to suspend before reaching end of
+ * marker parameters; restart point has not been moved. Same routine
+ * will be called again after application supplies more input data.
+ *
+ * This approach to suspension assumes that all of a marker's parameters
+ * can fit into a single input bufferload. This should hold for "normal"
+ * markers. Some COM/APPn markers might have large parameter segments
+ * that might not fit. If we are simply dropping such a marker, we use
+ * skip_input_data to get past it, and thereby put the problem on the
+ * source manager's shoulders. If we are saving the marker's contents
+ * into memory, we use a slightly different convention: when forced to
+ * suspend, the marker processor updates the restart point to the end of
+ * what it's consumed (ie, the end of the buffer) before returning FALSE.
+ * On resumption, cinfo->unread_marker still contains the marker code,
+ * but the data source will point to the next chunk of marker data.
+ * The marker processor must retain internal state to deal with this.
+ *
+ * Note that we don't bother to avoid duplicate trace messages if a
+ * suspension occurs within marker parameters. Other side effects
+ * require more care.
+ */
+
+
+LOCAL(boolean)
+get_soi (j_decompress_ptr cinfo)
+/* Process an SOI marker */
+{
+ int i;
+
+ TRACEMS(cinfo, 1, JTRC_SOI);
+
+ if (cinfo->marker->saw_SOI)
+ ERREXIT(cinfo, JERR_SOI_DUPLICATE);
+
+ /* Reset all parameters that are defined to be reset by SOI */
+
+ for (i = 0; i < NUM_ARITH_TBLS; i++) {
+ cinfo->arith_dc_L[i] = 0;
+ cinfo->arith_dc_U[i] = 1;
+ cinfo->arith_ac_K[i] = 5;
+ }
+ cinfo->restart_interval = 0;
+
+ /* Set initial assumptions for colorspace etc */
+
+ cinfo->jpeg_color_space = JCS_UNKNOWN;
+ cinfo->CCIR601_sampling = FALSE; /* Assume non-CCIR sampling??? */
+
+ cinfo->saw_JFIF_marker = FALSE;
+ cinfo->JFIF_major_version = 1; /* set default JFIF APP0 values */
+ cinfo->JFIF_minor_version = 1;
+ cinfo->density_unit = 0;
+ cinfo->X_density = 1;
+ cinfo->Y_density = 1;
+ cinfo->saw_Adobe_marker = FALSE;
+ cinfo->Adobe_transform = 0;
+
+ cinfo->marker->saw_SOI = TRUE;
+
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sof (j_decompress_ptr cinfo, boolean is_prog, boolean is_arith)
+/* Process a SOFn marker */
+{
+ INT32 length;
+ int c, ci;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ cinfo->progressive_mode = is_prog;
+ cinfo->arith_code = is_arith;
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, cinfo->data_precision, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_height, return FALSE);
+ INPUT_2BYTES(cinfo, cinfo->image_width, return FALSE);
+ INPUT_BYTE(cinfo, cinfo->num_components, return FALSE);
+
+ length -= 8;
+
+ TRACEMS4(cinfo, 1, JTRC_SOF, cinfo->unread_marker,
+ (int) cinfo->image_width, (int) cinfo->image_height,
+ cinfo->num_components);
+
+ if (cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOF_DUPLICATE);
+
+ /* We don't support files in which the image height is initially specified */
+ /* as 0 and is later redefined by DNL. As long as we have to check that, */
+ /* might as well have a general sanity check. */
+ if (cinfo->image_height <= 0 || cinfo->image_width <= 0
+ || cinfo->num_components <= 0)
+ ERREXIT(cinfo, JERR_EMPTY_IMAGE);
+
+ if (length != (cinfo->num_components * 3))
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ if (cinfo->comp_info == NULL) /* do only once, even if suspend */
+ cinfo->comp_info = (jpeg_component_info *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->num_components * SIZEOF(jpeg_component_info));
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ compptr->component_index = ci;
+ INPUT_BYTE(cinfo, compptr->component_id, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ compptr->h_samp_factor = (c >> 4) & 15;
+ compptr->v_samp_factor = (c ) & 15;
+ INPUT_BYTE(cinfo, compptr->quant_tbl_no, return FALSE);
+
+ TRACEMS4(cinfo, 1, JTRC_SOF_COMPONENT,
+ compptr->component_id, compptr->h_samp_factor,
+ compptr->v_samp_factor, compptr->quant_tbl_no);
+ }
+
+ cinfo->marker->saw_SOF = TRUE;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_sos (j_decompress_ptr cinfo)
+/* Process a SOS marker */
+{
+ INT32 length;
+ int i, ci, n, c, cc;
+ jpeg_component_info * compptr;
+ INPUT_VARS(cinfo);
+
+ if (! cinfo->marker->saw_SOF)
+ ERREXIT(cinfo, JERR_SOS_NO_SOF);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ INPUT_BYTE(cinfo, n, return FALSE); /* Number of components */
+
+ TRACEMS1(cinfo, 1, JTRC_SOS, n);
+
+ if (length != (n * 2 + 6) || n < 1 || n > MAX_COMPS_IN_SCAN)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ cinfo->comps_in_scan = n;
+
+ /* Collect the component-spec parameters */
+
+ for (i = 0; i < n; i++) {
+ INPUT_BYTE(cinfo, cc, return FALSE);
+ INPUT_BYTE(cinfo, c, return FALSE);
+
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ if (cc == compptr->component_id)
+ goto id_found;
+ }
+
+ ERREXIT1(cinfo, JERR_BAD_COMPONENT_ID, cc);
+
+ id_found:
+
+ cinfo->cur_comp_info[i] = compptr;
+ compptr->dc_tbl_no = (c >> 4) & 15;
+ compptr->ac_tbl_no = (c ) & 15;
+
+ TRACEMS3(cinfo, 1, JTRC_SOS_COMPONENT, cc,
+ compptr->dc_tbl_no, compptr->ac_tbl_no);
+ }
+
+ /* Collect the additional scan parameters Ss, Se, Ah/Al. */
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ss = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Se = c;
+ INPUT_BYTE(cinfo, c, return FALSE);
+ cinfo->Ah = (c >> 4) & 15;
+ cinfo->Al = (c ) & 15;
+
+ TRACEMS4(cinfo, 1, JTRC_SOS_PARAMS, cinfo->Ss, cinfo->Se,
+ cinfo->Ah, cinfo->Al);
+
+ /* Prepare to scan data & restart markers */
+ cinfo->marker->next_restart_num = 0;
+
+ /* Count another SOS marker */
+ cinfo->input_scan_number++;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+#ifdef D_ARITH_CODING_SUPPORTED
+
+LOCAL(boolean)
+get_dac (j_decompress_ptr cinfo)
+/* Process a DAC marker */
+{
+ INT32 length;
+ int index, val;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+ INPUT_BYTE(cinfo, val, return FALSE);
+
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_DAC, index, val);
+
+ if (index < 0 || index >= (2*NUM_ARITH_TBLS))
+ ERREXIT1(cinfo, JERR_DAC_INDEX, index);
+
+ if (index >= NUM_ARITH_TBLS) { /* define AC table */
+ cinfo->arith_ac_K[index-NUM_ARITH_TBLS] = (UINT8) val;
+ } else { /* define DC table */
+ cinfo->arith_dc_L[index] = (UINT8) (val & 0x0F);
+ cinfo->arith_dc_U[index] = (UINT8) (val >> 4);
+ if (cinfo->arith_dc_L[index] > cinfo->arith_dc_U[index])
+ ERREXIT1(cinfo, JERR_DAC_VALUE, val);
+ }
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+#else /* ! D_ARITH_CODING_SUPPORTED */
+
+#define get_dac(cinfo) skip_variable(cinfo)
+
+#endif /* D_ARITH_CODING_SUPPORTED */
+
+
+LOCAL(boolean)
+get_dht (j_decompress_ptr cinfo)
+/* Process a DHT marker */
+{
+ INT32 length;
+ UINT8 bits[17];
+ UINT8 huffval[256];
+ int i, index, count;
+ JHUFF_TBL **htblptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 16) {
+ INPUT_BYTE(cinfo, index, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DHT, index);
+
+ bits[0] = 0;
+ count = 0;
+ for (i = 1; i <= 16; i++) {
+ INPUT_BYTE(cinfo, bits[i], return FALSE);
+ count += bits[i];
+ }
+
+ length -= 1 + 16;
+
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[1], bits[2], bits[3], bits[4],
+ bits[5], bits[6], bits[7], bits[8]);
+ TRACEMS8(cinfo, 2, JTRC_HUFFBITS,
+ bits[9], bits[10], bits[11], bits[12],
+ bits[13], bits[14], bits[15], bits[16]);
+
+ /* Here we just do minimal validation of the counts to avoid walking
+ * off the end of our table space. jdhuff.c will check more carefully.
+ */
+ if (count > 256 || ((INT32) count) > length)
+ ERREXIT(cinfo, JERR_BAD_HUFF_TABLE);
+
+ for (i = 0; i < count; i++)
+ INPUT_BYTE(cinfo, huffval[i], return FALSE);
+
+ length -= count;
+
+ if (index & 0x10) { /* AC table definition */
+ index -= 0x10;
+ htblptr = &cinfo->ac_huff_tbl_ptrs[index];
+ } else { /* DC table definition */
+ htblptr = &cinfo->dc_huff_tbl_ptrs[index];
+ }
+
+ if (index < 0 || index >= NUM_HUFF_TBLS)
+ ERREXIT1(cinfo, JERR_DHT_INDEX, index);
+
+ if (*htblptr == NULL)
+ *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo);
+
+ MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits));
+ MEMCOPY((*htblptr)->huffval, huffval, SIZEOF((*htblptr)->huffval));
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dqt (j_decompress_ptr cinfo)
+/* Process a DQT marker */
+{
+ INT32 length;
+ int n, i, prec;
+ unsigned int tmp;
+ JQUANT_TBL *quant_ptr;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ while (length > 0) {
+ INPUT_BYTE(cinfo, n, return FALSE);
+ prec = n >> 4;
+ n &= 0x0F;
+
+ TRACEMS2(cinfo, 1, JTRC_DQT, n, prec);
+
+ if (n >= NUM_QUANT_TBLS)
+ ERREXIT1(cinfo, JERR_DQT_INDEX, n);
+
+ if (cinfo->quant_tbl_ptrs[n] == NULL)
+ cinfo->quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) cinfo);
+ quant_ptr = cinfo->quant_tbl_ptrs[n];
+
+ for (i = 0; i < DCTSIZE2; i++) {
+ if (prec)
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+ else
+ INPUT_BYTE(cinfo, tmp, return FALSE);
+ /* We convert the zigzag-order table to natural array order. */
+ quant_ptr->quantval[jpeg_natural_order[i]] = (UINT16) tmp;
+ }
+
+ if (cinfo->err->trace_level >= 2) {
+ for (i = 0; i < DCTSIZE2; i += 8) {
+ TRACEMS8(cinfo, 2, JTRC_QUANTVALS,
+ quant_ptr->quantval[i], quant_ptr->quantval[i+1],
+ quant_ptr->quantval[i+2], quant_ptr->quantval[i+3],
+ quant_ptr->quantval[i+4], quant_ptr->quantval[i+5],
+ quant_ptr->quantval[i+6], quant_ptr->quantval[i+7]);
+ }
+ }
+
+ length -= DCTSIZE2+1;
+ if (prec) length -= DCTSIZE2;
+ }
+
+ if (length != 0)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+get_dri (j_decompress_ptr cinfo)
+/* Process a DRI marker */
+{
+ INT32 length;
+ unsigned int tmp;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+
+ if (length != 4)
+ ERREXIT(cinfo, JERR_BAD_LENGTH);
+
+ INPUT_2BYTES(cinfo, tmp, return FALSE);
+
+ TRACEMS1(cinfo, 1, JTRC_DRI, tmp);
+
+ cinfo->restart_interval = tmp;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Routines for processing APPn and COM markers.
+ * These are either saved in memory or discarded, per application request.
+ * APP0 and APP14 are specially checked to see if they are
+ * JFIF and Adobe markers, respectively.
+ */
+
+#define APP0_DATA_LEN 14 /* Length of interesting data in APP0 */
+#define APP14_DATA_LEN 12 /* Length of interesting data in APP14 */
+#define APPN_DATA_LEN 14 /* Must be the largest of the above!! */
+
+
+LOCAL(void)
+examine_app0 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP0.
+ * Take appropriate action if it is a JFIF marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ INT32 totallen = (INT32) datalen + remaining;
+
+ if (datalen >= APP0_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x49 &&
+ GETJOCTET(data[3]) == 0x46 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF APP0 marker: save info */
+ cinfo->saw_JFIF_marker = TRUE;
+ cinfo->JFIF_major_version = GETJOCTET(data[5]);
+ cinfo->JFIF_minor_version = GETJOCTET(data[6]);
+ cinfo->density_unit = GETJOCTET(data[7]);
+ cinfo->X_density = (GETJOCTET(data[8]) << 8) + GETJOCTET(data[9]);
+ cinfo->Y_density = (GETJOCTET(data[10]) << 8) + GETJOCTET(data[11]);
+ /* Check version.
+ * Major version must be 1, anything else signals an incompatible change.
+ * (We used to treat this as an error, but now it's a nonfatal warning,
+ * because some bozo at Hijaak couldn't read the spec.)
+ * Minor version should be 0..2, but process anyway if newer.
+ */
+ if (cinfo->JFIF_major_version != 1)
+ WARNMS2(cinfo, JWRN_JFIF_MAJOR,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version);
+ /* Generate trace messages */
+ TRACEMS5(cinfo, 1, JTRC_JFIF,
+ cinfo->JFIF_major_version, cinfo->JFIF_minor_version,
+ cinfo->X_density, cinfo->Y_density, cinfo->density_unit);
+ /* Validate thumbnail dimensions and issue appropriate messages */
+ if (GETJOCTET(data[12]) | GETJOCTET(data[13]))
+ TRACEMS2(cinfo, 1, JTRC_JFIF_THUMBNAIL,
+ GETJOCTET(data[12]), GETJOCTET(data[13]));
+ totallen -= APP0_DATA_LEN;
+ if (totallen !=
+ ((INT32)GETJOCTET(data[12]) * (INT32)GETJOCTET(data[13]) * (INT32) 3))
+ TRACEMS1(cinfo, 1, JTRC_JFIF_BADTHUMBNAILSIZE, (int) totallen);
+ } else if (datalen >= 6 &&
+ GETJOCTET(data[0]) == 0x4A &&
+ GETJOCTET(data[1]) == 0x46 &&
+ GETJOCTET(data[2]) == 0x58 &&
+ GETJOCTET(data[3]) == 0x58 &&
+ GETJOCTET(data[4]) == 0) {
+ /* Found JFIF "JFXX" extension APP0 marker */
+ /* The library doesn't actually do anything with these,
+ * but we try to produce a helpful trace message.
+ */
+ switch (GETJOCTET(data[5])) {
+ case 0x10:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_JPEG, (int) totallen);
+ break;
+ case 0x11:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_PALETTE, (int) totallen);
+ break;
+ case 0x13:
+ TRACEMS1(cinfo, 1, JTRC_THUMB_RGB, (int) totallen);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_JFIF_EXTENSION,
+ GETJOCTET(data[5]), (int) totallen);
+ break;
+ }
+ } else {
+ /* Start of APP0 does not match "JFIF" or "JFXX", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP0, (int) totallen);
+ }
+}
+
+
+LOCAL(void)
+examine_app14 (j_decompress_ptr cinfo, JOCTET FAR * data,
+ unsigned int datalen, INT32 remaining)
+/* Examine first few bytes from an APP14.
+ * Take appropriate action if it is an Adobe marker.
+ * datalen is # of bytes at data[], remaining is length of rest of marker data.
+ */
+{
+ unsigned int version, flags0, flags1, transform;
+
+ if (datalen >= APP14_DATA_LEN &&
+ GETJOCTET(data[0]) == 0x41 &&
+ GETJOCTET(data[1]) == 0x64 &&
+ GETJOCTET(data[2]) == 0x6F &&
+ GETJOCTET(data[3]) == 0x62 &&
+ GETJOCTET(data[4]) == 0x65) {
+ /* Found Adobe APP14 marker */
+ version = (GETJOCTET(data[5]) << 8) + GETJOCTET(data[6]);
+ flags0 = (GETJOCTET(data[7]) << 8) + GETJOCTET(data[8]);
+ flags1 = (GETJOCTET(data[9]) << 8) + GETJOCTET(data[10]);
+ transform = GETJOCTET(data[11]);
+ TRACEMS4(cinfo, 1, JTRC_ADOBE, version, flags0, flags1, transform);
+ cinfo->saw_Adobe_marker = TRUE;
+ cinfo->Adobe_transform = (UINT8) transform;
+ } else {
+ /* Start of APP14 does not match "Adobe", or too short */
+ TRACEMS1(cinfo, 1, JTRC_APP14, (int) (datalen + remaining));
+ }
+}
+
+
+METHODDEF(boolean)
+get_interesting_appn (j_decompress_ptr cinfo)
+/* Process an APP0 or APP14 marker without saving it */
+{
+ INT32 length;
+ JOCTET b[APPN_DATA_LEN];
+ unsigned int i, numtoread;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ /* get the interesting part of the marker data */
+ if (length >= APPN_DATA_LEN)
+ numtoread = APPN_DATA_LEN;
+ else if (length > 0)
+ numtoread = (unsigned int) length;
+ else
+ numtoread = 0;
+ for (i = 0; i < numtoread; i++)
+ INPUT_BYTE(cinfo, b[i], return FALSE);
+ length -= numtoread;
+
+ /* process it */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, (JOCTET FAR *) b, numtoread, length);
+ break;
+ default:
+ /* can't get here unless jpeg_save_markers chooses wrong processor */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo);
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+METHODDEF(boolean)
+save_marker (j_decompress_ptr cinfo)
+/* Save an APPn or COM marker into the marker list */
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ jpeg_saved_marker_ptr cur_marker = marker->cur_marker;
+ unsigned int bytes_read, data_length;
+ JOCTET FAR * data;
+ INT32 length = 0;
+ INPUT_VARS(cinfo);
+
+ if (cur_marker == NULL) {
+ /* begin reading a marker */
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+ if (length >= 0) { /* watch out for bogus length word */
+ /* figure out how much we want to save */
+ unsigned int limit;
+ if (cinfo->unread_marker == (int) M_COM)
+ limit = marker->length_limit_COM;
+ else
+ limit = marker->length_limit_APPn[cinfo->unread_marker - (int) M_APP0];
+ if ((unsigned int) length < limit)
+ limit = (unsigned int) length;
+ /* allocate and initialize the marker item */
+ cur_marker = (jpeg_saved_marker_ptr)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(struct jpeg_marker_struct) + limit);
+ cur_marker->next = NULL;
+ cur_marker->marker = (UINT8) cinfo->unread_marker;
+ cur_marker->original_length = (unsigned int) length;
+ cur_marker->data_length = limit;
+ /* data area is just beyond the jpeg_marker_struct */
+ data = cur_marker->data = (JOCTET FAR *) (cur_marker + 1);
+ marker->cur_marker = cur_marker;
+ marker->bytes_read = 0;
+ bytes_read = 0;
+ data_length = limit;
+ } else {
+ /* deal with bogus length word */
+ bytes_read = data_length = 0;
+ data = NULL;
+ }
+ } else {
+ /* resume reading a marker */
+ bytes_read = marker->bytes_read;
+ data_length = cur_marker->data_length;
+ data = cur_marker->data + bytes_read;
+ }
+
+ while (bytes_read < data_length) {
+ INPUT_SYNC(cinfo); /* move the restart point to here */
+ marker->bytes_read = bytes_read;
+ /* If there's not at least one byte in buffer, suspend */
+ MAKE_BYTE_AVAIL(cinfo, return FALSE);
+ /* Copy bytes with reasonable rapidity */
+ while (bytes_read < data_length && bytes_in_buffer > 0) {
+ *data++ = *next_input_byte++;
+ bytes_in_buffer--;
+ bytes_read++;
+ }
+ }
+
+ /* Done reading what we want to read */
+ if (cur_marker != NULL) { /* will be NULL if bogus length word */
+ /* Add new marker to end of list */
+ if (cinfo->marker_list == NULL) {
+ cinfo->marker_list = cur_marker;
+ } else {
+ jpeg_saved_marker_ptr prev = cinfo->marker_list;
+ while (prev->next != NULL)
+ prev = prev->next;
+ prev->next = cur_marker;
+ }
+ /* Reset pointer & calc remaining data length */
+ data = cur_marker->data;
+ length = cur_marker->original_length - data_length;
+ }
+ /* Reset to initial state for next marker */
+ marker->cur_marker = NULL;
+
+ /* Process the marker if interesting; else just make a generic trace msg */
+ switch (cinfo->unread_marker) {
+ case M_APP0:
+ examine_app0(cinfo, data, data_length, length);
+ break;
+ case M_APP14:
+ examine_app14(cinfo, data, data_length, length);
+ break;
+ default:
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker,
+ (int) (data_length + length));
+ break;
+ }
+
+ /* skip any remaining data -- could be lots */
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+METHODDEF(boolean)
+skip_variable (j_decompress_ptr cinfo)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+ INT32 length;
+ INPUT_VARS(cinfo);
+
+ INPUT_2BYTES(cinfo, length, return FALSE);
+ length -= 2;
+
+ TRACEMS2(cinfo, 1, JTRC_MISC_MARKER, cinfo->unread_marker, (int) length);
+
+ INPUT_SYNC(cinfo); /* do before skip_input_data */
+ if (length > 0)
+ (*cinfo->src->skip_input_data) (cinfo, (long) length);
+
+ return TRUE;
+}
+
+
+/*
+ * Find the next JPEG marker, save it in cinfo->unread_marker.
+ * Returns FALSE if had to suspend before reaching a marker;
+ * in that case cinfo->unread_marker is unchanged.
+ *
+ * Note that the result might not be a valid marker code,
+ * but it will never be 0 or FF.
+ */
+
+LOCAL(boolean)
+next_marker (j_decompress_ptr cinfo)
+{
+ int c;
+ INPUT_VARS(cinfo);
+
+ for (;;) {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ /* Skip any non-FF bytes.
+ * This may look a bit inefficient, but it will not occur in a valid file.
+ * We sync after each discarded byte so that a suspending data source
+ * can discard the byte from its buffer.
+ */
+ while (c != 0xFF) {
+ cinfo->marker->discarded_bytes++;
+ INPUT_SYNC(cinfo);
+ INPUT_BYTE(cinfo, c, return FALSE);
+ }
+ /* This loop swallows any duplicate FF bytes. Extra FFs are legal as
+ * pad bytes, so don't count them in discarded_bytes. We assume there
+ * will not be so many consecutive FF bytes as to overflow a suspending
+ * data source's input buffer.
+ */
+ do {
+ INPUT_BYTE(cinfo, c, return FALSE);
+ } while (c == 0xFF);
+ if (c != 0)
+ break; /* found a valid marker, exit loop */
+ /* Reach here if we found a stuffed-zero data sequence (FF/00).
+ * Discard it and loop back to try again.
+ */
+ cinfo->marker->discarded_bytes += 2;
+ INPUT_SYNC(cinfo);
+ }
+
+ if (cinfo->marker->discarded_bytes != 0) {
+ WARNMS2(cinfo, JWRN_EXTRANEOUS_DATA, cinfo->marker->discarded_bytes, c);
+ cinfo->marker->discarded_bytes = 0;
+ }
+
+ cinfo->unread_marker = c;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+LOCAL(boolean)
+first_marker (j_decompress_ptr cinfo)
+/* Like next_marker, but used to obtain the initial SOI marker. */
+/* For this marker, we do not allow preceding garbage or fill; otherwise,
+ * we might well scan an entire input file before realizing it ain't JPEG.
+ * If an application wants to process non-JFIF files, it must seek to the
+ * SOI before calling the JPEG library.
+ */
+{
+ int c, c2;
+ INPUT_VARS(cinfo);
+
+ INPUT_BYTE(cinfo, c, return FALSE);
+ INPUT_BYTE(cinfo, c2, return FALSE);
+ if (c != 0xFF || c2 != (int) M_SOI)
+ ERREXIT2(cinfo, JERR_NO_SOI, c, c2);
+
+ cinfo->unread_marker = c2;
+
+ INPUT_SYNC(cinfo);
+ return TRUE;
+}
+
+
+/*
+ * Read markers until SOS or EOI.
+ *
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+
+METHODDEF(int)
+read_markers (j_decompress_ptr cinfo)
+{
+ /* Outer loop repeats once for each marker. */
+ for (;;) {
+ /* Collect the marker proper, unless we already did. */
+ /* NB: first_marker() enforces the requirement that SOI appear first. */
+ if (cinfo->unread_marker == 0) {
+ if (! cinfo->marker->saw_SOI) {
+ if (! first_marker(cinfo))
+ return JPEG_SUSPENDED;
+ } else {
+ if (! next_marker(cinfo))
+ return JPEG_SUSPENDED;
+ }
+ }
+ /* At this point cinfo->unread_marker contains the marker code and the
+ * input point is just past the marker proper, but before any parameters.
+ * A suspension will cause us to return with this state still true.
+ */
+ switch (cinfo->unread_marker) {
+ case M_SOI:
+ if (! get_soi(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF0: /* Baseline */
+ case M_SOF1: /* Extended sequential, Huffman */
+ if (! get_sof(cinfo, FALSE, FALSE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF2: /* Progressive, Huffman */
+ if (! get_sof(cinfo, TRUE, FALSE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF9: /* Extended sequential, arithmetic */
+ if (! get_sof(cinfo, FALSE, TRUE))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_SOF10: /* Progressive, arithmetic */
+ if (! get_sof(cinfo, TRUE, TRUE))
+ return JPEG_SUSPENDED;
+ break;
+
+ /* Currently unsupported SOFn types */
+ case M_SOF3: /* Lossless, Huffman */
+ case M_SOF5: /* Differential sequential, Huffman */
+ case M_SOF6: /* Differential progressive, Huffman */
+ case M_SOF7: /* Differential lossless, Huffman */
+ case M_JPG: /* Reserved for JPEG extensions */
+ case M_SOF11: /* Lossless, arithmetic */
+ case M_SOF13: /* Differential sequential, arithmetic */
+ case M_SOF14: /* Differential progressive, arithmetic */
+ case M_SOF15: /* Differential lossless, arithmetic */
+ ERREXIT1(cinfo, JERR_SOF_UNSUPPORTED, cinfo->unread_marker);
+ break;
+
+ case M_SOS:
+ if (! get_sos(cinfo))
+ return JPEG_SUSPENDED;
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_SOS;
+
+ case M_EOI:
+ TRACEMS(cinfo, 1, JTRC_EOI);
+ cinfo->unread_marker = 0; /* processed the marker */
+ return JPEG_REACHED_EOI;
+
+ case M_DAC:
+ if (! get_dac(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DHT:
+ if (! get_dht(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DQT:
+ if (! get_dqt(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_DRI:
+ if (! get_dri(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_APP0:
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP14:
+ case M_APP15:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_APPn[
+ cinfo->unread_marker - (int) M_APP0]) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_COM:
+ if (! (*((my_marker_ptr) cinfo->marker)->process_COM) (cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ case M_RST0: /* these are all parameterless */
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ TRACEMS1(cinfo, 1, JTRC_PARMLESS_MARKER, cinfo->unread_marker);
+ break;
+
+ case M_DNL: /* Ignore DNL ... perhaps the wrong thing */
+ if (! skip_variable(cinfo))
+ return JPEG_SUSPENDED;
+ break;
+
+ default: /* must be DHP, EXP, JPGn, or RESn */
+ /* For now, we treat the reserved markers as fatal errors since they are
+ * likely to be used to signal incompatible JPEG Part 3 extensions.
+ * Once the JPEG 3 version-number marker is well defined, this code
+ * ought to change!
+ */
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, cinfo->unread_marker);
+ break;
+ }
+ /* Successfully processed marker, so reset state variable */
+ cinfo->unread_marker = 0;
+ } /* end loop */
+}
+
+
+/*
+ * Read a restart marker, which is expected to appear next in the datastream;
+ * if the marker is not there, take appropriate recovery action.
+ * Returns FALSE if suspension is required.
+ *
+ * This is called by the entropy decoder after it has read an appropriate
+ * number of MCUs. cinfo->unread_marker may be nonzero if the entropy decoder
+ * has already read a marker from the data source. Under normal conditions
+ * cinfo->unread_marker will be reset to 0 before returning; if not reset,
+ * it holds a marker which the decoder will be unable to read past.
+ */
+
+METHODDEF(boolean)
+read_restart_marker (j_decompress_ptr cinfo)
+{
+ /* Obtain a marker unless we already did. */
+ /* Note that next_marker will complain if it skips any data. */
+ if (cinfo->unread_marker == 0) {
+ if (! next_marker(cinfo))
+ return FALSE;
+ }
+
+ if (cinfo->unread_marker ==
+ ((int) M_RST0 + cinfo->marker->next_restart_num)) {
+ /* Normal case --- swallow the marker and let entropy decoder continue */
+ TRACEMS1(cinfo, 3, JTRC_RST, cinfo->marker->next_restart_num);
+ cinfo->unread_marker = 0;
+ } else {
+ /* Uh-oh, the restart markers have been messed up. */
+ /* Let the data source manager determine how to resync. */
+ if (! (*cinfo->src->resync_to_restart) (cinfo,
+ cinfo->marker->next_restart_num))
+ return FALSE;
+ }
+
+ /* Update next-restart state */
+ cinfo->marker->next_restart_num = (cinfo->marker->next_restart_num + 1) & 7;
+
+ return TRUE;
+}
+
+
+/*
+ * This is the default resync_to_restart method for data source managers
+ * to use if they don't have any better approach. Some data source managers
+ * may be able to back up, or may have additional knowledge about the data
+ * which permits a more intelligent recovery strategy; such managers would
+ * presumably supply their own resync method.
+ *
+ * read_restart_marker calls resync_to_restart if it finds a marker other than
+ * the restart marker it was expecting. (This code is *not* used unless
+ * a nonzero restart interval has been declared.) cinfo->unread_marker is
+ * the marker code actually found (might be anything, except 0 or FF).
+ * The desired restart marker number (0..7) is passed as a parameter.
+ * This routine is supposed to apply whatever error recovery strategy seems
+ * appropriate in order to position the input stream to the next data segment.
+ * Note that cinfo->unread_marker is treated as a marker appearing before
+ * the current data-source input point; usually it should be reset to zero
+ * before returning.
+ * Returns FALSE if suspension is required.
+ *
+ * This implementation is substantially constrained by wanting to treat the
+ * input as a data stream; this means we can't back up. Therefore, we have
+ * only the following actions to work with:
+ * 1. Simply discard the marker and let the entropy decoder resume at next
+ * byte of file.
+ * 2. Read forward until we find another marker, discarding intervening
+ * data. (In theory we could look ahead within the current bufferload,
+ * without having to discard data if we don't find the desired marker.
+ * This idea is not implemented here, in part because it makes behavior
+ * dependent on buffer size and chance buffer-boundary positions.)
+ * 3. Leave the marker unread (by failing to zero cinfo->unread_marker).
+ * This will cause the entropy decoder to process an empty data segment,
+ * inserting dummy zeroes, and then we will reprocess the marker.
+ *
+ * #2 is appropriate if we think the desired marker lies ahead, while #3 is
+ * appropriate if the found marker is a future restart marker (indicating
+ * that we have missed the desired restart marker, probably because it got
+ * corrupted).
+ * We apply #2 or #3 if the found marker is a restart marker no more than
+ * two counts behind or ahead of the expected one. We also apply #2 if the
+ * found marker is not a legal JPEG marker code (it's certainly bogus data).
+ * If the found marker is a restart marker more than 2 counts away, we do #1
+ * (too much risk that the marker is erroneous; with luck we will be able to
+ * resync at some future point).
+ * For any valid non-restart JPEG marker, we apply #3. This keeps us from
+ * overrunning the end of a scan. An implementation limited to single-scan
+ * files might find it better to apply #2 for markers other than EOI, since
+ * any other marker would have to be bogus data in that case.
+ */
+
+GLOBAL(boolean)
+jpeg_resync_to_restart (j_decompress_ptr cinfo, int desired)
+{
+ int marker = cinfo->unread_marker;
+ int action = 1;
+
+ /* Always put up a warning. */
+ WARNMS2(cinfo, JWRN_MUST_RESYNC, marker, desired);
+
+ /* Outer loop handles repeated decision after scanning forward. */
+ for (;;) {
+ if (marker < (int) M_SOF0)
+ action = 2; /* invalid marker */
+ else if (marker < (int) M_RST0 || marker > (int) M_RST7)
+ action = 3; /* valid non-restart marker */
+ else {
+ if (marker == ((int) M_RST0 + ((desired+1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired+2) & 7)))
+ action = 3; /* one of the next two expected restarts */
+ else if (marker == ((int) M_RST0 + ((desired-1) & 7)) ||
+ marker == ((int) M_RST0 + ((desired-2) & 7)))
+ action = 2; /* a prior restart, so advance */
+ else
+ action = 1; /* desired restart or too far away */
+ }
+ TRACEMS2(cinfo, 4, JTRC_RECOVERY_ACTION, marker, action);
+ switch (action) {
+ case 1:
+ /* Discard marker and let entropy decoder resume processing. */
+ cinfo->unread_marker = 0;
+ return TRUE;
+ case 2:
+ /* Scan to the next marker, and repeat the decision loop. */
+ if (! next_marker(cinfo))
+ return FALSE;
+ marker = cinfo->unread_marker;
+ break;
+ case 3:
+ /* Return without advancing past this marker. */
+ /* Entropy decoder will be forced to process an empty segment. */
+ return TRUE;
+ }
+ } /* end loop */
+}
+
+
+/*
+ * Reset marker processing state to begin a fresh datastream.
+ */
+
+METHODDEF(void)
+reset_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ cinfo->comp_info = NULL; /* until allocated by get_sof */
+ cinfo->input_scan_number = 0; /* no SOS seen yet */
+ cinfo->unread_marker = 0; /* no pending marker */
+ marker->pub.saw_SOI = FALSE; /* set internal state too */
+ marker->pub.saw_SOF = FALSE;
+ marker->pub.discarded_bytes = 0;
+ marker->cur_marker = NULL;
+}
+
+
+/*
+ * Initialize the marker reader module.
+ * This is called only once, when the decompression object is created.
+ */
+
+GLOBAL(void)
+jinit_marker_reader (j_decompress_ptr cinfo)
+{
+ my_marker_ptr marker;
+ int i;
+
+ /* Create subobject in permanent pool */
+ marker = (my_marker_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ SIZEOF(my_marker_reader));
+ cinfo->marker = (struct jpeg_marker_reader *) marker;
+ /* Initialize public method pointers */
+ marker->pub.reset_marker_reader = reset_marker_reader;
+ marker->pub.read_markers = read_markers;
+ marker->pub.read_restart_marker = read_restart_marker;
+ /* Initialize COM/APPn processing.
+ * By default, we examine and then discard APP0 and APP14,
+ * but simply discard COM and all other APPn.
+ */
+ marker->process_COM = skip_variable;
+ marker->length_limit_COM = 0;
+ for (i = 0; i < 16; i++) {
+ marker->process_APPn[i] = skip_variable;
+ marker->length_limit_APPn[i] = 0;
+ }
+ marker->process_APPn[0] = get_interesting_appn;
+ marker->process_APPn[14] = get_interesting_appn;
+ /* Reset marker processing state */
+ reset_marker_reader(cinfo);
+}
+
+
+/*
+ * Control saving of COM and APPn markers into marker_list.
+ */
+
+#ifdef SAVE_MARKERS_SUPPORTED
+
+GLOBAL(void)
+jpeg_save_markers (j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+ long maxlength;
+ jpeg_marker_parser_method processor;
+
+ /* Length limit mustn't be larger than what we can allocate
+ * (should only be a concern in a 16-bit environment).
+ */
+ maxlength = cinfo->mem->max_alloc_chunk - SIZEOF(struct jpeg_marker_struct);
+ if (((long) length_limit) > maxlength)
+ length_limit = (unsigned int) maxlength;
+
+ /* Choose processor routine to use.
+ * APP0/APP14 have special requirements.
+ */
+ if (length_limit) {
+ processor = save_marker;
+ /* If saving APP0/APP14, save at least enough for our internal use. */
+ if (marker_code == (int) M_APP0 && length_limit < APP0_DATA_LEN)
+ length_limit = APP0_DATA_LEN;
+ else if (marker_code == (int) M_APP14 && length_limit < APP14_DATA_LEN)
+ length_limit = APP14_DATA_LEN;
+ } else {
+ processor = skip_variable;
+ /* If discarding APP0/APP14, use our regular on-the-fly processor. */
+ if (marker_code == (int) M_APP0 || marker_code == (int) M_APP14)
+ processor = get_interesting_appn;
+ }
+
+ if (marker_code == (int) M_COM) {
+ marker->process_COM = processor;
+ marker->length_limit_COM = length_limit;
+ } else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15) {
+ marker->process_APPn[marker_code - (int) M_APP0] = processor;
+ marker->length_limit_APPn[marker_code - (int) M_APP0] = length_limit;
+ } else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
+
+#endif /* SAVE_MARKERS_SUPPORTED */
+
+
+/*
+ * Install a special processing method for COM or APPn markers.
+ */
+
+GLOBAL(void)
+jpeg_set_marker_processor (j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine)
+{
+ my_marker_ptr marker = (my_marker_ptr) cinfo->marker;
+
+ if (marker_code == (int) M_COM)
+ marker->process_COM = routine;
+ else if (marker_code >= (int) M_APP0 && marker_code <= (int) M_APP15)
+ marker->process_APPn[marker_code - (int) M_APP0] = routine;
+ else
+ ERREXIT1(cinfo, JERR_UNKNOWN_MARKER, marker_code);
+}
diff --git a/Source/LibJPEG/jdmaster.c b/Source/LibJPEG/jdmaster.c
new file mode 100644
index 0000000..04f8312
--- /dev/null
+++ b/Source/LibJPEG/jdmaster.c
@@ -0,0 +1,663 @@
+/*
+ * jdmaster.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2002-2008 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains master control logic for the JPEG decompressor.
+ * These routines are concerned with selecting the modules to be executed
+ * and with determining the number of passes and the work to be done in each
+ * pass.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private state */
+
+typedef struct {
+ struct jpeg_decomp_master pub; /* public fields */
+
+ int pass_number; /* # of passes completed */
+
+ boolean using_merged_upsample; /* TRUE if using merged upsample/cconvert */
+
+ /* Saved references to initialized quantizer modules,
+ * in case we need to switch modes.
+ */
+ struct jpeg_color_quantizer * quantizer_1pass;
+ struct jpeg_color_quantizer * quantizer_2pass;
+} my_decomp_master;
+
+typedef my_decomp_master * my_master_ptr;
+
+
+/*
+ * Determine whether merged upsample/color conversion should be used.
+ * CRUCIAL: this must match the actual capabilities of jdmerge.c!
+ */
+
+LOCAL(boolean)
+use_merged_upsample (j_decompress_ptr cinfo)
+{
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ /* Merging is the equivalent of plain box-filter upsampling */
+ if (cinfo->do_fancy_upsampling || cinfo->CCIR601_sampling)
+ return FALSE;
+ /* jdmerge.c only supports YCC=>RGB color conversion */
+ if (cinfo->jpeg_color_space != JCS_YCbCr || cinfo->num_components != 3 ||
+ cinfo->out_color_space != JCS_RGB ||
+ cinfo->out_color_components != RGB_PIXELSIZE)
+ return FALSE;
+ /* and it only handles 2h1v or 2h2v sampling ratios */
+ if (cinfo->comp_info[0].h_samp_factor != 2 ||
+ cinfo->comp_info[1].h_samp_factor != 1 ||
+ cinfo->comp_info[2].h_samp_factor != 1 ||
+ cinfo->comp_info[0].v_samp_factor > 2 ||
+ cinfo->comp_info[1].v_samp_factor != 1 ||
+ cinfo->comp_info[2].v_samp_factor != 1)
+ return FALSE;
+ /* furthermore, it doesn't work if we've scaled the IDCTs differently */
+ if (cinfo->comp_info[0].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size ||
+ cinfo->comp_info[1].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size ||
+ cinfo->comp_info[2].DCT_h_scaled_size != cinfo->min_DCT_h_scaled_size ||
+ cinfo->comp_info[0].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size ||
+ cinfo->comp_info[1].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size ||
+ cinfo->comp_info[2].DCT_v_scaled_size != cinfo->min_DCT_v_scaled_size)
+ return FALSE;
+ /* ??? also need to test for upsample-time rescaling, when & if supported */
+ return TRUE; /* by golly, it'll work... */
+#else
+ return FALSE;
+#endif
+}
+
+
+/*
+ * Compute output image dimensions and related values.
+ * NOTE: this is exported for possible use by application.
+ * Hence it mustn't do anything that can't be done twice.
+ * Also note that it may be called before the master module is initialized!
+ */
+
+GLOBAL(void)
+jpeg_calc_output_dimensions (j_decompress_ptr cinfo)
+/* Do computations that are needed before master selection phase */
+{
+#ifdef IDCT_SCALING_SUPPORTED
+ int ci;
+ jpeg_component_info *compptr;
+#endif
+
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_READY)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+ /* Compute actual output image dimensions and DCT scaling choices. */
+ if (cinfo->scale_num * 8 <= cinfo->scale_denom) {
+ /* Provide 1/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 8L);
+ cinfo->min_DCT_h_scaled_size = 1;
+ cinfo->min_DCT_v_scaled_size = 1;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom) {
+ /* Provide 1/4 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 4L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 4L);
+ cinfo->min_DCT_h_scaled_size = 2;
+ cinfo->min_DCT_v_scaled_size = 2;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 3) {
+ /* Provide 3/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 3L, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 3L, 8L);
+ cinfo->min_DCT_h_scaled_size = 3;
+ cinfo->min_DCT_v_scaled_size = 3;
+ } else if (cinfo->scale_num * 2 <= cinfo->scale_denom) {
+ /* Provide 1/2 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 2L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 2L);
+ cinfo->min_DCT_h_scaled_size = 4;
+ cinfo->min_DCT_v_scaled_size = 4;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 5) {
+ /* Provide 5/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 5L, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 5L, 8L);
+ cinfo->min_DCT_h_scaled_size = 5;
+ cinfo->min_DCT_v_scaled_size = 5;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom * 3) {
+ /* Provide 3/4 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 3L, 4L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 3L, 4L);
+ cinfo->min_DCT_h_scaled_size = 6;
+ cinfo->min_DCT_v_scaled_size = 6;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 7) {
+ /* Provide 7/8 scaling */
+ cinfo->output_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 7L, 8L);
+ cinfo->output_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 7L, 8L);
+ cinfo->min_DCT_h_scaled_size = 7;
+ cinfo->min_DCT_v_scaled_size = 7;
+ } else if (cinfo->scale_num <= cinfo->scale_denom) {
+ /* Provide 1/1 scaling */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ cinfo->min_DCT_h_scaled_size = DCTSIZE;
+ cinfo->min_DCT_v_scaled_size = DCTSIZE;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 9) {
+ /* Provide 9/8 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 8L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 8L);
+ cinfo->min_DCT_h_scaled_size = 9;
+ cinfo->min_DCT_v_scaled_size = 9;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom * 5) {
+ /* Provide 5/4 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 4L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 4L);
+ cinfo->min_DCT_h_scaled_size = 10;
+ cinfo->min_DCT_v_scaled_size = 10;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 11) {
+ /* Provide 11/8 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 3L, 8L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 3L, 8L);
+ cinfo->min_DCT_h_scaled_size = 11;
+ cinfo->min_DCT_v_scaled_size = 11;
+ } else if (cinfo->scale_num * 2 <= cinfo->scale_denom * 3) {
+ /* Provide 3/2 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width, 2L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height, 2L);
+ cinfo->min_DCT_h_scaled_size = 12;
+ cinfo->min_DCT_v_scaled_size = 12;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 13) {
+ /* Provide 13/8 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 5L, 8L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 5L, 8L);
+ cinfo->min_DCT_h_scaled_size = 13;
+ cinfo->min_DCT_v_scaled_size = 13;
+ } else if (cinfo->scale_num * 4 <= cinfo->scale_denom * 7) {
+ /* Provide 7/4 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 3L, 4L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 3L, 4L);
+ cinfo->min_DCT_h_scaled_size = 14;
+ cinfo->min_DCT_v_scaled_size = 14;
+ } else if (cinfo->scale_num * 8 <= cinfo->scale_denom * 15) {
+ /* Provide 15/8 scaling */
+ cinfo->output_width = cinfo->image_width + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width * 7L, 8L);
+ cinfo->output_height = cinfo->image_height + (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height * 7L, 8L);
+ cinfo->min_DCT_h_scaled_size = 15;
+ cinfo->min_DCT_v_scaled_size = 15;
+ } else {
+ /* Provide 2/1 scaling */
+ cinfo->output_width = cinfo->image_width << 1;
+ cinfo->output_height = cinfo->image_height << 1;
+ cinfo->min_DCT_h_scaled_size = 16;
+ cinfo->min_DCT_v_scaled_size = 16;
+ }
+ /* In selecting the actual DCT scaling for each component, we try to
+ * scale up the chroma components via IDCT scaling rather than upsampling.
+ * This saves time if the upsampler gets to use 1:1 scaling.
+ * Note this code adapts subsampling ratios which are powers of 2.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ int ssize = 1;
+ while (cinfo->min_DCT_h_scaled_size * ssize <=
+ (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) &&
+ (cinfo->max_h_samp_factor % (compptr->h_samp_factor * ssize * 2)) == 0) {
+ ssize = ssize * 2;
+ }
+ compptr->DCT_h_scaled_size = cinfo->min_DCT_h_scaled_size * ssize;
+ ssize = 1;
+ while (cinfo->min_DCT_v_scaled_size * ssize <=
+ (cinfo->do_fancy_upsampling ? DCTSIZE : DCTSIZE / 2) &&
+ (cinfo->max_v_samp_factor % (compptr->v_samp_factor * ssize * 2)) == 0) {
+ ssize = ssize * 2;
+ }
+ compptr->DCT_v_scaled_size = cinfo->min_DCT_v_scaled_size * ssize;
+
+ /* We don't support IDCT ratios larger than 2. */
+ if (compptr->DCT_h_scaled_size > compptr->DCT_v_scaled_size * 2)
+ compptr->DCT_h_scaled_size = compptr->DCT_v_scaled_size * 2;
+ else if (compptr->DCT_v_scaled_size > compptr->DCT_h_scaled_size * 2)
+ compptr->DCT_v_scaled_size = compptr->DCT_h_scaled_size * 2;
+ }
+
+ /* Recompute downsampled dimensions of components;
+ * application needs to know these if using raw downsampled data.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Size in samples, after IDCT scaling */
+ compptr->downsampled_width = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_width *
+ (long) (compptr->h_samp_factor * compptr->DCT_h_scaled_size),
+ (long) (cinfo->max_h_samp_factor * DCTSIZE));
+ compptr->downsampled_height = (JDIMENSION)
+ jdiv_round_up((long) cinfo->image_height *
+ (long) (compptr->v_samp_factor * compptr->DCT_v_scaled_size),
+ (long) (cinfo->max_v_samp_factor * DCTSIZE));
+ }
+
+#else /* !IDCT_SCALING_SUPPORTED */
+
+ /* Hardwire it to "no scaling" */
+ cinfo->output_width = cinfo->image_width;
+ cinfo->output_height = cinfo->image_height;
+ /* jdinput.c has already initialized DCT_scaled_size to DCTSIZE,
+ * and has computed unscaled downsampled_width and downsampled_height.
+ */
+
+#endif /* IDCT_SCALING_SUPPORTED */
+
+ /* Report number of components in selected colorspace. */
+ /* Probably this should be in the color conversion module... */
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ cinfo->out_color_components = 1;
+ break;
+ case JCS_RGB:
+#if RGB_PIXELSIZE != 3
+ cinfo->out_color_components = RGB_PIXELSIZE;
+ break;
+#endif /* else share code with YCbCr */
+ case JCS_YCbCr:
+ cinfo->out_color_components = 3;
+ break;
+ case JCS_CMYK:
+ case JCS_YCCK:
+ cinfo->out_color_components = 4;
+ break;
+ default: /* else must be same colorspace as in file */
+ cinfo->out_color_components = cinfo->num_components;
+ break;
+ }
+ cinfo->output_components = (cinfo->quantize_colors ? 1 :
+ cinfo->out_color_components);
+
+ /* See if upsampler will want to emit more than one row at a time */
+ if (use_merged_upsample(cinfo))
+ cinfo->rec_outbuf_height = cinfo->max_v_samp_factor;
+ else
+ cinfo->rec_outbuf_height = 1;
+}
+
+
+/*
+ * Several decompression processes need to range-limit values to the range
+ * 0..MAXJSAMPLE; the input value may fall somewhat outside this range
+ * due to noise introduced by quantization, roundoff error, etc. These
+ * processes are inner loops and need to be as fast as possible. On most
+ * machines, particularly CPUs with pipelines or instruction prefetch,
+ * a (subscript-check-less) C table lookup
+ * x = sample_range_limit[x];
+ * is faster than explicit tests
+ * if (x < 0) x = 0;
+ * else if (x > MAXJSAMPLE) x = MAXJSAMPLE;
+ * These processes all use a common table prepared by the routine below.
+ *
+ * For most steps we can mathematically guarantee that the initial value
+ * of x is within MAXJSAMPLE+1 of the legal range, so a table running from
+ * -(MAXJSAMPLE+1) to 2*MAXJSAMPLE+1 is sufficient. But for the initial
+ * limiting step (just after the IDCT), a wildly out-of-range value is
+ * possible if the input data is corrupt. To avoid any chance of indexing
+ * off the end of memory and getting a bad-pointer trap, we perform the
+ * post-IDCT limiting thus:
+ * x = range_limit[x & MASK];
+ * where MASK is 2 bits wider than legal sample data, ie 10 bits for 8-bit
+ * samples. Under normal circumstances this is more than enough range and
+ * a correct output will be generated; with bogus input data the mask will
+ * cause wraparound, and we will safely generate a bogus-but-in-range output.
+ * For the post-IDCT step, we want to convert the data from signed to unsigned
+ * representation by adding CENTERJSAMPLE at the same time that we limit it.
+ * So the post-IDCT limiting table ends up looking like this:
+ * CENTERJSAMPLE,CENTERJSAMPLE+1,...,MAXJSAMPLE,
+ * MAXJSAMPLE (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0 (repeat 2*(MAXJSAMPLE+1)-CENTERJSAMPLE times),
+ * 0,1,...,CENTERJSAMPLE-1
+ * Negative inputs select values from the upper half of the table after
+ * masking.
+ *
+ * We can save some space by overlapping the start of the post-IDCT table
+ * with the simpler range limiting table. The post-IDCT table begins at
+ * sample_range_limit + CENTERJSAMPLE.
+ *
+ * Note that the table is allocated in near data space on PCs; it's small
+ * enough and used often enough to justify this.
+ */
+
+LOCAL(void)
+prepare_range_limit_table (j_decompress_ptr cinfo)
+/* Allocate and fill in the sample_range_limit table */
+{
+ JSAMPLE * table;
+ int i;
+
+ table = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (5 * (MAXJSAMPLE+1) + CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ table += (MAXJSAMPLE+1); /* allow negative subscripts of simple table */
+ cinfo->sample_range_limit = table;
+ /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+ MEMZERO(table - (MAXJSAMPLE+1), (MAXJSAMPLE+1) * SIZEOF(JSAMPLE));
+ /* Main part of "simple" table: limit[x] = x */
+ for (i = 0; i <= MAXJSAMPLE; i++)
+ table[i] = (JSAMPLE) i;
+ table += CENTERJSAMPLE; /* Point to where post-IDCT table starts */
+ /* End of simple table, rest of first half of post-IDCT table */
+ for (i = CENTERJSAMPLE; i < 2*(MAXJSAMPLE+1); i++)
+ table[i] = MAXJSAMPLE;
+ /* Second half of post-IDCT table */
+ MEMZERO(table + (2 * (MAXJSAMPLE+1)),
+ (2 * (MAXJSAMPLE+1) - CENTERJSAMPLE) * SIZEOF(JSAMPLE));
+ MEMCOPY(table + (4 * (MAXJSAMPLE+1) - CENTERJSAMPLE),
+ cinfo->sample_range_limit, CENTERJSAMPLE * SIZEOF(JSAMPLE));
+}
+
+
+/*
+ * Master selection of decompression modules.
+ * This is done once at jpeg_start_decompress time. We determine
+ * which modules will be used and give them appropriate initialization calls.
+ * We also initialize the decompressor input side to begin consuming data.
+ *
+ * Since jpeg_read_header has finished, we know what is in the SOF
+ * and (first) SOS markers. We also have all the application parameter
+ * settings.
+ */
+
+LOCAL(void)
+master_selection (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+ boolean use_c_buffer;
+ long samplesperrow;
+ JDIMENSION jd_samplesperrow;
+
+ /* Initialize dimensions and other stuff */
+ jpeg_calc_output_dimensions(cinfo);
+ prepare_range_limit_table(cinfo);
+
+ /* Width of an output scanline must be representable as JDIMENSION. */
+ samplesperrow = (long) cinfo->output_width * (long) cinfo->out_color_components;
+ jd_samplesperrow = (JDIMENSION) samplesperrow;
+ if ((long) jd_samplesperrow != samplesperrow)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+
+ /* Initialize my private state */
+ master->pass_number = 0;
+ master->using_merged_upsample = use_merged_upsample(cinfo);
+
+ /* Color quantizer selection */
+ master->quantizer_1pass = NULL;
+ master->quantizer_2pass = NULL;
+ /* No mode changes if not using buffered-image mode. */
+ if (! cinfo->quantize_colors || ! cinfo->buffered_image) {
+ cinfo->enable_1pass_quant = FALSE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ }
+ if (cinfo->quantize_colors) {
+ if (cinfo->raw_data_out)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+ /* 2-pass quantizer only works in 3-component color space. */
+ if (cinfo->out_color_components != 3) {
+ cinfo->enable_1pass_quant = TRUE;
+ cinfo->enable_external_quant = FALSE;
+ cinfo->enable_2pass_quant = FALSE;
+ cinfo->colormap = NULL;
+ } else if (cinfo->colormap != NULL) {
+ cinfo->enable_external_quant = TRUE;
+ } else if (cinfo->two_pass_quantize) {
+ cinfo->enable_2pass_quant = TRUE;
+ } else {
+ cinfo->enable_1pass_quant = TRUE;
+ }
+
+ if (cinfo->enable_1pass_quant) {
+#ifdef QUANT_1PASS_SUPPORTED
+ jinit_1pass_quantizer(cinfo);
+ master->quantizer_1pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+
+ /* We use the 2-pass code to map to external colormaps. */
+ if (cinfo->enable_2pass_quant || cinfo->enable_external_quant) {
+#ifdef QUANT_2PASS_SUPPORTED
+ jinit_2pass_quantizer(cinfo);
+ master->quantizer_2pass = cinfo->cquantize;
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ }
+ /* If both quantizers are initialized, the 2-pass one is left active;
+ * this is necessary for starting with quantization to an external map.
+ */
+ }
+
+ /* Post-processing: in particular, color conversion first */
+ if (! cinfo->raw_data_out) {
+ if (master->using_merged_upsample) {
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+ jinit_merged_upsampler(cinfo); /* does color conversion too */
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif
+ } else {
+ jinit_color_deconverter(cinfo);
+ jinit_upsampler(cinfo);
+ }
+ jinit_d_post_controller(cinfo, cinfo->enable_2pass_quant);
+ }
+ /* Inverse DCT */
+ jinit_inverse_dct(cinfo);
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code) {
+ jinit_arith_decoder(cinfo);
+ } else {
+ jinit_huff_decoder(cinfo);
+ }
+
+ /* Initialize principal buffer controllers. */
+ use_c_buffer = cinfo->inputctl->has_multiple_scans || cinfo->buffered_image;
+ jinit_d_coef_controller(cinfo, use_c_buffer);
+
+ if (! cinfo->raw_data_out)
+ jinit_d_main_controller(cinfo, FALSE /* never need full buffer here */);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+ /* If jpeg_start_decompress will read the whole file, initialize
+ * progress monitoring appropriately. The input step is counted
+ * as one pass.
+ */
+ if (cinfo->progress != NULL && ! cinfo->buffered_image &&
+ cinfo->inputctl->has_multiple_scans) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->progressive_mode) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = (cinfo->enable_2pass_quant ? 3 : 2);
+ /* Count the input pass as done */
+ master->pass_number++;
+ }
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+}
+
+
+/*
+ * Per-pass setup.
+ * This is called at the beginning of each output pass. We determine which
+ * modules will be active during this pass and give them appropriate
+ * start_pass calls. We also set is_dummy_pass to indicate whether this
+ * is a "real" output pass or a dummy pass for color quantization.
+ * (In the latter case, jdapistd.c will crank the pass to completion.)
+ */
+
+METHODDEF(void)
+prepare_for_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (master->pub.is_dummy_pass) {
+#ifdef QUANT_2PASS_SUPPORTED
+ /* Final pass of 2-pass quantization */
+ master->pub.is_dummy_pass = FALSE;
+ (*cinfo->cquantize->start_pass) (cinfo, FALSE);
+ (*cinfo->post->start_pass) (cinfo, JBUF_CRANK_DEST);
+ (*cinfo->main->start_pass) (cinfo, JBUF_CRANK_DEST);
+#else
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ if (cinfo->quantize_colors && cinfo->colormap == NULL) {
+ /* Select new quantization method */
+ if (cinfo->two_pass_quantize && cinfo->enable_2pass_quant) {
+ cinfo->cquantize = master->quantizer_2pass;
+ master->pub.is_dummy_pass = TRUE;
+ } else if (cinfo->enable_1pass_quant) {
+ cinfo->cquantize = master->quantizer_1pass;
+ } else {
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+ }
+ }
+ (*cinfo->idct->start_pass) (cinfo);
+ (*cinfo->coef->start_output_pass) (cinfo);
+ if (! cinfo->raw_data_out) {
+ if (! master->using_merged_upsample)
+ (*cinfo->cconvert->start_pass) (cinfo);
+ (*cinfo->upsample->start_pass) (cinfo);
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->start_pass) (cinfo, master->pub.is_dummy_pass);
+ (*cinfo->post->start_pass) (cinfo,
+ (master->pub.is_dummy_pass ? JBUF_SAVE_AND_PASS : JBUF_PASS_THRU));
+ (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU);
+ }
+ }
+
+ /* Set up progress monitor's pass info if present */
+ if (cinfo->progress != NULL) {
+ cinfo->progress->completed_passes = master->pass_number;
+ cinfo->progress->total_passes = master->pass_number +
+ (master->pub.is_dummy_pass ? 2 : 1);
+ /* In buffered-image mode, we assume one more output pass if EOI not
+ * yet reached, but no more passes if EOI has been reached.
+ */
+ if (cinfo->buffered_image && ! cinfo->inputctl->eoi_reached) {
+ cinfo->progress->total_passes += (cinfo->enable_2pass_quant ? 2 : 1);
+ }
+ }
+}
+
+
+/*
+ * Finish up at end of an output pass.
+ */
+
+METHODDEF(void)
+finish_output_pass (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ if (cinfo->quantize_colors)
+ (*cinfo->cquantize->finish_pass) (cinfo);
+ master->pass_number++;
+}
+
+
+#ifdef D_MULTISCAN_FILES_SUPPORTED
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+GLOBAL(void)
+jpeg_new_colormap (j_decompress_ptr cinfo)
+{
+ my_master_ptr master = (my_master_ptr) cinfo->master;
+
+ /* Prevent application from calling me at wrong times */
+ if (cinfo->global_state != DSTATE_BUFIMAGE)
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+
+ if (cinfo->quantize_colors && cinfo->enable_external_quant &&
+ cinfo->colormap != NULL) {
+ /* Select 2-pass quantizer for external colormap use */
+ cinfo->cquantize = master->quantizer_2pass;
+ /* Notify quantizer of colormap change */
+ (*cinfo->cquantize->new_color_map) (cinfo);
+ master->pub.is_dummy_pass = FALSE; /* just in case */
+ } else
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+#endif /* D_MULTISCAN_FILES_SUPPORTED */
+
+
+/*
+ * Initialize master decompression control and select active modules.
+ * This is performed at the start of jpeg_start_decompress.
+ */
+
+GLOBAL(void)
+jinit_master_decompress (j_decompress_ptr cinfo)
+{
+ my_master_ptr master;
+
+ master = (my_master_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_decomp_master));
+ cinfo->master = (struct jpeg_decomp_master *) master;
+ master->pub.prepare_for_output_pass = prepare_for_output_pass;
+ master->pub.finish_output_pass = finish_output_pass;
+
+ master->pub.is_dummy_pass = FALSE;
+
+ master_selection(cinfo);
+}
diff --git a/Source/LibJPEG/jdmerge.c b/Source/LibJPEG/jdmerge.c
new file mode 100644
index 0000000..3744446
--- /dev/null
+++ b/Source/LibJPEG/jdmerge.c
@@ -0,0 +1,400 @@
+/*
+ * jdmerge.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains code for merged upsampling/color conversion.
+ *
+ * This file combines functions from jdsample.c and jdcolor.c;
+ * read those files first to understand what's going on.
+ *
+ * When the chroma components are to be upsampled by simple replication
+ * (ie, box filtering), we can save some work in color conversion by
+ * calculating all the output pixels corresponding to a pair of chroma
+ * samples at one time. In the conversion equations
+ * R = Y + K1 * Cr
+ * G = Y + K2 * Cb + K3 * Cr
+ * B = Y + K4 * Cb
+ * only the Y term varies among the group of pixels corresponding to a pair
+ * of chroma samples, so the rest of the terms can be calculated just once.
+ * At typical sampling ratios, this eliminates half or three-quarters of the
+ * multiplications needed for color conversion.
+ *
+ * This file currently provides implementations for the following cases:
+ * YCbCr => RGB color conversion only.
+ * Sampling ratios of 2h1v or 2h2v.
+ * No scaling needed at upsample time.
+ * Corner-aligned (non-CCIR601) sampling alignment.
+ * Other special cases could be added, but in most applications these are
+ * the only common cases. (For uncommon cases we fall back on the more
+ * general code in jdsample.c and jdcolor.c.)
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef UPSAMPLE_MERGING_SUPPORTED
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Pointer to routine to do actual upsampling/conversion of one row group */
+ JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf));
+
+ /* Private state for YCC->RGB conversion */
+ int * Cr_r_tab; /* => table for Cr to R conversion */
+ int * Cb_b_tab; /* => table for Cb to B conversion */
+ INT32 * Cr_g_tab; /* => table for Cr to G conversion */
+ INT32 * Cb_g_tab; /* => table for Cb to G conversion */
+
+ /* For 2:1 vertical sampling, we produce two output rows at a time.
+ * We need a "spare" row buffer to hold the second output row if the
+ * application provides just a one-row buffer; we also use the spare
+ * to discard the dummy last row if the image height is odd.
+ */
+ JSAMPROW spare_row;
+ boolean spare_full; /* T if spare buffer is occupied */
+
+ JDIMENSION out_row_width; /* samples per output row */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+#define SCALEBITS 16 /* speediest right-shift on some machines */
+#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
+#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
+
+
+/*
+ * Initialize tables for YCC->RGB colorspace conversion.
+ * This is taken directly from jdcolor.c; see that file for more info.
+ */
+
+LOCAL(void)
+build_ycc_rgb_table (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int i;
+ INT32 x;
+ SHIFT_TEMPS
+
+ upsample->Cr_r_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cb_b_tab = (int *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(int));
+ upsample->Cr_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+ upsample->Cb_g_tab = (INT32 *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (MAXJSAMPLE+1) * SIZEOF(INT32));
+
+ for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
+ /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+ /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+ /* Cr=>R value is nearest int to 1.40200 * x */
+ upsample->Cr_r_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
+ /* Cb=>B value is nearest int to 1.77200 * x */
+ upsample->Cb_b_tab[i] = (int)
+ RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
+ /* Cr=>G value is scaled-up -0.71414 * x */
+ upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
+ /* Cb=>G value is scaled-up -0.34414 * x */
+ /* We also add in ONE_HALF so that need not do it in inner loop */
+ upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
+ }
+}
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_merged_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the spare buffer empty */
+ upsample->spare_full = FALSE;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * The control routine just handles the row buffering considerations.
+ */
+
+METHODDEF(void)
+merged_2v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 2:1 vertical sampling case: may need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPROW work_ptrs[2];
+ JDIMENSION num_rows; /* number of rows returned to caller */
+
+ if (upsample->spare_full) {
+ /* If we have a spare row saved from a previous cycle, just return it. */
+ jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
+ 1, upsample->out_row_width);
+ num_rows = 1;
+ upsample->spare_full = FALSE;
+ } else {
+ /* Figure number of rows to return to caller. */
+ num_rows = 2;
+ /* Not more than the distance to the end of the image. */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+ /* Create output pointer array for upsampler. */
+ work_ptrs[0] = output_buf[*out_row_ctr];
+ if (num_rows > 1) {
+ work_ptrs[1] = output_buf[*out_row_ctr + 1];
+ } else {
+ work_ptrs[1] = upsample->spare_row;
+ upsample->spare_full = TRUE;
+ }
+ /* Now do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
+ }
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (! upsample->spare_full)
+ (*in_row_group_ctr)++;
+}
+
+
+METHODDEF(void)
+merged_1v_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+/* 1:1 vertical sampling case: much easier, never need a spare row. */
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Just do the upsampling. */
+ (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
+ output_buf + *out_row_ctr);
+ /* Adjust counts */
+ (*out_row_ctr)++;
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by the control routines to do
+ * the actual upsampling/conversion. One row group is processed per call.
+ *
+ * Note: since we may be writing directly into application-supplied buffers,
+ * we have to be honest about the output width; we can't assume the buffer
+ * has been rounded up to an even width.
+ */
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
+ */
+
+METHODDEF(void)
+h2v1_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr;
+ JSAMPROW inptr0, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr0 = input_buf[0][in_row_group_ctr];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr = output_buf[0];
+ /* Loop for each pair of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 2 Y values and emit 2 pixels */
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr0++);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ outptr += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr0);
+ outptr[RGB_RED] = range_limit[y + cred];
+ outptr[RGB_GREEN] = range_limit[y + cgreen];
+ outptr[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
+ */
+
+METHODDEF(void)
+h2v2_merged_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
+ JSAMPARRAY output_buf)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ register int y, cred, cgreen, cblue;
+ int cb, cr;
+ register JSAMPROW outptr0, outptr1;
+ JSAMPROW inptr00, inptr01, inptr1, inptr2;
+ JDIMENSION col;
+ /* copy these pointers into registers if possible */
+ register JSAMPLE * range_limit = cinfo->sample_range_limit;
+ int * Crrtab = upsample->Cr_r_tab;
+ int * Cbbtab = upsample->Cb_b_tab;
+ INT32 * Crgtab = upsample->Cr_g_tab;
+ INT32 * Cbgtab = upsample->Cb_g_tab;
+ SHIFT_TEMPS
+
+ inptr00 = input_buf[0][in_row_group_ctr*2];
+ inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
+ inptr1 = input_buf[1][in_row_group_ctr];
+ inptr2 = input_buf[2][in_row_group_ctr];
+ outptr0 = output_buf[0];
+ outptr1 = output_buf[1];
+ /* Loop for each group of output pixels */
+ for (col = cinfo->output_width >> 1; col > 0; col--) {
+ /* Do the chroma part of the calculation */
+ cb = GETJSAMPLE(*inptr1++);
+ cr = GETJSAMPLE(*inptr2++);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ /* Fetch 4 Y values and emit 4 pixels */
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr00++);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ outptr0 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ y = GETJSAMPLE(*inptr01++);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ outptr1 += RGB_PIXELSIZE;
+ }
+ /* If image width is odd, do the last output column separately */
+ if (cinfo->output_width & 1) {
+ cb = GETJSAMPLE(*inptr1);
+ cr = GETJSAMPLE(*inptr2);
+ cred = Crrtab[cr];
+ cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
+ cblue = Cbbtab[cb];
+ y = GETJSAMPLE(*inptr00);
+ outptr0[RGB_RED] = range_limit[y + cred];
+ outptr0[RGB_GREEN] = range_limit[y + cgreen];
+ outptr0[RGB_BLUE] = range_limit[y + cblue];
+ y = GETJSAMPLE(*inptr01);
+ outptr1[RGB_RED] = range_limit[y + cred];
+ outptr1[RGB_GREEN] = range_limit[y + cgreen];
+ outptr1[RGB_BLUE] = range_limit[y + cblue];
+ }
+}
+
+
+/*
+ * Module initialization routine for merged upsampling/color conversion.
+ *
+ * NB: this is called under the conditions determined by use_merged_upsample()
+ * in jdmaster.c. That routine MUST correspond to the actual capabilities
+ * of this module; no safety checks are made here.
+ */
+
+GLOBAL(void)
+jinit_merged_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_merged_upsample;
+ upsample->pub.need_context_rows = FALSE;
+
+ upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
+
+ if (cinfo->max_v_samp_factor == 2) {
+ upsample->pub.upsample = merged_2v_upsample;
+ upsample->upmethod = h2v2_merged_upsample;
+ /* Allocate a spare row buffer */
+ upsample->spare_row = (JSAMPROW)
+ (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
+ } else {
+ upsample->pub.upsample = merged_1v_upsample;
+ upsample->upmethod = h2v1_merged_upsample;
+ /* No spare row needed */
+ upsample->spare_row = NULL;
+ }
+
+ build_ycc_rgb_table(cinfo);
+}
+
+#endif /* UPSAMPLE_MERGING_SUPPORTED */
diff --git a/Source/LibJPEG/jdpostct.c b/Source/LibJPEG/jdpostct.c
new file mode 100644
index 0000000..571563d
--- /dev/null
+++ b/Source/LibJPEG/jdpostct.c
@@ -0,0 +1,290 @@
+/*
+ * jdpostct.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the decompression postprocessing controller.
+ * This controller manages the upsampling, color conversion, and color
+ * quantization/reduction steps; specifically, it controls the buffering
+ * between upsample/color conversion and color quantization/reduction.
+ *
+ * If no color quantization/reduction is required, then this module has no
+ * work to do, and it just hands off to the upsample/color conversion code.
+ * An integrated upsample/convert/quantize process would replace this module
+ * entirely.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Private buffer controller object */
+
+typedef struct {
+ struct jpeg_d_post_controller pub; /* public fields */
+
+ /* Color quantization source buffer: this holds output data from
+ * the upsample/color conversion step to be passed to the quantizer.
+ * For two-pass color quantization, we need a full-image buffer;
+ * for one-pass operation, a strip buffer is sufficient.
+ */
+ jvirt_sarray_ptr whole_image; /* virtual array, or NULL if one-pass */
+ JSAMPARRAY buffer; /* strip buffer, or current strip of virtual */
+ JDIMENSION strip_height; /* buffer size in rows */
+ /* for two-pass mode only: */
+ JDIMENSION starting_row; /* row # of first row in current strip */
+ JDIMENSION next_row; /* index of next row to fill/empty in strip */
+} my_post_controller;
+
+typedef my_post_controller * my_post_ptr;
+
+
+/* Forward declarations */
+METHODDEF(void) post_process_1pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#ifdef QUANT_2PASS_SUPPORTED
+METHODDEF(void) post_process_prepass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+METHODDEF(void) post_process_2pass
+ JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+#endif
+
+
+/*
+ * Initialize for a processing pass.
+ */
+
+METHODDEF(void)
+start_pass_dpost (j_decompress_ptr cinfo, J_BUF_MODE pass_mode)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+
+ switch (pass_mode) {
+ case JBUF_PASS_THRU:
+ if (cinfo->quantize_colors) {
+ /* Single-pass processing with color quantization. */
+ post->pub.post_process_data = post_process_1pass;
+ /* We could be doing buffered-image output before starting a 2-pass
+ * color quantization; in that case, jinit_d_post_controller did not
+ * allocate a strip buffer. Use the virtual-array buffer as workspace.
+ */
+ if (post->buffer == NULL) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ (JDIMENSION) 0, post->strip_height, TRUE);
+ }
+ } else {
+ /* For single-pass processing without color quantization,
+ * I have no work to do; just call the upsampler directly.
+ */
+ post->pub.post_process_data = cinfo->upsample->upsample;
+ }
+ break;
+#ifdef QUANT_2PASS_SUPPORTED
+ case JBUF_SAVE_AND_PASS:
+ /* First pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_prepass;
+ break;
+ case JBUF_CRANK_DEST:
+ /* Second pass of 2-pass quantization */
+ if (post->whole_image == NULL)
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ post->pub.post_process_data = post_process_2pass;
+ break;
+#endif /* QUANT_2PASS_SUPPORTED */
+ default:
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+ break;
+ }
+ post->starting_row = post->next_row = 0;
+}
+
+
+/*
+ * Process some data in the one-pass (strip buffer) case.
+ * This is used for color precision reduction as well as one-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_1pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Fill the buffer, but not more than what we can dump out in one go. */
+ /* Note we rely on the upsampler to detect bottom of image. */
+ max_rows = out_rows_avail - *out_row_ctr;
+ if (max_rows > post->strip_height)
+ max_rows = post->strip_height;
+ num_rows = 0;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &num_rows, max_rows);
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer, output_buf + *out_row_ctr, (int) num_rows);
+ *out_row_ctr += num_rows;
+}
+
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+/*
+ * Process some data in the first pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_prepass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION old_next_row, num_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, TRUE);
+ }
+
+ /* Upsample some data (up to a strip height's worth). */
+ old_next_row = post->next_row;
+ (*cinfo->upsample->upsample) (cinfo,
+ input_buf, in_row_group_ctr, in_row_groups_avail,
+ post->buffer, &post->next_row, post->strip_height);
+
+ /* Allow quantizer to scan new data. No data is emitted, */
+ /* but we advance out_row_ctr so outer loop can tell when we're done. */
+ if (post->next_row > old_next_row) {
+ num_rows = post->next_row - old_next_row;
+ (*cinfo->cquantize->color_quantize) (cinfo, post->buffer + old_next_row,
+ (JSAMPARRAY) NULL, (int) num_rows);
+ *out_row_ctr += num_rows;
+ }
+
+ /* Advance if we filled the strip. */
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+
+/*
+ * Process some data in the second pass of 2-pass quantization.
+ */
+
+METHODDEF(void)
+post_process_2pass (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_post_ptr post = (my_post_ptr) cinfo->post;
+ JDIMENSION num_rows, max_rows;
+
+ /* Reposition virtual buffer if at start of strip. */
+ if (post->next_row == 0) {
+ post->buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, post->whole_image,
+ post->starting_row, post->strip_height, FALSE);
+ }
+
+ /* Determine number of rows to emit. */
+ num_rows = post->strip_height - post->next_row; /* available in strip */
+ max_rows = out_rows_avail - *out_row_ctr; /* available in output area */
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+ /* We have to check bottom of image here, can't depend on upsampler. */
+ max_rows = cinfo->output_height - post->starting_row;
+ if (num_rows > max_rows)
+ num_rows = max_rows;
+
+ /* Quantize and emit data. */
+ (*cinfo->cquantize->color_quantize) (cinfo,
+ post->buffer + post->next_row, output_buf + *out_row_ctr,
+ (int) num_rows);
+ *out_row_ctr += num_rows;
+
+ /* Advance if we filled the strip. */
+ post->next_row += num_rows;
+ if (post->next_row >= post->strip_height) {
+ post->starting_row += post->strip_height;
+ post->next_row = 0;
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
+
+
+/*
+ * Initialize postprocessing controller.
+ */
+
+GLOBAL(void)
+jinit_d_post_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
+{
+ my_post_ptr post;
+
+ post = (my_post_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_post_controller));
+ cinfo->post = (struct jpeg_d_post_controller *) post;
+ post->pub.start_pass = start_pass_dpost;
+ post->whole_image = NULL; /* flag for no virtual arrays */
+ post->buffer = NULL; /* flag for no strip buffer */
+
+ /* Create the quantization buffer, if needed */
+ if (cinfo->quantize_colors) {
+ /* The buffer strip height is max_v_samp_factor, which is typically
+ * an efficient number of rows for upsampling to return.
+ * (In the presence of output rescaling, we might want to be smarter?)
+ */
+ post->strip_height = (JDIMENSION) cinfo->max_v_samp_factor;
+ if (need_full_buffer) {
+ /* Two-pass color quantization: need full-image storage. */
+ /* We round up the number of rows to a multiple of the strip height. */
+#ifdef QUANT_2PASS_SUPPORTED
+ post->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ cinfo->output_width * cinfo->out_color_components,
+ (JDIMENSION) jround_up((long) cinfo->output_height,
+ (long) post->strip_height),
+ post->strip_height);
+#else
+ ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
+#endif /* QUANT_2PASS_SUPPORTED */
+ } else {
+ /* One-pass color quantization: just make a strip buffer. */
+ post->buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width * cinfo->out_color_components,
+ post->strip_height);
+ }
+ }
+}
diff --git a/Source/LibJPEG/jdsample.c b/Source/LibJPEG/jdsample.c
new file mode 100644
index 0000000..7bc8885
--- /dev/null
+++ b/Source/LibJPEG/jdsample.c
@@ -0,0 +1,361 @@
+/*
+ * jdsample.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * Modified 2002-2008 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains upsampling routines.
+ *
+ * Upsampling input data is counted in "row groups". A row group
+ * is defined to be (v_samp_factor * DCT_v_scaled_size / min_DCT_v_scaled_size)
+ * sample rows of each component. Upsampling will normally produce
+ * max_v_samp_factor pixel rows from each row group (but this could vary
+ * if the upsampler is applying a scale factor of its own).
+ *
+ * An excellent reference for image resampling is
+ * Digital Image Warping, George Wolberg, 1990.
+ * Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Pointer to routine to upsample a single component */
+typedef JMETHOD(void, upsample1_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr));
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_upsampler pub; /* public fields */
+
+ /* Color conversion buffer. When using separate upsampling and color
+ * conversion steps, this buffer holds one upsampled row group until it
+ * has been color converted and output.
+ * Note: we do not allocate any storage for component(s) which are full-size,
+ * ie do not need rescaling. The corresponding entry of color_buf[] is
+ * simply set to point to the input data array, thereby avoiding copying.
+ */
+ JSAMPARRAY color_buf[MAX_COMPONENTS];
+
+ /* Per-component upsampling method pointers */
+ upsample1_ptr methods[MAX_COMPONENTS];
+
+ int next_row_out; /* counts rows emitted from color_buf */
+ JDIMENSION rows_to_go; /* counts rows remaining in image */
+
+ /* Height of an input row group for each component. */
+ int rowgroup_height[MAX_COMPONENTS];
+
+ /* These arrays save pixel expansion factors so that int_expand need not
+ * recompute them each time. They are unused for other upsampling methods.
+ */
+ UINT8 h_expand[MAX_COMPONENTS];
+ UINT8 v_expand[MAX_COMPONENTS];
+} my_upsampler;
+
+typedef my_upsampler * my_upsample_ptr;
+
+
+/*
+ * Initialize for an upsampling pass.
+ */
+
+METHODDEF(void)
+start_pass_upsample (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+
+ /* Mark the conversion buffer empty */
+ upsample->next_row_out = cinfo->max_v_samp_factor;
+ /* Initialize total-height counter for detecting bottom of image */
+ upsample->rows_to_go = cinfo->output_height;
+}
+
+
+/*
+ * Control routine to do upsampling (and color conversion).
+ *
+ * In this version we upsample each component independently.
+ * We upsample one row group into the conversion buffer, then apply
+ * color conversion a row at a time.
+ */
+
+METHODDEF(void)
+sep_upsample (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ JDIMENSION num_rows;
+
+ /* Fill the conversion buffer, if it's empty */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor) {
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Invoke per-component upsample method. Notice we pass a POINTER
+ * to color_buf[ci], so that fullsize_upsample can change it.
+ */
+ (*upsample->methods[ci]) (cinfo, compptr,
+ input_buf[ci] + (*in_row_group_ctr * upsample->rowgroup_height[ci]),
+ upsample->color_buf + ci);
+ }
+ upsample->next_row_out = 0;
+ }
+
+ /* Color-convert and emit rows */
+
+ /* How many we have in the buffer: */
+ num_rows = (JDIMENSION) (cinfo->max_v_samp_factor - upsample->next_row_out);
+ /* Not more than the distance to the end of the image. Need this test
+ * in case the image height is not a multiple of max_v_samp_factor:
+ */
+ if (num_rows > upsample->rows_to_go)
+ num_rows = upsample->rows_to_go;
+ /* And not more than what the client can accept: */
+ out_rows_avail -= *out_row_ctr;
+ if (num_rows > out_rows_avail)
+ num_rows = out_rows_avail;
+
+ (*cinfo->cconvert->color_convert) (cinfo, upsample->color_buf,
+ (JDIMENSION) upsample->next_row_out,
+ output_buf + *out_row_ctr,
+ (int) num_rows);
+
+ /* Adjust counts */
+ *out_row_ctr += num_rows;
+ upsample->rows_to_go -= num_rows;
+ upsample->next_row_out += num_rows;
+ /* When the buffer is emptied, declare this input row group consumed */
+ if (upsample->next_row_out >= cinfo->max_v_samp_factor)
+ (*in_row_group_ctr)++;
+}
+
+
+/*
+ * These are the routines invoked by sep_upsample to upsample pixel values
+ * of a single component. One row group is processed per call.
+ */
+
+
+/*
+ * For full-size components, we just make color_buf[ci] point at the
+ * input buffer, and thus avoid copying any data. Note that this is
+ * safe only because sep_upsample doesn't declare the input row group
+ * "consumed" until we are done color converting and emitting it.
+ */
+
+METHODDEF(void)
+fullsize_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = input_data;
+}
+
+
+/*
+ * This is a no-op version used for "uninteresting" components.
+ * These components will not be referenced by color conversion.
+ */
+
+METHODDEF(void)
+noop_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ *output_data_ptr = NULL; /* safety check */
+}
+
+
+/*
+ * This version handles any integral sampling ratios.
+ * This is not used for typical JPEG files, so it need not be fast.
+ * Nor, for that matter, is it particularly accurate: the algorithm is
+ * simple replication of the input pixel onto the corresponding output
+ * pixels. The hi-falutin sampling literature refers to this as a
+ * "box filter". A box filter tends to introduce visible artifacts,
+ * so if you are actually going to use 3:1 or 4:1 sampling ratios
+ * you would be well advised to improve this code.
+ */
+
+METHODDEF(void)
+int_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ register int h;
+ JSAMPROW outend;
+ int h_expand, v_expand;
+ int inrow, outrow;
+
+ h_expand = upsample->h_expand[compptr->component_index];
+ v_expand = upsample->v_expand[compptr->component_index];
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ /* Generate one output row with proper horizontal expansion */
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ for (h = h_expand; h > 0; h--) {
+ *outptr++ = invalue;
+ }
+ }
+ /* Generate any additional output rows by duplicating the first one */
+ if (v_expand > 1) {
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ v_expand-1, cinfo->output_width);
+ }
+ inrow++;
+ outrow += v_expand;
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 1:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v1_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int outrow;
+
+ for (outrow = 0; outrow < cinfo->max_v_samp_factor; outrow++) {
+ inptr = input_data[outrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ }
+}
+
+
+/*
+ * Fast processing for the common case of 2:1 horizontal and 2:1 vertical.
+ * It's still a box filter.
+ */
+
+METHODDEF(void)
+h2v2_upsample (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY input_data, JSAMPARRAY * output_data_ptr)
+{
+ JSAMPARRAY output_data = *output_data_ptr;
+ register JSAMPROW inptr, outptr;
+ register JSAMPLE invalue;
+ JSAMPROW outend;
+ int inrow, outrow;
+
+ inrow = outrow = 0;
+ while (outrow < cinfo->max_v_samp_factor) {
+ inptr = input_data[inrow];
+ outptr = output_data[outrow];
+ outend = outptr + cinfo->output_width;
+ while (outptr < outend) {
+ invalue = *inptr++; /* don't need GETJSAMPLE() here */
+ *outptr++ = invalue;
+ *outptr++ = invalue;
+ }
+ jcopy_sample_rows(output_data, outrow, output_data, outrow+1,
+ 1, cinfo->output_width);
+ inrow++;
+ outrow += 2;
+ }
+}
+
+
+/*
+ * Module initialization routine for upsampling.
+ */
+
+GLOBAL(void)
+jinit_upsampler (j_decompress_ptr cinfo)
+{
+ my_upsample_ptr upsample;
+ int ci;
+ jpeg_component_info * compptr;
+ boolean need_buffer;
+ int h_in_group, v_in_group, h_out_group, v_out_group;
+
+ upsample = (my_upsample_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_upsampler));
+ cinfo->upsample = (struct jpeg_upsampler *) upsample;
+ upsample->pub.start_pass = start_pass_upsample;
+ upsample->pub.upsample = sep_upsample;
+ upsample->pub.need_context_rows = FALSE; /* until we find out differently */
+
+ if (cinfo->CCIR601_sampling) /* this isn't supported */
+ ERREXIT(cinfo, JERR_CCIR601_NOTIMPL);
+
+ /* Verify we can handle the sampling factors, select per-component methods,
+ * and create storage as needed.
+ */
+ for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
+ ci++, compptr++) {
+ /* Compute size of an "input group" after IDCT scaling. This many samples
+ * are to be converted to max_h_samp_factor * max_v_samp_factor pixels.
+ */
+ h_in_group = (compptr->h_samp_factor * compptr->DCT_h_scaled_size) /
+ cinfo->min_DCT_h_scaled_size;
+ v_in_group = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
+ cinfo->min_DCT_v_scaled_size;
+ h_out_group = cinfo->max_h_samp_factor;
+ v_out_group = cinfo->max_v_samp_factor;
+ upsample->rowgroup_height[ci] = v_in_group; /* save for use later */
+ need_buffer = TRUE;
+ if (! compptr->component_needed) {
+ /* Don't bother to upsample an uninteresting component. */
+ upsample->methods[ci] = noop_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group == h_out_group && v_in_group == v_out_group) {
+ /* Fullsize components can be processed without any work. */
+ upsample->methods[ci] = fullsize_upsample;
+ need_buffer = FALSE;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group == v_out_group) {
+ /* Special case for 2h1v upsampling */
+ upsample->methods[ci] = h2v1_upsample;
+ } else if (h_in_group * 2 == h_out_group &&
+ v_in_group * 2 == v_out_group) {
+ /* Special case for 2h2v upsampling */
+ upsample->methods[ci] = h2v2_upsample;
+ } else if ((h_out_group % h_in_group) == 0 &&
+ (v_out_group % v_in_group) == 0) {
+ /* Generic integral-factors upsampling method */
+ upsample->methods[ci] = int_upsample;
+ upsample->h_expand[ci] = (UINT8) (h_out_group / h_in_group);
+ upsample->v_expand[ci] = (UINT8) (v_out_group / v_in_group);
+ } else
+ ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL);
+ if (need_buffer) {
+ upsample->color_buf[ci] = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) jround_up((long) cinfo->output_width,
+ (long) cinfo->max_h_samp_factor),
+ (JDIMENSION) cinfo->max_v_samp_factor);
+ }
+ }
+}
diff --git a/Source/LibJPEG/jdtrans.c b/Source/LibJPEG/jdtrans.c
new file mode 100644
index 0000000..385c336
--- /dev/null
+++ b/Source/LibJPEG/jdtrans.c
@@ -0,0 +1,136 @@
+/*
+ * jdtrans.c
+ *
+ * Copyright (C) 1995-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains library routines for transcoding decompression,
+ * that is, reading raw DCT coefficient arrays from an input JPEG file.
+ * The routines in jdapimin.c will also be needed by a transcoder.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/* Forward declarations */
+LOCAL(void) transdecode_master_selection JPP((j_decompress_ptr cinfo));
+
+
+/*
+ * Read the coefficient arrays from a JPEG file.
+ * jpeg_read_header must be completed before calling this.
+ *
+ * The entire image is read into a set of virtual coefficient-block arrays,
+ * one per component. The return value is a pointer to the array of
+ * virtual-array descriptors. These can be manipulated directly via the
+ * JPEG memory manager, or handed off to jpeg_write_coefficients().
+ * To release the memory occupied by the virtual arrays, call
+ * jpeg_finish_decompress() when done with the data.
+ *
+ * An alternative usage is to simply obtain access to the coefficient arrays
+ * during a buffered-image-mode decompression operation. This is allowed
+ * after any jpeg_finish_output() call. The arrays can be accessed until
+ * jpeg_finish_decompress() is called. (Note that any call to the library
+ * may reposition the arrays, so don't rely on access_virt_barray() results
+ * to stay valid across library calls.)
+ *
+ * Returns NULL if suspended. This case need be checked only if
+ * a suspending data source is used.
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jpeg_read_coefficients (j_decompress_ptr cinfo)
+{
+ if (cinfo->global_state == DSTATE_READY) {
+ /* First call: initialize active modules */
+ transdecode_master_selection(cinfo);
+ cinfo->global_state = DSTATE_RDCOEFS;
+ }
+ if (cinfo->global_state == DSTATE_RDCOEFS) {
+ /* Absorb whole file into the coef buffer */
+ for (;;) {
+ int retcode;
+ /* Call progress monitor hook if present */
+ if (cinfo->progress != NULL)
+ (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);
+ /* Absorb some more input */
+ retcode = (*cinfo->inputctl->consume_input) (cinfo);
+ if (retcode == JPEG_SUSPENDED)
+ return NULL;
+ if (retcode == JPEG_REACHED_EOI)
+ break;
+ /* Advance progress counter if appropriate */
+ if (cinfo->progress != NULL &&
+ (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {
+ if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {
+ /* startup underestimated number of scans; ratchet up one scan */
+ cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;
+ }
+ }
+ }
+ /* Set state so that jpeg_finish_decompress does the right thing */
+ cinfo->global_state = DSTATE_STOPPING;
+ }
+ /* At this point we should be in state DSTATE_STOPPING if being used
+ * standalone, or in state DSTATE_BUFIMAGE if being invoked to get access
+ * to the coefficients during a full buffered-image-mode decompression.
+ */
+ if ((cinfo->global_state == DSTATE_STOPPING ||
+ cinfo->global_state == DSTATE_BUFIMAGE) && cinfo->buffered_image) {
+ return cinfo->coef->coef_arrays;
+ }
+ /* Oops, improper usage */
+ ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
+ return NULL; /* keep compiler happy */
+}
+
+
+/*
+ * Master selection of decompression modules for transcoding.
+ * This substitutes for jdmaster.c's initialization of the full decompressor.
+ */
+
+LOCAL(void)
+transdecode_master_selection (j_decompress_ptr cinfo)
+{
+ /* This is effectively a buffered-image operation. */
+ cinfo->buffered_image = TRUE;
+
+ /* Entropy decoding: either Huffman or arithmetic coding. */
+ if (cinfo->arith_code)
+ jinit_arith_decoder(cinfo);
+ else {
+ jinit_huff_decoder(cinfo);
+ }
+
+ /* Always get a full-image coefficient buffer. */
+ jinit_d_coef_controller(cinfo, TRUE);
+
+ /* We can now tell the memory manager to allocate virtual arrays. */
+ (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo);
+
+ /* Initialize input side of decompressor to consume first scan. */
+ (*cinfo->inputctl->start_input_pass) (cinfo);
+
+ /* Initialize progress monitoring. */
+ if (cinfo->progress != NULL) {
+ int nscans;
+ /* Estimate number of scans to set pass_limit. */
+ if (cinfo->progressive_mode) {
+ /* Arbitrarily estimate 2 interleaved DC scans + 3 AC scans/component. */
+ nscans = 2 + 3 * cinfo->num_components;
+ } else if (cinfo->inputctl->has_multiple_scans) {
+ /* For a nonprogressive multiscan file, estimate 1 scan per component. */
+ nscans = cinfo->num_components;
+ } else {
+ nscans = 1;
+ }
+ cinfo->progress->pass_counter = 0L;
+ cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows * nscans;
+ cinfo->progress->completed_passes = 0;
+ cinfo->progress->total_passes = 1;
+ }
+}
diff --git a/Source/LibJPEG/jerror.c b/Source/LibJPEG/jerror.c
new file mode 100644
index 0000000..3da7be8
--- /dev/null
+++ b/Source/LibJPEG/jerror.c
@@ -0,0 +1,252 @@
+/*
+ * jerror.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains simple error-reporting and trace-message routines.
+ * These are suitable for Unix-like systems and others where writing to
+ * stderr is the right thing to do. Many applications will want to replace
+ * some or all of these routines.
+ *
+ * If you define USE_WINDOWS_MESSAGEBOX in jconfig.h or in the makefile,
+ * you get a Windows-specific hack to display error messages in a dialog box.
+ * It ain't much, but it beats dropping error messages into the bit bucket,
+ * which is what happens to output to stderr under most Windows C compilers.
+ *
+ * These routines are used by both the compression and decompression code.
+ */
+
+/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jversion.h"
+#include "jerror.h"
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+#include <windows.h>
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+
+
+/*
+ * Create the message string table.
+ * We do this from the master message list in jerror.h by re-reading
+ * jerror.h with a suitable definition for macro JMESSAGE.
+ * The message table is made an external symbol just in case any applications
+ * want to refer to it directly.
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_message_table jMsgTable
+#endif
+
+#define JMESSAGE(code,string) string ,
+
+const char * const jpeg_std_message_table[] = {
+#include "jerror.h"
+ NULL
+};
+
+
+/*
+ * Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error. Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object. Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ */
+
+METHODDEF(void)
+error_exit (j_common_ptr cinfo)
+{
+ /* Always display the message */
+ (*cinfo->err->output_message) (cinfo);
+
+ /* Let the memory manager delete any temp files before we die */
+ jpeg_destroy(cinfo);
+
+ exit(EXIT_FAILURE);
+}
+
+
+/*
+ * Actual output of an error or trace message.
+ * Applications may override this method to send JPEG messages somewhere
+ * other than stderr.
+ *
+ * On Windows, printing to stderr is generally completely useless,
+ * so we provide optional code to produce an error-dialog popup.
+ * Most Windows applications will still prefer to override this routine,
+ * but if they don't, it'll do something at least marginally useful.
+ *
+ * NOTE: to use the library in an environment that doesn't support the
+ * C stdio library, you may have to delete the call to fprintf() entirely,
+ * not just not use this routine.
+ */
+
+METHODDEF(void)
+output_message (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+
+ /* Create the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+#ifdef USE_WINDOWS_MESSAGEBOX
+ /* Display it in a message dialog box */
+ MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
+ MB_OK | MB_ICONERROR);
+#else
+ /* Send it to stderr, adding a newline */
+ fprintf(stderr, "%s\n", buffer);
+#endif
+}
+
+
+/*
+ * Decide whether to emit a trace or warning message.
+ * msg_level is one of:
+ * -1: recoverable corrupt-data warning, may want to abort.
+ * 0: important advisory messages (always display to user).
+ * 1: first level of tracing detail.
+ * 2,3,...: successively more detailed tracing messages.
+ * An application might override this method if it wanted to abort on warnings
+ * or change the policy about which messages to display.
+ */
+
+METHODDEF(void)
+emit_message (j_common_ptr cinfo, int msg_level)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+
+ if (msg_level < 0) {
+ /* It's a warning message. Since corrupt files may generate many warnings,
+ * the policy implemented here is to show only the first warning,
+ * unless trace_level >= 3.
+ */
+ if (err->num_warnings == 0 || err->trace_level >= 3)
+ (*err->output_message) (cinfo);
+ /* Always count warnings in num_warnings. */
+ err->num_warnings++;
+ } else {
+ /* It's a trace message. Show it if trace_level >= msg_level. */
+ if (err->trace_level >= msg_level)
+ (*err->output_message) (cinfo);
+ }
+}
+
+
+/*
+ * Format a message string for the most recent JPEG error or message.
+ * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
+ * characters. Note that no '\n' character is added to the string.
+ * Few applications should need to override this method.
+ */
+
+METHODDEF(void)
+format_message (j_common_ptr cinfo, char * buffer)
+{
+ struct jpeg_error_mgr * err = cinfo->err;
+ int msg_code = err->msg_code;
+ const char * msgtext = NULL;
+ const char * msgptr;
+ char ch;
+ boolean isstring;
+
+ /* Look up message string in proper table */
+ if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
+ msgtext = err->jpeg_message_table[msg_code];
+ } else if (err->addon_message_table != NULL &&
+ msg_code >= err->first_addon_message &&
+ msg_code <= err->last_addon_message) {
+ msgtext = err->addon_message_table[msg_code - err->first_addon_message];
+ }
+
+ /* Defend against bogus message number */
+ if (msgtext == NULL) {
+ err->msg_parm.i[0] = msg_code;
+ msgtext = err->jpeg_message_table[0];
+ }
+
+ /* Check for string parameter, as indicated by %s in the message text */
+ isstring = FALSE;
+ msgptr = msgtext;
+ while ((ch = *msgptr++) != '\0') {
+ if (ch == '%') {
+ if (*msgptr == 's') isstring = TRUE;
+ break;
+ }
+ }
+
+ /* Format the message into the passed buffer */
+ if (isstring)
+ sprintf(buffer, msgtext, err->msg_parm.s);
+ else
+ sprintf(buffer, msgtext,
+ err->msg_parm.i[0], err->msg_parm.i[1],
+ err->msg_parm.i[2], err->msg_parm.i[3],
+ err->msg_parm.i[4], err->msg_parm.i[5],
+ err->msg_parm.i[6], err->msg_parm.i[7]);
+}
+
+
+/*
+ * Reset error state variables at start of a new image.
+ * This is called during compression startup to reset trace/error
+ * processing to default state, without losing any application-specific
+ * method pointers. An application might possibly want to override
+ * this method if it has additional error processing state.
+ */
+
+METHODDEF(void)
+reset_error_mgr (j_common_ptr cinfo)
+{
+ cinfo->err->num_warnings = 0;
+ /* trace_level is not reset since it is an application-supplied parameter */
+ cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
+}
+
+
+/*
+ * Fill in the standard error-handling methods in a jpeg_error_mgr object.
+ * Typical call is:
+ * struct jpeg_compress_struct cinfo;
+ * struct jpeg_error_mgr err;
+ *
+ * cinfo.err = jpeg_std_error(&err);
+ * after which the application may override some of the methods.
+ */
+
+GLOBAL(struct jpeg_error_mgr *)
+jpeg_std_error (struct jpeg_error_mgr * err)
+{
+ err->error_exit = error_exit;
+ err->emit_message = emit_message;
+ err->output_message = output_message;
+ err->format_message = format_message;
+ err->reset_error_mgr = reset_error_mgr;
+
+ err->trace_level = 0; /* default = no tracing */
+ err->num_warnings = 0; /* no warnings emitted yet */
+ err->msg_code = 0; /* may be useful as a flag for "no error" */
+
+ /* Initialize message table pointers */
+ err->jpeg_message_table = jpeg_std_message_table;
+ err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
+
+ err->addon_message_table = NULL;
+ err->first_addon_message = 0; /* for safety */
+ err->last_addon_message = 0;
+
+ return err;
+}
diff --git a/Source/LibJPEG/jerror.h b/Source/LibJPEG/jerror.h
new file mode 100644
index 0000000..1cfb2b1
--- /dev/null
+++ b/Source/LibJPEG/jerror.h
@@ -0,0 +1,304 @@
+/*
+ * jerror.h
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * Modified 1997-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the error and message codes for the JPEG library.
+ * Edit this file to add new codes, or to translate the message strings to
+ * some other language.
+ * A set of error-reporting macros are defined too. Some applications using
+ * the JPEG library may wish to include this file to get the error codes
+ * and/or the macros.
+ */
+
+/*
+ * To define the enum list of message codes, include this file without
+ * defining macro JMESSAGE. To create a message string table, include it
+ * again with a suitable JMESSAGE definition (see jerror.c for an example).
+ */
+#ifndef JMESSAGE
+#ifndef JERROR_H
+/* First time through, define the enum list */
+#define JMAKE_ENUM_LIST
+#else
+/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
+#define JMESSAGE(code,string)
+#endif /* JERROR_H */
+#endif /* JMESSAGE */
+
+#ifdef JMAKE_ENUM_LIST
+
+typedef enum {
+
+#define JMESSAGE(code,string) code ,
+
+#endif /* JMAKE_ENUM_LIST */
+
+JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
+
+/* For maintenance convenience, list is alphabetical by message code name */
+JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
+JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
+JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
+JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
+JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
+JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
+JMESSAGE(JERR_BAD_DCTSIZE, "DCT scaled block size %dx%d not supported")
+JMESSAGE(JERR_BAD_DROP_SAMPLING,
+ "Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
+JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
+JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
+JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
+JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
+JMESSAGE(JERR_BAD_LIB_VERSION,
+ "Wrong JPEG library version: library is %d, caller expects %d")
+JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
+JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
+JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
+JMESSAGE(JERR_BAD_PROGRESSION,
+ "Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
+JMESSAGE(JERR_BAD_PROG_SCRIPT,
+ "Invalid progressive parameters at scan script entry %d")
+JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
+JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
+JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
+JMESSAGE(JERR_BAD_STRUCT_SIZE,
+ "JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
+JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
+JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
+JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
+JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
+JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
+JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
+JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
+JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
+JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
+JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
+JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
+JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
+JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
+JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
+JMESSAGE(JERR_FILE_READ, "Input file read error")
+JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
+JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
+JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
+JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
+JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
+JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
+JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
+JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
+ "Cannot transcode due to multiple use of quantization table %d")
+JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
+JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
+JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
+JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
+JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
+JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
+JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
+JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
+JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
+JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
+JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
+JMESSAGE(JERR_QUANT_COMPONENTS,
+ "Cannot quantize more than %d color components")
+JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
+JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
+JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
+JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
+JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
+JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
+JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
+JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
+JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
+JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
+JMESSAGE(JERR_TFILE_WRITE,
+ "Write failed on temporary file --- out of disk space?")
+JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
+JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
+JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
+JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
+JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
+JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
+JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
+JMESSAGE(JMSG_VERSION, JVERSION)
+JMESSAGE(JTRC_16BIT_TABLES,
+ "Caution: quantization tables are too coarse for baseline JPEG")
+JMESSAGE(JTRC_ADOBE,
+ "Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
+JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
+JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
+JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
+JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
+JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
+JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
+JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
+JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
+JMESSAGE(JTRC_EOI, "End Of Image")
+JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
+JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
+JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
+ "Warning: thumbnail image size does not match data length %u")
+JMESSAGE(JTRC_JFIF_EXTENSION,
+ "JFIF extension marker: type 0x%02x, length %u")
+JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
+JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
+JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
+JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
+JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
+JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
+JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
+JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
+JMESSAGE(JTRC_RST, "RST%d")
+JMESSAGE(JTRC_SMOOTH_NOTIMPL,
+ "Smoothing not supported with nonstandard sampling ratios")
+JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
+JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
+JMESSAGE(JTRC_SOI, "Start of Image")
+JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
+JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
+JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
+JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
+JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
+JMESSAGE(JTRC_THUMB_JPEG,
+ "JFIF extension marker: JPEG-compressed thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_PALETTE,
+ "JFIF extension marker: palette thumbnail image, length %u")
+JMESSAGE(JTRC_THUMB_RGB,
+ "JFIF extension marker: RGB thumbnail image, length %u")
+JMESSAGE(JTRC_UNKNOWN_IDS,
+ "Unrecognized component IDs %d %d %d, assuming YCbCr")
+JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
+JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
+JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
+JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
+JMESSAGE(JWRN_BOGUS_PROGRESSION,
+ "Inconsistent progression sequence for component %d coefficient %d")
+JMESSAGE(JWRN_EXTRANEOUS_DATA,
+ "Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
+JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
+JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
+JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
+JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
+JMESSAGE(JWRN_MUST_RESYNC,
+ "Corrupt JPEG data: found marker 0x%02x instead of RST%d")
+JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
+JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
+
+#ifdef JMAKE_ENUM_LIST
+
+ JMSG_LASTMSGCODE
+} J_MESSAGE_CODE;
+
+#undef JMAKE_ENUM_LIST
+#endif /* JMAKE_ENUM_LIST */
+
+/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
+#undef JMESSAGE
+
+
+#ifndef JERROR_H
+#define JERROR_H
+
+/* Macros to simplify using the error and trace message stuff */
+/* The first parameter is either type of cinfo pointer */
+
+/* Fatal errors (print message and exit) */
+#define ERREXIT(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT3(cinfo,code,p1,p2,p3) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (cinfo)->err->msg_parm.i[3] = (p4), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXIT6(cinfo,code,p1,p2,p3,p4,p5,p6) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (cinfo)->err->msg_parm.i[2] = (p3), \
+ (cinfo)->err->msg_parm.i[3] = (p4), \
+ (cinfo)->err->msg_parm.i[4] = (p5), \
+ (cinfo)->err->msg_parm.i[5] = (p6), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+#define ERREXITS(cinfo,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
+
+#define MAKESTMT(stuff) do { stuff } while (0)
+
+/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
+#define WARNMS(cinfo,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS1(cinfo,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+#define WARNMS2(cinfo,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
+
+/* Informational/debugging messages */
+#define TRACEMS(cinfo,lvl,code) \
+ ((cinfo)->err->msg_code = (code), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS1(cinfo,lvl,code,p1) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS2(cinfo,lvl,code,p1,p2) \
+ ((cinfo)->err->msg_code = (code), \
+ (cinfo)->err->msg_parm.i[0] = (p1), \
+ (cinfo)->err->msg_parm.i[1] = (p2), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
+ MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
+ _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
+ _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
+ (cinfo)->err->msg_code = (code); \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
+#define TRACEMSS(cinfo,lvl,code,str) \
+ ((cinfo)->err->msg_code = (code), \
+ strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
+ (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
+
+#endif /* JERROR_H */
diff --git a/Source/LibJPEG/jfdctflt.c b/Source/LibJPEG/jfdctflt.c
new file mode 100644
index 0000000..74d0d86
--- /dev/null
+++ b/Source/LibJPEG/jfdctflt.c
@@ -0,0 +1,174 @@
+/*
+ * jfdctflt.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2003-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * This implementation should be more accurate than either of the integer
+ * DCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_float (FAST_FLOAT * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z1, z2, z3, z4, z5, z11, z13;
+ FAST_FLOAT *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Load data into workspace */
+ tmp0 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]));
+ tmp7 = (FAST_FLOAT) (GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]));
+ tmp1 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]));
+ tmp6 = (FAST_FLOAT) (GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]));
+ tmp2 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]));
+ tmp5 = (FAST_FLOAT) (GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]));
+ tmp3 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]));
+ tmp4 = (FAST_FLOAT) (GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]));
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = (tmp12 + tmp13) * ((FAST_FLOAT) 0.707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = (tmp10 - tmp12) * ((FAST_FLOAT) 0.382683433); /* c6 */
+ z2 = ((FAST_FLOAT) 0.541196100) * tmp10 + z5; /* c2-c6 */
+ z4 = ((FAST_FLOAT) 1.306562965) * tmp12 + z5; /* c2+c6 */
+ z3 = tmp11 * ((FAST_FLOAT) 0.707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/Source/LibJPEG/jfdctfst.c b/Source/LibJPEG/jfdctfst.c
new file mode 100644
index 0000000..8cad5f2
--- /dev/null
+++ b/Source/LibJPEG/jfdctfst.c
@@ -0,0 +1,230 @@
+/*
+ * jfdctfst.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * Modified 2003-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jfdctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * Again to save a few shifts, the intermediate results between pass 1 and
+ * pass 2 are not upscaled, but are represented only to integral precision.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#define CONST_BITS 8
+
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_0_382683433 ((INT32) 98) /* FIX(0.382683433) */
+#define FIX_0_541196100 ((INT32) 139) /* FIX(0.541196100) */
+#define FIX_0_707106781 ((INT32) 181) /* FIX(0.707106781) */
+#define FIX_1_306562965 ((INT32) 334) /* FIX(1.306562965) */
+#else
+#define FIX_0_382683433 FIX(0.382683433)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_707106781 FIX(0.707106781)
+#define FIX_1_306562965 FIX(1.306562965)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_ifast (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z1, z2, z3, z4, z5, z11, z13;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Load data into workspace */
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
+ tmp7 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]);
+ tmp6 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]);
+ tmp5 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]);
+ tmp4 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]);
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = tmp10 + tmp11 - 8 * CENTERJSAMPLE; /* phase 3 */
+ dataptr[4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[2] = tmp13 + z1; /* phase 5 */
+ dataptr[6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[5] = z13 + z2; /* phase 6 */
+ dataptr[3] = z13 - z2;
+ dataptr[1] = z11 + z4;
+ dataptr[7] = z11 - z4;
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns. */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ /* Even part */
+
+ tmp10 = tmp0 + tmp3; /* phase 2 */
+ tmp13 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp1 - tmp2;
+
+ dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */
+ dataptr[DCTSIZE*4] = tmp10 - tmp11;
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_707106781); /* c4 */
+ dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */
+ dataptr[DCTSIZE*6] = tmp13 - z1;
+
+ /* Odd part */
+
+ tmp10 = tmp4 + tmp5; /* phase 2 */
+ tmp11 = tmp5 + tmp6;
+ tmp12 = tmp6 + tmp7;
+
+ /* The rotator is modified from fig 4-8 to avoid extra negations. */
+ z5 = MULTIPLY(tmp10 - tmp12, FIX_0_382683433); /* c6 */
+ z2 = MULTIPLY(tmp10, FIX_0_541196100) + z5; /* c2-c6 */
+ z4 = MULTIPLY(tmp12, FIX_1_306562965) + z5; /* c2+c6 */
+ z3 = MULTIPLY(tmp11, FIX_0_707106781); /* c4 */
+
+ z11 = tmp7 + z3; /* phase 5 */
+ z13 = tmp7 - z3;
+
+ dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */
+ dataptr[DCTSIZE*3] = z13 - z2;
+ dataptr[DCTSIZE*1] = z11 + z4;
+ dataptr[DCTSIZE*7] = z11 - z4;
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/Source/LibJPEG/jfdctint.c b/Source/LibJPEG/jfdctint.c
new file mode 100644
index 0000000..1dde58c
--- /dev/null
+++ b/Source/LibJPEG/jfdctint.c
@@ -0,0 +1,4348 @@
+/*
+ * jfdctint.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * Modification developed 2003-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * forward DCT (Discrete Cosine Transform).
+ *
+ * A 2-D DCT can be done by 1-D DCT on each row followed by 1-D DCT
+ * on each column. Direct algorithms are also available, but they are
+ * much more complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ *
+ * We also provide FDCT routines with various input sample block sizes for
+ * direct resolution reduction or enlargement and for direct resolving the
+ * common 2x1 and 1x2 subsampling cases without additional resampling: NxN
+ * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 output DCT block.
+ *
+ * For N<8 we fill the remaining block coefficients with zero.
+ * For N>8 we apply a partial N-point FDCT on the input samples, computing
+ * just the lower 8 frequency coefficients and discarding the rest.
+ *
+ * We must scale the output coefficients of the N-point FDCT appropriately
+ * to the standard 8-point FDCT level by 8/N per 1-D pass. This scaling
+ * is folded into the constant multipliers (pass 2) and/or final/initial
+ * shifting.
+ *
+ * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases
+ * since there would be too many additional constants to pre-calculate.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D DCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true DCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D DCT,
+ * because the y0 and y4 outputs need not be divided by sqrt(N).
+ * In the IJG code, this factor of 8 is removed by the quantization step
+ * (in jcdctmgr.c), NOT in this module.
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (For 12-bit sample data, the intermediate
+ * array is INT32 anyway.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/*
+ * Perform the forward DCT on one block of samples.
+ */
+
+GLOBAL(void)
+jpeg_fdct_islow (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]);
+
+ tmp10 = tmp0 + tmp3;
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065),
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM)
+ RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM)
+ RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM)
+ RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+
+ /* Add fudge factor here for final descale. */
+ tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1));
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS+PASS1_BITS-1);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS+PASS1_BITS-1);
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM)
+ RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+#ifdef DCT_SCALING_SUPPORTED
+
+
+/*
+ * Perform the forward DCT on a 7x7 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_7x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12;
+ INT32 z1, z2, z3;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* cK represents sqrt(2) * cos(K*pi/14). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 7; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]);
+ tmp3 = GETJSAMPLE(elemptr[3]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]);
+
+ z1 = tmp0 + tmp2;
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS);
+ tmp3 += tmp3;
+ z1 -= tmp3;
+ z1 -= tmp3;
+ z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */
+ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */
+ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS);
+ z1 -= z2;
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */
+ dataptr[4] = (DCTELEM)
+ DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */
+ tmp1 += tmp2;
+ tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */
+ tmp0 += tmp3;
+ tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/7)**2 = 64/49, which we fold
+ * into the constant multipliers:
+ * cK now represents sqrt(2) * cos(K*pi/14) * 64/49.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 7; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4];
+ tmp3 = dataptr[DCTSIZE*3];
+
+ tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5];
+ tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4];
+
+ z1 = tmp0 + tmp2;
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */
+ CONST_BITS+PASS1_BITS);
+ tmp3 += tmp3;
+ z1 -= tmp3;
+ z1 -= tmp3;
+ z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */
+ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS);
+ z1 -= z2;
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */
+ tmp1 += tmp2;
+ tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */
+ tmp0 += tmp3;
+ tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 6x6 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_6x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2;
+ INT32 tmp10, tmp11, tmp12;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* cK represents sqrt(2) * cos(K*pi/12). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 6; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]);
+ tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */
+ CONST_BITS-PASS1_BITS);
+
+ dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS));
+ dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS);
+ dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS));
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/6)**2 = 16/9, which we fold
+ * into the constant multipliers:
+ * cK now represents sqrt(2) * cos(K*pi/12) * 16/9.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 6; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5];
+ tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3];
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 5x5 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_5x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2;
+ INT32 tmp10, tmp11;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* cK represents sqrt(2) * cos(K*pi/10). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 5; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]);
+ tmp2 = GETJSAMPLE(elemptr[2]);
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << (PASS1_BITS+1));
+ tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */
+ tmp10 -= tmp2 << 2;
+ tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */
+ dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS-1);
+ dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS-1);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */
+
+ dataptr[1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */
+ CONST_BITS-PASS1_BITS-1);
+ dataptr[3] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */
+ CONST_BITS-PASS1_BITS-1);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/5)**2 = 64/25, which we partially
+ * fold into the constant multipliers (other part was done in pass 1):
+ * cK now represents sqrt(2) * cos(K*pi/10) * 32/25.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 5; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3];
+ tmp2 = dataptr[DCTSIZE*2];
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */
+ CONST_BITS+PASS1_BITS);
+ tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */
+ tmp10 -= tmp2 << 2;
+ tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 4x4 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_4x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1;
+ INT32 tmp10, tmp11;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We must also scale the output by (8/4)**2 = 2**2, which we add here. */
+ /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+2));
+ dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+2));
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-3);
+
+ dataptr[1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS-2);
+ dataptr[3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS-PASS1_BITS-2);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1));
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2];
+
+ tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS);
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS+PASS1_BITS-1);
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 3x3 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_3x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We scale the results further by 2**2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* cK represents sqrt(2) * cos(K*pi/6). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 3; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]);
+ tmp1 = GETJSAMPLE(elemptr[1]);
+
+ tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+2));
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */
+ CONST_BITS-PASS1_BITS-2);
+
+ /* Odd part */
+
+ dataptr[1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */
+ CONST_BITS-PASS1_BITS-2);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/3)**2 = 64/9, which we partially
+ * fold into the constant multipliers (other part was done in pass 1):
+ * cK now represents sqrt(2) * cos(K*pi/6) * 16/9.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 3; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2];
+ tmp1 = dataptr[DCTSIZE*1];
+
+ tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 2x2 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_2x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ JSAMPROW elemptr;
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+
+ /* Row 0 */
+ elemptr = sample_data[0] + start_col;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]);
+ tmp1 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]);
+
+ /* Row 1 */
+ elemptr = sample_data[1] + start_col;
+
+ tmp2 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[1]);
+ tmp3 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[1]);
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/2)**2 = 2**4.
+ */
+
+ /* Column 0 */
+ /* Apply unsigned->signed conversion */
+ data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp2 - 4 * CENTERJSAMPLE) << 4);
+ data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp2) << 4);
+
+ /* Column 1 */
+ data[DCTSIZE*0+1] = (DCTELEM) ((tmp1 + tmp3) << 4);
+ data[DCTSIZE*1+1] = (DCTELEM) ((tmp1 - tmp3) << 4);
+}
+
+
+/*
+ * Perform the forward DCT on a 1x1 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_1x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* We leave the result scaled up by an overall factor of 8. */
+ /* We must also scale the output by (8/1)**2 = 2**6. */
+ /* Apply unsigned->signed conversion */
+ data[0] = (DCTELEM)
+ ((GETJSAMPLE(sample_data[0][start_col]) - CENTERJSAMPLE) << 6);
+}
+
+
+/*
+ * Perform the forward DCT on a 9x9 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_9x9 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2;
+ DCTELEM workspace[8];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* we scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* cK represents sqrt(2) * cos(K*pi/18). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[8]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[7]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[6]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[5]);
+ tmp4 = GETJSAMPLE(elemptr[4]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[8]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[7]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[6]);
+ tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[5]);
+
+ z1 = tmp0 + tmp2 + tmp3;
+ z2 = tmp1 + tmp4;
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) ((z1 + z2 - 9 * CENTERJSAMPLE) << 1);
+ dataptr[6] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 - z2 - z2, FIX(0.707106781)), /* c6 */
+ CONST_BITS-1);
+ z1 = MULTIPLY(tmp0 - tmp2, FIX(1.328926049)); /* c2 */
+ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(0.707106781)); /* c6 */
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.083350441)) /* c4 */
+ + z1 + z2, CONST_BITS-1);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.245575608)) /* c8 */
+ + z1 - z2, CONST_BITS-1);
+
+ /* Odd part */
+
+ dataptr[3] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.224744871)), /* c3 */
+ CONST_BITS-1);
+
+ tmp11 = MULTIPLY(tmp11, FIX(1.224744871)); /* c3 */
+ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(0.909038955)); /* c5 */
+ tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.483689525)); /* c7 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS-1);
+
+ tmp2 = MULTIPLY(tmp12 - tmp13, FIX(1.392728481)); /* c1 */
+
+ dataptr[5] = (DCTELEM) DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS-1);
+ dataptr[7] = (DCTELEM) DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS-1);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 9)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/9)**2 = 64/81, which we partially
+ * fold into the constant multipliers and final/initial shifting:
+ * cK now represents sqrt(2) * cos(K*pi/18) * 128/81.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*0];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*7];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*6];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*5];
+ tmp4 = dataptr[DCTSIZE*4];
+
+ tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*0];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*7];
+ tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*6];
+ tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*5];
+
+ z1 = tmp0 + tmp2 + tmp3;
+ z2 = tmp1 + tmp4;
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 + z2, FIX(1.580246914)), /* 128/81 */
+ CONST_BITS+2);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 - z2 - z2, FIX(1.117403309)), /* c6 */
+ CONST_BITS+2);
+ z1 = MULTIPLY(tmp0 - tmp2, FIX(2.100031287)); /* c2 */
+ z2 = MULTIPLY(tmp1 - tmp4 - tmp4, FIX(1.117403309)); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2 - tmp3, FIX(1.711961190)) /* c4 */
+ + z1 + z2, CONST_BITS+2);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp3 - tmp0, FIX(0.388070096)) /* c8 */
+ + z1 - z2, CONST_BITS+2);
+
+ /* Odd part */
+
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12 - tmp13, FIX(1.935399303)), /* c3 */
+ CONST_BITS+2);
+
+ tmp11 = MULTIPLY(tmp11, FIX(1.935399303)); /* c3 */
+ tmp0 = MULTIPLY(tmp10 + tmp12, FIX(1.436506004)); /* c5 */
+ tmp1 = MULTIPLY(tmp10 + tmp13, FIX(0.764348879)); /* c7 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp11 + tmp0 + tmp1, CONST_BITS+2);
+
+ tmp2 = MULTIPLY(tmp12 - tmp13, FIX(2.200854883)); /* c1 */
+
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp0 - tmp11 - tmp2, CONST_BITS+2);
+ dataptr[DCTSIZE*7] = (DCTELEM)
+ DESCALE(tmp1 - tmp11 + tmp2, CONST_BITS+2);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 10x10 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_10x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ DCTELEM workspace[8*2];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* we scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* cK represents sqrt(2) * cos(K*pi/20). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]);
+ tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]);
+
+ tmp10 = tmp0 + tmp4;
+ tmp13 = tmp0 - tmp4;
+ tmp11 = tmp1 + tmp3;
+ tmp14 = tmp1 - tmp3;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << 1);
+ tmp12 += tmp12;
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */
+ MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */
+ CONST_BITS-1);
+ tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */
+ CONST_BITS-1);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */
+ CONST_BITS-1);
+
+ /* Odd part */
+
+ tmp10 = tmp0 + tmp4;
+ tmp11 = tmp1 - tmp3;
+ dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << 1);
+ tmp2 <<= CONST_BITS;
+ dataptr[1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */
+ MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */
+ MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */
+ MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */
+ CONST_BITS-1);
+ tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */
+ MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */
+ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */
+ (tmp11 << (CONST_BITS - 1)) - tmp2;
+ dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-1);
+ dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-1);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 10)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/10)**2 = 16/25, which we partially
+ * fold into the constant multipliers and final/initial shifting:
+ * cK now represents sqrt(2) * cos(K*pi/20) * 32/25.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0];
+ tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6];
+ tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5];
+
+ tmp10 = tmp0 + tmp4;
+ tmp13 = tmp0 - tmp4;
+ tmp11 = tmp1 + tmp3;
+ tmp14 = tmp1 - tmp3;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7];
+ tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6];
+ tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */
+ CONST_BITS+2);
+ tmp12 += tmp12;
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */
+ MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */
+ CONST_BITS+2);
+ tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */
+ CONST_BITS+2);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */
+ CONST_BITS+2);
+
+ /* Odd part */
+
+ tmp10 = tmp0 + tmp4;
+ tmp11 = tmp1 - tmp3;
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */
+ CONST_BITS+2);
+ tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */
+ MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */
+ MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */
+ MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */
+ CONST_BITS+2);
+ tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */
+ MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */
+ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */
+ MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+2);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+2);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on an 11x11 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_11x11 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 z1, z2, z3;
+ DCTELEM workspace[8*3];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* we scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* cK represents sqrt(2) * cos(K*pi/22). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[10]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[9]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[8]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[7]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[6]);
+ tmp5 = GETJSAMPLE(elemptr[5]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[10]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[9]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[8]);
+ tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[7]);
+ tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[6]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 - 11 * CENTERJSAMPLE) << 1);
+ tmp5 += tmp5;
+ tmp0 -= tmp5;
+ tmp1 -= tmp5;
+ tmp2 -= tmp5;
+ tmp3 -= tmp5;
+ tmp4 -= tmp5;
+ z1 = MULTIPLY(tmp0 + tmp3, FIX(1.356927976)) + /* c2 */
+ MULTIPLY(tmp2 + tmp4, FIX(0.201263574)); /* c10 */
+ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.926112931)); /* c6 */
+ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.189712156)); /* c4 */
+ dataptr[2] = (DCTELEM)
+ DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.018300590)) /* c2+c8-c6 */
+ - MULTIPLY(tmp4, FIX(1.390975730)), /* c4+c10 */
+ CONST_BITS-1);
+ dataptr[4] = (DCTELEM)
+ DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.062335650)) /* c4-c6-c10 */
+ - MULTIPLY(tmp2, FIX(1.356927976)) /* c2 */
+ + MULTIPLY(tmp4, FIX(0.587485545)), /* c8 */
+ CONST_BITS-1);
+ dataptr[6] = (DCTELEM)
+ DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.620527200)) /* c2+c4-c6 */
+ - MULTIPLY(tmp2, FIX(0.788749120)), /* c8+c10 */
+ CONST_BITS-1);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.286413905)); /* c3 */
+ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.068791298)); /* c5 */
+ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.764581576)); /* c7 */
+ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.719967871)) /* c7+c5+c3-c1 */
+ + MULTIPLY(tmp14, FIX(0.398430003)); /* c9 */
+ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.764581576)); /* -c7 */
+ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.399818907)); /* -c1 */
+ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.276416582)) /* c9+c7+c1-c3 */
+ - MULTIPLY(tmp14, FIX(1.068791298)); /* c5 */
+ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.398430003)); /* c9 */
+ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(1.989053629)) /* c9+c5+c3-c7 */
+ + MULTIPLY(tmp14, FIX(1.399818907)); /* c1 */
+ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.305598626)) /* c1+c5-c9-c7 */
+ - MULTIPLY(tmp14, FIX(1.286413905)); /* c3 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-1);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-1);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-1);
+ dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS-1);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 11)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/11)**2 = 64/121, which we partially
+ * fold into the constant multipliers and final/initial shifting:
+ * cK now represents sqrt(2) * cos(K*pi/22) * 128/121.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*2];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*1];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*0];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*7];
+ tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*6];
+ tmp5 = dataptr[DCTSIZE*5];
+
+ tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*2];
+ tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*1];
+ tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*0];
+ tmp13 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*7];
+ tmp14 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*6];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5,
+ FIX(1.057851240)), /* 128/121 */
+ CONST_BITS+2);
+ tmp5 += tmp5;
+ tmp0 -= tmp5;
+ tmp1 -= tmp5;
+ tmp2 -= tmp5;
+ tmp3 -= tmp5;
+ tmp4 -= tmp5;
+ z1 = MULTIPLY(tmp0 + tmp3, FIX(1.435427942)) + /* c2 */
+ MULTIPLY(tmp2 + tmp4, FIX(0.212906922)); /* c10 */
+ z2 = MULTIPLY(tmp1 - tmp3, FIX(0.979689713)); /* c6 */
+ z3 = MULTIPLY(tmp0 - tmp1, FIX(1.258538479)); /* c4 */
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(z1 + z2 - MULTIPLY(tmp3, FIX(1.077210542)) /* c2+c8-c6 */
+ - MULTIPLY(tmp4, FIX(1.471445400)), /* c4+c10 */
+ CONST_BITS+2);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(z2 + z3 + MULTIPLY(tmp1, FIX(0.065941844)) /* c4-c6-c10 */
+ - MULTIPLY(tmp2, FIX(1.435427942)) /* c2 */
+ + MULTIPLY(tmp4, FIX(0.621472312)), /* c8 */
+ CONST_BITS+2);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(z1 + z3 - MULTIPLY(tmp0, FIX(1.714276708)) /* c2+c4-c6 */
+ - MULTIPLY(tmp2, FIX(0.834379234)), /* c8+c10 */
+ CONST_BITS+2);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.360834544)); /* c3 */
+ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.130622199)); /* c5 */
+ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.808813568)); /* c7 */
+ tmp0 = tmp1 + tmp2 + tmp3 - MULTIPLY(tmp10, FIX(1.819470145)) /* c7+c5+c3-c1 */
+ + MULTIPLY(tmp14, FIX(0.421479672)); /* c9 */
+ tmp4 = MULTIPLY(tmp11 + tmp12, - FIX(0.808813568)); /* -c7 */
+ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.480800167)); /* -c1 */
+ tmp1 += tmp4 + tmp5 + MULTIPLY(tmp11, FIX(1.350258864)) /* c9+c7+c1-c3 */
+ - MULTIPLY(tmp14, FIX(1.130622199)); /* c5 */
+ tmp10 = MULTIPLY(tmp12 + tmp13, FIX(0.421479672)); /* c9 */
+ tmp2 += tmp4 + tmp10 - MULTIPLY(tmp12, FIX(2.104122847)) /* c9+c5+c3-c7 */
+ + MULTIPLY(tmp14, FIX(1.480800167)); /* c1 */
+ tmp3 += tmp5 + tmp10 + MULTIPLY(tmp13, FIX(1.381129125)) /* c1+c5-c9-c7 */
+ - MULTIPLY(tmp14, FIX(1.360834544)); /* c3 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 12x12 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_12x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ DCTELEM workspace[8*4];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+ /* cK represents sqrt(2) * cos(K*pi/24). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]);
+
+ tmp10 = tmp0 + tmp5;
+ tmp13 = tmp0 - tmp5;
+ tmp11 = tmp1 + tmp4;
+ tmp14 = tmp1 - tmp4;
+ tmp12 = tmp2 + tmp3;
+ tmp15 = tmp2 - tmp3;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) (tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE);
+ dataptr[6] = (DCTELEM) (tmp13 - tmp14 - tmp15);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */
+ CONST_BITS);
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */
+ CONST_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */
+ tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */
+ tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */
+ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */
+ + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */
+ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */
+ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */
+ + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */
+ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */
+ - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */
+ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */
+ - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 12)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/12)**2 = 4/9, which we partially
+ * fold into the constant multipliers and final shifting:
+ * cK now represents sqrt(2) * cos(K*pi/24) * 8/9.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0];
+ tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7];
+ tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6];
+
+ tmp10 = tmp0 + tmp5;
+ tmp13 = tmp0 - tmp5;
+ tmp11 = tmp1 + tmp4;
+ tmp14 = tmp1 - tmp4;
+ tmp12 = tmp2 + tmp3;
+ tmp15 = tmp2 - tmp3;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0];
+ tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7];
+ tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */
+ CONST_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */
+ CONST_BITS+1);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */
+ CONST_BITS+1);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */
+ MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */
+ CONST_BITS+1);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */
+ tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */
+ tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */
+ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */
+ + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */
+ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */
+ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */
+ + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */
+ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */
+ - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */
+ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */
+ - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+1);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 13x13 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_13x13 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ INT32 z1, z2;
+ DCTELEM workspace[8*5];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+ /* cK represents sqrt(2) * cos(K*pi/26). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[12]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[11]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[10]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[9]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[8]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[7]);
+ tmp6 = GETJSAMPLE(elemptr[6]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[12]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[11]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[10]);
+ tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[9]);
+ tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[8]);
+ tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[7]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ (tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6 - 13 * CENTERJSAMPLE);
+ tmp6 += tmp6;
+ tmp0 -= tmp6;
+ tmp1 -= tmp6;
+ tmp2 -= tmp6;
+ tmp3 -= tmp6;
+ tmp4 -= tmp6;
+ tmp5 -= tmp6;
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.373119086)) + /* c2 */
+ MULTIPLY(tmp1, FIX(1.058554052)) + /* c6 */
+ MULTIPLY(tmp2, FIX(0.501487041)) - /* c10 */
+ MULTIPLY(tmp3, FIX(0.170464608)) - /* c12 */
+ MULTIPLY(tmp4, FIX(0.803364869)) - /* c8 */
+ MULTIPLY(tmp5, FIX(1.252223920)), /* c4 */
+ CONST_BITS);
+ z1 = MULTIPLY(tmp0 - tmp2, FIX(1.155388986)) - /* (c4+c6)/2 */
+ MULTIPLY(tmp3 - tmp4, FIX(0.435816023)) - /* (c2-c10)/2 */
+ MULTIPLY(tmp1 - tmp5, FIX(0.316450131)); /* (c8-c12)/2 */
+ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.096834934)) - /* (c4-c6)/2 */
+ MULTIPLY(tmp3 + tmp4, FIX(0.937303064)) + /* (c2+c10)/2 */
+ MULTIPLY(tmp1 + tmp5, FIX(0.486914739)); /* (c8+c12)/2 */
+
+ dataptr[4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.322312651)); /* c3 */
+ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(1.163874945)); /* c5 */
+ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.937797057)) + /* c7 */
+ MULTIPLY(tmp14 + tmp15, FIX(0.338443458)); /* c11 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(tmp10, FIX(2.020082300)) + /* c3+c5+c7-c1 */
+ MULTIPLY(tmp14, FIX(0.318774355)); /* c9-c11 */
+ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.937797057)) - /* c7 */
+ MULTIPLY(tmp11 + tmp12, FIX(0.338443458)); /* c11 */
+ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(1.163874945)); /* -c5 */
+ tmp1 += tmp4 + tmp5 +
+ MULTIPLY(tmp11, FIX(0.837223564)) - /* c5+c9+c11-c3 */
+ MULTIPLY(tmp14, FIX(2.341699410)); /* c1+c7 */
+ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.657217813)); /* -c9 */
+ tmp2 += tmp4 + tmp6 -
+ MULTIPLY(tmp12, FIX(1.572116027)) + /* c1+c5-c9-c11 */
+ MULTIPLY(tmp15, FIX(2.260109708)); /* c3+c7 */
+ tmp3 += tmp5 + tmp6 +
+ MULTIPLY(tmp13, FIX(2.205608352)) - /* c3+c5+c9-c7 */
+ MULTIPLY(tmp15, FIX(1.742345811)); /* c1+c11 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 13)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/13)**2 = 64/169, which we partially
+ * fold into the constant multipliers and final shifting:
+ * cK now represents sqrt(2) * cos(K*pi/26) * 128/169.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*4];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*3];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*2];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*1];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*0];
+ tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*7];
+ tmp6 = dataptr[DCTSIZE*6];
+
+ tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*4];
+ tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*3];
+ tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*2];
+ tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*1];
+ tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*0];
+ tmp15 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*7];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 + tmp1 + tmp2 + tmp3 + tmp4 + tmp5 + tmp6,
+ FIX(0.757396450)), /* 128/169 */
+ CONST_BITS+1);
+ tmp6 += tmp6;
+ tmp0 -= tmp6;
+ tmp1 -= tmp6;
+ tmp2 -= tmp6;
+ tmp3 -= tmp6;
+ tmp4 -= tmp6;
+ tmp5 -= tmp6;
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.039995521)) + /* c2 */
+ MULTIPLY(tmp1, FIX(0.801745081)) + /* c6 */
+ MULTIPLY(tmp2, FIX(0.379824504)) - /* c10 */
+ MULTIPLY(tmp3, FIX(0.129109289)) - /* c12 */
+ MULTIPLY(tmp4, FIX(0.608465700)) - /* c8 */
+ MULTIPLY(tmp5, FIX(0.948429952)), /* c4 */
+ CONST_BITS+1);
+ z1 = MULTIPLY(tmp0 - tmp2, FIX(0.875087516)) - /* (c4+c6)/2 */
+ MULTIPLY(tmp3 - tmp4, FIX(0.330085509)) - /* (c2-c10)/2 */
+ MULTIPLY(tmp1 - tmp5, FIX(0.239678205)); /* (c8-c12)/2 */
+ z2 = MULTIPLY(tmp0 + tmp2, FIX(0.073342435)) - /* (c4-c6)/2 */
+ MULTIPLY(tmp3 + tmp4, FIX(0.709910013)) + /* (c2+c10)/2 */
+ MULTIPLY(tmp1 + tmp5, FIX(0.368787494)); /* (c8+c12)/2 */
+
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - z2, CONST_BITS+1);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.001514908)); /* c3 */
+ tmp2 = MULTIPLY(tmp10 + tmp12, FIX(0.881514751)); /* c5 */
+ tmp3 = MULTIPLY(tmp10 + tmp13, FIX(0.710284161)) + /* c7 */
+ MULTIPLY(tmp14 + tmp15, FIX(0.256335874)); /* c11 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(tmp10, FIX(1.530003162)) + /* c3+c5+c7-c1 */
+ MULTIPLY(tmp14, FIX(0.241438564)); /* c9-c11 */
+ tmp4 = MULTIPLY(tmp14 - tmp15, FIX(0.710284161)) - /* c7 */
+ MULTIPLY(tmp11 + tmp12, FIX(0.256335874)); /* c11 */
+ tmp5 = MULTIPLY(tmp11 + tmp13, - FIX(0.881514751)); /* -c5 */
+ tmp1 += tmp4 + tmp5 +
+ MULTIPLY(tmp11, FIX(0.634110155)) - /* c5+c9+c11-c3 */
+ MULTIPLY(tmp14, FIX(1.773594819)); /* c1+c7 */
+ tmp6 = MULTIPLY(tmp12 + tmp13, - FIX(0.497774438)); /* -c9 */
+ tmp2 += tmp4 + tmp6 -
+ MULTIPLY(tmp12, FIX(1.190715098)) + /* c1+c5-c9-c11 */
+ MULTIPLY(tmp15, FIX(1.711799069)); /* c3+c7 */
+ tmp3 += tmp5 + tmp6 +
+ MULTIPLY(tmp13, FIX(1.670519935)) - /* c3+c5+c9-c7 */
+ MULTIPLY(tmp15, FIX(1.319646532)); /* c1+c11 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+1);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 14x14 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_14x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ DCTELEM workspace[8*6];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+ /* cK represents sqrt(2) * cos(K*pi/28). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]);
+ tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]);
+ tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]);
+
+ tmp10 = tmp0 + tmp6;
+ tmp14 = tmp0 - tmp6;
+ tmp11 = tmp1 + tmp5;
+ tmp15 = tmp1 - tmp5;
+ tmp12 = tmp2 + tmp4;
+ tmp16 = tmp2 - tmp4;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]);
+ tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ (tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE);
+ tmp13 += tmp13;
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */
+ MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */
+ MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */
+ CONST_BITS);
+
+ tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */
+
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */
+ + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */
+ CONST_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */
+ - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */
+ CONST_BITS);
+
+ /* Odd part */
+
+ tmp10 = tmp1 + tmp2;
+ tmp11 = tmp5 - tmp4;
+ dataptr[7] = (DCTELEM) (tmp0 - tmp10 + tmp3 - tmp11 - tmp6);
+ tmp3 <<= CONST_BITS;
+ tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */
+ tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */
+ tmp10 += tmp11 - tmp3;
+ tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */
+ MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */
+ dataptr[5] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */
+ + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */
+ CONST_BITS);
+ tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */
+ MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */
+ dataptr[3] = (DCTELEM)
+ DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */
+ - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */
+ CONST_BITS);
+ dataptr[1] = (DCTELEM)
+ DESCALE(tmp11 + tmp12 + tmp3 + tmp6 -
+ MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */
+ CONST_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 14)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/14)**2 = 16/49, which we partially
+ * fold into the constant multipliers and final shifting:
+ * cK now represents sqrt(2) * cos(K*pi/28) * 32/49.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3];
+ tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1];
+ tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0];
+ tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7];
+
+ tmp10 = tmp0 + tmp6;
+ tmp14 = tmp0 - tmp6;
+ tmp11 = tmp1 + tmp5;
+ tmp15 = tmp1 - tmp5;
+ tmp12 = tmp2 + tmp4;
+ tmp16 = tmp2 - tmp4;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2];
+ tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1];
+ tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0];
+ tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13,
+ FIX(0.653061224)), /* 32/49 */
+ CONST_BITS+1);
+ tmp13 += tmp13;
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */
+ MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */
+ MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */
+ CONST_BITS+1);
+
+ tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */
+
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */
+ + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */
+ CONST_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */
+ - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */
+ CONST_BITS+1);
+
+ /* Odd part */
+
+ tmp10 = tmp1 + tmp2;
+ tmp11 = tmp5 - tmp4;
+ dataptr[DCTSIZE*7] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6,
+ FIX(0.653061224)), /* 32/49 */
+ CONST_BITS+1);
+ tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */
+ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */
+ tmp10 += tmp11 - tmp3;
+ tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */
+ MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */
+ + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */
+ CONST_BITS+1);
+ tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */
+ MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */
+ - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */
+ CONST_BITS+1);
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp11 + tmp12 + tmp3
+ - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */
+ - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */
+ CONST_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 15x15 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_15x15 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 z1, z2, z3;
+ DCTELEM workspace[8*7];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+ /* cK represents sqrt(2) * cos(K*pi/30). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[14]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[13]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[12]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[11]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[10]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[9]);
+ tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[8]);
+ tmp7 = GETJSAMPLE(elemptr[7]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[14]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[13]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[12]);
+ tmp13 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[11]);
+ tmp14 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[10]);
+ tmp15 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[9]);
+ tmp16 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[8]);
+
+ z1 = tmp0 + tmp4 + tmp5;
+ z2 = tmp1 + tmp3 + tmp6;
+ z3 = tmp2 + tmp7;
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) (z1 + z2 + z3 - 15 * CENTERJSAMPLE);
+ z3 += z3;
+ dataptr[6] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 - z3, FIX(1.144122806)) - /* c6 */
+ MULTIPLY(z2 - z3, FIX(0.437016024)), /* c12 */
+ CONST_BITS);
+ tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7;
+ z1 = MULTIPLY(tmp3 - tmp2, FIX(1.531135173)) - /* c2+c14 */
+ MULTIPLY(tmp6 - tmp2, FIX(2.238241955)); /* c4+c8 */
+ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.798468008)) - /* c8-c14 */
+ MULTIPLY(tmp0 - tmp2, FIX(0.091361227)); /* c2-c4 */
+ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.383309603)) + /* c2 */
+ MULTIPLY(tmp6 - tmp5, FIX(0.946293579)) + /* c8 */
+ MULTIPLY(tmp1 - tmp4, FIX(0.790569415)); /* (c6+c12)/2 */
+
+ dataptr[2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS);
+ dataptr[4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS);
+
+ /* Odd part */
+
+ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16,
+ FIX(1.224744871)); /* c5 */
+ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.344997024)) + /* c3 */
+ MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.831253876)); /* c9 */
+ tmp12 = MULTIPLY(tmp12, FIX(1.224744871)); /* c5 */
+ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.406466353)) + /* c1 */
+ MULTIPLY(tmp11 + tmp14, FIX(1.344997024)) + /* c3 */
+ MULTIPLY(tmp13 + tmp15, FIX(0.575212477)); /* c11 */
+ tmp0 = MULTIPLY(tmp13, FIX(0.475753014)) - /* c7-c11 */
+ MULTIPLY(tmp14, FIX(0.513743148)) + /* c3-c9 */
+ MULTIPLY(tmp16, FIX(1.700497885)) + tmp4 + tmp12; /* c1+c13 */
+ tmp3 = MULTIPLY(tmp10, - FIX(0.355500862)) - /* -(c1-c7) */
+ MULTIPLY(tmp11, FIX(2.176250899)) - /* c3+c9 */
+ MULTIPLY(tmp15, FIX(0.869244010)) + tmp4 - tmp12; /* c11+c13 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp3, CONST_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 15)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/15)**2 = 64/225, which we partially
+ * fold into the constant multipliers and final shifting:
+ * cK now represents sqrt(2) * cos(K*pi/30) * 256/225.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*6];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*5];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*4];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*3];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*2];
+ tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*1];
+ tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*0];
+ tmp7 = dataptr[DCTSIZE*7];
+
+ tmp10 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*6];
+ tmp11 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*5];
+ tmp12 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*4];
+ tmp13 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*3];
+ tmp14 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*2];
+ tmp15 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*1];
+ tmp16 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*0];
+
+ z1 = tmp0 + tmp4 + tmp5;
+ z2 = tmp1 + tmp3 + tmp6;
+ z3 = tmp2 + tmp7;
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 + z2 + z3, FIX(1.137777778)), /* 256/225 */
+ CONST_BITS+2);
+ z3 += z3;
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 - z3, FIX(1.301757503)) - /* c6 */
+ MULTIPLY(z2 - z3, FIX(0.497227121)), /* c12 */
+ CONST_BITS+2);
+ tmp2 += ((tmp1 + tmp4) >> 1) - tmp7 - tmp7;
+ z1 = MULTIPLY(tmp3 - tmp2, FIX(1.742091575)) - /* c2+c14 */
+ MULTIPLY(tmp6 - tmp2, FIX(2.546621957)); /* c4+c8 */
+ z2 = MULTIPLY(tmp5 - tmp2, FIX(0.908479156)) - /* c8-c14 */
+ MULTIPLY(tmp0 - tmp2, FIX(0.103948774)); /* c2-c4 */
+ z3 = MULTIPLY(tmp0 - tmp3, FIX(1.573898926)) + /* c2 */
+ MULTIPLY(tmp6 - tmp5, FIX(1.076671805)) + /* c8 */
+ MULTIPLY(tmp1 - tmp4, FIX(0.899492312)); /* (c6+c12)/2 */
+
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z3, CONST_BITS+2);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(z2 + z3, CONST_BITS+2);
+
+ /* Odd part */
+
+ tmp2 = MULTIPLY(tmp10 - tmp12 - tmp13 + tmp15 + tmp16,
+ FIX(1.393487498)); /* c5 */
+ tmp1 = MULTIPLY(tmp10 - tmp14 - tmp15, FIX(1.530307725)) + /* c3 */
+ MULTIPLY(tmp11 - tmp13 - tmp16, FIX(0.945782187)); /* c9 */
+ tmp12 = MULTIPLY(tmp12, FIX(1.393487498)); /* c5 */
+ tmp4 = MULTIPLY(tmp10 - tmp16, FIX(1.600246161)) + /* c1 */
+ MULTIPLY(tmp11 + tmp14, FIX(1.530307725)) + /* c3 */
+ MULTIPLY(tmp13 + tmp15, FIX(0.654463974)); /* c11 */
+ tmp0 = MULTIPLY(tmp13, FIX(0.541301207)) - /* c7-c11 */
+ MULTIPLY(tmp14, FIX(0.584525538)) + /* c3-c9 */
+ MULTIPLY(tmp16, FIX(1.934788705)) + tmp4 + tmp12; /* c1+c13 */
+ tmp3 = MULTIPLY(tmp10, - FIX(0.404480980)) - /* -(c1-c7) */
+ MULTIPLY(tmp11, FIX(2.476089912)) - /* c3+c9 */
+ MULTIPLY(tmp15, FIX(0.989006518)) + tmp4 - tmp12; /* c11+c13 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+2);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+2);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+2);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3, CONST_BITS+2);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 16x16 sample block.
+ */
+
+GLOBAL(void)
+jpeg_fdct_16x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17;
+ DCTELEM workspace[DCTSIZE2];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* cK represents sqrt(2) * cos(K*pi/32). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]);
+ tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]);
+ tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]);
+
+ tmp10 = tmp0 + tmp7;
+ tmp14 = tmp0 - tmp7;
+ tmp11 = tmp1 + tmp6;
+ tmp15 = tmp1 - tmp6;
+ tmp12 = tmp2 + tmp5;
+ tmp16 = tmp2 - tmp5;
+ tmp13 = tmp3 + tmp4;
+ tmp17 = tmp3 - tmp4;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]);
+ tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]);
+ tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */
+ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */
+ CONST_BITS-PASS1_BITS);
+
+ tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */
+ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */
+ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */
+ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */
+ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */
+ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */
+ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */
+ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */
+ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */
+ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */
+ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */
+ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */
+ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */
+ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */
+ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */
+ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */
+ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */
+ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */
+ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */
+ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == DCTSIZE * 2)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/16)**2 = 1/2**2.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3];
+ tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2];
+ tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1];
+ tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0];
+
+ tmp10 = tmp0 + tmp7;
+ tmp14 = tmp0 - tmp7;
+ tmp11 = tmp1 + tmp6;
+ tmp15 = tmp1 - tmp6;
+ tmp12 = tmp2 + tmp5;
+ tmp16 = tmp2 - tmp5;
+ tmp13 = tmp3 + tmp4;
+ tmp17 = tmp3 - tmp4;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3];
+ tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2];
+ tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1];
+ tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+2);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */
+ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */
+ CONST_BITS+PASS1_BITS+2);
+
+ tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */
+ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */
+ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+10 */
+ CONST_BITS+PASS1_BITS+2);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */
+ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */
+ CONST_BITS+PASS1_BITS+2);
+
+ /* Odd part */
+
+ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */
+ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */
+ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */
+ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */
+ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */
+ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */
+ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */
+ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */
+ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */
+ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */
+ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */
+ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */
+ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */
+ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */
+ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */
+ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */
+ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+2);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+2);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+2);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+2);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 16x8 sample block.
+ *
+ * 16-point FDCT in pass 1 (rows), 8-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_16x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17;
+ INT32 z1;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32). */
+
+ dataptr = data;
+ ctr = 0;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[15]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[14]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[13]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[12]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[11]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[10]);
+ tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[9]);
+ tmp7 = GETJSAMPLE(elemptr[7]) + GETJSAMPLE(elemptr[8]);
+
+ tmp10 = tmp0 + tmp7;
+ tmp14 = tmp0 - tmp7;
+ tmp11 = tmp1 + tmp6;
+ tmp15 = tmp1 - tmp6;
+ tmp12 = tmp2 + tmp5;
+ tmp16 = tmp2 - tmp5;
+ tmp13 = tmp3 + tmp4;
+ tmp17 = tmp3 - tmp4;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[15]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[14]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[13]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[12]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[11]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[10]);
+ tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[9]);
+ tmp7 = GETJSAMPLE(elemptr[7]) - GETJSAMPLE(elemptr[8]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 + tmp13 - 16 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */
+ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */
+ CONST_BITS-PASS1_BITS);
+
+ tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */
+ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */
+ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */
+ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */
+ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */
+ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */
+ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */
+ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */
+ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */
+ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */
+ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */
+ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */
+ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */
+ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */
+ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */
+ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */
+ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */
+ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */
+ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */
+ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by 8/16 = 1/2.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+
+ tmp10 = tmp0 + tmp3;
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) DESCALE(tmp10 + tmp11, PASS1_BITS+1);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp10 - tmp11, PASS1_BITS+1);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865),
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065),
+ CONST_BITS+PASS1_BITS+1);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12,
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13,
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12,
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13,
+ CONST_BITS+PASS1_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 14x7 sample block.
+ *
+ * 14-point FDCT in pass 1 (rows), 7-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_14x7 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 z1, z2, z3;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Zero bottom row of output coefficient block. */
+ MEMZERO(&data[DCTSIZE*7], SIZEOF(DCTELEM) * DCTSIZE);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 7; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[13]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[12]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[11]);
+ tmp13 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[10]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[9]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[8]);
+ tmp6 = GETJSAMPLE(elemptr[6]) + GETJSAMPLE(elemptr[7]);
+
+ tmp10 = tmp0 + tmp6;
+ tmp14 = tmp0 - tmp6;
+ tmp11 = tmp1 + tmp5;
+ tmp15 = tmp1 - tmp5;
+ tmp12 = tmp2 + tmp4;
+ tmp16 = tmp2 - tmp4;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[13]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[12]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[11]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[10]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[9]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[8]);
+ tmp6 = GETJSAMPLE(elemptr[6]) - GETJSAMPLE(elemptr[7]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 + tmp13 - 14 * CENTERJSAMPLE) << PASS1_BITS);
+ tmp13 += tmp13;
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.274162392)) + /* c4 */
+ MULTIPLY(tmp11 - tmp13, FIX(0.314692123)) - /* c12 */
+ MULTIPLY(tmp12 - tmp13, FIX(0.881747734)), /* c8 */
+ CONST_BITS-PASS1_BITS);
+
+ tmp10 = MULTIPLY(tmp14 + tmp15, FIX(1.105676686)); /* c6 */
+
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.273079590)) /* c2-c6 */
+ + MULTIPLY(tmp16, FIX(0.613604268)), /* c10 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.719280954)) /* c6+c10 */
+ - MULTIPLY(tmp16, FIX(1.378756276)), /* c2 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = tmp1 + tmp2;
+ tmp11 = tmp5 - tmp4;
+ dataptr[7] = (DCTELEM) ((tmp0 - tmp10 + tmp3 - tmp11 - tmp6) << PASS1_BITS);
+ tmp3 <<= CONST_BITS;
+ tmp10 = MULTIPLY(tmp10, - FIX(0.158341681)); /* -c13 */
+ tmp11 = MULTIPLY(tmp11, FIX(1.405321284)); /* c1 */
+ tmp10 += tmp11 - tmp3;
+ tmp11 = MULTIPLY(tmp0 + tmp2, FIX(1.197448846)) + /* c5 */
+ MULTIPLY(tmp4 + tmp6, FIX(0.752406978)); /* c9 */
+ dataptr[5] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(2.373959773)) /* c3+c5-c13 */
+ + MULTIPLY(tmp4, FIX(1.119999435)), /* c1+c11-c9 */
+ CONST_BITS-PASS1_BITS);
+ tmp12 = MULTIPLY(tmp0 + tmp1, FIX(1.334852607)) + /* c3 */
+ MULTIPLY(tmp5 - tmp6, FIX(0.467085129)); /* c11 */
+ dataptr[3] = (DCTELEM)
+ DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.424103948)) /* c3-c9-c13 */
+ - MULTIPLY(tmp5, FIX(3.069855259)), /* c1+c5+c11 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[1] = (DCTELEM)
+ DESCALE(tmp11 + tmp12 + tmp3 + tmp6 -
+ MULTIPLY(tmp0 + tmp6, FIX(1.126980169)), /* c3+c5-c1 */
+ CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/14)*(8/7) = 32/49, which we
+ * partially fold into the constant multipliers and final shifting:
+ * 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14) * 64/49.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*6];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*5];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*4];
+ tmp3 = dataptr[DCTSIZE*3];
+
+ tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*6];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*5];
+ tmp12 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*4];
+
+ z1 = tmp0 + tmp2;
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(z1 + tmp1 + tmp3, FIX(1.306122449)), /* 64/49 */
+ CONST_BITS+PASS1_BITS+1);
+ tmp3 += tmp3;
+ z1 -= tmp3;
+ z1 -= tmp3;
+ z1 = MULTIPLY(z1, FIX(0.461784020)); /* (c2+c6-c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp2, FIX(1.202428084)); /* (c2+c4-c6)/2 */
+ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.411026446)); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS+PASS1_BITS+1);
+ z1 -= z2;
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(1.151670509)); /* c4 */
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.923568041)), /* c2+c6-c4 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS+PASS1_BITS+1);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(1.221765677)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.222383464)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.800824523)); /* -c1 */
+ tmp1 += tmp2;
+ tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.801442310)); /* c5 */
+ tmp0 += tmp3;
+ tmp2 += tmp3 + MULTIPLY(tmp12, FIX(2.443531355)); /* c3+c1-c5 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp0, CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp1, CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp2, CONST_BITS+PASS1_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 12x6 sample block.
+ *
+ * 12-point FDCT in pass 1 (rows), 6-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_12x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Zero 2 bottom rows of output coefficient block. */
+ MEMZERO(&data[DCTSIZE*6], SIZEOF(DCTELEM) * DCTSIZE * 2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 6; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[11]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[10]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[9]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[8]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[7]);
+ tmp5 = GETJSAMPLE(elemptr[5]) + GETJSAMPLE(elemptr[6]);
+
+ tmp10 = tmp0 + tmp5;
+ tmp13 = tmp0 - tmp5;
+ tmp11 = tmp1 + tmp4;
+ tmp14 = tmp1 - tmp4;
+ tmp12 = tmp2 + tmp3;
+ tmp15 = tmp2 - tmp3;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[11]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[10]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[9]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[8]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[7]);
+ tmp5 = GETJSAMPLE(elemptr[5]) - GETJSAMPLE(elemptr[6]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 - 12 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[6] = (DCTELEM) ((tmp13 - tmp14 - tmp15) << PASS1_BITS);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.224744871)), /* c4 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp14 - tmp15 + MULTIPLY(tmp13 + tmp15, FIX(1.366025404)), /* c2 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp1 + tmp4, FIX_0_541196100); /* c9 */
+ tmp14 = tmp10 + MULTIPLY(tmp1, FIX_0_765366865); /* c3-c9 */
+ tmp15 = tmp10 - MULTIPLY(tmp4, FIX_1_847759065); /* c3+c9 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.121971054)); /* c5 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.860918669)); /* c7 */
+ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.580774953)) /* c5+c7-c1 */
+ + MULTIPLY(tmp5, FIX(0.184591911)); /* c11 */
+ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.184591911)); /* -c11 */
+ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.339493912)) /* c1+c5-c11 */
+ + MULTIPLY(tmp5, FIX(0.860918669)); /* c7 */
+ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.725788011)) /* c1+c11-c7 */
+ - MULTIPLY(tmp5, FIX(1.121971054)); /* c5 */
+ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.306562965)) /* c3 */
+ - MULTIPLY(tmp2 + tmp5, FIX_0_541196100); /* c9 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp10, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp11, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp13, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/12)*(8/6) = 8/9, which we
+ * partially fold into the constant multipliers and final shifting:
+ * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5];
+ tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3];
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */
+ CONST_BITS+PASS1_BITS+1);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 10x5 sample block.
+ *
+ * 10-point FDCT in pass 1 (rows), 5-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_10x5 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Zero 3 bottom rows of output coefficient block. */
+ MEMZERO(&data[DCTSIZE*5], SIZEOF(DCTELEM) * DCTSIZE * 3);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 5; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[9]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[8]);
+ tmp12 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[7]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[6]);
+ tmp4 = GETJSAMPLE(elemptr[4]) + GETJSAMPLE(elemptr[5]);
+
+ tmp10 = tmp0 + tmp4;
+ tmp13 = tmp0 - tmp4;
+ tmp11 = tmp1 + tmp3;
+ tmp14 = tmp1 - tmp3;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[9]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[8]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[7]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[6]);
+ tmp4 = GETJSAMPLE(elemptr[4]) - GETJSAMPLE(elemptr[5]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 + tmp12 - 10 * CENTERJSAMPLE) << PASS1_BITS);
+ tmp12 += tmp12;
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.144122806)) - /* c4 */
+ MULTIPLY(tmp11 - tmp12, FIX(0.437016024)), /* c8 */
+ CONST_BITS-PASS1_BITS);
+ tmp10 = MULTIPLY(tmp13 + tmp14, FIX(0.831253876)); /* c6 */
+ dataptr[2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.513743148)), /* c2-c6 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.176250899)), /* c2+c6 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = tmp0 + tmp4;
+ tmp11 = tmp1 - tmp3;
+ dataptr[5] = (DCTELEM) ((tmp10 - tmp11 - tmp2) << PASS1_BITS);
+ tmp2 <<= CONST_BITS;
+ dataptr[1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.396802247)) + /* c1 */
+ MULTIPLY(tmp1, FIX(1.260073511)) + tmp2 + /* c3 */
+ MULTIPLY(tmp3, FIX(0.642039522)) + /* c7 */
+ MULTIPLY(tmp4, FIX(0.221231742)), /* c9 */
+ CONST_BITS-PASS1_BITS);
+ tmp12 = MULTIPLY(tmp0 - tmp4, FIX(0.951056516)) - /* (c3+c7)/2 */
+ MULTIPLY(tmp1 + tmp3, FIX(0.587785252)); /* (c1-c9)/2 */
+ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.309016994)) + /* (c3-c7)/2 */
+ (tmp11 << (CONST_BITS - 1)) - tmp2;
+ dataptr[3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS-PASS1_BITS);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/10)*(8/5) = 32/25, which we
+ * fold into the constant multipliers:
+ * 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10) * 32/25.
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*4];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*3];
+ tmp2 = dataptr[DCTSIZE*2];
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*4];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*3];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp2, FIX(1.28)), /* 32/25 */
+ CONST_BITS+PASS1_BITS);
+ tmp11 = MULTIPLY(tmp11, FIX(1.011928851)); /* (c2+c4)/2 */
+ tmp10 -= tmp2 << 2;
+ tmp10 = MULTIPLY(tmp10, FIX(0.452548340)); /* (c2-c4)/2 */
+ dataptr[DCTSIZE*2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(1.064004961)); /* c3 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.657591230)), /* c1-c3 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.785601151)), /* c1+c3 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on an 8x4 sample block.
+ *
+ * 8-point FDCT in pass 1 (rows), 4-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_8x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Zero 4 bottom rows of output coefficient block. */
+ MEMZERO(&data[DCTSIZE*4], SIZEOF(DCTELEM) * DCTSIZE * 4);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We must also scale the output by 8/4 = 2, which we add here. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]);
+
+ tmp10 = tmp0 + tmp3;
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << (PASS1_BITS+1));
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << (PASS1_BITS+1));
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-2);
+ dataptr[2] = (DCTELEM) RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS-1);
+ dataptr[6] = (DCTELEM) RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065),
+ CONST_BITS-PASS1_BITS-1);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-2);
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS-1);
+ dataptr[3] = (DCTELEM)
+ RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS-1);
+ dataptr[5] = (DCTELEM)
+ RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS-1);
+ dataptr[7] = (DCTELEM)
+ RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS-1);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
+
+ dataptr = data;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3] + (ONE << (PASS1_BITS-1));
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2];
+
+ tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS);
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS+PASS1_BITS-1);
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 6x3 sample block.
+ *
+ * 6-point FDCT in pass 1 (rows), 3-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_6x3 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2;
+ INT32 tmp10, tmp11, tmp12;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 3; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]);
+ tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << (PASS1_BITS+1));
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */
+ CONST_BITS-PASS1_BITS-1);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */
+ CONST_BITS-PASS1_BITS-1);
+
+ /* Odd part */
+
+ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */
+ CONST_BITS-PASS1_BITS-1);
+
+ dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << (PASS1_BITS+1)));
+ dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << (PASS1_BITS+1));
+ dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << (PASS1_BITS+1)));
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially
+ * fold into the constant multipliers (other part was done in pass 1):
+ * 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6) * 16/9.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 6; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*2];
+ tmp1 = dataptr[DCTSIZE*1];
+
+ tmp2 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*2];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(1.257078722)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2, FIX(2.177324216)), /* c1 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 4x2 sample block.
+ *
+ * 4-point FDCT in pass 1 (rows), 2-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_4x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1;
+ INT32 tmp10, tmp11;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We must also scale the output by (8/4)*(8/2) = 2**3, which we add here. */
+ /* 4-point FDCT kernel, */
+ /* cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT]. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 2; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+3));
+ dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+3));
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-4);
+
+ dataptr[1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS-3);
+ dataptr[3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS-PASS1_BITS-3);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = dataptr[DCTSIZE*0] + (ONE << (PASS1_BITS-1));
+ tmp1 = dataptr[DCTSIZE*1];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp0 + tmp1, PASS1_BITS);
+
+ /* Odd part */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) RIGHT_SHIFT(tmp0 - tmp1, PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 2x1 sample block.
+ *
+ * 2-point FDCT in pass 1 (rows), 1-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_2x1 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1;
+ JSAMPROW elemptr;
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ elemptr = sample_data[0] + start_col;
+
+ tmp0 = GETJSAMPLE(elemptr[0]);
+ tmp1 = GETJSAMPLE(elemptr[1]);
+
+ /* We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/2)*(8/1) = 2**5.
+ */
+
+ /* Even part */
+ /* Apply unsigned->signed conversion */
+ data[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5);
+
+ /* Odd part */
+ data[1] = (DCTELEM) ((tmp0 - tmp1) << 5);
+}
+
+
+/*
+ * Perform the forward DCT on an 8x16 sample block.
+ *
+ * 8-point FDCT in pass 1 (rows), 16-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_8x16 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16, tmp17;
+ INT32 z1;
+ DCTELEM workspace[DCTSIZE2];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) + GETJSAMPLE(elemptr[4]);
+
+ tmp10 = tmp0 + tmp3;
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[7]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[6]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[5]);
+ tmp3 = GETJSAMPLE(elemptr[3]) - GETJSAMPLE(elemptr[4]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) ((tmp10 + tmp11 - 8 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[4] = (DCTELEM) ((tmp10 - tmp11) << PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ dataptr[2] = (DCTELEM) DESCALE(z1 + MULTIPLY(tmp12, FIX_0_765366865),
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 - MULTIPLY(tmp13, FIX_1_847759065),
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0 + tmp10 + tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1 + tmp11 + tmp13, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2 + tmp11 + tmp12, CONST_BITS-PASS1_BITS);
+ dataptr[7] = (DCTELEM) DESCALE(tmp3 + tmp10 + tmp13, CONST_BITS-PASS1_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == DCTSIZE * 2)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by 8/16 = 1/2.
+ * 16-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/32).
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = DCTSIZE-1; ctr >= 0; ctr--) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*3];
+ tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*2];
+ tmp6 = dataptr[DCTSIZE*6] + wsptr[DCTSIZE*1];
+ tmp7 = dataptr[DCTSIZE*7] + wsptr[DCTSIZE*0];
+
+ tmp10 = tmp0 + tmp7;
+ tmp14 = tmp0 - tmp7;
+ tmp11 = tmp1 + tmp6;
+ tmp15 = tmp1 - tmp6;
+ tmp12 = tmp2 + tmp5;
+ tmp16 = tmp2 - tmp5;
+ tmp13 = tmp3 + tmp4;
+ tmp17 = tmp3 - tmp4;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*4];
+ tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*3];
+ tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*2];
+ tmp6 = dataptr[DCTSIZE*6] - wsptr[DCTSIZE*1];
+ tmp7 = dataptr[DCTSIZE*7] - wsptr[DCTSIZE*0];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 + tmp12 + tmp13, PASS1_BITS+1);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(1.306562965)) + /* c4[16] = c2[8] */
+ MULTIPLY(tmp11 - tmp12, FIX_0_541196100), /* c12[16] = c6[8] */
+ CONST_BITS+PASS1_BITS+1);
+
+ tmp10 = MULTIPLY(tmp17 - tmp15, FIX(0.275899379)) + /* c14[16] = c7[8] */
+ MULTIPLY(tmp14 - tmp16, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp15, FIX(1.451774982)) /* c6+c14 */
+ + MULTIPLY(tmp16, FIX(2.172734804)), /* c2+c10 */
+ CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(0.211164243)) /* c2-c6 */
+ - MULTIPLY(tmp17, FIX(1.061594338)), /* c10+c14 */
+ CONST_BITS+PASS1_BITS+1);
+
+ /* Odd part */
+
+ tmp11 = MULTIPLY(tmp0 + tmp1, FIX(1.353318001)) + /* c3 */
+ MULTIPLY(tmp6 - tmp7, FIX(0.410524528)); /* c13 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(1.247225013)) + /* c5 */
+ MULTIPLY(tmp5 + tmp7, FIX(0.666655658)); /* c11 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(1.093201867)) + /* c7 */
+ MULTIPLY(tmp4 - tmp7, FIX(0.897167586)); /* c9 */
+ tmp14 = MULTIPLY(tmp1 + tmp2, FIX(0.138617169)) + /* c15 */
+ MULTIPLY(tmp6 - tmp5, FIX(1.407403738)); /* c1 */
+ tmp15 = MULTIPLY(tmp1 + tmp3, - FIX(0.666655658)) + /* -c11 */
+ MULTIPLY(tmp4 + tmp6, - FIX(1.247225013)); /* -c5 */
+ tmp16 = MULTIPLY(tmp2 + tmp3, - FIX(1.353318001)) + /* -c3 */
+ MULTIPLY(tmp5 - tmp4, FIX(0.410524528)); /* c13 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(tmp0, FIX(2.286341144)) + /* c7+c5+c3-c1 */
+ MULTIPLY(tmp7, FIX(0.779653625)); /* c15+c13-c11+c9 */
+ tmp11 += tmp14 + tmp15 + MULTIPLY(tmp1, FIX(0.071888074)) /* c9-c3-c15+c11 */
+ - MULTIPLY(tmp6, FIX(1.663905119)); /* c7+c13+c1-c5 */
+ tmp12 += tmp14 + tmp16 - MULTIPLY(tmp2, FIX(1.125726048)) /* c7+c5+c15-c3 */
+ + MULTIPLY(tmp5, FIX(1.227391138)); /* c9-c11+c1-c13 */
+ tmp13 += tmp15 + tmp16 + MULTIPLY(tmp3, FIX(1.065388962)) /* c15+c3+c11-c7 */
+ + MULTIPLY(tmp4, FIX(2.167985692)); /* c1+c13+c5-c9 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS+1);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS+1);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 7x14 sample block.
+ *
+ * 7-point FDCT in pass 1 (rows), 14-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_7x14 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 z1, z2, z3;
+ DCTELEM workspace[8*6];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 7-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/14). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[6]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[5]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[4]);
+ tmp3 = GETJSAMPLE(elemptr[3]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[6]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[5]);
+ tmp12 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[4]);
+
+ z1 = tmp0 + tmp2;
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((z1 + tmp1 + tmp3 - 7 * CENTERJSAMPLE) << PASS1_BITS);
+ tmp3 += tmp3;
+ z1 -= tmp3;
+ z1 -= tmp3;
+ z1 = MULTIPLY(z1, FIX(0.353553391)); /* (c2+c6-c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp2, FIX(0.920609002)); /* (c2+c4-c6)/2 */
+ z3 = MULTIPLY(tmp1 - tmp2, FIX(0.314692123)); /* c6 */
+ dataptr[2] = (DCTELEM) DESCALE(z1 + z2 + z3, CONST_BITS-PASS1_BITS);
+ z1 -= z2;
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.881747734)); /* c4 */
+ dataptr[4] = (DCTELEM)
+ DESCALE(z2 + z3 - MULTIPLY(tmp1 - tmp3, FIX(0.707106781)), /* c2+c6-c4 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[6] = (DCTELEM) DESCALE(z1 + z2, CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp1 = MULTIPLY(tmp10 + tmp11, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(tmp10 - tmp11, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(tmp11 + tmp12, - FIX(1.378756276)); /* -c1 */
+ tmp1 += tmp2;
+ tmp3 = MULTIPLY(tmp10 + tmp12, FIX(0.613604268)); /* c5 */
+ tmp0 += tmp3;
+ tmp2 += tmp3 + MULTIPLY(tmp12, FIX(1.870828693)); /* c3+c1-c5 */
+
+ dataptr[1] = (DCTELEM) DESCALE(tmp0, CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM) DESCALE(tmp1, CONST_BITS-PASS1_BITS);
+ dataptr[5] = (DCTELEM) DESCALE(tmp2, CONST_BITS-PASS1_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 14)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/7)*(8/14) = 32/49, which we
+ * fold into the constant multipliers:
+ * 14-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/28) * 32/49.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 7; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*3];
+ tmp13 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*2];
+ tmp4 = dataptr[DCTSIZE*4] + wsptr[DCTSIZE*1];
+ tmp5 = dataptr[DCTSIZE*5] + wsptr[DCTSIZE*0];
+ tmp6 = dataptr[DCTSIZE*6] + dataptr[DCTSIZE*7];
+
+ tmp10 = tmp0 + tmp6;
+ tmp14 = tmp0 - tmp6;
+ tmp11 = tmp1 + tmp5;
+ tmp15 = tmp1 - tmp5;
+ tmp12 = tmp2 + tmp4;
+ tmp16 = tmp2 - tmp4;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*3];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*2];
+ tmp4 = dataptr[DCTSIZE*4] - wsptr[DCTSIZE*1];
+ tmp5 = dataptr[DCTSIZE*5] - wsptr[DCTSIZE*0];
+ tmp6 = dataptr[DCTSIZE*6] - dataptr[DCTSIZE*7];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12 + tmp13,
+ FIX(0.653061224)), /* 32/49 */
+ CONST_BITS+PASS1_BITS);
+ tmp13 += tmp13;
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp13, FIX(0.832106052)) + /* c4 */
+ MULTIPLY(tmp11 - tmp13, FIX(0.205513223)) - /* c12 */
+ MULTIPLY(tmp12 - tmp13, FIX(0.575835255)), /* c8 */
+ CONST_BITS+PASS1_BITS);
+
+ tmp10 = MULTIPLY(tmp14 + tmp15, FIX(0.722074570)); /* c6 */
+
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp14, FIX(0.178337691)) /* c2-c6 */
+ + MULTIPLY(tmp16, FIX(0.400721155)), /* c10 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp15, FIX(1.122795725)) /* c6+c10 */
+ - MULTIPLY(tmp16, FIX(0.900412262)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = tmp1 + tmp2;
+ tmp11 = tmp5 - tmp4;
+ dataptr[DCTSIZE*7] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp10 + tmp3 - tmp11 - tmp6,
+ FIX(0.653061224)), /* 32/49 */
+ CONST_BITS+PASS1_BITS);
+ tmp3 = MULTIPLY(tmp3 , FIX(0.653061224)); /* 32/49 */
+ tmp10 = MULTIPLY(tmp10, - FIX(0.103406812)); /* -c13 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.917760839)); /* c1 */
+ tmp10 += tmp11 - tmp3;
+ tmp11 = MULTIPLY(tmp0 + tmp2, FIX(0.782007410)) + /* c5 */
+ MULTIPLY(tmp4 + tmp6, FIX(0.491367823)); /* c9 */
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp10 + tmp11 - MULTIPLY(tmp2, FIX(1.550341076)) /* c3+c5-c13 */
+ + MULTIPLY(tmp4, FIX(0.731428202)), /* c1+c11-c9 */
+ CONST_BITS+PASS1_BITS);
+ tmp12 = MULTIPLY(tmp0 + tmp1, FIX(0.871740478)) + /* c3 */
+ MULTIPLY(tmp5 - tmp6, FIX(0.305035186)); /* c11 */
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(tmp10 + tmp12 - MULTIPLY(tmp1, FIX(0.276965844)) /* c3-c9-c13 */
+ - MULTIPLY(tmp5, FIX(2.004803435)), /* c1+c5+c11 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp11 + tmp12 + tmp3
+ - MULTIPLY(tmp0, FIX(0.735987049)) /* c3+c5-c1 */
+ - MULTIPLY(tmp6, FIX(0.082925825)), /* c9-c11-c13 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 6x12 sample block.
+ *
+ * 6-point FDCT in pass 1 (rows), 12-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_6x12 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ DCTELEM workspace[8*4];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[5]);
+ tmp11 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) + GETJSAMPLE(elemptr[3]);
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[5]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[4]);
+ tmp2 = GETJSAMPLE(elemptr[2]) - GETJSAMPLE(elemptr[3]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp11 - 6 * CENTERJSAMPLE) << PASS1_BITS);
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(1.224744871)), /* c2 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(0.707106781)), /* c4 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = DESCALE(MULTIPLY(tmp0 + tmp2, FIX(0.366025404)), /* c5 */
+ CONST_BITS-PASS1_BITS);
+
+ dataptr[1] = (DCTELEM) (tmp10 + ((tmp0 + tmp1) << PASS1_BITS));
+ dataptr[3] = (DCTELEM) ((tmp0 - tmp1 - tmp2) << PASS1_BITS);
+ dataptr[5] = (DCTELEM) (tmp10 + ((tmp2 - tmp1) << PASS1_BITS));
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 12)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/6)*(8/12) = 8/9, which we
+ * fold into the constant multipliers:
+ * 12-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/24) * 8/9.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*3];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*2];
+ tmp2 = dataptr[DCTSIZE*2] + wsptr[DCTSIZE*1];
+ tmp3 = dataptr[DCTSIZE*3] + wsptr[DCTSIZE*0];
+ tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*7];
+ tmp5 = dataptr[DCTSIZE*5] + dataptr[DCTSIZE*6];
+
+ tmp10 = tmp0 + tmp5;
+ tmp13 = tmp0 - tmp5;
+ tmp11 = tmp1 + tmp4;
+ tmp14 = tmp1 - tmp4;
+ tmp12 = tmp2 + tmp3;
+ tmp15 = tmp2 - tmp3;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*3];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*2];
+ tmp2 = dataptr[DCTSIZE*2] - wsptr[DCTSIZE*1];
+ tmp3 = dataptr[DCTSIZE*3] - wsptr[DCTSIZE*0];
+ tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*7];
+ tmp5 = dataptr[DCTSIZE*5] - dataptr[DCTSIZE*6];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(0.888888889)), /* 8/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp13 - tmp14 - tmp15, FIX(0.888888889)), /* 8/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.088662108)), /* c4 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp14 - tmp15, FIX(0.888888889)) + /* 8/9 */
+ MULTIPLY(tmp13 + tmp15, FIX(1.214244803)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp1 + tmp4, FIX(0.481063200)); /* c9 */
+ tmp14 = tmp10 + MULTIPLY(tmp1, FIX(0.680326102)); /* c3-c9 */
+ tmp15 = tmp10 - MULTIPLY(tmp4, FIX(1.642452502)); /* c3+c9 */
+ tmp12 = MULTIPLY(tmp0 + tmp2, FIX(0.997307603)); /* c5 */
+ tmp13 = MULTIPLY(tmp0 + tmp3, FIX(0.765261039)); /* c7 */
+ tmp10 = tmp12 + tmp13 + tmp14 - MULTIPLY(tmp0, FIX(0.516244403)) /* c5+c7-c1 */
+ + MULTIPLY(tmp5, FIX(0.164081699)); /* c11 */
+ tmp11 = MULTIPLY(tmp2 + tmp3, - FIX(0.164081699)); /* -c11 */
+ tmp12 += tmp11 - tmp15 - MULTIPLY(tmp2, FIX(2.079550144)) /* c1+c5-c11 */
+ + MULTIPLY(tmp5, FIX(0.765261039)); /* c7 */
+ tmp13 += tmp11 - tmp14 + MULTIPLY(tmp3, FIX(0.645144899)) /* c1+c11-c7 */
+ - MULTIPLY(tmp5, FIX(0.997307603)); /* c5 */
+ tmp11 = tmp15 + MULTIPLY(tmp0 - tmp3, FIX(1.161389302)) /* c3 */
+ - MULTIPLY(tmp2 + tmp5, FIX(0.481063200)); /* c9 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM) DESCALE(tmp10, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp11, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM) DESCALE(tmp12, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp13, CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 5x10 sample block.
+ *
+ * 5-point FDCT in pass 1 (rows), 10-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_5x10 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4;
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ DCTELEM workspace[8*2];
+ DCTELEM *dataptr;
+ DCTELEM *wsptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* 5-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/10). */
+
+ dataptr = data;
+ ctr = 0;
+ for (;;) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[4]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[3]);
+ tmp2 = GETJSAMPLE(elemptr[2]);
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+
+ tmp0 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[4]);
+ tmp1 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[3]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp10 + tmp2 - 5 * CENTERJSAMPLE) << PASS1_BITS);
+ tmp11 = MULTIPLY(tmp11, FIX(0.790569415)); /* (c2+c4)/2 */
+ tmp10 -= tmp2 << 2;
+ tmp10 = MULTIPLY(tmp10, FIX(0.353553391)); /* (c2-c4)/2 */
+ dataptr[2] = (DCTELEM) DESCALE(tmp11 + tmp10, CONST_BITS-PASS1_BITS);
+ dataptr[4] = (DCTELEM) DESCALE(tmp11 - tmp10, CONST_BITS-PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp1, FIX(0.831253876)); /* c3 */
+
+ dataptr[1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0, FIX(0.513743148)), /* c1-c3 */
+ CONST_BITS-PASS1_BITS);
+ dataptr[3] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp1, FIX(2.176250899)), /* c1+c3 */
+ CONST_BITS-PASS1_BITS);
+
+ ctr++;
+
+ if (ctr != DCTSIZE) {
+ if (ctr == 10)
+ break; /* Done. */
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ } else
+ dataptr = workspace; /* switch pointer to extended workspace */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/5)*(8/10) = 32/25, which we
+ * fold into the constant multipliers:
+ * 10-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/20) * 32/25.
+ */
+
+ dataptr = data;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 5; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + wsptr[DCTSIZE*1];
+ tmp1 = dataptr[DCTSIZE*1] + wsptr[DCTSIZE*0];
+ tmp12 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*7];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*6];
+ tmp4 = dataptr[DCTSIZE*4] + dataptr[DCTSIZE*5];
+
+ tmp10 = tmp0 + tmp4;
+ tmp13 = tmp0 - tmp4;
+ tmp11 = tmp1 + tmp3;
+ tmp14 = tmp1 - tmp3;
+
+ tmp0 = dataptr[DCTSIZE*0] - wsptr[DCTSIZE*1];
+ tmp1 = dataptr[DCTSIZE*1] - wsptr[DCTSIZE*0];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*7];
+ tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*6];
+ tmp4 = dataptr[DCTSIZE*4] - dataptr[DCTSIZE*5];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11 + tmp12, FIX(1.28)), /* 32/25 */
+ CONST_BITS+PASS1_BITS);
+ tmp12 += tmp12;
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp12, FIX(1.464477191)) - /* c4 */
+ MULTIPLY(tmp11 - tmp12, FIX(0.559380511)), /* c8 */
+ CONST_BITS+PASS1_BITS);
+ tmp10 = MULTIPLY(tmp13 + tmp14, FIX(1.064004961)); /* c6 */
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp13, FIX(0.657591230)), /* c2-c6 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ DESCALE(tmp10 - MULTIPLY(tmp14, FIX(2.785601151)), /* c2+c6 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = tmp0 + tmp4;
+ tmp11 = tmp1 - tmp3;
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp2, FIX(1.28)), /* 32/25 */
+ CONST_BITS+PASS1_BITS);
+ tmp2 = MULTIPLY(tmp2, FIX(1.28)); /* 32/25 */
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0, FIX(1.787906876)) + /* c1 */
+ MULTIPLY(tmp1, FIX(1.612894094)) + tmp2 + /* c3 */
+ MULTIPLY(tmp3, FIX(0.821810588)) + /* c7 */
+ MULTIPLY(tmp4, FIX(0.283176630)), /* c9 */
+ CONST_BITS+PASS1_BITS);
+ tmp12 = MULTIPLY(tmp0 - tmp4, FIX(1.217352341)) - /* (c3+c7)/2 */
+ MULTIPLY(tmp1 + tmp3, FIX(0.752365123)); /* (c1-c9)/2 */
+ tmp13 = MULTIPLY(tmp10 + tmp11, FIX(0.395541753)) + /* (c3-c7)/2 */
+ MULTIPLY(tmp11, FIX(0.64)) - tmp2; /* 16/25 */
+ dataptr[DCTSIZE*3] = (DCTELEM) DESCALE(tmp12 + tmp13, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM) DESCALE(tmp12 - tmp13, CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ wsptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 4x8 sample block.
+ *
+ * 4-point FDCT in pass 1 (rows), 8-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_4x8 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We must also scale the output by 8/4 = 2, which we add here. */
+ /* 4-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[3]);
+ tmp1 = GETJSAMPLE(elemptr[1]) + GETJSAMPLE(elemptr[2]);
+
+ tmp10 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[3]);
+ tmp11 = GETJSAMPLE(elemptr[1]) - GETJSAMPLE(elemptr[2]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 - 4 * CENTERJSAMPLE) << (PASS1_BITS+1));
+ dataptr[2] = (DCTELEM) ((tmp0 - tmp1) << (PASS1_BITS+1));
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-2);
+
+ dataptr[1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS-1);
+ dataptr[3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS-PASS1_BITS-1);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ /* Even part per LL&M figure 1 --- note that published figure is faulty;
+ * rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
+ */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4];
+
+ /* Add fudge factor here for final descale. */
+ tmp10 = tmp0 + tmp3 + (ONE << (PASS1_BITS-1));
+ tmp12 = tmp0 - tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp13 = tmp1 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5];
+ tmp3 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) RIGHT_SHIFT(tmp10 + tmp11, PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM) RIGHT_SHIFT(tmp10 - tmp11, PASS1_BITS);
+
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_0_541196100);
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS+PASS1_BITS-1);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ RIGHT_SHIFT(z1 + MULTIPLY(tmp12, FIX_0_765366865), CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*6] = (DCTELEM)
+ RIGHT_SHIFT(z1 - MULTIPLY(tmp13, FIX_1_847759065), CONST_BITS+PASS1_BITS);
+
+ /* Odd part per figure 8 --- note paper omits factor of sqrt(2).
+ * 8-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ * i0..i3 in the paper are tmp0..tmp3 here.
+ */
+
+ tmp10 = tmp0 + tmp3;
+ tmp11 = tmp1 + tmp2;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp1 + tmp3;
+ z1 = MULTIPLY(tmp12 + tmp13, FIX_1_175875602); /* c3 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS+PASS1_BITS-1);
+
+ tmp0 = MULTIPLY(tmp0, FIX_1_501321110); /* c1+c3-c5-c7 */
+ tmp1 = MULTIPLY(tmp1, FIX_3_072711026); /* c1+c3+c5-c7 */
+ tmp2 = MULTIPLY(tmp2, FIX_2_053119869); /* c1+c3-c5+c7 */
+ tmp3 = MULTIPLY(tmp3, FIX_0_298631336); /* -c1+c3+c5-c7 */
+ tmp10 = MULTIPLY(tmp10, - FIX_0_899976223); /* c7-c3 */
+ tmp11 = MULTIPLY(tmp11, - FIX_2_562915447); /* -c1-c3 */
+ tmp12 = MULTIPLY(tmp12, - FIX_0_390180644); /* c5-c3 */
+ tmp13 = MULTIPLY(tmp13, - FIX_1_961570560); /* -c3-c5 */
+
+ tmp12 += z1;
+ tmp13 += z1;
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + tmp10 + tmp12, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ RIGHT_SHIFT(tmp1 + tmp11 + tmp13, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ RIGHT_SHIFT(tmp2 + tmp11 + tmp12, CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*7] = (DCTELEM)
+ RIGHT_SHIFT(tmp3 + tmp10 + tmp13, CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 3x6 sample block.
+ *
+ * 3-point FDCT in pass 1 (rows), 6-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_3x6 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1, tmp2;
+ INT32 tmp10, tmp11, tmp12;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+ /* We scale the results further by 2 as part of output adaption */
+ /* scaling for different DCT size. */
+ /* 3-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/6). */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 6; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]) + GETJSAMPLE(elemptr[2]);
+ tmp1 = GETJSAMPLE(elemptr[1]);
+
+ tmp2 = GETJSAMPLE(elemptr[0]) - GETJSAMPLE(elemptr[2]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM)
+ ((tmp0 + tmp1 - 3 * CENTERJSAMPLE) << (PASS1_BITS+1));
+ dataptr[2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp1, FIX(0.707106781)), /* c2 */
+ CONST_BITS-PASS1_BITS-1);
+
+ /* Odd part */
+
+ dataptr[1] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp2, FIX(1.224744871)), /* c1 */
+ CONST_BITS-PASS1_BITS-1);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We remove the PASS1_BITS scaling, but leave the results scaled up
+ * by an overall factor of 8.
+ * We must also scale the output by (8/6)*(8/3) = 32/9, which we partially
+ * fold into the constant multipliers (other part was done in pass 1):
+ * 6-point FDCT kernel, cK represents sqrt(2) * cos(K*pi/12) * 16/9.
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 3; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*5];
+ tmp11 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*3];
+
+ tmp10 = tmp0 + tmp2;
+ tmp12 = tmp0 - tmp2;
+
+ tmp0 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*5];
+ tmp1 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*4];
+ tmp2 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*3];
+
+ dataptr[DCTSIZE*0] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 + tmp11, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*2] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp12, FIX(2.177324216)), /* c2 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*4] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp10 - tmp11 - tmp11, FIX(1.257078722)), /* c4 */
+ CONST_BITS+PASS1_BITS);
+
+ /* Odd part */
+
+ tmp10 = MULTIPLY(tmp0 + tmp2, FIX(0.650711829)); /* c5 */
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp0 + tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ DESCALE(MULTIPLY(tmp0 - tmp1 - tmp2, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+ dataptr[DCTSIZE*5] = (DCTELEM)
+ DESCALE(tmp10 + MULTIPLY(tmp2 - tmp1, FIX(1.777777778)), /* 16/9 */
+ CONST_BITS+PASS1_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 2x4 sample block.
+ *
+ * 2-point FDCT in pass 1 (rows), 4-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_2x4 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1;
+ INT32 tmp10, tmp11;
+ DCTELEM *dataptr;
+ JSAMPROW elemptr;
+ int ctr;
+ SHIFT_TEMPS
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ /* Pass 1: process rows. */
+ /* Note results are scaled up by sqrt(8) compared to a true DCT. */
+ /* We must also scale the output by (8/2)*(8/4) = 2**3, which we add here. */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 4; ctr++) {
+ elemptr = sample_data[ctr] + start_col;
+
+ /* Even part */
+
+ tmp0 = GETJSAMPLE(elemptr[0]);
+ tmp1 = GETJSAMPLE(elemptr[1]);
+
+ /* Apply unsigned->signed conversion */
+ dataptr[0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 3);
+
+ /* Odd part */
+
+ dataptr[1] = (DCTELEM) ((tmp0 - tmp1) << 3);
+
+ dataptr += DCTSIZE; /* advance pointer to next row */
+ }
+
+ /* Pass 2: process columns.
+ * We leave the results scaled up by an overall factor of 8.
+ * 4-point FDCT kernel,
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point FDCT].
+ */
+
+ dataptr = data;
+ for (ctr = 0; ctr < 2; ctr++) {
+ /* Even part */
+
+ tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*3];
+ tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*2];
+
+ tmp10 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*3];
+ tmp11 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*2];
+
+ dataptr[DCTSIZE*0] = (DCTELEM) (tmp0 + tmp1);
+ dataptr[DCTSIZE*2] = (DCTELEM) (tmp0 - tmp1);
+
+ /* Odd part */
+
+ tmp0 = MULTIPLY(tmp10 + tmp11, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-1);
+
+ dataptr[DCTSIZE*1] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 + MULTIPLY(tmp10, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS);
+ dataptr[DCTSIZE*3] = (DCTELEM)
+ RIGHT_SHIFT(tmp0 - MULTIPLY(tmp11, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS);
+
+ dataptr++; /* advance pointer to next column */
+ }
+}
+
+
+/*
+ * Perform the forward DCT on a 1x2 sample block.
+ *
+ * 1-point FDCT in pass 1 (rows), 2-point in pass 2 (columns).
+ */
+
+GLOBAL(void)
+jpeg_fdct_1x2 (DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col)
+{
+ INT32 tmp0, tmp1;
+
+ /* Pre-zero output coefficient block. */
+ MEMZERO(data, SIZEOF(DCTELEM) * DCTSIZE2);
+
+ tmp0 = GETJSAMPLE(sample_data[0][start_col]);
+ tmp1 = GETJSAMPLE(sample_data[1][start_col]);
+
+ /* We leave the results scaled up by an overall factor of 8.
+ * We must also scale the output by (8/1)*(8/2) = 2**5.
+ */
+
+ /* Even part */
+ /* Apply unsigned->signed conversion */
+ data[DCTSIZE*0] = (DCTELEM) ((tmp0 + tmp1 - 2 * CENTERJSAMPLE) << 5);
+
+ /* Odd part */
+ data[DCTSIZE*1] = (DCTELEM) ((tmp0 - tmp1) << 5);
+}
+
+#endif /* DCT_SCALING_SUPPORTED */
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/Source/LibJPEG/jidctflt.c b/Source/LibJPEG/jidctflt.c
new file mode 100644
index 0000000..0188ce3
--- /dev/null
+++ b/Source/LibJPEG/jidctflt.c
@@ -0,0 +1,242 @@
+/*
+ * jidctflt.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a floating-point implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * This implementation should be more accurate than either of the integer
+ * IDCT implementations. However, it may not give the same results on all
+ * machines because of differences in roundoff behavior. Speed will depend
+ * on the hardware's floating point capacity.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with a fixed-point
+ * implementation, accuracy is lost due to imprecise representation of the
+ * scaled quantization values. However, that problem does not arise if
+ * we use floating point arithmetic.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_FLOAT_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a float result.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_float (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ FAST_FLOAT tmp10, tmp11, tmp12, tmp13;
+ FAST_FLOAT z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ FLOAT_MULT_TYPE * quantptr;
+ FAST_FLOAT * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (FLOAT_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = tmp0 + tmp7;
+ wsptr[DCTSIZE*7] = tmp0 - tmp7;
+ wsptr[DCTSIZE*1] = tmp1 + tmp6;
+ wsptr[DCTSIZE*6] = tmp1 - tmp6;
+ wsptr[DCTSIZE*2] = tmp2 + tmp5;
+ wsptr[DCTSIZE*5] = tmp2 - tmp5;
+ wsptr[DCTSIZE*4] = tmp3 + tmp4;
+ wsptr[DCTSIZE*3] = tmp3 - tmp4;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * And testing floats for zero is relatively expensive, so we don't bother.
+ */
+
+ /* Even part */
+
+ tmp10 = wsptr[0] + wsptr[4];
+ tmp11 = wsptr[0] - wsptr[4];
+
+ tmp13 = wsptr[2] + wsptr[6];
+ tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = wsptr[5] + wsptr[3];
+ z10 = wsptr[5] - wsptr[3];
+ z11 = wsptr[1] + wsptr[7];
+ z12 = wsptr[1] - wsptr[7];
+
+ tmp7 = z11 + z13;
+ tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562);
+
+ z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */
+ tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */
+ tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7;
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[(int) DESCALE((INT32) (tmp0 + tmp7), 3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) DESCALE((INT32) (tmp0 - tmp7), 3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) DESCALE((INT32) (tmp1 + tmp6), 3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) DESCALE((INT32) (tmp1 - tmp6), 3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) DESCALE((INT32) (tmp2 + tmp5), 3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) DESCALE((INT32) (tmp2 - tmp5), 3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) DESCALE((INT32) (tmp3 + tmp4), 3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) DESCALE((INT32) (tmp3 - tmp4), 3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_FLOAT_SUPPORTED */
diff --git a/Source/LibJPEG/jidctfst.c b/Source/LibJPEG/jidctfst.c
new file mode 100644
index 0000000..dba4216
--- /dev/null
+++ b/Source/LibJPEG/jidctfst.c
@@ -0,0 +1,368 @@
+/*
+ * jidctfst.c
+ *
+ * Copyright (C) 1994-1998, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a fast, not so accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on Arai, Agui, and Nakajima's algorithm for
+ * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in
+ * Japanese, but the algorithm is described in the Pennebaker & Mitchell
+ * JPEG textbook (see REFERENCES section in file README). The following code
+ * is based directly on figure 4-8 in P&M.
+ * While an 8-point DCT cannot be done in less than 11 multiplies, it is
+ * possible to arrange the computation so that many of the multiplies are
+ * simple scalings of the final outputs. These multiplies can then be
+ * folded into the multiplications or divisions by the JPEG quantization
+ * table entries. The AA&N method leaves only 5 multiplies and 29 adds
+ * to be done in the DCT itself.
+ * The primary disadvantage of this method is that with fixed-point math,
+ * accuracy is lost due to imprecise representation of the scaled
+ * quantization values. The smaller the quantization table entry, the less
+ * precise the scaled value, so this implementation does worse with high-
+ * quality-setting files than with low-quality ones.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_IFAST_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCTs. /* deliberate syntax err */
+#endif
+
+
+/* Scaling decisions are generally the same as in the LL&M algorithm;
+ * see jidctint.c for more details. However, we choose to descale
+ * (right shift) multiplication products as soon as they are formed,
+ * rather than carrying additional fractional bits into subsequent additions.
+ * This compromises accuracy slightly, but it lets us save a few shifts.
+ * More importantly, 16-bit arithmetic is then adequate (for 8-bit samples)
+ * everywhere except in the multiplications proper; this saves a good deal
+ * of work on 16-bit-int machines.
+ *
+ * The dequantized coefficients are not integers because the AA&N scaling
+ * factors have been incorporated. We represent them scaled up by PASS1_BITS,
+ * so that the first and second IDCT rounds have the same input scaling.
+ * For 8-bit JSAMPLEs, we choose IFAST_SCALE_BITS = PASS1_BITS so as to
+ * avoid a descaling shift; this compromises accuracy rather drastically
+ * for small quantization table entries, but it saves a lot of shifts.
+ * For 12-bit JSAMPLEs, there's no hope of using 16x16 multiplies anyway,
+ * so we use a much larger scaling factor to preserve accuracy.
+ *
+ * A final compromise is to represent the multiplicative constants to only
+ * 8 fractional bits, rather than 13. This saves some shifting work on some
+ * machines, and may also reduce the cost of multiplication (since there
+ * are fewer one-bits in the constants).
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 8
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 8
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 8
+#define FIX_1_082392200 ((INT32) 277) /* FIX(1.082392200) */
+#define FIX_1_414213562 ((INT32) 362) /* FIX(1.414213562) */
+#define FIX_1_847759065 ((INT32) 473) /* FIX(1.847759065) */
+#define FIX_2_613125930 ((INT32) 669) /* FIX(2.613125930) */
+#else
+#define FIX_1_082392200 FIX(1.082392200)
+#define FIX_1_414213562 FIX(1.414213562)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_2_613125930 FIX(2.613125930)
+#endif
+
+
+/* We can gain a little more speed, with a further compromise in accuracy,
+ * by omitting the addition in a descaling shift. This yields an incorrectly
+ * rounded result half the time...
+ */
+
+#ifndef USE_ACCURATE_ROUNDING
+#undef DESCALE
+#define DESCALE(x,n) RIGHT_SHIFT(x, n)
+#endif
+
+
+/* Multiply a DCTELEM variable by an INT32 constant, and immediately
+ * descale to yield a DCTELEM result.
+ */
+
+#define MULTIPLY(var,const) ((DCTELEM) DESCALE((var) * (const), CONST_BITS))
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce a DCTELEM result. For 8-bit data a 16x16->16
+ * multiplication will do. For 12-bit data, the multiplier table is
+ * declared INT32, so a 32-bit multiply will be used.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define DEQUANTIZE(coef,quantval) (((IFAST_MULT_TYPE) (coef)) * (quantval))
+#else
+#define DEQUANTIZE(coef,quantval) \
+ DESCALE((coef)*(quantval), IFAST_SCALE_BITS-PASS1_BITS)
+#endif
+
+
+/* Like DESCALE, but applies to a DCTELEM and produces an int.
+ * We assume that int right shift is unsigned if INT32 right shift is.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define ISHIFT_TEMPS DCTELEM ishift_temp;
+#if BITS_IN_JSAMPLE == 8
+#define DCTELEMBITS 16 /* DCTELEM may be 16 or 32 bits */
+#else
+#define DCTELEMBITS 32 /* DCTELEM must be 32 bits */
+#endif
+#define IRIGHT_SHIFT(x,shft) \
+ ((ishift_temp = (x)) < 0 ? \
+ (ishift_temp >> (shft)) | ((~((DCTELEM) 0)) << (DCTELEMBITS-(shft))) : \
+ (ishift_temp >> (shft)))
+#else
+#define ISHIFT_TEMPS
+#define IRIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+#ifdef USE_ACCURATE_ROUNDING
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT((x) + (1 << ((n)-1)), n))
+#else
+#define IDESCALE(x,n) ((int) IRIGHT_SHIFT(x, n))
+#endif
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_ifast (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ DCTELEM tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+ DCTELEM tmp10, tmp11, tmp12, tmp13;
+ DCTELEM z5, z10, z11, z12, z13;
+ JCOEFPTR inptr;
+ IFAST_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS /* for DESCALE */
+ ISHIFT_TEMPS /* for IDESCALE */
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (IFAST_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = (int) DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = tmp0 + tmp2; /* phase 3 */
+ tmp11 = tmp0 - tmp2;
+
+ tmp13 = tmp1 + tmp3; /* phases 5-3 */
+ tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
+
+ tmp0 = tmp10 + tmp13; /* phase 2 */
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z13 = tmp6 + tmp5; /* phase 6 */
+ z10 = tmp6 - tmp5;
+ z11 = tmp4 + tmp7;
+ z12 = tmp4 - tmp7;
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ wsptr[DCTSIZE*0] = (int) (tmp0 + tmp7);
+ wsptr[DCTSIZE*7] = (int) (tmp0 - tmp7);
+ wsptr[DCTSIZE*1] = (int) (tmp1 + tmp6);
+ wsptr[DCTSIZE*6] = (int) (tmp1 - tmp6);
+ wsptr[DCTSIZE*2] = (int) (tmp2 + tmp5);
+ wsptr[DCTSIZE*5] = (int) (tmp2 - tmp5);
+ wsptr[DCTSIZE*4] = (int) (tmp3 + tmp4);
+ wsptr[DCTSIZE*3] = (int) (tmp3 - tmp4);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[IDESCALE(wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part */
+
+ tmp10 = ((DCTELEM) wsptr[0] + (DCTELEM) wsptr[4]);
+ tmp11 = ((DCTELEM) wsptr[0] - (DCTELEM) wsptr[4]);
+
+ tmp13 = ((DCTELEM) wsptr[2] + (DCTELEM) wsptr[6]);
+ tmp12 = MULTIPLY((DCTELEM) wsptr[2] - (DCTELEM) wsptr[6], FIX_1_414213562)
+ - tmp13;
+
+ tmp0 = tmp10 + tmp13;
+ tmp3 = tmp10 - tmp13;
+ tmp1 = tmp11 + tmp12;
+ tmp2 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z13 = (DCTELEM) wsptr[5] + (DCTELEM) wsptr[3];
+ z10 = (DCTELEM) wsptr[5] - (DCTELEM) wsptr[3];
+ z11 = (DCTELEM) wsptr[1] + (DCTELEM) wsptr[7];
+ z12 = (DCTELEM) wsptr[1] - (DCTELEM) wsptr[7];
+
+ tmp7 = z11 + z13; /* phase 5 */
+ tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+
+ z5 = MULTIPLY(z10 + z12, FIX_1_847759065); /* 2*c2 */
+ tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5; /* 2*(c2-c6) */
+ tmp12 = MULTIPLY(z10, - FIX_2_613125930) + z5; /* -2*(c2+c6) */
+
+ tmp6 = tmp12 - tmp7; /* phase 2 */
+ tmp5 = tmp11 - tmp6;
+ tmp4 = tmp10 + tmp5;
+
+ /* Final output stage: scale down by a factor of 8 and range-limit */
+
+ outptr[0] = range_limit[IDESCALE(tmp0 + tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[IDESCALE(tmp0 - tmp7, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[IDESCALE(tmp1 + tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[IDESCALE(tmp1 - tmp6, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[IDESCALE(tmp2 + tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[IDESCALE(tmp2 - tmp5, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[IDESCALE(tmp3 + tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[IDESCALE(tmp3 - tmp4, PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#endif /* DCT_IFAST_SUPPORTED */
diff --git a/Source/LibJPEG/jidctint.c b/Source/LibJPEG/jidctint.c
new file mode 100644
index 0000000..dcdf7ce
--- /dev/null
+++ b/Source/LibJPEG/jidctint.c
@@ -0,0 +1,5137 @@
+/*
+ * jidctint.c
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * Modification developed 2002-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a slow-but-accurate integer implementation of the
+ * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine
+ * must also perform dequantization of the input coefficients.
+ *
+ * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT
+ * on each row (or vice versa, but it's more convenient to emit a row at
+ * a time). Direct algorithms are also available, but they are much more
+ * complex and seem not to be any faster when reduced to code.
+ *
+ * This implementation is based on an algorithm described in
+ * C. Loeffler, A. Ligtenberg and G. Moschytz, "Practical Fast 1-D DCT
+ * Algorithms with 11 Multiplications", Proc. Int'l. Conf. on Acoustics,
+ * Speech, and Signal Processing 1989 (ICASSP '89), pp. 988-991.
+ * The primary algorithm described there uses 11 multiplies and 29 adds.
+ * We use their alternate method with 12 multiplies and 32 adds.
+ * The advantage of this method is that no data path contains more than one
+ * multiplication; this allows a very simple and accurate implementation in
+ * scaled fixed-point arithmetic, with a minimal number of shifts.
+ *
+ * We also provide IDCT routines with various output sample block sizes for
+ * direct resolution reduction or enlargement and for direct resolving the
+ * common 2x1 and 1x2 subsampling cases without additional resampling: NxN
+ * (N=1...16), 2NxN, and Nx2N (N=1...8) pixels for one 8x8 input DCT block.
+ *
+ * For N<8 we simply take the corresponding low-frequency coefficients of
+ * the 8x8 input DCT block and apply an NxN point IDCT on the sub-block
+ * to yield the downscaled outputs.
+ * This can be seen as direct low-pass downsampling from the DCT domain
+ * point of view rather than the usual spatial domain point of view,
+ * yielding significant computational savings and results at least
+ * as good as common bilinear (averaging) spatial downsampling.
+ *
+ * For N>8 we apply a partial NxN IDCT on the 8 input coefficients as
+ * lower frequencies and higher frequencies assumed to be zero.
+ * It turns out that the computational effort is similar to the 8x8 IDCT
+ * regarding the output size.
+ * Furthermore, the scaling and descaling is the same for all IDCT sizes.
+ *
+ * CAUTION: We rely on the FIX() macro except for the N=1,2,4,8 cases
+ * since there would be too many additional constants to pre-calculate.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jdct.h" /* Private declarations for DCT subsystem */
+
+#ifdef DCT_ISLOW_SUPPORTED
+
+
+/*
+ * This module is specialized to the case DCTSIZE = 8.
+ */
+
+#if DCTSIZE != 8
+ Sorry, this code only copes with 8x8 DCT blocks. /* deliberate syntax err */
+#endif
+
+
+/*
+ * The poop on this scaling stuff is as follows:
+ *
+ * Each 1-D IDCT step produces outputs which are a factor of sqrt(N)
+ * larger than the true IDCT outputs. The final outputs are therefore
+ * a factor of N larger than desired; since N=8 this can be cured by
+ * a simple right shift at the end of the algorithm. The advantage of
+ * this arrangement is that we save two multiplications per 1-D IDCT,
+ * because the y0 and y4 inputs need not be divided by sqrt(N).
+ *
+ * We have to do addition and subtraction of the integer inputs, which
+ * is no problem, and multiplication by fractional constants, which is
+ * a problem to do in integer arithmetic. We multiply all the constants
+ * by CONST_SCALE and convert them to integer constants (thus retaining
+ * CONST_BITS bits of precision in the constants). After doing a
+ * multiplication we have to divide the product by CONST_SCALE, with proper
+ * rounding, to produce the correct output. This division can be done
+ * cheaply as a right shift of CONST_BITS bits. We postpone shifting
+ * as long as possible so that partial sums can be added together with
+ * full fractional precision.
+ *
+ * The outputs of the first pass are scaled up by PASS1_BITS bits so that
+ * they are represented to better-than-integral precision. These outputs
+ * require BITS_IN_JSAMPLE + PASS1_BITS + 3 bits; this fits in a 16-bit word
+ * with the recommended scaling. (To scale up 12-bit sample data further, an
+ * intermediate INT32 array would be needed.)
+ *
+ * To avoid overflow of the 32-bit intermediate results in pass 2, we must
+ * have BITS_IN_JSAMPLE + CONST_BITS + PASS1_BITS <= 26. Error analysis
+ * shows that the values given below are the most effective.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define CONST_BITS 13
+#define PASS1_BITS 2
+#else
+#define CONST_BITS 13
+#define PASS1_BITS 1 /* lose a little precision to avoid overflow */
+#endif
+
+/* Some C compilers fail to reduce "FIX(constant)" at compile time, thus
+ * causing a lot of useless floating-point operations at run time.
+ * To get around this we use the following pre-calculated constants.
+ * If you change CONST_BITS you may want to add appropriate values.
+ * (With a reasonable C compiler, you can just rely on the FIX() macro...)
+ */
+
+#if CONST_BITS == 13
+#define FIX_0_298631336 ((INT32) 2446) /* FIX(0.298631336) */
+#define FIX_0_390180644 ((INT32) 3196) /* FIX(0.390180644) */
+#define FIX_0_541196100 ((INT32) 4433) /* FIX(0.541196100) */
+#define FIX_0_765366865 ((INT32) 6270) /* FIX(0.765366865) */
+#define FIX_0_899976223 ((INT32) 7373) /* FIX(0.899976223) */
+#define FIX_1_175875602 ((INT32) 9633) /* FIX(1.175875602) */
+#define FIX_1_501321110 ((INT32) 12299) /* FIX(1.501321110) */
+#define FIX_1_847759065 ((INT32) 15137) /* FIX(1.847759065) */
+#define FIX_1_961570560 ((INT32) 16069) /* FIX(1.961570560) */
+#define FIX_2_053119869 ((INT32) 16819) /* FIX(2.053119869) */
+#define FIX_2_562915447 ((INT32) 20995) /* FIX(2.562915447) */
+#define FIX_3_072711026 ((INT32) 25172) /* FIX(3.072711026) */
+#else
+#define FIX_0_298631336 FIX(0.298631336)
+#define FIX_0_390180644 FIX(0.390180644)
+#define FIX_0_541196100 FIX(0.541196100)
+#define FIX_0_765366865 FIX(0.765366865)
+#define FIX_0_899976223 FIX(0.899976223)
+#define FIX_1_175875602 FIX(1.175875602)
+#define FIX_1_501321110 FIX(1.501321110)
+#define FIX_1_847759065 FIX(1.847759065)
+#define FIX_1_961570560 FIX(1.961570560)
+#define FIX_2_053119869 FIX(2.053119869)
+#define FIX_2_562915447 FIX(2.562915447)
+#define FIX_3_072711026 FIX(3.072711026)
+#endif
+
+
+/* Multiply an INT32 variable by an INT32 constant to yield an INT32 result.
+ * For 8-bit samples with the recommended scaling, all the variable
+ * and constant values involved are no more than 16 bits wide, so a
+ * 16x16->32 bit multiply can be used instead of a full 32x32 multiply.
+ * For 12-bit samples, a full 32-bit multiplication will be needed.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define MULTIPLY(var,const) MULTIPLY16C16(var,const)
+#else
+#define MULTIPLY(var,const) ((var) * (const))
+#endif
+
+
+/* Dequantize a coefficient by multiplying it by the multiplier-table
+ * entry; produce an int result. In this module, both inputs and result
+ * are 16 bits or less, so either int or short multiply will work.
+ */
+
+#define DEQUANTIZE(coef,quantval) (((ISLOW_MULT_TYPE) (coef)) * (quantval))
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients.
+ */
+
+GLOBAL(void)
+jpeg_idct_islow (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[DCTSIZE2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 <<= CONST_BITS;
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z2 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ tmp0 = z2 + z3;
+ tmp1 = z2 - z3;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < DCTSIZE; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+ /* Rows of zeroes can be exploited in the same way as we did with columns.
+ * However, the column calculation has created many nonzero AC terms, so
+ * the simplification applies less often (typically 5% to 10% of the time).
+ * On machines with very fast multiplication, it's possible that the
+ * test takes more time than it's worth. In that case this section
+ * may be commented out.
+ */
+
+#ifndef NO_ZERO_ROW_TEST
+ if (wsptr[1] == 0 && wsptr[2] == 0 && wsptr[3] == 0 && wsptr[4] == 0 &&
+ wsptr[5] == 0 && wsptr[6] == 0 && wsptr[7] == 0) {
+ /* AC terms all zero */
+ JSAMPLE dcval = range_limit[(int) DESCALE((INT32) wsptr[0], PASS1_BITS+3)
+ & RANGE_MASK];
+
+ outptr[0] = dcval;
+ outptr[1] = dcval;
+ outptr[2] = dcval;
+ outptr[3] = dcval;
+ outptr[4] = dcval;
+ outptr[5] = dcval;
+ outptr[6] = dcval;
+ outptr[7] = dcval;
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ continue;
+ }
+#endif
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ /* Add fudge factor here for final descale. */
+ z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (INT32) wsptr[4];
+
+ tmp0 = (z2 + z3) << CONST_BITS;
+ tmp1 = (z2 - z3) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) wsptr[7];
+ tmp1 = (INT32) wsptr[5];
+ tmp2 = (INT32) wsptr[3];
+ tmp3 = (INT32) wsptr[1];
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+#ifdef IDCT_SCALING_SUPPORTED
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 7x7 output block.
+ *
+ * Optimized algorithm with 12 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/14).
+ */
+
+GLOBAL(void)
+jpeg_idct_7x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[7*7]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp13 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp13 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp13 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
+ tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */
+ tmp0 = z1 + z3;
+ z2 -= tmp0;
+ tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */
+ tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */
+ tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */
+ tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp1 += tmp2;
+ z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
+ tmp0 += z2;
+ tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */
+
+ /* Final output stage */
+
+ wsptr[7*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[7*6] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[7*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[7*5] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[7*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[7*4] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[7*3] = (int) RIGHT_SHIFT(tmp13, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 7 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 7; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp13 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp13 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[4];
+ z3 = (INT32) wsptr[6];
+
+ tmp10 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
+ tmp11 = tmp10 + tmp12 + tmp13 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */
+ tmp0 = z1 + z3;
+ z2 -= tmp0;
+ tmp0 = MULTIPLY(tmp0, FIX(1.274162392)) + tmp13; /* c2 */
+ tmp10 += tmp0 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */
+ tmp12 += tmp0 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */
+ tmp13 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp2 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp0 = tmp1 - tmp2;
+ tmp1 += tmp2;
+ tmp2 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp1 += tmp2;
+ z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
+ tmp0 += z2;
+ tmp2 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 7; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 6x6 output block.
+ *
+ * Optimized algorithm with 3 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/12).
+ */
+
+GLOBAL(void)
+jpeg_idct_6x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[6*6]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
+ tmp1 = tmp0 + tmp10;
+ tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
+ tmp10 = tmp1 + tmp0;
+ tmp12 = tmp1 - tmp0;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS);
+ tmp2 = tmp1 + ((z3 - z2) << CONST_BITS);
+ tmp1 = (z1 - z2 - z3) << PASS1_BITS;
+
+ /* Final output stage */
+
+ wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[6*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[6*1] = (int) (tmp11 + tmp1);
+ wsptr[6*4] = (int) (tmp11 - tmp1);
+ wsptr[6*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[6*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 6 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+ tmp2 = (INT32) wsptr[4];
+ tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
+ tmp1 = tmp0 + tmp10;
+ tmp11 = tmp0 - tmp10 - tmp10;
+ tmp10 = (INT32) wsptr[2];
+ tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
+ tmp10 = tmp1 + tmp0;
+ tmp12 = tmp1 - tmp0;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS);
+ tmp2 = tmp1 + ((z3 - z2) << CONST_BITS);
+ tmp1 = (z1 - z2 - z3) << CONST_BITS;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 6; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 5x5 output block.
+ *
+ * Optimized algorithm with 5 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/10).
+ */
+
+GLOBAL(void)
+jpeg_idct_5x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp10, tmp11, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[5*5]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp12 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp12 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
+ z3 = tmp12 + z2;
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z1;
+ tmp12 -= z2 << 2;
+
+ /* Odd part */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
+ tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
+ tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */
+
+ /* Final output stage */
+
+ wsptr[5*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[5*4] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[5*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[5*3] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[5*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 5 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 5; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp12 <<= CONST_BITS;
+ tmp0 = (INT32) wsptr[2];
+ tmp1 = (INT32) wsptr[4];
+ z1 = MULTIPLY(tmp0 + tmp1, FIX(0.790569415)); /* (c2+c4)/2 */
+ z2 = MULTIPLY(tmp0 - tmp1, FIX(0.353553391)); /* (c2-c4)/2 */
+ z3 = tmp12 + z2;
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z1;
+ tmp12 -= z2 << 2;
+
+ /* Odd part */
+
+ z2 = (INT32) wsptr[1];
+ z3 = (INT32) wsptr[3];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
+ tmp0 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
+ tmp1 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 5; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 4x4 output block.
+ *
+ * Optimized algorithm with 3 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT].
+ */
+
+GLOBAL(void)
+jpeg_idct_4x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[4*4]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+
+ tmp10 = (tmp0 + tmp2) << PASS1_BITS;
+ tmp12 = (tmp0 - tmp2) << PASS1_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS);
+ tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Final output stage */
+
+ wsptr[4*0] = (int) (tmp10 + tmp0);
+ wsptr[4*3] = (int) (tmp10 - tmp0);
+ wsptr[4*1] = (int) (tmp12 + tmp2);
+ wsptr[4*2] = (int) (tmp12 - tmp2);
+ }
+
+ /* Pass 2: process 4 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp2 = (INT32) wsptr[2];
+
+ tmp10 = (tmp0 + tmp2) << CONST_BITS;
+ tmp12 = (tmp0 - tmp2) << CONST_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = (INT32) wsptr[1];
+ z3 = (INT32) wsptr[3];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 4; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 3x3 output block.
+ *
+ * Optimized algorithm with 2 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/6).
+ */
+
+GLOBAL(void)
+jpeg_idct_3x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[3*3]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
+ tmp10 = tmp0 + tmp12;
+ tmp2 = tmp0 - tmp12 - tmp12;
+
+ /* Odd part */
+
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
+
+ /* Final output stage */
+
+ wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[3*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[3*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 3 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 3; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+ tmp2 = (INT32) wsptr[2];
+ tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
+ tmp10 = tmp0 + tmp12;
+ tmp2 = tmp0 - tmp12 - tmp12;
+
+ /* Odd part */
+
+ tmp12 = (INT32) wsptr[1];
+ tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 3; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 2x2 output block.
+ *
+ * Multiplication-less algorithm.
+ */
+
+GLOBAL(void)
+jpeg_idct_2x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp4, tmp5;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input. */
+
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+
+ /* Column 0 */
+ tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ /* Add fudge factor here for final descale. */
+ tmp4 += ONE << 2;
+
+ tmp0 = tmp4 + tmp5;
+ tmp2 = tmp4 - tmp5;
+
+ /* Column 1 */
+ tmp4 = DEQUANTIZE(coef_block[DCTSIZE*0+1], quantptr[DCTSIZE*0+1]);
+ tmp5 = DEQUANTIZE(coef_block[DCTSIZE*1+1], quantptr[DCTSIZE*1+1]);
+
+ tmp1 = tmp4 + tmp5;
+ tmp3 = tmp4 - tmp5;
+
+ /* Pass 2: process 2 rows, store into output array. */
+
+ /* Row 0 */
+ outptr = output_buf[0] + output_col;
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp0 + tmp1, 3) & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp0 - tmp1, 3) & RANGE_MASK];
+
+ /* Row 1 */
+ outptr = output_buf[1] + output_col;
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp2 + tmp3, 3) & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2 - tmp3, 3) & RANGE_MASK];
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 1x1 output block.
+ *
+ * We hardly need an inverse DCT routine for this: just take the
+ * average pixel value, which is one-eighth of the DC coefficient.
+ */
+
+GLOBAL(void)
+jpeg_idct_1x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ int dcval;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* 1x1 is trivial: just take the DC coefficient divided by 8. */
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ dcval = DEQUANTIZE(coef_block[0], quantptr[0]);
+ dcval = (int) DESCALE((INT32) dcval, 3);
+
+ output_buf[0][output_col] = range_limit[dcval & RANGE_MASK];
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 9x9 output block.
+ *
+ * Optimized algorithm with 10 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/18).
+ */
+
+GLOBAL(void)
+jpeg_idct_9x9 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*9]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
+ tmp1 = tmp0 + tmp3;
+ tmp2 = tmp0 - tmp3 - tmp3;
+
+ tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */
+ tmp11 = tmp2 + tmp0;
+ tmp14 = tmp2 - tmp0 - tmp0;
+
+ tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */
+ tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */
+ tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */
+
+ tmp10 = tmp1 + tmp0 - tmp3;
+ tmp12 = tmp1 - tmp0 + tmp2;
+ tmp13 = tmp1 - tmp2 + tmp3;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+
+ tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
+ tmp0 = tmp2 + tmp3 - z2;
+ tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */
+ tmp2 += z2 - tmp1;
+ tmp3 += z2 + tmp1;
+ tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp11 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp13 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp13 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp14, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 9 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 9; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[4];
+ z3 = (INT32) wsptr[6];
+
+ tmp3 = MULTIPLY(z3, FIX(0.707106781)); /* c6 */
+ tmp1 = tmp0 + tmp3;
+ tmp2 = tmp0 - tmp3 - tmp3;
+
+ tmp0 = MULTIPLY(z1 - z2, FIX(0.707106781)); /* c6 */
+ tmp11 = tmp2 + tmp0;
+ tmp14 = tmp2 - tmp0 - tmp0;
+
+ tmp0 = MULTIPLY(z1 + z2, FIX(1.328926049)); /* c2 */
+ tmp2 = MULTIPLY(z1, FIX(1.083350441)); /* c4 */
+ tmp3 = MULTIPLY(z2, FIX(0.245575608)); /* c8 */
+
+ tmp10 = tmp1 + tmp0 - tmp3;
+ tmp12 = tmp1 - tmp0 + tmp2;
+ tmp13 = tmp1 - tmp2 + tmp3;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ z2 = MULTIPLY(z2, - FIX(1.224744871)); /* -c3 */
+
+ tmp2 = MULTIPLY(z1 + z3, FIX(0.909038955)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(0.483689525)); /* c7 */
+ tmp0 = tmp2 + tmp3 - z2;
+ tmp1 = MULTIPLY(z3 - z4, FIX(1.392728481)); /* c1 */
+ tmp2 += z2 - tmp1;
+ tmp3 += z2 + tmp1;
+ tmp1 = MULTIPLY(z1 - z3 - z4, FIX(1.224744871)); /* c3 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 10x10 output block.
+ *
+ * Optimized algorithm with 12 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/20).
+ */
+
+GLOBAL(void)
+jpeg_idct_10x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24;
+ INT32 z1, z2, z3, z4, z5;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*10]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
+ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z2;
+
+ tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */
+ CONST_BITS-PASS1_BITS);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
+ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
+ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */
+
+ tmp20 = tmp10 + tmp12;
+ tmp24 = tmp10 - tmp12;
+ tmp21 = tmp11 + tmp13;
+ tmp23 = tmp11 - tmp13;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = z2 + z4;
+ tmp13 = z2 - z4;
+
+ tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */
+ z5 = z3 << CONST_BITS;
+
+ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */
+ z4 = z5 + tmp12;
+
+ tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */
+ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */
+ z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1));
+
+ tmp12 = (z1 - tmp13 - z3) << PASS1_BITS;
+
+ tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */
+ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) (tmp22 + tmp12);
+ wsptr[8*7] = (int) (tmp22 - tmp12);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 10 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 10; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 <<= CONST_BITS;
+ z4 = (INT32) wsptr[4];
+ z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
+ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z2;
+
+ tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
+ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
+ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */
+
+ tmp20 = tmp10 + tmp12;
+ tmp24 = tmp10 - tmp12;
+ tmp21 = tmp11 + tmp13;
+ tmp23 = tmp11 - tmp13;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z3 <<= CONST_BITS;
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = z2 + z4;
+ tmp13 = z2 - z4;
+
+ tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */
+ z4 = z3 + tmp12;
+
+ tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */
+ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */
+ z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1));
+
+ tmp12 = ((z1 - tmp13) << CONST_BITS) - z3;
+
+ tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */
+ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 11x11 output block.
+ *
+ * Optimized algorithm with 24 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/22).
+ */
+
+GLOBAL(void)
+jpeg_idct_11x11 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*11]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp10 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
+ tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
+ z4 = z1 + z3;
+ tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ z4 -= z2;
+ tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
+ tmp21 = tmp20 + tmp23 + tmp25 -
+ MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */
+ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */
+ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */
+ tmp24 += tmp25;
+ tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */
+ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */
+ MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */
+ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = z1 + z2;
+ tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */
+ tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */
+ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */
+ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
+ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
+ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
+ z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ tmp11 += z1;
+ tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
+ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
+ MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 11 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 11; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp10 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[4];
+ z3 = (INT32) wsptr[6];
+
+ tmp20 = MULTIPLY(z2 - z3, FIX(2.546640132)); /* c2+c4 */
+ tmp23 = MULTIPLY(z2 - z1, FIX(0.430815045)); /* c2-c6 */
+ z4 = z1 + z3;
+ tmp24 = MULTIPLY(z4, - FIX(1.155664402)); /* -(c2-c10) */
+ z4 -= z2;
+ tmp25 = tmp10 + MULTIPLY(z4, FIX(1.356927976)); /* c2 */
+ tmp21 = tmp20 + tmp23 + tmp25 -
+ MULTIPLY(z2, FIX(1.821790775)); /* c2+c4+c10-c6 */
+ tmp20 += tmp25 + MULTIPLY(z3, FIX(2.115825087)); /* c4+c6 */
+ tmp23 += tmp25 - MULTIPLY(z1, FIX(1.513598477)); /* c6+c8 */
+ tmp24 += tmp25;
+ tmp22 = tmp24 - MULTIPLY(z3, FIX(0.788749120)); /* c8+c10 */
+ tmp24 += MULTIPLY(z2, FIX(1.944413522)) - /* c2+c8 */
+ MULTIPLY(z1, FIX(1.390975730)); /* c4+c10 */
+ tmp25 = tmp10 - MULTIPLY(z4, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = z1 + z2;
+ tmp14 = MULTIPLY(tmp11 + z3 + z4, FIX(0.398430003)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.887983902)); /* c3-c9 */
+ tmp12 = MULTIPLY(z1 + z3, FIX(0.670361295)); /* c5-c9 */
+ tmp13 = tmp14 + MULTIPLY(z1 + z4, FIX(0.366151574)); /* c7-c9 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(z1, FIX(0.923107866)); /* c7+c5+c3-c1-2*c9 */
+ z1 = tmp14 - MULTIPLY(z2 + z3, FIX(1.163011579)); /* c7+c9 */
+ tmp11 += z1 + MULTIPLY(z2, FIX(2.073276588)); /* c1+c7+3*c9-c3 */
+ tmp12 += z1 - MULTIPLY(z3, FIX(1.192193623)); /* c3+c5-c7-c9 */
+ z1 = MULTIPLY(z2 + z4, - FIX(1.798248910)); /* -(c1+c9) */
+ tmp11 += z1;
+ tmp13 += z1 + MULTIPLY(z4, FIX(2.102458632)); /* c1+c5+c9-c7 */
+ tmp14 += MULTIPLY(z2, - FIX(1.467221301)) + /* -(c5+c9) */
+ MULTIPLY(z3, FIX(1.001388905)) - /* c1-c9 */
+ MULTIPLY(z4, FIX(1.684843907)); /* c3+c9 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 12x12 output block.
+ *
+ * Optimized algorithm with 15 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/24).
+ */
+
+GLOBAL(void)
+jpeg_idct_12x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*12]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
+ z1 <<= CONST_BITS;
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 <<= CONST_BITS;
+
+ tmp12 = z1 - z2;
+
+ tmp21 = z3 + tmp12;
+ tmp24 = z3 - tmp12;
+
+ tmp12 = z4 + z2;
+
+ tmp20 = tmp10 + tmp12;
+ tmp25 = tmp10 - tmp12;
+
+ tmp12 = z4 - z1 - z2;
+
+ tmp22 = tmp11 + tmp12;
+ tmp23 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
+ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+
+ tmp10 = z1 + z3;
+ tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
+ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
+ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
+ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
+ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
+ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
+ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */
+
+ z1 -= z4;
+ z2 -= z3;
+ z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */
+ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */
+ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 12 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 12; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 <<= CONST_BITS;
+
+ z4 = (INT32) wsptr[4];
+ z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ z1 = (INT32) wsptr[2];
+ z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
+ z1 <<= CONST_BITS;
+ z2 = (INT32) wsptr[6];
+ z2 <<= CONST_BITS;
+
+ tmp12 = z1 - z2;
+
+ tmp21 = z3 + tmp12;
+ tmp24 = z3 - tmp12;
+
+ tmp12 = z4 + z2;
+
+ tmp20 = tmp10 + tmp12;
+ tmp25 = tmp10 - tmp12;
+
+ tmp12 = z4 - z1 - z2;
+
+ tmp22 = tmp11 + tmp12;
+ tmp23 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
+ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+
+ tmp10 = z1 + z3;
+ tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
+ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
+ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
+ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
+ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
+ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
+ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */
+
+ z1 -= z4;
+ z2 -= z3;
+ z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */
+ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */
+ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 13x13 output block.
+ *
+ * Optimized algorithm with 29 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/26).
+ */
+
+GLOBAL(void)
+jpeg_idct_13x13 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*13]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */
+
+ tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */
+ tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */
+
+ tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
+
+ tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
+ tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+
+ tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
+
+ tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+
+ tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
+ tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
+ tmp15 = z1 + z4;
+ tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
+ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
+ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
+ tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp11 += tmp14;
+ tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
+ tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp12 += tmp14;
+ tmp13 += tmp14;
+ tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
+ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */
+ MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */
+ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */
+ tmp14 += z1;
+ tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */
+ MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*12] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp26, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 13 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 13; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 <<= CONST_BITS;
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[4];
+ z4 = (INT32) wsptr[6];
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ tmp12 = MULTIPLY(tmp10, FIX(1.155388986)); /* (c4+c6)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.096834934)) + z1; /* (c4-c6)/2 */
+
+ tmp20 = MULTIPLY(z2, FIX(1.373119086)) + tmp12 + tmp13; /* c2 */
+ tmp22 = MULTIPLY(z2, FIX(0.501487041)) - tmp12 + tmp13; /* c10 */
+
+ tmp12 = MULTIPLY(tmp10, FIX(0.316450131)); /* (c8-c12)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.486914739)) + z1; /* (c8+c12)/2 */
+
+ tmp21 = MULTIPLY(z2, FIX(1.058554052)) - tmp12 + tmp13; /* c6 */
+ tmp25 = MULTIPLY(z2, - FIX(1.252223920)) + tmp12 + tmp13; /* c4 */
+
+ tmp12 = MULTIPLY(tmp10, FIX(0.435816023)); /* (c2-c10)/2 */
+ tmp13 = MULTIPLY(tmp11, FIX(0.937303064)) - z1; /* (c2+c10)/2 */
+
+ tmp23 = MULTIPLY(z2, - FIX(0.170464608)) - tmp12 - tmp13; /* c12 */
+ tmp24 = MULTIPLY(z2, - FIX(0.803364869)) + tmp12 - tmp13; /* c8 */
+
+ tmp26 = MULTIPLY(tmp11 - z2, FIX(1.414213562)) + z1; /* c0 */
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.322312651)); /* c3 */
+ tmp12 = MULTIPLY(z1 + z3, FIX(1.163874945)); /* c5 */
+ tmp15 = z1 + z4;
+ tmp13 = MULTIPLY(tmp15, FIX(0.937797057)); /* c7 */
+ tmp10 = tmp11 + tmp12 + tmp13 -
+ MULTIPLY(z1, FIX(2.020082300)); /* c7+c5+c3-c1 */
+ tmp14 = MULTIPLY(z2 + z3, - FIX(0.338443458)); /* -c11 */
+ tmp11 += tmp14 + MULTIPLY(z2, FIX(0.837223564)); /* c5+c9+c11-c3 */
+ tmp12 += tmp14 - MULTIPLY(z3, FIX(1.572116027)); /* c1+c5-c9-c11 */
+ tmp14 = MULTIPLY(z2 + z4, - FIX(1.163874945)); /* -c5 */
+ tmp11 += tmp14;
+ tmp13 += tmp14 + MULTIPLY(z4, FIX(2.205608352)); /* c3+c5+c9-c7 */
+ tmp14 = MULTIPLY(z3 + z4, - FIX(0.657217813)); /* -c9 */
+ tmp12 += tmp14;
+ tmp13 += tmp14;
+ tmp15 = MULTIPLY(tmp15, FIX(0.338443458)); /* c11 */
+ tmp14 = tmp15 + MULTIPLY(z1, FIX(0.318774355)) - /* c9-c11 */
+ MULTIPLY(z2, FIX(0.466105296)); /* c1-c7 */
+ z1 = MULTIPLY(z3 - z2, FIX(0.937797057)); /* c7 */
+ tmp14 += z1;
+ tmp15 += z1 + MULTIPLY(z3, FIX(0.384515595)) - /* c3-c7 */
+ MULTIPLY(z4, FIX(1.742345811)); /* c1+c11 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 14x14 output block.
+ *
+ * Optimized algorithm with 20 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/28).
+ */
+
+GLOBAL(void)
+jpeg_idct_14x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*14]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
+ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
+ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
+
+ tmp10 = z1 + z2;
+ tmp11 = z1 + z3;
+ tmp12 = z1 - z4;
+
+ tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */
+ CONST_BITS-PASS1_BITS);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
+
+ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */
+ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */
+ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */
+ MULTIPLY(z2, FIX(1.378756276)); /* c2 */
+
+ tmp20 = tmp10 + tmp13;
+ tmp26 = tmp10 - tmp13;
+ tmp21 = tmp11 + tmp14;
+ tmp25 = tmp11 - tmp14;
+ tmp22 = tmp12 + tmp15;
+ tmp24 = tmp12 - tmp15;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp13 = z4 << CONST_BITS;
+
+ tmp14 = z1 + z3;
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */
+ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */
+ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */
+ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */
+ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */
+ z1 -= z2;
+ tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */
+ tmp16 += tmp15;
+ z1 += z4;
+ z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */
+ tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
+ tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
+ z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
+ tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */
+ tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */
+
+ tmp13 = (z1 - z3) << PASS1_BITS;
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) (tmp23 + tmp13);
+ wsptr[8*10] = (int) (tmp23 - tmp13);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 14 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 14; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 <<= CONST_BITS;
+ z4 = (INT32) wsptr[4];
+ z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
+ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
+ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
+
+ tmp10 = z1 + z2;
+ tmp11 = z1 + z3;
+ tmp12 = z1 - z4;
+
+ tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[6];
+
+ z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
+
+ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */
+ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */
+ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */
+ MULTIPLY(z2, FIX(1.378756276)); /* c2 */
+
+ tmp20 = tmp10 + tmp13;
+ tmp26 = tmp10 - tmp13;
+ tmp21 = tmp11 + tmp14;
+ tmp25 = tmp11 - tmp14;
+ tmp22 = tmp12 + tmp15;
+ tmp24 = tmp12 - tmp15;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+ z4 <<= CONST_BITS;
+
+ tmp14 = z1 + z3;
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */
+ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */
+ tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */
+ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */
+ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */
+ z1 -= z2;
+ tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */
+ tmp16 += tmp15;
+ tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */
+ tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
+ tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
+ tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
+ tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */
+ tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */
+
+ tmp13 = ((z1 - z3) << CONST_BITS) + z4;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 15x15 output block.
+ *
+ * Optimized algorithm with 22 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/30).
+ */
+
+GLOBAL(void)
+jpeg_idct_15x15 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*15]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
+ tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
+
+ tmp12 = z1 - tmp10;
+ tmp13 = z1 + tmp11;
+ z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */
+
+ z4 = z2 - z3;
+ z3 += z2;
+ tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */
+ z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */
+
+ tmp20 = tmp13 + tmp10 + tmp11;
+ tmp23 = tmp12 - tmp10 + tmp11 + z2;
+
+ tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */
+
+ tmp25 = tmp13 - tmp10 - tmp11;
+ tmp26 = tmp12 + tmp10 - tmp11 - z2;
+
+ tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */
+
+ tmp21 = tmp12 + tmp10 + tmp11;
+ tmp24 = tmp13 - tmp10 + tmp11;
+ tmp11 += tmp11;
+ tmp22 = z1 + tmp11; /* c10 = c6-c12 */
+ tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp13 = z2 - z4;
+ tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
+ tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
+ tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
+
+ tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ z2 = z1 - z4;
+ tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
+
+ tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */
+ tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */
+ tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */
+ z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */
+ tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */
+ tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*14] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*13] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*12] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp27, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 15 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 15; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 <<= CONST_BITS;
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[4];
+ z4 = (INT32) wsptr[6];
+
+ tmp10 = MULTIPLY(z4, FIX(0.437016024)); /* c12 */
+ tmp11 = MULTIPLY(z4, FIX(1.144122806)); /* c6 */
+
+ tmp12 = z1 - tmp10;
+ tmp13 = z1 + tmp11;
+ z1 -= (tmp11 - tmp10) << 1; /* c0 = (c6-c12)*2 */
+
+ z4 = z2 - z3;
+ z3 += z2;
+ tmp10 = MULTIPLY(z3, FIX(1.337628990)); /* (c2+c4)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.045680613)); /* (c2-c4)/2 */
+ z2 = MULTIPLY(z2, FIX(1.439773946)); /* c4+c14 */
+
+ tmp20 = tmp13 + tmp10 + tmp11;
+ tmp23 = tmp12 - tmp10 + tmp11 + z2;
+
+ tmp10 = MULTIPLY(z3, FIX(0.547059574)); /* (c8+c14)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.399234004)); /* (c8-c14)/2 */
+
+ tmp25 = tmp13 - tmp10 - tmp11;
+ tmp26 = tmp12 + tmp10 - tmp11 - z2;
+
+ tmp10 = MULTIPLY(z3, FIX(0.790569415)); /* (c6+c12)/2 */
+ tmp11 = MULTIPLY(z4, FIX(0.353553391)); /* (c6-c12)/2 */
+
+ tmp21 = tmp12 + tmp10 + tmp11;
+ tmp24 = tmp13 - tmp10 + tmp11;
+ tmp11 += tmp11;
+ tmp22 = z1 + tmp11; /* c10 = c6-c12 */
+ tmp27 = z1 - tmp11 - tmp11; /* c0 = (c6-c12)*2 */
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z4 = (INT32) wsptr[5];
+ z3 = MULTIPLY(z4, FIX(1.224744871)); /* c5 */
+ z4 = (INT32) wsptr[7];
+
+ tmp13 = z2 - z4;
+ tmp15 = MULTIPLY(z1 + tmp13, FIX(0.831253876)); /* c9 */
+ tmp11 = tmp15 + MULTIPLY(z1, FIX(0.513743148)); /* c3-c9 */
+ tmp14 = tmp15 - MULTIPLY(tmp13, FIX(2.176250899)); /* c3+c9 */
+
+ tmp13 = MULTIPLY(z2, - FIX(0.831253876)); /* -c9 */
+ tmp15 = MULTIPLY(z2, - FIX(1.344997024)); /* -c3 */
+ z2 = z1 - z4;
+ tmp12 = z3 + MULTIPLY(z2, FIX(1.406466353)); /* c1 */
+
+ tmp10 = tmp12 + MULTIPLY(z4, FIX(2.457431844)) - tmp15; /* c1+c7 */
+ tmp16 = tmp12 - MULTIPLY(z1, FIX(1.112434820)) + tmp13; /* c1-c13 */
+ tmp12 = MULTIPLY(z2, FIX(1.224744871)) - z3; /* c5 */
+ z2 = MULTIPLY(z1 + z4, FIX(0.575212477)); /* c11 */
+ tmp13 += z2 + MULTIPLY(z1, FIX(0.475753014)) - z3; /* c7-c11 */
+ tmp15 += z2 - MULTIPLY(z4, FIX(0.869244010)) + z3; /* c11+c13 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 16x16 output block.
+ *
+ * Optimized algorithm with 28 multiplications in the 1-D kernel.
+ * cK represents sqrt(2) * cos(K*pi/32).
+ */
+
+GLOBAL(void)
+jpeg_idct_16x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*16]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += 1 << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
+ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z3 = z1 - z2;
+ z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
+ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */
+ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */
+ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */
+ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */
+
+ tmp20 = tmp10 + tmp0;
+ tmp27 = tmp10 - tmp0;
+ tmp21 = tmp12 + tmp1;
+ tmp26 = tmp12 - tmp1;
+ tmp22 = tmp13 + tmp2;
+ tmp25 = tmp13 - tmp2;
+ tmp23 = tmp11 + tmp3;
+ tmp24 = tmp11 - tmp3;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = z1 + z3;
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */
+ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */
+ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */
+ tmp13 = tmp10 + tmp11 + tmp12 -
+ MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */
+ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */
+ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */
+ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */
+ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */
+ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
+ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
+ z2 += z4;
+ z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ tmp1 += z1;
+ tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
+ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
+ tmp12 += z2;
+ z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ tmp2 += z2;
+ tmp3 += z2;
+ z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
+ tmp10 += z2;
+ tmp11 += z2;
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 16 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 16; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[4];
+ tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
+ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[6];
+ z3 = z1 - z2;
+ z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
+ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */
+ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */
+ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */
+ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */
+
+ tmp20 = tmp10 + tmp0;
+ tmp27 = tmp10 - tmp0;
+ tmp21 = tmp12 + tmp1;
+ tmp26 = tmp12 - tmp1;
+ tmp22 = tmp13 + tmp2;
+ tmp25 = tmp13 - tmp2;
+ tmp23 = tmp11 + tmp3;
+ tmp24 = tmp11 - tmp3;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = z1 + z3;
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */
+ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */
+ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */
+ tmp13 = tmp10 + tmp11 + tmp12 -
+ MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */
+ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */
+ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */
+ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */
+ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */
+ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
+ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
+ z2 += z4;
+ z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ tmp1 += z1;
+ tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
+ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
+ tmp12 += z2;
+ z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ tmp2 += z2;
+ tmp3 += z2;
+ z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
+ tmp10 += z2;
+ tmp11 += z2;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 16x8 output block.
+ *
+ * 8-point IDCT in pass 1 (columns), 16-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_16x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*8]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = DCTSIZE; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[DCTSIZE*0] = dcval;
+ wsptr[DCTSIZE*1] = dcval;
+ wsptr[DCTSIZE*2] = dcval;
+ wsptr[DCTSIZE*3] = dcval;
+ wsptr[DCTSIZE*4] = dcval;
+ wsptr[DCTSIZE*5] = dcval;
+ wsptr[DCTSIZE*6] = dcval;
+ wsptr[DCTSIZE*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 <<= CONST_BITS;
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z2 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ tmp0 = z2 + z3;
+ tmp1 = z2 - z3;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ wsptr[DCTSIZE*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[DCTSIZE*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process 8 rows from work array, store into output array.
+ * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[4];
+ tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
+ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[6];
+ z3 = z1 - z2;
+ z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
+ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */
+ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */
+ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */
+ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */
+
+ tmp20 = tmp10 + tmp0;
+ tmp27 = tmp10 - tmp0;
+ tmp21 = tmp12 + tmp1;
+ tmp26 = tmp12 - tmp1;
+ tmp22 = tmp13 + tmp2;
+ tmp25 = tmp13 - tmp2;
+ tmp23 = tmp11 + tmp3;
+ tmp24 = tmp11 - tmp3;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = z1 + z3;
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */
+ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */
+ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */
+ tmp13 = tmp10 + tmp11 + tmp12 -
+ MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */
+ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */
+ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */
+ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */
+ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */
+ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
+ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
+ z2 += z4;
+ z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ tmp1 += z1;
+ tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
+ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
+ tmp12 += z2;
+ z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ tmp2 += z2;
+ tmp3 += z2;
+ z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
+ tmp10 += z2;
+ tmp11 += z2;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[15] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[14] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp27 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp27 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 14x7 output block.
+ *
+ * 7-point IDCT in pass 1 (columns), 14-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_14x7 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*7]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp23 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp23 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp23 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
+ tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
+ tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */
+ tmp10 = z1 + z3;
+ z2 -= tmp10;
+ tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */
+ tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */
+ tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */
+ tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+
+ tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp10 = tmp11 - tmp12;
+ tmp11 += tmp12;
+ tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp11 += tmp12;
+ z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
+ tmp10 += z2;
+ tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 7 rows from work array, store into output array.
+ * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 7; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z1 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z1 <<= CONST_BITS;
+ z4 = (INT32) wsptr[4];
+ z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
+ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
+ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
+
+ tmp10 = z1 + z2;
+ tmp11 = z1 + z3;
+ tmp12 = z1 - z4;
+
+ tmp23 = z1 - ((z2 + z3 - z4) << 1); /* c0 = (c4+c12-c8)*2 */
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[6];
+
+ z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
+
+ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */
+ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */
+ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */
+ MULTIPLY(z2, FIX(1.378756276)); /* c2 */
+
+ tmp20 = tmp10 + tmp13;
+ tmp26 = tmp10 - tmp13;
+ tmp21 = tmp11 + tmp14;
+ tmp25 = tmp11 - tmp14;
+ tmp22 = tmp12 + tmp15;
+ tmp24 = tmp12 - tmp15;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+ z4 <<= CONST_BITS;
+
+ tmp14 = z1 + z3;
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */
+ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */
+ tmp10 = tmp11 + tmp12 + z4 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */
+ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */
+ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */
+ z1 -= z2;
+ tmp15 = MULTIPLY(z1, FIX(0.467085129)) - z4; /* c11 */
+ tmp16 += tmp15;
+ tmp13 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - z4; /* -c13 */
+ tmp11 += tmp13 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
+ tmp12 += tmp13 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
+ tmp13 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
+ tmp14 += tmp13 + z4 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */
+ tmp15 += tmp13 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */
+
+ tmp13 = ((z1 - z3) << CONST_BITS) + z4;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[13] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[12] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp26 + tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp26 - tmp16,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 12x6 output block.
+ *
+ * 6-point IDCT in pass 1 (columns), 12-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_12x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*6]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp10 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp10 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */
+ tmp11 = tmp10 + tmp20;
+ tmp21 = RIGHT_SHIFT(tmp10 - tmp20 - tmp20, CONST_BITS-PASS1_BITS);
+ tmp20 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */
+ tmp20 = tmp11 + tmp10;
+ tmp22 = tmp11 - tmp10;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp10 = tmp11 + ((z1 + z2) << CONST_BITS);
+ tmp12 = tmp11 + ((z3 - z2) << CONST_BITS);
+ tmp11 = (z1 - z2 - z3) << PASS1_BITS;
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) (tmp21 + tmp11);
+ wsptr[8*4] = (int) (tmp21 - tmp11);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 6 rows from work array, store into output array.
+ * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 <<= CONST_BITS;
+
+ z4 = (INT32) wsptr[4];
+ z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ z1 = (INT32) wsptr[2];
+ z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
+ z1 <<= CONST_BITS;
+ z2 = (INT32) wsptr[6];
+ z2 <<= CONST_BITS;
+
+ tmp12 = z1 - z2;
+
+ tmp21 = z3 + tmp12;
+ tmp24 = z3 - tmp12;
+
+ tmp12 = z4 + z2;
+
+ tmp20 = tmp10 + tmp12;
+ tmp25 = tmp10 - tmp12;
+
+ tmp12 = z4 - z1 - z2;
+
+ tmp22 = tmp11 + tmp12;
+ tmp23 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
+ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+
+ tmp10 = z1 + z3;
+ tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
+ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
+ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
+ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
+ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
+ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
+ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */
+
+ z1 -= z4;
+ z2 -= z3;
+ z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */
+ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */
+ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[11] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[10] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp25 + tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp25 - tmp15,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 10x5 output block.
+ *
+ * 5-point IDCT in pass 1 (columns), 10-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_10x5 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*5]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp12 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp12 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp13 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp14 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */
+ z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */
+ z3 = tmp12 + z2;
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z1;
+ tmp12 -= z2 << 2;
+
+ /* Odd part */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
+ tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
+ tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp10 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp10 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp11 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp11 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp12, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 5 rows from work array, store into output array.
+ * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 5; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ z3 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 <<= CONST_BITS;
+ z4 = (INT32) wsptr[4];
+ z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
+ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z2;
+
+ tmp22 = z3 - ((z1 - z2) << 1); /* c0 = (c4-c8)*2 */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
+ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
+ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */
+
+ tmp20 = tmp10 + tmp12;
+ tmp24 = tmp10 - tmp12;
+ tmp21 = tmp11 + tmp13;
+ tmp23 = tmp11 - tmp13;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ z3 <<= CONST_BITS;
+ z4 = (INT32) wsptr[7];
+
+ tmp11 = z2 + z4;
+ tmp13 = z2 - z4;
+
+ tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */
+ z4 = z3 + tmp12;
+
+ tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */
+ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */
+ z4 = z3 - tmp12 - (tmp13 << (CONST_BITS - 1));
+
+ tmp12 = ((z1 - tmp13) << CONST_BITS) - z3;
+
+ tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */
+ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[9] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[8] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp23 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp24 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp24 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 8; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 8x4 output block.
+ *
+ * 4-point IDCT in pass 1 (columns), 8-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_8x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*4]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+
+ tmp10 = (tmp0 + tmp2) << PASS1_BITS;
+ tmp12 = (tmp0 - tmp2) << PASS1_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp0 = RIGHT_SHIFT(z1 + MULTIPLY(z2, FIX_0_765366865), /* c2-c6 */
+ CONST_BITS-PASS1_BITS);
+ tmp2 = RIGHT_SHIFT(z1 - MULTIPLY(z3, FIX_1_847759065), /* c2+c6 */
+ CONST_BITS-PASS1_BITS);
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) (tmp10 + tmp0);
+ wsptr[8*3] = (int) (tmp10 - tmp0);
+ wsptr[8*1] = (int) (tmp12 + tmp2);
+ wsptr[8*2] = (int) (tmp12 - tmp2);
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ /* Add fudge factor here for final descale. */
+ z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (INT32) wsptr[4];
+
+ tmp0 = (z2 + z3) << CONST_BITS;
+ tmp1 = (z2 - z3) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) wsptr[7];
+ tmp1 = (INT32) wsptr[5];
+ tmp2 = (INT32) wsptr[3];
+ tmp3 = (INT32) wsptr[1];
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 6x3 output block.
+ *
+ * 3-point IDCT in pass 1 (columns), 6-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_6x3 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[6*3]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
+ tmp10 = tmp0 + tmp12;
+ tmp2 = tmp0 - tmp12 - tmp12;
+
+ /* Odd part */
+
+ tmp12 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
+
+ /* Final output stage */
+
+ wsptr[6*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[6*2] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[6*1] = (int) RIGHT_SHIFT(tmp2, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 3 rows from work array, store into output array.
+ * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 3; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+ tmp2 = (INT32) wsptr[4];
+ tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
+ tmp1 = tmp0 + tmp10;
+ tmp11 = tmp0 - tmp10 - tmp10;
+ tmp10 = (INT32) wsptr[2];
+ tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
+ tmp10 = tmp1 + tmp0;
+ tmp12 = tmp1 - tmp0;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS);
+ tmp2 = tmp1 + ((z3 - z2) << CONST_BITS);
+ tmp1 = (z1 - z2 - z3) << CONST_BITS;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 6; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 4x2 output block.
+ *
+ * 2-point IDCT in pass 1 (columns), 4-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_4x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ INT32 * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ INT32 workspace[4*2]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+
+ /* Odd part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ /* Final output stage */
+
+ wsptr[4*0] = tmp10 + tmp0;
+ wsptr[4*1] = tmp10 - tmp0;
+ }
+
+ /* Pass 2: process 2 rows from work array, store into output array.
+ * 4-point IDCT kernel,
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT].
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 2; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = wsptr[0] + (ONE << 2);
+ tmp2 = wsptr[2];
+
+ tmp10 = (tmp0 + tmp2) << CONST_BITS;
+ tmp12 = (tmp0 - tmp2) << CONST_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = wsptr[1];
+ z3 = wsptr[3];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 4; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 2x1 output block.
+ *
+ * 1-point IDCT in pass 1 (columns), 2-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_2x1 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp10;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* Pass 1: empty. */
+
+ /* Pass 2: process 1 row from input, store into output array. */
+
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ outptr = output_buf[0] + output_col;
+
+ /* Even part */
+
+ tmp10 = DEQUANTIZE(coef_block[0], quantptr[0]);
+ /* Add fudge factor here for final descale. */
+ tmp10 += ONE << 2;
+
+ /* Odd part */
+
+ tmp0 = DEQUANTIZE(coef_block[1], quantptr[1]);
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3) & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3) & RANGE_MASK];
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 8x16 output block.
+ *
+ * 16-point IDCT in pass 1 (columns), 8-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_8x16 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3, tmp10, tmp11, tmp12, tmp13;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26, tmp27;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[8*16]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 16-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/32).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp1 = MULTIPLY(z1, FIX(1.306562965)); /* c4[16] = c2[8] */
+ tmp2 = MULTIPLY(z1, FIX_0_541196100); /* c12[16] = c6[8] */
+
+ tmp10 = tmp0 + tmp1;
+ tmp11 = tmp0 - tmp1;
+ tmp12 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z3 = z1 - z2;
+ z4 = MULTIPLY(z3, FIX(0.275899379)); /* c14[16] = c7[8] */
+ z3 = MULTIPLY(z3, FIX(1.387039845)); /* c2[16] = c1[8] */
+
+ tmp0 = z3 + MULTIPLY(z2, FIX_2_562915447); /* (c6+c2)[16] = (c3+c1)[8] */
+ tmp1 = z4 + MULTIPLY(z1, FIX_0_899976223); /* (c6-c14)[16] = (c3-c7)[8] */
+ tmp2 = z3 - MULTIPLY(z1, FIX(0.601344887)); /* (c2-c10)[16] = (c1-c5)[8] */
+ tmp3 = z4 - MULTIPLY(z2, FIX(0.509795579)); /* (c10-c14)[16] = (c5-c7)[8] */
+
+ tmp20 = tmp10 + tmp0;
+ tmp27 = tmp10 - tmp0;
+ tmp21 = tmp12 + tmp1;
+ tmp26 = tmp12 - tmp1;
+ tmp22 = tmp13 + tmp2;
+ tmp25 = tmp13 - tmp2;
+ tmp23 = tmp11 + tmp3;
+ tmp24 = tmp11 - tmp3;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = z1 + z3;
+
+ tmp1 = MULTIPLY(z1 + z2, FIX(1.353318001)); /* c3 */
+ tmp2 = MULTIPLY(tmp11, FIX(1.247225013)); /* c5 */
+ tmp3 = MULTIPLY(z1 + z4, FIX(1.093201867)); /* c7 */
+ tmp10 = MULTIPLY(z1 - z4, FIX(0.897167586)); /* c9 */
+ tmp11 = MULTIPLY(tmp11, FIX(0.666655658)); /* c11 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.410524528)); /* c13 */
+ tmp0 = tmp1 + tmp2 + tmp3 -
+ MULTIPLY(z1, FIX(2.286341144)); /* c7+c5+c3-c1 */
+ tmp13 = tmp10 + tmp11 + tmp12 -
+ MULTIPLY(z1, FIX(1.835730603)); /* c9+c11+c13-c15 */
+ z1 = MULTIPLY(z2 + z3, FIX(0.138617169)); /* c15 */
+ tmp1 += z1 + MULTIPLY(z2, FIX(0.071888074)); /* c9+c11-c3-c15 */
+ tmp2 += z1 - MULTIPLY(z3, FIX(1.125726048)); /* c5+c7+c15-c3 */
+ z1 = MULTIPLY(z3 - z2, FIX(1.407403738)); /* c1 */
+ tmp11 += z1 - MULTIPLY(z3, FIX(0.766367282)); /* c1+c11-c9-c13 */
+ tmp12 += z1 + MULTIPLY(z2, FIX(1.971951411)); /* c1+c5+c13-c7 */
+ z2 += z4;
+ z1 = MULTIPLY(z2, - FIX(0.666655658)); /* -c11 */
+ tmp1 += z1;
+ tmp3 += z1 + MULTIPLY(z4, FIX(1.065388962)); /* c3+c11+c15-c7 */
+ z2 = MULTIPLY(z2, - FIX(1.247225013)); /* -c5 */
+ tmp10 += z2 + MULTIPLY(z4, FIX(3.141271809)); /* c1+c5+c9-c13 */
+ tmp12 += z2;
+ z2 = MULTIPLY(z3 + z4, - FIX(1.353318001)); /* -c3 */
+ tmp2 += z2;
+ tmp3 += z2;
+ z2 = MULTIPLY(z4 - z3, FIX(0.410524528)); /* c13 */
+ tmp10 += z2;
+ tmp11 += z2;
+
+ /* Final output stage */
+
+ wsptr[8*0] = (int) RIGHT_SHIFT(tmp20 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*15] = (int) RIGHT_SHIFT(tmp20 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[8*1] = (int) RIGHT_SHIFT(tmp21 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*14] = (int) RIGHT_SHIFT(tmp21 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[8*2] = (int) RIGHT_SHIFT(tmp22 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*13] = (int) RIGHT_SHIFT(tmp22 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[8*3] = (int) RIGHT_SHIFT(tmp23 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*12] = (int) RIGHT_SHIFT(tmp23 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[8*4] = (int) RIGHT_SHIFT(tmp24 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*11] = (int) RIGHT_SHIFT(tmp24 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[8*5] = (int) RIGHT_SHIFT(tmp25 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*10] = (int) RIGHT_SHIFT(tmp25 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[8*6] = (int) RIGHT_SHIFT(tmp26 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*9] = (int) RIGHT_SHIFT(tmp26 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[8*7] = (int) RIGHT_SHIFT(tmp27 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[8*8] = (int) RIGHT_SHIFT(tmp27 - tmp13, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process rows from work array, store into output array. */
+ /* Note that we must descale the results by a factor of 8 == 2**3, */
+ /* and also undo the PASS1_BITS scaling. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 16; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = (INT32) wsptr[2];
+ z3 = (INT32) wsptr[6];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ /* Add fudge factor here for final descale. */
+ z2 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ z3 = (INT32) wsptr[4];
+
+ tmp0 = (z2 + z3) << CONST_BITS;
+ tmp1 = (z2 - z3) << CONST_BITS;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = (INT32) wsptr[7];
+ tmp1 = (INT32) wsptr[5];
+ tmp2 = (INT32) wsptr[3];
+ tmp3 = (INT32) wsptr[1];
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[7] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp3,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp1,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp13 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp13 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += DCTSIZE; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 7x14 output block.
+ *
+ * 14-point IDCT in pass 1 (columns), 7-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_7x14 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, tmp16;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25, tmp26;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[7*14]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 14-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/28).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 7; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z1 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z1 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 = MULTIPLY(z4, FIX(1.274162392)); /* c4 */
+ z3 = MULTIPLY(z4, FIX(0.314692123)); /* c12 */
+ z4 = MULTIPLY(z4, FIX(0.881747734)); /* c8 */
+
+ tmp10 = z1 + z2;
+ tmp11 = z1 + z3;
+ tmp12 = z1 - z4;
+
+ tmp23 = RIGHT_SHIFT(z1 - ((z2 + z3 - z4) << 1), /* c0 = (c4+c12-c8)*2 */
+ CONST_BITS-PASS1_BITS);
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z3 = MULTIPLY(z1 + z2, FIX(1.105676686)); /* c6 */
+
+ tmp13 = z3 + MULTIPLY(z1, FIX(0.273079590)); /* c2-c6 */
+ tmp14 = z3 - MULTIPLY(z2, FIX(1.719280954)); /* c6+c10 */
+ tmp15 = MULTIPLY(z1, FIX(0.613604268)) - /* c10 */
+ MULTIPLY(z2, FIX(1.378756276)); /* c2 */
+
+ tmp20 = tmp10 + tmp13;
+ tmp26 = tmp10 - tmp13;
+ tmp21 = tmp11 + tmp14;
+ tmp25 = tmp11 - tmp14;
+ tmp22 = tmp12 + tmp15;
+ tmp24 = tmp12 - tmp15;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp13 = z4 << CONST_BITS;
+
+ tmp14 = z1 + z3;
+ tmp11 = MULTIPLY(z1 + z2, FIX(1.334852607)); /* c3 */
+ tmp12 = MULTIPLY(tmp14, FIX(1.197448846)); /* c5 */
+ tmp10 = tmp11 + tmp12 + tmp13 - MULTIPLY(z1, FIX(1.126980169)); /* c3+c5-c1 */
+ tmp14 = MULTIPLY(tmp14, FIX(0.752406978)); /* c9 */
+ tmp16 = tmp14 - MULTIPLY(z1, FIX(1.061150426)); /* c9+c11-c13 */
+ z1 -= z2;
+ tmp15 = MULTIPLY(z1, FIX(0.467085129)) - tmp13; /* c11 */
+ tmp16 += tmp15;
+ z1 += z4;
+ z4 = MULTIPLY(z2 + z3, - FIX(0.158341681)) - tmp13; /* -c13 */
+ tmp11 += z4 - MULTIPLY(z2, FIX(0.424103948)); /* c3-c9-c13 */
+ tmp12 += z4 - MULTIPLY(z3, FIX(2.373959773)); /* c3+c5-c13 */
+ z4 = MULTIPLY(z3 - z2, FIX(1.405321284)); /* c1 */
+ tmp14 += z4 + tmp13 - MULTIPLY(z3, FIX(1.6906431334)); /* c1+c9-c11 */
+ tmp15 += z4 + MULTIPLY(z2, FIX(0.674957567)); /* c1+c11-c5 */
+
+ tmp13 = (z1 - z3) << PASS1_BITS;
+
+ /* Final output stage */
+
+ wsptr[7*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[7*13] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[7*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[7*12] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[7*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[7*11] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[7*3] = (int) (tmp23 + tmp13);
+ wsptr[7*10] = (int) (tmp23 - tmp13);
+ wsptr[7*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[7*9] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[7*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[7*8] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[7*6] = (int) RIGHT_SHIFT(tmp26 + tmp16, CONST_BITS-PASS1_BITS);
+ wsptr[7*7] = (int) RIGHT_SHIFT(tmp26 - tmp16, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 14 rows from work array, store into output array.
+ * 7-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/14).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 14; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp23 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp23 <<= CONST_BITS;
+
+ z1 = (INT32) wsptr[2];
+ z2 = (INT32) wsptr[4];
+ z3 = (INT32) wsptr[6];
+
+ tmp20 = MULTIPLY(z2 - z3, FIX(0.881747734)); /* c4 */
+ tmp22 = MULTIPLY(z1 - z2, FIX(0.314692123)); /* c6 */
+ tmp21 = tmp20 + tmp22 + tmp23 - MULTIPLY(z2, FIX(1.841218003)); /* c2+c4-c6 */
+ tmp10 = z1 + z3;
+ z2 -= tmp10;
+ tmp10 = MULTIPLY(tmp10, FIX(1.274162392)) + tmp23; /* c2 */
+ tmp20 += tmp10 - MULTIPLY(z3, FIX(0.077722536)); /* c2-c4-c6 */
+ tmp22 += tmp10 - MULTIPLY(z1, FIX(2.470602249)); /* c2+c4+c6 */
+ tmp23 += MULTIPLY(z2, FIX(1.414213562)); /* c0 */
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+
+ tmp11 = MULTIPLY(z1 + z2, FIX(0.935414347)); /* (c3+c1-c5)/2 */
+ tmp12 = MULTIPLY(z1 - z2, FIX(0.170262339)); /* (c3+c5-c1)/2 */
+ tmp10 = tmp11 - tmp12;
+ tmp11 += tmp12;
+ tmp12 = MULTIPLY(z2 + z3, - FIX(1.378756276)); /* -c1 */
+ tmp11 += tmp12;
+ z2 = MULTIPLY(z1 + z3, FIX(0.613604268)); /* c5 */
+ tmp10 += z2;
+ tmp12 += z2 + MULTIPLY(z3, FIX(1.870828693)); /* c3+c1-c5 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[6] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp23,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 7; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 6x12 output block.
+ *
+ * 12-point IDCT in pass 1 (columns), 6-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_6x12 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14, tmp15;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24, tmp25;
+ INT32 z1, z2, z3, z4;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[6*12]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 12-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/24).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z4 = MULTIPLY(z4, FIX(1.224744871)); /* c4 */
+
+ tmp10 = z3 + z4;
+ tmp11 = z3 - z4;
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z4 = MULTIPLY(z1, FIX(1.366025404)); /* c2 */
+ z1 <<= CONST_BITS;
+ z2 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+ z2 <<= CONST_BITS;
+
+ tmp12 = z1 - z2;
+
+ tmp21 = z3 + tmp12;
+ tmp24 = z3 - tmp12;
+
+ tmp12 = z4 + z2;
+
+ tmp20 = tmp10 + tmp12;
+ tmp25 = tmp10 - tmp12;
+
+ tmp12 = z4 - z1 - z2;
+
+ tmp22 = tmp11 + tmp12;
+ tmp23 = tmp11 - tmp12;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = MULTIPLY(z2, FIX(1.306562965)); /* c3 */
+ tmp14 = MULTIPLY(z2, - FIX_0_541196100); /* -c9 */
+
+ tmp10 = z1 + z3;
+ tmp15 = MULTIPLY(tmp10 + z4, FIX(0.860918669)); /* c7 */
+ tmp12 = tmp15 + MULTIPLY(tmp10, FIX(0.261052384)); /* c5-c7 */
+ tmp10 = tmp12 + tmp11 + MULTIPLY(z1, FIX(0.280143716)); /* c1-c5 */
+ tmp13 = MULTIPLY(z3 + z4, - FIX(1.045510580)); /* -(c7+c11) */
+ tmp12 += tmp13 + tmp14 - MULTIPLY(z3, FIX(1.478575242)); /* c1+c5-c7-c11 */
+ tmp13 += tmp15 - tmp11 + MULTIPLY(z4, FIX(1.586706681)); /* c1+c11 */
+ tmp15 += tmp14 - MULTIPLY(z1, FIX(0.676326758)) - /* c7-c11 */
+ MULTIPLY(z4, FIX(1.982889723)); /* c5+c7 */
+
+ z1 -= z4;
+ z2 -= z3;
+ z3 = MULTIPLY(z1 + z2, FIX_0_541196100); /* c9 */
+ tmp11 = z3 + MULTIPLY(z1, FIX_0_765366865); /* c3-c9 */
+ tmp14 = z3 - MULTIPLY(z2, FIX_1_847759065); /* c3+c9 */
+
+ /* Final output stage */
+
+ wsptr[6*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[6*11] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[6*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[6*10] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[6*2] = (int) RIGHT_SHIFT(tmp22 + tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[6*9] = (int) RIGHT_SHIFT(tmp22 - tmp12, CONST_BITS-PASS1_BITS);
+ wsptr[6*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[6*8] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[6*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[6*7] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[6*5] = (int) RIGHT_SHIFT(tmp25 + tmp15, CONST_BITS-PASS1_BITS);
+ wsptr[6*6] = (int) RIGHT_SHIFT(tmp25 - tmp15, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 12 rows from work array, store into output array.
+ * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 12; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp10 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp10 <<= CONST_BITS;
+ tmp12 = (INT32) wsptr[4];
+ tmp20 = MULTIPLY(tmp12, FIX(0.707106781)); /* c4 */
+ tmp11 = tmp10 + tmp20;
+ tmp21 = tmp10 - tmp20 - tmp20;
+ tmp20 = (INT32) wsptr[2];
+ tmp10 = MULTIPLY(tmp20, FIX(1.224744871)); /* c2 */
+ tmp20 = tmp11 + tmp10;
+ tmp22 = tmp11 - tmp10;
+
+ /* Odd part */
+
+ z1 = (INT32) wsptr[1];
+ z2 = (INT32) wsptr[3];
+ z3 = (INT32) wsptr[5];
+ tmp11 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp10 = tmp11 + ((z1 + z2) << CONST_BITS);
+ tmp12 = tmp11 + ((z3 - z2) << CONST_BITS);
+ tmp11 = (z1 - z2 - z3) << CONST_BITS;
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp20 + tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[5] = range_limit[(int) RIGHT_SHIFT(tmp20 - tmp10,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp21 + tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp21 - tmp11,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp22 + tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp22 - tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 6; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 5x10 output block.
+ *
+ * 10-point IDCT in pass 1 (columns), 5-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_5x10 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp10, tmp11, tmp12, tmp13, tmp14;
+ INT32 tmp20, tmp21, tmp22, tmp23, tmp24;
+ INT32 z1, z2, z3, z4, z5;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[5*10]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 10-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/20).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 5; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ z3 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z3 += ONE << (CONST_BITS-PASS1_BITS-1);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z1 = MULTIPLY(z4, FIX(1.144122806)); /* c4 */
+ z2 = MULTIPLY(z4, FIX(0.437016024)); /* c8 */
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z2;
+
+ tmp22 = RIGHT_SHIFT(z3 - ((z1 - z2) << 1), /* c0 = (c4-c8)*2 */
+ CONST_BITS-PASS1_BITS);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c6 */
+ tmp12 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c2-c6 */
+ tmp13 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c2+c6 */
+
+ tmp20 = tmp10 + tmp12;
+ tmp24 = tmp10 - tmp12;
+ tmp21 = tmp11 + tmp13;
+ tmp23 = tmp11 - tmp13;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ z4 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+
+ tmp11 = z2 + z4;
+ tmp13 = z2 - z4;
+
+ tmp12 = MULTIPLY(tmp13, FIX(0.309016994)); /* (c3-c7)/2 */
+ z5 = z3 << CONST_BITS;
+
+ z2 = MULTIPLY(tmp11, FIX(0.951056516)); /* (c3+c7)/2 */
+ z4 = z5 + tmp12;
+
+ tmp10 = MULTIPLY(z1, FIX(1.396802247)) + z2 + z4; /* c1 */
+ tmp14 = MULTIPLY(z1, FIX(0.221231742)) - z2 + z4; /* c9 */
+
+ z2 = MULTIPLY(tmp11, FIX(0.587785252)); /* (c1-c9)/2 */
+ z4 = z5 - tmp12 - (tmp13 << (CONST_BITS - 1));
+
+ tmp12 = (z1 - tmp13 - z3) << PASS1_BITS;
+
+ tmp11 = MULTIPLY(z1, FIX(1.260073511)) - z2 - z4; /* c3 */
+ tmp13 = MULTIPLY(z1, FIX(0.642039522)) - z2 + z4; /* c7 */
+
+ /* Final output stage */
+
+ wsptr[5*0] = (int) RIGHT_SHIFT(tmp20 + tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[5*9] = (int) RIGHT_SHIFT(tmp20 - tmp10, CONST_BITS-PASS1_BITS);
+ wsptr[5*1] = (int) RIGHT_SHIFT(tmp21 + tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[5*8] = (int) RIGHT_SHIFT(tmp21 - tmp11, CONST_BITS-PASS1_BITS);
+ wsptr[5*2] = (int) (tmp22 + tmp12);
+ wsptr[5*7] = (int) (tmp22 - tmp12);
+ wsptr[5*3] = (int) RIGHT_SHIFT(tmp23 + tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[5*6] = (int) RIGHT_SHIFT(tmp23 - tmp13, CONST_BITS-PASS1_BITS);
+ wsptr[5*4] = (int) RIGHT_SHIFT(tmp24 + tmp14, CONST_BITS-PASS1_BITS);
+ wsptr[5*5] = (int) RIGHT_SHIFT(tmp24 - tmp14, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 10 rows from work array, store into output array.
+ * 5-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/10).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 10; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp12 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp12 <<= CONST_BITS;
+ tmp13 = (INT32) wsptr[2];
+ tmp14 = (INT32) wsptr[4];
+ z1 = MULTIPLY(tmp13 + tmp14, FIX(0.790569415)); /* (c2+c4)/2 */
+ z2 = MULTIPLY(tmp13 - tmp14, FIX(0.353553391)); /* (c2-c4)/2 */
+ z3 = tmp12 + z2;
+ tmp10 = z3 + z1;
+ tmp11 = z3 - z1;
+ tmp12 -= z2 << 2;
+
+ /* Odd part */
+
+ z2 = (INT32) wsptr[1];
+ z3 = (INT32) wsptr[3];
+
+ z1 = MULTIPLY(z2 + z3, FIX(0.831253876)); /* c3 */
+ tmp13 = z1 + MULTIPLY(z2, FIX(0.513743148)); /* c1-c3 */
+ tmp14 = z1 - MULTIPLY(z3, FIX(2.176250899)); /* c1+c3 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[4] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp13,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp11 + tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp11 - tmp14,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 5; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 4x8 output block.
+ *
+ * 8-point IDCT in pass 1 (columns), 4-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_4x8 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp3;
+ INT32 tmp10, tmp11, tmp12, tmp13;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[4*8]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array. */
+ /* Note results are scaled up by sqrt(8) compared to a true IDCT; */
+ /* furthermore, we scale the results by 2**PASS1_BITS. */
+
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 4; ctr > 0; ctr--) {
+ /* Due to quantization, we will usually find that many of the input
+ * coefficients are zero, especially the AC terms. We can exploit this
+ * by short-circuiting the IDCT calculation for any column in which all
+ * the AC terms are zero. In that case each output is equal to the
+ * DC coefficient (with scale factor as needed).
+ * With typical images and quantization tables, half or more of the
+ * column DCT calculations can be simplified this way.
+ */
+
+ if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 &&
+ inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 &&
+ inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 &&
+ inptr[DCTSIZE*7] == 0) {
+ /* AC terms all zero */
+ int dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]) << PASS1_BITS;
+
+ wsptr[4*0] = dcval;
+ wsptr[4*1] = dcval;
+ wsptr[4*2] = dcval;
+ wsptr[4*3] = dcval;
+ wsptr[4*4] = dcval;
+ wsptr[4*5] = dcval;
+ wsptr[4*6] = dcval;
+ wsptr[4*7] = dcval;
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ continue;
+ }
+
+ /* Even part: reverse the even part of the forward DCT. */
+ /* The rotator is sqrt(2)*c(-6). */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100);
+ tmp2 = z1 + MULTIPLY(z2, FIX_0_765366865);
+ tmp3 = z1 - MULTIPLY(z3, FIX_1_847759065);
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ z2 <<= CONST_BITS;
+ z3 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ z2 += ONE << (CONST_BITS-PASS1_BITS-1);
+
+ tmp0 = z2 + z3;
+ tmp1 = z2 - z3;
+
+ tmp10 = tmp0 + tmp2;
+ tmp13 = tmp0 - tmp2;
+ tmp11 = tmp1 + tmp3;
+ tmp12 = tmp1 - tmp3;
+
+ /* Odd part per figure 8; the matrix is unitary and hence its
+ * transpose is its inverse. i0..i3 are y7,y5,y3,y1 respectively.
+ */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]);
+ tmp1 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ tmp3 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ z2 = tmp0 + tmp2;
+ z3 = tmp1 + tmp3;
+
+ z1 = MULTIPLY(z2 + z3, FIX_1_175875602); /* sqrt(2) * c3 */
+ z2 = MULTIPLY(z2, - FIX_1_961570560); /* sqrt(2) * (-c3-c5) */
+ z3 = MULTIPLY(z3, - FIX_0_390180644); /* sqrt(2) * (c5-c3) */
+ z2 += z1;
+ z3 += z1;
+
+ z1 = MULTIPLY(tmp0 + tmp3, - FIX_0_899976223); /* sqrt(2) * (c7-c3) */
+ tmp0 = MULTIPLY(tmp0, FIX_0_298631336); /* sqrt(2) * (-c1+c3+c5-c7) */
+ tmp3 = MULTIPLY(tmp3, FIX_1_501321110); /* sqrt(2) * ( c1+c3-c5-c7) */
+ tmp0 += z1 + z2;
+ tmp3 += z1 + z3;
+
+ z1 = MULTIPLY(tmp1 + tmp2, - FIX_2_562915447); /* sqrt(2) * (-c1-c3) */
+ tmp1 = MULTIPLY(tmp1, FIX_2_053119869); /* sqrt(2) * ( c1+c3-c5+c7) */
+ tmp2 = MULTIPLY(tmp2, FIX_3_072711026); /* sqrt(2) * ( c1+c3+c5-c7) */
+ tmp1 += z1 + z3;
+ tmp2 += z1 + z2;
+
+ /* Final output stage: inputs are tmp10..tmp13, tmp0..tmp3 */
+
+ wsptr[4*0] = (int) RIGHT_SHIFT(tmp10 + tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[4*7] = (int) RIGHT_SHIFT(tmp10 - tmp3, CONST_BITS-PASS1_BITS);
+ wsptr[4*1] = (int) RIGHT_SHIFT(tmp11 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[4*6] = (int) RIGHT_SHIFT(tmp11 - tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[4*2] = (int) RIGHT_SHIFT(tmp12 + tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[4*5] = (int) RIGHT_SHIFT(tmp12 - tmp1, CONST_BITS-PASS1_BITS);
+ wsptr[4*3] = (int) RIGHT_SHIFT(tmp13 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[4*4] = (int) RIGHT_SHIFT(tmp13 - tmp0, CONST_BITS-PASS1_BITS);
+
+ inptr++; /* advance pointers to next column */
+ quantptr++;
+ wsptr++;
+ }
+
+ /* Pass 2: process 8 rows from work array, store into output array.
+ * 4-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/16).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 8; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp2 = (INT32) wsptr[2];
+
+ tmp10 = (tmp0 + tmp2) << CONST_BITS;
+ tmp12 = (tmp0 - tmp2) << CONST_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = (INT32) wsptr[1];
+ z3 = (INT32) wsptr[3];
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[3] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp12 + tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp12 - tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 4; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a reduced-size 3x6 output block.
+ *
+ * 6-point IDCT in pass 1 (columns), 3-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_3x6 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp1, tmp2, tmp10, tmp11, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ int * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ int workspace[3*6]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 6-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/12).
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 3; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp0 <<= CONST_BITS;
+ /* Add fudge factor here for final descale. */
+ tmp0 += ONE << (CONST_BITS-PASS1_BITS-1);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]);
+ tmp10 = MULTIPLY(tmp2, FIX(0.707106781)); /* c4 */
+ tmp1 = tmp0 + tmp10;
+ tmp11 = RIGHT_SHIFT(tmp0 - tmp10 - tmp10, CONST_BITS-PASS1_BITS);
+ tmp10 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+ tmp0 = MULTIPLY(tmp10, FIX(1.224744871)); /* c2 */
+ tmp10 = tmp1 + tmp0;
+ tmp12 = tmp1 - tmp0;
+
+ /* Odd part */
+
+ z1 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z2 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]);
+ tmp1 = MULTIPLY(z1 + z3, FIX(0.366025404)); /* c5 */
+ tmp0 = tmp1 + ((z1 + z2) << CONST_BITS);
+ tmp2 = tmp1 + ((z3 - z2) << CONST_BITS);
+ tmp1 = (z1 - z2 - z3) << PASS1_BITS;
+
+ /* Final output stage */
+
+ wsptr[3*0] = (int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[3*5] = (int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS-PASS1_BITS);
+ wsptr[3*1] = (int) (tmp11 + tmp1);
+ wsptr[3*4] = (int) (tmp11 - tmp1);
+ wsptr[3*2] = (int) RIGHT_SHIFT(tmp12 + tmp2, CONST_BITS-PASS1_BITS);
+ wsptr[3*3] = (int) RIGHT_SHIFT(tmp12 - tmp2, CONST_BITS-PASS1_BITS);
+ }
+
+ /* Pass 2: process 6 rows from work array, store into output array.
+ * 3-point IDCT kernel, cK represents sqrt(2) * cos(K*pi/6).
+ */
+ wsptr = workspace;
+ for (ctr = 0; ctr < 6; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp0 = (INT32) wsptr[0] + (ONE << (PASS1_BITS+2));
+ tmp0 <<= CONST_BITS;
+ tmp2 = (INT32) wsptr[2];
+ tmp12 = MULTIPLY(tmp2, FIX(0.707106781)); /* c2 */
+ tmp10 = tmp0 + tmp12;
+ tmp2 = tmp0 - tmp12 - tmp12;
+
+ /* Odd part */
+
+ tmp12 = (INT32) wsptr[1];
+ tmp0 = MULTIPLY(tmp12, FIX(1.224744871)); /* c1 */
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[2] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp2,
+ CONST_BITS+PASS1_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 3; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 2x4 output block.
+ *
+ * 4-point IDCT in pass 1 (columns), 2-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_2x4 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp2, tmp10, tmp12;
+ INT32 z1, z2, z3;
+ JCOEFPTR inptr;
+ ISLOW_MULT_TYPE * quantptr;
+ INT32 * wsptr;
+ JSAMPROW outptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ int ctr;
+ INT32 workspace[2*4]; /* buffers data between passes */
+ SHIFT_TEMPS
+
+ /* Pass 1: process columns from input, store into work array.
+ * 4-point IDCT kernel,
+ * cK represents sqrt(2) * cos(K*pi/16) [refers to 8-point IDCT].
+ */
+ inptr = coef_block;
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+ wsptr = workspace;
+ for (ctr = 0; ctr < 2; ctr++, inptr++, quantptr++, wsptr++) {
+ /* Even part */
+
+ tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ tmp2 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]);
+
+ tmp10 = (tmp0 + tmp2) << CONST_BITS;
+ tmp12 = (tmp0 - tmp2) << CONST_BITS;
+
+ /* Odd part */
+ /* Same rotation as in the even part of the 8x8 LL&M IDCT */
+
+ z2 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]);
+ z3 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]);
+
+ z1 = MULTIPLY(z2 + z3, FIX_0_541196100); /* c6 */
+ tmp0 = z1 + MULTIPLY(z2, FIX_0_765366865); /* c2-c6 */
+ tmp2 = z1 - MULTIPLY(z3, FIX_1_847759065); /* c2+c6 */
+
+ /* Final output stage */
+
+ wsptr[2*0] = tmp10 + tmp0;
+ wsptr[2*3] = tmp10 - tmp0;
+ wsptr[2*1] = tmp12 + tmp2;
+ wsptr[2*2] = tmp12 - tmp2;
+ }
+
+ /* Pass 2: process 4 rows from work array, store into output array. */
+
+ wsptr = workspace;
+ for (ctr = 0; ctr < 4; ctr++) {
+ outptr = output_buf[ctr] + output_col;
+
+ /* Even part */
+
+ /* Add fudge factor here for final descale. */
+ tmp10 = wsptr[0] + (ONE << (CONST_BITS+2));
+
+ /* Odd part */
+
+ tmp0 = wsptr[1];
+
+ /* Final output stage */
+
+ outptr[0] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, CONST_BITS+3)
+ & RANGE_MASK];
+ outptr[1] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, CONST_BITS+3)
+ & RANGE_MASK];
+
+ wsptr += 2; /* advance pointer to next row */
+ }
+}
+
+
+/*
+ * Perform dequantization and inverse DCT on one block of coefficients,
+ * producing a 1x2 output block.
+ *
+ * 2-point IDCT in pass 1 (columns), 1-point in pass 2 (rows).
+ */
+
+GLOBAL(void)
+jpeg_idct_1x2 (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col)
+{
+ INT32 tmp0, tmp10;
+ ISLOW_MULT_TYPE * quantptr;
+ JSAMPLE *range_limit = IDCT_range_limit(cinfo);
+ SHIFT_TEMPS
+
+ /* Process 1 column from input, store into output array. */
+
+ quantptr = (ISLOW_MULT_TYPE *) compptr->dct_table;
+
+ /* Even part */
+
+ tmp10 = DEQUANTIZE(coef_block[DCTSIZE*0], quantptr[DCTSIZE*0]);
+ /* Add fudge factor here for final descale. */
+ tmp10 += ONE << 2;
+
+ /* Odd part */
+
+ tmp0 = DEQUANTIZE(coef_block[DCTSIZE*1], quantptr[DCTSIZE*1]);
+
+ /* Final output stage */
+
+ output_buf[0][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 + tmp0, 3)
+ & RANGE_MASK];
+ output_buf[1][output_col] = range_limit[(int) RIGHT_SHIFT(tmp10 - tmp0, 3)
+ & RANGE_MASK];
+}
+
+#endif /* IDCT_SCALING_SUPPORTED */
+#endif /* DCT_ISLOW_SUPPORTED */
diff --git a/Source/LibJPEG/jinclude.h b/Source/LibJPEG/jinclude.h
new file mode 100644
index 0000000..0a4f151
--- /dev/null
+++ b/Source/LibJPEG/jinclude.h
@@ -0,0 +1,91 @@
+/*
+ * jinclude.h
+ *
+ * Copyright (C) 1991-1994, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file exists to provide a single place to fix any problems with
+ * including the wrong system include files. (Common problems are taken
+ * care of by the standard jconfig symbols, but on really weird systems
+ * you may have to edit this file.)
+ *
+ * NOTE: this file is NOT intended to be included by applications using the
+ * JPEG library. Most applications need only include jpeglib.h.
+ */
+
+
+/* Include auto-config file to find out which system include files we need. */
+
+#include "jconfig.h" /* auto configuration options */
+#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */
+
+/*
+ * We need the NULL macro and size_t typedef.
+ * On an ANSI-conforming system it is sufficient to include <stddef.h>.
+ * Otherwise, we get them from <stdlib.h> or <stdio.h>; we may have to
+ * pull in <sys/types.h> as well.
+ * Note that the core JPEG library does not require <stdio.h>;
+ * only the default error handler and data source/destination modules do.
+ * But we must pull it in because of the references to FILE in jpeglib.h.
+ * You can remove those references if you want to compile without <stdio.h>.
+ */
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+
+/*
+ * We need memory copying and zeroing functions, plus strncpy().
+ * ANSI and System V implementations declare these in <string.h>.
+ * BSD doesn't have the mem() functions, but it does have bcopy()/bzero().
+ * Some systems may declare memset and memcpy in <memory.h>.
+ *
+ * NOTE: we assume the size parameters to these functions are of type size_t.
+ * Change the casts in these macros if not!
+ */
+
+#ifdef NEED_BSD_STRINGS
+
+#include <strings.h>
+#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size))
+#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size))
+
+#else /* not BSD, assume ANSI/SysV string lib */
+
+#include <string.h>
+#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size))
+#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size))
+
+#endif
+
+/*
+ * In ANSI C, and indeed any rational implementation, size_t is also the
+ * type returned by sizeof(). However, it seems there are some irrational
+ * implementations out there, in which sizeof() returns an int even though
+ * size_t is defined as long or unsigned long. To ensure consistent results
+ * we always use this SIZEOF() macro in place of using sizeof() directly.
+ */
+
+#define SIZEOF(object) ((size_t) sizeof(object))
+
+/*
+ * The modules that use fread() and fwrite() always invoke them through
+ * these macros. On some systems you may need to twiddle the argument casts.
+ * CAUTION: argument order is different from underlying functions!
+ */
+
+#define JFREAD(file,buf,sizeofbuf) \
+ ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
+#define JFWRITE(file,buf,sizeofbuf) \
+ ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
diff --git a/Source/LibJPEG/jmemansi.c b/Source/LibJPEG/jmemansi.c
new file mode 100644
index 0000000..2d93e49
--- /dev/null
+++ b/Source/LibJPEG/jmemansi.c
@@ -0,0 +1,167 @@
+/*
+ * jmemansi.c
+ *
+ * Copyright (C) 1992-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a simple generic implementation of the system-
+ * dependent portion of the JPEG memory manager. This implementation
+ * assumes that you have the ANSI-standard library routine tmpfile().
+ * Also, the problem of determining the amount of memory available
+ * is shoved onto the user.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
+#define SEEK_SET 0 /* if not, assume 0 is correct */
+#endif
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * It's impossible to do this in a portable way; our current solution is
+ * to make the user tell us (with a default value set at compile time).
+ * If you can actually get the available space, it's a good idea to subtract
+ * a slop factor of 5% or so.
+ */
+
+#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
+#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
+#endif
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return cinfo->mem->max_memory_to_use - already_allocated;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Backing store objects are only used when the value returned by
+ * jpeg_mem_available is less than the total space needed. You can dispense
+ * with these routines if you have plenty of virtual memory; see jmemnobs.c.
+ */
+
+
+METHODDEF(void)
+read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (fseek(info->temp_file, file_offset, SEEK_SET))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ if (JFREAD(info->temp_file, buffer_address, byte_count)
+ != (size_t) byte_count)
+ ERREXIT(cinfo, JERR_TFILE_READ);
+}
+
+
+METHODDEF(void)
+write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (fseek(info->temp_file, file_offset, SEEK_SET))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ if (JFWRITE(info->temp_file, buffer_address, byte_count)
+ != (size_t) byte_count)
+ ERREXIT(cinfo, JERR_TFILE_WRITE);
+}
+
+
+METHODDEF(void)
+close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ fclose(info->temp_file);
+ /* Since this implementation uses tmpfile() to create the file,
+ * no explicit file deletion is needed.
+ */
+}
+
+
+/*
+ * Initial opening of a backing-store object.
+ *
+ * This version uses tmpfile(), which constructs a suitable file name
+ * behind the scenes. We don't have to use info->temp_name[] at all;
+ * indeed, we can't even find out the actual name of the temp file.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ if ((info->temp_file = tmpfile()) == NULL)
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "");
+ info->read_backing_store = read_backing_store;
+ info->write_backing_store = write_backing_store;
+ info->close_backing_store = close_backing_store;
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/Source/LibJPEG/jmemdos.c b/Source/LibJPEG/jmemdos.c
new file mode 100644
index 0000000..60b45c6
--- /dev/null
+++ b/Source/LibJPEG/jmemdos.c
@@ -0,0 +1,638 @@
+/*
+ * jmemdos.c
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides an MS-DOS-compatible implementation of the system-
+ * dependent portion of the JPEG memory manager. Temporary data can be
+ * stored in extended or expanded memory as well as in regular DOS files.
+ *
+ * If you use this file, you must be sure that NEED_FAR_POINTERS is defined
+ * if you compile in a small-data memory model; it should NOT be defined if
+ * you use a large-data memory model. This file is not recommended if you
+ * are using a flat-memory-space 386 environment such as DJGCC or Watcom C.
+ * Also, this code will NOT work if struct fields are aligned on greater than
+ * 2-byte boundaries.
+ *
+ * Based on code contributed by Ge' Weijers.
+ */
+
+/*
+ * If you have both extended and expanded memory, you may want to change the
+ * order in which they are tried in jopen_backing_store. On a 286 machine
+ * expanded memory is usually faster, since extended memory access involves
+ * an expensive protected-mode-and-back switch. On 386 and better, extended
+ * memory is usually faster. As distributed, the code tries extended memory
+ * first (what? not everyone has a 386? :-).
+ *
+ * You can disable use of extended/expanded memory entirely by altering these
+ * definitions or overriding them from the Makefile (eg, -DEMS_SUPPORTED=0).
+ */
+
+#ifndef XMS_SUPPORTED
+#define XMS_SUPPORTED 1
+#endif
+#ifndef EMS_SUPPORTED
+#define EMS_SUPPORTED 1
+#endif
+
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare these */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+extern char * getenv JPP((const char * name));
+#endif
+
+#ifdef NEED_FAR_POINTERS
+
+#ifdef __TURBOC__
+/* These definitions work for Borland C (Turbo C) */
+#include <alloc.h> /* need farmalloc(), farfree() */
+#define far_malloc(x) farmalloc(x)
+#define far_free(x) farfree(x)
+#else
+/* These definitions work for Microsoft C and compatible compilers */
+#include <malloc.h> /* need _fmalloc(), _ffree() */
+#define far_malloc(x) _fmalloc(x)
+#define far_free(x) _ffree(x)
+#endif
+
+#else /* not NEED_FAR_POINTERS */
+
+#define far_malloc(x) malloc(x)
+#define far_free(x) free(x)
+
+#endif /* NEED_FAR_POINTERS */
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#else
+#define READ_BINARY "rb"
+#endif
+
+#ifndef USE_MSDOS_MEMMGR /* make sure user got configuration right */
+ You forgot to define USE_MSDOS_MEMMGR in jconfig.h. /* deliberate syntax error */
+#endif
+
+#if MAX_ALLOC_CHUNK >= 65535L /* make sure jconfig.h got this right */
+ MAX_ALLOC_CHUNK should be less than 64K. /* deliberate syntax error */
+#endif
+
+
+/*
+ * Declarations for assembly-language support routines (see jmemdosa.asm).
+ *
+ * The functions are declared "far" as are all their pointer arguments;
+ * this ensures the assembly source code will work regardless of the
+ * compiler memory model. We assume "short" is 16 bits, "long" is 32.
+ */
+
+typedef void far * XMSDRIVER; /* actually a pointer to code */
+typedef struct { /* registers for calling XMS driver */
+ unsigned short ax, dx, bx;
+ void far * ds_si;
+ } XMScontext;
+typedef struct { /* registers for calling EMS driver */
+ unsigned short ax, dx, bx;
+ void far * ds_si;
+ } EMScontext;
+
+extern short far jdos_open JPP((short far * handle, char far * filename));
+extern short far jdos_close JPP((short handle));
+extern short far jdos_seek JPP((short handle, long offset));
+extern short far jdos_read JPP((short handle, void far * buffer,
+ unsigned short count));
+extern short far jdos_write JPP((short handle, void far * buffer,
+ unsigned short count));
+extern void far jxms_getdriver JPP((XMSDRIVER far *));
+extern void far jxms_calldriver JPP((XMSDRIVER, XMScontext far *));
+extern short far jems_available JPP((void));
+extern void far jems_calldriver JPP((EMScontext far *));
+
+
+/*
+ * Selection of a file name for a temporary file.
+ * This is highly system-dependent, and you may want to customize it.
+ */
+
+static int next_file_num; /* to distinguish among several temp files */
+
+LOCAL(void)
+select_file_name (char * fname)
+{
+ const char * env;
+ char * ptr;
+ FILE * tfile;
+
+ /* Keep generating file names till we find one that's not in use */
+ for (;;) {
+ /* Get temp directory name from environment TMP or TEMP variable;
+ * if none, use "."
+ */
+ if ((env = (const char *) getenv("TMP")) == NULL)
+ if ((env = (const char *) getenv("TEMP")) == NULL)
+ env = ".";
+ if (*env == '\0') /* null string means "." */
+ env = ".";
+ ptr = fname; /* copy name to fname */
+ while (*env != '\0')
+ *ptr++ = *env++;
+ if (ptr[-1] != '\\' && ptr[-1] != '/')
+ *ptr++ = '\\'; /* append backslash if not in env variable */
+ /* Append a suitable file name */
+ next_file_num++; /* advance counter */
+ sprintf(ptr, "JPG%03d.TMP", next_file_num);
+ /* Probe to see if file name is already in use */
+ if ((tfile = fopen(fname, READ_BINARY)) == NULL)
+ break;
+ fclose(tfile); /* oops, it's there; close tfile & try again */
+ }
+}
+
+
+/*
+ * Near-memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are allocated in far memory, if possible
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) far_malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ far_free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * It's impossible to do this in a portable way; our current solution is
+ * to make the user tell us (with a default value set at compile time).
+ * If you can actually get the available space, it's a good idea to subtract
+ * a slop factor of 5% or so.
+ */
+
+#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
+#define DEFAULT_MAX_MEM 300000L /* for total usage about 450K */
+#endif
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return cinfo->mem->max_memory_to_use - already_allocated;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Backing store objects are only used when the value returned by
+ * jpeg_mem_available is less than the total space needed. You can dispense
+ * with these routines if you have plenty of virtual memory; see jmemnobs.c.
+ */
+
+/*
+ * For MS-DOS we support three types of backing storage:
+ * 1. Conventional DOS files. We access these by direct DOS calls rather
+ * than via the stdio package. This provides a bit better performance,
+ * but the real reason is that the buffers to be read or written are FAR.
+ * The stdio library for small-data memory models can't cope with that.
+ * 2. Extended memory, accessed per the XMS V2.0 specification.
+ * 3. Expanded memory, accessed per the LIM/EMS 4.0 specification.
+ * You'll need copies of those specs to make sense of the related code.
+ * The specs are available by Internet FTP from the SIMTEL archives
+ * (oak.oakland.edu and its various mirror sites). See files
+ * pub/msdos/microsoft/xms20.arc and pub/msdos/info/limems41.zip.
+ */
+
+
+/*
+ * Access methods for a DOS file.
+ */
+
+
+METHODDEF(void)
+read_file_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (jdos_seek(info->handle.file_handle, file_offset))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
+ if (byte_count > 65535L) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+ if (jdos_read(info->handle.file_handle, buffer_address,
+ (unsigned short) byte_count))
+ ERREXIT(cinfo, JERR_TFILE_READ);
+}
+
+
+METHODDEF(void)
+write_file_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (jdos_seek(info->handle.file_handle, file_offset))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ /* Since MAX_ALLOC_CHUNK is less than 64K, byte_count will be too. */
+ if (byte_count > 65535L) /* safety check */
+ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+ if (jdos_write(info->handle.file_handle, buffer_address,
+ (unsigned short) byte_count))
+ ERREXIT(cinfo, JERR_TFILE_WRITE);
+}
+
+
+METHODDEF(void)
+close_file_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ jdos_close(info->handle.file_handle); /* close the file */
+ remove(info->temp_name); /* delete the file */
+/* If your system doesn't have remove(), try unlink() instead.
+ * remove() is the ANSI-standard name for this function, but
+ * unlink() was more common in pre-ANSI systems.
+ */
+ TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
+}
+
+
+LOCAL(boolean)
+open_file_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ short handle;
+
+ select_file_name(info->temp_name);
+ if (jdos_open((short far *) & handle, (char far *) info->temp_name)) {
+ /* might as well exit since jpeg_open_backing_store will fail anyway */
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+ return FALSE;
+ }
+ info->handle.file_handle = handle;
+ info->read_backing_store = read_file_store;
+ info->write_backing_store = write_file_store;
+ info->close_backing_store = close_file_store;
+ TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
+ return TRUE; /* succeeded */
+}
+
+
+/*
+ * Access methods for extended memory.
+ */
+
+#if XMS_SUPPORTED
+
+static XMSDRIVER xms_driver; /* saved address of XMS driver */
+
+typedef union { /* either long offset or real-mode pointer */
+ long offset;
+ void far * ptr;
+ } XMSPTR;
+
+typedef struct { /* XMS move specification structure */
+ long length;
+ XMSH src_handle;
+ XMSPTR src;
+ XMSH dst_handle;
+ XMSPTR dst;
+ } XMSspec;
+
+#define ODD(X) (((X) & 1L) != 0)
+
+
+METHODDEF(void)
+read_xms_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ XMScontext ctx;
+ XMSspec spec;
+ char endbuffer[2];
+
+ /* The XMS driver can't cope with an odd length, so handle the last byte
+ * specially if byte_count is odd. We don't expect this to be common.
+ */
+
+ spec.length = byte_count & (~ 1L);
+ spec.src_handle = info->handle.xms_handle;
+ spec.src.offset = file_offset;
+ spec.dst_handle = 0;
+ spec.dst.ptr = buffer_address;
+
+ ctx.ds_si = (void far *) & spec;
+ ctx.ax = 0x0b00; /* EMB move */
+ jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
+ if (ctx.ax != 1)
+ ERREXIT(cinfo, JERR_XMS_READ);
+
+ if (ODD(byte_count)) {
+ read_xms_store(cinfo, info, (void FAR *) endbuffer,
+ file_offset + byte_count - 1L, 2L);
+ ((char FAR *) buffer_address)[byte_count - 1L] = endbuffer[0];
+ }
+}
+
+
+METHODDEF(void)
+write_xms_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ XMScontext ctx;
+ XMSspec spec;
+ char endbuffer[2];
+
+ /* The XMS driver can't cope with an odd length, so handle the last byte
+ * specially if byte_count is odd. We don't expect this to be common.
+ */
+
+ spec.length = byte_count & (~ 1L);
+ spec.src_handle = 0;
+ spec.src.ptr = buffer_address;
+ spec.dst_handle = info->handle.xms_handle;
+ spec.dst.offset = file_offset;
+
+ ctx.ds_si = (void far *) & spec;
+ ctx.ax = 0x0b00; /* EMB move */
+ jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
+ if (ctx.ax != 1)
+ ERREXIT(cinfo, JERR_XMS_WRITE);
+
+ if (ODD(byte_count)) {
+ read_xms_store(cinfo, info, (void FAR *) endbuffer,
+ file_offset + byte_count - 1L, 2L);
+ endbuffer[0] = ((char FAR *) buffer_address)[byte_count - 1L];
+ write_xms_store(cinfo, info, (void FAR *) endbuffer,
+ file_offset + byte_count - 1L, 2L);
+ }
+}
+
+
+METHODDEF(void)
+close_xms_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ XMScontext ctx;
+
+ ctx.dx = info->handle.xms_handle;
+ ctx.ax = 0x0a00;
+ jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
+ TRACEMS1(cinfo, 1, JTRC_XMS_CLOSE, info->handle.xms_handle);
+ /* we ignore any error return from the driver */
+}
+
+
+LOCAL(boolean)
+open_xms_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ XMScontext ctx;
+
+ /* Get address of XMS driver */
+ jxms_getdriver((XMSDRIVER far *) & xms_driver);
+ if (xms_driver == NULL)
+ return FALSE; /* no driver to be had */
+
+ /* Get version number, must be >= 2.00 */
+ ctx.ax = 0x0000;
+ jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
+ if (ctx.ax < (unsigned short) 0x0200)
+ return FALSE;
+
+ /* Try to get space (expressed in kilobytes) */
+ ctx.dx = (unsigned short) ((total_bytes_needed + 1023L) >> 10);
+ ctx.ax = 0x0900;
+ jxms_calldriver(xms_driver, (XMScontext far *) & ctx);
+ if (ctx.ax != 1)
+ return FALSE;
+
+ /* Succeeded, save the handle and away we go */
+ info->handle.xms_handle = ctx.dx;
+ info->read_backing_store = read_xms_store;
+ info->write_backing_store = write_xms_store;
+ info->close_backing_store = close_xms_store;
+ TRACEMS1(cinfo, 1, JTRC_XMS_OPEN, ctx.dx);
+ return TRUE; /* succeeded */
+}
+
+#endif /* XMS_SUPPORTED */
+
+
+/*
+ * Access methods for expanded memory.
+ */
+
+#if EMS_SUPPORTED
+
+/* The EMS move specification structure requires word and long fields aligned
+ * at odd byte boundaries. Some compilers will align struct fields at even
+ * byte boundaries. While it's usually possible to force byte alignment,
+ * that causes an overall performance penalty and may pose problems in merging
+ * JPEG into a larger application. Instead we accept some rather dirty code
+ * here. Note this code would fail if the hardware did not allow odd-byte
+ * word & long accesses, but all 80x86 CPUs do.
+ */
+
+typedef void far * EMSPTR;
+
+typedef union { /* EMS move specification structure */
+ long length; /* It's easy to access first 4 bytes */
+ char bytes[18]; /* Misaligned fields in here! */
+ } EMSspec;
+
+/* Macros for accessing misaligned fields */
+#define FIELD_AT(spec,offset,type) (*((type *) &(spec.bytes[offset])))
+#define SRC_TYPE(spec) FIELD_AT(spec,4,char)
+#define SRC_HANDLE(spec) FIELD_AT(spec,5,EMSH)
+#define SRC_OFFSET(spec) FIELD_AT(spec,7,unsigned short)
+#define SRC_PAGE(spec) FIELD_AT(spec,9,unsigned short)
+#define SRC_PTR(spec) FIELD_AT(spec,7,EMSPTR)
+#define DST_TYPE(spec) FIELD_AT(spec,11,char)
+#define DST_HANDLE(spec) FIELD_AT(spec,12,EMSH)
+#define DST_OFFSET(spec) FIELD_AT(spec,14,unsigned short)
+#define DST_PAGE(spec) FIELD_AT(spec,16,unsigned short)
+#define DST_PTR(spec) FIELD_AT(spec,14,EMSPTR)
+
+#define EMSPAGESIZE 16384L /* gospel, see the EMS specs */
+
+#define HIBYTE(W) (((W) >> 8) & 0xFF)
+#define LOBYTE(W) ((W) & 0xFF)
+
+
+METHODDEF(void)
+read_ems_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ EMScontext ctx;
+ EMSspec spec;
+
+ spec.length = byte_count;
+ SRC_TYPE(spec) = 1;
+ SRC_HANDLE(spec) = info->handle.ems_handle;
+ SRC_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
+ SRC_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
+ DST_TYPE(spec) = 0;
+ DST_HANDLE(spec) = 0;
+ DST_PTR(spec) = buffer_address;
+
+ ctx.ds_si = (void far *) & spec;
+ ctx.ax = 0x5700; /* move memory region */
+ jems_calldriver((EMScontext far *) & ctx);
+ if (HIBYTE(ctx.ax) != 0)
+ ERREXIT(cinfo, JERR_EMS_READ);
+}
+
+
+METHODDEF(void)
+write_ems_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ EMScontext ctx;
+ EMSspec spec;
+
+ spec.length = byte_count;
+ SRC_TYPE(spec) = 0;
+ SRC_HANDLE(spec) = 0;
+ SRC_PTR(spec) = buffer_address;
+ DST_TYPE(spec) = 1;
+ DST_HANDLE(spec) = info->handle.ems_handle;
+ DST_PAGE(spec) = (unsigned short) (file_offset / EMSPAGESIZE);
+ DST_OFFSET(spec) = (unsigned short) (file_offset % EMSPAGESIZE);
+
+ ctx.ds_si = (void far *) & spec;
+ ctx.ax = 0x5700; /* move memory region */
+ jems_calldriver((EMScontext far *) & ctx);
+ if (HIBYTE(ctx.ax) != 0)
+ ERREXIT(cinfo, JERR_EMS_WRITE);
+}
+
+
+METHODDEF(void)
+close_ems_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ EMScontext ctx;
+
+ ctx.ax = 0x4500;
+ ctx.dx = info->handle.ems_handle;
+ jems_calldriver((EMScontext far *) & ctx);
+ TRACEMS1(cinfo, 1, JTRC_EMS_CLOSE, info->handle.ems_handle);
+ /* we ignore any error return from the driver */
+}
+
+
+LOCAL(boolean)
+open_ems_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ EMScontext ctx;
+
+ /* Is EMS driver there? */
+ if (! jems_available())
+ return FALSE;
+
+ /* Get status, make sure EMS is OK */
+ ctx.ax = 0x4000;
+ jems_calldriver((EMScontext far *) & ctx);
+ if (HIBYTE(ctx.ax) != 0)
+ return FALSE;
+
+ /* Get version, must be >= 4.0 */
+ ctx.ax = 0x4600;
+ jems_calldriver((EMScontext far *) & ctx);
+ if (HIBYTE(ctx.ax) != 0 || LOBYTE(ctx.ax) < 0x40)
+ return FALSE;
+
+ /* Try to allocate requested space */
+ ctx.ax = 0x4300;
+ ctx.bx = (unsigned short) ((total_bytes_needed + EMSPAGESIZE-1L) / EMSPAGESIZE);
+ jems_calldriver((EMScontext far *) & ctx);
+ if (HIBYTE(ctx.ax) != 0)
+ return FALSE;
+
+ /* Succeeded, save the handle and away we go */
+ info->handle.ems_handle = ctx.dx;
+ info->read_backing_store = read_ems_store;
+ info->write_backing_store = write_ems_store;
+ info->close_backing_store = close_ems_store;
+ TRACEMS1(cinfo, 1, JTRC_EMS_OPEN, ctx.dx);
+ return TRUE; /* succeeded */
+}
+
+#endif /* EMS_SUPPORTED */
+
+
+/*
+ * Initial opening of a backing-store object.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ /* Try extended memory, then expanded memory, then regular file. */
+#if XMS_SUPPORTED
+ if (open_xms_store(cinfo, info, total_bytes_needed))
+ return;
+#endif
+#if EMS_SUPPORTED
+ if (open_ems_store(cinfo, info, total_bytes_needed))
+ return;
+#endif
+ if (open_file_store(cinfo, info, total_bytes_needed))
+ return;
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "");
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ next_file_num = 0; /* initialize temp file name generator */
+ return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* Microsoft C, at least in v6.00A, will not successfully reclaim freed
+ * blocks of size > 32Kbytes unless we give it a kick in the rear, like so:
+ */
+#ifdef NEED_FHEAPMIN
+ _fheapmin();
+#endif
+}
diff --git a/Source/LibJPEG/jmemdosa.asm b/Source/LibJPEG/jmemdosa.asm
new file mode 100644
index 0000000..c6ec48b
--- /dev/null
+++ b/Source/LibJPEG/jmemdosa.asm
@@ -0,0 +1,379 @@
+;
+; jmemdosa.asm
+;
+; Copyright (C) 1992, Thomas G. Lane.
+; This file is part of the Independent JPEG Group's software.
+; For conditions of distribution and use, see the accompanying README file.
+;
+; This file contains low-level interface routines to support the MS-DOS
+; backing store manager (jmemdos.c). Routines are provided to access disk
+; files through direct DOS calls, and to access XMS and EMS drivers.
+;
+; This file should assemble with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler). If you haven't got
+; a compatible assembler, better fall back to jmemansi.c or jmemname.c.
+;
+; To minimize dependence on the C compiler's register usage conventions,
+; we save and restore all 8086 registers, even though most compilers only
+; require SI,DI,DS to be preserved. Also, we use only 16-bit-wide return
+; values, which everybody returns in AX.
+;
+; Based on code contributed by Ge' Weijers.
+;
+
+JMEMDOSA_TXT segment byte public 'CODE'
+
+ assume cs:JMEMDOSA_TXT
+
+ public _jdos_open
+ public _jdos_close
+ public _jdos_seek
+ public _jdos_read
+ public _jdos_write
+ public _jxms_getdriver
+ public _jxms_calldriver
+ public _jems_available
+ public _jems_calldriver
+
+;
+; short far jdos_open (short far * handle, char far * filename)
+;
+; Create and open a temporary file
+;
+_jdos_open proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov cx,0 ; normal file attributes
+ lds dx,dword ptr [bp+10] ; get filename pointer
+ mov ah,3ch ; create file
+ int 21h
+ jc open_err ; if failed, return error code
+ lds bx,dword ptr [bp+6] ; get handle pointer
+ mov word ptr [bx],ax ; save the handle
+ xor ax,ax ; return zero for OK
+open_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_open endp
+
+
+;
+; short far jdos_close (short handle)
+;
+; Close the file handle
+;
+_jdos_close proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ mov ah,3eh ; close file
+ int 21h
+ jc close_err ; if failed, return error code
+ xor ax,ax ; return zero for OK
+close_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_close endp
+
+
+;
+; short far jdos_seek (short handle, long offset)
+;
+; Set file position
+;
+_jdos_seek proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ mov dx,word ptr [bp+8] ; LS offset
+ mov cx,word ptr [bp+10] ; MS offset
+ mov ax,4200h ; absolute seek
+ int 21h
+ jc seek_err ; if failed, return error code
+ xor ax,ax ; return zero for OK
+seek_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_seek endp
+
+
+;
+; short far jdos_read (short handle, void far * buffer, unsigned short count)
+;
+; Read from file
+;
+_jdos_read proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ lds dx,dword ptr [bp+8] ; buffer address
+ mov cx,word ptr [bp+12] ; number of bytes
+ mov ah,3fh ; read file
+ int 21h
+ jc read_err ; if failed, return error code
+ cmp ax,word ptr [bp+12] ; make sure all bytes were read
+ je read_ok
+ mov ax,1 ; else return 1 for not OK
+ jmp short read_err
+read_ok: xor ax,ax ; return zero for OK
+read_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_read endp
+
+
+;
+; short far jdos_write (short handle, void far * buffer, unsigned short count)
+;
+; Write to file
+;
+_jdos_write proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov bx,word ptr [bp+6] ; file handle
+ lds dx,dword ptr [bp+8] ; buffer address
+ mov cx,word ptr [bp+12] ; number of bytes
+ mov ah,40h ; write file
+ int 21h
+ jc write_err ; if failed, return error code
+ cmp ax,word ptr [bp+12] ; make sure all bytes written
+ je write_ok
+ mov ax,1 ; else return 1 for not OK
+ jmp short write_err
+write_ok: xor ax,ax ; return zero for OK
+write_err: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jdos_write endp
+
+
+;
+; void far jxms_getdriver (XMSDRIVER far *)
+;
+; Get the address of the XMS driver, or NULL if not available
+;
+_jxms_getdriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov ax,4300h ; call multiplex interrupt with
+ int 2fh ; a magic cookie, hex 4300
+ cmp al,80h ; AL should contain hex 80
+ je xmsavail
+ xor dx,dx ; no XMS driver available
+ xor ax,ax ; return a nil pointer
+ jmp short xmsavail_done
+xmsavail: mov ax,4310h ; fetch driver address with
+ int 2fh ; another magic cookie
+ mov dx,es ; copy address to dx:ax
+ mov ax,bx
+xmsavail_done: les bx,dword ptr [bp+6] ; get pointer to return value
+ mov word ptr es:[bx],ax
+ mov word ptr es:[bx+2],dx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jxms_getdriver endp
+
+
+;
+; void far jxms_calldriver (XMSDRIVER, XMScontext far *)
+;
+; The XMScontext structure contains values for the AX,DX,BX,SI,DS registers.
+; These are loaded, the XMS call is performed, and the new values of the
+; AX,DX,BX registers are written back to the context structure.
+;
+_jxms_calldriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ les bx,dword ptr [bp+10] ; get XMScontext pointer
+ mov ax,word ptr es:[bx] ; load registers
+ mov dx,word ptr es:[bx+2]
+ mov si,word ptr es:[bx+6]
+ mov ds,word ptr es:[bx+8]
+ mov bx,word ptr es:[bx+4]
+ call dword ptr [bp+6] ; call the driver
+ mov cx,bx ; save returned BX for a sec
+ les bx,dword ptr [bp+10] ; get XMScontext pointer
+ mov word ptr es:[bx],ax ; put back ax,dx,bx
+ mov word ptr es:[bx+2],dx
+ mov word ptr es:[bx+4],cx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jxms_calldriver endp
+
+
+;
+; short far jems_available (void)
+;
+; Have we got an EMS driver? (this comes straight from the EMS 4.0 specs)
+;
+_jems_available proc far
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ mov ax,3567h ; get interrupt vector 67h
+ int 21h
+ push cs
+ pop ds
+ mov di,000ah ; check offs 10 in returned seg
+ lea si,ASCII_device_name ; against literal string
+ mov cx,8
+ cld
+ repe cmpsb
+ jne no_ems
+ mov ax,1 ; match, it's there
+ jmp short avail_done
+no_ems: xor ax,ax ; it's not there
+avail_done: pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ ret
+
+ASCII_device_name db "EMMXXXX0"
+
+_jems_available endp
+
+
+;
+; void far jems_calldriver (EMScontext far *)
+;
+; The EMScontext structure contains values for the AX,DX,BX,SI,DS registers.
+; These are loaded, the EMS trap is performed, and the new values of the
+; AX,DX,BX registers are written back to the context structure.
+;
+_jems_calldriver proc far
+ push bp ; linkage
+ mov bp,sp
+ push si ; save all registers for safety
+ push di
+ push bx
+ push cx
+ push dx
+ push es
+ push ds
+ les bx,dword ptr [bp+6] ; get EMScontext pointer
+ mov ax,word ptr es:[bx] ; load registers
+ mov dx,word ptr es:[bx+2]
+ mov si,word ptr es:[bx+6]
+ mov ds,word ptr es:[bx+8]
+ mov bx,word ptr es:[bx+4]
+ int 67h ; call the EMS driver
+ mov cx,bx ; save returned BX for a sec
+ les bx,dword ptr [bp+6] ; get EMScontext pointer
+ mov word ptr es:[bx],ax ; put back ax,dx,bx
+ mov word ptr es:[bx+2],dx
+ mov word ptr es:[bx+4],cx
+ pop ds ; restore registers and exit
+ pop es
+ pop dx
+ pop cx
+ pop bx
+ pop di
+ pop si
+ pop bp
+ ret
+_jems_calldriver endp
+
+JMEMDOSA_TXT ends
+
+ end
diff --git a/Source/LibJPEG/jmemmac.c b/Source/LibJPEG/jmemmac.c
new file mode 100644
index 0000000..8d21736
--- /dev/null
+++ b/Source/LibJPEG/jmemmac.c
@@ -0,0 +1,291 @@
+/*
+ * jmemmac.c
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * jmemmac.c provides an Apple Macintosh implementation of the system-
+ * dependent portion of the JPEG memory manager.
+ *
+ * If you use jmemmac.c, then you must define USE_MAC_MEMMGR in the
+ * JPEG_INTERNALS part of jconfig.h.
+ *
+ * jmemmac.c uses the Macintosh toolbox routines NewPtr and DisposePtr
+ * instead of malloc and free. It accurately determines the amount of
+ * memory available by using CompactMem. Notice that if left to its
+ * own devices, this code can chew up all available space in the
+ * application's zone, with the exception of the rather small "slop"
+ * factor computed in jpeg_mem_available(). The application can ensure
+ * that more space is left over by reducing max_memory_to_use.
+ *
+ * Large images are swapped to disk using temporary files and System 7.0+'s
+ * temporary folder functionality.
+ *
+ * Note that jmemmac.c depends on two features of MacOS that were first
+ * introduced in System 7: FindFolder and the FSSpec-based calls.
+ * If your application uses jmemmac.c and is run under System 6 or earlier,
+ * and the jpeg library decides it needs a temporary file, it will abort,
+ * printing error messages about requiring System 7. (If no temporary files
+ * are created, it will run fine.)
+ *
+ * If you want to use jmemmac.c in an application that might be used with
+ * System 6 or earlier, then you should remove dependencies on FindFolder
+ * and the FSSpec calls. You will need to replace FindFolder with some
+ * other mechanism for finding a place to put temporary files, and you
+ * should replace the FSSpec calls with their HFS equivalents:
+ *
+ * FSpDelete -> HDelete
+ * FSpGetFInfo -> HGetFInfo
+ * FSpCreate -> HCreate
+ * FSpOpenDF -> HOpen *** Note: not HOpenDF ***
+ * FSMakeFSSpec -> (fill in spec by hand.)
+ *
+ * (Use HOpen instead of HOpenDF. HOpen is just a glue-interface to PBHOpen,
+ * which is on all HFS macs. HOpenDF is a System 7 addition which avoids the
+ * ages-old problem of names starting with a period.)
+ *
+ * Contributed by Sam Bushell (jsam@iagu.on.net) and
+ * Dan Gildor (gyld@in-touch.com).
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef USE_MAC_MEMMGR /* make sure user got configuration right */
+ You forgot to define USE_MAC_MEMMGR in jconfig.h. /* deliberate syntax error */
+#endif
+
+//#include <Memory.h> /* we use the MacOS memory manager */
+//#include <Files.h> /* we use the MacOS File stuff */
+//#include <Folders.h> /* we use the MacOS HFS stuff */
+//#include <Script.h> /* for smSystemScript */
+//#include <Gestalt.h> /* we use Gestalt to test for specific functionality */
+#define __OPENTRANSPORTPROVIDERS__ // Avoid re-definition issues
+#include <CoreServices/CoreServices.h>
+
+#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
+#define TEMP_FILE_NAME "JPG%03d.TMP"
+#endif
+
+static int next_file_num; /* to distinguish among several temp files */
+
+
+/*
+ * Memory allocation and freeing are controlled by the MacOS library
+ * routines NewPtr() and DisposePtr(), which allocate fixed-address
+ * storage. Unfortunately, the IJG library isn't smart enough to cope
+ * with relocatable storage.
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) NewPtr(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ DisposePtr((Ptr) object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: we include FAR keywords in the routine declarations simply for
+ * consistency with the rest of the IJG code; FAR should expand to empty
+ * on rational architectures like the Mac.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) NewPtr(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ DisposePtr((Ptr) object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ long limit = cinfo->mem->max_memory_to_use - already_allocated;
+ long slop, mem;
+
+ /* Don't ask for more than what application has told us we may use */
+ if (max_bytes_needed > limit && limit > 0)
+ max_bytes_needed = limit;
+ /* Find whether there's a big enough free block in the heap.
+ * CompactMem tries to create a contiguous block of the requested size,
+ * and then returns the size of the largest free block (which could be
+ * much more or much less than we asked for).
+ * We add some slop to ensure we don't use up all available memory.
+ */
+ slop = max_bytes_needed / 16 + 32768L;
+ mem = CompactMem(max_bytes_needed + slop) - slop;
+ if (mem < 0)
+ mem = 0; /* sigh, couldn't even get the slop */
+ /* Don't take more than the application says we can have */
+ if (mem > limit && limit > 0)
+ mem = limit;
+ return mem;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Backing store objects are only used when the value returned by
+ * jpeg_mem_available is less than the total space needed. You can dispense
+ * with these routines if you have plenty of virtual memory; see jmemnobs.c.
+ */
+
+
+METHODDEF(void)
+read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ long bytes = byte_count;
+ long retVal;
+
+ if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+
+ retVal = FSRead ( info->temp_file, &bytes,
+ (unsigned char *) buffer_address );
+ if ( retVal != noErr || bytes != byte_count )
+ ERREXIT(cinfo, JERR_TFILE_READ);
+}
+
+
+METHODDEF(void)
+write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ long bytes = byte_count;
+ long retVal;
+
+ if ( SetFPos ( info->temp_file, fsFromStart, file_offset ) != noErr )
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+
+ retVal = FSWrite ( info->temp_file, &bytes,
+ (unsigned char *) buffer_address );
+ if ( retVal != noErr || bytes != byte_count )
+ ERREXIT(cinfo, JERR_TFILE_WRITE);
+}
+
+
+METHODDEF(void)
+close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ FSClose ( info->temp_file );
+ FSpDelete ( &(info->tempSpec) );
+}
+
+
+/*
+ * Initial opening of a backing-store object.
+ *
+ * This version uses FindFolder to find the Temporary Items folder,
+ * and puts the temporary file in there.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ short tmpRef, vRefNum;
+ long dirID;
+ FInfo finderInfo;
+ FSSpec theSpec;
+ Str255 fName;
+ OSErr osErr;
+ long gestaltResponse = 0;
+
+ /* Check that FSSpec calls are available. */
+ osErr = Gestalt( gestaltFSAttr, &gestaltResponse );
+ if ( ( osErr != noErr )
+ || !( gestaltResponse & (1<<gestaltHasFSSpecCalls) ) )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required");
+ /* TO DO: add a proper error message to jerror.h. */
+
+ /* Check that FindFolder is available. */
+ osErr = Gestalt( gestaltFindFolderAttr, &gestaltResponse );
+ if ( ( osErr != noErr )
+ || !( gestaltResponse & (1<<gestaltFindFolderPresent) ) )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- System 7.0 or later required.");
+ /* TO DO: add a proper error message to jerror.h. */
+
+ osErr = FindFolder ( kOnSystemDisk, kTemporaryFolderType, kCreateFolder,
+ &vRefNum, &dirID );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, "- temporary items folder unavailable");
+ /* TO DO: Try putting the temp files somewhere else. */
+
+ /* Keep generating file names till we find one that's not in use */
+ for (;;) {
+ next_file_num++; /* advance counter */
+
+ sprintf(info->temp_name, TEMP_FILE_NAME, next_file_num);
+ strcpy ( (Ptr)fName+1, info->temp_name );
+ *fName = strlen (info->temp_name);
+ osErr = FSMakeFSSpec ( vRefNum, dirID, fName, &theSpec );
+
+ if ( (osErr = FSpGetFInfo ( &theSpec, &finderInfo ) ) != noErr )
+ break;
+ }
+
+ osErr = FSpCreate ( &theSpec, '????', '????', smSystemScript );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+
+ osErr = FSpOpenDF ( &theSpec, fsRdWrPerm, &(info->temp_file) );
+ if ( osErr != noErr )
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+
+ info->tempSpec = theSpec;
+
+ info->read_backing_store = read_backing_store;
+ info->write_backing_store = write_backing_store;
+ info->close_backing_store = close_backing_store;
+ TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ next_file_num = 0;
+
+ /* max_memory_to_use will be initialized to FreeMem()'s result;
+ * the calling application might later reduce it, for example
+ * to leave room to invoke multiple JPEG objects.
+ * Note that FreeMem returns the total number of free bytes;
+ * it may not be possible to allocate a single block of this size.
+ */
+ return FreeMem();
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/Source/LibJPEG/jmemmgr.c b/Source/LibJPEG/jmemmgr.c
new file mode 100644
index 0000000..d801b32
--- /dev/null
+++ b/Source/LibJPEG/jmemmgr.c
@@ -0,0 +1,1118 @@
+/*
+ * jmemmgr.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains the JPEG system-independent memory management
+ * routines. This code is usable across a wide variety of machines; most
+ * of the system dependencies have been isolated in a separate file.
+ * The major functions provided here are:
+ * * pool-based allocation and freeing of memory;
+ * * policy decisions about how to divide available memory among the
+ * virtual arrays;
+ * * control logic for swapping virtual arrays between main memory and
+ * backing storage.
+ * The separate system-dependent file provides the actual backing-storage
+ * access code, and it contains the policy decision about how much total
+ * main memory to use.
+ * This file is system-dependent in the sense that some of its functions
+ * are unnecessary in some systems. For example, if there is enough virtual
+ * memory so that backing storage will never be used, much of the virtual
+ * array control logic could be removed. (Of course, if you have that much
+ * memory then you shouldn't care about a little bit of unused code...)
+ */
+
+#define JPEG_INTERNALS
+#define AM_MEMORY_MANAGER /* we define jvirt_Xarray_control structs */
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef NO_GETENV
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare getenv() */
+extern char * getenv JPP((const char * name));
+#endif
+#endif
+
+
+/*
+ * Some important notes:
+ * The allocation routines provided here must never return NULL.
+ * They should exit to error_exit if unsuccessful.
+ *
+ * It's not a good idea to try to merge the sarray and barray routines,
+ * even though they are textually almost the same, because samples are
+ * usually stored as bytes while coefficients are shorts or ints. Thus,
+ * in machines where byte pointers have a different representation from
+ * word pointers, the resulting machine code could not be the same.
+ */
+
+
+/*
+ * Many machines require storage alignment: longs must start on 4-byte
+ * boundaries, doubles on 8-byte boundaries, etc. On such machines, malloc()
+ * always returns pointers that are multiples of the worst-case alignment
+ * requirement, and we had better do so too.
+ * There isn't any really portable way to determine the worst-case alignment
+ * requirement. This module assumes that the alignment requirement is
+ * multiples of sizeof(ALIGN_TYPE).
+ * By default, we define ALIGN_TYPE as double. This is necessary on some
+ * workstations (where doubles really do need 8-byte alignment) and will work
+ * fine on nearly everything. If your machine has lesser alignment needs,
+ * you can save a few bytes by making ALIGN_TYPE smaller.
+ * The only place I know of where this will NOT work is certain Macintosh
+ * 680x0 compilers that define double as a 10-byte IEEE extended float.
+ * Doing 10-byte alignment is counterproductive because longwords won't be
+ * aligned well. Put "#define ALIGN_TYPE long" in jconfig.h if you have
+ * such a compiler.
+ */
+
+#ifndef ALIGN_TYPE /* so can override from jconfig.h */
+#define ALIGN_TYPE double
+#endif
+
+
+/*
+ * We allocate objects from "pools", where each pool is gotten with a single
+ * request to jpeg_get_small() or jpeg_get_large(). There is no per-object
+ * overhead within a pool, except for alignment padding. Each pool has a
+ * header with a link to the next pool of the same class.
+ * Small and large pool headers are identical except that the latter's
+ * link pointer must be FAR on 80x86 machines.
+ * Notice that the "real" header fields are union'ed with a dummy ALIGN_TYPE
+ * field. This forces the compiler to make SIZEOF(small_pool_hdr) a multiple
+ * of the alignment requirement of ALIGN_TYPE.
+ */
+
+typedef union small_pool_struct * small_pool_ptr;
+
+typedef union small_pool_struct {
+ struct {
+ small_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} small_pool_hdr;
+
+typedef union large_pool_struct FAR * large_pool_ptr;
+
+typedef union large_pool_struct {
+ struct {
+ large_pool_ptr next; /* next in list of pools */
+ size_t bytes_used; /* how many bytes already used within pool */
+ size_t bytes_left; /* bytes still available in this pool */
+ } hdr;
+ ALIGN_TYPE dummy; /* included in union to ensure alignment */
+} large_pool_hdr;
+
+
+/*
+ * Here is the full definition of a memory manager object.
+ */
+
+typedef struct {
+ struct jpeg_memory_mgr pub; /* public fields */
+
+ /* Each pool identifier (lifetime class) names a linked list of pools. */
+ small_pool_ptr small_list[JPOOL_NUMPOOLS];
+ large_pool_ptr large_list[JPOOL_NUMPOOLS];
+
+ /* Since we only have one lifetime class of virtual arrays, only one
+ * linked list is necessary (for each datatype). Note that the virtual
+ * array control blocks being linked together are actually stored somewhere
+ * in the small-pool list.
+ */
+ jvirt_sarray_ptr virt_sarray_list;
+ jvirt_barray_ptr virt_barray_list;
+
+ /* This counts total space obtained from jpeg_get_small/large */
+ long total_space_allocated;
+
+ /* alloc_sarray and alloc_barray set this value for use by virtual
+ * array routines.
+ */
+ JDIMENSION last_rowsperchunk; /* from most recent alloc_sarray/barray */
+} my_memory_mgr;
+
+typedef my_memory_mgr * my_mem_ptr;
+
+
+/*
+ * The control blocks for virtual arrays.
+ * Note that these blocks are allocated in the "small" pool area.
+ * System-dependent info for the associated backing store (if any) is hidden
+ * inside the backing_store_info struct.
+ */
+
+struct jvirt_sarray_control {
+ JSAMPARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION samplesperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_sarray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_sarray_ptr next; /* link to next virtual sarray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+struct jvirt_barray_control {
+ JBLOCKARRAY mem_buffer; /* => the in-memory buffer */
+ JDIMENSION rows_in_array; /* total virtual array height */
+ JDIMENSION blocksperrow; /* width of array (and of memory buffer) */
+ JDIMENSION maxaccess; /* max rows accessed by access_virt_barray */
+ JDIMENSION rows_in_mem; /* height of memory buffer */
+ JDIMENSION rowsperchunk; /* allocation chunk size in mem_buffer */
+ JDIMENSION cur_start_row; /* first logical row # in the buffer */
+ JDIMENSION first_undef_row; /* row # of first uninitialized row */
+ boolean pre_zero; /* pre-zero mode requested? */
+ boolean dirty; /* do current buffer contents need written? */
+ boolean b_s_open; /* is backing-store data valid? */
+ jvirt_barray_ptr next; /* link to next virtual barray control block */
+ backing_store_info b_s_info; /* System-dependent control info */
+};
+
+
+#ifdef MEM_STATS /* optional extra stuff for statistics */
+
+LOCAL(void)
+print_mem_stats (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+
+ /* Since this is only a debugging stub, we can cheat a little by using
+ * fprintf directly rather than going through the trace message code.
+ * This is helpful because message parm array can't handle longs.
+ */
+ fprintf(stderr, "Freeing pool %d, total space = %ld\n",
+ pool_id, mem->total_space_allocated);
+
+ for (lhdr_ptr = mem->large_list[pool_id]; lhdr_ptr != NULL;
+ lhdr_ptr = lhdr_ptr->hdr.next) {
+ fprintf(stderr, " Large chunk used %ld\n",
+ (long) lhdr_ptr->hdr.bytes_used);
+ }
+
+ for (shdr_ptr = mem->small_list[pool_id]; shdr_ptr != NULL;
+ shdr_ptr = shdr_ptr->hdr.next) {
+ fprintf(stderr, " Small chunk used %ld free %ld\n",
+ (long) shdr_ptr->hdr.bytes_used,
+ (long) shdr_ptr->hdr.bytes_left);
+ }
+}
+
+#endif /* MEM_STATS */
+
+
+LOCAL(void)
+out_of_memory (j_common_ptr cinfo, int which)
+/* Report an out-of-memory error and stop execution */
+/* If we compiled MEM_STATS support, report alloc requests before dying */
+{
+#ifdef MEM_STATS
+ cinfo->err->trace_level = 2; /* force self_destruct to report stats */
+#endif
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, which);
+}
+
+
+/*
+ * Allocation of "small" objects.
+ *
+ * For these, we use pooled storage. When a new pool must be created,
+ * we try to get enough space for the current request plus a "slop" factor,
+ * where the slop will be the amount of leftover space in the new pool.
+ * The speed vs. space tradeoff is largely determined by the slop values.
+ * A different slop value is provided for each pool class (lifetime),
+ * and we also distinguish the first pool of a class from later ones.
+ * NOTE: the values given work fairly well on both 16- and 32-bit-int
+ * machines, but may be too small if longs are 64 bits or more.
+ */
+
+static const size_t first_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 1600, /* first PERMANENT pool */
+ 16000 /* first IMAGE pool */
+};
+
+static const size_t extra_pool_slop[JPOOL_NUMPOOLS] =
+{
+ 0, /* additional PERMANENT pools */
+ 5000 /* additional IMAGE pools */
+};
+
+#define MIN_SLOP 50 /* greater than 0 to avoid futile looping */
+
+
+METHODDEF(void *)
+alloc_small (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "small" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr hdr_ptr, prev_hdr_ptr;
+ char * data_ptr;
+ size_t odd_bytes, min_request, slop;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(small_pool_hdr)))
+ out_of_memory(cinfo, 1); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* See if space is available in any existing pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+ prev_hdr_ptr = NULL;
+ hdr_ptr = mem->small_list[pool_id];
+ while (hdr_ptr != NULL) {
+ if (hdr_ptr->hdr.bytes_left >= sizeofobject)
+ break; /* found pool with enough space */
+ prev_hdr_ptr = hdr_ptr;
+ hdr_ptr = hdr_ptr->hdr.next;
+ }
+
+ /* Time to make a new pool? */
+ if (hdr_ptr == NULL) {
+ /* min_request is what we need now, slop is what will be leftover */
+ min_request = sizeofobject + SIZEOF(small_pool_hdr);
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ slop = first_pool_slop[pool_id];
+ else
+ slop = extra_pool_slop[pool_id];
+ /* Don't ask for more than MAX_ALLOC_CHUNK */
+ if (slop > (size_t) (MAX_ALLOC_CHUNK-min_request))
+ slop = (size_t) (MAX_ALLOC_CHUNK-min_request);
+ /* Try to get space, if fail reduce slop and try again */
+ for (;;) {
+ hdr_ptr = (small_pool_ptr) jpeg_get_small(cinfo, min_request + slop);
+ if (hdr_ptr != NULL)
+ break;
+ slop /= 2;
+ if (slop < MIN_SLOP) /* give up when it gets real small */
+ out_of_memory(cinfo, 2); /* jpeg_get_small failed */
+ }
+ mem->total_space_allocated += min_request + slop;
+ /* Success, initialize the new pool header and add to end of list */
+ hdr_ptr->hdr.next = NULL;
+ hdr_ptr->hdr.bytes_used = 0;
+ hdr_ptr->hdr.bytes_left = sizeofobject + slop;
+ if (prev_hdr_ptr == NULL) /* first pool in class? */
+ mem->small_list[pool_id] = hdr_ptr;
+ else
+ prev_hdr_ptr->hdr.next = hdr_ptr;
+ }
+
+ /* OK, allocate the object from the current pool */
+ data_ptr = (char *) (hdr_ptr + 1); /* point to first data byte in pool */
+ data_ptr += hdr_ptr->hdr.bytes_used; /* point to place for object */
+ hdr_ptr->hdr.bytes_used += sizeofobject;
+ hdr_ptr->hdr.bytes_left -= sizeofobject;
+
+ return (void *) data_ptr;
+}
+
+
+/*
+ * Allocation of "large" objects.
+ *
+ * The external semantics of these are the same as "small" objects,
+ * except that FAR pointers are used on 80x86. However the pool
+ * management heuristics are quite different. We assume that each
+ * request is large enough that it may as well be passed directly to
+ * jpeg_get_large; the pool management just links everything together
+ * so that we can free it all on demand.
+ * Note: the major use of "large" objects is in JSAMPARRAY and JBLOCKARRAY
+ * structures. The routines that create these structures (see below)
+ * deliberately bunch rows together to ensure a large request size.
+ */
+
+METHODDEF(void FAR *)
+alloc_large (j_common_ptr cinfo, int pool_id, size_t sizeofobject)
+/* Allocate a "large" object */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ large_pool_ptr hdr_ptr;
+ size_t odd_bytes;
+
+ /* Check for unsatisfiable request (do now to ensure no overflow below) */
+ if (sizeofobject > (size_t) (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)))
+ out_of_memory(cinfo, 3); /* request exceeds malloc's ability */
+
+ /* Round up the requested size to a multiple of SIZEOF(ALIGN_TYPE) */
+ odd_bytes = sizeofobject % SIZEOF(ALIGN_TYPE);
+ if (odd_bytes > 0)
+ sizeofobject += SIZEOF(ALIGN_TYPE) - odd_bytes;
+
+ /* Always make a new pool */
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ hdr_ptr = (large_pool_ptr) jpeg_get_large(cinfo, sizeofobject +
+ SIZEOF(large_pool_hdr));
+ if (hdr_ptr == NULL)
+ out_of_memory(cinfo, 4); /* jpeg_get_large failed */
+ mem->total_space_allocated += sizeofobject + SIZEOF(large_pool_hdr);
+
+ /* Success, initialize the new pool header and add to list */
+ hdr_ptr->hdr.next = mem->large_list[pool_id];
+ /* We maintain space counts in each pool header for statistical purposes,
+ * even though they are not needed for allocation.
+ */
+ hdr_ptr->hdr.bytes_used = sizeofobject;
+ hdr_ptr->hdr.bytes_left = 0;
+ mem->large_list[pool_id] = hdr_ptr;
+
+ return (void FAR *) (hdr_ptr + 1); /* point to first data byte in pool */
+}
+
+
+/*
+ * Creation of 2-D sample arrays.
+ * The pointers are in near heap, the samples themselves in FAR heap.
+ *
+ * To minimize allocation overhead and to allow I/O of large contiguous
+ * blocks, we allocate the sample rows in groups of as many rows as possible
+ * without exceeding MAX_ALLOC_CHUNK total bytes per allocation request.
+ * NB: the virtual array control routines, later in this file, know about
+ * this chunking of rows. The rowsperchunk value is left in the mem manager
+ * object so that it can be saved away if this sarray is the workspace for
+ * a virtual array.
+ */
+
+METHODDEF(JSAMPARRAY)
+alloc_sarray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow, JDIMENSION numrows)
+/* Allocate a 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JSAMPARRAY result;
+ JSAMPROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) samplesperrow * SIZEOF(JSAMPLE));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JSAMPARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JSAMPROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JSAMPROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) samplesperrow
+ * SIZEOF(JSAMPLE)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += samplesperrow;
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * Creation of 2-D coefficient-block arrays.
+ * This is essentially the same as the code for sample arrays, above.
+ */
+
+METHODDEF(JBLOCKARRAY)
+alloc_barray (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow, JDIMENSION numrows)
+/* Allocate a 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ JBLOCKARRAY result;
+ JBLOCKROW workspace;
+ JDIMENSION rowsperchunk, currow, i;
+ long ltemp;
+
+ /* Calculate max # of rows allowed in one allocation chunk */
+ ltemp = (MAX_ALLOC_CHUNK-SIZEOF(large_pool_hdr)) /
+ ((long) blocksperrow * SIZEOF(JBLOCK));
+ if (ltemp <= 0)
+ ERREXIT(cinfo, JERR_WIDTH_OVERFLOW);
+ if (ltemp < (long) numrows)
+ rowsperchunk = (JDIMENSION) ltemp;
+ else
+ rowsperchunk = numrows;
+ mem->last_rowsperchunk = rowsperchunk;
+
+ /* Get space for row pointers (small object) */
+ result = (JBLOCKARRAY) alloc_small(cinfo, pool_id,
+ (size_t) (numrows * SIZEOF(JBLOCKROW)));
+
+ /* Get the rows themselves (large objects) */
+ currow = 0;
+ while (currow < numrows) {
+ rowsperchunk = MIN(rowsperchunk, numrows - currow);
+ workspace = (JBLOCKROW) alloc_large(cinfo, pool_id,
+ (size_t) ((size_t) rowsperchunk * (size_t) blocksperrow
+ * SIZEOF(JBLOCK)));
+ for (i = rowsperchunk; i > 0; i--) {
+ result[currow++] = workspace;
+ workspace += blocksperrow;
+ }
+ }
+
+ return result;
+}
+
+
+/*
+ * About virtual array management:
+ *
+ * The above "normal" array routines are only used to allocate strip buffers
+ * (as wide as the image, but just a few rows high). Full-image-sized buffers
+ * are handled as "virtual" arrays. The array is still accessed a strip at a
+ * time, but the memory manager must save the whole array for repeated
+ * accesses. The intended implementation is that there is a strip buffer in
+ * memory (as high as is possible given the desired memory limit), plus a
+ * backing file that holds the rest of the array.
+ *
+ * The request_virt_array routines are told the total size of the image and
+ * the maximum number of rows that will be accessed at once. The in-memory
+ * buffer must be at least as large as the maxaccess value.
+ *
+ * The request routines create control blocks but not the in-memory buffers.
+ * That is postponed until realize_virt_arrays is called. At that time the
+ * total amount of space needed is known (approximately, anyway), so free
+ * memory can be divided up fairly.
+ *
+ * The access_virt_array routines are responsible for making a specific strip
+ * area accessible (after reading or writing the backing file, if necessary).
+ * Note that the access routines are told whether the caller intends to modify
+ * the accessed strip; during a read-only pass this saves having to rewrite
+ * data to disk. The access routines are also responsible for pre-zeroing
+ * any newly accessed rows, if pre-zeroing was requested.
+ *
+ * In current usage, the access requests are usually for nonoverlapping
+ * strips; that is, successive access start_row numbers differ by exactly
+ * num_rows = maxaccess. This means we can get good performance with simple
+ * buffer dump/reload logic, by making the in-memory buffer be a multiple
+ * of the access height; then there will never be accesses across bufferload
+ * boundaries. The code will still work with overlapping access requests,
+ * but it doesn't handle bufferload overlaps very efficiently.
+ */
+
+
+METHODDEF(jvirt_sarray_ptr)
+request_virt_sarray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION samplesperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D sample array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_sarray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_sarray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_sarray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->samplesperrow = samplesperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_sarray_list; /* add to list of virtual arrays */
+ mem->virt_sarray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(jvirt_barray_ptr)
+request_virt_barray (j_common_ptr cinfo, int pool_id, boolean pre_zero,
+ JDIMENSION blocksperrow, JDIMENSION numrows,
+ JDIMENSION maxaccess)
+/* Request a virtual 2-D coefficient-block array */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ jvirt_barray_ptr result;
+
+ /* Only IMAGE-lifetime virtual arrays are currently supported */
+ if (pool_id != JPOOL_IMAGE)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+ /* get control block */
+ result = (jvirt_barray_ptr) alloc_small(cinfo, pool_id,
+ SIZEOF(struct jvirt_barray_control));
+
+ result->mem_buffer = NULL; /* marks array not yet realized */
+ result->rows_in_array = numrows;
+ result->blocksperrow = blocksperrow;
+ result->maxaccess = maxaccess;
+ result->pre_zero = pre_zero;
+ result->b_s_open = FALSE; /* no associated backing-store object */
+ result->next = mem->virt_barray_list; /* add to list of virtual arrays */
+ mem->virt_barray_list = result;
+
+ return result;
+}
+
+
+METHODDEF(void)
+realize_virt_arrays (j_common_ptr cinfo)
+/* Allocate the in-memory buffers for any unrealized virtual arrays */
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ long space_per_minheight, maximum_space, avail_mem;
+ long minheights, max_minheights;
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ /* Compute the minimum space needed (maxaccess rows in each buffer)
+ * and the maximum space needed (full image height in each buffer).
+ * These may be of use to the system-dependent jpeg_mem_available routine.
+ */
+ space_per_minheight = 0;
+ maximum_space = 0;
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) sptr->maxaccess *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ maximum_space += (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow * SIZEOF(JSAMPLE);
+ }
+ }
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ space_per_minheight += (long) bptr->maxaccess *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ maximum_space += (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow * SIZEOF(JBLOCK);
+ }
+ }
+
+ if (space_per_minheight <= 0)
+ return; /* no unrealized arrays, no work */
+
+ /* Determine amount of memory to actually use; this is system-dependent. */
+ avail_mem = jpeg_mem_available(cinfo, space_per_minheight, maximum_space,
+ mem->total_space_allocated);
+
+ /* If the maximum space needed is available, make all the buffers full
+ * height; otherwise parcel it out with the same number of minheights
+ * in each buffer.
+ */
+ if (avail_mem >= maximum_space)
+ max_minheights = 1000000000L;
+ else {
+ max_minheights = avail_mem / space_per_minheight;
+ /* If there doesn't seem to be enough space, try to get the minimum
+ * anyway. This allows a "stub" implementation of jpeg_mem_available().
+ */
+ if (max_minheights <= 0)
+ max_minheights = 1;
+ }
+
+ /* Allocate the in-memory buffers and initialize backing store as needed. */
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) sptr->rows_in_array - 1L) / sptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ sptr->rows_in_mem = sptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ sptr->rows_in_mem = (JDIMENSION) (max_minheights * sptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & sptr->b_s_info,
+ (long) sptr->rows_in_array *
+ (long) sptr->samplesperrow *
+ (long) SIZEOF(JSAMPLE));
+ sptr->b_s_open = TRUE;
+ }
+ sptr->mem_buffer = alloc_sarray(cinfo, JPOOL_IMAGE,
+ sptr->samplesperrow, sptr->rows_in_mem);
+ sptr->rowsperchunk = mem->last_rowsperchunk;
+ sptr->cur_start_row = 0;
+ sptr->first_undef_row = 0;
+ sptr->dirty = FALSE;
+ }
+ }
+
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->mem_buffer == NULL) { /* if not realized yet */
+ minheights = ((long) bptr->rows_in_array - 1L) / bptr->maxaccess + 1L;
+ if (minheights <= max_minheights) {
+ /* This buffer fits in memory */
+ bptr->rows_in_mem = bptr->rows_in_array;
+ } else {
+ /* It doesn't fit in memory, create backing store. */
+ bptr->rows_in_mem = (JDIMENSION) (max_minheights * bptr->maxaccess);
+ jpeg_open_backing_store(cinfo, & bptr->b_s_info,
+ (long) bptr->rows_in_array *
+ (long) bptr->blocksperrow *
+ (long) SIZEOF(JBLOCK));
+ bptr->b_s_open = TRUE;
+ }
+ bptr->mem_buffer = alloc_barray(cinfo, JPOOL_IMAGE,
+ bptr->blocksperrow, bptr->rows_in_mem);
+ bptr->rowsperchunk = mem->last_rowsperchunk;
+ bptr->cur_start_row = 0;
+ bptr->first_undef_row = 0;
+ bptr->dirty = FALSE;
+ }
+ }
+}
+
+
+LOCAL(void)
+do_sarray_io (j_common_ptr cinfo, jvirt_sarray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual sample array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+LOCAL(void)
+do_barray_io (j_common_ptr cinfo, jvirt_barray_ptr ptr, boolean writing)
+/* Do backing store read or write of a virtual coefficient-block array */
+{
+ long bytesperrow, file_offset, byte_count, rows, thisrow, i;
+
+ bytesperrow = (long) ptr->blocksperrow * SIZEOF(JBLOCK);
+ file_offset = ptr->cur_start_row * bytesperrow;
+ /* Loop to read or write each allocation chunk in mem_buffer */
+ for (i = 0; i < (long) ptr->rows_in_mem; i += ptr->rowsperchunk) {
+ /* One chunk, but check for short chunk at end of buffer */
+ rows = MIN((long) ptr->rowsperchunk, (long) ptr->rows_in_mem - i);
+ /* Transfer no more than is currently defined */
+ thisrow = (long) ptr->cur_start_row + i;
+ rows = MIN(rows, (long) ptr->first_undef_row - thisrow);
+ /* Transfer no more than fits in file */
+ rows = MIN(rows, (long) ptr->rows_in_array - thisrow);
+ if (rows <= 0) /* this chunk might be past end of file! */
+ break;
+ byte_count = rows * bytesperrow;
+ if (writing)
+ (*ptr->b_s_info.write_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ else
+ (*ptr->b_s_info.read_backing_store) (cinfo, & ptr->b_s_info,
+ (void FAR *) ptr->mem_buffer[i],
+ file_offset, byte_count);
+ file_offset += byte_count;
+ }
+}
+
+
+METHODDEF(JSAMPARRAY)
+access_virt_sarray (j_common_ptr cinfo, jvirt_sarray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual sample array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_sarray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_sarray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->samplesperrow * SIZEOF(JSAMPLE);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+METHODDEF(JBLOCKARRAY)
+access_virt_barray (j_common_ptr cinfo, jvirt_barray_ptr ptr,
+ JDIMENSION start_row, JDIMENSION num_rows,
+ boolean writable)
+/* Access the part of a virtual block array starting at start_row */
+/* and extending for num_rows rows. writable is true if */
+/* caller intends to modify the accessed area. */
+{
+ JDIMENSION end_row = start_row + num_rows;
+ JDIMENSION undef_row;
+
+ /* debugging check */
+ if (end_row > ptr->rows_in_array || num_rows > ptr->maxaccess ||
+ ptr->mem_buffer == NULL)
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+
+ /* Make the desired part of the virtual array accessible */
+ if (start_row < ptr->cur_start_row ||
+ end_row > ptr->cur_start_row+ptr->rows_in_mem) {
+ if (! ptr->b_s_open)
+ ERREXIT(cinfo, JERR_VIRTUAL_BUG);
+ /* Flush old buffer contents if necessary */
+ if (ptr->dirty) {
+ do_barray_io(cinfo, ptr, TRUE);
+ ptr->dirty = FALSE;
+ }
+ /* Decide what part of virtual array to access.
+ * Algorithm: if target address > current window, assume forward scan,
+ * load starting at target address. If target address < current window,
+ * assume backward scan, load so that target area is top of window.
+ * Note that when switching from forward write to forward read, will have
+ * start_row = 0, so the limiting case applies and we load from 0 anyway.
+ */
+ if (start_row > ptr->cur_start_row) {
+ ptr->cur_start_row = start_row;
+ } else {
+ /* use long arithmetic here to avoid overflow & unsigned problems */
+ long ltemp;
+
+ ltemp = (long) end_row - (long) ptr->rows_in_mem;
+ if (ltemp < 0)
+ ltemp = 0; /* don't fall off front end of file */
+ ptr->cur_start_row = (JDIMENSION) ltemp;
+ }
+ /* Read in the selected part of the array.
+ * During the initial write pass, we will do no actual read
+ * because the selected part is all undefined.
+ */
+ do_barray_io(cinfo, ptr, FALSE);
+ }
+ /* Ensure the accessed part of the array is defined; prezero if needed.
+ * To improve locality of access, we only prezero the part of the array
+ * that the caller is about to access, not the entire in-memory array.
+ */
+ if (ptr->first_undef_row < end_row) {
+ if (ptr->first_undef_row < start_row) {
+ if (writable) /* writer skipped over a section of array */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ undef_row = start_row; /* but reader is allowed to read ahead */
+ } else {
+ undef_row = ptr->first_undef_row;
+ }
+ if (writable)
+ ptr->first_undef_row = end_row;
+ if (ptr->pre_zero) {
+ size_t bytesperrow = (size_t) ptr->blocksperrow * SIZEOF(JBLOCK);
+ undef_row -= ptr->cur_start_row; /* make indexes relative to buffer */
+ end_row -= ptr->cur_start_row;
+ while (undef_row < end_row) {
+ jzero_far((void FAR *) ptr->mem_buffer[undef_row], bytesperrow);
+ undef_row++;
+ }
+ } else {
+ if (! writable) /* reader looking at undefined data */
+ ERREXIT(cinfo, JERR_BAD_VIRTUAL_ACCESS);
+ }
+ }
+ /* Flag the buffer dirty if caller will write in it */
+ if (writable)
+ ptr->dirty = TRUE;
+ /* Return address of proper part of the buffer */
+ return ptr->mem_buffer + (start_row - ptr->cur_start_row);
+}
+
+
+/*
+ * Release all objects belonging to a specified pool.
+ */
+
+METHODDEF(void)
+free_pool (j_common_ptr cinfo, int pool_id)
+{
+ my_mem_ptr mem = (my_mem_ptr) cinfo->mem;
+ small_pool_ptr shdr_ptr;
+ large_pool_ptr lhdr_ptr;
+ size_t space_freed;
+
+ if (pool_id < 0 || pool_id >= JPOOL_NUMPOOLS)
+ ERREXIT1(cinfo, JERR_BAD_POOL_ID, pool_id); /* safety check */
+
+#ifdef MEM_STATS
+ if (cinfo->err->trace_level > 1)
+ print_mem_stats(cinfo, pool_id); /* print pool's memory usage statistics */
+#endif
+
+ /* If freeing IMAGE pool, close any virtual arrays first */
+ if (pool_id == JPOOL_IMAGE) {
+ jvirt_sarray_ptr sptr;
+ jvirt_barray_ptr bptr;
+
+ for (sptr = mem->virt_sarray_list; sptr != NULL; sptr = sptr->next) {
+ if (sptr->b_s_open) { /* there may be no backing store */
+ sptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*sptr->b_s_info.close_backing_store) (cinfo, & sptr->b_s_info);
+ }
+ }
+ mem->virt_sarray_list = NULL;
+ for (bptr = mem->virt_barray_list; bptr != NULL; bptr = bptr->next) {
+ if (bptr->b_s_open) { /* there may be no backing store */
+ bptr->b_s_open = FALSE; /* prevent recursive close if error */
+ (*bptr->b_s_info.close_backing_store) (cinfo, & bptr->b_s_info);
+ }
+ }
+ mem->virt_barray_list = NULL;
+ }
+
+ /* Release large objects */
+ lhdr_ptr = mem->large_list[pool_id];
+ mem->large_list[pool_id] = NULL;
+
+ while (lhdr_ptr != NULL) {
+ large_pool_ptr next_lhdr_ptr = lhdr_ptr->hdr.next;
+ space_freed = lhdr_ptr->hdr.bytes_used +
+ lhdr_ptr->hdr.bytes_left +
+ SIZEOF(large_pool_hdr);
+ jpeg_free_large(cinfo, (void FAR *) lhdr_ptr, space_freed);
+ mem->total_space_allocated -= space_freed;
+ lhdr_ptr = next_lhdr_ptr;
+ }
+
+ /* Release small objects */
+ shdr_ptr = mem->small_list[pool_id];
+ mem->small_list[pool_id] = NULL;
+
+ while (shdr_ptr != NULL) {
+ small_pool_ptr next_shdr_ptr = shdr_ptr->hdr.next;
+ space_freed = shdr_ptr->hdr.bytes_used +
+ shdr_ptr->hdr.bytes_left +
+ SIZEOF(small_pool_hdr);
+ jpeg_free_small(cinfo, (void *) shdr_ptr, space_freed);
+ mem->total_space_allocated -= space_freed;
+ shdr_ptr = next_shdr_ptr;
+ }
+}
+
+
+/*
+ * Close up shop entirely.
+ * Note that this cannot be called unless cinfo->mem is non-NULL.
+ */
+
+METHODDEF(void)
+self_destruct (j_common_ptr cinfo)
+{
+ int pool;
+
+ /* Close all backing store, release all memory.
+ * Releasing pools in reverse order might help avoid fragmentation
+ * with some (brain-damaged) malloc libraries.
+ */
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ free_pool(cinfo, pool);
+ }
+
+ /* Release the memory manager control block too. */
+ jpeg_free_small(cinfo, (void *) cinfo->mem, SIZEOF(my_memory_mgr));
+ cinfo->mem = NULL; /* ensures I will be called only once */
+
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+}
+
+
+/*
+ * Memory manager initialization.
+ * When this is called, only the error manager pointer is valid in cinfo!
+ */
+
+GLOBAL(void)
+jinit_memory_mgr (j_common_ptr cinfo)
+{
+ my_mem_ptr mem;
+ long max_to_use;
+ int pool;
+ size_t test_mac;
+
+ cinfo->mem = NULL; /* for safety if init fails */
+
+ /* Check for configuration errors.
+ * SIZEOF(ALIGN_TYPE) should be a power of 2; otherwise, it probably
+ * doesn't reflect any real hardware alignment requirement.
+ * The test is a little tricky: for X>0, X and X-1 have no one-bits
+ * in common if and only if X is a power of 2, ie has only one one-bit.
+ * Some compilers may give an "unreachable code" warning here; ignore it.
+ */
+ if ((SIZEOF(ALIGN_TYPE) & (SIZEOF(ALIGN_TYPE)-1)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALIGN_TYPE);
+ /* MAX_ALLOC_CHUNK must be representable as type size_t, and must be
+ * a multiple of SIZEOF(ALIGN_TYPE).
+ * Again, an "unreachable code" warning may be ignored here.
+ * But a "constant too large" warning means you need to fix MAX_ALLOC_CHUNK.
+ */
+ test_mac = (size_t) MAX_ALLOC_CHUNK;
+ if ((long) test_mac != MAX_ALLOC_CHUNK ||
+ (MAX_ALLOC_CHUNK % SIZEOF(ALIGN_TYPE)) != 0)
+ ERREXIT(cinfo, JERR_BAD_ALLOC_CHUNK);
+
+ max_to_use = jpeg_mem_init(cinfo); /* system-dependent initialization */
+
+ /* Attempt to allocate memory manager's control block */
+ mem = (my_mem_ptr) jpeg_get_small(cinfo, SIZEOF(my_memory_mgr));
+
+ if (mem == NULL) {
+ jpeg_mem_term(cinfo); /* system-dependent cleanup */
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
+ }
+
+ /* OK, fill in the method pointers */
+ mem->pub.alloc_small = alloc_small;
+ mem->pub.alloc_large = alloc_large;
+ mem->pub.alloc_sarray = alloc_sarray;
+ mem->pub.alloc_barray = alloc_barray;
+ mem->pub.request_virt_sarray = request_virt_sarray;
+ mem->pub.request_virt_barray = request_virt_barray;
+ mem->pub.realize_virt_arrays = realize_virt_arrays;
+ mem->pub.access_virt_sarray = access_virt_sarray;
+ mem->pub.access_virt_barray = access_virt_barray;
+ mem->pub.free_pool = free_pool;
+ mem->pub.self_destruct = self_destruct;
+
+ /* Make MAX_ALLOC_CHUNK accessible to other modules */
+ mem->pub.max_alloc_chunk = MAX_ALLOC_CHUNK;
+
+ /* Initialize working state */
+ mem->pub.max_memory_to_use = max_to_use;
+
+ for (pool = JPOOL_NUMPOOLS-1; pool >= JPOOL_PERMANENT; pool--) {
+ mem->small_list[pool] = NULL;
+ mem->large_list[pool] = NULL;
+ }
+ mem->virt_sarray_list = NULL;
+ mem->virt_barray_list = NULL;
+
+ mem->total_space_allocated = SIZEOF(my_memory_mgr);
+
+ /* Declare ourselves open for business */
+ cinfo->mem = & mem->pub;
+
+ /* Check for an environment variable JPEGMEM; if found, override the
+ * default max_memory setting from jpeg_mem_init. Note that the
+ * surrounding application may again override this value.
+ * If your system doesn't support getenv(), define NO_GETENV to disable
+ * this feature.
+ */
+#ifndef NO_GETENV
+ { char * memenv;
+
+ if ((memenv = getenv("JPEGMEM")) != NULL) {
+ char ch = 'x';
+
+ if (sscanf(memenv, "%ld%c", &max_to_use, &ch) > 0) {
+ if (ch == 'm' || ch == 'M')
+ max_to_use *= 1000L;
+ mem->pub.max_memory_to_use = max_to_use * 1000L;
+ }
+ }
+ }
+#endif
+
+}
diff --git a/Source/LibJPEG/jmemname.c b/Source/LibJPEG/jmemname.c
new file mode 100644
index 0000000..ed96dee
--- /dev/null
+++ b/Source/LibJPEG/jmemname.c
@@ -0,0 +1,276 @@
+/*
+ * jmemname.c
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a generic implementation of the system-dependent
+ * portion of the JPEG memory manager. This implementation assumes that
+ * you must explicitly construct a name for each temp file.
+ * Also, the problem of determining the amount of memory available
+ * is shoved onto the user.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+#ifndef SEEK_SET /* pre-ANSI systems may not define this; */
+#define SEEK_SET 0 /* if not, assume 0 is correct */
+#endif
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#define RW_BINARY "w+"
+#else
+#ifdef VMS /* VMS is very nonstandard */
+#define READ_BINARY "rb", "ctx=stm"
+#define RW_BINARY "w+b", "ctx=stm"
+#else /* standard ANSI-compliant case */
+#define READ_BINARY "rb"
+#define RW_BINARY "w+b"
+#endif
+#endif
+
+
+/*
+ * Selection of a file name for a temporary file.
+ * This is system-dependent!
+ *
+ * The code as given is suitable for most Unix systems, and it is easily
+ * modified for most non-Unix systems. Some notes:
+ * 1. The temp file is created in the directory named by TEMP_DIRECTORY.
+ * The default value is /usr/tmp, which is the conventional place for
+ * creating large temp files on Unix. On other systems you'll probably
+ * want to change the file location. You can do this by editing the
+ * #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h.
+ *
+ * 2. If you need to change the file name as well as its location,
+ * you can override the TEMP_FILE_NAME macro. (Note that this is
+ * actually a printf format string; it must contain %s and %d.)
+ * Few people should need to do this.
+ *
+ * 3. mktemp() is used to ensure that multiple processes running
+ * simultaneously won't select the same file names. If your system
+ * doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
+ * (If you don't have <errno.h>, also define NO_ERRNO_H.)
+ *
+ * 4. You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c
+ * will cause the temp files to be removed if you stop the program early.
+ */
+
+#ifndef TEMP_DIRECTORY /* can override from jconfig.h or Makefile */
+#define TEMP_DIRECTORY "/usr/tmp/" /* recommended setting for Unix */
+#endif
+
+static int next_file_num; /* to distinguish among several temp files */
+
+#ifdef NO_MKTEMP
+
+#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
+#define TEMP_FILE_NAME "%sJPG%03d.TMP"
+#endif
+
+#ifndef NO_ERRNO_H
+#include <errno.h> /* to define ENOENT */
+#endif
+
+/* ANSI C specifies that errno is a macro, but on older systems it's more
+ * likely to be a plain int variable. And not all versions of errno.h
+ * bother to declare it, so we have to in order to be most portable. Thus:
+ */
+#ifndef errno
+extern int errno;
+#endif
+
+
+LOCAL(void)
+select_file_name (char * fname)
+{
+ FILE * tfile;
+
+ /* Keep generating file names till we find one that's not in use */
+ for (;;) {
+ next_file_num++; /* advance counter */
+ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
+ if ((tfile = fopen(fname, READ_BINARY)) == NULL) {
+ /* fopen could have failed for a reason other than the file not
+ * being there; for example, file there but unreadable.
+ * If <errno.h> isn't available, then we cannot test the cause.
+ */
+#ifdef ENOENT
+ if (errno != ENOENT)
+ continue;
+#endif
+ break;
+ }
+ fclose(tfile); /* oops, it's there; close tfile & try again */
+ }
+}
+
+#else /* ! NO_MKTEMP */
+
+/* Note that mktemp() requires the initial filename to end in six X's */
+#ifndef TEMP_FILE_NAME /* can override from jconfig.h or Makefile */
+#define TEMP_FILE_NAME "%sJPG%dXXXXXX"
+#endif
+
+LOCAL(void)
+select_file_name (char * fname)
+{
+ next_file_num++; /* advance counter */
+ sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
+ mktemp(fname); /* make sure file name is unique */
+ /* mktemp replaces the trailing XXXXXX with a unique string of characters */
+}
+
+#endif /* NO_MKTEMP */
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * It's impossible to do this in a portable way; our current solution is
+ * to make the user tell us (with a default value set at compile time).
+ * If you can actually get the available space, it's a good idea to subtract
+ * a slop factor of 5% or so.
+ */
+
+#ifndef DEFAULT_MAX_MEM /* so can override from makefile */
+#define DEFAULT_MAX_MEM 1000000L /* default: one megabyte */
+#endif
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return cinfo->mem->max_memory_to_use - already_allocated;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Backing store objects are only used when the value returned by
+ * jpeg_mem_available is less than the total space needed. You can dispense
+ * with these routines if you have plenty of virtual memory; see jmemnobs.c.
+ */
+
+
+METHODDEF(void)
+read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (fseek(info->temp_file, file_offset, SEEK_SET))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ if (JFREAD(info->temp_file, buffer_address, byte_count)
+ != (size_t) byte_count)
+ ERREXIT(cinfo, JERR_TFILE_READ);
+}
+
+
+METHODDEF(void)
+write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count)
+{
+ if (fseek(info->temp_file, file_offset, SEEK_SET))
+ ERREXIT(cinfo, JERR_TFILE_SEEK);
+ if (JFWRITE(info->temp_file, buffer_address, byte_count)
+ != (size_t) byte_count)
+ ERREXIT(cinfo, JERR_TFILE_WRITE);
+}
+
+
+METHODDEF(void)
+close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
+{
+ fclose(info->temp_file); /* close the file */
+ unlink(info->temp_name); /* delete the file */
+/* If your system doesn't have unlink(), use remove() instead.
+ * remove() is the ANSI-standard name for this function, but if
+ * your system was ANSI you'd be using jmemansi.c, right?
+ */
+ TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
+}
+
+
+/*
+ * Initial opening of a backing-store object.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ select_file_name(info->temp_name);
+ if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL)
+ ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
+ info->read_backing_store = read_backing_store;
+ info->write_backing_store = write_backing_store;
+ info->close_backing_store = close_backing_store;
+ TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ next_file_num = 0; /* initialize temp file name generator */
+ return DEFAULT_MAX_MEM; /* default for max_memory_to_use */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/Source/LibJPEG/jmemnobs.c b/Source/LibJPEG/jmemnobs.c
new file mode 100644
index 0000000..eb8c337
--- /dev/null
+++ b/Source/LibJPEG/jmemnobs.c
@@ -0,0 +1,109 @@
+/*
+ * jmemnobs.c
+ *
+ * Copyright (C) 1992-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides a really simple implementation of the system-
+ * dependent portion of the JPEG memory manager. This implementation
+ * assumes that no backing-store files are needed: all required space
+ * can be obtained from malloc().
+ * This is very portable in the sense that it'll compile on almost anything,
+ * but you'd better have lots of main memory (or virtual memory) if you want
+ * to process big images.
+ * Note that the max_memory_to_use option is ignored by this implementation.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "jmemsys.h" /* import the system-dependent declarations */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */
+extern void * malloc JPP((size_t size));
+extern void free JPP((void *ptr));
+#endif
+
+
+/*
+ * Memory allocation and freeing are controlled by the regular library
+ * routines malloc() and free().
+ */
+
+GLOBAL(void *)
+jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * "Large" objects are treated the same as "small" ones.
+ * NB: although we include FAR keywords in the routine declarations,
+ * this file won't actually work in 80x86 small/medium model; at least,
+ * you probably won't be able to process useful-size images in only 64KB.
+ */
+
+GLOBAL(void FAR *)
+jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
+{
+ return (void FAR *) malloc(sizeofobject);
+}
+
+GLOBAL(void)
+jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
+{
+ free(object);
+}
+
+
+/*
+ * This routine computes the total memory space available for allocation.
+ * Here we always say, "we got all you want bud!"
+ */
+
+GLOBAL(long)
+jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
+ long max_bytes_needed, long already_allocated)
+{
+ return max_bytes_needed;
+}
+
+
+/*
+ * Backing store (temporary file) management.
+ * Since jpeg_mem_available always promised the moon,
+ * this should never be called and we can just error out.
+ */
+
+GLOBAL(void)
+jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
+ long total_bytes_needed)
+{
+ ERREXIT(cinfo, JERR_NO_BACKING_STORE);
+}
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. Here, there isn't any.
+ */
+
+GLOBAL(long)
+jpeg_mem_init (j_common_ptr cinfo)
+{
+ return 0; /* just set max_memory_to_use to 0 */
+}
+
+GLOBAL(void)
+jpeg_mem_term (j_common_ptr cinfo)
+{
+ /* no work */
+}
diff --git a/Source/LibJPEG/jmemsys.h b/Source/LibJPEG/jmemsys.h
new file mode 100644
index 0000000..093856a
--- /dev/null
+++ b/Source/LibJPEG/jmemsys.h
@@ -0,0 +1,201 @@
+/*
+ * jmemsys.h
+ *
+ * Copyright (C) 1992-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This include file defines the interface between the system-independent
+ * and system-dependent portions of the JPEG memory manager. No other
+ * modules need include it. (The system-independent portion is jmemmgr.c;
+ * there are several different versions of the system-dependent portion.)
+ *
+ * This file works as-is for the system-dependent memory managers supplied
+ * in the IJG distribution. You may need to modify it if you write a
+ * custom memory manager. If system-dependent changes are needed in
+ * this file, the best method is to #ifdef them based on a configuration
+ * symbol supplied in jconfig.h, as we have done with USE_MSDOS_MEMMGR
+ * and USE_MAC_MEMMGR.
+ */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_get_small jGetSmall
+#define jpeg_free_small jFreeSmall
+#define jpeg_get_large jGetLarge
+#define jpeg_free_large jFreeLarge
+#define jpeg_mem_available jMemAvail
+#define jpeg_open_backing_store jOpenBackStore
+#define jpeg_mem_init jMemInit
+#define jpeg_mem_term jMemTerm
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * These two functions are used to allocate and release small chunks of
+ * memory. (Typically the total amount requested through jpeg_get_small is
+ * no more than 20K or so; this will be requested in chunks of a few K each.)
+ * Behavior should be the same as for the standard library functions malloc
+ * and free; in particular, jpeg_get_small must return NULL on failure.
+ * On most systems, these ARE malloc and free. jpeg_free_small is passed the
+ * size of the object being freed, just in case it's needed.
+ * On an 80x86 machine using small-data memory model, these manage near heap.
+ */
+
+EXTERN(void *) jpeg_get_small JPP((j_common_ptr cinfo, size_t sizeofobject));
+EXTERN(void) jpeg_free_small JPP((j_common_ptr cinfo, void * object,
+ size_t sizeofobject));
+
+/*
+ * These two functions are used to allocate and release large chunks of
+ * memory (up to the total free space designated by jpeg_mem_available).
+ * The interface is the same as above, except that on an 80x86 machine,
+ * far pointers are used. On most other machines these are identical to
+ * the jpeg_get/free_small routines; but we keep them separate anyway,
+ * in case a different allocation strategy is desirable for large chunks.
+ */
+
+EXTERN(void FAR *) jpeg_get_large JPP((j_common_ptr cinfo,
+ size_t sizeofobject));
+EXTERN(void) jpeg_free_large JPP((j_common_ptr cinfo, void FAR * object,
+ size_t sizeofobject));
+
+/*
+ * The macro MAX_ALLOC_CHUNK designates the maximum number of bytes that may
+ * be requested in a single call to jpeg_get_large (and jpeg_get_small for that
+ * matter, but that case should never come into play). This macro is needed
+ * to model the 64Kb-segment-size limit of far addressing on 80x86 machines.
+ * On those machines, we expect that jconfig.h will provide a proper value.
+ * On machines with 32-bit flat address spaces, any large constant may be used.
+ *
+ * NB: jmemmgr.c expects that MAX_ALLOC_CHUNK will be representable as type
+ * size_t and will be a multiple of sizeof(align_type).
+ */
+
+#ifndef MAX_ALLOC_CHUNK /* may be overridden in jconfig.h */
+#define MAX_ALLOC_CHUNK 1000000000L
+#endif
+
+/*
+ * This routine computes the total space still available for allocation by
+ * jpeg_get_large. If more space than this is needed, backing store will be
+ * used. NOTE: any memory already allocated must not be counted.
+ *
+ * There is a minimum space requirement, corresponding to the minimum
+ * feasible buffer sizes; jmemmgr.c will request that much space even if
+ * jpeg_mem_available returns zero. The maximum space needed, enough to hold
+ * all working storage in memory, is also passed in case it is useful.
+ * Finally, the total space already allocated is passed. If no better
+ * method is available, cinfo->mem->max_memory_to_use - already_allocated
+ * is often a suitable calculation.
+ *
+ * It is OK for jpeg_mem_available to underestimate the space available
+ * (that'll just lead to more backing-store access than is really necessary).
+ * However, an overestimate will lead to failure. Hence it's wise to subtract
+ * a slop factor from the true available space. 5% should be enough.
+ *
+ * On machines with lots of virtual memory, any large constant may be returned.
+ * Conversely, zero may be returned to always use the minimum amount of memory.
+ */
+
+EXTERN(long) jpeg_mem_available JPP((j_common_ptr cinfo,
+ long min_bytes_needed,
+ long max_bytes_needed,
+ long already_allocated));
+
+
+/*
+ * This structure holds whatever state is needed to access a single
+ * backing-store object. The read/write/close method pointers are called
+ * by jmemmgr.c to manipulate the backing-store object; all other fields
+ * are private to the system-dependent backing store routines.
+ */
+
+#define TEMP_NAME_LENGTH 64 /* max length of a temporary file's name */
+
+
+#ifdef USE_MSDOS_MEMMGR /* DOS-specific junk */
+
+typedef unsigned short XMSH; /* type of extended-memory handles */
+typedef unsigned short EMSH; /* type of expanded-memory handles */
+
+typedef union {
+ short file_handle; /* DOS file handle if it's a temp file */
+ XMSH xms_handle; /* handle if it's a chunk of XMS */
+ EMSH ems_handle; /* handle if it's a chunk of EMS */
+} handle_union;
+
+#endif /* USE_MSDOS_MEMMGR */
+
+#ifdef USE_MAC_MEMMGR /* Mac-specific junk */
+//#include <Files.h>
+#define __OPENTRANSPORTPROVIDERS__ // Avoid re-definition issues
+#include <CoreServices/CoreServices.h>
+
+#endif /* USE_MAC_MEMMGR */
+
+
+typedef struct backing_store_struct * backing_store_ptr;
+
+typedef struct backing_store_struct {
+ /* Methods for reading/writing/closing this backing-store object */
+ JMETHOD(void, read_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, write_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info,
+ void FAR * buffer_address,
+ long file_offset, long byte_count));
+ JMETHOD(void, close_backing_store, (j_common_ptr cinfo,
+ backing_store_ptr info));
+
+ /* Private fields for system-dependent backing-store management */
+#ifdef USE_MSDOS_MEMMGR
+ /* For the MS-DOS manager (jmemdos.c), we need: */
+ handle_union handle; /* reference to backing-store storage object */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+#ifdef USE_MAC_MEMMGR
+ /* For the Mac manager (jmemmac.c), we need: */
+ short temp_file; /* file reference number to temp file */
+ FSSpec tempSpec; /* the FSSpec for the temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name if it's a file */
+#else
+ /* For a typical implementation with temp files, we need: */
+ FILE * temp_file; /* stdio reference to temp file */
+ char temp_name[TEMP_NAME_LENGTH]; /* name of temp file */
+#endif
+#endif
+} backing_store_info;
+
+
+/*
+ * Initial opening of a backing-store object. This must fill in the
+ * read/write/close pointers in the object. The read/write routines
+ * may take an error exit if the specified maximum file size is exceeded.
+ * (If jpeg_mem_available always returns a large value, this routine can
+ * just take an error exit.)
+ */
+
+EXTERN(void) jpeg_open_backing_store JPP((j_common_ptr cinfo,
+ backing_store_ptr info,
+ long total_bytes_needed));
+
+
+/*
+ * These routines take care of any system-dependent initialization and
+ * cleanup required. jpeg_mem_init will be called before anything is
+ * allocated (and, therefore, nothing in cinfo is of use except the error
+ * manager pointer). It should return a suitable default value for
+ * max_memory_to_use; this may subsequently be overridden by the surrounding
+ * application. (Note that max_memory_to_use is only important if
+ * jpeg_mem_available chooses to consult it ... no one else will.)
+ * jpeg_mem_term may assume that all requested memory has been freed and that
+ * all opened backing-store objects have been closed.
+ */
+
+EXTERN(long) jpeg_mem_init JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_mem_term JPP((j_common_ptr cinfo));
diff --git a/Source/LibJPEG/jmorecfg.h b/Source/LibJPEG/jmorecfg.h
new file mode 100644
index 0000000..c610bc2
--- /dev/null
+++ b/Source/LibJPEG/jmorecfg.h
@@ -0,0 +1,369 @@
+/*
+ * jmorecfg.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 1997-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains additional configuration options that customize the
+ * JPEG software for special applications or support machine-dependent
+ * optimizations. Most users will not need to touch this file.
+ */
+
+
+/*
+ * Define BITS_IN_JSAMPLE as either
+ * 8 for 8-bit sample values (the usual setting)
+ * 12 for 12-bit sample values
+ * Only 8 and 12 are legal data precisions for lossy JPEG according to the
+ * JPEG standard, and the IJG code does not support anything else!
+ * We do not support run-time selection of data precision, sorry.
+ */
+
+#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
+
+
+/*
+ * Maximum number of components (color channels) allowed in JPEG image.
+ * To meet the letter of the JPEG spec, set this to 255. However, darn
+ * few applications need more than 4 channels (maybe 5 for CMYK + alpha
+ * mask). We recommend 10 as a reasonable compromise; use 4 if you are
+ * really short on memory. (Each allowed component costs a hundred or so
+ * bytes of storage, whether actually used in an image or not.)
+ */
+
+#define MAX_COMPONENTS 10 /* maximum number of image components */
+
+
+/*
+ * Basic data types.
+ * You may need to change these if you have a machine with unusual data
+ * type sizes; for example, "char" not 8 bits, "short" not 16 bits,
+ * or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
+ * but it had better be at least 16.
+ */
+
+/* Representation of a single sample (pixel element value).
+ * We frequently allocate large arrays of these, so it's important to keep
+ * them small. But if you have memory to burn and access to char or short
+ * arrays is very slow on your hardware, you might want to change these.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+/* JSAMPLE should be the smallest type that will hold the values 0..255.
+ * You can use a signed char by having GETJSAMPLE mask it with 0xFF.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JSAMPLE;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJSAMPLE(value) ((int) (value))
+#else
+#define GETJSAMPLE(value) ((int) (value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+#define MAXJSAMPLE 255
+#define CENTERJSAMPLE 128
+
+#endif /* BITS_IN_JSAMPLE == 8 */
+
+
+#if BITS_IN_JSAMPLE == 12
+/* JSAMPLE should be the smallest type that will hold the values 0..4095.
+ * On nearly all machines "short" will do nicely.
+ */
+
+typedef short JSAMPLE;
+#define GETJSAMPLE(value) ((int) (value))
+
+#define MAXJSAMPLE 4095
+#define CENTERJSAMPLE 2048
+
+#endif /* BITS_IN_JSAMPLE == 12 */
+
+
+/* Representation of a DCT frequency coefficient.
+ * This should be a signed value of at least 16 bits; "short" is usually OK.
+ * Again, we allocate large arrays of these, but you can change to int
+ * if you have memory to burn and "short" is really slow.
+ */
+
+typedef short JCOEF;
+
+
+/* Compressed datastreams are represented as arrays of JOCTET.
+ * These must be EXACTLY 8 bits wide, at least once they are written to
+ * external storage. Note that when using the stdio data source/destination
+ * managers, this is also the data type passed to fread/fwrite.
+ */
+
+#ifdef HAVE_UNSIGNED_CHAR
+
+typedef unsigned char JOCTET;
+#define GETJOCTET(value) (value)
+
+#else /* not HAVE_UNSIGNED_CHAR */
+
+typedef char JOCTET;
+#ifdef CHAR_IS_UNSIGNED
+#define GETJOCTET(value) (value)
+#else
+#define GETJOCTET(value) ((value) & 0xFF)
+#endif /* CHAR_IS_UNSIGNED */
+
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+/* These typedefs are used for various table entries and so forth.
+ * They must be at least as wide as specified; but making them too big
+ * won't cost a huge amount of memory, so we don't provide special
+ * extraction code like we did for JSAMPLE. (In other words, these
+ * typedefs live at a different point on the speed/space tradeoff curve.)
+ */
+
+/* UINT8 must hold at least the values 0..255. */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char UINT8;
+#else /* not HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char UINT8;
+#else /* not CHAR_IS_UNSIGNED */
+typedef short UINT8;
+#endif /* CHAR_IS_UNSIGNED */
+#endif /* HAVE_UNSIGNED_CHAR */
+
+/* UINT16 must hold at least the values 0..65535. */
+
+#ifdef HAVE_UNSIGNED_SHORT
+typedef unsigned short UINT16;
+#else /* not HAVE_UNSIGNED_SHORT */
+typedef unsigned int UINT16;
+#endif /* HAVE_UNSIGNED_SHORT */
+
+/* INT16 must hold at least the values -32768..32767. */
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
+typedef short INT16;
+#endif
+
+/* INT32 must hold at least signed 32-bit values. */
+
+#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
+#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
+#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
+typedef long INT32;
+#endif
+#endif
+#endif
+
+/* Datatype used for image dimensions. The JPEG standard only supports
+ * images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
+ * "unsigned int" is sufficient on all machines. However, if you need to
+ * handle larger images and you don't mind deviating from the spec, you
+ * can change this datatype.
+ */
+
+typedef unsigned int JDIMENSION;
+
+#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
+
+
+/* These macros are used in all function definitions and extern declarations.
+ * You could modify them if you need to change function linkage conventions;
+ * in particular, you'll need to do that to make the library a Windows DLL.
+ * Another application is to make all functions global for use with debuggers
+ * or code profilers that require it.
+ */
+
+/* a function called through method pointers: */
+#define METHODDEF(type) static type
+/* a function used only in its module: */
+#define LOCAL(type) static type
+/* a function referenced thru EXTERNs: */
+#define GLOBAL(type) type
+/* a reference to a GLOBAL function: */
+#define EXTERN(type) extern type
+
+
+/* This macro is used to declare a "method", that is, a function pointer.
+ * We want to supply prototype parameters if the compiler can cope.
+ * Note that the arglist parameter must be parenthesized!
+ * Again, you can customize this if you need special linkage keywords.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
+#else
+#define JMETHOD(type,methodname,arglist) type (*methodname) ()
+#endif
+
+
+/* Here is the pseudo-keyword for declaring pointers that must be "far"
+ * on 80x86 machines. Most of the specialized coding for 80x86 is handled
+ * by just saying "FAR *" where such a pointer is needed. In a few places
+ * explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
+ */
+
+#ifndef FAR
+#ifdef NEED_FAR_POINTERS
+#define FAR far
+#else
+#define FAR
+#endif
+#endif
+
+
+/*
+ * On a few systems, type boolean and/or its values FALSE, TRUE may appear
+ * in standard header files. Or you may have conflicts with application-
+ * specific header files that you want to include together with these files.
+ * Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
+ */
+
+#ifndef HAVE_BOOLEAN
+typedef int boolean;
+#endif
+#ifndef FALSE /* in case these macros already exist */
+#define FALSE 0 /* values of boolean */
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+
+/*
+ * The remaining options affect code selection within the JPEG library,
+ * but they don't need to be visible to most applications using the library.
+ * To minimize application namespace pollution, the symbols won't be
+ * defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
+ */
+
+#ifdef JPEG_INTERNALS
+#define JPEG_INTERNAL_OPTIONS
+#endif
+
+#ifdef JPEG_INTERNAL_OPTIONS
+
+
+/*
+ * These defines indicate whether to include various optional functions.
+ * Undefining some of these symbols will produce a smaller but less capable
+ * library. Note that you can leave certain source files out of the
+ * compilation/linking process if you've #undef'd the corresponding symbols.
+ * (You may HAVE to do that if your compiler doesn't like null source files.)
+ */
+
+/* Capability options common to encoder and decoder: */
+
+#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
+#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
+#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
+
+/* Encoder capability options: */
+
+#define C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define DCT_SCALING_SUPPORTED /* Input rescaling via DCT? (Requires DCT_ISLOW)*/
+#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
+/* Note: if you selected 12-bit data precision, it is dangerous to turn off
+ * ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
+ * precision, so jchuff.c normally uses entropy optimization to compute
+ * usable tables for higher precision. If you don't want to do optimization,
+ * you'll have to supply different default Huffman tables.
+ * The exact same statements apply for progressive JPEG: the default tables
+ * don't work for progressive mode. (This may get fixed, however.)
+ */
+#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
+
+/* Decoder capability options: */
+
+#define D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
+#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
+#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
+#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
+#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
+#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
+#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
+#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
+#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
+#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
+
+/* more capability options later, no doubt */
+
+
+/*
+ * Ordering of RGB data in scanlines passed to or from the application.
+ * If your application wants to deal with data in the order B,G,R, just
+ * change these macros. You can also deal with formats such as R,G,B,X
+ * (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
+ * the offsets will also change the order in which colormap data is organized.
+ * RESTRICTIONS:
+ * 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
+ * 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
+ * useful if you are using JPEG color spaces other than YCbCr or grayscale.
+ * 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
+ * is not 3 (they don't understand about dummy color components!). So you
+ * can't use color quantization if you change that value.
+ */
+
+#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
+#define RGB_GREEN 1 /* Offset of Green */
+#define RGB_BLUE 2 /* Offset of Blue */
+#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
+
+
+/* Definitions for speed-related optimizations. */
+
+
+/* If your compiler supports inline functions, define INLINE
+ * as the inline keyword; otherwise define it as empty.
+ */
+
+#ifndef INLINE
+#ifdef __GNUC__ /* for instance, GNU C knows about inline */
+#define INLINE __inline__
+#endif
+#ifndef INLINE
+#define INLINE /* default is to define it as empty */
+#endif
+#endif
+
+
+/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
+ * two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
+ * as short on such a machine. MULTIPLIER must be at least 16 bits wide.
+ */
+
+#ifndef MULTIPLIER
+#define MULTIPLIER int /* type for fastest integer multiply */
+#endif
+
+
+/* FAST_FLOAT should be either float or double, whichever is done faster
+ * by your compiler. (Note that this type is only used in the floating point
+ * DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
+ * Typically, float is faster in ANSI C compilers, while double is faster in
+ * pre-ANSI compilers (because they insist on converting to double anyway).
+ * The code below therefore chooses float if we have ANSI-style prototypes.
+ */
+
+#ifndef FAST_FLOAT
+#ifdef HAVE_PROTOTYPES
+#define FAST_FLOAT float
+#else
+#define FAST_FLOAT double
+#endif
+#endif
+
+#endif /* JPEG_INTERNAL_OPTIONS */
diff --git a/Source/LibJPEG/jpegint.h b/Source/LibJPEG/jpegint.h
new file mode 100644
index 0000000..69b781b
--- /dev/null
+++ b/Source/LibJPEG/jpegint.h
@@ -0,0 +1,395 @@
+/*
+ * jpegint.h
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 1997-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file provides common declarations for the various JPEG modules.
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+
+/* Declarations for both compression & decompression */
+
+typedef enum { /* Operating modes for buffer controllers */
+ JBUF_PASS_THRU, /* Plain stripwise operation */
+ /* Remaining modes require a full-image buffer to have been created */
+ JBUF_SAVE_SOURCE, /* Run source subobject only, save output */
+ JBUF_CRANK_DEST, /* Run dest subobject only, using saved data */
+ JBUF_SAVE_AND_PASS /* Run both subobjects, save output */
+} J_BUF_MODE;
+
+/* Values of global_state field (jdapi.c has some dependencies on ordering!) */
+#define CSTATE_START 100 /* after create_compress */
+#define CSTATE_SCANNING 101 /* start_compress done, write_scanlines OK */
+#define CSTATE_RAW_OK 102 /* start_compress done, write_raw_data OK */
+#define CSTATE_WRCOEFS 103 /* jpeg_write_coefficients done */
+#define DSTATE_START 200 /* after create_decompress */
+#define DSTATE_INHEADER 201 /* reading header markers, no SOS yet */
+#define DSTATE_READY 202 /* found SOS, ready for start_decompress */
+#define DSTATE_PRELOAD 203 /* reading multiscan file in start_decompress*/
+#define DSTATE_PRESCAN 204 /* performing dummy pass for 2-pass quant */
+#define DSTATE_SCANNING 205 /* start_decompress done, read_scanlines OK */
+#define DSTATE_RAW_OK 206 /* start_decompress done, read_raw_data OK */
+#define DSTATE_BUFIMAGE 207 /* expecting jpeg_start_output */
+#define DSTATE_BUFPOST 208 /* looking for SOS/EOI in jpeg_finish_output */
+#define DSTATE_RDCOEFS 209 /* reading file in jpeg_read_coefficients */
+#define DSTATE_STOPPING 210 /* looking for EOI in jpeg_finish_decompress */
+
+
+/* Declarations for compression modules */
+
+/* Master control module */
+struct jpeg_comp_master {
+ JMETHOD(void, prepare_for_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, pass_startup, (j_compress_ptr cinfo));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean call_pass_startup; /* True if pass_startup must be called */
+ boolean is_last_pass; /* True during last pass */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_c_main_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail));
+};
+
+/* Compression preprocessing (downsampling input buffer control) */
+struct jpeg_c_prep_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, pre_process_data, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf,
+ JDIMENSION *in_row_ctr,
+ JDIMENSION in_rows_avail,
+ JSAMPIMAGE output_buf,
+ JDIMENSION *out_row_group_ctr,
+ JDIMENSION out_row_groups_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_c_coef_controller {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(boolean, compress_data, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf));
+};
+
+/* Colorspace conversion */
+struct jpeg_color_converter {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_compress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+ JDIMENSION output_row, int num_rows));
+};
+
+/* Downsampling */
+struct jpeg_downsampler {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ JMETHOD(void, downsample, (j_compress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION in_row_index,
+ JSAMPIMAGE output_buf,
+ JDIMENSION out_row_group_index));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Forward DCT (also controls coefficient quantization) */
+typedef JMETHOD(void, forward_DCT_ptr,
+ (j_compress_ptr cinfo, jpeg_component_info * compptr,
+ JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
+ JDIMENSION start_row, JDIMENSION start_col,
+ JDIMENSION num_blocks));
+
+struct jpeg_forward_dct {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo));
+ /* It is useful to allow each component to have a separate FDCT method. */
+ forward_DCT_ptr forward_DCT[MAX_COMPONENTS];
+};
+
+/* Entropy encoding */
+struct jpeg_entropy_encoder {
+ JMETHOD(void, start_pass, (j_compress_ptr cinfo, boolean gather_statistics));
+ JMETHOD(boolean, encode_mcu, (j_compress_ptr cinfo, JBLOCKROW *MCU_data));
+ JMETHOD(void, finish_pass, (j_compress_ptr cinfo));
+};
+
+/* Marker writing */
+struct jpeg_marker_writer {
+ JMETHOD(void, write_file_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_frame_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_scan_header, (j_compress_ptr cinfo));
+ JMETHOD(void, write_file_trailer, (j_compress_ptr cinfo));
+ JMETHOD(void, write_tables_only, (j_compress_ptr cinfo));
+ /* These routines are exported to allow insertion of extra markers */
+ /* Probably only COM and APPn markers should be written this way */
+ JMETHOD(void, write_marker_header, (j_compress_ptr cinfo, int marker,
+ unsigned int datalen));
+ JMETHOD(void, write_marker_byte, (j_compress_ptr cinfo, int val));
+};
+
+
+/* Declarations for decompression modules */
+
+/* Master control module */
+struct jpeg_decomp_master {
+ JMETHOD(void, prepare_for_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_output_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean is_dummy_pass; /* True during 1st pass for 2-pass quant */
+};
+
+/* Input control module */
+struct jpeg_input_controller {
+ JMETHOD(int, consume_input, (j_decompress_ptr cinfo));
+ JMETHOD(void, reset_input_controller, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, finish_input_pass, (j_decompress_ptr cinfo));
+
+ /* State variables made visible to other modules */
+ boolean has_multiple_scans; /* True if file has multiple scans */
+ boolean eoi_reached; /* True when EOI has been consumed */
+};
+
+/* Main buffer control (downsampled-data buffer) */
+struct jpeg_d_main_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, process_data, (j_decompress_ptr cinfo,
+ JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Coefficient buffer control */
+struct jpeg_d_coef_controller {
+ JMETHOD(void, start_input_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, consume_data, (j_decompress_ptr cinfo));
+ JMETHOD(void, start_output_pass, (j_decompress_ptr cinfo));
+ JMETHOD(int, decompress_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE output_buf));
+ /* Pointer to array of coefficient virtual arrays, or NULL if none */
+ jvirt_barray_ptr *coef_arrays;
+};
+
+/* Decompression postprocessing (color quantization buffer control) */
+struct jpeg_d_post_controller {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, J_BUF_MODE pass_mode));
+ JMETHOD(void, post_process_data, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+};
+
+/* Marker reading & parsing */
+struct jpeg_marker_reader {
+ JMETHOD(void, reset_marker_reader, (j_decompress_ptr cinfo));
+ /* Read markers until SOS or EOI.
+ * Returns same codes as are defined for jpeg_consume_input:
+ * JPEG_SUSPENDED, JPEG_REACHED_SOS, or JPEG_REACHED_EOI.
+ */
+ JMETHOD(int, read_markers, (j_decompress_ptr cinfo));
+ /* Read a restart marker --- exported for use by entropy decoder only */
+ jpeg_marker_parser_method read_restart_marker;
+
+ /* State of marker reader --- nominally internal, but applications
+ * supplying COM or APPn handlers might like to know the state.
+ */
+ boolean saw_SOI; /* found SOI? */
+ boolean saw_SOF; /* found SOF? */
+ int next_restart_num; /* next restart number expected (0-7) */
+ unsigned int discarded_bytes; /* # of bytes skipped looking for a marker */
+};
+
+/* Entropy decoding */
+struct jpeg_entropy_decoder {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, decode_mcu, (j_decompress_ptr cinfo,
+ JBLOCKROW *MCU_data));
+
+ /* This is here to share code between baseline and progressive decoders; */
+ /* other modules probably should not use it */
+ boolean insufficient_data; /* set TRUE after emitting warning */
+};
+
+/* Inverse DCT (also performs dequantization) */
+typedef JMETHOD(void, inverse_DCT_method_ptr,
+ (j_decompress_ptr cinfo, jpeg_component_info * compptr,
+ JCOEFPTR coef_block,
+ JSAMPARRAY output_buf, JDIMENSION output_col));
+
+struct jpeg_inverse_dct {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ /* It is useful to allow each component to have a separate IDCT method. */
+ inverse_DCT_method_ptr inverse_DCT[MAX_COMPONENTS];
+};
+
+/* Upsampling (note that upsampler must also call color converter) */
+struct jpeg_upsampler {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, upsample, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf,
+ JDIMENSION *in_row_group_ctr,
+ JDIMENSION in_row_groups_avail,
+ JSAMPARRAY output_buf,
+ JDIMENSION *out_row_ctr,
+ JDIMENSION out_rows_avail));
+
+ boolean need_context_rows; /* TRUE if need rows above & below */
+};
+
+/* Colorspace conversion */
+struct jpeg_color_deconverter {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, color_convert, (j_decompress_ptr cinfo,
+ JSAMPIMAGE input_buf, JDIMENSION input_row,
+ JSAMPARRAY output_buf, int num_rows));
+};
+
+/* Color quantization or color precision reduction */
+struct jpeg_color_quantizer {
+ JMETHOD(void, start_pass, (j_decompress_ptr cinfo, boolean is_pre_scan));
+ JMETHOD(void, color_quantize, (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf,
+ int num_rows));
+ JMETHOD(void, finish_pass, (j_decompress_ptr cinfo));
+ JMETHOD(void, new_color_map, (j_decompress_ptr cinfo));
+};
+
+
+/* Miscellaneous useful macros */
+
+#undef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#undef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity. This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit. But some
+ * C compilers implement >> with an unsigned shift. For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts. SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft) \
+ ((shift_temp = (x)) < 0 ? \
+ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+ (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft) ((x) >> (shft))
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jinit_compress_master jICompress
+#define jinit_c_master_control jICMaster
+#define jinit_c_main_controller jICMainC
+#define jinit_c_prep_controller jICPrepC
+#define jinit_c_coef_controller jICCoefC
+#define jinit_color_converter jICColor
+#define jinit_downsampler jIDownsampler
+#define jinit_forward_dct jIFDCT
+#define jinit_huff_encoder jIHEncoder
+#define jinit_arith_encoder jIAEncoder
+#define jinit_marker_writer jIMWriter
+#define jinit_master_decompress jIDMaster
+#define jinit_d_main_controller jIDMainC
+#define jinit_d_coef_controller jIDCoefC
+#define jinit_d_post_controller jIDPostC
+#define jinit_input_controller jIInCtlr
+#define jinit_marker_reader jIMReader
+#define jinit_huff_decoder jIHDecoder
+#define jinit_arith_decoder jIADecoder
+#define jinit_inverse_dct jIIDCT
+#define jinit_upsampler jIUpsampler
+#define jinit_color_deconverter jIDColor
+#define jinit_1pass_quantizer jI1Quant
+#define jinit_2pass_quantizer jI2Quant
+#define jinit_merged_upsampler jIMUpsampler
+#define jinit_memory_mgr jIMemMgr
+#define jdiv_round_up jDivRound
+#define jround_up jRound
+#define jcopy_sample_rows jCopySamples
+#define jcopy_block_row jCopyBlocks
+#define jzero_far jZeroFar
+#define jpeg_zigzag_order jZIGTable
+#define jpeg_natural_order jZAGTable
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Compression module initialization routines */
+EXTERN(void) jinit_compress_master JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_c_master_control JPP((j_compress_ptr cinfo,
+ boolean transcode_only));
+EXTERN(void) jinit_c_main_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_prep_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_c_coef_controller JPP((j_compress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_color_converter JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
+/* Decompression module initialization routines */
+EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_d_main_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_coef_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_d_post_controller JPP((j_decompress_ptr cinfo,
+ boolean need_full_buffer));
+EXTERN(void) jinit_input_controller JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_1pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_2pass_quantizer JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_merged_upsampler JPP((j_decompress_ptr cinfo));
+/* Memory manager initialization */
+EXTERN(void) jinit_memory_mgr JPP((j_common_ptr cinfo));
+
+/* Utility routines in jutils.c */
+EXTERN(long) jdiv_round_up JPP((long a, long b));
+EXTERN(long) jround_up JPP((long a, long b));
+EXTERN(void) jcopy_sample_rows JPP((JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols));
+EXTERN(void) jcopy_block_row JPP((JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks));
+EXTERN(void) jzero_far JPP((void FAR * target, size_t bytestozero));
+/* Constant tables in jutils.c */
+#if 0 /* This table is not actually needed in v6a */
+extern const int jpeg_zigzag_order[]; /* natural coef order to zigzag order */
+#endif
+extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
+
+/* Suppress undefined-structure complaints if necessary. */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef AM_MEMORY_MANAGER /* only jmemmgr.c defines these */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+#endif
+#endif /* INCOMPLETE_TYPES_BROKEN */
diff --git a/Source/LibJPEG/jpeglib.h b/Source/LibJPEG/jpeglib.h
new file mode 100644
index 0000000..341a19c
--- /dev/null
+++ b/Source/LibJPEG/jpeglib.h
@@ -0,0 +1,1135 @@
+/*
+ * jpeglib.h
+ *
+ * Copyright (C) 1991-1998, Thomas G. Lane.
+ * Modified 2002-2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file defines the application interface for the JPEG library.
+ * Most applications using the library need only include this file,
+ * and perhaps jerror.h if they want to know the exact error codes.
+ */
+
+#ifndef JPEGLIB_H
+#define JPEGLIB_H
+
+/*
+ * First we include the configuration files that record how this
+ * installation of the JPEG library is set up. jconfig.h can be
+ * generated automatically for many systems. jmorecfg.h contains
+ * manual configuration options that most people need not worry about.
+ */
+
+#ifndef JCONFIG_INCLUDED /* in case jinclude.h already did */
+#include "jconfig.h" /* widely used configuration options */
+#endif
+#include "jmorecfg.h" /* seldom changed options */
+
+
+#ifdef __cplusplus
+#ifndef DONT_USE_EXTERN_C
+extern "C" {
+#endif
+#endif
+
+/* Version ID for the JPEG library.
+ * Might be useful for tests like "#if JPEG_LIB_VERSION >= 70".
+ */
+
+#define JPEG_LIB_VERSION 70 /* Version 7.0 */
+
+
+/* Various constants determining the sizes of things.
+ * All of these are specified by the JPEG standard, so don't change them
+ * if you want to be compatible.
+ */
+
+#define DCTSIZE 8 /* The basic DCT block is 8x8 samples */
+#define DCTSIZE2 64 /* DCTSIZE squared; # of elements in a block */
+#define NUM_QUANT_TBLS 4 /* Quantization tables are numbered 0..3 */
+#define NUM_HUFF_TBLS 4 /* Huffman tables are numbered 0..3 */
+#define NUM_ARITH_TBLS 16 /* Arith-coding tables are numbered 0..15 */
+#define MAX_COMPS_IN_SCAN 4 /* JPEG limit on # of components in one scan */
+#define MAX_SAMP_FACTOR 4 /* JPEG limit on sampling factors */
+/* Unfortunately, some bozo at Adobe saw no reason to be bound by the standard;
+ * the PostScript DCT filter can emit files with many more than 10 blocks/MCU.
+ * If you happen to run across such a file, you can up D_MAX_BLOCKS_IN_MCU
+ * to handle it. We even let you do this from the jconfig.h file. However,
+ * we strongly discourage changing C_MAX_BLOCKS_IN_MCU; just because Adobe
+ * sometimes emits noncompliant files doesn't mean you should too.
+ */
+#define C_MAX_BLOCKS_IN_MCU 10 /* compressor's limit on blocks per MCU */
+#ifndef D_MAX_BLOCKS_IN_MCU
+#define D_MAX_BLOCKS_IN_MCU 10 /* decompressor's limit on blocks per MCU */
+#endif
+
+
+/* Data structures for images (arrays of samples and of DCT coefficients).
+ * On 80x86 machines, the image arrays are too big for near pointers,
+ * but the pointer arrays can fit in near memory.
+ */
+
+typedef JSAMPLE FAR *JSAMPROW; /* ptr to one image row of pixel samples. */
+typedef JSAMPROW *JSAMPARRAY; /* ptr to some rows (a 2-D sample array) */
+typedef JSAMPARRAY *JSAMPIMAGE; /* a 3-D sample array: top index is color */
+
+typedef JCOEF JBLOCK[DCTSIZE2]; /* one block of coefficients */
+typedef JBLOCK FAR *JBLOCKROW; /* pointer to one row of coefficient blocks */
+typedef JBLOCKROW *JBLOCKARRAY; /* a 2-D array of coefficient blocks */
+typedef JBLOCKARRAY *JBLOCKIMAGE; /* a 3-D array of coefficient blocks */
+
+typedef JCOEF FAR *JCOEFPTR; /* useful in a couple of places */
+
+
+/* Types for JPEG compression parameters and working tables. */
+
+
+/* DCT coefficient quantization tables. */
+
+typedef struct {
+ /* This array gives the coefficient quantizers in natural array order
+ * (not the zigzag order in which they are stored in a JPEG DQT marker).
+ * CAUTION: IJG versions prior to v6a kept this array in zigzag order.
+ */
+ UINT16 quantval[DCTSIZE2]; /* quantization step for each coefficient */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JQUANT_TBL;
+
+
+/* Huffman coding tables. */
+
+typedef struct {
+ /* These two fields directly represent the contents of a JPEG DHT marker */
+ UINT8 bits[17]; /* bits[k] = # of symbols with codes of */
+ /* length k bits; bits[0] is unused */
+ UINT8 huffval[256]; /* The symbols, in order of incr code length */
+ /* This field is used only during compression. It's initialized FALSE when
+ * the table is created, and set TRUE when it's been output to the file.
+ * You could suppress output of a table by setting this to TRUE.
+ * (See jpeg_suppress_tables for an example.)
+ */
+ boolean sent_table; /* TRUE when table has been output */
+} JHUFF_TBL;
+
+
+/* Basic info about one component (color channel). */
+
+typedef struct {
+ /* These values are fixed over the whole image. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOF marker. */
+ int component_id; /* identifier for this component (0..255) */
+ int component_index; /* its index in SOF or cinfo->comp_info[] */
+ int h_samp_factor; /* horizontal sampling factor (1..4) */
+ int v_samp_factor; /* vertical sampling factor (1..4) */
+ int quant_tbl_no; /* quantization table selector (0..3) */
+ /* These values may vary between scans. */
+ /* For compression, they must be supplied by parameter setup; */
+ /* for decompression, they are read from the SOS marker. */
+ /* The decompressor output side may not use these variables. */
+ int dc_tbl_no; /* DC entropy table selector (0..3) */
+ int ac_tbl_no; /* AC entropy table selector (0..3) */
+
+ /* Remaining fields should be treated as private by applications. */
+
+ /* These values are computed during compression or decompression startup: */
+ /* Component's size in DCT blocks.
+ * Any dummy blocks added to complete an MCU are not counted; therefore
+ * these values do not depend on whether a scan is interleaved or not.
+ */
+ JDIMENSION width_in_blocks;
+ JDIMENSION height_in_blocks;
+ /* Size of a DCT block in samples,
+ * reflecting any scaling we choose to apply during the DCT step.
+ * Values from 1 to 16 are supported.
+ * Note that different components may receive different DCT scalings.
+ */
+ int DCT_h_scaled_size;
+ int DCT_v_scaled_size;
+ /* The downsampled dimensions are the component's actual, unpadded number
+ * of samples at the main buffer (preprocessing/compression interface);
+ * DCT scaling is included, so
+ * downsampled_width = ceil(image_width * Hi/Hmax * DCT_h_scaled_size/DCTSIZE)
+ * and similarly for height.
+ */
+ JDIMENSION downsampled_width; /* actual width in samples */
+ JDIMENSION downsampled_height; /* actual height in samples */
+ /* This flag is used only for decompression. In cases where some of the
+ * components will be ignored (eg grayscale output from YCbCr image),
+ * we can skip most computations for the unused components.
+ */
+ boolean component_needed; /* do we need the value of this component? */
+
+ /* These values are computed before starting a scan of the component. */
+ /* The decompressor output side may not use these variables. */
+ int MCU_width; /* number of blocks per MCU, horizontally */
+ int MCU_height; /* number of blocks per MCU, vertically */
+ int MCU_blocks; /* MCU_width * MCU_height */
+ int MCU_sample_width; /* MCU width in samples, MCU_width*DCT_scaled_size */
+ int last_col_width; /* # of non-dummy blocks across in last MCU */
+ int last_row_height; /* # of non-dummy blocks down in last MCU */
+
+ /* Saved quantization table for component; NULL if none yet saved.
+ * See jdinput.c comments about the need for this information.
+ * This field is currently used only for decompression.
+ */
+ JQUANT_TBL * quant_table;
+
+ /* Private per-component storage for DCT or IDCT subsystem. */
+ void * dct_table;
+} jpeg_component_info;
+
+
+/* The script for encoding a multiple-scan file is an array of these: */
+
+typedef struct {
+ int comps_in_scan; /* number of components encoded in this scan */
+ int component_index[MAX_COMPS_IN_SCAN]; /* their SOF/comp_info[] indexes */
+ int Ss, Se; /* progressive JPEG spectral selection parms */
+ int Ah, Al; /* progressive JPEG successive approx. parms */
+} jpeg_scan_info;
+
+/* The decompressor can save APPn and COM markers in a list of these: */
+
+typedef struct jpeg_marker_struct FAR * jpeg_saved_marker_ptr;
+
+struct jpeg_marker_struct {
+ jpeg_saved_marker_ptr next; /* next in list, or NULL */
+ UINT8 marker; /* marker code: JPEG_COM, or JPEG_APP0+n */
+ unsigned int original_length; /* # bytes of data in the file */
+ unsigned int data_length; /* # bytes of data saved at data[] */
+ JOCTET FAR * data; /* the data contained in the marker */
+ /* the marker length word is not counted in data_length or original_length */
+};
+
+/* Known color spaces. */
+
+typedef enum {
+ JCS_UNKNOWN, /* error/unspecified */
+ JCS_GRAYSCALE, /* monochrome */
+ JCS_RGB, /* red/green/blue */
+ JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
+ JCS_CMYK, /* C/M/Y/K */
+ JCS_YCCK /* Y/Cb/Cr/K */
+} J_COLOR_SPACE;
+
+/* DCT/IDCT algorithm options. */
+
+typedef enum {
+ JDCT_ISLOW, /* slow but accurate integer algorithm */
+ JDCT_IFAST, /* faster, less accurate integer method */
+ JDCT_FLOAT /* floating-point: accurate, fast on fast HW */
+} J_DCT_METHOD;
+
+#ifndef JDCT_DEFAULT /* may be overridden in jconfig.h */
+#define JDCT_DEFAULT JDCT_ISLOW
+#endif
+#ifndef JDCT_FASTEST /* may be overridden in jconfig.h */
+#define JDCT_FASTEST JDCT_IFAST
+#endif
+
+/* Dithering options for decompression. */
+
+typedef enum {
+ JDITHER_NONE, /* no dithering */
+ JDITHER_ORDERED, /* simple ordered dither */
+ JDITHER_FS /* Floyd-Steinberg error diffusion dither */
+} J_DITHER_MODE;
+
+
+/* Common fields between JPEG compression and decompression master structs. */
+
+#define jpeg_common_fields \
+ struct jpeg_error_mgr * err; /* Error handler module */\
+ struct jpeg_memory_mgr * mem; /* Memory manager module */\
+ struct jpeg_progress_mgr * progress; /* Progress monitor, or NULL if none */\
+ void * client_data; /* Available for use by application */\
+ boolean is_decompressor; /* So common code can tell which is which */\
+ int global_state /* For checking call sequence validity */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure. There are no actual instances of
+ * jpeg_common_struct, only of jpeg_compress_struct and jpeg_decompress_struct.
+ */
+struct jpeg_common_struct {
+ jpeg_common_fields; /* Fields common to both master struct types */
+ /* Additional fields follow in an actual jpeg_compress_struct or
+ * jpeg_decompress_struct. All three structs must agree on these
+ * initial fields! (This would be a lot cleaner in C++.)
+ */
+};
+
+typedef struct jpeg_common_struct * j_common_ptr;
+typedef struct jpeg_compress_struct * j_compress_ptr;
+typedef struct jpeg_decompress_struct * j_decompress_ptr;
+
+
+/* Master record for a compression instance */
+
+struct jpeg_compress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_decompress_struct */
+
+ /* Destination for compressed data */
+ struct jpeg_destination_mgr * dest;
+
+ /* Description of source image --- these fields must be filled in by
+ * outer application before starting compression. in_color_space must
+ * be correct before you can even call jpeg_set_defaults().
+ */
+
+ JDIMENSION image_width; /* input image width */
+ JDIMENSION image_height; /* input image height */
+ int input_components; /* # of color components in input image */
+ J_COLOR_SPACE in_color_space; /* colorspace of input image */
+
+ double input_gamma; /* image gamma of input image */
+
+ /* Compression parameters --- these fields must be set before calling
+ * jpeg_start_compress(). We recommend calling jpeg_set_defaults() to
+ * initialize everything to reasonable defaults, then changing anything
+ * the application specifically wants to change. That way you won't get
+ * burnt when new parameters are added. Also note that there are several
+ * helper routines to simplify changing parameters.
+ */
+
+ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+ JDIMENSION jpeg_width; /* scaled JPEG image width */
+ JDIMENSION jpeg_height; /* scaled JPEG image height */
+ /* Dimensions of actual JPEG image that will be written to file,
+ * derived from input dimensions by scaling factors above.
+ * These fields are computed by jpeg_start_compress().
+ * You can also use jpeg_calc_jpeg_dimensions() to determine these values
+ * in advance of calling jpeg_start_compress().
+ */
+
+ int data_precision; /* bits of precision in image data */
+
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ int q_scale_factor[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined,
+ * and corresponding scale factors (percentage, initialized 100).
+ */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ int num_scans; /* # of entries in scan_info array */
+ const jpeg_scan_info * scan_info; /* script for multi-scan file, or NULL */
+ /* The default value of scan_info is NULL, which causes a single-scan
+ * sequential JPEG file to be emitted. To create a multi-scan file,
+ * set num_scans and scan_info to point to an array of scan definitions.
+ */
+
+ boolean raw_data_in; /* TRUE=caller supplies downsampled data */
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+ boolean optimize_coding; /* TRUE=optimize entropy encoding parms */
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+ boolean do_fancy_downsampling; /* TRUE=apply fancy downsampling */
+ int smoothing_factor; /* 1..100, or 0 for no input smoothing */
+ J_DCT_METHOD dct_method; /* DCT algorithm selector */
+
+ /* The restart interval can be specified in absolute MCUs by setting
+ * restart_interval, or in MCU rows by setting restart_in_rows
+ * (in which case the correct restart_interval will be figured
+ * for each scan).
+ */
+ unsigned int restart_interval; /* MCUs per restart, or 0 for no restart */
+ int restart_in_rows; /* if > 0, MCU rows per restart interval */
+
+ /* Parameters controlling emission of special markers. */
+
+ boolean write_JFIF_header; /* should a JFIF marker be written? */
+ UINT8 JFIF_major_version; /* What to write for the JFIF version number */
+ UINT8 JFIF_minor_version;
+ /* These three values are not used by the JPEG code, merely copied */
+ /* into the JFIF APP0 marker. density_unit can be 0 for unknown, */
+ /* 1 for dots/inch, or 2 for dots/cm. Note that the pixel aspect */
+ /* ratio is defined by X_density/Y_density even when density_unit=0. */
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean write_Adobe_marker; /* should an Adobe marker be written? */
+
+ /* State variable: index of next scanline to be written to
+ * jpeg_write_scanlines(). Application may use this to control its
+ * processing loop, e.g., "while (next_scanline < image_height)".
+ */
+
+ JDIMENSION next_scanline; /* 0 .. image_height-1 */
+
+ /* Remaining fields are known throughout compressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during compression startup
+ */
+ boolean progressive_mode; /* TRUE if scan script uses progressive mode */
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
+ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows to be input to coef ctlr */
+ /* The coefficient controller receives data in units of MCU rows as defined
+ * for fully interleaved scans (whether the JPEG file is interleaved or not).
+ * There are v_samp_factor * DCTSIZE sample rows of each component in an
+ * "iMCU" (interleaved MCU) row.
+ */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int blocks_in_MCU; /* # of DCT blocks per MCU */
+ int MCU_membership[C_MAX_BLOCKS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th block in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
+
+ /*
+ * Links to compression subobjects (methods and private variables of modules)
+ */
+ struct jpeg_comp_master * master;
+ struct jpeg_c_main_controller * main;
+ struct jpeg_c_prep_controller * prep;
+ struct jpeg_c_coef_controller * coef;
+ struct jpeg_marker_writer * marker;
+ struct jpeg_color_converter * cconvert;
+ struct jpeg_downsampler * downsample;
+ struct jpeg_forward_dct * fdct;
+ struct jpeg_entropy_encoder * entropy;
+ jpeg_scan_info * script_space; /* workspace for jpeg_simple_progression */
+ int script_space_size;
+};
+
+
+/* Master record for a decompression instance */
+
+struct jpeg_decompress_struct {
+ jpeg_common_fields; /* Fields shared with jpeg_compress_struct */
+
+ /* Source of compressed data */
+ struct jpeg_source_mgr * src;
+
+ /* Basic description of image --- filled in by jpeg_read_header(). */
+ /* Application may inspect these values to decide how to process image. */
+
+ JDIMENSION image_width; /* nominal image width (from SOF marker) */
+ JDIMENSION image_height; /* nominal image height */
+ int num_components; /* # of color components in JPEG image */
+ J_COLOR_SPACE jpeg_color_space; /* colorspace of JPEG image */
+
+ /* Decompression processing parameters --- these fields must be set before
+ * calling jpeg_start_decompress(). Note that jpeg_read_header() initializes
+ * them to default values.
+ */
+
+ J_COLOR_SPACE out_color_space; /* colorspace for output */
+
+ unsigned int scale_num, scale_denom; /* fraction by which to scale image */
+
+ double output_gamma; /* image gamma wanted in output */
+
+ boolean buffered_image; /* TRUE=multiple output passes */
+ boolean raw_data_out; /* TRUE=downsampled data wanted */
+
+ J_DCT_METHOD dct_method; /* IDCT algorithm selector */
+ boolean do_fancy_upsampling; /* TRUE=apply fancy upsampling */
+ boolean do_block_smoothing; /* TRUE=apply interblock smoothing */
+
+ boolean quantize_colors; /* TRUE=colormapped output wanted */
+ /* the following are ignored if not quantize_colors: */
+ J_DITHER_MODE dither_mode; /* type of color dithering to use */
+ boolean two_pass_quantize; /* TRUE=use two-pass color quantization */
+ int desired_number_of_colors; /* max # colors to use in created colormap */
+ /* these are significant only in buffered-image mode: */
+ boolean enable_1pass_quant; /* enable future use of 1-pass quantizer */
+ boolean enable_external_quant;/* enable future use of external colormap */
+ boolean enable_2pass_quant; /* enable future use of 2-pass quantizer */
+
+ /* Description of actual output image that will be returned to application.
+ * These fields are computed by jpeg_start_decompress().
+ * You can also use jpeg_calc_output_dimensions() to determine these values
+ * in advance of calling jpeg_start_decompress().
+ */
+
+ JDIMENSION output_width; /* scaled image width */
+ JDIMENSION output_height; /* scaled image height */
+ int out_color_components; /* # of color components in out_color_space */
+ int output_components; /* # of color components returned */
+ /* output_components is 1 (a colormap index) when quantizing colors;
+ * otherwise it equals out_color_components.
+ */
+ int rec_outbuf_height; /* min recommended height of scanline buffer */
+ /* If the buffer passed to jpeg_read_scanlines() is less than this many rows
+ * high, space and time will be wasted due to unnecessary data copying.
+ * Usually rec_outbuf_height will be 1 or 2, at most 4.
+ */
+
+ /* When quantizing colors, the output colormap is described by these fields.
+ * The application can supply a colormap by setting colormap non-NULL before
+ * calling jpeg_start_decompress; otherwise a colormap is created during
+ * jpeg_start_decompress or jpeg_start_output.
+ * The map has out_color_components rows and actual_number_of_colors columns.
+ */
+ int actual_number_of_colors; /* number of entries in use */
+ JSAMPARRAY colormap; /* The color map as a 2-D pixel array */
+
+ /* State variables: these variables indicate the progress of decompression.
+ * The application may examine these but must not modify them.
+ */
+
+ /* Row index of next scanline to be read from jpeg_read_scanlines().
+ * Application may use this to control its processing loop, e.g.,
+ * "while (output_scanline < output_height)".
+ */
+ JDIMENSION output_scanline; /* 0 .. output_height-1 */
+
+ /* Current input scan number and number of iMCU rows completed in scan.
+ * These indicate the progress of the decompressor input side.
+ */
+ int input_scan_number; /* Number of SOS markers seen so far */
+ JDIMENSION input_iMCU_row; /* Number of iMCU rows completed */
+
+ /* The "output scan number" is the notional scan being displayed by the
+ * output side. The decompressor will not allow output scan/row number
+ * to get ahead of input scan/row, but it can fall arbitrarily far behind.
+ */
+ int output_scan_number; /* Nominal scan number being displayed */
+ JDIMENSION output_iMCU_row; /* Number of iMCU rows read */
+
+ /* Current progression status. coef_bits[c][i] indicates the precision
+ * with which component c's DCT coefficient i (in zigzag order) is known.
+ * It is -1 when no data has yet been received, otherwise it is the point
+ * transform (shift) value for the most recent scan of the coefficient
+ * (thus, 0 at completion of the progression).
+ * This pointer is NULL when reading a non-progressive file.
+ */
+ int (*coef_bits)[DCTSIZE2]; /* -1 or current Al value for each coef */
+
+ /* Internal JPEG parameters --- the application usually need not look at
+ * these fields. Note that the decompressor output side may not use
+ * any parameters that can change between scans.
+ */
+
+ /* Quantization and Huffman tables are carried forward across input
+ * datastreams when processing abbreviated JPEG datastreams.
+ */
+
+ JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS];
+ /* ptrs to coefficient quantization tables, or NULL if not defined */
+
+ JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS];
+ /* ptrs to Huffman coding tables, or NULL if not defined */
+
+ /* These parameters are never carried across datastreams, since they
+ * are given in SOF/SOS markers or defined to be reset by SOI.
+ */
+
+ int data_precision; /* bits of precision in image data */
+
+ jpeg_component_info * comp_info;
+ /* comp_info[i] describes component that appears i'th in SOF */
+
+ boolean progressive_mode; /* TRUE if SOFn specifies progressive mode */
+ boolean arith_code; /* TRUE=arithmetic coding, FALSE=Huffman */
+
+ UINT8 arith_dc_L[NUM_ARITH_TBLS]; /* L values for DC arith-coding tables */
+ UINT8 arith_dc_U[NUM_ARITH_TBLS]; /* U values for DC arith-coding tables */
+ UINT8 arith_ac_K[NUM_ARITH_TBLS]; /* Kx values for AC arith-coding tables */
+
+ unsigned int restart_interval; /* MCUs per restart interval, or 0 for no restart */
+
+ /* These fields record data obtained from optional markers recognized by
+ * the JPEG library.
+ */
+ boolean saw_JFIF_marker; /* TRUE iff a JFIF APP0 marker was found */
+ /* Data copied from JFIF marker; only valid if saw_JFIF_marker is TRUE: */
+ UINT8 JFIF_major_version; /* JFIF version number */
+ UINT8 JFIF_minor_version;
+ UINT8 density_unit; /* JFIF code for pixel size units */
+ UINT16 X_density; /* Horizontal pixel density */
+ UINT16 Y_density; /* Vertical pixel density */
+ boolean saw_Adobe_marker; /* TRUE iff an Adobe APP14 marker was found */
+ UINT8 Adobe_transform; /* Color transform code from Adobe marker */
+
+ boolean CCIR601_sampling; /* TRUE=first samples are cosited */
+
+ /* Aside from the specific data retained from APPn markers known to the
+ * library, the uninterpreted contents of any or all APPn and COM markers
+ * can be saved in a list for examination by the application.
+ */
+ jpeg_saved_marker_ptr marker_list; /* Head of list of saved markers */
+
+ /* Remaining fields are known throughout decompressor, but generally
+ * should not be touched by a surrounding application.
+ */
+
+ /*
+ * These fields are computed during decompression startup
+ */
+ int max_h_samp_factor; /* largest h_samp_factor */
+ int max_v_samp_factor; /* largest v_samp_factor */
+
+ int min_DCT_h_scaled_size; /* smallest DCT_h_scaled_size of any component */
+ int min_DCT_v_scaled_size; /* smallest DCT_v_scaled_size of any component */
+
+ JDIMENSION total_iMCU_rows; /* # of iMCU rows in image */
+ /* The coefficient controller's input and output progress is measured in
+ * units of "iMCU" (interleaved MCU) rows. These are the same as MCU rows
+ * in fully interleaved JPEG scans, but are used whether the scan is
+ * interleaved or not. We define an iMCU row as v_samp_factor DCT block
+ * rows of each component. Therefore, the IDCT output contains
+ * v_samp_factor*DCT_v_scaled_size sample rows of a component per iMCU row.
+ */
+
+ JSAMPLE * sample_range_limit; /* table for fast range-limiting */
+
+ /*
+ * These fields are valid during any one scan.
+ * They describe the components and MCUs actually appearing in the scan.
+ * Note that the decompressor output side must not use these fields.
+ */
+ int comps_in_scan; /* # of JPEG components in this scan */
+ jpeg_component_info * cur_comp_info[MAX_COMPS_IN_SCAN];
+ /* *cur_comp_info[i] describes component that appears i'th in SOS */
+
+ JDIMENSION MCUs_per_row; /* # of MCUs across the image */
+ JDIMENSION MCU_rows_in_scan; /* # of MCU rows in the image */
+
+ int blocks_in_MCU; /* # of DCT blocks per MCU */
+ int MCU_membership[D_MAX_BLOCKS_IN_MCU];
+ /* MCU_membership[i] is index in cur_comp_info of component owning */
+ /* i'th block in an MCU */
+
+ int Ss, Se, Ah, Al; /* progressive JPEG parameters for scan */
+
+ /* This field is shared between entropy decoder and marker parser.
+ * It is either zero or the code of a JPEG marker that has been
+ * read from the data source, but has not yet been processed.
+ */
+ int unread_marker;
+
+ /*
+ * Links to decompression subobjects (methods, private variables of modules)
+ */
+ struct jpeg_decomp_master * master;
+ struct jpeg_d_main_controller * main;
+ struct jpeg_d_coef_controller * coef;
+ struct jpeg_d_post_controller * post;
+ struct jpeg_input_controller * inputctl;
+ struct jpeg_marker_reader * marker;
+ struct jpeg_entropy_decoder * entropy;
+ struct jpeg_inverse_dct * idct;
+ struct jpeg_upsampler * upsample;
+ struct jpeg_color_deconverter * cconvert;
+ struct jpeg_color_quantizer * cquantize;
+};
+
+
+/* "Object" declarations for JPEG modules that may be supplied or called
+ * directly by the surrounding application.
+ * As with all objects in the JPEG library, these structs only define the
+ * publicly visible methods and state variables of a module. Additional
+ * private fields may exist after the public ones.
+ */
+
+
+/* Error handler object */
+
+struct jpeg_error_mgr {
+ /* Error exit handler: does not return to caller */
+ JMETHOD(void, error_exit, (j_common_ptr cinfo));
+ /* Conditionally emit a trace or warning message */
+ JMETHOD(void, emit_message, (j_common_ptr cinfo, int msg_level));
+ /* Routine that actually outputs a trace or error message */
+ JMETHOD(void, output_message, (j_common_ptr cinfo));
+ /* Format a message string for the most recent JPEG error or message */
+ JMETHOD(void, format_message, (j_common_ptr cinfo, char * buffer));
+#define JMSG_LENGTH_MAX 200 /* recommended size of format_message buffer */
+ /* Reset error state variables at start of a new image */
+ JMETHOD(void, reset_error_mgr, (j_common_ptr cinfo));
+
+ /* The message ID code and any parameters are saved here.
+ * A message can have one string parameter or up to 8 int parameters.
+ */
+ int msg_code;
+#define JMSG_STR_PARM_MAX 80
+ union {
+ int i[8];
+ char s[JMSG_STR_PARM_MAX];
+ } msg_parm;
+
+ /* Standard state variables for error facility */
+
+ int trace_level; /* max msg_level that will be displayed */
+
+ /* For recoverable corrupt-data errors, we emit a warning message,
+ * but keep going unless emit_message chooses to abort. emit_message
+ * should count warnings in num_warnings. The surrounding application
+ * can check for bad data by seeing if num_warnings is nonzero at the
+ * end of processing.
+ */
+ long num_warnings; /* number of corrupt-data warnings */
+
+ /* These fields point to the table(s) of error message strings.
+ * An application can change the table pointer to switch to a different
+ * message list (typically, to change the language in which errors are
+ * reported). Some applications may wish to add additional error codes
+ * that will be handled by the JPEG library error mechanism; the second
+ * table pointer is used for this purpose.
+ *
+ * First table includes all errors generated by JPEG library itself.
+ * Error code 0 is reserved for a "no such error string" message.
+ */
+ const char * const * jpeg_message_table; /* Library errors */
+ int last_jpeg_message; /* Table contains strings 0..last_jpeg_message */
+ /* Second table can be added by application (see cjpeg/djpeg for example).
+ * It contains strings numbered first_addon_message..last_addon_message.
+ */
+ const char * const * addon_message_table; /* Non-library errors */
+ int first_addon_message; /* code for first string in addon table */
+ int last_addon_message; /* code for last string in addon table */
+};
+
+
+/* Progress monitor object */
+
+struct jpeg_progress_mgr {
+ JMETHOD(void, progress_monitor, (j_common_ptr cinfo));
+
+ long pass_counter; /* work units completed in this pass */
+ long pass_limit; /* total number of work units in this pass */
+ int completed_passes; /* passes completed so far */
+ int total_passes; /* total number of passes expected */
+};
+
+
+/* Data destination object for compression */
+
+struct jpeg_destination_mgr {
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+
+ JMETHOD(void, init_destination, (j_compress_ptr cinfo));
+ JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
+ JMETHOD(void, term_destination, (j_compress_ptr cinfo));
+};
+
+
+/* Data source object for decompression */
+
+struct jpeg_source_mgr {
+ const JOCTET * next_input_byte; /* => next byte to read from buffer */
+ size_t bytes_in_buffer; /* # of bytes remaining in buffer */
+
+ JMETHOD(void, init_source, (j_decompress_ptr cinfo));
+ JMETHOD(boolean, fill_input_buffer, (j_decompress_ptr cinfo));
+ JMETHOD(void, skip_input_data, (j_decompress_ptr cinfo, long num_bytes));
+ JMETHOD(boolean, resync_to_restart, (j_decompress_ptr cinfo, int desired));
+ JMETHOD(void, term_source, (j_decompress_ptr cinfo));
+};
+
+
+/* Memory manager object.
+ * Allocates "small" objects (a few K total), "large" objects (tens of K),
+ * and "really big" objects (virtual arrays with backing store if needed).
+ * The memory manager does not allow individual objects to be freed; rather,
+ * each created object is assigned to a pool, and whole pools can be freed
+ * at once. This is faster and more convenient than remembering exactly what
+ * to free, especially where malloc()/free() are not too speedy.
+ * NB: alloc routines never return NULL. They exit to error_exit if not
+ * successful.
+ */
+
+#define JPOOL_PERMANENT 0 /* lasts until master record is destroyed */
+#define JPOOL_IMAGE 1 /* lasts until done with image/datastream */
+#define JPOOL_NUMPOOLS 2
+
+typedef struct jvirt_sarray_control * jvirt_sarray_ptr;
+typedef struct jvirt_barray_control * jvirt_barray_ptr;
+
+
+struct jpeg_memory_mgr {
+ /* Method pointers */
+ JMETHOD(void *, alloc_small, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(void FAR *, alloc_large, (j_common_ptr cinfo, int pool_id,
+ size_t sizeofobject));
+ JMETHOD(JSAMPARRAY, alloc_sarray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows));
+ JMETHOD(JBLOCKARRAY, alloc_barray, (j_common_ptr cinfo, int pool_id,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows));
+ JMETHOD(jvirt_sarray_ptr, request_virt_sarray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION samplesperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(jvirt_barray_ptr, request_virt_barray, (j_common_ptr cinfo,
+ int pool_id,
+ boolean pre_zero,
+ JDIMENSION blocksperrow,
+ JDIMENSION numrows,
+ JDIMENSION maxaccess));
+ JMETHOD(void, realize_virt_arrays, (j_common_ptr cinfo));
+ JMETHOD(JSAMPARRAY, access_virt_sarray, (j_common_ptr cinfo,
+ jvirt_sarray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(JBLOCKARRAY, access_virt_barray, (j_common_ptr cinfo,
+ jvirt_barray_ptr ptr,
+ JDIMENSION start_row,
+ JDIMENSION num_rows,
+ boolean writable));
+ JMETHOD(void, free_pool, (j_common_ptr cinfo, int pool_id));
+ JMETHOD(void, self_destruct, (j_common_ptr cinfo));
+
+ /* Limit on memory allocation for this JPEG object. (Note that this is
+ * merely advisory, not a guaranteed maximum; it only affects the space
+ * used for virtual-array buffers.) May be changed by outer application
+ * after creating the JPEG object.
+ */
+ long max_memory_to_use;
+
+ /* Maximum allocation request accepted by alloc_large. */
+ long max_alloc_chunk;
+};
+
+
+/* Routine signature for application-supplied marker processing methods.
+ * Need not pass marker code since it is stored in cinfo->unread_marker.
+ */
+typedef JMETHOD(boolean, jpeg_marker_parser_method, (j_decompress_ptr cinfo));
+
+
+/* Declarations for routines called by application.
+ * The JPP macro hides prototype parameters from compilers that can't cope.
+ * Note JPP requires double parentheses.
+ */
+
+#ifdef HAVE_PROTOTYPES
+#define JPP(arglist) arglist
+#else
+#define JPP(arglist) ()
+#endif
+
+
+/* Short forms of external names for systems with brain-damaged linkers.
+ * We shorten external names to be unique in the first six letters, which
+ * is good enough for all known systems.
+ * (If your compiler itself needs names to be unique in less than 15
+ * characters, you are out of luck. Get a better compiler.)
+ */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jpeg_std_error jStdError
+#define jpeg_CreateCompress jCreaCompress
+#define jpeg_CreateDecompress jCreaDecompress
+#define jpeg_destroy_compress jDestCompress
+#define jpeg_destroy_decompress jDestDecompress
+#define jpeg_stdio_dest jStdDest
+#define jpeg_stdio_src jStdSrc
+#define jpeg_set_defaults jSetDefaults
+#define jpeg_set_colorspace jSetColorspace
+#define jpeg_default_colorspace jDefColorspace
+#define jpeg_set_quality jSetQuality
+#define jpeg_set_linear_quality jSetLQuality
+#define jpeg_default_qtables jDefQTables
+#define jpeg_add_quant_table jAddQuantTable
+#define jpeg_quality_scaling jQualityScaling
+#define jpeg_simple_progression jSimProgress
+#define jpeg_suppress_tables jSuppressTables
+#define jpeg_alloc_quant_table jAlcQTable
+#define jpeg_alloc_huff_table jAlcHTable
+#define jpeg_start_compress jStrtCompress
+#define jpeg_write_scanlines jWrtScanlines
+#define jpeg_finish_compress jFinCompress
+#define jpeg_calc_jpeg_dimensions jCjpegDimensions
+#define jpeg_write_raw_data jWrtRawData
+#define jpeg_write_marker jWrtMarker
+#define jpeg_write_m_header jWrtMHeader
+#define jpeg_write_m_byte jWrtMByte
+#define jpeg_write_tables jWrtTables
+#define jpeg_read_header jReadHeader
+#define jpeg_start_decompress jStrtDecompress
+#define jpeg_read_scanlines jReadScanlines
+#define jpeg_finish_decompress jFinDecompress
+#define jpeg_read_raw_data jReadRawData
+#define jpeg_has_multiple_scans jHasMultScn
+#define jpeg_start_output jStrtOutput
+#define jpeg_finish_output jFinOutput
+#define jpeg_input_complete jInComplete
+#define jpeg_new_colormap jNewCMap
+#define jpeg_consume_input jConsumeInput
+#define jpeg_calc_output_dimensions jCalcDimensions
+#define jpeg_save_markers jSaveMarkers
+#define jpeg_set_marker_processor jSetMarker
+#define jpeg_read_coefficients jReadCoefs
+#define jpeg_write_coefficients jWrtCoefs
+#define jpeg_copy_critical_parameters jCopyCrit
+#define jpeg_abort_compress jAbrtCompress
+#define jpeg_abort_decompress jAbrtDecompress
+#define jpeg_abort jAbort
+#define jpeg_destroy jDestroy
+#define jpeg_resync_to_restart jResyncRestart
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/* Default error-management setup */
+EXTERN(struct jpeg_error_mgr *) jpeg_std_error
+ JPP((struct jpeg_error_mgr * err));
+
+/* Initialization of JPEG compression objects.
+ * jpeg_create_compress() and jpeg_create_decompress() are the exported
+ * names that applications should call. These expand to calls on
+ * jpeg_CreateCompress and jpeg_CreateDecompress with additional information
+ * passed for version mismatch checking.
+ * NB: you must set up the error-manager BEFORE calling jpeg_create_xxx.
+ */
+#define jpeg_create_compress(cinfo) \
+ jpeg_CreateCompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_compress_struct))
+#define jpeg_create_decompress(cinfo) \
+ jpeg_CreateDecompress((cinfo), JPEG_LIB_VERSION, \
+ (size_t) sizeof(struct jpeg_decompress_struct))
+EXTERN(void) jpeg_CreateCompress JPP((j_compress_ptr cinfo,
+ int version, size_t structsize));
+EXTERN(void) jpeg_CreateDecompress JPP((j_decompress_ptr cinfo,
+ int version, size_t structsize));
+/* Destruction of JPEG compression objects */
+EXTERN(void) jpeg_destroy_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_destroy_decompress JPP((j_decompress_ptr cinfo));
+
+/* Standard data source and destination managers: stdio streams. */
+/* Caller is responsible for opening the file before and closing after. */
+EXTERN(void) jpeg_stdio_dest JPP((j_compress_ptr cinfo, FILE * outfile));
+EXTERN(void) jpeg_stdio_src JPP((j_decompress_ptr cinfo, FILE * infile));
+
+/* Default parameter setup for compression */
+EXTERN(void) jpeg_set_defaults JPP((j_compress_ptr cinfo));
+/* Compression parameter setup aids */
+EXTERN(void) jpeg_set_colorspace JPP((j_compress_ptr cinfo,
+ J_COLOR_SPACE colorspace));
+EXTERN(void) jpeg_default_colorspace JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_set_quality JPP((j_compress_ptr cinfo, int quality,
+ boolean force_baseline));
+EXTERN(void) jpeg_set_linear_quality JPP((j_compress_ptr cinfo,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(void) jpeg_default_qtables JPP((j_compress_ptr cinfo,
+ boolean force_baseline));
+EXTERN(void) jpeg_add_quant_table JPP((j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor,
+ boolean force_baseline));
+EXTERN(int) jpeg_quality_scaling JPP((int quality));
+EXTERN(void) jpeg_simple_progression JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_suppress_tables JPP((j_compress_ptr cinfo,
+ boolean suppress));
+EXTERN(JQUANT_TBL *) jpeg_alloc_quant_table JPP((j_common_ptr cinfo));
+EXTERN(JHUFF_TBL *) jpeg_alloc_huff_table JPP((j_common_ptr cinfo));
+
+/* Main entry points for compression */
+EXTERN(void) jpeg_start_compress JPP((j_compress_ptr cinfo,
+ boolean write_all_tables));
+EXTERN(JDIMENSION) jpeg_write_scanlines JPP((j_compress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION num_lines));
+EXTERN(void) jpeg_finish_compress JPP((j_compress_ptr cinfo));
+
+/* Precalculate JPEG dimensions for current compression parameters. */
+EXTERN(void) jpeg_calc_jpeg_dimensions JPP((j_compress_ptr cinfo));
+
+/* Replaces jpeg_write_scanlines when writing raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_write_raw_data JPP((j_compress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION num_lines));
+
+/* Write a special marker. See libjpeg.txt concerning safe usage. */
+EXTERN(void) jpeg_write_marker
+ JPP((j_compress_ptr cinfo, int marker,
+ const JOCTET * dataptr, unsigned int datalen));
+/* Same, but piecemeal. */
+EXTERN(void) jpeg_write_m_header
+ JPP((j_compress_ptr cinfo, int marker, unsigned int datalen));
+EXTERN(void) jpeg_write_m_byte
+ JPP((j_compress_ptr cinfo, int val));
+
+/* Alternate compression function: just write an abbreviated table file */
+EXTERN(void) jpeg_write_tables JPP((j_compress_ptr cinfo));
+
+/* Decompression startup: read start of JPEG datastream to see what's there */
+EXTERN(int) jpeg_read_header JPP((j_decompress_ptr cinfo,
+ boolean require_image));
+/* Return value is one of: */
+#define JPEG_SUSPENDED 0 /* Suspended due to lack of input data */
+#define JPEG_HEADER_OK 1 /* Found valid image datastream */
+#define JPEG_HEADER_TABLES_ONLY 2 /* Found valid table-specs-only datastream */
+/* If you pass require_image = TRUE (normal case), you need not check for
+ * a TABLES_ONLY return code; an abbreviated file will cause an error exit.
+ * JPEG_SUSPENDED is only possible if you use a data source module that can
+ * give a suspension return (the stdio source module doesn't).
+ */
+
+/* Main entry points for decompression */
+EXTERN(boolean) jpeg_start_decompress JPP((j_decompress_ptr cinfo));
+EXTERN(JDIMENSION) jpeg_read_scanlines JPP((j_decompress_ptr cinfo,
+ JSAMPARRAY scanlines,
+ JDIMENSION max_lines));
+EXTERN(boolean) jpeg_finish_decompress JPP((j_decompress_ptr cinfo));
+
+/* Replaces jpeg_read_scanlines when reading raw downsampled data. */
+EXTERN(JDIMENSION) jpeg_read_raw_data JPP((j_decompress_ptr cinfo,
+ JSAMPIMAGE data,
+ JDIMENSION max_lines));
+
+/* Additional entry points for buffered-image mode. */
+EXTERN(boolean) jpeg_has_multiple_scans JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_start_output JPP((j_decompress_ptr cinfo,
+ int scan_number));
+EXTERN(boolean) jpeg_finish_output JPP((j_decompress_ptr cinfo));
+EXTERN(boolean) jpeg_input_complete JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_new_colormap JPP((j_decompress_ptr cinfo));
+EXTERN(int) jpeg_consume_input JPP((j_decompress_ptr cinfo));
+/* Return value is one of: */
+/* #define JPEG_SUSPENDED 0 Suspended due to lack of input data */
+#define JPEG_REACHED_SOS 1 /* Reached start of new scan */
+#define JPEG_REACHED_EOI 2 /* Reached end of image */
+#define JPEG_ROW_COMPLETED 3 /* Completed one iMCU row */
+#define JPEG_SCAN_COMPLETED 4 /* Completed last iMCU row of a scan */
+
+/* Precalculate output dimensions for current decompression parameters. */
+EXTERN(void) jpeg_calc_output_dimensions JPP((j_decompress_ptr cinfo));
+
+/* Control saving of COM and APPn markers into marker_list. */
+EXTERN(void) jpeg_save_markers
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ unsigned int length_limit));
+
+/* Install a special processing method for COM or APPn markers. */
+EXTERN(void) jpeg_set_marker_processor
+ JPP((j_decompress_ptr cinfo, int marker_code,
+ jpeg_marker_parser_method routine));
+
+/* Read or write raw DCT coefficients --- useful for lossless transcoding. */
+EXTERN(jvirt_barray_ptr *) jpeg_read_coefficients JPP((j_decompress_ptr cinfo));
+EXTERN(void) jpeg_write_coefficients JPP((j_compress_ptr cinfo,
+ jvirt_barray_ptr * coef_arrays));
+EXTERN(void) jpeg_copy_critical_parameters JPP((j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo));
+
+/* If you choose to abort compression or decompression before completing
+ * jpeg_finish_(de)compress, then you need to clean up to release memory,
+ * temporary files, etc. You can just call jpeg_destroy_(de)compress
+ * if you're done with the JPEG object, but if you want to clean it up and
+ * reuse it, call this:
+ */
+EXTERN(void) jpeg_abort_compress JPP((j_compress_ptr cinfo));
+EXTERN(void) jpeg_abort_decompress JPP((j_decompress_ptr cinfo));
+
+/* Generic versions of jpeg_abort and jpeg_destroy that work on either
+ * flavor of JPEG object. These may be more convenient in some places.
+ */
+EXTERN(void) jpeg_abort JPP((j_common_ptr cinfo));
+EXTERN(void) jpeg_destroy JPP((j_common_ptr cinfo));
+
+/* Default restart-marker-resync procedure for use by data source modules */
+EXTERN(boolean) jpeg_resync_to_restart JPP((j_decompress_ptr cinfo,
+ int desired));
+
+
+/* These marker codes are exported since applications and data source modules
+ * are likely to want to use them.
+ */
+
+#define JPEG_RST0 0xD0 /* RST0 marker code */
+#define JPEG_EOI 0xD9 /* EOI marker code */
+#define JPEG_APP0 0xE0 /* APP0 marker code */
+#define JPEG_COM 0xFE /* COM marker code */
+
+
+/* If we have a brain-damaged compiler that emits warnings (or worse, errors)
+ * for structure definitions that are never filled in, keep it quiet by
+ * supplying dummy definitions for the various substructures.
+ */
+
+#ifdef INCOMPLETE_TYPES_BROKEN
+#ifndef JPEG_INTERNALS /* will be defined in jpegint.h */
+struct jvirt_sarray_control { long dummy; };
+struct jvirt_barray_control { long dummy; };
+struct jpeg_comp_master { long dummy; };
+struct jpeg_c_main_controller { long dummy; };
+struct jpeg_c_prep_controller { long dummy; };
+struct jpeg_c_coef_controller { long dummy; };
+struct jpeg_marker_writer { long dummy; };
+struct jpeg_color_converter { long dummy; };
+struct jpeg_downsampler { long dummy; };
+struct jpeg_forward_dct { long dummy; };
+struct jpeg_entropy_encoder { long dummy; };
+struct jpeg_decomp_master { long dummy; };
+struct jpeg_d_main_controller { long dummy; };
+struct jpeg_d_coef_controller { long dummy; };
+struct jpeg_d_post_controller { long dummy; };
+struct jpeg_input_controller { long dummy; };
+struct jpeg_marker_reader { long dummy; };
+struct jpeg_entropy_decoder { long dummy; };
+struct jpeg_inverse_dct { long dummy; };
+struct jpeg_upsampler { long dummy; };
+struct jpeg_color_deconverter { long dummy; };
+struct jpeg_color_quantizer { long dummy; };
+#endif /* JPEG_INTERNALS */
+#endif /* INCOMPLETE_TYPES_BROKEN */
+
+
+/*
+ * The JPEG library modules define JPEG_INTERNALS before including this file.
+ * The internal structure declarations are read only when that is true.
+ * Applications using the library should not include jpegint.h, but may wish
+ * to include jerror.h.
+ */
+
+#ifdef JPEG_INTERNALS
+#include "jpegint.h" /* fetch private declarations */
+#include "jerror.h" /* fetch error codes too */
+#endif
+
+#ifdef __cplusplus
+#ifndef DONT_USE_EXTERN_C
+}
+#endif
+#endif
+
+#endif /* JPEGLIB_H */
diff --git a/Source/LibJPEG/jpegtran.c b/Source/LibJPEG/jpegtran.c
new file mode 100644
index 0000000..44c061a
--- /dev/null
+++ b/Source/LibJPEG/jpegtran.c
@@ -0,0 +1,546 @@
+/*
+ * jpegtran.c
+ *
+ * Copyright (C) 1995-2001, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a command-line user interface for JPEG transcoding.
+ * It is very similar to cjpeg.c, but provides lossless transcoding between
+ * different JPEG file formats. It also provides some lossless and sort-of-
+ * lossless transformations of JPEG data.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include "transupp.h" /* Support routines for jpegtran */
+#include "jversion.h" /* for version message */
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+
+/*
+ * Argument-parsing code.
+ * The switch parser is designed to be useful with DOS-style command line
+ * syntax, ie, intermixed switches and file names, where only the switches
+ * to the left of a given file name affect processing of that file.
+ * The main program in this file doesn't actually use this capability...
+ */
+
+
+static const char * progname; /* program name for error messages */
+static char * outfilename; /* for -outfile switch */
+static JCOPY_OPTION copyoption; /* -copy switch */
+static jpeg_transform_info transformoption; /* image transformation options */
+
+
+LOCAL(void)
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -copy none Copy no extra markers from source file\n");
+ fprintf(stderr, " -copy comments Copy only comment markers (default)\n");
+ fprintf(stderr, " -copy all Copy all extra markers\n");
+#ifdef ENTROPY_OPT_SUPPORTED
+ fprintf(stderr, " -optimize Optimize Huffman table (smaller file, but slow compression)\n");
+#endif
+#ifdef C_PROGRESSIVE_SUPPORTED
+ fprintf(stderr, " -progressive Create progressive JPEG file\n");
+#endif
+#if TRANSFORMS_SUPPORTED
+ fprintf(stderr, "Switches for modifying the image:\n");
+ fprintf(stderr, " -crop WxH+X+Y Crop to a rectangular subarea\n");
+ fprintf(stderr, " -grayscale Reduce to grayscale (omit color data)\n");
+ fprintf(stderr, " -flip [horizontal|vertical] Mirror image (left-right or top-bottom)\n");
+ fprintf(stderr, " -perfect Fail if there is non-transformable edge blocks\n");
+ fprintf(stderr, " -rotate [90|180|270] Rotate image (degrees clockwise)\n");
+ fprintf(stderr, " -transpose Transpose image\n");
+ fprintf(stderr, " -transverse Transverse transpose image\n");
+ fprintf(stderr, " -trim Drop non-transformable edge blocks\n");
+#endif /* TRANSFORMS_SUPPORTED */
+ fprintf(stderr, "Switches for advanced users:\n");
+ fprintf(stderr, " -restart N Set restart interval in rows, or in blocks with B\n");
+ fprintf(stderr, " -maxmemory N Maximum memory to use (in kbytes)\n");
+ fprintf(stderr, " -outfile name Specify name for output file\n");
+ fprintf(stderr, " -verbose or -debug Emit debug output\n");
+ fprintf(stderr, "Switches for wizards:\n");
+#ifdef C_ARITH_CODING_SUPPORTED
+ fprintf(stderr, " -arithmetic Use arithmetic coding\n");
+#endif
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ fprintf(stderr, " -scans file Create multi-scan JPEG per script file\n");
+#endif
+ exit(EXIT_FAILURE);
+}
+
+
+LOCAL(void)
+select_transform (JXFORM_CODE transform)
+/* Silly little routine to detect multiple transform options,
+ * which we can't handle.
+ */
+{
+#if TRANSFORMS_SUPPORTED
+ if (transformoption.transform == JXFORM_NONE ||
+ transformoption.transform == transform) {
+ transformoption.transform = transform;
+ } else {
+ fprintf(stderr, "%s: can only do one image transformation at a time\n",
+ progname);
+ usage();
+ }
+#else
+ fprintf(stderr, "%s: sorry, image transformation was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+}
+
+
+LOCAL(int)
+parse_switches (j_compress_ptr cinfo, int argc, char **argv,
+ int last_file_arg_seen, boolean for_real)
+/* Parse optional switches.
+ * Returns argv[] index of first file-name argument (== argc if none).
+ * Any file names with indexes <= last_file_arg_seen are ignored;
+ * they have presumably been processed in a previous iteration.
+ * (Pass 0 for last_file_arg_seen on the first or only iteration.)
+ * for_real is FALSE on the first (dummy) pass; we may skip any expensive
+ * processing.
+ */
+{
+ int argn;
+ char * arg;
+ boolean simple_progressive;
+ char * scansarg = NULL; /* saves -scans parm if any */
+
+ /* Set up default JPEG parameters. */
+ simple_progressive = FALSE;
+ outfilename = NULL;
+ copyoption = JCOPYOPT_DEFAULT;
+ transformoption.transform = JXFORM_NONE;
+ transformoption.trim = FALSE;
+ transformoption.perfect = FALSE;
+ transformoption.force_grayscale = FALSE;
+ transformoption.crop = FALSE;
+ cinfo->err->trace_level = 0;
+
+ /* Scan command line options, adjust parameters */
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Not a switch, must be a file name argument */
+ if (argn <= last_file_arg_seen) {
+ outfilename = NULL; /* -outfile applies to just one input file */
+ continue; /* ignore this name if previously processed */
+ }
+ break; /* else done parsing switches */
+ }
+ arg++; /* advance past switch marker character */
+
+ if (keymatch(arg, "arithmetic", 1)) {
+ /* Use arithmetic coding. */
+#ifdef C_ARITH_CODING_SUPPORTED
+ cinfo->arith_code = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, arithmetic coding not supported\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "copy", 2)) {
+ /* Select which extra markers to copy. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "none", 1)) {
+ copyoption = JCOPYOPT_NONE;
+ } else if (keymatch(argv[argn], "comments", 1)) {
+ copyoption = JCOPYOPT_COMMENTS;
+ } else if (keymatch(argv[argn], "all", 1)) {
+ copyoption = JCOPYOPT_ALL;
+ } else
+ usage();
+
+ } else if (keymatch(arg, "crop", 2)) {
+ /* Perform lossless cropping. */
+#if TRANSFORMS_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (! jtransform_parse_crop_spec(&transformoption, argv[argn])) {
+ fprintf(stderr, "%s: bogus -crop argument '%s'\n",
+ progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+#else
+ select_transform(JXFORM_NONE); /* force an error */
+#endif
+
+ } else if (keymatch(arg, "debug", 1) || keymatch(arg, "verbose", 1)) {
+ /* Enable debug printouts. */
+ /* On first -d, print version identification */
+ static boolean printed_version = FALSE;
+
+ if (! printed_version) {
+ fprintf(stderr, "Independent JPEG Group's JPEGTRAN, version %s\n%s\n",
+ JVERSION, JCOPYRIGHT);
+ printed_version = TRUE;
+ }
+ cinfo->err->trace_level++;
+
+ } else if (keymatch(arg, "flip", 1)) {
+ /* Mirror left-right or top-bottom. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "horizontal", 1))
+ select_transform(JXFORM_FLIP_H);
+ else if (keymatch(argv[argn], "vertical", 1))
+ select_transform(JXFORM_FLIP_V);
+ else
+ usage();
+
+ } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
+ /* Force to grayscale. */
+#if TRANSFORMS_SUPPORTED
+ transformoption.force_grayscale = TRUE;
+#else
+ select_transform(JXFORM_NONE); /* force an error */
+#endif
+
+ } else if (keymatch(arg, "maxmemory", 3)) {
+ /* Maximum memory in Kb (or Mb with 'm'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (ch == 'm' || ch == 'M')
+ lval *= 1000L;
+ cinfo->mem->max_memory_to_use = lval * 1000L;
+
+ } else if (keymatch(arg, "optimize", 1) || keymatch(arg, "optimise", 1)) {
+ /* Enable entropy parm optimization. */
+#ifdef ENTROPY_OPT_SUPPORTED
+ cinfo->optimize_coding = TRUE;
+#else
+ fprintf(stderr, "%s: sorry, entropy optimization was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "outfile", 4)) {
+ /* Set output file name. */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ outfilename = argv[argn]; /* save it away for later use */
+
+ } else if (keymatch(arg, "perfect", 2)) {
+ /* Fail if there is any partial edge MCUs that the transform can't
+ * handle. */
+ transformoption.perfect = TRUE;
+
+ } else if (keymatch(arg, "progressive", 2)) {
+ /* Select simple progressive mode. */
+#ifdef C_PROGRESSIVE_SUPPORTED
+ simple_progressive = TRUE;
+ /* We must postpone execution until num_components is known. */
+#else
+ fprintf(stderr, "%s: sorry, progressive output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "restart", 1)) {
+ /* Restart interval in MCU rows (or in MCUs with 'b'). */
+ long lval;
+ char ch = 'x';
+
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (sscanf(argv[argn], "%ld%c", &lval, &ch) < 1)
+ usage();
+ if (lval < 0 || lval > 65535L)
+ usage();
+ if (ch == 'b' || ch == 'B') {
+ cinfo->restart_interval = (unsigned int) lval;
+ cinfo->restart_in_rows = 0; /* else prior '-restart n' overrides me */
+ } else {
+ cinfo->restart_in_rows = (int) lval;
+ /* restart_interval will be computed during startup */
+ }
+
+ } else if (keymatch(arg, "rotate", 2)) {
+ /* Rotate 90, 180, or 270 degrees (measured clockwise). */
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ if (keymatch(argv[argn], "90", 2))
+ select_transform(JXFORM_ROT_90);
+ else if (keymatch(argv[argn], "180", 3))
+ select_transform(JXFORM_ROT_180);
+ else if (keymatch(argv[argn], "270", 3))
+ select_transform(JXFORM_ROT_270);
+ else
+ usage();
+
+ } else if (keymatch(arg, "scans", 1)) {
+ /* Set scan script. */
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (++argn >= argc) /* advance to next argument */
+ usage();
+ scansarg = argv[argn];
+ /* We must postpone reading the file in case -progressive appears. */
+#else
+ fprintf(stderr, "%s: sorry, multi-scan output was not compiled\n",
+ progname);
+ exit(EXIT_FAILURE);
+#endif
+
+ } else if (keymatch(arg, "transpose", 1)) {
+ /* Transpose (across UL-to-LR axis). */
+ select_transform(JXFORM_TRANSPOSE);
+
+ } else if (keymatch(arg, "transverse", 6)) {
+ /* Transverse transpose (across UR-to-LL axis). */
+ select_transform(JXFORM_TRANSVERSE);
+
+ } else if (keymatch(arg, "trim", 3)) {
+ /* Trim off any partial edge MCUs that the transform can't handle. */
+ transformoption.trim = TRUE;
+
+ } else {
+ usage(); /* bogus switch */
+ }
+ }
+
+ /* Post-switch-scanning cleanup */
+
+ if (for_real) {
+
+#ifdef C_PROGRESSIVE_SUPPORTED
+ if (simple_progressive) /* process -progressive; -scans can override */
+ jpeg_simple_progression(cinfo);
+#endif
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+ if (scansarg != NULL) /* process -scans if it was present */
+ if (! read_scan_script(cinfo, scansarg))
+ usage();
+#endif
+ }
+
+ return argn; /* return index of next arg (file name) */
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ struct jpeg_decompress_struct srcinfo;
+ struct jpeg_compress_struct dstinfo;
+ struct jpeg_error_mgr jsrcerr, jdsterr;
+#ifdef PROGRESS_REPORT
+ struct cdjpeg_progress_mgr progress;
+#endif
+ jvirt_barray_ptr * src_coef_arrays;
+ jvirt_barray_ptr * dst_coef_arrays;
+ int file_index;
+ /* We assume all-in-memory processing and can therefore use only a
+ * single file pointer for sequential input and output operation.
+ */
+ FILE * fp;
+
+ /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+ argc = ccommand(&argv);
+#endif
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "jpegtran"; /* in case C library doesn't provide it */
+
+ /* Initialize the JPEG decompression object with default error handling. */
+ srcinfo.err = jpeg_std_error(&jsrcerr);
+ jpeg_create_decompress(&srcinfo);
+ /* Initialize the JPEG compression object with default error handling. */
+ dstinfo.err = jpeg_std_error(&jdsterr);
+ jpeg_create_compress(&dstinfo);
+
+ /* Now safe to enable signal catcher.
+ * Note: we assume only the decompression object will have virtual arrays.
+ */
+#ifdef NEED_SIGNAL_CATCHER
+ enable_signal_catcher((j_common_ptr) &srcinfo);
+#endif
+
+ /* Scan command line to find file names.
+ * It is convenient to use just one switch-parsing routine, but the switch
+ * values read here are mostly ignored; we will rescan the switches after
+ * opening the input file. Also note that most of the switches affect the
+ * destination JPEG object, so we parse into that and then copy over what
+ * needs to affects the source too.
+ */
+
+ file_index = parse_switches(&dstinfo, argc, argv, 0, FALSE);
+ jsrcerr.trace_level = jdsterr.trace_level;
+ srcinfo.mem->max_memory_to_use = dstinfo.mem->max_memory_to_use;
+
+#ifdef TWO_FILE_COMMANDLINE
+ /* Must have either -outfile switch or explicit output file name */
+ if (outfilename == NULL) {
+ if (file_index != argc-2) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ outfilename = argv[file_index+1];
+ } else {
+ if (file_index != argc-1) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ }
+#else
+ /* Unix style: expect zero or one file name */
+ if (file_index < argc-1) {
+ fprintf(stderr, "%s: only one input file\n", progname);
+ usage();
+ }
+#endif /* TWO_FILE_COMMANDLINE */
+
+ /* Open the input file. */
+ if (file_index < argc) {
+ if ((fp = fopen(argv[file_index], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s for reading\n", progname, argv[file_index]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default input file is stdin */
+ fp = read_stdin();
+ }
+
+#ifdef PROGRESS_REPORT
+ start_progress_monitor((j_common_ptr) &dstinfo, &progress);
+#endif
+
+ /* Specify data source for decompression */
+ jpeg_stdio_src(&srcinfo, fp);
+
+ /* Enable saving of extra markers that we want to copy */
+ jcopy_markers_setup(&srcinfo, copyoption);
+
+ /* Read file header */
+ (void) jpeg_read_header(&srcinfo, TRUE);
+
+ /* Any space needed by a transform option must be requested before
+ * jpeg_read_coefficients so that memory allocation will be done right.
+ */
+#if TRANSFORMS_SUPPORTED
+ /* Fails right away if -perfect is given and transformation is not perfect.
+ */
+ if (transformoption.perfect &&
+ !jtransform_perfect_transform(srcinfo.image_width, srcinfo.image_height,
+ srcinfo.max_h_samp_factor * DCTSIZE, srcinfo.max_v_samp_factor * DCTSIZE,
+ transformoption.transform)) {
+ fprintf(stderr, "%s: transformation is not perfect\n", progname);
+ exit(EXIT_FAILURE);
+ }
+ jtransform_request_workspace(&srcinfo, &transformoption);
+#endif
+
+ /* Read source file as DCT coefficients */
+ src_coef_arrays = jpeg_read_coefficients(&srcinfo);
+
+ /* Initialize destination compression parameters from source values */
+ jpeg_copy_critical_parameters(&srcinfo, &dstinfo);
+
+ /* Adjust destination parameters if required by transform options;
+ * also find out which set of coefficient arrays will hold the output.
+ */
+#if TRANSFORMS_SUPPORTED
+ dst_coef_arrays = jtransform_adjust_parameters(&srcinfo, &dstinfo,
+ src_coef_arrays,
+ &transformoption);
+#else
+ dst_coef_arrays = src_coef_arrays;
+#endif
+
+ /* Close input file, if we opened it.
+ * Note: we assume that jpeg_read_coefficients consumed all input
+ * until JPEG_REACHED_EOI, and that jpeg_finish_decompress will
+ * only consume more while (! cinfo->inputctl->eoi_reached).
+ * We cannot call jpeg_finish_decompress here since we still need the
+ * virtual arrays allocated from the source object for processing.
+ */
+ if (fp != stdin)
+ fclose(fp);
+
+ /* Open the output file. */
+ if (outfilename != NULL) {
+ if ((fp = fopen(outfilename, WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s for writing\n", progname, outfilename);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default output file is stdout */
+ fp = write_stdout();
+ }
+
+ /* Adjust default compression parameters by re-parsing the options */
+ file_index = parse_switches(&dstinfo, argc, argv, 0, TRUE);
+
+ /* Specify data destination for compression */
+ jpeg_stdio_dest(&dstinfo, fp);
+
+ /* Start compressor (note no image data is actually written here) */
+ jpeg_write_coefficients(&dstinfo, dst_coef_arrays);
+
+ /* Copy to the output file any extra markers that we want to preserve */
+ jcopy_markers_execute(&srcinfo, &dstinfo, copyoption);
+
+ /* Execute image transformation, if any */
+#if TRANSFORMS_SUPPORTED
+ jtransform_execute_transformation(&srcinfo, &dstinfo,
+ src_coef_arrays,
+ &transformoption);
+#endif
+
+ /* Finish compression and release memory */
+ jpeg_finish_compress(&dstinfo);
+ jpeg_destroy_compress(&dstinfo);
+ (void) jpeg_finish_decompress(&srcinfo);
+ jpeg_destroy_decompress(&srcinfo);
+
+ /* Close output file, if we opened it */
+ if (fp != stdout)
+ fclose(fp);
+
+#ifdef PROGRESS_REPORT
+ end_progress_monitor((j_common_ptr) &dstinfo);
+#endif
+
+ /* All done. */
+ exit(jsrcerr.num_warnings + jdsterr.num_warnings ?EXIT_WARNING:EXIT_SUCCESS);
+ return 0; /* suppress no-return-value warnings */
+}
diff --git a/Source/LibJPEG/jquant1.c b/Source/LibJPEG/jquant1.c
new file mode 100644
index 0000000..b2f96aa
--- /dev/null
+++ b/Source/LibJPEG/jquant1.c
@@ -0,0 +1,856 @@
+/*
+ * jquant1.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 1-pass color quantization (color mapping) routines.
+ * These routines provide mapping to a fixed color map using equally spaced
+ * color values. Optional Floyd-Steinberg or ordered dithering is available.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_1PASS_SUPPORTED
+
+
+/*
+ * The main purpose of 1-pass quantization is to provide a fast, if not very
+ * high quality, colormapped output capability. A 2-pass quantizer usually
+ * gives better visual quality; however, for quantized grayscale output this
+ * quantizer is perfectly adequate. Dithering is highly recommended with this
+ * quantizer, though you can turn it off if you really want to.
+ *
+ * In 1-pass quantization the colormap must be chosen in advance of seeing the
+ * image. We use a map consisting of all combinations of Ncolors[i] color
+ * values for the i'th component. The Ncolors[] values are chosen so that
+ * their product, the total number of colors, is no more than that requested.
+ * (In most cases, the product will be somewhat less.)
+ *
+ * Since the colormap is orthogonal, the representative value for each color
+ * component can be determined without considering the other components;
+ * then these indexes can be combined into a colormap index by a standard
+ * N-dimensional-array-subscript calculation. Most of the arithmetic involved
+ * can be precalculated and stored in the lookup table colorindex[].
+ * colorindex[i][j] maps pixel value j in component i to the nearest
+ * representative value (grid plane) for that component; this index is
+ * multiplied by the array stride for component i, so that the
+ * index of the colormap entry closest to a given pixel value is just
+ * sum( colorindex[component-number][pixel-component-value] )
+ * Aside from being fast, this scheme allows for variable spacing between
+ * representative values with no additional lookup cost.
+ *
+ * If gamma correction has been applied in color conversion, it might be wise
+ * to adjust the color grid spacing so that the representative colors are
+ * equidistant in linear space. At this writing, gamma correction is not
+ * implemented by jdcolor, so nothing is done here.
+ */
+
+
+/* Declarations for ordered dithering.
+ *
+ * We use a standard 16x16 ordered dither array. The basic concept of ordered
+ * dithering is described in many references, for instance Dale Schumacher's
+ * chapter II.2 of Graphics Gems II (James Arvo, ed. Academic Press, 1991).
+ * In place of Schumacher's comparisons against a "threshold" value, we add a
+ * "dither" value to the input pixel and then round the result to the nearest
+ * output value. The dither value is equivalent to (0.5 - threshold) times
+ * the distance between output values. For ordered dithering, we assume that
+ * the output colors are equally spaced; if not, results will probably be
+ * worse, since the dither may be too much or too little at a given point.
+ *
+ * The normal calculation would be to form pixel value + dither, range-limit
+ * this to 0..MAXJSAMPLE, and then index into the colorindex table as usual.
+ * We can skip the separate range-limiting step by extending the colorindex
+ * table in both directions.
+ */
+
+#define ODITHER_SIZE 16 /* dimension of dither matrix */
+/* NB: if ODITHER_SIZE is not a power of 2, ODITHER_MASK uses will break */
+#define ODITHER_CELLS (ODITHER_SIZE*ODITHER_SIZE) /* # cells in matrix */
+#define ODITHER_MASK (ODITHER_SIZE-1) /* mask for wrapping around counters */
+
+typedef int ODITHER_MATRIX[ODITHER_SIZE][ODITHER_SIZE];
+typedef int (*ODITHER_MATRIX_PTR)[ODITHER_SIZE];
+
+static const UINT8 base_dither_matrix[ODITHER_SIZE][ODITHER_SIZE] = {
+ /* Bayer's order-4 dither array. Generated by the code given in
+ * Stephen Hawley's article "Ordered Dithering" in Graphics Gems I.
+ * The values in this array must range from 0 to ODITHER_CELLS-1.
+ */
+ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
+ { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
+ { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
+ { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
+ { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
+ { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
+ { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
+ { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
+ { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
+ { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
+ { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
+ { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
+ { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
+ { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
+ { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
+ { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
+};
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array is indexed [component#][position].
+ * We provide (#columns + 2) entries per component; the extra entry at each
+ * end saves us from special-casing the first and last pixels.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+#define MAX_Q_COMPS 4 /* max components I can handle */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Initially allocated colormap is saved here */
+ JSAMPARRAY sv_colormap; /* The color map as a 2-D pixel array */
+ int sv_actual; /* number of entries in use */
+
+ JSAMPARRAY colorindex; /* Precomputed mapping for speed */
+ /* colorindex[i][j] = index of color closest to pixel value j in component i,
+ * premultiplied as described above. Since colormap indexes must fit into
+ * JSAMPLEs, the entries of this array will too.
+ */
+ boolean is_padded; /* is the colorindex padded for odither? */
+
+ int Ncolors[MAX_Q_COMPS]; /* # of values alloced to each component */
+
+ /* Variables for ordered dithering */
+ int row_index; /* cur row's vertical index in dither matrix */
+ ODITHER_MATRIX_PTR odither[MAX_Q_COMPS]; /* one dither array per component */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors[MAX_Q_COMPS]; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Policy-making subroutines for create_colormap and create_colorindex.
+ * These routines determine the colormap to be used. The rest of the module
+ * only assumes that the colormap is orthogonal.
+ *
+ * * select_ncolors decides how to divvy up the available colors
+ * among the components.
+ * * output_value defines the set of representative values for a component.
+ * * largest_input_value defines the mapping from input values to
+ * representative values for a component.
+ * Note that the latter two routines may impose different policies for
+ * different components, though this is not currently done.
+ */
+
+
+LOCAL(int)
+select_ncolors (j_decompress_ptr cinfo, int Ncolors[])
+/* Determine allocation of desired colors to components, */
+/* and fill in Ncolors[] array to indicate choice. */
+/* Return value is total number of colors (product of Ncolors[] values). */
+{
+ int nc = cinfo->out_color_components; /* number of color components */
+ int max_colors = cinfo->desired_number_of_colors;
+ int total_colors, iroot, i, j;
+ boolean changed;
+ long temp;
+ static const int RGB_order[3] = { RGB_GREEN, RGB_RED, RGB_BLUE };
+
+ /* We can allocate at least the nc'th root of max_colors per component. */
+ /* Compute floor(nc'th root of max_colors). */
+ iroot = 1;
+ do {
+ iroot++;
+ temp = iroot; /* set temp = iroot ** nc */
+ for (i = 1; i < nc; i++)
+ temp *= iroot;
+ } while (temp <= (long) max_colors); /* repeat till iroot exceeds root */
+ iroot--; /* now iroot = floor(root) */
+
+ /* Must have at least 2 color values per component */
+ if (iroot < 2)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, (int) temp);
+
+ /* Initialize to iroot color values for each component */
+ total_colors = 1;
+ for (i = 0; i < nc; i++) {
+ Ncolors[i] = iroot;
+ total_colors *= iroot;
+ }
+ /* We may be able to increment the count for one or more components without
+ * exceeding max_colors, though we know not all can be incremented.
+ * Sometimes, the first component can be incremented more than once!
+ * (Example: for 16 colors, we start at 2*2*2, go to 3*2*2, then 4*2*2.)
+ * In RGB colorspace, try to increment G first, then R, then B.
+ */
+ do {
+ changed = FALSE;
+ for (i = 0; i < nc; i++) {
+ j = (cinfo->out_color_space == JCS_RGB ? RGB_order[i] : i);
+ /* calculate new total_colors if Ncolors[j] is incremented */
+ temp = total_colors / Ncolors[j];
+ temp *= Ncolors[j]+1; /* done in long arith to avoid oflo */
+ if (temp > (long) max_colors)
+ break; /* won't fit, done with this pass */
+ Ncolors[j]++; /* OK, apply the increment */
+ total_colors = (int) temp;
+ changed = TRUE;
+ }
+ } while (changed);
+
+ return total_colors;
+}
+
+
+LOCAL(int)
+output_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return j'th output value, where j will range from 0 to maxj */
+/* The output values must fall in 0..MAXJSAMPLE in increasing order */
+{
+ /* We always provide values 0 and MAXJSAMPLE for each component;
+ * any additional values are equally spaced between these limits.
+ * (Forcing the upper and lower values to the limits ensures that
+ * dithering can't produce a color outside the selected gamut.)
+ */
+ return (int) (((INT32) j * MAXJSAMPLE + maxj/2) / maxj);
+}
+
+
+LOCAL(int)
+largest_input_value (j_decompress_ptr cinfo, int ci, int j, int maxj)
+/* Return largest input value that should map to j'th output value */
+/* Must have largest(j=0) >= 0, and largest(j=maxj) >= MAXJSAMPLE */
+{
+ /* Breakpoints are halfway between values returned by output_value */
+ return (int) (((INT32) (2*j + 1) * MAXJSAMPLE + maxj) / (2*maxj));
+}
+
+
+/*
+ * Create the colormap.
+ */
+
+LOCAL(void)
+create_colormap (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colormap; /* Created colormap */
+ int total_colors; /* Number of distinct output colors */
+ int i,j,k, nci, blksize, blkdist, ptr, val;
+
+ /* Select number of colors for each component */
+ total_colors = select_ncolors(cinfo, cquantize->Ncolors);
+
+ /* Report selected color counts */
+ if (cinfo->out_color_components == 3)
+ TRACEMS4(cinfo, 1, JTRC_QUANT_3_NCOLORS,
+ total_colors, cquantize->Ncolors[0],
+ cquantize->Ncolors[1], cquantize->Ncolors[2]);
+ else
+ TRACEMS1(cinfo, 1, JTRC_QUANT_NCOLORS, total_colors);
+
+ /* Allocate and fill in the colormap. */
+ /* The colors are ordered in the map in standard row-major order, */
+ /* i.e. rightmost (highest-indexed) color changes most rapidly. */
+
+ colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) total_colors, (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ /* blkdist is distance between groups of identical entries for a component */
+ blkdist = total_colors;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colormap entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blkdist / nci;
+ for (j = 0; j < nci; j++) {
+ /* Compute j'th output value (out of nci) for component */
+ val = output_value(cinfo, i, j, nci-1);
+ /* Fill in all colormap entries that have this value of this component */
+ for (ptr = j * blksize; ptr < total_colors; ptr += blkdist) {
+ /* fill in blksize entries beginning at ptr */
+ for (k = 0; k < blksize; k++)
+ colormap[i][ptr+k] = (JSAMPLE) val;
+ }
+ }
+ blkdist = blksize; /* blksize of this color is blkdist of next */
+ }
+
+ /* Save the colormap in private storage,
+ * where it will survive color quantization mode changes.
+ */
+ cquantize->sv_colormap = colormap;
+ cquantize->sv_actual = total_colors;
+}
+
+
+/*
+ * Create the color index table.
+ */
+
+LOCAL(void)
+create_colorindex (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPROW indexptr;
+ int i,j,k, nci, blksize, val, pad;
+
+ /* For ordered dither, we pad the color index tables by MAXJSAMPLE in
+ * each direction (input index values can be -MAXJSAMPLE .. 2*MAXJSAMPLE).
+ * This is not necessary in the other dithering modes. However, we
+ * flag whether it was done in case user changes dithering mode.
+ */
+ if (cinfo->dither_mode == JDITHER_ORDERED) {
+ pad = MAXJSAMPLE*2;
+ cquantize->is_padded = TRUE;
+ } else {
+ pad = 0;
+ cquantize->is_padded = FALSE;
+ }
+
+ cquantize->colorindex = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (MAXJSAMPLE+1 + pad),
+ (JDIMENSION) cinfo->out_color_components);
+
+ /* blksize is number of adjacent repeated entries for a component */
+ blksize = cquantize->sv_actual;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ /* fill in colorindex entries for i'th color component */
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ blksize = blksize / nci;
+
+ /* adjust colorindex pointers to provide padding at negative indexes. */
+ if (pad)
+ cquantize->colorindex[i] += MAXJSAMPLE;
+
+ /* in loop, val = index of current output value, */
+ /* and k = largest j that maps to current val */
+ indexptr = cquantize->colorindex[i];
+ val = 0;
+ k = largest_input_value(cinfo, i, 0, nci-1);
+ for (j = 0; j <= MAXJSAMPLE; j++) {
+ while (j > k) /* advance val if past boundary */
+ k = largest_input_value(cinfo, i, ++val, nci-1);
+ /* premultiply so that no multiplication needed in main processing */
+ indexptr[j] = (JSAMPLE) (val * blksize);
+ }
+ /* Pad at both ends if necessary */
+ if (pad)
+ for (j = 1; j <= MAXJSAMPLE; j++) {
+ indexptr[-j] = indexptr[0];
+ indexptr[MAXJSAMPLE+j] = indexptr[MAXJSAMPLE];
+ }
+ }
+}
+
+
+/*
+ * Create an ordered-dither array for a component having ncolors
+ * distinct output values.
+ */
+
+LOCAL(ODITHER_MATRIX_PTR)
+make_odither_array (j_decompress_ptr cinfo, int ncolors)
+{
+ ODITHER_MATRIX_PTR odither;
+ int j,k;
+ INT32 num,den;
+
+ odither = (ODITHER_MATRIX_PTR)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ODITHER_MATRIX));
+ /* The inter-value distance for this color is MAXJSAMPLE/(ncolors-1).
+ * Hence the dither value for the matrix cell with fill order f
+ * (f=0..N-1) should be (N-1-2*f)/(2*N) * MAXJSAMPLE/(ncolors-1).
+ * On 16-bit-int machine, be careful to avoid overflow.
+ */
+ den = 2 * ODITHER_CELLS * ((INT32) (ncolors - 1));
+ for (j = 0; j < ODITHER_SIZE; j++) {
+ for (k = 0; k < ODITHER_SIZE; k++) {
+ num = ((INT32) (ODITHER_CELLS-1 - 2*((int)base_dither_matrix[j][k])))
+ * MAXJSAMPLE;
+ /* Ensure round towards zero despite C's lack of consistency
+ * about rounding negative values in integer division...
+ */
+ odither[j][k] = (int) (num<0 ? -((-num)/den) : num/den);
+ }
+ }
+ return odither;
+}
+
+
+/*
+ * Create the ordered-dither tables.
+ * Components having the same number of representative colors may
+ * share a dither table.
+ */
+
+LOCAL(void)
+create_odither_tables (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ ODITHER_MATRIX_PTR odither;
+ int i, j, nci;
+
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ nci = cquantize->Ncolors[i]; /* # of distinct values for this color */
+ odither = NULL; /* search for matching prior component */
+ for (j = 0; j < i; j++) {
+ if (nci == cquantize->Ncolors[j]) {
+ odither = cquantize->odither[j];
+ break;
+ }
+ }
+ if (odither == NULL) /* need a new table? */
+ odither = make_odither_array(cinfo, nci);
+ cquantize->odither[i] = odither;
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+color_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ JSAMPARRAY colorindex = cquantize->colorindex;
+ register int pixcode, ci;
+ register JSAMPROW ptrin, ptrout;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ register int nc = cinfo->out_color_components;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = 0;
+ for (ci = 0; ci < nc; ci++) {
+ pixcode += GETJSAMPLE(colorindex[ci][GETJSAMPLE(*ptrin++)]);
+ }
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+color_quantize3 (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW ptrin, ptrout;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptrin = input_buf[row];
+ ptrout = output_buf[row];
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*ptrin++)]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*ptrin++)]);
+ *ptrout++ = (JSAMPLE) pixcode;
+ }
+ }
+}
+
+
+METHODDEF(void)
+quantize_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ int * dither; /* points to active row of dither matrix */
+ int row_index, col_index; /* current indexes into dither matrix */
+ int nc = cinfo->out_color_components;
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ row_index = cquantize->row_index;
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ colorindex_ci = cquantize->colorindex[ci];
+ dither = cquantize->odither[ci][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ /* Form pixel value + dither, range-limit to 0..MAXJSAMPLE,
+ * select output value, accumulate into output code for this pixel.
+ * Range-limiting need not be done explicitly, as we have extended
+ * the colorindex table to produce the right answers for out-of-range
+ * inputs. The maximum dither is +- MAXJSAMPLE; this sets the
+ * required amount of padding.
+ */
+ *output_ptr += colorindex_ci[GETJSAMPLE(*input_ptr)+dither[col_index]];
+ input_ptr += nc;
+ output_ptr++;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ }
+ /* Advance row index for next row */
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize3_ord_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* Fast path for out_color_components==3, with ordered dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register int pixcode;
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex0 = cquantize->colorindex[0];
+ JSAMPROW colorindex1 = cquantize->colorindex[1];
+ JSAMPROW colorindex2 = cquantize->colorindex[2];
+ int * dither0; /* points to active row of dither matrix */
+ int * dither1;
+ int * dither2;
+ int row_index, col_index; /* current indexes into dither matrix */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ row_index = cquantize->row_index;
+ input_ptr = input_buf[row];
+ output_ptr = output_buf[row];
+ dither0 = cquantize->odither[0][row_index];
+ dither1 = cquantize->odither[1][row_index];
+ dither2 = cquantize->odither[2][row_index];
+ col_index = 0;
+
+ for (col = width; col > 0; col--) {
+ pixcode = GETJSAMPLE(colorindex0[GETJSAMPLE(*input_ptr++) +
+ dither0[col_index]]);
+ pixcode += GETJSAMPLE(colorindex1[GETJSAMPLE(*input_ptr++) +
+ dither1[col_index]]);
+ pixcode += GETJSAMPLE(colorindex2[GETJSAMPLE(*input_ptr++) +
+ dither2[col_index]]);
+ *output_ptr++ = (JSAMPLE) pixcode;
+ col_index = (col_index + 1) & ODITHER_MASK;
+ }
+ row_index = (row_index + 1) & ODITHER_MASK;
+ cquantize->row_index = row_index;
+ }
+}
+
+
+METHODDEF(void)
+quantize_fs_dither (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+/* General case, with Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register LOCFSERROR cur; /* current error or pixel value */
+ LOCFSERROR belowerr; /* error for pixel below cur */
+ LOCFSERROR bpreverr; /* error for below/prev col */
+ LOCFSERROR bnexterr; /* error for below/next col */
+ LOCFSERROR delta;
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ register JSAMPROW input_ptr;
+ register JSAMPROW output_ptr;
+ JSAMPROW colorindex_ci;
+ JSAMPROW colormap_ci;
+ int pixcode;
+ int nc = cinfo->out_color_components;
+ int dir; /* 1 for left-to-right, -1 for right-to-left */
+ int dirnc; /* dir * nc */
+ int ci;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ /* Initialize output values to 0 so can process components separately */
+ jzero_far((void FAR *) output_buf[row],
+ (size_t) (width * SIZEOF(JSAMPLE)));
+ for (ci = 0; ci < nc; ci++) {
+ input_ptr = input_buf[row] + ci;
+ output_ptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ input_ptr += (width-1) * nc; /* so point to rightmost pixel */
+ output_ptr += width-1;
+ dir = -1;
+ dirnc = -nc;
+ errorptr = cquantize->fserrors[ci] + (width+1); /* => entry after last column */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dirnc = nc;
+ errorptr = cquantize->fserrors[ci]; /* => entry before first column */
+ }
+ colorindex_ci = cquantize->colorindex[ci];
+ colormap_ci = cquantize->sv_colormap[ci];
+ /* Preset error values: no error propagated to first pixel from left */
+ cur = 0;
+ /* and no error propagated to row below yet */
+ belowerr = bpreverr = 0;
+
+ for (col = width; col > 0; col--) {
+ /* cur holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur = RIGHT_SHIFT(cur + errorptr[dir] + 8, 4);
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE; this sets the required size
+ * of the range_limit array.
+ */
+ cur += GETJSAMPLE(*input_ptr);
+ cur = GETJSAMPLE(range_limit[cur]);
+ /* Select output value, accumulate into output code for this pixel */
+ pixcode = GETJSAMPLE(colorindex_ci[cur]);
+ *output_ptr += (JSAMPLE) pixcode;
+ /* Compute actual representation error at this pixel */
+ /* Note: we can do this even though we don't have the final */
+ /* pixel code, because the colormap is orthogonal. */
+ cur -= GETJSAMPLE(colormap_ci[pixcode]);
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ bnexterr = cur;
+ delta = cur * 2;
+ cur += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr + cur);
+ cur += delta; /* form error * 5 */
+ bpreverr = belowerr + cur;
+ belowerr = bnexterr;
+ cur += delta; /* form error * 7 */
+ /* At this point cur contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ input_ptr += dirnc; /* advance input ptr to next column */
+ output_ptr += dir; /* advance output ptr to next column */
+ errorptr += dir; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error value into the
+ * final fserrors[] entry. Note we need not unload belowerr because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr; /* unload prev err into array */
+ }
+ cquantize->on_odd_row = (cquantize->on_odd_row ? FALSE : TRUE);
+ }
+}
+
+
+/*
+ * Allocate workspace for Floyd-Steinberg errors.
+ */
+
+LOCAL(void)
+alloc_fs_workspace (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++) {
+ cquantize->fserrors[i] = (FSERRPTR)
+ (*cinfo->mem->alloc_large)((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ }
+}
+
+
+/*
+ * Initialize for one-pass color quantization.
+ */
+
+METHODDEF(void)
+start_pass_1_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ size_t arraysize;
+ int i;
+
+ /* Install my colormap. */
+ cinfo->colormap = cquantize->sv_colormap;
+ cinfo->actual_number_of_colors = cquantize->sv_actual;
+
+ /* Initialize for desired dithering mode. */
+ switch (cinfo->dither_mode) {
+ case JDITHER_NONE:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = color_quantize3;
+ else
+ cquantize->pub.color_quantize = color_quantize;
+ break;
+ case JDITHER_ORDERED:
+ if (cinfo->out_color_components == 3)
+ cquantize->pub.color_quantize = quantize3_ord_dither;
+ else
+ cquantize->pub.color_quantize = quantize_ord_dither;
+ cquantize->row_index = 0; /* initialize state for ordered dither */
+ /* If user changed to ordered dither from another mode,
+ * we must recreate the color index table with padding.
+ * This will cost extra space, but probably isn't very likely.
+ */
+ if (! cquantize->is_padded)
+ create_colorindex(cinfo);
+ /* Create ordered-dither tables if we didn't already. */
+ if (cquantize->odither[0] == NULL)
+ create_odither_tables(cinfo);
+ break;
+ case JDITHER_FS:
+ cquantize->pub.color_quantize = quantize_fs_dither;
+ cquantize->on_odd_row = FALSE; /* initialize state for F-S dither */
+ /* Allocate Floyd-Steinberg workspace if didn't already. */
+ if (cquantize->fserrors[0] == NULL)
+ alloc_fs_workspace(cinfo);
+ /* Initialize the propagated errors to zero. */
+ arraysize = (size_t) ((cinfo->output_width + 2) * SIZEOF(FSERROR));
+ for (i = 0; i < cinfo->out_color_components; i++)
+ jzero_far((void FAR *) cquantize->fserrors[i], arraysize);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_NOT_COMPILED);
+ break;
+ }
+}
+
+
+/*
+ * Finish up at the end of the pass.
+ */
+
+METHODDEF(void)
+finish_pass_1_quant (j_decompress_ptr cinfo)
+{
+ /* no work in 1-pass case */
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ * Shouldn't get to this module!
+ */
+
+METHODDEF(void)
+new_color_map_1_quant (j_decompress_ptr cinfo)
+{
+ ERREXIT(cinfo, JERR_MODE_CHANGE);
+}
+
+
+/*
+ * Module initialization routine for 1-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_1pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_1_quant;
+ cquantize->pub.finish_pass = finish_pass_1_quant;
+ cquantize->pub.new_color_map = new_color_map_1_quant;
+ cquantize->fserrors[0] = NULL; /* Flag FS workspace not allocated */
+ cquantize->odither[0] = NULL; /* Also flag odither arrays not allocated */
+
+ /* Make sure my internal arrays won't overflow */
+ if (cinfo->out_color_components > MAX_Q_COMPS)
+ ERREXIT1(cinfo, JERR_QUANT_COMPONENTS, MAX_Q_COMPS);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (cinfo->desired_number_of_colors > (MAXJSAMPLE+1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXJSAMPLE+1);
+
+ /* Create the colormap and color index table. */
+ create_colormap(cinfo);
+ create_colorindex(cinfo);
+
+ /* Allocate Floyd-Steinberg workspace now if requested.
+ * We do this now since it is FAR storage and may affect the memory
+ * manager's space calculations. If the user changes to FS dither
+ * mode in a later pass, we will allocate the space then, and will
+ * possibly overrun the max_memory_to_use setting.
+ */
+ if (cinfo->dither_mode == JDITHER_FS)
+ alloc_fs_workspace(cinfo);
+}
+
+#endif /* QUANT_1PASS_SUPPORTED */
diff --git a/Source/LibJPEG/jquant2.c b/Source/LibJPEG/jquant2.c
new file mode 100644
index 0000000..af601e3
--- /dev/null
+++ b/Source/LibJPEG/jquant2.c
@@ -0,0 +1,1310 @@
+/*
+ * jquant2.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains 2-pass color quantization (color mapping) routines.
+ * These routines provide selection of a custom color map for an image,
+ * followed by mapping of the image to that color map, with optional
+ * Floyd-Steinberg dithering.
+ * It is also possible to use just the second pass to map to an arbitrary
+ * externally-given color map.
+ *
+ * Note: ordered dithering is not supported, since there isn't any fast
+ * way to compute intercolor distances; it's unclear that ordered dither's
+ * fundamental assumptions even hold with an irregularly spaced color map.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
+/*
+ * This module implements the well-known Heckbert paradigm for color
+ * quantization. Most of the ideas used here can be traced back to
+ * Heckbert's seminal paper
+ * Heckbert, Paul. "Color Image Quantization for Frame Buffer Display",
+ * Proc. SIGGRAPH '82, Computer Graphics v.16 #3 (July 1982), pp 297-304.
+ *
+ * In the first pass over the image, we accumulate a histogram showing the
+ * usage count of each possible color. To keep the histogram to a reasonable
+ * size, we reduce the precision of the input; typical practice is to retain
+ * 5 or 6 bits per color, so that 8 or 4 different input values are counted
+ * in the same histogram cell.
+ *
+ * Next, the color-selection step begins with a box representing the whole
+ * color space, and repeatedly splits the "largest" remaining box until we
+ * have as many boxes as desired colors. Then the mean color in each
+ * remaining box becomes one of the possible output colors.
+ *
+ * The second pass over the image maps each input pixel to the closest output
+ * color (optionally after applying a Floyd-Steinberg dithering correction).
+ * This mapping is logically trivial, but making it go fast enough requires
+ * considerable care.
+ *
+ * Heckbert-style quantizers vary a good deal in their policies for choosing
+ * the "largest" box and deciding where to cut it. The particular policies
+ * used here have proved out well in experimental comparisons, but better ones
+ * may yet be found.
+ *
+ * In earlier versions of the IJG code, this module quantized in YCbCr color
+ * space, processing the raw upsampled data without a color conversion step.
+ * This allowed the color conversion math to be done only once per colormap
+ * entry, not once per pixel. However, that optimization precluded other
+ * useful optimizations (such as merging color conversion with upsampling)
+ * and it also interfered with desired capabilities such as quantizing to an
+ * externally-supplied colormap. We have therefore abandoned that approach.
+ * The present code works in the post-conversion color space, typically RGB.
+ *
+ * To improve the visual quality of the results, we actually work in scaled
+ * RGB space, giving G distances more weight than R, and R in turn more than
+ * B. To do everything in integer math, we must use integer scale factors.
+ * The 2/3/1 scale factors used here correspond loosely to the relative
+ * weights of the colors in the NTSC grayscale equation.
+ * If you want to use this code to quantize a non-RGB color space, you'll
+ * probably need to change these scale factors.
+ */
+
+#define R_SCALE 2 /* scale R distances by this much */
+#define G_SCALE 3 /* scale G distances by this much */
+#define B_SCALE 1 /* and B by this much */
+
+/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
+ * in jmorecfg.h. As the code stands, it will do the right thing for R,G,B
+ * and B,G,R orders. If you define some other weird order in jmorecfg.h,
+ * you'll get compile errors until you extend this logic. In that case
+ * you'll probably want to tweak the histogram sizes too.
+ */
+
+#if RGB_RED == 0
+#define C0_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 0
+#define C0_SCALE B_SCALE
+#endif
+#if RGB_GREEN == 1
+#define C1_SCALE G_SCALE
+#endif
+#if RGB_RED == 2
+#define C2_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 2
+#define C2_SCALE B_SCALE
+#endif
+
+
+/*
+ * First we have the histogram data structure and routines for creating it.
+ *
+ * The number of bits of precision can be adjusted by changing these symbols.
+ * We recommend keeping 6 bits for G and 5 each for R and B.
+ * If you have plenty of memory and cycles, 6 bits all around gives marginally
+ * better results; if you are short of memory, 5 bits all around will save
+ * some space but degrade the results.
+ * To maintain a fully accurate histogram, we'd need to allocate a "long"
+ * (preferably unsigned long) for each cell. In practice this is overkill;
+ * we can get by with 16 bits per cell. Few of the cell counts will overflow,
+ * and clamping those that do overflow to the maximum value will give close-
+ * enough results. This reduces the recommended histogram size from 256Kb
+ * to 128Kb, which is a useful savings on PC-class machines.
+ * (In the second pass the histogram space is re-used for pixel mapping data;
+ * in that capacity, each cell must be able to store zero to the number of
+ * desired colors. 16 bits/cell is plenty for that too.)
+ * Since the JPEG code is intended to run in small memory model on 80x86
+ * machines, we can't just allocate the histogram in one chunk. Instead
+ * of a true 3-D array, we use a row of pointers to 2-D arrays. Each
+ * pointer corresponds to a C0 value (typically 2^5 = 32 pointers) and
+ * each 2-D array has 2^6*2^5 = 2048 or 2^6*2^6 = 4096 entries. Note that
+ * on 80x86 machines, the pointer row is in near memory but the actual
+ * arrays are in far memory (same arrangement as we use for image arrays).
+ */
+
+#define MAXNUMCOLORS (MAXJSAMPLE+1) /* maximum size of colormap */
+
+/* These will do the right thing for either R,G,B or B,G,R color order,
+ * but you may not like the results for other color orders.
+ */
+#define HIST_C0_BITS 5 /* bits of precision in R/B histogram */
+#define HIST_C1_BITS 6 /* bits of precision in G histogram */
+#define HIST_C2_BITS 5 /* bits of precision in B/R histogram */
+
+/* Number of elements along histogram axes. */
+#define HIST_C0_ELEMS (1<<HIST_C0_BITS)
+#define HIST_C1_ELEMS (1<<HIST_C1_BITS)
+#define HIST_C2_ELEMS (1<<HIST_C2_BITS)
+
+/* These are the amounts to shift an input value to get a histogram index. */
+#define C0_SHIFT (BITS_IN_JSAMPLE-HIST_C0_BITS)
+#define C1_SHIFT (BITS_IN_JSAMPLE-HIST_C1_BITS)
+#define C2_SHIFT (BITS_IN_JSAMPLE-HIST_C2_BITS)
+
+
+typedef UINT16 histcell; /* histogram cell; prefer an unsigned type */
+
+typedef histcell FAR * histptr; /* for pointers to histogram cells */
+
+typedef histcell hist1d[HIST_C2_ELEMS]; /* typedefs for the array */
+typedef hist1d FAR * hist2d; /* type for the 2nd-level pointers */
+typedef hist2d * hist3d; /* type for top-level pointer */
+
+
+/* Declarations for Floyd-Steinberg dithering.
+ *
+ * Errors are accumulated into the array fserrors[], at a resolution of
+ * 1/16th of a pixel count. The error at a given pixel is propagated
+ * to its not-yet-processed neighbors using the standard F-S fractions,
+ * ... (here) 7/16
+ * 3/16 5/16 1/16
+ * We work left-to-right on even rows, right-to-left on odd rows.
+ *
+ * We can get away with a single array (holding one row's worth of errors)
+ * by using it to store the current row's errors at pixel columns not yet
+ * processed, but the next row's errors at columns already processed. We
+ * need only a few extra variables to hold the errors immediately around the
+ * current column. (If we are lucky, those variables are in registers, but
+ * even if not, they're probably cheaper to access than array elements are.)
+ *
+ * The fserrors[] array has (#columns + 2) entries; the extra entry at
+ * each end saves us from special-casing the first and last pixels.
+ * Each entry is three values long, one value for each color component.
+ *
+ * Note: on a wide image, we might not have enough room in a PC's near data
+ * segment to hold the error array; so it is allocated with alloc_large.
+ */
+
+#if BITS_IN_JSAMPLE == 8
+typedef INT16 FSERROR; /* 16 bits should be enough */
+typedef int LOCFSERROR; /* use 'int' for calculation temps */
+#else
+typedef INT32 FSERROR; /* may need more than 16 bits */
+typedef INT32 LOCFSERROR; /* be sure calculation temps are big enough */
+#endif
+
+typedef FSERROR FAR *FSERRPTR; /* pointer to error array (in FAR storage!) */
+
+
+/* Private subobject */
+
+typedef struct {
+ struct jpeg_color_quantizer pub; /* public fields */
+
+ /* Space for the eventually created colormap is stashed here */
+ JSAMPARRAY sv_colormap; /* colormap allocated at init time */
+ int desired; /* desired # of colors = size of colormap */
+
+ /* Variables for accumulating image statistics */
+ hist3d histogram; /* pointer to the histogram */
+
+ boolean needs_zeroed; /* TRUE if next pass must zero histogram */
+
+ /* Variables for Floyd-Steinberg dithering */
+ FSERRPTR fserrors; /* accumulated errors */
+ boolean on_odd_row; /* flag to remember which row we are on */
+ int * error_limiter; /* table for clamping the applied error */
+} my_cquantizer;
+
+typedef my_cquantizer * my_cquantize_ptr;
+
+
+/*
+ * Prescan some rows of pixels.
+ * In this module the prescan simply updates the histogram, which has been
+ * initialized to zeroes by start_pass.
+ * An output_buf parameter is required by the method signature, but no data
+ * is actually output (in fact the buffer controller is probably passing a
+ * NULL pointer).
+ */
+
+METHODDEF(void)
+prescan_quantize (j_decompress_ptr cinfo, JSAMPARRAY input_buf,
+ JSAMPARRAY output_buf, int num_rows)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ register JSAMPROW ptr;
+ register histptr histp;
+ register hist3d histogram = cquantize->histogram;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ ptr = input_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the histogram */
+ histp = & histogram[GETJSAMPLE(ptr[0]) >> C0_SHIFT]
+ [GETJSAMPLE(ptr[1]) >> C1_SHIFT]
+ [GETJSAMPLE(ptr[2]) >> C2_SHIFT];
+ /* increment, check for overflow and undo increment if so. */
+ if (++(*histp) <= 0)
+ (*histp)--;
+ ptr += 3;
+ }
+ }
+}
+
+
+/*
+ * Next we have the really interesting routines: selection of a colormap
+ * given the completed histogram.
+ * These routines work with a list of "boxes", each representing a rectangular
+ * subset of the input color space (to histogram precision).
+ */
+
+typedef struct {
+ /* The bounds of the box (inclusive); expressed as histogram indexes */
+ int c0min, c0max;
+ int c1min, c1max;
+ int c2min, c2max;
+ /* The volume (actually 2-norm) of the box */
+ INT32 volume;
+ /* The number of nonzero histogram cells within this box */
+ long colorcount;
+} box;
+
+typedef box * boxptr;
+
+
+LOCAL(boxptr)
+find_biggest_color_pop (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest color population */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register long maxc = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->colorcount > maxc && boxp->volume > 0) {
+ which = boxp;
+ maxc = boxp->colorcount;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(boxptr)
+find_biggest_volume (boxptr boxlist, int numboxes)
+/* Find the splittable box with the largest (scaled) volume */
+/* Returns NULL if no splittable boxes remain */
+{
+ register boxptr boxp;
+ register int i;
+ register INT32 maxv = 0;
+ boxptr which = NULL;
+
+ for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) {
+ if (boxp->volume > maxv) {
+ which = boxp;
+ maxv = boxp->volume;
+ }
+ }
+ return which;
+}
+
+
+LOCAL(void)
+update_box (j_decompress_ptr cinfo, boxptr boxp)
+/* Shrink the min/max bounds of a box to enclose only nonzero elements, */
+/* and recompute its volume and population */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ INT32 dist0,dist1,dist2;
+ long ccount;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ if (c0max > c0min)
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0min = c0min = c0;
+ goto have_c0min;
+ }
+ }
+ have_c0min:
+ if (c0max > c0min)
+ for (c0 = c0max; c0 >= c0min; c0--)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c0max = c0max = c0;
+ goto have_c0max;
+ }
+ }
+ have_c0max:
+ if (c1max > c1min)
+ for (c1 = c1min; c1 <= c1max; c1++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1min = c1min = c1;
+ goto have_c1min;
+ }
+ }
+ have_c1min:
+ if (c1max > c1min)
+ for (c1 = c1max; c1 >= c1min; c1--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++)
+ if (*histp++ != 0) {
+ boxp->c1max = c1max = c1;
+ goto have_c1max;
+ }
+ }
+ have_c1max:
+ if (c2max > c2min)
+ for (c2 = c2min; c2 <= c2max; c2++)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2min = c2min = c2;
+ goto have_c2min;
+ }
+ }
+ have_c2min:
+ if (c2max > c2min)
+ for (c2 = c2max; c2 >= c2min; c2--)
+ for (c0 = c0min; c0 <= c0max; c0++) {
+ histp = & histogram[c0][c1min][c2];
+ for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS)
+ if (*histp != 0) {
+ boxp->c2max = c2max = c2;
+ goto have_c2max;
+ }
+ }
+ have_c2max:
+
+ /* Update box volume.
+ * We use 2-norm rather than real volume here; this biases the method
+ * against making long narrow boxes, and it has the side benefit that
+ * a box is splittable iff norm > 0.
+ * Since the differences are expressed in histogram-cell units,
+ * we have to shift back to JSAMPLE units to get consistent distances;
+ * after which, we scale according to the selected distance scale factors.
+ */
+ dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE;
+ dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE;
+ dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE;
+ boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2;
+
+ /* Now scan remaining volume of box and compute population */
+ ccount = 0;
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++, histp++)
+ if (*histp != 0) {
+ ccount++;
+ }
+ }
+ boxp->colorcount = ccount;
+}
+
+
+LOCAL(int)
+median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
+ int desired_colors)
+/* Repeatedly select and split the largest box until we have enough boxes */
+{
+ int n,lb;
+ int c0,c1,c2,cmax;
+ register boxptr b1,b2;
+
+ while (numboxes < desired_colors) {
+ /* Select box to split.
+ * Current algorithm: by population for first half, then by volume.
+ */
+ if (numboxes*2 <= desired_colors) {
+ b1 = find_biggest_color_pop(boxlist, numboxes);
+ } else {
+ b1 = find_biggest_volume(boxlist, numboxes);
+ }
+ if (b1 == NULL) /* no splittable boxes left! */
+ break;
+ b2 = &boxlist[numboxes]; /* where new box will go */
+ /* Copy the color bounds to the new box. */
+ b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
+ b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
+ /* Choose which axis to split the box on.
+ * Current algorithm: longest scaled axis.
+ * See notes in update_box about scaling distances.
+ */
+ c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
+ c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
+ c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
+ /* We want to break any ties in favor of green, then red, blue last.
+ * This code does the right thing for R,G,B or B,G,R color orders only.
+ */
+#if RGB_RED == 0
+ cmax = c1; n = 1;
+ if (c0 > cmax) { cmax = c0; n = 0; }
+ if (c2 > cmax) { n = 2; }
+#else
+ cmax = c1; n = 1;
+ if (c2 > cmax) { cmax = c2; n = 2; }
+ if (c0 > cmax) { n = 0; }
+#endif
+ /* Choose split point along selected axis, and update box bounds.
+ * Current algorithm: split at halfway point.
+ * (Since the box has been shrunk to minimum volume,
+ * any split will produce two nonempty subboxes.)
+ * Note that lb value is max for lower box, so must be < old max.
+ */
+ switch (n) {
+ case 0:
+ lb = (b1->c0max + b1->c0min) / 2;
+ b1->c0max = lb;
+ b2->c0min = lb+1;
+ break;
+ case 1:
+ lb = (b1->c1max + b1->c1min) / 2;
+ b1->c1max = lb;
+ b2->c1min = lb+1;
+ break;
+ case 2:
+ lb = (b1->c2max + b1->c2min) / 2;
+ b1->c2max = lb;
+ b2->c2min = lb+1;
+ break;
+ }
+ /* Update stats for boxes */
+ update_box(cinfo, b1);
+ update_box(cinfo, b2);
+ numboxes++;
+ }
+ return numboxes;
+}
+
+
+LOCAL(void)
+compute_color (j_decompress_ptr cinfo, boxptr boxp, int icolor)
+/* Compute representative color for a box, put it in colormap[icolor] */
+{
+ /* Current algorithm: mean weighted by pixels (not colors) */
+ /* Note it is important to get the rounding correct! */
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ histptr histp;
+ int c0,c1,c2;
+ int c0min,c0max,c1min,c1max,c2min,c2max;
+ long count;
+ long total = 0;
+ long c0total = 0;
+ long c1total = 0;
+ long c2total = 0;
+
+ c0min = boxp->c0min; c0max = boxp->c0max;
+ c1min = boxp->c1min; c1max = boxp->c1max;
+ c2min = boxp->c2min; c2max = boxp->c2max;
+
+ for (c0 = c0min; c0 <= c0max; c0++)
+ for (c1 = c1min; c1 <= c1max; c1++) {
+ histp = & histogram[c0][c1][c2min];
+ for (c2 = c2min; c2 <= c2max; c2++) {
+ if ((count = *histp++) != 0) {
+ total += count;
+ c0total += ((c0 << C0_SHIFT) + ((1<<C0_SHIFT)>>1)) * count;
+ c1total += ((c1 << C1_SHIFT) + ((1<<C1_SHIFT)>>1)) * count;
+ c2total += ((c2 << C2_SHIFT) + ((1<<C2_SHIFT)>>1)) * count;
+ }
+ }
+ }
+
+ cinfo->colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total);
+ cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total);
+ cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total);
+}
+
+
+LOCAL(void)
+select_colors (j_decompress_ptr cinfo, int desired_colors)
+/* Master routine for color selection */
+{
+ boxptr boxlist;
+ int numboxes;
+ int i;
+
+ /* Allocate workspace for box list */
+ boxlist = (boxptr) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, desired_colors * SIZEOF(box));
+ /* Initialize one box containing whole space */
+ numboxes = 1;
+ boxlist[0].c0min = 0;
+ boxlist[0].c0max = MAXJSAMPLE >> C0_SHIFT;
+ boxlist[0].c1min = 0;
+ boxlist[0].c1max = MAXJSAMPLE >> C1_SHIFT;
+ boxlist[0].c2min = 0;
+ boxlist[0].c2max = MAXJSAMPLE >> C2_SHIFT;
+ /* Shrink it to actually-used volume and set its statistics */
+ update_box(cinfo, & boxlist[0]);
+ /* Perform median-cut to produce final box list */
+ numboxes = median_cut(cinfo, boxlist, numboxes, desired_colors);
+ /* Compute the representative color for each box, fill colormap */
+ for (i = 0; i < numboxes; i++)
+ compute_color(cinfo, & boxlist[i], i);
+ cinfo->actual_number_of_colors = numboxes;
+ TRACEMS1(cinfo, 1, JTRC_QUANT_SELECTED, numboxes);
+}
+
+
+/*
+ * These routines are concerned with the time-critical task of mapping input
+ * colors to the nearest color in the selected colormap.
+ *
+ * We re-use the histogram space as an "inverse color map", essentially a
+ * cache for the results of nearest-color searches. All colors within a
+ * histogram cell will be mapped to the same colormap entry, namely the one
+ * closest to the cell's center. This may not be quite the closest entry to
+ * the actual input color, but it's almost as good. A zero in the cache
+ * indicates we haven't found the nearest color for that cell yet; the array
+ * is cleared to zeroes before starting the mapping pass. When we find the
+ * nearest color for a cell, its colormap index plus one is recorded in the
+ * cache for future use. The pass2 scanning routines call fill_inverse_cmap
+ * when they need to use an unfilled entry in the cache.
+ *
+ * Our method of efficiently finding nearest colors is based on the "locally
+ * sorted search" idea described by Heckbert and on the incremental distance
+ * calculation described by Spencer W. Thomas in chapter III.1 of Graphics
+ * Gems II (James Arvo, ed. Academic Press, 1991). Thomas points out that
+ * the distances from a given colormap entry to each cell of the histogram can
+ * be computed quickly using an incremental method: the differences between
+ * distances to adjacent cells themselves differ by a constant. This allows a
+ * fairly fast implementation of the "brute force" approach of computing the
+ * distance from every colormap entry to every histogram cell. Unfortunately,
+ * it needs a work array to hold the best-distance-so-far for each histogram
+ * cell (because the inner loop has to be over cells, not colormap entries).
+ * The work array elements have to be INT32s, so the work array would need
+ * 256Kb at our recommended precision. This is not feasible in DOS machines.
+ *
+ * To get around these problems, we apply Thomas' method to compute the
+ * nearest colors for only the cells within a small subbox of the histogram.
+ * The work array need be only as big as the subbox, so the memory usage
+ * problem is solved. Furthermore, we need not fill subboxes that are never
+ * referenced in pass2; many images use only part of the color gamut, so a
+ * fair amount of work is saved. An additional advantage of this
+ * approach is that we can apply Heckbert's locality criterion to quickly
+ * eliminate colormap entries that are far away from the subbox; typically
+ * three-fourths of the colormap entries are rejected by Heckbert's criterion,
+ * and we need not compute their distances to individual cells in the subbox.
+ * The speed of this approach is heavily influenced by the subbox size: too
+ * small means too much overhead, too big loses because Heckbert's criterion
+ * can't eliminate as many colormap entries. Empirically the best subbox
+ * size seems to be about 1/512th of the histogram (1/8th in each direction).
+ *
+ * Thomas' article also describes a refined method which is asymptotically
+ * faster than the brute-force method, but it is also far more complex and
+ * cannot efficiently be applied to small subboxes. It is therefore not
+ * useful for programs intended to be portable to DOS machines. On machines
+ * with plenty of memory, filling the whole histogram in one shot with Thomas'
+ * refined method might be faster than the present code --- but then again,
+ * it might not be any faster, and it's certainly more complicated.
+ */
+
+
+/* log2(histogram cells in update box) for each axis; this can be adjusted */
+#define BOX_C0_LOG (HIST_C0_BITS-3)
+#define BOX_C1_LOG (HIST_C1_BITS-3)
+#define BOX_C2_LOG (HIST_C2_BITS-3)
+
+#define BOX_C0_ELEMS (1<<BOX_C0_LOG) /* # of hist cells in update box */
+#define BOX_C1_ELEMS (1<<BOX_C1_LOG)
+#define BOX_C2_ELEMS (1<<BOX_C2_LOG)
+
+#define BOX_C0_SHIFT (C0_SHIFT + BOX_C0_LOG)
+#define BOX_C1_SHIFT (C1_SHIFT + BOX_C1_LOG)
+#define BOX_C2_SHIFT (C2_SHIFT + BOX_C2_LOG)
+
+
+/*
+ * The next three routines implement inverse colormap filling. They could
+ * all be folded into one big routine, but splitting them up this way saves
+ * some stack space (the mindist[] and bestdist[] arrays need not coexist)
+ * and may allow some compilers to produce better code by registerizing more
+ * inner-loop variables.
+ */
+
+LOCAL(int)
+find_nearby_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ JSAMPLE colorlist[])
+/* Locate the colormap entries close enough to an update box to be candidates
+ * for the nearest entry to some cell(s) in the update box. The update box
+ * is specified by the center coordinates of its first cell. The number of
+ * candidate colormap entries is returned, and their colormap indexes are
+ * placed in colorlist[].
+ * This routine uses Heckbert's "locally sorted search" criterion to select
+ * the colors that need further consideration.
+ */
+{
+ int numcolors = cinfo->actual_number_of_colors;
+ int maxc0, maxc1, maxc2;
+ int centerc0, centerc1, centerc2;
+ int i, x, ncolors;
+ INT32 minmaxdist, min_dist, max_dist, tdist;
+ INT32 mindist[MAXNUMCOLORS]; /* min distance to colormap entry i */
+
+ /* Compute true coordinates of update box's upper corner and center.
+ * Actually we compute the coordinates of the center of the upper-corner
+ * histogram cell, which are the upper bounds of the volume we care about.
+ * Note that since ">>" rounds down, the "center" values may be closer to
+ * min than to max; hence comparisons to them must be "<=", not "<".
+ */
+ maxc0 = minc0 + ((1 << BOX_C0_SHIFT) - (1 << C0_SHIFT));
+ centerc0 = (minc0 + maxc0) >> 1;
+ maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT));
+ centerc1 = (minc1 + maxc1) >> 1;
+ maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT));
+ centerc2 = (minc2 + maxc2) >> 1;
+
+ /* For each color in colormap, find:
+ * 1. its minimum squared-distance to any point in the update box
+ * (zero if color is within update box);
+ * 2. its maximum squared-distance to any point in the update box.
+ * Both of these can be found by considering only the corners of the box.
+ * We save the minimum distance for each color in mindist[];
+ * only the smallest maximum distance is of interest.
+ */
+ minmaxdist = 0x7FFFFFFFL;
+
+ for (i = 0; i < numcolors; i++) {
+ /* We compute the squared-c0-distance term, then add in the other two. */
+ x = GETJSAMPLE(cinfo->colormap[0][i]);
+ if (x < minc0) {
+ tdist = (x - minc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else if (x > maxc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ min_dist = tdist*tdist;
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ min_dist = 0;
+ if (x <= centerc0) {
+ tdist = (x - maxc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ } else {
+ tdist = (x - minc0) * C0_SCALE;
+ max_dist = tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[1][i]);
+ if (x < minc1) {
+ tdist = (x - minc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc1) {
+ tdist = (x - maxc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc1) * C1_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ x = GETJSAMPLE(cinfo->colormap[2][i]);
+ if (x < minc2) {
+ tdist = (x - minc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else if (x > maxc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ min_dist += tdist*tdist;
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ /* within cell range so no contribution to min_dist */
+ if (x <= centerc2) {
+ tdist = (x - maxc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ } else {
+ tdist = (x - minc2) * C2_SCALE;
+ max_dist += tdist*tdist;
+ }
+ }
+
+ mindist[i] = min_dist; /* save away the results */
+ if (max_dist < minmaxdist)
+ minmaxdist = max_dist;
+ }
+
+ /* Now we know that no cell in the update box is more than minmaxdist
+ * away from some colormap entry. Therefore, only colors that are
+ * within minmaxdist of some part of the box need be considered.
+ */
+ ncolors = 0;
+ for (i = 0; i < numcolors; i++) {
+ if (mindist[i] <= minmaxdist)
+ colorlist[ncolors++] = (JSAMPLE) i;
+ }
+ return ncolors;
+}
+
+
+LOCAL(void)
+find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
+ int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
+/* Find the closest colormap entry for each cell in the update box,
+ * given the list of candidate colors prepared by find_nearby_colors.
+ * Return the indexes of the closest entries in the bestcolor[] array.
+ * This routine uses Thomas' incremental distance calculation method to
+ * find the distance from a colormap entry to successive cells in the box.
+ */
+{
+ int ic0, ic1, ic2;
+ int i, icolor;
+ register INT32 * bptr; /* pointer into bestdist[] array */
+ JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ INT32 dist0, dist1; /* initial distance values */
+ register INT32 dist2; /* current distance in inner loop */
+ INT32 xx0, xx1; /* distance increments */
+ register INT32 xx2;
+ INT32 inc0, inc1, inc2; /* initial values for increments */
+ /* This array holds the distance to the nearest-so-far color for each cell */
+ INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Initialize best-distance for each cell of the update box */
+ bptr = bestdist;
+ for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
+ *bptr++ = 0x7FFFFFFFL;
+
+ /* For each color selected by find_nearby_colors,
+ * compute its distance to the center of each cell in the box.
+ * If that's less than best-so-far, update best distance and color number.
+ */
+
+ /* Nominal steps between cell centers ("x" in Thomas article) */
+#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE)
+#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE)
+#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE)
+
+ for (i = 0; i < numcolors; i++) {
+ icolor = GETJSAMPLE(colorlist[i]);
+ /* Compute (square of) distance from minc0/c1/c2 to this color */
+ inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
+ dist0 = inc0*inc0;
+ inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
+ dist0 += inc1*inc1;
+ inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
+ dist0 += inc2*inc2;
+ /* Form the initial difference increments */
+ inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
+ inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
+ inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
+ /* Now loop over all cells in box, updating distance per Thomas method */
+ bptr = bestdist;
+ cptr = bestcolor;
+ xx0 = inc0;
+ for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
+ dist1 = dist0;
+ xx1 = inc1;
+ for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
+ dist2 = dist1;
+ xx2 = inc2;
+ for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
+ if (dist2 < *bptr) {
+ *bptr = dist2;
+ *cptr = (JSAMPLE) icolor;
+ }
+ dist2 += xx2;
+ xx2 += 2 * STEP_C2 * STEP_C2;
+ bptr++;
+ cptr++;
+ }
+ dist1 += xx1;
+ xx1 += 2 * STEP_C1 * STEP_C1;
+ }
+ dist0 += xx0;
+ xx0 += 2 * STEP_C0 * STEP_C0;
+ }
+ }
+}
+
+
+LOCAL(void)
+fill_inverse_cmap (j_decompress_ptr cinfo, int c0, int c1, int c2)
+/* Fill the inverse-colormap entries in the update box that contains */
+/* histogram cell c0/c1/c2. (Only that one cell MUST be filled, but */
+/* we can fill as many others as we wish.) */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int minc0, minc1, minc2; /* lower left corner of update box */
+ int ic0, ic1, ic2;
+ register JSAMPLE * cptr; /* pointer into bestcolor[] array */
+ register histptr cachep; /* pointer into main cache array */
+ /* This array lists the candidate colormap indexes. */
+ JSAMPLE colorlist[MAXNUMCOLORS];
+ int numcolors; /* number of candidate colors */
+ /* This array holds the actually closest colormap index for each cell. */
+ JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];
+
+ /* Convert cell coordinates to update box ID */
+ c0 >>= BOX_C0_LOG;
+ c1 >>= BOX_C1_LOG;
+ c2 >>= BOX_C2_LOG;
+
+ /* Compute true coordinates of update box's origin corner.
+ * Actually we compute the coordinates of the center of the corner
+ * histogram cell, which are the lower bounds of the volume we care about.
+ */
+ minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1);
+ minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1);
+ minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1);
+
+ /* Determine which colormap entries are close enough to be candidates
+ * for the nearest entry to some cell in the update box.
+ */
+ numcolors = find_nearby_colors(cinfo, minc0, minc1, minc2, colorlist);
+
+ /* Determine the actually nearest colors. */
+ find_best_colors(cinfo, minc0, minc1, minc2, numcolors, colorlist,
+ bestcolor);
+
+ /* Save the best color numbers (plus 1) in the main cache array */
+ c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */
+ c1 <<= BOX_C1_LOG;
+ c2 <<= BOX_C2_LOG;
+ cptr = bestcolor;
+ for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) {
+ for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) {
+ cachep = & histogram[c0+ic0][c1+ic1][c2];
+ for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) {
+ *cachep++ = (histcell) (GETJSAMPLE(*cptr++) + 1);
+ }
+ }
+ }
+}
+
+
+/*
+ * Map some rows of pixels to the output colormapped representation.
+ */
+
+METHODDEF(void)
+pass2_no_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs no dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register JSAMPROW inptr, outptr;
+ register histptr cachep;
+ register int c0, c1, c2;
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ for (col = width; col > 0; col--) {
+ /* get pixel value and index into the cache */
+ c0 = GETJSAMPLE(*inptr++) >> C0_SHIFT;
+ c1 = GETJSAMPLE(*inptr++) >> C1_SHIFT;
+ c2 = GETJSAMPLE(*inptr++) >> C2_SHIFT;
+ cachep = & histogram[c0][c1][c2];
+ /* If we have not seen this color before, find nearest colormap entry */
+ /* and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, c0,c1,c2);
+ /* Now emit the colormap index for this cell */
+ *outptr++ = (JSAMPLE) (*cachep - 1);
+ }
+ }
+}
+
+
+METHODDEF(void)
+pass2_fs_dither (j_decompress_ptr cinfo,
+ JSAMPARRAY input_buf, JSAMPARRAY output_buf, int num_rows)
+/* This version performs Floyd-Steinberg dithering */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */
+ LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */
+ LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */
+ register FSERRPTR errorptr; /* => fserrors[] at column before current */
+ JSAMPROW inptr; /* => current input pixel */
+ JSAMPROW outptr; /* => current output pixel */
+ histptr cachep;
+ int dir; /* +1 or -1 depending on direction */
+ int dir3; /* 3*dir, for advancing inptr & errorptr */
+ int row;
+ JDIMENSION col;
+ JDIMENSION width = cinfo->output_width;
+ JSAMPLE *range_limit = cinfo->sample_range_limit;
+ int *error_limit = cquantize->error_limiter;
+ JSAMPROW colormap0 = cinfo->colormap[0];
+ JSAMPROW colormap1 = cinfo->colormap[1];
+ JSAMPROW colormap2 = cinfo->colormap[2];
+ SHIFT_TEMPS
+
+ for (row = 0; row < num_rows; row++) {
+ inptr = input_buf[row];
+ outptr = output_buf[row];
+ if (cquantize->on_odd_row) {
+ /* work right to left in this row */
+ inptr += (width-1) * 3; /* so point to rightmost pixel */
+ outptr += width-1;
+ dir = -1;
+ dir3 = -3;
+ errorptr = cquantize->fserrors + (width+1)*3; /* => entry after last column */
+ cquantize->on_odd_row = FALSE; /* flip for next time */
+ } else {
+ /* work left to right in this row */
+ dir = 1;
+ dir3 = 3;
+ errorptr = cquantize->fserrors; /* => entry before first real column */
+ cquantize->on_odd_row = TRUE; /* flip for next time */
+ }
+ /* Preset error values: no error propagated to first pixel from left */
+ cur0 = cur1 = cur2 = 0;
+ /* and no error propagated to row below yet */
+ belowerr0 = belowerr1 = belowerr2 = 0;
+ bpreverr0 = bpreverr1 = bpreverr2 = 0;
+
+ for (col = width; col > 0; col--) {
+ /* curN holds the error propagated from the previous pixel on the
+ * current line. Add the error propagated from the previous line
+ * to form the complete error correction term for this pixel, and
+ * round the error term (which is expressed * 16) to an integer.
+ * RIGHT_SHIFT rounds towards minus infinity, so adding 8 is correct
+ * for either sign of the error value.
+ * Note: errorptr points to *previous* column's array entry.
+ */
+ cur0 = RIGHT_SHIFT(cur0 + errorptr[dir3+0] + 8, 4);
+ cur1 = RIGHT_SHIFT(cur1 + errorptr[dir3+1] + 8, 4);
+ cur2 = RIGHT_SHIFT(cur2 + errorptr[dir3+2] + 8, 4);
+ /* Limit the error using transfer function set by init_error_limit.
+ * See comments with init_error_limit for rationale.
+ */
+ cur0 = error_limit[cur0];
+ cur1 = error_limit[cur1];
+ cur2 = error_limit[cur2];
+ /* Form pixel value + error, and range-limit to 0..MAXJSAMPLE.
+ * The maximum error is +- MAXJSAMPLE (or less with error limiting);
+ * this sets the required size of the range_limit array.
+ */
+ cur0 += GETJSAMPLE(inptr[0]);
+ cur1 += GETJSAMPLE(inptr[1]);
+ cur2 += GETJSAMPLE(inptr[2]);
+ cur0 = GETJSAMPLE(range_limit[cur0]);
+ cur1 = GETJSAMPLE(range_limit[cur1]);
+ cur2 = GETJSAMPLE(range_limit[cur2]);
+ /* Index into the cache with adjusted pixel value */
+ cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT];
+ /* If we have not seen this color before, find nearest colormap */
+ /* entry and update the cache */
+ if (*cachep == 0)
+ fill_inverse_cmap(cinfo, cur0>>C0_SHIFT,cur1>>C1_SHIFT,cur2>>C2_SHIFT);
+ /* Now emit the colormap index for this cell */
+ { register int pixcode = *cachep - 1;
+ *outptr = (JSAMPLE) pixcode;
+ /* Compute representation error for this pixel */
+ cur0 -= GETJSAMPLE(colormap0[pixcode]);
+ cur1 -= GETJSAMPLE(colormap1[pixcode]);
+ cur2 -= GETJSAMPLE(colormap2[pixcode]);
+ }
+ /* Compute error fractions to be propagated to adjacent pixels.
+ * Add these into the running sums, and simultaneously shift the
+ * next-line error sums left by 1 column.
+ */
+ { register LOCFSERROR bnexterr, delta;
+
+ bnexterr = cur0; /* Process component 0 */
+ delta = cur0 * 2;
+ cur0 += delta; /* form error * 3 */
+ errorptr[0] = (FSERROR) (bpreverr0 + cur0);
+ cur0 += delta; /* form error * 5 */
+ bpreverr0 = belowerr0 + cur0;
+ belowerr0 = bnexterr;
+ cur0 += delta; /* form error * 7 */
+ bnexterr = cur1; /* Process component 1 */
+ delta = cur1 * 2;
+ cur1 += delta; /* form error * 3 */
+ errorptr[1] = (FSERROR) (bpreverr1 + cur1);
+ cur1 += delta; /* form error * 5 */
+ bpreverr1 = belowerr1 + cur1;
+ belowerr1 = bnexterr;
+ cur1 += delta; /* form error * 7 */
+ bnexterr = cur2; /* Process component 2 */
+ delta = cur2 * 2;
+ cur2 += delta; /* form error * 3 */
+ errorptr[2] = (FSERROR) (bpreverr2 + cur2);
+ cur2 += delta; /* form error * 5 */
+ bpreverr2 = belowerr2 + cur2;
+ belowerr2 = bnexterr;
+ cur2 += delta; /* form error * 7 */
+ }
+ /* At this point curN contains the 7/16 error value to be propagated
+ * to the next pixel on the current line, and all the errors for the
+ * next line have been shifted over. We are therefore ready to move on.
+ */
+ inptr += dir3; /* Advance pixel pointers to next column */
+ outptr += dir;
+ errorptr += dir3; /* advance errorptr to current column */
+ }
+ /* Post-loop cleanup: we must unload the final error values into the
+ * final fserrors[] entry. Note we need not unload belowerrN because
+ * it is for the dummy column before or after the actual array.
+ */
+ errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */
+ errorptr[1] = (FSERROR) bpreverr1;
+ errorptr[2] = (FSERROR) bpreverr2;
+ }
+}
+
+
+/*
+ * Initialize the error-limiting transfer function (lookup table).
+ * The raw F-S error computation can potentially compute error values of up to
+ * +- MAXJSAMPLE. But we want the maximum correction applied to a pixel to be
+ * much less, otherwise obviously wrong pixels will be created. (Typical
+ * effects include weird fringes at color-area boundaries, isolated bright
+ * pixels in a dark area, etc.) The standard advice for avoiding this problem
+ * is to ensure that the "corners" of the color cube are allocated as output
+ * colors; then repeated errors in the same direction cannot cause cascading
+ * error buildup. However, that only prevents the error from getting
+ * completely out of hand; Aaron Giles reports that error limiting improves
+ * the results even with corner colors allocated.
+ * A simple clamping of the error values to about +- MAXJSAMPLE/8 works pretty
+ * well, but the smoother transfer function used below is even better. Thanks
+ * to Aaron Giles for this idea.
+ */
+
+LOCAL(void)
+init_error_limit (j_decompress_ptr cinfo)
+/* Allocate and fill in the error_limiter table */
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ int * table;
+ int in, out;
+
+ table = (int *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, (MAXJSAMPLE*2+1) * SIZEOF(int));
+ table += MAXJSAMPLE; /* so can index -MAXJSAMPLE .. +MAXJSAMPLE */
+ cquantize->error_limiter = table;
+
+#define STEPSIZE ((MAXJSAMPLE+1)/16)
+ /* Map errors 1:1 up to +- MAXJSAMPLE/16 */
+ out = 0;
+ for (in = 0; in < STEPSIZE; in++, out++) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Map errors 1:2 up to +- 3*MAXJSAMPLE/16 */
+ for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) {
+ table[in] = out; table[-in] = -out;
+ }
+ /* Clamp the rest to final out value (which is (MAXJSAMPLE+1)/8) */
+ for (; in <= MAXJSAMPLE; in++) {
+ table[in] = out; table[-in] = -out;
+ }
+#undef STEPSIZE
+}
+
+
+/*
+ * Finish up at the end of each pass.
+ */
+
+METHODDEF(void)
+finish_pass1 (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Select the representative colors and fill in cinfo->colormap */
+ cinfo->colormap = cquantize->sv_colormap;
+ select_colors(cinfo, cquantize->desired);
+ /* Force next pass to zero the color index table */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+METHODDEF(void)
+finish_pass2 (j_decompress_ptr cinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * Initialize for each processing pass.
+ */
+
+METHODDEF(void)
+start_pass_2_quant (j_decompress_ptr cinfo, boolean is_pre_scan)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+ hist3d histogram = cquantize->histogram;
+ int i;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ if (is_pre_scan) {
+ /* Set up method pointers */
+ cquantize->pub.color_quantize = prescan_quantize;
+ cquantize->pub.finish_pass = finish_pass1;
+ cquantize->needs_zeroed = TRUE; /* Always zero histogram */
+ } else {
+ /* Set up method pointers */
+ if (cinfo->dither_mode == JDITHER_FS)
+ cquantize->pub.color_quantize = pass2_fs_dither;
+ else
+ cquantize->pub.color_quantize = pass2_no_dither;
+ cquantize->pub.finish_pass = finish_pass2;
+
+ /* Make sure color count is acceptable */
+ i = cinfo->actual_number_of_colors;
+ if (i < 1)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 1);
+ if (i > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+
+ if (cinfo->dither_mode == JDITHER_FS) {
+ size_t arraysize = (size_t) ((cinfo->output_width + 2) *
+ (3 * SIZEOF(FSERROR)));
+ /* Allocate Floyd-Steinberg workspace if we didn't already. */
+ if (cquantize->fserrors == NULL)
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, arraysize);
+ /* Initialize the propagated errors to zero. */
+ jzero_far((void FAR *) cquantize->fserrors, arraysize);
+ /* Make the error-limit table if we didn't already. */
+ if (cquantize->error_limiter == NULL)
+ init_error_limit(cinfo);
+ cquantize->on_odd_row = FALSE;
+ }
+
+ }
+ /* Zero the histogram or inverse color map, if necessary */
+ if (cquantize->needs_zeroed) {
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ jzero_far((void FAR *) histogram[i],
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = FALSE;
+ }
+}
+
+
+/*
+ * Switch to a new external colormap between output passes.
+ */
+
+METHODDEF(void)
+new_color_map_2_quant (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize = (my_cquantize_ptr) cinfo->cquantize;
+
+ /* Reset the inverse color map */
+ cquantize->needs_zeroed = TRUE;
+}
+
+
+/*
+ * Module initialization routine for 2-pass color quantization.
+ */
+
+GLOBAL(void)
+jinit_2pass_quantizer (j_decompress_ptr cinfo)
+{
+ my_cquantize_ptr cquantize;
+ int i;
+
+ cquantize = (my_cquantize_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(my_cquantizer));
+ cinfo->cquantize = (struct jpeg_color_quantizer *) cquantize;
+ cquantize->pub.start_pass = start_pass_2_quant;
+ cquantize->pub.new_color_map = new_color_map_2_quant;
+ cquantize->fserrors = NULL; /* flag optional arrays not allocated */
+ cquantize->error_limiter = NULL;
+
+ /* Make sure jdmaster didn't give me a case I can't handle */
+ if (cinfo->out_color_components != 3)
+ ERREXIT(cinfo, JERR_NOTIMPL);
+
+ /* Allocate the histogram/inverse colormap storage */
+ cquantize->histogram = (hist3d) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, HIST_C0_ELEMS * SIZEOF(hist2d));
+ for (i = 0; i < HIST_C0_ELEMS; i++) {
+ cquantize->histogram[i] = (hist2d) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ HIST_C1_ELEMS*HIST_C2_ELEMS * SIZEOF(histcell));
+ }
+ cquantize->needs_zeroed = TRUE; /* histogram is garbage now */
+
+ /* Allocate storage for the completed colormap, if required.
+ * We do this now since it is FAR storage and may affect
+ * the memory manager's space calculations.
+ */
+ if (cinfo->enable_2pass_quant) {
+ /* Make sure color count is acceptable */
+ int desired = cinfo->desired_number_of_colors;
+ /* Lower bound on # of colors ... somewhat arbitrary as long as > 0 */
+ if (desired < 8)
+ ERREXIT1(cinfo, JERR_QUANT_FEW_COLORS, 8);
+ /* Make sure colormap indexes can be represented by JSAMPLEs */
+ if (desired > MAXNUMCOLORS)
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, MAXNUMCOLORS);
+ cquantize->sv_colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo,JPOOL_IMAGE, (JDIMENSION) desired, (JDIMENSION) 3);
+ cquantize->desired = desired;
+ } else
+ cquantize->sv_colormap = NULL;
+
+ /* Only F-S dithering or no dithering is supported. */
+ /* If user asks for ordered dither, give him F-S. */
+ if (cinfo->dither_mode != JDITHER_NONE)
+ cinfo->dither_mode = JDITHER_FS;
+
+ /* Allocate Floyd-Steinberg workspace if necessary.
+ * This isn't really needed until pass 2, but again it is FAR storage.
+ * Although we will cope with a later change in dither_mode,
+ * we do not promise to honor max_memory_to_use if dither_mode changes.
+ */
+ if (cinfo->dither_mode == JDITHER_FS) {
+ cquantize->fserrors = (FSERRPTR) (*cinfo->mem->alloc_large)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) ((cinfo->output_width + 2) * (3 * SIZEOF(FSERROR))));
+ /* Might as well create the error-limiting table too. */
+ init_error_limit(cinfo);
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/Source/LibJPEG/jutils.c b/Source/LibJPEG/jutils.c
new file mode 100644
index 0000000..d18a955
--- /dev/null
+++ b/Source/LibJPEG/jutils.c
@@ -0,0 +1,179 @@
+/*
+ * jutils.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains tables and miscellaneous utility routines needed
+ * for both compression and decompression.
+ * Note we prefix all global names with "j" to minimize conflicts with
+ * a surrounding application.
+ */
+
+#define JPEG_INTERNALS
+#include "jinclude.h"
+#include "jpeglib.h"
+
+
+/*
+ * jpeg_zigzag_order[i] is the zigzag-order position of the i'th element
+ * of a DCT block read in natural order (left to right, top to bottom).
+ */
+
+#if 0 /* This table is not actually needed in v6a */
+
+const int jpeg_zigzag_order[DCTSIZE2] = {
+ 0, 1, 5, 6, 14, 15, 27, 28,
+ 2, 4, 7, 13, 16, 26, 29, 42,
+ 3, 8, 12, 17, 25, 30, 41, 43,
+ 9, 11, 18, 24, 31, 40, 44, 53,
+ 10, 19, 23, 32, 39, 45, 52, 54,
+ 20, 22, 33, 38, 46, 51, 55, 60,
+ 21, 34, 37, 47, 50, 56, 59, 61,
+ 35, 36, 48, 49, 57, 58, 62, 63
+};
+
+#endif
+
+/*
+ * jpeg_natural_order[i] is the natural-order position of the i'th element
+ * of zigzag order.
+ *
+ * When reading corrupted data, the Huffman decoders could attempt
+ * to reference an entry beyond the end of this array (if the decoded
+ * zero run length reaches past the end of the block). To prevent
+ * wild stores without adding an inner-loop test, we put some extra
+ * "63"s after the real entries. This will cause the extra coefficient
+ * to be stored in location 63 of the block, not somewhere random.
+ * The worst case would be a run-length of 15, which means we need 16
+ * fake entries.
+ */
+
+const int jpeg_natural_order[DCTSIZE2+16] = {
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63,
+ 63, 63, 63, 63, 63, 63, 63, 63, /* extra entries for safety in decoder */
+ 63, 63, 63, 63, 63, 63, 63, 63
+};
+
+
+/*
+ * Arithmetic utilities
+ */
+
+GLOBAL(long)
+jdiv_round_up (long a, long b)
+/* Compute a/b rounded up to next integer, ie, ceil(a/b) */
+/* Assumes a >= 0, b > 0 */
+{
+ return (a + b - 1L) / b;
+}
+
+
+GLOBAL(long)
+jround_up (long a, long b)
+/* Compute a rounded up to next multiple of b, ie, ceil(a/b)*b */
+/* Assumes a >= 0, b > 0 */
+{
+ a += b - 1L;
+ return a - (a % b);
+}
+
+
+/* On normal machines we can apply MEMCOPY() and MEMZERO() to sample arrays
+ * and coefficient-block arrays. This won't work on 80x86 because the arrays
+ * are FAR and we're assuming a small-pointer memory model. However, some
+ * DOS compilers provide far-pointer versions of memcpy() and memset() even
+ * in the small-model libraries. These will be used if USE_FMEM is defined.
+ * Otherwise, the routines below do it the hard way. (The performance cost
+ * is not all that great, because these routines aren't very heavily used.)
+ */
+
+#ifndef NEED_FAR_POINTERS /* normal case, same as regular macros */
+#define FMEMCOPY(dest,src,size) MEMCOPY(dest,src,size)
+#define FMEMZERO(target,size) MEMZERO(target,size)
+#else /* 80x86 case, define if we can */
+#ifdef USE_FMEM
+#define FMEMCOPY(dest,src,size) _fmemcpy((void FAR *)(dest), (const void FAR *)(src), (size_t)(size))
+#define FMEMZERO(target,size) _fmemset((void FAR *)(target), 0, (size_t)(size))
+#endif
+#endif
+
+
+GLOBAL(void)
+jcopy_sample_rows (JSAMPARRAY input_array, int source_row,
+ JSAMPARRAY output_array, int dest_row,
+ int num_rows, JDIMENSION num_cols)
+/* Copy some rows of samples from one place to another.
+ * num_rows rows are copied from input_array[source_row++]
+ * to output_array[dest_row++]; these areas may overlap for duplication.
+ * The source and destination arrays must be at least as wide as num_cols.
+ */
+{
+ register JSAMPROW inptr, outptr;
+#ifdef FMEMCOPY
+ register size_t count = (size_t) (num_cols * SIZEOF(JSAMPLE));
+#else
+ register JDIMENSION count;
+#endif
+ register int row;
+
+ input_array += source_row;
+ output_array += dest_row;
+
+ for (row = num_rows; row > 0; row--) {
+ inptr = *input_array++;
+ outptr = *output_array++;
+#ifdef FMEMCOPY
+ FMEMCOPY(outptr, inptr, count);
+#else
+ for (count = num_cols; count > 0; count--)
+ *outptr++ = *inptr++; /* needn't bother with GETJSAMPLE() here */
+#endif
+ }
+}
+
+
+GLOBAL(void)
+jcopy_block_row (JBLOCKROW input_row, JBLOCKROW output_row,
+ JDIMENSION num_blocks)
+/* Copy a row of coefficient blocks from one place to another. */
+{
+#ifdef FMEMCOPY
+ FMEMCOPY(output_row, input_row, num_blocks * (DCTSIZE2 * SIZEOF(JCOEF)));
+#else
+ register JCOEFPTR inptr, outptr;
+ register long count;
+
+ inptr = (JCOEFPTR) input_row;
+ outptr = (JCOEFPTR) output_row;
+ for (count = (long) num_blocks * DCTSIZE2; count > 0; count--) {
+ *outptr++ = *inptr++;
+ }
+#endif
+}
+
+
+GLOBAL(void)
+jzero_far (void FAR * target, size_t bytestozero)
+/* Zero out a chunk of FAR memory. */
+/* This might be sample-array data, block-array data, or alloc_large data. */
+{
+#ifdef FMEMZERO
+ FMEMZERO(target, bytestozero);
+#else
+ register char FAR * ptr = (char FAR *) target;
+ register size_t count;
+
+ for (count = bytestozero; count > 0; count--) {
+ *ptr++ = 0;
+ }
+#endif
+}
diff --git a/Source/LibJPEG/jversion.h b/Source/LibJPEG/jversion.h
new file mode 100644
index 0000000..5151731
--- /dev/null
+++ b/Source/LibJPEG/jversion.h
@@ -0,0 +1,14 @@
+/*
+ * jversion.h
+ *
+ * Copyright (C) 1991-2009, Thomas G. Lane, Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains software version identification.
+ */
+
+
+#define JVERSION "7 27-Jun-2009"
+
+#define JCOPYRIGHT "Copyright (C) 2009, Thomas G. Lane, Guido Vollbeding"
diff --git a/Source/LibJPEG/libjpeg.txt b/Source/LibJPEG/libjpeg.txt
new file mode 100644
index 0000000..324e234
--- /dev/null
+++ b/Source/LibJPEG/libjpeg.txt
@@ -0,0 +1,3067 @@
+USING THE IJG JPEG LIBRARY
+
+Copyright (C) 1994-2009, Thomas G. Lane, Guido Vollbeding.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file describes how to use the IJG JPEG library within an application
+program. Read it if you want to write a program that uses the library.
+
+The file example.c provides heavily commented skeleton code for calling the
+JPEG library. Also see jpeglib.h (the include file to be used by application
+programs) for full details about data structures and function parameter lists.
+The library source code, of course, is the ultimate reference.
+
+Note that there have been *major* changes from the application interface
+presented by IJG version 4 and earlier versions. The old design had several
+inherent limitations, and it had accumulated a lot of cruft as we added
+features while trying to minimize application-interface changes. We have
+sacrificed backward compatibility in the version 5 rewrite, but we think the
+improvements justify this.
+
+
+TABLE OF CONTENTS
+-----------------
+
+Overview:
+ Functions provided by the library
+ Outline of typical usage
+Basic library usage:
+ Data formats
+ Compression details
+ Decompression details
+ Mechanics of usage: include files, linking, etc
+Advanced features:
+ Compression parameter selection
+ Decompression parameter selection
+ Special color spaces
+ Error handling
+ Compressed data handling (source and destination managers)
+ I/O suspension
+ Progressive JPEG support
+ Buffered-image mode
+ Abbreviated datastreams and multiple images
+ Special markers
+ Raw (downsampled) image data
+ Really raw data: DCT coefficients
+ Progress monitoring
+ Memory management
+ Memory usage
+ Library compile-time options
+ Portability considerations
+ Notes for MS-DOS implementors
+
+You should read at least the overview and basic usage sections before trying
+to program with the library. The sections on advanced features can be read
+if and when you need them.
+
+
+OVERVIEW
+========
+
+Functions provided by the library
+---------------------------------
+
+The IJG JPEG library provides C code to read and write JPEG-compressed image
+files. The surrounding application program receives or supplies image data a
+scanline at a time, using a straightforward uncompressed image format. All
+details of color conversion and other preprocessing/postprocessing can be
+handled by the library.
+
+The library includes a substantial amount of code that is not covered by the
+JPEG standard but is necessary for typical applications of JPEG. These
+functions preprocess the image before JPEG compression or postprocess it after
+decompression. They include colorspace conversion, downsampling/upsampling,
+and color quantization. The application indirectly selects use of this code
+by specifying the format in which it wishes to supply or receive image data.
+For example, if colormapped output is requested, then the decompression
+library automatically invokes color quantization.
+
+A wide range of quality vs. speed tradeoffs are possible in JPEG processing,
+and even more so in decompression postprocessing. The decompression library
+provides multiple implementations that cover most of the useful tradeoffs,
+ranging from very-high-quality down to fast-preview operation. On the
+compression side we have generally not provided low-quality choices, since
+compression is normally less time-critical. It should be understood that the
+low-quality modes may not meet the JPEG standard's accuracy requirements;
+nonetheless, they are useful for viewers.
+
+A word about functions *not* provided by the library. We handle a subset of
+the ISO JPEG standard; most baseline, extended-sequential, and progressive
+JPEG processes are supported. (Our subset includes all features now in common
+use.) Unsupported ISO options include:
+ * Hierarchical storage
+ * Lossless JPEG
+ * DNL marker
+ * Nonintegral subsampling ratios
+We support both 8- and 12-bit data precision, but this is a compile-time
+choice rather than a run-time choice; hence it is difficult to use both
+precisions in a single application.
+
+By itself, the library handles only interchange JPEG datastreams --- in
+particular the widely used JFIF file format. The library can be used by
+surrounding code to process interchange or abbreviated JPEG datastreams that
+are embedded in more complex file formats. (For example, this library is
+used by the free LIBTIFF library to support JPEG compression in TIFF.)
+
+
+Outline of typical usage
+------------------------
+
+The rough outline of a JPEG compression operation is:
+
+ Allocate and initialize a JPEG compression object
+ Specify the destination for the compressed data (eg, a file)
+ Set parameters for compression, including image size & colorspace
+ jpeg_start_compress(...);
+ while (scan lines remain to be written)
+ jpeg_write_scanlines(...);
+ jpeg_finish_compress(...);
+ Release the JPEG compression object
+
+A JPEG compression object holds parameters and working state for the JPEG
+library. We make creation/destruction of the object separate from starting
+or finishing compression of an image; the same object can be re-used for a
+series of image compression operations. This makes it easy to re-use the
+same parameter settings for a sequence of images. Re-use of a JPEG object
+also has important implications for processing abbreviated JPEG datastreams,
+as discussed later.
+
+The image data to be compressed is supplied to jpeg_write_scanlines() from
+in-memory buffers. If the application is doing file-to-file compression,
+reading image data from the source file is the application's responsibility.
+The library emits compressed data by calling a "data destination manager",
+which typically will write the data into a file; but the application can
+provide its own destination manager to do something else.
+
+Similarly, the rough outline of a JPEG decompression operation is:
+
+ Allocate and initialize a JPEG decompression object
+ Specify the source of the compressed data (eg, a file)
+ Call jpeg_read_header() to obtain image info
+ Set parameters for decompression
+ jpeg_start_decompress(...);
+ while (scan lines remain to be read)
+ jpeg_read_scanlines(...);
+ jpeg_finish_decompress(...);
+ Release the JPEG decompression object
+
+This is comparable to the compression outline except that reading the
+datastream header is a separate step. This is helpful because information
+about the image's size, colorspace, etc is available when the application
+selects decompression parameters. For example, the application can choose an
+output scaling ratio that will fit the image into the available screen size.
+
+The decompression library obtains compressed data by calling a data source
+manager, which typically will read the data from a file; but other behaviors
+can be obtained with a custom source manager. Decompressed data is delivered
+into in-memory buffers passed to jpeg_read_scanlines().
+
+It is possible to abort an incomplete compression or decompression operation
+by calling jpeg_abort(); or, if you do not need to retain the JPEG object,
+simply release it by calling jpeg_destroy().
+
+JPEG compression and decompression objects are two separate struct types.
+However, they share some common fields, and certain routines such as
+jpeg_destroy() can work on either type of object.
+
+The JPEG library has no static variables: all state is in the compression
+or decompression object. Therefore it is possible to process multiple
+compression and decompression operations concurrently, using multiple JPEG
+objects.
+
+Both compression and decompression can be done in an incremental memory-to-
+memory fashion, if suitable source/destination managers are used. See the
+section on "I/O suspension" for more details.
+
+
+BASIC LIBRARY USAGE
+===================
+
+Data formats
+------------
+
+Before diving into procedural details, it is helpful to understand the
+image data format that the JPEG library expects or returns.
+
+The standard input image format is a rectangular array of pixels, with each
+pixel having the same number of "component" or "sample" values (color
+channels). You must specify how many components there are and the colorspace
+interpretation of the components. Most applications will use RGB data
+(three components per pixel) or grayscale data (one component per pixel).
+PLEASE NOTE THAT RGB DATA IS THREE SAMPLES PER PIXEL, GRAYSCALE ONLY ONE.
+A remarkable number of people manage to miss this, only to find that their
+programs don't work with grayscale JPEG files.
+
+There is no provision for colormapped input. JPEG files are always full-color
+or full grayscale (or sometimes another colorspace such as CMYK). You can
+feed in a colormapped image by expanding it to full-color format. However
+JPEG often doesn't work very well with source data that has been colormapped,
+because of dithering noise. This is discussed in more detail in the JPEG FAQ
+and the other references mentioned in the README file.
+
+Pixels are stored by scanlines, with each scanline running from left to
+right. The component values for each pixel are adjacent in the row; for
+example, R,G,B,R,G,B,R,G,B,... for 24-bit RGB color. Each scanline is an
+array of data type JSAMPLE --- which is typically "unsigned char", unless
+you've changed jmorecfg.h. (You can also change the RGB pixel layout, say
+to B,G,R order, by modifying jmorecfg.h. But see the restrictions listed in
+that file before doing so.)
+
+A 2-D array of pixels is formed by making a list of pointers to the starts of
+scanlines; so the scanlines need not be physically adjacent in memory. Even
+if you process just one scanline at a time, you must make a one-element
+pointer array to conform to this structure. Pointers to JSAMPLE rows are of
+type JSAMPROW, and the pointer to the pointer array is of type JSAMPARRAY.
+
+The library accepts or supplies one or more complete scanlines per call.
+It is not possible to process part of a row at a time. Scanlines are always
+processed top-to-bottom. You can process an entire image in one call if you
+have it all in memory, but usually it's simplest to process one scanline at
+a time.
+
+For best results, source data values should have the precision specified by
+BITS_IN_JSAMPLE (normally 8 bits). For instance, if you choose to compress
+data that's only 6 bits/channel, you should left-justify each value in a
+byte before passing it to the compressor. If you need to compress data
+that has more than 8 bits/channel, compile with BITS_IN_JSAMPLE = 12.
+(See "Library compile-time options", later.)
+
+
+The data format returned by the decompressor is the same in all details,
+except that colormapped output is supported. (Again, a JPEG file is never
+colormapped. But you can ask the decompressor to perform on-the-fly color
+quantization to deliver colormapped output.) If you request colormapped
+output then the returned data array contains a single JSAMPLE per pixel;
+its value is an index into a color map. The color map is represented as
+a 2-D JSAMPARRAY in which each row holds the values of one color component,
+that is, colormap[i][j] is the value of the i'th color component for pixel
+value (map index) j. Note that since the colormap indexes are stored in
+JSAMPLEs, the maximum number of colors is limited by the size of JSAMPLE
+(ie, at most 256 colors for an 8-bit JPEG library).
+
+
+Compression details
+-------------------
+
+Here we revisit the JPEG compression outline given in the overview.
+
+1. Allocate and initialize a JPEG compression object.
+
+A JPEG compression object is a "struct jpeg_compress_struct". (It also has
+a bunch of subsidiary structures which are allocated via malloc(), but the
+application doesn't control those directly.) This struct can be just a local
+variable in the calling routine, if a single routine is going to execute the
+whole JPEG compression sequence. Otherwise it can be static or allocated
+from malloc().
+
+You will also need a structure representing a JPEG error handler. The part
+of this that the library cares about is a "struct jpeg_error_mgr". If you
+are providing your own error handler, you'll typically want to embed the
+jpeg_error_mgr struct in a larger structure; this is discussed later under
+"Error handling". For now we'll assume you are just using the default error
+handler. The default error handler will print JPEG error/warning messages
+on stderr, and it will call exit() if a fatal error occurs.
+
+You must initialize the error handler structure, store a pointer to it into
+the JPEG object's "err" field, and then call jpeg_create_compress() to
+initialize the rest of the JPEG object.
+
+Typical code for this step, if you are using the default error handler, is
+
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ ...
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+jpeg_create_compress allocates a small amount of memory, so it could fail
+if you are out of memory. In that case it will exit via the error handler;
+that's why the error handler must be initialized first.
+
+
+2. Specify the destination for the compressed data (eg, a file).
+
+As previously mentioned, the JPEG library delivers compressed data to a
+"data destination" module. The library includes one data destination
+module which knows how to write to a stdio stream. You can use your own
+destination module if you want to do something else, as discussed later.
+
+If you use the standard destination module, you must open the target stdio
+stream beforehand. Typical code for this step looks like:
+
+ FILE * outfile;
+ ...
+ if ((outfile = fopen(filename, "wb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", filename);
+ exit(1);
+ }
+ jpeg_stdio_dest(&cinfo, outfile);
+
+where the last line invokes the standard destination module.
+
+WARNING: it is critical that the binary compressed data be delivered to the
+output file unchanged. On non-Unix systems the stdio library may perform
+newline translation or otherwise corrupt binary data. To suppress this
+behavior, you may need to use a "b" option to fopen (as shown above), or use
+setmode() or another routine to put the stdio stream in binary mode. See
+cjpeg.c and djpeg.c for code that has been found to work on many systems.
+
+You can select the data destination after setting other parameters (step 3),
+if that's more convenient. You may not change the destination between
+calling jpeg_start_compress() and jpeg_finish_compress().
+
+
+3. Set parameters for compression, including image size & colorspace.
+
+You must supply information about the source image by setting the following
+fields in the JPEG object (cinfo structure):
+
+ image_width Width of image, in pixels
+ image_height Height of image, in pixels
+ input_components Number of color channels (samples per pixel)
+ in_color_space Color space of source image
+
+The image dimensions are, hopefully, obvious. JPEG supports image dimensions
+of 1 to 64K pixels in either direction. The input color space is typically
+RGB or grayscale, and input_components is 3 or 1 accordingly. (See "Special
+color spaces", later, for more info.) The in_color_space field must be
+assigned one of the J_COLOR_SPACE enum constants, typically JCS_RGB or
+JCS_GRAYSCALE.
+
+JPEG has a large number of compression parameters that determine how the
+image is encoded. Most applications don't need or want to know about all
+these parameters. You can set all the parameters to reasonable defaults by
+calling jpeg_set_defaults(); then, if there are particular values you want
+to change, you can do so after that. The "Compression parameter selection"
+section tells about all the parameters.
+
+You must set in_color_space correctly before calling jpeg_set_defaults(),
+because the defaults depend on the source image colorspace. However the
+other three source image parameters need not be valid until you call
+jpeg_start_compress(). There's no harm in calling jpeg_set_defaults() more
+than once, if that happens to be convenient.
+
+Typical code for a 24-bit RGB source image is
+
+ cinfo.image_width = Width; /* image width and height, in pixels */
+ cinfo.image_height = Height;
+ cinfo.input_components = 3; /* # of color components per pixel */
+ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+
+ jpeg_set_defaults(&cinfo);
+ /* Make optional parameter settings here */
+
+
+4. jpeg_start_compress(...);
+
+After you have established the data destination and set all the necessary
+source image info and other parameters, call jpeg_start_compress() to begin
+a compression cycle. This will initialize internal state, allocate working
+storage, and emit the first few bytes of the JPEG datastream header.
+
+Typical code:
+
+ jpeg_start_compress(&cinfo, TRUE);
+
+The "TRUE" parameter ensures that a complete JPEG interchange datastream
+will be written. This is appropriate in most cases. If you think you might
+want to use an abbreviated datastream, read the section on abbreviated
+datastreams, below.
+
+Once you have called jpeg_start_compress(), you may not alter any JPEG
+parameters or other fields of the JPEG object until you have completed
+the compression cycle.
+
+
+5. while (scan lines remain to be written)
+ jpeg_write_scanlines(...);
+
+Now write all the required image data by calling jpeg_write_scanlines()
+one or more times. You can pass one or more scanlines in each call, up
+to the total image height. In most applications it is convenient to pass
+just one or a few scanlines at a time. The expected format for the passed
+data is discussed under "Data formats", above.
+
+Image data should be written in top-to-bottom scanline order. The JPEG spec
+contains some weasel wording about how top and bottom are application-defined
+terms (a curious interpretation of the English language...) but if you want
+your files to be compatible with everyone else's, you WILL use top-to-bottom
+order. If the source data must be read in bottom-to-top order, you can use
+the JPEG library's virtual array mechanism to invert the data efficiently.
+Examples of this can be found in the sample application cjpeg.
+
+The library maintains a count of the number of scanlines written so far
+in the next_scanline field of the JPEG object. Usually you can just use
+this variable as the loop counter, so that the loop test looks like
+"while (cinfo.next_scanline < cinfo.image_height)".
+
+Code for this step depends heavily on the way that you store the source data.
+example.c shows the following code for the case of a full-size 2-D source
+array containing 3-byte RGB pixels:
+
+ JSAMPROW row_pointer[1]; /* pointer to a single row */
+ int row_stride; /* physical row width in buffer */
+
+ row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+jpeg_write_scanlines() returns the number of scanlines actually written.
+This will normally be equal to the number passed in, so you can usually
+ignore the return value. It is different in just two cases:
+ * If you try to write more scanlines than the declared image height,
+ the additional scanlines are ignored.
+ * If you use a suspending data destination manager, output buffer overrun
+ will cause the compressor to return before accepting all the passed lines.
+ This feature is discussed under "I/O suspension", below. The normal
+ stdio destination manager will NOT cause this to happen.
+In any case, the return value is the same as the change in the value of
+next_scanline.
+
+
+6. jpeg_finish_compress(...);
+
+After all the image data has been written, call jpeg_finish_compress() to
+complete the compression cycle. This step is ESSENTIAL to ensure that the
+last bufferload of data is written to the data destination.
+jpeg_finish_compress() also releases working memory associated with the JPEG
+object.
+
+Typical code:
+
+ jpeg_finish_compress(&cinfo);
+
+If using the stdio destination manager, don't forget to close the output
+stdio stream (if necessary) afterwards.
+
+If you have requested a multi-pass operating mode, such as Huffman code
+optimization, jpeg_finish_compress() will perform the additional passes using
+data buffered by the first pass. In this case jpeg_finish_compress() may take
+quite a while to complete. With the default compression parameters, this will
+not happen.
+
+It is an error to call jpeg_finish_compress() before writing the necessary
+total number of scanlines. If you wish to abort compression, call
+jpeg_abort() as discussed below.
+
+After completing a compression cycle, you may dispose of the JPEG object
+as discussed next, or you may use it to compress another image. In that case
+return to step 2, 3, or 4 as appropriate. If you do not change the
+destination manager, the new datastream will be written to the same target.
+If you do not change any JPEG parameters, the new datastream will be written
+with the same parameters as before. Note that you can change the input image
+dimensions freely between cycles, but if you change the input colorspace, you
+should call jpeg_set_defaults() to adjust for the new colorspace; and then
+you'll need to repeat all of step 3.
+
+
+7. Release the JPEG compression object.
+
+When you are done with a JPEG compression object, destroy it by calling
+jpeg_destroy_compress(). This will free all subsidiary memory (regardless of
+the previous state of the object). Or you can call jpeg_destroy(), which
+works for either compression or decompression objects --- this may be more
+convenient if you are sharing code between compression and decompression
+cases. (Actually, these routines are equivalent except for the declared type
+of the passed pointer. To avoid gripes from ANSI C compilers, jpeg_destroy()
+should be passed a j_common_ptr.)
+
+If you allocated the jpeg_compress_struct structure from malloc(), freeing
+it is your responsibility --- jpeg_destroy() won't. Ditto for the error
+handler structure.
+
+Typical code:
+
+ jpeg_destroy_compress(&cinfo);
+
+
+8. Aborting.
+
+If you decide to abort a compression cycle before finishing, you can clean up
+in either of two ways:
+
+* If you don't need the JPEG object any more, just call
+ jpeg_destroy_compress() or jpeg_destroy() to release memory. This is
+ legitimate at any point after calling jpeg_create_compress() --- in fact,
+ it's safe even if jpeg_create_compress() fails.
+
+* If you want to re-use the JPEG object, call jpeg_abort_compress(), or call
+ jpeg_abort() which works on both compression and decompression objects.
+ This will return the object to an idle state, releasing any working memory.
+ jpeg_abort() is allowed at any time after successful object creation.
+
+Note that cleaning up the data destination, if required, is your
+responsibility; neither of these routines will call term_destination().
+(See "Compressed data handling", below, for more about that.)
+
+jpeg_destroy() and jpeg_abort() are the only safe calls to make on a JPEG
+object that has reported an error by calling error_exit (see "Error handling"
+for more info). The internal state of such an object is likely to be out of
+whack. Either of these two routines will return the object to a known state.
+
+
+Decompression details
+---------------------
+
+Here we revisit the JPEG decompression outline given in the overview.
+
+1. Allocate and initialize a JPEG decompression object.
+
+This is just like initialization for compression, as discussed above,
+except that the object is a "struct jpeg_decompress_struct" and you
+call jpeg_create_decompress(). Error handling is exactly the same.
+
+Typical code:
+
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ ...
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_decompress(&cinfo);
+
+(Both here and in the IJG code, we usually use variable name "cinfo" for
+both compression and decompression objects.)
+
+
+2. Specify the source of the compressed data (eg, a file).
+
+As previously mentioned, the JPEG library reads compressed data from a "data
+source" module. The library includes one data source module which knows how
+to read from a stdio stream. You can use your own source module if you want
+to do something else, as discussed later.
+
+If you use the standard source module, you must open the source stdio stream
+beforehand. Typical code for this step looks like:
+
+ FILE * infile;
+ ...
+ if ((infile = fopen(filename, "rb")) == NULL) {
+ fprintf(stderr, "can't open %s\n", filename);
+ exit(1);
+ }
+ jpeg_stdio_src(&cinfo, infile);
+
+where the last line invokes the standard source module.
+
+WARNING: it is critical that the binary compressed data be read unchanged.
+On non-Unix systems the stdio library may perform newline translation or
+otherwise corrupt binary data. To suppress this behavior, you may need to use
+a "b" option to fopen (as shown above), or use setmode() or another routine to
+put the stdio stream in binary mode. See cjpeg.c and djpeg.c for code that
+has been found to work on many systems.
+
+You may not change the data source between calling jpeg_read_header() and
+jpeg_finish_decompress(). If you wish to read a series of JPEG images from
+a single source file, you should repeat the jpeg_read_header() to
+jpeg_finish_decompress() sequence without reinitializing either the JPEG
+object or the data source module; this prevents buffered input data from
+being discarded.
+
+
+3. Call jpeg_read_header() to obtain image info.
+
+Typical code for this step is just
+
+ jpeg_read_header(&cinfo, TRUE);
+
+This will read the source datastream header markers, up to the beginning
+of the compressed data proper. On return, the image dimensions and other
+info have been stored in the JPEG object. The application may wish to
+consult this information before selecting decompression parameters.
+
+More complex code is necessary if
+ * A suspending data source is used --- in that case jpeg_read_header()
+ may return before it has read all the header data. See "I/O suspension",
+ below. The normal stdio source manager will NOT cause this to happen.
+ * Abbreviated JPEG files are to be processed --- see the section on
+ abbreviated datastreams. Standard applications that deal only in
+ interchange JPEG files need not be concerned with this case either.
+
+It is permissible to stop at this point if you just wanted to find out the
+image dimensions and other header info for a JPEG file. In that case,
+call jpeg_destroy() when you are done with the JPEG object, or call
+jpeg_abort() to return it to an idle state before selecting a new data
+source and reading another header.
+
+
+4. Set parameters for decompression.
+
+jpeg_read_header() sets appropriate default decompression parameters based on
+the properties of the image (in particular, its colorspace). However, you
+may well want to alter these defaults before beginning the decompression.
+For example, the default is to produce full color output from a color file.
+If you want colormapped output you must ask for it. Other options allow the
+returned image to be scaled and allow various speed/quality tradeoffs to be
+selected. "Decompression parameter selection", below, gives details.
+
+If the defaults are appropriate, nothing need be done at this step.
+
+Note that all default values are set by each call to jpeg_read_header().
+If you reuse a decompression object, you cannot expect your parameter
+settings to be preserved across cycles, as you can for compression.
+You must set desired parameter values each time.
+
+
+5. jpeg_start_decompress(...);
+
+Once the parameter values are satisfactory, call jpeg_start_decompress() to
+begin decompression. This will initialize internal state, allocate working
+memory, and prepare for returning data.
+
+Typical code is just
+
+ jpeg_start_decompress(&cinfo);
+
+If you have requested a multi-pass operating mode, such as 2-pass color
+quantization, jpeg_start_decompress() will do everything needed before data
+output can begin. In this case jpeg_start_decompress() may take quite a while
+to complete. With a single-scan (non progressive) JPEG file and default
+decompression parameters, this will not happen; jpeg_start_decompress() will
+return quickly.
+
+After this call, the final output image dimensions, including any requested
+scaling, are available in the JPEG object; so is the selected colormap, if
+colormapped output has been requested. Useful fields include
+
+ output_width image width and height, as scaled
+ output_height
+ out_color_components # of color components in out_color_space
+ output_components # of color components returned per pixel
+ colormap the selected colormap, if any
+ actual_number_of_colors number of entries in colormap
+
+output_components is 1 (a colormap index) when quantizing colors; otherwise it
+equals out_color_components. It is the number of JSAMPLE values that will be
+emitted per pixel in the output arrays.
+
+Typically you will need to allocate data buffers to hold the incoming image.
+You will need output_width * output_components JSAMPLEs per scanline in your
+output buffer, and a total of output_height scanlines will be returned.
+
+Note: if you are using the JPEG library's internal memory manager to allocate
+data buffers (as djpeg does), then the manager's protocol requires that you
+request large buffers *before* calling jpeg_start_decompress(). This is a
+little tricky since the output_XXX fields are not normally valid then. You
+can make them valid by calling jpeg_calc_output_dimensions() after setting the
+relevant parameters (scaling, output color space, and quantization flag).
+
+
+6. while (scan lines remain to be read)
+ jpeg_read_scanlines(...);
+
+Now you can read the decompressed image data by calling jpeg_read_scanlines()
+one or more times. At each call, you pass in the maximum number of scanlines
+to be read (ie, the height of your working buffer); jpeg_read_scanlines()
+will return up to that many lines. The return value is the number of lines
+actually read. The format of the returned data is discussed under "Data
+formats", above. Don't forget that grayscale and color JPEGs will return
+different data formats!
+
+Image data is returned in top-to-bottom scanline order. If you must write
+out the image in bottom-to-top order, you can use the JPEG library's virtual
+array mechanism to invert the data efficiently. Examples of this can be
+found in the sample application djpeg.
+
+The library maintains a count of the number of scanlines returned so far
+in the output_scanline field of the JPEG object. Usually you can just use
+this variable as the loop counter, so that the loop test looks like
+"while (cinfo.output_scanline < cinfo.output_height)". (Note that the test
+should NOT be against image_height, unless you never use scaling. The
+image_height field is the height of the original unscaled image.)
+The return value always equals the change in the value of output_scanline.
+
+If you don't use a suspending data source, it is safe to assume that
+jpeg_read_scanlines() reads at least one scanline per call, until the
+bottom of the image has been reached.
+
+If you use a buffer larger than one scanline, it is NOT safe to assume that
+jpeg_read_scanlines() fills it. (The current implementation returns only a
+few scanlines per call, no matter how large a buffer you pass.) So you must
+always provide a loop that calls jpeg_read_scanlines() repeatedly until the
+whole image has been read.
+
+
+7. jpeg_finish_decompress(...);
+
+After all the image data has been read, call jpeg_finish_decompress() to
+complete the decompression cycle. This causes working memory associated
+with the JPEG object to be released.
+
+Typical code:
+
+ jpeg_finish_decompress(&cinfo);
+
+If using the stdio source manager, don't forget to close the source stdio
+stream if necessary.
+
+It is an error to call jpeg_finish_decompress() before reading the correct
+total number of scanlines. If you wish to abort decompression, call
+jpeg_abort() as discussed below.
+
+After completing a decompression cycle, you may dispose of the JPEG object as
+discussed next, or you may use it to decompress another image. In that case
+return to step 2 or 3 as appropriate. If you do not change the source
+manager, the next image will be read from the same source.
+
+
+8. Release the JPEG decompression object.
+
+When you are done with a JPEG decompression object, destroy it by calling
+jpeg_destroy_decompress() or jpeg_destroy(). The previous discussion of
+destroying compression objects applies here too.
+
+Typical code:
+
+ jpeg_destroy_decompress(&cinfo);
+
+
+9. Aborting.
+
+You can abort a decompression cycle by calling jpeg_destroy_decompress() or
+jpeg_destroy() if you don't need the JPEG object any more, or
+jpeg_abort_decompress() or jpeg_abort() if you want to reuse the object.
+The previous discussion of aborting compression cycles applies here too.
+
+
+Mechanics of usage: include files, linking, etc
+-----------------------------------------------
+
+Applications using the JPEG library should include the header file jpeglib.h
+to obtain declarations of data types and routines. Before including
+jpeglib.h, include system headers that define at least the typedefs FILE and
+size_t. On ANSI-conforming systems, including <stdio.h> is sufficient; on
+older Unix systems, you may need <sys/types.h> to define size_t.
+
+If the application needs to refer to individual JPEG library error codes, also
+include jerror.h to define those symbols.
+
+jpeglib.h indirectly includes the files jconfig.h and jmorecfg.h. If you are
+installing the JPEG header files in a system directory, you will want to
+install all four files: jpeglib.h, jerror.h, jconfig.h, jmorecfg.h.
+
+The most convenient way to include the JPEG code into your executable program
+is to prepare a library file ("libjpeg.a", or a corresponding name on non-Unix
+machines) and reference it at your link step. If you use only half of the
+library (only compression or only decompression), only that much code will be
+included from the library, unless your linker is hopelessly brain-damaged.
+The supplied makefiles build libjpeg.a automatically (see install.txt).
+
+While you can build the JPEG library as a shared library if the whim strikes
+you, we don't really recommend it. The trouble with shared libraries is that
+at some point you'll probably try to substitute a new version of the library
+without recompiling the calling applications. That generally doesn't work
+because the parameter struct declarations usually change with each new
+version. In other words, the library's API is *not* guaranteed binary
+compatible across versions; we only try to ensure source-code compatibility.
+(In hindsight, it might have been smarter to hide the parameter structs from
+applications and introduce a ton of access functions instead. Too late now,
+however.)
+
+On some systems your application may need to set up a signal handler to ensure
+that temporary files are deleted if the program is interrupted. This is most
+critical if you are on MS-DOS and use the jmemdos.c memory manager back end;
+it will try to grab extended memory for temp files, and that space will NOT be
+freed automatically. See cjpeg.c or djpeg.c for an example signal handler.
+
+It may be worth pointing out that the core JPEG library does not actually
+require the stdio library: only the default source/destination managers and
+error handler need it. You can use the library in a stdio-less environment
+if you replace those modules and use jmemnobs.c (or another memory manager of
+your own devising). More info about the minimum system library requirements
+may be found in jinclude.h.
+
+
+ADVANCED FEATURES
+=================
+
+Compression parameter selection
+-------------------------------
+
+This section describes all the optional parameters you can set for JPEG
+compression, as well as the "helper" routines provided to assist in this
+task. Proper setting of some parameters requires detailed understanding
+of the JPEG standard; if you don't know what a parameter is for, it's best
+not to mess with it! See REFERENCES in the README file for pointers to
+more info about JPEG.
+
+It's a good idea to call jpeg_set_defaults() first, even if you plan to set
+all the parameters; that way your code is more likely to work with future JPEG
+libraries that have additional parameters. For the same reason, we recommend
+you use a helper routine where one is provided, in preference to twiddling
+cinfo fields directly.
+
+The helper routines are:
+
+jpeg_set_defaults (j_compress_ptr cinfo)
+ This routine sets all JPEG parameters to reasonable defaults, using
+ only the input image's color space (field in_color_space, which must
+ already be set in cinfo). Many applications will only need to use
+ this routine and perhaps jpeg_set_quality().
+
+jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace)
+ Sets the JPEG file's colorspace (field jpeg_color_space) as specified,
+ and sets other color-space-dependent parameters appropriately. See
+ "Special color spaces", below, before using this. A large number of
+ parameters, including all per-component parameters, are set by this
+ routine; if you want to twiddle individual parameters you should call
+ jpeg_set_colorspace() before rather than after.
+
+jpeg_default_colorspace (j_compress_ptr cinfo)
+ Selects an appropriate JPEG colorspace based on cinfo->in_color_space,
+ and calls jpeg_set_colorspace(). This is actually a subroutine of
+ jpeg_set_defaults(). It's broken out in case you want to change
+ just the colorspace-dependent JPEG parameters.
+
+jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline)
+ Constructs JPEG quantization tables appropriate for the indicated
+ quality setting. The quality value is expressed on the 0..100 scale
+ recommended by IJG (cjpeg's "-quality" switch uses this routine).
+ Note that the exact mapping from quality values to tables may change
+ in future IJG releases as more is learned about DCT quantization.
+ If the force_baseline parameter is TRUE, then the quantization table
+ entries are constrained to the range 1..255 for full JPEG baseline
+ compatibility. In the current implementation, this only makes a
+ difference for quality settings below 25, and it effectively prevents
+ very small/low quality files from being generated. The IJG decoder
+ is capable of reading the non-baseline files generated at low quality
+ settings when force_baseline is FALSE, but other decoders may not be.
+
+jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor,
+ boolean force_baseline)
+ Same as jpeg_set_quality() except that the generated tables are the
+ sample tables given in the JPEC spec section K.1, multiplied by the
+ specified scale factor (which is expressed as a percentage; thus
+ scale_factor = 100 reproduces the spec's tables). Note that larger
+ scale factors give lower quality. This entry point is useful for
+ conforming to the Adobe PostScript DCT conventions, but we do not
+ recommend linear scaling as a user-visible quality scale otherwise.
+ force_baseline again constrains the computed table entries to 1..255.
+
+int jpeg_quality_scaling (int quality)
+ Converts a value on the IJG-recommended quality scale to a linear
+ scaling percentage. Note that this routine may change or go away
+ in future releases --- IJG may choose to adopt a scaling method that
+ can't be expressed as a simple scalar multiplier, in which case the
+ premise of this routine collapses. Caveat user.
+
+jpeg_default_qtables (j_compress_ptr cinfo, boolean force_baseline)
+ Set default quantization tables with linear q_scale_factor[] values
+ (see below).
+
+jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl,
+ const unsigned int *basic_table,
+ int scale_factor, boolean force_baseline)
+ Allows an arbitrary quantization table to be created. which_tbl
+ indicates which table slot to fill. basic_table points to an array
+ of 64 unsigned ints given in normal array order. These values are
+ multiplied by scale_factor/100 and then clamped to the range 1..65535
+ (or to 1..255 if force_baseline is TRUE).
+ CAUTION: prior to library version 6a, jpeg_add_quant_table expected
+ the basic table to be given in JPEG zigzag order. If you need to
+ write code that works with either older or newer versions of this
+ routine, you must check the library version number. Something like
+ "#if JPEG_LIB_VERSION >= 61" is the right test.
+
+jpeg_simple_progression (j_compress_ptr cinfo)
+ Generates a default scan script for writing a progressive-JPEG file.
+ This is the recommended method of creating a progressive file,
+ unless you want to make a custom scan sequence. You must ensure that
+ the JPEG color space is set correctly before calling this routine.
+
+
+Compression parameters (cinfo fields) include:
+
+J_DCT_METHOD dct_method
+ Selects the algorithm used for the DCT step. Choices are:
+ JDCT_ISLOW: slow but accurate integer algorithm
+ JDCT_IFAST: faster, less accurate integer method
+ JDCT_FLOAT: floating-point method
+ JDCT_DEFAULT: default method (normally JDCT_ISLOW)
+ JDCT_FASTEST: fastest method (normally JDCT_IFAST)
+ The FLOAT method is very slightly more accurate than the ISLOW method,
+ but may give different results on different machines due to varying
+ roundoff behavior. The integer methods should give the same results
+ on all machines. On machines with sufficiently fast FP hardware, the
+ floating-point method may also be the fastest. The IFAST method is
+ considerably less accurate than the other two; its use is not
+ recommended if high quality is a concern. JDCT_DEFAULT and
+ JDCT_FASTEST are macros configurable by each installation.
+
+unsigned int scale_num, scale_denom
+ Scale the image by the fraction scale_num/scale_denom. Default is
+ 1/1, or no scaling. Currently, the supported scaling ratios are
+ 8/N with all N from 1 to 16. (The library design allows for arbitrary
+ scaling ratios but this is not likely to be implemented any time soon.)
+
+J_COLOR_SPACE jpeg_color_space
+int num_components
+ The JPEG color space and corresponding number of components; see
+ "Special color spaces", below, for more info. We recommend using
+ jpeg_set_color_space() if you want to change these.
+
+boolean optimize_coding
+ TRUE causes the compressor to compute optimal Huffman coding tables
+ for the image. This requires an extra pass over the data and
+ therefore costs a good deal of space and time. The default is
+ FALSE, which tells the compressor to use the supplied or default
+ Huffman tables. In most cases optimal tables save only a few percent
+ of file size compared to the default tables. Note that when this is
+ TRUE, you need not supply Huffman tables at all, and any you do
+ supply will be overwritten.
+
+unsigned int restart_interval
+int restart_in_rows
+ To emit restart markers in the JPEG file, set one of these nonzero.
+ Set restart_interval to specify the exact interval in MCU blocks.
+ Set restart_in_rows to specify the interval in MCU rows. (If
+ restart_in_rows is not 0, then restart_interval is set after the
+ image width in MCUs is computed.) Defaults are zero (no restarts).
+ One restart marker per MCU row is often a good choice.
+ NOTE: the overhead of restart markers is higher in grayscale JPEG
+ files than in color files, and MUCH higher in progressive JPEGs.
+ If you use restarts, you may want to use larger intervals in those
+ cases.
+
+const jpeg_scan_info * scan_info
+int num_scans
+ By default, scan_info is NULL; this causes the compressor to write a
+ single-scan sequential JPEG file. If not NULL, scan_info points to
+ an array of scan definition records of length num_scans. The
+ compressor will then write a JPEG file having one scan for each scan
+ definition record. This is used to generate noninterleaved or
+ progressive JPEG files. The library checks that the scan array
+ defines a valid JPEG scan sequence. (jpeg_simple_progression creates
+ a suitable scan definition array for progressive JPEG.) This is
+ discussed further under "Progressive JPEG support".
+
+boolean do_fancy_downsampling
+ If TRUE, use direct DCT scaling with DCT size > 8 for downsampling
+ of chroma components.
+ If FALSE, use only DCT size <= 8 and simple separate downsampling.
+ Default is TRUE.
+ For better image stability in multiple generation compression cycles
+ it is preferable that this value matches the corresponding
+ do_fancy_upsampling value in decompression.
+
+int smoothing_factor
+ If non-zero, the input image is smoothed; the value should be 1 for
+ minimal smoothing to 100 for maximum smoothing. Consult jcsample.c
+ for details of the smoothing algorithm. The default is zero.
+
+boolean write_JFIF_header
+ If TRUE, a JFIF APP0 marker is emitted. jpeg_set_defaults() and
+ jpeg_set_colorspace() set this TRUE if a JFIF-legal JPEG color space
+ (ie, YCbCr or grayscale) is selected, otherwise FALSE.
+
+UINT8 JFIF_major_version
+UINT8 JFIF_minor_version
+ The version number to be written into the JFIF marker.
+ jpeg_set_defaults() initializes the version to 1.01 (major=minor=1).
+ You should set it to 1.02 (major=1, minor=2) if you plan to write
+ any JFIF 1.02 extension markers.
+
+UINT8 density_unit
+UINT16 X_density
+UINT16 Y_density
+ The resolution information to be written into the JFIF marker;
+ not used otherwise. density_unit may be 0 for unknown,
+ 1 for dots/inch, or 2 for dots/cm. The default values are 0,1,1
+ indicating square pixels of unknown size.
+
+boolean write_Adobe_marker
+ If TRUE, an Adobe APP14 marker is emitted. jpeg_set_defaults() and
+ jpeg_set_colorspace() set this TRUE if JPEG color space RGB, CMYK,
+ or YCCK is selected, otherwise FALSE. It is generally a bad idea
+ to set both write_JFIF_header and write_Adobe_marker. In fact,
+ you probably shouldn't change the default settings at all --- the
+ default behavior ensures that the JPEG file's color space can be
+ recognized by the decoder.
+
+JQUANT_TBL * quant_tbl_ptrs[NUM_QUANT_TBLS]
+ Pointers to coefficient quantization tables, one per table slot,
+ or NULL if no table is defined for a slot. Usually these should
+ be set via one of the above helper routines; jpeg_add_quant_table()
+ is general enough to define any quantization table. The other
+ routines will set up table slot 0 for luminance quality and table
+ slot 1 for chrominance.
+
+int q_scale_factor[NUM_QUANT_TBLS]
+ Linear quantization scaling factors (percentage, initialized 100)
+ for use with jpeg_default_qtables().
+ See rdswitch.c and cjpeg.c for an example of usage.
+ Note that the q_scale_factor[] fields are the "linear" scales, so you
+ have to convert from user-defined ratings via jpeg_quality_scaling().
+ Here is an example code which corresponds to cjpeg -quality 90,70:
+
+ jpeg_set_defaults(cinfo);
+
+ /* Set luminance quality 90. */
+ cinfo->q_scale_factor[0] = jpeg_quality_scaling(90);
+ /* Set chrominance quality 70. */
+ cinfo->q_scale_factor[1] = jpeg_quality_scaling(70);
+
+ jpeg_default_qtables(cinfo, force_baseline);
+
+ CAUTION: You must also set 1x1 subsampling for efficient separate
+ color quality selection, since the default value used by library
+ is 2x2:
+
+ cinfo->comp_info[0].v_samp_factor = 1;
+ cinfo->comp_info[0].h_samp_factor = 1;
+
+JHUFF_TBL * dc_huff_tbl_ptrs[NUM_HUFF_TBLS]
+JHUFF_TBL * ac_huff_tbl_ptrs[NUM_HUFF_TBLS]
+ Pointers to Huffman coding tables, one per table slot, or NULL if
+ no table is defined for a slot. Slots 0 and 1 are filled with the
+ JPEG sample tables by jpeg_set_defaults(). If you need to allocate
+ more table structures, jpeg_alloc_huff_table() may be used.
+ Note that optimal Huffman tables can be computed for an image
+ by setting optimize_coding, as discussed above; there's seldom
+ any need to mess with providing your own Huffman tables.
+
+
+The actual dimensions of the JPEG image that will be written to the file are
+given by the following fields. These are computed from the input image
+dimensions and the compression parameters by jpeg_start_compress(). You can
+also call jpeg_calc_jpeg_dimensions() to obtain the values that will result
+from the current parameter settings. This can be useful if you are trying
+to pick a scaling ratio that will get close to a desired target size.
+
+JDIMENSION jpeg_width Actual dimensions of output image.
+JDIMENSION jpeg_height
+
+
+Per-component parameters are stored in the struct cinfo.comp_info[i] for
+component number i. Note that components here refer to components of the
+JPEG color space, *not* the source image color space. A suitably large
+comp_info[] array is allocated by jpeg_set_defaults(); if you choose not
+to use that routine, it's up to you to allocate the array.
+
+int component_id
+ The one-byte identifier code to be recorded in the JPEG file for
+ this component. For the standard color spaces, we recommend you
+ leave the default values alone.
+
+int h_samp_factor
+int v_samp_factor
+ Horizontal and vertical sampling factors for the component; must
+ be 1..4 according to the JPEG standard. Note that larger sampling
+ factors indicate a higher-resolution component; many people find
+ this behavior quite unintuitive. The default values are 2,2 for
+ luminance components and 1,1 for chrominance components, except
+ for grayscale where 1,1 is used.
+
+int quant_tbl_no
+ Quantization table number for component. The default value is
+ 0 for luminance components and 1 for chrominance components.
+
+int dc_tbl_no
+int ac_tbl_no
+ DC and AC entropy coding table numbers. The default values are
+ 0 for luminance components and 1 for chrominance components.
+
+int component_index
+ Must equal the component's index in comp_info[]. (Beginning in
+ release v6, the compressor library will fill this in automatically;
+ you don't have to.)
+
+
+Decompression parameter selection
+---------------------------------
+
+Decompression parameter selection is somewhat simpler than compression
+parameter selection, since all of the JPEG internal parameters are
+recorded in the source file and need not be supplied by the application.
+(Unless you are working with abbreviated files, in which case see
+"Abbreviated datastreams", below.) Decompression parameters control
+the postprocessing done on the image to deliver it in a format suitable
+for the application's use. Many of the parameters control speed/quality
+tradeoffs, in which faster decompression may be obtained at the price of
+a poorer-quality image. The defaults select the highest quality (slowest)
+processing.
+
+The following fields in the JPEG object are set by jpeg_read_header() and
+may be useful to the application in choosing decompression parameters:
+
+JDIMENSION image_width Width and height of image
+JDIMENSION image_height
+int num_components Number of color components
+J_COLOR_SPACE jpeg_color_space Colorspace of image
+boolean saw_JFIF_marker TRUE if a JFIF APP0 marker was seen
+ UINT8 JFIF_major_version Version information from JFIF marker
+ UINT8 JFIF_minor_version
+ UINT8 density_unit Resolution data from JFIF marker
+ UINT16 X_density
+ UINT16 Y_density
+boolean saw_Adobe_marker TRUE if an Adobe APP14 marker was seen
+ UINT8 Adobe_transform Color transform code from Adobe marker
+
+The JPEG color space, unfortunately, is something of a guess since the JPEG
+standard proper does not provide a way to record it. In practice most files
+adhere to the JFIF or Adobe conventions, and the decoder will recognize these
+correctly. See "Special color spaces", below, for more info.
+
+
+The decompression parameters that determine the basic properties of the
+returned image are:
+
+J_COLOR_SPACE out_color_space
+ Output color space. jpeg_read_header() sets an appropriate default
+ based on jpeg_color_space; typically it will be RGB or grayscale.
+ The application can change this field to request output in a different
+ colorspace. For example, set it to JCS_GRAYSCALE to get grayscale
+ output from a color file. (This is useful for previewing: grayscale
+ output is faster than full color since the color components need not
+ be processed.) Note that not all possible color space transforms are
+ currently implemented; you may need to extend jdcolor.c if you want an
+ unusual conversion.
+
+unsigned int scale_num, scale_denom
+ Scale the image by the fraction scale_num/scale_denom. Currently,
+ the supported scaling ratios are N/8 with all N from 1 to 16. (The
+ library design allows for arbitrary scaling ratios but this is not
+ likely to be implemented any time soon.) The values are initialized
+ by jpeg_read_header() with the source DCT size, which is currently
+ 8/8. If you change only the scale_num value while leaving the other
+ unchanged, then this specifies the DCT scaled size to be applied on
+ the given input, which is currently equivalent to N/8 scaling, since
+ the source DCT size is currently always 8. Smaller scaling ratios
+ permit significantly faster decoding since fewer pixels need be
+ processed and a simpler IDCT method can be used.
+
+boolean quantize_colors
+ If set TRUE, colormapped output will be delivered. Default is FALSE,
+ meaning that full-color output will be delivered.
+
+The next three parameters are relevant only if quantize_colors is TRUE.
+
+int desired_number_of_colors
+ Maximum number of colors to use in generating a library-supplied color
+ map (the actual number of colors is returned in a different field).
+ Default 256. Ignored when the application supplies its own color map.
+
+boolean two_pass_quantize
+ If TRUE, an extra pass over the image is made to select a custom color
+ map for the image. This usually looks a lot better than the one-size-
+ fits-all colormap that is used otherwise. Default is TRUE. Ignored
+ when the application supplies its own color map.
+
+J_DITHER_MODE dither_mode
+ Selects color dithering method. Supported values are:
+ JDITHER_NONE no dithering: fast, very low quality
+ JDITHER_ORDERED ordered dither: moderate speed and quality
+ JDITHER_FS Floyd-Steinberg dither: slow, high quality
+ Default is JDITHER_FS. (At present, ordered dither is implemented
+ only in the single-pass, standard-colormap case. If you ask for
+ ordered dither when two_pass_quantize is TRUE or when you supply
+ an external color map, you'll get F-S dithering.)
+
+When quantize_colors is TRUE, the target color map is described by the next
+two fields. colormap is set to NULL by jpeg_read_header(). The application
+can supply a color map by setting colormap non-NULL and setting
+actual_number_of_colors to the map size. Otherwise, jpeg_start_decompress()
+selects a suitable color map and sets these two fields itself.
+[Implementation restriction: at present, an externally supplied colormap is
+only accepted for 3-component output color spaces.]
+
+JSAMPARRAY colormap
+ The color map, represented as a 2-D pixel array of out_color_components
+ rows and actual_number_of_colors columns. Ignored if not quantizing.
+ CAUTION: if the JPEG library creates its own colormap, the storage
+ pointed to by this field is released by jpeg_finish_decompress().
+ Copy the colormap somewhere else first, if you want to save it.
+
+int actual_number_of_colors
+ The number of colors in the color map.
+
+Additional decompression parameters that the application may set include:
+
+J_DCT_METHOD dct_method
+ Selects the algorithm used for the DCT step. Choices are the same
+ as described above for compression.
+
+boolean do_fancy_upsampling
+ If TRUE, use direct DCT scaling with DCT size > 8 for upsampling
+ of chroma components.
+ If FALSE, use only DCT size <= 8 and simple separate upsampling.
+ Default is TRUE.
+ For better image stability in multiple generation compression cycles
+ it is preferable that this value matches the corresponding
+ do_fancy_downsampling value in compression.
+
+boolean do_block_smoothing
+ If TRUE, interblock smoothing is applied in early stages of decoding
+ progressive JPEG files; if FALSE, not. Default is TRUE. Early
+ progression stages look "fuzzy" with smoothing, "blocky" without.
+ In any case, block smoothing ceases to be applied after the first few
+ AC coefficients are known to full accuracy, so it is relevant only
+ when using buffered-image mode for progressive images.
+
+boolean enable_1pass_quant
+boolean enable_external_quant
+boolean enable_2pass_quant
+ These are significant only in buffered-image mode, which is
+ described in its own section below.
+
+
+The output image dimensions are given by the following fields. These are
+computed from the source image dimensions and the decompression parameters
+by jpeg_start_decompress(). You can also call jpeg_calc_output_dimensions()
+to obtain the values that will result from the current parameter settings.
+This can be useful if you are trying to pick a scaling ratio that will get
+close to a desired target size. It's also important if you are using the
+JPEG library's memory manager to allocate output buffer space, because you
+are supposed to request such buffers *before* jpeg_start_decompress().
+
+JDIMENSION output_width Actual dimensions of output image.
+JDIMENSION output_height
+int out_color_components Number of color components in out_color_space.
+int output_components Number of color components returned.
+int rec_outbuf_height Recommended height of scanline buffer.
+
+When quantizing colors, output_components is 1, indicating a single color map
+index per pixel. Otherwise it equals out_color_components. The output arrays
+are required to be output_width * output_components JSAMPLEs wide.
+
+rec_outbuf_height is the recommended minimum height (in scanlines) of the
+buffer passed to jpeg_read_scanlines(). If the buffer is smaller, the
+library will still work, but time will be wasted due to unnecessary data
+copying. In high-quality modes, rec_outbuf_height is always 1, but some
+faster, lower-quality modes set it to larger values (typically 2 to 4).
+If you are going to ask for a high-speed processing mode, you may as well
+go to the trouble of honoring rec_outbuf_height so as to avoid data copying.
+(An output buffer larger than rec_outbuf_height lines is OK, but won't
+provide any material speed improvement over that height.)
+
+
+Special color spaces
+--------------------
+
+The JPEG standard itself is "color blind" and doesn't specify any particular
+color space. It is customary to convert color data to a luminance/chrominance
+color space before compressing, since this permits greater compression. The
+existing de-facto JPEG file format standards specify YCbCr or grayscale data
+(JFIF), or grayscale, RGB, YCbCr, CMYK, or YCCK (Adobe). For special
+applications such as multispectral images, other color spaces can be used,
+but it must be understood that such files will be unportable.
+
+The JPEG library can handle the most common colorspace conversions (namely
+RGB <=> YCbCr and CMYK <=> YCCK). It can also deal with data of an unknown
+color space, passing it through without conversion. If you deal extensively
+with an unusual color space, you can easily extend the library to understand
+additional color spaces and perform appropriate conversions.
+
+For compression, the source data's color space is specified by field
+in_color_space. This is transformed to the JPEG file's color space given
+by jpeg_color_space. jpeg_set_defaults() chooses a reasonable JPEG color
+space depending on in_color_space, but you can override this by calling
+jpeg_set_colorspace(). Of course you must select a supported transformation.
+jccolor.c currently supports the following transformations:
+ RGB => YCbCr
+ RGB => GRAYSCALE
+ YCbCr => GRAYSCALE
+ CMYK => YCCK
+plus the null transforms: GRAYSCALE => GRAYSCALE, RGB => RGB,
+YCbCr => YCbCr, CMYK => CMYK, YCCK => YCCK, and UNKNOWN => UNKNOWN.
+
+The de-facto file format standards (JFIF and Adobe) specify APPn markers that
+indicate the color space of the JPEG file. It is important to ensure that
+these are written correctly, or omitted if the JPEG file's color space is not
+one of the ones supported by the de-facto standards. jpeg_set_colorspace()
+will set the compression parameters to include or omit the APPn markers
+properly, so long as it is told the truth about the JPEG color space.
+For example, if you are writing some random 3-component color space without
+conversion, don't try to fake out the library by setting in_color_space and
+jpeg_color_space to JCS_YCbCr; use JCS_UNKNOWN. You may want to write an
+APPn marker of your own devising to identify the colorspace --- see "Special
+markers", below.
+
+When told that the color space is UNKNOWN, the library will default to using
+luminance-quality compression parameters for all color components. You may
+well want to change these parameters. See the source code for
+jpeg_set_colorspace(), in jcparam.c, for details.
+
+For decompression, the JPEG file's color space is given in jpeg_color_space,
+and this is transformed to the output color space out_color_space.
+jpeg_read_header's setting of jpeg_color_space can be relied on if the file
+conforms to JFIF or Adobe conventions, but otherwise it is no better than a
+guess. If you know the JPEG file's color space for certain, you can override
+jpeg_read_header's guess by setting jpeg_color_space. jpeg_read_header also
+selects a default output color space based on (its guess of) jpeg_color_space;
+set out_color_space to override this. Again, you must select a supported
+transformation. jdcolor.c currently supports
+ YCbCr => GRAYSCALE
+ YCbCr => RGB
+ GRAYSCALE => RGB
+ YCCK => CMYK
+as well as the null transforms. (Since GRAYSCALE=>RGB is provided, an
+application can force grayscale JPEGs to look like color JPEGs if it only
+wants to handle one case.)
+
+The two-pass color quantizer, jquant2.c, is specialized to handle RGB data
+(it weights distances appropriately for RGB colors). You'll need to modify
+the code if you want to use it for non-RGB output color spaces. Note that
+jquant2.c is used to map to an application-supplied colormap as well as for
+the normal two-pass colormap selection process.
+
+CAUTION: it appears that Adobe Photoshop writes inverted data in CMYK JPEG
+files: 0 represents 100% ink coverage, rather than 0% ink as you'd expect.
+This is arguably a bug in Photoshop, but if you need to work with Photoshop
+CMYK files, you will have to deal with it in your application. We cannot
+"fix" this in the library by inverting the data during the CMYK<=>YCCK
+transform, because that would break other applications, notably Ghostscript.
+Photoshop versions prior to 3.0 write EPS files containing JPEG-encoded CMYK
+data in the same inverted-YCCK representation used in bare JPEG files, but
+the surrounding PostScript code performs an inversion using the PS image
+operator. I am told that Photoshop 3.0 will write uninverted YCCK in
+EPS/JPEG files, and will omit the PS-level inversion. (But the data
+polarity used in bare JPEG files will not change in 3.0.) In either case,
+the JPEG library must not invert the data itself, or else Ghostscript would
+read these EPS files incorrectly.
+
+
+Error handling
+--------------
+
+When the default error handler is used, any error detected inside the JPEG
+routines will cause a message to be printed on stderr, followed by exit().
+You can supply your own error handling routines to override this behavior
+and to control the treatment of nonfatal warnings and trace/debug messages.
+The file example.c illustrates the most common case, which is to have the
+application regain control after an error rather than exiting.
+
+The JPEG library never writes any message directly; it always goes through
+the error handling routines. Three classes of messages are recognized:
+ * Fatal errors: the library cannot continue.
+ * Warnings: the library can continue, but the data is corrupt, and a
+ damaged output image is likely to result.
+ * Trace/informational messages. These come with a trace level indicating
+ the importance of the message; you can control the verbosity of the
+ program by adjusting the maximum trace level that will be displayed.
+
+You may, if you wish, simply replace the entire JPEG error handling module
+(jerror.c) with your own code. However, you can avoid code duplication by
+only replacing some of the routines depending on the behavior you need.
+This is accomplished by calling jpeg_std_error() as usual, but then overriding
+some of the method pointers in the jpeg_error_mgr struct, as illustrated by
+example.c.
+
+All of the error handling routines will receive a pointer to the JPEG object
+(a j_common_ptr which points to either a jpeg_compress_struct or a
+jpeg_decompress_struct; if you need to tell which, test the is_decompressor
+field). This struct includes a pointer to the error manager struct in its
+"err" field. Frequently, custom error handler routines will need to access
+additional data which is not known to the JPEG library or the standard error
+handler. The most convenient way to do this is to embed either the JPEG
+object or the jpeg_error_mgr struct in a larger structure that contains
+additional fields; then casting the passed pointer provides access to the
+additional fields. Again, see example.c for one way to do it. (Beginning
+with IJG version 6b, there is also a void pointer "client_data" in each
+JPEG object, which the application can also use to find related data.
+The library does not touch client_data at all.)
+
+The individual methods that you might wish to override are:
+
+error_exit (j_common_ptr cinfo)
+ Receives control for a fatal error. Information sufficient to
+ generate the error message has been stored in cinfo->err; call
+ output_message to display it. Control must NOT return to the caller;
+ generally this routine will exit() or longjmp() somewhere.
+ Typically you would override this routine to get rid of the exit()
+ default behavior. Note that if you continue processing, you should
+ clean up the JPEG object with jpeg_abort() or jpeg_destroy().
+
+output_message (j_common_ptr cinfo)
+ Actual output of any JPEG message. Override this to send messages
+ somewhere other than stderr. Note that this method does not know
+ how to generate a message, only where to send it.
+
+format_message (j_common_ptr cinfo, char * buffer)
+ Constructs a readable error message string based on the error info
+ stored in cinfo->err. This method is called by output_message. Few
+ applications should need to override this method. One possible
+ reason for doing so is to implement dynamic switching of error message
+ language.
+
+emit_message (j_common_ptr cinfo, int msg_level)
+ Decide whether or not to emit a warning or trace message; if so,
+ calls output_message. The main reason for overriding this method
+ would be to abort on warnings. msg_level is -1 for warnings,
+ 0 and up for trace messages.
+
+Only error_exit() and emit_message() are called from the rest of the JPEG
+library; the other two are internal to the error handler.
+
+The actual message texts are stored in an array of strings which is pointed to
+by the field err->jpeg_message_table. The messages are numbered from 0 to
+err->last_jpeg_message, and it is these code numbers that are used in the
+JPEG library code. You could replace the message texts (for instance, with
+messages in French or German) by changing the message table pointer. See
+jerror.h for the default texts. CAUTION: this table will almost certainly
+change or grow from one library version to the next.
+
+It may be useful for an application to add its own message texts that are
+handled by the same mechanism. The error handler supports a second "add-on"
+message table for this purpose. To define an addon table, set the pointer
+err->addon_message_table and the message numbers err->first_addon_message and
+err->last_addon_message. If you number the addon messages beginning at 1000
+or so, you won't have to worry about conflicts with the library's built-in
+messages. See the sample applications cjpeg/djpeg for an example of using
+addon messages (the addon messages are defined in cderror.h).
+
+Actual invocation of the error handler is done via macros defined in jerror.h:
+ ERREXITn(...) for fatal errors
+ WARNMSn(...) for corrupt-data warnings
+ TRACEMSn(...) for trace and informational messages.
+These macros store the message code and any additional parameters into the
+error handler struct, then invoke the error_exit() or emit_message() method.
+The variants of each macro are for varying numbers of additional parameters.
+The additional parameters are inserted into the generated message using
+standard printf() format codes.
+
+See jerror.h and jerror.c for further details.
+
+
+Compressed data handling (source and destination managers)
+----------------------------------------------------------
+
+The JPEG compression library sends its compressed data to a "destination
+manager" module. The default destination manager just writes the data to a
+stdio stream, but you can provide your own manager to do something else.
+Similarly, the decompression library calls a "source manager" to obtain the
+compressed data; you can provide your own source manager if you want the data
+to come from somewhere other than a stdio stream.
+
+In both cases, compressed data is processed a bufferload at a time: the
+destination or source manager provides a work buffer, and the library invokes
+the manager only when the buffer is filled or emptied. (You could define a
+one-character buffer to force the manager to be invoked for each byte, but
+that would be rather inefficient.) The buffer's size and location are
+controlled by the manager, not by the library. For example, if you desired to
+decompress a JPEG datastream that was all in memory, you could just make the
+buffer pointer and length point to the original data in memory. Then the
+buffer-reload procedure would be invoked only if the decompressor ran off the
+end of the datastream, which would indicate an erroneous datastream.
+
+The work buffer is defined as an array of datatype JOCTET, which is generally
+"char" or "unsigned char". On a machine where char is not exactly 8 bits
+wide, you must define JOCTET as a wider data type and then modify the data
+source and destination modules to transcribe the work arrays into 8-bit units
+on external storage.
+
+A data destination manager struct contains a pointer and count defining the
+next byte to write in the work buffer and the remaining free space:
+
+ JOCTET * next_output_byte; /* => next byte to write in buffer */
+ size_t free_in_buffer; /* # of byte spaces remaining in buffer */
+
+The library increments the pointer and decrements the count until the buffer
+is filled. The manager's empty_output_buffer method must reset the pointer
+and count. The manager is expected to remember the buffer's starting address
+and total size in private fields not visible to the library.
+
+A data destination manager provides three methods:
+
+init_destination (j_compress_ptr cinfo)
+ Initialize destination. This is called by jpeg_start_compress()
+ before any data is actually written. It must initialize
+ next_output_byte and free_in_buffer. free_in_buffer must be
+ initialized to a positive value.
+
+empty_output_buffer (j_compress_ptr cinfo)
+ This is called whenever the buffer has filled (free_in_buffer
+ reaches zero). In typical applications, it should write out the
+ *entire* buffer (use the saved start address and buffer length;
+ ignore the current state of next_output_byte and free_in_buffer).
+ Then reset the pointer & count to the start of the buffer, and
+ return TRUE indicating that the buffer has been dumped.
+ free_in_buffer must be set to a positive value when TRUE is
+ returned. A FALSE return should only be used when I/O suspension is
+ desired (this operating mode is discussed in the next section).
+
+term_destination (j_compress_ptr cinfo)
+ Terminate destination --- called by jpeg_finish_compress() after all
+ data has been written. In most applications, this must flush any
+ data remaining in the buffer. Use either next_output_byte or
+ free_in_buffer to determine how much data is in the buffer.
+
+term_destination() is NOT called by jpeg_abort() or jpeg_destroy(). If you
+want the destination manager to be cleaned up during an abort, you must do it
+yourself.
+
+You will also need code to create a jpeg_destination_mgr struct, fill in its
+method pointers, and insert a pointer to the struct into the "dest" field of
+the JPEG compression object. This can be done in-line in your setup code if
+you like, but it's probably cleaner to provide a separate routine similar to
+the jpeg_stdio_dest() routine of the supplied destination manager.
+
+Decompression source managers follow a parallel design, but with some
+additional frammishes. The source manager struct contains a pointer and count
+defining the next byte to read from the work buffer and the number of bytes
+remaining:
+
+ const JOCTET * next_input_byte; /* => next byte to read from buffer */
+ size_t bytes_in_buffer; /* # of bytes remaining in buffer */
+
+The library increments the pointer and decrements the count until the buffer
+is emptied. The manager's fill_input_buffer method must reset the pointer and
+count. In most applications, the manager must remember the buffer's starting
+address and total size in private fields not visible to the library.
+
+A data source manager provides five methods:
+
+init_source (j_decompress_ptr cinfo)
+ Initialize source. This is called by jpeg_read_header() before any
+ data is actually read. Unlike init_destination(), it may leave
+ bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
+ will occur immediately).
+
+fill_input_buffer (j_decompress_ptr cinfo)
+ This is called whenever bytes_in_buffer has reached zero and more
+ data is wanted. In typical applications, it should read fresh data
+ into the buffer (ignoring the current state of next_input_byte and
+ bytes_in_buffer), reset the pointer & count to the start of the
+ buffer, and return TRUE indicating that the buffer has been reloaded.
+ It is not necessary to fill the buffer entirely, only to obtain at
+ least one more byte. bytes_in_buffer MUST be set to a positive value
+ if TRUE is returned. A FALSE return should only be used when I/O
+ suspension is desired (this mode is discussed in the next section).
+
+skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+ Skip num_bytes worth of data. The buffer pointer and count should
+ be advanced over num_bytes input bytes, refilling the buffer as
+ needed. This is used to skip over a potentially large amount of
+ uninteresting data (such as an APPn marker). In some applications
+ it may be possible to optimize away the reading of the skipped data,
+ but it's not clear that being smart is worth much trouble; large
+ skips are uncommon. bytes_in_buffer may be zero on return.
+ A zero or negative skip count should be treated as a no-op.
+
+resync_to_restart (j_decompress_ptr cinfo, int desired)
+ This routine is called only when the decompressor has failed to find
+ a restart (RSTn) marker where one is expected. Its mission is to
+ find a suitable point for resuming decompression. For most
+ applications, we recommend that you just use the default resync
+ procedure, jpeg_resync_to_restart(). However, if you are able to back
+ up in the input data stream, or if you have a-priori knowledge about
+ the likely location of restart markers, you may be able to do better.
+ Read the read_restart_marker() and jpeg_resync_to_restart() routines
+ in jdmarker.c if you think you'd like to implement your own resync
+ procedure.
+
+term_source (j_decompress_ptr cinfo)
+ Terminate source --- called by jpeg_finish_decompress() after all
+ data has been read. Often a no-op.
+
+For both fill_input_buffer() and skip_input_data(), there is no such thing
+as an EOF return. If the end of the file has been reached, the routine has
+a choice of exiting via ERREXIT() or inserting fake data into the buffer.
+In most cases, generating a warning message and inserting a fake EOI marker
+is the best course of action --- this will allow the decompressor to output
+however much of the image is there. In pathological cases, the decompressor
+may swallow the EOI and again demand data ... just keep feeding it fake EOIs.
+jdatasrc.c illustrates the recommended error recovery behavior.
+
+term_source() is NOT called by jpeg_abort() or jpeg_destroy(). If you want
+the source manager to be cleaned up during an abort, you must do it yourself.
+
+You will also need code to create a jpeg_source_mgr struct, fill in its method
+pointers, and insert a pointer to the struct into the "src" field of the JPEG
+decompression object. This can be done in-line in your setup code if you
+like, but it's probably cleaner to provide a separate routine similar to the
+jpeg_stdio_src() routine of the supplied source manager.
+
+For more information, consult the stdio source and destination managers
+in jdatasrc.c and jdatadst.c.
+
+
+I/O suspension
+--------------
+
+Some applications need to use the JPEG library as an incremental memory-to-
+memory filter: when the compressed data buffer is filled or emptied, they want
+control to return to the outer loop, rather than expecting that the buffer can
+be emptied or reloaded within the data source/destination manager subroutine.
+The library supports this need by providing an "I/O suspension" mode, which we
+describe in this section.
+
+The I/O suspension mode is not a panacea: nothing is guaranteed about the
+maximum amount of time spent in any one call to the library, so it will not
+eliminate response-time problems in single-threaded applications. If you
+need guaranteed response time, we suggest you "bite the bullet" and implement
+a real multi-tasking capability.
+
+To use I/O suspension, cooperation is needed between the calling application
+and the data source or destination manager; you will always need a custom
+source/destination manager. (Please read the previous section if you haven't
+already.) The basic idea is that the empty_output_buffer() or
+fill_input_buffer() routine is a no-op, merely returning FALSE to indicate
+that it has done nothing. Upon seeing this, the JPEG library suspends
+operation and returns to its caller. The surrounding application is
+responsible for emptying or refilling the work buffer before calling the
+JPEG library again.
+
+Compression suspension:
+
+For compression suspension, use an empty_output_buffer() routine that returns
+FALSE; typically it will not do anything else. This will cause the
+compressor to return to the caller of jpeg_write_scanlines(), with the return
+value indicating that not all the supplied scanlines have been accepted.
+The application must make more room in the output buffer, adjust the output
+buffer pointer/count appropriately, and then call jpeg_write_scanlines()
+again, pointing to the first unconsumed scanline.
+
+When forced to suspend, the compressor will backtrack to a convenient stopping
+point (usually the start of the current MCU); it will regenerate some output
+data when restarted. Therefore, although empty_output_buffer() is only
+called when the buffer is filled, you should NOT write out the entire buffer
+after a suspension. Write only the data up to the current position of
+next_output_byte/free_in_buffer. The data beyond that point will be
+regenerated after resumption.
+
+Because of the backtracking behavior, a good-size output buffer is essential
+for efficiency; you don't want the compressor to suspend often. (In fact, an
+overly small buffer could lead to infinite looping, if a single MCU required
+more data than would fit in the buffer.) We recommend a buffer of at least
+several Kbytes. You may want to insert explicit code to ensure that you don't
+call jpeg_write_scanlines() unless there is a reasonable amount of space in
+the output buffer; in other words, flush the buffer before trying to compress
+more data.
+
+The compressor does not allow suspension while it is trying to write JPEG
+markers at the beginning and end of the file. This means that:
+ * At the beginning of a compression operation, there must be enough free
+ space in the output buffer to hold the header markers (typically 600 or
+ so bytes). The recommended buffer size is bigger than this anyway, so
+ this is not a problem as long as you start with an empty buffer. However,
+ this restriction might catch you if you insert large special markers, such
+ as a JFIF thumbnail image, without flushing the buffer afterwards.
+ * When you call jpeg_finish_compress(), there must be enough space in the
+ output buffer to emit any buffered data and the final EOI marker. In the
+ current implementation, half a dozen bytes should suffice for this, but
+ for safety's sake we recommend ensuring that at least 100 bytes are free
+ before calling jpeg_finish_compress().
+
+A more significant restriction is that jpeg_finish_compress() cannot suspend.
+This means you cannot use suspension with multi-pass operating modes, namely
+Huffman code optimization and multiple-scan output. Those modes write the
+whole file during jpeg_finish_compress(), which will certainly result in
+buffer overrun. (Note that this restriction applies only to compression,
+not decompression. The decompressor supports input suspension in all of its
+operating modes.)
+
+Decompression suspension:
+
+For decompression suspension, use a fill_input_buffer() routine that simply
+returns FALSE (except perhaps during error recovery, as discussed below).
+This will cause the decompressor to return to its caller with an indication
+that suspension has occurred. This can happen at four places:
+ * jpeg_read_header(): will return JPEG_SUSPENDED.
+ * jpeg_start_decompress(): will return FALSE, rather than its usual TRUE.
+ * jpeg_read_scanlines(): will return the number of scanlines already
+ completed (possibly 0).
+ * jpeg_finish_decompress(): will return FALSE, rather than its usual TRUE.
+The surrounding application must recognize these cases, load more data into
+the input buffer, and repeat the call. In the case of jpeg_read_scanlines(),
+increment the passed pointers past any scanlines successfully read.
+
+Just as with compression, the decompressor will typically backtrack to a
+convenient restart point before suspending. When fill_input_buffer() is
+called, next_input_byte/bytes_in_buffer point to the current restart point,
+which is where the decompressor will backtrack to if FALSE is returned.
+The data beyond that position must NOT be discarded if you suspend; it needs
+to be re-read upon resumption. In most implementations, you'll need to shift
+this data down to the start of your work buffer and then load more data after
+it. Again, this behavior means that a several-Kbyte work buffer is essential
+for decent performance; furthermore, you should load a reasonable amount of
+new data before resuming decompression. (If you loaded, say, only one new
+byte each time around, you could waste a LOT of cycles.)
+
+The skip_input_data() source manager routine requires special care in a
+suspension scenario. This routine is NOT granted the ability to suspend the
+decompressor; it can decrement bytes_in_buffer to zero, but no more. If the
+requested skip distance exceeds the amount of data currently in the input
+buffer, then skip_input_data() must set bytes_in_buffer to zero and record the
+additional skip distance somewhere else. The decompressor will immediately
+call fill_input_buffer(), which should return FALSE, which will cause a
+suspension return. The surrounding application must then arrange to discard
+the recorded number of bytes before it resumes loading the input buffer.
+(Yes, this design is rather baroque, but it avoids complexity in the far more
+common case where a non-suspending source manager is used.)
+
+If the input data has been exhausted, we recommend that you emit a warning
+and insert dummy EOI markers just as a non-suspending data source manager
+would do. This can be handled either in the surrounding application logic or
+within fill_input_buffer(); the latter is probably more efficient. If
+fill_input_buffer() knows that no more data is available, it can set the
+pointer/count to point to a dummy EOI marker and then return TRUE just as
+though it had read more data in a non-suspending situation.
+
+The decompressor does not attempt to suspend within standard JPEG markers;
+instead it will backtrack to the start of the marker and reprocess the whole
+marker next time. Hence the input buffer must be large enough to hold the
+longest standard marker in the file. Standard JPEG markers should normally
+not exceed a few hundred bytes each (DHT tables are typically the longest).
+We recommend at least a 2K buffer for performance reasons, which is much
+larger than any correct marker is likely to be. For robustness against
+damaged marker length counts, you may wish to insert a test in your
+application for the case that the input buffer is completely full and yet
+the decoder has suspended without consuming any data --- otherwise, if this
+situation did occur, it would lead to an endless loop. (The library can't
+provide this test since it has no idea whether "the buffer is full", or
+even whether there is a fixed-size input buffer.)
+
+The input buffer would need to be 64K to allow for arbitrary COM or APPn
+markers, but these are handled specially: they are either saved into allocated
+memory, or skipped over by calling skip_input_data(). In the former case,
+suspension is handled correctly, and in the latter case, the problem of
+buffer overrun is placed on skip_input_data's shoulders, as explained above.
+Note that if you provide your own marker handling routine for large markers,
+you should consider how to deal with buffer overflow.
+
+Multiple-buffer management:
+
+In some applications it is desirable to store the compressed data in a linked
+list of buffer areas, so as to avoid data copying. This can be handled by
+having empty_output_buffer() or fill_input_buffer() set the pointer and count
+to reference the next available buffer; FALSE is returned only if no more
+buffers are available. Although seemingly straightforward, there is a
+pitfall in this approach: the backtrack that occurs when FALSE is returned
+could back up into an earlier buffer. For example, when fill_input_buffer()
+is called, the current pointer & count indicate the backtrack restart point.
+Since fill_input_buffer() will set the pointer and count to refer to a new
+buffer, the restart position must be saved somewhere else. Suppose a second
+call to fill_input_buffer() occurs in the same library call, and no
+additional input data is available, so fill_input_buffer must return FALSE.
+If the JPEG library has not moved the pointer/count forward in the current
+buffer, then *the correct restart point is the saved position in the prior
+buffer*. Prior buffers may be discarded only after the library establishes
+a restart point within a later buffer. Similar remarks apply for output into
+a chain of buffers.
+
+The library will never attempt to backtrack over a skip_input_data() call,
+so any skipped data can be permanently discarded. You still have to deal
+with the case of skipping not-yet-received data, however.
+
+It's much simpler to use only a single buffer; when fill_input_buffer() is
+called, move any unconsumed data (beyond the current pointer/count) down to
+the beginning of this buffer and then load new data into the remaining buffer
+space. This approach requires a little more data copying but is far easier
+to get right.
+
+
+Progressive JPEG support
+------------------------
+
+Progressive JPEG rearranges the stored data into a series of scans of
+increasing quality. In situations where a JPEG file is transmitted across a
+slow communications link, a decoder can generate a low-quality image very
+quickly from the first scan, then gradually improve the displayed quality as
+more scans are received. The final image after all scans are complete is
+identical to that of a regular (sequential) JPEG file of the same quality
+setting. Progressive JPEG files are often slightly smaller than equivalent
+sequential JPEG files, but the possibility of incremental display is the main
+reason for using progressive JPEG.
+
+The IJG encoder library generates progressive JPEG files when given a
+suitable "scan script" defining how to divide the data into scans.
+Creation of progressive JPEG files is otherwise transparent to the encoder.
+Progressive JPEG files can also be read transparently by the decoder library.
+If the decoding application simply uses the library as defined above, it
+will receive a final decoded image without any indication that the file was
+progressive. Of course, this approach does not allow incremental display.
+To perform incremental display, an application needs to use the decoder
+library's "buffered-image" mode, in which it receives a decoded image
+multiple times.
+
+Each displayed scan requires about as much work to decode as a full JPEG
+image of the same size, so the decoder must be fairly fast in relation to the
+data transmission rate in order to make incremental display useful. However,
+it is possible to skip displaying the image and simply add the incoming bits
+to the decoder's coefficient buffer. This is fast because only Huffman
+decoding need be done, not IDCT, upsampling, colorspace conversion, etc.
+The IJG decoder library allows the application to switch dynamically between
+displaying the image and simply absorbing the incoming bits. A properly
+coded application can automatically adapt the number of display passes to
+suit the time available as the image is received. Also, a final
+higher-quality display cycle can be performed from the buffered data after
+the end of the file is reached.
+
+Progressive compression:
+
+To create a progressive JPEG file (or a multiple-scan sequential JPEG file),
+set the scan_info cinfo field to point to an array of scan descriptors, and
+perform compression as usual. Instead of constructing your own scan list,
+you can call the jpeg_simple_progression() helper routine to create a
+recommended progression sequence; this method should be used by all
+applications that don't want to get involved in the nitty-gritty of
+progressive scan sequence design. (If you want to provide user control of
+scan sequences, you may wish to borrow the scan script reading code found
+in rdswitch.c, so that you can read scan script files just like cjpeg's.)
+When scan_info is not NULL, the compression library will store DCT'd data
+into a buffer array as jpeg_write_scanlines() is called, and will emit all
+the requested scans during jpeg_finish_compress(). This implies that
+multiple-scan output cannot be created with a suspending data destination
+manager, since jpeg_finish_compress() does not support suspension. We
+should also note that the compressor currently forces Huffman optimization
+mode when creating a progressive JPEG file, because the default Huffman
+tables are unsuitable for progressive files.
+
+Progressive decompression:
+
+When buffered-image mode is not used, the decoder library will read all of
+a multi-scan file during jpeg_start_decompress(), so that it can provide a
+final decoded image. (Here "multi-scan" means either progressive or
+multi-scan sequential.) This makes multi-scan files transparent to the
+decoding application. However, existing applications that used suspending
+input with version 5 of the IJG library will need to be modified to check
+for a suspension return from jpeg_start_decompress().
+
+To perform incremental display, an application must use the library's
+buffered-image mode. This is described in the next section.
+
+
+Buffered-image mode
+-------------------
+
+In buffered-image mode, the library stores the partially decoded image in a
+coefficient buffer, from which it can be read out as many times as desired.
+This mode is typically used for incremental display of progressive JPEG files,
+but it can be used with any JPEG file. Each scan of a progressive JPEG file
+adds more data (more detail) to the buffered image. The application can
+display in lockstep with the source file (one display pass per input scan),
+or it can allow input processing to outrun display processing. By making
+input and display processing run independently, it is possible for the
+application to adapt progressive display to a wide range of data transmission
+rates.
+
+The basic control flow for buffered-image decoding is
+
+ jpeg_create_decompress()
+ set data source
+ jpeg_read_header()
+ set overall decompression parameters
+ cinfo.buffered_image = TRUE; /* select buffered-image mode */
+ jpeg_start_decompress()
+ for (each output pass) {
+ adjust output decompression parameters if required
+ jpeg_start_output() /* start a new output pass */
+ for (all scanlines in image) {
+ jpeg_read_scanlines()
+ display scanlines
+ }
+ jpeg_finish_output() /* terminate output pass */
+ }
+ jpeg_finish_decompress()
+ jpeg_destroy_decompress()
+
+This differs from ordinary unbuffered decoding in that there is an additional
+level of looping. The application can choose how many output passes to make
+and how to display each pass.
+
+The simplest approach to displaying progressive images is to do one display
+pass for each scan appearing in the input file. In this case the outer loop
+condition is typically
+ while (! jpeg_input_complete(&cinfo))
+and the start-output call should read
+ jpeg_start_output(&cinfo, cinfo.input_scan_number);
+The second parameter to jpeg_start_output() indicates which scan of the input
+file is to be displayed; the scans are numbered starting at 1 for this
+purpose. (You can use a loop counter starting at 1 if you like, but using
+the library's input scan counter is easier.) The library automatically reads
+data as necessary to complete each requested scan, and jpeg_finish_output()
+advances to the next scan or end-of-image marker (hence input_scan_number
+will be incremented by the time control arrives back at jpeg_start_output()).
+With this technique, data is read from the input file only as needed, and
+input and output processing run in lockstep.
+
+After reading the final scan and reaching the end of the input file, the
+buffered image remains available; it can be read additional times by
+repeating the jpeg_start_output()/jpeg_read_scanlines()/jpeg_finish_output()
+sequence. For example, a useful technique is to use fast one-pass color
+quantization for display passes made while the image is arriving, followed by
+a final display pass using two-pass quantization for highest quality. This
+is done by changing the library parameters before the final output pass.
+Changing parameters between passes is discussed in detail below.
+
+In general the last scan of a progressive file cannot be recognized as such
+until after it is read, so a post-input display pass is the best approach if
+you want special processing in the final pass.
+
+When done with the image, be sure to call jpeg_finish_decompress() to release
+the buffered image (or just use jpeg_destroy_decompress()).
+
+If input data arrives faster than it can be displayed, the application can
+cause the library to decode input data in advance of what's needed to produce
+output. This is done by calling the routine jpeg_consume_input().
+The return value is one of the following:
+ JPEG_REACHED_SOS: reached an SOS marker (the start of a new scan)
+ JPEG_REACHED_EOI: reached the EOI marker (end of image)
+ JPEG_ROW_COMPLETED: completed reading one MCU row of compressed data
+ JPEG_SCAN_COMPLETED: completed reading last MCU row of current scan
+ JPEG_SUSPENDED: suspended before completing any of the above
+(JPEG_SUSPENDED can occur only if a suspending data source is used.) This
+routine can be called at any time after initializing the JPEG object. It
+reads some additional data and returns when one of the indicated significant
+events occurs. (If called after the EOI marker is reached, it will
+immediately return JPEG_REACHED_EOI without attempting to read more data.)
+
+The library's output processing will automatically call jpeg_consume_input()
+whenever the output processing overtakes the input; thus, simple lockstep
+display requires no direct calls to jpeg_consume_input(). But by adding
+calls to jpeg_consume_input(), you can absorb data in advance of what is
+being displayed. This has two benefits:
+ * You can limit buildup of unprocessed data in your input buffer.
+ * You can eliminate extra display passes by paying attention to the
+ state of the library's input processing.
+
+The first of these benefits only requires interspersing calls to
+jpeg_consume_input() with your display operations and any other processing
+you may be doing. To avoid wasting cycles due to backtracking, it's best to
+call jpeg_consume_input() only after a hundred or so new bytes have arrived.
+This is discussed further under "I/O suspension", above. (Note: the JPEG
+library currently is not thread-safe. You must not call jpeg_consume_input()
+from one thread of control if a different library routine is working on the
+same JPEG object in another thread.)
+
+When input arrives fast enough that more than one new scan is available
+before you start a new output pass, you may as well skip the output pass
+corresponding to the completed scan. This occurs for free if you pass
+cinfo.input_scan_number as the target scan number to jpeg_start_output().
+The input_scan_number field is simply the index of the scan currently being
+consumed by the input processor. You can ensure that this is up-to-date by
+emptying the input buffer just before calling jpeg_start_output(): call
+jpeg_consume_input() repeatedly until it returns JPEG_SUSPENDED or
+JPEG_REACHED_EOI.
+
+The target scan number passed to jpeg_start_output() is saved in the
+cinfo.output_scan_number field. The library's output processing calls
+jpeg_consume_input() whenever the current input scan number and row within
+that scan is less than or equal to the current output scan number and row.
+Thus, input processing can "get ahead" of the output processing but is not
+allowed to "fall behind". You can achieve several different effects by
+manipulating this interlock rule. For example, if you pass a target scan
+number greater than the current input scan number, the output processor will
+wait until that scan starts to arrive before producing any output. (To avoid
+an infinite loop, the target scan number is automatically reset to the last
+scan number when the end of image is reached. Thus, if you specify a large
+target scan number, the library will just absorb the entire input file and
+then perform an output pass. This is effectively the same as what
+jpeg_start_decompress() does when you don't select buffered-image mode.)
+When you pass a target scan number equal to the current input scan number,
+the image is displayed no faster than the current input scan arrives. The
+final possibility is to pass a target scan number less than the current input
+scan number; this disables the input/output interlock and causes the output
+processor to simply display whatever it finds in the image buffer, without
+waiting for input. (However, the library will not accept a target scan
+number less than one, so you can't avoid waiting for the first scan.)
+
+When data is arriving faster than the output display processing can advance
+through the image, jpeg_consume_input() will store data into the buffered
+image beyond the point at which the output processing is reading data out
+again. If the input arrives fast enough, it may "wrap around" the buffer to
+the point where the input is more than one whole scan ahead of the output.
+If the output processing simply proceeds through its display pass without
+paying attention to the input, the effect seen on-screen is that the lower
+part of the image is one or more scans better in quality than the upper part.
+Then, when the next output scan is started, you have a choice of what target
+scan number to use. The recommended choice is to use the current input scan
+number at that time, which implies that you've skipped the output scans
+corresponding to the input scans that were completed while you processed the
+previous output scan. In this way, the decoder automatically adapts its
+speed to the arriving data, by skipping output scans as necessary to keep up
+with the arriving data.
+
+When using this strategy, you'll want to be sure that you perform a final
+output pass after receiving all the data; otherwise your last display may not
+be full quality across the whole screen. So the right outer loop logic is
+something like this:
+ do {
+ absorb any waiting input by calling jpeg_consume_input()
+ final_pass = jpeg_input_complete(&cinfo);
+ adjust output decompression parameters if required
+ jpeg_start_output(&cinfo, cinfo.input_scan_number);
+ ...
+ jpeg_finish_output()
+ } while (! final_pass);
+rather than quitting as soon as jpeg_input_complete() returns TRUE. This
+arrangement makes it simple to use higher-quality decoding parameters
+for the final pass. But if you don't want to use special parameters for
+the final pass, the right loop logic is like this:
+ for (;;) {
+ absorb any waiting input by calling jpeg_consume_input()
+ jpeg_start_output(&cinfo, cinfo.input_scan_number);
+ ...
+ jpeg_finish_output()
+ if (jpeg_input_complete(&cinfo) &&
+ cinfo.input_scan_number == cinfo.output_scan_number)
+ break;
+ }
+In this case you don't need to know in advance whether an output pass is to
+be the last one, so it's not necessary to have reached EOF before starting
+the final output pass; rather, what you want to test is whether the output
+pass was performed in sync with the final input scan. This form of the loop
+will avoid an extra output pass whenever the decoder is able (or nearly able)
+to keep up with the incoming data.
+
+When the data transmission speed is high, you might begin a display pass,
+then find that much or all of the file has arrived before you can complete
+the pass. (You can detect this by noting the JPEG_REACHED_EOI return code
+from jpeg_consume_input(), or equivalently by testing jpeg_input_complete().)
+In this situation you may wish to abort the current display pass and start a
+new one using the newly arrived information. To do so, just call
+jpeg_finish_output() and then start a new pass with jpeg_start_output().
+
+A variant strategy is to abort and restart display if more than one complete
+scan arrives during an output pass; this can be detected by noting
+JPEG_REACHED_SOS returns and/or examining cinfo.input_scan_number. This
+idea should be employed with caution, however, since the display process
+might never get to the bottom of the image before being aborted, resulting
+in the lower part of the screen being several passes worse than the upper.
+In most cases it's probably best to abort an output pass only if the whole
+file has arrived and you want to begin the final output pass immediately.
+
+When receiving data across a communication link, we recommend always using
+the current input scan number for the output target scan number; if a
+higher-quality final pass is to be done, it should be started (aborting any
+incomplete output pass) as soon as the end of file is received. However,
+many other strategies are possible. For example, the application can examine
+the parameters of the current input scan and decide whether to display it or
+not. If the scan contains only chroma data, one might choose not to use it
+as the target scan, expecting that the scan will be small and will arrive
+quickly. To skip to the next scan, call jpeg_consume_input() until it
+returns JPEG_REACHED_SOS or JPEG_REACHED_EOI. Or just use the next higher
+number as the target scan for jpeg_start_output(); but that method doesn't
+let you inspect the next scan's parameters before deciding to display it.
+
+
+In buffered-image mode, jpeg_start_decompress() never performs input and
+thus never suspends. An application that uses input suspension with
+buffered-image mode must be prepared for suspension returns from these
+routines:
+* jpeg_start_output() performs input only if you request 2-pass quantization
+ and the target scan isn't fully read yet. (This is discussed below.)
+* jpeg_read_scanlines(), as always, returns the number of scanlines that it
+ was able to produce before suspending.
+* jpeg_finish_output() will read any markers following the target scan,
+ up to the end of the file or the SOS marker that begins another scan.
+ (But it reads no input if jpeg_consume_input() has already reached the
+ end of the file or a SOS marker beyond the target output scan.)
+* jpeg_finish_decompress() will read until the end of file, and thus can
+ suspend if the end hasn't already been reached (as can be tested by
+ calling jpeg_input_complete()).
+jpeg_start_output(), jpeg_finish_output(), and jpeg_finish_decompress()
+all return TRUE if they completed their tasks, FALSE if they had to suspend.
+In the event of a FALSE return, the application must load more input data
+and repeat the call. Applications that use non-suspending data sources need
+not check the return values of these three routines.
+
+
+It is possible to change decoding parameters between output passes in the
+buffered-image mode. The decoder library currently supports only very
+limited changes of parameters. ONLY THE FOLLOWING parameter changes are
+allowed after jpeg_start_decompress() is called:
+* dct_method can be changed before each call to jpeg_start_output().
+ For example, one could use a fast DCT method for early scans, changing
+ to a higher quality method for the final scan.
+* dither_mode can be changed before each call to jpeg_start_output();
+ of course this has no impact if not using color quantization. Typically
+ one would use ordered dither for initial passes, then switch to
+ Floyd-Steinberg dither for the final pass. Caution: changing dither mode
+ can cause more memory to be allocated by the library. Although the amount
+ of memory involved is not large (a scanline or so), it may cause the
+ initial max_memory_to_use specification to be exceeded, which in the worst
+ case would result in an out-of-memory failure.
+* do_block_smoothing can be changed before each call to jpeg_start_output().
+ This setting is relevant only when decoding a progressive JPEG image.
+ During the first DC-only scan, block smoothing provides a very "fuzzy" look
+ instead of the very "blocky" look seen without it; which is better seems a
+ matter of personal taste. But block smoothing is nearly always a win
+ during later stages, especially when decoding a successive-approximation
+ image: smoothing helps to hide the slight blockiness that otherwise shows
+ up on smooth gradients until the lowest coefficient bits are sent.
+* Color quantization mode can be changed under the rules described below.
+ You *cannot* change between full-color and quantized output (because that
+ would alter the required I/O buffer sizes), but you can change which
+ quantization method is used.
+
+When generating color-quantized output, changing quantization method is a
+very useful way of switching between high-speed and high-quality display.
+The library allows you to change among its three quantization methods:
+1. Single-pass quantization to a fixed color cube.
+ Selected by cinfo.two_pass_quantize = FALSE and cinfo.colormap = NULL.
+2. Single-pass quantization to an application-supplied colormap.
+ Selected by setting cinfo.colormap to point to the colormap (the value of
+ two_pass_quantize is ignored); also set cinfo.actual_number_of_colors.
+3. Two-pass quantization to a colormap chosen specifically for the image.
+ Selected by cinfo.two_pass_quantize = TRUE and cinfo.colormap = NULL.
+ (This is the default setting selected by jpeg_read_header, but it is
+ probably NOT what you want for the first pass of progressive display!)
+These methods offer successively better quality and lesser speed. However,
+only the first method is available for quantizing in non-RGB color spaces.
+
+IMPORTANT: because the different quantizer methods have very different
+working-storage requirements, the library requires you to indicate which
+one(s) you intend to use before you call jpeg_start_decompress(). (If we did
+not require this, the max_memory_to_use setting would be a complete fiction.)
+You do this by setting one or more of these three cinfo fields to TRUE:
+ enable_1pass_quant Fixed color cube colormap
+ enable_external_quant Externally-supplied colormap
+ enable_2pass_quant Two-pass custom colormap
+All three are initialized FALSE by jpeg_read_header(). But
+jpeg_start_decompress() automatically sets TRUE the one selected by the
+current two_pass_quantize and colormap settings, so you only need to set the
+enable flags for any other quantization methods you plan to change to later.
+
+After setting the enable flags correctly at jpeg_start_decompress() time, you
+can change to any enabled quantization method by setting two_pass_quantize
+and colormap properly just before calling jpeg_start_output(). The following
+special rules apply:
+1. You must explicitly set cinfo.colormap to NULL when switching to 1-pass
+ or 2-pass mode from a different mode, or when you want the 2-pass
+ quantizer to be re-run to generate a new colormap.
+2. To switch to an external colormap, or to change to a different external
+ colormap than was used on the prior pass, you must call
+ jpeg_new_colormap() after setting cinfo.colormap.
+NOTE: if you want to use the same colormap as was used in the prior pass,
+you should not do either of these things. This will save some nontrivial
+switchover costs.
+(These requirements exist because cinfo.colormap will always be non-NULL
+after completing a prior output pass, since both the 1-pass and 2-pass
+quantizers set it to point to their output colormaps. Thus you have to
+do one of these two things to notify the library that something has changed.
+Yup, it's a bit klugy, but it's necessary to do it this way for backwards
+compatibility.)
+
+Note that in buffered-image mode, the library generates any requested colormap
+during jpeg_start_output(), not during jpeg_start_decompress().
+
+When using two-pass quantization, jpeg_start_output() makes a pass over the
+buffered image to determine the optimum color map; it therefore may take a
+significant amount of time, whereas ordinarily it does little work. The
+progress monitor hook is called during this pass, if defined. It is also
+important to realize that if the specified target scan number is greater than
+or equal to the current input scan number, jpeg_start_output() will attempt
+to consume input as it makes this pass. If you use a suspending data source,
+you need to check for a FALSE return from jpeg_start_output() under these
+conditions. The combination of 2-pass quantization and a not-yet-fully-read
+target scan is the only case in which jpeg_start_output() will consume input.
+
+
+Application authors who support buffered-image mode may be tempted to use it
+for all JPEG images, even single-scan ones. This will work, but it is
+inefficient: there is no need to create an image-sized coefficient buffer for
+single-scan images. Requesting buffered-image mode for such an image wastes
+memory. Worse, it can cost time on large images, since the buffered data has
+to be swapped out or written to a temporary file. If you are concerned about
+maximum performance on baseline JPEG files, you should use buffered-image
+mode only when the incoming file actually has multiple scans. This can be
+tested by calling jpeg_has_multiple_scans(), which will return a correct
+result at any time after jpeg_read_header() completes.
+
+It is also worth noting that when you use jpeg_consume_input() to let input
+processing get ahead of output processing, the resulting pattern of access to
+the coefficient buffer is quite nonsequential. It's best to use the memory
+manager jmemnobs.c if you can (ie, if you have enough real or virtual main
+memory). If not, at least make sure that max_memory_to_use is set as high as
+possible. If the JPEG memory manager has to use a temporary file, you will
+probably see a lot of disk traffic and poor performance. (This could be
+improved with additional work on the memory manager, but we haven't gotten
+around to it yet.)
+
+In some applications it may be convenient to use jpeg_consume_input() for all
+input processing, including reading the initial markers; that is, you may
+wish to call jpeg_consume_input() instead of jpeg_read_header() during
+startup. This works, but note that you must check for JPEG_REACHED_SOS and
+JPEG_REACHED_EOI return codes as the equivalent of jpeg_read_header's codes.
+Once the first SOS marker has been reached, you must call
+jpeg_start_decompress() before jpeg_consume_input() will consume more input;
+it'll just keep returning JPEG_REACHED_SOS until you do. If you read a
+tables-only file this way, jpeg_consume_input() will return JPEG_REACHED_EOI
+without ever returning JPEG_REACHED_SOS; be sure to check for this case.
+If this happens, the decompressor will not read any more input until you call
+jpeg_abort() to reset it. It is OK to call jpeg_consume_input() even when not
+using buffered-image mode, but in that case it's basically a no-op after the
+initial markers have been read: it will just return JPEG_SUSPENDED.
+
+
+Abbreviated datastreams and multiple images
+-------------------------------------------
+
+A JPEG compression or decompression object can be reused to process multiple
+images. This saves a small amount of time per image by eliminating the
+"create" and "destroy" operations, but that isn't the real purpose of the
+feature. Rather, reuse of an object provides support for abbreviated JPEG
+datastreams. Object reuse can also simplify processing a series of images in
+a single input or output file. This section explains these features.
+
+A JPEG file normally contains several hundred bytes worth of quantization
+and Huffman tables. In a situation where many images will be stored or
+transmitted with identical tables, this may represent an annoying overhead.
+The JPEG standard therefore permits tables to be omitted. The standard
+defines three classes of JPEG datastreams:
+ * "Interchange" datastreams contain an image and all tables needed to decode
+ the image. These are the usual kind of JPEG file.
+ * "Abbreviated image" datastreams contain an image, but are missing some or
+ all of the tables needed to decode that image.
+ * "Abbreviated table specification" (henceforth "tables-only") datastreams
+ contain only table specifications.
+To decode an abbreviated image, it is necessary to load the missing table(s)
+into the decoder beforehand. This can be accomplished by reading a separate
+tables-only file. A variant scheme uses a series of images in which the first
+image is an interchange (complete) datastream, while subsequent ones are
+abbreviated and rely on the tables loaded by the first image. It is assumed
+that once the decoder has read a table, it will remember that table until a
+new definition for the same table number is encountered.
+
+It is the application designer's responsibility to figure out how to associate
+the correct tables with an abbreviated image. While abbreviated datastreams
+can be useful in a closed environment, their use is strongly discouraged in
+any situation where data exchange with other applications might be needed.
+Caveat designer.
+
+The JPEG library provides support for reading and writing any combination of
+tables-only datastreams and abbreviated images. In both compression and
+decompression objects, a quantization or Huffman table will be retained for
+the lifetime of the object, unless it is overwritten by a new table definition.
+
+
+To create abbreviated image datastreams, it is only necessary to tell the
+compressor not to emit some or all of the tables it is using. Each
+quantization and Huffman table struct contains a boolean field "sent_table",
+which normally is initialized to FALSE. For each table used by the image, the
+header-writing process emits the table and sets sent_table = TRUE unless it is
+already TRUE. (In normal usage, this prevents outputting the same table
+definition multiple times, as would otherwise occur because the chroma
+components typically share tables.) Thus, setting this field to TRUE before
+calling jpeg_start_compress() will prevent the table from being written at
+all.
+
+If you want to create a "pure" abbreviated image file containing no tables,
+just call "jpeg_suppress_tables(&cinfo, TRUE)" after constructing all the
+tables. If you want to emit some but not all tables, you'll need to set the
+individual sent_table fields directly.
+
+To create an abbreviated image, you must also call jpeg_start_compress()
+with a second parameter of FALSE, not TRUE. Otherwise jpeg_start_compress()
+will force all the sent_table fields to FALSE. (This is a safety feature to
+prevent abbreviated images from being created accidentally.)
+
+To create a tables-only file, perform the same parameter setup that you
+normally would, but instead of calling jpeg_start_compress() and so on, call
+jpeg_write_tables(&cinfo). This will write an abbreviated datastream
+containing only SOI, DQT and/or DHT markers, and EOI. All the quantization
+and Huffman tables that are currently defined in the compression object will
+be emitted unless their sent_tables flag is already TRUE, and then all the
+sent_tables flags will be set TRUE.
+
+A sure-fire way to create matching tables-only and abbreviated image files
+is to proceed as follows:
+
+ create JPEG compression object
+ set JPEG parameters
+ set destination to tables-only file
+ jpeg_write_tables(&cinfo);
+ set destination to image file
+ jpeg_start_compress(&cinfo, FALSE);
+ write data...
+ jpeg_finish_compress(&cinfo);
+
+Since the JPEG parameters are not altered between writing the table file and
+the abbreviated image file, the same tables are sure to be used. Of course,
+you can repeat the jpeg_start_compress() ... jpeg_finish_compress() sequence
+many times to produce many abbreviated image files matching the table file.
+
+You cannot suppress output of the computed Huffman tables when Huffman
+optimization is selected. (If you could, there'd be no way to decode the
+image...) Generally, you don't want to set optimize_coding = TRUE when
+you are trying to produce abbreviated files.
+
+In some cases you might want to compress an image using tables which are
+not stored in the application, but are defined in an interchange or
+tables-only file readable by the application. This can be done by setting up
+a JPEG decompression object to read the specification file, then copying the
+tables into your compression object. See jpeg_copy_critical_parameters()
+for an example of copying quantization tables.
+
+
+To read abbreviated image files, you simply need to load the proper tables
+into the decompression object before trying to read the abbreviated image.
+If the proper tables are stored in the application program, you can just
+allocate the table structs and fill in their contents directly. For example,
+to load a fixed quantization table into table slot "n":
+
+ if (cinfo.quant_tbl_ptrs[n] == NULL)
+ cinfo.quant_tbl_ptrs[n] = jpeg_alloc_quant_table((j_common_ptr) &cinfo);
+ quant_ptr = cinfo.quant_tbl_ptrs[n]; /* quant_ptr is JQUANT_TBL* */
+ for (i = 0; i < 64; i++) {
+ /* Qtable[] is desired quantization table, in natural array order */
+ quant_ptr->quantval[i] = Qtable[i];
+ }
+
+Code to load a fixed Huffman table is typically (for AC table "n"):
+
+ if (cinfo.ac_huff_tbl_ptrs[n] == NULL)
+ cinfo.ac_huff_tbl_ptrs[n] = jpeg_alloc_huff_table((j_common_ptr) &cinfo);
+ huff_ptr = cinfo.ac_huff_tbl_ptrs[n]; /* huff_ptr is JHUFF_TBL* */
+ for (i = 1; i <= 16; i++) {
+ /* counts[i] is number of Huffman codes of length i bits, i=1..16 */
+ huff_ptr->bits[i] = counts[i];
+ }
+ for (i = 0; i < 256; i++) {
+ /* symbols[] is the list of Huffman symbols, in code-length order */
+ huff_ptr->huffval[i] = symbols[i];
+ }
+
+(Note that trying to set cinfo.quant_tbl_ptrs[n] to point directly at a
+constant JQUANT_TBL object is not safe. If the incoming file happened to
+contain a quantization table definition, your master table would get
+overwritten! Instead allocate a working table copy and copy the master table
+into it, as illustrated above. Ditto for Huffman tables, of course.)
+
+You might want to read the tables from a tables-only file, rather than
+hard-wiring them into your application. The jpeg_read_header() call is
+sufficient to read a tables-only file. You must pass a second parameter of
+FALSE to indicate that you do not require an image to be present. Thus, the
+typical scenario is
+
+ create JPEG decompression object
+ set source to tables-only file
+ jpeg_read_header(&cinfo, FALSE);
+ set source to abbreviated image file
+ jpeg_read_header(&cinfo, TRUE);
+ set decompression parameters
+ jpeg_start_decompress(&cinfo);
+ read data...
+ jpeg_finish_decompress(&cinfo);
+
+In some cases, you may want to read a file without knowing whether it contains
+an image or just tables. In that case, pass FALSE and check the return value
+from jpeg_read_header(): it will be JPEG_HEADER_OK if an image was found,
+JPEG_HEADER_TABLES_ONLY if only tables were found. (A third return value,
+JPEG_SUSPENDED, is possible when using a suspending data source manager.)
+Note that jpeg_read_header() will not complain if you read an abbreviated
+image for which you haven't loaded the missing tables; the missing-table check
+occurs later, in jpeg_start_decompress().
+
+
+It is possible to read a series of images from a single source file by
+repeating the jpeg_read_header() ... jpeg_finish_decompress() sequence,
+without releasing/recreating the JPEG object or the data source module.
+(If you did reinitialize, any partial bufferload left in the data source
+buffer at the end of one image would be discarded, causing you to lose the
+start of the next image.) When you use this method, stored tables are
+automatically carried forward, so some of the images can be abbreviated images
+that depend on tables from earlier images.
+
+If you intend to write a series of images into a single destination file,
+you might want to make a specialized data destination module that doesn't
+flush the output buffer at term_destination() time. This would speed things
+up by some trifling amount. Of course, you'd need to remember to flush the
+buffer after the last image. You can make the later images be abbreviated
+ones by passing FALSE to jpeg_start_compress().
+
+
+Special markers
+---------------
+
+Some applications may need to insert or extract special data in the JPEG
+datastream. The JPEG standard provides marker types "COM" (comment) and
+"APP0" through "APP15" (application) to hold application-specific data.
+Unfortunately, the use of these markers is not specified by the standard.
+COM markers are fairly widely used to hold user-supplied text. The JFIF file
+format spec uses APP0 markers with specified initial strings to hold certain
+data. Adobe applications use APP14 markers beginning with the string "Adobe"
+for miscellaneous data. Other APPn markers are rarely seen, but might
+contain almost anything.
+
+If you wish to store user-supplied text, we recommend you use COM markers
+and place readable 7-bit ASCII text in them. Newline conventions are not
+standardized --- expect to find LF (Unix style), CR/LF (DOS style), or CR
+(Mac style). A robust COM reader should be able to cope with random binary
+garbage, including nulls, since some applications generate COM markers
+containing non-ASCII junk. (But yours should not be one of them.)
+
+For program-supplied data, use an APPn marker, and be sure to begin it with an
+identifying string so that you can tell whether the marker is actually yours.
+It's probably best to avoid using APP0 or APP14 for any private markers.
+(NOTE: the upcoming SPIFF standard will use APP8 markers; we recommend you
+not use APP8 markers for any private purposes, either.)
+
+Keep in mind that at most 65533 bytes can be put into one marker, but you
+can have as many markers as you like.
+
+By default, the IJG compression library will write a JFIF APP0 marker if the
+selected JPEG colorspace is grayscale or YCbCr, or an Adobe APP14 marker if
+the selected colorspace is RGB, CMYK, or YCCK. You can disable this, but
+we don't recommend it. The decompression library will recognize JFIF and
+Adobe markers and will set the JPEG colorspace properly when one is found.
+
+
+You can write special markers immediately following the datastream header by
+calling jpeg_write_marker() after jpeg_start_compress() and before the first
+call to jpeg_write_scanlines(). When you do this, the markers appear after
+the SOI and the JFIF APP0 and Adobe APP14 markers (if written), but before
+all else. Specify the marker type parameter as "JPEG_COM" for COM or
+"JPEG_APP0 + n" for APPn. (Actually, jpeg_write_marker will let you write
+any marker type, but we don't recommend writing any other kinds of marker.)
+For example, to write a user comment string pointed to by comment_text:
+ jpeg_write_marker(cinfo, JPEG_COM, comment_text, strlen(comment_text));
+
+If it's not convenient to store all the marker data in memory at once,
+you can instead call jpeg_write_m_header() followed by multiple calls to
+jpeg_write_m_byte(). If you do it this way, it's your responsibility to
+call jpeg_write_m_byte() exactly the number of times given in the length
+parameter to jpeg_write_m_header(). (This method lets you empty the
+output buffer partway through a marker, which might be important when
+using a suspending data destination module. In any case, if you are using
+a suspending destination, you should flush its buffer after inserting
+any special markers. See "I/O suspension".)
+
+Or, if you prefer to synthesize the marker byte sequence yourself,
+you can just cram it straight into the data destination module.
+
+If you are writing JFIF 1.02 extension markers (thumbnail images), don't
+forget to set cinfo.JFIF_minor_version = 2 so that the encoder will write the
+correct JFIF version number in the JFIF header marker. The library's default
+is to write version 1.01, but that's wrong if you insert any 1.02 extension
+markers. (We could probably get away with just defaulting to 1.02, but there
+used to be broken decoders that would complain about unknown minor version
+numbers. To reduce compatibility risks it's safest not to write 1.02 unless
+you are actually using 1.02 extensions.)
+
+
+When reading, two methods of handling special markers are available:
+1. You can ask the library to save the contents of COM and/or APPn markers
+into memory, and then examine them at your leisure afterwards.
+2. You can supply your own routine to process COM and/or APPn markers
+on-the-fly as they are read.
+The first method is simpler to use, especially if you are using a suspending
+data source; writing a marker processor that copes with input suspension is
+not easy (consider what happens if the marker is longer than your available
+input buffer). However, the second method conserves memory since the marker
+data need not be kept around after it's been processed.
+
+For either method, you'd normally set up marker handling after creating a
+decompression object and before calling jpeg_read_header(), because the
+markers of interest will typically be near the head of the file and so will
+be scanned by jpeg_read_header. Once you've established a marker handling
+method, it will be used for the life of that decompression object
+(potentially many datastreams), unless you change it. Marker handling is
+determined separately for COM markers and for each APPn marker code.
+
+
+To save the contents of special markers in memory, call
+ jpeg_save_markers(cinfo, marker_code, length_limit)
+where marker_code is the marker type to save, JPEG_COM or JPEG_APP0+n.
+(To arrange to save all the special marker types, you need to call this
+routine 17 times, for COM and APP0-APP15.) If the incoming marker is longer
+than length_limit data bytes, only length_limit bytes will be saved; this
+parameter allows you to avoid chewing up memory when you only need to see the
+first few bytes of a potentially large marker. If you want to save all the
+data, set length_limit to 0xFFFF; that is enough since marker lengths are only
+16 bits. As a special case, setting length_limit to 0 prevents that marker
+type from being saved at all. (That is the default behavior, in fact.)
+
+After jpeg_read_header() completes, you can examine the special markers by
+following the cinfo->marker_list pointer chain. All the special markers in
+the file appear in this list, in order of their occurrence in the file (but
+omitting any markers of types you didn't ask for). Both the original data
+length and the saved data length are recorded for each list entry; the latter
+will not exceed length_limit for the particular marker type. Note that these
+lengths exclude the marker length word, whereas the stored representation
+within the JPEG file includes it. (Hence the maximum data length is really
+only 65533.)
+
+It is possible that additional special markers appear in the file beyond the
+SOS marker at which jpeg_read_header stops; if so, the marker list will be
+extended during reading of the rest of the file. This is not expected to be
+common, however. If you are short on memory you may want to reset the length
+limit to zero for all marker types after finishing jpeg_read_header, to
+ensure that the max_memory_to_use setting cannot be exceeded due to addition
+of later markers.
+
+The marker list remains stored until you call jpeg_finish_decompress or
+jpeg_abort, at which point the memory is freed and the list is set to empty.
+(jpeg_destroy also releases the storage, of course.)
+
+Note that the library is internally interested in APP0 and APP14 markers;
+if you try to set a small nonzero length limit on these types, the library
+will silently force the length up to the minimum it wants. (But you can set
+a zero length limit to prevent them from being saved at all.) Also, in a
+16-bit environment, the maximum length limit may be constrained to less than
+65533 by malloc() limitations. It is therefore best not to assume that the
+effective length limit is exactly what you set it to be.
+
+
+If you want to supply your own marker-reading routine, you do it by calling
+jpeg_set_marker_processor(). A marker processor routine must have the
+signature
+ boolean jpeg_marker_parser_method (j_decompress_ptr cinfo)
+Although the marker code is not explicitly passed, the routine can find it
+in cinfo->unread_marker. At the time of call, the marker proper has been
+read from the data source module. The processor routine is responsible for
+reading the marker length word and the remaining parameter bytes, if any.
+Return TRUE to indicate success. (FALSE should be returned only if you are
+using a suspending data source and it tells you to suspend. See the standard
+marker processors in jdmarker.c for appropriate coding methods if you need to
+use a suspending data source.)
+
+If you override the default APP0 or APP14 processors, it is up to you to
+recognize JFIF and Adobe markers if you want colorspace recognition to occur
+properly. We recommend copying and extending the default processors if you
+want to do that. (A better idea is to save these marker types for later
+examination by calling jpeg_save_markers(); that method doesn't interfere
+with the library's own processing of these markers.)
+
+jpeg_set_marker_processor() and jpeg_save_markers() are mutually exclusive
+--- if you call one it overrides any previous call to the other, for the
+particular marker type specified.
+
+A simple example of an external COM processor can be found in djpeg.c.
+Also, see jpegtran.c for an example of using jpeg_save_markers.
+
+
+Raw (downsampled) image data
+----------------------------
+
+Some applications need to supply already-downsampled image data to the JPEG
+compressor, or to receive raw downsampled data from the decompressor. The
+library supports this requirement by allowing the application to write or
+read raw data, bypassing the normal preprocessing or postprocessing steps.
+The interface is different from the standard one and is somewhat harder to
+use. If your interest is merely in bypassing color conversion, we recommend
+that you use the standard interface and simply set jpeg_color_space =
+in_color_space (or jpeg_color_space = out_color_space for decompression).
+The mechanism described in this section is necessary only to supply or
+receive downsampled image data, in which not all components have the same
+dimensions.
+
+
+To compress raw data, you must supply the data in the colorspace to be used
+in the JPEG file (please read the earlier section on Special color spaces)
+and downsampled to the sampling factors specified in the JPEG parameters.
+You must supply the data in the format used internally by the JPEG library,
+namely a JSAMPIMAGE array. This is an array of pointers to two-dimensional
+arrays, each of type JSAMPARRAY. Each 2-D array holds the values for one
+color component. This structure is necessary since the components are of
+different sizes. If the image dimensions are not a multiple of the MCU size,
+you must also pad the data correctly (usually, this is done by replicating
+the last column and/or row). The data must be padded to a multiple of a DCT
+block in each component: that is, each downsampled row must contain a
+multiple of 8 valid samples, and there must be a multiple of 8 sample rows
+for each component. (For applications such as conversion of digital TV
+images, the standard image size is usually a multiple of the DCT block size,
+so that no padding need actually be done.)
+
+The procedure for compression of raw data is basically the same as normal
+compression, except that you call jpeg_write_raw_data() in place of
+jpeg_write_scanlines(). Before calling jpeg_start_compress(), you must do
+the following:
+ * Set cinfo->raw_data_in to TRUE. (It is set FALSE by jpeg_set_defaults().)
+ This notifies the library that you will be supplying raw data.
+ Furthermore, set cinfo->do_fancy_downsampling to FALSE if you want to use
+ real downsampled data. (It is set TRUE by jpeg_set_defaults().)
+ * Ensure jpeg_color_space is correct --- an explicit jpeg_set_colorspace()
+ call is a good idea. Note that since color conversion is bypassed,
+ in_color_space is ignored, except that jpeg_set_defaults() uses it to
+ choose the default jpeg_color_space setting.
+ * Ensure the sampling factors, cinfo->comp_info[i].h_samp_factor and
+ cinfo->comp_info[i].v_samp_factor, are correct. Since these indicate the
+ dimensions of the data you are supplying, it's wise to set them
+ explicitly, rather than assuming the library's defaults are what you want.
+
+To pass raw data to the library, call jpeg_write_raw_data() in place of
+jpeg_write_scanlines(). The two routines work similarly except that
+jpeg_write_raw_data takes a JSAMPIMAGE data array rather than JSAMPARRAY.
+The scanlines count passed to and returned from jpeg_write_raw_data is
+measured in terms of the component with the largest v_samp_factor.
+
+jpeg_write_raw_data() processes one MCU row per call, which is to say
+v_samp_factor*DCTSIZE sample rows of each component. The passed num_lines
+value must be at least max_v_samp_factor*DCTSIZE, and the return value will
+be exactly that amount (or possibly some multiple of that amount, in future
+library versions). This is true even on the last call at the bottom of the
+image; don't forget to pad your data as necessary.
+
+The required dimensions of the supplied data can be computed for each
+component as
+ cinfo->comp_info[i].width_in_blocks*DCTSIZE samples per row
+ cinfo->comp_info[i].height_in_blocks*DCTSIZE rows in image
+after jpeg_start_compress() has initialized those fields. If the valid data
+is smaller than this, it must be padded appropriately. For some sampling
+factors and image sizes, additional dummy DCT blocks are inserted to make
+the image a multiple of the MCU dimensions. The library creates such dummy
+blocks itself; it does not read them from your supplied data. Therefore you
+need never pad by more than DCTSIZE samples. An example may help here.
+Assume 2h2v downsampling of YCbCr data, that is
+ cinfo->comp_info[0].h_samp_factor = 2 for Y
+ cinfo->comp_info[0].v_samp_factor = 2
+ cinfo->comp_info[1].h_samp_factor = 1 for Cb
+ cinfo->comp_info[1].v_samp_factor = 1
+ cinfo->comp_info[2].h_samp_factor = 1 for Cr
+ cinfo->comp_info[2].v_samp_factor = 1
+and suppose that the nominal image dimensions (cinfo->image_width and
+cinfo->image_height) are 101x101 pixels. Then jpeg_start_compress() will
+compute downsampled_width = 101 and width_in_blocks = 13 for Y,
+downsampled_width = 51 and width_in_blocks = 7 for Cb and Cr (and the same
+for the height fields). You must pad the Y data to at least 13*8 = 104
+columns and rows, the Cb/Cr data to at least 7*8 = 56 columns and rows. The
+MCU height is max_v_samp_factor = 2 DCT rows so you must pass at least 16
+scanlines on each call to jpeg_write_raw_data(), which is to say 16 actual
+sample rows of Y and 8 each of Cb and Cr. A total of 7 MCU rows are needed,
+so you must pass a total of 7*16 = 112 "scanlines". The last DCT block row
+of Y data is dummy, so it doesn't matter what you pass for it in the data
+arrays, but the scanlines count must total up to 112 so that all of the Cb
+and Cr data gets passed.
+
+Output suspension is supported with raw-data compression: if the data
+destination module suspends, jpeg_write_raw_data() will return 0.
+In this case the same data rows must be passed again on the next call.
+
+
+Decompression with raw data output implies bypassing all postprocessing.
+You must deal with the color space and sampling factors present in the
+incoming file. If your application only handles, say, 2h1v YCbCr data,
+you must check for and fail on other color spaces or other sampling factors.
+The library will not convert to a different color space for you.
+
+To obtain raw data output, set cinfo->raw_data_out = TRUE before
+jpeg_start_decompress() (it is set FALSE by jpeg_read_header()). Be sure to
+verify that the color space and sampling factors are ones you can handle.
+Furthermore, set cinfo->do_fancy_upsampling = FALSE if you want to get real
+downsampled data (it is set TRUE by jpeg_read_header()).
+Then call jpeg_read_raw_data() in place of jpeg_read_scanlines(). The
+decompression process is otherwise the same as usual.
+
+jpeg_read_raw_data() returns one MCU row per call, and thus you must pass a
+buffer of at least max_v_samp_factor*DCTSIZE scanlines (scanline counting is
+the same as for raw-data compression). The buffer you pass must be large
+enough to hold the actual data plus padding to DCT-block boundaries. As with
+compression, any entirely dummy DCT blocks are not processed so you need not
+allocate space for them, but the total scanline count includes them. The
+above example of computing buffer dimensions for raw-data compression is
+equally valid for decompression.
+
+Input suspension is supported with raw-data decompression: if the data source
+module suspends, jpeg_read_raw_data() will return 0. You can also use
+buffered-image mode to read raw data in multiple passes.
+
+
+Really raw data: DCT coefficients
+---------------------------------
+
+It is possible to read or write the contents of a JPEG file as raw DCT
+coefficients. This facility is mainly intended for use in lossless
+transcoding between different JPEG file formats. Other possible applications
+include lossless cropping of a JPEG image, lossless reassembly of a
+multi-strip or multi-tile TIFF/JPEG file into a single JPEG datastream, etc.
+
+To read the contents of a JPEG file as DCT coefficients, open the file and do
+jpeg_read_header() as usual. But instead of calling jpeg_start_decompress()
+and jpeg_read_scanlines(), call jpeg_read_coefficients(). This will read the
+entire image into a set of virtual coefficient-block arrays, one array per
+component. The return value is a pointer to an array of virtual-array
+descriptors. Each virtual array can be accessed directly using the JPEG
+memory manager's access_virt_barray method (see Memory management, below,
+and also read structure.txt's discussion of virtual array handling). Or,
+for simple transcoding to a different JPEG file format, the array list can
+just be handed directly to jpeg_write_coefficients().
+
+Each block in the block arrays contains quantized coefficient values in
+normal array order (not JPEG zigzag order). The block arrays contain only
+DCT blocks containing real data; any entirely-dummy blocks added to fill out
+interleaved MCUs at the right or bottom edges of the image are discarded
+during reading and are not stored in the block arrays. (The size of each
+block array can be determined from the width_in_blocks and height_in_blocks
+fields of the component's comp_info entry.) This is also the data format
+expected by jpeg_write_coefficients().
+
+When you are done using the virtual arrays, call jpeg_finish_decompress()
+to release the array storage and return the decompression object to an idle
+state; or just call jpeg_destroy() if you don't need to reuse the object.
+
+If you use a suspending data source, jpeg_read_coefficients() will return
+NULL if it is forced to suspend; a non-NULL return value indicates successful
+completion. You need not test for a NULL return value when using a
+non-suspending data source.
+
+It is also possible to call jpeg_read_coefficients() to obtain access to the
+decoder's coefficient arrays during a normal decode cycle in buffered-image
+mode. This frammish might be useful for progressively displaying an incoming
+image and then re-encoding it without loss. To do this, decode in buffered-
+image mode as discussed previously, then call jpeg_read_coefficients() after
+the last jpeg_finish_output() call. The arrays will be available for your use
+until you call jpeg_finish_decompress().
+
+
+To write the contents of a JPEG file as DCT coefficients, you must provide
+the DCT coefficients stored in virtual block arrays. You can either pass
+block arrays read from an input JPEG file by jpeg_read_coefficients(), or
+allocate virtual arrays from the JPEG compression object and fill them
+yourself. In either case, jpeg_write_coefficients() is substituted for
+jpeg_start_compress() and jpeg_write_scanlines(). Thus the sequence is
+ * Create compression object
+ * Set all compression parameters as necessary
+ * Request virtual arrays if needed
+ * jpeg_write_coefficients()
+ * jpeg_finish_compress()
+ * Destroy or re-use compression object
+jpeg_write_coefficients() is passed a pointer to an array of virtual block
+array descriptors; the number of arrays is equal to cinfo.num_components.
+
+The virtual arrays need only have been requested, not realized, before
+jpeg_write_coefficients() is called. A side-effect of
+jpeg_write_coefficients() is to realize any virtual arrays that have been
+requested from the compression object's memory manager. Thus, when obtaining
+the virtual arrays from the compression object, you should fill the arrays
+after calling jpeg_write_coefficients(). The data is actually written out
+when you call jpeg_finish_compress(); jpeg_write_coefficients() only writes
+the file header.
+
+When writing raw DCT coefficients, it is crucial that the JPEG quantization
+tables and sampling factors match the way the data was encoded, or the
+resulting file will be invalid. For transcoding from an existing JPEG file,
+we recommend using jpeg_copy_critical_parameters(). This routine initializes
+all the compression parameters to default values (like jpeg_set_defaults()),
+then copies the critical information from a source decompression object.
+The decompression object should have just been used to read the entire
+JPEG input file --- that is, it should be awaiting jpeg_finish_decompress().
+
+jpeg_write_coefficients() marks all tables stored in the compression object
+as needing to be written to the output file (thus, it acts like
+jpeg_start_compress(cinfo, TRUE)). This is for safety's sake, to avoid
+emitting abbreviated JPEG files by accident. If you really want to emit an
+abbreviated JPEG file, call jpeg_suppress_tables(), or set the tables'
+individual sent_table flags, between calling jpeg_write_coefficients() and
+jpeg_finish_compress().
+
+
+Progress monitoring
+-------------------
+
+Some applications may need to regain control from the JPEG library every so
+often. The typical use of this feature is to produce a percent-done bar or
+other progress display. (For a simple example, see cjpeg.c or djpeg.c.)
+Although you do get control back frequently during the data-transferring pass
+(the jpeg_read_scanlines or jpeg_write_scanlines loop), any additional passes
+will occur inside jpeg_finish_compress or jpeg_start_decompress; those
+routines may take a long time to execute, and you don't get control back
+until they are done.
+
+You can define a progress-monitor routine which will be called periodically
+by the library. No guarantees are made about how often this call will occur,
+so we don't recommend you use it for mouse tracking or anything like that.
+At present, a call will occur once per MCU row, scanline, or sample row
+group, whichever unit is convenient for the current processing mode; so the
+wider the image, the longer the time between calls. During the data
+transferring pass, only one call occurs per call of jpeg_read_scanlines or
+jpeg_write_scanlines, so don't pass a large number of scanlines at once if
+you want fine resolution in the progress count. (If you really need to use
+the callback mechanism for time-critical tasks like mouse tracking, you could
+insert additional calls inside some of the library's inner loops.)
+
+To establish a progress-monitor callback, create a struct jpeg_progress_mgr,
+fill in its progress_monitor field with a pointer to your callback routine,
+and set cinfo->progress to point to the struct. The callback will be called
+whenever cinfo->progress is non-NULL. (This pointer is set to NULL by
+jpeg_create_compress or jpeg_create_decompress; the library will not change
+it thereafter. So if you allocate dynamic storage for the progress struct,
+make sure it will live as long as the JPEG object does. Allocating from the
+JPEG memory manager with lifetime JPOOL_PERMANENT will work nicely.) You
+can use the same callback routine for both compression and decompression.
+
+The jpeg_progress_mgr struct contains four fields which are set by the library:
+ long pass_counter; /* work units completed in this pass */
+ long pass_limit; /* total number of work units in this pass */
+ int completed_passes; /* passes completed so far */
+ int total_passes; /* total number of passes expected */
+During any one pass, pass_counter increases from 0 up to (not including)
+pass_limit; the step size is usually but not necessarily 1. The pass_limit
+value may change from one pass to another. The expected total number of
+passes is in total_passes, and the number of passes already completed is in
+completed_passes. Thus the fraction of work completed may be estimated as
+ completed_passes + (pass_counter/pass_limit)
+ --------------------------------------------
+ total_passes
+ignoring the fact that the passes may not be equal amounts of work.
+
+When decompressing, pass_limit can even change within a pass, because it
+depends on the number of scans in the JPEG file, which isn't always known in
+advance. The computed fraction-of-work-done may jump suddenly (if the library
+discovers it has overestimated the number of scans) or even decrease (in the
+opposite case). It is not wise to put great faith in the work estimate.
+
+When using the decompressor's buffered-image mode, the progress monitor work
+estimate is likely to be completely unhelpful, because the library has no way
+to know how many output passes will be demanded of it. Currently, the library
+sets total_passes based on the assumption that there will be one more output
+pass if the input file end hasn't yet been read (jpeg_input_complete() isn't
+TRUE), but no more output passes if the file end has been reached when the
+output pass is started. This means that total_passes will rise as additional
+output passes are requested. If you have a way of determining the input file
+size, estimating progress based on the fraction of the file that's been read
+will probably be more useful than using the library's value.
+
+
+Memory management
+-----------------
+
+This section covers some key facts about the JPEG library's built-in memory
+manager. For more info, please read structure.txt's section about the memory
+manager, and consult the source code if necessary.
+
+All memory and temporary file allocation within the library is done via the
+memory manager. If necessary, you can replace the "back end" of the memory
+manager to control allocation yourself (for example, if you don't want the
+library to use malloc() and free() for some reason).
+
+Some data is allocated "permanently" and will not be freed until the JPEG
+object is destroyed. Most data is allocated "per image" and is freed by
+jpeg_finish_compress, jpeg_finish_decompress, or jpeg_abort. You can call the
+memory manager yourself to allocate structures that will automatically be
+freed at these times. Typical code for this is
+ ptr = (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, size);
+Use JPOOL_PERMANENT to get storage that lasts as long as the JPEG object.
+Use alloc_large instead of alloc_small for anything bigger than a few Kbytes.
+There are also alloc_sarray and alloc_barray routines that automatically
+build 2-D sample or block arrays.
+
+The library's minimum space requirements to process an image depend on the
+image's width, but not on its height, because the library ordinarily works
+with "strip" buffers that are as wide as the image but just a few rows high.
+Some operating modes (eg, two-pass color quantization) require full-image
+buffers. Such buffers are treated as "virtual arrays": only the current strip
+need be in memory, and the rest can be swapped out to a temporary file.
+
+If you use the simplest memory manager back end (jmemnobs.c), then no
+temporary files are used; virtual arrays are simply malloc()'d. Images bigger
+than memory can be processed only if your system supports virtual memory.
+The other memory manager back ends support temporary files of various flavors
+and thus work in machines without virtual memory. They may also be useful on
+Unix machines if you need to process images that exceed available swap space.
+
+When using temporary files, the library will make the in-memory buffers for
+its virtual arrays just big enough to stay within a "maximum memory" setting.
+Your application can set this limit by setting cinfo->mem->max_memory_to_use
+after creating the JPEG object. (Of course, there is still a minimum size for
+the buffers, so the max-memory setting is effective only if it is bigger than
+the minimum space needed.) If you allocate any large structures yourself, you
+must allocate them before jpeg_start_compress() or jpeg_start_decompress() in
+order to have them counted against the max memory limit. Also keep in mind
+that space allocated with alloc_small() is ignored, on the assumption that
+it's too small to be worth worrying about; so a reasonable safety margin
+should be left when setting max_memory_to_use.
+
+If you use the jmemname.c or jmemdos.c memory manager back end, it is
+important to clean up the JPEG object properly to ensure that the temporary
+files get deleted. (This is especially crucial with jmemdos.c, where the
+"temporary files" may be extended-memory segments; if they are not freed,
+DOS will require a reboot to recover the memory.) Thus, with these memory
+managers, it's a good idea to provide a signal handler that will trap any
+early exit from your program. The handler should call either jpeg_abort()
+or jpeg_destroy() for any active JPEG objects. A handler is not needed with
+jmemnobs.c, and shouldn't be necessary with jmemansi.c or jmemmac.c either,
+since the C library is supposed to take care of deleting files made with
+tmpfile().
+
+
+Memory usage
+------------
+
+Working memory requirements while performing compression or decompression
+depend on image dimensions, image characteristics (such as colorspace and
+JPEG process), and operating mode (application-selected options).
+
+As of v6b, the decompressor requires:
+ 1. About 24K in more-or-less-fixed-size data. This varies a bit depending
+ on operating mode and image characteristics (particularly color vs.
+ grayscale), but it doesn't depend on image dimensions.
+ 2. Strip buffers (of size proportional to the image width) for IDCT and
+ upsampling results. The worst case for commonly used sampling factors
+ is about 34 bytes * width in pixels for a color image. A grayscale image
+ only needs about 8 bytes per pixel column.
+ 3. A full-image DCT coefficient buffer is needed to decode a multi-scan JPEG
+ file (including progressive JPEGs), or whenever you select buffered-image
+ mode. This takes 2 bytes/coefficient. At typical 2x2 sampling, that's
+ 3 bytes per pixel for a color image. Worst case (1x1 sampling) requires
+ 6 bytes/pixel. For grayscale, figure 2 bytes/pixel.
+ 4. To perform 2-pass color quantization, the decompressor also needs a
+ 128K color lookup table and a full-image pixel buffer (3 bytes/pixel).
+This does not count any memory allocated by the application, such as a
+buffer to hold the final output image.
+
+The above figures are valid for 8-bit JPEG data precision and a machine with
+32-bit ints. For 12-bit JPEG data, double the size of the strip buffers and
+quantization pixel buffer. The "fixed-size" data will be somewhat smaller
+with 16-bit ints, larger with 64-bit ints. Also, CMYK or other unusual
+color spaces will require different amounts of space.
+
+The full-image coefficient and pixel buffers, if needed at all, do not
+have to be fully RAM resident; you can have the library use temporary
+files instead when the total memory usage would exceed a limit you set.
+(But if your OS supports virtual memory, it's probably better to just use
+jmemnobs and let the OS do the swapping.)
+
+The compressor's memory requirements are similar, except that it has no need
+for color quantization. Also, it needs a full-image DCT coefficient buffer
+if Huffman-table optimization is asked for, even if progressive mode is not
+requested.
+
+If you need more detailed information about memory usage in a particular
+situation, you can enable the MEM_STATS code in jmemmgr.c.
+
+
+Library compile-time options
+----------------------------
+
+A number of compile-time options are available by modifying jmorecfg.h.
+
+The JPEG standard provides for both the baseline 8-bit DCT process and
+a 12-bit DCT process. The IJG code supports 12-bit lossy JPEG if you define
+BITS_IN_JSAMPLE as 12 rather than 8. Note that this causes JSAMPLE to be
+larger than a char, so it affects the surrounding application's image data.
+The sample applications cjpeg and djpeg can support 12-bit mode only for PPM
+and GIF file formats; you must disable the other file formats to compile a
+12-bit cjpeg or djpeg. (install.txt has more information about that.)
+At present, a 12-bit library can handle *only* 12-bit images, not both
+precisions. (If you need to include both 8- and 12-bit libraries in a single
+application, you could probably do it by defining NEED_SHORT_EXTERNAL_NAMES
+for just one of the copies. You'd have to access the 8-bit and 12-bit copies
+from separate application source files. This is untested ... if you try it,
+we'd like to hear whether it works!)
+
+Note that a 12-bit library always compresses in Huffman optimization mode,
+in order to generate valid Huffman tables. This is necessary because our
+default Huffman tables only cover 8-bit data. If you need to output 12-bit
+files in one pass, you'll have to supply suitable default Huffman tables.
+You may also want to supply your own DCT quantization tables; the existing
+quality-scaling code has been developed for 8-bit use, and probably doesn't
+generate especially good tables for 12-bit.
+
+The maximum number of components (color channels) in the image is determined
+by MAX_COMPONENTS. The JPEG standard allows up to 255 components, but we
+expect that few applications will need more than four or so.
+
+On machines with unusual data type sizes, you may be able to improve
+performance or reduce memory space by tweaking the various typedefs in
+jmorecfg.h. In particular, on some RISC CPUs, access to arrays of "short"s
+is quite slow; consider trading memory for speed by making JCOEF, INT16, and
+UINT16 be "int" or "unsigned int". UINT8 is also a candidate to become int.
+You probably don't want to make JSAMPLE be int unless you have lots of memory
+to burn.
+
+You can reduce the size of the library by compiling out various optional
+functions. To do this, undefine xxx_SUPPORTED symbols as necessary.
+
+You can also save a few K by not having text error messages in the library;
+the standard error message table occupies about 5Kb. This is particularly
+reasonable for embedded applications where there's no good way to display
+a message anyway. To do this, remove the creation of the message table
+(jpeg_std_message_table[]) from jerror.c, and alter format_message to do
+something reasonable without it. You could output the numeric value of the
+message code number, for example. If you do this, you can also save a couple
+more K by modifying the TRACEMSn() macros in jerror.h to expand to nothing;
+you don't need trace capability anyway, right?
+
+
+Portability considerations
+--------------------------
+
+The JPEG library has been written to be extremely portable; the sample
+applications cjpeg and djpeg are slightly less so. This section summarizes
+the design goals in this area. (If you encounter any bugs that cause the
+library to be less portable than is claimed here, we'd appreciate hearing
+about them.)
+
+The code works fine on ANSI C, C++, and pre-ANSI C compilers, using any of
+the popular system include file setups, and some not-so-popular ones too.
+See install.txt for configuration procedures.
+
+The code is not dependent on the exact sizes of the C data types. As
+distributed, we make the assumptions that
+ char is at least 8 bits wide
+ short is at least 16 bits wide
+ int is at least 16 bits wide
+ long is at least 32 bits wide
+(These are the minimum requirements of the ANSI C standard.) Wider types will
+work fine, although memory may be used inefficiently if char is much larger
+than 8 bits or short is much bigger than 16 bits. The code should work
+equally well with 16- or 32-bit ints.
+
+In a system where these assumptions are not met, you may be able to make the
+code work by modifying the typedefs in jmorecfg.h. However, you will probably
+have difficulty if int is less than 16 bits wide, since references to plain
+int abound in the code.
+
+char can be either signed or unsigned, although the code runs faster if an
+unsigned char type is available. If char is wider than 8 bits, you will need
+to redefine JOCTET and/or provide custom data source/destination managers so
+that JOCTET represents exactly 8 bits of data on external storage.
+
+The JPEG library proper does not assume ASCII representation of characters.
+But some of the image file I/O modules in cjpeg/djpeg do have ASCII
+dependencies in file-header manipulation; so does cjpeg's select_file_type()
+routine.
+
+The JPEG library does not rely heavily on the C library. In particular, C
+stdio is used only by the data source/destination modules and the error
+handler, all of which are application-replaceable. (cjpeg/djpeg are more
+heavily dependent on stdio.) malloc and free are called only from the memory
+manager "back end" module, so you can use a different memory allocator by
+replacing that one file.
+
+The code generally assumes that C names must be unique in the first 15
+characters. However, global function names can be made unique in the
+first 6 characters by defining NEED_SHORT_EXTERNAL_NAMES.
+
+More info about porting the code may be gleaned by reading jconfig.txt,
+jmorecfg.h, and jinclude.h.
+
+
+Notes for MS-DOS implementors
+-----------------------------
+
+The IJG code is designed to work efficiently in 80x86 "small" or "medium"
+memory models (i.e., data pointers are 16 bits unless explicitly declared
+"far"; code pointers can be either size). You may be able to use small
+model to compile cjpeg or djpeg by itself, but you will probably have to use
+medium model for any larger application. This won't make much difference in
+performance. You *will* take a noticeable performance hit if you use a
+large-data memory model (perhaps 10%-25%), and you should avoid "huge" model
+if at all possible.
+
+The JPEG library typically needs 2Kb-3Kb of stack space. It will also
+malloc about 20K-30K of near heap space while executing (and lots of far
+heap, but that doesn't count in this calculation). This figure will vary
+depending on selected operating mode, and to a lesser extent on image size.
+There is also about 5Kb-6Kb of constant data which will be allocated in the
+near data segment (about 4Kb of this is the error message table).
+Thus you have perhaps 20K available for other modules' static data and near
+heap space before you need to go to a larger memory model. The C library's
+static data will account for several K of this, but that still leaves a good
+deal for your needs. (If you are tight on space, you could reduce the sizes
+of the I/O buffers allocated by jdatasrc.c and jdatadst.c, say from 4K to
+1K. Another possibility is to move the error message table to far memory;
+this should be doable with only localized hacking on jerror.c.)
+
+About 2K of the near heap space is "permanent" memory that will not be
+released until you destroy the JPEG object. This is only an issue if you
+save a JPEG object between compression or decompression operations.
+
+Far data space may also be a tight resource when you are dealing with large
+images. The most memory-intensive case is decompression with two-pass color
+quantization, or single-pass quantization to an externally supplied color
+map. This requires a 128Kb color lookup table plus strip buffers amounting
+to about 40 bytes per column for typical sampling ratios (eg, about 25600
+bytes for a 640-pixel-wide image). You may not be able to process wide
+images if you have large data structures of your own.
+
+Of course, all of these concerns vanish if you use a 32-bit flat-memory-model
+compiler, such as DJGPP or Watcom C. We highly recommend flat model if you
+can use it; the JPEG library is significantly faster in flat model.
diff --git a/Source/LibJPEG/libjpeg.xcodeproj/project.pbxproj b/Source/LibJPEG/libjpeg.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..3fad730
--- /dev/null
+++ b/Source/LibJPEG/libjpeg.xcodeproj/project.pbxproj
@@ -0,0 +1,888 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D70F8C760E0AE23A003F1625 /* jconfig.h in Headers */ = {isa = PBXBuildFile; fileRef = D70F8C750E0AE23A003F1625 /* jconfig.h */; };
+ D725A6FD0E0AFB6F008C767D /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D76558830E0AE74D0038F973 /* CoreServices.framework */; };
+ D725A6FE0E0AFB73008C767D /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libjpeg.a */; };
+ D725A6FF0E0AFB7F008C767D /* cdjpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557780E0AE5360038F973 /* cdjpeg.c */; };
+ D725A7090E0AFB9F008C767D /* djpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A7080E0AFB9F008C767D /* djpeg.c */; };
+ D725A70F0E0AFBEE008C767D /* wrtarga.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A70A0E0AFBEE008C767D /* wrtarga.c */; };
+ D725A7100E0AFBEE008C767D /* wrrle.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A70B0E0AFBEE008C767D /* wrrle.c */; };
+ D725A7110E0AFBEE008C767D /* wrppm.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A70C0E0AFBEE008C767D /* wrppm.c */; };
+ D725A7120E0AFBEE008C767D /* wrgif.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A70D0E0AFBEE008C767D /* wrgif.c */; };
+ D725A7130E0AFBEE008C767D /* wrbmp.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A70E0E0AFBEE008C767D /* wrbmp.c */; };
+ D725A7150E0AFC04008C767D /* rdcolmap.c in Sources */ = {isa = PBXBuildFile; fileRef = D725A7140E0AFC04008C767D /* rdcolmap.c */; };
+ D764935C0E0ADD46007CC7CE /* jversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493070E0ADD46007CC7CE /* jversion.h */; };
+ D764935D0E0ADD46007CC7CE /* jquant2.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493080E0ADD46007CC7CE /* jquant2.c */; };
+ D76493600E0ADD46007CC7CE /* jmemmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = D764930B0E0ADD46007CC7CE /* jmemmgr.c */; };
+ D76493610E0ADD46007CC7CE /* jmemmac.c in Sources */ = {isa = PBXBuildFile; fileRef = D764930C0E0ADD46007CC7CE /* jmemmac.c */; };
+ D76493660E0ADD46007CC7CE /* jidctint.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493110E0ADD46007CC7CE /* jidctint.c */; };
+ D76493670E0ADD46007CC7CE /* jidctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493120E0ADD46007CC7CE /* jidctfst.c */; };
+ D76493680E0ADD46007CC7CE /* jinclude.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493130E0ADD46007CC7CE /* jinclude.h */; };
+ D76493690E0ADD46007CC7CE /* jidctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493140E0ADD46007CC7CE /* jidctflt.c */; };
+ D764936A0E0ADD46007CC7CE /* jfdctint.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493150E0ADD46007CC7CE /* jfdctint.c */; };
+ D764936B0E0ADD46007CC7CE /* jfdctflt.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493160E0ADD46007CC7CE /* jfdctflt.c */; };
+ D764936C0E0ADD46007CC7CE /* jerror.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493170E0ADD46007CC7CE /* jerror.h */; };
+ D764936D0E0ADD46007CC7CE /* jfdctfst.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493180E0ADD46007CC7CE /* jfdctfst.c */; };
+ D764936E0E0ADD46007CC7CE /* jerror.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493190E0ADD46007CC7CE /* jerror.c */; };
+ D764936F0E0ADD46007CC7CE /* jdtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = D764931A0E0ADD46007CC7CE /* jdtrans.c */; };
+ D76493700E0ADD46007CC7CE /* jdsample.c in Sources */ = {isa = PBXBuildFile; fileRef = D764931B0E0ADD46007CC7CE /* jdsample.c */; };
+ D76493710E0ADD46007CC7CE /* jmemsys.h in Headers */ = {isa = PBXBuildFile; fileRef = D764931C0E0ADD46007CC7CE /* jmemsys.h */; };
+ D76493720E0ADD46007CC7CE /* jdmerge.c in Sources */ = {isa = PBXBuildFile; fileRef = D764931D0E0ADD46007CC7CE /* jdmerge.c */; };
+ D76493730E0ADD46007CC7CE /* jdmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = D764931E0E0ADD46007CC7CE /* jdmarker.c */; };
+ D76493740E0ADD46007CC7CE /* jdpostct.c in Sources */ = {isa = PBXBuildFile; fileRef = D764931F0E0ADD46007CC7CE /* jdpostct.c */; };
+ D76493750E0ADD46007CC7CE /* jdmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493200E0ADD46007CC7CE /* jdmainct.c */; };
+ D76493760E0ADD46007CC7CE /* jdhuff.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493210E0ADD46007CC7CE /* jdhuff.h */; };
+ D76493770E0ADD46007CC7CE /* jdmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493220E0ADD46007CC7CE /* jdmaster.c */; };
+ D76493780E0ADD46007CC7CE /* jdinput.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493230E0ADD46007CC7CE /* jdinput.c */; };
+ D76493790E0ADD46007CC7CE /* jdhuff.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493240E0ADD46007CC7CE /* jdhuff.c */; };
+ D764937A0E0ADD46007CC7CE /* jddctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493250E0ADD46007CC7CE /* jddctmgr.c */; };
+ D764937B0E0ADD46007CC7CE /* jdct.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493260E0ADD46007CC7CE /* jdct.h */; };
+ D764937C0E0ADD46007CC7CE /* jdcolor.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493270E0ADD46007CC7CE /* jdcolor.c */; };
+ D764937D0E0ADD46007CC7CE /* jmorecfg.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493280E0ADD46007CC7CE /* jmorecfg.h */; };
+ D764937E0E0ADD46007CC7CE /* jdcoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493290E0ADD46007CC7CE /* jdcoefct.c */; };
+ D764937F0E0ADD46007CC7CE /* jdatadst.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932A0E0ADD46007CC7CE /* jdatadst.c */; };
+ D76493800E0ADD46007CC7CE /* jdapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932B0E0ADD46007CC7CE /* jdapistd.c */; };
+ D76493810E0ADD46007CC7CE /* jdatasrc.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932C0E0ADD46007CC7CE /* jdatasrc.c */; };
+ D76493820E0ADD46007CC7CE /* jdapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932D0E0ADD46007CC7CE /* jdapimin.c */; };
+ D76493830E0ADD46007CC7CE /* jctrans.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932E0E0ADD46007CC7CE /* jctrans.c */; };
+ D76493840E0ADD46007CC7CE /* jcsample.c in Sources */ = {isa = PBXBuildFile; fileRef = D764932F0E0ADD46007CC7CE /* jcsample.c */; };
+ D76493860E0ADD46007CC7CE /* jcprepct.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493310E0ADD46007CC7CE /* jcprepct.c */; };
+ D76493870E0ADD46007CC7CE /* jcparam.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493320E0ADD46007CC7CE /* jcparam.c */; };
+ D76493880E0ADD46007CC7CE /* jpegint.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493330E0ADD46007CC7CE /* jpegint.h */; };
+ D76493890E0ADD46007CC7CE /* jcapimin.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493340E0ADD46007CC7CE /* jcapimin.c */; };
+ D764938A0E0ADD46007CC7CE /* jquant1.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493350E0ADD46007CC7CE /* jquant1.c */; };
+ D764938B0E0ADD46007CC7CE /* jcapistd.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493360E0ADD46007CC7CE /* jcapistd.c */; };
+ D764938C0E0ADD46007CC7CE /* jccoefct.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493370E0ADD46007CC7CE /* jccoefct.c */; };
+ D764938D0E0ADD46007CC7CE /* jutils.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493380E0ADD46007CC7CE /* jutils.c */; };
+ D76493910E0ADD46007CC7CE /* jccolor.c in Sources */ = {isa = PBXBuildFile; fileRef = D764933C0E0ADD46007CC7CE /* jccolor.c */; };
+ D76493930E0ADD46007CC7CE /* jchuff.c in Sources */ = {isa = PBXBuildFile; fileRef = D764933E0E0ADD46007CC7CE /* jchuff.c */; };
+ D76493950E0ADD46007CC7CE /* jcdctmgr.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493400E0ADD46007CC7CE /* jcdctmgr.c */; };
+ D76493960E0ADD46007CC7CE /* jchuff.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493410E0ADD46007CC7CE /* jchuff.h */; };
+ D76493990E0ADD46007CC7CE /* jcomapi.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493440E0ADD46007CC7CE /* jcomapi.c */; };
+ D764939A0E0ADD46007CC7CE /* jcmaster.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493450E0ADD46007CC7CE /* jcmaster.c */; };
+ D764939B0E0ADD46007CC7CE /* jcmarker.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493460E0ADD46007CC7CE /* jcmarker.c */; };
+ D764939C0E0ADD46007CC7CE /* jcmainct.c in Sources */ = {isa = PBXBuildFile; fileRef = D76493470E0ADD46007CC7CE /* jcmainct.c */; };
+ D764939D0E0ADD46007CC7CE /* jpeglib.h in Headers */ = {isa = PBXBuildFile; fileRef = D76493480E0ADD46007CC7CE /* jpeglib.h */; };
+ D76493A00E0ADD46007CC7CE /* jcinit.c in Sources */ = {isa = PBXBuildFile; fileRef = D764934B0E0ADD46007CC7CE /* jcinit.c */; };
+ D765575B0E0AE43D0038F973 /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libjpeg.a */; };
+ D765576B0E0AE4890038F973 /* cjpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557690E0AE4820038F973 /* cjpeg.c */; };
+ D765576D0E0AE4B50038F973 /* rdppm.c in Sources */ = {isa = PBXBuildFile; fileRef = D765576C0E0AE4B50038F973 /* rdppm.c */; };
+ D765576F0E0AE4D10038F973 /* rdgif.c in Sources */ = {isa = PBXBuildFile; fileRef = D765576E0E0AE4D10038F973 /* rdgif.c */; };
+ D76557710E0AE4DF0038F973 /* rdtarga.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557700E0AE4DF0038F973 /* rdtarga.c */; };
+ D76557740E0AE4FD0038F973 /* rdswitch.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557720E0AE4FD0038F973 /* rdswitch.c */; };
+ D76557750E0AE4FD0038F973 /* rdrle.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557730E0AE4FD0038F973 /* rdrle.c */; };
+ D76557770E0AE5180038F973 /* rdbmp.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557760E0AE5180038F973 /* rdbmp.c */; };
+ D76557790E0AE5360038F973 /* cdjpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557780E0AE5360038F973 /* cdjpeg.c */; };
+ D76558840E0AE74D0038F973 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D76558830E0AE74D0038F973 /* CoreServices.framework */; };
+ D76E029C10D06BDA00F2706E /* jaricom.c in Sources */ = {isa = PBXBuildFile; fileRef = D76E029910D06BDA00F2706E /* jaricom.c */; };
+ D76E029D10D06BDA00F2706E /* jcarith.c in Sources */ = {isa = PBXBuildFile; fileRef = D76E029A10D06BDA00F2706E /* jcarith.c */; };
+ D76E029E10D06BDA00F2706E /* jdarith.c in Sources */ = {isa = PBXBuildFile; fileRef = D76E029B10D06BDA00F2706E /* jdarith.c */; };
+ D7DBEE190E2BF8B90099D25F /* transupp.c in Sources */ = {isa = PBXBuildFile; fileRef = D7EFF60F0E0AFCF80025E981 /* transupp.c */; };
+ D7DBEE1A0E2BF8B90099D25F /* transupp.h in Headers */ = {isa = PBXBuildFile; fileRef = D7EFF60E0E0AFCF80025E981 /* transupp.h */; };
+ D7EFF6070E0AFC8B0025E981 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D76558830E0AE74D0038F973 /* CoreServices.framework */; };
+ D7EFF6080E0AFC8F0025E981 /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libjpeg.a */; };
+ D7EFF60A0E0AFCA30025E981 /* cdjpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557780E0AE5360038F973 /* cdjpeg.c */; };
+ D7EFF60C0E0AFCC50025E981 /* jpegtran.c in Sources */ = {isa = PBXBuildFile; fileRef = D7EFF60B0E0AFCC50025E981 /* jpegtran.c */; };
+ D7EFF60D0E0AFCD10025E981 /* rdswitch.c in Sources */ = {isa = PBXBuildFile; fileRef = D76557720E0AE4FD0038F973 /* rdswitch.c */; };
+ D7EFF6100E0AFCF80025E981 /* transupp.c in Sources */ = {isa = PBXBuildFile; fileRef = D7EFF60F0E0AFCF80025E981 /* transupp.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ D725A6FB0E0AFB64008C767D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libjpeg;
+ };
+ D76557590E0AE42B0038F973 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libjpeg;
+ };
+ D77878710E0AFF8200C99215 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D76557540E0AE4150038F973;
+ remoteInfo = cjpeg;
+ };
+ D77878730E0AFF8200C99215 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D725A6F60E0AFB5F008C767D;
+ remoteInfo = djpeg;
+ };
+ D77878750E0AFF8200C99215 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D7EFF6000E0AFC7D0025E981;
+ remoteInfo = jpegtran;
+ };
+ D7EFF6050E0AFC820025E981 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libjpeg;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libjpeg.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjpeg.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D70F8C750E0AE23A003F1625 /* jconfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jconfig.h; sourceTree = SOURCE_ROOT; };
+ D725A6EF0E0AE8D6008C767D /* cdjpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cdjpeg.h; sourceTree = SOURCE_ROOT; };
+ D725A6F70E0AFB5F008C767D /* djpeg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = djpeg; sourceTree = BUILT_PRODUCTS_DIR; };
+ D725A7080E0AFB9F008C767D /* djpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = djpeg.c; sourceTree = SOURCE_ROOT; };
+ D725A70A0E0AFBEE008C767D /* wrtarga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrtarga.c; sourceTree = SOURCE_ROOT; };
+ D725A70B0E0AFBEE008C767D /* wrrle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrrle.c; sourceTree = SOURCE_ROOT; };
+ D725A70C0E0AFBEE008C767D /* wrppm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrppm.c; sourceTree = SOURCE_ROOT; };
+ D725A70D0E0AFBEE008C767D /* wrgif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrgif.c; sourceTree = SOURCE_ROOT; };
+ D725A70E0E0AFBEE008C767D /* wrbmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrbmp.c; sourceTree = SOURCE_ROOT; };
+ D725A7140E0AFC04008C767D /* rdcolmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdcolmap.c; sourceTree = SOURCE_ROOT; };
+ D76493070E0ADD46007CC7CE /* jversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jversion.h; sourceTree = "<group>"; };
+ D76493080E0ADD46007CC7CE /* jquant2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant2.c; sourceTree = SOURCE_ROOT; };
+ D764930B0E0ADD46007CC7CE /* jmemmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemmgr.c; sourceTree = SOURCE_ROOT; };
+ D764930C0E0ADD46007CC7CE /* jmemmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jmemmac.c; sourceTree = SOURCE_ROOT; };
+ D76493110E0ADD46007CC7CE /* jidctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctint.c; sourceTree = SOURCE_ROOT; };
+ D76493120E0ADD46007CC7CE /* jidctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctfst.c; sourceTree = SOURCE_ROOT; };
+ D76493130E0ADD46007CC7CE /* jinclude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jinclude.h; sourceTree = "<group>"; };
+ D76493140E0ADD46007CC7CE /* jidctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jidctflt.c; sourceTree = SOURCE_ROOT; };
+ D76493150E0ADD46007CC7CE /* jfdctint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctint.c; sourceTree = SOURCE_ROOT; };
+ D76493160E0ADD46007CC7CE /* jfdctflt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctflt.c; sourceTree = SOURCE_ROOT; };
+ D76493170E0ADD46007CC7CE /* jerror.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jerror.h; sourceTree = "<group>"; };
+ D76493180E0ADD46007CC7CE /* jfdctfst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jfdctfst.c; sourceTree = SOURCE_ROOT; };
+ D76493190E0ADD46007CC7CE /* jerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jerror.c; sourceTree = SOURCE_ROOT; };
+ D764931A0E0ADD46007CC7CE /* jdtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdtrans.c; sourceTree = SOURCE_ROOT; };
+ D764931B0E0ADD46007CC7CE /* jdsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdsample.c; sourceTree = SOURCE_ROOT; };
+ D764931C0E0ADD46007CC7CE /* jmemsys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmemsys.h; sourceTree = "<group>"; };
+ D764931D0E0ADD46007CC7CE /* jdmerge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmerge.c; sourceTree = SOURCE_ROOT; };
+ D764931E0E0ADD46007CC7CE /* jdmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmarker.c; sourceTree = SOURCE_ROOT; };
+ D764931F0E0ADD46007CC7CE /* jdpostct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdpostct.c; sourceTree = SOURCE_ROOT; };
+ D76493200E0ADD46007CC7CE /* jdmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmainct.c; sourceTree = SOURCE_ROOT; };
+ D76493210E0ADD46007CC7CE /* jdhuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdhuff.h; sourceTree = "<group>"; };
+ D76493220E0ADD46007CC7CE /* jdmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdmaster.c; sourceTree = SOURCE_ROOT; };
+ D76493230E0ADD46007CC7CE /* jdinput.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdinput.c; sourceTree = SOURCE_ROOT; };
+ D76493240E0ADD46007CC7CE /* jdhuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdhuff.c; sourceTree = SOURCE_ROOT; };
+ D76493250E0ADD46007CC7CE /* jddctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jddctmgr.c; sourceTree = SOURCE_ROOT; };
+ D76493260E0ADD46007CC7CE /* jdct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdct.h; sourceTree = "<group>"; };
+ D76493270E0ADD46007CC7CE /* jdcolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcolor.c; sourceTree = SOURCE_ROOT; };
+ D76493280E0ADD46007CC7CE /* jmorecfg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jmorecfg.h; sourceTree = "<group>"; };
+ D76493290E0ADD46007CC7CE /* jdcoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdcoefct.c; sourceTree = SOURCE_ROOT; };
+ D764932A0E0ADD46007CC7CE /* jdatadst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatadst.c; sourceTree = SOURCE_ROOT; };
+ D764932B0E0ADD46007CC7CE /* jdapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapistd.c; sourceTree = SOURCE_ROOT; };
+ D764932C0E0ADD46007CC7CE /* jdatasrc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdatasrc.c; sourceTree = SOURCE_ROOT; };
+ D764932D0E0ADD46007CC7CE /* jdapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdapimin.c; sourceTree = SOURCE_ROOT; };
+ D764932E0E0ADD46007CC7CE /* jctrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jctrans.c; sourceTree = SOURCE_ROOT; };
+ D764932F0E0ADD46007CC7CE /* jcsample.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcsample.c; sourceTree = SOURCE_ROOT; };
+ D76493310E0ADD46007CC7CE /* jcprepct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcprepct.c; sourceTree = SOURCE_ROOT; };
+ D76493320E0ADD46007CC7CE /* jcparam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcparam.c; sourceTree = SOURCE_ROOT; };
+ D76493330E0ADD46007CC7CE /* jpegint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpegint.h; sourceTree = "<group>"; };
+ D76493340E0ADD46007CC7CE /* jcapimin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapimin.c; sourceTree = SOURCE_ROOT; };
+ D76493350E0ADD46007CC7CE /* jquant1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jquant1.c; sourceTree = SOURCE_ROOT; };
+ D76493360E0ADD46007CC7CE /* jcapistd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcapistd.c; sourceTree = SOURCE_ROOT; };
+ D76493370E0ADD46007CC7CE /* jccoefct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccoefct.c; sourceTree = SOURCE_ROOT; };
+ D76493380E0ADD46007CC7CE /* jutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jutils.c; sourceTree = SOURCE_ROOT; };
+ D764933C0E0ADD46007CC7CE /* jccolor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jccolor.c; sourceTree = SOURCE_ROOT; };
+ D764933E0E0ADD46007CC7CE /* jchuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jchuff.c; sourceTree = SOURCE_ROOT; };
+ D76493400E0ADD46007CC7CE /* jcdctmgr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcdctmgr.c; sourceTree = SOURCE_ROOT; };
+ D76493410E0ADD46007CC7CE /* jchuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jchuff.h; sourceTree = "<group>"; };
+ D76493440E0ADD46007CC7CE /* jcomapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcomapi.c; sourceTree = SOURCE_ROOT; };
+ D76493450E0ADD46007CC7CE /* jcmaster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmaster.c; sourceTree = SOURCE_ROOT; };
+ D76493460E0ADD46007CC7CE /* jcmarker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmarker.c; sourceTree = SOURCE_ROOT; };
+ D76493470E0ADD46007CC7CE /* jcmainct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcmainct.c; sourceTree = SOURCE_ROOT; };
+ D76493480E0ADD46007CC7CE /* jpeglib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpeglib.h; sourceTree = "<group>"; };
+ D764934B0E0ADD46007CC7CE /* jcinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcinit.c; sourceTree = SOURCE_ROOT; };
+ D76557550E0AE4150038F973 /* cjpeg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cjpeg; sourceTree = BUILT_PRODUCTS_DIR; };
+ D76557690E0AE4820038F973 /* cjpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cjpeg.c; sourceTree = SOURCE_ROOT; };
+ D765576C0E0AE4B50038F973 /* rdppm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdppm.c; sourceTree = SOURCE_ROOT; };
+ D765576E0E0AE4D10038F973 /* rdgif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdgif.c; sourceTree = SOURCE_ROOT; };
+ D76557700E0AE4DF0038F973 /* rdtarga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdtarga.c; sourceTree = SOURCE_ROOT; };
+ D76557720E0AE4FD0038F973 /* rdswitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdswitch.c; sourceTree = SOURCE_ROOT; };
+ D76557730E0AE4FD0038F973 /* rdrle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdrle.c; sourceTree = SOURCE_ROOT; };
+ D76557760E0AE5180038F973 /* rdbmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rdbmp.c; sourceTree = SOURCE_ROOT; };
+ D76557780E0AE5360038F973 /* cdjpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cdjpeg.c; sourceTree = SOURCE_ROOT; };
+ D76558830E0AE74D0038F973 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
+ D76E029910D06BDA00F2706E /* jaricom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jaricom.c; sourceTree = SOURCE_ROOT; };
+ D76E029A10D06BDA00F2706E /* jcarith.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jcarith.c; sourceTree = SOURCE_ROOT; };
+ D76E029B10D06BDA00F2706E /* jdarith.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jdarith.c; sourceTree = SOURCE_ROOT; };
+ D778786D0E0AFF7B00C99215 /* tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tests; sourceTree = BUILT_PRODUCTS_DIR; };
+ D7A4EEE50E0ADE9200D6883C /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../../../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D7A4EEE60E0ADE9200D6883C /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../../../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D7EFF6010E0AFC7D0025E981 /* jpegtran */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jpegtran; sourceTree = BUILT_PRODUCTS_DIR; };
+ D7EFF60B0E0AFCC50025E981 /* jpegtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jpegtran.c; sourceTree = SOURCE_ROOT; };
+ D7EFF60E0E0AFCF80025E981 /* transupp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transupp.h; sourceTree = "<group>"; };
+ D7EFF60F0E0AFCF80025E981 /* transupp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = transupp.c; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D725A6F50E0AFB5F008C767D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D725A6FD0E0AFB6F008C767D /* CoreServices.framework in Frameworks */,
+ D725A6FE0E0AFB73008C767D /* libjpeg.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D76557530E0AE4150038F973 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D765575B0E0AE43D0038F973 /* libjpeg.a in Frameworks */,
+ D76558840E0AE74D0038F973 /* CoreServices.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D7EFF5FF0E0AFC7D0025E981 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7EFF6070E0AFC8B0025E981 /* CoreServices.framework in Frameworks */,
+ D7EFF6080E0AFC8F0025E981 /* libjpeg.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libjpeg */ = {
+ isa = PBXGroup;
+ children = (
+ D7A4EEE50E0ADE9200D6883C /* MacConfigExternalDebug.xcconfig */,
+ D7A4EEE60E0ADE9200D6883C /* MacConfigExternalRelease.xcconfig */,
+ D7C07B750E0AE0730096EB18 /* Headers */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ D76557670E0AE4510038F973 /* Utilities Sources (non-lib) */,
+ D76557EB0E0AE58D0038F973 /* External Libraries */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libjpeg;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D76E029910D06BDA00F2706E /* jaricom.c */,
+ D76E029A10D06BDA00F2706E /* jcarith.c */,
+ D76E029B10D06BDA00F2706E /* jdarith.c */,
+ D76493080E0ADD46007CC7CE /* jquant2.c */,
+ D764930B0E0ADD46007CC7CE /* jmemmgr.c */,
+ D764930C0E0ADD46007CC7CE /* jmemmac.c */,
+ D76493110E0ADD46007CC7CE /* jidctint.c */,
+ D76493120E0ADD46007CC7CE /* jidctfst.c */,
+ D76493140E0ADD46007CC7CE /* jidctflt.c */,
+ D76493150E0ADD46007CC7CE /* jfdctint.c */,
+ D76493160E0ADD46007CC7CE /* jfdctflt.c */,
+ D76493180E0ADD46007CC7CE /* jfdctfst.c */,
+ D76493190E0ADD46007CC7CE /* jerror.c */,
+ D764931A0E0ADD46007CC7CE /* jdtrans.c */,
+ D764931B0E0ADD46007CC7CE /* jdsample.c */,
+ D764931D0E0ADD46007CC7CE /* jdmerge.c */,
+ D764931E0E0ADD46007CC7CE /* jdmarker.c */,
+ D764931F0E0ADD46007CC7CE /* jdpostct.c */,
+ D76493200E0ADD46007CC7CE /* jdmainct.c */,
+ D76493220E0ADD46007CC7CE /* jdmaster.c */,
+ D76493230E0ADD46007CC7CE /* jdinput.c */,
+ D76493240E0ADD46007CC7CE /* jdhuff.c */,
+ D76493250E0ADD46007CC7CE /* jddctmgr.c */,
+ D76493270E0ADD46007CC7CE /* jdcolor.c */,
+ D76493290E0ADD46007CC7CE /* jdcoefct.c */,
+ D764932A0E0ADD46007CC7CE /* jdatadst.c */,
+ D764932B0E0ADD46007CC7CE /* jdapistd.c */,
+ D764932C0E0ADD46007CC7CE /* jdatasrc.c */,
+ D764932D0E0ADD46007CC7CE /* jdapimin.c */,
+ D764932E0E0ADD46007CC7CE /* jctrans.c */,
+ D764932F0E0ADD46007CC7CE /* jcsample.c */,
+ D76493310E0ADD46007CC7CE /* jcprepct.c */,
+ D76493320E0ADD46007CC7CE /* jcparam.c */,
+ D76493340E0ADD46007CC7CE /* jcapimin.c */,
+ D76493350E0ADD46007CC7CE /* jquant1.c */,
+ D76493360E0ADD46007CC7CE /* jcapistd.c */,
+ D76493370E0ADD46007CC7CE /* jccoefct.c */,
+ D76493380E0ADD46007CC7CE /* jutils.c */,
+ D764933C0E0ADD46007CC7CE /* jccolor.c */,
+ D764933E0E0ADD46007CC7CE /* jchuff.c */,
+ D76493400E0ADD46007CC7CE /* jcdctmgr.c */,
+ D76493440E0ADD46007CC7CE /* jcomapi.c */,
+ D76493450E0ADD46007CC7CE /* jcmaster.c */,
+ D76493460E0ADD46007CC7CE /* jcmarker.c */,
+ D76493470E0ADD46007CC7CE /* jcmainct.c */,
+ D764934B0E0ADD46007CC7CE /* jcinit.c */,
+ D7EFF60E0E0AFCF80025E981 /* transupp.h */,
+ D7EFF60F0E0AFCF80025E981 /* transupp.c */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libjpeg.a */,
+ D76557550E0AE4150038F973 /* cjpeg */,
+ D725A6F70E0AFB5F008C767D /* djpeg */,
+ D7EFF6010E0AFC7D0025E981 /* jpegtran */,
+ D778786D0E0AFF7B00C99215 /* tests */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ D76557670E0AE4510038F973 /* Utilities Sources (non-lib) */ = {
+ isa = PBXGroup;
+ children = (
+ D725A6EF0E0AE8D6008C767D /* cdjpeg.h */,
+ D76557690E0AE4820038F973 /* cjpeg.c */,
+ D765576C0E0AE4B50038F973 /* rdppm.c */,
+ D765576E0E0AE4D10038F973 /* rdgif.c */,
+ D76557700E0AE4DF0038F973 /* rdtarga.c */,
+ D76557730E0AE4FD0038F973 /* rdrle.c */,
+ D76557760E0AE5180038F973 /* rdbmp.c */,
+ D76557720E0AE4FD0038F973 /* rdswitch.c */,
+ D76557780E0AE5360038F973 /* cdjpeg.c */,
+ D725A7080E0AFB9F008C767D /* djpeg.c */,
+ D725A70A0E0AFBEE008C767D /* wrtarga.c */,
+ D725A70B0E0AFBEE008C767D /* wrrle.c */,
+ D725A70C0E0AFBEE008C767D /* wrppm.c */,
+ D725A70D0E0AFBEE008C767D /* wrgif.c */,
+ D725A70E0E0AFBEE008C767D /* wrbmp.c */,
+ D725A7140E0AFC04008C767D /* rdcolmap.c */,
+ D7EFF60B0E0AFCC50025E981 /* jpegtran.c */,
+ );
+ name = "Utilities Sources (non-lib)";
+ sourceTree = "<group>";
+ };
+ D76557EB0E0AE58D0038F973 /* External Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ D76558830E0AE74D0038F973 /* CoreServices.framework */,
+ );
+ name = "External Libraries";
+ sourceTree = "<group>";
+ };
+ D7C07B750E0AE0730096EB18 /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ D70F8C750E0AE23A003F1625 /* jconfig.h */,
+ D76493210E0ADD46007CC7CE /* jdhuff.h */,
+ D76493070E0ADD46007CC7CE /* jversion.h */,
+ D76493280E0ADD46007CC7CE /* jmorecfg.h */,
+ D76493260E0ADD46007CC7CE /* jdct.h */,
+ D76493330E0ADD46007CC7CE /* jpegint.h */,
+ D76493170E0ADD46007CC7CE /* jerror.h */,
+ D76493130E0ADD46007CC7CE /* jinclude.h */,
+ D76493410E0ADD46007CC7CE /* jchuff.h */,
+ D764931C0E0ADD46007CC7CE /* jmemsys.h */,
+ D76493480E0ADD46007CC7CE /* jpeglib.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D764935C0E0ADD46007CC7CE /* jversion.h in Headers */,
+ D76493680E0ADD46007CC7CE /* jinclude.h in Headers */,
+ D764936C0E0ADD46007CC7CE /* jerror.h in Headers */,
+ D76493710E0ADD46007CC7CE /* jmemsys.h in Headers */,
+ D76493760E0ADD46007CC7CE /* jdhuff.h in Headers */,
+ D764937B0E0ADD46007CC7CE /* jdct.h in Headers */,
+ D764937D0E0ADD46007CC7CE /* jmorecfg.h in Headers */,
+ D76493880E0ADD46007CC7CE /* jpegint.h in Headers */,
+ D76493960E0ADD46007CC7CE /* jchuff.h in Headers */,
+ D764939D0E0ADD46007CC7CE /* jpeglib.h in Headers */,
+ D70F8C760E0AE23A003F1625 /* jconfig.h in Headers */,
+ D7DBEE1A0E2BF8B90099D25F /* transupp.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libjpeg */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libjpeg" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libjpeg;
+ productName = libjpeg;
+ productReference = D2AAC046055464E500DB518D /* libjpeg.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ D725A6F60E0AFB5F008C767D /* djpeg */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D725A7070E0AFB8A008C767D /* Build configuration list for PBXNativeTarget "djpeg" */;
+ buildPhases = (
+ D725A6F40E0AFB5F008C767D /* Sources */,
+ D725A6F50E0AFB5F008C767D /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D725A6FC0E0AFB64008C767D /* PBXTargetDependency */,
+ );
+ name = djpeg;
+ productName = djpeg;
+ productReference = D725A6F70E0AFB5F008C767D /* djpeg */;
+ productType = "com.apple.product-type.tool";
+ };
+ D76557540E0AE4150038F973 /* cjpeg */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D76557680E0AE4510038F973 /* Build configuration list for PBXNativeTarget "cjpeg" */;
+ buildPhases = (
+ D76557520E0AE4150038F973 /* Sources */,
+ D76557530E0AE4150038F973 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D765575A0E0AE42B0038F973 /* PBXTargetDependency */,
+ );
+ name = cjpeg;
+ productName = cjpeg;
+ productReference = D76557550E0AE4150038F973 /* cjpeg */;
+ productType = "com.apple.product-type.tool";
+ };
+ D778786C0E0AFF7B00C99215 /* tests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D77878770E0AFF8A00C99215 /* Build configuration list for PBXNativeTarget "tests" */;
+ buildPhases = (
+ D778787A0E0AFF9E00C99215 /* Run Tests (Build phase) */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D77878720E0AFF8200C99215 /* PBXTargetDependency */,
+ D77878740E0AFF8200C99215 /* PBXTargetDependency */,
+ D77878760E0AFF8200C99215 /* PBXTargetDependency */,
+ );
+ name = tests;
+ productName = tests;
+ productReference = D778786D0E0AFF7B00C99215 /* tests */;
+ productType = "com.apple.product-type.tool";
+ };
+ D7EFF6000E0AFC7D0025E981 /* jpegtran */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D7EFF6090E0AFC920025E981 /* Build configuration list for PBXNativeTarget "jpegtran" */;
+ buildPhases = (
+ D7EFF5FE0E0AFC7D0025E981 /* Sources */,
+ D7EFF5FF0E0AFC7D0025E981 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D7EFF6060E0AFC820025E981 /* PBXTargetDependency */,
+ );
+ name = jpegtran;
+ productName = jpegtran;
+ productReference = D7EFF6010E0AFC7D0025E981 /* jpegtran */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libjpeg" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libjpeg */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libjpeg */,
+ D76557540E0AE4150038F973 /* cjpeg */,
+ D725A6F60E0AFB5F008C767D /* djpeg */,
+ D7EFF6000E0AFC7D0025E981 /* jpegtran */,
+ D778786C0E0AFF7B00C99215 /* tests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ D778787A0E0AFF9E00C99215 /* Run Tests (Build phase) */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/testimg.ppm",
+ "$(SRCROOT)/testimg.bmp",
+ "$(SRCROOT)/testimg.jpg",
+ "$(SRCROOT)/testimg.ppm",
+ "$(SRCROOT)/testimgp.jpg",
+ );
+ name = "Run Tests (Build phase)";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "rm -f testout*\n${BUILD_DIR}/${CONFIGURATION}/djpeg -dct int -ppm -outfile testout.ppm testorig.jpg\n${BUILD_DIR}/${CONFIGURATION}/djpeg -dct int -bmp -colors 256 -outfile testout.bmp testorig.jpg\n${BUILD_DIR}/${CONFIGURATION}/cjpeg -dct int -outfile testout.jpg testimg.ppm\n${BUILD_DIR}/${CONFIGURATION}/djpeg -dct int -ppm -outfile testoutp.ppm testprog.jpg\n${BUILD_DIR}/${CONFIGURATION}/cjpeg -dct int -progressive -opt -outfile testoutp.jpg testimg.ppm\n${BUILD_DIR}/${CONFIGURATION}/jpegtran -outfile testoutt.jpg testprog.jpg\ncmp testimg.ppm testout.ppm\ncmp testimg.bmp testout.bmp\ncmp testimg.jpg testout.jpg\ncmp testimg.ppm testoutp.ppm\ncmp testimgp.jpg testoutp.jpg\ncmp testorig.jpg testoutt.jpg\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D764935D0E0ADD46007CC7CE /* jquant2.c in Sources */,
+ D76493600E0ADD46007CC7CE /* jmemmgr.c in Sources */,
+ D76493610E0ADD46007CC7CE /* jmemmac.c in Sources */,
+ D76493660E0ADD46007CC7CE /* jidctint.c in Sources */,
+ D76493670E0ADD46007CC7CE /* jidctfst.c in Sources */,
+ D76493690E0ADD46007CC7CE /* jidctflt.c in Sources */,
+ D764936A0E0ADD46007CC7CE /* jfdctint.c in Sources */,
+ D764936B0E0ADD46007CC7CE /* jfdctflt.c in Sources */,
+ D764936D0E0ADD46007CC7CE /* jfdctfst.c in Sources */,
+ D764936E0E0ADD46007CC7CE /* jerror.c in Sources */,
+ D764936F0E0ADD46007CC7CE /* jdtrans.c in Sources */,
+ D76493700E0ADD46007CC7CE /* jdsample.c in Sources */,
+ D76493720E0ADD46007CC7CE /* jdmerge.c in Sources */,
+ D76493730E0ADD46007CC7CE /* jdmarker.c in Sources */,
+ D76493740E0ADD46007CC7CE /* jdpostct.c in Sources */,
+ D76493750E0ADD46007CC7CE /* jdmainct.c in Sources */,
+ D76493770E0ADD46007CC7CE /* jdmaster.c in Sources */,
+ D76493780E0ADD46007CC7CE /* jdinput.c in Sources */,
+ D76493790E0ADD46007CC7CE /* jdhuff.c in Sources */,
+ D764937A0E0ADD46007CC7CE /* jddctmgr.c in Sources */,
+ D764937C0E0ADD46007CC7CE /* jdcolor.c in Sources */,
+ D764937E0E0ADD46007CC7CE /* jdcoefct.c in Sources */,
+ D764937F0E0ADD46007CC7CE /* jdatadst.c in Sources */,
+ D76493800E0ADD46007CC7CE /* jdapistd.c in Sources */,
+ D76493810E0ADD46007CC7CE /* jdatasrc.c in Sources */,
+ D76493820E0ADD46007CC7CE /* jdapimin.c in Sources */,
+ D76493830E0ADD46007CC7CE /* jctrans.c in Sources */,
+ D76493840E0ADD46007CC7CE /* jcsample.c in Sources */,
+ D76493860E0ADD46007CC7CE /* jcprepct.c in Sources */,
+ D76493870E0ADD46007CC7CE /* jcparam.c in Sources */,
+ D76493890E0ADD46007CC7CE /* jcapimin.c in Sources */,
+ D764938A0E0ADD46007CC7CE /* jquant1.c in Sources */,
+ D764938B0E0ADD46007CC7CE /* jcapistd.c in Sources */,
+ D764938C0E0ADD46007CC7CE /* jccoefct.c in Sources */,
+ D764938D0E0ADD46007CC7CE /* jutils.c in Sources */,
+ D76493910E0ADD46007CC7CE /* jccolor.c in Sources */,
+ D76493930E0ADD46007CC7CE /* jchuff.c in Sources */,
+ D76493950E0ADD46007CC7CE /* jcdctmgr.c in Sources */,
+ D76493990E0ADD46007CC7CE /* jcomapi.c in Sources */,
+ D764939A0E0ADD46007CC7CE /* jcmaster.c in Sources */,
+ D764939B0E0ADD46007CC7CE /* jcmarker.c in Sources */,
+ D764939C0E0ADD46007CC7CE /* jcmainct.c in Sources */,
+ D76493A00E0ADD46007CC7CE /* jcinit.c in Sources */,
+ D7DBEE190E2BF8B90099D25F /* transupp.c in Sources */,
+ D76E029C10D06BDA00F2706E /* jaricom.c in Sources */,
+ D76E029D10D06BDA00F2706E /* jcarith.c in Sources */,
+ D76E029E10D06BDA00F2706E /* jdarith.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D725A6F40E0AFB5F008C767D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D725A6FF0E0AFB7F008C767D /* cdjpeg.c in Sources */,
+ D725A7090E0AFB9F008C767D /* djpeg.c in Sources */,
+ D725A70F0E0AFBEE008C767D /* wrtarga.c in Sources */,
+ D725A7100E0AFBEE008C767D /* wrrle.c in Sources */,
+ D725A7110E0AFBEE008C767D /* wrppm.c in Sources */,
+ D725A7120E0AFBEE008C767D /* wrgif.c in Sources */,
+ D725A7130E0AFBEE008C767D /* wrbmp.c in Sources */,
+ D725A7150E0AFC04008C767D /* rdcolmap.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D76557520E0AE4150038F973 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D765576B0E0AE4890038F973 /* cjpeg.c in Sources */,
+ D765576D0E0AE4B50038F973 /* rdppm.c in Sources */,
+ D765576F0E0AE4D10038F973 /* rdgif.c in Sources */,
+ D76557710E0AE4DF0038F973 /* rdtarga.c in Sources */,
+ D76557740E0AE4FD0038F973 /* rdswitch.c in Sources */,
+ D76557750E0AE4FD0038F973 /* rdrle.c in Sources */,
+ D76557770E0AE5180038F973 /* rdbmp.c in Sources */,
+ D76557790E0AE5360038F973 /* cdjpeg.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D7EFF5FE0E0AFC7D0025E981 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7EFF60A0E0AFCA30025E981 /* cdjpeg.c in Sources */,
+ D7EFF60C0E0AFCC50025E981 /* jpegtran.c in Sources */,
+ D7EFF60D0E0AFCD10025E981 /* rdswitch.c in Sources */,
+ D7EFF6100E0AFCF80025E981 /* transupp.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ D725A6FC0E0AFB64008C767D /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC045055464E500DB518D /* libjpeg */;
+ targetProxy = D725A6FB0E0AFB64008C767D /* PBXContainerItemProxy */;
+ };
+ D765575A0E0AE42B0038F973 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC045055464E500DB518D /* libjpeg */;
+ targetProxy = D76557590E0AE42B0038F973 /* PBXContainerItemProxy */;
+ };
+ D77878720E0AFF8200C99215 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D76557540E0AE4150038F973 /* cjpeg */;
+ targetProxy = D77878710E0AFF8200C99215 /* PBXContainerItemProxy */;
+ };
+ D77878740E0AFF8200C99215 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D725A6F60E0AFB5F008C767D /* djpeg */;
+ targetProxy = D77878730E0AFF8200C99215 /* PBXContainerItemProxy */;
+ };
+ D77878760E0AFF8200C99215 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D7EFF6000E0AFC7D0025E981 /* jpegtran */;
+ targetProxy = D77878750E0AFF8200C99215 /* PBXContainerItemProxy */;
+ };
+ D7EFF6060E0AFC820025E981 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC045055464E500DB518D /* libjpeg */;
+ targetProxy = D7EFF6050E0AFC820025E981 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = jpeg;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = jpeg;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D7A4EEE50E0ADE9200D6883C /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D7A4EEE60E0ADE9200D6883C /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+ D725A6F90E0AFB60008C767D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = djpeg;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ D725A6FA0E0AFB60008C767D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = djpeg;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ D76557570E0AE4150038F973 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = cjpeg;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ D76557580E0AE4150038F973 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = cjpeg;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ D778786F0E0AFF7B00C99215 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = tests;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ D77878700E0AFF7B00C99215 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = tests;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+ D7EFF6030E0AFC7D0025E981 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = jpegtran;
+ ZERO_LINK = YES;
+ };
+ name = Debug;
+ };
+ D7EFF6040E0AFC7D0025E981 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = jpegtran;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libjpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libjpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D725A7070E0AFB8A008C767D /* Build configuration list for PBXNativeTarget "djpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D725A6F90E0AFB60008C767D /* Debug */,
+ D725A6FA0E0AFB60008C767D /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D76557680E0AE4510038F973 /* Build configuration list for PBXNativeTarget "cjpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D76557570E0AE4150038F973 /* Debug */,
+ D76557580E0AE4150038F973 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D77878770E0AFF8A00C99215 /* Build configuration list for PBXNativeTarget "tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D778786F0E0AFF7B00C99215 /* Debug */,
+ D77878700E0AFF7B00C99215 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D7EFF6090E0AFC920025E981 /* Build configuration list for PBXNativeTarget "jpegtran" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D7EFF6030E0AFC7D0025E981 /* Debug */,
+ D7EFF6040E0AFC7D0025E981 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Source/LibJPEG/rdbmp.c b/Source/LibJPEG/rdbmp.c
new file mode 100644
index 0000000..b05fe2a
--- /dev/null
+++ b/Source/LibJPEG/rdbmp.c
@@ -0,0 +1,439 @@
+/*
+ * rdbmp.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Microsoft "BMP"
+ * format (MS Windows 3.x, OS/2 1.x, and OS/2 2.x flavors).
+ * Currently, only 8-bit and 24-bit images are supported, not 1-bit or
+ * 4-bit (feeding such low-depth images into JPEG would be silly anyway).
+ * Also, we don't support RLE-compressed files.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed BMP format).
+ *
+ * This code contributed by James Arthur Boucher.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef BMP_SUPPORTED
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/* Private version of data source object */
+
+typedef struct _bmp_source_struct * bmp_source_ptr;
+
+typedef struct _bmp_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ j_compress_ptr cinfo; /* back link saves passing separate parm */
+
+ JSAMPARRAY colormap; /* BMP colormap (converted to my format) */
+
+ jvirt_sarray_ptr whole_image; /* Needed to reverse row order */
+ JDIMENSION source_row; /* Current source row number */
+ JDIMENSION row_width; /* Physical width of scanlines in file */
+
+ int bits_per_pixel; /* remembers 8- or 24-bit format */
+} bmp_source_struct;
+
+
+LOCAL(int)
+read_byte (bmp_source_ptr sinfo)
+/* Read next byte from BMP file */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int c;
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
+ return c;
+}
+
+
+LOCAL(void)
+read_colormap (bmp_source_ptr sinfo, int cmaplen, int mapentrysize)
+/* Read the colormap from a BMP file */
+{
+ int i;
+
+ switch (mapentrysize) {
+ case 3:
+ /* BGR format (occurs in OS/2 files) */
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ }
+ break;
+ case 4:
+ /* BGR0 format (occurs in MS Windows files) */
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ (void) read_byte(sinfo);
+ }
+ break;
+ default:
+ ERREXIT(sinfo->cinfo, JERR_BMP_BADCMAP);
+ break;
+ }
+}
+
+
+/*
+ * Read one row of pixels.
+ * The image has been read into the whole_image array, but is otherwise
+ * unprocessed. We must read it out in top-to-bottom row order, and if
+ * it is an 8-bit image, we must expand colormapped pixels to 24bit format.
+ */
+
+METHODDEF(JDIMENSION)
+get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit colormap indexes */
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ register JSAMPARRAY colormap = source->colormap;
+ JSAMPARRAY image_ptr;
+ register int t;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+
+ /* Fetch next row from virtual array */
+ source->source_row--;
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source->source_row, (JDIMENSION) 1, FALSE);
+
+ /* Expand the colormap indexes to real data */
+ inptr = image_ptr[0];
+ outptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ t = GETJSAMPLE(*inptr++);
+ *outptr++ = colormap[0][t]; /* can omit GETJSAMPLE() safely */
+ *outptr++ = colormap[1][t];
+ *outptr++ = colormap[2][t];
+ }
+
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 24-bit pixels */
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+
+ /* Fetch next row from virtual array */
+ source->source_row--;
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source->source_row, (JDIMENSION) 1, FALSE);
+
+ /* Transfer data. Note source values are in BGR order
+ * (even though Microsoft's own documents say the opposite).
+ */
+ inptr = image_ptr[0];
+ outptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
+ outptr[1] = *inptr++;
+ outptr[0] = *inptr++;
+ outptr += 3;
+ }
+
+ return 1;
+}
+
+
+/*
+ * This method loads the image into whole_image during the first call on
+ * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
+ * get_8bit_row or get_24bit_row on subsequent calls.
+ */
+
+METHODDEF(JDIMENSION)
+preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ register FILE *infile = source->pub.input_file;
+ register int c;
+ register JSAMPROW out_ptr;
+ JSAMPARRAY image_ptr;
+ JDIMENSION row, col;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Read the data into a virtual array in input-file row order. */
+ for (row = 0; row < cinfo->image_height; row++) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) row;
+ progress->pub.pass_limit = (long) cinfo->image_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ row, (JDIMENSION) 1, TRUE);
+ out_ptr = image_ptr[0];
+ for (col = source->row_width; col > 0; col--) {
+ /* inline copy of read_byte() for speed */
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ *out_ptr++ = (JSAMPLE) c;
+ }
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Set up to read from the virtual array in top-to-bottom order */
+ switch (source->bits_per_pixel) {
+ case 8:
+ source->pub.get_pixel_rows = get_8bit_row;
+ break;
+ case 24:
+ source->pub.get_pixel_rows = get_24bit_row;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ }
+ source->source_row = cinfo->image_height;
+
+ /* And read the first row */
+ return (*source->pub.get_pixel_rows) (cinfo, sinfo);
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ bmp_source_ptr source = (bmp_source_ptr) sinfo;
+ U_CHAR bmpfileheader[14];
+ U_CHAR bmpinfoheader[64];
+#define GET_2B(array,offset) ((unsigned int) UCH(array[offset]) + \
+ (((unsigned int) UCH(array[offset+1])) << 8))
+#define GET_4B(array,offset) ((INT32) UCH(array[offset]) + \
+ (((INT32) UCH(array[offset+1])) << 8) + \
+ (((INT32) UCH(array[offset+2])) << 16) + \
+ (((INT32) UCH(array[offset+3])) << 24))
+ INT32 bfOffBits;
+ INT32 headerSize;
+ INT32 biWidth = 0; /* initialize to avoid compiler warning */
+ INT32 biHeight = 0;
+ unsigned int biPlanes;
+ INT32 biCompression;
+ INT32 biXPelsPerMeter,biYPelsPerMeter;
+ INT32 biClrUsed = 0;
+ int mapentrysize = 0; /* 0 indicates no colormap */
+ INT32 bPad;
+ JDIMENSION row_width;
+
+ /* Read and verify the bitmap file header */
+ if (! ReadOK(source->pub.input_file, bmpfileheader, 14))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ if (GET_2B(bmpfileheader,0) != 0x4D42) /* 'BM' */
+ ERREXIT(cinfo, JERR_BMP_NOT);
+ bfOffBits = (INT32) GET_4B(bmpfileheader,10);
+ /* We ignore the remaining fileheader fields */
+
+ /* The infoheader might be 12 bytes (OS/2 1.x), 40 bytes (Windows),
+ * or 64 bytes (OS/2 2.x). Check the first 4 bytes to find out which.
+ */
+ if (! ReadOK(source->pub.input_file, bmpinfoheader, 4))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ headerSize = (INT32) GET_4B(bmpinfoheader,0);
+ if (headerSize < 12 || headerSize > 64)
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ if (! ReadOK(source->pub.input_file, bmpinfoheader+4, headerSize-4))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+
+ switch ((int) headerSize) {
+ case 12:
+ /* Decode OS/2 1.x header (Microsoft calls this a BITMAPCOREHEADER) */
+ biWidth = (INT32) GET_2B(bmpinfoheader,4);
+ biHeight = (INT32) GET_2B(bmpinfoheader,6);
+ biPlanes = GET_2B(bmpinfoheader,8);
+ source->bits_per_pixel = (int) GET_2B(bmpinfoheader,10);
+
+ switch (source->bits_per_pixel) {
+ case 8: /* colormapped image */
+ mapentrysize = 3; /* OS/2 uses RGBTRIPLE colormap */
+ TRACEMS2(cinfo, 1, JTRC_BMP_OS2_MAPPED, (int) biWidth, (int) biHeight);
+ break;
+ case 24: /* RGB image */
+ TRACEMS2(cinfo, 1, JTRC_BMP_OS2, (int) biWidth, (int) biHeight);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ break;
+ }
+ if (biPlanes != 1)
+ ERREXIT(cinfo, JERR_BMP_BADPLANES);
+ break;
+ case 40:
+ case 64:
+ /* Decode Windows 3.x header (Microsoft calls this a BITMAPINFOHEADER) */
+ /* or OS/2 2.x header, which has additional fields that we ignore */
+ biWidth = GET_4B(bmpinfoheader,4);
+ biHeight = GET_4B(bmpinfoheader,8);
+ biPlanes = GET_2B(bmpinfoheader,12);
+ source->bits_per_pixel = (int) GET_2B(bmpinfoheader,14);
+ biCompression = GET_4B(bmpinfoheader,16);
+ biXPelsPerMeter = GET_4B(bmpinfoheader,24);
+ biYPelsPerMeter = GET_4B(bmpinfoheader,28);
+ biClrUsed = GET_4B(bmpinfoheader,32);
+ /* biSizeImage, biClrImportant fields are ignored */
+
+ switch (source->bits_per_pixel) {
+ case 8: /* colormapped image */
+ mapentrysize = 4; /* Windows uses RGBQUAD colormap */
+ TRACEMS2(cinfo, 1, JTRC_BMP_MAPPED, (int) biWidth, (int) biHeight);
+ break;
+ case 24: /* RGB image */
+ TRACEMS2(cinfo, 1, JTRC_BMP, (int) biWidth, (int) biHeight);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADDEPTH);
+ break;
+ }
+ if (biPlanes != 1)
+ ERREXIT(cinfo, JERR_BMP_BADPLANES);
+ if (biCompression != 0)
+ ERREXIT(cinfo, JERR_BMP_COMPRESSED);
+
+ if (biXPelsPerMeter > 0 && biYPelsPerMeter > 0) {
+ /* Set JFIF density parameters from the BMP data */
+ cinfo->X_density = (UINT16) (biXPelsPerMeter/100); /* 100 cm per meter */
+ cinfo->Y_density = (UINT16) (biYPelsPerMeter/100);
+ cinfo->density_unit = 2; /* dots/cm */
+ }
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ break;
+ }
+
+ /* Compute distance to bitmap data --- will adjust for colormap below */
+ bPad = bfOffBits - (headerSize + 14);
+
+ /* Read the colormap, if any */
+ if (mapentrysize > 0) {
+ if (biClrUsed <= 0)
+ biClrUsed = 256; /* assume it's 256 */
+ else if (biClrUsed > 256)
+ ERREXIT(cinfo, JERR_BMP_BADCMAP);
+ /* Allocate space to store the colormap */
+ source->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) biClrUsed, (JDIMENSION) 3);
+ /* and read it from the file */
+ read_colormap(source, (int) biClrUsed, mapentrysize);
+ /* account for size of colormap */
+ bPad -= biClrUsed * mapentrysize;
+ }
+
+ /* Skip any remaining pad bytes */
+ if (bPad < 0) /* incorrect bfOffBits value? */
+ ERREXIT(cinfo, JERR_BMP_BADHEADER);
+ while (--bPad >= 0) {
+ (void) read_byte(source);
+ }
+
+ /* Compute row width in file, including padding to 4-byte boundary */
+ if (source->bits_per_pixel == 24)
+ row_width = (JDIMENSION) (biWidth * 3);
+ else
+ row_width = (JDIMENSION) biWidth;
+ while ((row_width & 3) != 0) row_width++;
+ source->row_width = row_width;
+
+ /* Allocate space for inversion array, prepare for preload pass */
+ source->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ row_width, (JDIMENSION) biHeight, (JDIMENSION) 1);
+ source->pub.get_pixel_rows = preload_image;
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+
+ /* Allocate one-row buffer for returned data */
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (biWidth * 3), (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+
+ cinfo->in_color_space = JCS_RGB;
+ cinfo->input_components = 3;
+ cinfo->data_precision = 8;
+ cinfo->image_width = (JDIMENSION) biWidth;
+ cinfo->image_height = (JDIMENSION) biHeight;
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_bmp (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for BMP format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_bmp (j_compress_ptr cinfo)
+{
+ bmp_source_ptr source;
+
+ /* Create module interface object */
+ source = (bmp_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(bmp_source_struct));
+ source->cinfo = cinfo; /* make back link for subroutines */
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_bmp;
+ source->pub.finish_input = finish_input_bmp;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* BMP_SUPPORTED */
diff --git a/Source/LibJPEG/rdcolmap.c b/Source/LibJPEG/rdcolmap.c
new file mode 100644
index 0000000..42b3437
--- /dev/null
+++ b/Source/LibJPEG/rdcolmap.c
@@ -0,0 +1,253 @@
+/*
+ * rdcolmap.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file implements djpeg's "-map file" switch. It reads a source image
+ * and constructs a colormap to be supplied to the JPEG decompressor.
+ *
+ * Currently, these file formats are supported for the map file:
+ * GIF: the contents of the GIF's global colormap are used.
+ * PPM (either text or raw flavor): the entire file is read and
+ * each unique pixel value is entered in the map.
+ * Note that reading a large PPM file will be horrendously slow.
+ * Typically, a PPM-format map file should contain just one pixel
+ * of each desired color. Such a file can be extracted from an
+ * ordinary image PPM file with ppmtomap(1).
+ *
+ * Rescaling a PPM that has a maxval unequal to MAXJSAMPLE is not
+ * currently implemented.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef QUANT_2PASS_SUPPORTED /* otherwise can't quantize to supplied map */
+
+/* Portions of this code are based on the PBMPLUS library, which is:
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+
+/*
+ * Add a (potentially) new color to the color map.
+ */
+
+LOCAL(void)
+add_map_entry (j_decompress_ptr cinfo, int R, int G, int B)
+{
+ JSAMPROW colormap0 = cinfo->colormap[0];
+ JSAMPROW colormap1 = cinfo->colormap[1];
+ JSAMPROW colormap2 = cinfo->colormap[2];
+ int ncolors = cinfo->actual_number_of_colors;
+ int index;
+
+ /* Check for duplicate color. */
+ for (index = 0; index < ncolors; index++) {
+ if (GETJSAMPLE(colormap0[index]) == R &&
+ GETJSAMPLE(colormap1[index]) == G &&
+ GETJSAMPLE(colormap2[index]) == B)
+ return; /* color is already in map */
+ }
+
+ /* Check for map overflow. */
+ if (ncolors >= (MAXJSAMPLE+1))
+ ERREXIT1(cinfo, JERR_QUANT_MANY_COLORS, (MAXJSAMPLE+1));
+
+ /* OK, add color to map. */
+ colormap0[ncolors] = (JSAMPLE) R;
+ colormap1[ncolors] = (JSAMPLE) G;
+ colormap2[ncolors] = (JSAMPLE) B;
+ cinfo->actual_number_of_colors++;
+}
+
+
+/*
+ * Extract color map from a GIF file.
+ */
+
+LOCAL(void)
+read_gif_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ int header[13];
+ int i, colormaplen;
+ int R, G, B;
+
+ /* Initial 'G' has already been read by read_color_map */
+ /* Read the rest of the GIF header and logical screen descriptor */
+ for (i = 1; i < 13; i++) {
+ if ((header[i] = getc(infile)) == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ }
+
+ /* Verify GIF Header */
+ if (header[1] != 'I' || header[2] != 'F')
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* There must be a global color map. */
+ if ((header[10] & 0x80) == 0)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* OK, fetch it. */
+ colormaplen = 2 << (header[10] & 0x07);
+
+ for (i = 0; i < colormaplen; i++) {
+ R = getc(infile);
+ G = getc(infile);
+ B = getc(infile);
+ if (R == EOF || G == EOF || B == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ add_map_entry(cinfo,
+ R << (BITS_IN_JSAMPLE-8),
+ G << (BITS_IN_JSAMPLE-8),
+ B << (BITS_IN_JSAMPLE-8));
+ }
+}
+
+
+/* Support routines for reading PPM */
+
+
+LOCAL(int)
+pbm_getc (FILE * infile)
+/* Read next char, skipping over any comments */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(infile);
+ if (ch == '#') {
+ do {
+ ch = getc(infile);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(unsigned int)
+read_pbm_integer (j_decompress_ptr cinfo, FILE * infile)
+/* Read an unsigned decimal integer from the PPM file */
+/* Swallows one trailing character after the integer */
+/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
+/* This should not be a problem in practice. */
+{
+ register int ch;
+ register unsigned int val;
+
+ /* Skip any leading whitespace */
+ do {
+ ch = pbm_getc(infile);
+ if (ch == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
+
+ if (ch < '0' || ch > '9')
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ val = ch - '0';
+ while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
+ val *= 10;
+ val += ch - '0';
+ }
+ return val;
+}
+
+
+/*
+ * Extract color map from a PPM file.
+ */
+
+LOCAL(void)
+read_ppm_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ int c;
+ unsigned int w, h, maxval, row, col;
+ int R, G, B;
+
+ /* Initial 'P' has already been read by read_color_map */
+ c = getc(infile); /* save format discriminator for a sec */
+
+ /* while we fetch the remaining header info */
+ w = read_pbm_integer(cinfo, infile);
+ h = read_pbm_integer(cinfo, infile);
+ maxval = read_pbm_integer(cinfo, infile);
+
+ if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ /* For now, we don't support rescaling from an unusual maxval. */
+ if (maxval != (unsigned int) MAXJSAMPLE)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+
+ switch (c) {
+ case '3': /* it's a text-format PPM file */
+ for (row = 0; row < h; row++) {
+ for (col = 0; col < w; col++) {
+ R = read_pbm_integer(cinfo, infile);
+ G = read_pbm_integer(cinfo, infile);
+ B = read_pbm_integer(cinfo, infile);
+ add_map_entry(cinfo, R, G, B);
+ }
+ }
+ break;
+
+ case '6': /* it's a raw-format PPM file */
+ for (row = 0; row < h; row++) {
+ for (col = 0; col < w; col++) {
+ R = getc(infile);
+ G = getc(infile);
+ B = getc(infile);
+ if (R == EOF || G == EOF || B == EOF)
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ add_map_entry(cinfo, R, G, B);
+ }
+ }
+ break;
+
+ default:
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ break;
+ }
+}
+
+
+/*
+ * Main entry point from djpeg.c.
+ * Input: opened input file (from file name argument on command line).
+ * Output: colormap and actual_number_of_colors fields are set in cinfo.
+ */
+
+GLOBAL(void)
+read_color_map (j_decompress_ptr cinfo, FILE * infile)
+{
+ /* Allocate space for a color map of maximum supported size. */
+ cinfo->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) (MAXJSAMPLE+1), (JDIMENSION) 3);
+ cinfo->actual_number_of_colors = 0; /* initialize map to empty */
+
+ /* Read first byte to determine file format */
+ switch (getc(infile)) {
+ case 'G':
+ read_gif_map(cinfo, infile);
+ break;
+ case 'P':
+ read_ppm_map(cinfo, infile);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_BAD_CMAP_FILE);
+ break;
+ }
+}
+
+#endif /* QUANT_2PASS_SUPPORTED */
diff --git a/Source/LibJPEG/rdgif.c b/Source/LibJPEG/rdgif.c
new file mode 100644
index 0000000..b27c167
--- /dev/null
+++ b/Source/LibJPEG/rdgif.c
@@ -0,0 +1,38 @@
+/*
+ * rdgif.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in GIF format.
+ *
+ *****************************************************************************
+ * NOTE: to avoid entanglements with Unisys' patent on LZW compression, *
+ * the ability to read GIF files has been removed from the IJG distribution. *
+ * Sorry about that. *
+ *****************************************************************************
+ *
+ * We are required to state that
+ * "The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated."
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef GIF_SUPPORTED
+
+/*
+ * The module selection routine for GIF format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_gif (j_compress_ptr cinfo)
+{
+ fprintf(stderr, "GIF input is unsupported for legal reasons. Sorry.\n");
+ exit(EXIT_FAILURE);
+ return NULL; /* keep compiler happy */
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/Source/LibJPEG/rdjpgcom.c b/Source/LibJPEG/rdjpgcom.c
new file mode 100644
index 0000000..3719154
--- /dev/null
+++ b/Source/LibJPEG/rdjpgcom.c
@@ -0,0 +1,515 @@
+/*
+ * rdjpgcom.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * Modified 2009 by Bill Allombert, Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a very simple stand-alone application that displays
+ * the text in COM (comment) markers in a JFIF file.
+ * This may be useful as an example of the minimum logic needed to parse
+ * JPEG markers.
+ */
+
+#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
+#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h> /* Bill Allombert: use locale for isprint */
+#endif
+#include <ctype.h> /* to declare isupper(), tolower() */
+#ifdef USE_SETMODE
+#include <fcntl.h> /* to declare setmode()'s parameter macros */
+/* If you have setmode() but not <io.h>, just delete this line: */
+#include <io.h> /* to declare setmode() */
+#endif
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#else
+#ifdef VMS /* VMS is very nonstandard */
+#define READ_BINARY "rb", "ctx=stm"
+#else /* standard ANSI-compliant case */
+#define READ_BINARY "rb"
+#endif
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#ifdef VMS
+#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
+#else
+#define EXIT_SUCCESS 0
+#endif
+#endif
+
+
+/*
+ * These macros are used to read the input file.
+ * To reuse this code in another application, you might need to change these.
+ */
+
+static FILE * infile; /* input JPEG file */
+
+/* Return next input byte, or EOF if no more */
+#define NEXTBYTE() getc(infile)
+
+
+/* Error exit handler */
+#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
+
+
+/* Read one byte, testing for EOF */
+static int
+read_1_byte (void)
+{
+ int c;
+
+ c = NEXTBYTE();
+ if (c == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return c;
+}
+
+/* Read 2 bytes, convert to unsigned int */
+/* All 2-byte quantities in JPEG markers are MSB first */
+static unsigned int
+read_2_bytes (void)
+{
+ int c1, c2;
+
+ c1 = NEXTBYTE();
+ if (c1 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ c2 = NEXTBYTE();
+ if (c2 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return (((unsigned int) c1) << 8) + ((unsigned int) c2);
+}
+
+
+/*
+ * JPEG markers consist of one or more 0xFF bytes, followed by a marker
+ * code byte (which is not an FF). Here are the marker codes of interest
+ * in this program. (See jdmarker.c for a more complete list.)
+ */
+
+#define M_SOF0 0xC0 /* Start Of Frame N */
+#define M_SOF1 0xC1 /* N indicates which compression process */
+#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
+#define M_EOI 0xD9 /* End Of Image (end of datastream) */
+#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+#define M_APP0 0xE0 /* Application-specific marker, type N */
+#define M_APP12 0xEC /* (we don't bother to list all 16 APPn's) */
+#define M_COM 0xFE /* COMment */
+
+
+/*
+ * Find the next JPEG marker and return its marker code.
+ * We expect at least one FF byte, possibly more if the compressor used FFs
+ * to pad the file.
+ * There could also be non-FF garbage between markers. The treatment of such
+ * garbage is unspecified; we choose to skip over it but emit a warning msg.
+ * NB: this routine must not be used after seeing SOS marker, since it will
+ * not deal correctly with FF/00 sequences in the compressed image data...
+ */
+
+static int
+next_marker (void)
+{
+ int c;
+ int discarded_bytes = 0;
+
+ /* Find 0xFF byte; count and skip any non-FFs. */
+ c = read_1_byte();
+ while (c != 0xFF) {
+ discarded_bytes++;
+ c = read_1_byte();
+ }
+ /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
+ * are legal as pad bytes, so don't count them in discarded_bytes.
+ */
+ do {
+ c = read_1_byte();
+ } while (c == 0xFF);
+
+ if (discarded_bytes != 0) {
+ fprintf(stderr, "Warning: garbage data found in JPEG file\n");
+ }
+
+ return c;
+}
+
+
+/*
+ * Read the initial marker, which should be SOI.
+ * For a JFIF file, the first two bytes of the file should be literally
+ * 0xFF M_SOI. To be more general, we could use next_marker, but if the
+ * input file weren't actually JPEG at all, next_marker might read the whole
+ * file and then return a misleading error message...
+ */
+
+static int
+first_marker (void)
+{
+ int c1, c2;
+
+ c1 = NEXTBYTE();
+ c2 = NEXTBYTE();
+ if (c1 != 0xFF || c2 != M_SOI)
+ ERREXIT("Not a JPEG file");
+ return c2;
+}
+
+
+/*
+ * Most types of marker are followed by a variable-length parameter segment.
+ * This routine skips over the parameters for any marker we don't otherwise
+ * want to process.
+ * Note that we MUST skip the parameter segment explicitly in order not to
+ * be fooled by 0xFF bytes that might appear within the parameter segment;
+ * such bytes do NOT introduce new markers.
+ */
+
+static void
+skip_variable (void)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+ unsigned int length;
+
+ /* Get the marker parameter length count */
+ length = read_2_bytes();
+ /* Length includes itself, so must be at least 2 */
+ if (length < 2)
+ ERREXIT("Erroneous JPEG marker length");
+ length -= 2;
+ /* Skip over the remaining bytes */
+ while (length > 0) {
+ (void) read_1_byte();
+ length--;
+ }
+}
+
+
+/*
+ * Process a COM marker.
+ * We want to print out the marker contents as legible text;
+ * we must guard against non-text junk and varying newline representations.
+ */
+
+static void
+process_COM (int raw)
+{
+ unsigned int length;
+ int ch;
+ int lastch = 0;
+
+ /* Bill Allombert: set locale properly for isprint */
+#ifdef HAVE_LOCALE_H
+ setlocale(LC_CTYPE, "");
+#endif
+
+ /* Get the marker parameter length count */
+ length = read_2_bytes();
+ /* Length includes itself, so must be at least 2 */
+ if (length < 2)
+ ERREXIT("Erroneous JPEG marker length");
+ length -= 2;
+
+ while (length > 0) {
+ ch = read_1_byte();
+ if (raw) {
+ putc(ch, stdout);
+ /* Emit the character in a readable form.
+ * Nonprintables are converted to \nnn form,
+ * while \ is converted to \\.
+ * Newlines in CR, CR/LF, or LF form will be printed as one newline.
+ */
+ } else if (ch == '\r') {
+ printf("\n");
+ } else if (ch == '\n') {
+ if (lastch != '\r')
+ printf("\n");
+ } else if (ch == '\\') {
+ printf("\\\\");
+ } else if (isprint(ch)) {
+ putc(ch, stdout);
+ } else {
+ printf("\\%03o", ch);
+ }
+ lastch = ch;
+ length--;
+ }
+ printf("\n");
+
+ /* Bill Allombert: revert to C locale */
+#ifdef HAVE_LOCALE_H
+ setlocale(LC_CTYPE, "C");
+#endif
+}
+
+
+/*
+ * Process a SOFn marker.
+ * This code is only needed if you want to know the image dimensions...
+ */
+
+static void
+process_SOFn (int marker)
+{
+ unsigned int length;
+ unsigned int image_height, image_width;
+ int data_precision, num_components;
+ const char * process;
+ int ci;
+
+ length = read_2_bytes(); /* usual parameter length count */
+
+ data_precision = read_1_byte();
+ image_height = read_2_bytes();
+ image_width = read_2_bytes();
+ num_components = read_1_byte();
+
+ switch (marker) {
+ case M_SOF0: process = "Baseline"; break;
+ case M_SOF1: process = "Extended sequential"; break;
+ case M_SOF2: process = "Progressive"; break;
+ case M_SOF3: process = "Lossless"; break;
+ case M_SOF5: process = "Differential sequential"; break;
+ case M_SOF6: process = "Differential progressive"; break;
+ case M_SOF7: process = "Differential lossless"; break;
+ case M_SOF9: process = "Extended sequential, arithmetic coding"; break;
+ case M_SOF10: process = "Progressive, arithmetic coding"; break;
+ case M_SOF11: process = "Lossless, arithmetic coding"; break;
+ case M_SOF13: process = "Differential sequential, arithmetic coding"; break;
+ case M_SOF14: process = "Differential progressive, arithmetic coding"; break;
+ case M_SOF15: process = "Differential lossless, arithmetic coding"; break;
+ default: process = "Unknown"; break;
+ }
+
+ printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n",
+ image_width, image_height, num_components, data_precision);
+ printf("JPEG process: %s\n", process);
+
+ if (length != (unsigned int) (8 + num_components * 3))
+ ERREXIT("Bogus SOF marker length");
+
+ for (ci = 0; ci < num_components; ci++) {
+ (void) read_1_byte(); /* Component ID code */
+ (void) read_1_byte(); /* H, V sampling factors */
+ (void) read_1_byte(); /* Quantization table number */
+ }
+}
+
+
+/*
+ * Parse the marker stream until SOS or EOI is seen;
+ * display any COM markers.
+ * While the companion program wrjpgcom will always insert COM markers before
+ * SOFn, other implementations might not, so we scan to SOS before stopping.
+ * If we were only interested in the image dimensions, we would stop at SOFn.
+ * (Conversely, if we only cared about COM markers, there would be no need
+ * for special code to handle SOFn; we could treat it like other markers.)
+ */
+
+static int
+scan_JPEG_header (int verbose, int raw)
+{
+ int marker;
+
+ /* Expect SOI at start of file */
+ if (first_marker() != M_SOI)
+ ERREXIT("Expected SOI marker first");
+
+ /* Scan miscellaneous markers until we reach SOS. */
+ for (;;) {
+ marker = next_marker();
+ switch (marker) {
+ /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
+ * treated as SOFn. C4 in particular is actually DHT.
+ */
+ case M_SOF0: /* Baseline */
+ case M_SOF1: /* Extended sequential, Huffman */
+ case M_SOF2: /* Progressive, Huffman */
+ case M_SOF3: /* Lossless, Huffman */
+ case M_SOF5: /* Differential sequential, Huffman */
+ case M_SOF6: /* Differential progressive, Huffman */
+ case M_SOF7: /* Differential lossless, Huffman */
+ case M_SOF9: /* Extended sequential, arithmetic */
+ case M_SOF10: /* Progressive, arithmetic */
+ case M_SOF11: /* Lossless, arithmetic */
+ case M_SOF13: /* Differential sequential, arithmetic */
+ case M_SOF14: /* Differential progressive, arithmetic */
+ case M_SOF15: /* Differential lossless, arithmetic */
+ if (verbose)
+ process_SOFn(marker);
+ else
+ skip_variable();
+ break;
+
+ case M_SOS: /* stop before hitting compressed data */
+ return marker;
+
+ case M_EOI: /* in case it's a tables-only JPEG stream */
+ return marker;
+
+ case M_COM:
+ process_COM(raw);
+ break;
+
+ case M_APP12:
+ /* Some digital camera makers put useful textual information into
+ * APP12 markers, so we print those out too when in -verbose mode.
+ */
+ if (verbose) {
+ printf("APP12 contains:\n");
+ process_COM(raw);
+ } else
+ skip_variable();
+ break;
+
+ default: /* Anything else just gets skipped */
+ skip_variable(); /* we assume it has a parameter count... */
+ break;
+ }
+ } /* end loop */
+}
+
+
+/* Command line parsing code */
+
+static const char * progname; /* program name for error messages */
+
+
+static void
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "rdjpgcom displays any textual comments in a JPEG file.\n");
+
+ fprintf(stderr, "Usage: %s [switches] [inputfile]\n", progname);
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -raw Display non-printable characters in comments (unsafe)\n");
+ fprintf(stderr, " -verbose Also display dimensions of JPEG image\n");
+
+ exit(EXIT_FAILURE);
+}
+
+
+static int
+keymatch (char * arg, const char * keyword, int minchars)
+/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
+/* keyword is the constant keyword (must be lower case already), */
+/* minchars is length of minimum legal abbreviation. */
+{
+ register int ca, ck;
+ register int nmatched = 0;
+
+ while ((ca = *arg++) != '\0') {
+ if ((ck = *keyword++) == '\0')
+ return 0; /* arg longer than keyword, no good */
+ if (isupper(ca)) /* force arg to lcase (assume ck is already) */
+ ca = tolower(ca);
+ if (ca != ck)
+ return 0; /* no good */
+ nmatched++; /* count matched characters */
+ }
+ /* reached end of argument; fail if it's too short for unique abbrev */
+ if (nmatched < minchars)
+ return 0;
+ return 1; /* A-OK */
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ int argn;
+ char * arg;
+ int verbose = 0, raw = 0;
+
+ /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+ argc = ccommand(&argv);
+#endif
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "rdjpgcom"; /* in case C library doesn't provide it */
+
+ /* Parse switches, if any */
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (arg[0] != '-')
+ break; /* not switch, must be file name */
+ arg++; /* advance over '-' */
+ if (keymatch(arg, "verbose", 1)) {
+ verbose++;
+ } else if (keymatch(arg, "raw", 1)) {
+ raw = 1;
+ } else
+ usage();
+ }
+
+ /* Open the input file. */
+ /* Unix style: expect zero or one file name */
+ if (argn < argc-1) {
+ fprintf(stderr, "%s: only one input file\n", progname);
+ usage();
+ }
+ if (argn < argc) {
+ if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default input file is stdin */
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdin), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open stdin\n", progname);
+ exit(EXIT_FAILURE);
+ }
+#else
+ infile = stdin;
+#endif
+ }
+
+ /* Scan the JPEG headers. */
+ (void) scan_JPEG_header(verbose, raw);
+
+ /* All done. */
+ exit(EXIT_SUCCESS);
+ return 0; /* suppress no-return-value warnings */
+}
diff --git a/Source/LibJPEG/rdppm.c b/Source/LibJPEG/rdppm.c
new file mode 100644
index 0000000..a757022
--- /dev/null
+++ b/Source/LibJPEG/rdppm.c
@@ -0,0 +1,459 @@
+/*
+ * rdppm.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 2009 by Bill Allombert, Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in PPM/PGM format.
+ * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
+ * The PBMPLUS library is NOT required to compile this software
+ * (but it is highly useful as a set of PPM image manipulation programs).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed PPM format).
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef PPM_SUPPORTED
+
+
+/* Portions of this code are based on the PBMPLUS library, which is:
+**
+** Copyright (C) 1988 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+*/
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/*
+ * On most systems, reading individual bytes with getc() is drastically less
+ * efficient than buffering a row at a time with fread(). On PCs, we must
+ * allocate the buffer in near data space, because we are assuming small-data
+ * memory model, wherein fread() can't reach far memory. If you need to
+ * process very wide images on a PC, you might have to compile in large-memory
+ * model, or else replace fread() with a getc() loop --- which will be much
+ * slower.
+ */
+
+
+/* Private version of data source object */
+
+typedef struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ U_CHAR *iobuffer; /* non-FAR pointer to I/O buffer */
+ JSAMPROW pixrow; /* FAR pointer to same */
+ size_t buffer_width; /* width of I/O buffer */
+ JSAMPLE *rescale; /* => maxval-remapping array, or NULL */
+} ppm_source_struct;
+
+typedef ppm_source_struct * ppm_source_ptr;
+
+
+LOCAL(int)
+pbm_getc (FILE * infile)
+/* Read next char, skipping over any comments */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(infile);
+ if (ch == '#') {
+ do {
+ ch = getc(infile);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(unsigned int)
+read_pbm_integer (j_compress_ptr cinfo, FILE * infile)
+/* Read an unsigned decimal integer from the PPM file */
+/* Swallows one trailing character after the integer */
+/* Note that on a 16-bit-int machine, only values up to 64k can be read. */
+/* This should not be a problem in practice. */
+{
+ register int ch;
+ register unsigned int val;
+
+ /* Skip any leading whitespace */
+ do {
+ ch = pbm_getc(infile);
+ if (ch == EOF)
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ } while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
+
+ if (ch < '0' || ch > '9')
+ ERREXIT(cinfo, JERR_PPM_NONNUMERIC);
+
+ val = ch - '0';
+ while ((ch = pbm_getc(infile)) >= '0' && ch <= '9') {
+ val *= 10;
+ val += ch - '0';
+ }
+ return val;
+}
+
+
+/*
+ * Read one row of pixels.
+ *
+ * We provide several different versions depending on input file format.
+ * In all cases, input is scaled to the size of JSAMPLE.
+ *
+ * A really fast path is provided for reading byte/sample raw files with
+ * maxval = MAXJSAMPLE, which is the normal case for 8-bit data.
+ */
+
+
+METHODDEF(JDIMENSION)
+get_text_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading text-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ FILE * infile = source->pub.input_file;
+ register JSAMPROW ptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_text_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading text-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ FILE * infile = source->pub.input_file;
+ register JSAMPROW ptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ *ptr++ = rescale[read_pbm_integer(cinfo, infile)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_scaled_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_scaled_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ *ptr++ = rescale[UCH(*bufferptr++)];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_raw_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-byte-format files with maxval = MAXJSAMPLE.
+ * In this case we just read right into the JSAMPLE buffer!
+ * Note that same code works for PPM and PGM files.
+ */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_word_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-word-format PGM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ register int temp;
+ temp = UCH(*bufferptr++) << 8;
+ temp |= UCH(*bufferptr++);
+ *ptr++ = rescale[temp];
+ }
+ return 1;
+}
+
+
+METHODDEF(JDIMENSION)
+get_word_rgb_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading raw-word-format PPM files with any maxval */
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register U_CHAR * bufferptr;
+ register JSAMPLE *rescale = source->rescale;
+ JDIMENSION col;
+
+ if (! ReadOK(source->pub.input_file, source->iobuffer, source->buffer_width))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+ ptr = source->pub.buffer[0];
+ bufferptr = source->iobuffer;
+ for (col = cinfo->image_width; col > 0; col--) {
+ register int temp;
+ temp = UCH(*bufferptr++) << 8;
+ temp |= UCH(*bufferptr++);
+ *ptr++ = rescale[temp];
+ temp = UCH(*bufferptr++) << 8;
+ temp |= UCH(*bufferptr++);
+ *ptr++ = rescale[temp];
+ temp = UCH(*bufferptr++) << 8;
+ temp |= UCH(*bufferptr++);
+ *ptr++ = rescale[temp];
+ }
+ return 1;
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ ppm_source_ptr source = (ppm_source_ptr) sinfo;
+ int c;
+ unsigned int w, h, maxval;
+ boolean need_iobuffer, use_raw_buffer, need_rescale;
+
+ if (getc(source->pub.input_file) != 'P')
+ ERREXIT(cinfo, JERR_PPM_NOT);
+
+ c = getc(source->pub.input_file); /* subformat discriminator character */
+
+ /* detect unsupported variants (ie, PBM) before trying to read header */
+ switch (c) {
+ case '2': /* it's a text-format PGM file */
+ case '3': /* it's a text-format PPM file */
+ case '5': /* it's a raw-format PGM file */
+ case '6': /* it's a raw-format PPM file */
+ break;
+ default:
+ ERREXIT(cinfo, JERR_PPM_NOT);
+ break;
+ }
+
+ /* fetch the remaining header info */
+ w = read_pbm_integer(cinfo, source->pub.input_file);
+ h = read_pbm_integer(cinfo, source->pub.input_file);
+ maxval = read_pbm_integer(cinfo, source->pub.input_file);
+
+ if (w <= 0 || h <= 0 || maxval <= 0) /* error check */
+ ERREXIT(cinfo, JERR_PPM_NOT);
+
+ cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */
+ cinfo->image_width = (JDIMENSION) w;
+ cinfo->image_height = (JDIMENSION) h;
+
+ /* initialize flags to most common settings */
+ need_iobuffer = TRUE; /* do we need an I/O buffer? */
+ use_raw_buffer = FALSE; /* do we map input buffer onto I/O buffer? */
+ need_rescale = TRUE; /* do we need a rescale array? */
+
+ switch (c) {
+ case '2': /* it's a text-format PGM file */
+ cinfo->input_components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_PGM_TEXT, w, h);
+ source->pub.get_pixel_rows = get_text_gray_row;
+ need_iobuffer = FALSE;
+ break;
+
+ case '3': /* it's a text-format PPM file */
+ cinfo->input_components = 3;
+ cinfo->in_color_space = JCS_RGB;
+ TRACEMS2(cinfo, 1, JTRC_PPM_TEXT, w, h);
+ source->pub.get_pixel_rows = get_text_rgb_row;
+ need_iobuffer = FALSE;
+ break;
+
+ case '5': /* it's a raw-format PGM file */
+ cinfo->input_components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_PGM, w, h);
+ if (maxval > 255) {
+ source->pub.get_pixel_rows = get_word_gray_row;
+ } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
+ source->pub.get_pixel_rows = get_raw_row;
+ use_raw_buffer = TRUE;
+ need_rescale = FALSE;
+ } else {
+ source->pub.get_pixel_rows = get_scaled_gray_row;
+ }
+ break;
+
+ case '6': /* it's a raw-format PPM file */
+ cinfo->input_components = 3;
+ cinfo->in_color_space = JCS_RGB;
+ TRACEMS2(cinfo, 1, JTRC_PPM, w, h);
+ if (maxval > 255) {
+ source->pub.get_pixel_rows = get_word_rgb_row;
+ } else if (maxval == MAXJSAMPLE && SIZEOF(JSAMPLE) == SIZEOF(U_CHAR)) {
+ source->pub.get_pixel_rows = get_raw_row;
+ use_raw_buffer = TRUE;
+ need_rescale = FALSE;
+ } else {
+ source->pub.get_pixel_rows = get_scaled_rgb_row;
+ }
+ break;
+ }
+
+ /* Allocate space for I/O buffer: 1 or 3 bytes or words/pixel. */
+ if (need_iobuffer) {
+ source->buffer_width = (size_t) w * cinfo->input_components *
+ ((maxval<=255) ? SIZEOF(U_CHAR) : (2*SIZEOF(U_CHAR)));
+ source->iobuffer = (U_CHAR *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ source->buffer_width);
+ }
+
+ /* Create compressor input buffer. */
+ if (use_raw_buffer) {
+ /* For unscaled raw-input case, we can just map it onto the I/O buffer. */
+ /* Synthesize a JSAMPARRAY pointer structure */
+ /* Cast here implies near->far pointer conversion on PCs */
+ source->pixrow = (JSAMPROW) source->iobuffer;
+ source->pub.buffer = & source->pixrow;
+ source->pub.buffer_height = 1;
+ } else {
+ /* Need to translate anyway, so make a separate sample buffer. */
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) w * cinfo->input_components, (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+ }
+
+ /* Compute the rescaling array if required. */
+ if (need_rescale) {
+ INT32 val, half_maxval;
+
+ /* On 16-bit-int machines we have to be careful of maxval = 65535 */
+ source->rescale = (JSAMPLE *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (((long) maxval + 1L) * SIZEOF(JSAMPLE)));
+ half_maxval = maxval / 2;
+ for (val = 0; val <= (INT32) maxval; val++) {
+ /* The multiplication here must be done in 32 bits to avoid overflow */
+ source->rescale[val] = (JSAMPLE) ((val*MAXJSAMPLE + half_maxval)/maxval);
+ }
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_ppm (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for PPM format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_ppm (j_compress_ptr cinfo)
+{
+ ppm_source_ptr source;
+
+ /* Create module interface object */
+ source = (ppm_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ppm_source_struct));
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_ppm;
+ source->pub.finish_input = finish_input_ppm;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/Source/LibJPEG/rdrle.c b/Source/LibJPEG/rdrle.c
new file mode 100644
index 0000000..542bc37
--- /dev/null
+++ b/Source/LibJPEG/rdrle.c
@@ -0,0 +1,387 @@
+/*
+ * rdrle.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Utah RLE format.
+ * The Utah Raster Toolkit library is required (version 3.1 or later).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed RLE format).
+ *
+ * Based on code contributed by Mike Lijewski,
+ * with updates from Robert Hutchinson.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef RLE_SUPPORTED
+
+/* rle.h is provided by the Utah Raster Toolkit. */
+
+#include <rle.h>
+
+/*
+ * We assume that JSAMPLE has the same representation as rle_pixel,
+ * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+/*
+ * We support the following types of RLE files:
+ *
+ * GRAYSCALE - 8 bits, no colormap
+ * MAPPEDGRAY - 8 bits, 1 channel colomap
+ * PSEUDOCOLOR - 8 bits, 3 channel colormap
+ * TRUECOLOR - 24 bits, 3 channel colormap
+ * DIRECTCOLOR - 24 bits, no colormap
+ *
+ * For now, we ignore any alpha channel in the image.
+ */
+
+typedef enum
+ { GRAYSCALE, MAPPEDGRAY, PSEUDOCOLOR, TRUECOLOR, DIRECTCOLOR } rle_kind;
+
+
+/*
+ * Since RLE stores scanlines bottom-to-top, we have to invert the image
+ * to conform to JPEG's top-to-bottom order. To do this, we read the
+ * incoming image into a virtual array on the first get_pixel_rows call,
+ * then fetch the required row from the virtual array on subsequent calls.
+ */
+
+typedef struct _rle_source_struct * rle_source_ptr;
+
+typedef struct _rle_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ rle_kind visual; /* actual type of input file */
+ jvirt_sarray_ptr image; /* virtual array to hold the image */
+ JDIMENSION row; /* current row # in the virtual array */
+ rle_hdr header; /* Input file information */
+ rle_pixel** rle_row; /* holds a row returned by rle_getrow() */
+
+} rle_source_struct;
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JDIMENSION width, height;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /* Use RLE library routine to get the header info */
+ source->header = *rle_hdr_init(NULL);
+ source->header.rle_file = source->pub.input_file;
+ switch (rle_get_setup(&(source->header))) {
+ case RLE_SUCCESS:
+ /* A-OK */
+ break;
+ case RLE_NOT_RLE:
+ ERREXIT(cinfo, JERR_RLE_NOT);
+ break;
+ case RLE_NO_SPACE:
+ ERREXIT(cinfo, JERR_RLE_MEM);
+ break;
+ case RLE_EMPTY:
+ ERREXIT(cinfo, JERR_RLE_EMPTY);
+ break;
+ case RLE_EOF:
+ ERREXIT(cinfo, JERR_RLE_EOF);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_RLE_BADERROR);
+ break;
+ }
+
+ /* Figure out what we have, set private vars and return values accordingly */
+
+ width = source->header.xmax - source->header.xmin + 1;
+ height = source->header.ymax - source->header.ymin + 1;
+ source->header.xmin = 0; /* realign horizontally */
+ source->header.xmax = width-1;
+
+ cinfo->image_width = width;
+ cinfo->image_height = height;
+ cinfo->data_precision = 8; /* we can only handle 8 bit data */
+
+ if (source->header.ncolors == 1 && source->header.ncmap == 0) {
+ source->visual = GRAYSCALE;
+ TRACEMS2(cinfo, 1, JTRC_RLE_GRAY, width, height);
+ } else if (source->header.ncolors == 1 && source->header.ncmap == 1) {
+ source->visual = MAPPEDGRAY;
+ TRACEMS3(cinfo, 1, JTRC_RLE_MAPGRAY, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 1 && source->header.ncmap == 3) {
+ source->visual = PSEUDOCOLOR;
+ TRACEMS3(cinfo, 1, JTRC_RLE_MAPPED, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 3 && source->header.ncmap == 3) {
+ source->visual = TRUECOLOR;
+ TRACEMS3(cinfo, 1, JTRC_RLE_FULLMAP, width, height,
+ 1 << source->header.cmaplen);
+ } else if (source->header.ncolors == 3 && source->header.ncmap == 0) {
+ source->visual = DIRECTCOLOR;
+ TRACEMS2(cinfo, 1, JTRC_RLE, width, height);
+ } else
+ ERREXIT(cinfo, JERR_RLE_UNSUPPORTED);
+
+ if (source->visual == GRAYSCALE || source->visual == MAPPEDGRAY) {
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ cinfo->input_components = 1;
+ } else {
+ cinfo->in_color_space = JCS_RGB;
+ cinfo->input_components = 3;
+ }
+
+ /*
+ * A place to hold each scanline while it's converted.
+ * (GRAYSCALE scanlines don't need converting)
+ */
+ if (source->visual != GRAYSCALE) {
+ source->rle_row = (rle_pixel**) (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) width, (JDIMENSION) cinfo->input_components);
+ }
+
+ /* request a virtual array to hold the image */
+ source->image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) (width * source->header.ncolors),
+ (JDIMENSION) height, (JDIMENSION) 1);
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ /* count file input as separate pass */
+ progress->total_extra_passes++;
+ }
+#endif
+
+ source->pub.buffer_height = 1;
+}
+
+
+/*
+ * Read one row of pixels.
+ * Called only after load_image has read the image into the virtual array.
+ * Used for GRAYSCALE, MAPPEDGRAY, TRUECOLOR, and DIRECTCOLOR images.
+ */
+
+METHODDEF(JDIMENSION)
+get_rle_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+
+ source->row--;
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
+
+ return 1;
+}
+
+/*
+ * Read one row of pixels.
+ * Called only after load_image has read the image into the virtual array.
+ * Used for PSEUDOCOLOR images.
+ */
+
+METHODDEF(JDIMENSION)
+get_pseudocolor_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JSAMPROW src_row, dest_row;
+ JDIMENSION col;
+ rle_map *colormap;
+ int val;
+
+ colormap = source->header.cmap;
+ dest_row = source->pub.buffer[0];
+ source->row--;
+ src_row = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, source->row, (JDIMENSION) 1, FALSE);
+
+ for (col = cinfo->image_width; col > 0; col--) {
+ val = GETJSAMPLE(*src_row++);
+ *dest_row++ = (JSAMPLE) (colormap[val ] >> 8);
+ *dest_row++ = (JSAMPLE) (colormap[val + 256] >> 8);
+ *dest_row++ = (JSAMPLE) (colormap[val + 512] >> 8);
+ }
+
+ return 1;
+}
+
+
+/*
+ * Load the image into a virtual array. We have to do this because RLE
+ * files start at the lower left while the JPEG standard has them starting
+ * in the upper left. This is called the first time we want to get a row
+ * of input. What we do is load the RLE data into the array and then call
+ * the appropriate routine to read one row from the array. Before returning,
+ * we set source->pub.get_pixel_rows so that subsequent calls go straight to
+ * the appropriate row-reading routine.
+ */
+
+METHODDEF(JDIMENSION)
+load_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ rle_source_ptr source = (rle_source_ptr) sinfo;
+ JDIMENSION row, col;
+ JSAMPROW scanline, red_ptr, green_ptr, blue_ptr;
+ rle_pixel **rle_row;
+ rle_map *colormap;
+ char channel;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ colormap = source->header.cmap;
+ rle_row = source->rle_row;
+
+ /* Read the RLE data into our virtual array.
+ * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
+ * and (b) we are not on a machine where FAR pointers differ from regular.
+ */
+ RLE_CLR_BIT(source->header, RLE_ALPHA); /* don't read the alpha channel */
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_limit = cinfo->image_height;
+ progress->pub.pass_counter = 0;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+
+ switch (source->visual) {
+
+ case GRAYSCALE:
+ case PSEUDOCOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_getrow(&source->header, rle_row);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ break;
+
+ case MAPPEDGRAY:
+ case TRUECOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ scanline = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_row = source->rle_row;
+ rle_getrow(&source->header, rle_row);
+
+ for (col = 0; col < cinfo->image_width; col++) {
+ for (channel = 0; channel < source->header.ncolors; channel++) {
+ *scanline++ = (JSAMPLE)
+ (colormap[GETJSAMPLE(rle_row[channel][col]) + 256 * channel] >> 8);
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ break;
+
+ case DIRECTCOLOR:
+ for (row = 0; row < cinfo->image_height; row++) {
+ scanline = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->image, row, (JDIMENSION) 1, TRUE);
+ rle_getrow(&source->header, rle_row);
+
+ red_ptr = rle_row[0];
+ green_ptr = rle_row[1];
+ blue_ptr = rle_row[2];
+
+ for (col = cinfo->image_width; col > 0; col--) {
+ *scanline++ = *red_ptr++;
+ *scanline++ = *green_ptr++;
+ *scanline++ = *blue_ptr++;
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+#endif
+
+ /* Set up to call proper row-extraction routine in future */
+ if (source->visual == PSEUDOCOLOR) {
+ source->pub.buffer = source->rle_row;
+ source->pub.get_pixel_rows = get_pseudocolor_row;
+ } else {
+ source->pub.get_pixel_rows = get_rle_row;
+ }
+ source->row = cinfo->image_height;
+
+ /* And fetch the topmost (bottommost) row */
+ return (*source->pub.get_pixel_rows) (cinfo, sinfo);
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_rle (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for RLE format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_rle (j_compress_ptr cinfo)
+{
+ rle_source_ptr source;
+
+ /* Create module interface object */
+ source = (rle_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(rle_source_struct));
+ /* Fill in method ptrs */
+ source->pub.start_input = start_input_rle;
+ source->pub.finish_input = finish_input_rle;
+ source->pub.get_pixel_rows = load_image;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* RLE_SUPPORTED */
diff --git a/Source/LibJPEG/rdswitch.c b/Source/LibJPEG/rdswitch.c
new file mode 100644
index 0000000..7a839af
--- /dev/null
+++ b/Source/LibJPEG/rdswitch.c
@@ -0,0 +1,365 @@
+/*
+ * rdswitch.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to process some of cjpeg's more complicated
+ * command-line switches. Switches processed here are:
+ * -qtables file Read quantization tables from text file
+ * -scans file Read scan script from text file
+ * -quality N[,N,...] Set quality ratings
+ * -qslots N[,N,...] Set component quantization table selectors
+ * -sample HxV[,HxV,...] Set component sampling factors
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+#include <ctype.h> /* to declare isdigit(), isspace() */
+
+
+LOCAL(int)
+text_getc (FILE * file)
+/* Read next char, skipping over any comments (# to end of line) */
+/* A comment/newline sequence is returned as a newline */
+{
+ register int ch;
+
+ ch = getc(file);
+ if (ch == '#') {
+ do {
+ ch = getc(file);
+ } while (ch != '\n' && ch != EOF);
+ }
+ return ch;
+}
+
+
+LOCAL(boolean)
+read_text_integer (FILE * file, long * result, int * termchar)
+/* Read an unsigned decimal integer from a file, store it in result */
+/* Reads one trailing character after the integer; returns it in termchar */
+{
+ register int ch;
+ register long val;
+
+ /* Skip any leading whitespace, detect EOF */
+ do {
+ ch = text_getc(file);
+ if (ch == EOF) {
+ *termchar = ch;
+ return FALSE;
+ }
+ } while (isspace(ch));
+
+ if (! isdigit(ch)) {
+ *termchar = ch;
+ return FALSE;
+ }
+
+ val = ch - '0';
+ while ((ch = text_getc(file)) != EOF) {
+ if (! isdigit(ch))
+ break;
+ val *= 10;
+ val += ch - '0';
+ }
+ *result = val;
+ *termchar = ch;
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+read_quant_tables (j_compress_ptr cinfo, char * filename, boolean force_baseline)
+/* Read a set of quantization tables from the specified file.
+ * The file is plain ASCII text: decimal numbers with whitespace between.
+ * Comments preceded by '#' may be included in the file.
+ * There may be one to NUM_QUANT_TBLS tables in the file, each of 64 values.
+ * The tables are implicitly numbered 0,1,etc.
+ * NOTE: does not affect the qslots mapping, which will default to selecting
+ * table 0 for luminance (or primary) components, 1 for chrominance components.
+ * You must use -qslots if you want a different component->table mapping.
+ */
+{
+ FILE * fp;
+ int tblno, i, termchar;
+ long val;
+ unsigned int table[DCTSIZE2];
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Can't open table file %s\n", filename);
+ return FALSE;
+ }
+ tblno = 0;
+
+ while (read_text_integer(fp, &val, &termchar)) { /* read 1st element of table */
+ if (tblno >= NUM_QUANT_TBLS) {
+ fprintf(stderr, "Too many tables in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ table[0] = (unsigned int) val;
+ for (i = 1; i < DCTSIZE2; i++) {
+ if (! read_text_integer(fp, &val, &termchar)) {
+ fprintf(stderr, "Invalid table data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ table[i] = (unsigned int) val;
+ }
+ jpeg_add_quant_table(cinfo, tblno, table, cinfo->q_scale_factor[tblno],
+ force_baseline);
+ tblno++;
+ }
+
+ if (termchar != EOF) {
+ fprintf(stderr, "Non-numeric data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+
+
+#ifdef C_MULTISCAN_FILES_SUPPORTED
+
+LOCAL(boolean)
+read_scan_integer (FILE * file, long * result, int * termchar)
+/* Variant of read_text_integer that always looks for a non-space termchar;
+ * this simplifies parsing of punctuation in scan scripts.
+ */
+{
+ register int ch;
+
+ if (! read_text_integer(file, result, termchar))
+ return FALSE;
+ ch = *termchar;
+ while (ch != EOF && isspace(ch))
+ ch = text_getc(file);
+ if (isdigit(ch)) { /* oops, put it back */
+ if (ungetc(ch, file) == EOF)
+ return FALSE;
+ ch = ' ';
+ } else {
+ /* Any separators other than ';' and ':' are ignored;
+ * this allows user to insert commas, etc, if desired.
+ */
+ if (ch != EOF && ch != ';' && ch != ':')
+ ch = ' ';
+ }
+ *termchar = ch;
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+read_scan_script (j_compress_ptr cinfo, char * filename)
+/* Read a scan script from the specified text file.
+ * Each entry in the file defines one scan to be emitted.
+ * Entries are separated by semicolons ';'.
+ * An entry contains one to four component indexes,
+ * optionally followed by a colon ':' and four progressive-JPEG parameters.
+ * The component indexes denote which component(s) are to be transmitted
+ * in the current scan. The first component has index 0.
+ * Sequential JPEG is used if the progressive-JPEG parameters are omitted.
+ * The file is free format text: any whitespace may appear between numbers
+ * and the ':' and ';' punctuation marks. Also, other punctuation (such
+ * as commas or dashes) can be placed between numbers if desired.
+ * Comments preceded by '#' may be included in the file.
+ * Note: we do very little validity checking here;
+ * jcmaster.c will validate the script parameters.
+ */
+{
+ FILE * fp;
+ int scanno, ncomps, termchar;
+ long val;
+ jpeg_scan_info * scanptr;
+#define MAX_SCANS 100 /* quite arbitrary limit */
+ jpeg_scan_info scans[MAX_SCANS];
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ fprintf(stderr, "Can't open scan definition file %s\n", filename);
+ return FALSE;
+ }
+ scanptr = scans;
+ scanno = 0;
+
+ while (read_scan_integer(fp, &val, &termchar)) {
+ if (scanno >= MAX_SCANS) {
+ fprintf(stderr, "Too many scans defined in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ scanptr->component_index[0] = (int) val;
+ ncomps = 1;
+ while (termchar == ' ') {
+ if (ncomps >= MAX_COMPS_IN_SCAN) {
+ fprintf(stderr, "Too many components in one scan in file %s\n",
+ filename);
+ fclose(fp);
+ return FALSE;
+ }
+ if (! read_scan_integer(fp, &val, &termchar))
+ goto bogus;
+ scanptr->component_index[ncomps] = (int) val;
+ ncomps++;
+ }
+ scanptr->comps_in_scan = ncomps;
+ if (termchar == ':') {
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Ss = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Se = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar) || termchar != ' ')
+ goto bogus;
+ scanptr->Ah = (int) val;
+ if (! read_scan_integer(fp, &val, &termchar))
+ goto bogus;
+ scanptr->Al = (int) val;
+ } else {
+ /* set non-progressive parameters */
+ scanptr->Ss = 0;
+ scanptr->Se = DCTSIZE2-1;
+ scanptr->Ah = 0;
+ scanptr->Al = 0;
+ }
+ if (termchar != ';' && termchar != EOF) {
+bogus:
+ fprintf(stderr, "Invalid scan entry format in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+ scanptr++, scanno++;
+ }
+
+ if (termchar != EOF) {
+ fprintf(stderr, "Non-numeric data in file %s\n", filename);
+ fclose(fp);
+ return FALSE;
+ }
+
+ if (scanno > 0) {
+ /* Stash completed scan list in cinfo structure.
+ * NOTE: for cjpeg's use, JPOOL_IMAGE is the right lifetime for this data,
+ * but if you want to compress multiple images you'd want JPOOL_PERMANENT.
+ */
+ scanptr = (jpeg_scan_info *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ scanno * SIZEOF(jpeg_scan_info));
+ MEMCOPY(scanptr, scans, scanno * SIZEOF(jpeg_scan_info));
+ cinfo->scan_info = scanptr;
+ cinfo->num_scans = scanno;
+ }
+
+ fclose(fp);
+ return TRUE;
+}
+
+#endif /* C_MULTISCAN_FILES_SUPPORTED */
+
+
+GLOBAL(boolean)
+set_quality_ratings (j_compress_ptr cinfo, char *arg, boolean force_baseline)
+/* Process a quality-ratings parameter string, of the form
+ * N[,N,...]
+ * If there are more q-table slots than parameters, the last value is replicated.
+ */
+{
+ int val = 75; /* default value */
+ int tblno;
+ char ch;
+
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ if (*arg) {
+ ch = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c", &val, &ch) < 1)
+ return FALSE;
+ if (ch != ',') /* syntax check */
+ return FALSE;
+ /* Convert user 0-100 rating to percentage scaling */
+ cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ } else {
+ /* reached end of parameter, set remaining factors to last value */
+ cinfo->q_scale_factor[tblno] = jpeg_quality_scaling(val);
+ }
+ }
+ jpeg_default_qtables(cinfo, force_baseline);
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+set_quant_slots (j_compress_ptr cinfo, char *arg)
+/* Process a quantization-table-selectors parameter string, of the form
+ * N[,N,...]
+ * If there are more components than parameters, the last value is replicated.
+ */
+{
+ int val = 0; /* default table # */
+ int ci;
+ char ch;
+
+ for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+ if (*arg) {
+ ch = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c", &val, &ch) < 1)
+ return FALSE;
+ if (ch != ',') /* syntax check */
+ return FALSE;
+ if (val < 0 || val >= NUM_QUANT_TBLS) {
+ fprintf(stderr, "JPEG quantization tables are numbered 0..%d\n",
+ NUM_QUANT_TBLS-1);
+ return FALSE;
+ }
+ cinfo->comp_info[ci].quant_tbl_no = val;
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ } else {
+ /* reached end of parameter, set remaining components to last table */
+ cinfo->comp_info[ci].quant_tbl_no = val;
+ }
+ }
+ return TRUE;
+}
+
+
+GLOBAL(boolean)
+set_sample_factors (j_compress_ptr cinfo, char *arg)
+/* Process a sample-factors parameter string, of the form
+ * HxV[,HxV,...]
+ * If there are more components than parameters, "1x1" is assumed for the rest.
+ */
+{
+ int ci, val1, val2;
+ char ch1, ch2;
+
+ for (ci = 0; ci < MAX_COMPONENTS; ci++) {
+ if (*arg) {
+ ch2 = ','; /* if not set by sscanf, will be ',' */
+ if (sscanf(arg, "%d%c%d%c", &val1, &ch1, &val2, &ch2) < 3)
+ return FALSE;
+ if ((ch1 != 'x' && ch1 != 'X') || ch2 != ',') /* syntax check */
+ return FALSE;
+ if (val1 <= 0 || val1 > 4 || val2 <= 0 || val2 > 4) {
+ fprintf(stderr, "JPEG sampling factors must be 1..4\n");
+ return FALSE;
+ }
+ cinfo->comp_info[ci].h_samp_factor = val1;
+ cinfo->comp_info[ci].v_samp_factor = val2;
+ while (*arg && *arg++ != ',') /* advance to next segment of arg string */
+ ;
+ } else {
+ /* reached end of parameter, set remaining components to 1x1 sampling */
+ cinfo->comp_info[ci].h_samp_factor = 1;
+ cinfo->comp_info[ci].v_samp_factor = 1;
+ }
+ }
+ return TRUE;
+}
diff --git a/Source/LibJPEG/rdtarga.c b/Source/LibJPEG/rdtarga.c
new file mode 100644
index 0000000..4c2cd26
--- /dev/null
+++ b/Source/LibJPEG/rdtarga.c
@@ -0,0 +1,500 @@
+/*
+ * rdtarga.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to read input images in Targa format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume input from
+ * an ordinary stdio stream. They further assume that reading begins
+ * at the start of the file; start_input may need work if the
+ * user interface has already read some data (e.g., to determine that
+ * the file is indeed Targa format).
+ *
+ * Based on code contributed by Lee Daniel Crocker.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef TARGA_SUPPORTED
+
+
+/* Macros to deal with unsigned chars as efficiently as compiler allows */
+
+#ifdef HAVE_UNSIGNED_CHAR
+typedef unsigned char U_CHAR;
+#define UCH(x) ((int) (x))
+#else /* !HAVE_UNSIGNED_CHAR */
+#ifdef CHAR_IS_UNSIGNED
+typedef char U_CHAR;
+#define UCH(x) ((int) (x))
+#else
+typedef char U_CHAR;
+#define UCH(x) ((int) (x) & 0xFF)
+#endif
+#endif /* HAVE_UNSIGNED_CHAR */
+
+
+#define ReadOK(file,buffer,len) (JFREAD(file,buffer,len) == ((size_t) (len)))
+
+
+/* Private version of data source object */
+
+typedef struct _tga_source_struct * tga_source_ptr;
+
+typedef struct _tga_source_struct {
+ struct cjpeg_source_struct pub; /* public fields */
+
+ j_compress_ptr cinfo; /* back link saves passing separate parm */
+
+ JSAMPARRAY colormap; /* Targa colormap (converted to my format) */
+
+ jvirt_sarray_ptr whole_image; /* Needed if funny input row order */
+ JDIMENSION current_row; /* Current logical row number to read */
+
+ /* Pointer to routine to extract next Targa pixel from input file */
+ JMETHOD(void, read_pixel, (tga_source_ptr sinfo));
+
+ /* Result of read_pixel is delivered here: */
+ U_CHAR tga_pixel[4];
+
+ int pixel_size; /* Bytes per Targa pixel (1 to 4) */
+
+ /* State info for reading RLE-coded pixels; both counts must be init to 0 */
+ int block_count; /* # of pixels remaining in RLE block */
+ int dup_pixel_count; /* # of times to duplicate previous pixel */
+
+ /* This saves the correct pixel-row-expansion method for preload_image */
+ JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
+ cjpeg_source_ptr sinfo));
+} tga_source_struct;
+
+
+/* For expanding 5-bit pixel values to 8-bit with best rounding */
+
+static const UINT8 c5to8bits[32] = {
+ 0, 8, 16, 25, 33, 41, 49, 58,
+ 66, 74, 82, 90, 99, 107, 115, 123,
+ 132, 140, 148, 156, 165, 173, 181, 189,
+ 197, 206, 214, 222, 230, 239, 247, 255
+};
+
+
+
+LOCAL(int)
+read_byte (tga_source_ptr sinfo)
+/* Read next byte from Targa file */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int c;
+
+ if ((c = getc(infile)) == EOF)
+ ERREXIT(sinfo->cinfo, JERR_INPUT_EOF);
+ return c;
+}
+
+
+LOCAL(void)
+read_colormap (tga_source_ptr sinfo, int cmaplen, int mapentrysize)
+/* Read the colormap from a Targa file */
+{
+ int i;
+
+ /* Presently only handles 24-bit BGR format */
+ if (mapentrysize != 24)
+ ERREXIT(sinfo->cinfo, JERR_TGA_BADCMAP);
+
+ for (i = 0; i < cmaplen; i++) {
+ sinfo->colormap[2][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[1][i] = (JSAMPLE) read_byte(sinfo);
+ sinfo->colormap[0][i] = (JSAMPLE) read_byte(sinfo);
+ }
+}
+
+
+/*
+ * read_pixel methods: get a single pixel from Targa file into tga_pixel[]
+ */
+
+METHODDEF(void)
+read_non_rle_pixel (tga_source_ptr sinfo)
+/* Read one Targa pixel from the input file; no RLE expansion */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int i;
+
+ for (i = 0; i < sinfo->pixel_size; i++) {
+ sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
+ }
+}
+
+
+METHODDEF(void)
+read_rle_pixel (tga_source_ptr sinfo)
+/* Read one Targa pixel from the input file, expanding RLE data as needed */
+{
+ register FILE *infile = sinfo->pub.input_file;
+ register int i;
+
+ /* Duplicate previously read pixel? */
+ if (sinfo->dup_pixel_count > 0) {
+ sinfo->dup_pixel_count--;
+ return;
+ }
+
+ /* Time to read RLE block header? */
+ if (--sinfo->block_count < 0) { /* decrement pixels remaining in block */
+ i = read_byte(sinfo);
+ if (i & 0x80) { /* Start of duplicate-pixel block? */
+ sinfo->dup_pixel_count = i & 0x7F; /* number of dups after this one */
+ sinfo->block_count = 0; /* then read new block header */
+ } else {
+ sinfo->block_count = i & 0x7F; /* number of pixels after this one */
+ }
+ }
+
+ /* Read next pixel */
+ for (i = 0; i < sinfo->pixel_size; i++) {
+ sinfo->tga_pixel[i] = (U_CHAR) getc(infile);
+ }
+}
+
+
+/*
+ * Read one row of pixels.
+ *
+ * We provide several different versions depending on input file format.
+ */
+
+
+METHODDEF(JDIMENSION)
+get_8bit_gray_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit grayscale pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_8bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 8-bit colormap indexes */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register int t;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+ register JSAMPARRAY colormap = source->colormap;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ t = UCH(source->tga_pixel[0]);
+ *ptr++ = colormap[0][t];
+ *ptr++ = colormap[1][t];
+ *ptr++ = colormap[2][t];
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_16bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 16-bit pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register int t;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ t = UCH(source->tga_pixel[0]);
+ t += UCH(source->tga_pixel[1]) << 8;
+ /* We expand 5 bit data to 8 bit sample width.
+ * The format of the 16-bit (LSB first) input word is
+ * xRRRRRGGGGGBBBBB
+ */
+ ptr[2] = (JSAMPLE) c5to8bits[t & 0x1F];
+ t >>= 5;
+ ptr[1] = (JSAMPLE) c5to8bits[t & 0x1F];
+ t >>= 5;
+ ptr[0] = (JSAMPLE) c5to8bits[t & 0x1F];
+ ptr += 3;
+ }
+ return 1;
+}
+
+METHODDEF(JDIMENSION)
+get_24bit_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+/* This version is for reading 24-bit pixels */
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = source->pub.buffer[0];
+ for (col = cinfo->image_width; col > 0; col--) {
+ (*source->read_pixel) (source); /* Load next pixel into tga_pixel */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[2]); /* change BGR to RGB order */
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[1]);
+ *ptr++ = (JSAMPLE) UCH(source->tga_pixel[0]);
+ }
+ return 1;
+}
+
+/*
+ * Targa also defines a 32-bit pixel format with order B,G,R,A.
+ * We presently ignore the attribute byte, so the code for reading
+ * these pixels is identical to the 24-bit routine above.
+ * This works because the actual pixel length is only known to read_pixel.
+ */
+
+#define get_32bit_row get_24bit_row
+
+
+/*
+ * This method is for re-reading the input data in standard top-down
+ * row order. The entire image has already been read into whole_image
+ * with proper conversion of pixel format, but it's in a funny row order.
+ */
+
+METHODDEF(JDIMENSION)
+get_memory_row (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ JDIMENSION source_row;
+
+ /* Compute row of source that maps to current_row of normal order */
+ /* For now, assume image is bottom-up and not interlaced. */
+ /* NEEDS WORK to support interlaced images! */
+ source_row = cinfo->image_height - source->current_row - 1;
+
+ /* Fetch that row from virtual array */
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image,
+ source_row, (JDIMENSION) 1, FALSE);
+
+ source->current_row++;
+ return 1;
+}
+
+
+/*
+ * This method loads the image into whole_image during the first call on
+ * get_pixel_rows. The get_pixel_rows pointer is then adjusted to call
+ * get_memory_row on subsequent calls.
+ */
+
+METHODDEF(JDIMENSION)
+preload_image (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ JDIMENSION row;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Read the data into a virtual array in input-file row order. */
+ for (row = 0; row < cinfo->image_height; row++) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) row;
+ progress->pub.pass_limit = (long) cinfo->image_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ source->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, source->whole_image, row, (JDIMENSION) 1, TRUE);
+ (*source->get_pixel_rows) (cinfo, sinfo);
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Set up to read from the virtual array in unscrambled order */
+ source->pub.get_pixel_rows = get_memory_row;
+ source->current_row = 0;
+ /* And read the first row */
+ return get_memory_row(cinfo, sinfo);
+}
+
+
+/*
+ * Read the file header; return image size and component count.
+ */
+
+METHODDEF(void)
+start_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ tga_source_ptr source = (tga_source_ptr) sinfo;
+ U_CHAR targaheader[18];
+ int idlen, cmaptype, subtype, flags, interlace_type, components;
+ unsigned int width, height, maplen;
+ boolean is_bottom_up;
+
+#define GET_2B(offset) ((unsigned int) UCH(targaheader[offset]) + \
+ (((unsigned int) UCH(targaheader[offset+1])) << 8))
+
+ if (! ReadOK(source->pub.input_file, targaheader, 18))
+ ERREXIT(cinfo, JERR_INPUT_EOF);
+
+ /* Pretend "15-bit" pixels are 16-bit --- we ignore attribute bit anyway */
+ if (targaheader[16] == 15)
+ targaheader[16] = 16;
+
+ idlen = UCH(targaheader[0]);
+ cmaptype = UCH(targaheader[1]);
+ subtype = UCH(targaheader[2]);
+ maplen = GET_2B(5);
+ width = GET_2B(12);
+ height = GET_2B(14);
+ source->pixel_size = UCH(targaheader[16]) >> 3;
+ flags = UCH(targaheader[17]); /* Image Descriptor byte */
+
+ is_bottom_up = ((flags & 0x20) == 0); /* bit 5 set => top-down */
+ interlace_type = flags >> 6; /* bits 6/7 are interlace code */
+
+ if (cmaptype > 1 || /* cmaptype must be 0 or 1 */
+ source->pixel_size < 1 || source->pixel_size > 4 ||
+ (UCH(targaheader[16]) & 7) != 0 || /* bits/pixel must be multiple of 8 */
+ interlace_type != 0) /* currently don't allow interlaced image */
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+
+ if (subtype > 8) {
+ /* It's an RLE-coded file */
+ source->read_pixel = read_rle_pixel;
+ source->block_count = source->dup_pixel_count = 0;
+ subtype -= 8;
+ } else {
+ /* Non-RLE file */
+ source->read_pixel = read_non_rle_pixel;
+ }
+
+ /* Now should have subtype 1, 2, or 3 */
+ components = 3; /* until proven different */
+ cinfo->in_color_space = JCS_RGB;
+
+ switch (subtype) {
+ case 1: /* Colormapped image */
+ if (source->pixel_size == 1 && cmaptype == 1)
+ source->get_pixel_rows = get_8bit_row;
+ else
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ TRACEMS2(cinfo, 1, JTRC_TGA_MAPPED, width, height);
+ break;
+ case 2: /* RGB image */
+ switch (source->pixel_size) {
+ case 2:
+ source->get_pixel_rows = get_16bit_row;
+ break;
+ case 3:
+ source->get_pixel_rows = get_24bit_row;
+ break;
+ case 4:
+ source->get_pixel_rows = get_32bit_row;
+ break;
+ default:
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ break;
+ }
+ TRACEMS2(cinfo, 1, JTRC_TGA, width, height);
+ break;
+ case 3: /* Grayscale image */
+ components = 1;
+ cinfo->in_color_space = JCS_GRAYSCALE;
+ if (source->pixel_size == 1)
+ source->get_pixel_rows = get_8bit_gray_row;
+ else
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ TRACEMS2(cinfo, 1, JTRC_TGA_GRAY, width, height);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ break;
+ }
+
+ if (is_bottom_up) {
+ /* Create a virtual array to buffer the upside-down image. */
+ source->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) width * components, (JDIMENSION) height, (JDIMENSION) 1);
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+ /* source->pub.buffer will point to the virtual array. */
+ source->pub.buffer_height = 1; /* in case anyone looks at it */
+ source->pub.get_pixel_rows = preload_image;
+ } else {
+ /* Don't need a virtual array, but do need a one-row input buffer. */
+ source->whole_image = NULL;
+ source->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (JDIMENSION) width * components, (JDIMENSION) 1);
+ source->pub.buffer_height = 1;
+ source->pub.get_pixel_rows = source->get_pixel_rows;
+ }
+
+ while (idlen--) /* Throw away ID field */
+ (void) read_byte(source);
+
+ if (maplen > 0) {
+ if (maplen > 256 || GET_2B(3) != 0)
+ ERREXIT(cinfo, JERR_TGA_BADCMAP);
+ /* Allocate space to store the colormap */
+ source->colormap = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, (JDIMENSION) maplen, (JDIMENSION) 3);
+ /* and read it from the file */
+ read_colormap(source, (int) maplen, UCH(targaheader[7]));
+ } else {
+ if (cmaptype) /* but you promised a cmap! */
+ ERREXIT(cinfo, JERR_TGA_BADPARMS);
+ source->colormap = NULL;
+ }
+
+ cinfo->input_components = components;
+ cinfo->data_precision = 8;
+ cinfo->image_width = width;
+ cinfo->image_height = height;
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_input_tga (j_compress_ptr cinfo, cjpeg_source_ptr sinfo)
+{
+ /* no work */
+}
+
+
+/*
+ * The module selection routine for Targa format input.
+ */
+
+GLOBAL(cjpeg_source_ptr)
+jinit_read_targa (j_compress_ptr cinfo)
+{
+ tga_source_ptr source;
+
+ /* Create module interface object */
+ source = (tga_source_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(tga_source_struct));
+ source->cinfo = cinfo; /* make back link for subroutines */
+ /* Fill in method ptrs, except get_pixel_rows which start_input sets */
+ source->pub.start_input = start_input_tga;
+ source->pub.finish_input = finish_input_tga;
+
+ return (cjpeg_source_ptr) source;
+}
+
+#endif /* TARGA_SUPPORTED */
diff --git a/Source/LibJPEG/structure.txt b/Source/LibJPEG/structure.txt
new file mode 100644
index 0000000..fe88701
--- /dev/null
+++ b/Source/LibJPEG/structure.txt
@@ -0,0 +1,945 @@
+IJG JPEG LIBRARY: SYSTEM ARCHITECTURE
+
+Copyright (C) 1991-2009, Thomas G. Lane, Guido Vollbeding.
+This file is part of the Independent JPEG Group's software.
+For conditions of distribution and use, see the accompanying README file.
+
+
+This file provides an overview of the architecture of the IJG JPEG software;
+that is, the functions of the various modules in the system and the interfaces
+between modules. For more precise details about any data structure or calling
+convention, see the include files and comments in the source code.
+
+We assume that the reader is already somewhat familiar with the JPEG standard.
+The README file includes references for learning about JPEG. The file
+libjpeg.txt describes the library from the viewpoint of an application
+programmer using the library; it's best to read that file before this one.
+Also, the file coderules.txt describes the coding style conventions we use.
+
+In this document, JPEG-specific terminology follows the JPEG standard:
+ A "component" means a color channel, e.g., Red or Luminance.
+ A "sample" is a single component value (i.e., one number in the image data).
+ A "coefficient" is a frequency coefficient (a DCT transform output number).
+ A "block" is an 8x8 group of samples or coefficients.
+ An "MCU" (minimum coded unit) is an interleaved set of blocks of size
+ determined by the sampling factors, or a single block in a
+ noninterleaved scan.
+We do not use the terms "pixel" and "sample" interchangeably. When we say
+pixel, we mean an element of the full-size image, while a sample is an element
+of the downsampled image. Thus the number of samples may vary across
+components while the number of pixels does not. (This terminology is not used
+rigorously throughout the code, but it is used in places where confusion would
+otherwise result.)
+
+
+*** System features ***
+
+The IJG distribution contains two parts:
+ * A subroutine library for JPEG compression and decompression.
+ * cjpeg/djpeg, two sample applications that use the library to transform
+ JFIF JPEG files to and from several other image formats.
+cjpeg/djpeg are of no great intellectual complexity: they merely add a simple
+command-line user interface and I/O routines for several uncompressed image
+formats. This document concentrates on the library itself.
+
+We desire the library to be capable of supporting all JPEG baseline, extended
+sequential, and progressive DCT processes. Hierarchical processes are not
+supported.
+
+The library does not support the lossless (spatial) JPEG process. Lossless
+JPEG shares little or no code with lossy JPEG, and would normally be used
+without the extensive pre- and post-processing provided by this library.
+We feel that lossless JPEG is better handled by a separate library.
+
+Within these limits, any set of compression parameters allowed by the JPEG
+spec should be readable for decompression. (We can be more restrictive about
+what formats we can generate.) Although the system design allows for all
+parameter values, some uncommon settings are not yet implemented and may
+never be; nonintegral sampling ratios are the prime example. Furthermore,
+we treat 8-bit vs. 12-bit data precision as a compile-time switch, not a
+run-time option, because most machines can store 8-bit pixels much more
+compactly than 12-bit.
+
+By itself, the library handles only interchange JPEG datastreams --- in
+particular the widely used JFIF file format. The library can be used by
+surrounding code to process interchange or abbreviated JPEG datastreams that
+are embedded in more complex file formats. (For example, libtiff uses this
+library to implement JPEG compression within the TIFF file format.)
+
+The library includes a substantial amount of code that is not covered by the
+JPEG standard but is necessary for typical applications of JPEG. These
+functions preprocess the image before JPEG compression or postprocess it after
+decompression. They include colorspace conversion, downsampling/upsampling,
+and color quantization. This code can be omitted if not needed.
+
+A wide range of quality vs. speed tradeoffs are possible in JPEG processing,
+and even more so in decompression postprocessing. The decompression library
+provides multiple implementations that cover most of the useful tradeoffs,
+ranging from very-high-quality down to fast-preview operation. On the
+compression side we have generally not provided low-quality choices, since
+compression is normally less time-critical. It should be understood that the
+low-quality modes may not meet the JPEG standard's accuracy requirements;
+nonetheless, they are useful for viewers.
+
+
+*** Portability issues ***
+
+Portability is an essential requirement for the library. The key portability
+issues that show up at the level of system architecture are:
+
+1. Memory usage. We want the code to be able to run on PC-class machines
+with limited memory. Images should therefore be processed sequentially (in
+strips), to avoid holding the whole image in memory at once. Where a
+full-image buffer is necessary, we should be able to use either virtual memory
+or temporary files.
+
+2. Near/far pointer distinction. To run efficiently on 80x86 machines, the
+code should distinguish "small" objects (kept in near data space) from
+"large" ones (kept in far data space). This is an annoying restriction, but
+fortunately it does not impact code quality for less brain-damaged machines,
+and the source code clutter turns out to be minimal with sufficient use of
+pointer typedefs.
+
+3. Data precision. We assume that "char" is at least 8 bits, "short" and
+"int" at least 16, "long" at least 32. The code will work fine with larger
+data sizes, although memory may be used inefficiently in some cases. However,
+the JPEG compressed datastream must ultimately appear on external storage as a
+sequence of 8-bit bytes if it is to conform to the standard. This may pose a
+problem on machines where char is wider than 8 bits. The library represents
+compressed data as an array of values of typedef JOCTET. If no data type
+exactly 8 bits wide is available, custom data source and data destination
+modules must be written to unpack and pack the chosen JOCTET datatype into
+8-bit external representation.
+
+
+*** System overview ***
+
+The compressor and decompressor are each divided into two main sections:
+the JPEG compressor or decompressor proper, and the preprocessing or
+postprocessing functions. The interface between these two sections is the
+image data that the official JPEG spec regards as its input or output: this
+data is in the colorspace to be used for compression, and it is downsampled
+to the sampling factors to be used. The preprocessing and postprocessing
+steps are responsible for converting a normal image representation to or from
+this form. (Those few applications that want to deal with YCbCr downsampled
+data can skip the preprocessing or postprocessing step.)
+
+Looking more closely, the compressor library contains the following main
+elements:
+
+ Preprocessing:
+ * Color space conversion (e.g., RGB to YCbCr).
+ * Edge expansion and downsampling. Optionally, this step can do simple
+ smoothing --- this is often helpful for low-quality source data.
+ JPEG proper:
+ * MCU assembly, DCT, quantization.
+ * Entropy coding (sequential or progressive, Huffman or arithmetic).
+
+In addition to these modules we need overall control, marker generation,
+and support code (memory management & error handling). There is also a
+module responsible for physically writing the output data --- typically
+this is just an interface to fwrite(), but some applications may need to
+do something else with the data.
+
+The decompressor library contains the following main elements:
+
+ JPEG proper:
+ * Entropy decoding (sequential or progressive, Huffman or arithmetic).
+ * Dequantization, inverse DCT, MCU disassembly.
+ Postprocessing:
+ * Upsampling. Optionally, this step may be able to do more general
+ rescaling of the image.
+ * Color space conversion (e.g., YCbCr to RGB). This step may also
+ provide gamma adjustment [ currently it does not ].
+ * Optional color quantization (e.g., reduction to 256 colors).
+ * Optional color precision reduction (e.g., 24-bit to 15-bit color).
+ [This feature is not currently implemented.]
+
+We also need overall control, marker parsing, and a data source module.
+The support code (memory management & error handling) can be shared with
+the compression half of the library.
+
+There may be several implementations of each of these elements, particularly
+in the decompressor, where a wide range of speed/quality tradeoffs is very
+useful. It must be understood that some of the best speedups involve
+merging adjacent steps in the pipeline. For example, upsampling, color space
+conversion, and color quantization might all be done at once when using a
+low-quality ordered-dither technique. The system architecture is designed to
+allow such merging where appropriate.
+
+
+Note: it is convenient to regard edge expansion (padding to block boundaries)
+as a preprocessing/postprocessing function, even though the JPEG spec includes
+it in compression/decompression. We do this because downsampling/upsampling
+can be simplified a little if they work on padded data: it's not necessary to
+have special cases at the right and bottom edges. Therefore the interface
+buffer is always an integral number of blocks wide and high, and we expect
+compression preprocessing to pad the source data properly. Padding will occur
+only to the next block (8-sample) boundary. In an interleaved-scan situation,
+additional dummy blocks may be used to fill out MCUs, but the MCU assembly and
+disassembly logic will create or discard these blocks internally. (This is
+advantageous for speed reasons, since we avoid DCTing the dummy blocks.
+It also permits a small reduction in file size, because the compressor can
+choose dummy block contents so as to minimize their size in compressed form.
+Finally, it makes the interface buffer specification independent of whether
+the file is actually interleaved or not.) Applications that wish to deal
+directly with the downsampled data must provide similar buffering and padding
+for odd-sized images.
+
+
+*** Poor man's object-oriented programming ***
+
+It should be clear by now that we have a lot of quasi-independent processing
+steps, many of which have several possible behaviors. To avoid cluttering the
+code with lots of switch statements, we use a simple form of object-style
+programming to separate out the different possibilities.
+
+For example, two different color quantization algorithms could be implemented
+as two separate modules that present the same external interface; at runtime,
+the calling code will access the proper module indirectly through an "object".
+
+We can get the limited features we need while staying within portable C.
+The basic tool is a function pointer. An "object" is just a struct
+containing one or more function pointer fields, each of which corresponds to
+a method name in real object-oriented languages. During initialization we
+fill in the function pointers with references to whichever module we have
+determined we need to use in this run. Then invocation of the module is done
+by indirecting through a function pointer; on most machines this is no more
+expensive than a switch statement, which would be the only other way of
+making the required run-time choice. The really significant benefit, of
+course, is keeping the source code clean and well structured.
+
+We can also arrange to have private storage that varies between different
+implementations of the same kind of object. We do this by making all the
+module-specific object structs be separately allocated entities, which will
+be accessed via pointers in the master compression or decompression struct.
+The "public" fields or methods for a given kind of object are specified by
+a commonly known struct. But a module's initialization code can allocate
+a larger struct that contains the common struct as its first member, plus
+additional private fields. With appropriate pointer casting, the module's
+internal functions can access these private fields. (For a simple example,
+see jdatadst.c, which implements the external interface specified by struct
+jpeg_destination_mgr, but adds extra fields.)
+
+(Of course this would all be a lot easier if we were using C++, but we are
+not yet prepared to assume that everyone has a C++ compiler.)
+
+An important benefit of this scheme is that it is easy to provide multiple
+versions of any method, each tuned to a particular case. While a lot of
+precalculation might be done to select an optimal implementation of a method,
+the cost per invocation is constant. For example, the upsampling step might
+have a "generic" method, plus one or more "hardwired" methods for the most
+popular sampling factors; the hardwired methods would be faster because they'd
+use straight-line code instead of for-loops. The cost to determine which
+method to use is paid only once, at startup, and the selection criteria are
+hidden from the callers of the method.
+
+This plan differs a little bit from usual object-oriented structures, in that
+only one instance of each object class will exist during execution. The
+reason for having the class structure is that on different runs we may create
+different instances (choose to execute different modules). You can think of
+the term "method" as denoting the common interface presented by a particular
+set of interchangeable functions, and "object" as denoting a group of related
+methods, or the total shared interface behavior of a group of modules.
+
+
+*** Overall control structure ***
+
+We previously mentioned the need for overall control logic in the compression
+and decompression libraries. In IJG implementations prior to v5, overall
+control was mostly provided by "pipeline control" modules, which proved to be
+large, unwieldy, and hard to understand. To improve the situation, the
+control logic has been subdivided into multiple modules. The control modules
+consist of:
+
+1. Master control for module selection and initialization. This has two
+responsibilities:
+
+ 1A. Startup initialization at the beginning of image processing.
+ The individual processing modules to be used in this run are selected
+ and given initialization calls.
+
+ 1B. Per-pass control. This determines how many passes will be performed
+ and calls each active processing module to configure itself
+ appropriately at the beginning of each pass. End-of-pass processing,
+ where necessary, is also invoked from the master control module.
+
+ Method selection is partially distributed, in that a particular processing
+ module may contain several possible implementations of a particular method,
+ which it will select among when given its initialization call. The master
+ control code need only be concerned with decisions that affect more than
+ one module.
+
+2. Data buffering control. A separate control module exists for each
+ inter-processing-step data buffer. This module is responsible for
+ invoking the processing steps that write or read that data buffer.
+
+Each buffer controller sees the world as follows:
+
+input data => processing step A => buffer => processing step B => output data
+ | | |
+ ------------------ controller ------------------
+
+The controller knows the dataflow requirements of steps A and B: how much data
+they want to accept in one chunk and how much they output in one chunk. Its
+function is to manage its buffer and call A and B at the proper times.
+
+A data buffer control module may itself be viewed as a processing step by a
+higher-level control module; thus the control modules form a binary tree with
+elementary processing steps at the leaves of the tree.
+
+The control modules are objects. A considerable amount of flexibility can
+be had by replacing implementations of a control module. For example:
+* Merging of adjacent steps in the pipeline is done by replacing a control
+ module and its pair of processing-step modules with a single processing-
+ step module. (Hence the possible merges are determined by the tree of
+ control modules.)
+* In some processing modes, a given interstep buffer need only be a "strip"
+ buffer large enough to accommodate the desired data chunk sizes. In other
+ modes, a full-image buffer is needed and several passes are required.
+ The control module determines which kind of buffer is used and manipulates
+ virtual array buffers as needed. One or both processing steps may be
+ unaware of the multi-pass behavior.
+
+In theory, we might be able to make all of the data buffer controllers
+interchangeable and provide just one set of implementations for all. In
+practice, each one contains considerable special-case processing for its
+particular job. The buffer controller concept should be regarded as an
+overall system structuring principle, not as a complete description of the
+task performed by any one controller.
+
+
+*** Compression object structure ***
+
+Here is a sketch of the logical structure of the JPEG compression library:
+
+ |-- Colorspace conversion
+ |-- Preprocessing controller --|
+ | |-- Downsampling
+Main controller --|
+ | |-- Forward DCT, quantize
+ |-- Coefficient controller --|
+ |-- Entropy encoding
+
+This sketch also describes the flow of control (subroutine calls) during
+typical image data processing. Each of the components shown in the diagram is
+an "object" which may have several different implementations available. One
+or more source code files contain the actual implementation(s) of each object.
+
+The objects shown above are:
+
+* Main controller: buffer controller for the subsampled-data buffer, which
+ holds the preprocessed input data. This controller invokes preprocessing to
+ fill the subsampled-data buffer, and JPEG compression to empty it. There is
+ usually no need for a full-image buffer here; a strip buffer is adequate.
+
+* Preprocessing controller: buffer controller for the downsampling input data
+ buffer, which lies between colorspace conversion and downsampling. Note
+ that a unified conversion/downsampling module would probably replace this
+ controller entirely.
+
+* Colorspace conversion: converts application image data into the desired
+ JPEG color space; also changes the data from pixel-interleaved layout to
+ separate component planes. Processes one pixel row at a time.
+
+* Downsampling: performs reduction of chroma components as required.
+ Optionally may perform pixel-level smoothing as well. Processes a "row
+ group" at a time, where a row group is defined as Vmax pixel rows of each
+ component before downsampling, and Vk sample rows afterwards (remember Vk
+ differs across components). Some downsampling or smoothing algorithms may
+ require context rows above and below the current row group; the
+ preprocessing controller is responsible for supplying these rows via proper
+ buffering. The downsampler is responsible for edge expansion at the right
+ edge (i.e., extending each sample row to a multiple of 8 samples); but the
+ preprocessing controller is responsible for vertical edge expansion (i.e.,
+ duplicating the bottom sample row as needed to make a multiple of 8 rows).
+
+* Coefficient controller: buffer controller for the DCT-coefficient data.
+ This controller handles MCU assembly, including insertion of dummy DCT
+ blocks when needed at the right or bottom edge. When performing
+ Huffman-code optimization or emitting a multiscan JPEG file, this
+ controller is responsible for buffering the full image. The equivalent of
+ one fully interleaved MCU row of subsampled data is processed per call,
+ even when the JPEG file is noninterleaved.
+
+* Forward DCT and quantization: Perform DCT, quantize, and emit coefficients.
+ Works on one or more DCT blocks at a time. (Note: the coefficients are now
+ emitted in normal array order, which the entropy encoder is expected to
+ convert to zigzag order as necessary. Prior versions of the IJG code did
+ the conversion to zigzag order within the quantization step.)
+
+* Entropy encoding: Perform Huffman or arithmetic entropy coding and emit the
+ coded data to the data destination module. Works on one MCU per call.
+ For progressive JPEG, the same DCT blocks are fed to the entropy coder
+ during each pass, and the coder must emit the appropriate subset of
+ coefficients.
+
+In addition to the above objects, the compression library includes these
+objects:
+
+* Master control: determines the number of passes required, controls overall
+ and per-pass initialization of the other modules.
+
+* Marker writing: generates JPEG markers (except for RSTn, which is emitted
+ by the entropy encoder when needed).
+
+* Data destination manager: writes the output JPEG datastream to its final
+ destination (e.g., a file). The destination manager supplied with the
+ library knows how to write to a stdio stream; for other behaviors, the
+ surrounding application may provide its own destination manager.
+
+* Memory manager: allocates and releases memory, controls virtual arrays
+ (with backing store management, where required).
+
+* Error handler: performs formatting and output of error and trace messages;
+ determines handling of nonfatal errors. The surrounding application may
+ override some or all of this object's methods to change error handling.
+
+* Progress monitor: supports output of "percent-done" progress reports.
+ This object represents an optional callback to the surrounding application:
+ if wanted, it must be supplied by the application.
+
+The error handler, destination manager, and progress monitor objects are
+defined as separate objects in order to simplify application-specific
+customization of the JPEG library. A surrounding application may override
+individual methods or supply its own all-new implementation of one of these
+objects. The object interfaces for these objects are therefore treated as
+part of the application interface of the library, whereas the other objects
+are internal to the library.
+
+The error handler and memory manager are shared by JPEG compression and
+decompression; the progress monitor, if used, may be shared as well.
+
+
+*** Decompression object structure ***
+
+Here is a sketch of the logical structure of the JPEG decompression library:
+
+ |-- Entropy decoding
+ |-- Coefficient controller --|
+ | |-- Dequantize, Inverse DCT
+Main controller --|
+ | |-- Upsampling
+ |-- Postprocessing controller --| |-- Colorspace conversion
+ |-- Color quantization
+ |-- Color precision reduction
+
+As before, this diagram also represents typical control flow. The objects
+shown are:
+
+* Main controller: buffer controller for the subsampled-data buffer, which
+ holds the output of JPEG decompression proper. This controller's primary
+ task is to feed the postprocessing procedure. Some upsampling algorithms
+ may require context rows above and below the current row group; when this
+ is true, the main controller is responsible for managing its buffer so as
+ to make context rows available. In the current design, the main buffer is
+ always a strip buffer; a full-image buffer is never required.
+
+* Coefficient controller: buffer controller for the DCT-coefficient data.
+ This controller handles MCU disassembly, including deletion of any dummy
+ DCT blocks at the right or bottom edge. When reading a multiscan JPEG
+ file, this controller is responsible for buffering the full image.
+ (Buffering DCT coefficients, rather than samples, is necessary to support
+ progressive JPEG.) The equivalent of one fully interleaved MCU row of
+ subsampled data is processed per call, even when the source JPEG file is
+ noninterleaved.
+
+* Entropy decoding: Read coded data from the data source module and perform
+ Huffman or arithmetic entropy decoding. Works on one MCU per call.
+ For progressive JPEG decoding, the coefficient controller supplies the prior
+ coefficients of each MCU (initially all zeroes), which the entropy decoder
+ modifies in each scan.
+
+* Dequantization and inverse DCT: like it says. Note that the coefficients
+ buffered by the coefficient controller have NOT been dequantized; we
+ merge dequantization and inverse DCT into a single step for speed reasons.
+ When scaled-down output is asked for, simplified DCT algorithms may be used
+ that need fewer coefficients and emit fewer samples per DCT block, not the
+ full 8x8. Works on one DCT block at a time.
+
+* Postprocessing controller: buffer controller for the color quantization
+ input buffer, when quantization is in use. (Without quantization, this
+ controller just calls the upsampler.) For two-pass quantization, this
+ controller is responsible for buffering the full-image data.
+
+* Upsampling: restores chroma components to full size. (May support more
+ general output rescaling, too. Note that if undersized DCT outputs have
+ been emitted by the DCT module, this module must adjust so that properly
+ sized outputs are created.) Works on one row group at a time. This module
+ also calls the color conversion module, so its top level is effectively a
+ buffer controller for the upsampling->color conversion buffer. However, in
+ all but the highest-quality operating modes, upsampling and color
+ conversion are likely to be merged into a single step.
+
+* Colorspace conversion: convert from JPEG color space to output color space,
+ and change data layout from separate component planes to pixel-interleaved.
+ Works on one pixel row at a time.
+
+* Color quantization: reduce the data to colormapped form, using either an
+ externally specified colormap or an internally generated one. This module
+ is not used for full-color output. Works on one pixel row at a time; may
+ require two passes to generate a color map. Note that the output will
+ always be a single component representing colormap indexes. In the current
+ design, the output values are JSAMPLEs, so an 8-bit compilation cannot
+ quantize to more than 256 colors. This is unlikely to be a problem in
+ practice.
+
+* Color reduction: this module handles color precision reduction, e.g.,
+ generating 15-bit color (5 bits/primary) from JPEG's 24-bit output.
+ Not quite clear yet how this should be handled... should we merge it with
+ colorspace conversion???
+
+Note that some high-speed operating modes might condense the entire
+postprocessing sequence to a single module (upsample, color convert, and
+quantize in one step).
+
+In addition to the above objects, the decompression library includes these
+objects:
+
+* Master control: determines the number of passes required, controls overall
+ and per-pass initialization of the other modules. This is subdivided into
+ input and output control: jdinput.c controls only input-side processing,
+ while jdmaster.c handles overall initialization and output-side control.
+
+* Marker reading: decodes JPEG markers (except for RSTn).
+
+* Data source manager: supplies the input JPEG datastream. The source
+ manager supplied with the library knows how to read from a stdio stream;
+ for other behaviors, the surrounding application may provide its own source
+ manager.
+
+* Memory manager: same as for compression library.
+
+* Error handler: same as for compression library.
+
+* Progress monitor: same as for compression library.
+
+As with compression, the data source manager, error handler, and progress
+monitor are candidates for replacement by a surrounding application.
+
+
+*** Decompression input and output separation ***
+
+To support efficient incremental display of progressive JPEG files, the
+decompressor is divided into two sections that can run independently:
+
+1. Data input includes marker parsing, entropy decoding, and input into the
+ coefficient controller's DCT coefficient buffer. Note that this
+ processing is relatively cheap and fast.
+
+2. Data output reads from the DCT coefficient buffer and performs the IDCT
+ and all postprocessing steps.
+
+For a progressive JPEG file, the data input processing is allowed to get
+arbitrarily far ahead of the data output processing. (This occurs only
+if the application calls jpeg_consume_input(); otherwise input and output
+run in lockstep, since the input section is called only when the output
+section needs more data.) In this way the application can avoid making
+extra display passes when data is arriving faster than the display pass
+can run. Furthermore, it is possible to abort an output pass without
+losing anything, since the coefficient buffer is read-only as far as the
+output section is concerned. See libjpeg.txt for more detail.
+
+A full-image coefficient array is only created if the JPEG file has multiple
+scans (or if the application specifies buffered-image mode anyway). When
+reading a single-scan file, the coefficient controller normally creates only
+a one-MCU buffer, so input and output processing must run in lockstep in this
+case. jpeg_consume_input() is effectively a no-op in this situation.
+
+The main impact of dividing the decompressor in this fashion is that we must
+be very careful with shared variables in the cinfo data structure. Each
+variable that can change during the course of decompression must be
+classified as belonging to data input or data output, and each section must
+look only at its own variables. For example, the data output section may not
+depend on any of the variables that describe the current scan in the JPEG
+file, because these may change as the data input section advances into a new
+scan.
+
+The progress monitor is (somewhat arbitrarily) defined to treat input of the
+file as one pass when buffered-image mode is not used, and to ignore data
+input work completely when buffered-image mode is used. Note that the
+library has no reliable way to predict the number of passes when dealing
+with a progressive JPEG file, nor can it predict the number of output passes
+in buffered-image mode. So the work estimate is inherently bogus anyway.
+
+No comparable division is currently made in the compression library, because
+there isn't any real need for it.
+
+
+*** Data formats ***
+
+Arrays of pixel sample values use the following data structure:
+
+ typedef something JSAMPLE; a pixel component value, 0..MAXJSAMPLE
+ typedef JSAMPLE *JSAMPROW; ptr to a row of samples
+ typedef JSAMPROW *JSAMPARRAY; ptr to a list of rows
+ typedef JSAMPARRAY *JSAMPIMAGE; ptr to a list of color-component arrays
+
+The basic element type JSAMPLE will typically be one of unsigned char,
+(signed) char, or short. Short will be used if samples wider than 8 bits are
+to be supported (this is a compile-time option). Otherwise, unsigned char is
+used if possible. If the compiler only supports signed chars, then it is
+necessary to mask off the value when reading. Thus, all reads of JSAMPLE
+values must be coded as "GETJSAMPLE(value)", where the macro will be defined
+as "((value) & 0xFF)" on signed-char machines and "((int) (value))" elsewhere.
+
+With these conventions, JSAMPLE values can be assumed to be >= 0. This helps
+simplify correct rounding during downsampling, etc. The JPEG standard's
+specification that sample values run from -128..127 is accommodated by
+subtracting 128 from the sample value in the DCT step. Similarly, during
+decompression the output of the IDCT step will be immediately shifted back to
+0..255. (NB: different values are required when 12-bit samples are in use.
+The code is written in terms of MAXJSAMPLE and CENTERJSAMPLE, which will be
+defined as 255 and 128 respectively in an 8-bit implementation, and as 4095
+and 2048 in a 12-bit implementation.)
+
+We use a pointer per row, rather than a two-dimensional JSAMPLE array. This
+choice costs only a small amount of memory and has several benefits:
+* Code using the data structure doesn't need to know the allocated width of
+ the rows. This simplifies edge expansion/compression, since we can work
+ in an array that's wider than the logical picture width.
+* Indexing doesn't require multiplication; this is a performance win on many
+ machines.
+* Arrays with more than 64K total elements can be supported even on machines
+ where malloc() cannot allocate chunks larger than 64K.
+* The rows forming a component array may be allocated at different times
+ without extra copying. This trick allows some speedups in smoothing steps
+ that need access to the previous and next rows.
+
+Note that each color component is stored in a separate array; we don't use the
+traditional layout in which the components of a pixel are stored together.
+This simplifies coding of modules that work on each component independently,
+because they don't need to know how many components there are. Furthermore,
+we can read or write each component to a temporary file independently, which
+is helpful when dealing with noninterleaved JPEG files.
+
+In general, a specific sample value is accessed by code such as
+ GETJSAMPLE(image[colorcomponent][row][col])
+where col is measured from the image left edge, but row is measured from the
+first sample row currently in memory. Either of the first two indexings can
+be precomputed by copying the relevant pointer.
+
+
+Since most image-processing applications prefer to work on images in which
+the components of a pixel are stored together, the data passed to or from the
+surrounding application uses the traditional convention: a single pixel is
+represented by N consecutive JSAMPLE values, and an image row is an array of
+(# of color components)*(image width) JSAMPLEs. One or more rows of data can
+be represented by a pointer of type JSAMPARRAY in this scheme. This scheme is
+converted to component-wise storage inside the JPEG library. (Applications
+that want to skip JPEG preprocessing or postprocessing will have to contend
+with component-wise storage.)
+
+
+Arrays of DCT-coefficient values use the following data structure:
+
+ typedef short JCOEF; a 16-bit signed integer
+ typedef JCOEF JBLOCK[DCTSIZE2]; an 8x8 block of coefficients
+ typedef JBLOCK *JBLOCKROW; ptr to one horizontal row of 8x8 blocks
+ typedef JBLOCKROW *JBLOCKARRAY; ptr to a list of such rows
+ typedef JBLOCKARRAY *JBLOCKIMAGE; ptr to a list of color component arrays
+
+The underlying type is at least a 16-bit signed integer; while "short" is big
+enough on all machines of interest, on some machines it is preferable to use
+"int" for speed reasons, despite the storage cost. Coefficients are grouped
+into 8x8 blocks (but we always use #defines DCTSIZE and DCTSIZE2 rather than
+"8" and "64").
+
+The contents of a coefficient block may be in either "natural" or zigzagged
+order, and may be true values or divided by the quantization coefficients,
+depending on where the block is in the processing pipeline. In the current
+library, coefficient blocks are kept in natural order everywhere; the entropy
+codecs zigzag or dezigzag the data as it is written or read. The blocks
+contain quantized coefficients everywhere outside the DCT/IDCT subsystems.
+(This latter decision may need to be revisited to support variable
+quantization a la JPEG Part 3.)
+
+Notice that the allocation unit is now a row of 8x8 blocks, corresponding to
+eight rows of samples. Otherwise the structure is much the same as for
+samples, and for the same reasons.
+
+On machines where malloc() can't handle a request bigger than 64Kb, this data
+structure limits us to rows of less than 512 JBLOCKs, or a picture width of
+4000+ pixels. This seems an acceptable restriction.
+
+
+On 80x86 machines, the bottom-level pointer types (JSAMPROW and JBLOCKROW)
+must be declared as "far" pointers, but the upper levels can be "near"
+(implying that the pointer lists are allocated in the DS segment).
+We use a #define symbol FAR, which expands to the "far" keyword when
+compiling on 80x86 machines and to nothing elsewhere.
+
+
+*** Suspendable processing ***
+
+In some applications it is desirable to use the JPEG library as an
+incremental, memory-to-memory filter. In this situation the data source or
+destination may be a limited-size buffer, and we can't rely on being able to
+empty or refill the buffer at arbitrary times. Instead the application would
+like to have control return from the library at buffer overflow/underrun, and
+then resume compression or decompression at a later time.
+
+This scenario is supported for simple cases. (For anything more complex, we
+recommend that the application "bite the bullet" and develop real multitasking
+capability.) The libjpeg.txt file goes into more detail about the usage and
+limitations of this capability; here we address the implications for library
+structure.
+
+The essence of the problem is that the entropy codec (coder or decoder) must
+be prepared to stop at arbitrary times. In turn, the controllers that call
+the entropy codec must be able to stop before having produced or consumed all
+the data that they normally would handle in one call. That part is reasonably
+straightforward: we make the controller call interfaces include "progress
+counters" which indicate the number of data chunks successfully processed, and
+we require callers to test the counter rather than just assume all of the data
+was processed.
+
+Rather than trying to restart at an arbitrary point, the current Huffman
+codecs are designed to restart at the beginning of the current MCU after a
+suspension due to buffer overflow/underrun. At the start of each call, the
+codec's internal state is loaded from permanent storage (in the JPEG object
+structures) into local variables. On successful completion of the MCU, the
+permanent state is updated. (This copying is not very expensive, and may even
+lead to *improved* performance if the local variables can be registerized.)
+If a suspension occurs, the codec simply returns without updating the state,
+thus effectively reverting to the start of the MCU. Note that this implies
+leaving some data unprocessed in the source/destination buffer (ie, the
+compressed partial MCU). The data source/destination module interfaces are
+specified so as to make this possible. This also implies that the data buffer
+must be large enough to hold a worst-case compressed MCU; a couple thousand
+bytes should be enough.
+
+In a successive-approximation AC refinement scan, the progressive Huffman
+decoder has to be able to undo assignments of newly nonzero coefficients if it
+suspends before the MCU is complete, since decoding requires distinguishing
+previously-zero and previously-nonzero coefficients. This is a bit tedious
+but probably won't have much effect on performance. Other variants of Huffman
+decoding need not worry about this, since they will just store the same values
+again if forced to repeat the MCU.
+
+This approach would probably not work for an arithmetic codec, since its
+modifiable state is quite large and couldn't be copied cheaply. Instead it
+would have to suspend and resume exactly at the point of the buffer end.
+
+The JPEG marker reader is designed to cope with suspension at an arbitrary
+point. It does so by backing up to the start of the marker parameter segment,
+so the data buffer must be big enough to hold the largest marker of interest.
+Again, a couple KB should be adequate. (A special "skip" convention is used
+to bypass COM and APPn markers, so these can be larger than the buffer size
+without causing problems; otherwise a 64K buffer would be needed in the worst
+case.)
+
+The JPEG marker writer currently does *not* cope with suspension.
+We feel that this is not necessary; it is much easier simply to require
+the application to ensure there is enough buffer space before starting. (An
+empty 2K buffer is more than sufficient for the header markers; and ensuring
+there are a dozen or two bytes available before calling jpeg_finish_compress()
+will suffice for the trailer.) This would not work for writing multi-scan
+JPEG files, but we simply do not intend to support that capability with
+suspension.
+
+
+*** Memory manager services ***
+
+The JPEG library's memory manager controls allocation and deallocation of
+memory, and it manages large "virtual" data arrays on machines where the
+operating system does not provide virtual memory. Note that the same
+memory manager serves both compression and decompression operations.
+
+In all cases, allocated objects are tied to a particular compression or
+decompression master record, and they will be released when that master
+record is destroyed.
+
+The memory manager does not provide explicit deallocation of objects.
+Instead, objects are created in "pools" of free storage, and a whole pool
+can be freed at once. This approach helps prevent storage-leak bugs, and
+it speeds up operations whenever malloc/free are slow (as they often are).
+The pools can be regarded as lifetime identifiers for objects. Two
+pools/lifetimes are defined:
+ * JPOOL_PERMANENT lasts until master record is destroyed
+ * JPOOL_IMAGE lasts until done with image (JPEG datastream)
+Permanent lifetime is used for parameters and tables that should be carried
+across from one datastream to another; this includes all application-visible
+parameters. Image lifetime is used for everything else. (A third lifetime,
+JPOOL_PASS = one processing pass, was originally planned. However it was
+dropped as not being worthwhile. The actual usage patterns are such that the
+peak memory usage would be about the same anyway; and having per-pass storage
+substantially complicates the virtual memory allocation rules --- see below.)
+
+The memory manager deals with three kinds of object:
+1. "Small" objects. Typically these require no more than 10K-20K total.
+2. "Large" objects. These may require tens to hundreds of K depending on
+ image size. Semantically they behave the same as small objects, but we
+ distinguish them for two reasons:
+ * On MS-DOS machines, large objects are referenced by FAR pointers,
+ small objects by NEAR pointers.
+ * Pool allocation heuristics may differ for large and small objects.
+ Note that individual "large" objects cannot exceed the size allowed by
+ type size_t, which may be 64K or less on some machines.
+3. "Virtual" objects. These are large 2-D arrays of JSAMPLEs or JBLOCKs
+ (typically large enough for the entire image being processed). The
+ memory manager provides stripwise access to these arrays. On machines
+ without virtual memory, the rest of the array may be swapped out to a
+ temporary file.
+
+(Note: JSAMPARRAY and JBLOCKARRAY data structures are a combination of large
+objects for the data proper and small objects for the row pointers. For
+convenience and speed, the memory manager provides single routines to create
+these structures. Similarly, virtual arrays include a small control block
+and a JSAMPARRAY or JBLOCKARRAY working buffer, all created with one call.)
+
+In the present implementation, virtual arrays are only permitted to have image
+lifespan. (Permanent lifespan would not be reasonable, and pass lifespan is
+not very useful since a virtual array's raison d'etre is to store data for
+multiple passes through the image.) We also expect that only "small" objects
+will be given permanent lifespan, though this restriction is not required by
+the memory manager.
+
+In a non-virtual-memory machine, some performance benefit can be gained by
+making the in-memory buffers for virtual arrays be as large as possible.
+(For small images, the buffers might fit entirely in memory, so blind
+swapping would be very wasteful.) The memory manager will adjust the height
+of the buffers to fit within a prespecified maximum memory usage. In order
+to do this in a reasonably optimal fashion, the manager needs to allocate all
+of the virtual arrays at once. Therefore, there isn't a one-step allocation
+routine for virtual arrays; instead, there is a "request" routine that simply
+allocates the control block, and a "realize" routine (called just once) that
+determines space allocation and creates all of the actual buffers. The
+realize routine must allow for space occupied by non-virtual large objects.
+(We don't bother to factor in the space needed for small objects, on the
+grounds that it isn't worth the trouble.)
+
+To support all this, we establish the following protocol for doing business
+with the memory manager:
+ 1. Modules must request virtual arrays (which may have only image lifespan)
+ during the initial setup phase, i.e., in their jinit_xxx routines.
+ 2. All "large" objects (including JSAMPARRAYs and JBLOCKARRAYs) must also be
+ allocated during initial setup.
+ 3. realize_virt_arrays will be called at the completion of initial setup.
+ The above conventions ensure that sufficient information is available
+ for it to choose a good size for virtual array buffers.
+Small objects of any lifespan may be allocated at any time. We expect that
+the total space used for small objects will be small enough to be negligible
+in the realize_virt_arrays computation.
+
+In a virtual-memory machine, we simply pretend that the available space is
+infinite, thus causing realize_virt_arrays to decide that it can allocate all
+the virtual arrays as full-size in-memory buffers. The overhead of the
+virtual-array access protocol is very small when no swapping occurs.
+
+A virtual array can be specified to be "pre-zeroed"; when this flag is set,
+never-yet-written sections of the array are set to zero before being made
+available to the caller. If this flag is not set, never-written sections
+of the array contain garbage. (This feature exists primarily because the
+equivalent logic would otherwise be needed in jdcoefct.c for progressive
+JPEG mode; we may as well make it available for possible other uses.)
+
+The first write pass on a virtual array is required to occur in top-to-bottom
+order; read passes, as well as any write passes after the first one, may
+access the array in any order. This restriction exists partly to simplify
+the virtual array control logic, and partly because some file systems may not
+support seeking beyond the current end-of-file in a temporary file. The main
+implication of this restriction is that rearrangement of rows (such as
+converting top-to-bottom data order to bottom-to-top) must be handled while
+reading data out of the virtual array, not while putting it in.
+
+
+*** Memory manager internal structure ***
+
+To isolate system dependencies as much as possible, we have broken the
+memory manager into two parts. There is a reasonably system-independent
+"front end" (jmemmgr.c) and a "back end" that contains only the code
+likely to change across systems. All of the memory management methods
+outlined above are implemented by the front end. The back end provides
+the following routines for use by the front end (none of these routines
+are known to the rest of the JPEG code):
+
+jpeg_mem_init, jpeg_mem_term system-dependent initialization/shutdown
+
+jpeg_get_small, jpeg_free_small interface to malloc and free library routines
+ (or their equivalents)
+
+jpeg_get_large, jpeg_free_large interface to FAR malloc/free in MSDOS machines;
+ else usually the same as
+ jpeg_get_small/jpeg_free_small
+
+jpeg_mem_available estimate available memory
+
+jpeg_open_backing_store create a backing-store object
+
+read_backing_store, manipulate a backing-store object
+write_backing_store,
+close_backing_store
+
+On some systems there will be more than one type of backing-store object
+(specifically, in MS-DOS a backing store file might be an area of extended
+memory as well as a disk file). jpeg_open_backing_store is responsible for
+choosing how to implement a given object. The read/write/close routines
+are method pointers in the structure that describes a given object; this
+lets them be different for different object types.
+
+It may be necessary to ensure that backing store objects are explicitly
+released upon abnormal program termination. For example, MS-DOS won't free
+extended memory by itself. To support this, we will expect the main program
+or surrounding application to arrange to call self_destruct (typically via
+jpeg_destroy) upon abnormal termination. This may require a SIGINT signal
+handler or equivalent. We don't want to have the back end module install its
+own signal handler, because that would pre-empt the surrounding application's
+ability to control signal handling.
+
+The IJG distribution includes several memory manager back end implementations.
+Usually the same back end should be suitable for all applications on a given
+system, but it is possible for an application to supply its own back end at
+need.
+
+
+*** Implications of DNL marker ***
+
+Some JPEG files may use a DNL marker to postpone definition of the image
+height (this would be useful for a fax-like scanner's output, for instance).
+In these files the SOF marker claims the image height is 0, and you only
+find out the true image height at the end of the first scan.
+
+We could read these files as follows:
+1. Upon seeing zero image height, replace it by 65535 (the maximum allowed).
+2. When the DNL is found, update the image height in the global image
+ descriptor.
+This implies that control modules must avoid making copies of the image
+height, and must re-test for termination after each MCU row. This would
+be easy enough to do.
+
+In cases where image-size data structures are allocated, this approach will
+result in very inefficient use of virtual memory or much-larger-than-necessary
+temporary files. This seems acceptable for something that probably won't be a
+mainstream usage. People might have to forgo use of memory-hogging options
+(such as two-pass color quantization or noninterleaved JPEG files) if they
+want efficient conversion of such files. (One could improve efficiency by
+demanding a user-supplied upper bound for the height, less than 65536; in most
+cases it could be much less.)
+
+The standard also permits the SOF marker to overestimate the image height,
+with a DNL to give the true, smaller height at the end of the first scan.
+This would solve the space problems if the overestimate wasn't too great.
+However, it implies that you don't even know whether DNL will be used.
+
+This leads to a couple of very serious objections:
+1. Testing for a DNL marker must occur in the inner loop of the decompressor's
+ Huffman decoder; this implies a speed penalty whether the feature is used
+ or not.
+2. There is no way to hide the last-minute change in image height from an
+ application using the decoder. Thus *every* application using the IJG
+ library would suffer a complexity penalty whether it cared about DNL or
+ not.
+We currently do not support DNL because of these problems.
+
+A different approach is to insist that DNL-using files be preprocessed by a
+separate program that reads ahead to the DNL, then goes back and fixes the SOF
+marker. This is a much simpler solution and is probably far more efficient.
+Even if one wants piped input, buffering the first scan of the JPEG file needs
+a lot smaller temp file than is implied by the maximum-height method. For
+this approach we'd simply treat DNL as a no-op in the decompressor (at most,
+check that it matches the SOF image height).
+
+We will not worry about making the compressor capable of outputting DNL.
+Something similar to the first scheme above could be applied if anyone ever
+wants to make that work.
diff --git a/Source/LibJPEG/transupp.c b/Source/LibJPEG/transupp.c
new file mode 100644
index 0000000..b89bc9e
--- /dev/null
+++ b/Source/LibJPEG/transupp.c
@@ -0,0 +1,1533 @@
+/*
+ * transupp.c
+ *
+ * Copyright (C) 1997-2009, Thomas G. Lane, Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains image transformation routines and other utility code
+ * used by the jpegtran sample application. These are NOT part of the core
+ * JPEG library. But we keep these routines separate from jpegtran.c to
+ * ease the task of maintaining jpegtran-like programs that have other user
+ * interfaces.
+ */
+
+/* Although this file really shouldn't have access to the library internals,
+ * it's helpful to let it call jround_up() and jcopy_block_row().
+ */
+#define JPEG_INTERNALS
+
+#include "jinclude.h"
+#include "jpeglib.h"
+#include "transupp.h" /* My own external interface */
+#include <ctype.h> /* to declare isdigit() */
+
+
+#if TRANSFORMS_SUPPORTED
+
+/*
+ * Lossless image transformation routines. These routines work on DCT
+ * coefficient arrays and thus do not require any lossy decompression
+ * or recompression of the image.
+ * Thanks to Guido Vollbeding for the initial design and code of this feature,
+ * and to Ben Jackson for introducing the cropping feature.
+ *
+ * Horizontal flipping is done in-place, using a single top-to-bottom
+ * pass through the virtual source array. It will thus be much the
+ * fastest option for images larger than main memory.
+ *
+ * The other routines require a set of destination virtual arrays, so they
+ * need twice as much memory as jpegtran normally does. The destination
+ * arrays are always written in normal scan order (top to bottom) because
+ * the virtual array manager expects this. The source arrays will be scanned
+ * in the corresponding order, which means multiple passes through the source
+ * arrays for most of the transforms. That could result in much thrashing
+ * if the image is larger than main memory.
+ *
+ * If cropping or trimming is involved, the destination arrays may be smaller
+ * than the source arrays. Note it is not possible to do horizontal flip
+ * in-place when a nonzero Y crop offset is specified, since we'd have to move
+ * data from one block row to another but the virtual array manager doesn't
+ * guarantee we can touch more than one row at a time. So in that case,
+ * we have to use a separate destination array.
+ *
+ * Some notes about the operating environment of the individual transform
+ * routines:
+ * 1. Both the source and destination virtual arrays are allocated from the
+ * source JPEG object, and therefore should be manipulated by calling the
+ * source's memory manager.
+ * 2. The destination's component count should be used. It may be smaller
+ * than the source's when forcing to grayscale.
+ * 3. Likewise the destination's sampling factors should be used. When
+ * forcing to grayscale the destination's sampling factors will be all 1,
+ * and we may as well take that as the effective iMCU size.
+ * 4. When "trim" is in effect, the destination's dimensions will be the
+ * trimmed values but the source's will be untrimmed.
+ * 5. When "crop" is in effect, the destination's dimensions will be the
+ * cropped values but the source's will be uncropped. Each transform
+ * routine is responsible for picking up source data starting at the
+ * correct X and Y offset for the crop region. (The X and Y offsets
+ * passed to the transform routines are measured in iMCU blocks of the
+ * destination.)
+ * 6. All the routines assume that the source and destination buffers are
+ * padded out to a full iMCU boundary. This is true, although for the
+ * source buffer it is an undocumented property of jdcoefct.c.
+ */
+
+
+LOCAL(void)
+do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Crop. This is only used when no rotate/flip is requested with the crop. */
+{
+ JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
+ int ci, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ jpeg_component_info *compptr;
+
+ /* We simply have to copy the right amount of data (the destination's
+ * image size) starting at the given X and Y offsets in the source.
+ */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_y + y_crop_blocks,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
+ dst_buffer[offset_y],
+ compptr->width_in_blocks);
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays)
+/* Horizontal flip; done in-place, so no separate dest array is required.
+ * NB: this only works when y_crop_offset is zero.
+ */
+{
+ JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
+ int ci, k, offset_y;
+ JBLOCKARRAY buffer;
+ JCOEFPTR ptr1, ptr2;
+ JCOEF temp1, temp2;
+ jpeg_component_info *compptr;
+
+ /* Horizontal mirroring of DCT blocks is accomplished by swapping
+ * pairs of blocks in-place. Within a DCT block, we perform horizontal
+ * mirroring by changing the signs of odd-numbered columns.
+ * Partial iMCUs at the right edge are left untouched.
+ */
+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ for (blk_y = 0; blk_y < compptr->height_in_blocks;
+ blk_y += compptr->v_samp_factor) {
+ buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ /* Do the mirroring */
+ for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
+ ptr1 = buffer[offset_y][blk_x];
+ ptr2 = buffer[offset_y][comp_width - blk_x - 1];
+ /* this unrolled loop doesn't need to know which row it's on... */
+ for (k = 0; k < DCTSIZE2; k += 2) {
+ temp1 = *ptr1; /* swap even column */
+ temp2 = *ptr2;
+ *ptr1++ = temp2;
+ *ptr2++ = temp1;
+ temp1 = *ptr1; /* swap odd column with sign change */
+ temp2 = *ptr2;
+ *ptr1++ = -temp2;
+ *ptr2++ = -temp1;
+ }
+ }
+ if (x_crop_blocks > 0) {
+ /* Now left-justify the portion of the data to be kept.
+ * We can't use a single jcopy_block_row() call because that routine
+ * depends on memcpy(), whose behavior is unspecified for overlapping
+ * source and destination areas. Sigh.
+ */
+ for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
+ jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
+ buffer[offset_y] + blk_x,
+ (JDIMENSION) 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Horizontal flip in general cropping case */
+{
+ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, k, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Here we must output into a separate array because we can't touch
+ * different rows of a single virtual array simultaneously. Otherwise,
+ * this is essentially the same as the routine above.
+ */
+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_y + y_crop_blocks,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[offset_y];
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Do the mirrorable blocks */
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
+ /* this unrolled loop doesn't need to know which row it's on... */
+ for (k = 0; k < DCTSIZE2; k += 2) {
+ *dst_ptr++ = *src_ptr++; /* copy even column */
+ *dst_ptr++ = - *src_ptr++; /* copy odd column with sign change */
+ }
+ } else {
+ /* Copy last partial block(s) verbatim */
+ jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
+ dst_row_ptr + dst_blk_x,
+ (JDIMENSION) 1);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Vertical flip */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* We output into a separate array because we can't touch different
+ * rows of the source virtual array simultaneously. Otherwise, this
+ * is a pretty straightforward analog of horizontal flip.
+ * Within a DCT block, vertical mirroring is done by changing the signs
+ * of odd-numbered rows.
+ * Partial iMCUs at the bottom edge are copied verbatim.
+ */
+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - y_crop_blocks - dst_blk_y -
+ (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge blocks will be copied verbatim. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_y + y_crop_blocks,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ dst_row_ptr = dst_buffer[offset_y];
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ src_row_ptr += x_crop_blocks;
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* copy even row */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ /* copy odd row with sign change */
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ } else {
+ /* Just copy row verbatim. */
+ jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
+ dst_buffer[offset_y],
+ compptr->width_in_blocks);
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transpose (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transpose source into destination */
+{
+ JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Transposing pixels within a block just requires transposing the
+ * DCT coefficients.
+ * Partial iMCUs at the edges require no special treatment; we simply
+ * process all the available DCT blocks for every component.
+ */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_x + x_crop_blocks,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ src_ptr = src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 90 degree rotation is equivalent to
+ * 1. Transposing the image;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) right edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_width - x_crop_blocks - dst_blk_x -
+ (JDIMENSION) compptr->h_samp_factor,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_x + x_crop_blocks,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ }
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
+ [dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ src_ptr = src_buffer[offset_x]
+ [dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 270 degree rotation is equivalent to
+ * 1. Horizontal mirroring;
+ * 2. Transposing the image.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ /* Because of the horizontal mirror step, we can't process partial iMCUs
+ * at the (output) bottom edge properly. They just get transposed and
+ * not mirrored.
+ */
+ MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_x + x_crop_blocks,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ /* Block is within the mirrorable area. */
+ src_ptr = src_buffer[offset_x]
+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Edge blocks are transposed but not mirrored. */
+ src_ptr = src_buffer[offset_x]
+ [dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* 180 degree rotation is equivalent to
+ * 1. Vertical mirroring;
+ * 2. Horizontal mirroring.
+ * These two steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JBLOCKROW src_row_ptr, dst_row_ptr;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ /* Row is within the vertically mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_height - y_crop_blocks - dst_blk_y -
+ (JDIMENSION) compptr->v_samp_factor,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ } else {
+ /* Bottom-edge rows are only mirrored horizontally. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_y + y_crop_blocks,
+ (JDIMENSION) compptr->v_samp_factor, FALSE);
+ }
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ dst_row_ptr = dst_buffer[offset_y];
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ /* Row is within the mirrorable area. */
+ src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Process the blocks that can be mirrored both ways. */
+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ /* For even row, negate every odd column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ /* For odd row, negate every even column. */
+ for (j = 0; j < DCTSIZE; j += 2) {
+ *dst_ptr++ = - *src_ptr++;
+ *dst_ptr++ = *src_ptr++;
+ }
+ }
+ } else {
+ /* Any remaining right-edge blocks are only mirrored vertically. */
+ src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
+ for (i = 0; i < DCTSIZE; i += 2) {
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = *src_ptr++;
+ for (j = 0; j < DCTSIZE; j++)
+ *dst_ptr++ = - *src_ptr++;
+ }
+ }
+ }
+ } else {
+ /* Remaining rows are just mirrored horizontally. */
+ src_row_ptr = src_buffer[offset_y];
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Process the blocks that can be mirrored. */
+ dst_ptr = dst_row_ptr[dst_blk_x];
+ src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
+ for (i = 0; i < DCTSIZE2; i += 2) {
+ *dst_ptr++ = *src_ptr++;
+ *dst_ptr++ = - *src_ptr++;
+ }
+ } else {
+ /* Any remaining right-edge blocks are only copied. */
+ jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
+ dst_row_ptr + dst_blk_x,
+ (JDIMENSION) 1);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+LOCAL(void)
+do_transverse (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
+ jvirt_barray_ptr *src_coef_arrays,
+ jvirt_barray_ptr *dst_coef_arrays)
+/* Transverse transpose is equivalent to
+ * 1. 180 degree rotation;
+ * 2. Transposition;
+ * or
+ * 1. Horizontal mirroring;
+ * 2. Transposition;
+ * 3. Horizontal mirroring.
+ * These steps are merged into a single processing routine.
+ */
+{
+ JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
+ JDIMENSION x_crop_blocks, y_crop_blocks;
+ int ci, i, j, offset_x, offset_y;
+ JBLOCKARRAY src_buffer, dst_buffer;
+ JCOEFPTR src_ptr, dst_ptr;
+ jpeg_component_info *compptr;
+
+ MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
+ MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
+
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ comp_width = MCU_cols * compptr->h_samp_factor;
+ comp_height = MCU_rows * compptr->v_samp_factor;
+ x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
+ y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
+ for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
+ dst_blk_y += compptr->v_samp_factor) {
+ dst_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, dst_coef_arrays[ci], dst_blk_y,
+ (JDIMENSION) compptr->v_samp_factor, TRUE);
+ for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
+ dst_blk_x += compptr->h_samp_factor) {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ comp_width - x_crop_blocks - dst_blk_x -
+ (JDIMENSION) compptr->h_samp_factor,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ } else {
+ src_buffer = (*srcinfo->mem->access_virt_barray)
+ ((j_common_ptr) srcinfo, src_coef_arrays[ci],
+ dst_blk_x + x_crop_blocks,
+ (JDIMENSION) compptr->h_samp_factor, FALSE);
+ }
+ for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
+ dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
+ if (y_crop_blocks + dst_blk_y < comp_height) {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Block is within the mirrorable area. */
+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ i++;
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ } else {
+ /* Right-edge blocks are mirrored in y only */
+ src_ptr = src_buffer[offset_x]
+ [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++) {
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ j++;
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ } else {
+ if (x_crop_blocks + dst_blk_x < comp_width) {
+ /* Bottom-edge blocks are mirrored in x only */
+ src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
+ [dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ i++;
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = -src_ptr[i*DCTSIZE+j];
+ }
+ } else {
+ /* At lower right corner, just transpose, no mirroring */
+ src_ptr = src_buffer[offset_x]
+ [dst_blk_y + offset_y + y_crop_blocks];
+ for (i = 0; i < DCTSIZE; i++)
+ for (j = 0; j < DCTSIZE; j++)
+ dst_ptr[j*DCTSIZE+i] = src_ptr[i*DCTSIZE+j];
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
+ * Returns TRUE if valid integer found, FALSE if not.
+ * *strptr is advanced over the digit string, and *result is set to its value.
+ */
+
+LOCAL(boolean)
+jt_read_integer (const char ** strptr, JDIMENSION * result)
+{
+ const char * ptr = *strptr;
+ JDIMENSION val = 0;
+
+ for (; isdigit(*ptr); ptr++) {
+ val = val * 10 + (JDIMENSION) (*ptr - '0');
+ }
+ *result = val;
+ if (ptr == *strptr)
+ return FALSE; /* oops, no digits */
+ *strptr = ptr;
+ return TRUE;
+}
+
+
+/* Parse a crop specification (written in X11 geometry style).
+ * The routine returns TRUE if the spec string is valid, FALSE if not.
+ *
+ * The crop spec string should have the format
+ * <width>x<height>{+-}<xoffset>{+-}<yoffset>
+ * where width, height, xoffset, and yoffset are unsigned integers.
+ * Each of the elements can be omitted to indicate a default value.
+ * (A weakness of this style is that it is not possible to omit xoffset
+ * while specifying yoffset, since they look alike.)
+ *
+ * This code is loosely based on XParseGeometry from the X11 distribution.
+ */
+
+GLOBAL(boolean)
+jtransform_parse_crop_spec (jpeg_transform_info *info, const char *spec)
+{
+ info->crop = FALSE;
+ info->crop_width_set = JCROP_UNSET;
+ info->crop_height_set = JCROP_UNSET;
+ info->crop_xoffset_set = JCROP_UNSET;
+ info->crop_yoffset_set = JCROP_UNSET;
+
+ if (isdigit(*spec)) {
+ /* fetch width */
+ if (! jt_read_integer(&spec, &info->crop_width))
+ return FALSE;
+ info->crop_width_set = JCROP_POS;
+ }
+ if (*spec == 'x' || *spec == 'X') {
+ /* fetch height */
+ spec++;
+ if (! jt_read_integer(&spec, &info->crop_height))
+ return FALSE;
+ info->crop_height_set = JCROP_POS;
+ }
+ if (*spec == '+' || *spec == '-') {
+ /* fetch xoffset */
+ info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
+ spec++;
+ if (! jt_read_integer(&spec, &info->crop_xoffset))
+ return FALSE;
+ }
+ if (*spec == '+' || *spec == '-') {
+ /* fetch yoffset */
+ info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
+ spec++;
+ if (! jt_read_integer(&spec, &info->crop_yoffset))
+ return FALSE;
+ }
+ /* We had better have gotten to the end of the string. */
+ if (*spec != '\0')
+ return FALSE;
+ info->crop = TRUE;
+ return TRUE;
+}
+
+
+/* Trim off any partial iMCUs on the indicated destination edge */
+
+LOCAL(void)
+trim_right_edge (jpeg_transform_info *info, JDIMENSION full_width)
+{
+ JDIMENSION MCU_cols;
+
+ MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE);
+ if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
+ full_width / (info->max_h_samp_factor * DCTSIZE))
+ info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE);
+}
+
+LOCAL(void)
+trim_bottom_edge (jpeg_transform_info *info, JDIMENSION full_height)
+{
+ JDIMENSION MCU_rows;
+
+ MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE);
+ if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
+ full_height / (info->max_v_samp_factor * DCTSIZE))
+ info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE);
+}
+
+
+/* Request any required workspace.
+ *
+ * This routine figures out the size that the output image will be
+ * (which implies that all the transform parameters must be set before
+ * it is called).
+ *
+ * We allocate the workspace virtual arrays from the source decompression
+ * object, so that all the arrays (both the original data and the workspace)
+ * will be taken into account while making memory management decisions.
+ * Hence, this routine must be called after jpeg_read_header (which reads
+ * the image dimensions) and before jpeg_read_coefficients (which realizes
+ * the source's virtual arrays).
+ */
+
+GLOBAL(void)
+jtransform_request_workspace (j_decompress_ptr srcinfo,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *coef_arrays = NULL;
+ boolean need_workspace, transpose_it;
+ jpeg_component_info *compptr;
+ JDIMENSION xoffset, yoffset, width_in_iMCUs, height_in_iMCUs;
+ JDIMENSION width_in_blocks, height_in_blocks;
+ int ci, h_samp_factor, v_samp_factor;
+
+ /* Determine number of components in output image */
+ if (info->force_grayscale &&
+ srcinfo->jpeg_color_space == JCS_YCbCr &&
+ srcinfo->num_components == 3) {
+ /* We'll only process the first component */
+ info->num_components = 1;
+ } else {
+ /* Process all the components */
+ info->num_components = srcinfo->num_components;
+ }
+ /* If there is only one output component, force the iMCU size to be 1;
+ * else use the source iMCU size. (This allows us to do the right thing
+ * when reducing color to grayscale, and also provides a handy way of
+ * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
+ */
+
+ switch (info->transform) {
+ case JXFORM_TRANSPOSE:
+ case JXFORM_TRANSVERSE:
+ case JXFORM_ROT_90:
+ case JXFORM_ROT_270:
+ info->output_width = srcinfo->image_height;
+ info->output_height = srcinfo->image_width;
+ if (info->num_components == 1) {
+ info->max_h_samp_factor = 1;
+ info->max_v_samp_factor = 1;
+ } else {
+ info->max_h_samp_factor = srcinfo->max_v_samp_factor;
+ info->max_v_samp_factor = srcinfo->max_h_samp_factor;
+ }
+ break;
+ default:
+ info->output_width = srcinfo->image_width;
+ info->output_height = srcinfo->image_height;
+ if (info->num_components == 1) {
+ info->max_h_samp_factor = 1;
+ info->max_v_samp_factor = 1;
+ } else {
+ info->max_h_samp_factor = srcinfo->max_h_samp_factor;
+ info->max_v_samp_factor = srcinfo->max_v_samp_factor;
+ }
+ break;
+ }
+
+ /* If cropping has been requested, compute the crop area's position and
+ * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
+ */
+ if (info->crop) {
+ /* Insert default values for unset crop parameters */
+ if (info->crop_xoffset_set == JCROP_UNSET)
+ info->crop_xoffset = 0; /* default to +0 */
+ if (info->crop_yoffset_set == JCROP_UNSET)
+ info->crop_yoffset = 0; /* default to +0 */
+ if (info->crop_xoffset >= info->output_width ||
+ info->crop_yoffset >= info->output_height)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
+ if (info->crop_width_set == JCROP_UNSET)
+ info->crop_width = info->output_width - info->crop_xoffset;
+ if (info->crop_height_set == JCROP_UNSET)
+ info->crop_height = info->output_height - info->crop_yoffset;
+ /* Ensure parameters are valid */
+ if (info->crop_width <= 0 || info->crop_width > info->output_width ||
+ info->crop_height <= 0 || info->crop_height > info->output_height ||
+ info->crop_xoffset > info->output_width - info->crop_width ||
+ info->crop_yoffset > info->output_height - info->crop_height)
+ ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
+ /* Convert negative crop offsets into regular offsets */
+ if (info->crop_xoffset_set == JCROP_NEG)
+ xoffset = info->output_width - info->crop_width - info->crop_xoffset;
+ else
+ xoffset = info->crop_xoffset;
+ if (info->crop_yoffset_set == JCROP_NEG)
+ yoffset = info->output_height - info->crop_height - info->crop_yoffset;
+ else
+ yoffset = info->crop_yoffset;
+ /* Now adjust so that upper left corner falls at an iMCU boundary */
+ info->output_width =
+ info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE));
+ info->output_height =
+ info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE));
+ /* Save x/y offsets measured in iMCUs */
+ info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE);
+ info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE);
+ } else {
+ info->x_crop_offset = 0;
+ info->y_crop_offset = 0;
+ }
+
+ /* Figure out whether we need workspace arrays,
+ * and if so whether they are transposed relative to the source.
+ */
+ need_workspace = FALSE;
+ transpose_it = FALSE;
+ switch (info->transform) {
+ case JXFORM_NONE:
+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
+ need_workspace = TRUE;
+ /* No workspace needed if neither cropping nor transforming */
+ break;
+ case JXFORM_FLIP_H:
+ if (info->trim)
+ trim_right_edge(info, srcinfo->image_width);
+ if (info->y_crop_offset != 0)
+ need_workspace = TRUE;
+ /* do_flip_h_no_crop doesn't need a workspace array */
+ break;
+ case JXFORM_FLIP_V:
+ if (info->trim)
+ trim_bottom_edge(info, srcinfo->image_height);
+ /* Need workspace arrays having same dimensions as source image. */
+ need_workspace = TRUE;
+ break;
+ case JXFORM_TRANSPOSE:
+ /* transpose does NOT have to trim anything */
+ /* Need workspace arrays having transposed dimensions. */
+ need_workspace = TRUE;
+ transpose_it = TRUE;
+ break;
+ case JXFORM_TRANSVERSE:
+ if (info->trim) {
+ trim_right_edge(info, srcinfo->image_height);
+ trim_bottom_edge(info, srcinfo->image_width);
+ }
+ /* Need workspace arrays having transposed dimensions. */
+ need_workspace = TRUE;
+ transpose_it = TRUE;
+ break;
+ case JXFORM_ROT_90:
+ if (info->trim)
+ trim_right_edge(info, srcinfo->image_height);
+ /* Need workspace arrays having transposed dimensions. */
+ need_workspace = TRUE;
+ transpose_it = TRUE;
+ break;
+ case JXFORM_ROT_180:
+ if (info->trim) {
+ trim_right_edge(info, srcinfo->image_width);
+ trim_bottom_edge(info, srcinfo->image_height);
+ }
+ /* Need workspace arrays having same dimensions as source image. */
+ need_workspace = TRUE;
+ break;
+ case JXFORM_ROT_270:
+ if (info->trim)
+ trim_bottom_edge(info, srcinfo->image_width);
+ /* Need workspace arrays having transposed dimensions. */
+ need_workspace = TRUE;
+ transpose_it = TRUE;
+ break;
+ }
+
+ /* Allocate workspace if needed.
+ * Note that we allocate arrays padded out to the next iMCU boundary,
+ * so that transform routines need not worry about missing edge blocks.
+ */
+ if (need_workspace) {
+ coef_arrays = (jvirt_barray_ptr *)
+ (*srcinfo->mem->alloc_small) ((j_common_ptr) srcinfo, JPOOL_IMAGE,
+ SIZEOF(jvirt_barray_ptr) * info->num_components);
+ width_in_iMCUs = (JDIMENSION)
+ jdiv_round_up((long) info->output_width,
+ (long) (info->max_h_samp_factor * DCTSIZE));
+ height_in_iMCUs = (JDIMENSION)
+ jdiv_round_up((long) info->output_height,
+ (long) (info->max_v_samp_factor * DCTSIZE));
+ for (ci = 0; ci < info->num_components; ci++) {
+ compptr = srcinfo->comp_info + ci;
+ if (info->num_components == 1) {
+ /* we're going to force samp factors to 1x1 in this case */
+ h_samp_factor = v_samp_factor = 1;
+ } else if (transpose_it) {
+ h_samp_factor = compptr->v_samp_factor;
+ v_samp_factor = compptr->h_samp_factor;
+ } else {
+ h_samp_factor = compptr->h_samp_factor;
+ v_samp_factor = compptr->v_samp_factor;
+ }
+ width_in_blocks = width_in_iMCUs * h_samp_factor;
+ height_in_blocks = height_in_iMCUs * v_samp_factor;
+ coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
+ ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
+ width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
+ }
+ }
+
+ info->workspace_coef_arrays = coef_arrays;
+}
+
+
+/* Transpose destination image parameters */
+
+LOCAL(void)
+transpose_critical_parameters (j_compress_ptr dstinfo)
+{
+ int tblno, i, j, ci, itemp;
+ jpeg_component_info *compptr;
+ JQUANT_TBL *qtblptr;
+ UINT16 qtemp;
+
+ /* Transpose sampling factors */
+ for (ci = 0; ci < dstinfo->num_components; ci++) {
+ compptr = dstinfo->comp_info + ci;
+ itemp = compptr->h_samp_factor;
+ compptr->h_samp_factor = compptr->v_samp_factor;
+ compptr->v_samp_factor = itemp;
+ }
+
+ /* Transpose quantization tables */
+ for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
+ qtblptr = dstinfo->quant_tbl_ptrs[tblno];
+ if (qtblptr != NULL) {
+ for (i = 0; i < DCTSIZE; i++) {
+ for (j = 0; j < i; j++) {
+ qtemp = qtblptr->quantval[i*DCTSIZE+j];
+ qtblptr->quantval[i*DCTSIZE+j] = qtblptr->quantval[j*DCTSIZE+i];
+ qtblptr->quantval[j*DCTSIZE+i] = qtemp;
+ }
+ }
+ }
+ }
+}
+
+
+/* Adjust Exif image parameters.
+ *
+ * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
+ */
+
+LOCAL(void)
+adjust_exif_parameters (JOCTET FAR * data, unsigned int length,
+ JDIMENSION new_width, JDIMENSION new_height)
+{
+ boolean is_motorola; /* Flag for byte order */
+ unsigned int number_of_tags, tagnum;
+ unsigned int firstoffset, offset;
+ JDIMENSION new_value;
+
+ if (length < 12) return; /* Length of an IFD entry */
+
+ /* Discover byte order */
+ if (GETJOCTET(data[0]) == 0x49 && GETJOCTET(data[1]) == 0x49)
+ is_motorola = FALSE;
+ else if (GETJOCTET(data[0]) == 0x4D && GETJOCTET(data[1]) == 0x4D)
+ is_motorola = TRUE;
+ else
+ return;
+
+ /* Check Tag Mark */
+ if (is_motorola) {
+ if (GETJOCTET(data[2]) != 0) return;
+ if (GETJOCTET(data[3]) != 0x2A) return;
+ } else {
+ if (GETJOCTET(data[3]) != 0) return;
+ if (GETJOCTET(data[2]) != 0x2A) return;
+ }
+
+ /* Get first IFD offset (offset to IFD0) */
+ if (is_motorola) {
+ if (GETJOCTET(data[4]) != 0) return;
+ if (GETJOCTET(data[5]) != 0) return;
+ firstoffset = GETJOCTET(data[6]);
+ firstoffset <<= 8;
+ firstoffset += GETJOCTET(data[7]);
+ } else {
+ if (GETJOCTET(data[7]) != 0) return;
+ if (GETJOCTET(data[6]) != 0) return;
+ firstoffset = GETJOCTET(data[5]);
+ firstoffset <<= 8;
+ firstoffset += GETJOCTET(data[4]);
+ }
+ if (firstoffset > length - 2) return; /* check end of data segment */
+
+ /* Get the number of directory entries contained in this IFD */
+ if (is_motorola) {
+ number_of_tags = GETJOCTET(data[firstoffset]);
+ number_of_tags <<= 8;
+ number_of_tags += GETJOCTET(data[firstoffset+1]);
+ } else {
+ number_of_tags = GETJOCTET(data[firstoffset+1]);
+ number_of_tags <<= 8;
+ number_of_tags += GETJOCTET(data[firstoffset]);
+ }
+ if (number_of_tags == 0) return;
+ firstoffset += 2;
+
+ /* Search for ExifSubIFD offset Tag in IFD0 */
+ for (;;) {
+ if (firstoffset > length - 12) return; /* check end of data segment */
+ /* Get Tag number */
+ if (is_motorola) {
+ tagnum = GETJOCTET(data[firstoffset]);
+ tagnum <<= 8;
+ tagnum += GETJOCTET(data[firstoffset+1]);
+ } else {
+ tagnum = GETJOCTET(data[firstoffset+1]);
+ tagnum <<= 8;
+ tagnum += GETJOCTET(data[firstoffset]);
+ }
+ if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
+ if (--number_of_tags == 0) return;
+ firstoffset += 12;
+ }
+
+ /* Get the ExifSubIFD offset */
+ if (is_motorola) {
+ if (GETJOCTET(data[firstoffset+8]) != 0) return;
+ if (GETJOCTET(data[firstoffset+9]) != 0) return;
+ offset = GETJOCTET(data[firstoffset+10]);
+ offset <<= 8;
+ offset += GETJOCTET(data[firstoffset+11]);
+ } else {
+ if (GETJOCTET(data[firstoffset+11]) != 0) return;
+ if (GETJOCTET(data[firstoffset+10]) != 0) return;
+ offset = GETJOCTET(data[firstoffset+9]);
+ offset <<= 8;
+ offset += GETJOCTET(data[firstoffset+8]);
+ }
+ if (offset > length - 2) return; /* check end of data segment */
+
+ /* Get the number of directory entries contained in this SubIFD */
+ if (is_motorola) {
+ number_of_tags = GETJOCTET(data[offset]);
+ number_of_tags <<= 8;
+ number_of_tags += GETJOCTET(data[offset+1]);
+ } else {
+ number_of_tags = GETJOCTET(data[offset+1]);
+ number_of_tags <<= 8;
+ number_of_tags += GETJOCTET(data[offset]);
+ }
+ if (number_of_tags < 2) return;
+ offset += 2;
+
+ /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
+ do {
+ if (offset > length - 12) return; /* check end of data segment */
+ /* Get Tag number */
+ if (is_motorola) {
+ tagnum = GETJOCTET(data[offset]);
+ tagnum <<= 8;
+ tagnum += GETJOCTET(data[offset+1]);
+ } else {
+ tagnum = GETJOCTET(data[offset+1]);
+ tagnum <<= 8;
+ tagnum += GETJOCTET(data[offset]);
+ }
+ if (tagnum == 0xA002 || tagnum == 0xA003) {
+ if (tagnum == 0xA002)
+ new_value = new_width; /* ExifImageWidth Tag */
+ else
+ new_value = new_height; /* ExifImageHeight Tag */
+ if (is_motorola) {
+ data[offset+2] = 0; /* Format = unsigned long (4 octets) */
+ data[offset+3] = 4;
+ data[offset+4] = 0; /* Number Of Components = 1 */
+ data[offset+5] = 0;
+ data[offset+6] = 0;
+ data[offset+7] = 1;
+ data[offset+8] = 0;
+ data[offset+9] = 0;
+ data[offset+10] = (JOCTET)((new_value >> 8) & 0xFF);
+ data[offset+11] = (JOCTET)(new_value & 0xFF);
+ } else {
+ data[offset+2] = 4; /* Format = unsigned long (4 octets) */
+ data[offset+3] = 0;
+ data[offset+4] = 1; /* Number Of Components = 1 */
+ data[offset+5] = 0;
+ data[offset+6] = 0;
+ data[offset+7] = 0;
+ data[offset+8] = (JOCTET)(new_value & 0xFF);
+ data[offset+9] = (JOCTET)((new_value >> 8) & 0xFF);
+ data[offset+10] = 0;
+ data[offset+11] = 0;
+ }
+ }
+ offset += 12;
+ } while (--number_of_tags);
+}
+
+
+/* Adjust output image parameters as needed.
+ *
+ * This must be called after jpeg_copy_critical_parameters()
+ * and before jpeg_write_coefficients().
+ *
+ * The return value is the set of virtual coefficient arrays to be written
+ * (either the ones allocated by jtransform_request_workspace, or the
+ * original source data arrays). The caller will need to pass this value
+ * to jpeg_write_coefficients().
+ */
+
+GLOBAL(jvirt_barray_ptr *)
+jtransform_adjust_parameters (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ /* If force-to-grayscale is requested, adjust destination parameters */
+ if (info->force_grayscale) {
+ /* First, ensure we have YCbCr or grayscale data, and that the source's
+ * Y channel is full resolution. (No reasonable person would make Y
+ * be less than full resolution, so actually coping with that case
+ * isn't worth extra code space. But we check it to avoid crashing.)
+ */
+ if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
+ dstinfo->num_components == 3) ||
+ (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
+ dstinfo->num_components == 1)) &&
+ srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
+ srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
+ /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
+ * properly. Among other things, it sets the target h_samp_factor &
+ * v_samp_factor to 1, which typically won't match the source.
+ * We have to preserve the source's quantization table number, however.
+ */
+ int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
+ jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
+ dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
+ } else {
+ /* Sorry, can't do it */
+ ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
+ }
+ } else if (info->num_components == 1) {
+ /* For a single-component source, we force the destination sampling factors
+ * to 1x1, with or without force_grayscale. This is useful because some
+ * decoders choke on grayscale images with other sampling factors.
+ */
+ dstinfo->comp_info[0].h_samp_factor = 1;
+ dstinfo->comp_info[0].v_samp_factor = 1;
+ }
+
+ /* Correct the destination's image dimensions as necessary
+ * for crop and rotate/flip operations.
+ */
+ dstinfo->image_width = info->output_width;
+ dstinfo->image_height = info->output_height;
+
+ /* Transpose destination image parameters */
+ switch (info->transform) {
+ case JXFORM_TRANSPOSE:
+ case JXFORM_TRANSVERSE:
+ case JXFORM_ROT_90:
+ case JXFORM_ROT_270:
+ transpose_critical_parameters(dstinfo);
+ break;
+ default:
+ break;
+ }
+
+ /* Adjust Exif properties */
+ if (srcinfo->marker_list != NULL &&
+ srcinfo->marker_list->marker == JPEG_APP0+1 &&
+ srcinfo->marker_list->data_length >= 6 &&
+ GETJOCTET(srcinfo->marker_list->data[0]) == 0x45 &&
+ GETJOCTET(srcinfo->marker_list->data[1]) == 0x78 &&
+ GETJOCTET(srcinfo->marker_list->data[2]) == 0x69 &&
+ GETJOCTET(srcinfo->marker_list->data[3]) == 0x66 &&
+ GETJOCTET(srcinfo->marker_list->data[4]) == 0 &&
+ GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
+ /* Suppress output of JFIF marker */
+ dstinfo->write_JFIF_header = FALSE;
+ /* Adjust Exif image parameters */
+ if (dstinfo->image_width != srcinfo->image_width ||
+ dstinfo->image_height != srcinfo->image_height)
+ /* Align data segment to start of TIFF structure for parsing */
+ adjust_exif_parameters(srcinfo->marker_list->data + 6,
+ srcinfo->marker_list->data_length - 6,
+ dstinfo->image_width, dstinfo->image_height);
+ }
+
+ /* Return the appropriate output data set */
+ if (info->workspace_coef_arrays != NULL)
+ return info->workspace_coef_arrays;
+ return src_coef_arrays;
+}
+
+
+/* Execute the actual transformation, if any.
+ *
+ * This must be called *after* jpeg_write_coefficients, because it depends
+ * on jpeg_write_coefficients to have computed subsidiary values such as
+ * the per-component width and height fields in the destination object.
+ *
+ * Note that some transformations will modify the source data arrays!
+ */
+
+GLOBAL(void)
+jtransform_execute_transform (j_decompress_ptr srcinfo,
+ j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info)
+{
+ jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
+
+ /* Note: conditions tested here should match those in switch statement
+ * in jtransform_request_workspace()
+ */
+ switch (info->transform) {
+ case JXFORM_NONE:
+ if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
+ do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_FLIP_H:
+ if (info->y_crop_offset != 0)
+ do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ else
+ do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
+ src_coef_arrays);
+ break;
+ case JXFORM_FLIP_V:
+ do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSPOSE:
+ do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_TRANSVERSE:
+ do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_90:
+ do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_180:
+ do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ case JXFORM_ROT_270:
+ do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
+ src_coef_arrays, dst_coef_arrays);
+ break;
+ }
+}
+
+/* jtransform_perfect_transform
+ *
+ * Determine whether lossless transformation is perfectly
+ * possible for a specified image and transformation.
+ *
+ * Inputs:
+ * image_width, image_height: source image dimensions.
+ * MCU_width, MCU_height: pixel dimensions of MCU.
+ * transform: transformation identifier.
+ * Parameter sources from initialized jpeg_struct
+ * (after reading source header):
+ * image_width = cinfo.image_width
+ * image_height = cinfo.image_height
+ * MCU_width = cinfo.max_h_samp_factor * DCTSIZE
+ * MCU_height = cinfo.max_v_samp_factor * DCTSIZE
+ * Result:
+ * TRUE = perfect transformation possible
+ * FALSE = perfect transformation not possible
+ * (may use custom action then)
+ */
+
+GLOBAL(boolean)
+jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
+ int MCU_width, int MCU_height,
+ JXFORM_CODE transform)
+{
+ boolean result = TRUE; /* initialize TRUE */
+
+ switch (transform) {
+ case JXFORM_FLIP_H:
+ case JXFORM_ROT_270:
+ if (image_width % (JDIMENSION) MCU_width)
+ result = FALSE;
+ break;
+ case JXFORM_FLIP_V:
+ case JXFORM_ROT_90:
+ if (image_height % (JDIMENSION) MCU_height)
+ result = FALSE;
+ break;
+ case JXFORM_TRANSVERSE:
+ case JXFORM_ROT_180:
+ if (image_width % (JDIMENSION) MCU_width)
+ result = FALSE;
+ if (image_height % (JDIMENSION) MCU_height)
+ result = FALSE;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+}
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/* Setup decompression object to save desired markers in memory.
+ * This must be called before jpeg_read_header() to have the desired effect.
+ */
+
+GLOBAL(void)
+jcopy_markers_setup (j_decompress_ptr srcinfo, JCOPY_OPTION option)
+{
+#ifdef SAVE_MARKERS_SUPPORTED
+ int m;
+
+ /* Save comments except under NONE option */
+ if (option != JCOPYOPT_NONE) {
+ jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
+ }
+ /* Save all types of APPn markers iff ALL option */
+ if (option == JCOPYOPT_ALL) {
+ for (m = 0; m < 16; m++)
+ jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
+ }
+#endif /* SAVE_MARKERS_SUPPORTED */
+}
+
+/* Copy markers saved in the given source object to the destination object.
+ * This should be called just after jpeg_start_compress() or
+ * jpeg_write_coefficients().
+ * Note that those routines will have written the SOI, and also the
+ * JFIF APP0 or Adobe APP14 markers if selected.
+ */
+
+GLOBAL(void)
+jcopy_markers_execute (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION option)
+{
+ jpeg_saved_marker_ptr marker;
+
+ /* In the current implementation, we don't actually need to examine the
+ * option flag here; we just copy everything that got saved.
+ * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
+ * if the encoder library already wrote one.
+ */
+ for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
+ if (dstinfo->write_JFIF_header &&
+ marker->marker == JPEG_APP0 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x4A &&
+ GETJOCTET(marker->data[1]) == 0x46 &&
+ GETJOCTET(marker->data[2]) == 0x49 &&
+ GETJOCTET(marker->data[3]) == 0x46 &&
+ GETJOCTET(marker->data[4]) == 0)
+ continue; /* reject duplicate JFIF */
+ if (dstinfo->write_Adobe_marker &&
+ marker->marker == JPEG_APP0+14 &&
+ marker->data_length >= 5 &&
+ GETJOCTET(marker->data[0]) == 0x41 &&
+ GETJOCTET(marker->data[1]) == 0x64 &&
+ GETJOCTET(marker->data[2]) == 0x6F &&
+ GETJOCTET(marker->data[3]) == 0x62 &&
+ GETJOCTET(marker->data[4]) == 0x65)
+ continue; /* reject duplicate Adobe */
+#ifdef NEED_FAR_POINTERS
+ /* We could use jpeg_write_marker if the data weren't FAR... */
+ {
+ unsigned int i;
+ jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
+ for (i = 0; i < marker->data_length; i++)
+ jpeg_write_m_byte(dstinfo, marker->data[i]);
+ }
+#else
+ jpeg_write_marker(dstinfo, marker->marker,
+ marker->data, marker->data_length);
+#endif
+ }
+}
diff --git a/Source/LibJPEG/transupp.h b/Source/LibJPEG/transupp.h
new file mode 100644
index 0000000..981b1ce
--- /dev/null
+++ b/Source/LibJPEG/transupp.h
@@ -0,0 +1,205 @@
+/*
+ * transupp.h
+ *
+ * Copyright (C) 1997-2001, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains declarations for image transformation routines and
+ * other utility code used by the jpegtran sample application. These are
+ * NOT part of the core JPEG library. But we keep these routines separate
+ * from jpegtran.c to ease the task of maintaining jpegtran-like programs
+ * that have other user interfaces.
+ *
+ * NOTE: all the routines declared here have very specific requirements
+ * about when they are to be executed during the reading and writing of the
+ * source and destination files. See the comments in transupp.c, or see
+ * jpegtran.c for an example of correct usage.
+ */
+
+/* If you happen not to want the image transform support, disable it here */
+#ifndef TRANSFORMS_SUPPORTED
+#define TRANSFORMS_SUPPORTED 1 /* 0 disables transform code */
+#endif
+
+/*
+ * Although rotating and flipping data expressed as DCT coefficients is not
+ * hard, there is an asymmetry in the JPEG format specification for images
+ * whose dimensions aren't multiples of the iMCU size. The right and bottom
+ * image edges are padded out to the next iMCU boundary with junk data; but
+ * no padding is possible at the top and left edges. If we were to flip
+ * the whole image including the pad data, then pad garbage would become
+ * visible at the top and/or left, and real pixels would disappear into the
+ * pad margins --- perhaps permanently, since encoders & decoders may not
+ * bother to preserve DCT blocks that appear to be completely outside the
+ * nominal image area. So, we have to exclude any partial iMCUs from the
+ * basic transformation.
+ *
+ * Transpose is the only transformation that can handle partial iMCUs at the
+ * right and bottom edges completely cleanly. flip_h can flip partial iMCUs
+ * at the bottom, but leaves any partial iMCUs at the right edge untouched.
+ * Similarly flip_v leaves any partial iMCUs at the bottom edge untouched.
+ * The other transforms are defined as combinations of these basic transforms
+ * and process edge blocks in a way that preserves the equivalence.
+ *
+ * The "trim" option causes untransformable partial iMCUs to be dropped;
+ * this is not strictly lossless, but it usually gives the best-looking
+ * result for odd-size images. Note that when this option is active,
+ * the expected mathematical equivalences between the transforms may not hold.
+ * (For example, -rot 270 -trim trims only the bottom edge, but -rot 90 -trim
+ * followed by -rot 180 -trim trims both edges.)
+ *
+ * We also offer a lossless-crop option, which discards data outside a given
+ * image region but losslessly preserves what is inside. Like the rotate and
+ * flip transforms, lossless crop is restricted by the JPEG format: the upper
+ * left corner of the selected region must fall on an iMCU boundary. If this
+ * does not hold for the given crop parameters, we silently move the upper left
+ * corner up and/or left to make it so, simultaneously increasing the region
+ * dimensions to keep the lower right crop corner unchanged. (Thus, the
+ * output image covers at least the requested region, but may cover more.)
+ *
+ * If both crop and a rotate/flip transform are requested, the crop is applied
+ * last --- that is, the crop region is specified in terms of the destination
+ * image.
+ *
+ * We also offer a "force to grayscale" option, which simply discards the
+ * chrominance channels of a YCbCr image. This is lossless in the sense that
+ * the luminance channel is preserved exactly. It's not the same kind of
+ * thing as the rotate/flip transformations, but it's convenient to handle it
+ * as part of this package, mainly because the transformation routines have to
+ * be aware of the option to know how many components to work on.
+ */
+
+
+/* Short forms of external names for systems with brain-damaged linkers. */
+
+#ifdef NEED_SHORT_EXTERNAL_NAMES
+#define jtransform_parse_crop_spec jTrParCrop
+#define jtransform_request_workspace jTrRequest
+#define jtransform_adjust_parameters jTrAdjust
+#define jtransform_execute_transform jTrExec
+#define jtransform_perfect_transform jTrPerfect
+#define jcopy_markers_setup jCMrkSetup
+#define jcopy_markers_execute jCMrkExec
+#endif /* NEED_SHORT_EXTERNAL_NAMES */
+
+
+/*
+ * Codes for supported types of image transformations.
+ */
+
+typedef enum {
+ JXFORM_NONE, /* no transformation */
+ JXFORM_FLIP_H, /* horizontal flip */
+ JXFORM_FLIP_V, /* vertical flip */
+ JXFORM_TRANSPOSE, /* transpose across UL-to-LR axis */
+ JXFORM_TRANSVERSE, /* transpose across UR-to-LL axis */
+ JXFORM_ROT_90, /* 90-degree clockwise rotation */
+ JXFORM_ROT_180, /* 180-degree rotation */
+ JXFORM_ROT_270 /* 270-degree clockwise (or 90 ccw) */
+} JXFORM_CODE;
+
+/*
+ * Codes for crop parameters, which can individually be unspecified,
+ * positive, or negative. (Negative width or height makes no sense, though.)
+ */
+
+typedef enum {
+ JCROP_UNSET,
+ JCROP_POS,
+ JCROP_NEG
+} JCROP_CODE;
+
+/*
+ * Transform parameters struct.
+ * NB: application must not change any elements of this struct after
+ * calling jtransform_request_workspace.
+ */
+
+typedef struct {
+ /* Options: set by caller */
+ JXFORM_CODE transform; /* image transform operator */
+ boolean perfect; /* if TRUE, fail if partial MCUs are requested */
+ boolean trim; /* if TRUE, trim partial MCUs as needed */
+ boolean force_grayscale; /* if TRUE, convert color image to grayscale */
+ boolean crop; /* if TRUE, crop source image */
+
+ /* Crop parameters: application need not set these unless crop is TRUE.
+ * These can be filled in by jtransform_parse_crop_spec().
+ */
+ JDIMENSION crop_width; /* Width of selected region */
+ JCROP_CODE crop_width_set;
+ JDIMENSION crop_height; /* Height of selected region */
+ JCROP_CODE crop_height_set;
+ JDIMENSION crop_xoffset; /* X offset of selected region */
+ JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
+ JDIMENSION crop_yoffset; /* Y offset of selected region */
+ JCROP_CODE crop_yoffset_set; /* (negative measures from bottom edge) */
+
+ /* Internal workspace: caller should not touch these */
+ int num_components; /* # of components in workspace */
+ jvirt_barray_ptr * workspace_coef_arrays; /* workspace for transformations */
+ JDIMENSION output_width; /* cropped destination dimensions */
+ JDIMENSION output_height;
+ JDIMENSION x_crop_offset; /* destination crop offsets measured in iMCUs */
+ JDIMENSION y_crop_offset;
+ int max_h_samp_factor; /* destination iMCU size */
+ int max_v_samp_factor;
+} jpeg_transform_info;
+
+
+#if TRANSFORMS_SUPPORTED
+
+/* Parse a crop specification (written in X11 geometry style) */
+EXTERN(boolean) jtransform_parse_crop_spec
+ JPP((jpeg_transform_info *info, const char *spec));
+/* Request any required workspace */
+EXTERN(void) jtransform_request_workspace
+ JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
+/* Adjust output image parameters */
+EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+/* Execute the actual transformation, if any */
+EXTERN(void) jtransform_execute_transform
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ jvirt_barray_ptr *src_coef_arrays,
+ jpeg_transform_info *info));
+/* Determine whether lossless transformation is perfectly
+ * possible for a specified image and transformation.
+ */
+EXTERN(boolean) jtransform_perfect_transform
+ JPP((JDIMENSION image_width, JDIMENSION image_height,
+ int MCU_width, int MCU_height,
+ JXFORM_CODE transform));
+
+/* jtransform_execute_transform used to be called
+ * jtransform_execute_transformation, but some compilers complain about
+ * routine names that long. This macro is here to avoid breaking any
+ * old source code that uses the original name...
+ */
+#define jtransform_execute_transformation jtransform_execute_transform
+
+#endif /* TRANSFORMS_SUPPORTED */
+
+
+/*
+ * Support for copying optional markers from source to destination file.
+ */
+
+typedef enum {
+ JCOPYOPT_NONE, /* copy no optional markers */
+ JCOPYOPT_COMMENTS, /* copy only comment (COM) markers */
+ JCOPYOPT_ALL /* copy all optional markers */
+} JCOPY_OPTION;
+
+#define JCOPYOPT_DEFAULT JCOPYOPT_COMMENTS /* recommended default */
+
+/* Setup decompression object to save desired markers in memory */
+EXTERN(void) jcopy_markers_setup
+ JPP((j_decompress_ptr srcinfo, JCOPY_OPTION option));
+/* Copy markers saved in the given source object to the destination object */
+EXTERN(void) jcopy_markers_execute
+ JPP((j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ JCOPY_OPTION option));
diff --git a/Source/LibJPEG/usage.txt b/Source/LibJPEG/usage.txt
new file mode 100644
index 0000000..e78b26c
--- /dev/null
+++ b/Source/LibJPEG/usage.txt
@@ -0,0 +1,605 @@
+USAGE instructions for the Independent JPEG Group's JPEG software
+=================================================================
+
+This file describes usage of the JPEG conversion programs cjpeg and djpeg,
+as well as the utility programs jpegtran, rdjpgcom and wrjpgcom. (See
+the other documentation files if you wish to use the JPEG library within
+your own programs.)
+
+If you are on a Unix machine you may prefer to read the Unix-style manual
+pages in files cjpeg.1, djpeg.1, jpegtran.1, rdjpgcom.1, wrjpgcom.1.
+
+
+INTRODUCTION
+
+These programs implement JPEG image encoding, decoding, and transcoding.
+JPEG (pronounced "jay-peg") is a standardized compression method for
+full-color and gray-scale images.
+
+
+GENERAL USAGE
+
+We provide two programs, cjpeg to compress an image file into JPEG format,
+and djpeg to decompress a JPEG file back into a conventional image format.
+
+On Unix-like systems, you say:
+ cjpeg [switches] [imagefile] >jpegfile
+or
+ djpeg [switches] [jpegfile] >imagefile
+The programs read the specified input file, or standard input if none is
+named. They always write to standard output (with trace/error messages to
+standard error). These conventions are handy for piping images between
+programs.
+
+On most non-Unix systems, you say:
+ cjpeg [switches] imagefile jpegfile
+or
+ djpeg [switches] jpegfile imagefile
+i.e., both the input and output files are named on the command line. This
+style is a little more foolproof, and it loses no functionality if you don't
+have pipes. (You can get this style on Unix too, if you prefer, by defining
+TWO_FILE_COMMANDLINE when you compile the programs; see install.txt.)
+
+You can also say:
+ cjpeg [switches] -outfile jpegfile imagefile
+or
+ djpeg [switches] -outfile imagefile jpegfile
+This syntax works on all systems, so it is useful for scripts.
+
+The currently supported image file formats are: PPM (PBMPLUS color format),
+PGM (PBMPLUS gray-scale format), BMP, Targa, and RLE (Utah Raster Toolkit
+format). (RLE is supported only if the URT library is available.)
+cjpeg recognizes the input image format automatically, with the exception
+of some Targa-format files. You have to tell djpeg which format to generate.
+
+JPEG files are in the defacto standard JFIF file format. There are other,
+less widely used JPEG-based file formats, but we don't support them.
+
+All switch names may be abbreviated; for example, -grayscale may be written
+-gray or -gr. Most of the "basic" switches can be abbreviated to as little as
+one letter. Upper and lower case are equivalent (-BMP is the same as -bmp).
+British spellings are also accepted (e.g., -greyscale), though for brevity
+these are not mentioned below.
+
+
+CJPEG DETAILS
+
+The basic command line switches for cjpeg are:
+
+ -quality N[,...] Scale quantization tables to adjust image quality.
+ Quality is 0 (worst) to 100 (best); default is 75.
+ (See below for more info.)
+
+ -grayscale Create monochrome JPEG file from color input.
+ Be sure to use this switch when compressing a grayscale
+ BMP file, because cjpeg isn't bright enough to notice
+ whether a BMP file uses only shades of gray. By
+ saying -grayscale, you'll get a smaller JPEG file that
+ takes less time to process.
+
+ -optimize Perform optimization of entropy encoding parameters.
+ Without this, default encoding parameters are used.
+ -optimize usually makes the JPEG file a little smaller,
+ but cjpeg runs somewhat slower and needs much more
+ memory. Image quality and speed of decompression are
+ unaffected by -optimize.
+
+ -progressive Create progressive JPEG file (see below).
+
+ -scale M/N Scale the output image by a factor M/N. Currently
+ supported scale factors are 8/N with all N from 1 to
+ 16.
+
+ -targa Input file is Targa format. Targa files that contain
+ an "identification" field will not be automatically
+ recognized by cjpeg; for such files you must specify
+ -targa to make cjpeg treat the input as Targa format.
+ For most Targa files, you won't need this switch.
+
+The -quality switch lets you trade off compressed file size against quality of
+the reconstructed image: the higher the quality setting, the larger the JPEG
+file, and the closer the output image will be to the original input. Normally
+you want to use the lowest quality setting (smallest file) that decompresses
+into something visually indistinguishable from the original image. For this
+purpose the quality setting should be between 50 and 95; the default of 75 is
+often about right. If you see defects at -quality 75, then go up 5 or 10
+counts at a time until you are happy with the output image. (The optimal
+setting will vary from one image to another.)
+
+-quality 100 will generate a quantization table of all 1's, minimizing loss
+in the quantization step (but there is still information loss in subsampling,
+as well as roundoff error). This setting is mainly of interest for
+experimental purposes. Quality values above about 95 are NOT recommended for
+normal use; the compressed file size goes up dramatically for hardly any gain
+in output image quality.
+
+In the other direction, quality values below 50 will produce very small files
+of low image quality. Settings around 5 to 10 might be useful in preparing an
+index of a large image library, for example. Try -quality 2 (or so) for some
+amusing Cubist effects. (Note: quality values below about 25 generate 2-byte
+quantization tables, which are considered optional in the JPEG standard.
+cjpeg emits a warning message when you give such a quality value, because some
+other JPEG programs may be unable to decode the resulting file. Use -baseline
+if you need to ensure compatibility at low quality values.)
+
+The -quality option has been extended in IJG version 7 for support of separate
+quality settings for luminance and chrominance (or in general, for every
+provided quantization table slot). This feature is useful for high-quality
+applications which cannot accept the damage of color data by coarse
+subsampling settings. You can now easily reduce the color data amount more
+smoothly with finer control without separate subsampling. The resulting file
+is fully compliant with standard JPEG decoders.
+Note that the -quality ratings refer to the quantization table slots, and that
+the last value is replicated if there are more q-table slots than parameters.
+The default q-table slots are 0 for luminance and 1 for chrominance with
+default tables as given in the JPEG standard. This is compatible with the old
+behaviour in case that only one parameter is given, which is then used for
+both luminance and chrominance (slots 0 and 1). More or custom quantization
+tables can be set with -qtables and assigned to components with -qslots
+parameter (see the "wizard" switches below).
+CAUTION: You must explicitely add -sample 1x1 for efficient separate color
+quality selection, since the default value used by library is 2x2!
+
+The -progressive switch creates a "progressive JPEG" file. In this type of
+JPEG file, the data is stored in multiple scans of increasing quality. If the
+file is being transmitted over a slow communications link, the decoder can use
+the first scan to display a low-quality image very quickly, and can then
+improve the display with each subsequent scan. The final image is exactly
+equivalent to a standard JPEG file of the same quality setting, and the total
+file size is about the same --- often a little smaller.
+
+Switches for advanced users:
+
+ -dct int Use integer DCT method (default).
+ -dct fast Use fast integer DCT (less accurate).
+ -dct float Use floating-point DCT method.
+ The float method is very slightly more accurate than
+ the int method, but is much slower unless your machine
+ has very fast floating-point hardware. Also note that
+ results of the floating-point method may vary slightly
+ across machines, while the integer methods should give
+ the same results everywhere. The fast integer method
+ is much less accurate than the other two.
+
+ -nosmooth Don't use high-quality downsampling.
+
+ -restart N Emit a JPEG restart marker every N MCU rows, or every
+ N MCU blocks if "B" is attached to the number.
+ -restart 0 (the default) means no restart markers.
+
+ -smooth N Smooth the input image to eliminate dithering noise.
+ N, ranging from 1 to 100, indicates the strength of
+ smoothing. 0 (the default) means no smoothing.
+
+ -maxmemory N Set limit for amount of memory to use in processing
+ large images. Value is in thousands of bytes, or
+ millions of bytes if "M" is attached to the number.
+ For example, -max 4m selects 4000000 bytes. If more
+ space is needed, temporary files will be used.
+
+ -verbose Enable debug printout. More -v's give more printout.
+ or -debug Also, version information is printed at startup.
+
+The -restart option inserts extra markers that allow a JPEG decoder to
+resynchronize after a transmission error. Without restart markers, any damage
+to a compressed file will usually ruin the image from the point of the error
+to the end of the image; with restart markers, the damage is usually confined
+to the portion of the image up to the next restart marker. Of course, the
+restart markers occupy extra space. We recommend -restart 1 for images that
+will be transmitted across unreliable networks such as Usenet.
+
+The -smooth option filters the input to eliminate fine-scale noise. This is
+often useful when converting dithered images to JPEG: a moderate smoothing
+factor of 10 to 50 gets rid of dithering patterns in the input file, resulting
+in a smaller JPEG file and a better-looking image. Too large a smoothing
+factor will visibly blur the image, however.
+
+Switches for wizards:
+
+ -arithmetic Use arithmetic coding. CAUTION: arithmetic coded JPEG
+ is not yet widely implemented, so many decoders will
+ be unable to view an arithmetic coded JPEG file at
+ all.
+
+ -baseline Force baseline-compatible quantization tables to be
+ generated. This clamps quantization values to 8 bits
+ even at low quality settings. (This switch is poorly
+ named, since it does not ensure that the output is
+ actually baseline JPEG. For example, you can use
+ -baseline and -progressive together.)
+
+ -qtables file Use the quantization tables given in the specified
+ text file.
+
+ -qslots N[,...] Select which quantization table to use for each color
+ component.
+
+ -sample HxV[,...] Set JPEG sampling factors for each color component.
+
+ -scans file Use the scan script given in the specified text file.
+
+The "wizard" switches are intended for experimentation with JPEG. If you
+don't know what you are doing, DON'T USE THEM. These switches are documented
+further in the file wizard.txt.
+
+
+DJPEG DETAILS
+
+The basic command line switches for djpeg are:
+
+ -colors N Reduce image to at most N colors. This reduces the
+ or -quantize N number of colors used in the output image, so that it
+ can be displayed on a colormapped display or stored in
+ a colormapped file format. For example, if you have
+ an 8-bit display, you'd need to reduce to 256 or fewer
+ colors. (-colors is the recommended name, -quantize
+ is provided only for backwards compatibility.)
+
+ -fast Select recommended processing options for fast, low
+ quality output. (The default options are chosen for
+ highest quality output.) Currently, this is equivalent
+ to "-dct fast -nosmooth -onepass -dither ordered".
+
+ -grayscale Force gray-scale output even if JPEG file is color.
+ Useful for viewing on monochrome displays; also,
+ djpeg runs noticeably faster in this mode.
+
+ -scale M/N Scale the output image by a factor M/N. Currently
+ supported scale factors are M/8 with all M from 1 to
+ 16. If the /N part is omitted, then M specifies the
+ DCT scaled size to be applied on the given input,
+ which is currently equivalent to M/8 scaling, since
+ the source DCT size is currently always 8.
+ Scaling is handy if the image is larger than your
+ screen; also, djpeg runs much faster when scaling
+ down the output.
+
+ -bmp Select BMP output format (Windows flavor). 8-bit
+ colormapped format is emitted if -colors or -grayscale
+ is specified, or if the JPEG file is gray-scale;
+ otherwise, 24-bit full-color format is emitted.
+
+ -gif Select GIF output format. Since GIF does not support
+ more than 256 colors, -colors 256 is assumed (unless
+ you specify a smaller number of colors). If you
+ specify -fast, the default number of colors is 216.
+
+ -os2 Select BMP output format (OS/2 1.x flavor). 8-bit
+ colormapped format is emitted if -colors or -grayscale
+ is specified, or if the JPEG file is gray-scale;
+ otherwise, 24-bit full-color format is emitted.
+
+ -pnm Select PBMPLUS (PPM/PGM) output format (this is the
+ default format). PGM is emitted if the JPEG file is
+ gray-scale or if -grayscale is specified; otherwise
+ PPM is emitted.
+
+ -rle Select RLE output format. (Requires URT library.)
+
+ -targa Select Targa output format. Gray-scale format is
+ emitted if the JPEG file is gray-scale or if
+ -grayscale is specified; otherwise, colormapped format
+ is emitted if -colors is specified; otherwise, 24-bit
+ full-color format is emitted.
+
+Switches for advanced users:
+
+ -dct int Use integer DCT method (default).
+ -dct fast Use fast integer DCT (less accurate).
+ -dct float Use floating-point DCT method.
+ The float method is very slightly more accurate than
+ the int method, but is much slower unless your machine
+ has very fast floating-point hardware. Also note that
+ results of the floating-point method may vary slightly
+ across machines, while the integer methods should give
+ the same results everywhere. The fast integer method
+ is much less accurate than the other two.
+
+ -dither fs Use Floyd-Steinberg dithering in color quantization.
+ -dither ordered Use ordered dithering in color quantization.
+ -dither none Do not use dithering in color quantization.
+ By default, Floyd-Steinberg dithering is applied when
+ quantizing colors; this is slow but usually produces
+ the best results. Ordered dither is a compromise
+ between speed and quality; no dithering is fast but
+ usually looks awful. Note that these switches have
+ no effect unless color quantization is being done.
+ Ordered dither is only available in -onepass mode.
+
+ -map FILE Quantize to the colors used in the specified image
+ file. This is useful for producing multiple files
+ with identical color maps, or for forcing a predefined
+ set of colors to be used. The FILE must be a GIF
+ or PPM file. This option overrides -colors and
+ -onepass.
+
+ -nosmooth Don't use high-quality upsampling.
+
+ -onepass Use one-pass instead of two-pass color quantization.
+ The one-pass method is faster and needs less memory,
+ but it produces a lower-quality image. -onepass is
+ ignored unless you also say -colors N. Also,
+ the one-pass method is always used for gray-scale
+ output (the two-pass method is no improvement then).
+
+ -maxmemory N Set limit for amount of memory to use in processing
+ large images. Value is in thousands of bytes, or
+ millions of bytes if "M" is attached to the number.
+ For example, -max 4m selects 4000000 bytes. If more
+ space is needed, temporary files will be used.
+
+ -verbose Enable debug printout. More -v's give more printout.
+ or -debug Also, version information is printed at startup.
+
+
+HINTS FOR CJPEG
+
+Color GIF files are not the ideal input for JPEG; JPEG is really intended for
+compressing full-color (24-bit) images. In particular, don't try to convert
+cartoons, line drawings, and other images that have only a few distinct
+colors. GIF works great on these, JPEG does not. If you want to convert a
+GIF to JPEG, you should experiment with cjpeg's -quality and -smooth options
+to get a satisfactory conversion. -smooth 10 or so is often helpful.
+
+Avoid running an image through a series of JPEG compression/decompression
+cycles. Image quality loss will accumulate; after ten or so cycles the image
+may be noticeably worse than it was after one cycle. It's best to use a
+lossless format while manipulating an image, then convert to JPEG format when
+you are ready to file the image away.
+
+The -optimize option to cjpeg is worth using when you are making a "final"
+version for posting or archiving. It's also a win when you are using low
+quality settings to make very small JPEG files; the percentage improvement
+is often a lot more than it is on larger files. (At present, -optimize
+mode is always selected when generating progressive JPEG files.)
+
+GIF input files are no longer supported, to avoid the Unisys LZW patent.
+(Conversion of GIF files to JPEG is usually a bad idea anyway.)
+
+
+HINTS FOR DJPEG
+
+To get a quick preview of an image, use the -grayscale and/or -scale switches.
+"-grayscale -scale 1/8" is the fastest case.
+
+Several options are available that trade off image quality to gain speed.
+"-fast" turns on the recommended settings.
+
+"-dct fast" and/or "-nosmooth" gain speed at a small sacrifice in quality.
+When producing a color-quantized image, "-onepass -dither ordered" is fast but
+much lower quality than the default behavior. "-dither none" may give
+acceptable results in two-pass mode, but is seldom tolerable in one-pass mode.
+
+If you are fortunate enough to have very fast floating point hardware,
+"-dct float" may be even faster than "-dct fast". But on most machines
+"-dct float" is slower than "-dct int"; in this case it is not worth using,
+because its theoretical accuracy advantage is too small to be significant
+in practice.
+
+Two-pass color quantization requires a good deal of memory; on MS-DOS machines
+it may run out of memory even with -maxmemory 0. In that case you can still
+decompress, with some loss of image quality, by specifying -onepass for
+one-pass quantization.
+
+To avoid the Unisys LZW patent, djpeg produces uncompressed GIF files. These
+are larger than they should be, but are readable by standard GIF decoders.
+
+
+HINTS FOR BOTH PROGRAMS
+
+If more space is needed than will fit in the available main memory (as
+determined by -maxmemory), temporary files will be used. (MS-DOS versions
+will try to get extended or expanded memory first.) The temporary files are
+often rather large: in typical cases they occupy three bytes per pixel, for
+example 3*800*600 = 1.44Mb for an 800x600 image. If you don't have enough
+free disk space, leave out -progressive and -optimize (for cjpeg) or specify
+-onepass (for djpeg).
+
+On MS-DOS, the temporary files are created in the directory named by the TMP
+or TEMP environment variable, or in the current directory if neither of those
+exist. Amiga implementations put the temp files in the directory named by
+JPEGTMP:, so be sure to assign JPEGTMP: to a disk partition with adequate free
+space.
+
+The default memory usage limit (-maxmemory) is set when the software is
+compiled. If you get an "insufficient memory" error, try specifying a smaller
+-maxmemory value, even -maxmemory 0 to use the absolute minimum space. You
+may want to recompile with a smaller default value if this happens often.
+
+On machines that have "environment" variables, you can define the environment
+variable JPEGMEM to set the default memory limit. The value is specified as
+described for the -maxmemory switch. JPEGMEM overrides the default value
+specified when the program was compiled, and itself is overridden by an
+explicit -maxmemory switch.
+
+On MS-DOS machines, -maxmemory is the amount of main (conventional) memory to
+use. (Extended or expanded memory is also used if available.) Most
+DOS-specific versions of this software do their own memory space estimation
+and do not need you to specify -maxmemory.
+
+
+JPEGTRAN
+
+jpegtran performs various useful transformations of JPEG files.
+It can translate the coded representation from one variant of JPEG to another,
+for example from baseline JPEG to progressive JPEG or vice versa. It can also
+perform some rearrangements of the image data, for example turning an image
+from landscape to portrait format by rotation.
+
+jpegtran works by rearranging the compressed data (DCT coefficients), without
+ever fully decoding the image. Therefore, its transformations are lossless:
+there is no image degradation at all, which would not be true if you used
+djpeg followed by cjpeg to accomplish the same conversion. But by the same
+token, jpegtran cannot perform lossy operations such as changing the image
+quality.
+
+jpegtran uses a command line syntax similar to cjpeg or djpeg.
+On Unix-like systems, you say:
+ jpegtran [switches] [inputfile] >outputfile
+On most non-Unix systems, you say:
+ jpegtran [switches] inputfile outputfile
+where both the input and output files are JPEG files.
+
+To specify the coded JPEG representation used in the output file,
+jpegtran accepts a subset of the switches recognized by cjpeg:
+ -optimize Perform optimization of entropy encoding parameters.
+ -progressive Create progressive JPEG file.
+ -restart N Emit a JPEG restart marker every N MCU rows, or every
+ N MCU blocks if "B" is attached to the number.
+ -arithmetic Use arithmetic coding.
+ -scans file Use the scan script given in the specified text file.
+See the previous discussion of cjpeg for more details about these switches.
+If you specify none of these switches, you get a plain baseline-JPEG output
+file. The quality setting and so forth are determined by the input file.
+
+The image can be losslessly transformed by giving one of these switches:
+ -flip horizontal Mirror image horizontally (left-right).
+ -flip vertical Mirror image vertically (top-bottom).
+ -rotate 90 Rotate image 90 degrees clockwise.
+ -rotate 180 Rotate image 180 degrees.
+ -rotate 270 Rotate image 270 degrees clockwise (or 90 ccw).
+ -transpose Transpose image (across UL-to-LR axis).
+ -transverse Transverse transpose (across UR-to-LL axis).
+
+The transpose transformation has no restrictions regarding image dimensions.
+The other transformations operate rather oddly if the image dimensions are not
+a multiple of the iMCU size (usually 8 or 16 pixels), because they can only
+transform complete blocks of DCT coefficient data in the desired way.
+
+jpegtran's default behavior when transforming an odd-size image is designed
+to preserve exact reversibility and mathematical consistency of the
+transformation set. As stated, transpose is able to flip the entire image
+area. Horizontal mirroring leaves any partial iMCU column at the right edge
+untouched, but is able to flip all rows of the image. Similarly, vertical
+mirroring leaves any partial iMCU row at the bottom edge untouched, but is
+able to flip all columns. The other transforms can be built up as sequences
+of transpose and flip operations; for consistency, their actions on edge
+pixels are defined to be the same as the end result of the corresponding
+transpose-and-flip sequence.
+
+For practical use, you may prefer to discard any untransformable edge pixels
+rather than having a strange-looking strip along the right and/or bottom edges
+of a transformed image. To do this, add the -trim switch:
+ -trim Drop non-transformable edge blocks.
+Obviously, a transformation with -trim is not reversible, so strictly speaking
+jpegtran with this switch is not lossless. Also, the expected mathematical
+equivalences between the transformations no longer hold. For example,
+"-rot 270 -trim" trims only the bottom edge, but "-rot 90 -trim" followed by
+"-rot 180 -trim" trims both edges.
+
+If you are only interested in perfect transformation, add the -perfect switch:
+ -perfect Fails with an error if the transformation is not
+ perfect.
+For example you may want to do
+ jpegtran -rot 90 -perfect foo.jpg || djpeg foo.jpg | pnmflip -r90 | cjpeg
+to do a perfect rotation if available or an approximated one if not.
+
+We also offer a lossless-crop option, which discards data outside a given
+image region but losslessly preserves what is inside. Like the rotate and
+flip transforms, lossless crop is restricted by the current JPEG format: the
+upper left corner of the selected region must fall on an iMCU boundary. If
+this does not hold for the given crop parameters, we silently move the upper
+left corner up and/or left to make it so, simultaneously increasing the region
+dimensions to keep the lower right crop corner unchanged. (Thus, the output
+image covers at least the requested region, but may cover more.)
+
+The image can be losslessly cropped by giving the switch:
+ -crop WxH+X+Y Crop to a rectangular subarea of width W, height H
+ starting at point X,Y.
+
+Another not-strictly-lossless transformation switch is:
+ -grayscale Force grayscale output.
+This option discards the chrominance channels if the input image is YCbCr
+(ie, a standard color JPEG), resulting in a grayscale JPEG file. The
+luminance channel is preserved exactly, so this is a better method of reducing
+to grayscale than decompression, conversion, and recompression. This switch
+is particularly handy for fixing a monochrome picture that was mistakenly
+encoded as a color JPEG. (In such a case, the space savings from getting rid
+of the near-empty chroma channels won't be large; but the decoding time for
+a grayscale JPEG is substantially less than that for a color JPEG.)
+
+jpegtran also recognizes these switches that control what to do with "extra"
+markers, such as comment blocks:
+ -copy none Copy no extra markers from source file. This setting
+ suppresses all comments and other excess baggage
+ present in the source file.
+ -copy comments Copy only comment markers. This setting copies
+ comments from the source file, but discards
+ any other inessential (for image display) data.
+ -copy all Copy all extra markers. This setting preserves
+ miscellaneous markers found in the source file, such
+ as JFIF thumbnails, Exif data, and Photoshop settings.
+ In some files these extra markers can be sizable.
+The default behavior is -copy comments. (Note: in IJG releases v6 and v6a,
+jpegtran always did the equivalent of -copy none.)
+
+Additional switches recognized by jpegtran are:
+ -outfile filename
+ -maxmemory N
+ -verbose
+ -debug
+These work the same as in cjpeg or djpeg.
+
+
+THE COMMENT UTILITIES
+
+The JPEG standard allows "comment" (COM) blocks to occur within a JPEG file.
+Although the standard doesn't actually define what COM blocks are for, they
+are widely used to hold user-supplied text strings. This lets you add
+annotations, titles, index terms, etc to your JPEG files, and later retrieve
+them as text. COM blocks do not interfere with the image stored in the JPEG
+file. The maximum size of a COM block is 64K, but you can have as many of
+them as you like in one JPEG file.
+
+We provide two utility programs to display COM block contents and add COM
+blocks to a JPEG file.
+
+rdjpgcom searches a JPEG file and prints the contents of any COM blocks on
+standard output. The command line syntax is
+ rdjpgcom [-raw] [-verbose] [inputfilename]
+The switch "-raw" (or just "-r") causes rdjpgcom to also output non-printable
+characters in comments, which are normally escaped for security reasons.
+The switch "-verbose" (or just "-v") causes rdjpgcom to also display the JPEG
+image dimensions. If you omit the input file name from the command line,
+the JPEG file is read from standard input. (This may not work on some
+operating systems, if binary data can't be read from stdin.)
+
+wrjpgcom adds a COM block, containing text you provide, to a JPEG file.
+Ordinarily, the COM block is added after any existing COM blocks, but you
+can delete the old COM blocks if you wish. wrjpgcom produces a new JPEG
+file; it does not modify the input file. DO NOT try to overwrite the input
+file by directing wrjpgcom's output back into it; on most systems this will
+just destroy your file.
+
+The command line syntax for wrjpgcom is similar to cjpeg's. On Unix-like
+systems, it is
+ wrjpgcom [switches] [inputfilename]
+The output file is written to standard output. The input file comes from
+the named file, or from standard input if no input file is named.
+
+On most non-Unix systems, the syntax is
+ wrjpgcom [switches] inputfilename outputfilename
+where both input and output file names must be given explicitly.
+
+wrjpgcom understands three switches:
+ -replace Delete any existing COM blocks from the file.
+ -comment "Comment text" Supply new COM text on command line.
+ -cfile name Read text for new COM block from named file.
+(Switch names can be abbreviated.) If you have only one line of comment text
+to add, you can provide it on the command line with -comment. The comment
+text must be surrounded with quotes so that it is treated as a single
+argument. Longer comments can be read from a text file.
+
+If you give neither -comment nor -cfile, then wrjpgcom will read the comment
+text from standard input. (In this case an input image file name MUST be
+supplied, so that the source JPEG file comes from somewhere else.) You can
+enter multiple lines, up to 64KB worth. Type an end-of-file indicator
+(usually control-D or control-Z) to terminate the comment text entry.
+
+wrjpgcom will not add a COM block if the provided comment string is empty.
+Therefore -replace -comment "" can be used to delete all COM blocks from a
+file.
+
+These utility programs do not depend on the IJG JPEG library. In
+particular, the source code for rdjpgcom is intended as an illustration of
+the minimum amount of code required to parse a JPEG file header correctly.
diff --git a/Source/LibJPEG/wizard.txt b/Source/LibJPEG/wizard.txt
new file mode 100644
index 0000000..54170b2
--- /dev/null
+++ b/Source/LibJPEG/wizard.txt
@@ -0,0 +1,211 @@
+Advanced usage instructions for the Independent JPEG Group's JPEG software
+==========================================================================
+
+This file describes cjpeg's "switches for wizards".
+
+The "wizard" switches are intended for experimentation with JPEG by persons
+who are reasonably knowledgeable about the JPEG standard. If you don't know
+what you are doing, DON'T USE THESE SWITCHES. You'll likely produce files
+with worse image quality and/or poorer compression than you'd get from the
+default settings. Furthermore, these switches must be used with caution
+when making files intended for general use, because not all JPEG decoders
+will support unusual JPEG parameter settings.
+
+
+Quantization Table Adjustment
+-----------------------------
+
+Ordinarily, cjpeg starts with a default set of tables (the same ones given
+as examples in the JPEG standard) and scales them up or down according to
+the -quality setting. The details of the scaling algorithm can be found in
+jcparam.c. At very low quality settings, some quantization table entries
+can get scaled up to values exceeding 255. Although 2-byte quantization
+values are supported by the IJG software, this feature is not in baseline
+JPEG and is not supported by all implementations. If you need to ensure
+wide compatibility of low-quality files, you can constrain the scaled
+quantization values to no more than 255 by giving the -baseline switch.
+Note that use of -baseline will result in poorer quality for the same file
+size, since more bits than necessary are expended on higher AC coefficients.
+
+You can substitute a different set of quantization values by using the
+-qtables switch:
+
+ -qtables file Use the quantization tables given in the named file.
+
+The specified file should be a text file containing decimal quantization
+values. The file should contain one to four tables, each of 64 elements.
+The tables are implicitly numbered 0,1,etc. in order of appearance. Table
+entries appear in normal array order (NOT in the zigzag order in which they
+will be stored in the JPEG file).
+
+Quantization table files are free format, in that arbitrary whitespace can
+appear between numbers. Also, comments can be included: a comment starts
+with '#' and extends to the end of the line. Here is an example file that
+duplicates the default quantization tables:
+
+ # Quantization tables given in JPEG spec, section K.1
+
+ # This is table 0 (the luminance table):
+ 16 11 10 16 24 40 51 61
+ 12 12 14 19 26 58 60 55
+ 14 13 16 24 40 57 69 56
+ 14 17 22 29 51 87 80 62
+ 18 22 37 56 68 109 103 77
+ 24 35 55 64 81 104 113 92
+ 49 64 78 87 103 121 120 101
+ 72 92 95 98 112 100 103 99
+
+ # This is table 1 (the chrominance table):
+ 17 18 24 47 99 99 99 99
+ 18 21 26 66 99 99 99 99
+ 24 26 56 99 99 99 99 99
+ 47 66 99 99 99 99 99 99
+ 99 99 99 99 99 99 99 99
+ 99 99 99 99 99 99 99 99
+ 99 99 99 99 99 99 99 99
+ 99 99 99 99 99 99 99 99
+
+If the -qtables switch is used without -quality, then the specified tables
+are used exactly as-is. If both -qtables and -quality are used, then the
+tables taken from the file are scaled in the same fashion that the default
+tables would be scaled for that quality setting. If -baseline appears, then
+the quantization values are constrained to the range 1-255.
+
+By default, cjpeg will use quantization table 0 for luminance components and
+table 1 for chrominance components. To override this choice, use the -qslots
+switch:
+
+ -qslots N[,...] Select which quantization table to use for
+ each color component.
+
+The -qslots switch specifies a quantization table number for each color
+component, in the order in which the components appear in the JPEG SOF marker.
+For example, to create a separate table for each of Y,Cb,Cr, you could
+provide a -qtables file that defines three quantization tables and say
+"-qslots 0,1,2". If -qslots gives fewer table numbers than there are color
+components, then the last table number is repeated as necessary.
+
+
+Sampling Factor Adjustment
+--------------------------
+
+By default, cjpeg uses 2:1 horizontal and vertical downsampling when
+compressing YCbCr data, and no downsampling for all other color spaces.
+You can override this default with the -sample switch:
+
+ -sample HxV[,...] Set JPEG sampling factors for each color
+ component.
+
+The -sample switch specifies the JPEG sampling factors for each color
+component, in the order in which they appear in the JPEG SOF marker.
+If you specify fewer HxV pairs than there are components, the remaining
+components are set to 1x1 sampling. For example, the default YCbCr setting
+is equivalent to "-sample 2x2,1x1,1x1", which can be abbreviated to
+"-sample 2x2".
+
+There are still some JPEG decoders in existence that support only 2x1
+sampling (also called 4:2:2 sampling). Compatibility with such decoders can
+be achieved by specifying "-sample 2x1". This is not recommended unless
+really necessary, since it increases file size and encoding/decoding time
+with very little quality gain.
+
+
+Multiple Scan / Progression Control
+-----------------------------------
+
+By default, cjpeg emits a single-scan sequential JPEG file. The
+-progressive switch generates a progressive JPEG file using a default series
+of progression parameters. You can create multiple-scan sequential JPEG
+files or progressive JPEG files with custom progression parameters by using
+the -scans switch:
+
+ -scans file Use the scan sequence given in the named file.
+
+The specified file should be a text file containing a "scan script".
+The script specifies the contents and ordering of the scans to be emitted.
+Each entry in the script defines one scan. A scan definition specifies
+the components to be included in the scan, and for progressive JPEG it also
+specifies the progression parameters Ss,Se,Ah,Al for the scan. Scan
+definitions are separated by semicolons (';'). A semicolon after the last
+scan definition is optional.
+
+Each scan definition contains one to four component indexes, optionally
+followed by a colon (':') and the four progressive-JPEG parameters. The
+component indexes denote which color component(s) are to be transmitted in
+the scan. Components are numbered in the order in which they appear in the
+JPEG SOF marker, with the first component being numbered 0. (Note that these
+indexes are not the "component ID" codes assigned to the components, just
+positional indexes.)
+
+The progression parameters for each scan are:
+ Ss Zigzag index of first coefficient included in scan
+ Se Zigzag index of last coefficient included in scan
+ Ah Zero for first scan of a coefficient, else Al of prior scan
+ Al Successive approximation low bit position for scan
+If the progression parameters are omitted, the values 0,63,0,0 are used,
+producing a sequential JPEG file. cjpeg automatically determines whether
+the script represents a progressive or sequential file, by observing whether
+Ss and Se values other than 0 and 63 appear. (The -progressive switch is
+not needed to specify this; in fact, it is ignored when -scans appears.)
+The scan script must meet the JPEG restrictions on progression sequences.
+(cjpeg checks that the spec's requirements are obeyed.)
+
+Scan script files are free format, in that arbitrary whitespace can appear
+between numbers and around punctuation. Also, comments can be included: a
+comment starts with '#' and extends to the end of the line. For additional
+legibility, commas or dashes can be placed between values. (Actually, any
+single punctuation character other than ':' or ';' can be inserted.) For
+example, the following two scan definitions are equivalent:
+ 0 1 2: 0 63 0 0;
+ 0,1,2 : 0-63, 0,0 ;
+
+Here is an example of a scan script that generates a partially interleaved
+sequential JPEG file:
+
+ 0; # Y only in first scan
+ 1 2; # Cb and Cr in second scan
+
+Here is an example of a progressive scan script using only spectral selection
+(no successive approximation):
+
+ # Interleaved DC scan for Y,Cb,Cr:
+ 0,1,2: 0-0, 0, 0 ;
+ # AC scans:
+ 0: 1-2, 0, 0 ; # First two Y AC coefficients
+ 0: 3-5, 0, 0 ; # Three more
+ 1: 1-63, 0, 0 ; # All AC coefficients for Cb
+ 2: 1-63, 0, 0 ; # All AC coefficients for Cr
+ 0: 6-9, 0, 0 ; # More Y coefficients
+ 0: 10-63, 0, 0 ; # Remaining Y coefficients
+
+Here is an example of a successive-approximation script. This is equivalent
+to the default script used by "cjpeg -progressive" for YCbCr images:
+
+ # Initial DC scan for Y,Cb,Cr (lowest bit not sent)
+ 0,1,2: 0-0, 0, 1 ;
+ # First AC scan: send first 5 Y AC coefficients, minus 2 lowest bits:
+ 0: 1-5, 0, 2 ;
+ # Send all Cr,Cb AC coefficients, minus lowest bit:
+ # (chroma data is usually too small to be worth subdividing further;
+ # but note we send Cr first since eye is least sensitive to Cb)
+ 2: 1-63, 0, 1 ;
+ 1: 1-63, 0, 1 ;
+ # Send remaining Y AC coefficients, minus 2 lowest bits:
+ 0: 6-63, 0, 2 ;
+ # Send next-to-lowest bit of all Y AC coefficients:
+ 0: 1-63, 2, 1 ;
+ # At this point we've sent all but the lowest bit of all coefficients.
+ # Send lowest bit of DC coefficients
+ 0,1,2: 0-0, 1, 0 ;
+ # Send lowest bit of AC coefficients
+ 2: 1-63, 1, 0 ;
+ 1: 1-63, 1, 0 ;
+ # Y AC lowest bit scan is last; it's usually the largest scan
+ 0: 1-63, 1, 0 ;
+
+It may be worth pointing out that this script is tuned for quality settings
+of around 50 to 75. For lower quality settings, you'd probably want to use
+a script with fewer stages of successive approximation (otherwise the
+initial scans will be really bad). For higher quality settings, you might
+want to use more stages of successive approximation (so that the initial
+scans are not too large).
diff --git a/Source/LibJPEG/wrbmp.c b/Source/LibJPEG/wrbmp.c
new file mode 100644
index 0000000..3283b0f
--- /dev/null
+++ b/Source/LibJPEG/wrbmp.c
@@ -0,0 +1,442 @@
+/*
+ * wrbmp.c
+ *
+ * Copyright (C) 1994-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in Microsoft "BMP"
+ * format (MS Windows 3.x and OS/2 1.x flavors).
+ * Either 8-bit colormapped or 24-bit full-color format can be written.
+ * No compression is supported.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * This code contributed by James Arthur Boucher.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef BMP_SUPPORTED
+
+
+/*
+ * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
+ * This is not yet implemented.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+/*
+ * Since BMP stores scanlines bottom-to-top, we have to invert the image
+ * from JPEG's top-to-bottom order. To do this, we save the outgoing data
+ * in a virtual array during put_pixel_row calls, then actually emit the
+ * BMP file during finish_output. The virtual array contains one JSAMPLE per
+ * pixel if the output is grayscale or colormapped, three if it is full color.
+ */
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ boolean is_os2; /* saves the OS2 format request flag */
+
+ jvirt_sarray_ptr whole_image; /* needed to reverse row order */
+ JDIMENSION data_width; /* JSAMPLEs per row */
+ JDIMENSION row_width; /* physical width of one row in the BMP file */
+ int pad_bytes; /* number of padding bytes needed per row */
+ JDIMENSION cur_output_row; /* next row# to write to virtual array */
+} bmp_dest_struct;
+
+typedef bmp_dest_struct * bmp_dest_ptr;
+
+
+/* Forward declarations */
+LOCAL(void) write_colormap
+ JPP((j_decompress_ptr cinfo, bmp_dest_ptr dest,
+ int map_colors, int map_entry_size));
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* This version is for writing 24-bit pixels */
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ int pad;
+
+ /* Access next row in virtual array */
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image,
+ dest->cur_output_row, (JDIMENSION) 1, TRUE);
+ dest->cur_output_row++;
+
+ /* Transfer data. Note destination values must be in BGR order
+ * (even though Microsoft's own documents say the opposite).
+ */
+ inptr = dest->pub.buffer[0];
+ outptr = image_ptr[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ outptr[2] = *inptr++; /* can omit GETJSAMPLE() safely */
+ outptr[1] = *inptr++;
+ outptr[0] = *inptr++;
+ outptr += 3;
+ }
+
+ /* Zero out the pad bytes. */
+ pad = dest->pad_bytes;
+ while (--pad >= 0)
+ *outptr++ = 0;
+}
+
+METHODDEF(void)
+put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* This version is for grayscale OR quantized color output */
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW inptr, outptr;
+ register JDIMENSION col;
+ int pad;
+
+ /* Access next row in virtual array */
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image,
+ dest->cur_output_row, (JDIMENSION) 1, TRUE);
+ dest->cur_output_row++;
+
+ /* Transfer data. */
+ inptr = dest->pub.buffer[0];
+ outptr = image_ptr[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = *inptr++; /* can omit GETJSAMPLE() safely */
+ }
+
+ /* Zero out the pad bytes. */
+ pad = dest->pad_bytes;
+ while (--pad >= 0)
+ *outptr++ = 0;
+}
+
+
+/*
+ * Startup: normally writes the file header.
+ * In this module we may as well postpone everything until finish_output.
+ */
+
+METHODDEF(void)
+start_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* no work here */
+}
+
+
+/*
+ * Finish up at the end of the file.
+ *
+ * Here is where we really output the BMP file.
+ *
+ * First, routines to write the Windows and OS/2 variants of the file header.
+ */
+
+LOCAL(void)
+write_bmp_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
+/* Write a Windows-style BMP file header, including colormap if needed */
+{
+ char bmpfileheader[14];
+ char bmpinfoheader[40];
+#define PUT_2B(array,offset,value) \
+ (array[offset] = (char) ((value) & 0xFF), \
+ array[offset+1] = (char) (((value) >> 8) & 0xFF))
+#define PUT_4B(array,offset,value) \
+ (array[offset] = (char) ((value) & 0xFF), \
+ array[offset+1] = (char) (((value) >> 8) & 0xFF), \
+ array[offset+2] = (char) (((value) >> 16) & 0xFF), \
+ array[offset+3] = (char) (((value) >> 24) & 0xFF))
+ INT32 headersize, bfSize;
+ int bits_per_pixel, cmap_entries;
+
+ /* Compute colormap size and total file size */
+ if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* Colormapped RGB */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ } else {
+ /* Unquantized, full color RGB */
+ bits_per_pixel = 24;
+ cmap_entries = 0;
+ }
+ } else {
+ /* Grayscale output. We need to fake a 256-entry colormap. */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ }
+ /* File size */
+ headersize = 14 + 40 + cmap_entries * 4; /* Header and colormap */
+ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
+ MEMZERO(bmpinfoheader, SIZEOF(bmpinfoheader));
+
+ /* Fill the file header */
+ bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
+ bmpfileheader[1] = 0x4D;
+ PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
+ /* we leave bfReserved1 & bfReserved2 = 0 */
+ PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
+
+ /* Fill the info header (Microsoft calls this a BITMAPINFOHEADER) */
+ PUT_2B(bmpinfoheader, 0, 40); /* biSize */
+ PUT_4B(bmpinfoheader, 4, cinfo->output_width); /* biWidth */
+ PUT_4B(bmpinfoheader, 8, cinfo->output_height); /* biHeight */
+ PUT_2B(bmpinfoheader, 12, 1); /* biPlanes - must be 1 */
+ PUT_2B(bmpinfoheader, 14, bits_per_pixel); /* biBitCount */
+ /* we leave biCompression = 0, for none */
+ /* we leave biSizeImage = 0; this is correct for uncompressed data */
+ if (cinfo->density_unit == 2) { /* if have density in dots/cm, then */
+ PUT_4B(bmpinfoheader, 24, (INT32) (cinfo->X_density*100)); /* XPels/M */
+ PUT_4B(bmpinfoheader, 28, (INT32) (cinfo->Y_density*100)); /* XPels/M */
+ }
+ PUT_2B(bmpinfoheader, 32, cmap_entries); /* biClrUsed */
+ /* we leave biClrImportant = 0 */
+
+ if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ if (JFWRITE(dest->pub.output_file, bmpinfoheader, 40) != (size_t) 40)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ if (cmap_entries > 0)
+ write_colormap(cinfo, dest, cmap_entries, 4);
+}
+
+
+LOCAL(void)
+write_os2_header (j_decompress_ptr cinfo, bmp_dest_ptr dest)
+/* Write an OS2-style BMP file header, including colormap if needed */
+{
+ char bmpfileheader[14];
+ char bmpcoreheader[12];
+ INT32 headersize, bfSize;
+ int bits_per_pixel, cmap_entries;
+
+ /* Compute colormap size and total file size */
+ if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* Colormapped RGB */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ } else {
+ /* Unquantized, full color RGB */
+ bits_per_pixel = 24;
+ cmap_entries = 0;
+ }
+ } else {
+ /* Grayscale output. We need to fake a 256-entry colormap. */
+ bits_per_pixel = 8;
+ cmap_entries = 256;
+ }
+ /* File size */
+ headersize = 14 + 12 + cmap_entries * 3; /* Header and colormap */
+ bfSize = headersize + (INT32) dest->row_width * (INT32) cinfo->output_height;
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(bmpfileheader, SIZEOF(bmpfileheader));
+ MEMZERO(bmpcoreheader, SIZEOF(bmpcoreheader));
+
+ /* Fill the file header */
+ bmpfileheader[0] = 0x42; /* first 2 bytes are ASCII 'B', 'M' */
+ bmpfileheader[1] = 0x4D;
+ PUT_4B(bmpfileheader, 2, bfSize); /* bfSize */
+ /* we leave bfReserved1 & bfReserved2 = 0 */
+ PUT_4B(bmpfileheader, 10, headersize); /* bfOffBits */
+
+ /* Fill the info header (Microsoft calls this a BITMAPCOREHEADER) */
+ PUT_2B(bmpcoreheader, 0, 12); /* bcSize */
+ PUT_2B(bmpcoreheader, 4, cinfo->output_width); /* bcWidth */
+ PUT_2B(bmpcoreheader, 6, cinfo->output_height); /* bcHeight */
+ PUT_2B(bmpcoreheader, 8, 1); /* bcPlanes - must be 1 */
+ PUT_2B(bmpcoreheader, 10, bits_per_pixel); /* bcBitCount */
+
+ if (JFWRITE(dest->pub.output_file, bmpfileheader, 14) != (size_t) 14)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+ if (JFWRITE(dest->pub.output_file, bmpcoreheader, 12) != (size_t) 12)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+
+ if (cmap_entries > 0)
+ write_colormap(cinfo, dest, cmap_entries, 3);
+}
+
+
+/*
+ * Write the colormap.
+ * Windows uses BGR0 map entries; OS/2 uses BGR entries.
+ */
+
+LOCAL(void)
+write_colormap (j_decompress_ptr cinfo, bmp_dest_ptr dest,
+ int map_colors, int map_entry_size)
+{
+ JSAMPARRAY colormap = cinfo->colormap;
+ int num_colors = cinfo->actual_number_of_colors;
+ FILE * outfile = dest->pub.output_file;
+ int i;
+
+ if (colormap != NULL) {
+ if (cinfo->out_color_components == 3) {
+ /* Normal case with RGB colormap */
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(colormap[2][i]), outfile);
+ putc(GETJSAMPLE(colormap[1][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ } else {
+ /* Grayscale colormap (only happens with grayscale quantization) */
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ putc(GETJSAMPLE(colormap[0][i]), outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ }
+ } else {
+ /* If no colormap, must be grayscale data. Generate a linear "map". */
+ for (i = 0; i < 256; i++) {
+ putc(i, outfile);
+ putc(i, outfile);
+ putc(i, outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+ }
+ /* Pad colormap with zeros to ensure specified number of colormap entries */
+ if (i > map_colors)
+ ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, i);
+ for (; i < map_colors; i++) {
+ putc(0, outfile);
+ putc(0, outfile);
+ putc(0, outfile);
+ if (map_entry_size == 4)
+ putc(0, outfile);
+ }
+}
+
+
+METHODDEF(void)
+finish_output_bmp (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ bmp_dest_ptr dest = (bmp_dest_ptr) dinfo;
+ register FILE * outfile = dest->pub.output_file;
+ JSAMPARRAY image_ptr;
+ register JSAMPROW data_ptr;
+ JDIMENSION row;
+ register JDIMENSION col;
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+
+ /* Write the header and colormap */
+ if (dest->is_os2)
+ write_os2_header(cinfo, dest);
+ else
+ write_bmp_header(cinfo, dest);
+
+ /* Write the file body from our virtual array */
+ for (row = cinfo->output_height; row > 0; row--) {
+ if (progress != NULL) {
+ progress->pub.pass_counter = (long) (cinfo->output_height - row);
+ progress->pub.pass_limit = (long) cinfo->output_height;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+ image_ptr = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->whole_image, row-1, (JDIMENSION) 1, FALSE);
+ data_ptr = image_ptr[0];
+ for (col = dest->row_width; col > 0; col--) {
+ putc(GETJSAMPLE(*data_ptr), outfile);
+ data_ptr++;
+ }
+ }
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+
+ /* Make sure we wrote the output file OK */
+ fflush(outfile);
+ if (ferror(outfile))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for BMP format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_bmp (j_decompress_ptr cinfo, boolean is_os2)
+{
+ bmp_dest_ptr dest;
+ JDIMENSION row_width;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (bmp_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(bmp_dest_struct));
+ dest->pub.start_output = start_output_bmp;
+ dest->pub.finish_output = finish_output_bmp;
+ dest->is_os2 = is_os2;
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = put_gray_rows;
+ else
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ } else {
+ ERREXIT(cinfo, JERR_BMP_COLORSPACE);
+ }
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Determine width of rows in the BMP file (padded to 4-byte boundary). */
+ row_width = cinfo->output_width * cinfo->output_components;
+ dest->data_width = row_width;
+ while ((row_width & 3) != 0) row_width++;
+ dest->row_width = row_width;
+ dest->pad_bytes = (int) (row_width - dest->data_width);
+
+ /* Allocate space for inversion array, prepare for write pass */
+ dest->whole_image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ row_width, cinfo->output_height, (JDIMENSION) 1);
+ dest->cur_output_row = 0;
+ if (cinfo->progress != NULL) {
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+ progress->total_extra_passes++; /* count file input as separate pass */
+ }
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, row_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* BMP_SUPPORTED */
diff --git a/Source/LibJPEG/wrgif.c b/Source/LibJPEG/wrgif.c
new file mode 100644
index 0000000..5fe8328
--- /dev/null
+++ b/Source/LibJPEG/wrgif.c
@@ -0,0 +1,399 @@
+/*
+ * wrgif.c
+ *
+ * Copyright (C) 1991-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in GIF format.
+ *
+ **************************************************************************
+ * NOTE: to avoid entanglements with Unisys' patent on LZW compression, *
+ * this code has been modified to output "uncompressed GIF" files. *
+ * There is no trace of the LZW algorithm in this file. *
+ **************************************************************************
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ */
+
+/*
+ * This code is loosely based on ppmtogif from the PBMPLUS distribution
+ * of Feb. 1991. That file contains the following copyright notice:
+ * Based on GIFENCODE by David Rowley <mgardi@watdscu.waterloo.edu>.
+ * Lempel-Ziv compression based on "compress" by Spencer W. Thomas et al.
+ * Copyright (C) 1989 by Jef Poskanzer.
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "as is" without express or
+ * implied warranty.
+ *
+ * We are also required to state that
+ * "The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated."
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef GIF_SUPPORTED
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ j_decompress_ptr cinfo; /* back link saves passing separate parm */
+
+ /* State for packing variable-width codes into a bitstream */
+ int n_bits; /* current number of bits/code */
+ int maxcode; /* maximum code, given n_bits */
+ INT32 cur_accum; /* holds bits not yet output */
+ int cur_bits; /* # of bits in cur_accum */
+
+ /* State for GIF code assignment */
+ int ClearCode; /* clear code (doesn't change) */
+ int EOFCode; /* EOF code (ditto) */
+ int code_counter; /* counts output symbols */
+
+ /* GIF data packet construction buffer */
+ int bytesinpkt; /* # of bytes in current packet */
+ char packetbuf[256]; /* workspace for accumulating packet */
+
+} gif_dest_struct;
+
+typedef gif_dest_struct * gif_dest_ptr;
+
+/* Largest value that will fit in N bits */
+#define MAXCODE(n_bits) ((1 << (n_bits)) - 1)
+
+
+/*
+ * Routines to package finished data bytes into GIF data blocks.
+ * A data block consists of a count byte (1..255) and that many data bytes.
+ */
+
+LOCAL(void)
+flush_packet (gif_dest_ptr dinfo)
+/* flush any accumulated data */
+{
+ if (dinfo->bytesinpkt > 0) { /* never write zero-length packet */
+ dinfo->packetbuf[0] = (char) dinfo->bytesinpkt++;
+ if (JFWRITE(dinfo->pub.output_file, dinfo->packetbuf, dinfo->bytesinpkt)
+ != (size_t) dinfo->bytesinpkt)
+ ERREXIT(dinfo->cinfo, JERR_FILE_WRITE);
+ dinfo->bytesinpkt = 0;
+ }
+}
+
+
+/* Add a character to current packet; flush to disk if necessary */
+#define CHAR_OUT(dinfo,c) \
+ { (dinfo)->packetbuf[++(dinfo)->bytesinpkt] = (char) (c); \
+ if ((dinfo)->bytesinpkt >= 255) \
+ flush_packet(dinfo); \
+ }
+
+
+/* Routine to convert variable-width codes into a byte stream */
+
+LOCAL(void)
+output (gif_dest_ptr dinfo, int code)
+/* Emit a code of n_bits bits */
+/* Uses cur_accum and cur_bits to reblock into 8-bit bytes */
+{
+ dinfo->cur_accum |= ((INT32) code) << dinfo->cur_bits;
+ dinfo->cur_bits += dinfo->n_bits;
+
+ while (dinfo->cur_bits >= 8) {
+ CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
+ dinfo->cur_accum >>= 8;
+ dinfo->cur_bits -= 8;
+ }
+}
+
+
+/* The pseudo-compression algorithm.
+ *
+ * In this module we simply output each pixel value as a separate symbol;
+ * thus, no compression occurs. In fact, there is expansion of one bit per
+ * pixel, because we use a symbol width one bit wider than the pixel width.
+ *
+ * GIF ordinarily uses variable-width symbols, and the decoder will expect
+ * to ratchet up the symbol width after a fixed number of symbols.
+ * To simplify the logic and keep the expansion penalty down, we emit a
+ * GIF Clear code to reset the decoder just before the width would ratchet up.
+ * Thus, all the symbols in the output file will have the same bit width.
+ * Note that emitting the Clear codes at the right times is a mere matter of
+ * counting output symbols and is in no way dependent on the LZW patent.
+ *
+ * With a small basic pixel width (low color count), Clear codes will be
+ * needed very frequently, causing the file to expand even more. So this
+ * simplistic approach wouldn't work too well on bilevel images, for example.
+ * But for output of JPEG conversions the pixel width will usually be 8 bits
+ * (129 to 256 colors), so the overhead added by Clear symbols is only about
+ * one symbol in every 256.
+ */
+
+LOCAL(void)
+compress_init (gif_dest_ptr dinfo, int i_bits)
+/* Initialize pseudo-compressor */
+{
+ /* init all the state variables */
+ dinfo->n_bits = i_bits;
+ dinfo->maxcode = MAXCODE(dinfo->n_bits);
+ dinfo->ClearCode = (1 << (i_bits - 1));
+ dinfo->EOFCode = dinfo->ClearCode + 1;
+ dinfo->code_counter = dinfo->ClearCode + 2;
+ /* init output buffering vars */
+ dinfo->bytesinpkt = 0;
+ dinfo->cur_accum = 0;
+ dinfo->cur_bits = 0;
+ /* GIF specifies an initial Clear code */
+ output(dinfo, dinfo->ClearCode);
+}
+
+
+LOCAL(void)
+compress_pixel (gif_dest_ptr dinfo, int c)
+/* Accept and "compress" one pixel value.
+ * The given value must be less than n_bits wide.
+ */
+{
+ /* Output the given pixel value as a symbol. */
+ output(dinfo, c);
+ /* Issue Clear codes often enough to keep the reader from ratcheting up
+ * its symbol size.
+ */
+ if (dinfo->code_counter < dinfo->maxcode) {
+ dinfo->code_counter++;
+ } else {
+ output(dinfo, dinfo->ClearCode);
+ dinfo->code_counter = dinfo->ClearCode + 2; /* reset the counter */
+ }
+}
+
+
+LOCAL(void)
+compress_term (gif_dest_ptr dinfo)
+/* Clean up at end */
+{
+ /* Send an EOF code */
+ output(dinfo, dinfo->EOFCode);
+ /* Flush the bit-packing buffer */
+ if (dinfo->cur_bits > 0) {
+ CHAR_OUT(dinfo, dinfo->cur_accum & 0xFF);
+ }
+ /* Flush the packet buffer */
+ flush_packet(dinfo);
+}
+
+
+/* GIF header construction */
+
+
+LOCAL(void)
+put_word (gif_dest_ptr dinfo, unsigned int w)
+/* Emit a 16-bit word, LSB first */
+{
+ putc(w & 0xFF, dinfo->pub.output_file);
+ putc((w >> 8) & 0xFF, dinfo->pub.output_file);
+}
+
+
+LOCAL(void)
+put_3bytes (gif_dest_ptr dinfo, int val)
+/* Emit 3 copies of same byte value --- handy subr for colormap construction */
+{
+ putc(val, dinfo->pub.output_file);
+ putc(val, dinfo->pub.output_file);
+ putc(val, dinfo->pub.output_file);
+}
+
+
+LOCAL(void)
+emit_header (gif_dest_ptr dinfo, int num_colors, JSAMPARRAY colormap)
+/* Output the GIF file header, including color map */
+/* If colormap==NULL, synthesize a gray-scale colormap */
+{
+ int BitsPerPixel, ColorMapSize, InitCodeSize, FlagByte;
+ int cshift = dinfo->cinfo->data_precision - 8;
+ int i;
+
+ if (num_colors > 256)
+ ERREXIT1(dinfo->cinfo, JERR_TOO_MANY_COLORS, num_colors);
+ /* Compute bits/pixel and related values */
+ BitsPerPixel = 1;
+ while (num_colors > (1 << BitsPerPixel))
+ BitsPerPixel++;
+ ColorMapSize = 1 << BitsPerPixel;
+ if (BitsPerPixel <= 1)
+ InitCodeSize = 2;
+ else
+ InitCodeSize = BitsPerPixel;
+ /*
+ * Write the GIF header.
+ * Note that we generate a plain GIF87 header for maximum compatibility.
+ */
+ putc('G', dinfo->pub.output_file);
+ putc('I', dinfo->pub.output_file);
+ putc('F', dinfo->pub.output_file);
+ putc('8', dinfo->pub.output_file);
+ putc('7', dinfo->pub.output_file);
+ putc('a', dinfo->pub.output_file);
+ /* Write the Logical Screen Descriptor */
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_width);
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
+ FlagByte = 0x80; /* Yes, there is a global color table */
+ FlagByte |= (BitsPerPixel-1) << 4; /* color resolution */
+ FlagByte |= (BitsPerPixel-1); /* size of global color table */
+ putc(FlagByte, dinfo->pub.output_file);
+ putc(0, dinfo->pub.output_file); /* Background color index */
+ putc(0, dinfo->pub.output_file); /* Reserved (aspect ratio in GIF89) */
+ /* Write the Global Color Map */
+ /* If the color map is more than 8 bits precision, */
+ /* we reduce it to 8 bits by shifting */
+ for (i=0; i < ColorMapSize; i++) {
+ if (i < num_colors) {
+ if (colormap != NULL) {
+ if (dinfo->cinfo->out_color_space == JCS_RGB) {
+ /* Normal case: RGB color map */
+ putc(GETJSAMPLE(colormap[0][i]) >> cshift, dinfo->pub.output_file);
+ putc(GETJSAMPLE(colormap[1][i]) >> cshift, dinfo->pub.output_file);
+ putc(GETJSAMPLE(colormap[2][i]) >> cshift, dinfo->pub.output_file);
+ } else {
+ /* Grayscale "color map": possible if quantizing grayscale image */
+ put_3bytes(dinfo, GETJSAMPLE(colormap[0][i]) >> cshift);
+ }
+ } else {
+ /* Create a gray-scale map of num_colors values, range 0..255 */
+ put_3bytes(dinfo, (i * 255 + (num_colors-1)/2) / (num_colors-1));
+ }
+ } else {
+ /* fill out the map to a power of 2 */
+ put_3bytes(dinfo, 0);
+ }
+ }
+ /* Write image separator and Image Descriptor */
+ putc(',', dinfo->pub.output_file); /* separator */
+ put_word(dinfo, 0); /* left/top offset */
+ put_word(dinfo, 0);
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_width); /* image size */
+ put_word(dinfo, (unsigned int) dinfo->cinfo->output_height);
+ /* flag byte: not interlaced, no local color map */
+ putc(0x00, dinfo->pub.output_file);
+ /* Write Initial Code Size byte */
+ putc(InitCodeSize, dinfo->pub.output_file);
+
+ /* Initialize for "compression" of image data */
+ compress_init(dinfo, InitCodeSize+1);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+
+ if (cinfo->quantize_colors)
+ emit_header(dest, cinfo->actual_number_of_colors, cinfo->colormap);
+ else
+ emit_header(dest, 256, (JSAMPARRAY) NULL);
+}
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ for (col = cinfo->output_width; col > 0; col--) {
+ compress_pixel(dest, GETJSAMPLE(*ptr++));
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_gif (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ gif_dest_ptr dest = (gif_dest_ptr) dinfo;
+
+ /* Flush "compression" mechanism */
+ compress_term(dest);
+ /* Write a zero-length data block to end the series */
+ putc(0, dest->pub.output_file);
+ /* Write the GIF terminator mark */
+ putc(';', dest->pub.output_file);
+ /* Make sure we wrote the output file OK */
+ fflush(dest->pub.output_file);
+ if (ferror(dest->pub.output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for GIF format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_gif (j_decompress_ptr cinfo)
+{
+ gif_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (gif_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(gif_dest_struct));
+ dest->cinfo = cinfo; /* make back link for subroutines */
+ dest->pub.start_output = start_output_gif;
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ dest->pub.finish_output = finish_output_gif;
+
+ if (cinfo->out_color_space != JCS_GRAYSCALE &&
+ cinfo->out_color_space != JCS_RGB)
+ ERREXIT(cinfo, JERR_GIF_COLORSPACE);
+
+ /* Force quantization if color or if > 8 bits input */
+ if (cinfo->out_color_space != JCS_GRAYSCALE || cinfo->data_precision > 8) {
+ /* Force quantization to at most 256 colors */
+ cinfo->quantize_colors = TRUE;
+ if (cinfo->desired_number_of_colors > 256)
+ cinfo->desired_number_of_colors = 256;
+ }
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ if (cinfo->output_components != 1) /* safety check: just one component? */
+ ERREXIT(cinfo, JERR_GIF_BUG);
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, cinfo->output_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* GIF_SUPPORTED */
diff --git a/Source/LibJPEG/wrjpgcom.c b/Source/LibJPEG/wrjpgcom.c
new file mode 100644
index 0000000..8c04b05
--- /dev/null
+++ b/Source/LibJPEG/wrjpgcom.c
@@ -0,0 +1,583 @@
+/*
+ * wrjpgcom.c
+ *
+ * Copyright (C) 1994-1997, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains a very simple stand-alone application that inserts
+ * user-supplied text as a COM (comment) marker in a JFIF file.
+ * This may be useful as an example of the minimum logic needed to parse
+ * JPEG markers.
+ */
+
+#define JPEG_CJPEG_DJPEG /* to get the command-line config symbols */
+#include "jinclude.h" /* get auto-config symbols, <stdio.h> */
+
+#ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc() */
+extern void * malloc ();
+#endif
+#include <ctype.h> /* to declare isupper(), tolower() */
+#ifdef USE_SETMODE
+#include <fcntl.h> /* to declare setmode()'s parameter macros */
+/* If you have setmode() but not <io.h>, just delete this line: */
+#include <io.h> /* to declare setmode() */
+#endif
+
+#ifdef USE_CCOMMAND /* command-line reader for Macintosh */
+#ifdef __MWERKS__
+#include <SIOUX.h> /* Metrowerks needs this */
+#include <console.h> /* ... and this */
+#endif
+#ifdef THINK_C
+#include <console.h> /* Think declares it here */
+#endif
+#endif
+
+#ifdef DONT_USE_B_MODE /* define mode parameters for fopen() */
+#define READ_BINARY "r"
+#define WRITE_BINARY "w"
+#else
+#ifdef VMS /* VMS is very nonstandard */
+#define READ_BINARY "rb", "ctx=stm"
+#define WRITE_BINARY "wb", "ctx=stm"
+#else /* standard ANSI-compliant case */
+#define READ_BINARY "rb"
+#define WRITE_BINARY "wb"
+#endif
+#endif
+
+#ifndef EXIT_FAILURE /* define exit() codes if not provided */
+#define EXIT_FAILURE 1
+#endif
+#ifndef EXIT_SUCCESS
+#ifdef VMS
+#define EXIT_SUCCESS 1 /* VMS is very nonstandard */
+#else
+#define EXIT_SUCCESS 0
+#endif
+#endif
+
+/* Reduce this value if your malloc() can't allocate blocks up to 64K.
+ * On DOS, compiling in large model is usually a better solution.
+ */
+
+#ifndef MAX_COM_LENGTH
+#define MAX_COM_LENGTH 65000L /* must be <= 65533 in any case */
+#endif
+
+
+/*
+ * These macros are used to read the input file and write the output file.
+ * To reuse this code in another application, you might need to change these.
+ */
+
+static FILE * infile; /* input JPEG file */
+
+/* Return next input byte, or EOF if no more */
+#define NEXTBYTE() getc(infile)
+
+static FILE * outfile; /* output JPEG file */
+
+/* Emit an output byte */
+#define PUTBYTE(x) putc((x), outfile)
+
+
+/* Error exit handler */
+#define ERREXIT(msg) (fprintf(stderr, "%s\n", msg), exit(EXIT_FAILURE))
+
+
+/* Read one byte, testing for EOF */
+static int
+read_1_byte (void)
+{
+ int c;
+
+ c = NEXTBYTE();
+ if (c == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return c;
+}
+
+/* Read 2 bytes, convert to unsigned int */
+/* All 2-byte quantities in JPEG markers are MSB first */
+static unsigned int
+read_2_bytes (void)
+{
+ int c1, c2;
+
+ c1 = NEXTBYTE();
+ if (c1 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ c2 = NEXTBYTE();
+ if (c2 == EOF)
+ ERREXIT("Premature EOF in JPEG file");
+ return (((unsigned int) c1) << 8) + ((unsigned int) c2);
+}
+
+
+/* Routines to write data to output file */
+
+static void
+write_1_byte (int c)
+{
+ PUTBYTE(c);
+}
+
+static void
+write_2_bytes (unsigned int val)
+{
+ PUTBYTE((val >> 8) & 0xFF);
+ PUTBYTE(val & 0xFF);
+}
+
+static void
+write_marker (int marker)
+{
+ PUTBYTE(0xFF);
+ PUTBYTE(marker);
+}
+
+static void
+copy_rest_of_file (void)
+{
+ int c;
+
+ while ((c = NEXTBYTE()) != EOF)
+ PUTBYTE(c);
+}
+
+
+/*
+ * JPEG markers consist of one or more 0xFF bytes, followed by a marker
+ * code byte (which is not an FF). Here are the marker codes of interest
+ * in this program. (See jdmarker.c for a more complete list.)
+ */
+
+#define M_SOF0 0xC0 /* Start Of Frame N */
+#define M_SOF1 0xC1 /* N indicates which compression process */
+#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */
+#define M_EOI 0xD9 /* End Of Image (end of datastream) */
+#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+#define M_COM 0xFE /* COMment */
+
+
+/*
+ * Find the next JPEG marker and return its marker code.
+ * We expect at least one FF byte, possibly more if the compressor used FFs
+ * to pad the file. (Padding FFs will NOT be replicated in the output file.)
+ * There could also be non-FF garbage between markers. The treatment of such
+ * garbage is unspecified; we choose to skip over it but emit a warning msg.
+ * NB: this routine must not be used after seeing SOS marker, since it will
+ * not deal correctly with FF/00 sequences in the compressed image data...
+ */
+
+static int
+next_marker (void)
+{
+ int c;
+ int discarded_bytes = 0;
+
+ /* Find 0xFF byte; count and skip any non-FFs. */
+ c = read_1_byte();
+ while (c != 0xFF) {
+ discarded_bytes++;
+ c = read_1_byte();
+ }
+ /* Get marker code byte, swallowing any duplicate FF bytes. Extra FFs
+ * are legal as pad bytes, so don't count them in discarded_bytes.
+ */
+ do {
+ c = read_1_byte();
+ } while (c == 0xFF);
+
+ if (discarded_bytes != 0) {
+ fprintf(stderr, "Warning: garbage data found in JPEG file\n");
+ }
+
+ return c;
+}
+
+
+/*
+ * Read the initial marker, which should be SOI.
+ * For a JFIF file, the first two bytes of the file should be literally
+ * 0xFF M_SOI. To be more general, we could use next_marker, but if the
+ * input file weren't actually JPEG at all, next_marker might read the whole
+ * file and then return a misleading error message...
+ */
+
+static int
+first_marker (void)
+{
+ int c1, c2;
+
+ c1 = NEXTBYTE();
+ c2 = NEXTBYTE();
+ if (c1 != 0xFF || c2 != M_SOI)
+ ERREXIT("Not a JPEG file");
+ return c2;
+}
+
+
+/*
+ * Most types of marker are followed by a variable-length parameter segment.
+ * This routine skips over the parameters for any marker we don't otherwise
+ * want to process.
+ * Note that we MUST skip the parameter segment explicitly in order not to
+ * be fooled by 0xFF bytes that might appear within the parameter segment;
+ * such bytes do NOT introduce new markers.
+ */
+
+static void
+copy_variable (void)
+/* Copy an unknown or uninteresting variable-length marker */
+{
+ unsigned int length;
+
+ /* Get the marker parameter length count */
+ length = read_2_bytes();
+ write_2_bytes(length);
+ /* Length includes itself, so must be at least 2 */
+ if (length < 2)
+ ERREXIT("Erroneous JPEG marker length");
+ length -= 2;
+ /* Skip over the remaining bytes */
+ while (length > 0) {
+ write_1_byte(read_1_byte());
+ length--;
+ }
+}
+
+static void
+skip_variable (void)
+/* Skip over an unknown or uninteresting variable-length marker */
+{
+ unsigned int length;
+
+ /* Get the marker parameter length count */
+ length = read_2_bytes();
+ /* Length includes itself, so must be at least 2 */
+ if (length < 2)
+ ERREXIT("Erroneous JPEG marker length");
+ length -= 2;
+ /* Skip over the remaining bytes */
+ while (length > 0) {
+ (void) read_1_byte();
+ length--;
+ }
+}
+
+
+/*
+ * Parse the marker stream until SOFn or EOI is seen;
+ * copy data to output, but discard COM markers unless keep_COM is true.
+ */
+
+static int
+scan_JPEG_header (int keep_COM)
+{
+ int marker;
+
+ /* Expect SOI at start of file */
+ if (first_marker() != M_SOI)
+ ERREXIT("Expected SOI marker first");
+ write_marker(M_SOI);
+
+ /* Scan miscellaneous markers until we reach SOFn. */
+ for (;;) {
+ marker = next_marker();
+ switch (marker) {
+ /* Note that marker codes 0xC4, 0xC8, 0xCC are not, and must not be,
+ * treated as SOFn. C4 in particular is actually DHT.
+ */
+ case M_SOF0: /* Baseline */
+ case M_SOF1: /* Extended sequential, Huffman */
+ case M_SOF2: /* Progressive, Huffman */
+ case M_SOF3: /* Lossless, Huffman */
+ case M_SOF5: /* Differential sequential, Huffman */
+ case M_SOF6: /* Differential progressive, Huffman */
+ case M_SOF7: /* Differential lossless, Huffman */
+ case M_SOF9: /* Extended sequential, arithmetic */
+ case M_SOF10: /* Progressive, arithmetic */
+ case M_SOF11: /* Lossless, arithmetic */
+ case M_SOF13: /* Differential sequential, arithmetic */
+ case M_SOF14: /* Differential progressive, arithmetic */
+ case M_SOF15: /* Differential lossless, arithmetic */
+ return marker;
+
+ case M_SOS: /* should not see compressed data before SOF */
+ ERREXIT("SOS without prior SOFn");
+ break;
+
+ case M_EOI: /* in case it's a tables-only JPEG stream */
+ return marker;
+
+ case M_COM: /* Existing COM: conditionally discard */
+ if (keep_COM) {
+ write_marker(marker);
+ copy_variable();
+ } else {
+ skip_variable();
+ }
+ break;
+
+ default: /* Anything else just gets copied */
+ write_marker(marker);
+ copy_variable(); /* we assume it has a parameter count... */
+ break;
+ }
+ } /* end loop */
+}
+
+
+/* Command line parsing code */
+
+static const char * progname; /* program name for error messages */
+
+
+static void
+usage (void)
+/* complain about bad command line */
+{
+ fprintf(stderr, "wrjpgcom inserts a textual comment in a JPEG file.\n");
+ fprintf(stderr, "You can add to or replace any existing comment(s).\n");
+
+ fprintf(stderr, "Usage: %s [switches] ", progname);
+#ifdef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "inputfile outputfile\n");
+#else
+ fprintf(stderr, "[inputfile]\n");
+#endif
+
+ fprintf(stderr, "Switches (names may be abbreviated):\n");
+ fprintf(stderr, " -replace Delete any existing comments\n");
+ fprintf(stderr, " -comment \"text\" Insert comment with given text\n");
+ fprintf(stderr, " -cfile name Read comment from named file\n");
+ fprintf(stderr, "Notice that you must put quotes around the comment text\n");
+ fprintf(stderr, "when you use -comment.\n");
+ fprintf(stderr, "If you do not give either -comment or -cfile on the command line,\n");
+ fprintf(stderr, "then the comment text is read from standard input.\n");
+ fprintf(stderr, "It can be multiple lines, up to %u characters total.\n",
+ (unsigned int) MAX_COM_LENGTH);
+#ifndef TWO_FILE_COMMANDLINE
+ fprintf(stderr, "You must specify an input JPEG file name when supplying\n");
+ fprintf(stderr, "comment text from standard input.\n");
+#endif
+
+ exit(EXIT_FAILURE);
+}
+
+
+static int
+keymatch (char * arg, const char * keyword, int minchars)
+/* Case-insensitive matching of (possibly abbreviated) keyword switches. */
+/* keyword is the constant keyword (must be lower case already), */
+/* minchars is length of minimum legal abbreviation. */
+{
+ register int ca, ck;
+ register int nmatched = 0;
+
+ while ((ca = *arg++) != '\0') {
+ if ((ck = *keyword++) == '\0')
+ return 0; /* arg longer than keyword, no good */
+ if (isupper(ca)) /* force arg to lcase (assume ck is already) */
+ ca = tolower(ca);
+ if (ca != ck)
+ return 0; /* no good */
+ nmatched++; /* count matched characters */
+ }
+ /* reached end of argument; fail if it's too short for unique abbrev */
+ if (nmatched < minchars)
+ return 0;
+ return 1; /* A-OK */
+}
+
+
+/*
+ * The main program.
+ */
+
+int
+main (int argc, char **argv)
+{
+ int argn;
+ char * arg;
+ int keep_COM = 1;
+ char * comment_arg = NULL;
+ FILE * comment_file = NULL;
+ unsigned int comment_length = 0;
+ int marker;
+
+ /* On Mac, fetch a command line. */
+#ifdef USE_CCOMMAND
+ argc = ccommand(&argv);
+#endif
+
+ progname = argv[0];
+ if (progname == NULL || progname[0] == 0)
+ progname = "wrjpgcom"; /* in case C library doesn't provide it */
+
+ /* Parse switches, if any */
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (arg[0] != '-')
+ break; /* not switch, must be file name */
+ arg++; /* advance over '-' */
+ if (keymatch(arg, "replace", 1)) {
+ keep_COM = 0;
+ } else if (keymatch(arg, "cfile", 2)) {
+ if (++argn >= argc) usage();
+ if ((comment_file = fopen(argv[argn], "r")) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ } else if (keymatch(arg, "comment", 1)) {
+ if (++argn >= argc) usage();
+ comment_arg = argv[argn];
+ /* If the comment text starts with '"', then we are probably running
+ * under MS-DOG and must parse out the quoted string ourselves. Sigh.
+ */
+ if (comment_arg[0] == '"') {
+ comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
+ if (comment_arg == NULL)
+ ERREXIT("Insufficient memory");
+ strcpy(comment_arg, argv[argn]+1);
+ for (;;) {
+ comment_length = (unsigned int) strlen(comment_arg);
+ if (comment_length > 0 && comment_arg[comment_length-1] == '"') {
+ comment_arg[comment_length-1] = '\0'; /* zap terminating quote */
+ break;
+ }
+ if (++argn >= argc)
+ ERREXIT("Missing ending quote mark");
+ strcat(comment_arg, " ");
+ strcat(comment_arg, argv[argn]);
+ }
+ }
+ comment_length = (unsigned int) strlen(comment_arg);
+ } else
+ usage();
+ }
+
+ /* Cannot use both -comment and -cfile. */
+ if (comment_arg != NULL && comment_file != NULL)
+ usage();
+ /* If there is neither -comment nor -cfile, we will read the comment text
+ * from stdin; in this case there MUST be an input JPEG file name.
+ */
+ if (comment_arg == NULL && comment_file == NULL && argn >= argc)
+ usage();
+
+ /* Open the input file. */
+ if (argn < argc) {
+ if ((infile = fopen(argv[argn], READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ /* default input file is stdin */
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdin), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((infile = fdopen(fileno(stdin), READ_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open stdin\n", progname);
+ exit(EXIT_FAILURE);
+ }
+#else
+ infile = stdin;
+#endif
+ }
+
+ /* Open the output file. */
+#ifdef TWO_FILE_COMMANDLINE
+ /* Must have explicit output file name */
+ if (argn != argc-2) {
+ fprintf(stderr, "%s: must name one input and one output file\n",
+ progname);
+ usage();
+ }
+ if ((outfile = fopen(argv[argn+1], WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open %s\n", progname, argv[argn+1]);
+ exit(EXIT_FAILURE);
+ }
+#else
+ /* Unix style: expect zero or one file name */
+ if (argn < argc-1) {
+ fprintf(stderr, "%s: only one input file\n", progname);
+ usage();
+ }
+ /* default output file is stdout */
+#ifdef USE_SETMODE /* need to hack file mode? */
+ setmode(fileno(stdout), O_BINARY);
+#endif
+#ifdef USE_FDOPEN /* need to re-open in binary mode? */
+ if ((outfile = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) {
+ fprintf(stderr, "%s: can't open stdout\n", progname);
+ exit(EXIT_FAILURE);
+ }
+#else
+ outfile = stdout;
+#endif
+#endif /* TWO_FILE_COMMANDLINE */
+
+ /* Collect comment text from comment_file or stdin, if necessary */
+ if (comment_arg == NULL) {
+ FILE * src_file;
+ int c;
+
+ comment_arg = (char *) malloc((size_t) MAX_COM_LENGTH);
+ if (comment_arg == NULL)
+ ERREXIT("Insufficient memory");
+ comment_length = 0;
+ src_file = (comment_file != NULL ? comment_file : stdin);
+ while ((c = getc(src_file)) != EOF) {
+ if (comment_length >= (unsigned int) MAX_COM_LENGTH) {
+ fprintf(stderr, "Comment text may not exceed %u bytes\n",
+ (unsigned int) MAX_COM_LENGTH);
+ exit(EXIT_FAILURE);
+ }
+ comment_arg[comment_length++] = (char) c;
+ }
+ if (comment_file != NULL)
+ fclose(comment_file);
+ }
+
+ /* Copy JPEG headers until SOFn marker;
+ * we will insert the new comment marker just before SOFn.
+ * This (a) causes the new comment to appear after, rather than before,
+ * existing comments; and (b) ensures that comments come after any JFIF
+ * or JFXX markers, as required by the JFIF specification.
+ */
+ marker = scan_JPEG_header(keep_COM);
+ /* Insert the new COM marker, but only if nonempty text has been supplied */
+ if (comment_length > 0) {
+ write_marker(M_COM);
+ write_2_bytes(comment_length + 2);
+ while (comment_length > 0) {
+ write_1_byte(*comment_arg++);
+ comment_length--;
+ }
+ }
+ /* Duplicate the remainder of the source file.
+ * Note that any COM markers occuring after SOF will not be touched.
+ */
+ write_marker(marker);
+ copy_rest_of_file();
+
+ /* All done. */
+ exit(EXIT_SUCCESS);
+ return 0; /* suppress no-return-value warnings */
+}
diff --git a/Source/LibJPEG/wrppm.c b/Source/LibJPEG/wrppm.c
new file mode 100644
index 0000000..68e0c85
--- /dev/null
+++ b/Source/LibJPEG/wrppm.c
@@ -0,0 +1,269 @@
+/*
+ * wrppm.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * Modified 2009 by Guido Vollbeding.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in PPM/PGM format.
+ * The extended 2-byte-per-sample raw PPM/PGM formats are supported.
+ * The PBMPLUS library is NOT required to compile this software
+ * (but it is highly useful as a set of PPM image manipulation programs).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef PPM_SUPPORTED
+
+
+/*
+ * For 12-bit JPEG data, we either downscale the values to 8 bits
+ * (to write standard byte-per-sample PPM/PGM files), or output
+ * nonstandard word-per-sample PPM/PGM files. Downscaling is done
+ * if PPM_NORAWWORD is defined (this can be done in the Makefile
+ * or in jconfig.h).
+ * (When the core library supports data precision reduction, a cleaner
+ * implementation will be to ask for that instead.)
+ */
+
+#if BITS_IN_JSAMPLE == 8
+#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) (v)
+#define BYTESPERSAMPLE 1
+#define PPM_MAXVAL 255
+#else
+#ifdef PPM_NORAWWORD
+#define PUTPPMSAMPLE(ptr,v) *ptr++ = (char) ((v) >> (BITS_IN_JSAMPLE-8))
+#define BYTESPERSAMPLE 1
+#define PPM_MAXVAL 255
+#else
+/* The word-per-sample format always puts the MSB first. */
+#define PUTPPMSAMPLE(ptr,v) \
+ { register int val_ = v; \
+ *ptr++ = (char) ((val_ >> 8) & 0xFF); \
+ *ptr++ = (char) (val_ & 0xFF); \
+ }
+#define BYTESPERSAMPLE 2
+#define PPM_MAXVAL ((1<<BITS_IN_JSAMPLE)-1)
+#endif
+#endif
+
+
+/*
+ * When JSAMPLE is the same size as char, we can just fwrite() the
+ * decompressed data to the PPM or PGM file. On PCs, in order to make this
+ * work the output buffer must be allocated in near data space, because we are
+ * assuming small-data memory model wherein fwrite() can't reach far memory.
+ * If you need to process very wide images on a PC, you might have to compile
+ * in large-memory model, or else replace fwrite() with a putc() loop ---
+ * which will be much slower.
+ */
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ /* Usually these two pointers point to the same place: */
+ char *iobuffer; /* fwrite's I/O buffer */
+ JSAMPROW pixrow; /* decompressor output buffer */
+ size_t buffer_width; /* width of I/O buffer */
+ JDIMENSION samples_per_row; /* JSAMPLEs per output row */
+} ppm_dest_struct;
+
+typedef ppm_dest_struct * ppm_dest_ptr;
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ *
+ * put_pixel_rows handles the "normal" 8-bit case where the decompressor
+ * output buffer is physically the same as the fwrite buffer.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * This code is used when we have to copy the data and apply a pixel
+ * format translation. Typically this only happens in 12-bit mode.
+ */
+
+METHODDEF(void)
+copy_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register JSAMPROW ptr;
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = dest->samples_per_row; col > 0; col--) {
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(*ptr++));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Write some pixel data when color quantization is in effect.
+ * We have to demap the color index values to straight data.
+ */
+
+METHODDEF(void)
+put_demapped_rgb (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register int pixval;
+ register JSAMPROW ptr;
+ register JSAMPROW color_map0 = cinfo->colormap[0];
+ register JSAMPROW color_map1 = cinfo->colormap[1];
+ register JSAMPROW color_map2 = cinfo->colormap[2];
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ pixval = GETJSAMPLE(*ptr++);
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map0[pixval]));
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map1[pixval]));
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map2[pixval]));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+METHODDEF(void)
+put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+ register char * bufferptr;
+ register JSAMPROW ptr;
+ register JSAMPROW color_map = cinfo->colormap[0];
+ register JDIMENSION col;
+
+ ptr = dest->pub.buffer[0];
+ bufferptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ PUTPPMSAMPLE(bufferptr, GETJSAMPLE(color_map[GETJSAMPLE(*ptr++)]));
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ ppm_dest_ptr dest = (ppm_dest_ptr) dinfo;
+
+ /* Emit file header */
+ switch (cinfo->out_color_space) {
+ case JCS_GRAYSCALE:
+ /* emit header for raw PGM format */
+ fprintf(dest->pub.output_file, "P5\n%ld %ld\n%d\n",
+ (long) cinfo->output_width, (long) cinfo->output_height,
+ PPM_MAXVAL);
+ break;
+ case JCS_RGB:
+ /* emit header for raw PPM format */
+ fprintf(dest->pub.output_file, "P6\n%ld %ld\n%d\n",
+ (long) cinfo->output_width, (long) cinfo->output_height,
+ PPM_MAXVAL);
+ break;
+ default:
+ ERREXIT(cinfo, JERR_PPM_COLORSPACE);
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_ppm (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* Make sure we wrote the output file OK */
+ fflush(dinfo->output_file);
+ if (ferror(dinfo->output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for PPM format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_ppm (j_decompress_ptr cinfo)
+{
+ ppm_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (ppm_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(ppm_dest_struct));
+ dest->pub.start_output = start_output_ppm;
+ dest->pub.finish_output = finish_output_ppm;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Create physical I/O buffer. Note we make this near on a PC. */
+ dest->samples_per_row = cinfo->output_width * cinfo->out_color_components;
+ dest->buffer_width = dest->samples_per_row * (BYTESPERSAMPLE * SIZEOF(char));
+ dest->iobuffer = (char *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width);
+
+ if (cinfo->quantize_colors || BITS_IN_JSAMPLE != 8 ||
+ SIZEOF(JSAMPLE) != SIZEOF(char)) {
+ /* When quantizing, we need an output buffer for colormap indexes
+ * that's separate from the physical I/O buffer. We also need a
+ * separate buffer if pixel format translation must take place.
+ */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width * cinfo->output_components, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+ if (! cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = copy_pixel_rows;
+ else if (cinfo->out_color_space == JCS_GRAYSCALE)
+ dest->pub.put_pixel_rows = put_demapped_gray;
+ else
+ dest->pub.put_pixel_rows = put_demapped_rgb;
+ } else {
+ /* We will fwrite() directly from decompressor output buffer. */
+ /* Synthesize a JSAMPARRAY pointer structure */
+ /* Cast here implies near->far pointer conversion on PCs */
+ dest->pixrow = (JSAMPROW) dest->iobuffer;
+ dest->pub.buffer = & dest->pixrow;
+ dest->pub.buffer_height = 1;
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ }
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* PPM_SUPPORTED */
diff --git a/Source/LibJPEG/wrrle.c b/Source/LibJPEG/wrrle.c
new file mode 100644
index 0000000..a4e7337
--- /dev/null
+++ b/Source/LibJPEG/wrrle.c
@@ -0,0 +1,305 @@
+/*
+ * wrrle.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in RLE format.
+ * The Utah Raster Toolkit library is required (version 3.1 or later).
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * Based on code contributed by Mike Lijewski,
+ * with updates from Robert Hutchinson.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef RLE_SUPPORTED
+
+/* rle.h is provided by the Utah Raster Toolkit. */
+
+#include <rle.h>
+
+/*
+ * We assume that JSAMPLE has the same representation as rle_pixel,
+ * to wit, "unsigned char". Hence we can't cope with 12- or 16-bit samples.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+
+/*
+ * Since RLE stores scanlines bottom-to-top, we have to invert the image
+ * from JPEG's top-to-bottom order. To do this, we save the outgoing data
+ * in a virtual array during put_pixel_row calls, then actually emit the
+ * RLE file during finish_output.
+ */
+
+
+/*
+ * For now, if we emit an RLE color map then it is always 256 entries long,
+ * though not all of the entries need be used.
+ */
+
+#define CMAPBITS 8
+#define CMAPLENGTH (1<<(CMAPBITS))
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ jvirt_sarray_ptr image; /* virtual array to store the output image */
+ rle_map *colormap; /* RLE-style color map, or NULL if none */
+ rle_pixel **rle_row; /* To pass rows to rle_putrow() */
+
+} rle_dest_struct;
+
+typedef rle_dest_struct * rle_dest_ptr;
+
+/* Forward declarations */
+METHODDEF(void) rle_put_pixel_rows
+ JPP((j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied));
+
+
+/*
+ * Write the file header.
+ *
+ * In this module it's easier to wait till finish_output to write anything.
+ */
+
+METHODDEF(void)
+start_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+ size_t cmapsize;
+ int i, ci;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /*
+ * Make sure the image can be stored in RLE format.
+ *
+ * - RLE stores image dimensions as *signed* 16 bit integers. JPEG
+ * uses unsigned, so we have to check the width.
+ *
+ * - Colorspace is expected to be grayscale or RGB.
+ *
+ * - The number of channels (components) is expected to be 1 (grayscale/
+ * pseudocolor) or 3 (truecolor/directcolor).
+ * (could be 2 or 4 if using an alpha channel, but we aren't)
+ */
+
+ if (cinfo->output_width > 32767 || cinfo->output_height > 32767)
+ ERREXIT2(cinfo, JERR_RLE_DIMENSIONS, cinfo->output_width,
+ cinfo->output_height);
+
+ if (cinfo->out_color_space != JCS_GRAYSCALE &&
+ cinfo->out_color_space != JCS_RGB)
+ ERREXIT(cinfo, JERR_RLE_COLORSPACE);
+
+ if (cinfo->output_components != 1 && cinfo->output_components != 3)
+ ERREXIT1(cinfo, JERR_RLE_TOOMANYCHANNELS, cinfo->num_components);
+
+ /* Convert colormap, if any, to RLE format. */
+
+ dest->colormap = NULL;
+
+ if (cinfo->quantize_colors) {
+ /* Allocate storage for RLE-style cmap, zero any extra entries */
+ cmapsize = cinfo->out_color_components * CMAPLENGTH * SIZEOF(rle_map);
+ dest->colormap = (rle_map *) (*cinfo->mem->alloc_small)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, cmapsize);
+ MEMZERO(dest->colormap, cmapsize);
+
+ /* Save away data in RLE format --- note 8-bit left shift! */
+ /* Shifting would need adjustment for JSAMPLEs wider than 8 bits. */
+ for (ci = 0; ci < cinfo->out_color_components; ci++) {
+ for (i = 0; i < cinfo->actual_number_of_colors; i++) {
+ dest->colormap[ci * CMAPLENGTH + i] =
+ GETJSAMPLE(cinfo->colormap[ci][i]) << 8;
+ }
+ }
+ }
+
+ /* Set the output buffer to the first row */
+ dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image, (JDIMENSION) 0, (JDIMENSION) 1, TRUE);
+ dest->pub.buffer_height = 1;
+
+ dest->pub.put_pixel_rows = rle_put_pixel_rows;
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->total_extra_passes++; /* count file writing as separate pass */
+ }
+#endif
+}
+
+
+/*
+ * Write some pixel data.
+ *
+ * This routine just saves the data away in a virtual array.
+ */
+
+METHODDEF(void)
+rle_put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+
+ if (cinfo->output_scanline < cinfo->output_height) {
+ dest->pub.buffer = (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ cinfo->output_scanline, (JDIMENSION) 1, TRUE);
+ }
+}
+
+/*
+ * Finish up at the end of the file.
+ *
+ * Here is where we really output the RLE file.
+ */
+
+METHODDEF(void)
+finish_output_rle (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ rle_dest_ptr dest = (rle_dest_ptr) dinfo;
+ rle_hdr header; /* Output file information */
+ rle_pixel **rle_row, *red, *green, *blue;
+ JSAMPROW output_row;
+ char cmapcomment[80];
+ int row, col;
+ int ci;
+#ifdef PROGRESS_REPORT
+ cd_progress_ptr progress = (cd_progress_ptr) cinfo->progress;
+#endif
+
+ /* Initialize the header info */
+ header = *rle_hdr_init(NULL);
+ header.rle_file = dest->pub.output_file;
+ header.xmin = 0;
+ header.xmax = cinfo->output_width - 1;
+ header.ymin = 0;
+ header.ymax = cinfo->output_height - 1;
+ header.alpha = 0;
+ header.ncolors = cinfo->output_components;
+ for (ci = 0; ci < cinfo->output_components; ci++) {
+ RLE_SET_BIT(header, ci);
+ }
+ if (cinfo->quantize_colors) {
+ header.ncmap = cinfo->out_color_components;
+ header.cmaplen = CMAPBITS;
+ header.cmap = dest->colormap;
+ /* Add a comment to the output image with the true colormap length. */
+ sprintf(cmapcomment, "color_map_length=%d", cinfo->actual_number_of_colors);
+ rle_putcom(cmapcomment, &header);
+ }
+
+ /* Emit the RLE header and color map (if any) */
+ rle_put_setup(&header);
+
+ /* Now output the RLE data from our virtual array.
+ * We assume here that (a) rle_pixel is represented the same as JSAMPLE,
+ * and (b) we are not on a machine where FAR pointers differ from regular.
+ */
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_limit = cinfo->output_height;
+ progress->pub.pass_counter = 0;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+
+ if (cinfo->output_components == 1) {
+ for (row = cinfo->output_height-1; row >= 0; row--) {
+ rle_row = (rle_pixel **) (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ (JDIMENSION) row, (JDIMENSION) 1, FALSE);
+ rle_putrow(rle_row, (int) cinfo->output_width, &header);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ } else {
+ for (row = cinfo->output_height-1; row >= 0; row--) {
+ rle_row = (rle_pixel **) dest->rle_row;
+ output_row = * (*cinfo->mem->access_virt_sarray)
+ ((j_common_ptr) cinfo, dest->image,
+ (JDIMENSION) row, (JDIMENSION) 1, FALSE);
+ red = rle_row[0];
+ green = rle_row[1];
+ blue = rle_row[2];
+ for (col = cinfo->output_width; col > 0; col--) {
+ *red++ = GETJSAMPLE(*output_row++);
+ *green++ = GETJSAMPLE(*output_row++);
+ *blue++ = GETJSAMPLE(*output_row++);
+ }
+ rle_putrow(rle_row, (int) cinfo->output_width, &header);
+#ifdef PROGRESS_REPORT
+ if (progress != NULL) {
+ progress->pub.pass_counter++;
+ (*progress->pub.progress_monitor) ((j_common_ptr) cinfo);
+ }
+#endif
+ }
+ }
+
+#ifdef PROGRESS_REPORT
+ if (progress != NULL)
+ progress->completed_extra_passes++;
+#endif
+
+ /* Emit file trailer */
+ rle_puteof(&header);
+ fflush(dest->pub.output_file);
+ if (ferror(dest->pub.output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for RLE format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_rle (j_decompress_ptr cinfo)
+{
+ rle_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (rle_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(rle_dest_struct));
+ dest->pub.start_output = start_output_rle;
+ dest->pub.finish_output = finish_output_rle;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Allocate a work array for output to the RLE library. */
+ dest->rle_row = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ cinfo->output_width, (JDIMENSION) cinfo->output_components);
+
+ /* Allocate a virtual array to hold the image. */
+ dest->image = (*cinfo->mem->request_virt_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE,
+ (JDIMENSION) (cinfo->output_width * cinfo->output_components),
+ cinfo->output_height, (JDIMENSION) 1);
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* RLE_SUPPORTED */
diff --git a/Source/LibJPEG/wrtarga.c b/Source/LibJPEG/wrtarga.c
new file mode 100644
index 0000000..cf104d2
--- /dev/null
+++ b/Source/LibJPEG/wrtarga.c
@@ -0,0 +1,253 @@
+/*
+ * wrtarga.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * This file contains routines to write output images in Targa format.
+ *
+ * These routines may need modification for non-Unix environments or
+ * specialized applications. As they stand, they assume output to
+ * an ordinary stdio stream.
+ *
+ * Based on code contributed by Lee Daniel Crocker.
+ */
+
+#include "cdjpeg.h" /* Common decls for cjpeg/djpeg applications */
+
+#ifdef TARGA_SUPPORTED
+
+
+/*
+ * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
+ * This is not yet implemented.
+ */
+
+#if BITS_IN_JSAMPLE != 8
+ Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
+#endif
+
+/*
+ * The output buffer needs to be writable by fwrite(). On PCs, we must
+ * allocate the buffer in near data space, because we are assuming small-data
+ * memory model, wherein fwrite() can't reach far memory. If you need to
+ * process very wide images on a PC, you might have to compile in large-memory
+ * model, or else replace fwrite() with a putc() loop --- which will be much
+ * slower.
+ */
+
+
+/* Private version of data destination object */
+
+typedef struct {
+ struct djpeg_dest_struct pub; /* public fields */
+
+ char *iobuffer; /* physical I/O buffer */
+ JDIMENSION buffer_width; /* width of one row */
+} tga_dest_struct;
+
+typedef tga_dest_struct * tga_dest_ptr;
+
+
+LOCAL(void)
+write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
+/* Create and write a Targa header */
+{
+ char targaheader[18];
+
+ /* Set unused fields of header to 0 */
+ MEMZERO(targaheader, SIZEOF(targaheader));
+
+ if (num_colors > 0) {
+ targaheader[1] = 1; /* color map type 1 */
+ targaheader[5] = (char) (num_colors & 0xFF);
+ targaheader[6] = (char) (num_colors >> 8);
+ targaheader[7] = 24; /* 24 bits per cmap entry */
+ }
+
+ targaheader[12] = (char) (cinfo->output_width & 0xFF);
+ targaheader[13] = (char) (cinfo->output_width >> 8);
+ targaheader[14] = (char) (cinfo->output_height & 0xFF);
+ targaheader[15] = (char) (cinfo->output_height >> 8);
+ targaheader[17] = 0x20; /* Top-down, non-interlaced */
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ targaheader[2] = 3; /* image type = uncompressed gray-scale */
+ targaheader[16] = 8; /* bits per pixel */
+ } else { /* must be RGB */
+ if (num_colors > 0) {
+ targaheader[2] = 1; /* image type = colormapped RGB */
+ targaheader[16] = 8;
+ } else {
+ targaheader[2] = 2; /* image type = uncompressed RGB */
+ targaheader[16] = 24;
+ }
+ }
+
+ if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * Write some pixel data.
+ * In this module rows_supplied will always be 1.
+ */
+
+METHODDEF(void)
+put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* used for unquantized full-color output */
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
+ outptr[1] = (char) GETJSAMPLE(inptr[1]);
+ outptr[2] = (char) GETJSAMPLE(inptr[0]);
+ inptr += 3, outptr += 3;
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+METHODDEF(void)
+put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+/* used for grayscale OR quantized color output */
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = (char) GETJSAMPLE(*inptr++);
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Write some demapped pixel data when color quantization is in effect.
+ * For Targa, this is only applied to grayscale data.
+ */
+
+METHODDEF(void)
+put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
+ JDIMENSION rows_supplied)
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ register JSAMPROW inptr;
+ register char * outptr;
+ register JSAMPROW color_map0 = cinfo->colormap[0];
+ register JDIMENSION col;
+
+ inptr = dest->pub.buffer[0];
+ outptr = dest->iobuffer;
+ for (col = cinfo->output_width; col > 0; col--) {
+ *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
+ }
+ (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
+}
+
+
+/*
+ * Startup: write the file header.
+ */
+
+METHODDEF(void)
+start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ tga_dest_ptr dest = (tga_dest_ptr) dinfo;
+ int num_colors, i;
+ FILE *outfile;
+
+ if (cinfo->out_color_space == JCS_GRAYSCALE) {
+ /* Targa doesn't have a mapped grayscale format, so we will */
+ /* demap quantized gray output. Never emit a colormap. */
+ write_header(cinfo, dinfo, 0);
+ if (cinfo->quantize_colors)
+ dest->pub.put_pixel_rows = put_demapped_gray;
+ else
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else if (cinfo->out_color_space == JCS_RGB) {
+ if (cinfo->quantize_colors) {
+ /* We only support 8-bit colormap indexes, so only 256 colors */
+ num_colors = cinfo->actual_number_of_colors;
+ if (num_colors > 256)
+ ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
+ write_header(cinfo, dinfo, num_colors);
+ /* Write the colormap. Note Targa uses BGR byte order */
+ outfile = dest->pub.output_file;
+ for (i = 0; i < num_colors; i++) {
+ putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
+ putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
+ putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
+ }
+ dest->pub.put_pixel_rows = put_gray_rows;
+ } else {
+ write_header(cinfo, dinfo, 0);
+ dest->pub.put_pixel_rows = put_pixel_rows;
+ }
+ } else {
+ ERREXIT(cinfo, JERR_TGA_COLORSPACE);
+ }
+}
+
+
+/*
+ * Finish up at the end of the file.
+ */
+
+METHODDEF(void)
+finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
+{
+ /* Make sure we wrote the output file OK */
+ fflush(dinfo->output_file);
+ if (ferror(dinfo->output_file))
+ ERREXIT(cinfo, JERR_FILE_WRITE);
+}
+
+
+/*
+ * The module selection routine for Targa format output.
+ */
+
+GLOBAL(djpeg_dest_ptr)
+jinit_write_targa (j_decompress_ptr cinfo)
+{
+ tga_dest_ptr dest;
+
+ /* Create module interface object, fill in method pointers */
+ dest = (tga_dest_ptr)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ SIZEOF(tga_dest_struct));
+ dest->pub.start_output = start_output_tga;
+ dest->pub.finish_output = finish_output_tga;
+
+ /* Calculate output image dimensions so we can allocate space */
+ jpeg_calc_output_dimensions(cinfo);
+
+ /* Create I/O buffer. Note we make this near on a PC. */
+ dest->buffer_width = cinfo->output_width * cinfo->output_components;
+ dest->iobuffer = (char *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
+ (size_t) (dest->buffer_width * SIZEOF(char)));
+
+ /* Create decompressor output buffer. */
+ dest->pub.buffer = (*cinfo->mem->alloc_sarray)
+ ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
+ dest->pub.buffer_height = 1;
+
+ return (djpeg_dest_ptr) dest;
+}
+
+#endif /* TARGA_SUPPORTED */
diff --git a/Source/LibMNG/Changes b/Source/LibMNG/Changes
new file mode 100644
index 0000000..fbf2ac5
--- /dev/null
+++ b/Source/LibMNG/Changes
@@ -0,0 +1,1447 @@
+-----------------------------------------------------------
+
+1.0.10 (Jul 13th 2007)
+----------------------
+
+in short:
+
+intermediate CVS
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed some compiler-warnings
+- fixed display routines called twice for FULL_MNG support in mozlibmngconf.h
+- standard windows dll upgraded to zlib 1.2.3
+- fixed problem with CLON object during readdisplay() (thanks Winfried!)
+- added typecast to appease the compiler (G R-P)
+- added more SKIPCHUNK conditionals (G R-P)
+- added MORE MNG_NO_1_2_4BIT_SUPPORT (G R-P)
+- added provisional support for anIM(mpNG) proposal
+- added provisional support for ANG proposal
+
+samples:
+- xmngview upgraded to 0.6 (thanks Winfried!)
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.9 (jan 30th 2005)
+---------------------
+
+in short:
+
+New optimizations save over 20KB on footprint.
+Also a few bugfixes and several patches.
+
+Thanks to those sending in their additions and for testing!
+
+To turn on the optimizations do:
+
+#DEFINE MNG_OPTIMIZE_CHUNKINITFREE
+#DEFINE MNG_OPTIMIZE_OBJCLEANUP
+#DEFINE MNG_OPTIMIZE_CHUNKASSIGN
+#DEFINE MNG_OPTIMIZE_CHUNKREADER
+
+(eg. they're not on by default (yet) !)
+
+-------------------
+
+bugfixes:
+- fixed chunk pushing mechanism
+- fixed bug in writing sBIT for indexed color
+- fixed PPLT getchunk/putchunk routines
+- fixed MNG_NO_1_2_4BIT_SUPPORT for TBBN1G04.PNG
+- cleaned up macro-invocations (thanks to D. Airlie)
+
+core:
+- added more SKIPCHUNK conditionals
+- replaced MNG_TWEAK_LARGE_FILES with permanent solution
+- improved handling of cheap transparency when 16-bit support is disabled
+- added some MNG_SUPPORT_WRITE conditionals
+- added function to retrieve current FRAM delay
+- added MNG_NO_1_2_4BIT_SUPPORT
+- added bgr565_a8 canvas-style (thanks to J. Elvander)
+- standard windows dll upgraded to zlib 1.2.2
+- added LITTLEENDIAN/BIGENDIAN fixtures (thanks J.Stiles)
+- inclusion of zlib/lcms/ijgsrc6b with <> instead of ""
+- added conditional MNG_OPTIMIZE_CHUNKINITFREE
+- added conditional MNG_OPTIMIZE_OBJCLEANUP
+- added conditional MNG_OPTIMIZE_CHUNKASSIGN
+- added conditional MNG_OPTIMIZE_CHUNKREADER
+- fixed problem with global PLTE/tRNS
+
+samples:
+
+contrib:
+
+doc:
+- patched jng & mng manual pages (Thanks Peter Breitenlohner)
+
+makefiles:
+
+autoconf:
+- patched makefile.am & configure.in (Thanks Peter Breitenlohner)
+
+-----------------------------------------------------------
+
+1.0.8 (aug 5th 2004)
+--------------------
+
+in short:
+
+added special data-pushing mechanisms and a few other tid-bits
+
+-------------------
+
+bugfixes:
+- fixed problem with PAST usage where source > dest
+
+core:
+- added missing get-/put-chunk-jdaa
+- added CRC existence & checking flags
+- added data-push mechanisms for specialized decoders
+- some speed optimizations (thanks to John Stiles)
+- defend against using undefined closestream function
+- defend against using undefined openstream function
+- added check for extreme chunk-lengths
+- change worst-case iAlphadepth to 1 for standalone PNGs
+- added support for 3+byte pixelsize for JPEG's
+- added conditional to allow easier writing of large MNG's
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.7 (March 21st 2004)
+-----------------------
+
+in short:
+
+A bunch of new canvas-styles, some bug-fixes, upgraded to latest zlib/lcms
+and yet more work to please the Mozilla crowd.
+Releasing beta's doesn't seem very responsive, and this one's hardly changed
+much anyway. I just wanted to bump to a regular version for Mozilla
+re-integration.
+
+-------------------
+
+bugfixes:
+- fixed inclusion of IJNG chunk for non-JNG use (J.S)
+- fixed bug in chunk-storage of SHOW chunk (where from == to)
+- fixed bug in promote_g8_g8 with 16bit support off
+
+core:
+- added CANVAS_RGB565 and CANVAS_BGR565 (big thanx to Raphael Assenat!!)
+- added CANVAS_RGBA565 and CANVAS_BGRA565 ( -- ditto -- )
+- upgraded to zlib 1.2.1
+- upgraded to lcms 1.11
+- added premultiplied alpha canvas' for RGBA, ARGB, ABGR (thx to John Stiles)
+- more optimizations with 16bit support off
+- put conditionals around openstream/closestream callbacks.
+- fixed typo (MNG_SKIPCHUNK_SAVE -> MNG_SKIPCHUNK_nEED)
+- fixed some 64-bit platform compiler warnings
+
+samples:
+
+contrib:
+- fixed mngtree sample (Raphael)
+- added 5-6-5 canvas to SDL sample (Raphael)
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.6 (oct 19th 2003)
+---------------------
+
+in short:
+
+Final release from beta1. No feedback is good feedback I presume,
+so here's 1.0.6-final!
+
+
+-------------------
+
+bugfixes:
+
+core:
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.6-beta1 (sep 14th 2003)
+---------------------------
+
+in short:
+
+further footprint-reductions
+removing email-addresses
+
+1.0.6 (final) will be out shortly
+
+-------------------
+
+bugfixes:
+
+core:
+- added support for reducing the footprint of libmng by macros that optionally
+ skip unused chunks, remove 16-bit sample support, remove Delta support, and
+ remove JNG support, to accomodate Mozilla/Firebird.
+- further optional removal of unused functions
+- added MNG_NO_SUPPORT_FUNCQUERY conditional
+- added iPNGdepth member to pData structure
+- added conditionals around MAGN chunk support
+- added conditionals around non-VLC chunk support
+- added conditionals around "mng_display_go*" and other unused functions
+- added more conditionals around "promote" functions
+- removed email references as appropriate
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.6-alpha1 (aug 2nd 2003)
+---------------------------
+
+in short:
+
+This is mostly in the light of footprint-reduction to please the Mozilla
+crew with a leaner and meaner libmng. See bug 18574 if you're interested:
+http://bugzilla.mozilla.org/show_bug.cgi?id=18574
+
+-------------------
+
+bugfixes:
+- B719420 - fixed several MNG_APP_CMS problems
+
+core:
+- removed some compiler-warnings
+- hiding 12-bit JPEG stuff
+- fixed problem with infinite loops during readdisplay()
+- added size-optimiation COMPOSE routine usage
+- added conditionals around canvas update routines
+- added MNG_SKIPCHUNK_cHNK footprint optimizations
+- added conditionals around some JNG-supporting code
+- added conditionals around 16-bit supporting code
+- combined init functions into one function
+- replaced nested switches with simple init setup function
+- added conditionals zlib and jpeg property accessors
+- added size-optimization DIV255B8 routine usage
+- added conditionals around 8-bit magn routines
+- removed conditionals around 8-bit magn routines
+- added MNG_NO_16BIT_SUPPORT and MNG_NO_DELTA_PNG conditionals
+- reversed many loops to use decrementing counter
+- converted some switches to array references
+- removed some redundant checks for iRawlen==0
+- optionally use zlib's crc32 function instead of local mng_update_crc
+- bugfix empty "if" statement when 16-bit code is enabled
+- restored two misplaced #else/#endif blocks
+- added conditionals around "mng_display_go*" and other unused functions
+- added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional
+- fixed duplicate for-loop
+- fixed invalid test in promote_imageobject
+- added conditionals around PAST chunk support
+- fixed "FOOTPRINT_COMPOSEIV" typo (now "FOOTPRINT_DIV")
+
+samples:
+
+contrib:
+- updated xmngview
+- added MSVC project for creating delta-MNGs: makemng (thanks Alex!)
+- added MSVC lib-file for use with the standard libmng.dll (again thanks Alex)
+
+doc:
+- updated readme.contrib
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5 (mar 1st 2003)
+--------------------
+
+in short:
+
+Only a small fix for progressive jpeg suspension problem.
+
+This is the long-awaited final release containing the new 'dynamic MNG' feature
+and bringing MNG compliance to near 100%!
+
+-------------------
+
+bugfixes:
+- B683152 - libjpeg suspension not always honored correctly
+
+core:
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5-rc3 (jan 20th 2003)
+-------------------------
+
+in short:
+
+Third release-candidate for the upcoming 1.0.5 version.
+
+Minor bug-fixes and finalizing the accepted proposal (by official vote) for
+the TERM/frame_delay changes on mng-list (nov-dec/2002).
+
+-------------------
+
+bugfixes:
+- B654627 - fixed SEGV when no gettickcount callback (thanks Adam!)
+- B664383 - fixed typo (thanks Dimitri)
+- B664911 - fixed buffer overflow during init (thanks Alex!)
+
+core:
+- finalized changes in TERM/final_delay to elected proposal (positive vote)
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5-rc2 (dec 9th 2002)
+------------------------
+
+in short:
+
+Second release-candidate for the upcoming 1.0.5 version.
+This contains fixes for a few minor details reported by the loyal testers.
+It fixes some issues with the goframe/golayer/gotime processing and related
+stuff. And it adds a way to disable playback-caching from within the MNG,
+which is very useful for streaming-MNG encoders (such as gserver!).
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed layer- & frame-counting during read()
+- changed FRAMECOUNT/LAYERCOUNT/PLAYTIME error to warning
+- fixed goframe/golayer/gotime processing
+- added support for nEED "MNG 1.1"
+- added support for nEED "CACHEOFF"; turn playback caching off for streaming MNG
+- fixed magnification bug with object 0
+- added support to get totals for frames/layers/playtime after mng_read()
+- fixed some issues in init_app_cms()
+- fixed goxxxxx() support for zero values
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5-rc1 (nov 1st 2002)
+------------------------
+
+in short:
+
+First release-candidate for the upcoming 1.0.5 version.
+This fixes a few small problems and brings the TERM/MEND processing, with
+respect to interframe_delay as per the current discussion on MNG-list,
+up-to-date with the latest proposal.
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed initialization of pIds in dISC read routine (Thanks Winfried!)
+- fixed issue in freeing evNT chunk (Thanks Winfried!)
+- fixed clipping-problem with BACK tiling (Thanks Sakura!)
+- fixed processing for multiple objects in MAGN (Thanks Sakura!)
+- fixed display of visible target of PAST operation (Thanks Sakura!)
+- modified TERM/MEND processing for max(1, TERM_delay, interframe_delay)
+
+samples:
+
+contrib:
+- fixed typo in Makefile for gtk-mng-view sample
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5-b3 (oct 15th 2002)
+------------------------
+
+in short:
+
+Fairly quick after beta2, since that introduced a couple of unfortunate
+booboo's and wasn't very workable. It also changes the standard configure
+script to build a standard shared object similar to what I intended.
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed support for condition=2 in TERM chunk
+- fixed trace-constants for PAST chunk
+- added mng_status_dynamic to supports function
+
+samples:
+
+contrib:
+
+doc:
+- small cosmetic changes in man/libmng.3
+
+makefiles:
+
+autoconf:
+- fixed configure.in to build a 'standard' SO primarily
+
+-----------------------------------------------------------
+
+1.0.5-b2 (oct 9th 2002)
+------------------------
+
+in short:
+
+Second beta for next 1.0.5 release. This addresses some minor problems
+detected during testing. It adds the proposed change to the MNG spec as
+discussed on the "mng-list" recently; eg. Adam's option 4.
+And it adds a little function to check at run-time if the lib is a beta or not.
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed chunk-storage for evNT chunk
+- fixed dropping mix of frozen/unfrozen objects
+- fixed problem with cloned objects marked as invalid
+- fixed problem cloning frozen object_buffers
+- fixed DISC support
+- added proposed change in handling of TERM- & interframe-delay
+- added another fix for misplaced TERM chunk
+- added check for TERM placement during create/write
+- completed support for condition=2 in TERM chunk
+- added beta version function & constant
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.5-b1 (sep 24th 2002)
+------------------------
+
+in short:
+
+First beta of a large maintenance release. This completes support of the MNG
+specification to nearly 100% (PAST, PROM, delta-images, BACK image+tile).
+It adds "dynamic" MNG and a few other neat routines as well as fixes several
+bugs reported through SourceForge or to me directly.
+
+-------------------
+
+bugfixes:
+- B575832 - library has wrong patch version number
+- B578572 - remove in 1.0.0!
+- B578940 - some functions not implemented
+- B581625 - large chunks fail with suspension reads
+- B597134 - libmng pollutes the linker namespace
+
+core:
+- added sanity check for improbable chunklengths
+- removed eMNGma hack (thanks Dimitri!)
+- unimplemented functions return an errorcode now
+- added test-option for PNG filter method 192 (= levelling)
+- added test-option for PNG filter method 193 (= no filtering)
+ (both are conditional and only for testing purposes!!!)
+- completed PROM support
+- completed delta-image support
+- completed MAGN support (16-bit functions)
+- added HLAPI function to copy a chunk from a read MNG to a newly created MNG
+- added option for soft-handling of errors (only for repair software!!!)
+- fixed some routine inclusion/exclusion for undefined conditionals
+- pre-fixed all internal routines with mng_
+- added symbol MNG_LOCAL (= static) to really local functions
+- fixed reading of FRAM with just frame_mode and name
+- fixed read/write of MAGN chunk
+- added event handling for dynamic MNG
+- added 'supports' call to check function availability
+- fixed copyright notice in the headers of all libmng modules
+- fixed LOOP iteration=0 special case
+- re-compiled standard Windows dll with lcms-1.0.9
+- added warning for too much IDAT data
+- warnings are ignored by default now
+- misplaced TERM is now treated as warning
+- fixed color-correction for restore-background handling
+- optimized restore-background for bKGD cases
+- cleaned up some old stuff
+- completed support for BACK image & tiling
+- completed support for PAST
+- added bgrx8 canvas (filler byte)
+- fixed reset_object_detail to clear old buffer
+- added in-memory color-correction of abstract images
+- added compose over/under routines for PAST processing
+- added flip & tile routines for PAST processing
+
+samples:
+- Added new BCB sample for fixing invalid JASC Animation Shop files
+ (shows new copy_chunks function; use of MNG_SOFTERRORS & static linking)
+
+contrib:
+- added xmngview by Winfried Szukalski (Vielen dank!)
+- Updated the Delphi mngview sample to handle dynamic MNGs
+- Added Kylix example (simplified port of the Delphi mngview sample)
+
+doc:
+- added diff to add MNG&JNG to a systems 'magic' file (Thanks Winfried)
+- fixed docs about using mng_display_resume after display_reset
+ (should read to use mng_display!)
+
+makefiles:
+- added makefile to build a libmng.dll for MingW
+ (makefile.mingwdll - thanks to Frank Richter!)
+
+autoconf:
+- fixing libtool version-number to be in line with what it should be
+
+-----------------------------------------------------------
+
+1.0.4 (Jun 23rd 2002)
+---------------------
+
+in short:
+
+Just some small fixes
+Standard dll now compiled with zlib 1.1.4 and lcms 1.0.8
+
+-------------------
+
+bugfixes:
+- B495442 - invalid returnvalue in mng_get_suspensionmode
+- B495443 - incorrect suspend check in read_databuffer
+- B526138 - returned IJGSRC6B calling convention to default for MSVC
+- B558212 - off by one error
+- B557677 - can't find lcms.h
+
+core:
+- fixed possible compile-problem in cleanup_rowproc
+- MNG subimage alpha composite wrong for rgba8 images
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+- fixed check for lcms.h in configure.in
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.3 (Sep 18th 2001)
+---------------------
+
+in short:
+
+Small cosmetic changes. Cleaning up the contributions.
+New makefile for mingw32, and new fbcon example.
+Major thanks to Greg for helping out with the *nix stuff!
+Note that there's also a separate download for ASM programmers now.
+Check http://www.libmng.com for details (download/ports&packages page).
+
+It may be a while for the next release. I'm "off duty" for the next 8 or
+so months...
+
+Gerard
+
+-------------------
+
+bugfixes:
+- B459058 - wrong include for lcms headers
+
+core:
+- changed inclusion of lcms.h header for Linux platforms (suggested by Greg)
+- added get function for last processed BACK chunk
+
+samples:
+- replaced the gtk & sdl viewer apps with updates by Greg Roelofs
+
+contrib:
+
+doc:
+
+makefiles:
+- changed makefile.linux & makefile.unix as suggested by Greg Roelofs
+ (makefile.linux now compiles with lcms by default)
+- added makefile.mingw for mingw32 by Benoit Blanchon (thanks Mate!)
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.2 (Jul 7th 2001)
+--------------------
+
+in short:
+
+Another maintenance release with a few added extra's.
+
+-------------------
+
+bugfixes:
+- B421427 - writes wrong format in bKGD and tRNS
+- B434583 - compiler-warning if MNG_STORE_CHUNKS undefined
+
+core:
+- added optimization option for MNG-video playback
+- added processterm callback
+- added late binding errorcode (not used internally)
+- fixed memory-leak with delta-images (Thanks Michael!)
+- added option to turn off progressive refresh for large images
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.1 (May 2nd 2001)
+--------------------
+
+in short:
+
+Maintenance release.
+Fixed several memory-leaks with the help of Gregg Kelly, added/fixed some CMS
+handling, exported JPEG functions from standard DLL, and some other minor fixes.
+
+The CMS fix now makes libmng automagically work in MNG_FULL_CMS mode as a
+sRGB compliant system. YOU WILL NEED TO CHANGE THIS IF YOU ARE NOT ON AN sRGB
+COMPLIANT SYSTEM AND WANT TO USE CMS!!!!
+(look in libmng.h for the proper function-calls)
+
+-------------------
+
+bugfixes:
+
+core:
+- added MEND processing callback
+- fixed first FRAM_MODE=4 timing problem
+- added handle status-copy function (use with care)
+- exported JPEG functions from standard DLL
+- added BGRA8 canvas with premultiplied alpha (contrib by Gregg Kelly)
+- fixed problem with display_reset/display_resume (Thanks Gregg!)
+- fixed several memory-leaks (Thanks Gregg!)
+- fixed reset_rundata to drop all objects (Thanks again, Gregg!)
+- fixed problem with cms profile being created multiple times when both
+ iCCP & cHRM/gAMA are present (And again... Gregg)
+- moved mng_clear_cms to libmng_cms
+- added "default" sRGB generation (Thanks Marti!)
+
+samples:
+
+contrib:
+
+doc:
+
+makefiles:
+
+autoconf:
+
+-----------------------------------------------------------
+
+1.0.0 (Feb 6th 2001)
+--------------------
+
+in short:
+
+First public release. Finally(!)
+
+This is the 0.9.5 CVS version, which will never be released, because I feel it
+is now ready for a public release. So apart from the version-numbers here and
+there, all other changes are listed under 0.9.5.
+
+This library will work with every MNG/JNG known and available to me. Note that
+there are still parts that need to be coded, and that MNG support is around
+90-95% (JNG at 100%). It is however compliant with the latest and greatest
+MNG 1.0 specification.
+
+I hope to dedicate a bit more time this year to finish up full support and fill
+in the remaining blanks. But this is coming out of my spare time. And extra
+help is always appreciated.
+
+Please enjoy!
+
+Gerard
+
+-----------------------------------------------------------
+
+0.9.5 (no release)
+------------------
+
+in short:
+
+intermediate CVS
+
+-------------------
+
+bugfixes:
+B129681 - fixed compiler warnings SGI/Irix (thanks Dimitri)
+
+core:
+- fixed compiler-warnings Mozilla (thanks Tim)
+- fixed timing-problem with switching framing_modes
+- fixed some small compiler warnings (thanks Nikki)
+
+samples:
+
+contrib:
+- fixed library-paths for MSVC DLL project (thanks Chad)
+
+doc:
+
+makefiles:
+- added makefile for DJGPP (thanks Silvio)
+
+autoconf:
+
+-----------------------------------------------------------
+
+0.9.4 (Jan 19th 2001)
+----------------------
+
+in short:
+
+Now that the MNG spec is at 1.0, this should be the last beta. There's a few
+small changes to make it inline with the spec, and a couple of bug-fixes.
+This is a serious release-candidate for libmng-1.0!!
+Please... test test test test!!
+
+-------------------
+
+bugfixes:
+B123314 - fixed number of TERM related problems
+B123322 - fixed unwanted repetition in mng_readdisplay()
+B123443 - fixed by Ralph
+B124910 - fixed definition for WIN32_LEAN_AND_MEAN (thanks Chad)
+B125750 - fixed by Ralph
+B125756 - fixed mixup of data- & function-pointers (thanks Dimitri)
+B127517 - changed inclusion of the lcms header file for non-windows platforms
+
+core:
+- version numbers
+- fixed possible loop in display_resume() (Thanks Vova!)
+- fixed unwanted repetition in mng_readdisplay()
+- changed inclusion of the lcms header file for non-windows platforms
+- changed IHDR filter_method check for PNGs
+- moved restore of object 0 to libmng_display
+- added restore of object 0 to TERM processing (B123314)
+- fixed TERM delay processing (B123314)
+- fixed TERM end processing when count = 0 (B123314)
+- changed callback convention for MSVC (Thanks Chad)
+- fixed mixup of data- & function-pointers (thanks Dimitri)
+- added support for "nEED MNG-1.0"
+- added errorcode for MAGN methods
+- added errorchecking for MAGN methods
+- removed "old" MAGN methods 3 & 4
+- added "new" MAGN methods 3, 4 & 5
+- removed test filter-methods 1 & 65
+- set default level-set for filtertype=64 to all zeroes
+
+samples:
+
+contrib:
+- added GTK mng-view example by Vova Babin
+- added MSVC MNGview sample by Nikolaus Brennig
+- updated Jason Summer's mngplg to version 0.9.2
+ (that's mngplg-0.9.2 based on libmng-0.9.3 !!!)
+- rearranged contrib directory slightly
+- added MSVC project to build libmng.dll by Chad Austin
+
+doc:
+- added README.dll
+- added README.config
+
+makefiles:
+- added a makefile for MS Visual C++ (Thanks to Atsushi Matsuda)
+
+autoconf:
+- fixed configure.in for lcms (FreeBSD port by Mikhail Teterin)
+- by default configure includes CMS support if lcms is present
+
+-----------------------------------------------------------
+
+0.9.3 (October 29th 2000)
+-------------------------
+
+in short:
+
+Another beta release. The number of changes in the MNG specification have
+resulted in a lot of new code and some changed code. At the same time I saw
+no need to withhold some new functionality as it was pretty clear there was
+going to be another beta-round. If things go well, I'm going to try to release
+libmng 1.0.0 very shortly after this one.
+
+Many thanks to a lot of people for helping out, sending contributions, making
+suggestions and testing this little baby. This would get nowhere without YOU!!!
+
+- fixed bug 111300/117103
+- added workaround for faulty PhotoShop iCCP chunk
+- added MAGN/JDAA chunks
+- added support for new filter_types
+- added PNG/MNG spec version indicators
+- added BCB mngview contribution by Andy Protano
+- added BCB mngdump; a GUI-based MNG dumping utility (Andy Protano)
+- implemented support for nEED "draft nn"
+- implemented app-defined support for bKGD for PNG images
+- removed trace-options from default SO/DLL builds (!!!)
+- raised initial maximum canvas size to 10000x10000 (!!!)
+ (an App that wants to protect from overly large images should call
+ mng_set_maxcanvassize() with appropriate values)
+- fixed other assorted stuff
+
+-------------------
+
+bugfixes:
+B111300 - fixup for improved portability
+B117103 - fixed compilation errors on *nix with lcms (thanks Ralph!)
+
+core:
+- fixed compiler-warnings from Mozilla
+- added check for simplicity-bits in MHDR
+- added workaround for faulty PhotoShop iCCP chunk
+- fixed app-supplied background restore
+- fixed TERM processing delay of 0 msecs
+- fixed write-code for zTXt & iTXt
+- fixed read-code for iTXt
+- added MAGN chunk
+- fixed sRGB precedence for gamma_only corection
+- added support for new filter_types
+- fixed problem with no refresh after TERM
+- fixed DEFI behavior
+- fixed inclusion parameters to make the external libs work together
+- added export of zlib functions from windows dll
+- fixed timing & refresh behavior for single PNG/JNG
+- removed trace-options from default SO/DLL builds (!!!)
+- fixed MAGN rounding errors (thanks Matthias!)
+- fixed small timing problem when FRAM delay = 0
+- fixed simplicity-check in compliance with draft 81/0.98a
+- fixed alpha-blending for all alpha-canvasstyles
+- added support for alpha-depth prediction
+- fixed processing of unknown critical chunks
+- removed test-MaGN
+- added PNG/MNG spec version indicators
+- implemented support for nEED
+- added support for JDAA
+- added functions to retrieve PNG/JNG specific header-info
+- added optional support for bKGD for PNG images
+- raised initial maximum canvas size to 10000x10000
+- added support for delta-JNG
+- added callback to process non-critical unknown chunks
+- fixed support for delta-images during read() / display()
+- added closestream() processing for mng_cleanup()
+- fixed delta-processing behavior
+- added storage for pixel-/alpha-sampledepth for delta's
+- implemented delayed delta-processing
+- fixed putchunk_plte() to set bEmpty parameter (thanks Ben!)
+- added errorcode for delayed delta-processing
+- added get/set for bKGD preference setting
+- added get function for interlace/progressive display
+- fixed bug in empty PLTE handling
+- fixed seperate read() & display() processing
+- fixed tRNS processing for gray-image < 8-bits
+
+samples:
+- added BCB mngview contribution by Andy Protano
+
+contrib:
+- added BCB mngdump; a GUI-based MNG dumping utility (Andy Protano)
+
+doc:
+- updated RPM spec-file by MATSUURA Takanori
+- updated README.contrib
+
+makefiles:
+- fixed some stuff in automake/autoconf/libtool
+- fixed auto* for bug B117103
+
+-----------------------------------------------------------
+
+0.9.2 (August 7th 2000)
+-----------------------
+
+in short:
+
+Third beta release! Last one???
+
+!!IMPORTANT!! All file-names are now prefixed with "libmng_" !!IMPORTANT!!
+
+Many thanks to Albert Chin-A-Young for his contribution of the
+autoconf/automake/libtool stuff and to Ralph Giles for helping me
+put it in the right places.
+
+There's a special README.autoconf so please read it!
+
+- fixed bug 110320/110546/110547/111096
+- added several status retrieval functions
+- fixed other small bugs in display processing
+- fixed number of small problems and documentation typos
+- added autoconf/automake/libtool
+- added latest MNG plugin (0.9.0) by Jason Summers
+
+-------------------
+
+bugfixes:
+B110320 - fixed GCC warning about mix-sized pointer math
+B110546 - fixed for improperly returning UNEXPECTEDEOF
+B110547 - fixed bug in interlace code
+B111096 - fixed large-buffer read-suspension
+
+core:
+- version numbers
+- fixed small bugs in display processing
+- removed Nextbackxxx fields (no longer used)
+- fixed problem with trace-functions improperly wrapped
+- put specific code in add_chunk() inside MNG_SUPPORT_WRITE wrapper
+- fixed documentation typos
+- fixed wrapping of suspension parameters
+- added status_xxxx functions
+- added trace-codes/-strings for status_xxxxx functions
+- changed file-prefixes
+- added function to set simplicity field
+- added trace-code/-string for updatemngsimplicity
+- fixed putchunk_unknown() function
+
+samples:
+
+contrib:
+- added latest MNG plugin (0.9.0) by Jason Summers
+
+doc:
+- version numbers
+- added autoconf readme
+- version numbers in RPM stuff
+
+makefiles:
+- fixed for new file-prefix
+- added autoconf/automake/libtool
+
+-----------------------------------------------------------
+
+0.9.1 (July 26th 2000)
+----------------------
+
+in short:
+
+Second beta release.
+
+Given the enormous amount of bug-reports (not ;-), this will most likely
+be one of the last betas. If things remain upright, the first public release
+(1.0.0) is fairly eminent in the weeks to come...
+
+- added SDL mng player by Ralph Giles to contributions
+- fixed timing and added internal buffering for I/O-suspension scenarios
+- added get routines for internal display-state variables (frame/layer/playtime)
+- changed read-processing for improved I/O-suspension (internal buffering)
+- fixed several problems with create- & write-support
+- added a load of documentation
+- lots of small stuff
+
+-------------------
+
+bugfixes:
+
+core:
+- fixed mandatory BACK color to be opaque
+- changed mng_display_resume to allow to be called after a suspension
+ return with MNG_NEEDMOREDATA
+- changed comments to indicate modified behavior for timer & suspension breaks
+- added variables for go_xxxx processing
+- implemented support for freeze/reset/resume & go_xxxx
+- added trace-codes/-strings for special display processing
+- added variables for improved timing support
+- added support for improved timing
+- added get routines for internal display variables
+- added get/set routines for suspensionmode variable
+- added trace-code/-string for get/set suspensionmode
+- added trace-codes/-strings for get/set display variables
+- added support for improved I/O-suspension
+- changed read-processing for improved I/O-suspension
+- added trace-code/-string for read_databuffer (I/O-suspension)
+- added suspendbuffer constants
+- changed EOF processing behavior
+- fixed TERM delay processing
+- changed pre-draft48 frame_mode=3 to frame_mode=1
+- added callbacks for SAVE/SEEK processing
+- added trace-codes/-strings for SAVE/SEEK callbacks
+- added variable for NEEDSECTIONWAIT breaks
+- added trace-codes/-strings for get/set sectionbreaks
+- added NEEDSECTIONWAIT error-code/-string
+- added macro + routine to set returncode without calling error callback
+- added trace-code/-string for special error routine
+- changed default readbuffer size from 1024 to 4200
+- added variable for freeze & reset processing
+- fixed storage of images during mng_read()
+- fixed support for mng_display() after mng_read()
+- added error cleanup processing
+- fixed support for mng_display_reset()
+- fixed suspension-buffering for 32K+ chunks
+- added function to set frame-/layer-count & playtime
+- added trace-code/-string for updatemngheader
+- added error-code/-string for updatemngheader if not a MNG
+- fixed creation-code
+- fixed writing of signature
+- fixed several chunk-writing routines
+
+samples:
+- fixed the libmng.pas module in line with libmng.h
+
+contrib:
+- added the SDL based mngplay viewer by Ralph Giles
+
+doc:
+- extended the RPM contribution by MATSUURA Takanori
+- added libmng.txt, a full description of the library and its usage
+- added man-pages for mng(5), jng(5) and libmng(3)
+
+makefiles:
+
+-----------------------------------------------------------
+
+0.9.0 (June 30th 2000)
+----------------------
+
+in short:
+
+This is the first beta!!! Yippee!!!
+
+Thanks to all the people who helped to guide me in the right direction.
+You know who you are!
+
+A special thanks to the guys with early implementations, who stood by and
+put up with my whims :-)
+
+changes over 0.5.3:
+
+- updated mngplg to 0.4.1 (the latest & greatest)
+- changed refresh parameters to 'x,y,width,height'
+
+-----------------------------------------------------------
+
+0.5.3 (never released)
+----------------------
+
+in short:
+
+This is a working version only; the next release will be 0.9.0 (first Beta!)
+
+There are a few incompatible changes with previous versions. The userdata
+variable has been changed from mng_uint32 to mng_ptr to accomodate 64-bit
+systems. For the same reason memory allocation size parameters have been
+changed to a mng_size_t type which is a typedef of size_t.
+
+Thanks to Aleks Jakulin for helping to iron out some 64-bit platform issues!
+
+- implemented the update-region parameters of the refresh callback
+- added support for most common delta-image options
+- added an animation-speed modifier
+- added an image-level parameter for the processtext callback
+- updated mngplg to 0.4.0 (supports JNG, full CMS, and other enhancements!)
+- fixed a lot of small things
+- added support for PPLT chunk
+- fixed to support 64-bit platforms
+
+-------------------
+
+bugfixes:
+
+core:
+- added processing of color-info on delta-image
+- fixed handling of empty SAVE chunk
+- fixed display of stored JNG images
+- fixed problem with BASI-IEND as object 0
+- changed the version parameters (obviously)
+- added update-region parms for refresh calback
+- added Needrefresh parameter
+- added initialization of update-region for refresh
+- added initialization of Needrefresh parameter
+- changed progressive-display processing
+- added tracecodes for tracing JPEG progression
+- added tracing of JPEG calls
+- added Deltaimmediate parm for faster delta-processing
+- added extra checks for delta-images
+- many changes to support delta-images
+- optimized some store_xxx routines
+- fixed some small things (as precaution)
+- fixed possible trouble if IEND display-processing got broken up
+- fixed nasty bug with embedded PNG after delta-image
+- added processing of PLTE & tRNS for delta-images
+- added processing of PLTE/tRNS & color-info for delta-images in the
+ ani_objects chain
+- fixed problem with color-correction for stored images
+- added get/set for speedtype to facilitate testing
+- added trace-codes & -strings for get/set speedtype
+- added speed-modifier to timing routine
+- added get-routine of imagelevel for processtext callback
+- added trace-code & -string for get imagelevel
+- added administration of imagelevel parameter
+- added support for PPLT chunk
+- added trace-codes & -strings for PPLT chunk processing
+- fixed problem with incorrect gamma-correction
+- fixed inclusion of IJG read/write code
+- fixed problem with 16-bit GA format
+- fixed problem with cheap transparency for 4-bit gray
+- fixed display_xxxx routines for interlaced images
+- added precaution against faulty iCCP chunks from PS
+- changed userdata variable to mng_ptr
+- added typedef for mng_size_t
+- changed size parameter for memory allocation to mng_size_t
+- fixed compiler-warning for non-initialized iB variable
+- changed definition for 32-bit ints (64-bit platforms)
+- changed definition for mng_handle (64-bit platforms)
+- swapped refresh parameters
+- fixed initialization routine for new mng_handle type
+- added inclusion of stdlib.h for abs()
+- fixed some 64-bit warnings
+- fixed incompatible return-types
+
+samples:
+
+contrib:
+- updated mngplg to 0.3.0 (supports JNG & full color-correction!)
+- updated mngplg to 0.4.0 (Jason is picking up the pace ;-)
+
+doc:
+- added rpm directory with rpm spec-file (contributed by MATSUURA Takanori)
+
+makefiles:
+- changed makefile.linux to reflect versionnr for shared-lib
+- changed makefile.linux to depend on mng_conf.h & mng_types.h
+
+-----------------------------------------------------------
+
+0.5.2 (June 10th 2000)
+----------------------
+
+in short:
+
+This is the third release for developers
+Another milestone since JNG is now fully supported
+The next release will most likely be numbered 0.9.0 as the first Beta!!
+
+Fixed bug 106017 & 106019
+Added many constants regarding chunk-property values
+Implemented full JNG support
+Added all the error- & trace-strings
+Added get/set routines for default ZLIB/IJG parameters
+Added a generic makefile for Unix platforms (contributed by Tim Rowley)
+Added canvasstyle for separate RGB + A canvas (eg. mozilla-style)
+Separated configuration-options into a separate file: "mng_conf.h"
+Fixed stuff for generic Unix compilation (contributed by Tim Rowley)
+Upgraded to lcms1.0.6 (now supports 16-bit endian-peculiarities)
+Added a makefile for Linux ELF & fixed some code-issues to go along with gcc
+Added support for suspended input-buffer processing
+Implemented the display-routines for RGBA/ARGB/BGRA/ABGR canvasstyles
+Implemented the application background-restore functionality
+Fixed & tested the mngtree Unix-sample (runs on Linux-RH6.2 with libmng.so)
+Upgraded mngplg to v0.2.2 (based on the latest code including JNG)
+Fixed a lot of other assorted stuff
+
+-------------------
+
+bugfixes:
+B003(106017) - fixed problem with <mem.h> being proprietary to BCB
+B004(106019) - fixed problem when MNG_SUPPORT_WRITE not defined
+
+core:
+- bumped version-numbers up to 0.5.2 (yeah, really)
+- fixed support for IJGSRC6B
+- cleaned up some code regarding mixed support-options
+- complemented constants for chunk-property values
+- fixed MNG_UINT_pHYg value
+- implemented JNG support
+- fixed problem with DEFI clipping
+- added error telltale strings & support
+- added trace telltale strings & support
+- added support for global color-chunks inside TERM/LOOP
+- added support for global PLTE,tRNS,bKGD inside TERM/LOOP
+- added default IJG compression parameters and such
+- moved init of default zlib parms to "mng_hlapi.c"
+- added init of default IJG parms
+- added support for get/set of zlib/IJG default parms
+- added tracestrings for global animation color-chunks
+- added tracestrings for get/set of default ZLIB/IJG parms
+- added tracestrings for global PLTE,tRNS,bKGD
+- added framenr/layernr/playtime to object header
+- added initialization of framenr/layernr/playtime
+- changed ani_create calls not returning object pointer
+- create ani objects always (not just inside TERM/LOOP)
+- fixed inconsistancy with freeing global iCCP profile
+- fixed minor bugs 16-bit pixel-handling
+- added object promotion routine (PROM handling)
+- added trace-codes & -strings for image-object promotion
+- added trace-codes & -strings for delta-image processing
+- added error-codes & -strings for delta-image processing
+- added support for delta-image processing
+- added ani-object routines for delta-image processing
+- added delta-image fields
+- added compression/filter/interlace fields to object-buffer for
+ delta-image processing
+- added delta-image row-processing routines
+- fixed up punctuation in several files (contributed by Tim Rowley)
+- removed useless definition in "mng_chunks.h" (contributed by Tim Rowley)
+- fixed pointer confusion in "mng_display.c" (contributed by Tim Rowley)
+- fixed inclusion for memcpy (contributed by Tim Rowley)
+- added mng_int32p (contributed by Tim Rowley)
+- added internal delta-image processing callbacks
+- separated configuration-options into "mng_conf.h"
+- changed to most likely configuration
+- added RGB8_A8 canvasstyle
+- added getalphaline callback for RGB8_A8 canvasstyle
+- fixed some makeup for Linux gcc compile
+- implemented app bkgd restore routines
+- implemented RGBA8, ARGB8, BGRA8 & ABGR8 display routines
+- added support for RGB8_A8 canvasstyle
+- added support for suspended input-buffer processing
+- added mng_read_resume HLAPI function to support read-suspension
+- fixed timer-handling to run with Mozilla (Tim Rowley)
+- fixed alpha-handling for alpha canvasstyles
+- fixed some compilation-warnings (contrib Jason Morris)
+
+samples:
+- fixed mngview(delphi) to work with the new core
+- synchronized libmng.pas(delphi) with the new libmng.h header
+- removed the error- & trace-strings from libmng.pas(delphi)
+- fixed mngtree(Unix) to compile on Linux (runs with libmng.so)
+- added makefile.linux for mngtree(Unix) (tested on RedHat6.2)
+
+contrib:
+- updated mngplg to 0.2.2 (based on latest code; supports JNG!)
+
+doc:
+- this file obviously
+- added Tim Rowley as contributing author
+- changed the examples.readme doc
+- updated the design-schematics in line with the current code
+
+makefiles:
+- changed the directory to "makefiles" to avoid name-conflicts
+- added generic Unix makefile (thanks to Tim Rowley)
+- added Linux ELF makefile (tested on RedHat6.2)
+
+-----------------------------------------------------------
+
+0.5.1 May 16th 2000
+-------------------
+
+in short:
+
+This is the second release for developers
+It's a bit of a milestone since all the chunk functionality is in place and
+functioning (read, examine, create & write)
+This version is incompatible with 0.5.0 since some of the callback prototypes
+have changed (should be the last time that happens!)
+There are a few more samples and even a real contribution!
+
+Fixed bug 105795 & 105797
+Fixed a mis-alignment in animation-timing
+Added chunk-access functions
+Finished all chunk-storage routine-bits
+Finished all chunk-write routines
+Changed the callback prototypes to allow error-reporting back to the library
+Fixed some routines to allow for callback error-reporting
+Added version-control functions & constants
+Added two functions to set display- & sRGB-profile from memory
+Moved CRC table to dynamic structure (for improved thread-safety)
+Added SAVE & SEEK save&restore functionality
+Finished the application-based CMS-callbacks
+Fixed a few BCB specifics
+Changed the Win32 DLL and samples to use __stdcall
+Did some more assorted little changes
+Added 2 BCB samples
+Added 1 Unix sample
+Added the MNG plugin by Jason Summers in the contrib section
+Changed some documents to reflect these changes
+
+-------------------
+
+bugfixes:
+B001(105795) - fixed wrong lcms call & memory-leak for gammatables
+B002(105797) - fixed problem with missing sRGB profile
+
+core:
+- changed chunk iteration function
+- added chunk access functions
+- added version control constants & functions
+- changed strict-ANSI stuff
+- added set_outputprofile2 & set_srgbprofile2
+- added empty-chunk put-routines
+- added version_dll & VERSION_DLL (for consistency)
+- added version control explanatory text & samples
+- added iteratechunk callback definition
+- improved definitions for DLL support
+- added 8-bit palette definition
+- added general array definitions
+- added MNG_NULL definition
+- changed most callback prototypes to allow the app
+ to report errors during callback processing
+- added CRC table to main structure (for thread-safety)
+- added iPLTEentries for checking hIST-length
+- changed palette definition to exported palette-type
+- removed frozen indicator
+- added create/write indicators
+- added eMNGma hack (will be removed in 1.0.0 !!!)
+- added TERM animation object pointer (easier reference)
+- added saved-data structure for SAVE/SEEK processing
+- added some errorcodes
+- added application errorcodes (used with callbacks)
+- moved chunk-access errorcodes to severity 5
+- added chunk-access function trace-codes
+- changed trace to macro for callback error-reporting
+- added save_state & restore_state trace-codes
+- put in some extra comments
+- fixed layout for sBIT, PPLT
+- changed write callback definition
+- fixed layout for PPLT again (missed deltatype ?!?)
+- cleaned up left-over teststuff in the BACK chunk routine
+- changed CRC initialization to use dynamic structure
+ (wasn't thread-safe the old way !)
+- filled in many missing sequence&length checks
+- filled in many missing chunk-store snippets
+- added checks for running animations
+- filled remaining write routines
+- fixed read_pplt with regard to deltatype
+- added callback error-reporting support
+- added pre-draft48 support (short MHDR, frame_mode, LOOP)
+- fixed chunk-storage bit in several routines
+- supplemented the SAVE & SEEK display processing
+- added init of iPLTEcount
+- changed calling-convention definition
+- changed status-handling of display-routines
+- added versioning-control routines
+- filled the write routine
+- fixed frame_delay misalignment
+- added sanity check for frozen status
+- changed display_mend to reset state to initial or SAVE
+- added save_state and restore_state for SAVE/SEEK/TERM
+ processing
+- added process_save & process_seek routines
+- changed and filled iterate-chunk function
+- added getchunk functions
+- added putchunk functions
+- added empty-chunk put-routines
+- filled application-based color-management routines
+- added creatememprofile
+- filled the deflatedata routine
+- added cleanup of saved-data (SAVE/SEEK processing)
+- moved the actual write_graphic functionality from mng_hlapi.c
+ to it's appropriate function in the mng_write.c module
+- moved standard header includes into mng_types.h
+ (stdlib/mem for mem-mngmt & math for fp gamma-calc)
+- added getimgdata & putimgdata functions
+
+samples:
+- fixed mngview(delphi) to work with the new core
+- synchronized libmng.pas(delphi) with the new libmng.h header
+- added mngtree(bcb) sample
+- added bogus(bcb) sample
+- added mngtree(unix) sample
+
+contrib:
+- added mngplg 0.1.0 / a MNG plugin for Win32 by Jason Summers
+
+doc:
+- added this changes.readme file
+- changed the samples.readme doc accordingly
+- changed the contrib.readme doc accordingly
+
+-----------------------------------------------------------
+
+0.5.0 May 1st 2000
+------------------
+
+in short:
+
+This is the first developers release.
+It's roughly about 60% done.
diff --git a/Source/LibMNG/LICENSE b/Source/LibMNG/LICENSE
new file mode 100644
index 0000000..5878e32
--- /dev/null
+++ b/Source/LibMNG/LICENSE
@@ -0,0 +1,57 @@
+/* ************************************************************************** */
+/* * * */
+/* * COPYRIGHT NOTICE: * */
+/* * * */
+/* * Copyright (c) 2000-2007 Gerard Juyn (gerard@libmng.com) * */
+/* * [You may insert additional notices after this sentence if you modify * */
+/* * this source] * */
+/* * * */
+/* * For the purposes of this copyright and license, "Contributing Authors" * */
+/* * is defined as the following set of individuals: * */
+/* * * */
+/* * Gerard Juyn * */
+/* * Glenn Randers-Pehrson * */
+/* * * */
+/* * The MNG Library is supplied "AS IS". The Contributing Authors * */
+/* * disclaim all warranties, expressed or implied, including, without * */
+/* * limitation, the warranties of merchantability and of fitness for any * */
+/* * purpose. The Contributing Authors assume no liability for direct, * */
+/* * indirect, incidental, special, exemplary, or consequential damages, * */
+/* * which may result from the use of the MNG Library, even if advised of * */
+/* * the possibility of such damage. * */
+/* * * */
+/* * Permission is hereby granted to use, copy, modify, and distribute this * */
+/* * source code, or portions hereof, for any purpose, without fee, subject * */
+/* * to the following restrictions: * */
+/* * * */
+/* * 1. The origin of this source code must not be misrepresented; * */
+/* * you must not claim that you wrote the original software. * */
+/* * * */
+/* * 2. Altered versions must be plainly marked as such and must not be * */
+/* * misrepresented as being the original source. * */
+/* * * */
+/* * 3. This Copyright notice may not be removed or altered from any source * */
+/* * or altered source distribution. * */
+/* * * */
+/* * The Contributing Authors specifically permit, without fee, and * */
+/* * encourage the use of this source code as a component to supporting * */
+/* * the MNG and JNG file format in commercial products. If you use this * */
+/* * source code in a product, acknowledgment would be highly appreciated. * */
+/* * * */
+/* ************************************************************************** */
+/* * * */
+/* * Parts of this software have been adapted from the libpng package. * */
+/* * Although this library supports all features from the PNG specification * */
+/* * (as MNG descends from it) it does not require the libpng package. * */
+/* * It does require the zlib library and optionally the IJG jpeg library, * */
+/* * and/or the "little-cms" library by Marti Maria (depending on the * */
+/* * inclusion of support for JNG and Full-Color-Management respectively. * */
+/* * * */
+/* * This library's function is primarily to read and display MNG * */
+/* * animations. It is not meant as a full-featured image-editing * */
+/* * component! It does however offer creation and editing functionality * */
+/* * at the chunk level. * */
+/* * (future modifications may include some more support for creation * */
+/* * and or editing) * */
+/* * * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/LibMNG.2003.vcproj b/Source/LibMNG/LibMNG.2003.vcproj
new file mode 100644
index 0000000..6536fb3
--- /dev/null
+++ b/Source/LibMNG/LibMNG.2003.vcproj
@@ -0,0 +1,520 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+
+<VisualStudioProject
+
+ ProjectType="Visual C++"
+
+ Version="7.10"
+
+ Name="LibMNG"
+
+ SccProjectName=""
+
+ SccLocalPath="">
+
+ <Platforms>
+
+ <Platform
+
+ Name="Win32"/>
+
+ </Platforms>
+
+ <Configurations>
+
+ <Configuration
+
+ Name="Release|Win32"
+
+ OutputDirectory=".\Release"
+
+ IntermediateDirectory=".\Release"
+
+ ConfigurationType="4"
+
+ UseOfMFC="0"
+
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+
+ CharacterSet="2">
+
+ <Tool
+
+ Name="VCCLCompilerTool"
+
+ Optimization="2"
+
+ GlobalOptimizations="TRUE"
+
+ InlineFunctionExpansion="2"
+
+ EnableIntrinsicFunctions="TRUE"
+
+ FavorSizeOrSpeed="1"
+
+ OmitFramePointers="TRUE"
+
+ OptimizeForProcessor="3"
+
+ AdditionalIncludeDirectories="..\Zlib,..\libjpeg"
+
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+
+ StringPooling="TRUE"
+
+ RuntimeLibrary="0"
+
+ BufferSecurityCheck="FALSE"
+
+ UsePrecompiledHeader="2"
+
+ PrecompiledHeaderFile=".\Release/LibMNG.pch"
+
+ AssemblerListingLocation=".\Release/"
+
+ ObjectFile=".\Release/"
+
+ ProgramDataBaseFileName=".\Release/"
+
+ WarningLevel="3"
+
+ SuppressStartupBanner="TRUE"
+
+ CompileAs="0"/>
+
+ <Tool
+
+ Name="VCCustomBuildTool"/>
+
+ <Tool
+
+ Name="VCLibrarianTool"
+
+ OutputFile=".\Release\LibMNG.lib"
+
+ SuppressStartupBanner="TRUE"/>
+
+ <Tool
+
+ Name="VCMIDLTool"/>
+
+ <Tool
+
+ Name="VCPostBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreLinkEventTool"/>
+
+ <Tool
+
+ Name="VCResourceCompilerTool"
+
+ PreprocessorDefinitions="NDEBUG"
+
+ Culture="1043"/>
+
+ <Tool
+
+ Name="VCWebServiceProxyGeneratorTool"/>
+
+ <Tool
+
+ Name="VCXMLDataGeneratorTool"/>
+
+ <Tool
+
+ Name="VCManagedWrapperGeneratorTool"/>
+
+ <Tool
+
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+
+ </Configuration>
+
+ <Configuration
+
+ Name="Debug|Win32"
+
+ OutputDirectory=".\Debug"
+
+ IntermediateDirectory=".\Debug"
+
+ ConfigurationType="4"
+
+ UseOfMFC="0"
+
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+
+ CharacterSet="2">
+
+ <Tool
+
+ Name="VCCLCompilerTool"
+
+ Optimization="0"
+
+ AdditionalIncludeDirectories="..\ZLib,..\LibJPEG"
+
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;MNG_BUILD_SO"
+
+ StringPooling="TRUE"
+
+ BasicRuntimeChecks="3"
+
+ RuntimeLibrary="1"
+
+ UsePrecompiledHeader="2"
+
+ PrecompiledHeaderFile=".\Debug/LibMNG.pch"
+
+ AssemblerListingLocation=".\Debug/"
+
+ ObjectFile=".\Debug/"
+
+ ProgramDataBaseFileName=".\Debug/"
+
+ WarningLevel="3"
+
+ SuppressStartupBanner="TRUE"
+
+ DebugInformationFormat="4"
+
+ CompileAs="0"/>
+
+ <Tool
+
+ Name="VCCustomBuildTool"/>
+
+ <Tool
+
+ Name="VCLibrarianTool"
+
+ OutputFile=".\Debug\LibMNG.lib"
+
+ SuppressStartupBanner="TRUE"/>
+
+ <Tool
+
+ Name="VCMIDLTool"/>
+
+ <Tool
+
+ Name="VCPostBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreLinkEventTool"/>
+
+ <Tool
+
+ Name="VCResourceCompilerTool"
+
+ PreprocessorDefinitions="_DEBUG"
+
+ Culture="1043"/>
+
+ <Tool
+
+ Name="VCWebServiceProxyGeneratorTool"/>
+
+ <Tool
+
+ Name="VCXMLDataGeneratorTool"/>
+
+ <Tool
+
+ Name="VCManagedWrapperGeneratorTool"/>
+
+ <Tool
+
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+
+ </Configuration>
+
+ </Configurations>
+
+ <References>
+
+ </References>
+
+ <Files>
+
+ <Filter
+
+ Name="Source Files"
+
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+
+ <File
+
+ RelativePath="libmng_callback_xs.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_descr.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_io.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_prc.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_xs.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_cms.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_display.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_dither.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_error.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_filter.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_hlapi.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_jpeg.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_object_prc.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_pixels.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_prop_xs.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_read.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_trace.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_write.c">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_zlib.c">
+
+ </File>
+
+ </Filter>
+
+ <Filter
+
+ Name="Header Files"
+
+ Filter="h;hpp;hxx;hm;inl">
+
+ <File
+
+ RelativePath="libmng.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_descr.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_io.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunk_prc.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_chunks.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_cms.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_conf.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_data.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_display.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_dither.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_error.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_filter.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_jpeg.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_memory.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_object_prc.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_objects.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_pixels.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_read.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_trace.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_types.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_write.h">
+
+ </File>
+
+ <File
+
+ RelativePath="libmng_zlib.h">
+
+ </File>
+
+ </Filter>
+
+ </Files>
+
+ <Globals>
+
+ </Globals>
+
+</VisualStudioProject>
+
diff --git a/Source/LibMNG/LibMNG.2005.vcproj b/Source/LibMNG/LibMNG.2005.vcproj
new file mode 100644
index 0000000..629d75d
--- /dev/null
+++ b/Source/LibMNG/LibMNG.2005.vcproj
@@ -0,0 +1,351 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibMNG"
+ ProjectGUID="{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+ RootNamespace="LibMNG"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\Zlib,..\libjpeg"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/LibMNG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibMNG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\ZLib,..\LibJPEG"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;MNG_BUILD_SO;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/LibMNG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibMNG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="libmng_callback_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_descr.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_io.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_prc.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_cms.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_display.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_dither.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_error.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_filter.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_hlapi.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_object_prc.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_pixels.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_prop_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_read.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_trace.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_write.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_zlib.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="libmng.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_descr.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_io.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_prc.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunks.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_cms.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_conf.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_data.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_display.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_dither.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_error.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_filter.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_jpeg.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_memory.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_object_prc.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_objects.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_pixels.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_read.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_trace.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_types.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_write.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_zlib.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibMNG/LibMNG.2008.vcproj b/Source/LibMNG/LibMNG.2008.vcproj
new file mode 100644
index 0000000..9c1d407
--- /dev/null
+++ b/Source/LibMNG/LibMNG.2008.vcproj
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibMNG"
+ ProjectGUID="{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+ RootNamespace="LibMNG"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;;..\LibJPEG"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ PrecompiledHeaderFile=".\Release/LibMNG.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;;..\LibJPEG"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ PrecompiledHeaderFile=".\Debug/LibMNG.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1043"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="libmng_callback_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_descr.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_io.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_prc.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_cms.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_display.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_dither.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_error.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_filter.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_hlapi.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_object_prc.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_pixels.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_prop_xs.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_read.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_trace.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_write.c"
+ >
+ </File>
+ <File
+ RelativePath="libmng_zlib.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="libmng.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_descr.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_io.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunk_prc.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_chunks.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_cms.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_conf.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_data.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_display.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_dither.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_error.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_filter.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_jpeg.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_memory.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_object_prc.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_objects.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_pixels.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_read.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_trace.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_types.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_write.h"
+ >
+ </File>
+ <File
+ RelativePath="libmng_zlib.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibMNG/README b/Source/LibMNG/README
new file mode 100644
index 0000000..a8e67ca
--- /dev/null
+++ b/Source/LibMNG/README
@@ -0,0 +1,36 @@
+libmng 1.0.10
+-------------
+
+Added provisional ANG and anIM support, and made some minor bugfixes.
+
+libmng 1.0.9
+------------
+
+A number of optimizations in the chunk handling and reader/writer code.
+This saves over 20KB on binary footprint!
+
+Also several bugfixes and a couple of patches bring it another step
+closer to perfection.... :-)
+
+See CHANGELOG for details.
+
+
+Y.T.
+
+Gerard
+
+
+For more information please visit:
+
+The official libmng web-site:
+ http://www.libmng.com/
+
+Libmng's community on SourceForge:
+ https://sourceforge.net/project/?group_id=5635
+
+The official MNG homepage:
+ http://www.libpng.org/pub/mng/
+
+The official PNG homepage:
+ http://www.libpng.org/pub/png/
+
diff --git a/Source/LibMNG/README.autoconf b/Source/LibMNG/README.autoconf
new file mode 100644
index 0000000..97167b7
--- /dev/null
+++ b/Source/LibMNG/README.autoconf
@@ -0,0 +1,213 @@
+**********************************************************************
+**********************************************************************
+
+ ***** this is unmaintained *****
+
+If you happen to find problems with autoconfiguration and building,
+I simply cannot help you. I'm looking for a maintainer that doesn't mind
+spending a few minutes every now and then on the next release to make sure
+things are still in working order.
+
+For the moment all autoconf stuff ahs been moved into unmaintained!!
+
+**********************************************************************
+**********************************************************************
+
+
+
+
+Configuration from CVS
+======================
+
+If you're using source checked out from CVS, rather than a source
+distribution tarball, please be aware that you can use ./autogen.sh in
+place of ./configure below.
+
+Because this is a cross-platform project, the source templates for
+the autoconf scripts are sequestered in the 'makefiles' directory.
+Running './autogen.sh' will copy them into their conventional places at
+the lop level. If you already see the files there, you don't need to
+worry about this step.
+
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/bin', `/usr/local/man', etc. You can specify an
+installation prefix other than `/usr/local' by giving `configure' the
+option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=PATH' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
diff --git a/Source/LibMNG/README.config b/Source/LibMNG/README.config
new file mode 100644
index 0000000..d5cd454
--- /dev/null
+++ b/Source/LibMNG/README.config
@@ -0,0 +1,104 @@
+Configuration options in libmng
+===============================
+
+The library is fairly configurable through the use of a number of defines.
+Please note however that certain defines are for internal use only.
+The following list gives a summary of options that can be used externally to
+define the functionality of the library:
+
+========================================
+
+#define MNG_BUILD_DLL
+
+This is used to indicate that a "standard" DLL should result from compiling
+the library. Please note the remarks in README.dll if you intend to work
+with the library as a DLL. The purpose of this option is to ensure that
+DLL builds have the same set of functions.
+
+#define MNG_BUILD_SO
+
+This is used to indicate that a "standard" shared library (SO) should result
+from a compilation. The purpose of this option is to ensure that all
+shared libraries generated this way will have the same set of functions.
+
+#define MNG_USE_DLL / #define MNG_USE_SO
+
+These should be used when including the library header in the compilation
+of an application to indicate that the compiler/linker must take the
+necessary steps to make the binary executable to use the standard DLL
+or shared library (SO).
+
+#define MNG_SKIP_ZLIB / #define MNG_SKIP_LCMS / #define MNG_SKIP_IJG6B
+
+Use these in conjunction with MNG_USE_DLL / MNG_USE_SO. This is useful if
+you only need the external definitions of the MNG library and not the others,
+which will speed up the compilation process.
+
+#define MNG_SUPPORT_FULL / #define MNG_SUPPORT_LC / #define MNG_SUPPORT_VLC
+
+These can be used to indicate the level of MNG spec compliance required.
+Currently only full MNG compliance is supported.
+
+#define MNG_SUPPORT_IJG6B
+
+This can be used to indicate if JNG support is required. This option will
+include the IJG JPEG-library. Note that MNG_SUPPORT_FULL will automatically
+set this option. Use this only if you need JNG support with MNG-(V)LC.
+
+#define MNG_FULL_CMS / #define MNG_GAMMA_ONLY / #define MNG_NO_CMS /
+#define MNG_APP_CMS
+
+These indicate the color-correction support level of the library.
+If you are on a platform that supports lcms (Little CMS by Marti Maria Saguar)
+then it is highly recommended to define MNG_FULL_CMS.
+If your platform has it's own CMS then select MNG_APP_CMS and be sure to
+include the appropriate callbacks in your app.
+In all other cases it is recommended to define MNG_GAMMA_ONLY.
+
+#define MNG_SUPPORT_READ / #define MNG_SUPPORT_WRITE /
+#define MNG_SUPPORT_DISPLAY
+
+These indicate the high-level support for reading, writing and/or
+displaying files. Note that in order to display a file, you'll need to read
+it first. (yes, really!)
+
+#define MNG_STORE_CHUNKS
+
+This indicates that the library should store chunk-information when reading
+a file. This information can then be processed through the
+MNG_ITERATE_CHUNKS() function. Note that you must specify this option if
+you want to create and write a new file.
+
+#define MNG_ACCESS_CHUNKS
+
+This is used to indicate that the app may need access to internally stored
+chunk information. MNG_STORE_CHUNKS must be defined as well for this option
+to function properly.
+
+#define MNG_INTERNAL_MEMMNGMT
+
+You can use this to have the library handle it's own memory allocation and
+deallocation through the "standard" memory functions. This option is turned
+off by default, which means your app must define the memory callbacks.
+
+#define MNG_ERROR_TELLTALE
+
+Set this on to allow human-readable error-messages to be included in the
+library and the error function and callback.
+
+#define MNG_BIGENDIAN_SUPPORTED
+
+This option should be used to indicate the hardware is based on big endian
+integers.
+
+#define MNG_SUPPORT_TRACE / #define MNG_TRACE_TELLTALE
+
+These two can be used when debugging an app. You'll need to have the trace
+callback setup also. This allows for a rather thorough investigation of the
+libraries function paths.
+
+========================================
+
+Any other optional defines you may encounter are for internal use only.
+please do not specify them externally. In case of doubt, consult the
+support email lists. More info can be found on http://www.libmng.com
diff --git a/Source/LibMNG/README.contrib b/Source/LibMNG/README.contrib
new file mode 100644
index 0000000..2d51ac5
--- /dev/null
+++ b/Source/LibMNG/README.contrib
@@ -0,0 +1,95 @@
+The contrib directory contains contributions made by fellow
+enthousiasts. (Check respective web-sites for the latest version)
+
+----------------------------------------------------------------------
+
+mngplg - A Netscape plugin for MNG - by Jason Summers
+
+http://pobox.com/~jason1/imaging/mngplg/
+
+The very first contribution, and what a start!
+GIF look out, MNG is on the prowl and ready to swat you like a fly!
+
+----------------------------------------------------------------------
+
+mngplay - An SDL based MNG viewer - by Ralph Giles
+
+http://snow.ashlu.bc.ca/~giles/mng/
+
+Another nice contribution. View MNG files on practically any platform
+with this standalone viewer.
+Source-code only; Requires SDL library and libmng.so
+
+(Modified by Greg Roelofs)
+
+----------------------------------------------------------------------
+
+mngview - A BCB port of the Delphi sample - by Andy Protano
+
+I have added this nice little port to the BCB samples directory.
+It adds a nifty progressbar while reading a file. Excellent work!
+Requires libmng.dll
+(note: this is in the BCB samples directory)
+
+----------------------------------------------------------------------
+
+mngdump - A BCB GUI-based dump utility - by Andy Protano
+
+Andy has sent me this fully functional MNG dump utility, that gives
+detailed information of the contents of any MNG file.
+Requires libmng.dll
+
+----------------------------------------------------------------------
+
+mng-view - A GTK-based MNG viewer - by Vova Babin
+
+Vova has been hacking away with the libmng code and has come up with
+this nice little sample how to write a MNG viewer using GTK.
+Thanks mate!
+Source-code only
+Requires GTK+ (1.2 or higher) and libmng (0.9.2 or higher)
+
+(Modified by Greg Roelofs)
+
+----------------------------------------------------------------------
+
+mngview - Another MNG viewer; this one for MSVC - by Nicholaus Brennig
+
+A welcome contribution from Nicholaus. Author of SlowView. A very nice
+image-handling utility for Windows. A welcome contribution since there
+have been numerous questions about linking libmng with MSVC.
+Well, look no further. Here it is!
+
+----------------------------------------------------------------------
+
+MSVC libmng project - An MSVC project to build libmng.dll
+ - by Chad Austin
+
+Chad has contributed some project-files that you could use to build
+libmng.dll with MSVC. Please be sure to read the README file included.
+
+----------------------------------------------------------------------
+
+fbmngplay - A simple fbcon based mng player - by Stefan Reinauer
+
+Stefan has contributed this little example, based on Ralph's
+SDL player. It uses the kernel framebuffer device to display mng
+animations through the libmng interface.
+(currently for 16-bit buffers only)
+
+----------------------------------------------------------------------
+
+xmngview - Lesstif/Motif standalone player for MNG files
+ - by Winfried Szukalski
+
+Winfried contributed this MNG player for X-based systems.
+(recently updated)
+
+----------------------------------------------------------------------
+
+makemng - A delta-MNG creation utility for MSVC - by Alex Volkov
+
+Alex sent me this nice utility that will allow you to create highly
+optmized MNGs using the delta-PNG capabilities of MNG.
+
+----------------------------------------------------------------------
diff --git a/Source/LibMNG/README.examples b/Source/LibMNG/README.examples
new file mode 100644
index 0000000..9f23b50
--- /dev/null
+++ b/Source/LibMNG/README.examples
@@ -0,0 +1,48 @@
+The samples are in platform-specific directories.
+
+!!! contributions are very welcome !!!
+
+
+bcb - Borland C++ Builder (3.0) (found under bcb/xxx)
+-----------------------------------------------------
+
+win32dll - sample project to create a Windows dll. Requires zlib1.2.1,
+ IJG jpgsrc6b and lcms1.0.14. The directories containing these
+ libraries must be at the same level as the libmng directory.
+ So if you're in the directory with this file and the libmng
+ sources, they should be in ..\zlib , ..\jpgsrc6b and ..\lcms
+ respectively.
+
+!!! To run the other Win32 samples you need to copy the libmng.dll
+ file from here into the sample's directory !!!
+
+mngtree - sample project to create a little command-line tool that dumps
+ the chunk-structure of a given file onto stdout.
+
+bogus - a completely bogus example on how to create a perfectly valid
+ (though slightly biased) MNG.
+
+mngview - port of the Delphi mngview sample. contributed by Andy Protano.
+ see also README.contrib
+
+mngrepair- an example on how to fix invalid MNG files
+ uses the new mng_copy_chunks() function and MNG_SOFTERRORS to
+ 'ignore' certain input-errors. This conditional *MUST* only be used
+ for exactly this kind of software; eg. repair utilities.
+
+
+delphi - Borland Delphi (3.0+) (found under contrib/delphi/xxx)
+---------------------------------------------------------------
+
+mngview - sample project for a simple mng-viewer. The general unit in
+ the delphi directory was translated from libmng.h It can be
+ used in other projects to access libmng.dll created with the
+ win32dll example above.
+
+
+unix - Unix (found under contrib/gcc/xxx)
+-----------------------------------------
+
+mngtree - basically a copy of the BCB sample. It includes a makefile for
+ Linux and it's been tested on RedHat6.2
+
diff --git a/Source/LibMNG/README.footprint b/Source/LibMNG/README.footprint
new file mode 100644
index 0000000..ae47da2
--- /dev/null
+++ b/Source/LibMNG/README.footprint
@@ -0,0 +1,46 @@
+/*
+ You can use one or more of the following defines to
+ reduce the size of the compiled library. Define the
+ SKIPCANVAS macros for any canvas configurations that
+ your application doesn't use. Define the SKIPCHUNK
+ macros for any chunks that your application doesn't
+ process. Define MNG_OPTIMIZE_FOOTPRINT to choose
+ smaller code size over faster execution and less memory
+ usage. These macros became available in version 1.0.6.
+*/
+
+/* eliminate unused features from libmng */
+#define MNG_OPTIMIZE_FOOTPRINT
+#define MNG_OPTIMIZE_OBJCLEANUP
+#define MNG_OPTIMIZE_CHUNKINITFREE
+#define MNG_OPTIMIZE_CHUNKASSIGN
+#define MNG_OPTIMIZE_CHUNKREADER
+
+#define MNG_SKIPCANVAS_ABGR8
+#define MNG_SKIPCANVAS_ARGB8
+#define MNG_SKIPCANVAS_BGR8
+#define MNG_SKIPCANVAS_BGRA8
+#define MNG_SKIPCANVAS_BGRA8_PM
+#define MNG_SKIPCANVAS_BGRX8
+#define MNG_SKIPCANVAS_RGBA8
+#define MNG_SKIPCANVAS_BGR565
+#define MNG_SKIPCANVAS_RGB565
+#define MNG_SKIPCANVAS_BGRA565
+#define MNG_SKIPCANVAS_RGBA565
+
+#define MNG_SKIPCHUNK_iCCP
+#define MNG_SKIPCHUNK_tEXt
+#define MNG_SKIPCHUNK_zTXt
+#define MNG_SKIPCHUNK_iTXt
+#define MNG_SKIPCHUNK_bKGD
+#define MNG_SKIPCHUNK_pHYs
+#define MNG_SKIPCHUNK_sBIT
+#define MNG_SKIPCHUNK_sPLT
+#define MNG_SKIPCHUNK_hIST
+#define MNG_SKIPCHUNK_tIME
+#define MNG_SKIPCHUNK_eXPI
+#define MNG_SKIPCHUNK_fPRI
+#define MNG_SKIPCHUNK_nEED
+#define MNG_SKIPCHUNK_pHYg
+
+
diff --git a/Source/LibMNG/README.packaging b/Source/LibMNG/README.packaging
new file mode 100644
index 0000000..32fb2da
--- /dev/null
+++ b/Source/LibMNG/README.packaging
@@ -0,0 +1,24 @@
+Packaging Libmng for distribution
+---------------------------------
+
+These are some notes for those building binaries for distribution.
+
+We're interested to hear about anywhere libmng is helpful, so let us
+know if you're including it with your application or OS. Also, if your
+build is publicly accessible, we'd be happy to link to it from
+the libmng site.
+
+However, We respectfully request that you *not* distribute binaries as a
+shared library (DLL) with any of the major features disabled. While
+there is support for this in terms of #ifdef directives (in
+libmng_conf.h) and autoconf switches they are intended for embedded
+application and testing. The default compilation options support the
+full MNG specification, and we wish to avoid the confusion among
+general users that partial support would engender.
+
+
+Platform specific notes:
+
+We have a basic .spec file for generating rpms. Send us a note if you'd
+like to clean it up.
+
diff --git a/Source/LibMNG/libmng.h b/Source/LibMNG/libmng.h
new file mode 100644
index 0000000..b3b1ab1
--- /dev/null
+++ b/Source/LibMNG/libmng.h
@@ -0,0 +1,2932 @@
+/* ************************************************************************** */
+/* * * */
+/* * COPYRIGHT NOTICE: * */
+/* * * */
+/* * Copyright (c) 2000-2007 Gerard Juyn * */
+/* * [You may insert additional notices after this sentence if you modify * */
+/* * this source] * */
+/* * * */
+/* * For the purposes of this copyright and license, "Contributing Authors" * */
+/* * is defined as the following set of individuals: * */
+/* * * */
+/* * Gerard Juyn - gjuyn :at: users.sourceforge.net * */
+/* * Glenn Randers-Pehrson - glennrp :at: users.sourceforge.net * */
+/* * Raphael Assenat - raph :at: raphnet.net * */
+/* * John Stiles - * */
+/* * * */
+/* * The MNG Library is supplied "AS IS". The Contributing Authors * */
+/* * disclaim all warranties, expressed or implied, including, without * */
+/* * limitation, the warranties of merchantability and of fitness for any * */
+/* * purpose. The Contributing Authors assume no liability for direct, * */
+/* * indirect, incidental, special, exemplary, or consequential damages, * */
+/* * which may result from the use of the MNG Library, even if advised of * */
+/* * the possibility of such damage. * */
+/* * * */
+/* * Permission is hereby granted to use, copy, modify, and distribute this * */
+/* * source code, or portions hereof, for any purpose, without fee, subject * */
+/* * to the following restrictions: * */
+/* * * */
+/* * 1. The origin of this source code must not be misrepresented; * */
+/* * you must not claim that you wrote the original software. * */
+/* * * */
+/* * 2. Altered versions must be plainly marked as such and must not be * */
+/* * misrepresented as being the original source. * */
+/* * * */
+/* * 3. This Copyright notice may not be removed or altered from any source * */
+/* * or altered source distribution. * */
+/* * * */
+/* * The Contributing Authors specifically permit, without fee, and * */
+/* * encourage the use of this source code as a component to supporting * */
+/* * the MNG and JNG file format in commercial products. If you use this * */
+/* * source code in a product, acknowledgment would be highly appreciated. * */
+/* * * */
+/* ************************************************************************** */
+/* * * */
+/* * Parts of this software have been adapted from the libpng package. * */
+/* * Although this library supports all features from the PNG specification * */
+/* * (as MNG descends from it) it does not require the libpng package. * */
+/* * It does require the zlib library and optionally the IJG jpeg library, * */
+/* * and/or the "little-cms" library by Marti Maria (depending on the * */
+/* * inclusion of support for JNG and Full-Color-Management respectively. * */
+/* * * */
+/* * This library's function is primarily to read and display MNG * */
+/* * animations. It is not meant as a full-featured image-editing * */
+/* * component! It does however offer creation and editing functionality * */
+/* * at the chunk level. * */
+/* * (future modifications may include some more support for creation * */
+/* * and or editing) * */
+/* * * */
+/* ************************************************************************** */
+
+/* ************************************************************************** */
+/* * * */
+/* * Version numbering * */
+/* * * */
+/* * X.Y.Z : X = release (0 = initial build) * */
+/* * Y = major version (uneven = test; even = production) * */
+/* * Z = minor version (bugfixes; 2 is older than 10) * */
+/* * * */
+/* * production versions only appear when a test-version is extensively * */
+/* * tested and found stable or for intermediate bug-fixes (recognized by * */
+/* * a change in the Z number) * */
+/* * * */
+/* * x.1.x = test version * */
+/* * x.2.x = production version * */
+/* * x.3.x = test version * */
+/* * x.4.x = production version * */
+/* * etc. * */
+/* * * */
+/* ************************************************************************** */
+/* * * */
+/* * Identifier naming conventions throughout this library * */
+/* * * */
+/* * iXxxx = an integer * */
+/* * dXxxx = a float * */
+/* * pXxxx = a pointer * */
+/* * bXxxx = a boolean * */
+/* * eXxxx = an enumeration * */
+/* * hXxxx = a handle * */
+/* * zXxxx = a zero-terminated string (pchar) * */
+/* * fXxxx = a pointer to a function (callback) * */
+/* * aXxxx = an array * */
+/* * sXxxx = a structure * */
+/* * * */
+/* * Macros & defines are in all uppercase. * */
+/* * Functions & typedefs in all lowercase. * */
+/* * Exported stuff is prefixed with MNG_ or mng_ respectively. * */
+/* * * */
+/* * (I may have missed a couple; don't hesitate to let me know!) * */
+/* * * */
+/* ************************************************************************** */
+
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : main application interface * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : The main application interface. An application should not * */
+/* * need access to any of the other modules! * */
+/* * * */
+/* * changes : 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - changed chunk iteration function * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - added chunk access functions * */
+/* * - added version control constants & functions * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added set_outputprofile2 & set_srgbprofile2 * */
+/* * - added empty-chunk put-routines * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - added version_dll & VERSION_DLL (for consistency) * */
+/* * - added version control explanatory text & samples * */
+/* * 0.5.1 - 05/15/2000 - G.Juyn * */
+/* * - added getimgdata & putimgdata functions * */
+/* * * */
+/* * 0.5.2 - 05/16/2000 - G.Juyn * */
+/* * - changed the version parameters (obviously) * */
+/* * 0.5.2 - 05/18/2000 - G.Juyn * */
+/* * - complimented constants for chunk-property values * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - fixed MNG_UINT_pHYg value * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added support for get/set default zlib/IJG parms * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - added MNG_BIGENDIAN_SUPPORT (contributed by Tim Rowley) * */
+/* * - separated configuration-options into "mng_conf.h" * */
+/* * - added RGB8_A8 canvasstyle * */
+/* * - added getalphaline callback for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - moved errorcodes from "mng_error.h" * */
+/* * - added mng_read_resume function to support * */
+/* * read-suspension * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed the version parameters (obviously) * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added get/set for speedtype to facilitate testing * */
+/* * - added get for imagelevel during processtext callback * */
+/* * 0.5.3 - 06/24/2000 - G.Juyn * */
+/* * - fixed inclusion of IJG read/write code * */
+/* * 0.5.3 - 06/26/2000 - G.Juyn * */
+/* * - changed userdata variable to mng_ptr * */
+/* * * */
+/* * 0.9.0 - 06/30/2000 - G.Juyn * */
+/* * - changed refresh parameters to 'x,y,width,height' * */
+/* * * */
+/* * 0.9.1 - 07/06/2000 - G.Juyn * */
+/* * - added MNG_NEEDTIMERWAIT errorcode * */
+/* * - changed comments to indicate modified behavior for * */
+/* * timer & suspension breaks * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added get routines for internal display variables * */
+/* * - added get/set routines for suspensionmode variable * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added callbacks for SAVE/SEEK processing * */
+/* * - added get/set routines for sectionbreak variable * */
+/* * - added NEEDSECTIONWAIT errorcode * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - added function to set frame-/layer-count & playtime * */
+/* * - added errorcode for updatemngheader if not a MNG * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - fixed problem with trace-functions improperly wrapped * */
+/* * - added status_xxxx functions * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * - added function to set simplicity field * */
+/* * * */
+/* * 0.9.3 - 08/09/2000 - G.Juyn * */
+/* * - added check for simplicity-bits in MHDR * */
+/* * 0.9.3 - 08/12/2000 - G.Juyn * */
+/* * - added workaround for faulty PhotoShop iCCP chunk * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - fixed processing of unknown critical chunks * */
+/* * - removed test-MaGN * */
+/* * - added PNG/MNG spec version indicators * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added functions to retrieve PNG/JNG specific header-info * */
+/* * - added JDAA chunk * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - added errocode for delayed delta-processing * */
+/* * - added get/set for bKGD preference setting * */
+/* * 0.9.3 - 10/21/2000 - G.Juyn * */
+/* * - added get function for interlace/progressive display * */
+/* * * */
+/* * 0.9.4 - 01/18/2001 - G.Juyn * */
+/* * - added errorcode for MAGN methods * */
+/* * - removed test filter-methods 1 & 65 * */
+/* * * */
+/* * 1.0.0 - 02/05/2001 - G.Juyn * */
+/* * - version numbers (obviously) * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * - added processterm callback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added late binding errorcode (not used internally) * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.3 - 08/06/2001 - G.Juyn * */
+/* * - added get function for last processed BACK chunk * */
+/* * * */
+/* * 1.0.5 - 07/04/2002 - G.Juyn * */
+/* * - added errorcode for extreme chunk-sizes * */
+/* * 1.0.5 - 08/07/2002 - G.Juyn * */
+/* * - added test-option for PNG filter method 193 (=no filter) * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * - added 'supports' call to check function availability * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added check for TERM placement during create/write * */
+/* * - added beta version function & constant * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G. Randers-Pehrson * */
+/* * - added support for reducing the footprint of libmng * */
+/* * by macros that optionally skip unused chunks, remove * */
+/* * 16-bit sample support, remove Delta support, and * */
+/* * remove JNG support, to accomodate Mozilla/Firebird. * */
+/* * 1.0.6 - 07/14/2003 - G. Randers-Pehrson * */
+/* * - further optional removal of unused functions * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 12/06/2003 - R.A * */
+/* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 03/07/2004 - G. Randers-Pehrson * */
+/* * - put gamma, cms-related declarations inside #ifdef * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/12/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * 1.0.8 - 06/05/2004 - G.R-P * */
+/* * - define MNG_INCLUDE_ZLIB when MNG_USE_ZLIB_CRC is defined * */
+/* * * */
+/* * 1.0.9 - 10/03/2004 - G.Juyn * */
+/* * - added function to retrieve current FRAM delay * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * 1.0.9 - 10/17/2004 - G.Juyn * */
+/* * - fixed PPLT getchunk/putchunk routines * */
+/* * * */
+/* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
+/* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_h_
+#define _libmng_h_
+
+/* ************************************************************************** */
+
+#include "libmng_conf.h" /* user-specific configuration options */
+
+/* ************************************************************************** */
+
+#define MNG_CHECK_BAD_ICCP /* let's catch that sucker !!! */
+
+#ifdef MNG_SUPPORT_READ /* dependencies based on user-configuration */
+#define MNG_INCLUDE_READ_PROCS
+#endif
+
+#ifdef MNG_SUPPORT_WRITE
+#define MNG_INCLUDE_WRITE_PROCS
+#endif
+
+#ifdef MNG_USE_ZLIB_CRC
+#define MNG_INCLUDE_ZLIB
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+#define MNG_INCLUDE_FILTERS
+#define MNG_INCLUDE_INTERLACE
+#define MNG_INCLUDE_OBJECTS
+#define MNG_INCLUDE_DISPLAY_PROCS
+#define MNG_INCLUDE_TIMING_PROCS
+#define MNG_INCLUDE_ZLIB
+#endif
+
+#ifdef MNG_STORE_CHUNKS
+#define MNG_INCLUDE_ZLIB
+#endif
+
+#ifdef MNG_SUPPORT_IJG6B
+#define MNG_INCLUDE_JNG
+#define MNG_INCLUDE_IJG6B
+#define MNG_USE_SETJMP
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_ACCESS_CHUNKS)
+#define MNG_INCLUDE_JNG_READ
+#endif
+#if defined(MNG_SUPPORT_WRITE) || defined(MNG_ACCESS_CHUNKS)
+#define MNG_INCLUDE_JNG_WRITE
+#endif
+#endif
+
+#ifdef MNG_FULL_CMS
+#define MNG_INCLUDE_LCMS
+#endif
+
+#ifdef MNG_AUTO_DITHER
+#define MNG_INCLUDE_DITHERING
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+#define MNG_INCLUDE_TRACE_PROCS
+#ifdef MNG_TRACE_TELLTALE
+#define MNG_INCLUDE_TRACE_STRINGS
+#endif
+#endif
+
+#ifdef MNG_ERROR_TELLTALE
+#define MNG_INCLUDE_ERROR_STRINGS
+#endif
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_OPTIMIZE_CHUNKACCESS
+#define MNG_OPTIMIZE_CHUNKACCESS
+#endif
+#else
+#ifdef MNG_OPTIMIZE_CHUNKACCESS
+#undef MNG_OPTIMIZE_CHUNKACCESS
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#include "libmng_types.h" /* platform-specific definitions
+ and other assorted stuff */
+
+/* ************************************************************************** */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Versioning control * */
+/* * * */
+/* * version_so and version_dll will NOT reflect version_major; * */
+/* * these will only change for binary incompatible changes (which will * */
+/* * hopefully never occur) * */
+/* * note: they will be set to 1 on the first public release !!! * */
+/* * * */
+/* * first public release: * */
+/* * #define MNG_VERSION_TEXT "1.0.0" * */
+/* * #define MNG_VERSION_SO 1 eg. libmng.so.1 * */
+/* * #define MNG_VERSION_DLL 1 eg. libmng.dll * */
+/* * #define MNG_VERSION_MAJOR 1 * */
+/* * #define MNG_VERSION_MINOR 0 * */
+/* * #define MNG_VERSION_RELEASE 0 * */
+/* * * */
+/* * bug fix & cosmetics : * */
+/* * #define MNG_VERSION_TEXT "1.0.1" * */
+/* * #define MNG_VERSION_SO 1 eg. libmng.so.1 * */
+/* * #define MNG_VERSION_DLL 1 eg. libmng.dll * */
+/* * #define MNG_VERSION_MAJOR 1 * */
+/* * #define MNG_VERSION_MINOR 0 * */
+/* * #define MNG_VERSION_RELEASE 1 * */
+/* * * */
+/* * feature change : * */
+/* * #define MNG_VERSION_TEXT "1.2.0" * */
+/* * #define MNG_VERSION_SO 1 eg. libmng.so.1 * */
+/* * #define MNG_VERSION_DLL 1 eg. libmng.dll * */
+/* * #define MNG_VERSION_MAJOR 1 * */
+/* * #define MNG_VERSION_MINOR 2 * */
+/* * #define MNG_VERSION_RELEASE 0 * */
+/* * * */
+/* * major rewrite (still binary compatible) : * */
+/* * #define MNG_VERSION_TEXT "2.0.0" * */
+/* * #define MNG_VERSION_SO 1 eg. libmng.so.1 * */
+/* * #define MNG_VERSION_DLL 1 eg. libmng.dll * */
+/* * #define MNG_VERSION_MAJOR 2 * */
+/* * #define MNG_VERSION_MINOR 0 * */
+/* * #define MNG_VERSION_RELEASE 0 * */
+/* * * */
+/* * binary incompatible change: * */
+/* * #define MNG_VERSION_TEXT "13.0.0" * */
+/* * #define MNG_VERSION_SO 2 eg. libmng.so.2 * */
+/* * #define MNG_VERSION_DLL 2 eg. libmng2.dll * */
+/* * #define MNG_VERSION_MAJOR 13 * */
+/* * #define MNG_VERSION_MINOR 0 * */
+/* * #define MNG_VERSION_RELEASE 0 * */
+/* * * */
+/* * note that version_so & version_dll will always remain equal so it * */
+/* * doesn't matter which one is called to do version-checking; they are * */
+/* * just provided for their target platform * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_VERSION_TEXT "1.0.10"
+#define MNG_VERSION_SO 1 /* eg. libmng.so.1 */
+#define MNG_VERSION_DLL 1 /* but: libmng.dll (!) */
+#define MNG_VERSION_MAJOR 1
+#define MNG_VERSION_MINOR 0
+#define MNG_VERSION_RELEASE 10
+#define MNG_VERSION_BETA MNG_FALSE
+
+MNG_EXT mng_pchar MNG_DECL mng_version_text (void);
+MNG_EXT mng_uint8 MNG_DECL mng_version_so (void);
+MNG_EXT mng_uint8 MNG_DECL mng_version_dll (void);
+MNG_EXT mng_uint8 MNG_DECL mng_version_major (void);
+MNG_EXT mng_uint8 MNG_DECL mng_version_minor (void);
+MNG_EXT mng_uint8 MNG_DECL mng_version_release (void);
+MNG_EXT mng_bool MNG_DECL mng_version_beta (void);
+
+/* use the following call to check wether the version of libmng your app
+ is using supports the given function; this is useful in apps that dynamically
+ load the library to make sure a certain function will work; the result will
+ be MNG_TRUE if the given function is implemented in this version of the library;
+ Major/Minor/Version indicate the version the function became available;
+ (if these fields are zero the function is not yet implemented!) */
+#ifdef MNG_SUPPORT_FUNCQUERY
+MNG_EXT mng_bool MNG_DECL mng_supports_func (mng_pchar zFunction,
+ mng_uint8* iMajor,
+ mng_uint8* iMinor,
+ mng_uint8* iRelease);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * MNG/PNG specification level conformance * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_PNG_VERSION "1.2"
+#define MNG_PNG_VERSION_MAJ 1
+#define MNG_PNG_VERSION_MIN 2
+
+#define MNG_MNG_VERSION "1.1"
+#define MNG_MNG_VERSION_MAJ 1
+#define MNG_MNG_VERSION_MIN 1
+#define MNG_MNG_DRAFT 99 /* deprecated;
+ only used for nEED "MNG DRAFT nn" */
+
+/* ************************************************************************** */
+/* * * */
+/* * High-level application functions * */
+/* * * */
+/* ************************************************************************** */
+
+/* library initialization function */
+/* must be the first called before anything can be done at all */
+/* initializes internal datastructure(s) */
+MNG_EXT mng_handle MNG_DECL mng_initialize (mng_ptr pUserdata,
+ mng_memalloc fMemalloc,
+ mng_memfree fMemfree,
+ mng_traceproc fTraceproc);
+
+/* library reset function */
+/* can be used to re-initialize the library, so another image can be
+ processed. there's absolutely no harm in calling it, even when it's not
+ really necessary */
+MNG_EXT mng_retcode MNG_DECL mng_reset (mng_handle hHandle);
+
+/* library cleanup function */
+/* must be the last called to clean up internal datastructure(s) */
+MNG_EXT mng_retcode MNG_DECL mng_cleanup (mng_handle* hHandle);
+
+/* high-level read functions */
+/* use mng_read if you simply want to read a Network Graphic */
+/* mng_read_resume is used in I/O-read-suspension scenarios, where the
+ "readdata" callback may return FALSE & length=0 indicating its buffer is
+ depleted or too short to supply the required bytes, and the buffer needs
+ to be refilled; libmng will return the errorcode MNG_NEEDMOREDATA telling
+ the app to refill its read-buffer after which it must call mng_read_resume
+ (or mng_display_resume if it also displaying the image simultaneously) */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_read (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_read_resume (mng_handle hHandle);
+#endif
+
+/* high-level "data push" functions */
+/* these functions can be used in situations where data is streaming into the
+ application and needs to be buffered by libmng before it is actually
+ requested by libmng itself. the pushing complements the normal reading
+ mechanism, but applications can decide to always return "0 bytes read" to
+ make libmng go into suspension mode with the returncode MNG_NEEDMOREDATA */
+/* mng_read_pushdata can be used to push blobs of data of arbitrary size;
+ mng_read_pushsig and mng_read_pushchunk can be used if the application
+ has already done some low-level decoding (eg. at the chunk level) */
+/* the data being pushed into libmng with mng_read_pushdata *must* contain
+ the regular 4-byte chunklength, but *must not* contain it with
+ mng_read_pushchunk!!! */
+/* mng_read_pushsig is used to prevent libmng from trying to parse the regular
+ PNG/JNG/MNG signature bytes; the application must have done this itself
+ and *must* indicate the proper type in the function call or things will
+ go amiss!!
+ also you *must* call this first, so pretty much right after mng_initialize
+ and certainly before any call to mng_read or mng_readdisplay !!!! */
+/* IMPORTANT!!! data can only be safely pushed when libmng is in a
+ "wait" state; eg. during MNG_NEEDTIMERWAIT, MNG_NEEDSECTIONWAIT or
+ MNG_NEEDMOREDATA !!! this just means you can't have one thread displaying
+ and another thread pushing data !!! */
+/* if bOwnership = MNG_TRUE, libmng will retain the supplied pointer and
+ *will* expect the buffer to remain available until libmng is finished
+ with it; what happens then depends on whether or not you have set the
+ releasedata() callback; if this is set than the supplied buffer will
+ be returned through this callback and your application can take care of
+ cleaning it up, otherwise libmng will use its internal freeing mechanism
+ (which, depending on compile-options, will be the standard C free() call,
+ or the memfree() callback */
+/* if bOwnership = MNG_FALSE, libmng will just copy the data into its own
+ buffers and dispose of it in the normal way */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_read_pushdata (mng_handle hHandle,
+ mng_ptr pData,
+ mng_size_t iLength,
+ mng_bool bTakeownership);
+MNG_EXT mng_retcode MNG_DECL mng_read_pushsig (mng_handle hHandle,
+ mng_imgtype eSigtype);
+MNG_EXT mng_retcode MNG_DECL mng_read_pushchunk (mng_handle hHandle,
+ mng_ptr pChunk,
+ mng_size_t iLength,
+ mng_bool bTakeownership);
+#endif
+
+/* high-level write & create functions */
+/* use this if you want to write a previously read Network Graphic or
+ if you want to create a new graphic and write it */
+/* to write a previously read graphic you must have defined MNG_STORE_CHUNKS */
+/* to create a new graphic you'll also need access to the chunks
+ (eg. #define MNG_ACCESS_CHUNKS !) */
+#ifdef MNG_SUPPORT_WRITE
+MNG_EXT mng_retcode MNG_DECL mng_write (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_create (mng_handle hHandle);
+#endif
+
+/* high-level display functions */
+/* use these to display a previously read or created graphic or
+ to read & display a graphic simultaneously */
+/* mng_display_resume should be called after a timer-interval
+ expires that was set through the settimer-callback, after a
+ read suspension-break, or, to resume an animation after a call
+ to mng_display_freeze/mng_display_reset */
+/* mng_display_freeze thru mng_display_gotime can be used to influence
+ the display of an image, BUT ONLY if it has been completely read! */
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_readdisplay (mng_handle hHandle);
+#endif
+MNG_EXT mng_retcode MNG_DECL mng_display (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_display_resume (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_display_freeze (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_display_reset (mng_handle hHandle);
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+MNG_EXT mng_retcode MNG_DECL mng_display_goframe (mng_handle hHandle,
+ mng_uint32 iFramenr);
+MNG_EXT mng_retcode MNG_DECL mng_display_golayer (mng_handle hHandle,
+ mng_uint32 iLayernr);
+MNG_EXT mng_retcode MNG_DECL mng_display_gotime (mng_handle hHandle,
+ mng_uint32 iPlaytime);
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* event processing function */
+/* this needs to be called by the app when dynamic MNG is enabled and
+ a specific event occurs in the user-interface */
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
+MNG_EXT mng_retcode MNG_DECL mng_trapevent (mng_handle hHandle,
+ mng_uint8 iEventtype,
+ mng_int32 iX,
+ mng_int32 iY);
+#endif
+
+/* error reporting function */
+/* use this if you need more detailed info on the last error */
+/* iExtra1 & iExtra2 may contain errorcodes from zlib, jpeg, etc... */
+/* zErrortext will only be filled if you #define MNG_ERROR_TELLTALE */
+MNG_EXT mng_retcode MNG_DECL mng_getlasterror (mng_handle hHandle,
+ mng_int8* iSeverity,
+ mng_chunkid* iChunkname,
+ mng_uint32* iChunkseq,
+ mng_int32* iExtra1,
+ mng_int32* iExtra2,
+ mng_pchar* zErrortext);
+
+/* ************************************************************************** */
+/* * * */
+/* * Callback set functions * */
+/* * * */
+/* ************************************************************************** */
+
+/* memory callbacks */
+/* called to allocate and release internal datastructures */
+#ifndef MNG_INTERNAL_MEMMNGMT
+MNG_EXT mng_retcode MNG_DECL mng_setcb_memalloc (mng_handle hHandle,
+ mng_memalloc fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_memfree (mng_handle hHandle,
+ mng_memfree fProc);
+#endif /* MNG_INTERNAL_MEMMNGMT */
+
+/* open- & close-stream callbacks */
+/* called to open & close streams for input or output */
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+MNG_EXT mng_retcode MNG_DECL mng_setcb_openstream (mng_handle hHandle,
+ mng_openstream fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_closestream (mng_handle hHandle,
+ mng_closestream fProc);
+#endif
+#endif
+
+/* read callback */
+/* called to get data from the inputstream */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_setcb_readdata (mng_handle hHandle,
+ mng_readdata fProc);
+#endif
+
+/* write callback */
+/* called to put data into the outputstream */
+#ifdef MNG_SUPPORT_WRITE
+MNG_EXT mng_retcode MNG_DECL mng_setcb_writedata (mng_handle hHandle,
+ mng_writedata fProc);
+#endif
+
+/* error callback */
+/* called when an error occurs */
+/* the application can determine if the error is recoverable,
+ and may inform the library by setting specific returncodes */
+MNG_EXT mng_retcode MNG_DECL mng_setcb_errorproc (mng_handle hHandle,
+ mng_errorproc fProc);
+
+/* trace callback */
+/* called to show the currently executing function */
+#ifdef MNG_SUPPORT_TRACE
+MNG_EXT mng_retcode MNG_DECL mng_setcb_traceproc (mng_handle hHandle,
+ mng_traceproc fProc);
+#endif
+
+/* callbacks for read processing */
+/* processheader is called when all header information has been gathered
+ from the inputstream */
+/* processtext is called for every tEXt, zTXt and iTXt chunk in the
+ inputstream (iType=0 for tEXt, 1 for zTXt and 2 for iTXt);
+ you can call get_imagelevel to check at what nesting-level the chunk is
+ encountered (eg. tEXt inside an embedded image inside a MNG -> level == 2;
+ in most other case -> level == 1) */
+/* processsave & processseek are called for SAVE/SEEK chunks */
+/* processneed is called for the nEED chunk; you should specify a callback
+ for this as the default behavior will be to abort processing, unless
+ the requirement is one of:
+ - a supported chunk
+ - the text "draft nn" where nn is a numeric value
+ - the text "MNG-1.0" or "MNG-1.1"
+ - the text "CACHEOFF" */
+/* processmend is called at the very end of the animation-stream;
+ note that this may not be the end of the animation though! */
+/* processterm is called when a TERM chunk is encountered; there can be only
+ 1 in the stream (or none) */
+/* processunknown is called after reading each non-critical unknown chunk */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processheader (mng_handle hHandle,
+ mng_processheader fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processtext (mng_handle hHandle,
+ mng_processtext fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processsave (mng_handle hHandle,
+ mng_processsave fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processseek (mng_handle hHandle,
+ mng_processseek fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processneed (mng_handle hHandle,
+ mng_processneed fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processmend (mng_handle hHandle,
+ mng_processmend fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processterm (mng_handle hHandle,
+ mng_processterm fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processunknown(mng_handle hHandle,
+ mng_processunknown fProc);
+#endif
+
+/* callbacks for display processing */
+/* getcanvasline is called to get an access-pointer to a line on the
+ drawing-canvas */
+/* getbkgdline is called to get an access-pointer to a line from the
+ background-canvas */
+/* refresh is called to inform the GUI to redraw the current canvas onto
+ its output device (eg. in Win32 this would mean sending an
+ invalidate message for the specified region */
+/* NOTE that the update-region is specified as x,y,width,height; eg. the
+ invalidate message for Windows requires left,top,right,bottom parameters
+ where the bottom-right is exclusive of the region!!
+ to get these correctly is as simple as:
+ left = x;
+ top = y;
+ right = x + width;
+ bottom = y + height;
+ if your implementation requires inclusive points, simply subtract 1 from
+ both the right & bottom values calculated above.
+ */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_retcode MNG_DECL mng_setcb_getcanvasline (mng_handle hHandle,
+ mng_getcanvasline fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_getbkgdline (mng_handle hHandle,
+ mng_getbkgdline fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_getalphaline (mng_handle hHandle,
+ mng_getalphaline fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_refresh (mng_handle hHandle,
+ mng_refresh fProc);
+
+/* timing callbacks */
+/* gettickcount is called to get the system tickcount (milliseconds);
+ this is used to determine the remaining interval between frames */
+/* settimer is called to inform the application that it should set a timer;
+ when the timer is triggered the app must call mng_display_resume */
+MNG_EXT mng_retcode MNG_DECL mng_setcb_gettickcount (mng_handle hHandle,
+ mng_gettickcount fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_settimer (mng_handle hHandle,
+ mng_settimer fProc);
+
+/* color management callbacks */
+/* called to transmit color management information to the application */
+/* these are only used when you #define MNG_APP_CMS */
+#ifdef MNG_APP_CMS
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processgamma (mng_handle hHandle,
+ mng_processgamma fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processchroma (mng_handle hHandle,
+ mng_processchroma fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processsrgb (mng_handle hHandle,
+ mng_processsrgb fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processiccp (mng_handle hHandle,
+ mng_processiccp fProc);
+MNG_EXT mng_retcode MNG_DECL mng_setcb_processarow (mng_handle hHandle,
+ mng_processarow fProc);
+#endif /* MNG_APP_CMS */
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* release push data callback */
+/* used when the app pushes data into libmng (as opposed to libmng pulling it)
+ and relinquishes ownership of the pushed data-buffer, but *does* want to
+ release (free) the buffer itself once libmng has finished processing it */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_retcode MNG_DECL mng_setcb_releasedata (mng_handle hHandle,
+ mng_releasedata fProc);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Callback get functions * */
+/* * * */
+/* ************************************************************************** */
+
+/* see _setcb_ */
+#ifndef MNG_INTERNAL_MEMMNGMT
+MNG_EXT mng_memalloc MNG_DECL mng_getcb_memalloc (mng_handle hHandle);
+MNG_EXT mng_memfree MNG_DECL mng_getcb_memfree (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_releasedata MNG_DECL mng_getcb_releasedata (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+#if defined(MNG_SUPPORT_READ) || defined(MNG_WRITE_SUPPORT)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+MNG_EXT mng_openstream MNG_DECL mng_getcb_openstream (mng_handle hHandle);
+MNG_EXT mng_closestream MNG_DECL mng_getcb_closestream (mng_handle hHandle);
+#endif
+#endif
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_readdata MNG_DECL mng_getcb_readdata (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_WRITE
+MNG_EXT mng_writedata MNG_DECL mng_getcb_writedata (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+MNG_EXT mng_errorproc MNG_DECL mng_getcb_errorproc (mng_handle hHandle);
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_TRACE
+MNG_EXT mng_traceproc MNG_DECL mng_getcb_traceproc (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_processheader MNG_DECL mng_getcb_processheader (mng_handle hHandle);
+MNG_EXT mng_processtext MNG_DECL mng_getcb_processtext (mng_handle hHandle);
+MNG_EXT mng_processsave MNG_DECL mng_getcb_processsave (mng_handle hHandle);
+MNG_EXT mng_processseek MNG_DECL mng_getcb_processseek (mng_handle hHandle);
+MNG_EXT mng_processneed MNG_DECL mng_getcb_processneed (mng_handle hHandle);
+MNG_EXT mng_processunknown MNG_DECL mng_getcb_processunknown (mng_handle hHandle);
+MNG_EXT mng_processterm MNG_DECL mng_getcb_processterm (mng_handle hHandle);
+#endif
+
+/* see _setcb_ */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_getcanvasline MNG_DECL mng_getcb_getcanvasline (mng_handle hHandle);
+MNG_EXT mng_getbkgdline MNG_DECL mng_getcb_getbkgdline (mng_handle hHandle);
+MNG_EXT mng_getalphaline MNG_DECL mng_getcb_getalphaline (mng_handle hHandle);
+MNG_EXT mng_refresh MNG_DECL mng_getcb_refresh (mng_handle hHandle);
+
+/* see _setcb_ */
+MNG_EXT mng_gettickcount MNG_DECL mng_getcb_gettickcount (mng_handle hHandle);
+MNG_EXT mng_settimer MNG_DECL mng_getcb_settimer (mng_handle hHandle);
+
+/* see _setcb_ */
+#ifdef MNG_APP_CMS
+MNG_EXT mng_processgamma MNG_DECL mng_getcb_processgamma (mng_handle hHandle);
+MNG_EXT mng_processchroma MNG_DECL mng_getcb_processchroma (mng_handle hHandle);
+MNG_EXT mng_processsrgb MNG_DECL mng_getcb_processsrgb (mng_handle hHandle);
+MNG_EXT mng_processiccp MNG_DECL mng_getcb_processiccp (mng_handle hHandle);
+MNG_EXT mng_processarow MNG_DECL mng_getcb_processarow (mng_handle hHandle);
+#endif /* MNG_APP_CMS */
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+/* * * */
+/* * Property set functions * */
+/* * * */
+/* ************************************************************************** */
+
+/* Application data pointer */
+/* provided for application use; not used by the library */
+MNG_EXT mng_retcode MNG_DECL mng_set_userdata (mng_handle hHandle,
+ mng_ptr pUserdata);
+
+/* The style of the drawing- & background-canvas */
+/* only used for displaying images */
+/* both are initially set to 24-bit RGB (eg. 8-bit per channel) */
+MNG_EXT mng_retcode MNG_DECL mng_set_canvasstyle (mng_handle hHandle,
+ mng_uint32 iStyle);
+MNG_EXT mng_retcode MNG_DECL mng_set_bkgdstyle (mng_handle hHandle,
+ mng_uint32 iStyle);
+
+/* The default background color */
+/* only used if the getbkgdline callback is not defined */
+/* for initially painting the canvas and restoring (part of) the background */
+MNG_EXT mng_retcode MNG_DECL mng_set_bgcolor (mng_handle hHandle,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue);
+
+/* Indicates preferred use of the bKGD chunk for PNG images */
+MNG_EXT mng_retcode MNG_DECL mng_set_usebkgd (mng_handle hHandle,
+ mng_bool bUseBKGD);
+
+/* Indicates storage of read chunks */
+/* only useful if you #define mng_store_chunks */
+/* can be used to dynamically change storage management */
+MNG_EXT mng_retcode MNG_DECL mng_set_storechunks (mng_handle hHandle,
+ mng_bool bStorechunks);
+
+/* Indicates breaks requested when processing SAVE/SEEK */
+/* set this to let the app handle section breaks; the library will return
+ MNG_NEEDSECTIONWAIT return-codes for each SEEK chunk */
+MNG_EXT mng_retcode MNG_DECL mng_set_sectionbreaks (mng_handle hHandle,
+ mng_bool bSectionbreaks);
+
+/* Indicates storage of playback info (ON by default!) */
+/* can be used to turn off caching of playback info; this is useful to
+ specifically optimize MNG-video playback; note that if caching is turned off
+ LOOP chunks will be flagged as errors! TERM chunks will be ignored and only
+ passed to the processterm() callback if it is defined by the app; also, this
+ feature can only be used with mng_readdisplay(); mng_read(),
+ mng_display_reset() and mng_display_goxxxx() will return an error;
+ once this option is turned off it can't be turned on for the same stream!!! */
+MNG_EXT mng_retcode MNG_DECL mng_set_cacheplayback (mng_handle hHandle,
+ mng_bool bCacheplayback);
+
+/* Indicates automatic progressive refreshes for large images (ON by default!) */
+/* turn this off if you do not want intermittent painting while a large image
+ is being read. useful if the input-stream comes from a fast medium, such
+ as a local harddisk */
+MNG_EXT mng_retcode MNG_DECL mng_set_doprogressive (mng_handle hHandle,
+ mng_bool bDoProgressive);
+
+/* Indicates existence and required checking of the CRC in input streams,
+ and generation in output streams */
+/* !!!! Use this ONLY if you know what you are doing !!!! */
+/* The value is a combination of the following flags:
+ 0x0000001 = CRC is present in the input stream
+ 0x0000002 = CRC must be generated in the output stream
+ 0x0000010 = CRC should be checked for ancillary chunks
+ 0x0000020 = a faulty CRC for ancillary chunks generates a warning only
+ 0x0000040 = a faulty CRC for ancillary chunks generates an error
+ 0x0000100 = CRC should be checked for critical chunks
+ 0x0000200 = a faulty CRC for critical chunks generates a warning only
+ 0x0000400 = a faulty CRC for critical chunks generates an error
+
+ The default is 0x00000533 = CRC present in input streams; should be checked;
+ warning for ancillary chunks; error for critical
+ chunks; generate CRC for output streams
+
+ Note that some combinations are meaningless; eg. if the CRC is not present
+ it won't do any good to turn the checking flags on; if a checking flag
+ is off, it doesn't do any good to ask for generation of warnings or errors.
+ Also libmng will generate either an error or a warning, not both,
+ so if you specify both the default will be to generate an error!
+ The only useful combinations for input are 331, 551, 351, 531, 0, 301, 501
+ and optionally 031 and 051, but only checking ancillary chunks and not
+ critical chunks is generally not a very good idea!!!
+ If you've also writing these values should be combined with 0x02 if
+ CRC's are required in the output stream
+ */
+MNG_EXT mng_retcode MNG_DECL mng_set_crcmode (mng_handle hHandle,
+ mng_uint32 iCrcmode);
+
+/* Color-management necessaries */
+/*
+ *************************************************************************
+ !!!!!!!! THIS NEXT BIT IS IMPORTANT !!!!!!!!!
+ *************************************************************************
+
+ If you have defined MNG_FULL_CMS (and are using lcms), you will have to
+ think hard about the following routines.
+
+ lcms requires 2 profiles to work off the differences in the input-image
+ and the output-device. The ICC profile for the input-image will be
+ embedded within it to reflect its color-characteristics, but the output
+ profile depends on the output-device, which is something only *YOU* know
+ about. sRGB (standard RGB) is common for x86 compatible environments
+ (eg. Windows, Linux and some others)
+
+ If you are compiling for a sRGB compliant system you probably won't have
+ to do anything special. (unless you want to of course)
+
+ If you are compiling for a non-sRGB compliant system
+ (eg. SGI, Mac, Next, others...)
+ you *MUST* define a proper ICC profile for the generic output-device
+ associated with that platform.
+
+ In either event, you may also want to offer an option to your users to
+ set the profile manually, or, if you know how, set it from a
+ system-defined default.
+
+ TO RECAP: for sRGB systems (Windows, Linux) no action required!
+ for non-sRGB systems (SGI, Mac, Next) ACTION REQUIRED!
+
+ Please visit http://www.srgb.com, http://www.color.org and
+ http://www.littlecms.com for more info.
+
+ *************************************************************************
+ !!!!!!!! THE BIT ABOVE IS IMPORTANT !!!!!!!!!
+ *************************************************************************
+*/
+/* mng_set_srgb tells libmng if it's running on a sRGB compliant system or not
+ the default is already set to MNG_TRUE */
+/* mng_set_outputprofile, mng_set_outputprofile2, mng_set_outputsrgb
+ are used to set the default profile describing the output-device
+ by default it is already initialized with an sRGB profile */
+/* mng_set_srgbprofile, mng_set_srgbprofile2, mng_set_srgbimplicit
+ are used to set the default profile describing a standard sRGB device
+ this is used when the input-image is tagged only as being sRGB, but the
+ output-device is defined as not being sRGB compliant
+ by default it is already initialized with a standard sRGB profile */
+#if defined(MNG_SUPPORT_DISPLAY)
+MNG_EXT mng_retcode MNG_DECL mng_set_srgb (mng_handle hHandle,
+ mng_bool bIssRGB);
+MNG_EXT mng_retcode MNG_DECL mng_set_outputprofile (mng_handle hHandle,
+ mng_pchar zFilename);
+MNG_EXT mng_retcode MNG_DECL mng_set_outputprofile2 (mng_handle hHandle,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile);
+MNG_EXT mng_retcode MNG_DECL mng_set_outputsrgb (mng_handle hHandle);
+MNG_EXT mng_retcode MNG_DECL mng_set_srgbprofile (mng_handle hHandle,
+ mng_pchar zFilename);
+MNG_EXT mng_retcode MNG_DECL mng_set_srgbprofile2 (mng_handle hHandle,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile);
+MNG_EXT mng_retcode MNG_DECL mng_set_srgbimplicit (mng_handle hHandle);
+#endif
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+/* Gamma settings */
+/* ... blabla (explain gamma processing a little; eg. formula & stuff) ... */
+MNG_EXT mng_retcode MNG_DECL mng_set_viewgamma (mng_handle hHandle,
+ mng_float dGamma);
+MNG_EXT mng_retcode MNG_DECL mng_set_displaygamma (mng_handle hHandle,
+ mng_float dGamma);
+MNG_EXT mng_retcode MNG_DECL mng_set_dfltimggamma (mng_handle hHandle,
+ mng_float dGamma);
+MNG_EXT mng_retcode MNG_DECL mng_set_viewgammaint (mng_handle hHandle,
+ mng_uint32 iGamma);
+MNG_EXT mng_retcode MNG_DECL mng_set_displaygammaint (mng_handle hHandle,
+ mng_uint32 iGamma);
+MNG_EXT mng_retcode MNG_DECL mng_set_dfltimggammaint (mng_handle hHandle,
+ mng_uint32 iGamma);
+#endif
+
+#ifndef MNG_SKIP_MAXCANVAS
+/* Ultimate clipping size */
+/* used to limit extreme graphics from overloading the system */
+/* if a graphic exceeds these limits a warning is issued, which can
+ be ignored by the app (using the errorproc callback). in that case
+ the library will use these settings to clip the input graphic, and
+ the app's canvas must account for this */
+MNG_EXT mng_retcode MNG_DECL mng_set_maxcanvaswidth (mng_handle hHandle,
+ mng_uint32 iMaxwidth);
+MNG_EXT mng_retcode MNG_DECL mng_set_maxcanvasheight (mng_handle hHandle,
+ mng_uint32 iMaxheight);
+MNG_EXT mng_retcode MNG_DECL mng_set_maxcanvassize (mng_handle hHandle,
+ mng_uint32 iMaxwidth,
+ mng_uint32 iMaxheight);
+#endif
+
+/* ZLIB default compression parameters */
+/* these are used when writing out chunks */
+/* they are also used when compressing PNG image-data or JNG alpha-data;
+ in this case you can set them just before calling mng_putimgdata_ihdr */
+/* set to your liking; usually the defaults will suffice though! */
+/* check the documentation for ZLIB for details on these parameters */
+#ifdef MNG_INCLUDE_ZLIB
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_level (mng_handle hHandle,
+ mng_int32 iZlevel);
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_method (mng_handle hHandle,
+ mng_int32 iZmethod);
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_windowbits (mng_handle hHandle,
+ mng_int32 iZwindowbits);
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_memlevel (mng_handle hHandle,
+ mng_int32 iZmemlevel);
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_strategy (mng_handle hHandle,
+ mng_int32 iZstrategy);
+
+MNG_EXT mng_retcode MNG_DECL mng_set_zlib_maxidat (mng_handle hHandle,
+ mng_uint32 iMaxIDAT);
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* JNG default compression parameters (based on IJG code) */
+/* these are used when compressing JNG image-data; so you can set them
+ just before calling mng_putimgdata_jhdr */
+/* set to your liking; usually the defaults will suffice though! */
+/* check the documentation for IJGSRC6B for details on these parameters */
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_INCLUDE_IJG6B
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_dctmethod (mng_handle hHandle,
+ mngjpeg_dctmethod eJPEGdctmethod);
+#endif
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_quality (mng_handle hHandle,
+ mng_int32 iJPEGquality);
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_smoothing (mng_handle hHandle,
+ mng_int32 iJPEGsmoothing);
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_progressive(mng_handle hHandle,
+ mng_bool bJPEGprogressive);
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_optimized (mng_handle hHandle,
+ mng_bool bJPEGoptimized);
+
+MNG_EXT mng_retcode MNG_DECL mng_set_jpeg_maxjdat (mng_handle hHandle,
+ mng_uint32 iMaxJDAT);
+#endif /* MNG_INCLUDE_JNG */
+
+/* Suspension-mode setting */
+/* use this to activate the internal suspension-buffer to improve
+ read-suspension processing */
+/* TODO: write-suspension ??? */
+#if defined(MNG_SUPPORT_READ)
+MNG_EXT mng_retcode MNG_DECL mng_set_suspensionmode (mng_handle hHandle,
+ mng_bool bSuspensionmode);
+#endif
+
+/* Speed setting */
+/* use this to influence the display-speed of animations */
+#if defined(MNG_SUPPORT_DISPLAY)
+MNG_EXT mng_retcode MNG_DECL mng_set_speed (mng_handle hHandle,
+ mng_speedtype iSpeed);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Property get functions * */
+/* * * */
+/* ************************************************************************** */
+
+/* see _set_ */
+MNG_EXT mng_ptr MNG_DECL mng_get_userdata (mng_handle hHandle);
+
+/* Network Graphic header details */
+/* these get filled once the graphics header is processed,
+ so they are available in the processheader callback; before that
+ they are zeroed out and imagetype is set to it_unknown */
+/* this might be a good point for the app to initialize the drawing-canvas! */
+/* note that some fields are only set for the first(!) header-chunk:
+ MNG/MHDR (imagetype = mng_it_mng) - ticks thru simplicity
+ PNG/IHDR (imagetype = mng_it_png) - bitdepth thru interlace
+ JNG/JHDR (imagetype = mng_it_jng) - bitdepth thru compression &
+ interlace thru alphainterlace */
+MNG_EXT mng_imgtype MNG_DECL mng_get_sigtype (mng_handle hHandle);
+MNG_EXT mng_imgtype MNG_DECL mng_get_imagetype (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_imagewidth (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_imageheight (mng_handle hHandle);
+
+MNG_EXT mng_uint32 MNG_DECL mng_get_ticks (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_framecount (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_layercount (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_playtime (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_simplicity (mng_handle hHandle);
+
+MNG_EXT mng_uint8 MNG_DECL mng_get_bitdepth (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_colortype (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_compression (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_filter (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_interlace (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_alphabitdepth (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_alphacompression(mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_alphafilter (mng_handle hHandle);
+MNG_EXT mng_uint8 MNG_DECL mng_get_alphainterlace (mng_handle hHandle);
+
+/* indicates the predicted alpha-depth required to properly display the image */
+/* gets set once the graphics header is processed and is available in the
+ processheader callback for any type of input-image (PNG, JNG or MNG) */
+/* possible values are 0,1,2,4,8,16
+ 0 = no transparency required
+ 1 = on/off transparency required (alpha-values are 0 or 2^bit_depth-1)
+ 2+ = semi-transparency required (values will be scaled to the bitdepth of the
+ canvasstyle supplied by the application) */
+MNG_EXT mng_uint8 MNG_DECL mng_get_alphadepth (mng_handle hHandle);
+
+/* defines whether a refresh() callback is called for an interlace pass (PNG)
+ or progressive scan (JNG) */
+/* returns the interlace pass number for PNG or a fabricated pass number for JNG;
+ returns 0 in all other cases */
+/* only useful if the image_type = mng_it_png or mng_it_jng and if the image
+ is actually interlaced (PNG) or progressive (JNG) */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_uint8 MNG_DECL mng_get_refreshpass (mng_handle hHandle);
+#endif
+
+/* see _set_ */
+MNG_EXT mng_uint32 MNG_DECL mng_get_canvasstyle (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_bkgdstyle (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_retcode MNG_DECL mng_get_bgcolor (mng_handle hHandle,
+ mng_uint16* iRed,
+ mng_uint16* iGreen,
+ mng_uint16* iBlue);
+
+/* see _set_ */
+MNG_EXT mng_bool MNG_DECL mng_get_usebkgd (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_bool MNG_DECL mng_get_storechunks (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_bool MNG_DECL mng_get_sectionbreaks (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_bool MNG_DECL mng_get_cacheplayback (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_bool MNG_DECL mng_get_doprogressive (mng_handle hHandle);
+
+/* see _set_ */
+MNG_EXT mng_uint32 MNG_DECL mng_get_crcmode (mng_handle hHandle);
+
+/* see _set_ */
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_FULL_CMS)
+MNG_EXT mng_bool MNG_DECL mng_get_srgb (mng_handle hHandle);
+#endif
+
+/* see _set_ */
+MNG_EXT mng_float MNG_DECL mng_get_viewgamma (mng_handle hHandle);
+MNG_EXT mng_float MNG_DECL mng_get_displaygamma (mng_handle hHandle);
+MNG_EXT mng_float MNG_DECL mng_get_dfltimggamma (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_viewgammaint (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_displaygammaint (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_dfltimggammaint (mng_handle hHandle);
+
+#ifndef MNG_SKIP_MAXCANVAS
+/* see _set_ */
+MNG_EXT mng_uint32 MNG_DECL mng_get_maxcanvaswidth (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_maxcanvasheight (mng_handle hHandle);
+#endif
+
+/* see _set_ */
+#ifdef MNG_INCLUDE_ZLIB
+MNG_EXT mng_int32 MNG_DECL mng_get_zlib_level (mng_handle hHandle);
+MNG_EXT mng_int32 MNG_DECL mng_get_zlib_method (mng_handle hHandle);
+MNG_EXT mng_int32 MNG_DECL mng_get_zlib_windowbits (mng_handle hHandle);
+MNG_EXT mng_int32 MNG_DECL mng_get_zlib_memlevel (mng_handle hHandle);
+MNG_EXT mng_int32 MNG_DECL mng_get_zlib_strategy (mng_handle hHandle);
+
+MNG_EXT mng_uint32 MNG_DECL mng_get_zlib_maxidat (mng_handle hHandle);
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* see _set_ */
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_INCLUDE_IJG6B
+MNG_EXT mngjpeg_dctmethod
+ MNG_DECL mng_get_jpeg_dctmethod (mng_handle hHandle);
+#endif
+MNG_EXT mng_int32 MNG_DECL mng_get_jpeg_quality (mng_handle hHandle);
+MNG_EXT mng_int32 MNG_DECL mng_get_jpeg_smoothing (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_get_jpeg_progressive(mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_get_jpeg_optimized (mng_handle hHandle);
+
+MNG_EXT mng_uint32 MNG_DECL mng_get_jpeg_maxjdat (mng_handle hHandle);
+#endif /* MNG_INCLUDE_JNG */
+
+/* see _set_ */
+#if defined(MNG_SUPPORT_READ)
+MNG_EXT mng_bool MNG_DECL mng_get_suspensionmode (mng_handle hHandle);
+#endif
+
+/* see _set_ */
+#if defined(MNG_SUPPORT_DISPLAY)
+MNG_EXT mng_speedtype
+ MNG_DECL mng_get_speed (mng_handle hHandle);
+#endif
+
+/* Image-level */
+/* this can be used inside the processtext callback to determine the level of
+ text of the image being processed; the value 1 is returned for top-level
+ texts, and the value 2 for a text inside an embedded image inside a MNG */
+MNG_EXT mng_uint32 MNG_DECL mng_get_imagelevel (mng_handle hHandle);
+
+/* BACK info */
+/* can be used to retrieve the color & mandatory values for the last processed
+ BACK chunk of a MNG (will fail for other image-types);
+ if no BACK chunk was processed yet, it will return all zeroes */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_retcode MNG_DECL mng_get_lastbackchunk (mng_handle hHandle,
+ mng_uint16* iRed,
+ mng_uint16* iGreen,
+ mng_uint16* iBlue,
+ mng_uint8* iMandatory);
+#endif
+
+/* SEEK info */
+/* can be used to retrieve the segmentname of the last processed SEEK chunk;
+ if no SEEK chunk was processed or its segmentname was empty, the function
+ will return an empty string; the provided buffer must be at least 80 bytes!! */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_retcode MNG_DECL mng_get_lastseekname (mng_handle hHandle,
+ mng_pchar zSegmentname);
+#endif
+
+/* FRAM info */
+/* can be used to retrieve the current FRAM delay; this may be useful when
+ retrieving a stream of frames with their corresponding delays by "fake"
+ reading and displaying the file */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_uint32 MNG_DECL mng_get_currframdelay (mng_handle hHandle);
+#endif
+
+/* Display status variables */
+/* these get filled & updated during display processing */
+/* starttime is the tickcount at the start of displaying the animation */
+/* runtime is the actual number of millisecs since the start of the animation */
+/* currentframe, currentlayer & currentplaytime indicate the current
+ frame/layer/playtime(msecs) in the animation (these keep increasing;
+ even after the animation loops back to the TERM chunk) */
+/* totalframes, totallayers & totalplaytime are filled after a complete run
+ of an animation (eg. at MEND); they are also valid after just reading the MNG */
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_uint32 MNG_DECL mng_get_starttime (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_runtime (mng_handle hHandle);
+#ifndef MNG_NO_CURRENT_INFO
+MNG_EXT mng_uint32 MNG_DECL mng_get_currentframe (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_currentlayer (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_currentplaytime (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_totalframes (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_totallayers (mng_handle hHandle);
+MNG_EXT mng_uint32 MNG_DECL mng_get_totalplaytime (mng_handle hHandle);
+#endif
+#endif
+
+/* Status variables */
+/* these indicate the internal state of the library */
+/* most indicate exactly what you would expect -
+ status_error: true if the last function call returned an errorcode
+ status_reading: true if the library is (still) reading an image
+ status_suspendbreak: true if the library has suspended for "I/O"
+ status_creating: true if the library is in the middle of creating an image
+ status_writing: true if the library is in the middle of writing an image
+ status_displaying: true if the library is displaying an image
+ status_running: true if display processing is active (eg. not frozen or reset)
+ status_timerbreak: true if the library has suspended for a "timer-break"
+ status_dynamic: true if the library encountered an evNT chunk in the MNG
+ status_runningevent: true if the library is processing an external event */
+/* eg. mng_readdisplay() will turn the reading, displaying and running status on;
+ when EOF is reached the reading status will be turned off */
+MNG_EXT mng_bool MNG_DECL mng_status_error (mng_handle hHandle);
+#ifdef MNG_SUPPORT_READ
+MNG_EXT mng_bool MNG_DECL mng_status_reading (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_status_suspendbreak (mng_handle hHandle);
+#endif
+#ifdef MNG_SUPPORT_WRITE
+MNG_EXT mng_bool MNG_DECL mng_status_creating (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_status_writing (mng_handle hHandle);
+#endif
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_EXT mng_bool MNG_DECL mng_status_displaying (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_status_running (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_status_timerbreak (mng_handle hHandle);
+#endif
+#ifdef MNG_SUPPORT_DYNAMICMNG
+MNG_EXT mng_bool MNG_DECL mng_status_dynamic (mng_handle hHandle);
+MNG_EXT mng_bool MNG_DECL mng_status_runningevent (mng_handle hHandle);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk access functions * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_ACCESS_CHUNKS
+
+/* ************************************************************************** */
+
+/* use this to iterate the stored chunks */
+/* requires MNG_ACCESS_CHUNKS & MNG_STORE_CHUNKS */
+/* starts from the supplied chunk-index-nr; the first chunk has index 0!! */
+MNG_EXT mng_retcode MNG_DECL mng_iterate_chunks (mng_handle hHandle,
+ mng_uint32 iChunkseq,
+ mng_iteratechunk fProc);
+
+/* use the next function inside your 'iteratechunk' callback to copy
+ the given chunk to a new mng you are creating */
+/* the 'out' handle should be in 'create' status! */
+#ifdef MNG_SUPPORT_WRITE
+MNG_EXT mng_retcode MNG_DECL mng_copy_chunk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_handle hHandleOut);
+#endif
+
+/* ************************************************************************** */
+
+/* use these to get chunk data from within the callback in iterate_chunks */
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_ihdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iBitdepth,
+ mng_uint8 *iColortype,
+ mng_uint8 *iCompression,
+ mng_uint8 *iFilter,
+ mng_uint8 *iInterlace);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_plte (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_palette8 *aPalette);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_idat (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_trns (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_bool *bGlobal,
+ mng_uint8 *iType,
+ mng_uint32 *iCount,
+ mng_uint8arr *aAlphas,
+ mng_uint16 *iGray,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint32 *iRawlen,
+ mng_uint8arr *aRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_gama (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iGamma);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_chrm (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iWhitepointx,
+ mng_uint32 *iWhitepointy,
+ mng_uint32 *iRedx,
+ mng_uint32 *iRedy,
+ mng_uint32 *iGreenx,
+ mng_uint32 *iGreeny,
+ mng_uint32 *iBluex,
+ mng_uint32 *iBluey);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_srgb (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iRenderingintent);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_iccp (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iCompression,
+ mng_uint32 *iProfilesize,
+ mng_ptr *pProfile);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_text (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_ztxt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint8 *iCompression,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_itxt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint8 *iCompressionflag,
+ mng_uint8 *iCompressionmethod,
+ mng_uint32 *iLanguagesize,
+ mng_pchar *zLanguage,
+ mng_uint32 *iTranslationsize,
+ mng_pchar *zTranslation,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_bkgd (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iType,
+ mng_uint8 *iIndex,
+ mng_uint16 *iGray,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_phys (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iSizex,
+ mng_uint32 *iSizey,
+ mng_uint8 *iUnit);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_sbit (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iType,
+ mng_uint8arr4 *aBits);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_splt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iSampledepth,
+ mng_uint32 *iEntrycount,
+ mng_ptr *pEntries);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_hist (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iEntrycount,
+ mng_uint16arr *aEntries);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_time (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iYear,
+ mng_uint8 *iMonth,
+ mng_uint8 *iDay,
+ mng_uint8 *iHour,
+ mng_uint8 *iMinute,
+ mng_uint8 *iSecond);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_mhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint32 *iTicks,
+ mng_uint32 *iLayercount,
+ mng_uint32 *iFramecount,
+ mng_uint32 *iPlaytime,
+ mng_uint32 *iSimplicity);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_loop (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iLevel,
+ mng_uint32 *iRepeat,
+ mng_uint8 *iTermination,
+ mng_uint32 *iItermin,
+ mng_uint32 *iItermax,
+ mng_uint32 *iCount,
+ mng_uint32p *pSignals);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_endl (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iLevel);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_defi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iDonotshow,
+ mng_uint8 *iConcrete,
+ mng_bool *bHasloca,
+ mng_int32 *iXlocation,
+ mng_int32 *iYlocation,
+ mng_bool *bHasclip,
+ mng_int32 *iLeftcb,
+ mng_int32 *iRightcb,
+ mng_int32 *iTopcb,
+ mng_int32 *iBottomcb);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_basi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iBitdepth,
+ mng_uint8 *iColortype,
+ mng_uint8 *iCompression,
+ mng_uint8 *iFilter,
+ mng_uint8 *iInterlace,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint16 *iAlpha,
+ mng_uint8 *iViewable);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_clon (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iSourceid,
+ mng_uint16 *iCloneid,
+ mng_uint8 *iClonetype,
+ mng_uint8 *iDonotshow,
+ mng_uint8 *iConcrete,
+ mng_bool *bHasloca,
+ mng_uint8 *iLocationtype,
+ mng_int32 *iLocationx,
+ mng_int32 *iLocationy);
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_past (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iDestid,
+ mng_uint8 *iTargettype,
+ mng_int32 *iTargetx,
+ mng_int32 *iTargety,
+ mng_uint32 *iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_past_src (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint16 *iSourceid,
+ mng_uint8 *iComposition,
+ mng_uint8 *iOrientation,
+ mng_uint8 *iOffsettype,
+ mng_int32 *iOffsetx,
+ mng_int32 *iOffsety,
+ mng_uint8 *iBoundarytype,
+ mng_int32 *iBoundaryl,
+ mng_int32 *iBoundaryr,
+ mng_int32 *iBoundaryt,
+ mng_int32 *iBoundaryb);
+#endif
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_disc (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_uint16p *pObjectids);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_back (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint8 *iMandatory,
+ mng_uint16 *iImageid,
+ mng_uint8 *iTile);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_fram (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iMode,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iChangedelay,
+ mng_uint8 *iChangetimeout,
+ mng_uint8 *iChangeclipping,
+ mng_uint8 *iChangesyncid,
+ mng_uint32 *iDelay,
+ mng_uint32 *iTimeout,
+ mng_uint8 *iBoundarytype,
+ mng_int32 *iBoundaryl,
+ mng_int32 *iBoundaryr,
+ mng_int32 *iBoundaryt,
+ mng_int32 *iBoundaryb,
+ mng_uint32 *iCount,
+ mng_uint32p *pSyncids);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_move (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iMovetype,
+ mng_int32 *iMovex,
+ mng_int32 *iMovey);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_clip (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iCliptype,
+ mng_int32 *iClipl,
+ mng_int32 *iClipr,
+ mng_int32 *iClipt,
+ mng_int32 *iClipb);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_show (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iMode);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_term (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iTermaction,
+ mng_uint8 *iIteraction,
+ mng_uint32 *iDelay,
+ mng_uint32 *iItermax);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_save (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iOffsettype,
+ mng_uint32 *iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_save_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint8 *iEntrytype,
+ mng_uint32arr2 *iOffset,
+ mng_uint32arr2 *iStarttime,
+ mng_uint32 *iLayernr,
+ mng_uint32 *iFramenr,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_seek (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_expi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iSnapshotid,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_fpri (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iDeltatype,
+ mng_uint8 *iPriority);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_need (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordssize,
+ mng_pchar *zKeywords);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_phyg (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iSizex,
+ mng_uint32 *iSizey,
+ mng_uint8 *iUnit);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_jhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iColortype,
+ mng_uint8 *iImagesampledepth,
+ mng_uint8 *iImagecompression,
+ mng_uint8 *iImageinterlace,
+ mng_uint8 *iAlphasampledepth,
+ mng_uint8 *iAlphacompression,
+ mng_uint8 *iAlphafilter,
+ mng_uint8 *iAlphainterlace);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_jdat (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_jdaa (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_dhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iImagetype,
+ mng_uint8 *iDeltatype,
+ mng_uint32 *iBlockwidth,
+ mng_uint32 *iBlockheight,
+ mng_uint32 *iBlockx,
+ mng_uint32 *iBlocky);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_prom (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iColortype,
+ mng_uint8 *iSampledepth,
+ mng_uint8 *iFilltype);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_pplt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iDeltatype,
+ mng_uint32 *iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_pplt_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint16 *iAlpha,
+ mng_bool *bUsed);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_drop (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_chunkidp *pChunknames);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_dbyk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_chunkid *iChunkname,
+ mng_uint8 *iPolarity,
+ mng_uint32 *iKeywordssize,
+ mng_pchar *zKeywords);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_ordr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_ordr_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_chunkid *iChunkname,
+ mng_uint8 *iOrdertype);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_magn (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint16 *iMethodX,
+ mng_uint16 *iMX,
+ mng_uint16 *iMY,
+ mng_uint16 *iML,
+ mng_uint16 *iMR,
+ mng_uint16 *iMT,
+ mng_uint16 *iMB,
+ mng_uint16 *iMethodY);
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_mpng (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iFramewidth,
+ mng_uint32 *iFrameheight,
+ mng_uint16 *iNumplays,
+ mng_uint16 *iTickspersec,
+ mng_uint8 *iCompressionmethod,
+ mng_uint32 *iCount);
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_mpng_frame (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint32 *iX,
+ mng_uint32 *iY,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_int32 *iXoffset,
+ mng_int32 *iYoffset,
+ mng_uint16 *iTicks);
+#endif
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_evnt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_evnt_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint8 *iEventtype,
+ mng_uint8 *iMasktype,
+ mng_int32 *iLeft,
+ mng_int32 *iRight,
+ mng_int32 *iTop,
+ mng_int32 *iBottom,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iIndex,
+ mng_uint32 *iSegmentnamesize,
+ mng_pchar *zSegmentname);
+
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_unknown (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_chunkid *iChunkname,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata);
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* use these to create new chunks at the end of the chunk-list */
+/* requires at least MNG_ACCESS_CHUNKS (MNG_SUPPORT_WRITE may be nice too) */
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_ihdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_plte (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_palette8 aPalette);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_idat (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_iend (mng_handle hHandle);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_trns (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_bool bGlobal,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_uint8arr aAlphas,
+ mng_uint16 iGray,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint32 iRawlen,
+ mng_uint8arr aRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_gama (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iGamma);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_chrm (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iWhitepointx,
+ mng_uint32 iWhitepointy,
+ mng_uint32 iRedx,
+ mng_uint32 iRedy,
+ mng_uint32 iGreenx,
+ mng_uint32 iGreeny,
+ mng_uint32 iBluex,
+ mng_uint32 iBluey);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_srgb (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iRenderingintent);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_iccp (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iCompression,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_text (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint32 iTextsize,
+ mng_pchar zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_ztxt (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint8 iCompression,
+ mng_uint32 iTextsize,
+ mng_pchar zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_itxt (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint8 iCompressionflag,
+ mng_uint8 iCompressionmethod,
+ mng_uint32 iLanguagesize,
+ mng_pchar zLanguage,
+ mng_uint32 iTranslationsize,
+ mng_pchar zTranslation,
+ mng_uint32 iTextsize,
+ mng_pchar zText);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_bkgd (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iType,
+ mng_uint8 iIndex,
+ mng_uint16 iGray,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_phys (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iSizex,
+ mng_uint32 iSizey,
+ mng_uint8 iUnit);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_sbit (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iType,
+ mng_uint8arr4 aBits);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_splt (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iSampledepth,
+ mng_uint32 iEntrycount,
+ mng_ptr pEntries);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_hist (mng_handle hHandle,
+ mng_uint32 iEntrycount,
+ mng_uint16arr aEntries);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_time (mng_handle hHandle,
+ mng_uint16 iYear,
+ mng_uint8 iMonth,
+ mng_uint8 iDay,
+ mng_uint8 iHour,
+ mng_uint8 iMinute,
+ mng_uint8 iSecond);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint32 iTicks,
+ mng_uint32 iLayercount,
+ mng_uint32 iFramecount,
+ mng_uint32 iPlaytime,
+ mng_uint32 iSimplicity);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mend (mng_handle hHandle);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_loop (mng_handle hHandle,
+ mng_uint8 iLevel,
+ mng_uint32 iRepeat,
+ mng_uint8 iTermination,
+ mng_uint32 iItermin,
+ mng_uint32 iItermax,
+ mng_uint32 iCount,
+ mng_uint32p pSignals);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_endl (mng_handle hHandle,
+ mng_uint8 iLevel);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_defi (mng_handle hHandle,
+ mng_uint16 iObjectid,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_int32 iXlocation,
+ mng_int32 iYlocation,
+ mng_bool bHasclip,
+ mng_int32 iLeftcb,
+ mng_int32 iRightcb,
+ mng_int32 iTopcb,
+ mng_int32 iBottomcb);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_basi (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_clon (mng_handle hHandle,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy);
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_past (mng_handle hHandle,
+ mng_uint16 iDestid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_past_src (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint16 iSourceid,
+ mng_uint8 iComposition,
+ mng_uint8 iOrientation,
+ mng_uint8 iOffsettype,
+ mng_int32 iOffsetx,
+ mng_int32 iOffsety,
+ mng_uint8 iBoundarytype,
+ mng_int32 iBoundaryl,
+ mng_int32 iBoundaryr,
+ mng_int32 iBoundaryt,
+ mng_int32 iBoundaryb);
+#endif
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_disc (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_uint16p pObjectids);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_back (mng_handle hHandle,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint8 iMandatory,
+ mng_uint16 iImageid,
+ mng_uint8 iTile);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_fram (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iMode,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iChangedelay,
+ mng_uint8 iChangetimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iChangesyncid,
+ mng_uint32 iDelay,
+ mng_uint32 iTimeout,
+ mng_uint8 iBoundarytype,
+ mng_int32 iBoundaryl,
+ mng_int32 iBoundaryr,
+ mng_int32 iBoundaryt,
+ mng_int32 iBoundaryb,
+ mng_uint32 iCount,
+ mng_uint32p pSyncids);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_move (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMovetype,
+ mng_int32 iMovex,
+ mng_int32 iMovey);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_clip (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_show (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMode);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_term (mng_handle hHandle,
+ mng_uint8 iTermaction,
+ mng_uint8 iIteraction,
+ mng_uint32 iDelay,
+ mng_uint32 iItermax);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_save (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iOffsettype,
+ mng_uint32 iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_save_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint8 iEntrytype,
+ mng_uint32arr2 iOffset,
+ mng_uint32arr2 iStarttime,
+ mng_uint32 iLayernr,
+ mng_uint32 iFramenr,
+ mng_uint32 iNamesize,
+ mng_pchar zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_seek (mng_handle hHandle,
+ mng_uint32 iNamesize,
+ mng_pchar zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_expi (mng_handle hHandle,
+ mng_uint16 iSnapshotid,
+ mng_uint32 iNamesize,
+ mng_pchar zName);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_fpri (mng_handle hHandle,
+ mng_uint8 iDeltatype,
+ mng_uint8 iPriority);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_need (mng_handle hHandle,
+ mng_uint32 iKeywordssize,
+ mng_pchar zKeywords);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_phyg (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iSizex,
+ mng_uint32 iSizey,
+ mng_uint8 iUnit);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_jhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iImagesampledepth,
+ mng_uint8 iImagecompression,
+ mng_uint8 iImageinterlace,
+ mng_uint8 iAlphasampledepth,
+ mng_uint8 iAlphacompression,
+ mng_uint8 iAlphafilter,
+ mng_uint8 iAlphainterlace);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_jdat (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_jdaa (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_jsep (mng_handle hHandle);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_dhdr (mng_handle hHandle,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_prom (mng_handle hHandle,
+ mng_uint8 iColortype,
+ mng_uint8 iSampledepth,
+ mng_uint8 iFilltype);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_ipng (mng_handle hHandle);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_pplt (mng_handle hHandle,
+ mng_uint8 iDeltatype,
+ mng_uint32 iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_pplt_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint16 iAlpha);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_jpng (mng_handle hHandle);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_drop (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_chunkidp pChunknames);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_dbyk (mng_handle hHandle,
+ mng_chunkid iChunkname,
+ mng_uint8 iPolarity,
+ mng_uint32 iKeywordssize,
+ mng_pchar zKeywords);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_ordr (mng_handle hHandle,
+ mng_uint32 iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_ordr_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_chunkid iChunkname,
+ mng_uint8 iOrdertype);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_magn (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint16 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint16 iMethodY);
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mpng (mng_handle hHandle,
+ mng_uint32 iFramewidth,
+ mng_uint32 iFrameheight,
+ mng_uint16 iNumplays,
+ mng_uint16 iTickspersec,
+ mng_uint8 iCompressionmethod,
+ mng_uint32 iCount);
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mpng_frame (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint32 iX,
+ mng_uint32 iY,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_int32 iXoffset,
+ mng_int32 iYoffset,
+ mng_uint16 iTicks);
+#endif
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_evnt (mng_handle hHandle,
+ mng_uint32 iCount);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_evnt_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint8 iEventtype,
+ mng_uint8 iMasktype,
+ mng_int32 iLeft,
+ mng_int32 iRight,
+ mng_int32 iTop,
+ mng_int32 iBottom,
+ mng_uint16 iObjectid,
+ mng_uint8 iIndex,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname);
+
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_unknown (mng_handle hHandle,
+ mng_chunkid iChunkname,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata);
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+
+/* use these functions to access the actual image-data in stored chunks,
+ as opposed to the IDAT/JDAT data */
+/* to get accurate pixel-data the canvasstyle should seriously reflect the
+ bitdepth/colortype combination of the preceding IHDR/JHDR/BASI/DHDR;
+ all input can be converted to rgb(a)8 (rgb(a)16 for 16-bit images), but
+ there are only limited conversions back (see below for putimgdata) */
+
+/* call this function if you want to extract the nth image from the list;
+ the first image is designated seqnr 0! */
+/* this function finds the IHDR/JHDR/BASI/DHDR with the appropriate seqnr,
+ starting from the beginning of the chunk-list; this may tend to get a little
+ slow for animations with a large number of chunks for images near the end */
+/* supplying a seqnr past the last image in the animation will return with
+ an errorcode */
+MNG_EXT mng_retcode MNG_DECL mng_getimgdata_seq (mng_handle hHandle,
+ mng_uint32 iSeqnr,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline);
+
+/* both the following functions will search forward to find the first IDAT/JDAT,
+ and then traverse back to find the start of the image (IHDR,JHDR,DHDR,BASI);
+ note that this is very fast compared to decoding the IDAT/JDAT, so there's
+ not really a need for optimization; either can be called from the
+ iterate_chunks callback when a IHDR/JHDR is encountered; for BASI/DHDR there
+ may not be real image-data so it's wisest to keep iterating till the IEND,
+ and then call either of these functions if necessary (remember the correct seqnr!) */
+
+/* call this function if you want to extract the image starting at or after the nth
+ position in the chunk-list; this number is returned in the iterate_chunks callback */
+MNG_EXT mng_retcode MNG_DECL mng_getimgdata_chunkseq (mng_handle hHandle,
+ mng_uint32 iSeqnr,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline);
+
+/* call this function if you want to extract the image starting at or after the
+ indicated chunk; the handle of a chunk is returned in the iterate_chunks callback */
+MNG_EXT mng_retcode MNG_DECL mng_getimgdata_chunk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline);
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* use the following functions to add image-data to the list of stored chunks */
+/* note that this only adds the IDAT or JDAT chunks and no others; you must call
+ one of these functions after you 'put' the initial chunks of the image and
+ before you 'put' the closing chunks */
+/* the canvasstyle should seriously reflect the bitdepth/colortype combination;
+ eg. bitdepth=16 would expect a 16-bit canvasstyle,
+ colortype=g or ga would expect a gray or gray+alpha style respectively
+ and so on, and so forth ...
+ (nb. the number of conversions will be extremely limited for the moment!) */
+
+MNG_EXT mng_retcode MNG_DECL mng_putimgdata_ihdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iBitdepth,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline);
+
+MNG_EXT mng_retcode MNG_DECL mng_putimgdata_jhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iBitdepth,
+ mng_uint8 iCompression,
+ mng_uint8 iInterlace,
+ mng_uint8 iAlphaBitdepth,
+ mng_uint8 iAlphaCompression,
+ mng_uint8 iAlphaFilter,
+ mng_uint8 iAlphaInterlace,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline);
+
+/* ************************************************************************** */
+
+/* use the following functions to set the framecount/layercount/playtime or
+ simplicity of an animation you are creating; this may be useful if these
+ variables are calculated during the creation-process */
+
+MNG_EXT mng_retcode MNG_DECL mng_updatemngheader (mng_handle hHandle,
+ mng_uint32 iFramecount,
+ mng_uint32 iLayercount,
+ mng_uint32 iPlaytime);
+
+MNG_EXT mng_retcode MNG_DECL mng_updatemngsimplicity (mng_handle hHandle,
+ mng_uint32 iSimplicity);
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+#endif /* MNG_ACCESS_CHUNKS */
+
+/* ************************************************************************** */
+/* * * */
+/* * Error-code structure * */
+/* * * */
+/* * 0b0000 00xx xxxx xxxx - basic errors; severity 9 (environment) * */
+/* * 0b0000 01xx xxxx xxxx - chunk errors; severity 9 (image induced) * */
+/* * 0b0000 10xx xxxx xxxx - severity 5 errors (application induced) * */
+/* * 0b0001 00xx xxxx xxxx - severity 2 warnings (recoverable) * */
+/* * 0b0010 00xx xxxx xxxx - severity 1 warnings (recoverable) * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_NOERROR (mng_retcode)0 /* er.. indicates all's well */
+
+#define MNG_OUTOFMEMORY (mng_retcode)1 /* oops, buy some megabytes! */
+#define MNG_INVALIDHANDLE (mng_retcode)2 /* call mng_initialize first */
+#define MNG_NOCALLBACK (mng_retcode)3 /* set the callbacks please */
+#define MNG_UNEXPECTEDEOF (mng_retcode)4 /* what'd ya do with the data? */
+#define MNG_ZLIBERROR (mng_retcode)5 /* zlib burped */
+#define MNG_JPEGERROR (mng_retcode)6 /* jpglib complained */
+#define MNG_LCMSERROR (mng_retcode)7 /* little cms stressed out */
+#define MNG_NOOUTPUTPROFILE (mng_retcode)8 /* no output-profile defined */
+#define MNG_NOSRGBPROFILE (mng_retcode)9 /* no sRGB-profile defined */
+#define MNG_BUFOVERFLOW (mng_retcode)10 /* zlib output-buffer overflow */
+#define MNG_FUNCTIONINVALID (mng_retcode)11 /* ay, totally inappropriate */
+#define MNG_OUTPUTERROR (mng_retcode)12 /* disk full ? */
+#define MNG_JPEGBUFTOOSMALL (mng_retcode)13 /* can't handle buffer overflow*/
+#define MNG_NEEDMOREDATA (mng_retcode)14 /* I'm hungry, give me more */
+#define MNG_NEEDTIMERWAIT (mng_retcode)15 /* Sleep a while then wake me */
+#define MNG_NEEDSECTIONWAIT (mng_retcode)16 /* just processed a SEEK */
+#define MNG_LOOPWITHCACHEOFF (mng_retcode)17 /* LOOP when playback info off */
+
+#define MNG_DLLNOTLOADED (mng_retcode)99 /* late binding failed */
+
+#define MNG_APPIOERROR (mng_retcode)901 /* application I/O error */
+#define MNG_APPTIMERERROR (mng_retcode)902 /* application timing error */
+#define MNG_APPCMSERROR (mng_retcode)903 /* application CMS error */
+#define MNG_APPMISCERROR (mng_retcode)904 /* application other error */
+#define MNG_APPTRACEABORT (mng_retcode)905 /* application aborts on trace */
+
+#define MNG_INTERNALERROR (mng_retcode)999 /* internal inconsistancy */
+
+#define MNG_INVALIDSIG (mng_retcode)1025 /* invalid graphics file */
+#define MNG_INVALIDCRC (mng_retcode)1027 /* crc check failed */
+#define MNG_INVALIDLENGTH (mng_retcode)1028 /* chunklength mystifies me */
+#define MNG_SEQUENCEERROR (mng_retcode)1029 /* invalid chunk sequence */
+#define MNG_CHUNKNOTALLOWED (mng_retcode)1030 /* completely out-of-place */
+#define MNG_MULTIPLEERROR (mng_retcode)1031 /* only one occurence allowed */
+#define MNG_PLTEMISSING (mng_retcode)1032 /* indexed-color requires PLTE */
+#define MNG_IDATMISSING (mng_retcode)1033 /* IHDR-block requires IDAT */
+#define MNG_CANNOTBEEMPTY (mng_retcode)1034 /* must contain some data */
+#define MNG_GLOBALLENGTHERR (mng_retcode)1035 /* global data incorrect */
+#define MNG_INVALIDBITDEPTH (mng_retcode)1036 /* bitdepth out-of-range */
+#define MNG_INVALIDCOLORTYPE (mng_retcode)1037 /* colortype out-of-range */
+#define MNG_INVALIDCOMPRESS (mng_retcode)1038 /* compression method invalid */
+#define MNG_INVALIDFILTER (mng_retcode)1039 /* filter method invalid */
+#define MNG_INVALIDINTERLACE (mng_retcode)1040 /* interlace method invalid */
+#define MNG_NOTENOUGHIDAT (mng_retcode)1041 /* ran out of compressed data */
+#define MNG_PLTEINDEXERROR (mng_retcode)1042 /* palette-index out-of-range */
+#define MNG_NULLNOTFOUND (mng_retcode)1043 /* couldn't find null-separator*/
+#define MNG_KEYWORDNULL (mng_retcode)1044 /* keyword cannot be empty */
+#define MNG_OBJECTUNKNOWN (mng_retcode)1045 /* the object can't be found */
+#define MNG_OBJECTEXISTS (mng_retcode)1046 /* the object already exists */
+#define MNG_TOOMUCHIDAT (mng_retcode)1047 /* got too much compressed data*/
+#define MNG_INVSAMPLEDEPTH (mng_retcode)1048 /* sampledepth out-of-range */
+#define MNG_INVOFFSETSIZE (mng_retcode)1049 /* invalid offset-size */
+#define MNG_INVENTRYTYPE (mng_retcode)1050 /* invalid entry-type */
+#define MNG_ENDWITHNULL (mng_retcode)1051 /* may not end with NULL */
+#define MNG_INVIMAGETYPE (mng_retcode)1052 /* invalid image_type */
+#define MNG_INVDELTATYPE (mng_retcode)1053 /* invalid delta_type */
+#define MNG_INVALIDINDEX (mng_retcode)1054 /* index-value invalid */
+#define MNG_TOOMUCHJDAT (mng_retcode)1055 /* got too much compressed data*/
+#define MNG_JPEGPARMSERR (mng_retcode)1056 /* JHDR/JPEG parms do not match*/
+#define MNG_INVFILLMETHOD (mng_retcode)1057 /* invalid fill_method */
+#define MNG_OBJNOTCONCRETE (mng_retcode)1058 /* object must be concrete */
+#define MNG_TARGETNOALPHA (mng_retcode)1059 /* object has no alpha-channel */
+#define MNG_MNGTOOCOMPLEX (mng_retcode)1060 /* can't handle complexity */
+#define MNG_UNKNOWNCRITICAL (mng_retcode)1061 /* unknown critical chunk found*/
+#define MNG_UNSUPPORTEDNEED (mng_retcode)1062 /* nEED requirement unsupported*/
+#define MNG_INVALIDDELTA (mng_retcode)1063 /* Delta operation illegal */
+#define MNG_INVALIDMETHOD (mng_retcode)1064 /* invalid MAGN method */
+#define MNG_IMPROBABLELENGTH (mng_retcode)1065 /* impropable chunk length */
+#define MNG_INVALIDBLOCK (mng_retcode)1066 /* invalid delta block */
+#define MNG_INVALIDEVENT (mng_retcode)1067 /* invalid event_type */
+#define MNG_INVALIDMASK (mng_retcode)1068 /* invalid mask_type */
+#define MNG_NOMATCHINGLOOP (mng_retcode)1069 /* ENDL without matching LOOP */
+#define MNG_SEEKNOTFOUND (mng_retcode)1070 /* EvNT points to unknown SEEK */
+#define MNG_OBJNOTABSTRACT (mng_retcode)1071 /* object must be abstract */
+#define MNG_TERMSEQERROR (mng_retcode)1072 /* TERM in wrong place */
+#define MNG_INVALIDFIELDVAL (mng_retcode)1073 /* invalid fieldvalue (generic)*/
+#define MNG_INVALIDWIDTH (mng_retcode)1074 /* invalid frame/image width */
+#define MNG_INVALIDHEIGHT (mng_retcode)1075 /* invalid frame/image height */
+
+#define MNG_INVALIDCNVSTYLE (mng_retcode)2049 /* can't make anything of this */
+#define MNG_WRONGCHUNK (mng_retcode)2050 /* accessing the wrong chunk */
+#define MNG_INVALIDENTRYIX (mng_retcode)2051 /* accessing the wrong entry */
+#define MNG_NOHEADER (mng_retcode)2052 /* must have had header first */
+#define MNG_NOCORRCHUNK (mng_retcode)2053 /* can't find parent chunk */
+#define MNG_NOMHDR (mng_retcode)2054 /* no MNG header available */
+
+#define MNG_IMAGETOOLARGE (mng_retcode)4097 /* input-image way too big */
+#define MNG_NOTANANIMATION (mng_retcode)4098 /* file not a MNG */
+#define MNG_FRAMENRTOOHIGH (mng_retcode)4099 /* frame-nr out-of-range */
+#define MNG_LAYERNRTOOHIGH (mng_retcode)4100 /* layer-nr out-of-range */
+#define MNG_PLAYTIMETOOHIGH (mng_retcode)4101 /* playtime out-of-range */
+#define MNG_FNNOTIMPLEMENTED (mng_retcode)4102 /* function not yet available */
+
+#define MNG_IMAGEFROZEN (mng_retcode)8193 /* stopped displaying */
+
+#define MNG_LCMS_NOHANDLE 1 /* LCMS returned NULL handle */
+#define MNG_LCMS_NOMEM 2 /* LCMS returned NULL gammatab */
+#define MNG_LCMS_NOTRANS 3 /* LCMS returned NULL transform*/
+
+/* ************************************************************************** */
+/* * * */
+/* * Canvas styles * */
+/* * * */
+/* * Note that the intentions are pretty darn good, but that the focus * */
+/* * is currently on 8-bit color support * */
+/* * * */
+/* * The RGB8_A8 style is defined for apps that require a separate * */
+/* * canvas for the color-planes and the alpha-plane (eg. mozilla) * */
+/* * This requires for the app to supply the "getalphaline" callback!!! * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_CANVAS_RGB8 0x00000000L
+#define MNG_CANVAS_RGBA8 0x00001000L
+#define MNG_CANVAS_RGBA8_PM 0x00009000L
+#define MNG_CANVAS_ARGB8 0x00003000L
+#define MNG_CANVAS_ARGB8_PM 0x0000B000L
+#define MNG_CANVAS_RGB8_A8 0x00005000L
+#define MNG_CANVAS_BGR8 0x00000001L
+#define MNG_CANVAS_BGRX8 0x00010001L
+#define MNG_CANVAS_BGRA8 0x00001001L
+#define MNG_CANVAS_BGRA8PM 0x00009001L /* backward compatibility */
+#define MNG_CANVAS_BGRA8_PM 0x00009001L
+#define MNG_CANVAS_ABGR8 0x00003001L
+#define MNG_CANVAS_ABGR8_PM 0x0000B001L
+#define MNG_CANVAS_RGB16 0x00000100L /* not supported yet */
+#define MNG_CANVAS_RGBA16 0x00001100L /* not supported yet */
+#define MNG_CANVAS_ARGB16 0x00003100L /* not supported yet */
+#define MNG_CANVAS_BGR16 0x00000101L /* not supported yet */
+#define MNG_CANVAS_BGRA16 0x00001101L /* not supported yet */
+#define MNG_CANVAS_ABGR16 0x00003101L /* not supported yet */
+#define MNG_CANVAS_GRAY8 0x00000002L /* not supported yet */
+#define MNG_CANVAS_GRAY16 0x00000102L /* not supported yet */
+#define MNG_CANVAS_GRAYA8 0x00001002L /* not supported yet */
+#define MNG_CANVAS_GRAYA16 0x00001102L /* not supported yet */
+#define MNG_CANVAS_AGRAY8 0x00003002L /* not supported yet */
+#define MNG_CANVAS_AGRAY16 0x00003102L /* not supported yet */
+#define MNG_CANVAS_DX15 0x00000003L /* not supported yet */
+#define MNG_CANVAS_DX16 0x00000004L /* not supported yet */
+
+#define MNG_CANVAS_RGB565 0x00000005L
+#define MNG_CANVAS_RGBA565 0x00001005L
+#define MNG_CANVAS_BGR565 0x00000006L
+#define MNG_CANVAS_BGRA565 0x00001006L
+#define MNG_CANVAS_BGR565_A8 0x00004006L
+
+#define MNG_CANVAS_RGB555 0x00000007L
+#define MNG_CANVAS_BGR555 0x00000008L
+
+#define MNG_CANVAS_PIXELTYPE(C) (C & 0x000000FFL)
+#define MNG_CANVAS_BITDEPTH(C) (C & 0x00000100L)
+#define MNG_CANVAS_HASALPHA(C) (C & 0x00001000L)
+#define MNG_CANVAS_ALPHAFIRST(C) (C & 0x00002000L)
+#define MNG_CANVAS_ALPHASEPD(C) (C & 0x00004000L)
+#define MNG_CANVAS_ALPHAPM(C) (C & 0x00008000L)
+#define MNG_CANVAS_HASFILLER(C) (C & 0x00010000L)
+
+#define MNG_CANVAS_RGB(C) (MNG_CANVAS_PIXELTYPE (C) == 0)
+#define MNG_CANVAS_BGR(C) (MNG_CANVAS_PIXELTYPE (C) == 1)
+#define MNG_CANVAS_GRAY(C) (MNG_CANVAS_PIXELTYPE (C) == 2)
+#define MNG_CANVAS_DIRECTX15(C) (MNG_CANVAS_PIXELTYPE (C) == 3)
+#define MNG_CANVAS_DIRECTX16(C) (MNG_CANVAS_PIXELTYPE (C) == 4)
+#define MNG_CANVAS_RGB_565(C) (MNG_CANVAS_PIXELTYPE (C) == 5)
+#define MNG_CANVAS_BGR_565(C) (MNG_CANVAS_PIXELTYPE (C) == 6)
+#define MNG_CANVAS_8BIT(C) (!MNG_CANVAS_BITDEPTH (C))
+#define MNG_CANVAS_16BIT(C) (MNG_CANVAS_BITDEPTH (C))
+#define MNG_CANVAS_PIXELFIRST(C) (!MNG_CANVAS_ALPHAFIRST (C))
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk names (idea adapted from libpng 1.1.0 - png.h) * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_UINT_HUH 0x40404040L
+
+#define MNG_UINT_BACK 0x4241434bL
+#define MNG_UINT_BASI 0x42415349L
+#define MNG_UINT_CLIP 0x434c4950L
+#define MNG_UINT_CLON 0x434c4f4eL
+#define MNG_UINT_DBYK 0x4442594bL
+#define MNG_UINT_DEFI 0x44454649L
+#define MNG_UINT_DHDR 0x44484452L
+#define MNG_UINT_DISC 0x44495343L
+#define MNG_UINT_DROP 0x44524f50L
+#define MNG_UINT_ENDL 0x454e444cL
+#define MNG_UINT_FRAM 0x4652414dL
+#define MNG_UINT_IDAT 0x49444154L
+#define MNG_UINT_IEND 0x49454e44L
+#define MNG_UINT_IHDR 0x49484452L
+#define MNG_UINT_IJNG 0x494a4e47L
+#define MNG_UINT_IPNG 0x49504e47L
+#define MNG_UINT_JDAA 0x4a444141L
+#define MNG_UINT_JDAT 0x4a444154L
+#define MNG_UINT_JHDR 0x4a484452L
+#define MNG_UINT_JSEP 0x4a534550L
+#define MNG_UINT_JdAA 0x4a644141L
+#define MNG_UINT_LOOP 0x4c4f4f50L
+#define MNG_UINT_MAGN 0x4d41474eL
+#define MNG_UINT_MEND 0x4d454e44L
+#define MNG_UINT_MHDR 0x4d484452L
+#define MNG_UINT_MOVE 0x4d4f5645L
+#define MNG_UINT_ORDR 0x4f524452L
+#define MNG_UINT_PAST 0x50415354L
+#define MNG_UINT_PLTE 0x504c5445L
+#define MNG_UINT_PPLT 0x50504c54L
+#define MNG_UINT_PROM 0x50524f4dL
+#define MNG_UINT_SAVE 0x53415645L
+#define MNG_UINT_SEEK 0x5345454bL
+#define MNG_UINT_SHOW 0x53484f57L
+#define MNG_UINT_TERM 0x5445524dL
+#define MNG_UINT_adAT 0x61644154L
+#define MNG_UINT_ahDR 0x61684452L
+#define MNG_UINT_bKGD 0x624b4744L
+#define MNG_UINT_cHRM 0x6348524dL
+#define MNG_UINT_eXPI 0x65585049L
+#define MNG_UINT_evNT 0x65764e54L
+#define MNG_UINT_fPRI 0x66505249L
+#define MNG_UINT_gAMA 0x67414d41L
+#define MNG_UINT_hIST 0x68495354L
+#define MNG_UINT_iCCP 0x69434350L
+#define MNG_UINT_iTXt 0x69545874L
+#define MNG_UINT_mpNG 0x6d704e47L
+#define MNG_UINT_nEED 0x6e454544L
+#define MNG_UINT_oFFs 0x6f464673L
+#define MNG_UINT_pCAL 0x7043414cL
+#define MNG_UINT_pHYg 0x70444167L
+#define MNG_UINT_pHYs 0x70485973L
+#define MNG_UINT_sBIT 0x73424954L
+#define MNG_UINT_sCAL 0x7343414cL
+#define MNG_UINT_sPLT 0x73504c54L
+#define MNG_UINT_sRGB 0x73524742L
+#define MNG_UINT_tEXt 0x74455874L
+#define MNG_UINT_tIME 0x74494d45L
+#define MNG_UINT_tRNS 0x74524e53L
+#define MNG_UINT_zTXt 0x7a545874L
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk property values * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_BITDEPTH_1 1 /* IHDR, BASI, JHDR, PROM */
+#define MNG_BITDEPTH_2 2
+#define MNG_BITDEPTH_4 4
+#define MNG_BITDEPTH_8 8 /* sPLT */
+#define MNG_BITDEPTH_16 16
+
+#define MNG_COLORTYPE_GRAY 0 /* IHDR, BASI, PROM */
+#define MNG_COLORTYPE_RGB 2
+#define MNG_COLORTYPE_INDEXED 3
+#define MNG_COLORTYPE_GRAYA 4
+#define MNG_COLORTYPE_RGBA 6
+
+#define MNG_COMPRESSION_DEFLATE 0 /* IHDR, zTXt, iTXt, iCCP,
+ BASI, JHDR */
+
+#define MNG_FILTER_ADAPTIVE 0 /* IHDR, BASI, JHDR */
+/* #define MNG_FILTER_NO_ADAPTIVE 1
+#define MNG_FILTER_NO_DIFFERING 0
+#define MNG_FILTER_DIFFERING 0x40
+#define MNG_FILTER_MASK (MNG_FILTER_NO_ADAPTIVE | MNG_FILTER_DIFFERING) */
+#ifdef FILTER192
+#define MNG_FILTER_DIFFERING 0xC0
+#endif
+#ifdef FILTER193
+#define MNG_FILTER_NOFILTER 0xC1
+#endif
+
+#define MNG_INTERLACE_NONE 0 /* IHDR, BASI, JHDR */
+#define MNG_INTERLACE_ADAM7 1
+
+#define MNG_FILTER_NONE 0 /* IDAT */
+#define MNG_FILTER_SUB 1
+#define MNG_FILTER_UP 2
+#define MNG_FILTER_AVERAGE 3
+#define MNG_FILTER_PAETH 4
+
+#define MNG_INTENT_PERCEPTUAL 0 /* sRGB */
+#define MNG_INTENT_RELATIVECOLORIMETRIC 1
+#define MNG_INTENT_SATURATION 2
+#define MNG_INTENT_ABSOLUTECOLORIMETRIC 3
+ /* tEXt, zTXt, iTXt */
+#define MNG_TEXT_TITLE "Title"
+#define MNG_TEXT_AUTHOR "Author"
+#define MNG_TEXT_DESCRIPTION "Description"
+#define MNG_TEXT_COPYRIGHT "Copyright"
+#define MNG_TEXT_CREATIONTIME "Creation Time"
+#define MNG_TEXT_SOFTWARE "Software"
+#define MNG_TEXT_DISCLAIMER "Disclaimer"
+#define MNG_TEXT_WARNING "Warning"
+#define MNG_TEXT_SOURCE "Source"
+#define MNG_TEXT_COMMENT "Comment"
+
+#define MNG_FLAG_UNCOMPRESSED 0 /* iTXt */
+#define MNG_FLAG_COMPRESSED 1
+
+#define MNG_UNIT_UNKNOWN 0 /* pHYs, pHYg */
+#define MNG_UNIT_METER 1
+ /* MHDR */
+#define MNG_SIMPLICITY_VALID 0x00000001
+#define MNG_SIMPLICITY_SIMPLEFEATURES 0x00000002
+#define MNG_SIMPLICITY_COMPLEXFEATURES 0x00000004
+#define MNG_SIMPLICITY_TRANSPARENCY 0x00000008
+#define MNG_SIMPLICITY_JNG 0x00000010
+#define MNG_SIMPLICITY_DELTAPNG 0x00000020
+
+#define MNG_TERMINATION_DECODER_NC 0 /* LOOP */
+#define MNG_TERMINATION_USER_NC 1
+#define MNG_TERMINATION_EXTERNAL_NC 2
+#define MNG_TERMINATION_DETERMINISTIC_NC 3
+#define MNG_TERMINATION_DECODER_C 4
+#define MNG_TERMINATION_USER_C 5
+#define MNG_TERMINATION_EXTERNAL_C 6
+#define MNG_TERMINATION_DETERMINISTIC_C 7
+
+#define MNG_DONOTSHOW_VISIBLE 0 /* DEFI */
+#define MNG_DONOTSHOW_NOTVISIBLE 1
+
+#define MNG_ABSTRACT 0 /* DEFI */
+#define MNG_CONCRETE 1
+
+#define MNG_NOTVIEWABLE 0 /* BASI */
+#define MNG_VIEWABLE 1
+
+#define MNG_FULL_CLONE 0 /* CLON */
+#define MNG_PARTIAL_CLONE 1
+#define MNG_RENUMBER 2
+
+#define MNG_CONCRETE_ASPARENT 0 /* CLON */
+#define MNG_CONCRETE_MAKEABSTRACT 1
+
+#define MNG_LOCATION_ABSOLUTE 0 /* CLON, MOVE */
+#define MNG_LOCATION_RELATIVE 1
+
+#ifndef MNG_SKIPCHUNK_PAST
+#define MNG_TARGET_ABSOLUTE 0 /* PAST */
+#define MNG_TARGET_RELATIVE_SAMEPAST 1
+#define MNG_TARGET_RELATIVE_PREVPAST 2
+
+#define MNG_COMPOSITE_OVER 0 /* PAST */
+#define MNG_COMPOSITE_REPLACE 1
+#define MNG_COMPOSITE_UNDER 2
+
+#define MNG_ORIENTATION_SAME 0 /* PAST */
+#define MNG_ORIENTATION_180DEG 2
+#define MNG_ORIENTATION_FLIPHORZ 4
+#define MNG_ORIENTATION_FLIPVERT 6
+#define MNG_ORIENTATION_TILED 8
+
+#define MNG_OFFSET_ABSOLUTE 0 /* PAST */
+#define MNG_OFFSET_RELATIVE 1
+#endif
+
+#define MNG_BOUNDARY_ABSOLUTE 0 /* PAST, FRAM */
+#define MNG_BOUNDARY_RELATIVE 1
+
+#define MNG_BACKGROUNDCOLOR_MANDATORY 0x01 /* BACK */
+#define MNG_BACKGROUNDIMAGE_MANDATORY 0x02 /* BACK */
+
+#define MNG_BACKGROUNDIMAGE_NOTILE 0 /* BACK */
+#define MNG_BACKGROUNDIMAGE_TILE 1
+
+#define MNG_FRAMINGMODE_NOCHANGE 0 /* FRAM */
+#define MNG_FRAMINGMODE_1 1
+#define MNG_FRAMINGMODE_2 2
+#define MNG_FRAMINGMODE_3 3
+#define MNG_FRAMINGMODE_4 4
+
+#define MNG_CHANGEDELAY_NO 0 /* FRAM */
+#define MNG_CHANGEDELAY_NEXTSUBFRAME 1
+#define MNG_CHANGEDELAY_DEFAULT 2
+
+#define MNG_CHANGETIMOUT_NO 0 /* FRAM */
+#define MNG_CHANGETIMOUT_DETERMINISTIC_1 1
+#define MNG_CHANGETIMOUT_DETERMINISTIC_2 2
+#define MNG_CHANGETIMOUT_DECODER_1 3
+#define MNG_CHANGETIMOUT_DECODER_2 4
+#define MNG_CHANGETIMOUT_USER_1 5
+#define MNG_CHANGETIMOUT_USER_2 6
+#define MNG_CHANGETIMOUT_EXTERNAL_1 7
+#define MNG_CHANGETIMOUT_EXTERNAL_2 8
+
+#define MNG_CHANGECLIPPING_NO 0 /* FRAM */
+#define MNG_CHANGECLIPPING_NEXTSUBFRAME 1
+#define MNG_CHANGECLIPPING_DEFAULT 2
+
+#define MNG_CHANGESYNCID_NO 0 /* FRAM */
+#define MNG_CHANGESYNCID_NEXTSUBFRAME 1
+#define MNG_CHANGESYNCID_DEFAULT 2
+
+#define MNG_CLIPPING_ABSOLUTE 0 /* CLIP */
+#define MNG_CLIPPING_RELATIVE 1
+
+#define MNG_SHOWMODE_0 0 /* SHOW */
+#define MNG_SHOWMODE_1 1
+#define MNG_SHOWMODE_2 2
+#define MNG_SHOWMODE_3 3
+#define MNG_SHOWMODE_4 4
+#define MNG_SHOWMODE_5 5
+#define MNG_SHOWMODE_6 6
+#define MNG_SHOWMODE_7 7
+
+#define MNG_TERMACTION_LASTFRAME 0 /* TERM */
+#define MNG_TERMACTION_CLEAR 1
+#define MNG_TERMACTION_FIRSTFRAME 2
+#define MNG_TERMACTION_REPEAT 3
+
+#define MNG_ITERACTION_LASTFRAME 0 /* TERM */
+#define MNG_ITERACTION_CLEAR 1
+#define MNG_ITERACTION_FIRSTFRAME 2
+
+#define MNG_SAVEOFFSET_4BYTE 4 /* SAVE */
+#define MNG_SAVEOFFSET_8BYTE 8
+
+#define MNG_SAVEENTRY_SEGMENTFULL 0 /* SAVE */
+#define MNG_SAVEENTRY_SEGMENT 1
+#define MNG_SAVEENTRY_SUBFRAME 2
+#define MNG_SAVEENTRY_EXPORTEDIMAGE 3
+
+#define MNG_PRIORITY_ABSOLUTE 0 /* fPRI */
+#define MNG_PRIORITY_RELATIVE 1
+
+#ifdef MNG_INCLUDE_JNG
+#define MNG_COLORTYPE_JPEGGRAY 8 /* JHDR */
+#define MNG_COLORTYPE_JPEGCOLOR 10
+#define MNG_COLORTYPE_JPEGGRAYA 12
+#define MNG_COLORTYPE_JPEGCOLORA 14
+
+#define MNG_BITDEPTH_JPEG8 8 /* JHDR */
+#define MNG_BITDEPTH_JPEG12 12
+#define MNG_BITDEPTH_JPEG8AND12 20
+
+#define MNG_COMPRESSION_BASELINEJPEG 8 /* JHDR */
+
+#define MNG_INTERLACE_SEQUENTIAL 0 /* JHDR */
+#define MNG_INTERLACE_PROGRESSIVE 8
+#endif /* MNG_INCLUDE_JNG */
+
+#define MNG_IMAGETYPE_UNKNOWN 0 /* DHDR */
+#define MNG_IMAGETYPE_PNG 1
+#define MNG_IMAGETYPE_JNG 2
+
+#define MNG_DELTATYPE_REPLACE 0 /* DHDR */
+#define MNG_DELTATYPE_BLOCKPIXELADD 1
+#define MNG_DELTATYPE_BLOCKALPHAADD 2
+#define MNG_DELTATYPE_BLOCKCOLORADD 3
+#define MNG_DELTATYPE_BLOCKPIXELREPLACE 4
+#define MNG_DELTATYPE_BLOCKALPHAREPLACE 5
+#define MNG_DELTATYPE_BLOCKCOLORREPLACE 6
+#define MNG_DELTATYPE_NOCHANGE 7
+
+#define MNG_FILLMETHOD_LEFTBITREPLICATE 0 /* PROM */
+#define MNG_FILLMETHOD_ZEROFILL 1
+
+#define MNG_DELTATYPE_REPLACERGB 0 /* PPLT */
+#define MNG_DELTATYPE_DELTARGB 1
+#define MNG_DELTATYPE_REPLACEALPHA 2
+#define MNG_DELTATYPE_DELTAALPHA 3
+#define MNG_DELTATYPE_REPLACERGBA 4
+#define MNG_DELTATYPE_DELTARGBA 5
+
+#define MNG_POLARITY_ONLY 0 /* DBYK */
+#define MNG_POLARITY_ALLBUT 1
+
+#define MNG_EVENT_NONE 0 /* evNT */
+#define MNG_EVENT_MOUSEENTER 1
+#define MNG_EVENT_MOUSEMOVE 2
+#define MNG_EVENT_MOUSEEXIT 3
+#define MNG_EVENT_MOUSEDOWN 4
+#define MNG_EVENT_MOUSEUP 5
+
+#define MNG_MASK_NONE 0 /* evNT */
+#define MNG_MASK_BOX 1
+#define MNG_MASK_OBJECT 2
+#define MNG_MASK_OBJECTIX 3
+#define MNG_MASK_BOXOBJECT 4
+#define MNG_MASK_BOXOBJECTIX 5
+
+/* ************************************************************************** */
+/* * * */
+/* * Processtext callback types * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_TYPE_TEXT 0
+#define MNG_TYPE_ZTXT 1
+#define MNG_TYPE_ITXT 2
+
+/* ************************************************************************** */
+/* * * */
+/* * CRC processing masks * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_CRC_INPUT 0x0000000f
+#define MNG_CRC_INPUT_NONE 0x00000000
+#define MNG_CRC_INPUT_PRESENT 0x00000001
+#define MNG_CRC_OUTPUT 0x000000f0
+#define MNG_CRC_OUTPUT_NONE 0x00000000
+#define MNG_CRC_OUTPUT_GENERATE 0x00000020
+#define MNG_CRC_OUTPUT_DUMMY 0x00000040
+#define MNG_CRC_ANCILLARY 0x00000f00
+#define MNG_CRC_ANCILLARY_IGNORE 0x00000000
+#define MNG_CRC_ANCILLARY_DISCARD 0x00000100
+#define MNG_CRC_ANCILLARY_WARNING 0x00000200
+#define MNG_CRC_ANCILLARY_ERROR 0x00000300
+#define MNG_CRC_CRITICAL 0x0000f000
+#define MNG_CRC_CRITICAL_IGNORE 0x00000000
+#define MNG_CRC_CRITICAL_WARNING 0x00002000
+#define MNG_CRC_CRITICAL_ERROR 0x00003000
+#define MNG_CRC_DEFAULT 0x00002121
+
+/* ************************************************************************** */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _libmng_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng.xcodeproj/project.pbxproj b/Source/LibMNG/libmng.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..dea729e
--- /dev/null
+++ b/Source/LibMNG/libmng.xcodeproj/project.pbxproj
@@ -0,0 +1,407 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D775FBBD0E27F98E00427EA5 /* libmng_error.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB960E27F98E00427EA5 /* libmng_error.h */; };
+ D775FBBE0E27F98E00427EA5 /* libmng_dither.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB970E27F98E00427EA5 /* libmng_dither.h */; };
+ D775FBBF0E27F98E00427EA5 /* libmng_dither.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FB980E27F98E00427EA5 /* libmng_dither.c */; };
+ D775FBC00E27F98E00427EA5 /* libmng_display.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB990E27F98E00427EA5 /* libmng_display.h */; };
+ D775FBC10E27F98E00427EA5 /* libmng_display.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FB9A0E27F98E00427EA5 /* libmng_display.c */; };
+ D775FBC20E27F98E00427EA5 /* libmng_data.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB9B0E27F98E00427EA5 /* libmng_data.h */; };
+ D775FBC30E27F98E00427EA5 /* libmng_conf.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB9C0E27F98E00427EA5 /* libmng_conf.h */; };
+ D775FBC40E27F98E00427EA5 /* libmng_cms.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB9D0E27F98E00427EA5 /* libmng_cms.h */; };
+ D775FBC50E27F98E00427EA5 /* libmng_cms.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FB9E0E27F98E00427EA5 /* libmng_cms.c */; };
+ D775FBC60E27F98E00427EA5 /* libmng_chunks.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FB9F0E27F98E00427EA5 /* libmng_chunks.h */; };
+ D775FBC70E27F98E00427EA5 /* libmng_chunk_xs.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA00E27F98E00427EA5 /* libmng_chunk_xs.c */; };
+ D775FBC80E27F98E00427EA5 /* libmng_chunk_prc.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBA10E27F98E00427EA5 /* libmng_chunk_prc.h */; };
+ D775FBC90E27F98E00427EA5 /* libmng_chunk_prc.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA20E27F98E00427EA5 /* libmng_chunk_prc.c */; };
+ D775FBCA0E27F98E00427EA5 /* libmng_chunk_io.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBA30E27F98E00427EA5 /* libmng_chunk_io.h */; };
+ D775FBCB0E27F98E00427EA5 /* libmng_chunk_io.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA40E27F98E00427EA5 /* libmng_chunk_io.c */; };
+ D775FBCC0E27F98E00427EA5 /* libmng_callback_xs.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA50E27F98E00427EA5 /* libmng_callback_xs.c */; };
+ D775FBCD0E27F98E00427EA5 /* libmng_error.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA60E27F98E00427EA5 /* libmng_error.c */; };
+ D775FBCE0E27F98E00427EA5 /* libmng.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBA70E27F98E00427EA5 /* libmng.h */; };
+ D775FBCF0E27F98E00427EA5 /* libmng_filter.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBA80E27F98E00427EA5 /* libmng_filter.h */; };
+ D775FBD00E27F98E00427EA5 /* libmng_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBA90E27F98E00427EA5 /* libmng_filter.c */; };
+ D775FBD10E27F98E00427EA5 /* libmng_jpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBAA0E27F98E00427EA5 /* libmng_jpeg.c */; };
+ D775FBD20E27F98E00427EA5 /* libmng_read.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBAB0E27F98E00427EA5 /* libmng_read.h */; };
+ D775FBD30E27F98E00427EA5 /* libmng_zlib.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBAC0E27F98E00427EA5 /* libmng_zlib.h */; };
+ D775FBD40E27F98E00427EA5 /* libmng_zlib.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBAD0E27F98E00427EA5 /* libmng_zlib.c */; };
+ D775FBD50E27F98E00427EA5 /* libmng_write.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBAE0E27F98E00427EA5 /* libmng_write.h */; };
+ D775FBD60E27F98E00427EA5 /* libmng_write.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBAF0E27F98E00427EA5 /* libmng_write.c */; };
+ D775FBD70E27F98E00427EA5 /* libmng_types.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB00E27F98E00427EA5 /* libmng_types.h */; };
+ D775FBD80E27F98E00427EA5 /* libmng_trace.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB10E27F98E00427EA5 /* libmng_trace.h */; };
+ D775FBD90E27F98E00427EA5 /* libmng_trace.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBB20E27F98E00427EA5 /* libmng_trace.c */; };
+ D775FBDA0E27F98E00427EA5 /* libmng_hlapi.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBB30E27F98E00427EA5 /* libmng_hlapi.c */; };
+ D775FBDB0E27F98E00427EA5 /* libmng_pixels.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB40E27F98E00427EA5 /* libmng_pixels.h */; };
+ D775FBDC0E27F98E00427EA5 /* libmng_pixels.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBB50E27F98E00427EA5 /* libmng_pixels.c */; };
+ D775FBDD0E27F98E00427EA5 /* libmng_objects.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB60E27F98E00427EA5 /* libmng_objects.h */; };
+ D775FBDE0E27F98E00427EA5 /* libmng_object_prc.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB70E27F98E00427EA5 /* libmng_object_prc.h */; };
+ D775FBDF0E27F98E00427EA5 /* libmng_object_prc.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBB80E27F98E00427EA5 /* libmng_object_prc.c */; };
+ D775FBE00E27F98E00427EA5 /* libmng_memory.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBB90E27F98E00427EA5 /* libmng_memory.h */; };
+ D775FBE10E27F98E00427EA5 /* libmng_read.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBBA0E27F98E00427EA5 /* libmng_read.c */; };
+ D775FBE20E27F98E00427EA5 /* libmng_prop_xs.c in Sources */ = {isa = PBXBuildFile; fileRef = D775FBBB0E27F98E00427EA5 /* libmng_prop_xs.c */; };
+ D775FBE30E27F98E00427EA5 /* libmng_jpeg.h in Headers */ = {isa = PBXBuildFile; fileRef = D775FBBC0E27F98E00427EA5 /* libmng_jpeg.h */; };
+ D79680B90E27FA8400F55C3F /* libmng_chunk_descr.c in Sources */ = {isa = PBXBuildFile; fileRef = D79680B70E27FA8400F55C3F /* libmng_chunk_descr.c */; };
+ D79680BA0E27FA8400F55C3F /* libmng_chunk_descr.h in Headers */ = {isa = PBXBuildFile; fileRef = D79680B80E27FA8400F55C3F /* libmng_chunk_descr.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libmng.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmng.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D775FB960E27F98E00427EA5 /* libmng_error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_error.h; sourceTree = SOURCE_ROOT; };
+ D775FB970E27F98E00427EA5 /* libmng_dither.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_dither.h; sourceTree = SOURCE_ROOT; };
+ D775FB980E27F98E00427EA5 /* libmng_dither.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_dither.c; sourceTree = SOURCE_ROOT; };
+ D775FB990E27F98E00427EA5 /* libmng_display.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_display.h; sourceTree = SOURCE_ROOT; };
+ D775FB9A0E27F98E00427EA5 /* libmng_display.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_display.c; sourceTree = SOURCE_ROOT; };
+ D775FB9B0E27F98E00427EA5 /* libmng_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_data.h; sourceTree = SOURCE_ROOT; };
+ D775FB9C0E27F98E00427EA5 /* libmng_conf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_conf.h; sourceTree = SOURCE_ROOT; };
+ D775FB9D0E27F98E00427EA5 /* libmng_cms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_cms.h; sourceTree = SOURCE_ROOT; };
+ D775FB9E0E27F98E00427EA5 /* libmng_cms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_cms.c; sourceTree = SOURCE_ROOT; };
+ D775FB9F0E27F98E00427EA5 /* libmng_chunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_chunks.h; sourceTree = SOURCE_ROOT; };
+ D775FBA00E27F98E00427EA5 /* libmng_chunk_xs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_chunk_xs.c; sourceTree = SOURCE_ROOT; };
+ D775FBA10E27F98E00427EA5 /* libmng_chunk_prc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_chunk_prc.h; sourceTree = SOURCE_ROOT; };
+ D775FBA20E27F98E00427EA5 /* libmng_chunk_prc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_chunk_prc.c; sourceTree = SOURCE_ROOT; };
+ D775FBA30E27F98E00427EA5 /* libmng_chunk_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_chunk_io.h; sourceTree = SOURCE_ROOT; };
+ D775FBA40E27F98E00427EA5 /* libmng_chunk_io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_chunk_io.c; sourceTree = SOURCE_ROOT; };
+ D775FBA50E27F98E00427EA5 /* libmng_callback_xs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_callback_xs.c; sourceTree = SOURCE_ROOT; };
+ D775FBA60E27F98E00427EA5 /* libmng_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_error.c; sourceTree = SOURCE_ROOT; };
+ D775FBA70E27F98E00427EA5 /* libmng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng.h; sourceTree = SOURCE_ROOT; };
+ D775FBA80E27F98E00427EA5 /* libmng_filter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_filter.h; sourceTree = SOURCE_ROOT; };
+ D775FBA90E27F98E00427EA5 /* libmng_filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_filter.c; sourceTree = SOURCE_ROOT; };
+ D775FBAA0E27F98E00427EA5 /* libmng_jpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_jpeg.c; sourceTree = SOURCE_ROOT; };
+ D775FBAB0E27F98E00427EA5 /* libmng_read.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_read.h; sourceTree = SOURCE_ROOT; };
+ D775FBAC0E27F98E00427EA5 /* libmng_zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_zlib.h; sourceTree = SOURCE_ROOT; };
+ D775FBAD0E27F98E00427EA5 /* libmng_zlib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_zlib.c; sourceTree = SOURCE_ROOT; };
+ D775FBAE0E27F98E00427EA5 /* libmng_write.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_write.h; sourceTree = SOURCE_ROOT; };
+ D775FBAF0E27F98E00427EA5 /* libmng_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_write.c; sourceTree = SOURCE_ROOT; };
+ D775FBB00E27F98E00427EA5 /* libmng_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_types.h; sourceTree = SOURCE_ROOT; };
+ D775FBB10E27F98E00427EA5 /* libmng_trace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_trace.h; sourceTree = SOURCE_ROOT; };
+ D775FBB20E27F98E00427EA5 /* libmng_trace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_trace.c; sourceTree = SOURCE_ROOT; };
+ D775FBB30E27F98E00427EA5 /* libmng_hlapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_hlapi.c; sourceTree = SOURCE_ROOT; };
+ D775FBB40E27F98E00427EA5 /* libmng_pixels.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_pixels.h; sourceTree = SOURCE_ROOT; };
+ D775FBB50E27F98E00427EA5 /* libmng_pixels.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_pixels.c; sourceTree = SOURCE_ROOT; };
+ D775FBB60E27F98E00427EA5 /* libmng_objects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_objects.h; sourceTree = SOURCE_ROOT; };
+ D775FBB70E27F98E00427EA5 /* libmng_object_prc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_object_prc.h; sourceTree = SOURCE_ROOT; };
+ D775FBB80E27F98E00427EA5 /* libmng_object_prc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_object_prc.c; sourceTree = SOURCE_ROOT; };
+ D775FBB90E27F98E00427EA5 /* libmng_memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_memory.h; sourceTree = SOURCE_ROOT; };
+ D775FBBA0E27F98E00427EA5 /* libmng_read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_read.c; sourceTree = SOURCE_ROOT; };
+ D775FBBB0E27F98E00427EA5 /* libmng_prop_xs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_prop_xs.c; sourceTree = SOURCE_ROOT; };
+ D775FBBC0E27F98E00427EA5 /* libmng_jpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_jpeg.h; sourceTree = SOURCE_ROOT; };
+ D775FBE40E27F9A900427EA5 /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../../../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D775FBE50E27F9A900427EA5 /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../../../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D79680B70E27FA8400F55C3F /* libmng_chunk_descr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libmng_chunk_descr.c; sourceTree = SOURCE_ROOT; };
+ D79680B80E27FA8400F55C3F /* libmng_chunk_descr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libmng_chunk_descr.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libmng */ = {
+ isa = PBXGroup;
+ children = (
+ D775FBE40E27F9A900427EA5 /* MacConfigExternalDebug.xcconfig */,
+ D775FBE50E27F9A900427EA5 /* MacConfigExternalRelease.xcconfig */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libmng;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D775FB960E27F98E00427EA5 /* libmng_error.h */,
+ D775FB970E27F98E00427EA5 /* libmng_dither.h */,
+ D775FB980E27F98E00427EA5 /* libmng_dither.c */,
+ D775FB990E27F98E00427EA5 /* libmng_display.h */,
+ D775FB9A0E27F98E00427EA5 /* libmng_display.c */,
+ D775FB9B0E27F98E00427EA5 /* libmng_data.h */,
+ D775FB9C0E27F98E00427EA5 /* libmng_conf.h */,
+ D775FB9D0E27F98E00427EA5 /* libmng_cms.h */,
+ D775FB9E0E27F98E00427EA5 /* libmng_cms.c */,
+ D79680B70E27FA8400F55C3F /* libmng_chunk_descr.c */,
+ D79680B80E27FA8400F55C3F /* libmng_chunk_descr.h */,
+ D775FB9F0E27F98E00427EA5 /* libmng_chunks.h */,
+ D775FBA00E27F98E00427EA5 /* libmng_chunk_xs.c */,
+ D775FBA10E27F98E00427EA5 /* libmng_chunk_prc.h */,
+ D775FBA20E27F98E00427EA5 /* libmng_chunk_prc.c */,
+ D775FBA30E27F98E00427EA5 /* libmng_chunk_io.h */,
+ D775FBA40E27F98E00427EA5 /* libmng_chunk_io.c */,
+ D775FBA50E27F98E00427EA5 /* libmng_callback_xs.c */,
+ D775FBA60E27F98E00427EA5 /* libmng_error.c */,
+ D775FBA70E27F98E00427EA5 /* libmng.h */,
+ D775FBA80E27F98E00427EA5 /* libmng_filter.h */,
+ D775FBA90E27F98E00427EA5 /* libmng_filter.c */,
+ D775FBAA0E27F98E00427EA5 /* libmng_jpeg.c */,
+ D775FBAB0E27F98E00427EA5 /* libmng_read.h */,
+ D775FBAC0E27F98E00427EA5 /* libmng_zlib.h */,
+ D775FBAD0E27F98E00427EA5 /* libmng_zlib.c */,
+ D775FBAE0E27F98E00427EA5 /* libmng_write.h */,
+ D775FBAF0E27F98E00427EA5 /* libmng_write.c */,
+ D775FBB00E27F98E00427EA5 /* libmng_types.h */,
+ D775FBB10E27F98E00427EA5 /* libmng_trace.h */,
+ D775FBB20E27F98E00427EA5 /* libmng_trace.c */,
+ D775FBB30E27F98E00427EA5 /* libmng_hlapi.c */,
+ D775FBB40E27F98E00427EA5 /* libmng_pixels.h */,
+ D775FBB50E27F98E00427EA5 /* libmng_pixels.c */,
+ D775FBB60E27F98E00427EA5 /* libmng_objects.h */,
+ D775FBB70E27F98E00427EA5 /* libmng_object_prc.h */,
+ D775FBB80E27F98E00427EA5 /* libmng_object_prc.c */,
+ D775FBB90E27F98E00427EA5 /* libmng_memory.h */,
+ D775FBBA0E27F98E00427EA5 /* libmng_read.c */,
+ D775FBBB0E27F98E00427EA5 /* libmng_prop_xs.c */,
+ D775FBBC0E27F98E00427EA5 /* libmng_jpeg.h */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libmng.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D775FBBD0E27F98E00427EA5 /* libmng_error.h in Headers */,
+ D775FBBE0E27F98E00427EA5 /* libmng_dither.h in Headers */,
+ D775FBC00E27F98E00427EA5 /* libmng_display.h in Headers */,
+ D775FBC20E27F98E00427EA5 /* libmng_data.h in Headers */,
+ D775FBC30E27F98E00427EA5 /* libmng_conf.h in Headers */,
+ D775FBC40E27F98E00427EA5 /* libmng_cms.h in Headers */,
+ D775FBC60E27F98E00427EA5 /* libmng_chunks.h in Headers */,
+ D775FBC80E27F98E00427EA5 /* libmng_chunk_prc.h in Headers */,
+ D775FBCA0E27F98E00427EA5 /* libmng_chunk_io.h in Headers */,
+ D775FBCE0E27F98E00427EA5 /* libmng.h in Headers */,
+ D775FBCF0E27F98E00427EA5 /* libmng_filter.h in Headers */,
+ D775FBD20E27F98E00427EA5 /* libmng_read.h in Headers */,
+ D775FBD30E27F98E00427EA5 /* libmng_zlib.h in Headers */,
+ D775FBD50E27F98E00427EA5 /* libmng_write.h in Headers */,
+ D775FBD70E27F98E00427EA5 /* libmng_types.h in Headers */,
+ D775FBD80E27F98E00427EA5 /* libmng_trace.h in Headers */,
+ D775FBDB0E27F98E00427EA5 /* libmng_pixels.h in Headers */,
+ D775FBDD0E27F98E00427EA5 /* libmng_objects.h in Headers */,
+ D775FBDE0E27F98E00427EA5 /* libmng_object_prc.h in Headers */,
+ D775FBE00E27F98E00427EA5 /* libmng_memory.h in Headers */,
+ D775FBE30E27F98E00427EA5 /* libmng_jpeg.h in Headers */,
+ D79680BA0E27FA8400F55C3F /* libmng_chunk_descr.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libmng */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libmng" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libmng;
+ productName = libmng;
+ productReference = D2AAC046055464E500DB518D /* libmng.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libmng" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libmng */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libmng */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D775FBBF0E27F98E00427EA5 /* libmng_dither.c in Sources */,
+ D775FBC10E27F98E00427EA5 /* libmng_display.c in Sources */,
+ D775FBC50E27F98E00427EA5 /* libmng_cms.c in Sources */,
+ D775FBC70E27F98E00427EA5 /* libmng_chunk_xs.c in Sources */,
+ D775FBC90E27F98E00427EA5 /* libmng_chunk_prc.c in Sources */,
+ D775FBCB0E27F98E00427EA5 /* libmng_chunk_io.c in Sources */,
+ D775FBCC0E27F98E00427EA5 /* libmng_callback_xs.c in Sources */,
+ D775FBCD0E27F98E00427EA5 /* libmng_error.c in Sources */,
+ D775FBD00E27F98E00427EA5 /* libmng_filter.c in Sources */,
+ D775FBD10E27F98E00427EA5 /* libmng_jpeg.c in Sources */,
+ D775FBD40E27F98E00427EA5 /* libmng_zlib.c in Sources */,
+ D775FBD60E27F98E00427EA5 /* libmng_write.c in Sources */,
+ D775FBD90E27F98E00427EA5 /* libmng_trace.c in Sources */,
+ D775FBDA0E27F98E00427EA5 /* libmng_hlapi.c in Sources */,
+ D775FBDC0E27F98E00427EA5 /* libmng_pixels.c in Sources */,
+ D775FBDF0E27F98E00427EA5 /* libmng_object_prc.c in Sources */,
+ D775FBE10E27F98E00427EA5 /* libmng_read.c in Sources */,
+ D775FBE20E27F98E00427EA5 /* libmng_prop_xs.c in Sources */,
+ D79680B90E27FA8400F55C3F /* libmng_chunk_descr.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = mng;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = mng;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D775FBE40E27F9A900427EA5 /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DPACKAGE_NAME=\\\"\\\"",
+ "-DPACKAGE_TARNAME=\\\"\\\"",
+ "-DPACKAGE_VERSION=\\\"\\\"",
+ "-DPACKAGE_STRING=\\\"\\\"",
+ "-DPACKAGE_BUGREPORT=\\\"\\\"",
+ "-DPACKAGE=\\\"libmng\\\"",
+ "-DVERSION=\\\"1.0.9\\\"",
+ "-DPROTOTYPES=1",
+ "-D__PROTOTYPES=1",
+ "-DSTDC_HEADERS=1",
+ "-DHAVE_SYS_TYPES_H=1",
+ "-DHAVE_SYS_STAT_H=1",
+ "-DHAVE_STDLIB_H=1",
+ "-DHAVE_STRING_H=1",
+ "-DHAVE_MEMORY_H=1",
+ "-DHAVE_STRINGS_H=1",
+ "-DHAVE_INTTYPES_H=1",
+ "-DHAVE_STDINT_H=1",
+ "-DHAVE_UNISTD_H=1",
+ "-DHAVE_STRING_H=1",
+ "-DHAVE_DLFCN_H=1",
+ "-DSTDC_HEADERS=1",
+ "-DMNG_BUILD_SO=1",
+ "-DMNG_SUPPORT_FULL=1",
+ "-DMNG_SUPPORT_READ=1",
+ "-DMNG_SUPPORT_WRITE=1",
+ "-DMNG_SUPPORT_DISPLAY=1",
+ "-DMNG_SUPPORT_DYNAMICMNG=1",
+ "-DMNG_ACCESS_CHUNKS=1",
+ "-DMNG_STORE_CHUNKS=1",
+ "-DMNG_ERROR_TELLTALE=1",
+ "-DHAVE_LIBZ=1",
+ );
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D775FBE50E27F9A900427EA5 /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DPACKAGE_NAME=\\\"\\\"",
+ "-DPACKAGE_TARNAME=\\\"\\\"",
+ "-DPACKAGE_VERSION=\\\"\\\"",
+ "-DPACKAGE_STRING=\\\"\\\"",
+ "-DPACKAGE_BUGREPORT=\\\"\\\"",
+ "-DPACKAGE=\\\"libmng\\\"",
+ "-DVERSION=\\\"1.0.9\\\"",
+ "-DPROTOTYPES=1",
+ "-D__PROTOTYPES=1",
+ "-DSTDC_HEADERS=1",
+ "-DHAVE_SYS_TYPES_H=1",
+ "-DHAVE_SYS_STAT_H=1",
+ "-DHAVE_STDLIB_H=1",
+ "-DHAVE_STRING_H=1",
+ "-DHAVE_MEMORY_H=1",
+ "-DHAVE_STRINGS_H=1",
+ "-DHAVE_INTTYPES_H=1",
+ "-DHAVE_STDINT_H=1",
+ "-DHAVE_UNISTD_H=1",
+ "-DHAVE_STRING_H=1",
+ "-DHAVE_DLFCN_H=1",
+ "-DSTDC_HEADERS=1",
+ "-DMNG_BUILD_SO=1",
+ "-DMNG_SUPPORT_FULL=1",
+ "-DMNG_SUPPORT_READ=1",
+ "-DMNG_SUPPORT_WRITE=1",
+ "-DMNG_SUPPORT_DISPLAY=1",
+ "-DMNG_SUPPORT_DYNAMICMNG=1",
+ "-DMNG_ACCESS_CHUNKS=1",
+ "-DMNG_STORE_CHUNKS=1",
+ "-DMNG_ERROR_TELLTALE=1",
+ "-DHAVE_LIBZ=1",
+ );
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libmng" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libmng" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Source/LibMNG/libmng_callback_xs.c b/Source/LibMNG/libmng_callback_xs.c
new file mode 100644
index 0000000..ff1a22a
--- /dev/null
+++ b/Source/LibMNG/libmng_callback_xs.c
@@ -0,0 +1,1239 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_callback_xs.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : callback get/set interface (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the callback get/set functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - fixed calling convention * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed up punctuation (contribution by Tim Rowley) * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - added getalphaline callback for RGB8_A8 canvasstyle * */
+/* * * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added callbacks for SAVE/SEEK processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added processterm callback * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G. R-P * */
+/* * - added SKIPCHUNK feature * */
+/* * * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * 1.0.7 - 03/19/2004 - G.R-P * */
+/* * - fixed typo (MNG_SKIPCHUNK_SAVE -> MNG_SKIPCHUNK_nEED * */
+/* * * */
+/* * 1.0.8 - 04/10/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * * */
+/* * 1.0.9 - 09/18/2004 - G.R-P. * */
+/* * - added two SKIPCHUNK_TERM conditionals * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Callback set functions * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+mng_retcode MNG_DECL mng_setcb_memalloc (mng_handle hHandle,
+ mng_memalloc fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_MEMALLOC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fMemalloc = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_MEMALLOC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INTERNAL_MEMMNGMT */
+
+/* ************************************************************************** */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+mng_retcode MNG_DECL mng_setcb_memfree (mng_handle hHandle,
+ mng_memfree fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_MEMFREE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fMemfree = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_MEMFREE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INTERNAL_MEMMNGMT */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_setcb_releasedata (mng_handle hHandle,
+ mng_releasedata fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_RELEASEDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fReleasedata = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_RELEASEDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+mng_retcode MNG_DECL mng_setcb_openstream (mng_handle hHandle,
+ mng_openstream fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_OPENSTREAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fOpenstream = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_OPENSTREAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+mng_retcode MNG_DECL mng_setcb_closestream (mng_handle hHandle,
+ mng_closestream fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_CLOSESTREAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fClosestream = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_CLOSESTREAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_setcb_readdata (mng_handle hHandle,
+ mng_readdata fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_READDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fReaddata = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_READDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_setcb_writedata (mng_handle hHandle,
+ mng_writedata fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_WRITEDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fWritedata = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_WRITEDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_setcb_errorproc (mng_handle hHandle,
+ mng_errorproc fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_ERRORPROC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fErrorproc = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_ERRORPROC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_TRACE
+mng_retcode MNG_DECL mng_setcb_traceproc (mng_handle hHandle,
+ mng_traceproc fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_TRACEPROC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fTraceproc = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_TRACEPROC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_TRACE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_setcb_processheader (mng_handle hHandle,
+ mng_processheader fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSHEADER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessheader = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSHEADER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_tEXt
+mng_retcode MNG_DECL mng_setcb_processtext (mng_handle hHandle,
+ mng_processtext fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSTEXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcesstext = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSTEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode MNG_DECL mng_setcb_processsave (mng_handle hHandle,
+ mng_processsave fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSAVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcesssave = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode MNG_DECL mng_setcb_processseek (mng_handle hHandle,
+ mng_processseek fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSEEK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessseek = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_nEED
+mng_retcode MNG_DECL mng_setcb_processneed (mng_handle hHandle,
+ mng_processneed fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSNEED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessneed = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSNEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_setcb_processmend (mng_handle hHandle,
+ mng_processmend fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSMEND, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessmend = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSMEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_setcb_processunknown (mng_handle hHandle,
+ mng_processunknown fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSUNKNOWN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessunknown = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSUNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_TERM
+mng_retcode MNG_DECL mng_setcb_processterm (mng_handle hHandle,
+ mng_processterm fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSTERM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessterm = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSTERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_getcanvasline (mng_handle hHandle,
+ mng_getcanvasline fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETCANVASLINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fGetcanvasline = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETCANVASLINE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_getbkgdline (mng_handle hHandle,
+ mng_getbkgdline fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETBKGDLINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fGetbkgdline = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETBKGDLINE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_getalphaline (mng_handle hHandle,
+ mng_getalphaline fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETALPHALINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fGetalphaline = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETALPHALINE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_refresh (mng_handle hHandle,
+ mng_refresh fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_REFRESH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fRefresh = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_REFRESH, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_gettickcount (mng_handle hHandle,
+ mng_gettickcount fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETTICKCOUNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fGettickcount = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_GETTICKCOUNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_setcb_settimer (mng_handle hHandle,
+ mng_settimer fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_SETTIMER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fSettimer = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_SETTIMER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_retcode MNG_DECL mng_setcb_processgamma (mng_handle hHandle,
+ mng_processgamma fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSGAMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessgamma = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSGAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_retcode MNG_DECL mng_setcb_processchroma (mng_handle hHandle,
+ mng_processchroma fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSCHROMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcesschroma = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSCHROMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_retcode MNG_DECL mng_setcb_processsrgb (mng_handle hHandle,
+ mng_processsrgb fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcesssrgb = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSSRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode MNG_DECL mng_setcb_processiccp (mng_handle hHandle,
+ mng_processiccp fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSICCP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessiccp = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_retcode MNG_DECL mng_setcb_processarow (mng_handle hHandle,
+ mng_processarow fProc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSAROW, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->fProcessarow = fProc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SETCB_PROCESSAROW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+/* * * */
+/* * Callback get functions * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+mng_memalloc MNG_DECL mng_getcb_memalloc (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_MEMALLOC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_MEMALLOC, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fMemalloc;
+}
+#endif /* MNG_INTERNAL_MEMMNGMT */
+
+/* ************************************************************************** */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+mng_memfree MNG_DECL mng_getcb_memfree (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_MEMFREE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_MEMFREE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fMemfree;
+}
+#endif /* MNG_INTERNAL_MEMMNGMT */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_releasedata MNG_DECL mng_getcb_releasedata (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_RELEASEDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_RELEASEDATA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fReleasedata;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_readdata MNG_DECL mng_getcb_readdata (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_READDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_READDATA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fReaddata;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+mng_openstream MNG_DECL mng_getcb_openstream (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_OPENSTREAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_OPENSTREAM, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fOpenstream;
+}
+#endif
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+mng_closestream MNG_DECL mng_getcb_closestream (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_CLOSESTREAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_CLOSESTREAM, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fClosestream;
+}
+#endif
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_writedata MNG_DECL mng_getcb_writedata (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_WRITEDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_WRITEDATA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fWritedata;
+}
+#endif /* MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+mng_errorproc MNG_DECL mng_getcb_errorproc (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_ERRORPROC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_ERRORPROC, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fErrorproc;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_TRACE
+mng_traceproc MNG_DECL mng_getcb_traceproc (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_TRACEPROC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_TRACEPROC, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fTraceproc;
+}
+#endif /* MNG_SUPPORT_TRACE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_processheader MNG_DECL mng_getcb_processheader (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSHEADER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSHEADER, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessheader;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_tEXt
+mng_processtext MNG_DECL mng_getcb_processtext (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSTEXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSTEXT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcesstext;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_processsave MNG_DECL mng_getcb_processsave (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSAVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSAVE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcesssave;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_processseek MNG_DECL mng_getcb_processseek (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSEEK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSEEK, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessseek;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_nEED
+mng_processneed MNG_DECL mng_getcb_processneed (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSNEED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSNEED, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessneed;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_processmend MNG_DECL mng_getcb_processmend (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSMEND, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSMEND, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessmend;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_processunknown MNG_DECL mng_getcb_processunknown (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSUNKNOWN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSUNKNOWN, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessunknown;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+#ifndef MNG_SKIPCHUNK_TERM
+mng_processterm MNG_DECL mng_getcb_processterm (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSTERM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSTERM, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessterm;
+}
+#endif
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_getcanvasline MNG_DECL mng_getcb_getcanvasline (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETCANVASLINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETCANVASLINE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fGetcanvasline;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_getbkgdline MNG_DECL mng_getcb_getbkgdline (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETBKGDLINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETBKGDLINE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fGetbkgdline;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_getalphaline MNG_DECL mng_getcb_getalphaline (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETALPHALINE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETALPHALINE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fGetalphaline;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_refresh MNG_DECL mng_getcb_refresh (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_REFRESH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_REFRESH, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fRefresh;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_gettickcount MNG_DECL mng_getcb_gettickcount (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETTICKCOUNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_GETTICKCOUNT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fGettickcount;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_settimer MNG_DECL mng_getcb_settimer (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_SETTIMER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_SETTIMER, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fSettimer;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_processgamma MNG_DECL mng_getcb_processgamma (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSGAMMA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessgamma;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_processchroma MNG_DECL mng_getcb_processchroma (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSCHROMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSCHROMA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcesschroma;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_processsrgb MNG_DECL mng_getcb_processsrgb (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSSRGB, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcesssrgb;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_processiccp MNG_DECL mng_getcb_processiccp (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSICCP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSICCP, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessiccp;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_APP_CMS)
+mng_processarow MNG_DECL mng_getcb_processarow (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSAROW, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GETCB_PROCESSAROW, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->fProcessarow;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_APP_CMS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
+
diff --git a/Source/LibMNG/libmng_chunk_descr.c b/Source/LibMNG/libmng_chunk_descr.c
new file mode 100644
index 0000000..e1004a5
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_descr.c
@@ -0,0 +1,6090 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_descr.c copyright (c) 2005-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk descriptor functions (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the chunk- anf field-descriptor * */
+/* * routines * */
+/* * * */
+/* * changes : 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - made all constants 'static' * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * 1.0.9 - 01/17/2005 - G.Juyn * */
+/* * - fixed problem with global PLTE/tRNS * */
+/* * * */
+/* * 1.0.10 - 01/17/2005 - G.R-P. * */
+/* * - added typecast to appease the compiler * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include <stddef.h> /* needed for offsetof() */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_objects.h"
+#include "libmng_chunks.h"
+#include "libmng_chunk_descr.h"
+#include "libmng_object_prc.h"
+#include "libmng_chunk_prc.h"
+#include "libmng_chunk_io.h"
+#include "libmng_display.h"
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+#include "libmng_pixels.h"
+#include "libmng_filter.h"
+#endif
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+#if defined(MNG_INCLUDE_READ_PROCS) || defined(MNG_INCLUDE_WRITE_PROCS)
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* PNG chunks */
+
+MNG_LOCAL mng_field_descriptor mng_fields_ihdr [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_NOHIGHBIT,
+ 1, 0, 4, 4,
+ offsetof(mng_ihdr, iWidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_NOHIGHBIT,
+ 1, 0, 4, 4,
+ offsetof(mng_ihdr, iHeight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 16, 1, 1,
+ offsetof(mng_ihdr, iBitdepth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 6, 1, 1,
+ offsetof(mng_ihdr, iColortype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_ihdr, iCompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_ihdr, iFilter), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_ihdr, iInterlace), MNG_NULL, MNG_NULL}
+ };
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_field_descriptor mng_fields_plte [] =
+ {
+ {mng_debunk_plte,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_field_descriptor mng_fields_idat [] =
+ {
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ offsetof(mng_idat, pData), MNG_NULL, offsetof(mng_idat, iDatasize)}
+ };
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_field_descriptor mng_fields_trns [] =
+ {
+ {mng_debunk_trns,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_gAMA
+MNG_LOCAL mng_field_descriptor mng_fields_gama [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_gama, iGamma), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+MNG_LOCAL mng_field_descriptor mng_fields_chrm [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iWhitepointx), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iWhitepointy), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iRedx), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iRedy), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iGreeny), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iGreeny), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iBluex), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_chrm, iBluey), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sRGB
+MNG_LOCAL mng_field_descriptor mng_fields_srgb [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 4, 1, 1,
+ offsetof(mng_srgb, iRenderingintent), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+MNG_LOCAL mng_field_descriptor mng_fields_iccp [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 1, 79,
+ offsetof(mng_iccp, zName), MNG_NULL, offsetof(mng_iccp, iNamesize)},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_iccp, iCompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_DEFLATED,
+ 0, 0, 0, 0,
+ offsetof(mng_iccp, pProfile), MNG_NULL, offsetof(mng_iccp, iProfilesize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+MNG_LOCAL mng_field_descriptor mng_fields_text [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 1, 79,
+ offsetof(mng_text, zKeyword), MNG_NULL, offsetof(mng_text, iKeywordsize)},
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ offsetof(mng_text, zText), MNG_NULL, offsetof(mng_text, iTextsize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+MNG_LOCAL mng_field_descriptor mng_fields_ztxt [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 1, 79,
+ offsetof(mng_ztxt, zKeyword), MNG_NULL, offsetof(mng_ztxt, iKeywordsize)},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_ztxt, iCompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_DEFLATED,
+ 0, 0, 0, 0,
+ offsetof(mng_ztxt, zText), MNG_NULL, offsetof(mng_ztxt, iTextsize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+MNG_LOCAL mng_field_descriptor mng_fields_itxt [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 1, 79,
+ offsetof(mng_itxt, zKeyword), MNG_NULL, offsetof(mng_itxt, iKeywordsize)},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_itxt, iCompressionflag), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_itxt, iCompressionmethod), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 0, 0,
+ offsetof(mng_itxt, zLanguage), MNG_NULL, offsetof(mng_itxt, iLanguagesize)},
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR,
+ 0, 0, 0, 0,
+ offsetof(mng_itxt, zTranslation), MNG_NULL, offsetof(mng_itxt, iTranslationsize)},
+ {mng_deflate_itxt,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+MNG_LOCAL mng_field_descriptor mng_fields_bkgd [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_PUTIMGTYPE,
+ 0, 0, 0, 0,
+ offsetof(mng_bkgd, iType), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE3,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_bkgd, iIndex), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE0 | MNG_FIELD_IFIMGTYPE4,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_bkgd, iGray), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE2 | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_bkgd, iRed), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE2 | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_bkgd, iGreen), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE2 | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_bkgd, iBlue), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+MNG_LOCAL mng_field_descriptor mng_fields_phys [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_phys, iSizex), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_phys, iSizey), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_phys, iUnit), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+MNG_LOCAL mng_field_descriptor mng_fields_sbit [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_PUTIMGTYPE,
+ 0, 0, 0, 0,
+ offsetof(mng_sbit, iType), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPES,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_sbit, aBits[0]), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE2 | MNG_FIELD_IFIMGTYPE3 | MNG_FIELD_IFIMGTYPE4 | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_sbit, aBits[1]), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE2 | MNG_FIELD_IFIMGTYPE3 | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_sbit, aBits[2]), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_IFIMGTYPE6,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_sbit, aBits[3]), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+MNG_LOCAL mng_field_descriptor mng_fields_splt [] =
+ {
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 79,
+ offsetof(mng_splt, zName), MNG_NULL, offsetof(mng_splt, iNamesize)},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 8, 16, 1, 1,
+ offsetof(mng_splt, iSampledepth), MNG_NULL, MNG_NULL},
+ {mng_splt_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+MNG_LOCAL mng_field_descriptor mng_fields_hist [] =
+ {
+ {mng_hist_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+MNG_LOCAL mng_field_descriptor mng_fields_time [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_time, iYear), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 12, 1, 1,
+ offsetof(mng_time, iMonth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 31, 1, 1,
+ offsetof(mng_time, iDay), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 24, 1, 1,
+ offsetof(mng_time, iHour), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 60, 1, 1,
+ offsetof(mng_time, iMinute), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 60, 1, 1,
+ offsetof(mng_time, iSecond), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* JNG chunks */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_field_descriptor mng_fields_jhdr [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_NOHIGHBIT,
+ 1, 0, 4, 4,
+ offsetof(mng_jhdr, iWidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_NOHIGHBIT,
+ 1, 0, 4, 4,
+ offsetof(mng_jhdr, iHeight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 8, 16, 1, 1,
+ offsetof(mng_jhdr, iColortype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 8, 20, 1, 1,
+ offsetof(mng_jhdr, iImagesampledepth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 8, 8, 1, 1,
+ offsetof(mng_jhdr, iImagecompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 8, 1, 1,
+ offsetof(mng_jhdr, iImageinterlace), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 16, 1, 1,
+ offsetof(mng_jhdr, iAlphasampledepth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 8, 1, 1,
+ offsetof(mng_jhdr, iAlphacompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_jhdr, iAlphafilter), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_jhdr, iAlphainterlace), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#define mng_fields_jdaa mng_fields_idat
+#define mng_fields_jdat mng_fields_idat
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* MNG chunks */
+
+MNG_LOCAL mng_field_descriptor mng_fields_mhdr [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iWidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iHeight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iTicks), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iLayercount), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iFramecount), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iPlaytime), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_mhdr, iSimplicity), MNG_NULL, MNG_NULL}
+ };
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_LOCAL mng_field_descriptor mng_fields_loop [] =
+ {
+ {mng_debunk_loop,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_LOCAL mng_field_descriptor mng_fields_endl [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_endl, iLevel), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+MNG_LOCAL mng_field_descriptor mng_fields_defi [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_defi, iObjectid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_defi, iDonotshow), offsetof(mng_defi, bHasdonotshow), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_defi, iConcrete), offsetof(mng_defi, bHasconcrete), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iXlocation), offsetof(mng_defi, bHasloca), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iYlocation), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iLeftcb), offsetof(mng_defi, bHasclip), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iRightcb), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iTopcb), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_defi, iBottomcb), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+MNG_LOCAL mng_field_descriptor mng_fields_basi [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_basi, iWidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_basi, iHeight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 16, 1, 1,
+ offsetof(mng_basi, iBitdepth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 6, 1, 1,
+ offsetof(mng_basi, iColortype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_basi, iCompression), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_basi, iFilter), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_basi, iInterlace), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_basi, iRed), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_basi, iGreen), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_basi, iBlue), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_basi, iAlpha), offsetof(mng_basi, bHasalpha), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 1, 1, 1,
+ offsetof(mng_basi, iViewable), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+MNG_LOCAL mng_field_descriptor mng_fields_clon [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_clon, iSourceid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_clon, iCloneid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 2, 1, 1,
+ offsetof(mng_clon, iClonetype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 1, 1, 1,
+ offsetof(mng_clon, iDonotshow), offsetof(mng_clon, bHasdonotshow), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 1, 1, 1,
+ offsetof(mng_clon, iConcrete), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 2, 1, 1,
+ offsetof(mng_clon, iLocationtype), offsetof(mng_clon, bHasloca), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_clon, iLocationx), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_clon, iLocationy), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_LOCAL mng_field_descriptor mng_fields_past [] =
+ {
+ {mng_debunk_past,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+MNG_LOCAL mng_field_descriptor mng_fields_disc [] =
+ {
+ {mng_disc_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+MNG_LOCAL mng_field_descriptor mng_fields_back [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_back, iRed), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_back, iGreen), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_back, iBlue), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 3, 1, 1,
+ offsetof(mng_back, iMandatory), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_back, iImageid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 1, 1, 1,
+ offsetof(mng_back, iTile), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+MNG_LOCAL mng_field_descriptor mng_fields_fram [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 4, 1, 1,
+ offsetof(mng_fram, iMode), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_TERMINATOR | MNG_FIELD_OPTIONAL,
+ 0, 0, 1, 79,
+ offsetof(mng_fram, zName), MNG_NULL, offsetof(mng_fram, iNamesize)},
+ {mng_fram_remainder,
+ MNG_FIELD_OPTIONAL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+MNG_LOCAL mng_field_descriptor mng_fields_move [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_move, iFirstid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_move, iLastid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_move, iMovetype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_move, iMovex), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_move, iMovey), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+MNG_LOCAL mng_field_descriptor mng_fields_clip [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_clip, iFirstid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_clip, iLastid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_clip, iCliptype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_clip, iClipl), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_clip, iClipr), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_clip, iClipt), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_clip, iClipb), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+MNG_LOCAL mng_field_descriptor mng_fields_show [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0xFFFF, 2, 2,
+ offsetof(mng_show, iFirstid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 1, 0xFFFF, 2, 2,
+ offsetof(mng_show, iLastid), offsetof(mng_show, bHaslastid), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL,
+ 0, 7, 1, 1,
+ offsetof(mng_show, iMode), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+MNG_LOCAL mng_field_descriptor mng_fields_term [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 3, 1, 1,
+ offsetof(mng_term, iTermaction), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 2, 1, 1,
+ offsetof(mng_term, iIteraction), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_term, iDelay), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_term, iItermax), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_LOCAL mng_field_descriptor mng_fields_save [] =
+ {
+ {mng_save_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+MNG_LOCAL mng_field_descriptor mng_fields_seek [] =
+ {
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 79,
+ offsetof(mng_seek, zName), MNG_NULL, offsetof(mng_seek, iNamesize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+MNG_LOCAL mng_field_descriptor mng_fields_expi [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_expi, iSnapshotid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 79,
+ offsetof(mng_expi, zName), MNG_NULL, offsetof(mng_expi, iNamesize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+MNG_LOCAL mng_field_descriptor mng_fields_fpri [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_fpri, iDeltatype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFF, 1, 1,
+ offsetof(mng_fpri, iPriority), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+MNG_LOCAL mng_field_descriptor mng_fields_need [] =
+ {
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 0,
+ offsetof(mng_need, zKeywords), MNG_NULL, offsetof(mng_need, iKeywordssize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+#define mng_fields_phyg mng_fields_phys
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_field_descriptor mng_fields_dhdr [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_dhdr, iObjectid), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 2, 1, 1,
+ offsetof(mng_dhdr, iImagetype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 7, 1, 1,
+ offsetof(mng_dhdr, iDeltatype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_dhdr, iBlockwidth), offsetof(mng_dhdr, bHasblocksize), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP1,
+ 0, 0, 4, 4,
+ offsetof(mng_dhdr, iBlockheight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_dhdr, iBlockx), offsetof(mng_dhdr, bHasblockloc), MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT | MNG_FIELD_OPTIONAL | MNG_FIELD_GROUP2,
+ 0, 0, 4, 4,
+ offsetof(mng_dhdr, iBlocky), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_field_descriptor mng_fields_prom [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 14, 1, 1,
+ offsetof(mng_prom, iColortype), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 16, 1, 1,
+ offsetof(mng_prom, iSampledepth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_prom, iFilltype), MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_field_descriptor mng_fields_pplt [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 5, 1, 1,
+ offsetof(mng_pplt, iDeltatype), MNG_NULL, MNG_NULL},
+ {mng_pplt_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_field_descriptor mng_fields_drop [] =
+ {
+ {mng_drop_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+MNG_LOCAL mng_field_descriptor mng_fields_dbyk [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_dbyk, iChunkname), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_dbyk, iPolarity), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 0,
+ offsetof(mng_dbyk, zKeywords), MNG_NULL, offsetof(mng_dbyk, iKeywordssize)}
+ };
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+MNG_LOCAL mng_field_descriptor mng_fields_ordr [] =
+ {
+ {mng_drop_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+MNG_LOCAL mng_field_descriptor mng_fields_magn [] =
+ {
+ {mng_debunk_magn,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_LOCAL mng_field_descriptor mng_fields_mpng [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0, 4, 4,
+ offsetof(mng_mpng, iFramewidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0, 4, 4,
+ offsetof(mng_mpng, iFrameheight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0xFFFF, 2, 2,
+ offsetof(mng_mpng, iNumplays), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0xFFFF, 2, 2,
+ offsetof(mng_mpng, iTickspersec), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 1, 1,
+ offsetof(mng_mpng, iCompressionmethod), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_DEFLATED,
+ 0, 0, 1, 0,
+ offsetof(mng_mpng, pFrames), MNG_NULL, offsetof(mng_mpng, iFramessize)}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+MNG_LOCAL mng_field_descriptor mng_fields_ahdr [] =
+ {
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0, 4, 4,
+ offsetof(mng_ahdr, iNumframes), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_ahdr, iTickspersec), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 0, 4, 4,
+ offsetof(mng_ahdr, iNumplays), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0, 4, 4,
+ offsetof(mng_ahdr, iTilewidth), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 1, 0, 4, 4,
+ offsetof(mng_ahdr, iTileheight), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_ahdr, iInterlace), MNG_NULL, MNG_NULL},
+ {MNG_NULL,
+ MNG_FIELD_INT,
+ 0, 1, 1, 1,
+ offsetof(mng_ahdr, iStillused), MNG_NULL, MNG_NULL}
+ };
+
+MNG_LOCAL mng_field_descriptor mng_fields_adat [] =
+ {
+ {mng_adat_tiles,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+MNG_LOCAL mng_field_descriptor mng_fields_evnt [] =
+ {
+ {mng_evnt_entries,
+ MNG_NULL,
+ 0, 0, 0, 0,
+ MNG_NULL, MNG_NULL, MNG_NULL}
+ };
+#endif
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_field_descriptor mng_fields_unknown [] =
+ {
+ {MNG_NULL,
+ MNG_NULL,
+ 0, 0, 1, 0,
+ offsetof(mng_unknown_chunk, pData), MNG_NULL, offsetof(mng_unknown_chunk, iDatasize)}
+ };
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* PNG chunks */
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ihdr =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ihdr,
+ mng_fields_ihdr, (sizeof(mng_fields_ihdr) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL,
+ MNG_NULL,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOJHDR | MNG_DESCR_NOBASI | MNG_DESCR_NOIDAT | MNG_DESCR_NOPLTE};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_plte =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_plte, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_plte,
+ mng_fields_plte, (sizeof(mng_fields_plte) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_idat =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_idat, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_idat,
+ mng_fields_idat, (sizeof(mng_fields_idat) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOJSEP};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_iend =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_iend,
+ MNG_NULL, 0,
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_GenHDR,
+ MNG_NULL};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_trns =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_trns, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_trns,
+ mng_fields_trns, (sizeof(mng_fields_trns) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+
+#ifndef MNG_SKIPCHUNK_gAMA
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_gama =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_gama, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_gama,
+ mng_fields_gama, (sizeof(mng_fields_gama) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOPLTE | MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_cHRM
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_chrm =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_chrm, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_chrm,
+ mng_fields_chrm, (sizeof(mng_fields_chrm) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOPLTE | MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_sRGB
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_srgb =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_srgb, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_srgb,
+ mng_fields_srgb, (sizeof(mng_fields_srgb) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOPLTE | MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_iCCP
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_iccp =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_iccp, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_iccp,
+ mng_fields_iccp, (sizeof(mng_fields_iccp) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOPLTE | MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_tEXt
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_text =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_text,
+ mng_fields_text, (sizeof(mng_fields_text) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_SKIPCHUNK_zTXt
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ztxt =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ztxt,
+ mng_fields_ztxt, (sizeof(mng_fields_ztxt) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_SKIPCHUNK_iTXt
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_itxt =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_itxt,
+ mng_fields_itxt, (sizeof(mng_fields_itxt) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_bkgd =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_bkgd, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_bkgd,
+ mng_fields_bkgd, (sizeof(mng_fields_bkgd) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_pHYs
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_phys =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_phys, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_phys,
+ mng_fields_phys, (sizeof(mng_fields_phys) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_sBIT
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_sbit =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_sbit, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_sbit,
+ mng_fields_sbit, (sizeof(mng_fields_sbit) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_sPLT
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_splt =
+ {mng_it_png, mng_create_none, 0, offsetof(mng_splt, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_splt,
+ mng_fields_splt, (sizeof(mng_fields_splt) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL | MNG_DESCR_EMPTYEMBED | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_hIST
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_hist =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_hist,
+ mng_fields_hist, (sizeof(mng_fields_hist) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_GenHDR | MNG_DESCR_PLTE,
+ MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT | MNG_DESCR_NOJDAA};
+#endif
+
+#ifndef MNG_SKIPCHUNK_tIME
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_time =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_time,
+ mng_fields_time, (sizeof(mng_fields_time) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_GLOBAL,
+ MNG_DESCR_GenHDR,
+ MNG_NULL};
+#endif
+
+/* ************************************************************************** */
+/* JNG chunks */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_jhdr =
+ {mng_it_jng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_jhdr,
+ mng_fields_jhdr, (sizeof(mng_fields_jhdr) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_NULL,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_jdaa =
+ {mng_it_jng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_jdaa,
+ mng_fields_jdaa, (sizeof(mng_fields_jdaa) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_JngHDR,
+ MNG_DESCR_NOJSEP};
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_jdat =
+ {mng_it_jng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_jdat,
+ mng_fields_jdat, (sizeof(mng_fields_jdat) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_JngHDR,
+ MNG_NULL};
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_jsep =
+ {mng_it_jng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_jsep,
+ MNG_NULL, 0,
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_JngHDR,
+ MNG_DESCR_NOJSEP};
+#endif
+
+/* ************************************************************************** */
+/* MNG chunks */
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_mhdr =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_mhdr,
+ mng_fields_mhdr, (sizeof(mng_fields_mhdr) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_NULL,
+ MNG_DESCR_NOMHDR | MNG_DESCR_NOIHDR | MNG_DESCR_NOJHDR};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_mend =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_mend,
+ MNG_NULL, 0,
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_MHDR,
+ MNG_NULL};
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_loop =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_loop,
+ mng_fields_loop, (sizeof(mng_fields_loop) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_endl =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_endl,
+ mng_fields_endl, (sizeof(mng_fields_endl) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_DEFI
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_defi =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_defi,
+ mng_fields_defi, (sizeof(mng_fields_defi) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_BASI
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_basi =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_basi,
+ mng_fields_basi, (sizeof(mng_fields_basi) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_CLON
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_clon =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_clon,
+ mng_fields_clon, (sizeof(mng_fields_clon) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_past =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_past,
+ mng_fields_past, (sizeof(mng_fields_past) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_DISC
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_disc =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_disc,
+ mng_fields_disc, (sizeof(mng_fields_disc) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_BACK
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_back =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_back,
+ mng_fields_back, (sizeof(mng_fields_back) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_fram =
+ {mng_it_mng, mng_create_none, 0, offsetof(mng_fram, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_fram,
+ mng_fields_fram, (sizeof(mng_fields_fram) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_MOVE
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_move =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_move,
+ mng_fields_move, (sizeof(mng_fields_move) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_CLIP
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_clip =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_clip,
+ mng_fields_clip, (sizeof(mng_fields_clip) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_SHOW
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_show =
+ {mng_it_mng, mng_create_none, 0, offsetof(mng_show, bEmpty),
+ MNG_NULL, MNG_NULL, mng_special_show,
+ mng_fields_show, (sizeof(mng_fields_show) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_TERM
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_term =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_term,
+ mng_fields_term, (sizeof(mng_fields_term) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR | MNG_DESCR_NOTERM | MNG_DESCR_NOLOOP};
+#endif
+
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_save =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_save,
+ mng_fields_save, (sizeof(mng_fields_save) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOSAVE | MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_SEEK
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_seek =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_seek,
+ mng_fields_seek, (sizeof(mng_fields_seek) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYGLOBAL,
+ MNG_DESCR_MHDR | MNG_DESCR_SAVE,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_eXPI
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_expi =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_expi,
+ mng_fields_expi, (sizeof(mng_fields_expi) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_fPRI
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_fpri =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_fpri,
+ mng_fields_fpri, (sizeof(mng_fields_fpri) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_nEED
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_need =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_need,
+ mng_fields_need, (sizeof(mng_fields_need) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_pHYg
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_phyg =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_phyg,
+ mng_fields_phyg, (sizeof(mng_fields_phyg) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_dhdr =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_dhdr,
+ mng_fields_dhdr, (sizeof(mng_fields_dhdr) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_prom =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_prom,
+ mng_fields_prom, (sizeof(mng_fields_prom) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ipng =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ipng,
+ MNG_NULL, 0,
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_pplt =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_pplt,
+ mng_fields_pplt, (sizeof(mng_fields_pplt) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ijng =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ijng,
+ MNG_NULL, 0,
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_drop =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_drop,
+ mng_fields_drop, (sizeof(mng_fields_drop) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_dbyk =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_dbyk,
+ mng_fields_dbyk, (sizeof(mng_fields_dbyk) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ordr =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ordr,
+ mng_fields_ordr, (sizeof(mng_fields_ordr) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR | MNG_DESCR_DHDR,
+ MNG_NULL};
+#endif
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_magn =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_magn,
+ mng_fields_magn, (sizeof(mng_fields_magn) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOIHDR | MNG_DESCR_NOBASI | MNG_DESCR_NODHDR | MNG_DESCR_NOJHDR};
+#endif
+
+#ifndef MNG_SKIPCHUNK_evNT
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_evnt =
+ {mng_it_mng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_evnt,
+ mng_fields_evnt, (sizeof(mng_fields_evnt) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_MHDR,
+ MNG_DESCR_NOSAVE};
+#endif
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_mpng =
+ {mng_it_mpng, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_mpng,
+ mng_fields_mpng, (sizeof(mng_fields_mpng) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_NULL,
+ MNG_DESCR_NOMHDR | MNG_DESCR_NOIDAT | MNG_DESCR_NOJDAT};
+#endif
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_ahdr =
+ {mng_it_ang, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_ahdr,
+ mng_fields_ahdr, (sizeof(mng_fields_ahdr) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_IHDR,
+ MNG_DESCR_NOMHDR | MNG_DESCR_NOJHDR | MNG_DESCR_NOIDAT};
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_adat =
+ {mng_it_ang, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_adat,
+ mng_fields_adat, (sizeof(mng_fields_adat) / sizeof(mng_field_descriptor)),
+ MNG_NULL,
+ MNG_DESCR_IHDR,
+ MNG_DESCR_NOMHDR | MNG_DESCR_NOJHDR};
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* the good ol' unknown babe */
+
+MNG_LOCAL mng_chunk_descriptor mng_chunk_descr_unknown =
+ {mng_it_png, mng_create_none, 0, 0,
+ MNG_NULL, MNG_NULL, mng_special_unknown,
+ mng_fields_unknown, (sizeof(mng_fields_unknown) / sizeof(mng_field_descriptor)),
+ MNG_DESCR_EMPTY | MNG_DESCR_EMPTYEMBED,
+ MNG_NULL,
+ MNG_NULL};
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+MNG_LOCAL mng_chunk_header mng_chunk_unknown =
+ {MNG_UINT_HUH, mng_init_general, mng_free_unknown,
+ mng_read_general, mng_write_unknown, mng_assign_unknown,
+ 0, 0, sizeof(mng_unknown_chunk), &mng_chunk_descr_unknown};
+
+/* ************************************************************************** */
+
+ /* the table-idea & binary search code was adapted from
+ libpng 1.1.0 (pngread.c) */
+ /* NOTE1: the table must remain sorted by chunkname, otherwise the binary
+ search will break !!! (ps. watch upper-/lower-case chunknames !!) */
+ /* NOTE2: the layout must remain equal to the header part of all the
+ chunk-structures (yes, that means even the pNext and pPrev fields;
+ it's wasting a bit of space, but hey, the code is a lot easier) */
+
+MNG_LOCAL mng_chunk_header mng_chunk_table [] =
+ {
+#ifndef MNG_SKIPCHUNK_BACK
+ {MNG_UINT_BACK, mng_init_general, mng_free_general, mng_read_general, mng_write_back, mng_assign_general, 0, 0, sizeof(mng_back), &mng_chunk_descr_back},
+#endif
+#ifndef MNG_SKIPCHUNK_BASI
+ {MNG_UINT_BASI, mng_init_general, mng_free_general, mng_read_general, mng_write_basi, mng_assign_general, 0, 0, sizeof(mng_basi), &mng_chunk_descr_basi},
+#endif
+#ifndef MNG_SKIPCHUNK_CLIP
+ {MNG_UINT_CLIP, mng_init_general, mng_free_general, mng_read_general, mng_write_clip, mng_assign_general, 0, 0, sizeof(mng_clip), &mng_chunk_descr_clip},
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ {MNG_UINT_CLON, mng_init_general, mng_free_general, mng_read_general, mng_write_clon, mng_assign_general, 0, 0, sizeof(mng_clon), &mng_chunk_descr_clon},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+ {MNG_UINT_DBYK, mng_init_general, mng_free_dbyk, mng_read_general, mng_write_dbyk, mng_assign_dbyk, 0, 0, sizeof(mng_dbyk), &mng_chunk_descr_dbyk},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_DEFI
+ {MNG_UINT_DEFI, mng_init_general, mng_free_general, mng_read_general, mng_write_defi, mng_assign_general, 0, 0, sizeof(mng_defi), &mng_chunk_descr_defi},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_DHDR, mng_init_general, mng_free_general, mng_read_general, mng_write_dhdr, mng_assign_general, 0, 0, sizeof(mng_dhdr), &mng_chunk_descr_dhdr},
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+ {MNG_UINT_DISC, mng_init_general, mng_free_disc, mng_read_general, mng_write_disc, mng_assign_disc, 0, 0, sizeof(mng_disc), &mng_chunk_descr_disc},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DROP
+ {MNG_UINT_DROP, mng_init_general, mng_free_drop, mng_read_general, mng_write_drop, mng_assign_drop, 0, 0, sizeof(mng_drop), &mng_chunk_descr_drop},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_ENDL, mng_init_general, mng_free_general, mng_read_general, mng_write_endl, mng_assign_general, 0, 0, sizeof(mng_endl), &mng_chunk_descr_endl},
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+ {MNG_UINT_FRAM, mng_init_general, mng_free_fram, mng_read_general, mng_write_fram, mng_assign_fram, 0, 0, sizeof(mng_fram), &mng_chunk_descr_fram},
+#endif
+ {MNG_UINT_IDAT, mng_init_general, mng_free_idat, mng_read_general, mng_write_idat, mng_assign_idat, 0, 0, sizeof(mng_idat), &mng_chunk_descr_idat}, /* 12-th element! */
+ {MNG_UINT_IEND, mng_init_general, mng_free_general, mng_read_general, mng_write_iend, mng_assign_general, 0, 0, sizeof(mng_iend), &mng_chunk_descr_iend},
+ {MNG_UINT_IHDR, mng_init_general, mng_free_general, mng_read_general, mng_write_ihdr, mng_assign_general, 0, 0, sizeof(mng_ihdr), &mng_chunk_descr_ihdr},
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_IJNG, mng_init_general, mng_free_general, mng_read_general, mng_write_ijng, mng_assign_general, 0, 0, sizeof(mng_ijng), &mng_chunk_descr_ijng},
+#endif
+ {MNG_UINT_IPNG, mng_init_general, mng_free_general, mng_read_general, mng_write_ipng, mng_assign_general, 0, 0, sizeof(mng_ipng), &mng_chunk_descr_ipng},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_JDAA, mng_init_general, mng_free_jdaa, mng_read_general, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa), &mng_chunk_descr_jdaa},
+ {MNG_UINT_JDAT, mng_init_general, mng_free_jdat, mng_read_general, mng_write_jdat, mng_assign_jdat, 0, 0, sizeof(mng_jdat), &mng_chunk_descr_jdat},
+ {MNG_UINT_JHDR, mng_init_general, mng_free_general, mng_read_general, mng_write_jhdr, mng_assign_general, 0, 0, sizeof(mng_jhdr), &mng_chunk_descr_jhdr},
+ {MNG_UINT_JSEP, mng_init_general, mng_free_general, mng_read_general, mng_write_jsep, mng_assign_general, 0, 0, sizeof(mng_jsep), &mng_chunk_descr_jsep},
+ {MNG_UINT_JdAA, mng_init_general, mng_free_jdaa, mng_read_general, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa), &mng_chunk_descr_jdaa},
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_LOOP, mng_init_general, mng_free_loop, mng_read_general, mng_write_loop, mng_assign_loop, 0, 0, sizeof(mng_loop), &mng_chunk_descr_loop},
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+ {MNG_UINT_MAGN, mng_init_general, mng_free_general, mng_read_general, mng_write_magn, mng_assign_general, 0, 0, sizeof(mng_magn), &mng_chunk_descr_magn},
+#endif
+ {MNG_UINT_MEND, mng_init_general, mng_free_general, mng_read_general, mng_write_mend, mng_assign_general, 0, 0, sizeof(mng_mend), &mng_chunk_descr_mend},
+ {MNG_UINT_MHDR, mng_init_general, mng_free_general, mng_read_general, mng_write_mhdr, mng_assign_general, 0, 0, sizeof(mng_mhdr), &mng_chunk_descr_mhdr},
+#ifndef MNG_SKIPCHUNK_MOVE
+ {MNG_UINT_MOVE, mng_init_general, mng_free_general, mng_read_general, mng_write_move, mng_assign_general, 0, 0, sizeof(mng_move), &mng_chunk_descr_move},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_UINT_ORDR, mng_init_general, mng_free_ordr, mng_read_general, mng_write_ordr, mng_assign_ordr, 0, 0, sizeof(mng_ordr), &mng_chunk_descr_ordr},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_UINT_PAST, mng_init_general, mng_free_past, mng_read_general, mng_write_past, mng_assign_past, 0, 0, sizeof(mng_past), &mng_chunk_descr_past},
+#endif
+ {MNG_UINT_PLTE, mng_init_general, mng_free_general, mng_read_general, mng_write_plte, mng_assign_general, 0, 0, sizeof(mng_plte), &mng_chunk_descr_plte},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_PPLT, mng_init_general, mng_free_general, mng_read_general, mng_write_pplt, mng_assign_general, 0, 0, sizeof(mng_pplt), &mng_chunk_descr_pplt},
+ {MNG_UINT_PROM, mng_init_general, mng_free_general, mng_read_general, mng_write_prom, mng_assign_general, 0, 0, sizeof(mng_prom), &mng_chunk_descr_prom},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_UINT_SAVE, mng_init_general, mng_free_save, mng_read_general, mng_write_save, mng_assign_save, 0, 0, sizeof(mng_save), &mng_chunk_descr_save},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {MNG_UINT_SEEK, mng_init_general, mng_free_seek, mng_read_general, mng_write_seek, mng_assign_seek, 0, 0, sizeof(mng_seek), &mng_chunk_descr_seek},
+#endif
+#ifndef MNG_SKIPCHUNK_SHOW
+ {MNG_UINT_SHOW, mng_init_general, mng_free_general, mng_read_general, mng_write_show, mng_assign_general, 0, 0, sizeof(mng_show), &mng_chunk_descr_show},
+#endif
+#ifndef MNG_SKIPCHUNK_TERM
+ {MNG_UINT_TERM, mng_init_general, mng_free_general, mng_read_general, mng_write_term, mng_assign_general, 0, 0, sizeof(mng_term), &mng_chunk_descr_term},
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ {MNG_UINT_adAT, mng_init_general, mng_free_adat, mng_read_general, mng_write_adat, mng_assign_adat, 0, 0, sizeof(mng_adat), &mng_chunk_descr_adat},
+ {MNG_UINT_ahDR, mng_init_general, mng_free_general, mng_read_general, mng_write_ahdr, mng_assign_ahdr, 0, 0, sizeof(mng_ahdr), &mng_chunk_descr_ahdr},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {MNG_UINT_bKGD, mng_init_general, mng_free_general, mng_read_general, mng_write_bkgd, mng_assign_general, 0, 0, sizeof(mng_bkgd), &mng_chunk_descr_bkgd},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {MNG_UINT_cHRM, mng_init_general, mng_free_general, mng_read_general, mng_write_chrm, mng_assign_general, 0, 0, sizeof(mng_chrm), &mng_chunk_descr_chrm},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {MNG_UINT_eXPI, mng_init_general, mng_free_expi, mng_read_general, mng_write_expi, mng_assign_expi, 0, 0, sizeof(mng_expi), &mng_chunk_descr_expi},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_UINT_evNT, mng_init_general, mng_free_evnt, mng_read_general, mng_write_evnt, mng_assign_evnt, 0, 0, sizeof(mng_evnt), &mng_chunk_descr_evnt},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {MNG_UINT_fPRI, mng_init_general, mng_free_general, mng_read_general, mng_write_fpri, mng_assign_general, 0, 0, sizeof(mng_fpri), &mng_chunk_descr_fpri},
+#endif
+#ifndef MNG_SKIPCHUNK_gAMA
+ {MNG_UINT_gAMA, mng_init_general, mng_free_general, mng_read_general, mng_write_gama, mng_assign_general, 0, 0, sizeof(mng_gama), &mng_chunk_descr_gama},
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+ {MNG_UINT_hIST, mng_init_general, mng_free_general, mng_read_general, mng_write_hist, mng_assign_general, 0, 0, sizeof(mng_hist), &mng_chunk_descr_hist},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {MNG_UINT_iCCP, mng_init_general, mng_free_iccp, mng_read_general, mng_write_iccp, mng_assign_iccp, 0, 0, sizeof(mng_iccp), &mng_chunk_descr_iccp},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {MNG_UINT_iTXt, mng_init_general, mng_free_itxt, mng_read_general, mng_write_itxt, mng_assign_itxt, 0, 0, sizeof(mng_itxt), &mng_chunk_descr_itxt},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_UINT_mpNG, mng_init_general, mng_free_mpng, mng_read_general, mng_write_mpng, mng_assign_mpng, 0, 0, sizeof(mng_mpng), &mng_chunk_descr_mpng},
+#endif
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_UINT_nEED, mng_init_general, mng_free_need, mng_read_general, mng_write_need, mng_assign_need, 0, 0, sizeof(mng_need), &mng_chunk_descr_need},
+#endif
+/* TODO: {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0}, */
+/* TODO: {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_pHYg
+ {MNG_UINT_pHYg, mng_init_general, mng_free_general, mng_read_general, mng_write_phyg, mng_assign_general, 0, 0, sizeof(mng_phyg), &mng_chunk_descr_phyg},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {MNG_UINT_pHYs, mng_init_general, mng_free_general, mng_read_general, mng_write_phys, mng_assign_general, 0, 0, sizeof(mng_phys), &mng_chunk_descr_phys},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {MNG_UINT_sBIT, mng_init_general, mng_free_general, mng_read_general, mng_write_sbit, mng_assign_general, 0, 0, sizeof(mng_sbit), &mng_chunk_descr_sbit},
+#endif
+/* TODO: {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_sPLT
+ {MNG_UINT_sPLT, mng_init_general, mng_free_splt, mng_read_general, mng_write_splt, mng_assign_splt, 0, 0, sizeof(mng_splt), &mng_chunk_descr_splt},
+#endif
+ {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_general, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb), &mng_chunk_descr_srgb},
+#ifndef MNG_SKIPCHUNK_tEXt
+ {MNG_UINT_tEXt, mng_init_general, mng_free_text, mng_read_general, mng_write_text, mng_assign_text, 0, 0, sizeof(mng_text), &mng_chunk_descr_text},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {MNG_UINT_tIME, mng_init_general, mng_free_general, mng_read_general, mng_write_time, mng_assign_general, 0, 0, sizeof(mng_time), &mng_chunk_descr_time},
+#endif
+ {MNG_UINT_tRNS, mng_init_general, mng_free_general, mng_read_general, mng_write_trns, mng_assign_general, 0, 0, sizeof(mng_trns), &mng_chunk_descr_trns},
+#ifndef MNG_SKIPCHUNK_zTXt
+ {MNG_UINT_zTXt, mng_init_general, mng_free_ztxt, mng_read_general, mng_write_ztxt, mng_assign_ztxt, 0, 0, sizeof(mng_ztxt), &mng_chunk_descr_ztxt},
+#endif
+ };
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+void mng_get_chunkheader (mng_chunkid iChunkname,
+ mng_chunk_headerp pResult)
+{
+ /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ mng_chunk_headerp pEntry; /* pointer to found entry */
+ /* determine max index of table */
+ iTop = (sizeof (mng_chunk_table) / sizeof (mng_chunk_table [0])) - 1;
+
+ /* binary search; with 54 chunks, worst-case is 7 comparisons */
+ iLower = 0;
+#ifndef MNG_NO_DELTA_PNG
+ iMiddle = 11; /* start with the IDAT entry */
+#else
+ iMiddle = 8;
+#endif
+ iUpper = iTop;
+ pEntry = 0; /* no goods yet! */
+
+ do /* the binary search itself */
+ {
+ if (mng_chunk_table [iMiddle].iChunkname < iChunkname)
+ iLower = iMiddle + 1;
+ else if (mng_chunk_table [iMiddle].iChunkname > iChunkname)
+ iUpper = iMiddle - 1;
+ else
+ {
+ pEntry = &mng_chunk_table [iMiddle];
+ break;
+ }
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+
+ if (!pEntry) /* unknown chunk ? */
+ pEntry = &mng_chunk_unknown; /* make it so! */
+
+ MNG_COPY (pResult, pEntry, sizeof(mng_chunk_header));
+
+ return;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* PNG chunks */
+
+MNG_C_SPECIALFUNC (mng_special_ihdr)
+{
+ pData->bHasIHDR = MNG_TRUE; /* indicate IHDR is present */
+ /* and store interesting fields */
+ if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_NOCHANGE))
+ {
+ pData->iDatawidth = ((mng_ihdrp)pChunk)->iWidth;
+ pData->iDataheight = ((mng_ihdrp)pChunk)->iHeight;
+ }
+
+ pData->iBitdepth = ((mng_ihdrp)pChunk)->iBitdepth;
+ pData->iColortype = ((mng_ihdrp)pChunk)->iColortype;
+ pData->iCompression = ((mng_ihdrp)pChunk)->iCompression;
+ pData->iFilter = ((mng_ihdrp)pChunk)->iFilter;
+ pData->iInterlace = ((mng_ihdrp)pChunk)->iInterlace;
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iBitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iBitdepth < 8)
+ pData->iBitdepth = 8;
+#endif
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth > 8)
+ {
+ pData->iBitdepth = 8;
+ pData->iPNGmult = 2;
+ }
+#endif
+
+ if ((pData->iBitdepth != 8) /* parameter validity checks */
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iBitdepth != 1) &&
+ (pData->iBitdepth != 2) &&
+ (pData->iBitdepth != 4)
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iBitdepth != 16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
+ (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
+ (pData->iBitdepth < 8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iFilter != MNG_FILTER_DIFFERING) &&
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iFilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iFilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
+ (pData->iInterlace != MNG_INTERLACE_ADAM7) )
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* check the colortype for delta-images ! */
+ {
+ mng_imagedatap pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+
+ if (pData->iColortype != pBuf->iColortype)
+ {
+ if ( ( (pData->iColortype != MNG_COLORTYPE_INDEXED) ||
+ (pBuf->iColortype == MNG_COLORTYPE_GRAY ) ) &&
+ ( (pData->iColortype != MNG_COLORTYPE_GRAY ) ||
+ (pBuf->iColortype == MNG_COLORTYPE_INDEXED) ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+ }
+ }
+#endif
+#endif
+
+ if (!pData->bHasheader) /* first chunk ? */
+ {
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_png; /* then this must be a PNG */
+ pData->iWidth = pData->iDatawidth;
+ pData->iHeight = pData->iDataheight;
+ /* predict alpha-depth ! */
+ if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) )
+ pData->iAlphadepth = pData->iBitdepth;
+ else
+ if (pData->iColortype == MNG_COLORTYPE_INDEXED)
+ pData->iAlphadepth = 8; /* worst case scenario */
+ else
+ pData->iAlphadepth = 1; /* Possible tRNS cheap binary transparency */
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+#if !defined(MNG_INCLUDE_MPNG_PROPOSAL) || !defined(MNG_SUPPORT_DISPLAY)
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+#endif
+ }
+
+ if (!pData->bHasDHDR)
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_process_display_ihdr (pData);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+
+/* ************************************************************************** */
+
+MNG_F_SPECIALFUNC (mng_debunk_plte)
+{
+ mng_pltep pPLTE = (mng_pltep)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ /* length must be multiple of 3 */
+ if (((iRawlen % 3) != 0) || (iRawlen > 768))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ /* this is the exact length */
+ pPLTE->iEntrycount = iRawlen / 3;
+
+ MNG_COPY (pPLTE->aEntries, pRawdata, iRawlen);
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_plte)
+{ /* multiple PLTE only inside BASI */
+ if ((pData->bHasPLTE) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_MULTIPLEERROR);
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* only allowed for indexed-color or
+ rgb(a)-color! */
+ if ((pData->iColortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (pData->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+ /* empty only allowed if global present */
+ if ((((mng_pltep)pChunk)->bEmpty) && (!pData->bHasglobalPLTE))
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+ else
+ {
+ if (((mng_pltep)pChunk)->bEmpty) /* cannot be empty as global! */
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ pData->bHasPLTE = MNG_TRUE; /* got it! */
+ else
+ pData->bHasglobalPLTE = MNG_TRUE;
+
+ pData->iPLTEcount = ((mng_pltep)pChunk)->iEntrycount;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ { /* store in object 0 !!! */
+ pImage = (mng_imagep)pData->pObjzero;
+ pBuf = pImage->pImgbuf;
+ pBuf->bHasPLTE = MNG_TRUE; /* it's definitely got a PLTE now */
+ pBuf->iPLTEcount = ((mng_pltep)pChunk)->iEntrycount;
+ MNG_COPY (pBuf->aPLTEentries, ((mng_pltep)pChunk)->aEntries,
+ sizeof (pBuf->aPLTEentries));
+ }
+ else
+#endif
+ { /* get the current object */
+ pImage = (mng_imagep)pData->pCurrentobj;
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address the object buffer */
+ pBuf->bHasPLTE = MNG_TRUE; /* and tell it it's got a PLTE now */
+
+ if (((mng_pltep)pChunk)->bEmpty) /* if empty, inherit from global */
+ {
+ pBuf->iPLTEcount = pData->iGlobalPLTEcount;
+ MNG_COPY (pBuf->aPLTEentries, pData->aGlobalPLTEentries,
+ sizeof (pBuf->aPLTEentries));
+
+ if (pData->bHasglobalTRNS) /* also copy global tRNS ? */
+ {
+ mng_uint32 iRawlen2 = pData->iGlobalTRNSrawlen;
+ mng_uint8p pRawdata2 = (mng_uint8p)(pData->aGlobalTRNSrawdata);
+ /* indicate tRNS available */
+ pBuf->bHasTRNS = MNG_TRUE;
+ /* global length oke ? */
+ if ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+ /* copy it */
+ pBuf->iTRNScount = iRawlen2;
+ MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
+ }
+ }
+ else
+ { /* store fields for future reference */
+ pBuf->iPLTEcount = ((mng_pltep)pChunk)->iEntrycount;
+ MNG_COPY (pBuf->aPLTEentries, ((mng_pltep)pChunk)->aEntries,
+ sizeof (pBuf->aPLTEentries));
+ }
+ }
+ }
+ else /* store as global */
+ {
+ pData->iGlobalPLTEcount = ((mng_pltep)pChunk)->iEntrycount;
+ MNG_COPY (pData->aGlobalPLTEentries, ((mng_pltep)pChunk)->aEntries,
+ sizeof (pData->aGlobalPLTEentries));
+ /* create an animation object */
+ return mng_create_ani_plte (pData);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_idat)
+{
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasJHDR) &&
+ (pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+#endif
+ /* not allowed for deltatype NO_CHANGE */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && ((pData->iDeltatype == MNG_DELTATYPE_NOCHANGE)))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+#endif
+ /* can only be empty in BASI-block! */
+ if ((((mng_idatp)pChunk)->bEmpty) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ /* indexed-color requires PLTE */
+ if ((pData->bHasIHDR) && (pData->iColortype == 3) && (!pData->bHasPLTE))
+ MNG_ERROR (pData, MNG_PLTEMISSING);
+
+ pData->bHasIDAT = MNG_TRUE; /* got some IDAT now, don't we */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_iend)
+{ /* IHDR-block requires IDAT */
+ if ((pData->bHasIHDR) && (!pData->bHasIDAT))
+ MNG_ERROR (pData, MNG_IDATMISSING);
+
+ pData->iImagelevel--; /* one level up */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_image (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* display processing */
+ iRetcode = mng_process_display_iend (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (!pData->bTimerset) /* reset only if not broken !!! */
+ {
+#endif
+ /* IEND signals the end for most ... */
+ pData->bHasIHDR = MNG_FALSE;
+ pData->bHasBASI = MNG_FALSE;
+ pData->bHasDHDR = MNG_FALSE;
+#ifdef MNG_INCLUDE_JNG
+ pData->bHasJHDR = MNG_FALSE;
+ pData->bHasJSEP = MNG_FALSE;
+ pData->bHasJDAA = MNG_FALSE;
+ pData->bHasJDAT = MNG_FALSE;
+#endif
+ pData->bHasPLTE = MNG_FALSE;
+ pData->bHasTRNS = MNG_FALSE;
+ pData->bHasGAMA = MNG_FALSE;
+ pData->bHasCHRM = MNG_FALSE;
+ pData->bHasSRGB = MNG_FALSE;
+ pData->bHasICCP = MNG_FALSE;
+ pData->bHasBKGD = MNG_FALSE;
+ pData->bHasIDAT = MNG_FALSE;
+#ifdef MNG_SUPPORT_DISPLAY
+ }
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+MNG_F_SPECIALFUNC (mng_debunk_trns)
+{
+ mng_trnsp pTRNS = (mng_trnsp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* not global! */
+ pTRNS->bGlobal = MNG_FALSE;
+ pTRNS->iType = pData->iColortype;
+
+ if (iRawlen != 0)
+ {
+ switch (pData->iColortype) /* store fields */
+ {
+ case 0: { /* gray */
+ if (iRawlen != 2)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ pTRNS->iGray = mng_get_uint16 (pRawdata);
+ break;
+ }
+ case 2: { /* rgb */
+ if (iRawlen != 6)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ pTRNS->iRed = mng_get_uint16 (pRawdata);
+ pTRNS->iGreen = mng_get_uint16 (pRawdata+2);
+ pTRNS->iBlue = mng_get_uint16 (pRawdata+4);
+ break;
+ }
+ case 3: { /* indexed */
+ if (iRawlen > 256)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ pTRNS->iCount = iRawlen;
+ MNG_COPY (pTRNS->aEntries, pRawdata, iRawlen);
+ break;
+ }
+ }
+ }
+ }
+ else /* it's global! */
+ {
+ if (iRawlen == 0)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ pTRNS->bGlobal = MNG_TRUE;
+ pTRNS->iType = 0;
+ pTRNS->iRawlen = iRawlen;
+ MNG_COPY (pTRNS->aRawdata, pRawdata, iRawlen);
+
+ pData->iGlobalTRNSrawlen = iRawlen;
+ MNG_COPY (pData->aGlobalTRNSrawdata, pRawdata, iRawlen);
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_trns)
+{ /* multiple tRNS only inside BASI */
+ if ((pData->bHasTRNS) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_MULTIPLEERROR);
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* not allowed with full alpha-channel */
+ if ((pData->iColortype == 4) || (pData->iColortype == 6))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ if (!((mng_trnsp)pChunk)->bEmpty) /* filled ? */
+ {
+#ifdef MNG_SUPPORT_DISPLAY
+ if (pData->iColortype == 3)
+ {
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf;
+
+ if (!pImage) /* no object then check obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+
+ if (((mng_trnsp)pChunk)->iCount > pBuf->iPLTEcount)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+#endif
+ }
+ else /* if empty there must be global stuff! */
+ {
+ if (!pData->bHasglobalTRNS)
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+ }
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ pData->bHasTRNS = MNG_TRUE; /* indicate tRNS available */
+ else
+ pData->bHasglobalTRNS = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+ mng_uint8p pRawdata2;
+ mng_uint32 iRawlen2;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ { /* store in object 0 !!! */
+#if defined(MNG_NO_1_2_4BIT_SUPPORT)
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1,0,0,0,0,0,0,0,1};
+#endif
+ pImage = (mng_imagep)pData->pObjzero;
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasTRNS = MNG_TRUE; /* tell it it's got a tRNS now */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = 0;
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0: { /* gray */
+ pBuf->iTRNSgray = ((mng_trnsp)pChunk)->iGray;
+#if defined(MNG_NO_1_2_4BIT_SUPPORT)
+ pBuf->iTRNSgray *= multiplier[pData->iPNGdepth];
+#endif
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ pBuf->iTRNSgray >>= 8;
+#endif
+ break;
+ }
+ case 2: { /* rgb */
+ pBuf->iTRNSred = ((mng_trnsp)pChunk)->iRed;
+ pBuf->iTRNSgreen = ((mng_trnsp)pChunk)->iGreen;
+ pBuf->iTRNSblue = ((mng_trnsp)pChunk)->iBlue;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ {
+ pBuf->iTRNSred >>= 8;
+ pBuf->iTRNSgreen >>= 8;
+ pBuf->iTRNSblue >>= 8;
+ }
+#endif
+ break;
+ }
+ case 3: { /* indexed */
+ pBuf->iTRNScount = ((mng_trnsp)pChunk)->iCount;
+ MNG_COPY (pBuf->aTRNSentries,
+ ((mng_trnsp)pChunk)->aEntries,
+ ((mng_trnsp)pChunk)->iCount);
+ break;
+ }
+ }
+ }
+ else
+#endif
+ { /* address current object */
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasTRNS = MNG_TRUE; /* and tell it it's got a tRNS now */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = 0;
+
+ if (((mng_trnsp)pChunk)->bEmpty) /* if empty, inherit from global */
+ {
+ iRawlen2 = pData->iGlobalTRNSrawlen;
+ pRawdata2 = (mng_ptr)(pData->aGlobalTRNSrawdata);
+ /* global length oke ? */
+ if ((pData->iColortype == 0) && (iRawlen2 != 2))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+
+ if ((pData->iColortype == 2) && (iRawlen2 != 6))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+
+ if ((pData->iColortype == 3) && ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount)))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0: { /* gray */
+ pBuf->iTRNSgray = mng_get_uint16 (pRawdata2);
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ pBuf->iTRNSgray >>= 8;
+#endif
+ break;
+ }
+ case 2: { /* rgb */
+ pBuf->iTRNSred = mng_get_uint16 (pRawdata2);
+ pBuf->iTRNSgreen = mng_get_uint16 (pRawdata2+2);
+ pBuf->iTRNSblue = mng_get_uint16 (pRawdata2+4);
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ {
+ pBuf->iTRNSred >>= 8;
+ pBuf->iTRNSgreen >>= 8;
+ pBuf->iTRNSblue >>= 8;
+ }
+#endif
+ break;
+ }
+ case 3: { /* indexed */
+ pBuf->iTRNScount = iRawlen2;
+ MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
+ break;
+ }
+ }
+ }
+ else
+ {
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0: { /* gray */
+ pBuf->iTRNSgray = ((mng_trnsp)pChunk)->iGray;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ pBuf->iTRNSgray >>= 8;
+#endif
+ break;
+ }
+ case 2: { /* rgb */
+ pBuf->iTRNSred = ((mng_trnsp)pChunk)->iRed;
+ pBuf->iTRNSgreen = ((mng_trnsp)pChunk)->iGreen;
+ pBuf->iTRNSblue = ((mng_trnsp)pChunk)->iBlue;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ {
+ pBuf->iTRNSred >>= 8;
+ pBuf->iTRNSgreen >>= 8;
+ pBuf->iTRNSblue >>= 8;
+ }
+#endif
+ break;
+ }
+ case 3: { /* indexed */
+ pBuf->iTRNScount = ((mng_trnsp)pChunk)->iCount;
+ MNG_COPY (pBuf->aTRNSentries,
+ ((mng_trnsp)pChunk)->aEntries,
+ ((mng_trnsp)pChunk)->iCount);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ { /* create an animation object */
+ return mng_create_ani_trns (pData);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_gama)
+{
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasGAMA = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalGAMA = (mng_bool)!((mng_gamap)pChunk)->bEmpty;
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+ /* store for color-processing routines */
+ pImage->pImgbuf->iGamma = ((mng_gamap)pChunk)->iGamma;
+ pImage->pImgbuf->bHasGAMA = MNG_TRUE;
+ }
+ else
+ { /* store as global */
+ if (!((mng_gamap)pChunk)->bEmpty)
+ pData->iGlobalGamma = ((mng_gamap)pChunk)->iGamma;
+ /* create an animation object */
+ return mng_create_ani_gama (pData, pChunk);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+MNG_C_SPECIALFUNC (mng_special_chrm)
+{
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasCHRM = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalCHRM = (mng_bool)!((mng_chrmp)pChunk)->bEmpty;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasCHRM = MNG_TRUE; /* and tell it it's got a CHRM now */
+ /* store for color-processing routines */
+ pBuf->iWhitepointx = ((mng_chrmp)pChunk)->iWhitepointx;
+ pBuf->iWhitepointy = ((mng_chrmp)pChunk)->iWhitepointy;
+ pBuf->iPrimaryredx = ((mng_chrmp)pChunk)->iRedx;
+ pBuf->iPrimaryredy = ((mng_chrmp)pChunk)->iRedy;
+ pBuf->iPrimarygreenx = ((mng_chrmp)pChunk)->iGreenx;
+ pBuf->iPrimarygreeny = ((mng_chrmp)pChunk)->iGreeny;
+ pBuf->iPrimarybluex = ((mng_chrmp)pChunk)->iBluex;
+ pBuf->iPrimarybluey = ((mng_chrmp)pChunk)->iBluey;
+ }
+ else
+ { /* store as global */
+ if (!((mng_chrmp)pChunk)->bEmpty)
+ {
+ pData->iGlobalWhitepointx = ((mng_chrmp)pChunk)->iWhitepointx;
+ pData->iGlobalWhitepointy = ((mng_chrmp)pChunk)->iWhitepointy;
+ pData->iGlobalPrimaryredx = ((mng_chrmp)pChunk)->iRedx;
+ pData->iGlobalPrimaryredy = ((mng_chrmp)pChunk)->iRedy;
+ pData->iGlobalPrimarygreenx = ((mng_chrmp)pChunk)->iGreenx;
+ pData->iGlobalPrimarygreeny = ((mng_chrmp)pChunk)->iGreeny;
+ pData->iGlobalPrimarybluex = ((mng_chrmp)pChunk)->iBluex;
+ pData->iGlobalPrimarybluey = ((mng_chrmp)pChunk)->iBluey;
+ }
+ /* create an animation object */
+ return mng_create_ani_chrm (pData, pChunk);
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_srgb)
+{
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasSRGB = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalSRGB = (mng_bool)!((mng_srgbp)pChunk)->bEmpty;
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+ /* store for color-processing routines */
+ pImage->pImgbuf->iRenderingintent = ((mng_srgbp)pChunk)->iRenderingintent;
+ pImage->pImgbuf->bHasSRGB = MNG_TRUE;
+ }
+ else
+ { /* store as global */
+ if (!((mng_srgbp)pChunk)->bEmpty)
+ pData->iGlobalRendintent = ((mng_srgbp)pChunk)->iRenderingintent;
+ /* create an animation object */
+ return mng_create_ani_srgb (pData, pChunk);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+MNG_C_SPECIALFUNC (mng_special_iccp)
+{
+ mng_retcode iRetcode;
+ mng_chunk_headerp pDummy;
+
+#ifdef MNG_CHECK_BAD_ICCP /* Check for bad iCCP chunk */
+ if (!strncmp (((mng_iccpp)pChunk)->zName, "Photoshop ICC profile", 21))
+ {
+ if (((mng_iccpp)pChunk)->iProfilesize == 2615) /* is it the sRGB profile ? */
+ {
+ mng_chunk_header chunk_srgb;
+ mng_get_chunkheader (MNG_UINT_sRGB, &chunk_srgb);
+ /* pretend it's an sRGB chunk then ! */
+ iRetcode = mng_read_general (pData, &chunk_srgb, 1, (mng_ptr)"0", &pDummy);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pDummy->fCleanup (pData, pDummy);
+ }
+ }
+ else
+ {
+#endif /* MNG_CHECK_BAD_ICCP */
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasICCP = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalICCP = (mng_bool)!((mng_iccpp)pChunk)->bEmpty;
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ { /* store in object 0 ! */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ if (pImage->pImgbuf->pProfile) /* profile existed ? */
+ MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
+ /* allocate a buffer & copy it */
+ MNG_ALLOC (pData, pImage->pImgbuf->pProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ MNG_COPY (pImage->pImgbuf->pProfile, ((mng_iccpp)pChunk)->pProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ /* store its length as well */
+ pImage->pImgbuf->iProfilesize = ((mng_iccpp)pChunk)->iProfilesize;
+ pImage->pImgbuf->bHasICCP = MNG_TRUE;
+ }
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ if (pImage->pImgbuf->pProfile) /* profile existed ? */
+ MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
+ /* allocate a buffer & copy it */
+ MNG_ALLOC (pData, pImage->pImgbuf->pProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ MNG_COPY (pImage->pImgbuf->pProfile, ((mng_iccpp)pChunk)->pProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ /* store its length as well */
+ pImage->pImgbuf->iProfilesize = ((mng_iccpp)pChunk)->iProfilesize;
+ pImage->pImgbuf->bHasICCP = MNG_TRUE;
+ }
+ }
+ else
+ { /* store as global */
+ if (pData->pGlobalProfile) /* did we have a global profile ? */
+ MNG_FREEX (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ if (((mng_iccpp)pChunk)->bEmpty) /* empty chunk ? */
+ {
+ pData->iGlobalProfilesize = 0; /* reset to null */
+ pData->pGlobalProfile = MNG_NULL;
+ }
+ else
+ { /* allocate a global buffer & copy it */
+ MNG_ALLOC (pData, pData->pGlobalProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ MNG_COPY (pData->pGlobalProfile, ((mng_iccpp)pChunk)->pProfile, ((mng_iccpp)pChunk)->iProfilesize);
+ /* store its length as well */
+ pData->iGlobalProfilesize = ((mng_iccpp)pChunk)->iProfilesize;
+ }
+ /* create an animation object */
+ return mng_create_ani_iccp (pData, pChunk);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_CHECK_BAD_ICCP
+ }
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+MNG_C_SPECIALFUNC (mng_special_text)
+{
+ if (pData->fProcesstext) /* inform the application ? */
+ {
+ mng_bool bOke = pData->fProcesstext ((mng_handle)pData, MNG_TYPE_TEXT,
+ ((mng_textp)pChunk)->zKeyword,
+ ((mng_textp)pChunk)->zText, 0, 0);
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+MNG_C_SPECIALFUNC (mng_special_ztxt)
+{
+ if (pData->fProcesstext) /* inform the application ? */
+ {
+ mng_bool bOke = pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ZTXT,
+ ((mng_ztxtp)pChunk)->zKeyword,
+ ((mng_ztxtp)pChunk)->zText, 0, 0);
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+MNG_F_SPECIALFUNC (mng_deflate_itxt)
+{
+ mng_itxtp pITXT = (mng_itxtp)pChunk;
+ mng_uint32 iBufsize = 0;
+ mng_uint8p pBuf = 0;
+ mng_uint32 iTextlen = 0;
+
+ if (pITXT->iCompressionflag) /* decompress the text ? */
+ {
+ mng_retcode iRetcode = mng_inflate_buffer (pData, *ppRawdata, *piRawlen,
+ &pBuf, &iBufsize, &iTextlen);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ MNG_ALLOC (pData, pITXT->zText, iTextlen+1);
+ MNG_COPY (pITXT->zText, pBuf, iTextlen);
+
+ pITXT->iTextsize = iTextlen;
+
+ MNG_FREEX (pData, pBuf, iBufsize);
+
+ } else {
+
+ MNG_ALLOC (pData, pITXT->zText, (*piRawlen)+1);
+ MNG_COPY (pITXT->zText, *ppRawdata, *piRawlen);
+
+ pITXT->iTextsize = *piRawlen;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+MNG_C_SPECIALFUNC (mng_special_itxt)
+{
+ if (pData->fProcesstext) /* inform the application ? */
+ {
+ mng_bool bOke = pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ITXT,
+ ((mng_itxtp)pChunk)->zKeyword,
+ ((mng_itxtp)pChunk)->zText,
+ ((mng_itxtp)pChunk)->zLanguage,
+ ((mng_itxtp)pChunk)->zTranslation);
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+MNG_C_SPECIALFUNC (mng_special_bkgd)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf;
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasBKGD = MNG_TRUE; /* indicate bKGD available */
+ else
+ pData->bHasglobalBKGD = (mng_bool)!(((mng_bkgdp)pChunk)->bEmpty);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (!pImage) /* if no object dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ pBuf = pImage->pImgbuf; /* address object buffer */
+
+#ifdef MNG_INCLUDE_JNG
+ if (pData->bHasJHDR)
+ {
+ pBuf->bHasBKGD = MNG_TRUE; /* tell the object it's got bKGD now */
+
+ switch (pData->iJHDRcolortype) /* store fields for future reference */
+ {
+ case 8 : ; /* gray */
+ case 12 : { /* graya */
+ pBuf->iBKGDgray = ((mng_bkgdp)pChunk)->iGray;
+ break;
+ }
+ case 10 : ; /* rgb */
+ case 14 : { /* rgba */
+ pBuf->iBKGDred = ((mng_bkgdp)pChunk)->iRed;
+ pBuf->iBKGDgreen = ((mng_bkgdp)pChunk)->iGreen;
+ pBuf->iBKGDblue = ((mng_bkgdp)pChunk)->iBlue;
+ break;
+ }
+ }
+ }
+ else
+#endif /* MNG_INCLUDE_JNG */
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ pBuf->bHasBKGD = MNG_TRUE; /* tell the object it's got bKGD now */
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0 : ; /* gray */
+ case 4 : { /* graya */
+ pBuf->iBKGDgray = ((mng_bkgdp)pChunk)->iGray;
+ break;
+ }
+ case 2 : ; /* rgb */
+ case 6 : { /* rgba */
+ pBuf->iBKGDred = ((mng_bkgdp)pChunk)->iRed;
+ pBuf->iBKGDgreen = ((mng_bkgdp)pChunk)->iGreen;
+ pBuf->iBKGDblue = ((mng_bkgdp)pChunk)->iBlue;
+ break;
+ }
+ case 3 : { /* indexed */
+ pBuf->iBKGDindex = ((mng_bkgdp)pChunk)->iIndex;
+ break;
+ }
+ }
+ }
+ else /* store as global */
+ {
+ if (!(((mng_bkgdp)pChunk)->bEmpty))
+ {
+ pData->iGlobalBKGDred = ((mng_bkgdp)pChunk)->iRed;
+ pData->iGlobalBKGDgreen = ((mng_bkgdp)pChunk)->iGreen;
+ pData->iGlobalBKGDblue = ((mng_bkgdp)pChunk)->iBlue;
+ }
+ /* create an animation object */
+ return mng_create_ani_bkgd (pData);
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+MNG_C_SPECIALFUNC (mng_special_phys)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+MNG_C_SPECIALFUNC (mng_special_sbit)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+MNG_F_SPECIALFUNC (mng_splt_entries)
+{
+ mng_spltp pSPLT = (mng_spltp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+
+ if ((pSPLT->iSampledepth != MNG_BITDEPTH_8 ) &&
+ (pSPLT->iSampledepth != MNG_BITDEPTH_16) )
+ MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
+ /* check remaining length */
+ if ( ((pSPLT->iSampledepth == MNG_BITDEPTH_8 ) && (iRawlen % 6 != 0)) ||
+ ((pSPLT->iSampledepth == MNG_BITDEPTH_16) && (iRawlen % 10 != 0)) )
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if (pSPLT->iSampledepth == MNG_BITDEPTH_8)
+ pSPLT->iEntrycount = iRawlen / 6;
+ else
+ pSPLT->iEntrycount = iRawlen / 10;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, pSPLT->pEntries, iRawlen);
+ MNG_COPY (pSPLT->pEntries, pRawdata, iRawlen);
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+MNG_C_SPECIALFUNC (mng_special_splt)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+MNG_F_SPECIALFUNC (mng_hist_entries)
+{
+ mng_histp pHIST = (mng_histp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint32 iX;
+
+ if ( ((iRawlen & 0x01) != 0) || ((iRawlen >> 1) != pData->iPLTEcount) )
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pHIST->iEntrycount = iRawlen >> 1;
+
+ for (iX = 0; iX < pHIST->iEntrycount; iX++)
+ {
+ pHIST->aEntries[iX] = mng_get_uint16 (pRawdata);
+ pRawdata += 2;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+MNG_C_SPECIALFUNC (mng_special_hist)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+MNG_C_SPECIALFUNC (mng_special_time)
+{
+/* if (pData->fProcesstime) */ /* inform the application ? */
+/* {
+
+ pData->fProcesstime ((mng_handle)pData, );
+ } */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* JNG chunks */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_C_SPECIALFUNC (mng_special_jhdr)
+{
+ if ((pData->eSigtype == mng_it_jng) && (pData->iChunkseq > 1))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* inside a JHDR-IEND block now */
+ pData->bHasJHDR = MNG_TRUE;
+ /* and store interesting fields */
+ pData->iDatawidth = ((mng_jhdrp)pChunk)->iWidth;
+ pData->iDataheight = ((mng_jhdrp)pChunk)->iHeight;
+ pData->iJHDRcolortype = ((mng_jhdrp)pChunk)->iColortype;
+ pData->iJHDRimgbitdepth = ((mng_jhdrp)pChunk)->iImagesampledepth;
+ pData->iJHDRimgcompression = ((mng_jhdrp)pChunk)->iImagecompression;
+ pData->iJHDRimginterlace = ((mng_jhdrp)pChunk)->iImageinterlace;
+ pData->iJHDRalphabitdepth = ((mng_jhdrp)pChunk)->iAlphasampledepth;
+ pData->iJHDRalphacompression = ((mng_jhdrp)pChunk)->iAlphacompression;
+ pData->iJHDRalphafilter = ((mng_jhdrp)pChunk)->iAlphafilter;
+ pData->iJHDRalphainterlace = ((mng_jhdrp)pChunk)->iAlphainterlace;
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iJHDRalphabitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iJHDRalphabitdepth < 8)
+ pData->iJHDRalphabitdepth = 8;
+#endif
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iJHDRalphabitdepth > 8)
+ {
+ pData->iPNGmult = 2;
+ pData->iJHDRalphabitdepth = 8;
+ }
+#endif
+ /* parameter validity checks */
+ if ((pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAY ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLORA) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8 ) &&
+ (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG12 ) &&
+ (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8AND12) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ {
+ if ((pData->iJHDRalphabitdepth != MNG_BITDEPTH_8 )
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_1 ) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_2 ) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_4 )
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE ) &&
+ (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG) )
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ if ((pData->iJHDRalphacompression == MNG_COMPRESSION_BASELINEJPEG) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iJHDRalphafilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING) &&
+ (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iJHDRalphafilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ }
+ else
+ {
+ if (pData->iJHDRalphabitdepth)
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+ if (pData->iJHDRalphacompression)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+ if (pData->iJHDRalphafilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+ if (pData->iJHDRalphainterlace)
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+ }
+
+ if (!pData->bHasheader) /* first chunk ? */
+ {
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_jng; /* then this must be a JNG */
+ pData->iWidth = ((mng_jhdrp)pChunk)->iWidth;
+ pData->iHeight = ((mng_jhdrp)pChunk)->iHeight;
+ /* predict alpha-depth ! */
+ if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ pData->iAlphadepth = pData->iJHDRalphabitdepth;
+ else
+ pData->iAlphadepth = 0;
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ }
+
+ pData->iColortype = 0; /* fake grayscale for other routines */
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_process_display_jhdr (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (((mng_jhdrp)pChunk)->iAlphasampledepth > 8)
+ ((mng_jhdrp)pChunk)->iAlphasampledepth = 8;
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_C_SPECIALFUNC (mng_special_jdaa)
+{
+ if (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ pData->bHasJDAA = MNG_TRUE; /* got some JDAA now, don't we */
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_C_SPECIALFUNC (mng_special_jdat)
+{
+ pData->bHasJDAT = MNG_TRUE; /* got some JDAT now, don't we */
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+MNG_C_SPECIALFUNC (mng_special_jsep)
+{
+ pData->bHasJSEP = MNG_TRUE; /* indicate we've had the 8-/12-bit separator */
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+/* MNG chunks */
+
+MNG_C_SPECIALFUNC (mng_special_mhdr)
+{
+ if (pData->bHasheader) /* can only be the first chunk! */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ pData->bHasMHDR = MNG_TRUE; /* oh boy, a real MNG */
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_mng; /* fill header fields */
+ pData->iWidth = ((mng_mhdrp)pChunk)->iWidth;
+ pData->iHeight = ((mng_mhdrp)pChunk)->iHeight;
+ pData->iTicks = ((mng_mhdrp)pChunk)->iTicks;
+ pData->iLayercount = ((mng_mhdrp)pChunk)->iLayercount;
+ pData->iFramecount = ((mng_mhdrp)pChunk)->iFramecount;
+ pData->iPlaytime = ((mng_mhdrp)pChunk)->iPlaytime;
+ pData->iSimplicity = ((mng_mhdrp)pChunk)->iSimplicity;
+#ifndef MNG_NO_OLD_VERSIONS
+ pData->bPreDraft48 = MNG_FALSE;
+#endif
+ /* predict alpha-depth */
+ if ((pData->iSimplicity & 0x00000001) == 0)
+#ifndef MNG_NO_16BIT_SUPPORT
+ pData->iAlphadepth = 16; /* no indicators = assume the worst */
+#else
+ pData->iAlphadepth = 8; /* anything else = assume the worst */
+#endif
+ else
+ if ((pData->iSimplicity & 0x00000008) == 0)
+ pData->iAlphadepth = 0; /* no transparency at all */
+ else
+ if ((pData->iSimplicity & 0x00000140) == 0x00000040)
+ pData->iAlphadepth = 1; /* no semi-transparency guaranteed */
+ else
+#ifndef MNG_NO_16BIT_SUPPORT
+ pData->iAlphadepth = 16; /* anything else = assume the worst */
+#else
+ pData->iAlphadepth = 8; /* anything else = assume the worst */
+#endif
+
+#ifdef MNG_INCLUDE_JNG /* can we handle the complexity ? */
+ if (pData->iSimplicity & 0x0000FC00)
+#else
+ if (pData->iSimplicity & 0x0000FC10)
+#endif
+ MNG_ERROR (pData, MNG_MNGTOOCOMPLEX);
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ pData->iImagelevel++; /* one level deeper */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_mend)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* do something */
+ mng_retcode iRetcode = mng_process_display_mend (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (!pData->iTotalframes) /* save totals */
+ pData->iTotalframes = pData->iFrameseq;
+ if (!pData->iTotallayers)
+ pData->iTotallayers = pData->iLayerseq;
+ if (!pData->iTotalplaytime)
+ pData->iTotalplaytime = pData->iFrametime;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ pData->bHasMHDR = MNG_FALSE; /* end of the line, bro! */
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_F_SPECIALFUNC (mng_debunk_loop)
+{
+ mng_loopp pLOOP = (mng_loopp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+
+ if (iRawlen >= 5) /* length checks */
+ {
+ if (iRawlen >= 6)
+ {
+ if ((iRawlen - 6) % 4 != 0)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if (iRawlen >= 5) /* store the fields */
+ {
+ pLOOP->iLevel = *pRawdata;
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48)
+ {
+ pLOOP->iTermination = *(pRawdata+1);
+ pLOOP->iRepeat = mng_get_uint32 (pRawdata+2);
+ }
+ else
+#endif
+ {
+ pLOOP->iRepeat = mng_get_uint32 (pRawdata+1);
+ }
+
+ if (iRawlen >= 6)
+ {
+#ifndef MNG_NO_OLD_VERSIONS
+ if (!pData->bPreDraft48)
+#endif
+ pLOOP->iTermination = *(pRawdata+5);
+
+ if (iRawlen >= 10)
+ {
+ pLOOP->iItermin = mng_get_uint32 (pRawdata+6);
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (iRawlen >= 14)
+ {
+ pLOOP->iItermax = mng_get_uint32 (pRawdata+10);
+ pLOOP->iCount = (iRawlen - 14) / 4;
+
+ if (pLOOP->iCount)
+ {
+ MNG_ALLOC (pData, pLOOP->pSignals, pLOOP->iCount << 2);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint8p pIn = pRawdata + 14;
+ mng_uint32p pOut = (mng_uint32p)pLOOP->pSignals;
+
+ for (iX = 0; iX < pLOOP->iCount; iX++)
+ {
+ *pOut++ = mng_get_uint32 (pIn);
+ pIn += 4;
+ }
+ }
+#else
+ MNG_COPY (pLOOP->pSignals, pRawdata + 14, pLOOP->iCount << 2);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+ }
+#endif
+ }
+ }
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_C_SPECIALFUNC (mng_special_loop)
+{
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_LOOPWITHCACHEOFF);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+ pData->bHasLOOP = MNG_TRUE; /* indicate we're inside a loop */
+ /* create the LOOP ani-object */
+ iRetcode = mng_create_ani_loop (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* skip till matching ENDL if iteration=0 */
+ if ((!pData->bSkipping) && (((mng_loopp)pChunk)->iRepeat == 0))
+ pData->bSkipping = MNG_TRUE;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+MNG_C_SPECIALFUNC (mng_special_endl)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ if (pData->bHasLOOP) /* are we really processing a loop ? */
+ {
+ mng_uint8 iLevel = ((mng_endlp)pChunk)->iLevel;
+ /* create an ENDL animation object */
+ return mng_create_ani_endl (pData, iLevel);
+ }
+ else
+ MNG_ERROR (pData, MNG_NOMATCHINGLOOP);
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+MNG_C_SPECIALFUNC (mng_special_defi)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_retcode iRetcode;
+
+ pData->iDEFIobjectid = ((mng_defip)pChunk)->iObjectid;
+ pData->bDEFIhasdonotshow = ((mng_defip)pChunk)->bHasdonotshow;
+ pData->iDEFIdonotshow = ((mng_defip)pChunk)->iDonotshow;
+ pData->bDEFIhasconcrete = ((mng_defip)pChunk)->bHasconcrete;
+ pData->iDEFIconcrete = ((mng_defip)pChunk)->iConcrete;
+ pData->bDEFIhasloca = ((mng_defip)pChunk)->bHasloca;
+ pData->iDEFIlocax = ((mng_defip)pChunk)->iXlocation;
+ pData->iDEFIlocay = ((mng_defip)pChunk)->iYlocation;
+ pData->bDEFIhasclip = ((mng_defip)pChunk)->bHasclip;
+ pData->iDEFIclipl = ((mng_defip)pChunk)->iLeftcb;
+ pData->iDEFIclipr = ((mng_defip)pChunk)->iRightcb;
+ pData->iDEFIclipt = ((mng_defip)pChunk)->iTopcb;
+ pData->iDEFIclipb = ((mng_defip)pChunk)->iBottomcb;
+ /* create an animation object */
+ iRetcode = mng_create_ani_defi (pData);
+ if (!iRetcode) /* do display processing */
+ iRetcode = mng_process_display_defi (pData);
+ return iRetcode;
+#else
+ return MNG_NOERROR; /* done */
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+MNG_C_SPECIALFUNC (mng_special_basi)
+{
+ pData->bHasBASI = MNG_TRUE; /* inside a BASI-IEND block now */
+ /* store interesting fields */
+ pData->iDatawidth = ((mng_basip)pChunk)->iWidth;
+ pData->iDataheight = ((mng_basip)pChunk)->iHeight;
+ pData->iBitdepth = ((mng_basip)pChunk)->iBitdepth;
+ pData->iColortype = ((mng_basip)pChunk)->iColortype;
+ pData->iCompression = ((mng_basip)pChunk)->iCompression;
+ pData->iFilter = ((mng_basip)pChunk)->iFilter;
+ pData->iInterlace = ((mng_basip)pChunk)->iInterlace;
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iBitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iBitdepth < 8)
+ pData->iBitdepth = 8;
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth > 8)
+ {
+ pData->iBitdepth = 8;
+ pData->iPNGmult = 2;
+ }
+#endif
+
+ if ((pData->iBitdepth != 8) /* parameter validity checks */
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iBitdepth != 1) &&
+ (pData->iBitdepth != 2) &&
+ (pData->iBitdepth != 4)
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iBitdepth != 16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
+ (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
+ (pData->iBitdepth < 8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iFilter != MNG_FILTER_DIFFERING) &&
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iFilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iFilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_basi (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (((mng_basip)pChunk)->iBitdepth > 8)
+ ((mng_basip)pChunk)->iBitdepth = 8;
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+MNG_C_SPECIALFUNC (mng_special_clon)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_clon (pData, pChunk);
+#else
+ return MNG_NOERROR; /* done */
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_F_SPECIALFUNC (mng_debunk_past)
+{
+ mng_pastp pPAST = (mng_pastp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint32 iSize;
+ mng_uint32 iX;
+ mng_past_sourcep pSource;
+ /* check the length */
+ if ((iRawlen < 41) || (((iRawlen - 11) % 30) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pPAST->iDestid = mng_get_uint16 (pRawdata);
+ pPAST->iTargettype = *(pRawdata+2);
+ pPAST->iTargetx = mng_get_int32 (pRawdata+3);
+ pPAST->iTargety = mng_get_int32 (pRawdata+7);
+ pPAST->iCount = ((iRawlen - 11) / 30); /* how many entries again? */
+ iSize = pPAST->iCount * sizeof (mng_past_source);
+
+ pRawdata += 11;
+ /* get a buffer for all the source blocks */
+ MNG_ALLOC (pData, pPAST->pSources, iSize);
+
+ pSource = (mng_past_sourcep)(pPAST->pSources);
+
+ for (iX = pPAST->iCount; iX > 0; iX--)
+ { /* now copy the source blocks */
+ pSource->iSourceid = mng_get_uint16 (pRawdata);
+ pSource->iComposition = *(pRawdata+2);
+ pSource->iOrientation = *(pRawdata+3);
+ pSource->iOffsettype = *(pRawdata+4);
+ pSource->iOffsetx = mng_get_int32 (pRawdata+5);
+ pSource->iOffsety = mng_get_int32 (pRawdata+9);
+ pSource->iBoundarytype = *(pRawdata+13);
+ pSource->iBoundaryl = mng_get_int32 (pRawdata+14);
+ pSource->iBoundaryr = mng_get_int32 (pRawdata+18);
+ pSource->iBoundaryt = mng_get_int32 (pRawdata+22);
+ pSource->iBoundaryb = mng_get_int32 (pRawdata+26);
+
+ pSource++;
+ pRawdata += 30;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+MNG_C_SPECIALFUNC (mng_special_past)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_past (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+MNG_F_SPECIALFUNC (mng_disc_entries)
+{
+ mng_discp pDISC = (mng_discp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+
+ if ((iRawlen % 2) != 0) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pDISC->iCount = (iRawlen / sizeof (mng_uint16));
+
+ if (pDISC->iCount)
+ {
+ MNG_ALLOC (pData, pDISC->pObjectids, iRawlen);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint8p pIn = pRawdata;
+ mng_uint16p pOut = pDISC->pObjectids;
+
+ for (iX = pDISC->iCount; iX > 0; iX--)
+ {
+ *pOut++ = mng_get_uint16 (pIn);
+ pIn += 2;
+ }
+ }
+#else
+ MNG_COPY (pDISC->pObjectids, pRawdata, iRawlen);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+MNG_C_SPECIALFUNC (mng_special_disc)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_disc (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+MNG_C_SPECIALFUNC (mng_special_back)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ /* retrieve the fields */
+ pData->bHasBACK = MNG_TRUE;
+ pData->iBACKred = ((mng_backp)pChunk)->iRed;
+ pData->iBACKgreen = ((mng_backp)pChunk)->iGreen;
+ pData->iBACKblue = ((mng_backp)pChunk)->iBlue;
+ pData->iBACKmandatory = ((mng_backp)pChunk)->iMandatory;
+ pData->iBACKimageid = ((mng_backp)pChunk)->iImageid;
+ pData->iBACKtile = ((mng_backp)pChunk)->iTile;
+
+ return mng_create_ani_back (pData);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+MNG_F_SPECIALFUNC (mng_fram_remainder)
+{
+ mng_framp pFRAM = (mng_framp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint32 iRequired = 0;
+
+ if (iRawlen < 4) /* must have at least 4 bytes */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iRequired = 4; /* calculate and check required remaining length */
+
+ pFRAM->iChangedelay = *pRawdata;
+ pFRAM->iChangetimeout = *(pRawdata+1);
+ pFRAM->iChangeclipping = *(pRawdata+2);
+ pFRAM->iChangesyncid = *(pRawdata+3);
+
+ if (pFRAM->iChangedelay ) { iRequired += 4; }
+ if (pFRAM->iChangetimeout ) { iRequired += 4; }
+ if (pFRAM->iChangeclipping) { iRequired += 17; }
+
+ if (pFRAM->iChangesyncid)
+ {
+ if ((iRawlen - iRequired) % 4 != 0)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ {
+ if (iRawlen != iRequired)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+ pRawdata += 4;
+
+ if (pFRAM->iChangedelay) /* delay changed ? */
+ {
+ pFRAM->iDelay = mng_get_uint32 (pRawdata);
+ pRawdata += 4;
+ }
+
+ if (pFRAM->iChangetimeout) /* timeout changed ? */
+ {
+ pFRAM->iTimeout = mng_get_uint32 (pRawdata);
+ pRawdata += 4;
+ }
+
+ if (pFRAM->iChangeclipping) /* clipping changed ? */
+ {
+ pFRAM->iBoundarytype = *pRawdata;
+ pFRAM->iBoundaryl = mng_get_int32 (pRawdata+1);
+ pFRAM->iBoundaryr = mng_get_int32 (pRawdata+5);
+ pFRAM->iBoundaryt = mng_get_int32 (pRawdata+9);
+ pFRAM->iBoundaryb = mng_get_int32 (pRawdata+13);
+ pRawdata += 17;
+ }
+
+ if (pFRAM->iChangesyncid)
+ {
+ pFRAM->iCount = (iRawlen - iRequired) / 4;
+
+ if (pFRAM->iCount)
+ {
+ MNG_ALLOC (pData, pFRAM->pSyncids, pFRAM->iCount * 4);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint32p pOut = pFRAM->pSyncids;
+
+ for (iX = pFRAM->iCount; iX > 0; iX--)
+ {
+ *pOut++ = mng_get_uint32 (pRawdata);
+ pRawdata += 4;
+ }
+ }
+#else
+ MNG_COPY (pFRAM->pSyncids, pRawdata, pFRAM->iCount * 4);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+ }
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48) /* old style input-stream ? */
+ {
+ switch (pFRAM->iMode) /* fix the framing mode then */
+ {
+ case 0: { break; }
+ case 1: { pFRAM->iMode = 3; break; }
+ case 2: { pFRAM->iMode = 4; break; }
+ case 3: { pFRAM->iMode = 1; break; }
+ case 4: { pFRAM->iMode = 1; break; }
+ case 5: { pFRAM->iMode = 2; break; }
+ default: { pFRAM->iMode = 1; break; }
+ }
+ }
+#endif
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+MNG_C_SPECIALFUNC (mng_special_fram)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_fram (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+MNG_C_SPECIALFUNC (mng_special_move)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_move (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+MNG_C_SPECIALFUNC (mng_special_clip)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_clip (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+MNG_C_SPECIALFUNC (mng_special_show)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_retcode iRetcode;
+
+ if (!((mng_showp)pChunk)->bEmpty) /* any data ? */
+ {
+ if (!((mng_showp)pChunk)->bHaslastid)
+ ((mng_showp)pChunk)->iLastid = ((mng_showp)pChunk)->iFirstid;
+
+ pData->iSHOWfromid = ((mng_showp)pChunk)->iFirstid;
+ pData->iSHOWtoid = ((mng_showp)pChunk)->iLastid;
+ pData->iSHOWmode = ((mng_showp)pChunk)->iMode;
+ }
+ else /* use defaults then */
+ {
+ pData->iSHOWfromid = 1;
+ pData->iSHOWtoid = 65535;
+ pData->iSHOWmode = 2;
+ }
+ /* create a SHOW animation object */
+ iRetcode = mng_create_ani_show (pData);
+ if (!iRetcode) /* go and do it! */
+ iRetcode = mng_process_display_show (pData);
+
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+MNG_C_SPECIALFUNC (mng_special_term)
+{
+ /* should be behind MHDR or SAVE !! */
+ if ((!pData->bHasSAVE) && (pData->iChunkseq > 2))
+ {
+ pData->bMisplacedTERM = MNG_TRUE; /* indicate we found a misplaced TERM */
+ /* and send a warning signal!!! */
+ MNG_WARNING (pData, MNG_SEQUENCEERROR);
+ }
+
+ pData->bHasTERM = MNG_TRUE;
+
+ if (pData->fProcessterm) /* inform the app ? */
+ if (!pData->fProcessterm (((mng_handle)pData),
+ ((mng_termp)pChunk)->iTermaction,
+ ((mng_termp)pChunk)->iIteraction,
+ ((mng_termp)pChunk)->iDelay,
+ ((mng_termp)pChunk)->iItermax))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create the TERM ani-object */
+ mng_retcode iRetcode = mng_create_ani_term (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* save for future reference */
+ pData->pTermaniobj = pData->pLastaniobj;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_F_SPECIALFUNC (mng_save_entries)
+{
+ mng_savep pSAVE = (mng_savep)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_save_entryp pEntry = MNG_NULL;
+ mng_uint32 iCount = 0;
+ mng_uint8 iOtype = *pRawdata;
+ mng_uint8 iEtype;
+ mng_uint8p pTemp;
+ mng_uint8p pNull;
+ mng_uint32 iLen;
+ mng_uint32 iOffset[2];
+ mng_uint32 iStarttime[2];
+ mng_uint32 iFramenr;
+ mng_uint32 iLayernr;
+ mng_uint32 iX;
+ mng_uint32 iNamesize;
+
+ if ((iOtype != 4) && (iOtype != 8))
+ MNG_ERROR (pData, MNG_INVOFFSETSIZE);
+
+ pSAVE->iOffsettype = iOtype;
+
+ for (iX = 0; iX < 2; iX++) /* do this twice to get the count first ! */
+ {
+ pTemp = pRawdata + 1;
+ iLen = iRawlen - 1;
+
+ if (iX) /* second run ? */
+ {
+ MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_save_entry)));
+
+ pSAVE->iCount = iCount;
+ pSAVE->pEntries = pEntry;
+ }
+
+ while (iLen) /* anything left ? */
+ {
+ iEtype = *pTemp; /* entrytype */
+
+ if ((iEtype != 0) && (iEtype != 1) && (iEtype != 2) && (iEtype != 3))
+ MNG_ERROR (pData, MNG_INVENTRYTYPE);
+
+ pTemp++;
+
+ if (iEtype > 1)
+ {
+ iOffset [0] = 0;
+ iOffset [1] = 0;
+ iStarttime [0] = 0;
+ iStarttime [1] = 0;
+ iLayernr = 0;
+ iFramenr = 0;
+ }
+ else
+ {
+ if (iOtype == 4)
+ {
+ iOffset [0] = 0;
+ iOffset [1] = mng_get_uint32 (pTemp);
+
+ pTemp += 4;
+ }
+ else
+ {
+ iOffset [0] = mng_get_uint32 (pTemp);
+ iOffset [1] = mng_get_uint32 (pTemp+4);
+
+ pTemp += 8;
+ }
+
+ if (iEtype > 0)
+ {
+ iStarttime [0] = 0;
+ iStarttime [1] = 0;
+ iLayernr = 0;
+ iFramenr = 0;
+ }
+ else
+ {
+ if (iOtype == 4)
+ {
+ iStarttime [0] = 0;
+ iStarttime [1] = mng_get_uint32 (pTemp+0);
+ iLayernr = mng_get_uint32 (pTemp+4);
+ iFramenr = mng_get_uint32 (pTemp+8);
+
+ pTemp += 12;
+ }
+ else
+ {
+ iStarttime [0] = mng_get_uint32 (pTemp+0);
+ iStarttime [1] = mng_get_uint32 (pTemp+4);
+ iLayernr = mng_get_uint32 (pTemp+8);
+ iFramenr = mng_get_uint32 (pTemp+12);
+
+ pTemp += 16;
+ }
+ }
+ }
+
+ pNull = pTemp; /* get the name length */
+ while (*pNull)
+ pNull++;
+
+ if ((pNull - pRawdata) > (mng_int32)iRawlen)
+ {
+ iNamesize = iLen; /* no null found; so end of SAVE */
+ iLen = 0;
+ }
+ else
+ {
+ iNamesize = pNull - pTemp; /* should be another entry */
+ iLen -= iNamesize;
+
+ if (!iLen) /* must not end with a null ! */
+ MNG_ERROR (pData, MNG_ENDWITHNULL);
+ }
+
+ if (!pEntry)
+ {
+ iCount++;
+ }
+ else
+ {
+ pEntry->iEntrytype = iEtype;
+ pEntry->iOffset [0] = iOffset [0];
+ pEntry->iOffset [1] = iOffset [1];
+ pEntry->iStarttime [0] = iStarttime [0];
+ pEntry->iStarttime [1] = iStarttime [1];
+ pEntry->iLayernr = iLayernr;
+ pEntry->iFramenr = iFramenr;
+ pEntry->iNamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zName, iNamesize+1);
+ MNG_COPY (pEntry->zName, pTemp, iNamesize);
+ }
+
+ pEntry++;
+ }
+
+ pTemp += iNamesize;
+ }
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_C_SPECIALFUNC (mng_special_save)
+{
+ pData->bHasSAVE = MNG_TRUE;
+
+ if (pData->fProcesssave) /* inform the application ? */
+ {
+ mng_bool bOke = pData->fProcesssave ((mng_handle)pData);
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+ /* TODO: something with the parameters */
+
+ /* create a SAVE animation object */
+ iRetcode = mng_create_ani_save (pData);
+ if (!iRetcode) /* process it */
+ iRetcode = mng_process_display_save (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+MNG_C_SPECIALFUNC (mng_special_seek)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ /* create a SEEK animation object */
+ iRetcode = mng_create_ani_seek (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ if (pData->fProcessseek) /* inform the app ? */
+ if (!pData->fProcessseek ((mng_handle)pData, ((mng_seekp)pChunk)->zName))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_process_display_seek (pData);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+MNG_C_SPECIALFUNC (mng_special_expi)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+MNG_C_SPECIALFUNC (mng_special_fpri)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+MNG_LOCAL mng_bool CheckKeyword (mng_datap pData,
+ mng_uint8p pKeyword)
+{
+ mng_chunkid handled_chunks [] =
+ {
+ MNG_UINT_BACK, /* keep it sorted !!!! */
+ MNG_UINT_BASI,
+ MNG_UINT_CLIP,
+ MNG_UINT_CLON,
+#ifndef MNG_NO_DELTA_PNG
+/* TODO: MNG_UINT_DBYK, */
+#endif
+ MNG_UINT_DEFI,
+#ifndef MNG_NO_DELTA_PNG
+ MNG_UINT_DHDR,
+#endif
+ MNG_UINT_DISC,
+#ifndef MNG_NO_DELTA_PNG
+/* TODO: MNG_UINT_DROP, */
+#endif
+ MNG_UINT_ENDL,
+ MNG_UINT_FRAM,
+ MNG_UINT_IDAT,
+ MNG_UINT_IEND,
+ MNG_UINT_IHDR,
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ MNG_UINT_IJNG,
+#endif
+ MNG_UINT_IPNG,
+#endif
+#ifdef MNG_INCLUDE_JNG
+ MNG_UINT_JDAA,
+ MNG_UINT_JDAT,
+ MNG_UINT_JHDR,
+/* TODO: MNG_UINT_JSEP, */
+ MNG_UINT_JdAA,
+#endif
+ MNG_UINT_LOOP,
+ MNG_UINT_MAGN,
+ MNG_UINT_MEND,
+ MNG_UINT_MHDR,
+ MNG_UINT_MOVE,
+/* TODO: MNG_UINT_ORDR, */
+ MNG_UINT_PAST,
+ MNG_UINT_PLTE,
+#ifndef MNG_NO_DELTA_PNG
+ MNG_UINT_PPLT,
+ MNG_UINT_PROM,
+#endif
+ MNG_UINT_SAVE,
+ MNG_UINT_SEEK,
+ MNG_UINT_SHOW,
+ MNG_UINT_TERM,
+ MNG_UINT_bKGD,
+ MNG_UINT_cHRM,
+/* TODO: MNG_UINT_eXPI, */
+ MNG_UINT_evNT,
+/* TODO: MNG_UINT_fPRI, */
+ MNG_UINT_gAMA,
+/* TODO: MNG_UINT_hIST, */
+ MNG_UINT_iCCP,
+ MNG_UINT_iTXt,
+ MNG_UINT_nEED,
+/* TODO: MNG_UINT_oFFs, */
+/* TODO: MNG_UINT_pCAL, */
+/* TODO: MNG_UINT_pHYg, */
+/* TODO: MNG_UINT_pHYs, */
+/* TODO: MNG_UINT_sBIT, */
+/* TODO: MNG_UINT_sCAL, */
+/* TODO: MNG_UINT_sPLT, */
+ MNG_UINT_sRGB,
+ MNG_UINT_tEXt,
+ MNG_UINT_tIME,
+ MNG_UINT_tRNS,
+ MNG_UINT_zTXt,
+ };
+
+ mng_bool bOke = MNG_FALSE;
+
+ if (pData->fProcessneed) /* does the app handle it ? */
+ bOke = pData->fProcessneed ((mng_handle)pData, (mng_pchar)pKeyword);
+
+ if (!bOke)
+ { /* find the keyword length */
+ mng_uint8p pNull = pKeyword;
+ while (*pNull)
+ pNull++;
+
+ if ((pNull - pKeyword) == 4) /* test a chunk ? */
+ { /* get the chunk-id */
+ mng_chunkid iChunkid = (*pKeyword << 24) + (*(pKeyword+1) << 16) +
+ (*(pKeyword+2) << 8) + (*(pKeyword+3) );
+ /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ /* determine max index of table */
+ iTop = (sizeof (handled_chunks) / sizeof (handled_chunks [0])) - 1;
+
+ /* binary search; with 52 chunks, worst-case is 7 comparisons */
+ iLower = 0;
+ iMiddle = iTop >> 1;
+ iUpper = iTop;
+
+ do /* the binary search itself */
+ {
+ if (handled_chunks [iMiddle] < iChunkid)
+ iLower = iMiddle + 1;
+ else if (handled_chunks [iMiddle] > iChunkid)
+ iUpper = iMiddle - 1;
+ else
+ {
+ bOke = MNG_TRUE;
+ break;
+ }
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+ }
+ /* test draft ? */
+ if ((!bOke) && ((pNull - pKeyword) == 8) &&
+ (*pKeyword == 'd') && (*(pKeyword+1) == 'r') &&
+ (*(pKeyword+2) == 'a') && (*(pKeyword+3) == 'f') &&
+ (*(pKeyword+4) == 't') && (*(pKeyword+5) == ' '))
+ {
+ mng_uint32 iDraft;
+
+ iDraft = (*(pKeyword+6) - '0') * 10 + (*(pKeyword+7) - '0');
+ bOke = (mng_bool)(iDraft <= MNG_MNG_DRAFT);
+ }
+ /* test MNG 1.0/1.1 ? */
+ if ((!bOke) && ((pNull - pKeyword) == 7) &&
+ (*pKeyword == 'M') && (*(pKeyword+1) == 'N') &&
+ (*(pKeyword+2) == 'G') && (*(pKeyword+3) == '-') &&
+ (*(pKeyword+4) == '1') && (*(pKeyword+5) == '.') &&
+ ((*(pKeyword+6) == '0') || (*(pKeyword+6) == '1')))
+ bOke = MNG_TRUE;
+ /* test CACHEOFF ? */
+ if ((!bOke) && ((pNull - pKeyword) == 8) &&
+ (*pKeyword == 'C') && (*(pKeyword+1) == 'A') &&
+ (*(pKeyword+2) == 'C') && (*(pKeyword+3) == 'H') &&
+ (*(pKeyword+4) == 'E') && (*(pKeyword+5) == 'O') &&
+ (*(pKeyword+6) == 'F') && (*(pKeyword+7) == 'F'))
+ {
+ if (!pData->pFirstaniobj) /* only if caching hasn't started yet ! */
+ {
+ bOke = MNG_TRUE;
+ pData->bCacheplayback = MNG_FALSE;
+ pData->bStorechunks = MNG_FALSE;
+ }
+ }
+ }
+
+ return bOke;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+MNG_C_SPECIALFUNC (mng_special_need)
+{
+ /* let's check it */
+ mng_bool bOke = MNG_TRUE;
+ mng_uint8p pNull, pTemp, pMax;
+
+ pTemp = (mng_uint8p)((mng_needp)pChunk)->zKeywords;
+ pMax = (mng_uint8p)(pTemp + ((mng_needp)pChunk)->iKeywordssize);
+ pNull = pTemp;
+ while (*pNull)
+ pNull++;
+
+ while ((bOke) && (pNull < pMax))
+ {
+ bOke = CheckKeyword (pData, pTemp);
+ pTemp = pNull + 1;
+ pNull = pTemp;
+ while (*pNull)
+ pNull++;
+ }
+
+ if (bOke)
+ bOke = CheckKeyword (pData, pTemp);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_UNSUPPORTEDNEED);
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+MNG_C_SPECIALFUNC (mng_special_phyg)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_C_SPECIALFUNC (mng_special_dhdr)
+{
+ if ((((mng_dhdrp)pChunk)->iDeltatype == MNG_DELTATYPE_REPLACE) && (((mng_dhdrp)pChunk)->bHasblockloc))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ if ((((mng_dhdrp)pChunk)->iDeltatype == MNG_DELTATYPE_NOCHANGE) && (((mng_dhdrp)pChunk)->bHasblocksize))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasDHDR = MNG_TRUE; /* inside a DHDR-IEND block now */
+ pData->iDeltatype = ((mng_dhdrp)pChunk)->iDeltatype;
+
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_dhdr (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_C_SPECIALFUNC (mng_special_prom)
+{
+ if ((((mng_promp)pChunk)->iColortype != MNG_COLORTYPE_GRAY ) &&
+ (((mng_promp)pChunk)->iColortype != MNG_COLORTYPE_RGB ) &&
+ (((mng_promp)pChunk)->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (((mng_promp)pChunk)->iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (((mng_promp)pChunk)->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (((mng_promp)pChunk)->iSampledepth == MNG_BITDEPTH_16 )
+ ((mng_promp)pChunk)->iSampledepth = MNG_BITDEPTH_8;
+#endif
+
+ if ((((mng_promp)pChunk)->iSampledepth != MNG_BITDEPTH_1 ) &&
+ (((mng_promp)pChunk)->iSampledepth != MNG_BITDEPTH_2 ) &&
+ (((mng_promp)pChunk)->iSampledepth != MNG_BITDEPTH_4 ) &&
+ (((mng_promp)pChunk)->iSampledepth != MNG_BITDEPTH_8 )
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (((mng_promp)pChunk)->iSampledepth != MNG_BITDEPTH_16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_create_ani_prom (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_C_SPECIALFUNC (mng_special_ipng)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_retcode iRetcode = mng_create_ani_ipng (pData);
+ if (!iRetcode) /* process it */
+ iRetcode = mng_process_display_ipng (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_F_SPECIALFUNC (mng_pplt_entries)
+{
+ mng_ppltp pPPLT = (mng_ppltp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint8 iDeltatype = pPPLT->iDeltatype;
+ mng_uint32 iMax = 0;
+ mng_int32 iX, iY, iM;
+ mng_rgbpaltab aIndexentries;
+ mng_uint8arr aAlphaentries;
+ mng_uint8arr aUsedentries;
+ /* must be indexed color ! */
+ if (pData->iColortype != MNG_COLORTYPE_INDEXED)
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ for (iY = 255; iY >= 0; iY--) /* reset arrays */
+ {
+ aIndexentries [iY].iRed = 0;
+ aIndexentries [iY].iGreen = 0;
+ aIndexentries [iY].iBlue = 0;
+ aAlphaentries [iY] = 255;
+ aUsedentries [iY] = 0;
+ }
+
+ while (iRawlen) /* as long as there are entries left ... */
+ {
+ mng_uint32 iDiff;
+
+ if (iRawlen < 2)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iX = (mng_int32)(*pRawdata); /* get start and end index */
+ iM = (mng_int32)(*(pRawdata+1));
+
+ if (iM < iX)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+
+ if (iM >= (mng_int32) iMax) /* determine highest used index */
+ iMax = iM + 1;
+
+ pRawdata += 2;
+ iRawlen -= 2;
+ iDiff = (iM - iX + 1);
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGB ) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGB ) )
+ iDiff = iDiff * 3;
+ else
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGBA) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGBA ) )
+ iDiff = iDiff * 4;
+
+ if (iRawlen < iDiff)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGB ) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGB ) )
+ {
+ for (iY = iX; iY <= iM; iY++)
+ {
+ aIndexentries [iY].iRed = *pRawdata;
+ aIndexentries [iY].iGreen = *(pRawdata+1);
+ aIndexentries [iY].iBlue = *(pRawdata+2);
+ aUsedentries [iY] = 1;
+
+ pRawdata += 3;
+ iRawlen -= 3;
+ }
+ }
+ else
+ if ((iDeltatype == MNG_DELTATYPE_REPLACEALPHA) ||
+ (iDeltatype == MNG_DELTATYPE_DELTAALPHA ) )
+ {
+ for (iY = iX; iY <= iM; iY++)
+ {
+ aAlphaentries [iY] = *pRawdata;
+ aUsedentries [iY] = 1;
+
+ pRawdata++;
+ iRawlen--;
+ }
+ }
+ else
+ {
+ for (iY = iX; iY <= iM; iY++)
+ {
+ aIndexentries [iY].iRed = *pRawdata;
+ aIndexentries [iY].iGreen = *(pRawdata+1);
+ aIndexentries [iY].iBlue = *(pRawdata+2);
+ aAlphaentries [iY] = *(pRawdata+3);
+ aUsedentries [iY] = 1;
+
+ pRawdata += 4;
+ iRawlen -= 4;
+ }
+ }
+ }
+
+ switch (pData->iBitdepth) /* check maximum allowed entries for bitdepth */
+ {
+ case MNG_BITDEPTH_1 : {
+ if (iMax > 2)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ case MNG_BITDEPTH_2 : {
+ if (iMax > 4)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ case MNG_BITDEPTH_4 : {
+ if (iMax > 16)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ }
+
+ pPPLT->iCount = iMax;
+
+ for (iY = 255; iY >= 0; iY--)
+ {
+ pPPLT->aEntries [iY].iRed = aIndexentries [iY].iRed;
+ pPPLT->aEntries [iY].iGreen = aIndexentries [iY].iGreen;
+ pPPLT->aEntries [iY].iBlue = aIndexentries [iY].iBlue;
+ pPPLT->aEntries [iY].iAlpha = aAlphaentries [iY];
+ pPPLT->aEntries [iY].bUsed = (mng_bool)(aUsedentries [iY]);
+ }
+
+ { /* create animation object */
+ mng_retcode iRetcode = mng_create_ani_pplt (pData, iDeltatype, iMax,
+ aIndexentries, aAlphaentries,
+ aUsedentries);
+ if (iRetcode)
+ return iRetcode;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_C_SPECIALFUNC (mng_special_pplt)
+{
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+MNG_C_SPECIALFUNC (mng_special_ijng)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_retcode iRetcode = mng_create_ani_ijng (pData);
+ if (!iRetcode) /* process it */
+ iRetcode = mng_process_display_ijng (pData);
+ return iRetcode;
+#else
+ return MNG_NOERROR; /* done */
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_F_SPECIALFUNC (mng_drop_entries)
+{
+ mng_dropp pDROP = (mng_dropp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint32 iX;
+ mng_uint32p pEntry;
+ /* check length */
+ if ((iRawlen < 4) || ((iRawlen % 4) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ MNG_ALLOC (pData, pEntry, iRawlen);
+ pDROP->iCount = iRawlen / 4;
+ pDROP->pChunknames = (mng_ptr)pEntry;
+
+ for (iX = pDROP->iCount; iX > 0; iX--)
+ {
+ *pEntry++ = mng_get_uint32 (pRawdata);
+ pRawdata += 4;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+MNG_C_SPECIALFUNC (mng_special_drop)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+MNG_C_SPECIALFUNC (mng_special_dbyk)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+MNG_F_SPECIALFUNC (mng_ordr_entries)
+{
+ mng_ordrp pORDR = (mng_ordrp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_uint32 iX;
+ mng_ordr_entryp pEntry;
+ /* check length */
+ if ((iRawlen < 5) || ((iRawlen % 5) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ MNG_ALLOC (pData, pEntry, iRawlen);
+ pORDR->iCount = iRawlen / 5;
+ pORDR->pEntries = (mng_ptr)pEntry;
+
+ for (iX = pORDR->iCount; iX > 0; iX--)
+ {
+ pEntry->iChunkname = mng_get_uint32 (pRawdata);
+ pEntry->iOrdertype = *(pRawdata+4);
+ pEntry++;
+ pRawdata += 5;
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+MNG_C_SPECIALFUNC (mng_special_ordr)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+MNG_F_SPECIALFUNC (mng_debunk_magn)
+{
+ mng_magnp pMAGN = (mng_magnp)pChunk;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_bool bFaulty;
+ /* check length */
+ if (iRawlen > 20)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ /* following is an ugly hack to allow faulty layout caused by previous
+ versions of libmng and MNGeye, which wrote MAGN with a 16-bit
+ MethodX/MethodY (as opposed to the proper 8-bit as defined in the spec!) */
+
+ if ((iRawlen == 6) || (iRawlen == 8) || (iRawlen == 10) || (iRawlen == 12) ||
+ (iRawlen == 14) || (iRawlen == 16) || (iRawlen == 20))
+ bFaulty = MNG_TRUE; /* these lengths are all wrong */
+ else /* length 18 can be right or wrong !!! */
+ if ((iRawlen == 18) && (mng_get_uint16 (pRawdata+4) <= 5) &&
+ (mng_get_uint16 (pRawdata+6) < 256) &&
+ (mng_get_uint16 (pRawdata+8) < 256) &&
+ (mng_get_uint16 (pRawdata+10) < 256) &&
+ (mng_get_uint16 (pRawdata+12) < 256) &&
+ (mng_get_uint16 (pRawdata+14) < 256) &&
+ (mng_get_uint16 (pRawdata+16) < 256))
+ bFaulty = MNG_TRUE; /* this is very likely the wrong layout */
+ else
+ bFaulty = MNG_FALSE; /* all other cases are handled as right */
+
+ if (bFaulty) /* wrong layout ? */
+ {
+ if (iRawlen > 0) /* get the fields */
+ pMAGN->iFirstid = mng_get_uint16 (pRawdata);
+ else
+ pMAGN->iFirstid = 0;
+
+ if (iRawlen > 2)
+ pMAGN->iLastid = mng_get_uint16 (pRawdata+2);
+ else
+ pMAGN->iLastid = pMAGN->iFirstid;
+
+ if (iRawlen > 4)
+ pMAGN->iMethodX = (mng_uint8)(mng_get_uint16 (pRawdata+4));
+ else
+ pMAGN->iMethodX = 0;
+
+ if (iRawlen > 6)
+ pMAGN->iMX = mng_get_uint16 (pRawdata+6);
+ else
+ pMAGN->iMX = 1;
+
+ if (iRawlen > 8)
+ pMAGN->iMY = mng_get_uint16 (pRawdata+8);
+ else
+ pMAGN->iMY = pMAGN->iMX;
+
+ if (iRawlen > 10)
+ pMAGN->iML = mng_get_uint16 (pRawdata+10);
+ else
+ pMAGN->iML = pMAGN->iMX;
+
+ if (iRawlen > 12)
+ pMAGN->iMR = mng_get_uint16 (pRawdata+12);
+ else
+ pMAGN->iMR = pMAGN->iMX;
+
+ if (iRawlen > 14)
+ pMAGN->iMT = mng_get_uint16 (pRawdata+14);
+ else
+ pMAGN->iMT = pMAGN->iMY;
+
+ if (iRawlen > 16)
+ pMAGN->iMB = mng_get_uint16 (pRawdata+16);
+ else
+ pMAGN->iMB = pMAGN->iMY;
+
+ if (iRawlen > 18)
+ pMAGN->iMethodY = (mng_uint8)(mng_get_uint16 (pRawdata+18));
+ else
+ pMAGN->iMethodY = pMAGN->iMethodX;
+ }
+ else /* proper layout !!!! */
+ {
+ if (iRawlen > 0) /* get the fields */
+ pMAGN->iFirstid = mng_get_uint16 (pRawdata);
+ else
+ pMAGN->iFirstid = 0;
+
+ if (iRawlen > 2)
+ pMAGN->iLastid = mng_get_uint16 (pRawdata+2);
+ else
+ pMAGN->iLastid = pMAGN->iFirstid;
+
+ if (iRawlen > 4)
+ pMAGN->iMethodX = *(pRawdata+4);
+ else
+ pMAGN->iMethodX = 0;
+
+ if (iRawlen > 5)
+ pMAGN->iMX = mng_get_uint16 (pRawdata+5);
+ else
+ pMAGN->iMX = 1;
+
+ if (iRawlen > 7)
+ pMAGN->iMY = mng_get_uint16 (pRawdata+7);
+ else
+ pMAGN->iMY = pMAGN->iMX;
+
+ if (iRawlen > 9)
+ pMAGN->iML = mng_get_uint16 (pRawdata+9);
+ else
+ pMAGN->iML = pMAGN->iMX;
+
+ if (iRawlen > 11)
+ pMAGN->iMR = mng_get_uint16 (pRawdata+11);
+ else
+ pMAGN->iMR = pMAGN->iMX;
+
+ if (iRawlen > 13)
+ pMAGN->iMT = mng_get_uint16 (pRawdata+13);
+ else
+ pMAGN->iMT = pMAGN->iMY;
+
+ if (iRawlen > 15)
+ pMAGN->iMB = mng_get_uint16 (pRawdata+15);
+ else
+ pMAGN->iMB = pMAGN->iMY;
+
+ if (iRawlen > 17)
+ pMAGN->iMethodY = *(pRawdata+17);
+ else
+ pMAGN->iMethodY = pMAGN->iMethodX;
+ }
+ /* check field validity */
+ if ((pMAGN->iMethodX > 5) || (pMAGN->iMethodY > 5))
+ MNG_ERROR (pData, MNG_INVALIDMETHOD);
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+MNG_C_SPECIALFUNC (mng_special_magn)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ani_magn (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif /* MNG_SUPPORT_DISPLAY */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+MNG_F_SPECIALFUNC (mng_evnt_entries)
+{
+ mng_evntp pEVNT = (mng_evntp)pChunk;
+ mng_uint32 iRawlen;
+ mng_uint8p pRawdata;
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
+ mng_retcode iRetcode;
+#endif
+ mng_uint8p pNull;
+ mng_uint8 iEventtype;
+ mng_uint8 iMasktype;
+ mng_int32 iLeft;
+ mng_int32 iRight;
+ mng_int32 iTop;
+ mng_int32 iBottom;
+ mng_uint16 iObjectid;
+ mng_uint8 iIndex;
+ mng_uint32 iNamesize;
+ mng_uint32 iCount = 0;
+ mng_evnt_entryp pEntry = MNG_NULL;
+ mng_uint32 iX;
+
+ for (iX = 0; iX < 2; iX++)
+ {
+ iRawlen = *piRawlen;
+ pRawdata = *ppRawdata;
+
+ if (iX) /* second run ? */
+ {
+ MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_evnt_entry)));
+ pEVNT->iCount = iCount;
+ pEVNT->pEntries = pEntry;
+ }
+
+ while (iRawlen) /* anything left ? */
+ {
+ if (iRawlen < 2) /* must have at least 2 bytes ! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iEventtype = *pRawdata; /* eventtype */
+ if (iEventtype > 5)
+ MNG_ERROR (pData, MNG_INVALIDEVENT);
+
+ pRawdata++;
+
+ iMasktype = *pRawdata; /* masktype */
+ if (iMasktype > 5)
+ MNG_ERROR (pData, MNG_INVALIDMASK);
+
+ pRawdata++;
+ iRawlen -= 2;
+
+ iLeft = 0;
+ iRight = 0;
+ iTop = 0;
+ iBottom = 0;
+ iObjectid = 0;
+ iIndex = 0;
+
+ switch (iMasktype)
+ {
+ case 1 :
+ {
+ if (iRawlen > 16)
+ {
+ iLeft = mng_get_int32 (pRawdata);
+ iRight = mng_get_int32 (pRawdata+4);
+ iTop = mng_get_int32 (pRawdata+8);
+ iBottom = mng_get_int32 (pRawdata+12);
+ pRawdata += 16;
+ iRawlen -= 16;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 2 :
+ {
+ if (iRawlen > 2)
+ {
+ iObjectid = mng_get_uint16 (pRawdata);
+ pRawdata += 2;
+ iRawlen -= 2;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 3 :
+ {
+ if (iRawlen > 3)
+ {
+ iObjectid = mng_get_uint16 (pRawdata);
+ iIndex = *(pRawdata+2);
+ pRawdata += 3;
+ iRawlen -= 3;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 4 :
+ {
+ if (iRawlen > 18)
+ {
+ iLeft = mng_get_int32 (pRawdata);
+ iRight = mng_get_int32 (pRawdata+4);
+ iTop = mng_get_int32 (pRawdata+8);
+ iBottom = mng_get_int32 (pRawdata+12);
+ iObjectid = mng_get_uint16 (pRawdata+16);
+ pRawdata += 18;
+ iRawlen -= 18;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 5 :
+ {
+ if (iRawlen > 19)
+ {
+ iLeft = mng_get_int32 (pRawdata);
+ iRight = mng_get_int32 (pRawdata+4);
+ iTop = mng_get_int32 (pRawdata+8);
+ iBottom = mng_get_int32 (pRawdata+12);
+ iObjectid = mng_get_uint16 (pRawdata+16);
+ iIndex = *(pRawdata+18);
+ pRawdata += 19;
+ iRawlen -= 19;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ }
+
+ pNull = pRawdata; /* get the name length */
+ while (*pNull)
+ pNull++;
+
+ if ((pNull - pRawdata) > (mng_int32)iRawlen)
+ {
+ iNamesize = iRawlen; /* no null found; so end of evNT */
+ iRawlen = 0;
+ }
+ else
+ {
+ iNamesize = pNull - pRawdata; /* should be another entry */
+ iRawlen = iRawlen - iNamesize - 1;
+
+ if (!iRawlen) /* must not end with a null ! */
+ MNG_ERROR (pData, MNG_ENDWITHNULL);
+ }
+
+ if (!iX)
+ {
+ iCount++;
+ }
+ else
+ {
+ pEntry->iEventtype = iEventtype;
+ pEntry->iMasktype = iMasktype;
+ pEntry->iLeft = iLeft;
+ pEntry->iRight = iRight;
+ pEntry->iTop = iTop;
+ pEntry->iBottom = iBottom;
+ pEntry->iObjectid = iObjectid;
+ pEntry->iIndex = iIndex;
+ pEntry->iSegmentnamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zSegmentname, iNamesize+1);
+ MNG_COPY (pEntry->zSegmentname, pRawdata, iNamesize);
+ }
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
+ iRetcode = mng_create_event (pData, (mng_ptr)pEntry);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+
+ pEntry++;
+ }
+
+ pRawdata = pRawdata + iNamesize + 1;
+ }
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+MNG_C_SPECIALFUNC (mng_special_evnt)
+{
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_C_SPECIALFUNC (mng_special_mpng)
+{
+ if ((pData->eImagetype != mng_it_png) && (pData->eImagetype != mng_it_jng))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_mpng_obj (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+MNG_C_SPECIALFUNC (mng_special_ahdr)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ return mng_create_ang_obj (pData, pChunk);
+#else
+ return MNG_NOERROR;
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+MNG_F_SPECIALFUNC (mng_adat_tiles)
+{
+ if ((pData->eImagetype != mng_it_ang) || (!pData->pANG))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ {
+ mng_adatp pADAT = (mng_adatp)pChunk;
+ mng_ang_objp pANG = (mng_ang_objp)pData->pANG;
+ mng_uint32 iRawlen = *piRawlen;
+ mng_uint8p pRawdata = *ppRawdata;
+ mng_retcode iRetcode;
+ mng_uint8p pBuf;
+ mng_uint32 iBufsize;
+ mng_uint32 iRealsize;
+ mng_uint8p pTemp;
+ mng_uint8p pTemp2;
+ mng_int32 iX;
+ mng_int32 iSize;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_imagep pImage;
+ mng_int32 iTemplen;
+ mng_uint8p pSwap;
+
+ mng_processobject pProcess;
+
+ mng_uint32 iSavedatawidth;
+ mng_uint32 iSavedataheight;
+
+ mng_fptr fSaveinitrowproc;
+ mng_fptr fSavestorerow;
+ mng_fptr fSaveprocessrow;
+ mng_fptr fSavedifferrow;
+ mng_imagep fSavestoreobj;
+ mng_imagedatap fSavestorebuf;
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ png_imgtype eSavepngimgtype;
+#endif
+
+ mng_uint8 iSaveinterlace;
+ mng_int8 iSavepass;
+ mng_int32 iSaverow;
+ mng_int32 iSaverowinc;
+ mng_int32 iSavecol;
+ mng_int32 iSavecolinc;
+ mng_int32 iSaverowsamples;
+ mng_int32 iSavesamplemul;
+ mng_int32 iSavesampleofs;
+ mng_int32 iSavesamplediv;
+ mng_int32 iSaverowsize;
+ mng_int32 iSaverowmax;
+ mng_int32 iSavefilterofs;
+ mng_int32 iSavepixelofs;
+ mng_uint32 iSavelevel0;
+ mng_uint32 iSavelevel1;
+ mng_uint32 iSavelevel2;
+ mng_uint32 iSavelevel3;
+ mng_uint8p pSaveworkrow;
+ mng_uint8p pSaveprevrow;
+ mng_uint8p pSaverGBArow;
+ mng_bool bSaveisRGBA16;
+ mng_bool bSaveisOpaque;
+ mng_int32 iSavefilterbpp;
+
+ mng_int32 iSavedestl;
+ mng_int32 iSavedestt;
+ mng_int32 iSavedestr;
+ mng_int32 iSavedestb;
+ mng_int32 iSavesourcel;
+ mng_int32 iSavesourcet;
+ mng_int32 iSavesourcer;
+ mng_int32 iSavesourceb;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ iRetcode = mng_inflate_buffer (pData, pRawdata, iRawlen,
+ &pBuf, &iBufsize, &iRealsize);
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ /* get buffer for tile info in ADAT chunk */
+ pADAT->iTilessize = pANG->iNumframes * sizeof(mng_adat_tile);
+ MNG_ALLOCX (pData, pADAT->pTiles, pADAT->iTilessize);
+ if (!pADAT->pTiles)
+ {
+ pADAT->iTilessize = 0;
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ pTemp = pBuf;
+ pTemp2 = (mng_uint8p)pADAT->pTiles;
+
+ if (!pANG->iStillused)
+ iSize = 12;
+ else
+ iSize = 13;
+
+ for (iX = 0; iX < pANG->iNumframes; iX++)
+ {
+ MNG_COPY (pTemp2, pTemp, iSize);
+ pTemp += iSize;
+ pTemp2 += sizeof(mng_adat_tile);
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ /* get buffer for tile info in ANG object */
+ pANG->iTilessize = pADAT->iTilessize;
+ MNG_ALLOCX (pData, pANG->pTiles, pANG->iTilessize);
+ if (!pANG->pTiles)
+ {
+ pANG->iTilessize = 0;
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+ /* copy it from the ADAT object */
+ MNG_COPY (pANG->pTiles, pADAT->pTiles, pANG->iTilessize);
+
+ /* save IDAT work-parms */
+ fSaveinitrowproc = pData->fInitrowproc;
+ fSavestorerow = pData->fDisplayrow;
+ fSaveprocessrow = pData->fProcessrow;
+ fSavedifferrow = pData->fDifferrow;
+ fSavestoreobj = pData->pStoreobj;
+ fSavestorebuf = pData->pStorebuf;
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ eSavepngimgtype = pData->ePng_imgtype;
+#endif
+
+ iSavedatawidth = pData->iDatawidth;
+ iSavedataheight = pData->iDataheight;
+ iSaveinterlace = pData->iInterlace;
+ iSavepass = pData->iPass;
+ iSaverow = pData->iRow;
+ iSaverowinc = pData->iRowinc;
+ iSavecol = pData->iCol;
+ iSavecolinc = pData->iColinc;
+ iSaverowsamples = pData->iRowsamples;
+ iSavesamplemul = pData->iSamplemul;
+ iSavesampleofs = pData->iSampleofs;
+ iSavesamplediv = pData->iSamplediv;
+ iSaverowsize = pData->iRowsize;
+ iSaverowmax = pData->iRowmax;
+ iSavefilterofs = pData->iFilterofs;
+ iSavepixelofs = pData->iPixelofs;
+ iSavelevel0 = pData->iLevel0;
+ iSavelevel1 = pData->iLevel1;
+ iSavelevel2 = pData->iLevel2;
+ iSavelevel3 = pData->iLevel3;
+ pSaveworkrow = pData->pWorkrow;
+ pSaveprevrow = pData->pPrevrow;
+ pSaverGBArow = pData->pRGBArow;
+ bSaveisRGBA16 = pData->bIsRGBA16;
+ bSaveisOpaque = pData->bIsOpaque;
+ iSavefilterbpp = pData->iFilterbpp;
+ iSavedestl = pData->iDestl;
+ iSavedestt = pData->iDestt;
+ iSavedestr = pData->iDestr;
+ iSavedestb = pData->iDestb;
+ iSavesourcel = pData->iSourcel;
+ iSavesourcet = pData->iSourcet;
+ iSavesourcer = pData->iSourcer;
+ iSavesourceb = pData->iSourceb;
+
+ pData->iDatawidth = pANG->iTilewidth;
+ pData->iDataheight = pANG->iTileheight;
+
+ pData->iDestl = 0;
+ pData->iDestt = 0;
+ pData->iDestr = pANG->iTilewidth;
+ pData->iDestb = pANG->iTileheight;
+ pData->iSourcel = 0;
+ pData->iSourcet = 0;
+ pData->iSourcer = pANG->iTilewidth;
+ pData->iSourceb = pANG->iTileheight;
+
+ pData->fInitrowproc = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ pData->fDifferrow = MNG_NULL;
+
+ /* clone image object to store the pixel-data from object 0 */
+ iRetcode = mng_clone_imageobject (pData, 1, MNG_FALSE, MNG_FALSE, MNG_FALSE,
+ MNG_FALSE, 0, 0, 0, pData->pObjzero, &pImage);
+ if (iRetcode) /* on error, drop temp buffer and bail */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ /* make sure we got the right dimensions and interlacing */
+ iRetcode = mng_reset_object_details (pData, pImage, pANG->iTilewidth, pANG->iTileheight,
+ pImage->pImgbuf->iBitdepth, pImage->pImgbuf->iColortype,
+ pImage->pImgbuf->iCompression, pImage->pImgbuf->iFilter,
+ pANG->iInterlace, MNG_FALSE);
+ if (iRetcode) /* on error, drop temp buffer and bail */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ pData->pStoreobj = pImage;
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+ pData->ePng_imgtype = mng_png_imgtype(pData->iColortype,pData->iBitdepth);
+#else
+ switch (pData->iColortype) /* determine row initialization routine */
+ {
+ case 0 : { /* gray */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_i;
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 2 : { /* rgb */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_i;
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 3 : { /* indexed */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_i;
+
+ break;
+ }
+ }
+
+ break;
+ }
+ case 4 : { /* gray+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_i;
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 6 : { /* rgb+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ }
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+ pData->iFilterofs = 0; /* determine filter characteristics */
+ pData->iLevel0 = 0; /* default levels */
+ pData->iLevel1 = 0;
+ pData->iLevel2 = 0;
+ pData->iLevel3 = 0;
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ {
+ switch (pData->iColortype)
+ {
+ case 0 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 1;
+ else
+ pData->iFilterofs = 2;
+
+ break;
+ }
+ case 2 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 3;
+ else
+ pData->iFilterofs = 6;
+
+ break;
+ }
+ case 3 : {
+ pData->iFilterofs = 1;
+ break;
+ }
+ case 4 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 2;
+ else
+ pData->iFilterofs = 4;
+
+ break;
+ }
+ case 6 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 4;
+ else
+ pData->iFilterofs = 8;
+
+ break;
+ }
+ }
+ }
+#endif
+
+#ifdef FILTER193 /* no adaptive filtering ? */
+ if (pData->iFilter == MNG_FILTER_NOFILTER)
+ pData->iPixelofs = pData->iFilterofs;
+ else
+#endif
+ pData->iPixelofs = pData->iFilterofs + 1;
+
+ if (pData->fInitrowproc) /* need to initialize row processing? */
+ {
+ iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData);
+ if (iRetcode)
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+ /* calculate remainder of buffer */
+ pTemp = pBuf + (mng_int32)(pANG->iNumframes * iSize);
+ iTemplen = iRealsize - (mng_int32)(pANG->iNumframes * iSize);
+
+ do
+ {
+ if (iTemplen > pData->iRowmax) /* get a pixel-row from the temp buffer */
+ {
+ MNG_COPY (pData->pWorkrow, pTemp, pData->iRowmax);
+ }
+ else
+ {
+ MNG_COPY (pData->pWorkrow, pTemp, iTemplen);
+ }
+
+ { /* image not completed yet ? */
+ if (pData->iRow < (mng_int32)pData->iDataheight)
+ {
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iPNGdepth == 1)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (pData->iRowsize+7)/8;
+
+ for (iX = ((pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>7)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>6)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>5)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>4)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>3)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>2)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>1)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&1);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ else if (pData->iPNGdepth == 2)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (2*pData->iRowsize+7)/8;
+
+ for (iX = ((2*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (2*pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>6)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>4)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>2)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&3);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ else if (pData->iPNGdepth == 4)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (4*pData->iRowsize+7)/8;
+
+ for (iX = ((4*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (4*pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>4)&0x0f);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&0x0f);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ if (pData->iPNGdepth < 8 && pData->iColortype == 0)
+ {
+ /* Expand samples to 8-bit by LBR */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1};
+
+ for (iX = pData->iRowsize; iX > 0; iX--)
+ *pSrc++ *= multiplier[pData->iPNGdepth];
+ }
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iPNGdepth > 8)
+ {
+ /* Reduce Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc;
+
+ for (iX = pData->iRowsize; iX > 0; iX--)
+ {
+ *pDest = *pSrc;
+ pDest++;
+ pSrc+=2;
+ }
+ }
+#endif
+
+#ifdef FILTER192 /* has leveling info ? */
+ if (pData->iFilterofs == MNG_FILTER_DIFFERING)
+ iRetcode = init_rowdiffering (pData);
+ else
+#endif
+ iRetcode = MNG_NOERROR;
+ /* filter the row if necessary */
+ if ((!iRetcode) && (pData->iFilterofs < pData->iPixelofs ) &&
+ (*(pData->pWorkrow + pData->iFilterofs)) )
+ iRetcode = mng_filter_a_row (pData);
+
+ /* additional leveling/differing ? */
+ if ((!iRetcode) && (pData->fDifferrow))
+ {
+ iRetcode = ((mng_differrow)pData->fDifferrow) (pData);
+
+ pSwap = pData->pWorkrow;
+ pData->pWorkrow = pData->pPrevrow;
+ pData->pPrevrow = pSwap; /* make sure we're processing the right data */
+ }
+
+ if (!iRetcode)
+ {
+ { /* process this row */
+ if ((!iRetcode) && (pData->fProcessrow))
+ iRetcode = ((mng_processrow)pData->fProcessrow) (pData);
+ /* store in object ? */
+ if ((!iRetcode) && (pData->fStorerow))
+ iRetcode = ((mng_storerow)pData->fStorerow) (pData);
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, iRetcode);
+ }
+
+ if (!pData->fDifferrow) /* swap row-pointers */
+ {
+ pSwap = pData->pWorkrow;
+ pData->pWorkrow = pData->pPrevrow;
+ pData->pPrevrow = pSwap; /* so prev points to the processed row! */
+ }
+ /* adjust variables for next row */
+ iRetcode = mng_next_row (pData);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, iRetcode);
+ }
+ }
+ }
+
+ pTemp += pData->iRowmax;
+ iTemplen -= pData->iRowmax;
+ } /* until some error or EOI
+ or all pixels received */
+ while ( (iTemplen > 0) &&
+ ( (pData->iRow < (mng_int32)pData->iDataheight) ||
+ ( (pData->iPass >= 0) && (pData->iPass < 7) ) ) );
+
+ mng_cleanup_rowproc (pData); /* cleanup row processing buffers !! */
+
+ /* restore saved work-parms */
+ pData->iDatawidth = iSavedatawidth;
+ pData->iDataheight = iSavedataheight;
+
+ pData->fInitrowproc = fSaveinitrowproc;
+ pData->fDisplayrow = fSavestorerow;
+ pData->fProcessrow = fSaveprocessrow;
+ pData->fDifferrow = fSavedifferrow;
+ pData->pStoreobj = fSavestoreobj;
+ pData->pStorebuf = fSavestorebuf;
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->ePng_imgtype = eSavepngimgtype;
+#endif
+
+ pData->iInterlace = iSaveinterlace;
+ pData->iPass = iSavepass;
+ pData->iRow = iSaverow;
+ pData->iRowinc = iSaverowinc;
+ pData->iCol = iSavecol;
+ pData->iColinc = iSavecolinc;
+ pData->iRowsamples = iSaverowsamples;
+ pData->iSamplemul = iSavesamplemul;
+ pData->iSampleofs = iSavesampleofs;
+ pData->iSamplediv = iSavesamplediv;
+ pData->iRowsize = iSaverowsize;
+ pData->iRowmax = iSaverowmax;
+ pData->iFilterofs = iSavefilterofs;
+ pData->iPixelofs = iSavepixelofs;
+ pData->iLevel0 = iSavelevel0;
+ pData->iLevel1 = iSavelevel1;
+ pData->iLevel2 = iSavelevel2;
+ pData->iLevel3 = iSavelevel3;
+ pData->pWorkrow = pSaveworkrow;
+ pData->pPrevrow = pSaveprevrow;
+ pData->pRGBArow = pSaverGBArow;
+ pData->bIsRGBA16 = bSaveisRGBA16;
+ pData->bIsOpaque = bSaveisOpaque;
+ pData->iFilterbpp = iSavefilterbpp;
+ pData->iDestl = iSavedestl;
+ pData->iDestt = iSavedestt;
+ pData->iDestr = iSavedestr;
+ pData->iDestb = iSavedestb;
+ pData->iSourcel = iSavesourcel;
+ pData->iSourcet = iSavesourcet;
+ pData->iSourcer = iSavesourcer;
+ pData->iSourceb = iSavesourceb;
+
+ /* create the animation directives ! */
+ pProcess = (mng_processobject)pANG->sHeader.fProcess;
+ iRetcode = pProcess (pData, (mng_objectp)pData->pANG);
+ if (iRetcode)
+ return iRetcode;
+
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ MNG_FREE (pData, pBuf, iBufsize); /* always free the temp buffer ! */
+ }
+
+ *piRawlen = 0;
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+MNG_C_SPECIALFUNC (mng_special_adat)
+{
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+MNG_C_SPECIALFUNC (mng_special_unknown)
+{
+ /* critical chunk ? */
+ if ((((mng_uint32)pData->iChunkname & 0x20000000) == 0)
+#ifdef MNG_SKIPCHUNK_SAVE
+ && (pData->iChunkname != MNG_UINT_SAVE)
+#endif
+#ifdef MNG_SKIPCHUNK_SEEK
+ && (pData->iChunkname != MNG_UINT_SEEK)
+#endif
+#ifdef MNG_SKIPCHUNK_DBYK
+ && (pData->iChunkname != MNG_UINT_DBYK)
+#endif
+#ifdef MNG_SKIPCHUNK_ORDR
+ && (pData->iChunkname != MNG_UINT_ORDR)
+#endif
+ )
+ MNG_ERROR (pData, MNG_UNKNOWNCRITICAL);
+
+ if (pData->fProcessunknown) /* let the app handle it ? */
+ {
+ mng_bool bOke = pData->fProcessunknown ((mng_handle)pData, pData->iChunkname,
+ ((mng_unknown_chunkp)pChunk)->iDatasize,
+ ((mng_unknown_chunkp)pChunk)->pData);
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_READ_PROCS || MNG_INCLUDE_WRITE_PROCS */
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
+
+
+
diff --git a/Source/LibMNG/libmng_chunk_descr.h b/Source/LibMNG/libmng_chunk_descr.h
new file mode 100644
index 0000000..3781ab0
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_descr.h
@@ -0,0 +1,146 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_descr.h copyright (c) 2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk descriptor functions (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : definition of the chunk- anf field-descriptor routines * */
+/* * * */
+/* * changes : 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_chunk_descr_h_
+#define _libmng_chunk_descr_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+#if defined(MNG_INCLUDE_READ_PROCS) || defined(MNG_INCLUDE_WRITE_PROCS)
+
+/* ************************************************************************** */
+
+void mng_get_chunkheader (mng_chunkid iChunkname,
+ mng_chunk_headerp pResult);
+
+/* ************************************************************************** */
+
+#define MNG_F_SPECIALFUNC(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pChunk, \
+ mng_uint32* piRawlen, \
+ mng_uint8p* ppRawdata)
+
+MNG_F_SPECIALFUNC (mng_debunk_plte) ;
+MNG_F_SPECIALFUNC (mng_debunk_trns) ;
+MNG_F_SPECIALFUNC (mng_deflate_itxt) ;
+MNG_F_SPECIALFUNC (mng_splt_entries) ;
+MNG_F_SPECIALFUNC (mng_hist_entries) ;
+
+MNG_F_SPECIALFUNC (mng_debunk_loop) ;
+MNG_F_SPECIALFUNC (mng_debunk_past) ;
+MNG_F_SPECIALFUNC (mng_disc_entries) ;
+MNG_F_SPECIALFUNC (mng_fram_remainder) ;
+MNG_F_SPECIALFUNC (mng_save_entries) ;
+MNG_F_SPECIALFUNC (mng_pplt_entries) ;
+MNG_F_SPECIALFUNC (mng_drop_entries) ;
+MNG_F_SPECIALFUNC (mng_ordr_entries) ;
+MNG_F_SPECIALFUNC (mng_debunk_magn) ;
+MNG_F_SPECIALFUNC (mng_evnt_entries) ;
+MNG_F_SPECIALFUNC (mng_adat_tiles) ;
+
+/* ************************************************************************** */
+
+#define MNG_C_SPECIALFUNC(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pChunk)
+
+MNG_C_SPECIALFUNC (mng_special_ihdr) ;
+MNG_C_SPECIALFUNC (mng_special_plte) ;
+MNG_C_SPECIALFUNC (mng_special_idat) ;
+MNG_C_SPECIALFUNC (mng_special_iend) ;
+MNG_C_SPECIALFUNC (mng_special_trns) ;
+MNG_C_SPECIALFUNC (mng_special_gama) ;
+MNG_C_SPECIALFUNC (mng_special_chrm) ;
+MNG_C_SPECIALFUNC (mng_special_srgb) ;
+MNG_C_SPECIALFUNC (mng_special_iccp) ;
+MNG_C_SPECIALFUNC (mng_special_text) ;
+MNG_C_SPECIALFUNC (mng_special_ztxt) ;
+MNG_C_SPECIALFUNC (mng_special_itxt) ;
+MNG_C_SPECIALFUNC (mng_special_bkgd) ;
+MNG_C_SPECIALFUNC (mng_special_phys) ;
+MNG_C_SPECIALFUNC (mng_special_sbit) ;
+MNG_C_SPECIALFUNC (mng_special_splt) ;
+MNG_C_SPECIALFUNC (mng_special_hist) ;
+MNG_C_SPECIALFUNC (mng_special_time) ;
+
+MNG_C_SPECIALFUNC (mng_special_jhdr) ;
+MNG_C_SPECIALFUNC (mng_special_jdaa) ;
+MNG_C_SPECIALFUNC (mng_special_jdat) ;
+MNG_C_SPECIALFUNC (mng_special_jsep) ;
+
+MNG_C_SPECIALFUNC (mng_special_mhdr) ;
+MNG_C_SPECIALFUNC (mng_special_mend) ;
+MNG_C_SPECIALFUNC (mng_special_loop) ;
+MNG_C_SPECIALFUNC (mng_special_endl) ;
+MNG_C_SPECIALFUNC (mng_special_defi) ;
+MNG_C_SPECIALFUNC (mng_special_basi) ;
+MNG_C_SPECIALFUNC (mng_special_clon) ;
+MNG_C_SPECIALFUNC (mng_special_past) ;
+MNG_C_SPECIALFUNC (mng_special_disc) ;
+MNG_C_SPECIALFUNC (mng_special_back) ;
+MNG_C_SPECIALFUNC (mng_special_fram) ;
+MNG_C_SPECIALFUNC (mng_special_move) ;
+MNG_C_SPECIALFUNC (mng_special_clip) ;
+MNG_C_SPECIALFUNC (mng_special_show) ;
+MNG_C_SPECIALFUNC (mng_special_term) ;
+MNG_C_SPECIALFUNC (mng_special_save) ;
+MNG_C_SPECIALFUNC (mng_special_seek) ;
+MNG_C_SPECIALFUNC (mng_special_expi) ;
+MNG_C_SPECIALFUNC (mng_special_fpri) ;
+MNG_C_SPECIALFUNC (mng_special_need) ;
+MNG_C_SPECIALFUNC (mng_special_phyg) ;
+
+MNG_C_SPECIALFUNC (mng_special_dhdr) ;
+MNG_C_SPECIALFUNC (mng_special_prom) ;
+MNG_C_SPECIALFUNC (mng_special_ipng) ;
+MNG_C_SPECIALFUNC (mng_special_pplt) ;
+MNG_C_SPECIALFUNC (mng_special_ijng) ;
+MNG_C_SPECIALFUNC (mng_special_drop) ;
+MNG_C_SPECIALFUNC (mng_special_dbyk) ;
+MNG_C_SPECIALFUNC (mng_special_ordr) ;
+
+MNG_C_SPECIALFUNC (mng_special_magn) ;
+MNG_C_SPECIALFUNC (mng_special_evnt) ;
+MNG_C_SPECIALFUNC (mng_special_mpng) ;
+MNG_C_SPECIALFUNC (mng_special_ahdr) ;
+MNG_C_SPECIALFUNC (mng_special_adat) ;
+MNG_C_SPECIALFUNC (mng_special_unknown) ;
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_READ_PROCS) || MNG_INCLUDE_WRITE_PROCS */
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_chunk_descr_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_chunk_io.c b/Source/LibMNG/libmng_chunk_io.c
new file mode 100644
index 0000000..eb18099
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_io.c
@@ -0,0 +1,10740 @@
+/** ************************************************************************* */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_io.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk I/O routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of chunk input/output routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/01/2000 - G.Juyn * */
+/* * - cleaned up left-over teststuff in the BACK chunk routine * */
+/* * 0.5.1 - 05/04/2000 - G.Juyn * */
+/* * - changed CRC initialization to use dynamic structure * */
+/* * (wasn't thread-safe the old way !) * */
+/* * 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - filled in many missing sequence&length checks * */
+/* * - filled in many missing chunk-store snippets * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - added checks for running animations * */
+/* * - filled some write routines * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/10/2000 - G.Juyn * */
+/* * - filled some more write routines * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - filled remaining write routines * */
+/* * - fixed read_pplt with regard to deltatype * */
+/* * - added callback error-reporting support * */
+/* * - added pre-draft48 support (short MHDR, frame_mode, LOOP) * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * - fixed chunk-storage bit in several routines * */
+/* * 0.5.1 - 05/13/2000 - G.Juyn * */
+/* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
+/* * - added TERM animation object pointer (easier reference) * */
+/* * - supplemented the SAVE & SEEK display processing * */
+/* * * */
+/* * 0.5.2 - 05/18/2000 - G.Juyn * */
+/* * - B004 - fixed problem with MNG_SUPPORT_WRITE not defined * */
+/* * also for MNG_SUPPORT_WRITE without MNG_INCLUDE_JNG * */
+/* * 0.5.2 - 05/19/2000 - G.Juyn * */
+/* * - cleaned up some code regarding mixed support * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - implemented JNG support * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added support for global color-chunks in animation * */
+/* * - added support for global PLTE,tRNS,bKGD in animation * */
+/* * - added support for SAVE & SEEK in animation * */
+/* * 0.5.2 - 05/29/2000 - G.Juyn * */
+/* * - changed ani_create calls not returning object pointer * */
+/* * - create ani objects always (not just inside TERM/LOOP) * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added support for delta-image processing * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed up punctuation (contributed by Tim Rowley) * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - changed SWAP_ENDIAN to BIGENDIAN_SUPPORTED * */
+/* * 0.5.2 - 06/03/2000 - G.Juyn * */
+/* * - fixed makeup for Linux gcc compile * */
+/* * * */
+/* * 0.5.3 - 06/12/2000 - G.Juyn * */
+/* * - added processing of color-info on delta-image * */
+/* * 0.5.3 - 06/13/2000 - G.Juyn * */
+/* * - fixed handling of empty SAVE chunk * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - changed to support delta-images * */
+/* * - added extra checks for delta-images * */
+/* * 0.5.3 - 06/20/2000 - G.Juyn * */
+/* * - fixed possible trouble if IEND display-process got * */
+/* * broken up * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added processing of PLTE & tRNS for delta-images * */
+/* * - added administration of imagelevel parameter * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - implemented support for PPLT chunk * */
+/* * 0.5.3 - 06/26/2000 - G.Juyn * */
+/* * - added precaution against faulty iCCP chunks from PS * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - fixed some 64-bit warnings * */
+/* * * */
+/* * 0.9.1 - 07/14/2000 - G.Juyn * */
+/* * - changed pre-draft48 frame_mode=3 to frame_mode=1 * */
+/* * 0.9.1 - 07/16/2000 - G.Juyn * */
+/* * - fixed storage of images during mng_read() * */
+/* * - fixed support for mng_display() after mng_read() * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - fixed several chunk-writing routines * */
+/* * 0.9.1 - 07/24/2000 - G.Juyn * */
+/* * - fixed reading of still-images * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/08/2000 - G.Juyn * */
+/* * - fixed compiler-warnings from Mozilla * */
+/* * 0.9.3 - 08/09/2000 - G.Juyn * */
+/* * - added check for simplicity-bits in MHDR * */
+/* * 0.9.3 - 08/12/2000 - G.Juyn * */
+/* * - fixed check for simplicity-bits in MHDR (JNG) * */
+/* * 0.9.3 - 08/12/2000 - G.Juyn * */
+/* * - added workaround for faulty PhotoShop iCCP chunk * */
+/* * 0.9.3 - 08/22/2000 - G.Juyn * */
+/* * - fixed write-code for zTXt & iTXt * */
+/* * - fixed read-code for iTXt * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/02/2000 - G.Juyn * */
+/* * - fixed simplicity-check in compliance with draft 81/0.98a * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - fixed support for MAGN * */
+/* * - implemented nEED "xxxx" (where "xxxx" is a chunkid) * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * - fixed support for bKGD * */
+/* * 0.9.3 - 10/23/2000 - G.Juyn * */
+/* * - fixed bug in empty PLTE handling * */
+/* * * */
+/* * 0.9.4 - 11/20/2000 - G.Juyn * */
+/* * - changed IHDR filter_method check for PNGs * */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - added errorchecking for MAGN methods * */
+/* * - removed test filter-methods 1 & 65 * */
+/* * * */
+/* * 0.9.5 - 1/25/2001 - G.Juyn * */
+/* * - fixed some small compiler warnings (thanks Nikki) * */
+/* * * */
+/* * 1.0.2 - 05/05/2000 - G.Juyn * */
+/* * - B421427 - writes wrong format in bKGD and tRNS * */
+/* * 1.0.2 - 06/20/2000 - G.Juyn * */
+/* * - B434583 - compiler-warning if MNG_STORE_CHUNKS undefined * */
+/* * * */
+/* * 1.0.5 - 07/08/2002 - G.Juyn * */
+/* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
+/* * 1.0.5 - 08/07/2002 - G.Juyn * */
+/* * - added test-option for PNG filter method 193 (=no filter) * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/07/2002 - G.Juyn * */
+/* * - fixed reading of FRAM with just frame_mode and name * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - misplaced TERM is now treated as warning * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 10/03/2002 - G.Juyn * */
+/* * - fixed chunk-storage for evNT chunk * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - fixed DISC support * */
+/* * - added another fix for misplaced TERM chunk * */
+/* * 1.0.5 - 10/17/2002 - G.Juyn * */
+/* * - fixed initializtion of pIds in dISC read routine * */
+/* * 1.0.5 - 11/06/2002 - G.Juyn * */
+/* * - added support for nEED "MNG 1.1" * */
+/* * - added support for nEED "CACHEOFF" * */
+/* * * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 06/02/2003 - G.R-P * */
+/* * - removed some redundant checks for iRawlen==0 * */
+/* * 1.0.6 - 06/22/2003 - G.R-P * */
+/* * - added MNG_NO_16BIT_SUPPORT, MNG_NO_DELTA_PNG reductions * */
+/* * - optionally use zlib's crc32 function instead of * */
+/* * local mng_update_crc * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added conditionals around non-VLC chunk support * */
+/* * * */
+/* * 1.0.7 - 10/29/2003 - G.R-P * */
+/* * - revised JDAA and JDAT readers to avoid compiler bug * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 01/27/2004 - J.S * */
+/* * - fixed inclusion of IJNG chunk for non-JNG use * */
+/* * 1.0.7 - 02/26/2004 - G.Juyn * */
+/* * - fixed bug in chunk-storage of SHOW chunk (from == to) * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 07/07/2004 - G.R-P * */
+/* * - change worst-case iAlphadepth to 1 for standalone PNGs * */
+/* * * */
+/* * 1.0.9 - 09/28/2004 - G.R-P * */
+/* * - improved handling of cheap transparency when 16-bit * */
+/* * support is disabled * */
+/* * 1.0.9 - 10/04/2004 - G.Juyn * */
+/* * - fixed bug in writing sBIT for indexed color * */
+/* * 1.0.9 - 10/10/2004 - G.R-P. * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
+/* * 1.0.9 - 12/07/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * 1.0.9 - 01/17/2005 - G.Juyn * */
+/* * - fixed problem with global PLTE/tRNS * */
+/* * * */
+/* * 1.0.10 - 02/07/2005 - G.Juyn * */
+/* * - fixed display routines called twice for FULL_MNG * */
+/* * support in mozlibmngconf.h * */
+/* * 1.0.10 - 12/04/2005 - G.R-P. * */
+/* * - #ifdef out use of mng_inflate_buffer when it is not * */
+/* * available. * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * 1.0.10 - 05/02/2007 - G.Juyn * */
+/* * - fixed inflate_buffer for extreme compression ratios * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_objects.h"
+#include "libmng_object_prc.h"
+#include "libmng_chunks.h"
+#ifdef MNG_CHECK_BAD_ICCP
+#include "libmng_chunk_prc.h"
+#endif
+#include "libmng_memory.h"
+#include "libmng_display.h"
+#include "libmng_zlib.h"
+#include "libmng_pixels.h"
+#include "libmng_chunk_io.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * CRC - Cyclic Redundancy Check * */
+/* * * */
+/* * The code below is taken directly from the sample provided with the * */
+/* * PNG specification. * */
+/* * (it is only adapted to the library's internal data-definitions) * */
+/* * * */
+/* ************************************************************************** */
+/* Make the table for a fast CRC. */
+#ifndef MNG_USE_ZLIB_CRC
+MNG_LOCAL void make_crc_table (mng_datap pData)
+{
+ mng_uint32 iC;
+ mng_int32 iN, iK;
+
+ for (iN = 0; iN < 256; iN++)
+ {
+ iC = (mng_uint32) iN;
+
+ for (iK = 0; iK < 8; iK++)
+ {
+ if (iC & 1)
+ iC = 0xedb88320U ^ (iC >> 1);
+ else
+ iC = iC >> 1;
+ }
+
+ pData->aCRCtable [iN] = iC;
+ }
+
+ pData->bCRCcomputed = MNG_TRUE;
+}
+#endif
+
+/* Update a running CRC with the bytes buf[0..len-1]--the CRC
+ should be initialized to all 1's, and the transmitted value
+ is the 1's complement of the final running CRC (see the
+ crc() routine below). */
+
+MNG_LOCAL mng_uint32 update_crc (mng_datap pData,
+ mng_uint32 iCrc,
+ mng_uint8p pBuf,
+ mng_int32 iLen)
+{
+#ifdef MNG_USE_ZLIB_CRC
+ return crc32 (iCrc, pBuf, iLen);
+#else
+ mng_uint32 iC = iCrc;
+ mng_int32 iN;
+
+ if (!pData->bCRCcomputed)
+ make_crc_table (pData);
+
+ for (iN = 0; iN < iLen; iN++)
+ iC = pData->aCRCtable [(iC ^ pBuf [iN]) & 0xff] ^ (iC >> 8);
+
+ return iC;
+#endif
+}
+
+/* Return the CRC of the bytes buf[0..len-1]. */
+mng_uint32 mng_crc (mng_datap pData,
+ mng_uint8p pBuf,
+ mng_int32 iLen)
+{
+#ifdef MNG_USE_ZLIB_CRC
+ return update_crc (pData, 0, pBuf, iLen);
+#else
+ return update_crc (pData, 0xffffffffU, pBuf, iLen) ^ 0xffffffffU;
+#endif
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Routines for swapping byte-order from and to graphic files * */
+/* * (This code is adapted from the libpng package) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+
+/* ************************************************************************** */
+
+mng_uint32 mng_get_uint32 (mng_uint8p pBuf)
+{
+ mng_uint32 i = ((mng_uint32)(*pBuf) << 24) +
+ ((mng_uint32)(*(pBuf + 1)) << 16) +
+ ((mng_uint32)(*(pBuf + 2)) << 8) +
+ (mng_uint32)(*(pBuf + 3));
+ return (i);
+}
+
+/* ************************************************************************** */
+
+mng_int32 mng_get_int32 (mng_uint8p pBuf)
+{
+ mng_int32 i = ((mng_int32)(*pBuf) << 24) +
+ ((mng_int32)(*(pBuf + 1)) << 16) +
+ ((mng_int32)(*(pBuf + 2)) << 8) +
+ (mng_int32)(*(pBuf + 3));
+ return (i);
+}
+
+/* ************************************************************************** */
+
+mng_uint16 mng_get_uint16 (mng_uint8p pBuf)
+{
+ mng_uint16 i = (mng_uint16)(((mng_uint16)(*pBuf) << 8) +
+ (mng_uint16)(*(pBuf + 1)));
+ return (i);
+}
+
+/* ************************************************************************** */
+
+void mng_put_uint32 (mng_uint8p pBuf,
+ mng_uint32 i)
+{
+ *pBuf = (mng_uint8)((i >> 24) & 0xff);
+ *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
+ *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
+ *(pBuf+3) = (mng_uint8)(i & 0xff);
+}
+
+/* ************************************************************************** */
+
+void mng_put_int32 (mng_uint8p pBuf,
+ mng_int32 i)
+{
+ *pBuf = (mng_uint8)((i >> 24) & 0xff);
+ *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
+ *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
+ *(pBuf+3) = (mng_uint8)(i & 0xff);
+}
+
+/* ************************************************************************** */
+
+void mng_put_uint16 (mng_uint8p pBuf,
+ mng_uint16 i)
+{
+ *pBuf = (mng_uint8)((i >> 8) & 0xff);
+ *(pBuf+1) = (mng_uint8)(i & 0xff);
+}
+
+/* ************************************************************************** */
+
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+
+/* ************************************************************************** */
+/* * * */
+/* * Helper routines to simplify chunk-data extraction * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_READ_PROCS
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+MNG_LOCAL mng_uint8p find_null (mng_uint8p pIn)
+{
+ mng_uint8p pOut = pIn;
+ while (*pOut) /* the read_graphic routine has made sure there's */
+ pOut++; /* always at least 1 zero-byte in the buffer */
+ return pOut;
+}
+#endif
+
+/* ************************************************************************** */
+
+#if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
+ !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
+ defined(MNG_INCLUDE_ANG_PROPOSAL)
+mng_retcode mng_inflate_buffer (mng_datap pData,
+ mng_uint8p pInbuf,
+ mng_uint32 iInsize,
+ mng_uint8p *pOutbuf,
+ mng_uint32 *iOutsize,
+ mng_uint32 *iRealsize)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_START);
+#endif
+
+ if (iInsize) /* anything to do ? */
+ {
+ *iOutsize = iInsize * 3; /* estimate uncompressed size */
+ /* and allocate a temporary buffer */
+ MNG_ALLOC (pData, *pOutbuf, *iOutsize);
+
+ do
+ {
+ mngzlib_inflateinit (pData); /* initialize zlib */
+ /* let zlib know where to store the output */
+ pData->sZlib.next_out = *pOutbuf;
+ /* "size - 1" so we've got space for the
+ zero-termination of a possible string */
+ pData->sZlib.avail_out = *iOutsize - 1;
+ /* ok; let's inflate... */
+ iRetcode = mngzlib_inflatedata (pData, iInsize, pInbuf);
+ /* determine actual output size */
+ *iRealsize = (mng_uint32)pData->sZlib.total_out;
+
+ mngzlib_inflatefree (pData); /* zlib's done */
+
+ if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
+ { /* then get some more */
+ MNG_FREEX (pData, *pOutbuf, *iOutsize);
+ *iOutsize = *iOutsize + *iOutsize;
+ MNG_ALLOC (pData, *pOutbuf, *iOutsize);
+ }
+ } /* repeat if we didn't have enough space */
+ while ((iRetcode == MNG_BUFOVERFLOW) &&
+ (*iOutsize < 200 * iInsize));
+
+ if (!iRetcode) /* if oke ? */
+ *((*pOutbuf) + *iRealsize) = 0; /* then put terminator zero */
+
+ }
+ else
+ {
+ *pOutbuf = 0; /* nothing to do; then there's no output */
+ *iOutsize = 0;
+ *iRealsize = 0;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_READ_PROCS */
+
+/* ************************************************************************** */
+/* * * */
+/* * Helper routines to simplify chunk writing * */
+/* * * */
+/* ************************************************************************** */
+#ifdef MNG_INCLUDE_WRITE_PROCS
+/* ************************************************************************** */
+
+#if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || !defined(MNG_SKIPCHUNK_iTXt)
+MNG_LOCAL mng_retcode deflate_buffer (mng_datap pData,
+ mng_uint8p pInbuf,
+ mng_uint32 iInsize,
+ mng_uint8p *pOutbuf,
+ mng_uint32 *iOutsize,
+ mng_uint32 *iRealsize)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_START);
+#endif
+
+ if (iInsize) /* anything to do ? */
+ {
+ *iOutsize = (iInsize * 5) >> 2; /* estimate compressed size */
+ /* and allocate a temporary buffer */
+ MNG_ALLOC (pData, *pOutbuf, *iOutsize);
+
+ do
+ {
+ mngzlib_deflateinit (pData); /* initialize zlib */
+ /* let zlib know where to store the output */
+ pData->sZlib.next_out = *pOutbuf;
+ pData->sZlib.avail_out = *iOutsize;
+ /* ok; let's deflate... */
+ iRetcode = mngzlib_deflatedata (pData, iInsize, pInbuf);
+ /* determine actual output size */
+ *iRealsize = pData->sZlib.total_out;
+
+ mngzlib_deflatefree (pData); /* zlib's done */
+
+ if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
+ { /* then get some more */
+ MNG_FREEX (pData, *pOutbuf, *iOutsize);
+ *iOutsize = *iOutsize + (iInsize >> 1);
+ MNG_ALLOC (pData, *pOutbuf, *iOutsize);
+ }
+ } /* repeat if we didn't have enough space */
+ while (iRetcode == MNG_BUFOVERFLOW);
+ }
+ else
+ {
+ *pOutbuf = 0; /* nothing to do; then there's no output */
+ *iOutsize = 0;
+ *iRealsize = 0;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode write_raw_chunk (mng_datap pData,
+ mng_chunkid iChunkname,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata)
+{
+ mng_uint32 iCrc;
+ mng_uint32 iWritten;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_START);
+#endif
+ /* temporary buffer ? */
+ if ((pRawdata != 0) && (pRawdata != pData->pWritebuf+8))
+ { /* store length & chunktype in default buffer */
+ mng_put_uint32 (pData->pWritebuf, iRawlen);
+ mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
+
+ if (pData->iCrcmode & MNG_CRC_OUTPUT)
+ {
+ if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
+ { /* calculate the crc */
+ iCrc = update_crc (pData, 0xffffffffL, pData->pWritebuf+4, 4);
+ iCrc = update_crc (pData, iCrc, pRawdata, iRawlen) ^ 0xffffffffL;
+ } else {
+ iCrc = 0; /* dummy crc */
+ } /* store in default buffer */
+ mng_put_uint32 (pData->pWritebuf+8, iCrc);
+ }
+ /* write the length & chunktype */
+ if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, 8, &iWritten))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ if (iWritten != 8) /* disk full ? */
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+ /* write the temporary buffer */
+ if (!pData->fWritedata ((mng_handle)pData, pRawdata, iRawlen, &iWritten))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ if (iWritten != iRawlen) /* disk full ? */
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+
+ if (pData->iCrcmode & MNG_CRC_OUTPUT)
+ { /* write the crc */
+ if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf+8, 4, &iWritten))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ if (iWritten != 4) /* disk full ? */
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+ }
+ }
+ else
+ { /* prefix with length & chunktype */
+ mng_put_uint32 (pData->pWritebuf, iRawlen);
+ mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
+
+ if (pData->iCrcmode & MNG_CRC_OUTPUT)
+ {
+ if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
+ /* calculate the crc */
+ iCrc = mng_crc (pData, pData->pWritebuf+4, iRawlen + 4);
+ else
+ iCrc = 0; /* dummy crc */
+ /* add it to the buffer */
+ mng_put_uint32 (pData->pWritebuf + iRawlen + 8, iCrc);
+ /* write it in a single pass */
+ if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 12, &iWritten))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ if (iWritten != iRawlen + 12) /* disk full ? */
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+ } else {
+ if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 8, &iWritten))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ if (iWritten != iRawlen + 8) /* disk full ? */
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* B004 */
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+/* B004 */
+/* ************************************************************************** */
+/* * * */
+/* * chunk read functions * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_READ_PROCS
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode create_chunk_storage (mng_datap pData,
+ mng_chunkp pHeader,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata,
+ mng_field_descp pField,
+ mng_uint16 iFields,
+ mng_chunkp* ppChunk,
+ mng_bool bWorkcopy)
+{
+ mng_field_descp pTempfield = pField;
+ mng_uint16 iFieldcount = iFields;
+ mng_uint8p pTempdata = pRawdata;
+ mng_uint32 iTemplen = iRawlen;
+ mng_uint16 iLastgroup = 0;
+ mng_uint8p pChunkdata;
+ mng_uint32 iDatalen;
+ mng_uint8 iColortype;
+ mng_bool bProcess;
+ /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (((mng_chunk_headerp)(*ppChunk))->iChunkname == MNG_UINT_HUH)
+ ((mng_chunk_headerp)(*ppChunk))->iChunkname = pData->iChunkname;
+
+ if ((!bWorkcopy) ||
+ ((((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_IDAT) &&
+ (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAT) &&
+ (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAA) ))
+ {
+ pChunkdata = (mng_uint8p)(*ppChunk);
+
+#ifdef MNG_INCLUDE_JNG /* determine current colortype */
+ if (pData->bHasJHDR)
+ iColortype = (mng_uint8)(pData->iJHDRcolortype - 8);
+ else
+#endif /* MNG_INCLUDE_JNG */
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ iColortype = pData->iColortype;
+ else
+ iColortype = 6;
+
+ if (iTemplen) /* not empty ? */
+ { /* then go fill the fields */
+ while ((iFieldcount) && (iTemplen))
+ {
+ if (pTempfield->iOffsetchunk)
+ {
+ if (pTempfield->iFlags & MNG_FIELD_PUTIMGTYPE)
+ {
+ *(pChunkdata+pTempfield->iOffsetchunk) = iColortype;
+ bProcess = MNG_FALSE;
+ }
+ else
+ if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
+ bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
+ else
+ bProcess = MNG_TRUE;
+
+ if (bProcess)
+ {
+ iLastgroup = (mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK);
+ /* numeric field ? */
+ if (pTempfield->iFlags & MNG_FIELD_INT)
+ {
+ if (iTemplen < pTempfield->iLengthmax)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ switch (pTempfield->iLengthmax)
+ {
+ case 1 : { mng_uint8 iNum = *pTempdata;
+ if (((mng_uint16)iNum < pTempfield->iMinvalue) ||
+ ((mng_uint16)iNum > pTempfield->iMaxvalue) )
+ MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
+ *(pChunkdata+pTempfield->iOffsetchunk) = iNum;
+ break; }
+ case 2 : { mng_uint16 iNum = mng_get_uint16 (pTempdata);
+ if ((iNum < pTempfield->iMinvalue) || (iNum > pTempfield->iMaxvalue))
+ MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
+ *((mng_uint16p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
+ break; }
+ case 4 : { mng_uint32 iNum = mng_get_uint32 (pTempdata);
+ if ((iNum < pTempfield->iMinvalue) ||
+ ((pTempfield->iFlags & MNG_FIELD_NOHIGHBIT) && (iNum & 0x80000000)) )
+ MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
+ *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
+ break; }
+ }
+
+ pTempdata += pTempfield->iLengthmax;
+ iTemplen -= pTempfield->iLengthmax;
+
+ } else { /* not numeric so it's a bunch of bytes */
+
+ if (!pTempfield->iOffsetchunklen) /* big fat NONO */
+ MNG_ERROR (pData, MNG_INTERNALERROR);
+ /* with terminating 0 ? */
+ if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
+ {
+ mng_uint8p pWork = pTempdata;
+ while (*pWork) /* find the zero */
+ pWork++;
+ iDatalen = (mng_uint32)(pWork - pTempdata);
+ } else { /* no terminator, so everything that's left ! */
+ iDatalen = iTemplen;
+ }
+
+ if ((pTempfield->iLengthmax) && (iDatalen > pTempfield->iLengthmax))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+#if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
+ !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
+ defined(MNG_INCLUDE_ANG_PROPOSAL)
+ /* needs decompression ? */
+ if (pTempfield->iFlags & MNG_FIELD_DEFLATED)
+ {
+ mng_uint8p pBuf = 0;
+ mng_uint32 iBufsize = 0;
+ mng_uint32 iRealsize;
+ mng_ptr pWork;
+
+ iRetcode = mng_inflate_buffer (pData, pTempdata, iDatalen,
+ &pBuf, &iBufsize, &iRealsize);
+
+#ifdef MNG_CHECK_BAD_ICCP /* Check for bad iCCP chunk */
+ if ((iRetcode) && (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_iCCP))
+ {
+ *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = MNG_NULL;
+ *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
+ }
+ else
+#endif
+ {
+ if (iRetcode)
+ return iRetcode;
+
+#if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
+ if ( (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_mpNG) ||
+ (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_adAT) )
+ {
+ MNG_ALLOC (pData, pWork, iRealsize);
+ }
+ else
+ {
+#endif
+ /* don't forget to generate null terminator */
+ MNG_ALLOC (pData, pWork, iRealsize+1);
+#if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
+ }
+#endif
+ MNG_COPY (pWork, pBuf, iRealsize);
+
+ *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
+ *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iRealsize;
+ }
+
+ if (pBuf) /* free the temporary buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+
+ } else
+#endif
+ { /* no decompression, so just copy */
+
+ mng_ptr pWork;
+ /* don't forget to generate null terminator */
+ MNG_ALLOC (pData, pWork, iDatalen+1);
+ MNG_COPY (pWork, pTempdata, iDatalen);
+
+ *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
+ *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
+ }
+
+ if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
+ iDatalen++; /* skip the terminating zero as well !!! */
+
+ iTemplen -= iDatalen;
+ pTempdata += iDatalen;
+ }
+ /* need to set an indicator ? */
+ if (pTempfield->iOffsetchunkind)
+ *((mng_uint8p)(pChunkdata+pTempfield->iOffsetchunkind)) = MNG_TRUE;
+ }
+ }
+
+ if (pTempfield->pSpecialfunc) /* special function required ? */
+ {
+ iRetcode = pTempfield->pSpecialfunc(pData, *ppChunk, &iTemplen, &pTempdata);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ pTempfield++; /* Neeeeeeexxxtt */
+ iFieldcount--;
+ }
+
+ if (iTemplen) /* extra data ??? */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ while (iFieldcount) /* not enough data ??? */
+ {
+ if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
+ bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
+ ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
+ else
+ bProcess = MNG_TRUE;
+
+ if (bProcess)
+ {
+ if (!(pTempfield->iFlags & MNG_FIELD_OPTIONAL))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ if ((pTempfield->iFlags & MNG_FIELD_GROUPMASK) &&
+ ((mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK) == iLastgroup))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+ pTempfield++;
+ iFieldcount--;
+ }
+ }
+ }
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+READ_CHUNK (mng_read_general)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+ mng_chunk_descp pDescr = ((mng_chunk_headerp)pHeader)->pChunkdescr;
+ mng_field_descp pField;
+ mng_uint16 iFields;
+
+ if (!pDescr) /* this is a bad booboo !!! */
+ MNG_ERROR (pData, MNG_INTERNALERROR);
+
+ pField = pDescr->pFielddesc;
+ iFields = pDescr->iFielddesc;
+ /* check chunk against signature */
+ if ((pDescr->eImgtype == mng_it_mng) && (pData->eSigtype != mng_it_mng))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ if ((pDescr->eImgtype == mng_it_jng) && (pData->eSigtype == mng_it_png))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+ /* empties allowed ? */
+ if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTY)))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->eImagetype != mng_it_mng) || (!(pDescr->iAllowed & MNG_DESCR_GLOBAL)))
+ { /* *a* header required ? */
+ if ((pDescr->iMusthaves & MNG_DESCR_GenHDR) &&
+#ifdef MNG_INCLUDE_JNG
+ (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pDescr->iMusthaves & MNG_DESCR_JngHDR) &&
+ (!pData->bHasDHDR) && (!pData->bHasJHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+#endif
+ }
+ /* specific chunk pre-requisite ? */
+ if (((pDescr->iMusthaves & MNG_DESCR_IHDR) && (!pData->bHasIHDR)) ||
+#ifdef MNG_INCLUDE_JNG
+ ((pDescr->iMusthaves & MNG_DESCR_JHDR) && (!pData->bHasJHDR)) ||
+#endif
+ ((pDescr->iMusthaves & MNG_DESCR_DHDR) && (!pData->bHasDHDR)) ||
+ ((pDescr->iMusthaves & MNG_DESCR_LOOP) && (!pData->bHasLOOP)) ||
+ ((pDescr->iMusthaves & MNG_DESCR_PLTE) && (!pData->bHasPLTE)) ||
+ ((pDescr->iMusthaves & MNG_DESCR_MHDR) && (!pData->bHasMHDR)) ||
+ ((pDescr->iMusthaves & MNG_DESCR_SAVE) && (!pData->bHasSAVE)) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* specific chunk undesired ? */
+ if (((pDescr->iMustNOThaves & MNG_DESCR_NOIHDR) && (pData->bHasIHDR)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOBASI) && (pData->bHasBASI)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NODHDR) && (pData->bHasDHDR)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOIDAT) && (pData->bHasIDAT)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOPLTE) && (pData->bHasPLTE)) ||
+#ifdef MNG_INCLUDE_JNG
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOJHDR) && (pData->bHasJHDR)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAT) && (pData->bHasJDAT)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAA) && (pData->bHasJDAA)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOJSEP) && (pData->bHasJSEP)) ||
+#endif
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOMHDR) && (pData->bHasMHDR)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOLOOP) && (pData->bHasLOOP)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOTERM) && (pData->bHasTERM)) ||
+ ((pDescr->iMustNOThaves & MNG_DESCR_NOSAVE) && (pData->bHasSAVE)) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->eSigtype == mng_it_mng) /* check global and embedded empty chunks */
+ {
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYEMBED)))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ } else {
+ if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYGLOBAL)))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ }
+
+ if (pDescr->pSpecialfunc) /* need special processing ? */
+ {
+ iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
+ pField, iFields, ppChunk, MNG_TRUE);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* empty indicator ? */
+ if ((!iRawlen) && (pDescr->iOffsetempty))
+ *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
+
+ iRetcode = pDescr->pSpecialfunc(pData, *ppChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if ((((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT) ||
+ (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT) ||
+ (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA) )
+ {
+ iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ *ppChunk = MNG_NULL;
+ } else {
+#ifdef MNG_STORE_CHUNKS
+ if (!pData->bStorechunks)
+#endif
+ {
+ iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ *ppChunk = MNG_NULL;
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (iRawlen)
+ {
+#ifdef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iRawlen = iRawlen;
+ pData->pRawdata = pRawdata;
+#endif
+
+ /* display processing */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
+ iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
+#ifdef MNG_INCLUDE_JNG
+ else
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
+ iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
+ else
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
+ iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
+#endif
+#else
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
+ iRetcode = mng_process_display_idat (pData);
+#ifdef MNG_INCLUDE_JNG
+ else
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
+ iRetcode = mng_process_display_jdat (pData);
+ else
+ if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
+ iRetcode = mng_process_display_jdaa (pData);
+#endif
+#endif
+
+ if (iRetcode)
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if ((pData->bStorechunks) && (!(*ppChunk)))
+ {
+ iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
+ pField, iFields, ppChunk, MNG_FALSE);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* empty indicator ? */
+ if ((!iRawlen) && (pDescr->iOffsetempty))
+ *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_ihdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_START);
+#endif
+
+ if (iRawlen != 13) /* length oke ? */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ /* only allowed inside PNG or MNG */
+ if ((pData->eSigtype != mng_it_png) && (pData->eSigtype != mng_it_mng))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+ /* sequence checks */
+ if ((pData->eSigtype == mng_it_png) && (pData->iChunkseq > 1))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ pData->bHasIHDR = MNG_TRUE; /* indicate IHDR is present */
+ /* and store interesting fields */
+ if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_NOCHANGE))
+ {
+ pData->iDatawidth = mng_get_uint32 (pRawdata);
+ pData->iDataheight = mng_get_uint32 (pRawdata+4);
+ }
+
+ pData->iBitdepth = *(pRawdata+8);
+ pData->iColortype = *(pRawdata+9);
+ pData->iCompression = *(pRawdata+10);
+ pData->iFilter = *(pRawdata+11);
+ pData->iInterlace = *(pRawdata+12);
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iBitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iBitdepth < 8)
+ pData->iBitdepth = 8;
+#endif
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth > 8)
+ {
+ pData->iBitdepth = 8;
+ pData->iPNGmult = 2;
+ }
+#endif
+
+ if ((pData->iBitdepth != 8) /* parameter validity checks */
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iBitdepth != 1) &&
+ (pData->iBitdepth != 2) &&
+ (pData->iBitdepth != 4)
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iBitdepth != 16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
+ (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
+ (pData->iBitdepth < 8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iFilter != MNG_FILTER_DIFFERING) &&
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iFilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iFilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
+ (pData->iInterlace != MNG_INTERLACE_ADAM7) )
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* check the colortype for delta-images ! */
+ {
+ mng_imagedatap pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+
+ if (pData->iColortype != pBuf->iColortype)
+ {
+ if ( ( (pData->iColortype != MNG_COLORTYPE_INDEXED) ||
+ (pBuf->iColortype == MNG_COLORTYPE_GRAY ) ) &&
+ ( (pData->iColortype != MNG_COLORTYPE_GRAY ) ||
+ (pBuf->iColortype == MNG_COLORTYPE_INDEXED) ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+ }
+ }
+#endif
+#endif
+
+ if (!pData->bHasheader) /* first chunk ? */
+ {
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_png; /* then this must be a PNG */
+ pData->iWidth = pData->iDatawidth;
+ pData->iHeight = pData->iDataheight;
+ /* predict alpha-depth ! */
+ if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) )
+ pData->iAlphadepth = pData->iBitdepth;
+ else
+ if (pData->iColortype == MNG_COLORTYPE_INDEXED)
+ pData->iAlphadepth = 8; /* worst case scenario */
+ else
+ pData->iAlphadepth = 1; /* Possible tRNS cheap binary transparency */
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+#if !defined(MNG_INCLUDE_MPNG_PROPOSAL) || !defined(MNG_SUPPORT_DISPLAY)
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+#endif
+ }
+
+ if (!pData->bHasDHDR)
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_process_display_ihdr (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the fields */
+ ((mng_ihdrp)*ppChunk)->iWidth = mng_get_uint32 (pRawdata);
+ ((mng_ihdrp)*ppChunk)->iHeight = mng_get_uint32 (pRawdata+4);
+ ((mng_ihdrp)*ppChunk)->iBitdepth = pData->iBitdepth;
+ ((mng_ihdrp)*ppChunk)->iColortype = pData->iColortype;
+ ((mng_ihdrp)*ppChunk)->iCompression = pData->iCompression;
+ ((mng_ihdrp)*ppChunk)->iFilter = pData->iFilter;
+ ((mng_ihdrp)*ppChunk)->iInterlace = pData->iInterlace;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_plte)
+{
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ mng_uint32 iX;
+ mng_uint8p pRawdata2;
+#endif
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_uint32 iRawlen2;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasJHDR))
+#else
+ if (pData->bHasIDAT)
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* multiple PLTE only inside BASI */
+ if ((pData->bHasPLTE) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_MULTIPLEERROR);
+ /* length must be multiple of 3 */
+ if (((iRawlen % 3) != 0) || (iRawlen > 768))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* only allowed for indexed-color or
+ rgb(a)-color! */
+ if ((pData->iColortype != 2) && (pData->iColortype != 3) && (pData->iColortype != 6))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+ /* empty only allowed if global present */
+ if ((iRawlen == 0) && (!pData->bHasglobalPLTE))
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+ else
+ {
+ if (iRawlen == 0) /* cannot be empty as global! */
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ pData->bHasPLTE = MNG_TRUE; /* got it! */
+ else
+ pData->bHasglobalPLTE = MNG_TRUE;
+
+ pData->iPLTEcount = iRawlen / 3;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ { /* store in object 0 !!! */
+ pImage = (mng_imagep)pData->pObjzero;
+ pBuf = pImage->pImgbuf;
+ pBuf->bHasPLTE = MNG_TRUE; /* it's definitely got a PLTE now */
+ pBuf->iPLTEcount = iRawlen / 3; /* this is the exact length */
+ pRawdata2 = pRawdata; /* copy the entries */
+
+ for (iX = 0; iX < iRawlen / 3; iX++)
+ {
+ pBuf->aPLTEentries[iX].iRed = *pRawdata2;
+ pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
+ pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
+
+ pRawdata2 += 3;
+ }
+ }
+ else
+#endif
+ { /* get the current object */
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address the object buffer */
+ pBuf->bHasPLTE = MNG_TRUE; /* and tell it it's got a PLTE now */
+
+ if (!iRawlen) /* if empty, inherit from global */
+ {
+ pBuf->iPLTEcount = pData->iGlobalPLTEcount;
+ MNG_COPY (pBuf->aPLTEentries, pData->aGlobalPLTEentries,
+ sizeof (pBuf->aPLTEentries));
+
+ if (pData->bHasglobalTRNS) /* also copy global tRNS ? */
+ { /* indicate tRNS available */
+ pBuf->bHasTRNS = MNG_TRUE;
+
+ iRawlen2 = pData->iGlobalTRNSrawlen;
+ pRawdata2 = (mng_uint8p)(pData->aGlobalTRNSrawdata);
+ /* global length oke ? */
+ if ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+ /* copy it */
+ pBuf->iTRNScount = iRawlen2;
+ MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
+ }
+ }
+ else
+ { /* store fields for future reference */
+ pBuf->iPLTEcount = iRawlen / 3;
+ pRawdata2 = pRawdata;
+
+ for (iX = 0; iX < pBuf->iPLTEcount; iX++)
+ {
+ pBuf->aPLTEentries[iX].iRed = *pRawdata2;
+ pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
+ pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
+
+ pRawdata2 += 3;
+ }
+ }
+ }
+ }
+ else /* store as global */
+ {
+ pData->iGlobalPLTEcount = iRawlen / 3;
+ pRawdata2 = pRawdata;
+
+ for (iX = 0; iX < pData->iGlobalPLTEcount; iX++)
+ {
+ pData->aGlobalPLTEentries[iX].iRed = *pRawdata2;
+ pData->aGlobalPLTEentries[iX].iGreen = *(pRawdata2+1);
+ pData->aGlobalPLTEentries[iX].iBlue = *(pRawdata2+2);
+
+ pRawdata2 += 3;
+ }
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_plte (pData, pData->iGlobalPLTEcount,
+ pData->aGlobalPLTEentries);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_pltep)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_pltep)*ppChunk)->iEntrycount = iRawlen / 3;
+ pRawdata2 = pRawdata;
+
+ for (iX = 0; iX < ((mng_pltep)*ppChunk)->iEntrycount; iX++)
+ {
+ ((mng_pltep)*ppChunk)->aEntries[iX].iRed = *pRawdata2;
+ ((mng_pltep)*ppChunk)->aEntries[iX].iGreen = *(pRawdata2+1);
+ ((mng_pltep)*ppChunk)->aEntries[iX].iBlue = *(pRawdata2+2);
+
+ pRawdata2 += 3;
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_idat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IDAT, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_JNG /* sequence checks */
+ if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasJHDR) &&
+ (pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->bHasJSEP)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+#endif
+ /* not allowed for deltatype NO_CHANGE */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && ((pData->iDeltatype == MNG_DELTATYPE_NOCHANGE)))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+#endif
+ /* can only be empty in BASI-block! */
+ if ((iRawlen == 0) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ /* indexed-color requires PLTE */
+ if ((pData->bHasIHDR) && (pData->iColortype == 3) && (!pData->bHasPLTE))
+ MNG_ERROR (pData, MNG_PLTEMISSING);
+
+ pData->bHasIDAT = MNG_TRUE; /* got some IDAT now, don't we */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (iRawlen)
+ { /* display processing */
+ mng_retcode iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_idatp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_idatp)*ppChunk)->iDatasize = iRawlen;
+
+ if (iRawlen != 0) /* is there any data ? */
+ {
+ MNG_ALLOC (pData, ((mng_idatp)*ppChunk)->pData, iRawlen);
+ MNG_COPY (((mng_idatp)*ppChunk)->pData, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_iend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IEND, MNG_LC_START);
+#endif
+
+ if (iRawlen > 0) /* must not contain data! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_INCLUDE_JNG /* sequence checks */
+ if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* IHDR-block requires IDAT */
+ if ((pData->bHasIHDR) && (!pData->bHasIDAT))
+ MNG_ERROR (pData, MNG_IDATMISSING);
+
+ pData->iImagelevel--; /* one level up */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_image (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* display processing */
+ iRetcode = mng_process_display_iend (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (!pData->bTimerset) /* reset only if not broken !!! */
+ {
+#endif
+ /* IEND signals the end for most ... */
+ pData->bHasIHDR = MNG_FALSE;
+ pData->bHasBASI = MNG_FALSE;
+ pData->bHasDHDR = MNG_FALSE;
+#ifdef MNG_INCLUDE_JNG
+ pData->bHasJHDR = MNG_FALSE;
+ pData->bHasJSEP = MNG_FALSE;
+ pData->bHasJDAA = MNG_FALSE;
+ pData->bHasJDAT = MNG_FALSE;
+#endif
+ pData->bHasPLTE = MNG_FALSE;
+ pData->bHasTRNS = MNG_FALSE;
+ pData->bHasGAMA = MNG_FALSE;
+ pData->bHasCHRM = MNG_FALSE;
+ pData->bHasSRGB = MNG_FALSE;
+ pData->bHasICCP = MNG_FALSE;
+ pData->bHasBKGD = MNG_FALSE;
+ pData->bHasIDAT = MNG_FALSE;
+#ifdef MNG_SUPPORT_DISPLAY
+ }
+#endif
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_trns)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TRNS, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasJHDR))
+#else
+ if (pData->bHasIDAT)
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* multiple tRNS only inside BASI */
+ if ((pData->bHasTRNS) && (!pData->bHasBASI))
+ MNG_ERROR (pData, MNG_MULTIPLEERROR);
+
+ if (iRawlen > 256) /* it just can't be bigger than that! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* not allowed with full alpha-channel */
+ if ((pData->iColortype == 4) || (pData->iColortype == 6))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ if (iRawlen != 0) /* filled ? */
+ { /* length checks */
+ if ((pData->iColortype == 0) && (iRawlen != 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 2) && (iRawlen != 6))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (pData->iColortype == 3)
+ {
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf;
+
+ if (!pImage) /* no object then check obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+
+ if (iRawlen > pBuf->iPLTEcount)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+#endif
+ }
+ else /* if empty there must be global stuff! */
+ {
+ if (!pData->bHasglobalTRNS)
+ MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
+ }
+ }
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ pData->bHasTRNS = MNG_TRUE; /* indicate tRNS available */
+ else
+ pData->bHasglobalTRNS = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+ mng_uint8p pRawdata2;
+ mng_uint32 iRawlen2;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ { /* store in object 0 !!! */
+ pImage = (mng_imagep)pData->pObjzero;
+ pBuf = pImage->pImgbuf; /* address object buffer */
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0: { /* gray */
+#if defined(MNG_NO_1_2_4BIT_SUPPORT)
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1,
+ 0,0,0,0,0,0,0,1};
+#endif
+ pBuf->iTRNSgray = mng_get_uint16 (pRawdata);
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = 0;
+#if defined(MNG_NO_1_2_4BIT_SUPPORT)
+ pBuf->iTRNSgray *= multiplier[pData->iPNGdepth];
+#endif
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ pBuf->iTRNSgray >>= 8;
+#endif
+ break;
+ }
+ case 2: { /* rgb */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = mng_get_uint16 (pRawdata);
+ pBuf->iTRNSgreen = mng_get_uint16 (pRawdata+2);
+ pBuf->iTRNSblue = mng_get_uint16 (pRawdata+4);
+ pBuf->iTRNScount = 0;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ {
+ pBuf->iTRNSred >>= 8;
+ pBuf->iTRNSgreen >>= 8;
+ pBuf->iTRNSblue >>= 8;
+ }
+#endif
+ break;
+ }
+ case 3: { /* indexed */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = iRawlen;
+ MNG_COPY (pBuf->aTRNSentries, pRawdata, iRawlen);
+ break;
+ }
+ }
+
+ pBuf->bHasTRNS = MNG_TRUE; /* tell it it's got a tRNS now */
+ }
+ else
+#endif
+ { /* address current object */
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasTRNS = MNG_TRUE; /* and tell it it's got a tRNS now */
+
+ if (iRawlen == 0) /* if empty, inherit from global */
+ {
+ iRawlen2 = pData->iGlobalTRNSrawlen;
+ pRawdata2 = (mng_ptr)(pData->aGlobalTRNSrawdata);
+ /* global length oke ? */
+ if ((pData->iColortype == 0) && (iRawlen2 != 2))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+
+ if ((pData->iColortype == 2) && (iRawlen2 != 6))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+
+ if ((pData->iColortype == 3) && ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount)))
+ MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
+ }
+ else
+ {
+ iRawlen2 = iRawlen;
+ pRawdata2 = pRawdata;
+ }
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0: { /* gray */
+ pBuf->iTRNSgray = mng_get_uint16 (pRawdata2);
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = 0;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ pBuf->iTRNSgray >>= 8;
+#endif
+ break;
+ }
+ case 2: { /* rgb */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = mng_get_uint16 (pRawdata2);
+ pBuf->iTRNSgreen = mng_get_uint16 (pRawdata2+2);
+ pBuf->iTRNSblue = mng_get_uint16 (pRawdata2+4);
+ pBuf->iTRNScount = 0;
+#if defined(MNG_NO_16BIT_SUPPORT)
+ if (pData->iPNGmult == 2)
+ {
+ pBuf->iTRNSred >>= 8;
+ pBuf->iTRNSgreen >>= 8;
+ pBuf->iTRNSblue >>= 8;
+ }
+#endif
+ break;
+ }
+ case 3: { /* indexed */
+ pBuf->iTRNSgray = 0;
+ pBuf->iTRNSred = 0;
+ pBuf->iTRNSgreen = 0;
+ pBuf->iTRNSblue = 0;
+ pBuf->iTRNScount = iRawlen2;
+ MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
+ break;
+ }
+ }
+ }
+ }
+ else /* store as global */
+ {
+ pData->iGlobalTRNSrawlen = iRawlen;
+ MNG_COPY (pData->aGlobalTRNSrawdata, pRawdata, iRawlen);
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_trns (pData, pData->iGlobalTRNSrawlen,
+ pData->aGlobalTRNSrawdata);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ { /* not global! */
+ ((mng_trnsp)*ppChunk)->bGlobal = MNG_FALSE;
+ ((mng_trnsp)*ppChunk)->iType = pData->iColortype;
+
+ if (iRawlen == 0) /* if empty, indicate so */
+ ((mng_trnsp)*ppChunk)->bEmpty = MNG_TRUE;
+ else
+ {
+ ((mng_trnsp)*ppChunk)->bEmpty = MNG_FALSE;
+
+ switch (pData->iColortype) /* store fields */
+ {
+ case 0: { /* gray */
+ ((mng_trnsp)*ppChunk)->iGray = mng_get_uint16 (pRawdata);
+ break;
+ }
+ case 2: { /* rgb */
+ ((mng_trnsp)*ppChunk)->iRed = mng_get_uint16 (pRawdata);
+ ((mng_trnsp)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+2);
+ ((mng_trnsp)*ppChunk)->iBlue = mng_get_uint16 (pRawdata+4);
+ break;
+ }
+ case 3: { /* indexed */
+ ((mng_trnsp)*ppChunk)->iCount = iRawlen;
+ MNG_COPY (((mng_trnsp)*ppChunk)->aEntries, pRawdata, iRawlen);
+ break;
+ }
+ }
+ }
+ }
+ else /* it's global! */
+ {
+ ((mng_trnsp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_trnsp)*ppChunk)->bGlobal = MNG_TRUE;
+ ((mng_trnsp)*ppChunk)->iType = 0;
+ ((mng_trnsp)*ppChunk)->iRawlen = iRawlen;
+
+ MNG_COPY (((mng_trnsp)*ppChunk)->aRawdata, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_gama)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_GAMA, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if ((pData->bHasIDAT) || (pData->bHasPLTE))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ { /* length must be exactly 4 */
+ if (iRawlen != 4)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ { /* length must be empty or exactly 4 */
+ if ((iRawlen != 0) && (iRawlen != 4))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasGAMA = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalGAMA = (mng_bool)(iRawlen != 0);
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ { /* store in object 0 ! */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* store for color-processing routines */
+ pImage->pImgbuf->iGamma = mng_get_uint32 (pRawdata);
+ pImage->pImgbuf->bHasGAMA = MNG_TRUE;
+ }
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* store for color-processing routines */
+ pImage->pImgbuf->iGamma = mng_get_uint32 (pRawdata);
+ pImage->pImgbuf->bHasGAMA = MNG_TRUE;
+ }
+ }
+ else
+ { /* store as global */
+ if (iRawlen != 0)
+ pData->iGlobalGamma = mng_get_uint32 (pRawdata);
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_gama (pData, (mng_bool)(iRawlen == 0),
+ pData->iGlobalGamma);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_gamap)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ ((mng_gamap)*ppChunk)->iGamma = mng_get_uint32 (pRawdata);
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_cHRM
+READ_CHUNK (mng_read_chrm)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHRM, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if ((pData->bHasIDAT) || (pData->bHasPLTE))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ { /* length must be exactly 32 */
+ if (iRawlen != 32)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ { /* length must be empty or exactly 32 */
+ if ((iRawlen != 0) && (iRawlen != 32))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasCHRM = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalCHRM = (mng_bool)(iRawlen != 0);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint32 iWhitepointx, iWhitepointy;
+ mng_uint32 iPrimaryredx, iPrimaryredy;
+ mng_uint32 iPrimarygreenx, iPrimarygreeny;
+ mng_uint32 iPrimarybluex, iPrimarybluey;
+
+ iWhitepointx = mng_get_uint32 (pRawdata);
+ iWhitepointy = mng_get_uint32 (pRawdata+4);
+ iPrimaryredx = mng_get_uint32 (pRawdata+8);
+ iPrimaryredy = mng_get_uint32 (pRawdata+12);
+ iPrimarygreenx = mng_get_uint32 (pRawdata+16);
+ iPrimarygreeny = mng_get_uint32 (pRawdata+20);
+ iPrimarybluex = mng_get_uint32 (pRawdata+24);
+ iPrimarybluey = mng_get_uint32 (pRawdata+28);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ { /* store it in object 0 ! */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasCHRM = MNG_TRUE; /* and tell it it's got a CHRM now */
+ /* store for color-processing routines */
+ pBuf->iWhitepointx = iWhitepointx;
+ pBuf->iWhitepointy = iWhitepointy;
+ pBuf->iPrimaryredx = iPrimaryredx;
+ pBuf->iPrimaryredy = iPrimaryredy;
+ pBuf->iPrimarygreenx = iPrimarygreenx;
+ pBuf->iPrimarygreeny = iPrimarygreeny;
+ pBuf->iPrimarybluex = iPrimarybluex;
+ pBuf->iPrimarybluey = iPrimarybluey;
+ }
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+ pBuf->bHasCHRM = MNG_TRUE; /* and tell it it's got a CHRM now */
+ /* store for color-processing routines */
+ pBuf->iWhitepointx = iWhitepointx;
+ pBuf->iWhitepointy = iWhitepointy;
+ pBuf->iPrimaryredx = iPrimaryredx;
+ pBuf->iPrimaryredy = iPrimaryredy;
+ pBuf->iPrimarygreenx = iPrimarygreenx;
+ pBuf->iPrimarygreeny = iPrimarygreeny;
+ pBuf->iPrimarybluex = iPrimarybluex;
+ pBuf->iPrimarybluey = iPrimarybluey;
+ }
+ }
+ else
+ { /* store as global */
+ if (iRawlen != 0)
+ {
+ pData->iGlobalWhitepointx = iWhitepointx;
+ pData->iGlobalWhitepointy = iWhitepointy;
+ pData->iGlobalPrimaryredx = iPrimaryredx;
+ pData->iGlobalPrimaryredy = iPrimaryredy;
+ pData->iGlobalPrimarygreenx = iPrimarygreenx;
+ pData->iGlobalPrimarygreeny = iPrimarygreeny;
+ pData->iGlobalPrimarybluex = iPrimarybluex;
+ pData->iGlobalPrimarybluey = iPrimarybluey;
+ }
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_chrm (pData, (mng_bool)(iRawlen == 0),
+ iWhitepointx, iWhitepointy,
+ iPrimaryredx, iPrimaryredy,
+ iPrimarygreenx, iPrimarygreeny,
+ iPrimarybluex, iPrimarybluey);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_chrmp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ ((mng_chrmp)*ppChunk)->iWhitepointx = mng_get_uint32 (pRawdata);
+ ((mng_chrmp)*ppChunk)->iWhitepointy = mng_get_uint32 (pRawdata+4);
+ ((mng_chrmp)*ppChunk)->iRedx = mng_get_uint32 (pRawdata+8);
+ ((mng_chrmp)*ppChunk)->iRedy = mng_get_uint32 (pRawdata+12);
+ ((mng_chrmp)*ppChunk)->iGreenx = mng_get_uint32 (pRawdata+16);
+ ((mng_chrmp)*ppChunk)->iGreeny = mng_get_uint32 (pRawdata+20);
+ ((mng_chrmp)*ppChunk)->iBluex = mng_get_uint32 (pRawdata+24);
+ ((mng_chrmp)*ppChunk)->iBluey = mng_get_uint32 (pRawdata+28);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_srgb)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SRGB, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if ((pData->bHasIDAT) || (pData->bHasPLTE))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ { /* length must be exactly 1 */
+ if (iRawlen != 1)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ { /* length must be empty or exactly 1 */
+ if ((iRawlen != 0) && (iRawlen != 1))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasSRGB = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalSRGB = (mng_bool)(iRawlen != 0);
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ { /* store in object 0 ! */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* store for color-processing routines */
+ pImage->pImgbuf->iRenderingintent = *pRawdata;
+ pImage->pImgbuf->bHasSRGB = MNG_TRUE;
+ }
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* store for color-processing routines */
+ pImage->pImgbuf->iRenderingintent = *pRawdata;
+ pImage->pImgbuf->bHasSRGB = MNG_TRUE;
+ }
+ }
+ else
+ { /* store as global */
+ if (iRawlen != 0)
+ pData->iGlobalRendintent = *pRawdata;
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_srgb (pData, (mng_bool)(iRawlen == 0),
+ pData->iGlobalRendintent);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_srgbp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ ((mng_srgbp)*ppChunk)->iRenderingintent = *pRawdata;
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_iCCP
+READ_CHUNK (mng_read_iccp)
+{
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint32 iCompressedsize;
+ mng_uint32 iProfilesize;
+ mng_uint32 iBufsize = 0;
+ mng_uint8p pBuf = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ICCP, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasPLTE) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if ((pData->bHasIDAT) || (pData->bHasPLTE))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ { /* length must be at least 2 */
+ if (iRawlen < 2)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ { /* length must be empty or at least 2 */
+ if ((iRawlen != 0) && (iRawlen < 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+ pTemp = find_null (pRawdata); /* find null-separator */
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+ /* determine size of compressed profile */
+ iCompressedsize = (mng_uint32)(iRawlen - (pTemp - pRawdata) - 2);
+ /* decompress the profile */
+ iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
+ &pBuf, &iBufsize, &iProfilesize);
+
+#ifdef MNG_CHECK_BAD_ICCP /* Check for bad iCCP chunk */
+ if ((iRetcode) && (!strncmp ((char *)pRawdata, "Photoshop ICC profile", 21)))
+ {
+ if (iRawlen == 2615) /* is it the sRGB profile ? */
+ {
+ mng_chunk_header chunk_srgb =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)};
+#else
+ {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0};
+#endif
+ /* pretend it's an sRGB chunk then ! */
+ iRetcode = mng_read_srgb (pData, &chunk_srgb, 1, (mng_ptr)"0", ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+ }
+ else
+ {
+#endif /* MNG_CHECK_BAD_ICCP */
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasICCP = MNG_TRUE; /* indicate we've got it */
+ else
+ pData->bHasglobalICCP = (mng_bool)(iRawlen != 0);
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ {
+ mng_imagep pImage;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* update delta image ? */
+ { /* store in object 0 ! */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ if (pImage->pImgbuf->pProfile) /* profile existed ? */
+ MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
+ /* allocate a buffer & copy it */
+ MNG_ALLOC (pData, pImage->pImgbuf->pProfile, iProfilesize);
+ MNG_COPY (pImage->pImgbuf->pProfile, pBuf, iProfilesize);
+ /* store its length as well */
+ pImage->pImgbuf->iProfilesize = iProfilesize;
+ pImage->pImgbuf->bHasICCP = MNG_TRUE;
+ }
+ else
+#endif
+ {
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* no object then dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ if (pImage->pImgbuf->pProfile) /* profile existed ? */
+ MNG_FREEX (pData, pImage->pImgbuf->pProfile, pImage->pImgbuf->iProfilesize);
+ /* allocate a buffer & copy it */
+ MNG_ALLOC (pData, pImage->pImgbuf->pProfile, iProfilesize);
+ MNG_COPY (pImage->pImgbuf->pProfile, pBuf, iProfilesize);
+ /* store its length as well */
+ pImage->pImgbuf->iProfilesize = iProfilesize;
+ pImage->pImgbuf->bHasICCP = MNG_TRUE;
+ }
+ }
+ else
+ { /* store as global */
+ if (iRawlen == 0) /* empty chunk ? */
+ {
+ if (pData->pGlobalProfile) /* did we have a global profile ? */
+ MNG_FREEX (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ pData->iGlobalProfilesize = 0; /* reset to null */
+ pData->pGlobalProfile = MNG_NULL;
+ }
+ else
+ { /* allocate a global buffer & copy it */
+ MNG_ALLOC (pData, pData->pGlobalProfile, iProfilesize);
+ MNG_COPY (pData->pGlobalProfile, pBuf, iProfilesize);
+ /* store its length as well */
+ pData->iGlobalProfilesize = iProfilesize;
+ }
+
+ /* create an animation object */
+ iRetcode = mng_create_ani_iccp (pData, (mng_bool)(iRawlen == 0),
+ pData->iGlobalProfilesize,
+ pData->pGlobalProfile);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ /* store the fields */
+ ((mng_iccpp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen) /* not empty ? */
+ {
+ if (!pBuf) /* hasn't been unpuzzled it yet ? */
+ { /* find null-separator */
+ pTemp = find_null (pRawdata);
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+ /* determine size of compressed profile */
+ iCompressedsize = iRawlen - (pTemp - pRawdata) - 2;
+ /* decompress the profile */
+ iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
+ &pBuf, &iBufsize, &iProfilesize);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+
+ ((mng_iccpp)*ppChunk)->iNamesize = (mng_uint32)(pTemp - pRawdata);
+
+ if (((mng_iccpp)*ppChunk)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_iccpp)*ppChunk)->zName,
+ ((mng_iccpp)*ppChunk)->iNamesize + 1);
+ MNG_COPY (((mng_iccpp)*ppChunk)->zName, pRawdata,
+ ((mng_iccpp)*ppChunk)->iNamesize);
+ }
+
+ ((mng_iccpp)*ppChunk)->iCompression = *(pTemp+1);
+ ((mng_iccpp)*ppChunk)->iProfilesize = iProfilesize;
+
+ MNG_ALLOC (pData, ((mng_iccpp)*ppChunk)->pProfile, iProfilesize);
+ MNG_COPY (((mng_iccpp)*ppChunk)->pProfile, pBuf, iProfilesize);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+ if (pBuf) /* free the temporary buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+
+#ifdef MNG_CHECK_BAD_ICCP
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_tEXt
+READ_CHUNK (mng_read_text)
+{
+ mng_uint32 iKeywordlen, iTextlen;
+ mng_pchar zKeyword, zText;
+ mng_uint8p pTemp;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TEXT, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 2) /* length must be at least 2 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pTemp = find_null (pRawdata); /* find the null separator */
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+
+ if (pTemp == pRawdata) /* there must be at least 1 char for keyword */
+ MNG_ERROR (pData, MNG_KEYWORDNULL);
+
+ iKeywordlen = (mng_uint32)(pTemp - pRawdata);
+ iTextlen = iRawlen - iKeywordlen - 1;
+
+ if (pData->fProcesstext) /* inform the application ? */
+ {
+ mng_bool bOke;
+
+ MNG_ALLOC (pData, zKeyword, iKeywordlen + 1);
+ MNG_COPY (zKeyword, pRawdata, iKeywordlen);
+
+ MNG_ALLOCX (pData, zText, iTextlen + 1);
+
+ if (!zText) /* on error bail out */
+ {
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ if (iTextlen)
+ MNG_COPY (zText, pTemp+1, iTextlen);
+
+ bOke = pData->fProcesstext ((mng_handle)pData, MNG_TYPE_TEXT, zKeyword, zText, 0, 0);
+
+ MNG_FREEX (pData, zText, iTextlen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ }
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_textp)*ppChunk)->iKeywordsize = iKeywordlen;
+ ((mng_textp)*ppChunk)->iTextsize = iTextlen;
+
+ if (iKeywordlen)
+ {
+ MNG_ALLOC (pData, ((mng_textp)*ppChunk)->zKeyword, iKeywordlen+1);
+ MNG_COPY (((mng_textp)*ppChunk)->zKeyword, pRawdata, iKeywordlen);
+ }
+
+ if (iTextlen)
+ {
+ MNG_ALLOC (pData, ((mng_textp)*ppChunk)->zText, iTextlen+1);
+ MNG_COPY (((mng_textp)*ppChunk)->zText, pTemp+1, iTextlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_zTXt
+READ_CHUNK (mng_read_ztxt)
+{
+ mng_retcode iRetcode;
+ mng_uint32 iKeywordlen, iTextlen;
+ mng_pchar zKeyword;
+ mng_uint8p pTemp;
+ mng_uint32 iCompressedsize;
+ mng_uint32 iBufsize;
+ mng_uint8p pBuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ZTXT, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 3) /* length must be at least 3 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pTemp = find_null (pRawdata); /* find the null separator */
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+
+ if (pTemp == pRawdata) /* there must be at least 1 char for keyword */
+ MNG_ERROR (pData, MNG_KEYWORDNULL);
+
+ if (*(pTemp+1) != 0) /* only deflate compression-method allowed */
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ iKeywordlen = (mng_uint32)(pTemp - pRawdata);
+ iCompressedsize = (mng_uint32)(iRawlen - iKeywordlen - 2);
+
+ zKeyword = 0; /* there's no keyword buffer yet */
+ pBuf = 0; /* or a temporary buffer ! */
+
+ if (pData->fProcesstext) /* inform the application ? */
+ { /* decompress the text */
+ iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
+ &pBuf, &iBufsize, &iTextlen);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ MNG_ALLOCX (pData, zKeyword, iKeywordlen+1);
+
+ if (!zKeyword) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (zKeyword, pRawdata, iKeywordlen);
+
+ if (!pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ZTXT, zKeyword, (mng_pchar)pBuf, 0, 0))
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+ }
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+ return iRetcode;
+ }
+ /* store the fields */
+ ((mng_ztxtp)*ppChunk)->iKeywordsize = iKeywordlen;
+ ((mng_ztxtp)*ppChunk)->iCompression = *(pTemp+1);
+
+ if ((!pBuf) && (iCompressedsize)) /* did we not get a text-buffer yet ? */
+ { /* decompress the text */
+ iRetcode = mng_inflate_buffer (pData, pTemp+2, iCompressedsize,
+ &pBuf, &iBufsize, &iTextlen);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+ return iRetcode;
+ }
+ }
+
+ MNG_ALLOCX (pData, ((mng_ztxtp)*ppChunk)->zKeyword, iKeywordlen + 1);
+ /* on error bail out */
+ if (!((mng_ztxtp)*ppChunk)->zKeyword)
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (((mng_ztxtp)*ppChunk)->zKeyword, pRawdata, iKeywordlen);
+
+ ((mng_ztxtp)*ppChunk)->iTextsize = iTextlen;
+
+ if (iCompressedsize)
+ {
+ MNG_ALLOCX (pData, ((mng_ztxtp)*ppChunk)->zText, iTextlen + 1);
+ /* on error bail out */
+ if (!((mng_ztxtp)*ppChunk)->zText)
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (((mng_ztxtp)*ppChunk)->zText, pBuf, iTextlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+ MNG_FREEX (pData, pBuf, iBufsize); /* free the temporary buffers */
+ MNG_FREEX (pData, zKeyword, iKeywordlen+1);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ZTXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_iTXt
+READ_CHUNK (mng_read_itxt)
+{
+ mng_retcode iRetcode;
+ mng_uint32 iKeywordlen, iTextlen, iLanguagelen, iTranslationlen;
+ mng_pchar zKeyword, zLanguage, zTranslation;
+ mng_uint8p pNull1, pNull2, pNull3;
+ mng_uint32 iCompressedsize;
+ mng_uint8 iCompressionflag;
+ mng_uint32 iBufsize;
+ mng_uint8p pBuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ITXT, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 6) /* length must be at least 6 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pNull1 = find_null (pRawdata); /* find the null separators */
+ pNull2 = find_null (pNull1+3);
+ pNull3 = find_null (pNull2+1);
+ /* not found inside input-data ? */
+ if (((pNull1 - pRawdata) > (mng_int32)iRawlen) ||
+ ((pNull2 - pRawdata) > (mng_int32)iRawlen) ||
+ ((pNull3 - pRawdata) > (mng_int32)iRawlen) )
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+
+ if (pNull1 == pRawdata) /* there must be at least 1 char for keyword */
+ MNG_ERROR (pData, MNG_KEYWORDNULL);
+ /* compression or not ? */
+ if ((*(pNull1+1) != 0) && (*(pNull1+1) != 1))
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ if (*(pNull1+2) != 0) /* only deflate compression-method allowed */
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ iKeywordlen = (mng_uint32)(pNull1 - pRawdata);
+ iLanguagelen = (mng_uint32)(pNull2 - pNull1 - 3);
+ iTranslationlen = (mng_uint32)(pNull3 - pNull2 - 1);
+ iCompressedsize = (mng_uint32)(iRawlen - iKeywordlen - iLanguagelen - iTranslationlen - 5);
+ iCompressionflag = *(pNull1+1);
+
+ zKeyword = 0; /* no buffers acquired yet */
+ zLanguage = 0;
+ zTranslation = 0;
+ pBuf = 0;
+ iTextlen = 0;
+
+ if (pData->fProcesstext) /* inform the application ? */
+ {
+ if (iCompressionflag) /* decompress the text ? */
+ {
+ iRetcode = mng_inflate_buffer (pData, pNull3+1, iCompressedsize,
+ &pBuf, &iBufsize, &iTextlen);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffer */
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+ else
+ {
+ iTextlen = iCompressedsize;
+ iBufsize = iTextlen+1; /* plus 1 for terminator byte!!! */
+
+ MNG_ALLOC (pData, pBuf, iBufsize);
+ MNG_COPY (pBuf, pNull3+1, iTextlen);
+ }
+
+ MNG_ALLOCX (pData, zKeyword, iKeywordlen + 1);
+ MNG_ALLOCX (pData, zLanguage, iLanguagelen + 1);
+ MNG_ALLOCX (pData, zTranslation, iTranslationlen + 1);
+ /* on error bail out */
+ if ((!zKeyword) || (!zLanguage) || (!zTranslation))
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (zKeyword, pRawdata, iKeywordlen);
+ MNG_COPY (zLanguage, pNull1+3, iLanguagelen);
+ MNG_COPY (zTranslation, pNull2+1, iTranslationlen);
+
+ if (!pData->fProcesstext ((mng_handle)pData, MNG_TYPE_ITXT, zKeyword, (mng_pchar)pBuf,
+ zLanguage, zTranslation))
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+ }
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ /* store the fields */
+ ((mng_itxtp)*ppChunk)->iKeywordsize = iKeywordlen;
+ ((mng_itxtp)*ppChunk)->iLanguagesize = iLanguagelen;
+ ((mng_itxtp)*ppChunk)->iTranslationsize = iTranslationlen;
+ ((mng_itxtp)*ppChunk)->iCompressionflag = *(pNull1+1);
+ ((mng_itxtp)*ppChunk)->iCompressionmethod = *(pNull1+2);
+
+ if ((!pBuf) && (iCompressedsize)) /* did we not get a text-buffer yet ? */
+ {
+ if (iCompressionflag) /* decompress the text ? */
+ {
+ iRetcode = mng_inflate_buffer (pData, pNull3+1, iCompressedsize,
+ &pBuf, &iBufsize, &iTextlen);
+
+ if (iRetcode) /* on error bail out */
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+ else
+ {
+ iTextlen = iCompressedsize;
+ iBufsize = iTextlen+1; /* plus 1 for terminator byte!!! */
+
+ MNG_ALLOC (pData, pBuf, iBufsize);
+ MNG_COPY (pBuf, pNull3+1, iTextlen);
+ }
+ }
+
+ MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zKeyword, iKeywordlen + 1);
+ MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zLanguage, iLanguagelen + 1);
+ MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zTranslation, iTranslationlen + 1);
+ /* on error bail out */
+ if ((!((mng_itxtp)*ppChunk)->zKeyword ) ||
+ (!((mng_itxtp)*ppChunk)->zLanguage ) ||
+ (!((mng_itxtp)*ppChunk)->zTranslation) )
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (((mng_itxtp)*ppChunk)->zKeyword, pRawdata, iKeywordlen);
+ MNG_COPY (((mng_itxtp)*ppChunk)->zLanguage, pNull1+3, iLanguagelen);
+ MNG_COPY (((mng_itxtp)*ppChunk)->zTranslation, pNull2+1, iTranslationlen);
+
+ ((mng_itxtp)*ppChunk)->iTextsize = iTextlen;
+
+ if (iTextlen)
+ {
+ MNG_ALLOCX (pData, ((mng_itxtp)*ppChunk)->zText, iTextlen + 1);
+
+ if (!((mng_itxtp)*ppChunk)->zText)
+ { /* don't forget to drop the temp buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (((mng_itxtp)*ppChunk)->zText, pBuf, iTextlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+ /* free the temporary buffers */
+ MNG_FREEX (pData, zTranslation, iTranslationlen + 1);
+ MNG_FREEX (pData, zLanguage, iLanguagelen + 1);
+ MNG_FREEX (pData, zKeyword, iKeywordlen + 1);
+ MNG_FREEX (pData, pBuf, iBufsize);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_bKGD
+READ_CHUNK (mng_read_bkgd)
+{
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BKGD, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if (pData->bHasIDAT)
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen > 6) /* it just can't be bigger than that! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_INCLUDE_JNG /* length checks */
+ if (pData->bHasJHDR)
+ {
+ if (((pData->iJHDRcolortype == 8) || (pData->iJHDRcolortype == 12)) && (iRawlen != 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if (((pData->iJHDRcolortype == 10) || (pData->iJHDRcolortype == 14)) && (iRawlen != 6))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+#endif /* MNG_INCLUDE_JNG */
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ if (((pData->iColortype == 0) || (pData->iColortype == 4)) && (iRawlen != 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if (((pData->iColortype == 2) || (pData->iColortype == 6)) && (iRawlen != 6))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 3) && (iRawlen != 1))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ {
+ if (iRawlen != 6) /* global is always 16-bit RGB ! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ pData->bHasBKGD = MNG_TRUE; /* indicate bKGD available */
+ else
+ pData->bHasglobalBKGD = (mng_bool)(iRawlen != 0);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (!pImage) /* if no object dump it in obj 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+
+ pBuf = pImage->pImgbuf; /* address object buffer */
+
+#ifdef MNG_INCLUDE_JNG
+ if (pData->bHasJHDR)
+ {
+ pBuf->bHasBKGD = MNG_TRUE; /* tell the object it's got bKGD now */
+
+ switch (pData->iJHDRcolortype) /* store fields for future reference */
+ {
+ case 8 : ; /* gray */
+ case 12 : { /* graya */
+ pBuf->iBKGDgray = mng_get_uint16 (pRawdata);
+ break;
+ }
+ case 10 : ; /* rgb */
+ case 14 : { /* rgba */
+ pBuf->iBKGDred = mng_get_uint16 (pRawdata);
+ pBuf->iBKGDgreen = mng_get_uint16 (pRawdata+2);
+ pBuf->iBKGDblue = mng_get_uint16 (pRawdata+4);
+ break;
+ }
+ }
+ }
+ else
+#endif /* MNG_INCLUDE_JNG */
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ pBuf->bHasBKGD = MNG_TRUE; /* tell the object it's got bKGD now */
+
+ switch (pData->iColortype) /* store fields for future reference */
+ {
+ case 0 : ; /* gray */
+ case 4 : { /* graya */
+ pBuf->iBKGDgray = mng_get_uint16 (pRawdata);
+ break;
+ }
+ case 2 : ; /* rgb */
+ case 6 : { /* rgba */
+ pBuf->iBKGDred = mng_get_uint16 (pRawdata);
+ pBuf->iBKGDgreen = mng_get_uint16 (pRawdata+2);
+ pBuf->iBKGDblue = mng_get_uint16 (pRawdata+4);
+ break;
+ }
+ case 3 : { /* indexed */
+ pBuf->iBKGDindex = *pRawdata;
+ break;
+ }
+ }
+ }
+ else /* store as global */
+ {
+ if (iRawlen)
+ {
+ pData->iGlobalBKGDred = mng_get_uint16 (pRawdata);
+ pData->iGlobalBKGDgreen = mng_get_uint16 (pRawdata+2);
+ pData->iGlobalBKGDblue = mng_get_uint16 (pRawdata+4);
+ }
+
+ { /* create an animation object */
+ mng_retcode iRetcode = mng_create_ani_bkgd (pData, pData->iGlobalBKGDred,
+ pData->iGlobalBKGDgreen,
+ pData->iGlobalBKGDblue);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_bkgdp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_bkgdp)*ppChunk)->iType = pData->iColortype;
+
+ if (iRawlen)
+ {
+ switch (iRawlen) /* guess from length */
+ {
+ case 1 : { /* indexed */
+ ((mng_bkgdp)*ppChunk)->iType = 3;
+ ((mng_bkgdp)*ppChunk)->iIndex = *pRawdata;
+ break;
+ }
+ case 2 : { /* gray */
+ ((mng_bkgdp)*ppChunk)->iType = 0;
+ ((mng_bkgdp)*ppChunk)->iGray = mng_get_uint16 (pRawdata);
+ break;
+ }
+ case 6 : { /* rgb */
+ ((mng_bkgdp)*ppChunk)->iType = 2;
+ ((mng_bkgdp)*ppChunk)->iRed = mng_get_uint16 (pRawdata);
+ ((mng_bkgdp)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+2);
+ ((mng_bkgdp)*ppChunk)->iBlue = mng_get_uint16 (pRawdata+4);
+ break;
+ }
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_pHYs
+READ_CHUNK (mng_read_phys)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PHYS, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if (pData->bHasIDAT)
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* it's 9 bytes or empty; no more, no less! */
+ if ((iRawlen != 9) && (iRawlen != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_physp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ ((mng_physp)*ppChunk)->iSizex = mng_get_uint32 (pRawdata);
+ ((mng_physp)*ppChunk)->iSizey = mng_get_uint32 (pRawdata+4);
+ ((mng_physp)*ppChunk)->iUnit = *(pRawdata+8);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_sBIT
+READ_CHUNK (mng_read_sbit)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SBIT, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasPLTE) || (pData->bHasIDAT) || (pData->bHasJDAT) || (pData->bHasJDAA))
+#else
+ if ((pData->bHasPLTE) || (pData->bHasIDAT))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen > 4) /* it just can't be bigger than that! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_INCLUDE_JNG /* length checks */
+ if (pData->bHasJHDR)
+ {
+ if ((pData->iJHDRcolortype == 8) && (iRawlen != 1))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iJHDRcolortype == 10) && (iRawlen != 3))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iJHDRcolortype == 12) && (iRawlen != 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iJHDRcolortype == 14) && (iRawlen != 4))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+#endif /* MNG_INCLUDE_JNG */
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+ {
+ if ((pData->iColortype == 0) && (iRawlen != 1))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 2) && (iRawlen != 3))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 3) && (iRawlen != 3))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 4) && (iRawlen != 2))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((pData->iColortype == 6) && (iRawlen != 4))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ { /* global = empty or RGBA */
+ if ((iRawlen != 0) && (iRawlen != 4))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_sbitp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+#ifdef MNG_INCLUDE_JNG
+ if (pData->bHasJHDR)
+ ((mng_sbitp)*ppChunk)->iType = pData->iJHDRcolortype;
+ else
+#endif
+ if (pData->bHasIHDR)
+ ((mng_sbitp)*ppChunk)->iType = pData->iColortype;
+ else /* global ! */
+ ((mng_sbitp)*ppChunk)->iType = 6;
+
+ if (iRawlen > 0)
+ ((mng_sbitp)*ppChunk)->aBits [0] = *pRawdata;
+ if (iRawlen > 1)
+ ((mng_sbitp)*ppChunk)->aBits [1] = *(pRawdata+1);
+ if (iRawlen > 2)
+ ((mng_sbitp)*ppChunk)->aBits [2] = *(pRawdata+2);
+ if (iRawlen > 3)
+ ((mng_sbitp)*ppChunk)->aBits [3] = *(pRawdata+3);
+
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_sPLT
+READ_CHUNK (mng_read_splt)
+{
+ mng_uint8p pTemp;
+ mng_uint32 iNamelen;
+ mng_uint8 iSampledepth;
+ mng_uint32 iRemain;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SPLT, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->bHasIDAT)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen)
+ {
+ pTemp = find_null (pRawdata); /* find null-separator */
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ MNG_ERROR (pData, MNG_NULLNOTFOUND);
+
+ iNamelen = (mng_uint32)(pTemp - pRawdata);
+ iSampledepth = *(pTemp+1);
+ iRemain = (iRawlen - 2 - iNamelen);
+
+ if ((iSampledepth != 1) && (iSampledepth != 2))
+ MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
+ /* check remaining length */
+ if ( ((iSampledepth == 1) && (iRemain % 6 != 0)) ||
+ ((iSampledepth == 2) && (iRemain % 10 != 0)) )
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ }
+ else
+ {
+ pTemp = MNG_NULL;
+ iNamelen = 0;
+ iSampledepth = 0;
+ iRemain = 0;
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_spltp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ ((mng_spltp)*ppChunk)->iNamesize = iNamelen;
+ ((mng_spltp)*ppChunk)->iSampledepth = iSampledepth;
+
+ if (iSampledepth == 1)
+ ((mng_spltp)*ppChunk)->iEntrycount = iRemain / 6;
+ else
+ ((mng_spltp)*ppChunk)->iEntrycount = iRemain / 10;
+
+ if (iNamelen)
+ {
+ MNG_ALLOC (pData, ((mng_spltp)*ppChunk)->zName, iNamelen+1);
+ MNG_COPY (((mng_spltp)*ppChunk)->zName, pRawdata, iNamelen);
+ }
+
+ if (iRemain)
+ {
+ MNG_ALLOC (pData, ((mng_spltp)*ppChunk)->pEntries, iRemain);
+ MNG_COPY (((mng_spltp)*ppChunk)->pEntries, pTemp+2, iRemain);
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_hIST
+READ_CHUNK (mng_read_hist)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_HIST, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) )
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if ((!pData->bHasPLTE) || (pData->bHasIDAT))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* length oke ? */
+ if ( ((iRawlen & 0x01) != 0) || ((iRawlen >> 1) != pData->iPLTEcount) )
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ {
+ mng_uint32 iX;
+ /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_histp)*ppChunk)->iEntrycount = iRawlen >> 1;
+
+ for (iX = 0; iX < (iRawlen >> 1); iX++)
+ {
+ ((mng_histp)*ppChunk)->aEntries [iX] = mng_get_uint16 (pRawdata);
+ pRawdata += 2;
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_tIME
+READ_CHUNK (mng_read_time)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TIME, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 7) /* length must be exactly 7 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+/* if (pData->fProcesstime) */ /* inform the application ? */
+/* {
+
+ pData->fProcesstime ((mng_handle)pData, );
+ } */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_timep)*ppChunk)->iYear = mng_get_uint16 (pRawdata);
+ ((mng_timep)*ppChunk)->iMonth = *(pRawdata+2);
+ ((mng_timep)*ppChunk)->iDay = *(pRawdata+3);
+ ((mng_timep)*ppChunk)->iHour = *(pRawdata+4);
+ ((mng_timep)*ppChunk)->iMinute = *(pRawdata+5);
+ ((mng_timep)*ppChunk)->iSecond = *(pRawdata+6);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_mhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MHDR, MNG_LC_START);
+#endif
+
+ if (pData->eSigtype != mng_it_mng) /* sequence checks */
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ if (pData->bHasheader) /* can only be the first chunk! */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* correct length ? */
+#ifndef MNG_NO_OLD_VERSIONS
+ if ((iRawlen != 28) && (iRawlen != 12))
+#else
+ if ((iRawlen != 28))
+#endif
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasMHDR = MNG_TRUE; /* oh boy, a real MNG */
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_mng; /* fill header fields */
+ pData->iWidth = mng_get_uint32 (pRawdata);
+ pData->iHeight = mng_get_uint32 (pRawdata+4);
+ pData->iTicks = mng_get_uint32 (pRawdata+8);
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (iRawlen == 28) /* proper MHDR ? */
+ {
+#endif
+ pData->iLayercount = mng_get_uint32 (pRawdata+12);
+ pData->iFramecount = mng_get_uint32 (pRawdata+16);
+ pData->iPlaytime = mng_get_uint32 (pRawdata+20);
+ pData->iSimplicity = mng_get_uint32 (pRawdata+24);
+
+#ifndef MNG_NO_OLD_VERSIONS
+ pData->bPreDraft48 = MNG_FALSE;
+ }
+ else /* probably pre-draft48 then */
+ {
+ pData->iLayercount = 0;
+ pData->iFramecount = 0;
+ pData->iPlaytime = 0;
+ pData->iSimplicity = 0;
+
+ pData->bPreDraft48 = MNG_TRUE;
+ }
+#endif
+ /* predict alpha-depth */
+ if ((pData->iSimplicity & 0x00000001) == 0)
+#ifndef MNG_NO_16BIT_SUPPORT
+ pData->iAlphadepth = 16; /* no indicators = assume the worst */
+#else
+ pData->iAlphadepth = 8; /* anything else = assume the worst */
+#endif
+ else
+ if ((pData->iSimplicity & 0x00000008) == 0)
+ pData->iAlphadepth = 0; /* no transparency at all */
+ else
+ if ((pData->iSimplicity & 0x00000140) == 0x00000040)
+ pData->iAlphadepth = 1; /* no semi-transparency guaranteed */
+ else
+#ifndef MNG_NO_16BIT_SUPPORT
+ pData->iAlphadepth = 16; /* anything else = assume the worst */
+#else
+ pData->iAlphadepth = 8; /* anything else = assume the worst */
+#endif
+
+#ifdef MNG_INCLUDE_JNG /* can we handle the complexity ? */
+ if (pData->iSimplicity & 0x0000FC00)
+#else
+ if (pData->iSimplicity & 0x0000FC10)
+#endif
+ MNG_ERROR (pData, MNG_MNGTOOCOMPLEX);
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_mhdrp)*ppChunk)->iWidth = pData->iWidth;
+ ((mng_mhdrp)*ppChunk)->iHeight = pData->iHeight;
+ ((mng_mhdrp)*ppChunk)->iTicks = pData->iTicks;
+ ((mng_mhdrp)*ppChunk)->iLayercount = pData->iLayercount;
+ ((mng_mhdrp)*ppChunk)->iFramecount = pData->iFramecount;
+ ((mng_mhdrp)*ppChunk)->iPlaytime = pData->iPlaytime;
+ ((mng_mhdrp)*ppChunk)->iSimplicity = pData->iSimplicity;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_mend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MEND, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen > 0) /* must not contain data! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* do something */
+ mng_retcode iRetcode = mng_process_display_mend (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (!pData->iTotalframes) /* save totals */
+ pData->iTotalframes = pData->iFrameseq;
+ if (!pData->iTotallayers)
+ pData->iTotallayers = pData->iLayerseq;
+ if (!pData->iTotalplaytime)
+ pData->iTotalplaytime = pData->iFrametime;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ pData->bHasMHDR = MNG_FALSE; /* end of the line, bro! */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_LOOP
+READ_CHUNK (mng_read_loop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_LOOP, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_LOOPWITHCACHEOFF);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen >= 5) /* length checks */
+ {
+ if (iRawlen >= 6)
+ {
+ if ((iRawlen - 6) % 4 != 0)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint8 iLevel;
+ mng_uint32 iRepeat;
+ mng_uint8 iTermination = 0;
+ mng_uint32 iItermin = 1;
+ mng_uint32 iItermax = 0x7fffffffL;
+ mng_retcode iRetcode;
+
+ pData->bHasLOOP = MNG_TRUE; /* indicate we're inside a loop */
+
+ iLevel = *pRawdata; /* determine the fields for processing */
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48)
+ {
+ iTermination = *(pRawdata+1);
+
+ iRepeat = mng_get_uint32 (pRawdata+2);
+ }
+ else
+#endif
+ iRepeat = mng_get_uint32 (pRawdata+1);
+
+ if (iRawlen >= 6)
+ {
+#ifndef MNG_NO_OLD_VERSIONS
+ if (!pData->bPreDraft48)
+#endif
+ iTermination = *(pRawdata+5);
+
+ if (iRawlen >= 10)
+ {
+ iItermin = mng_get_uint32 (pRawdata+6);
+
+ if (iRawlen >= 14)
+ {
+ iItermax = mng_get_uint32 (pRawdata+10);
+
+ /* TODO: process signals */
+
+ }
+ }
+ }
+ /* create the LOOP ani-object */
+ iRetcode = mng_create_ani_loop (pData, iLevel, iRepeat, iTermination,
+ iItermin, iItermax, 0, 0);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* skip till matching ENDL if iteration=0 */
+ if ((!pData->bSkipping) && (iRepeat == 0))
+ pData->bSkipping = MNG_TRUE;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (iRawlen >= 5) /* store the fields */
+ {
+ ((mng_loopp)*ppChunk)->iLevel = *pRawdata;
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48)
+ {
+ ((mng_loopp)*ppChunk)->iTermination = *(pRawdata+1);
+ ((mng_loopp)*ppChunk)->iRepeat = mng_get_uint32 (pRawdata+2);
+ }
+ else
+#endif
+ {
+ ((mng_loopp)*ppChunk)->iRepeat = mng_get_uint32 (pRawdata+1);
+ }
+
+ if (iRawlen >= 6)
+ {
+#ifndef MNG_NO_OLD_VERSIONS
+ if (!pData->bPreDraft48)
+#endif
+ ((mng_loopp)*ppChunk)->iTermination = *(pRawdata+5);
+
+ if (iRawlen >= 10)
+ {
+ ((mng_loopp)*ppChunk)->iItermin = mng_get_uint32 (pRawdata+6);
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (iRawlen >= 14)
+ {
+ ((mng_loopp)*ppChunk)->iItermax = mng_get_uint32 (pRawdata+10);
+ ((mng_loopp)*ppChunk)->iCount = (iRawlen - 14) / 4;
+
+ if (((mng_loopp)*ppChunk)->iCount)
+ {
+ MNG_ALLOC (pData, ((mng_loopp)*ppChunk)->pSignals,
+ ((mng_loopp)*ppChunk)->iCount << 2);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint8p pIn = pRawdata + 14;
+ mng_uint32p pOut = (mng_uint32p)((mng_loopp)*ppChunk)->pSignals;
+
+ for (iX = 0; iX < ((mng_loopp)*ppChunk)->iCount; iX++)
+ {
+ *pOut++ = mng_get_uint32 (pIn);
+ pIn += 4;
+ }
+ }
+#else
+ MNG_COPY (((mng_loopp)*ppChunk)->pSignals, pRawdata + 14,
+ ((mng_loopp)*ppChunk)->iCount << 2);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_LOOP
+READ_CHUNK (mng_read_endl)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ENDL, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 1) /* length must be exactly 1 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ if (pData->bHasLOOP) /* are we really processing a loop ? */
+ {
+ mng_uint8 iLevel = *pRawdata; /* get the nest level */
+ /* create an ENDL animation object */
+ mng_retcode iRetcode = mng_create_ani_endl (pData, iLevel);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+/* {
+ mng_ani_endlp pENDL = (mng_ani_endlp)pData->pLastaniobj;
+
+ iRetcode = pENDL->sHeader.fProcess (pData, pENDL);
+
+ if (iRetcode)
+ return iRetcode;
+ } */
+ }
+ else
+ MNG_ERROR (pData, MNG_NOMATCHINGLOOP);
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_endlp)*ppChunk)->iLevel = *pRawdata;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_DEFI
+READ_CHUNK (mng_read_defi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DEFI, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check the length */
+ if ((iRawlen != 2) && (iRawlen != 3) && (iRawlen != 4) &&
+ (iRawlen != 12) && (iRawlen != 28))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+ pData->iDEFIobjectid = mng_get_uint16 (pRawdata);
+
+ if (iRawlen > 2)
+ {
+ pData->bDEFIhasdonotshow = MNG_TRUE;
+ pData->iDEFIdonotshow = *(pRawdata+2);
+ }
+ else
+ {
+ pData->bDEFIhasdonotshow = MNG_FALSE;
+ pData->iDEFIdonotshow = 0;
+ }
+
+ if (iRawlen > 3)
+ {
+ pData->bDEFIhasconcrete = MNG_TRUE;
+ pData->iDEFIconcrete = *(pRawdata+3);
+ }
+ else
+ {
+ pData->bDEFIhasconcrete = MNG_FALSE;
+ pData->iDEFIconcrete = 0;
+ }
+
+ if (iRawlen > 4)
+ {
+ pData->bDEFIhasloca = MNG_TRUE;
+ pData->iDEFIlocax = mng_get_int32 (pRawdata+4);
+ pData->iDEFIlocay = mng_get_int32 (pRawdata+8);
+ }
+ else
+ {
+ pData->bDEFIhasloca = MNG_FALSE;
+ pData->iDEFIlocax = 0;
+ pData->iDEFIlocay = 0;
+ }
+
+ if (iRawlen > 12)
+ {
+ pData->bDEFIhasclip = MNG_TRUE;
+ pData->iDEFIclipl = mng_get_int32 (pRawdata+12);
+ pData->iDEFIclipr = mng_get_int32 (pRawdata+16);
+ pData->iDEFIclipt = mng_get_int32 (pRawdata+20);
+ pData->iDEFIclipb = mng_get_int32 (pRawdata+24);
+ }
+ else
+ {
+ pData->bDEFIhasclip = MNG_FALSE;
+ pData->iDEFIclipl = 0;
+ pData->iDEFIclipr = 0;
+ pData->iDEFIclipt = 0;
+ pData->iDEFIclipb = 0;
+ }
+ /* create an animation object */
+ iRetcode = mng_create_ani_defi (pData);
+
+ if (!iRetcode) /* do display processing */
+ iRetcode = mng_process_display_defi (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_defip)*ppChunk)->iObjectid = mng_get_uint16 (pRawdata);
+
+ if (iRawlen > 2)
+ {
+ ((mng_defip)*ppChunk)->bHasdonotshow = MNG_TRUE;
+ ((mng_defip)*ppChunk)->iDonotshow = *(pRawdata+2);
+ }
+ else
+ ((mng_defip)*ppChunk)->bHasdonotshow = MNG_FALSE;
+
+ if (iRawlen > 3)
+ {
+ ((mng_defip)*ppChunk)->bHasconcrete = MNG_TRUE;
+ ((mng_defip)*ppChunk)->iConcrete = *(pRawdata+3);
+ }
+ else
+ ((mng_defip)*ppChunk)->bHasconcrete = MNG_FALSE;
+
+ if (iRawlen > 4)
+ {
+ ((mng_defip)*ppChunk)->bHasloca = MNG_TRUE;
+ ((mng_defip)*ppChunk)->iXlocation = mng_get_int32 (pRawdata+4);
+ ((mng_defip)*ppChunk)->iYlocation = mng_get_int32 (pRawdata+8);
+ }
+ else
+ ((mng_defip)*ppChunk)->bHasloca = MNG_FALSE;
+
+ if (iRawlen > 12)
+ {
+ ((mng_defip)*ppChunk)->bHasclip = MNG_TRUE;
+ ((mng_defip)*ppChunk)->iLeftcb = mng_get_int32 (pRawdata+12);
+ ((mng_defip)*ppChunk)->iRightcb = mng_get_int32 (pRawdata+16);
+ ((mng_defip)*ppChunk)->iTopcb = mng_get_int32 (pRawdata+20);
+ ((mng_defip)*ppChunk)->iBottomcb = mng_get_int32 (pRawdata+24);
+ }
+ else
+ ((mng_defip)*ppChunk)->bHasclip = MNG_FALSE;
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_BASI
+READ_CHUNK (mng_read_basi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BASI, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check the length */
+ if ((iRawlen != 13) && (iRawlen != 19) && (iRawlen != 21) && (iRawlen != 22))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasBASI = MNG_TRUE; /* inside a BASI-IEND block now */
+ /* store interesting fields */
+ pData->iDatawidth = mng_get_uint32 (pRawdata);
+ pData->iDataheight = mng_get_uint32 (pRawdata+4);
+ pData->iBitdepth = *(pRawdata+8);
+ pData->iColortype = *(pRawdata+9);
+ pData->iCompression = *(pRawdata+10);
+ pData->iFilter = *(pRawdata+11);
+ pData->iInterlace = *(pRawdata+12);
+
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iBitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iBitdepth < 8)
+ pData->iBitdepth = 8;
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth > 8)
+ {
+ pData->iBitdepth = 8;
+ pData->iPNGmult = 2;
+ }
+#endif
+
+ if ((pData->iBitdepth != 8) /* parameter validity checks */
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iBitdepth != 1) &&
+ (pData->iBitdepth != 2) &&
+ (pData->iBitdepth != 4)
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iBitdepth != 16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
+ (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
+ (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
+ (pData->iBitdepth < 8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iFilter != MNG_FILTER_DIFFERING) &&
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iFilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iFilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iFilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
+ (pData->iInterlace != MNG_INTERLACE_ADAM7) )
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint16 iRed = 0;
+ mng_uint16 iGreen = 0;
+ mng_uint16 iBlue = 0;
+ mng_bool bHasalpha = MNG_FALSE;
+ mng_uint16 iAlpha = 0xFFFF;
+ mng_uint8 iViewable = 0;
+ mng_retcode iRetcode;
+
+ if (iRawlen > 13) /* get remaining fields, if any */
+ {
+ iRed = mng_get_uint16 (pRawdata+13);
+ iGreen = mng_get_uint16 (pRawdata+15);
+ iBlue = mng_get_uint16 (pRawdata+17);
+ }
+
+ if (iRawlen > 19)
+ {
+ bHasalpha = MNG_TRUE;
+ iAlpha = mng_get_uint16 (pRawdata+19);
+ }
+
+ if (iRawlen > 21)
+ iViewable = *(pRawdata+21);
+ /* create an animation object */
+ iRetcode = mng_create_ani_basi (pData, iRed, iGreen, iBlue,
+ bHasalpha, iAlpha, iViewable);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_basi (pData, iRed, iGreen, iBlue,
+ bHasalpha, iAlpha, iViewable); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_basip)*ppChunk)->iWidth = mng_get_uint32 (pRawdata);
+ ((mng_basip)*ppChunk)->iHeight = mng_get_uint32 (pRawdata+4);
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (*(pRawdata+8) > 8)
+ ((mng_basip)*ppChunk)->iBitdepth = 8;
+ else
+#endif
+ ((mng_basip)*ppChunk)->iBitdepth = *(pRawdata+8);
+ ((mng_basip)*ppChunk)->iColortype = *(pRawdata+9);
+ ((mng_basip)*ppChunk)->iCompression = *(pRawdata+10);
+ ((mng_basip)*ppChunk)->iFilter = *(pRawdata+11);
+ ((mng_basip)*ppChunk)->iInterlace = *(pRawdata+12);
+
+ if (iRawlen > 13)
+ {
+ ((mng_basip)*ppChunk)->iRed = mng_get_uint16 (pRawdata+13);
+ ((mng_basip)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+15);
+ ((mng_basip)*ppChunk)->iBlue = mng_get_uint16 (pRawdata+17);
+ }
+
+ if (iRawlen > 19)
+ ((mng_basip)*ppChunk)->iAlpha = mng_get_uint16 (pRawdata+19);
+
+ if (iRawlen > 21)
+ ((mng_basip)*ppChunk)->iViewable = *(pRawdata+21);
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_CLON
+READ_CHUNK (mng_read_clon)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CLON, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check the length */
+ if ((iRawlen != 4) && (iRawlen != 5) && (iRawlen != 6) &&
+ (iRawlen != 7) && (iRawlen != 16))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint16 iSourceid, iCloneid;
+ mng_uint8 iClonetype = 0;
+ mng_bool bHasdonotshow = MNG_FALSE;
+ mng_uint8 iDonotshow = 0;
+ mng_uint8 iConcrete = 0;
+ mng_bool bHasloca = MNG_FALSE;
+ mng_uint8 iLocationtype = 0;
+ mng_int32 iLocationx = 0;
+ mng_int32 iLocationy = 0;
+ mng_retcode iRetcode;
+
+ iSourceid = mng_get_uint16 (pRawdata);
+ iCloneid = mng_get_uint16 (pRawdata+2);
+
+ if (iRawlen > 4)
+ iClonetype = *(pRawdata+4);
+
+ if (iRawlen > 5)
+ {
+ bHasdonotshow = MNG_TRUE;
+ iDonotshow = *(pRawdata+5);
+ }
+
+ if (iRawlen > 6)
+ iConcrete = *(pRawdata+6);
+
+ if (iRawlen > 7)
+ {
+ bHasloca = MNG_TRUE;
+ iLocationtype = *(pRawdata+7);
+ iLocationx = mng_get_int32 (pRawdata+8);
+ iLocationy = mng_get_int32 (pRawdata+12);
+ }
+
+ iRetcode = mng_create_ani_clon (pData, iSourceid, iCloneid, iClonetype,
+ bHasdonotshow, iDonotshow, iConcrete,
+ bHasloca, iLocationtype, iLocationx, iLocationy);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_clon (pData, iSourceid, iCloneid, iClonetype,
+ bHasdonotshow, iDonotshow, iConcrete,
+ bHasloca, iLocationtype, iLocationx,
+ iLocationy); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_clonp)*ppChunk)->iSourceid = mng_get_uint16 (pRawdata);
+ ((mng_clonp)*ppChunk)->iCloneid = mng_get_uint16 (pRawdata+2);
+
+ if (iRawlen > 4)
+ ((mng_clonp)*ppChunk)->iClonetype = *(pRawdata+4);
+
+ if (iRawlen > 5)
+ ((mng_clonp)*ppChunk)->iDonotshow = *(pRawdata+5);
+
+ if (iRawlen > 6)
+ ((mng_clonp)*ppChunk)->iConcrete = *(pRawdata+6);
+
+ if (iRawlen > 7)
+ {
+ ((mng_clonp)*ppChunk)->bHasloca = MNG_TRUE;
+ ((mng_clonp)*ppChunk)->iLocationtype = *(pRawdata+7);
+ ((mng_clonp)*ppChunk)->iLocationx = mng_get_int32 (pRawdata+8);
+ ((mng_clonp)*ppChunk)->iLocationy = mng_get_int32 (pRawdata+12);
+ }
+ else
+ {
+ ((mng_clonp)*ppChunk)->bHasloca = MNG_FALSE;
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_PAST
+READ_CHUNK (mng_read_past)
+{
+#if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
+ mng_retcode iRetcode;
+ mng_uint16 iTargetid;
+ mng_uint8 iTargettype;
+ mng_int32 iTargetx;
+ mng_int32 iTargety;
+ mng_uint32 iCount;
+ mng_uint32 iSize;
+ mng_ptr pSources;
+ mng_uint32 iX;
+ mng_past_sourcep pSource;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PAST, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ /* check the length */
+ if ((iRawlen < 41) || (((iRawlen - 11) % 30) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
+ iTargetid = mng_get_uint16 (pRawdata);
+ iTargettype = *(pRawdata+2);
+ iTargetx = mng_get_int32 (pRawdata+3);
+ iTargety = mng_get_int32 (pRawdata+7);
+ iCount = ((iRawlen - 11) / 30); /* how many entries again? */
+ iSize = iCount * sizeof (mng_past_source);
+
+ pRawdata += 11;
+ /* get a buffer for all the source blocks */
+ MNG_ALLOC (pData, pSources, iSize);
+
+ pSource = (mng_past_sourcep)pSources;
+
+ for (iX = 0; iX < iCount; iX++) /* now copy the source blocks */
+ {
+ pSource->iSourceid = mng_get_uint16 (pRawdata);
+ pSource->iComposition = *(pRawdata+2);
+ pSource->iOrientation = *(pRawdata+3);
+ pSource->iOffsettype = *(pRawdata+4);
+ pSource->iOffsetx = mng_get_int32 (pRawdata+5);
+ pSource->iOffsety = mng_get_int32 (pRawdata+9);
+ pSource->iBoundarytype = *(pRawdata+13);
+ pSource->iBoundaryl = mng_get_int32 (pRawdata+14);
+ pSource->iBoundaryr = mng_get_int32 (pRawdata+18);
+ pSource->iBoundaryt = mng_get_int32 (pRawdata+22);
+ pSource->iBoundaryb = mng_get_int32 (pRawdata+26);
+
+ pSource++;
+ pRawdata += 30;
+ }
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create playback object */
+ iRetcode = mng_create_ani_past (pData, iTargetid, iTargettype, iTargetx,
+ iTargety, iCount, pSources);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_past (pData, iTargetid, iTargettype, iTargetx,
+ iTargety, iCount, pSources); */
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pSources, iSize);
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pSources, iSize);
+ return iRetcode;
+ }
+ /* store the fields */
+ ((mng_pastp)*ppChunk)->iDestid = iTargetid;
+ ((mng_pastp)*ppChunk)->iTargettype = iTargettype;
+ ((mng_pastp)*ppChunk)->iTargetx = iTargetx;
+ ((mng_pastp)*ppChunk)->iTargety = iTargety;
+ ((mng_pastp)*ppChunk)->iCount = iCount;
+ /* get a buffer & copy the source blocks */
+ MNG_ALLOC (pData, ((mng_pastp)*ppChunk)->pSources, iSize);
+ MNG_COPY (((mng_pastp)*ppChunk)->pSources, pSources, iSize);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#if defined(MNG_STORE_CHUNKS) || defined(MNG_SUPPORT_DISPLAY)
+ /* free the source block buffer */
+ MNG_FREEX (pData, pSources, iSize);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_DISC
+READ_CHUNK (mng_read_disc)
+{
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ mng_uint32 iCount;
+ mng_uint16p pIds = MNG_NULL;
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DISC, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if ((iRawlen % 2) != 0) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ iCount = (iRawlen / sizeof (mng_uint16));
+
+ if (iCount)
+ {
+ MNG_ALLOC (pData, pIds, iRawlen);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint8p pIn = pRawdata;
+ mng_uint16p pOut = pIds;
+
+ for (iX = 0; iX < iCount; iX++)
+ {
+ *pOut++ = mng_get_uint16 (pIn);
+ pIn += 2;
+ }
+ }
+#else
+ MNG_COPY (pIds, pRawdata, iRawlen);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create playback object */
+ iRetcode = mng_create_ani_disc (pData, iCount, pIds);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_disc (pData, iCount, pIds); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_discp)*ppChunk)->iCount = iCount;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_discp)*ppChunk)->pObjectids, iRawlen);
+ MNG_COPY (((mng_discp)*ppChunk)->pObjectids, pIds, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ if (iRawlen)
+ MNG_FREEX (pData, pIds, iRawlen);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_BACK
+READ_CHUNK (mng_read_back)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BACK, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check the length */
+ if ((iRawlen != 6) && (iRawlen != 7) && (iRawlen != 9) && (iRawlen != 10))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+ /* retrieve the fields */
+ pData->bHasBACK = MNG_TRUE;
+ pData->iBACKred = mng_get_uint16 (pRawdata);
+ pData->iBACKgreen = mng_get_uint16 (pRawdata+2);
+ pData->iBACKblue = mng_get_uint16 (pRawdata+4);
+
+ if (iRawlen > 6)
+ pData->iBACKmandatory = *(pRawdata+6);
+ else
+ pData->iBACKmandatory = 0;
+
+ if (iRawlen > 7)
+ pData->iBACKimageid = mng_get_uint16 (pRawdata+7);
+ else
+ pData->iBACKimageid = 0;
+
+ if (iRawlen > 9)
+ pData->iBACKtile = *(pRawdata+9);
+ else
+ pData->iBACKtile = 0;
+
+ iRetcode = mng_create_ani_back (pData, pData->iBACKred, pData->iBACKgreen,
+ pData->iBACKblue, pData->iBACKmandatory,
+ pData->iBACKimageid, pData->iBACKtile);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_backp)*ppChunk)->iRed = mng_get_uint16 (pRawdata);
+ ((mng_backp)*ppChunk)->iGreen = mng_get_uint16 (pRawdata+2);
+ ((mng_backp)*ppChunk)->iBlue = mng_get_uint16 (pRawdata+4);
+
+ if (iRawlen > 6)
+ ((mng_backp)*ppChunk)->iMandatory = *(pRawdata+6);
+
+ if (iRawlen > 7)
+ ((mng_backp)*ppChunk)->iImageid = mng_get_uint16 (pRawdata+7);
+
+ if (iRawlen > 9)
+ ((mng_backp)*ppChunk)->iTile = *(pRawdata+9);
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_FRAM
+READ_CHUNK (mng_read_fram)
+{
+ mng_uint8p pTemp;
+#ifdef MNG_STORE_CHUNKS
+ mng_uint32 iNamelen;
+#endif
+ mng_uint32 iRemain;
+ mng_uint32 iRequired = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_FRAM, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen <= 1) /* only framing-mode ? */
+ {
+#ifdef MNG_STORE_CHUNKS
+ iNamelen = 0; /* indicate so */
+#endif
+ iRemain = 0;
+ pTemp = MNG_NULL;
+ }
+ else
+ {
+ pTemp = find_null (pRawdata+1); /* find null-separator */
+ /* not found inside input-data ? */
+ if ((pTemp - pRawdata) > (mng_int32)iRawlen)
+ pTemp = pRawdata + iRawlen; /* than remainder is name */
+
+#ifdef MNG_STORE_CHUNKS
+ iNamelen = (mng_uint32)((pTemp - pRawdata) - 1);
+#endif
+ iRemain = (mng_uint32)(iRawlen - (pTemp - pRawdata));
+
+ if (iRemain) /* if there is remaining data it's less 1 byte */
+ iRemain--;
+
+ if ((iRemain) && (iRemain < 4)) /* remains must be empty or at least 4 bytes */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if (iRemain)
+ {
+ iRequired = 4; /* calculate and check required remaining length */
+
+ if (*(pTemp+1)) { iRequired += 4; }
+ if (*(pTemp+2)) { iRequired += 4; }
+ if (*(pTemp+3)) { iRequired += 17; }
+
+ if (*(pTemp+4))
+ {
+ if ((iRemain - iRequired) % 4 != 0)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ else
+ {
+ if (iRemain != iRequired)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint8p pWork = pTemp;
+ mng_uint8 iFramemode = 0;
+ mng_uint8 iChangedelay = 0;
+ mng_uint32 iDelay = 0;
+ mng_uint8 iChangetimeout = 0;
+ mng_uint32 iTimeout = 0;
+ mng_uint8 iChangeclipping = 0;
+ mng_uint8 iCliptype = 0;
+ mng_int32 iClipl = 0;
+ mng_int32 iClipr = 0;
+ mng_int32 iClipt = 0;
+ mng_int32 iClipb = 0;
+ mng_retcode iRetcode;
+
+ if (iRawlen) /* any data specified ? */
+ {
+ if (*(pRawdata)) /* save the new framing mode ? */
+ {
+ iFramemode = *(pRawdata);
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48) /* old style input-stream ? */
+ {
+ switch (iFramemode)
+ {
+ case 0: { break; }
+ case 1: { iFramemode = 3; break; }
+ case 2: { iFramemode = 4; break; }
+ case 3: { iFramemode = 1; break; }
+ case 4: { iFramemode = 1; break; }
+ case 5: { iFramemode = 2; break; }
+ default: { iFramemode = 1; break; }
+ }
+ }
+#endif
+ }
+
+ if (iRemain)
+ {
+ iChangedelay = *(pWork+1);
+ iChangetimeout = *(pWork+2);
+ iChangeclipping = *(pWork+3);
+ pWork += 5;
+
+ if (iChangedelay) /* delay changed ? */
+ {
+ iDelay = mng_get_uint32 (pWork);
+ pWork += 4;
+ }
+
+ if (iChangetimeout) /* timeout changed ? */
+ {
+ iTimeout = mng_get_uint32 (pWork);
+ pWork += 4;
+ }
+
+ if (iChangeclipping) /* clipping changed ? */
+ {
+ iCliptype = *pWork;
+ iClipl = mng_get_int32 (pWork+1);
+ iClipr = mng_get_int32 (pWork+5);
+ iClipt = mng_get_int32 (pWork+9);
+ iClipb = mng_get_int32 (pWork+13);
+ }
+ }
+ }
+
+ iRetcode = mng_create_ani_fram (pData, iFramemode, iChangedelay, iDelay,
+ iChangetimeout, iTimeout,
+ iChangeclipping, iCliptype,
+ iClipl, iClipr, iClipt, iClipb);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_fram (pData, iFramemode, iChangedelay, iDelay,
+ iChangetimeout, iTimeout,
+ iChangeclipping, iCliptype,
+ iClipl, iClipr, iClipt, iClipb); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_framp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ mng_uint8 iFramemode = *(pRawdata);
+
+#ifndef MNG_NO_OLD_VERSIONS
+ if (pData->bPreDraft48) /* old style input-stream ? */
+ {
+ switch (iFramemode)
+ {
+ case 1: { iFramemode = 3; break; }
+ case 2: { iFramemode = 4; break; }
+ case 3: { iFramemode = 5; break; } /* TODO: provision for mode=5 ??? */
+ case 4: { iFramemode = 1; break; }
+ case 5: { iFramemode = 2; break; }
+ default: { iFramemode = 1; break; }
+ }
+ }
+#endif
+
+ ((mng_framp)*ppChunk)->iMode = iFramemode;
+ ((mng_framp)*ppChunk)->iNamesize = iNamelen;
+
+ if (iNamelen)
+ {
+ MNG_ALLOC (pData, ((mng_framp)*ppChunk)->zName, iNamelen+1);
+ MNG_COPY (((mng_framp)*ppChunk)->zName, pRawdata+1, iNamelen);
+ }
+
+ if (iRemain)
+ {
+ ((mng_framp)*ppChunk)->iChangedelay = *(pTemp+1);
+ ((mng_framp)*ppChunk)->iChangetimeout = *(pTemp+2);
+ ((mng_framp)*ppChunk)->iChangeclipping = *(pTemp+3);
+ ((mng_framp)*ppChunk)->iChangesyncid = *(pTemp+4);
+
+ pTemp += 5;
+
+ if (((mng_framp)*ppChunk)->iChangedelay)
+ {
+ ((mng_framp)*ppChunk)->iDelay = mng_get_uint32 (pTemp);
+ pTemp += 4;
+ }
+
+ if (((mng_framp)*ppChunk)->iChangetimeout)
+ {
+ ((mng_framp)*ppChunk)->iTimeout = mng_get_uint32 (pTemp);
+ pTemp += 4;
+ }
+
+ if (((mng_framp)*ppChunk)->iChangeclipping)
+ {
+ ((mng_framp)*ppChunk)->iBoundarytype = *pTemp;
+ ((mng_framp)*ppChunk)->iBoundaryl = mng_get_int32 (pTemp+1);
+ ((mng_framp)*ppChunk)->iBoundaryr = mng_get_int32 (pTemp+5);
+ ((mng_framp)*ppChunk)->iBoundaryt = mng_get_int32 (pTemp+9);
+ ((mng_framp)*ppChunk)->iBoundaryb = mng_get_int32 (pTemp+13);
+ pTemp += 17;
+ }
+
+ if (((mng_framp)*ppChunk)->iChangesyncid)
+ {
+ ((mng_framp)*ppChunk)->iCount = (iRemain - iRequired) / 4;
+
+ if (((mng_framp)*ppChunk)->iCount)
+ {
+ MNG_ALLOC (pData, ((mng_framp)*ppChunk)->pSyncids,
+ ((mng_framp)*ppChunk)->iCount * 4);
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+ {
+ mng_uint32 iX;
+ mng_uint32p pOut = ((mng_framp)*ppChunk)->pSyncids;
+
+ for (iX = 0; iX < ((mng_framp)*ppChunk)->iCount; iX++)
+ {
+ *pOut++ = mng_get_uint32 (pTemp);
+ pTemp += 4;
+ }
+ }
+#else
+ MNG_COPY (((mng_framp)*ppChunk)->pSyncids, pTemp,
+ ((mng_framp)*ppChunk)->iCount * 4);
+#endif /* !MNG_BIGENDIAN_SUPPORTED */
+ }
+ }
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_MOVE
+READ_CHUNK (mng_read_move)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MOVE, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 13) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+ /* create a MOVE animation object */
+ iRetcode = mng_create_ani_move (pData, mng_get_uint16 (pRawdata),
+ mng_get_uint16 (pRawdata+2),
+ *(pRawdata+4),
+ mng_get_int32 (pRawdata+5),
+ mng_get_int32 (pRawdata+9));
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_move (pData,
+ mng_get_uint16 (pRawdata),
+ mng_get_uint16 (pRawdata+2),
+ *(pRawdata+4),
+ mng_get_int32 (pRawdata+5),
+ mng_get_int32 (pRawdata+9)); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_movep)*ppChunk)->iFirstid = mng_get_uint16 (pRawdata);
+ ((mng_movep)*ppChunk)->iLastid = mng_get_uint16 (pRawdata+2);
+ ((mng_movep)*ppChunk)->iMovetype = *(pRawdata+4);
+ ((mng_movep)*ppChunk)->iMovex = mng_get_int32 (pRawdata+5);
+ ((mng_movep)*ppChunk)->iMovey = mng_get_int32 (pRawdata+9);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_CLIP
+READ_CHUNK (mng_read_clip)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CLIP, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 21) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+ /* create a CLIP animation object */
+ iRetcode = mng_create_ani_clip (pData, mng_get_uint16 (pRawdata),
+ mng_get_uint16 (pRawdata+2),
+ *(pRawdata+4),
+ mng_get_int32 (pRawdata+5),
+ mng_get_int32 (pRawdata+9),
+ mng_get_int32 (pRawdata+13),
+ mng_get_int32 (pRawdata+17));
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_clip (pData,
+ mng_get_uint16 (pRawdata),
+ mng_get_uint16 (pRawdata+2),
+ *(pRawdata+4),
+ mng_get_int32 (pRawdata+5),
+ mng_get_int32 (pRawdata+9),
+ mng_get_int32 (pRawdata+13),
+ mng_get_int32 (pRawdata+17)); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_clipp)*ppChunk)->iFirstid = mng_get_uint16 (pRawdata);
+ ((mng_clipp)*ppChunk)->iLastid = mng_get_uint16 (pRawdata+2);
+ ((mng_clipp)*ppChunk)->iCliptype = *(pRawdata+4);
+ ((mng_clipp)*ppChunk)->iClipl = mng_get_int32 (pRawdata+5);
+ ((mng_clipp)*ppChunk)->iClipr = mng_get_int32 (pRawdata+9);
+ ((mng_clipp)*ppChunk)->iClipt = mng_get_int32 (pRawdata+13);
+ ((mng_clipp)*ppChunk)->iClipb = mng_get_int32 (pRawdata+17);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_SHOW
+READ_CHUNK (mng_read_show)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SHOW, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check the length */
+ if ((iRawlen != 0) && (iRawlen != 2) && (iRawlen != 4) && (iRawlen != 5))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+ if (iRawlen) /* determine parameters if any */
+ {
+ pData->iSHOWfromid = mng_get_uint16 (pRawdata);
+
+ if (iRawlen > 2)
+ pData->iSHOWtoid = mng_get_uint16 (pRawdata+2);
+ else
+ pData->iSHOWtoid = pData->iSHOWfromid;
+
+ if (iRawlen > 4)
+ pData->iSHOWmode = *(pRawdata+4);
+ else
+ pData->iSHOWmode = 0;
+ }
+ else /* use defaults then */
+ {
+ pData->iSHOWmode = 2;
+ pData->iSHOWfromid = 1;
+ pData->iSHOWtoid = 65535;
+ }
+ /* create a SHOW animation object */
+ iRetcode = mng_create_ani_show (pData, pData->iSHOWfromid,
+ pData->iSHOWtoid, pData->iSHOWmode);
+
+ if (!iRetcode)
+ iRetcode = mng_process_display_show (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_showp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ ((mng_showp)*ppChunk)->iFirstid = mng_get_uint16 (pRawdata);
+
+ if (iRawlen > 2)
+ ((mng_showp)*ppChunk)->iLastid = mng_get_uint16 (pRawdata+2);
+ else
+ ((mng_showp)*ppChunk)->iLastid = ((mng_showp)*ppChunk)->iFirstid;
+
+ if (iRawlen > 4)
+ ((mng_showp)*ppChunk)->iMode = *(pRawdata+4);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_TERM
+READ_CHUNK (mng_read_term)
+{
+ mng_uint8 iTermaction;
+ mng_uint8 iIteraction = 0;
+ mng_uint32 iDelay = 0;
+ mng_uint32 iItermax = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TERM, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ /* should be behind MHDR or SAVE !! */
+ if ((!pData->bHasSAVE) && (pData->iChunkseq > 2))
+ {
+ pData->bMisplacedTERM = MNG_TRUE; /* indicate we found a misplaced TERM */
+ /* and send a warning signal!!! */
+ MNG_WARNING (pData, MNG_SEQUENCEERROR);
+ }
+
+ if (pData->bHasLOOP) /* no way, jose! */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->bHasTERM) /* only 1 allowed! */
+ MNG_ERROR (pData, MNG_MULTIPLEERROR);
+ /* check the length */
+ if ((iRawlen != 1) && (iRawlen != 10))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasTERM = MNG_TRUE;
+
+ iTermaction = *pRawdata; /* get the fields */
+
+ if (iRawlen > 1)
+ {
+ iIteraction = *(pRawdata+1);
+ iDelay = mng_get_uint32 (pRawdata+2);
+ iItermax = mng_get_uint32 (pRawdata+6);
+ }
+
+ if (pData->fProcessterm) /* inform the app ? */
+ if (!pData->fProcessterm (((mng_handle)pData), iTermaction, iIteraction,
+ iDelay, iItermax))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create the TERM ani-object */
+ mng_retcode iRetcode = mng_create_ani_term (pData, iTermaction, iIteraction,
+ iDelay, iItermax);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* save for future reference */
+ pData->pTermaniobj = pData->pLastaniobj;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_termp)*ppChunk)->iTermaction = iTermaction;
+ ((mng_termp)*ppChunk)->iIteraction = iIteraction;
+ ((mng_termp)*ppChunk)->iDelay = iDelay;
+ ((mng_termp)*ppChunk)->iItermax = iItermax;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_SAVE
+READ_CHUNK (mng_read_save)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SAVE, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (pData->bHasSAVE))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ pData->bHasSAVE = MNG_TRUE;
+
+ if (pData->fProcesssave) /* inform the application ? */
+ {
+ mng_bool bOke = pData->fProcesssave ((mng_handle)pData);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+
+ /* TODO: something with the parameters */
+
+
+ /* create a SAVE animation object */
+ iRetcode = mng_create_ani_save (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_process_display_save (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_savep)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen) /* not empty ? */
+ {
+ mng_uint8 iOtype = *pRawdata;
+ mng_uint8 iEtype;
+ mng_uint32 iCount = 0;
+ mng_uint8p pTemp;
+ mng_uint8p pNull;
+ mng_uint32 iLen;
+ mng_uint32 iOffset[2];
+ mng_uint32 iStarttime[2];
+ mng_uint32 iFramenr;
+ mng_uint32 iLayernr;
+ mng_uint32 iX;
+ mng_save_entryp pEntry = MNG_NULL;
+ mng_uint32 iNamesize;
+
+ if ((iOtype != 4) && (iOtype != 8))
+ MNG_ERROR (pData, MNG_INVOFFSETSIZE);
+
+ ((mng_savep)*ppChunk)->iOffsettype = iOtype;
+
+ for (iX = 0; iX < 2; iX++) /* do this twice to get the count first ! */
+ {
+ pTemp = pRawdata + 1;
+ iLen = iRawlen - 1;
+
+ if (iX) /* second run ? */
+ {
+ MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_save_entry)));
+
+ ((mng_savep)*ppChunk)->iCount = iCount;
+ ((mng_savep)*ppChunk)->pEntries = pEntry;
+ }
+
+ while (iLen) /* anything left ? */
+ {
+ iEtype = *pTemp; /* entrytype */
+
+ if ((iEtype != 0) && (iEtype != 1) && (iEtype != 2) && (iEtype != 3))
+ MNG_ERROR (pData, MNG_INVENTRYTYPE);
+
+ pTemp++;
+
+ if (iEtype > 1)
+ {
+ iOffset [0] = 0;
+ iOffset [1] = 0;
+ iStarttime [0] = 0;
+ iStarttime [1] = 0;
+ iLayernr = 0;
+ iFramenr = 0;
+ }
+ else
+ {
+ if (iOtype == 4)
+ {
+ iOffset [0] = 0;
+ iOffset [1] = mng_get_uint32 (pTemp);
+
+ pTemp += 4;
+ }
+ else
+ {
+ iOffset [0] = mng_get_uint32 (pTemp);
+ iOffset [1] = mng_get_uint32 (pTemp+4);
+
+ pTemp += 8;
+ }
+
+ if (iEtype > 0)
+ {
+ iStarttime [0] = 0;
+ iStarttime [1] = 0;
+ iLayernr = 0;
+ iFramenr = 0;
+ }
+ else
+ {
+ if (iOtype == 4)
+ {
+ iStarttime [0] = 0;
+ iStarttime [1] = mng_get_uint32 (pTemp+0);
+ iLayernr = mng_get_uint32 (pTemp+4);
+ iFramenr = mng_get_uint32 (pTemp+8);
+
+ pTemp += 12;
+ }
+ else
+ {
+ iStarttime [0] = mng_get_uint32 (pTemp+0);
+ iStarttime [1] = mng_get_uint32 (pTemp+4);
+ iLayernr = mng_get_uint32 (pTemp+8);
+ iFramenr = mng_get_uint32 (pTemp+12);
+
+ pTemp += 16;
+ }
+ }
+ }
+
+ pNull = find_null (pTemp); /* get the name length */
+
+ if ((pNull - pRawdata) > (mng_int32)iRawlen)
+ {
+ iNamesize = iLen; /* no null found; so end of SAVE */
+ iLen = 0;
+ }
+ else
+ {
+ iNamesize = pNull - pTemp; /* should be another entry */
+ iLen -= iNamesize;
+
+ if (!iLen) /* must not end with a null ! */
+ MNG_ERROR (pData, MNG_ENDWITHNULL);
+ }
+
+ if (!pEntry)
+ {
+ iCount++;
+ }
+ else
+ {
+ pEntry->iEntrytype = iEtype;
+ pEntry->iOffset [0] = iOffset [0];
+ pEntry->iOffset [1] = iOffset [1];
+ pEntry->iStarttime [0] = iStarttime [0];
+ pEntry->iStarttime [1] = iStarttime [1];
+ pEntry->iLayernr = iLayernr;
+ pEntry->iFramenr = iFramenr;
+ pEntry->iNamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zName, iNamesize+1);
+ MNG_COPY (pEntry->zName, pTemp, iNamesize);
+ }
+
+ pEntry++;
+ }
+
+ pTemp += iNamesize;
+ }
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_SEEK
+READ_CHUNK (mng_read_seek)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SEEK, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasSAVE))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ /* create a SEEK animation object */
+ iRetcode = mng_create_ani_seek (pData, iRawlen, (mng_pchar)pRawdata);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ if (pData->fProcessseek) /* inform the app ? */
+ {
+ mng_bool bOke;
+ mng_pchar zName;
+
+ MNG_ALLOC (pData, zName, iRawlen + 1);
+
+ if (iRawlen)
+ MNG_COPY (zName, pRawdata, iRawlen);
+
+ bOke = pData->fProcessseek ((mng_handle)pData, zName);
+
+ MNG_FREEX (pData, zName, iRawlen + 1);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ /* do display processing of the SEEK */
+ iRetcode = mng_process_display_seek (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_seekp)*ppChunk)->iNamesize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_seekp)*ppChunk)->zName, iRawlen+1);
+ MNG_COPY (((mng_seekp)*ppChunk)->zName, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_eXPI
+READ_CHUNK (mng_read_expi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_EXPI, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 3) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_expip)*ppChunk)->iSnapshotid = mng_get_uint16 (pRawdata);
+ ((mng_expip)*ppChunk)->iNamesize = iRawlen - 2;
+
+ if (((mng_expip)*ppChunk)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_expip)*ppChunk)->zName,
+ ((mng_expip)*ppChunk)->iNamesize + 1);
+ MNG_COPY (((mng_expip)*ppChunk)->zName, pRawdata+2,
+ ((mng_expip)*ppChunk)->iNamesize);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_EXPI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_fPRI
+READ_CHUNK (mng_read_fpri)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_FPRI, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 2) /* must be two bytes long */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_fprip)*ppChunk)->iDeltatype = *pRawdata;
+ ((mng_fprip)*ppChunk)->iPriority = *(pRawdata+1);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_nEED
+MNG_LOCAL mng_bool CheckKeyword (mng_datap pData,
+ mng_uint8p pKeyword)
+{
+ mng_chunkid handled_chunks [] =
+ {
+ MNG_UINT_BACK, /* keep it sorted !!!! */
+ MNG_UINT_BASI,
+ MNG_UINT_CLIP,
+ MNG_UINT_CLON,
+#ifndef MNG_NO_DELTA_PNG
+/* TODO: MNG_UINT_DBYK, */
+#endif
+ MNG_UINT_DEFI,
+#ifndef MNG_NO_DELTA_PNG
+ MNG_UINT_DHDR,
+#endif
+ MNG_UINT_DISC,
+#ifndef MNG_NO_DELTA_PNG
+/* TODO: MNG_UINT_DROP, */
+#endif
+ MNG_UINT_ENDL,
+ MNG_UINT_FRAM,
+ MNG_UINT_IDAT,
+ MNG_UINT_IEND,
+ MNG_UINT_IHDR,
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ MNG_UINT_IJNG,
+#endif
+ MNG_UINT_IPNG,
+#endif
+#ifdef MNG_INCLUDE_JNG
+ MNG_UINT_JDAA,
+ MNG_UINT_JDAT,
+ MNG_UINT_JHDR,
+/* TODO: MNG_UINT_JSEP, */
+ MNG_UINT_JdAA,
+#endif
+ MNG_UINT_LOOP,
+ MNG_UINT_MAGN,
+ MNG_UINT_MEND,
+ MNG_UINT_MHDR,
+ MNG_UINT_MOVE,
+/* TODO: MNG_UINT_ORDR, */
+ MNG_UINT_PAST,
+ MNG_UINT_PLTE,
+#ifndef MNG_NO_DELTA_PNG
+ MNG_UINT_PPLT,
+ MNG_UINT_PROM,
+#endif
+ MNG_UINT_SAVE,
+ MNG_UINT_SEEK,
+ MNG_UINT_SHOW,
+ MNG_UINT_TERM,
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ MNG_UINT_adAT,
+ MNG_UINT_ahDR,
+#endif
+ MNG_UINT_bKGD,
+ MNG_UINT_cHRM,
+/* TODO: MNG_UINT_eXPI, */
+ MNG_UINT_evNT,
+/* TODO: MNG_UINT_fPRI, */
+ MNG_UINT_gAMA,
+/* TODO: MNG_UINT_hIST, */
+ MNG_UINT_iCCP,
+ MNG_UINT_iTXt,
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ MNG_UINT_mpNG,
+#endif
+ MNG_UINT_nEED,
+/* TODO: MNG_UINT_oFFs, */
+/* TODO: MNG_UINT_pCAL, */
+/* TODO: MNG_UINT_pHYg, */
+/* TODO: MNG_UINT_pHYs, */
+/* TODO: MNG_UINT_sBIT, */
+/* TODO: MNG_UINT_sCAL, */
+/* TODO: MNG_UINT_sPLT, */
+ MNG_UINT_sRGB,
+ MNG_UINT_tEXt,
+ MNG_UINT_tIME,
+ MNG_UINT_tRNS,
+ MNG_UINT_zTXt,
+ };
+
+ mng_bool bOke = MNG_FALSE;
+
+ if (pData->fProcessneed) /* does the app handle it ? */
+ bOke = pData->fProcessneed ((mng_handle)pData, (mng_pchar)pKeyword);
+
+ if (!bOke)
+ { /* find the keyword length */
+ mng_uint8p pNull = find_null (pKeyword);
+
+ if (pNull - pKeyword == 4) /* test a chunk ? */
+ { /* get the chunk-id */
+ mng_chunkid iChunkid = (*pKeyword << 24) + (*(pKeyword+1) << 16) +
+ (*(pKeyword+2) << 8) + (*(pKeyword+3) );
+ /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ /* determine max index of table */
+ iTop = (sizeof (handled_chunks) / sizeof (handled_chunks [0])) - 1;
+
+ /* binary search; with 52 chunks, worst-case is 7 comparisons */
+ iLower = 0;
+ iMiddle = iTop >> 1;
+ iUpper = iTop;
+
+ do /* the binary search itself */
+ {
+ if (handled_chunks [iMiddle] < iChunkid)
+ iLower = iMiddle + 1;
+ else if (handled_chunks [iMiddle] > iChunkid)
+ iUpper = iMiddle - 1;
+ else
+ {
+ bOke = MNG_TRUE;
+ break;
+ }
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+ }
+ /* test draft ? */
+ if ((!bOke) && (pNull - pKeyword == 8) &&
+ (*pKeyword == 'd') && (*(pKeyword+1) == 'r') &&
+ (*(pKeyword+2) == 'a') && (*(pKeyword+3) == 'f') &&
+ (*(pKeyword+4) == 't') && (*(pKeyword+5) == ' '))
+ {
+ mng_uint32 iDraft;
+
+ iDraft = (*(pKeyword+6) - '0') * 10 + (*(pKeyword+7) - '0');
+ bOke = (mng_bool)(iDraft <= MNG_MNG_DRAFT);
+ }
+ /* test MNG 1.0/1.1 ? */
+ if ((!bOke) && (pNull - pKeyword == 7) &&
+ (*pKeyword == 'M') && (*(pKeyword+1) == 'N') &&
+ (*(pKeyword+2) == 'G') && (*(pKeyword+3) == '-') &&
+ (*(pKeyword+4) == '1') && (*(pKeyword+5) == '.') &&
+ ((*(pKeyword+6) == '0') || (*(pKeyword+6) == '1')))
+ bOke = MNG_TRUE;
+ /* test CACHEOFF ? */
+ if ((!bOke) && (pNull - pKeyword == 8) &&
+ (*pKeyword == 'C') && (*(pKeyword+1) == 'A') &&
+ (*(pKeyword+2) == 'C') && (*(pKeyword+3) == 'H') &&
+ (*(pKeyword+4) == 'E') && (*(pKeyword+5) == 'O') &&
+ (*(pKeyword+6) == 'F') && (*(pKeyword+7) == 'F'))
+ {
+ if (!pData->pFirstaniobj) /* only if caching hasn't started yet ! */
+ {
+ bOke = MNG_TRUE;
+ pData->bCacheplayback = MNG_FALSE;
+ pData->bStorechunks = MNG_FALSE;
+ }
+ }
+ }
+
+ return bOke;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_nEED
+READ_CHUNK (mng_read_need)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_NEED, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 1) /* check the length */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ { /* let's check it */
+ mng_bool bOke = MNG_TRUE;
+ mng_pchar zKeywords;
+ mng_uint8p pNull, pTemp;
+
+ MNG_ALLOC (pData, zKeywords, iRawlen + 1);
+
+ if (iRawlen)
+ MNG_COPY (zKeywords, pRawdata, iRawlen);
+
+ pTemp = (mng_uint8p)zKeywords;
+ pNull = find_null (pTemp);
+
+ while ((bOke) && (pNull < (mng_uint8p)zKeywords + iRawlen))
+ {
+ bOke = CheckKeyword (pData, pTemp);
+ pTemp = pNull + 1;
+ pNull = find_null (pTemp);
+ }
+
+ if (bOke)
+ bOke = CheckKeyword (pData, pTemp);
+
+ MNG_FREEX (pData, zKeywords, iRawlen + 1);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_UNSUPPORTEDNEED);
+ }
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_needp)*ppChunk)->iKeywordssize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_needp)*ppChunk)->zKeywords, iRawlen+1);
+ MNG_COPY (((mng_needp)*ppChunk)->zKeywords, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_NEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_pHYg
+READ_CHUNK (mng_read_phyg)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PHYG, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* it's 9 bytes or empty; no more, no less! */
+ if ((iRawlen != 9) && (iRawlen != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_phygp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+
+ if (iRawlen)
+ {
+ ((mng_phygp)*ppChunk)->iSizex = mng_get_uint32 (pRawdata);
+ ((mng_phygp)*ppChunk)->iSizey = mng_get_uint32 (pRawdata+4);
+ ((mng_phygp)*ppChunk)->iUnit = *(pRawdata+8);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_jhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JHDR, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((pData->eSigtype != mng_it_jng) && (pData->eSigtype != mng_it_mng))
+ MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
+
+ if ((pData->eSigtype == mng_it_jng) && (pData->iChunkseq > 1))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 16) /* length oke ? */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ /* inside a JHDR-IEND block now */
+ pData->bHasJHDR = MNG_TRUE;
+ /* and store interesting fields */
+ pData->iDatawidth = mng_get_uint32 (pRawdata);
+ pData->iDataheight = mng_get_uint32 (pRawdata+4);
+ pData->iJHDRcolortype = *(pRawdata+8);
+ pData->iJHDRimgbitdepth = *(pRawdata+9);
+ pData->iJHDRimgcompression = *(pRawdata+10);
+ pData->iJHDRimginterlace = *(pRawdata+11);
+ pData->iJHDRalphabitdepth = *(pRawdata+12);
+ pData->iJHDRalphacompression = *(pRawdata+13);
+ pData->iJHDRalphafilter = *(pRawdata+14);
+ pData->iJHDRalphainterlace = *(pRawdata+15);
+
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ pData->iPNGmult = 1;
+ pData->iPNGdepth = pData->iJHDRalphabitdepth;
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iJHDRalphabitdepth < 8)
+ pData->iJHDRalphabitdepth = 8;
+#endif
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iJHDRalphabitdepth > 8)
+ {
+ pData->iPNGmult = 2;
+ pData->iJHDRalphabitdepth = 8;
+ }
+#endif
+ /* parameter validity checks */
+ if ((pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAY ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (pData->iJHDRcolortype != MNG_COLORTYPE_JPEGCOLORA) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ if ((pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8 ) &&
+ (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG12 ) &&
+ (pData->iJHDRimgbitdepth != MNG_BITDEPTH_JPEG8AND12) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (pData->iJHDRimgcompression != MNG_COMPRESSION_BASELINEJPEG)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ if ((pData->iJHDRimginterlace != MNG_INTERLACE_SEQUENTIAL ) &&
+ (pData->iJHDRimginterlace != MNG_INTERLACE_PROGRESSIVE) )
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+ if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ {
+ if ((pData->iJHDRalphabitdepth != MNG_BITDEPTH_8 )
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_1 ) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_2 ) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_4 )
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (pData->iJHDRalphabitdepth != MNG_BITDEPTH_16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ((pData->iJHDRalphacompression != MNG_COMPRESSION_DEFLATE ) &&
+ (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG) )
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ if ((pData->iJHDRalphacompression == MNG_COMPRESSION_BASELINEJPEG) &&
+ (pData->iJHDRalphabitdepth != MNG_BITDEPTH_8 ) )
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+#if defined(FILTER192) || defined(FILTER193)
+ if ((pData->iJHDRalphafilter != MNG_FILTER_ADAPTIVE ) &&
+#if defined(FILTER192) && defined(FILTER193)
+ (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING) &&
+ (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER ) )
+#else
+#ifdef FILTER192
+ (pData->iJHDRalphafilter != MNG_FILTER_DIFFERING) )
+#else
+ (pData->iJHDRalphafilter != MNG_FILTER_NOFILTER ) )
+#endif
+#endif
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#else
+ if (pData->iJHDRalphafilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+#endif
+
+ if ((pData->iJHDRalphainterlace != MNG_INTERLACE_NONE ) &&
+ (pData->iJHDRalphainterlace != MNG_INTERLACE_ADAM7) )
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+ }
+ else
+ {
+ if (pData->iJHDRalphabitdepth)
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if (pData->iJHDRalphacompression)
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+ if (pData->iJHDRalphafilter)
+ MNG_ERROR (pData, MNG_INVALIDFILTER);
+
+ if (pData->iJHDRalphainterlace)
+ MNG_ERROR (pData, MNG_INVALIDINTERLACE);
+
+ }
+
+ if (!pData->bHasheader) /* first chunk ? */
+ {
+ pData->bHasheader = MNG_TRUE; /* we've got a header */
+ pData->eImagetype = mng_it_jng; /* then this must be a JNG */
+ pData->iWidth = mng_get_uint32 (pRawdata);
+ pData->iHeight = mng_get_uint32 (pRawdata+4);
+ /* predict alpha-depth ! */
+ if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ pData->iAlphadepth = pData->iJHDRalphabitdepth;
+ else
+ pData->iAlphadepth = 0;
+ /* fits on maximum canvas ? */
+ if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
+ MNG_WARNING (pData, MNG_IMAGETOOLARGE);
+
+ if (pData->fProcessheader) /* inform the app ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ }
+
+ pData->iColortype = 0; /* fake grayscale for other routines */
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_process_display_jhdr (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_jhdrp)*ppChunk)->iWidth = mng_get_uint32 (pRawdata);
+ ((mng_jhdrp)*ppChunk)->iHeight = mng_get_uint32 (pRawdata+4);
+ ((mng_jhdrp)*ppChunk)->iColortype = *(pRawdata+8);
+ ((mng_jhdrp)*ppChunk)->iImagesampledepth = *(pRawdata+9);
+ ((mng_jhdrp)*ppChunk)->iImagecompression = *(pRawdata+10);
+ ((mng_jhdrp)*ppChunk)->iImageinterlace = *(pRawdata+11);
+ ((mng_jhdrp)*ppChunk)->iAlphasampledepth = *(pRawdata+12);
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (*(pRawdata+12) > 8)
+ ((mng_jhdrp)*ppChunk)->iAlphasampledepth = 8;
+#endif
+ ((mng_jhdrp)*ppChunk)->iAlphacompression = *(pRawdata+13);
+ ((mng_jhdrp)*ppChunk)->iAlphafilter = *(pRawdata+14);
+ ((mng_jhdrp)*ppChunk)->iAlphainterlace = *(pRawdata+15);
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#else
+#define read_jhdr 0
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_jdaa)
+{
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ volatile mng_retcode iRetcode;
+
+ iRetcode=MNG_NOERROR;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JDAA, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasJHDR) && (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->bHasJSEP)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (pData->iJHDRalphacompression != MNG_COMPRESSION_BASELINEJPEG)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen == 0) /* can never be empty */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasJDAA = MNG_TRUE; /* got some JDAA now, don't we */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_jdaap)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_jdaap)*ppChunk)->iDatasize = iRawlen;
+
+ if (iRawlen != 0) /* is there any data ? */
+ {
+ MNG_ALLOC (pData, ((mng_jdaap)*ppChunk)->pData, iRawlen);
+ MNG_COPY (((mng_jdaap)*ppChunk)->pData, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#else
+#define read_jdaa 0
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_jdat)
+{
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ volatile mng_retcode iRetcode;
+
+ iRetcode=MNG_NOERROR;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JDAT, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasJHDR) && (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen == 0) /* can never be empty */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasJDAT = MNG_TRUE; /* got some JDAT now, don't we */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_jdatp)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_jdatp)*ppChunk)->iDatasize = iRawlen;
+
+ if (iRawlen != 0) /* is there any data ? */
+ {
+ MNG_ALLOC (pData, ((mng_jdatp)*ppChunk)->pData, iRawlen);
+ MNG_COPY (((mng_jdatp)*ppChunk)->pData, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#else
+#define read_jdat 0
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_jsep)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JSEP, MNG_LC_START);
+#endif
+
+ if (!pData->bHasJHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 0) /* must be empty ! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasJSEP = MNG_TRUE; /* indicate we've had the 8-/12-bit separator */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_JSEP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#else
+#define read_jsep 0
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_dhdr)
+{
+ mng_uint8 iImagetype, iDeltatype;
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DHDR, MNG_LC_START);
+#endif
+
+ if (!pData->bHasMHDR) /* sequence checks */
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check for valid length */
+ if ((iRawlen != 4) && (iRawlen != 12) && (iRawlen != 20))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iImagetype = *(pRawdata+2); /* check fields for validity */
+ iDeltatype = *(pRawdata+3);
+
+ if (iImagetype > MNG_IMAGETYPE_JNG)
+ MNG_ERROR (pData, MNG_INVIMAGETYPE);
+
+ if (iDeltatype > MNG_DELTATYPE_NOCHANGE)
+ MNG_ERROR (pData, MNG_INVDELTATYPE);
+
+ if ((iDeltatype == MNG_DELTATYPE_REPLACE) && (iRawlen > 12))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((iDeltatype == MNG_DELTATYPE_NOCHANGE) && (iRawlen > 4))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ pData->bHasDHDR = MNG_TRUE; /* inside a DHDR-IEND block now */
+ pData->iDeltatype = iDeltatype;
+
+ pData->iImagelevel++; /* one level deeper */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_uint16 iObjectid = mng_get_uint16 (pRawdata);
+ mng_uint32 iBlockwidth = 0;
+ mng_uint32 iBlockheight = 0;
+ mng_uint32 iBlockx = 0;
+ mng_uint32 iBlocky = 0;
+ mng_retcode iRetcode;
+
+ if (iRawlen > 4)
+ {
+ iBlockwidth = mng_get_uint32 (pRawdata+4);
+ iBlockheight = mng_get_uint32 (pRawdata+8);
+ }
+
+ if (iRawlen > 12)
+ {
+ iBlockx = mng_get_uint32 (pRawdata+12);
+ iBlocky = mng_get_uint32 (pRawdata+16);
+ }
+
+ iRetcode = mng_create_ani_dhdr (pData, iObjectid, iImagetype, iDeltatype,
+ iBlockwidth, iBlockheight, iBlockx, iBlocky);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_dhdr (pData, iObjectid, iImagetype, iDeltatype,
+ iBlockwidth, iBlockheight, iBlockx, iBlocky); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_dhdrp)*ppChunk)->iObjectid = mng_get_uint16 (pRawdata);
+ ((mng_dhdrp)*ppChunk)->iImagetype = iImagetype;
+ ((mng_dhdrp)*ppChunk)->iDeltatype = iDeltatype;
+
+ if (iRawlen > 4)
+ {
+ ((mng_dhdrp)*ppChunk)->iBlockwidth = mng_get_uint32 (pRawdata+4);
+ ((mng_dhdrp)*ppChunk)->iBlockheight = mng_get_uint32 (pRawdata+8);
+ }
+
+ if (iRawlen > 12)
+ {
+ ((mng_dhdrp)*ppChunk)->iBlockx = mng_get_uint32 (pRawdata+12);
+ ((mng_dhdrp)*ppChunk)->iBlocky = mng_get_uint32 (pRawdata+16);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_prom)
+{
+ mng_uint8 iColortype;
+ mng_uint8 iSampledepth;
+ mng_uint8 iFilltype;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PROM, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 3) /* gotta be exactly 3 bytes */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iColortype = *pRawdata; /* check fields for validity */
+ iSampledepth = *(pRawdata+1);
+ iFilltype = *(pRawdata+2);
+
+ if ((iColortype != MNG_COLORTYPE_GRAY ) &&
+ (iColortype != MNG_COLORTYPE_RGB ) &&
+ (iColortype != MNG_COLORTYPE_INDEXED) &&
+ (iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (iSampledepth == MNG_BITDEPTH_16 )
+ iSampledepth = MNG_BITDEPTH_8;
+#endif
+
+ if ((iSampledepth != MNG_BITDEPTH_1 ) &&
+ (iSampledepth != MNG_BITDEPTH_2 ) &&
+ (iSampledepth != MNG_BITDEPTH_4 ) &&
+ (iSampledepth != MNG_BITDEPTH_8 )
+#ifndef MNG_NO_16BIT_SUPPORT
+ && (iSampledepth != MNG_BITDEPTH_16)
+#endif
+ )
+ MNG_ERROR (pData, MNG_INVSAMPLEDEPTH);
+
+ if ((iFilltype != MNG_FILLMETHOD_LEFTBITREPLICATE) &&
+ (iFilltype != MNG_FILLMETHOD_ZEROFILL ) )
+ MNG_ERROR (pData, MNG_INVFILLMETHOD);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_create_ani_prom (pData, iSampledepth,
+ iColortype, iFilltype);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_prom (pData, iSampledepth,
+ iColortype, iFilltype); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_promp)*ppChunk)->iColortype = iColortype;
+ ((mng_promp)*ppChunk)->iSampledepth = iSampledepth;
+ ((mng_promp)*ppChunk)->iFilltype = iFilltype;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_ipng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IPNG, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 0) /* gotta be empty */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_create_ani_ipng (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_process_display_ipng (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_pplt)
+{
+ mng_uint8 iDeltatype;
+ mng_uint8p pTemp;
+ mng_uint32 iLen;
+ mng_uint8 iX, iM;
+ mng_uint32 iY;
+ mng_uint32 iMax;
+ mng_rgbpaltab aIndexentries;
+ mng_uint8arr aAlphaentries;
+ mng_uint8arr aUsedentries;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PPLT, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) && (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 1) /* must have at least 1 byte */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iDeltatype = *pRawdata;
+ /* valid ? */
+ if (iDeltatype > MNG_DELTATYPE_DELTARGBA)
+ MNG_ERROR (pData, MNG_INVDELTATYPE);
+ /* must be indexed color ! */
+ if (pData->iColortype != MNG_COLORTYPE_INDEXED)
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ pTemp = pRawdata + 1;
+ iLen = iRawlen - 1;
+ iMax = 0;
+
+ for (iY = 0; iY < 256; iY++) /* reset arrays */
+ {
+ aIndexentries [iY].iRed = 0;
+ aIndexentries [iY].iGreen = 0;
+ aIndexentries [iY].iBlue = 0;
+ aAlphaentries [iY] = 255;
+ aUsedentries [iY] = 0;
+ }
+
+ while (iLen) /* as long as there are entries left ... */
+ {
+ mng_uint32 iDiff;
+
+ if (iLen < 2)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iX = *pTemp; /* get start and end index */
+ iM = *(pTemp+1);
+
+ if (iM < iX)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+
+ if ((mng_uint32)iM >= iMax) /* determine highest used index */
+ iMax = (mng_uint32)iM + 1;
+
+ pTemp += 2;
+ iLen -= 2;
+ iDiff = (iM - iX + 1);
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGB ) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGB ) )
+ iDiff = iDiff * 3;
+ else
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGBA) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGBA ) )
+ iDiff = iDiff * 4;
+
+ if (iLen < iDiff)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ if ((iDeltatype == MNG_DELTATYPE_REPLACERGB ) ||
+ (iDeltatype == MNG_DELTATYPE_DELTARGB ) )
+ {
+ for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
+ {
+ aIndexentries [iY].iRed = *pTemp;
+ aIndexentries [iY].iGreen = *(pTemp+1);
+ aIndexentries [iY].iBlue = *(pTemp+2);
+ aUsedentries [iY] = 1;
+
+ pTemp += 3;
+ iLen -= 3;
+ }
+ }
+ else
+ if ((iDeltatype == MNG_DELTATYPE_REPLACEALPHA) ||
+ (iDeltatype == MNG_DELTATYPE_DELTAALPHA ) )
+ {
+ for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
+ {
+ aAlphaentries [iY] = *pTemp;
+ aUsedentries [iY] = 1;
+
+ pTemp++;
+ iLen--;
+ }
+ }
+ else
+ {
+ for (iY = (mng_uint32)iX; iY <= (mng_uint32)iM; iY++)
+ {
+ aIndexentries [iY].iRed = *pTemp;
+ aIndexentries [iY].iGreen = *(pTemp+1);
+ aIndexentries [iY].iBlue = *(pTemp+2);
+ aAlphaentries [iY] = *(pTemp+3);
+ aUsedentries [iY] = 1;
+
+ pTemp += 4;
+ iLen -= 4;
+ }
+ }
+ }
+
+ switch (pData->iBitdepth) /* check maximum allowed entries for bitdepth */
+ {
+ case MNG_BITDEPTH_1 : {
+ if (iMax > 2)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ case MNG_BITDEPTH_2 : {
+ if (iMax > 4)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ case MNG_BITDEPTH_4 : {
+ if (iMax > 16)
+ MNG_ERROR (pData, MNG_INVALIDINDEX);
+ break;
+ }
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY
+ { /* create animation object */
+ mng_retcode iRetcode = mng_create_ani_pplt (pData, iDeltatype, iMax,
+ aIndexentries, aAlphaentries,
+ aUsedentries);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_pplt (pData, iDeltatype, iMax, aIndexentries,
+ aAlphaentries, aUsedentries); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_ppltp)*ppChunk)->iDeltatype = iDeltatype;
+ ((mng_ppltp)*ppChunk)->iCount = iMax;
+
+ for (iY = 0; iY < 256; iY++)
+ {
+ ((mng_ppltp)*ppChunk)->aEntries [iY].iRed = aIndexentries [iY].iRed;
+ ((mng_ppltp)*ppChunk)->aEntries [iY].iGreen = aIndexentries [iY].iGreen;
+ ((mng_ppltp)*ppChunk)->aEntries [iY].iBlue = aIndexentries [iY].iBlue;
+ ((mng_ppltp)*ppChunk)->aEntries [iY].iAlpha = aAlphaentries [iY];
+ ((mng_ppltp)*ppChunk)->aEntries [iY].bUsed = (mng_bool)(aUsedentries [iY]);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_ijng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IJNG, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen != 0) /* gotta be empty */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode = mng_create_ani_ijng (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_process_display_ijng (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_drop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DROP, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check length */
+ if ((iRawlen < 4) || ((iRawlen % 4) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_dropp)*ppChunk)->iCount = iRawlen / 4;
+
+ if (iRawlen)
+ {
+ mng_uint32 iX;
+ mng_uint8p pTemp = pRawdata;
+ mng_uint32p pEntry;
+
+ MNG_ALLOC (pData, pEntry, iRawlen);
+
+ ((mng_dropp)*ppChunk)->pChunknames = (mng_ptr)pEntry;
+
+ for (iX = 0; iX < iRawlen / 4; iX++)
+ {
+ *pEntry = mng_get_uint32 (pTemp);
+
+ pTemp += 4;
+ pEntry++;
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DROP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+READ_CHUNK (mng_read_dbyk)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DBYK, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 6) /* must be at least 6 long */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_dbykp)*ppChunk)->iChunkname = mng_get_uint32 (pRawdata);
+ ((mng_dbykp)*ppChunk)->iPolarity = *(pRawdata+4);
+ ((mng_dbykp)*ppChunk)->iKeywordssize = iRawlen - 5;
+
+ if (iRawlen > 5)
+ {
+ MNG_ALLOC (pData, ((mng_dbykp)*ppChunk)->zKeywords, iRawlen-4);
+ MNG_COPY (((mng_dbykp)*ppChunk)->zKeywords, pRawdata+5, iRawlen-5);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DBYK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+READ_CHUNK (mng_read_ordr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ORDR, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (!pData->bHasDHDR))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check length */
+ if ((iRawlen < 5) || ((iRawlen % 5) != 0))
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+
+
+ /* TODO: something !!! */
+
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_ordrp)*ppChunk)->iCount = iRawlen / 5;
+
+ if (iRawlen)
+ {
+ mng_uint32 iX;
+ mng_ordr_entryp pEntry;
+ mng_uint8p pTemp = pRawdata;
+
+ MNG_ALLOC (pData, pEntry, iRawlen);
+
+ ((mng_ordrp)*ppChunk)->pEntries = pEntry;
+
+ for (iX = 0; iX < iRawlen / 5; iX++)
+ {
+ pEntry->iChunkname = mng_get_uint32 (pTemp);
+ pEntry->iOrdertype = *(pTemp+4);
+
+ pTemp += 5;
+ pEntry++;
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_ORDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_MAGN
+READ_CHUNK (mng_read_magn)
+{
+ mng_uint16 iFirstid, iLastid;
+ mng_uint8 iMethodX, iMethodY;
+ mng_uint16 iMX, iMY, iML, iMR, iMT, iMB;
+ mng_bool bFaulty;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MAGN, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_SUPPORT_JNG
+ if ((!pData->bHasMHDR) || (pData->bHasIHDR) || (pData->bHasDHDR) || (pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) || (pData->bHasIHDR) || (pData->bHasDHDR))
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* check length */
+ if (iRawlen > 20)
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ /* following is an ugly hack to allow faulty layout caused by previous
+ versions of libmng and MNGeye, which wrote MAGN with a 16-bit
+ MethodX/MethodY (as opposed to the proper 8-bit as defined in the spec!) */
+
+ if ((iRawlen == 6) || (iRawlen == 8) || (iRawlen == 10) || (iRawlen == 12) ||
+ (iRawlen == 14) || (iRawlen == 16) || (iRawlen == 20))
+ bFaulty = MNG_TRUE; /* these lengths are all wrong */
+ else /* length 18 can be right or wrong !!! */
+ if ((iRawlen == 18) && (mng_get_uint16 (pRawdata+4) <= 5) &&
+ (mng_get_uint16 (pRawdata+6) < 256) &&
+ (mng_get_uint16 (pRawdata+8) < 256) &&
+ (mng_get_uint16 (pRawdata+10) < 256) &&
+ (mng_get_uint16 (pRawdata+12) < 256) &&
+ (mng_get_uint16 (pRawdata+14) < 256) &&
+ (mng_get_uint16 (pRawdata+16) < 256))
+ bFaulty = MNG_TRUE; /* this is very likely the wrong layout */
+ else
+ bFaulty = MNG_FALSE; /* all other cases are handled as right */
+
+ if (bFaulty) /* wrong layout ? */
+ {
+ if (iRawlen > 0) /* get the fields */
+ iFirstid = mng_get_uint16 (pRawdata);
+ else
+ iFirstid = 0;
+
+ if (iRawlen > 2)
+ iLastid = mng_get_uint16 (pRawdata+2);
+ else
+ iLastid = iFirstid;
+
+ if (iRawlen > 4)
+ iMethodX = (mng_uint8)(mng_get_uint16 (pRawdata+4));
+ else
+ iMethodX = 0;
+
+ if (iRawlen > 6)
+ iMX = mng_get_uint16 (pRawdata+6);
+ else
+ iMX = 1;
+
+ if (iRawlen > 8)
+ iMY = mng_get_uint16 (pRawdata+8);
+ else
+ iMY = iMX;
+
+ if (iRawlen > 10)
+ iML = mng_get_uint16 (pRawdata+10);
+ else
+ iML = iMX;
+
+ if (iRawlen > 12)
+ iMR = mng_get_uint16 (pRawdata+12);
+ else
+ iMR = iMX;
+
+ if (iRawlen > 14)
+ iMT = mng_get_uint16 (pRawdata+14);
+ else
+ iMT = iMY;
+
+ if (iRawlen > 16)
+ iMB = mng_get_uint16 (pRawdata+16);
+ else
+ iMB = iMY;
+
+ if (iRawlen > 18)
+ iMethodY = (mng_uint8)(mng_get_uint16 (pRawdata+18));
+ else
+ iMethodY = iMethodX;
+ }
+ else /* proper layout !!!! */
+ {
+ if (iRawlen > 0) /* get the fields */
+ iFirstid = mng_get_uint16 (pRawdata);
+ else
+ iFirstid = 0;
+
+ if (iRawlen > 2)
+ iLastid = mng_get_uint16 (pRawdata+2);
+ else
+ iLastid = iFirstid;
+
+ if (iRawlen > 4)
+ iMethodX = *(pRawdata+4);
+ else
+ iMethodX = 0;
+
+ if (iRawlen > 5)
+ iMX = mng_get_uint16 (pRawdata+5);
+ else
+ iMX = 1;
+
+ if (iRawlen > 7)
+ iMY = mng_get_uint16 (pRawdata+7);
+ else
+ iMY = iMX;
+
+ if (iRawlen > 9)
+ iML = mng_get_uint16 (pRawdata+9);
+ else
+ iML = iMX;
+
+ if (iRawlen > 11)
+ iMR = mng_get_uint16 (pRawdata+11);
+ else
+ iMR = iMX;
+
+ if (iRawlen > 13)
+ iMT = mng_get_uint16 (pRawdata+13);
+ else
+ iMT = iMY;
+
+ if (iRawlen > 15)
+ iMB = mng_get_uint16 (pRawdata+15);
+ else
+ iMB = iMY;
+
+ if (iRawlen > 17)
+ iMethodY = *(pRawdata+17);
+ else
+ iMethodY = iMethodX;
+ }
+ /* check field validity */
+ if ((iMethodX > 5) || (iMethodY > 5))
+ MNG_ERROR (pData, MNG_INVALIDMETHOD);
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ mng_retcode iRetcode;
+
+ iRetcode = mng_create_ani_magn (pData, iFirstid, iLastid, iMethodX,
+ iMX, iMY, iML, iMR, iMT, iMB, iMethodY);
+
+/* if (!iRetcode)
+ iRetcode = mng_process_display_magn (pData, iFirstid, iLastid, iMethodX,
+ iMX, iMY, iML, iMR, iMT, iMB, iMethodY); */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_magnp)*ppChunk)->iFirstid = iFirstid;
+ ((mng_magnp)*ppChunk)->iLastid = iLastid;
+ ((mng_magnp)*ppChunk)->iMethodX = iMethodX;
+ ((mng_magnp)*ppChunk)->iMX = iMX;
+ ((mng_magnp)*ppChunk)->iMY = iMY;
+ ((mng_magnp)*ppChunk)->iML = iML;
+ ((mng_magnp)*ppChunk)->iMR = iMR;
+ ((mng_magnp)*ppChunk)->iMT = iMT;
+ ((mng_magnp)*ppChunk)->iMB = iMB;
+ ((mng_magnp)*ppChunk)->iMethodY = iMethodY;
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+READ_CHUNK (mng_read_mpng)
+{
+ mng_uint32 iFramewidth;
+ mng_uint32 iFrameheight;
+ mng_uint16 iTickspersec;
+ mng_uint32 iFramessize;
+ mng_uint32 iCompressedsize;
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ mng_retcode iRetcode;
+ mng_uint16 iNumplays;
+ mng_uint32 iBufsize;
+ mng_uint8p pBuf = 0;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MPNG, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if (!pData->bHasIHDR)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 41) /* length must be at least 41 */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+ iFramewidth = mng_get_int32 (pRawdata);
+ if (iFramewidth == 0) /* frame_width must not be zero */
+ MNG_ERROR (pData, MNG_INVALIDWIDTH);
+
+ iFrameheight = mng_get_int32 (pRawdata+4);
+ if (iFrameheight == 0) /* frame_height must not be zero */
+ MNG_ERROR (pData, MNG_INVALIDHEIGHT);
+
+ iTickspersec = mng_get_uint16 (pRawdata+10);
+ if (iTickspersec == 0) /* delay_den must not be zero */
+ MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
+
+ if (*(pRawdata+12) != 0) /* only deflate compression-method allowed */
+ MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
+
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ iNumplays = mng_get_uint16 (pRawdata+8);
+ iCompressedsize = (mng_uint32)(iRawlen - 13);
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ {
+ iRetcode = mng_inflate_buffer (pData, pRawdata+13, iCompressedsize,
+ &pBuf, &iBufsize, &iFramessize);
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ if (iFramessize % 26)
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+
+ iRetcode = mng_create_mpng_obj (pData, iFramewidth, iFrameheight, iNumplays,
+ iTickspersec, iFramessize, pBuf);
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the fields */
+ ((mng_mpngp)*ppChunk)->iFramewidth = iFramewidth;
+ ((mng_mpngp)*ppChunk)->iFrameheight = iFrameheight;
+ ((mng_mpngp)*ppChunk)->iNumplays = iNumplays;
+ ((mng_mpngp)*ppChunk)->iTickspersec = iTickspersec;
+ ((mng_mpngp)*ppChunk)->iCompressionmethod = *(pRawdata+14);
+
+#ifndef MNG_SUPPORT_DISPLAY
+ iRetcode = mng_inflate_buffer (pData, pRawdata+13, iCompressedsize,
+ &pBuf, &iBufsize, &iFramessize);
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ return iRetcode;
+ }
+
+ if (iFramessize % 26)
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ }
+#endif
+
+ if (iFramessize)
+ {
+ MNG_ALLOCX (pData, ((mng_mpngp)*ppChunk)->pFrames, iFramessize);
+ if (((mng_mpngp)*ppChunk)->pFrames == 0)
+ {
+ MNG_FREEX (pData, pBuf, iBufsize);
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ ((mng_mpngp)*ppChunk)->iFramessize = iFramessize;
+ MNG_COPY (((mng_mpngp)*ppChunk)->pFrames, pBuf, iFramessize);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
+ MNG_FREEX (pData, pBuf, iBufsize);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_MPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifndef MNG_SKIPCHUNK_evNT
+READ_CHUNK (mng_read_evnt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_EVNT, MNG_LC_START);
+#endif
+ /* sequence checks */
+ if ((!pData->bHasMHDR) || (pData->bHasSAVE))
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+
+ if (iRawlen < 2) /* must have at least 1 entry ! */
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
+ {
+ if (iRawlen) /* not empty ? */
+ {
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint8p pNull;
+ mng_uint32 iLen;
+ mng_uint8 iEventtype;
+ mng_uint8 iMasktype;
+ mng_int32 iLeft;
+ mng_int32 iRight;
+ mng_int32 iTop;
+ mng_int32 iBottom;
+ mng_uint16 iObjectid;
+ mng_uint8 iIndex;
+ mng_uint32 iNamesize;
+
+ pTemp = pRawdata;
+ iLen = iRawlen;
+
+ while (iLen) /* anything left ? */
+ {
+ iEventtype = *pTemp; /* eventtype */
+ if (iEventtype > 5)
+ MNG_ERROR (pData, MNG_INVALIDEVENT);
+
+ pTemp++;
+
+ iMasktype = *pTemp; /* masktype */
+ if (iMasktype > 5)
+ MNG_ERROR (pData, MNG_INVALIDMASK);
+
+ pTemp++;
+ iLen -= 2;
+
+ iLeft = 0;
+ iRight = 0;
+ iTop = 0;
+ iBottom = 0;
+ iObjectid = 0;
+ iIndex = 0;
+
+ switch (iMasktype)
+ {
+ case 1 :
+ {
+ if (iLen > 16)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ pTemp += 16;
+ iLen -= 16;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 2 :
+ {
+ if (iLen > 2)
+ {
+ iObjectid = mng_get_uint16 (pTemp);
+ pTemp += 2;
+ iLen -= 2;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 3 :
+ {
+ if (iLen > 3)
+ {
+ iObjectid = mng_get_uint16 (pTemp);
+ iIndex = *(pTemp+2);
+ pTemp += 3;
+ iLen -= 3;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 4 :
+ {
+ if (iLen > 18)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ iObjectid = mng_get_uint16 (pTemp+16);
+ pTemp += 18;
+ iLen -= 18;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 5 :
+ {
+ if (iLen > 19)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ iObjectid = mng_get_uint16 (pTemp+16);
+ iIndex = *(pTemp+18);
+ pTemp += 19;
+ iLen -= 19;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ }
+
+ pNull = find_null (pTemp); /* get the name length */
+
+ if ((pNull - pTemp) > (mng_int32)iLen)
+ {
+ iNamesize = iLen; /* no null found; so end of evNT */
+ iLen = 0;
+ }
+ else
+ {
+ iNamesize = pNull - pTemp; /* should be another entry */
+ iLen = iLen - iNamesize - 1;
+
+ if (!iLen) /* must not end with a null ! */
+ MNG_ERROR (pData, MNG_ENDWITHNULL);
+ }
+
+ iRetcode = mng_create_event (pData, iEventtype, iMasktype, iLeft, iRight,
+ iTop, iBottom, iObjectid, iIndex,
+ iNamesize, (mng_pchar)pTemp);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pTemp = pTemp + iNamesize + 1;
+ }
+ }
+ }
+#endif /* MNG_SUPPORT_DISPLAY && MNG_SUPPORT_DYNAMICMNG */
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (iRawlen) /* not empty ? */
+ {
+ mng_uint32 iX;
+ mng_uint32 iCount = 0;
+ mng_uint8p pTemp;
+ mng_uint8p pNull;
+ mng_uint32 iLen;
+ mng_uint8 iEventtype;
+ mng_uint8 iMasktype;
+ mng_int32 iLeft;
+ mng_int32 iRight;
+ mng_int32 iTop;
+ mng_int32 iBottom;
+ mng_uint16 iObjectid;
+ mng_uint8 iIndex;
+ mng_uint32 iNamesize;
+ mng_evnt_entryp pEntry = MNG_NULL;
+
+ for (iX = 0; iX < 2; iX++) /* do this twice to get the count first ! */
+ {
+ pTemp = pRawdata;
+ iLen = iRawlen;
+
+ if (iX) /* second run ? */
+ {
+ MNG_ALLOC (pData, pEntry, (iCount * sizeof (mng_evnt_entry)));
+
+ ((mng_evntp)*ppChunk)->iCount = iCount;
+ ((mng_evntp)*ppChunk)->pEntries = pEntry;
+ }
+
+ while (iLen) /* anything left ? */
+ {
+ iEventtype = *pTemp; /* eventtype */
+ if (iEventtype > 5)
+ MNG_ERROR (pData, MNG_INVALIDEVENT);
+
+ pTemp++;
+
+ iMasktype = *pTemp; /* masktype */
+ if (iMasktype > 5)
+ MNG_ERROR (pData, MNG_INVALIDMASK);
+
+ pTemp++;
+ iLen -= 2;
+
+ iLeft = 0;
+ iRight = 0;
+ iTop = 0;
+ iBottom = 0;
+ iObjectid = 0;
+ iIndex = 0;
+
+ switch (iMasktype)
+ {
+ case 1 :
+ {
+ if (iLen > 16)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ pTemp += 16;
+ iLen -= 16;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 2 :
+ {
+ if (iLen > 2)
+ {
+ iObjectid = mng_get_uint16 (pTemp);
+ pTemp += 2;
+ iLen -= 2;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 3 :
+ {
+ if (iLen > 3)
+ {
+ iObjectid = mng_get_uint16 (pTemp);
+ iIndex = *(pTemp+2);
+ pTemp += 3;
+ iLen -= 3;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 4 :
+ {
+ if (iLen > 18)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ iObjectid = mng_get_uint16 (pTemp+16);
+ pTemp += 18;
+ iLen -= 18;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ case 5 :
+ {
+ if (iLen > 19)
+ {
+ iLeft = mng_get_int32 (pTemp);
+ iRight = mng_get_int32 (pTemp+4);
+ iTop = mng_get_int32 (pTemp+8);
+ iBottom = mng_get_int32 (pTemp+12);
+ iObjectid = mng_get_uint16 (pTemp+16);
+ iIndex = *(pTemp+18);
+ pTemp += 19;
+ iLen -= 19;
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDLENGTH);
+ break;
+ }
+ }
+
+ pNull = find_null (pTemp); /* get the name length */
+
+ if ((pNull - pTemp) > (mng_int32)iLen)
+ {
+ iNamesize = iLen; /* no null found; so end of evNT */
+ iLen = 0;
+ }
+ else
+ {
+ iNamesize = pNull - pTemp; /* should be another entry */
+ iLen = iLen - iNamesize - 1;
+
+ if (!iLen) /* must not end with a null ! */
+ MNG_ERROR (pData, MNG_ENDWITHNULL);
+ }
+
+ if (!iX)
+ {
+ iCount++;
+ }
+ else
+ {
+ pEntry->iEventtype = iEventtype;
+ pEntry->iMasktype = iMasktype;
+ pEntry->iLeft = iLeft;
+ pEntry->iRight = iRight;
+ pEntry->iTop = iTop;
+ pEntry->iBottom = iBottom;
+ pEntry->iObjectid = iObjectid;
+ pEntry->iIndex = iIndex;
+ pEntry->iSegmentnamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zSegmentname, iNamesize+1);
+ MNG_COPY (pEntry->zSegmentname, pTemp, iNamesize);
+ }
+
+ pEntry++;
+ }
+
+ pTemp = pTemp + iNamesize + 1;
+ }
+ }
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_EVNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_unknown)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_UNKNOWN, MNG_LC_START);
+#endif
+ /* sequence checks */
+#ifdef MNG_INCLUDE_JNG
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
+ (!pData->bHasBASI) && (!pData->bHasDHDR) )
+#endif
+ MNG_ERROR (pData, MNG_SEQUENCEERROR);
+ /* critical chunk ? */
+ if ((((mng_uint32)pData->iChunkname & 0x20000000) == 0)
+#ifdef MNG_SKIPCHUNK_SAVE
+ && (pData->iChunkname != MNG_UINT_SAVE)
+#endif
+#ifdef MNG_SKIPCHUNK_SEEK
+ && (pData->iChunkname != MNG_UINT_SEEK)
+#endif
+#ifdef MNG_SKIPCHUNK_DBYK
+ && (pData->iChunkname != MNG_UINT_DBYK)
+#endif
+#ifdef MNG_SKIPCHUNK_ORDR
+ && (pData->iChunkname != MNG_UINT_ORDR)
+#endif
+ )
+ MNG_ERROR (pData, MNG_UNKNOWNCRITICAL);
+
+ if (pData->fProcessunknown) /* let the app handle it ? */
+ {
+ mng_bool bOke = pData->fProcessunknown ((mng_handle)pData, pData->iChunkname,
+ iRawlen, (mng_ptr)pRawdata);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+#ifdef MNG_STORE_CHUNKS
+ if (pData->bStorechunks)
+ { /* initialize storage */
+ mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* store the length */
+ ((mng_chunk_headerp)*ppChunk)->iChunkname = pData->iChunkname;
+ ((mng_unknown_chunkp)*ppChunk)->iDatasize = iRawlen;
+
+ if (iRawlen == 0) /* any data at all ? */
+ ((mng_unknown_chunkp)*ppChunk)->pData = 0;
+ else
+ { /* then store it */
+ MNG_ALLOC (pData, ((mng_unknown_chunkp)*ppChunk)->pData, iRawlen);
+ MNG_COPY (((mng_unknown_chunkp)*ppChunk)->pData, pRawdata, iRawlen);
+ }
+ }
+#endif /* MNG_STORE_CHUNKS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_UNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+#endif
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_READ_PROCS */
+
+/* ************************************************************************** */
+/* * * */
+/* * chunk write functions * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_ihdr)
+{
+ mng_ihdrp pIHDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IHDR, MNG_LC_START);
+#endif
+
+ pIHDR = (mng_ihdrp)pChunk; /* address the proper chunk */
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 13;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pIHDR->iWidth);
+ mng_put_uint32 (pRawdata+4, pIHDR->iHeight);
+
+ *(pRawdata+8) = pIHDR->iBitdepth;
+ *(pRawdata+9) = pIHDR->iColortype;
+ *(pRawdata+10) = pIHDR->iCompression;
+ *(pRawdata+11) = pIHDR->iFilter;
+ *(pRawdata+12) = pIHDR->iInterlace;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pIHDR->sHeader.iChunkname, iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_plte)
+{
+ mng_pltep pPLTE;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PLTE, MNG_LC_START);
+#endif
+
+ pPLTE = (mng_pltep)pChunk; /* address the proper chunk */
+
+ if (pPLTE->bEmpty) /* write empty chunk ? */
+ iRetcode = write_raw_chunk (pData, pPLTE->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pPLTE->iEntrycount * 3;
+ /* fill the output buffer */
+ pTemp = pRawdata;
+
+ for (iX = 0; iX < pPLTE->iEntrycount; iX++)
+ {
+ *pTemp = pPLTE->aEntries [iX].iRed;
+ *(pTemp+1) = pPLTE->aEntries [iX].iGreen;
+ *(pTemp+2) = pPLTE->aEntries [iX].iBlue;
+
+ pTemp += 3;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pPLTE->sHeader.iChunkname, iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PLTE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_idat)
+{
+ mng_idatp pIDAT;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IDAT, MNG_LC_START);
+#endif
+
+ pIDAT = (mng_idatp)pChunk; /* address the proper chunk */
+
+ if (pIDAT->bEmpty) /* and write it */
+ iRetcode = write_raw_chunk (pData, pIDAT->sHeader.iChunkname, 0, 0);
+ else
+ iRetcode = write_raw_chunk (pData, pIDAT->sHeader.iChunkname,
+ pIDAT->iDatasize, pIDAT->pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IDAT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_iend)
+{
+ mng_iendp pIEND;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IEND, MNG_LC_START);
+#endif
+
+ pIEND = (mng_iendp)pChunk; /* address the proper chunk */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pIEND->sHeader.iChunkname, 0, 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IEND, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_trns)
+{
+ mng_trnsp pTRNS;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TRNS, MNG_LC_START);
+#endif
+
+ pTRNS = (mng_trnsp)pChunk; /* address the proper chunk */
+
+ if (pTRNS->bEmpty) /* write empty chunk ? */
+ iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname, 0, 0);
+ else
+ if (pTRNS->bGlobal) /* write global chunk ? */
+ iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname,
+ pTRNS->iRawlen, (mng_uint8p)pTRNS->aRawdata);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer */
+ iRawlen = 0; /* and default size */
+
+ switch (pTRNS->iType)
+ {
+ case 0: {
+ iRawlen = 2; /* fill the size & output buffer */
+ mng_put_uint16 (pRawdata, pTRNS->iGray);
+
+ break;
+ }
+ case 2: {
+ iRawlen = 6; /* fill the size & output buffer */
+ mng_put_uint16 (pRawdata, pTRNS->iRed);
+ mng_put_uint16 (pRawdata+2, pTRNS->iGreen);
+ mng_put_uint16 (pRawdata+4, pTRNS->iBlue);
+
+ break;
+ }
+ case 3: { /* init output buffer size */
+ iRawlen = pTRNS->iCount;
+
+ pTemp = pRawdata; /* fill the output buffer */
+
+ for (iX = 0; iX < pTRNS->iCount; iX++)
+ {
+ *pTemp = pTRNS->aEntries[iX];
+ pTemp++;
+ }
+
+ break;
+ }
+ }
+ /* write the chunk */
+ iRetcode = write_raw_chunk (pData, pTRNS->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TRNS, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_gama)
+{
+ mng_gamap pGAMA;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_GAMA, MNG_LC_START);
+#endif
+
+ pGAMA = (mng_gamap)pChunk; /* address the proper chunk */
+
+ if (pGAMA->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pGAMA->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 4;
+ /* fill the buffer */
+ mng_put_uint32 (pRawdata, pGAMA->iGamma);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pGAMA->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_GAMA, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+WRITE_CHUNK (mng_write_chrm)
+{
+ mng_chrmp pCHRM;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CHRM, MNG_LC_START);
+#endif
+
+ pCHRM = (mng_chrmp)pChunk; /* address the proper chunk */
+
+ if (pCHRM->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pCHRM->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 32;
+ /* fill the buffer */
+ mng_put_uint32 (pRawdata, pCHRM->iWhitepointx);
+ mng_put_uint32 (pRawdata+4, pCHRM->iWhitepointy);
+ mng_put_uint32 (pRawdata+8, pCHRM->iRedx);
+ mng_put_uint32 (pRawdata+12, pCHRM->iRedy);
+ mng_put_uint32 (pRawdata+16, pCHRM->iGreenx);
+ mng_put_uint32 (pRawdata+20, pCHRM->iGreeny);
+ mng_put_uint32 (pRawdata+24, pCHRM->iBluex);
+ mng_put_uint32 (pRawdata+28, pCHRM->iBluey);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pCHRM->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CHRM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_srgb)
+{
+ mng_srgbp pSRGB;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SRGB, MNG_LC_START);
+#endif
+
+ pSRGB = (mng_srgbp)pChunk; /* address the proper chunk */
+
+ if (pSRGB->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pSRGB->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+ /* fill the buffer */
+ *pRawdata = pSRGB->iRenderingintent;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSRGB->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SRGB, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+WRITE_CHUNK (mng_write_iccp)
+{
+ mng_iccpp pICCP;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint8p pBuf = 0;
+ mng_uint32 iBuflen;
+ mng_uint32 iReallen;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ICCP, MNG_LC_START);
+#endif
+
+ pICCP = (mng_iccpp)pChunk; /* address the proper chunk */
+
+ if (pICCP->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pICCP->sHeader.iChunkname, 0, 0);
+ else
+ { /* compress the profile */
+ iRetcode = deflate_buffer (pData, pICCP->pProfile, pICCP->iProfilesize,
+ &pBuf, &iBuflen, &iReallen);
+
+ if (!iRetcode) /* still oke ? */
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pICCP->iNamesize + 2 + iReallen;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+
+ pTemp = pRawdata; /* fill the buffer */
+
+ if (pICCP->iNamesize)
+ {
+ MNG_COPY (pTemp, pICCP->zName, pICCP->iNamesize);
+ pTemp += pICCP->iNamesize;
+ }
+
+ *pTemp = 0;
+ *(pTemp+1) = pICCP->iCompression;
+ pTemp += 2;
+
+ if (iReallen)
+ MNG_COPY (pTemp, pBuf, iReallen);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pICCP->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ /* drop the temp buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+ }
+
+ MNG_FREEX (pData, pBuf, iBuflen); /* always drop the extra buffer */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ICCP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+WRITE_CHUNK (mng_write_text)
+{
+ mng_textp pTEXT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TEXT, MNG_LC_START);
+#endif
+
+ pTEXT = (mng_textp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pTEXT->iKeywordsize + 1 + pTEXT->iTextsize;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+
+ pTemp = pRawdata; /* fill the buffer */
+
+ if (pTEXT->iKeywordsize)
+ {
+ MNG_COPY (pTemp, pTEXT->zKeyword, pTEXT->iKeywordsize);
+ pTemp += pTEXT->iKeywordsize;
+ }
+
+ *pTemp = 0;
+ pTemp += 1;
+
+ if (pTEXT->iTextsize)
+ MNG_COPY (pTemp, pTEXT->zText, pTEXT->iTextsize);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pTEXT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+ if (iRawlen > pData->iWritebufsize) /* drop the temp buffer ? */
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TEXT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+WRITE_CHUNK (mng_write_ztxt)
+{
+ mng_ztxtp pZTXT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint8p pBuf = 0;
+ mng_uint32 iBuflen;
+ mng_uint32 iReallen;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ZTXT, MNG_LC_START);
+#endif
+
+ pZTXT = (mng_ztxtp)pChunk; /* address the proper chunk */
+ /* compress the text */
+ iRetcode = deflate_buffer (pData, (mng_uint8p)pZTXT->zText, pZTXT->iTextsize,
+ &pBuf, &iBuflen, &iReallen);
+
+ if (!iRetcode) /* all ok ? */
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pZTXT->iKeywordsize + 2 + iReallen;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+
+ pTemp = pRawdata; /* fill the buffer */
+
+ if (pZTXT->iKeywordsize)
+ {
+ MNG_COPY (pTemp, pZTXT->zKeyword, pZTXT->iKeywordsize);
+ pTemp += pZTXT->iKeywordsize;
+ }
+
+ *pTemp = 0; /* terminator zero */
+ pTemp++;
+ *pTemp = 0; /* compression type */
+ pTemp++;
+
+ if (iReallen)
+ MNG_COPY (pTemp, pBuf, iReallen);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pZTXT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ /* drop the temp buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+ }
+
+ MNG_FREEX (pData, pBuf, iBuflen); /* always drop the compression buffer */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ZTXT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+WRITE_CHUNK (mng_write_itxt)
+{
+ mng_itxtp pITXT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint8p pBuf = 0;
+ mng_uint32 iBuflen;
+ mng_uint32 iReallen;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ITXT, MNG_LC_START);
+#endif
+
+ pITXT = (mng_itxtp)pChunk; /* address the proper chunk */
+
+ if (pITXT->iCompressionflag) /* compress the text */
+ iRetcode = deflate_buffer (pData, (mng_uint8p)pITXT->zText, pITXT->iTextsize,
+ &pBuf, &iBuflen, &iReallen);
+ else
+ iRetcode = MNG_NOERROR;
+
+ if (!iRetcode) /* all ok ? */
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pITXT->iKeywordsize + pITXT->iLanguagesize +
+ pITXT->iTranslationsize + 5;
+
+ if (pITXT->iCompressionflag)
+ iRawlen = iRawlen + iReallen;
+ else
+ iRawlen = iRawlen + pITXT->iTextsize;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+
+ pTemp = pRawdata; /* fill the buffer */
+
+ if (pITXT->iKeywordsize)
+ {
+ MNG_COPY (pTemp, pITXT->zKeyword, pITXT->iKeywordsize);
+ pTemp += pITXT->iKeywordsize;
+ }
+
+ *pTemp = 0;
+ pTemp++;
+ *pTemp = pITXT->iCompressionflag;
+ pTemp++;
+ *pTemp = pITXT->iCompressionmethod;
+ pTemp++;
+
+ if (pITXT->iLanguagesize)
+ {
+ MNG_COPY (pTemp, pITXT->zLanguage, pITXT->iLanguagesize);
+ pTemp += pITXT->iLanguagesize;
+ }
+
+ *pTemp = 0;
+ pTemp++;
+
+ if (pITXT->iTranslationsize)
+ {
+ MNG_COPY (pTemp, pITXT->zTranslation, pITXT->iTranslationsize);
+ pTemp += pITXT->iTranslationsize;
+ }
+
+ *pTemp = 0;
+ pTemp++;
+
+ if (pITXT->iCompressionflag)
+ {
+ if (iReallen)
+ MNG_COPY (pTemp, pBuf, iReallen);
+ }
+ else
+ {
+ if (pITXT->iTextsize)
+ MNG_COPY (pTemp, pITXT->zText, pITXT->iTextsize);
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pITXT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ /* drop the temp buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+ }
+
+ MNG_FREEX (pData, pBuf, iBuflen); /* always drop the compression buffer */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+WRITE_CHUNK (mng_write_bkgd)
+{
+ mng_bkgdp pBKGD;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BKGD, MNG_LC_START);
+#endif
+
+ pBKGD = (mng_bkgdp)pChunk; /* address the proper chunk */
+
+ if (pBKGD->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pBKGD->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 0; /* and default size */
+
+ switch (pBKGD->iType)
+ {
+ case 0: { /* gray */
+ iRawlen = 2; /* fill the size & output buffer */
+ mng_put_uint16 (pRawdata, pBKGD->iGray);
+
+ break;
+ }
+ case 2: { /* rgb */
+ iRawlen = 6; /* fill the size & output buffer */
+ mng_put_uint16 (pRawdata, pBKGD->iRed);
+ mng_put_uint16 (pRawdata+2, pBKGD->iGreen);
+ mng_put_uint16 (pRawdata+4, pBKGD->iBlue);
+
+ break;
+ }
+ case 3: { /* indexed */
+ iRawlen = 1; /* fill the size & output buffer */
+ *pRawdata = pBKGD->iIndex;
+
+ break;
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pBKGD->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BKGD, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+WRITE_CHUNK (mng_write_phys)
+{
+ mng_physp pPHYS;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PHYS, MNG_LC_START);
+#endif
+
+ pPHYS = (mng_physp)pChunk; /* address the proper chunk */
+
+ if (pPHYS->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pPHYS->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 9;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pPHYS->iSizex);
+ mng_put_uint32 (pRawdata+4, pPHYS->iSizey);
+
+ *(pRawdata+8) = pPHYS->iUnit;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pPHYS->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PHYS, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+WRITE_CHUNK (mng_write_sbit)
+{
+ mng_sbitp pSBIT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SBIT, MNG_LC_START);
+#endif
+
+ pSBIT = (mng_sbitp)pChunk; /* address the proper chunk */
+
+ if (pSBIT->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pSBIT->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 0; /* and default size */
+
+ switch (pSBIT->iType)
+ {
+ case 0: { /* gray */
+ iRawlen = 1; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+
+ break;
+ }
+ case 2: { /* rgb */
+ iRawlen = 3; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+ *(pRawdata+2) = pSBIT->aBits[2];
+
+ break;
+ }
+ case 3: { /* indexed */
+ iRawlen = 3; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *pRawdata = pSBIT->aBits[1];
+ *pRawdata = pSBIT->aBits[2];
+
+ break;
+ }
+ case 4: { /* gray + alpha */
+ iRawlen = 2; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+
+ break;
+ }
+ case 6: { /* rgb + alpha */
+ iRawlen = 4; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+ *(pRawdata+2) = pSBIT->aBits[2];
+ *(pRawdata+3) = pSBIT->aBits[3];
+
+ break;
+ }
+ case 10: { /* jpeg gray */
+ iRawlen = 1; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+
+ break;
+ }
+ case 12: { /* jpeg rgb */
+ iRawlen = 3; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+ *(pRawdata+2) = pSBIT->aBits[2];
+
+ break;
+ }
+ case 14: { /* jpeg gray + alpha */
+ iRawlen = 2; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+
+ break;
+ }
+ case 16: { /* jpeg rgb + alpha */
+ iRawlen = 4; /* fill the size & output buffer */
+ *pRawdata = pSBIT->aBits[0];
+ *(pRawdata+1) = pSBIT->aBits[1];
+ *(pRawdata+2) = pSBIT->aBits[2];
+ *(pRawdata+3) = pSBIT->aBits[3];
+
+ break;
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSBIT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SBIT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+WRITE_CHUNK (mng_write_splt)
+{
+ mng_spltp pSPLT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint32 iEntrieslen;
+ mng_uint8p pTemp;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SPLT, MNG_LC_START);
+#endif
+
+ pSPLT = (mng_spltp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iEntrieslen = ((pSPLT->iSampledepth >> 3) * 4 + 2) * pSPLT->iEntrycount;
+ iRawlen = pSPLT->iNamesize + 2 + iEntrieslen;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+
+ pTemp = pRawdata; /* fill the buffer */
+
+ if (pSPLT->iNamesize)
+ {
+ MNG_COPY (pTemp, pSPLT->zName, pSPLT->iNamesize);
+ pTemp += pSPLT->iNamesize;
+ }
+
+ *pTemp = 0;
+ *(pTemp+1) = pSPLT->iSampledepth;
+ pTemp += 2;
+
+ if (pSPLT->iEntrycount)
+ MNG_COPY (pTemp, pSPLT->pEntries, iEntrieslen);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSPLT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+ if (iRawlen > pData->iWritebufsize) /* drop the temp buffer ? */
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SPLT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+WRITE_CHUNK (mng_write_hist)
+{
+ mng_histp pHIST;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_HIST, MNG_LC_START);
+#endif
+
+ pHIST = (mng_histp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pHIST->iEntrycount << 1;
+
+ pTemp = pRawdata; /* fill the output buffer */
+
+ for (iX = 0; iX < pHIST->iEntrycount; iX++)
+ {
+ mng_put_uint16 (pTemp, pHIST->aEntries [iX]);
+ pTemp += 2;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pHIST->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_HIST, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+WRITE_CHUNK (mng_write_time)
+{
+ mng_timep pTIME;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TIME, MNG_LC_START);
+#endif
+
+ pTIME = (mng_timep)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 7;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pTIME->iYear);
+
+ *(pRawdata+2) = pTIME->iMonth;
+ *(pRawdata+3) = pTIME->iDay;
+ *(pRawdata+4) = pTIME->iHour;
+ *(pRawdata+5) = pTIME->iMinute;
+ *(pRawdata+6) = pTIME->iSecond;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pTIME->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TIME, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_mhdr)
+{
+ mng_mhdrp pMHDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MHDR, MNG_LC_START);
+#endif
+
+ pMHDR = (mng_mhdrp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 28;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pMHDR->iWidth);
+ mng_put_uint32 (pRawdata+4, pMHDR->iHeight);
+ mng_put_uint32 (pRawdata+8, pMHDR->iTicks);
+ mng_put_uint32 (pRawdata+12, pMHDR->iLayercount);
+ mng_put_uint32 (pRawdata+16, pMHDR->iFramecount);
+ mng_put_uint32 (pRawdata+20, pMHDR->iPlaytime);
+ mng_put_uint32 (pRawdata+24, pMHDR->iSimplicity);
+
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pMHDR->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_mend)
+{
+ mng_mendp pMEND;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MEND, MNG_LC_START);
+#endif
+
+ pMEND = (mng_mendp)pChunk; /* address the proper chunk */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pMEND->sHeader.iChunkname, 0, 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MEND, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_loop)
+{
+ mng_loopp pLOOP;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ mng_uint8p pTemp1;
+ mng_uint32p pTemp2;
+ mng_uint32 iX;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_LOOP, MNG_LC_START);
+#endif
+
+ pLOOP = (mng_loopp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 5;
+ /* fill the output buffer */
+ *pRawdata = pLOOP->iLevel;
+ mng_put_uint32 (pRawdata+1, pLOOP->iRepeat);
+
+ if (pLOOP->iTermination)
+ {
+ iRawlen++;
+ *(pRawdata+5) = pLOOP->iTermination;
+
+ if ((pLOOP->iCount) ||
+ (pLOOP->iItermin != 1) || (pLOOP->iItermax != 0x7FFFFFFFL))
+ {
+ iRawlen += 8;
+
+ mng_put_uint32 (pRawdata+6, pLOOP->iItermin);
+ mng_put_uint32 (pRawdata+10, pLOOP->iItermax);
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (pLOOP->iCount)
+ {
+ iRawlen += pLOOP->iCount * 4;
+
+ pTemp1 = pRawdata+14;
+ pTemp2 = pLOOP->pSignals;
+
+ for (iX = 0; iX < pLOOP->iCount; iX++)
+ {
+ mng_put_uint32 (pTemp1, *pTemp2);
+
+ pTemp1 += 4;
+ pTemp2++;
+ }
+ }
+#endif
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pLOOP->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_LOOP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_endl)
+{
+ mng_endlp pENDL;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ENDL, MNG_LC_START);
+#endif
+
+ pENDL = (mng_endlp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+
+ *pRawdata = pENDL->iLevel; /* fill the output buffer */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pENDL->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ENDL, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_defi)
+{
+ mng_defip pDEFI;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DEFI, MNG_LC_START);
+#endif
+
+ pDEFI = (mng_defip)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 2;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pDEFI->iObjectid);
+
+ if ((pDEFI->iDonotshow) || (pDEFI->iConcrete) || (pDEFI->bHasloca) || (pDEFI->bHasclip))
+ {
+ iRawlen++;
+ *(pRawdata+2) = pDEFI->iDonotshow;
+
+ if ((pDEFI->iConcrete) || (pDEFI->bHasloca) || (pDEFI->bHasclip))
+ {
+ iRawlen++;
+ *(pRawdata+3) = pDEFI->iConcrete;
+
+ if ((pDEFI->bHasloca) || (pDEFI->bHasclip))
+ {
+ iRawlen += 8;
+
+ mng_put_uint32 (pRawdata+4, pDEFI->iXlocation);
+ mng_put_uint32 (pRawdata+8, pDEFI->iYlocation);
+
+ if (pDEFI->bHasclip)
+ {
+ iRawlen += 16;
+
+ mng_put_uint32 (pRawdata+12, pDEFI->iLeftcb);
+ mng_put_uint32 (pRawdata+16, pDEFI->iRightcb);
+ mng_put_uint32 (pRawdata+20, pDEFI->iTopcb);
+ mng_put_uint32 (pRawdata+24, pDEFI->iBottomcb);
+ }
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pDEFI->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DEFI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_basi)
+{
+ mng_basip pBASI;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_bool bOpaque;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BASI, MNG_LC_START);
+#endif
+
+ pBASI = (mng_basip)pChunk; /* address the proper chunk */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBASI->iBitdepth <= 8) /* determine opacity alpha-field */
+#endif
+ bOpaque = (mng_bool)(pBASI->iAlpha == 0xFF);
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ bOpaque = (mng_bool)(pBASI->iAlpha == 0xFFFF);
+#endif
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 13;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pBASI->iWidth);
+ mng_put_uint32 (pRawdata+4, pBASI->iHeight);
+
+ *(pRawdata+8) = pBASI->iBitdepth;
+ *(pRawdata+9) = pBASI->iColortype;
+ *(pRawdata+10) = pBASI->iCompression;
+ *(pRawdata+11) = pBASI->iFilter;
+ *(pRawdata+12) = pBASI->iInterlace;
+
+ if ((pBASI->iRed) || (pBASI->iGreen) || (pBASI->iBlue) ||
+ (!bOpaque) || (pBASI->iViewable))
+ {
+ iRawlen += 6;
+ mng_put_uint16 (pRawdata+13, pBASI->iRed);
+ mng_put_uint16 (pRawdata+15, pBASI->iGreen);
+ mng_put_uint16 (pRawdata+17, pBASI->iBlue);
+
+ if ((!bOpaque) || (pBASI->iViewable))
+ {
+ iRawlen += 2;
+ mng_put_uint16 (pRawdata+19, pBASI->iAlpha);
+
+ if (pBASI->iViewable)
+ {
+ iRawlen++;
+ *(pRawdata+21) = pBASI->iViewable;
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pBASI->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BASI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_clon)
+{
+ mng_clonp pCLON;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CLON, MNG_LC_START);
+#endif
+
+ pCLON = (mng_clonp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 4;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pCLON->iSourceid);
+ mng_put_uint16 (pRawdata+2, pCLON->iCloneid);
+
+ if ((pCLON->iClonetype) || (pCLON->iDonotshow) || (pCLON->iConcrete) || (pCLON->bHasloca))
+ {
+ iRawlen++;
+ *(pRawdata+4) = pCLON->iClonetype;
+
+ if ((pCLON->iDonotshow) || (pCLON->iConcrete) || (pCLON->bHasloca))
+ {
+ iRawlen++;
+ *(pRawdata+5) = pCLON->iDonotshow;
+
+ if ((pCLON->iConcrete) || (pCLON->bHasloca))
+ {
+ iRawlen++;
+ *(pRawdata+6) = pCLON->iConcrete;
+
+ if (pCLON->bHasloca)
+ {
+ iRawlen += 9;
+ *(pRawdata+7) = pCLON->iLocationtype;
+ mng_put_int32 (pRawdata+8, pCLON->iLocationx);
+ mng_put_int32 (pRawdata+12, pCLON->iLocationy);
+ }
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pCLON->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CLON, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+WRITE_CHUNK (mng_write_past)
+{
+ mng_pastp pPAST;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_past_sourcep pSource;
+ mng_uint32 iX;
+ mng_uint8p pTemp;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PAST, MNG_LC_START);
+#endif
+
+ pPAST = (mng_pastp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 11 + (30 * pPAST->iCount);
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pPAST->iDestid);
+
+ *(pRawdata+2) = pPAST->iTargettype;
+
+ mng_put_int32 (pRawdata+3, pPAST->iTargetx);
+ mng_put_int32 (pRawdata+7, pPAST->iTargety);
+
+ pTemp = pRawdata+11;
+ pSource = pPAST->pSources;
+
+ for (iX = 0; iX < pPAST->iCount; iX++)
+ {
+ mng_put_uint16 (pTemp, pSource->iSourceid);
+
+ *(pTemp+2) = pSource->iComposition;
+ *(pTemp+3) = pSource->iOrientation;
+ *(pTemp+4) = pSource->iOffsettype;
+
+ mng_put_int32 (pTemp+5, pSource->iOffsetx);
+ mng_put_int32 (pTemp+9, pSource->iOffsety);
+
+ *(pTemp+13) = pSource->iBoundarytype;
+
+ mng_put_int32 (pTemp+14, pSource->iBoundaryl);
+ mng_put_int32 (pTemp+18, pSource->iBoundaryr);
+ mng_put_int32 (pTemp+22, pSource->iBoundaryt);
+ mng_put_int32 (pTemp+26, pSource->iBoundaryb);
+
+ pSource++;
+ pTemp += 30;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pPAST->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ /* free temporary buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_FREEX (pData, pRawdata, iRawlen);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PAST, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_disc)
+{
+ mng_discp pDISC;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint32 iX;
+ mng_uint8p pTemp1;
+ mng_uint16p pTemp2;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DISC, MNG_LC_START);
+#endif
+
+ pDISC = (mng_discp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pDISC->iCount << 1;
+
+ pTemp1 = pRawdata; /* fill the output buffer */
+ pTemp2 = pDISC->pObjectids;
+
+ for (iX = 0; iX < pDISC->iCount; iX++)
+ {
+ mng_put_uint16 (pTemp1, *pTemp2);
+
+ pTemp2++;
+ pTemp1 += 2;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pDISC->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DISC, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_back)
+{
+ mng_backp pBACK;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BACK, MNG_LC_START);
+#endif
+
+ pBACK = (mng_backp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 6;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pBACK->iRed);
+ mng_put_uint16 (pRawdata+2, pBACK->iGreen);
+ mng_put_uint16 (pRawdata+4, pBACK->iBlue);
+
+ if ((pBACK->iMandatory) || (pBACK->iImageid) || (pBACK->iTile))
+ {
+ iRawlen++;
+ *(pRawdata+6) = pBACK->iMandatory;
+
+ if ((pBACK->iImageid) || (pBACK->iTile))
+ {
+ iRawlen += 2;
+ mng_put_uint16 (pRawdata+7, pBACK->iImageid);
+
+ if (pBACK->iTile)
+ {
+ iRawlen++;
+ *(pRawdata+9) = pBACK->iTile;
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pBACK->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_BACK, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_fram)
+{
+ mng_framp pFRAM;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_uint32p pTemp2;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_FRAM, MNG_LC_START);
+#endif
+
+ pFRAM = (mng_framp)pChunk; /* address the proper chunk */
+
+ if (pFRAM->bEmpty) /* empty ? */
+ iRetcode = write_raw_chunk (pData, pFRAM->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+ /* fill the output buffer */
+ *pRawdata = pFRAM->iMode;
+
+ if ((pFRAM->iNamesize ) ||
+ (pFRAM->iChangedelay ) || (pFRAM->iChangetimeout) ||
+ (pFRAM->iChangeclipping) || (pFRAM->iChangesyncid ) )
+ {
+ if (pFRAM->iNamesize)
+ MNG_COPY (pRawdata+1, pFRAM->zName, pFRAM->iNamesize);
+
+ iRawlen += pFRAM->iNamesize;
+ pTemp = pRawdata + pFRAM->iNamesize + 1;
+
+ if ((pFRAM->iChangedelay ) || (pFRAM->iChangetimeout) ||
+ (pFRAM->iChangeclipping) || (pFRAM->iChangesyncid ) )
+ {
+ *pTemp = 0;
+ *(pTemp+1) = pFRAM->iChangedelay;
+ *(pTemp+2) = pFRAM->iChangetimeout;
+ *(pTemp+3) = pFRAM->iChangeclipping;
+ *(pTemp+4) = pFRAM->iChangesyncid;
+
+ iRawlen += 5;
+ pTemp += 5;
+
+ if (pFRAM->iChangedelay)
+ {
+ mng_put_uint32 (pTemp, pFRAM->iDelay);
+ iRawlen += 4;
+ pTemp += 4;
+ }
+
+ if (pFRAM->iChangetimeout)
+ {
+ mng_put_uint32 (pTemp, pFRAM->iTimeout);
+ iRawlen += 4;
+ pTemp += 4;
+ }
+
+ if (pFRAM->iChangeclipping)
+ {
+ *pTemp = pFRAM->iBoundarytype;
+
+ mng_put_uint32 (pTemp+1, pFRAM->iBoundaryl);
+ mng_put_uint32 (pTemp+5, pFRAM->iBoundaryr);
+ mng_put_uint32 (pTemp+9, pFRAM->iBoundaryt);
+ mng_put_uint32 (pTemp+13, pFRAM->iBoundaryb);
+
+ iRawlen += 17;
+ pTemp += 17;
+ }
+
+ if (pFRAM->iChangesyncid)
+ {
+ iRawlen += pFRAM->iCount * 4;
+ pTemp2 = pFRAM->pSyncids;
+
+ for (iX = 0; iX < pFRAM->iCount; iX++)
+ {
+ mng_put_uint32 (pTemp, *pTemp2);
+
+ pTemp2++;
+ pTemp += 4;
+ }
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pFRAM->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_FRAM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_move)
+{
+ mng_movep pMOVE;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MOVE, MNG_LC_START);
+#endif
+
+ pMOVE = (mng_movep)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 13;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pMOVE->iFirstid);
+ mng_put_uint16 (pRawdata+2, pMOVE->iLastid);
+
+ *(pRawdata+4) = pMOVE->iMovetype;
+
+ mng_put_int32 (pRawdata+5, pMOVE->iMovex);
+ mng_put_int32 (pRawdata+9, pMOVE->iMovey);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pMOVE->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MOVE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_clip)
+{
+ mng_clipp pCLIP;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CLIP, MNG_LC_START);
+#endif
+
+ pCLIP = (mng_clipp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 21;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pCLIP->iFirstid);
+ mng_put_uint16 (pRawdata+2, pCLIP->iLastid);
+
+ *(pRawdata+4) = pCLIP->iCliptype;
+
+ mng_put_int32 (pRawdata+5, pCLIP->iClipl);
+ mng_put_int32 (pRawdata+9, pCLIP->iClipr);
+ mng_put_int32 (pRawdata+13, pCLIP->iClipt);
+ mng_put_int32 (pRawdata+17, pCLIP->iClipb);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pCLIP->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_CLIP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_show)
+{
+ mng_showp pSHOW;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SHOW, MNG_LC_START);
+#endif
+
+ pSHOW = (mng_showp)pChunk; /* address the proper chunk */
+
+ if (pSHOW->bEmpty) /* empty ? */
+ iRetcode = write_raw_chunk (pData, pSHOW->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 2;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pSHOW->iFirstid);
+
+ if ((pSHOW->iLastid != pSHOW->iFirstid) || (pSHOW->iMode))
+ {
+ iRawlen += 2;
+ mng_put_uint16 (pRawdata+2, pSHOW->iLastid);
+
+ if (pSHOW->iMode)
+ {
+ iRawlen++;
+ *(pRawdata+4) = pSHOW->iMode;
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSHOW->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SHOW, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_term)
+{
+ mng_termp pTERM;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TERM, MNG_LC_START);
+#endif
+
+ pTERM = (mng_termp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+
+ *pRawdata = pTERM->iTermaction; /* fill the output buffer */
+
+ if (pTERM->iTermaction == 3)
+ {
+ iRawlen = 10;
+ *(pRawdata+1) = pTERM->iIteraction;
+
+ mng_put_uint32 (pRawdata+2, pTERM->iDelay);
+ mng_put_uint32 (pRawdata+6, pTERM->iItermax);
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pTERM->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_TERM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+WRITE_CHUNK (mng_write_save)
+{
+ mng_savep pSAVE;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_save_entryp pEntry;
+ mng_uint32 iEntrysize;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SAVE, MNG_LC_START);
+#endif
+
+ pSAVE = (mng_savep)pChunk; /* address the proper chunk */
+
+ if (pSAVE->bEmpty) /* empty ? */
+ iRetcode = write_raw_chunk (pData, pSAVE->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+
+ *pRawdata = pSAVE->iOffsettype; /* fill the output buffer */
+
+ if (pSAVE->iOffsettype == 16)
+ iEntrysize = 25;
+ else
+ iEntrysize = 17;
+
+ pTemp = pRawdata+1;
+ pEntry = pSAVE->pEntries;
+
+ for (iX = 0; iX < pSAVE->iCount; iX++)
+ {
+ if (iX) /* put separator null-byte, except the first */
+ {
+ *pTemp = 0;
+ pTemp++;
+ iRawlen++;
+ }
+
+ iRawlen += iEntrysize + pEntry->iNamesize;
+ *pTemp = pEntry->iEntrytype;
+
+ if (pSAVE->iOffsettype == 16)
+ {
+ mng_put_uint32 (pTemp+1, pEntry->iOffset[0]);
+ mng_put_uint32 (pTemp+5, pEntry->iOffset[1]);
+ mng_put_uint32 (pTemp+9, pEntry->iStarttime[0]);
+ mng_put_uint32 (pTemp+13, pEntry->iStarttime[1]);
+ mng_put_uint32 (pTemp+17, pEntry->iLayernr);
+ mng_put_uint32 (pTemp+21, pEntry->iFramenr);
+
+ pTemp += 25;
+ }
+ else
+ {
+ mng_put_uint32 (pTemp+1, pEntry->iOffset[1]);
+ mng_put_uint32 (pTemp+5, pEntry->iStarttime[1]);
+ mng_put_uint32 (pTemp+9, pEntry->iLayernr);
+ mng_put_uint32 (pTemp+13, pEntry->iFramenr);
+
+ pTemp += 17;
+ }
+
+ if (pEntry->iNamesize)
+ {
+ MNG_COPY (pTemp, pEntry->zName, pEntry->iNamesize);
+ pTemp += pEntry->iNamesize;
+ }
+
+ pEntry++;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSAVE->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SAVE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+WRITE_CHUNK (mng_write_seek)
+{
+ mng_seekp pSEEK;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SEEK, MNG_LC_START);
+#endif
+
+ pSEEK = (mng_seekp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pSEEK->iNamesize;
+
+ if (iRawlen) /* fill the output buffer */
+ MNG_COPY (pRawdata, pSEEK->zName, iRawlen);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pSEEK->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_SEEK, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+WRITE_CHUNK (mng_write_expi)
+{
+ mng_expip pEXPI;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_EXPI, MNG_LC_START);
+#endif
+
+ pEXPI = (mng_expip)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 2 + pEXPI->iNamesize;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pEXPI->iSnapshotid);
+
+ if (pEXPI->iNamesize)
+ MNG_COPY (pRawdata+2, pEXPI->zName, pEXPI->iNamesize);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pEXPI->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_EXPI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+WRITE_CHUNK (mng_write_fpri)
+{
+ mng_fprip pFPRI;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_FPRI, MNG_LC_START);
+#endif
+
+ pFPRI = (mng_fprip)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 2;
+
+ *pRawdata = pFPRI->iDeltatype; /* fill the output buffer */
+ *(pRawdata+1) = pFPRI->iPriority;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pFPRI->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_FPRI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+WRITE_CHUNK (mng_write_need)
+{
+ mng_needp pNEED;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_NEED, MNG_LC_START);
+#endif
+
+ pNEED = (mng_needp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pNEED->iKeywordssize;
+ /* fill the output buffer */
+ if (pNEED->iKeywordssize)
+ MNG_COPY (pRawdata, pNEED->zKeywords, pNEED->iKeywordssize);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pNEED->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_NEED, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+WRITE_CHUNK (mng_write_phyg)
+{
+ mng_phygp pPHYG;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PHYG, MNG_LC_START);
+#endif
+
+ pPHYG = (mng_phygp)pChunk; /* address the proper chunk */
+
+ if (pPHYG->bEmpty) /* write empty ? */
+ iRetcode = write_raw_chunk (pData, pPHYG->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 9;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pPHYG->iSizex);
+ mng_put_uint32 (pRawdata+4, pPHYG->iSizey);
+
+ *(pRawdata+8) = pPHYG->iUnit;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pPHYG->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PHYG, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+/* B004 */
+#ifdef MNG_INCLUDE_JNG
+/* B004 */
+WRITE_CHUNK (mng_write_jhdr)
+{
+ mng_jhdrp pJHDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JHDR, MNG_LC_START);
+#endif
+
+ pJHDR = (mng_jhdrp)pChunk; /* address the proper chunk */
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 16;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pJHDR->iWidth);
+ mng_put_uint32 (pRawdata+4, pJHDR->iHeight);
+
+ *(pRawdata+8) = pJHDR->iColortype;
+ *(pRawdata+9) = pJHDR->iImagesampledepth;
+ *(pRawdata+10) = pJHDR->iImagecompression;
+ *(pRawdata+11) = pJHDR->iImageinterlace;
+ *(pRawdata+12) = pJHDR->iAlphasampledepth;
+ *(pRawdata+13) = pJHDR->iAlphacompression;
+ *(pRawdata+14) = pJHDR->iAlphafilter;
+ *(pRawdata+15) = pJHDR->iAlphainterlace;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pJHDR->sHeader.iChunkname, iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#else
+#define write_jhdr 0
+/* B004 */
+#endif /* MNG_INCLUDE_JNG */
+/* B004 */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+WRITE_CHUNK (mng_write_jdaa)
+{
+ mng_jdatp pJDAA;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JDAA, MNG_LC_START);
+#endif
+
+ pJDAA = (mng_jdaap)pChunk; /* address the proper chunk */
+
+ if (pJDAA->bEmpty) /* and write it */
+ iRetcode = write_raw_chunk (pData, pJDAA->sHeader.iChunkname, 0, 0);
+ else
+ iRetcode = write_raw_chunk (pData, pJDAA->sHeader.iChunkname,
+ pJDAA->iDatasize, pJDAA->pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JDAA, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#else
+#define write_jdaa 0
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+/* B004 */
+#ifdef MNG_INCLUDE_JNG
+/* B004 */
+WRITE_CHUNK (mng_write_jdat)
+{
+ mng_jdatp pJDAT;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JDAT, MNG_LC_START);
+#endif
+
+ pJDAT = (mng_jdatp)pChunk; /* address the proper chunk */
+
+ if (pJDAT->bEmpty) /* and write it */
+ iRetcode = write_raw_chunk (pData, pJDAT->sHeader.iChunkname, 0, 0);
+ else
+ iRetcode = write_raw_chunk (pData, pJDAT->sHeader.iChunkname,
+ pJDAT->iDatasize, pJDAT->pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JDAT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#else
+#define write_jdat 0
+/* B004 */
+#endif /* MNG_INCLUDE_JNG */
+/* B004 */
+
+/* ************************************************************************** */
+
+/* B004 */
+#ifdef MNG_INCLUDE_JNG
+/* B004 */
+WRITE_CHUNK (mng_write_jsep)
+{
+ mng_jsepp pJSEP;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JSEP, MNG_LC_START);
+#endif
+
+ pJSEP = (mng_jsepp)pChunk; /* address the proper chunk */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pJSEP->sHeader.iChunkname, 0, 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_JSEP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#else
+#define write_jsep 0
+/* B004 */
+#endif /* MNG_INCLUDE_JNG */
+/* B004 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_dhdr)
+{
+ mng_dhdrp pDHDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DHDR, MNG_LC_START);
+#endif
+
+ pDHDR = (mng_dhdrp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 4;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pDHDR->iObjectid);
+
+ *(pRawdata+2) = pDHDR->iImagetype;
+ *(pRawdata+3) = pDHDR->iDeltatype;
+
+ if (pDHDR->iDeltatype != 7)
+ {
+ iRawlen += 8;
+ mng_put_uint32 (pRawdata+4, pDHDR->iBlockwidth);
+ mng_put_uint32 (pRawdata+8, pDHDR->iBlockheight);
+
+ if (pDHDR->iDeltatype != 0)
+ {
+ iRawlen += 8;
+ mng_put_uint32 (pRawdata+12, pDHDR->iBlockx);
+ mng_put_uint32 (pRawdata+16, pDHDR->iBlocky);
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pDHDR->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_prom)
+{
+ mng_promp pPROM;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PROM, MNG_LC_START);
+#endif
+
+ pPROM = (mng_promp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 3;
+
+ *pRawdata = pPROM->iColortype; /* fill the output buffer */
+ *(pRawdata+1) = pPROM->iSampledepth;
+ *(pRawdata+2) = pPROM->iFilltype;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pPROM->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PROM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_ipng)
+{
+ mng_ipngp pIPNG;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IPNG, MNG_LC_START);
+#endif
+
+ pIPNG = (mng_ipngp)pChunk; /* address the proper chunk */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pIPNG->sHeader.iChunkname, 0, 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IPNG, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_pplt)
+{
+ mng_ppltp pPPLT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_pplt_entryp pEntry;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+ mng_bool bHasgroup;
+ mng_uint8p pLastid = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PPLT, MNG_LC_START);
+#endif
+
+ pPPLT = (mng_ppltp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 1;
+
+ *pRawdata = pPPLT->iDeltatype; /* fill the output buffer */
+
+ pTemp = pRawdata+1;
+ bHasgroup = MNG_FALSE;
+
+ for (iX = 0; iX < pPPLT->iCount; iX++)
+ {
+ pEntry = &pPPLT->aEntries[iX];
+
+ if (pEntry->bUsed) /* valid entry ? */
+ {
+ if (!bHasgroup) /* start a new group ? */
+ {
+ bHasgroup = MNG_TRUE;
+ pLastid = pTemp+1;
+
+ *pTemp = (mng_uint8)iX;
+ *(pTemp+1) = 0;
+
+ pTemp += 2;
+ iRawlen += 2;
+ }
+
+ switch (pPPLT->iDeltatype) /* add group-entry depending on type */
+ {
+ case 0: ;
+ case 1: {
+ *pTemp = pEntry->iRed;
+ *(pTemp+1) = pEntry->iGreen;
+ *(pTemp+2) = pEntry->iBlue;
+
+ pTemp += 3;
+ iRawlen += 3;
+
+ break;
+ }
+
+ case 2: ;
+ case 3: {
+ *pTemp = pEntry->iAlpha;
+
+ pTemp++;
+ iRawlen++;
+
+ break;
+ }
+
+ case 4: ;
+ case 5: {
+ *pTemp = pEntry->iRed;
+ *(pTemp+1) = pEntry->iGreen;
+ *(pTemp+2) = pEntry->iBlue;
+ *(pTemp+3) = pEntry->iAlpha;
+
+ pTemp += 4;
+ iRawlen += 4;
+
+ break;
+ }
+
+ }
+ }
+ else
+ {
+ if (bHasgroup) /* finish off a group ? */
+ *pLastid = (mng_uint8)(iX-1);
+
+ bHasgroup = MNG_FALSE;
+ }
+ }
+
+ if (bHasgroup) /* last group unfinished ? */
+ *pLastid = (mng_uint8)(pPPLT->iCount-1);
+ /* write the output buffer */
+ iRetcode = write_raw_chunk (pData, pPPLT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_PPLT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+WRITE_CHUNK (mng_write_ijng)
+{
+ mng_ijngp pIJNG;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IJNG, MNG_LC_START);
+#endif
+
+ pIJNG = (mng_ijngp)pChunk; /* address the proper chunk */
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pIJNG->sHeader.iChunkname, 0, 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_IJNG, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_drop)
+{
+ mng_dropp pDROP;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint32 iX;
+ mng_uint8p pTemp1;
+ mng_chunkidp pTemp2;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DROP, MNG_LC_START);
+#endif
+
+ pDROP = (mng_dropp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pDROP->iCount << 2;
+
+ pTemp1 = pRawdata; /* fill the output buffer */
+ pTemp2 = pDROP->pChunknames;
+
+ for (iX = 0; iX < pDROP->iCount; iX++)
+ {
+ mng_put_uint32 (pTemp1, (mng_uint32)*pTemp2);
+
+ pTemp2++;
+ pTemp1 += 4;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pDROP->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DROP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+WRITE_CHUNK (mng_write_dbyk)
+{
+ mng_dbykp pDBYK;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DBYK, MNG_LC_START);
+#endif
+
+ pDBYK = (mng_dbykp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 5 + pDBYK->iKeywordssize;
+ /* fill the output buffer */
+ mng_put_uint32 (pRawdata, pDBYK->iChunkname);
+ *(pRawdata+4) = pDBYK->iPolarity;
+
+ if (pDBYK->iKeywordssize)
+ MNG_COPY (pRawdata+5, pDBYK->zKeywords, pDBYK->iKeywordssize);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pDBYK->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_DBYK, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+WRITE_CHUNK (mng_write_ordr)
+{
+ mng_ordrp pORDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pTemp;
+ mng_ordr_entryp pEntry;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ORDR, MNG_LC_START);
+#endif
+
+ pORDR = (mng_ordrp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = pORDR->iCount * 5;
+
+ pTemp = pRawdata; /* fill the output buffer */
+ pEntry = pORDR->pEntries;
+
+ for (iX = 0; iX < pORDR->iCount; iX++)
+ {
+ mng_put_uint32 (pTemp, pEntry->iChunkname);
+ *(pTemp+4) = pEntry->iOrdertype;
+ pTemp += 5;
+ pEntry++;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pORDR->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_ORDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_magn)
+{
+ mng_magnp pMAGN;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MAGN, MNG_LC_START);
+#endif
+
+ pMAGN = (mng_magnp)pChunk; /* address the proper chunk */
+
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 18;
+ /* fill the output buffer */
+ mng_put_uint16 (pRawdata, pMAGN->iFirstid);
+ mng_put_uint16 (pRawdata+2, pMAGN->iLastid);
+ *(pRawdata+4) = pMAGN->iMethodX;
+ mng_put_uint16 (pRawdata+5, pMAGN->iMX);
+ mng_put_uint16 (pRawdata+7, pMAGN->iMY);
+ mng_put_uint16 (pRawdata+9, pMAGN->iML);
+ mng_put_uint16 (pRawdata+11, pMAGN->iMR);
+ mng_put_uint16 (pRawdata+13, pMAGN->iMT);
+ mng_put_uint16 (pRawdata+15, pMAGN->iMB);
+ *(pRawdata+17) = pMAGN->iMethodY;
+ /* optimize length */
+ if (pMAGN->iMethodY == pMAGN->iMethodX)
+ {
+ iRawlen--;
+
+ if (pMAGN->iMB == pMAGN->iMY)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iMT == pMAGN->iMY)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iMR == pMAGN->iMX)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iML == pMAGN->iMX)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iMY == pMAGN->iMX)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iMX == 1)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iMethodX == 0)
+ {
+ iRawlen--;
+
+ if (pMAGN->iLastid == pMAGN->iFirstid)
+ {
+ iRawlen -= 2;
+
+ if (pMAGN->iFirstid == 0)
+ iRawlen = 0;
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pMAGN->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MAGN, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+WRITE_CHUNK (mng_write_mpng)
+{
+ mng_mpngp pMPNG;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_uint8p pBuf = 0;
+ mng_uint32 iBuflen;
+ mng_uint32 iReallen;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MPNG, MNG_LC_START);
+#endif
+
+ pMPNG = (mng_mpngp)pChunk; /* address the proper chunk */
+ /* compress the frame structures */
+ iRetcode = deflate_buffer (pData, (mng_uint8p)pMPNG->pFrames, pMPNG->iFramessize,
+ &pBuf, &iBuflen, &iReallen);
+
+ if (!iRetcode) /* all ok ? */
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 15 + iReallen;
+ /* requires large buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_ALLOC (pData, pRawdata, iRawlen);
+ /* fill the buffer */
+ mng_put_uint32 (pRawdata, pMPNG->iFramewidth);
+ mng_put_uint32 (pRawdata+4, pMPNG->iFrameheight);
+ mng_put_uint16 (pRawdata+8, pMPNG->iNumplays);
+ mng_put_uint16 (pRawdata+10, pMPNG->iTickspersec);
+ *(pRawdata+12) = pMPNG->iCompressionmethod;
+
+ if (iReallen)
+ MNG_COPY (pRawdata+13, pBuf, iReallen);
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pMPNG->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ /* drop the temp buffer ? */
+ if (iRawlen > pData->iWritebufsize)
+ MNG_FREEX (pData, pRawdata, iRawlen);
+ }
+
+ MNG_FREEX (pData, pBuf, iBuflen); /* always drop the compression buffer */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_MPNG, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+WRITE_CHUNK (mng_write_ahdr)
+{
+ mng_ahdrp pAHDR;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_AHDR, MNG_LC_START);
+#endif
+
+ pAHDR = (mng_ahdrp)pChunk; /* address the proper chunk */
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 22;
+ /* fill the buffer */
+ mng_put_uint32 (pRawdata, pAHDR->iNumframes);
+ mng_put_uint32 (pRawdata+4, pAHDR->iTickspersec);
+ mng_put_uint32 (pRawdata+8, pAHDR->iNumplays);
+ mng_put_uint32 (pRawdata+12, pAHDR->iTilewidth);
+ mng_put_uint32 (pRawdata+16, pAHDR->iTileheight);
+ *(pRawdata+20) = pAHDR->iInterlace;
+ *(pRawdata+21) = pAHDR->iStillused;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pAHDR->sHeader.iChunkname,
+ iRawlen, pRawdata);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_AHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+WRITE_CHUNK (mng_write_adat)
+{
+
+ /* TODO: something */
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+WRITE_CHUNK (mng_write_evnt)
+{
+ mng_evntp pEVNT;
+ mng_uint8p pRawdata;
+ mng_uint32 iRawlen;
+ mng_retcode iRetcode;
+ mng_evnt_entryp pEntry;
+ mng_uint8p pTemp;
+ mng_uint32 iX;
+ mng_uint32 iNamesize;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_EVNT, MNG_LC_START);
+#endif
+
+ pEVNT = (mng_evntp)pChunk; /* address the proper chunk */
+
+ if (!pEVNT->iCount) /* empty ? */
+ iRetcode = write_raw_chunk (pData, pEVNT->sHeader.iChunkname, 0, 0);
+ else
+ {
+ pRawdata = pData->pWritebuf+8; /* init output buffer & size */
+ iRawlen = 0;
+ pTemp = pRawdata;
+ pEntry = pEVNT->pEntries;
+
+ for (iX = 0; iX < pEVNT->iCount; iX++)
+ {
+ if (iX) /* put separator null-byte, except the first */
+ {
+ *pTemp = 0;
+ pTemp++;
+ iRawlen++;
+ }
+
+ *pTemp = pEntry->iEventtype;
+ *(pTemp+1) = pEntry->iMasktype;
+ pTemp += 2;
+ iRawlen += 2;
+
+ switch (pEntry->iMasktype)
+ {
+ case 1 :
+ {
+ mng_put_int32 (pTemp, pEntry->iLeft);
+ mng_put_int32 (pTemp+4, pEntry->iRight);
+ mng_put_int32 (pTemp+8, pEntry->iTop);
+ mng_put_int32 (pTemp+12, pEntry->iBottom);
+ pTemp += 16;
+ iRawlen += 16;
+ break;
+ }
+ case 2 :
+ {
+ mng_put_uint16 (pTemp, pEntry->iObjectid);
+ pTemp += 2;
+ iRawlen += 2;
+ break;
+ }
+ case 3 :
+ {
+ mng_put_uint16 (pTemp, pEntry->iObjectid);
+ *(pTemp+2) = pEntry->iIndex;
+ pTemp += 3;
+ iRawlen += 3;
+ break;
+ }
+ case 4 :
+ {
+ mng_put_int32 (pTemp, pEntry->iLeft);
+ mng_put_int32 (pTemp+4, pEntry->iRight);
+ mng_put_int32 (pTemp+8, pEntry->iTop);
+ mng_put_int32 (pTemp+12, pEntry->iBottom);
+ mng_put_uint16 (pTemp+16, pEntry->iObjectid);
+ pTemp += 18;
+ iRawlen += 18;
+ break;
+ }
+ case 5 :
+ {
+ mng_put_int32 (pTemp, pEntry->iLeft);
+ mng_put_int32 (pTemp+4, pEntry->iRight);
+ mng_put_int32 (pTemp+8, pEntry->iTop);
+ mng_put_int32 (pTemp+12, pEntry->iBottom);
+ mng_put_uint16 (pTemp+16, pEntry->iObjectid);
+ *(pTemp+18) = pEntry->iIndex;
+ pTemp += 19;
+ iRawlen += 19;
+ break;
+ }
+ }
+
+ iNamesize = pEntry->iSegmentnamesize;
+
+ if (iNamesize)
+ {
+ MNG_COPY (pTemp, pEntry->zSegmentname, iNamesize);
+ pTemp += iNamesize;
+ iRawlen += iNamesize;
+ }
+
+ pEntry++;
+ }
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pEVNT->sHeader.iChunkname,
+ iRawlen, pRawdata);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_EVNT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+WRITE_CHUNK (mng_write_unknown)
+{
+ mng_unknown_chunkp pUnknown;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_UNKNOWN, MNG_LC_START);
+#endif
+ /* address the proper chunk */
+ pUnknown = (mng_unknown_chunkp)pChunk;
+ /* and write it */
+ iRetcode = write_raw_chunk (pData, pUnknown->sHeader.iChunkname,
+ pUnknown->iDatasize, pUnknown->pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_UNKNOWN, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_chunk_io.h b/Source/LibMNG/libmng_chunk_io.h
new file mode 100644
index 0000000..f8505ba
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_io.h
@@ -0,0 +1,415 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_io.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.109 * */
+/* * * */
+/* * purpose : Chunk I/O routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the chunk input/output routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/04/2000 - G.Juyn * */
+/* * - changed CRC initialization to use dynamic structure * */
+/* * (wasn't thread-safe the old way !) * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed write routines definition * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added SKIP_CHUNK and NO_DELTA_PNG support * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - fixed SKIPCHUNK_itXT and SKIPCHUNK_ztXT typos * */
+/* * * */
+/* * 1.0.9 - 12/07/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_chunk_io_h_
+#define _libmng_chunk_io_h_
+
+/* ************************************************************************** */
+
+mng_uint32 mng_crc (mng_datap pData,
+ mng_uint8p buf,
+ mng_int32 len);
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_READ_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode mng_inflate_buffer (mng_datap pData,
+ mng_uint8p pInbuf,
+ mng_uint32 iInsize,
+ mng_uint8p *pOutbuf,
+ mng_uint32 *iOutsize,
+ mng_uint32 *iRealsize);
+
+/* ************************************************************************** */
+
+#define READ_CHUNK(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pHeader, \
+ mng_uint32 iRawlen, \
+ mng_uint8p pRawdata, \
+ mng_chunkp* ppChunk)
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+READ_CHUNK (mng_read_general) ;
+#endif
+
+READ_CHUNK (mng_read_ihdr) ;
+READ_CHUNK (mng_read_plte) ;
+READ_CHUNK (mng_read_idat) ;
+READ_CHUNK (mng_read_iend) ;
+READ_CHUNK (mng_read_trns) ;
+READ_CHUNK (mng_read_gama) ;
+READ_CHUNK (mng_read_chrm) ;
+READ_CHUNK (mng_read_srgb) ;
+#ifndef MNG_SKIPCHUNK_iCCP
+READ_CHUNK (mng_read_iccp) ;
+#endif
+#ifndef MNG_SKIPCHUNK_tEXt
+READ_CHUNK (mng_read_text) ;
+#endif
+#ifndef MNG_SKIPCHUNK_zTXt
+READ_CHUNK (mng_read_ztxt) ;
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+READ_CHUNK (mng_read_itxt) ;
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+READ_CHUNK (mng_read_bkgd) ;
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+READ_CHUNK (mng_read_phys) ;
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+READ_CHUNK (mng_read_sbit) ;
+#endif
+#ifndef MNG_SKIPCHUNK_sPLT
+READ_CHUNK (mng_read_splt) ;
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+READ_CHUNK (mng_read_hist) ;
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+READ_CHUNK (mng_read_time) ;
+#endif
+READ_CHUNK (mng_read_mhdr) ;
+READ_CHUNK (mng_read_mend) ;
+READ_CHUNK (mng_read_loop) ;
+READ_CHUNK (mng_read_endl) ;
+READ_CHUNK (mng_read_defi) ;
+READ_CHUNK (mng_read_basi) ;
+READ_CHUNK (mng_read_clon) ;
+#ifndef MNG_SKIPCHUNK_PAST
+READ_CHUNK (mng_read_past) ;
+#endif
+READ_CHUNK (mng_read_disc) ;
+READ_CHUNK (mng_read_back) ;
+READ_CHUNK (mng_read_fram) ;
+READ_CHUNK (mng_read_move) ;
+READ_CHUNK (mng_read_clip) ;
+READ_CHUNK (mng_read_show) ;
+READ_CHUNK (mng_read_term) ;
+READ_CHUNK (mng_read_save) ;
+READ_CHUNK (mng_read_seek) ;
+#ifndef MNG_SKIPCHUNK_eXPI
+READ_CHUNK (mng_read_expi) ;
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+READ_CHUNK (mng_read_fpri) ;
+#endif
+#ifndef MNG_SKIPCHUNK_pHYg
+READ_CHUNK (mng_read_phyg) ;
+#endif
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_jhdr) ;
+READ_CHUNK (mng_read_jdaa) ;
+READ_CHUNK (mng_read_jdat) ;
+READ_CHUNK (mng_read_jsep) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+READ_CHUNK (mng_read_dhdr) ;
+READ_CHUNK (mng_read_prom) ;
+READ_CHUNK (mng_read_ipng) ;
+READ_CHUNK (mng_read_pplt) ;
+#ifdef MNG_INCLUDE_JNG
+READ_CHUNK (mng_read_ijng) ;
+#endif
+READ_CHUNK (mng_read_drop) ;
+READ_CHUNK (mng_read_dbyk) ;
+READ_CHUNK (mng_read_ordr) ;
+#endif
+READ_CHUNK (mng_read_magn) ;
+#ifndef MNG_SKIPCHUNK_nEED
+READ_CHUNK (mng_read_need) ;
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+READ_CHUNK (mng_read_mpng) ;
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+READ_CHUNK (mng_read_evnt) ;
+#endif
+READ_CHUNK (mng_read_unknown) ;
+
+/* ************************************************************************** */
+
+#else /* MNG_INCLUDE_READ_PROCS */
+#define mng_read_ihdr 0
+#define mng_read_plte 0
+#define mng_read_idat 0
+#define mng_read_iend 0
+#define mng_read_trns 0
+#define mng_read_gama 0
+#define mng_read_chrm 0
+#define mng_read_srgb 0
+#define mng_read_iccp 0
+#define mng_read_text 0
+#define mng_read_ztxt 0
+#define mng_read_itxt 0
+#define mng_read_bkgd 0
+#define mng_read_phys 0
+#define mng_read_sbit 0
+#define mng_read_splt 0
+#define mng_read_hist 0
+#define mng_read_time 0
+#define mng_read_mhdr 0
+#define mng_read_mend 0
+#define mng_read_loop 0
+#define mng_read_endl 0
+#define mng_read_defi 0
+#define mng_read_basi 0
+#define mng_read_clon 0
+#ifndef MNG_SKIPCHUNK_PAST
+#define mng_read_past 0
+#endif
+#define mng_read_disc 0
+#define mng_read_back 0
+#define mng_read_fram 0
+#define mng_read_move 0
+#define mng_read_clip 0
+#define mng_read_show 0
+#define mng_read_term 0
+#define mng_read_save 0
+#define mng_read_seek 0
+#define mng_read_expi 0
+#define mng_read_fpri 0
+#define mng_read_phyg 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_read_jhdr 0
+#define mng_read_jdaa 0
+#define mng_read_jdat 0
+#define mng_read_jsep 0
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#define mng_read_dhdr 0
+#define mng_read_prom 0
+#define mng_read_ipng 0
+#define mng_read_pplt 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_read_ijng 0
+#endif
+#define mng_read_drop 0
+#define mng_read_dbyk 0
+#define mng_read_ordr 0
+#endif
+#define mng_read_magn 0
+#define mng_read_need 0
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+#define mng_read_mpng 0
+#endif
+#define mng_read_evnt 0
+#define mng_read_unknown 0
+#endif /* MNG_INCLUDE_READ_PROCS */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+#define WRITE_CHUNK(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pChunk)
+
+WRITE_CHUNK (mng_write_ihdr) ;
+WRITE_CHUNK (mng_write_plte) ;
+WRITE_CHUNK (mng_write_idat) ;
+WRITE_CHUNK (mng_write_iend) ;
+WRITE_CHUNK (mng_write_trns) ;
+WRITE_CHUNK (mng_write_gama) ;
+WRITE_CHUNK (mng_write_chrm) ;
+WRITE_CHUNK (mng_write_srgb) ;
+WRITE_CHUNK (mng_write_iccp) ;
+WRITE_CHUNK (mng_write_text) ;
+WRITE_CHUNK (mng_write_ztxt) ;
+WRITE_CHUNK (mng_write_itxt) ;
+WRITE_CHUNK (mng_write_bkgd) ;
+WRITE_CHUNK (mng_write_phys) ;
+WRITE_CHUNK (mng_write_sbit) ;
+WRITE_CHUNK (mng_write_splt) ;
+WRITE_CHUNK (mng_write_hist) ;
+WRITE_CHUNK (mng_write_time) ;
+WRITE_CHUNK (mng_write_mhdr) ;
+WRITE_CHUNK (mng_write_mend) ;
+WRITE_CHUNK (mng_write_loop) ;
+WRITE_CHUNK (mng_write_endl) ;
+WRITE_CHUNK (mng_write_defi) ;
+WRITE_CHUNK (mng_write_basi) ;
+WRITE_CHUNK (mng_write_clon) ;
+#ifndef MNG_SKIPCHUNK_PAST
+WRITE_CHUNK (mng_write_past) ;
+#endif
+WRITE_CHUNK (mng_write_disc) ;
+WRITE_CHUNK (mng_write_back) ;
+WRITE_CHUNK (mng_write_fram) ;
+WRITE_CHUNK (mng_write_move) ;
+WRITE_CHUNK (mng_write_clip) ;
+WRITE_CHUNK (mng_write_show) ;
+WRITE_CHUNK (mng_write_term) ;
+WRITE_CHUNK (mng_write_save) ;
+WRITE_CHUNK (mng_write_seek) ;
+WRITE_CHUNK (mng_write_expi) ;
+WRITE_CHUNK (mng_write_fpri) ;
+WRITE_CHUNK (mng_write_phyg) ;
+#ifdef MNG_INCLUDE_JNG
+WRITE_CHUNK (mng_write_jhdr) ;
+WRITE_CHUNK (mng_write_jdaa) ;
+WRITE_CHUNK (mng_write_jdat) ;
+WRITE_CHUNK (mng_write_jsep) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+WRITE_CHUNK (mng_write_dhdr) ;
+WRITE_CHUNK (mng_write_prom) ;
+WRITE_CHUNK (mng_write_ipng) ;
+WRITE_CHUNK (mng_write_pplt) ;
+#ifdef MNG_INCLUDE_JNG
+WRITE_CHUNK (mng_write_ijng) ;
+#endif
+WRITE_CHUNK (mng_write_drop) ;
+WRITE_CHUNK (mng_write_dbyk) ;
+WRITE_CHUNK (mng_write_ordr) ;
+#endif
+WRITE_CHUNK (mng_write_magn) ;
+WRITE_CHUNK (mng_write_need) ;
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+WRITE_CHUNK (mng_write_mpng) ;
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+WRITE_CHUNK (mng_write_ahdr) ;
+WRITE_CHUNK (mng_write_adat) ;
+#endif
+WRITE_CHUNK (mng_write_evnt) ;
+WRITE_CHUNK (mng_write_unknown) ;
+
+/* ************************************************************************** */
+
+#else /* MNG_INCLUDE_WRITE_PROCS */
+#define mng_write_ihdr 0
+#define mng_write_plte 0
+#define mng_write_idat 0
+#define mng_write_iend 0
+#define mng_write_trns 0
+#define mng_write_gama 0
+#define mng_write_chrm 0
+#define mng_write_srgb 0
+#define mng_write_iccp 0
+#define mng_write_text 0
+#define mng_write_ztxt 0
+#define mng_write_itxt 0
+#define mng_write_bkgd 0
+#define mng_write_phys 0
+#define mng_write_sbit 0
+#define mng_write_splt 0
+#define mng_write_hist 0
+#define mng_write_time 0
+#define mng_write_mhdr 0
+#define mng_write_mend 0
+#define mng_write_loop 0
+#define mng_write_endl 0
+#define mng_write_defi 0
+#define mng_write_basi 0
+#define mng_write_clon 0
+#ifndef MNG_SKIPCHUNK_PAST
+#define mng_write_past 0
+#endif
+#define mng_write_disc 0
+#define mng_write_back 0
+#define mng_write_fram 0
+#define mng_write_move 0
+#define mng_write_clip 0
+#define mng_write_show 0
+#define mng_write_term 0
+#define mng_write_save 0
+#define mng_write_seek 0
+#define mng_write_expi 0
+#define mng_write_fpri 0
+#define mng_write_phyg 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_write_jhdr 0
+#define mng_write_jdaa 0
+#define mng_write_jdat 0
+#define mng_write_jsep 0
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#define mng_write_dhdr 0
+#define mng_write_prom 0
+#define mng_write_ipng 0
+#define mng_write_pplt 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_write_ijng 0
+#endif
+#define mng_write_drop 0
+#define mng_write_dbyk 0
+#define mng_write_ordr 0
+#endif
+#define mng_write_magn 0
+#define mng_write_need 0
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+#define mng_write_mpng 0
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+#define mng_write_adat 0
+#define mng_write_ahdr 0
+#endif
+#define mng_write_evnt 0
+#define mng_write_unknown 0
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_chunk_io_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_chunk_prc.c b/Source/LibMNG/libmng_chunk_prc.c
new file mode 100644
index 0000000..e633e7e
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_prc.c
@@ -0,0 +1,4452 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_prc.c copyright (c) 2000-2005 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk initialization & cleanup (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the chunk initialization & cleanup * */
+/* * routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - fixed creation-code * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - put add_chunk() inside MNG_INCLUDE_WRITE_PROCS wrapper * */
+/* * 0.9.2 - 08/01/2000 - G.Juyn * */
+/* * - wrapper for add_chunk() changed * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 10/04/2002 - G.Juyn * */
+/* * - fixed chunk-storage for evNT chunk * */
+/* * 1.0.5 - 10/17/2002 - G.Juyn * */
+/* * - fixed issue in freeing evNT chunk * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * - added MNG_NO_DELTA_PNG reduction feature * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added conditionals around non-VLC chunk support * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - fixed SKIPCHUNK_eXPI -> fPRI typo * */
+/* * * */
+/* * 1.0.9 - 09/25/2004 - G.Juyn * */
+/* * - replaced MNG_TWEAK_LARGE_FILES with permanent solution * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 07/30/2005 - G.Juyn * */
+/* * - fixed problem with CLON object during readdisplay() * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_chunks.h"
+#include "libmng_chunk_prc.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * General chunk routines * */
+/* * * */
+/* ************************************************************************** */
+
+void mng_add_chunk (mng_datap pData,
+ mng_chunkp pChunk)
+{
+ if (!pData->pFirstchunk) /* list is still empty ? */
+ {
+ pData->pFirstchunk = pChunk; /* then this becomes the first */
+
+#ifdef MNG_SUPPORT_WRITE
+ if (!pData->iFirstchunkadded)
+ {
+ pData->iFirstchunkadded = ((mng_chunk_headerp)pChunk)->iChunkname;
+#endif
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname == MNG_UINT_IHDR)
+ pData->eImagetype = mng_it_png;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_chunk_headerp)pChunk)->iChunkname == MNG_UINT_JHDR)
+ pData->eImagetype = mng_it_jng;
+ else
+#endif
+ pData->eImagetype = mng_it_mng;
+
+ pData->eSigtype = pData->eImagetype;
+#ifdef MNG_SUPPORT_WRITE
+ }
+#endif
+ }
+ else
+ { /* else we make appropriate links */
+ ((mng_chunk_headerp)pChunk)->pPrev = pData->pLastchunk;
+ ((mng_chunk_headerp)pData->pLastchunk)->pNext = pChunk;
+ }
+
+ pData->pLastchunk = pChunk; /* and it's always the last */
+
+ return;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk specific initialization routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+INIT_CHUNK_HDR (mng_init_general)
+{
+ MNG_ALLOC (pData, *ppChunk, ((mng_chunk_headerp)pHeader)->iChunksize);
+ MNG_COPY (*ppChunk, pHeader, sizeof (mng_chunk_header));
+ return MNG_NOERROR;
+}
+
+#else /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_ihdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IHDR, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_ihdr));
+ ((mng_ihdrp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_plte)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PLTE, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_plte));
+ ((mng_pltep)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_idat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDAT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_idat));
+ ((mng_idatp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_iend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IEND, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_iend));
+ ((mng_iendp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_trns)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TRNS, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_trns));
+ ((mng_trnsp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_gAMA
+INIT_CHUNK_HDR (mng_init_gama)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GAMA, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_gama));
+ ((mng_gamap)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+INIT_CHUNK_HDR (mng_init_chrm)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CHRM, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_chrm));
+ ((mng_chrmp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sRGB
+INIT_CHUNK_HDR (mng_init_srgb)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SRGB, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_srgb));
+ ((mng_srgbp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+INIT_CHUNK_HDR (mng_init_iccp)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ICCP, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_iccp));
+ ((mng_iccpp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+INIT_CHUNK_HDR (mng_init_text)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TEXT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_text));
+ ((mng_textp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+INIT_CHUNK_HDR (mng_init_ztxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ZTXT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_ztxt));
+ ((mng_ztxtp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ZTXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+INIT_CHUNK_HDR (mng_init_itxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ITXT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_itxt));
+ ((mng_itxtp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+INIT_CHUNK_HDR (mng_init_bkgd)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BKGD, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_bkgd));
+ ((mng_bkgdp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+INIT_CHUNK_HDR (mng_init_phys)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PHYS, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_phys));
+ ((mng_physp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+INIT_CHUNK_HDR (mng_init_sbit)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SBIT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_sbit));
+ ((mng_sbitp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+INIT_CHUNK_HDR (mng_init_splt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SPLT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_splt));
+ ((mng_spltp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+INIT_CHUNK_HDR (mng_init_hist)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_HIST, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_hist));
+ ((mng_histp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+INIT_CHUNK_HDR (mng_init_time)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TIME, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_time));
+ ((mng_timep)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_mhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MHDR, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_mhdr));
+ ((mng_mhdrp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_mend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MEND, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_mend));
+ ((mng_mendp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+INIT_CHUNK_HDR (mng_init_loop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_LOOP, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_loop));
+ ((mng_loopp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_endl)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ENDL, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_endl));
+ ((mng_endlp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+INIT_CHUNK_HDR (mng_init_defi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DEFI, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_defi));
+ ((mng_defip)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+INIT_CHUNK_HDR (mng_init_basi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BASI, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_basi));
+ ((mng_basip)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+INIT_CHUNK_HDR (mng_init_clon)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CLON, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_clon));
+ ((mng_clonp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+INIT_CHUNK_HDR (mng_init_past)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PAST, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_past));
+ ((mng_pastp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+INIT_CHUNK_HDR (mng_init_disc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DISC, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_disc));
+ ((mng_discp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+INIT_CHUNK_HDR (mng_init_back)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BACK, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_back));
+ ((mng_backp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+INIT_CHUNK_HDR (mng_init_fram)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FRAM, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_fram));
+ ((mng_framp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+INIT_CHUNK_HDR (mng_init_move)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MOVE, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_move));
+ ((mng_movep)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+INIT_CHUNK_HDR (mng_init_clip)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CLIP, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_clip));
+ ((mng_clipp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+INIT_CHUNK_HDR (mng_init_show)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SHOW, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_show));
+ ((mng_showp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+INIT_CHUNK_HDR (mng_init_term)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TERM, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_term));
+ ((mng_termp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+INIT_CHUNK_HDR (mng_init_save)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SAVE, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_save));
+ ((mng_savep)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+INIT_CHUNK_HDR (mng_init_seek)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SEEK, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_seek));
+ ((mng_seekp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+INIT_CHUNK_HDR (mng_init_expi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_EXPI, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_expi));
+ ((mng_expip)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_EXPI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+INIT_CHUNK_HDR (mng_init_fpri)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FPRI, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_fpri));
+ ((mng_fprip)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+INIT_CHUNK_HDR (mng_init_need)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_NEED, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_need));
+ ((mng_needp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_NEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+INIT_CHUNK_HDR (mng_init_phyg)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PHYG, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_phyg));
+ ((mng_phygp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_jhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JHDR, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_jhdr));
+ ((mng_jhdrp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_jdaa)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JDAA, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_jdaa));
+ ((mng_jdaap)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_jdat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JDAT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_jdat));
+ ((mng_jdatp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_jsep)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JSEP, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_jsep));
+ ((mng_jsepp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JSEP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_dhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DHDR, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_dhdr));
+ ((mng_dhdrp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_prom)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PROM, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_prom));
+ ((mng_promp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_ipng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IPNG, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_ipng));
+ ((mng_ipngp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_pplt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PPLT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_pplt));
+ ((mng_ppltp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_ijng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IJNG, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_ijng));
+ ((mng_ijngp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_drop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DROP, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_drop));
+ ((mng_dropp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DROP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+INIT_CHUNK_HDR (mng_init_dbyk)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DBYK, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_dbyk));
+ ((mng_dbykp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_DBYK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+INIT_CHUNK_HDR (mng_init_ordr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ORDR, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_ordr));
+ ((mng_ordrp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ORDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+INIT_CHUNK_HDR (mng_init_magn)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MAGN, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_magn));
+ ((mng_magnp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+INIT_CHUNK_HDR (mng_init_evnt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_EVNT, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_evnt));
+ ((mng_evntp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_EVNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+INIT_CHUNK_HDR (mng_init_unknown)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_UNKNOWN, MNG_LC_START);
+#endif
+
+ MNG_ALLOC (pData, *ppChunk, sizeof (mng_unknown_chunk));
+ ((mng_unknown_chunkp)*ppChunk)->sHeader = *((mng_chunk_headerp)pHeader);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_UNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk specific cleanup routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_general)
+{
+ MNG_FREEX (pData, pHeader, ((mng_chunk_headerp)pHeader)->iChunksize);
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_ihdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IHDR, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_ihdr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_plte)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PLTE, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_plte));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+FREE_CHUNK_HDR (mng_free_idat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IDAT, MNG_LC_START);
+#endif
+
+ if (((mng_idatp)pHeader)->iDatasize)
+ MNG_FREEX (pData, ((mng_idatp)pHeader)->pData,
+ ((mng_idatp)pHeader)->iDatasize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_idat));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IDAT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_iend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IEND, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_iend));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_trns)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TRNS, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_trns));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_gAMA
+FREE_CHUNK_HDR (mng_free_gama)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_GAMA, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_gama));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_cHRM
+FREE_CHUNK_HDR (mng_free_chrm)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CHRM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_chrm));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_sRGB
+FREE_CHUNK_HDR (mng_free_srgb)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SRGB, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_srgb));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+FREE_CHUNK_HDR (mng_free_iccp)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ICCP, MNG_LC_START);
+#endif
+
+ if (((mng_iccpp)pHeader)->iNamesize)
+ MNG_FREEX (pData, ((mng_iccpp)pHeader)->zName,
+ ((mng_iccpp)pHeader)->iNamesize + 1);
+
+ if (((mng_iccpp)pHeader)->iProfilesize)
+ MNG_FREEX (pData, ((mng_iccpp)pHeader)->pProfile,
+ ((mng_iccpp)pHeader)->iProfilesize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_iccp));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ICCP, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+FREE_CHUNK_HDR (mng_free_text)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TEXT, MNG_LC_START);
+#endif
+
+ if (((mng_textp)pHeader)->iKeywordsize)
+ MNG_FREEX (pData, ((mng_textp)pHeader)->zKeyword,
+ ((mng_textp)pHeader)->iKeywordsize + 1);
+
+ if (((mng_textp)pHeader)->iTextsize)
+ MNG_FREEX (pData, ((mng_textp)pHeader)->zText,
+ ((mng_textp)pHeader)->iTextsize + 1);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_text));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TEXT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+FREE_CHUNK_HDR (mng_free_ztxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ZTXT, MNG_LC_START);
+#endif
+
+ if (((mng_ztxtp)pHeader)->iKeywordsize)
+ MNG_FREEX (pData, ((mng_ztxtp)pHeader)->zKeyword,
+ ((mng_ztxtp)pHeader)->iKeywordsize + 1);
+
+ if (((mng_ztxtp)pHeader)->iTextsize)
+ MNG_FREEX (pData, ((mng_ztxtp)pHeader)->zText,
+ ((mng_ztxtp)pHeader)->iTextsize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_ztxt));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ZTXT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+#ifndef MNG_SKIPCHUNK_iTXt
+FREE_CHUNK_HDR (mng_free_itxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ITXT, MNG_LC_START);
+#endif
+
+ if (((mng_itxtp)pHeader)->iKeywordsize)
+ MNG_FREEX (pData, ((mng_itxtp)pHeader)->zKeyword,
+ ((mng_itxtp)pHeader)->iKeywordsize + 1);
+
+ if (((mng_itxtp)pHeader)->iLanguagesize)
+ MNG_FREEX (pData, ((mng_itxtp)pHeader)->zLanguage,
+ ((mng_itxtp)pHeader)->iLanguagesize + 1);
+
+ if (((mng_itxtp)pHeader)->iTranslationsize)
+ MNG_FREEX (pData, ((mng_itxtp)pHeader)->zTranslation,
+ ((mng_itxtp)pHeader)->iTranslationsize + 1);
+
+ if (((mng_itxtp)pHeader)->iTextsize)
+ MNG_FREEX (pData, ((mng_itxtp)pHeader)->zText,
+ ((mng_itxtp)pHeader)->iTextsize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_itxt));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ITXT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+FREE_CHUNK_HDR (mng_free_mpng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MPNG, MNG_LC_START);
+#endif
+
+ if (((mng_mpngp)pHeader)->iFramessize)
+ MNG_FREEX (pData, ((mng_mpngp)pHeader)->pFrames,
+ ((mng_mpngp)pHeader)->iFramessize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_mpng));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MPNG, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+FREE_CHUNK_HDR (mng_free_adat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ADAT, MNG_LC_START);
+#endif
+
+ if (((mng_adatp)pHeader)->iTilessize)
+ MNG_FREEX (pData, ((mng_adatp)pHeader)->pTiles, ((mng_adatp)pHeader)->iTilessize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_adat));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ADAT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_bKGD
+FREE_CHUNK_HDR (mng_free_bkgd)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BKGD, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_bkgd));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_pHYs
+FREE_CHUNK_HDR (mng_free_phys)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PHYS, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_phys));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_sBIT
+FREE_CHUNK_HDR (mng_free_sbit)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SBIT, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_sbit));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+FREE_CHUNK_HDR (mng_free_splt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SPLT, MNG_LC_START);
+#endif
+
+ if (((mng_spltp)pHeader)->iNamesize)
+ MNG_FREEX (pData, ((mng_spltp)pHeader)->zName,
+ ((mng_spltp)pHeader)->iNamesize + 1);
+
+ if (((mng_spltp)pHeader)->iEntrycount)
+ MNG_FREEX (pData, ((mng_spltp)pHeader)->pEntries,
+ ((mng_spltp)pHeader)->iEntrycount *
+ (((mng_spltp)pHeader)->iSampledepth * 3 + sizeof (mng_uint16)) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_splt));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SPLT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_hIST
+FREE_CHUNK_HDR (mng_free_hist)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_HIST, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_hist));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_tIME
+FREE_CHUNK_HDR (mng_free_time)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TIME, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_time));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_mhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MHDR, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_mhdr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_mend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MEND, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_mend));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+FREE_CHUNK_HDR (mng_free_loop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_LOOP, MNG_LC_START);
+#endif
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (((mng_loopp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_loopp)pHeader)->pSignals,
+ ((mng_loopp)pHeader)->iCount * sizeof (mng_uint32) );
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_loop));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_LOOP, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_endl)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ENDL, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_endl));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_DEFI
+FREE_CHUNK_HDR (mng_free_defi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DEFI, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_defi));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_BASI
+FREE_CHUNK_HDR (mng_free_basi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BASI, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_basi));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_CLON
+FREE_CHUNK_HDR (mng_free_clon)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CLON, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_clon));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+FREE_CHUNK_HDR (mng_free_past)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PAST, MNG_LC_START);
+#endif
+
+ if (((mng_pastp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_pastp)pHeader)->pSources,
+ ((mng_pastp)pHeader)->iCount * sizeof (mng_past_source) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_past));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PAST, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+FREE_CHUNK_HDR (mng_free_disc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DISC, MNG_LC_START);
+#endif
+
+ if (((mng_discp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_discp)pHeader)->pObjectids,
+ ((mng_discp)pHeader)->iCount * sizeof (mng_uint16) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_disc));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DISC, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_BACK
+FREE_CHUNK_HDR (mng_free_back)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BACK, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_back));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+FREE_CHUNK_HDR (mng_free_fram)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_FRAM, MNG_LC_START);
+#endif
+
+ if (((mng_framp)pHeader)->iNamesize)
+ MNG_FREEX (pData, ((mng_framp)pHeader)->zName,
+ ((mng_framp)pHeader)->iNamesize + 1);
+
+ if (((mng_framp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_framp)pHeader)->pSyncids,
+ ((mng_framp)pHeader)->iCount * sizeof (mng_uint32) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_fram));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_FRAM, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_MOVE
+FREE_CHUNK_HDR (mng_free_move)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MOVE, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_move));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_CLIP
+FREE_CHUNK_HDR (mng_free_clip)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CLIP, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_clip));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_SHOW
+FREE_CHUNK_HDR (mng_free_show)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SHOW, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_show));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_TERM
+FREE_CHUNK_HDR (mng_free_term)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TERM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_term));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+FREE_CHUNK_HDR (mng_free_save)
+{
+ mng_save_entryp pEntry = ((mng_savep)pHeader)->pEntries;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SAVE, MNG_LC_START);
+#endif
+
+ for (iX = 0; iX < ((mng_savep)pHeader)->iCount; iX++)
+ {
+ if (pEntry->iNamesize)
+ MNG_FREEX (pData, pEntry->zName, pEntry->iNamesize);
+
+ pEntry = pEntry + sizeof (mng_save_entry);
+ }
+
+ if (((mng_savep)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_savep)pHeader)->pEntries,
+ ((mng_savep)pHeader)->iCount * sizeof (mng_save_entry) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_save));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SAVE, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+FREE_CHUNK_HDR (mng_free_seek)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SEEK, MNG_LC_START);
+#endif
+
+ if (((mng_seekp)pHeader)->iNamesize)
+ MNG_FREEX (pData, ((mng_seekp)pHeader)->zName,
+ ((mng_seekp)pHeader)->iNamesize + 1);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_seek));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_SEEK, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+FREE_CHUNK_HDR (mng_free_expi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EXPI, MNG_LC_START);
+#endif
+
+ if (((mng_expip)pHeader)->iNamesize)
+ MNG_FREEX (pData, ((mng_expip)pHeader)->zName,
+ ((mng_expip)pHeader)->iNamesize + 1);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_expi));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EXPI, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_fPRI
+FREE_CHUNK_HDR (mng_free_fpri)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_FPRI, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_fpri));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+FREE_CHUNK_HDR (mng_free_need)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_NEED, MNG_LC_START);
+#endif
+
+ if (((mng_needp)pHeader)->iKeywordssize)
+ MNG_FREEX (pData, ((mng_needp)pHeader)->zKeywords,
+ ((mng_needp)pHeader)->iKeywordssize + 1);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_need));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_NEED, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_pHYg
+FREE_CHUNK_HDR (mng_free_phyg)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PHYG, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_phyg));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JHDR, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_jhdr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jdaa)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JDAA, MNG_LC_START);
+#endif
+
+ if (((mng_jdaap)pHeader)->iDatasize)
+ MNG_FREEX (pData, ((mng_jdaap)pHeader)->pData,
+ ((mng_jdaap)pHeader)->iDatasize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_jdaa));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JDAA, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jdat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JDAT, MNG_LC_START);
+#endif
+
+ if (((mng_jdatp)pHeader)->iDatasize)
+ MNG_FREEX (pData, ((mng_jdatp)pHeader)->pData,
+ ((mng_jdatp)pHeader)->iDatasize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_jdat));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JDAT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jsep)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JSEP, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_jsep));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_JSEP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_dhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DHDR, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_dhdr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_prom)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PROM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_prom));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_ipng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IPNG, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_ipng));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_pplt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PPLT, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_pplt));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_ijng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IJNG, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_ijng));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_drop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DROP, MNG_LC_START);
+#endif
+
+ if (((mng_dropp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_dropp)pHeader)->pChunknames,
+ ((mng_dropp)pHeader)->iCount * sizeof (mng_chunkid) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_drop));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DROP, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+FREE_CHUNK_HDR (mng_free_dbyk)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DBYK, MNG_LC_START);
+#endif
+
+ if (((mng_dbykp)pHeader)->iKeywordssize)
+ MNG_FREEX (pData, ((mng_dbykp)pHeader)->zKeywords,
+ ((mng_dbykp)pHeader)->iKeywordssize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_dbyk));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_DBYK, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+FREE_CHUNK_HDR (mng_free_ordr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ORDR, MNG_LC_START);
+#endif
+
+ if (((mng_ordrp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_ordrp)pHeader)->pEntries,
+ ((mng_ordrp)pHeader)->iCount * sizeof (mng_ordr_entry) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_ordr));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ORDR, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+#ifndef MNG_SKIPCHUNK_MAGN
+FREE_CHUNK_HDR (mng_free_magn)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MAGN, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pHeader, sizeof (mng_magn));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+FREE_CHUNK_HDR (mng_free_evnt)
+{
+ mng_evnt_entryp pEntry = ((mng_evntp)pHeader)->pEntries;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EVNT, MNG_LC_START);
+#endif
+
+ for (iX = 0; iX < ((mng_evntp)pHeader)->iCount; iX++)
+ {
+ if (pEntry->iSegmentnamesize)
+ MNG_FREEX (pData, pEntry->zSegmentname, pEntry->iSegmentnamesize+1);
+
+ pEntry++;
+ }
+
+ if (((mng_evntp)pHeader)->iCount)
+ MNG_FREEX (pData, ((mng_evntp)pHeader)->pEntries,
+ ((mng_evntp)pHeader)->iCount * sizeof (mng_evnt_entry) );
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_evnt));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EVNT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+FREE_CHUNK_HDR (mng_free_unknown)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_UNKNOWN, MNG_LC_START);
+#endif
+
+ if (((mng_unknown_chunkp)pHeader)->iDatasize)
+ MNG_FREEX (pData, ((mng_unknown_chunkp)pHeader)->pData,
+ ((mng_unknown_chunkp)pHeader)->iDatasize);
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ MNG_FREEX (pData, pHeader, sizeof (mng_unknown_chunk));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_UNKNOWN, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKINITFREE
+ return MNG_NOERROR;
+#else
+ return mng_free_general(pData, pHeader);
+#endif
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk specific copy routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_general)
+{
+ mng_ptr pSrc = (mng_uint8p)pChunkfrom + sizeof (mng_chunk_header);
+ mng_ptr pDst = (mng_uint8p)pChunkto + sizeof (mng_chunk_header);
+ mng_size_t iLen = ((mng_chunk_headerp)pChunkfrom)->iChunksize - sizeof (mng_chunk_header);
+
+ MNG_COPY (pDst, pSrc, iLen);
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_ihdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IHDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_IHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_ihdrp)pChunkto)->iWidth = ((mng_ihdrp)pChunkfrom)->iWidth;
+ ((mng_ihdrp)pChunkto)->iHeight = ((mng_ihdrp)pChunkfrom)->iHeight;
+ ((mng_ihdrp)pChunkto)->iBitdepth = ((mng_ihdrp)pChunkfrom)->iBitdepth;
+ ((mng_ihdrp)pChunkto)->iColortype = ((mng_ihdrp)pChunkfrom)->iColortype;
+ ((mng_ihdrp)pChunkto)->iCompression = ((mng_ihdrp)pChunkfrom)->iCompression;
+ ((mng_ihdrp)pChunkto)->iFilter = ((mng_ihdrp)pChunkfrom)->iFilter;
+ ((mng_ihdrp)pChunkto)->iInterlace = ((mng_ihdrp)pChunkfrom)->iInterlace;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_plte)
+{
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PLTE, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_PLTE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_pltep)pChunkto)->bEmpty = ((mng_pltep)pChunkfrom)->bEmpty;
+ ((mng_pltep)pChunkto)->iEntrycount = ((mng_pltep)pChunkfrom)->iEntrycount;
+
+ for (iX = 0; iX < ((mng_pltep)pChunkto)->iEntrycount; iX++)
+ ((mng_pltep)pChunkto)->aEntries [iX] = ((mng_pltep)pChunkfrom)->aEntries [iX];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+ASSIGN_CHUNK_HDR (mng_assign_idat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IDAT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_IDAT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_idatp)pChunkto)->bEmpty = ((mng_idatp)pChunkfrom)->bEmpty;
+ ((mng_idatp)pChunkto)->iDatasize = ((mng_idatp)pChunkfrom)->iDatasize;
+
+ if (((mng_idatp)pChunkto)->iDatasize)
+ {
+ MNG_ALLOC (pData, ((mng_idatp)pChunkto)->pData, ((mng_idatp)pChunkto)->iDatasize);
+ MNG_COPY (((mng_idatp)pChunkto)->pData, ((mng_idatp)pChunkfrom)->pData,
+ ((mng_idatp)pChunkto)->iDatasize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_iend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IEND, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_IEND)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_trns)
+{
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TRNS, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_tRNS)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_trnsp)pChunkto)->bEmpty = ((mng_trnsp)pChunkfrom)->bEmpty;
+ ((mng_trnsp)pChunkto)->bGlobal = ((mng_trnsp)pChunkfrom)->bGlobal;
+ ((mng_trnsp)pChunkto)->iType = ((mng_trnsp)pChunkfrom)->iType;
+ ((mng_trnsp)pChunkto)->iCount = ((mng_trnsp)pChunkfrom)->iCount;
+ ((mng_trnsp)pChunkto)->iGray = ((mng_trnsp)pChunkfrom)->iGray;
+ ((mng_trnsp)pChunkto)->iRed = ((mng_trnsp)pChunkfrom)->iRed;
+ ((mng_trnsp)pChunkto)->iGreen = ((mng_trnsp)pChunkfrom)->iGreen;
+ ((mng_trnsp)pChunkto)->iBlue = ((mng_trnsp)pChunkfrom)->iBlue;
+ ((mng_trnsp)pChunkto)->iRawlen = ((mng_trnsp)pChunkfrom)->iRawlen;
+
+ for (iX = 0; iX < ((mng_trnsp)pChunkto)->iCount; iX++)
+ ((mng_trnsp)pChunkto)->aEntries [iX] = ((mng_trnsp)pChunkfrom)->aEntries [iX];
+
+ for (iX = 0; iX < ((mng_trnsp)pChunkto)->iRawlen; iX++)
+ ((mng_trnsp)pChunkto)->aRawdata [iX] = ((mng_trnsp)pChunkfrom)->aRawdata [iX];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_gAMA
+ASSIGN_CHUNK_HDR (mng_assign_gama)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_GAMA, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_gAMA)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_gamap)pChunkto)->bEmpty = ((mng_gamap)pChunkfrom)->bEmpty;
+ ((mng_gamap)pChunkto)->iGamma = ((mng_gamap)pChunkfrom)->iGamma;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_cHRM
+ASSIGN_CHUNK_HDR (mng_assign_chrm)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CHRM, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_cHRM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_chrmp)pChunkto)->bEmpty = ((mng_chrmp)pChunkfrom)->bEmpty;
+ ((mng_chrmp)pChunkto)->iWhitepointx = ((mng_chrmp)pChunkfrom)->iWhitepointx;
+ ((mng_chrmp)pChunkto)->iWhitepointy = ((mng_chrmp)pChunkfrom)->iWhitepointy;
+ ((mng_chrmp)pChunkto)->iRedx = ((mng_chrmp)pChunkfrom)->iRedx;
+ ((mng_chrmp)pChunkto)->iRedy = ((mng_chrmp)pChunkfrom)->iRedy;
+ ((mng_chrmp)pChunkto)->iGreenx = ((mng_chrmp)pChunkfrom)->iGreenx;
+ ((mng_chrmp)pChunkto)->iGreeny = ((mng_chrmp)pChunkfrom)->iGreeny;
+ ((mng_chrmp)pChunkto)->iBluex = ((mng_chrmp)pChunkfrom)->iBluex;
+ ((mng_chrmp)pChunkto)->iBluey = ((mng_chrmp)pChunkfrom)->iBluey;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_sRGB
+ASSIGN_CHUNK_HDR (mng_assign_srgb)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SRGB, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_sRGB)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_srgbp)pChunkto)->iRenderingintent = ((mng_srgbp)pChunkfrom)->iRenderingintent;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ASSIGN_CHUNK_HDR (mng_assign_iccp)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ICCP, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_iCCP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_iccpp)pChunkto)->bEmpty = ((mng_iccpp)pChunkfrom)->bEmpty;
+ ((mng_iccpp)pChunkto)->iNamesize = ((mng_iccpp)pChunkfrom)->iNamesize;
+ ((mng_iccpp)pChunkto)->iCompression = ((mng_iccpp)pChunkfrom)->iCompression;
+ ((mng_iccpp)pChunkto)->iProfilesize = ((mng_iccpp)pChunkfrom)->iProfilesize;
+
+ if (((mng_iccpp)pChunkto)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_iccpp)pChunkto)->zName, ((mng_iccpp)pChunkto)->iNamesize);
+ MNG_COPY (((mng_iccpp)pChunkto)->zName, ((mng_iccpp)pChunkfrom)->zName,
+ ((mng_iccpp)pChunkto)->iNamesize);
+ }
+
+ if (((mng_iccpp)pChunkto)->iProfilesize)
+ {
+ MNG_ALLOC (pData, ((mng_iccpp)pChunkto)->pProfile, ((mng_iccpp)pChunkto)->iProfilesize);
+ MNG_COPY (((mng_iccpp)pChunkto)->pProfile, ((mng_iccpp)pChunkfrom)->pProfile,
+ ((mng_iccpp)pChunkto)->iProfilesize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+ASSIGN_CHUNK_HDR (mng_assign_text)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TEXT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_tEXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_textp)pChunkto)->iKeywordsize = ((mng_textp)pChunkfrom)->iKeywordsize;
+ ((mng_textp)pChunkto)->iTextsize = ((mng_textp)pChunkfrom)->iTextsize;
+
+ if (((mng_textp)pChunkto)->iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunkto)->zKeyword, ((mng_textp)pChunkto)->iKeywordsize);
+ MNG_COPY (((mng_itxtp)pChunkto)->zKeyword, ((mng_textp)pChunkfrom)->zKeyword,
+ ((mng_itxtp)pChunkto)->iKeywordsize);
+ }
+
+ if (((mng_textp)pChunkto)->iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_textp)pChunkto)->zText, ((mng_textp)pChunkto)->iTextsize);
+ MNG_COPY (((mng_textp)pChunkto)->zText, ((mng_textp)pChunkfrom)->zText,
+ ((mng_textp)pChunkto)->iTextsize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+ASSIGN_CHUNK_HDR (mng_assign_ztxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ZTXT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_zTXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_ztxtp)pChunkto)->iKeywordsize = ((mng_ztxtp)pChunkfrom)->iKeywordsize;
+ ((mng_ztxtp)pChunkto)->iCompression = ((mng_ztxtp)pChunkfrom)->iCompression;
+ ((mng_ztxtp)pChunkto)->iTextsize = ((mng_ztxtp)pChunkfrom)->iTextsize;
+
+ if (((mng_ztxtp)pChunkto)->iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_ztxtp)pChunkto)->zKeyword, ((mng_ztxtp)pChunkto)->iKeywordsize);
+ MNG_COPY (((mng_ztxtp)pChunkto)->zKeyword, ((mng_ztxtp)pChunkfrom)->zKeyword,
+ ((mng_ztxtp)pChunkto)->iKeywordsize);
+ }
+
+ if (((mng_ztxtp)pChunkto)->iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_ztxtp)pChunkto)->zText, ((mng_ztxtp)pChunkto)->iTextsize);
+ MNG_COPY (((mng_ztxtp)pChunkto)->zText, ((mng_ztxtp)pChunkfrom)->zText,
+ ((mng_ztxtp)pChunkto)->iTextsize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ZTXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+ASSIGN_CHUNK_HDR (mng_assign_itxt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ITXT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_iTXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_itxtp)pChunkto)->iKeywordsize = ((mng_itxtp)pChunkfrom)->iKeywordsize;
+ ((mng_itxtp)pChunkto)->iCompressionflag = ((mng_itxtp)pChunkfrom)->iCompressionflag;
+ ((mng_itxtp)pChunkto)->iCompressionmethod = ((mng_itxtp)pChunkfrom)->iCompressionmethod;
+ ((mng_itxtp)pChunkto)->iLanguagesize = ((mng_itxtp)pChunkfrom)->iLanguagesize;
+ ((mng_itxtp)pChunkto)->iTranslationsize = ((mng_itxtp)pChunkfrom)->iTranslationsize;
+ ((mng_itxtp)pChunkto)->iTextsize = ((mng_itxtp)pChunkfrom)->iTextsize;
+
+ if (((mng_itxtp)pChunkto)->iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunkto)->zKeyword, ((mng_itxtp)pChunkto)->iKeywordsize);
+ MNG_COPY (((mng_itxtp)pChunkto)->zKeyword, ((mng_itxtp)pChunkfrom)->zKeyword,
+ ((mng_itxtp)pChunkto)->iKeywordsize);
+ }
+
+ if (((mng_itxtp)pChunkto)->iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunkto)->zLanguage, ((mng_itxtp)pChunkto)->iLanguagesize);
+ MNG_COPY (((mng_itxtp)pChunkto)->zLanguage, ((mng_itxtp)pChunkfrom)->zLanguage,
+ ((mng_itxtp)pChunkto)->iLanguagesize);
+ }
+
+ if (((mng_itxtp)pChunkto)->iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunkto)->zTranslation, ((mng_itxtp)pChunkto)->iTranslationsize);
+ MNG_COPY (((mng_itxtp)pChunkto)->zTranslation, ((mng_itxtp)pChunkfrom)->zTranslation,
+ ((mng_itxtp)pChunkto)->iTranslationsize);
+ }
+
+ if (((mng_itxtp)pChunkto)->iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunkto)->zText, ((mng_itxtp)pChunkto)->iTextsize);
+ MNG_COPY (((mng_itxtp)pChunkto)->zText, ((mng_itxtp)pChunkfrom)->zText,
+ ((mng_itxtp)pChunkto)->iTextsize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_bKGD
+ASSIGN_CHUNK_HDR (mng_assign_bkgd)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BKGD, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_bKGD)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_bkgdp)pChunkto)->bEmpty = ((mng_bkgdp)pChunkfrom)->bEmpty;
+ ((mng_bkgdp)pChunkto)->iType = ((mng_bkgdp)pChunkfrom)->iType;
+ ((mng_bkgdp)pChunkto)->iIndex = ((mng_bkgdp)pChunkfrom)->iIndex;
+ ((mng_bkgdp)pChunkto)->iGray = ((mng_bkgdp)pChunkfrom)->iGray;
+ ((mng_bkgdp)pChunkto)->iRed = ((mng_bkgdp)pChunkfrom)->iRed;
+ ((mng_bkgdp)pChunkto)->iGreen = ((mng_bkgdp)pChunkfrom)->iGreen;
+ ((mng_bkgdp)pChunkto)->iBlue = ((mng_bkgdp)pChunkfrom)->iBlue;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_pHYs
+ASSIGN_CHUNK_HDR (mng_assign_phys)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PHYS, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_pHYs)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_physp)pChunkto)->bEmpty = ((mng_physp)pChunkfrom)->bEmpty;
+ ((mng_physp)pChunkto)->iSizex = ((mng_physp)pChunkfrom)->iSizex;
+ ((mng_physp)pChunkto)->iSizey = ((mng_physp)pChunkfrom)->iSizey;
+ ((mng_physp)pChunkto)->iUnit = ((mng_physp)pChunkfrom)->iUnit;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_sBIT
+ASSIGN_CHUNK_HDR (mng_assign_sbit)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SBIT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_sBIT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_sbitp)pChunkto)->bEmpty = ((mng_sbitp)pChunkfrom)->bEmpty;
+ ((mng_sbitp)pChunkto)->iType = ((mng_sbitp)pChunkfrom)->iType;
+ ((mng_sbitp)pChunkto)->aBits [0] = ((mng_sbitp)pChunkfrom)->aBits [0];
+ ((mng_sbitp)pChunkto)->aBits [1] = ((mng_sbitp)pChunkfrom)->aBits [1];
+ ((mng_sbitp)pChunkto)->aBits [2] = ((mng_sbitp)pChunkfrom)->aBits [2];
+ ((mng_sbitp)pChunkto)->aBits [3] = ((mng_sbitp)pChunkfrom)->aBits [3];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+ASSIGN_CHUNK_HDR (mng_assign_splt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SPLT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_sPLT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_spltp)pChunkto)->bEmpty = ((mng_spltp)pChunkfrom)->bEmpty;
+ ((mng_spltp)pChunkto)->iNamesize = ((mng_spltp)pChunkfrom)->iNamesize;
+ ((mng_spltp)pChunkto)->iSampledepth = ((mng_spltp)pChunkfrom)->iSampledepth;
+ ((mng_spltp)pChunkto)->iEntrycount = ((mng_spltp)pChunkfrom)->iEntrycount;
+ ((mng_spltp)pChunkto)->pEntries = ((mng_spltp)pChunkfrom)->pEntries;
+
+ if (((mng_spltp)pChunkto)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_spltp)pChunkto)->zName, ((mng_spltp)pChunkto)->iNamesize);
+ MNG_COPY (((mng_spltp)pChunkto)->zName, ((mng_spltp)pChunkfrom)->zName,
+ ((mng_spltp)pChunkto)->iNamesize);
+ }
+
+ if (((mng_spltp)pChunkto)->iEntrycount)
+ {
+ mng_uint32 iLen = ((mng_spltp)pChunkto)->iEntrycount *
+ (((mng_spltp)pChunkto)->iSampledepth * 3 + sizeof (mng_uint16));
+
+ MNG_ALLOC (pData, ((mng_spltp)pChunkto)->pEntries, iLen);
+ MNG_COPY (((mng_spltp)pChunkto)->pEntries, ((mng_spltp)pChunkfrom)->pEntries, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_hIST
+ASSIGN_CHUNK_HDR (mng_assign_hist)
+{
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_HIST, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_hIST)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_histp)pChunkto)->iEntrycount = ((mng_histp)pChunkfrom)->iEntrycount;
+
+ for (iX = 0; iX < ((mng_histp)pChunkto)->iEntrycount; iX++)
+ ((mng_histp)pChunkto)->aEntries [iX] = ((mng_histp)pChunkfrom)->aEntries [iX];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_tIME
+ASSIGN_CHUNK_HDR (mng_assign_time)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TIME, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_tIME)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_timep)pChunkto)->iYear = ((mng_timep)pChunkfrom)->iYear;
+ ((mng_timep)pChunkto)->iMonth = ((mng_timep)pChunkfrom)->iMonth;
+ ((mng_timep)pChunkto)->iDay = ((mng_timep)pChunkfrom)->iDay;
+ ((mng_timep)pChunkto)->iHour = ((mng_timep)pChunkfrom)->iHour;
+ ((mng_timep)pChunkto)->iMinute = ((mng_timep)pChunkfrom)->iMinute;
+ ((mng_timep)pChunkto)->iSecond = ((mng_timep)pChunkfrom)->iSecond;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_mhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MHDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_mhdrp)pChunkto)->iWidth = ((mng_mhdrp)pChunkfrom)->iWidth;
+ ((mng_mhdrp)pChunkto)->iHeight = ((mng_mhdrp)pChunkfrom)->iHeight;
+ ((mng_mhdrp)pChunkto)->iTicks = ((mng_mhdrp)pChunkfrom)->iTicks;
+ ((mng_mhdrp)pChunkto)->iLayercount = ((mng_mhdrp)pChunkfrom)->iLayercount;
+ ((mng_mhdrp)pChunkto)->iFramecount = ((mng_mhdrp)pChunkfrom)->iFramecount;
+ ((mng_mhdrp)pChunkto)->iPlaytime = ((mng_mhdrp)pChunkfrom)->iPlaytime;
+ ((mng_mhdrp)pChunkto)->iSimplicity = ((mng_mhdrp)pChunkfrom)->iSimplicity;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_mend)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MEND, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_MEND)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+ASSIGN_CHUNK_HDR (mng_assign_loop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_LOOP, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_LOOP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_loopp)pChunkto)->iLevel = ((mng_loopp)pChunkfrom)->iLevel;
+ ((mng_loopp)pChunkto)->iRepeat = ((mng_loopp)pChunkfrom)->iRepeat;
+ ((mng_loopp)pChunkto)->iTermination = ((mng_loopp)pChunkfrom)->iTermination;
+ ((mng_loopp)pChunkto)->iItermin = ((mng_loopp)pChunkfrom)->iItermin;
+ ((mng_loopp)pChunkto)->iItermax = ((mng_loopp)pChunkfrom)->iItermax;
+ ((mng_loopp)pChunkto)->iCount = ((mng_loopp)pChunkfrom)->iCount;
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (((mng_loopp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_loopp)pChunkto)->iCount * sizeof (mng_uint32);
+ MNG_ALLOC (pData, ((mng_loopp)pChunkto)->pSignals, iLen);
+ MNG_COPY (((mng_loopp)pChunkto)->pSignals, ((mng_loopp)pChunkfrom)->pSignals, iLen);
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_endl)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ENDL, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_ENDL)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_endlp)pChunkto)->iLevel = ((mng_endlp)pChunkfrom)->iLevel;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_DEFI
+ASSIGN_CHUNK_HDR (mng_assign_defi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DEFI, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_DEFI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_defip)pChunkto)->iObjectid = ((mng_defip)pChunkfrom)->iObjectid;
+ ((mng_defip)pChunkto)->bHasdonotshow = ((mng_defip)pChunkfrom)->bHasdonotshow;
+ ((mng_defip)pChunkto)->iDonotshow = ((mng_defip)pChunkfrom)->iDonotshow;
+ ((mng_defip)pChunkto)->bHasconcrete = ((mng_defip)pChunkfrom)->bHasconcrete;
+ ((mng_defip)pChunkto)->iConcrete = ((mng_defip)pChunkfrom)->iConcrete;
+ ((mng_defip)pChunkto)->bHasloca = ((mng_defip)pChunkfrom)->bHasloca;
+ ((mng_defip)pChunkto)->iXlocation = ((mng_defip)pChunkfrom)->iXlocation;
+ ((mng_defip)pChunkto)->iYlocation = ((mng_defip)pChunkfrom)->iYlocation;
+ ((mng_defip)pChunkto)->bHasclip = ((mng_defip)pChunkfrom)->bHasclip;
+ ((mng_defip)pChunkto)->iLeftcb = ((mng_defip)pChunkfrom)->iLeftcb;
+ ((mng_defip)pChunkto)->iRightcb = ((mng_defip)pChunkfrom)->iRightcb;
+ ((mng_defip)pChunkto)->iTopcb = ((mng_defip)pChunkfrom)->iTopcb;
+ ((mng_defip)pChunkto)->iBottomcb = ((mng_defip)pChunkfrom)->iBottomcb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_BASI
+ASSIGN_CHUNK_HDR (mng_assign_basi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BASI, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_BASI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_basip)pChunkto)->iWidth = ((mng_basip)pChunkfrom)->iWidth;
+ ((mng_basip)pChunkto)->iHeight = ((mng_basip)pChunkfrom)->iHeight;
+ ((mng_basip)pChunkto)->iBitdepth = ((mng_basip)pChunkfrom)->iBitdepth;
+ ((mng_basip)pChunkto)->iColortype = ((mng_basip)pChunkfrom)->iColortype;
+ ((mng_basip)pChunkto)->iCompression = ((mng_basip)pChunkfrom)->iCompression;
+ ((mng_basip)pChunkto)->iFilter = ((mng_basip)pChunkfrom)->iFilter;
+ ((mng_basip)pChunkto)->iInterlace = ((mng_basip)pChunkfrom)->iInterlace;
+ ((mng_basip)pChunkto)->iRed = ((mng_basip)pChunkfrom)->iRed;
+ ((mng_basip)pChunkto)->iGreen = ((mng_basip)pChunkfrom)->iGreen;
+ ((mng_basip)pChunkto)->iBlue = ((mng_basip)pChunkfrom)->iBlue;
+ ((mng_basip)pChunkto)->iAlpha = ((mng_basip)pChunkfrom)->iAlpha;
+ ((mng_basip)pChunkto)->iViewable = ((mng_basip)pChunkfrom)->iViewable;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_CLON
+ASSIGN_CHUNK_HDR (mng_assign_clon)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CLON, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_CLON)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_clonp)pChunkto)->iSourceid = ((mng_clonp)pChunkfrom)->iSourceid;
+ ((mng_clonp)pChunkto)->iCloneid = ((mng_clonp)pChunkfrom)->iCloneid;
+ ((mng_clonp)pChunkto)->iClonetype = ((mng_clonp)pChunkfrom)->iClonetype;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ ((mng_clonp)pChunkto)->bHasdonotshow = ((mng_clonp)pChunkfrom)->bHasdonotshow;
+#endif
+ ((mng_clonp)pChunkto)->iDonotshow = ((mng_clonp)pChunkfrom)->iDonotshow;
+ ((mng_clonp)pChunkto)->iConcrete = ((mng_clonp)pChunkfrom)->iConcrete;
+ ((mng_clonp)pChunkto)->bHasloca = ((mng_clonp)pChunkfrom)->bHasloca;
+ ((mng_clonp)pChunkto)->iLocationtype = ((mng_clonp)pChunkfrom)->iLocationtype;
+ ((mng_clonp)pChunkto)->iLocationx = ((mng_clonp)pChunkfrom)->iLocationx;
+ ((mng_clonp)pChunkto)->iLocationy = ((mng_clonp)pChunkfrom)->iLocationy;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+ASSIGN_CHUNK_HDR (mng_assign_past)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PAST, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_PAST)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_pastp)pChunkto)->iDestid = ((mng_pastp)pChunkfrom)->iDestid;
+ ((mng_pastp)pChunkto)->iTargettype = ((mng_pastp)pChunkfrom)->iTargettype;
+ ((mng_pastp)pChunkto)->iTargetx = ((mng_pastp)pChunkfrom)->iTargetx;
+ ((mng_pastp)pChunkto)->iTargety = ((mng_pastp)pChunkfrom)->iTargety;
+ ((mng_pastp)pChunkto)->iCount = ((mng_pastp)pChunkfrom)->iCount;
+
+ if (((mng_pastp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_pastp)pChunkto)->iCount * sizeof (mng_past_source);
+
+ MNG_ALLOC (pData, ((mng_pastp)pChunkto)->pSources, iLen);
+ MNG_COPY (((mng_pastp)pChunkto)->pSources, ((mng_pastp)pChunkfrom)->pSources, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+ASSIGN_CHUNK_HDR (mng_assign_disc)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DISC, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_DISC)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_discp)pChunkto)->iCount = ((mng_discp)pChunkfrom)->iCount;
+
+ if (((mng_discp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_discp)pChunkto)->iCount * sizeof (mng_uint16);
+
+ MNG_ALLOC (pData, ((mng_discp)pChunkto)->pObjectids, iLen);
+ MNG_COPY (((mng_discp)pChunkto)->pObjectids, ((mng_discp)pChunkfrom)->pObjectids, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_BACK
+ASSIGN_CHUNK_HDR (mng_assign_back)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BACK, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_BACK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_backp)pChunkto)->iRed = ((mng_backp)pChunkfrom)->iRed;
+ ((mng_backp)pChunkto)->iGreen = ((mng_backp)pChunkfrom)->iGreen;
+ ((mng_backp)pChunkto)->iBlue = ((mng_backp)pChunkfrom)->iBlue;
+ ((mng_backp)pChunkto)->iMandatory = ((mng_backp)pChunkfrom)->iMandatory;
+ ((mng_backp)pChunkto)->iImageid = ((mng_backp)pChunkfrom)->iImageid;
+ ((mng_backp)pChunkto)->iTile = ((mng_backp)pChunkfrom)->iTile;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ASSIGN_CHUNK_HDR (mng_assign_fram)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_FRAM, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_FRAM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_framp)pChunkto)->bEmpty = ((mng_framp)pChunkfrom)->bEmpty;
+ ((mng_framp)pChunkto)->iMode = ((mng_framp)pChunkfrom)->iMode;
+ ((mng_framp)pChunkto)->iNamesize = ((mng_framp)pChunkfrom)->iNamesize;
+ ((mng_framp)pChunkto)->iChangedelay = ((mng_framp)pChunkfrom)->iChangedelay;
+ ((mng_framp)pChunkto)->iChangetimeout = ((mng_framp)pChunkfrom)->iChangetimeout;
+ ((mng_framp)pChunkto)->iChangeclipping = ((mng_framp)pChunkfrom)->iChangeclipping;
+ ((mng_framp)pChunkto)->iChangesyncid = ((mng_framp)pChunkfrom)->iChangesyncid;
+ ((mng_framp)pChunkto)->iDelay = ((mng_framp)pChunkfrom)->iDelay;
+ ((mng_framp)pChunkto)->iTimeout = ((mng_framp)pChunkfrom)->iTimeout;
+ ((mng_framp)pChunkto)->iBoundarytype = ((mng_framp)pChunkfrom)->iBoundarytype;
+ ((mng_framp)pChunkto)->iBoundaryl = ((mng_framp)pChunkfrom)->iBoundaryl;
+ ((mng_framp)pChunkto)->iBoundaryr = ((mng_framp)pChunkfrom)->iBoundaryr;
+ ((mng_framp)pChunkto)->iBoundaryt = ((mng_framp)pChunkfrom)->iBoundaryt;
+ ((mng_framp)pChunkto)->iBoundaryb = ((mng_framp)pChunkfrom)->iBoundaryb;
+ ((mng_framp)pChunkto)->iCount = ((mng_framp)pChunkfrom)->iCount;
+
+ if (((mng_framp)pChunkto)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_framp)pChunkto)->zName, ((mng_framp)pChunkto)->iNamesize);
+ MNG_COPY (((mng_framp)pChunkto)->zName, ((mng_framp)pChunkfrom)->zName,
+ ((mng_framp)pChunkto)->iNamesize);
+ }
+
+ if (((mng_framp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_framp)pChunkto)->iCount * sizeof (mng_uint32);
+
+ MNG_ALLOC (pData, ((mng_framp)pChunkto)->pSyncids, iLen);
+ MNG_COPY (((mng_framp)pChunkto)->pSyncids, ((mng_framp)pChunkfrom)->pSyncids, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_MOVE
+ASSIGN_CHUNK_HDR (mng_assign_move)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MOVE, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_MOVE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_movep)pChunkto)->iFirstid = ((mng_movep)pChunkfrom)->iFirstid;
+ ((mng_movep)pChunkto)->iLastid = ((mng_movep)pChunkfrom)->iLastid;
+ ((mng_movep)pChunkto)->iMovetype = ((mng_movep)pChunkfrom)->iMovetype;
+ ((mng_movep)pChunkto)->iMovex = ((mng_movep)pChunkfrom)->iMovex;
+ ((mng_movep)pChunkto)->iMovey = ((mng_movep)pChunkfrom)->iMovey;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_CLIP
+ASSIGN_CHUNK_HDR (mng_assign_clip)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CLIP, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_CLIP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_clipp)pChunkto)->iFirstid = ((mng_clipp)pChunkfrom)->iFirstid;
+ ((mng_clipp)pChunkto)->iLastid = ((mng_clipp)pChunkfrom)->iLastid;
+ ((mng_clipp)pChunkto)->iCliptype = ((mng_clipp)pChunkfrom)->iCliptype;
+ ((mng_clipp)pChunkto)->iClipl = ((mng_clipp)pChunkfrom)->iClipl;
+ ((mng_clipp)pChunkto)->iClipr = ((mng_clipp)pChunkfrom)->iClipr;
+ ((mng_clipp)pChunkto)->iClipt = ((mng_clipp)pChunkfrom)->iClipt;
+ ((mng_clipp)pChunkto)->iClipb = ((mng_clipp)pChunkfrom)->iClipb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_SHOW
+ASSIGN_CHUNK_HDR (mng_assign_show)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SHOW, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_SHOW)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_showp)pChunkto)->bEmpty = ((mng_showp)pChunkfrom)->bEmpty;
+ ((mng_showp)pChunkto)->iFirstid = ((mng_showp)pChunkfrom)->iFirstid;
+ ((mng_showp)pChunkto)->iLastid = ((mng_showp)pChunkfrom)->iLastid;
+ ((mng_showp)pChunkto)->iMode = ((mng_showp)pChunkfrom)->iMode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_TERM
+ASSIGN_CHUNK_HDR (mng_assign_term)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TERM, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_TERM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_termp)pChunkto)->iTermaction = ((mng_termp)pChunkfrom)->iTermaction;
+ ((mng_termp)pChunkto)->iIteraction = ((mng_termp)pChunkfrom)->iIteraction;
+ ((mng_termp)pChunkto)->iDelay = ((mng_termp)pChunkfrom)->iDelay;
+ ((mng_termp)pChunkto)->iItermax = ((mng_termp)pChunkfrom)->iItermax;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+ASSIGN_CHUNK_HDR (mng_assign_save)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SAVE, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_SAVE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_savep)pChunkto)->bEmpty = ((mng_savep)pChunkfrom)->bEmpty;
+ ((mng_savep)pChunkto)->iOffsettype = ((mng_savep)pChunkfrom)->iOffsettype;
+ ((mng_savep)pChunkto)->iCount = ((mng_savep)pChunkfrom)->iCount;
+
+ if (((mng_savep)pChunkto)->iCount)
+ {
+ mng_uint32 iX;
+ mng_save_entryp pEntry;
+ mng_uint32 iLen = ((mng_savep)pChunkto)->iCount * sizeof (mng_save_entry);
+
+ MNG_ALLOC (pData, ((mng_savep)pChunkto)->pEntries, iLen);
+ MNG_COPY (((mng_savep)pChunkto)->pEntries, ((mng_savep)pChunkfrom)->pEntries, iLen);
+
+ pEntry = ((mng_savep)pChunkto)->pEntries;
+
+ for (iX = 0; iX < ((mng_savep)pChunkto)->iCount; iX++)
+ {
+ if (pEntry->iNamesize)
+ {
+ mng_pchar pTemp = pEntry->zName;
+
+ MNG_ALLOC (pData, pEntry->zName, pEntry->iNamesize);
+ MNG_COPY (pEntry->zName, pTemp, pEntry->iNamesize);
+ }
+ else
+ {
+ pEntry->zName = MNG_NULL;
+ }
+
+ pEntry++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+ASSIGN_CHUNK_HDR (mng_assign_seek)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SEEK, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_SEEK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_seekp)pChunkto)->iNamesize = ((mng_seekp)pChunkfrom)->iNamesize;
+
+ if (((mng_seekp)pChunkto)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_seekp)pChunkto)->zName, ((mng_seekp)pChunkto)->iNamesize);
+ MNG_COPY (((mng_seekp)pChunkto)->zName, ((mng_seekp)pChunkfrom)->zName,
+ ((mng_seekp)pChunkto)->iNamesize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+ASSIGN_CHUNK_HDR (mng_assign_expi)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_EXPI, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_eXPI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_expip)pChunkto)->iSnapshotid = ((mng_expip)pChunkfrom)->iSnapshotid;
+ ((mng_expip)pChunkto)->iNamesize = ((mng_expip)pChunkfrom)->iNamesize;
+
+ if (((mng_expip)pChunkto)->iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_expip)pChunkto)->zName, ((mng_expip)pChunkto)->iNamesize);
+ MNG_COPY (((mng_expip)pChunkto)->zName, ((mng_expip)pChunkfrom)->zName,
+ ((mng_expip)pChunkto)->iNamesize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_EXPI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_fPRI
+ASSIGN_CHUNK_HDR (mng_assign_fpri)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_FPRI, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_fPRI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_fprip)pChunkto)->iDeltatype = ((mng_fprip)pChunkfrom)->iDeltatype;
+ ((mng_fprip)pChunkto)->iPriority = ((mng_fprip)pChunkfrom)->iPriority;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+ASSIGN_CHUNK_HDR (mng_assign_need)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_NEED, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_nEED)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_needp)pChunkto)->iKeywordssize = ((mng_needp)pChunkfrom)->iKeywordssize;
+
+ if (((mng_needp)pChunkto)->iKeywordssize)
+ {
+ MNG_ALLOC (pData, ((mng_needp)pChunkto)->zKeywords, ((mng_needp)pChunkto)->iKeywordssize);
+ MNG_COPY (((mng_needp)pChunkto)->zKeywords, ((mng_needp)pChunkfrom)->zKeywords,
+ ((mng_needp)pChunkto)->iKeywordssize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_NEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_pHYg
+ASSIGN_CHUNK_HDR (mng_assign_phyg)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PHYG, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_pHYg)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_phygp)pChunkto)->bEmpty = ((mng_phygp)pChunkfrom)->bEmpty;
+ ((mng_phygp)pChunkto)->iSizex = ((mng_phygp)pChunkfrom)->iSizex;
+ ((mng_phygp)pChunkto)->iSizey = ((mng_phygp)pChunkfrom)->iSizey;
+ ((mng_phygp)pChunkto)->iUnit = ((mng_phygp)pChunkfrom)->iUnit;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JHDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_JHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_jhdrp)pChunkto)->iWidth = ((mng_jhdrp)pChunkfrom)->iWidth;
+ ((mng_jhdrp)pChunkto)->iHeight = ((mng_jhdrp)pChunkfrom)->iHeight;
+ ((mng_jhdrp)pChunkto)->iColortype = ((mng_jhdrp)pChunkfrom)->iColortype;
+ ((mng_jhdrp)pChunkto)->iImagesampledepth = ((mng_jhdrp)pChunkfrom)->iImagesampledepth;
+ ((mng_jhdrp)pChunkto)->iImagecompression = ((mng_jhdrp)pChunkfrom)->iImagecompression;
+ ((mng_jhdrp)pChunkto)->iImageinterlace = ((mng_jhdrp)pChunkfrom)->iImageinterlace;
+ ((mng_jhdrp)pChunkto)->iAlphasampledepth = ((mng_jhdrp)pChunkfrom)->iAlphasampledepth;
+ ((mng_jhdrp)pChunkto)->iAlphacompression = ((mng_jhdrp)pChunkfrom)->iAlphacompression;
+ ((mng_jhdrp)pChunkto)->iAlphafilter = ((mng_jhdrp)pChunkfrom)->iAlphafilter;
+ ((mng_jhdrp)pChunkto)->iAlphainterlace = ((mng_jhdrp)pChunkfrom)->iAlphainterlace;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jdaa)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JDAA, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_JDAA)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_jdaap)pChunkto)->bEmpty = ((mng_jdaap)pChunkfrom)->bEmpty;
+ ((mng_jdaap)pChunkto)->iDatasize = ((mng_jdaap)pChunkfrom)->iDatasize;
+
+ if (((mng_jdaap)pChunkto)->iDatasize)
+ {
+ MNG_ALLOC (pData, ((mng_jdaap)pChunkto)->pData, ((mng_jdaap)pChunkto)->iDatasize);
+ MNG_COPY (((mng_jdaap)pChunkto)->pData, ((mng_jdaap)pChunkfrom)->pData,
+ ((mng_jdaap)pChunkto)->iDatasize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jdat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JDAT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_JDAT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_jdatp)pChunkto)->bEmpty = ((mng_jdatp)pChunkfrom)->bEmpty;
+ ((mng_jdatp)pChunkto)->iDatasize = ((mng_jdatp)pChunkfrom)->iDatasize;
+
+ if (((mng_jdatp)pChunkto)->iDatasize)
+ {
+ MNG_ALLOC (pData, ((mng_jdatp)pChunkto)->pData, ((mng_jdatp)pChunkto)->iDatasize);
+ MNG_COPY (((mng_jdatp)pChunkto)->pData, ((mng_jdatp)pChunkfrom)->pData,
+ ((mng_jdatp)pChunkto)->iDatasize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jsep)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JSEP, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_JSEP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_JSEP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_dhdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DHDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_DHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_dhdrp)pChunkto)->iObjectid = ((mng_dhdrp)pChunkfrom)->iObjectid;
+ ((mng_dhdrp)pChunkto)->iImagetype = ((mng_dhdrp)pChunkfrom)->iImagetype;
+ ((mng_dhdrp)pChunkto)->iDeltatype = ((mng_dhdrp)pChunkfrom)->iDeltatype;
+ ((mng_dhdrp)pChunkto)->iBlockwidth = ((mng_dhdrp)pChunkfrom)->iBlockwidth;
+ ((mng_dhdrp)pChunkto)->iBlockheight = ((mng_dhdrp)pChunkfrom)->iBlockheight;
+ ((mng_dhdrp)pChunkto)->iBlockx = ((mng_dhdrp)pChunkfrom)->iBlockx;
+ ((mng_dhdrp)pChunkto)->iBlocky = ((mng_dhdrp)pChunkfrom)->iBlocky;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_prom)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PROM, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_PROM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_promp)pChunkto)->iColortype = ((mng_promp)pChunkfrom)->iColortype;
+ ((mng_promp)pChunkto)->iSampledepth = ((mng_promp)pChunkfrom)->iSampledepth;
+ ((mng_promp)pChunkto)->iFilltype = ((mng_promp)pChunkfrom)->iFilltype;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_ipng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IPNG, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_IPNG)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_pplt)
+{
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PPLT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_PPLT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_ppltp)pChunkto)->iDeltatype = ((mng_ppltp)pChunkfrom)->iDeltatype;
+ ((mng_ppltp)pChunkto)->iCount = ((mng_ppltp)pChunkfrom)->iCount;
+
+ for (iX = 0; iX < ((mng_ppltp)pChunkto)->iCount; iX++)
+ ((mng_ppltp)pChunkto)->aEntries [iX] = ((mng_ppltp)pChunkfrom)->aEntries [iX];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_ijng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IJNG, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_IJNG)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_drop)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DROP, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_DROP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_dropp)pChunkto)->iCount = ((mng_dropp)pChunkfrom)->iCount;
+
+ if (((mng_dropp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_dropp)pChunkto)->iCount * sizeof (mng_uint32);
+
+ MNG_ALLOC (pData, ((mng_dropp)pChunkto)->pChunknames, iLen);
+ MNG_COPY (((mng_dropp)pChunkto)->pChunknames, ((mng_dropp)pChunkfrom)->pChunknames, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DROP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+ASSIGN_CHUNK_HDR (mng_assign_dbyk)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DBYK, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_DBYK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_dbykp)pChunkto)->iChunkname = ((mng_dbykp)pChunkfrom)->iChunkname;
+ ((mng_dbykp)pChunkto)->iPolarity = ((mng_dbykp)pChunkfrom)->iPolarity;
+ ((mng_dbykp)pChunkto)->iKeywordssize = ((mng_dbykp)pChunkfrom)->iKeywordssize;
+
+ if (((mng_dbykp)pChunkto)->iKeywordssize)
+ {
+ MNG_ALLOC (pData, ((mng_dbykp)pChunkto)->zKeywords, ((mng_dbykp)pChunkto)->iKeywordssize);
+ MNG_COPY (((mng_dbykp)pChunkto)->zKeywords, ((mng_dbykp)pChunkfrom)->zKeywords,
+ ((mng_dbykp)pChunkto)->iKeywordssize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_DBYK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+ASSIGN_CHUNK_HDR (mng_assign_ordr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ORDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_ORDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_ordrp)pChunkto)->iCount = ((mng_ordrp)pChunkfrom)->iCount;
+
+ if (((mng_ordrp)pChunkto)->iCount)
+ {
+ mng_uint32 iLen = ((mng_ordrp)pChunkto)->iCount * sizeof (mng_ordr_entry);
+
+ MNG_ALLOC (pData, ((mng_ordrp)pChunkto)->pEntries, iLen);
+ MNG_COPY (((mng_ordrp)pChunkto)->pEntries, ((mng_ordrp)pChunkfrom)->pEntries, iLen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ORDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKASSIGN
+#ifndef MNG_SKIPCHUNK_MAGN
+ASSIGN_CHUNK_HDR (mng_assign_magn)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MAGN, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_MAGN)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_magnp)pChunkto)->iFirstid = ((mng_magnp)pChunkfrom)->iFirstid;
+ ((mng_magnp)pChunkto)->iLastid = ((mng_magnp)pChunkfrom)->iLastid;
+ ((mng_magnp)pChunkto)->iMethodX = ((mng_magnp)pChunkfrom)->iMethodX;
+ ((mng_magnp)pChunkto)->iMX = ((mng_magnp)pChunkfrom)->iMX;
+ ((mng_magnp)pChunkto)->iMY = ((mng_magnp)pChunkfrom)->iMY;
+ ((mng_magnp)pChunkto)->iML = ((mng_magnp)pChunkfrom)->iML;
+ ((mng_magnp)pChunkto)->iMR = ((mng_magnp)pChunkfrom)->iMR;
+ ((mng_magnp)pChunkto)->iMT = ((mng_magnp)pChunkfrom)->iMT;
+ ((mng_magnp)pChunkto)->iMB = ((mng_magnp)pChunkfrom)->iMB;
+ ((mng_magnp)pChunkto)->iMethodY = ((mng_magnp)pChunkfrom)->iMethodY;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ASSIGN_CHUNK_HDR (mng_assign_mpng)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MPNG, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_mpNG)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_mpngp)pChunkto)->iFramewidth = ((mng_mpngp)pChunkfrom)->iFramewidth;
+ ((mng_mpngp)pChunkto)->iFrameheight = ((mng_mpngp)pChunkfrom)->iFrameheight;
+ ((mng_mpngp)pChunkto)->iNumplays = ((mng_mpngp)pChunkfrom)->iNumplays;
+ ((mng_mpngp)pChunkto)->iTickspersec = ((mng_mpngp)pChunkfrom)->iTickspersec;
+ ((mng_mpngp)pChunkto)->iCompressionmethod = ((mng_mpngp)pChunkfrom)->iCompressionmethod;
+ ((mng_mpngp)pChunkto)->iFramessize = ((mng_mpngp)pChunkfrom)->iFramessize;
+
+ if (((mng_mpngp)pChunkto)->iFramessize)
+ {
+ MNG_ALLOC (pData, ((mng_mpngp)pChunkto)->pFrames, ((mng_mpngp)pChunkto)->iFramessize);
+ MNG_COPY (((mng_mpngp)pChunkto)->pFrames, ((mng_mpngp)pChunkfrom)->pFrames,
+ ((mng_mpngp)pChunkto)->iFramessize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_MPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ASSIGN_CHUNK_HDR (mng_assign_ahdr)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_AHDR, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_ahDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_ahdrp)pChunkto)->iNumframes = ((mng_ahdrp)pChunkfrom)->iNumframes;
+ ((mng_ahdrp)pChunkto)->iTickspersec = ((mng_ahdrp)pChunkfrom)->iTickspersec;
+ ((mng_ahdrp)pChunkto)->iNumplays = ((mng_ahdrp)pChunkfrom)->iNumplays;
+ ((mng_ahdrp)pChunkto)->iTilewidth = ((mng_ahdrp)pChunkfrom)->iTilewidth;
+ ((mng_ahdrp)pChunkto)->iTileheight = ((mng_ahdrp)pChunkfrom)->iTileheight;
+ ((mng_ahdrp)pChunkto)->iInterlace = ((mng_ahdrp)pChunkfrom)->iInterlace;
+ ((mng_ahdrp)pChunkto)->iStillused = ((mng_ahdrp)pChunkfrom)->iStillused;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_AHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ASSIGN_CHUNK_HDR (mng_assign_adat)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ADAT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_adAT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_adatp)pChunkto)->iTilessize = ((mng_adatp)pChunkfrom)->iTilessize;
+
+ if (((mng_adatp)pChunkto)->iTilessize)
+ {
+ MNG_ALLOC (pData, ((mng_adatp)pChunkto)->pTiles, ((mng_adatp)pChunkto)->iTilessize);
+ MNG_COPY (((mng_adatp)pChunkto)->pTiles, ((mng_adatp)pChunkfrom)->pTiles,
+ ((mng_adatp)pChunkto)->iTilessize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_ADAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+ASSIGN_CHUNK_HDR (mng_assign_evnt)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_EVNT, MNG_LC_START);
+#endif
+
+ if (((mng_chunk_headerp)pChunkfrom)->iChunkname != MNG_UINT_evNT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK); /* ouch */
+
+ ((mng_evntp)pChunkto)->iCount = ((mng_evntp)pChunkfrom)->iCount;
+
+ if (((mng_evntp)pChunkto)->iCount)
+ {
+ mng_uint32 iX;
+ mng_evnt_entryp pEntry;
+ mng_uint32 iLen = ((mng_evntp)pChunkto)->iCount * sizeof (mng_evnt_entry);
+
+ MNG_ALLOC (pData, ((mng_evntp)pChunkto)->pEntries, iLen);
+ MNG_COPY (((mng_evntp)pChunkto)->pEntries, ((mng_evntp)pChunkfrom)->pEntries, iLen);
+
+ pEntry = ((mng_evntp)pChunkto)->pEntries;
+
+ for (iX = 0; iX < ((mng_evntp)pChunkto)->iCount; iX++)
+ {
+ if (pEntry->iSegmentnamesize)
+ {
+ mng_pchar pTemp = pEntry->zSegmentname;
+
+ MNG_ALLOC (pData, pEntry->zSegmentname, pEntry->iSegmentnamesize+1);
+ MNG_COPY (pEntry->zSegmentname, pTemp, pEntry->iSegmentnamesize);
+ }
+ else
+ {
+ pEntry->zSegmentname = MNG_NULL;
+ }
+
+ pEntry++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_EVNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+ASSIGN_CHUNK_HDR (mng_assign_unknown)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_UNKNOWN, MNG_LC_START);
+#endif
+
+ ((mng_unknown_chunkp)pChunkto)->iDatasize = ((mng_unknown_chunkp)pChunkfrom)->iDatasize;
+
+ if (((mng_unknown_chunkp)pChunkto)->iDatasize)
+ {
+ MNG_ALLOC (pData, ((mng_unknown_chunkp)pChunkto)->pData, ((mng_unknown_chunkp)pChunkto)->iDatasize);
+ MNG_COPY (((mng_unknown_chunkp)pChunkto)->pData, ((mng_unknown_chunkp)pChunkfrom)->pData,
+ ((mng_unknown_chunkp)pChunkto)->iDatasize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ASSIGN_UNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_chunk_prc.h b/Source/LibMNG/libmng_chunk_prc.h
new file mode 100644
index 0000000..0cf0f3c
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_prc.h
@@ -0,0 +1,381 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_prc.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk initialization & cleanup (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : definition of the chunk initialization & cleanup routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added NO_DELTA_PNG support * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_chunk_prc_h_
+#define _libmng_chunk_prc_h_
+
+/* ************************************************************************** */
+
+void mng_add_chunk (mng_datap pData,
+ mng_chunkp pChunk);
+
+/* ************************************************************************** */
+
+#define INIT_CHUNK_HDR(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pHeader, \
+ mng_chunkp* ppChunk)
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+INIT_CHUNK_HDR (mng_init_general) ;
+#else
+INIT_CHUNK_HDR (mng_init_ihdr) ;
+INIT_CHUNK_HDR (mng_init_plte) ;
+INIT_CHUNK_HDR (mng_init_idat) ;
+INIT_CHUNK_HDR (mng_init_iend) ;
+INIT_CHUNK_HDR (mng_init_trns) ;
+INIT_CHUNK_HDR (mng_init_gama) ;
+INIT_CHUNK_HDR (mng_init_chrm) ;
+INIT_CHUNK_HDR (mng_init_srgb) ;
+INIT_CHUNK_HDR (mng_init_iccp) ;
+INIT_CHUNK_HDR (mng_init_text) ;
+INIT_CHUNK_HDR (mng_init_ztxt) ;
+INIT_CHUNK_HDR (mng_init_itxt) ;
+INIT_CHUNK_HDR (mng_init_bkgd) ;
+INIT_CHUNK_HDR (mng_init_phys) ;
+INIT_CHUNK_HDR (mng_init_sbit) ;
+INIT_CHUNK_HDR (mng_init_splt) ;
+INIT_CHUNK_HDR (mng_init_hist) ;
+INIT_CHUNK_HDR (mng_init_time) ;
+INIT_CHUNK_HDR (mng_init_mhdr) ;
+INIT_CHUNK_HDR (mng_init_mend) ;
+INIT_CHUNK_HDR (mng_init_loop) ;
+INIT_CHUNK_HDR (mng_init_endl) ;
+INIT_CHUNK_HDR (mng_init_defi) ;
+INIT_CHUNK_HDR (mng_init_basi) ;
+INIT_CHUNK_HDR (mng_init_clon) ;
+#ifndef MNG_SKIPCHUNK_PAST
+INIT_CHUNK_HDR (mng_init_past) ;
+#endif
+INIT_CHUNK_HDR (mng_init_disc) ;
+INIT_CHUNK_HDR (mng_init_back) ;
+INIT_CHUNK_HDR (mng_init_fram) ;
+INIT_CHUNK_HDR (mng_init_move) ;
+INIT_CHUNK_HDR (mng_init_clip) ;
+INIT_CHUNK_HDR (mng_init_show) ;
+INIT_CHUNK_HDR (mng_init_term) ;
+INIT_CHUNK_HDR (mng_init_save) ;
+INIT_CHUNK_HDR (mng_init_seek) ;
+INIT_CHUNK_HDR (mng_init_expi) ;
+INIT_CHUNK_HDR (mng_init_fpri) ;
+INIT_CHUNK_HDR (mng_init_need) ;
+INIT_CHUNK_HDR (mng_init_phyg) ;
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_jhdr) ;
+INIT_CHUNK_HDR (mng_init_jdaa) ;
+INIT_CHUNK_HDR (mng_init_jdat) ;
+INIT_CHUNK_HDR (mng_init_jsep) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+INIT_CHUNK_HDR (mng_init_dhdr) ;
+INIT_CHUNK_HDR (mng_init_prom) ;
+INIT_CHUNK_HDR (mng_init_ipng) ;
+INIT_CHUNK_HDR (mng_init_pplt) ;
+#ifdef MNG_INCLUDE_JNG
+INIT_CHUNK_HDR (mng_init_ijng) ;
+#endif
+INIT_CHUNK_HDR (mng_init_drop) ;
+INIT_CHUNK_HDR (mng_init_dbyk) ;
+INIT_CHUNK_HDR (mng_init_ordr) ;
+#endif
+INIT_CHUNK_HDR (mng_init_magn) ;
+INIT_CHUNK_HDR (mng_init_evnt) ;
+INIT_CHUNK_HDR (mng_init_unknown) ;
+#endif /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+/* ************************************************************************** */
+
+#define FREE_CHUNK_HDR(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pHeader)
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+FREE_CHUNK_HDR (mng_free_general) ;
+#else /* MNG_OPTIMIZE_CHUNKINITFREE */
+FREE_CHUNK_HDR (mng_free_ihdr) ;
+FREE_CHUNK_HDR (mng_free_plte) ;
+FREE_CHUNK_HDR (mng_free_iend) ;
+FREE_CHUNK_HDR (mng_free_trns) ;
+FREE_CHUNK_HDR (mng_free_gama) ;
+FREE_CHUNK_HDR (mng_free_chrm) ;
+FREE_CHUNK_HDR (mng_free_srgb) ;
+FREE_CHUNK_HDR (mng_free_bkgd) ;
+FREE_CHUNK_HDR (mng_free_phys) ;
+FREE_CHUNK_HDR (mng_free_sbit) ;
+FREE_CHUNK_HDR (mng_free_hist) ;
+FREE_CHUNK_HDR (mng_free_time) ;
+FREE_CHUNK_HDR (mng_free_mhdr) ;
+FREE_CHUNK_HDR (mng_free_mend) ;
+FREE_CHUNK_HDR (mng_free_endl) ;
+FREE_CHUNK_HDR (mng_free_defi) ;
+FREE_CHUNK_HDR (mng_free_basi) ;
+FREE_CHUNK_HDR (mng_free_clon) ;
+FREE_CHUNK_HDR (mng_free_back) ;
+FREE_CHUNK_HDR (mng_free_move) ;
+FREE_CHUNK_HDR (mng_free_clip) ;
+FREE_CHUNK_HDR (mng_free_show) ;
+FREE_CHUNK_HDR (mng_free_term) ;
+FREE_CHUNK_HDR (mng_free_fpri) ;
+FREE_CHUNK_HDR (mng_free_phyg) ;
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jhdr) ;
+FREE_CHUNK_HDR (mng_free_jsep) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_dhdr) ;
+FREE_CHUNK_HDR (mng_free_prom) ;
+FREE_CHUNK_HDR (mng_free_ipng) ;
+FREE_CHUNK_HDR (mng_free_pplt) ;
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_ijng) ;
+#endif
+#endif
+FREE_CHUNK_HDR (mng_free_magn) ;
+#endif /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+FREE_CHUNK_HDR (mng_free_idat) ;
+FREE_CHUNK_HDR (mng_free_iccp) ;
+FREE_CHUNK_HDR (mng_free_text) ;
+FREE_CHUNK_HDR (mng_free_ztxt) ;
+FREE_CHUNK_HDR (mng_free_itxt) ;
+FREE_CHUNK_HDR (mng_free_splt) ;
+FREE_CHUNK_HDR (mng_free_loop) ;
+#ifndef MNG_SKIPCHUNK_PAST
+FREE_CHUNK_HDR (mng_free_past) ;
+#endif
+FREE_CHUNK_HDR (mng_free_disc) ;
+FREE_CHUNK_HDR (mng_free_fram) ;
+FREE_CHUNK_HDR (mng_free_save) ;
+FREE_CHUNK_HDR (mng_free_seek) ;
+FREE_CHUNK_HDR (mng_free_expi) ;
+FREE_CHUNK_HDR (mng_free_need) ;
+#ifdef MNG_INCLUDE_JNG
+FREE_CHUNK_HDR (mng_free_jdaa) ;
+FREE_CHUNK_HDR (mng_free_jdat) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+FREE_CHUNK_HDR (mng_free_drop) ;
+FREE_CHUNK_HDR (mng_free_dbyk) ;
+FREE_CHUNK_HDR (mng_free_ordr) ;
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+FREE_CHUNK_HDR (mng_free_mpng) ;
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+FREE_CHUNK_HDR (mng_free_adat) ;
+#endif
+FREE_CHUNK_HDR (mng_free_evnt) ;
+FREE_CHUNK_HDR (mng_free_unknown) ;
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+#define ASSIGN_CHUNK_HDR(n) mng_retcode n (mng_datap pData, \
+ mng_chunkp pChunkto, \
+ mng_chunkp pChunkfrom)
+
+#ifdef MNG_OPTIMIZE_CHUNKASSIGN
+ASSIGN_CHUNK_HDR (mng_assign_general) ;
+#else /* MNG_OPTIMIZE_CHUNKASSIGN */
+ASSIGN_CHUNK_HDR (mng_assign_ihdr) ;
+ASSIGN_CHUNK_HDR (mng_assign_plte) ;
+ASSIGN_CHUNK_HDR (mng_assign_iend) ;
+ASSIGN_CHUNK_HDR (mng_assign_trns) ;
+ASSIGN_CHUNK_HDR (mng_assign_gama) ;
+ASSIGN_CHUNK_HDR (mng_assign_chrm) ;
+ASSIGN_CHUNK_HDR (mng_assign_srgb) ;
+ASSIGN_CHUNK_HDR (mng_assign_bkgd) ;
+ASSIGN_CHUNK_HDR (mng_assign_phys) ;
+ASSIGN_CHUNK_HDR (mng_assign_sbit) ;
+ASSIGN_CHUNK_HDR (mng_assign_hist) ;
+ASSIGN_CHUNK_HDR (mng_assign_time) ;
+ASSIGN_CHUNK_HDR (mng_assign_mhdr) ;
+ASSIGN_CHUNK_HDR (mng_assign_mend) ;
+ASSIGN_CHUNK_HDR (mng_assign_endl) ;
+ASSIGN_CHUNK_HDR (mng_assign_defi) ;
+ASSIGN_CHUNK_HDR (mng_assign_basi) ;
+ASSIGN_CHUNK_HDR (mng_assign_clon) ;
+ASSIGN_CHUNK_HDR (mng_assign_back) ;
+ASSIGN_CHUNK_HDR (mng_assign_move) ;
+ASSIGN_CHUNK_HDR (mng_assign_clip) ;
+ASSIGN_CHUNK_HDR (mng_assign_show) ;
+ASSIGN_CHUNK_HDR (mng_assign_term) ;
+ASSIGN_CHUNK_HDR (mng_assign_fpri) ;
+ASSIGN_CHUNK_HDR (mng_assign_phyg) ;
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jhdr) ;
+ASSIGN_CHUNK_HDR (mng_assign_jsep) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_dhdr) ;
+ASSIGN_CHUNK_HDR (mng_assign_prom) ;
+ASSIGN_CHUNK_HDR (mng_assign_ipng) ;
+ASSIGN_CHUNK_HDR (mng_assign_pplt) ;
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_ijng) ;
+#endif
+#endif
+ASSIGN_CHUNK_HDR (mng_assign_magn) ;
+#endif /* MNG_OPTIMIZE_CHUNKASSIGN */
+
+ASSIGN_CHUNK_HDR (mng_assign_idat) ;
+ASSIGN_CHUNK_HDR (mng_assign_iccp) ;
+ASSIGN_CHUNK_HDR (mng_assign_text) ;
+ASSIGN_CHUNK_HDR (mng_assign_ztxt) ;
+ASSIGN_CHUNK_HDR (mng_assign_itxt) ;
+ASSIGN_CHUNK_HDR (mng_assign_splt) ;
+ASSIGN_CHUNK_HDR (mng_assign_loop) ;
+#ifndef MNG_SKIPCHUNK_PAST
+ASSIGN_CHUNK_HDR (mng_assign_past) ;
+#endif
+ASSIGN_CHUNK_HDR (mng_assign_disc) ;
+ASSIGN_CHUNK_HDR (mng_assign_fram) ;
+ASSIGN_CHUNK_HDR (mng_assign_save) ;
+ASSIGN_CHUNK_HDR (mng_assign_seek) ;
+ASSIGN_CHUNK_HDR (mng_assign_need) ;
+ASSIGN_CHUNK_HDR (mng_assign_expi) ;
+#ifdef MNG_INCLUDE_JNG
+ASSIGN_CHUNK_HDR (mng_assign_jdaa) ;
+ASSIGN_CHUNK_HDR (mng_assign_jdat) ;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ASSIGN_CHUNK_HDR (mng_assign_drop) ;
+ASSIGN_CHUNK_HDR (mng_assign_dbyk) ;
+ASSIGN_CHUNK_HDR (mng_assign_ordr) ;
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ASSIGN_CHUNK_HDR (mng_assign_mpng) ;
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ASSIGN_CHUNK_HDR (mng_assign_ahdr) ;
+ASSIGN_CHUNK_HDR (mng_assign_adat) ;
+#endif
+ASSIGN_CHUNK_HDR (mng_assign_evnt) ;
+ASSIGN_CHUNK_HDR (mng_assign_unknown) ;
+
+/* ************************************************************************** */
+
+#else /* MNG_INCLUDE_WRITE_PROCS */
+#define mng_assign_general 0
+#define mng_assign_ihdr 0
+#define mng_assign_plte 0
+#define mng_assign_idat 0
+#define mng_assign_iend 0
+#define mng_assign_trns 0
+#define mng_assign_gama 0
+#define mng_assign_chrm 0
+#define mng_assign_srgb 0
+#define mng_assign_iccp 0
+#define mng_assign_text 0
+#define mng_assign_ztxt 0
+#define mng_assign_itxt 0
+#define mng_assign_bkgd 0
+#define mng_assign_phys 0
+#define mng_assign_sbit 0
+#define mng_assign_splt 0
+#define mng_assign_hist 0
+#define mng_assign_time 0
+#define mng_assign_mhdr 0
+#define mng_assign_mend 0
+#define mng_assign_loop 0
+#define mng_assign_endl 0
+#define mng_assign_defi 0
+#define mng_assign_basi 0
+#define mng_assign_clon 0
+#ifndef MNG_SKIPCHUNK_PAST
+#define mng_assign_past 0
+#endif
+#define mng_assign_disc 0
+#define mng_assign_back 0
+#define mng_assign_fram 0
+#define mng_assign_move 0
+#define mng_assign_clip 0
+#define mng_assign_show 0
+#define mng_assign_term 0
+#define mng_assign_save 0
+#define mng_assign_seek 0
+#define mng_assign_expi 0
+#define mng_assign_fpri 0
+#define mng_assign_phyg 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_assign_jhdr 0
+#define mng_assign_jdaa 0
+#define mng_assign_jdat 0
+#define mng_assign_jsep 0
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#define mng_assign_dhdr 0
+#define mng_assign_prom 0
+#define mng_assign_ipng 0
+#define mng_assign_pplt 0
+#ifdef MNG_INCLUDE_JNG
+#define mng_assign_ijng 0
+#endif
+#define mng_assign_drop 0
+#define mng_assign_dbyk 0
+#define mng_assign_ordr 0
+#endif
+#define mng_assign_magn 0
+#define mng_assign_need 0
+#define mng_assign_mpng 0
+#define mng_assign_ahdr 0
+#define mng_assign_adat 0
+#define mng_assign_evnt 0
+#define mng_assign_unknown 0
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_chunk_prc_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_chunk_xs.c b/Source/LibMNG/libmng_chunk_xs.c
new file mode 100644
index 0000000..1311409
--- /dev/null
+++ b/Source/LibMNG/libmng_chunk_xs.c
@@ -0,0 +1,7016 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunk_xs.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : chunk access functions (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the chunk access functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - changed and filled iterate-chunk function * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - fixed calling convention * */
+/* * - added getchunk functions * */
+/* * - added putchunk functions * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added empty-chunk put-routines * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * 0.5.1 - 05/15/2000 - G.Juyn * */
+/* * - added getimgdata & putimgdata functions * */
+/* * * */
+/* * 0.5.2 - 05/19/2000 - G.Juyn * */
+/* * - B004 - fixed problem with MNG_SUPPORT_WRITE not defined * */
+/* * also for MNG_SUPPORT_WRITE without MNG_INCLUDE_JNG * */
+/* * - Cleaned up some code regarding mixed support * */
+/* * * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - fixed creation-code * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * - added function to set simplicity field * */
+/* * - fixed putchunk_unknown() function * */
+/* * * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - fixed putchunk_plte() to set bEmpty parameter * */
+/* * * */
+/* * 0.9.5 - 01/25/2001 - G.Juyn * */
+/* * - fixed some small compiler warnings (thanks Nikki) * */
+/* * * */
+/* * 1.0.5 - 09/07/2002 - G.Juyn * */
+/* * - B578940 - unimplemented functions return errorcode * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added check for TERM placement during create/write * */
+/* * 1.0.5 - 11/28/2002 - G.Juyn * */
+/* * - fixed definition of iMethodX/Y for MAGN chunk * */
+/* * * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added MNG_NO_DELTA_PNG reduction and more SKIPCHUNK * */
+/* * optimizations * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added conditionals around non-VLC chunk support * */
+/* * * */
+/* * 1.0.8 - 04/01/2004 - G.Juyn * */
+/* * - added missing get-/put-chunk-jdaa * */
+/* * 1.0.8 - 08/02/2004 - G.Juyn * */
+/* * - added conditional to allow easier writing of large MNG's * */
+/* * * */
+/* * 1.0.9 - 09/17/2004 - G.R-P * */
+/* * - added two more conditionals * */
+/* * 1.0.9 - 09/25/2004 - G.Juyn * */
+/* * - replaced MNG_TWEAK_LARGE_FILES with permanent solution * */
+/* * 1.0.9 - 17/14/2004 - G.Juyn * */
+/* * - fixed PPLT getchunk/putchunk routines * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_chunks.h"
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+#include "libmng_chunk_descr.h"
+#endif
+#include "libmng_chunk_prc.h"
+#include "libmng_chunk_io.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_ACCESS_CHUNKS
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_iterate_chunks (mng_handle hHandle,
+ mng_uint32 iChunkseq,
+ mng_iteratechunk fProc)
+{
+ mng_uint32 iSeq;
+ mng_chunkid iChunkname;
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_bool bCont;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_ITERATE_CHUNKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ iSeq = 0;
+ bCont = MNG_TRUE;
+ pChunk = pData->pFirstchunk; /* get the first chunk */
+ /* as long as there are some more */
+ while ((pChunk) && (bCont)) /* and the app didn't signal a stop */
+ {
+ if (iSeq >= iChunkseq) /* reached the first target ? */
+ { /* then call this and next ones back in... */
+ iChunkname = ((mng_chunk_headerp)pChunk)->iChunkname;
+ bCont = fProc (hHandle, (mng_handle)pChunk, iChunkname, iSeq);
+ }
+
+ iSeq++; /* next one */
+ pChunk = ((mng_chunk_headerp)pChunk)->pNext;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_ITERATE_CHUNKS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_copy_chunk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_handle hHandleOut)
+{
+ mng_datap pDataOut;
+ mng_chunkp pChunk;
+ mng_chunkp pChunkOut;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_COPY_CHUNK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handles */
+ MNG_VALIDHANDLE (hHandleOut)
+
+ pDataOut = (mng_datap)hHandleOut; /* make outhandle addressable */
+ pChunk = (mng_chunkp)hChunk; /* address the chunk */
+
+ if (!pDataOut->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pDataOut, MNG_FUNCTIONINVALID)
+ /* create a new chunk */
+ iRetcode = ((mng_createchunk)((mng_chunk_headerp)pChunk)->fCreate)
+ (pDataOut, ((mng_chunk_headerp)pChunk), &pChunkOut);
+ if (!iRetcode) /* assign the chunk-specific data */
+ iRetcode = ((mng_assignchunk)((mng_chunk_headerp)pChunk)->fAssign)
+ (pDataOut, pChunkOut, pChunk);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pDataOut, pChunkOut); /* and put it in the output-stream */
+
+ /* could it be the end of the chain ? */
+ if (((mng_chunk_headerp)pChunkOut)->iChunkname == MNG_UINT_IEND)
+ {
+#ifdef MNG_INCLUDE_JNG
+ if ((pDataOut->iFirstchunkadded == MNG_UINT_IHDR) ||
+ (pDataOut->iFirstchunkadded == MNG_UINT_JHDR) )
+#else
+ if (pDataOut->iFirstchunkadded == MNG_UINT_IHDR)
+#endif
+ pDataOut->bCreating = MNG_FALSE; /* right; this should be the last chunk !!! */
+ }
+
+ if (((mng_chunk_headerp)pChunkOut)->iChunkname == MNG_UINT_MEND)
+ pDataOut->bCreating = MNG_FALSE; /* definitely this should be the last !!! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_COPY_CHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_ihdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iBitdepth,
+ mng_uint8 *iColortype,
+ mng_uint8 *iCompression,
+ mng_uint8 *iFilter,
+ mng_uint8 *iInterlace)
+{
+ mng_datap pData;
+ mng_ihdrp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_IHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ihdrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_IHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iWidth = pChunk->iWidth; /* fill the fields */
+ *iHeight = pChunk->iHeight;
+ *iBitdepth = pChunk->iBitdepth;
+ *iColortype = pChunk->iColortype;
+ *iCompression = pChunk->iCompression;
+ *iFilter = pChunk->iFilter;
+ *iInterlace = pChunk->iInterlace;
+
+ /* fill the chunk */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_plte (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_palette8 *aPalette)
+{
+ mng_datap pData;
+ mng_pltep pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PLTE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_pltep)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PLTE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iCount = pChunk->iEntrycount; /* fill the fields */
+
+ MNG_COPY (*aPalette, pChunk->aEntries, sizeof (mng_palette8));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_idat (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata)
+{
+ mng_datap pData;
+ mng_idatp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_IDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_idatp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_IDAT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iRawlen = pChunk->iDatasize; /* fill the fields */
+ *pRawdata = pChunk->pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_trns (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_bool *bGlobal,
+ mng_uint8 *iType,
+ mng_uint32 *iCount,
+ mng_uint8arr *aAlphas,
+ mng_uint16 *iGray,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint32 *iRawlen,
+ mng_uint8arr *aRawdata)
+{
+ mng_datap pData;
+ mng_trnsp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TRNS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_trnsp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_tRNS)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *bGlobal = pChunk->bGlobal;
+ *iType = pChunk->iType;
+ *iCount = pChunk->iCount;
+ *iGray = pChunk->iGray;
+ *iRed = pChunk->iRed;
+ *iGreen = pChunk->iGreen;
+ *iBlue = pChunk->iBlue;
+ *iRawlen = pChunk->iRawlen;
+
+ MNG_COPY (*aAlphas, pChunk->aEntries, sizeof (mng_uint8arr));
+ MNG_COPY (*aRawdata, pChunk->aRawdata, sizeof (mng_uint8arr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_gAMA
+mng_retcode MNG_DECL mng_getchunk_gama (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iGamma)
+{
+ mng_datap pData;
+ mng_gamap pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_GAMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_gamap)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_gAMA)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iGamma = pChunk->iGamma;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_retcode MNG_DECL mng_getchunk_chrm (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iWhitepointx,
+ mng_uint32 *iWhitepointy,
+ mng_uint32 *iRedx,
+ mng_uint32 *iRedy,
+ mng_uint32 *iGreenx,
+ mng_uint32 *iGreeny,
+ mng_uint32 *iBluex,
+ mng_uint32 *iBluey)
+{
+ mng_datap pData;
+ mng_chrmp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CHRM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_chrmp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_cHRM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iWhitepointx = pChunk->iWhitepointx;
+ *iWhitepointy = pChunk->iWhitepointy;
+ *iRedx = pChunk->iRedx;
+ *iRedy = pChunk->iRedy;
+ *iGreenx = pChunk->iGreenx;
+ *iGreeny = pChunk->iGreeny;
+ *iBluex = pChunk->iBluex;
+ *iBluey = pChunk->iBluey;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sRGB
+mng_retcode MNG_DECL mng_getchunk_srgb (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iRenderingintent)
+{
+ mng_datap pData;
+ mng_srgbp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_srgbp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_sRGB)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iRenderingintent = pChunk->iRenderingintent;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode MNG_DECL mng_getchunk_iccp (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iCompression,
+ mng_uint32 *iProfilesize,
+ mng_ptr *pProfile)
+{
+ mng_datap pData;
+ mng_iccpp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ICCP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_iccpp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_iCCP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iNamesize = pChunk->iNamesize;
+ *zName = pChunk->zName;
+ *iCompression = pChunk->iCompression;
+ *iProfilesize = pChunk->iProfilesize;
+ *pProfile = pChunk->pProfile;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+mng_retcode MNG_DECL mng_getchunk_text (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText)
+{
+ mng_datap pData;
+ mng_textp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TEXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_textp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_tEXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iKeywordsize = pChunk->iKeywordsize;
+ *zKeyword = pChunk->zKeyword;
+ *iTextsize = pChunk->iTextsize;
+ *zText = pChunk->zText;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+mng_retcode MNG_DECL mng_getchunk_ztxt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint8 *iCompression,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText)
+{
+ mng_datap pData;
+ mng_ztxtp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ZTXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ztxtp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_zTXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iKeywordsize = pChunk->iKeywordsize;
+ *zKeyword = pChunk->zKeyword;
+ *iCompression = pChunk->iCompression;
+ *iTextsize = pChunk->iTextsize;
+ *zText = pChunk->zText;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ZTXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+mng_retcode MNG_DECL mng_getchunk_itxt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordsize,
+ mng_pchar *zKeyword,
+ mng_uint8 *iCompressionflag,
+ mng_uint8 *iCompressionmethod,
+ mng_uint32 *iLanguagesize,
+ mng_pchar *zLanguage,
+ mng_uint32 *iTranslationsize,
+ mng_pchar *zTranslation,
+ mng_uint32 *iTextsize,
+ mng_pchar *zText)
+{
+ mng_datap pData;
+ mng_itxtp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ITXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_itxtp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_iTXt)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iKeywordsize = pChunk->iKeywordsize;
+ *zKeyword = pChunk->zKeyword;
+ *iCompressionflag = pChunk->iCompressionflag;
+ *iCompressionmethod = pChunk->iCompressionmethod;
+ *iLanguagesize = pChunk->iLanguagesize;
+ *zLanguage = pChunk->zLanguage;
+ *iTranslationsize = pChunk->iTranslationsize;
+ *zTranslation = pChunk->zTranslation;
+ *iTextsize = pChunk->iTextsize;
+ *zText = pChunk->zText;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+mng_retcode MNG_DECL mng_getchunk_bkgd (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iType,
+ mng_uint8 *iIndex,
+ mng_uint16 *iGray,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue)
+{
+ mng_datap pData;
+ mng_bkgdp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BKGD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_bkgdp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_bKGD)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iType = pChunk->iType;
+ *iIndex = pChunk->iIndex;
+ *iGray = pChunk->iGray;
+ *iRed = pChunk->iRed;
+ *iGreen = pChunk->iGreen;
+ *iBlue = pChunk->iBlue;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+mng_retcode MNG_DECL mng_getchunk_phys (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iSizex,
+ mng_uint32 *iSizey,
+ mng_uint8 *iUnit)
+{
+ mng_datap pData;
+ mng_physp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PHYS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_physp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_pHYs)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iSizex = pChunk->iSizex;
+ *iSizey = pChunk->iSizey;
+ *iUnit = pChunk->iUnit;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+mng_retcode MNG_DECL mng_getchunk_sbit (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iType,
+ mng_uint8arr4 *aBits)
+{
+ mng_datap pData;
+ mng_sbitp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SBIT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_sbitp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_sBIT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty;
+ *iType = pChunk->iType;
+ (*aBits)[0] = pChunk->aBits[0];
+ (*aBits)[1] = pChunk->aBits[1];
+ (*aBits)[2] = pChunk->aBits[2];
+ (*aBits)[3] = pChunk->aBits[3];
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+mng_retcode MNG_DECL mng_getchunk_splt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iSampledepth,
+ mng_uint32 *iEntrycount,
+ mng_ptr *pEntries)
+{
+ mng_datap pData;
+ mng_spltp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SPLT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_spltp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_sPLT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iNamesize = pChunk->iNamesize;
+ *zName = pChunk->zName;
+ *iSampledepth = pChunk->iSampledepth;
+ *iEntrycount = pChunk->iEntrycount;
+ *pEntries = pChunk->pEntries;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+mng_retcode MNG_DECL mng_getchunk_hist (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iEntrycount,
+ mng_uint16arr *aEntries)
+{
+ mng_datap pData;
+ mng_histp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_HIST, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_histp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_hIST)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iEntrycount = pChunk->iEntrycount; /* fill the fields */
+
+ MNG_COPY (*aEntries, pChunk->aEntries, sizeof (mng_uint16arr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+mng_retcode MNG_DECL mng_getchunk_time (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iYear,
+ mng_uint8 *iMonth,
+ mng_uint8 *iDay,
+ mng_uint8 *iHour,
+ mng_uint8 *iMinute,
+ mng_uint8 *iSecond)
+{
+ mng_datap pData;
+ mng_timep pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TIME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_timep)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_tIME)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iYear = pChunk->iYear; /* fill the fields */
+ *iMonth = pChunk->iMonth;
+ *iDay = pChunk->iDay;
+ *iHour = pChunk->iHour;
+ *iMinute = pChunk->iMinute;
+ *iSecond = pChunk->iSecond;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_mhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint32 *iTicks,
+ mng_uint32 *iLayercount,
+ mng_uint32 *iFramecount,
+ mng_uint32 *iPlaytime,
+ mng_uint32 *iSimplicity)
+{
+ mng_datap pData;
+ mng_mhdrp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_mhdrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iWidth = pChunk->iWidth; /* fill the fields */
+ *iHeight = pChunk->iHeight;
+ *iTicks = pChunk->iTicks;
+ *iLayercount = pChunk->iLayercount;
+ *iFramecount = pChunk->iFramecount;
+ *iPlaytime = pChunk->iPlaytime;
+ *iSimplicity = pChunk->iSimplicity;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+mng_retcode MNG_DECL mng_getchunk_loop (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iLevel,
+ mng_uint32 *iRepeat,
+ mng_uint8 *iTermination,
+ mng_uint32 *iItermin,
+ mng_uint32 *iItermax,
+ mng_uint32 *iCount,
+ mng_uint32p *pSignals)
+{
+ mng_datap pData;
+ mng_loopp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_LOOP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_loopp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_LOOP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iLevel = pChunk->iLevel; /* fill teh fields */
+ *iRepeat = pChunk->iRepeat;
+ *iTermination = pChunk->iTermination;
+ *iItermin = pChunk->iItermin;
+ *iItermax = pChunk->iItermax;
+ *iCount = pChunk->iCount;
+ *pSignals = pChunk->pSignals;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_endl (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iLevel)
+{
+ mng_datap pData;
+ mng_endlp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ENDL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_endlp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_ENDL)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iLevel = pChunk->iLevel; /* fill the field */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+mng_retcode MNG_DECL mng_getchunk_defi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iDonotshow,
+ mng_uint8 *iConcrete,
+ mng_bool *bHasloca,
+ mng_int32 *iXlocation,
+ mng_int32 *iYlocation,
+ mng_bool *bHasclip,
+ mng_int32 *iLeftcb,
+ mng_int32 *iRightcb,
+ mng_int32 *iTopcb,
+ mng_int32 *iBottomcb)
+{
+ mng_datap pData;
+ mng_defip pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DEFI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_defip)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_DEFI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iObjectid = pChunk->iObjectid; /* fill the fields */
+ *iDonotshow = pChunk->iDonotshow;
+ *iConcrete = pChunk->iConcrete;
+ *bHasloca = pChunk->bHasloca;
+ *iXlocation = pChunk->iXlocation;
+ *iYlocation = pChunk->iYlocation;
+ *bHasclip = pChunk->bHasclip;
+ *iLeftcb = pChunk->iLeftcb;
+ *iRightcb = pChunk->iRightcb;
+ *iTopcb = pChunk->iTopcb;
+ *iBottomcb = pChunk->iBottomcb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+mng_retcode MNG_DECL mng_getchunk_basi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iBitdepth,
+ mng_uint8 *iColortype,
+ mng_uint8 *iCompression,
+ mng_uint8 *iFilter,
+ mng_uint8 *iInterlace,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint16 *iAlpha,
+ mng_uint8 *iViewable)
+{
+ mng_datap pData;
+ mng_basip pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BASI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_basip)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_BASI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iWidth = pChunk->iWidth; /* fill the fields */
+ *iHeight = pChunk->iHeight;
+ *iBitdepth = pChunk->iBitdepth;
+ *iColortype = pChunk->iColortype;
+ *iCompression = pChunk->iCompression;
+ *iFilter = pChunk->iFilter;
+ *iInterlace = pChunk->iInterlace;
+ *iRed = pChunk->iRed;
+ *iGreen = pChunk->iGreen;
+ *iBlue = pChunk->iBlue;
+ *iAlpha = pChunk->iAlpha;
+ *iViewable = pChunk->iViewable;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+mng_retcode MNG_DECL mng_getchunk_clon (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iSourceid,
+ mng_uint16 *iCloneid,
+ mng_uint8 *iClonetype,
+ mng_uint8 *iDonotshow,
+ mng_uint8 *iConcrete,
+ mng_bool *bHasloca,
+ mng_uint8 *iLocationtype,
+ mng_int32 *iLocationx,
+ mng_int32 *iLocationy)
+{
+ mng_datap pData;
+ mng_clonp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CLON, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_clonp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_CLON)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iSourceid = pChunk->iSourceid; /* fill the fields */
+ *iCloneid = pChunk->iCloneid;
+ *iClonetype = pChunk->iClonetype;
+ *iDonotshow = pChunk->iDonotshow;
+ *iConcrete = pChunk->iConcrete;
+ *bHasloca = pChunk->bHasloca;
+ *iLocationtype = pChunk->iLocationtype;
+ *iLocationx = pChunk->iLocationx;
+ *iLocationy = pChunk->iLocationy;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode MNG_DECL mng_getchunk_past (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iDestid,
+ mng_uint8 *iTargettype,
+ mng_int32 *iTargetx,
+ mng_int32 *iTargety,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_pastp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PAST, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_pastp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PAST)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iDestid = pChunk->iDestid; /* fill the fields */
+ *iTargettype = pChunk->iTargettype;
+ *iTargetx = pChunk->iTargetx;
+ *iTargety = pChunk->iTargety;
+ *iCount = pChunk->iCount;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode MNG_DECL mng_getchunk_past_src (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint16 *iSourceid,
+ mng_uint8 *iComposition,
+ mng_uint8 *iOrientation,
+ mng_uint8 *iOffsettype,
+ mng_int32 *iOffsetx,
+ mng_int32 *iOffsety,
+ mng_uint8 *iBoundarytype,
+ mng_int32 *iBoundaryl,
+ mng_int32 *iBoundaryr,
+ mng_int32 *iBoundaryt,
+ mng_int32 *iBoundaryb)
+{
+ mng_datap pData;
+ mng_pastp pChunk;
+ mng_past_sourcep pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PAST_SRC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_pastp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PAST)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ if (iEntry >= pChunk->iCount) /* valid index ? */
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address the entry */
+ pEntry = pChunk->pSources + iEntry;
+
+ *iSourceid = pEntry->iSourceid; /* fill the fields */
+ *iComposition = pEntry->iComposition;
+ *iOrientation = pEntry->iOrientation;
+ *iOffsettype = pEntry->iOffsettype;
+ *iOffsetx = pEntry->iOffsetx;
+ *iOffsety = pEntry->iOffsety;
+ *iBoundarytype = pEntry->iBoundarytype;
+ *iBoundaryl = pEntry->iBoundaryl;
+ *iBoundaryr = pEntry->iBoundaryr;
+ *iBoundaryt = pEntry->iBoundaryt;
+ *iBoundaryb = pEntry->iBoundaryb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PAST_SRC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode MNG_DECL mng_getchunk_disc (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_uint16p *pObjectids)
+{
+ mng_datap pData;
+ mng_discp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DISC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_discp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_DISC)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iCount = pChunk->iCount; /* fill the fields */
+ *pObjectids = pChunk->pObjectids;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+mng_retcode MNG_DECL mng_getchunk_back (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint8 *iMandatory,
+ mng_uint16 *iImageid,
+ mng_uint8 *iTile)
+{
+ mng_datap pData;
+ mng_backp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BACK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_backp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_BACK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iRed = pChunk->iRed; /* fill the fields */
+ *iGreen = pChunk->iGreen;
+ *iBlue = pChunk->iBlue;
+ *iMandatory = pChunk->iMandatory;
+ *iImageid = pChunk->iImageid;
+ *iTile = pChunk->iTile;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+mng_retcode MNG_DECL mng_getchunk_fram (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iMode,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName,
+ mng_uint8 *iChangedelay,
+ mng_uint8 *iChangetimeout,
+ mng_uint8 *iChangeclipping,
+ mng_uint8 *iChangesyncid,
+ mng_uint32 *iDelay,
+ mng_uint32 *iTimeout,
+ mng_uint8 *iBoundarytype,
+ mng_int32 *iBoundaryl,
+ mng_int32 *iBoundaryr,
+ mng_int32 *iBoundaryt,
+ mng_int32 *iBoundaryb,
+ mng_uint32 *iCount,
+ mng_uint32p *pSyncids)
+{
+ mng_datap pData;
+ mng_framp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_FRAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_framp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_FRAM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iMode = pChunk->iMode;
+ *iNamesize = pChunk->iNamesize;
+ *zName = pChunk->zName;
+ *iChangedelay = pChunk->iChangedelay;
+ *iChangetimeout = pChunk->iChangetimeout;
+ *iChangeclipping = pChunk->iChangeclipping;
+ *iChangesyncid = pChunk->iChangesyncid;
+ *iDelay = pChunk->iDelay;
+ *iTimeout = pChunk->iTimeout;
+ *iBoundarytype = pChunk->iBoundarytype;
+ *iBoundaryl = pChunk->iBoundaryl;
+ *iBoundaryr = pChunk->iBoundaryr;
+ *iBoundaryt = pChunk->iBoundaryt;
+ *iBoundaryb = pChunk->iBoundaryb;
+ *iCount = pChunk->iCount;
+ *pSyncids = pChunk->pSyncids;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+mng_retcode MNG_DECL mng_getchunk_move (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iMovetype,
+ mng_int32 *iMovex,
+ mng_int32 *iMovey)
+{
+ mng_datap pData;
+ mng_movep pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MOVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_movep)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_MOVE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iFirstid = pChunk->iFirstid; /* fill the fields */
+ *iLastid = pChunk->iLastid;
+ *iMovetype = pChunk->iMovetype;
+ *iMovex = pChunk->iMovex;
+ *iMovey = pChunk->iMovey;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+mng_retcode MNG_DECL mng_getchunk_clip (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iCliptype,
+ mng_int32 *iClipl,
+ mng_int32 *iClipr,
+ mng_int32 *iClipt,
+ mng_int32 *iClipb)
+{
+ mng_datap pData;
+ mng_clipp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CLIP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_clipp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_CLIP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iFirstid = pChunk->iFirstid; /* fill the fields */
+ *iLastid = pChunk->iLastid;
+ *iCliptype = pChunk->iCliptype;
+ *iClipl = pChunk->iClipl;
+ *iClipr = pChunk->iClipr;
+ *iClipt = pChunk->iClipt;
+ *iClipb = pChunk->iClipb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+mng_retcode MNG_DECL mng_getchunk_show (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint8 *iMode)
+{
+ mng_datap pData;
+ mng_showp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SHOW, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_showp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_SHOW)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iFirstid = pChunk->iFirstid;
+ *iLastid = pChunk->iLastid;
+ *iMode = pChunk->iMode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+mng_retcode MNG_DECL mng_getchunk_term (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iTermaction,
+ mng_uint8 *iIteraction,
+ mng_uint32 *iDelay,
+ mng_uint32 *iItermax)
+{
+ mng_datap pData;
+ mng_termp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TERM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_termp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_TERM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iTermaction = pChunk->iTermaction; /* fill the fields */
+ *iIteraction = pChunk->iIteraction;
+ *iDelay = pChunk->iDelay;
+ *iItermax = pChunk->iItermax;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode MNG_DECL mng_getchunk_save (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint8 *iOffsettype,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_savep pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SAVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_savep)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_SAVE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iOffsettype = pChunk->iOffsettype;
+ *iCount = pChunk->iCount;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_save_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint8 *iEntrytype,
+ mng_uint32arr2 *iOffset,
+ mng_uint32arr2 *iStarttime,
+ mng_uint32 *iLayernr,
+ mng_uint32 *iFramenr,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName)
+{
+ mng_datap pData;
+ mng_savep pChunk;
+ mng_save_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SAVE_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_savep)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_SAVE)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ if (iEntry >= pChunk->iCount) /* valid index ? */
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+
+ pEntry = pChunk->pEntries + iEntry; /* address the entry */
+ /* fill the fields */
+ *iEntrytype = pEntry->iEntrytype;
+ (*iOffset)[0] = pEntry->iOffset[0];
+ (*iOffset)[1] = pEntry->iOffset[1];
+ (*iStarttime)[0] = pEntry->iStarttime[0];
+ (*iStarttime)[1] = pEntry->iStarttime[1];
+ *iLayernr = pEntry->iLayernr;
+ *iFramenr = pEntry->iFramenr;
+ *iNamesize = pEntry->iNamesize;
+ *zName = pEntry->zName;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SAVE_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode MNG_DECL mng_getchunk_seek (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName)
+{
+ mng_datap pData;
+ mng_seekp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SEEK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_seekp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_SEEK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iNamesize = pChunk->iNamesize; /* fill the fields */
+ *zName = pChunk->zName;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+mng_retcode MNG_DECL mng_getchunk_expi (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iSnapshotid,
+ mng_uint32 *iNamesize,
+ mng_pchar *zName)
+{
+ mng_datap pData;
+ mng_expip pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EXPI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_expip)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_eXPI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iSnapshotid = pChunk->iSnapshotid; /* fill the fields */
+ *iNamesize = pChunk->iNamesize;
+ *zName = pChunk->zName;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EXPI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+mng_retcode MNG_DECL mng_getchunk_fpri (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iDeltatype,
+ mng_uint8 *iPriority)
+{
+ mng_datap pData;
+ mng_fprip pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_FPRI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_fprip)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_fPRI)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iDeltatype = pChunk->iDeltatype; /* fill the fields */
+ *iPriority = pChunk->iPriority;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+mng_retcode MNG_DECL mng_getchunk_need (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iKeywordssize,
+ mng_pchar *zKeywords)
+{
+ mng_datap pData;
+ mng_needp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_NEED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_needp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_nEED)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iKeywordssize = pChunk->iKeywordssize;
+ *zKeywords = pChunk->zKeywords;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_NEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+mng_retcode MNG_DECL mng_getchunk_phyg (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_bool *bEmpty,
+ mng_uint32 *iSizex,
+ mng_uint32 *iSizey,
+ mng_uint8 *iUnit)
+{
+ mng_datap pData;
+ mng_phygp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PHYG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_phygp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_pHYg)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *bEmpty = pChunk->bEmpty; /* fill the fields */
+ *iSizex = pChunk->iSizex;
+ *iSizey = pChunk->iSizey;
+ *iUnit = pChunk->iUnit;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_getchunk_jhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_uint8 *iColortype,
+ mng_uint8 *iImagesampledepth,
+ mng_uint8 *iImagecompression,
+ mng_uint8 *iImageinterlace,
+ mng_uint8 *iAlphasampledepth,
+ mng_uint8 *iAlphacompression,
+ mng_uint8 *iAlphafilter,
+ mng_uint8 *iAlphainterlace)
+{
+ mng_datap pData;
+ mng_jhdrp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_jhdrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_JHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iWidth = pChunk->iWidth; /* fill the fields */
+ *iHeight = pChunk->iHeight;
+ *iColortype = pChunk->iColortype;
+ *iImagesampledepth = pChunk->iImagesampledepth;
+ *iImagecompression = pChunk->iImagecompression;
+ *iImageinterlace = pChunk->iImageinterlace;
+ *iAlphasampledepth = pChunk->iAlphasampledepth;
+ *iAlphacompression = pChunk->iAlphacompression;
+ *iAlphafilter = pChunk->iAlphafilter;
+ *iAlphainterlace = pChunk->iAlphainterlace;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_getchunk_jdat (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata)
+{
+ mng_datap pData;
+ mng_jdatp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_jdatp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_JDAT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iRawlen = pChunk->iDatasize; /* fill the fields */
+ *pRawdata = pChunk->pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_getchunk_jdaa (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata)
+{
+ mng_datap pData;
+ mng_jdaap pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JDAA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_jdaap)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_JDAA)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iRawlen = pChunk->iDatasize; /* fill the fields */
+ *pRawdata = pChunk->pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_getchunk_dhdr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iImagetype,
+ mng_uint8 *iDeltatype,
+ mng_uint32 *iBlockwidth,
+ mng_uint32 *iBlockheight,
+ mng_uint32 *iBlockx,
+ mng_uint32 *iBlocky)
+{
+ mng_datap pData;
+ mng_dhdrp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_dhdrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_DHDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iObjectid = pChunk->iObjectid; /* fill the fields */
+ *iImagetype = pChunk->iImagetype;
+ *iDeltatype = pChunk->iDeltatype;
+ *iBlockwidth = pChunk->iBlockwidth;
+ *iBlockheight = pChunk->iBlockheight;
+ *iBlockx = pChunk->iBlockx;
+ *iBlocky = pChunk->iBlocky;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_getchunk_prom (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iColortype,
+ mng_uint8 *iSampledepth,
+ mng_uint8 *iFilltype)
+{
+ mng_datap pData;
+ mng_promp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PROM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_promp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PROM)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iColortype = pChunk->iColortype; /* fill the fields */
+ *iSampledepth = pChunk->iSampledepth;
+ *iFilltype = pChunk->iFilltype;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_getchunk_pplt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint8 *iDeltatype,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_ppltp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PPLT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ppltp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PPLT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iDeltatype = pChunk->iDeltatype; /* fill the fields */
+ *iCount = pChunk->iCount;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_getchunk_pplt_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint16 *iRed,
+ mng_uint16 *iGreen,
+ mng_uint16 *iBlue,
+ mng_uint16 *iAlpha,
+ mng_bool *bUsed)
+{
+ mng_datap pData;
+ mng_ppltp pChunk;
+ mng_pplt_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PPLT_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ppltp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_PPLT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ if (iEntry >= pChunk->iCount) /* valid index ? */
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+
+ pEntry = &pChunk->aEntries[iEntry]; /* address the entry */
+
+ *iRed = pEntry->iRed; /* fill the fields */
+ *iGreen = pEntry->iGreen;
+ *iBlue = pEntry->iBlue;
+ *iAlpha = pEntry->iAlpha;
+ *bUsed = pEntry->bUsed;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_PPLT_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_getchunk_drop (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount,
+ mng_chunkidp *pChunknames)
+{
+ mng_datap pData;
+ mng_dropp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DROP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_dropp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_DROP)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iCount = pChunk->iCount; /* fill the fields */
+ *pChunknames = pChunk->pChunknames;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DROP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+mng_retcode MNG_DECL mng_getchunk_dbyk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_chunkid *iChunkname,
+ mng_uint8 *iPolarity,
+ mng_uint32 *iKeywordssize,
+ mng_pchar *zKeywords)
+{
+ mng_datap pData;
+ mng_dbykp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DBYK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_dbykp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_DBYK)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iChunkname = pChunk->iChunkname; /* fill the fields */
+ *iPolarity = pChunk->iPolarity;
+ *iKeywordssize = pChunk->iKeywordssize;
+ *zKeywords = pChunk->zKeywords;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_DBYK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+mng_retcode MNG_DECL mng_getchunk_ordr (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_ordrp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ORDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ordrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_ORDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iCount = pChunk->iCount; /* fill the field */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ORDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+mng_retcode MNG_DECL mng_getchunk_ordr_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_chunkid *iChunkname,
+ mng_uint8 *iOrdertype)
+{
+ mng_datap pData;
+ mng_ordrp pChunk;
+ mng_ordr_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ORDR_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_ordrp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_ORDR)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ if (iEntry >= pChunk->iCount) /* valid index ? */
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+
+ pEntry = pChunk->pEntries + iEntry; /* address the proper entry */
+
+ *iChunkname = pEntry->iChunkname; /* fill the fields */
+ *iOrdertype = pEntry->iOrdertype;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_ORDR_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode MNG_DECL mng_getchunk_magn (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint16 *iFirstid,
+ mng_uint16 *iLastid,
+ mng_uint16 *iMethodX,
+ mng_uint16 *iMX,
+ mng_uint16 *iMY,
+ mng_uint16 *iML,
+ mng_uint16 *iMR,
+ mng_uint16 *iMT,
+ mng_uint16 *iMB,
+ mng_uint16 *iMethodY)
+{
+ mng_datap pData;
+ mng_magnp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MAGN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_magnp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_MAGN)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iFirstid = pChunk->iFirstid; /* fill the fields */
+ *iLastid = pChunk->iLastid;
+ *iMethodX = (mng_uint16)pChunk->iMethodX;
+ *iMX = pChunk->iMX;
+ *iMY = pChunk->iMY;
+ *iML = pChunk->iML;
+ *iMR = pChunk->iMR;
+ *iMT = pChunk->iMT;
+ *iMB = pChunk->iMB;
+ *iMethodY = (mng_uint16)pChunk->iMethodY;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_mpng (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iFramewidth,
+ mng_uint32 *iFrameheight,
+ mng_uint16 *iNumplays,
+ mng_uint16 *iTickspersec,
+ mng_uint8 *iCompressionmethod,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_mpngp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MPNG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_mpngp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_mpNG)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iFramewidth = pChunk->iFramewidth;
+ *iFrameheight = pChunk->iFrameheight;
+ *iNumplays = pChunk->iNumplays;
+ *iTickspersec = pChunk->iTickspersec;
+ *iCompressionmethod = pChunk->iCompressionmethod;
+ *iCount = pChunk->iFramessize / sizeof (mng_mpng_frame);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_getchunk_mpng_frame (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint32 *iX,
+ mng_uint32 *iY,
+ mng_uint32 *iWidth,
+ mng_uint32 *iHeight,
+ mng_int32 *iXoffset,
+ mng_int32 *iYoffset,
+ mng_uint16 *iTicks)
+{
+ mng_datap pData;
+ mng_mpngp pChunk;
+ mng_mpng_framep pFrame;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MPNG_FRAME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_mpngp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_mpNG)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* valid index ? */
+ if (iEntry >= (pChunk->iFramessize / sizeof (mng_mpng_frame)))
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+
+ pFrame = pChunk->pFrames + iEntry; /* address the entry */
+ /* fill the fields */
+ *iX = pFrame->iX;
+ *iY = pFrame->iY;
+ *iWidth = pFrame->iWidth;
+ *iHeight = pFrame->iHeight;
+ *iXoffset = pFrame->iXoffset;
+ *iYoffset = pFrame->iYoffset;
+ *iTicks = pFrame->iTicks;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_MPNG_FRAME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+mng_retcode MNG_DECL mng_getchunk_evnt (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 *iCount)
+{
+ mng_datap pData;
+ mng_evntp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EVNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_evntp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_evNT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ *iCount = pChunk->iCount; /* fill the fields */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EVNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_evnt_entry (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iEntry,
+ mng_uint8 *iEventtype,
+ mng_uint8 *iMasktype,
+ mng_int32 *iLeft,
+ mng_int32 *iRight,
+ mng_int32 *iTop,
+ mng_int32 *iBottom,
+ mng_uint16 *iObjectid,
+ mng_uint8 *iIndex,
+ mng_uint32 *iSegmentnamesize,
+ mng_pchar *zSegmentname)
+{
+ mng_datap pData;
+ mng_evntp pChunk;
+ mng_evnt_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EVNT_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_evntp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.iChunkname != MNG_UINT_evNT)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+
+ if (iEntry >= pChunk->iCount) /* valid index ? */
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+
+ pEntry = pChunk->pEntries + iEntry; /* address the entry */
+ /* fill the fields */
+ *iEventtype = pEntry->iEventtype;
+ *iMasktype = pEntry->iMasktype;
+ *iLeft = pEntry->iLeft;
+ *iRight = pEntry->iRight;
+ *iTop = pEntry->iTop;
+ *iBottom = pEntry->iBottom;
+ *iObjectid = pEntry->iObjectid;
+ *iIndex = pEntry->iIndex;
+ *iSegmentnamesize = pEntry->iSegmentnamesize;
+ *zSegmentname = pEntry->zSegmentname;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_EVNT_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getchunk_unknown (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_chunkid *iChunkname,
+ mng_uint32 *iRawlen,
+ mng_ptr *pRawdata)
+{
+ mng_datap pData;
+ mng_unknown_chunkp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_UNKNOWN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+ pChunk = (mng_unknown_chunkp)hChunk; /* address the chunk */
+
+ if (pChunk->sHeader.fCleanup != mng_free_unknown)
+ MNG_ERROR (pData, MNG_WRONGCHUNK) /* ouch */
+ /* fill the fields */
+ *iChunkname = pChunk->sHeader.iChunkname;
+ *iRawlen = pChunk->iDatasize;
+ *pRawdata = pChunk->pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETCHUNK_UNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+MNG_LOCAL mng_bool check_term (mng_datap pData,
+ mng_chunkid iChunkname)
+{
+ mng_chunk_headerp pChunk = (mng_chunk_headerp)pData->pLastchunk;
+
+ if (!pChunk) /* nothing added yet ? */
+ return MNG_TRUE;
+ /* last added chunk is TERM ? */
+ if (pChunk->iChunkname != MNG_UINT_TERM)
+ return MNG_TRUE;
+ /* previous to last is MHDR ? */
+ if ((pChunk->pPrev) && (((mng_chunk_headerp)pChunk->pPrev)->iChunkname == MNG_UINT_MHDR))
+ return MNG_TRUE;
+
+ if (iChunkname == MNG_UINT_SEEK) /* new chunk to be added is SEEK ? */
+ return MNG_TRUE;
+
+ return MNG_FALSE;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_ihdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_IHDR, mng_init_general, mng_free_general, mng_read_ihdr, mng_write_ihdr, mng_assign_general, 0, 0, sizeof(mng_ihdr)};
+#else
+ {MNG_UINT_IHDR, mng_init_ihdr, mng_free_ihdr, mng_read_ihdr, mng_write_ihdr, mng_assign_ihdr, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_IHDR))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_ihdr (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_IHDR, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ ((mng_ihdrp)pChunk)->iWidth = iWidth;
+ ((mng_ihdrp)pChunk)->iHeight = iHeight;
+ ((mng_ihdrp)pChunk)->iBitdepth = iBitdepth;
+ ((mng_ihdrp)pChunk)->iColortype = iColortype;
+ ((mng_ihdrp)pChunk)->iCompression = iCompression;
+ ((mng_ihdrp)pChunk)->iFilter = iFilter;
+ ((mng_ihdrp)pChunk)->iInterlace = iInterlace;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_plte (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_palette8 aPalette)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_PLTE, mng_init_general, mng_free_general, mng_read_plte, mng_write_plte, mng_assign_general, 0, 0, sizeof(mng_plte)};
+#else
+ {MNG_UINT_PLTE, mng_init_plte, mng_free_plte, mng_read_plte, mng_write_plte, mng_assign_plte, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PLTE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_PLTE))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_plte (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_PLTE, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_pltep)pChunk)->iEntrycount = iCount;
+ ((mng_pltep)pChunk)->bEmpty = (mng_bool)(iCount == 0);
+
+ MNG_COPY (((mng_pltep)pChunk)->aEntries, aPalette, sizeof (mng_palette8));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_idat (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_IDAT, mng_init_general, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0, sizeof(mng_idat)};
+#else
+ {MNG_UINT_IDAT, mng_init_idat, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_IDAT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_idat (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_IDAT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_idatp)pChunk)->bEmpty = (mng_bool)(iRawlen == 0);
+ ((mng_idatp)pChunk)->iDatasize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_idatp)pChunk)->pData, iRawlen);
+ MNG_COPY (((mng_idatp)pChunk)->pData, pRawdata, iRawlen);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_iend (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_IEND, mng_init_general, mng_free_general, mng_read_iend, mng_write_iend, mng_assign_general, 0, 0, sizeof(mng_iend)};
+#else
+ {MNG_UINT_IEND, mng_init_iend, mng_free_iend, mng_read_iend, mng_write_iend, mng_assign_iend, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IEND, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_IEND))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_iend (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_IEND, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->iFirstchunkadded == MNG_UINT_IHDR) ||
+ (pData->iFirstchunkadded == MNG_UINT_JHDR) )
+#else
+ if (pData->iFirstchunkadded == MNG_UINT_IHDR)
+#endif
+ pData->bCreating = MNG_FALSE; /* should be last chunk !!! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_trns (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_bool bGlobal,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_uint8arr aAlphas,
+ mng_uint16 iGray,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint32 iRawlen,
+ mng_uint8arr aRawdata)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_tRNS, mng_init_general, mng_free_general, mng_read_trns, mng_write_trns, mng_assign_general, 0, 0, sizeof(mng_trns)};
+#else
+ {MNG_UINT_tRNS, mng_init_trns, mng_free_trns, mng_read_trns, mng_write_trns, mng_assign_trns, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TRNS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_tRNS))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_trns (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_tRNS, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_trnsp)pChunk)->bEmpty = bEmpty;
+ ((mng_trnsp)pChunk)->bGlobal = bGlobal;
+ ((mng_trnsp)pChunk)->iType = iType;
+ ((mng_trnsp)pChunk)->iCount = iCount;
+ ((mng_trnsp)pChunk)->iGray = iGray;
+ ((mng_trnsp)pChunk)->iRed = iRed;
+ ((mng_trnsp)pChunk)->iGreen = iGreen;
+ ((mng_trnsp)pChunk)->iBlue = iBlue;
+ ((mng_trnsp)pChunk)->iRawlen = iRawlen;
+
+ MNG_COPY (((mng_trnsp)pChunk)->aEntries, aAlphas, sizeof (mng_uint8arr));
+ MNG_COPY (((mng_trnsp)pChunk)->aRawdata, aRawdata, sizeof (mng_uint8arr));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_gAMA
+mng_retcode MNG_DECL mng_putchunk_gama (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iGamma)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_gAMA, mng_init_general, mng_free_general, mng_read_gama, mng_write_gama, mng_assign_general, 0, 0, sizeof(mng_gama)};
+#else
+ {MNG_UINT_gAMA, mng_init_gama, mng_free_gama, mng_read_gama, mng_write_gama, mng_assign_gama, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_GAMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_gAMA))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_gama (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_gAMA, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_gamap)pChunk)->bEmpty = bEmpty;
+ ((mng_gamap)pChunk)->iGamma = iGamma;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_retcode MNG_DECL mng_putchunk_chrm (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iWhitepointx,
+ mng_uint32 iWhitepointy,
+ mng_uint32 iRedx,
+ mng_uint32 iRedy,
+ mng_uint32 iGreenx,
+ mng_uint32 iGreeny,
+ mng_uint32 iBluex,
+ mng_uint32 iBluey)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_cHRM, mng_init_general, mng_free_general, mng_read_chrm, mng_write_chrm, mng_assign_general, 0, 0, sizeof(mng_chrm)};
+#else
+ {MNG_UINT_cHRM, mng_init_chrm, mng_free_chrm, mng_read_chrm, mng_write_chrm, mng_assign_chrm, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CHRM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_cHRM))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_chrm (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_cHRM, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_chrmp)pChunk)->bEmpty = bEmpty;
+ ((mng_chrmp)pChunk)->iWhitepointx = iWhitepointx;
+ ((mng_chrmp)pChunk)->iWhitepointy = iWhitepointy;
+ ((mng_chrmp)pChunk)->iRedx = iRedx;
+ ((mng_chrmp)pChunk)->iRedy = iRedy;
+ ((mng_chrmp)pChunk)->iGreenx = iGreenx;
+ ((mng_chrmp)pChunk)->iGreeny = iGreeny;
+ ((mng_chrmp)pChunk)->iBluex = iBluex;
+ ((mng_chrmp)pChunk)->iBluey = iBluey;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sRGB
+mng_retcode MNG_DECL mng_putchunk_srgb (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iRenderingintent)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)};
+#else
+ {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_sRGB))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_srgb (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_sRGB, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_srgbp)pChunk)->bEmpty = bEmpty;
+ ((mng_srgbp)pChunk)->iRenderingintent = iRenderingintent;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode MNG_DECL mng_putchunk_iccp (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iCompression,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_iCCP, mng_init_general, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0, sizeof(mng_iccp)};
+#else
+ {MNG_UINT_iCCP, mng_init_iccp, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ICCP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_iCCP))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_iccp (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_iCCP, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_iccpp)pChunk)->bEmpty = bEmpty;
+ ((mng_iccpp)pChunk)->iNamesize = iNamesize;
+ ((mng_iccpp)pChunk)->iCompression = iCompression;
+ ((mng_iccpp)pChunk)->iProfilesize = iProfilesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_iccpp)pChunk)->zName, iNamesize + 1);
+ MNG_COPY (((mng_iccpp)pChunk)->zName, zName, iNamesize);
+ }
+
+ if (iProfilesize)
+ {
+ MNG_ALLOC (pData, ((mng_iccpp)pChunk)->pProfile, iProfilesize);
+ MNG_COPY (((mng_iccpp)pChunk)->pProfile, pProfile, iProfilesize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+mng_retcode MNG_DECL mng_putchunk_text (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint32 iTextsize,
+ mng_pchar zText)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_tEXt, mng_init_general, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0, sizeof(mng_text)};
+#else
+ {MNG_UINT_tEXt, mng_init_text, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TEXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_tEXt))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_text (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_tEXt, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_textp)pChunk)->iKeywordsize = iKeywordsize;
+ ((mng_textp)pChunk)->iTextsize = iTextsize;
+
+ if (iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_textp)pChunk)->zKeyword, iKeywordsize + 1);
+ MNG_COPY (((mng_textp)pChunk)->zKeyword, zKeyword, iKeywordsize);
+ }
+
+ if (iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_textp)pChunk)->zText, iTextsize + 1);
+ MNG_COPY (((mng_textp)pChunk)->zText, zText, iTextsize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TEXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+mng_retcode MNG_DECL mng_putchunk_ztxt (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint8 iCompression,
+ mng_uint32 iTextsize,
+ mng_pchar zText)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_zTXt, mng_init_general, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0, sizeof(mng_ztxt)};
+#else
+ {MNG_UINT_zTXt, mng_init_ztxt, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ZTXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_zTXt))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_ztxt (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_zTXt, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_ztxtp)pChunk)->iKeywordsize = iKeywordsize;
+ ((mng_ztxtp)pChunk)->iCompression = iCompression;
+ ((mng_ztxtp)pChunk)->iTextsize = iTextsize;
+
+ if (iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_ztxtp)pChunk)->zKeyword, iKeywordsize + 1);
+ MNG_COPY (((mng_ztxtp)pChunk)->zKeyword, zKeyword, iKeywordsize);
+ }
+
+ if (iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_ztxtp)pChunk)->zText, iTextsize + 1);
+ MNG_COPY (((mng_ztxtp)pChunk)->zText, zText, iTextsize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ZTXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+mng_retcode MNG_DECL mng_putchunk_itxt (mng_handle hHandle,
+ mng_uint32 iKeywordsize,
+ mng_pchar zKeyword,
+ mng_uint8 iCompressionflag,
+ mng_uint8 iCompressionmethod,
+ mng_uint32 iLanguagesize,
+ mng_pchar zLanguage,
+ mng_uint32 iTranslationsize,
+ mng_pchar zTranslation,
+ mng_uint32 iTextsize,
+ mng_pchar zText)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_iTXt, mng_init_general, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0, sizeof(mng_itxt)};
+#else
+ {MNG_UINT_iTXt, mng_init_itxt, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ITXT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_iTXt))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_itxt (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_iTXt, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_itxtp)pChunk)->iKeywordsize = iKeywordsize;
+ ((mng_itxtp)pChunk)->iCompressionflag = iCompressionflag;
+ ((mng_itxtp)pChunk)->iCompressionmethod = iCompressionmethod;
+ ((mng_itxtp)pChunk)->iLanguagesize = iLanguagesize;
+ ((mng_itxtp)pChunk)->iTranslationsize = iTranslationsize;
+ ((mng_itxtp)pChunk)->iTextsize = iTextsize;
+
+ if (iKeywordsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunk)->zKeyword, iKeywordsize + 1);
+ MNG_COPY (((mng_itxtp)pChunk)->zKeyword, zKeyword, iKeywordsize);
+ }
+
+ if (iLanguagesize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunk)->zLanguage, iLanguagesize + 1);
+ MNG_COPY (((mng_itxtp)pChunk)->zLanguage, zLanguage, iLanguagesize);
+ }
+
+ if (iTranslationsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunk)->zTranslation, iTranslationsize + 1);
+ MNG_COPY (((mng_itxtp)pChunk)->zTranslation, zTranslation, iTranslationsize);
+ }
+
+ if (iTextsize)
+ {
+ MNG_ALLOC (pData, ((mng_itxtp)pChunk)->zText, iTextsize + 1);
+ MNG_COPY (((mng_itxtp)pChunk)->zText, zText, iTextsize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ITXT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+mng_retcode MNG_DECL mng_putchunk_bkgd (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iType,
+ mng_uint8 iIndex,
+ mng_uint16 iGray,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_bKGD, mng_init_general, mng_free_general, mng_read_bkgd, mng_write_bkgd, mng_assign_general, 0, 0, sizeof(mng_bkgd)};
+#else
+ {MNG_UINT_bKGD, mng_init_bkgd, mng_free_bkgd, mng_read_bkgd, mng_write_bkgd, mng_assign_bkgd, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BKGD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_bKGD))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_bkgd (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_bKGD, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_bkgdp)pChunk)->bEmpty = bEmpty;
+ ((mng_bkgdp)pChunk)->iType = iType;
+ ((mng_bkgdp)pChunk)->iIndex = iIndex;
+ ((mng_bkgdp)pChunk)->iGray = iGray;
+ ((mng_bkgdp)pChunk)->iRed = iRed;
+ ((mng_bkgdp)pChunk)->iGreen = iGreen;
+ ((mng_bkgdp)pChunk)->iBlue = iBlue;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+mng_retcode MNG_DECL mng_putchunk_phys (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iSizex,
+ mng_uint32 iSizey,
+ mng_uint8 iUnit)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_pHYs, mng_init_general, mng_free_general, mng_read_phys, mng_write_phys, mng_assign_general, 0, 0, sizeof(mng_phys)};
+#else
+ {MNG_UINT_pHYs, mng_init_phys, mng_free_phys, mng_read_phys, mng_write_phys, mng_assign_phys, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PHYS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_pHYs))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_phys (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_pHYs, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_physp)pChunk)->bEmpty = bEmpty;
+ ((mng_physp)pChunk)->iSizex = iSizex;
+ ((mng_physp)pChunk)->iSizey = iSizey;
+ ((mng_physp)pChunk)->iUnit = iUnit;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PHYS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sBIT
+mng_retcode MNG_DECL mng_putchunk_sbit (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iType,
+ mng_uint8arr4 aBits)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_sBIT, mng_init_general, mng_free_general, mng_read_sbit, mng_write_sbit, mng_assign_general, 0, 0, sizeof(mng_sbit)};
+#else
+ {MNG_UINT_sBIT, mng_init_sbit, mng_free_sbit, mng_read_sbit, mng_write_sbit, mng_assign_sbit, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SBIT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_sBIT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_sbit (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_sBIT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_sbitp)pChunk)->bEmpty = bEmpty;
+ ((mng_sbitp)pChunk)->iType = iType;
+ ((mng_sbitp)pChunk)->aBits[0] = aBits[0];
+ ((mng_sbitp)pChunk)->aBits[1] = aBits[1];
+ ((mng_sbitp)pChunk)->aBits[2] = aBits[2];
+ ((mng_sbitp)pChunk)->aBits[3] = aBits[3];
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SBIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+mng_retcode MNG_DECL mng_putchunk_splt (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iSampledepth,
+ mng_uint32 iEntrycount,
+ mng_ptr pEntries)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_sPLT, mng_init_general, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0, sizeof(mng_splt)};
+#else
+ {MNG_UINT_sPLT, mng_init_splt, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SPLT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_sPLT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_splt (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_sPLT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_spltp)pChunk)->bEmpty = bEmpty;
+ ((mng_spltp)pChunk)->iNamesize = iNamesize;
+ ((mng_spltp)pChunk)->iSampledepth = iSampledepth;
+ ((mng_spltp)pChunk)->iEntrycount = iEntrycount;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_spltp)pChunk)->zName, iNamesize + 1);
+ MNG_COPY (((mng_spltp)pChunk)->zName, zName, iNamesize);
+ }
+
+ if (iEntrycount)
+ {
+ mng_uint32 iSize = iEntrycount * ((iSampledepth >> 1) + 2);
+
+ MNG_ALLOC (pData, ((mng_spltp)pChunk)->pEntries, iSize);
+ MNG_COPY (((mng_spltp)pChunk)->pEntries, pEntries, iSize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+mng_retcode MNG_DECL mng_putchunk_hist (mng_handle hHandle,
+ mng_uint32 iEntrycount,
+ mng_uint16arr aEntries)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_hIST, mng_init_general, mng_free_general, mng_read_hist, mng_write_hist, mng_assign_general, 0, 0, sizeof(mng_hist)};
+#else
+ {MNG_UINT_hIST, mng_init_hist, mng_free_hist, mng_read_hist, mng_write_hist, mng_assign_hist, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_HIST, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_hIST))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_hist (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_hIST, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_histp)pChunk)->iEntrycount = iEntrycount;
+
+ MNG_COPY (((mng_histp)pChunk)->aEntries, aEntries, sizeof (mng_uint16arr));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_HIST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+mng_retcode MNG_DECL mng_putchunk_time (mng_handle hHandle,
+ mng_uint16 iYear,
+ mng_uint8 iMonth,
+ mng_uint8 iDay,
+ mng_uint8 iHour,
+ mng_uint8 iMinute,
+ mng_uint8 iSecond)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_tIME, mng_init_general, mng_free_general, mng_read_time, mng_write_time, mng_assign_general, 0, 0, sizeof(mng_time)};
+#else
+ {MNG_UINT_tIME, mng_init_time, mng_free_time, mng_read_time, mng_write_time, mng_assign_time, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TIME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_tIME))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_time (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_tIME, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_timep)pChunk)->iYear = iYear;
+ ((mng_timep)pChunk)->iMonth = iMonth;
+ ((mng_timep)pChunk)->iDay = iDay;
+ ((mng_timep)pChunk)->iHour = iHour;
+ ((mng_timep)pChunk)->iMinute = iMinute;
+ ((mng_timep)pChunk)->iSecond = iSecond;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_mhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint32 iTicks,
+ mng_uint32 iLayercount,
+ mng_uint32 iFramecount,
+ mng_uint32 iPlaytime,
+ mng_uint32 iSimplicity)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_MHDR, mng_init_general, mng_free_general, mng_read_mhdr, mng_write_mhdr, mng_assign_general, 0, 0, sizeof(mng_mhdr)};
+#else
+ {MNG_UINT_MHDR, mng_init_mhdr, mng_free_mhdr, mng_read_mhdr, mng_write_mhdr, mng_assign_mhdr, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must be very first! */
+ if (pData->iFirstchunkadded != 0)
+ MNG_ERROR (pData, MNG_SEQUENCEERROR)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_MHDR))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_mhdr (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_MHDR, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_mhdrp)pChunk)->iWidth = iWidth;
+ ((mng_mhdrp)pChunk)->iHeight = iHeight;
+ ((mng_mhdrp)pChunk)->iTicks = iTicks;
+ ((mng_mhdrp)pChunk)->iLayercount = iLayercount;
+ ((mng_mhdrp)pChunk)->iFramecount = iFramecount;
+ ((mng_mhdrp)pChunk)->iPlaytime = iPlaytime;
+ ((mng_mhdrp)pChunk)->iSimplicity = iSimplicity;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_mend (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_MEND, mng_init_general, mng_free_general, mng_read_mend, mng_write_mend, mng_assign_general, 0, 0, sizeof(mng_mend)};
+#else
+ {MNG_UINT_MEND, mng_init_mend, mng_free_mend, mng_read_mend, mng_write_mend, mng_assign_mend, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MEND, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_MEND))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_mend (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_MEND, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+ pData->bCreating = MNG_FALSE; /* should be last chunk !!! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+mng_retcode MNG_DECL mng_putchunk_loop (mng_handle hHandle,
+ mng_uint8 iLevel,
+ mng_uint32 iRepeat,
+ mng_uint8 iTermination,
+ mng_uint32 iItermin,
+ mng_uint32 iItermax,
+ mng_uint32 iCount,
+ mng_uint32p pSignals)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_LOOP, mng_init_general, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0, sizeof(mng_loop)};
+#else
+ {MNG_UINT_LOOP, mng_init_loop, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_LOOP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_LOOP))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_loop (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_LOOP, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_loopp)pChunk)->iLevel = iLevel;
+ ((mng_loopp)pChunk)->iRepeat = iRepeat;
+ ((mng_loopp)pChunk)->iTermination = iTermination;
+ ((mng_loopp)pChunk)->iItermin = iItermin;
+ ((mng_loopp)pChunk)->iItermax = iItermax;
+ ((mng_loopp)pChunk)->iCount = iCount;
+ ((mng_loopp)pChunk)->pSignals = pSignals;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_endl (mng_handle hHandle,
+ mng_uint8 iLevel)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_ENDL, mng_init_general, mng_free_general, mng_read_endl, mng_write_endl, mng_assign_general, 0, 0, sizeof(mng_endl)};
+#else
+ {MNG_UINT_ENDL, mng_init_endl, mng_free_endl, mng_read_endl, mng_write_endl, mng_assign_endl, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ENDL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_ENDL))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_endl (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_ENDL, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_endlp)pChunk)->iLevel = iLevel;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+mng_retcode MNG_DECL mng_putchunk_defi (mng_handle hHandle,
+ mng_uint16 iObjectid,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_int32 iXlocation,
+ mng_int32 iYlocation,
+ mng_bool bHasclip,
+ mng_int32 iLeftcb,
+ mng_int32 iRightcb,
+ mng_int32 iTopcb,
+ mng_int32 iBottomcb)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_DEFI, mng_init_general, mng_free_general, mng_read_defi, mng_write_defi, mng_assign_general, 0, 0, sizeof(mng_defi)};
+#else
+ {MNG_UINT_DEFI, mng_init_defi, mng_free_defi, mng_read_defi, mng_write_defi, mng_assign_defi, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DEFI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_DEFI))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_defi (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_DEFI, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_defip)pChunk)->iObjectid = iObjectid;
+ ((mng_defip)pChunk)->iDonotshow = iDonotshow;
+ ((mng_defip)pChunk)->iConcrete = iConcrete;
+ ((mng_defip)pChunk)->bHasloca = bHasloca;
+ ((mng_defip)pChunk)->iXlocation = iXlocation;
+ ((mng_defip)pChunk)->iYlocation = iYlocation;
+ ((mng_defip)pChunk)->bHasclip = bHasclip;
+ ((mng_defip)pChunk)->iLeftcb = iLeftcb;
+ ((mng_defip)pChunk)->iRightcb = iRightcb;
+ ((mng_defip)pChunk)->iTopcb = iTopcb;
+ ((mng_defip)pChunk)->iBottomcb = iBottomcb;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+mng_retcode MNG_DECL mng_putchunk_basi (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_BASI, mng_init_general, mng_free_general, mng_read_basi, mng_write_basi, mng_assign_general, 0, 0, sizeof(mng_basi)};
+#else
+ {MNG_UINT_BASI, mng_init_basi, mng_free_basi, mng_read_basi, mng_write_basi, mng_assign_basi, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BASI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_BASI))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_basi (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_BASI, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_basip)pChunk)->iWidth = iWidth;
+ ((mng_basip)pChunk)->iHeight = iHeight;
+ ((mng_basip)pChunk)->iBitdepth = iBitdepth;
+ ((mng_basip)pChunk)->iColortype = iColortype;
+ ((mng_basip)pChunk)->iCompression = iCompression;
+ ((mng_basip)pChunk)->iFilter = iFilter;
+ ((mng_basip)pChunk)->iInterlace = iInterlace;
+ ((mng_basip)pChunk)->iRed = iRed;
+ ((mng_basip)pChunk)->iGreen = iGreen;
+ ((mng_basip)pChunk)->iBlue = iBlue;
+ ((mng_basip)pChunk)->iAlpha = iAlpha;
+ ((mng_basip)pChunk)->iViewable = iViewable;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+mng_retcode MNG_DECL mng_putchunk_clon (mng_handle hHandle,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_CLON, mng_init_general, mng_free_general, mng_read_clon, mng_write_clon, mng_assign_general, 0, 0, sizeof(mng_clon)};
+#else
+ {MNG_UINT_CLON, mng_init_clon, mng_free_clon, mng_read_clon, mng_write_clon, mng_assign_clon, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CLON, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_CLON))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_clon (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_CLON, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_clonp)pChunk)->iSourceid = iSourceid;
+ ((mng_clonp)pChunk)->iCloneid = iCloneid;
+ ((mng_clonp)pChunk)->iClonetype = iClonetype;
+ ((mng_clonp)pChunk)->iDonotshow = iDonotshow;
+ ((mng_clonp)pChunk)->iConcrete = iConcrete;
+ ((mng_clonp)pChunk)->bHasloca = bHasloca;
+ ((mng_clonp)pChunk)->iLocationtype = iLocationtype;
+ ((mng_clonp)pChunk)->iLocationx = iLocationx;
+ ((mng_clonp)pChunk)->iLocationy = iLocationy;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode MNG_DECL mng_putchunk_past (mng_handle hHandle,
+ mng_uint16 iDestid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_PAST, mng_init_general, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0, sizeof(mng_past)};
+#else
+ {MNG_UINT_PAST, mng_init_past, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PAST, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_PAST))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_past (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_PAST, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_pastp)pChunk)->iDestid = iDestid;
+ ((mng_pastp)pChunk)->iTargettype = iTargettype;
+ ((mng_pastp)pChunk)->iTargetx = iTargetx;
+ ((mng_pastp)pChunk)->iTargety = iTargety;
+ ((mng_pastp)pChunk)->iCount = iCount;
+
+ if (iCount)
+ MNG_ALLOC (pData, ((mng_pastp)pChunk)->pSources, iCount * sizeof (mng_past_source));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode MNG_DECL mng_putchunk_past_src (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint16 iSourceid,
+ mng_uint8 iComposition,
+ mng_uint8 iOrientation,
+ mng_uint8 iOffsettype,
+ mng_int32 iOffsetx,
+ mng_int32 iOffsety,
+ mng_uint8 iBoundarytype,
+ mng_int32 iBoundaryl,
+ mng_int32 iBoundaryr,
+ mng_int32 iBoundaryt,
+ mng_int32 iBoundaryb)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_past_sourcep pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PAST_SRC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been PAST ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_PAST)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+ /* index out of bounds ? */
+ if (iEntry >= ((mng_pastp)pChunk)->iCount)
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pEntry = ((mng_pastp)pChunk)->pSources + iEntry;
+
+ pEntry->iSourceid = iSourceid; /* fill entry */
+ pEntry->iComposition = iComposition;
+ pEntry->iOrientation = iOrientation;
+ pEntry->iOffsettype = iOffsettype;
+ pEntry->iOffsetx = iOffsetx;
+ pEntry->iOffsety = iOffsety;
+ pEntry->iBoundarytype = iBoundarytype;
+ pEntry->iBoundaryl = iBoundaryl;
+ pEntry->iBoundaryr = iBoundaryr;
+ pEntry->iBoundaryt = iBoundaryt;
+ pEntry->iBoundaryb = iBoundaryb;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PAST_SRC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode MNG_DECL mng_putchunk_disc (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_uint16p pObjectids)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_DISC, mng_init_general, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0, sizeof(mng_disc)};
+#else
+ {MNG_UINT_DISC, mng_init_disc, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DISC, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_DISC))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_disc (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_DISC, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_discp)pChunk)->iCount = iCount;
+
+ if (iCount)
+ {
+ mng_uint32 iSize = iCount * sizeof (mng_uint32);
+
+ MNG_ALLOC (pData, ((mng_discp)pChunk)->pObjectids, iSize);
+ MNG_COPY (((mng_discp)pChunk)->pObjectids, pObjectids, iSize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+mng_retcode MNG_DECL mng_putchunk_back (mng_handle hHandle,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint8 iMandatory,
+ mng_uint16 iImageid,
+ mng_uint8 iTile)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_BACK, mng_init_general, mng_free_general, mng_read_back, mng_write_back, mng_assign_general, 0, 0, sizeof(mng_back)};
+#else
+ {MNG_UINT_BACK, mng_init_back, mng_free_back, mng_read_back, mng_write_back, mng_assign_back, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BACK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_BACK))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_back (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_BACK, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_backp)pChunk)->iRed = iRed;
+ ((mng_backp)pChunk)->iGreen = iGreen;
+ ((mng_backp)pChunk)->iBlue = iBlue;
+ ((mng_backp)pChunk)->iMandatory = iMandatory;
+ ((mng_backp)pChunk)->iImageid = iImageid;
+ ((mng_backp)pChunk)->iTile = iTile;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+mng_retcode MNG_DECL mng_putchunk_fram (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iMode,
+ mng_uint32 iNamesize,
+ mng_pchar zName,
+ mng_uint8 iChangedelay,
+ mng_uint8 iChangetimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iChangesyncid,
+ mng_uint32 iDelay,
+ mng_uint32 iTimeout,
+ mng_uint8 iBoundarytype,
+ mng_int32 iBoundaryl,
+ mng_int32 iBoundaryr,
+ mng_int32 iBoundaryt,
+ mng_int32 iBoundaryb,
+ mng_uint32 iCount,
+ mng_uint32p pSyncids)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_FRAM, mng_init_general, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0, sizeof(mng_fram)};
+#else
+ {MNG_UINT_FRAM, mng_init_fram, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_FRAM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_FRAM))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_fram (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_FRAM, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_framp)pChunk)->bEmpty = bEmpty;
+ ((mng_framp)pChunk)->iMode = iMode;
+ ((mng_framp)pChunk)->iNamesize = iNamesize;
+ ((mng_framp)pChunk)->iChangedelay = iChangedelay;
+ ((mng_framp)pChunk)->iChangetimeout = iChangetimeout;
+ ((mng_framp)pChunk)->iChangeclipping = iChangeclipping;
+ ((mng_framp)pChunk)->iChangesyncid = iChangesyncid;
+ ((mng_framp)pChunk)->iDelay = iDelay;
+ ((mng_framp)pChunk)->iTimeout = iTimeout;
+ ((mng_framp)pChunk)->iBoundarytype = iBoundarytype;
+ ((mng_framp)pChunk)->iBoundaryl = iBoundaryl;
+ ((mng_framp)pChunk)->iBoundaryr = iBoundaryr;
+ ((mng_framp)pChunk)->iBoundaryt = iBoundaryt;
+ ((mng_framp)pChunk)->iBoundaryb = iBoundaryb;
+ ((mng_framp)pChunk)->iCount = iCount;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_framp)pChunk)->zName, iNamesize + 1);
+ MNG_COPY (((mng_framp)pChunk)->zName, zName, iNamesize);
+ }
+
+ if (iCount)
+ {
+ mng_uint32 iSize = iCount * sizeof (mng_uint32);
+
+ MNG_ALLOC (pData, ((mng_framp)pChunk)->pSyncids, iSize);
+ MNG_COPY (((mng_framp)pChunk)->pSyncids, pSyncids, iSize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+mng_retcode MNG_DECL mng_putchunk_move (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMovetype,
+ mng_int32 iMovex,
+ mng_int32 iMovey)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_MOVE, mng_init_general, mng_free_general, mng_read_move, mng_write_move, mng_assign_general, 0, 0, sizeof(mng_move)};
+#else
+ {MNG_UINT_MOVE, mng_init_move, mng_free_move, mng_read_move, mng_write_move, mng_assign_move, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MOVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_MOVE))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_move (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_MOVE, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_movep)pChunk)->iFirstid = iFirstid;
+ ((mng_movep)pChunk)->iLastid = iLastid;
+ ((mng_movep)pChunk)->iMovetype = iMovetype;
+ ((mng_movep)pChunk)->iMovex = iMovex;
+ ((mng_movep)pChunk)->iMovey = iMovey;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+mng_retcode MNG_DECL mng_putchunk_clip (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_CLIP, mng_init_general, mng_free_general, mng_read_clip, mng_write_clip, mng_assign_general, 0, 0, sizeof(mng_clip)};
+#else
+ {MNG_UINT_CLIP, mng_init_clip, mng_free_clip, mng_read_clip, mng_write_clip, mng_assign_clip, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CLIP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_CLIP))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_clip (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_CLIP, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_clipp)pChunk)->iFirstid = iFirstid;
+ ((mng_clipp)pChunk)->iLastid = iLastid;
+ ((mng_clipp)pChunk)->iCliptype = iCliptype;
+ ((mng_clipp)pChunk)->iClipl = iClipl;
+ ((mng_clipp)pChunk)->iClipr = iClipr;
+ ((mng_clipp)pChunk)->iClipt = iClipt;
+ ((mng_clipp)pChunk)->iClipb = iClipb;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+mng_retcode MNG_DECL mng_putchunk_show (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMode)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_SHOW, mng_init_general, mng_free_general, mng_read_show, mng_write_show, mng_assign_general, 0, 0, sizeof(mng_show)};
+#else
+ {MNG_UINT_SHOW, mng_init_show, mng_free_show, mng_read_show, mng_write_show, mng_assign_show, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SHOW, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_SHOW))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_show (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_SHOW, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_showp)pChunk)->bEmpty = bEmpty;
+ ((mng_showp)pChunk)->iFirstid = iFirstid;
+ ((mng_showp)pChunk)->iLastid = iLastid;
+ ((mng_showp)pChunk)->iMode = iMode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+mng_retcode MNG_DECL mng_putchunk_term (mng_handle hHandle,
+ mng_uint8 iTermaction,
+ mng_uint8 iIteraction,
+ mng_uint32 iDelay,
+ mng_uint32 iItermax)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_TERM, mng_init_general, mng_free_general, mng_read_term, mng_write_term, mng_assign_general, 0, 0, sizeof(mng_term)};
+#else
+ {MNG_UINT_TERM, mng_init_term, mng_free_term, mng_read_term, mng_write_term, mng_assign_term, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TERM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_term (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_TERM, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_termp)pChunk)->iTermaction = iTermaction;
+ ((mng_termp)pChunk)->iIteraction = iIteraction;
+ ((mng_termp)pChunk)->iDelay = iDelay;
+ ((mng_termp)pChunk)->iItermax = iItermax;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode MNG_DECL mng_putchunk_save (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint8 iOffsettype,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_SAVE, mng_init_general, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0, sizeof(mng_save)};
+#else
+ {MNG_UINT_SAVE, mng_init_save, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SAVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_SAVE))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_save (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_SAVE, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_savep)pChunk)->bEmpty = bEmpty;
+ ((mng_savep)pChunk)->iOffsettype = iOffsettype;
+ ((mng_savep)pChunk)->iCount = iCount;
+
+ if (iCount)
+ MNG_ALLOC (pData, ((mng_savep)pChunk)->pEntries, iCount * sizeof (mng_save_entry));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_save_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint8 iEntrytype,
+ mng_uint32arr2 iOffset,
+ mng_uint32arr2 iStarttime,
+ mng_uint32 iLayernr,
+ mng_uint32 iFramenr,
+ mng_uint32 iNamesize,
+ mng_pchar zName)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_save_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SAVE_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been SAVE ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_SAVE)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+ /* index out of bounds ? */
+ if (iEntry >= ((mng_savep)pChunk)->iCount)
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pEntry = ((mng_savep)pChunk)->pEntries + iEntry;
+
+ pEntry->iEntrytype = iEntrytype; /* fill entry */
+ pEntry->iOffset[0] = iOffset[0];
+ pEntry->iOffset[1] = iOffset[1];
+ pEntry->iStarttime[0] = iStarttime[0];
+ pEntry->iStarttime[1] = iStarttime[1];
+ pEntry->iLayernr = iLayernr;
+ pEntry->iFramenr = iFramenr;
+ pEntry->iNamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zName, iNamesize + 1);
+ MNG_COPY (pEntry->zName, zName, iNamesize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SAVE_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode MNG_DECL mng_putchunk_seek (mng_handle hHandle,
+ mng_uint32 iNamesize,
+ mng_pchar zName)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_SEEK, mng_init_general, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0, sizeof(mng_seek)};
+#else
+ {MNG_UINT_SEEK, mng_init_seek, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SEEK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_SEEK))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_seek (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_SEEK, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_seekp)pChunk)->iNamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_seekp)pChunk)->zName, iNamesize + 1);
+ MNG_COPY (((mng_seekp)pChunk)->zName, zName, iNamesize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+mng_retcode MNG_DECL mng_putchunk_expi (mng_handle hHandle,
+ mng_uint16 iSnapshotid,
+ mng_uint32 iNamesize,
+ mng_pchar zName)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_eXPI, mng_init_general, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_general, 0, 0, sizeof(mng_expi)};
+#else
+ {MNG_UINT_eXPI, mng_init_expi, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EXPI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_eXPI))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_expi (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_eXPI, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_expip)pChunk)->iSnapshotid = iSnapshotid;
+ ((mng_expip)pChunk)->iNamesize = iNamesize;
+
+ if (iNamesize)
+ {
+ MNG_ALLOC (pData, ((mng_expip)pChunk)->zName, iNamesize + 1);
+ MNG_COPY (((mng_expip)pChunk)->zName, zName, iNamesize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EXPI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+mng_retcode MNG_DECL mng_putchunk_fpri (mng_handle hHandle,
+ mng_uint8 iDeltatype,
+ mng_uint8 iPriority)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_fPRI, mng_init_general, mng_free_general, mng_read_fpri, mng_write_fpri, mng_assign_general, 0, 0, sizeof(mng_fpri)};
+#else
+ {MNG_UINT_fPRI, mng_init_fpri, mng_free_fpri, mng_read_fpri, mng_write_fpri, mng_assign_fpri, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_FPRI, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_fPRI))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_fpri (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_fPRI, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_fprip)pChunk)->iDeltatype = iDeltatype;
+ ((mng_fprip)pChunk)->iPriority = iPriority;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_FPRI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+mng_retcode MNG_DECL mng_putchunk_need (mng_handle hHandle,
+ mng_uint32 iKeywordssize,
+ mng_pchar zKeywords)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_nEED, mng_init_general, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0, sizeof(mng_need)};
+#else
+ {MNG_UINT_nEED, mng_init_need, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_NEED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_nEED))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_need (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_nEED, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_needp)pChunk)->iKeywordssize = iKeywordssize;
+
+ if (iKeywordssize)
+ {
+ MNG_ALLOC (pData, ((mng_needp)pChunk)->zKeywords, iKeywordssize + 1);
+ MNG_COPY (((mng_needp)pChunk)->zKeywords, zKeywords, iKeywordssize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_NEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+mng_retcode MNG_DECL mng_putchunk_phyg (mng_handle hHandle,
+ mng_bool bEmpty,
+ mng_uint32 iSizex,
+ mng_uint32 iSizey,
+ mng_uint8 iUnit)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_pHYg, mng_init_general, mng_free_general, mng_read_phyg, mng_write_phyg, mng_assign_general, 0, 0, sizeof(mng_phyg)};
+#else
+ {MNG_UINT_pHYg, mng_init_phyg, mng_free_phyg, mng_read_phyg, mng_write_phyg, mng_assign_phyg, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PHYG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_pHYg))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_phyg (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_pHYg, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_phygp)pChunk)->bEmpty = bEmpty;
+ ((mng_phygp)pChunk)->iSizex = iSizex;
+ ((mng_phygp)pChunk)->iSizey = iSizey;
+ ((mng_phygp)pChunk)->iUnit = iUnit;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PHYG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_putchunk_jhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iImagesampledepth,
+ mng_uint8 iImagecompression,
+ mng_uint8 iImageinterlace,
+ mng_uint8 iAlphasampledepth,
+ mng_uint8 iAlphacompression,
+ mng_uint8 iAlphafilter,
+ mng_uint8 iAlphainterlace)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_JHDR, mng_init_general, mng_free_general, mng_read_jhdr, mng_write_jhdr, mng_assign_general, 0, 0, sizeof(mng_jhdr)};
+#else
+ {MNG_UINT_JHDR, mng_init_jhdr, mng_free_jhdr, mng_read_jhdr, mng_write_jhdr, mng_assign_jhdr, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_JHDR))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_jhdr (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_JHDR, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_jhdrp)pChunk)->iWidth = iWidth;
+ ((mng_jhdrp)pChunk)->iHeight = iHeight;
+ ((mng_jhdrp)pChunk)->iColortype = iColortype;
+ ((mng_jhdrp)pChunk)->iImagesampledepth = iImagesampledepth;
+ ((mng_jhdrp)pChunk)->iImagecompression = iImagecompression;
+ ((mng_jhdrp)pChunk)->iImageinterlace = iImageinterlace;
+ ((mng_jhdrp)pChunk)->iAlphasampledepth = iAlphasampledepth;
+ ((mng_jhdrp)pChunk)->iAlphacompression = iAlphacompression;
+ ((mng_jhdrp)pChunk)->iAlphafilter = iAlphafilter;
+ ((mng_jhdrp)pChunk)->iAlphainterlace = iAlphainterlace;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_putchunk_jdat (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_JDAT, mng_init_general, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0, sizeof(mng_jdat)};
+#else
+ {MNG_UINT_JDAT, mng_init_jdat, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR or JHDR first! */
+ if ((pData->iFirstchunkadded != MNG_UINT_MHDR) &&
+ (pData->iFirstchunkadded != MNG_UINT_JHDR) )
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_JDAT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_jdat (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_JDAT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_jdatp)pChunk)->iDatasize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_jdatp)pChunk)->pData, iRawlen);
+ MNG_COPY (((mng_jdatp)pChunk)->pData, pRawdata, iRawlen);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_putchunk_jdaa (mng_handle hHandle,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_JDAA, mng_init_general, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa)};
+#else
+ {MNG_UINT_JDAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JDAA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR or JHDR first! */
+ if ((pData->iFirstchunkadded != MNG_UINT_MHDR) &&
+ (pData->iFirstchunkadded != MNG_UINT_JHDR) )
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_JDAA))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_jdaa (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_JDAA, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_jdaap)pChunk)->iDatasize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_jdaap)pChunk)->pData, iRawlen);
+ MNG_COPY (((mng_jdaap)pChunk)->pData, pRawdata, iRawlen);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+mng_retcode MNG_DECL mng_putchunk_jsep (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_JSEP, mng_init_general, mng_free_general, mng_read_jsep, mng_write_jsep, mng_assign_general, 0, 0, sizeof(mng_jsep)};
+#else
+ {MNG_UINT_JSEP, mng_init_jsep, mng_free_jsep, mng_read_jsep, mng_write_jsep, mng_assign_jsep, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JSEP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR or JHDR first! */
+ if ((pData->iFirstchunkadded != MNG_UINT_MHDR) &&
+ (pData->iFirstchunkadded != MNG_UINT_JHDR) )
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_JSEP))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_jsep (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_JSEP, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_JSEP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_dhdr (mng_handle hHandle,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_DHDR, mng_init_general, mng_free_general, mng_read_dhdr, mng_write_dhdr, mng_assign_general, 0, 0, sizeof(mng_dhdr)};
+#else
+ {MNG_UINT_DHDR, mng_init_dhdr, mng_free_dhdr, mng_read_dhdr, mng_write_dhdr, mng_assign_dhdr, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DHDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_DHDR))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_dhdr (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_DHDR, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_dhdrp)pChunk)->iObjectid = iObjectid;
+ ((mng_dhdrp)pChunk)->iImagetype = iImagetype;
+ ((mng_dhdrp)pChunk)->iDeltatype = iDeltatype;
+ ((mng_dhdrp)pChunk)->iBlockwidth = iBlockwidth;
+ ((mng_dhdrp)pChunk)->iBlockheight = iBlockheight;
+ ((mng_dhdrp)pChunk)->iBlockx = iBlockx;
+ ((mng_dhdrp)pChunk)->iBlocky = iBlocky;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_prom (mng_handle hHandle,
+ mng_uint8 iColortype,
+ mng_uint8 iSampledepth,
+ mng_uint8 iFilltype)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_PROM, mng_init_general, mng_free_general, mng_read_prom, mng_write_prom, mng_assign_general, 0, 0, sizeof(mng_prom)};
+#else
+ {MNG_UINT_PROM, mng_init_prom, mng_free_prom, mng_read_prom, mng_write_prom, mng_assign_prom, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PROM, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_PROM))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_prom (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_PROM, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_promp)pChunk)->iColortype = iColortype;
+ ((mng_promp)pChunk)->iSampledepth = iSampledepth;
+ ((mng_promp)pChunk)->iFilltype = iFilltype;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_ipng (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_IPNG, mng_init_general, mng_free_general, mng_read_ipng, mng_write_ipng, mng_assign_general, 0, 0, sizeof(mng_ipng)};
+#else
+ {MNG_UINT_IPNG, mng_init_ipng, mng_free_ipng, mng_read_ipng, mng_write_ipng, mng_assign_ipng, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IPNG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_IPNG))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_ipng (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_IPNG, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_pplt (mng_handle hHandle,
+ mng_uint8 iDeltatype,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_PPLT, mng_init_general, mng_free_general, mng_read_pplt, mng_write_pplt, mng_assign_general, 0, 0, sizeof(mng_pplt)};
+#else
+ {MNG_UINT_PPLT, mng_init_pplt, mng_free_pplt, mng_read_pplt, mng_write_pplt, mng_assign_pplt, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PPLT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_PPLT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_pplt (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_PPLT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_ppltp)pChunk)->iDeltatype = iDeltatype;
+ ((mng_ppltp)pChunk)->iCount = iCount;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_pplt_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint16 iAlpha)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_pplt_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PPLT_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been PPLT ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_PPLT)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+
+ /* index out of bounds ? */
+ if (iEntry >= ((mng_ppltp)pChunk)->iCount)
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pEntry = (mng_pplt_entryp)(((mng_ppltp)pChunk)->aEntries) + iEntry;
+
+ pEntry->iRed = (mng_uint8)iRed; /* fill the entry */
+ pEntry->iGreen = (mng_uint8)iGreen;
+ pEntry->iBlue = (mng_uint8)iBlue;
+ pEntry->iAlpha = (mng_uint8)iAlpha;
+ pEntry->bUsed = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_PPLT_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+mng_retcode MNG_DECL mng_putchunk_ijng (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_IJNG, mng_init_general, mng_free_general, mng_read_ijng, mng_write_ijng, mng_assign_general, 0, 0, sizeof(mng_ijng)};
+#else
+ {MNG_UINT_IJNG, mng_init_ijng, mng_free_ijng, mng_read_ijng, mng_write_ijng, mng_assign_ijng, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IJNG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_IJNG))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_ijng (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_IJNG, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode MNG_DECL mng_putchunk_drop (mng_handle hHandle,
+ mng_uint32 iCount,
+ mng_chunkidp pChunknames)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_DROP, mng_init_general, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0, sizeof(mng_drop)};
+#else
+ {MNG_UINT_DROP, mng_init_drop, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DROP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_DROP))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_drop (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_DROP, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_dropp)pChunk)->iCount = iCount;
+
+ if (iCount)
+ {
+ mng_uint32 iSize = iCount * sizeof (mng_chunkid);
+
+ MNG_ALLOC (pData, ((mng_dropp)pChunk)->pChunknames, iSize);
+ MNG_COPY (((mng_dropp)pChunk)->pChunknames, pChunknames, iSize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DROP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+mng_retcode MNG_DECL mng_putchunk_dbyk (mng_handle hHandle,
+ mng_chunkid iChunkname,
+ mng_uint8 iPolarity,
+ mng_uint32 iKeywordssize,
+ mng_pchar zKeywords)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_DBYK, mng_init_general, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0, sizeof(mng_dbyk)};
+#else
+ {MNG_UINT_DBYK, mng_init_dbyk, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DBYK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_DBYK))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_dbyk (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_DBYK, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_dbykp)pChunk)->iChunkname = iChunkname;
+ ((mng_dbykp)pChunk)->iPolarity = iPolarity;
+ ((mng_dbykp)pChunk)->iKeywordssize = iKeywordssize;
+
+ if (iKeywordssize)
+ {
+ MNG_ALLOC (pData, ((mng_dbykp)pChunk)->zKeywords, iKeywordssize + 1);
+ MNG_COPY (((mng_dbykp)pChunk)->zKeywords, zKeywords, iKeywordssize);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_DBYK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+mng_retcode MNG_DECL mng_putchunk_ordr (mng_handle hHandle,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_ORDR, mng_init_general, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0, sizeof(mng_ordr)};
+#else
+ {MNG_UINT_ORDR, mng_init_ordr, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ORDR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_ORDR))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_ordr (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_ORDR, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_ordrp)pChunk)->iCount = iCount;
+
+ if (iCount)
+ MNG_ALLOC (pData, ((mng_ordrp)pChunk)->pEntries, iCount * sizeof (mng_ordr_entry));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ORDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+mng_retcode MNG_DECL mng_putchunk_ordr_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_chunkid iChunkname,
+ mng_uint8 iOrdertype)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_ordr_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ORDR_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been ORDR ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_ORDR)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+ /* index out of bounds ? */
+ if (iEntry >= ((mng_ordrp)pChunk)->iCount)
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pEntry = ((mng_ordrp)pChunk)->pEntries + iEntry;
+
+ pEntry->iChunkname = iChunkname; /* fill the entry */
+ pEntry->iOrdertype = iOrdertype;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_ORDR_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode MNG_DECL mng_putchunk_magn (mng_handle hHandle,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint16 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint16 iMethodY)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_MAGN, mng_init_general, mng_free_general, mng_read_magn, mng_write_magn, mng_assign_general, 0, 0, sizeof(mng_magn)};
+#else
+ {MNG_UINT_MAGN, mng_init_magn, mng_free_magn, mng_read_magn, mng_write_magn, mng_assign_magn, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MAGN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_MAGN))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_magn (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_MAGN, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_magnp)pChunk)->iFirstid = iFirstid;
+ ((mng_magnp)pChunk)->iLastid = iLastid;
+ ((mng_magnp)pChunk)->iMethodX = (mng_uint8)iMethodX;
+ ((mng_magnp)pChunk)->iMX = iMX;
+ ((mng_magnp)pChunk)->iMY = iMY;
+ ((mng_magnp)pChunk)->iML = iML;
+ ((mng_magnp)pChunk)->iMR = iMR;
+ ((mng_magnp)pChunk)->iMT = iMT;
+ ((mng_magnp)pChunk)->iMB = iMB;
+ ((mng_magnp)pChunk)->iMethodY = (mng_uint8)iMethodY;
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mpng (mng_handle hHandle,
+ mng_uint32 iFramewidth,
+ mng_uint32 iFrameheight,
+ mng_uint16 iNumplays,
+ mng_uint16 iTickspersec,
+ mng_uint8 iCompressionmethod,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_mpNG, mng_init_general, mng_free_mpng, mng_read_mpng, mng_write_mpng, mng_assign_mpng, 0, 0, sizeof(mng_mpng)};
+#else
+ {MNG_UINT_mpNG, mng_init_mpng, mng_free_mpng, mng_read_mpng, mng_write_mpng, mng_assign_mpng, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MPNG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a IHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_IHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_mpng (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_mpNG, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_mpngp)pChunk)->iFramewidth = iFramewidth;
+ ((mng_mpngp)pChunk)->iFrameheight = iFrameheight;
+ ((mng_mpngp)pChunk)->iNumplays = iNumplays;
+ ((mng_mpngp)pChunk)->iTickspersec = iTickspersec;
+ ((mng_mpngp)pChunk)->iCompressionmethod = iCompressionmethod;
+ ((mng_mpngp)pChunk)->iFramessize = iCount * sizeof (mng_mpng_frame);
+
+ if (iCount)
+ MNG_ALLOC (pData, ((mng_mpngp)pChunk)->pFrames, ((mng_mpngp)pChunk)->iFramessize);
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+MNG_EXT mng_retcode MNG_DECL mng_putchunk_mpng_frame (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint32 iX,
+ mng_uint32 iY,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_int32 iXoffset,
+ mng_int32 iYoffset,
+ mng_uint16 iTicks)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_mpng_framep pFrame;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MPNG_FRAME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a IHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_IHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been mpNG ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_mpNG)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+ /* index out of bounds ? */
+ if (iEntry >= (((mng_mpngp)pChunk)->iFramessize / sizeof (mng_mpng_frame)))
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pFrame = ((mng_mpngp)pChunk)->pFrames + iEntry;
+ /* fill entry */
+ pFrame->iX = iX;
+ pFrame->iY = iY;
+ pFrame->iWidth = iWidth;
+ pFrame->iHeight = iHeight;
+ pFrame->iXoffset = iXoffset;
+ pFrame->iYoffset = iYoffset;
+ pFrame->iTicks = iTicks;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_MPNG_FRAME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_evNT
+mng_retcode MNG_DECL mng_putchunk_evnt (mng_handle hHandle,
+ mng_uint32 iCount)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_evNT, mng_init_general, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0, sizeof(mng_evnt)};
+#else
+ {MNG_UINT_evNT, mng_init_evnt, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EVNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, MNG_UINT_evNT))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_evnt (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_evNT, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_evntp)pChunk)->iCount = iCount;
+
+ if (iCount)
+ MNG_ALLOC (pData, ((mng_evntp)pChunk)->pEntries, iCount * sizeof (mng_evnt_entry));
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EVNT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_evnt_entry (mng_handle hHandle,
+ mng_uint32 iEntry,
+ mng_uint8 iEventtype,
+ mng_uint8 iMasktype,
+ mng_int32 iLeft,
+ mng_int32 iRight,
+ mng_int32 iTop,
+ mng_int32 iBottom,
+ mng_uint16 iObjectid,
+ mng_uint8 iIndex,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_evnt_entryp pEntry;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EVNT_ENTRY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a MHDR first! */
+ if (pData->iFirstchunkadded != MNG_UINT_MHDR)
+ MNG_ERROR (pData, MNG_NOHEADER)
+
+ pChunk = pData->pLastchunk; /* last one must have been evNT ! */
+
+ if (((mng_chunk_headerp)pChunk)->iChunkname != MNG_UINT_evNT)
+ MNG_ERROR (pData, MNG_NOCORRCHUNK)
+ /* index out of bounds ? */
+ if (iEntry >= ((mng_evntp)pChunk)->iCount)
+ MNG_ERROR (pData, MNG_INVALIDENTRYIX)
+ /* address proper entry */
+ pEntry = ((mng_evntp)pChunk)->pEntries + iEntry;
+ /* fill entry */
+ pEntry->iEventtype = iEventtype;
+ pEntry->iMasktype = iMasktype;
+ pEntry->iLeft = iLeft;
+ pEntry->iRight = iRight;
+ pEntry->iTop = iTop;
+ pEntry->iBottom = iBottom;
+ pEntry->iObjectid = iObjectid;
+ pEntry->iIndex = iIndex;
+ pEntry->iSegmentnamesize = iSegmentnamesize;
+
+ if (iSegmentnamesize)
+ {
+ MNG_ALLOC (pData, pEntry->zSegmentname, iSegmentnamesize + 1);
+ MNG_COPY (pEntry->zSegmentname, zSegmentname, iSegmentnamesize);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_EVNT_ENTRY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putchunk_unknown (mng_handle hHandle,
+ mng_chunkid iChunkname,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_header sChunkheader =
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ {MNG_UINT_HUH, mng_init_general, mng_free_unknown, mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0, sizeof(mng_unknown_chunk)};
+#else
+ {MNG_UINT_HUH, mng_init_unknown, mng_free_unknown, mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0};
+#endif
+#else
+ mng_chunk_header sChunkheader;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_UNKNOWN, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must have had a header first! */
+ if (pData->iFirstchunkadded == 0)
+ MNG_ERROR (pData, MNG_NOHEADER)
+ /* prevent misplaced TERM ! */
+ if (!check_term (pData, iChunkname))
+ MNG_ERROR (pData, MNG_TERMSEQERROR)
+ /* create the chunk */
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#else
+ iRetcode = mng_init_unknown (pData, &sChunkheader, &pChunk);
+#endif
+#else
+ mng_get_chunkheader(MNG_UINT_HUH, &sChunkheader);
+ iRetcode = mng_init_general (pData, &sChunkheader, &pChunk);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fill the chunk */
+ ((mng_unknown_chunkp)pChunk)->sHeader.iChunkname = iChunkname;
+ ((mng_unknown_chunkp)pChunk)->iDatasize = iRawlen;
+
+ if (iRawlen)
+ {
+ MNG_ALLOC (pData, ((mng_unknown_chunkp)pChunk)->pData, iRawlen);
+ MNG_COPY (((mng_unknown_chunkp)pChunk)->pData, pRawdata, iRawlen);
+ }
+
+ mng_add_chunk (pData, pChunk); /* add it to the list */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTCHUNK_UNKNOWN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getimgdata_seq (mng_handle hHandle,
+ mng_uint32 iSeqnr,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_SEQ, MNG_LC_START);
+#endif
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_SEQ, MNG_LC_END);
+#endif
+
+ return MNG_FNNOTIMPLEMENTED;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getimgdata_chunkseq (mng_handle hHandle,
+ mng_uint32 iSeqnr,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_CHUNKSEQ, MNG_LC_START);
+#endif
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_CHUNKSEQ, MNG_LC_END);
+#endif
+
+ return MNG_FNNOTIMPLEMENTED;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getimgdata_chunk (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_CHUNK, MNG_LC_START);
+#endif
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETIMGDATA_CHUNK, MNG_LC_END);
+#endif
+
+ return MNG_FNNOTIMPLEMENTED;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_putimgdata_ihdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iBitdepth,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTIMGDATA_IHDR, MNG_LC_START);
+#endif
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTIMGDATA_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_FNNOTIMPLEMENTED;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+mng_retcode MNG_DECL mng_putimgdata_jhdr (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iColortype,
+ mng_uint8 iBitdepth,
+ mng_uint8 iCompression,
+ mng_uint8 iInterlace,
+ mng_uint8 iAlphaBitdepth,
+ mng_uint8 iAlphaCompression,
+ mng_uint8 iAlphaFilter,
+ mng_uint8 iAlphaInterlace,
+ mng_uint32 iCanvasstyle,
+ mng_getcanvasline fGetcanvasline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTIMGDATA_JHDR, MNG_LC_START);
+#endif
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_PUTIMGDATA_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_FNNOTIMPLEMENTED;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_updatemngheader (mng_handle hHandle,
+ mng_uint32 iFramecount,
+ mng_uint32 iLayercount,
+ mng_uint32 iPlaytime)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_UPDATEMNGHEADER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must be a MNG animation! */
+ if ((pData->eImagetype != mng_it_mng) || (pData->iFirstchunkadded != MNG_UINT_MHDR))
+ MNG_ERROR (pData, MNG_NOMHDR)
+
+ pChunk = pData->pFirstchunk; /* get the first chunk */
+ /* and update the variables */
+ ((mng_mhdrp)pChunk)->iFramecount = iFramecount;
+ ((mng_mhdrp)pChunk)->iLayercount = iLayercount;
+ ((mng_mhdrp)pChunk)->iPlaytime = iPlaytime;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_UPDATEMNGHEADER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_updatemngsimplicity (mng_handle hHandle,
+ mng_uint32 iSimplicity)
+{
+ mng_datap pData;
+ mng_chunkp pChunk;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_UPDATEMNGSIMPLICITY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = (mng_datap)hHandle; /* and make it addressable */
+
+ if (!pData->bCreating) /* aren't we creating a new file ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID)
+ /* must be a MNG animation! */
+ if ((pData->eImagetype != mng_it_mng) || (pData->iFirstchunkadded != MNG_UINT_MHDR))
+ MNG_ERROR (pData, MNG_NOMHDR)
+
+ pChunk = pData->pFirstchunk; /* get the first chunk */
+ /* and update the variable */
+ ((mng_mhdrp)pChunk)->iSimplicity = iSimplicity;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_UPDATEMNGSIMPLICITY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* MNG_ACCESS_CHUNKS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
+
diff --git a/Source/LibMNG/libmng_chunks.h b/Source/LibMNG/libmng_chunks.h
new file mode 100644
index 0000000..d10bf2d
--- /dev/null
+++ b/Source/LibMNG/libmng_chunks.h
@@ -0,0 +1,1026 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_chunks.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Chunk structures (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of known chunk structures * */
+/* * * */
+/* * changes : 0.5.1 - 05/04/2000 - G.Juyn * */
+/* * - put in some extra comments * */
+/* * 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - fixed layout for sBIT, PPLT * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed write callback definition * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - fixed layout for PPLT again (missed deltatype ?!?) * */
+/* * * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - removed useless definition (contributed by Tim Rowley) * */
+/* * 0.5.2 - 06/03/2000 - G.Juyn * */
+/* * - fixed makeup for Linux gcc compile * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added JDAA chunk * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 11/28/2002 - G.Juyn * */
+/* * - fixed definition of iMethodX/Y for MAGN chunk * */
+/* * * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - added conditional around MNG_NO_DELTA_PNG support * */
+/* * * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_chunks_h_
+#define _libmng_chunks_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_SWAP_ENDIAN
+#define PNG_SIG 0x474e5089L
+#define JNG_SIG 0x474e4a8bL
+#define MNG_SIG 0x474e4d8aL
+#define POST_SIG 0x0a1a0a0dL
+#else
+#define PNG_SIG 0x89504e47L
+#define JNG_SIG 0x8b4a4e47L
+#define MNG_SIG 0x8a4d4e47L
+#define POST_SIG 0x0d0a1a0aL
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+
+typedef mng_retcode (*mng_f_specialfunc) (mng_datap pData,
+ mng_chunkp pChunk,
+ mng_uint32* piRawlen,
+ mng_uint8p* ppRawdata);
+
+typedef mng_retcode (*mng_c_specialfunc) (mng_datap pData,
+ mng_chunkp pChunk);
+
+#define MNG_FIELD_OPTIONAL 0x0001
+#define MNG_FIELD_TERMINATOR 0x0002
+#define MNG_FIELD_REPETITIVE 0x0004
+#define MNG_FIELD_DEFLATED 0x0008
+#define MNG_FIELD_IFIMGTYPES 0x01F0 /* image-type mask */
+#define MNG_FIELD_IFIMGTYPE0 0x0010
+#define MNG_FIELD_IFIMGTYPE2 0x0020
+#define MNG_FIELD_IFIMGTYPE3 0x0040
+#define MNG_FIELD_IFIMGTYPE4 0x0080
+#define MNG_FIELD_IFIMGTYPE6 0x0100
+#define MNG_FIELD_PUTIMGTYPE 0x0200
+#define MNG_FIELD_NOHIGHBIT 0x0400
+#define MNG_FIELD_GROUPMASK 0x7000
+#define MNG_FIELD_GROUP1 0x1000
+#define MNG_FIELD_GROUP2 0x2000
+#define MNG_FIELD_GROUP3 0x3000
+#define MNG_FIELD_GROUP4 0x4000
+#define MNG_FIELD_GROUP5 0x5000
+#define MNG_FIELD_GROUP6 0x6000
+#define MNG_FIELD_GROUP7 0x7000
+#define MNG_FIELD_INT 0x8000
+
+typedef struct { /* chunk-field descriptor */
+ mng_f_specialfunc pSpecialfunc;
+ mng_uint16 iFlags;
+ mng_uint16 iMinvalue;
+ mng_uint16 iMaxvalue;
+ mng_uint16 iLengthmin;
+ mng_uint16 iLengthmax;
+ mng_uint16 iOffsetchunk;
+ mng_uint16 iOffsetchunkind;
+ mng_uint16 iOffsetchunklen;
+ } mng_field_descriptor;
+typedef mng_field_descriptor * mng_field_descp;
+
+#define MNG_DESCR_GLOBAL 0x0001
+#define MNG_DESCR_EMPTY 0x0002
+#define MNG_DESCR_EMPTYEMBED 0x0006
+#define MNG_DESCR_EMPTYGLOBAL 0x000A
+
+#define MNG_DESCR_GenHDR 0x0001 /* IHDR/JHDR/BASI/DHDR */
+#define MNG_DESCR_JngHDR 0x0002 /* JHDR/DHDR */
+#define MNG_DESCR_MHDR 0x0004
+#define MNG_DESCR_IHDR 0x0008
+#define MNG_DESCR_JHDR 0x0010
+#define MNG_DESCR_DHDR 0x0020
+#define MNG_DESCR_LOOP 0x0040
+#define MNG_DESCR_PLTE 0x0080
+#define MNG_DESCR_SAVE 0x0100
+
+#define MNG_DESCR_NOIHDR 0x0001
+#define MNG_DESCR_NOJHDR 0x0002
+#define MNG_DESCR_NOBASI 0x0004
+#define MNG_DESCR_NODHDR 0x0008
+#define MNG_DESCR_NOIDAT 0x0010
+#define MNG_DESCR_NOJDAT 0x0020
+#define MNG_DESCR_NOJDAA 0x0040
+#define MNG_DESCR_NOPLTE 0x0080
+#define MNG_DESCR_NOJSEP 0x0100
+#define MNG_DESCR_NOMHDR 0x0200
+#define MNG_DESCR_NOTERM 0x0400
+#define MNG_DESCR_NOLOOP 0x0800
+#define MNG_DESCR_NOSAVE 0x1000
+
+typedef struct { /* chunk descriptor */
+ mng_imgtype eImgtype;
+ mng_createobjtype eCreateobject;
+ mng_uint16 iObjsize;
+ mng_uint16 iOffsetempty;
+ mng_ptr pObjcleanup;
+ mng_ptr pObjprocess;
+ mng_c_specialfunc pSpecialfunc;
+ mng_field_descp pFielddesc;
+ mng_uint16 iFielddesc;
+ mng_uint16 iAllowed;
+ mng_uint16 iMusthaves;
+ mng_uint16 iMustNOThaves;
+ } mng_chunk_descriptor;
+typedef mng_chunk_descriptor * mng_chunk_descp;
+
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+typedef mng_retcode (*mng_createchunk) (mng_datap pData,
+ mng_chunkp pHeader,
+ mng_chunkp* ppChunk);
+
+typedef mng_retcode (*mng_cleanupchunk) (mng_datap pData,
+ mng_chunkp pHeader);
+
+typedef mng_retcode (*mng_readchunk) (mng_datap pData,
+ mng_chunkp pHeader,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata,
+ mng_chunkp* pChunk);
+
+typedef mng_retcode (*mng_writechunk) (mng_datap pData,
+ mng_chunkp pChunk);
+
+typedef mng_retcode (*mng_assignchunk) (mng_datap pData,
+ mng_chunkp pChunkto,
+ mng_chunkp pChunkfrom);
+
+/* ************************************************************************** */
+
+typedef struct { /* generic header */
+ mng_chunkid iChunkname;
+ mng_createchunk fCreate;
+ mng_cleanupchunk fCleanup;
+ mng_readchunk fRead;
+ mng_writechunk fWrite;
+ mng_assignchunk fAssign;
+ mng_chunkp pNext; /* for double-linked list */
+ mng_chunkp pPrev;
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ mng_size_t iChunksize;
+#endif
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_chunk_descp pChunkdescr;
+#endif
+ } mng_chunk_header;
+typedef mng_chunk_header * mng_chunk_headerp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IHDR */
+ mng_chunk_header sHeader;
+ mng_uint32 iWidth;
+ mng_uint32 iHeight;
+ mng_uint8 iBitdepth;
+ mng_uint8 iColortype;
+ mng_uint8 iCompression;
+ mng_uint8 iFilter;
+ mng_uint8 iInterlace;
+ } mng_ihdr;
+typedef mng_ihdr * mng_ihdrp;
+
+/* ************************************************************************** */
+
+typedef struct { /* PLTE */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iEntrycount;
+ mng_rgbpaltab aEntries;
+ } mng_plte;
+typedef mng_plte * mng_pltep;
+
+/* ************************************************************************** */
+
+typedef struct { /* IDAT */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iDatasize;
+ mng_ptr pData;
+ } mng_idat;
+typedef mng_idat * mng_idatp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IEND */
+ mng_chunk_header sHeader;
+ } mng_iend;
+typedef mng_iend * mng_iendp;
+
+/* ************************************************************************** */
+
+typedef struct { /* tRNS */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_bool bGlobal;
+ mng_uint8 iType; /* colortype (0,2,3) */
+ mng_uint32 iCount;
+ mng_uint8arr aEntries;
+ mng_uint16 iGray;
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ mng_uint32 iRawlen;
+ mng_uint8arr aRawdata;
+ } mng_trns;
+typedef mng_trns * mng_trnsp;
+
+/* ************************************************************************** */
+
+typedef struct { /* gAMA */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iGamma;
+ } mng_gama;
+typedef mng_gama * mng_gamap;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+typedef struct { /* cHRM */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iWhitepointx;
+ mng_uint32 iWhitepointy;
+ mng_uint32 iRedx;
+ mng_uint32 iRedy;
+ mng_uint32 iGreenx;
+ mng_uint32 iGreeny;
+ mng_uint32 iBluex;
+ mng_uint32 iBluey;
+ } mng_chrm;
+typedef mng_chrm * mng_chrmp;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* sRGB */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint8 iRenderingintent;
+ } mng_srgb;
+typedef mng_srgb * mng_srgbp;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+typedef struct { /* iCCP */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ mng_uint8 iCompression;
+ mng_uint32 iProfilesize;
+ mng_ptr pProfile;
+ } mng_iccp;
+typedef mng_iccp * mng_iccpp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tEXt
+typedef struct { /* tEXt */
+ mng_chunk_header sHeader;
+ mng_uint32 iKeywordsize;
+ mng_pchar zKeyword;
+ mng_uint32 iTextsize;
+ mng_pchar zText;
+ } mng_text;
+typedef mng_text * mng_textp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_zTXt
+typedef struct { /* zTXt */
+ mng_chunk_header sHeader;
+ mng_uint32 iKeywordsize;
+ mng_pchar zKeyword;
+ mng_uint8 iCompression;
+ mng_uint32 iTextsize;
+ mng_pchar zText;
+ } mng_ztxt;
+typedef mng_ztxt * mng_ztxtp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iTXt
+typedef struct { /* iTXt */
+ mng_chunk_header sHeader;
+ mng_uint32 iKeywordsize;
+ mng_pchar zKeyword;
+ mng_uint8 iCompressionflag;
+ mng_uint8 iCompressionmethod;
+ mng_uint32 iLanguagesize;
+ mng_pchar zLanguage;
+ mng_uint32 iTranslationsize;
+ mng_pchar zTranslation;
+ mng_uint32 iTextsize;
+ mng_pchar zText;
+ } mng_itxt;
+typedef mng_itxt * mng_itxtp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+typedef struct { /* bKGD */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint8 iType; /* 3=indexed, 0=gray, 2=rgb */
+ mng_uint8 iIndex;
+ mng_uint16 iGray;
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ } mng_bkgd;
+typedef mng_bkgd * mng_bkgdp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYs
+typedef struct { /* pHYs */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iSizex;
+ mng_uint32 iSizey;
+ mng_uint8 iUnit;
+ } mng_phys;
+typedef mng_phys * mng_physp;
+#endif
+
+/* ************************************************************************** */
+#ifndef MNG_SKIPCHUNK_sBIT
+
+typedef struct { /* sBIT */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint8 iType; /* colortype (0,2,3,4,6,10,12,14,16) */
+ mng_uint8arr4 aBits;
+ } mng_sbit;
+typedef mng_sbit * mng_sbitp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sPLT
+typedef struct { /* sPLT */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ mng_uint8 iSampledepth;
+ mng_uint32 iEntrycount;
+ mng_ptr pEntries;
+ } mng_splt;
+typedef mng_splt * mng_spltp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_hIST
+typedef struct { /* hIST */
+ mng_chunk_header sHeader;
+ mng_uint32 iEntrycount;
+ mng_uint16arr aEntries;
+ } mng_hist;
+typedef mng_hist * mng_histp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_tIME
+typedef struct { /* tIME */
+ mng_chunk_header sHeader;
+ mng_uint16 iYear;
+ mng_uint8 iMonth;
+ mng_uint8 iDay;
+ mng_uint8 iHour;
+ mng_uint8 iMinute;
+ mng_uint8 iSecond;
+ } mng_time;
+typedef mng_time * mng_timep;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* MHDR */
+ mng_chunk_header sHeader;
+ mng_uint32 iWidth;
+ mng_uint32 iHeight;
+ mng_uint32 iTicks;
+ mng_uint32 iLayercount;
+ mng_uint32 iFramecount;
+ mng_uint32 iPlaytime;
+ mng_uint32 iSimplicity;
+ } mng_mhdr;
+typedef mng_mhdr * mng_mhdrp;
+
+/* ************************************************************************** */
+
+typedef struct { /* MEND */
+ mng_chunk_header sHeader;
+ } mng_mend;
+typedef mng_mend * mng_mendp;
+
+/* ************************************************************************** */
+
+typedef struct { /* LOOP */
+ mng_chunk_header sHeader;
+ mng_uint8 iLevel;
+ mng_uint32 iRepeat;
+ mng_uint8 iTermination;
+ mng_uint32 iItermin;
+ mng_uint32 iItermax;
+ mng_uint32 iCount;
+ mng_uint32p pSignals;
+ } mng_loop;
+typedef mng_loop * mng_loopp;
+
+/* ************************************************************************** */
+
+typedef struct { /* ENDL */
+ mng_chunk_header sHeader;
+ mng_uint8 iLevel;
+ } mng_endl;
+typedef mng_endl * mng_endlp;
+
+/* ************************************************************************** */
+
+typedef struct { /* DEFI */
+ mng_chunk_header sHeader;
+ mng_uint16 iObjectid;
+ mng_bool bHasdonotshow;
+ mng_uint8 iDonotshow;
+ mng_bool bHasconcrete;
+ mng_uint8 iConcrete;
+ mng_bool bHasloca;
+ mng_int32 iXlocation;
+ mng_int32 iYlocation;
+ mng_bool bHasclip;
+ mng_int32 iLeftcb;
+ mng_int32 iRightcb;
+ mng_int32 iTopcb;
+ mng_int32 iBottomcb;
+ } mng_defi;
+typedef mng_defi * mng_defip;
+
+/* ************************************************************************** */
+
+typedef struct { /* BASI */
+ mng_chunk_header sHeader;
+ mng_uint32 iWidth;
+ mng_uint32 iHeight;
+ mng_uint8 iBitdepth;
+ mng_uint8 iColortype;
+ mng_uint8 iCompression;
+ mng_uint8 iFilter;
+ mng_uint8 iInterlace;
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_bool bHasalpha;
+#endif
+ mng_uint16 iAlpha;
+ mng_uint8 iViewable;
+ } mng_basi;
+typedef mng_basi * mng_basip;
+
+/* ************************************************************************** */
+
+typedef struct { /* CLON */
+ mng_chunk_header sHeader;
+ mng_uint16 iSourceid;
+ mng_uint16 iCloneid;
+ mng_uint8 iClonetype;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_bool bHasdonotshow;
+#endif
+ mng_uint8 iDonotshow;
+ mng_uint8 iConcrete;
+ mng_bool bHasloca;
+ mng_uint8 iLocationtype;
+ mng_int32 iLocationx;
+ mng_int32 iLocationy;
+ } mng_clon;
+typedef mng_clon * mng_clonp;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+typedef struct { /* PAST source */
+ mng_uint16 iSourceid;
+ mng_uint8 iComposition;
+ mng_uint8 iOrientation;
+ mng_uint8 iOffsettype;
+ mng_int32 iOffsetx;
+ mng_int32 iOffsety;
+ mng_uint8 iBoundarytype;
+ mng_int32 iBoundaryl;
+ mng_int32 iBoundaryr;
+ mng_int32 iBoundaryt;
+ mng_int32 iBoundaryb;
+ } mng_past_source;
+typedef mng_past_source * mng_past_sourcep;
+
+typedef struct { /* PAST */
+ mng_chunk_header sHeader;
+ mng_uint16 iDestid;
+ mng_uint8 iTargettype;
+ mng_int32 iTargetx;
+ mng_int32 iTargety;
+ mng_uint32 iCount;
+ mng_past_sourcep pSources;
+ } mng_past;
+typedef mng_past * mng_pastp;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* DISC */
+ mng_chunk_header sHeader;
+ mng_uint32 iCount;
+ mng_uint16p pObjectids;
+ } mng_disc;
+typedef mng_disc * mng_discp;
+
+/* ************************************************************************** */
+
+typedef struct { /* BACK */
+ mng_chunk_header sHeader;
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ mng_uint8 iMandatory;
+ mng_uint16 iImageid;
+ mng_uint8 iTile;
+ } mng_back;
+typedef mng_back * mng_backp;
+
+/* ************************************************************************** */
+
+typedef struct { /* FRAM */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint8 iMode;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ mng_uint8 iChangedelay;
+ mng_uint8 iChangetimeout;
+ mng_uint8 iChangeclipping;
+ mng_uint8 iChangesyncid;
+ mng_uint32 iDelay;
+ mng_uint32 iTimeout;
+ mng_uint8 iBoundarytype;
+ mng_int32 iBoundaryl;
+ mng_int32 iBoundaryr;
+ mng_int32 iBoundaryt;
+ mng_int32 iBoundaryb;
+ mng_uint32 iCount;
+ mng_uint32p pSyncids;
+ } mng_fram;
+typedef mng_fram * mng_framp;
+
+/* ************************************************************************** */
+
+typedef struct { /* MOVE */
+ mng_chunk_header sHeader;
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iMovetype;
+ mng_int32 iMovex;
+ mng_int32 iMovey;
+ } mng_move;
+typedef mng_move * mng_movep;
+
+/* ************************************************************************** */
+
+typedef struct { /* CLIP */
+ mng_chunk_header sHeader;
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iCliptype;
+ mng_int32 iClipl;
+ mng_int32 iClipr;
+ mng_int32 iClipt;
+ mng_int32 iClipb;
+ } mng_clip;
+typedef mng_clip * mng_clipp;
+
+/* ************************************************************************** */
+
+typedef struct { /* SHOW */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint16 iFirstid;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_bool bHaslastid;
+#endif
+ mng_uint16 iLastid;
+ mng_uint8 iMode;
+ } mng_show;
+typedef mng_show * mng_showp;
+
+/* ************************************************************************** */
+
+typedef struct { /* TERM */
+ mng_chunk_header sHeader;
+ mng_uint8 iTermaction;
+ mng_uint8 iIteraction;
+ mng_uint32 iDelay;
+ mng_uint32 iItermax;
+ } mng_term;
+typedef mng_term * mng_termp;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+typedef struct { /* SAVE entry */
+ mng_uint8 iEntrytype;
+ mng_uint32arr2 iOffset; /* 0=MSI, 1=LSI */
+ mng_uint32arr2 iStarttime; /* 0=MSI, 1=LSI */
+ mng_uint32 iLayernr;
+ mng_uint32 iFramenr;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ } mng_save_entry;
+typedef mng_save_entry * mng_save_entryp;
+
+typedef struct { /* SAVE */
+ mng_chunk_header sHeader;
+ mng_bool bEmpty;
+ mng_uint8 iOffsettype;
+ mng_uint32 iCount;
+ mng_save_entryp pEntries;
+ } mng_save;
+typedef mng_save * mng_savep;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+typedef struct { /* SEEK */
+ mng_chunk_header sHeader;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ } mng_seek;
+typedef mng_seek * mng_seekp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_eXPI
+typedef struct { /* eXPI */
+ mng_chunk_header sHeader;
+ mng_uint16 iSnapshotid;
+ mng_uint32 iNamesize;
+ mng_pchar zName;
+ } mng_expi;
+typedef mng_expi * mng_expip;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_fPRI
+typedef struct { /* fPRI */
+ mng_chunk_header sHeader;
+ mng_uint8 iDeltatype;
+ mng_uint8 iPriority;
+ } mng_fpri;
+typedef mng_fpri * mng_fprip;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_nEED
+typedef struct { /* nEED */
+ mng_chunk_header sHeader;
+ mng_uint32 iKeywordssize;
+ mng_pchar zKeywords;
+ } mng_need;
+typedef mng_need * mng_needp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_pHYg
+typedef mng_phys mng_phyg; /* pHYg */
+typedef mng_phyg * mng_phygp;
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+typedef struct { /* JHDR */
+ mng_chunk_header sHeader;
+ mng_uint32 iWidth;
+ mng_uint32 iHeight;
+ mng_uint8 iColortype;
+ mng_uint8 iImagesampledepth;
+ mng_uint8 iImagecompression;
+ mng_uint8 iImageinterlace;
+ mng_uint8 iAlphasampledepth;
+ mng_uint8 iAlphacompression;
+ mng_uint8 iAlphafilter;
+ mng_uint8 iAlphainterlace;
+ } mng_jhdr;
+typedef mng_jhdr * mng_jhdrp;
+
+/* ************************************************************************** */
+
+typedef mng_idat mng_jdaa; /* JDAA */
+typedef mng_jdaa * mng_jdaap;
+
+/* ************************************************************************** */
+
+typedef mng_idat mng_jdat; /* JDAT */
+typedef mng_jdat * mng_jdatp;
+
+/* ************************************************************************** */
+
+typedef struct { /* JSEP */
+ mng_chunk_header sHeader;
+ } mng_jsep;
+typedef mng_jsep * mng_jsepp;
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+
+typedef struct { /* DHDR */
+ mng_chunk_header sHeader;
+ mng_uint16 iObjectid;
+ mng_uint8 iImagetype;
+ mng_uint8 iDeltatype;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_bool bHasblocksize;
+#endif
+ mng_uint32 iBlockwidth;
+ mng_uint32 iBlockheight;
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ mng_bool bHasblockloc;
+#endif
+ mng_uint32 iBlockx;
+ mng_uint32 iBlocky;
+ } mng_dhdr;
+typedef mng_dhdr * mng_dhdrp;
+
+/* ************************************************************************** */
+
+typedef struct { /* PROM */
+ mng_chunk_header sHeader;
+ mng_uint8 iColortype;
+ mng_uint8 iSampledepth;
+ mng_uint8 iFilltype;
+ } mng_prom;
+typedef mng_prom * mng_promp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IPNG */
+ mng_chunk_header sHeader;
+ } mng_ipng;
+typedef mng_ipng *mng_ipngp;
+
+/* ************************************************************************** */
+
+typedef struct { /* PPLT entry */
+ mng_uint8 iRed;
+ mng_uint8 iGreen;
+ mng_uint8 iBlue;
+ mng_uint8 iAlpha;
+ mng_bool bUsed;
+ } mng_pplt_entry;
+typedef mng_pplt_entry * mng_pplt_entryp;
+
+typedef struct { /* PPLT */
+ mng_chunk_header sHeader;
+ mng_uint8 iDeltatype;
+ mng_uint32 iCount;
+ mng_pplt_entry aEntries [256];
+ } mng_pplt;
+typedef mng_pplt * mng_ppltp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IJNG */
+ mng_chunk_header sHeader;
+ } mng_ijng;
+typedef mng_ijng *mng_ijngp;
+
+/* ************************************************************************** */
+
+typedef struct { /* DROP */
+ mng_chunk_header sHeader;
+ mng_uint32 iCount;
+ mng_chunkidp pChunknames;
+ } mng_drop;
+typedef mng_drop * mng_dropp;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DBYK
+typedef struct { /* DBYK */
+ mng_chunk_header sHeader;
+ mng_chunkid iChunkname;
+ mng_uint8 iPolarity;
+ mng_uint32 iKeywordssize;
+ mng_pchar zKeywords;
+ } mng_dbyk;
+typedef mng_dbyk * mng_dbykp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_ORDR
+typedef struct { /* ORDR entry */
+ mng_chunkid iChunkname;
+ mng_uint8 iOrdertype;
+ } mng_ordr_entry;
+typedef mng_ordr_entry * mng_ordr_entryp;
+
+typedef struct mng_ordr_struct { /* ORDR */
+ mng_chunk_header sHeader;
+ mng_uint32 iCount;
+ mng_ordr_entryp pEntries;
+ } mng_ordr;
+typedef mng_ordr * mng_ordrp;
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+
+typedef struct { /* MAGN */
+ mng_chunk_header sHeader;
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iMethodX;
+ mng_uint16 iMX;
+ mng_uint16 iMY;
+ mng_uint16 iML;
+ mng_uint16 iMR;
+ mng_uint16 iMT;
+ mng_uint16 iMB;
+ mng_uint8 iMethodY;
+ } mng_magn;
+typedef mng_magn * mng_magnp;
+
+/* ************************************************************************** */
+
+typedef struct { /* evNT entry */
+ mng_uint8 iEventtype;
+ mng_uint8 iMasktype;
+ mng_int32 iLeft;
+ mng_int32 iRight;
+ mng_int32 iTop;
+ mng_int32 iBottom;
+ mng_uint16 iObjectid;
+ mng_uint8 iIndex;
+ mng_uint32 iSegmentnamesize;
+ mng_pchar zSegmentname;
+ } mng_evnt_entry;
+typedef mng_evnt_entry * mng_evnt_entryp;
+
+typedef struct { /* evNT */
+ mng_chunk_header sHeader;
+ mng_uint32 iCount;
+ mng_evnt_entryp pEntries;
+ } mng_evnt;
+typedef mng_evnt * mng_evntp;
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+typedef struct { /* mpNG frame */
+ mng_uint32 iX;
+ mng_uint32 iY;
+ mng_uint32 iWidth;
+ mng_uint32 iHeight;
+ mng_int32 iXoffset;
+ mng_int32 iYoffset;
+ mng_uint16 iTicks;
+ } mng_mpng_frame;
+typedef mng_mpng_frame * mng_mpng_framep;
+
+typedef struct { /* mpNG */
+ mng_chunk_header sHeader;
+ mng_uint32 iFramewidth;
+ mng_uint32 iFrameheight;
+ mng_uint16 iNumplays;
+ mng_uint16 iTickspersec;
+ mng_uint8 iCompressionmethod;
+ mng_uint32 iFramessize;
+ mng_mpng_framep pFrames;
+ } mng_mpng;
+typedef mng_mpng * mng_mpngp;
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+typedef struct { /* ahDR */
+ mng_chunk_header sHeader;
+ mng_uint32 iNumframes;
+ mng_uint32 iTickspersec;
+ mng_uint32 iNumplays;
+ mng_uint32 iTilewidth;
+ mng_uint32 iTileheight;
+ mng_uint8 iInterlace;
+ mng_uint8 iStillused;
+ } mng_ahdr;
+typedef mng_ahdr * mng_ahdrp;
+
+typedef struct { /* adAT tile */
+ mng_uint32 iTicks;
+ mng_int32 iXoffset;
+ mng_int32 iYoffset;
+ mng_uint8 iTilesource;
+ } mng_adat_tile;
+typedef mng_adat_tile * mng_adat_tilep;
+
+typedef struct { /* adAT */
+ mng_chunk_header sHeader;
+ mng_uint32 iTilessize;
+ mng_adat_tilep pTiles;
+ } mng_adat;
+typedef mng_adat * mng_adatp;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* unknown chunk */
+ mng_chunk_header sHeader;
+ mng_uint32 iDatasize;
+ mng_ptr pData;
+ } mng_unknown_chunk;
+typedef mng_unknown_chunk * mng_unknown_chunkp;
+
+/* ************************************************************************** */
+
+#endif /* _libmng_chunks_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_cms.c b/Source/LibMNG/libmng_cms.c
new file mode 100644
index 0000000..999575f
--- /dev/null
+++ b/Source/LibMNG/libmng_cms.c
@@ -0,0 +1,758 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_cms.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : color management routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the color management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/01/2000 - G.Juyn * */
+/* * - B001(105795) - fixed a typo and misconception about * */
+/* * freeing allocated gamma-table. (reported by Marti Maria) * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/09/2000 - G.Juyn * */
+/* * - filled application-based color-management routines * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added creatememprofile * */
+/* * - added callback error-reporting support * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 06/10/2000 - G.Juyn * */
+/* * - fixed some compilation-warnings (contrib Jason Morris) * */
+/* * * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - fixed problem with color-correction for stored images * */
+/* * 0.5.3 - 06/23/2000 - G.Juyn * */
+/* * - fixed problem with incorrect gamma-correction * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/31/2000 - G.Juyn * */
+/* * - fixed sRGB precedence for gamma_only corection * */
+/* * * */
+/* * 0.9.4 - 12/16/2000 - G.Juyn * */
+/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
+/* * * */
+/* * 1.0.1 - 03/31/2001 - G.Juyn * */
+/* * - ignore gamma=0 (see png-list for more info) * */
+/* * 1.0.1 - 04/25/2001 - G.Juyn (reported by Gregg Kelly) * */
+/* * - fixed problem with cms profile being created multiple * */
+/* * times when both iCCP & cHRM/gAMA are present * */
+/* * 1.0.1 - 04/25/2001 - G.Juyn * */
+/* * - moved mng_clear_cms to libmng_cms * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - optimized color-correction routines * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added in-memory color-correction of abstract images * */
+/* * 1.0.5 - 11/08/2002 - G.Juyn * */
+/* * - fixed issues in init_app_cms() * */
+/* * * */
+/* * 1.0.6 - 04/11/2003 - G.Juyn * */
+/* * - B719420 - fixed several MNG_APP_CMS problems * */
+/* * 1.0.6 - 07/11/2003 - G. R-P * */
+/* * - added conditional MNG_SKIPCHUNK_cHRM/iCCP * */
+/* * * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_objects.h"
+#include "libmng_cms.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+/* * * */
+/* * Little CMS helper routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_LCMS
+
+#define MNG_CMS_FLAGS 0
+
+/* ************************************************************************** */
+
+void mnglcms_initlibrary ()
+{
+ cmsErrorAction (LCMS_ERROR_IGNORE); /* LCMS should ignore errors! */
+}
+
+/* ************************************************************************** */
+
+mng_cmsprof mnglcms_createfileprofile (mng_pchar zFilename)
+{
+ return cmsOpenProfileFromFile (zFilename, "r");
+}
+
+/* ************************************************************************** */
+
+mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize,
+ mng_ptr pProfile)
+{
+ return cmsOpenProfileFromMem (pProfile, iProfilesize);
+}
+
+/* ************************************************************************** */
+
+mng_cmsprof mnglcms_createsrgbprofile (void)
+{
+ cmsCIExyY D65;
+ cmsCIExyYTRIPLE Rec709Primaries = {
+ {0.6400, 0.3300, 1.0},
+ {0.3000, 0.6000, 1.0},
+ {0.1500, 0.0600, 1.0}
+ };
+ LPGAMMATABLE Gamma24[3];
+ mng_cmsprof hsRGB;
+
+ cmsWhitePointFromTemp(6504, &D65);
+ Gamma24[0] = Gamma24[1] = Gamma24[2] = cmsBuildGamma(256, 2.4);
+ hsRGB = cmsCreateRGBProfile(&D65, &Rec709Primaries, Gamma24);
+ cmsFreeGamma(Gamma24[0]);
+
+ return hsRGB;
+}
+
+/* ************************************************************************** */
+
+void mnglcms_freeprofile (mng_cmsprof hProf)
+{
+ cmsCloseProfile (hProf);
+ return;
+}
+
+/* ************************************************************************** */
+
+void mnglcms_freetransform (mng_cmstrans hTrans)
+{
+/* B001 start */
+ cmsDeleteTransform (hTrans);
+/* B001 end */
+ return;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_clear_cms (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_START);
+#endif
+
+ if (pData->hTrans) /* transformation still active ? */
+ mnglcms_freetransform (pData->hTrans);
+
+ pData->hTrans = 0;
+
+ if (pData->hProf1) /* file profile still active ? */
+ mnglcms_freeprofile (pData->hProf1);
+
+ pData->hProf1 = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEAR_CMS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_LCMS */
+
+/* ************************************************************************** */
+/* * * */
+/* * Color-management initialization & correction routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_LCMS
+
+mng_retcode mng_init_full_cms (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj)
+{
+ mng_cmsprof hProf;
+ mng_cmstrans hTrans;
+ mng_imagep pImage = MNG_NULL;
+ mng_imagedatap pBuf = MNG_NULL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_START);
+#endif
+
+ if (bObject) /* use object if present ? */
+ { /* current object ? */
+ if ((mng_imagep)pData->pCurrentobj)
+ pImage = (mng_imagep)pData->pCurrentobj;
+ else /* if not; use object 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+
+ if (bRetrobj) /* retrieving from an object ? */
+ pImage = (mng_imagep)pData->pRetrieveobj;
+
+ if (pImage) /* are we using an object ? */
+ pBuf = pImage->pImgbuf; /* then address the buffer */
+
+ if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
+ {
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP)))
+ {
+ if (!pData->hProf2) /* output profile not defined ? */
+ { /* then assume sRGB !! */
+ pData->hProf2 = mnglcms_createsrgbprofile ();
+
+ if (!pData->hProf2) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+ }
+
+ if ((pBuf) && (pBuf->bHasICCP)) /* generate a profile handle */
+ hProf = cmsOpenProfileFromMem (pBuf->pProfile, pBuf->iProfilesize);
+ else
+ hProf = cmsOpenProfileFromMem (pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ pData->hProf1 = hProf; /* save for future use */
+
+ if (!hProf) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->bIsRGBA16) /* 16-bit intermediates ? */
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
+ pData->hProf2, TYPE_RGBA_16_SE,
+ INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
+ else
+#endif
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
+ pData->hProf2, TYPE_RGBA_8,
+ INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
+
+ pData->hTrans = hTrans; /* save for future use */
+
+ if (!hTrans) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
+
+ return MNG_NOERROR; /* and done */
+ }
+ else
+#endif
+ if (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB)))
+ {
+ mng_uint8 iIntent;
+
+ if (pData->bIssRGB) /* sRGB system ? */
+ return MNG_NOERROR; /* no conversion required */
+
+ if (!pData->hProf3) /* sRGB profile not defined ? */
+ { /* then create it implicitly !! */
+ pData->hProf3 = mnglcms_createsrgbprofile ();
+
+ if (!pData->hProf3) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+ }
+
+ hProf = pData->hProf3; /* convert from sRGB profile */
+
+ if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */
+ iIntent = pBuf->iRenderingintent;
+ else
+ iIntent = pData->iGlobalRendintent;
+
+ if (pData->bIsRGBA16) /* 16-bit intermediates ? */
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
+ pData->hProf2, TYPE_RGBA_16_SE,
+ iIntent, MNG_CMS_FLAGS);
+ else
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
+ pData->hProf2, TYPE_RGBA_8,
+ iIntent, MNG_CMS_FLAGS);
+
+ pData->hTrans = hTrans; /* save for future use */
+
+ if (!hTrans) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
+
+ return MNG_NOERROR; /* and done */
+ }
+ else
+ if ( (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) &&
+ ( ((pBuf) && (pBuf->bHasGAMA) && (pBuf->iGamma > 0)) ||
+ ((bGlobal) && (pData->bHasglobalGAMA) && (pData->iGlobalGamma > 0)) ) )
+ {
+ mng_CIExyY sWhitepoint;
+ mng_CIExyYTRIPLE sPrimaries;
+ mng_gammatabp pGammatable[3];
+ mng_float dGamma;
+
+ if (!pData->hProf2) /* output profile not defined ? */
+ { /* then assume sRGB !! */
+ pData->hProf2 = mnglcms_createsrgbprofile ();
+
+ if (!pData->hProf2) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+ }
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */
+ {
+ sWhitepoint.x = (mng_float)pBuf->iWhitepointx / 100000;
+ sWhitepoint.y = (mng_float)pBuf->iWhitepointy / 100000;
+ sPrimaries.Red.x = (mng_float)pBuf->iPrimaryredx / 100000;
+ sPrimaries.Red.y = (mng_float)pBuf->iPrimaryredy / 100000;
+ sPrimaries.Green.x = (mng_float)pBuf->iPrimarygreenx / 100000;
+ sPrimaries.Green.y = (mng_float)pBuf->iPrimarygreeny / 100000;
+ sPrimaries.Blue.x = (mng_float)pBuf->iPrimarybluex / 100000;
+ sPrimaries.Blue.y = (mng_float)pBuf->iPrimarybluey / 100000;
+ }
+ else
+ {
+ sWhitepoint.x = (mng_float)pData->iGlobalWhitepointx / 100000;
+ sWhitepoint.y = (mng_float)pData->iGlobalWhitepointy / 100000;
+ sPrimaries.Red.x = (mng_float)pData->iGlobalPrimaryredx / 100000;
+ sPrimaries.Red.y = (mng_float)pData->iGlobalPrimaryredy / 100000;
+ sPrimaries.Green.x = (mng_float)pData->iGlobalPrimarygreenx / 100000;
+ sPrimaries.Green.y = (mng_float)pData->iGlobalPrimarygreeny / 100000;
+ sPrimaries.Blue.x = (mng_float)pData->iGlobalPrimarybluex / 100000;
+ sPrimaries.Blue.y = (mng_float)pData->iGlobalPrimarybluey / 100000;
+ }
+#endif
+
+ sWhitepoint.Y = /* Y component is always 1.0 */
+ sPrimaries.Red.Y =
+ sPrimaries.Green.Y =
+ sPrimaries.Blue.Y = 1.0;
+
+ if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */
+ dGamma = (mng_float)pBuf->iGamma / 100000;
+ else
+ dGamma = (mng_float)pData->iGlobalGamma / 100000;
+
+ dGamma = pData->dViewgamma / dGamma;
+
+ pGammatable [0] = /* and build the lookup tables */
+ pGammatable [1] =
+ pGammatable [2] = cmsBuildGamma (256, dGamma);
+
+ if (!pGammatable [0]) /* enough memory ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOMEM);
+ /* create the profile */
+ hProf = cmsCreateRGBProfile (&sWhitepoint, &sPrimaries, pGammatable);
+
+ cmsFreeGamma (pGammatable [0]); /* free the temporary gamma tables ? */
+ /* yes! but just the one! */
+
+ pData->hProf1 = hProf; /* save for future use */
+
+ if (!hProf) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+
+ if (pData->bIsRGBA16) /* 16-bit intermediates ? */
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_16_SE,
+ pData->hProf2, TYPE_RGBA_16_SE,
+ INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
+ else
+ hTrans = cmsCreateTransform (hProf, TYPE_RGBA_8,
+ pData->hProf2, TYPE_RGBA_8,
+ INTENT_PERCEPTUAL, MNG_CMS_FLAGS);
+
+ pData->hTrans = hTrans; /* save for future use */
+
+ if (!hTrans) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOTRANS);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_full_cms;
+
+ return MNG_NOERROR; /* and done */
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_FULL_CMS, MNG_LC_END);
+#endif
+ /* if we get here, we'll only do gamma */
+ return mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
+}
+#endif /* MNG_INCLUDE_LCMS */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_LCMS
+mng_retcode mng_correct_full_cms (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_START);
+#endif
+
+ cmsDoTransform (pData->hTrans, pData->pRGBArow, pData->pRGBArow, pData->iRowsamples);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_FULL_CMS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_LCMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
+mng_retcode mng_init_gamma_only (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj)
+{
+ mng_float dGamma;
+ mng_imagep pImage = MNG_NULL;
+ mng_imagedatap pBuf = MNG_NULL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_START);
+#endif
+
+ if (bObject) /* use object if present ? */
+ { /* current object ? */
+ if ((mng_imagep)pData->pCurrentobj)
+ pImage = (mng_imagep)pData->pCurrentobj;
+ else /* if not; use object 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+
+ if (bRetrobj) /* retrieving from an object ? */
+ pImage = (mng_imagep)pData->pRetrieveobj;
+
+ if (pImage) /* are we using an object ? */
+ pBuf = pImage->pImgbuf; /* then address the buffer */
+
+ if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
+ {
+ if ((pBuf) && (pBuf->bHasSRGB)) /* get the gamma value */
+ dGamma = 0.45455;
+ else
+ if ((pBuf) && (pBuf->bHasGAMA))
+ dGamma = (mng_float)pBuf->iGamma / 100000;
+ else
+ if ((bGlobal) && (pData->bHasglobalSRGB))
+ dGamma = 0.45455;
+ else
+ if ((bGlobal) && (pData->bHasglobalGAMA))
+ dGamma = (mng_float)pData->iGlobalGamma / 100000;
+ else
+ dGamma = pData->dDfltimggamma;
+
+ if (dGamma > 0) /* ignore gamma=0 */
+ {
+ dGamma = pData->dViewgamma / (dGamma * pData->dDisplaygamma);
+
+ if (dGamma != pData->dLastgamma) /* lookup table needs to be computed ? */
+ {
+ mng_int32 iX;
+
+ pData->aGammatab [0] = 0;
+
+ for (iX = 1; iX <= 255; iX++)
+ pData->aGammatab [iX] = (mng_uint8)(pow (iX / 255.0, dGamma) * 255 + 0.5);
+
+ pData->dLastgamma = dGamma; /* keep for next time */
+ }
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_gamma_only;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GAMMA_ONLY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
+mng_retcode mng_correct_gamma_only (mng_datap pData)
+{
+ mng_uint8p pWork;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_START);
+#endif
+
+ pWork = pData->pRGBArow; /* address intermediate row */
+
+ if (pData->bIsRGBA16) /* 16-bit intermediate row ? */
+ {
+
+
+ /* TODO: 16-bit precision gamma processing */
+ /* we'll just do the high-order byte for now */
+
+
+ /* convert all samples in the row */
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+ { /* using the precalculated gamma lookup table */
+ *pWork = pData->aGammatab [*pWork];
+ *(pWork+2) = pData->aGammatab [*(pWork+2)];
+ *(pWork+4) = pData->aGammatab [*(pWork+4)];
+
+ pWork += 8;
+ }
+ }
+ else
+ { /* convert all samples in the row */
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+ { /* using the precalculated gamma lookup table */
+ *pWork = pData->aGammatab [*pWork];
+ *(pWork+1) = pData->aGammatab [*(pWork+1)];
+ *(pWork+2) = pData->aGammatab [*(pWork+2)];
+
+ pWork += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_GAMMA_ONLY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_GAMMA_ONLY || MNG_FULL_CMS || MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#ifdef MNG_APP_CMS
+mng_retcode mng_init_app_cms (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj)
+{
+ mng_imagep pImage = MNG_NULL;
+ mng_imagedatap pBuf = MNG_NULL;
+ mng_bool bDone = MNG_FALSE;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_START);
+#endif
+
+ if (bObject) /* use object if present ? */
+ { /* current object ? */
+ if ((mng_imagep)pData->pCurrentobj)
+ pImage = (mng_imagep)pData->pCurrentobj;
+ else /* if not; use object 0 */
+ pImage = (mng_imagep)pData->pObjzero;
+ }
+
+ if (bRetrobj) /* retrieving from an object ? */
+ pImage = (mng_imagep)pData->pRetrieveobj;
+
+ if (pImage) /* are we using an object ? */
+ pBuf = pImage->pImgbuf; /* then address the buffer */
+
+ if ((!pBuf) || (!pBuf->bCorrected)) /* is the buffer already corrected ? */
+ {
+#ifndef MNG_SKIPCHUNK_iCCP
+ if ( (pData->fProcessiccp) &&
+ (((pBuf) && (pBuf->bHasICCP)) || ((bGlobal) && (pData->bHasglobalICCP))) )
+ {
+ mng_uint32 iProfilesize;
+ mng_ptr pProfile;
+
+ if ((pBuf) && (pBuf->bHasICCP)) /* get the right profile */
+ {
+ iProfilesize = pBuf->iProfilesize;
+ pProfile = pBuf->pProfile;
+ }
+ else
+ {
+ iProfilesize = pData->iGlobalProfilesize;
+ pProfile = pData->pGlobalProfile;
+ }
+ /* inform the app */
+ if (!pData->fProcessiccp ((mng_handle)pData, iProfilesize, pProfile))
+ MNG_ERROR (pData, MNG_APPCMSERROR);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
+ bDone = MNG_TRUE;
+ }
+#endif
+
+ if ( (pData->fProcesssrgb) &&
+ (((pBuf) && (pBuf->bHasSRGB)) || ((bGlobal) && (pData->bHasglobalSRGB))) )
+ {
+ mng_uint8 iIntent;
+
+ if ((pBuf) && (pBuf->bHasSRGB)) /* determine rendering intent */
+ iIntent = pBuf->iRenderingintent;
+ else
+ iIntent = pData->iGlobalRendintent;
+ /* inform the app */
+ if (!pData->fProcesssrgb ((mng_handle)pData, iIntent))
+ MNG_ERROR (pData, MNG_APPCMSERROR);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
+ bDone = MNG_TRUE;
+ }
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ if ( (pData->fProcesschroma) &&
+ (((pBuf) && (pBuf->bHasCHRM)) || ((bGlobal) && (pData->bHasglobalCHRM))) )
+ {
+ mng_uint32 iWhitepointx, iWhitepointy;
+ mng_uint32 iPrimaryredx, iPrimaryredy;
+ mng_uint32 iPrimarygreenx, iPrimarygreeny;
+ mng_uint32 iPrimarybluex, iPrimarybluey;
+
+ if ((pBuf) && (pBuf->bHasCHRM)) /* local cHRM ? */
+ {
+ iWhitepointx = pBuf->iWhitepointx;
+ iWhitepointy = pBuf->iWhitepointy;
+ iPrimaryredx = pBuf->iPrimaryredx;
+ iPrimaryredy = pBuf->iPrimaryredy;
+ iPrimarygreenx = pBuf->iPrimarygreenx;
+ iPrimarygreeny = pBuf->iPrimarygreeny;
+ iPrimarybluex = pBuf->iPrimarybluex;
+ iPrimarybluey = pBuf->iPrimarybluey;
+ }
+ else
+ {
+ iWhitepointx = pData->iGlobalWhitepointx;
+ iWhitepointy = pData->iGlobalWhitepointy;
+ iPrimaryredx = pData->iGlobalPrimaryredx;
+ iPrimaryredy = pData->iGlobalPrimaryredy;
+ iPrimarygreenx = pData->iGlobalPrimarygreenx;
+ iPrimarygreeny = pData->iGlobalPrimarygreeny;
+ iPrimarybluex = pData->iGlobalPrimarybluex;
+ iPrimarybluey = pData->iGlobalPrimarybluey;
+ }
+ /* inform the app */
+ if (!pData->fProcesschroma ((mng_handle)pData, iWhitepointx, iWhitepointy,
+ iPrimaryredx, iPrimaryredy,
+ iPrimarygreenx, iPrimarygreeny,
+ iPrimarybluex, iPrimarybluey))
+ MNG_ERROR (pData, MNG_APPCMSERROR);
+ /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
+ bDone = MNG_TRUE;
+ }
+#endif
+
+ if ( (pData->fProcessgamma) &&
+ (((pBuf) && (pBuf->bHasGAMA)) || ((bGlobal) && (pData->bHasglobalGAMA))) )
+ {
+ mng_uint32 iGamma;
+
+ if ((pBuf) && (pBuf->bHasGAMA)) /* get the gamma value */
+ iGamma = pBuf->iGamma;
+ else
+ iGamma = pData->iGlobalGamma;
+ /* inform the app */
+ if (!pData->fProcessgamma ((mng_handle)pData, iGamma))
+ { /* app wants us to use internal routines ! */
+ iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
+ }
+
+ bDone = MNG_TRUE;
+ }
+
+ if (!bDone) /* no color-info at all ? */
+ {
+ /* then use default image gamma ! */
+ if (!pData->fProcessgamma ((mng_handle)pData,
+ (mng_uint32)((pData->dDfltimggamma * 100000) + 0.5)))
+ { /* app wants us to use internal routines ! */
+ iRetcode = mng_init_gamma_only (pData, bGlobal, bObject, bRetrobj);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* load color-correction routine */
+ pData->fCorrectrow = (mng_fptr)mng_correct_app_cms;
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_APP_CMS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#ifdef MNG_APP_CMS
+mng_retcode mng_correct_app_cms (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_START);
+#endif
+
+ if (pData->fProcessarow) /* let the app do something with our row */
+ if (!pData->fProcessarow ((mng_handle)pData, pData->iRowsamples,
+ pData->bIsRGBA16, pData->pRGBArow))
+ MNG_ERROR (pData, MNG_APPCMSERROR);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CORRECT_APP_CMS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
+
diff --git a/Source/LibMNG/libmng_cms.h b/Source/LibMNG/libmng_cms.h
new file mode 100644
index 0000000..4459f80
--- /dev/null
+++ b/Source/LibMNG/libmng_cms.h
@@ -0,0 +1,92 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_cms.h copyright (c) 2000-2003 G.Juyn * */
+/* * version : 1.0.6 * */
+/* * * */
+/* * purpose : color management routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of color management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added creatememprofile * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.1 - 04/25/2001 - G.Juyn * */
+/* * - moved mng_clear_cms to libmng_cms * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - optimized color-correction routines * */
+/* * * */
+/* * 1.0.6 - 04/11/2003 - G.Juyn * */
+/* * - B719420 - fixed several MNG_APP_CMS problems * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_cms_h_
+#define _libmng_cms_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_LCMS
+void mnglcms_initlibrary (void);
+mng_cmsprof mnglcms_createfileprofile (mng_pchar zFilename);
+mng_cmsprof mnglcms_creatememprofile (mng_uint32 iProfilesize,
+ mng_ptr pProfile );
+mng_cmsprof mnglcms_createsrgbprofile (void);
+void mnglcms_freeprofile (mng_cmsprof hProf );
+void mnglcms_freetransform (mng_cmstrans hTrans );
+
+mng_retcode mng_clear_cms (mng_datap pData );
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_FULL_CMS
+mng_retcode mng_init_full_cms (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj);
+mng_retcode mng_correct_full_cms (mng_datap pData);
+#endif
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_retcode mng_init_gamma_only (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj);
+mng_retcode mng_correct_gamma_only (mng_datap pData);
+#endif
+
+#ifdef MNG_APP_CMS
+mng_retcode mng_init_app_cms (mng_datap pData,
+ mng_bool bGlobal,
+ mng_bool bObject,
+ mng_bool bRetrobj);
+mng_retcode mng_correct_app_cms (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+
+#endif /* _libmng_cms_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_conf.h b/Source/LibMNG/libmng_conf.h
new file mode 100644
index 0000000..8e0925e
--- /dev/null
+++ b/Source/LibMNG/libmng_conf.h
@@ -0,0 +1,306 @@
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_conf.h copyright (c) G.Juyn 2000-2004 * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : main configuration file * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : The configuration file. Change this to include/exclude * */
+/* * the options you want or do not want in libmng. * */
+/* * * */
+/* * changes : 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - separated configuration-options into this file * */
+/* * - changed to most likely configuration (?) * */
+/* * 0.5.2 - 06/03/2000 - G.Juyn * */
+/* * - changed options to create a standard so-library * */
+/* * with everything enabled * */
+/* * 0.5.2 - 06/04/2000 - G.Juyn * */
+/* * - changed options to create a standard win32-dll * */
+/* * with everything enabled * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/12/2000 - G.Juyn * */
+/* * - added workaround for faulty PhotoShop iCCP chunk * */
+/* * 0.9.3 - 09/16/2000 - G.Juyn * */
+/* * - removed trace-options from default SO/DLL builds * */
+/* * * */
+/* * 1.0.4 - 06/22/2002 - G.Juyn * */
+/* * - B526138 - returned IJGSRC6B calling convention to * */
+/* * default for MSVC * */
+/* * * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * - added 'supports' call to check function availability * */
+/* * * */
+/* * 1.0.6 - 06/22/2002 - G.R-P * */
+/* * - added MNG_NO_INCLUDE_JNG conditional * */
+/* * - added MNG_SKIPCHUNK_evNT conditional * */
+/* * 1.0.6 - 07/14/2002 - G.R-P * */
+/* * - added MNG_NO_SUPPORT_FUNCQUERY conditional * */
+/* * * */
+/* * 1.0.7 - 03/07/2004 - G.R-P * */
+/* * - added MNG_VERSION_QUERY_SUPPORT_ conditional * */
+/* * * */
+/* * 1.0.9 - 05/12/2004 - G.Juyn * */
+/* * - clearified MNG_BIGENDIAN_SUPPORTED conditional * */
+/* * - added MNG_LITTLEENDIAN_SUPPORTED conditional * */
+/* * * */
+/* ************************************************************************** */
+
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_conf_h_
+#define _libmng_conf_h_
+
+#ifdef MNG_MOZILLA_CFG
+#include "special\mozcfg\mozlibmngconf.h"
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * User-selectable compile-time options * */
+/* * * */
+/* ************************************************************************** */
+
+/* ************************************************************************** */
+/* added by FreeImage */
+/* ************************************************************************** */
+
+#define MNG_OPTIMIZE_CHUNKINITFREE
+#define MNG_OPTIMIZE_OBJCLEANUP
+#define MNG_OPTIMIZE_CHUNKASSIGN
+#define MNG_OPTIMIZE_CHUNKREADER
+
+/* ************************************************************************** */
+
+/* enable exactly one(1) of the MNG-(sub)set selectors */
+/* use this to select which (sub)set of the MNG specification you wish
+ to support */
+/* generally you'll want full support as the library provides it automatically
+ for you! if you're really strung on memory-requirements you can opt
+ to enable less support (but it's just NOT a good idea!) */
+/* NOTE that this isn't actually implemented yet */
+
+#if !defined(MNG_SUPPORT_FULL) && !defined(MNG_SUPPORT_LC) && !defined(MNG_SUPPORT_VLC)
+#define MNG_SUPPORT_FULL
+/* #define MNG_SUPPORT_LC */
+/* #define MNG_SUPPORT_VLC */
+#endif
+
+/* ************************************************************************** */
+
+/* enable JPEG support if required */
+/* use this to enable the JNG support routines */
+/* this requires an external jpeg package;
+ currently only IJG's jpgsrc6b is supported! */
+/* NOTE that the IJG code can be either 8- or 12-bit (eg. not both);
+ so choose the one you've defined in jconfig.h; if you don't know what
+ the heck I'm talking about, just leave it at 8-bit support (thank you!) */
+
+#ifndef MNG_NO_INCLUDE_JNG
+#ifdef MNG_SUPPORT_FULL /* full support includes JNG */
+#define MNG_SUPPORT_IJG6B
+#endif
+
+#ifndef MNG_SUPPORT_IJG6B
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_SUPPORT_IJG6B
+#endif
+#endif
+
+#if defined(MNG_SUPPORT_IJG6B) && !defined(MNG_SUPPORT_JPEG8) && !defined(MNG_SUPPORT_JPEG12)
+#define MNG_SUPPORT_JPEG8
+/* #define MNG_SUPPORT_JPEG12 */
+#endif
+
+/* The following is required to export the IJG routines from the DLL in
+ the Windows-standard calling convention;
+ currently this only works for Borland C++ !!! */
+
+#if defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#if defined(MNG_SUPPORT_IJG6B) && defined(__BORLANDC__)
+#define MNG_DEFINE_JPEG_STDCALL
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+
+/* enable required high-level functions */
+/* use this to select the high-level functions you require */
+/* if you only need to display a MNG, disable write support! */
+/* if you only need to examine a MNG, disable write & display support! */
+/* if you only need to copy a MNG, disable display support! */
+/* if you only need to create a MNG, disable read & display support! */
+/* NOTE that turning all options off will be very unuseful! */
+
+#if !defined(MNG_SUPPORT_READ) && !defined(MNG_SUPPORT_WRITE) && !defined(MNG_SUPPORT_DISPLAY)
+#define MNG_SUPPORT_READ
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_SUPPORT_WRITE
+#endif
+#define MNG_SUPPORT_DISPLAY
+#endif
+
+/* ************************************************************************** */
+
+/* enable chunk access functions */
+/* use this to select whether you need access to the individual chunks */
+/* useful if you want to examine a read MNG (you'll also need MNG_STORE_CHUNKS !)*/
+/* required if you need to create & write a new MNG! */
+
+#ifndef MNG_ACCESS_CHUNKS
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_ACCESS_CHUNKS
+#endif
+#endif
+
+/* ************************************************************************** */
+
+/* enable exactly one(1) of the color-management functionality selectors */
+/* use this to select the level of automatic color support */
+/* MNG_FULL_CMS requires the lcms (little cms) external package ! */
+/* if you want your own app (or the OS) to handle color-management
+ select MNG_APP_CMS */
+
+#define MNG_GAMMA_ONLY
+/* #define MNG_FULL_CMS */
+/* #define MNG_APP_CMS */
+
+/* ************************************************************************** */
+
+/* enable automatic dithering */
+/* use this if you need dithering support to convert high-resolution
+ images to a low-resolution output-device */
+/* NOTE that this is not supported yet */
+
+/* #define MNG_AUTO_DITHER */
+
+/* ************************************************************************** */
+
+/* enable whether chunks should be stored for reference later */
+/* use this if you need to examine the chunks of a MNG you have read,
+ or (re-)write a MNG you have read */
+/* turn this off if you want to reduce memory-consumption */
+
+#ifndef MNG_STORE_CHUNKS
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_STORE_CHUNKS
+#endif
+#endif
+
+/* ************************************************************************** */
+
+/* enable internal memory management (if your compiler supports it) */
+/* use this if your compiler supports the 'standard' memory functions
+ (calloc & free), and you want the library to use these functions and not
+ bother your app with memory-callbacks */
+
+/* #define MNG_INTERNAL_MEMMNGMT */
+
+/* ************************************************************************** */
+
+/* enable internal tracing-functionality (manual debugging purposes) */
+/* use this if you have trouble location bugs or problems */
+/* NOTE that you'll need to specify the trace callback function! */
+
+/* #define MNG_SUPPORT_TRACE */
+
+/* ************************************************************************** */
+
+/* enable extended error- and trace-telltaling */
+/* use this if you need explanatory messages with errors and/or tracing */
+
+#if !defined(MNG_ERROR_TELLTALE) && !defined(MNG_TRACE_TELLTALE)
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_ERROR_TELLTALE
+#define MNG_TRACE_TELLTALE
+#endif
+#endif
+
+/* ************************************************************************** */
+
+/* enable BIG/LITTLE endian optimizations */
+/* enable BIG if you're on an architecture that supports big-endian reads
+ and writes that aren't word-aligned */
+/* according to reliable sources this only works for PowerPC (bigendian mode)
+ and 680x0 */
+/* enable LITTLE if you're on an architecture that supports little-endian */
+/* when in doubt leave both off !!! */
+
+/* #define MNG_BIGENDIAN_SUPPORTED */
+/* #define MNG_LITTLEENDIAN_SUPPORTED */
+
+/* ************************************************************************** */
+/* enable 'version' functions */
+#if !defined(MNG_VERSION_QUERY_SUPPORT) && \
+ !defined(MNG_NO_VERSION_QUERY_SUPPORT)
+#define MNG_VERSION_QUERY_SUPPORT
+#endif
+
+/* enable 'supports' function */
+/* use this if you need to query the availability of functions at runtime;
+ useful for apps that dynamically load the library and that need specific
+ functions */
+
+#if !defined(MNG_NO_SUPPORT_FUNCQUERY) && !defined(MNG_SUPPORT_FUNCQUERY)
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || \
+ defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_SUPPORT_FUNCQUERY
+#endif
+#endif
+
+/* ************************************************************************** */
+
+/* enable dynamic MNG features */
+/* use this if you would like to have dynamic support for specifically
+ designed MNGs; eg. this is useful for 'rollover' effects such as common
+ on the world wide web */
+
+#ifndef MNG_SUPPORT_DYNAMICMNG
+#if defined(MNG_BUILD_SO) || defined(MNG_USE_SO) || defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_SUPPORT_DYNAMICMNG
+#endif
+#endif
+#ifndef MNG_SUPPORT_DYNAMICMNG
+#ifndef MNG_SKIPCHUNK_evNT
+#define MNG_SKIPCHUNK_evNT
+#endif
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+#ifndef MNG_NO_ACCESS_JPEG
+#ifndef MNG_ACCESS_JPEG
+#define MNG_ACCESS_JPEG
+#endif
+#endif
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifndef MNG_NO_ACCESS_ZLIB
+#ifndef MNG_ACCESS_ZLIB
+#define MNG_ACCESS_ZLIB
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * End of user-selectable compile-time options * */
+/* * * */
+/* ************************************************************************** */
+
+#endif /* _libmng_conf_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_data.h b/Source/LibMNG/libmng_data.h
new file mode 100644
index 0000000..430dca9
--- /dev/null
+++ b/Source/LibMNG/libmng_data.h
@@ -0,0 +1,1029 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_data.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : main data structure definition * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the library main data structure * */
+/* * * */
+/* * changes : 0.5.1 - 05/04/2000 - G.Juyn * */
+/* * - added CRC table to main structure (for thread-safety) * */
+/* * 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - added iPLTEentries for checking hIST-length * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed palette definition to exported palette-type * */
+/* * - removed frozen indicator * */
+/* * - added create/write indicators * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/13/2000 - G.Juyn * */
+/* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
+/* * - added TERM animation object pointer (easier reference) * */
+/* * - added saved-data structure for SAVE/SEEK processing * */
+/* * * */
+/* * 0.5.2 - 05/18/2000 - G.Juyn * */
+/* * - added fields for JNG support (IJG-based) * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - changed global tRNS definition * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added delta-image fields * */
+/* * 0.5.2 - 06/01/2000 - G.Juyn * */
+/* * - added internal delta-image processing callbacks * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - changed SWAP_ENDIAN to BIGENDIAN_SUPPORTED * */
+/* * (contributed by Tim Rowley) * */
+/* * - added getalphaline callback for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added parameter for delayed buffer-processing * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - added update-region parms for refresh calback * */
+/* * - added Needrefresh parameter * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - added Deltaimmediate parm for faster delta-processing * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added Speed parameter to facilitate testing * */
+/* * - added Imagelevel parameter for processtext callback * */
+/* * 0.5.3 - 06/26/2000 - G.Juyn * */
+/* * - changed userdata variable to mng_ptr * */
+/* * * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - added variables for go_xxxx processing * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added variables for improved timing support * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added callbacks for SAVE/SEEK processing * */
+/* * - added variable for NEEDSECTIONWAIT breaks * */
+/* * - added variable for freeze & reset processing * */
+/* * 0.9.1 - 07/17/2000 - G.Juyn * */
+/* * - fixed suspension-buffering for 32K+ chunks * */
+/* * * */
+/* * 0.9.2 - 07/29/2000 - G.Juyn * */
+/* * - removed Nextbackxxx fields (no longer used) * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - fixed wrapping of suspension parameters * */
+/* * 0.9.2 - 08/04/2000 - G.Juyn * */
+/* * - B111096 - fixed large-buffer read-suspension * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added optional support for bKGD for PNG images * */
+/* * - added support for JDAA * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * - fixed support for bKGD * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - implemented delayed delta-processing * */
+/* * 0.9.4 - 12/16/2000 - G.Juyn * */
+/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 02/13/2001 - G.Juyn * */
+/* * - fixed first FRAM_MODE=4 timing problem * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * - added processterm callback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.5 - 07/08/2002 - G.Juyn * */
+/* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
+/* * 1.0.5 - 07/16/2002 - G.Juyn * */
+/* * - B581625 - large chunks fail with suspension reads * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - finished support for BACK image & tiling * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added another fix for misplaced TERM chunk * */
+/* * - completed support for condition=2 in TERM chunk * */
+/* * 1.0.5 - 10/20/2002 - G.Juyn * */
+/* * - fixed processing for multiple objects in MAGN * */
+/* * - fixed display of visible target of PAST operation * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * 1.0.5 - 24/02/2003 - G.Juyn * */
+/* * - B683152 - libjpeg suspension not always honored correctly* */
+/* * * */
+/* * 1.0.6 - 04/11/2003 - G.Juyn * */
+/* * - B719420 - fixed several MNG_APP_CMS problems * */
+/* * 1.0.6 - 07/05/2003 - G. R-P * */
+/* * - optionally use zlib's crc32() function * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added SKIPCHUNK conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added iPNGdepth member to pData structure * */
+/* * * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/10/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_data_h_
+#define _libmng_data_h_
+
+/* ************************************************************************** */
+
+#define MNG_MAGIC 0x52530a0aL
+
+/* ************************************************************************** */
+/* * * */
+/* * Internal structures * */
+/* * * */
+/* ************************************************************************** */
+
+typedef mng_palette8 mng_rgbpaltab;
+
+/* ************************************************************************** */
+/* * * */
+/* * The saved_data structure * */
+/* * * */
+/* * This contains the saved data after a SAVE chunk has been processed. * */
+/* * The data is saved from the main data structure during SAVE processing, * */
+/* * and restored to the main data structure during SEEK processing. * */
+/* * * */
+/* ************************************************************************** */
+
+typedef struct mng_savedata_struct {
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ mng_bool bHasglobalPLTE; /* global PLTE chunk processed */
+ mng_bool bHasglobalTRNS; /* global tRNS chunk processed */
+ mng_bool bHasglobalGAMA; /* global gAMA chunk processed */
+ mng_bool bHasglobalCHRM; /* global cHRM chunk processed */
+ mng_bool bHasglobalSRGB; /* global sRGB chunk processed */
+ mng_bool bHasglobalICCP; /* global iCCP chunk processed */
+ mng_bool bHasglobalBKGD; /* global bKGD chunk processed */
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_uint16 iBACKred; /* BACK fields */
+ mng_uint16 iBACKgreen;
+ mng_uint16 iBACKblue;
+ mng_uint8 iBACKmandatory;
+ mng_uint16 iBACKimageid;
+ mng_uint8 iBACKtile;
+
+ mng_uint8 iFRAMmode; /* FRAM fields (global) */
+ mng_uint32 iFRAMdelay;
+ mng_uint32 iFRAMtimeout;
+ mng_bool bFRAMclipping;
+ mng_int32 iFRAMclipl;
+ mng_int32 iFRAMclipr;
+ mng_int32 iFRAMclipt;
+ mng_int32 iFRAMclipb;
+
+ mng_uint32 iGlobalPLTEcount; /* global PLTE fields */
+ mng_rgbpaltab aGlobalPLTEentries;
+
+ mng_uint32 iGlobalTRNSrawlen; /* global tRNS fields */
+ mng_uint8arr aGlobalTRNSrawdata;
+
+ mng_uint32 iGlobalGamma; /* global gAMA fields */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ mng_uint32 iGlobalWhitepointx; /* global cHRM fields */
+ mng_uint32 iGlobalWhitepointy;
+ mng_uint32 iGlobalPrimaryredx;
+ mng_uint32 iGlobalPrimaryredy;
+ mng_uint32 iGlobalPrimarygreenx;
+ mng_uint32 iGlobalPrimarygreeny;
+ mng_uint32 iGlobalPrimarybluex;
+ mng_uint32 iGlobalPrimarybluey;
+#endif
+
+ mng_uint8 iGlobalRendintent; /* global sRGB fields */
+
+ mng_uint32 iGlobalProfilesize; /* global iCCP fields */
+ mng_ptr pGlobalProfile;
+
+ mng_uint16 iGlobalBKGDred; /* global bKGD fields */
+ mng_uint16 iGlobalBKGDgreen;
+ mng_uint16 iGlobalBKGDblue;
+#endif /* MNG_SUPPORT_DISPLAY */
+
+ } mng_savedata;
+
+typedef mng_savedata * mng_savedatap;
+
+/* ************************************************************************** */
+/* * * */
+/* * Internal buffer structure for data push mechanisms * */
+/* * * */
+/* ************************************************************************** */
+
+typedef struct {
+ mng_ptr pNext; /* for linked list */
+ mng_ptr pData; /* used for chunks & data */
+ mng_uint32 iLength;
+ mng_bool bOwned;
+ mng_uint8p pDatanext; /* only used for data */
+ mng_uint32 iRemaining;
+ } mng_pushdata;
+typedef mng_pushdata * mng_pushdatap;
+
+/* ************************************************************************** */
+/* * * */
+/* * The main libmng data structure * */
+/* * * */
+/* * The handle used in all functions points to this structure which * */
+/* * contains all volatile data necessary to process the network graphic. * */
+/* * * */
+/* ************************************************************************** */
+
+typedef struct mng_data_struct {
+
+ mng_uint32 iMagic; /* magic number to validate
+ a given handle */
+ mng_ptr pUserdata; /* application workdata */
+
+ mng_imgtype eSigtype; /* image information */
+ mng_imgtype eImagetype; /* initially zeroed */
+ mng_uint32 iWidth; /* filled after header is processed */
+ mng_uint32 iHeight;
+ mng_uint32 iTicks; /* these only after MHDR */
+ mng_uint32 iLayercount;
+ mng_uint32 iFramecount;
+ mng_uint32 iPlaytime;
+ mng_uint32 iSimplicity;
+ mng_uint8 iAlphadepth; /* indicates expected alpha-depth */
+
+ mng_uint32 iImagelevel; /* level of image inside a stream */
+
+ mng_uint32 iCanvasstyle; /* layout of the drawing-canvas */
+ mng_uint32 iBkgdstyle; /* layout of the background-canvas */
+
+ mng_int8 iMagnify; /* magnification factor (not used yet) */
+ mng_uint32 iOffsetx; /* x-offset for extremely large image */
+ mng_uint32 iOffsety; /* y-offset for extremely large image */
+ mng_uint32 iCanvaswidth; /* real canvas size */
+ mng_uint32 iCanvasheight; /* must be set by processheader callback */
+
+ mng_uint16 iBGred; /* default background color */
+ mng_uint16 iBGgreen; /* initially "black" */
+ mng_uint16 iBGblue;
+ mng_bool bUseBKGD; /* preferred use of bKGD for PNG */
+
+ mng_bool bIssRGB; /* indicates sRGB system */
+
+#ifdef MNG_FULL_CMS /* little CMS variables */
+ mng_cmsprof hProf1; /* image input profile */
+ mng_cmsprof hProf2; /* default output profile */
+ mng_cmsprof hProf3; /* default sRGB profile */
+ mng_cmstrans hTrans; /* current transformation handle */
+#endif
+
+ mng_float dViewgamma; /* gamma calculation variables */
+ mng_float dDisplaygamma; /* initially set for sRGB conditions */
+ mng_float dDfltimggamma;
+
+ mng_bool bStorechunks; /* switch for storing chunkdata */
+ mng_bool bSectionbreaks; /* indicate NEEDSECTIONWAIT breaks */
+ mng_bool bCacheplayback; /* switch to cache playback info */
+ mng_bool bDoProgressive; /* progressive refresh for large images */
+ mng_uint32 iCrcmode; /* CRC existence & checking flags */
+
+ mng_speedtype iSpeed; /* speed-modifier for animations */
+
+ mng_uint32 iMaxwidth; /* maximum canvas size */
+ mng_uint32 iMaxheight; /* initially set to 1024 x 1024 */
+
+ mng_int32 iErrorcode; /* error reporting fields */
+ mng_int8 iSeverity;
+ mng_int32 iErrorx1;
+ mng_int32 iErrorx2;
+ mng_pchar zErrortext;
+
+ mng_memalloc fMemalloc; /* callback pointers */
+ mng_memfree fMemfree; /* initially nulled */
+ mng_releasedata fReleasedata;
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ mng_openstream fOpenstream;
+ mng_closestream fClosestream;
+#endif
+ mng_readdata fReaddata;
+ mng_writedata fWritedata;
+ mng_errorproc fErrorproc;
+ mng_traceproc fTraceproc;
+ mng_processheader fProcessheader;
+ mng_processtext fProcesstext;
+ mng_processsave fProcesssave;
+ mng_processseek fProcessseek;
+ mng_processneed fProcessneed;
+ mng_processmend fProcessmend;
+ mng_processunknown fProcessunknown;
+ mng_processterm fProcessterm;
+ mng_getcanvasline fGetcanvasline;
+ mng_getbkgdline fGetbkgdline;
+ mng_getalphaline fGetalphaline;
+ mng_refresh fRefresh;
+ mng_gettickcount fGettickcount;
+ mng_settimer fSettimer;
+ mng_processgamma fProcessgamma;
+ mng_processchroma fProcesschroma;
+ mng_processsrgb fProcesssrgb;
+ mng_processiccp fProcessiccp;
+ mng_processarow fProcessarow;
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+#ifndef MNG_NO_OLD_VERSIONS
+ mng_bool bPreDraft48; /* flags ancient style draft */
+#endif
+
+ mng_chunkid iChunkname; /* read/write-state variables */
+ mng_uint32 iChunkseq;
+ mng_chunkp pFirstchunk; /* double-linked list of */
+ mng_chunkp pLastchunk; /* stored chunk-structures */
+
+ mng_bool bHasheader; /* first header chunk processed */
+ mng_bool bHasMHDR; /* inside a MHDR-MEND sequence */
+ mng_bool bHasIHDR; /* inside a IHDR-IEND sequence */
+ mng_bool bHasBASI; /* inside a BASI-IEND sequence */
+ mng_bool bHasDHDR; /* inside a DHDR-IEND sequence */
+#ifdef MNG_INCLUDE_JNG
+ mng_bool bHasJHDR; /* inside a JHDR-IEND sequence */
+ mng_bool bHasJSEP; /* passed the JSEP separator */
+ mng_bool bHasJDAA; /* at least 1 JDAA processed */
+ mng_bool bHasJDAT; /* at least 1 JDAT processed */
+#endif
+ mng_bool bHasPLTE; /* PLTE chunk processed */
+ mng_bool bHasTRNS; /* tRNS chunk processed */
+ mng_bool bHasGAMA; /* gAMA chunk processed */
+ mng_bool bHasCHRM; /* cHRM chunk processed */
+ mng_bool bHasSRGB; /* sRGB chunk processed */
+ mng_bool bHasICCP; /* iCCP chunk processed */
+ mng_bool bHasBKGD; /* bKGD chunk processed */
+ mng_bool bHasIDAT; /* at least 1 IDAT processed */
+
+ mng_bool bHasSAVE; /* SAVE chunk processed */
+ mng_bool bHasBACK; /* BACK chunk processed */
+ mng_bool bHasFRAM; /* FRAM chunk processed */
+ mng_bool bHasTERM; /* TERM chunk processed */
+ mng_bool bHasLOOP; /* at least 1 LOOP open */
+
+ mng_bool bHasglobalPLTE; /* global PLTE chunk processed */
+ mng_bool bHasglobalTRNS; /* global tRNS chunk processed */
+ mng_bool bHasglobalGAMA; /* global gAMA chunk processed */
+ mng_bool bHasglobalCHRM; /* global cHRM chunk processed */
+ mng_bool bHasglobalSRGB; /* global sRGB chunk processed */
+ mng_bool bHasglobalICCP; /* global iCCP chunk processed */
+ mng_bool bHasglobalBKGD; /* global bKGD chunk processed */
+
+ mng_uint32 iDatawidth; /* IHDR/BASI/DHDR fields */
+ mng_uint32 iDataheight; /* valid if inside IHDR-IEND, */
+ mng_uint8 iBitdepth; /* BASI-IEND or DHDR-IEND */
+ mng_uint8 iColortype;
+ mng_uint8 iCompression;
+ mng_uint8 iFilter;
+ mng_uint8 iInterlace;
+
+ mng_uint32 iPLTEcount; /* PLTE fields */
+
+#ifdef MNG_INCLUDE_JNG
+ mng_uint8 iJHDRcolortype; /* JHDR fields */
+ mng_uint8 iJHDRimgbitdepth; /* valid if inside JHDR-IEND */
+ mng_uint8 iJHDRimgcompression;
+ mng_uint8 iJHDRimginterlace;
+ mng_uint8 iJHDRalphabitdepth;
+ mng_uint8 iJHDRalphacompression;
+ mng_uint8 iJHDRalphafilter;
+ mng_uint8 iJHDRalphainterlace;
+#endif
+
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifdef MNG_SUPPORT_READ
+ mng_bool bReading; /* read processing variables */
+ mng_bool bHavesig;
+ mng_bool bEOF;
+ mng_uint32 iReadbufsize;
+ mng_uint8p pReadbuf;
+
+ mng_uint32 iLargebufsize; /* temp for very large chunks */
+ mng_uint8p pLargebuf;
+
+ mng_uint32 iSuspendtime; /* tickcount at last suspension */
+ mng_bool bSuspended; /* input-reading has been suspended;
+ we're expecting a call to
+ mng_read_resume! */
+ mng_uint8 iSuspendpoint; /* indicates at which point the flow
+ was broken to suspend input-reading */
+
+ mng_bool bSuspensionmode; /* I/O-suspension variables */
+ mng_uint32 iSuspendbufsize;
+ mng_uint8p pSuspendbuf;
+ mng_uint8p pSuspendbufnext;
+ mng_uint32 iSuspendbufleft;
+ mng_uint32 iChunklen; /* chunk length */
+ mng_uint8p pReadbufnext; /* 32K+ suspension-processing */
+ mng_uint8p pLargebufnext;
+
+ mng_pushdatap pFirstpushchunk; /* variables for push mechanisms */
+ mng_pushdatap pLastpushchunk;
+ mng_pushdatap pFirstpushdata;
+ mng_pushdatap pLastpushdata;
+#endif /* MNG_SUPPORT_READ */
+
+#ifdef MNG_SUPPORT_WRITE
+ mng_bool bCreating; /* create/write processing variables */
+ mng_bool bWriting;
+ mng_chunkid iFirstchunkadded;
+ mng_uint32 iWritebufsize;
+ mng_uint8p pWritebuf;
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_bool bDisplaying; /* display-state variables */
+ mng_bool bFramedone;
+ mng_uint32 iFrameseq;
+ mng_uint32 iLayerseq;
+ mng_uint32 iFrametime; /* millisecs */
+
+ mng_uint32 iTotalframes; /* end-totals after mng_read() */
+ mng_uint32 iTotallayers;
+ mng_uint32 iTotalplaytime; /* millisecs */
+
+ mng_bool bSkipping; /* LOOP iteration=0 */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ mng_bool bDynamic; /* MNG is dynamic (eg. has events) */
+ mng_bool bRunningevent; /* currently processing an event */
+ mng_bool bStopafterseek; /* stop after next SEEK */
+ mng_int32 iEventx; /* X/Y of current event */
+ mng_int32 iEventy;
+ mng_objectp pLastmousemove; /* last event triggered */
+#endif
+
+ mng_uint32 iRequestframe; /* go_xxxx variables */
+ mng_uint32 iRequestlayer;
+ mng_uint32 iRequesttime;
+ mng_bool bSearching;
+
+ mng_bool bRestorebkgd; /* flags restore required before IDAT/JDAT */
+
+ mng_uint32 iRuntime; /* millisecs since start */
+ mng_uint32 iSynctime; /* tickcount at last framesync */
+ mng_uint32 iStarttime; /* tickcount at start */
+ mng_uint32 iEndtime; /* tickcount at end */
+ mng_bool bRunning; /* animation is active */
+ mng_bool bTimerset; /* the timer has been set;
+ we're expecting a call to
+ mng_display_resume! */
+ mng_uint8 iBreakpoint; /* indicates at which point the
+ flow was broken to run the timer */
+ mng_bool bSectionwait; /* indicates a section break */
+ mng_bool bFreezing; /* indicates app requested a freeze */
+ mng_bool bResetting; /* indicates app requested a reset */
+ mng_bool bNeedrefresh; /* indicates screen-refresh is needed */
+ mng_bool bMisplacedTERM; /* indicates TERM is out of place */
+ mng_bool bOnlyfirstframe; /* show first frame after TERM and stop */
+ mng_uint32 iFramesafterTERM; /* determines frame-count after TERM */
+ mng_objectp pCurrentobj; /* current "object" */
+ mng_objectp pCurraniobj; /* current animation object
+ "to be"/"being" processed */
+ mng_objectp pTermaniobj; /* TERM animation object */
+ mng_uint32 iIterations; /* TERM/MEND iteration count */
+ mng_objectp pObjzero; /* "on-the-fly" image (object = 0) */
+ mng_objectp pLastclone; /* last clone */
+ mng_objectp pStoreobj; /* current store object for row routines */
+ mng_objectp pStorebuf; /* current store object-buffer for row routines */
+ mng_objectp pRetrieveobj; /* current retrieve object for row routines */
+ mng_savedatap pSavedata; /* pointer to saved data (after SAVE) */
+
+ mng_uint32 iUpdateleft; /* update region for refresh */
+ mng_uint32 iUpdateright;
+ mng_uint32 iUpdatetop;
+ mng_uint32 iUpdatebottom;
+
+ mng_int8 iPass; /* current interlacing pass;
+ negative value means no interlace */
+ mng_int32 iRow; /* current row counter */
+ mng_int32 iRowinc; /* row increment for this pass */
+ mng_int32 iCol; /* current starting column */
+ mng_int32 iColinc; /* column increment for this pass */
+ mng_int32 iRowsamples; /* nr. of samples in current workrow */
+ mng_int32 iSamplemul; /* needed to calculate rowsize */
+ mng_int32 iSampleofs; /* from rowsamples */
+ mng_int32 iSamplediv;
+ mng_int32 iRowsize; /* size of actual data in work row */
+ mng_int32 iRowmax; /* maximum size of data in work row */
+ mng_int32 iFilterofs; /* offset to filter-byte in work row */
+ mng_int32 iPixelofs; /* offset to pixel-bytes in work row */
+ mng_uint32 iLevel0; /* leveling variables */
+ mng_uint32 iLevel1;
+ mng_uint32 iLevel2;
+ mng_uint32 iLevel3;
+ mng_uint8p pWorkrow; /* working row of pixel-data */
+ mng_uint8p pPrevrow; /* previous row of pixel-data */
+ mng_uint8p pRGBArow; /* intermediate row of RGBA8 or RGBA16 data */
+ mng_bool bIsRGBA16; /* indicates intermediate row is RGBA16 */
+ mng_bool bIsOpaque; /* indicates intermediate row is fully opaque */
+ mng_int32 iFilterbpp; /* bpp index for filtering routines */
+
+ mng_int32 iSourcel; /* variables for showing objects */
+ mng_int32 iSourcer;
+ mng_int32 iSourcet;
+ mng_int32 iSourceb;
+ mng_int32 iDestl;
+ mng_int32 iDestr;
+ mng_int32 iDestt;
+ mng_int32 iDestb;
+
+ mng_objectp pFirstimgobj; /* double-linked list of */
+ mng_objectp pLastimgobj; /* image-object structures */
+ mng_objectp pFirstaniobj; /* double-linked list of */
+ mng_objectp pLastaniobj; /* animation-object structures */
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ mng_objectp pFirstevent; /* double-linked list of */
+ mng_objectp pLastevent; /* event-object structures */
+#endif
+
+#if defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS) || defined(MNG_APP_CMS)
+ mng_uint8 aGammatab[256]; /* precomputed gamma lookup table */
+ mng_float dLastgamma; /* last gamma used to compute table */
+#endif
+
+ mng_fptr fDisplayrow; /* internal callback to display an
+ uncompressed/unfiltered/
+ color-corrected row */
+ mng_fptr fRestbkgdrow; /* internal callback for restore-
+ background processing of a row */
+ mng_fptr fCorrectrow; /* internal callback to color-correct an
+ uncompressed/unfiltered row */
+ mng_fptr fRetrieverow; /* internal callback to retrieve an
+ uncompressed/unfiltered row of data */
+ mng_fptr fStorerow; /* internal callback to store an
+ uncompressed/unfiltered row of data */
+ mng_fptr fProcessrow; /* internal callback to process an
+ uncompressed row of data */
+ mng_fptr fDifferrow; /* internal callback to perform
+ added filter leveling and
+ differing on an unfiltered row */
+ mng_fptr fScalerow; /* internal callback to scale a
+ delta-row to the bitdepth of its target */
+ mng_fptr fDeltarow; /* internal callback to execute a
+ delta-row onto a target */
+#ifndef MNG_SKIPCHUNK_PAST
+ mng_fptr fFliprow; /* internal callback to flip a row of pixels
+ left<->right for a PAST operation */
+ mng_fptr fTilerow; /* internal callback to tile a row of pixels
+ during a PAST operation */
+#endif
+ mng_fptr fInitrowproc; /* internal callback to initialize
+ the row processing */
+
+ mng_uint16 iDEFIobjectid; /* DEFI fields */
+ mng_bool bDEFIhasdonotshow;
+ mng_uint8 iDEFIdonotshow;
+ mng_bool bDEFIhasconcrete;
+ mng_uint8 iDEFIconcrete;
+ mng_bool bDEFIhasloca;
+ mng_int32 iDEFIlocax;
+ mng_int32 iDEFIlocay;
+ mng_bool bDEFIhasclip;
+ mng_int32 iDEFIclipl;
+ mng_int32 iDEFIclipr;
+ mng_int32 iDEFIclipt;
+ mng_int32 iDEFIclipb;
+
+ mng_uint16 iBACKred; /* BACK fields */
+ mng_uint16 iBACKgreen;
+ mng_uint16 iBACKblue;
+ mng_uint8 iBACKmandatory;
+ mng_uint16 iBACKimageid;
+ mng_uint8 iBACKtile;
+
+ mng_int32 iBackimgoffsx; /* temp variables for restore_bkgd */
+ mng_int32 iBackimgoffsy;
+ mng_uint32 iBackimgwidth;
+ mng_uint32 iBackimgheight;
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ mng_uint8 iFRAMmode; /* FRAM fields (global) */
+ mng_uint32 iFRAMdelay;
+ mng_uint32 iFRAMtimeout;
+ mng_bool bFRAMclipping;
+ mng_int32 iFRAMclipl;
+ mng_int32 iFRAMclipr;
+ mng_int32 iFRAMclipt;
+ mng_int32 iFRAMclipb;
+
+ mng_uint8 iFramemode; /* current subframe variables */
+ mng_uint32 iFramedelay;
+ mng_uint32 iFrametimeout;
+ mng_bool bFrameclipping;
+ mng_int32 iFrameclipl;
+ mng_int32 iFrameclipr;
+ mng_int32 iFrameclipt;
+ mng_int32 iFrameclipb;
+
+ mng_uint32 iNextdelay; /* delay *after* next image */
+#endif
+
+#ifndef MNG_SKIPCHUNK_SHOW
+ mng_uint8 iSHOWmode; /* SHOW fields */
+ mng_uint16 iSHOWfromid;
+ mng_uint16 iSHOWtoid;
+ mng_uint16 iSHOWnextid;
+ mng_int16 iSHOWskip;
+#endif
+
+ mng_uint32 iGlobalPLTEcount; /* global PLTE fields */
+ mng_rgbpaltab aGlobalPLTEentries;
+
+ mng_uint32 iGlobalTRNSrawlen; /* global tRNS fields */
+ mng_uint8arr aGlobalTRNSrawdata;
+
+ mng_uint32 iGlobalGamma; /* global gAMA fields */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ mng_uint32 iGlobalWhitepointx; /* global cHRM fields */
+ mng_uint32 iGlobalWhitepointy;
+ mng_uint32 iGlobalPrimaryredx;
+ mng_uint32 iGlobalPrimaryredy;
+ mng_uint32 iGlobalPrimarygreenx;
+ mng_uint32 iGlobalPrimarygreeny;
+ mng_uint32 iGlobalPrimarybluex;
+ mng_uint32 iGlobalPrimarybluey;
+#endif
+
+ mng_uint8 iGlobalRendintent; /* global sRGB fields */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ mng_uint32 iGlobalProfilesize; /* global iCCP fields */
+ mng_ptr pGlobalProfile;
+#endif
+
+ mng_uint16 iGlobalBKGDred; /* global bKGD fields */
+ mng_uint16 iGlobalBKGDgreen;
+ mng_uint16 iGlobalBKGDblue;
+
+ mng_ptr pDeltaImage; /* delta-image fields */
+ mng_uint8 iDeltaImagetype;
+#endif /* MNG_SUPPORT_DISPLAY */
+ mng_uint8 iDeltatype; /* need this one in read processing !! */
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_uint32 iDeltaBlockwidth;
+ mng_uint32 iDeltaBlockheight;
+ mng_uint32 iDeltaBlockx;
+ mng_uint32 iDeltaBlocky;
+ mng_bool bDeltaimmediate;
+
+ mng_fptr fDeltagetrow; /* internal delta-proc callbacks */
+ mng_fptr fDeltaaddrow;
+ mng_fptr fDeltareplacerow;
+ mng_fptr fDeltaputrow;
+
+#ifndef MNG_SKIPCHUNK_PROM
+ mng_fptr fPromoterow; /* internal PROM fields */
+ mng_fptr fPromBitdepth;
+ mng_ptr pPromBuf;
+ mng_uint8 iPromColortype;
+ mng_uint8 iPromBitdepth;
+ mng_uint8 iPromFilltype;
+ mng_uint32 iPromWidth;
+ mng_ptr pPromSrc;
+ mng_ptr pPromDst;
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ mng_uint16 iMAGNfromid;
+ mng_uint16 iMAGNcurrentid;
+ mng_uint16 iMAGNtoid;
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ mng_uint16 iPASTid;
+ mng_int32 iPastx; /* target x/y of last PAST */
+ mng_int32 iPasty;
+#endif
+
+ mng_objectp pLastseek; /* last processed ani_seek object */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ mng_objectp pMPNG; /* mpNG object if available */
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ mng_objectp pANG; /* ANG object if available */
+#endif
+
+#endif /* MNG_SUPPORT_DISPLAY */
+
+#ifdef MNG_INCLUDE_ZLIB
+ z_stream sZlib; /* zlib (de)compression variables */
+
+ mng_int32 iZlevel; /* zlib compression parameters */
+ mng_int32 iZmethod;
+ mng_int32 iZwindowbits;
+ mng_int32 iZmemlevel;
+ mng_int32 iZstrategy;
+
+ mng_uint32 iMaxIDAT; /* maximum size of IDAT data */
+
+ mng_bool bInflating; /* indicates "inflate" in progress */
+ mng_bool bDeflating; /* indicates "deflate" in progress */
+#endif /* MNG_INCLUDE_ZLIB */
+
+#ifdef MNG_INCLUDE_JNG
+ mngjpeg_dctmethod eJPEGdctmethod; /* IJG compression variables */
+ mng_int32 iJPEGquality;
+ mng_int32 iJPEGsmoothing;
+ mng_bool bJPEGcompressprogr;
+ mng_bool bJPEGcompressopt;
+
+ mng_uint32 iMaxJDAT; /* maximum size of JDAT/JDAA data */
+
+ mngjpeg_compp pJPEGcinfo; /* compression structure */
+ mngjpeg_errorp pJPEGcerr; /* error-manager compress */
+
+ mngjpeg_decompp pJPEGdinfo; /* decompression structure (JDAT) */
+ mngjpeg_errorp pJPEGderr; /* error-manager decompress (JDAT) */
+ mngjpeg_sourcep pJPEGdsrc; /* source-manager decompress (JDAT) */
+
+ mngjpeg_decompp pJPEGdinfo2; /* decompression structure (JDAA) */
+ mngjpeg_errorp pJPEGderr2; /* error-manager decompress (JDAA) */
+ mngjpeg_sourcep pJPEGdsrc2; /* source-manager decompress (JDAA) */
+
+ mng_uint8p pJPEGbuf; /* buffer for JPEG (de)compression (JDAT) */
+ mng_uint32 iJPEGbufmax; /* allocated space for buffer (JDAT) */
+ mng_uint8p pJPEGcurrent; /* current pointer into buffer (JDAT) */
+ mng_uint32 iJPEGbufremain; /* remaining bytes in buffer (JDAT) */
+ mng_uint32 iJPEGtoskip; /* bytes to skip on next input-block (JDAT) */
+
+ mng_uint8p pJPEGbuf2; /* buffer for JPEG (de)compression (JDAA) */
+ mng_uint32 iJPEGbufmax2; /* allocated space for buffer (JDAA) */
+ mng_uint8p pJPEGcurrent2; /* current pointer into buffer (JDAA) */
+ mng_uint32 iJPEGbufremain2; /* remaining bytes in buffer (JDAA) */
+ mng_uint32 iJPEGtoskip2; /* bytes to skip on next input-block (JDAA) */
+
+ mng_uint8p pJPEGrow; /* buffer for a JPEG row of samples (JDAT) */
+ mng_uint32 iJPEGrowlen;
+
+ mng_uint8p pJPEGrow2; /* buffer for a JPEG row of samples (JDAA) */
+ mng_uint32 iJPEGrowlen2;
+
+ mng_bool bJPEGcompress; /* indicates "compress" initialized */
+
+ mng_bool bJPEGdecompress; /* indicates "decompress" initialized (JDAT) */
+ mng_bool bJPEGhasheader; /* indicates "readheader" succeeded (JDAT) */
+ mng_bool bJPEGdecostarted; /* indicates "decompress" started (JDAT) */
+ mng_bool bJPEGscanstarted; /* indicates "first scan" started (JDAT) */
+ mng_bool bJPEGscanending; /* indicates "finish_output" suspended (JDAT) */
+ mng_bool bJPEGprogressive; /* indicates a progressive image (JDAT) */
+
+ mng_bool bJPEGdecompress2; /* indicates "decompress" initialized (JDAA) */
+ mng_bool bJPEGhasheader2; /* indicates "readheader" succeeded (JDAA) */
+ mng_bool bJPEGdecostarted2; /* indicates "decompress" started (JDAA) */
+ mng_bool bJPEGscanstarted2; /* indicates "first scan" started (JDAA) */
+ mng_bool bJPEGprogressive2; /* indicates a progressive image (JDAA) */
+
+ mng_fptr fStorerow2; /* internal callback to store an
+ uncompressed/unfiltered row of JPEG-data (JDAT) */
+
+ mng_fptr fStorerow3; /* internal callback to store an
+ uncompressed/unfiltered row of JPEG-data (JDAA) */
+
+ mng_uint32 iJPEGrow; /* row-number for current JPEG row */
+ mng_uint32 iJPEGalpharow; /* nr. of rows filled with alpha */
+ mng_uint32 iJPEGrgbrow; /* nr. of rows filled with 'color'-info */
+ mng_uint32 iJPEGdisprow; /* nr. of rows already displayed "on-the-fly" */
+
+#if defined(MNG_USE_SETJMP) && defined (MNG_INCLUDE_IJG6B)
+ jmp_buf sErrorbuf; /* setjmp/longjmp buffer (error-recovery) */
+#endif
+
+#endif /* MNG_INCLUDE_JNG */
+
+#ifndef MNG_USE_ZLIB_CRC
+ mng_uint32 aCRCtable [256]; /* CRC prefab table */
+ mng_bool bCRCcomputed; /* "has been built" indicator */
+#endif
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ png_imgtype ePng_imgtype;
+#endif
+
+#if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
+ mng_uint8 iPNGdepth; /* Real input depth */
+ mng_uint8 iPNGmult;
+#endif
+
+#ifdef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_uint32 iRawlen; /* temp vars for display processing */
+ mng_uint8p pRawdata;
+#ifndef MNG_SKIPCHUNK_BASI
+ mng_uint16 iBASIred;
+ mng_uint16 iBASIgreen;
+ mng_uint16 iBASIblue;
+ mng_bool bBASIhasalpha;
+ mng_uint16 iBASIalpha;
+ mng_uint8 iBASIviewable;
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ mng_uint16 iCLONsourceid;
+ mng_uint16 iCLONcloneid;
+ mng_uint8 iCLONclonetype;
+ mng_bool bCLONhasdonotshow;
+ mng_uint8 iCLONdonotshow;
+ mng_uint8 iCLONconcrete;
+ mng_bool bCLONhasloca;
+ mng_uint8 iCLONlocationtype;
+ mng_int32 iCLONlocationx;
+ mng_int32 iCLONlocationy;
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+ mng_uint32 iDISCcount;
+ mng_uint16p pDISCids;
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+ mng_uint8 iTempFramemode;
+ mng_uint8 iTempChangedelay;
+ mng_uint32 iTempDelay;
+ mng_uint8 iTempChangetimeout;
+ mng_uint32 iTempTimeout;
+ mng_uint8 iTempChangeclipping;
+ mng_uint8 iTempCliptype;
+ mng_int32 iTempClipl;
+ mng_int32 iTempClipr;
+ mng_int32 iTempClipt;
+ mng_int32 iTempClipb;
+#endif
+#ifndef MNG_SKIPCHUNK_MOVE
+ mng_uint16 iMOVEfromid;
+ mng_uint16 iMOVEtoid;
+ mng_uint8 iMOVEmovetype;
+ mng_int32 iMOVEmovex;
+ mng_int32 iMOVEmovey;
+#endif
+#ifndef MNG_SKIPCHUNK_CLIP
+ mng_uint16 iCLIPfromid;
+ mng_uint16 iCLIPtoid;
+ mng_uint8 iCLIPcliptype;
+ mng_int32 iCLIPclipl;
+ mng_int32 iCLIPclipr;
+ mng_int32 iCLIPclipt;
+ mng_int32 iCLIPclipb;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ mng_uint16 iDHDRobjectid;
+ mng_uint8 iDHDRimagetype;
+ mng_uint8 iDHDRdeltatype;
+ mng_uint32 iDHDRblockwidth;
+ mng_uint32 iDHDRblockheight;
+ mng_uint32 iDHDRblockx;
+ mng_uint32 iDHDRblocky;
+ mng_uint8 iPROMbitdepth;
+ mng_uint8 iPROMcolortype;
+ mng_uint8 iPROMfilltype;
+ mng_uint8 iPPLTtype;
+ mng_uint32 iPPLTcount;
+ mng_palette8ep paPPLTindexentries;
+ mng_uint8p paPPLTalphaentries;
+ mng_uint8p paPPLTusedentries;
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+ mng_uint16 iMAGNfirstid;
+ mng_uint16 iMAGNlastid;
+ mng_uint8 iMAGNmethodX;
+ mng_uint16 iMAGNmX;
+ mng_uint16 iMAGNmY;
+ mng_uint16 iMAGNmL;
+ mng_uint16 iMAGNmR;
+ mng_uint16 iMAGNmT;
+ mng_uint16 iMAGNmB;
+ mng_uint8 iMAGNmethodY;
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ mng_uint16 iPASTtargetid;
+ mng_uint8 iPASTtargettype;
+ mng_int32 iPASTtargetx;
+ mng_int32 iPASTtargety;
+ mng_uint32 iPASTcount;
+ mng_ptr pPASTsources;
+#endif
+#endif /* MNG_OPTIMIZE_DISPLAYCALLS */
+
+ } mng_data;
+
+typedef mng_data * mng_datap;
+
+/* ************************************************************************** */
+/* * * */
+/* * Internal Callback-Function prototypes * */
+/* * * */
+/* ************************************************************************** */
+
+typedef mng_retcode(*mng_displayrow) (mng_datap pData);
+typedef mng_retcode(*mng_restbkgdrow) (mng_datap pData);
+typedef mng_retcode(*mng_correctrow) (mng_datap pData);
+typedef mng_retcode(*mng_retrieverow) (mng_datap pData);
+typedef mng_retcode(*mng_storerow) (mng_datap pData);
+typedef mng_retcode(*mng_processrow) (mng_datap pData);
+typedef mng_retcode(*mng_initrowproc) (mng_datap pData);
+typedef mng_retcode(*mng_differrow) (mng_datap pData);
+typedef mng_retcode(*mng_scalerow) (mng_datap pData);
+typedef mng_retcode(*mng_deltarow) (mng_datap pData);
+typedef mng_retcode(*mng_promoterow) (mng_datap pData);
+typedef mng_retcode(*mng_fliprow) (mng_datap pData);
+typedef mng_retcode(*mng_tilerow) (mng_datap pData);
+
+typedef mng_uint8 (*mng_bitdepth_8) (mng_uint8 iB);
+typedef mng_uint16 (*mng_bitdepth_16) (mng_uint8 iB);
+
+typedef mng_retcode(*mng_magnify_x) (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p iSrcline,
+ mng_uint8p iDstline);
+typedef mng_retcode(*mng_magnify_y) (mng_datap pData,
+ mng_int32 iM,
+ mng_int32 iS,
+ mng_uint32 iWidth,
+ mng_uint8p iSrcline1,
+ mng_uint8p iSrcline2,
+ mng_uint8p iDstline);
+
+/* ************************************************************************** */
+/* * * */
+/* * Routines for swapping byte-order from and to graphic files * */
+/* * (This code is adapted from the libpng package) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_BIGENDIAN_SUPPORTED
+mng_uint32 mng_get_uint32 (mng_uint8p pBuf);
+mng_int32 mng_get_int32 (mng_uint8p pBuf);
+mng_uint16 mng_get_uint16 (mng_uint8p pBuf);
+void mng_put_uint32 (mng_uint8p pBuf,
+ mng_uint32 i);
+void mng_put_int32 (mng_uint8p pBuf,
+ mng_int32 i);
+void mng_put_uint16 (mng_uint8p pBuf,
+ mng_uint16 i);
+#else /* MNG_BIGENDIAN_SUPPORTED */
+#define mng_get_uint32(P) *(mng_uint32p)(P)
+#define mng_get_int32(P) *(mng_int32p)(P)
+#define mng_get_uint16(P) *(mng_uint16p)(P)
+#define mng_put_uint32(P,I) *(mng_uint32p)(P) = (I)
+#define mng_put_int32(P,I) *(mng_int32p)(P) = (I)
+#define mng_put_uint16(P,I) *(mng_uint16p)(P) = (I)
+#endif /* MNG_BIGENDIAN_SUPPORTED */
+
+/* ************************************************************************** */
+/* * * */
+/* * Some handy(?) macro definitions * */
+/* * * */
+/* ************************************************************************** */
+
+#define MAX_COORD(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN_COORD(a, b) (((a) < (b)) ? (a) : (b))
+
+/* ************************************************************************** */
+
+#endif /* _libmng_data_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_display.c b/Source/LibMNG/libmng_display.c
new file mode 100644
index 0000000..adfb91d
--- /dev/null
+++ b/Source/LibMNG/libmng_display.c
@@ -0,0 +1,7135 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_display.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Display management (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the display management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added callback error-reporting support * */
+/* * - fixed frame_delay misalignment * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - added sanity check for frozen status * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * 0.5.1 - 05/13/2000 - G.Juyn * */
+/* * - changed display_mend to reset state to initial or SAVE * */
+/* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
+/* * - added TERM animation object pointer (easier reference) * */
+/* * - added process_save & process_seek routines * */
+/* * 0.5.1 - 05/14/2000 - G.Juyn * */
+/* * - added save_state and restore_state for SAVE/SEEK/TERM * */
+/* * processing * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - added JNG support (JHDR/JDAT) * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - fixed problem with DEFI clipping * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added delta-image support (DHDR,PROM,IPNG,IJNG) * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed pointer confusion (contributed by Tim Rowley) * */
+/* * 0.5.2 - 06/03/2000 - G.Juyn * */
+/* * - fixed makeup for Linux gcc compile * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - added support for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/09/2000 - G.Juyn * */
+/* * - fixed timer-handling to run with Mozilla (Tim Rowley) * */
+/* * 0.5.2 - 06/10/2000 - G.Juyn * */
+/* * - fixed some compilation-warnings (contrib Jason Morris) * */
+/* * * */
+/* * 0.5.3 - 06/12/2000 - G.Juyn * */
+/* * - fixed display of stored JNG images * */
+/* * 0.5.3 - 06/13/2000 - G.Juyn * */
+/* * - fixed problem with BASI-IEND as object 0 * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - changed delta-image processing * */
+/* * 0.5.3 - 06/20/2000 - G.Juyn * */
+/* * - fixed some minor stuff * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added speed-modifier to timing routine * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added support for PPLT chunk processing * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - swapped refresh parameters * */
+/* * * */
+/* * 0.9.0 - 06/30/2000 - G.Juyn * */
+/* * - changed refresh parameters to 'x,y,width,height' * */
+/* * * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - implemented support for freeze/reset/resume & go_xxxx * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added support for improved timing * */
+/* * 0.9.1 - 07/14/2000 - G.Juyn * */
+/* * - changed EOF processing behavior * */
+/* * - fixed TERM delay processing * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - fixed freeze & reset processing * */
+/* * 0.9.1 - 07/16/2000 - G.Juyn * */
+/* * - fixed storage of images during mng_read() * */
+/* * - fixed support for mng_display() after mng_read() * */
+/* * 0.9.1 - 07/24/2000 - G.Juyn * */
+/* * - fixed reading of still-images * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/21/2000 - G.Juyn * */
+/* * - fixed TERM processing delay of 0 msecs * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed problem with no refresh after TERM * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 09/16/2000 - G.Juyn * */
+/* * - fixed timing & refresh behavior for single PNG/JNG * */
+/* * 0.9.3 - 09/19/2000 - G.Juyn * */
+/* * - refixed timing & refresh behavior for single PNG/JNG * */
+/* * 0.9.3 - 10/02/2000 - G.Juyn * */
+/* * - fixed timing again (this is getting boring...) * */
+/* * - refixed problem with no refresh after TERM * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added JDAA chunk * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - fixed support for bKGD * */
+/* * 0.9.3 - 10/18/2000 - G.Juyn * */
+/* * - fixed delta-processing behavior * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - added storage for pixel-/alpha-sampledepth for delta's * */
+/* * 0.9.3 - 10/27/2000 - G.Juyn * */
+/* * - fixed separate read() & display() processing * */
+/* * * */
+/* * 0.9.4 - 10/31/2000 - G.Juyn * */
+/* * - fixed possible loop in display_resume() (Thanks Vova!) * */
+/* * 0.9.4 - 11/20/2000 - G.Juyn * */
+/* * - fixed unwanted repetition in mng_readdisplay() * */
+/* * 0.9.4 - 11/24/2000 - G.Juyn * */
+/* * - moved restore of object 0 to libmng_display * */
+/* * - added restore of object 0 to TERM processing !!! * */
+/* * - fixed TERM delay processing * */
+/* * - fixed TERM end processing (count = 0) * */
+/* * 0.9.4 - 12/16/2000 - G.Juyn * */
+/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - removed test filter-methods 1 & 65 * */
+/* * - set default level-set for filtertype=64 to all zeroes * */
+/* * * */
+/* * 0.9.5 - 1/20/2001 - G.Juyn * */
+/* * - fixed compiler-warnings Mozilla (thanks Tim) * */
+/* * 0.9.5 - 1/23/2001 - G.Juyn * */
+/* * - fixed timing-problem with switching framing_modes * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 02/13/2001 - G.Juyn * */
+/* * - fixed first FRAM_MODE=4 timing problem * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn * */
+/* * - fixed memory-leak for JNGs with alpha (Thanks Gregg!) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - fixed memory-leak with delta-images (Thanks Michael!) * */
+/* * * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - fixed color-correction for restore-background handling * */
+/* * - optimized restore-background for bKGD cases * */
+/* * - cleaned up some old stuff * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - finished support for BACK image & tiling * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 10/05/2002 - G.Juyn * */
+/* * - fixed dropping mix of frozen/unfrozen objects * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added proposed change in handling of TERM- & if-delay * */
+/* * - added another fix for misplaced TERM chunk * */
+/* * - completed support for condition=2 in TERM chunk * */
+/* * 1.0.5 - 10/18/2002 - G.Juyn * */
+/* * - fixed clipping-problem with BACK tiling (Thanks Sakura!) * */
+/* * 1.0.5 - 10/20/2002 - G.Juyn * */
+/* * - fixed processing for multiple objects in MAGN * */
+/* * - fixed display of visible target of PAST operation * */
+/* * 1.0.5 - 10/30/2002 - G.Juyn * */
+/* * - modified TERM/MEND processing for max(1, TERM_delay, * */
+/* * interframe_delay) * */
+/* * 1.0.5 - 11/04/2002 - G.Juyn * */
+/* * - fixed layer- & frame-counting during read() * */
+/* * - fixed goframe/golayer/gotime processing * */
+/* * 1.0.5 - 01/19/2003 - G.Juyn * */
+/* * - B654627 - fixed SEGV when no gettickcount callback * */
+/* * - B664383 - fixed typo * */
+/* * - finalized changes in TERM/final_delay to elected proposal* */
+/* * * */
+/* * 1.0.6 - 05/11/2003 - G. Juyn * */
+/* * - added conditionals around canvas update routines * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added conditionals around some JNG-supporting code * */
+/* * - added conditionals around 16-bit supporting code * */
+/* * - reversed some loops to use decrementing counter * */
+/* * - combined init functions into one function * */
+/* * 1.0.6 - 07/10/2003 - G.R-P * */
+/* * - replaced nested switches with simple init setup function * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added conditionals around non-VLC chunk support * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 12/06/2003 - R.A * */
+/* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * * */
+/* * 1.0.8 - 03/31/2004 - G.Juyn * */
+/* * - fixed problem with PAST usage where source > dest * */
+/* * 1.0.8 - 05/04/2004 - G.R-P. * */
+/* * - fixed misplaced 16-bit conditionals * */
+/* * * */
+/* * 1.0.9 - 09/18/2004 - G.R-P. * */
+/* * - revised some SKIPCHUNK conditionals * */
+/* * 1.0.9 - 10/10/2004 - G.R-P. * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 07/06/2005 - G.R-P. * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * 1.0.10 - 12/28/2005 - G.R-P. * */
+/* * - added missing SKIPCHUNK_MAGN conditional * */
+/* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
+/* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - fixed several compiler warnings * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_chunks.h"
+#include "libmng_objects.h"
+#include "libmng_object_prc.h"
+#include "libmng_memory.h"
+#include "libmng_zlib.h"
+#include "libmng_jpeg.h"
+#include "libmng_cms.h"
+#include "libmng_pixels.h"
+#include "libmng_display.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode set_delay (mng_datap pData,
+ mng_uint32 iInterval)
+{
+ if (!iInterval) /* at least 1 msec please! */
+ iInterval = 1;
+
+ if (pData->bRunning) /* only when really displaying */
+ if (!pData->fSettimer ((mng_handle)pData, iInterval))
+ MNG_ERROR (pData, MNG_APPTIMERERROR);
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ if ((!pData->bDynamic) || (pData->bRunning))
+#else
+ if (pData->bRunning)
+#endif
+ pData->bTimerset = MNG_TRUE; /* and indicate so */
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_uint32 calculate_delay (mng_datap pData,
+ mng_uint32 iDelay)
+{
+ mng_uint32 iTicks = pData->iTicks;
+ mng_uint32 iWaitfor = 1; /* default non-MNG delay */
+
+ if (!iTicks) /* tick_count not specified ? */
+ if (pData->eImagetype == mng_it_mng)
+ iTicks = 1000;
+
+ if (iTicks)
+ {
+ switch (pData->iSpeed) /* honor speed modifier */
+ {
+ case mng_st_fast :
+ {
+ iWaitfor = (mng_uint32)(( 500 * iDelay) / iTicks);
+ break;
+ }
+ case mng_st_slow :
+ {
+ iWaitfor = (mng_uint32)((3000 * iDelay) / iTicks);
+ break;
+ }
+ case mng_st_slowest :
+ {
+ iWaitfor = (mng_uint32)((8000 * iDelay) / iTicks);
+ break;
+ }
+ default :
+ {
+ iWaitfor = (mng_uint32)((1000 * iDelay) / iTicks);
+ }
+ }
+ }
+
+ return iWaitfor;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Progressive display refresh - does the call to the refresh callback * */
+/* * and sets the timer to allow the app to perform the actual refresh to * */
+/* * the screen (eg. process its main message-loop) * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_display_progressive_refresh (mng_datap pData,
+ mng_uint32 iInterval)
+{
+ { /* let the app refresh first ? */
+ if ((pData->bRunning) && (!pData->bSkipping) &&
+ (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright))
+ {
+ if (!pData->fRefresh (((mng_handle)pData),
+ pData->iUpdateleft, pData->iUpdatetop,
+ pData->iUpdateright - pData->iUpdateleft,
+ pData->iUpdatebottom - pData->iUpdatetop))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ pData->iUpdateleft = 0; /* reset update-region */
+ pData->iUpdateright = 0;
+ pData->iUpdatetop = 0;
+ pData->iUpdatebottom = 0; /* reset refreshneeded indicator */
+ pData->bNeedrefresh = MNG_FALSE;
+ /* interval requested ? */
+ if ((!pData->bFreezing) && (iInterval))
+ { /* setup the timer */
+ mng_retcode iRetcode = set_delay (pData, iInterval);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+ }
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Generic display routines * */
+/* * * */
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode interframe_delay (mng_datap pData)
+{
+ mng_uint32 iWaitfor = 0;
+ mng_uint32 iInterval;
+ mng_uint32 iRuninterval;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_START);
+#endif
+
+ {
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pData->iFramedelay > 0) /* real delay ? */
+ { /* let the app refresh first ? */
+ if ((pData->bRunning) && (!pData->bSkipping) &&
+ (pData->iUpdatetop < pData->iUpdatebottom) && (pData->iUpdateleft < pData->iUpdateright))
+ if (!pData->fRefresh (((mng_handle)pData),
+ pData->iUpdateleft, pData->iUpdatetop,
+ pData->iUpdateright - pData->iUpdateleft,
+ pData->iUpdatebottom - pData->iUpdatetop))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ pData->iUpdateleft = 0; /* reset update-region */
+ pData->iUpdateright = 0;
+ pData->iUpdatetop = 0;
+ pData->iUpdatebottom = 0; /* reset refreshneeded indicator */
+ pData->bNeedrefresh = MNG_FALSE;
+
+#ifndef MNG_SKIPCHUNK_TERM
+ if (pData->bOnlyfirstframe) /* only processing first frame after TERM ? */
+ {
+ pData->iFramesafterTERM++;
+ /* did we do a frame yet ? */
+ if (pData->iFramesafterTERM > 1)
+ { /* then that's it; just stop right here ! */
+ pData->pCurraniobj = MNG_NULL;
+ pData->bRunning = MNG_FALSE;
+
+ return MNG_NOERROR;
+ }
+ }
+#endif
+
+ if (pData->fGettickcount)
+ { /* get current tickcount */
+ pData->iRuntime = pData->fGettickcount ((mng_handle)pData);
+ /* calculate interval since last sync-point */
+ if (pData->iRuntime < pData->iSynctime)
+ iRuninterval = pData->iRuntime + ~pData->iSynctime + 1;
+ else
+ iRuninterval = pData->iRuntime - pData->iSynctime;
+ /* calculate actual run-time */
+ if (pData->iRuntime < pData->iStarttime)
+ pData->iRuntime = pData->iRuntime + ~pData->iStarttime + 1;
+ else
+ pData->iRuntime = pData->iRuntime - pData->iStarttime;
+ }
+ else
+ {
+ iRuninterval = 0;
+ }
+
+ iWaitfor = calculate_delay (pData, pData->iFramedelay);
+
+ if (iWaitfor > iRuninterval) /* delay necessary ? */
+ iInterval = iWaitfor - iRuninterval;
+ else
+ iInterval = 1; /* force app to process messageloop */
+ /* set the timer ? */
+ if (((pData->bRunning) || (pData->bSearching) || (pData->bReading)) &&
+ (!pData->bSkipping))
+ {
+ iRetcode = set_delay (pData, iInterval);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+
+ if (!pData->bSkipping) /* increase frametime in advance */
+ pData->iFrametime = pData->iFrametime + iWaitfor;
+ /* setup for next delay */
+ pData->iFramedelay = pData->iNextdelay;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INTERFRAME_DELAY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL void set_display_routine (mng_datap pData)
+{ /* actively running ? */
+ if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
+ {
+ switch (pData->iCanvasstyle) /* determine display routine */
+ {
+#ifndef MNG_SKIPCANVAS_RGB8
+ case MNG_CANVAS_RGB8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8
+ case MNG_CANVAS_RGBA8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8_PM
+ case MNG_CANVAS_RGBA8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_rgba8_pm; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8
+ case MNG_CANVAS_ARGB8 : { pData->fDisplayrow = (mng_fptr)mng_display_argb8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8_PM
+ case MNG_CANVAS_ARGB8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_argb8_pm; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGB8_A8
+ case MNG_CANVAS_RGB8_A8 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb8_a8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+ case MNG_CANVAS_BGR8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+ case MNG_CANVAS_BGRX8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgrx8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8
+ case MNG_CANVAS_BGRA8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8_PM
+ case MNG_CANVAS_BGRA8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_bgra8_pm; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8
+ case MNG_CANVAS_ABGR8 : { pData->fDisplayrow = (mng_fptr)mng_display_abgr8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8_PM
+ case MNG_CANVAS_ABGR8_PM: { pData->fDisplayrow = (mng_fptr)mng_display_abgr8_pm; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+ case MNG_CANVAS_RGB565 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb565; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA565
+ case MNG_CANVAS_RGBA565 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba565; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+ case MNG_CANVAS_BGR565 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr565; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA565
+ case MNG_CANVAS_BGRA565 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra565; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565_A8
+ case MNG_CANVAS_BGR565_A8 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr565_a8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGB555
+ case MNG_CANVAS_RGB555 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb555; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR555
+ case MNG_CANVAS_BGR555 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr555; break; }
+#endif
+
+#ifndef MNG_NO_16BIT_SUPPORT
+/* case MNG_CANVAS_RGB16 : { pData->fDisplayrow = (mng_fptr)mng_display_rgb16; break; } */
+/* case MNG_CANVAS_RGBA16 : { pData->fDisplayrow = (mng_fptr)mng_display_rgba16; break; } */
+/* case MNG_CANVAS_ARGB16 : { pData->fDisplayrow = (mng_fptr)mng_display_argb16; break; } */
+/* case MNG_CANVAS_BGR16 : { pData->fDisplayrow = (mng_fptr)mng_display_bgr16; break; } */
+/* case MNG_CANVAS_BGRA16 : { pData->fDisplayrow = (mng_fptr)mng_display_bgra16; break; } */
+/* case MNG_CANVAS_ABGR16 : { pData->fDisplayrow = (mng_fptr)mng_display_abgr16; break; } */
+#endif
+/* case MNG_CANVAS_INDEX8 : { pData->fDisplayrow = (mng_fptr)mng_display_index8; break; } */
+/* case MNG_CANVAS_INDEXA8 : { pData->fDisplayrow = (mng_fptr)mng_display_indexa8; break; } */
+/* case MNG_CANVAS_AINDEX8 : { pData->fDisplayrow = (mng_fptr)mng_display_aindex8; break; } */
+/* case MNG_CANVAS_GRAY8 : { pData->fDisplayrow = (mng_fptr)mng_display_gray8; break; } */
+/* case MNG_CANVAS_AGRAY8 : { pData->fDisplayrow = (mng_fptr)mng_display_agray8; break; } */
+/* case MNG_CANVAS_GRAYA8 : { pData->fDisplayrow = (mng_fptr)mng_display_graya8; break; } */
+#ifndef MNG_NO_16BIT_SUPPORT
+/* case MNG_CANVAS_GRAY16 : { pData->fDisplayrow = (mng_fptr)mng_display_gray16; break; } */
+/* case MNG_CANVAS_GRAYA16 : { pData->fDisplayrow = (mng_fptr)mng_display_graya16; break; } */
+/* case MNG_CANVAS_AGRAY16 : { pData->fDisplayrow = (mng_fptr)mng_display_agray16; break; } */
+#endif
+/* case MNG_CANVAS_DX15 : { pData->fDisplayrow = (mng_fptr)mng_display_dx15; break; } */
+/* case MNG_CANVAS_DX16 : { pData->fDisplayrow = (mng_fptr)mng_display_dx16; break; } */
+ }
+ }
+
+ return;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode load_bkgdlayer (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_START);
+#endif
+ /* actively running ? */
+ if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
+ {
+ mng_int32 iY;
+ mng_retcode iRetcode;
+ mng_bool bColorcorr = MNG_FALSE;
+ /* save values */
+ mng_int32 iDestl = pData->iDestl;
+ mng_int32 iDestr = pData->iDestr;
+ mng_int32 iDestt = pData->iDestt;
+ mng_int32 iDestb = pData->iDestb;
+ mng_int32 iSourcel = pData->iSourcel;
+ mng_int32 iSourcer = pData->iSourcer;
+ mng_int32 iSourcet = pData->iSourcet;
+ mng_int32 iSourceb = pData->iSourceb;
+ mng_int8 iPass = pData->iPass;
+ mng_int32 iRow = pData->iRow;
+ mng_int32 iRowinc = pData->iRowinc;
+ mng_int32 iCol = pData->iCol;
+ mng_int32 iColinc = pData->iColinc;
+ mng_int32 iRowsamples = pData->iRowsamples;
+ mng_int32 iRowsize = pData->iRowsize;
+ mng_uint8p pPrevrow = pData->pPrevrow;
+ mng_uint8p pRGBArow = pData->pRGBArow;
+ mng_bool bIsRGBA16 = pData->bIsRGBA16;
+ mng_bool bIsOpaque = pData->bIsOpaque;
+ mng_fptr fCorrectrow = pData->fCorrectrow;
+ mng_fptr fDisplayrow = pData->fDisplayrow;
+ mng_fptr fRetrieverow = pData->fRetrieverow;
+ mng_objectp pCurrentobj = pData->pCurrentobj;
+ mng_objectp pRetrieveobj = pData->pRetrieveobj;
+
+ pData->iDestl = 0; /* determine clipping region */
+ pData->iDestt = 0;
+ pData->iDestr = pData->iWidth;
+ pData->iDestb = pData->iHeight;
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pData->bFrameclipping) /* frame clipping specified ? */
+ {
+ pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl);
+ pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt);
+ pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr);
+ pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb);
+ }
+#endif
+ /* anything to clear ? */
+ if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt))
+ {
+ pData->iPass = -1; /* these are the object's dimensions now */
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iWidth;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */
+ pData->bIsOpaque = MNG_TRUE;
+
+ pData->iSourcel = 0; /* source relative to destination */
+ pData->iSourcer = pData->iDestr - pData->iDestl;
+ pData->iSourcet = 0;
+ pData->iSourceb = pData->iDestb - pData->iDestt;
+
+ set_display_routine (pData); /* determine display routine */
+ /* default restore using preset BG color */
+ pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgcolor;
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ if (((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng)) &&
+ (pData->bUseBKGD))
+ { /* prefer bKGD in PNG/JNG */
+ if (!pData->pCurrentobj)
+ pData->pCurrentobj = pData->pObjzero;
+
+ if (((mng_imagep)pData->pCurrentobj)->pImgbuf->bHasBKGD)
+ {
+ pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bkgd;
+ bColorcorr = MNG_TRUE;
+ }
+ }
+#endif
+
+ if (pData->fGetbkgdline) /* background-canvas-access callback set ? */
+ {
+ switch (pData->iBkgdstyle)
+ {
+#ifndef MNG_SKIPCANVAS_RGB8
+ case MNG_CANVAS_RGB8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+ case MNG_CANVAS_BGR8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+ case MNG_CANVAS_BGRX8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgrx8; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+ case MNG_CANVAS_BGR565 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr565; break; }
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+ case MNG_CANVAS_RGB565 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb565; break; }
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ /* case MNG_CANVAS_RGB16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_rgb16; break; } */
+ /* case MNG_CANVAS_BGR16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_bgr16; break; } */
+#endif
+ /* case MNG_CANVAS_INDEX8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_index8; break; } */
+ /* case MNG_CANVAS_GRAY8 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_gray8; break; } */
+#ifndef MNG_NO_16BIT_SUPPORT
+ /* case MNG_CANVAS_GRAY16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_gray16; break; } */
+#endif
+ /* case MNG_CANVAS_DX15 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_dx15; break; } */
+ /* case MNG_CANVAS_DX16 : { pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_dx16; break; } */
+ }
+ }
+
+#ifndef MNG_SKIPCHUNK_BACK
+ if (pData->bHasBACK)
+ { /* background image ? */
+ if ((pData->iBACKmandatory & 0x02) && (pData->iBACKimageid))
+ {
+ pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_backcolor;
+ bColorcorr = MNG_TRUE;
+ }
+ else /* background color ? */
+ if (pData->iBACKmandatory & 0x01)
+ {
+ pData->fRestbkgdrow = (mng_fptr)mng_restore_bkgd_backcolor;
+ bColorcorr = MNG_TRUE;
+ }
+ }
+#endif
+
+ pData->fCorrectrow = MNG_NULL; /* default no color-correction */
+
+ if (bColorcorr) /* do we have to do color-correction ? */
+ {
+#ifdef MNG_NO_CMS
+ iRetcode = MNG_NOERROR;
+#else
+#if defined(MNG_FULL_CMS) /* determine color-management routine */
+ iRetcode = mng_init_full_cms (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
+#elif defined(MNG_GAMMA_ONLY)
+ iRetcode = mng_init_gamma_only (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
+#elif defined(MNG_APP_CMS)
+ iRetcode = mng_init_app_cms (pData, MNG_TRUE, MNG_FALSE, MNG_FALSE);
+#endif
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_NO_CMS */
+ }
+ /* get a temporary row-buffer */
+ MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
+
+ iY = pData->iDestt; /* this is where we start */
+ iRetcode = MNG_NOERROR; /* so far, so good */
+
+ while ((!iRetcode) && (iY < pData->iDestb))
+ { /* restore a background row */
+ iRetcode = ((mng_restbkgdrow)pData->fRestbkgdrow) (pData);
+ /* color correction ? */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* so... display it */
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_next_row (pData);
+
+ iY++; /* and next line */
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#if defined(MNG_FULL_CMS) /* cleanup cms stuff */
+ if (bColorcorr) /* did we do color-correction ? */
+ {
+ iRetcode = mng_clear_cms (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+#ifndef MNG_SKIPCHUNK_BACK
+ /* background image ? */
+ if ((pData->bHasBACK) && (pData->iBACKmandatory & 0x02) && (pData->iBACKimageid))
+ {
+ mng_imagep pImage;
+ /* let's find that object then */
+ pData->pRetrieveobj = mng_find_imageobject (pData, pData->iBACKimageid);
+ pImage = (mng_imagep)pData->pRetrieveobj;
+ /* exists, viewable and visible ? */
+ if ((pImage) && (pImage->bViewable) && (pImage->bVisible))
+ { /* will it fall within the target region ? */
+ if ((pImage->iPosx < pData->iDestr) && (pImage->iPosy < pData->iDestb) &&
+ ((pData->iBACKtile) ||
+ ((pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth >= pData->iDestl) &&
+ (pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight >= pData->iDestt) )) &&
+ ((!pImage->bClipped) ||
+ ((pImage->iClipl <= pImage->iClipr) && (pImage->iClipt <= pImage->iClipb) &&
+ (pImage->iClipl < pData->iDestr) && (pImage->iClipr >= pData->iDestl) &&
+ (pImage->iClipt < pData->iDestb) && (pImage->iClipb >= pData->iDestt) )))
+ { /* right; we've got ourselves something to do */
+ if (pImage->bClipped) /* clip output region with image's clipping region ? */
+ {
+ if (pImage->iClipl > pData->iDestl)
+ pData->iDestl = pImage->iClipl;
+ if (pImage->iClipr < pData->iDestr)
+ pData->iDestr = pImage->iClipr;
+ if (pImage->iClipt > pData->iDestt)
+ pData->iDestt = pImage->iClipt;
+ if (pImage->iClipb < pData->iDestb)
+ pData->iDestb = pImage->iClipb;
+ }
+ /* image offset does some extra clipping too ! */
+ if (pImage->iPosx > pData->iDestl)
+ pData->iDestl = pImage->iPosx;
+ if (pImage->iPosy > pData->iDestt)
+ pData->iDestt = pImage->iPosy;
+
+ if (!pData->iBACKtile) /* without tiling further clipping is needed */
+ {
+ if (pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth < pData->iDestr)
+ pData->iDestr = pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth;
+ if (pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight < pData->iDestb)
+ pData->iDestb = pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight;
+ }
+
+ pData->iSourcel = 0; /* source relative to destination */
+ pData->iSourcer = pData->iDestr - pData->iDestl;
+ pData->iSourcet = 0;
+ pData->iSourceb = pData->iDestb - pData->iDestt;
+ /* 16-bit background ? */
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ pData->bIsRGBA16 = MNG_FALSE;
+#else
+ pData->bIsRGBA16 = (mng_bool)(pImage->pImgbuf->iBitdepth > 8);
+#endif
+ /* let restore routine know the offsets !!! */
+ pData->iBackimgoffsx = pImage->iPosx;
+ pData->iBackimgoffsy = pImage->iPosy;
+ pData->iBackimgwidth = pImage->pImgbuf->iWidth;
+ pData->iBackimgheight = pImage->pImgbuf->iHeight;
+ pData->iRow = 0; /* start at the top again !! */
+ /* determine background object retrieval routine */
+ switch (pImage->pImgbuf->iColortype)
+ {
+ case 0 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+ case 2 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+ case 3 : { pData->fRetrieverow = (mng_fptr)mng_retrieve_idx8;
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+ case 4 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ case 6 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+ case 10 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+ case 12 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ case 14 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+ }
+
+#ifdef MNG_NO_CMS
+ iRetcode = MNG_NOERROR;
+#else
+#if defined(MNG_FULL_CMS) /* determine color-management routine */
+ iRetcode = mng_init_full_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_GAMMA_ONLY)
+ iRetcode = mng_init_gamma_only (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_APP_CMS)
+ iRetcode = mng_init_app_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#endif
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_NO_CMS */
+ /* get temporary row-buffers */
+ MNG_ALLOC (pData, pData->pPrevrow, pData->iRowsize);
+ MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
+
+ iY = pData->iDestt; /* this is where we start */
+ iRetcode = MNG_NOERROR; /* so far, so good */
+
+ while ((!iRetcode) && (iY < pData->iDestb))
+ { /* restore a background row */
+ iRetcode = mng_restore_bkgd_backimage (pData);
+ /* color correction ? */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* so... display it */
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_next_row (pData);
+
+ iY++; /* and next line */
+ }
+ /* drop temporary row-buffers */
+ MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
+ MNG_FREE (pData, pData->pPrevrow, pData->iRowsize);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#if defined(MNG_FULL_CMS) /* cleanup cms stuff */
+ iRetcode = mng_clear_cms (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+ }
+ }
+ }
+#endif
+ }
+
+ pData->iDestl = iDestl; /* restore values */
+ pData->iDestr = iDestr;
+ pData->iDestt = iDestt;
+ pData->iDestb = iDestb;
+ pData->iSourcel = iSourcel;
+ pData->iSourcer = iSourcer;
+ pData->iSourcet = iSourcet;
+ pData->iSourceb = iSourceb;
+ pData->iPass = iPass;
+ pData->iRow = iRow;
+ pData->iRowinc = iRowinc;
+ pData->iCol = iCol;
+ pData->iColinc = iColinc;
+ pData->iRowsamples = iRowsamples;
+ pData->iRowsize = iRowsize;
+ pData->pPrevrow = pPrevrow;
+ pData->pRGBArow = pRGBArow;
+ pData->bIsRGBA16 = bIsRGBA16;
+ pData->bIsOpaque = bIsOpaque;
+ pData->fCorrectrow = fCorrectrow;
+ pData->fDisplayrow = fDisplayrow;
+ pData->fRetrieverow = fRetrieverow;
+ pData->pCurrentobj = pCurrentobj;
+ pData->pRetrieveobj = pRetrieveobj;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_LOAD_BKGDLAYER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode clear_canvas (mng_datap pData)
+{
+ mng_int32 iY;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_START);
+#endif
+
+ pData->iDestl = 0; /* clipping region is full canvas! */
+ pData->iDestt = 0;
+ pData->iDestr = pData->iWidth;
+ pData->iDestb = pData->iHeight;
+
+ pData->iSourcel = 0; /* source is same as destination */
+ pData->iSourcer = pData->iWidth;
+ pData->iSourcet = 0;
+ pData->iSourceb = pData->iHeight;
+
+ pData->iPass = -1; /* these are the object's dimensions now */
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iWidth;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->bIsRGBA16 = MNG_FALSE; /* let's keep it simple ! */
+ pData->bIsOpaque = MNG_TRUE;
+
+ set_display_routine (pData); /* determine display routine */
+ /* get a temporary row-buffer */
+ /* it's transparent black by default!! */
+ MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
+
+ iY = pData->iDestt; /* this is where we start */
+ iRetcode = MNG_NOERROR; /* so far, so good */
+
+ while ((!iRetcode) && (iY < pData->iDestb))
+ { /* clear a row then */
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode)
+ iRetcode = mng_next_row (pData); /* adjust variables for next row */
+
+ iY++; /* and next line */
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEAR_CANVAS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode next_frame (mng_datap pData,
+ mng_uint8 iFramemode,
+ mng_uint8 iChangedelay,
+ mng_uint32 iDelay,
+ mng_uint8 iChangetimeout,
+ mng_uint32 iTimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_START);
+#endif
+
+ if (!pData->iBreakpoint) /* no previous break here ? */
+ {
+#ifndef MNG_SKIPCHUNK_FRAM
+ mng_uint8 iOldmode = pData->iFramemode;
+ /* interframe delay required ? */
+ if ((iOldmode == 2) || (iOldmode == 4))
+ {
+ if ((pData->iFrameseq) && (iFramemode != 1) && (iFramemode != 3))
+ iRetcode = interframe_delay (pData);
+ else
+ pData->iFramedelay = pData->iNextdelay;
+ }
+ else
+ { /* delay before inserting background layer? */
+ if ((pData->bFramedone) && (iFramemode == 4))
+ iRetcode = interframe_delay (pData);
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* now we'll assume we're in the next frame! */
+ if (iFramemode) /* save the new framing mode ? */
+ {
+ pData->iFRAMmode = iFramemode;
+ pData->iFramemode = iFramemode;
+ }
+ else /* reload default */
+ pData->iFramemode = pData->iFRAMmode;
+
+ if (iChangedelay) /* delay changed ? */
+ {
+ pData->iNextdelay = iDelay; /* for *after* next subframe */
+
+ if ((iOldmode == 2) || (iOldmode == 4))
+ pData->iFramedelay = pData->iFRAMdelay;
+
+ if (iChangedelay == 2) /* also overall ? */
+ pData->iFRAMdelay = iDelay;
+ }
+ else
+ { /* reload default */
+ pData->iNextdelay = pData->iFRAMdelay;
+ }
+
+ if (iChangetimeout) /* timeout changed ? */
+ { /* for next subframe */
+ pData->iFrametimeout = iTimeout;
+
+ if ((iChangetimeout == 2) || /* also overall ? */
+ (iChangetimeout == 4) ||
+ (iChangetimeout == 6) ||
+ (iChangetimeout == 8))
+ pData->iFRAMtimeout = iTimeout;
+ }
+ else /* reload default */
+ pData->iFrametimeout = pData->iFRAMtimeout;
+
+ if (iChangeclipping) /* clipping changed ? */
+ {
+ pData->bFrameclipping = MNG_TRUE;
+
+ if (!iCliptype) /* absolute ? */
+ {
+ pData->iFrameclipl = iClipl;
+ pData->iFrameclipr = iClipr;
+ pData->iFrameclipt = iClipt;
+ pData->iFrameclipb = iClipb;
+ }
+ else /* relative */
+ {
+ pData->iFrameclipl = pData->iFrameclipl + iClipl;
+ pData->iFrameclipr = pData->iFrameclipr + iClipr;
+ pData->iFrameclipt = pData->iFrameclipt + iClipt;
+ pData->iFrameclipb = pData->iFrameclipb + iClipb;
+ }
+
+ if (iChangeclipping == 2) /* also overall ? */
+ {
+ pData->bFRAMclipping = MNG_TRUE;
+
+ if (!iCliptype) /* absolute ? */
+ {
+ pData->iFRAMclipl = iClipl;
+ pData->iFRAMclipr = iClipr;
+ pData->iFRAMclipt = iClipt;
+ pData->iFRAMclipb = iClipb;
+ }
+ else /* relative */
+ {
+ pData->iFRAMclipl = pData->iFRAMclipl + iClipl;
+ pData->iFRAMclipr = pData->iFRAMclipr + iClipr;
+ pData->iFRAMclipt = pData->iFRAMclipt + iClipt;
+ pData->iFRAMclipb = pData->iFRAMclipb + iClipb;
+ }
+ }
+ }
+ else
+ { /* reload defaults */
+ pData->bFrameclipping = pData->bFRAMclipping;
+ pData->iFrameclipl = pData->iFRAMclipl;
+ pData->iFrameclipr = pData->iFRAMclipr;
+ pData->iFrameclipt = pData->iFRAMclipt;
+ pData->iFrameclipb = pData->iFRAMclipb;
+ }
+#endif
+ }
+
+ if (!pData->bTimerset) /* timer still off ? */
+ {
+ if (
+#ifndef MNG_SKIPCHUNK_FRAM
+ (pData->iFramemode == 4) || /* insert background layer after a new frame */
+#endif
+ (!pData->iLayerseq)) /* and certainly before the very first layer */
+ iRetcode = load_bkgdlayer (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->iFrameseq++; /* count the frame ! */
+ pData->bFramedone = MNG_TRUE; /* and indicate we've done one */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_FRAME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode next_layer (mng_datap pData)
+{
+ mng_imagep pImage;
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_START);
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (!pData->iBreakpoint) /* no previous break here ? */
+ { /* interframe delay required ? */
+ if ((pData->eImagetype == mng_it_mng) && (pData->iLayerseq) &&
+ ((pData->iFramemode == 1) || (pData->iFramemode == 3)))
+ iRetcode = interframe_delay (pData);
+ else
+ pData->iFramedelay = pData->iNextdelay;
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+
+ if (!pData->bTimerset) /* timer still off ? */
+ {
+ if (!pData->iLayerseq) /* restore background for the very first layer ? */
+ { /* wait till IDAT/JDAT for PNGs & JNGs !!! */
+ if ((pData->eImagetype == mng_it_png) || (pData->eImagetype == mng_it_jng))
+ pData->bRestorebkgd = MNG_TRUE;
+ else
+ { /* for MNG we do it right away */
+ iRetcode = load_bkgdlayer (pData);
+ pData->iLayerseq++; /* and it counts as a layer then ! */
+ }
+ }
+#ifndef MNG_SKIPCHUNK_FRAM
+ else
+ if (pData->iFramemode == 3) /* restore background for each layer ? */
+ iRetcode = load_bkgdlayer (pData);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing a delta-image ? */
+ pImage = (mng_imagep)pData->pDeltaImage;
+ else
+#endif
+ pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* not an active object ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* determine display rectangle */
+ pData->iDestl = MAX_COORD ((mng_int32)0, pImage->iPosx);
+ pData->iDestt = MAX_COORD ((mng_int32)0, pImage->iPosy);
+ /* is it a valid buffer ? */
+ if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight))
+ {
+ pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth,
+ pImage->iPosx + (mng_int32)pImage->pImgbuf->iWidth );
+ pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight,
+ pImage->iPosy + (mng_int32)pImage->pImgbuf->iHeight);
+ }
+ else /* it's a single image ! */
+ {
+ pData->iDestr = MIN_COORD ((mng_int32)pData->iWidth,
+ (mng_int32)pData->iDatawidth );
+ pData->iDestb = MIN_COORD ((mng_int32)pData->iHeight,
+ (mng_int32)pData->iDataheight);
+ }
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pData->bFrameclipping) /* frame clipping specified ? */
+ {
+ pData->iDestl = MAX_COORD (pData->iDestl, pData->iFrameclipl);
+ pData->iDestt = MAX_COORD (pData->iDestt, pData->iFrameclipt);
+ pData->iDestr = MIN_COORD (pData->iDestr, pData->iFrameclipr);
+ pData->iDestb = MIN_COORD (pData->iDestb, pData->iFrameclipb);
+ }
+#endif
+
+ if (pImage->bClipped) /* is the image clipped itself ? */
+ {
+ pData->iDestl = MAX_COORD (pData->iDestl, pImage->iClipl);
+ pData->iDestt = MAX_COORD (pData->iDestt, pImage->iClipt);
+ pData->iDestr = MIN_COORD (pData->iDestr, pImage->iClipr);
+ pData->iDestb = MIN_COORD (pData->iDestb, pImage->iClipb);
+ }
+ /* determine source starting point */
+ pData->iSourcel = MAX_COORD ((mng_int32)0, pData->iDestl - pImage->iPosx);
+ pData->iSourcet = MAX_COORD ((mng_int32)0, pData->iDestt - pImage->iPosy);
+
+ if ((pImage->pImgbuf->iWidth) && (pImage->pImgbuf->iHeight))
+ { /* and maximum size */
+ pData->iSourcer = MIN_COORD ((mng_int32)pImage->pImgbuf->iWidth,
+ pData->iSourcel + pData->iDestr - pData->iDestl);
+ pData->iSourceb = MIN_COORD ((mng_int32)pImage->pImgbuf->iHeight,
+ pData->iSourcet + pData->iDestb - pData->iDestt);
+ }
+ else /* it's a single image ! */
+ {
+ pData->iSourcer = pData->iSourcel + pData->iDestr - pData->iDestl;
+ pData->iSourceb = pData->iSourcet + pData->iDestb - pData->iDestt;
+ }
+
+ pData->iLayerseq++; /* count the layer ! */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_LAYER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_display_image (mng_datap pData,
+ mng_imagep pImage,
+ mng_bool bLayeradvanced)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_IMAGE, MNG_LC_START);
+#endif
+ /* actively running ? */
+#ifndef MNG_SKIPCHUNK_MAGN
+ if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
+ {
+ if ( (!pData->iBreakpoint) && /* needs magnification ? */
+ ( (pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY) ) )
+ {
+ iRetcode = mng_magnify_imageobject (pData, pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+#endif
+
+ pData->pRetrieveobj = pImage; /* so retrieve-row and color-correction can find it */
+
+ if (!bLayeradvanced) /* need to advance the layer ? */
+ {
+ mng_imagep pSave = pData->pCurrentobj;
+ pData->pCurrentobj = pImage;
+ next_layer (pData); /* advance to next layer */
+ pData->pCurrentobj = pSave;
+ }
+ /* need to restore the background ? */
+ if ((!pData->bTimerset) && (pData->bRestorebkgd))
+ {
+ mng_imagep pSave = pData->pCurrentobj;
+ pData->pCurrentobj = pImage;
+ pData->bRestorebkgd = MNG_FALSE;
+ iRetcode = load_bkgdlayer (pData);
+ pData->pCurrentobj = pSave;
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->iLayerseq++; /* and it counts as a layer then ! */
+ }
+ /* actively running ? */
+ if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
+ {
+ if (!pData->bTimerset) /* all systems still go ? */
+ {
+ pData->iBreakpoint = 0; /* let's make absolutely sure... */
+ /* anything to display ? */
+ if ((pData->iDestr >= pData->iDestl) && (pData->iDestb >= pData->iDestt))
+ {
+ mng_int32 iY;
+
+ set_display_routine (pData); /* determine display routine */
+ /* and image-buffer retrieval routine */
+ switch (pImage->pImgbuf->iColortype)
+ {
+ case 0 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+ case 2 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+
+ case 3 : { pData->fRetrieverow = (mng_fptr)mng_retrieve_idx8;
+ pData->bIsOpaque = (mng_bool)(!pImage->pImgbuf->bHasTRNS);
+ break;
+ }
+
+
+ case 4 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+
+ case 6 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+ case 10 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+
+ case 12 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+
+ case 14 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ }
+
+ pData->iPass = -1; /* these are the object's dimensions now */
+ pData->iRow = pData->iSourcet;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pImage->pImgbuf->iWidth;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->bIsRGBA16 = MNG_FALSE;
+ /* adjust for 16-bit object ? */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pImage->pImgbuf->iBitdepth > 8)
+ {
+ pData->bIsRGBA16 = MNG_TRUE;
+ pData->iRowsize = pData->iRowsamples << 3;
+ }
+#endif
+
+ pData->fCorrectrow = MNG_NULL; /* default no color-correction */
+
+#ifdef MNG_NO_CMS
+ iRetcode = MNG_NOERROR;
+#else
+#if defined(MNG_FULL_CMS) /* determine color-management routine */
+ iRetcode = mng_init_full_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_GAMMA_ONLY)
+ iRetcode = mng_init_gamma_only (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_APP_CMS)
+ iRetcode = mng_init_app_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#endif
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_NO_CMS */
+ /* get a temporary row-buffer */
+ MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
+
+ iY = pData->iSourcet; /* this is where we start */
+
+ while ((!iRetcode) && (iY < pData->iSourceb))
+ { /* get a row */
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+ /* color correction ? */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* so... display it */
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode) /* adjust variables for next row */
+ iRetcode = mng_next_row (pData);
+
+ iY++; /* and next line */
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREE (pData, pData->pRGBArow, pData->iRowsize);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#if defined(MNG_FULL_CMS) /* cleanup cms stuff */
+ iRetcode = mng_clear_cms (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_IMAGE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* whehehe, this is good ! */
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_execute_delta_image (mng_datap pData,
+ mng_imagep pTarget,
+ mng_imagep pDelta)
+{
+ mng_imagedatap pBuftarget = pTarget->pImgbuf;
+ mng_imagedatap pBufdelta = pDelta->pImgbuf;
+ mng_uint32 iY;
+ mng_retcode iRetcode;
+ mng_ptr pSaveRGBA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_EXECUTE_DELTA_IMAGE, MNG_LC_START);
+#endif
+ /* actively running ? */
+ if (((pData->bRunning) || (pData->bSearching)) && (!pData->bSkipping))
+ {
+ if (pBufdelta->bHasPLTE) /* palette in delta ? */
+ {
+ mng_uint32 iX;
+ /* new palette larger than old one ? */
+ if ((!pBuftarget->bHasPLTE) || (pBuftarget->iPLTEcount < pBufdelta->iPLTEcount))
+ pBuftarget->iPLTEcount = pBufdelta->iPLTEcount;
+ /* it's definitely got a PLTE now */
+ pBuftarget->bHasPLTE = MNG_TRUE;
+
+ for (iX = 0; iX < pBufdelta->iPLTEcount; iX++)
+ {
+ pBuftarget->aPLTEentries[iX].iRed = pBufdelta->aPLTEentries[iX].iRed;
+ pBuftarget->aPLTEentries[iX].iGreen = pBufdelta->aPLTEentries[iX].iGreen;
+ pBuftarget->aPLTEentries[iX].iBlue = pBufdelta->aPLTEentries[iX].iBlue;
+ }
+ }
+
+ if (pBufdelta->bHasTRNS) /* cheap transparency in delta ? */
+ {
+ switch (pData->iColortype) /* drop it into the target */
+ {
+ case 0: { /* gray */
+ pBuftarget->iTRNSgray = pBufdelta->iTRNSgray;
+ pBuftarget->iTRNSred = 0;
+ pBuftarget->iTRNSgreen = 0;
+ pBuftarget->iTRNSblue = 0;
+ pBuftarget->iTRNScount = 0;
+ break;
+ }
+ case 2: { /* rgb */
+ pBuftarget->iTRNSgray = 0;
+ pBuftarget->iTRNSred = pBufdelta->iTRNSred;
+ pBuftarget->iTRNSgreen = pBufdelta->iTRNSgreen;
+ pBuftarget->iTRNSblue = pBufdelta->iTRNSblue;
+ pBuftarget->iTRNScount = 0;
+ break;
+ }
+ case 3: { /* indexed */
+ pBuftarget->iTRNSgray = 0;
+ pBuftarget->iTRNSred = 0;
+ pBuftarget->iTRNSgreen = 0;
+ pBuftarget->iTRNSblue = 0;
+ /* existing range smaller than new one ? */
+ if ((!pBuftarget->bHasTRNS) || (pBuftarget->iTRNScount < pBufdelta->iTRNScount))
+ pBuftarget->iTRNScount = pBufdelta->iTRNScount;
+
+ MNG_COPY (pBuftarget->aTRNSentries, pBufdelta->aTRNSentries, pBufdelta->iTRNScount);
+ break;
+ }
+ }
+
+ pBuftarget->bHasTRNS = MNG_TRUE; /* tell it it's got a tRNS now */
+ }
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ if (pBufdelta->bHasBKGD) /* bkgd in source ? */
+ { /* drop it onto the target */
+ pBuftarget->bHasBKGD = MNG_TRUE;
+ pBuftarget->iBKGDindex = pBufdelta->iBKGDindex;
+ pBuftarget->iBKGDgray = pBufdelta->iBKGDgray;
+ pBuftarget->iBKGDred = pBufdelta->iBKGDred;
+ pBuftarget->iBKGDgreen = pBufdelta->iBKGDgreen;
+ pBuftarget->iBKGDblue = pBufdelta->iBKGDblue;
+ }
+#endif
+
+ if (pBufdelta->bHasGAMA) /* gamma in source ? */
+ {
+ pBuftarget->bHasGAMA = MNG_TRUE; /* drop it onto the target */
+ pBuftarget->iGamma = pBufdelta->iGamma;
+ }
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ if (pBufdelta->bHasCHRM) /* chroma in delta ? */
+ { /* drop it onto the target */
+ pBuftarget->bHasCHRM = MNG_TRUE;
+ pBuftarget->iWhitepointx = pBufdelta->iWhitepointx;
+ pBuftarget->iWhitepointy = pBufdelta->iWhitepointy;
+ pBuftarget->iPrimaryredx = pBufdelta->iPrimaryredx;
+ pBuftarget->iPrimaryredy = pBufdelta->iPrimaryredy;
+ pBuftarget->iPrimarygreenx = pBufdelta->iPrimarygreenx;
+ pBuftarget->iPrimarygreeny = pBufdelta->iPrimarygreeny;
+ pBuftarget->iPrimarybluex = pBufdelta->iPrimarybluex;
+ pBuftarget->iPrimarybluey = pBufdelta->iPrimarybluey;
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_sRGB
+ if (pBufdelta->bHasSRGB) /* sRGB in delta ? */
+ { /* drop it onto the target */
+ pBuftarget->bHasSRGB = MNG_TRUE;
+ pBuftarget->iRenderingintent = pBufdelta->iRenderingintent;
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBufdelta->bHasICCP) /* ICC profile in delta ? */
+ {
+ pBuftarget->bHasICCP = MNG_TRUE; /* drop it onto the target */
+
+ if (pBuftarget->pProfile) /* profile existed ? */
+ MNG_FREEX (pData, pBuftarget->pProfile, pBuftarget->iProfilesize);
+ /* allocate a buffer & copy it */
+ MNG_ALLOC (pData, pBuftarget->pProfile, pBufdelta->iProfilesize);
+ MNG_COPY (pBuftarget->pProfile, pBufdelta->pProfile, pBufdelta->iProfilesize);
+ /* store its length as well */
+ pBuftarget->iProfilesize = pBufdelta->iProfilesize;
+ }
+#endif
+ /* need to execute delta pixels ? */
+ if ((!pData->bDeltaimmediate) && (pData->iDeltatype != MNG_DELTATYPE_NOCHANGE))
+ {
+ pData->fScalerow = MNG_NULL; /* not needed by default */
+
+ switch (pBufdelta->iBitdepth) /* determine scaling routine */
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 2 : { pData->fScalerow = (mng_fptr)mng_scale_g1_g2; break; }
+ case 4 : { pData->fScalerow = (mng_fptr)mng_scale_g1_g4; break; }
+
+ case 8 : { pData->fScalerow = (mng_fptr)mng_scale_g1_g8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fScalerow = (mng_fptr)mng_scale_g1_g16; break; }
+#endif
+ }
+ break;
+ }
+
+ case 2 : {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 1 : { pData->fScalerow = (mng_fptr)mng_scale_g2_g1; break; }
+ case 4 : { pData->fScalerow = (mng_fptr)mng_scale_g2_g4; break; }
+ case 8 : { pData->fScalerow = (mng_fptr)mng_scale_g2_g8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fScalerow = (mng_fptr)mng_scale_g2_g16; break; }
+#endif
+ }
+ break;
+ }
+
+ case 4 : {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 1 : { pData->fScalerow = (mng_fptr)mng_scale_g4_g1; break; }
+ case 2 : { pData->fScalerow = (mng_fptr)mng_scale_g4_g2; break; }
+ case 8 : { pData->fScalerow = (mng_fptr)mng_scale_g4_g8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fScalerow = (mng_fptr)mng_scale_g4_g16; break; }
+#endif
+ }
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+ case 8 : {
+ switch (pBufdelta->iColortype)
+ {
+ case 0 : ;
+ case 3 : ;
+ case 8 : {
+ switch (pBuftarget->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fScalerow = (mng_fptr)mng_scale_g8_g1; break; }
+ case 2 : { pData->fScalerow = (mng_fptr)mng_scale_g8_g2; break; }
+ case 4 : { pData->fScalerow = (mng_fptr)mng_scale_g8_g4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fScalerow = (mng_fptr)mng_scale_g8_g16; break; }
+#endif
+ }
+ break;
+ }
+ case 2 : ;
+ case 10 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuftarget->iBitdepth == 16)
+ pData->fScalerow = (mng_fptr)mng_scale_rgb8_rgb16;
+#endif
+ break;
+ }
+ case 4 : ;
+ case 12 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuftarget->iBitdepth == 16)
+ pData->fScalerow = (mng_fptr)mng_scale_ga8_ga16;
+#endif
+ break;
+ }
+ case 6 : ;
+ case 14 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuftarget->iBitdepth == 16)
+ pData->fScalerow = (mng_fptr)mng_scale_rgba8_rgba16;
+#endif
+ break;
+ }
+ }
+ break;
+ }
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ switch (pBufdelta->iColortype)
+ {
+ case 0 : ;
+ case 3 : ;
+ case 8 : {
+ switch (pBuftarget->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fScalerow = (mng_fptr)mng_scale_g16_g1; break; }
+ case 2 : { pData->fScalerow = (mng_fptr)mng_scale_g16_g2; break; }
+ case 4 : { pData->fScalerow = (mng_fptr)mng_scale_g16_g4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->fScalerow = (mng_fptr)mng_scale_g16_g8; break; }
+ }
+ break;
+ }
+ case 2 : ;
+ case 10 : {
+ if (pBuftarget->iBitdepth == 8)
+ pData->fScalerow = (mng_fptr)mng_scale_rgb16_rgb8;
+ break;
+ }
+ case 4 : ;
+ case 12 : {
+ if (pBuftarget->iBitdepth == 8)
+ pData->fScalerow = (mng_fptr)mng_scale_ga16_ga8;
+ break;
+ }
+ case 6 : ;
+ case 14 : {
+ if (pBuftarget->iBitdepth == 8)
+ pData->fScalerow = (mng_fptr)mng_scale_rgba16_rgba8;
+ break;
+ }
+ }
+ break;
+ }
+#endif
+
+ }
+
+ pData->fDeltarow = MNG_NULL; /* let's assume there's nothing to do */
+
+ switch (pBuftarget->iColortype) /* determine delta processing routine */
+ {
+ case 0 : ;
+ case 8 : { /* gray */
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3) ||
+ (pBufdelta->iColortype == 8))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fDeltarow = (mng_fptr)mng_delta_g1_g1; break; }
+ case 2 : { pData->fDeltarow = (mng_fptr)mng_delta_g2_g2; break; }
+ case 4 : { pData->fDeltarow = (mng_fptr)mng_delta_g4_g4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_g8_g8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_g16_g16; break; }
+#endif
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 2 : ;
+ case 10 : { /* rgb */
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 2) || (pBufdelta->iColortype == 10))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_rgb8_rgb8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_rgb16_rgb16; break; }
+#endif
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 3 : { /* indexed; abuse gray routines */
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fDeltarow = (mng_fptr)mng_delta_g1_g1; break; }
+ case 2 : { pData->fDeltarow = (mng_fptr)mng_delta_g2_g2; break; }
+ case 4 : { pData->fDeltarow = (mng_fptr)mng_delta_g4_g4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_g8_g8; break; }
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 4 : ;
+ case 12 : { /* gray + alpha */
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 4) || (pBufdelta->iColortype == 12))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_ga8_ga8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_ga16_ga16; break; }
+#endif
+ }
+ }
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3) ||
+ (pBufdelta->iColortype == 8))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_ga8_g8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_ga16_g16; break; }
+#endif
+ }
+ }
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_ga8_a8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_ga16_a16; break; }
+#endif
+ }
+ }
+ }
+
+ break;
+ }
+
+ case 6 : ;
+ case 14 : { /* rgb + alpha */
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 6) || (pBufdelta->iColortype == 14))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba8_rgba8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba16_rgba16; break; }
+#endif
+ }
+ }
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 2) || (pBufdelta->iColortype == 10))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba8_rgb8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba16_rgb16; break; }
+#endif
+ }
+ }
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ {
+ if ((pBufdelta->iColortype == 0) || (pBufdelta->iColortype == 3))
+ {
+ switch (pBuftarget->iBitdepth)
+ {
+ case 8 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba8_a8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fDeltarow = (mng_fptr)mng_delta_rgba16_a16; break; }
+#endif
+ }
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ if (pData->fDeltarow) /* do we need to take action ? */
+ {
+ pData->iPass = -1; /* setup row dimensions and stuff */
+ pData->iRow = pData->iDeltaBlocky;
+ pData->iRowinc = 1;
+ pData->iCol = pData->iDeltaBlockx;
+ pData->iColinc = 1;
+ pData->iRowsamples = pBufdelta->iWidth;
+ pData->iRowsize = pBuftarget->iRowsize;
+ /* indicate where to retrieve & where to store */
+ pData->pRetrieveobj = (mng_objectp)pDelta;
+ pData->pStoreobj = (mng_objectp)pTarget;
+
+ pSaveRGBA = pData->pRGBArow; /* save current temp-buffer! */
+ /* get a temporary row-buffer */
+ MNG_ALLOC (pData, pData->pRGBArow, (pBufdelta->iRowsize << 1));
+
+ iY = 0; /* this is where we start */
+ iRetcode = MNG_NOERROR; /* still oke for now */
+
+ while ((!iRetcode) && (iY < pBufdelta->iHeight))
+ { /* get a row */
+ mng_uint8p pWork = pBufdelta->pImgdata + (iY * pBufdelta->iRowsize);
+
+ MNG_COPY (pData->pRGBArow, pWork, pBufdelta->iRowsize);
+
+ if (pData->fScalerow) /* scale it (if necessary) */
+ iRetcode = ((mng_scalerow)pData->fScalerow) (pData);
+
+ if (!iRetcode) /* and... execute it */
+ iRetcode = ((mng_deltarow)pData->fDeltarow) (pData);
+
+ if (!iRetcode) /* adjust variables for next row */
+ iRetcode = mng_next_row (pData);
+
+ iY++; /* and next line */
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREE (pData, pData->pRGBArow, (pBufdelta->iRowsize << 1));
+ pData->pRGBArow = pSaveRGBA; /* restore saved temp-buffer! */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+ else
+ MNG_ERROR (pData, MNG_INVALIDDELTA);
+
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_EXECUTE_DELTA_IMAGE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_LOCAL mng_retcode save_state (mng_datap pData)
+{
+ mng_savedatap pSave;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SAVE_STATE, MNG_LC_START);
+#endif
+
+ if (pData->pSavedata) /* sanity check */
+ MNG_ERROR (pData, MNG_INTERNALERROR);
+ /* get a buffer for saving */
+ MNG_ALLOC (pData, pData->pSavedata, sizeof (mng_savedata));
+
+ pSave = pData->pSavedata; /* address it more directly */
+ /* and copy global data from the main struct */
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ pSave->bHasglobalPLTE = pData->bHasglobalPLTE;
+ pSave->bHasglobalTRNS = pData->bHasglobalTRNS;
+ pSave->bHasglobalGAMA = pData->bHasglobalGAMA;
+ pSave->bHasglobalCHRM = pData->bHasglobalCHRM;
+ pSave->bHasglobalSRGB = pData->bHasglobalSRGB;
+ pSave->bHasglobalICCP = pData->bHasglobalICCP;
+ pSave->bHasglobalBKGD = pData->bHasglobalBKGD;
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifndef MNG_SKIPCHUNK_BACK
+ pSave->iBACKred = pData->iBACKred;
+ pSave->iBACKgreen = pData->iBACKgreen;
+ pSave->iBACKblue = pData->iBACKblue;
+ pSave->iBACKmandatory = pData->iBACKmandatory;
+ pSave->iBACKimageid = pData->iBACKimageid;
+ pSave->iBACKtile = pData->iBACKtile;
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pSave->iFRAMmode = pData->iFRAMmode;
+ pSave->iFRAMdelay = pData->iFRAMdelay;
+ pSave->iFRAMtimeout = pData->iFRAMtimeout;
+ pSave->bFRAMclipping = pData->bFRAMclipping;
+ pSave->iFRAMclipl = pData->iFRAMclipl;
+ pSave->iFRAMclipr = pData->iFRAMclipr;
+ pSave->iFRAMclipt = pData->iFRAMclipt;
+ pSave->iFRAMclipb = pData->iFRAMclipb;
+#endif
+
+ pSave->iGlobalPLTEcount = pData->iGlobalPLTEcount;
+
+ MNG_COPY (pSave->aGlobalPLTEentries, pData->aGlobalPLTEentries, sizeof (mng_rgbpaltab));
+
+ pSave->iGlobalTRNSrawlen = pData->iGlobalTRNSrawlen;
+ MNG_COPY (pSave->aGlobalTRNSrawdata, pData->aGlobalTRNSrawdata, 256);
+
+ pSave->iGlobalGamma = pData->iGlobalGamma;
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ pSave->iGlobalWhitepointx = pData->iGlobalWhitepointx;
+ pSave->iGlobalWhitepointy = pData->iGlobalWhitepointy;
+ pSave->iGlobalPrimaryredx = pData->iGlobalPrimaryredx;
+ pSave->iGlobalPrimaryredy = pData->iGlobalPrimaryredy;
+ pSave->iGlobalPrimarygreenx = pData->iGlobalPrimarygreenx;
+ pSave->iGlobalPrimarygreeny = pData->iGlobalPrimarygreeny;
+ pSave->iGlobalPrimarybluex = pData->iGlobalPrimarybluex;
+ pSave->iGlobalPrimarybluey = pData->iGlobalPrimarybluey;
+#endif
+
+#ifndef MNG_SKIPCHUNK_sRGB
+ pSave->iGlobalRendintent = pData->iGlobalRendintent;
+#endif
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ pSave->iGlobalProfilesize = pData->iGlobalProfilesize;
+
+ if (pSave->iGlobalProfilesize) /* has a profile ? */
+ { /* then copy that ! */
+ MNG_ALLOC (pData, pSave->pGlobalProfile, pSave->iGlobalProfilesize);
+ MNG_COPY (pSave->pGlobalProfile, pData->pGlobalProfile, pSave->iGlobalProfilesize);
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ pSave->iGlobalBKGDred = pData->iGlobalBKGDred;
+ pSave->iGlobalBKGDgreen = pData->iGlobalBKGDgreen;
+ pSave->iGlobalBKGDblue = pData->iGlobalBKGDblue;
+#endif
+
+ /* freeze current image objects */
+ pImage = (mng_imagep)pData->pFirstimgobj;
+
+ while (pImage)
+ { /* freeze the object AND its buffer */
+ pImage->bFrozen = MNG_TRUE;
+ pImage->pImgbuf->bFrozen = MNG_TRUE;
+ /* neeeext */
+ pImage = (mng_imagep)pImage->sHeader.pNext;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SAVE_STATE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_reset_objzero (mng_datap pData)
+{
+ mng_imagep pImage = (mng_imagep)pData->pObjzero;
+ mng_retcode iRetcode = mng_reset_object_details (pData, pImage, 0, 0, 0,
+ 0, 0, 0, 0, MNG_TRUE);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pImage->bVisible = MNG_TRUE;
+ pImage->bViewable = MNG_TRUE;
+ pImage->iPosx = 0;
+ pImage->iPosy = 0;
+ pImage->bClipped = MNG_FALSE;
+ pImage->iClipl = 0;
+ pImage->iClipr = 0;
+ pImage->iClipt = 0;
+ pImage->iClipb = 0;
+#ifndef MNG_SKIPCHUNK_MAGN
+ pImage->iMAGN_MethodX = 0;
+ pImage->iMAGN_MethodY = 0;
+ pImage->iMAGN_MX = 0;
+ pImage->iMAGN_MY = 0;
+ pImage->iMAGN_ML = 0;
+ pImage->iMAGN_MR = 0;
+ pImage->iMAGN_MT = 0;
+ pImage->iMAGN_MB = 0;
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode restore_state (mng_datap pData)
+{
+#ifndef MNG_SKIPCHUNK_SAVE
+ mng_savedatap pSave;
+#endif
+ mng_imagep pImage;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_STATE, MNG_LC_START);
+#endif
+ /* restore object 0 status !!! */
+ iRetcode = mng_reset_objzero (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* fresh cycle; fake no frames done yet */
+ pData->bFramedone = MNG_FALSE;
+
+#ifndef MNG_SKIPCHUNK_SAVE
+ if (pData->pSavedata) /* do we have a saved state ? */
+ {
+ pSave = pData->pSavedata; /* address it more directly */
+ /* and copy it back to the main struct */
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ pData->bHasglobalPLTE = pSave->bHasglobalPLTE;
+ pData->bHasglobalTRNS = pSave->bHasglobalTRNS;
+ pData->bHasglobalGAMA = pSave->bHasglobalGAMA;
+ pData->bHasglobalCHRM = pSave->bHasglobalCHRM;
+ pData->bHasglobalSRGB = pSave->bHasglobalSRGB;
+ pData->bHasglobalICCP = pSave->bHasglobalICCP;
+ pData->bHasglobalBKGD = pSave->bHasglobalBKGD;
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifndef MNG_SKIPCHUNK_BACK
+ pData->iBACKred = pSave->iBACKred;
+ pData->iBACKgreen = pSave->iBACKgreen;
+ pData->iBACKblue = pSave->iBACKblue;
+ pData->iBACKmandatory = pSave->iBACKmandatory;
+ pData->iBACKimageid = pSave->iBACKimageid;
+ pData->iBACKtile = pSave->iBACKtile;
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pData->iFRAMmode = pSave->iFRAMmode;
+/* pData->iFRAMdelay = pSave->iFRAMdelay; */
+ pData->iFRAMtimeout = pSave->iFRAMtimeout;
+ pData->bFRAMclipping = pSave->bFRAMclipping;
+ pData->iFRAMclipl = pSave->iFRAMclipl;
+ pData->iFRAMclipr = pSave->iFRAMclipr;
+ pData->iFRAMclipt = pSave->iFRAMclipt;
+ pData->iFRAMclipb = pSave->iFRAMclipb;
+ /* NOOOOOOOOOOOO */
+/* pData->iFramemode = pSave->iFRAMmode;
+ pData->iFramedelay = pSave->iFRAMdelay;
+ pData->iFrametimeout = pSave->iFRAMtimeout;
+ pData->bFrameclipping = pSave->bFRAMclipping;
+ pData->iFrameclipl = pSave->iFRAMclipl;
+ pData->iFrameclipr = pSave->iFRAMclipr;
+ pData->iFrameclipt = pSave->iFRAMclipt;
+ pData->iFrameclipb = pSave->iFRAMclipb; */
+
+/* pData->iNextdelay = pSave->iFRAMdelay; */
+ pData->iNextdelay = pData->iFramedelay;
+#endif
+
+ pData->iGlobalPLTEcount = pSave->iGlobalPLTEcount;
+ MNG_COPY (pData->aGlobalPLTEentries, pSave->aGlobalPLTEentries, sizeof (mng_rgbpaltab));
+
+ pData->iGlobalTRNSrawlen = pSave->iGlobalTRNSrawlen;
+ MNG_COPY (pData->aGlobalTRNSrawdata, pSave->aGlobalTRNSrawdata, 256);
+
+ pData->iGlobalGamma = pSave->iGlobalGamma;
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ pData->iGlobalWhitepointx = pSave->iGlobalWhitepointx;
+ pData->iGlobalWhitepointy = pSave->iGlobalWhitepointy;
+ pData->iGlobalPrimaryredx = pSave->iGlobalPrimaryredx;
+ pData->iGlobalPrimaryredy = pSave->iGlobalPrimaryredy;
+ pData->iGlobalPrimarygreenx = pSave->iGlobalPrimarygreenx;
+ pData->iGlobalPrimarygreeny = pSave->iGlobalPrimarygreeny;
+ pData->iGlobalPrimarybluex = pSave->iGlobalPrimarybluex;
+ pData->iGlobalPrimarybluey = pSave->iGlobalPrimarybluey;
+#endif
+
+ pData->iGlobalRendintent = pSave->iGlobalRendintent;
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ pData->iGlobalProfilesize = pSave->iGlobalProfilesize;
+
+ if (pData->iGlobalProfilesize) /* has a profile ? */
+ { /* then copy that ! */
+ MNG_ALLOC (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+ MNG_COPY (pData->pGlobalProfile, pSave->pGlobalProfile, pData->iGlobalProfilesize);
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ pData->iGlobalBKGDred = pSave->iGlobalBKGDred;
+ pData->iGlobalBKGDgreen = pSave->iGlobalBKGDgreen;
+ pData->iGlobalBKGDblue = pSave->iGlobalBKGDblue;
+#endif
+ }
+ else /* no saved-data; so reset the lot */
+#endif /* SKIPCHUNK_SAVE */
+ {
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ pData->bHasglobalPLTE = MNG_FALSE;
+ pData->bHasglobalTRNS = MNG_FALSE;
+ pData->bHasglobalGAMA = MNG_FALSE;
+ pData->bHasglobalCHRM = MNG_FALSE;
+ pData->bHasglobalSRGB = MNG_FALSE;
+ pData->bHasglobalICCP = MNG_FALSE;
+ pData->bHasglobalBKGD = MNG_FALSE;
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifndef MNG_SKIPCHUNK_TERM
+ if (!pData->bMisplacedTERM) /* backward compatible ugliness !!! */
+ {
+ pData->iBACKred = 0;
+ pData->iBACKgreen = 0;
+ pData->iBACKblue = 0;
+ pData->iBACKmandatory = 0;
+ pData->iBACKimageid = 0;
+ pData->iBACKtile = 0;
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pData->iFRAMmode = 1;
+/* pData->iFRAMdelay = 1; */
+ pData->iFRAMtimeout = 0x7fffffffl;
+ pData->bFRAMclipping = MNG_FALSE;
+ pData->iFRAMclipl = 0;
+ pData->iFRAMclipr = 0;
+ pData->iFRAMclipt = 0;
+ pData->iFRAMclipb = 0;
+ /* NOOOOOOOOOOOO */
+/* pData->iFramemode = 1;
+ pData->iFramedelay = 1;
+ pData->iFrametimeout = 0x7fffffffl;
+ pData->bFrameclipping = MNG_FALSE;
+ pData->iFrameclipl = 0;
+ pData->iFrameclipr = 0;
+ pData->iFrameclipt = 0;
+ pData->iFrameclipb = 0; */
+
+/* pData->iNextdelay = 1; */
+ pData->iNextdelay = pData->iFramedelay;
+#endif
+
+ pData->iGlobalPLTEcount = 0;
+
+ pData->iGlobalTRNSrawlen = 0;
+
+ pData->iGlobalGamma = 0;
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ pData->iGlobalWhitepointx = 0;
+ pData->iGlobalWhitepointy = 0;
+ pData->iGlobalPrimaryredx = 0;
+ pData->iGlobalPrimaryredy = 0;
+ pData->iGlobalPrimarygreenx = 0;
+ pData->iGlobalPrimarygreeny = 0;
+ pData->iGlobalPrimarybluex = 0;
+ pData->iGlobalPrimarybluey = 0;
+#endif
+
+ pData->iGlobalRendintent = 0;
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pData->iGlobalProfilesize) /* free a previous profile ? */
+ MNG_FREE (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ pData->iGlobalProfilesize = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ pData->iGlobalBKGDred = 0;
+ pData->iGlobalBKGDgreen = 0;
+ pData->iGlobalBKGDblue = 0;
+#endif
+ }
+
+#ifndef MNG_SKIPCHUNK_TERM
+ if (!pData->bMisplacedTERM) /* backward compatible ugliness !!! */
+ {
+ pImage = (mng_imagep)pData->pFirstimgobj;
+ /* drop un-frozen image objects */
+ while (pImage)
+ {
+ mng_imagep pNext = (mng_imagep)pImage->sHeader.pNext;
+
+ if (!pImage->bFrozen) /* is it un-frozen ? */
+ {
+ mng_imagep pPrev = (mng_imagep)pImage->sHeader.pPrev;
+
+ if (pPrev) /* unlink it */
+ pPrev->sHeader.pNext = pNext;
+ else
+ pData->pFirstimgobj = pNext;
+
+ if (pNext)
+ pNext->sHeader.pPrev = pPrev;
+ else
+ pData->pLastimgobj = pPrev;
+
+ if (pImage->pImgbuf->bFrozen) /* buffer frozen ? */
+ {
+ if (pImage->pImgbuf->iRefcount < 2)
+ MNG_ERROR (pData, MNG_INTERNALERROR);
+ /* decrease ref counter */
+ pImage->pImgbuf->iRefcount--;
+ /* just cleanup the object then */
+ MNG_FREEX (pData, pImage, sizeof (mng_image));
+ }
+ else
+ { /* free the image buffer */
+ iRetcode = mng_free_imagedataobject (pData, pImage->pImgbuf);
+ /* and cleanup the object */
+ MNG_FREEX (pData, pImage, sizeof (mng_image));
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+
+ pImage = pNext; /* neeeext */
+ }
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_STATE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * General display processing routine * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_process_display (mng_datap pData)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY, MNG_LC_START);
+#endif
+
+ if (!pData->iBreakpoint) /* not broken previously ? */
+ {
+ if ((pData->iRequestframe) || (pData->iRequestlayer) || (pData->iRequesttime))
+ {
+ pData->bSearching = MNG_TRUE; /* indicate we're searching */
+
+ iRetcode = clear_canvas (pData); /* make the canvas virgin black ?!? */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* let's start from the top, shall we */
+ pData->pCurraniobj = pData->pFirstaniobj;
+ }
+ }
+
+ do /* process the objects */
+ {
+ if (pData->bSearching) /* clear timer-flag when searching !!! */
+ pData->bTimerset = MNG_FALSE;
+ /* do we need to finish something first ? */
+ if ((pData->iBreakpoint) && (pData->iBreakpoint < 99))
+ {
+ switch (pData->iBreakpoint) /* return to broken display routine */
+ {
+#ifndef MNG_SKIPCHUNK_FRAM
+ case 1 : { iRetcode = mng_process_display_fram2 (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_SHOW
+ case 3 : ; /* same as 4 !!! */
+ case 4 : { iRetcode = mng_process_display_show (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ case 5 : { iRetcode = mng_process_display_clon2 (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+ case 9 : { iRetcode = mng_process_display_magn2 (pData); break; }
+ case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
+#endif
+ default : MNG_ERROR (pData, MNG_INTERNALERROR);
+ }
+ }
+ else
+ {
+ if (pData->pCurraniobj)
+ iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
+ }
+
+ if (!pData->bTimerset) /* reset breakpoint flag ? */
+ pData->iBreakpoint = 0;
+ /* can we advance to next object ? */
+ if ((!iRetcode) && (pData->pCurraniobj) &&
+ (!pData->bTimerset) && (!pData->bSectionwait))
+ {
+ pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
+ /* MEND processing to be done ? */
+ if ((pData->eImagetype == mng_it_mng) && (!pData->pCurraniobj))
+ iRetcode = mng_process_display_mend (pData);
+
+ if (!pData->pCurraniobj) /* refresh after last image ? */
+ pData->bNeedrefresh = MNG_TRUE;
+ }
+
+ if (pData->bSearching) /* are we looking for something ? */
+ {
+ if ((pData->iRequestframe) && (pData->iRequestframe <= pData->iFrameseq))
+ {
+ pData->iRequestframe = 0; /* found the frame ! */
+ pData->bSearching = MNG_FALSE;
+ }
+ else
+ if ((pData->iRequestlayer) && (pData->iRequestlayer <= pData->iLayerseq))
+ {
+ pData->iRequestlayer = 0; /* found the layer ! */
+ pData->bSearching = MNG_FALSE;
+ }
+ else
+ if ((pData->iRequesttime) && (pData->iRequesttime <= pData->iFrametime))
+ {
+ pData->iRequesttime = 0; /* found the playtime ! */
+ pData->bSearching = MNG_FALSE;
+ }
+ }
+ } /* until error or a break or no more objects */
+ while ((!iRetcode) && (pData->pCurraniobj) &&
+ (((pData->bRunning) && (!pData->bTimerset)) || (pData->bSearching)) &&
+ (!pData->bSectionwait) && (!pData->bFreezing));
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* refresh needed ? */
+ if ((!pData->bTimerset) && (pData->bNeedrefresh))
+ {
+ iRetcode = mng_display_progressive_refresh (pData, 1);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ /* timer break ? */
+ if ((pData->bTimerset) && (!pData->iBreakpoint))
+ pData->iBreakpoint = 99;
+ else
+ if (!pData->bTimerset)
+ pData->iBreakpoint = 0; /* reset if no timer break */
+
+ if ((!pData->bTimerset) && (!pData->pCurraniobj))
+ pData->bRunning = MNG_FALSE; /* all done now ! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Chunk display processing routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+png_imgtype mng_png_imgtype(mng_uint8 colortype, mng_uint8 bitdepth)
+{
+ png_imgtype ret;
+ switch (bitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1:
+ {
+ png_imgtype imgtype[]={png_g1,png_none,png_none,png_idx1};
+ ret=imgtype[colortype];
+ break;
+ }
+ case 2:
+ {
+ png_imgtype imgtype[]={png_g2,png_none,png_none,png_idx2};
+ ret=imgtype[colortype];
+ break;
+ }
+ case 4:
+ {
+ png_imgtype imgtype[]={png_g4,png_none,png_none,png_idx4};
+ ret=imgtype[colortype];
+ break;
+ }
+#endif
+ case 8:
+ {
+ png_imgtype imgtype[]={png_g8,png_none,png_rgb8,png_idx8,png_ga8,
+ png_none,png_rgba8};
+ ret=imgtype[colortype];
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16:
+ {
+ png_imgtype imgtype[]={png_g16,png_none,png_rgb16,png_none,png_ga16,
+ png_none,png_rgba16};
+ ret=imgtype[colortype];
+ break;
+ }
+#endif
+ default:
+ ret=png_none;
+ break;
+ }
+ return (ret);
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_ihdr (mng_datap pData)
+{ /* address the current "object" if any */
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IHDR, MNG_LC_START);
+#endif
+
+ if (!pData->bHasDHDR)
+ {
+ pData->fInitrowproc = MNG_NULL; /* do nothing by default */
+ pData->fDisplayrow = MNG_NULL;
+ pData->fCorrectrow = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ pData->fDifferrow = MNG_NULL;
+ pData->pStoreobj = MNG_NULL;
+ }
+
+ if (!pData->iBreakpoint) /* not previously broken ? */
+ {
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* is a delta-image ? */
+ {
+ if (pData->iDeltatype == MNG_DELTATYPE_REPLACE)
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pDeltaImage,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_TRUE);
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iBitdepth;
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iBitdepth;
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iBitdepth;
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iBitdepth;
+
+ if (!iRetcode)
+ { /* process immediately if bitdepth & colortype are equal */
+ pData->bDeltaimmediate =
+ (mng_bool)((pData->iBitdepth == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iBitdepth ) &&
+ (pData->iColortype == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iColortype) );
+ /* be sure to reset object 0 */
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pObjzero,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_TRUE);
+ }
+ }
+ else
+#endif
+ {
+ if (pImage) /* update object buffer ? */
+ iRetcode = mng_reset_object_details (pData, pImage,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_TRUE);
+ else
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pObjzero,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_TRUE);
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifndef MNG_NO_DELTA_PNG
+ if (!pData->bHasDHDR)
+#endif
+ {
+ if (pImage) /* real object ? */
+ pData->pStoreobj = pImage; /* tell the row routines */
+ else /* otherwise use object 0 */
+ pData->pStoreobj = pData->pObjzero;
+
+#if !defined(MNG_INCLUDE_MPNG_PROPOSAL) && !defined(MNG_INCLUDE_ANG_PROPOSAL)
+ if ( /* display "on-the-fly" ? */
+#ifndef MNG_SKIPCHUNK_MAGN
+ (((mng_imagep)pData->pStoreobj)->iMAGN_MethodX == 0) &&
+ (((mng_imagep)pData->pStoreobj)->iMAGN_MethodY == 0) &&
+#endif
+ ( (pData->eImagetype == mng_it_png ) ||
+ (((mng_imagep)pData->pStoreobj)->bVisible) ) )
+ {
+ next_layer (pData); /* that's a new layer then ! */
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 2;
+ else
+ {
+ pData->iBreakpoint = 0;
+ /* anything to display ? */
+ if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt))
+ set_display_routine (pData); /* then determine display routine */
+ }
+ }
+#endif
+ }
+
+ if (!pData->bTimerset) /* no timer break ? */
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+ pData->ePng_imgtype=mng_png_imgtype(pData->iColortype,pData->iBitdepth);
+#else
+ switch (pData->iColortype) /* determine row initialization routine */
+ {
+ case 0 : { /* gray */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_i;
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 2 : { /* rgb */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_i;
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 3 : { /* indexed */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_i;
+
+ break;
+ }
+ }
+
+ break;
+ }
+ case 4 : { /* gray+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_i;
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 6 : { /* rgb+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ }
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+ pData->iFilterofs = 0; /* determine filter characteristics */
+ pData->iLevel0 = 0; /* default levels */
+ pData->iLevel1 = 0;
+ pData->iLevel2 = 0;
+ pData->iLevel3 = 0;
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ {
+ switch (pData->iColortype)
+ {
+ case 0 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 1;
+ else
+ pData->iFilterofs = 2;
+
+ break;
+ }
+ case 2 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 3;
+ else
+ pData->iFilterofs = 6;
+
+ break;
+ }
+ case 3 : {
+ pData->iFilterofs = 1;
+ break;
+ }
+ case 4 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 2;
+ else
+ pData->iFilterofs = 4;
+
+ break;
+ }
+ case 6 : {
+ if (pData->iBitdepth <= 8)
+ pData->iFilterofs = 4;
+ else
+ pData->iFilterofs = 8;
+
+ break;
+ }
+ }
+ }
+#endif
+
+#ifdef FILTER193 /* no adaptive filtering ? */
+ if (pData->iFilter == MNG_FILTER_NOFILTER)
+ pData->iPixelofs = pData->iFilterofs;
+ else
+#endif
+ pData->iPixelofs = pData->iFilterofs + 1;
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+mng_retcode mng_process_display_mpng (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MPNG, MNG_LC_START);
+#endif
+
+ pData->iAlphadepth = 8; /* assume transparency !! */
+
+ if (pData->fProcessheader) /* inform the app (creating the output canvas) ? */
+ {
+ pData->iWidth = ((mng_mpng_objp)pData->pMPNG)->iFramewidth;
+ pData->iHeight = ((mng_mpng_objp)pData->pMPNG)->iFrameheight;
+
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ next_layer (pData); /* first mPNG layer then ! */
+ pData->bTimerset = MNG_FALSE;
+ pData->iBreakpoint = 0;
+
+ if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt))
+ set_display_routine (pData); /* then determine display routine */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+mng_retcode mng_process_display_ang (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_ANG, MNG_LC_START);
+#endif
+
+ if (pData->fProcessheader) /* inform the app (creating the output canvas) ? */
+ {
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+
+ next_layer (pData); /* first mPNG layer then ! */
+ pData->bTimerset = MNG_FALSE;
+ pData->iBreakpoint = 0;
+
+ if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt))
+ set_display_routine (pData); /* then determine display routine */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_ANG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_idat (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata)
+#else
+mng_retcode mng_process_display_idat (mng_datap pData)
+#endif
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IDAT, MNG_LC_START);
+#endif
+
+#if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
+ if ((pData->eImagetype == mng_it_png) && (pData->iLayerseq <= 0))
+ {
+ if (pData->fProcessheader) /* inform the app (creating the output canvas) ? */
+ if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ next_layer (pData); /* first regular PNG layer then ! */
+ pData->bTimerset = MNG_FALSE;
+ pData->iBreakpoint = 0;
+
+ if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt))
+ set_display_routine (pData); /* then determine display routine */
+ }
+#endif
+
+ if (pData->bRestorebkgd) /* need to restore the background ? */
+ {
+ pData->bRestorebkgd = MNG_FALSE;
+ iRetcode = load_bkgdlayer (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->iLayerseq++; /* and it counts as a layer then ! */
+ }
+
+ if (pData->fInitrowproc) /* need to initialize row processing? */
+ {
+ iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData);
+ pData->fInitrowproc = MNG_NULL; /* only call this once !!! */
+ }
+
+ if ((!iRetcode) && (!pData->bInflating))
+ /* initialize inflate */
+ iRetcode = mngzlib_inflateinit (pData);
+
+ if (!iRetcode) /* all ok? then inflate, my man */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mngzlib_inflaterows (pData, iRawlen, pRawdata);
+#else
+ iRetcode = mngzlib_inflaterows (pData, pData->iRawlen, pData->pRawdata);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_iend (mng_datap pData)
+{
+ mng_retcode iRetcode, iRetcode2;
+ mng_bool bDodisplay = MNG_FALSE;
+ mng_bool bMagnify = MNG_FALSE;
+ mng_bool bCleanup = (mng_bool)(pData->iBreakpoint != 0);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IEND, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_JNG /* progressive+alpha JNG can be displayed now */
+ if ( (pData->bHasJHDR ) &&
+ ( (pData->bJPEGprogressive) || (pData->bJPEGprogressive2)) &&
+ ( (pData->eImagetype == mng_it_jng ) ||
+ (((mng_imagep)pData->pStoreobj)->bVisible) ) &&
+ ( (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ) )
+ bDodisplay = MNG_TRUE;
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ if ( (pData->pStoreobj) && /* on-the-fly magnification ? */
+ ( (((mng_imagep)pData->pStoreobj)->iMAGN_MethodX) ||
+ (((mng_imagep)pData->pStoreobj)->iMAGN_MethodY) ) )
+ bMagnify = MNG_TRUE;
+#endif
+
+ if ((pData->bHasBASI) || /* was it a BASI stream */
+ (bDodisplay) || /* or should we display the JNG */
+#ifndef MNG_SKIPCHUNK_MAGN
+ (bMagnify) || /* or should we magnify it */
+#endif
+ /* or did we get broken here last time ? */
+ ((pData->iBreakpoint) && (pData->iBreakpoint != 8)))
+ {
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+
+ if (!pImage) /* or was it object 0 ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* display it now then ? */
+ if ((pImage->bVisible) && (pImage->bViewable))
+ { /* ok, so do it */
+ iRetcode = mng_display_image (pData, pImage, bDodisplay);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 6;
+ }
+ }
+#ifndef MNG_NO_DELTA_PNG
+ else
+ if ((pData->bHasDHDR) || /* was it a DHDR stream */
+ (pData->iBreakpoint == 8)) /* or did we get broken here last time ? */
+ {
+ mng_imagep pImage = (mng_imagep)pData->pDeltaImage;
+
+ if (!pData->iBreakpoint)
+ { /* perform the delta operations needed */
+ iRetcode = mng_execute_delta_image (pData, pImage, (mng_imagep)pData->pObjzero);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ /* display it now then ? */
+ if ((pImage->bVisible) && (pImage->bViewable))
+ { /* ok, so do it */
+ iRetcode = mng_display_image (pData, pImage, MNG_FALSE);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 8;
+ }
+ }
+#endif
+
+ if (!pData->bTimerset) /* can we continue ? */
+ {
+ pData->iBreakpoint = 0; /* clear this flag now ! */
+
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ if (pData->eImagetype == mng_it_mpng)
+ {
+ pData->pCurraniobj = pData->pFirstaniobj;
+ } else
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ if (pData->eImagetype == mng_it_ang)
+ {
+ pData->pCurraniobj = pData->pFirstaniobj;
+ } else
+#endif
+ { /* cleanup object 0 */
+ mng_reset_object_details (pData, (mng_imagep)pData->pObjzero,
+ 0, 0, 0, 0, 0, 0, 0, MNG_TRUE);
+ }
+
+ if (pData->bInflating) /* if we've been inflating */
+ { /* cleanup row-processing, */
+ iRetcode = mng_cleanup_rowproc (pData);
+ /* also cleanup inflate! */
+ iRetcode2 = mngzlib_inflatefree (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ if (iRetcode2)
+ return iRetcode2;
+ }
+
+#ifdef MNG_INCLUDE_JNG
+ if (pData->bJPEGdecompress) /* if we've been decompressing JDAT */
+ { /* cleanup row-processing, */
+ iRetcode = mng_cleanup_rowproc (pData);
+ /* also cleanup decompress! */
+ iRetcode2 = mngjpeg_decompressfree (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ if (iRetcode2)
+ return iRetcode2;
+ }
+
+ if (pData->bJPEGdecompress2) /* if we've been decompressing JDAA */
+ { /* cleanup row-processing, */
+ iRetcode = mng_cleanup_rowproc (pData);
+ /* also cleanup decompress! */
+ iRetcode2 = mngjpeg_decompressfree2 (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ if (iRetcode2)
+ return iRetcode2;
+ }
+#endif
+
+ if (bCleanup) /* if we got broken last time we need to cleanup */
+ {
+ pData->bHasIHDR = MNG_FALSE; /* IEND signals the end for most ... */
+ pData->bHasBASI = MNG_FALSE;
+ pData->bHasDHDR = MNG_FALSE;
+#ifdef MNG_INCLUDE_JNG
+ pData->bHasJHDR = MNG_FALSE;
+ pData->bHasJSEP = MNG_FALSE;
+ pData->bHasJDAA = MNG_FALSE;
+ pData->bHasJDAT = MNG_FALSE;
+#endif
+ pData->bHasPLTE = MNG_FALSE;
+ pData->bHasTRNS = MNG_FALSE;
+ pData->bHasGAMA = MNG_FALSE;
+ pData->bHasCHRM = MNG_FALSE;
+ pData->bHasSRGB = MNG_FALSE;
+ pData->bHasICCP = MNG_FALSE;
+ pData->bHasBKGD = MNG_FALSE;
+ pData->bHasIDAT = MNG_FALSE;
+ }
+ /* if the image was displayed on the fly, */
+ /* we'll have to make the app refresh */
+ if ((pData->eImagetype != mng_it_mng) && (pData->fDisplayrow))
+ pData->bNeedrefresh = MNG_TRUE;
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+/* change in the MNG spec with regards to TERM delay & interframe_delay
+ as proposed by Adam M. Costello (option 4) and finalized by official vote
+ during december 2002 / check the 'mng-list' archives for more details */
+
+mng_retcode mng_process_display_mend (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_START);
+#endif
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ if (pData->bStopafterseek) /* need to stop after this ? */
+ {
+ pData->bFreezing = MNG_TRUE; /* stop processing on this one */
+ pData->bRunningevent = MNG_FALSE;
+ pData->bStopafterseek = MNG_FALSE;
+ pData->bNeedrefresh = MNG_TRUE; /* make sure the last bit is displayed ! */
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_TERM
+ /* TERM processed ? */
+ if ((pData->bDisplaying) && (pData->bRunning) &&
+ (pData->bHasTERM) && (pData->pTermaniobj))
+ {
+ mng_retcode iRetcode;
+ mng_ani_termp pTERM;
+ /* get the right animation object ! */
+ pTERM = (mng_ani_termp)pData->pTermaniobj;
+
+ pData->iIterations++; /* increase iteration count */
+
+ switch (pTERM->iTermaction) /* determine what to do! */
+ {
+ case 0 : { /* show last frame indefinitly */
+ break; /* piece of cake, that is... */
+ }
+
+ case 1 : { /* cease displaying anything */
+ /* max(1, TERM delay, interframe_delay) */
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pTERM->iDelay > pData->iFramedelay)
+ pData->iFramedelay = pTERM->iDelay;
+ if (!pData->iFramedelay)
+ pData->iFramedelay = 1;
+#endif
+
+ iRetcode = interframe_delay (pData);
+ /* no interframe_delay? then fake it */
+ if ((!iRetcode) && (!pData->bTimerset))
+ iRetcode = set_delay (pData, 1);
+
+ if (iRetcode)
+ return iRetcode;
+
+ pData->iBreakpoint = 10;
+ break;
+ }
+
+ case 2 : { /* show first image after TERM */
+ iRetcode = restore_state (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* notify the app ? */
+ if (pData->fProcessmend)
+ if (!pData->fProcessmend ((mng_handle)pData, pData->iIterations, 0))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ /* show first frame after TERM chunk */
+ pData->pCurraniobj = pTERM;
+ pData->bOnlyfirstframe = MNG_TRUE;
+ pData->iFramesafterTERM = 0;
+
+ /* max(1, TERM delay, interframe_delay) */
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pTERM->iDelay > pData->iFramedelay)
+ pData->iFramedelay = pTERM->iDelay;
+ if (!pData->iFramedelay)
+ pData->iFramedelay = 1;
+#endif
+
+ break;
+ }
+
+ case 3 : { /* repeat */
+ if ((pTERM->iItermax) && (pTERM->iItermax < 0x7FFFFFFF))
+ pTERM->iItermax--;
+
+ if (pTERM->iItermax) /* go back to TERM ? */
+ { /* restore to initial or SAVE state */
+ iRetcode = restore_state (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* notify the app ? */
+ if (pData->fProcessmend)
+ if (!pData->fProcessmend ((mng_handle)pData,
+ pData->iIterations, pTERM->iItermax))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ /* restart from TERM chunk */
+ pData->pCurraniobj = pTERM;
+
+ if (pTERM->iDelay) /* set the delay (?) */
+ {
+ /* max(1, TERM delay, interframe_delay) */
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pTERM->iDelay > pData->iFramedelay)
+ pData->iFramedelay = pTERM->iDelay;
+ if (!pData->iFramedelay)
+ pData->iFramedelay = 1;
+#endif
+
+ pData->bNeedrefresh = MNG_TRUE;
+ }
+ }
+ else
+ {
+ switch (pTERM->iIteraction)
+ {
+ case 0 : { /* show last frame indefinitly */
+ break; /* piece of cake, that is... */
+ }
+
+ case 1 : { /* cease displaying anything */
+ /* max(1, TERM delay, interframe_delay) */
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pTERM->iDelay > pData->iFramedelay)
+ pData->iFramedelay = pTERM->iDelay;
+ if (!pData->iFramedelay)
+ pData->iFramedelay = 1;
+#endif
+
+ iRetcode = interframe_delay (pData);
+ /* no interframe_delay? then fake it */
+ if ((!iRetcode) && (!pData->bTimerset))
+ iRetcode = set_delay (pData, 1);
+
+ if (iRetcode)
+ return iRetcode;
+
+ pData->iBreakpoint = 10;
+ break;
+ }
+
+ case 2 : { /* show first image after TERM */
+ iRetcode = restore_state (pData);
+ /* on error bail out */
+ if (iRetcode)
+ return iRetcode;
+ /* notify the app ? */
+ if (pData->fProcessmend)
+ if (!pData->fProcessmend ((mng_handle)pData,
+ pData->iIterations, 0))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ /* show first frame after TERM chunk */
+ pData->pCurraniobj = pTERM;
+ pData->bOnlyfirstframe = MNG_TRUE;
+ pData->iFramesafterTERM = 0;
+ /* max(1, TERM delay, interframe_delay) */
+#ifndef MNG_SKIPCHUNK_FRAM
+ if (pTERM->iDelay > pData->iFramedelay)
+ pData->iFramedelay = pTERM->iDelay;
+ if (!pData->iFramedelay)
+ pData->iFramedelay = 1;
+#endif
+
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+ }
+ }
+#endif /* MNG_SKIPCHUNK_TERM */
+ /* just reading ? */
+ if ((!pData->bDisplaying) && (pData->bReading))
+ if (pData->fProcessmend) /* inform the app ? */
+ if (!pData->fProcessmend ((mng_handle)pData, 0, 0))
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+
+ if (!pData->pCurraniobj) /* always let the app refresh at the end ! */
+ pData->bNeedrefresh = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_mend2 (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_START);
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pData->bFrameclipping = MNG_FALSE; /* nothing to do but restore the app background */
+#endif
+ load_bkgdlayer (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MEND, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+mng_retcode mng_process_display_defi (mng_datap pData)
+{
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DEFI, MNG_LC_START);
+#endif
+
+ if (!pData->iDEFIobjectid) /* object id=0 ? */
+ {
+ pImage = (mng_imagep)pData->pObjzero;
+
+ if (pData->bDEFIhasdonotshow)
+ pImage->bVisible = (mng_bool)(pData->iDEFIdonotshow == 0);
+
+ if (pData->bDEFIhasloca)
+ {
+ pImage->iPosx = pData->iDEFIlocax;
+ pImage->iPosy = pData->iDEFIlocay;
+ }
+
+ if (pData->bDEFIhasclip)
+ {
+ pImage->bClipped = pData->bDEFIhasclip;
+ pImage->iClipl = pData->iDEFIclipl;
+ pImage->iClipr = pData->iDEFIclipr;
+ pImage->iClipt = pData->iDEFIclipt;
+ pImage->iClipb = pData->iDEFIclipb;
+ }
+
+ pData->pCurrentobj = 0; /* not a real object ! */
+ }
+ else
+ { /* already exists ? */
+ pImage = (mng_imagep)mng_find_imageobject (pData, pData->iDEFIobjectid);
+
+ if (!pImage) /* if not; create new */
+ {
+ mng_retcode iRetcode = mng_create_imageobject (pData, pData->iDEFIobjectid,
+ (mng_bool)(pData->iDEFIconcrete == 1),
+ (mng_bool)(pData->iDEFIdonotshow == 0),
+ MNG_FALSE, 0, 0, 0, 0, 0, 0, 0,
+ pData->iDEFIlocax, pData->iDEFIlocay,
+ pData->bDEFIhasclip,
+ pData->iDEFIclipl, pData->iDEFIclipr,
+ pData->iDEFIclipt, pData->iDEFIclipb,
+ &pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* exists; then set new info */
+ if (pData->bDEFIhasdonotshow)
+ pImage->bVisible = (mng_bool)(pData->iDEFIdonotshow == 0);
+
+ pImage->bViewable = MNG_FALSE;
+
+ if (pData->bDEFIhasloca)
+ {
+ pImage->iPosx = pData->iDEFIlocax;
+ pImage->iPosy = pData->iDEFIlocay;
+ }
+
+ if (pData->bDEFIhasclip)
+ {
+ pImage->bClipped = pData->bDEFIhasclip;
+ pImage->iClipl = pData->iDEFIclipl;
+ pImage->iClipr = pData->iDEFIclipr;
+ pImage->iClipt = pData->iDEFIclipt;
+ pImage->iClipb = pData->iDEFIclipb;
+ }
+
+ if (pData->bDEFIhasconcrete)
+ pImage->pImgbuf->bConcrete = (mng_bool)(pData->iDEFIconcrete == 1);
+ }
+
+ pData->pCurrentobj = pImage; /* others may want to know this */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_basi (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_bool bHasalpha,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable)
+#else
+mng_retcode mng_process_display_basi (mng_datap pData)
+#endif
+{ /* address the current "object" if any */
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_uint8p pWork;
+ mng_uint32 iX;
+ mng_imagedatap pBuf;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_BASI, MNG_LC_START);
+#endif
+
+ if (!pImage) /* or is it an "on-the-fly" image ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ /* address the object-buffer */
+ pBuf = pImage->pImgbuf;
+
+ pData->fDisplayrow = MNG_NULL; /* do nothing by default */
+ pData->fCorrectrow = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ /* set parms now that they're known */
+ iRetcode = mng_reset_object_details (pData, pImage, pData->iDatawidth,
+ pData->iDataheight, pData->iBitdepth,
+ pData->iColortype, pData->iCompression,
+ pData->iFilter, pData->iInterlace, MNG_FALSE);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* save the viewable flag */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->bViewable = (mng_bool)(iViewable == 1);
+#else
+ pImage->bViewable = (mng_bool)(pData->iBASIviewable == 1);
+#endif
+ pBuf->bViewable = pImage->bViewable;
+ pData->pStoreobj = pImage; /* let row-routines know which object */
+
+ pWork = pBuf->pImgdata; /* fill the object-buffer with the specified
+ "color" sample */
+ switch (pData->iColortype) /* depending on color_type & bit_depth */
+ {
+ case 0 : { /* gray */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth == 16)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_put_uint16 (pWork, iRed);
+#else
+ mng_put_uint16 (pWork, pData->iBASIred);
+#endif
+ pWork += 2;
+ }
+ }
+ else
+#endif
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ *pWork = (mng_uint8)iRed;
+#else
+ *pWork = (mng_uint8)pData->iBASIred;
+#endif
+ pWork++;
+ }
+ }
+ /* force tRNS ? */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((bHasalpha) && (!iAlpha))
+#else
+ if ((pData->bBASIhasalpha) && (!pData->iBASIalpha))
+#endif
+ {
+ pBuf->bHasTRNS = MNG_TRUE;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pBuf->iTRNSgray = iRed;
+#else
+ pBuf->iTRNSgray = pData->iBASIred;
+#endif
+ }
+
+ break;
+ }
+
+ case 2 : { /* rgb */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth == 16)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_put_uint16 (pWork, iRed );
+ mng_put_uint16 (pWork+2, iGreen);
+ mng_put_uint16 (pWork+4, iBlue );
+#else
+ mng_put_uint16 (pWork, pData->iBASIred );
+ mng_put_uint16 (pWork+2, pData->iBASIgreen);
+ mng_put_uint16 (pWork+4, pData->iBASIblue );
+#endif
+ pWork += 6;
+ }
+ }
+ else
+#endif
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ *pWork = (mng_uint8)iRed;
+ *(pWork+1) = (mng_uint8)iGreen;
+ *(pWork+2) = (mng_uint8)iBlue;
+#else
+ *pWork = (mng_uint8)pData->iBASIred;
+ *(pWork+1) = (mng_uint8)pData->iBASIgreen;
+ *(pWork+2) = (mng_uint8)pData->iBASIblue;
+#endif
+ pWork += 3;
+ }
+ }
+ /* force tRNS ? */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((bHasalpha) && (!iAlpha))
+#else
+ if ((pData->bBASIhasalpha) && (!pData->iBASIalpha))
+#endif
+ {
+ pBuf->bHasTRNS = MNG_TRUE;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pBuf->iTRNSred = iRed;
+ pBuf->iTRNSgreen = iGreen;
+ pBuf->iTRNSblue = iBlue;
+#else
+ pBuf->iTRNSred = pData->iBASIred;
+ pBuf->iTRNSgreen = pData->iBASIgreen;
+ pBuf->iTRNSblue = pData->iBASIblue;
+#endif
+ }
+
+ break;
+ }
+
+ case 3 : { /* indexed */
+ pBuf->bHasPLTE = MNG_TRUE;
+
+ switch (pData->iBitdepth)
+ {
+ case 1 : { pBuf->iPLTEcount = 2; break; }
+ case 2 : { pBuf->iPLTEcount = 4; break; }
+ case 4 : { pBuf->iPLTEcount = 16; break; }
+ case 8 : { pBuf->iPLTEcount = 256; break; }
+ default : { pBuf->iPLTEcount = 1; break; }
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pBuf->aPLTEentries [0].iRed = (mng_uint8)iRed;
+ pBuf->aPLTEentries [0].iGreen = (mng_uint8)iGreen;
+ pBuf->aPLTEentries [0].iBlue = (mng_uint8)iBlue;
+#else
+ pBuf->aPLTEentries [0].iRed = (mng_uint8)pData->iBASIred;
+ pBuf->aPLTEentries [0].iGreen = (mng_uint8)pData->iBASIgreen;
+ pBuf->aPLTEentries [0].iBlue = (mng_uint8)pData->iBASIblue;
+#endif
+
+ for (iX = 1; iX < pBuf->iPLTEcount; iX++)
+ {
+ pBuf->aPLTEentries [iX].iRed = 0;
+ pBuf->aPLTEentries [iX].iGreen = 0;
+ pBuf->aPLTEentries [iX].iBlue = 0;
+ }
+ /* force tRNS ? */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((bHasalpha) && (iAlpha < 255))
+#else
+ if ((pData->bBASIhasalpha) && (pData->iBASIalpha < 255))
+#endif
+ {
+ pBuf->bHasTRNS = MNG_TRUE;
+ pBuf->iTRNScount = 1;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pBuf->aTRNSentries [0] = (mng_uint8)iAlpha;
+#else
+ pBuf->aTRNSentries [0] = (mng_uint8)pData->iBASIalpha;
+#endif
+ }
+
+ break;
+ }
+
+ case 4 : { /* gray+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth == 16)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_put_uint16 (pWork, iRed);
+ mng_put_uint16 (pWork+2, iAlpha);
+#else
+ mng_put_uint16 (pWork, pData->iBASIred);
+ mng_put_uint16 (pWork+2, pData->iBASIalpha);
+#endif
+ pWork += 4;
+ }
+ }
+ else
+#endif
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ *pWork = (mng_uint8)iRed;
+ *(pWork+1) = (mng_uint8)iAlpha;
+#else
+ *pWork = (mng_uint8)pData->iBASIred;
+ *(pWork+1) = (mng_uint8)pData->iBASIalpha;
+#endif
+ pWork += 2;
+ }
+ }
+
+ break;
+ }
+
+ case 6 : { /* rgb+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth == 16)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_put_uint16 (pWork, iRed);
+ mng_put_uint16 (pWork+2, iGreen);
+ mng_put_uint16 (pWork+4, iBlue);
+ mng_put_uint16 (pWork+6, iAlpha);
+#else
+ mng_put_uint16 (pWork, pData->iBASIred);
+ mng_put_uint16 (pWork+2, pData->iBASIgreen);
+ mng_put_uint16 (pWork+4, pData->iBASIblue);
+ mng_put_uint16 (pWork+6, pData->iBASIalpha);
+#endif
+ pWork += 8;
+ }
+ }
+ else
+#endif
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iDatawidth * pData->iDataheight;
+ iX > 0;iX--)
+#else
+ for (iX = 0; iX < pData->iDatawidth * pData->iDataheight; iX++)
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ *pWork = (mng_uint8)iRed;
+ *(pWork+1) = (mng_uint8)iGreen;
+ *(pWork+2) = (mng_uint8)iBlue;
+ *(pWork+3) = (mng_uint8)iAlpha;
+#else
+ *pWork = (mng_uint8)pData->iBASIred;
+ *(pWork+1) = (mng_uint8)pData->iBASIgreen;
+ *(pWork+2) = (mng_uint8)pData->iBASIblue;
+ *(pWork+3) = (mng_uint8)pData->iBASIalpha;
+#endif
+ pWork += 4;
+ }
+ }
+
+ break;
+ }
+
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+ pData->ePng_imgtype=mng_png_imgtype(pData->iColortype,pData->iBitdepth);
+#else
+ switch (pData->iColortype) /* determine row initialization routine */
+ { /* just to accomodate IDAT if it arrives */
+ case 0 : { /* gray */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 2 : { /* rgb */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 3 : { /* indexed */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_i;
+
+ break;
+ }
+ }
+
+ break;
+ }
+ case 4 : { /* gray+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 6 : { /* rgb+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ }
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+ pData->iFilterofs = 0; /* determine filter characteristics */
+ pData->iLevel0 = 0; /* default levels */
+ pData->iLevel1 = 0;
+ pData->iLevel2 = 0;
+ pData->iLevel3 = 0;
+
+#ifdef FILTER192
+ if (pData->iFilter == 0xC0) /* leveling & differing ? */
+ {
+ switch (pData->iColortype)
+ {
+ case 0 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth <= 8)
+#endif
+ pData->iFilterofs = 1;
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ pData->iFilterofs = 2;
+#endif
+
+ break;
+ }
+ case 2 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth <= 8)
+#endif
+ pData->iFilterofs = 3;
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ pData->iFilterofs = 6;
+#endif
+
+ break;
+ }
+ case 3 : {
+ pData->iFilterofs = 1;
+ break;
+ }
+ case 4 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth <= 8)
+#endif
+ pData->iFilterofs = 2;
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ pData->iFilterofs = 4;
+#endif
+
+ break;
+ }
+ case 6 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->iBitdepth <= 8)
+#endif
+ pData->iFilterofs = 4;
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ pData->iFilterofs = 8;
+#endif
+
+ break;
+ }
+ }
+ }
+#endif
+
+#ifdef FILTER193
+ if (pData->iFilter == 0xC1) /* no adaptive filtering ? */
+ pData->iPixelofs = pData->iFilterofs;
+ else
+#endif
+ pData->iPixelofs = pData->iFilterofs + 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_clon (mng_datap pData,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_bool bHasdonotshow,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy)
+#else
+mng_retcode mng_process_display_clon (mng_datap pData)
+#endif
+{
+ mng_imagep pSource, pClone;
+ mng_bool bVisible, bAbstract;
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_START);
+#endif
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ /* locate the source object first */
+ pSource = mng_find_imageobject (pData, iSourceid);
+ /* check if the clone exists */
+ pClone = mng_find_imageobject (pData, iCloneid);
+#else
+ /* locate the source object first */
+ pSource = mng_find_imageobject (pData, pData->iCLONsourceid);
+ /* check if the clone exists */
+ pClone = mng_find_imageobject (pData, pData->iCLONcloneid);
+#endif
+
+ if (!pSource) /* source must exist ! */
+ MNG_ERROR (pData, MNG_OBJECTUNKNOWN);
+
+ if (pClone) /* clone must not exist ! */
+ MNG_ERROR (pData, MNG_OBJECTEXISTS);
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (bHasdonotshow) /* DoNotShow flag filled ? */
+ bVisible = (mng_bool)(iDonotshow == 0);
+ else
+ bVisible = pSource->bVisible;
+#else
+ if (pData->bCLONhasdonotshow) /* DoNotShow flag filled ? */
+ bVisible = (mng_bool)(pData->iCLONdonotshow == 0);
+ else
+ bVisible = pSource->bVisible;
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ bAbstract = (mng_bool)(iConcrete == 1);
+#else
+ bAbstract = (mng_bool)(pData->iCLONconcrete == 1);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iClonetype) /* determine action to take */
+ {
+ case 0 : { /* full clone */
+ iRetcode = mng_clone_imageobject (pData, iCloneid, MNG_FALSE,
+ bVisible, bAbstract, bHasloca,
+ iLocationtype, iLocationx, iLocationy,
+ pSource, &pClone);
+ break;
+ }
+
+ case 1 : { /* partial clone */
+ iRetcode = mng_clone_imageobject (pData, iCloneid, MNG_TRUE,
+ bVisible, bAbstract, bHasloca,
+ iLocationtype, iLocationx, iLocationy,
+ pSource, &pClone);
+ break;
+ }
+
+ case 2 : { /* renumber object */
+ iRetcode = mng_renum_imageobject (pData, pSource, iCloneid,
+ bVisible, bAbstract, bHasloca,
+ iLocationtype, iLocationx, iLocationy);
+ pClone = pSource;
+ break;
+ }
+
+ }
+#else
+ switch (pData->iCLONclonetype) /* determine action to take */
+ {
+ case 0 : { /* full clone */
+ iRetcode = mng_clone_imageobject (pData, pData->iCLONcloneid, MNG_FALSE,
+ bVisible, bAbstract,
+ pData->bCLONhasloca, pData->iCLONlocationtype,
+ pData->iCLONlocationx, pData->iCLONlocationy,
+ pSource, &pClone);
+ break;
+ }
+
+ case 1 : { /* partial clone */
+ iRetcode = mng_clone_imageobject (pData, pData->iCLONcloneid, MNG_TRUE,
+ bVisible, bAbstract,
+ pData->bCLONhasloca, pData->iCLONlocationtype,
+ pData->iCLONlocationx, pData->iCLONlocationy,
+ pSource, &pClone);
+ break;
+ }
+
+ case 2 : { /* renumber object */
+ iRetcode = mng_renum_imageobject (pData, pSource, pData->iCLONcloneid,
+ bVisible, bAbstract,
+ pData->bCLONhasloca, pData->iCLONlocationtype,
+ pData->iCLONlocationx, pData->iCLONlocationy);
+ pClone = pSource;
+ break;
+ }
+
+ }
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ /* display on the fly ? */
+ if ((pClone->bViewable) && (pClone->bVisible))
+ {
+ pData->pLastclone = pClone; /* remember in case of timer break ! */
+ /* display it */
+ mng_display_image (pData, pClone, MNG_FALSE);
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 5;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_clon2 (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_START);
+#endif
+ /* only called after timer break ! */
+ mng_display_image (pData, (mng_imagep)pData->pLastclone, MNG_FALSE);
+ pData->iBreakpoint = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_disc (mng_datap pData,
+ mng_uint32 iCount,
+ mng_uint16p pIds)
+#else
+mng_retcode mng_process_display_disc (mng_datap pData)
+#endif
+{
+ mng_uint32 iX;
+ mng_imagep pImage;
+ mng_uint32 iRetcode;
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DISC, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iCount) /* specific list ? */
+#else
+ if (pData->iDISCcount) /* specific list ? */
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_uint16p pWork = pIds;
+#else
+ mng_uint16p pWork = pData->pDISCids;
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifdef MNG_DECREMENT_LOOPS /* iterate the list */
+ for (iX = iCount; iX > 0; iX--)
+#else
+ for (iX = 0; iX < iCount; iX++)
+#endif
+#else
+#ifdef MNG_DECREMENT_LOOPS /* iterate the list */
+ for (iX = pData->iDISCcount; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iDISCcount; iX++)
+#endif
+#endif
+ {
+ pImage = mng_find_imageobject (pData, *pWork++);
+
+ if (pImage) /* found the object ? */
+ { /* then drop it */
+ iRetcode = mng_free_imageobject (pData, pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+ }
+ else /* empty: drop all un-frozen objects */
+ {
+ mng_imagep pNext = (mng_imagep)pData->pFirstimgobj;
+
+ while (pNext) /* any left ? */
+ {
+ pImage = pNext;
+ pNext = pImage->sHeader.pNext;
+
+ if (!pImage->bFrozen) /* not frozen ? */
+ { /* then drop it */
+ iRetcode = mng_free_imageobject (pData, pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_fram (mng_datap pData,
+ mng_uint8 iFramemode,
+ mng_uint8 iChangedelay,
+ mng_uint32 iDelay,
+ mng_uint8 iChangetimeout,
+ mng_uint32 iTimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+#else
+mng_retcode mng_process_display_fram (mng_datap pData)
+#endif
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_START);
+#endif
+ /* advance a frame then */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = next_frame (pData, iFramemode, iChangedelay, iDelay,
+ iChangetimeout, iTimeout, iChangeclipping,
+ iCliptype, iClipl, iClipr, iClipt, iClipb);
+#else
+ iRetcode = next_frame (pData, pData->iTempFramemode, pData->iTempChangedelay,
+ pData->iTempDelay, pData->iTempChangetimeout,
+ pData->iTempTimeout, pData->iTempChangeclipping,
+ pData->iTempCliptype, pData->iTempClipl, pData->iTempClipr,
+ pData->iTempClipt, pData->iTempClipb);
+#endif
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_fram2 (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_START);
+#endif
+ /* again; after the break */
+ iRetcode = next_frame (pData, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ pData->iBreakpoint = 0; /* not again! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_FRAM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_move (mng_datap pData,
+ mng_uint16 iFromid,
+ mng_uint16 iToid,
+ mng_uint8 iMovetype,
+ mng_int32 iMovex,
+ mng_int32 iMovey)
+#else
+mng_retcode mng_process_display_move (mng_datap pData)
+#endif
+{
+ mng_uint16 iX;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MOVE, MNG_LC_START);
+#endif
+ /* iterate the list */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = iFromid; iX <= iToid; iX++)
+#else
+ for (iX = pData->iMOVEfromid; iX <= pData->iMOVEtoid; iX++)
+#endif
+ {
+ if (!iX) /* object id=0 ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ else
+ pImage = mng_find_imageobject (pData, iX);
+
+ if (pImage) /* object exists ? */
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iMovetype)
+#else
+ switch (pData->iMOVEmovetype)
+#endif
+ {
+ case 0 : { /* absolute */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iPosx = iMovex;
+ pImage->iPosy = iMovey;
+#else
+ pImage->iPosx = pData->iMOVEmovex;
+ pImage->iPosy = pData->iMOVEmovey;
+#endif
+ break;
+ }
+ case 1 : { /* relative */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iPosx = pImage->iPosx + iMovex;
+ pImage->iPosy = pImage->iPosy + iMovey;
+#else
+ pImage->iPosx = pImage->iPosx + pData->iMOVEmovex;
+ pImage->iPosy = pImage->iPosy + pData->iMOVEmovey;
+#endif
+ break;
+ }
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_clip (mng_datap pData,
+ mng_uint16 iFromid,
+ mng_uint16 iToid,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+#else
+mng_retcode mng_process_display_clip (mng_datap pData)
+#endif
+{
+ mng_uint16 iX;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLIP, MNG_LC_START);
+#endif
+ /* iterate the list */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = iFromid; iX <= iToid; iX++)
+#else
+ for (iX = pData->iCLIPfromid; iX <= pData->iCLIPtoid; iX++)
+#endif
+ {
+ if (!iX) /* object id=0 ? */
+ pImage = (mng_imagep)pData->pObjzero;
+ else
+ pImage = mng_find_imageobject (pData, iX);
+
+ if (pImage) /* object exists ? */
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iCliptype)
+#else
+ switch (pData->iCLIPcliptype)
+#endif
+ {
+ case 0 : { /* absolute */
+ pImage->bClipped = MNG_TRUE;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iClipl = iClipl;
+ pImage->iClipr = iClipr;
+ pImage->iClipt = iClipt;
+ pImage->iClipb = iClipb;
+#else
+ pImage->iClipl = pData->iCLIPclipl;
+ pImage->iClipr = pData->iCLIPclipr;
+ pImage->iClipt = pData->iCLIPclipt;
+ pImage->iClipb = pData->iCLIPclipb;
+#endif
+ break;
+ }
+ case 1 : { /* relative */
+ pImage->bClipped = MNG_TRUE;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iClipl = pImage->iClipl + iClipl;
+ pImage->iClipr = pImage->iClipr + iClipr;
+ pImage->iClipt = pImage->iClipt + iClipt;
+ pImage->iClipb = pImage->iClipb + iClipb;
+#else
+ pImage->iClipl = pImage->iClipl + pData->iCLIPclipl;
+ pImage->iClipr = pImage->iClipr + pData->iCLIPclipr;
+ pImage->iClipt = pImage->iClipt + pData->iCLIPclipt;
+ pImage->iClipb = pImage->iClipb + pData->iCLIPclipb;
+#endif
+ break;
+ }
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+mng_retcode mng_process_display_show (mng_datap pData)
+{
+ mng_int16 iX, iS, iFrom, iTo;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SHOW, MNG_LC_START);
+#endif
+
+ /* TODO: optimization for the cases where "abs (iTo - iFrom)" is rather high;
+ especially where ((iFrom==1) && (iTo==65535)); eg. an empty SHOW !!! */
+
+ if (pData->iBreakpoint == 3) /* previously broken during cycle-mode ? */
+ {
+ pImage = mng_find_imageobject (pData, pData->iSHOWnextid);
+
+ if (pImage) /* still there ? */
+ mng_display_image (pData, pImage, MNG_FALSE);
+
+ pData->iBreakpoint = 0; /* let's not go through this again! */
+ }
+ else
+ {
+ if (pData->iBreakpoint) /* previously broken at other point ? */
+ { /* restore last parms */
+ iFrom = (mng_int16)pData->iSHOWfromid;
+ iTo = (mng_int16)pData->iSHOWtoid;
+ iX = (mng_int16)pData->iSHOWnextid;
+ iS = (mng_int16)pData->iSHOWskip;
+ }
+ else
+ { /* regular sequence ? */
+ if (pData->iSHOWtoid >= pData->iSHOWfromid)
+ iS = 1;
+ else /* reverse sequence ! */
+ iS = -1;
+
+ iFrom = (mng_int16)pData->iSHOWfromid;
+ iTo = (mng_int16)pData->iSHOWtoid;
+ iX = iFrom;
+
+ pData->iSHOWfromid = (mng_uint16)iFrom;
+ pData->iSHOWtoid = (mng_uint16)iTo;
+ pData->iSHOWskip = iS;
+ }
+ /* cycle mode ? */
+ if ((pData->iSHOWmode == 6) || (pData->iSHOWmode == 7))
+ {
+ mng_uint16 iTrigger = 0;
+ mng_uint16 iFound = 0;
+ mng_uint16 iPass = 0;
+ mng_imagep pFound = 0;
+
+ do
+ {
+ iPass++; /* lets prevent endless loops when there
+ are no potential candidates in the list! */
+
+ if (iS > 0) /* forward ? */
+ {
+ for (iX = iFrom; iX <= iTo; iX += iS)
+ {
+ pImage = mng_find_imageobject (pData, (mng_uint16)iX);
+
+ if (pImage) /* object exists ? */
+ {
+ if (iFound) /* already found a candidate ? */
+ pImage->bVisible = MNG_FALSE;
+ else
+ if (iTrigger) /* found the trigger ? */
+ {
+ pImage->bVisible = MNG_TRUE;
+ iFound = iX;
+ pFound = pImage;
+ }
+ else
+ if (pImage->bVisible) /* ok, this is the trigger */
+ {
+ pImage->bVisible = MNG_FALSE;
+ iTrigger = iX;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (iX = iFrom; iX >= iTo; iX += iS)
+ {
+ pImage = mng_find_imageobject (pData, (mng_uint16)iX);
+
+ if (pImage) /* object exists ? */
+ {
+ if (iFound) /* already found a candidate ? */
+ pImage->bVisible = MNG_FALSE;
+ else
+ if (iTrigger) /* found the trigger ? */
+ {
+ pImage->bVisible = MNG_TRUE;
+ iFound = iX;
+ pFound = pImage;
+ }
+ else
+ if (pImage->bVisible) /* ok, this is the trigger */
+ {
+ pImage->bVisible = MNG_FALSE;
+ iTrigger = iX;
+ }
+ }
+ }
+ }
+
+ if (!iTrigger) /* did not find a trigger ? */
+ iTrigger = 1; /* then fake it so the first image
+ gets nominated */
+ } /* cycle back to beginning ? */
+ while ((iPass < 2) && (iTrigger) && (!iFound));
+
+ pData->iBreakpoint = 0; /* just a sanity precaution */
+ /* display it ? */
+ if ((pData->iSHOWmode == 6) && (pFound))
+ {
+ mng_display_image (pData, pFound, MNG_FALSE);
+
+ if (pData->bTimerset) /* timer set ? */
+ {
+ pData->iBreakpoint = 3;
+ pData->iSHOWnextid = iFound; /* save it for after the break */
+ }
+ }
+ }
+ else
+ {
+ do
+ {
+ pImage = mng_find_imageobject (pData, iX);
+
+ if (pImage) /* object exists ? */
+ {
+ if (pData->iBreakpoint) /* did we get broken last time ? */
+ { /* could only happen in the display routine */
+ mng_display_image (pData, pImage, MNG_FALSE);
+ pData->iBreakpoint = 0; /* only once inside this loop please ! */
+ }
+ else
+ {
+ switch (pData->iSHOWmode) /* do what ? */
+ {
+ case 0 : {
+ pImage->bVisible = MNG_TRUE;
+ mng_display_image (pData, pImage, MNG_FALSE);
+ break;
+ }
+ case 1 : {
+ pImage->bVisible = MNG_FALSE;
+ break;
+ }
+ case 2 : {
+ if (pImage->bVisible)
+ mng_display_image (pData, pImage, MNG_FALSE);
+ break;
+ }
+ case 3 : {
+ pImage->bVisible = MNG_TRUE;
+ break;
+ }
+ case 4 : {
+ pImage->bVisible = (mng_bool)(!pImage->bVisible);
+ if (pImage->bVisible)
+ mng_display_image (pData, pImage, MNG_FALSE);
+ break;
+ }
+ case 5 : {
+ pImage->bVisible = (mng_bool)(!pImage->bVisible);
+ }
+ }
+ }
+ }
+
+ if (!pData->bTimerset) /* next ? */
+ iX += iS;
+
+ } /* continue ? */
+ while ((!pData->bTimerset) && (((iS > 0) && (iX <= iTo)) ||
+ ((iS < 0) && (iX >= iTo)) ));
+
+ if (pData->bTimerset) /* timer set ? */
+ {
+ pData->iBreakpoint = 4;
+ pData->iSHOWnextid = iX; /* save for next time */
+ }
+ else
+ pData->iBreakpoint = 0;
+
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_process_display_save (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SAVE, MNG_LC_START);
+#endif
+
+ iRetcode = save_state (pData); /* save the current state */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_process_display_seek (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SEEK, MNG_LC_START);
+#endif
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ if (pData->bStopafterseek) /* need to stop after this SEEK ? */
+ {
+ pData->bFreezing = MNG_TRUE; /* stop processing on this one */
+ pData->bRunningevent = MNG_FALSE;
+ pData->bStopafterseek = MNG_FALSE;
+ pData->bNeedrefresh = MNG_TRUE; /* make sure the last bit is displayed ! */
+ }
+ else
+#endif
+ { /* restore the initial or SAVE state */
+ mng_retcode iRetcode = restore_state (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ /* stop after next SEEK ? */
+ if ((pData->bDynamic) || (pData->bRunningevent))
+ pData->bStopafterseek = MNG_TRUE;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_jhdr (mng_datap pData)
+{ /* address the current "object" if any */
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JHDR, MNG_LC_START);
+#endif
+
+ if (!pData->bHasDHDR)
+ {
+ pData->fInitrowproc = MNG_NULL; /* do nothing by default */
+ pData->fDisplayrow = MNG_NULL;
+ pData->fCorrectrow = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ pData->fDifferrow = MNG_NULL;
+ pData->fStorerow2 = MNG_NULL;
+ pData->fStorerow3 = MNG_NULL;
+
+ pData->pStoreobj = MNG_NULL; /* initialize important work-parms */
+
+ pData->iJPEGrow = 0;
+ pData->iJPEGalpharow = 0;
+ pData->iJPEGrgbrow = 0;
+ pData->iRowmax = 0; /* so init_rowproc does the right thing ! */
+ }
+
+ if (!pData->iBreakpoint) /* not previously broken ? */
+ {
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* delta-image ? */
+ {
+ if (pData->iDeltatype == MNG_DELTATYPE_REPLACE)
+ {
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pDeltaImage,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iJHDRimgbitdepth, pData->iJHDRcolortype,
+ pData->iJHDRalphacompression, pData->iJHDRalphafilter,
+ pData->iJHDRalphainterlace, MNG_TRUE);
+
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth;
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression;
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace;
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth;
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iJHDRimgbitdepth;
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth;
+ }
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth;
+ else
+ if ((pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ ((mng_imagep)pData->pDeltaImage)->pImgbuf->iPixelsampledepth = pData->iJHDRimgbitdepth;
+
+ }
+ else
+#endif /* MNG_NO_DELTA_PNG */
+ {
+ if (pImage) /* update object buffer ? */
+ {
+ iRetcode = mng_reset_object_details (pData, pImage,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iJHDRimgbitdepth, pData->iJHDRcolortype,
+ pData->iJHDRalphacompression, pData->iJHDRalphafilter,
+ pData->iJHDRalphainterlace, MNG_TRUE);
+
+ pImage->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth;
+ pImage->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression;
+ pImage->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace;
+ pImage->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth;
+ }
+ else /* update object 0 */
+ {
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pObjzero,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iJHDRimgbitdepth, pData->iJHDRcolortype,
+ pData->iJHDRalphacompression, pData->iJHDRalphafilter,
+ pData->iJHDRalphainterlace, MNG_TRUE);
+
+ ((mng_imagep)pData->pObjzero)->pImgbuf->iAlphabitdepth = pData->iJHDRalphabitdepth;
+ ((mng_imagep)pData->pObjzero)->pImgbuf->iJHDRcompression = pData->iJHDRimgcompression;
+ ((mng_imagep)pData->pObjzero)->pImgbuf->iJHDRinterlace = pData->iJHDRimginterlace;
+ ((mng_imagep)pData->pObjzero)->pImgbuf->iAlphasampledepth = pData->iJHDRalphabitdepth;
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ if (!pData->bHasDHDR)
+ { /* we're always storing a JPEG */
+ if (pImage) /* real object ? */
+ pData->pStoreobj = pImage; /* tell the row routines */
+ else /* otherwise use object 0 */
+ pData->pStoreobj = pData->pObjzero;
+ /* display "on-the-fly" ? */
+ if (
+#ifndef MNG_SKIPCHUNK_MAGN
+ ( ((mng_imagep)pData->pStoreobj)->iMAGN_MethodX == 0) &&
+ ( ((mng_imagep)pData->pStoreobj)->iMAGN_MethodY == 0) &&
+#endif
+ ( (pData->eImagetype == mng_it_jng ) ||
+ (((mng_imagep)pData->pStoreobj)->bVisible) ) )
+ {
+ next_layer (pData); /* that's a new layer then ! */
+
+ pData->iBreakpoint = 0;
+
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 7;
+ else
+ if (pData->bRunning) /* still running ? */
+ { /* anything to display ? */
+ if ((pData->iDestr > pData->iDestl) && (pData->iDestb > pData->iDestt))
+ {
+ set_display_routine (pData); /* then determine display routine */
+ /* display from the object we store in */
+ pData->pRetrieveobj = pData->pStoreobj;
+ }
+ }
+ }
+ }
+
+ if (!pData->bTimerset) /* no timer break ? */
+ { /* default row initialization ! */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->ePng_imgtype=png_none;
+#endif
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+
+ if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_REPLACE))
+ { /* 8-bit JPEG ? */
+ if (pData->iJHDRimgbitdepth == 8)
+ { /* intermediate row is 8-bit deep */
+ pData->bIsRGBA16 = MNG_FALSE;
+ pData->iRowsamples = pData->iDatawidth;
+
+ switch (pData->iJHDRcolortype) /* determine pixel processing routines */
+ {
+ case MNG_COLORTYPE_JPEGGRAY :
+ {
+ pData->fStorerow2 = (mng_fptr)mng_store_jpeg_g8;
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+ case MNG_COLORTYPE_JPEGCOLOR :
+ {
+ pData->fStorerow2 = (mng_fptr)mng_store_jpeg_rgb8;
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+ case MNG_COLORTYPE_JPEGGRAYA :
+ {
+ pData->fStorerow2 = (mng_fptr)mng_store_jpeg_ga8;
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+ case MNG_COLORTYPE_JPEGCOLORA :
+ {
+ pData->fStorerow2 = (mng_fptr)mng_store_jpeg_rgba8;
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+ }
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ {
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+ /* TODO: 12-bit JPEG */
+ /* TODO: 8- + 12-bit JPEG (eg. type=20) */
+
+ }
+#endif
+ /* possible IDAT alpha-channel ? */
+ if (pData->iJHDRalphacompression == MNG_COMPRESSION_DEFLATE)
+ {
+ /* determine alpha processing routine */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+#endif
+ switch (pData->iJHDRalphabitdepth)
+ {
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fInitrowproc = (mng_fptr)mng_init_jpeg_a1_ni; break; }
+ case 2 : { pData->fInitrowproc = (mng_fptr)mng_init_jpeg_a2_ni; break; }
+ case 4 : { pData->fInitrowproc = (mng_fptr)mng_init_jpeg_a4_ni; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->fInitrowproc = (mng_fptr)mng_init_jpeg_a8_ni; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fInitrowproc = (mng_fptr)mng_init_jpeg_a16_ni; break; }
+#endif
+#else
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->ePng_imgtype = png_jpeg_a1; break; }
+ case 2 : { pData->ePng_imgtype = png_jpeg_a2; break; }
+ case 4 : { pData->ePng_imgtype = png_jpeg_a4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->ePng_imgtype = png_jpeg_a8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->ePng_imgtype = png_jpeg_a16; break; }
+#endif
+#endif
+ }
+ }
+ else /* possible JDAA alpha-channel ? */
+ if (pData->iJHDRalphacompression == MNG_COMPRESSION_BASELINEJPEG)
+ { /* 8-bit JPEG ? */
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ if (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA)
+ pData->fStorerow3 = (mng_fptr)mng_store_jpeg_g8_alpha;
+ else
+ if (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA)
+ pData->fStorerow3 = (mng_fptr)mng_store_jpeg_rgb8_alpha;
+ }
+ else
+ {
+ /* TODO: 12-bit JPEG with 8-bit JDAA */
+ }
+ }
+ /* initialize JPEG library */
+ iRetcode = mngjpeg_initialize (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* must be alpha add/replace !! */
+ if ((pData->iDeltatype != MNG_DELTATYPE_BLOCKALPHAADD ) &&
+ (pData->iDeltatype != MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ MNG_ERROR (pData, MNG_INVDELTATYPE);
+ /* determine alpha processing routine */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+#endif
+ switch (pData->iJHDRalphabitdepth)
+ {
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->fInitrowproc = (mng_fptr)mng_init_g1_ni; break; }
+ case 2 : { pData->fInitrowproc = (mng_fptr)mng_init_g2_ni; break; }
+ case 4 : { pData->fInitrowproc = (mng_fptr)mng_init_g4_ni; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->fInitrowproc = (mng_fptr)mng_init_g8_ni; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fInitrowproc = (mng_fptr)mng_init_g16_ni; break; }
+#endif
+#else
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : { pData->ePng_imgtype = png_jpeg_a1; break; }
+ case 2 : { pData->ePng_imgtype = png_jpeg_a2; break; }
+ case 4 : { pData->ePng_imgtype = png_jpeg_a4; break; }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : { pData->ePng_imgtype = png_jpeg_a8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->ePng_imgtype = png_jpeg_a16; break; }
+#endif
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+ }
+ }
+
+ pData->iFilterofs = 0; /* determine filter characteristics */
+ pData->iLevel0 = 0; /* default levels */
+ pData->iLevel1 = 0;
+ pData->iLevel2 = 0;
+ pData->iLevel3 = 0;
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iJHDRalphafilter == 0xC0)
+ {
+ if (pData->iJHDRalphabitdepth <= 8)
+ pData->iFilterofs = 1;
+ else
+ pData->iFilterofs = 2;
+
+ }
+#endif
+#ifdef FILTER193 /* no adaptive filtering ? */
+ if (pData->iJHDRalphafilter == 0xC1)
+ pData->iPixelofs = pData->iFilterofs;
+ else
+#endif
+ pData->iPixelofs = pData->iFilterofs + 1;
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_jdaa (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata)
+#else
+mng_retcode mng_process_display_jdaa (mng_datap pData)
+#endif
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAA, MNG_LC_START);
+#endif
+
+ if (!pData->bJPEGdecompress2) /* if we're not decompressing already */
+ {
+ if (pData->fInitrowproc) /* initialize row-processing? */
+ {
+ iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData);
+ pData->fInitrowproc = MNG_NULL; /* only call this once !!! */
+ }
+
+ if (!iRetcode) /* initialize decompress */
+ iRetcode = mngjpeg_decompressinit2 (pData);
+ }
+
+ if (!iRetcode) /* all ok? then decompress, my man */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mngjpeg_decompressdata2 (pData, iRawlen, pRawdata);
+#else
+ iRetcode = mngjpeg_decompressdata2 (pData, pData->iRawlen, pData->pRawdata);
+#endif
+
+ if (iRetcode)
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_jdat (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata)
+#else
+mng_retcode mng_process_display_jdat (mng_datap pData)
+#endif
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAT, MNG_LC_START);
+#endif
+
+ if (pData->bRestorebkgd) /* need to restore the background ? */
+ {
+ pData->bRestorebkgd = MNG_FALSE;
+ iRetcode = load_bkgdlayer (pData);
+
+ pData->iLayerseq++; /* and it counts as a layer then ! */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ if (!pData->bJPEGdecompress) /* if we're not decompressing already */
+ {
+ if (pData->fInitrowproc) /* initialize row-processing? */
+ {
+ iRetcode = ((mng_initrowproc)pData->fInitrowproc) (pData);
+ pData->fInitrowproc = MNG_NULL; /* only call this once !!! */
+ }
+
+ if (!iRetcode) /* initialize decompress */
+ iRetcode = mngjpeg_decompressinit (pData);
+ }
+
+ if (!iRetcode) /* all ok? then decompress, my man */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mngjpeg_decompressdata (pData, iRawlen, pRawdata);
+#else
+ iRetcode = mngjpeg_decompressdata (pData, pData->iRawlen, pData->pRawdata);
+#endif
+
+ if (iRetcode)
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_JDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_dhdr (mng_datap pData,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky)
+#else
+mng_retcode mng_process_display_dhdr (mng_datap pData)
+#endif
+{
+ mng_imagep pImage;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DHDR, MNG_LC_START);
+#endif
+
+ pData->fInitrowproc = MNG_NULL; /* do nothing by default */
+ pData->fDisplayrow = MNG_NULL;
+ pData->fCorrectrow = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ pData->pStoreobj = MNG_NULL;
+
+ pData->fDeltagetrow = MNG_NULL;
+ pData->fDeltaaddrow = MNG_NULL;
+ pData->fDeltareplacerow = MNG_NULL;
+ pData->fDeltaputrow = MNG_NULL;
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage = mng_find_imageobject (pData, iObjectid);
+#else
+ pImage = mng_find_imageobject (pData, pData->iDHDRobjectid);
+#endif
+
+ if (pImage) /* object exists ? */
+ {
+ if (pImage->pImgbuf->bConcrete) /* is it concrete ? */
+ { /* previous magnification to be done ? */
+#ifndef MNG_SKIPCHUNK_MAGN
+ if ((pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY))
+ {
+ iRetcode = mng_magnify_imageobject (pData, pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+ /* save delta fields */
+ pData->pDeltaImage = (mng_ptr)pImage;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iDeltaImagetype = iImagetype;
+ pData->iDeltatype = iDeltatype;
+ pData->iDeltaBlockwidth = iBlockwidth;
+ pData->iDeltaBlockheight = iBlockheight;
+ pData->iDeltaBlockx = iBlockx;
+ pData->iDeltaBlocky = iBlocky;
+#else
+ pData->iDeltaImagetype = pData->iDHDRimagetype;
+ pData->iDeltatype = pData->iDHDRdeltatype;
+ pData->iDeltaBlockwidth = pData->iDHDRblockwidth;
+ pData->iDeltaBlockheight = pData->iDHDRblockheight;
+ pData->iDeltaBlockx = pData->iDHDRblockx;
+ pData->iDeltaBlocky = pData->iDHDRblocky;
+#endif
+ /* restore target-object fields */
+ pData->iDatawidth = pImage->pImgbuf->iWidth;
+ pData->iDataheight = pImage->pImgbuf->iHeight;
+ pData->iBitdepth = pImage->pImgbuf->iBitdepth;
+ pData->iColortype = pImage->pImgbuf->iColortype;
+ pData->iCompression = pImage->pImgbuf->iCompression;
+ pData->iFilter = pImage->pImgbuf->iFilter;
+ pData->iInterlace = pImage->pImgbuf->iInterlace;
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iPixelsampledepth;
+ else
+ if ((iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iAlphasampledepth;
+ else
+ if ((iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iPixelsampledepth;
+#else
+ if ((pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKPIXELADD ) ||
+ (pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iPixelsampledepth;
+ else
+ if ((pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKALPHAADD ) ||
+ (pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iAlphasampledepth;
+ else
+ if ((pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKCOLORADD ) ||
+ (pData->iDHDRdeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE) )
+ pData->iBitdepth = pImage->pImgbuf->iPixelsampledepth;
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+ pData->iJHDRimgbitdepth = pImage->pImgbuf->iBitdepth;
+ pData->iJHDRcolortype = pImage->pImgbuf->iColortype;
+ pData->iJHDRimgcompression = pImage->pImgbuf->iJHDRcompression;
+ pData->iJHDRimginterlace = pImage->pImgbuf->iJHDRinterlace;
+ pData->iJHDRalphacompression = pImage->pImgbuf->iCompression;
+ pData->iJHDRalphafilter = pImage->pImgbuf->iFilter;
+ pData->iJHDRalphainterlace = pImage->pImgbuf->iInterlace;
+ pData->iJHDRalphabitdepth = pImage->pImgbuf->iAlphabitdepth;
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ /* block size specified ? */
+ if (iDeltatype != MNG_DELTATYPE_NOCHANGE)
+ { /* block entirely within target ? */
+ if (iDeltatype != MNG_DELTATYPE_REPLACE)
+ {
+ if (((iBlockx + iBlockwidth ) > pData->iDatawidth ) ||
+ ((iBlocky + iBlockheight) > pData->iDataheight) )
+ MNG_ERROR (pData, MNG_INVALIDBLOCK);
+ }
+
+ pData->iDatawidth = iBlockwidth;
+ pData->iDataheight = iBlockheight;
+ }
+#else
+ /* block size specified ? */
+ if (pData->iDHDRdeltatype != MNG_DELTATYPE_NOCHANGE)
+ { /* block entirely within target ? */
+ if (pData->iDHDRdeltatype != MNG_DELTATYPE_REPLACE)
+ {
+ if (((pData->iDHDRblockx + pData->iDHDRblockwidth ) > pData->iDatawidth ) ||
+ ((pData->iDHDRblocky + pData->iDHDRblockheight) > pData->iDataheight) )
+ MNG_ERROR (pData, MNG_INVALIDBLOCK);
+ }
+
+ pData->iDatawidth = pData->iDHDRblockwidth;
+ pData->iDataheight = pData->iDHDRblockheight;
+ }
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iDeltatype) /* determine nr of delta-channels */
+#else
+ switch (pData->iDHDRdeltatype) /* determine nr of delta-channels */
+#endif
+ {
+ case MNG_DELTATYPE_BLOCKALPHAADD : ;
+ case MNG_DELTATYPE_BLOCKALPHAREPLACE :
+ {
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) )
+ {
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+ pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY;
+ }
+ else
+ if ((pData->iColortype == MNG_COLORTYPE_RGBA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ {
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+ pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY;
+ }
+#else
+ if (pData->iColortype == MNG_COLORTYPE_GRAYA)
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+ else
+ if (pData->iColortype == MNG_COLORTYPE_RGBA)
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+#endif
+ else /* target has no alpha; that sucks! */
+ MNG_ERROR (pData, MNG_TARGETNOALPHA);
+
+ break;
+ }
+
+ case MNG_DELTATYPE_BLOCKCOLORADD : ;
+ case MNG_DELTATYPE_BLOCKCOLORREPLACE :
+ {
+#ifdef MNG_INCLUDE_JNG
+ if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) )
+ {
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+ pData->iJHDRcolortype = MNG_COLORTYPE_JPEGGRAY;
+ }
+ else
+ if ((pData->iColortype == MNG_COLORTYPE_RGBA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ {
+ pData->iColortype = MNG_COLORTYPE_RGB;
+ pData->iJHDRcolortype = MNG_COLORTYPE_JPEGCOLOR;
+ }
+#else
+ if (pData->iColortype == MNG_COLORTYPE_GRAYA)
+ pData->iColortype = MNG_COLORTYPE_GRAY;
+ else
+ if (pData->iColortype == MNG_COLORTYPE_RGBA)
+ pData->iColortype = MNG_COLORTYPE_RGB;
+#endif
+ else /* target has no alpha; that sucks! */
+ MNG_ERROR (pData, MNG_TARGETNOALPHA);
+
+ break;
+ }
+
+ }
+ /* full image replace ? */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iDeltatype == MNG_DELTATYPE_REPLACE)
+#else
+ if (pData->iDHDRdeltatype == MNG_DELTATYPE_REPLACE)
+#endif
+ {
+ iRetcode = mng_reset_object_details (pData, pImage,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_FALSE);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->pStoreobj = pImage; /* and store straight into this object */
+ }
+ else
+ {
+ mng_imagedatap pBufzero, pBuf;
+ /* we store in object 0 and process it later */
+ pData->pStoreobj = pData->pObjzero;
+ /* make sure to initialize object 0 then */
+ iRetcode = mng_reset_object_details (pData, (mng_imagep)pData->pObjzero,
+ pData->iDatawidth, pData->iDataheight,
+ pData->iBitdepth, pData->iColortype,
+ pData->iCompression, pData->iFilter,
+ pData->iInterlace, MNG_TRUE);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pBuf = pImage->pImgbuf; /* copy possible palette & cheap transparency */
+ pBufzero = ((mng_imagep)pData->pObjzero)->pImgbuf;
+
+ pBufzero->bHasPLTE = pBuf->bHasPLTE;
+ pBufzero->bHasTRNS = pBuf->bHasTRNS;
+
+ if (pBufzero->bHasPLTE) /* copy palette ? */
+ {
+ mng_uint32 iX;
+
+ pBufzero->iPLTEcount = pBuf->iPLTEcount;
+
+ for (iX = 0; iX < pBuf->iPLTEcount; iX++)
+ {
+ pBufzero->aPLTEentries [iX].iRed = pBuf->aPLTEentries [iX].iRed;
+ pBufzero->aPLTEentries [iX].iGreen = pBuf->aPLTEentries [iX].iGreen;
+ pBufzero->aPLTEentries [iX].iBlue = pBuf->aPLTEentries [iX].iBlue;
+ }
+ }
+
+ if (pBufzero->bHasTRNS) /* copy cheap transparency ? */
+ {
+ pBufzero->iTRNSgray = pBuf->iTRNSgray;
+ pBufzero->iTRNSred = pBuf->iTRNSred;
+ pBufzero->iTRNSgreen = pBuf->iTRNSgreen;
+ pBufzero->iTRNSblue = pBuf->iTRNSblue;
+ pBufzero->iTRNScount = pBuf->iTRNScount;
+
+ MNG_COPY (pBufzero->aTRNSentries, pBuf->aTRNSentries,
+ sizeof (pBufzero->aTRNSentries));
+ }
+ /* process immediately if bitdepth & colortype are equal */
+ pData->bDeltaimmediate =
+ (mng_bool)((pData->bDisplaying) && (!pData->bSkipping) &&
+ ((pData->bRunning) || (pData->bSearching)) &&
+ (pData->iBitdepth == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iBitdepth ) &&
+ (pData->iColortype == ((mng_imagep)pData->pDeltaImage)->pImgbuf->iColortype) );
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ pData->fInitrowproc = (mng_fptr)mng_init_rowproc;
+ pData->ePng_imgtype = mng_png_imgtype (pData->iColortype, pData->iBitdepth);
+#else
+ switch (pData->iColortype) /* determine row initialization routine */
+ {
+ case 0 : { /* gray */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_g16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 2 : { /* rgb */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgb16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 3 : { /* indexed */
+ switch (pData->iBitdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx1_i;
+
+ break;
+ }
+ case 2 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx2_i;
+
+ break;
+ }
+ case 4 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx4_i;
+
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_idx8_i;
+
+ break;
+ }
+ }
+
+ break;
+ }
+ case 4 : { /* gray+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_ga16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ case 6 : { /* rgb+alpha */
+ switch (pData->iBitdepth)
+ {
+ case 8 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba8_i;
+
+ break;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : {
+ if (!pData->iInterlace)
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_ni;
+ else
+ pData->fInitrowproc = (mng_fptr)mng_init_rgba16_i;
+
+ break;
+ }
+#endif
+ }
+
+ break;
+ }
+ }
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+ }
+ else
+ MNG_ERROR (pData, MNG_OBJNOTCONCRETE);
+
+ }
+ else
+ MNG_ERROR (pData, MNG_OBJECTUNKNOWN);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_prom (mng_datap pData,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype)
+#else
+mng_retcode mng_process_display_prom (mng_datap pData)
+#endif
+{
+ mng_imagep pImage;
+ mng_imagedatap pBuf;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PROM, MNG_LC_START);
+#endif
+
+ if (!pData->pDeltaImage) /* gotta have this now! */
+ MNG_ERROR (pData, MNG_INVALIDDELTA);
+
+ pImage = (mng_imagep)pData->pDeltaImage;
+ pBuf = pImage->pImgbuf;
+ /* can't demote bitdepth! */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iBitdepth < pBuf->iBitdepth)
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ( ((pBuf->iColortype == MNG_COLORTYPE_GRAY ) &&
+ (iColortype != MNG_COLORTYPE_GRAY ) &&
+ (iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (iColortype != MNG_COLORTYPE_RGB ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_GRAYA ) &&
+ (iColortype != MNG_COLORTYPE_GRAYA ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_RGB ) &&
+ (iColortype != MNG_COLORTYPE_RGB ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_RGBA ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) ) ||
+#ifdef MNG_INCLUDE_JNG
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY ) &&
+ (iColortype != MNG_COLORTYPE_JPEGGRAY ) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (iColortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR ) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA ) &&
+ (iColortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLORA) &&
+ (iColortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+#endif
+ ((pBuf->iColortype == MNG_COLORTYPE_INDEXED ) &&
+ (iColortype != MNG_COLORTYPE_INDEXED ) &&
+ (iColortype != MNG_COLORTYPE_RGB ) &&
+ (iColortype != MNG_COLORTYPE_RGBA ) ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ iRetcode = mng_promote_imageobject (pData, pImage, iBitdepth, iColortype, iFilltype);
+#else
+ if (pData->iPROMbitdepth < pBuf->iBitdepth)
+ MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
+
+ if ( ((pBuf->iColortype == MNG_COLORTYPE_GRAY ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_GRAY ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_GRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_GRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_RGB ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGBA ) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_RGBA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGBA ) ) ||
+#ifdef MNG_INCLUDE_JNG
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGGRAY ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLOR ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGGRAYA ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+ ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLORA) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_JPEGCOLORA) ) ||
+#endif
+ ((pBuf->iColortype == MNG_COLORTYPE_INDEXED ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_INDEXED ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGB ) &&
+ (pData->iPROMcolortype != MNG_COLORTYPE_RGBA ) ) )
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+ iRetcode = mng_promote_imageobject (pData, pImage, pData->iPROMbitdepth,
+ pData->iPROMcolortype, pData->iPROMfilltype);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_process_display_ipng (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IPNG, MNG_LC_START);
+#endif
+ /* indicate it for what it is now */
+ pData->iDeltaImagetype = MNG_IMAGETYPE_PNG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_ijng (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IJNG, MNG_LC_START);
+#endif
+ /* indicate it for what it is now */
+ pData->iDeltaImagetype = MNG_IMAGETYPE_JNG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_pplt (mng_datap pData,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_palette8ep paIndexentries,
+ mng_uint8p paAlphaentries,
+ mng_uint8p paUsedentries)
+#else
+mng_retcode mng_process_display_pplt (mng_datap pData)
+#endif
+{
+ mng_uint32 iX;
+ mng_imagep pImage = (mng_imagep)pData->pObjzero;
+ mng_imagedatap pBuf = pImage->pImgbuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PPLT, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iX = iCount;
+#else
+ iX = pData->iPPLTcount;
+#endif
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iType)
+#else
+ switch (pData->iPPLTtype)
+#endif
+ {
+ case MNG_DELTATYPE_REPLACERGB :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed = paIndexentries [iX].iRed;
+ pBuf->aPLTEentries [iX].iGreen = paIndexentries [iX].iGreen;
+ pBuf->aPLTEentries [iX].iBlue = paIndexentries [iX].iBlue;
+ }
+#else
+ if (pData->paPPLTusedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed = pData->paPPLTindexentries [iX].iRed;
+ pBuf->aPLTEentries [iX].iGreen = pData->paPPLTindexentries [iX].iGreen;
+ pBuf->aPLTEentries [iX].iBlue = pData->paPPLTindexentries [iX].iBlue;
+ }
+#endif
+ }
+
+ break;
+ }
+ case MNG_DELTATYPE_DELTARGB :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iRed +
+ paIndexentries [iX].iRed );
+ pBuf->aPLTEentries [iX].iGreen =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iGreen +
+ paIndexentries [iX].iGreen);
+ pBuf->aPLTEentries [iX].iBlue =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iBlue +
+ paIndexentries [iX].iBlue );
+ }
+#else
+ if (pData->paPPLTusedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iRed +
+ pData->paPPLTindexentries [iX].iRed );
+ pBuf->aPLTEentries [iX].iGreen =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iGreen +
+ pData->paPPLTindexentries [iX].iGreen);
+ pBuf->aPLTEentries [iX].iBlue =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iBlue +
+ pData->paPPLTindexentries [iX].iBlue );
+ }
+#endif
+ }
+
+ break;
+ }
+ case MNG_DELTATYPE_REPLACEALPHA :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ pBuf->aTRNSentries [iX] = paAlphaentries [iX];
+ }
+#else
+ if (pData->paPPLTusedentries [iX])
+ pBuf->aTRNSentries [iX] = pData->paPPLTalphaentries [iX];
+ }
+#endif
+
+ break;
+ }
+ case MNG_DELTATYPE_DELTAALPHA :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ pBuf->aTRNSentries [iX] =
+ (mng_uint8)(pBuf->aTRNSentries [iX] +
+ paAlphaentries [iX]);
+#else
+ if (pData->paPPLTusedentries [iX])
+ pBuf->aTRNSentries [iX] =
+ (mng_uint8)(pBuf->aTRNSentries [iX] +
+ pData->paPPLTalphaentries [iX]);
+#endif
+ }
+
+ break;
+ }
+ case MNG_DELTATYPE_REPLACERGBA :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed = paIndexentries [iX].iRed;
+ pBuf->aPLTEentries [iX].iGreen = paIndexentries [iX].iGreen;
+ pBuf->aPLTEentries [iX].iBlue = paIndexentries [iX].iBlue;
+ pBuf->aTRNSentries [iX] = paAlphaentries [iX];
+ }
+#else
+ if (pData->paPPLTusedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed = pData->paPPLTindexentries [iX].iRed;
+ pBuf->aPLTEentries [iX].iGreen = pData->paPPLTindexentries [iX].iGreen;
+ pBuf->aPLTEentries [iX].iBlue = pData->paPPLTindexentries [iX].iBlue;
+ pBuf->aTRNSentries [iX] = pData->paPPLTalphaentries [iX];
+ }
+#endif
+ }
+
+ break;
+ }
+ case MNG_DELTATYPE_DELTARGBA :
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (; iX > 0;iX--)
+#else
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = 0; iX < iCount; iX++)
+#else
+ for (iX = 0; iX < pData->iPPLTcount; iX++)
+#endif
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (paUsedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iRed +
+ paIndexentries [iX].iRed );
+ pBuf->aPLTEentries [iX].iGreen =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iGreen +
+ paIndexentries [iX].iGreen);
+ pBuf->aPLTEentries [iX].iBlue =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iBlue +
+ paIndexentries [iX].iBlue );
+ pBuf->aTRNSentries [iX] =
+ (mng_uint8)(pBuf->aTRNSentries [iX] +
+ paAlphaentries [iX]);
+ }
+#else
+ if (pData->paPPLTusedentries [iX])
+ {
+ pBuf->aPLTEentries [iX].iRed =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iRed +
+ pData->paPPLTindexentries [iX].iRed );
+ pBuf->aPLTEentries [iX].iGreen =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iGreen +
+ pData->paPPLTindexentries [iX].iGreen);
+ pBuf->aPLTEentries [iX].iBlue =
+ (mng_uint8)(pBuf->aPLTEentries [iX].iBlue +
+ pData->paPPLTindexentries [iX].iBlue );
+ pBuf->aTRNSentries [iX] =
+ (mng_uint8)(pBuf->aTRNSentries [iX] +
+ pData->paPPLTalphaentries [iX]);
+ }
+#endif
+ }
+
+ break;
+ }
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((iType != MNG_DELTATYPE_REPLACERGB) && (iType != MNG_DELTATYPE_DELTARGB))
+#else
+ if ((pData->iPPLTtype != MNG_DELTATYPE_REPLACERGB) &&
+ (pData->iPPLTtype != MNG_DELTATYPE_DELTARGB ) )
+#endif
+ {
+ if (pBuf->bHasTRNS)
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iCount > pBuf->iTRNScount)
+ pBuf->iTRNScount = iCount;
+#else
+ if (pData->iPPLTcount > pBuf->iTRNScount)
+ pBuf->iTRNScount = pData->iPPLTcount;
+#endif
+ }
+ else
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pBuf->iTRNScount = iCount;
+ pBuf->bHasTRNS = MNG_TRUE;
+#else
+ pBuf->iTRNScount = pData->iPPLTcount;
+ pBuf->bHasTRNS = MNG_TRUE;
+#endif
+ }
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if ((iType != MNG_DELTATYPE_REPLACEALPHA) && (iType != MNG_DELTATYPE_DELTAALPHA))
+#else
+ if ((pData->iPPLTtype != MNG_DELTATYPE_REPLACEALPHA) &&
+ (pData->iPPLTtype != MNG_DELTATYPE_DELTAALPHA ) )
+#endif
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iCount > pBuf->iPLTEcount)
+ pBuf->iPLTEcount = iCount;
+#else
+ if (pData->iPPLTcount > pBuf->iPLTEcount)
+ pBuf->iPLTEcount = pData->iPPLTcount;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_magn (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint8 iMethodY)
+#else
+mng_retcode mng_process_display_magn (mng_datap pData)
+#endif
+{
+ mng_uint16 iX;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_START);
+#endif
+ /* iterate the object-ids */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ for (iX = iFirstid; iX <= iLastid; iX++)
+#else
+ for (iX = pData->iMAGNfirstid; iX <= pData->iMAGNlastid; iX++)
+#endif
+ {
+ if (iX == 0) /* process object 0 ? */
+ {
+ pImage = (mng_imagep)pData->pObjzero;
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iMAGN_MethodX = iMethodX;
+ pImage->iMAGN_MethodY = iMethodY;
+ pImage->iMAGN_MX = iMX;
+ pImage->iMAGN_MY = iMY;
+ pImage->iMAGN_ML = iML;
+ pImage->iMAGN_MR = iMR;
+ pImage->iMAGN_MT = iMT;
+ pImage->iMAGN_MB = iMB;
+#else
+ pImage->iMAGN_MethodX = pData->iMAGNmethodX;
+ pImage->iMAGN_MethodY = pData->iMAGNmethodY;
+ pImage->iMAGN_MX = pData->iMAGNmX;
+ pImage->iMAGN_MY = pData->iMAGNmY;
+ pImage->iMAGN_ML = pData->iMAGNmL;
+ pImage->iMAGN_MR = pData->iMAGNmR;
+ pImage->iMAGN_MT = pData->iMAGNmT;
+ pImage->iMAGN_MB = pData->iMAGNmB;
+#endif
+ }
+ else
+ {
+ pImage = mng_find_imageobject (pData, iX);
+ /* object exists & is not frozen ? */
+ if ((pImage) && (!pImage->bFrozen))
+ { /* previous magnification to be done ? */
+ if ((pImage->iMAGN_MethodX) || (pImage->iMAGN_MethodY))
+ {
+ mng_retcode iRetcode = mng_magnify_imageobject (pData, pImage);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pImage->iMAGN_MethodX = iMethodX;
+ pImage->iMAGN_MethodY = iMethodY;
+ pImage->iMAGN_MX = iMX;
+ pImage->iMAGN_MY = iMY;
+ pImage->iMAGN_ML = iML;
+ pImage->iMAGN_MR = iMR;
+ pImage->iMAGN_MT = iMT;
+ pImage->iMAGN_MB = iMB;
+#else
+ pImage->iMAGN_MethodX = pData->iMAGNmethodX;
+ pImage->iMAGN_MethodY = pData->iMAGNmethodY;
+ pImage->iMAGN_MX = pData->iMAGNmX;
+ pImage->iMAGN_MY = pData->iMAGNmY;
+ pImage->iMAGN_ML = pData->iMAGNmL;
+ pImage->iMAGN_MR = pData->iMAGNmR;
+ pImage->iMAGN_MT = pData->iMAGNmT;
+ pImage->iMAGN_MB = pData->iMAGNmB;
+#endif
+ }
+ }
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iMAGNfromid = iFirstid;
+ pData->iMAGNtoid = iLastid;
+ iX = iFirstid;
+#else
+ pData->iMAGNfromid = pData->iMAGNfirstid;
+ pData->iMAGNtoid = pData->iMAGNlastid;
+ iX = pData->iMAGNfirstid;
+#endif
+ /* iterate again for showing */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ while ((iX <= iLastid) && (!pData->bTimerset))
+#else
+ while ((iX <= pData->iMAGNlastid) && (!pData->bTimerset))
+#endif
+ {
+ pData->iMAGNcurrentid = iX;
+
+ if (iX) /* only real objects ! */
+ {
+ pImage = mng_find_imageobject (pData, iX);
+ /* object exists & is not frozen &
+ is visible & is viewable ? */
+ if ((pImage) && (!pImage->bFrozen) &&
+ (pImage->bVisible) && (pImage->bViewable))
+ {
+ mng_retcode iRetcode = mng_display_image (pData, pImage, MNG_FALSE);
+ if (iRetcode)
+ return iRetcode;
+ }
+ }
+
+ iX++;
+ }
+
+ if (pData->bTimerset) /* broken ? */
+ pData->iBreakpoint = 9;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display_magn2 (mng_datap pData)
+{
+ mng_uint16 iX;
+ mng_imagep pImage;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_START);
+#endif
+
+ iX = pData->iMAGNcurrentid;
+ /* iterate again for showing */
+ while ((iX <= pData->iMAGNtoid) && (!pData->bTimerset))
+ {
+ pData->iMAGNcurrentid = iX;
+
+ if (iX) /* only real objects ! */
+ {
+ pImage = mng_find_imageobject (pData, iX);
+ /* object exists & is not frozen &
+ is visible & is viewable ? */
+ if ((pImage) && (!pImage->bFrozen) &&
+ (pImage->bVisible) && (pImage->bViewable))
+ {
+ mng_retcode iRetcode = mng_display_image (pData, pImage, MNG_FALSE);
+ if (iRetcode)
+ return iRetcode;
+ }
+ }
+
+ iX++;
+ }
+
+ if (pData->bTimerset) /* broken ? */
+ pData->iBreakpoint = 9;
+ else
+ pData->iBreakpoint = 0; /* not again ! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+mng_retcode mng_process_display_past (mng_datap pData,
+ mng_uint16 iTargetid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount,
+ mng_ptr pSources)
+#else
+mng_retcode mng_process_display_past (mng_datap pData)
+#endif
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+ mng_imagep pTargetimg;
+ mng_imagep pSourceimg;
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ mng_past_sourcep pSource = (mng_past_sourcep)pSources;
+#else
+ mng_past_sourcep pSource = (mng_past_sourcep)pData->pPASTsources;
+#endif
+ mng_uint32 iX = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PAST, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (iTargetid) /* a real destination object ? */
+#else
+ if (pData->iPASTtargetid) /* a real destination object ? */
+#endif
+ { /* let's find it then */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pTargetimg = (mng_imagep)mng_find_imageobject (pData, iTargetid);
+#else
+ pTargetimg = (mng_imagep)mng_find_imageobject (pData, pData->iPASTtargetid);
+#endif
+
+ if (!pTargetimg) /* if it doesn't exists; do a barf */
+ MNG_ERROR (pData, MNG_OBJECTUNKNOWN);
+ /* it's gotta be abstract !!! */
+ if (pTargetimg->pImgbuf->bConcrete)
+ MNG_ERROR (pData, MNG_OBJNOTABSTRACT);
+ /* we want 32-/64-bit RGBA to play with ! */
+ if ((pTargetimg->pImgbuf->iBitdepth <= MNG_BITDEPTH_8) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_GRAY) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_RGB) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_INDEXED) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_GRAYA) )
+ iRetcode = mng_promote_imageobject (pData, pTargetimg, MNG_BITDEPTH_8,
+ MNG_COLORTYPE_RGBA,
+ MNG_FILLMETHOD_LEFTBITREPLICATE);
+ else
+ if ((pTargetimg->pImgbuf->iBitdepth > MNG_BITDEPTH_8) &&
+ ((pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_GRAY) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_RGB) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_GRAYA) ) )
+ iRetcode = mng_promote_imageobject (pData, pTargetimg, MNG_BITDEPTH_16,
+ MNG_COLORTYPE_RGBA,
+ MNG_FILLMETHOD_LEFTBITREPLICATE);
+#ifdef MNG_INCLUDE_JNG
+ else
+ if ((pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_JPEGGRAY) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_JPEGCOLOR) ||
+ (pTargetimg->pImgbuf->iColortype == MNG_COLORTYPE_JPEGGRAYA) )
+ iRetcode = mng_promote_imageobject (pData, pTargetimg,
+ pTargetimg->pImgbuf->iBitdepth,
+ MNG_COLORTYPE_JPEGCOLORA,
+ MNG_FILLMETHOD_LEFTBITREPLICATE);
+#endif
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* make it really abstract ? */
+ if (!pTargetimg->pImgbuf->bCorrected)
+ {
+ iRetcode = mng_colorcorrect_object (pData, pTargetimg);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+ else
+ { /* pasting into object 0 !!! */
+ pTargetimg = (mng_imagep)pData->pObjzero;
+ /* is it usable ??? */
+ if ((pTargetimg->bClipped) &&
+ (pTargetimg->iClipr > pTargetimg->iPosx) &&
+ (pTargetimg->iClipb > pTargetimg->iPosy))
+ {
+ /* make it 32-bit RGBA please !!! */
+ iRetcode = mng_reset_object_details (pData, pTargetimg,
+ pTargetimg->iClipr - pTargetimg->iPosx,
+ pTargetimg->iClipb - pTargetimg->iPosy,
+ MNG_BITDEPTH_8, MNG_COLORTYPE_RGBA,
+ 0, 0, 0, MNG_FALSE);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ pTargetimg = MNG_NULL; /* clipped beyond visibility ! */
+ }
+
+ if (pTargetimg) /* usable destination ? */
+ {
+ mng_int32 iSourceY;
+ mng_int32 iSourceYinc;
+ mng_int32 iSourcerowsize;
+ mng_int32 iSourcesamples;
+ mng_bool bSourceRGBA16;
+ mng_int32 iTargetY;
+ mng_int32 iTargetrowsize;
+ mng_int32 iTargetsamples;
+ mng_bool bTargetRGBA16 = MNG_FALSE;
+ mng_int32 iTemprowsize;
+ mng_imagedatap pBuf;
+#ifndef MNG_SKIPCHUNK_MAGN
+ /* needs magnification ? */
+ if ((pTargetimg->iMAGN_MethodX) || (pTargetimg->iMAGN_MethodY))
+ iRetcode = mng_magnify_imageobject (pData, pTargetimg);
+#endif
+
+ if (!iRetcode) /* still ok ? */
+ {
+ bTargetRGBA16 = (mng_bool)(pTargetimg->pImgbuf->iBitdepth > 8);
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ switch (iTargettype) /* determine target x/y */
+#else
+ switch (pData->iPASTtargettype) /* determine target x/y */
+#endif
+ {
+ case 0 : {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iPastx = iTargetx;
+ pData->iPasty = iTargety;
+#else
+ pData->iPastx = pData->iPASTtargetx;
+ pData->iPasty = pData->iPASTtargety;
+#endif
+ break;
+ }
+
+ case 1 : {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iPastx = pTargetimg->iPastx + iTargetx;
+ pData->iPasty = pTargetimg->iPasty + iTargety;
+#else
+ pData->iPastx = pTargetimg->iPastx + pData->iPASTtargetx;
+ pData->iPasty = pTargetimg->iPasty + pData->iPASTtargety;
+#endif
+ break;
+ }
+
+ case 2 : {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iPastx += iTargetx;
+ pData->iPasty += iTargety;
+#else
+ pData->iPastx += pData->iPASTtargetx;
+ pData->iPasty += pData->iPASTtargety;
+#endif
+ break;
+ }
+ }
+ /* save for next time ... */
+ pTargetimg->iPastx = pData->iPastx;
+ pTargetimg->iPasty = pData->iPasty;
+ /* address destination for row-routines */
+ pData->pStoreobj = (mng_objectp)pTargetimg;
+ pData->pStorebuf = (mng_objectp)pTargetimg->pImgbuf;
+ }
+ /* process the sources one by one */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ while ((!iRetcode) && (iX < iCount))
+#else
+ while ((!iRetcode) && (iX < pData->iPASTcount))
+#endif
+ { /* find the little bastards first */
+ pSourceimg = (mng_imagep)mng_find_imageobject (pData, pSource->iSourceid);
+ /* exists and viewable? */
+ if ((pSourceimg) && (pSourceimg->bViewable))
+ { /* needs magnification ? */
+#ifndef MNG_SKIPCHUNK_MAGN
+ if ((pSourceimg->iMAGN_MethodX) || (pSourceimg->iMAGN_MethodY))
+ iRetcode = mng_magnify_imageobject (pData, pSourceimg);
+#endif
+
+ if (!iRetcode) /* still ok ? */
+ {
+ pBuf = (mng_imagedatap)pSourceimg->pImgbuf;
+ /* address source for row-routines */
+ pData->pRetrieveobj = (mng_objectp)pSourceimg;
+
+ pData->iPass = -1; /* init row-processing variables */
+ pData->iRowinc = 1;
+ pData->iColinc = 1;
+ pData->iPixelofs = 0;
+ iSourcesamples = (mng_int32)pBuf->iWidth;
+ iSourcerowsize = pBuf->iRowsize;
+ bSourceRGBA16 = (mng_bool)(pBuf->iBitdepth > 8);
+ /* make sure the delta-routines do the right thing */
+ pData->iDeltatype = MNG_DELTATYPE_BLOCKPIXELREPLACE;
+
+ switch (pBuf->iColortype)
+ {
+ case 0 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = (mng_bool)(!pBuf->bHasTRNS);
+ break;
+ }
+
+ case 2 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = (mng_bool)(!pBuf->bHasTRNS);
+ break;
+ }
+
+
+ case 3 : { pData->fRetrieverow = (mng_fptr)mng_retrieve_idx8;
+ pData->bIsOpaque = (mng_bool)(!pBuf->bHasTRNS);
+ break;
+ }
+
+
+ case 4 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+
+ case 6 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_g8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+ case 10 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgb8;
+
+ pData->bIsOpaque = MNG_TRUE;
+ break;
+ }
+
+
+ case 12 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_ga8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+
+
+ case 14 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bSourceRGBA16)
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ else
+#endif
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+
+ pData->bIsOpaque = MNG_FALSE;
+ break;
+ }
+ }
+ /* determine scaling */
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_NO_DELTA_PNG
+ if ((!bSourceRGBA16) && (bTargetRGBA16))
+ pData->fScalerow = (mng_fptr)mng_scale_rgba8_rgba16;
+ else
+ if ((bSourceRGBA16) && (!bTargetRGBA16))
+ pData->fScalerow = (mng_fptr)mng_scale_rgba16_rgba8;
+ else
+#endif
+#endif
+ pData->fScalerow = MNG_NULL;
+
+ /* default no color-correction */
+ pData->fCorrectrow = MNG_NULL;
+
+#if defined(MNG_FULL_CMS) /* determine color-management routine */
+ iRetcode = mng_init_full_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_GAMMA_ONLY)
+ iRetcode = mng_init_gamma_only (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_APP_CMS)
+ iRetcode = mng_init_app_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#endif
+ }
+
+ if (!iRetcode) /* still ok ? */
+ {
+ pData->fFliprow = MNG_NULL; /* no flipping or tiling by default */
+ pData->fTilerow = MNG_NULL;
+ /* but perhaps we do have to ... */
+ switch (pSource->iOrientation)
+ {
+ case 2 : ;
+ case 4 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ pData->fFliprow = (mng_fptr)mng_flip_rgba16;
+ else
+#endif
+ pData->fFliprow = (mng_fptr)mng_flip_rgba8;
+ break;
+ }
+
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ pData->fTilerow = (mng_fptr)mng_tile_rgba16;
+ else
+#endif
+ pData->fTilerow = (mng_fptr)mng_tile_rgba8;
+ break;
+ }
+ }
+ /* determine composition routine */
+ /* note that we're abusing the delta-routine setup !!! */
+ switch (pSource->iComposition)
+ {
+ case 0 : { /* composite over */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ pData->fDeltarow = (mng_fptr)mng_composeover_rgba16;
+ else
+#endif
+ pData->fDeltarow = (mng_fptr)mng_composeover_rgba8;
+ break;
+ }
+
+ case 1 : { /* replace */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ pData->fDeltarow = (mng_fptr)mng_delta_rgba16_rgba16;
+ else
+#endif
+ pData->fDeltarow = (mng_fptr)mng_delta_rgba8_rgba8;
+ break;
+ }
+
+ case 2 : { /* composite under */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ pData->fDeltarow = (mng_fptr)mng_composeunder_rgba16;
+ else
+#endif
+ pData->fDeltarow = (mng_fptr)mng_composeunder_rgba8;
+ break;
+ }
+ }
+ /* determine offsets & clipping */
+ if (pSource->iOffsettype == 1)
+ {
+ pData->iDestl = pData->iPastx + pSource->iOffsetx;
+ pData->iDestt = pData->iPasty + pSource->iOffsety;
+ }
+ else
+ {
+ pData->iDestl = pSource->iOffsetx;
+ pData->iDestt = pSource->iOffsety;
+ }
+
+ pData->iDestr = (mng_int32)pTargetimg->pImgbuf->iWidth;
+ pData->iDestb = (mng_int32)pTargetimg->pImgbuf->iHeight;
+ /* take the source dimension into account ? */
+ if (pSource->iOrientation != 8)
+ {
+ pData->iDestr = MIN_COORD (pData->iDestr, pData->iDestl + (mng_int32)pBuf->iWidth);
+ pData->iDestb = MIN_COORD (pData->iDestb, pData->iDestt + (mng_int32)pBuf->iHeight);
+ }
+ /* source clipping */
+ if (pSource->iBoundarytype == 1)
+ {
+ if (pData->iDestl < pData->iPastx + pSource->iBoundaryl)
+ pData->iSourcel = pData->iPastx + pSource->iBoundaryl - pData->iDestl;
+ else
+ pData->iSourcel = 0;
+
+ if (pData->iDestt < pData->iPasty + pSource->iBoundaryt)
+ pData->iSourcet = pData->iPasty + pSource->iBoundaryt - pData->iDestt;
+ else
+ pData->iSourcet = 0;
+
+ pData->iDestl = MAX_COORD (pData->iDestl, pData->iPastx + pSource->iBoundaryl);
+ pData->iDestt = MAX_COORD (pData->iDestt, pData->iPasty + pSource->iBoundaryt);
+ pData->iDestr = MIN_COORD (pData->iDestr, pData->iPastx + pSource->iBoundaryr);
+ pData->iDestb = MIN_COORD (pData->iDestb, pData->iPasty + pSource->iBoundaryb);
+ }
+ else
+ {
+ if (pData->iDestl < pSource->iBoundaryl)
+ pData->iSourcel = pSource->iBoundaryl - pData->iDestl;
+ else
+ pData->iSourcel = 0;
+
+ if (pData->iDestt < pSource->iBoundaryt)
+ pData->iSourcet = pSource->iBoundaryt - pData->iDestt;
+ else
+ pData->iSourcet = 0;
+
+ pData->iDestl = MAX_COORD (pData->iDestl, pSource->iBoundaryl);
+ pData->iDestt = MAX_COORD (pData->iDestt, pSource->iBoundaryt);
+ pData->iDestr = MIN_COORD (pData->iDestr, pSource->iBoundaryr);
+ pData->iDestb = MIN_COORD (pData->iDestb, pSource->iBoundaryb);
+ }
+
+ if (pData->iSourcel) /* indent source ? */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16) /* abuse tiling routine to shift source-pixels */
+ pData->fTilerow = (mng_fptr)mng_tile_rgba16;
+ else
+#endif
+ pData->fTilerow = (mng_fptr)mng_tile_rgba8;
+ }
+ /* anything to display ? */
+ if ((pData->iDestl <= pData->iDestr) && (pData->iDestt <= pData->iDestb))
+ { /* init variables for the loop */
+ if ((pSource->iOrientation == 2) || (pSource->iOrientation == 6))
+ {
+ iSourceY = (mng_int32)pBuf->iHeight - 1 - pData->iSourcet;
+ iSourceYinc = -1;
+ }
+ else
+ {
+ iSourceY = pData->iSourcet;
+ iSourceYinc = 1;
+ }
+
+ iTargetY = pData->iDestt;
+ pData->iCol = pData->iDestl;
+
+ iTargetsamples = pData->iDestr - pData->iDestl;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (bTargetRGBA16)
+ iTargetrowsize = (iTargetsamples << 3);
+ else
+#endif
+ iTargetrowsize = (iTargetsamples << 2);
+
+ /* get temporary work-buffers */
+ if (iSourcerowsize > iTargetrowsize)
+ iTemprowsize = iSourcerowsize << 1;
+ else
+ iTemprowsize = iTargetrowsize << 1;
+ MNG_ALLOC (pData, pData->pRGBArow, iTemprowsize);
+ MNG_ALLOC (pData, pData->pWorkrow, iTemprowsize);
+
+ while ((!iRetcode) && (iTargetY < pData->iDestb))
+ { /* get a row */
+ pData->iRow = iSourceY;
+ pData->iRowsamples = iSourcesamples;
+ pData->iRowsize = iSourcerowsize;
+ pData->bIsRGBA16 = bSourceRGBA16;
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+ /* scale it (if necessary) */
+ if ((!iRetcode) && (pData->fScalerow))
+ iRetcode = ((mng_scalerow)pData->fScalerow) (pData);
+
+ pData->bIsRGBA16 = bTargetRGBA16;
+ /* color correction (if necessary) */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+ /* flipping (if necessary) */
+ if ((!iRetcode) && (pData->fFliprow))
+ iRetcode = ((mng_fliprow)pData->fFliprow) (pData);
+ /* tiling (if necessary) */
+ if ((!iRetcode) && (pData->fTilerow))
+ iRetcode = ((mng_tilerow)pData->fTilerow) (pData);
+
+ if (!iRetcode) /* and paste..... */
+ {
+ pData->iRow = iTargetY;
+ pData->iRowsamples = iTargetsamples;
+ pData->iRowsize = iTargetrowsize;
+ iRetcode = ((mng_deltarow)pData->fDeltarow) (pData);
+ }
+
+ iSourceY += iSourceYinc; /* and next line */
+
+ if (iSourceY < 0)
+ iSourceY = (mng_int32)pBuf->iHeight - 1;
+ else
+ if (iSourceY >= (mng_int32)pBuf->iHeight)
+ iSourceY = 0;
+
+ iTargetY++;
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREEX (pData, pData->pWorkrow, iTemprowsize);
+ MNG_FREEX (pData, pData->pRGBArow, iTemprowsize);
+ }
+
+#if defined(MNG_FULL_CMS) /* cleanup cms stuff */
+ if (!iRetcode)
+ iRetcode = mng_clear_cms (pData);
+#endif
+ }
+
+ pSource++; /* neeeeext */
+ iX++;
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ if (!iTargetid) /* did we paste into object 0 ? */
+#else
+ if (!pData->iPASTtargetid) /* did we paste into object 0 ? */
+#endif
+ { /* display it then ! */
+ iRetcode = mng_display_image (pData, pTargetimg, MNG_FALSE);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* target is visible & viewable ? */
+ if ((pTargetimg->bVisible) && (pTargetimg->bViewable))
+ {
+ iRetcode = mng_display_image (pData, pTargetimg, MNG_FALSE);
+ if (iRetcode)
+ return iRetcode;
+ }
+ }
+ }
+
+ if (pData->bTimerset) /* broken ? */
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ pData->iPASTid = iTargetid;
+#else
+ pData->iPASTid = pData->iPASTtargetid;
+#endif
+ pData->iBreakpoint = 11;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCHUNK_PAST */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_process_display_past2 (mng_datap pData)
+{
+ mng_retcode iRetcode;
+ mng_imagep pTargetimg;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PAST, MNG_LC_START);
+#endif
+
+ if (pData->iPASTid) /* a real destination object ? */
+ pTargetimg = (mng_imagep)mng_find_imageobject (pData, pData->iPASTid);
+ else /* otherwise object 0 */
+ pTargetimg = (mng_imagep)pData->pObjzero;
+
+ iRetcode = mng_display_image (pData, pTargetimg, MNG_FALSE);
+ if (iRetcode)
+ return iRetcode;
+
+ pData->iBreakpoint = 0; /* only once */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_DISPLAY_PAST, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCHUNK_PAST */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
diff --git a/Source/LibMNG/libmng_display.h b/Source/LibMNG/libmng_display.h
new file mode 100644
index 0000000..f394dd2
--- /dev/null
+++ b/Source/LibMNG/libmng_display.h
@@ -0,0 +1,343 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_display.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Display management (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the display managament routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - added JNG support stuff * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added support for delta-image processing * */
+/* * - added support for PPLT chunk processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added JDAA chunk * */
+/* * * */
+/* * 0.9.4 - 11/24/2000 - G.Juyn * */
+/* * - moved restore of object 0 to libmng_display * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added proposed change in handling of TERM- & if-delay * */
+/* * 1.0.5 - 10/20/2002 - G.Juyn * */
+/* * - fixed display of visible target of PAST operation * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P. * */
+/* * - added some SKIPCHUNK conditionals * */
+/* * * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_display_h_
+#define _libmng_display_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode mng_display_progressive_refresh (mng_datap pData,
+ mng_uint32 iInterval);
+
+/* ************************************************************************** */
+
+mng_retcode mng_reset_objzero (mng_datap pData);
+
+mng_retcode mng_display_image (mng_datap pData,
+ mng_imagep pImage,
+ mng_bool bLayeradvanced);
+
+mng_retcode mng_execute_delta_image (mng_datap pData,
+ mng_imagep pTarget,
+ mng_imagep pDelta);
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_display (mng_datap pData);
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+png_imgtype mng_png_imgtype (mng_uint8 colortype,
+ mng_uint8 bitdepth);
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+
+mng_retcode mng_process_display_ihdr (mng_datap pData);
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+mng_retcode mng_process_display_mpng (mng_datap pData);
+#endif
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+mng_retcode mng_process_display_ang (mng_datap pData);
+#endif
+
+mng_retcode mng_process_display_idat (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata);
+
+mng_retcode mng_process_display_iend (mng_datap pData);
+mng_retcode mng_process_display_mend (mng_datap pData);
+mng_retcode mng_process_display_mend2 (mng_datap pData);
+mng_retcode mng_process_display_defi (mng_datap pData);
+
+#ifndef MNG_SKIPCHUNK_BASI
+mng_retcode mng_process_display_basi (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_bool bHasalpha,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable);
+#endif
+
+#ifndef MNG_SKIPCHUNK_CLON
+mng_retcode mng_process_display_clon (mng_datap pData,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_bool bHasdonotshow,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy);
+mng_retcode mng_process_display_clon2 (mng_datap pData);
+#endif
+
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode mng_process_display_disc (mng_datap pData,
+ mng_uint32 iCount,
+ mng_uint16p pIds);
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+mng_retcode mng_process_display_fram (mng_datap pData,
+ mng_uint8 iFramemode,
+ mng_uint8 iChangedelay,
+ mng_uint32 iDelay,
+ mng_uint8 iChangetimeout,
+ mng_uint32 iTimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb);
+mng_retcode mng_process_display_fram2 (mng_datap pData);
+#endif
+
+#ifndef MNG_SKIPCHUNK_MOVE
+mng_retcode mng_process_display_move (mng_datap pData,
+ mng_uint16 iFromid,
+ mng_uint16 iToid,
+ mng_uint8 iMovetype,
+ mng_int32 iMovex,
+ mng_int32 iMovey);
+#endif
+
+#ifndef MNG_SKIPCHUNK_CLIP
+mng_retcode mng_process_display_clip (mng_datap pData,
+ mng_uint16 iFromid,
+ mng_uint16 iToid,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb);
+#endif
+
+#ifndef MNG_SKIPCHUNK_SHOW
+mng_retcode mng_process_display_show (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_process_display_save (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_process_display_seek (mng_datap pData);
+#endif
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_jhdr (mng_datap pData);
+
+mng_retcode mng_process_display_jdaa (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata);
+
+mng_retcode mng_process_display_jdat (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata);
+
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_process_display_dhdr (mng_datap pData,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky);
+
+mng_retcode mng_process_display_prom (mng_datap pData,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype);
+
+mng_retcode mng_process_display_ipng (mng_datap pData);
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_ijng (mng_datap pData);
+#endif
+
+mng_retcode mng_process_display_pplt (mng_datap pData,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_palette8ep paIndexentries,
+ mng_uint8p paAlphaentries,
+ mng_uint8p paUsedentries);
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_process_display_magn (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint8 iMethodY);
+mng_retcode mng_process_display_magn2 (mng_datap pData);
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_process_display_past (mng_datap pData,
+ mng_uint16 iTargetid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount,
+ mng_ptr pSources);
+mng_retcode mng_process_display_past2 (mng_datap pData);
+#endif
+
+#else /* MNG_OPTIMIZE_DISPLAYCALLS */
+
+mng_retcode mng_process_display_ihdr (mng_datap pData);
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+mng_retcode mng_process_display_mpng (mng_datap pData);
+#endif
+mng_retcode mng_process_display_idat (mng_datap pData);
+mng_retcode mng_process_display_iend (mng_datap pData);
+mng_retcode mng_process_display_mend (mng_datap pData);
+mng_retcode mng_process_display_mend2 (mng_datap pData);
+mng_retcode mng_process_display_defi (mng_datap pData);
+#ifndef MNG_SKIPCHUNK_BASI
+mng_retcode mng_process_display_basi (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+mng_retcode mng_process_display_clon (mng_datap pData);
+mng_retcode mng_process_display_clon2 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode mng_process_display_disc (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+mng_retcode mng_process_display_fram (mng_datap pData);
+mng_retcode mng_process_display_fram2 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_MOVE
+mng_retcode mng_process_display_move (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_CLIP
+mng_retcode mng_process_display_clip (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SHOW
+mng_retcode mng_process_display_show (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_process_display_save (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_process_display_seek (mng_datap pData);
+#endif
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_jhdr (mng_datap pData);
+mng_retcode mng_process_display_jdaa (mng_datap pData);
+mng_retcode mng_process_display_jdat (mng_datap pData);
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_process_display_dhdr (mng_datap pData);
+mng_retcode mng_process_display_prom (mng_datap pData);
+mng_retcode mng_process_display_ipng (mng_datap pData);
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_process_display_ijng (mng_datap pData);
+#endif
+mng_retcode mng_process_display_pplt (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_process_display_magn (mng_datap pData);
+mng_retcode mng_process_display_magn2 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_process_display_past (mng_datap pData);
+mng_retcode mng_process_display_past2 (mng_datap pData);
+#endif
+
+#endif /* MNG_OPTIMIZE_DISPLAYCALLS */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_display_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_dither.c b/Source/LibMNG/libmng_dither.c
new file mode 100644
index 0000000..e23850c
--- /dev/null
+++ b/Source/LibMNG/libmng_dither.c
@@ -0,0 +1,58 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_dither.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : Dithering routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the dithering routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_dither.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_dither_a_row (mng_datap pData,
+ mng_uint8p pRow)
+{
+
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
+
diff --git a/Source/LibMNG/libmng_dither.h b/Source/LibMNG/libmng_dither.h
new file mode 100644
index 0000000..d9217c0
--- /dev/null
+++ b/Source/LibMNG/libmng_dither.h
@@ -0,0 +1,45 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_dither.h copyright (c) 2000-2002 G.Juyn * */
+/* * version : 1.0.5 * */
+/* * * */
+/* * purpose : Dithering routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the dithering routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_dither_h_
+#define _libmng_dither_h_
+
+/* ************************************************************************** */
+
+mng_retcode mng_dither_a_row (mng_datap pData,
+ mng_uint8p pRow);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_dither_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_error.c b/Source/LibMNG/libmng_error.c
new file mode 100644
index 0000000..3a4da20
--- /dev/null
+++ b/Source/LibMNG/libmng_error.c
@@ -0,0 +1,326 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_error.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Error routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the general error handling routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - added error telltaling * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added errorstrings for delta-image processing * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed up punctuation (contributed by Tim Rowley) * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added errorstring for delayed buffer-processing * */
+/* * * */
+/* * 0.9.1 - 07/06/2000 - G.Juyn * */
+/* * - added MNG_NEEDTIMERWAIT errorstring * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added NEEDSECTIONWAIT errorstring * */
+/* * - added macro + routine to set returncode without * */
+/* * calling error callback * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - added errorstring for updatemngheader if not a MNG * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/09/2000 - G.Juyn * */
+/* * - added check for simplicity-bits in MHDR * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - fixed processing of unknown critical chunks * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - added errorcode for delayed delta-processing * */
+/* * * */
+/* * 0.9.4 - 01/18/2001 - G.Juyn * */
+/* * - added errorcode for MAGN methods * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * * */
+/* * 1.0.5 - 07/04/2002 - G.Juyn * */
+/* * - added errorcode for extreme chunk-sizes * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - warnings are ignored by default now! * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added check for TERM placement during create/write * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G. R-P * */
+/* * - added MNG_SKIPCHUNK_CHNK, MNG_NO_DELTA_PNG reductions. * */
+/* * - skipped more code when MNG_INCLUDE_JNG is not enabled. * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditional around evNT chunk support * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - fixed typo on SKIPCHUNK_evNT (->PAST) * */
+/* * * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ERROR_STRINGS
+MNG_LOCAL mng_error_entry const error_table [] =
+ {
+ {MNG_NOERROR, "No error"},
+ {MNG_OUTOFMEMORY, "Out of memory"},
+ {MNG_INVALIDHANDLE, "The handle is invalid"},
+ {MNG_NOCALLBACK, "A required callback is not defined"},
+ {MNG_UNEXPECTEDEOF, "Encountered unexpected end-of-file"},
+ {MNG_ZLIBERROR, "zlib encountered an error"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_JPEGERROR, "ijgsrc6b encountered an error"},
+#endif
+ {MNG_LCMSERROR, "lcms encountered an error"},
+ {MNG_NOOUTPUTPROFILE, "No output-profile defined for CMS"},
+ {MNG_NOSRGBPROFILE, "No sRGB-profile defined for CMS"},
+ {MNG_BUFOVERFLOW, "Internal buffer-overflow"},
+ {MNG_FUNCTIONINVALID, "Function is invalid at this point"},
+ {MNG_OUTPUTERROR, "Writing was unsuccessful; disk full?"},
+ {MNG_JPEGBUFTOOSMALL, "Internal buffer for JPEG processing too small"},
+ {MNG_NEEDMOREDATA, "Reading suspended; waiting for I/O to catch up"},
+ {MNG_NEEDTIMERWAIT, "Timer suspension; normal animation delay"},
+ {MNG_NEEDSECTIONWAIT, "SEEK suspension; application decides"},
+ {MNG_LOOPWITHCACHEOFF, "LOOP encountered when playback cache is turned off"},
+
+ {MNG_APPIOERROR, "Application signalled I/O error"},
+ {MNG_APPTIMERERROR, "Application signalled timing error"},
+ {MNG_APPCMSERROR, "Application signalled CMS error"},
+ {MNG_APPMISCERROR, "Application signalled an error"},
+ {MNG_APPTRACEABORT, "Application signalled error during trace-callback"},
+
+ {MNG_INTERNALERROR, "Internal error in libmng"},
+
+ {MNG_INVALIDSIG, "The signature is invalid"},
+ {MNG_INVALIDCRC, "The CRC for this chunk is invalid"},
+ {MNG_INVALIDLENGTH, "Chunk-length is invalid"},
+ {MNG_SEQUENCEERROR, "Chunk out of sequence"},
+ {MNG_CHUNKNOTALLOWED, "Chunk not allowed at this point"},
+ {MNG_MULTIPLEERROR, "Chunk cannot occur multiple times"},
+ {MNG_PLTEMISSING, "Missing PLTE chunk"},
+ {MNG_IDATMISSING, "Missing IDAT chunk(s)"},
+ {MNG_CANNOTBEEMPTY, "Chunk cannot be empty"},
+ {MNG_GLOBALLENGTHERR, "Global data length invalid"},
+ {MNG_INVALIDBITDEPTH, "The bit_depth is invalid"},
+ {MNG_INVALIDCOLORTYPE, "The color_type is invalid"},
+ {MNG_INVALIDCOMPRESS, "The compression_method is invalid"},
+ {MNG_INVALIDFILTER, "The filter_method or filter_type is invalid"},
+ {MNG_INVALIDINTERLACE, "The interlace_method is invalid"},
+ {MNG_NOTENOUGHIDAT, "There is not enough data in the IDAT chunk(s)"},
+ {MNG_PLTEINDEXERROR, "Palette-index out of bounds"},
+ {MNG_NULLNOTFOUND, "NULL separator not found"},
+ {MNG_KEYWORDNULL, "Keyword cannot be zero-length"},
+ {MNG_OBJECTUNKNOWN, "Object does not exist"},
+ {MNG_OBJECTEXISTS, "Object already exists"},
+ {MNG_TOOMUCHIDAT, "Too much data in IDAT chunk(s)"},
+ {MNG_INVSAMPLEDEPTH, "The sample_depth is invalid"},
+ {MNG_INVOFFSETSIZE, "The offset_type is invalid"},
+ {MNG_INVENTRYTYPE, "The entry_type is invalid"},
+ {MNG_ENDWITHNULL, "Chunk must not end with NULL byte"},
+ {MNG_INVIMAGETYPE, "The image_type is invalid"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_INVDELTATYPE, "The delta_type is invalid"},
+#endif
+ {MNG_INVALIDINDEX, "Index-value out of bounds"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_TOOMUCHJDAT, "Too much data in JDAT chunk(s)"},
+ {MNG_JPEGPARMSERR, "JHDR parameters & JFIF-data do not match"},
+#endif
+ {MNG_INVFILLMETHOD, "The fill_method is invalid"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_OBJNOTCONCRETE, "Target object for DHDR must be concrete"},
+#endif
+ {MNG_TARGETNOALPHA, "Target object must have alpha-channel"},
+ {MNG_MNGTOOCOMPLEX, "MHDR simplicity indicates unsupported feature(s)"},
+ {MNG_UNKNOWNCRITICAL, "Unknown critical chunk encountered"},
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_UNSUPPORTEDNEED, "Requested nEED resources are not supported"},
+#endif
+ {MNG_INVALIDDELTA, "The delta operation is invalid (mismatched color_types?)"},
+ {MNG_INVALIDMETHOD, "Method is invalid"},
+ {MNG_IMPROBABLELENGTH, "Chunklength is incredibly large"},
+ {MNG_INVALIDBLOCK, "Delta block width and or height invalid"},
+ {MNG_INVALIDEVENT, "Event type is invalid"},
+ {MNG_INVALIDMASK, "Mask type is invalid"},
+ {MNG_NOMATCHINGLOOP, "ENDL without matching LOOP"},
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_SEEKNOTFOUND, "evNT points to unknown SEEK"},
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_OBJNOTABSTRACT, "Destination object for PAST must be abstract"},
+#endif
+ {MNG_TERMSEQERROR, "TERM misplaced during creation of MNG stream"},
+ {MNG_INVALIDFIELDVAL, "invalid fieldvalue (generic)"},
+ {MNG_INVALIDWIDTH, "invalid frame/image width"},
+ {MNG_INVALIDHEIGHT, "invalid frame/image height"},
+
+ {MNG_INVALIDCNVSTYLE, "Canvas_style is invalid"},
+ {MNG_WRONGCHUNK, "Attempt to access the wrong chunk"},
+ {MNG_INVALIDENTRYIX, "Attempt to access an non-existing entry"},
+ {MNG_NOHEADER, "No valid header-chunk"},
+ {MNG_NOCORRCHUNK, "Parent chunk not found"},
+ {MNG_NOMHDR, "No MNG header (MHDR) found"},
+
+ {MNG_IMAGETOOLARGE, "Image is larger than defined maximum"},
+ {MNG_NOTANANIMATION, "Image is not an animation"},
+ {MNG_FRAMENRTOOHIGH, "Framenr out of bounds"},
+ {MNG_LAYERNRTOOHIGH, "Layernr out of bounds"},
+ {MNG_PLAYTIMETOOHIGH, "Playtime out of bounds"},
+ {MNG_FNNOTIMPLEMENTED, "Function not yet implemented"},
+ {MNG_IMAGEFROZEN, "Image is frozen"},
+
+ {MNG_LCMS_NOHANDLE, "Handle could not be initialized"},
+ {MNG_LCMS_NOMEM, "No memory for gamma-table(s)"},
+ {MNG_LCMS_NOTRANS, "Transformation could not be initialized"}
+ };
+#endif /* MNG_INCLUDE_ERROR_STRINGS */
+
+/* ************************************************************************** */
+
+mng_bool mng_store_error (mng_datap pData,
+ mng_retcode iError,
+ mng_retcode iExtra1,
+ mng_retcode iExtra2)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (pData, MNG_FN_STORE_ERROR, MNG_LC_START);
+#endif
+
+ if (pData != 0)
+ {
+ pData->iErrorcode = iError; /* save also for getlasterror */
+ pData->iErrorx1 = iExtra1;
+ pData->iErrorx2 = iExtra2;
+
+#ifdef MNG_INCLUDE_ERROR_STRINGS
+ { /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ mng_error_entryp pEntry; /* pointer to found entry */
+ /* determine max index of table */
+ iTop = (sizeof (error_table) / sizeof (error_table [0])) - 1;
+
+ iLower = 0; /* initialize binary search */
+ iMiddle = iTop >> 1; /* start in the middle */
+ iUpper = iTop;
+ pEntry = 0; /* no goods yet! */
+
+ do /* the binary search itself */
+ {
+ if (error_table [iMiddle].iError < iError)
+ iLower = iMiddle + 1;
+ else if (error_table [iMiddle].iError > iError)
+ iUpper = iMiddle - 1;
+ else
+ {
+ pEntry = &error_table [iMiddle];
+ break;
+ }
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+
+ if (pEntry) /* found it ? */
+ pData->zErrortext = pEntry->zErrortext;
+ else
+ pData->zErrortext = "Unknown error";
+ }
+#else /* MNG_INCLUDE_ERROR_STRINGS */
+ pData->zErrortext = 0;
+#endif /* MNG_INCLUDE_ERROR_STRINGS */
+
+ if (iError == 0) /* no error is not severe ! */
+ {
+ pData->iSeverity = 0;
+ }
+ else
+ {
+ switch (iError&0x3C00) /* determine the severity */
+ {
+ case 0x0800 : { pData->iSeverity = 5; break; }
+ case 0x1000 : { pData->iSeverity = 2; break; }
+ case 0x2000 : { pData->iSeverity = 1; break; }
+ default : { pData->iSeverity = 9; }
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (pData, MNG_FN_STORE_ERROR, MNG_LC_END);
+#endif
+
+ return MNG_TRUE;
+}
+
+/* ************************************************************************** */
+
+mng_bool mng_process_error (mng_datap pData,
+ mng_retcode iError,
+ mng_retcode iExtra1,
+ mng_retcode iExtra2)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (pData, MNG_FN_PROCESS_ERROR, MNG_LC_START);
+#endif
+
+ mng_store_error (pData, iError, iExtra1, iExtra2);
+
+ if ((pData != MNG_NULL) && (pData->iMagic == MNG_MAGIC))
+ {
+ if (pData->fErrorproc) /* callback defined ? */
+ return pData->fErrorproc (((mng_handle)pData), iError, pData->iSeverity,
+ pData->iChunkname, pData->iChunkseq,
+ pData->iErrorx1, pData->iErrorx2, pData->zErrortext);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (pData, MNG_FN_PROCESS_ERROR, MNG_LC_END);
+#endif
+
+ return MNG_TRUE; /* warnings are ignored by default ! */
+}
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_error.h b/Source/LibMNG/libmng_error.h
new file mode 100644
index 0000000..b49ff73
--- /dev/null
+++ b/Source/LibMNG/libmng_error.h
@@ -0,0 +1,119 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_error.h copyright (c) 2000-2002 G.Juyn * */
+/* * version : 1.0.5 * */
+/* * * */
+/* * purpose : Error functions (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the generic error-codes and functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - added some errorcodes * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - added some errorcodes * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added application errorcodes (used with callbacks) * */
+/* * - moved chunk-access errorcodes to severity 5 * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - added JNG errorcodes * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - added error tell-tale definition * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added errorcodes for delta-image processing * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added errorcode for delayed buffer-processing * */
+/* * - moved errorcodes to "libmng.h" * */
+/* * * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added macro + routine to set returncode without * */
+/* * calling error callback * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 08/20/2002 - G.Juyn * */
+/* * - added option for soft-handling of errors * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_error_h_
+#define _libmng_error_h_
+
+/* ************************************************************************** */
+/* * * */
+/* * Default error routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_bool mng_store_error (mng_datap pData,
+ mng_retcode iError,
+ mng_retcode iExtra1,
+ mng_retcode iExtra2);
+
+mng_bool mng_process_error (mng_datap pData,
+ mng_retcode iError,
+ mng_retcode iExtra1,
+ mng_retcode iExtra2);
+
+/* ************************************************************************** */
+/* * * */
+/* * Error handling macros * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_SOFTERRORS
+#define MNG_ERROR(D,C) { if (!mng_process_error (D, C, 0, 0)) return C; }
+#define MNG_ERRORZ(D,Z) { if (!mng_process_error (D, MNG_ZLIBERROR, Z, 0)) return MNG_ZLIBERROR; }
+#define MNG_ERRORJ(D,J) { if (!mng_process_error (D, MNG_JPEGERROR, J, 0)) return MNG_JPEGERROR; }
+#define MNG_ERRORL(D,L) { if (!mng_process_error (D, MNG_LCMSERROR, L, 0)) return MNG_LCMSERROR; }
+#else
+#define MNG_ERROR(D,C) { mng_process_error (D, C, 0, 0); return C; }
+#define MNG_ERRORZ(D,Z) { mng_process_error (D, MNG_ZLIBERROR, Z, 0); return MNG_ZLIBERROR; }
+#define MNG_ERRORJ(D,J) { mng_process_error (D, MNG_JPEGERROR, J, 0); return MNG_JPEGERROR; }
+#define MNG_ERRORL(D,L) { mng_process_error (D, MNG_LCMSERROR, L, 0); return MNG_LCMSERROR; }
+#endif
+
+#define MNG_RETURN(D,C) { mng_store_error (D, C, 0, 0); return C; }
+
+#define MNG_WARNING(D,C) { if (!mng_process_error (D, C, 0, 0)) return C; }
+
+#define MNG_VALIDHANDLE(H) { if ((H == 0) || (((mng_datap)H)->iMagic != MNG_MAGIC)) \
+ return MNG_INVALIDHANDLE; }
+#define MNG_VALIDHANDLEX(H) { if ((H == 0) || (((mng_datap)H)->iMagic != MNG_MAGIC)) \
+ return 0; }
+#define MNG_VALIDCB(D,C) { if (!((mng_datap)D)->C) \
+ MNG_ERROR (((mng_datap)D), MNG_NOCALLBACK) }
+
+/* ************************************************************************** */
+/* * * */
+/* * Error string-table entry * */
+/* * * */
+/* ************************************************************************** */
+
+typedef struct {
+ mng_retcode iError;
+ mng_pchar zErrortext;
+ } mng_error_entry;
+typedef mng_error_entry const * mng_error_entryp;
+
+/* ************************************************************************** */
+
+#endif /* _libmng_error_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_filter.c b/Source/LibMNG/libmng_filter.c
new file mode 100644
index 0000000..ed69a75
--- /dev/null
+++ b/Source/LibMNG/libmng_filter.c
@@ -0,0 +1,978 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_filter.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : Filtering routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the filtering routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * * */
+/* * 1.0.5 - 08/07/2002 - G.Juyn * */
+/* * - added test-option for PNG filter method 193 (=no filter) * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - reversed some loops to use decrementing counter * */
+/* * * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_filter.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_FILTERS
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode filter_sub (mng_datap pData)
+{
+ mng_uint32 iBpp;
+ mng_uint8p pRawx;
+ mng_uint8p pRawx_prev;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_SUB, MNG_LC_START);
+#endif
+
+ iBpp = pData->iFilterbpp;
+ pRawx = pData->pWorkrow + pData->iPixelofs + iBpp;
+ pRawx_prev = pData->pWorkrow + pData->iPixelofs;
+
+ for (iX = iBpp; iX < pData->iRowsize; iX++)
+ {
+ *pRawx = (mng_uint8)(*pRawx + *pRawx_prev);
+ pRawx++;
+ pRawx_prev++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_SUB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode filter_up (mng_datap pData)
+{
+ mng_uint8p pRawx;
+ mng_uint8p pPriorx;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_UP, MNG_LC_START);
+#endif
+
+ pRawx = pData->pWorkrow + pData->iPixelofs;
+ pPriorx = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsize - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsize; iX++)
+#endif
+ {
+ *pRawx = (mng_uint8)(*pRawx + *pPriorx);
+ pRawx++;
+ pPriorx++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_UP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode filter_average (mng_datap pData)
+{
+ mng_int32 iBpp;
+ mng_uint8p pRawx;
+ mng_uint8p pRawx_prev;
+ mng_uint8p pPriorx;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_AVERAGE, MNG_LC_START);
+#endif
+
+ iBpp = pData->iFilterbpp;
+ pRawx = pData->pWorkrow + pData->iPixelofs;
+ pPriorx = pData->pPrevrow + pData->iPixelofs;
+ pRawx_prev = pData->pWorkrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = iBpp - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < iBpp; iX++)
+#endif
+ {
+ *pRawx = (mng_uint8)(*pRawx + ((*pPriorx) >> 1));
+ pRawx++;
+ pPriorx++;
+ }
+
+ for (iX = iBpp; iX < pData->iRowsize; iX++)
+ {
+ *pRawx = (mng_uint8)(*pRawx + ((*pRawx_prev + *pPriorx) >> 1));
+ pRawx++;
+ pPriorx++;
+ pRawx_prev++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_AVERAGE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode filter_paeth (mng_datap pData)
+{
+ mng_int32 iBpp;
+ mng_uint8p pRawx;
+ mng_uint8p pRawx_prev;
+ mng_uint8p pPriorx;
+ mng_uint8p pPriorx_prev;
+ mng_int32 iX;
+ mng_uint32 iA, iB, iC;
+ mng_uint32 iP;
+ mng_uint32 iPa, iPb, iPc;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_PAETH, MNG_LC_START);
+#endif
+
+ iBpp = pData->iFilterbpp;
+ pRawx = pData->pWorkrow + pData->iPixelofs;
+ pPriorx = pData->pPrevrow + pData->iPixelofs;
+ pRawx_prev = pData->pWorkrow + pData->iPixelofs;
+ pPriorx_prev = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = iBpp - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < iBpp; iX++)
+#endif
+ {
+ *pRawx = (mng_uint8)(*pRawx + *pPriorx);
+
+ pRawx++;
+ pPriorx++;
+ }
+
+ for (iX = iBpp; iX < pData->iRowsize; iX++)
+ {
+ iA = (mng_uint32)*pRawx_prev;
+ iB = (mng_uint32)*pPriorx;
+ iC = (mng_uint32)*pPriorx_prev;
+ iP = iA + iB - iC;
+ iPa = abs (iP - iA);
+ iPb = abs (iP - iB);
+ iPc = abs (iP - iC);
+
+ if ((iPa <= iPb) && (iPa <= iPc))
+ *pRawx = (mng_uint8)(*pRawx + iA);
+ else
+ if (iPb <= iPc)
+ *pRawx = (mng_uint8)(*pRawx + iB);
+ else
+ *pRawx = (mng_uint8)(*pRawx + iC);
+
+ pRawx++;
+ pPriorx++;
+ pRawx_prev++;
+ pPriorx_prev++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_PAETH, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_filter_a_row (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_A_ROW, MNG_LC_START);
+#endif
+
+ switch (*(pData->pWorkrow + pData->iFilterofs))
+ {
+ case 1 : {
+ iRetcode = filter_sub (pData);
+ break;
+ }
+ case 2 : {
+ iRetcode = filter_up (pData);
+ break;
+ }
+ case 3 : {
+ iRetcode = filter_average (pData);
+ break;
+ }
+ case 4 : {
+ iRetcode = filter_paeth (pData);
+ break;
+ }
+
+ default : iRetcode = MNG_INVALIDFILTER;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FILTER_A_ROW, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef FILTER192
+mng_retcode mng_init_rowdiffering (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ROWDIFFERING, MNG_LC_START);
+#endif
+
+ if (pData->iFilter == 0xC0) /* has leveling parameters ? */
+ {
+ switch (pData->iColortype) /* salvage leveling parameters */
+ {
+ case 0 : { /* gray */
+ if (pData->iBitdepth <= 8)
+ pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
+ else
+ pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
+
+ break;
+ }
+ case 2 : { /* rgb */
+ if (pData->iBitdepth <= 8)
+ {
+ pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
+ pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
+ pData->iLevel2 = (mng_uint16)*(pData->pWorkrow+2);
+ }
+ else
+ {
+ pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
+ pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
+ pData->iLevel2 = mng_get_uint16 (pData->pWorkrow+4);
+ }
+
+ break;
+ }
+ case 3 : { /* indexed */
+ pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
+ break;
+ }
+ case 4 : { /* gray+alpha */
+ if (pData->iBitdepth <= 8)
+ {
+ pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
+ pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
+ }
+ else
+ {
+ pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
+ pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
+ }
+
+ break;
+ }
+ case 6 : { /* rgb+alpha */
+ if (pData->iBitdepth <= 8)
+ {
+ pData->iLevel0 = (mng_uint16)*pData->pWorkrow;
+ pData->iLevel1 = (mng_uint16)*(pData->pWorkrow+1);
+ pData->iLevel2 = (mng_uint16)*(pData->pWorkrow+2);
+ pData->iLevel3 = (mng_uint16)*(pData->pWorkrow+3);
+ }
+ else
+ {
+ pData->iLevel0 = mng_get_uint16 (pData->pWorkrow);
+ pData->iLevel1 = mng_get_uint16 (pData->pWorkrow+2);
+ pData->iLevel2 = mng_get_uint16 (pData->pWorkrow+4);
+ pData->iLevel3 = mng_get_uint16 (pData->pWorkrow+6);
+ }
+
+ break;
+ }
+ }
+ }
+ /* shift the entire row back in place */
+ pRawi = pData->pWorkrow + pData->iFilterofs;
+ pRawo = pData->pWorkrow;
+
+ for (iX = 0; iX < pData->iRowsize + pData->iPixelofs - pData->iFilterofs; iX++)
+ *pRawo++ = *pRawi++;
+
+ pData->iFilterofs = 0; /* indicate so ! */
+
+#ifdef FILTER193
+ if (pData->iFilter == 0xC1) /* no adaptive filtering ? */
+ pData->iPixelofs = pData->iFilterofs;
+ else
+#endif
+ pData->iPixelofs = pData->iFilterofs + 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ROWDIFFERING, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_g1 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G1, MNG_LC_START);
+#endif
+
+ if (pData->iLevel0 & 0x01) /* is it uneven level ? */
+ {
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ /* just invert every bit */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsize - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsize; iX++)
+#endif
+ *pRawo++ = (mng_uint8)(~(*pRawi++));
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_g2 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+ mng_int32 iC, iS;
+ mng_uint8 iB, iN, iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G2, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ iC = 0;
+ iB = 0;
+ iN = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iC)
+ {
+ iC = 4;
+ iB = *pRawi++;
+ iN = 0;
+ iS = 8;
+ }
+
+ iS -= 2;
+ iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x03);
+ iN = (mng_uint8)((iN << 2) + iQ);
+ iC--;
+
+ if (!iC)
+ *pRawo++ = iN;
+
+ }
+
+ if (iC)
+ *pRawo = (mng_uint8)(iN << iS);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_g4 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+ mng_int32 iC, iS;
+ mng_uint8 iB, iN, iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G4, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ iC = 0;
+ iB = 0;
+ iN = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iC)
+ {
+ iC = 2;
+ iB = *pRawi++;
+ iN = 0;
+ iS = 8;
+ }
+
+ iS -= 4;
+ iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x0F);
+ iN = (mng_uint8)((iN << 4) + iQ);
+ iC--;
+
+ if (!iC)
+ *pRawo++ = iN;
+
+ }
+
+ if (iC)
+ *pRawo = (mng_uint8)(iN << iS);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_g8 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G8, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRawo++ = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0) & 0xFF);
+
+ pRawi++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_g16 (mng_datap pData)
+{
+ mng_uint16p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G16, MNG_LC_START);
+#endif
+
+ pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
+ pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRawo++ = (mng_uint16)(((mng_uint32)*pRawi + (mng_uint32)pData->iLevel0) & 0xFFFF);
+
+ pRawi++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_rgb8 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGB8, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
+ *pRawo = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0 +
+ (mng_uint16)*(pRawo+1)) & 0xFF);
+ *(pRawo+2) = (mng_uint8)(((mng_uint16)*(pRawi+2) + pData->iLevel2 +
+ (mng_uint16)*(pRawo+1)) & 0xFF);
+
+ pRawi += 3;
+ pRawo += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_rgb16 (mng_datap pData)
+{
+ mng_uint16p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGB16, MNG_LC_START);
+#endif
+
+ pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
+ pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
+ *pRawo = (mng_uint16)(((mng_uint32)*pRawi + (mng_uint32)pData->iLevel0 +
+ (mng_uint32)*(pRawo+1)) & 0xFFFF);
+ *(pRawo+2) = (mng_uint16)(((mng_uint32)*(pRawi+2) + (mng_uint32)pData->iLevel2 +
+ (mng_uint32)*(pRawo+1)) & 0xFFFF);
+
+ pRawi += 3;
+ pRawo += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_idx1 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX1, MNG_LC_START);
+#endif
+
+ if (pData->iLevel0 & 0x01) /* is it uneven level ? */
+ {
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ /* just invert every bit */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsize - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsize; iX++)
+#endif
+ *pRawo++ = (mng_uint8)(~(*pRawi++));
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_idx2 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+ mng_int32 iC, iS;
+ mng_uint8 iB, iN, iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX2, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ iC = 0;
+ iB = 0;
+ iN = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iC)
+ {
+ iC = 4;
+ iB = *pRawi++;
+ iN = 0;
+ iS = 8;
+ }
+
+ iS -= 2;
+ iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x03);
+ iN = (mng_uint8)((iN << 2) + iQ);
+ iC--;
+
+ if (!iC)
+ *pRawo++ = iN;
+
+ }
+
+ if (iC)
+ *pRawo = (mng_uint8)(iN << iS);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_idx4 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+ mng_int32 iC, iS;
+ mng_uint8 iB, iN, iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX4, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+ iC = 0;
+ iB = 0;
+ iN = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iC)
+ {
+ iC = 2;
+ iB = *pRawi++;
+ iN = 0;
+ iS = 8;
+ }
+
+ iS -= 4;
+ iQ = (mng_uint8)(((iB >> iS) + pData->iLevel0) & 0x0F);
+ iN = (mng_uint8)((iN << 4) + iQ);
+ iC--;
+
+ if (!iC)
+ *pRawo++ = iN;
+
+ }
+
+ if (iC)
+ *pRawo = (mng_uint8)(iN << iS);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_idx8 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX8, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRawo++ = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0) & 0xFF);
+
+ pRawi++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_IDX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_ga8 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_GA8, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRawo = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0) & 0xFF);
+ *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
+
+ pRawi += 2;
+ pRawo += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_ga16 (mng_datap pData)
+{
+ mng_uint16p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_GA16, MNG_LC_START);
+#endif
+
+ pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
+ pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRawo = (mng_uint16)(((mng_uint32)*pRawi + (mng_uint32)pData->iLevel0) & 0xFFFF);
+ *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
+
+ pRawi += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_rgba8 (mng_datap pData)
+{
+ mng_uint8p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGBA8, MNG_LC_START);
+#endif
+
+ pRawi = pData->pWorkrow + pData->iPixelofs;
+ pRawo = pData->pPrevrow + pData->iPixelofs;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pRawo+1) = (mng_uint8)(((mng_uint16)*(pRawi+1) + pData->iLevel1) & 0xFF);
+ *pRawo = (mng_uint8)(((mng_uint16)*pRawi + pData->iLevel0 +
+ (mng_uint16)*(pRawo+1)) & 0xFF);
+ *(pRawo+2) = (mng_uint8)(((mng_uint16)*(pRawi+2) + pData->iLevel2 +
+ (mng_uint16)*(pRawo+1)) & 0xFF);
+ *(pRawo+3) = (mng_uint8)(((mng_uint16)*(pRawi+3) + pData->iLevel3) & 0xFF);
+
+ pRawi += 4;
+ pRawo += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_differ_rgba16 (mng_datap pData)
+{
+ mng_uint16p pRawi, pRawo;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGBA16, MNG_LC_START);
+#endif
+
+ pRawi = (mng_uint16p)(pData->pWorkrow + pData->iPixelofs);
+ pRawo = (mng_uint16p)(pData->pPrevrow + pData->iPixelofs);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples - 1; iX >= 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pRawo+1) = (mng_uint16)(((mng_uint32)*(pRawi+1) + (mng_uint32)pData->iLevel1) & 0xFFFF);
+ *pRawo = (mng_uint16)(((mng_uint32)*pRawi + (mng_uint32)pData->iLevel0 +
+ (mng_uint32)*(pRawo+1)) & 0xFFFF);
+ *(pRawo+2) = (mng_uint16)(((mng_uint32)*(pRawi+2) + (mng_uint32)pData->iLevel2 +
+ (mng_uint32)*(pRawo+1)) & 0xFFFF);
+ *(pRawo+3) = (mng_uint16)(((mng_uint32)*(pRawi+3) + (mng_uint32)pData->iLevel3) & 0xFFFF);
+
+ pRawi += 4;
+ pRawo += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DIFFER_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* FILTER192 */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_FILTERS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_filter.h b/Source/LibMNG/libmng_filter.h
new file mode 100644
index 0000000..9ac9c7f
--- /dev/null
+++ b/Source/LibMNG/libmng_filter.h
@@ -0,0 +1,69 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_filter.h copyright (c) 2000-2002 G.Juyn * */
+/* * version : 1.0.5 * */
+/* * * */
+/* * purpose : Filtering routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the filtering routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_filter_h_
+#define _libmng_filter_h_
+
+/* ************************************************************************** */
+
+mng_retcode mng_filter_a_row (mng_datap pData);
+
+/* ************************************************************************** */
+
+#ifdef FILTER192
+mng_retcode mng_init_rowdiffering (mng_datap pData);
+
+mng_retcode mng_differ_g1 (mng_datap pData);
+mng_retcode mng_differ_g2 (mng_datap pData);
+mng_retcode mng_differ_g4 (mng_datap pData);
+mng_retcode mng_differ_g8 (mng_datap pData);
+mng_retcode mng_differ_g16 (mng_datap pData);
+mng_retcode mng_differ_rgb8 (mng_datap pData);
+mng_retcode mng_differ_rgb16 (mng_datap pData);
+mng_retcode mng_differ_idx1 (mng_datap pData);
+mng_retcode mng_differ_idx2 (mng_datap pData);
+mng_retcode mng_differ_idx4 (mng_datap pData);
+mng_retcode mng_differ_idx8 (mng_datap pData);
+mng_retcode mng_differ_ga8 (mng_datap pData);
+mng_retcode mng_differ_ga16 (mng_datap pData);
+mng_retcode mng_differ_rgba8 (mng_datap pData);
+mng_retcode mng_differ_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+
+#endif /* _libmng_filter_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_hlapi.c b/Source/LibMNG/libmng_hlapi.c
new file mode 100644
index 0000000..6199d59
--- /dev/null
+++ b/Source/LibMNG/libmng_hlapi.c
@@ -0,0 +1,2995 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_hlapi.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : high-level application API (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the high-level function interface * */
+/* * for applications. * */
+/* * * */
+/* * changes : 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - added init of iPLTEcount * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed calling-convention definition * */
+/* * - changed status-handling of display-routines * */
+/* * - added versioning-control routines * */
+/* * - filled the write routine * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added callback error-reporting support * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * 0.5.1 - 05/13/2000 - G.Juyn * */
+/* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
+/* * - added TERM animation object pointer (easier reference) * */
+/* * 0.5.1 - 05/14/2000 - G.Juyn * */
+/* * - added cleanup of saved-data (SAVE/SEEK processing) * */
+/* * 0.5.1 - 05/16/2000 - G.Juyn * */
+/* * - moved the actual write_graphic functionality from here * */
+/* * to its appropriate function in the mng_write module * */
+/* * * */
+/* * 0.5.2 - 05/19/2000 - G.Juyn * */
+/* * - cleaned up some code regarding mixed support * */
+/* * - added JNG support * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - moved init of default zlib parms here from "mng_zlib.c" * */
+/* * - added init of default IJG parms * */
+/* * 0.5.2 - 05/29/2000 - G.Juyn * */
+/* * - fixed inconsistancy with freeing global iCCP profile * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added delta-image field initialization * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added initialization of the buffer-suspend parameter * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - added initialization of update-region for refresh * */
+/* * - added initialization of Needrefresh parameter * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - added initialization of Deltaimmediate * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added initialization of Speed * */
+/* * - added initialization of Imagelevel * */
+/* * 0.5.3 - 06/26/2000 - G.Juyn * */
+/* * - changed userdata variable to mng_ptr * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - fixed initialization routine for new mng_handle type * */
+/* * * */
+/* * 0.9.1 - 07/06/2000 - G.Juyn * */
+/* * - changed mng_display_resume to allow to be called after * */
+/* * a suspension return with MNG_NEEDMOREDATA * */
+/* * - added returncode MNG_NEEDTIMERWAIT for timer breaks * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - implemented support for freeze/reset/resume & go_xxxx * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added support for improved timing * */
+/* * - added support for improved I/O-suspension * */
+/* * 0.9.1 - 07/14/2000 - G.Juyn * */
+/* * - changed EOF processing behavior * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added callbacks for SAVE/SEEK processing * */
+/* * - added variable for NEEDSECTIONWAIT breaks * */
+/* * - added variable for freeze & reset processing * */
+/* * 0.9.1 - 07/17/2000 - G.Juyn * */
+/* * - added error cleanup processing * */
+/* * - fixed support for mng_display_reset() * */
+/* * - fixed suspension-buffering for 32K+ chunks * */
+/* * * */
+/* * 0.9.2 - 07/29/2000 - G.Juyn * */
+/* * - fixed small bugs in display processing * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - fixed wrapping of suspension parameters * */
+/* * 0.9.2 - 08/04/2000 - G.Juyn * */
+/* * - B111096 - fixed large-buffer read-suspension * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added optional support for bKGD for PNG images * */
+/* * - raised initial maximum canvas size * */
+/* * - added support for JDAA * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * - fixed support for delta-images during read() / display() * */
+/* * 0.9.3 - 10/18/2000 - G.Juyn * */
+/* * - added closestream() processing for mng_cleanup() * */
+/* * 0.9.3 - 10/27/2000 - G.Juyn * */
+/* * - fixed separate read() & display() processing * */
+/* * * */
+/* * 0.9.4 - 11/20/2000 - G.Juyn * */
+/* * - fixed unwanted repetition in mng_readdisplay() * */
+/* * 0.9.4 - 11/24/2000 - G.Juyn * */
+/* * - moved restore of object 0 to libmng_display * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 02/13/2001 - G.Juyn * */
+/* * - fixed first FRAM_MODE=4 timing problem * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn * */
+/* * - fixed bug with display_reset/display_resume (Thanks G!) * */
+/* * 1.0.1 - 04/22/2001 - G.Juyn * */
+/* * - fixed memory-leak (Thanks Gregg!) * */
+/* * 1.0.1 - 04/23/2001 - G.Juyn * */
+/* * - fixed reset_rundata to drop all objects * */
+/* * 1.0.1 - 04/25/2001 - G.Juyn * */
+/* * - moved mng_clear_cms to libmng_cms * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * - added processterm callback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.5 - 07/08/2002 - G.Juyn * */
+/* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
+/* * 1.0.5 - 07/16/2002 - G.Juyn * */
+/* * - B581625 - large chunks fail with suspension reads * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - fixed LOOP iteration=0 special case * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - added another fix for misplaced TERM chunk * */
+/* * - completed support for condition=2 in TERM chunk * */
+/* * - added beta version function & constant * */
+/* * 1.0.5 - 10/11/2002 - G.Juyn * */
+/* * - added mng_status_dynamic to supports function * */
+/* * 1.0.5 - 11/04/2002 - G.Juyn * */
+/* * - changed FRAMECOUNT/LAYERCOUNT/PLAYTIME error to warning * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * 1.0.5 - 11/29/2002 - G.Juyn * */
+/* * - fixed goxxxxx() support for zero values * */
+/* * * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 07/11/2003 - G.R-P * */
+/* * - added conditionals zlib and jpeg property accessors * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added conditionals around "mng_display_go*" and other * */
+/* * unused functions * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.7 - 03/07/2004 - G. Randers-Pehrson * */
+/* * - put gamma, cms-related declarations inside #ifdef * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - fixed zTXT -> zTXt typo * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/10/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * 1.0.8 - 07/06/2004 - G.R-P * */
+/* * - defend against using undefined openstream function * */
+/* * 1.0.8 - 08/02/2004 - G.Juyn * */
+/* * - added conditional to allow easier writing of large MNG's * */
+/* * * */
+/* * 1.0.9 - 08/17/2004 - G.R-P * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * 1.0.9 - 09/25/2004 - G.Juyn * */
+/* * - replaced MNG_TWEAK_LARGE_FILES with permanent solution * */
+/* * 1.0.9 - 10/03/2004 - G.Juyn * */
+/* * - added function to retrieve current FRAM delay * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 07/06/2005 - G.R-P * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * 1.0.10 - 07/06/2007 - G.R-P bugfix by Lucas Quintana * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_objects.h"
+#include "libmng_object_prc.h"
+#include "libmng_chunks.h"
+#include "libmng_memory.h"
+#include "libmng_read.h"
+#include "libmng_write.h"
+#include "libmng_display.h"
+#include "libmng_zlib.h"
+#include "libmng_jpeg.h"
+#include "libmng_cms.h"
+#include "libmng_pixels.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * local routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_LOCAL mng_retcode mng_drop_objects (mng_datap pData,
+ mng_bool bDropaniobj)
+{
+ mng_objectp pObject;
+ mng_objectp pNext;
+ mng_cleanupobject fCleanup;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_OBJECTS, MNG_LC_START);
+#endif
+
+ pObject = pData->pFirstimgobj; /* get first stored image-object (if any) */
+
+ while (pObject) /* more objects to discard ? */
+ {
+ pNext = ((mng_object_headerp)pObject)->pNext;
+ /* call appropriate cleanup */
+ fCleanup = ((mng_object_headerp)pObject)->fCleanup;
+ fCleanup (pData, pObject);
+
+ pObject = pNext; /* neeeext */
+ }
+
+ pData->pFirstimgobj = MNG_NULL; /* clean this up!!! */
+ pData->pLastimgobj = MNG_NULL;
+
+ if (bDropaniobj) /* drop animation objects ? */
+ {
+ pObject = pData->pFirstaniobj; /* get first stored animation-object (if any) */
+
+ while (pObject) /* more objects to discard ? */
+ {
+ pNext = ((mng_object_headerp)pObject)->pNext;
+ /* call appropriate cleanup */
+ fCleanup = ((mng_object_headerp)pObject)->fCleanup;
+ fCleanup (pData, pObject);
+
+ pObject = pNext; /* neeeext */
+ }
+
+ pData->pFirstaniobj = MNG_NULL; /* clean this up!!! */
+ pData->pLastaniobj = MNG_NULL;
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ pObject = pData->pFirstevent; /* get first event-object (if any) */
+
+ while (pObject) /* more objects to discard ? */
+ {
+ pNext = ((mng_object_headerp)pObject)->pNext;
+ /* call appropriate cleanup */
+ fCleanup = ((mng_object_headerp)pObject)->fCleanup;
+ fCleanup (pData, pObject);
+
+ pObject = pNext; /* neeeext */
+ }
+
+ pData->pFirstevent = MNG_NULL; /* clean this up!!! */
+ pData->pLastevent = MNG_NULL;
+#endif
+ }
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ if (pData->pMPNG) /* drop MPNG data (if any) */
+ {
+ fCleanup = ((mng_object_headerp)pData->pMPNG)->fCleanup;
+ fCleanup (pData, pData->pMPNG);
+ pData->pMPNG = MNG_NULL;
+ }
+#endif
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ if (pData->pANG) /* drop ANG data (if any) */
+ {
+ fCleanup = ((mng_object_headerp)pData->pANG)->fCleanup;
+ fCleanup (pData, pData->pANG);
+ pData->pANG = MNG_NULL;
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_OBJECTS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_SKIPCHUNK_SAVE
+MNG_LOCAL mng_retcode mng_drop_savedata (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_SAVEDATA, MNG_LC_START);
+#endif
+
+ if (pData->pSavedata) /* sanity check */
+ { /* address it more directly */
+ mng_savedatap pSave = pData->pSavedata;
+
+ if (pSave->iGlobalProfilesize) /* cleanup the profile ? */
+ MNG_FREEX (pData, pSave->pGlobalProfile, pSave->iGlobalProfilesize);
+ /* cleanup the save structure */
+ MNG_FREE (pData, pData->pSavedata, sizeof (mng_savedata));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_SAVEDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+MNG_LOCAL mng_retcode mng_reset_rundata (mng_datap pData)
+{
+ mng_drop_invalid_objects (pData); /* drop invalidly stored objects */
+#ifndef MNG_SKIPCHUNK_SAVE
+ mng_drop_savedata (pData); /* drop stored savedata */
+#endif
+ mng_reset_objzero (pData); /* reset object 0 */
+ /* drop stored objects (if any) */
+ mng_drop_objects (pData, MNG_FALSE);
+
+ pData->bFramedone = MNG_FALSE;
+ pData->iFrameseq = 0; /* reset counters & stuff */
+ pData->iLayerseq = 0;
+ pData->iFrametime = 0;
+
+ pData->bSkipping = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ pData->bRunningevent = MNG_FALSE;
+ pData->bStopafterseek = MNG_FALSE;
+ pData->iEventx = 0;
+ pData->iEventy = 0;
+ pData->pLastmousemove = MNG_NULL;
+#endif
+
+ pData->iRequestframe = 0;
+ pData->iRequestlayer = 0;
+ pData->iRequesttime = 0;
+ pData->bSearching = MNG_FALSE;
+
+ pData->iRuntime = 0;
+ pData->iSynctime = 0;
+ pData->iStarttime = 0;
+ pData->iEndtime = 0;
+ pData->bRunning = MNG_FALSE;
+ pData->bTimerset = MNG_FALSE;
+ pData->iBreakpoint = 0;
+ pData->bSectionwait = MNG_FALSE;
+ pData->bFreezing = MNG_FALSE;
+ pData->bResetting = MNG_FALSE;
+ pData->bNeedrefresh = MNG_FALSE;
+ pData->bOnlyfirstframe = MNG_FALSE;
+ pData->iFramesafterTERM = 0;
+
+ pData->iIterations = 0;
+ /* start of animation objects! */
+ pData->pCurraniobj = MNG_NULL;
+
+ pData->iUpdateleft = 0; /* reset region */
+ pData->iUpdateright = 0;
+ pData->iUpdatetop = 0;
+ pData->iUpdatebottom = 0;
+ pData->iPLTEcount = 0; /* reset PLTE data */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+ pData->iDEFIobjectid = 0; /* reset DEFI data */
+ pData->bDEFIhasdonotshow = MNG_FALSE;
+ pData->iDEFIdonotshow = 0;
+ pData->bDEFIhasconcrete = MNG_FALSE;
+ pData->iDEFIconcrete = 0;
+ pData->bDEFIhasloca = MNG_FALSE;
+ pData->iDEFIlocax = 0;
+ pData->iDEFIlocay = 0;
+ pData->bDEFIhasclip = MNG_FALSE;
+ pData->iDEFIclipl = 0;
+ pData->iDEFIclipr = 0;
+ pData->iDEFIclipt = 0;
+ pData->iDEFIclipb = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_BACK
+ pData->iBACKred = 0; /* reset BACK data */
+ pData->iBACKgreen = 0;
+ pData->iBACKblue = 0;
+ pData->iBACKmandatory = 0;
+ pData->iBACKimageid = 0;
+ pData->iBACKtile = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pData->iFRAMmode = 1; /* default global FRAM variables */
+ pData->iFRAMdelay = 1;
+ pData->iFRAMtimeout = 0x7fffffffl;
+ pData->bFRAMclipping = MNG_FALSE;
+ pData->iFRAMclipl = 0;
+ pData->iFRAMclipr = 0;
+ pData->iFRAMclipt = 0;
+ pData->iFRAMclipb = 0;
+
+ pData->iFramemode = 1; /* again for the current frame */
+ pData->iFramedelay = 1;
+ pData->iFrametimeout = 0x7fffffffl;
+ pData->bFrameclipping = MNG_FALSE;
+ pData->iFrameclipl = 0;
+ pData->iFrameclipr = 0;
+ pData->iFrameclipt = 0;
+ pData->iFrameclipb = 0;
+
+ pData->iNextdelay = 1;
+#endif
+
+#ifndef MNG_SKIPCHUNK_SHOW
+ pData->iSHOWmode = 0; /* reset SHOW data */
+ pData->iSHOWfromid = 0;
+ pData->iSHOWtoid = 0;
+ pData->iSHOWnextid = 0;
+ pData->iSHOWskip = 0;
+#endif
+
+ pData->iGlobalPLTEcount = 0; /* reset global PLTE data */
+
+ pData->iGlobalTRNSrawlen = 0; /* reset global tRNS data */
+
+ pData->iGlobalGamma = 0; /* reset global gAMA data */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ pData->iGlobalWhitepointx = 0; /* reset global cHRM data */
+ pData->iGlobalWhitepointy = 0;
+ pData->iGlobalPrimaryredx = 0;
+ pData->iGlobalPrimaryredy = 0;
+ pData->iGlobalPrimarygreenx = 0;
+ pData->iGlobalPrimarygreeny = 0;
+ pData->iGlobalPrimarybluex = 0;
+ pData->iGlobalPrimarybluey = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_sRGB
+ pData->iGlobalRendintent = 0; /* reset global sRGB data */
+#endif
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pData->iGlobalProfilesize) /* drop global profile (if any) */
+ MNG_FREE (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ pData->iGlobalProfilesize = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ pData->iGlobalBKGDred = 0; /* reset global bKGD data */
+ pData->iGlobalBKGDgreen = 0;
+ pData->iGlobalBKGDblue = 0;
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ /* reset delta-image */
+ pData->pDeltaImage = MNG_NULL;
+ pData->iDeltaImagetype = 0;
+ pData->iDeltatype = 0;
+ pData->iDeltaBlockwidth = 0;
+ pData->iDeltaBlockheight = 0;
+ pData->iDeltaBlockx = 0;
+ pData->iDeltaBlocky = 0;
+ pData->bDeltaimmediate = MNG_FALSE;
+
+ pData->fDeltagetrow = MNG_NULL;
+ pData->fDeltaaddrow = MNG_NULL;
+ pData->fDeltareplacerow = MNG_NULL;
+ pData->fDeltaputrow = MNG_NULL;
+
+ pData->fPromoterow = MNG_NULL;
+ pData->fPromBitdepth = MNG_NULL;
+ pData->pPromBuf = MNG_NULL;
+ pData->iPromColortype = 0;
+ pData->iPromBitdepth = 0;
+ pData->iPromFilltype = 0;
+ pData->iPromWidth = 0;
+ pData->pPromSrc = MNG_NULL;
+ pData->pPromDst = MNG_NULL;
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ pData->iMAGNfromid = 0;
+ pData->iMAGNtoid = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ pData->iPastx = 0;
+ pData->iPasty = 0;
+#endif
+
+ pData->pLastseek = MNG_NULL;
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+MNG_LOCAL void cleanup_errors (mng_datap pData)
+{
+ pData->iErrorcode = MNG_NOERROR;
+ pData->iSeverity = 0;
+ pData->iErrorx1 = 0;
+ pData->iErrorx2 = 0;
+ pData->zErrortext = MNG_NULL;
+
+ return;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+MNG_LOCAL mng_retcode make_pushbuffer (mng_datap pData,
+ mng_ptr pPushdata,
+ mng_size_t iLength,
+ mng_bool bTakeownership,
+ mng_pushdatap * pPush)
+{
+ mng_pushdatap pTemp;
+
+ MNG_ALLOC (pData, pTemp, sizeof(mng_pushdata));
+
+ pTemp->pNext = MNG_NULL;
+
+ if (bTakeownership) /* are we going to own the buffer? */
+ { /* then just copy the pointer */
+ pTemp->pData = (mng_uint8p)pPushdata;
+ }
+ else
+ { /* otherwise create new buffer */
+ MNG_ALLOCX (pData, pTemp->pData, iLength);
+ if (!pTemp->pData) /* succeeded? */
+ {
+ MNG_FREEX (pData, pTemp, sizeof(mng_pushdata));
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+ /* and copy the bytes across */
+ MNG_COPY (pTemp->pData, pPushdata, iLength);
+ }
+
+ pTemp->iLength = iLength;
+ pTemp->bOwned = bTakeownership;
+ pTemp->pDatanext = pTemp->pData;
+ pTemp->iRemaining = iLength;
+
+ *pPush = pTemp; /* return it */
+
+ return MNG_NOERROR; /* and all's well */
+}
+#endif
+
+#ifdef MNG_VERSION_QUERY_SUPPORT
+/* ************************************************************************** */
+/* * * */
+/* * Versioning control * */
+/* * * */
+/* ************************************************************************** */
+
+mng_pchar MNG_DECL mng_version_text (void)
+{
+ return MNG_VERSION_TEXT;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_version_so (void)
+{
+ return MNG_VERSION_SO;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_version_dll (void)
+{
+ return MNG_VERSION_DLL;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_version_major (void)
+{
+ return MNG_VERSION_MAJOR;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_version_minor (void)
+{
+ return MNG_VERSION_MINOR;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_version_release (void)
+{
+ return MNG_VERSION_RELEASE;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_version_beta (void)
+{
+ return MNG_VERSION_BETA;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * 'supports' function * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_FUNCQUERY
+typedef struct {
+ mng_pchar zFunction;
+ mng_uint8 iMajor; /* Major == 0 means not implemented ! */
+ mng_uint8 iMinor;
+ mng_uint8 iRelease;
+ } mng_func_entry;
+typedef mng_func_entry const * mng_func_entryp;
+
+MNG_LOCAL mng_func_entry const func_table [] =
+ { /* keep it alphabetically sorted !!!!! */
+ {"mng_cleanup", 1, 0, 0},
+ {"mng_copy_chunk", 1, 0, 5},
+ {"mng_create", 1, 0, 0},
+ {"mng_display", 1, 0, 0},
+ {"mng_display_freeze", 1, 0, 0},
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+ {"mng_display_goframe", 1, 0, 0},
+ {"mng_display_golayer", 1, 0, 0},
+ {"mng_display_gotime", 1, 0, 0},
+#endif
+ {"mng_display_reset", 1, 0, 0},
+ {"mng_display_resume", 1, 0, 0},
+ {"mng_get_alphabitdepth", 1, 0, 0},
+ {"mng_get_alphacompression", 1, 0, 0},
+ {"mng_get_alphadepth", 1, 0, 0},
+ {"mng_get_alphafilter", 1, 0, 0},
+ {"mng_get_alphainterlace", 1, 0, 0},
+ {"mng_get_bgcolor", 1, 0, 0},
+ {"mng_get_bitdepth", 1, 0, 0},
+ {"mng_get_bkgdstyle", 1, 0, 0},
+ {"mng_get_cacheplayback", 1, 0, 2},
+ {"mng_get_canvasstyle", 1, 0, 0},
+ {"mng_get_colortype", 1, 0, 0},
+ {"mng_get_compression", 1, 0, 0},
+#ifndef MNG_NO_CURRENT_INFO
+ {"mng_get_currentframe", 1, 0, 0},
+ {"mng_get_currentlayer", 1, 0, 0},
+ {"mng_get_currentplaytime", 1, 0, 0},
+#endif
+ {"mng_get_currframdelay", 1, 0, 9},
+#ifndef MNG_NO_DFLT_INFO
+ {"mng_get_dfltimggamma", 1, 0, 0},
+ {"mng_get_dfltimggammaint", 1, 0, 0},
+#endif
+ {"mng_get_displaygamma", 1, 0, 0},
+ {"mng_get_displaygammaint", 1, 0, 0},
+ {"mng_get_doprogressive", 1, 0, 2},
+ {"mng_get_filter", 1, 0, 0},
+ {"mng_get_framecount", 1, 0, 0},
+ {"mng_get_imageheight", 1, 0, 0},
+ {"mng_get_imagelevel", 1, 0, 0},
+ {"mng_get_imagetype", 1, 0, 0},
+ {"mng_get_imagewidth", 1, 0, 0},
+ {"mng_get_interlace", 1, 0, 0},
+#ifdef MNG_ACCESS_JPEG
+ {"mng_get_jpeg_dctmethod", 1, 0, 0},
+ {"mng_get_jpeg_maxjdat", 1, 0, 0},
+ {"mng_get_jpeg_optimized", 1, 0, 0},
+ {"mng_get_jpeg_progressive", 1, 0, 0},
+ {"mng_get_jpeg_quality", 1, 0, 0},
+ {"mng_get_jpeg_smoothing", 1, 0, 0},
+#endif
+ {"mng_get_lastbackchunk", 1, 0, 3},
+ {"mng_get_lastseekname", 1, 0, 5},
+ {"mng_get_layercount", 1, 0, 0},
+#ifndef MNG_SKIP_MAXCANVAS
+ {"mng_get_maxcanvasheight", 1, 0, 0},
+ {"mng_get_maxcanvaswidth", 1, 0, 0},
+#endif
+ {"mng_get_playtime", 1, 0, 0},
+ {"mng_get_refreshpass", 1, 0, 0},
+ {"mng_get_runtime", 1, 0, 0},
+ {"mng_get_sectionbreaks", 1, 0, 0},
+ {"mng_get_sigtype", 1, 0, 0},
+ {"mng_get_simplicity", 1, 0, 0},
+ {"mng_get_speed", 1, 0, 0},
+ {"mng_get_srgb", 1, 0, 0},
+ {"mng_get_starttime", 1, 0, 0},
+ {"mng_get_storechunks", 1, 0, 0},
+ {"mng_get_suspensionmode", 1, 0, 0},
+ {"mng_get_ticks", 1, 0, 0},
+#ifndef MNG_NO_CURRENT_INFO
+ {"mng_get_totalframes", 1, 0, 5},
+ {"mng_get_totallayers", 1, 0, 5},
+ {"mng_get_totalplaytime", 1, 0, 5},
+#endif
+ {"mng_get_usebkgd", 1, 0, 0},
+ {"mng_get_userdata", 1, 0, 0},
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+ {"mng_get_viewgamma", 1, 0, 0},
+ {"mng_get_viewgammaint", 1, 0, 0},
+#endif
+#ifdef MNG_ACCESS_ZLIB
+ {"mng_get_zlib_level", 1, 0, 0},
+ {"mng_get_zlib_maxidat", 1, 0, 0},
+ {"mng_get_zlib_memlevel", 1, 0, 0},
+ {"mng_get_zlib_method", 1, 0, 0},
+ {"mng_get_zlib_strategy", 1, 0, 0},
+ {"mng_get_zlib_windowbits", 1, 0, 0},
+#endif
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {"mng_getcb_closestream", 1, 0, 0},
+#endif
+ {"mng_getcb_errorproc", 1, 0, 0},
+ {"mng_getcb_getalphaline", 1, 0, 0},
+ {"mng_getcb_getbkgdline", 1, 0, 0},
+ {"mng_getcb_getcanvasline", 1, 0, 0},
+ {"mng_getcb_gettickcount", 1, 0, 0},
+ {"mng_getcb_memalloc", 1, 0, 0},
+ {"mng_getcb_memfree", 1, 0, 0},
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {"mng_getcb_openstream", 1, 0, 0},
+#endif
+ {"mng_getcb_processarow", 1, 0, 0},
+ {"mng_getcb_processchroma", 1, 0, 0},
+ {"mng_getcb_processgamma", 1, 0, 0},
+ {"mng_getcb_processheader", 1, 0, 0},
+ {"mng_getcb_processiccp", 1, 0, 0},
+ {"mng_getcb_processmend", 1, 0, 1},
+ {"mng_getcb_processneed", 1, 0, 0},
+ {"mng_getcb_processsave", 1, 0, 0},
+ {"mng_getcb_processseek", 1, 0, 0},
+ {"mng_getcb_processsrgb", 1, 0, 0},
+ {"mng_getcb_processterm", 1, 0, 2},
+ {"mng_getcb_processtext", 1, 0, 0},
+ {"mng_getcb_processunknown", 1, 0, 0},
+ {"mng_getcb_readdata", 1, 0, 0},
+ {"mng_getcb_refresh", 1, 0, 0},
+ {"mng_getcb_releasedata", 1, 0, 8},
+ {"mng_getcb_settimer", 1, 0, 0},
+ {"mng_getcb_traceproc", 1, 0, 0},
+ {"mng_getcb_writedata", 1, 0, 0},
+ {"mng_getchunk_back", 1, 0, 0},
+ {"mng_getchunk_basi", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_bKGD
+ {"mng_getchunk_bkgd", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {"mng_getchunk_chrm", 1, 0, 0},
+#endif
+ {"mng_getchunk_clip", 1, 0, 0},
+ {"mng_getchunk_clon", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_dBYK
+ {"mng_getchunk_dbyk", 1, 0, 0},
+#endif
+#endif
+ {"mng_getchunk_defi", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_getchunk_dhdr", 1, 0, 0},
+#endif
+ {"mng_getchunk_disc", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_getchunk_drop", 1, 0, 0},
+#endif
+ {"mng_getchunk_endl", 1, 0, 0},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {"mng_getchunk_mpng", 1, 0, 10},
+ {"mng_getchunk_mpng_frame", 1, 0, 10},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {"mng_getchunk_evnt", 1, 0, 5},
+ {"mng_getchunk_evnt_entry", 1, 0, 5},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {"mng_getchunk_expi", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {"mng_getchunk_fpri", 1, 0, 0},
+#endif
+ {"mng_getchunk_fram", 1, 0, 0},
+ {"mng_getchunk_gama", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_hIST
+ {"mng_getchunk_hist", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {"mng_getchunk_iccp", 1, 0, 0},
+#endif
+ {"mng_getchunk_idat", 1, 0, 0},
+ {"mng_getchunk_iend", 1, 0, 0},
+ {"mng_getchunk_ihdr", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ {"mng_getchunk_ijng", 1, 0, 0},
+#endif
+ {"mng_getchunk_ipng", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {"mng_getchunk_itxt", 1, 0, 0},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {"mng_getchunk_jdaa", 1, 0, 0},
+ {"mng_getchunk_jdat", 1, 0, 0},
+ {"mng_getchunk_jhdr", 1, 0, 0},
+ {"mng_getchunk_jsep", 1, 0, 0},
+#endif
+ {"mng_getchunk_loop", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_MAGN
+ {"mng_getchunk_magn", 1, 0, 0},
+#endif
+ {"mng_getchunk_mend", 1, 0, 0},
+ {"mng_getchunk_mhdr", 1, 0, 0},
+ {"mng_getchunk_move", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_nEED
+ {"mng_getchunk_need", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_ORDR
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_getchunk_ordr", 1, 0, 0},
+ {"mng_getchunk_ordr_entry", 1, 0, 0},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {"mng_getchunk_past", 1, 0, 0},
+ {"mng_getchunk_past_src", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYg
+ {"mng_getchunk_phyg", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {"mng_getchunk_phys", 1, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_getchunk_plte", 1, 0, 0},
+ {"mng_getchunk_pplt", 1, 0, 0},
+ {"mng_getchunk_pplt_entry", 1, 0, 0},
+ {"mng_getchunk_prom", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {"mng_getchunk_save", 1, 0, 0},
+ {"mng_getchunk_save_entry", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {"mng_getchunk_sbit", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {"mng_getchunk_seek", 1, 0, 0},
+#endif
+ {"mng_getchunk_show", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_sPLT
+ {"mng_getchunk_splt", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+ {"mng_getchunk_srgb", 1, 0, 0},
+#endif
+ {"mng_getchunk_term", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_tEXt
+ {"mng_getchunk_text", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {"mng_getchunk_time", 1, 0, 0},
+#endif
+ {"mng_getchunk_trns", 1, 0, 0},
+ {"mng_getchunk_unkown", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_zTXt
+ {"mng_getchunk_ztxt", 1, 0, 0},
+#endif
+ {"mng_getimgdata_chunk", 0, 0, 0},
+ {"mng_getimgdata_chunkseq", 0, 0, 0},
+ {"mng_getimgdata_seq", 0, 0, 0},
+ {"mng_getlasterror", 1, 0, 0},
+ {"mng_initialize", 1, 0, 0},
+ {"mng_iterate_chunks", 1, 0, 0},
+ {"mng_putchunk_back", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_BASI
+ {"mng_putchunk_basi", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {"mng_putchunk_bkgd", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {"mng_putchunk_chrm", 1, 0, 0},
+#endif
+ {"mng_putchunk_clip", 1, 0, 0},
+ {"mng_putchunk_clon", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+ {"mng_putchunk_dbyk", 1, 0, 0},
+#endif
+#endif
+ {"mng_putchunk_defi", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_putchunk_dhdr", 1, 0, 0},
+#endif
+ {"mng_putchunk_disc", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_putchunk_drop", 1, 0, 0},
+#endif
+ {"mng_putchunk_endl", 1, 0, 0},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {"mng_putchunk_mpng", 1, 0, 10},
+ {"mng_putchunk_mpng_frame", 1, 0, 10},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {"mng_putchunk_evnt", 1, 0, 5},
+ {"mng_putchunk_evnt_entry", 1, 0, 5},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {"mng_putchunk_expi", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {"mng_putchunk_fpri", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+ {"mng_putchunk_fram", 1, 0, 0},
+#endif
+ {"mng_putchunk_gama", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_hIST
+ {"mng_putchunk_hist", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {"mng_putchunk_iccp", 1, 0, 0},
+#endif
+ {"mng_putchunk_idat", 1, 0, 0},
+ {"mng_putchunk_iend", 1, 0, 0},
+ {"mng_putchunk_ihdr", 1, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ {"mng_putchunk_ijng", 1, 0, 0},
+#endif
+ {"mng_putchunk_ipng", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {"mng_putchunk_itxt", 1, 0, 0},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {"mng_putchunk_jdaa", 1, 0, 0},
+ {"mng_putchunk_jdat", 1, 0, 0},
+ {"mng_putchunk_jhdr", 1, 0, 0},
+ {"mng_putchunk_jsep", 1, 0, 0},
+#endif
+ {"mng_putchunk_loop", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_MAGN
+ {"mng_putchunk_magn", 1, 0, 0},
+#endif
+ {"mng_putchunk_mend", 1, 0, 0},
+ {"mng_putchunk_mhdr", 1, 0, 0},
+ {"mng_putchunk_move", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_nEED
+ {"mng_putchunk_need", 1, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+ {"mng_putchunk_ordr", 1, 0, 0},
+ {"mng_putchunk_ordr_entry", 1, 0, 0},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {"mng_putchunk_past", 1, 0, 0},
+ {"mng_putchunk_past_src", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYg
+ {"mng_putchunk_phyg", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {"mng_putchunk_phys", 1, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {"mng_putchunk_plte", 1, 0, 0},
+ {"mng_putchunk_pplt", 1, 0, 0},
+ {"mng_putchunk_pplt_entry", 1, 0, 0},
+ {"mng_putchunk_prom", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {"mng_putchunk_save", 1, 0, 0},
+ {"mng_putchunk_save_entry", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {"mng_putchunk_sbit", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {"mng_putchunk_seek", 1, 0, 0},
+#endif
+ {"mng_putchunk_show", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_sPLT
+ {"mng_putchunk_splt", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+ {"mng_putchunk_srgb", 1, 0, 0},
+#endif
+ {"mng_putchunk_term", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_tEXt
+ {"mng_putchunk_text", 1, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {"mng_putchunk_time", 1, 0, 0},
+#endif
+ {"mng_putchunk_trns", 1, 0, 0},
+ {"mng_putchunk_unkown", 1, 0, 0},
+#ifndef MNG_SKIPCHUNK_zTXt
+ {"mng_putchunk_ztxt", 1, 0, 0},
+#endif
+ {"mng_putimgdata_ihdr", 0, 0, 0},
+ {"mng_putimgdata_jhdr", 0, 0, 0},
+ {"mng_reset", 1, 0, 0},
+ {"mng_read", 1, 0, 0},
+ {"mng_read_pushchunk", 1, 0, 8},
+ {"mng_read_pushdata", 1, 0, 8},
+ {"mng_read_pushsig", 1, 0, 8},
+ {"mng_read_resume", 1, 0, 0},
+ {"mng_readdisplay", 1, 0, 0},
+ {"mng_set_bgcolor", 1, 0, 0},
+ {"mng_set_bkgdstyle", 1, 0, 0},
+ {"mng_set_cacheplayback", 1, 0, 2},
+ {"mng_set_canvasstyle", 1, 0, 0},
+ {"mng_set_dfltimggamma", 1, 0, 0},
+#ifndef MNG_NO_DFLT_INFO
+ {"mng_set_dfltimggammaint", 1, 0, 0},
+#endif
+ {"mng_set_displaygamma", 1, 0, 0},
+ {"mng_set_displaygammaint", 1, 0, 0},
+ {"mng_set_doprogressive", 1, 0, 2},
+#ifdef MNG_ACCESS_JPEG
+ {"mng_set_jpeg_dctmethod", 1, 0, 0},
+ {"mng_set_jpeg_maxjdat", 1, 0, 0},
+ {"mng_set_jpeg_optimized", 1, 0, 0},
+ {"mng_set_jpeg_progressive", 1, 0, 0},
+ {"mng_set_jpeg_quality", 1, 0, 0},
+ {"mng_set_jpeg_smoothing", 1, 0, 0},
+#endif
+#ifndef MNG_SKIP_MAXCANVAS
+ {"mng_set_maxcanvasheight", 1, 0, 0},
+ {"mng_set_maxcanvassize", 1, 0, 0},
+ {"mng_set_maxcanvaswidth", 1, 0, 0},
+#endif
+ {"mng_set_outputprofile", 1, 0, 0},
+ {"mng_set_outputprofile2", 1, 0, 0},
+ {"mng_set_outputsrgb", 1, 0, 1},
+ {"mng_set_sectionbreaks", 1, 0, 0},
+ {"mng_set_speed", 1, 0, 0},
+ {"mng_set_srgb", 1, 0, 0},
+ {"mng_set_srgbimplicit", 1, 0, 1},
+ {"mng_set_srgbprofile", 1, 0, 0},
+ {"mng_set_srgbprofile2", 1, 0, 0},
+ {"mng_set_storechunks", 1, 0, 0},
+ {"mng_set_suspensionmode", 1, 0, 0},
+ {"mng_set_usebkgd", 1, 0, 0},
+ {"mng_set_userdata", 1, 0, 0},
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+ {"mng_set_viewgamma", 1, 0, 0},
+ {"mng_set_viewgammaint", 1, 0, 0},
+#endif
+#ifdef MNG_ACCESS_ZLIB
+ {"mng_set_zlib_level", 1, 0, 0},
+ {"mng_set_zlib_maxidat", 1, 0, 0},
+ {"mng_set_zlib_memlevel", 1, 0, 0},
+ {"mng_set_zlib_method", 1, 0, 0},
+ {"mng_set_zlib_strategy", 1, 0, 0},
+ {"mng_set_zlib_windowbits", 1, 0, 0},
+#endif
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {"mng_setcb_closestream", 1, 0, 0},
+#endif
+ {"mng_setcb_errorproc", 1, 0, 0},
+ {"mng_setcb_getalphaline", 1, 0, 0},
+ {"mng_setcb_getbkgdline", 1, 0, 0},
+ {"mng_setcb_getcanvasline", 1, 0, 0},
+ {"mng_setcb_gettickcount", 1, 0, 0},
+ {"mng_setcb_memalloc", 1, 0, 0},
+ {"mng_setcb_memfree", 1, 0, 0},
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {"mng_setcb_openstream", 1, 0, 0},
+#endif
+ {"mng_setcb_processarow", 1, 0, 0},
+ {"mng_setcb_processchroma", 1, 0, 0},
+ {"mng_setcb_processgamma", 1, 0, 0},
+ {"mng_setcb_processheader", 1, 0, 0},
+ {"mng_setcb_processiccp", 1, 0, 0},
+ {"mng_setcb_processmend", 1, 0, 1},
+ {"mng_setcb_processneed", 1, 0, 0},
+ {"mng_setcb_processsave", 1, 0, 0},
+ {"mng_setcb_processseek", 1, 0, 0},
+ {"mng_setcb_processsrgb", 1, 0, 0},
+ {"mng_setcb_processterm", 1, 0, 2},
+ {"mng_setcb_processtext", 1, 0, 0},
+ {"mng_setcb_processunknown", 1, 0, 0},
+ {"mng_setcb_readdata", 1, 0, 0},
+ {"mng_setcb_refresh", 1, 0, 0},
+ {"mng_setcb_releasedata", 1, 0, 8},
+ {"mng_setcb_settimer", 1, 0, 0},
+ {"mng_setcb_traceproc", 1, 0, 0},
+ {"mng_setcb_writedata", 1, 0, 0},
+ {"mng_status_creating", 1, 0, 0},
+ {"mng_status_displaying", 1, 0, 0},
+ {"mng_status_dynamic", 1, 0, 5},
+ {"mng_status_error", 1, 0, 0},
+ {"mng_status_reading", 1, 0, 0},
+ {"mng_status_running", 1, 0, 0},
+ {"mng_status_runningevent", 1, 0, 5},
+ {"mng_status_suspendbreak", 1, 0, 0},
+ {"mng_status_timerbreak", 1, 0, 0},
+ {"mng_status_writing", 1, 0, 0},
+ {"mng_supports_func", 1, 0, 5},
+ {"mng_trapevent", 1, 0, 5},
+ {"mng_updatemngheader", 1, 0, 0},
+ {"mng_updatemngsimplicity", 1, 0, 0},
+ {"mng_version_beta", 1, 0, 5},
+ {"mng_version_dll", 1, 0, 0},
+ {"mng_version_major", 1, 0, 0},
+ {"mng_version_minor", 1, 0, 0},
+ {"mng_version_release", 1, 0, 0},
+ {"mng_version_so", 1, 0, 0},
+ {"mng_version_text", 1, 0, 0},
+ {"mng_write", 1, 0, 0},
+ };
+
+mng_bool MNG_DECL mng_supports_func (mng_pchar zFunction,
+ mng_uint8* iMajor,
+ mng_uint8* iMinor,
+ mng_uint8* iRelease)
+{
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ mng_func_entryp pEntry; /* pointer to found entry */
+ /* determine max index of table */
+ iTop = (sizeof (func_table) / sizeof (func_table [0])) - 1;
+
+ iLower = 0; /* initialize binary search */
+ iMiddle = iTop >> 1; /* start in the middle */
+ iUpper = iTop;
+ pEntry = 0; /* no goods yet! */
+
+ do /* the binary search itself */
+ {
+ mng_int32 iRslt = strcmp(func_table [iMiddle].zFunction, zFunction);
+ if (iRslt < 0)
+ iLower = iMiddle + 1;
+ else if (iRslt > 0)
+ iUpper = iMiddle - 1;
+ else
+ {
+ pEntry = &func_table [iMiddle];
+ break;
+ };
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+
+ if (pEntry) /* found it ? */
+ {
+ *iMajor = pEntry->iMajor;
+ *iMinor = pEntry->iMinor;
+ *iRelease = pEntry->iRelease;
+ return MNG_TRUE;
+ }
+ else
+ {
+ *iMajor = 0;
+ *iMinor = 0;
+ *iRelease = 0;
+ return MNG_FALSE;
+ }
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * HLAPI routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_handle MNG_DECL mng_initialize (mng_ptr pUserdata,
+ mng_memalloc fMemalloc,
+ mng_memfree fMemfree,
+ mng_traceproc fTraceproc)
+{
+ mng_datap pData;
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_retcode iRetcode;
+ mng_imagep pImage;
+#endif
+
+#ifdef MNG_INTERNAL_MEMMNGMT /* allocate the main datastruc */
+ pData = (mng_datap)calloc (1, sizeof (mng_data));
+#else
+ pData = (mng_datap)fMemalloc (sizeof (mng_data));
+#endif
+
+ if (!pData)
+ return MNG_NULL; /* error: out of memory?? */
+ /* validate the structure */
+ pData->iMagic = MNG_MAGIC;
+ /* save userdata field */
+ pData->pUserdata = pUserdata;
+ /* remember trace callback */
+ pData->fTraceproc = fTraceproc;
+
+#ifdef MNG_SUPPORT_TRACE
+ if (mng_trace (pData, MNG_FN_INITIALIZE, MNG_LC_INITIALIZE))
+ {
+ MNG_FREEX (pData, pData, sizeof (mng_data));
+ return MNG_NULL;
+ }
+#endif
+ /* default canvas styles are 8-bit RGB */
+ pData->iCanvasstyle = MNG_CANVAS_RGB8;
+ pData->iBkgdstyle = MNG_CANVAS_RGB8;
+
+ pData->iBGred = 0; /* black */
+ pData->iBGgreen = 0;
+ pData->iBGblue = 0;
+
+ pData->bUseBKGD = MNG_TRUE;
+
+#ifdef MNG_FULL_CMS
+ pData->bIssRGB = MNG_TRUE;
+ pData->hProf1 = 0; /* no profiles yet */
+ pData->hProf2 = 0;
+ pData->hProf3 = 0;
+ pData->hTrans = 0;
+#endif
+
+ pData->dViewgamma = 1.0;
+ pData->dDisplaygamma = 2.2;
+ pData->dDfltimggamma = 0.45455;
+ /* initially remember chunks */
+ pData->bStorechunks = MNG_TRUE;
+ /* no breaks at section-borders */
+ pData->bSectionbreaks = MNG_FALSE;
+ /* initially cache playback info */
+ pData->bCacheplayback = MNG_TRUE;
+ /* progressive refresh for large images */
+ pData->bDoProgressive = MNG_TRUE;
+ /* crc exists; should check; error for
+ critical chunks; warning for ancillery;
+ generate crc for output */
+ pData->iCrcmode = MNG_CRC_DEFAULT;
+ /* normal animation-speed ! */
+ pData->iSpeed = mng_st_normal;
+ /* initial image limits */
+ pData->iMaxwidth = 10000;
+ pData->iMaxheight = 10000;
+
+#ifdef MNG_INTERNAL_MEMMNGMT /* internal management */
+ pData->fMemalloc = MNG_NULL;
+ pData->fMemfree = MNG_NULL;
+#else /* keep callbacks */
+ pData->fMemalloc = fMemalloc;
+ pData->fMemfree = fMemfree;
+#endif
+ /* no value (yet) */
+ pData->fReleasedata = MNG_NULL;
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ pData->fOpenstream = MNG_NULL;
+ pData->fClosestream = MNG_NULL;
+#endif
+ pData->fReaddata = MNG_NULL;
+ pData->fWritedata = MNG_NULL;
+ pData->fErrorproc = MNG_NULL;
+ pData->fProcessheader = MNG_NULL;
+ pData->fProcesstext = MNG_NULL;
+ pData->fProcesssave = MNG_NULL;
+ pData->fProcessseek = MNG_NULL;
+ pData->fProcessneed = MNG_NULL;
+ pData->fProcessmend = MNG_NULL;
+ pData->fProcessunknown = MNG_NULL;
+ pData->fProcessterm = MNG_NULL;
+ pData->fGetcanvasline = MNG_NULL;
+ pData->fGetbkgdline = MNG_NULL;
+ pData->fGetalphaline = MNG_NULL;
+ pData->fRefresh = MNG_NULL;
+ pData->fGettickcount = MNG_NULL;
+ pData->fSettimer = MNG_NULL;
+ pData->fProcessgamma = MNG_NULL;
+ pData->fProcesschroma = MNG_NULL;
+ pData->fProcesssrgb = MNG_NULL;
+ pData->fProcessiccp = MNG_NULL;
+ pData->fProcessarow = MNG_NULL;
+
+#if defined(MNG_SUPPORT_DISPLAY) && (defined(MNG_GAMMA_ONLY) || defined(MNG_FULL_CMS))
+ pData->dLastgamma = 0; /* lookup table needs first-time calc */
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY /* create object 0 */
+ iRetcode = mng_create_imageobject (pData, 0, MNG_TRUE, MNG_TRUE, MNG_TRUE,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, MNG_FALSE,
+ 0, 0, 0, 0, &pImage);
+
+ if (iRetcode) /* on error drop out */
+ {
+ MNG_FREEX (pData, pData, sizeof (mng_data));
+ return MNG_NULL;
+ }
+
+ pData->pObjzero = pImage;
+#endif
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_INCLUDE_LCMS)
+ mnglcms_initlibrary (); /* init lcms particulars */
+#endif
+
+#ifdef MNG_SUPPORT_READ
+ pData->bSuspensionmode = MNG_FALSE;
+ pData->iSuspendbufsize = 0;
+ pData->pSuspendbuf = MNG_NULL;
+ pData->pSuspendbufnext = MNG_NULL;
+ pData->iSuspendbufleft = 0;
+ pData->iChunklen = 0;
+ pData->pReadbufnext = MNG_NULL;
+ pData->pLargebufnext = MNG_NULL;
+
+ pData->pFirstpushchunk = MNG_NULL;
+ pData->pLastpushchunk = MNG_NULL;
+ pData->pFirstpushdata = MNG_NULL;
+ pData->pLastpushdata = MNG_NULL;
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB
+ mngzlib_initialize (pData); /* initialize zlib structures and such */
+ /* default zlib compression parameters */
+ pData->iZlevel = MNG_ZLIB_LEVEL;
+ pData->iZmethod = MNG_ZLIB_METHOD;
+ pData->iZwindowbits = MNG_ZLIB_WINDOWBITS;
+ pData->iZmemlevel = MNG_ZLIB_MEMLEVEL;
+ pData->iZstrategy = MNG_ZLIB_STRATEGY;
+ /* default maximum IDAT data size */
+ pData->iMaxIDAT = MNG_MAX_IDAT_SIZE;
+#endif
+
+#ifdef MNG_INCLUDE_JNG /* default IJG compression parameters */
+ pData->eJPEGdctmethod = MNG_JPEG_DCT;
+ pData->iJPEGquality = MNG_JPEG_QUALITY;
+ pData->iJPEGsmoothing = MNG_JPEG_SMOOTHING;
+ pData->bJPEGcompressprogr = MNG_JPEG_PROGRESSIVE;
+ pData->bJPEGcompressopt = MNG_JPEG_OPTIMIZED;
+ /* default maximum JDAT data size */
+ pData->iMaxJDAT = MNG_MAX_JDAT_SIZE;
+#endif
+
+ mng_reset ((mng_handle)pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ if (mng_trace (pData, MNG_FN_INITIALIZE, MNG_LC_END))
+ {
+ MNG_FREEX (pData, pData, sizeof (mng_data));
+ return MNG_NULL;
+ }
+#endif
+
+ return (mng_handle)pData; /* if we get here, we're in business */
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_reset (mng_handle hHandle)
+{
+ mng_datap pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_RESET, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)(hHandle)); /* address main structure */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_SKIPCHUNK_SAVE
+ mng_drop_savedata (pData); /* cleanup saved-data from SAVE/SEEK */
+#endif
+#endif
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_FULL_CMS)
+ mng_clear_cms (pData); /* cleanup left-over cms stuff if any */
+#endif
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_INCLUDE_JNG)
+ mngjpeg_cleanup (pData); /* cleanup jpeg stuff */
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB
+ if (pData->bInflating) /* if we've been inflating */
+ {
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+ mng_cleanup_rowproc (pData); /* cleanup row-processing, */
+#endif
+ mngzlib_inflatefree (pData); /* cleanup inflate! */
+ }
+#endif /* MNG_INCLUDE_ZLIB */
+
+#ifdef MNG_SUPPORT_READ
+ if ((pData->bReading) && (!pData->bEOF))
+ mng_process_eof (pData); /* cleanup app streaming */
+ /* cleanup default read buffers */
+ MNG_FREE (pData, pData->pReadbuf, pData->iReadbufsize);
+ MNG_FREE (pData, pData->pLargebuf, pData->iLargebufsize);
+ MNG_FREE (pData, pData->pSuspendbuf, pData->iSuspendbufsize);
+
+ while (pData->pFirstpushdata) /* release any pushed data & chunks */
+ mng_release_pushdata (pData);
+ while (pData->pFirstpushchunk)
+ mng_release_pushchunk (pData);
+#endif
+
+#ifdef MNG_SUPPORT_WRITE /* cleanup default write buffer */
+ MNG_FREE (pData, pData->pWritebuf, pData->iWritebufsize);
+#endif
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ mng_drop_chunks (pData); /* drop stored chunks (if any) */
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_drop_objects (pData, MNG_TRUE); /* drop stored objects (if any) */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pData->iGlobalProfilesize) /* drop global profile (if any) */
+ MNG_FREEX (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+#endif
+#endif
+
+ pData->eSigtype = mng_it_unknown;
+ pData->eImagetype = mng_it_unknown;
+ pData->iWidth = 0; /* these are unknown yet */
+ pData->iHeight = 0;
+ pData->iTicks = 0;
+ pData->iLayercount = 0;
+ pData->iFramecount = 0;
+ pData->iPlaytime = 0;
+ pData->iSimplicity = 0;
+ pData->iAlphadepth = 16; /* assume the worst! */
+
+ pData->iImagelevel = 0; /* no image encountered */
+
+ pData->iMagnify = 0; /* 1-to-1 display */
+ pData->iOffsetx = 0; /* no offsets */
+ pData->iOffsety = 0;
+ pData->iCanvaswidth = 0; /* let the app decide during processheader */
+ pData->iCanvasheight = 0;
+ /* so far, so good */
+ pData->iErrorcode = MNG_NOERROR;
+ pData->iSeverity = 0;
+ pData->iErrorx1 = 0;
+ pData->iErrorx2 = 0;
+ pData->zErrortext = MNG_NULL;
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ /* let's assume the best scenario */
+#ifndef MNG_NO_OLD_VERSIONS
+ pData->bPreDraft48 = MNG_FALSE;
+#endif
+ /* the unknown chunk */
+ pData->iChunkname = MNG_UINT_HUH;
+ pData->iChunkseq = 0;
+ pData->pFirstchunk = MNG_NULL;
+ pData->pLastchunk = MNG_NULL;
+ /* nothing processed yet */
+ pData->bHasheader = MNG_FALSE;
+ pData->bHasMHDR = MNG_FALSE;
+ pData->bHasIHDR = MNG_FALSE;
+ pData->bHasBASI = MNG_FALSE;
+ pData->bHasDHDR = MNG_FALSE;
+#ifdef MNG_INCLUDE_JNG
+ pData->bHasJHDR = MNG_FALSE;
+ pData->bHasJSEP = MNG_FALSE;
+ pData->bHasJDAA = MNG_FALSE;
+ pData->bHasJDAT = MNG_FALSE;
+#endif
+ pData->bHasPLTE = MNG_FALSE;
+ pData->bHasTRNS = MNG_FALSE;
+ pData->bHasGAMA = MNG_FALSE;
+ pData->bHasCHRM = MNG_FALSE;
+ pData->bHasSRGB = MNG_FALSE;
+ pData->bHasICCP = MNG_FALSE;
+ pData->bHasBKGD = MNG_FALSE;
+ pData->bHasIDAT = MNG_FALSE;
+
+ pData->bHasSAVE = MNG_FALSE;
+ pData->bHasBACK = MNG_FALSE;
+ pData->bHasFRAM = MNG_FALSE;
+ pData->bHasTERM = MNG_FALSE;
+ pData->bHasLOOP = MNG_FALSE;
+ /* there's no global stuff yet either */
+ pData->bHasglobalPLTE = MNG_FALSE;
+ pData->bHasglobalTRNS = MNG_FALSE;
+ pData->bHasglobalGAMA = MNG_FALSE;
+ pData->bHasglobalCHRM = MNG_FALSE;
+ pData->bHasglobalSRGB = MNG_FALSE;
+ pData->bHasglobalICCP = MNG_FALSE;
+
+ pData->iDatawidth = 0; /* no IHDR/BASI/DHDR done yet */
+ pData->iDataheight = 0;
+ pData->iBitdepth = 0;
+ pData->iColortype = 0;
+ pData->iCompression = 0;
+ pData->iFilter = 0;
+ pData->iInterlace = 0;
+
+#ifdef MNG_INCLUDE_JNG
+ pData->iJHDRcolortype = 0; /* no JHDR data */
+ pData->iJHDRimgbitdepth = 0;
+ pData->iJHDRimgcompression = 0;
+ pData->iJHDRimginterlace = 0;
+ pData->iJHDRalphabitdepth = 0;
+ pData->iJHDRalphacompression = 0;
+ pData->iJHDRalphafilter = 0;
+ pData->iJHDRalphainterlace = 0;
+#endif
+
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+#ifdef MNG_SUPPORT_READ /* no reading done */
+ pData->bReading = MNG_FALSE;
+ pData->bHavesig = MNG_FALSE;
+ pData->bEOF = MNG_FALSE;
+ pData->iReadbufsize = 0;
+ pData->pReadbuf = MNG_NULL;
+
+ pData->iLargebufsize = 0;
+ pData->pLargebuf = MNG_NULL;
+
+ pData->iSuspendtime = 0;
+ pData->bSuspended = MNG_FALSE;
+ pData->iSuspendpoint = 0;
+
+ pData->pSuspendbufnext = pData->pSuspendbuf;
+ pData->iSuspendbufleft = 0;
+#endif /* MNG_SUPPORT_READ */
+
+#ifdef MNG_SUPPORT_WRITE /* no creating/writing done */
+ pData->bCreating = MNG_FALSE;
+ pData->bWriting = MNG_FALSE;
+ pData->iFirstchunkadded = 0;
+ pData->iWritebufsize = 0;
+ pData->pWritebuf = MNG_NULL;
+#endif /* MNG_SUPPORT_WRITE */
+
+#ifdef MNG_SUPPORT_DISPLAY /* done nuttin' yet */
+ pData->bDisplaying = MNG_FALSE;
+ pData->iFrameseq = 0;
+ pData->iLayerseq = 0;
+ pData->iFrametime = 0;
+
+ pData->iTotallayers = 0;
+ pData->iTotalframes = 0;
+ pData->iTotalplaytime = 0;
+
+ pData->bSkipping = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ pData->bDynamic = MNG_FALSE;
+ pData->bRunningevent = MNG_FALSE;
+ pData->bStopafterseek = MNG_FALSE;
+ pData->iEventx = 0;
+ pData->iEventy = 0;
+ pData->pLastmousemove = MNG_NULL;
+#endif
+
+ pData->iRequestframe = 0;
+ pData->iRequestlayer = 0;
+ pData->iRequesttime = 0;
+ pData->bSearching = MNG_FALSE;
+
+ pData->bRestorebkgd = MNG_FALSE;
+
+ pData->iRuntime = 0;
+ pData->iSynctime = 0;
+ pData->iStarttime = 0;
+ pData->iEndtime = 0;
+ pData->bRunning = MNG_FALSE;
+ pData->bTimerset = MNG_FALSE;
+ pData->iBreakpoint = 0;
+ pData->bSectionwait = MNG_FALSE;
+ pData->bFreezing = MNG_FALSE;
+ pData->bResetting = MNG_FALSE;
+ pData->bNeedrefresh = MNG_FALSE;
+ pData->bMisplacedTERM = MNG_FALSE;
+ pData->bOnlyfirstframe = MNG_FALSE;
+ pData->iFramesafterTERM = 0;
+ /* these don't exist yet */
+ pData->pCurrentobj = MNG_NULL;
+ pData->pCurraniobj = MNG_NULL;
+ pData->pTermaniobj = MNG_NULL;
+ pData->pLastclone = MNG_NULL;
+ pData->pStoreobj = MNG_NULL;
+ pData->pStorebuf = MNG_NULL;
+ pData->pRetrieveobj = MNG_NULL;
+ /* no saved data ! */
+ pData->pSavedata = MNG_NULL;
+
+ pData->iUpdateleft = 0; /* no region updated yet */
+ pData->iUpdateright = 0;
+ pData->iUpdatetop = 0;
+ pData->iUpdatebottom = 0;
+
+ pData->iPass = -1; /* interlacing stuff and temp buffers */
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = 0;
+ pData->iSamplemul = 0;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = 0;
+ pData->iRowmax = 0;
+ pData->iFilterofs = 0;
+ pData->iPixelofs = 1;
+ pData->iLevel0 = 0;
+ pData->iLevel1 = 0;
+ pData->iLevel2 = 0;
+ pData->iLevel3 = 0;
+ pData->pWorkrow = MNG_NULL;
+ pData->pPrevrow = MNG_NULL;
+ pData->pRGBArow = MNG_NULL;
+ pData->bIsRGBA16 = MNG_TRUE;
+ pData->bIsOpaque = MNG_TRUE;
+ pData->iFilterbpp = 1;
+
+ pData->iSourcel = 0; /* always initialized just before */
+ pData->iSourcer = 0; /* compositing the next layer */
+ pData->iSourcet = 0;
+ pData->iSourceb = 0;
+ pData->iDestl = 0;
+ pData->iDestr = 0;
+ pData->iDestt = 0;
+ pData->iDestb = 0;
+ /* lists are empty */
+ pData->pFirstimgobj = MNG_NULL;
+ pData->pLastimgobj = MNG_NULL;
+ pData->pFirstaniobj = MNG_NULL;
+ pData->pLastaniobj = MNG_NULL;
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ pData->pFirstevent = MNG_NULL;
+ pData->pLastevent = MNG_NULL;
+#endif
+ /* no processing callbacks */
+ pData->fDisplayrow = MNG_NULL;
+ pData->fRestbkgdrow = MNG_NULL;
+ pData->fCorrectrow = MNG_NULL;
+ pData->fRetrieverow = MNG_NULL;
+ pData->fStorerow = MNG_NULL;
+ pData->fProcessrow = MNG_NULL;
+ pData->fDifferrow = MNG_NULL;
+ pData->fScalerow = MNG_NULL;
+ pData->fDeltarow = MNG_NULL;
+#ifndef MNG_SKIPCHUNK_PAST
+ pData->fFliprow = MNG_NULL;
+ pData->fTilerow = MNG_NULL;
+#endif
+ pData->fInitrowproc = MNG_NULL;
+
+ pData->iPLTEcount = 0; /* no PLTE data */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+ pData->iDEFIobjectid = 0; /* no DEFI data */
+ pData->bDEFIhasdonotshow = MNG_FALSE;
+ pData->iDEFIdonotshow = 0;
+ pData->bDEFIhasconcrete = MNG_FALSE;
+ pData->iDEFIconcrete = 0;
+ pData->bDEFIhasloca = MNG_FALSE;
+ pData->iDEFIlocax = 0;
+ pData->iDEFIlocay = 0;
+ pData->bDEFIhasclip = MNG_FALSE;
+ pData->iDEFIclipl = 0;
+ pData->iDEFIclipr = 0;
+ pData->iDEFIclipt = 0;
+ pData->iDEFIclipb = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_BACK
+ pData->iBACKred = 0; /* no BACK data */
+ pData->iBACKgreen = 0;
+ pData->iBACKblue = 0;
+ pData->iBACKmandatory = 0;
+ pData->iBACKimageid = 0;
+ pData->iBACKtile = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_FRAM
+ pData->iFRAMmode = 1; /* default global FRAM variables */
+ pData->iFRAMdelay = 1;
+ pData->iFRAMtimeout = 0x7fffffffl;
+ pData->bFRAMclipping = MNG_FALSE;
+ pData->iFRAMclipl = 0;
+ pData->iFRAMclipr = 0;
+ pData->iFRAMclipt = 0;
+ pData->iFRAMclipb = 0;
+
+ pData->iFramemode = 1; /* again for the current frame */
+ pData->iFramedelay = 1;
+ pData->iFrametimeout = 0x7fffffffl;
+ pData->bFrameclipping = MNG_FALSE;
+ pData->iFrameclipl = 0;
+ pData->iFrameclipr = 0;
+ pData->iFrameclipt = 0;
+ pData->iFrameclipb = 0;
+
+ pData->iNextdelay = 1;
+#endif
+
+#ifndef MNG_SKIPCHUNK_SHOW
+ pData->iSHOWmode = 0; /* no SHOW data */
+ pData->iSHOWfromid = 0;
+ pData->iSHOWtoid = 0;
+ pData->iSHOWnextid = 0;
+ pData->iSHOWskip = 0;
+#endif
+
+ pData->iGlobalPLTEcount = 0; /* no global PLTE data */
+
+ pData->iGlobalTRNSrawlen = 0; /* no global tRNS data */
+
+ pData->iGlobalGamma = 0; /* no global gAMA data */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ pData->iGlobalWhitepointx = 0; /* no global cHRM data */
+ pData->iGlobalWhitepointy = 0;
+ pData->iGlobalPrimaryredx = 0;
+ pData->iGlobalPrimaryredy = 0;
+ pData->iGlobalPrimarygreenx = 0;
+ pData->iGlobalPrimarygreeny = 0;
+ pData->iGlobalPrimarybluex = 0;
+ pData->iGlobalPrimarybluey = 0;
+#endif
+
+ pData->iGlobalRendintent = 0; /* no global sRGB data */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ pData->iGlobalProfilesize = 0; /* no global iCCP data */
+ pData->pGlobalProfile = MNG_NULL;
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ pData->iGlobalBKGDred = 0; /* no global bKGD data */
+ pData->iGlobalBKGDgreen = 0;
+ pData->iGlobalBKGDblue = 0;
+#endif
+ /* no delta-image */
+#ifndef MNG_NO_DELTA_PNG
+ pData->pDeltaImage = MNG_NULL;
+ pData->iDeltaImagetype = 0;
+ pData->iDeltatype = 0;
+ pData->iDeltaBlockwidth = 0;
+ pData->iDeltaBlockheight = 0;
+ pData->iDeltaBlockx = 0;
+ pData->iDeltaBlocky = 0;
+ pData->bDeltaimmediate = MNG_FALSE;
+
+ pData->fDeltagetrow = MNG_NULL;
+ pData->fDeltaaddrow = MNG_NULL;
+ pData->fDeltareplacerow = MNG_NULL;
+ pData->fDeltaputrow = MNG_NULL;
+
+ pData->fPromoterow = MNG_NULL;
+ pData->fPromBitdepth = MNG_NULL;
+ pData->pPromBuf = MNG_NULL;
+ pData->iPromColortype = 0;
+ pData->iPromBitdepth = 0;
+ pData->iPromFilltype = 0;
+ pData->iPromWidth = 0;
+ pData->pPromSrc = MNG_NULL;
+ pData->pPromDst = MNG_NULL;
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ pData->iMAGNfromid = 0;
+ pData->iMAGNtoid = 0;
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ pData->iPastx = 0;
+ pData->iPasty = 0;
+#endif
+
+ pData->pLastseek = MNG_NULL;
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB
+ pData->bInflating = 0; /* no inflating or deflating */
+ pData->bDeflating = 0; /* going on at the moment */
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY /* reset object 0 */
+ mng_reset_objzero (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_RESET, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_cleanup (mng_handle* hHandle)
+{
+ mng_datap pData; /* local vars */
+#ifndef MNG_INTERNAL_MEMMNGMT
+ mng_memfree fFree;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)*hHandle), MNG_FN_CLEANUP, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (*hHandle) /* check validity handle */
+ pData = ((mng_datap)(*hHandle)); /* and address main structure */
+
+ mng_reset (*hHandle); /* do an implicit reset to cleanup most stuff */
+
+#ifdef MNG_SUPPORT_DISPLAY /* drop object 0 */
+ mng_free_imageobject (pData, (mng_imagep)pData->pObjzero);
+#endif
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_FULL_CMS)
+ if (pData->hProf2) /* output profile defined ? */
+ mnglcms_freeprofile (pData->hProf2);
+
+ if (pData->hProf3) /* sRGB profile defined ? */
+ mnglcms_freeprofile (pData->hProf3);
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB
+ mngzlib_cleanup (pData); /* cleanup zlib stuff */
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)*hHandle), MNG_FN_CLEANUP, MNG_LC_CLEANUP)
+#endif
+
+ pData->iMagic = 0; /* invalidate the actual memory */
+
+#ifdef MNG_INTERNAL_MEMMNGMT
+ free ((void *)*hHandle); /* cleanup the data-structure */
+#else
+ fFree = ((mng_datap)*hHandle)->fMemfree;
+ fFree ((mng_ptr)*hHandle, sizeof (mng_data));
+#endif
+
+ *hHandle = 0; /* wipe pointer to inhibit future use */
+
+ return MNG_NOERROR; /* and we're done */
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_read (mng_handle hHandle)
+{
+ mng_datap pData; /* local vars */
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle and callbacks */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+ MNG_VALIDCB (hHandle, fMemalloc)
+ MNG_VALIDCB (hHandle, fMemfree)
+#endif
+
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ MNG_VALIDCB (hHandle, fOpenstream)
+ MNG_VALIDCB (hHandle, fClosestream)
+#endif
+ MNG_VALIDCB (hHandle, fReaddata)
+
+#ifdef MNG_SUPPORT_DISPLAY /* valid at this point ? */
+ if ((pData->bReading) || (pData->bDisplaying))
+#else
+ if (pData->bReading)
+#endif
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+#ifdef MNG_SUPPORT_WRITE
+ if ((pData->bWriting) || (pData->bCreating))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ pData->bReading = MNG_TRUE; /* read only! */
+
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ if (pData->fOpenstream && !pData->fOpenstream (hHandle))
+ /* open it and start reading */
+ iRetcode = MNG_APPIOERROR;
+ else
+#endif
+ iRetcode = mng_read_graphic (pData);
+
+ if (pData->bEOF) /* already at EOF ? */
+ {
+ pData->bReading = MNG_FALSE; /* then we're no longer reading */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_reset_rundata (pData); /* reset rundata */
+#endif
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bSuspended) /* read suspension ? */
+ {
+ iRetcode = MNG_NEEDMOREDATA;
+ pData->iSuspendtime = pData->fGettickcount ((mng_handle)pData);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_read_pushdata (mng_handle hHandle,
+ mng_ptr pData,
+ mng_size_t iLength,
+ mng_bool bTakeownership)
+{
+ mng_datap pMyData; /* local vars */
+ mng_pushdatap pPush;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pMyData = ((mng_datap)hHandle); /* and make it addressable */
+ /* create a containing buffer */
+ iRetcode = make_pushbuffer (pMyData, pData, iLength, bTakeownership, &pPush);
+ if (iRetcode)
+ return iRetcode;
+
+ if (pMyData->pLastpushdata) /* and update the buffer chain */
+ pMyData->pLastpushdata->pNext = pPush;
+ else
+ pMyData->pFirstpushdata = pPush;
+
+ pMyData->pLastpushdata = pPush;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_read_pushsig (mng_handle hHandle,
+ mng_imgtype eSigtype)
+{
+ mng_datap pData; /* local vars */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHSIG, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (pData->bHavesig) /* can we expect this call ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ pData->eSigtype = eSigtype;
+ pData->bHavesig = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHSIG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_read_pushchunk (mng_handle hHandle,
+ mng_ptr pChunk,
+ mng_size_t iLength,
+ mng_bool bTakeownership)
+{
+ mng_datap pMyData; /* local vars */
+ mng_pushdatap pPush;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHCHUNK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pMyData = ((mng_datap)hHandle); /* and make it addressable */
+ /* create a containing buffer */
+ iRetcode = make_pushbuffer (pMyData, pChunk, iLength, bTakeownership, &pPush);
+ if (iRetcode)
+ return iRetcode;
+
+ if (pMyData->pLastpushchunk) /* and update the buffer chain */
+ pMyData->pLastpushchunk->pNext = pPush;
+ else
+ pMyData->pFirstpushchunk = pPush;
+
+ pMyData->pLastpushchunk = pPush;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_PUSHCHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_read_resume (mng_handle hHandle)
+{
+ mng_datap pData; /* local vars */
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_RESUME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+ /* can we expect this call ? */
+ if ((!pData->bReading) || (!pData->bSuspended))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ pData->bSuspended = MNG_FALSE; /* reset the flag */
+
+#ifdef MNG_SUPPORT_DISPLAY /* re-synchronize ? */
+ if ((pData->bDisplaying) && (pData->bRunning))
+ pData->iSynctime = pData->iSynctime - pData->iSuspendtime +
+ pData->fGettickcount (hHandle);
+#endif
+
+ iRetcode = mng_read_graphic (pData); /* continue reading now */
+
+ if (pData->bEOF) /* at EOF ? */
+ {
+ pData->bReading = MNG_FALSE; /* then we're no longer reading */
+
+#ifdef MNG_SUPPORT_DISPLAY
+ mng_reset_rundata (pData); /* reset rundata */
+#endif
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bSuspended) /* read suspension ? */
+ {
+ iRetcode = MNG_NEEDMOREDATA;
+ pData->iSuspendtime = pData->fGettickcount ((mng_handle)pData);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READ_RESUME, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_write (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_WRITE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle and callbacks */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+ MNG_VALIDCB (hHandle, fMemalloc)
+ MNG_VALIDCB (hHandle, fMemfree)
+#endif
+
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ MNG_VALIDCB (hHandle, fOpenstream)
+ MNG_VALIDCB (hHandle, fClosestream)
+#endif
+ MNG_VALIDCB (hHandle, fWritedata)
+
+#ifdef MNG_SUPPORT_READ
+ if (pData->bReading) /* valid at this point ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ iRetcode = mng_write_graphic (pData);/* do the write */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_WRITE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_create (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_CREATE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle and callbacks */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+ MNG_VALIDCB (hHandle, fMemalloc)
+ MNG_VALIDCB (hHandle, fMemfree)
+#endif
+
+#ifdef MNG_SUPPORT_READ
+ if (pData->bReading) /* valid at this point ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+ if ((pData->bWriting) || (pData->bCreating))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ iRetcode = mng_reset (hHandle); /* clear any previous stuff */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->bCreating = MNG_TRUE; /* indicate we're creating a new file */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_CREATE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_READ)
+mng_retcode MNG_DECL mng_readdisplay (mng_handle hHandle)
+{
+ mng_datap pData; /* local vars */
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READDISPLAY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle and callbacks */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+ MNG_VALIDCB (hHandle, fMemalloc)
+ MNG_VALIDCB (hHandle, fMemfree)
+#endif
+
+ MNG_VALIDCB (hHandle, fReaddata)
+ MNG_VALIDCB (hHandle, fGetcanvasline)
+ MNG_VALIDCB (hHandle, fRefresh)
+ MNG_VALIDCB (hHandle, fGettickcount)
+ MNG_VALIDCB (hHandle, fSettimer)
+ /* valid at this point ? */
+ if ((pData->bReading) || (pData->bDisplaying))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+#ifdef MNG_SUPPORT_WRITE
+ if ((pData->bWriting) || (pData->bCreating))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ pData->bReading = MNG_TRUE; /* read & display! */
+ pData->bDisplaying = MNG_TRUE;
+ pData->bRunning = MNG_TRUE;
+ pData->iFrameseq = 0;
+ pData->iLayerseq = 0;
+ pData->iFrametime = 0;
+ pData->iRequestframe = 0;
+ pData->iRequestlayer = 0;
+ pData->iRequesttime = 0;
+ pData->bSearching = MNG_FALSE;
+ pData->iRuntime = 0;
+ pData->iSynctime = pData->fGettickcount (hHandle);
+ pData->iSuspendtime = 0;
+ pData->iStarttime = pData->iSynctime;
+ pData->iEndtime = 0;
+
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ if (pData->fOpenstream && !pData->fOpenstream (hHandle))
+ /* open it and start reading */
+ iRetcode = MNG_APPIOERROR;
+ else
+#endif
+ iRetcode = mng_read_graphic (pData);
+
+ if (pData->bEOF) /* already at EOF ? */
+ {
+ pData->bReading = MNG_FALSE; /* then we're no longer reading */
+ mng_drop_invalid_objects (pData); /* drop invalidly stored objects */
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bSuspended) /* read suspension ? */
+ {
+ iRetcode = MNG_NEEDMOREDATA;
+ pData->iSuspendtime = pData->fGettickcount ((mng_handle)pData);
+ }
+ else
+ if (pData->bTimerset) /* indicate timer break ? */
+ iRetcode = MNG_NEEDTIMERWAIT;
+ else
+ if (pData->bSectionwait) /* indicate section break ? */
+ iRetcode = MNG_NEEDSECTIONWAIT;
+ else
+ { /* no breaks = end of run */
+ pData->bRunning = MNG_FALSE;
+
+ if (pData->bFreezing) /* dynamic MNG reached SEEK ? */
+ pData->bFreezing = MNG_FALSE; /* reset it ! */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_READDISPLAY, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif /* MNG_SUPPORT_DISPLAY && MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_display (mng_handle hHandle)
+{
+ mng_datap pData; /* local vars */
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle and callbacks */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+#ifndef MNG_INTERNAL_MEMMNGMT
+ MNG_VALIDCB (hHandle, fMemalloc)
+ MNG_VALIDCB (hHandle, fMemfree)
+#endif
+
+ MNG_VALIDCB (hHandle, fGetcanvasline)
+ MNG_VALIDCB (hHandle, fRefresh)
+ MNG_VALIDCB (hHandle, fGettickcount)
+ MNG_VALIDCB (hHandle, fSettimer)
+
+ if (pData->bDisplaying) /* valid at this point ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+#ifdef MNG_SUPPORT_READ
+ if (pData->bReading)
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+#ifdef MNG_SUPPORT_WRITE
+ if ((pData->bWriting) || (pData->bCreating))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+#endif
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ pData->bDisplaying = MNG_TRUE; /* display! */
+ pData->bRunning = MNG_TRUE;
+ pData->iFrameseq = 0;
+ pData->iLayerseq = 0;
+ pData->iFrametime = 0;
+ pData->iRequestframe = 0;
+ pData->iRequestlayer = 0;
+ pData->iRequesttime = 0;
+ pData->bSearching = MNG_FALSE;
+ pData->iRuntime = 0;
+ pData->iSynctime = pData->fGettickcount (hHandle);
+#ifdef MNG_SUPPORT_READ
+ pData->iSuspendtime = 0;
+#endif
+ pData->iStarttime = pData->iSynctime;
+ pData->iEndtime = 0;
+ pData->pCurraniobj = pData->pFirstaniobj;
+ /* go do it */
+ iRetcode = mng_process_display (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bTimerset) /* indicate timer break ? */
+ iRetcode = MNG_NEEDTIMERWAIT;
+ else
+ { /* no breaks = end of run */
+ pData->bRunning = MNG_FALSE;
+
+ if (pData->bFreezing) /* dynamic MNG reached SEEK ? */
+ pData->bFreezing = MNG_FALSE; /* reset it ! */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_display_resume (mng_handle hHandle)
+{
+ mng_datap pData; /* local vars */
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_RESUME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (!pData->bDisplaying) /* can we expect this call ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+ /* was it running ? */
+ if ((pData->bRunning) || (pData->bReading))
+ { /* are we expecting this call ? */
+ if ((pData->bTimerset) || (pData->bSuspended) || (pData->bSectionwait))
+ {
+ pData->bTimerset = MNG_FALSE; /* reset the flags */
+ pData->bSectionwait = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_READ
+ if (pData->bReading) /* set during read&display ? */
+ {
+ if (pData->bSuspended) /* calculate proper synchronization */
+ pData->iSynctime = pData->iSynctime - pData->iSuspendtime +
+ pData->fGettickcount (hHandle);
+ else
+ pData->iSynctime = pData->fGettickcount (hHandle);
+
+ pData->bSuspended = MNG_FALSE; /* now reset this flag */
+ /* and continue reading */
+ iRetcode = mng_read_graphic (pData);
+
+ if (pData->bEOF) /* already at EOF ? */
+ {
+ pData->bReading = MNG_FALSE; /* then we're no longer reading */
+ /* drop invalidly stored objects */
+ mng_drop_invalid_objects (pData);
+ }
+ }
+ else
+#endif /* MNG_SUPPORT_READ */
+ { /* synchronize timing */
+ pData->iSynctime = pData->fGettickcount (hHandle);
+ /* resume display processing */
+ iRetcode = mng_process_display (pData);
+ }
+ }
+ else
+ {
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+ }
+ }
+ else
+ { /* synchronize timing */
+ pData->iSynctime = pData->fGettickcount (hHandle);
+ pData->bRunning = MNG_TRUE; /* it's restarted again ! */
+ /* resume display processing */
+ iRetcode = mng_process_display (pData);
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->bSuspended) /* read suspension ? */
+ {
+ iRetcode = MNG_NEEDMOREDATA;
+ pData->iSuspendtime = pData->fGettickcount ((mng_handle)pData);
+ }
+ else
+ if (pData->bTimerset) /* indicate timer break ? */
+ iRetcode = MNG_NEEDTIMERWAIT;
+ else
+ if (pData->bSectionwait) /* indicate section break ? */
+ iRetcode = MNG_NEEDSECTIONWAIT;
+ else
+ { /* no breaks = end of run */
+ pData->bRunning = MNG_FALSE;
+
+ if (pData->bFreezing) /* trying to freeze ? */
+ pData->bFreezing = MNG_FALSE; /* then we're there */
+
+ if (pData->bResetting) /* trying to reset as well ? */
+ { /* full stop!!! */
+ pData->bDisplaying = MNG_FALSE;
+
+ iRetcode = mng_reset_rundata (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_RESUME, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_display_freeze (mng_handle hHandle)
+{
+ mng_datap pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_FREEZE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+ /* can we expect this call ? */
+ if ((!pData->bDisplaying) || (pData->bReading))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ if (pData->bRunning) /* is it running ? */
+ {
+ mng_retcode iRetcode;
+
+ pData->bFreezing = MNG_TRUE; /* indicate we need to freeze */
+ /* continue "normal" processing */
+ iRetcode = mng_display_resume (hHandle);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_FREEZE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_display_reset (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_RESET, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+ /* can we expect this call ? */
+ if ((!pData->bDisplaying) || (pData->bReading))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ if (pData->bRunning) /* is it running ? */
+ {
+ pData->bFreezing = MNG_TRUE; /* indicate we need to freeze */
+ pData->bResetting = MNG_TRUE; /* indicate we're about to reset too */
+ /* continue normal processing ? */
+ iRetcode = mng_display_resume (hHandle);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ else
+ { /* full stop!!! */
+ pData->bDisplaying = MNG_FALSE;
+
+ iRetcode = mng_reset_rundata (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_RESET, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+mng_retcode MNG_DECL mng_display_goframe (mng_handle hHandle,
+ mng_uint32 iFramenr)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOFRAME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (pData->eImagetype != mng_it_mng) /* is it an animation ? */
+ MNG_ERROR (pData, MNG_NOTANANIMATION);
+ /* can we expect this call ? */
+ if ((!pData->bDisplaying) || (pData->bRunning))
+ MNG_ERROR ((mng_datap)hHandle, MNG_FUNCTIONINVALID);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (iFramenr > pData->iTotalframes) /* is the parameter within bounds ? */
+ MNG_ERROR (pData, MNG_FRAMENRTOOHIGH);
+ /* within MHDR bounds ? */
+ if ((pData->iFramecount) && (iFramenr > pData->iFramecount))
+ MNG_WARNING (pData, MNG_FRAMENRTOOHIGH);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ if (pData->iFrameseq > iFramenr) /* search from current or go back to start ? */
+ {
+ iRetcode = mng_reset_rundata (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ if (iFramenr)
+ {
+ pData->iRequestframe = iFramenr; /* go find the requested frame then */
+ iRetcode = mng_process_display (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->bTimerset = MNG_FALSE; /* reset just to be safe */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOFRAME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+mng_retcode MNG_DECL mng_display_golayer (mng_handle hHandle,
+ mng_uint32 iLayernr)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOLAYER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (pData->eImagetype != mng_it_mng) /* is it an animation ? */
+ MNG_ERROR (pData, MNG_NOTANANIMATION);
+ /* can we expect this call ? */
+ if ((!pData->bDisplaying) || (pData->bRunning))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (iLayernr > pData->iTotallayers) /* is the parameter within bounds ? */
+ MNG_ERROR (pData, MNG_LAYERNRTOOHIGH);
+ /* within MHDR bounds ? */
+ if ((pData->iLayercount) && (iLayernr > pData->iLayercount))
+ MNG_WARNING (pData, MNG_LAYERNRTOOHIGH);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ if (pData->iLayerseq > iLayernr) /* search from current or go back to start ? */
+ {
+ iRetcode = mng_reset_rundata (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ if (iLayernr)
+ {
+ pData->iRequestlayer = iLayernr; /* go find the requested layer then */
+ iRetcode = mng_process_display (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->bTimerset = MNG_FALSE; /* reset just to be safe */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOLAYER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+mng_retcode MNG_DECL mng_display_gotime (mng_handle hHandle,
+ mng_uint32 iPlaytime)
+{
+ mng_datap pData;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOTIME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (pData->eImagetype != mng_it_mng) /* is it an animation ? */
+ MNG_ERROR (pData, MNG_NOTANANIMATION);
+ /* can we expect this call ? */
+ if ((!pData->bDisplaying) || (pData->bRunning))
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+ /* is the parameter within bounds ? */
+ if (iPlaytime > pData->iTotalplaytime)
+ MNG_ERROR (pData, MNG_PLAYTIMETOOHIGH);
+ /* within MHDR bounds ? */
+ if ((pData->iPlaytime) && (iPlaytime > pData->iPlaytime))
+ MNG_WARNING (pData, MNG_PLAYTIMETOOHIGH);
+
+ cleanup_errors (pData); /* cleanup previous errors */
+
+ if (pData->iFrametime > iPlaytime) /* search from current or go back to start ? */
+ {
+ iRetcode = mng_reset_rundata (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ if (iPlaytime)
+ {
+ pData->iRequesttime = iPlaytime; /* go find the requested playtime then */
+ iRetcode = mng_process_display (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pData->bTimerset = MNG_FALSE; /* reset just to be safe */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_DISPLAY_GOTIME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_DISPLAY) && defined(MNG_SUPPORT_DYNAMICMNG)
+mng_retcode MNG_DECL mng_trapevent (mng_handle hHandle,
+ mng_uint8 iEventtype,
+ mng_int32 iX,
+ mng_int32 iY)
+{
+ mng_datap pData;
+ mng_eventp pEvent;
+ mng_bool bFound = MNG_FALSE;
+ mng_retcode iRetcode;
+ mng_imagep pImage;
+ mng_uint8p pPixel;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_TRAPEVENT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ if (pData->eImagetype != mng_it_mng) /* is it an animation ? */
+ MNG_ERROR (pData, MNG_NOTANANIMATION);
+
+ if (!pData->bDisplaying) /* can we expect this call ? */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (!pData->bCacheplayback) /* must store playback info to work!! */
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+ /* let's find a matching event object */
+ pEvent = (mng_eventp)pData->pFirstevent;
+
+ while ((pEvent) && (!bFound))
+ { /* matching eventtype ? */
+ if (pEvent->iEventtype == iEventtype)
+ {
+ switch (pEvent->iMasktype) /* check X/Y on basis of masktype */
+ {
+ case MNG_MASK_NONE : /* no mask is easy */
+ {
+ bFound = MNG_TRUE;
+ break;
+ }
+
+ case MNG_MASK_BOX : /* inside the given box ? */
+ { /* right- and bottom-border don't count ! */
+ if ((iX >= pEvent->iLeft) && (iX < pEvent->iRight) &&
+ (iY >= pEvent->iTop) && (iY < pEvent->iBottom))
+ bFound = MNG_TRUE;
+ break;
+ }
+
+ case MNG_MASK_OBJECT : /* non-zero pixel in the image object ? */
+ {
+ pImage = mng_find_imageobject (pData, pEvent->iObjectid);
+ /* valid image ? */
+ if ((pImage) && (pImage->pImgbuf->iBitdepth <= 8) &&
+ ((pImage->pImgbuf->iColortype == 0) || (pImage->pImgbuf->iColortype == 3)) &&
+ ((mng_int32)pImage->pImgbuf->iWidth > iX) &&
+ ((mng_int32)pImage->pImgbuf->iHeight > iY))
+ {
+ pPixel = pImage->pImgbuf->pImgdata + ((pImage->pImgbuf->iWidth * iY) + iX);
+
+ if (*pPixel) /* non-zero ? */
+ bFound = MNG_TRUE;
+ }
+
+ break;
+ }
+
+ case MNG_MASK_OBJECTIX : /* pixel in the image object matches index ? */
+ {
+ pImage = mng_find_imageobject (pData, pEvent->iObjectid);
+ /* valid image ? */
+ if ((pImage) && (pImage->pImgbuf->iBitdepth <= 8) &&
+ ((pImage->pImgbuf->iColortype == 0) || (pImage->pImgbuf->iColortype == 3)) &&
+ ((mng_int32)pImage->pImgbuf->iWidth > iX) && (iX >= 0) &&
+ ((mng_int32)pImage->pImgbuf->iHeight > iY) && (iY >= 0))
+ {
+ pPixel = pImage->pImgbuf->pImgdata + ((pImage->pImgbuf->iWidth * iY) + iX);
+ /* matching index ? */
+ if (*pPixel == pEvent->iIndex)
+ bFound = MNG_TRUE;
+ }
+
+ break;
+ }
+
+ case MNG_MASK_BOXOBJECT : /* non-zero pixel in the image object ? */
+ {
+ mng_int32 iTempx = iX - pEvent->iLeft;
+ mng_int32 iTempy = iY - pEvent->iTop;
+
+ pImage = mng_find_imageobject (pData, pEvent->iObjectid);
+ /* valid image ? */
+ if ((pImage) && (pImage->pImgbuf->iBitdepth <= 8) &&
+ ((pImage->pImgbuf->iColortype == 0) || (pImage->pImgbuf->iColortype == 3)) &&
+ (iTempx < (mng_int32)pImage->pImgbuf->iWidth) &&
+ (iTempx >= 0) && (iX < pEvent->iRight) &&
+ (iTempy < (mng_int32)pImage->pImgbuf->iHeight) &&
+ (iTempy >= 0) && (iY < pEvent->iBottom))
+ {
+ pPixel = pImage->pImgbuf->pImgdata + ((pImage->pImgbuf->iWidth * iTempy) + iTempx);
+
+ if (*pPixel) /* non-zero ? */
+ bFound = MNG_TRUE;
+ }
+
+ break;
+ }
+
+ case MNG_MASK_BOXOBJECTIX : /* pixel in the image object matches index ? */
+ {
+ mng_int32 iTempx = iX - pEvent->iLeft;
+ mng_int32 iTempy = iY - pEvent->iTop;
+
+ pImage = mng_find_imageobject (pData, pEvent->iObjectid);
+ /* valid image ? */
+ if ((pImage) && (pImage->pImgbuf->iBitdepth <= 8) &&
+ ((pImage->pImgbuf->iColortype == 0) || (pImage->pImgbuf->iColortype == 3)) &&
+ (iTempx < (mng_int32)pImage->pImgbuf->iWidth) &&
+ (iTempx >= 0) && (iX < pEvent->iRight) &&
+ (iTempy < (mng_int32)pImage->pImgbuf->iHeight) &&
+ (iTempy >= 0) && (iY < pEvent->iBottom))
+ {
+ pPixel = pImage->pImgbuf->pImgdata + ((pImage->pImgbuf->iWidth * iTempy) + iTempx);
+ /* matching index ? */
+ if (*pPixel == pEvent->iIndex)
+ bFound = MNG_TRUE;
+ }
+
+ break;
+ }
+
+ }
+ }
+
+ if (!bFound) /* try the next one */
+ pEvent = (mng_eventp)pEvent->sHeader.pNext;
+ }
+ /* found one that's not the last mousemove ? */
+ if ((pEvent) && ((mng_objectp)pEvent != pData->pLastmousemove))
+ { /* can we start an event process now ? */
+ if ((!pData->bReading) && (!pData->bRunning))
+ {
+ pData->iEventx = iX; /* save coordinates */
+ pData->iEventy = iY;
+ /* do it then ! */
+ iRetcode = pEvent->sHeader.fProcess (pData, pEvent);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* remember last mousemove event */
+ if (pEvent->iEventtype == MNG_EVENT_MOUSEMOVE)
+ pData->pLastmousemove = (mng_objectp)pEvent;
+ else
+ pData->pLastmousemove = MNG_NULL;
+ }
+ else
+ {
+
+ /* TODO: store unprocessed events or not ??? */
+
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_TRAPEVENT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_getlasterror (mng_handle hHandle,
+ mng_int8* iSeverity,
+ mng_chunkid* iChunkname,
+ mng_uint32* iChunkseq,
+ mng_int32* iExtra1,
+ mng_int32* iExtra2,
+ mng_pchar* zErrortext)
+{
+ mng_datap pData; /* local vars */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETLASTERROR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle) /* check validity handle */
+ pData = ((mng_datap)hHandle); /* and make it addressable */
+
+ *iSeverity = pData->iSeverity; /* return the appropriate fields */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+ *iChunkname = pData->iChunkname;
+ *iChunkseq = pData->iChunkseq;
+#else
+ *iChunkname = MNG_UINT_HUH;
+ *iChunkseq = 0;
+#endif
+
+ *iExtra1 = pData->iErrorx1;
+ *iExtra2 = pData->iErrorx2;
+ *zErrortext = pData->zErrortext;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GETLASTERROR, MNG_LC_END);
+#endif
+
+ return pData->iErrorcode; /* and the errorcode */
+}
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
diff --git a/Source/LibMNG/libmng_jpeg.c b/Source/LibMNG/libmng_jpeg.c
new file mode 100644
index 0000000..5042e1d
--- /dev/null
+++ b/Source/LibMNG/libmng_jpeg.c
@@ -0,0 +1,1088 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_jpeg.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : JPEG library interface (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the JPEG library interface * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/22/2000 - G.Juyn * */
+/* * - implemented all the JNG routines * */
+/* * * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - added tracing of JPEG calls * */
+/* * 0.5.3 - 06/24/2000 - G.Juyn * */
+/* * - fixed inclusion of IJG read/write code * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - fixed some 64-bit warnings * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* * 1.0.1 - 04/19/2001 - G.Juyn * */
+/* * - added export of JPEG functions for DLL * */
+/* * 1.0.1 - 04/22/2001 - G.Juyn * */
+/* * - fixed memory-leaks (Thanks Gregg!) * */
+/* * * */
+/* * 1.0.4 - 06/22/2002 - G.Juyn * */
+/* * - B526138 - returned IJGSRC6B calling convention to * */
+/* * default for MSVC * */
+/* * * */
+/* * 1.0.5 - 24/02/2003 - G.Juyn * */
+/* * - B683152 - libjpeg suspension not always honored correctly* */
+/* * * */
+/* * 1.0.6 - 03/04/2003 - G.Juyn * */
+/* * - fixed some compiler-warnings * */
+/* * * */
+/* * 1.0.8 - 08/01/2004 - G.Juyn * */
+/* * - added support for 3+byte pixelsize for JPEG's * */
+/* * * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_pixels.h"
+#include "libmng_jpeg.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#if defined(MNG_INCLUDE_JNG) && defined(MNG_INCLUDE_DISPLAY_PROCS)
+
+/* ************************************************************************** */
+/* * * */
+/* * Local IJG callback routines (source-manager, error-manager and such) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_IJG6B
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_init_source (j_decompress_ptr cinfo)
+#else
+void mng_init_source (j_decompress_ptr cinfo)
+#endif
+{
+ return; /* nothing needed */
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+#ifdef MNG_DEFINE_JPEG_STDCALL
+boolean MNG_DECL mng_fill_input_buffer (j_decompress_ptr cinfo)
+#else
+boolean mng_fill_input_buffer (j_decompress_ptr cinfo)
+#endif
+{
+ return FALSE; /* force IJG routine to return to caller */
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+#else
+void mng_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
+#endif
+{
+ if (num_bytes > 0) /* ignore fony calls */
+ { /* address my generic structure */
+ mng_datap pData = (mng_datap)cinfo->client_data;
+ /* address source manager */
+ mngjpeg_sourcep pSrc = pData->pJPEGdinfo->src;
+ /* problem scenario ? */
+ if (pSrc->bytes_in_buffer < (size_t)num_bytes)
+ { /* tell the boss we need to skip some data! */
+ pData->iJPEGtoskip = (mng_uint32)((size_t)num_bytes - pSrc->bytes_in_buffer);
+
+ pSrc->bytes_in_buffer = 0; /* let the JPEG lib suspend */
+ pSrc->next_input_byte = MNG_NULL;
+ }
+ else
+ { /* simply advance in the buffer */
+ pSrc->bytes_in_buffer -= num_bytes;
+ pSrc->next_input_byte += num_bytes;
+ }
+ }
+
+ return;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_skip_input_data2 (j_decompress_ptr cinfo, long num_bytes)
+#else
+void mng_skip_input_data2 (j_decompress_ptr cinfo, long num_bytes)
+#endif
+{
+ if (num_bytes > 0) /* ignore fony calls */
+ { /* address my generic structure */
+ mng_datap pData = (mng_datap)cinfo->client_data;
+ /* address source manager */
+ mngjpeg_sourcep pSrc = pData->pJPEGdinfo2->src;
+ /* problem scenario ? */
+ if (pSrc->bytes_in_buffer < (size_t)num_bytes)
+ { /* tell the boss we need to skip some data! */
+ pData->iJPEGtoskip2 = (mng_uint32)((size_t)num_bytes - pSrc->bytes_in_buffer);
+
+ pSrc->bytes_in_buffer = 0; /* let the JPEG lib suspend */
+ pSrc->next_input_byte = MNG_NULL;
+ }
+ else
+ { /* simply advance in the buffer */
+ pSrc->bytes_in_buffer -= num_bytes;
+ pSrc->next_input_byte += num_bytes;
+ }
+ }
+
+ return;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_term_source (j_decompress_ptr cinfo)
+#else
+void mng_term_source (j_decompress_ptr cinfo)
+#endif
+{
+ return; /* nothing needed */
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_USE_SETJMP
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_error_exit (j_common_ptr cinfo)
+#else
+void mng_error_exit (j_common_ptr cinfo)
+#endif
+{ /* address my generic structure */
+ mng_datap pData = (mng_datap)cinfo->client_data;
+
+#ifdef MNG_ERROR_TELLTALE /* fill the message text ??? */
+ (*cinfo->err->output_message) (cinfo);
+#endif
+ /* return to the point of no return... */
+ longjmp (pData->sErrorbuf, cinfo->err->msg_code);
+}
+#endif /* MNG_USE_SETJMP */
+
+/* ************************************************************************** */
+
+#ifdef MNG_USE_SETJMP
+#ifdef MNG_DEFINE_JPEG_STDCALL
+void MNG_DECL mng_output_message (j_common_ptr cinfo)
+#else
+void mng_output_message (j_common_ptr cinfo)
+#endif
+{
+ return; /* just do nothing ! */
+}
+#endif /* MNG_USE_SETJMP */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_IJG6B */
+
+/* ************************************************************************** */
+/* * * */
+/* * Global JPEG routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mngjpeg_initialize (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_INITIALIZE, MNG_LC_START);
+#endif
+ /* allocate space for JPEG structures if necessary */
+#ifdef MNG_INCLUDE_JNG_READ
+ if (pData->pJPEGderr == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGderr, sizeof (mngjpeg_error ));
+ if (pData->pJPEGdsrc == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGdsrc, sizeof (mngjpeg_source));
+ if (pData->pJPEGdinfo == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGdinfo, sizeof (mngjpeg_decomp));
+ /* enable reverse addressing */
+ pData->pJPEGdinfo->client_data = pData;
+
+ if (pData->pJPEGderr2 == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGderr2, sizeof (mngjpeg_error ));
+ if (pData->pJPEGdsrc2 == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGdsrc2, sizeof (mngjpeg_source));
+ if (pData->pJPEGdinfo2 == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGdinfo2, sizeof (mngjpeg_decomp));
+ /* enable reverse addressing */
+ pData->pJPEGdinfo2->client_data = pData;
+#endif
+
+#ifdef MNG_INCLUDE_JNG_WRITE
+ if (pData->pJPEGcerr == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGcerr, sizeof (mngjpeg_error ));
+ if (pData->pJPEGcinfo == MNG_NULL)
+ MNG_ALLOC (pData, pData->pJPEGcinfo, sizeof (mngjpeg_comp ));
+ /* enable reverse addressing */
+ pData->pJPEGcinfo->client_data = pData;
+#endif
+
+ if (pData->pJPEGbuf == MNG_NULL) /* initialize temporary buffers */
+ {
+ pData->iJPEGbufmax = MNG_JPEG_MAXBUF;
+ MNG_ALLOC (pData, pData->pJPEGbuf, pData->iJPEGbufmax);
+ }
+
+ if (pData->pJPEGbuf2 == MNG_NULL)
+ {
+ pData->iJPEGbufmax2 = MNG_JPEG_MAXBUF;
+ MNG_ALLOC (pData, pData->pJPEGbuf2, pData->iJPEGbufmax2);
+ }
+
+ pData->pJPEGcurrent = pData->pJPEGbuf;
+ pData->iJPEGbufremain = 0;
+ pData->pJPEGrow = MNG_NULL;
+ pData->iJPEGrowlen = 0;
+ pData->iJPEGtoskip = 0;
+
+ pData->pJPEGcurrent2 = pData->pJPEGbuf2;
+ pData->iJPEGbufremain2 = 0;
+ pData->pJPEGrow2 = MNG_NULL;
+ pData->iJPEGrowlen2 = 0;
+ pData->iJPEGtoskip2 = 0;
+ /* not doing anything yet ! */
+ pData->bJPEGcompress = MNG_FALSE;
+
+ pData->bJPEGdecompress = MNG_FALSE;
+ pData->bJPEGhasheader = MNG_FALSE;
+ pData->bJPEGdecostarted = MNG_FALSE;
+ pData->bJPEGscanstarted = MNG_FALSE;
+ pData->bJPEGscanending = MNG_FALSE;
+
+ pData->bJPEGdecompress2 = MNG_FALSE;
+ pData->bJPEGhasheader2 = MNG_FALSE;
+ pData->bJPEGdecostarted2 = MNG_FALSE;
+ pData->bJPEGscanstarted2 = MNG_FALSE;
+
+ pData->iJPEGrow = 0; /* zero input/output lines */
+ pData->iJPEGalpharow = 0;
+ pData->iJPEGrgbrow = 0;
+ pData->iJPEGdisprow = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_INITIALIZE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngjpeg_cleanup (mng_datap pData)
+{
+#if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_CLEANUP, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_IJG6B
+#ifdef MNG_USE_SETJMP
+ iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif
+
+#ifdef MNG_INCLUDE_JNG_READ /* still decompressing something ? */
+ if (pData->bJPEGdecompress)
+ jpeg_destroy_decompress (pData->pJPEGdinfo);
+ if (pData->bJPEGdecompress2)
+ jpeg_destroy_decompress (pData->pJPEGdinfo2);
+#endif
+
+#ifdef MNG_INCLUDE_JNG_WRITE
+ if (pData->bJPEGcompress) /* still compressing something ? */
+ jpeg_destroy_compress (pData->pJPEGcinfo);
+#endif
+
+#endif /* MNG_INCLUDE_IJG6B */
+ /* cleanup temporary buffers */
+ MNG_FREE (pData, pData->pJPEGbuf2, pData->iJPEGbufmax2);
+ MNG_FREE (pData, pData->pJPEGbuf, pData->iJPEGbufmax);
+ /* cleanup space for JPEG structures */
+#ifdef MNG_INCLUDE_JNG_WRITE
+ MNG_FREE (pData, pData->pJPEGcinfo, sizeof (mngjpeg_comp ));
+ MNG_FREE (pData, pData->pJPEGcerr, sizeof (mngjpeg_error ));
+#endif
+
+#ifdef MNG_INCLUDE_JNG_READ
+ MNG_FREE (pData, pData->pJPEGdinfo, sizeof (mngjpeg_decomp));
+ MNG_FREE (pData, pData->pJPEGdsrc, sizeof (mngjpeg_source));
+ MNG_FREE (pData, pData->pJPEGderr, sizeof (mngjpeg_error ));
+ MNG_FREE (pData, pData->pJPEGdinfo2, sizeof (mngjpeg_decomp));
+ MNG_FREE (pData, pData->pJPEGdsrc2, sizeof (mngjpeg_source));
+ MNG_FREE (pData, pData->pJPEGderr2, sizeof (mngjpeg_error ));
+#endif
+
+ MNG_FREE (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
+ MNG_FREE (pData, pData->pJPEGrow, pData->iJPEGrowlen);
+ /* whatever we were doing ... */
+ /* we don't anymore ... */
+ pData->bJPEGcompress = MNG_FALSE;
+
+ pData->bJPEGdecompress = MNG_FALSE;
+ pData->bJPEGhasheader = MNG_FALSE;
+ pData->bJPEGdecostarted = MNG_FALSE;
+ pData->bJPEGscanstarted = MNG_FALSE;
+ pData->bJPEGscanending = MNG_FALSE;
+
+ pData->bJPEGdecompress2 = MNG_FALSE;
+ pData->bJPEGhasheader2 = MNG_FALSE;
+ pData->bJPEGdecostarted2 = MNG_FALSE;
+ pData->bJPEGscanstarted2 = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_CLEANUP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * JPEG decompression routines (JDAT) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressinit (mng_datap pData)
+{
+#if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_IJG6B
+ /* allocate and initialize a JPEG decompression object */
+ pData->pJPEGdinfo->err = jpeg_std_error (pData->pJPEGderr);
+
+#ifdef MNG_USE_SETJMP /* setup local JPEG error-routines */
+ pData->pJPEGderr->error_exit = mng_error_exit;
+ pData->pJPEGderr->output_message = mng_output_message;
+
+ iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif /* MNG_USE_SETJMP */
+
+ /* allocate and initialize a JPEG decompression object (continued) */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_JPEG_CREATE_DECOMPRESS)
+#endif
+ jpeg_create_decompress (pData->pJPEGdinfo);
+
+ pData->bJPEGdecompress = MNG_TRUE; /* indicate it's initialized */
+
+ /* specify the source of the compressed data (eg, a file) */
+ /* no, not a file; we have buffered input */
+ pData->pJPEGdinfo->src = pData->pJPEGdsrc;
+ /* use the default handler */
+ pData->pJPEGdinfo->src->resync_to_restart = jpeg_resync_to_restart;
+ /* setup local source routine & parms */
+ pData->pJPEGdinfo->src->init_source = mng_init_source;
+ pData->pJPEGdinfo->src->fill_input_buffer = mng_fill_input_buffer;
+ pData->pJPEGdinfo->src->skip_input_data = mng_skip_input_data;
+ pData->pJPEGdinfo->src->term_source = mng_term_source;
+ pData->pJPEGdinfo->src->next_input_byte = pData->pJPEGcurrent;
+ pData->pJPEGdinfo->src->bytes_in_buffer = pData->iJPEGbufremain;
+
+#endif /* MNG_INCLUDE_IJG6B */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressdata (mng_datap pData,
+ mng_uint32 iRawsize,
+ mng_uint8p pRawdata)
+{
+ mng_retcode iRetcode;
+ mng_uint32 iRemain;
+ mng_uint8p pWork;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_START);
+#endif
+
+#if defined (MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ iRetcode = setjmp (pData->sErrorbuf);/* initialize local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif
+
+ pWork = pRawdata;
+ iRemain = iRawsize;
+
+ if (pData->iJPEGtoskip) /* JPEG-lib told us to skip some more data ? */
+ {
+ if (iRemain > pData->iJPEGtoskip) /* enough data in this buffer ? */
+ {
+ iRemain -= pData->iJPEGtoskip; /* skip enough to access the next byte */
+ pWork += pData->iJPEGtoskip;
+
+ pData->iJPEGtoskip = 0; /* no more to skip then */
+ }
+ else
+ {
+ pData->iJPEGtoskip -= iRemain; /* skip all data in the buffer */
+ iRemain = 0; /* and indicate this accordingly */
+ }
+ /* the skip set current-pointer to NULL ! */
+ pData->pJPEGcurrent = pData->pJPEGbuf;
+ }
+
+ while (iRemain) /* repeat until no more input-bytes */
+ { /* need to shift anything ? */
+ if ((pData->pJPEGcurrent > pData->pJPEGbuf) &&
+ (pData->pJPEGcurrent - pData->pJPEGbuf + pData->iJPEGbufremain + iRemain > pData->iJPEGbufmax))
+ {
+ if (pData->iJPEGbufremain > 0) /* then do so */
+ MNG_COPY (pData->pJPEGbuf, pData->pJPEGcurrent, pData->iJPEGbufremain);
+
+ pData->pJPEGcurrent = pData->pJPEGbuf;
+ }
+ /* does the remaining input fit into the buffer ? */
+ if (pData->iJPEGbufremain + iRemain <= pData->iJPEGbufmax)
+ { /* move the lot */
+ MNG_COPY ((pData->pJPEGcurrent + pData->iJPEGbufremain), pWork, iRemain);
+
+ pData->iJPEGbufremain += iRemain;/* adjust remaining_bytes counter */
+ iRemain = 0; /* and indicate there's no input left */
+ }
+ else
+ { /* calculate what does fit */
+ mng_uint32 iFits = pData->iJPEGbufmax - pData->iJPEGbufremain;
+
+ if (iFits <= 0) /* no space is just bugger 'm all */
+ MNG_ERROR (pData, MNG_JPEGBUFTOOSMALL);
+ /* move that */
+ MNG_COPY ((pData->pJPEGcurrent + pData->iJPEGbufremain), pWork, iFits);
+
+ pData->iJPEGbufremain += iFits; /* adjust remain_bytes counter */
+ iRemain -= iFits; /* and the input-parms */
+ pWork += iFits;
+ }
+
+#ifdef MNG_INCLUDE_IJG6B
+ pData->pJPEGdinfo->src->next_input_byte = pData->pJPEGcurrent;
+ pData->pJPEGdinfo->src->bytes_in_buffer = pData->iJPEGbufremain;
+
+ if (!pData->bJPEGhasheader) /* haven't got the header yet ? */
+ {
+ /* call jpeg_read_header() to obtain image info */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_HEADER)
+#endif
+ if (jpeg_read_header (pData->pJPEGdinfo, TRUE) != JPEG_SUSPENDED)
+ { /* indicate the header's oke */
+ pData->bJPEGhasheader = MNG_TRUE;
+ /* let's do some sanity checks ! */
+ if ((pData->pJPEGdinfo->image_width != pData->iDatawidth ) ||
+ (pData->pJPEGdinfo->image_height != pData->iDataheight) )
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+
+ if ( ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAY ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA) ) &&
+ (pData->pJPEGdinfo->jpeg_color_space != JCS_GRAYSCALE ) )
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+
+ if ( ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLOR ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ) &&
+ (pData->pJPEGdinfo->jpeg_color_space != JCS_YCbCr ) )
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+ /* indicate whether or not it's progressive */
+ pData->bJPEGprogressive = (mng_bool)jpeg_has_multiple_scans (pData->pJPEGdinfo);
+ /* progressive+alpha can't display "on-the-fly"!! */
+ if ((pData->bJPEGprogressive) &&
+ ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) ))
+ pData->fDisplayrow = MNG_NULL;
+ /* allocate a row of JPEG-samples */
+ if (pData->pJPEGdinfo->jpeg_color_space == JCS_YCbCr)
+ pData->iJPEGrowlen = pData->pJPEGdinfo->image_width * RGB_PIXELSIZE;
+ else
+ pData->iJPEGrowlen = pData->pJPEGdinfo->image_width;
+
+ MNG_ALLOC (pData, pData->pJPEGrow, pData->iJPEGrowlen);
+
+ pData->iJPEGrgbrow = 0; /* quite empty up to now */
+ }
+
+ pData->pJPEGcurrent = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
+ pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
+ }
+ /* decompress not started ? */
+ if ((pData->bJPEGhasheader) && (!pData->bJPEGdecostarted))
+ {
+ /* set parameters for decompression */
+
+ if (pData->bJPEGprogressive) /* progressive display ? */
+ pData->pJPEGdinfo->buffered_image = TRUE;
+
+ /* jpeg_start_decompress(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_DECOMPRESS)
+#endif
+ if (jpeg_start_decompress (pData->pJPEGdinfo) == TRUE)
+ /* indicate it started */
+ pData->bJPEGdecostarted = MNG_TRUE;
+
+ pData->pJPEGcurrent = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
+ pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
+ }
+ /* process some scanlines ? */
+ if ((pData->bJPEGhasheader) && (pData->bJPEGdecostarted) &&
+ ((!jpeg_input_complete (pData->pJPEGdinfo)) ||
+ (pData->pJPEGdinfo->output_scanline < pData->pJPEGdinfo->output_height) ||
+ ((pData->bJPEGprogressive) && (pData->bJPEGscanending))))
+ {
+ mng_int32 iLines = 0;
+
+ /* for (each output pass) */
+ do
+ { /* address the row output buffer */
+ JSAMPROW pRow = (JSAMPROW)pData->pJPEGrow;
+
+ /* init new pass ? */
+ if ((pData->bJPEGprogressive) && (!pData->bJPEGscanstarted))
+ {
+ pData->bJPEGscanstarted = MNG_TRUE;
+
+ /* adjust output decompression parameters if required */
+ /* nop */
+
+ /* start a new output pass */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_OUTPUT)
+#endif
+ jpeg_start_output (pData->pJPEGdinfo, pData->pJPEGdinfo->input_scan_number);
+
+ pData->iJPEGrow = 0; /* start at row 0 in the image again */
+ }
+
+ /* while (scan lines remain to be read) */
+ if ((!pData->bJPEGprogressive) || (!pData->bJPEGscanending))
+ {
+ do
+ {
+ /* jpeg_read_scanlines(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_SCANLINES)
+#endif
+ iLines = jpeg_read_scanlines (pData->pJPEGdinfo, (JSAMPARRAY)&pRow, 1);
+
+ pData->pJPEGcurrent = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
+ pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
+
+ if (iLines > 0) /* got something ? */
+ {
+ if (pData->fStorerow2) /* store in object ? */
+ {
+ iRetcode = ((mng_storerow)pData->fStorerow2) (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+ }
+ }
+ while ((pData->pJPEGdinfo->output_scanline < pData->pJPEGdinfo->output_height) &&
+ (iLines > 0)); /* until end-of-image or not enough input-data */
+ }
+
+ /* terminate output pass */
+ if ((pData->bJPEGprogressive) &&
+ (pData->pJPEGdinfo->output_scanline >= pData->pJPEGdinfo->output_height))
+ {
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_OUTPUT)
+#endif
+ if (jpeg_finish_output (pData->pJPEGdinfo) != JPEG_SUSPENDED)
+ { /* this scan has ended */
+ pData->bJPEGscanstarted = MNG_FALSE;
+ pData->bJPEGscanending = MNG_FALSE;
+ }
+ else
+ {
+ pData->bJPEGscanending = MNG_TRUE;
+ }
+ }
+ }
+ while ((!jpeg_input_complete (pData->pJPEGdinfo)) &&
+ (iLines > 0) && (!pData->bJPEGscanending));
+ }
+ /* end of image ? */
+ if ((pData->bJPEGhasheader) && (pData->bJPEGdecostarted) &&
+ (!pData->bJPEGscanending) && (jpeg_input_complete (pData->pJPEGdinfo)) &&
+ (pData->pJPEGdinfo->input_scan_number == pData->pJPEGdinfo->output_scan_number))
+ {
+ /* jpeg_finish_decompress(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_DECOMPRESS)
+#endif
+ if (jpeg_finish_decompress (pData->pJPEGdinfo) == TRUE)
+ { /* indicate it's done */
+ pData->bJPEGhasheader = MNG_FALSE;
+ pData->bJPEGdecostarted = MNG_FALSE;
+ pData->pJPEGcurrent = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
+ pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
+ /* remaining fluff is an error ! */
+ if ((pData->iJPEGbufremain > 0) || (iRemain > 0))
+ MNG_ERROR (pData, MNG_TOOMUCHJDAT);
+ }
+ }
+#endif /* MNG_INCLUDE_IJG6B */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressfree (mng_datap pData)
+{
+#if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_IJG6B
+#ifdef MNG_USE_SETJMP
+ iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif
+ /* free the row of JPEG-samples*/
+ MNG_FREE (pData, pData->pJPEGrow, pData->iJPEGrowlen);
+
+ /* release the JPEG decompression object */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_JPEG_DESTROY_DECOMPRESS)
+#endif
+ jpeg_destroy_decompress (pData->pJPEGdinfo);
+
+ pData->bJPEGdecompress = MNG_FALSE; /* indicate it's done */
+
+#endif /* MNG_INCLUDE_IJG6B */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+/* * * */
+/* * JPEG decompression routines (JDAA) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressinit2 (mng_datap pData)
+{
+#if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_IJG6B
+ /* allocate and initialize a JPEG decompression object */
+ pData->pJPEGdinfo2->err = jpeg_std_error (pData->pJPEGderr2);
+
+#ifdef MNG_USE_SETJMP /* setup local JPEG error-routines */
+ pData->pJPEGderr2->error_exit = mng_error_exit;
+ pData->pJPEGderr2->output_message = mng_output_message;
+
+ iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif /* MNG_USE_SETJMP */
+
+ /* allocate and initialize a JPEG decompression object (continued) */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_JPEG_CREATE_DECOMPRESS)
+#endif
+ jpeg_create_decompress (pData->pJPEGdinfo2);
+
+ pData->bJPEGdecompress2 = MNG_TRUE; /* indicate it's initialized */
+
+ /* specify the source of the compressed data (eg, a file) */
+ /* no, not a file; we have buffered input */
+ pData->pJPEGdinfo2->src = pData->pJPEGdsrc2;
+ /* use the default handler */
+ pData->pJPEGdinfo2->src->resync_to_restart = jpeg_resync_to_restart;
+ /* setup local source routine & parms */
+ pData->pJPEGdinfo2->src->init_source = mng_init_source;
+ pData->pJPEGdinfo2->src->fill_input_buffer = mng_fill_input_buffer;
+ pData->pJPEGdinfo2->src->skip_input_data = mng_skip_input_data2;
+ pData->pJPEGdinfo2->src->term_source = mng_term_source;
+ pData->pJPEGdinfo2->src->next_input_byte = pData->pJPEGcurrent2;
+ pData->pJPEGdinfo2->src->bytes_in_buffer = pData->iJPEGbufremain2;
+
+#endif /* MNG_INCLUDE_IJG6B */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressdata2 (mng_datap pData,
+ mng_uint32 iRawsize,
+ mng_uint8p pRawdata)
+{
+ mng_retcode iRetcode;
+ mng_uint32 iRemain;
+ mng_uint8p pWork;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_START);
+#endif
+
+#if defined (MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ iRetcode = setjmp (pData->sErrorbuf);/* initialize local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif
+
+ pWork = pRawdata;
+ iRemain = iRawsize;
+
+ if (pData->iJPEGtoskip2) /* JPEG-lib told us to skip some more data ? */
+ {
+ if (iRemain > pData->iJPEGtoskip2) /* enough data in this buffer ? */
+ {
+ iRemain -= pData->iJPEGtoskip2; /* skip enough to access the next byte */
+ pWork += pData->iJPEGtoskip2;
+
+ pData->iJPEGtoskip2 = 0; /* no more to skip then */
+ }
+ else
+ {
+ pData->iJPEGtoskip2 -= iRemain; /* skip all data in the buffer */
+ iRemain = 0; /* and indicate this accordingly */
+ }
+ /* the skip set current-pointer to NULL ! */
+ pData->pJPEGcurrent2 = pData->pJPEGbuf2;
+ }
+
+ while (iRemain) /* repeat until no more input-bytes */
+ { /* need to shift anything ? */
+ if ((pData->pJPEGcurrent2 > pData->pJPEGbuf2) &&
+ (pData->pJPEGcurrent2 - pData->pJPEGbuf2 + pData->iJPEGbufremain2 + iRemain > pData->iJPEGbufmax2))
+ {
+ if (pData->iJPEGbufremain2 > 0) /* then do so */
+ MNG_COPY (pData->pJPEGbuf2, pData->pJPEGcurrent2, pData->iJPEGbufremain2);
+
+ pData->pJPEGcurrent2 = pData->pJPEGbuf2;
+ }
+ /* does the remaining input fit into the buffer ? */
+ if (pData->iJPEGbufremain2 + iRemain <= pData->iJPEGbufmax2)
+ { /* move the lot */
+ MNG_COPY ((pData->pJPEGcurrent2 + pData->iJPEGbufremain2), pWork, iRemain);
+ /* adjust remaining_bytes counter */
+ pData->iJPEGbufremain2 += iRemain;
+ iRemain = 0; /* and indicate there's no input left */
+ }
+ else
+ { /* calculate what does fit */
+ mng_uint32 iFits = pData->iJPEGbufmax2 - pData->iJPEGbufremain2;
+
+ if (iFits <= 0) /* no space is just bugger 'm all */
+ MNG_ERROR (pData, MNG_JPEGBUFTOOSMALL);
+ /* move that */
+ MNG_COPY ((pData->pJPEGcurrent2 + pData->iJPEGbufremain2), pWork, iFits);
+
+ pData->iJPEGbufremain2 += iFits; /* adjust remain_bytes counter */
+ iRemain -= iFits; /* and the input-parms */
+ pWork += iFits;
+ }
+
+#ifdef MNG_INCLUDE_IJG6B
+ pData->pJPEGdinfo2->src->next_input_byte = pData->pJPEGcurrent2;
+ pData->pJPEGdinfo2->src->bytes_in_buffer = pData->iJPEGbufremain2;
+
+ if (!pData->bJPEGhasheader2) /* haven't got the header yet ? */
+ {
+ /* call jpeg_read_header() to obtain image info */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_HEADER)
+#endif
+ if (jpeg_read_header (pData->pJPEGdinfo2, TRUE) != JPEG_SUSPENDED)
+ { /* indicate the header's oke */
+ pData->bJPEGhasheader2 = MNG_TRUE;
+ /* let's do some sanity checks ! */
+ if ((pData->pJPEGdinfo2->image_width != pData->iDatawidth ) ||
+ (pData->pJPEGdinfo2->image_height != pData->iDataheight) )
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+
+ if (pData->pJPEGdinfo2->jpeg_color_space != JCS_GRAYSCALE)
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+ /* indicate whether or not it's progressive */
+ pData->bJPEGprogressive2 = (mng_bool)jpeg_has_multiple_scans (pData->pJPEGdinfo2);
+
+ if (pData->bJPEGprogressive2) /* progressive alphachannel not allowed !!! */
+ MNG_ERROR (pData, MNG_JPEGPARMSERR);
+ /* allocate a row of JPEG-samples */
+ if (pData->pJPEGdinfo2->jpeg_color_space == JCS_YCbCr)
+ pData->iJPEGrowlen2 = pData->pJPEGdinfo2->image_width * RGB_PIXELSIZE;
+ else
+ pData->iJPEGrowlen2 = pData->pJPEGdinfo2->image_width;
+
+ MNG_ALLOC (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
+
+ pData->iJPEGalpharow = 0; /* quite empty up to now */
+ }
+
+ pData->pJPEGcurrent2 = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
+ pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
+ }
+ /* decompress not started ? */
+ if ((pData->bJPEGhasheader2) && (!pData->bJPEGdecostarted2))
+ {
+ /* set parameters for decompression */
+
+ if (pData->bJPEGprogressive2) /* progressive display ? */
+ pData->pJPEGdinfo2->buffered_image = TRUE;
+
+ /* jpeg_start_decompress(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_DECOMPRESS)
+#endif
+ if (jpeg_start_decompress (pData->pJPEGdinfo2) == TRUE)
+ /* indicate it started */
+ pData->bJPEGdecostarted2 = MNG_TRUE;
+
+ pData->pJPEGcurrent2 = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
+ pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
+ }
+ /* process some scanlines ? */
+ if ((pData->bJPEGhasheader2) && (pData->bJPEGdecostarted2) &&
+ ((!jpeg_input_complete (pData->pJPEGdinfo2)) ||
+ (pData->pJPEGdinfo2->output_scanline < pData->pJPEGdinfo2->output_height)))
+ {
+ mng_int32 iLines;
+
+ /* for (each output pass) */
+ do
+ { /* address the row output buffer */
+ JSAMPROW pRow = (JSAMPROW)pData->pJPEGrow2;
+
+ /* init new pass ? */
+ if ((pData->bJPEGprogressive2) &&
+ ((!pData->bJPEGscanstarted2) ||
+ (pData->pJPEGdinfo2->output_scanline >= pData->pJPEGdinfo2->output_height)))
+ {
+ pData->bJPEGscanstarted2 = MNG_TRUE;
+
+ /* adjust output decompression parameters if required */
+ /* nop */
+
+ /* start a new output pass */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_OUTPUT)
+#endif
+ jpeg_start_output (pData->pJPEGdinfo2, pData->pJPEGdinfo2->input_scan_number);
+
+ pData->iJPEGrow = 0; /* start at row 0 in the image again */
+ }
+
+ /* while (scan lines remain to be read) */
+ do
+ {
+ /* jpeg_read_scanlines(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_SCANLINES)
+#endif
+ iLines = jpeg_read_scanlines (pData->pJPEGdinfo2, (JSAMPARRAY)&pRow, 1);
+
+ pData->pJPEGcurrent2 = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
+ pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
+
+ if (iLines > 0) /* got something ? */
+ {
+ if (pData->fStorerow3) /* store in object ? */
+ {
+ iRetcode = ((mng_storerow)pData->fStorerow3) (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+ }
+ }
+ while ((pData->pJPEGdinfo2->output_scanline < pData->pJPEGdinfo2->output_height) &&
+ (iLines > 0)); /* until end-of-image or not enough input-data */
+
+ /* terminate output pass */
+ if ((pData->bJPEGprogressive2) &&
+ (pData->pJPEGdinfo2->output_scanline >= pData->pJPEGdinfo2->output_height))
+ {
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_OUTPUT)
+#endif
+ if (jpeg_finish_output (pData->pJPEGdinfo2) == JPEG_SUSPENDED)
+ jpeg_finish_output (pData->pJPEGdinfo2);
+ /* this scan has ended */
+ pData->bJPEGscanstarted2 = MNG_FALSE;
+ }
+ }
+ while ((!jpeg_input_complete (pData->pJPEGdinfo2)) && (iLines > 0));
+ }
+ /* end of image ? */
+ if ((pData->bJPEGhasheader2) && (pData->bJPEGdecostarted2) &&
+ (jpeg_input_complete (pData->pJPEGdinfo2)) &&
+ (pData->pJPEGdinfo2->input_scan_number == pData->pJPEGdinfo2->output_scan_number))
+ {
+ /* jpeg_finish_decompress(...); */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_DECOMPRESS)
+#endif
+ if (jpeg_finish_decompress (pData->pJPEGdinfo2) == TRUE)
+ { /* indicate it's done */
+ pData->bJPEGhasheader2 = MNG_FALSE;
+ pData->bJPEGdecostarted2 = MNG_FALSE;
+ pData->pJPEGcurrent2 = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
+ pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
+ /* remaining fluff is an error ! */
+ if ((pData->iJPEGbufremain2 > 0) || (iRemain > 0))
+ MNG_ERROR (pData, MNG_TOOMUCHJDAT);
+ }
+ }
+#endif /* MNG_INCLUDE_IJG6B */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG_READ
+mng_retcode mngjpeg_decompressfree2 (mng_datap pData)
+{
+#if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
+ mng_retcode iRetcode;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_IJG6B
+#ifdef MNG_USE_SETJMP
+ iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
+ if (iRetcode != 0) /* got here from longjmp ? */
+ MNG_ERRORJ (pData, iRetcode); /* then IJG-lib issued an error */
+#endif
+ /* free the row of JPEG-samples*/
+ MNG_FREE (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
+
+ /* release the JPEG decompression object */
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_JPEG_DESTROY_DECOMPRESS)
+#endif
+ jpeg_destroy_decompress (pData->pJPEGdinfo2);
+
+ pData->bJPEGdecompress2 = MNG_FALSE; /* indicate it's done */
+
+#endif /* MNG_INCLUDE_IJG6B */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_INCLUDE_JNG_READ */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_JNG && MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_jpeg.h b/Source/LibMNG/libmng_jpeg.h
new file mode 100644
index 0000000..a072af9
--- /dev/null
+++ b/Source/LibMNG/libmng_jpeg.h
@@ -0,0 +1,57 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_jpeg.h copyright (c) 2000-2002 G.Juyn * */
+/* * version : 1.0.0 * */
+/* * * */
+/* * purpose : JPEG library interface (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the JPEG library interface * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_jpeg_h_
+#define _libmng_jpeg_h_
+
+/* ************************************************************************** */
+
+mng_retcode mngjpeg_initialize (mng_datap pData);
+mng_retcode mngjpeg_cleanup (mng_datap pData);
+
+mng_retcode mngjpeg_decompressinit (mng_datap pData);
+mng_retcode mngjpeg_decompressdata (mng_datap pData,
+ mng_uint32 iRawsize,
+ mng_uint8p pRawdata);
+mng_retcode mngjpeg_decompressfree (mng_datap pData);
+
+mng_retcode mngjpeg_decompressinit2 (mng_datap pData);
+mng_retcode mngjpeg_decompressdata2 (mng_datap pData,
+ mng_uint32 iRawsize,
+ mng_uint8p pRawdata);
+mng_retcode mngjpeg_decompressfree2 (mng_datap pData);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_jpeg_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_memory.h b/Source/LibMNG/libmng_memory.h
new file mode 100644
index 0000000..b92d0c1
--- /dev/null
+++ b/Source/LibMNG/libmng_memory.h
@@ -0,0 +1,64 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_memory.h copyright (c) 2000-2003 G.Juyn * */
+/* * version : 1.0.0 * */
+/* * * */
+/* * purpose : Memory management (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of memory management functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.3 - 06/12/2000 - G.Juyn * */
+/* * - swapped MNG_COPY parameter-names * */
+/* * 0.5.3 - 06/27/2000 - G.Juyn * */
+/* * - changed size parameter to mng_size_t * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_memory_h_
+#define _libmng_memory_h_
+
+/* ************************************************************************** */
+/* * * */
+/* * Generic memory manager macros * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INTERNAL_MEMMNGMT
+#define MNG_ALLOC(H,P,L) { P = calloc (1, (mng_size_t)(L)); \
+ if (P == 0) { MNG_ERROR (H, MNG_OUTOFMEMORY) } }
+#define MNG_ALLOCX(H,P,L) { P = calloc (1, (mng_size_t)(L)); }
+#define MNG_FREE(H,P,L) { if (P) { free (P); P = 0; } }
+#define MNG_FREEX(H,P,L) { if (P) free (P); }
+#else
+#define MNG_ALLOC(H,P,L) { P = H->fMemalloc ((mng_size_t)(L)); \
+ if (P == 0) { MNG_ERROR (H, MNG_OUTOFMEMORY) } }
+#define MNG_ALLOCX(H,P,L) { P = H->fMemalloc ((mng_size_t)(L)); }
+#define MNG_FREE(H,P,L) { if (P) { H->fMemfree (P, (mng_size_t)(L)); P = 0; } }
+#define MNG_FREEX(H,P,L) { if (P) { H->fMemfree (P, (mng_size_t)(L)); } }
+#endif /* mng_internal_memmngmt */
+
+#define MNG_COPY(D,S,L) { memcpy (D, S, (mng_size_t)(L)); }
+
+/* ************************************************************************** */
+
+#endif /* _libmng_memory_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_object_prc.c b/Source/LibMNG/libmng_object_prc.c
new file mode 100644
index 0000000..f6691ff
--- /dev/null
+++ b/Source/LibMNG/libmng_object_prc.c
@@ -0,0 +1,6998 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_object_prc.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Object processing routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the internal object processing routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - fixed to support JNG objects * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added support for global color-chunks in animation * */
+/* * - added support for global PLTE,tRNS,bKGD in animation * */
+/* * - added SAVE & SEEK animation objects * */
+/* * 0.5.2 - 05/29/2000 - G.Juyn * */
+/* * - added initialization of framenr/layernr/playtime * */
+/* * - changed ani_object create routines not to return the * */
+/* * created object (wasn't necessary) * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added object promotion routine (PROM handling) * */
+/* * - added ani-object routines for delta-image processing * */
+/* * - added compression/filter/interlace fields to * */
+/* * object-buffer for delta-image processing * */
+/* * * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - changed support for delta-image processing * */
+/* * 0.5.3 - 06/20/2000 - G.Juyn * */
+/* * - fixed some small things (as precaution) * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added processing of PLTE/tRNS & color-info for * */
+/* * delta-images in the ani_objects chain * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added support for PPLT chunk * */
+/* * * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - added support for freeze/restart/resume & go_xxxx * */
+/* * 0.9.1 - 07/16/2000 - G.Juyn * */
+/* * - fixed support for mng_display() after mng_read() * */
+/* * * */
+/* * 0.9.2 - 07/29/2000 - G.Juyn * */
+/* * - fixed small bugs in display processing * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added valid-flag to stored objects for read() / display()* */
+/* * - added routine to discard "invalid" objects * */
+/* * 0.9.3 - 10/18/2000 - G.Juyn * */
+/* * - fixed delta-processing behavior * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - added storage for pixel-/alpha-sampledepth for delta's * */
+/* * * */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - removed "old" MAGN methods 3 & 4 * */
+/* * - added "new" MAGN methods 3, 4 & 5 * */
+/* * * */
+/* * 0.9.5 - 1/22/2001 - G.Juyn * */
+/* * - B129681 - fixed compiler warnings SGI/Irix * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * 1.0.5 - 08/16/2002 - G.Juyn * */
+/* * - completed MAGN support (16-bit functions) * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - fixed reset_object_detail to clear old buffer * */
+/* * - added in-memory color-correction of abstract images * */
+/* * 1.0.5 - 10/05/2002 - G.Juyn * */
+/* * - fixed problem with cloned objects marked as invalid * */
+/* * - fixed problem cloning frozen object_buffers * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - fixed DISC support * */
+/* * 1.0.5 - 11/04/2002 - G.Juyn * */
+/* * - fixed goframe/golayer/gotime processing * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - fixed magnification bug with object 0 * */
+/* * 1.0.5 - 01/19/2003 - G.Juyn * */
+/* * - B664911 - fixed buffer overflow during init * */
+/* * * */
+/* * 1.0.6 - 04/19/2003 - G.Juyn * */
+/* * - fixed problem with infinite loops during readdisplay() * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 06/09/2003 - G. R-P * */
+/* * - added conditionals around 8-bit magn routines * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added conditionals around some JNG-supporting code * */
+/* * - removed conditionals around 8-bit magn routines * */
+/* * - added conditionals around delta-png and 16-bit code * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional * */
+/* * 1.0.6 - 07/29/2003 - G.Juyn * */
+/* * - fixed invalid test in promote_imageobject * */
+/* * 1.0.6 - 07/29/2003 - G.R-P. * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P. * */
+/* * - added conditionals around MAGN chunk support * */
+/* * * */
+/* * 1.0.7 - 03/21/2004 - G.Juyn * */
+/* * - fixed some 64-bit platform compiler warnings * */
+/* * * */
+/* * 1.0.9 - 10/10/2004 - G.R-P. * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT support * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_OBJCLEANUP * */
+/* * 1.0.9 - 12/11/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
+/* * 1.0.9 - 12/31/2004 - G.R-P. * */
+/* * - fixed warnings about possible uninitialized pointers * */
+/* * 1.0.9 - 01/02/2005 - G.Juyn * */
+/* * - fixing some compiler-warnings * */
+/* * * */
+/* * 1.0.10 - 02/07/2005 - G.Juyn * */
+/* * - fixed some compiler-warnings * */
+/* * 1.0.10 - 07/30/2005 - G.Juyn * */
+/* * - fixed problem with CLON object during readdisplay() * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_chunks.h"
+#include "libmng_objects.h"
+#include "libmng_display.h"
+#include "libmng_pixels.h"
+#include "libmng_object_prc.h"
+#include "libmng_cms.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+/* * * */
+/* * Generic object routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_drop_invalid_objects (mng_datap pData)
+{
+ mng_objectp pObject;
+ mng_objectp pNext;
+ mng_cleanupobject fCleanup;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_INVALID_OBJECTS, MNG_LC_START);
+#endif
+
+ pObject = pData->pFirstimgobj; /* get first stored image-object (if any) */
+
+ while (pObject) /* more objects to check ? */
+ {
+ pNext = ((mng_object_headerp)pObject)->pNext;
+ /* invalid ? */
+ if (!((mng_imagep)pObject)->bValid)
+ { /* call appropriate cleanup */
+ fCleanup = ((mng_object_headerp)pObject)->fCleanup;
+ fCleanup (pData, pObject);
+ }
+
+ pObject = pNext; /* neeeext */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_INVALID_OBJECTS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+MNG_LOCAL mng_retcode create_obj_general (mng_datap pData,
+ mng_size_t iObjsize,
+ mng_cleanupobject fCleanup,
+ mng_processobject fProcess,
+ mng_ptr *ppObject)
+{
+ mng_object_headerp pWork;
+
+ MNG_ALLOC (pData, pWork, iObjsize);
+
+ pWork->fCleanup = fCleanup;
+ pWork->fProcess = fProcess;
+ pWork->iObjsize = iObjsize;
+ *ppObject = (mng_ptr)pWork;
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode mng_free_obj_general (mng_datap pData,
+ mng_objectp pObject)
+{
+ MNG_FREEX (pData, pObject, ((mng_object_headerp)pObject)->iObjsize);
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Image-data-object routines * */
+/* * * */
+/* * these handle the "object buffer" as defined by the MNG specification * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_create_imagedataobject (mng_datap pData,
+ mng_bool bConcrete,
+ mng_bool bViewable,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_imagedatap *ppObject)
+{
+ mng_imagedatap pImagedata;
+ mng_uint32 iSamplesize = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_IMGDATAOBJECT, MNG_LC_START);
+#endif
+ /* get a buffer */
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ {
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_imagedata),
+ (mng_cleanupobject)mng_free_imagedataobject,
+ MNG_NULL, &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pImagedata = (mng_imagedatap)pTemp;
+ }
+#else
+ MNG_ALLOC (pData, pImagedata, sizeof (mng_imagedata));
+ /* fill the appropriate fields */
+ pImagedata->sHeader.fCleanup = (mng_cleanupobject)mng_free_imagedataobject;
+ pImagedata->sHeader.fProcess = MNG_NULL;
+#endif
+ pImagedata->iRefcount = 1;
+ pImagedata->bFrozen = MNG_FALSE;
+ pImagedata->bConcrete = bConcrete;
+ pImagedata->bViewable = bViewable;
+ pImagedata->iWidth = iWidth;
+ pImagedata->iHeight = iHeight;
+ pImagedata->iBitdepth = iBitdepth;
+ pImagedata->iColortype = iColortype;
+ pImagedata->iCompression = iCompression;
+ pImagedata->iFilter = iFilter;
+ pImagedata->iInterlace = iInterlace;
+ pImagedata->bCorrected = MNG_FALSE;
+ pImagedata->iAlphabitdepth = 0;
+ pImagedata->iJHDRcompression = 0;
+ pImagedata->iJHDRinterlace = 0;
+ pImagedata->iPixelsampledepth = iBitdepth;
+ pImagedata->iAlphasampledepth = iBitdepth;
+ /* determine samplesize from color_type/bit_depth */
+ switch (iColortype) /* for < 8-bit samples we just reserve 8 bits */
+ {
+ case 0 : ; /* gray */
+ case 8 : { /* JPEG gray */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 2;
+ else
+#endif
+ iSamplesize = 1;
+
+ break;
+ }
+ case 2 : ; /* rgb */
+ case 10 : { /* JPEG rgb */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 6;
+ else
+#endif
+ iSamplesize = 3;
+
+ break;
+ }
+ case 3 : { /* indexed */
+ iSamplesize = 1;
+ break;
+ }
+ case 4 : ; /* gray+alpha */
+ case 12 : { /* JPEG gray+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 4;
+ else
+#endif
+ iSamplesize = 2;
+
+ break;
+ }
+ case 6 : ; /* rgb+alpha */
+ case 14 : { /* JPEG rgb+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 8;
+ else
+#endif
+ iSamplesize = 4;
+
+ break;
+ }
+ }
+ /* make sure we remember all this */
+ pImagedata->iSamplesize = iSamplesize;
+ pImagedata->iRowsize = iSamplesize * iWidth;
+ pImagedata->iImgdatasize = pImagedata->iRowsize * iHeight;
+
+ if (pImagedata->iImgdatasize) /* need a buffer ? */
+ { /* so allocate it */
+ MNG_ALLOCX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
+
+ if (!pImagedata->pImgdata) /* enough memory ? */
+ {
+ MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+ }
+ /* check global stuff */
+ pImagedata->bHasGAMA = pData->bHasglobalGAMA;
+#ifndef MNG_SKIPCHUNK_cHRM
+ pImagedata->bHasCHRM = pData->bHasglobalCHRM;
+#endif
+ pImagedata->bHasSRGB = pData->bHasglobalSRGB;
+#ifndef MNG_SKIPCHUNK_iCCP
+ pImagedata->bHasICCP = pData->bHasglobalICCP;
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ pImagedata->bHasBKGD = pData->bHasglobalBKGD;
+#endif
+
+ if (pData->bHasglobalGAMA) /* global gAMA present ? */
+ pImagedata->iGamma = pData->iGlobalGamma;
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ if (pData->bHasglobalCHRM) /* global cHRM present ? */
+ {
+ pImagedata->iWhitepointx = pData->iGlobalWhitepointx;
+ pImagedata->iWhitepointy = pData->iGlobalWhitepointy;
+ pImagedata->iPrimaryredx = pData->iGlobalPrimaryredx;
+ pImagedata->iPrimaryredy = pData->iGlobalPrimaryredy;
+ pImagedata->iPrimarygreenx = pData->iGlobalPrimarygreenx;
+ pImagedata->iPrimarygreeny = pData->iGlobalPrimarygreeny;
+ pImagedata->iPrimarybluex = pData->iGlobalPrimarybluex;
+ pImagedata->iPrimarybluey = pData->iGlobalPrimarybluey;
+ }
+#endif
+
+ if (pData->bHasglobalSRGB) /* glbal sRGB present ? */
+ pImagedata->iRenderingintent = pData->iGlobalRendintent;
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pData->bHasglobalICCP) /* glbal iCCP present ? */
+ {
+ pImagedata->iProfilesize = pData->iGlobalProfilesize;
+
+ if (pImagedata->iProfilesize)
+ {
+ MNG_ALLOCX (pData, pImagedata->pProfile, pImagedata->iProfilesize);
+
+ if (!pImagedata->pProfile) /* enough memory ? */
+ {
+ MNG_FREEX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
+ MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+
+ MNG_COPY (pImagedata->pProfile, pData->pGlobalProfile, pImagedata->iProfilesize);
+ }
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ if (pData->bHasglobalBKGD) /* global bKGD present ? */
+ {
+ pImagedata->iBKGDred = pData->iGlobalBKGDred;
+ pImagedata->iBKGDgreen = pData->iGlobalBKGDgreen;
+ pImagedata->iBKGDblue = pData->iGlobalBKGDblue;
+ }
+#endif
+
+ *ppObject = pImagedata; /* return it */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_IMGDATAOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_imagedataobject (mng_datap pData,
+ mng_imagedatap pImagedata)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IMGDATAOBJECT, MNG_LC_START);
+#endif
+
+ if (pImagedata->iRefcount) /* decrease reference count */
+ pImagedata->iRefcount--;
+
+ if (!pImagedata->iRefcount) /* reached zero ? */
+ {
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pImagedata->iProfilesize) /* stored an iCCP profile ? */
+ MNG_FREEX (pData, pImagedata->pProfile, pImagedata->iProfilesize);
+#endif
+ if (pImagedata->iImgdatasize) /* sample-buffer present ? */
+ MNG_FREEX (pData, pImagedata->pImgdata, pImagedata->iImgdatasize);
+ /* drop the buffer */
+ MNG_FREEX (pData, pImagedata, sizeof (mng_imagedata));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IMGDATAOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_clone_imagedataobject (mng_datap pData,
+ mng_bool bConcrete,
+ mng_imagedatap pSource,
+ mng_imagedatap *ppClone)
+{
+ mng_imagedatap pNewdata;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLONE_IMGDATAOBJECT, MNG_LC_START);
+#endif
+ /* get a buffer */
+ MNG_ALLOC (pData, pNewdata, sizeof (mng_imagedata));
+ /* blatently copy the original buffer */
+ MNG_COPY (pNewdata, pSource, sizeof (mng_imagedata));
+
+ pNewdata->iRefcount = 1; /* only the reference count */
+ pNewdata->bConcrete = bConcrete; /* and concrete-flag are different */
+ pNewdata->bFrozen = MNG_FALSE;
+
+ if (pNewdata->iImgdatasize) /* sample buffer present ? */
+ {
+ MNG_ALLOCX (pData, pNewdata->pImgdata, pNewdata->iImgdatasize);
+
+ if (!pNewdata->pImgdata) /* not enough memory ? */
+ {
+ MNG_FREEX (pData, pNewdata, sizeof (mng_imagedata));
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+ /* make a copy */
+ MNG_COPY (pNewdata->pImgdata, pSource->pImgdata, pNewdata->iImgdatasize);
+ }
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pNewdata->iProfilesize) /* iCCP profile present ? */
+ {
+ MNG_ALLOCX (pData, pNewdata->pProfile, pNewdata->iProfilesize);
+
+ if (!pNewdata->pProfile) /* enough memory ? */
+ {
+ MNG_FREEX (pData, pNewdata, sizeof (mng_imagedata));
+ MNG_ERROR (pData, MNG_OUTOFMEMORY);
+ }
+ /* make a copy */
+ MNG_COPY (pNewdata->pProfile, pSource->pProfile, pNewdata->iProfilesize);
+ }
+#endif
+
+ *ppClone = pNewdata; /* return the clone */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLONE_IMGDATAOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Image-object routines * */
+/* * * */
+/* * these handle the "object" as defined by the MNG specification * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_create_imageobject (mng_datap pData,
+ mng_uint16 iId,
+ mng_bool bConcrete,
+ mng_bool bVisible,
+ mng_bool bViewable,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_int32 iPosx,
+ mng_int32 iPosy,
+ mng_bool bClipped,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb,
+ mng_imagep *ppObject)
+{
+ mng_imagep pImage;
+ mng_imagep pPrev, pNext;
+ mng_retcode iRetcode;
+ mng_imagedatap pImgbuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_IMGOBJECT, MNG_LC_START);
+#endif
+ /* get a buffer */
+ MNG_ALLOC (pData, pImage, sizeof (mng_image));
+ /* now get a new "object buffer" */
+ iRetcode = mng_create_imagedataobject (pData, bConcrete, bViewable,
+ iWidth, iHeight, iBitdepth, iColortype,
+ iCompression, iFilter, iInterlace,
+ &pImgbuf);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pImage, sizeof (mng_image));
+ return iRetcode;
+ }
+ /* fill the appropriate fields */
+ pImage->sHeader.fCleanup = (mng_cleanupobject)mng_free_imageobject;
+ pImage->sHeader.fProcess = MNG_NULL;
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ pImage->sHeader.iObjsize = sizeof (mng_image);
+#endif
+ pImage->iId = iId;
+ pImage->bFrozen = MNG_FALSE;
+ pImage->bVisible = bVisible;
+ pImage->bViewable = bViewable;
+ pImage->bValid = (mng_bool)((pData->bDisplaying) &&
+ ((pData->bRunning) || (pData->bSearching)) &&
+ (!pData->bFreezing));
+ pImage->iPosx = iPosx;
+ pImage->iPosy = iPosy;
+ pImage->bClipped = bClipped;
+ pImage->iClipl = iClipl;
+ pImage->iClipr = iClipr;
+ pImage->iClipt = iClipt;
+ pImage->iClipb = iClipb;
+#ifndef MNG_SKIPCHUNK_MAGN
+ pImage->iMAGN_MethodX = 0;
+ pImage->iMAGN_MethodY = 0;
+ pImage->iMAGN_MX = 0;
+ pImage->iMAGN_MY = 0;
+ pImage->iMAGN_ML = 0;
+ pImage->iMAGN_MR = 0;
+ pImage->iMAGN_MT = 0;
+ pImage->iMAGN_MB = 0;
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ pImage->iPastx = 0;
+ pImage->iPasty = 0;
+#endif
+ pImage->pImgbuf = pImgbuf;
+
+ if (iId) /* only if not object 0 ! */
+ { /* find previous lower object-id */
+ pPrev = (mng_imagep)pData->pLastimgobj;
+
+ while ((pPrev) && (pPrev->iId > iId))
+ pPrev = (mng_imagep)pPrev->sHeader.pPrev;
+
+ if (pPrev) /* found it ? */
+ {
+ pImage->sHeader.pPrev = pPrev; /* than link it in place */
+ pImage->sHeader.pNext = pPrev->sHeader.pNext;
+ pPrev->sHeader.pNext = pImage;
+ }
+ else /* if not found, it becomes the first ! */
+ {
+ pImage->sHeader.pNext = pData->pFirstimgobj;
+ pData->pFirstimgobj = pImage;
+ }
+
+ pNext = (mng_imagep)pImage->sHeader.pNext;
+
+ if (pNext)
+ pNext->sHeader.pPrev = pImage;
+ else
+ pData->pLastimgobj = pImage;
+
+ }
+
+ *ppObject = pImage; /* and return the new buffer */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* okido */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_imageobject (mng_datap pData,
+ mng_imagep pImage)
+{
+ mng_retcode iRetcode;
+ mng_imagep pPrev = pImage->sHeader.pPrev;
+ mng_imagep pNext = pImage->sHeader.pNext;
+ mng_imagedatap pImgbuf = pImage->pImgbuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IMGOBJECT, MNG_LC_START);
+#endif
+
+ if (pImage->iId) /* not for object 0 */
+ {
+ if (pPrev) /* unlink from the list first ! */
+ pPrev->sHeader.pNext = pImage->sHeader.pNext;
+ else
+ pData->pFirstimgobj = pImage->sHeader.pNext;
+
+ if (pNext)
+ pNext->sHeader.pPrev = pImage->sHeader.pPrev;
+ else
+ pData->pLastimgobj = pImage->sHeader.pPrev;
+
+ }
+ /* unlink the image-data buffer */
+ iRetcode = mng_free_imagedataobject (pData, pImgbuf);
+ /* drop its own buffer */
+ MNG_FREEX (pData, pImage, sizeof (mng_image));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+mng_imagep mng_find_imageobject (mng_datap pData,
+ mng_uint16 iId)
+{
+ mng_imagep pImage = (mng_imagep)pData->pFirstimgobj;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (pData, MNG_FN_FIND_IMGOBJECT, MNG_LC_START);
+#endif
+ /* look up the right id */
+ while ((pImage) && (pImage->iId != iId))
+ pImage = (mng_imagep)pImage->sHeader.pNext;
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ if ((!pImage) && (pData->eImagetype == mng_it_mpng))
+ pImage = pData->pObjzero;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (pData, MNG_FN_FIND_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return pImage;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_clone_imageobject (mng_datap pData,
+ mng_uint16 iId,
+ mng_bool bPartial,
+ mng_bool bVisible,
+ mng_bool bAbstract,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy,
+ mng_imagep pSource,
+ mng_imagep *ppClone)
+{
+ mng_imagep pNew;
+ mng_imagep pPrev, pNext;
+ mng_retcode iRetcode;
+ mng_imagedatap pImgbuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLONE_IMGOBJECT, MNG_LC_START);
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ if ((pSource->iId) && /* needs magnification ? */
+ ((pSource->iMAGN_MethodX) || (pSource->iMAGN_MethodY)))
+ {
+ iRetcode = mng_magnify_imageobject (pData, pSource);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+ /* get a buffer */
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ {
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_image),
+ (mng_cleanupobject)mng_free_imageobject,
+ MNG_NULL, &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pNew = (mng_imagep)pTemp;
+ }
+#else
+ MNG_ALLOC (pData, pNew, sizeof (mng_image));
+ /* fill or copy the appropriate fields */
+ pNew->sHeader.fCleanup = (mng_cleanupobject)mng_free_imageobject;
+ pNew->sHeader.fProcess = MNG_NULL;
+#endif
+ pNew->iId = iId;
+ pNew->bFrozen = MNG_FALSE;
+ pNew->bVisible = bVisible;
+ pNew->bViewable = pSource->bViewable;
+ pNew->bValid = MNG_TRUE;
+
+ if (bHasloca) /* location info available ? */
+ {
+ if (iLocationtype == 0) /* absolute position ? */
+ {
+ pNew->iPosx = iLocationx;
+ pNew->iPosy = iLocationy;
+ }
+ else /* relative */
+ {
+ pNew->iPosx = pSource->iPosx + iLocationx;
+ pNew->iPosy = pSource->iPosy + iLocationy;
+ }
+ }
+ else /* copy from source */
+ {
+ pNew->iPosx = pSource->iPosx;
+ pNew->iPosy = pSource->iPosy;
+ }
+ /* copy clipping info */
+ pNew->bClipped = pSource->bClipped;
+ pNew->iClipl = pSource->iClipl;
+ pNew->iClipr = pSource->iClipr;
+ pNew->iClipt = pSource->iClipt;
+ pNew->iClipb = pSource->iClipb;
+#ifndef MNG_SKIPCHUNK_MAGN
+ /* copy magnification info */
+/* pNew->iMAGN_MethodX = pSource->iMAGN_MethodX; LET'S NOT !!!!!!
+ pNew->iMAGN_MethodY = pSource->iMAGN_MethodY;
+ pNew->iMAGN_MX = pSource->iMAGN_MX;
+ pNew->iMAGN_MY = pSource->iMAGN_MY;
+ pNew->iMAGN_ML = pSource->iMAGN_ML;
+ pNew->iMAGN_MR = pSource->iMAGN_MR;
+ pNew->iMAGN_MT = pSource->iMAGN_MT;
+ pNew->iMAGN_MB = pSource->iMAGN_MB; */
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ pNew->iPastx = 0; /* initialize PAST info */
+ pNew->iPasty = 0;
+#endif
+
+ if (iId) /* not for object 0 */
+ { /* find previous lower object-id */
+ pPrev = (mng_imagep)pData->pLastimgobj;
+ while ((pPrev) && (pPrev->iId > iId))
+ pPrev = (mng_imagep)pPrev->sHeader.pPrev;
+
+ if (pPrev) /* found it ? */
+ {
+ pNew->sHeader.pPrev = pPrev; /* than link it in place */
+ pNew->sHeader.pNext = pPrev->sHeader.pNext;
+ pPrev->sHeader.pNext = pNew;
+ }
+ else /* if not found, it becomes the first ! */
+ {
+ pNew->sHeader.pNext = pData->pFirstimgobj;
+ pData->pFirstimgobj = pNew;
+ }
+
+ pNext = (mng_imagep)pNew->sHeader.pNext;
+
+ if (pNext)
+ pNext->sHeader.pPrev = pNew;
+ else
+ pData->pLastimgobj = pNew;
+
+ }
+
+ if (bPartial) /* partial clone ? */
+ {
+ pNew->pImgbuf = pSource->pImgbuf; /* use the same object buffer */
+ pNew->pImgbuf->iRefcount++; /* and increase the reference count */
+ }
+ else /* create a full clone ! */
+ {
+ mng_bool bConcrete = MNG_FALSE; /* it's abstract by default (?) */
+
+ if (!bAbstract) /* determine concreteness from source ? */
+ bConcrete = pSource->pImgbuf->bConcrete;
+ /* create a full clone ! */
+ iRetcode = mng_clone_imagedataobject (pData, bConcrete, pSource->pImgbuf, &pImgbuf);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pNew, sizeof (mng_image));
+ return iRetcode;
+ }
+
+ pNew->pImgbuf = pImgbuf; /* and remember it */
+ }
+
+ *ppClone = pNew; /* return it */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLONE_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_renum_imageobject (mng_datap pData,
+ mng_imagep pSource,
+ mng_uint16 iId,
+ mng_bool bVisible,
+ mng_bool bAbstract,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy)
+{
+ mng_imagep pPrev, pNext;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RENUM_IMGOBJECT, MNG_LC_START);
+#endif
+
+ pSource->bVisible = bVisible; /* store the new visibility */
+
+ if (bHasloca) /* location info available ? */
+ {
+ if (iLocationtype == 0) /* absolute position ? */
+ {
+ pSource->iPosx = iLocationx;
+ pSource->iPosy = iLocationy;
+ }
+ else /* relative */
+ {
+ pSource->iPosx = pSource->iPosx + iLocationx;
+ pSource->iPosy = pSource->iPosy + iLocationy;
+ }
+ }
+
+ if (iId) /* not for object 0 */
+ { /* find previous lower object-id */
+ pPrev = (mng_imagep)pData->pLastimgobj;
+ while ((pPrev) && (pPrev->iId > iId))
+ pPrev = (mng_imagep)pPrev->sHeader.pPrev;
+ /* different from current ? */
+ if (pPrev != (mng_imagep)pSource->sHeader.pPrev)
+ {
+ if (pSource->sHeader.pPrev) /* unlink from current position !! */
+ ((mng_imagep)pSource->sHeader.pPrev)->sHeader.pNext = pSource->sHeader.pNext;
+ else
+ pData->pFirstimgobj = pSource->sHeader.pNext;
+
+ if (pSource->sHeader.pNext)
+ ((mng_imagep)pSource->sHeader.pNext)->sHeader.pPrev = pSource->sHeader.pPrev;
+ else
+ pData->pLastimgobj = pSource->sHeader.pPrev;
+
+ if (pPrev) /* found the previous ? */
+ { /* than link it in place */
+ pSource->sHeader.pPrev = pPrev;
+ pSource->sHeader.pNext = pPrev->sHeader.pNext;
+ pPrev->sHeader.pNext = pSource;
+ }
+ else /* if not found, it becomes the first ! */
+ {
+ pSource->sHeader.pNext = pData->pFirstimgobj;
+ pData->pFirstimgobj = pSource;
+ }
+
+ pNext = (mng_imagep)pSource->sHeader.pNext;
+
+ if (pNext)
+ pNext->sHeader.pPrev = pSource;
+ else
+ pData->pLastimgobj = pSource;
+
+ }
+ }
+
+ pSource->iId = iId; /* now set the new id! */
+
+ if (bAbstract) /* force it to abstract ? */
+ pSource->pImgbuf->bConcrete = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RENUM_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_reset_object_details (mng_datap pData,
+ mng_imagep pImage,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_bool bResetall)
+{
+ mng_imagedatap pBuf = pImage->pImgbuf;
+ mng_uint32 iSamplesize = 0;
+ mng_uint32 iRowsize;
+ mng_uint32 iImgdatasize;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESET_OBJECTDETAILS, MNG_LC_START);
+#endif
+
+ pBuf->iWidth = iWidth; /* set buffer characteristics */
+ pBuf->iHeight = iHeight;
+ pBuf->iBitdepth = iBitdepth;
+ pBuf->iColortype = iColortype;
+ pBuf->iCompression = iCompression;
+ pBuf->iFilter = iFilter;
+ pBuf->iInterlace = iInterlace;
+ pBuf->bCorrected = MNG_FALSE;
+ pBuf->iAlphabitdepth = 0;
+ /* determine samplesize from color_type/bit_depth */
+ switch (iColortype) /* for < 8-bit samples we just reserve 8 bits */
+ {
+ case 0 : ; /* gray */
+ case 8 : { /* JPEG gray */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 2;
+ else
+#endif
+ iSamplesize = 1;
+
+ break;
+ }
+ case 2 : ; /* rgb */
+ case 10 : { /* JPEG rgb */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 6;
+ else
+#endif
+ iSamplesize = 3;
+
+ break;
+ }
+ case 3 : { /* indexed */
+ iSamplesize = 1;
+ break;
+ }
+ case 4 : ; /* gray+alpha */
+ case 12 : { /* JPEG gray+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 4;
+ else
+#endif
+ iSamplesize = 2;
+
+ break;
+ }
+ case 6 : ; /* rgb+alpha */
+ case 14 : { /* JPEG rgb+alpha */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iSamplesize = 8;
+ else
+#endif
+ iSamplesize = 4;
+
+ break;
+ }
+ }
+
+ iRowsize = iSamplesize * iWidth;
+ iImgdatasize = iRowsize * iHeight;
+ /* buffer size changed ? */
+ if (iImgdatasize != pBuf->iImgdatasize)
+ { /* drop the old one */
+ MNG_FREE (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+
+ if (iImgdatasize) /* allocate new sample-buffer ? */
+ MNG_ALLOC (pData, pBuf->pImgdata, iImgdatasize);
+ }
+ else
+ {
+ if (iImgdatasize) /* clear old buffer */
+ {
+ mng_uint8p pTemp = pBuf->pImgdata;
+ mng_uint32 iX;
+
+ for (iX = 0; iX < (iImgdatasize & (mng_uint32)(~3L)); iX += 4)
+ {
+ *((mng_uint32p)pTemp) = 0x00000000l;
+ pTemp += 4;
+ }
+
+ while (pTemp < (pBuf->pImgdata + iImgdatasize))
+ {
+ *pTemp = 0;
+ pTemp++;
+ }
+ }
+ }
+
+ pBuf->iSamplesize = iSamplesize; /* remember new sizes */
+ pBuf->iRowsize = iRowsize;
+ pBuf->iImgdatasize = iImgdatasize;
+
+ if (!pBuf->iPixelsampledepth) /* set delta sampledepths if empty */
+ pBuf->iPixelsampledepth = iBitdepth;
+ if (!pBuf->iAlphasampledepth)
+ pBuf->iAlphasampledepth = iBitdepth;
+ /* dimension set and clipping not ? */
+ if ((iWidth) && (iHeight) && (!pImage->bClipped))
+ {
+ pImage->iClipl = 0; /* set clipping to dimension by default */
+ pImage->iClipr = iWidth;
+ pImage->iClipt = 0;
+ pImage->iClipb = iHeight;
+ }
+
+#ifndef MNG_SKIPCHUNK_MAGN
+ if (pImage->iId) /* reset magnification info ? */
+ {
+ pImage->iMAGN_MethodX = 0;
+ pImage->iMAGN_MethodY = 0;
+ pImage->iMAGN_MX = 0;
+ pImage->iMAGN_MY = 0;
+ pImage->iMAGN_ML = 0;
+ pImage->iMAGN_MR = 0;
+ pImage->iMAGN_MT = 0;
+ pImage->iMAGN_MB = 0;
+ }
+#endif
+
+ if (bResetall) /* reset the other characteristics ? */
+ {
+#ifndef MNG_SKIPCHUNK_PAST
+ pImage->iPastx = 0;
+ pImage->iPasty = 0;
+#endif
+
+ pBuf->bHasPLTE = MNG_FALSE;
+ pBuf->bHasTRNS = MNG_FALSE;
+ pBuf->bHasGAMA = pData->bHasglobalGAMA;
+#ifndef MNG_SKIPCHUNK_cHRM
+ pBuf->bHasCHRM = pData->bHasglobalCHRM;
+#endif
+ pBuf->bHasSRGB = pData->bHasglobalSRGB;
+#ifndef MNG_SKIPCHUNK_iCCP
+ pBuf->bHasICCP = pData->bHasglobalICCP;
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ pBuf->bHasBKGD = pData->bHasglobalBKGD;
+#endif
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBuf->iProfilesize) /* drop possibly old ICC profile */
+ {
+ MNG_FREE (pData, pBuf->pProfile, pBuf->iProfilesize);
+ pBuf->iProfilesize = 0;
+ }
+#endif
+
+ if (pData->bHasglobalGAMA) /* global gAMA present ? */
+ pBuf->iGamma = pData->iGlobalGamma;
+
+#ifndef MNG_SKIPCHUNK_cHRM
+ if (pData->bHasglobalCHRM) /* global cHRM present ? */
+ {
+ pBuf->iWhitepointx = pData->iGlobalWhitepointx;
+ pBuf->iWhitepointy = pData->iGlobalWhitepointy;
+ pBuf->iPrimaryredx = pData->iGlobalPrimaryredx;
+ pBuf->iPrimaryredy = pData->iGlobalPrimaryredy;
+ pBuf->iPrimarygreenx = pData->iGlobalPrimarygreenx;
+ pBuf->iPrimarygreeny = pData->iGlobalPrimarygreeny;
+ pBuf->iPrimarybluex = pData->iGlobalPrimarybluex;
+ pBuf->iPrimarybluey = pData->iGlobalPrimarybluey;
+ }
+#endif
+
+ if (pData->bHasglobalSRGB) /* global sRGB present ? */
+ pBuf->iRenderingintent = pData->iGlobalRendintent;
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pData->bHasglobalICCP) /* global iCCP present ? */
+ {
+ if (pData->iGlobalProfilesize)
+ {
+ MNG_ALLOC (pData, pBuf->pProfile, pData->iGlobalProfilesize);
+ MNG_COPY (pBuf->pProfile, pData->pGlobalProfile, pData->iGlobalProfilesize);
+ }
+
+ pBuf->iProfilesize = pData->iGlobalProfilesize;
+ }
+#endif
+
+#ifndef MNG_SKIPCHUNK_bKGD
+ if (pData->bHasglobalBKGD) /* global bKGD present ? */
+ {
+ pBuf->iBKGDred = pData->iGlobalBKGDred;
+ pBuf->iBKGDgreen = pData->iGlobalBKGDgreen;
+ pBuf->iBKGDblue = pData->iGlobalBKGDblue;
+ }
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESET_OBJECTDETAILS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#if !defined(MNG_NO_DELTA_PNG) || !defined(MNG_SKIPCHUNK_PAST) || !defined(MNG_SKIPCHUNK_MAGN)
+mng_retcode mng_promote_imageobject (mng_datap pData,
+ mng_imagep pImage,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+ mng_imagedatap pBuf = pImage->pImgbuf;
+ mng_uint32 iW = pBuf->iWidth;
+ mng_uint32 iH = pBuf->iHeight;
+ mng_uint8p pNewbuf;
+ mng_uint32 iNewbufsize;
+ mng_uint32 iNewrowsize;
+ mng_uint32 iNewsamplesize = pBuf->iSamplesize;
+ mng_uint32 iY;
+ mng_uint8 iTempdepth;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IMGOBJECT, MNG_LC_START);
+#endif
+
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (iBitdepth < 8)
+ iBitdepth=8;
+ if (pBuf->iBitdepth < 8)
+ pBuf->iBitdepth=8;
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth > 8)
+ iBitdepth=8;
+ if (pBuf->iBitdepth > 8)
+ pBuf->iBitdepth=8;
+#endif
+
+ pData->fPromoterow = MNG_NULL; /* init promotion fields */
+ pData->fPromBitdepth = MNG_NULL;
+ pData->iPromColortype = iColortype;
+ pData->iPromBitdepth = iBitdepth;
+ pData->iPromFilltype = iFilltype;
+
+ if (iBitdepth != pBuf->iBitdepth) /* determine bitdepth promotion */
+ {
+ if (pBuf->iColortype == MNG_COLORTYPE_INDEXED)
+ iTempdepth = 8;
+ else
+ iTempdepth = pBuf->iBitdepth;
+
+#ifndef MNG_NO_DELTA_PNG
+ if (iFilltype == MNG_FILLMETHOD_ZEROFILL)
+ {
+ switch (iTempdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ switch (iBitdepth)
+ {
+ case 2 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_2; break; }
+ case 4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_4; break; }
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_1_16; break; }
+#endif
+ }
+ break;
+ }
+ case 2 : {
+ switch (iBitdepth)
+ {
+ case 4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_4; break; }
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_2_16; break; }
+#endif
+ }
+ break;
+ }
+ case 4 : {
+ switch (iBitdepth)
+ {
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_4_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_4_16; break; }
+#endif
+ }
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromBitdepth = (mng_fptr)mng_promote_zerofill_8_16;
+#endif
+ break;
+ }
+ }
+ }
+ else
+#endif
+ {
+ switch (iTempdepth)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case 1 : {
+ switch (iBitdepth)
+ {
+ case 2 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_2; break; }
+ case 4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_4; break; }
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_1_16; break; }
+#endif
+ }
+ break;
+ }
+ case 2 : {
+ switch (iBitdepth)
+ {
+ case 4 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_4; break; }
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_2_16; break; }
+#endif
+ }
+ break;
+ }
+ case 4 : {
+ switch (iBitdepth)
+ {
+ case 8 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_4_8; break; }
+#ifndef MNG_NO_16BIT_SUPPORT
+ case 16 : { pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_4_16; break; }
+#endif
+ }
+ break;
+ }
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case 8 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromBitdepth = (mng_fptr)mng_promote_replicate_8_16;
+#endif
+ break;
+ }
+ }
+ }
+ }
+ /* g -> g */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
+ (iColortype == MNG_COLORTYPE_GRAY))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_g16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_g8;
+ }
+
+ iNewsamplesize = 1;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 2;
+#endif
+ }
+ else /* g -> ga */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
+ (iColortype == MNG_COLORTYPE_GRAYA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_ga16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_ga8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_ga16;
+#endif
+
+ iNewsamplesize = 2;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 4;
+#endif
+ }
+ else /* g -> rgb */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
+ (iColortype == MNG_COLORTYPE_RGB))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_rgb16;
+#endif
+
+ iNewsamplesize = 3;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 6;
+#endif
+ }
+ else /* g -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAY) &&
+ (iColortype == MNG_COLORTYPE_RGBA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* ga -> ga */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAYA) &&
+ (iColortype == MNG_COLORTYPE_GRAYA))
+ {
+ iNewsamplesize = 2;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_ga16;
+ if (iBitdepth == 16)
+ iNewsamplesize = 4;
+#endif
+ }
+ else /* ga -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_GRAYA) &&
+ (iColortype == MNG_COLORTYPE_RGBA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_ga16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* rgb -> rgb */
+ if ((pBuf->iColortype == MNG_COLORTYPE_RGB) &&
+ (iColortype == MNG_COLORTYPE_RGB))
+ {
+ iNewsamplesize = 3;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgb16;
+ if (iBitdepth == 16)
+ iNewsamplesize = 6;
+#endif
+ }
+ else /* rgb -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_RGB) &&
+ (iColortype == MNG_COLORTYPE_RGBA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* indexed -> rgb */
+ if ((pBuf->iColortype == MNG_COLORTYPE_INDEXED) &&
+ (iColortype == MNG_COLORTYPE_RGB))
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgb16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgb8;
+
+ iNewsamplesize = 3;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 6;
+#endif
+ }
+ else /* indexed -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_INDEXED) &&
+ (iColortype == MNG_COLORTYPE_RGBA))
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_idx8_rgba8;
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* rgba -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_RGBA) &&
+ (iColortype == MNG_COLORTYPE_RGBA))
+ {
+ iNewsamplesize = 4;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgba8_rgba16;
+ }
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+#ifdef MNG_INCLUDE_JNG
+ else /* JPEG g -> g */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
+ (iColortype == MNG_COLORTYPE_JPEGGRAY))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_g16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_g8;
+ }
+
+ iNewsamplesize = 1;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 2;
+#endif
+ }
+ else /* JPEG g -> ga */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
+ (iColortype == MNG_COLORTYPE_JPEGGRAYA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_ga16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_ga8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_ga16;
+#endif
+
+ iNewsamplesize = 2;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 4;
+#endif
+ }
+ else /* JPEG g -> rgb */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLOR))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgb8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_rgb16;
+#endif
+
+ iNewsamplesize = 3;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 6;
+#endif
+ }
+ else /* JPEG g -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAY) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLORA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_g8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_g16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* JPEG ga -> ga */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA) &&
+ (iColortype == MNG_COLORTYPE_JPEGGRAYA))
+ {
+ iNewsamplesize = 2;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_ga16;
+ if (iBitdepth == 16)
+ iNewsamplesize = 4;
+#endif
+
+ }
+ else /* JPEG ga -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGGRAYA) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLORA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_ga8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_ga16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* JPEG rgb -> rgb */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLOR))
+ {
+ iNewsamplesize = 3;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgb16;
+ if (iBitdepth == 16)
+ iNewsamplesize = 6;
+#endif
+
+ }
+ else /* JPEG rgb -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLOR) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLORA))
+ {
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba16;
+ else
+#endif
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb8_rgba8;
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else /* source = 16 bits */
+ pData->fPromoterow = (mng_fptr)mng_promote_rgb16_rgba16;
+#endif
+
+ iNewsamplesize = 4;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (iBitdepth == 16) /* 16-bit wide ? */
+ iNewsamplesize = 8;
+#endif
+ }
+ else /* JPEG rgba -> rgba */
+ if ((pBuf->iColortype == MNG_COLORTYPE_JPEGCOLORA) &&
+ (iColortype == MNG_COLORTYPE_JPEGCOLORA))
+ {
+ iNewsamplesize = 4;
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth <= 8) /* source <= 8 bits */
+ if (iBitdepth == 16)
+ pData->fPromoterow = (mng_fptr)mng_promote_rgba8_rgba16;
+ if (iBitdepth == 16)
+ iNewsamplesize = 8;
+#endif
+ }
+#endif /* JNG */
+
+ /* found a proper promotion ? */
+ if (pData->fPromoterow)
+ {
+ pData->pPromBuf = (mng_ptr)pBuf;
+ pData->iPromWidth = pBuf->iWidth;
+ iNewrowsize = iW * iNewsamplesize;
+ iNewbufsize = iH * iNewrowsize;
+
+ MNG_ALLOC (pData, pNewbuf, iNewbufsize);
+
+ pData->pPromSrc = (mng_ptr)pBuf->pImgdata;
+ pData->pPromDst = (mng_ptr)pNewbuf;
+ iY = 0;
+
+ while ((!iRetcode) && (iY < iH))
+ {
+ iRetcode = ((mng_promoterow)pData->fPromoterow) (pData);
+ pData->pPromSrc = (mng_uint8p)pData->pPromSrc + pBuf->iRowsize;
+ pData->pPromDst = (mng_uint8p)pData->pPromDst + iNewrowsize;
+/* pData->pPromSrc = (mng_ptr)((mng_uint32)pData->pPromSrc + pBuf->iRowsize); */
+/* pData->pPromDst = (mng_ptr)((mng_uint32)pData->pPromDst + iNewrowsize); */
+ iY++;
+ }
+
+ MNG_FREEX (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+
+ pBuf->iBitdepth = iBitdepth;
+ pBuf->iColortype = iColortype;
+ pBuf->iSamplesize = iNewsamplesize;
+ pBuf->iRowsize = iNewrowsize;
+ pBuf->iImgdatasize = iNewbufsize;
+ pBuf->pImgdata = pNewbuf;
+ pBuf->bHasPLTE = MNG_FALSE;
+ pBuf->iPLTEcount = 0;
+ pBuf->bHasTRNS = MNG_FALSE;
+ pBuf->iTRNScount = 0;
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_magnify_imageobject (mng_datap pData,
+ mng_imagep pImage)
+{
+ mng_uint8p pNewdata;
+ mng_uint8p pSrcline1;
+ mng_uint8p pSrcline2;
+ mng_uint8p pTempline;
+ mng_uint8p pDstline;
+ mng_uint32 iNewrowsize;
+ mng_uint32 iNewsize;
+ mng_uint32 iY;
+ mng_int32 iS, iM;
+ mng_retcode iRetcode;
+
+ mng_imagedatap pBuf = pImage->pImgbuf;
+ mng_uint32 iNewW = pBuf->iWidth;
+ mng_uint32 iNewH = pBuf->iHeight;
+ mng_magnify_x fMagnifyX = MNG_NULL;
+ mng_magnify_y fMagnifyY = MNG_NULL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_IMGOBJECT, MNG_LC_START);
+#endif
+
+ if (pBuf->iColortype == MNG_COLORTYPE_INDEXED) /* indexed color ? */
+ { /* concrete buffer ? */
+ if ((pBuf->bConcrete) && (pImage->iId))
+ MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+ if (pBuf->iTRNScount) /* with transparency ? */
+ iRetcode = mng_promote_imageobject (pData, pImage, 8, 6, 0);
+ else
+ iRetcode = mng_promote_imageobject (pData, pImage, 8, 2, 0);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_MAGN
+ /* Promote everything to RGBA, using fill method 0 (LBR) */
+ iRetcode = mng_promote_imageobject (pData, pImage, 8, 6, 0);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+
+ if (pImage->iMAGN_MethodX) /* determine new width */
+ {
+ if (pImage->iMAGN_MethodX == 1)
+ {
+ iNewW = pImage->iMAGN_ML;
+ if (pBuf->iWidth > 1)
+ iNewW = iNewW + pImage->iMAGN_MR;
+ if (pBuf->iWidth > 2)
+ iNewW = iNewW + (pBuf->iWidth - 2) * (pImage->iMAGN_MX);
+ }
+ else
+ {
+ iNewW = pBuf->iWidth + pImage->iMAGN_ML - 1;
+ if (pBuf->iWidth > 2)
+ iNewW = iNewW + pImage->iMAGN_MR - 1;
+ if (pBuf->iWidth > 3)
+ iNewW = iNewW + (pBuf->iWidth - 3) * (pImage->iMAGN_MX - 1);
+ }
+ }
+
+ if (pImage->iMAGN_MethodY) /* determine new height */
+ {
+ if (pImage->iMAGN_MethodY == 1)
+ {
+ iNewH = pImage->iMAGN_MT;
+ if (pBuf->iHeight > 1)
+ iNewH = iNewH + pImage->iMAGN_ML;
+ if (pBuf->iHeight > 2)
+ iNewH = iNewH + (pBuf->iHeight - 2) * (pImage->iMAGN_MY);
+ }
+ else
+ {
+ iNewH = pBuf->iHeight + pImage->iMAGN_MT - 1;
+ if (pBuf->iHeight > 2)
+ iNewH = iNewH + pImage->iMAGN_MB - 1;
+ if (pBuf->iHeight > 3)
+ iNewH = iNewH + (pBuf->iHeight - 3) * (pImage->iMAGN_MY - 1);
+ }
+ }
+ /* get new buffer */
+ iNewrowsize = iNewW * pBuf->iSamplesize;
+ iNewsize = iNewH * iNewrowsize;
+
+ MNG_ALLOC (pData, pNewdata, iNewsize);
+
+ switch (pBuf->iColortype) /* determine magnification routines */
+ {
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+ case 0 : ;
+ case 8 : {
+ if (pBuf->iBitdepth <= 8)
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_g8_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_g8_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_g8_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_g8_x2; break; }
+ case 5 : { fMagnifyX = mng_magnify_g8_x3; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_g8_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_g8_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_g8_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_g8_y2; break; }
+ case 5 : { fMagnifyY = mng_magnify_g8_y3; break; }
+ }
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_g16_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_g16_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_g16_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_g16_x2; break; }
+ case 5 : { fMagnifyX = mng_magnify_g16_x3; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_g16_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_g16_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_g16_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_g16_y2; break; }
+ case 5 : { fMagnifyY = mng_magnify_g16_y3; break; }
+ }
+ }
+#endif
+
+ break;
+ }
+
+ case 2 : ;
+ case 10 : {
+ if (pBuf->iBitdepth <= 8)
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_rgb8_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_rgb8_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_rgb8_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_rgb8_x2; break; }
+ case 5 : { fMagnifyX = mng_magnify_rgb8_x3; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_rgb8_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_rgb8_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_rgb8_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_rgb8_y2; break; }
+ case 5 : { fMagnifyY = mng_magnify_rgb8_y3; break; }
+ }
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_rgb16_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_rgb16_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_rgb16_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_rgb16_x2; break; }
+ case 5 : { fMagnifyX = mng_magnify_rgb16_x3; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_rgb16_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_rgb16_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_rgb16_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_rgb16_y2; break; }
+ case 5 : { fMagnifyY = mng_magnify_rgb16_y3; break; }
+ }
+ }
+#endif
+
+ break;
+ }
+
+ case 4 : ;
+ case 12 : {
+ if (pBuf->iBitdepth <= 8)
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_ga8_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_ga8_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_ga8_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_ga8_x4; break; }
+ case 5 : { fMagnifyX = mng_magnify_ga8_x5; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_ga8_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_ga8_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_ga8_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_ga8_y4; break; }
+ case 5 : { fMagnifyY = mng_magnify_ga8_y5; break; }
+ }
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+ else
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_ga16_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_ga16_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_ga16_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_ga16_x4; break; }
+ case 5 : { fMagnifyX = mng_magnify_ga16_x5; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_ga16_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_ga16_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_ga16_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_ga16_y4; break; }
+ case 5 : { fMagnifyY = mng_magnify_ga16_y5; break; }
+ }
+ }
+#endif
+
+ break;
+ }
+#endif
+
+ case 6 : ;
+ case 14 : {
+ if (pBuf->iBitdepth <= 8)
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_rgba8_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_rgba8_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_rgba8_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_rgba8_x4; break; }
+ case 5 : { fMagnifyX = mng_magnify_rgba8_x5; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_rgba8_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_rgba8_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_rgba8_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_rgba8_y4; break; }
+ case 5 : { fMagnifyY = mng_magnify_rgba8_y5; break; }
+ }
+ }
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+ else
+ {
+ switch (pImage->iMAGN_MethodX)
+ {
+ case 1 : { fMagnifyX = mng_magnify_rgba16_x1; break; }
+ case 2 : { fMagnifyX = mng_magnify_rgba16_x2; break; }
+ case 3 : { fMagnifyX = mng_magnify_rgba16_x3; break; }
+ case 4 : { fMagnifyX = mng_magnify_rgba16_x4; break; }
+ case 5 : { fMagnifyX = mng_magnify_rgba16_x5; break; }
+ }
+
+ switch (pImage->iMAGN_MethodY)
+ {
+ case 1 : { fMagnifyY = mng_magnify_rgba16_y1; break; }
+ case 2 : { fMagnifyY = mng_magnify_rgba16_y2; break; }
+ case 3 : { fMagnifyY = mng_magnify_rgba16_y3; break; }
+ case 4 : { fMagnifyY = mng_magnify_rgba16_y4; break; }
+ case 5 : { fMagnifyY = mng_magnify_rgba16_y5; break; }
+ }
+ }
+#endif
+#endif
+ break;
+ }
+ }
+
+ pSrcline1 = pBuf->pImgdata; /* initialize row-loop variables */
+ pDstline = pNewdata;
+ /* allocate temporary row */
+ MNG_ALLOC (pData, pTempline, iNewrowsize);
+
+ for (iY = 0; iY < pBuf->iHeight; iY++)
+ {
+ pSrcline2 = pSrcline1 + pBuf->iRowsize;
+
+ if (fMagnifyX) /* magnifying in X-direction ? */
+ {
+ iRetcode = fMagnifyX (pData, pImage->iMAGN_MX,
+ pImage->iMAGN_ML, pImage->iMAGN_MR,
+ pBuf->iWidth, pSrcline1, pDstline);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pTempline, iNewrowsize);
+ MNG_FREEX (pData, pNewdata, iNewsize);
+ return iRetcode;
+ }
+ }
+ else
+ {
+ MNG_COPY (pDstline, pSrcline1, iNewrowsize);
+ }
+
+ pDstline += iNewrowsize;
+ /* magnifying in Y-direction ? */
+ if ((fMagnifyY) &&
+ ((iY < pBuf->iHeight - 1) || (pBuf->iHeight == 1) || (pImage->iMAGN_MethodY == 1)))
+ {
+ if (iY == 0) /* first interval ? */
+ {
+ if (pBuf->iHeight == 1) /* single row ? */
+ pSrcline2 = MNG_NULL;
+
+ iM = (mng_int32)pImage->iMAGN_MT;
+ }
+ else /* last interval ? */
+ if (((pImage->iMAGN_MethodY == 1) && (iY == (pBuf->iHeight - 1))) ||
+ ((pImage->iMAGN_MethodY != 1) && (iY == (pBuf->iHeight - 2))) )
+ iM = (mng_int32)pImage->iMAGN_MB;
+ else /* middle interval */
+ iM = (mng_int32)pImage->iMAGN_MY;
+
+ for (iS = 1; iS < iM; iS++)
+ {
+ iRetcode = fMagnifyY (pData, iS, iM, pBuf->iWidth,
+ pSrcline1, pSrcline2, pTempline);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pTempline, iNewrowsize);
+ MNG_FREEX (pData, pNewdata, iNewsize);
+ return iRetcode;
+ }
+
+ if (fMagnifyX) /* magnifying in X-direction ? */
+ {
+ iRetcode = fMagnifyX (pData, pImage->iMAGN_MX,
+ pImage->iMAGN_ML, pImage->iMAGN_MR,
+ pBuf->iWidth, pTempline, pDstline);
+
+ if (iRetcode) /* on error bail out */
+ {
+ MNG_FREEX (pData, pTempline, iNewrowsize);
+ MNG_FREEX (pData, pNewdata, iNewsize);
+ return iRetcode;
+ }
+ }
+ else
+ {
+ MNG_COPY (pDstline, pTempline, iNewrowsize);
+ }
+
+ pDstline += iNewrowsize;
+ }
+ }
+
+ pSrcline1 += pBuf->iRowsize;
+ }
+ /* drop temporary row */
+ MNG_FREEX (pData, pTempline, iNewrowsize);
+ /* drop old pixel-data */
+ MNG_FREEX (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+
+ pBuf->pImgdata = pNewdata; /* save new buffer dimensions */
+ pBuf->iRowsize = iNewrowsize;
+ pBuf->iImgdatasize = iNewsize;
+ pBuf->iWidth = iNewW;
+ pBuf->iHeight = iNewH;
+
+ if (pImage->iId) /* real object ? */
+ {
+ pImage->iMAGN_MethodX = 0; /* it's done; don't do it again !!! */
+ pImage->iMAGN_MethodY = 0;
+ pImage->iMAGN_MX = 0;
+ pImage->iMAGN_MY = 0;
+ pImage->iMAGN_ML = 0;
+ pImage->iMAGN_MR = 0;
+ pImage->iMAGN_MT = 0;
+ pImage->iMAGN_MB = 0;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_IMGOBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_colorcorrect_object (mng_datap pData,
+ mng_imagep pImage)
+{
+ mng_imagedatap pBuf = pImage->pImgbuf;
+ mng_retcode iRetcode;
+ mng_uint32 iY;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COLORCORRECT_OBJECT, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+ if ((pBuf->iBitdepth < 8) || /* we need 8- or 16-bit RGBA !!! */
+ ((pBuf->iColortype != MNG_COLORTYPE_RGBA ) &&
+ (pBuf->iColortype != MNG_COLORTYPE_JPEGCOLORA) ))
+#else
+ if (pBuf->iBitdepth < 8) /* we need 8- or 16-bit RGBA !!! */
+#endif
+ MNG_ERROR (pData, MNG_OBJNOTABSTRACT);
+
+ if (!pBuf->bCorrected) /* only if not already done ! */
+ { /* so the row routines now to find it */
+ pData->pRetrieveobj = (mng_objectp)pImage;
+ pData->pStoreobj = (mng_objectp)pImage;
+ pData->pStorebuf = (mng_objectp)pImage->pImgbuf;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth > 8)
+ {
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba16;
+ pData->fStorerow = (mng_fptr)mng_store_rgba16;
+ }
+ else
+#endif
+ {
+ pData->fRetrieverow = (mng_fptr)mng_retrieve_rgba8;
+ pData->fStorerow = (mng_fptr)mng_store_rgba8;
+ }
+
+ pData->bIsOpaque = MNG_FALSE;
+
+ pData->iPass = -1; /* these are the object's dimensions now */
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pBuf->iWidth;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->iPixelofs = 0;
+ pData->bIsRGBA16 = MNG_FALSE;
+ /* adjust for 16-bit object ? */
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth > 8)
+ {
+ pData->bIsRGBA16 = MNG_TRUE;
+ pData->iRowsize = pData->iRowsamples << 3;
+ }
+#endif
+
+ pData->fCorrectrow = MNG_NULL; /* default no color-correction */
+
+#ifdef MNG_NO_CMS
+ iRetcode = MNG_NOERROR;
+#else
+#if defined(MNG_FULL_CMS) /* determine color-management routine */
+ iRetcode = mng_init_full_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_GAMMA_ONLY)
+ iRetcode = mng_init_gamma_only (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#elif defined(MNG_APP_CMS)
+ iRetcode = mng_init_app_cms (pData, MNG_FALSE, MNG_FALSE, MNG_TRUE);
+#endif
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif /* MNG_NO_CMS */
+
+ if (pData->fCorrectrow) /* really correct something ? */
+ { /* get a temporary row-buffer */
+ MNG_ALLOC (pData, pData->pRGBArow, pData->iRowsize);
+
+ pData->pWorkrow = pData->pRGBArow;
+ iY = 0; /* start from the top */
+
+ while ((!iRetcode) && (iY < pBuf->iHeight))
+ { /* get a row */
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+
+ if (!iRetcode) /* color correct it */
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* store it back ! */
+ iRetcode = ((mng_storerow)pData->fStorerow) (pData);
+
+ if (!iRetcode) /* adjust variables for next row */
+ iRetcode = mng_next_row (pData);
+
+ iY++; /* and next line */
+ }
+ /* drop the temporary row-buffer */
+ MNG_FREEX (pData, pData->pRGBArow, pData->iRowsize);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#if defined(MNG_FULL_CMS) /* cleanup cms stuff */
+ iRetcode = mng_clear_cms (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+#endif
+ }
+
+ pBuf->bCorrected = MNG_TRUE; /* let's not go through that again ! */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COLORCORRECT_OBJECT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Animation-object routines * */
+/* * * */
+/* * these handle the animation objects used to re-run parts of a MNG. * */
+/* * eg. during LOOP or TERM processing * */
+/* * * */
+/* ************************************************************************** */
+
+void mng_add_ani_object (mng_datap pData,
+ mng_object_headerp pObject)
+{
+ mng_object_headerp pLast = (mng_object_headerp)pData->pLastaniobj;
+
+ if (pLast) /* link it as last in the chain */
+ {
+ pObject->pPrev = pLast;
+ pLast->pNext = pObject;
+ }
+ else
+ {
+ pObject->pPrev = MNG_NULL; /* be on the safe side */
+ pData->pFirstaniobj = pObject;
+ }
+
+ pObject->pNext = MNG_NULL; /* be on the safe side */
+ pData->pLastaniobj = pObject;
+ /* keep track for jumping */
+ pObject->iFramenr = pData->iFrameseq;
+ pObject->iLayernr = pData->iLayerseq;
+ pObject->iPlaytime = pData->iFrametime;
+ /* save restart object ? */
+ if ((pData->bDisplaying) && (!pData->bRunning) && (!pData->pCurraniobj))
+ pData->pCurraniobj = pObject;
+
+ return;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+mng_retcode mng_create_ani_image (mng_datap pData)
+{
+ mng_ani_imagep pImage;
+ mng_imagep pCurrent;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IMAGE, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ pCurrent = (mng_imagep)pData->pObjzero;
+ else /* get the current object */
+#endif
+ pCurrent = (mng_imagep)pData->pCurrentobj;
+
+ if (!pCurrent) /* otherwise object 0 */
+ pCurrent = (mng_imagep)pData->pObjzero;
+ /* now just clone the object !!! */
+ iRetcode = mng_clone_imageobject (pData, 0, MNG_FALSE, pCurrent->bVisible,
+ MNG_FALSE, MNG_FALSE, 0, 0, 0, pCurrent,
+ &pImage);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ pImage->sHeader.fCleanup = mng_free_ani_image;
+ pImage->sHeader.fProcess = mng_process_ani_image;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pImage);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IMAGE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* okido */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_image (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_imagep pImage = (mng_ani_imagep)pObject;
+ mng_imagedatap pImgbuf = pImage->pImgbuf;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IMAGE, MNG_LC_START);
+#endif
+ /* unlink the image-data buffer */
+ iRetcode = mng_free_imagedataobject (pData, pImgbuf);
+ /* drop its own buffer */
+ MNG_FREEX (pData, pImage, sizeof (mng_ani_image));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IMAGE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_image (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode = MNG_NOERROR;
+ mng_ani_imagep pImage = (mng_imagep)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IMAGE, MNG_LC_START);
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+ if (pData->bHasDHDR) /* processing delta-image ? */
+ {
+ mng_imagep pDelta = (mng_imagep)pData->pDeltaImage;
+
+ if (!pData->iBreakpoint) /* only execute if not broken before */
+ { /* make sure to process pixels as well */
+ pData->bDeltaimmediate = MNG_FALSE;
+ /* execute the delta process */
+ iRetcode = mng_execute_delta_image (pData, pDelta, (mng_imagep)pObject);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ /* now go and shoot it off (if required) */
+ if ((pDelta->bVisible) && (pDelta->bViewable))
+ iRetcode = mng_display_image (pData, pDelta, MNG_FALSE);
+
+ if (!pData->bTimerset)
+ pData->bHasDHDR = MNG_FALSE; /* this image signifies IEND !! */
+
+ }
+ else
+#endif
+ if (pData->pCurrentobj) /* active object ? */
+ {
+ mng_imagep pCurrent = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf = pCurrent->pImgbuf;
+
+ if (!pData->iBreakpoint) /* don't copy it again ! */
+ {
+ if (pBuf->iImgdatasize) /* buffer present in active object ? */
+ /* then drop it */
+ MNG_FREE (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBuf->iProfilesize) /* iCCP profile present ? */
+ /* then drop it */
+ MNG_FREE (pData, pBuf->pProfile, pBuf->iProfilesize);
+#endif
+ /* now blatently copy the animation buffer */
+ MNG_COPY (pBuf, pImage->pImgbuf, sizeof (mng_imagedata));
+ /* copy viewability */
+ pCurrent->bViewable = pImage->bViewable;
+
+ if (pBuf->iImgdatasize) /* sample buffer present ? */
+ { /* then make a copy */
+ MNG_ALLOC (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+ MNG_COPY (pBuf->pImgdata, pImage->pImgbuf->pImgdata, pBuf->iImgdatasize);
+ }
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBuf->iProfilesize) /* iCCP profile present ? */
+ { /* then make a copy */
+ MNG_ALLOC (pData, pBuf->pProfile, pBuf->iProfilesize);
+ MNG_COPY (pBuf->pProfile, pImage->pImgbuf->pProfile, pBuf->iProfilesize);
+ }
+#endif
+ }
+ /* now go and shoot it off (if required) */
+ if ((pCurrent->bVisible) && (pCurrent->bViewable))
+ iRetcode = mng_display_image (pData, pCurrent, MNG_FALSE);
+ }
+ else
+ {
+ mng_imagep pObjzero = (mng_imagep)pData->pObjzero;
+ mng_imagedatap pBuf = pObjzero->pImgbuf;
+
+ if (!pData->iBreakpoint) /* don't copy it again ! */
+ {
+ if (pBuf->iImgdatasize) /* buffer present in active object ? */
+ /* then drop it */
+ MNG_FREE (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBuf->iProfilesize) /* iCCP profile present ? */
+ /* then drop it */
+ MNG_FREE (pData, pBuf->pProfile, pBuf->iProfilesize);
+#endif
+ /* now blatently copy the animation buffer */
+ MNG_COPY (pBuf, pImage->pImgbuf, sizeof (mng_imagedata));
+ /* copy viewability */
+ pObjzero->bViewable = pImage->bViewable;
+
+ if (pBuf->iImgdatasize) /* sample buffer present ? */
+ { /* then make a copy */
+ MNG_ALLOC (pData, pBuf->pImgdata, pBuf->iImgdatasize);
+ MNG_COPY (pBuf->pImgdata, pImage->pImgbuf->pImgdata, pBuf->iImgdatasize);
+ }
+
+#ifndef MNG_SKIPCHUNK_iCCP
+ if (pBuf->iProfilesize) /* iCCP profile present ? */
+ { /* then make a copy */
+ MNG_ALLOC (pData, pBuf->pProfile, pBuf->iProfilesize);
+ MNG_COPY (pBuf->pProfile, pImage->pImgbuf->pProfile, pBuf->iProfilesize);
+ }
+#endif
+ }
+ /* now go and show it */
+ iRetcode = mng_display_image (pData, pObjzero, MNG_FALSE);
+ }
+
+ if (!iRetcode) /* all's well ? */
+ {
+ if (pData->bTimerset) /* timer break ? */
+ pData->iBreakpoint = 99; /* fictive number; no more processing needed! */
+ else
+ pData->iBreakpoint = 0; /* else clear it */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IMAGE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_plte (mng_datap pData,
+ mng_uint32 iEntrycount,
+ mng_palette8ep paEntries)
+#else
+mng_retcode mng_create_ani_plte (mng_datap pData)
+#endif
+{
+ mng_ani_pltep pPLTE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PLTE, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_plte),
+ mng_free_obj_general,
+ mng_process_ani_plte,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pPLTE = (mng_ani_pltep)pTemp;
+#else
+ MNG_ALLOC (pData, pPLTE, sizeof (mng_ani_plte));
+
+ pPLTE->sHeader.fCleanup = mng_free_ani_plte;
+ pPLTE->sHeader.fProcess = mng_process_ani_plte;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pPLTE);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pPLTE->iEntrycount = iEntrycount;
+ MNG_COPY (pPLTE->aEntries, paEntries, sizeof (pPLTE->aEntries));
+#else
+ pPLTE->iEntrycount = pData->iGlobalPLTEcount;
+ MNG_COPY (pPLTE->aEntries, pData->aGlobalPLTEentries, sizeof (pPLTE->aEntries));
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_plte (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PLTE, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_plte));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_plte (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_pltep pPLTE = (mng_ani_pltep)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PLTE, MNG_LC_START);
+#endif
+
+ pData->bHasglobalPLTE = MNG_TRUE;
+ pData->iGlobalPLTEcount = pPLTE->iEntrycount;
+
+ MNG_COPY (pData->aGlobalPLTEentries, pPLTE->aEntries, sizeof (pPLTE->aEntries));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PLTE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_trns (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata)
+#else
+mng_retcode mng_create_ani_trns (mng_datap pData)
+#endif
+{
+ mng_ani_trnsp pTRNS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_TRNS, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_trns),
+ mng_free_obj_general,
+ mng_process_ani_trns,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pTRNS = (mng_ani_trnsp)pTemp;
+#else
+ MNG_ALLOC (pData, pTRNS, sizeof (mng_ani_trns));
+
+ pTRNS->sHeader.fCleanup = mng_free_ani_trns;
+ pTRNS->sHeader.fProcess = mng_process_ani_trns;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pTRNS);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pTRNS->iRawlen = iRawlen;
+ MNG_COPY (pTRNS->aRawdata, pRawdata, sizeof (pTRNS->aRawdata));
+#else
+ pTRNS->iRawlen = pData->iGlobalTRNSrawlen;
+ MNG_COPY (pTRNS->aRawdata, pData->aGlobalTRNSrawdata, sizeof (pTRNS->aRawdata));
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_trns (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_TRNS, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_trns));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_trns (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_trnsp pTRNS = (mng_ani_trnsp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_TRNS, MNG_LC_START);
+#endif
+
+ pData->bHasglobalTRNS = MNG_TRUE;
+ pData->iGlobalTRNSrawlen = pTRNS->iRawlen;
+
+ MNG_COPY (pData->aGlobalTRNSrawdata, pTRNS->aRawdata, sizeof (pTRNS->aRawdata));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_TRNS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_gAMA
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_gama (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iGamma)
+#else
+mng_retcode mng_create_ani_gama (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_gamap pGAMA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_GAMA, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_gama),
+ mng_free_obj_general,
+ mng_process_ani_gama,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pGAMA = (mng_ani_gamap)pTemp;
+#else
+ MNG_ALLOC (pData, pGAMA, sizeof (mng_ani_gama));
+
+ pGAMA->sHeader.fCleanup = mng_free_ani_gama;
+ pGAMA->sHeader.fProcess = mng_process_ani_gama;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pGAMA);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pGAMA->bEmpty = bEmpty;
+ pGAMA->iGamma = iGamma;
+#else
+ pGAMA->bEmpty = ((mng_gamap)pChunk)->bEmpty;
+ pGAMA->iGamma = ((mng_gamap)pChunk)->iGamma;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_gama (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_GAMA, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_gama));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_gama (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_gamap pGAMA = (mng_ani_gamap)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_GAMA, MNG_LC_START);
+#endif
+
+ if (pGAMA->bEmpty) /* empty chunk ? */
+ { /* clear global gAMA */
+ pData->bHasglobalGAMA = MNG_FALSE;
+ pData->iGlobalGamma = 0;
+ }
+ else
+ { /* set global gAMA */
+ pData->bHasglobalGAMA = MNG_TRUE;
+ pData->iGlobalGamma = pGAMA->iGamma;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_GAMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_chrm (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iWhitepointx,
+ mng_uint32 iWhitepointy,
+ mng_uint32 iRedx,
+ mng_uint32 iRedy,
+ mng_uint32 iGreenx,
+ mng_uint32 iGreeny,
+ mng_uint32 iBluex,
+ mng_uint32 iBluey)
+#else
+mng_retcode mng_create_ani_chrm (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ptr pTemp;
+ mng_ani_chrmp pCHRM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CHRM, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_chrm),
+ mng_free_obj_general,
+ mng_process_ani_chrm,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pCHRM = (mng_ani_chrmp)pTemp;
+#else
+ MNG_ALLOC (pData, pCHRM, sizeof (mng_ani_chrm));
+
+ pCHRM->sHeader.fCleanup = mng_free_ani_chrm;
+ pCHRM->sHeader.fProcess = mng_process_ani_chrm;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pCHRM);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pCHRM->bEmpty = bEmpty;
+ pCHRM->iWhitepointx = iWhitepointx;
+ pCHRM->iWhitepointy = iWhitepointy;
+ pCHRM->iRedx = iRedx;
+ pCHRM->iRedy = iRedy;
+ pCHRM->iGreenx = iGreenx;
+ pCHRM->iGreeny = iGreeny;
+ pCHRM->iBluex = iBluex;
+ pCHRM->iBluey = iBluey;
+#else
+ pCHRM->bEmpty = ((mng_chrmp)pChunk)->bEmpty;
+ pCHRM->iWhitepointx = ((mng_chrmp)pChunk)->iWhitepointx;
+ pCHRM->iWhitepointy = ((mng_chrmp)pChunk)->iWhitepointy;
+ pCHRM->iRedx = ((mng_chrmp)pChunk)->iRedx;
+ pCHRM->iRedy = ((mng_chrmp)pChunk)->iRedy;
+ pCHRM->iGreenx = ((mng_chrmp)pChunk)->iGreenx;
+ pCHRM->iGreeny = ((mng_chrmp)pChunk)->iGreeny;
+ pCHRM->iBluex = ((mng_chrmp)pChunk)->iBluex;
+ pCHRM->iBluey = ((mng_chrmp)pChunk)->iBluey;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_chrm (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CHRM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_chrm));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_chrm (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_chrmp pCHRM = (mng_ani_chrmp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CHRM, MNG_LC_START);
+#endif
+
+ if (pCHRM->bEmpty) /* empty chunk ? */
+ { /* clear global cHRM */
+ pData->bHasglobalCHRM = MNG_FALSE;
+ pData->iGlobalWhitepointx = 0;
+ pData->iGlobalWhitepointy = 0;
+ pData->iGlobalPrimaryredx = 0;
+ pData->iGlobalPrimaryredy = 0;
+ pData->iGlobalPrimarygreenx = 0;
+ pData->iGlobalPrimarygreeny = 0;
+ pData->iGlobalPrimarybluex = 0;
+ pData->iGlobalPrimarybluey = 0;
+ }
+ else
+ { /* set global cHRM */
+ pData->bHasglobalCHRM = MNG_TRUE;
+ pData->iGlobalWhitepointx = pCHRM->iWhitepointx;
+ pData->iGlobalWhitepointy = pCHRM->iWhitepointy;
+ pData->iGlobalPrimaryredx = pCHRM->iRedx;
+ pData->iGlobalPrimaryredy = pCHRM->iRedy;
+ pData->iGlobalPrimarygreenx = pCHRM->iGreenx;
+ pData->iGlobalPrimarygreeny = pCHRM->iGreeny;
+ pData->iGlobalPrimarybluex = pCHRM->iBluex;
+ pData->iGlobalPrimarybluey = pCHRM->iBluey;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CHRM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_sRGB
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_srgb (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint8 iRenderingintent)
+#else
+mng_retcode mng_create_ani_srgb (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_srgbp pSRGB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SRGB, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_srgb),
+ mng_free_obj_general,
+ mng_process_ani_srgb,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pSRGB = (mng_ani_srgbp)pTemp;
+#else
+ MNG_ALLOC (pData, pSRGB, sizeof (mng_ani_srgb));
+
+ pSRGB->sHeader.fCleanup = mng_free_ani_srgb;
+ pSRGB->sHeader.fProcess = mng_process_ani_srgb;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSRGB);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pSRGB->bEmpty = bEmpty;
+ pSRGB->iRenderingintent = iRenderingintent;
+#else
+ pSRGB->bEmpty = ((mng_srgbp)pChunk)->bEmpty;
+ pSRGB->iRenderingintent = ((mng_srgbp)pChunk)->iRenderingintent;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_srgb (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SRGB, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_srgb));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_srgb (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_srgbp pSRGB = (mng_ani_srgbp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SRGB, MNG_LC_START);
+#endif
+
+ if (pSRGB->bEmpty) /* empty chunk ? */
+ { /* clear global sRGB */
+ pData->bHasglobalSRGB = MNG_FALSE;
+ pData->iGlobalRendintent = 0;
+ }
+ else
+ { /* set global sRGB */
+ pData->bHasglobalSRGB = MNG_TRUE;
+ pData->iGlobalRendintent = pSRGB->iRenderingintent;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_iccp (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile)
+#else
+mng_retcode mng_create_ani_iccp (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ptr pTemp;
+ mng_ani_iccpp pICCP;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_ICCP, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_iccp),
+ mng_free_ani_iccp,
+ mng_process_ani_iccp,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pICCP = (mng_ani_iccpp)pTemp;
+#else
+ MNG_ALLOC (pData, pICCP, sizeof (mng_ani_iccp));
+
+ pICCP->sHeader.fCleanup = mng_free_ani_iccp;
+ pICCP->sHeader.fProcess = mng_process_ani_iccp;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pICCP);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pICCP->bEmpty = bEmpty;
+ pICCP->iProfilesize = iProfilesize;
+
+ if (iProfilesize)
+ {
+ MNG_ALLOC (pData, pICCP->pProfile, iProfilesize);
+ MNG_COPY (pICCP->pProfile, pProfile, iProfilesize);
+ }
+#else
+ pICCP->bEmpty = ((mng_iccpp)pChunk)->bEmpty;
+ pICCP->iProfilesize = ((mng_iccpp)pChunk)->iProfilesize;
+
+ if (pICCP->iProfilesize)
+ {
+ MNG_ALLOC (pData, pICCP->pProfile, pICCP->iProfilesize);
+ MNG_COPY (pICCP->pProfile, ((mng_iccpp)pChunk)->pProfile, pICCP->iProfilesize);
+ }
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_iccp (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_iccpp pICCP = (mng_ani_iccpp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_ICCP, MNG_LC_START);
+#endif
+
+ if (pICCP->iProfilesize)
+ MNG_FREEX (pData, pICCP->pProfile, pICCP->iProfilesize);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_iccp));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_ICCP, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_iccp (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_iccpp pICCP = (mng_ani_iccpp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_ICCP, MNG_LC_START);
+#endif
+
+ if (pICCP->bEmpty) /* empty chunk ? */
+ { /* clear global iCCP */
+ pData->bHasglobalICCP = MNG_FALSE;
+
+ if (pData->iGlobalProfilesize)
+ MNG_FREEX (pData, pData->pGlobalProfile, pData->iGlobalProfilesize);
+
+ pData->iGlobalProfilesize = 0;
+ pData->pGlobalProfile = MNG_NULL;
+ }
+ else
+ { /* set global iCCP */
+ pData->bHasglobalICCP = MNG_TRUE;
+ pData->iGlobalProfilesize = pICCP->iProfilesize;
+
+ if (pICCP->iProfilesize)
+ {
+ MNG_ALLOC (pData, pData->pGlobalProfile, pICCP->iProfilesize);
+ MNG_COPY (pData->pGlobalProfile, pICCP->pProfile, pICCP->iProfilesize);
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_ICCP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_bkgd (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue)
+#else
+mng_retcode mng_create_ani_bkgd (mng_datap pData)
+#endif
+{
+ mng_ptr pTemp;
+ mng_ani_bkgdp pBKGD;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BKGD, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_bkgd),
+ mng_free_obj_general,
+ mng_process_ani_bkgd,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pBKGD = (mng_ani_bkgdp)pTemp;
+#else
+ MNG_ALLOC (pData, pBKGD, sizeof (mng_ani_bkgd));
+
+ pBKGD->sHeader.fCleanup = mng_free_ani_bkgd;
+ pBKGD->sHeader.fProcess = mng_process_ani_bkgd;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pBKGD);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pBKGD->iRed = iRed;
+ pBKGD->iGreen = iGreen;
+ pBKGD->iBlue = iBlue;
+#else
+ pBKGD->iRed = pData->iGlobalBKGDred;
+ pBKGD->iGreen = pData->iGlobalBKGDgreen;
+ pBKGD->iBlue = pData->iGlobalBKGDblue;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_bkgd (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BKGD, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_bkgd));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_bkgd (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_bkgdp pBKGD = (mng_ani_bkgdp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BKGD, MNG_LC_START);
+#endif
+
+ pData->bHasglobalBKGD = MNG_TRUE;
+ pData->iGlobalBKGDred = pBKGD->iRed;
+ pData->iGlobalBKGDgreen = pBKGD->iGreen;
+ pData->iGlobalBKGDblue = pBKGD->iBlue;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_LOOP
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_loop (mng_datap pData,
+ mng_uint8 iLevel,
+ mng_uint32 iRepeatcount,
+ mng_uint8 iTermcond,
+ mng_uint32 iItermin,
+ mng_uint32 iItermax,
+ mng_uint32 iCount,
+ mng_uint32p pSignals)
+#else
+mng_retcode mng_create_ani_loop (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_loopp pLOOP;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_LOOP, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_loop),
+ mng_free_ani_loop,
+ mng_process_ani_loop,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pLOOP = (mng_ani_loopp)pTemp;
+#else
+ MNG_ALLOC (pData, pLOOP, sizeof (mng_ani_loop));
+
+ pLOOP->sHeader.fCleanup = mng_free_ani_loop;
+ pLOOP->sHeader.fProcess = mng_process_ani_loop;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pLOOP);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pLOOP->iLevel = iLevel;
+ pLOOP->iRepeatcount = iRepeatcount;
+ pLOOP->iTermcond = iTermcond;
+ pLOOP->iItermin = iItermin;
+ pLOOP->iItermax = iItermax;
+ pLOOP->iCount = iCount;
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (iCount)
+ {
+ MNG_ALLOC (pData, pLOOP->pSignals, (iCount << 1));
+ MNG_COPY (pLOOP->pSignals, pSignals, (iCount << 1));
+ }
+#endif
+#else /* MNG_OPTIMIZE_CHUNKREADER */
+ pLOOP->iLevel = ((mng_loopp)pChunk)->iLevel;
+ pLOOP->iRepeatcount = ((mng_loopp)pChunk)->iRepeat;
+ pLOOP->iTermcond = ((mng_loopp)pChunk)->iTermination;
+ pLOOP->iItermin = ((mng_loopp)pChunk)->iItermin;
+ pLOOP->iItermax = ((mng_loopp)pChunk)->iItermax;
+ pLOOP->iCount = ((mng_loopp)pChunk)->iCount;
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (pLOOP->iCount)
+ {
+ MNG_ALLOC (pData, pLOOP->pSignals, (pLOOP->iCount << 1));
+ MNG_COPY (pLOOP->pSignals, ((mng_loopp)pChunk)->pSignals, (pLOOP->iCount << 1));
+ }
+#endif
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+ /* running counter starts with repeat_count */
+ pLOOP->iRunningcount = pLOOP->iRepeatcount;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_loop (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ mng_ani_loopp pLOOP = (mng_ani_loopp)pObject;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_LOOP, MNG_LC_START);
+#endif
+
+#ifndef MNG_NO_LOOP_SIGNALS_SUPPORTED
+ if (pLOOP->iCount) /* drop signal buffer ? */
+ MNG_FREEX (pData, pLOOP->pSignals, (pLOOP->iCount << 1));
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_loop));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_LOOP, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_loop (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_loopp pLOOP = (mng_ani_loopp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_LOOP, MNG_LC_START);
+#endif
+ /* just reset the running counter */
+ pLOOP->iRunningcount = pLOOP->iRepeatcount;
+ /* iteration=0 means we're skipping ! */
+ if ((!pData->bSkipping) && (pLOOP->iRepeatcount == 0))
+ pData->bSkipping = MNG_TRUE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_LOOP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+mng_retcode mng_create_ani_endl (mng_datap pData,
+ mng_uint8 iLevel)
+{
+ mng_ani_endlp pENDL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_ENDL, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+ mng_retcode iRetcode;
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_endl),
+ mng_free_obj_general,
+ mng_process_ani_endl,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pENDL = (mng_ani_endlp)pTemp;
+#else
+ MNG_ALLOC (pData, pENDL, sizeof (mng_ani_endl));
+
+ pENDL->sHeader.fCleanup = mng_free_ani_endl;
+ pENDL->sHeader.fProcess = mng_process_ani_endl;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pENDL);
+
+ pENDL->iLevel = iLevel;
+
+ iRetcode = mng_process_ani_endl (pData, (mng_objectp)pENDL);
+ if (iRetcode)
+ return iRetcode;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_endl (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_ENDL, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_endl));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_endl (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_endlp pENDL = (mng_ani_endlp)pObject;
+ mng_ani_loopp pLOOP;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_ENDL, MNG_LC_START);
+#endif
+
+ if (((pData->bDisplaying) && ((pData->bRunning) || (pData->bSearching))) ||
+ (pData->bReading) )
+ {
+ pLOOP = pENDL->pLOOP; /* determine matching LOOP */
+
+ if (!pLOOP) /* haven't got it yet ? */
+ { /* go and look back in the list */
+ pLOOP = (mng_ani_loopp)pENDL->sHeader.pPrev;
+
+ while ((pLOOP) &&
+ ((pLOOP->sHeader.fCleanup != mng_free_ani_loop) ||
+ (pLOOP->iLevel != pENDL->iLevel) ))
+ pLOOP = pLOOP->sHeader.pPrev;
+ }
+ /* got it now ? */
+ if ((pLOOP) && (pLOOP->iLevel == pENDL->iLevel))
+ {
+ pENDL->pLOOP = pLOOP; /* save for next time ! */
+ /* decrease running counter ? */
+ if ((pLOOP->iRunningcount) && (pLOOP->iRunningcount < 0x7fffffffL))
+ pLOOP->iRunningcount--;
+
+ if ((!pData->bDisplaying) && (pData->bReading) &&
+ (pLOOP->iRunningcount >= 0x7fffffffL))
+ {
+ pData->iTotalframes = 0x7fffffffL;
+ pData->iTotallayers = 0x7fffffffL;
+ pData->iTotalplaytime = 0x7fffffffL;
+ }
+ else
+ {
+ /* TODO: we're cheating out on the termination_condition,
+ iteration_min, iteration_max and possible signals;
+ the code is just not ready for that can of worms.... */
+
+ if (!pLOOP->iRunningcount) /* reached zero ? */
+ { /* was this the outer LOOP ? */
+ if (pData->pFirstaniobj == (mng_objectp)pLOOP) /* TODO: THIS IS WRONG!! */
+ pData->bHasLOOP = MNG_FALSE;
+ }
+ else
+ {
+ if (pData->pCurraniobj) /* was we processing objects ? */
+ pData->pCurraniobj = pLOOP;/* then restart with LOOP */
+ else /* else restart behind LOOP !!! */
+ pData->pCurraniobj = pLOOP->sHeader.pNext;
+ }
+ }
+ /* does this match a 'skipping' LOOP? */
+ if ((pData->bSkipping) && (pLOOP->iRepeatcount == 0))
+ pData->bSkipping = MNG_FALSE;
+ }
+ else
+ MNG_ERROR (pData, MNG_NOMATCHINGLOOP);
+
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_ENDL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DEFI
+mng_retcode mng_create_ani_defi (mng_datap pData)
+{
+ mng_ani_defip pDEFI;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DEFI, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_defi),
+ mng_free_obj_general,
+ mng_process_ani_defi,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pDEFI = (mng_ani_defip)pTemp;
+#else
+ MNG_ALLOC (pData, pDEFI, sizeof (mng_ani_defi));
+
+ pDEFI->sHeader.fCleanup = mng_free_ani_defi;
+ pDEFI->sHeader.fProcess = mng_process_ani_defi;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pDEFI);
+
+ pDEFI->iId = pData->iDEFIobjectid;
+ pDEFI->bHasdonotshow = pData->bDEFIhasdonotshow;
+ pDEFI->iDonotshow = pData->iDEFIdonotshow;
+ pDEFI->bHasconcrete = pData->bDEFIhasconcrete;
+ pDEFI->iConcrete = pData->iDEFIconcrete;
+ pDEFI->bHasloca = pData->bDEFIhasloca;
+ pDEFI->iLocax = pData->iDEFIlocax;
+ pDEFI->iLocay = pData->iDEFIlocay;
+ pDEFI->bHasclip = pData->bDEFIhasclip;
+ pDEFI->iClipl = pData->iDEFIclipl;
+ pDEFI->iClipr = pData->iDEFIclipr;
+ pDEFI->iClipt = pData->iDEFIclipt;
+ pDEFI->iClipb = pData->iDEFIclipb;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_defi (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DEFI, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_defi));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_defi (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_defip pDEFI = (mng_ani_defip)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DEFI, MNG_LC_START);
+#endif
+
+ pData->iDEFIobjectid = pDEFI->iId;
+ pData->bDEFIhasdonotshow = pDEFI->bHasdonotshow;
+ pData->iDEFIdonotshow = pDEFI->iDonotshow;
+ pData->bDEFIhasconcrete = pDEFI->bHasconcrete;
+ pData->iDEFIconcrete = pDEFI->iConcrete;
+ pData->bDEFIhasloca = pDEFI->bHasloca;
+ pData->iDEFIlocax = pDEFI->iLocax;
+ pData->iDEFIlocay = pDEFI->iLocay;
+ pData->bDEFIhasclip = pDEFI->bHasclip;
+ pData->iDEFIclipl = pDEFI->iClipl;
+ pData->iDEFIclipr = pDEFI->iClipr;
+ pData->iDEFIclipt = pDEFI->iClipt;
+ pData->iDEFIclipb = pDEFI->iClipb;
+
+ iRetcode = mng_process_display_defi (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DEFI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BASI
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_basi (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_bool bHasalpha,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable)
+#else
+mng_retcode mng_create_ani_basi (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_basip pBASI;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BASI, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_basi),
+ mng_free_obj_general,
+ mng_process_ani_basi,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pBASI = (mng_ani_basip)pTemp;
+#else
+ MNG_ALLOC (pData, pBASI, sizeof (mng_ani_basi));
+
+ pBASI->sHeader.fCleanup = mng_free_ani_basi;
+ pBASI->sHeader.fProcess = mng_process_ani_basi;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pBASI);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pBASI->iRed = iRed;
+ pBASI->iGreen = iGreen;
+ pBASI->iBlue = iBlue;
+ pBASI->bHasalpha = bHasalpha;
+ pBASI->iAlpha = iAlpha;
+ pBASI->iViewable = iViewable;
+#else
+ pBASI->iRed = ((mng_basip)pChunk)->iRed;
+ pBASI->iGreen = ((mng_basip)pChunk)->iGreen;
+ pBASI->iBlue = ((mng_basip)pChunk)->iBlue;
+ pBASI->bHasalpha = ((mng_basip)pChunk)->bHasalpha;
+ pBASI->iAlpha = ((mng_basip)pChunk)->iAlpha;
+ pBASI->iViewable = ((mng_basip)pChunk)->iViewable;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_basi (pData, iRed, iGreen, iBlue,
+ bHasalpha, iAlpha, iViewable);
+#else
+ iRetcode = mng_process_display_basi (pData,
+ ((mng_basip)pChunk)->iRed,
+ ((mng_basip)pChunk)->iGreen,
+ ((mng_basip)pChunk)->iBlue,
+ ((mng_basip)pChunk)->bHasalpha,
+ ((mng_basip)pChunk)->iAlpha,
+ ((mng_basip)pChunk)->iViewable);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iBASIred = iRed;
+ pData->iBASIgreen = iGreen;
+ pData->iBASIblue = iBlue;
+ pData->bBASIhasalpha = bHasalpha;
+ pData->iBASIalpha = iAlpha;
+ pData->iBASIviewable = iViewable;
+#else
+ pData->iBASIred = ((mng_basip)pChunk)->iRed;
+ pData->iBASIgreen = ((mng_basip)pChunk)->iGreen;
+ pData->iBASIblue = ((mng_basip)pChunk)->iBlue;
+ pData->bBASIhasalpha = ((mng_basip)pChunk)->bHasalpha;
+ pData->iBASIalpha = ((mng_basip)pChunk)->iAlpha;
+ pData->iBASIviewable = ((mng_basip)pChunk)->iViewable;
+#endif
+
+ iRetcode = mng_process_display_basi (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BASI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_basi (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BASI, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_basi));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BASI, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_basi (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_basip pBASI = (mng_ani_basip)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BASI, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_basi (pData, pBASI->iRed, pBASI->iGreen, pBASI->iBlue,
+ pBASI->bHasalpha, pBASI->iAlpha, pBASI->iViewable);
+#else
+ pData->iBASIred = pBASI->iRed;
+ pData->iBASIgreen = pBASI->iGreen;
+ pData->iBASIblue = pBASI->iBlue;
+ pData->bBASIhasalpha = pBASI->bHasalpha;
+ pData->iBASIalpha = pBASI->iAlpha;
+ pData->iBASIviewable = pBASI->iViewable;
+
+ iRetcode = mng_process_display_basi (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BASI, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLON
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_clon (mng_datap pData,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_bool bHasdonotshow,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocatype,
+ mng_int32 iLocax,
+ mng_int32 iLocay)
+#else
+mng_retcode mng_create_ani_clon (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_clonp pCLON;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CLON, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_clon),
+ mng_free_obj_general,
+ mng_process_ani_clon,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pCLON = (mng_ani_clonp)pTemp;
+#else
+ MNG_ALLOC (pData, pCLON, sizeof (mng_ani_clon));
+
+ pCLON->sHeader.fCleanup = mng_free_ani_clon;
+ pCLON->sHeader.fProcess = mng_process_ani_clon;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pCLON);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pCLON->iSourceid = iSourceid;
+ pCLON->iCloneid = iCloneid;
+ pCLON->iClonetype = iClonetype;
+ pCLON->bHasdonotshow = bHasdonotshow;
+ pCLON->iDonotshow = iDonotshow;
+ pCLON->iConcrete = iConcrete;
+ pCLON->bHasloca = bHasloca;
+ pCLON->iLocatype = iLocatype;
+ pCLON->iLocax = iLocax;
+ pCLON->iLocay = iLocay;
+#else
+ pCLON->iSourceid = ((mng_clonp)pChunk)->iSourceid;
+ pCLON->iCloneid = ((mng_clonp)pChunk)->iCloneid;
+ pCLON->iClonetype = ((mng_clonp)pChunk)->iClonetype;
+ pCLON->bHasdonotshow = ((mng_clonp)pChunk)->bHasdonotshow;
+ pCLON->iDonotshow = ((mng_clonp)pChunk)->iDonotshow;
+ pCLON->iConcrete = ((mng_clonp)pChunk)->iConcrete;
+ pCLON->bHasloca = ((mng_clonp)pChunk)->bHasloca;
+ pCLON->iLocatype = ((mng_clonp)pChunk)->iLocationtype;
+ pCLON->iLocax = ((mng_clonp)pChunk)->iLocationx;
+ pCLON->iLocay = ((mng_clonp)pChunk)->iLocationy;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_clon (pData, iSourceid, iCloneid, iClonetype,
+ bHasdonotshow, iDonotshow, iConcrete,
+ bHasloca, iLocatype, iLocax, iLocay);
+#else
+ iRetcode = mng_process_display_clon (pData,
+ ((mng_clonp)pChunk)->iSourceid,
+ ((mng_clonp)pChunk)->iCloneid,
+ ((mng_clonp)pChunk)->iClonetype,
+ ((mng_clonp)pChunk)->bHasdonotshow,
+ ((mng_clonp)pChunk)->iDonotshow,
+ ((mng_clonp)pChunk)->iConcrete,
+ ((mng_clonp)pChunk)->bHasloca,
+ ((mng_clonp)pChunk)->iLocationtype,
+ ((mng_clonp)pChunk)->iLocationx,
+ ((mng_clonp)pChunk)->iLocationy);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iCLONsourceid = iSourceid;
+ pData->iCLONcloneid = iCloneid;
+ pData->iCLONclonetype = iClonetype;
+ pData->bCLONhasdonotshow = bHasdonotshow;
+ pData->iCLONdonotshow = iDonotshow;
+ pData->iCLONconcrete = iConcrete;
+ pData->bCLONhasloca = bHasloca;
+ pData->iCLONlocationtype = iLocatype;
+ pData->iCLONlocationx = iLocax;
+ pData->iCLONlocationy = iLocay;
+#else
+ pData->iCLONsourceid = ((mng_clonp)pChunk)->iSourceid;
+ pData->iCLONcloneid = ((mng_clonp)pChunk)->iCloneid;
+ pData->iCLONclonetype = ((mng_clonp)pChunk)->iClonetype;
+ pData->bCLONhasdonotshow = ((mng_clonp)pChunk)->bHasdonotshow;
+ pData->iCLONdonotshow = ((mng_clonp)pChunk)->iDonotshow;
+ pData->iCLONconcrete = ((mng_clonp)pChunk)->iConcrete;
+ pData->bCLONhasloca = ((mng_clonp)pChunk)->bHasloca;
+ pData->iCLONlocationtype = ((mng_clonp)pChunk)->iLocationtype;
+ pData->iCLONlocationx = ((mng_clonp)pChunk)->iLocationx;
+ pData->iCLONlocationy = ((mng_clonp)pChunk)->iLocationy;
+#endif
+
+ iRetcode = mng_process_display_clon (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CLON, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_clon (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CLON, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_clon));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CLON, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_clon (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_clonp pCLON = (mng_ani_clonp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CLON, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_clon (pData, pCLON->iSourceid, pCLON->iCloneid,
+ pCLON->iClonetype, pCLON->bHasdonotshow,
+ pCLON->iDonotshow, pCLON->iConcrete,
+ pCLON->bHasloca, pCLON->iLocatype,
+ pCLON->iLocax, pCLON->iLocay);
+#else
+ pData->iCLONcloneid = pCLON->iCloneid;
+ pData->iCLONsourceid = pCLON->iSourceid;
+ pData->iCLONclonetype = pCLON->iClonetype;
+ pData->bCLONhasdonotshow = pCLON->bHasdonotshow;
+ pData->iCLONdonotshow = pCLON->iDonotshow;
+ pData->iCLONconcrete = pCLON->iConcrete;
+ pData->bCLONhasloca = pCLON->bHasloca;
+ pData->iCLONlocationtype = pCLON->iLocatype;
+ pData->iCLONlocationx = pCLON->iLocax;
+ pData->iCLONlocationy = pCLON->iLocay;
+
+ iRetcode = mng_process_display_clon (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CLON, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_BACK
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_back (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint8 iMandatory,
+ mng_uint16 iImageid,
+ mng_uint8 iTile)
+#else
+mng_retcode mng_create_ani_back (mng_datap pData)
+#endif
+{
+ mng_ani_backp pBACK;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BACK, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_back),
+ mng_free_obj_general,
+ mng_process_ani_back,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pBACK = (mng_ani_backp)pTemp;
+#else
+ MNG_ALLOC (pData, pBACK, sizeof (mng_ani_back));
+
+ pBACK->sHeader.fCleanup = mng_free_ani_back;
+ pBACK->sHeader.fProcess = mng_process_ani_back;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pBACK);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pBACK->iRed = iRed;
+ pBACK->iGreen = iGreen;
+ pBACK->iBlue = iBlue;
+ pBACK->iMandatory = iMandatory;
+ pBACK->iImageid = iImageid;
+ pBACK->iTile = iTile;
+#else
+ pBACK->iRed = pData->iBACKred;
+ pBACK->iGreen = pData->iBACKgreen;
+ pBACK->iBlue = pData->iBACKblue;
+ pBACK->iMandatory = pData->iBACKmandatory;
+ pBACK->iImageid = pData->iBACKimageid;
+ pBACK->iTile = pData->iBACKtile;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_back (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BACK, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_back));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_back (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_backp pBACK = (mng_ani_backp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BACK, MNG_LC_START);
+#endif
+
+ pData->iBACKred = pBACK->iRed;
+ pData->iBACKgreen = pBACK->iGreen;
+ pData->iBACKblue = pBACK->iBlue;
+ pData->iBACKmandatory = pBACK->iMandatory;
+ pData->iBACKimageid = pBACK->iImageid;
+ pData->iBACKtile = pBACK->iTile;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_BACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_FRAM
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_fram (mng_datap pData,
+ mng_uint8 iFramemode,
+ mng_uint8 iChangedelay,
+ mng_uint32 iDelay,
+ mng_uint8 iChangetimeout,
+ mng_uint32 iTimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+#else
+mng_retcode mng_create_ani_fram (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_framp pFRAM;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_FRAM, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_fram),
+ mng_free_obj_general,
+ mng_process_ani_fram,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pFRAM = (mng_ani_framp)pTemp;
+#else
+ MNG_ALLOC (pData, pFRAM, sizeof (mng_ani_fram));
+
+ pFRAM->sHeader.fCleanup = mng_free_ani_fram;
+ pFRAM->sHeader.fProcess = mng_process_ani_fram;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pFRAM);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pFRAM->iFramemode = iFramemode;
+ pFRAM->iChangedelay = iChangedelay;
+ pFRAM->iDelay = iDelay;
+ pFRAM->iChangetimeout = iChangetimeout;
+ pFRAM->iTimeout = iTimeout;
+ pFRAM->iChangeclipping = iChangeclipping;
+ pFRAM->iCliptype = iCliptype;
+ pFRAM->iClipl = iClipl;
+ pFRAM->iClipr = iClipr;
+ pFRAM->iClipt = iClipt;
+ pFRAM->iClipb = iClipb;
+#else
+ pFRAM->iFramemode = ((mng_framp)pChunk)->iMode;
+ pFRAM->iChangedelay = ((mng_framp)pChunk)->iChangedelay;
+ pFRAM->iDelay = ((mng_framp)pChunk)->iDelay;
+ pFRAM->iChangetimeout = ((mng_framp)pChunk)->iChangetimeout;
+ pFRAM->iTimeout = ((mng_framp)pChunk)->iTimeout;
+ pFRAM->iChangeclipping = ((mng_framp)pChunk)->iChangeclipping;
+ pFRAM->iCliptype = ((mng_framp)pChunk)->iBoundarytype;
+ pFRAM->iClipl = ((mng_framp)pChunk)->iBoundaryl;
+ pFRAM->iClipr = ((mng_framp)pChunk)->iBoundaryr;
+ pFRAM->iClipt = ((mng_framp)pChunk)->iBoundaryt;
+ pFRAM->iClipb = ((mng_framp)pChunk)->iBoundaryb;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_fram (pData, iFramemode,
+ iChangedelay, iDelay,
+ iChangetimeout, iTimeout,
+ iChangeclipping, iCliptype,
+ iClipl, iClipr,
+ iClipt, iClipb);
+#else
+ iRetcode = mng_process_display_fram (pData,
+ ((mng_framp)pChunk)->iMode,
+ ((mng_framp)pChunk)->iChangedelay,
+ ((mng_framp)pChunk)->iDelay,
+ ((mng_framp)pChunk)->iChangetimeout,
+ ((mng_framp)pChunk)->iTimeout,
+ ((mng_framp)pChunk)->iChangeclipping,
+ ((mng_framp)pChunk)->iBoundarytype,
+ ((mng_framp)pChunk)->iBoundaryl,
+ ((mng_framp)pChunk)->iBoundaryr,
+ ((mng_framp)pChunk)->iBoundaryt,
+ ((mng_framp)pChunk)->iBoundaryb);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iTempFramemode = iFramemode;
+ pData->iTempChangedelay = iChangedelay;
+ pData->iTempDelay = iDelay;
+ pData->iTempChangetimeout = iChangetimeout;
+ pData->iTempTimeout = iTimeout;
+ pData->iTempChangeclipping = iChangeclipping;
+ pData->iTempCliptype = iCliptype;
+ pData->iTempClipl = iClipl;
+ pData->iTempClipr = iClipr;
+ pData->iTempClipt = iClipt;
+ pData->iTempClipb = iClipb;
+#else
+ pData->iTempFramemode = ((mng_framp)pChunk)->iMode;
+ pData->iTempChangedelay = ((mng_framp)pChunk)->iChangedelay;
+ pData->iTempDelay = ((mng_framp)pChunk)->iDelay;
+ pData->iTempChangetimeout = ((mng_framp)pChunk)->iChangetimeout;
+ pData->iTempTimeout = ((mng_framp)pChunk)->iTimeout;
+ pData->iTempChangeclipping = ((mng_framp)pChunk)->iChangeclipping;
+ pData->iTempCliptype = ((mng_framp)pChunk)->iBoundarytype;
+ pData->iTempClipl = ((mng_framp)pChunk)->iBoundaryl;
+ pData->iTempClipr = ((mng_framp)pChunk)->iBoundaryr;
+ pData->iTempClipt = ((mng_framp)pChunk)->iBoundaryt;
+ pData->iTempClipb = ((mng_framp)pChunk)->iBoundaryb;
+#endif
+
+ iRetcode = mng_process_display_fram (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_FRAM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_fram (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_FRAM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_fram));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_FRAM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_fram (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_framp pFRAM = (mng_ani_framp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_FRAM, MNG_LC_START);
+#endif
+
+ if (pData->iBreakpoint) /* previously broken ? */
+ {
+ iRetcode = mng_process_display_fram2 (pData);
+ pData->iBreakpoint = 0; /* not again */
+ }
+ else
+ {
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_fram (pData, pFRAM->iFramemode,
+ pFRAM->iChangedelay, pFRAM->iDelay,
+ pFRAM->iChangetimeout, pFRAM->iTimeout,
+ pFRAM->iChangeclipping, pFRAM->iCliptype,
+ pFRAM->iClipl, pFRAM->iClipr,
+ pFRAM->iClipt, pFRAM->iClipb);
+#else
+ pData->iTempFramemode = pFRAM->iFramemode;
+ pData->iTempChangedelay = pFRAM->iChangedelay;
+ pData->iTempDelay = pFRAM->iDelay;
+ pData->iTempChangetimeout = pFRAM->iChangetimeout;
+ pData->iTempTimeout = pFRAM->iTimeout;
+ pData->iTempChangeclipping = pFRAM->iChangeclipping;
+ pData->iTempCliptype = pFRAM->iCliptype;
+ pData->iTempClipl = pFRAM->iClipl;
+ pData->iTempClipr = pFRAM->iClipr;
+ pData->iTempClipt = pFRAM->iClipt;
+ pData->iTempClipb = pFRAM->iClipb;
+
+ iRetcode = mng_process_display_fram (pData);
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_FRAM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MOVE
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_move (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iType,
+ mng_int32 iLocax,
+ mng_int32 iLocay)
+#else
+mng_retcode mng_create_ani_move (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_movep pMOVE;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_MOVE, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_move),
+ mng_free_obj_general,
+ mng_process_ani_move,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pMOVE = (mng_ani_movep)pTemp;
+#else
+ MNG_ALLOC (pData, pMOVE, sizeof (mng_ani_move));
+
+ pMOVE->sHeader.fCleanup = mng_free_ani_move;
+ pMOVE->sHeader.fProcess = mng_process_ani_move;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pMOVE);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pMOVE->iFirstid = iFirstid;
+ pMOVE->iLastid = iLastid;
+ pMOVE->iType = iType;
+ pMOVE->iLocax = iLocax;
+ pMOVE->iLocay = iLocay;
+#else
+ pMOVE->iFirstid = ((mng_movep)pChunk)->iFirstid;
+ pMOVE->iLastid = ((mng_movep)pChunk)->iLastid;
+ pMOVE->iType = ((mng_movep)pChunk)->iMovetype;
+ pMOVE->iLocax = ((mng_movep)pChunk)->iMovex;
+ pMOVE->iLocay = ((mng_movep)pChunk)->iMovey;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_move (pData, iFirstid, iLastid,
+ iType, iLocax, iLocay);
+#else
+ iRetcode = mng_process_display_move (pData,
+ ((mng_movep)pChunk)->iFirstid,
+ ((mng_movep)pChunk)->iLastid,
+ ((mng_movep)pChunk)->iMovetype,
+ ((mng_movep)pChunk)->iMovex,
+ ((mng_movep)pChunk)->iMovey);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iMOVEfromid = iFirstid;
+ pData->iMOVEtoid = iLastid;
+ pData->iMOVEmovetype = iType;
+ pData->iMOVEmovex = iLocax;
+ pData->iMOVEmovey = iLocay;
+#else
+ pData->iMOVEfromid = ((mng_movep)pChunk)->iFirstid;
+ pData->iMOVEtoid = ((mng_movep)pChunk)->iLastid;
+ pData->iMOVEmovetype = ((mng_movep)pChunk)->iMovetype;
+ pData->iMOVEmovex = ((mng_movep)pChunk)->iMovex;
+ pData->iMOVEmovey = ((mng_movep)pChunk)->iMovey;
+#endif
+
+ iRetcode = mng_process_display_move (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_MOVE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_move (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_MOVE, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_move));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_MOVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_move (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+ mng_ani_movep pMOVE = (mng_ani_movep)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_MOVE, MNG_LC_START);
+#endif
+ /* re-process the MOVE chunk */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_move (pData, pMOVE->iFirstid, pMOVE->iLastid,
+ pMOVE->iType, pMOVE->iLocax, pMOVE->iLocay);
+#else
+ pData->iMOVEfromid = pMOVE->iFirstid;
+ pData->iMOVEtoid = pMOVE->iLastid;
+ pData->iMOVEmovetype = pMOVE->iType;
+ pData->iMOVEmovex = pMOVE->iLocax;
+ pData->iMOVEmovey = pMOVE->iLocay;
+
+ iRetcode = mng_process_display_move (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_MOVE, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_CLIP
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_clip (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iType,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb)
+#else
+mng_retcode mng_create_ani_clip (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_clipp pCLIP;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CLIP, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_clip),
+ mng_free_obj_general,
+ mng_process_ani_clip,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pCLIP = (mng_ani_clipp)pTemp;
+#else
+ MNG_ALLOC (pData, pCLIP, sizeof (mng_ani_clip));
+
+ pCLIP->sHeader.fCleanup = mng_free_ani_clip;
+ pCLIP->sHeader.fProcess = mng_process_ani_clip;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pCLIP);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pCLIP->iFirstid = iFirstid;
+ pCLIP->iLastid = iLastid;
+ pCLIP->iType = iType;
+ pCLIP->iClipl = iClipl;
+ pCLIP->iClipr = iClipr;
+ pCLIP->iClipt = iClipt;
+ pCLIP->iClipb = iClipb;
+#else
+ pCLIP->iFirstid = ((mng_clipp)pChunk)->iFirstid;
+ pCLIP->iLastid = ((mng_clipp)pChunk)->iLastid;
+ pCLIP->iType = ((mng_clipp)pChunk)->iCliptype;
+ pCLIP->iClipl = ((mng_clipp)pChunk)->iClipl;
+ pCLIP->iClipr = ((mng_clipp)pChunk)->iClipr;
+ pCLIP->iClipt = ((mng_clipp)pChunk)->iClipt;
+ pCLIP->iClipb = ((mng_clipp)pChunk)->iClipb;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_clip (pData, iFirstid, iLastid,
+ iType, iClipl, iClipr,
+ iClipt, iClipb);
+#else
+ iRetcode = mng_process_display_clip (pData,
+ ((mng_clipp)pChunk)->iFirstid,
+ ((mng_clipp)pChunk)->iLastid,
+ ((mng_clipp)pChunk)->iCliptype,
+ ((mng_clipp)pChunk)->iClipl,
+ ((mng_clipp)pChunk)->iClipr,
+ ((mng_clipp)pChunk)->iClipt,
+ ((mng_clipp)pChunk)->iClipb);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iCLIPfromid = iFirstid;
+ pData->iCLIPtoid = iLastid;
+ pData->iCLIPcliptype = iType;
+ pData->iCLIPclipl = iClipl;
+ pData->iCLIPclipr = iClipr;
+ pData->iCLIPclipt = iClipt;
+ pData->iCLIPclipb = iClipb;
+#else
+ pData->iCLIPfromid = ((mng_clipp)pChunk)->iFirstid;
+ pData->iCLIPtoid = ((mng_clipp)pChunk)->iLastid;
+ pData->iCLIPcliptype = ((mng_clipp)pChunk)->iCliptype;
+ pData->iCLIPclipl = ((mng_clipp)pChunk)->iClipl;
+ pData->iCLIPclipr = ((mng_clipp)pChunk)->iClipr;
+ pData->iCLIPclipt = ((mng_clipp)pChunk)->iClipt;
+ pData->iCLIPclipb = ((mng_clipp)pChunk)->iClipb;
+#endif
+
+ iRetcode = mng_process_display_clip (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_CLIP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_clip (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CLIP, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_clip));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_CLIP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_clip (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+ mng_ani_clipp pCLIP = (mng_ani_clipp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CLIP, MNG_LC_START);
+#endif
+ /* re-process the CLIP chunk */
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_clip (pData, pCLIP->iFirstid, pCLIP->iLastid,
+ pCLIP->iType, pCLIP->iClipl, pCLIP->iClipr,
+ pCLIP->iClipt, pCLIP->iClipb);
+#else
+ pData->iCLIPfromid = pCLIP->iFirstid;
+ pData->iCLIPtoid = pCLIP->iLastid;
+ pData->iCLIPcliptype = pCLIP->iType;
+ pData->iCLIPclipl = pCLIP->iClipl;
+ pData->iCLIPclipr = pCLIP->iClipr;
+ pData->iCLIPclipt = pCLIP->iClipt;
+ pData->iCLIPclipb = pCLIP->iClipb;
+
+ iRetcode = mng_process_display_clip (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_CLIP, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SHOW
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_show (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMode)
+#else
+mng_retcode mng_create_ani_show (mng_datap pData)
+#endif
+{
+ mng_ani_showp pSHOW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SHOW, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_show),
+ mng_free_obj_general,
+ mng_process_ani_show,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pSHOW = (mng_ani_showp)pTemp;
+#else
+ MNG_ALLOC (pData, pSHOW, sizeof (mng_ani_show));
+
+ pSHOW->sHeader.fCleanup = mng_free_ani_show;
+ pSHOW->sHeader.fProcess = mng_process_ani_show;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSHOW);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pSHOW->iFirstid = iFirstid;
+ pSHOW->iLastid = iLastid;
+ pSHOW->iMode = iMode;
+#else
+ pSHOW->iFirstid = pData->iSHOWfromid;
+ pSHOW->iLastid = pData->iSHOWtoid;
+ pSHOW->iMode = pData->iSHOWmode;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_show (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SHOW, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_show));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SHOW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_show (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+ mng_ani_showp pSHOW = (mng_ani_showp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SHOW, MNG_LC_START);
+#endif
+
+ if (pData->iBreakpoint) /* returning from breakpoint ? */
+ {
+ iRetcode = mng_process_display_show (pData);
+ }
+ else
+ { /* "re-run" SHOW chunk */
+ pData->iSHOWmode = pSHOW->iMode;
+ pData->iSHOWfromid = pSHOW->iFirstid;
+ pData->iSHOWtoid = pSHOW->iLastid;
+
+ iRetcode = mng_process_display_show (pData);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SHOW, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_TERM
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_term (mng_datap pData,
+ mng_uint8 iTermaction,
+ mng_uint8 iIteraction,
+ mng_uint32 iDelay,
+ mng_uint32 iItermax)
+#else
+mng_retcode mng_create_ani_term (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_termp pTERM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_TERM, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_term),
+ mng_free_obj_general,
+ mng_process_ani_term,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pTERM = (mng_ani_termp)pTemp;
+#else
+ MNG_ALLOC (pData, pTERM, sizeof (mng_ani_term));
+
+ pTERM->sHeader.fCleanup = mng_free_ani_term;
+ pTERM->sHeader.fProcess = mng_process_ani_term;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pTERM);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pTERM->iTermaction = iTermaction;
+ pTERM->iIteraction = iIteraction;
+ pTERM->iDelay = iDelay;
+ pTERM->iItermax = iItermax;
+#else
+ pTERM->iTermaction = ((mng_termp)pChunk)->iTermaction;
+ pTERM->iIteraction = ((mng_termp)pChunk)->iIteraction;
+ pTERM->iDelay = ((mng_termp)pChunk)->iDelay;
+ pTERM->iItermax = ((mng_termp)pChunk)->iItermax;
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_term (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_TERM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_term));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_term (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_TERM, MNG_LC_START);
+#endif
+
+ /* dummy: no action required! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_TERM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_create_ani_save (mng_datap pData)
+{
+ mng_ptr pTemp;
+ mng_ani_savep pSAVE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SAVE, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_save),
+ mng_free_obj_general,
+ mng_process_ani_save,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pSAVE = (mng_ani_savep)pTemp;
+#else
+ MNG_ALLOC (pData, pSAVE, sizeof (mng_ani_save));
+
+ pSAVE->sHeader.fCleanup = mng_free_ani_save;
+ pSAVE->sHeader.fProcess = mng_process_ani_save;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSAVE);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_save (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SAVE, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_save));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_save (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SAVE, MNG_LC_START);
+#endif
+
+ iRetcode = mng_process_display_save (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SAVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_SEEK
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_seek (mng_datap pData,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname)
+#else
+mng_retcode mng_create_ani_seek (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ptr pTemp;
+ mng_ani_seekp pSEEK;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SEEK, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_seek),
+ mng_free_ani_seek,
+ mng_process_ani_seek,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pSEEK = (mng_ani_seekp)pTemp;
+#else
+ MNG_ALLOC (pData, pSEEK, sizeof (mng_ani_seek));
+
+ pSEEK->sHeader.fCleanup = mng_free_ani_seek;
+ pSEEK->sHeader.fProcess = mng_process_ani_seek;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSEEK);
+
+ pData->pLastseek = (mng_objectp)pSEEK;
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pSEEK->iSegmentnamesize = iSegmentnamesize;
+ if (iSegmentnamesize)
+ {
+ MNG_ALLOC (pData, pSEEK->zSegmentname, iSegmentnamesize + 1);
+ MNG_COPY (pSEEK->zSegmentname, zSegmentname, iSegmentnamesize);
+ }
+#else
+ pSEEK->iSegmentnamesize = ((mng_seekp)pChunk)->iNamesize;
+ if (pSEEK->iSegmentnamesize)
+ {
+ MNG_ALLOC (pData, pSEEK->zSegmentname, pSEEK->iSegmentnamesize + 1);
+ MNG_COPY (pSEEK->zSegmentname, ((mng_seekp)pChunk)->zName, pSEEK->iSegmentnamesize);
+ }
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_seek (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_seekp pSEEK = (mng_ani_seekp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SEEK, MNG_LC_START);
+#endif
+
+ if (pSEEK->iSegmentnamesize)
+ MNG_FREEX (pData, pSEEK->zSegmentname, pSEEK->iSegmentnamesize + 1);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_seek));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_SEEK, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_seek (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_seekp pSEEK = (mng_ani_seekp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SEEK, MNG_LC_START);
+#endif
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+ if (!pData->bStopafterseek) /* can we really process this one ? */
+#endif
+ {
+ pData->pLastseek = pObject;
+
+ if (pData->fProcessseek) /* inform the app ? */
+ {
+ mng_bool bOke;
+ mng_pchar zName;
+
+ MNG_ALLOC (pData, zName, pSEEK->iSegmentnamesize + 1);
+
+ if (pSEEK->iSegmentnamesize)
+ MNG_COPY (zName, pSEEK->zSegmentname, pSEEK->iSegmentnamesize);
+
+ bOke = pData->fProcessseek ((mng_handle)pData, zName);
+
+ MNG_FREEX (pData, zName, pSEEK->iSegmentnamesize + 1);
+
+ if (!bOke)
+ MNG_ERROR (pData, MNG_APPMISCERROR);
+ }
+ }
+
+ iRetcode = mng_process_display_seek (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_SEEK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_dhdr (mng_datap pData,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky)
+#else
+mng_retcode mng_create_ani_dhdr (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_dhdrp pDHDR;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DHDR, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_dhdr),
+ mng_free_obj_general,
+ mng_process_ani_dhdr,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pDHDR = (mng_ani_dhdrp)pTemp;
+#else
+ MNG_ALLOC (pData, pDHDR, sizeof (mng_ani_dhdr));
+
+ pDHDR->sHeader.fCleanup = mng_free_ani_dhdr;
+ pDHDR->sHeader.fProcess = mng_process_ani_dhdr;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pDHDR);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pDHDR->iObjectid = iObjectid;
+ pDHDR->iImagetype = iImagetype;
+ pDHDR->iDeltatype = iDeltatype;
+ pDHDR->iBlockwidth = iBlockwidth;
+ pDHDR->iBlockheight = iBlockheight;
+ pDHDR->iBlockx = iBlockx;
+ pDHDR->iBlocky = iBlocky;
+#else
+ pDHDR->iObjectid = ((mng_dhdrp)pChunk)->iObjectid;
+ pDHDR->iImagetype = ((mng_dhdrp)pChunk)->iImagetype;
+ pDHDR->iDeltatype = ((mng_dhdrp)pChunk)->iDeltatype;
+ pDHDR->iBlockwidth = ((mng_dhdrp)pChunk)->iBlockwidth;
+ pDHDR->iBlockheight = ((mng_dhdrp)pChunk)->iBlockheight;
+ pDHDR->iBlockx = ((mng_dhdrp)pChunk)->iBlockx;
+ pDHDR->iBlocky = ((mng_dhdrp)pChunk)->iBlocky;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_dhdr (pData, iObjectid,
+ iImagetype, iDeltatype,
+ iBlockwidth, iBlockheight,
+ iBlockx, iBlocky);
+#else
+ iRetcode = mng_process_display_dhdr (pData,
+ ((mng_dhdrp)pChunk)->iObjectid,
+ ((mng_dhdrp)pChunk)->iImagetype,
+ ((mng_dhdrp)pChunk)->iDeltatype,
+ ((mng_dhdrp)pChunk)->iBlockwidth,
+ ((mng_dhdrp)pChunk)->iBlockheight,
+ ((mng_dhdrp)pChunk)->iBlockx,
+ ((mng_dhdrp)pChunk)->iBlocky);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iDHDRobjectid = iObjectid;
+ pData->iDHDRimagetype = iImagetype;
+ pData->iDHDRdeltatype = iDeltatype;
+ pData->iDHDRblockwidth = iBlockwidth;
+ pData->iDHDRblockheight = iBlockheight;
+ pData->iDHDRblockx = iBlockx;
+ pData->iDHDRblocky = iBlocky;
+#else
+ pData->iDHDRobjectid = ((mng_dhdrp)pChunk)->iObjectid;
+ pData->iDHDRimagetype = ((mng_dhdrp)pChunk)->iImagetype;
+ pData->iDHDRdeltatype = ((mng_dhdrp)pChunk)->iDeltatype;
+ pData->iDHDRblockwidth = ((mng_dhdrp)pChunk)->iBlockwidth;
+ pData->iDHDRblockheight = ((mng_dhdrp)pChunk)->iBlockheight;
+ pData->iDHDRblockx = ((mng_dhdrp)pChunk)->iBlockx;
+ pData->iDHDRblocky = ((mng_dhdrp)pChunk)->iBlocky;
+#endif
+
+ iRetcode = mng_process_display_dhdr (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_dhdr (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DHDR, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_dhdr));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DHDR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_dhdr (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_dhdrp pDHDR = (mng_ani_dhdrp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DHDR, MNG_LC_START);
+#endif
+
+ pData->bHasDHDR = MNG_TRUE; /* let everyone know we're inside a DHDR */
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_dhdr (pData, pDHDR->iObjectid,
+ pDHDR->iImagetype, pDHDR->iDeltatype,
+ pDHDR->iBlockwidth, pDHDR->iBlockheight,
+ pDHDR->iBlockx, pDHDR->iBlocky);
+#else
+ pData->iDHDRobjectid = pDHDR->iObjectid;
+ pData->iDHDRimagetype = pDHDR->iImagetype;
+ pData->iDHDRdeltatype = pDHDR->iDeltatype;
+ pData->iDHDRblockwidth = pDHDR->iBlockwidth;
+ pData->iDHDRblockheight = pDHDR->iBlockheight;
+ pData->iDHDRblockx = pDHDR->iBlockx;
+ pData->iDHDRblocky = pDHDR->iBlocky;
+
+ iRetcode = mng_process_display_dhdr (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DHDR, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_prom (mng_datap pData,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype)
+#else
+mng_retcode mng_create_ani_prom (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_promp pPROM=NULL;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PROM, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_prom),
+ mng_free_obj_general,
+ mng_process_ani_prom,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pPROM = (mng_ani_promp)pTemp;
+#else
+ MNG_ALLOC (pData, pPROM, sizeof (mng_ani_prom));
+
+ pPROM->sHeader.fCleanup = mng_free_ani_prom;
+ pPROM->sHeader.fProcess = mng_process_ani_prom;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pPROM);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pPROM->iBitdepth = iBitdepth;
+ pPROM->iColortype = iColortype;
+ pPROM->iFilltype = iFilltype;
+#else
+ pPROM->iBitdepth = ((mng_promp)pChunk)->iSampledepth;
+ pPROM->iColortype = ((mng_promp)pChunk)->iColortype;
+ pPROM->iFilltype = ((mng_promp)pChunk)->iFilltype;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_prom (pData, iBitdepth,
+ iColortype, iFilltype);
+#else
+ iRetcode = mng_process_display_prom (pData,
+ ((mng_promp)pChunk)->iSampledepth,
+ ((mng_promp)pChunk)->iColortype,
+ ((mng_promp)pChunk)->iFilltype);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iPROMbitdepth = iBitdepth;
+ pData->iPROMcolortype = iColortype;
+ pData->iPROMfilltype = iFilltype;
+#else
+ pData->iPROMbitdepth = ((mng_promp)pChunk)->iSampledepth;
+ pData->iPROMcolortype = ((mng_promp)pChunk)->iColortype;
+ pData->iPROMfilltype = ((mng_promp)pChunk)->iFilltype;
+#endif
+
+ iRetcode = mng_process_display_prom (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PROM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_prom (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PROM, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_prom));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PROM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_prom (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_promp pPROM = (mng_ani_promp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PROM, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_prom (pData, pPROM->iBitdepth,
+ pPROM->iColortype, pPROM->iFilltype);
+#else
+ pData->iPROMbitdepth = pPROM->iBitdepth;
+ pData->iPROMcolortype = pPROM->iColortype;
+ pData->iPROMfilltype = pPROM->iFilltype;
+
+ iRetcode = mng_process_display_prom (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PROM, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_create_ani_ipng (mng_datap pData)
+{
+ mng_ani_ipngp pIPNG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IPNG, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_ipng),
+ mng_free_obj_general,
+ mng_process_ani_ipng,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pIPNG = (mng_ani_ipngp)pTemp;
+#else
+ MNG_ALLOC (pData, pIPNG, sizeof (mng_ani_ipng));
+
+ pIPNG->sHeader.fCleanup = mng_free_ani_ipng;
+ pIPNG->sHeader.fProcess = mng_process_ani_ipng;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pIPNG);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_ipng (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IPNG, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_ipng));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_ipng (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IPNG, MNG_LC_START);
+#endif
+
+ iRetcode = mng_process_display_ipng (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IPNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_create_ani_ijng (mng_datap pData)
+{
+ mng_ani_ijngp pIJNG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IJNG, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_ani_ijng),
+ mng_free_obj_general,
+ mng_process_ani_ijng,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pIJNG = (mng_ani_ijngp)pTemp;
+#else
+ MNG_ALLOC (pData, pIJNG, sizeof (mng_ani_ijng));
+
+ pIJNG->sHeader.fCleanup = mng_free_ani_ijng;
+ pIJNG->sHeader.fProcess = mng_process_ani_ijng;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pIJNG);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_ijng (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IJNG, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_ijng));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_ijng (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IJNG, MNG_LC_START);
+#endif
+
+ iRetcode = mng_process_display_ijng (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_IJNG, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_create_ani_pplt (mng_datap pData,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_palette8ep paIndexentries,
+ mng_uint8p paAlphaentries,
+ mng_uint8p paUsedentries)
+{
+ mng_ani_ppltp pPPLT;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PPLT, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_pplt),
+ mng_free_obj_general,
+ mng_process_ani_pplt,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pPPLT = (mng_ani_ppltp)pTemp;
+#else
+ MNG_ALLOC (pData, pPPLT, sizeof (mng_ani_pplt));
+
+ pPPLT->sHeader.fCleanup = mng_free_ani_pplt;
+ pPPLT->sHeader.fProcess = mng_process_ani_pplt;
+#endif
+
+ pPPLT->iType = iType;
+ pPPLT->iCount = iCount;
+
+ MNG_COPY (pPPLT->aIndexentries, paIndexentries, sizeof (pPPLT->aIndexentries));
+ MNG_COPY (pPPLT->aAlphaentries, paAlphaentries, sizeof (pPPLT->aAlphaentries));
+ MNG_COPY (pPPLT->aUsedentries, paUsedentries, sizeof (pPPLT->aUsedentries ));
+
+ mng_add_ani_object (pData, (mng_object_headerp)pPPLT);
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_pplt (pData, iType, iCount,
+ paIndexentries, paAlphaentries, paUsedentries);
+#else
+ pData->iPPLTtype = iType;
+ pData->iPPLTcount = iCount;
+ pData->paPPLTindexentries = paIndexentries;
+ pData->paPPLTalphaentries = paAlphaentries;
+ pData->paPPLTusedentries = paUsedentries;
+
+ iRetcode = mng_process_display_pplt (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PPLT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_pplt (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PPLT, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_pplt));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PPLT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_pplt (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_ppltp pPPLT = (mng_ani_ppltp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PPLT, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_pplt (pData, pPPLT->iType, pPPLT->iCount,
+ pPPLT->aIndexentries, pPPLT->aAlphaentries,
+ pPPLT->aUsedentries);
+#else
+ pData->iPPLTtype = pPPLT->iType;
+ pData->iPPLTcount = pPPLT->iCount;
+ pData->paPPLTindexentries = &pPPLT->aIndexentries;
+ pData->paPPLTalphaentries = &pPPLT->aAlphaentries;
+ pData->paPPLTusedentries = &pPPLT->aUsedentries;
+
+ iRetcode = mng_process_display_pplt (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PPLT, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_magn (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint8 iMethodY)
+#else
+mng_retcode mng_create_ani_magn (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_magnp pMAGN=NULL;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_MAGN, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_magn),
+ mng_free_obj_general,
+ mng_process_ani_magn,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pMAGN = (mng_ani_magnp)pTemp;
+#else
+ MNG_ALLOC (pData, pMAGN, sizeof (mng_ani_magn));
+
+ pMAGN->sHeader.fCleanup = mng_free_ani_magn;
+ pMAGN->sHeader.fProcess = mng_process_ani_magn;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pMAGN);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pMAGN->iFirstid = iFirstid;
+ pMAGN->iLastid = iLastid;
+ pMAGN->iMethodX = iMethodX;
+ pMAGN->iMX = iMX;
+ pMAGN->iMY = iMY;
+ pMAGN->iML = iML;
+ pMAGN->iMR = iMR;
+ pMAGN->iMT = iMT;
+ pMAGN->iMB = iMB;
+ pMAGN->iMethodY = iMethodY;
+#else
+ pMAGN->iFirstid = ((mng_magnp)pChunk)->iFirstid;
+ pMAGN->iLastid = ((mng_magnp)pChunk)->iLastid;
+ pMAGN->iMethodX = ((mng_magnp)pChunk)->iMethodX;
+ pMAGN->iMX = ((mng_magnp)pChunk)->iMX;
+ pMAGN->iMY = ((mng_magnp)pChunk)->iMY;
+ pMAGN->iML = ((mng_magnp)pChunk)->iML;
+ pMAGN->iMR = ((mng_magnp)pChunk)->iMR;
+ pMAGN->iMT = ((mng_magnp)pChunk)->iMT;
+ pMAGN->iMB = ((mng_magnp)pChunk)->iMB;
+ pMAGN->iMethodY = ((mng_magnp)pChunk)->iMethodY;
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_magn (pData, pMAGN->iFirstid, pMAGN->iLastid,
+ pMAGN->iMethodX, pMAGN->iMX, pMAGN->iMY,
+ pMAGN->iML, pMAGN->iMR, pMAGN->iMT,
+ pMAGN->iMB, pMAGN->iMethodY);
+#else
+ iRetcode = mng_process_display_magn (pData,
+ ((mng_magnp)pChunk)->iFirstid,
+ ((mng_magnp)pChunk)->iLastid,
+ ((mng_magnp)pChunk)->iMethodX,
+ ((mng_magnp)pChunk)->iMX,
+ ((mng_magnp)pChunk)->iMY,
+ ((mng_magnp)pChunk)->iML,
+ ((mng_magnp)pChunk)->iMR,
+ ((mng_magnp)pChunk)->iMT,
+ ((mng_magnp)pChunk)->iMB,
+ ((mng_magnp)pChunk)->iMethodY);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iMAGNfirstid = iFirstid;
+ pData->iMAGNlastid = iLastid;
+ pData->iMAGNmethodX = iMethodX;
+ pData->iMAGNmX = iMX;
+ pData->iMAGNmY = iMY;
+ pData->iMAGNmL = iML;
+ pData->iMAGNmR = iMR;
+ pData->iMAGNmT = iMT;
+ pData->iMAGNmB = iMB;
+ pData->iMAGNmethodY = iMethodY;
+#else
+ pData->iMAGNfirstid = ((mng_magnp)pChunk)->iFirstid;
+ pData->iMAGNlastid = ((mng_magnp)pChunk)->iLastid;
+ pData->iMAGNmethodX = ((mng_magnp)pChunk)->iMethodX;
+ pData->iMAGNmX = ((mng_magnp)pChunk)->iMX;
+ pData->iMAGNmY = ((mng_magnp)pChunk)->iMY;
+ pData->iMAGNmL = ((mng_magnp)pChunk)->iML;
+ pData->iMAGNmR = ((mng_magnp)pChunk)->iMR;
+ pData->iMAGNmT = ((mng_magnp)pChunk)->iMT;
+ pData->iMAGNmB = ((mng_magnp)pChunk)->iMB;
+ pData->iMAGNmethodY = ((mng_magnp)pChunk)->iMethodY;
+#endif
+
+ iRetcode = mng_process_display_magn (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_MAGN, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+mng_retcode mng_free_ani_magn (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_MAGN, MNG_LC_START);
+#endif
+
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_magn));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_MAGN, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_magn (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_magnp pMAGN = (mng_ani_magnp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_MAGN, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_magn (pData, pMAGN->iFirstid, pMAGN->iLastid,
+ pMAGN->iMethodX, pMAGN->iMX, pMAGN->iMY,
+ pMAGN->iML, pMAGN->iMR, pMAGN->iMT,
+ pMAGN->iMB, pMAGN->iMethodY);
+#else
+ pData->iMAGNfirstid = pMAGN->iFirstid;
+ pData->iMAGNlastid = pMAGN->iLastid;
+ pData->iMAGNmethodX = pMAGN->iMethodX;
+ pData->iMAGNmX = pMAGN->iMX;
+ pData->iMAGNmY = pMAGN->iMY;
+ pData->iMAGNmL = pMAGN->iML;
+ pData->iMAGNmR = pMAGN->iMR;
+ pData->iMAGNmT = pMAGN->iMT;
+ pData->iMAGNmB = pMAGN->iMB;
+ pData->iMAGNmethodY = pMAGN->iMethodY;
+
+ iRetcode = mng_process_display_magn (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_MAGN, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_past (mng_datap pData,
+ mng_uint16 iTargetid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount,
+ mng_ptr pSources)
+#else
+mng_retcode mng_create_ani_past (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_pastp pPAST;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PAST, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_past),
+ mng_free_ani_past,
+ mng_process_ani_past,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pPAST = (mng_ani_pastp)pTemp;
+#else
+ MNG_ALLOC (pData, pPAST, sizeof (mng_ani_past));
+
+ pPAST->sHeader.fCleanup = mng_free_ani_past;
+ pPAST->sHeader.fProcess = mng_process_ani_past;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pPAST);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pPAST->iTargetid = iTargetid;
+ pPAST->iTargettype = iTargettype;
+ pPAST->iTargetx = iTargetx;
+ pPAST->iTargety = iTargety;
+ pPAST->iCount = iCount;
+
+ if (iCount)
+ {
+ MNG_ALLOC (pData, pPAST->pSources, (iCount * sizeof (mng_past_source)));
+ MNG_COPY (pPAST->pSources, pSources, (iCount * sizeof (mng_past_source)));
+ }
+#else
+ pPAST->iTargetid = ((mng_pastp)pChunk)->iDestid;
+ pPAST->iTargettype = ((mng_pastp)pChunk)->iTargettype;
+ pPAST->iTargetx = ((mng_pastp)pChunk)->iTargetx;
+ pPAST->iTargety = ((mng_pastp)pChunk)->iTargety;
+ pPAST->iCount = ((mng_pastp)pChunk)->iCount;
+
+ if (pPAST->iCount)
+ {
+ mng_size_t iSize = (mng_size_t)(pPAST->iCount * sizeof (mng_past_source));
+ MNG_ALLOC (pData, pPAST->pSources, iSize);
+ MNG_COPY (pPAST->pSources, ((mng_pastp)pChunk)->pSources, iSize);
+ }
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_past (pData, iTargetid, iTargettype,
+ iTargetx, iTargety,
+ iCount, pSources);
+#else
+ iRetcode = mng_process_display_past (pData,
+ ((mng_pastp)pChunk)->iDestid,
+ ((mng_pastp)pChunk)->iTargettype,
+ ((mng_pastp)pChunk)->iTargetx,
+ ((mng_pastp)pChunk)->iTargety,
+ ((mng_pastp)pChunk)->iCount,
+ ((mng_pastp)pChunk)->pSources);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iPASTtargetid = iTargetid;
+ pData->iPASTtargettype = iTargettype;
+ pData->iPASTtargetx = iTargetx;
+ pData->iPASTtargety = iTargety;
+ pData->iPASTcount = iCount;
+ pData->pPASTsources = pSources;
+#else
+ pData->iPASTtargetid = ((mng_pastp)pChunk)->iDestid;
+ pData->iPASTtargettype = ((mng_pastp)pChunk)->iTargettype;
+ pData->iPASTtargetx = ((mng_pastp)pChunk)->iTargetx;
+ pData->iPASTtargety = ((mng_pastp)pChunk)->iTargety;
+ pData->iPASTcount = ((mng_pastp)pChunk)->iCount;
+ pData->pPASTsources = ((mng_pastp)pChunk)->pSources;
+#endif
+
+ iRetcode = mng_process_display_past (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_PAST, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_free_ani_past (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_pastp pPAST = (mng_ani_pastp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PAST, MNG_LC_START);
+#endif
+
+ if (pPAST->iCount)
+ MNG_FREEX (pData, pPAST->pSources, (pPAST->iCount * sizeof (mng_past_source)));
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_past));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_PAST, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_process_ani_past (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_pastp pPAST = (mng_ani_pastp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PAST, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_past (pData, pPAST->iTargetid, pPAST->iTargettype,
+ pPAST->iTargetx, pPAST->iTargety,
+ pPAST->iCount, pPAST->pSources);
+#else
+ pData->iPASTtargetid = pPAST->iTargetid;
+ pData->iPASTtargettype = pPAST->iTargettype;
+ pData->iPASTtargetx = pPAST->iTargetx;
+ pData->iPASTtargety = pPAST->iTargety;
+ pData->iPASTcount = pPAST->iCount;
+ pData->pPASTsources = pPAST->pSources;
+
+ iRetcode = mng_process_display_past (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_PAST, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ani_disc (mng_datap pData,
+ mng_uint32 iCount,
+ mng_uint16p pIds)
+#else
+mng_retcode mng_create_ani_disc (mng_datap pData,
+ mng_chunkp pChunk)
+#endif
+{
+ mng_ani_discp pDISC;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DISC, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_disc),
+ mng_free_ani_disc,
+ mng_process_ani_disc,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pDISC = (mng_ani_discp)pTemp;
+#else
+ MNG_ALLOC (pData, pDISC, sizeof (mng_ani_disc));
+
+ pDISC->sHeader.fCleanup = mng_free_ani_disc;
+ pDISC->sHeader.fProcess = mng_process_ani_disc;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pDISC);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pDISC->iCount = iCount;
+
+ if (iCount)
+ {
+ MNG_ALLOC (pData, pDISC->pIds, (iCount << 1));
+ MNG_COPY (pDISC->pIds, pIds, (iCount << 1));
+ }
+#else
+ pDISC->iCount = ((mng_discp)pChunk)->iCount;
+
+ if (pDISC->iCount)
+ {
+ mng_size_t iSize = (mng_size_t)(pDISC->iCount << 1);
+ MNG_ALLOC (pData, pDISC->pIds, iSize);
+ MNG_COPY (pDISC->pIds, ((mng_discp)pChunk)->pObjectids, iSize);
+ }
+#endif
+ }
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ iRetcode = mng_process_display_disc (pData, iCount, pIds);
+#else
+ iRetcode = mng_process_display_disc (pData,
+ ((mng_discp)pChunk)->iCount,
+ ((mng_discp)pChunk)->pObjectids);
+#endif
+#else
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pData->iDISCcount = iCount;
+ pData->pDISCids = pIds;
+#else
+ pData->iDISCcount = ((mng_discp)pChunk)->iCount;
+ pData->pDISCids = ((mng_discp)pChunk)->pObjectids;
+#endif
+
+ iRetcode = mng_process_display_disc (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANI_DISC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_disc (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_discp pDISC = (mng_ani_discp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DISC, MNG_LC_START);
+#endif
+
+ if (pDISC->iCount)
+ MNG_FREEX (pData, pDISC->pIds, (pDISC->iCount << 1));
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pObject, sizeof (mng_ani_disc));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANI_DISC, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_disc (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ani_discp pDISC = (mng_ani_discp)pObject;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DISC, MNG_LC_START);
+#endif
+
+#ifndef MNG_OPTIMIZE_DISPLAYCALLS
+ iRetcode = mng_process_display_disc (pData, pDISC->iCount, pDISC->pIds);
+#else
+ pData->iDISCcount = pDISC->iCount;
+ pData->pDISCids = pDISC->pIds;
+
+ iRetcode = mng_process_display_disc (pData);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANI_DISC, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+#endif
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_event (mng_datap pData,
+ mng_uint8 iEventtype,
+ mng_uint8 iMasktype,
+ mng_int32 iLeft,
+ mng_int32 iRight,
+ mng_int32 iTop,
+ mng_int32 iBottom,
+ mng_uint16 iObjectid,
+ mng_uint8 iIndex,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname)
+#else
+mng_retcode mng_create_event (mng_datap pData,
+ mng_ptr pEntry)
+#endif
+{
+ mng_eventp pEvent;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_EVENT, MNG_LC_START);
+#endif
+
+ if (pData->bCacheplayback) /* caching playback info ? */
+ {
+ mng_object_headerp pLast;
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_ptr pTemp;
+ mng_retcode iRetcode = create_obj_general (pData, sizeof (mng_event),
+ mng_free_event,
+ mng_process_event,
+ &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pEvent = (mng_eventp)pTemp;
+#else
+ MNG_ALLOC (pData, pEvent, sizeof (mng_event));
+
+ pEvent->sHeader.fCleanup = mng_free_event;
+ pEvent->sHeader.fProcess = mng_process_event;
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pEvent->iEventtype = iEventtype;
+ pEvent->iMasktype = iMasktype;
+ pEvent->iLeft = iLeft;
+ pEvent->iRight = iRight;
+ pEvent->iTop = iTop;
+ pEvent->iBottom = iBottom;
+ pEvent->iObjectid = iObjectid;
+ pEvent->iIndex = iIndex;
+ pEvent->iSegmentnamesize = iSegmentnamesize;
+
+ if (iSegmentnamesize)
+ {
+ MNG_ALLOC (pData, pEvent->zSegmentname, iSegmentnamesize+1);
+ MNG_COPY (pEvent->zSegmentname, zSegmentname, iSegmentnamesize);
+ }
+#else
+ pEvent->iEventtype = ((mng_evnt_entryp)pEntry)->iEventtype;
+ pEvent->iMasktype = ((mng_evnt_entryp)pEntry)->iMasktype;
+ pEvent->iLeft = ((mng_evnt_entryp)pEntry)->iLeft;
+ pEvent->iRight = ((mng_evnt_entryp)pEntry)->iRight;
+ pEvent->iTop = ((mng_evnt_entryp)pEntry)->iTop;
+ pEvent->iBottom = ((mng_evnt_entryp)pEntry)->iBottom;
+ pEvent->iObjectid = ((mng_evnt_entryp)pEntry)->iObjectid;
+ pEvent->iIndex = ((mng_evnt_entryp)pEntry)->iIndex;
+ pEvent->iSegmentnamesize = ((mng_evnt_entryp)pEntry)->iSegmentnamesize;
+
+ if (pEvent->iSegmentnamesize)
+ {
+ MNG_ALLOC (pData, pEvent->zSegmentname, pEvent->iSegmentnamesize+1);
+ MNG_COPY (pEvent->zSegmentname, ((mng_evnt_entryp)pEntry)->zSegmentname, pEvent->iSegmentnamesize);
+ }
+#endif
+ /* fixup the double-linked list */
+ pLast = (mng_object_headerp)pData->pLastevent;
+
+ if (pLast) /* link it as last in the chain */
+ {
+ pEvent->sHeader.pPrev = pLast;
+ pLast->pNext = pEvent;
+ }
+ else
+ {
+ pData->pFirstevent = pEvent;
+ }
+
+ pData->pLastevent = pEvent;
+ pData->bDynamic = MNG_TRUE;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_EVENT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_event (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_eventp pEvent = (mng_eventp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EVENT, MNG_LC_START);
+#endif
+
+ if (pEvent->iSegmentnamesize)
+ MNG_FREEX (pData, pEvent->zSegmentname, pEvent->iSegmentnamesize + 1);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pEvent, sizeof (mng_event));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_EVENT, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_event (mng_datap pData,
+ mng_objectp pObject)
+{
+#ifndef MNG_SKIPCHUNK_SEEK
+ mng_eventp pEvent = (mng_eventp)pObject;
+ mng_object_headerp pAni;
+ mng_bool bFound = MNG_FALSE;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_EVENT, MNG_LC_START);
+#endif
+
+#ifndef MNG_SKIPCHUNK_SEEK
+ if (!pEvent->pSEEK) /* need to find SEEK first ? */
+ {
+ pAni = (mng_object_headerp)pData->pFirstaniobj;
+
+ while ((pAni) && (!bFound))
+ {
+ if ((pAni->fCleanup == mng_free_ani_seek) &&
+ (strcmp(pEvent->zSegmentname, ((mng_ani_seekp)pAni)->zSegmentname) == 0))
+ bFound = MNG_TRUE;
+ else
+ pAni = (mng_object_headerp)pAni->pNext;
+ }
+
+ if (pAni)
+ pEvent->pSEEK = (mng_ani_seekp)pAni;
+ }
+
+ if (pEvent->pSEEK) /* anything to do ? */
+ {
+ pEvent->iLastx = pData->iEventx;
+ pEvent->iLasty = pData->iEventy;
+ /* let's start from this SEEK then */
+ pData->pCurraniobj = (mng_objectp)pEvent->pSEEK;
+ pData->bRunningevent = MNG_TRUE;
+ /* wake-up the app ! */
+ if (!pData->fSettimer ((mng_handle)pData, 5))
+ MNG_ERROR (pData, MNG_APPTIMERERROR);
+
+ }
+ else
+ MNG_ERROR (pData, MNG_SEEKNOTFOUND);
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_EVENT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_SUPPORT_DYNAMICMNG */
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_mpng_obj (mng_datap pData,
+ mng_uint32 iFramewidth,
+ mng_uint32 iFrameheight,
+ mng_uint16 iNumplays,
+ mng_uint16 iTickspersec,
+ mng_uint32 iFramessize,
+ mng_ptr pFrames)
+#else
+mng_retcode mng_create_mpng_obj (mng_datap pData,
+ mng_ptr pEntry)
+#endif
+{
+ mng_mpng_objp pMPNG;
+ mng_ptr pTemp;
+ mng_retcode iRetcode;
+ mng_uint8p pFrame;
+ mng_int32 iCnt, iMax;
+ mng_uint32 iX, iY, iWidth, iHeight;
+ mng_int32 iXoffset, iYoffset;
+ mng_uint16 iTicks;
+ mng_uint16 iDelay;
+ mng_bool bNewframe;
+ mng_ani_loopp pLOOP;
+ mng_ani_endlp pENDL;
+ mng_ani_framp pFRAM;
+ mng_ani_movep pMOVE;
+ mng_ani_clipp pCLIP;
+ mng_ani_showp pSHOW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_MPNG_OBJ, MNG_LC_START);
+#endif
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_mpng_obj), mng_free_mpng_obj,
+ mng_process_mpng_obj, &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pMPNG = (mng_mpng_objp)pTemp;
+#else
+ MNG_ALLOC (pData, pMPNG, sizeof (mng_mpng_obj));
+
+ pMPNG->sHeader.fCleanup = mng_free_mpng_obj;
+ pMPNG->sHeader.fProcess = mng_process_mpng_obj;
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pMPNG->iFramewidth = iFramewidth;
+ pMPNG->iFrameheight = iFrameheight;
+ pMPNG->iNumplays = iNumplays;
+ pMPNG->iTickspersec = iTickspersec;
+ pMPNG->iFramessize = iFramessize;
+
+ if (iFramessize)
+ {
+ MNG_ALLOC (pData, pMPNG->pFrames, iFramessize);
+ MNG_COPY (pMPNG->pFrames, pFrames, iFramessize);
+ }
+#else
+ pMPNG->iFramewidth = ((mng_mpngp)pEntry)->iFramewidth;
+ pMPNG->iFrameheight = ((mng_mpngp)pEntry)->iFrameheight;
+ pMPNG->iNumplays = ((mng_mpngp)pEntry)->iNumplays;
+ pMPNG->iTickspersec = ((mng_mpngp)pEntry)->iTickspersec;
+ pMPNG->iFramessize = ((mng_mpngp)pEntry)->iFramessize;
+
+ if (pMPNG->iFramessize)
+ {
+ MNG_ALLOC (pData, pMPNG->pFrames, pMPNG->iFramessize);
+ MNG_COPY (pMPNG->pFrames, ((mng_mpngp)pEntry)->pFrames, pMPNG->iFramessize);
+ }
+#endif
+
+ pData->pMPNG = pMPNG;
+ pData->eImagetype = mng_it_mpng;
+
+ iRetcode = mng_process_display_mpng (pData);
+ if (iRetcode)
+ return iRetcode;
+
+ /* now let's create the MNG animation directives from this */
+
+ pFrame = (mng_uint8p)pMPNG->pFrames;
+ iMax = pMPNG->iFramessize / 26;
+ /* set up MNG impersonation */
+ pData->iTicks = pMPNG->iTickspersec;
+ pData->iLayercount = iMax;
+
+ if (pMPNG->iNumplays != 1) /* create a LOOP/ENDL pair ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_loop),
+ mng_free_ani_loop, mng_process_ani_loop,
+ &((mng_ptr)pLOOP));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pLOOP, sizeof (mng_ani_loop));
+
+ pLOOP->sHeader.fCleanup = mng_free_ani_loop;
+ pLOOP->sHeader.fProcess = mng_process_ani_loop;
+#endif
+
+ pLOOP->iLevel = 1;
+ if (pMPNG->iNumplays)
+ pLOOP->iRepeatcount = pMPNG->iNumplays;
+ else
+ pLOOP->iRepeatcount = 0xFFFFFFFFl;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pLOOP);
+ }
+
+ bNewframe = MNG_TRUE; /* create the frame display objects */
+
+ for (iCnt = 0; iCnt < iMax; iCnt++)
+ {
+ iX = mng_get_uint32 (pFrame);
+ iY = mng_get_uint32 (pFrame+4);
+ iWidth = mng_get_uint32 (pFrame+8);
+ iHeight = mng_get_uint32 (pFrame+12);
+ iXoffset = mng_get_int32 (pFrame+16);
+ iYoffset = mng_get_int32 (pFrame+20);
+ iTicks = mng_get_uint16 (pFrame+24);
+
+ iDelay = iTicks;
+ if (!iDelay)
+ {
+ mng_uint8p pTemp = pFrame+26;
+ mng_int32 iTemp = iCnt+1;
+
+ while ((iTemp < iMax) && (!iDelay))
+ {
+ iDelay = mng_get_uint16 (pTemp+24);
+ pTemp += 26;
+ iTemp++;
+ }
+ }
+
+ if (bNewframe)
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_fram),
+ mng_free_obj_general, mng_process_ani_fram,
+ &((mng_ptr)pFRAM));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pFRAM, sizeof (mng_ani_fram));
+
+ pFRAM->sHeader.fCleanup = mng_free_ani_fram;
+ pFRAM->sHeader.fProcess = mng_process_ani_fram;
+#endif
+
+ pFRAM->iFramemode = 4;
+ pFRAM->iChangedelay = 1;
+ pFRAM->iDelay = iDelay;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pFRAM);
+ }
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_move),
+ mng_free_obj_general,
+ mng_process_ani_move,
+ &((mng_ptr)pMOVE));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pMOVE, sizeof (mng_ani_move));
+
+ pMOVE->sHeader.fCleanup = mng_free_ani_move;
+ pMOVE->sHeader.fProcess = mng_process_ani_move;
+#endif
+
+ pMOVE->iLocax = iXoffset - (mng_int32)iX;
+ pMOVE->iLocay = iYoffset - (mng_int32)iY;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pMOVE);
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_clip),
+ mng_free_obj_general,
+ mng_process_ani_clip,
+ &((mng_ptr)pCLIP));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pCLIP, sizeof (mng_ani_clip));
+
+ pCLIP->sHeader.fCleanup = mng_free_ani_clip;
+ pCLIP->sHeader.fProcess = mng_process_ani_clip;
+#endif
+
+ pCLIP->iClipl = iXoffset;
+ pCLIP->iClipr = iXoffset + (mng_int32)iWidth;
+ pCLIP->iClipt = iYoffset;
+ pCLIP->iClipb = iYoffset + (mng_int32)iHeight;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pCLIP);
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_show),
+ mng_free_obj_general, mng_process_ani_show,
+ &((mng_ptr)pSHOW));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pSHOW, sizeof (mng_ani_show));
+
+ pSHOW->sHeader.fCleanup = mng_free_ani_show;
+ pSHOW->sHeader.fProcess = mng_process_ani_show;
+#endif
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSHOW);
+
+ bNewframe = (mng_bool)iTicks;
+ pFrame += 26;
+ }
+
+ if (pMPNG->iNumplays != 1) /* create a LOOP/ENDL pair ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_endl),
+ mng_free_obj_general, mng_process_ani_endl,
+ &((mng_ptr)pENDL));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pENDL, sizeof (mng_ani_endl));
+
+ pENDL->sHeader.fCleanup = mng_free_ani_endl;
+ pENDL->sHeader.fProcess = mng_process_ani_endl;
+#endif
+
+ pENDL->iLevel = 1;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pENDL);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_MPNG_OBJ, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_mpng_obj (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_mpng_objp pMPNG = (mng_mpng_objp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MPNG_OBJ, MNG_LC_START);
+#endif
+
+ if (pMPNG->iFramessize)
+ MNG_FREEX (pData, pMPNG->pFrames, pMPNG->iFramessize);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pMPNG, sizeof (mng_mpng_obj));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_MPNG_OBJ, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_mpng_obj (mng_datap pData,
+ mng_objectp pObject)
+{
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_MPNG_PROPOSAL */
+
+/* ************************************************************************** */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ang_obj (mng_datap pData,
+ mng_uint32 iNumframes,
+ mng_uint32 iTickspersec,
+ mng_uint32 iNumplays,
+ mng_uint32 iTilewidth,
+ mng_uint32 iTileheight,
+ mng_uint8 iInterlace,
+ mng_uint8 iStillused)
+#else
+mng_retcode mng_create_ang_obj (mng_datap pData,
+ mng_ptr pEntry)
+#endif
+{
+ mng_ang_objp pANG;
+ mng_ptr pTemp;
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANG_OBJ, MNG_LC_START);
+#endif
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ang_obj), mng_free_ang_obj,
+ mng_process_ang_obj, &pTemp);
+ if (iRetcode)
+ return iRetcode;
+ pANG = (mng_ang_objp)pTemp;
+#else
+ MNG_ALLOC (pData, pANG, sizeof (mng_ang_obj));
+
+ pANG->sHeader.fCleanup = mng_free_ang_obj;
+ pANG->sHeader.fProcess = mng_process_ang_obj;
+#endif
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ pANG->iNumframes = iNumframes;
+ pANG->iTickspersec = iTickspersec;
+ pANG->iNumplays = iNumplays;
+ pANG->iTilewidth = iTilewidth;
+ pANG->iTileheight = iTileheight;
+ pANG->iInterlace = iInterlace;
+ pANG->iStillused = iStillused;
+#else
+ pANG->iNumframes = ((mng_ahdrp)pEntry)->iNumframes;
+ pANG->iTickspersec = ((mng_ahdrp)pEntry)->iTickspersec;
+ pANG->iNumplays = ((mng_ahdrp)pEntry)->iNumplays;
+ pANG->iTilewidth = ((mng_ahdrp)pEntry)->iTilewidth;
+ pANG->iTileheight = ((mng_ahdrp)pEntry)->iTileheight;
+ pANG->iInterlace = ((mng_ahdrp)pEntry)->iInterlace;
+ pANG->iStillused = ((mng_ahdrp)pEntry)->iStillused;
+#endif
+
+ pData->pANG = pANG;
+ pData->eImagetype = mng_it_ang;
+
+ iRetcode = mng_process_display_ang (pData);
+ if (iRetcode)
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CREATE_ANG_OBJ, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ang_obj (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ang_objp pANG = (mng_ang_objp)pObject;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANG_OBJ, MNG_LC_START);
+#endif
+
+ if (pANG->iTilessize)
+ MNG_FREEX (pData, pANG->pTiles, pANG->iTilessize);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ MNG_FREEX (pData, pANG, sizeof (mng_ang_obj));
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FREE_ANG_OBJ, MNG_LC_END);
+#endif
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+ return MNG_NOERROR;
+#else
+ return mng_free_obj_general(pData, pObject);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ang_obj (mng_datap pData,
+ mng_objectp pObject)
+{
+ mng_ang_objp pANG = (mng_ang_objp)pObject;
+ mng_uint8p pTile = (mng_uint8p)pANG->pTiles;
+ mng_retcode iRetcode;
+ mng_int32 iCnt, iMax;
+ mng_uint32 iTicks;
+ mng_int32 iXoffset, iYoffset;
+ mng_uint8 iSource;
+ mng_ani_loopp pLOOP;
+ mng_ani_endlp pENDL;
+ mng_ani_framp pFRAM;
+ mng_ani_movep pMOVE;
+ mng_ani_showp pSHOW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANG_OBJ, MNG_LC_START);
+#endif
+
+ /* let's create the MNG animation directives from this */
+
+ iMax = pANG->iNumframes;
+ /* set up MNG impersonation */
+ pData->iTicks = pANG->iTickspersec;
+ pData->iLayercount = iMax;
+
+ if (pANG->iNumplays != 1) /* create a LOOP/ENDL pair ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_loop),
+ mng_free_ani_loop, mng_process_ani_loop,
+ &((mng_ptr)pLOOP));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pLOOP, sizeof (mng_ani_loop));
+
+ pLOOP->sHeader.fCleanup = mng_free_ani_loop;
+ pLOOP->sHeader.fProcess = mng_process_ani_loop;
+#endif
+
+ pLOOP->iLevel = 1;
+ if (pANG->iNumplays)
+ pLOOP->iRepeatcount = pANG->iNumplays;
+ else
+ pLOOP->iRepeatcount = 0xFFFFFFFFl;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pLOOP);
+ }
+
+ for (iCnt = 0; iCnt < iMax; iCnt++)
+ {
+ iTicks = mng_get_uint32 (pTile);
+ iXoffset = mng_get_int32 (pTile+4);
+ iYoffset = mng_get_int32 (pTile+8);
+ iSource = *(pTile+12);
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_fram),
+ mng_free_obj_general, mng_process_ani_fram,
+ &((mng_ptr)pFRAM));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pFRAM, sizeof (mng_ani_fram));
+
+ pFRAM->sHeader.fCleanup = mng_free_ani_fram;
+ pFRAM->sHeader.fProcess = mng_process_ani_fram;
+#endif
+
+ pFRAM->iFramemode = 4;
+ pFRAM->iChangedelay = 1;
+ pFRAM->iDelay = iTicks;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pFRAM);
+
+ if (!iSource)
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_move),
+ mng_free_obj_general,
+ mng_process_ani_move,
+ &((mng_ptr)pMOVE));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pMOVE, sizeof (mng_ani_move));
+
+ pMOVE->sHeader.fCleanup = mng_free_ani_move;
+ pMOVE->sHeader.fProcess = mng_process_ani_move;
+#endif
+
+ pMOVE->iFirstid = 1;
+ pMOVE->iLastid = 1;
+ pMOVE->iLocax = -iXoffset;
+ pMOVE->iLocay = -iYoffset;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pMOVE);
+ }
+
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_show),
+ mng_free_obj_general, mng_process_ani_show,
+ &((mng_ptr)pSHOW));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pSHOW, sizeof (mng_ani_show));
+
+ pSHOW->sHeader.fCleanup = mng_free_ani_show;
+ pSHOW->sHeader.fProcess = mng_process_ani_show;
+#endif
+
+ if (iSource)
+ pSHOW->iFirstid = 0;
+ else
+ pSHOW->iFirstid = 1;
+ pSHOW->iLastid = pSHOW->iFirstid;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pSHOW);
+
+ pTile += sizeof(mng_adat_tile);
+ }
+
+ if (pANG->iNumplays != 1) /* create a LOOP/ENDL pair ? */
+ {
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ iRetcode = create_obj_general (pData, sizeof (mng_ani_endl),
+ mng_free_obj_general, mng_process_ani_endl,
+ &((mng_ptr)pENDL));
+ if (iRetcode)
+ return iRetcode;
+#else
+ MNG_ALLOC (pData, pENDL, sizeof (mng_ani_endl));
+
+ pENDL->sHeader.fCleanup = mng_free_ani_endl;
+ pENDL->sHeader.fProcess = mng_process_ani_endl;
+#endif
+
+ pENDL->iLevel = 1;
+
+ mng_add_ani_object (pData, (mng_object_headerp)pENDL);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_ANG_OBJ, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_ANG_PROPOSAL */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_object_prc.h b/Source/LibMNG/libmng_object_prc.h
new file mode 100644
index 0000000..ffd20c8
--- /dev/null
+++ b/Source/LibMNG/libmng_object_prc.h
@@ -0,0 +1,690 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_object_prc.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Object processing routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the internal object processing routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added support for global color-chunks in animation * */
+/* * - added support for global PLTE,tRNS,bKGD in animation * */
+/* * - added SAVE & SEEK animation objects * */
+/* * 0.5.2 - 05/29/2000 - G.Juyn * */
+/* * - changed ani_object create routines not to return the * */
+/* * created object (wasn't necessary) * */
+/* * - added compression/filter/interlace fields to * */
+/* * object-buffer for delta-image processing * */
+/* * * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added support for PPLT chunk * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added routine to discard "invalid" objects * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added in-memory color-correction of abstract images * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - fixed DISC support * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added conditionals around Delta-PNG code * */
+/* * - added SKIPCHUNK feature * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_OBJCLEANUP * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_object_prc_h_
+#define _libmng_object_prc_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode mng_drop_invalid_objects (mng_datap pData);
+
+/* ************************************************************************** */
+
+mng_retcode mng_create_imagedataobject (mng_datap pData,
+ mng_bool bConcrete,
+ mng_bool bViewable,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_imagedatap *ppObject);
+
+mng_retcode mng_free_imagedataobject (mng_datap pData,
+ mng_imagedatap pImagedata);
+
+mng_retcode mng_clone_imagedataobject (mng_datap pData,
+ mng_bool bConcrete,
+ mng_imagedatap pSource,
+ mng_imagedatap *ppClone);
+
+/* ************************************************************************** */
+
+mng_retcode mng_create_imageobject (mng_datap pData,
+ mng_uint16 iId,
+ mng_bool bConcrete,
+ mng_bool bVisible,
+ mng_bool bViewable,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_int32 iPosx,
+ mng_int32 iPosy,
+ mng_bool bClipped,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb,
+ mng_imagep *ppObject);
+
+mng_retcode mng_free_imageobject (mng_datap pData,
+ mng_imagep pImage);
+
+mng_imagep mng_find_imageobject (mng_datap pData,
+ mng_uint16 iId);
+
+mng_retcode mng_clone_imageobject (mng_datap pData,
+ mng_uint16 iId,
+ mng_bool bPartial,
+ mng_bool bVisible,
+ mng_bool bAbstract,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy,
+ mng_imagep pSource,
+ mng_imagep *ppClone);
+
+mng_retcode mng_renum_imageobject (mng_datap pData,
+ mng_imagep pSource,
+ mng_uint16 iId,
+ mng_bool bVisible,
+ mng_bool bAbstract,
+ mng_bool bHasloca,
+ mng_uint8 iLocationtype,
+ mng_int32 iLocationx,
+ mng_int32 iLocationy);
+
+mng_retcode mng_reset_object_details (mng_datap pData,
+ mng_imagep pImage,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iCompression,
+ mng_uint8 iFilter,
+ mng_uint8 iInterlace,
+ mng_bool bResetall);
+
+mng_retcode mng_promote_imageobject (mng_datap pData,
+ mng_imagep pImage,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype);
+
+mng_retcode mng_magnify_imageobject (mng_datap pData,
+ mng_imagep pImage);
+
+mng_retcode mng_colorcorrect_object (mng_datap pData,
+ mng_imagep pImage);
+
+/* ************************************************************************** */
+
+mng_retcode mng_create_ani_image (mng_datap pData);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+
+mng_retcode mng_create_ani_plte (mng_datap pData,
+ mng_uint32 iEntrycount,
+ mng_palette8ep paEntries);
+
+mng_retcode mng_create_ani_trns (mng_datap pData,
+ mng_uint32 iRawlen,
+ mng_uint8p pRawdata);
+
+mng_retcode mng_create_ani_gama (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iGamma);
+
+mng_retcode mng_create_ani_chrm (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iWhitepointx,
+ mng_uint32 iWhitepointy,
+ mng_uint32 iRedx,
+ mng_uint32 iRedy,
+ mng_uint32 iGreenx,
+ mng_uint32 iGreeny,
+ mng_uint32 iBluex,
+ mng_uint32 iBluey);
+
+mng_retcode mng_create_ani_srgb (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint8 iRenderinginent);
+
+mng_retcode mng_create_ani_iccp (mng_datap pData,
+ mng_bool bEmpty,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile);
+
+mng_retcode mng_create_ani_bkgd (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue);
+
+mng_retcode mng_create_ani_loop (mng_datap pData,
+ mng_uint8 iLevel,
+ mng_uint32 iRepeatcount,
+ mng_uint8 iTermcond,
+ mng_uint32 iItermin,
+ mng_uint32 iItermax,
+ mng_uint32 iCount,
+ mng_uint32p pSignals);
+
+mng_retcode mng_create_ani_endl (mng_datap pData,
+ mng_uint8 iLevel);
+
+mng_retcode mng_create_ani_defi (mng_datap pData);
+
+mng_retcode mng_create_ani_basi (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_bool bHasalpha,
+ mng_uint16 iAlpha,
+ mng_uint8 iViewable);
+
+mng_retcode mng_create_ani_clon (mng_datap pData,
+ mng_uint16 iSourceid,
+ mng_uint16 iCloneid,
+ mng_uint8 iClonetype,
+ mng_bool bHasdonotshow,
+ mng_uint8 iDonotshow,
+ mng_uint8 iConcrete,
+ mng_bool bHasloca,
+ mng_uint8 iLocatype,
+ mng_int32 iLocax,
+ mng_int32 iLocay);
+
+mng_retcode mng_create_ani_back (mng_datap pData,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue,
+ mng_uint8 iMandatory,
+ mng_uint16 iImageid,
+ mng_uint8 iTile);
+
+mng_retcode mng_create_ani_fram (mng_datap pData,
+ mng_uint8 iFramemode,
+ mng_uint8 iChangedelay,
+ mng_uint32 iDelay,
+ mng_uint8 iChangetimeout,
+ mng_uint32 iTimeout,
+ mng_uint8 iChangeclipping,
+ mng_uint8 iCliptype,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb);
+
+mng_retcode mng_create_ani_move (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iType,
+ mng_int32 iLocax,
+ mng_int32 iLocay);
+
+mng_retcode mng_create_ani_clip (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iType,
+ mng_int32 iClipl,
+ mng_int32 iClipr,
+ mng_int32 iClipt,
+ mng_int32 iClipb);
+
+mng_retcode mng_create_ani_show (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMode);
+
+mng_retcode mng_create_ani_term (mng_datap pData,
+ mng_uint8 iTermaction,
+ mng_uint8 iIteraction,
+ mng_uint32 iDelay,
+ mng_uint32 iItermax);
+
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_create_ani_save (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_create_ani_seek (mng_datap pData,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname);
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_create_ani_dhdr (mng_datap pData,
+ mng_uint16 iObjectid,
+ mng_uint8 iImagetype,
+ mng_uint8 iDeltatype,
+ mng_uint32 iBlockwidth,
+ mng_uint32 iBlockheight,
+ mng_uint32 iBlockx,
+ mng_uint32 iBlocky);
+
+mng_retcode mng_create_ani_prom (mng_datap pData,
+ mng_uint8 iBitdepth,
+ mng_uint8 iColortype,
+ mng_uint8 iFilltype);
+
+mng_retcode mng_create_ani_ipng (mng_datap pData);
+mng_retcode mng_create_ani_ijng (mng_datap pData);
+
+mng_retcode mng_create_ani_pplt (mng_datap pData,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_palette8ep paIndexentries,
+ mng_uint8p paAlphaentries,
+ mng_uint8p paUsedentries);
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_create_ani_magn (mng_datap pData,
+ mng_uint16 iFirstid,
+ mng_uint16 iLastid,
+ mng_uint8 iMethodX,
+ mng_uint16 iMX,
+ mng_uint16 iMY,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint16 iMT,
+ mng_uint16 iMB,
+ mng_uint8 iMethodY);
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_create_ani_past (mng_datap pData,
+ mng_uint16 iTargetid,
+ mng_uint8 iTargettype,
+ mng_int32 iTargetx,
+ mng_int32 iTargety,
+ mng_uint32 iCount,
+ mng_ptr pSources);
+#endif
+
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode mng_create_ani_disc (mng_datap pData,
+ mng_uint32 iCount,
+ mng_uint16p pIds);
+#endif
+
+#else /* MNG_OPTIMIZE_CHUNKREADER */
+
+mng_retcode mng_create_ani_plte (mng_datap pData);
+mng_retcode mng_create_ani_trns (mng_datap pData);
+mng_retcode mng_create_ani_gama (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_chrm (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_srgb (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_iccp (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_bkgd (mng_datap pData);
+mng_retcode mng_create_ani_loop (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_endl (mng_datap pData,
+ mng_uint8 iLevel);
+mng_retcode mng_create_ani_defi (mng_datap pData);
+mng_retcode mng_create_ani_basi (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_clon (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_back (mng_datap pData);
+mng_retcode mng_create_ani_fram (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_move (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_clip (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_show (mng_datap pData);
+mng_retcode mng_create_ani_term (mng_datap pData,
+ mng_chunkp pChunk);
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_create_ani_save (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_create_ani_seek (mng_datap pData,
+ mng_chunkp pChunk);
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_create_ani_dhdr (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_prom (mng_datap pData,
+ mng_chunkp pChunk);
+mng_retcode mng_create_ani_ipng (mng_datap pData);
+mng_retcode mng_create_ani_ijng (mng_datap pData);
+
+mng_retcode mng_create_ani_pplt (mng_datap pData,
+ mng_uint8 iType,
+ mng_uint32 iCount,
+ mng_palette8ep paIndexentries,
+ mng_uint8p paAlphaentries,
+ mng_uint8p paUsedentries);
+#endif
+
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_create_ani_magn (mng_datap pData,
+ mng_chunkp pChunk);
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_create_ani_past (mng_datap pData,
+ mng_chunkp pChunk);
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+mng_retcode mng_create_ani_disc (mng_datap pData,
+ mng_chunkp pChunk);
+#endif
+
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+/* ************************************************************************** */
+
+mng_retcode mng_free_ani_image (mng_datap pData,
+ mng_objectp pObject);
+
+#ifndef MNG_OPTIMIZE_OBJCLEANUP
+
+mng_retcode mng_free_ani_plte (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_trns (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_gama (mng_datap pData,
+ mng_objectp pObject);
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_retcode mng_free_ani_chrm (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+mng_retcode mng_free_ani_srgb (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+mng_retcode mng_free_ani_bkgd (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+mng_retcode mng_free_ani_endl (mng_datap pData,
+ mng_objectp pObject);
+#endif
+mng_retcode mng_free_ani_defi (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_basi (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_clon (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_back (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_fram (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_move (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_clip (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_show (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_term (mng_datap pData,
+ mng_objectp pObject);
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_free_ani_save (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_free_ani_dhdr (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_prom (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_ipng (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_ijng (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_free_ani_pplt (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+mng_retcode mng_free_ani_magn (mng_datap pData,
+ mng_objectp pObject);
+#endif
+
+#endif /* MNG_OPTIMIZE_OBJCLEANUP */
+
+
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode mng_free_ani_iccp (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+mng_retcode mng_free_ani_loop (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_free_ani_seek (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_free_ani_past (mng_datap pData,
+ mng_objectp pObject);
+#endif
+mng_retcode mng_free_ani_disc (mng_datap pData,
+ mng_objectp pObject);
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ani_image (mng_datap pData,
+ mng_objectp pObject);
+
+mng_retcode mng_process_ani_plte (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_trns (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_gama (mng_datap pData,
+ mng_objectp pObject);
+#ifndef MNG_SKIPCHUNK_cHRM
+mng_retcode mng_process_ani_chrm (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+mng_retcode mng_process_ani_srgb (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode mng_process_ani_iccp (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+mng_retcode mng_process_ani_bkgd (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+mng_retcode mng_process_ani_loop (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_endl (mng_datap pData,
+ mng_objectp pObject);
+#endif
+mng_retcode mng_process_ani_defi (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_basi (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_clon (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_back (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_fram (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_move (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_clip (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_show (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_term (mng_datap pData,
+ mng_objectp pObject);
+#ifndef MNG_SKIPCHUNK_SAVE
+mng_retcode mng_process_ani_save (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+mng_retcode mng_process_ani_seek (mng_datap pData,
+ mng_objectp pObject);
+#endif
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_process_ani_dhdr (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_prom (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_ipng (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_ijng (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ani_pplt (mng_datap pData,
+ mng_objectp pObject);
+#endif
+mng_retcode mng_process_ani_magn (mng_datap pData,
+ mng_objectp pObject);
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_process_ani_past (mng_datap pData,
+ mng_objectp pObject);
+#endif
+mng_retcode mng_process_ani_disc (mng_datap pData,
+ mng_objectp pObject);
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_event (mng_datap pData,
+ mng_uint8 iEventtype,
+ mng_uint8 iMasktype,
+ mng_int32 iLeft,
+ mng_int32 iRight,
+ mng_int32 iTop,
+ mng_int32 iBottom,
+ mng_uint16 iObjectid,
+ mng_uint8 iIndex,
+ mng_uint32 iSegmentnamesize,
+ mng_pchar zSegmentname);
+#else
+mng_retcode mng_create_event (mng_datap pData,
+ mng_ptr pEntry);
+#endif
+mng_retcode mng_free_event (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_event (mng_datap pData,
+ mng_objectp pObject);
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_mpng_obj (mng_datap pData,
+ mng_uint32 iFramewidth,
+ mng_uint32 iFrameheight,
+ mng_uint16 iNumplays,
+ mng_uint16 iTickspersec,
+ mng_uint32 iFramessize,
+ mng_ptr pFrames);
+#else
+mng_retcode mng_create_mpng_obj (mng_datap pData,
+ mng_ptr pEntry);
+#endif
+mng_retcode mng_free_mpng_obj (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_mpng_obj (mng_datap pData,
+ mng_objectp pObject);
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+mng_retcode mng_create_ang_obj (mng_datap pData,
+ mng_uint32 iNumframes,
+ mng_uint32 iTickspersec,
+ mng_uint32 iNumplays,
+ mng_uint32 iTilewidth,
+ mng_uint32 iTileheight,
+ mng_uint8 iInterlace,
+ mng_uint8 iStillused);
+#else
+mng_retcode mng_create_ang_obj (mng_datap pData,
+ mng_ptr pEntry);
+#endif
+mng_retcode mng_free_ang_obj (mng_datap pData,
+ mng_objectp pObject);
+mng_retcode mng_process_ang_obj (mng_datap pData,
+ mng_objectp pObject);
+#endif
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_object_prc_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_objects.h b/Source/LibMNG/libmng_objects.h
new file mode 100644
index 0000000..053e6b4
--- /dev/null
+++ b/Source/LibMNG/libmng_objects.h
@@ -0,0 +1,635 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_objects.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Internal object structures (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the internal object structures * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - changed inclusion to DISPLAY_PROCS * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added global color-chunks for animations * */
+/* * - added global PLTE,tRNS,bKGD chunks for animation * */
+/* * - added SAVE & SEEK animation objects * */
+/* * 0.5.2 - 05/29/2000 - G.Juyn * */
+/* * - added framenr/layernr/playtime to object header * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added ani-objects for delta-image processing * */
+/* * - added compression/filter/interlace fields to * */
+/* * object-buffer for delta-image processing * */
+/* * * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - changed definition of aTRNSentries * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added definition for PPLT animation-processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/10/2000 - G.Juyn * */
+/* * - fixed DEFI behavior * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for delta-JNG * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added valid-flag to stored objects for read() / display()* */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - added storage for pixel-/alpha-sampledepth for delta's * */
+/* * * */
+/* * 1.0.5 - 09/13/2002 - G.Juyn * */
+/* * - fixed read/write of MAGN chunk * */
+/* * 1.0.5 - 09/15/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added in-memory color-correction of abstract images * */
+/* * 1.0.5 - 10/07/2002 - G.Juyn * */
+/* * - fixed DISC support * */
+/* * * */
+/* * 1.0.6 - 10/07/2003 - G.R-P * */
+/* * - added SKIPCHUNK conditionals * */
+/* * * */
+/* * 1.0.7 - 03/24/2004 - G.R-P * */
+/* * - added more SKIPCHUNK conditionals * */
+/* * * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_OBJCLEANUP * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_objects_h_
+#define _libmng_objects_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* ************************************************************************** */
+
+typedef mng_retcode (*mng_cleanupobject) (mng_datap pData,
+ mng_objectp pHeader);
+
+typedef mng_retcode (*mng_processobject) (mng_datap pData,
+ mng_objectp pHeader);
+
+/* ************************************************************************** */
+
+typedef struct {
+ mng_cleanupobject fCleanup;
+ mng_processobject fProcess;
+ mng_objectp pNext; /* for double-linked list */
+ mng_objectp pPrev;
+ mng_uint32 iFramenr;
+ mng_uint32 iLayernr;
+ mng_uint32 iPlaytime;
+#ifdef MNG_OPTIMIZE_OBJCLEANUP
+ mng_size_t iObjsize;
+#endif
+ } mng_object_header;
+typedef mng_object_header * mng_object_headerp;
+
+/* ************************************************************************** */
+
+typedef struct { /* MNG specification "object-buffer" */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iRefcount; /* reference counter */
+ mng_bool bFrozen; /* frozen flag */
+ mng_bool bConcrete; /* concrete flag */
+ mng_bool bViewable; /* viewable flag */
+ mng_uint32 iWidth; /* image specifics */
+ mng_uint32 iHeight;
+ mng_uint8 iBitdepth;
+ mng_uint8 iColortype;
+ mng_uint8 iCompression;
+ mng_uint8 iFilter;
+ mng_uint8 iInterlace;
+
+ mng_bool bCorrected; /* indicates if an abstract image
+ has already been color-corrected */
+
+ mng_uint8 iAlphabitdepth; /* used only for JNG images */
+ mng_uint8 iJHDRcompression;
+ mng_uint8 iJHDRinterlace;
+
+ mng_uint8 iPixelsampledepth; /* used with delta-images */
+ mng_uint8 iAlphasampledepth;
+
+ mng_bool bHasPLTE; /* PLTE chunk present */
+ mng_bool bHasTRNS; /* tRNS chunk present */
+ mng_bool bHasGAMA; /* gAMA chunk present */
+ mng_bool bHasCHRM; /* cHRM chunk present */
+ mng_bool bHasSRGB; /* sRGB chunk present */
+ mng_bool bHasICCP; /* iCCP chunk present */
+ mng_bool bHasBKGD; /* bKGD chunk present */
+
+ mng_uint32 iPLTEcount; /* PLTE fields */
+ mng_rgbpaltab aPLTEentries;
+
+ mng_uint16 iTRNSgray; /* tRNS fields */
+ mng_uint16 iTRNSred;
+ mng_uint16 iTRNSgreen;
+ mng_uint16 iTRNSblue;
+ mng_uint32 iTRNScount;
+ mng_uint8arr aTRNSentries;
+
+ mng_uint32 iGamma; /* gAMA fields */
+
+ mng_uint32 iWhitepointx; /* cHRM fields */
+ mng_uint32 iWhitepointy;
+ mng_uint32 iPrimaryredx;
+ mng_uint32 iPrimaryredy;
+ mng_uint32 iPrimarygreenx;
+ mng_uint32 iPrimarygreeny;
+ mng_uint32 iPrimarybluex;
+ mng_uint32 iPrimarybluey;
+
+ mng_uint8 iRenderingintent; /* sRGB fields */
+
+ mng_uint32 iProfilesize; /* iCCP fields */
+ mng_ptr pProfile;
+
+ mng_uint8 iBKGDindex; /* bKGD fields */
+ mng_uint16 iBKGDgray;
+ mng_uint16 iBKGDred;
+ mng_uint16 iBKGDgreen;
+ mng_uint16 iBKGDblue;
+
+ mng_uint32 iSamplesize; /* size of a sample */
+ mng_uint32 iRowsize; /* size of a row of samples */
+ mng_uint32 iImgdatasize; /* size of the sample data buffer */
+ mng_uint8p pImgdata; /* actual sample data buffer */
+
+ } mng_imagedata;
+typedef mng_imagedata * mng_imagedatap;
+
+/* ************************************************************************** */
+
+typedef struct { /* MNG specification "object" */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iId; /* object-id */
+ mng_bool bFrozen; /* frozen flag */
+ mng_bool bVisible; /* potential visibility flag */
+ mng_bool bViewable; /* viewable flag */
+ mng_bool bValid; /* marks invalid when only reading */
+ mng_int32 iPosx; /* location fields */
+ mng_int32 iPosy;
+ mng_bool bClipped; /* clipping fields */
+ mng_int32 iClipl;
+ mng_int32 iClipr;
+ mng_int32 iClipt;
+ mng_int32 iClipb;
+#ifndef MNG_SKIPCHUNK_MAGN
+ mng_uint8 iMAGN_MethodX; /* magnification (MAGN) */
+ mng_uint8 iMAGN_MethodY;
+ mng_uint16 iMAGN_MX;
+ mng_uint16 iMAGN_MY;
+ mng_uint16 iMAGN_ML;
+ mng_uint16 iMAGN_MR;
+ mng_uint16 iMAGN_MT;
+ mng_uint16 iMAGN_MB;
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ mng_int32 iPastx; /* target x/y from previous PAST */
+ mng_int32 iPasty;
+#endif
+ mng_imagedatap pImgbuf; /* the image-data buffer */
+ } mng_image;
+typedef mng_image * mng_imagep;
+
+/* ************************************************************************** */
+
+ /* "on-the-fly" image (= object 0) */
+typedef mng_image mng_ani_image; /* let's (ab)use the general "object" */
+typedef mng_ani_image * mng_ani_imagep; /* that's actualy crucial, so don't change it! */
+
+/* ************************************************************************** */
+
+typedef struct { /* global PLTE object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iEntrycount;
+ mng_rgbpaltab aEntries;
+ } mng_ani_plte;
+typedef mng_ani_plte * mng_ani_pltep;
+
+/* ************************************************************************** */
+
+typedef struct { /* global tRNS object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iRawlen;
+ mng_uint8arr aRawdata;
+ } mng_ani_trns;
+typedef mng_ani_trns * mng_ani_trnsp;
+
+/* ************************************************************************** */
+
+typedef struct { /* global gAMA object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_bool bEmpty;
+ mng_uint32 iGamma;
+ } mng_ani_gama;
+typedef mng_ani_gama * mng_ani_gamap;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_cHRM
+typedef struct { /* global cHRM object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_bool bEmpty;
+ mng_uint32 iWhitepointx;
+ mng_uint32 iWhitepointy;
+ mng_uint32 iRedx;
+ mng_uint32 iRedy;
+ mng_uint32 iGreenx;
+ mng_uint32 iGreeny;
+ mng_uint32 iBluex;
+ mng_uint32 iBluey;
+ } mng_ani_chrm;
+typedef mng_ani_chrm * mng_ani_chrmp;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* global sRGB object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_bool bEmpty;
+ mng_uint8 iRenderingintent;
+ } mng_ani_srgb;
+typedef mng_ani_srgb * mng_ani_srgbp;
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_iCCP
+typedef struct { /* global iCCP object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_bool bEmpty;
+ mng_uint32 iProfilesize;
+ mng_ptr pProfile;
+ } mng_ani_iccp;
+typedef mng_ani_iccp * mng_ani_iccpp;
+#endif
+
+/* ************************************************************************** */
+
+typedef struct { /* global bKGD object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ } mng_ani_bkgd;
+typedef mng_ani_bkgd * mng_ani_bkgdp;
+
+/* ************************************************************************** */
+
+typedef struct { /* LOOP object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iLevel;
+ mng_uint32 iRepeatcount;
+ mng_uint8 iTermcond;
+ mng_uint32 iItermin;
+ mng_uint32 iItermax;
+ mng_uint32 iCount;
+ mng_uint32p pSignals;
+
+ mng_uint32 iRunningcount; /* running counter */
+ } mng_ani_loop;
+typedef mng_ani_loop * mng_ani_loopp;
+
+/* ************************************************************************** */
+
+typedef struct { /* ENDL object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iLevel;
+
+ mng_ani_loopp pLOOP; /* matching LOOP */
+ } mng_ani_endl;
+typedef mng_ani_endl * mng_ani_endlp;
+
+/* ************************************************************************** */
+
+typedef struct { /* DEFI object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iId;
+ mng_bool bHasdonotshow;
+ mng_uint8 iDonotshow;
+ mng_bool bHasconcrete;
+ mng_uint8 iConcrete;
+ mng_bool bHasloca;
+ mng_int32 iLocax;
+ mng_int32 iLocay;
+ mng_bool bHasclip;
+ mng_int32 iClipl;
+ mng_int32 iClipr;
+ mng_int32 iClipt;
+ mng_int32 iClipb;
+ } mng_ani_defi;
+typedef mng_ani_defi * mng_ani_defip;
+
+/* ************************************************************************** */
+
+typedef struct { /* BASI object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ mng_bool bHasalpha;
+ mng_uint16 iAlpha;
+ mng_uint8 iViewable;
+ } mng_ani_basi;
+typedef mng_ani_basi * mng_ani_basip;
+
+/* ************************************************************************** */
+
+typedef struct { /* CLON object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iCloneid;
+ mng_uint16 iSourceid;
+ mng_uint8 iClonetype;
+ mng_bool bHasdonotshow;
+ mng_uint8 iDonotshow;
+ mng_uint8 iConcrete;
+ mng_bool bHasloca;
+ mng_uint8 iLocatype;
+ mng_int32 iLocax;
+ mng_int32 iLocay;
+ } mng_ani_clon;
+typedef mng_ani_clon * mng_ani_clonp;
+
+/* ************************************************************************** */
+
+typedef struct { /* BACK object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iRed;
+ mng_uint16 iGreen;
+ mng_uint16 iBlue;
+ mng_uint8 iMandatory;
+ mng_uint16 iImageid;
+ mng_uint8 iTile;
+ } mng_ani_back;
+typedef mng_ani_back * mng_ani_backp;
+
+/* ************************************************************************** */
+
+typedef struct { /* FRAM object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iFramemode;
+ mng_uint8 iChangedelay;
+ mng_uint32 iDelay;
+ mng_uint8 iChangetimeout;
+ mng_uint32 iTimeout;
+ mng_uint8 iChangeclipping;
+ mng_uint8 iCliptype;
+ mng_int32 iClipl;
+ mng_int32 iClipr;
+ mng_int32 iClipt;
+ mng_int32 iClipb;
+ } mng_ani_fram;
+typedef mng_ani_fram * mng_ani_framp;
+
+/* ************************************************************************** */
+
+typedef struct { /* MOVE object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iType;
+ mng_int32 iLocax;
+ mng_int32 iLocay;
+ } mng_ani_move;
+typedef mng_ani_move * mng_ani_movep;
+
+/* ************************************************************************** */
+
+typedef struct { /* CLIP object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iType;
+ mng_int32 iClipl;
+ mng_int32 iClipr;
+ mng_int32 iClipt;
+ mng_int32 iClipb;
+ } mng_ani_clip;
+typedef mng_ani_clip * mng_ani_clipp;
+
+/* ************************************************************************** */
+
+typedef struct { /* SHOW object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iMode;
+ } mng_ani_show;
+typedef mng_ani_show * mng_ani_showp;
+
+/* ************************************************************************** */
+
+typedef struct { /* TERM object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iTermaction;
+ mng_uint8 iIteraction;
+ mng_uint32 iDelay;
+ mng_uint32 iItermax;
+ } mng_ani_term;
+typedef mng_ani_term * mng_ani_termp;
+
+/* ************************************************************************** */
+
+typedef struct { /* SAVE object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ } mng_ani_save;
+typedef mng_ani_save * mng_ani_savep;
+
+/* ************************************************************************** */
+
+typedef struct { /* SEEK object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iSegmentnamesize;
+ mng_pchar zSegmentname;
+ } mng_ani_seek;
+typedef mng_ani_seek * mng_ani_seekp;
+
+/* ************************************************************************** */
+#ifndef MNG_NO_DELTA_PNG
+typedef struct { /* DHDR object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iObjectid;
+ mng_uint8 iImagetype;
+ mng_uint8 iDeltatype;
+ mng_uint32 iBlockwidth;
+ mng_uint32 iBlockheight;
+ mng_uint32 iBlockx;
+ mng_uint32 iBlocky;
+ } mng_ani_dhdr;
+typedef mng_ani_dhdr * mng_ani_dhdrp;
+
+/* ************************************************************************** */
+
+typedef struct { /* PROM object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iBitdepth;
+ mng_uint8 iColortype;
+ mng_uint8 iFilltype;
+ } mng_ani_prom;
+typedef mng_ani_prom * mng_ani_promp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IPNG object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ } mng_ani_ipng;
+typedef mng_ani_ipng * mng_ani_ipngp;
+
+/* ************************************************************************** */
+
+typedef struct { /* IJNG object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ } mng_ani_ijng;
+typedef mng_ani_ijng * mng_ani_ijngp;
+
+/* ************************************************************************** */
+
+typedef struct { /* PPLT object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iType;
+ mng_uint32 iCount;
+ mng_rgbpaltab aIndexentries;
+ mng_uint8arr aAlphaentries;
+ mng_uint8arr aUsedentries;
+ } mng_ani_pplt;
+typedef mng_ani_pplt * mng_ani_ppltp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+typedef struct { /* MAGN object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iFirstid;
+ mng_uint16 iLastid;
+ mng_uint8 iMethodX;
+ mng_uint16 iMX;
+ mng_uint16 iMY;
+ mng_uint16 iML;
+ mng_uint16 iMR;
+ mng_uint16 iMT;
+ mng_uint16 iMB;
+ mng_uint8 iMethodY;
+ } mng_ani_magn;
+typedef mng_ani_magn * mng_ani_magnp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+typedef struct { /* PAST object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint16 iTargetid;
+ mng_uint8 iTargettype;
+ mng_int32 iTargetx;
+ mng_int32 iTargety;
+ mng_uint32 iCount;
+ mng_ptr pSources;
+ } mng_ani_past;
+typedef mng_ani_past * mng_ani_pastp;
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_DISC
+typedef struct { /* DISC object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iCount;
+ mng_uint16p pIds;
+ } mng_ani_disc;
+typedef mng_ani_disc * mng_ani_discp;
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+typedef struct { /* event object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint8 iEventtype;
+ mng_uint8 iMasktype;
+ mng_int32 iLeft;
+ mng_int32 iRight;
+ mng_int32 iTop;
+ mng_int32 iBottom;
+ mng_uint16 iObjectid;
+ mng_uint8 iIndex;
+ mng_uint32 iSegmentnamesize;
+ mng_pchar zSegmentname;
+
+ mng_ani_seekp pSEEK; /* SEEK ani object */
+ mng_int32 iLastx; /* last X/Y coordinates */
+ mng_int32 iLasty;
+ } mng_event;
+typedef mng_event * mng_eventp;
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+typedef struct { /* mPNG object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iFramewidth;
+ mng_uint32 iFrameheight;
+ mng_uint32 iNumplays;
+ mng_uint16 iTickspersec;
+ mng_uint32 iFramessize;
+ mng_ptr pFrames;
+ } mng_mpng_obj;
+typedef mng_mpng_obj * mng_mpng_objp;
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+typedef struct { /* ANG object */
+ mng_object_header sHeader; /* default header (DO NOT REMOVE) */
+ mng_uint32 iNumframes;
+ mng_uint32 iTickspersec;
+ mng_uint32 iNumplays;
+ mng_uint32 iTilewidth;
+ mng_uint32 iTileheight;
+ mng_uint8 iInterlace;
+ mng_uint8 iStillused;
+ mng_uint32 iTilessize;
+ mng_ptr pTiles;
+ } mng_ang_obj;
+typedef mng_ang_obj * mng_ang_objp;
+#endif
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_objects_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_pixels.c b/Source/LibMNG/libmng_pixels.c
new file mode 100644
index 0000000..ce5637b
--- /dev/null
+++ b/Source/LibMNG/libmng_pixels.c
@@ -0,0 +1,24610 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_pixels.c copyright (c) 2000-2005 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Pixel-row management routines (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the pixel-row management routines * */
+/* * * */
+/* * the dual alpha-composing for RGBA/BGRA/etc output-canvas' * */
+/* * is based on the Note on Compositing chapter of the * */
+/* * DOH-3 draft, noted to me by Adam M. Costello * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added callback error-reporting support * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/22/2000 - G.Juyn * */
+/* * - added JNG support * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - fixed minor bugs 16-bit pixel-handling * */
+/* * - added delta-image row-processing routines * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - fixed endian support (hopefully) * */
+/* * 0.5.2 - 06/03/2000 - G.Juyn * */
+/* * - fixed makeup for Linux gcc compile * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - implemented app bkgd restore routines * */
+/* * - implemented RGBA8, ARGB8, BGRA8 & ABGR8 display routines * */
+/* * - added support for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/09/2000 - G.Juyn * */
+/* * - fixed alpha-handling for alpha canvasstyles * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * 0.5.3 - 06/17/2000 - G.Juyn * */
+/* * - changed to support delta-images * */
+/* * - optimized some store_xxx routines * */
+/* * 0.5.3 - 06/20/2000 - G.Juyn * */
+/* * - fixed nasty bug with embedded PNG after delta-image * */
+/* * 0.5.3 - 06/24/2000 - G.Juyn * */
+/* * - fixed problem with 16-bit GA format * */
+/* * 0.5.3 - 06/25/2000 - G.Juyn * */
+/* * - fixed problem with cheap transparency for 4-bit gray * */
+/* * - fixed display_xxxx routines for interlaced images * */
+/* * 0.5.3 - 06/28/2000 - G.Juyn * */
+/* * - fixed compiler-warning for non-initialized iB variable * */
+/* * * */
+/* * 0.9.1 - 07/05/2000 - G.Juyn * */
+/* * - fixed mandatory BACK color to be opaque * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - B110547 - fixed bug in interlace code * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/20/2000 - G.Juyn * */
+/* * - fixed app-supplied background restore * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 09/30/2000 - G.Juyn * */
+/* * - fixed MAGN rounding errors (thanks Matthias!) * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - fixed alpha-blending for RGBA canvasstyle * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - fixed alpha-blending for other alpha-canvasstyles * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added optional support for bKGD for PNG images * */
+/* * - added support for JDAA * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - fixed support for bKGD * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - implemented delayed delta-processing * */
+/* * 0.9.3 - 10/28/2000 - G.Juyn * */
+/* * - fixed tRNS processing for gray-image < 8-bits * */
+/* * * */
+/* * 0.9.4 - 12/16/2000 - G.Juyn * */
+/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - removed "old" MAGN methods 3 & 4 * */
+/* * - added "new" MAGN methods 3, 4 & 5 * */
+/* * - removed test filter-methods 1 & 65 * */
+/* * * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * 1.0.1 - 04/25/2001 - G.Juyn * */
+/* * - moved mng_clear_cms to libmng_cms * */
+/* * * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.4 - 11/04/2001 - G.Juyn * */
+/* * - fixed possible compile-problem in cleanup_rowproc * */
+/* * 1.0.4 - 06/22/2002 - G.Juyn * */
+/* * - B558212 - off by one error * */
+/* * - MNG subimage alpha composite wrong for rgba8 images * */
+/* * * */
+/* * 1.0.5 - 08/07/2002 - G.Juyn * */
+/* * - added test-option for PNG filter method 193 (=no filter) * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/16/2002 - G.Juyn * */
+/* * - completed MAGN support (16-bit functions) * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - optimized restore-background for bKGD cases * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - finished support for BACK image & tiling * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added compose over/under routines for PAST processing * */
+/* * - added flip & tile routines for PAST processing * */
+/* * * */
+/* * 1.0.6 - 03/09/2003 - G.Juyn * */
+/* * - hiding 12-bit JPEG stuff * */
+/* * 1.0.6 - 05/11/2003 - Glenn RP * */
+/* * - added size-optimization COMPOSE routine usage * */
+/* * 1.0.6 - 05/11/2003 - G. Juyn * */
+/* * - added conditionals around canvas update routines * */
+/* * 1.0.6 - 05/25/2003 - Glenn RP * */
+/* * - added size-optimization DIV255B8 routine usage * */
+/* * 1.0.6 - 06/09/2003 - G. R-P * */
+/* * - added conditionals around 8-bit magn routines * */
+/* * 1.0.6 - 07/07/2003 - G. R-P * */
+/* * - removed conditionals around 8-bit magn routines * */
+/* * - added MNG_NO_16BIT_SUPPORT and MNG_NO_DELTA_PNG * */
+/* * conditionals * */
+/* * - reversed many loops to use decrementing counter * */
+/* * - combined init functions * */
+/* * - converted some switches to array references * */
+/* * 1.0.6 - 07/29/2003 - G.Juyn * */
+/* * - fixed duplicate for-loop * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added SKIPCHUNK conditionals around PAST chunk support * */
+/* * - fixed "FOOTPRINT_COMPOSEIV" typo (now "FOOTPRINT_DIV") * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added more conditionals around "promote" functions * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 12/06/2003 - R.A * */
+/* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 03/08/2004 - G.R-P * */
+/* * - added more conditionals around 16-bit-supporting code * */
+/* * 1.0.7 - 03/09/2004 - G.Juyn * */
+/* * - fixed bug in promote_g8_g8 with 16bit support off * */
+/* * 1.0.7 - 03/09/2004 - G.R-P * */
+/* * - more optimizations with 16bit support off * */
+/* * 1.0.7 - 03/10/2004 - G.Juyn * */
+/* * - fixed some warnings for 16bit optimizations * */
+/* * 1.0.7 - 03/21/2004 - G.Juyn * */
+/* * - fixed some 64-bit platform compiler warnings * */
+/* * * */
+/* * 1.0.8 - 06/20/2004 - G.Juyn * */
+/* * - some speed optimizations (thanks to John Stiles) * */
+/* * 1.0.8 - 08/01/2004 - G.Juyn * */
+/* * - added support for 3+byte pixelsize for JPEG's * */
+/* * * */
+/* * 1.0.9 - 10/10/2004 - G.R-P. * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added LITTLEENDIAN/BIGENDIAN fixtures (thanks J.Stiles) * */
+/* * - fixed MNG_NO_1_2_4BIT_SUPPORT for TBBN1G04.PNG * */
+/* * 1.0.9 - 12/31/2004 - G.R-P. * */
+/* * - fixed warnings about C++ style (//) comments * */
+/* * * */
+/* * 1.0.10 - 07/06/2005 - G.R-P. * */
+/* * - added MORE MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.10 - 10/06/2005 - G.R-P. * */
+/* * - alloc more memory for MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.10 - 12/07/2005 - G.R-P. * */
+/* * - optimized footprint of 16bit support * */
+/* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
+/* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_objects.h"
+#include "libmng_object_prc.h"
+#include "libmng_memory.h"
+#include "libmng_cms.h"
+#include "libmng_filter.h"
+#include "libmng_pixels.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_DISPLAY_PROCS
+
+/* TODO: magnification & canvas-positioning/-clipping */
+
+/* TODO: major optimization of pixel-loops by using assembler (?) */
+
+/* ************************************************************************** */
+/* * * */
+/* * Interlace tables * */
+/* * * */
+/* ************************************************************************** */
+
+MNG_LOCAL mng_uint32 const interlace_row [7] = { 0, 0, 4, 0, 2, 0, 1 };
+MNG_LOCAL mng_uint32 const interlace_rowskip [7] = { 8, 8, 8, 4, 4, 2, 2 };
+MNG_LOCAL mng_uint32 const interlace_col [7] = { 0, 4, 0, 2, 0, 1, 0 };
+MNG_LOCAL mng_uint32 const interlace_colskip [7] = { 8, 8, 4, 4, 2, 2, 1 };
+MNG_LOCAL mng_uint32 const interlace_roundoff [7] = { 7, 7, 3, 3, 1, 1, 0 };
+MNG_LOCAL mng_uint32 const interlace_divider [7] = { 3, 3, 2, 2, 1, 1, 0 };
+
+/* ************************************************************************** */
+/* * * */
+/* * Alpha composing macros * */
+/* * the code below is slightly modified from the libpng package * */
+/* * the original was last optimized by Greg Roelofs & Mark Adler * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_COMPOSE8(RET,FG,ALPHA,BG) { \
+ mng_uint16 iH = (mng_uint16)((mng_uint16)(FG) * (mng_uint16)(ALPHA) \
+ + (mng_uint16)(BG)*(mng_uint16)(255 - \
+ (mng_uint16)(ALPHA)) + (mng_uint16)128); \
+ (RET) = (mng_uint8)((iH + (iH >> 8)) >> 8); }
+
+#define MNG_COMPOSE16(RET,FG,ALPHA,BG) { \
+ mng_uint32 iH = (mng_uint32)((mng_uint32)(FG) * (mng_uint32)(ALPHA) \
+ + (mng_uint32)(BG)*(mng_uint32)(65535L - \
+ (mng_uint32)(ALPHA)) + (mng_uint32)32768L); \
+ (RET) = (mng_uint16)((iH + (iH >> 16)) >> 16); }
+
+/* ************************************************************************** */
+/* * * */
+/* * Alpha blending macros * */
+/* * this code is based on Adam Costello's "Note on Compositing" from the * */
+/* * mng-list which gives the following formula: * */
+/* * * */
+/* * top pixel = (Rt, Gt, Bt, At) * */
+/* * bottom pixel = (Rb, Gb, Bb, Ab) * */
+/* * composite pixel = (Rc, Gc, Bc, Ac) * */
+/* * * */
+/* * all values in the range 0..1 * */
+/* * * */
+/* * Ac = 1 - (1 - At)(1 - Ab) * */
+/* * s = At / Ac * */
+/* * t = (1 - At) Ab / Ac * */
+/* * Rc = s Rt + t Rb * */
+/* * Gc = s Gt + t Gb * */
+/* * Bc = s Bt + t Bb * */
+/* * * */
+/* * (I just hope I coded it correctly in integer arithmetic...) * */
+/* * * */
+/* ************************************************************************** */
+
+#define MNG_BLEND8(RT, GT, BT, AT, RB, GB, BB, AB, RC, GC, BC, AC) { \
+ mng_uint32 S, T; \
+ (AC) = (mng_uint8)((mng_uint32)255 - \
+ ((((mng_uint32)255 - (mng_uint32)(AT)) * \
+ ((mng_uint32)255 - (mng_uint32)(AB)) ) >> 8)); \
+ S = (mng_uint32)(((mng_uint32)(AT) << 8) / \
+ (mng_uint32)(AC)); \
+ T = (mng_uint32)(((mng_uint32)255 - (mng_uint32)(AT)) * \
+ (mng_uint32)(AB) / (mng_uint32)(AC)); \
+ (RC) = (mng_uint8)((S * (mng_uint32)(RT) + \
+ T * (mng_uint32)(RB) + (mng_uint32)127) >> 8); \
+ (GC) = (mng_uint8)((S * (mng_uint32)(GT) + \
+ T * (mng_uint32)(GB) + (mng_uint32)127) >> 8); \
+ (BC) = (mng_uint8)((S * (mng_uint32)(BT) + \
+ T * (mng_uint32)(BB) + (mng_uint32)127) >> 8); }
+
+#define MNG_BLEND16(RT, GT, BT, AT, RB, GB, BB, AB, RC, GC, BC, AC) { \
+ mng_uint32 S, T; \
+ (AC) = (mng_uint16)((mng_uint32)65535 - \
+ ((((mng_uint32)65535 - (mng_uint32)(AT)) * \
+ ((mng_uint32)65535 - (mng_uint32)(AB)) ) >> 16)); \
+ S = (mng_uint32)(((mng_uint32)(AT) << 16) / \
+ (mng_uint32)(AC)); \
+ T = (mng_uint32)(((mng_uint32)65535 - (mng_uint32)(AT)) * \
+ (mng_uint32)(AB) / (mng_uint32)(AC)); \
+ (RC) = (mng_uint16)((S * (mng_uint32)(RT) + \
+ T * (mng_uint32)(RB) + (mng_uint32)32767) >> 16); \
+ (GC) = (mng_uint16)((S * (mng_uint32)(GT) + \
+ T * (mng_uint32)(GB) + (mng_uint32)32767) >> 16); \
+ (BC) = (mng_uint16)((S * (mng_uint32)(BT) + \
+ T * (mng_uint32)(BB) + (mng_uint32)32767) >> 16); }
+
+/* ************************************************************************** */
+
+/* note a good optimizing compiler will optimize this */
+#define DIV255B8(x) (mng_uint8)(((x) + 127) / 255)
+#define DIV255B16(x) (mng_uint16)(((x) + 32767) / 65535)
+
+/* ************************************************************************** */
+/* * * */
+/* * Progressive display check - checks to see if progressive display is * */
+/* * in order & indicates so * */
+/* * * */
+/* * The routine is called after a call to one of the display_xxx routines * */
+/* * if appropriate * */
+/* * * */
+/* * The refresh is warrented in the read_chunk routine (mng_read.c) * */
+/* * and only during read&display processing, since there's not much point * */
+/* * doing it from memory! * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_display_progressive_check (mng_datap pData)
+{
+ if ((pData->bDoProgressive) && /* need progressive display? */
+ ((pData->eImagetype != mng_it_mng) || (pData->iDataheight > 300)) &&
+ (pData->iDestb - pData->iDestt > 50) && (!pData->pCurraniobj))
+ {
+ mng_int32 iC = pData->iRow + pData->iDestt - pData->iSourcet;
+
+ if (iC % 20 == 0) /* every 20th line */
+ pData->bNeedrefresh = MNG_TRUE;
+
+ }
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Display routines - convert rowdata (which is already color-corrected) * */
+/* * to the output canvas, respecting the opacity information * */
+/* * * */
+/* ************************************************************************** */
+
+MNG_LOCAL void check_update_region (mng_datap pData)
+{ /* determine actual canvas row */
+ mng_int32 iRow = pData->iRow + pData->iDestt - pData->iSourcet;
+ /* check for change in update-region */
+ if ((pData->iDestl < (mng_int32)pData->iUpdateleft) || (pData->iUpdateright == 0))
+ pData->iUpdateleft = pData->iDestl;
+
+ if (pData->iDestr > (mng_int32)pData->iUpdateright)
+ pData->iUpdateright = pData->iDestr;
+
+ if ((iRow < (mng_int32)pData->iUpdatetop) || (pData->iUpdatebottom == 0))
+ pData->iUpdatetop = iRow;
+
+ if (iRow+1 > (mng_int32)pData->iUpdatebottom)
+ pData->iUpdatebottom = iRow+1;
+
+ return;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGb16 >> 8);
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ }
+ else
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *pDataline, iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iA8, *(pScanline+2));
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGg16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *(pDataline+2*iBps);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4*iBps;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ }
+ else
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+i) = (mng_uint8)(iFGg16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ }
+ else
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iA8, *(pScanline+i));
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ }
+ else
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iA8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *pDataline, iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iA8, *(pScanline+2));
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGB8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGBA8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgba8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *(pScanline+3) = *(pDataline+6);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+3);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+3));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *(pScanline+3) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGb16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2));
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgba8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *(pDataline+2*iBps);
+ *(pScanline+3) = *(pDataline+3*iBps);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+3));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *(pScanline+3) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+i) = (mng_uint8)(iFGg16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i));
+ }
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgba8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+3);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2));
+#endif
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGBA8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGBA8_PM
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgba8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[4];
+ pScanline[3] = 255;
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[4-i-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[4]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[4];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[2-i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[4] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[2-i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgba8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[4];
+ pScanline[3] = 255;
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[4-i-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[4]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[4];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[2-i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[4] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[2-i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgba8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ *(mng_uint32*)pScanline = (*(mng_uint32*)pDataline) | 0x000000FF;
+#else
+ pScanline[0] = pDataline[0];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = 255;
+#endif
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[2-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[2-i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[0] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGBA8_PM */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_ARGB8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_argb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START);
+#endif
+
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+4);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *(pDataline+2);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pScanline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+4);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+1));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+3));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8)(iFGr16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iFGb16 >> 8);
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+1));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+3));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCa16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCb16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *(pDataline+2);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCr8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCb8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_argb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+3*iBps);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+iBps);
+ *(pScanline+3) = *(pDataline+2*iBps);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pScanline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *(pDataline+4);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+i+1));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ /* and return the composed values */
+ /* alpha remains fully opaque !!! */
+ *(pScanline+i+1) = (mng_uint8)(iFGg16 >> 8);
+ }
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+1));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+3));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCa16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCb16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *(pDataline+2);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+i), iFGa8, *(pScanline+i+1));
+ }
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCr8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCb8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_argb8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_START);
+#endif
+
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *(pDataline+2);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *pDataline;
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *(pDataline+2);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+i), iFGa8, *(pScanline+i+1));
+ }
+#else
+ MNG_COMPOSE8 (*(pScanline+1), *pDataline, iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+1), iFGa8, *(pScanline+2));
+ MNG_COMPOSE8 (*(pScanline+3), *(pDataline+2), iFGa8, *(pScanline+3));
+#endif
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+1), *(pScanline+2), *(pScanline+3), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCr8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCb8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_ARGB8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_ARGB8_PM
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_argb8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[4];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[4-i-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[4]);
+#endif
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[2]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[4];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[3-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[4] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[3-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_argb8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[4];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[4-i-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[4]);
+#endif
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[2]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[4];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[3-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[4] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[3-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_argb8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[2]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[0];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[2];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[3-i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[3-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[0] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[2] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ARGB8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_ARGB8_PM */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB8_A8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgb8_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination rows */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination rows starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *pAlphaline = *(pDataline+6);
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *pAlphaline = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pAlphaline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *pAlphaline = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGb16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCb16 >> 8);
+ *pAlphaline = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pAlphaline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2));
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgb8_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination rows */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination rows starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *(pDataline+2*iBps);
+ *pAlphaline = *(pDataline+3*iBps);
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pAlphaline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+4);
+ *pAlphaline = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+i) = (mng_uint8)(iFGg16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*pScanline );
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*(pScanline+2));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCb16 >> 8);
+ *pAlphaline = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pAlphaline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i));
+ }
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgb8_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination rows */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination rows starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *pAlphaline = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pAlphaline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *pDataline;
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *(pDataline+2);
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+i), iFGa8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *pDataline, iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+2), iFGa8, *(pScanline+2));
+#endif
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCr8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCb8;
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB8_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGB8_A8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 8;
+ else
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 4;
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha value */
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+2));
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*pScanline );
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGb16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGr16 >> 8);
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ }
+ else
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iA8, *(pScanline+2));
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGg16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+2*iBps);
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *pDataline;
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha value */
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ }
+ else
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+2-i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+2-i) = (mng_uint8)(iFGg16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ }
+ else
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iA8, *(pScanline+i));
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 3) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 4;
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ }
+ else
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iA8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iA8, *(pScanline+2));
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGR8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGRX8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgrx8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 8;
+ else
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 4;
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha value */
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+2));
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*pScanline );
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGb16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGr16 >> 8);
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ else
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iA8, *(pScanline+2));
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgrx8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGg16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+2*iBps);
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha value */
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ else
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+2-i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+2-i) = (mng_uint8)(iFGg16 >> 8);
+ }
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ else
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iA8, *(pScanline+i));
+ }
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgrx8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + (pData->iSourcel / pData->iColinc) * 4;
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ else
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iA8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iA8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iA8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iA8, *(pScanline+2));
+#endif
+ *(pScanline+3) = 0xFF; /* filler byte */
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGRX8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGRA8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgra8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+6);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+3));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+2));
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*pScanline );
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iFGb16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGr16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+2));
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*pScanline );
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iFGa8, *(pScanline+2));
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+2), *(pScanline+1), *pScanline, iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCb8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCr8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgra8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+2*iBps);
+ *(pScanline+1) = *(pDataline+iBps);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3*iBps);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+3));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+4);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+2-i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ /* and return the composed values */
+ *(pScanline+2-i) = (mng_uint8)(iFGg16 >> 8);
+ /* alpha remains fully opaque !!! */
+ }
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+2));
+ iBGg16 = (mng_uint16)(*(pScanline+1));
+ iBGb16 = (mng_uint16)(*pScanline );
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCr16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iFGa8, *(pScanline+i));
+ }
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+2), *(pScanline+1), *pScanline, iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCb8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCr8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgra8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3);
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+2);
+ *(pScanline+1) = *(pDataline+1);
+ *(pScanline+2) = *pDataline;
+ *(pScanline+3) = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i), *(pDataline+2-i), iFGa8, *(pScanline+i));
+ }
+#else
+ MNG_COMPOSE8 (*pScanline, *(pDataline+2), iFGa8, *pScanline );
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+1), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *pDataline, iFGa8, *(pScanline+2));
+#endif
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+2), *(pScanline+1), *pScanline, iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCb8;
+ *(pScanline+1) = iCg8;
+ *(pScanline+2) = iCr8;
+ *(pScanline+3) = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGRA8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGRA8_PM
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgra8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[4];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ {
+ pScanline[0] = DIV255B8(s * pDataline[4]);
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[0]);
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ {
+ pScanline[0] = DIV255B8(s * pDataline[2]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0]);
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = pDataline[4];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[4] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[2] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgra8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[4];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[4-i-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[4]);
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[0]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[2-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[2]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = pDataline[4];
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[4] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[2] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgra8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[2-i]);
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[2]);
+ pScanline[1] = DIV255B8(s * pDataline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0]);
+#endif
+ pScanline[3] = (mng_uint8)s;
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = pDataline[2];
+ pScanline[1] = pDataline[1];
+ pScanline[2] = pDataline[0];
+ pScanline[3] = 255;
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i]);
+ }
+ }
+#else
+ pScanline[0] = DIV255B8(s * pDataline[2] + t * pScanline[0]);
+ pScanline[1] = DIV255B8(s * pDataline[1] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[0] + t * pScanline[2]);
+#endif
+ pScanline[3] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[3])));
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA8PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGRA8_PM */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_ABGR8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_abgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *(pDataline+4);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *pDataline;
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *pDataline;
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pScanline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *(pDataline+4);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *pDataline;
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+3));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+1));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ /* alpha itself remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8)(iFGb16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iFGg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iFGr16 >> 8);
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+3));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+1));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCa16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCr16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *pDataline;
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+2), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+1), iFGa8, *(pScanline+2));
+ MNG_COMPOSE8 (*(pScanline+3), *pDataline, iFGa8, *(pScanline+3));
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+3), *(pScanline+2), *(pScanline+1), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCb8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCr8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_abgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGg16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *pScanline = *(pDataline+3*iBps);
+ *(pScanline+1) = *(pDataline+2*iBps);
+ *(pScanline+2) = *(pDataline+iBps);
+ *(pScanline+3) = *pDataline;
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pScanline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *pScanline = *(pDataline+6);
+ *(pScanline+1) = *(pDataline+4);
+ *(pScanline+2) = *(pDataline+2);
+ *(pScanline+3) = *pDataline;
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ iFGg16 = mng_get_uint16 (pDataline+i+i);
+ /* scale background up */
+ iBGg16 = (mng_uint16)(*(pScanline+3-i));
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ /* now compose */
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ /* and return the composed values */
+ /* alpha itself remains fully opaque !!! */
+ *(pScanline+3-i) = (mng_uint8)(iFGg16 >> 8);
+ }
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)(*(pScanline+3));
+ iBGg16 = (mng_uint16)(*(pScanline+2));
+ iBGb16 = (mng_uint16)(*(pScanline+1));
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *pScanline = (mng_uint8)(iCa16 >> 8);
+ *(pScanline+1) = (mng_uint8)(iCb16 >> 8);
+ *(pScanline+2) = (mng_uint8)(iCg16 >> 8);
+ *(pScanline+3) = (mng_uint8)(iCr16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *pDataline;
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+2-i), iFGa8, *(pScanline+i+1));
+ }
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+3), *(pScanline+2), *(pScanline+1), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCb8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCr8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_abgr8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *pDataline;
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *pScanline;
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pScanline = *(pDataline+3);
+ *(pScanline+1) = *(pDataline+2);
+ *(pScanline+2) = *(pDataline+1);
+ *(pScanline+3) = *pDataline;
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do simple alpha composing */
+ /* alpha itself remains fully opaque !!! */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pScanline+i+1), *(pDataline+2-i), iFGa8, *(pScanline+i+1));
+ }
+#else
+ MNG_COMPOSE8 (*(pScanline+1), *(pDataline+2), iFGa8, *(pScanline+1));
+ MNG_COMPOSE8 (*(pScanline+2), *(pDataline+1), iFGa8, *(pScanline+2));
+ MNG_COMPOSE8 (*(pScanline+3), *pDataline, iFGa8, *(pScanline+3));
+#endif
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ *(pScanline+3), *(pScanline+2), *(pScanline+1), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pScanline = iCa8;
+ *(pScanline+1) = iCb8;
+ *(pScanline+2) = iCg8;
+ *(pScanline+3) = iCr8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_ABGR8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_ABGR8_PM
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_abgr8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[4];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[4-i-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[4]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0]);
+#endif
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[0]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[4];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[i+1]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[4] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i+1]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_abgr8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ if ((s = pDataline[6]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[4];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[4-i-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[4]);
+ pScanline[2] = DIV255B8(s * pDataline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0]);
+#endif
+ }
+ }
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[0]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ if ((s = pDataline[6]) != 0) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if (s == 255)
+ { /* plain copy it */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[4];
+ pScanline[2] = pDataline[2];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[4-i-i] + t *
+ pScanline[i+1]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[4] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[2] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i+1]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_abgr8_pm (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint32 s, t;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl << 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values and premultiply */
+ if ((s = pDataline[3]) == 0)
+ *(mng_uint32*) pScanline = 0; /* set all components = 0 */
+ else
+ {
+ if (s == 255)
+ {
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ {
+ pScanline[0] = (mng_uint8)s;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2]);
+ pScanline[2] = DIV255B8(s * pDataline[1]);
+ pScanline[3] = DIV255B8(s * pDataline[0]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ if ((s = pDataline[3]) != 0) /* any opacity at all ? */
+ { /* fully opaque ? */
+ if (s == 255)
+ { /* then simply copy the values */
+ pScanline[0] = 255;
+ pScanline[1] = pDataline[2];
+ pScanline[2] = pDataline[1];
+ pScanline[3] = pDataline[0];
+ }
+ else
+ { /* now blend (premultiplied) */
+ t = 255 - s;
+ pScanline[0] = (mng_uint8)(255 - DIV255B8(t * (255 - pScanline[0])));
+#ifdef MNG_OPTIMIZE_FOOTPRINT_DIV
+ {
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ pScanline[i+1] = DIV255B8(s * pDataline[2-i] + t *
+ pScanline[i+1]);
+ }
+ }
+#else
+ pScanline[1] = DIV255B8(s * pDataline[2] + t * pScanline[1]);
+ pScanline[2] = DIV255B8(s * pDataline[1] + t * pScanline[2]);
+ pScanline[3] = DIV255B8(s * pDataline[0] + t * pScanline[3]);
+#endif
+ }
+ }
+
+ pScanline += (pData->iColinc << 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_ABGR8_PM, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_ABGR8_PM */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR565
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgr565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+2)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+4)) >>3) | ( (*(pDataline+2)&0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgr565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) |
+ ( (*(pDataline+iBps)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+2*iBps)) >>3) |
+ ( (*(pDataline+iBps)&0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgr565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGR565 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB565
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgb565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( ( *(pDataline+4)) & 0xF8) | (*(pDataline+2) >> 5 ) );
+ *pScanline = (mng_uint8)( ( ( *(pDataline )) >> 3 ) | ((*(pDataline+2) & 0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) & 0xF8) | (*(pDataline+1) >> 5 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+4)) & 0xF8) | (*(pDataline+2)>>5) );
+ *pScanline = (mng_uint8)( ( (*(pDataline )) >> 3 ) | ((*(pDataline+2)&0xFC) << 3) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGr16 = (mng_uint8)( *(pScanline+1) & 0xF8 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0) >> 3 ) );
+ iBGb16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)((iFGb16 >> 8) &0xF8) | ( (mng_uint8)(iFGg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) (iFGr16 >>11) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) & 0xF8) | ( *(pDataline+1) >> 5 ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline )) >> 3 ) | ( (*(pDataline+1) & 0xFC) << 3 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( *(pScanline+1) & 0xF8);
+ iGreen = (mng_uint8)( ( *(pScanline+1) << 5 ) | ( ( (*pScanline)&0xE0)>>3 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( iRed & 0xF8) | ( iGreen >> 5 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgb565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( ( *(pDataline+2*iBps)) & 0xF8) |
+ (*(pDataline+iBps) >> 5 ) );
+ *pScanline = (mng_uint8)( ( ( *(pDataline )) >> 3 ) |
+ ((*(pDataline+iBps) & 0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+4)) & 0xF8) | (*(pDataline+2)>>5) );
+ *pScanline = (mng_uint8)( ( (*(pDataline )) >> 3 ) | ((*(pDataline+2)&0xFC) << 3) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGr16 = (mng_uint8)( *(pScanline+1) & 0xF8 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0) >> 3 ) );
+ iBGb16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)((iFGb16 >> 8) &0xF8) | ( (mng_uint8)(iFGg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) (iFGr16 >>11) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) & 0xF8) | ( *(pDataline+1) >> 5 ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline )) >> 3 ) | ( (*(pDataline+1) & 0xFC) << 3 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( *(pScanline+1) & 0xF8);
+ iGreen = (mng_uint8)( ( *(pScanline+1) << 5 ) | ( ( (*pScanline)&0xE0)>>3 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( iRed & 0xF8) | ( iGreen >> 5 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgb565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) & 0xF8) | (*(pDataline+1) >> 5 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xFC) << 3) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) & 0xF8) | ( *(pDataline+1) >> 5 ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline )) >> 3 ) | ( (*(pDataline+1) & 0xFC) << 3 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( *(pScanline+1) & 0xF8);
+ iGreen = (mng_uint8)( ( *(pScanline+1) << 5 ) | ( ( (*pScanline)&0xE0)>>3 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( iRed & 0xF8) | ( iGreen >> 5 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGB565 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGRA565
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgra565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+2)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+4)) >>3) | ( (*(pDataline+2)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+6);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+2));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *(pScanline+2) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ else
+ { /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCr16 >> 8) & 0xF8 ) | ( (mng_uint8)(iCg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8) ( ( (iCb16 >> 11) ) | (((mng_uint8)(iCg16 >> 8) & 0xFC) << 3) );
+ *(pScanline+2) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgra565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) |
+ ( (*(pDataline+iBps)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+2*iBps)) >>3) |
+ ( (*(pDataline+iBps)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3*iBps);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+2));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *(pScanline+2) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ else
+ { /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCr16 >> 8) & 0xF8 ) | ( (mng_uint8)(iCg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8) ( ( (iCb16 >> 11) ) | (((mng_uint8)(iCg16 >> 8) & 0xFC) << 3) );
+ *(pScanline+2) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgra565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGRA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGRA565 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGBA565
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgba565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+4))&0xF8 ) | ( (*(pDataline+2)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline)) >>3) | ( (*(pDataline+2)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+6);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+2));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline+4))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *(pScanline+2) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGb16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGb16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGr16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGb16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCb16 >> 8) & 0xF8 ) | ( (mng_uint8)(iCg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8) ( ( (iCr16 >> 11) ) | (((mng_uint8)(iCg16 >> 8) & 0xFC) << 3) );
+ *(pScanline+2) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iBlue = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iRed = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iBlue & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iRed >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCr8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCb8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgba565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint16 iFGa16, iBGa16, iCa16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2*iBps))&0xF8 ) |
+ ( (*(pDataline+iBps)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline)) >>3) |
+ ( (*(pDataline+iBps)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3*iBps);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*(pScanline+2));
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* plain copy it */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline+4))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *(pScanline+2) = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+ iBGr16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGb16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iFGa16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGb16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGr16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ }
+ else
+ { /* scale background up */
+ iBGr16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGb16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCb16 >> 8) & 0xF8 ) | ( (mng_uint8)(iCg16 >> 8) >> 5 ) );
+ *pScanline = (mng_uint8) ( ( (iCr16 >> 11) ) | (((mng_uint8)(iCg16 >> 8) & 0xFC) << 3) );
+ *(pScanline+2) = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iBlue = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iRed = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iBlue & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iRed >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCr8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCb8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgba565 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol << 2) + (pData->iDestl * 3);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2))&0xF8 ) | ( (*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline) >>3 ) | ( (*(pDataline+1)&0xFC ) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+
+ pScanline += (pData->iColinc * 3);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iFGa8 = *(pDataline+3); /* get alpha values */
+ iBGa8 = *(pScanline+2);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline+2)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *(pScanline+2) = *(pDataline+3);
+ }
+ else
+ {
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iBlue = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | ( ((*pScanline) & 0xE0)>>3 ) );
+ iRed = (mng_uint8) ( (*pScanline << 3) );
+
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE8 (iRed, *pDataline, iFGa8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iFGa8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iFGa8, iBlue );
+ /* alpha remains fully opaque !!! */
+ *(pScanline+1) = (mng_uint8) ( ( iBlue & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iRed >> 3 ) | ( (iGreen & 0xFC) << 3) );
+ }
+ else
+ { /* now blend */
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iFGa8,
+ iRed , iGreen , iBlue , iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+
+
+ *pScanline = (mng_uint8) ( ( iCr8 >> 3 ) | ( (iCg8 & 0xFC) << 3) );
+ *(pScanline+1) = (mng_uint8) ( ( iCb8 & 0xF8 ) | (iCg8>>5) );
+ *(pScanline+2) = (mng_uint8) iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc *3);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGBA565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGBA565 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR565_A8
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgr565_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16, iBGa16;
+ mng_uint16 iCr16, iCg16, iCb16, iCa16;
+ mng_uint8 iA8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row
+starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ((*(pDataline+2)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+4)) >>3) | ((*(pDataline+2)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(*(pDataline+6));
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ((*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ((*(pDataline+1)&0xFC ) << 3) );
+ *pAlphaline = (mng_uint8)(*(pDataline+3));
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ else /* Not fully opaque */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pAlphaline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if ((iA16 == 0xFFFF) || (iBGa16 == 0)) /* fully opaque or background fully transparent ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *pAlphaline = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ {
+ /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(iA16>>8);
+ }
+ else /* background is not fully opaque */
+ { /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iA16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCr16 >> 8)&0xF8 ) | ( (mng_uint8)(iCg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iCb16>>11) ) | (((mng_uint8)(iCg16>>8)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+ iBGa8 = *pAlphaline;
+
+ if (iA8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iA8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ {
+ /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | (((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ((iGreen & 0xFC) << 3) );
+ *pAlphaline = iA8;
+ }
+ else /* background not fully opaque */
+ {
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iA8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ((iCg8 & 0xFC) << 3) );
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgr565_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16, iBGa16;
+ mng_uint16 iCr16, iCg16, iCb16, iCa16;
+ mng_uint8 iA8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+ mng_uint8 iBps;
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row
+starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) |
+ ((*(pDataline+iBps)>>5) ) );
+ *pScanline = (mng_uint8)( ( (*(pDataline+2*iBps)) >>3) |
+ ((*(pDataline+iBps)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(*(pDataline+6));
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else /* Not fully opaque */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+ iBGa16 = (mng_uint16)(*pAlphaline);
+ iBGa16 = (mng_uint16)(iBGa16 << 8) | iBGa16;
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if ((iA16 == 0xFFFF) || (iBGa16 == 0)) /* fully opaque or background fully transparent ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( (*(pDataline))&0xF8 ) | (mng_uint8)( (*(pDataline+2)>>5 ) );
+ *pScanline = (mng_uint8)( (*(pDataline+4)) >>3) | (mng_uint8)( (*(pDataline+2)&0xFC) << 3);
+ *pAlphaline = *(pDataline+6);
+ }
+ else
+ {
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ {
+ /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+ /* scale background up */
+
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iFGr16 >> 8)&0xF8 ) | ( (mng_uint8)(iFGg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iFGb16>>11) ) | (((mng_uint8)(iFGg16>>8)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(iA16>>8);
+ }
+ else /* background is not fully opaque */
+ { /* scale background up */
+ iBGb16 = (mng_uint16)( (*(pScanline+1)) & 0xF8 );
+ iBGg16 = (mng_uint16)( (*(pScanline+1) << 5) | (((*(pScanline )) & 0xE0) >>3 ) );
+ iBGr16 = (mng_uint16)( (*(pScanline )) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* let's blend */
+ MNG_BLEND16 (mng_get_uint16 (pDataline ),
+ mng_get_uint16 (pDataline+2),
+ mng_get_uint16 (pDataline+4), iA16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( (iCr16 >> 8)&0xF8 ) | ( (mng_uint8)(iCg16>>8) >> 5) );
+ *pScanline = (mng_uint8) ( ( (iCb16>>11) ) | (((mng_uint8)(iCg16>>8)&0xFC) << 3) );
+ *pAlphaline = (mng_uint8)(iCa16 >> 8);
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+ iBGa8 = *pAlphaline;
+
+ if (iA8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iA8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ {
+ /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | (((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ((iGreen & 0xFC) << 3) );
+ *pAlphaline = iA8;
+ }
+ else /* background not fully opaque */
+ {
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iA8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ((iCg8 & 0xFC) << 3) );
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgr565_a8 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pAlphaline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8, iBGa8, iCa8;
+ mng_uint8 iCr8, iCg8, iCb8;
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ pAlphaline = (mng_uint8p)pData->fGetalphaline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row
+starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pAlphaline = pAlphaline + pData->iCol + pData->iDestl;
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline))&0xF8 ) | ((*(pDataline+1)>>5 ) ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >>3 ) | ((*(pDataline+1)&0xFC ) << 3) );
+ *pAlphaline = (mng_uint8)(*(pDataline+3));
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ else /* Not fully opaque */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+ iBGa8 = *pAlphaline;
+
+ if (iA8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iA8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ( (*(pDataline)) &0xF8 ) | (*(pDataline+1) >>5 ) );
+ *pScanline = (mng_uint8)( ( ((*(pDataline+2))>>3) ) | ((*(pDataline+1)&0xFC) << 3) );
+ *pAlphaline = *(pDataline+3);
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ {
+ /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8) ( *(pScanline+1) & 0xF8 );
+ iGreen = (mng_uint8) ( (*(pScanline+1) << 5) | (((*pScanline) & 0xE0)>>3 ) );
+ iBlue = (mng_uint8) ( (*pScanline << 3) );
+
+ MNG_COMPOSE8 (iRed, *pDataline, iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8) ( ( iRed & 0xF8 ) | (iGreen>>5) );
+ *pScanline = (mng_uint8) ( ( iBlue >> 3 ) | ((iGreen & 0xFC) << 3) );
+ *pAlphaline = iA8;
+ }
+ else /* background not fully opaque */
+ {
+ MNG_BLEND8 (*pDataline, *(pDataline+1), *(pDataline+2), iA8,
+ *pScanline, *(pScanline+1), *(pScanline+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8) ( ( iCr8 & 0xF8 ) | (iCg8>>5) );
+ *pScanline = (mng_uint8) ( ( iCb8 >> 3 ) | ((iCg8 & 0xFC) << 3) );
+ *pAlphaline = iCa8;
+ }
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pAlphaline += pData->iColinc;
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR565_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGR565_A8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB555
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_rgb555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+4) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+4) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGr16 = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBGb16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)(((iFGb16 >> 8) & 0xF8) >> 1 ) | ( (mng_uint8)(iFGg16 >> 8) >> 6 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) ((iFGr16 >>11) >> 3 ) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_rgb555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2*iBps) & 0xF8) >> 1 ) | (*(pDataline+iBps) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+iBps) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+4) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGr16 = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBGb16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)(((iFGb16 >> 8) & 0xF8) >> 1 ) | ( (mng_uint8)(iFGg16 >> 8) >> 6 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) ((iFGr16 >>11) >> 3 ) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_rgb555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline+2) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline ) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+2), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+0), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_RGB555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_RGB555 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR555
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+mng_retcode mng_display_bgr555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ if (pData->bIsRGBA16) /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 3);
+ else
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+4) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+4) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGb16 = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBGr16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)(((iFGr16 >> 8) & 0xF8) >> 1 ) | ( (mng_uint8)(iFGg16 >> 8) >> 6 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) ((iFGb16 >>11) >> 3 ) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+0), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#else /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+mng_retcode mng_display_bgr555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint16 iA16;
+ mng_uint16 iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGr16, iBGg16, iBGb16;
+ mng_uint8 iA8;
+ mng_uint8 iBps;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_START);
+#endif
+
+ iBps=(mng_uint8)(pData->bIsRGBA16 ? 2:1);
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ /* adjust source row starting-point */
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << (iBps+1));
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+iBps) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2*iBps) >> 3 ) | ((*(pDataline+iBps) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4*iBps;
+ }
+ }
+ else
+ {
+ if (pData->bIsRGBA16) /* 16-bit input row ? */
+ {
+
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA16 = mng_get_uint16 (pDataline+6);
+
+ if (iA16) /* any opacity at all ? */
+ {
+ if (iA16 == 0xFFFF) /* fully opaque ? */
+ { /* scale down by dropping the LSB */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+2) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+4) >> 3 ) | ((*(pDataline+2) & 0xF8) << 2 ) );
+ }
+ else
+ { /* get the proper values */
+ iFGr16 = mng_get_uint16 (pDataline );
+ iFGg16 = mng_get_uint16 (pDataline+2);
+ iFGb16 = mng_get_uint16 (pDataline+4);
+
+ /* scale background up */
+ iBGb16 = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iBGg16 = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBGr16 = (mng_uint8)( *(pScanline ) << 3 );
+
+ iBGr16 = (mng_uint16)((mng_uint32)iBGr16 << 8) | iBGr16;
+ iBGg16 = (mng_uint16)((mng_uint32)iBGg16 << 8) | iBGg16;
+ iBGb16 = (mng_uint16)((mng_uint32)iBGb16 << 8) | iBGb16;
+ /* now compose */
+ MNG_COMPOSE16(iFGr16, iFGr16, iA16, iBGr16);
+ MNG_COMPOSE16(iFGg16, iFGg16, iA16, iBGg16);
+ MNG_COMPOSE16(iFGb16, iFGb16, iA16, iBGb16);
+ /* and return the composed values */
+ *(pScanline+1) = (mng_uint8)( (mng_uint8)(((iFGr16 >> 8) & 0xF8) >> 1 ) | ( (mng_uint8)(iFGg16 >> 8) >> 6 ) );
+ *pScanline = (mng_uint8)( (mng_uint8) ((iFGb16 >>11) >> 3 ) | ( ( (mng_uint8)(iFGg16 >> 8) & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 8;
+ }
+ }
+ else
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+0), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_OPTIMIZE_FOOTPRINT_COMPOSE */
+#else /* MNG_NO_16BIT_SUPPORT */
+mng_retcode mng_display_bgr555 (mng_datap pData)
+{
+ mng_uint8p pScanline;
+ mng_uint8p pDataline;
+ mng_int32 iX;
+ mng_uint8 iA8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_START);
+#endif
+ /* viewable row ? */
+ if ((pData->iRow >= pData->iSourcet) && (pData->iRow < pData->iSourceb))
+ { /* address destination row */
+ pScanline = (mng_uint8p)pData->fGetcanvasline (((mng_handle)pData),
+ pData->iRow + pData->iDestt -
+ pData->iSourcet);
+ /* adjust destination row starting-point */
+ pScanline = pScanline + (pData->iCol * 2) + (pData->iDestl * 2);
+ pDataline = pData->pRGBArow; /* address source row */
+
+ pDataline = pDataline + ((pData->iSourcel / pData->iColinc) << 2);
+
+ if (pData->bIsOpaque) /* forget about transparency ? */
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ { /* copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ else
+ {
+ {
+ for (iX = pData->iSourcel + pData->iCol; iX < pData->iSourcer;
+ iX += pData->iColinc)
+ {
+ iA8 = *(pDataline+3); /* get alpha value */
+
+ if (iA8) /* any opacity at all ? */
+ {
+ if (iA8 == 0xFF) /* fully opaque ? */
+ { /* then simply copy the values */
+ *(pScanline+1) = (mng_uint8)( ((*(pDataline ) & 0xF8) >> 1 ) | (*(pDataline+1) >> 6 ) );
+ *pScanline = (mng_uint8)( ( *(pDataline+2) >> 3 ) | ((*(pDataline+1) & 0xF8) << 2 ) );
+ }
+ else
+ { /* do alpha composing */
+ mng_uint8 iRed, iGreen, iBlue;
+
+ iRed = (mng_uint8)( (*(pScanline+1) & 0xF8) << 1 );
+ iGreen = (mng_uint8)( (*(pScanline+1) << 6 ) | ( ((*pScanline) & 0xE0) >> 2 ) );
+ iBlue = (mng_uint8)( *(pScanline ) << 3 );
+
+ MNG_COMPOSE8 (iRed, *(pDataline+0), iA8, iRed );
+ MNG_COMPOSE8 (iGreen, *(pDataline+1), iA8, iGreen );
+ MNG_COMPOSE8 (iBlue, *(pDataline+2), iA8, iBlue );
+
+ *(pScanline+1) = (mng_uint8)( ( (iRed & 0xF8) >> 1 ) | ( iGreen >> 6 ) );
+ *pScanline = (mng_uint8)( (iBlue >> 3 ) | ( (iGreen & 0xF8) << 2 ) );
+ }
+ }
+
+ pScanline += (pData->iColinc * 2);
+ pDataline += 4;
+ }
+ }
+ }
+ }
+
+ check_update_region (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_BGR555, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_SKIPCANVAS_BGR555 */
+
+
+#ifndef MNG_SKIPCHUNK_BACK
+/* ************************************************************************** */
+/* * * */
+/* * Background restore routines - restore the background with info from * */
+/* * the BACK and/or bKGD chunk or the app's background canvas * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_restore_bkgd_backimage (mng_datap pData)
+{
+ /* save some stuff */
+ mng_uint8p pRGBArow = pData->pRGBArow;
+ mng_int32 iRow = pData->iRow;
+ mng_int32 iRowsamples = pData->iRowsamples;
+
+ mng_retcode iRetcode; /* work variables */
+ mng_uint8p pTemp;
+ mng_uint8p pWork = pRGBArow;
+ mng_uint32 iX;
+ mng_int32 iZ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BACKIMAGE, MNG_LC_START);
+#endif
+ /* determine row to retrieve */
+ pData->iRow = pData->iDestt + iRow + pData->iBackimgoffsy;
+
+ while (pData->iRow >= (mng_int32)pData->iBackimgheight)
+ pData->iRow -= (mng_int32)pData->iBackimgheight;
+ /* set width to that of background image */
+ pData->iRowsamples = pData->iBackimgwidth;
+ /* retrieve into alternate buffer ! */
+ pData->pRGBArow = pData->pPrevrow;
+ /* get it then */
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+
+ if (iRetcode) /* on error; bail out */
+ return iRetcode;
+ /* we got the full row; but now need to
+ paste it into the proper location */
+ iX = pData->iDestl - pData->iBackimgoffsx;
+
+ while (iX >= pData->iBackimgwidth)
+ iX -= pData->iBackimgwidth;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pData->bIsRGBA16) /* 16-bit buffer ? */
+ {
+ pTemp = pData->pPrevrow + (iX << 3);
+
+ for (iZ = (pData->iDestr - pData->iDestl); iZ > 0; iZ--)
+ {
+ MNG_COPY (pWork, pTemp, 8);
+
+ pWork += 8;
+ pTemp += 8;
+ iX++;
+ /* reached end of bkgd-image line ? */
+ if (iX >= pData->iBackimgwidth)
+ {
+ iX = 0;
+ pTemp = pData->pPrevrow;
+ }
+ }
+ }
+ else
+#endif
+ {
+ pTemp = pData->pPrevrow + (iX << 2);
+
+ for (iZ = (pData->iDestr - pData->iDestl); iZ > 0; iZ--)
+ {
+ MNG_COPY (pWork, pTemp, 4);
+
+ pWork += 4;
+ pTemp += 4;
+ iX++;
+ /* reached end of bkgd-image line ? */
+ if (iX >= pData->iBackimgwidth)
+ {
+ iX = 0;
+ pTemp = pData->pPrevrow;
+ }
+ }
+ }
+
+ pData->pRGBArow = pRGBArow; /* restore original values */
+ pData->iRow = iRow;
+ pData->iRowsamples = iRowsamples;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BACKIMAGE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_restore_bkgd_backcolor (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint32p pWork32 = (mng_uint32p)pData->pRGBArow;
+ mng_uint32 iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BACKCOLOR, MNG_LC_START);
+#endif
+
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ /* fast way for big endian */
+ iWrite = (((mng_uint8)(pData->iBACKred >> 8)) << 24) |
+ (((mng_uint8)(pData->iBACKgreen >> 8)) << 16) |
+ (((mng_uint8)(pData->iBACKblue >> 8)) << 8) |
+ ( 0xFF );
+#elif defined(MNG_LITTLEENDIAN_SUPPORTED)
+ /* fast way for little endian */
+ iWrite = ( 0xFF << 24) |
+ (((mng_uint8)(pData->iBACKblue >> 8)) << 16) |
+ (((mng_uint8)(pData->iBACKgreen >> 8)) << 8) |
+ (((mng_uint8)(pData->iBACKred >> 8)) );
+#else
+ /* generic way, works on all platforms */
+ /* put the data in memory in the correct order */
+ {
+ mng_uint8 aBytes[4];
+ aBytes[0] = (mng_uint8)(pData->iBACKred >> 8);
+ aBytes[1] = (mng_uint8)(pData->iBACKgreen >> 8);
+ aBytes[2] = (mng_uint8)(pData->iBACKblue >> 8);
+ aBytes[3] = 0xFF;
+ /* load that data into a register */
+ iWrite = *(mng_uint32*) aBytes;
+ }
+#endif
+ /* ok; drop the background-color in there */
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ *pWork32++ = iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BACKCOLOR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_bKGD
+mng_retcode mng_restore_bkgd_bkgd (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pWork = pData->pRGBArow;
+ mng_imagep pImage = (mng_imagep)pData->pCurrentobj;
+ mng_imagedatap pBuf = pImage->pImgbuf;
+ mng_uint8 iRed = 0;
+ mng_uint8 iGreen = 0;
+ mng_uint8 iBlue = 0;
+ mng_uint32p pWork32 = (mng_uint32p)pWork;
+ mng_uint32 iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BKGD, MNG_LC_START);
+#endif
+
+ switch (pBuf->iColortype)
+ {
+ case 0 : ; /* gray types */
+ case 4 : {
+ mng_uint8 iGray;
+
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth > 8)
+ iGray = (mng_uint8)(pBuf->iBKGDgray >> 8);
+ else
+#endif
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ /* LBR scaling */
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1};
+ iGray = (mng_uint8)(multiplier[pBuf->iBitdepth] * pBuf->iBKGDgray);
+#else
+ iGray = (mng_uint8)pBuf->iBKGDgray;
+#endif
+ }
+
+ iRed = iGray;
+ iGreen = iGray;
+ iBlue = iGray;
+
+ break;
+ }
+
+ case 3 : { /* indexed type */
+ iRed = pBuf->aPLTEentries [pBuf->iBKGDindex].iRed;
+ iGreen = pBuf->aPLTEentries [pBuf->iBKGDindex].iGreen;
+ iBlue = pBuf->aPLTEentries [pBuf->iBKGDindex].iBlue;
+
+ break;
+ }
+
+ case 2 : ; /* rgb types */
+ case 6 : {
+#ifndef MNG_NO_16BIT_SUPPORT
+ if (pBuf->iBitdepth > 8)
+ {
+ iRed = (mng_uint8)(pBuf->iBKGDred >> 8);
+ iGreen = (mng_uint8)(pBuf->iBKGDgreen >> 8);
+ iBlue = (mng_uint8)(pBuf->iBKGDblue >> 8);
+ }
+ else
+#endif
+ {
+ iRed = (mng_uint8)(pBuf->iBKGDred );
+ iGreen = (mng_uint8)(pBuf->iBKGDgreen);
+ iBlue = (mng_uint8)(pBuf->iBKGDblue );
+ }
+
+ break;
+ }
+ }
+
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ /* fast way for big endian */
+ iWrite = (iRed << 24) |
+ (iGreen << 16) |
+ (iBlue << 8);
+#elif defined(MNG_LITTLEENDIAN_SUPPORTED)
+ /* fast way for little endian */
+ iWrite = (iBlue << 16) |
+ (iGreen << 8) |
+ (iRed );
+#else
+ /* generic way, works on all platforms */
+ /* put the data in memory in the correct order */
+ {
+ mng_uint8 aBytes[4];
+ aBytes[0] = (mng_uint8)(iRed);
+ aBytes[1] = (mng_uint8)(iGreen);
+ aBytes[2] = (mng_uint8)(iBlue);
+ aBytes[3] = 0x00;
+ /* load that data into a register */
+ iWrite = *(mng_uint32*) aBytes;
+ }
+#endif
+ /* ok; drop it in there */
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ *pWork32++ = iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_restore_bkgd_bgcolor (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint32p pWork32 = (mng_uint32p)pData->pRGBArow;
+ mng_uint32 iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGCOLOR, MNG_LC_START);
+#endif
+
+#ifdef MNG_BIGENDIAN_SUPPORTED
+ /* fast way for big endian */
+ iWrite = (((mng_uint8)(pData->iBGred >> 8)) << 24) |
+ (((mng_uint8)(pData->iBGgreen >> 8)) << 16) |
+ (((mng_uint8)(pData->iBGblue >> 8)) << 8);
+#elif defined(MNG_LITTLEENDIAN_SUPPORTED)
+ /* fast way for little endian */
+ iWrite = (((mng_uint8)(pData->iBGblue >> 8)) << 16) |
+ (((mng_uint8)(pData->iBGgreen >> 8)) << 8) |
+ (((mng_uint8)(pData->iBGred >> 8)) );
+#else
+ /* generic way, works on all platforms */
+ /* put the data in memory in the correct order */
+ {
+ mng_uint8 aBytes[4];
+ aBytes[0] = (mng_uint8)(pData->iBGred >> 8);
+ aBytes[1] = (mng_uint8)(pData->iBGgreen >> 8);
+ aBytes[2] = (mng_uint8)(pData->iBGblue >> 8);
+ aBytes[3] = 0x00;
+ /* load that data into a register */
+ iWrite = *(mng_uint32*) aBytes;
+ }
+#endif
+ /* ok; drop the background-color in there */
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ *pWork32++ = iWrite;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGCOLOR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB8
+mng_retcode mng_restore_bkgd_rgb8 (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pBkgd;
+ mng_uint8p pWork = pData->pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_RGB8, MNG_LC_START);
+#endif
+
+ if (pData->fGetbkgdline) /* can we access the background ? */
+ { /* point to the right pixel then */
+ pBkgd = (mng_uint8p)pData->fGetbkgdline ((mng_handle)pData,
+ pData->iRow + pData->iDestt) +
+ (3 * pData->iDestl);
+
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ {
+ *pWork = *pBkgd; /* ok; copy the pixel */
+ *(pWork+1) = *(pBkgd+1);
+ *(pWork+2) = *(pBkgd+2);
+ *(pWork+3) = 0x00; /* transparant for alpha-canvasses */
+
+ pWork += 4;
+ pBkgd += 3;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCANVAS_RGB8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR8
+mng_retcode mng_restore_bkgd_bgr8 (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pBkgd;
+ mng_uint8p pWork = pData->pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGR8, MNG_LC_START);
+#endif
+
+ if (pData->fGetbkgdline) /* can we access the background ? */
+ { /* point to the right pixel then */
+ pBkgd = (mng_uint8p)pData->fGetbkgdline ((mng_handle)pData,
+ pData->iRow + pData->iDestt) +
+ (3 * pData->iDestl);
+
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ {
+ *pWork = *(pBkgd+2); /* ok; copy the pixel */
+ *(pWork+1) = *(pBkgd+1);
+ *(pWork+2) = *pBkgd;
+ *(pWork+3) = 0x00; /* transparant for alpha-canvasses */
+
+ pWork += 4;
+ pBkgd += 3;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGR8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCANVAS_BGR8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGRX8
+mng_retcode mng_restore_bkgd_bgrx8 (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pBkgd;
+ mng_uint8p pWork = pData->pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGRX8, MNG_LC_START);
+#endif
+
+ if (pData->fGetbkgdline) /* can we access the background ? */
+ { /* point to the right pixel then */
+ pBkgd = (mng_uint8p)pData->fGetbkgdline ((mng_handle)pData,
+ pData->iRow + pData->iDestt) +
+ (3 * pData->iDestl);
+
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ {
+ *pWork = *(pBkgd+2); /* ok; copy the pixel */
+ *(pWork+1) = *(pBkgd+1);
+ *(pWork+2) = *pBkgd;
+ *(pWork+3) = 0x00; /* transparant for alpha-canvasses */
+
+ pWork += 4;
+ pBkgd += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGRX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCANVAS_BGRX8 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_BGR565
+mng_retcode mng_restore_bkgd_bgr565 (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pBkgd;
+ mng_uint8p pWork = pData->pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGR565, MNG_LC_START);
+#endif
+
+ if (pData->fGetbkgdline) /* can we access the background ? */
+ { /* point to the right pixel then */
+ pBkgd = (mng_uint8p)pData->fGetbkgdline ((mng_handle)pData,
+ pData->iRow + pData->iDestt) +
+ (3 * pData->iDestl);
+
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ {
+ *pWork = (mng_uint8)( *(pBkgd+1) & 0xF8); /* ok; copy the pixel */
+ *(pWork+1) = (mng_uint8)( (*(pBkgd+1) << 5 ) | ( ((*pBkgd)&0xE0)>>3 ) );
+ *(pWork+2) = (mng_uint8)( *(pBkgd) << 3 );
+ *(pWork+3) = 0x00; /* transparant for alpha-canvasses */
+
+ pWork += 4;
+ pBkgd += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_BGR565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCANVAS_BGR565 */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB565
+mng_retcode mng_restore_bkgd_rgb565 (mng_datap pData)
+{
+ mng_int32 iX;
+ mng_uint8p pBkgd;
+ mng_uint8p pWork = pData->pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_RGB565, MNG_LC_START);
+#endif
+
+ if (pData->fGetbkgdline) /* can we access the background ? */
+ { /* point to the right pixel then */
+ pBkgd = (mng_uint8p)pData->fGetbkgdline ((mng_handle)pData,
+ pData->iRow + pData->iDestt) +
+ (3 * pData->iDestl);
+
+ for (iX = (pData->iSourcer - pData->iSourcel); iX > 0; iX--)
+ {
+ *pWork = (mng_uint8)( *(pBkgd)&0xF8); /* ok; copy the pixel */
+ *(pWork+1) = (mng_uint8)( (*(pBkgd+1) << 5) | ( ((*pBkgd)&0xE0)>>3 ) );
+ *(pWork+2) = (mng_uint8)( *(pBkgd+1) << 3);
+ *(pWork+3) = 0x00; /* transparant for alpha-canvasses */
+
+ pWork += 4;
+ pBkgd += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RESTORE_RGB565, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SKIPCANVAS_RBB565 */
+
+
+/* ************************************************************************** */
+/* * * */
+/* * Row retrieval routines - retrieve processed & uncompressed row-data * */
+/* * from the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+/* TODO: a serious optimization is to retrieve only those pixels that will
+ actually be displayed; this would require changes in
+ the "display_image" routine (in mng_display.c) &
+ all the "retrieve_xxx" routines below &
+ the "display_xxx" routines above !!!!!
+ NOTE that "correct_xxx" routines would not require modification */
+
+mng_retcode mng_retrieve_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_G8, MNG_LC_START);
+#endif
+
+ pRGBArow = pData->pRGBArow; /* temporary work pointers */
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+ if (pBuf->bHasTRNS) /* tRNS in buffer ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iG = *pWorkrow; /* get the gray-value */
+ /* is it transparent ? */
+ if ((mng_uint16)iG == pBuf->iTRNSgray)
+ {
+ *pRGBArow = 0x00; /* nuttin to display */
+ *(pRGBArow+1) = 0x00;
+ *(pRGBArow+2) = 0x00;
+ *(pRGBArow+3) = 0x00;
+ }
+ else
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1};
+ iG = (mng_uint8)(iG * multiplier[pBuf->iBitdepth]);
+#endif
+
+ *pRGBArow = iG; /* put in intermediate row */
+ *(pRGBArow+1) = iG;
+ *(pRGBArow+2) = iG;
+ *(pRGBArow+3) = 0xFF;
+ }
+
+ pWorkrow++; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1}; /* LBR scaling */
+ iG = (mng_uint8)(multiplier[pBuf->iBitdepth] * *pWorkrow);
+#else
+ iG = *pWorkrow; /* get the gray-value */
+#endif
+
+ *pRGBArow = iG; /* put in intermediate row */
+ *(pRGBArow+1) = iG;
+ *(pRGBArow+2) = iG;
+ *(pRGBArow+3) = 0xFF;
+
+ pWorkrow++; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_retrieve_g16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_G16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pRGBArow = pData->pRGBArow;
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+ if (pBuf->bHasTRNS) /* tRNS in buffer ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iG = mng_get_uint16 (pWorkrow); /* get the gray-value */
+ /* is it transparent ? */
+ if (iG == pBuf->iTRNSgray)
+ { /* nuttin to display */
+ mng_put_uint16 (pRGBArow, 0x0000);
+ mng_put_uint16 (pRGBArow+2, 0x0000);
+ mng_put_uint16 (pRGBArow+4, 0x0000);
+ mng_put_uint16 (pRGBArow+6, 0x0000);
+ }
+ else
+ { /* put in intermediate row */
+ mng_put_uint16 (pRGBArow, iG);
+ mng_put_uint16 (pRGBArow+2, iG);
+ mng_put_uint16 (pRGBArow+4, iG);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+ }
+
+ pWorkrow += 2; /* next pixel */
+ pRGBArow += 8;
+ }
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iG = mng_get_uint16 (pWorkrow); /* get the gray-value */
+
+ mng_put_uint16 (pRGBArow, iG); /* and put in intermediate row */
+ mng_put_uint16 (pRGBArow+2, iG);
+ mng_put_uint16 (pRGBArow+4, iG);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+
+ pWorkrow += 2; /* next pixel */
+ pRGBArow += 8;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_retrieve_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iR, iG, iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGB8, MNG_LC_START);
+#endif
+
+ pRGBArow = pData->pRGBArow; /* temporary work pointers */
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+ if (pBuf->bHasTRNS) /* tRNS in buffer ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iR = *pWorkrow; /* get the rgb-values */
+ iG = *(pWorkrow+1);
+ iB = *(pWorkrow+2);
+ /* is it transparent ? */
+ if (((mng_uint16)iR == pBuf->iTRNSred ) &&
+ ((mng_uint16)iG == pBuf->iTRNSgreen) &&
+ ((mng_uint16)iB == pBuf->iTRNSblue ) )
+ {
+ *pRGBArow = 0x00; /* nothing to display */
+ *(pRGBArow+1) = 0x00;
+ *(pRGBArow+2) = 0x00;
+ *(pRGBArow+3) = 0x00;
+ }
+ else
+ {
+ *pRGBArow = iR; /* put in intermediate row */
+ *(pRGBArow+1) = iG;
+ *(pRGBArow+2) = iB;
+ *(pRGBArow+3) = 0xFF;
+ }
+
+ pWorkrow += 3; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRGBArow = *pWorkrow; /* just copy the pixel */
+ *(pRGBArow+1) = *(pWorkrow+1);
+ *(pRGBArow+2) = *(pWorkrow+2);
+ *(pRGBArow+3) = 0xFF;
+
+ pWorkrow += 3; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_retrieve_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iR, iG, iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGB16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pRGBArow = pData->pRGBArow;
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+ if (pBuf->bHasTRNS) /* tRNS in buffer ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iR = mng_get_uint16 (pWorkrow); /* get the rgb-values */
+ iG = mng_get_uint16 (pWorkrow+2);
+ iB = mng_get_uint16 (pWorkrow+4);
+ /* is it transparent ? */
+ if ((iR == pBuf->iTRNSred ) &&
+ (iG == pBuf->iTRNSgreen) &&
+ (iB == pBuf->iTRNSblue ) )
+ { /* nothing to display */
+ mng_put_uint16 (pRGBArow, 0x0000);
+ mng_put_uint16 (pRGBArow+2, 0x0000);
+ mng_put_uint16 (pRGBArow+4, 0x0000);
+ mng_put_uint16 (pRGBArow+6, 0x0000);
+ }
+ else
+ { /* put in intermediate row */
+ mng_put_uint16 (pRGBArow, iR);
+ mng_put_uint16 (pRGBArow+2, iG);
+ mng_put_uint16 (pRGBArow+4, iB);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+ }
+
+ pWorkrow += 6; /* next pixel */
+ pRGBArow += 8;
+ }
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* just copy the pixel */
+ mng_put_uint16 (pRGBArow, mng_get_uint16 (pWorkrow ));
+ mng_put_uint16 (pRGBArow+2, mng_get_uint16 (pWorkrow+2));
+ mng_put_uint16 (pRGBArow+4, mng_get_uint16 (pWorkrow+4));
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+
+ pWorkrow += 6; /* next pixel */
+ pRGBArow += 8;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_retrieve_idx8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_IDX8, MNG_LC_START);
+#endif
+
+ pRGBArow = pData->pRGBArow; /* temporary work pointers */
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+ if (pBuf->bHasTRNS) /* tRNS in buffer ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iQ = *pWorkrow; /* get the index */
+ /* is it valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ /* transparency for this index ? */
+ if ((mng_uint32)iQ < pBuf->iTRNScount)
+ *(pRGBArow+3) = pBuf->aTRNSentries [iQ];
+ else
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pWorkrow++; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iQ = *pWorkrow; /* get the index */
+ /* is it valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pWorkrow++; /* next pixel */
+ pRGBArow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_IDX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_retrieve_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_GA8, MNG_LC_START);
+#endif
+
+ pRGBArow = pData->pRGBArow; /* temporary work pointers */
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iG = *pWorkrow; /* get the gray-value */
+ *pRGBArow = iG; /* put in intermediate row */
+ *(pRGBArow+1) = iG;
+ *(pRGBArow+2) = iG;
+ *(pRGBArow+3) = *(pWorkrow+1);
+
+ pWorkrow += 2; /* next pixel */
+ pRGBArow += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_retrieve_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iG;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_GA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pRGBArow = pData->pRGBArow;
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iG = mng_get_uint16 (pWorkrow); /* get the gray-value */
+
+ mng_put_uint16 (pRGBArow, iG); /* and put in intermediate row */
+ mng_put_uint16 (pRGBArow+2, iG);
+ mng_put_uint16 (pRGBArow+4, iG);
+ mng_put_uint16 (pRGBArow+6, mng_get_uint16 (pWorkrow+2));
+
+ pWorkrow += 4; /* next pixel */
+ pRGBArow += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_retrieve_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGBA8, MNG_LC_START);
+#endif
+
+ pRGBArow = pData->pRGBArow; /* temporary work pointers */
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+ /* can't be easier than this ! */
+ MNG_COPY (pRGBArow, pWorkrow, pBuf->iRowsize);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_retrieve_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pRetrieveobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGBA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pRGBArow = pData->pRGBArow;
+ pWorkrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize);
+ /* can't be easier than this ! */
+ MNG_COPY (pRGBArow, pWorkrow, pBuf->iRowsize);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RETRIEVE_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row storage routines - store processed & uncompressed row-data * */
+/* * into the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_g1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it white ? */
+ *pOutrow = 0x01; /* white */
+ else
+ *pOutrow = 0x00; /* black */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_g2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+ iQ = (mng_uint8)((iB & iM) >> iS); /* get the gray level */
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_g4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+
+ iQ = (mng_uint8)((iB & iM) >> iS); /* get the gray level */
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_g16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* copy into object buffer */
+ mng_put_uint16 (pOutrow, mng_get_uint16 (pWorkrow));
+
+ pOutrow += (pData->iColinc << 1); /* next pixel */
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGB8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy the RGB bytes */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+
+ pWorkrow += 3; /* next pixel */
+ pOutrow += (pData->iColinc * 3);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGB16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ MNG_COPY (pOutrow, pWorkrow, 6); /* copy the RGB bytes */
+
+ pWorkrow += 6; /* next pixel */
+ pOutrow += (pData->iColinc * 6);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_idx1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* store the index */
+ *pOutrow = 0x01;
+ else
+ *pOutrow = 0x00;
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_idx2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* store the index */
+ *pOutrow = (mng_uint8)((iB & iM) >> iS);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_idx4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* store the index */
+ *pOutrow = (mng_uint8)((iB & iM) >> iS);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_idx8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_IDX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_GA8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy the GA bytes */
+ *(pOutrow+1) = *(pWorkrow+1);
+
+ pWorkrow += 2; /* next pixel */
+ pOutrow += (pData->iColinc << 1);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_GA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ MNG_COPY (pOutrow, pWorkrow, 4); /* copy the GA bytes */
+
+ pWorkrow += 4; /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGBA8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy the RGBA bytes */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = *(pWorkrow+3);
+
+ pWorkrow += 4; /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGBA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ MNG_COPY (pOutrow, pWorkrow, 8); /* copy the RGBA bytes */
+
+ pWorkrow += 8; /* next pixel */
+ pOutrow += (pData->iColinc << 3);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row storage routines (JPEG) - store processed & uncompressed row-data * */
+/* * into the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pJPEGrow; /* temporary work pointers */
+ pOutrow = pBuf->pImgdata + (pData->iJPEGrow * pBuf->iRowsize);
+ /* easy as pie ... */
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8, MNG_LC_END);
+#endif
+
+ return mng_next_jpeg_row (pData); /* we've got one more row of gray-samples */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+#if RGB_PIXELSIZE != 3
+ mng_int32 iX;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pJPEGrow; /* temporary work pointers */
+ pOutrow = pBuf->pImgdata + (pData->iJPEGrow * pBuf->iRowsize);
+
+#if RGB_PIXELSIZE == 3
+ /* easy as pie ... */
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples * 3);
+#else
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy pixel into object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+
+ pOutrow += 3; /* next pixel */
+ pWorkrow += RGB_PIXELSIZE;
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8, MNG_LC_END);
+#endif
+
+ return mng_next_jpeg_row (pData); /* we've got one more row of rgb-samples */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_GA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pJPEGrow; /* temporary work pointers */
+ pOutrow = pBuf->pImgdata + (pData->iJPEGrow * pBuf->iRowsize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy into object buffer */
+
+ pOutrow += 2; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_GA8, MNG_LC_END);
+#endif
+
+ return mng_next_jpeg_row (pData); /* we've got one more row of gray-samples */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGBA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pJPEGrow; /* temporary work pointers */
+ pOutrow = pBuf->pImgdata + (pData->iJPEGrow * pBuf->iRowsize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* copy pixel into object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow += RGB_PIXELSIZE;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGBA8, MNG_LC_END);
+#endif
+
+ return mng_next_jpeg_row (pData); /* we've got one more row of rgb-samples */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_g8_alpha (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_ALPHA, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pJPEGrow2;
+ pOutrow = pBuf->pImgdata + (pData->iJPEGalpharow * pBuf->iRowsize) + 1;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += 2; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_ALPHA, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgb8_alpha (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_ALPHA, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pJPEGrow2;
+ pOutrow = pBuf->pImgdata + (pData->iJPEGalpharow * pBuf->iRowsize) + 3;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_ALPHA, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_g8_a1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it opaque ? */
+ *pOutrow = 0xFF; /* opaque */
+ else
+ *pOutrow = 0x00; /* transparent */
+
+ pOutrow += 2; /* next pixel */
+ iM >>= 1;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A1, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_g8_a2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ {
+ const mng_uint8 alpha_level[4] = { 0x00, 0x55, 0xAA, 0xFF};
+ *pOutrow = alpha_level[((iB & iM) >> iS)] ;
+ }
+#else
+ switch ((iB & iM) >> iS) /* determine the alpha level */
+ {
+ case 0x03 : { *pOutrow = 0xFF; break; }
+ case 0x02 : { *pOutrow = 0xAA; break; }
+ case 0x01 : { *pOutrow = 0x55; break; }
+ default : { *pOutrow = 0x00; }
+ }
+#endif
+
+ pOutrow += 2; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A2, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_g8_a4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the alpha level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ iQ = (mng_uint8)(iQ + (iQ << 4)); /* expand to 8-bit by replication */
+
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += 2; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A4, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_g8_a8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += 2; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A8, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_g8_a16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* only high-order byte! */
+
+ pOutrow += 2; /* next pixel */
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G8_A16, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb8_a1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it opaque ? */
+ *pOutrow = 0xFF; /* opaque */
+ else
+ *pOutrow = 0x00; /* transparent */
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 1;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A1, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgb8_a2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ {
+ const mng_uint8 alpha_level[4] = { 0x00, 0x55, 0xAA, 0xFF};
+ *pOutrow = alpha_level[((iB & iM) >> iS)] ;
+ }
+#else
+ switch ((iB & iM) >> iS) /* determine the alpha level */
+ {
+ case 0x03 : { *pOutrow = 0xFF; break; }
+ case 0x02 : { *pOutrow = 0xAA; break; }
+ case 0x01 : { *pOutrow = 0x55; break; }
+ default : { *pOutrow = 0x00; }
+ }
+#endif
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A2, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgb8_a4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the alpha level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ iQ = (mng_uint8)(iQ + (iQ << 4)); /* expand to 8-bit by replication */
+
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A4, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_store_jpeg_rgb8_a8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in buffer */
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A8, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb8_a16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* only high-order byte */
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_RGB8_A16, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_JPEG12
+mng_retcode mng_store_jpeg_g12_a1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 2;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* opaque ? */
+ mng_put_uint16 (pOutrow, 0xFFFF);/* opaque */
+ else
+ mng_put_uint16 (pOutrow, 0x0000);/* transparent */
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 1;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A1, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif /* MNG_SUPPORT_JPEG12 */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_JPEG12
+mng_retcode mng_store_jpeg_g12_a2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 2;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ {
+ const mng_uint16 gray_level[4] = { 0x0000, 0x5555, 0xAAAA, 0xFFFF};
+ mng_put_uint16 (pOutrow, gray_level[((iB & iM) >> iS)]) ;
+ }
+#else
+ switch ((iB & iM) >> iS) /* determine the gray level */
+ {
+ case 0x03 : { mng_put_uint16 (pOutrow, 0xFFFF); break; }
+ case 0x02 : { mng_put_uint16 (pOutrow, 0xAAAA); break; }
+ case 0x01 : { mng_put_uint16 (pOutrow, 0x5555); break; }
+ default : { mng_put_uint16 (pOutrow, 0x0000); }
+ }
+#endif
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A2, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif /* MNG_SUPPORT_JPEG12 */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_JPEG12
+mng_retcode mng_store_jpeg_g12_a4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint16 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 2;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the gray level */
+ iQ = (mng_uint16)((iB & iM) >> iS);
+ iQ = (mng_uint16)(iQ + (iQ << 4)); /* expand to 16-bit by replication */
+ iQ = (mng_uint16)(iQ + (iQ << 8));
+ /* put in object buffer */
+ mng_put_uint16 (pOutrow, iQ);
+
+ pOutrow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A4, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif /* MNG_SUPPORT_JPEG12 */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_JPEG12
+mng_retcode mng_store_jpeg_g12_a8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 2;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iW = (mng_uint16)(*pWorkrow); /* get input byte */
+ iW = (mng_uint16)(iW + (iW << 8)); /* expand to 16-bit by replication */
+
+ mng_put_uint16 (pOutrow, iW); /* put in object buffer */
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A8, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif /* MNG_SUPPORT_JPEG12 */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_JPEG12
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_g12_a16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 2;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* copy it */
+ mng_put_uint16 (pOutrow, mng_get_uint16 (pWorkrow));
+
+ pOutrow += 4; /* next pixel */
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_STORE_JPEG_G12_A16, MNG_LC_END);
+#endif
+ /* we've got one more row of alpha-samples */
+ return mng_next_jpeg_alpharow (pData);
+}
+#endif
+#endif /* MNG_SUPPORT_JPEG12 */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_JNG */
+
+#ifndef MNG_NO_DELTA_PNG
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - apply the processed & uncompressed row-data * */
+/* * onto the target "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_g1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it white ? */
+ *pOutrow = 0xFF; /* white */
+ else
+ *pOutrow = 0x00; /* black */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* invert if it is white ? */
+ *pOutrow = (mng_uint8)(*pOutrow ^ 0xFF);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G1, MNG_LC_END);
+#endif
+
+ return mng_store_g1 (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ const mng_uint8 level[4] = { 0x00, 0x55, 0xAA, 0xFF};
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ *pOutrow = level[((iB & iM) >> iS)] ;
+#else
+ switch ((iB & iM) >> iS) /* determine the alpha level */
+ {
+ case 0x03 : { *pOutrow = 0xFF; break; }
+ case 0x02 : { *pOutrow = 0xAA; break; }
+ case 0x01 : { *pOutrow = 0x55; break; }
+ default : { *pOutrow = 0x00; }
+ }
+#endif
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ *pOutrow = level[((*pOutrow >> 6) + ((iB & iM) >> iS)) & 0x03] ;
+#else
+ switch (((*pOutrow >> 6) + ((iB & iM) >> iS)) & 0x03)
+ {
+ case 0x03 : { *pOutrow = 0xFF; break; }
+ case 0x02 : { *pOutrow = 0xAA; break; }
+ case 0x01 : { *pOutrow = 0x55; break; }
+ default : { *pOutrow = 0x00; }
+ }
+#endif
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G2, MNG_LC_END);
+#endif
+
+ return mng_store_g2 (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the gray level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* expand to 8-bit by replication */
+ iQ = (mng_uint8)(iQ + (iQ << 4));
+
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the gray level */
+ iQ = (mng_uint8)(((*pOutrow >> 4) + ((iB & iM) >> iS)) & 0x0F);
+ /* expand to 8-bit by replication */
+ iQ = (mng_uint8)(iQ + (iQ << 4));
+
+ *pOutrow = iQ; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G4, MNG_LC_END);
+#endif
+
+ return mng_store_g4 (pData);
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ *pOutrow = (mng_uint8)(*pOutrow + *pWorkrow);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G8, MNG_LC_END);
+#endif
+
+ return mng_store_g8 (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_g16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ /* next pixel */
+ pOutrow += (pData->iColinc << 1);
+ pWorkrow += 2;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ mng_put_uint16 (pOutrow, (mng_uint16)(mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow) ));
+ /* next pixel */
+ pOutrow += (pData->iColinc << 1);
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G16, MNG_LC_END);
+#endif
+
+ return mng_store_g16 (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ /* next pixel */
+ pOutrow += (pData->iColinc * 3);
+ pWorkrow += 3;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ *pOutrow = (mng_uint8)(*pOutrow + *pWorkrow );
+ *(pOutrow+1) = (mng_uint8)(*(pOutrow+1) + *(pWorkrow+1));
+ *(pOutrow+2) = (mng_uint8)(*(pOutrow+2) + *(pWorkrow+2));
+ /* next pixel */
+ pOutrow += (pData->iColinc * 3);
+ pWorkrow += 3;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB8, MNG_LC_END);
+#endif
+
+ return mng_store_rgb8 (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = *(pWorkrow+3);
+ *(pOutrow+4) = *(pWorkrow+4);
+ *(pOutrow+5) = *(pWorkrow+5);
+ /* next pixel */
+ pOutrow += (pData->iColinc * 6);
+ pWorkrow += 6;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ mng_put_uint16 (pOutrow, (mng_uint16)(mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow ) ));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)(mng_get_uint16 (pOutrow+2 ) +
+ mng_get_uint16 (pWorkrow+2) ));
+ mng_put_uint16 (pOutrow+4, (mng_uint16)(mng_get_uint16 (pOutrow+4 ) +
+ mng_get_uint16 (pWorkrow+4) ));
+ /* next pixel */
+ pOutrow += (pData->iColinc * 6);
+ pWorkrow += 6;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB16, MNG_LC_END);
+#endif
+
+ return mng_store_rgb16 (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_idx1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX1, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* put the right index value */
+ *pOutrow = 1;
+ else
+ *pOutrow = 0;
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* invert if it is non-zero index */
+ *pOutrow = (mng_uint8)(*pOutrow ^ 0x01);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 1;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX1, MNG_LC_END);
+#endif
+
+ return mng_store_idx1 (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_idx2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX2, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* put the index */
+ *pOutrow = (mng_uint8)((iB & iM) >> iS);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* calculate the index */
+ *pOutrow = (mng_uint8)((*pOutrow + ((iB & iM) >> iS)) & 0x03);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX2, MNG_LC_END);
+#endif
+
+ return mng_store_idx2 (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_idx4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX4, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* put the index */
+ *pOutrow = (mng_uint8)((iB & iM) >> iS);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* calculate the index */
+ *pOutrow = (mng_uint8)((*pOutrow + ((iB & iM) >> iS)) & 0x0F);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX4, MNG_LC_END);
+#endif
+
+ return mng_store_idx4 (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_idx8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ *pOutrow = (mng_uint8)(*pOutrow + *pWorkrow);
+
+ pOutrow += pData->iColinc; /* next pixel */
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_IDX8, MNG_LC_END);
+#endif
+
+ return mng_store_idx8 (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ /* next pixel */
+ pOutrow += (pData->iColinc << 1);
+ pWorkrow += 2;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ *pOutrow = (mng_uint8)(*pOutrow + *pWorkrow );
+ *(pOutrow+1) = (mng_uint8)(*(pOutrow+1) + *(pWorkrow+1));
+ /* next pixel */
+ pOutrow += (pData->iColinc << 1);
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8, MNG_LC_END);
+#endif
+
+ return mng_store_ga8 (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = *(pWorkrow+3);
+ /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ pWorkrow += 4;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ mng_put_uint16 (pOutrow, (mng_uint16)(mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow ) ));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)(mng_get_uint16 (pOutrow+2 ) +
+ mng_get_uint16 (pWorkrow+2) ));
+ /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ pWorkrow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16, MNG_LC_END);
+#endif
+
+ return mng_store_ga16 (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow; /* put in object buffer */
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = *(pWorkrow+3);
+ /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ pWorkrow += 4;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ *pOutrow = (mng_uint8)(*pOutrow + *pWorkrow );
+ *(pOutrow+1) = (mng_uint8)(*(pOutrow+1) + *(pWorkrow+1));
+ *(pOutrow+2) = (mng_uint8)(*(pOutrow+2) + *(pWorkrow+2));
+ *(pOutrow+3) = (mng_uint8)(*(pOutrow+3) + *(pWorkrow+3));
+ /* next pixel */
+ pOutrow += (pData->iColinc << 2);
+ pWorkrow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8, MNG_LC_END);
+#endif
+
+ return mng_store_rgba8 (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pDeltaImage)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iDeltaBlocky * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) +
+ (pData->iDeltaBlockx * pBuf->iSamplesize);
+ /* pixel replace ? */
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ MNG_COPY (pOutrow, pWorkrow, 8); /* put in object buffer */
+ /* next pixel */
+ pOutrow += (pData->iColinc << 3);
+ pWorkrow += 8;
+ }
+ }
+ else
+ { /* pixel add ! */
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* add to object buffer */
+ mng_put_uint16 (pOutrow, (mng_uint16)(mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow ) ));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)(mng_get_uint16 (pOutrow+2 ) +
+ mng_get_uint16 (pWorkrow+2) ));
+ mng_put_uint16 (pOutrow+4, (mng_uint16)(mng_get_uint16 (pOutrow+4 ) +
+ mng_get_uint16 (pWorkrow+4) ));
+ mng_put_uint16 (pOutrow+6, (mng_uint16)(mng_get_uint16 (pOutrow+6 ) +
+ mng_get_uint16 (pWorkrow+6) ));
+ /* next pixel */
+ pOutrow += (pData->iColinc << 3);
+ pWorkrow += 8;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16, MNG_LC_END);
+#endif
+
+ return mng_store_rgba16 (pData);
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - apply the source row onto the target * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_g1_g1 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G1_G1, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0x01);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G1_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g2_g2 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G2_G2, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0x03);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G2_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g4_g4 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G4_G4, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0x0F);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G4_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_g8_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G8_G8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G8_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_g16_g16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G16_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, (pData->iRowsamples << 1));
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow) +
+ mng_get_uint16 (pWorkrow)) & 0xFFFF));
+
+ pOutrow += 2;
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_G16_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_rgb8_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB8_RGB8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples * 3);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples*3; iX > 0; iX--)
+#else
+ for (iX = 0; iX < (pData->iRowsamples * 3); iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB8_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgb16_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB16_RGB16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, (pData->iRowsamples * 6));
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow )) & 0xFFFF));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)((mng_get_uint16 (pOutrow+2) +
+ mng_get_uint16 (pWorkrow+2)) & 0xFFFF));
+ mng_put_uint16 (pOutrow+4, (mng_uint16)((mng_get_uint16 (pOutrow+4) +
+ mng_get_uint16 (pWorkrow+4)) & 0xFFFF));
+
+ pOutrow += 6;
+ pWorkrow += 6;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGB16_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_delta_ga8_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_GA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples << 1);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = (pData->iRowsamples<<1); iX > 0; iX--)
+#else
+ for (iX = 0; iX < (pData->iRowsamples << 1); iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_ga8_g8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_G8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow;
+
+ pOutrow += 2;
+ pWorkrow++;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow += 2;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_ga8_a8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_A8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 1;
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow;
+
+ pOutrow += 2;
+ pWorkrow++;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow += 2;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA8_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_GA16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, (pData->iRowsamples << 2));
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow )) & 0xFFFF));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)((mng_get_uint16 (pOutrow+2) +
+ mng_get_uint16 (pWorkrow+2)) & 0xFFFF));
+
+ pOutrow += 4;
+ pWorkrow += 4;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16_g16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, mng_get_uint16 (pWorkrow));
+
+ pOutrow += 4;
+ pWorkrow += 2;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow) +
+ mng_get_uint16 (pWorkrow)) & 0xFFFF));
+
+ pOutrow += 4;
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16_a16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_A16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow+2, mng_get_uint16 (pWorkrow));
+
+ pOutrow += 4;
+ pWorkrow += 2;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow+2, (mng_uint16)((mng_get_uint16 (pOutrow+2) +
+ mng_get_uint16 (pWorkrow)) & 0xFFFF));
+
+ pOutrow += 4;
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_GA16_A16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_rgba8_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_RGBA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, pData->iRowsamples << 2);
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = (pData->iRowsamples << 2); iX > 0; iX--)
+#else
+ for (iX = 0; iX < (pData->iRowsamples << 2); iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow++;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_retcode mng_delta_rgba8_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_RGB8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow;
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+
+ pOutrow += 4;
+ pWorkrow += 3;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow ) & 0xFF);
+ *(pOutrow+1) = (mng_uint8)(((mng_uint16)*(pOutrow+1) +
+ (mng_uint16)*(pWorkrow+1)) & 0xFF);
+ *(pOutrow+2) = (mng_uint8)(((mng_uint16)*(pOutrow+2) +
+ (mng_uint16)*(pWorkrow+2)) & 0xFF);
+
+ pOutrow += 4;
+ pWorkrow += 3;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_delta_rgba8_a8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_A8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize) + 3;
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = *pWorkrow;
+
+ pOutrow += 4;
+ pWorkrow++;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(((mng_uint16)*pOutrow +
+ (mng_uint16)*pWorkrow) & 0xFF);
+
+ pOutrow += 4;
+ pWorkrow++;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA8_A8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgba16_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_RGBA16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if ((pData->iDeltatype == MNG_DELTATYPE_REPLACE ) ||
+ (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELREPLACE) )
+ {
+ MNG_COPY (pOutrow, pWorkrow, (pData->iRowsamples << 3));
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKPIXELADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow )) & 0xFFFF));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)((mng_get_uint16 (pOutrow+2) +
+ mng_get_uint16 (pWorkrow+2)) & 0xFFFF));
+ mng_put_uint16 (pOutrow+4, (mng_uint16)((mng_get_uint16 (pOutrow+4) +
+ mng_get_uint16 (pWorkrow+4)) & 0xFFFF));
+ mng_put_uint16 (pOutrow+6, (mng_uint16)((mng_get_uint16 (pOutrow+6) +
+ mng_get_uint16 (pWorkrow+6)) & 0xFFFF));
+
+ pOutrow += 8;
+ pWorkrow += 8;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgba16_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_RGB16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, mng_get_uint16 (pWorkrow ));
+ mng_put_uint16 (pOutrow+2, mng_get_uint16 (pWorkrow+2));
+ mng_put_uint16 (pOutrow+4, mng_get_uint16 (pWorkrow+4));
+
+ pOutrow += 8;
+ pWorkrow += 6;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKCOLORADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow, (mng_uint16)((mng_get_uint16 (pOutrow ) +
+ mng_get_uint16 (pWorkrow )) & 0xFFFF));
+ mng_put_uint16 (pOutrow+2, (mng_uint16)((mng_get_uint16 (pOutrow+2) +
+ mng_get_uint16 (pWorkrow+2)) & 0xFFFF));
+ mng_put_uint16 (pOutrow+4, (mng_uint16)((mng_get_uint16 (pOutrow+4) +
+ mng_get_uint16 (pWorkrow+4)) & 0xFFFF));
+
+ pOutrow += 8;
+ pWorkrow += 6;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgba16_a16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_A16, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAREPLACE)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow+6, mng_get_uint16 (pWorkrow));
+
+ pOutrow += 8;
+ pWorkrow += 2;
+ }
+ }
+ else
+ if (pData->iDeltatype == MNG_DELTATYPE_BLOCKALPHAADD)
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ mng_put_uint16 (pOutrow+6, (mng_uint16)((mng_get_uint16 (pOutrow+6) +
+ mng_get_uint16 (pWorkrow)) & 0xFFFF));
+
+ pOutrow += 8;
+ pWorkrow += 2;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DELTA_RGBA16_A16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - scale the delta to bitdepth of target * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g1_g2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G2, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 1);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g1_g4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G4, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 3);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g1_g8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 7);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g1_g16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + (pData->iRowsamples - 1);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 1);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + pData->iRowsamples - 1); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 1)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+1) = 0;
+ *pOutrow = (mng_uint8)(*pWorkrow << 7);
+
+ pWorkrow--;
+ pOutrow -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G1_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g2_g4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G4, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 2);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g2_g8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 6);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g2_g16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + (pData->iRowsamples - 1);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 1);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + pData->iRowsamples - 1); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 1)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+1) = 0;
+ *pOutrow = (mng_uint8)(*pWorkrow << 6);
+
+ pWorkrow--;
+ pOutrow -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g4_g8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow << 4);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g4_g16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + (pData->iRowsamples - 1);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 1);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + pData->iRowsamples - 1); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 1)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+1) = 0;
+ *pOutrow = (mng_uint8)(*pWorkrow << 4);
+
+ pWorkrow--;
+ pOutrow -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g8_g16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + (pData->iRowsamples - 1);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 1);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + pData->iRowsamples - 1); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 1)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+1) = 0;
+ *pOutrow = *pWorkrow;
+
+ pWorkrow--;
+ pOutrow -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_ga8_ga16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_GA8_GA16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + ((pData->iRowsamples - 1) << 1);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 2);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + ((pData->iRowsamples - 1) << 1)); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 2)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+3) = 0;
+ *(pOutrow+2) = *(pWorkrow+1);
+ *(pOutrow+1) = 0;
+ *pOutrow = *pWorkrow;
+
+ pWorkrow -= 2;
+ pOutrow -= 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_GA8_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_rgb8_rgb16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGB8_RGB16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + (3 * (pData->iRowsamples - 1));
+ pOutrow = pOutrow + (6 * (pData->iRowsamples - 1));
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + 3 * (pData->iRowsamples - 1)); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + 6 * (pData->iRowsamples - 1)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+5) = 0;
+ *(pOutrow+4) = *(pWorkrow+2);
+ *(pOutrow+3) = 0;
+ *(pOutrow+2) = *(pWorkrow+1);
+ *(pOutrow+1) = 0;
+ *pOutrow = *pWorkrow;
+
+ pWorkrow -= 3;
+ pOutrow -= 6;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGB8_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_rgba8_rgba16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGBA8_RGBA16, MNG_LC_START);
+#endif
+
+ pWorkrow = pWorkrow + ((pData->iRowsamples - 1) << 2);
+ pOutrow = pOutrow + ((pData->iRowsamples - 1) << 3);
+/* pWorkrow = (mng_uint8p)((mng_uint32)pWorkrow + ((pData->iRowsamples - 1) << 2)); */
+/* pOutrow = (mng_uint8p)((mng_uint32)pOutrow + ((pData->iRowsamples - 1) << 3)); */
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *(pOutrow+7) = 0;
+ *(pOutrow+6) = *(pWorkrow+3);
+ *(pOutrow+5) = 0;
+ *(pOutrow+4) = *(pWorkrow+2);
+ *(pOutrow+3) = 0;
+ *(pOutrow+2) = *(pWorkrow+1);
+ *(pOutrow+1) = 0;
+ *pOutrow = *pWorkrow;
+
+ pWorkrow -= 4;
+ pOutrow -= 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGBA8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g2_g1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G1, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 1);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G2_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g4_g1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G1, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 3);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g8_g1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G1, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 7);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g16_g1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G1, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 15);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g4_g2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G2, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 2);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G4_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g8_g2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G2, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 6);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g16_g2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G2, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 14);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g8_g4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G4, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pWorkrow = (mng_uint8)(*pWorkrow >> 4);
+ pWorkrow++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G8_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_scale_g16_g4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G4, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 12);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_g16_g8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_G16_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_ga16_ga8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_GA16_GA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_GA16_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_rgb16_rgb8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGB16_RGB8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGB16_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_scale_rgba16_rgba8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow = pData->pRGBArow;
+ mng_uint8p pOutrow = pData->pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGBA16_RGBA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ *pOutrow = (mng_uint8)(mng_get_uint16 (pWorkrow) >> 8);
+ pOutrow++;
+ pWorkrow += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_SCALE_RGBA16_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image bit routines - promote bit_depth * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_uint8 mng_promote_replicate_1_2 (mng_uint8 iB)
+{
+ return (mng_uint8)((iB << 1) | iB);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_1_4 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 1) + iB);
+ return (mng_uint8)((iB << 2) + iB);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_1_8 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 1) + iB);
+ iB = (mng_uint8)((iB << 2) + iB);
+ return (mng_uint8)((iB << 4) + iB);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_replicate_1_16 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 1) + iB);
+ iB = (mng_uint8)((iB << 2) + iB);
+ iB = (mng_uint8)((iB << 4) + iB);
+ return (mng_uint16)(((mng_uint16)iB << 8) + (mng_uint16)iB);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_2_4 (mng_uint8 iB)
+{
+ return (mng_uint8)((iB << 2) + iB);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_2_8 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 2) + iB);
+ return (mng_uint8)((iB << 4) + iB);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_replicate_2_16 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 2) + iB);
+ iB = (mng_uint8)((iB << 4) + iB);
+ return (mng_uint16)(((mng_uint16)iB << 8) + (mng_uint16)iB);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_4_8 (mng_uint8 iB)
+{
+ return (mng_uint8)((iB << 4) + iB);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_replicate_4_16 (mng_uint8 iB)
+{
+ iB = (mng_uint8)((iB << 4) + iB);
+ return (mng_uint16)(((mng_uint16)iB << 8) + (mng_uint16)iB);
+}
+#endif
+#endif /* NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_replicate_8_16 (mng_uint8 iB)
+{
+ return (mng_uint16)(((mng_uint16)iB << 8) + (mng_uint16)iB);
+}
+#endif
+
+/* ************************************************************************** */
+
+#if !defined(MNG_NO_DELTA_PNG)
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_uint8 mng_promote_zerofill_1_2 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 1);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_zerofill_1_4 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 3);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_zerofill_1_8 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 7);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_zerofill_1_16 (mng_uint8 iB)
+{
+ return (mng_uint16)((mng_uint16)iB << 15);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_zerofill_2_4 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 2);
+}
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_zerofill_2_8 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 6);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_zerofill_2_16 (mng_uint8 iB)
+{
+ return (mng_uint16)((mng_uint16)iB << 14);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_zerofill_4_8 (mng_uint8 iB)
+{
+ return (mng_uint8)(iB << 4);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_zerofill_4_16 (mng_uint8 iB)
+{
+ return (mng_uint16)((mng_uint16)iB << 12);
+}
+#endif
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_zerofill_8_16 (mng_uint8 iB)
+{
+ return (mng_uint16)((mng_uint16)iB << 8);
+}
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - promote color_type * */
+/* * * */
+/* ************************************************************************** */
+
+#if !defined(MNG_NO_DELTA_PNG) || !defined(MNG_SKIPCHUNK_PAST) || !defined(MNG_SKIPCHUNK_MAGN)
+mng_retcode mng_promote_g8_g8 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_G8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ if (pData->fPromBitdepth) /* bitdepth promoted ? */
+ iB = ((mng_bitdepth_8)pData->fPromBitdepth) (iB);
+ *pDstline = iB;
+
+ pSrcline++;
+ pDstline++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_g16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_G16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (*pSrcline);
+
+ *pDstline = (mng_uint8)(iW >> 8);
+ *(pDstline+1) = (mng_uint8)(iW && 0xFF);
+
+ pSrcline++;
+ pDstline += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_g16_g16 (mng_datap pData)
+{
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_G16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ *pDstline = *pSrcline;
+ pSrcline++;
+ pDstline++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_g8_ga8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_GA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iB != pBuf->iTRNSgray))
+ *(pDstline+1) = 0xFF;
+
+ if (pData->fPromBitdepth) /* bitdepth promoted ? */
+ iB = ((mng_bitdepth_8)pData->fPromBitdepth) (iB);
+
+ *pDstline = iB;
+
+ pSrcline++;
+ pDstline += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_GA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iB != pBuf->iTRNSgray))
+ {
+ *(pDstline+2) = 0xFF;
+ *(pDstline+3) = 0xFF;
+ }
+
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (iB);
+
+ *pDstline = (mng_uint8)(iW >> 8);
+ *(pDstline+1) = (mng_uint8)(iW && 0xFF);
+
+ pSrcline++;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g16_ga16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_GA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iW != pBuf->iTRNSgray))
+ *(pDstline+1) = 0xFFFF;
+
+ *pDstline = iW;
+
+ pSrcline++;
+ pDstline += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_g8_rgb8 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGB8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+
+ if (pData->fPromBitdepth) /* bitdepth promoted ? */
+ iB = ((mng_bitdepth_8)pData->fPromBitdepth) (iB);
+
+ *pDstline = iB;
+ *(pDstline+1) = iB;
+ *(pDstline+2) = iB;
+
+ pSrcline++;
+ pDstline += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_rgb16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGB16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (iB);
+
+ iB = (mng_uint8)(iW >> 8);
+ *pDstline = iB;
+ *(pDstline+2) = iB;
+ *(pDstline+4) = iB;
+ iB = (mng_uint8)(iW && 0xFF);
+ *(pDstline+1) = iB;
+ *(pDstline+3) = iB;
+ *(pDstline+5) = iB;
+
+ pSrcline++;
+ pDstline += 6;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g16_rgb16 (mng_datap pData)
+{
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_RGB16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = *pSrcline;
+
+ *pDstline = iW;
+ *(pDstline+1) = iW;
+ *(pDstline+2) = iW;
+
+ pSrcline++;
+ pDstline += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_g8_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGBA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iB != pBuf->iTRNSgray))
+ *(pDstline+3) = 0xFF;
+
+ if (pData->fPromBitdepth) /* bitdepth promoted ? */
+ iB = ((mng_bitdepth_8)pData->fPromBitdepth) (iB);
+
+ *pDstline = iB;
+ *(pDstline+1) = iB;
+ *(pDstline+2) = iB;
+
+ pSrcline++;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iB != pBuf->iTRNSgray))
+ {
+ *(pDstline+6) = 0xFF;
+ *(pDstline+7) = 0xFF;
+ }
+
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (iB);
+
+ iB = (mng_uint8)(iW >> 8);
+ *pDstline = iB;
+ *(pDstline+2) = iB;
+ *(pDstline+4) = iB;
+ iB = (mng_uint8)(iW && 0xFF);
+ *(pDstline+1) = iB;
+ *(pDstline+3) = iB;
+ *(pDstline+5) = iB;;
+
+ pSrcline++;
+ pDstline += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g16_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = *pSrcline;
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || (iW != pBuf->iTRNSgray))
+ *(pDstline+3) = 0xFFFF;
+
+ *pDstline = iW;
+ *(pDstline+1) = iW;
+ *(pDstline+2) = iW;
+
+ pSrcline++;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_G16_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_ga8_ga16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+ mng_uint16 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_GA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (*pSrcline);
+ iA = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+1));
+
+ *pDstline = (mng_uint8)(iW >> 8);
+ *(pDstline+1) = (mng_uint8)(iW && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iA >> 8);
+ *(pDstline+3) = (mng_uint8)(iA && 0xFF);
+
+ pSrcline += 2;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_ga8_rgba8 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+ mng_uint8 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_RGBA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+ iA = *(pSrcline+1);
+
+ *pDstline = iB;
+ *(pDstline+1) = iB;
+ *(pDstline+2) = iB;
+ *(pDstline+3) = iA;
+
+ pSrcline += 2;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_ga8_rgba16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+ mng_uint16 iW;
+ mng_uint16 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = ((mng_bitdepth_16)pData->fPromBitdepth) (*pSrcline);
+ iA = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+1));
+
+ iB = (mng_uint8)(iW >> 8);
+ *pDstline = iB;
+ *(pDstline+2) = iB;
+ *(pDstline+4) = iB;
+ iB = (mng_uint8)(iW && 0xFF);
+ *(pDstline+1) = iB;
+ *(pDstline+3) = iB;
+ *(pDstline+5) = iB;
+ *(pDstline+6) = (mng_uint8)(iA >> 8);
+ *(pDstline+7) = (mng_uint8)(iA && 0xFF);
+
+ pSrcline += 2;
+ pDstline += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_ga16_rgba16 (mng_datap pData)
+{
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iW;
+ mng_uint16 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA16_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iW = *pSrcline;
+ iA = *(pSrcline+1);
+
+ *pDstline = iW;
+ *(pDstline+1) = iW;
+ *(pDstline+2) = iW;
+ *(pDstline+3) = iA;
+
+ pSrcline += 2;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_GA16_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_rgb8_rgb16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iR;
+ mng_uint16 iG;
+ mng_uint16 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGB16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iR = ((mng_bitdepth_16)pData->fPromBitdepth) (*pSrcline);
+ iG = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+1));
+ iB = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+2));
+
+ *pDstline = (mng_uint8)(iR >> 8);
+ *(pDstline+1) = (mng_uint8)(iR && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iG >> 8);
+ *(pDstline+3) = (mng_uint8)(iG && 0xFF);
+ *(pDstline+4) = (mng_uint8)(iB >> 8);
+ *(pDstline+5) = (mng_uint8)(iB && 0xFF);
+
+ pSrcline += 3;
+ pDstline += 6;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_rgb8_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iR;
+ mng_uint8 iG;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGBA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iR = *pSrcline;
+ iG = *(pSrcline+1);
+ iB = *(pSrcline+2);
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iR != pBuf->iTRNSred) ||
+ ((mng_uint16)iG != pBuf->iTRNSgreen) || ((mng_uint16)iB != pBuf->iTRNSblue))
+ *(pDstline+3) = 0xFF;
+
+ *pDstline = iR;
+ *(pDstline+1) = iG;
+ *(pDstline+2) = iB;
+
+ pSrcline += 3;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_rgb8_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iR;
+ mng_uint8 iG;
+ mng_uint8 iB;
+ mng_uint16 iRw;
+ mng_uint16 iGw;
+ mng_uint16 iBw;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iR = *pSrcline;
+ iG = *(pSrcline+1);
+ iB = *(pSrcline+2);
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || ((mng_uint16)iR != pBuf->iTRNSred) ||
+ ((mng_uint16)iG != pBuf->iTRNSgreen) || ((mng_uint16)iB != pBuf->iTRNSblue))
+ {
+ *(pDstline+6) = 0xFF;
+ *(pDstline+7) = 0xFF;
+ }
+
+ iRw = ((mng_bitdepth_16)pData->fPromBitdepth) (iR);
+ iGw = ((mng_bitdepth_16)pData->fPromBitdepth) (iG);
+ iBw = ((mng_bitdepth_16)pData->fPromBitdepth) (iB);
+
+ *pDstline = (mng_uint8)(iRw >> 8);
+ *(pDstline+1) = (mng_uint8)(iRw && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iGw >> 8);
+ *(pDstline+3) = (mng_uint8)(iGw && 0xFF);
+ *(pDstline+4) = (mng_uint8)(iBw >> 8);
+ *(pDstline+5) = (mng_uint8)(iBw && 0xFF);
+
+ pSrcline += 3;
+ pDstline += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_rgb16_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint16p pSrcline = (mng_uint16p)pData->pPromSrc;
+ mng_uint16p pDstline = (mng_uint16p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iR;
+ mng_uint16 iG;
+ mng_uint16 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB16_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iR = *pSrcline;
+ iG = *(pSrcline+1);
+ iB = *(pSrcline+2);
+ /* no cheap transparency ? */
+ if ((!pBuf->bHasTRNS) || (iR != pBuf->iTRNSred) ||
+ (iG != pBuf->iTRNSgreen) || (iB != pBuf->iTRNSblue))
+ *(pDstline+3) = 0xFFFF;
+
+ *pDstline = iR;
+ *(pDstline+1) = iG;
+ *(pDstline+2) = iB;
+
+ pSrcline += 3;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGB16_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_idx8_rgb8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGB8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+
+ if ((mng_uint32)iB < pBuf->iPLTEcount)
+ {
+ *pDstline = pBuf->aPLTEentries [iB].iRed;
+ *(pDstline+1) = pBuf->aPLTEentries [iB].iGreen;
+ *(pDstline+2) = pBuf->aPLTEentries [iB].iBlue;
+ }
+
+ pSrcline++;
+ pDstline += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_idx8_rgb16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iN;
+ mng_uint16 iR;
+ mng_uint16 iG;
+ mng_uint16 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGB16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iN = *pSrcline;
+
+ if ((mng_uint32)iN < pBuf->iPLTEcount)
+ {
+ iR = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iRed);
+ iG = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iGreen);
+ iB = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iBlue);
+ *pDstline = (mng_uint8)(iR >> 8);
+ *(pDstline+1) = (mng_uint8)(iR && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iG >> 8);
+ *(pDstline+3) = (mng_uint8)(iG && 0xFF);
+ *(pDstline+4) = (mng_uint8)(iB >> 8);
+ *(pDstline+5) = (mng_uint8)(iB && 0xFF);
+ }
+
+ pSrcline++;
+ pDstline += 6;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_idx8_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGBA8, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iB = *pSrcline;
+
+ if ((mng_uint32)iB < pBuf->iPLTEcount)
+ {
+ *pDstline = pBuf->aPLTEentries [iB].iRed;
+ *(pDstline+1) = pBuf->aPLTEentries [iB].iGreen;
+ *(pDstline+2) = pBuf->aPLTEentries [iB].iBlue;
+
+ if ((pBuf->bHasTRNS) && ((mng_uint32)iB < pBuf->iTRNScount))
+ *(pDstline+3) = pBuf->aTRNSentries [iB];
+ else
+ *(pDstline+3) = 0xFF;
+ }
+
+ pSrcline++;
+ pDstline += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_idx8_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pPromBuf;
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint8 iN;
+ mng_uint16 iR;
+ mng_uint16 iG;
+ mng_uint16 iB;
+ mng_uint16 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iN = *pSrcline;
+
+ if ((mng_uint32)iN < pBuf->iPLTEcount)
+ {
+ iR = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iRed);
+ iG = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iGreen);
+ iB = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aPLTEentries [iN].iBlue);
+
+ if ((pBuf->bHasTRNS) && ((mng_uint32)iN < pBuf->iTRNScount))
+ iA = ((mng_bitdepth_16)pData->fPromBitdepth) (pBuf->aTRNSentries [iN]);
+ else
+ iA = 0xFFFF;
+
+ *pDstline = (mng_uint8)(iR >> 8);
+ *(pDstline+1) = (mng_uint8)(iR && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iG >> 8);
+ *(pDstline+3) = (mng_uint8)(iG && 0xFF);
+ *(pDstline+4) = (mng_uint8)(iB >> 8);
+ *(pDstline+5) = (mng_uint8)(iB && 0xFF);
+ *(pDstline+6) = (mng_uint8)(iA >> 8);
+ *(pDstline+7) = (mng_uint8)(iA && 0xFF);
+ }
+
+ pSrcline++;
+ pDstline += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_IDX8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_promote_rgba8_rgba16 (mng_datap pData)
+{
+ mng_uint8p pSrcline = (mng_uint8p)pData->pPromSrc;
+ mng_uint8p pDstline = (mng_uint8p)pData->pPromDst;
+ mng_uint32 iX;
+ mng_uint16 iR;
+ mng_uint16 iG;
+ mng_uint16 iB;
+ mng_uint16 iA;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGBA8_RGBA16, MNG_LC_START);
+#endif
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPromWidth; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPromWidth; iX++)
+#endif
+ {
+ iR = ((mng_bitdepth_16)pData->fPromBitdepth) (*pSrcline);
+ iG = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+1));
+ iB = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+2));
+ iA = ((mng_bitdepth_16)pData->fPromBitdepth) (*(pSrcline+3));
+
+ *pDstline = (mng_uint8)(iR >> 8);
+ *(pDstline+1) = (mng_uint8)(iR && 0xFF);
+ *(pDstline+2) = (mng_uint8)(iG >> 8);
+ *(pDstline+3) = (mng_uint8)(iG && 0xFF);
+ *(pDstline+4) = (mng_uint8)(iB >> 8);
+ *(pDstline+5) = (mng_uint8)(iB && 0xFF);
+ *(pDstline+6) = (mng_uint8)(iA >> 8);
+ *(pDstline+7) = (mng_uint8)(iA && 0xFF);
+
+ pSrcline += 4;
+ pDstline += 8;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROMOTE_RGBA8_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* !defined(MNG_NO_DELTA_PNG) || !defined(MNG_SKIPCHUNK_PAST) || !defined(MNG_SKIPCHUNK_MAGN) */
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing routines - convert uncompressed data from zlib to * */
+/* * managable row-data which serves as input to the color-management * */
+/* * routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_process_g1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G1, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+ if (pBuf->iTRNSgray) /* white transparent ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it white ? */
+ /* transparent ! */
+ mng_put_uint32 (pRGBArow, 0x00000000);
+ else /* opaque black */
+ mng_put_uint32 (pRGBArow, 0x000000FF);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 1;
+ }
+ }
+ else /* black transparent */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it white ? */
+ /* opaque white */
+ mng_put_uint32 (pRGBArow, 0xFFFFFFFF);
+ else /* transparent */
+ mng_put_uint32 (pRGBArow, 0x00000000);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 1;
+ }
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else /* no transparency */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ }
+
+ if (iB & iM) /* is it white ? */
+ /* opaque white */
+ mng_put_uint32 (pRGBArow, 0xFFFFFFFF);
+ else /* opaque black */
+ mng_put_uint32 (pRGBArow, 0x000000FF);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 1;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_g2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ const mng_uint32 level[4] = { 0x000000FF, 0x555555FF,
+ 0xAAAAAAFF, 0xFFFFFFFF};
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G2, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* determine gray level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+
+ if (iQ == pBuf->iTRNSgray) /* transparent ? */
+ mng_put_uint32 (pRGBArow, 0x00000000);
+ else
+ {
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ mng_put_uint32 (pRGBArow, level[iQ]);
+#else
+ switch (iQ) /* determine the gray level */
+ {
+ case 0x03 : { mng_put_uint32 (pRGBArow, 0xFFFFFFFF); break; }
+ case 0x02 : { mng_put_uint32 (pRGBArow, 0xAAAAAAFF); break; }
+ case 0x01 : { mng_put_uint32 (pRGBArow, 0x555555FF); break; }
+ default : { mng_put_uint32 (pRGBArow, 0x000000FF); }
+ }
+#endif
+ }
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_SWITCH
+ mng_put_uint32 (pRGBArow, level[((iB & iM) >> iS)] );
+#else
+ switch ((iB & iM) >> iS) /* determine the gray level */
+ {
+ case 0x03 : { mng_put_uint32 (pRGBArow, 0xFFFFFFFF); break; }
+ case 0x02 : { mng_put_uint32 (pRGBArow, 0xAAAAAAFF); break; }
+ case 0x01 : { mng_put_uint32 (pRGBArow, 0x555555FF); break; }
+ default : { mng_put_uint32 (pRGBArow, 0x000000FF); }
+ }
+#endif
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_g4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G4, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the gray level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+
+ if (iQ == pBuf->iTRNSgray) /* transparent ? */
+ {
+ *pRGBArow = 0; /* put in intermediate row */
+ *(pRGBArow+1) = 0;
+ *(pRGBArow+2) = 0;
+ *(pRGBArow+3) = 0;
+ }
+ else
+ { /* expand to 8-bit by replication */
+ iQ = (mng_uint8)(iQ + (iQ << 4));
+
+ *pRGBArow = iQ; /* put in intermediate row */
+ *(pRGBArow+1) = iQ;
+ *(pRGBArow+2) = iQ;
+ *(pRGBArow+3) = 0xFF;
+ }
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the gray level */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ iQ = (mng_uint8)(iQ + (iQ << 4));/* expand to 8-bit by replication */
+
+ *pRGBArow = iQ; /* put in intermediate row */
+ *(pRGBArow+1) = iQ;
+ *(pRGBArow+2) = iQ;
+ *(pRGBArow+3) = 0xFF;
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_g8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G8, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iB = *pWorkrow; /* get next input-byte */
+
+ if (iB == pBuf->iTRNSgray) /* transparent ? */
+ {
+ *pRGBArow = 0; /* put in intermediate row */
+ *(pRGBArow+1) = 0;
+ *(pRGBArow+2) = 0;
+ *(pRGBArow+3) = 0;
+ }
+ else
+ {
+ *pRGBArow = iB; /* put in intermediate row */
+ *(pRGBArow+1) = iB;
+ *(pRGBArow+2) = iB;
+ *(pRGBArow+3) = 0xFF;
+ }
+
+ pRGBArow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iB = *pWorkrow; /* get next input-byte */
+
+ *pRGBArow = iB; /* put in intermediate row */
+ *(pRGBArow+1) = iB;
+ *(pRGBArow+2) = iB;
+ *(pRGBArow+3) = 0xFF;
+
+ pRGBArow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_process_g16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iW;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G16, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iW = mng_get_uint16 (pWorkrow); /* get input */
+
+ if (iW == pBuf->iTRNSgray) /* transparent ? */
+ { /* put in intermediate row */
+ mng_put_uint16 (pRGBArow, 0);
+ mng_put_uint16 (pRGBArow+2, 0);
+ mng_put_uint16 (pRGBArow+4, 0);
+ mng_put_uint16 (pRGBArow+6, 0);
+ }
+ else
+ { /* put in intermediate row */
+ mng_put_uint16 (pRGBArow, iW);
+ mng_put_uint16 (pRGBArow+2, iW);
+ mng_put_uint16 (pRGBArow+4, iW);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+ }
+
+ pRGBArow += 8; /* next pixel */
+ pWorkrow += 2;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iW = mng_get_uint16 (pWorkrow); /* get input */
+
+ mng_put_uint16 (pRGBArow, iW); /* and put in intermediate row */
+ mng_put_uint16 (pRGBArow+2, iW);
+ mng_put_uint16 (pRGBArow+4, iW);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+
+ pRGBArow += 8; /* next pixel */
+ pWorkrow += 2;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_G16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_rgb8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iR, iG, iB;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGB8, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iR = *pWorkrow; /* get the RGB values */
+ iG = *(pWorkrow+1);
+ iB = *(pWorkrow+2);
+ /* transparent ? */
+ if ((iR == pBuf->iTRNSred) && (iG == pBuf->iTRNSgreen) &&
+ (iB == pBuf->iTRNSblue))
+ {
+ *pRGBArow = 0; /* this pixel is transparent ! */
+ *(pRGBArow+1) = 0;
+ *(pRGBArow+2) = 0;
+ *(pRGBArow+3) = 0;
+ }
+ else
+ {
+ *pRGBArow = iR; /* copy the RGB values */
+ *(pRGBArow+1) = iG;
+ *(pRGBArow+2) = iB;
+ *(pRGBArow+3) = 0xFF; /* this one isn't transparent */
+ }
+
+ pWorkrow += 3; /* next pixel */
+ pRGBArow += 4;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRGBArow = *pWorkrow; /* copy the RGB bytes */
+ *(pRGBArow+1) = *(pWorkrow+1);
+ *(pRGBArow+2) = *(pWorkrow+2);
+ *(pRGBArow+3) = 0xFF; /* no alpha; so always fully opaque */
+
+ pWorkrow += 3; /* next pixel */
+ pRGBArow += 4;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGB8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_process_rgb16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iR, iG, iB;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGB16, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iR = mng_get_uint16 (pWorkrow); /* get the RGB values */
+ iG = mng_get_uint16 (pWorkrow+2);
+ iB = mng_get_uint16 (pWorkrow+4);
+ /* transparent ? */
+ if ((iR == pBuf->iTRNSred) && (iG == pBuf->iTRNSgreen) &&
+ (iB == pBuf->iTRNSblue))
+ { /* transparent then */
+ mng_put_uint16 (pRGBArow, 0);
+ mng_put_uint16 (pRGBArow+2, 0);
+ mng_put_uint16 (pRGBArow+4, 0);
+ mng_put_uint16 (pRGBArow+6, 0);
+ }
+ else
+ { /* put in intermediate row */
+ mng_put_uint16 (pRGBArow, iR);
+ mng_put_uint16 (pRGBArow+2, iG);
+ mng_put_uint16 (pRGBArow+4, iB);
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+ }
+
+ pWorkrow += 6; /* next pixel */
+ pRGBArow += 8;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* copy the RGB values */
+ mng_put_uint16 (pRGBArow, mng_get_uint16 (pWorkrow ));
+ mng_put_uint16 (pRGBArow+2, mng_get_uint16 (pWorkrow+2));
+ mng_put_uint16 (pRGBArow+4, mng_get_uint16 (pWorkrow+4));
+ mng_put_uint16 (pRGBArow+6, 0xFFFF);
+
+ pWorkrow += 6; /* next pixel */
+ pRGBArow += 8;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGB16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_process_idx1 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX1, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ iS = 7;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ /* transparency for this index ? */
+ if ((mng_uint32)iQ < pBuf->iTRNScount)
+ *(pRGBArow+3) = pBuf->aTRNSentries [iQ];
+ else
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 1;
+ iS -= 1;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0x80;
+ iS = 7;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 1;
+ iS -= 1;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_idx2 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX2, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ /* transparency for this index ? */
+ if ((mng_uint32)iQ < pBuf->iTRNScount)
+ *(pRGBArow+3) = pBuf->aTRNSentries [iQ];
+ else
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = *pWorkrow; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xC0;
+ iS = 6;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ *pRGBArow = pBuf->aPLTEentries [iQ].iRed;
+ *(pRGBArow+1) = pBuf->aPLTEentries [iQ].iGreen;
+ *(pRGBArow+2) = pBuf->aPLTEentries [iQ].iBlue;
+ *(pRGBArow+3) = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 2;
+ iS -= 2;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_idx4 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iB;
+ mng_uint8 iM;
+ mng_uint32 iS;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX4, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+ iM = 0; /* start at pixel 0 */
+ iB = 0;
+ iS = 0;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = pWorkrow [0]; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ pRGBArow [0] = pBuf->aPLTEentries [iQ].iRed;
+ pRGBArow [1] = pBuf->aPLTEentries [iQ].iGreen;
+ pRGBArow [2] = pBuf->aPLTEentries [iQ].iBlue;
+ /* transparency for this index ? */
+ if ((mng_uint32)iQ < pBuf->iTRNScount)
+ pRGBArow [3] = pBuf->aTRNSentries [iQ];
+ else
+ pRGBArow [3] = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ if (!iM) /* mask underflow ? */
+ {
+ iB = pWorkrow [0]; /* get next input-byte */
+ pWorkrow++;
+ iM = 0xF0;
+ iS = 4;
+ }
+ /* get the index */
+ iQ = (mng_uint8)((iB & iM) >> iS);
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ pRGBArow [0] = pBuf->aPLTEentries [iQ].iRed;
+ pRGBArow [1] = pBuf->aPLTEentries [iQ].iGreen;
+ pRGBArow [2] = pBuf->aPLTEentries [iQ].iBlue;
+ pRGBArow [3] = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ iM >>= 4;
+ iS -= 4;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_idx8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint8 iQ;
+ mng_imagedatap pBuf = (mng_imagedatap)pData->pStorebuf;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX8, MNG_LC_START);
+#endif
+
+ if (!pBuf) /* no object? then use obj 0 */
+ pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+ if (pBuf->bHasTRNS) /* tRNS encountered ? */
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iQ = *pWorkrow; /* get input byte */
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ pRGBArow [0] = pBuf->aPLTEentries [iQ].iRed;
+ pRGBArow [1] = pBuf->aPLTEentries [iQ].iGreen;
+ pRGBArow [2] = pBuf->aPLTEentries [iQ].iBlue;
+ /* transparency for this index ? */
+ if ((mng_uint32)iQ < pBuf->iTRNScount)
+ pRGBArow [3] = pBuf->aTRNSentries [iQ];
+ else
+ pRGBArow [3] = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's not fully opaque */
+ }
+ else
+ {
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iQ = *pWorkrow; /* get input byte */
+ /* index valid ? */
+ if ((mng_uint32)iQ < pBuf->iPLTEcount)
+ { /* put in intermediate row */
+ pRGBArow [0] = pBuf->aPLTEentries [iQ].iRed;
+ pRGBArow [1] = pBuf->aPLTEentries [iQ].iGreen;
+ pRGBArow [2] = pBuf->aPLTEentries [iQ].iBlue;
+ pRGBArow [3] = 0xFF;
+ }
+ else
+ MNG_ERROR (pData, MNG_PLTEINDEXERROR);
+
+ pRGBArow += 4; /* next pixel */
+ pWorkrow++;
+ }
+
+ pData->bIsOpaque = MNG_TRUE; /* it's fully opaque */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_IDX8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_ga8 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_GA8, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ *pRGBArow = *pWorkrow; /* copy the gray value */
+ *(pRGBArow+1) = *pWorkrow;
+ *(pRGBArow+2) = *pWorkrow;
+ *(pRGBArow+3) = *(pWorkrow+1); /* copy the alpha value */
+
+ pWorkrow += 2; /* next pixel */
+ pRGBArow += 4;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's definitely not fully opaque */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_GA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_process_ga16 (mng_datap pData)
+{
+ mng_uint8p pWorkrow;
+ mng_uint8p pRGBArow;
+ mng_int32 iX;
+ mng_uint16 iW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_GA16, MNG_LC_START);
+#endif
+ /* temporary work pointers */
+ pWorkrow = pData->pWorkrow + pData->iPixelofs;
+ pRGBArow = pData->pRGBArow;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iW = mng_get_uint16 (pWorkrow); /* copy the gray value */
+ mng_put_uint16 (pRGBArow, iW);
+ mng_put_uint16 (pRGBArow+2, iW);
+ mng_put_uint16 (pRGBArow+4, iW);
+ /* copy the alpha value */
+ mng_put_uint16 (pRGBArow+6, mng_get_uint16 (pWorkrow+2));
+
+ pWorkrow += 4; /* next pixel */
+ pRGBArow += 8;
+ }
+
+ pData->bIsOpaque = MNG_FALSE; /* it's definitely not fully opaque */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_GA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_rgba8 (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGBA8, MNG_LC_START);
+#endif
+ /* this is the easiest transform */
+ MNG_COPY (pData->pRGBArow, pData->pWorkrow + pData->iPixelofs, pData->iRowsize);
+
+ pData->bIsOpaque = MNG_FALSE; /* it's definitely not fully opaque */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_process_rgba16 (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGBA16, MNG_LC_START);
+#endif
+ /* this is the easiest transform */
+ MNG_COPY (pData->pRGBArow, pData->pWorkrow + pData->iPixelofs, pData->iRowsize);
+
+ pData->bIsOpaque = MNG_FALSE; /* it's definitely not fully opaque */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing initialization routines - set up the variables needed * */
+/* * to process uncompressed row-data * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_g1_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G1_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g1;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g1;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g1;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g1;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iRowsize = (pData->iRowsamples + 7) >> 3;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G1_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g1_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G1_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g1;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g1;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g1;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g1;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iRowsize = ((pData->iRowsamples + 7) >> 3);
+ pData->iRowmax = ((pData->iDatawidth + 7) >> 3) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G1_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g2_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G2_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g2;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g2;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g2;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g2;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iRowsize = (pData->iRowsamples + 3) >> 2;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G2_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g2_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G2_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g2;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g2;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g2;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g2;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iRowsize = ((pData->iRowsamples + 3) >> 2);
+ pData->iRowmax = ((pData->iDatawidth + 3) >> 2) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G2_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g4_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G4_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g4;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g4;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g4;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g4;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iRowsize = (pData->iRowsamples + 1) >> 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G4_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g4_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G4_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g4;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g4;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g4;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g4;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iRowsize = ((pData->iRowsamples + 1) >> 1);
+ pData->iRowmax = ((pData->iDatawidth + 1) >> 1) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G4_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G8_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_g8_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G8_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g8;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples;
+ pData->iRowmax = pData->iDatawidth + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G8_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_g16_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G16_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g16;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 2;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G16_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_g16_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G16_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_g16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_g16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_g16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g16;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 1;
+ pData->iRowmax = (pData->iDatawidth << 1) + pData->iPixelofs;
+ pData->iFilterbpp = 2;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_G16_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_rgb8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB8_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgb8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgb8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgb8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 3;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples * 3;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 3;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_rgb8_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB8_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgb8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgb8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgb8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb8;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 3;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples * 3;
+ pData->iRowmax = (pData->iDatawidth * 3) + pData->iPixelofs;
+ pData->iFilterbpp = 3;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB8_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_rgb16_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB16_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgb16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgb16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgb16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb16;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 6;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples * 6;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 6;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB16_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_rgb16_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB16_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgb16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgb16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgb16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb16;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 6;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples * 6;
+ pData->iRowmax = (pData->iDatawidth * 6) + pData->iPixelofs;
+ pData->iFilterbpp = 6;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGB16_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_idx1_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX1_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx1;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx1;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx1;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx1;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iRowsize = (pData->iRowsamples + 7) >> 3;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX1_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx1_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX1_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx1;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx1;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx1;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx1;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iRowsize = (pData->iRowsamples + 7) >> 3;
+ pData->iRowmax = ((pData->iDatawidth + 7) >> 3) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX1_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx2_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX2_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx2;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx2;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx2;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx2;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iRowsize = (pData->iRowsamples + 3) >> 2;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX2_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx2_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX2_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx2;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx2;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx2;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx2;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iRowsize = (pData->iRowsamples + 3) >> 2;
+ pData->iRowmax = ((pData->iDatawidth + 3) >> 2) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX2_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx4_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX4_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx4;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx4;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx4;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx4;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iRowsize = (pData->iRowsamples + 1) >> 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX4_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx4_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX4_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx4;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx4;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx4;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx4;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iRowsize = (pData->iRowsamples + 1) >> 1;
+ pData->iRowmax = ((pData->iDatawidth + 1) >> 1) + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX4_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX8_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_idx8_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX8_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_idx8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_idx8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_idx8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_idx8;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples;
+ pData->iRowmax = pData->iDatawidth + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_IDX8_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_ga8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA8_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_ga8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_ga8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_ga8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_ga8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 2;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_ga8_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA8_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_ga8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_ga8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_ga8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_ga8;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 1;
+ pData->iRowmax = (pData->iDatawidth << 1) + pData->iPixelofs;
+ pData->iFilterbpp = 2;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA8_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_ga16_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA16_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_ga16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_ga16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_ga16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_ga16;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 4;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 4;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA16_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_ga16_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA16_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_ga16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_ga16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_ga16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_ga16;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 4;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->iRowmax = (pData->iDatawidth << 2) + pData->iPixelofs;
+ pData->iFilterbpp = 4;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_GA16_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_rgba8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA8_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgba8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgba8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgba8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 4;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 4;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+/* ************************************************************************** */
+
+mng_retcode mng_init_rgba8_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA8_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgba8;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgba8;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgba8;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba8;
+#endif
+
+ pData->iPass = 0; /* from 0..6; is 1..7 in specifications */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 4;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 2;
+ pData->iRowmax = (pData->iDatawidth << 2) + pData->iPixelofs;
+ pData->iFilterbpp = 4;
+ pData->bIsRGBA16 = MNG_FALSE; /* intermediate row is 8-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA8_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_rgba16_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA16_NI, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgba16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgba16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgba16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba16;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 8;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 3;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 8;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA16_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_rgba16_i (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA16_I, MNG_LC_START);
+#endif
+
+ if (pData->fDisplayrow)
+ pData->fProcessrow = (mng_fptr)mng_process_rgba16;
+
+ if (pData->pStoreobj) /* store in object too ? */
+ { /* immediate delta ? */
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ pData->fStorerow = (mng_fptr)mng_delta_rgba16;
+ else
+#endif
+ pData->fStorerow = (mng_fptr)mng_store_rgba16;
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba16;
+#endif
+
+ pData->iPass = 0; /* from 0..6; (1..7 in specification) */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >> interlace_divider [0];
+ pData->iSamplemul = 8;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 3;
+ pData->iRowmax = (pData->iDatawidth << 3) + pData->iPixelofs;
+ pData->iFilterbpp = 8;
+ pData->bIsRGBA16 = MNG_TRUE; /* intermediate row is 16-bit deep */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_RGBA16_I, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing initialization routines (JPEG) - set up the variables * */
+/* * needed to process uncompressed row-data * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_jpeg_a1_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A1_NI, MNG_LC_START);
+#endif
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a1; break; }
+ case 14 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a1; break; }
+ }
+ }
+
+ /* TODO: bitdepth 12 & 20 */
+
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g1;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iRowsize = (pData->iRowsamples + 7) >> 3;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A1_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_jpeg_a2_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A2_NI, MNG_LC_START);
+#endif
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a2; break; }
+ case 14 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a2; break; }
+ }
+ }
+
+ /* TODO: bitdepth 12 & 20 */
+
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g2;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iRowsize = (pData->iRowsamples + 3) >> 2;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A2_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_jpeg_a4_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A4_NI, MNG_LC_START);
+#endif
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a4; break; }
+ case 14 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a4; break; }
+ }
+ }
+
+ /* TODO: bitdepth 12 & 20 */
+
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g4;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iRowsize = (pData->iRowsamples + 1) >> 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A4_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_init_jpeg_a8_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A8_NI, MNG_LC_START);
+#endif
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a8; break; }
+ case 14 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a8; break; }
+ }
+ }
+
+ /* TODO: bitdepth 12 & 20 */
+
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g8;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 1;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A8_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_jpeg_a16_ni (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A16_NI, MNG_LC_START);
+#endif
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+ if (pData->iJHDRimgbitdepth == 8)
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a16; break; }
+ case 14 : { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a16; break; }
+ }
+ }
+
+ /* TODO: bitdepth 12 & 20 */
+
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ pData->fDifferrow = (mng_fptr)mng_differ_g16;
+#endif
+
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iRowsize = pData->iRowsamples << 1;
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+ pData->iFilterbpp = 2;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_JPEG_A16_NI, MNG_LC_END);
+#endif
+
+ return mng_init_rowproc (pData);
+}
+#endif
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_JNG */
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+
+/* ************************************************************************** */
+/* * * */
+/* * Generic row processing initialization & cleanup routines * */
+/* * - initialize the buffers used by the row processing routines * */
+/* * - cleanup the buffers used by the row processing routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_init_rowproc (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ROWPROC, MNG_LC_START);
+#endif
+
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+ if (pData->ePng_imgtype != png_none)
+ {
+ if (pData->fDisplayrow)
+ switch (pData->ePng_imgtype)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_g1:
+ pData->fProcessrow = (mng_fptr)mng_process_g1;
+ break;
+ case png_g2:
+ pData->fProcessrow = (mng_fptr)mng_process_g2;
+ break;
+ case png_g4:
+ pData->fProcessrow = (mng_fptr)mng_process_g4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_g8:
+ pData->fProcessrow = (mng_fptr)mng_process_g8;
+ break;
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_idx1:
+ pData->fProcessrow = (mng_fptr)mng_process_idx1;
+ break;
+ case png_idx2:
+ pData->fProcessrow = (mng_fptr)mng_process_idx2;
+ break;
+ case png_idx4:
+ pData->fProcessrow = (mng_fptr)mng_process_idx4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_idx8:
+ pData->fProcessrow = (mng_fptr)mng_process_idx8;
+ break;
+ case png_ga8:
+ pData->fProcessrow = (mng_fptr)mng_process_ga8;
+ break;
+ case png_rgb8:
+ pData->fProcessrow = (mng_fptr)mng_process_rgb8;
+ break;
+ case png_rgba8:
+ pData->fProcessrow = (mng_fptr)mng_process_rgba8;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_g16:
+ pData->fProcessrow = (mng_fptr)mng_process_g16;
+ break;
+ case png_ga16:
+ pData->fProcessrow = (mng_fptr)mng_process_ga16;
+ break;
+ case png_rgb16:
+ pData->fProcessrow = (mng_fptr)mng_process_rgb16;
+ break;
+ case png_rgba16:
+ pData->fProcessrow = (mng_fptr)mng_process_rgba16;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (pData->pStoreobj) /* store in object too ? */
+ {
+#ifndef MNG_NO_DELTA_PNG
+ if ((pData->bHasDHDR) && (pData->bDeltaimmediate))
+ switch (pData->ePng_imgtype)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_g1:
+ pData->fStorerow = (mng_fptr)mng_delta_g1;
+ break;
+ case png_g2:
+ pData->fStorerow = (mng_fptr)mng_delta_g2;
+ break;
+ case png_g4:
+ pData->fStorerow = (mng_fptr)mng_delta_g4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_g8:
+ pData->fStorerow = (mng_fptr)mng_delta_g8;
+ break;
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_idx1:
+ pData->fStorerow = (mng_fptr)mng_delta_idx1;
+ break;
+ case png_idx2:
+ pData->fStorerow = (mng_fptr)mng_delta_idx2;
+ break;
+ case png_idx4:
+ pData->fStorerow = (mng_fptr)mng_delta_idx4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_idx8:
+ pData->fStorerow = (mng_fptr)mng_delta_idx8;
+ break;
+ case png_ga8:
+ pData->fStorerow = (mng_fptr)mng_delta_ga8;
+ break;
+ case png_rgb8:
+ pData->fStorerow = (mng_fptr)mng_delta_rgb8;
+ break;
+ case png_rgba8:
+ pData->fStorerow = (mng_fptr)mng_delta_rgba8;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_g16:
+ pData->fStorerow = (mng_fptr)mng_delta_g16;
+ break;
+ case png_ga16:
+ pData->fStorerow = (mng_fptr)mng_delta_ga16;
+ break;
+ case png_rgb16:
+ pData->fStorerow = (mng_fptr)mng_delta_rgb16;
+ break;
+ case png_rgba16:
+ pData->fStorerow = (mng_fptr)mng_delta_rgba16;
+ break;
+#endif
+ default:
+ break;
+ }
+ else
+#endif /* MNG_NO_DELTA_PNG */
+ switch (pData->ePng_imgtype)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_g1:
+ pData->fStorerow = (mng_fptr)mng_store_g1;
+ break;
+ case png_g2:
+ pData->fStorerow = (mng_fptr)mng_store_g2;
+ break;
+ case png_g4:
+ pData->fStorerow = (mng_fptr)mng_store_g4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_g8:
+ pData->fStorerow = (mng_fptr)mng_store_g8;
+ break;
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_idx1:
+ pData->fStorerow = (mng_fptr)mng_store_idx1;
+ break;
+ case png_idx2:
+ pData->fStorerow = (mng_fptr)mng_store_idx2;
+ break;
+ case png_idx4:
+ pData->fStorerow = (mng_fptr)mng_store_idx4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_idx8:
+ pData->fStorerow = (mng_fptr)mng_store_idx8;
+ break;
+ case png_ga8:
+ pData->fStorerow = (mng_fptr)mng_store_ga8;
+ break;
+ case png_rgb8:
+ pData->fStorerow = (mng_fptr)mng_store_rgb8;
+ break;
+ case png_rgba8:
+ pData->fStorerow = (mng_fptr)mng_store_rgba8;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_g16:
+ pData->fStorerow = (mng_fptr)mng_store_g16;
+ break;
+ case png_ga16:
+ pData->fStorerow = (mng_fptr)mng_store_ga16;
+ break;
+ case png_rgb16:
+ pData->fStorerow = (mng_fptr)mng_store_rgb16;
+ break;
+ case png_rgba16:
+ pData->fStorerow = (mng_fptr)mng_store_rgba16;
+ break;
+#endif
+
+#ifdef MNG_INCLUDE_JNG
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_jpeg_a1:
+/* if (pData->iJHDRimgbitdepth == 8) */
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a1; break; }
+ case 14 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a1; break; }
+ }
+ }
+ /* TODO: bitdepth 12 & 20 */
+ break;
+ case png_jpeg_a2:
+/* if (pData->iJHDRimgbitdepth == 8) */
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a2; break; }
+ case 14 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a2; break; }
+ }
+ }
+ break;
+ /* TODO: bitdepth 12 & 20 */
+ case png_jpeg_a4:
+/* if (pData->iJHDRimgbitdepth == 8) */
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a4; break; }
+ case 14 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a4; break; }
+ }
+ }
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ /* TODO: bitdepth 12 & 20 */
+ case png_jpeg_a8:
+/* if (pData->iJHDRimgbitdepth == 8) */
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a8; break; }
+ case 14 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a8; break; }
+ }
+ }
+ break;
+ /* TODO: bitdepth 12 & 20 */
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_jpeg_a16:
+/* if (pData->iJHDRimgbitdepth == 8) */
+ {
+ switch (pData->iJHDRcolortype)
+ {
+ case 12 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_g8_a16; break; }
+ case 14 :
+ { pData->fStorerow = (mng_fptr)mng_store_jpeg_rgb8_a16; break; }
+ }
+ }
+ break;
+ /* TODO: bitdepth 12 & 20 */
+#endif
+#endif /* MNG_INCLUDE_JNG */
+ default:
+ break;
+ }
+ }
+
+#ifdef FILTER192 /* leveling & differing ? */
+ if (pData->iFilter == MNG_FILTER_DIFFERING)
+ switch (pData->ePng_imgtype)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_g1:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a1:
+#endif
+ pData->fDifferrow = (mng_fptr)mng_differ_g1;
+ break;
+ case png_g2:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a2:
+#endif
+ pData->fDifferrow = (mng_fptr)mng_differ_g2;
+ break;
+ case png_g4:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a4:
+#endif
+ pData->fDifferrow = (mng_fptr)mng_differ_g4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_g8:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a8:
+#endif
+ pData->fDifferrow = (mng_fptr)mng_differ_g8;
+ break;
+ case png_rgb8:
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb8;
+ break;
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_idx1:
+ pData->fDifferrow = (mng_fptr)mng_differ_idx1;
+ break;
+ case png_idx2:
+ pData->fDifferrow = (mng_fptr)mng_differ_idx2;
+ break;
+ case png_idx4:
+ pData->fDifferrow = (mng_fptr)mng_differ_idx4;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_idx8:
+ pData->fDifferrow = (mng_fptr)mng_differ_idx8;
+ break;
+ case png_ga8:
+ pData->fDifferrow = (mng_fptr)mng_differ_ga8;
+ break;
+ case png_rgb8:
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb8;
+ break;
+ case png_rgba8:
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba8;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_g16:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a16:
+#endif
+ pData->fDifferrow = (mng_fptr)mng_differ_g16;
+ break;
+ case png_ga16:
+ pData->fDifferrow = (mng_fptr)mng_differ_ga16;
+ break;
+ case png_rgb16:
+ pData->fDifferrow = (mng_fptr)mng_differ_rgb16;
+ break;
+ case png_rgba16:
+ pData->fDifferrow = (mng_fptr)mng_differ_rgba16;
+ break;
+#endif
+ default:
+ break;
+ }
+#endif
+
+ switch (pData->ePng_imgtype)
+ {
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+ case png_g1:
+ case png_idx1:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a1:
+#endif
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 7;
+ pData->iSamplediv = 3;
+ pData->iFilterbpp = 1;
+ break;
+ case png_g2:
+ case png_idx2:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a2:
+#endif
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 3;
+ pData->iSamplediv = 2;
+ pData->iFilterbpp = 1;
+ break;
+ case png_g4:
+ case png_idx4:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a4:
+#endif
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 1;
+ pData->iSamplediv = 1;
+ pData->iFilterbpp = 1;
+ break;
+#endif /* MNG_NO_1_2_4BIT_SUPPORT */
+ case png_g8:
+ case png_idx8:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a8:
+#endif
+ pData->iSamplemul = 1;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 1;
+ break;
+ case png_ga8:
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_g16:
+#ifdef MNG_INCLUDE_JNG
+ case png_jpeg_a16:
+#endif
+#endif
+ pData->iSamplemul = 2;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 2;
+ break;
+ case png_rgb8:
+ pData->iSamplemul = 3;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 3;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_ga16:
+#endif
+ case png_rgba8:
+ pData->iSamplemul = 4;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 4;
+ break;
+#ifndef MNG_NO_16BIT_SUPPORT
+ case png_rgb16:
+ pData->iSamplemul = 6;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 6;
+ break;
+ case png_rgba16:
+ pData->iSamplemul = 8;
+ pData->iSampleofs = 0;
+ pData->iSamplediv = 0;
+ pData->iFilterbpp = 8;
+ break;
+#endif
+ default:
+ break;
+ }
+
+ if (pData->iInterlace) /* noninterlaced */
+ {
+ pData->iPass = 0; /* from 0..6; (1..7 in specification) */
+ pData->iRow = interlace_row [0];
+ pData->iRowinc = interlace_rowskip [0];
+ pData->iCol = interlace_col [0];
+ pData->iColinc = interlace_colskip [0];
+ pData->iRowsamples = (pData->iDatawidth + interlace_roundoff [0]) >>
+ interlace_divider [0];
+ pData->iRowmax = ((pData->iDatawidth * pData->iSamplemul +
+ pData->iSampleofs) >> pData->iSamplediv) + pData->iPixelofs;
+ }
+ else /* interlaced */
+ {
+ pData->iPass = -1;
+ pData->iRow = 0;
+ pData->iRowinc = 1;
+ pData->iCol = 0;
+ pData->iColinc = 1;
+ pData->iRowsamples = pData->iDatawidth;
+ }
+ if (pData->iSamplediv > 0)
+ pData->iRowsize = (pData->iRowsamples + pData->iSampleofs) >>
+ pData->iSamplediv;
+ else
+ pData->iRowsize = (pData->iRowsamples * pData->iSamplemul);
+
+ if (!pData->iInterlace) /* noninterlaced */
+ pData->iRowmax = pData->iRowsize + pData->iPixelofs;
+
+#ifdef MNG_NO_16BIT_SUPPORT
+ pData->bIsRGBA16 = MNG_FALSE;
+#else
+ switch (pData->ePng_imgtype)
+ {
+ case png_g16:
+ case png_ga16:
+ case png_rgb16:
+ case png_rgba16:
+ pData->bIsRGBA16 = MNG_TRUE;
+ break;
+ default:
+ pData->bIsRGBA16 = MNG_FALSE;
+ break;
+ }
+#endif
+
+ }
+#endif /* MNG_OPTIMIZE_FOOTPRINT_INIT */
+
+ if (pData->pStoreobj) /* storage object selected ? */
+ {
+ pData->pStorebuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ /* and so it becomes viewable ! */
+ ((mng_imagep)pData->pStoreobj)->bViewable = MNG_TRUE;
+ ((mng_imagedatap)pData->pStorebuf)->bViewable = MNG_TRUE;
+ }
+
+ /* allocate the buffers; the individual init routines have already
+ calculated the required maximum size; except in the case of a JNG
+ without alpha!!! */
+ if (pData->iRowmax)
+ {
+#if defined(MNG_NO_16BIT_SUPPORT) || defined (MNG_NO_1_2_4BIT_SUPPORT)
+ mng_uint8 iRowadd = 0;
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iPNGdepth < 8)
+ iRowadd=(pData->iPNGdepth*pData->iRowmax+7)/8;
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iPNGdepth > 8)
+ iRowadd=pData->iRowmax;
+#endif
+ MNG_ALLOC (pData, pData->pWorkrow, pData->iRowmax+iRowadd);
+ MNG_ALLOC (pData, pData->pPrevrow, pData->iRowmax+iRowadd);
+#else
+ MNG_ALLOC (pData, pData->pWorkrow, pData->iRowmax);
+ MNG_ALLOC (pData, pData->pPrevrow, pData->iRowmax);
+#endif
+ }
+
+ /* allocate an RGBA16 row for intermediate processing */
+ MNG_ALLOC (pData, pData->pRGBArow, (pData->iDatawidth << 3));
+
+#ifndef MNG_NO_CMS
+ if (pData->fDisplayrow) /* display "on-the-fly" ? */
+ {
+#if defined(MNG_FULL_CMS) /* determine color-management initialization */
+ mng_retcode iRetcode = mng_init_full_cms (pData, MNG_TRUE, MNG_TRUE, MNG_FALSE);
+#elif defined(MNG_GAMMA_ONLY)
+ mng_retcode iRetcode = mng_init_gamma_only (pData, MNG_TRUE, MNG_TRUE, MNG_FALSE);
+#elif defined(MNG_APP_CMS)
+ mng_retcode iRetcode = mng_init_app_cms (pData, MNG_TRUE, MNG_TRUE, MNG_FALSE);
+#endif
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* !MNG_NO_CMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_INIT_ROWPROC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_next_row (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_ROW, MNG_LC_START);
+#endif
+
+ pData->iRow += pData->iRowinc; /* increase the row counter */
+
+ if (pData->iPass >= 0) /* interlaced ? */
+ {
+ while ((pData->iPass < 7) && /* went 'outside' the image ? */
+ ((pData->iRow >= (mng_int32)pData->iDataheight) ||
+ (pData->iCol >= (mng_int32)pData->iDatawidth ) ))
+ {
+ pData->iPass++; /* next pass ! */
+
+ if (pData->iPass < 7) /* there's only 7 passes ! */
+ {
+ pData->iRow = interlace_row [pData->iPass];
+ pData->iRowinc = interlace_rowskip [pData->iPass];
+ pData->iCol = interlace_col [pData->iPass];
+ pData->iColinc = interlace_colskip [pData->iPass];
+ pData->iRowsamples = (pData->iDatawidth - pData->iCol + interlace_roundoff [pData->iPass])
+ >> interlace_divider [pData->iPass];
+
+ if (pData->iSamplemul > 1) /* recalculate row dimension */
+ pData->iRowsize = pData->iRowsamples * pData->iSamplemul;
+ else
+ if (pData->iSamplediv > 0)
+ pData->iRowsize = (pData->iRowsamples + pData->iSampleofs) >> pData->iSamplediv;
+ else
+ pData->iRowsize = pData->iRowsamples;
+
+ }
+
+ if ((pData->iPass < 7) && /* reset previous row to zeroes ? */
+ (pData->iRow < (mng_int32)pData->iDataheight) &&
+ (pData->iCol < (mng_int32)pData->iDatawidth ) )
+ { /* making sure the filters will work properly! */
+ mng_int32 iX;
+ mng_uint8p pTemp = pData->pPrevrow;
+
+#ifdef MNG_NO_16BIT_SUPPORT
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iPNGmult*pData->iRowsize; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iPNGmult*pData->iRowsize; iX++)
+#endif
+#else
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsize; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsize; iX++)
+#endif
+#endif
+ {
+ *pTemp = 0;
+ pTemp++;
+ }
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_ROW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_cleanup_rowproc (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEANUP_ROWPROC, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS /* cleanup cms profile/transform */
+ {
+ mng_retcode iRetcode = mng_clear_cms (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif /* MNG_INCLUDE_LCMS */
+
+ if (pData->pRGBArow) /* cleanup buffer for intermediate row */
+ MNG_FREEX (pData, pData->pRGBArow, (pData->iDatawidth << 3));
+ if (pData->pPrevrow) /* cleanup buffer for previous row */
+ MNG_FREEX (pData, pData->pPrevrow, pData->iRowmax);
+ if (pData->pWorkrow) /* cleanup buffer for working row */
+ MNG_FREEX (pData, pData->pWorkrow, pData->iRowmax);
+
+ pData->pWorkrow = MNG_NULL; /* propogate uninitialized buffers */
+ pData->pPrevrow = MNG_NULL;
+ pData->pRGBArow = MNG_NULL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_CLEANUP_ROWPROC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* woohiii */
+}
+
+/* ************************************************************************** */
+/* * * */
+/* * Generic row processing routines for JNG * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+/* ************************************************************************** */
+
+mng_retcode mng_display_jpeg_rows (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_JPEG_ROWS, MNG_LC_START);
+#endif
+ /* any completed rows ? */
+ if ((pData->iJPEGrow > pData->iJPEGdisprow) &&
+ (pData->iJPEGalpharow > pData->iJPEGdisprow) )
+ {
+ mng_uint32 iX, iMax;
+ mng_uint32 iSaverow = pData->iRow; /* save alpha decompression row-count */
+ /* determine the highest complete(!) row */
+ if (pData->iJPEGrow > pData->iJPEGalpharow)
+ iMax = pData->iJPEGalpharow;
+ else
+ iMax = pData->iJPEGrow;
+ /* display the rows */
+ for (iX = pData->iJPEGdisprow; iX < iMax; iX++)
+ {
+ pData->iRow = iX; /* make sure we all know which row to handle */
+ /* makeup an intermediate row from the buffer */
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+ /* color-correct it if necessary */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* and display it */
+ {
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode) /* check progressive display refresh */
+ iRetcode = mng_display_progressive_check (pData);
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ pData->iJPEGdisprow = iMax; /* keep track of the last displayed row */
+ pData->iRow = iSaverow; /* restore alpha decompression row-count */
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DISPLAY_JPEG_ROWS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_next_jpeg_alpharow (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_JPEG_ALPHAROW, MNG_LC_START);
+#endif
+
+ pData->iJPEGalpharow++; /* count the row */
+
+ if (pData->fDisplayrow) /* display "on-the-fly" ? */
+ { /* try to display what you can */
+ iRetcode = mng_display_jpeg_rows (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_JPEG_ALPHAROW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_next_jpeg_row (mng_datap pData)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_JPEG_ROW, MNG_LC_START);
+#endif
+
+ pData->iJPEGrow++; /* increase the row-counter */
+
+ if (pData->fDisplayrow) /* display "on-the-fly" ? */
+ { /* has alpha channel ? */
+ if ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
+ (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA) )
+ { /* try to display what you can */
+ iRetcode = mng_display_jpeg_rows (pData);
+ }
+ else
+ { /* make sure we all know which row to handle */
+ pData->iRow = pData->iJPEGrow - 1;
+ /* makeup an intermediate row from the buffer */
+ iRetcode = ((mng_retrieverow)pData->fRetrieverow) (pData);
+ /* color-correct it if necessary */
+ if ((!iRetcode) && (pData->fCorrectrow))
+ iRetcode = ((mng_correctrow)pData->fCorrectrow) (pData);
+
+ if (!iRetcode) /* and display it */
+ {
+ iRetcode = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRetcode) /* check progressive display refresh */
+ iRetcode = mng_display_progressive_check (pData);
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+
+ /* surpassed last filled row ? */
+ if (pData->iJPEGrow > pData->iJPEGrgbrow)
+ pData->iJPEGrgbrow = pData->iJPEGrow;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_NEXT_JPEG_ROW, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_MAGN
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_g8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 1;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ { /* is it same as first ? */
+ if (*pTempsrc1 == *pTempsrc2)
+ {
+ for (iS = 1; iS < iM; iS++) /* then just repeat the first */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++) /* calculate the distances */
+ {
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+ pTempdst++;
+ }
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 1;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ { /* is it same as first ? */
+ if (*pTempsrc1 == *pTempsrc2)
+ {
+ for (iS = 1; iS < iM; iS++) /* then just repeat the first */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+ }
+ else
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ pTempdst++;
+ }
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 3;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+2)) -
+ (mng_int32)(*(pTempsrc1+2)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+2)) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 3;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+
+ pTempdst += 3;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+
+ pTempdst += 3;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_ga8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+
+ pTempdst += 2;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+
+ pTempdst += 2;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ *pTempdst = *(pTempsrc1+1); /* replicate alpha from left */
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ *pTempdst = *(pTempsrc2+1); /* replicate alpha from right */
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ *pTempdst = *pTempsrc1; /* replicate gray from left */
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);/* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ *pTempdst = *pTempsrc2; /* replicate gray from right */
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);/* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_X5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+#endif /* MNG_OPTIMIZE_FOOTPRINT_MAGN */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+2)) -
+ (mng_int32)(*(pTempsrc1+2)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+2)) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *pTempdst = *(pTempsrc1+3);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+3)) -
+ (mng_int32)(*(pTempsrc1+3)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+3)) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+ *(pTempdst+3) = *(pTempsrc1+3);
+
+ pTempdst += 4;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+ *(pTempdst+3) = *(pTempsrc2+3);
+
+ pTempdst += 4;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+2)) -
+ (mng_int32)(*(pTempsrc1+2)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+2)) );
+
+ pTempdst++;
+ /* replicate alpha from left */
+ *pTempdst = *(pTempsrc1+3);
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2)) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+1)) -
+ (mng_int32)(*(pTempsrc1+1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+1)) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ *pTempdst = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+2)) -
+ (mng_int32)(*(pTempsrc1+2)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+2)) );
+
+ pTempdst++;
+ /* replicate alpha from right */
+ *pTempdst = *(pTempsrc2+3);
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline; /* initialize pixel-loop */
+ pTempdst = pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ *pTempdst = *pTempsrc1; /* replicate color from left */
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *(pTempdst+3) = *(pTempsrc1+3);
+ else
+ *(pTempdst+3) = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+3)) -
+ (mng_int32)(*(pTempsrc1+3)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+3)) );
+
+ pTempdst += 4;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ *pTempdst = *pTempsrc2; /* replicate color from right */
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *(pTempdst+3) = *(pTempsrc1+3);
+ else
+ *(pTempdst+3) = (mng_uint8)(((2 * iS * ( (mng_int32)(*(pTempsrc2+3)) -
+ (mng_int32)(*(pTempsrc1+3)) ) + iM) /
+ (iM * 2)) + (mng_int32)(*(pTempsrc1+3)) );
+
+ pTempdst += 4;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_g8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, iWidth);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+mng_retcode mng_magnify_g8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, iWidth)
+ else
+ MNG_COPY (pDstline, pSrcline2, iWidth);
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, iWidth);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G8_Y3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, iWidth * 3);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth * 3);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, iWidth * 3)
+ else
+ MNG_COPY (pDstline, pSrcline2, iWidth * 3);
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, iWidth * 3);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB8_Y3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_ga8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, iWidth << 1);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 1);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, iWidth << 1)
+ else
+ MNG_COPY (pDstline, pSrcline2, iWidth << 1);
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, iWidth << 1);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2 += 2;
+
+ *pTempdst++ = *pTempsrc1++; /* replicate alpha from top */
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1 += 2;
+ pTempsrc2++;
+
+ *pTempdst++ = *pTempsrc2++; /* replicate alpha from bottom */
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 1);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga8_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* replicate gray from top */
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc2; /* replicate gray from bottom */
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 1);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA8_Y5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+#endif /* MNG_OPTIMIZE_FOOTPRINT_MAGN */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, iWidth << 2);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, iWidth << 2)
+ else
+ MNG_COPY (pDstline, pSrcline2, iWidth << 2);
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, iWidth << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2 += 2;
+
+ *pTempdst++ = *pTempsrc1++; /* replicate alpha from top */
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1 += 2;
+ pTempsrc2++;
+
+ *pTempdst++ = *pTempsrc2++; /* replicate alpha from bottom */
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba8_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint8p pTempsrc1;
+ mng_uint8p pTempsrc2;
+ mng_uint8p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = pSrcline2;
+ pTempdst = pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst++ = *pTempsrc1++; /* replicate color from top */
+ *pTempdst++ = *pTempsrc1++;
+ *pTempdst++ = *pTempsrc1++;
+
+ pTempsrc2 += 3;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst++ = *pTempsrc2++; /* replicate color from bottom */
+ *pTempdst++ = *pTempsrc2++;
+ *pTempdst++ = *pTempsrc2++;
+
+ pTempsrc1 += 3;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ *pTempdst = (mng_uint8)( ( (2 * iS * ( (mng_int32)(*pTempsrc2) -
+ (mng_int32)(*pTempsrc1) ) + iM) /
+ (iM * 2) ) + (mng_int32)(*pTempsrc1) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth << 2);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA8_Y5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_g16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 1;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ { /* is it same as first ? */
+ if (*pTempsrc1 == *pTempsrc2)
+ {
+ for (iS = 1; iS < iM; iS++) /* then just repeat the first */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++) /* calculate the distances */
+ {
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ));
+ pTempdst++;
+ }
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 1;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ { /* is it same as first ? */
+ if (*pTempsrc1 == *pTempsrc2)
+ {
+ for (iS = 1; iS < iM; iS++) /* then just repeat the first */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+ }
+ else
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ pTempdst++;
+ }
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1++;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 3;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+2))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 3;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+
+ pTempdst += 3;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+
+ pTempdst += 3;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 3;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_ga16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p) pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+
+ pTempdst += 2;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+
+ pTempdst += 2;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ *pTempdst = *(pTempsrc1+1); /* replicate alpha from left */
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ *pTempdst = *(pTempsrc2+1); /* replicate alpha from right */
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 2;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ *pTempdst = *pTempsrc1; /* replicate gray from left */
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);/* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ *pTempdst = *pTempsrc2; /* replicate gray from right */
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);/* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_X5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX, iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X1, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ iM = iML;
+ else
+ if (iX == (iWidth - 1)) /* last interval ? */
+ iM = iMR;
+ else
+ iM = iMX;
+
+ for (iS = 1; iS < iM; iS++) /* fill interval */
+ {
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+2))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *pTempdst = *(pTempsrc1+3);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+3))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) );
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X3, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* replicate first half */
+ {
+ *pTempdst = *pTempsrc1;
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+ *(pTempdst+3) = *(pTempsrc1+3);
+
+ pTempdst += 4;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* replicate second half */
+ {
+ *pTempdst = *pTempsrc2;
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+ *(pTempdst+3) = *(pTempsrc2+3);
+
+ pTempdst += 4;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+2))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) );
+
+ pTempdst++;
+ /* replicate alpha from left */
+ *pTempdst = *(pTempsrc1+3);
+
+ pTempdst++;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1; /* just repeat the first */
+ else /* calculate the distance */
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+1) == *(pTempsrc2+1))
+ *pTempdst = *(pTempsrc1+1);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+1))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+1))) ) );
+
+ pTempdst++;
+
+ if (*(pTempsrc1+2) == *(pTempsrc2+2))
+ *pTempdst = *(pTempsrc1+2);
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+2))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+2))) ) );
+
+ pTempdst++;
+ /* replicate alpha from right */
+ *pTempdst = *(pTempsrc2+3);
+
+ pTempdst++;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_int32 iS, iM, iH;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline; /* initialize pixel-loop */
+ pTempdst = (mng_uint16p)pDstline;
+
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ pTempsrc2 = pTempsrc1 + 4;
+
+ *pTempdst = *pTempsrc1; /* copy original source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+
+ if (iX == 0) /* first interval ? */
+ {
+ if (iWidth == 1) /* single pixel ? */
+ pTempsrc2 = MNG_NULL;
+
+ iM = (mng_int32)iML;
+ }
+ else
+ if (iX == (iWidth - 2)) /* last interval ? */
+ iM = (mng_int32)iMR;
+ else
+ iM = (mng_int32)iMX;
+ /* fill interval ? */
+ if ((iX < iWidth - 1) || (iWidth == 1))
+ {
+ if (pTempsrc2) /* do we have the second pixel ? */
+ {
+ iH = (iM+1) / 2; /* calculate halfway point */
+
+ for (iS = 1; iS < iH; iS++) /* first half */
+ {
+ *pTempdst = *pTempsrc1; /* replicate color from left */
+ *(pTempdst+1) = *(pTempsrc1+1);
+ *(pTempdst+2) = *(pTempsrc1+2);
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *(pTempdst+3) = *(pTempsrc1+3);
+ else
+ mng_put_uint16 ((mng_uint8p)(pTempdst+3),
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+3))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) );
+
+ pTempdst += 4;
+ }
+
+ for (iS = iH; iS < iM; iS++) /* second half */
+ {
+ *pTempdst = *pTempsrc2; /* replicate color from right */
+ *(pTempdst+1) = *(pTempsrc2+1);
+ *(pTempdst+2) = *(pTempsrc2+2);
+
+ if (*(pTempsrc1+3) == *(pTempsrc2+3))
+ *(pTempdst+3) = *(pTempsrc1+3);
+ else
+ mng_put_uint16 ((mng_uint8p)(pTempdst+3),
+ (mng_uint16)(((2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc2+3))) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)(pTempsrc1+3))) ) );
+
+ pTempdst += 4;
+ }
+ }
+ else
+ {
+ for (iS = 1; iS < iM; iS++)
+ {
+ *pTempdst = *pTempsrc1; /* repeat first source pixel */
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+1);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+2);
+ pTempdst++;
+ *pTempdst = *(pTempsrc1+3);
+ pTempdst++;
+ }
+ }
+ }
+
+ pTempsrc1 += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_X4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_g16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 1));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 1));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_g16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 1))
+ else
+ MNG_COPY (pDstline, pSrcline2, (iWidth << 1));
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 1));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_G16_Y3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, iWidth * 6);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, iWidth * 6);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgb16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, iWidth * 6)
+ else
+ MNG_COPY (pDstline, pSrcline2, iWidth * 6);
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, iWidth * 6);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGB16_Y3, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_GRAY_SUPPORT
+mng_retcode mng_magnify_ga16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 2));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 2));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 2))
+ else
+ MNG_COPY (pDstline, pSrcline2, (iWidth << 2));
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 2));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2 += 2;
+
+ *pTempdst++ = *pTempsrc1++; /* replicate alpha from top */
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1 += 2;
+ pTempsrc2++;
+
+ *pTempdst++ = *pTempsrc2++; /* replicate alpha from bottom */
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 2));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_ga16_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc1; /* replicate gray from top */
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst = *pTempsrc2; /* replicate gray from bottom */
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 2));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_GA16_Y5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_GRAY_SUPPORT */
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y1, MNG_LC_START);
+#endif
+
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 3));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y1, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y2, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 3));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y3, MNG_LC_START);
+#endif
+
+ if (pSrcline2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 3))
+ else
+ MNG_COPY (pDstline, pSrcline2, (iWidth << 3));
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pDstline, pSrcline1, (iWidth << 3));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y4, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2 += 2;
+
+ *pTempdst++ = *pTempsrc1++; /* replicate alpha from top */
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ { /* calculate the distances */
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+
+ if (*pTempsrc1 == *pTempsrc2)
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1 += 2;
+ pTempsrc2++;
+
+ *pTempdst++ = *pTempsrc2++; /* replicate alpha from bottom */
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 3));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y4, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_magnify_rgba16_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline)
+{
+ mng_uint32 iX;
+ mng_uint16p pTempsrc1;
+ mng_uint16p pTempsrc2;
+ mng_uint16p pTempdst;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y5, MNG_LC_START);
+#endif
+
+ pTempsrc1 = (mng_uint16p)pSrcline1; /* initialize pixel-loop */
+ pTempsrc2 = (mng_uint16p)pSrcline2;
+ pTempdst = (mng_uint16p)pDstline;
+
+ if (pTempsrc2) /* do we have a second line ? */
+ {
+ if (iS < (iM+1) / 2) /* top half ? */
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst++ = *pTempsrc1++; /* replicate color from top */
+ *pTempdst++ = *pTempsrc1++;
+ *pTempdst++ = *pTempsrc1++;
+
+ pTempsrc2 += 3;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ else
+ {
+ for (iX = 0; iX < iWidth; iX++)
+ {
+ *pTempdst++ = *pTempsrc2++; /* replicate color from bottom */
+ *pTempdst++ = *pTempsrc2++;
+ *pTempdst++ = *pTempsrc2++;
+
+ pTempsrc1 += 3;
+
+ if (*pTempsrc1 == *pTempsrc2) /* calculate the distances */
+ *pTempdst = *pTempsrc1;
+ else
+ mng_put_uint16 ((mng_uint8p)pTempdst,
+ (mng_uint16)( ( (2 * iS * ( (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc2)) -
+ (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) + iM) /
+ (iM * 2)) + (mng_int32)(mng_get_uint16 ((mng_uint8p)pTempsrc1)) ) );
+
+ pTempdst++;
+ pTempsrc1++;
+ pTempsrc2++;
+ }
+ }
+ }
+ else
+ { /* just repeat the entire line */
+ MNG_COPY (pTempdst, pTempsrc1, (iWidth << 3));
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_MAGNIFY_RGBA16_Y5, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_NO_16BIT_SUPPORT */
+#endif /* MNG_OPTIMIZE_FOOTPRINT_MAGN */
+#endif /* MNG_SKIPCHUNK_MAGN */
+
+/* ************************************************************************** */
+/* * * */
+/* * PAST composition routines - compose over/under with a target object * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_composeover_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8;
+ mng_uint8 iCr8, iCg8, iCb8, iCa8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEOVER_RGBA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iFGa8 = *(pWorkrow+3); /* get alpha values */
+ iBGa8 = *(pOutrow+3);
+
+ if (iFGa8) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa8 == 0xFF) || (iBGa8 == 0))
+ { /* then simply copy the values */
+ *pOutrow = *pWorkrow;
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = iFGa8;
+ }
+ else
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pOutrow+i), *(pWorkrow+i), iFGa8, *(pOutrow+i));
+ }
+#else
+ MNG_COMPOSE8 (*pOutrow, *pWorkrow, iFGa8, *pOutrow );
+ MNG_COMPOSE8 (*(pOutrow+1), *(pWorkrow+1), iFGa8, *(pOutrow+1));
+ MNG_COMPOSE8 (*(pOutrow+2), *(pWorkrow+2), iFGa8, *(pOutrow+2));
+#endif
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* here we'll have to blend */
+ MNG_BLEND8 (*pWorkrow, *(pWorkrow+1), *(pWorkrow+2), iFGa8,
+ *pOutrow, *(pOutrow+1), *(pOutrow+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pOutrow = iCr8;
+ *(pOutrow+1) = iCg8;
+ *(pOutrow+2) = iCb8;
+ *(pOutrow+3) = iCa8;
+ }
+ }
+ }
+
+ pOutrow += 4;
+ pWorkrow += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEOVER_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_composeover_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint16p pWorkrow;
+ mng_uint16p pOutrow;
+ mng_int32 iX;
+ mng_uint16 iFGa16, iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGa16, iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16, iCa16;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEOVER_RGBA16, MNG_LC_START);
+#endif
+
+ pWorkrow = (mng_uint16p)pData->pRGBArow;
+ pOutrow = (mng_uint16p)(pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize));
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+3));
+ iBGa16 = mng_get_uint16 ((mng_uint8p)(pOutrow+3));
+
+ if (iFGa16) /* any opacity at all ? */
+ { /* fully opaque or background fully transparent ? */
+ if ((iFGa16 == 0xFFFF) || (iBGa16 == 0))
+ { /* then simply copy the values */
+ *pOutrow = *pWorkrow;
+ *(pOutrow+1) = *(pWorkrow+1);
+ *(pOutrow+2) = *(pWorkrow+2);
+ *(pOutrow+3) = *(pWorkrow+3);
+ }
+ else
+ { /* get color values */
+ iFGr16 = mng_get_uint16 ((mng_uint8p)pWorkrow);
+ iFGg16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+1));
+ iFGb16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+2));
+ iBGr16 = mng_get_uint16 ((mng_uint8p)pOutrow);
+ iBGg16 = mng_get_uint16 ((mng_uint8p)(pOutrow+1));
+ iBGb16 = mng_get_uint16 ((mng_uint8p)(pOutrow+2));
+
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE16 (iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16 (iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16 (iFGb16, iFGb16, iFGa16, iBGb16);
+
+ mng_put_uint16 ((mng_uint8p)pOutrow, iFGr16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+1), iFGg16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+2), iFGb16);
+ /* alpha remains fully opaque !!! */
+ }
+ else
+ { /* here we'll have to blend */
+ MNG_BLEND16 (iFGr16, iFGg16, iFGb16, iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ mng_put_uint16 ((mng_uint8p)pOutrow, iCr16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+1), iCg16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+2), iCb16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+3), iCa16);
+ }
+ }
+ }
+
+ pOutrow += 4;
+ pWorkrow += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEOVER_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_composeunder_rgba8 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint8p pWorkrow;
+ mng_uint8p pOutrow;
+ mng_int32 iX;
+ mng_uint8 iFGa8, iBGa8;
+ mng_uint8 iCr8, iCg8, iCb8, iCa8;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEUNDER_RGBA8, MNG_LC_START);
+#endif
+
+ pWorkrow = pData->pRGBArow;
+ pOutrow = pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize);
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ {
+ iFGa8 = *(pOutrow+3); /* get alpha values */
+ iBGa8 = *(pWorkrow+3);
+ /* anything to do at all ? */
+ if ((iBGa8) && (iFGa8 != 0xFF))
+ {
+ if (iBGa8 == 0xFF) /* background fully opaque ? */
+ { /* do alpha composing */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_COMPOSE
+ int i;
+ for (i=2; i >= 0; i--)
+ {
+ MNG_COMPOSE8 (*(pOutrow+i), *(pOutrow+i), iFGa8, *(pWorkrow+i));
+ }
+#else
+ MNG_COMPOSE8 (*pOutrow, *pOutrow, iFGa8, *pWorkrow );
+ MNG_COMPOSE8 (*(pOutrow+1), *(pOutrow+1), iFGa8, *(pWorkrow+1));
+ MNG_COMPOSE8 (*(pOutrow+2), *(pOutrow+2), iFGa8, *(pWorkrow+2));
+#endif
+ *(pOutrow+3) = 0xFF; /* alpha becomes fully opaque !!! */
+ }
+ else
+ { /* here we'll have to blend */
+ MNG_BLEND8 (*pOutrow, *(pOutrow+1), *(pOutrow+2), iFGa8,
+ *pWorkrow, *(pWorkrow+1), *(pWorkrow+2), iBGa8,
+ iCr8, iCg8, iCb8, iCa8);
+ /* and return the composed values */
+ *pOutrow = iCr8;
+ *(pOutrow+1) = iCg8;
+ *(pOutrow+2) = iCb8;
+ *(pOutrow+3) = iCa8;
+ }
+ }
+
+ pOutrow += 4;
+ pWorkrow += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEUNDER_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_composeunder_rgba16 (mng_datap pData)
+{
+ mng_imagedatap pBuf = ((mng_imagep)pData->pStoreobj)->pImgbuf;
+ mng_uint16p pWorkrow;
+ mng_uint16p pOutrow;
+ mng_int32 iX;
+ mng_uint16 iFGa16, iFGr16, iFGg16, iFGb16;
+ mng_uint16 iBGa16, iBGr16, iBGg16, iBGb16;
+ mng_uint16 iCr16, iCg16, iCb16, iCa16;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEUNDER_RGBA16, MNG_LC_START);
+#endif
+
+ pWorkrow = (mng_uint16p)pData->pRGBArow;
+ pOutrow = (mng_uint16p)(pBuf->pImgdata + (pData->iRow * pBuf->iRowsize ) +
+ (pData->iCol * pBuf->iSamplesize));
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* get alpha values */
+ iFGa16 = mng_get_uint16 ((mng_uint8p)(pOutrow+3));
+ iBGa16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+3));
+ /* anything to do at all ? */
+ if ((iBGa16) && (iFGa16 != 0xFFFF))
+ {
+ iFGr16 = mng_get_uint16 ((mng_uint8p)pOutrow);
+ iFGg16 = mng_get_uint16 ((mng_uint8p)(pOutrow+1));
+ iFGb16 = mng_get_uint16 ((mng_uint8p)(pOutrow+2));
+ iBGr16 = mng_get_uint16 ((mng_uint8p)pWorkrow);
+ iBGg16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+1));
+ iBGb16 = mng_get_uint16 ((mng_uint8p)(pWorkrow+2));
+
+ if (iBGa16 == 0xFFFF) /* background fully opaque ? */
+ { /* do alpha composing */
+ MNG_COMPOSE16 (iFGr16, iFGr16, iFGa16, iBGr16);
+ MNG_COMPOSE16 (iFGg16, iFGg16, iFGa16, iBGg16);
+ MNG_COMPOSE16 (iFGb16, iFGb16, iFGa16, iBGb16);
+
+ mng_put_uint16 ((mng_uint8p)pOutrow, iFGr16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+1), iFGg16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+2), iFGb16);
+ *(pOutrow+3) = 0xFFFF; /* alpha becomes fully opaque !!! */
+ }
+ else
+ { /* here we'll have to blend */
+ MNG_BLEND16 (iFGr16, iFGg16, iFGb16, iFGa16,
+ iBGr16, iBGg16, iBGb16, iBGa16,
+ iCr16, iCg16, iCb16, iCa16);
+ /* and return the composed values */
+ mng_put_uint16 ((mng_uint8p)pOutrow, iCr16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+1), iCg16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+2), iCb16);
+ mng_put_uint16 ((mng_uint8p)(pOutrow+3), iCa16);
+ }
+ }
+
+ pOutrow += 4;
+ pWorkrow += 4;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_COMPOSEUNDER_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * PAST flip & tile routines - flip or tile a row of pixels * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_flip_rgba8 (mng_datap pData)
+{
+ mng_uint32p pWorkrow;
+ mng_uint32p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FLIP_RGBA8, MNG_LC_START);
+#endif
+ /* setup temp pointers */
+ pWorkrow = (mng_uint32p)pData->pRGBArow + pData->iRowsamples - 1;
+ pOutrow = (mng_uint32p)pData->pWorkrow;
+ /* swap original buffers */
+ pData->pWorkrow = pData->pRGBArow;
+ pData->pRGBArow = (mng_uint8p)pOutrow;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* let's flip */
+ *pOutrow = *pWorkrow;
+ pOutrow++;
+ pWorkrow--;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FLIP_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_flip_rgba16 (mng_datap pData)
+{
+ mng_uint32p pWorkrow;
+ mng_uint32p pOutrow;
+ mng_int32 iX;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FLIP_RGBA16, MNG_LC_START);
+#endif
+ /* setup temp pointers */
+ pWorkrow = (mng_uint32p)pData->pRGBArow + ((pData->iRowsamples - 1) << 1);
+ pOutrow = (mng_uint32p)pData->pWorkrow;
+ /* swap original buffers */
+ pData->pWorkrow = pData->pRGBArow;
+ pData->pRGBArow = (mng_uint8p)pOutrow;
+
+#ifdef MNG_DECREMENT_LOOPS
+ for (iX = pData->iRowsamples; iX > 0; iX--)
+#else
+ for (iX = 0; iX < pData->iRowsamples; iX++)
+#endif
+ { /* let's flip */
+ *pOutrow = *pWorkrow;
+ *(pOutrow + 1) = *(pWorkrow + 1);
+
+ pOutrow += 2;
+ pWorkrow -= 2;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_FLIP_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode mng_tile_rgba8 (mng_datap pData)
+{
+ mng_uint32p pWorkrow;
+ mng_uint32p pOutrow;
+ mng_int32 iX;
+ mng_uint32 iZ, iMax;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_TILE_RGBA8, MNG_LC_START);
+#endif
+
+ iZ = pData->iSourcel; /* indent ? */
+ /* what's our source-length */
+ iMax = ((mng_imagep)pData->pRetrieveobj)->pImgbuf->iWidth;
+ /* setup temp pointers */
+ pWorkrow = (mng_uint32p)pData->pRGBArow + iZ;
+ pOutrow = (mng_uint32p)pData->pWorkrow;
+ /* swap original buffers */
+ pData->pWorkrow = pData->pRGBArow;
+ pData->pRGBArow = (mng_uint8p)pOutrow;
+
+ for (iX = pData->iDestl; iX < pData->iDestr; iX++)
+ { /* tiiiile */
+ *pOutrow = *pWorkrow;
+
+ pWorkrow++;
+ pOutrow++;
+ iZ++;
+
+ if (iZ >= iMax) /* end of source ? */
+ {
+ iZ = 0;
+ pWorkrow = (mng_uint32p)pData->pWorkrow;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_TILE_RGBA8, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_tile_rgba16 (mng_datap pData)
+{
+ mng_uint32p pWorkrow;
+ mng_uint32p pOutrow;
+ mng_int32 iX;
+ mng_uint32 iZ, iMax;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_TILE_RGBA16, MNG_LC_START);
+#endif
+
+ iZ = pData->iSourcel; /* indent ? */
+ /* what's our source-length */
+ iMax = ((mng_imagep)pData->pRetrieveobj)->pImgbuf->iWidth;
+ /* setup temp pointers */
+ pWorkrow = (mng_uint32p)pData->pRGBArow + (iZ << 1);
+ pOutrow = (mng_uint32p)pData->pWorkrow;
+ /* swap original buffers */
+ pData->pWorkrow = pData->pRGBArow;
+ pData->pRGBArow = (mng_uint8p)pOutrow;
+
+ for (iX = pData->iDestl; iX < pData->iDestr; iX++)
+ { /* tiiiile */
+ *pOutrow = *pWorkrow;
+ *(pOutrow + 1) = *(pWorkrow + 1);
+
+ pWorkrow += 2;
+ pOutrow += 2;
+ iZ++;
+
+ if (iZ >= iMax) /* end of source ? */
+ {
+ iZ = 0;
+ pWorkrow = (mng_uint32p)pData->pWorkrow;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_TILE_RGBA16, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SKIPCHUNK_PAST */
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_DISPLAY_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_pixels.h b/Source/LibMNG/libmng_pixels.h
new file mode 100644
index 0000000..5a0281e
--- /dev/null
+++ b/Source/LibMNG/libmng_pixels.h
@@ -0,0 +1,1147 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_pixels.h copyright (c) 2000-2006 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Pixel-row management routines (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the pixel-row management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.5.2 - 05/22/2000 - G.Juyn * */
+/* * - added some JNG definitions * */
+/* * - added delta-image row-processing routines * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - added support for RGB8_A8 canvasstyle * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN support * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added optional support for bKGD for PNG images * */
+/* * - added support for JDAA * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - implemented delayed delta-processing * */
+/* * * */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - added "new" MAGN methods 3, 4 & 5 * */
+/* * * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/16/2002 - G.Juyn * */
+/* * - completed MAGN support (16-bit functions) * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added compose over/under routines for PAST processing * */
+/* * - added flip & tile routines for PAST processing * */
+/* * * */
+/* * 1.0.6 - 03/09/2003 - G.Juyn * */
+/* * - hiding 12-bit JPEG stuff * */
+/* * 1.0.6 - 05/11/2003 - G. Juyn * */
+/* * - added conditionals around canvas update routines * */
+/* * 1.0.6 - 06/09/2003 - G. R-P * */
+/* * - added conditionals around 8-bit magn routines * */
+/* * 1.0.6 - 07/07/2003 - G. R-P * */
+/* * - removed conditionals around 8-bit magn routines * */
+/* * - added conditionals around 16-bit and delta-PNG * */
+/* * supporting code * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added SKIPCHUNK conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/18/2003 - G.R-P * */
+/* * - added conditionals around 1, 2, and 4-bit prototypes * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 12/06/2003 - R.A * */
+/* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * * */
+/* * 1.0.9 - 10/10/2004 - G.R-P. * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * * */
+/* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
+/* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_pixels_h_
+#define _libmng_pixels_h_
+
+/* ************************************************************************** */
+/* * * */
+/* * Progressive display check - checks to see if progressive display is * */
+/* * in order & indicates so * */
+/* * * */
+/* * The routine is called after a call to one of the display_xxx routines * */
+/* * if appropriate * */
+/* * * */
+/* * The refresh is warrented in the read_chunk routine (mng_read.c) * */
+/* * and only during read&display processing, since there's not much point * */
+/* * doing it from memory! * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_display_progressive_check (mng_datap pData);
+
+/* ************************************************************************** */
+/* * * */
+/* * Display routines - convert rowdata (which is already color-corrected) * */
+/* * to the output canvas, respecting any transparency information * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCANVAS_RGB8
+mng_retcode mng_display_rgb8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8
+mng_retcode mng_display_rgba8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8_PM
+mng_retcode mng_display_rgba8_pm (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8
+mng_retcode mng_display_argb8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8_PM
+mng_retcode mng_display_argb8_pm (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGB8_A8
+mng_retcode mng_display_rgb8_a8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+mng_retcode mng_display_bgr8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+mng_retcode mng_display_bgrx8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8
+mng_retcode mng_display_bgra8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8_PM
+mng_retcode mng_display_bgra8_pm (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8
+mng_retcode mng_display_abgr8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8_PM
+mng_retcode mng_display_abgr8_pm (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+mng_retcode mng_display_rgb565 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA565
+mng_retcode mng_display_rgba565 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+mng_retcode mng_display_bgr565 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA565
+mng_retcode mng_display_bgra565 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565_A8
+mng_retcode mng_display_bgr565_a8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGB555
+mng_retcode mng_display_rgb555 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR555
+mng_retcode mng_display_bgr555 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Background restore routines - restore the background with info from * */
+/* * the BACK and/or bKGD chunk and/or the app's background canvas * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_restore_bkgd_backimage (mng_datap pData);
+mng_retcode mng_restore_bkgd_backcolor (mng_datap pData);
+mng_retcode mng_restore_bkgd_bkgd (mng_datap pData);
+mng_retcode mng_restore_bkgd_bgcolor (mng_datap pData);
+#ifndef MNG_SKIPCANVAS_RGB8
+mng_retcode mng_restore_bkgd_rgb8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+mng_retcode mng_restore_bkgd_bgr8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+mng_retcode mng_restore_bkgd_bgrx8 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+mng_retcode mng_restore_bkgd_rgb565 (mng_datap pData);
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+mng_retcode mng_restore_bkgd_bgr565 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row retrieval routines - retrieve processed & uncompressed row-data * */
+/* * from the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_retrieve_g8 (mng_datap pData);
+mng_retcode mng_retrieve_rgb8 (mng_datap pData);
+mng_retcode mng_retrieve_idx8 (mng_datap pData);
+mng_retcode mng_retrieve_ga8 (mng_datap pData);
+mng_retcode mng_retrieve_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_retrieve_g16 (mng_datap pData);
+mng_retcode mng_retrieve_ga16 (mng_datap pData);
+mng_retcode mng_retrieve_rgb16 (mng_datap pData);
+mng_retcode mng_retrieve_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row storage routines - store processed & uncompressed row-data * */
+/* * into the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_g1 (mng_datap pData);
+mng_retcode mng_store_g2 (mng_datap pData);
+mng_retcode mng_store_g4 (mng_datap pData);
+mng_retcode mng_store_idx1 (mng_datap pData);
+mng_retcode mng_store_idx2 (mng_datap pData);
+mng_retcode mng_store_idx4 (mng_datap pData);
+#endif
+mng_retcode mng_store_idx8 (mng_datap pData);
+mng_retcode mng_store_rgb8 (mng_datap pData);
+mng_retcode mng_store_g8 (mng_datap pData);
+mng_retcode mng_store_ga8 (mng_datap pData);
+mng_retcode mng_store_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_g16 (mng_datap pData);
+mng_retcode mng_store_ga16 (mng_datap pData);
+mng_retcode mng_store_rgb16 (mng_datap pData);
+mng_retcode mng_store_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row storage routines (JPEG) - store processed & uncompressed row-data * */
+/* * into the current "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_store_jpeg_g8 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb8 (mng_datap pData);
+mng_retcode mng_store_jpeg_ga8 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgba8 (mng_datap pData);
+
+#ifdef MNG_SUPPORT_JPEG12
+mng_retcode mng_store_jpeg_g12 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb12 (mng_datap pData);
+mng_retcode mng_store_jpeg_ga12 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgba12 (mng_datap pData);
+#endif
+
+mng_retcode mng_store_jpeg_g8_alpha (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb8_alpha (mng_datap pData);
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_g8_a1 (mng_datap pData);
+mng_retcode mng_store_jpeg_g8_a2 (mng_datap pData);
+mng_retcode mng_store_jpeg_g8_a4 (mng_datap pData);
+#endif
+mng_retcode mng_store_jpeg_g8_a8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_g8_a16 (mng_datap pData);
+#endif
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb8_a1 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb8_a2 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb8_a4 (mng_datap pData);
+#endif
+mng_retcode mng_store_jpeg_rgb8_a8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb8_a16 (mng_datap pData);
+#endif
+
+#ifdef MNG_SUPPORT_JPEG12
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_g12_a1 (mng_datap pData);
+mng_retcode mng_store_jpeg_g12_a2 (mng_datap pData);
+mng_retcode mng_store_jpeg_g12_a4 (mng_datap pData);
+#endif
+mng_retcode mng_store_jpeg_g12_a8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_g12_a16 (mng_datap pData);
+#endif
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb12_a1 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb12_a2 (mng_datap pData);
+mng_retcode mng_store_jpeg_rgb12_a4 (mng_datap pData);
+#endif
+mng_retcode mng_store_jpeg_rgb12_a8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_store_jpeg_rgb12_a16 (mng_datap pData);
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - apply the processed & uncompressed row-data * */
+/* * onto the target "object" * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_g1 (mng_datap pData);
+mng_retcode mng_delta_g2 (mng_datap pData);
+mng_retcode mng_delta_g4 (mng_datap pData);
+#endif
+mng_retcode mng_delta_g8 (mng_datap pData);
+mng_retcode mng_delta_g16 (mng_datap pData);
+mng_retcode mng_delta_rgb8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgb16 (mng_datap pData);
+#endif
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_idx1 (mng_datap pData);
+mng_retcode mng_delta_idx2 (mng_datap pData);
+mng_retcode mng_delta_idx4 (mng_datap pData);
+#endif
+mng_retcode mng_delta_idx8 (mng_datap pData);
+mng_retcode mng_delta_ga8 (mng_datap pData);
+mng_retcode mng_delta_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16 (mng_datap pData);
+mng_retcode mng_delta_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - apply the source row onto the target * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_delta_g1_g1 (mng_datap pData);
+mng_retcode mng_delta_g2_g2 (mng_datap pData);
+mng_retcode mng_delta_g4_g4 (mng_datap pData);
+#endif
+mng_retcode mng_delta_g8_g8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_g16_g16 (mng_datap pData);
+#endif
+mng_retcode mng_delta_ga8_ga8 (mng_datap pData);
+mng_retcode mng_delta_ga8_g8 (mng_datap pData);
+mng_retcode mng_delta_ga8_a8 (mng_datap pData);
+mng_retcode mng_delta_rgba8_rgb8 (mng_datap pData);
+mng_retcode mng_delta_rgba8_a8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_ga16_ga16 (mng_datap pData);
+mng_retcode mng_delta_ga16_g16 (mng_datap pData);
+mng_retcode mng_delta_ga16_a16 (mng_datap pData);
+mng_retcode mng_delta_rgba16_a16 (mng_datap pData);
+mng_retcode mng_delta_rgba16_rgb16 (mng_datap pData);
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+mng_retcode mng_delta_rgb8_rgb8 (mng_datap pData); /* Used for PAST */
+mng_retcode mng_delta_rgba8_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_delta_rgb16_rgb16 (mng_datap pData);
+mng_retcode mng_delta_rgba16_rgba16 (mng_datap pData);
+#endif
+
+#ifndef MNG_NO_DELTA_PNG
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - scale the delta to bitdepth of target * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g1_g2 (mng_datap pData);
+mng_retcode mng_scale_g1_g4 (mng_datap pData);
+mng_retcode mng_scale_g1_g8 (mng_datap pData);
+mng_retcode mng_scale_g2_g4 (mng_datap pData);
+mng_retcode mng_scale_g2_g8 (mng_datap pData);
+mng_retcode mng_scale_g4_g8 (mng_datap pData);
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g1_g16 (mng_datap pData);
+mng_retcode mng_scale_g2_g16 (mng_datap pData);
+mng_retcode mng_scale_g4_g16 (mng_datap pData);
+#endif
+mng_retcode mng_scale_g8_g16 (mng_datap pData);
+mng_retcode mng_scale_ga8_ga16 (mng_datap pData);
+mng_retcode mng_scale_rgb8_rgb16 (mng_datap pData);
+mng_retcode mng_scale_rgba8_rgba16 (mng_datap pData);
+#endif
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g2_g1 (mng_datap pData);
+mng_retcode mng_scale_g4_g1 (mng_datap pData);
+mng_retcode mng_scale_g8_g1 (mng_datap pData);
+mng_retcode mng_scale_g4_g2 (mng_datap pData);
+mng_retcode mng_scale_g8_g2 (mng_datap pData);
+mng_retcode mng_scale_g8_g4 (mng_datap pData);
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_scale_g16_g1 (mng_datap pData);
+mng_retcode mng_scale_g16_g2 (mng_datap pData);
+mng_retcode mng_scale_g16_g4 (mng_datap pData);
+#endif
+mng_retcode mng_scale_g16_g8 (mng_datap pData);
+mng_retcode mng_scale_ga16_ga8 (mng_datap pData);
+mng_retcode mng_scale_rgb16_rgb8 (mng_datap pData);
+mng_retcode mng_scale_rgba16_rgba8 (mng_datap pData);
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image bit routines - promote bit_depth * */
+/* * * */
+/* ************************************************************************** */
+
+mng_uint8 mng_promote_replicate_1_2 (mng_uint8 iB);
+mng_uint8 mng_promote_replicate_1_4 (mng_uint8 iB);
+mng_uint8 mng_promote_replicate_1_8 (mng_uint8 iB);
+mng_uint8 mng_promote_replicate_2_4 (mng_uint8 iB);
+mng_uint8 mng_promote_replicate_2_8 (mng_uint8 iB);
+mng_uint8 mng_promote_replicate_4_8 (mng_uint8 iB);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_replicate_1_16 (mng_uint8 iB);
+mng_uint16 mng_promote_replicate_2_16 (mng_uint8 iB);
+mng_uint16 mng_promote_replicate_4_16 (mng_uint8 iB);
+mng_uint16 mng_promote_replicate_8_16 (mng_uint8 iB);
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DELTA_PNG
+mng_uint8 mng_promote_zerofill_1_2 (mng_uint8 iB);
+mng_uint8 mng_promote_zerofill_1_4 (mng_uint8 iB);
+mng_uint8 mng_promote_zerofill_1_8 (mng_uint8 iB);
+mng_uint8 mng_promote_zerofill_2_4 (mng_uint8 iB);
+mng_uint8 mng_promote_zerofill_2_8 (mng_uint8 iB);
+mng_uint8 mng_promote_zerofill_4_8 (mng_uint8 iB);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_uint16 mng_promote_zerofill_1_16 (mng_uint8 iB);
+mng_uint16 mng_promote_zerofill_2_16 (mng_uint8 iB);
+mng_uint16 mng_promote_zerofill_4_16 (mng_uint8 iB);
+mng_uint16 mng_promote_zerofill_8_16 (mng_uint8 iB);
+#endif
+#endif /* MNG_NO_DELTA_PNG */
+
+/* ************************************************************************** */
+/* * * */
+/* * Delta-image row routines - promote color_type * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_promote_g8_g8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_g16 (mng_datap pData);
+mng_retcode mng_promote_g16_g16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_g8_ga8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_ga16 (mng_datap pData);
+mng_retcode mng_promote_g16_ga16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_g8_rgb8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_rgb16 (mng_datap pData);
+mng_retcode mng_promote_g16_rgb16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_g8_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_g8_rgba16 (mng_datap pData);
+mng_retcode mng_promote_g16_rgba16 (mng_datap pData);
+
+mng_retcode mng_promote_ga8_ga16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_ga8_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_ga8_rgba16 (mng_datap pData);
+mng_retcode mng_promote_ga16_rgba16 (mng_datap pData);
+#endif
+
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_rgb8_rgb16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_rgb8_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_rgb8_rgba16 (mng_datap pData);
+mng_retcode mng_promote_rgb16_rgba16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_idx8_rgb8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_idx8_rgb16 (mng_datap pData);
+#endif
+
+mng_retcode mng_promote_idx8_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_promote_idx8_rgba16 (mng_datap pData);
+
+mng_retcode mng_promote_rgba8_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing routines - convert uncompressed data from zlib to * */
+/* * managable row-data which serves as input to the color-management * */
+/* * routines * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_process_g1 (mng_datap pData);
+mng_retcode mng_process_g2 (mng_datap pData);
+mng_retcode mng_process_g4 (mng_datap pData);
+#endif
+mng_retcode mng_process_g8 (mng_datap pData);
+mng_retcode mng_process_rgb8 (mng_datap pData);
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_process_idx1 (mng_datap pData);
+mng_retcode mng_process_idx2 (mng_datap pData);
+mng_retcode mng_process_idx4 (mng_datap pData);
+#endif
+mng_retcode mng_process_idx8 (mng_datap pData);
+mng_retcode mng_process_ga8 (mng_datap pData);
+mng_retcode mng_process_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_process_g16 (mng_datap pData);
+mng_retcode mng_process_ga16 (mng_datap pData);
+mng_retcode mng_process_rgb16 (mng_datap pData);
+mng_retcode mng_process_rgba16 (mng_datap pData);
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing initialization routines - set up the variables needed * */
+/* * to process uncompressed row-data * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_g1_i (mng_datap pData);
+mng_retcode mng_init_g2_i (mng_datap pData);
+mng_retcode mng_init_g4_i (mng_datap pData);
+#endif
+mng_retcode mng_init_g8_i (mng_datap pData);
+mng_retcode mng_init_rgb8_i (mng_datap pData);
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_idx1_i (mng_datap pData);
+mng_retcode mng_init_idx2_i (mng_datap pData);
+mng_retcode mng_init_idx4_i (mng_datap pData);
+#endif
+mng_retcode mng_init_idx8_i (mng_datap pData);
+mng_retcode mng_init_ga8_i (mng_datap pData);
+mng_retcode mng_init_rgba8_i (mng_datap pData);
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_g1_ni (mng_datap pData);
+mng_retcode mng_init_g2_ni (mng_datap pData);
+mng_retcode mng_init_g4_ni (mng_datap pData);
+#endif
+mng_retcode mng_init_g8_ni (mng_datap pData);
+mng_retcode mng_init_rgb8_ni (mng_datap pData);
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_idx1_ni (mng_datap pData);
+mng_retcode mng_init_idx2_ni (mng_datap pData);
+mng_retcode mng_init_idx4_ni (mng_datap pData);
+#endif
+mng_retcode mng_init_idx8_ni (mng_datap pData);
+mng_retcode mng_init_ga8_ni (mng_datap pData);
+mng_retcode mng_init_rgba8_ni (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_g16_i (mng_datap pData);
+mng_retcode mng_init_rgb16_i (mng_datap pData);
+mng_retcode mng_init_ga16_i (mng_datap pData);
+mng_retcode mng_init_rgba16_i (mng_datap pData);
+mng_retcode mng_init_g16_ni (mng_datap pData);
+mng_retcode mng_init_rgb16_ni (mng_datap pData);
+mng_retcode mng_init_ga16_ni (mng_datap pData);
+mng_retcode mng_init_rgba16_ni (mng_datap pData);
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Row processing initialization routines (JPEG) - set up the variables * */
+/* * needed to process uncompressed row-data * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+#ifdef MNG_INCLUDE_JNG
+#ifndef MNG_NO_1_2_4BIT_SUPPORT
+mng_retcode mng_init_jpeg_a1_ni (mng_datap pData);
+mng_retcode mng_init_jpeg_a2_ni (mng_datap pData);
+mng_retcode mng_init_jpeg_a4_ni (mng_datap pData);
+#endif
+mng_retcode mng_init_jpeg_a8_ni (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_init_jpeg_a16_ni (mng_datap pData);
+#endif
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * General row processing routines * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_init_rowproc (mng_datap pData);
+mng_retcode mng_next_row (mng_datap pData);
+#ifdef MNG_INCLUDE_JNG
+mng_retcode mng_next_jpeg_alpharow (mng_datap pData);
+mng_retcode mng_next_jpeg_row (mng_datap pData);
+#endif
+mng_retcode mng_cleanup_rowproc (mng_datap pData);
+
+/* ************************************************************************** */
+/* * * */
+/* * Magnification row routines - apply magnification transforms * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+mng_retcode mng_magnify_g8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+#endif
+mng_retcode mng_magnify_rgba8_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+mng_retcode mng_magnify_g8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga8_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+#endif
+mng_retcode mng_magnify_rgba8_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba8_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+
+/* ************************************************************************** */
+#ifndef MNG_NO_16BIT_SUPPORT
+#ifndef MNG_OPTIMIZE_FOOTPRINT_MAGN
+mng_retcode mng_magnify_g16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_x1 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_x2 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_x3 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_x4 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_x5 (mng_datap pData,
+ mng_uint16 iMX,
+ mng_uint16 iML,
+ mng_uint16 iMR,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline,
+ mng_uint8p pDstline);
+
+mng_retcode mng_magnify_g16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_g16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgb16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_ga16_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_y1 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_y2 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_y3 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_y4 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+mng_retcode mng_magnify_rgba16_y5 (mng_datap pData,
+ mng_int32 iS,
+ mng_int32 iM,
+ mng_uint32 iWidth,
+ mng_uint8p pSrcline1,
+ mng_uint8p pSrcline2,
+ mng_uint8p pDstline);
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * PAST composition routines - compose over/under with a target object * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode mng_composeover_rgba8 (mng_datap pData);
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_composeunder_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_composeover_rgba16 (mng_datap pData);
+mng_retcode mng_composeunder_rgba16 (mng_datap pData);
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * PAST flip & tile routines - flip or tile a row of pixels * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef MNG_SKIPCHUNK_PAST
+mng_retcode mng_flip_rgba8 (mng_datap pData);
+mng_retcode mng_tile_rgba8 (mng_datap pData);
+#ifndef MNG_NO_16BIT_SUPPORT
+mng_retcode mng_flip_rgba16 (mng_datap pData);
+mng_retcode mng_tile_rgba16 (mng_datap pData);
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#endif /* _libmng_pixels_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_prop_xs.c b/Source/LibMNG/libmng_prop_xs.c
new file mode 100644
index 0000000..88e416d
--- /dev/null
+++ b/Source/LibMNG/libmng_prop_xs.c
@@ -0,0 +1,2799 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_prop_xs.c copyright (c) 2000-2006 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : property get/set interface (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the property get/set functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - fixed calling convention * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added set_outputprofile2 & set_srgbprofile2 * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - changed inclusion of cms-routines * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added support for get/set default zlib/IJG parms * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed up punctuation (contribution by Tim Rowley) * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - added support for RGB8_A8 canvasstyle * */
+/* * * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added get/set for speedtype to facilitate testing * */
+/* * - added get for imagelevel during processtext callback * */
+/* * 0.5.3 - 06/26/2000 - G.Juyn * */
+/* * - changed userdata variable to mng_ptr * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - fixed incompatible return-types * */
+/* * * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added get routines for internal display variables * */
+/* * - added get/set routines for suspensionmode variable * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added get/set routines for sectionbreak variable * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - added status_xxxx functions * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added functions to retrieve PNG/JNG specific header-info * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - added get/set for bKGD preference setting * */
+/* * 0.9.3 - 10/21/2000 - G.Juyn * */
+/* * - added get function for interlace/progressive display * */
+/* * * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.3 - 08/06/2001 - G.Juyn * */
+/* * - added get function for last processed BACK chunk * */
+/* * * */
+/* * 1.0.4 - 06/22/2002 - G.Juyn * */
+/* * - B495442 - invalid returnvalue in mng_get_suspensionmode * */
+/* * * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * * */
+/* * 1.0.6 - 05/11/2003 - G. Juyn * */
+/* * - added conditionals around canvas update routines * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added conditionals around some JNG-supporting code * */
+/* * 1.0.6 - 07/11/2003 - G.R-P * */
+/* * - added conditionals zlib and jpeg property accessors * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added conditionals around various unused functions * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 12/06/2003 - R.A * */
+/* * - added CANVAS_RGBA565 and CANVAS_BGRA565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 03/07/2004 - G.R-P. * */
+/* * - put gamma, cms-related functions inside #ifdef * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * * */
+/* * 1.0.9 - 09/18/2004 - G.R-P. * */
+/* * - added some MNG_SUPPORT_WRITE conditionals * */
+/* * 1.0.9 - 10/03/2004 - G.Juyn * */
+/* * - added function to retrieve current FRAM delay * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* * 1.0.10 - 03/07/2006 - (thanks to W. Manthey) * */
+/* * - added CANVAS_RGB555 and CANVAS_BGR555 * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_objects.h"
+#include "libmng_memory.h"
+#include "libmng_cms.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Property set functions * */
+/* * * */
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_userdata (mng_handle hHandle,
+ mng_ptr pUserdata)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_USERDATA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->pUserdata = pUserdata;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_USERDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_canvasstyle (mng_handle hHandle,
+ mng_uint32 iStyle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CANVASSTYLE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ switch (iStyle)
+ {
+#ifndef MNG_SKIPCANVAS_RGB8
+ case MNG_CANVAS_RGB8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8
+ case MNG_CANVAS_RGBA8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA8_PM
+ case MNG_CANVAS_RGBA8_PM: break;
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8
+ case MNG_CANVAS_ARGB8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_ARGB8_PM
+ case MNG_CANVAS_ARGB8_PM: break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGB8_A8
+ case MNG_CANVAS_RGB8_A8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+ case MNG_CANVAS_BGR8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+ case MNG_CANVAS_BGRX8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8
+ case MNG_CANVAS_BGRA8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA8_PM
+ case MNG_CANVAS_BGRA8_PM: break;
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8
+ case MNG_CANVAS_ABGR8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_ABGR8_PM
+ case MNG_CANVAS_ABGR8_PM: break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+ case MNG_CANVAS_RGB565 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGBA565
+ case MNG_CANVAS_RGBA565 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+ case MNG_CANVAS_BGR565 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGRA565
+ case MNG_CANVAS_BGRA565 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565_A8
+ case MNG_CANVAS_BGR565_A8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGB555
+ case MNG_CANVAS_RGB555 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR555
+ case MNG_CANVAS_BGR555 : break;
+#endif
+/* case MNG_CANVAS_RGB16 : break; */
+/* case MNG_CANVAS_RGBA16 : break; */
+/* case MNG_CANVAS_ARGB16 : break; */
+/* case MNG_CANVAS_BGR16 : break; */
+/* case MNG_CANVAS_BGRA16 : break; */
+/* case MNG_CANVAS_ABGR16 : break; */
+/* case MNG_CANVAS_INDEX8 : break; */
+/* case MNG_CANVAS_INDEXA8 : break; */
+/* case MNG_CANVAS_AINDEX8 : break; */
+/* case MNG_CANVAS_GRAY8 : break; */
+/* case MNG_CANVAS_GRAY16 : break; */
+/* case MNG_CANVAS_GRAYA8 : break; */
+/* case MNG_CANVAS_GRAYA16 : break; */
+/* case MNG_CANVAS_AGRAY8 : break; */
+/* case MNG_CANVAS_AGRAY16 : break; */
+/* case MNG_CANVAS_DX15 : break; */
+/* case MNG_CANVAS_DX16 : break; */
+ default : { MNG_ERROR (((mng_datap)hHandle), MNG_INVALIDCNVSTYLE) };
+ }
+
+ ((mng_datap)hHandle)->iCanvasstyle = iStyle;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CANVASSTYLE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_bkgdstyle (mng_handle hHandle,
+ mng_uint32 iStyle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_BKGDSTYLE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ switch (iStyle) /* alpha-modes not supported */
+ {
+#ifndef MNG_SKIPCANVAS_RGB8
+ case MNG_CANVAS_RGB8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR8
+ case MNG_CANVAS_BGR8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGRX8
+ case MNG_CANVAS_BGRX8 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_RGB565
+ case MNG_CANVAS_RGB565 : break;
+#endif
+#ifndef MNG_SKIPCANVAS_BGR565
+ case MNG_CANVAS_BGR565 : break;
+#endif
+/* case MNG_CANVAS_RGB16 : break; */
+/* case MNG_CANVAS_BGR16 : break; */
+/* case MNG_CANVAS_INDEX8 : break; */
+/* case MNG_CANVAS_GRAY8 : break; */
+/* case MNG_CANVAS_GRAY16 : break; */
+/* case MNG_CANVAS_DX15 : break; */
+/* case MNG_CANVAS_DX16 : break; */
+ default : MNG_ERROR (((mng_datap)hHandle), MNG_INVALIDCNVSTYLE);
+ }
+
+ ((mng_datap)hHandle)->iBkgdstyle = iStyle;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_BKGDSTYLE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_bgcolor (mng_handle hHandle,
+ mng_uint16 iRed,
+ mng_uint16 iGreen,
+ mng_uint16 iBlue)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_BGCOLOR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iBGred = iRed;
+ ((mng_datap)hHandle)->iBGgreen = iGreen;
+ ((mng_datap)hHandle)->iBGblue = iBlue;
+ ((mng_datap)hHandle)->bUseBKGD = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_BGCOLOR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_usebkgd (mng_handle hHandle,
+ mng_bool bUseBKGD)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_USEBKGD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bUseBKGD = bUseBKGD;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_USEBKGD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_storechunks (mng_handle hHandle,
+ mng_bool bStorechunks)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_STORECHUNKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bStorechunks = bStorechunks;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_STORECHUNKS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_sectionbreaks (mng_handle hHandle,
+ mng_bool bSectionbreaks)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SECTIONBREAKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bSectionbreaks = bSectionbreaks;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SECTIONBREAKS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_cacheplayback (mng_handle hHandle,
+ mng_bool bCacheplayback)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CACHEPLAYBACK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ if (((mng_datap)hHandle)->bHasheader)
+ MNG_ERROR (((mng_datap)hHandle), MNG_FUNCTIONINVALID);
+
+ ((mng_datap)hHandle)->bCacheplayback = bCacheplayback;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CACHEPLAYBACK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_doprogressive (mng_handle hHandle,
+ mng_bool bDoProgressive)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DOPROGRESSIVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ ((mng_datap)hHandle)->bDoProgressive = bDoProgressive;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DOPROGRESSIVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_crcmode (mng_handle hHandle,
+ mng_uint32 iCrcmode)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CRCMODE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ ((mng_datap)hHandle)->iCrcmode = iCrcmode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_CRCMODE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_set_srgb (mng_handle hHandle,
+ mng_bool bIssRGB)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bIssRGB = bIssRGB;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode MNG_DECL mng_set_outputprofile (mng_handle hHandle,
+ mng_pchar zFilename)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTPROFILE, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf2) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf2);
+ /* allocate new CMS profile handle */
+ pData->hProf2 = mnglcms_createfileprofile (zFilename);
+
+ if (!pData->hProf2) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTPROFILE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_SKIPCHUNK_iCCP
+mng_retcode MNG_DECL mng_set_outputprofile2 (mng_handle hHandle,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTPROFILE2, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf2) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf2);
+ /* allocate new CMS profile handle */
+ pData->hProf2 = mnglcms_creatememprofile (iProfilesize, pProfile);
+
+ if (!pData->hProf2) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTPROFILE2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_outputsrgb (mng_handle hHandle)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTSRGB, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf2) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf2);
+ /* allocate new CMS profile handle */
+ pData->hProf2 = mnglcms_createsrgbprofile ();
+
+ if (!pData->hProf2) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_OUTPUTSRGB, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_set_srgbprofile (mng_handle hHandle,
+ mng_pchar zFilename)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBPROFILE2, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf3) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf3);
+ /* allocate new CMS profile handle */
+ pData->hProf3 = mnglcms_createfileprofile (zFilename);
+
+ if (!pData->hProf3) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBPROFILE2, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_set_srgbprofile2 (mng_handle hHandle,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBPROFILE, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf3) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf3);
+ /* allocate new CMS profile handle */
+ pData->hProf3 = mnglcms_creatememprofile (iProfilesize, pProfile);
+
+ if (!pData->hProf3) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBPROFILE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_srgbimplicit (mng_handle hHandle)
+{
+#ifdef MNG_INCLUDE_LCMS
+ mng_datap pData;
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBIMPLICIT, MNG_LC_START);
+#endif
+
+#ifdef MNG_INCLUDE_LCMS
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle; /* address the structure */
+
+ if (pData->hProf3) /* previously defined ? */
+ mnglcms_freeprofile (pData->hProf3);
+ /* allocate new CMS profile handle */
+ pData->hProf3 = mnglcms_createsrgbprofile ();
+
+ if (!pData->hProf3) /* handle error ? */
+ MNG_ERRORL (pData, MNG_LCMS_NOHANDLE);
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SRGBIMPLICIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_retcode MNG_DECL mng_set_viewgamma (mng_handle hHandle,
+ mng_float dGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_VIEWGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dViewgamma = dGamma;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_VIEWGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_displaygamma (mng_handle hHandle,
+ mng_float dGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DISPLAYGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dDisplaygamma = dGamma;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DISPLAYGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_dfltimggamma (mng_handle hHandle,
+ mng_float dGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DFLTIMGGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dDfltimggamma = dGamma;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DFLTIMGGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_retcode MNG_DECL mng_set_viewgammaint (mng_handle hHandle,
+ mng_uint32 iGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_VIEWGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dViewgamma = (mng_float)iGamma / 100000;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_VIEWGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_displaygammaint (mng_handle hHandle,
+ mng_uint32 iGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DISPLAYGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dDisplaygamma = (mng_float)iGamma / 100000;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DISPLAYGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DFLT_INFO
+mng_retcode MNG_DECL mng_set_dfltimggammaint (mng_handle hHandle,
+ mng_uint32 iGamma)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DFLTIMGGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->dDfltimggamma = (mng_float)iGamma / 100000;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_DFLTIMGGAMMA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIP_MAXCANVAS
+mng_retcode MNG_DECL mng_set_maxcanvaswidth (mng_handle hHandle,
+ mng_uint32 iMaxwidth)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASWIDTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iMaxwidth = iMaxwidth;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASWIDTH, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_maxcanvasheight (mng_handle hHandle,
+ mng_uint32 iMaxheight)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASHEIGHT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iMaxheight = iMaxheight;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASHEIGHT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_set_maxcanvassize (mng_handle hHandle,
+ mng_uint32 iMaxwidth,
+ mng_uint32 iMaxheight)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASSIZE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iMaxwidth = iMaxwidth;
+ ((mng_datap)hHandle)->iMaxheight = iMaxheight;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_MAXCANVASSIZE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_level (mng_handle hHandle,
+ mng_int32 iZlevel)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_LEVEL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iZlevel = iZlevel;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_LEVEL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_method (mng_handle hHandle,
+ mng_int32 iZmethod)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_METHOD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iZmethod = iZmethod;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_METHOD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_windowbits (mng_handle hHandle,
+ mng_int32 iZwindowbits)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_WINDOWBITS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iZwindowbits = iZwindowbits;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_WINDOWBITS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_memlevel (mng_handle hHandle,
+ mng_int32 iZmemlevel)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_MEMLEVEL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iZmemlevel = iZmemlevel;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_MEMLEVEL, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_strategy (mng_handle hHandle,
+ mng_int32 iZstrategy)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_STRATEGY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iZstrategy = iZstrategy;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_STRATEGY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_zlib_maxidat (mng_handle hHandle,
+ mng_uint32 iMaxIDAT)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_MAXIDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iMaxIDAT = iMaxIDAT;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_ZLIB_MAXIDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_dctmethod (mng_handle hHandle,
+ mngjpeg_dctmethod eJPEGdctmethod)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_DCTMETHOD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->eJPEGdctmethod = eJPEGdctmethod;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_DCTMETHOD, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif MNG_SUPPORT_WRITE
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_quality (mng_handle hHandle,
+ mng_int32 iJPEGquality)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_QUALITY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iJPEGquality = iJPEGquality;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_QUALITY, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_smoothing (mng_handle hHandle,
+ mng_int32 iJPEGsmoothing)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_SMOOTHING, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iJPEGsmoothing = iJPEGsmoothing;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_SMOOTHING, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_progressive (mng_handle hHandle,
+ mng_bool bJPEGprogressive)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_PROGRESSIVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bJPEGcompressprogr = bJPEGprogressive;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_PROGRESSIVE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_optimized (mng_handle hHandle,
+ mng_bool bJPEGoptimized)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_OPTIMIZED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->bJPEGcompressopt = bJPEGoptimized;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_OPTIMIZED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+#ifdef MNG_SUPPORT_WRITE
+mng_retcode MNG_DECL mng_set_jpeg_maxjdat (mng_handle hHandle,
+ mng_uint32 iMaxJDAT)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_MAXJDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iMaxJDAT = iMaxJDAT;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_JPEG_MAXJDAT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_WRITE */
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_retcode MNG_DECL mng_set_suspensionmode (mng_handle hHandle,
+ mng_bool bSuspensionmode)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SUSPENSIONMODE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ if (((mng_datap)hHandle)->bReading) /* we must NOT be reading !!! */
+ MNG_ERROR ((mng_datap)hHandle, MNG_FUNCTIONINVALID);
+
+ ((mng_datap)hHandle)->bSuspensionmode = bSuspensionmode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SUSPENSIONMODE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_set_speed (mng_handle hHandle,
+ mng_speedtype iSpeed)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SPEED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ ((mng_datap)hHandle)->iSpeed = iSpeed;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_SET_SPEED, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+/* * * */
+/* * Property get functions * */
+/* * * */
+/* ************************************************************************** */
+
+mng_ptr MNG_DECL mng_get_userdata (mng_handle hHandle)
+{ /* no tracing in here to prevent recursive calls */
+ MNG_VALIDHANDLEX (hHandle)
+ return ((mng_datap)hHandle)->pUserdata;
+}
+
+/* ************************************************************************** */
+
+mng_imgtype MNG_DECL mng_get_sigtype (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SIGTYPE, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_it_unknown;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SIGTYPE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->eSigtype;
+}
+
+/* ************************************************************************** */
+
+mng_imgtype MNG_DECL mng_get_imagetype (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGETYPE, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_it_unknown;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGETYPE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->eImagetype;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_imagewidth (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGEWIDTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGEWIDTH, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iWidth;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_imageheight (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGEWIDTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGEHEIGHT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iHeight;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_ticks (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TICKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TICKS, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iTicks;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_framecount (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_FRAMECOUNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_FRAMECOUNT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iFramecount;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_layercount (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LAYERCOUNT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LAYERCOUNT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iLayercount;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_playtime (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_PLAYTIME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_PLAYTIME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iPlaytime;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_simplicity (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SIMPLICITY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SIMPLICITY, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iSimplicity;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_bitdepth (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_BITDEPTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype == mng_it_png)
+ iRslt = ((mng_datap)hHandle)->iBitdepth;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRimgbitdepth;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_BITDEPTH, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_colortype (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_COLORTYPE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype == mng_it_png)
+ iRslt = ((mng_datap)hHandle)->iColortype;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRcolortype;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_COLORTYPE, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_compression (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_COMPRESSION, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype == mng_it_png)
+ iRslt = ((mng_datap)hHandle)->iCompression;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRimgcompression;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_COMPRESSION, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_filter (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_FILTER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype == mng_it_png)
+ iRslt = ((mng_datap)hHandle)->iFilter;
+ else
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_FILTER, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_interlace (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_INTERLACE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype == mng_it_png)
+ iRslt = ((mng_datap)hHandle)->iInterlace;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRimginterlace;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_INTERLACE, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_alphabitdepth (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHABITDEPTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRalphabitdepth;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHABITDEPTH, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_uint8 MNG_DECL mng_get_refreshpass (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+ mng_datap pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_REFRESHPASS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+ pData = (mng_datap)hHandle;
+ /* for PNG we know the exact pass */
+ if ((pData->eImagetype == mng_it_png) && (pData->iPass >= 0))
+ iRslt = pData->iPass;
+#ifdef MNG_INCLUDE_JNG
+ else /* for JNG we'll fake it... */
+ if ((pData->eImagetype == mng_it_jng) &&
+ (pData->bJPEGhasheader) && (pData->bJPEGdecostarted) &&
+ (pData->bJPEGprogressive))
+ {
+ if (pData->pJPEGdinfo->input_scan_number <= 1)
+ iRslt = 0; /* first pass (I think...) */
+ else
+ if (jpeg_input_complete (pData->pJPEGdinfo))
+ iRslt = 7; /* input complete; aka final pass */
+ else
+ iRslt = 3; /* anything between 0 and 7 will do */
+
+ }
+#endif
+ else
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_REFRESHPASS, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+mng_uint8 MNG_DECL mng_get_alphacompression (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHACOMPRESSION, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRalphacompression;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHACOMPRESSION, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_alphafilter (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHAFILTER, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRalphafilter;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHAFILTER, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_alphainterlace (mng_handle hHandle)
+{
+ mng_uint8 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHAINTERLACE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_INCLUDE_JNG
+ if (((mng_datap)hHandle)->eImagetype == mng_it_jng)
+ iRslt = ((mng_datap)hHandle)->iJHDRalphainterlace;
+ else
+#endif
+ iRslt = 0;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHAINTERLACE, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+
+/* ************************************************************************** */
+
+mng_uint8 MNG_DECL mng_get_alphadepth (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHADEPTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ALPHADEPTH, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iAlphadepth;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_canvasstyle (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CANVASSTYLE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CANVASSTYLE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iCanvasstyle;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_bkgdstyle (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_BKGDSTYLE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_BKGDSTYLE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iBkgdstyle;
+}
+
+/* ************************************************************************** */
+
+mng_retcode MNG_DECL mng_get_bgcolor (mng_handle hHandle,
+ mng_uint16* iRed,
+ mng_uint16* iGreen,
+ mng_uint16* iBlue)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GET_BGCOLOR, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+ *iRed = ((mng_datap)hHandle)->iBGred;
+ *iGreen = ((mng_datap)hHandle)->iBGgreen;
+ *iBlue = ((mng_datap)hHandle)->iBGblue;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (((mng_datap)hHandle), MNG_FN_GET_BGCOLOR, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_get_usebkgd (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_USEBKGD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_USEBKGD, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bUseBKGD;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_get_storechunks (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_STORECHUNKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_STORECHUNKS, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bStorechunks;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_get_sectionbreaks (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_SECTIONBREAKS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_SECTIONBREAKS, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bSectionbreaks;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_get_cacheplayback (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_CACHEPLAYBACK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_CACHEPLAYBACK, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bCacheplayback;
+}
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_get_doprogressive (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_DOPROGRESSIVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_DOPROGRESSIVE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bDoProgressive;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_crcmode (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_CRCMODE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_CRCMODE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iCrcmode;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_bool MNG_DECL mng_get_srgb (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_SRGB, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEB (((mng_datap)hHandle), MNG_FN_GET_SRGB, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bIssRGB;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_float MNG_DECL mng_get_viewgamma (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_VIEWGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_VIEWGAMMA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->dViewgamma;
+}
+#endif
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_float MNG_DECL mng_get_displaygamma (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DISPLAYGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DISPLAYGAMMA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->dDisplaygamma;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DFLT_INFO
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_float MNG_DECL mng_get_dfltimggamma (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DFLTIMGGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DFLTIMGGAMMA, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->dDfltimggamma;
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_uint32 MNG_DECL mng_get_viewgammaint (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_VIEWGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_VIEWGAMMA, MNG_LC_END);
+#endif
+
+ return (mng_uint32)(((mng_datap)hHandle)->dViewgamma * 100000);
+}
+#endif
+
+/* ************************************************************************** */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_uint32 MNG_DECL mng_get_displaygammaint (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DISPLAYGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DISPLAYGAMMA, MNG_LC_END);
+#endif
+
+ return (mng_uint32)(((mng_datap)hHandle)->dDisplaygamma * 100000);
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_NO_DFLT_INFO
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+mng_uint32 MNG_DECL mng_get_dfltimggammaint (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DFLTIMGGAMMA, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_DFLTIMGGAMMA, MNG_LC_END);
+#endif
+
+ return (mng_uint32)(((mng_datap)hHandle)->dDfltimggamma * 100000);
+}
+#endif
+#endif
+
+/* ************************************************************************** */
+
+#ifndef MNG_SKIP_MAXCANVAS
+mng_uint32 MNG_DECL mng_get_maxcanvaswidth (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_MAXCANVASWIDTH, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_MAXCANVASWIDTH, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iMaxwidth;
+}
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_maxcanvasheight (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_MAXCANVASHEIGHT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_MAXCANVASHEIGHT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iMaxheight;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_int32 MNG_DECL mng_get_zlib_level (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_LEVEL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_LEVEL, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iZlevel;
+}
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_int32 MNG_DECL mng_get_zlib_method (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_METHOD, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_METHOD, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iZmethod;
+}
+
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_int32 MNG_DECL mng_get_zlib_windowbits (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_WINDOWBITS, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_WINDOWBITS, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iZwindowbits;
+}
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_int32 MNG_DECL mng_get_zlib_memlevel (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_MEMLEVEL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_MEMLEVEL, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iZmemlevel;
+}
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_int32 MNG_DECL mng_get_zlib_strategy (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_STRATEGY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_STRATEGY, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iZstrategy;
+}
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+#ifdef MNG_ACCESS_ZLIB
+mng_uint32 MNG_DECL mng_get_zlib_maxidat (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_MAXIDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_ZLIB_MAXIDAT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iMaxIDAT;
+}
+#endif /* MNG_ACCESS_ZLIB */
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mngjpeg_dctmethod MNG_DECL mng_get_jpeg_dctmethod (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_DCTMETHOD, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return JDCT_ISLOW;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_DCTMETHOD, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->eJPEGdctmethod;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mng_int32 MNG_DECL mng_get_jpeg_quality (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_QUALITY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_QUALITY, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iJPEGquality;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mng_int32 MNG_DECL mng_get_jpeg_smoothing (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_SMOOTHING, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_SMOOTHING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iJPEGsmoothing;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mng_bool MNG_DECL mng_get_jpeg_progressive (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_PROGRESSIVE, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_PROGRESSIVE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bJPEGcompressprogr;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mng_bool MNG_DECL mng_get_jpeg_optimized (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_OPTIMIZED, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_OPTIMIZED, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bJPEGcompressopt;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+#ifdef MNG_ACCESS_JPEG
+mng_uint32 MNG_DECL mng_get_jpeg_maxjdat (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_MAXJDAT, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_JPEG_MAXJDAT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iMaxJDAT;
+}
+#endif /* MNG_ACCESS_JPEG */
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_bool MNG_DECL mng_get_suspensionmode (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SUSPENSIONMODE, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SUSPENSIONMODE, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bSuspensionmode;
+}
+#endif /* MNG_SUPPORT_READ */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_speedtype MNG_DECL mng_get_speed (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SPEED, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_SPEED, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iSpeed;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+mng_uint32 MNG_DECL mng_get_imagelevel (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGELEVEL, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLEX (hHandle)
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_IMAGELEVEL, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iImagelevel;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_get_lastbackchunk (mng_handle hHandle,
+ mng_uint16* iRed,
+ mng_uint16* iGreen,
+ mng_uint16* iBlue,
+ mng_uint8* iMandatory)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LASTBACKCHUNK, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ if (((mng_datap)hHandle)->eImagetype != mng_it_mng)
+ MNG_ERROR (((mng_datap)hHandle), MNG_FUNCTIONINVALID);
+
+ *iRed = ((mng_datap)hHandle)->iBACKred;
+ *iGreen = ((mng_datap)hHandle)->iBACKgreen;
+ *iBlue = ((mng_datap)hHandle)->iBACKblue;
+ *iMandatory = ((mng_datap)hHandle)->iBACKmandatory;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LASTBACKCHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode MNG_DECL mng_get_lastseekname (mng_handle hHandle,
+ mng_pchar zSegmentname)
+{
+ mng_datap pData;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LASTSEEKNAME, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle;
+ /* only allowed for MNG ! */
+ if (pData->eImagetype != mng_it_mng)
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ if (pData->pLastseek) /* is there a last SEEK ? */
+ {
+ mng_ani_seekp pSEEK = (mng_ani_seekp)pData->pLastseek;
+
+ if (pSEEK->iSegmentnamesize) /* copy the name if there is one */
+ MNG_COPY (zSegmentname, pSEEK->zSegmentname, pSEEK->iSegmentnamesize);
+
+ *(((mng_uint8p)zSegmentname) + pSEEK->iSegmentnamesize) = 0;
+ }
+ else
+ { /* return an empty string */
+ *((mng_uint8p)zSegmentname) = 0;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_LASTSEEKNAME, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_uint32 MNG_DECL mng_get_currframdelay (mng_handle hHandle)
+{
+ mng_datap pData;
+ mng_uint32 iRslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRFRAMDELAY, MNG_LC_START);
+#endif
+
+ MNG_VALIDHANDLE (hHandle)
+
+ pData = (mng_datap)hHandle;
+ /* only allowed for MNG ! */
+ if (pData->eImagetype != mng_it_mng)
+ MNG_ERROR (pData, MNG_FUNCTIONINVALID);
+
+ iRslt = pData->iFramedelay;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRFRAMDELAY, MNG_LC_END);
+#endif
+
+ return iRslt;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_uint32 MNG_DECL mng_get_starttime (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_STARTTIME, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_STARTTIME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iStarttime;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_uint32 MNG_DECL mng_get_runtime (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_RUNTIME, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_RUNTIME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iRuntime;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_currentframe (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTFRAME, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTFRAME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iFrameseq;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_currentlayer (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTLAYER, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTLAYER, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iLayerseq;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_currentplaytime (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTPLAYTIME, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_CURRENTPLAYTIME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iFrametime;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_totalframes (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALFRAMES, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALFRAMES, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iTotalframes;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_totallayers (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALLAYERS, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALLAYERS, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iTotallayers;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+#ifndef MNG_NO_CURRENT_INFO
+mng_uint32 MNG_DECL mng_get_totalplaytime (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALPLAYTIME, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return mng_st_normal;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_GET_TOTALPLAYTIME, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->iTotalplaytime;
+}
+#endif
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+mng_bool MNG_DECL mng_status_error (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_ERROR, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_ERROR, MNG_LC_END);
+#endif
+
+ return (mng_bool)((mng_datap)hHandle)->iErrorcode;
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_bool MNG_DECL mng_status_reading (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_READING, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_READING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bReading;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_READ
+mng_bool MNG_DECL mng_status_suspendbreak (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_SUSPENDBREAK, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_SUSPENDBREAK, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bSuspended;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_bool MNG_DECL mng_status_creating (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_CREATING, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_CREATING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bCreating;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_WRITE
+mng_bool MNG_DECL mng_status_writing (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_WRITING, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_WRITING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bWriting;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_bool MNG_DECL mng_status_displaying (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_DISPLAYING, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_DISPLAYING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bDisplaying;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_bool MNG_DECL mng_status_running (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_RUNNING, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_RUNNING, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bRunning;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_bool MNG_DECL mng_status_timerbreak (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_TIMERBREAK, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_TIMERBREAK, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bTimerset;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+mng_bool MNG_DECL mng_status_dynamic (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_DYNAMIC, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_DYNAMIC, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bDynamic;
+}
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DYNAMICMNG
+mng_bool MNG_DECL mng_status_runningevent (mng_handle hHandle)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_RUNNINGEVENT, MNG_LC_START);
+#endif
+
+ if ((hHandle == 0) || (((mng_datap)hHandle)->iMagic != MNG_MAGIC))
+ return MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACEX (((mng_datap)hHandle), MNG_FN_STATUS_RUNNINGEVENT, MNG_LC_END);
+#endif
+
+ return ((mng_datap)hHandle)->bRunningevent;
+}
+#endif
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_read.c b/Source/LibMNG/libmng_read.c
new file mode 100644
index 0000000..c922e19
--- /dev/null
+++ b/Source/LibMNG/libmng_read.c
@@ -0,0 +1,1369 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_read.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Read logic (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the high-level read logic * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - added callback error-reporting support * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/19/2000 - G.Juyn * */
+/* * - cleaned up some code regarding mixed support * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - added support for JNG * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed up punctuation (contribution by Tim Rowley) * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - changed read-processing for improved I/O-suspension * */
+/* * 0.9.1 - 07/14/2000 - G.Juyn * */
+/* * - changed EOF processing behavior * */
+/* * 0.9.1 - 07/14/2000 - G.Juyn * */
+/* * - changed default readbuffer size from 1024 to 4200 * */
+/* * * */
+/* * 0.9.2 - 07/27/2000 - G.Juyn * */
+/* * - B110320 - fixed GCC warning about mix-sized pointer math * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - B110546 - fixed for improperly returning UNEXPECTEDEOF * */
+/* * 0.9.2 - 08/04/2000 - G.Juyn * */
+/* * - B111096 - fixed large-buffer read-suspension * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - removed test-MaGN * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added support for JDAA * */
+/* * * */
+/* * 0.9.5 - 01/23/2001 - G.Juyn * */
+/* * - fixed timing-problem with switching framing_modes * */
+/* * * */
+/* * 1.0.4 - 06/22/2002 - G.Juyn * */
+/* * - B495443 - incorrect suspend check in read_databuffer * */
+/* * * */
+/* * 1.0.5 - 07/04/2002 - G.Juyn * */
+/* * - added errorcode for extreme chunk-sizes * */
+/* * 1.0.5 - 07/08/2002 - G.Juyn * */
+/* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
+/* * 1.0.5 - 07/16/2002 - G.Juyn * */
+/* * - B581625 - large chunks fail with suspension reads * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/16/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * * */
+/* * 1.0.6 - 05/25/2003 - G.R-P * */
+/* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added MNG_NO_DELTA_PNG reduction * */
+/* * - skip additional code when MNG_INCLUDE_JNG is not enabled * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * 1.0.6 - 08/17/2003 - G.R-P * */
+/* * - added conditionals around non-VLC chunk support * */
+/* * * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * * */
+/* * 1.0.8 - 04/08/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/11/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * 1.0.8 - 07/06/2004 - G.R-P * */
+/* * - defend against using undefined closestream function * */
+/* * 1.0.8 - 07/28/2004 - G.R-P * */
+/* * - added check for extreme chunk-lengths * */
+/* * * */
+/* * 1.0.9 - 09/16/2004 - G.Juyn * */
+/* * - fixed chunk pushing mechanism * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * 1.0.9 - 12/31/2004 - G.R-P * */
+/* * - removed stray characters from #ifdef directive * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_objects.h"
+#include "libmng_object_prc.h"
+#include "libmng_chunks.h"
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+#include "libmng_chunk_descr.h"
+#endif
+#include "libmng_chunk_prc.h"
+#include "libmng_chunk_io.h"
+#include "libmng_display.h"
+#include "libmng_read.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_READ_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_eof (mng_datap pData)
+{
+ if (!pData->bEOF) /* haven't closed the stream yet ? */
+ {
+ pData->bEOF = MNG_TRUE; /* now we do! */
+
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ if (pData->fClosestream && !pData->fClosestream ((mng_handle)pData))
+ {
+ MNG_ERROR (pData, MNG_APPIOERROR);
+ }
+#endif
+ }
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_release_pushdata (mng_datap pData)
+{
+ mng_pushdatap pFirst = pData->pFirstpushdata;
+ mng_pushdatap pNext = pFirst->pNext;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_START);
+#endif
+
+ pData->pFirstpushdata = pNext; /* next becomes the first */
+
+ if (!pNext) /* no next? => no last! */
+ pData->pLastpushdata = MNG_NULL;
+ /* buffer owned and release callback defined? */
+ if ((pFirst->bOwned) && (pData->fReleasedata))
+ pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
+ else /* otherwise use internal free mechanism */
+ MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
+ /* and free it */
+ MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RELEASE_PUSHDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_release_pushchunk (mng_datap pData)
+{
+ mng_pushdatap pFirst = pData->pFirstpushchunk;
+ mng_pushdatap pNext = pFirst->pNext;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_START);
+#endif
+
+ pData->pFirstpushchunk = pNext; /* next becomes the first */
+
+ if (!pNext) /* no next? => no last! */
+ pData->pLastpushchunk = MNG_NULL;
+ /* buffer owned and release callback defined? */
+ if ((pFirst->bOwned) && (pData->fReleasedata))
+ pData->fReleasedata ((mng_handle)pData, pFirst->pData, pFirst->iLength);
+ else /* otherwise use internal free mechanism */
+ MNG_FREEX (pData, pFirst->pData, pFirst->iLength);
+ /* and free it */
+ MNG_FREEX (pData, pFirst, sizeof(mng_pushdata));
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_RELEASE_PUSHCHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode read_data (mng_datap pData,
+ mng_uint8p pBuf,
+ mng_uint32 iSize,
+ mng_uint32 * iRead)
+{
+ mng_retcode iRetcode;
+ mng_uint32 iTempsize = iSize;
+ mng_uint8p pTempbuf = pBuf;
+ mng_pushdatap pPush = pData->pFirstpushdata;
+ mng_uint32 iPushsize = 0;
+ *iRead = 0; /* nothing yet */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_START);
+#endif
+
+ while (pPush) /* calculate size of pushed data */
+ {
+ iPushsize += pPush->iRemaining;
+ pPush = pPush->pNext;
+ }
+
+ if (iTempsize <= iPushsize) /* got enough push data? */
+ {
+ while (iTempsize)
+ {
+ pPush = pData->pFirstpushdata;
+ /* enough data remaining in this buffer? */
+ if (pPush->iRemaining <= iTempsize)
+ { /* no: then copy what we've got */
+ MNG_COPY (pTempbuf, pPush->pDatanext, pPush->iRemaining);
+ /* move pointers & lengths */
+ pTempbuf += pPush->iRemaining;
+ *iRead += pPush->iRemaining;
+ iTempsize -= pPush->iRemaining;
+ /* release the depleted buffer */
+ iRetcode = mng_release_pushdata (pData);
+ if (iRetcode)
+ return iRetcode;
+ }
+ else
+ { /* copy the needed bytes */
+ MNG_COPY (pTempbuf, pPush->pDatanext, iTempsize);
+ /* move pointers & lengths */
+ pPush->iRemaining -= iTempsize;
+ pPush->pDatanext += iTempsize;
+ pTempbuf += iTempsize;
+ *iRead += iTempsize;
+ iTempsize = 0; /* all done!!! */
+ }
+ }
+ }
+ else
+ {
+ mng_uint32 iTempread = 0;
+ /* get it from the app then */
+ if (!pData->fReaddata (((mng_handle)pData), pTempbuf, iTempsize, &iTempread))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+
+ *iRead += iTempread;
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode read_databuffer (mng_datap pData,
+ mng_uint8p pBuf,
+ mng_uint8p * pBufnext,
+ mng_uint32 iSize,
+ mng_uint32 * iRead)
+{
+ mng_retcode iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_START);
+#endif
+
+ if (pData->bSuspensionmode)
+ {
+ mng_uint8p pTemp;
+ mng_uint32 iTemp;
+
+ *iRead = 0; /* let's be negative about the outcome */
+
+ if (!pData->pSuspendbuf) /* need to create a suspension buffer ? */
+ {
+ pData->iSuspendbufsize = MNG_SUSPENDBUFFERSIZE;
+ /* so, create it */
+ MNG_ALLOC (pData, pData->pSuspendbuf, pData->iSuspendbufsize);
+
+ pData->iSuspendbufleft = 0; /* make sure to fill it first time */
+ pData->pSuspendbufnext = pData->pSuspendbuf;
+ }
+ /* more than our buffer can hold ? */
+ if (iSize > pData->iSuspendbufsize)
+ {
+ mng_uint32 iRemain;
+
+ if (!*pBufnext) /* first time ? */
+ {
+ if (pData->iSuspendbufleft) /* do we have some data left ? */
+ { /* then copy it */
+ MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
+ /* fixup variables */
+ *pBufnext = pBuf + pData->iSuspendbufleft;
+ pData->pSuspendbufnext = pData->pSuspendbuf;
+ pData->iSuspendbufleft = 0;
+ }
+ else
+ {
+ *pBufnext = pBuf;
+ }
+ }
+ /* calculate how much to get */
+ iRemain = iSize - (mng_uint32)(*pBufnext - pBuf);
+ /* let's go get it */
+ iRetcode = read_data (pData, *pBufnext, iRemain, &iTemp);
+ if (iRetcode)
+ return iRetcode;
+ /* first read after suspension return 0 means EOF */
+ if ((pData->iSuspendpoint) && (iTemp == 0))
+ { /* that makes it final */
+ mng_retcode iRetcode = mng_process_eof (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* indicate the source is depleted */
+ *iRead = iSize - iRemain + iTemp;
+ }
+ else
+ {
+ if (iTemp < iRemain) /* suspension required ? */
+ {
+ *pBufnext = *pBufnext + iTemp;
+ pData->bSuspended = MNG_TRUE;
+ }
+ else
+ {
+ *iRead = iSize; /* got it all now ! */
+ }
+ }
+ }
+ else
+ { /* need to read some more ? */
+ while ((!pData->bSuspended) && (!pData->bEOF) && (iSize > pData->iSuspendbufleft))
+ { /* not enough space left in buffer ? */
+ if (pData->iSuspendbufsize - pData->iSuspendbufleft -
+ (mng_uint32)(pData->pSuspendbufnext - pData->pSuspendbuf) <
+ MNG_SUSPENDREQUESTSIZE)
+ {
+ if (pData->iSuspendbufleft) /* then lets shift (if there's anything left) */
+ MNG_COPY (pData->pSuspendbuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
+ /* adjust running pointer */
+ pData->pSuspendbufnext = pData->pSuspendbuf;
+ }
+ /* still not enough room ? */
+ if (pData->iSuspendbufsize - pData->iSuspendbufleft < MNG_SUSPENDREQUESTSIZE)
+ MNG_ERROR (pData, MNG_INTERNALERROR);
+ /* now read some more data */
+ pTemp = pData->pSuspendbufnext + pData->iSuspendbufleft;
+
+ iRetcode = read_data (pData, pTemp, MNG_SUSPENDREQUESTSIZE, &iTemp);
+ if (iRetcode)
+ return iRetcode;
+ /* adjust fill-counter */
+ pData->iSuspendbufleft += iTemp;
+ /* first read after suspension returning 0 means EOF */
+ if ((pData->iSuspendpoint) && (iTemp == 0))
+ { /* that makes it final */
+ mng_retcode iRetcode = mng_process_eof (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if (pData->iSuspendbufleft) /* return the leftover scraps */
+ MNG_COPY (pBuf, pData->pSuspendbufnext, pData->iSuspendbufleft);
+ /* and indicate so */
+ *iRead = pData->iSuspendbufleft;
+ pData->pSuspendbufnext = pData->pSuspendbuf;
+ pData->iSuspendbufleft = 0;
+ }
+ else
+ { /* suspension required ? */
+ if ((iSize > pData->iSuspendbufleft) && (iTemp < MNG_SUSPENDREQUESTSIZE))
+ pData->bSuspended = MNG_TRUE;
+
+ }
+
+ pData->iSuspendpoint = 0; /* reset it here in case we loop back */
+ }
+
+ if ((!pData->bSuspended) && (!pData->bEOF))
+ { /* return the data ! */
+ MNG_COPY (pBuf, pData->pSuspendbufnext, iSize);
+
+ *iRead = iSize; /* returned it all */
+ /* adjust suspension-buffer variables */
+ pData->pSuspendbufnext += iSize;
+ pData->iSuspendbufleft -= iSize;
+ }
+ }
+ }
+ else
+ {
+ iRetcode = read_data (pData, (mng_ptr)pBuf, iSize, iRead);
+ if (iRetcode)
+ return iRetcode;
+ if (*iRead == 0) /* suspension required ? */
+ pData->bSuspended = MNG_TRUE;
+ }
+
+ pData->iSuspendpoint = 0; /* safely reset it here ! */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_DATABUFFER, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode process_raw_chunk (mng_datap pData,
+ mng_uint8p pBuf,
+ mng_uint32 iBuflen)
+{
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ /* the table-idea & binary search code was adapted from
+ libpng 1.1.0 (pngread.c) */
+ /* NOTE1: the table must remain sorted by chunkname, otherwise the binary
+ search will break !!! (ps. watch upper-/lower-case chunknames !!) */
+ /* NOTE2: the layout must remain equal to the header part of all the
+ chunk-structures (yes, that means even the pNext and pPrev fields;
+ it's wasting a bit of space, but hey, the code is a lot easier) */
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+ mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_general, mng_free_unknown,
+ mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0, sizeof(mng_unknown_chunk)};
+#else
+ mng_chunk_header mng_chunk_unknown = {MNG_UINT_HUH, mng_init_unknown, mng_free_unknown,
+ mng_read_unknown, mng_write_unknown, mng_assign_unknown, 0, 0};
+#endif
+
+#ifdef MNG_OPTIMIZE_CHUNKINITFREE
+
+ mng_chunk_header mng_chunk_table [] =
+ {
+#ifndef MNG_SKIPCHUNK_BACK
+ {MNG_UINT_BACK, mng_init_general, mng_free_general, mng_read_back, mng_write_back, mng_assign_general, 0, 0, sizeof(mng_back)},
+#endif
+#ifndef MNG_SKIPCHUNK_BASI
+ {MNG_UINT_BASI, mng_init_general, mng_free_general, mng_read_basi, mng_write_basi, mng_assign_general, 0, 0, sizeof(mng_basi)},
+#endif
+#ifndef MNG_SKIPCHUNK_CLIP
+ {MNG_UINT_CLIP, mng_init_general, mng_free_general, mng_read_clip, mng_write_clip, mng_assign_general, 0, 0, sizeof(mng_clip)},
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ {MNG_UINT_CLON, mng_init_general, mng_free_general, mng_read_clon, mng_write_clon, mng_assign_general, 0, 0, sizeof(mng_clon)},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+ {MNG_UINT_DBYK, mng_init_general, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0, sizeof(mng_dbyk)},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_DEFI
+ {MNG_UINT_DEFI, mng_init_general, mng_free_general, mng_read_defi, mng_write_defi, mng_assign_general, 0, 0, sizeof(mng_defi)},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_DHDR, mng_init_general, mng_free_general, mng_read_dhdr, mng_write_dhdr, mng_assign_general, 0, 0, sizeof(mng_dhdr)},
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+ {MNG_UINT_DISC, mng_init_general, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0, sizeof(mng_disc)},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DROP
+ {MNG_UINT_DROP, mng_init_general, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0, sizeof(mng_drop)},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_ENDL, mng_init_general, mng_free_general, mng_read_endl, mng_write_endl, mng_assign_general, 0, 0, sizeof(mng_endl)},
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+ {MNG_UINT_FRAM, mng_init_general, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0, sizeof(mng_fram)},
+#endif
+ {MNG_UINT_IDAT, mng_init_general, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0, sizeof(mng_idat)}, /* 12-th element! */
+ {MNG_UINT_IEND, mng_init_general, mng_free_general, mng_read_iend, mng_write_iend, mng_assign_general, 0, 0, sizeof(mng_iend)},
+ {MNG_UINT_IHDR, mng_init_general, mng_free_general, mng_read_ihdr, mng_write_ihdr, mng_assign_general, 0, 0, sizeof(mng_ihdr)},
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_IJNG, mng_init_general, mng_free_general, mng_read_ijng, mng_write_ijng, mng_assign_general, 0, 0, sizeof(mng_ijng)},
+#endif
+ {MNG_UINT_IPNG, mng_init_general, mng_free_general, mng_read_ipng, mng_write_ipng, mng_assign_general, 0, 0, sizeof(mng_ipng)},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_JDAA, mng_init_general, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa)},
+ {MNG_UINT_JDAT, mng_init_general, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0, sizeof(mng_jdat)},
+ {MNG_UINT_JHDR, mng_init_general, mng_free_general, mng_read_jhdr, mng_write_jhdr, mng_assign_general, 0, 0, sizeof(mng_jhdr)},
+ {MNG_UINT_JSEP, mng_init_general, mng_free_general, mng_read_jsep, mng_write_jsep, mng_assign_general, 0, 0, sizeof(mng_jsep)},
+ {MNG_UINT_JdAA, mng_init_general, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0, sizeof(mng_jdaa)},
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_LOOP, mng_init_general, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0, sizeof(mng_loop)},
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+ {MNG_UINT_MAGN, mng_init_general, mng_free_general, mng_read_magn, mng_write_magn, mng_assign_general, 0, 0, sizeof(mng_magn)},
+#endif
+ {MNG_UINT_MEND, mng_init_general, mng_free_general, mng_read_mend, mng_write_mend, mng_assign_general, 0, 0, sizeof(mng_mend)},
+ {MNG_UINT_MHDR, mng_init_general, mng_free_general, mng_read_mhdr, mng_write_mhdr, mng_assign_general, 0, 0, sizeof(mng_mhdr)},
+#ifndef MNG_SKIPCHUNK_MOVE
+ {MNG_UINT_MOVE, mng_init_general, mng_free_general, mng_read_move, mng_write_move, mng_assign_general, 0, 0, sizeof(mng_move)},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_UINT_ORDR, mng_init_general, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0, sizeof(mng_ordr)},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_UINT_PAST, mng_init_general, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0, sizeof(mng_past)},
+#endif
+ {MNG_UINT_PLTE, mng_init_general, mng_free_general, mng_read_plte, mng_write_plte, mng_assign_general, 0, 0, sizeof(mng_plte)},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_PPLT, mng_init_general, mng_free_general, mng_read_pplt, mng_write_pplt, mng_assign_general, 0, 0, sizeof(mng_pplt)},
+ {MNG_UINT_PROM, mng_init_general, mng_free_general, mng_read_prom, mng_write_prom, mng_assign_general, 0, 0, sizeof(mng_prom)},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_UINT_SAVE, mng_init_general, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0, sizeof(mng_save)},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {MNG_UINT_SEEK, mng_init_general, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0, sizeof(mng_seek)},
+#endif
+#ifndef MNG_SKIPCHUNK_SHOW
+ {MNG_UINT_SHOW, mng_init_general, mng_free_general, mng_read_show, mng_write_show, mng_assign_general, 0, 0, sizeof(mng_show)},
+#endif
+#ifndef MNG_SKIPCHUNK_TERM
+ {MNG_UINT_TERM, mng_init_general, mng_free_general, mng_read_term, mng_write_term, mng_assign_general, 0, 0, sizeof(mng_term)},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {MNG_UINT_bKGD, mng_init_general, mng_free_general, mng_read_bkgd, mng_write_bkgd, mng_assign_general, 0, 0, sizeof(mng_bkgd)},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {MNG_UINT_cHRM, mng_init_general, mng_free_general, mng_read_chrm, mng_write_chrm, mng_assign_general, 0, 0, sizeof(mng_chrm)},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {MNG_UINT_eXPI, mng_init_general, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0, sizeof(mng_expi)},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_UINT_evNT, mng_init_general, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0, sizeof(mng_evnt)},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {MNG_UINT_fPRI, mng_init_general, mng_free_general, mng_read_fpri, mng_write_fpri, mng_assign_general, 0, 0, sizeof(mng_fpri)},
+#endif
+#ifndef MNG_SKIPCHUNK_gAMA
+ {MNG_UINT_gAMA, mng_init_general, mng_free_general, mng_read_gama, mng_write_gama, mng_assign_general, 0, 0, sizeof(mng_gama)},
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+ {MNG_UINT_hIST, mng_init_general, mng_free_general, mng_read_hist, mng_write_hist, mng_assign_general, 0, 0, sizeof(mng_hist)},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {MNG_UINT_iCCP, mng_init_general, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0, sizeof(mng_iccp)},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {MNG_UINT_iTXt, mng_init_general, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0, sizeof(mng_itxt)},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_UINT_mpNG, mng_init_general, mng_free_mpng, mng_read_mpng, mng_write_mpng, mng_assign_mpng, 0, 0, sizeof(mng_mpng)},
+#endif
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_UINT_nEED, mng_init_general, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0, sizeof(mng_need)},
+#endif
+/* TODO: {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0}, */
+/* TODO: {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_pHYg
+ {MNG_UINT_pHYg, mng_init_general, mng_free_general, mng_read_phyg, mng_write_phyg, mng_assign_general, 0, 0, sizeof(mng_phyg)},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {MNG_UINT_pHYs, mng_init_general, mng_free_general, mng_read_phys, mng_write_phys, mng_assign_general, 0, 0, sizeof(mng_phys)},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {MNG_UINT_sBIT, mng_init_general, mng_free_general, mng_read_sbit, mng_write_sbit, mng_assign_general, 0, 0, sizeof(mng_sbit)},
+#endif
+/* TODO: {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_sPLT
+ {MNG_UINT_sPLT, mng_init_general, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0, sizeof(mng_splt)},
+#endif
+ {MNG_UINT_sRGB, mng_init_general, mng_free_general, mng_read_srgb, mng_write_srgb, mng_assign_general, 0, 0, sizeof(mng_srgb)},
+#ifndef MNG_SKIPCHUNK_tEXt
+ {MNG_UINT_tEXt, mng_init_general, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0, sizeof(mng_text)},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {MNG_UINT_tIME, mng_init_general, mng_free_general, mng_read_time, mng_write_time, mng_assign_general, 0, 0, sizeof(mng_time)},
+#endif
+ {MNG_UINT_tRNS, mng_init_general, mng_free_general, mng_read_trns, mng_write_trns, mng_assign_general, 0, 0, sizeof(mng_trns)},
+#ifndef MNG_SKIPCHUNK_zTXt
+ {MNG_UINT_zTXt, mng_init_general, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0, sizeof(mng_ztxt)},
+#endif
+ };
+
+#else /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+ mng_chunk_header mng_chunk_table [] =
+ {
+#ifndef MNG_SKIPCHUNK_BACK
+ {MNG_UINT_BACK, mng_init_back, mng_free_back, mng_read_back, mng_write_back, mng_assign_back, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_BASI
+ {MNG_UINT_BASI, mng_init_basi, mng_free_basi, mng_read_basi, mng_write_basi, mng_assign_basi, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_CLIP
+ {MNG_UINT_CLIP, mng_init_clip, mng_free_clip, mng_read_clip, mng_write_clip, mng_assign_clip, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ {MNG_UINT_CLON, mng_init_clon, mng_free_clon, mng_read_clon, mng_write_clon, mng_assign_clon, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DBYK
+ {MNG_UINT_DBYK, mng_init_dbyk, mng_free_dbyk, mng_read_dbyk, mng_write_dbyk, mng_assign_dbyk, 0, 0},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_DEFI
+ {MNG_UINT_DEFI, mng_init_defi, mng_free_defi, mng_read_defi, mng_write_defi, mng_assign_defi, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_DHDR, mng_init_dhdr, mng_free_dhdr, mng_read_dhdr, mng_write_dhdr, mng_assign_dhdr, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_DISC
+ {MNG_UINT_DISC, mng_init_disc, mng_free_disc, mng_read_disc, mng_write_disc, mng_assign_disc, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_DROP
+ {MNG_UINT_DROP, mng_init_drop, mng_free_drop, mng_read_drop, mng_write_drop, mng_assign_drop, 0, 0},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_ENDL, mng_init_endl, mng_free_endl, mng_read_endl, mng_write_endl, mng_assign_endl, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_FRAM
+ {MNG_UINT_FRAM, mng_init_fram, mng_free_fram, mng_read_fram, mng_write_fram, mng_assign_fram, 0, 0},
+#endif
+ {MNG_UINT_IDAT, mng_init_idat, mng_free_idat, mng_read_idat, mng_write_idat, mng_assign_idat, 0, 0}, /* 12-th element! */
+ {MNG_UINT_IEND, mng_init_iend, mng_free_iend, mng_read_iend, mng_write_iend, mng_assign_iend, 0, 0},
+ {MNG_UINT_IHDR, mng_init_ihdr, mng_free_ihdr, mng_read_ihdr, mng_write_ihdr, mng_assign_ihdr, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_IJNG, mng_init_ijng, mng_free_ijng, mng_read_ijng, mng_write_ijng, mng_assign_ijng, 0, 0},
+#endif
+ {MNG_UINT_IPNG, mng_init_ipng, mng_free_ipng, mng_read_ipng, mng_write_ipng, mng_assign_ipng, 0, 0},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {MNG_UINT_JDAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
+ {MNG_UINT_JDAT, mng_init_jdat, mng_free_jdat, mng_read_jdat, mng_write_jdat, mng_assign_jdat, 0, 0},
+ {MNG_UINT_JHDR, mng_init_jhdr, mng_free_jhdr, mng_read_jhdr, mng_write_jhdr, mng_assign_jhdr, 0, 0},
+ {MNG_UINT_JSEP, mng_init_jsep, mng_free_jsep, mng_read_jsep, mng_write_jsep, mng_assign_jsep, 0, 0},
+ {MNG_UINT_JdAA, mng_init_jdaa, mng_free_jdaa, mng_read_jdaa, mng_write_jdaa, mng_assign_jdaa, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_UINT_LOOP, mng_init_loop, mng_free_loop, mng_read_loop, mng_write_loop, mng_assign_loop, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_MAGN
+ {MNG_UINT_MAGN, mng_init_magn, mng_free_magn, mng_read_magn, mng_write_magn, mng_assign_magn, 0, 0},
+#endif
+ {MNG_UINT_MEND, mng_init_mend, mng_free_mend, mng_read_mend, mng_write_mend, mng_assign_mend, 0, 0},
+ {MNG_UINT_MHDR, mng_init_mhdr, mng_free_mhdr, mng_read_mhdr, mng_write_mhdr, mng_assign_mhdr, 0, 0},
+#ifndef MNG_SKIPCHUNK_MOVE
+ {MNG_UINT_MOVE, mng_init_move, mng_free_move, mng_read_move, mng_write_move, mng_assign_move, 0, 0},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_UINT_ORDR, mng_init_ordr, mng_free_ordr, mng_read_ordr, mng_write_ordr, mng_assign_ordr, 0, 0},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_UINT_PAST, mng_init_past, mng_free_past, mng_read_past, mng_write_past, mng_assign_past, 0, 0},
+#endif
+ {MNG_UINT_PLTE, mng_init_plte, mng_free_plte, mng_read_plte, mng_write_plte, mng_assign_plte, 0, 0},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_UINT_PPLT, mng_init_pplt, mng_free_pplt, mng_read_pplt, mng_write_pplt, mng_assign_pplt, 0, 0},
+ {MNG_UINT_PROM, mng_init_prom, mng_free_prom, mng_read_prom, mng_write_prom, mng_assign_prom, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_UINT_SAVE, mng_init_save, mng_free_save, mng_read_save, mng_write_save, mng_assign_save, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {MNG_UINT_SEEK, mng_init_seek, mng_free_seek, mng_read_seek, mng_write_seek, mng_assign_seek, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_SHOW
+ {MNG_UINT_SHOW, mng_init_show, mng_free_show, mng_read_show, mng_write_show, mng_assign_show, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_TERM
+ {MNG_UINT_TERM, mng_init_term, mng_free_term, mng_read_term, mng_write_term, mng_assign_term, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {MNG_UINT_bKGD, mng_init_bkgd, mng_free_bkgd, mng_read_bkgd, mng_write_bkgd, mng_assign_bkgd, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {MNG_UINT_cHRM, mng_init_chrm, mng_free_chrm, mng_read_chrm, mng_write_chrm, mng_assign_chrm, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {MNG_UINT_eXPI, mng_init_expi, mng_free_expi, mng_read_expi, mng_write_expi, mng_assign_expi, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_UINT_evNT, mng_init_evnt, mng_free_evnt, mng_read_evnt, mng_write_evnt, mng_assign_evnt, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {MNG_UINT_fPRI, mng_init_fpri, mng_free_fpri, mng_read_fpri, mng_write_fpri, mng_assign_fpri, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_gAMA
+ {MNG_UINT_gAMA, mng_init_gama, mng_free_gama, mng_read_gama, mng_write_gama, mng_assign_gama, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+ {MNG_UINT_hIST, mng_init_hist, mng_free_hist, mng_read_hist, mng_write_hist, mng_assign_hist, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {MNG_UINT_iCCP, mng_init_iccp, mng_free_iccp, mng_read_iccp, mng_write_iccp, mng_assign_iccp, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {MNG_UINT_iTXt, mng_init_itxt, mng_free_itxt, mng_read_itxt, mng_write_itxt, mng_assign_itxt, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_UINT_nEED, mng_init_need, mng_free_need, mng_read_need, mng_write_need, mng_assign_need, 0, 0},
+#endif
+/* TODO: {MNG_UINT_oFFs, 0, 0, 0, 0, 0, 0}, */
+/* TODO: {MNG_UINT_pCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_pHYg
+ {MNG_UINT_pHYg, mng_init_phyg, mng_free_phyg, mng_read_phyg, mng_write_phyg, mng_assign_phyg, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {MNG_UINT_pHYs, mng_init_phys, mng_free_phys, mng_read_phys, mng_write_phys, mng_assign_phys, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {MNG_UINT_sBIT, mng_init_sbit, mng_free_sbit, mng_read_sbit, mng_write_sbit, mng_assign_sbit, 0, 0},
+#endif
+/* TODO: {MNG_UINT_sCAL, 0, 0, 0, 0, 0, 0}, */
+#ifndef MNG_SKIPCHUNK_sPLT
+ {MNG_UINT_sPLT, mng_init_splt, mng_free_splt, mng_read_splt, mng_write_splt, mng_assign_splt, 0, 0},
+#endif
+ {MNG_UINT_sRGB, mng_init_srgb, mng_free_srgb, mng_read_srgb, mng_write_srgb, mng_assign_srgb, 0, 0},
+#ifndef MNG_SKIPCHUNK_tEXt
+ {MNG_UINT_tEXt, mng_init_text, mng_free_text, mng_read_text, mng_write_text, mng_assign_text, 0, 0},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {MNG_UINT_tIME, mng_init_time, mng_free_time, mng_read_time, mng_write_time, mng_assign_time, 0, 0},
+#endif
+ {MNG_UINT_tRNS, mng_init_trns, mng_free_trns, mng_read_trns, mng_write_trns, mng_assign_trns, 0, 0},
+#ifndef MNG_SKIPCHUNK_zTXt
+ {MNG_UINT_zTXt, mng_init_ztxt, mng_free_ztxt, mng_read_ztxt, mng_write_ztxt, mng_assign_ztxt, 0, 0},
+#endif
+ };
+
+#endif /* MNG_OPTIMIZE_CHUNKINITFREE */
+
+ /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ mng_chunk_headerp pEntry; /* pointer to found entry */
+#else
+ mng_chunk_header sEntry; /* temp chunk-header */
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+ mng_chunkid iChunkname; /* the chunk's tag */
+ mng_chunkp pChunk; /* chunk structure (if #define MNG_STORE_CHUNKS) */
+ mng_retcode iRetcode; /* temporary error-code */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_START);
+#endif
+ /* reset timer indicator on read-cycle */
+ if ((pData->bReading) && (!pData->bDisplaying))
+ pData->bTimerset = MNG_FALSE;
+ /* get the chunkname */
+ iChunkname = (mng_chunkid)(mng_get_uint32 (pBuf));
+
+ pBuf += sizeof (mng_chunkid); /* adjust the buffer */
+ iBuflen -= sizeof (mng_chunkid);
+ pChunk = 0;
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ /* determine max index of table */
+ iTop = (sizeof (mng_chunk_table) / sizeof (mng_chunk_table [0])) - 1;
+
+ /* binary search; with 54 chunks, worst-case is 7 comparisons */
+ iLower = 0;
+#ifndef MNG_NO_DELTA_PNG
+ iMiddle = 11; /* start with the IDAT entry */
+#else
+ iMiddle = 8;
+#endif
+ iUpper = iTop;
+ pEntry = 0; /* no goods yet! */
+
+ do /* the binary search itself */
+ {
+ if (mng_chunk_table [iMiddle].iChunkname < iChunkname)
+ iLower = iMiddle + 1;
+ else if (mng_chunk_table [iMiddle].iChunkname > iChunkname)
+ iUpper = iMiddle - 1;
+ else
+ {
+ pEntry = &mng_chunk_table [iMiddle];
+ break;
+ }
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+
+ if (!pEntry) /* unknown chunk ? */
+ pEntry = &mng_chunk_unknown; /* make it so! */
+
+#else /* MNG_OPTIMIZE_CHUNKREADER */
+
+ mng_get_chunkheader (iChunkname, &sEntry);
+
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+
+ pData->iChunkname = iChunkname; /* keep track of where we are */
+ pData->iChunkseq++;
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ if (pEntry->fRead) /* read-callback available ? */
+ {
+ iRetcode = pEntry->fRead (pData, pEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
+
+ if (!iRetcode) /* everything oke ? */
+ { /* remember unknown chunk's id */
+ if ((pChunk) && (pEntry->iChunkname == MNG_UINT_HUH))
+ ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
+ }
+ }
+#else /* MNG_OPTIMIZE_CHUNKREADER */
+ if (sEntry.fRead) /* read-callback available ? */
+ {
+ iRetcode = sEntry.fRead (pData, &sEntry, iBuflen, (mng_ptr)pBuf, &pChunk);
+
+#ifndef MNG_OPTIMIZE_CHUNKREADER
+ if (!iRetcode) /* everything oke ? */
+ { /* remember unknown chunk's id */
+ if ((pChunk) && (sEntry.iChunkname == MNG_UINT_HUH))
+ ((mng_chunk_headerp)pChunk)->iChunkname = iChunkname;
+ }
+#endif
+ }
+#endif /* MNG_OPTIMIZE_CHUNKREADER */
+ else
+ iRetcode = MNG_NOERROR;
+
+ if (pChunk) /* store this chunk ? */
+ mng_add_chunk (pData, pChunk); /* do it */
+
+#ifdef MNG_INCLUDE_JNG /* implicit EOF ? */
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR) && (!pData->bHasJHDR))
+#else
+ if ((!pData->bHasMHDR) && (!pData->bHasIHDR))
+#endif
+ iRetcode = mng_process_eof (pData);/* then do some EOF processing */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_PROCESS_RAW_CHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode check_chunk_crc (mng_datap pData,
+ mng_uint8p pBuf,
+ mng_uint32 iBuflen)
+{
+ mng_uint32 iCrc; /* calculated CRC */
+ mng_bool bDiscard = MNG_FALSE;
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_START);
+#endif
+
+ if (pData->iCrcmode & MNG_CRC_INPUT) /* crc included ? */
+ {
+ mng_bool bCritical = (mng_bool)((*pBuf & 0x20) == 0);
+ mng_uint32 iL = iBuflen - (mng_uint32)(sizeof (iCrc));
+
+ if (((bCritical ) && (pData->iCrcmode & MNG_CRC_CRITICAL )) ||
+ ((!bCritical) && (pData->iCrcmode & MNG_CRC_ANCILLARY)))
+ { /* calculate the crc */
+ iCrc = mng_crc (pData, pBuf, iL);
+ /* and check it */
+ if (!(iCrc == mng_get_uint32 (pBuf + iL)))
+ {
+ mng_bool bWarning = MNG_FALSE;
+ mng_bool bError = MNG_FALSE;
+
+ if (bCritical)
+ {
+ switch (pData->iCrcmode & MNG_CRC_CRITICAL)
+ {
+ case MNG_CRC_CRITICAL_WARNING : { bWarning = MNG_TRUE; break; }
+ case MNG_CRC_CRITICAL_ERROR : { bError = MNG_TRUE; break; }
+ }
+ }
+ else
+ {
+ switch (pData->iCrcmode & MNG_CRC_ANCILLARY)
+ {
+ case MNG_CRC_ANCILLARY_DISCARD : { bDiscard = MNG_TRUE; break; }
+ case MNG_CRC_ANCILLARY_WARNING : { bWarning = MNG_TRUE; break; }
+ case MNG_CRC_ANCILLARY_ERROR : { bError = MNG_TRUE; break; }
+ }
+ }
+
+ if (bWarning)
+ MNG_WARNING (pData, MNG_INVALIDCRC);
+ if (bError)
+ MNG_ERROR (pData, MNG_INVALIDCRC);
+ }
+ }
+
+ if (!bDiscard) /* still processing ? */
+ iRetcode = process_raw_chunk (pData, pBuf, iL);
+ }
+ else
+ { /* no crc => straight onto processing */
+ iRetcode = process_raw_chunk (pData, pBuf, iBuflen);
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHUNK_CRC, MNG_LC_END);
+#endif
+
+ return iRetcode;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode read_chunk (mng_datap pData)
+{
+ mng_uint32 iBufmax = pData->iReadbufsize;
+ mng_uint8p pBuf = pData->pReadbuf;
+ mng_uint32 iBuflen = 0; /* number of bytes requested */
+ mng_uint32 iRead = 0; /* number of bytes read */
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_START);
+#endif
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (pData->pCurraniobj) /* processing an animation object ? */
+ {
+ do /* process it then */
+ {
+ iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
+ /* refresh needed ? */
+/* if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
+ iRetcode = display_progressive_refresh (pData, 1); */
+ /* can we advance to next object ? */
+ if ((!iRetcode) && (pData->pCurraniobj) &&
+ (!pData->bTimerset) && (!pData->bSectionwait))
+ { /* reset timer indicator on read-cycle */
+ if ((pData->bReading) && (!pData->bDisplaying))
+ pData->bTimerset = MNG_FALSE;
+
+ pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
+ /* TERM processing to be done ? */
+ if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
+ iRetcode = mng_process_display_mend (pData);
+ }
+ } /* until error or a break or no more objects */
+ while ((!iRetcode) && (pData->pCurraniobj) &&
+ (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
+ }
+ else
+ {
+ if (pData->iBreakpoint) /* do we need to finish something first ? */
+ {
+ switch (pData->iBreakpoint) /* return to broken display routine */
+ {
+#ifndef MNG_SKIPCHUNK_FRAM
+ case 1 : { iRetcode = mng_process_display_fram2 (pData); break; }
+#endif
+ case 2 : { iRetcode = mng_process_display_ihdr (pData); break; }
+#ifndef MNG_SKIPCHUNK_SHOW
+ case 3 : ; /* same as 4 !!! */
+ case 4 : { iRetcode = mng_process_display_show (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ case 5 : { iRetcode = mng_process_display_clon2 (pData); break; }
+#endif
+#ifdef MNG_INCLUDE_JNG
+ case 7 : { iRetcode = mng_process_display_jhdr (pData); break; }
+#endif
+ case 6 : ; /* same as 8 !!! */
+ case 8 : { iRetcode = mng_process_display_iend (pData); break; }
+#ifndef MNG_SKIPCHUNK_MAGN
+ case 9 : { iRetcode = mng_process_display_magn2 (pData); break; }
+#endif
+ case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
+#ifndef MNG_SKIPCHUNK_PAST
+ case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
+#endif
+ }
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#endif /* MNG_SUPPORT_DISPLAY */
+ /* can we continue processing now, or do we */
+ /* need to wait for the timer to finish (again) ? */
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
+#else
+ if (!pData->bEOF)
+#endif
+ {
+#ifdef MNG_SUPPORT_DISPLAY
+ /* freezing in progress ? */
+ if ((pData->bFreezing) && (pData->iSuspendpoint == 0))
+ pData->bRunning = MNG_FALSE; /* then this is the right moment to do it */
+#endif
+
+ if (pData->iSuspendpoint <= 2)
+ {
+ iBuflen = sizeof (mng_uint32); /* read length */
+ iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
+
+ if (iRetcode) /* bail on errors */
+ return iRetcode;
+
+ if (pData->bSuspended) /* suspended ? */
+ pData->iSuspendpoint = 2;
+ else /* save the length */
+ {
+ pData->iChunklen = mng_get_uint32 (pBuf);
+ if (pData->iChunklen > 0x7ffffff)
+ return MNG_INVALIDLENGTH;
+ }
+
+ }
+
+ if (!pData->bSuspended) /* still going ? */
+ { /* previously suspended or not eof ? */
+ if ((pData->iSuspendpoint > 2) || (iRead == iBuflen))
+ { /* determine length chunkname + data (+ crc) */
+ if (pData->iCrcmode & MNG_CRC_INPUT)
+ iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid) + sizeof (mng_uint32));
+ else
+ iBuflen = pData->iChunklen + (mng_uint32)(sizeof (mng_chunkid));
+
+ /* do we have enough data in the current push buffer ? */
+ if ((pData->pFirstpushdata) && (iBuflen <= pData->pFirstpushdata->iRemaining))
+ {
+ mng_pushdatap pPush = pData->pFirstpushdata;
+ pBuf = pPush->pDatanext;
+ pPush->pDatanext += iBuflen;
+ pPush->iRemaining -= iBuflen;
+ pData->iSuspendpoint = 0; /* safely reset this here ! */
+
+ iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
+ if (iRetcode)
+ return iRetcode;
+
+ if (!pPush->iRemaining) /* buffer depleted? then release it */
+ iRetcode = mng_release_pushdata (pData);
+ }
+ else
+ {
+ if (iBuflen < iBufmax) /* does it fit in default buffer ? */
+ { /* note that we don't use the full size
+ so there's always a zero-byte at the
+ very end !!! */
+ iRetcode = read_databuffer (pData, pBuf, &pData->pReadbufnext, iBuflen, &iRead);
+ if (iRetcode) /* bail on errors */
+ return iRetcode;
+
+ if (pData->bSuspended) /* suspended ? */
+ pData->iSuspendpoint = 3;
+ else
+ {
+ if (iRead != iBuflen) /* did we get all the data ? */
+ MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
+ iRetcode = check_chunk_crc (pData, pBuf, iBuflen);
+ }
+ }
+ else
+ {
+ if (iBuflen > 16777216) /* is the length incredible? */
+ MNG_ERROR (pData, MNG_IMPROBABLELENGTH);
+
+ if (!pData->iSuspendpoint) /* create additional large buffer ? */
+ { /* again reserve space for the last zero-byte */
+ pData->iLargebufsize = iBuflen + 1;
+ pData->pLargebufnext = MNG_NULL;
+ MNG_ALLOC (pData, pData->pLargebuf, pData->iLargebufsize);
+ }
+
+ iRetcode = read_databuffer (pData, pData->pLargebuf, &pData->pLargebufnext, iBuflen, &iRead);
+ if (iRetcode)
+ return iRetcode;
+
+ if (pData->bSuspended) /* suspended ? */
+ pData->iSuspendpoint = 4;
+ else
+ {
+ if (iRead != iBuflen) /* did we get all the data ? */
+ MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
+ iRetcode = check_chunk_crc (pData, pData->pLargebuf, iBuflen);
+ /* cleanup additional large buffer */
+ MNG_FREE (pData, pData->pLargebuf, pData->iLargebufsize);
+ }
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ }
+ else
+ { /* that's final */
+ iRetcode = mng_process_eof (pData);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+ if ((iRead != 0) || /* did we get an unexpected eof ? */
+#ifdef MNG_INCLUDE_JNG
+ (pData->bHasIHDR || pData->bHasMHDR || pData->bHasJHDR))
+#else
+ (pData->bHasIHDR || pData->bHasMHDR))
+#endif
+ MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
+ }
+ }
+ }
+
+#ifdef MNG_SUPPORT_DISPLAY /* refresh needed ? */
+ if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
+ {
+ iRetcode = mng_display_progressive_refresh (pData, 1);
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_CHUNK, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+MNG_LOCAL mng_retcode process_pushedchunk (mng_datap pData)
+{
+ mng_pushdatap pPush;
+ mng_retcode iRetcode = MNG_NOERROR;
+
+#ifdef MNG_SUPPORT_DISPLAY
+ if (pData->pCurraniobj) /* processing an animation object ? */
+ {
+ do /* process it then */
+ {
+ iRetcode = ((mng_object_headerp)pData->pCurraniobj)->fProcess (pData, pData->pCurraniobj);
+ /* refresh needed ? */
+/* if ((!iRetcode) && (!pData->bTimerset) && (pData->bNeedrefresh))
+ iRetcode = display_progressive_refresh (pData, 1); */
+ /* can we advance to next object ? */
+ if ((!iRetcode) && (pData->pCurraniobj) &&
+ (!pData->bTimerset) && (!pData->bSectionwait))
+ { /* reset timer indicator on read-cycle */
+ if ((pData->bReading) && (!pData->bDisplaying))
+ pData->bTimerset = MNG_FALSE;
+
+ pData->pCurraniobj = ((mng_object_headerp)pData->pCurraniobj)->pNext;
+ /* TERM processing to be done ? */
+ if ((!pData->pCurraniobj) && (pData->bHasTERM) && (!pData->bHasMHDR))
+ iRetcode = mng_process_display_mend (pData);
+ }
+ } /* until error or a break or no more objects */
+ while ((!iRetcode) && (pData->pCurraniobj) &&
+ (!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bFreezing));
+ }
+ else
+ {
+ if (pData->iBreakpoint) /* do we need to finish something first ? */
+ {
+ switch (pData->iBreakpoint) /* return to broken display routine */
+ {
+#ifndef MNG_SKIPCHUNK_FRAM
+ case 1 : { iRetcode = mng_process_display_fram2 (pData); break; }
+#endif
+ case 2 : { iRetcode = mng_process_display_ihdr (pData); break; }
+#ifndef MNG_SKIPCHUNK_SHOW
+ case 3 : ; /* same as 4 !!! */
+ case 4 : { iRetcode = mng_process_display_show (pData); break; }
+#endif
+#ifndef MNG_SKIPCHUNK_CLON
+ case 5 : { iRetcode = mng_process_display_clon2 (pData); break; }
+#endif
+#ifdef MNG_INCLUDE_JNG
+ case 7 : { iRetcode = mng_process_display_jhdr (pData); break; }
+#endif
+ case 6 : ; /* same as 8 !!! */
+ case 8 : { iRetcode = mng_process_display_iend (pData); break; }
+#ifndef MNG_SKIPCHUNK_MAGN
+ case 9 : { iRetcode = mng_process_display_magn2 (pData); break; }
+#endif
+ case 10 : { iRetcode = mng_process_display_mend2 (pData); break; }
+#ifndef MNG_SKIPCHUNK_PAST
+ case 11 : { iRetcode = mng_process_display_past2 (pData); break; }
+#endif
+ }
+ }
+ }
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+
+#endif /* MNG_SUPPORT_DISPLAY */
+ /* can we continue processing now, or do we */
+ /* need to wait for the timer to finish (again) ? */
+#ifdef MNG_SUPPORT_DISPLAY
+ if ((!pData->bTimerset) && (!pData->bSectionwait) && (!pData->bEOF))
+#else
+ if (!pData->bEOF)
+#endif
+ {
+ pData->iSuspendpoint = 0; /* safely reset it here ! */
+ pPush = pData->pFirstpushchunk;
+
+ iRetcode = process_raw_chunk (pData, pPush->pData, pPush->iLength);
+ if (iRetcode)
+ return iRetcode;
+
+#ifdef MNG_SUPPORT_DISPLAY /* refresh needed ? */
+ if ((!pData->bTimerset) && (!pData->bSuspended) && (pData->bNeedrefresh))
+ {
+ iRetcode = mng_display_progressive_refresh (pData, 1);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#endif
+ }
+
+ return mng_release_pushchunk (pData);
+}
+
+/* ************************************************************************** */
+
+mng_retcode mng_read_graphic (mng_datap pData)
+{
+ mng_uint32 iBuflen; /* number of bytes requested */
+ mng_uint32 iRead; /* number of bytes read */
+ mng_retcode iRetcode; /* temporary error-code */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_START);
+#endif
+
+ if (!pData->pReadbuf) /* buffer allocated ? */
+ {
+ pData->iReadbufsize = 4200; /* allocate a default read buffer */
+ MNG_ALLOC (pData, pData->pReadbuf, pData->iReadbufsize);
+ }
+ /* haven't processed the signature ? */
+ if ((!pData->bHavesig) || (pData->iSuspendpoint == 1))
+ {
+ iBuflen = 2 * sizeof (mng_uint32); /* read signature */
+
+ iRetcode = read_databuffer (pData, pData->pReadbuf, &pData->pReadbufnext, iBuflen, &iRead);
+
+ if (iRetcode)
+ return iRetcode;
+
+ if (pData->bSuspended) /* input suspension ? */
+ pData->iSuspendpoint = 1;
+ else
+ {
+ if (iRead != iBuflen) /* full signature received ? */
+ MNG_ERROR (pData, MNG_UNEXPECTEDEOF);
+ /* is it a valid signature ? */
+ if (mng_get_uint32 (pData->pReadbuf) == PNG_SIG)
+ pData->eSigtype = mng_it_png;
+ else
+#ifdef MNG_INCLUDE_JNG
+ if (mng_get_uint32 (pData->pReadbuf) == JNG_SIG)
+ pData->eSigtype = mng_it_jng;
+ else
+#endif
+ if (mng_get_uint32 (pData->pReadbuf) == MNG_SIG)
+ pData->eSigtype = mng_it_mng;
+ else
+ MNG_ERROR (pData, MNG_INVALIDSIG);
+ /* all of it ? */
+ if (mng_get_uint32 (pData->pReadbuf+4) != POST_SIG)
+ MNG_ERROR (pData, MNG_INVALIDSIG);
+
+ pData->bHavesig = MNG_TRUE;
+ }
+ }
+
+ if (!pData->bSuspended) /* still going ? */
+ {
+ do
+ { /* reset timer during mng_read() ? */
+ if ((pData->bReading) && (!pData->bDisplaying))
+ pData->bTimerset = MNG_FALSE;
+
+ if (pData->pFirstpushchunk) /* chunks pushed ? */
+ iRetcode = process_pushedchunk (pData); /* process the pushed chunk */
+ else
+ iRetcode = read_chunk (pData); /* read & process a chunk */
+
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+#ifdef MNG_SUPPORT_DISPLAY /* until EOF or a break-request */
+ while (((!pData->bEOF) || (pData->pCurraniobj)) &&
+ (!pData->bSuspended) && (!pData->bSectionwait) &&
+ ((!pData->bTimerset) || ((pData->bReading) && (!pData->bDisplaying))));
+#else
+ while ((!pData->bEOF) && (!pData->bSuspended));
+#endif
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_READ_GRAPHIC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_READ_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_read.h b/Source/LibMNG/libmng_read.h
new file mode 100644
index 0000000..119cc3e
--- /dev/null
+++ b/Source/LibMNG/libmng_read.h
@@ -0,0 +1,53 @@
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_read.h copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.8 * */
+/* * * */
+/* * purpose : Read management (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the read management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 10/18/2000 - G.Juyn * */
+/* * - added closestream() processing for mng_cleanup() * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.8 - 04/12/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_read_h_
+#define _libmng_read_h_
+
+/* ************************************************************************** */
+
+mng_retcode mng_process_eof (mng_datap pData);
+
+mng_retcode mng_release_pushdata (mng_datap pData);
+
+mng_retcode mng_release_pushchunk (mng_datap pData);
+
+mng_retcode mng_read_graphic (mng_datap pData);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_read_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_trace.c b/Source/LibMNG/libmng_trace.c
new file mode 100644
index 0000000..a6a2cab
--- /dev/null
+++ b/Source/LibMNG/libmng_trace.c
@@ -0,0 +1,1683 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_trace.c copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Trace functions (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the trace functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - added callback error-reporting support * */
+/* * * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - added trace telltale reporting * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added tracestrings for global animation color-chunks * */
+/* * - added tracestrings for get/set of default ZLIB/IJG parms * */
+/* * - added tracestrings for global PLTE,tRNS,bKGD * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added tracestrings for image-object promotion * */
+/* * - added tracestrings for delta-image processing * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - added tracestrings for getalphaline callback * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - added tracestring for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added tracestring for mng_read_resume HLAPI function * */
+/* * * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added tracestrings for get/set speedtype * */
+/* * - added tracestring for get imagelevel * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added tracestring for delta-image processing * */
+/* * - added tracestrings for PPLT chunk processing * */
+/* * * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - added tracecodes for special display processing * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added tracestring for get/set suspensionmode * */
+/* * - added tracestrings for get/set display variables * */
+/* * - added tracecode for read_databuffer (I/O-suspension) * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added tracestrings for SAVE/SEEK callbacks * */
+/* * - added tracestrings for get/set sectionbreaks * */
+/* * - added tracestring for special error routine * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - added tracestring for updatemngheader * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - added tracestrings for status_xxxxx functions * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * - added tracestring for updatemngsimplicity * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added JDAA chunk * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added functions to retrieve PNG/JNG specific header-info * */
+/* * - added optional support for bKGD for PNG images * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * - added routine to discard "invalid" objects * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - implemented delayed delta-processing * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - added get/set for bKGD preference setting * */
+/* * 0.9.3 - 10/21/2000 - G.Juyn * */
+/* * - added get function for interlace/progressive display * */
+/* * * */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - added "new" MAGN methods 3, 4 & 5 * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * - added processterm callback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.3 - 08/06/2001 - G.Juyn * */
+/* * - added get function for last processed BACK chunk * */
+/* * * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added in-memory color-correction of abstract images * */
+/* * - added compose over/under routines for PAST processing * */
+/* * - added flip & tile routines for PAST processing * */
+/* * 1.0.5 - 10/09/2002 - G.Juyn * */
+/* * - fixed trace-constants for PAST chunk * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added conditionals around JNG and Delta-PNG code * */
+/* * 1.0.6 - 07/14/2003 - G.R-P * */
+/* * - added conditionals around various unused functions * */
+/* * 1.0.6 - 07/29/2003 - G.R-P * */
+/* * - added conditionals around PAST chunk support * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 03/07/2004 - G. Randers-Pehrson * */
+/* * - put gamma, cms-related declarations inside #ifdef * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/11/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * * */
+/* * 1.0.9 - 10/03/2004 - G.Juyn * */
+/* * - added function to retrieve current FRAM delay * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 07/06/2007 - G.R-P bugfix by Lucas Quintana * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_TRACE_PROCS
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_TRACE_STRINGS
+MNG_LOCAL mng_trace_entry const trace_table [] =
+ {
+ {MNG_FN_INITIALIZE, "initialize"},
+ {MNG_FN_RESET, "reset"},
+ {MNG_FN_CLEANUP, "cleanup"},
+ {MNG_FN_READ, "read"},
+ {MNG_FN_WRITE, "write"},
+ {MNG_FN_CREATE, "create"},
+ {MNG_FN_READDISPLAY, "readdisplay"},
+ {MNG_FN_DISPLAY, "display"},
+ {MNG_FN_DISPLAY_RESUME, "display_resume"},
+ {MNG_FN_DISPLAY_FREEZE, "display_freeze"},
+ {MNG_FN_DISPLAY_RESET, "display_reset"},
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+ {MNG_FN_DISPLAY_GOFRAME, "display_goframe"},
+ {MNG_FN_DISPLAY_GOLAYER, "display_golayer"},
+ {MNG_FN_DISPLAY_GOTIME, "display_gotime"},
+#endif
+ {MNG_FN_GETLASTERROR, "getlasterror"},
+ {MNG_FN_READ_RESUME, "read_resume"},
+ {MNG_FN_TRAPEVENT, "trapevent"},
+ {MNG_FN_READ_PUSHDATA, "read_pushdata"},
+ {MNG_FN_READ_PUSHSIG, "read_pushsig"},
+ {MNG_FN_READ_PUSHCHUNK, "read_pushchunk"},
+
+ {MNG_FN_SETCB_MEMALLOC, "setcb_memalloc"},
+ {MNG_FN_SETCB_MEMFREE, "setcb_memfree"},
+ {MNG_FN_SETCB_READDATA, "setcb_readdata"},
+ {MNG_FN_SETCB_WRITEDATA, "setcb_writedata"},
+ {MNG_FN_SETCB_ERRORPROC, "setcb_errorproc"},
+ {MNG_FN_SETCB_TRACEPROC, "setcb_traceproc"},
+ {MNG_FN_SETCB_PROCESSHEADER, "setcb_processheader"},
+ {MNG_FN_SETCB_PROCESSTEXT, "setcb_processtext"},
+ {MNG_FN_SETCB_GETCANVASLINE, "setcb_getcanvasline"},
+ {MNG_FN_SETCB_GETBKGDLINE, "setcb_getbkgdline"},
+ {MNG_FN_SETCB_REFRESH, "setcb_refresh"},
+ {MNG_FN_SETCB_GETTICKCOUNT, "setcb_gettickcount"},
+ {MNG_FN_SETCB_SETTIMER, "setcb_settimer"},
+ {MNG_FN_SETCB_PROCESSGAMMA, "setcb_processgamma"},
+ {MNG_FN_SETCB_PROCESSCHROMA, "setcb_processchroma"},
+ {MNG_FN_SETCB_PROCESSSRGB, "setcb_processsrgb"},
+ {MNG_FN_SETCB_PROCESSICCP, "setcb_processiccp"},
+ {MNG_FN_SETCB_PROCESSAROW, "setcb_processarow"},
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {MNG_FN_SETCB_OPENSTREAM, "setcb_openstream"},
+ {MNG_FN_SETCB_CLOSESTREAM, "setcb_closestream"},
+#endif
+ {MNG_FN_SETCB_GETALPHALINE, "setcb_getalphaline"},
+ {MNG_FN_SETCB_PROCESSSAVE, "setcb_processsave"},
+ {MNG_FN_SETCB_PROCESSSEEK, "setcb_processseek"},
+ {MNG_FN_SETCB_PROCESSNEED, "setcb_processneed"},
+ {MNG_FN_SETCB_PROCESSUNKNOWN, "setcb_processunknown"},
+ {MNG_FN_SETCB_PROCESSMEND, "setcb_processmend"},
+ {MNG_FN_SETCB_PROCESSTERM, "setcb_processterm"},
+ {MNG_FN_SETCB_RELEASEDATA, "setcb_releasedata"},
+
+ {MNG_FN_GETCB_MEMALLOC, "getcb_memalloc"},
+ {MNG_FN_GETCB_MEMFREE, "getcb_memfree"},
+ {MNG_FN_GETCB_READDATA, "getcb_readdata,"},
+ {MNG_FN_GETCB_WRITEDATA, "getcb_writedata"},
+ {MNG_FN_GETCB_ERRORPROC, "getcb_errorproc"},
+ {MNG_FN_GETCB_TRACEPROC, "getcb_traceproc"},
+ {MNG_FN_GETCB_PROCESSHEADER, "getcb_processheader"},
+ {MNG_FN_GETCB_PROCESSTEXT, "getcb_processtext"},
+ {MNG_FN_GETCB_GETCANVASLINE, "getcb_getcanvasline"},
+ {MNG_FN_GETCB_GETBKGDLINE, "getcb_getbkgdline"},
+ {MNG_FN_GETCB_REFRESH, "getcb_refresh"},
+ {MNG_FN_GETCB_GETTICKCOUNT, "getcb_gettickcount"},
+ {MNG_FN_GETCB_SETTIMER, "getcb_settimer"},
+ {MNG_FN_GETCB_PROCESSGAMMA, "getcb_processgamma"},
+ {MNG_FN_GETCB_PROCESSCHROMA, "getcb_processchroma"},
+ {MNG_FN_GETCB_PROCESSSRGB, "getcb_processsrgb"},
+ {MNG_FN_GETCB_PROCESSICCP, "getcb_processiccp"},
+ {MNG_FN_GETCB_PROCESSAROW, "getcb_processarow"},
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ {MNG_FN_GETCB_OPENSTREAM, "getcb_openstream"},
+ {MNG_FN_GETCB_CLOSESTREAM, "getcb_closestream"},
+#endif
+ {MNG_FN_GETCB_GETALPHALINE, "getcb_getalphaline"},
+ {MNG_FN_GETCB_PROCESSSAVE, "getcb_processsave"},
+ {MNG_FN_GETCB_PROCESSSEEK, "getcb_processseek"},
+ {MNG_FN_GETCB_PROCESSNEED, "getcb_processneed"},
+ {MNG_FN_GETCB_PROCESSUNKNOWN, "getcb_processunknown"},
+ {MNG_FN_GETCB_PROCESSMEND, "getcb_processmend"},
+ {MNG_FN_GETCB_PROCESSTERM, "getcb_processterm"},
+ {MNG_FN_GETCB_RELEASEDATA, "getcb_releasedata"},
+
+ {MNG_FN_SET_USERDATA, "set_userdata"},
+ {MNG_FN_SET_CANVASSTYLE, "set_canvasstyle"},
+ {MNG_FN_SET_BKGDSTYLE, "set_bkgdstyle"},
+ {MNG_FN_SET_BGCOLOR, "set_bgcolor"},
+ {MNG_FN_SET_STORECHUNKS, "set_storechunks"},
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+ {MNG_FN_SET_VIEWGAMMA, "set_viewgamma"},
+#ifndef MNG_NO_DFLT_INFO
+ {MNG_FN_SET_DISPLAYGAMMA, "set_displaygamma"},
+#endif
+ {MNG_FN_SET_DFLTIMGGAMMA, "set_dfltimggamma"},
+#endif
+ {MNG_FN_SET_SRGB, "set_srgb"},
+ {MNG_FN_SET_OUTPUTPROFILE, "set_outputprofile"},
+ {MNG_FN_SET_SRGBPROFILE, "set_srgbprofile"},
+#ifndef MNG_SKIP_MAXCANVAS
+ {MNG_FN_SET_MAXCANVASWIDTH, "set_maxcanvaswidth"},
+ {MNG_FN_SET_MAXCANVASHEIGHT, "set_maxcanvasheight"},
+ {MNG_FN_SET_MAXCANVASSIZE, "set_maxcanvassize"},
+#endif
+#ifndef MNG_NO_ACCESS_ZLIB
+ {MNG_FN_SET_ZLIB_LEVEL, "set_zlib_level"},
+ {MNG_FN_SET_ZLIB_METHOD, "set_zlib_method"},
+ {MNG_FN_SET_ZLIB_WINDOWBITS, "set_zlib_windowbits"},
+ {MNG_FN_SET_ZLIB_MEMLEVEL, "set_zlib_memlevel"},
+ {MNG_FN_SET_ZLIB_STRATEGY, "set_zlib_strategy"},
+ {MNG_FN_SET_ZLIB_MAXIDAT, "set_zlib_maxidat"},
+#endif
+#ifndef MNG_NO_ACCESS_JPEG
+ {MNG_FN_SET_JPEG_DCTMETHOD, "set_jpeg_dctmethod"},
+ {MNG_FN_SET_JPEG_QUALITY, "set_jpeg_quality"},
+ {MNG_FN_SET_JPEG_SMOOTHING, "set_jpeg_smoothing"},
+ {MNG_FN_SET_JPEG_PROGRESSIVE, "set_jpeg_progressive"},
+ {MNG_FN_SET_JPEG_OPTIMIZED, "set_jpeg_optimized"},
+ {MNG_FN_SET_JPEG_MAXJDAT, "set_jpeg_maxjdat"},
+#endif
+ {MNG_FN_SET_SPEED, "set_speed"},
+ {MNG_FN_SET_SUSPENSIONMODE, "set_suspensionmode"},
+ {MNG_FN_SET_SECTIONBREAKS, "set_sectionbreaks"},
+ {MNG_FN_SET_USEBKGD, "set_usebkgd"},
+ {MNG_FN_SET_OUTPUTPROFILE2, "set_outputprofile2"},
+ {MNG_FN_SET_SRGBPROFILE2, "set_srgbprofile2"},
+ {MNG_FN_SET_OUTPUTSRGB, "set_outputsrgb"},
+ {MNG_FN_SET_SRGBIMPLICIT, "set_srgbimplicit"},
+ {MNG_FN_SET_CACHEPLAYBACK, "set_cacheplayback"},
+ {MNG_FN_SET_DOPROGRESSIVE, "set_doprogressive"},
+ {MNG_FN_SET_CRCMODE, "set_crcmode"},
+
+ {MNG_FN_GET_USERDATA, "get_userdata"},
+ {MNG_FN_GET_SIGTYPE, "get_sigtype"},
+ {MNG_FN_GET_IMAGETYPE, "get_imagetype"},
+ {MNG_FN_GET_IMAGEWIDTH, "get_imagewidth"},
+ {MNG_FN_GET_IMAGEHEIGHT, "get_imageheight"},
+ {MNG_FN_GET_TICKS, "get_ticks"},
+ {MNG_FN_GET_FRAMECOUNT, "get_framecount"},
+ {MNG_FN_GET_LAYERCOUNT, "get_layercount"},
+ {MNG_FN_GET_PLAYTIME, "get_playtime"},
+ {MNG_FN_GET_SIMPLICITY, "get_simplicity"},
+ {MNG_FN_GET_CANVASSTYLE, "get_canvasstyle"},
+ {MNG_FN_GET_BKGDSTYLE, "get_bkgdstyle"},
+ {MNG_FN_GET_BGCOLOR, "get_bgcolor"},
+ {MNG_FN_GET_STORECHUNKS, "get_storechunks"},
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+ {MNG_FN_GET_VIEWGAMMA, "get_viewgamma"},
+ {MNG_FN_GET_DISPLAYGAMMA, "get_displaygamma"},
+#ifndef MNG_NO_DFLT_INFO
+ {MNG_FN_GET_DFLTIMGGAMMA, "get_dfltimggamma"},
+#endif
+#endif
+ {MNG_FN_GET_SRGB, "get_srgb"},
+#ifndef MNG_SKIP_MAXCANVAS
+ {MNG_FN_GET_MAXCANVASWIDTH, "get_maxcanvaswidth"},
+ {MNG_FN_GET_MAXCANVASHEIGHT, "get_maxcanvasheight"},
+#endif
+#ifndef MNG_NO_ACCESS_ZLIB
+ {MNG_FN_GET_ZLIB_LEVEL, "get_zlib_level"},
+ {MNG_FN_GET_ZLIB_METHOD, "get_zlib_method"},
+ {MNG_FN_GET_ZLIB_WINDOWBITS, "get_zlib_windowbits"},
+ {MNG_FN_GET_ZLIB_MEMLEVEL, "get_zlib_memlevel"},
+ {MNG_FN_GET_ZLIB_STRATEGY, "get_zlib_strategy"},
+ {MNG_FN_GET_ZLIB_MAXIDAT, "get_zlib_maxidat"},
+#endif
+#ifndef MNG_NO_ACCESS_JPEG
+ {MNG_FN_GET_JPEG_DCTMETHOD, "get_jpeg_dctmethod"},
+ {MNG_FN_GET_JPEG_QUALITY, "get_jpeg_quality"},
+ {MNG_FN_GET_JPEG_SMOOTHING, "get_jpeg_smoothing"},
+ {MNG_FN_GET_JPEG_PROGRESSIVE, "get_jpeg_progressive"},
+ {MNG_FN_GET_JPEG_OPTIMIZED, "get_jpeg_optimized"},
+ {MNG_FN_GET_JPEG_MAXJDAT, "get_jpeg_maxjdat"},
+#endif
+ {MNG_FN_GET_SPEED, "get_speed"},
+ {MNG_FN_GET_IMAGELEVEL, "get_imagelevel"},
+ {MNG_FN_GET_SUSPENSIONMODE, "get_speed"},
+ {MNG_FN_GET_STARTTIME, "get_starttime"},
+ {MNG_FN_GET_RUNTIME, "get_runtime"},
+#ifndef MNG_NO_CURRENT_INFO
+ {MNG_FN_GET_CURRENTFRAME, "get_currentframe"},
+ {MNG_FN_GET_CURRENTLAYER, "get_currentlayer"},
+ {MNG_FN_GET_CURRENTPLAYTIME, "get_currentplaytime"},
+#endif
+ {MNG_FN_GET_SECTIONBREAKS, "get_sectionbreaks"},
+ {MNG_FN_GET_ALPHADEPTH, "get_alphadepth"},
+ {MNG_FN_GET_BITDEPTH, "get_bitdepth"},
+ {MNG_FN_GET_COLORTYPE, "get_colortype"},
+ {MNG_FN_GET_COMPRESSION, "get_compression"},
+ {MNG_FN_GET_FILTER, "get_filter"},
+ {MNG_FN_GET_INTERLACE, "get_interlace"},
+ {MNG_FN_GET_ALPHABITDEPTH, "get_alphabitdepth"},
+ {MNG_FN_GET_ALPHACOMPRESSION, "get_alphacompression"},
+ {MNG_FN_GET_ALPHAFILTER, "get_alphafilter"},
+ {MNG_FN_GET_ALPHAINTERLACE, "get_alphainterlace"},
+ {MNG_FN_GET_USEBKGD, "get_usebkgd"},
+ {MNG_FN_GET_REFRESHPASS, "get_refreshpass"},
+ {MNG_FN_GET_CACHEPLAYBACK, "get_cacheplayback"},
+ {MNG_FN_GET_DOPROGRESSIVE, "get_doprogressive"},
+ {MNG_FN_GET_LASTBACKCHUNK, "get_lastbackchunk"},
+ {MNG_FN_GET_LASTSEEKNAME, "get_lastseekname"},
+#ifndef MNG_NO_CURRENT_INFO
+ {MNG_FN_GET_TOTALFRAMES, "get_totalframes"},
+ {MNG_FN_GET_TOTALLAYERS, "get_totallayers"},
+ {MNG_FN_GET_TOTALPLAYTIME, "get_totalplaytime"},
+#endif
+ {MNG_FN_GET_CRCMODE, "get_crcmode"},
+ {MNG_FN_GET_CURRFRAMDELAY, "get_currframdelay"},
+
+ {MNG_FN_STATUS_ERROR, "status_error"},
+ {MNG_FN_STATUS_READING, "status_reading"},
+ {MNG_FN_STATUS_SUSPENDBREAK, "status_suspendbreak"},
+ {MNG_FN_STATUS_CREATING, "status_creating"},
+ {MNG_FN_STATUS_WRITING, "status_writing"},
+ {MNG_FN_STATUS_DISPLAYING, "status_displaying"},
+ {MNG_FN_STATUS_RUNNING, "status_running"},
+ {MNG_FN_STATUS_TIMERBREAK, "status_timerbreak"},
+ {MNG_FN_STATUS_DYNAMIC, "status_dynamic"},
+ {MNG_FN_STATUS_RUNNINGEVENT, "status_runningevent"},
+
+ {MNG_FN_ITERATE_CHUNKS, "iterate_chunks"},
+ {MNG_FN_COPY_CHUNK, "copy_chunk"},
+
+ {MNG_FN_GETCHUNK_IHDR, "getchunk_ihdr"},
+ {MNG_FN_GETCHUNK_PLTE, "getchunk_plte"},
+ {MNG_FN_GETCHUNK_IDAT, "getchunk_idat"},
+ {MNG_FN_GETCHUNK_IEND, "getchunk_iend"},
+ {MNG_FN_GETCHUNK_TRNS, "getchunk_trns"},
+#ifndef MNG_SKIPCHUNK_gAMA
+ {MNG_FN_GETCHUNK_GAMA, "getchunk_gama"},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {MNG_FN_GETCHUNK_CHRM, "getchunk_chrm"},
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+ {MNG_FN_GETCHUNK_SRGB, "getchunk_srgb"},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {MNG_FN_GETCHUNK_ICCP, "getchunk_iccp"},
+#endif
+#ifndef MNG_SKIPCHUNK_tEXt
+ {MNG_FN_GETCHUNK_TEXT, "getchunk_text"},
+#endif
+#ifndef MNG_SKIPCHUNK_zTXt
+ {MNG_FN_GETCHUNK_ZTXT, "getchunk_ztxt"},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {MNG_FN_GETCHUNK_ITXT, "getchunk_itxt"},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {MNG_FN_GETCHUNK_BKGD, "getchunk_bkgd"},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {MNG_FN_GETCHUNK_PHYS, "getchunk_phys"},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {MNG_FN_GETCHUNK_SBIT, "getchunk_sbit"},
+#endif
+#ifndef MNG_SKIPCHUNK_sPLT
+ {MNG_FN_GETCHUNK_SPLT, "getchunk_splt"},
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+ {MNG_FN_GETCHUNK_HIST, "getchunk_hist"},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {MNG_FN_GETCHUNK_TIME, "getchunk_time"},
+#endif
+ {MNG_FN_GETCHUNK_MHDR, "getchunk_mhdr"},
+ {MNG_FN_GETCHUNK_MEND, "getchunk_mend"},
+#ifndef MNG_SKIPCHUNK_LOOP
+ {MNG_FN_GETCHUNK_LOOP, "getchunk_loop"},
+ {MNG_FN_GETCHUNK_ENDL, "getchunk_endl"},
+#endif
+ {MNG_FN_GETCHUNK_DEFI, "getchunk_defi"},
+#ifndef MNG_SKIPCHUNK_BASI
+ {MNG_FN_GETCHUNK_BASI, "getchunk_basi"},
+#endif
+ {MNG_FN_GETCHUNK_CLON, "getchunk_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_GETCHUNK_PAST, "getchunk_past"},
+#endif
+ {MNG_FN_GETCHUNK_DISC, "getchunk_disc"},
+ {MNG_FN_GETCHUNK_BACK, "getchunk_back"},
+ {MNG_FN_GETCHUNK_FRAM, "getchunk_fram"},
+ {MNG_FN_GETCHUNK_MOVE, "getchunk_move"},
+ {MNG_FN_GETCHUNK_CLIP, "getchunk_clip"},
+ {MNG_FN_GETCHUNK_SHOW, "getchunk_show"},
+ {MNG_FN_GETCHUNK_TERM, "getchunk_term"},
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_FN_GETCHUNK_SAVE, "getchunk_save"},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {MNG_FN_GETCHUNK_SEEK, "getchunk_seek"},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {MNG_FN_GETCHUNK_EXPI, "getchunk_expi"},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {MNG_FN_GETCHUNK_FPRI, "getchunk_fpri"},
+#endif
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_FN_GETCHUNK_NEED, "getchunk_need"},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYg
+ {MNG_FN_GETCHUNK_PHYG, "getchunk_phyg"},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_GETCHUNK_JHDR, "getchunk_jhdr"},
+ {MNG_FN_GETCHUNK_JDAT, "getchunk_jdat"},
+ {MNG_FN_GETCHUNK_JSEP, "getchunk_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_GETCHUNK_DHDR, "getchunk_dhdr"},
+ {MNG_FN_GETCHUNK_PROM, "getchunk_prom"},
+ {MNG_FN_GETCHUNK_IPNG, "getchunk_ipng"},
+ {MNG_FN_GETCHUNK_PPLT, "getchunk_pplt"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_GETCHUNK_IJNG, "getchunk_ijng"},
+#endif
+#ifndef MNG_SKIPCHUNK_DROP
+ {MNG_FN_GETCHUNK_DROP, "getchunk_drop"},
+#endif
+#ifndef MNG_SKIPCHUNK_DBYK
+ {MNG_FN_GETCHUNK_DBYK, "getchunk_dbyk"},
+#endif
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_FN_GETCHUNK_ORDR, "getchunk_ordr"},
+#endif
+#endif
+ {MNG_FN_GETCHUNK_UNKNOWN, "getchunk_unknown"},
+ {MNG_FN_GETCHUNK_MAGN, "getchunk_magn"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_GETCHUNK_JDAA, "getchunk_jdaa"},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_FN_GETCHUNK_EVNT, "getchunk_evnt"},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_GETCHUNK_MPNG, "getchunk_mpng"},
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_GETCHUNK_PAST_SRC, "getchunk_past_src"},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_FN_GETCHUNK_SAVE_ENTRY, "getchunk_save_entry"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_GETCHUNK_PPLT_ENTRY, "getchunk_pplt_entry"},
+ {MNG_FN_GETCHUNK_ORDR_ENTRY, "getchunk_ordr_entry"},
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_FN_GETCHUNK_EVNT_ENTRY, "getchunk_evnt_entry"},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_GETCHUNK_MPNG_FRAME, "getchunk_mpng_frame"},
+#endif
+
+ {MNG_FN_PUTCHUNK_IHDR, "putchunk_ihdr"},
+ {MNG_FN_PUTCHUNK_PLTE, "putchunk_plte"},
+ {MNG_FN_PUTCHUNK_IDAT, "putchunk_idat"},
+ {MNG_FN_PUTCHUNK_IEND, "putchunk_iend"},
+ {MNG_FN_PUTCHUNK_TRNS, "putchunk_trns"},
+#ifndef MNG_SKIPCHUNK_gAMA
+ {MNG_FN_PUTCHUNK_GAMA, "putchunk_gama"},
+#endif
+#ifndef MNG_SKIPCHUNK_cHRM
+ {MNG_FN_PUTCHUNK_CHRM, "putchunk_chrm"},
+#endif
+#ifndef MNG_SKIPCHUNK_sRGB
+ {MNG_FN_PUTCHUNK_SRGB, "putchunk_srgb"},
+#endif
+#ifndef MNG_SKIPCHUNK_iCCP
+ {MNG_FN_PUTCHUNK_ICCP, "putchunk_iccp"},
+#endif
+#ifndef MNG_SKIPCHUNK_tEXt
+ {MNG_FN_PUTCHUNK_TEXT, "putchunk_text"},
+#endif
+#ifndef MNG_SKIPCHUNK_zTXt
+ {MNG_FN_PUTCHUNK_ZTXT, "putchunk_ztxt"},
+#endif
+#ifndef MNG_SKIPCHUNK_iTXt
+ {MNG_FN_PUTCHUNK_ITXT, "putchunk_itxt"},
+#endif
+#ifndef MNG_SKIPCHUNK_bKGD
+ {MNG_FN_PUTCHUNK_BKGD, "putchunk_bkgd"},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYs
+ {MNG_FN_PUTCHUNK_PHYS, "putchunk_phys"},
+#endif
+#ifndef MNG_SKIPCHUNK_sBIT
+ {MNG_FN_PUTCHUNK_SBIT, "putchunk_sbit"},
+#endif
+#ifndef MNG_SKIPCHUNK_sPLT
+ {MNG_FN_PUTCHUNK_SPLT, "putchunk_splt"},
+#endif
+#ifndef MNG_SKIPCHUNK_hIST
+ {MNG_FN_PUTCHUNK_HIST, "putchunk_hist"},
+#endif
+#ifndef MNG_SKIPCHUNK_tIME
+ {MNG_FN_PUTCHUNK_TIME, "putchunk_time"},
+#endif
+ {MNG_FN_PUTCHUNK_MHDR, "putchunk_mhdr"},
+ {MNG_FN_PUTCHUNK_MEND, "putchunk_mend"},
+ {MNG_FN_PUTCHUNK_LOOP, "putchunk_loop"},
+ {MNG_FN_PUTCHUNK_ENDL, "putchunk_endl"},
+ {MNG_FN_PUTCHUNK_DEFI, "putchunk_defi"},
+ {MNG_FN_PUTCHUNK_BASI, "putchunk_basi"},
+ {MNG_FN_PUTCHUNK_CLON, "putchunk_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_PUTCHUNK_PAST, "putchunk_past"},
+#endif
+ {MNG_FN_PUTCHUNK_DISC, "putchunk_disc"},
+ {MNG_FN_PUTCHUNK_BACK, "putchunk_back"},
+ {MNG_FN_PUTCHUNK_FRAM, "putchunk_fram"},
+ {MNG_FN_PUTCHUNK_MOVE, "putchunk_move"},
+ {MNG_FN_PUTCHUNK_CLIP, "putchunk_clip"},
+ {MNG_FN_PUTCHUNK_SHOW, "putchunk_show"},
+ {MNG_FN_PUTCHUNK_TERM, "putchunk_term"},
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_FN_PUTCHUNK_SAVE, "putchunk_save"},
+#endif
+#ifndef MNG_SKIPCHUNK_SEEK
+ {MNG_FN_PUTCHUNK_SEEK, "putchunk_seek"},
+#endif
+#ifndef MNG_SKIPCHUNK_eXPI
+ {MNG_FN_PUTCHUNK_EXPI, "putchunk_expi"},
+#endif
+#ifndef MNG_SKIPCHUNK_fPRI
+ {MNG_FN_PUTCHUNK_FPRI, "putchunk_fpri"},
+#endif
+#ifndef MNG_SKIPCHUNK_nEED
+ {MNG_FN_PUTCHUNK_NEED, "putchunk_need"},
+#endif
+#ifndef MNG_SKIPCHUNK_pHYg
+ {MNG_FN_PUTCHUNK_PHYG, "putchunk_phyg"},
+#endif
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PUTCHUNK_JHDR, "putchunk_jhdr"},
+ {MNG_FN_PUTCHUNK_JDAT, "putchunk_jdat"},
+ {MNG_FN_PUTCHUNK_JSEP, "putchunk_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_PUTCHUNK_DHDR, "putchunk_dhdr"},
+ {MNG_FN_PUTCHUNK_PROM, "putchunk_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PUTCHUNK_IPNG, "putchunk_ipng"},
+#endif
+ {MNG_FN_PUTCHUNK_PPLT, "putchunk_pplt"},
+ {MNG_FN_PUTCHUNK_IJNG, "putchunk_ijng"},
+#ifndef MNG_SKIPCHUNK_DROP
+ {MNG_FN_PUTCHUNK_DROP, "putchunk_drop"},
+#endif
+#ifndef MNG_SKIPCHUNK_DBYK
+ {MNG_FN_PUTCHUNK_DBYK, "putchunk_dbyk"},
+#endif
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_FN_PUTCHUNK_ORDR, "putchunk_ordr"},
+#endif
+#endif
+ {MNG_FN_PUTCHUNK_UNKNOWN, "putchunk_unknown"},
+ {MNG_FN_PUTCHUNK_MAGN, "putchunk_magn"},
+ {MNG_FN_PUTCHUNK_JDAA, "putchunk_jdaa"},
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_FN_PUTCHUNK_EVNT, "putchunk_evnt"},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_PUTCHUNK_MPNG, "putchunk_mpng"},
+#endif
+
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_PUTCHUNK_PAST_SRC, "putchunk_past_src"},
+#endif
+#ifndef MNG_SKIPCHUNK_SAVE
+ {MNG_FN_PUTCHUNK_SAVE_ENTRY, "putchunk_save_entry"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_PUTCHUNK_PPLT_ENTRY, "putchunk_pplt_entry"},
+#ifndef MNG_SKIPCHUNK_ORDR
+ {MNG_FN_PUTCHUNK_ORDR_ENTRY, "putchunk_ordr_entry"},
+#endif
+#endif
+#ifndef MNG_SKIPCHUNK_evNT
+ {MNG_FN_PUTCHUNK_EVNT_ENTRY, "putchunk_evnt_entry"},
+#endif
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_PUTCHUNK_MPNG_FRAME, "putchunk_mpng_frame"},
+#endif
+
+ {MNG_FN_GETIMGDATA_SEQ, "getimgdata_seq"},
+ {MNG_FN_GETIMGDATA_CHUNKSEQ, "getimgdata_chunkseq"},
+ {MNG_FN_GETIMGDATA_CHUNK, "getimgdata_chunk"},
+
+ {MNG_FN_PUTIMGDATA_IHDR, "putimgdata_ihdr"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PUTIMGDATA_JHDR, "putimgdata_jhdr"},
+ {MNG_FN_PUTIMGDATA_BASI, "putimgdata_basi"},
+ {MNG_FN_PUTIMGDATA_DHDR, "putimgdata_dhdr"},
+#endif
+
+ {MNG_FN_UPDATEMNGHEADER, "updatemngheader"},
+ {MNG_FN_UPDATEMNGSIMPLICITY, "updatemngsimplicity"},
+
+ {MNG_FN_PROCESS_RAW_CHUNK, "process_raw_chunk"},
+ {MNG_FN_READ_GRAPHIC, "read_graphic"},
+ {MNG_FN_DROP_CHUNKS, "drop_chunks"},
+ {MNG_FN_PROCESS_ERROR, "process_error"},
+ {MNG_FN_CLEAR_CMS, "clear_cms"},
+ {MNG_FN_DROP_OBJECTS, "drop_objects"},
+ {MNG_FN_READ_CHUNK, "read_chunk"},
+ {MNG_FN_LOAD_BKGDLAYER, "load_bkgdlayer"},
+ {MNG_FN_NEXT_FRAME, "next_frame"},
+ {MNG_FN_NEXT_LAYER, "next_layer"},
+ {MNG_FN_INTERFRAME_DELAY, "interframe_delay"},
+ {MNG_FN_DISPLAY_IMAGE, "display_image"},
+ {MNG_FN_DROP_IMGOBJECTS, "drop_imgobjects"},
+ {MNG_FN_DROP_ANIOBJECTS, "drop_aniobjects"},
+ {MNG_FN_INFLATE_BUFFER, "inflate_buffer"},
+ {MNG_FN_DEFLATE_BUFFER, "deflate_buffer"},
+ {MNG_FN_WRITE_RAW_CHUNK, "write_raw_chunk"},
+ {MNG_FN_WRITE_GRAPHIC, "write_graphic"},
+ {MNG_FN_SAVE_STATE, "save_state"},
+ {MNG_FN_RESTORE_STATE, "restore_state"},
+ {MNG_FN_DROP_SAVEDATA, "drop_savedata"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_EXECUTE_DELTA_IMAGE, "execute_delta_image"},
+#endif
+ {MNG_FN_PROCESS_DISPLAY, "process_display"},
+ {MNG_FN_CLEAR_CANVAS, "clear_canvas"},
+ {MNG_FN_READ_DATABUFFER, "read_databuffer"},
+ {MNG_FN_STORE_ERROR, "store_error"},
+ {MNG_FN_DROP_INVALID_OBJECTS, "drop_invalid_objects"},
+ {MNG_FN_RELEASE_PUSHDATA, "release_pushdata"},
+ {MNG_FN_READ_DATA, "read_data"},
+ {MNG_FN_READ_CHUNK_CRC, "read_chunk_crc"},
+ {MNG_FN_RELEASE_PUSHCHUNK, "release_pushchunk"},
+
+ {MNG_FN_DISPLAY_RGB8, "display_rgb8"},
+ {MNG_FN_DISPLAY_RGBA8, "display_rgba8"},
+ {MNG_FN_DISPLAY_ARGB8, "display_argb8"},
+ {MNG_FN_DISPLAY_BGR8, "display_bgr8"},
+ {MNG_FN_DISPLAY_BGRA8, "display_bgra8"},
+ {MNG_FN_DISPLAY_ABGR8, "display_abgr8"},
+ {MNG_FN_DISPLAY_RGB16, "display_rgb16"},
+ {MNG_FN_DISPLAY_RGBA16, "display_rgba16"},
+ {MNG_FN_DISPLAY_ARGB16, "display_argb16"},
+ {MNG_FN_DISPLAY_BGR16, "display_bgr16"},
+ {MNG_FN_DISPLAY_BGRA16, "display_bgra16"},
+ {MNG_FN_DISPLAY_ABGR16, "display_abgr16"},
+ {MNG_FN_DISPLAY_INDEX8, "display_index8"},
+ {MNG_FN_DISPLAY_INDEXA8, "display_indexa8"},
+ {MNG_FN_DISPLAY_AINDEX8, "display_aindex8"},
+ {MNG_FN_DISPLAY_GRAY8, "display_gray8"},
+ {MNG_FN_DISPLAY_GRAY16, "display_gray16"},
+ {MNG_FN_DISPLAY_GRAYA8, "display_graya8"},
+ {MNG_FN_DISPLAY_GRAYA16, "display_graya16"},
+ {MNG_FN_DISPLAY_AGRAY8, "display_agray8"},
+ {MNG_FN_DISPLAY_AGRAY16, "display_agray16"},
+ {MNG_FN_DISPLAY_DX15, "display_dx15"},
+ {MNG_FN_DISPLAY_DX16, "display_dx16"},
+ {MNG_FN_DISPLAY_RGB8_A8, "display_rgb8_a8"},
+ {MNG_FN_DISPLAY_BGRA8PM, "display_bgra8_pm"},
+ {MNG_FN_DISPLAY_BGRX8, "display_bgrx8"},
+ {MNG_FN_DISPLAY_RGB565, "display_rgb565"},
+ {MNG_FN_DISPLAY_RGBA565, "display_rgba565"},
+ {MNG_FN_DISPLAY_BGR565, "display_bgr565"},
+ {MNG_FN_DISPLAY_BGRA565, "display_bgra565"},
+ {MNG_FN_DISPLAY_RGBA8_PM, "display_rgba8_pm"},
+ {MNG_FN_DISPLAY_ARGB8_PM, "display_argb8_pm"},
+ {MNG_FN_DISPLAY_ABGR8_PM, "display_abgr8_pm"},
+ {MNG_FN_DISPLAY_BGR565_A8, "display_bgr565_a8"},
+
+ {MNG_FN_INIT_FULL_CMS, "init_full_cms"},
+ {MNG_FN_CORRECT_FULL_CMS, "correct_full_cms"},
+ {MNG_FN_INIT_GAMMA_ONLY, "init_gamma_only"},
+ {MNG_FN_CORRECT_GAMMA_ONLY, "correct_gamma_only"},
+ {MNG_FN_CORRECT_APP_CMS, "correct_app_cms"},
+ {MNG_FN_INIT_FULL_CMS_OBJ, "init_full_cms_obj"},
+ {MNG_FN_INIT_GAMMA_ONLY_OBJ, "init_gamma_only_obj"},
+ {MNG_FN_INIT_APP_CMS, "init_app_cms"},
+ {MNG_FN_INIT_APP_CMS_OBJ, "init_app_cms_obj"},
+
+ {MNG_FN_PROCESS_G1, "process_g1"},
+ {MNG_FN_PROCESS_G2, "process_g2"},
+ {MNG_FN_PROCESS_G4, "process_g4"},
+ {MNG_FN_PROCESS_G8, "process_g8"},
+ {MNG_FN_PROCESS_G16, "process_g16"},
+ {MNG_FN_PROCESS_RGB8, "process_rgb8"},
+ {MNG_FN_PROCESS_RGB16, "process_rgb16"},
+ {MNG_FN_PROCESS_IDX1, "process_idx1"},
+ {MNG_FN_PROCESS_IDX2, "process_idx2"},
+ {MNG_FN_PROCESS_IDX4, "process_idx4"},
+ {MNG_FN_PROCESS_IDX8, "process_idx8"},
+ {MNG_FN_PROCESS_GA8, "process_ga8"},
+ {MNG_FN_PROCESS_GA16, "process_ga16"},
+ {MNG_FN_PROCESS_RGBA8, "process_rgba8"},
+ {MNG_FN_PROCESS_RGBA16, "process_rgba16"},
+
+ {MNG_FN_INIT_G1_I, "init_g1_i"},
+ {MNG_FN_INIT_G2_I, "init_g2_i"},
+ {MNG_FN_INIT_G4_I, "init_g4_i"},
+ {MNG_FN_INIT_G8_I, "init_g8_i"},
+ {MNG_FN_INIT_G16_I, "init_g16_i"},
+ {MNG_FN_INIT_RGB8_I, "init_rgb8_i"},
+ {MNG_FN_INIT_RGB16_I, "init_rgb16_i"},
+ {MNG_FN_INIT_IDX1_I, "init_idx1_i"},
+ {MNG_FN_INIT_IDX2_I, "init_idx2_i"},
+ {MNG_FN_INIT_IDX4_I, "init_idx4_i"},
+ {MNG_FN_INIT_IDX8_I, "init_idx8_i"},
+ {MNG_FN_INIT_GA8_I, "init_ga8_i"},
+ {MNG_FN_INIT_GA16_I, "init_ga16_i"},
+ {MNG_FN_INIT_RGBA8_I, "init_rgba8_i"},
+ {MNG_FN_INIT_RGBA16_I, "init_rgba16_i"},
+#ifndef MNG_OPTIMIZE_FOOTPRINT_INIT
+ {MNG_FN_INIT_G1_NI, "init_g1_ni"},
+ {MNG_FN_INIT_G2_NI, "init_g2_ni"},
+ {MNG_FN_INIT_G4_NI, "init_g4_ni"},
+ {MNG_FN_INIT_G8_NI, "init_g8_ni"},
+ {MNG_FN_INIT_G16_NI, "init_g16_ni"},
+ {MNG_FN_INIT_RGB8_NI, "init_rgb8_ni"},
+ {MNG_FN_INIT_RGB16_NI, "init_rgb16_ni"},
+ {MNG_FN_INIT_IDX1_NI, "init_idx1_ni"},
+ {MNG_FN_INIT_IDX2_NI, "init_idx2_ni"},
+ {MNG_FN_INIT_IDX4_NI, "init_idx4_ni"},
+ {MNG_FN_INIT_IDX8_NI, "init_idx8_ni"},
+ {MNG_FN_INIT_GA8_NI, "init_ga8_ni"},
+ {MNG_FN_INIT_GA16_NI, "init_ga16_ni"},
+ {MNG_FN_INIT_RGBA8_NI, "init_rgba8_ni"},
+ {MNG_FN_INIT_RGBA16_NI, "init_rgba16_ni"},
+#endif
+
+ {MNG_FN_INIT_ROWPROC, "init_rowproc"},
+ {MNG_FN_NEXT_ROW, "next_row"},
+ {MNG_FN_CLEANUP_ROWPROC, "cleanup_rowproc"},
+
+ {MNG_FN_FILTER_A_ROW, "filter_a_row"},
+ {MNG_FN_FILTER_SUB, "filter_sub"},
+ {MNG_FN_FILTER_UP, "filter_up"},
+ {MNG_FN_FILTER_AVERAGE, "filter_average"},
+ {MNG_FN_FILTER_PAETH, "filter_paeth"},
+
+ {MNG_FN_INIT_ROWDIFFERING, "init_rowdiffering"},
+ {MNG_FN_DIFFER_G1, "differ_g1"},
+ {MNG_FN_DIFFER_G2, "differ_g2"},
+ {MNG_FN_DIFFER_G4, "differ_g4"},
+ {MNG_FN_DIFFER_G8, "differ_g8"},
+ {MNG_FN_DIFFER_G16, "differ_g16"},
+ {MNG_FN_DIFFER_RGB8, "differ_rgb8"},
+ {MNG_FN_DIFFER_RGB16, "differ_rgb16"},
+ {MNG_FN_DIFFER_IDX1, "differ_idx1"},
+ {MNG_FN_DIFFER_IDX2, "differ_idx2"},
+ {MNG_FN_DIFFER_IDX4, "differ_idx4"},
+ {MNG_FN_DIFFER_IDX8, "differ_idx8"},
+ {MNG_FN_DIFFER_GA8, "differ_ga8"},
+ {MNG_FN_DIFFER_GA16, "differ_ga16"},
+ {MNG_FN_DIFFER_RGBA8, "differ_rgba8"},
+ {MNG_FN_DIFFER_RGBA16, "differ_rgba16"},
+
+ {MNG_FN_CREATE_IMGDATAOBJECT, "create_imgdataobject"},
+ {MNG_FN_FREE_IMGDATAOBJECT, "free_imgdataobject"},
+ {MNG_FN_CLONE_IMGDATAOBJECT, "clone_imgdataobject"},
+ {MNG_FN_CREATE_IMGOBJECT, "create_imgobject"},
+ {MNG_FN_FREE_IMGOBJECT, "free_imgobject"},
+ {MNG_FN_FIND_IMGOBJECT, "find_imgobject"},
+ {MNG_FN_CLONE_IMGOBJECT, "clone_imgobject"},
+ {MNG_FN_RESET_OBJECTDETAILS, "reset_objectdetails"},
+ {MNG_FN_RENUM_IMGOBJECT, "renum_imgobject"},
+ {MNG_FN_PROMOTE_IMGOBJECT, "promote_imgobject"},
+ {MNG_FN_MAGNIFY_IMGOBJECT, "magnify_imgobject"},
+ {MNG_FN_COLORCORRECT_OBJECT, "colorcorrect_object"},
+
+ {MNG_FN_STORE_G1, "store_g1"},
+ {MNG_FN_STORE_G2, "store_g2"},
+ {MNG_FN_STORE_G4, "store_g4"},
+ {MNG_FN_STORE_G8, "store_g8"},
+ {MNG_FN_STORE_G16, "store_g16"},
+ {MNG_FN_STORE_RGB8, "store_rgb8"},
+ {MNG_FN_STORE_RGB16, "store_rgb16"},
+ {MNG_FN_STORE_IDX1, "store_idx1"},
+ {MNG_FN_STORE_IDX2, "store_idx2"},
+ {MNG_FN_STORE_IDX4, "store_idx4"},
+ {MNG_FN_STORE_IDX8, "store_idx8"},
+ {MNG_FN_STORE_GA8, "store_ga8"},
+ {MNG_FN_STORE_GA16, "store_ga16"},
+ {MNG_FN_STORE_RGBA8, "store_rgba8"},
+ {MNG_FN_STORE_RGBA16, "store_rgba16"},
+
+ {MNG_FN_RETRIEVE_G8, "retrieve_g8"},
+ {MNG_FN_RETRIEVE_G16, "retrieve_g16"},
+ {MNG_FN_RETRIEVE_RGB8, "retrieve_rgb8"},
+ {MNG_FN_RETRIEVE_RGB16, "retrieve_rgb16"},
+ {MNG_FN_RETRIEVE_IDX8, "retrieve_idx8"},
+ {MNG_FN_RETRIEVE_GA8, "retrieve_ga8"},
+ {MNG_FN_RETRIEVE_GA16, "retrieve_ga16"},
+ {MNG_FN_RETRIEVE_RGBA8, "retrieve_rgba8"},
+ {MNG_FN_RETRIEVE_RGBA16, "retrieve_rgba16"},
+
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_DELTA_G1, "delta_g1"},
+ {MNG_FN_DELTA_G2, "delta_g2"},
+ {MNG_FN_DELTA_G4, "delta_g4"},
+ {MNG_FN_DELTA_G8, "delta_g8"},
+ {MNG_FN_DELTA_G16, "delta_g16"},
+ {MNG_FN_DELTA_RGB8, "delta_rgb8"},
+ {MNG_FN_DELTA_RGB16, "delta_rgb16"},
+ {MNG_FN_DELTA_IDX1, "delta_idx1"},
+ {MNG_FN_DELTA_IDX2, "delta_idx2"},
+ {MNG_FN_DELTA_IDX4, "delta_idx4"},
+ {MNG_FN_DELTA_IDX8, "delta_idx8"},
+ {MNG_FN_DELTA_GA8, "delta_ga8"},
+ {MNG_FN_DELTA_GA16, "delta_ga16"},
+ {MNG_FN_DELTA_RGBA8, "delta_rgba8"},
+ {MNG_FN_DELTA_RGBA16, "delta_rgba16"},
+#endif
+
+ {MNG_FN_CREATE_ANI_LOOP, "create_ani_loop"},
+ {MNG_FN_CREATE_ANI_ENDL, "create_ani_endl"},
+ {MNG_FN_CREATE_ANI_DEFI, "create_ani_defi"},
+ {MNG_FN_CREATE_ANI_BASI, "create_ani_basi"},
+ {MNG_FN_CREATE_ANI_CLON, "create_ani_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_CREATE_ANI_PAST, "create_ani_past"},
+#endif
+ {MNG_FN_CREATE_ANI_DISC, "create_ani_disc"},
+ {MNG_FN_CREATE_ANI_BACK, "create_ani_back"},
+ {MNG_FN_CREATE_ANI_FRAM, "create_ani_fram"},
+ {MNG_FN_CREATE_ANI_MOVE, "create_ani_move"},
+ {MNG_FN_CREATE_ANI_CLIP, "create_ani_clip"},
+ {MNG_FN_CREATE_ANI_SHOW, "create_ani_show"},
+ {MNG_FN_CREATE_ANI_TERM, "create_ani_term"},
+ {MNG_FN_CREATE_ANI_SAVE, "create_ani_save"},
+ {MNG_FN_CREATE_ANI_SEEK, "create_ani_seek"},
+ {MNG_FN_CREATE_ANI_GAMA, "create_ani_gama"},
+ {MNG_FN_CREATE_ANI_CHRM, "create_ani_chrm"},
+ {MNG_FN_CREATE_ANI_SRGB, "create_ani_srgb"},
+ {MNG_FN_CREATE_ANI_ICCP, "create_ani_iccp"},
+ {MNG_FN_CREATE_ANI_PLTE, "create_ani_plte"},
+ {MNG_FN_CREATE_ANI_TRNS, "create_ani_trns"},
+ {MNG_FN_CREATE_ANI_BKGD, "create_ani_bkgd"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_CREATE_ANI_DHDR, "create_ani_dhdr"},
+ {MNG_FN_CREATE_ANI_PROM, "create_ani_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_CREATE_ANI_IPNG, "create_ani_ipng"},
+#endif
+ {MNG_FN_CREATE_ANI_IJNG, "create_ani_ijng"},
+ {MNG_FN_CREATE_ANI_PPLT, "create_ani_pplt"},
+#endif
+ {MNG_FN_CREATE_ANI_MAGN, "create_ani_magn"},
+
+ {MNG_FN_CREATE_ANI_IMAGE, "create_ani_image"},
+ {MNG_FN_CREATE_EVENT, "create_event"},
+
+ {MNG_FN_FREE_ANI_LOOP, "free_ani_loop"},
+ {MNG_FN_FREE_ANI_ENDL, "free_ani_endl"},
+ {MNG_FN_FREE_ANI_DEFI, "free_ani_defi"},
+ {MNG_FN_FREE_ANI_BASI, "free_ani_basi"},
+ {MNG_FN_FREE_ANI_CLON, "free_ani_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_FREE_ANI_PAST, "free_ani_past"},
+#endif
+ {MNG_FN_FREE_ANI_DISC, "free_ani_disc"},
+ {MNG_FN_FREE_ANI_BACK, "free_ani_back"},
+ {MNG_FN_FREE_ANI_FRAM, "free_ani_fram"},
+ {MNG_FN_FREE_ANI_MOVE, "free_ani_move"},
+ {MNG_FN_FREE_ANI_CLIP, "free_ani_clip"},
+ {MNG_FN_FREE_ANI_SHOW, "free_ani_show"},
+ {MNG_FN_FREE_ANI_TERM, "free_ani_term"},
+ {MNG_FN_FREE_ANI_SAVE, "free_ani_save"},
+ {MNG_FN_FREE_ANI_SEEK, "free_ani_seek"},
+ {MNG_FN_FREE_ANI_GAMA, "free_ani_gama"},
+ {MNG_FN_FREE_ANI_CHRM, "free_ani_chrm"},
+ {MNG_FN_FREE_ANI_SRGB, "free_ani_srgb"},
+ {MNG_FN_FREE_ANI_ICCP, "free_ani_iccp"},
+ {MNG_FN_FREE_ANI_PLTE, "free_ani_plte"},
+ {MNG_FN_FREE_ANI_TRNS, "free_ani_trns"},
+ {MNG_FN_FREE_ANI_BKGD, "free_ani_bkgd"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_FREE_ANI_DHDR, "free_ani_dhdr"},
+ {MNG_FN_FREE_ANI_PROM, "free_ani_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_FREE_ANI_IPNG, "free_ani_ipng"},
+#endif
+ {MNG_FN_FREE_ANI_IJNG, "free_ani_ijng"},
+ {MNG_FN_FREE_ANI_PPLT, "free_ani_pplt"},
+#endif
+ {MNG_FN_FREE_ANI_MAGN, "free_ani_magn"},
+
+ {MNG_FN_FREE_ANI_IMAGE, "free_ani_image"},
+ {MNG_FN_FREE_EVENT, "free_event"},
+
+ {MNG_FN_PROCESS_ANI_LOOP, "process_ani_loop"},
+ {MNG_FN_PROCESS_ANI_ENDL, "process_ani_endl"},
+ {MNG_FN_PROCESS_ANI_DEFI, "process_ani_defi"},
+ {MNG_FN_PROCESS_ANI_BASI, "process_ani_basi"},
+ {MNG_FN_PROCESS_ANI_CLON, "process_ani_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_PROCESS_ANI_PAST, "process_ani_past"},
+#endif
+ {MNG_FN_PROCESS_ANI_DISC, "process_ani_disc"},
+ {MNG_FN_PROCESS_ANI_BACK, "process_ani_back"},
+ {MNG_FN_PROCESS_ANI_FRAM, "process_ani_fram"},
+ {MNG_FN_PROCESS_ANI_MOVE, "process_ani_move"},
+ {MNG_FN_PROCESS_ANI_CLIP, "process_ani_clip"},
+ {MNG_FN_PROCESS_ANI_SHOW, "process_ani_show"},
+ {MNG_FN_PROCESS_ANI_TERM, "process_ani_term"},
+ {MNG_FN_PROCESS_ANI_SAVE, "process_ani_save"},
+ {MNG_FN_PROCESS_ANI_SEEK, "process_ani_seek"},
+ {MNG_FN_PROCESS_ANI_GAMA, "process_ani_gama"},
+ {MNG_FN_PROCESS_ANI_CHRM, "process_ani_chrm"},
+ {MNG_FN_PROCESS_ANI_SRGB, "process_ani_srgb"},
+ {MNG_FN_PROCESS_ANI_ICCP, "process_ani_iccp"},
+ {MNG_FN_PROCESS_ANI_PLTE, "process_ani_plte"},
+ {MNG_FN_PROCESS_ANI_TRNS, "process_ani_trns"},
+ {MNG_FN_PROCESS_ANI_BKGD, "process_ani_bkgd"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_PROCESS_ANI_DHDR, "process_ani_dhdr"},
+ {MNG_FN_PROCESS_ANI_PROM, "process_ani_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PROCESS_ANI_IPNG, "process_ani_ipng"},
+#endif
+ {MNG_FN_PROCESS_ANI_IJNG, "process_ani_ijng"},
+ {MNG_FN_PROCESS_ANI_PPLT, "process_ani_pplt"},
+#endif
+ {MNG_FN_PROCESS_ANI_MAGN, "process_ani_magn"},
+
+ {MNG_FN_PROCESS_ANI_IMAGE, "process_ani_image"},
+ {MNG_FN_PROCESS_EVENT, "process_event"},
+
+ {MNG_FN_RESTORE_BACKIMAGE, "restore_backimage"},
+ {MNG_FN_RESTORE_BACKCOLOR, "restore_backcolor"},
+ {MNG_FN_RESTORE_BGCOLOR, "restore_bgcolor"},
+ {MNG_FN_RESTORE_RGB8, "restore_rgb8"},
+ {MNG_FN_RESTORE_BGR8, "restore_bgr8"},
+ {MNG_FN_RESTORE_BKGD, "restore_bkgd"},
+ {MNG_FN_RESTORE_BGRX8, "restore_bgrx8"},
+ {MNG_FN_RESTORE_RGB565, "restore_rgb565"},
+
+ {MNG_FN_INIT_IHDR, "init_ihdr"},
+ {MNG_FN_INIT_PLTE, "init_plte"},
+ {MNG_FN_INIT_IDAT, "init_idat"},
+ {MNG_FN_INIT_IEND, "init_iend"},
+ {MNG_FN_INIT_TRNS, "init_trns"},
+ {MNG_FN_INIT_GAMA, "init_gama"},
+ {MNG_FN_INIT_CHRM, "init_chrm"},
+ {MNG_FN_INIT_SRGB, "init_srgb"},
+ {MNG_FN_INIT_ICCP, "init_iccp"},
+ {MNG_FN_INIT_TEXT, "init_text"},
+ {MNG_FN_INIT_ZTXT, "init_ztxt"},
+ {MNG_FN_INIT_ITXT, "init_itxt"},
+ {MNG_FN_INIT_BKGD, "init_bkgd"},
+ {MNG_FN_INIT_PHYS, "init_phys"},
+ {MNG_FN_INIT_SBIT, "init_sbit"},
+ {MNG_FN_INIT_SPLT, "init_splt"},
+ {MNG_FN_INIT_HIST, "init_hist"},
+ {MNG_FN_INIT_TIME, "init_time"},
+ {MNG_FN_INIT_MHDR, "init_mhdr"},
+ {MNG_FN_INIT_MEND, "init_mend"},
+ {MNG_FN_INIT_LOOP, "init_loop"},
+ {MNG_FN_INIT_ENDL, "init_endl"},
+ {MNG_FN_INIT_DEFI, "init_defi"},
+ {MNG_FN_INIT_BASI, "init_basi"},
+ {MNG_FN_INIT_CLON, "init_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_INIT_PAST, "init_past"},
+#endif
+ {MNG_FN_INIT_DISC, "init_disc"},
+ {MNG_FN_INIT_BACK, "init_back"},
+ {MNG_FN_INIT_FRAM, "init_fram"},
+ {MNG_FN_INIT_MOVE, "init_move"},
+ {MNG_FN_INIT_CLIP, "init_clip"},
+ {MNG_FN_INIT_SHOW, "init_show"},
+ {MNG_FN_INIT_TERM, "init_term"},
+ {MNG_FN_INIT_SAVE, "init_save"},
+ {MNG_FN_INIT_SEEK, "init_seek"},
+ {MNG_FN_INIT_EXPI, "init_expi"},
+ {MNG_FN_INIT_FPRI, "init_fpri"},
+ {MNG_FN_INIT_NEED, "init_need"},
+ {MNG_FN_INIT_PHYG, "init_phyg"},
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_INIT_JHDR, "init_jhdr"},
+ {MNG_FN_INIT_JDAT, "init_jdat"},
+ {MNG_FN_INIT_JSEP, "init_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_INIT_DHDR, "init_dhdr"},
+ {MNG_FN_INIT_PROM, "init_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_INIT_IPNG, "init_ipng"},
+#endif
+ {MNG_FN_INIT_PPLT, "init_pplt"},
+ {MNG_FN_INIT_IJNG, "init_ijng"},
+ {MNG_FN_INIT_DROP, "init_drop"},
+ {MNG_FN_INIT_DBYK, "init_dbyk"},
+ {MNG_FN_INIT_ORDR, "init_ordr"},
+#endif
+ {MNG_FN_INIT_UNKNOWN, "init_unknown"},
+ {MNG_FN_INIT_MAGN, "init_magn"},
+ {MNG_FN_INIT_JDAA, "init_jdaa"},
+ {MNG_FN_INIT_EVNT, "init_evnt"},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_INIT_MPNG, "init_mpng"},
+#endif
+
+ {MNG_FN_ASSIGN_IHDR, "assign_ihdr"},
+ {MNG_FN_ASSIGN_PLTE, "assign_plte"},
+ {MNG_FN_ASSIGN_IDAT, "assign_idat"},
+ {MNG_FN_ASSIGN_IEND, "assign_iend"},
+ {MNG_FN_ASSIGN_TRNS, "assign_trns"},
+ {MNG_FN_ASSIGN_GAMA, "assign_gama"},
+ {MNG_FN_ASSIGN_CHRM, "assign_chrm"},
+ {MNG_FN_ASSIGN_SRGB, "assign_srgb"},
+ {MNG_FN_ASSIGN_ICCP, "assign_iccp"},
+ {MNG_FN_ASSIGN_TEXT, "assign_text"},
+ {MNG_FN_ASSIGN_ZTXT, "assign_ztxt"},
+ {MNG_FN_ASSIGN_ITXT, "assign_itxt"},
+ {MNG_FN_ASSIGN_BKGD, "assign_bkgd"},
+ {MNG_FN_ASSIGN_PHYS, "assign_phys"},
+ {MNG_FN_ASSIGN_SBIT, "assign_sbit"},
+ {MNG_FN_ASSIGN_SPLT, "assign_splt"},
+ {MNG_FN_ASSIGN_HIST, "assign_hist"},
+ {MNG_FN_ASSIGN_TIME, "assign_time"},
+ {MNG_FN_ASSIGN_MHDR, "assign_mhdr"},
+ {MNG_FN_ASSIGN_MEND, "assign_mend"},
+ {MNG_FN_ASSIGN_LOOP, "assign_loop"},
+ {MNG_FN_ASSIGN_ENDL, "assign_endl"},
+ {MNG_FN_ASSIGN_DEFI, "assign_defi"},
+ {MNG_FN_ASSIGN_BASI, "assign_basi"},
+ {MNG_FN_ASSIGN_CLON, "assign_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_ASSIGN_PAST, "assign_past"},
+#endif
+ {MNG_FN_ASSIGN_DISC, "assign_disc"},
+ {MNG_FN_ASSIGN_BACK, "assign_back"},
+ {MNG_FN_ASSIGN_FRAM, "assign_fram"},
+ {MNG_FN_ASSIGN_MOVE, "assign_move"},
+ {MNG_FN_ASSIGN_CLIP, "assign_clip"},
+ {MNG_FN_ASSIGN_SHOW, "assign_show"},
+ {MNG_FN_ASSIGN_TERM, "assign_term"},
+ {MNG_FN_ASSIGN_SAVE, "assign_save"},
+ {MNG_FN_ASSIGN_SEEK, "assign_seek"},
+ {MNG_FN_ASSIGN_EXPI, "assign_expi"},
+ {MNG_FN_ASSIGN_FPRI, "assign_fpri"},
+ {MNG_FN_ASSIGN_NEED, "assign_need"},
+ {MNG_FN_ASSIGN_PHYG, "assign_phyg"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_ASSIGN_JHDR, "assign_jhdr"},
+ {MNG_FN_ASSIGN_JDAT, "assign_jdat"},
+ {MNG_FN_ASSIGN_JSEP, "assign_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_ASSIGN_DHDR, "assign_dhdr"},
+ {MNG_FN_ASSIGN_PROM, "assign_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_ASSIGN_IPNG, "assign_ipng"},
+#endif
+ {MNG_FN_ASSIGN_PPLT, "assign_pplt"},
+ {MNG_FN_ASSIGN_IJNG, "assign_ijng"},
+ {MNG_FN_ASSIGN_DROP, "assign_drop"},
+ {MNG_FN_ASSIGN_DBYK, "assign_dbyk"},
+ {MNG_FN_ASSIGN_ORDR, "assign_ordr"},
+#endif
+ {MNG_FN_ASSIGN_UNKNOWN, "assign_unknown"},
+ {MNG_FN_ASSIGN_MAGN, "assign_magn"},
+ {MNG_FN_ASSIGN_JDAA, "assign_jdaa"},
+ {MNG_FN_ASSIGN_EVNT, "assign_evnt"},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_ASSIGN_MPNG, "assign_mpng"},
+#endif
+
+ {MNG_FN_FREE_IHDR, "free_ihdr"},
+ {MNG_FN_FREE_PLTE, "free_plte"},
+ {MNG_FN_FREE_IDAT, "free_idat"},
+ {MNG_FN_FREE_IEND, "free_iend"},
+ {MNG_FN_FREE_TRNS, "free_trns"},
+ {MNG_FN_FREE_GAMA, "free_gama"},
+ {MNG_FN_FREE_CHRM, "free_chrm"},
+ {MNG_FN_FREE_SRGB, "free_srgb"},
+ {MNG_FN_FREE_ICCP, "free_iccp"},
+ {MNG_FN_FREE_TEXT, "free_text"},
+ {MNG_FN_FREE_ZTXT, "free_ztxt"},
+ {MNG_FN_FREE_ITXT, "free_itxt"},
+ {MNG_FN_FREE_BKGD, "free_bkgd"},
+ {MNG_FN_FREE_PHYS, "free_phys"},
+ {MNG_FN_FREE_SBIT, "free_sbit"},
+ {MNG_FN_FREE_SPLT, "free_splt"},
+ {MNG_FN_FREE_HIST, "free_hist"},
+ {MNG_FN_FREE_TIME, "free_time"},
+ {MNG_FN_FREE_MHDR, "free_mhdr"},
+ {MNG_FN_FREE_MEND, "free_mend"},
+ {MNG_FN_FREE_LOOP, "free_loop"},
+ {MNG_FN_FREE_ENDL, "free_endl"},
+ {MNG_FN_FREE_DEFI, "free_defi"},
+ {MNG_FN_FREE_BASI, "free_basi"},
+ {MNG_FN_FREE_CLON, "free_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_FREE_PAST, "free_past"},
+#endif
+ {MNG_FN_FREE_DISC, "free_disc"},
+ {MNG_FN_FREE_BACK, "free_back"},
+ {MNG_FN_FREE_FRAM, "free_fram"},
+ {MNG_FN_FREE_MOVE, "free_move"},
+ {MNG_FN_FREE_CLIP, "free_clip"},
+ {MNG_FN_FREE_SHOW, "free_show"},
+ {MNG_FN_FREE_TERM, "free_term"},
+ {MNG_FN_FREE_SAVE, "free_save"},
+ {MNG_FN_FREE_SEEK, "free_seek"},
+ {MNG_FN_FREE_EXPI, "free_expi"},
+ {MNG_FN_FREE_FPRI, "free_fpri"},
+ {MNG_FN_FREE_NEED, "free_need"},
+ {MNG_FN_FREE_PHYG, "free_phyg"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_FREE_JHDR, "free_jhdr"},
+ {MNG_FN_FREE_JDAT, "free_jdat"},
+ {MNG_FN_FREE_JSEP, "free_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_FREE_DHDR, "free_dhdr"},
+ {MNG_FN_FREE_PROM, "free_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_FREE_IPNG, "free_ipng"},
+#endif
+ {MNG_FN_FREE_PPLT, "free_pplt"},
+ {MNG_FN_FREE_IJNG, "free_ijng"},
+ {MNG_FN_FREE_DROP, "free_drop"},
+ {MNG_FN_FREE_DBYK, "free_dbyk"},
+ {MNG_FN_FREE_ORDR, "free_ordr"},
+#endif
+ {MNG_FN_FREE_UNKNOWN, "free_unknown"},
+ {MNG_FN_FREE_MAGN, "free_magn"},
+ {MNG_FN_FREE_JDAA, "free_jdaa"},
+ {MNG_FN_FREE_EVNT, "free_evnt"},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_FREE_MPNG, "free_mpng"},
+#endif
+
+ {MNG_FN_READ_IHDR, "read_ihdr"},
+ {MNG_FN_READ_PLTE, "read_plte"},
+ {MNG_FN_READ_IDAT, "read_idat"},
+ {MNG_FN_READ_IEND, "read_iend"},
+ {MNG_FN_READ_TRNS, "read_trns"},
+ {MNG_FN_READ_GAMA, "read_gama"},
+ {MNG_FN_READ_CHRM, "read_chrm"},
+ {MNG_FN_READ_SRGB, "read_srgb"},
+ {MNG_FN_READ_ICCP, "read_iccp"},
+ {MNG_FN_READ_TEXT, "read_text"},
+ {MNG_FN_READ_ZTXT, "read_ztxt"},
+ {MNG_FN_READ_ITXT, "read_itxt"},
+ {MNG_FN_READ_BKGD, "read_bkgd"},
+ {MNG_FN_READ_PHYS, "read_phys"},
+ {MNG_FN_READ_SBIT, "read_sbit"},
+ {MNG_FN_READ_SPLT, "read_splt"},
+ {MNG_FN_READ_HIST, "read_hist"},
+ {MNG_FN_READ_TIME, "read_time"},
+ {MNG_FN_READ_MHDR, "read_mhdr"},
+ {MNG_FN_READ_MEND, "read_mend"},
+ {MNG_FN_READ_LOOP, "read_loop"},
+ {MNG_FN_READ_ENDL, "read_endl"},
+ {MNG_FN_READ_DEFI, "read_defi"},
+ {MNG_FN_READ_BASI, "read_basi"},
+ {MNG_FN_READ_CLON, "read_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_READ_PAST, "read_past"},
+#endif
+ {MNG_FN_READ_DISC, "read_disc"},
+ {MNG_FN_READ_BACK, "read_back"},
+ {MNG_FN_READ_FRAM, "read_fram"},
+ {MNG_FN_READ_MOVE, "read_move"},
+ {MNG_FN_READ_CLIP, "read_clip"},
+ {MNG_FN_READ_SHOW, "read_show"},
+ {MNG_FN_READ_TERM, "read_term"},
+ {MNG_FN_READ_SAVE, "read_save"},
+ {MNG_FN_READ_SEEK, "read_seek"},
+ {MNG_FN_READ_EXPI, "read_expi"},
+ {MNG_FN_READ_FPRI, "read_fpri"},
+ {MNG_FN_READ_NEED, "read_need"},
+ {MNG_FN_READ_PHYG, "read_phyg"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_READ_JHDR, "read_jhdr"},
+ {MNG_FN_READ_JDAT, "read_jdat"},
+ {MNG_FN_READ_JSEP, "read_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_READ_DHDR, "read_dhdr"},
+ {MNG_FN_READ_PROM, "read_prom"},
+ {MNG_FN_READ_IPNG, "read_ipng"},
+ {MNG_FN_READ_PPLT, "read_pplt"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_READ_IJNG, "read_ijng"},
+#endif
+ {MNG_FN_READ_DROP, "read_drop"},
+ {MNG_FN_READ_DBYK, "read_dbyk"},
+ {MNG_FN_READ_ORDR, "read_ordr"},
+#endif
+ {MNG_FN_READ_UNKNOWN, "read_unknown"},
+ {MNG_FN_READ_MAGN, "read_magn"},
+ {MNG_FN_READ_JDAA, "read_jdaa"},
+ {MNG_FN_READ_EVNT, "read_evnt"},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_READ_MPNG, "read_mpng"},
+#endif
+
+ {MNG_FN_WRITE_IHDR, "write_ihdr"},
+ {MNG_FN_WRITE_PLTE, "write_plte"},
+ {MNG_FN_WRITE_IDAT, "write_idat"},
+ {MNG_FN_WRITE_IEND, "write_iend"},
+ {MNG_FN_WRITE_TRNS, "write_trns"},
+ {MNG_FN_WRITE_GAMA, "write_gama"},
+ {MNG_FN_WRITE_CHRM, "write_chrm"},
+ {MNG_FN_WRITE_SRGB, "write_srgb"},
+ {MNG_FN_WRITE_ICCP, "write_iccp"},
+ {MNG_FN_WRITE_TEXT, "write_text"},
+ {MNG_FN_WRITE_ZTXT, "write_ztxt"},
+ {MNG_FN_WRITE_ITXT, "write_itxt"},
+ {MNG_FN_WRITE_BKGD, "write_bkgd"},
+ {MNG_FN_WRITE_PHYS, "write_phys"},
+ {MNG_FN_WRITE_SBIT, "write_sbit"},
+ {MNG_FN_WRITE_SPLT, "write_splt"},
+ {MNG_FN_WRITE_HIST, "write_hist"},
+ {MNG_FN_WRITE_TIME, "write_time"},
+ {MNG_FN_WRITE_MHDR, "write_mhdr"},
+ {MNG_FN_WRITE_MEND, "write_mend"},
+ {MNG_FN_WRITE_LOOP, "write_loop"},
+ {MNG_FN_WRITE_ENDL, "write_endl"},
+ {MNG_FN_WRITE_DEFI, "write_defi"},
+ {MNG_FN_WRITE_BASI, "write_basi"},
+ {MNG_FN_WRITE_CLON, "write_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_WRITE_PAST, "write_past"},
+#endif
+ {MNG_FN_WRITE_DISC, "write_disc"},
+ {MNG_FN_WRITE_BACK, "write_back"},
+ {MNG_FN_WRITE_FRAM, "write_fram"},
+ {MNG_FN_WRITE_MOVE, "write_move"},
+ {MNG_FN_WRITE_CLIP, "write_clip"},
+ {MNG_FN_WRITE_SHOW, "write_show"},
+ {MNG_FN_WRITE_TERM, "write_term"},
+ {MNG_FN_WRITE_SAVE, "write_save"},
+ {MNG_FN_WRITE_SEEK, "write_seek"},
+ {MNG_FN_WRITE_EXPI, "write_expi"},
+ {MNG_FN_WRITE_FPRI, "write_fpri"},
+ {MNG_FN_WRITE_NEED, "write_need"},
+ {MNG_FN_WRITE_PHYG, "write_phyg"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_WRITE_JHDR, "write_jhdr"},
+ {MNG_FN_WRITE_JDAT, "write_jdat"},
+ {MNG_FN_WRITE_JSEP, "write_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_WRITE_DHDR, "write_dhdr"},
+ {MNG_FN_WRITE_PROM, "write_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_WRITE_IPNG, "write_ipng"},
+#endif
+ {MNG_FN_WRITE_PPLT, "write_pplt"},
+ {MNG_FN_WRITE_IJNG, "write_ijng"},
+ {MNG_FN_WRITE_DROP, "write_drop"},
+ {MNG_FN_WRITE_DBYK, "write_dbyk"},
+ {MNG_FN_WRITE_ORDR, "write_ordr"},
+#endif
+ {MNG_FN_WRITE_UNKNOWN, "write_unknown"},
+ {MNG_FN_WRITE_MAGN, "write_magn"},
+ {MNG_FN_WRITE_JDAA, "write_jdaa"},
+ {MNG_FN_WRITE_EVNT, "write_evnt"},
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ {MNG_FN_WRITE_MPNG, "write_mpng"},
+#endif
+
+ {MNG_FN_ZLIB_INITIALIZE, "zlib_initialize"},
+ {MNG_FN_ZLIB_CLEANUP, "zlib_cleanup"},
+ {MNG_FN_ZLIB_INFLATEINIT, "zlib_inflateinit"},
+ {MNG_FN_ZLIB_INFLATEROWS, "zlib_inflaterows"},
+ {MNG_FN_ZLIB_INFLATEDATA, "zlib_inflatedata"},
+ {MNG_FN_ZLIB_INFLATEFREE, "zlib_inflatefree"},
+ {MNG_FN_ZLIB_DEFLATEINIT, "zlib_deflateinit"},
+ {MNG_FN_ZLIB_DEFLATEROWS, "zlib_deflaterows"},
+ {MNG_FN_ZLIB_DEFLATEDATA, "zlib_deflatedata"},
+ {MNG_FN_ZLIB_DEFLATEFREE, "zlib_deflatefree"},
+
+ {MNG_FN_PROCESS_DISPLAY_IHDR, "process_display_ihdr"},
+ {MNG_FN_PROCESS_DISPLAY_PLTE, "process_display_plte"},
+ {MNG_FN_PROCESS_DISPLAY_IDAT, "process_display_idat"},
+ {MNG_FN_PROCESS_DISPLAY_IEND, "process_display_iend"},
+ {MNG_FN_PROCESS_DISPLAY_TRNS, "process_display_trns"},
+ {MNG_FN_PROCESS_DISPLAY_GAMA, "process_display_gama"},
+ {MNG_FN_PROCESS_DISPLAY_CHRM, "process_display_chrm"},
+ {MNG_FN_PROCESS_DISPLAY_SRGB, "process_display_srgb"},
+ {MNG_FN_PROCESS_DISPLAY_ICCP, "process_display_iccp"},
+ {MNG_FN_PROCESS_DISPLAY_BKGD, "process_display_bkgd"},
+ {MNG_FN_PROCESS_DISPLAY_PHYS, "process_display_phys"},
+ {MNG_FN_PROCESS_DISPLAY_SBIT, "process_display_sbit"},
+ {MNG_FN_PROCESS_DISPLAY_SPLT, "process_display_splt"},
+ {MNG_FN_PROCESS_DISPLAY_HIST, "process_display_hist"},
+ {MNG_FN_PROCESS_DISPLAY_MHDR, "process_display_mhdr"},
+ {MNG_FN_PROCESS_DISPLAY_MEND, "process_display_mend"},
+ {MNG_FN_PROCESS_DISPLAY_LOOP, "process_display_loop"},
+ {MNG_FN_PROCESS_DISPLAY_ENDL, "process_display_endl"},
+ {MNG_FN_PROCESS_DISPLAY_DEFI, "process_display_defi"},
+ {MNG_FN_PROCESS_DISPLAY_BASI, "process_display_basi"},
+ {MNG_FN_PROCESS_DISPLAY_CLON, "process_display_clon"},
+#ifndef MNG_SKIPCHUNK_PAST
+ {MNG_FN_PROCESS_DISPLAY_PAST, "process_display_past"},
+#endif
+ {MNG_FN_PROCESS_DISPLAY_DISC, "process_display_disc"},
+ {MNG_FN_PROCESS_DISPLAY_BACK, "process_display_back"},
+ {MNG_FN_PROCESS_DISPLAY_FRAM, "process_display_fram"},
+ {MNG_FN_PROCESS_DISPLAY_MOVE, "process_display_move"},
+ {MNG_FN_PROCESS_DISPLAY_CLIP, "process_display_clip"},
+ {MNG_FN_PROCESS_DISPLAY_SHOW, "process_display_show"},
+ {MNG_FN_PROCESS_DISPLAY_TERM, "process_display_term"},
+ {MNG_FN_PROCESS_DISPLAY_SAVE, "process_display_save"},
+ {MNG_FN_PROCESS_DISPLAY_SEEK, "process_display_seek"},
+ {MNG_FN_PROCESS_DISPLAY_EXPI, "process_display_expi"},
+ {MNG_FN_PROCESS_DISPLAY_FPRI, "process_display_fpri"},
+ {MNG_FN_PROCESS_DISPLAY_NEED, "process_display_need"},
+ {MNG_FN_PROCESS_DISPLAY_PHYG, "process_display_phyg"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PROCESS_DISPLAY_JHDR, "process_display_jhdr"},
+ {MNG_FN_PROCESS_DISPLAY_JDAT, "process_display_jdat"},
+ {MNG_FN_PROCESS_DISPLAY_JSEP, "process_display_jsep"},
+#endif
+#ifndef MNG_NO_DELTA_PNG
+ {MNG_FN_PROCESS_DISPLAY_DHDR, "process_display_dhdr"},
+ {MNG_FN_PROCESS_DISPLAY_PROM, "process_display_prom"},
+#ifdef MNG_INCLUDE_JNG
+ {MNG_FN_PROCESS_DISPLAY_IPNG, "process_display_ipng"},
+#endif
+ {MNG_FN_PROCESS_DISPLAY_PPLT, "process_display_pplt"},
+ {MNG_FN_PROCESS_DISPLAY_IJNG, "process_display_ijng"},
+ {MNG_FN_PROCESS_DISPLAY_DROP, "process_display_drop"},
+ {MNG_FN_PROCESS_DISPLAY_DBYK, "process_display_dbyk"},
+ {MNG_FN_PROCESS_DISPLAY_ORDR, "process_display_ordr"},
+#endif
+ {MNG_FN_PROCESS_DISPLAY_MAGN, "process_display_magn"},
+ {MNG_FN_PROCESS_DISPLAY_JDAA, "process_display_jdaa"},
+
+ {MNG_FN_JPEG_INITIALIZE, "jpeg_initialize"},
+ {MNG_FN_JPEG_CLEANUP, "jpeg_cleanup"},
+ {MNG_FN_JPEG_DECOMPRESSINIT, "jpeg_decompressinit"},
+ {MNG_FN_JPEG_DECOMPRESSDATA, "jpeg_decompressdata"},
+ {MNG_FN_JPEG_DECOMPRESSFREE, "jpeg_decompressfree"},
+
+ {MNG_FN_STORE_JPEG_G8, "store_jpeg_g8"},
+ {MNG_FN_STORE_JPEG_RGB8, "store_jpeg_rgb8"},
+ {MNG_FN_STORE_JPEG_G12, "store_jpeg_g12"},
+ {MNG_FN_STORE_JPEG_RGB12, "store_jpeg_rgb12"},
+ {MNG_FN_STORE_JPEG_GA8, "store_jpeg_ga8"},
+ {MNG_FN_STORE_JPEG_RGBA8, "store_jpeg_rgba8"},
+ {MNG_FN_STORE_JPEG_GA12, "store_jpeg_ga12"},
+ {MNG_FN_STORE_JPEG_RGBA12, "store_jpeg_rgba12"},
+ {MNG_FN_STORE_JPEG_G8_ALPHA, "store_jpeg_g8_alpha"},
+ {MNG_FN_STORE_JPEG_RGB8_ALPHA, "store_jpeg_rgb8_alpha"},
+
+ {MNG_FN_INIT_JPEG_A1_NI, "init_jpeg_a1_ni"},
+ {MNG_FN_INIT_JPEG_A2_NI, "init_jpeg_a2_ni"},
+ {MNG_FN_INIT_JPEG_A4_NI, "init_jpeg_a4_ni"},
+ {MNG_FN_INIT_JPEG_A8_NI, "init_jpeg_a8_ni"},
+ {MNG_FN_INIT_JPEG_A16_NI, "init_jpeg_a16_ni"},
+
+ {MNG_FN_STORE_JPEG_G8_A1, "store_jpeg_g8_a1"},
+ {MNG_FN_STORE_JPEG_G8_A2, "store_jpeg_g8_a2"},
+ {MNG_FN_STORE_JPEG_G8_A4, "store_jpeg_g8_a4"},
+ {MNG_FN_STORE_JPEG_G8_A8, "store_jpeg_g8_a8"},
+ {MNG_FN_STORE_JPEG_G8_A16, "store_jpeg_g8_a16"},
+
+ {MNG_FN_STORE_JPEG_RGB8_A1, "store_jpeg_rgb8_a1"},
+ {MNG_FN_STORE_JPEG_RGB8_A2, "store_jpeg_rgb8_a2"},
+ {MNG_FN_STORE_JPEG_RGB8_A4, "store_jpeg_rgb8_a4"},
+ {MNG_FN_STORE_JPEG_RGB8_A8, "store_jpeg_rgb8_a8"},
+ {MNG_FN_STORE_JPEG_RGB8_A16, "store_jpeg_rgb8_a16"},
+
+ {MNG_FN_STORE_JPEG_G12_A1, "store_jpeg_g12_a1"},
+ {MNG_FN_STORE_JPEG_G12_A2, "store_jpeg_g12_a2"},
+ {MNG_FN_STORE_JPEG_G12_A4, "store_jpeg_g12_a4"},
+ {MNG_FN_STORE_JPEG_G12_A8, "store_jpeg_g12_a8"},
+ {MNG_FN_STORE_JPEG_G12_A16, "store_jpeg_g12_a16"},
+
+ {MNG_FN_STORE_JPEG_RGB12_A1, "store_jpeg_rgb12_a1"},
+ {MNG_FN_STORE_JPEG_RGB12_A2, "store_jpeg_rgb12_a2"},
+ {MNG_FN_STORE_JPEG_RGB12_A4, "store_jpeg_rgb12_a4"},
+ {MNG_FN_STORE_JPEG_RGB12_A8, "store_jpeg_rgb12_a8"},
+ {MNG_FN_STORE_JPEG_RGB12_A16, "store_jpeg_rgb12_a16"},
+
+ {MNG_FN_NEXT_JPEG_ALPHAROW, "next_jpeg_alpharow"},
+ {MNG_FN_NEXT_JPEG_ROW, "next_jpeg_row"},
+ {MNG_FN_DISPLAY_JPEG_ROWS, "display_jpeg_rows"},
+
+ {MNG_FN_MAGNIFY_G8_X1, "magnify_g8_x1"},
+ {MNG_FN_MAGNIFY_G8_X2, "magnify_g8_x2"},
+ {MNG_FN_MAGNIFY_RGB8_X1, "magnify_rgb8_x1"},
+ {MNG_FN_MAGNIFY_RGB8_X2, "magnify_rgb8_x2"},
+ {MNG_FN_MAGNIFY_GA8_X1, "magnify_ga8_x1"},
+ {MNG_FN_MAGNIFY_GA8_X2, "magnify_ga8_x2"},
+ {MNG_FN_MAGNIFY_GA8_X3, "magnify_ga8_x3"},
+ {MNG_FN_MAGNIFY_GA8_X4, "magnify_ga8_x4"},
+ {MNG_FN_MAGNIFY_RGBA8_X1, "magnify_rgba8_x1"},
+ {MNG_FN_MAGNIFY_RGBA8_X2, "magnify_rgba8_x2"},
+ {MNG_FN_MAGNIFY_RGBA8_X3, "magnify_rgba8_x3"},
+ {MNG_FN_MAGNIFY_RGBA8_X4, "magnify_rgba8_x4"},
+ {MNG_FN_MAGNIFY_G8_X3, "magnify_g8_x3"},
+ {MNG_FN_MAGNIFY_RGB8_X3, "magnify_rgb8_x3"},
+ {MNG_FN_MAGNIFY_GA8_X5, "magnify_ga8_x5"},
+ {MNG_FN_MAGNIFY_RGBA8_X5, "magnify_rgba8_x5"},
+
+ {MNG_FN_MAGNIFY_G8_Y1, "magnify_g8_y1"},
+ {MNG_FN_MAGNIFY_G8_Y2, "magnify_g8_y2"},
+ {MNG_FN_MAGNIFY_RGB8_Y1, "magnify_rgb8_y1"},
+ {MNG_FN_MAGNIFY_RGB8_Y2, "magnify_rgb8_y2"},
+ {MNG_FN_MAGNIFY_GA8_Y1, "magnify_ga8_y1"},
+ {MNG_FN_MAGNIFY_GA8_Y2, "magnify_ga8_y2"},
+ {MNG_FN_MAGNIFY_GA8_Y3, "magnify_ga8_y3"},
+ {MNG_FN_MAGNIFY_GA8_Y4, "magnify_ga8_y4"},
+ {MNG_FN_MAGNIFY_RGBA8_Y1, "magnify_rgba8_y1"},
+ {MNG_FN_MAGNIFY_RGBA8_Y2, "magnify_rgba8_y2"},
+ {MNG_FN_MAGNIFY_RGBA8_Y3, "magnify_rgba8_y3"},
+ {MNG_FN_MAGNIFY_RGBA8_Y4, "magnify_rgba8_y4"},
+ {MNG_FN_MAGNIFY_G8_Y3, "magnify_g8_y3"},
+ {MNG_FN_MAGNIFY_RGB8_Y3, "magnify_rgb8_y3"},
+ {MNG_FN_MAGNIFY_GA8_Y5, "magnify_ga8_y5"},
+ {MNG_FN_MAGNIFY_RGBA8_Y5, "magnify_rgba8_y5"},
+
+ {MNG_FN_MAGNIFY_G8_X1, "magnify_g8_x1"},
+ {MNG_FN_MAGNIFY_G8_X2, "magnify_g8_x2"},
+ {MNG_FN_MAGNIFY_RGB8_X1, "magnify_rgb8_x1"},
+ {MNG_FN_MAGNIFY_RGB8_X2, "magnify_rgb8_x2"},
+ {MNG_FN_MAGNIFY_GA8_X1, "magnify_ga8_x1"},
+ {MNG_FN_MAGNIFY_GA8_X2, "magnify_ga8_x2"},
+ {MNG_FN_MAGNIFY_GA8_X3, "magnify_ga8_x3"},
+ {MNG_FN_MAGNIFY_GA8_X4, "magnify_ga8_x4"},
+ {MNG_FN_MAGNIFY_RGBA8_X1, "magnify_rgba8_x1"},
+ {MNG_FN_MAGNIFY_RGBA8_X2, "magnify_rgba8_x2"},
+ {MNG_FN_MAGNIFY_RGBA8_X3, "magnify_rgba8_x3"},
+ {MNG_FN_MAGNIFY_RGBA8_X4, "magnify_rgba8_x4"},
+ {MNG_FN_MAGNIFY_G8_X3, "magnify_g8_x3"},
+ {MNG_FN_MAGNIFY_RGB8_X3, "magnify_rgb8_x3"},
+ {MNG_FN_MAGNIFY_GA8_X5, "magnify_ga8_x5"},
+ {MNG_FN_MAGNIFY_RGBA8_X5, "magnify_rgba8_x5"},
+
+ {MNG_FN_MAGNIFY_G8_Y1, "magnify_g8_y1"},
+ {MNG_FN_MAGNIFY_G8_Y2, "magnify_g8_y2"},
+ {MNG_FN_MAGNIFY_RGB8_Y1, "magnify_rgb8_y1"},
+ {MNG_FN_MAGNIFY_RGB8_Y2, "magnify_rgb8_y2"},
+ {MNG_FN_MAGNIFY_GA8_Y1, "magnify_ga8_y1"},
+ {MNG_FN_MAGNIFY_GA8_Y2, "magnify_ga8_y2"},
+ {MNG_FN_MAGNIFY_GA8_Y3, "magnify_ga8_y3"},
+ {MNG_FN_MAGNIFY_GA8_Y4, "magnify_ga8_y4"},
+ {MNG_FN_MAGNIFY_RGBA8_Y1, "magnify_rgba8_y1"},
+ {MNG_FN_MAGNIFY_RGBA8_Y2, "magnify_rgba8_y2"},
+ {MNG_FN_MAGNIFY_RGBA8_Y3, "magnify_rgba8_y3"},
+ {MNG_FN_MAGNIFY_RGBA8_Y4, "magnify_rgba8_y4"},
+ {MNG_FN_MAGNIFY_G8_Y3, "magnify_g8_y3"},
+ {MNG_FN_MAGNIFY_RGB8_Y3, "magnify_rgb8_y3"},
+ {MNG_FN_MAGNIFY_GA8_Y5, "magnify_ga8_y5"},
+ {MNG_FN_MAGNIFY_RGBA8_Y5, "magnify_rgba8_y5"},
+
+ {MNG_FN_DELTA_G1_G1, "delta_g1_g1"},
+ {MNG_FN_DELTA_G2_G2, "delta_g2_g2"},
+ {MNG_FN_DELTA_G4_G4, "delta_g4_g4"},
+ {MNG_FN_DELTA_G8_G8, "delta_g8_g8"},
+ {MNG_FN_DELTA_G16_G16, "delta_g16_g16"},
+ {MNG_FN_DELTA_RGB8_RGB8, "delta_rgb8_rgb8"},
+ {MNG_FN_DELTA_RGB16_RGB16, "delta_rgb16_rgb16"},
+ {MNG_FN_DELTA_GA8_GA8, "delta_ga8_ga8"},
+ {MNG_FN_DELTA_GA8_G8, "delta_ga8_g8"},
+ {MNG_FN_DELTA_GA8_A8, "delta_ga8_a8"},
+ {MNG_FN_DELTA_GA16_GA16, "delta_ga16_ga16"},
+ {MNG_FN_DELTA_GA16_G16, "delta_ga16_g16"},
+ {MNG_FN_DELTA_GA16_A16, "delta_ga16_a16"},
+ {MNG_FN_DELTA_RGBA8_RGBA8, "delta_rgba8_rgba8"},
+ {MNG_FN_DELTA_RGBA8_RGB8, "delta_rgba8_rgb8"},
+ {MNG_FN_DELTA_RGBA8_A8, "delta_rgba8_a8"},
+ {MNG_FN_DELTA_RGBA16_RGBA16, "delta_rgba16_rgba16"},
+ {MNG_FN_DELTA_RGBA16_RGB16, "delta_rgba16_rgb16"},
+ {MNG_FN_DELTA_RGBA16_A16, "delta_rgba16_a16"},
+
+ {MNG_FN_PROMOTE_G8_G8, "promote_g8_g8"},
+ {MNG_FN_PROMOTE_G8_G16, "promote_g8_g16"},
+ {MNG_FN_PROMOTE_G16_G16, "promote_g8_g16"},
+ {MNG_FN_PROMOTE_G8_GA8, "promote_g8_ga8"},
+ {MNG_FN_PROMOTE_G8_GA16, "promote_g8_ga16"},
+ {MNG_FN_PROMOTE_G16_GA16, "promote_g16_ga16"},
+ {MNG_FN_PROMOTE_G8_RGB8, "promote_g8_rgb8"},
+ {MNG_FN_PROMOTE_G8_RGB16, "promote_g8_rgb16"},
+ {MNG_FN_PROMOTE_G16_RGB16, "promote_g16_rgb16"},
+ {MNG_FN_PROMOTE_G8_RGBA8, "promote_g8_rgba8"},
+ {MNG_FN_PROMOTE_G8_RGBA16, "promote_g8_rgba16"},
+ {MNG_FN_PROMOTE_G16_RGBA16, "promote_g16_rgba16"},
+ {MNG_FN_PROMOTE_GA8_GA16, "promote_ga8_ga16"},
+ {MNG_FN_PROMOTE_GA8_RGBA8, "promote_ga8_rgba8"},
+ {MNG_FN_PROMOTE_GA8_RGBA16, "promote_ga8_rgba16"},
+ {MNG_FN_PROMOTE_GA16_RGBA16, "promote_ga16_rgba16"},
+ {MNG_FN_PROMOTE_RGB8_RGB16, "promote_rgb8_rgb16"},
+ {MNG_FN_PROMOTE_RGB8_RGBA8, "promote_rgb8_rgba8"},
+ {MNG_FN_PROMOTE_RGB8_RGBA16, "promote_rgb8_rgba16"},
+ {MNG_FN_PROMOTE_RGB16_RGBA16, "promote_rgb16_rgba16"},
+ {MNG_FN_PROMOTE_RGBA8_RGBA16, "promote_rgba8_rgba16"},
+ {MNG_FN_PROMOTE_IDX8_RGB8, "promote_idx8_rgb8"},
+ {MNG_FN_PROMOTE_IDX8_RGB16, "promote_idx8_rgb16"},
+ {MNG_FN_PROMOTE_IDX8_RGBA8, "promote_idx8_rgba8"},
+ {MNG_FN_PROMOTE_IDX8_RGBA16, "promote_idx8_rgba16"},
+
+ {MNG_FN_SCALE_G1_G2, "scale_g1_g2"},
+ {MNG_FN_SCALE_G1_G4, "scale_g1_g4"},
+ {MNG_FN_SCALE_G1_G8, "scale_g1_g8"},
+ {MNG_FN_SCALE_G1_G16, "scale_g1_g16"},
+ {MNG_FN_SCALE_G2_G4, "scale_g2_g4"},
+ {MNG_FN_SCALE_G2_G8, "scale_g2_g8"},
+ {MNG_FN_SCALE_G2_G16, "scale_g2_g16"},
+ {MNG_FN_SCALE_G4_G8, "scale_g4_g8"},
+ {MNG_FN_SCALE_G4_G16, "scale_g4_g16"},
+ {MNG_FN_SCALE_G8_G16, "scale_g8_g16"},
+ {MNG_FN_SCALE_GA8_GA16, "scale_ga8_ga16"},
+ {MNG_FN_SCALE_RGB8_RGB16, "scale_rgb8_rgb16"},
+ {MNG_FN_SCALE_RGBA8_RGBA16, "scale_rgba8_rgba16"},
+
+ {MNG_FN_SCALE_G2_G1, "scale_g2_g1"},
+ {MNG_FN_SCALE_G4_G1, "scale_g4_g1"},
+ {MNG_FN_SCALE_G8_G1, "scale_g8_g1"},
+ {MNG_FN_SCALE_G16_G1, "scale_g16_g1"},
+ {MNG_FN_SCALE_G4_G2, "scale_g4_g2"},
+ {MNG_FN_SCALE_G8_G2, "scale_g8_g2"},
+ {MNG_FN_SCALE_G16_G2, "scale_g16_g2"},
+ {MNG_FN_SCALE_G8_G4, "scale_g8_g4"},
+ {MNG_FN_SCALE_G16_G4, "scale_g16_g4"},
+ {MNG_FN_SCALE_G16_G8, "scale_g16_g8"},
+ {MNG_FN_SCALE_GA16_GA8, "scale_ga16_ga8"},
+ {MNG_FN_SCALE_RGB16_RGB8, "scale_rgb16_rgb8"},
+ {MNG_FN_SCALE_RGBA16_RGBA8, "scale_rgba16_rgba8"},
+
+ {MNG_FN_COMPOSEOVER_RGBA8, "composeover_rgba8"},
+ {MNG_FN_COMPOSEOVER_RGBA16, "composeover_rgba16"},
+ {MNG_FN_COMPOSEUNDER_RGBA8, "composeunder_rgba8"},
+ {MNG_FN_COMPOSEUNDER_RGBA16, "composeunder_rgba16"},
+
+ {MNG_FN_FLIP_RGBA8, "flip_rgba8"},
+ {MNG_FN_FLIP_RGBA16, "flip_rgba16"},
+ {MNG_FN_TILE_RGBA8, "tile_rgba8"},
+ {MNG_FN_TILE_RGBA16, "tile_rgba16"}
+
+ };
+#endif /* MNG_INCLUDE_TRACE_STINGS */
+
+/* ************************************************************************** */
+
+mng_retcode mng_trace (mng_datap pData,
+ mng_uint32 iFunction,
+ mng_uint32 iLocation)
+{
+ mng_pchar zName = 0; /* bufferptr for tracestring */
+
+ if ((pData == 0) || (pData->iMagic != MNG_MAGIC))
+ return MNG_INVALIDHANDLE; /* no good if the handle is corrupt */
+
+ if (pData->fTraceproc) /* report back to user ? */
+ {
+#ifdef MNG_INCLUDE_TRACE_STRINGS
+ { /* binary search variables */
+ mng_int32 iTop, iLower, iUpper, iMiddle;
+ mng_trace_entryp pEntry; /* pointer to found entry */
+ /* determine max index of table */
+ iTop = (sizeof (trace_table) / sizeof (trace_table [0])) - 1;
+
+ iLower = 0; /* initialize binary search */
+ iMiddle = iTop >> 1; /* start in the middle */
+ iUpper = iTop;
+ pEntry = 0; /* no goods yet! */
+
+ do /* the binary search itself */
+ {
+ if (trace_table [iMiddle].iFunction < iFunction)
+ iLower = iMiddle + 1;
+ else if (trace_table [iMiddle].iFunction > iFunction)
+ iUpper = iMiddle - 1;
+ else
+ {
+ pEntry = &trace_table [iMiddle];
+ break;
+ };
+
+ iMiddle = (iLower + iUpper) >> 1;
+ }
+ while (iLower <= iUpper);
+
+ if (pEntry) /* found it ? */
+ zName = pEntry->zTracetext;
+
+ }
+#endif
+ /* oke, now tell */
+ if (!pData->fTraceproc (((mng_handle)pData), iFunction, iLocation, zName))
+ return MNG_APPTRACEABORT;
+
+ }
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_TRACE_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_trace.h b/Source/LibMNG/libmng_trace.h
new file mode 100644
index 0000000..0c749d9
--- /dev/null
+++ b/Source/LibMNG/libmng_trace.h
@@ -0,0 +1,1474 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_trace.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : Trace functions (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the trace functions * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - added chunk-access function trace-codes * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * 0.5.1 - 05/13/2000 - G.Juyn * */
+/* * - added save_state & restore_state trace-codes * */
+/* * 0.5.1 - 05/15/2000 - G.Juyn * */
+/* * - added getimgdata & putimgdata trace-codes * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - added JNG tracecodes * */
+/* * 0.5.2 - 05/23/2000 - G.Juyn * */
+/* * - added trace-table entry definition * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added tracecodes for global animation color-chunks * */
+/* * - added tracecodes for get/set of default ZLIB/IJG parms * */
+/* * - added tracecodes for global PLTE,tRNS,bKGD * */
+/* * 0.5.2 - 05/30/2000 - G.Juyn * */
+/* * - added tracecodes for image-object promotion * */
+/* * - added tracecodes for delta-image processing * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - added tracecodes for getalphaline callback * */
+/* * 0.5.2 - 06/05/2000 - G.Juyn * */
+/* * - added tracecode for RGB8_A8 canvasstyle * */
+/* * 0.5.2 - 06/06/2000 - G.Juyn * */
+/* * - added tracecode for mng_read_resume HLAPI function * */
+/* * * */
+/* * 0.5.3 - 06/06/2000 - G.Juyn * */
+/* * - added tracecodes for tracing JPEG progression * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added tracecodes for get/set speedtype * */
+/* * - added tracecodes for get imagelevel * */
+/* * 0.5.3 - 06/22/2000 - G.Juyn * */
+/* * - added tracecode for delta-image processing * */
+/* * - added tracecodes for PPLT chunk processing * */
+/* * * */
+/* * 0.9.1 - 07/07/2000 - G.Juyn * */
+/* * - added tracecodes for special display processing * */
+/* * 0.9.1 - 07/08/2000 - G.Juyn * */
+/* * - added tracecode for get/set suspensionmode * */
+/* * - added tracecodes for get/set display variables * */
+/* * - added tracecode for read_databuffer (I/O-suspension) * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added tracecodes for SAVE/SEEK callbacks * */
+/* * - added tracecodes for get/set sectionbreaks * */
+/* * - added tracecode for special error routine * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - added tracecode for updatemngheader * */
+/* * * */
+/* * 0.9.2 - 07/31/2000 - G.Juyn * */
+/* * - added tracecodes for status_xxxxx functions * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * - added tracecode for updatemngsimplicity * */
+/* * * */
+/* * 0.9.3 - 08/26/2000 - G.Juyn * */
+/* * - added MAGN chunk * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * 0.9.3 - 10/10/2000 - G.Juyn * */
+/* * - added support for alpha-depth prediction * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added JDAA chunk * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/16/2000 - G.Juyn * */
+/* * - added functions to retrieve PNG/JNG specific header-info * */
+/* * - added optional support for bKGD for PNG images * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * - added routine to discard "invalid" objects * */
+/* * 0.9.3 - 10/19/2000 - G.Juyn * */
+/* * - implemented delayed delta-processing * */
+/* * 0.9.3 - 10/20/2000 - G.Juyn * */
+/* * - added get/set for bKGD preference setting * */
+/* * 0.9.3 - 10/21/2000 - G.Juyn * */
+/* * - added get function for interlace/progressive display * */
+/* * * */
+/* * 0.9.4 - 1/18/2001 - G.Juyn * */
+/* * - added "new" MAGN methods 3, 4 & 5 * */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * 1.0.1 - 04/21/2001 - G.Juyn (code by G.Kelly) * */
+/* * - added BGRA8 canvas with premultiplied alpha * */
+/* * 1.0.1 - 05/02/2001 - G.Juyn * */
+/* * - added "default" sRGB generation (Thanks Marti!) * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added optimization option for MNG-video playback * */
+/* * - added processterm callback * */
+/* * 1.0.2 - 06/25/2001 - G.Juyn * */
+/* * - added option to turn off progressive refresh * */
+/* * * */
+/* * 1.0.3 - 08/06/2001 - G.Juyn * */
+/* * - added get function for last processed BACK chunk * */
+/* * * */
+/* * 1.0.5 - 08/15/2002 - G.Juyn * */
+/* * - completed PROM support * */
+/* * - completed delta-image support * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * - added HLAPI function to copy chunks * */
+/* * 1.0.5 - 09/14/2002 - G.Juyn * */
+/* * - added event handling for dynamic MNG * */
+/* * 1.0.5 - 09/20/2002 - G.Juyn * */
+/* * - added support for PAST * */
+/* * 1.0.5 - 09/22/2002 - G.Juyn * */
+/* * - added bgrx8 canvas (filler byte) * */
+/* * 1.0.5 - 09/23/2002 - G.Juyn * */
+/* * - added in-memory color-correction of abstract images * */
+/* * - added compose over/under routines for PAST processing * */
+/* * - added flip & tile routines for PAST processing * */
+/* * 1.0.5 - 10/09/2002 - G.Juyn * */
+/* * - fixed trace-constants for PAST chunk * */
+/* * 1.0.5 - 11/07/2002 - G.Juyn * */
+/* * - added support to get totals after mng_read() * */
+/* * * */
+/* * 1.0.6 - 07/14/2003 - G.Randers-Pehrson * */
+/* * - added conditionals around rarely used features * */
+/* * * */
+/* * 1.0.7 - 11/27/2003 - R.A * */
+/* * - added CANVAS_RGB565 and CANVAS_BGR565 * */
+/* * 1.0.7 - 01/25/2004 - J.S * */
+/* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * * */
+/* * 1.0.8 - 04/02/2004 - G.Juyn * */
+/* * - added CRC existence & checking flags * */
+/* * 1.0.8 - 04/11/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * * */
+/* * 1.0.9 - 10/03/2004 - G.Juyn * */
+/* * - added function to retrieve current FRAM delay * */
+/* * 1.0.9 - 10/14/2004 - G.Juyn * */
+/* * - added bgr565_a8 canvas-style (thanks to J. Elvander) * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 07/06/2007 - G.R-P bugfix by Lucas Quintana * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_trace_h_
+#define _libmng_trace_h_
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_TRACE_PROCS
+
+/* ************************************************************************** */
+
+/* TODO: add a trace-mask so certain functions can be excluded */
+
+mng_retcode mng_trace (mng_datap pData,
+ mng_uint32 iFunction,
+ mng_uint32 iLocation);
+
+/* ************************************************************************** */
+
+#define MNG_TRACE(D,F,L) { mng_retcode iR = mng_trace (D,F,L); \
+ if (iR) return iR; }
+
+#define MNG_TRACEB(D,F,L) { if (mng_trace (D,F,L)) return MNG_FALSE; }
+
+#define MNG_TRACEX(D,F,L) { if (mng_trace (D,F,L)) return 0; }
+
+/* ************************************************************************** */
+
+#define MNG_LC_START 1
+#define MNG_LC_END 2
+#define MNG_LC_INITIALIZE 3
+#define MNG_LC_CLEANUP 4
+
+/* ************************************************************************** */
+
+#define MNG_LC_JPEG_CREATE_DECOMPRESS 101
+#define MNG_LC_JPEG_READ_HEADER 102
+#define MNG_LC_JPEG_START_DECOMPRESS 103
+#define MNG_LC_JPEG_START_OUTPUT 104
+#define MNG_LC_JPEG_READ_SCANLINES 105
+#define MNG_LC_JPEG_FINISH_OUTPUT 106
+#define MNG_LC_JPEG_FINISH_DECOMPRESS 107
+#define MNG_LC_JPEG_DESTROY_DECOMPRESS 108
+
+/* ************************************************************************** */
+
+#define MNG_FN_INITIALIZE 1
+#define MNG_FN_RESET 2
+#define MNG_FN_CLEANUP 3
+#define MNG_FN_READ 4
+#define MNG_FN_WRITE 5
+#define MNG_FN_CREATE 6
+#define MNG_FN_READDISPLAY 7
+#define MNG_FN_DISPLAY 8
+#define MNG_FN_DISPLAY_RESUME 9
+#define MNG_FN_DISPLAY_FREEZE 10
+#define MNG_FN_DISPLAY_RESET 11
+#ifndef MNG_NO_DISPLAY_GO_SUPPORTED
+#define MNG_FN_DISPLAY_GOFRAME 12
+#define MNG_FN_DISPLAY_GOLAYER 13
+#define MNG_FN_DISPLAY_GOTIME 14
+#endif
+#define MNG_FN_GETLASTERROR 15
+#define MNG_FN_READ_RESUME 16
+#define MNG_FN_TRAPEVENT 17
+#define MNG_FN_READ_PUSHDATA 18
+#define MNG_FN_READ_PUSHSIG 19
+#define MNG_FN_READ_PUSHCHUNK 20
+
+#define MNG_FN_SETCB_MEMALLOC 101
+#define MNG_FN_SETCB_MEMFREE 102
+#define MNG_FN_SETCB_READDATA 103
+#define MNG_FN_SETCB_WRITEDATA 104
+#define MNG_FN_SETCB_ERRORPROC 105
+#define MNG_FN_SETCB_TRACEPROC 106
+#define MNG_FN_SETCB_PROCESSHEADER 107
+#define MNG_FN_SETCB_PROCESSTEXT 108
+#define MNG_FN_SETCB_GETCANVASLINE 109
+#define MNG_FN_SETCB_GETBKGDLINE 110
+#define MNG_FN_SETCB_REFRESH 111
+#define MNG_FN_SETCB_GETTICKCOUNT 112
+#define MNG_FN_SETCB_SETTIMER 113
+#define MNG_FN_SETCB_PROCESSGAMMA 114
+#define MNG_FN_SETCB_PROCESSCHROMA 115
+#define MNG_FN_SETCB_PROCESSSRGB 116
+#define MNG_FN_SETCB_PROCESSICCP 117
+#define MNG_FN_SETCB_PROCESSAROW 118
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+#define MNG_FN_SETCB_OPENSTREAM 119
+#define MNG_FN_SETCB_CLOSESTREAM 120
+#endif
+#define MNG_FN_SETCB_GETALPHALINE 121
+#define MNG_FN_SETCB_PROCESSSAVE 122
+#define MNG_FN_SETCB_PROCESSSEEK 123
+#define MNG_FN_SETCB_PROCESSNEED 124
+#define MNG_FN_SETCB_PROCESSUNKNOWN 125
+#define MNG_FN_SETCB_PROCESSMEND 126
+#define MNG_FN_SETCB_PROCESSTERM 127
+#define MNG_FN_SETCB_RELEASEDATA 128
+
+#define MNG_FN_GETCB_MEMALLOC 201
+#define MNG_FN_GETCB_MEMFREE 202
+#define MNG_FN_GETCB_READDATA 203
+#define MNG_FN_GETCB_WRITEDATA 204
+#define MNG_FN_GETCB_ERRORPROC 205
+#define MNG_FN_GETCB_TRACEPROC 206
+#define MNG_FN_GETCB_PROCESSHEADER 207
+#define MNG_FN_GETCB_PROCESSTEXT 208
+#define MNG_FN_GETCB_GETCANVASLINE 209
+#define MNG_FN_GETCB_GETBKGDLINE 210
+#define MNG_FN_GETCB_REFRESH 211
+#define MNG_FN_GETCB_GETTICKCOUNT 212
+#define MNG_FN_GETCB_SETTIMER 213
+#define MNG_FN_GETCB_PROCESSGAMMA 214
+#define MNG_FN_GETCB_PROCESSCHROMA 215
+#define MNG_FN_GETCB_PROCESSSRGB 216
+#define MNG_FN_GETCB_PROCESSICCP 217
+#define MNG_FN_GETCB_PROCESSAROW 218
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+#define MNG_FN_GETCB_OPENSTREAM 219
+#define MNG_FN_GETCB_CLOSESTREAM 220
+#endif
+#define MNG_FN_GETCB_GETALPHALINE 221
+#define MNG_FN_GETCB_PROCESSSAVE 222
+#define MNG_FN_GETCB_PROCESSSEEK 223
+#define MNG_FN_GETCB_PROCESSNEED 224
+#define MNG_FN_GETCB_PROCESSUNKNOWN 225
+#define MNG_FN_GETCB_PROCESSMEND 226
+#define MNG_FN_GETCB_PROCESSTERM 227
+#define MNG_FN_GETCB_RELEASEDATA 228
+
+#define MNG_FN_SET_USERDATA 301
+#define MNG_FN_SET_CANVASSTYLE 302
+#define MNG_FN_SET_BKGDSTYLE 303
+#define MNG_FN_SET_BGCOLOR 304
+#define MNG_FN_SET_STORECHUNKS 305
+#define MNG_FN_SET_VIEWGAMMA 306
+#define MNG_FN_SET_DISPLAYGAMMA 307
+#define MNG_FN_SET_DFLTIMGGAMMA 308
+#define MNG_FN_SET_SRGB 309
+#define MNG_FN_SET_OUTPUTPROFILE 310
+#define MNG_FN_SET_SRGBPROFILE 311
+#define MNG_FN_SET_MAXCANVASWIDTH 312
+#define MNG_FN_SET_MAXCANVASHEIGHT 313
+#define MNG_FN_SET_MAXCANVASSIZE 314
+#define MNG_FN_SET_ZLIB_LEVEL 315
+#define MNG_FN_SET_ZLIB_METHOD 316
+#define MNG_FN_SET_ZLIB_WINDOWBITS 317
+#define MNG_FN_SET_ZLIB_MEMLEVEL 318
+#define MNG_FN_SET_ZLIB_STRATEGY 319
+#define MNG_FN_SET_ZLIB_MAXIDAT 320
+#define MNG_FN_SET_JPEG_DCTMETHOD 321
+#define MNG_FN_SET_JPEG_QUALITY 322
+#define MNG_FN_SET_JPEG_SMOOTHING 323
+#define MNG_FN_SET_JPEG_PROGRESSIVE 324
+#define MNG_FN_SET_JPEG_OPTIMIZED 325
+#define MNG_FN_SET_JPEG_MAXJDAT 326
+#define MNG_FN_SET_SPEED 327
+#define MNG_FN_SET_SUSPENSIONMODE 328
+#define MNG_FN_SET_SECTIONBREAKS 329
+#define MNG_FN_SET_USEBKGD 330
+#define MNG_FN_SET_OUTPUTPROFILE2 331
+#define MNG_FN_SET_SRGBPROFILE2 332
+#define MNG_FN_SET_OUTPUTSRGB 333
+#define MNG_FN_SET_SRGBIMPLICIT 334
+#define MNG_FN_SET_CACHEPLAYBACK 335
+#define MNG_FN_SET_DOPROGRESSIVE 336
+#define MNG_FN_SET_CRCMODE 337
+
+#define MNG_FN_GET_USERDATA 401
+#define MNG_FN_GET_SIGTYPE 402
+#define MNG_FN_GET_IMAGETYPE 403
+#define MNG_FN_GET_IMAGEWIDTH 404
+#define MNG_FN_GET_IMAGEHEIGHT 405
+#define MNG_FN_GET_TICKS 406
+#define MNG_FN_GET_FRAMECOUNT 407
+#define MNG_FN_GET_LAYERCOUNT 408
+#define MNG_FN_GET_PLAYTIME 409
+#define MNG_FN_GET_SIMPLICITY 410
+#define MNG_FN_GET_CANVASSTYLE 411
+#define MNG_FN_GET_BKGDSTYLE 412
+#define MNG_FN_GET_BGCOLOR 413
+#define MNG_FN_GET_STORECHUNKS 414
+#define MNG_FN_GET_VIEWGAMMA 415
+#define MNG_FN_GET_DISPLAYGAMMA 416
+#define MNG_FN_GET_DFLTIMGGAMMA 417
+#define MNG_FN_GET_SRGB 418
+#define MNG_FN_GET_MAXCANVASWIDTH 419
+#define MNG_FN_GET_MAXCANVASHEIGHT 420
+#define MNG_FN_GET_ZLIB_LEVEL 421
+#define MNG_FN_GET_ZLIB_METHOD 422
+#define MNG_FN_GET_ZLIB_WINDOWBITS 423
+#define MNG_FN_GET_ZLIB_MEMLEVEL 424
+#define MNG_FN_GET_ZLIB_STRATEGY 425
+#define MNG_FN_GET_ZLIB_MAXIDAT 426
+#define MNG_FN_GET_JPEG_DCTMETHOD 427
+#define MNG_FN_GET_JPEG_QUALITY 428
+#define MNG_FN_GET_JPEG_SMOOTHING 429
+#define MNG_FN_GET_JPEG_PROGRESSIVE 430
+#define MNG_FN_GET_JPEG_OPTIMIZED 431
+#define MNG_FN_GET_JPEG_MAXJDAT 432
+#define MNG_FN_GET_SPEED 433
+#define MNG_FN_GET_IMAGELEVEL 434
+#define MNG_FN_GET_SUSPENSIONMODE 435
+#define MNG_FN_GET_STARTTIME 436
+#define MNG_FN_GET_RUNTIME 437
+#define MNG_FN_GET_CURRENTFRAME 438
+#define MNG_FN_GET_CURRENTLAYER 439
+#define MNG_FN_GET_CURRENTPLAYTIME 440
+#define MNG_FN_GET_SECTIONBREAKS 441
+#define MNG_FN_GET_ALPHADEPTH 442
+#define MNG_FN_GET_BITDEPTH 443
+#define MNG_FN_GET_COLORTYPE 444
+#define MNG_FN_GET_COMPRESSION 445
+#define MNG_FN_GET_FILTER 446
+#define MNG_FN_GET_INTERLACE 447
+#define MNG_FN_GET_ALPHABITDEPTH 448
+#define MNG_FN_GET_ALPHACOMPRESSION 449
+#define MNG_FN_GET_ALPHAFILTER 450
+#define MNG_FN_GET_ALPHAINTERLACE 451
+#define MNG_FN_GET_USEBKGD 452
+#define MNG_FN_GET_REFRESHPASS 453
+#define MNG_FN_GET_CACHEPLAYBACK 454
+#define MNG_FN_GET_DOPROGRESSIVE 455
+#define MNG_FN_GET_LASTBACKCHUNK 456
+#define MNG_FN_GET_LASTSEEKNAME 457
+#define MNG_FN_GET_TOTALFRAMES 458
+#define MNG_FN_GET_TOTALLAYERS 459
+#define MNG_FN_GET_TOTALPLAYTIME 460
+#define MNG_FN_GET_CRCMODE 461
+#define MNG_FN_GET_CURRFRAMDELAY 462
+
+#define MNG_FN_STATUS_ERROR 481
+#define MNG_FN_STATUS_READING 482
+#define MNG_FN_STATUS_SUSPENDBREAK 483
+#define MNG_FN_STATUS_CREATING 484
+#define MNG_FN_STATUS_WRITING 485
+#define MNG_FN_STATUS_DISPLAYING 486
+#define MNG_FN_STATUS_RUNNING 487
+#define MNG_FN_STATUS_TIMERBREAK 488
+#define MNG_FN_STATUS_DYNAMIC 489
+#define MNG_FN_STATUS_RUNNINGEVENT 490
+
+/* ************************************************************************** */
+
+#define MNG_FN_ITERATE_CHUNKS 601
+#define MNG_FN_COPY_CHUNK 602
+
+#define MNG_FN_GETCHUNK_IHDR 701
+#define MNG_FN_GETCHUNK_PLTE 702
+#define MNG_FN_GETCHUNK_IDAT 703
+#define MNG_FN_GETCHUNK_IEND 704
+#define MNG_FN_GETCHUNK_TRNS 705
+#define MNG_FN_GETCHUNK_GAMA 706
+#define MNG_FN_GETCHUNK_CHRM 707
+#define MNG_FN_GETCHUNK_SRGB 708
+#define MNG_FN_GETCHUNK_ICCP 709
+#define MNG_FN_GETCHUNK_TEXT 710
+#define MNG_FN_GETCHUNK_ZTXT 711
+#define MNG_FN_GETCHUNK_ITXT 712
+#define MNG_FN_GETCHUNK_BKGD 713
+#define MNG_FN_GETCHUNK_PHYS 714
+#define MNG_FN_GETCHUNK_SBIT 715
+#define MNG_FN_GETCHUNK_SPLT 716
+#define MNG_FN_GETCHUNK_HIST 717
+#define MNG_FN_GETCHUNK_TIME 718
+#define MNG_FN_GETCHUNK_MHDR 719
+#define MNG_FN_GETCHUNK_MEND 720
+#define MNG_FN_GETCHUNK_LOOP 721
+#define MNG_FN_GETCHUNK_ENDL 722
+#define MNG_FN_GETCHUNK_DEFI 723
+#define MNG_FN_GETCHUNK_BASI 724
+#define MNG_FN_GETCHUNK_CLON 725
+#define MNG_FN_GETCHUNK_PAST 726
+#define MNG_FN_GETCHUNK_DISC 727
+#define MNG_FN_GETCHUNK_BACK 728
+#define MNG_FN_GETCHUNK_FRAM 729
+#define MNG_FN_GETCHUNK_MOVE 730
+#define MNG_FN_GETCHUNK_CLIP 731
+#define MNG_FN_GETCHUNK_SHOW 732
+#define MNG_FN_GETCHUNK_TERM 733
+#define MNG_FN_GETCHUNK_SAVE 734
+#define MNG_FN_GETCHUNK_SEEK 735
+#define MNG_FN_GETCHUNK_EXPI 736
+#define MNG_FN_GETCHUNK_FPRI 737
+#define MNG_FN_GETCHUNK_NEED 738
+#define MNG_FN_GETCHUNK_PHYG 739
+#define MNG_FN_GETCHUNK_JHDR 740
+#define MNG_FN_GETCHUNK_JDAT 741
+#define MNG_FN_GETCHUNK_JSEP 742
+#define MNG_FN_GETCHUNK_DHDR 743
+#define MNG_FN_GETCHUNK_PROM 744
+#define MNG_FN_GETCHUNK_IPNG 745
+#define MNG_FN_GETCHUNK_PPLT 746
+#define MNG_FN_GETCHUNK_IJNG 747
+#define MNG_FN_GETCHUNK_DROP 748
+#define MNG_FN_GETCHUNK_DBYK 749
+#define MNG_FN_GETCHUNK_ORDR 750
+#define MNG_FN_GETCHUNK_UNKNOWN 751
+#define MNG_FN_GETCHUNK_MAGN 752
+#define MNG_FN_GETCHUNK_JDAA 753
+#define MNG_FN_GETCHUNK_EVNT 754
+#define MNG_FN_GETCHUNK_MPNG 755
+
+#define MNG_FN_GETCHUNK_PAST_SRC 781
+#define MNG_FN_GETCHUNK_SAVE_ENTRY 782
+#define MNG_FN_GETCHUNK_PPLT_ENTRY 783
+#define MNG_FN_GETCHUNK_ORDR_ENTRY 784
+#define MNG_FN_GETCHUNK_EVNT_ENTRY 785
+#define MNG_FN_GETCHUNK_MPNG_FRAME 786
+
+#define MNG_FN_PUTCHUNK_IHDR 801
+#define MNG_FN_PUTCHUNK_PLTE 802
+#define MNG_FN_PUTCHUNK_IDAT 803
+#define MNG_FN_PUTCHUNK_IEND 804
+#define MNG_FN_PUTCHUNK_TRNS 805
+#define MNG_FN_PUTCHUNK_GAMA 806
+#define MNG_FN_PUTCHUNK_CHRM 807
+#define MNG_FN_PUTCHUNK_SRGB 808
+#define MNG_FN_PUTCHUNK_ICCP 809
+#define MNG_FN_PUTCHUNK_TEXT 810
+#define MNG_FN_PUTCHUNK_ZTXT 811
+#define MNG_FN_PUTCHUNK_ITXT 812
+#define MNG_FN_PUTCHUNK_BKGD 813
+#define MNG_FN_PUTCHUNK_PHYS 814
+#define MNG_FN_PUTCHUNK_SBIT 815
+#define MNG_FN_PUTCHUNK_SPLT 816
+#define MNG_FN_PUTCHUNK_HIST 817
+#define MNG_FN_PUTCHUNK_TIME 818
+#define MNG_FN_PUTCHUNK_MHDR 819
+#define MNG_FN_PUTCHUNK_MEND 820
+#define MNG_FN_PUTCHUNK_LOOP 821
+#define MNG_FN_PUTCHUNK_ENDL 822
+#define MNG_FN_PUTCHUNK_DEFI 823
+#define MNG_FN_PUTCHUNK_BASI 824
+#define MNG_FN_PUTCHUNK_CLON 825
+#define MNG_FN_PUTCHUNK_PAST 826
+#define MNG_FN_PUTCHUNK_DISC 827
+#define MNG_FN_PUTCHUNK_BACK 828
+#define MNG_FN_PUTCHUNK_FRAM 829
+#define MNG_FN_PUTCHUNK_MOVE 830
+#define MNG_FN_PUTCHUNK_CLIP 831
+#define MNG_FN_PUTCHUNK_SHOW 832
+#define MNG_FN_PUTCHUNK_TERM 833
+#define MNG_FN_PUTCHUNK_SAVE 834
+#define MNG_FN_PUTCHUNK_SEEK 835
+#define MNG_FN_PUTCHUNK_EXPI 836
+#define MNG_FN_PUTCHUNK_FPRI 837
+#define MNG_FN_PUTCHUNK_NEED 838
+#define MNG_FN_PUTCHUNK_PHYG 839
+#define MNG_FN_PUTCHUNK_JHDR 840
+#define MNG_FN_PUTCHUNK_JDAT 841
+#define MNG_FN_PUTCHUNK_JSEP 842
+#define MNG_FN_PUTCHUNK_DHDR 843
+#define MNG_FN_PUTCHUNK_PROM 844
+#define MNG_FN_PUTCHUNK_IPNG 845
+#define MNG_FN_PUTCHUNK_PPLT 846
+#define MNG_FN_PUTCHUNK_IJNG 847
+#define MNG_FN_PUTCHUNK_DROP 848
+#define MNG_FN_PUTCHUNK_DBYK 849
+#define MNG_FN_PUTCHUNK_ORDR 850
+#define MNG_FN_PUTCHUNK_UNKNOWN 851
+#define MNG_FN_PUTCHUNK_MAGN 852
+#define MNG_FN_PUTCHUNK_JDAA 853
+#define MNG_FN_PUTCHUNK_EVNT 854
+#define MNG_FN_PUTCHUNK_MPNG 855
+
+#define MNG_FN_PUTCHUNK_PAST_SRC 881
+#define MNG_FN_PUTCHUNK_SAVE_ENTRY 882
+#define MNG_FN_PUTCHUNK_PPLT_ENTRY 883
+#define MNG_FN_PUTCHUNK_ORDR_ENTRY 884
+#define MNG_FN_PUTCHUNK_EVNT_ENTRY 885
+#define MNG_FN_PUTCHUNK_MPNG_FRAME 886
+
+/* ************************************************************************** */
+
+#define MNG_FN_GETIMGDATA_SEQ 901
+#define MNG_FN_GETIMGDATA_CHUNKSEQ 902
+#define MNG_FN_GETIMGDATA_CHUNK 903
+
+#define MNG_FN_PUTIMGDATA_IHDR 951
+#define MNG_FN_PUTIMGDATA_JHDR 952
+#define MNG_FN_PUTIMGDATA_BASI 953
+#define MNG_FN_PUTIMGDATA_DHDR 954
+
+#define MNG_FN_UPDATEMNGHEADER 981
+#define MNG_FN_UPDATEMNGSIMPLICITY 982
+
+/* ************************************************************************** */
+
+#define MNG_FN_PROCESS_RAW_CHUNK 1001
+#define MNG_FN_READ_GRAPHIC 1002
+#define MNG_FN_DROP_CHUNKS 1003
+#define MNG_FN_PROCESS_ERROR 1004
+#define MNG_FN_CLEAR_CMS 1005
+#define MNG_FN_DROP_OBJECTS 1006
+#define MNG_FN_READ_CHUNK 1007
+#define MNG_FN_LOAD_BKGDLAYER 1008
+#define MNG_FN_NEXT_FRAME 1009
+#define MNG_FN_NEXT_LAYER 1010
+#define MNG_FN_INTERFRAME_DELAY 1011
+#define MNG_FN_DISPLAY_IMAGE 1012
+#define MNG_FN_DROP_IMGOBJECTS 1013
+#define MNG_FN_DROP_ANIOBJECTS 1014
+#define MNG_FN_INFLATE_BUFFER 1015
+#define MNG_FN_DEFLATE_BUFFER 1016
+#define MNG_FN_WRITE_RAW_CHUNK 1017
+#define MNG_FN_WRITE_GRAPHIC 1018
+#define MNG_FN_SAVE_STATE 1019
+#define MNG_FN_RESTORE_STATE 1020
+#define MNG_FN_DROP_SAVEDATA 1021
+#define MNG_FN_EXECUTE_DELTA_IMAGE 1022
+#define MNG_FN_PROCESS_DISPLAY 1023
+#define MNG_FN_CLEAR_CANVAS 1024
+#define MNG_FN_READ_DATABUFFER 1025
+#define MNG_FN_STORE_ERROR 1026
+#define MNG_FN_DROP_INVALID_OBJECTS 1027
+#define MNG_FN_RELEASE_PUSHDATA 1028
+#define MNG_FN_READ_DATA 1029
+#define MNG_FN_READ_CHUNK_CRC 1030
+#define MNG_FN_RELEASE_PUSHCHUNK 1031
+
+/* ************************************************************************** */
+
+#define MNG_FN_DISPLAY_RGB8 1101
+#define MNG_FN_DISPLAY_RGBA8 1102
+#define MNG_FN_DISPLAY_ARGB8 1103
+#define MNG_FN_DISPLAY_BGR8 1104
+#define MNG_FN_DISPLAY_BGRA8 1105
+#define MNG_FN_DISPLAY_ABGR8 1106
+#define MNG_FN_DISPLAY_RGB16 1107
+#define MNG_FN_DISPLAY_RGBA16 1108
+#define MNG_FN_DISPLAY_ARGB16 1109
+#define MNG_FN_DISPLAY_BGR16 1110
+#define MNG_FN_DISPLAY_BGRA16 1111
+#define MNG_FN_DISPLAY_ABGR16 1112
+#define MNG_FN_DISPLAY_INDEX8 1113
+#define MNG_FN_DISPLAY_INDEXA8 1114
+#define MNG_FN_DISPLAY_AINDEX8 1115
+#define MNG_FN_DISPLAY_GRAY8 1116
+#define MNG_FN_DISPLAY_GRAY16 1117
+#define MNG_FN_DISPLAY_GRAYA8 1118
+#define MNG_FN_DISPLAY_GRAYA16 1119
+#define MNG_FN_DISPLAY_AGRAY8 1120
+#define MNG_FN_DISPLAY_AGRAY16 1121
+#define MNG_FN_DISPLAY_DX15 1122
+#define MNG_FN_DISPLAY_DX16 1123
+#define MNG_FN_DISPLAY_RGB8_A8 1124
+#define MNG_FN_DISPLAY_BGRA8PM 1125
+#define MNG_FN_DISPLAY_BGRX8 1126
+#define MNG_FN_DISPLAY_RGB565 1127
+#define MNG_FN_DISPLAY_RGBA565 1128
+#define MNG_FN_DISPLAY_BGR565 1129
+#define MNG_FN_DISPLAY_BGRA565 1130
+#define MNG_FN_DISPLAY_RGBA8_PM 1131
+#define MNG_FN_DISPLAY_ARGB8_PM 1132
+#define MNG_FN_DISPLAY_ABGR8_PM 1133
+#define MNG_FN_DISPLAY_BGR565_A8 1134
+#define MNG_FN_DISPLAY_RGB555 1135
+#define MNG_FN_DISPLAY_BGR555 1136
+
+/* ************************************************************************** */
+
+#define MNG_FN_INIT_FULL_CMS 1201
+#define MNG_FN_CORRECT_FULL_CMS 1202
+#define MNG_FN_INIT_GAMMA_ONLY 1204
+#define MNG_FN_CORRECT_GAMMA_ONLY 1205
+#define MNG_FN_CORRECT_APP_CMS 1206
+#define MNG_FN_INIT_FULL_CMS_OBJ 1207
+#define MNG_FN_INIT_GAMMA_ONLY_OBJ 1208
+#define MNG_FN_INIT_APP_CMS 1209
+#define MNG_FN_INIT_APP_CMS_OBJ 1210
+
+/* ************************************************************************** */
+
+#define MNG_FN_PROCESS_G1 1301
+#define MNG_FN_PROCESS_G2 1302
+#define MNG_FN_PROCESS_G4 1303
+#define MNG_FN_PROCESS_G8 1304
+#define MNG_FN_PROCESS_G16 1305
+#define MNG_FN_PROCESS_RGB8 1306
+#define MNG_FN_PROCESS_RGB16 1307
+#define MNG_FN_PROCESS_IDX1 1308
+#define MNG_FN_PROCESS_IDX2 1309
+#define MNG_FN_PROCESS_IDX4 1310
+#define MNG_FN_PROCESS_IDX8 1311
+#define MNG_FN_PROCESS_GA8 1312
+#define MNG_FN_PROCESS_GA16 1313
+#define MNG_FN_PROCESS_RGBA8 1314
+#define MNG_FN_PROCESS_RGBA16 1315
+
+/* ************************************************************************** */
+
+#define MNG_FN_INIT_G1_NI 1401
+#define MNG_FN_INIT_G1_I 1402
+#define MNG_FN_INIT_G2_NI 1403
+#define MNG_FN_INIT_G2_I 1404
+#define MNG_FN_INIT_G4_NI 1405
+#define MNG_FN_INIT_G4_I 1406
+#define MNG_FN_INIT_G8_NI 1407
+#define MNG_FN_INIT_G8_I 1408
+#define MNG_FN_INIT_G16_NI 1409
+#define MNG_FN_INIT_G16_I 1410
+#define MNG_FN_INIT_RGB8_NI 1411
+#define MNG_FN_INIT_RGB8_I 1412
+#define MNG_FN_INIT_RGB16_NI 1413
+#define MNG_FN_INIT_RGB16_I 1414
+#define MNG_FN_INIT_IDX1_NI 1415
+#define MNG_FN_INIT_IDX1_I 1416
+#define MNG_FN_INIT_IDX2_NI 1417
+#define MNG_FN_INIT_IDX2_I 1418
+#define MNG_FN_INIT_IDX4_NI 1419
+#define MNG_FN_INIT_IDX4_I 1420
+#define MNG_FN_INIT_IDX8_NI 1421
+#define MNG_FN_INIT_IDX8_I 1422
+#define MNG_FN_INIT_GA8_NI 1423
+#define MNG_FN_INIT_GA8_I 1424
+#define MNG_FN_INIT_GA16_NI 1425
+#define MNG_FN_INIT_GA16_I 1426
+#define MNG_FN_INIT_RGBA8_NI 1427
+#define MNG_FN_INIT_RGBA8_I 1428
+#define MNG_FN_INIT_RGBA16_NI 1429
+#define MNG_FN_INIT_RGBA16_I 1430
+
+#define MNG_FN_INIT_ROWPROC 1497
+#define MNG_FN_NEXT_ROW 1498
+#define MNG_FN_CLEANUP_ROWPROC 1499
+
+/* ************************************************************************** */
+
+#define MNG_FN_FILTER_A_ROW 1501
+#define MNG_FN_FILTER_SUB 1502
+#define MNG_FN_FILTER_UP 1503
+#define MNG_FN_FILTER_AVERAGE 1504
+#define MNG_FN_FILTER_PAETH 1505
+
+#define MNG_FN_INIT_ROWDIFFERING 1551
+#define MNG_FN_DIFFER_G1 1552
+#define MNG_FN_DIFFER_G2 1553
+#define MNG_FN_DIFFER_G4 1554
+#define MNG_FN_DIFFER_G8 1555
+#define MNG_FN_DIFFER_G16 1556
+#define MNG_FN_DIFFER_RGB8 1557
+#define MNG_FN_DIFFER_RGB16 1558
+#define MNG_FN_DIFFER_IDX1 1559
+#define MNG_FN_DIFFER_IDX2 1560
+#define MNG_FN_DIFFER_IDX4 1561
+#define MNG_FN_DIFFER_IDX8 1562
+#define MNG_FN_DIFFER_GA8 1563
+#define MNG_FN_DIFFER_GA16 1564
+#define MNG_FN_DIFFER_RGBA8 1565
+#define MNG_FN_DIFFER_RGBA16 1566
+
+/* ************************************************************************** */
+
+#define MNG_FN_CREATE_IMGDATAOBJECT 1601
+#define MNG_FN_FREE_IMGDATAOBJECT 1602
+#define MNG_FN_CLONE_IMGDATAOBJECT 1603
+#define MNG_FN_CREATE_IMGOBJECT 1604
+#define MNG_FN_FREE_IMGOBJECT 1605
+#define MNG_FN_FIND_IMGOBJECT 1606
+#define MNG_FN_CLONE_IMGOBJECT 1607
+#define MNG_FN_RESET_OBJECTDETAILS 1608
+#define MNG_FN_RENUM_IMGOBJECT 1609
+#define MNG_FN_PROMOTE_IMGOBJECT 1610
+#define MNG_FN_MAGNIFY_IMGOBJECT 1611
+#define MNG_FN_COLORCORRECT_OBJECT 1612
+
+/* ************************************************************************** */
+
+#define MNG_FN_STORE_G1 1701
+#define MNG_FN_STORE_G2 1702
+#define MNG_FN_STORE_G4 1703
+#define MNG_FN_STORE_G8 1704
+#define MNG_FN_STORE_G16 1705
+#define MNG_FN_STORE_RGB8 1706
+#define MNG_FN_STORE_RGB16 1707
+#define MNG_FN_STORE_IDX1 1708
+#define MNG_FN_STORE_IDX2 1709
+#define MNG_FN_STORE_IDX4 1710
+#define MNG_FN_STORE_IDX8 1711
+#define MNG_FN_STORE_GA8 1712
+#define MNG_FN_STORE_GA16 1713
+#define MNG_FN_STORE_RGBA8 1714
+#define MNG_FN_STORE_RGBA16 1715
+
+#define MNG_FN_RETRIEVE_G8 1751
+#define MNG_FN_RETRIEVE_G16 1752
+#define MNG_FN_RETRIEVE_RGB8 1753
+#define MNG_FN_RETRIEVE_RGB16 1754
+#define MNG_FN_RETRIEVE_IDX8 1755
+#define MNG_FN_RETRIEVE_GA8 1756
+#define MNG_FN_RETRIEVE_GA16 1757
+#define MNG_FN_RETRIEVE_RGBA8 1758
+#define MNG_FN_RETRIEVE_RGBA16 1759
+
+#define MNG_FN_DELTA_G1 1771
+#define MNG_FN_DELTA_G2 1772
+#define MNG_FN_DELTA_G4 1773
+#define MNG_FN_DELTA_G8 1774
+#define MNG_FN_DELTA_G16 1775
+#define MNG_FN_DELTA_RGB8 1776
+#define MNG_FN_DELTA_RGB16 1777
+#define MNG_FN_DELTA_IDX1 1778
+#define MNG_FN_DELTA_IDX2 1779
+#define MNG_FN_DELTA_IDX4 1780
+#define MNG_FN_DELTA_IDX8 1781
+#define MNG_FN_DELTA_GA8 1782
+#define MNG_FN_DELTA_GA16 1783
+#define MNG_FN_DELTA_RGBA8 1784
+#define MNG_FN_DELTA_RGBA16 1785
+
+/* ************************************************************************** */
+
+#define MNG_FN_CREATE_ANI_LOOP 1801
+#define MNG_FN_CREATE_ANI_ENDL 1802
+#define MNG_FN_CREATE_ANI_DEFI 1803
+#define MNG_FN_CREATE_ANI_BASI 1804
+#define MNG_FN_CREATE_ANI_CLON 1805
+#define MNG_FN_CREATE_ANI_PAST 1806
+#define MNG_FN_CREATE_ANI_DISC 1807
+#define MNG_FN_CREATE_ANI_BACK 1808
+#define MNG_FN_CREATE_ANI_FRAM 1809
+#define MNG_FN_CREATE_ANI_MOVE 1810
+#define MNG_FN_CREATE_ANI_CLIP 1811
+#define MNG_FN_CREATE_ANI_SHOW 1812
+#define MNG_FN_CREATE_ANI_TERM 1813
+#define MNG_FN_CREATE_ANI_SAVE 1814
+#define MNG_FN_CREATE_ANI_SEEK 1815
+#define MNG_FN_CREATE_ANI_GAMA 1816
+#define MNG_FN_CREATE_ANI_CHRM 1817
+#define MNG_FN_CREATE_ANI_SRGB 1818
+#define MNG_FN_CREATE_ANI_ICCP 1819
+#define MNG_FN_CREATE_ANI_PLTE 1820
+#define MNG_FN_CREATE_ANI_TRNS 1821
+#define MNG_FN_CREATE_ANI_BKGD 1822
+#define MNG_FN_CREATE_ANI_DHDR 1823
+#define MNG_FN_CREATE_ANI_PROM 1824
+#define MNG_FN_CREATE_ANI_IPNG 1825
+#define MNG_FN_CREATE_ANI_IJNG 1826
+#define MNG_FN_CREATE_ANI_PPLT 1827
+#define MNG_FN_CREATE_ANI_MAGN 1828
+
+#define MNG_FN_CREATE_ANI_IMAGE 1891
+#define MNG_FN_CREATE_EVENT 1892
+
+/* ************************************************************************** */
+
+#define MNG_FN_FREE_ANI_LOOP 1901
+#define MNG_FN_FREE_ANI_ENDL 1902
+#define MNG_FN_FREE_ANI_DEFI 1903
+#define MNG_FN_FREE_ANI_BASI 1904
+#define MNG_FN_FREE_ANI_CLON 1905
+#define MNG_FN_FREE_ANI_PAST 1906
+#define MNG_FN_FREE_ANI_DISC 1907
+#define MNG_FN_FREE_ANI_BACK 1908
+#define MNG_FN_FREE_ANI_FRAM 1909
+#define MNG_FN_FREE_ANI_MOVE 1910
+#define MNG_FN_FREE_ANI_CLIP 1911
+#define MNG_FN_FREE_ANI_SHOW 1912
+#define MNG_FN_FREE_ANI_TERM 1913
+#define MNG_FN_FREE_ANI_SAVE 1914
+#define MNG_FN_FREE_ANI_SEEK 1915
+#define MNG_FN_FREE_ANI_GAMA 1916
+#define MNG_FN_FREE_ANI_CHRM 1917
+#define MNG_FN_FREE_ANI_SRGB 1918
+#define MNG_FN_FREE_ANI_ICCP 1919
+#define MNG_FN_FREE_ANI_PLTE 1920
+#define MNG_FN_FREE_ANI_TRNS 1921
+#define MNG_FN_FREE_ANI_BKGD 1922
+#define MNG_FN_FREE_ANI_DHDR 1923
+#define MNG_FN_FREE_ANI_PROM 1924
+#define MNG_FN_FREE_ANI_IPNG 1925
+#define MNG_FN_FREE_ANI_IJNG 1926
+#define MNG_FN_FREE_ANI_PPLT 1927
+#define MNG_FN_FREE_ANI_MAGN 1928
+
+#define MNG_FN_FREE_ANI_IMAGE 1991
+#define MNG_FN_FREE_EVENT 1992
+
+/* ************************************************************************** */
+
+#define MNG_FN_PROCESS_ANI_LOOP 2001
+#define MNG_FN_PROCESS_ANI_ENDL 2002
+#define MNG_FN_PROCESS_ANI_DEFI 2003
+#define MNG_FN_PROCESS_ANI_BASI 2004
+#define MNG_FN_PROCESS_ANI_CLON 2005
+#define MNG_FN_PROCESS_ANI_PAST 2006
+#define MNG_FN_PROCESS_ANI_DISC 2007
+#define MNG_FN_PROCESS_ANI_BACK 2008
+#define MNG_FN_PROCESS_ANI_FRAM 2009
+#define MNG_FN_PROCESS_ANI_MOVE 2010
+#define MNG_FN_PROCESS_ANI_CLIP 2011
+#define MNG_FN_PROCESS_ANI_SHOW 2012
+#define MNG_FN_PROCESS_ANI_TERM 2013
+#define MNG_FN_PROCESS_ANI_SAVE 2014
+#define MNG_FN_PROCESS_ANI_SEEK 2015
+#define MNG_FN_PROCESS_ANI_GAMA 2016
+#define MNG_FN_PROCESS_ANI_CHRM 2017
+#define MNG_FN_PROCESS_ANI_SRGB 2018
+#define MNG_FN_PROCESS_ANI_ICCP 2019
+#define MNG_FN_PROCESS_ANI_PLTE 2020
+#define MNG_FN_PROCESS_ANI_TRNS 2021
+#define MNG_FN_PROCESS_ANI_BKGD 2022
+#define MNG_FN_PROCESS_ANI_DHDR 2023
+#define MNG_FN_PROCESS_ANI_PROM 2024
+#define MNG_FN_PROCESS_ANI_IPNG 2025
+#define MNG_FN_PROCESS_ANI_IJNG 2026
+#define MNG_FN_PROCESS_ANI_PPLT 2027
+#define MNG_FN_PROCESS_ANI_MAGN 2028
+
+#define MNG_FN_PROCESS_ANI_IMAGE 2091
+#define MNG_FN_PROCESS_EVENT 2092
+
+/* ************************************************************************** */
+
+#define MNG_FN_RESTORE_BACKIMAGE 2101
+#define MNG_FN_RESTORE_BACKCOLOR 2102
+#define MNG_FN_RESTORE_BGCOLOR 2103
+#define MNG_FN_RESTORE_RGB8 2104
+#define MNG_FN_RESTORE_BGR8 2105
+#define MNG_FN_RESTORE_BKGD 2106
+#define MNG_FN_RESTORE_BGRX8 2107
+#define MNG_FN_RESTORE_RGB565 2108
+#define MNG_FN_RESTORE_BGR565 2109
+
+/* ************************************************************************** */
+
+#define MNG_FN_INIT_IHDR 2201
+#define MNG_FN_INIT_PLTE 2202
+#define MNG_FN_INIT_IDAT 2203
+#define MNG_FN_INIT_IEND 2204
+#define MNG_FN_INIT_TRNS 2205
+#define MNG_FN_INIT_GAMA 2206
+#define MNG_FN_INIT_CHRM 2207
+#define MNG_FN_INIT_SRGB 2208
+#define MNG_FN_INIT_ICCP 2209
+#define MNG_FN_INIT_TEXT 2210
+#define MNG_FN_INIT_ZTXT 2211
+#define MNG_FN_INIT_ITXT 2212
+#define MNG_FN_INIT_BKGD 2213
+#define MNG_FN_INIT_PHYS 2214
+#define MNG_FN_INIT_SBIT 2215
+#define MNG_FN_INIT_SPLT 2216
+#define MNG_FN_INIT_HIST 2217
+#define MNG_FN_INIT_TIME 2218
+#define MNG_FN_INIT_MHDR 2219
+#define MNG_FN_INIT_MEND 2220
+#define MNG_FN_INIT_LOOP 2221
+#define MNG_FN_INIT_ENDL 2222
+#define MNG_FN_INIT_DEFI 2223
+#define MNG_FN_INIT_BASI 2224
+#define MNG_FN_INIT_CLON 2225
+#define MNG_FN_INIT_PAST 2226
+#define MNG_FN_INIT_DISC 2227
+#define MNG_FN_INIT_BACK 2228
+#define MNG_FN_INIT_FRAM 2229
+#define MNG_FN_INIT_MOVE 2230
+#define MNG_FN_INIT_CLIP 2231
+#define MNG_FN_INIT_SHOW 2232
+#define MNG_FN_INIT_TERM 2233
+#define MNG_FN_INIT_SAVE 2234
+#define MNG_FN_INIT_SEEK 2235
+#define MNG_FN_INIT_EXPI 2236
+#define MNG_FN_INIT_FPRI 2237
+#define MNG_FN_INIT_NEED 2238
+#define MNG_FN_INIT_PHYG 2239
+#define MNG_FN_INIT_JHDR 2240
+#define MNG_FN_INIT_JDAT 2241
+#define MNG_FN_INIT_JSEP 2242
+#define MNG_FN_INIT_DHDR 2243
+#define MNG_FN_INIT_PROM 2244
+#define MNG_FN_INIT_IPNG 2245
+#define MNG_FN_INIT_PPLT 2246
+#define MNG_FN_INIT_IJNG 2247
+#define MNG_FN_INIT_DROP 2248
+#define MNG_FN_INIT_DBYK 2249
+#define MNG_FN_INIT_ORDR 2250
+#define MNG_FN_INIT_UNKNOWN 2251
+#define MNG_FN_INIT_MAGN 2252
+#define MNG_FN_INIT_JDAA 2253
+#define MNG_FN_INIT_EVNT 2254
+#define MNG_FN_INIT_MPNG 2255
+
+/* ************************************************************************** */
+
+#define MNG_FN_ASSIGN_IHDR 2301
+#define MNG_FN_ASSIGN_PLTE 2302
+#define MNG_FN_ASSIGN_IDAT 2303
+#define MNG_FN_ASSIGN_IEND 2304
+#define MNG_FN_ASSIGN_TRNS 2305
+#define MNG_FN_ASSIGN_GAMA 2306
+#define MNG_FN_ASSIGN_CHRM 2307
+#define MNG_FN_ASSIGN_SRGB 2308
+#define MNG_FN_ASSIGN_ICCP 2309
+#define MNG_FN_ASSIGN_TEXT 2310
+#define MNG_FN_ASSIGN_ZTXT 2311
+#define MNG_FN_ASSIGN_ITXT 2312
+#define MNG_FN_ASSIGN_BKGD 2313
+#define MNG_FN_ASSIGN_PHYS 2314
+#define MNG_FN_ASSIGN_SBIT 2315
+#define MNG_FN_ASSIGN_SPLT 2316
+#define MNG_FN_ASSIGN_HIST 2317
+#define MNG_FN_ASSIGN_TIME 2318
+#define MNG_FN_ASSIGN_MHDR 2319
+#define MNG_FN_ASSIGN_MEND 2320
+#define MNG_FN_ASSIGN_LOOP 2321
+#define MNG_FN_ASSIGN_ENDL 2322
+#define MNG_FN_ASSIGN_DEFI 2323
+#define MNG_FN_ASSIGN_BASI 2324
+#define MNG_FN_ASSIGN_CLON 2325
+#define MNG_FN_ASSIGN_PAST 2326
+#define MNG_FN_ASSIGN_DISC 2327
+#define MNG_FN_ASSIGN_BACK 2328
+#define MNG_FN_ASSIGN_FRAM 2329
+#define MNG_FN_ASSIGN_MOVE 2330
+#define MNG_FN_ASSIGN_CLIP 2331
+#define MNG_FN_ASSIGN_SHOW 2332
+#define MNG_FN_ASSIGN_TERM 2333
+#define MNG_FN_ASSIGN_SAVE 2334
+#define MNG_FN_ASSIGN_SEEK 2335
+#define MNG_FN_ASSIGN_EXPI 2336
+#define MNG_FN_ASSIGN_FPRI 2337
+#define MNG_FN_ASSIGN_NEED 2338
+#define MNG_FN_ASSIGN_PHYG 2339
+#define MNG_FN_ASSIGN_JHDR 2340
+#define MNG_FN_ASSIGN_JDAT 2341
+#define MNG_FN_ASSIGN_JSEP 2342
+#define MNG_FN_ASSIGN_DHDR 2343
+#define MNG_FN_ASSIGN_PROM 2344
+#define MNG_FN_ASSIGN_IPNG 2345
+#define MNG_FN_ASSIGN_PPLT 2346
+#define MNG_FN_ASSIGN_IJNG 2347
+#define MNG_FN_ASSIGN_DROP 2348
+#define MNG_FN_ASSIGN_DBYK 2349
+#define MNG_FN_ASSIGN_ORDR 2350
+#define MNG_FN_ASSIGN_UNKNOWN 2351
+#define MNG_FN_ASSIGN_MAGN 2352
+#define MNG_FN_ASSIGN_JDAA 2353
+#define MNG_FN_ASSIGN_EVNT 2354
+#define MNG_FN_ASSIGN_MPNG 2355
+
+/* ************************************************************************** */
+
+#define MNG_FN_FREE_IHDR 2401
+#define MNG_FN_FREE_PLTE 2402
+#define MNG_FN_FREE_IDAT 2403
+#define MNG_FN_FREE_IEND 2404
+#define MNG_FN_FREE_TRNS 2405
+#define MNG_FN_FREE_GAMA 2406
+#define MNG_FN_FREE_CHRM 2407
+#define MNG_FN_FREE_SRGB 2408
+#define MNG_FN_FREE_ICCP 2409
+#define MNG_FN_FREE_TEXT 2410
+#define MNG_FN_FREE_ZTXT 2411
+#define MNG_FN_FREE_ITXT 2412
+#define MNG_FN_FREE_BKGD 2413
+#define MNG_FN_FREE_PHYS 2414
+#define MNG_FN_FREE_SBIT 2415
+#define MNG_FN_FREE_SPLT 2416
+#define MNG_FN_FREE_HIST 2417
+#define MNG_FN_FREE_TIME 2418
+#define MNG_FN_FREE_MHDR 2419
+#define MNG_FN_FREE_MEND 2420
+#define MNG_FN_FREE_LOOP 2421
+#define MNG_FN_FREE_ENDL 2422
+#define MNG_FN_FREE_DEFI 2423
+#define MNG_FN_FREE_BASI 2424
+#define MNG_FN_FREE_CLON 2425
+#define MNG_FN_FREE_PAST 2426
+#define MNG_FN_FREE_DISC 2427
+#define MNG_FN_FREE_BACK 2428
+#define MNG_FN_FREE_FRAM 2429
+#define MNG_FN_FREE_MOVE 2430
+#define MNG_FN_FREE_CLIP 2431
+#define MNG_FN_FREE_SHOW 2432
+#define MNG_FN_FREE_TERM 2433
+#define MNG_FN_FREE_SAVE 2434
+#define MNG_FN_FREE_SEEK 2435
+#define MNG_FN_FREE_EXPI 2436
+#define MNG_FN_FREE_FPRI 2437
+#define MNG_FN_FREE_NEED 2438
+#define MNG_FN_FREE_PHYG 2439
+#define MNG_FN_FREE_JHDR 2440
+#define MNG_FN_FREE_JDAT 2441
+#define MNG_FN_FREE_JSEP 2442
+#define MNG_FN_FREE_DHDR 2443
+#define MNG_FN_FREE_PROM 2444
+#define MNG_FN_FREE_IPNG 2445
+#define MNG_FN_FREE_PPLT 2446
+#define MNG_FN_FREE_IJNG 2447
+#define MNG_FN_FREE_DROP 2448
+#define MNG_FN_FREE_DBYK 2449
+#define MNG_FN_FREE_ORDR 2450
+#define MNG_FN_FREE_UNKNOWN 2451
+#define MNG_FN_FREE_MAGN 2452
+#define MNG_FN_FREE_JDAA 2453
+#define MNG_FN_FREE_EVNT 2454
+#define MNG_FN_FREE_MPNG 2455
+
+/* ************************************************************************** */
+
+#define MNG_FN_READ_IHDR 2601
+#define MNG_FN_READ_PLTE 2602
+#define MNG_FN_READ_IDAT 2603
+#define MNG_FN_READ_IEND 2604
+#define MNG_FN_READ_TRNS 2605
+#define MNG_FN_READ_GAMA 2606
+#define MNG_FN_READ_CHRM 2607
+#define MNG_FN_READ_SRGB 2608
+#define MNG_FN_READ_ICCP 2609
+#define MNG_FN_READ_TEXT 2610
+#define MNG_FN_READ_ZTXT 2611
+#define MNG_FN_READ_ITXT 2612
+#define MNG_FN_READ_BKGD 2613
+#define MNG_FN_READ_PHYS 2614
+#define MNG_FN_READ_SBIT 2615
+#define MNG_FN_READ_SPLT 2616
+#define MNG_FN_READ_HIST 2617
+#define MNG_FN_READ_TIME 2618
+#define MNG_FN_READ_MHDR 2619
+#define MNG_FN_READ_MEND 2620
+#define MNG_FN_READ_LOOP 2621
+#define MNG_FN_READ_ENDL 2622
+#define MNG_FN_READ_DEFI 2623
+#define MNG_FN_READ_BASI 2624
+#define MNG_FN_READ_CLON 2625
+#define MNG_FN_READ_PAST 2626
+#define MNG_FN_READ_DISC 2627
+#define MNG_FN_READ_BACK 2628
+#define MNG_FN_READ_FRAM 2629
+#define MNG_FN_READ_MOVE 2630
+#define MNG_FN_READ_CLIP 2631
+#define MNG_FN_READ_SHOW 2632
+#define MNG_FN_READ_TERM 2633
+#define MNG_FN_READ_SAVE 2634
+#define MNG_FN_READ_SEEK 2635
+#define MNG_FN_READ_EXPI 2636
+#define MNG_FN_READ_FPRI 2637
+#define MNG_FN_READ_NEED 2638
+#define MNG_FN_READ_PHYG 2639
+#define MNG_FN_READ_JHDR 2640
+#define MNG_FN_READ_JDAT 2641
+#define MNG_FN_READ_JSEP 2642
+#define MNG_FN_READ_DHDR 2643
+#define MNG_FN_READ_PROM 2644
+#define MNG_FN_READ_IPNG 2645
+#define MNG_FN_READ_PPLT 2646
+#define MNG_FN_READ_IJNG 2647
+#define MNG_FN_READ_DROP 2648
+#define MNG_FN_READ_DBYK 2649
+#define MNG_FN_READ_ORDR 2650
+#define MNG_FN_READ_UNKNOWN 2651
+#define MNG_FN_READ_MAGN 2652
+#define MNG_FN_READ_JDAA 2653
+#define MNG_FN_READ_EVNT 2654
+#define MNG_FN_READ_MPNG 2655
+
+/* ************************************************************************** */
+
+#define MNG_FN_WRITE_IHDR 2801
+#define MNG_FN_WRITE_PLTE 2802
+#define MNG_FN_WRITE_IDAT 2803
+#define MNG_FN_WRITE_IEND 2804
+#define MNG_FN_WRITE_TRNS 2805
+#define MNG_FN_WRITE_GAMA 2806
+#define MNG_FN_WRITE_CHRM 2807
+#define MNG_FN_WRITE_SRGB 2808
+#define MNG_FN_WRITE_ICCP 2809
+#define MNG_FN_WRITE_TEXT 2810
+#define MNG_FN_WRITE_ZTXT 2811
+#define MNG_FN_WRITE_ITXT 2812
+#define MNG_FN_WRITE_BKGD 2813
+#define MNG_FN_WRITE_PHYS 2814
+#define MNG_FN_WRITE_SBIT 2815
+#define MNG_FN_WRITE_SPLT 2816
+#define MNG_FN_WRITE_HIST 2817
+#define MNG_FN_WRITE_TIME 2818
+#define MNG_FN_WRITE_MHDR 2819
+#define MNG_FN_WRITE_MEND 2820
+#define MNG_FN_WRITE_LOOP 2821
+#define MNG_FN_WRITE_ENDL 2822
+#define MNG_FN_WRITE_DEFI 2823
+#define MNG_FN_WRITE_BASI 2824
+#define MNG_FN_WRITE_CLON 2825
+#define MNG_FN_WRITE_PAST 2826
+#define MNG_FN_WRITE_DISC 2827
+#define MNG_FN_WRITE_BACK 2828
+#define MNG_FN_WRITE_FRAM 2829
+#define MNG_FN_WRITE_MOVE 2830
+#define MNG_FN_WRITE_CLIP 2831
+#define MNG_FN_WRITE_SHOW 2832
+#define MNG_FN_WRITE_TERM 2833
+#define MNG_FN_WRITE_SAVE 2834
+#define MNG_FN_WRITE_SEEK 2835
+#define MNG_FN_WRITE_EXPI 2836
+#define MNG_FN_WRITE_FPRI 2837
+#define MNG_FN_WRITE_NEED 2838
+#define MNG_FN_WRITE_PHYG 2839
+#define MNG_FN_WRITE_JHDR 2840
+#define MNG_FN_WRITE_JDAT 2841
+#define MNG_FN_WRITE_JSEP 2842
+#define MNG_FN_WRITE_DHDR 2843
+#define MNG_FN_WRITE_PROM 2844
+#define MNG_FN_WRITE_IPNG 2845
+#define MNG_FN_WRITE_PPLT 2846
+#define MNG_FN_WRITE_IJNG 2847
+#define MNG_FN_WRITE_DROP 2848
+#define MNG_FN_WRITE_DBYK 2849
+#define MNG_FN_WRITE_ORDR 2850
+#define MNG_FN_WRITE_UNKNOWN 2851
+#define MNG_FN_WRITE_MAGN 2852
+#define MNG_FN_WRITE_JDAA 2853
+#define MNG_FN_WRITE_EVNT 2854
+#define MNG_FN_WRITE_MPNG 2855
+
+/* ************************************************************************** */
+
+#define MNG_FN_ZLIB_INITIALIZE 3001
+#define MNG_FN_ZLIB_CLEANUP 3002
+#define MNG_FN_ZLIB_INFLATEINIT 3003
+#define MNG_FN_ZLIB_INFLATEROWS 3004
+#define MNG_FN_ZLIB_INFLATEDATA 3005
+#define MNG_FN_ZLIB_INFLATEFREE 3006
+#define MNG_FN_ZLIB_DEFLATEINIT 3007
+#define MNG_FN_ZLIB_DEFLATEROWS 3008
+#define MNG_FN_ZLIB_DEFLATEDATA 3009
+#define MNG_FN_ZLIB_DEFLATEFREE 3010
+
+/* ************************************************************************** */
+
+#define MNG_FN_PROCESS_DISPLAY_IHDR 3201
+#define MNG_FN_PROCESS_DISPLAY_PLTE 3202
+#define MNG_FN_PROCESS_DISPLAY_IDAT 3203
+#define MNG_FN_PROCESS_DISPLAY_IEND 3204
+#define MNG_FN_PROCESS_DISPLAY_TRNS 3205
+#define MNG_FN_PROCESS_DISPLAY_GAMA 3206
+#define MNG_FN_PROCESS_DISPLAY_CHRM 3207
+#define MNG_FN_PROCESS_DISPLAY_SRGB 3208
+#define MNG_FN_PROCESS_DISPLAY_ICCP 3209
+#define MNG_FN_PROCESS_DISPLAY_BKGD 3210
+#define MNG_FN_PROCESS_DISPLAY_PHYS 3211
+#define MNG_FN_PROCESS_DISPLAY_SBIT 3212
+#define MNG_FN_PROCESS_DISPLAY_SPLT 3213
+#define MNG_FN_PROCESS_DISPLAY_HIST 3214
+#define MNG_FN_PROCESS_DISPLAY_MHDR 3215
+#define MNG_FN_PROCESS_DISPLAY_MEND 3216
+#define MNG_FN_PROCESS_DISPLAY_LOOP 3217
+#define MNG_FN_PROCESS_DISPLAY_ENDL 3218
+#define MNG_FN_PROCESS_DISPLAY_DEFI 3219
+#define MNG_FN_PROCESS_DISPLAY_BASI 3220
+#define MNG_FN_PROCESS_DISPLAY_CLON 3221
+#define MNG_FN_PROCESS_DISPLAY_PAST 3222
+#define MNG_FN_PROCESS_DISPLAY_DISC 3223
+#define MNG_FN_PROCESS_DISPLAY_BACK 3224
+#define MNG_FN_PROCESS_DISPLAY_FRAM 3225
+#define MNG_FN_PROCESS_DISPLAY_MOVE 3226
+#define MNG_FN_PROCESS_DISPLAY_CLIP 3227
+#define MNG_FN_PROCESS_DISPLAY_SHOW 3228
+#define MNG_FN_PROCESS_DISPLAY_TERM 3229
+#define MNG_FN_PROCESS_DISPLAY_SAVE 3230
+#define MNG_FN_PROCESS_DISPLAY_SEEK 3231
+#define MNG_FN_PROCESS_DISPLAY_EXPI 3232
+#define MNG_FN_PROCESS_DISPLAY_FPRI 3233
+#define MNG_FN_PROCESS_DISPLAY_NEED 3234
+#define MNG_FN_PROCESS_DISPLAY_PHYG 3235
+#define MNG_FN_PROCESS_DISPLAY_JHDR 3236
+#define MNG_FN_PROCESS_DISPLAY_JDAT 3237
+#define MNG_FN_PROCESS_DISPLAY_JSEP 3238
+#define MNG_FN_PROCESS_DISPLAY_DHDR 3239
+#define MNG_FN_PROCESS_DISPLAY_PROM 3240
+#define MNG_FN_PROCESS_DISPLAY_IPNG 3241
+#define MNG_FN_PROCESS_DISPLAY_PPLT 3242
+#define MNG_FN_PROCESS_DISPLAY_IJNG 3243
+#define MNG_FN_PROCESS_DISPLAY_DROP 3244
+#define MNG_FN_PROCESS_DISPLAY_DBYK 3245
+#define MNG_FN_PROCESS_DISPLAY_ORDR 3246
+#define MNG_FN_PROCESS_DISPLAY_MAGN 3247
+#define MNG_FN_PROCESS_DISPLAY_JDAA 3248
+
+/* ************************************************************************** */
+
+#define MNG_FN_JPEG_INITIALIZE 3401
+#define MNG_FN_JPEG_CLEANUP 3402
+#define MNG_FN_JPEG_DECOMPRESSINIT 3403
+#define MNG_FN_JPEG_DECOMPRESSDATA 3404
+#define MNG_FN_JPEG_DECOMPRESSFREE 3405
+
+#define MNG_FN_STORE_JPEG_G8 3501
+#define MNG_FN_STORE_JPEG_RGB8 3502
+#define MNG_FN_STORE_JPEG_G12 3503
+#define MNG_FN_STORE_JPEG_RGB12 3504
+#define MNG_FN_STORE_JPEG_GA8 3505
+#define MNG_FN_STORE_JPEG_RGBA8 3506
+#define MNG_FN_STORE_JPEG_GA12 3507
+#define MNG_FN_STORE_JPEG_RGBA12 3508
+#define MNG_FN_STORE_JPEG_G8_ALPHA 3509
+#define MNG_FN_STORE_JPEG_RGB8_ALPHA 3510
+
+#define MNG_FN_INIT_JPEG_A1_NI 3511
+#define MNG_FN_INIT_JPEG_A2_NI 3512
+#define MNG_FN_INIT_JPEG_A4_NI 3513
+#define MNG_FN_INIT_JPEG_A8_NI 3514
+#define MNG_FN_INIT_JPEG_A16_NI 3515
+
+#define MNG_FN_STORE_JPEG_G8_A1 3521
+#define MNG_FN_STORE_JPEG_G8_A2 3522
+#define MNG_FN_STORE_JPEG_G8_A4 3523
+#define MNG_FN_STORE_JPEG_G8_A8 3524
+#define MNG_FN_STORE_JPEG_G8_A16 3525
+
+#define MNG_FN_STORE_JPEG_RGB8_A1 3531
+#define MNG_FN_STORE_JPEG_RGB8_A2 3532
+#define MNG_FN_STORE_JPEG_RGB8_A4 3533
+#define MNG_FN_STORE_JPEG_RGB8_A8 3534
+#define MNG_FN_STORE_JPEG_RGB8_A16 3535
+
+#define MNG_FN_STORE_JPEG_G12_A1 3541
+#define MNG_FN_STORE_JPEG_G12_A2 3542
+#define MNG_FN_STORE_JPEG_G12_A4 3543
+#define MNG_FN_STORE_JPEG_G12_A8 3544
+#define MNG_FN_STORE_JPEG_G12_A16 3545
+
+#define MNG_FN_STORE_JPEG_RGB12_A1 3551
+#define MNG_FN_STORE_JPEG_RGB12_A2 3552
+#define MNG_FN_STORE_JPEG_RGB12_A4 3553
+#define MNG_FN_STORE_JPEG_RGB12_A8 3554
+#define MNG_FN_STORE_JPEG_RGB12_A16 3555
+
+#define MNG_FN_NEXT_JPEG_ALPHAROW 3591
+#define MNG_FN_NEXT_JPEG_ROW 3592
+#define MNG_FN_DISPLAY_JPEG_ROWS 3593
+
+/* ************************************************************************** */
+
+#define MNG_FN_MAGNIFY_G8_X1 3701
+#define MNG_FN_MAGNIFY_G8_X2 3702
+#define MNG_FN_MAGNIFY_RGB8_X1 3703
+#define MNG_FN_MAGNIFY_RGB8_X2 3704
+#define MNG_FN_MAGNIFY_GA8_X1 3705
+#define MNG_FN_MAGNIFY_GA8_X2 3706
+#define MNG_FN_MAGNIFY_GA8_X3 3707
+#define MNG_FN_MAGNIFY_GA8_X4 3708
+#define MNG_FN_MAGNIFY_RGBA8_X1 3709
+#define MNG_FN_MAGNIFY_RGBA8_X2 3710
+#define MNG_FN_MAGNIFY_RGBA8_X3 3711
+#define MNG_FN_MAGNIFY_RGBA8_X4 3712
+#define MNG_FN_MAGNIFY_G8_X3 3713
+#define MNG_FN_MAGNIFY_RGB8_X3 3714
+#define MNG_FN_MAGNIFY_GA8_X5 3715
+#define MNG_FN_MAGNIFY_RGBA8_X5 3716
+
+#define MNG_FN_MAGNIFY_G16_X1 3725
+#define MNG_FN_MAGNIFY_G16_X2 3726
+#define MNG_FN_MAGNIFY_RGB16_X1 3727
+#define MNG_FN_MAGNIFY_RGB16_X2 3728
+#define MNG_FN_MAGNIFY_GA16_X1 3729
+#define MNG_FN_MAGNIFY_GA16_X2 3730
+#define MNG_FN_MAGNIFY_GA16_X3 3731
+#define MNG_FN_MAGNIFY_GA16_X4 3732
+#define MNG_FN_MAGNIFY_RGBA16_X1 3733
+#define MNG_FN_MAGNIFY_RGBA16_X2 3734
+#define MNG_FN_MAGNIFY_RGBA16_X3 3735
+#define MNG_FN_MAGNIFY_RGBA16_X4 3736
+#define MNG_FN_MAGNIFY_G16_X3 3737
+#define MNG_FN_MAGNIFY_RGB16_X3 3738
+#define MNG_FN_MAGNIFY_GA16_X5 3739
+#define MNG_FN_MAGNIFY_RGBA16_X5 3740
+
+#define MNG_FN_MAGNIFY_G8_Y1 3751
+#define MNG_FN_MAGNIFY_G8_Y2 3752
+#define MNG_FN_MAGNIFY_RGB8_Y1 3753
+#define MNG_FN_MAGNIFY_RGB8_Y2 3754
+#define MNG_FN_MAGNIFY_GA8_Y1 3755
+#define MNG_FN_MAGNIFY_GA8_Y2 3756
+#define MNG_FN_MAGNIFY_GA8_Y3 3757
+#define MNG_FN_MAGNIFY_GA8_Y4 3758
+#define MNG_FN_MAGNIFY_RGBA8_Y1 3759
+#define MNG_FN_MAGNIFY_RGBA8_Y2 3760
+#define MNG_FN_MAGNIFY_RGBA8_Y3 3761
+#define MNG_FN_MAGNIFY_RGBA8_Y4 3762
+#define MNG_FN_MAGNIFY_G8_Y3 3763
+#define MNG_FN_MAGNIFY_RGB8_Y3 3764
+#define MNG_FN_MAGNIFY_GA8_Y5 3765
+#define MNG_FN_MAGNIFY_RGBA8_Y5 3766
+
+#define MNG_FN_MAGNIFY_G16_Y1 3775
+#define MNG_FN_MAGNIFY_G16_Y2 3776
+#define MNG_FN_MAGNIFY_RGB16_Y1 3777
+#define MNG_FN_MAGNIFY_RGB16_Y2 3778
+#define MNG_FN_MAGNIFY_GA16_Y1 3779
+#define MNG_FN_MAGNIFY_GA16_Y2 3780
+#define MNG_FN_MAGNIFY_GA16_Y3 3781
+#define MNG_FN_MAGNIFY_GA16_Y4 3782
+#define MNG_FN_MAGNIFY_RGBA16_Y1 3783
+#define MNG_FN_MAGNIFY_RGBA16_Y2 3784
+#define MNG_FN_MAGNIFY_RGBA16_Y3 3785
+#define MNG_FN_MAGNIFY_RGBA16_Y4 3786
+#define MNG_FN_MAGNIFY_G16_Y3 3787
+#define MNG_FN_MAGNIFY_RGB16_Y3 3788
+#define MNG_FN_MAGNIFY_GA16_Y5 3789
+#define MNG_FN_MAGNIFY_RGBA16_Y5 3790
+
+/* ************************************************************************** */
+
+#define MNG_FN_DELTA_G1_G1 3801
+#define MNG_FN_DELTA_G2_G2 3802
+#define MNG_FN_DELTA_G4_G4 3803
+#define MNG_FN_DELTA_G8_G8 3804
+#define MNG_FN_DELTA_G16_G16 3805
+#define MNG_FN_DELTA_RGB8_RGB8 3806
+#define MNG_FN_DELTA_RGB16_RGB16 3807
+#define MNG_FN_DELTA_GA8_GA8 3808
+#define MNG_FN_DELTA_GA8_G8 3809
+#define MNG_FN_DELTA_GA8_A8 3810
+#define MNG_FN_DELTA_GA16_GA16 3811
+#define MNG_FN_DELTA_GA16_G16 3812
+#define MNG_FN_DELTA_GA16_A16 3813
+#define MNG_FN_DELTA_RGBA8_RGBA8 3814
+#define MNG_FN_DELTA_RGBA8_RGB8 3815
+#define MNG_FN_DELTA_RGBA8_A8 3816
+#define MNG_FN_DELTA_RGBA16_RGBA16 3817
+#define MNG_FN_DELTA_RGBA16_RGB16 3818
+#define MNG_FN_DELTA_RGBA16_A16 3819
+
+#define MNG_FN_PROMOTE_G8_G8 3901
+#define MNG_FN_PROMOTE_G8_G16 3902
+#define MNG_FN_PROMOTE_G16_G16 3903
+#define MNG_FN_PROMOTE_G8_GA8 3904
+#define MNG_FN_PROMOTE_G8_GA16 3905
+#define MNG_FN_PROMOTE_G16_GA16 3906
+#define MNG_FN_PROMOTE_G8_RGB8 3907
+#define MNG_FN_PROMOTE_G8_RGB16 3908
+#define MNG_FN_PROMOTE_G16_RGB16 3909
+#define MNG_FN_PROMOTE_G8_RGBA8 3910
+#define MNG_FN_PROMOTE_G8_RGBA16 3911
+#define MNG_FN_PROMOTE_G16_RGBA16 3912
+#define MNG_FN_PROMOTE_GA8_GA16 3913
+#define MNG_FN_PROMOTE_GA8_RGBA8 3914
+#define MNG_FN_PROMOTE_GA8_RGBA16 3915
+#define MNG_FN_PROMOTE_GA16_RGBA16 3916
+#define MNG_FN_PROMOTE_RGB8_RGB16 3917
+#define MNG_FN_PROMOTE_RGB8_RGBA8 3918
+#define MNG_FN_PROMOTE_RGB8_RGBA16 3919
+#define MNG_FN_PROMOTE_RGB16_RGBA16 3920
+#define MNG_FN_PROMOTE_RGBA8_RGBA16 3921
+#define MNG_FN_PROMOTE_IDX8_RGB8 3922
+#define MNG_FN_PROMOTE_IDX8_RGB16 3923
+#define MNG_FN_PROMOTE_IDX8_RGBA8 3924
+#define MNG_FN_PROMOTE_IDX8_RGBA16 3925
+
+#define MNG_FN_SCALE_G1_G2 4001
+#define MNG_FN_SCALE_G1_G4 4002
+#define MNG_FN_SCALE_G1_G8 4003
+#define MNG_FN_SCALE_G1_G16 4004
+#define MNG_FN_SCALE_G2_G4 4005
+#define MNG_FN_SCALE_G2_G8 4006
+#define MNG_FN_SCALE_G2_G16 4007
+#define MNG_FN_SCALE_G4_G8 4008
+#define MNG_FN_SCALE_G4_G16 4009
+#define MNG_FN_SCALE_G8_G16 4010
+#define MNG_FN_SCALE_GA8_GA16 4011
+#define MNG_FN_SCALE_RGB8_RGB16 4012
+#define MNG_FN_SCALE_RGBA8_RGBA16 4013
+
+#define MNG_FN_SCALE_G2_G1 4021
+#define MNG_FN_SCALE_G4_G1 4022
+#define MNG_FN_SCALE_G8_G1 4023
+#define MNG_FN_SCALE_G16_G1 4024
+#define MNG_FN_SCALE_G4_G2 4025
+#define MNG_FN_SCALE_G8_G2 4026
+#define MNG_FN_SCALE_G16_G2 4027
+#define MNG_FN_SCALE_G8_G4 4028
+#define MNG_FN_SCALE_G16_G4 4029
+#define MNG_FN_SCALE_G16_G8 4030
+#define MNG_FN_SCALE_GA16_GA8 4031
+#define MNG_FN_SCALE_RGB16_RGB8 4032
+#define MNG_FN_SCALE_RGBA16_RGBA8 4033
+
+#define MNG_FN_COMPOSEOVER_RGBA8 4501
+#define MNG_FN_COMPOSEOVER_RGBA16 4502
+#define MNG_FN_COMPOSEUNDER_RGBA8 4503
+#define MNG_FN_COMPOSEUNDER_RGBA16 4504
+
+#define MNG_FN_FLIP_RGBA8 4521
+#define MNG_FN_FLIP_RGBA16 4522
+#define MNG_FN_TILE_RGBA8 4523
+#define MNG_FN_TILE_RGBA16 4524
+
+/* ************************************************************************** */
+/* * * */
+/* * Trace string-table entry * */
+/* * * */
+/* ************************************************************************** */
+
+typedef struct {
+ mng_uint32 iFunction;
+ mng_pchar zTracetext;
+ } mng_trace_entry;
+typedef mng_trace_entry const * mng_trace_entryp;
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_TRACE_PROCS */
+
+/* ************************************************************************** */
+
+#endif /* _libmng_trace_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_types.h b/Source/LibMNG/libmng_types.h
new file mode 100644
index 0000000..000a9a4
--- /dev/null
+++ b/Source/LibMNG/libmng_types.h
@@ -0,0 +1,574 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_types.h copyright (c) 2000-2007 G.Juyn * */
+/* * version : 1.0.10 * */
+/* * * */
+/* * purpose : type specifications * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Specification of the types used by the library * */
+/* * Creates platform-independant structure * */
+/* * * */
+/* * changes : 0.5.1 - 05/06/2000 - G.Juyn * */
+/* * - added iteratechunk callback definition * */
+/* * 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - improved definitions for DLL support * */
+/* * - added 8-bit palette definition * */
+/* * - added general array definitions * */
+/* * - added MNG_NULL definition * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - changed most callback prototypes to allow the app * */
+/* * to report errors during callback processing * */
+/* * 0.5.1 - 05/16/2000 - G.Juyn * */
+/* * - moved standard header includes into this file * */
+/* * (stdlib/mem for mem-mngmt & math for fp gamma-calc) * */
+/* * * */
+/* * 0.5.2 - 05/18/2000 - G.Juyn * */
+/* * - B003 - fixed problem with <mem.h> being proprietary * */
+/* * to Borland platform * */
+/* * - added helper definitions for JNG (IJG-based) * */
+/* * - fixed support for IJGSRC6B * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - added default IJG compression parameters and such * */
+/* * 0.5.2 - 05/31/2000 - G.Juyn * */
+/* * - fixed inclusion for memcpy (contributed by Tim Rowley) * */
+/* * - added mng_int32p (contributed by Tim Rowley) * */
+/* * 0.5.2 - 06/02/2000 - G.Juyn * */
+/* * - removed SWAP_ENDIAN reference (contributed by Tim Rowley)* */
+/* * - added getalphaline callback for RGB8_A8 canvasstyle * */
+/* * * */
+/* * 0.5.3 - 06/21/2000 - G.Juyn * */
+/* * - added speedtype to facilitate testing * */
+/* * 0.5.3 - 06/27/2000 - G.Juyn * */
+/* * - added typedef for mng_size_t * */
+/* * - changed size parameter for memory callbacks to * */
+/* * mng_size_t * */
+/* * 0.5.3 - 06/28/2000 - G.Juyn * */
+/* * - changed definition of 32-bit ints (64-bit platforms) * */
+/* * - changed definition of mng_handle (64-bit platforms) * */
+/* * 0.5.3 - 06/29/2000 - G.Juyn * */
+/* * - changed definition of mng_handle (again) * */
+/* * - swapped refresh parameters * */
+/* * - added inclusion of stdlib.h for abs() * */
+/* * * */
+/* * 0.9.0 - 06/30/2000 - G.Juyn * */
+/* * - changed refresh parameters to 'x,y,width,height' * */
+/* * 0.9.1 - 07/10/2000 - G.Juyn * */
+/* * - added suspendbuffer constants * */
+/* * 0.9.1 - 07/15/2000 - G.Juyn * */
+/* * - added callbacks for SAVE/SEEK processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/07/2000 - G.Juyn * */
+/* * - B111300 - fixup for improved portability * */
+/* * 0.9.3 - 08/12/2000 - G.Juyn * */
+/* * - added workaround for faulty PhotoShop iCCP chunk * */
+/* * 0.9.3 - 09/11/2000 - G.Juyn * */
+/* * - added export of zlib functions from windows dll * */
+/* * - fixed inclusion parameters once again to make those * */
+/* * external libs work together * */
+/* * - re-fixed fixed inclusion parameters * */
+/* * (these freeking libraries make me mad) * */
+/* * 0.9.3 - 10/11/2000 - G.Juyn * */
+/* * - added support for nEED * */
+/* * 0.9.3 - 10/17/2000 - G.Juyn * */
+/* * - added callback to process non-critical unknown chunks * */
+/* * * */
+/* * 0.9.4 - 11/20/2000 - R.Giles * */
+/* * - fixed inclusion of lcms header for non-windows platforms * */
+/* * 0.9.4 - 12/12/2000 - G.Juyn * */
+/* * - changed callback convention for MSVC (Thanks Chad) * */
+/* * 0.9.4 - 12/16/2000 - G.Juyn * */
+/* * - fixed mixup of data- & function-pointers (thanks Dimitri)* */
+/* * * */
+/* * 1.0.1 - 02/08/2001 - G.Juyn * */
+/* * - added MEND processing callback * */
+/* * * */
+/* * 1.0.2 - 06/23/2001 - G.Juyn * */
+/* * - added processterm callback * */
+/* * * */
+/* * 1.0.3 - 08/06/2001 - G.Juyn * */
+/* * - changed inclusion of lcms.h for Linux platforms * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.6 - 04/11/2003 - G.Juyn * */
+/* * - B719420 - fixed several MNG_APP_CMS problems * */
+/* * 1.0.6 - 06/15/2003 - R.Giles * */
+/* * - lcms.h inclusion is generally no longer prefixed * */
+/* * 1.0.6 - 07/07/2003 - G. R-P. * */
+/* * - added png_imgtypes enumeration * */
+/* * * */
+/* * 1.0.7 - 03/10/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * * */
+/* * 1.0.8 - 04/11/2004 - G.Juyn * */
+/* * - added data-push mechanisms for specialized decoders * */
+/* * 1.0.8 - 08/01/2004 - G.Juyn * */
+/* * - added support for 3+byte pixelsize for JPEG's * */
+/* * * */
+/* * 1.0.9 - 12/05/2004 - G.Juyn * */
+/* * - inclusion of zlib/lcms/ijgsrc6b with <> instead of "" * */
+/* * 1.0.9 - 12/06/2004 - G.Juyn * */
+/* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
+/* * * */
+/* * 1.0.10 - 04/08/2007 - G.Juyn * */
+/* * - added support for mPNG proposal * */
+/* * 1.0.10 - 04/12/2007 - G.Juyn * */
+/* * - added support for ANG proposal * */
+/* * * */
+/* ************************************************************************** */
+
+#ifndef _libmng_types_h_
+#define _libmng_types_h_
+
+/* ************************************************************************** */
+
+#ifdef __BORLANDC__
+#pragma option -AT /* turn off strict ANSI-C for the moment */
+#endif
+
+#ifndef WIN32
+#if defined(_WIN32) || defined(__WIN32__) || defined(_Windows) || defined(_WINDOWS)
+#define WIN32 /* gather them into a single define */
+#endif
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Here's where the external & standard libs are embedded * */
+/* * * */
+/* * (it can be a bit of a pain in the lower-back to get them to work * */
+/* * together) * */
+/* * * */
+/* ************************************************************************** */
+
+#ifdef WIN32 /* only include needed stuff */
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#endif
+
+#ifdef MNG_USE_DLL
+#ifdef MNG_SKIP_ZLIB
+#undef MNG_INCLUDE_ZLIB
+#endif
+#ifdef MNG_SKIP_LCMS
+#undef MNG_INCLUDE_LCMS
+#endif
+#ifdef MNG_SKIP_IJG6B
+#undef MNG_INCLUDE_IJG6B
+#endif
+#endif
+
+#ifdef MNG_INCLUDE_ZLIB /* zlib by Mark Adler & Jean-loup Gailly */
+#include <zlib.h>
+#endif
+
+#ifdef MNG_INCLUDE_LCMS /* little cms by Marti Maria Saguer */
+#ifndef ZLIB_DLL
+#undef FAR
+#endif
+#include <lcms.h>
+#endif /* MNG_INCLUDE_LCMS */
+
+#ifdef MNG_INCLUDE_IJG6B /* IJG's jpgsrc6b */
+#include <stdio.h>
+#ifdef MNG_USE_SETJMP
+#include <setjmp.h> /* needed for error-recovery (blergh) */
+#else
+#ifdef WIN32
+#define USE_WINDOWS_MESSAGEBOX /* display a messagebox under Windoze */
+#endif
+#endif /* MNG_USE_SETJMP */
+#ifdef FAR
+#undef FAR /* possibly defined by zlib or lcms */
+#endif
+#define JPEG_INTERNAL_OPTIONS /* for RGB_PIXELSIZE */
+#include "../LibJPEG/jpeglib.h" /* all that for JPEG support :-) */
+#endif /* MNG_INCLUDE_IJG6B */
+
+#if defined(MNG_INTERNAL_MEMMNGMT) || defined(MNG_INCLUDE_FILTERS)
+#include <stdlib.h> /* "calloc" & "free" & "abs" */
+#endif
+
+#include <limits.h> /* get proper integer widths */
+
+#ifdef WIN32
+#if defined __BORLANDC__
+#include <mem.h> /* defines "memcpy" for BCB */
+#else
+#include <memory.h> /* defines "memcpy" for other win32 platforms */
+#endif
+#include <string.h> /* "strncmp" + "strcmp" */
+#else /* WIN32 */
+#ifdef BSD
+#include <strings.h> /* defines "memcpy", etc for BSD (?) */
+#else
+#include <string.h> /* defines "memcpy", etc for all others (???) */
+#endif
+#endif /* WIN32 */
+
+#if defined(MNG_FULL_CMS) || defined(MNG_GAMMA_ONLY) || defined(MNG_APP_CMS)
+#include <math.h> /* fp gamma-calculation */
+#endif
+
+/* ************************************************************************** */
+/* * * */
+/* * Platform-dependant stuff * */
+/* * * */
+/* ************************************************************************** */
+
+/* TODO: this may require some elaboration for other platforms;
+ only works with BCB for now */
+
+#ifndef MNG_DLL
+#if defined(MNG_BUILD_DLL) || defined(MNG_USE_DLL)
+#define MNG_DLL
+#endif
+#endif
+
+#define MNG_LOCAL static
+
+#if defined(MNG_DLL) && defined(WIN32) /* setup DLL calling conventions */
+#define MNG_DECL __stdcall
+#if defined(MNG_BUILD_DLL)
+#define MNG_EXT __declspec(dllexport)
+#elif defined(MNG_USE_DLL)
+#define MNG_EXT __declspec(dllimport)
+#else
+#define MNG_EXT
+#endif
+#ifdef MNG_STRICT_ANSI
+#undef MNG_STRICT_ANSI /* can't do strict-ANSI with this DLL-stuff */
+#endif
+#else
+#define MNG_DECL /* dummies for non-DLL */
+#define MNG_EXT
+#endif /* MNG_DLL && WIN32 */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* now force ANSI-C from here on */
+#endif
+
+/* ************************************************************************** */
+
+#if USHRT_MAX == 0xffffffffU /* get the proper 32-bit width !!! */
+typedef unsigned short mng_uint32;
+typedef signed short mng_int32;
+#elif UINT_MAX == 0xffffffffU
+typedef unsigned int mng_uint32;
+typedef signed int mng_int32;
+#elif ULONG_MAX == 0xffffffffU
+typedef unsigned long mng_uint32;
+typedef signed long mng_int32;
+#else
+#error "Sorry, I can't find any 32-bit integers on this platform."
+#endif
+
+typedef signed short mng_int16; /* other basic integers */
+typedef unsigned short mng_uint16;
+typedef signed char mng_int8;
+typedef unsigned char mng_uint8;
+
+typedef double mng_float; /* basic float */
+
+typedef size_t mng_size_t; /* size field for memory allocation */
+
+typedef char * mng_pchar; /* string */
+typedef void * mng_ptr; /* generic pointer */
+typedef void (*mng_fptr) (void); /* generic function pointer */
+
+/* ************************************************************************** */
+/* * * */
+/* * Platform-independant from here * */
+/* * * */
+/* ************************************************************************** */
+
+typedef mng_uint32 * mng_uint32p; /* pointer to unsigned longs */
+typedef mng_int32 * mng_int32p; /* pointer to longs */
+typedef mng_uint16 * mng_uint16p; /* pointer to unsigned words */
+typedef mng_uint8 * mng_uint8p; /* pointer to unsigned bytes */
+
+typedef mng_int8 mng_bool; /* booleans */
+
+struct mng_data_struct;
+typedef struct mng_data_struct * mng_handle; /* generic handle */
+
+typedef mng_int32 mng_retcode; /* generic return code */
+typedef mng_int32 mng_chunkid; /* 4-byte chunkname identifier */
+typedef mng_ptr mng_chunkp; /* pointer to a chunk-structure */
+typedef mng_ptr mng_objectp; /* pointer to an object-structure */
+
+typedef mng_chunkid * mng_chunkidp; /* pointer to chunkid */
+
+typedef struct { /* 8-bit palette element */
+ mng_uint8 iRed;
+ mng_uint8 iGreen;
+ mng_uint8 iBlue;
+ } mng_palette8e;
+typedef mng_palette8e mng_palette8[256]; /* 8-bit palette */
+typedef mng_palette8e * mng_palette8ep;
+
+typedef mng_uint8 mng_uint8arr[256]; /* generic arrays */
+typedef mng_uint8 mng_uint8arr4[4];
+typedef mng_uint16 mng_uint16arr[256];
+typedef mng_uint32 mng_uint32arr2[2];
+
+/* ************************************************************************** */
+
+#define MNG_FALSE 0
+#define MNG_TRUE 1
+#define MNG_NULL 0
+
+#define MNG_SUSPENDBUFFERSIZE 32768
+#define MNG_SUSPENDREQUESTSIZE 1024
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+
+/* size of temporary zlib buffer for deflate processing */
+#define MNG_ZLIB_MAXBUF 8192
+
+/* default zlib compression parameters for deflateinit2 */
+#define MNG_ZLIB_LEVEL 9 /* level */
+#define MNG_ZLIB_METHOD Z_DEFLATED /* method */
+#define MNG_ZLIB_WINDOWBITS 15 /* window size */
+#define MNG_ZLIB_MEMLEVEL 9 /* memory level */
+#define MNG_ZLIB_STRATEGY Z_DEFAULT_STRATEGY /* strategy */
+
+#define MNG_MAX_IDAT_SIZE 4096 /* maximum size of IDAT data */
+
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_JNG
+
+#ifdef MNG_INCLUDE_IJG6B /* IJG helper defs */
+typedef struct jpeg_compress_struct mngjpeg_comp;
+typedef struct jpeg_decompress_struct mngjpeg_decomp;
+typedef struct jpeg_error_mgr mngjpeg_error;
+typedef struct jpeg_source_mgr mngjpeg_source;
+
+typedef mngjpeg_comp * mngjpeg_compp;
+typedef mngjpeg_decomp * mngjpeg_decompp;
+typedef mngjpeg_error * mngjpeg_errorp;
+typedef mngjpeg_source * mngjpeg_sourcep;
+
+typedef J_DCT_METHOD mngjpeg_dctmethod;
+
+/* default IJG parameters for compression */
+#define MNG_JPEG_DCT JDCT_DEFAULT /* DCT algorithm (JDCT_ISLOW) */
+#define MNG_JPEG_QUALITY 100 /* quality 0..100; 100=best */
+#define MNG_JPEG_SMOOTHING 0 /* default no smoothing */
+#define MNG_JPEG_PROGRESSIVE MNG_FALSE /* default is just baseline */
+#define MNG_JPEG_OPTIMIZED MNG_FALSE /* default is not optimized */
+#endif /* MNG_INCLUDE_IJG6B */
+
+#define MNG_JPEG_MAXBUF 65500 /* max size of temp JPEG buffer */
+#define MNG_MAX_JDAT_SIZE 4096 /* maximum size of JDAT data */
+
+#endif /* MNG_INCLUDE_JNG */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_LCMS
+typedef cmsHPROFILE mng_cmsprof; /* little CMS helper defs */
+typedef cmsHTRANSFORM mng_cmstrans;
+typedef cmsCIExyY mng_CIExyY;
+typedef cmsCIExyYTRIPLE mng_CIExyYTRIPLE;
+typedef LPGAMMATABLE mng_gammatabp;
+#endif /* MNG_INCLUDE_LCMS */
+
+/* ************************************************************************** */
+
+ /* enumeration of known graphics types */
+enum mng_imgtypes {mng_it_unknown, mng_it_png, mng_it_mng, mng_it_jng
+#ifdef MNG_INCLUDE_MPNG_PROPOSAL
+ ,mng_it_mpng
+#endif
+#ifdef MNG_INCLUDE_ANG_PROPOSAL
+ ,mng_it_ang
+#endif
+ };
+typedef enum mng_imgtypes mng_imgtype;
+
+ /* enumeration of animation speed-types */
+enum mng_speedtypes {mng_st_normal, mng_st_fast, mng_st_slow, mng_st_slowest};
+typedef enum mng_speedtypes mng_speedtype;
+
+#ifdef MNG_OPTIMIZE_CHUNKREADER
+ /* enumeration object-creation indicators */
+enum mng_createobjtypes {mng_create_none, mng_create_always, mng_create_ifglobal};
+typedef enum mng_createobjtypes mng_createobjtype;
+#endif
+
+/* ************************************************************************** */
+
+/* enumeration of PNG image types */
+#ifdef MNG_OPTIMIZE_FOOTPRINT_INIT
+enum png_imgtypes
+ {
+ png_g1,
+ png_g2,
+ png_g4,
+ png_g8,
+ png_rgb8,
+ png_idx1,
+ png_idx2,
+ png_idx4,
+ png_idx8,
+ png_ga8,
+ png_rgba8,
+#ifdef MNG_INCLUDE_JNG
+ png_jpeg_a1,
+ png_jpeg_a2,
+ png_jpeg_a4,
+ png_jpeg_a8,
+#endif
+#ifndef MNG_NO_16BIT_SUPPORT
+ png_g16,
+ png_ga16,
+ png_rgb16,
+ png_rgba16,
+#ifdef MNG_INCLUDE_JNG
+ png_jpeg_a16,
+#endif
+#endif
+ png_none
+ };
+
+typedef enum png_imgtypes png_imgtype;
+#endif
+/* ************************************************************************** */
+
+ /* memory management callbacks */
+typedef mng_ptr (MNG_DECL *mng_memalloc) (mng_size_t iLen);
+typedef void (MNG_DECL *mng_memfree) (mng_ptr iPtr,
+ mng_size_t iLen);
+
+typedef void (MNG_DECL *mng_releasedata) (mng_ptr pUserdata,
+ mng_ptr pData,
+ mng_size_t iLength);
+
+ /* I/O management callbacks */
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+typedef mng_bool (MNG_DECL *mng_openstream) (mng_handle hHandle);
+typedef mng_bool (MNG_DECL *mng_closestream) (mng_handle hHandle);
+#endif
+typedef mng_bool (MNG_DECL *mng_readdata) (mng_handle hHandle,
+ mng_ptr pBuf,
+ mng_uint32 iBuflen,
+ mng_uint32p pRead);
+typedef mng_bool (MNG_DECL *mng_writedata) (mng_handle hHandle,
+ mng_ptr pBuf,
+ mng_uint32 iBuflen,
+ mng_uint32p pWritten);
+
+ /* error & trace processing callbacks */
+typedef mng_bool (MNG_DECL *mng_errorproc) (mng_handle hHandle,
+ mng_int32 iErrorcode,
+ mng_int8 iSeverity,
+ mng_chunkid iChunkname,
+ mng_uint32 iChunkseq,
+ mng_int32 iExtra1,
+ mng_int32 iExtra2,
+ mng_pchar zErrortext);
+typedef mng_bool (MNG_DECL *mng_traceproc) (mng_handle hHandle,
+ mng_int32 iFuncnr,
+ mng_int32 iFuncseq,
+ mng_pchar zFuncname);
+
+ /* read processing callbacks */
+typedef mng_bool (MNG_DECL *mng_processheader) (mng_handle hHandle,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight);
+typedef mng_bool (MNG_DECL *mng_processtext) (mng_handle hHandle,
+ mng_uint8 iType,
+ mng_pchar zKeyword,
+ mng_pchar zText,
+ mng_pchar zLanguage,
+ mng_pchar zTranslation);
+typedef mng_bool (MNG_DECL *mng_processsave) (mng_handle hHandle);
+typedef mng_bool (MNG_DECL *mng_processseek) (mng_handle hHandle,
+ mng_pchar zName);
+typedef mng_bool (MNG_DECL *mng_processneed) (mng_handle hHandle,
+ mng_pchar zKeyword);
+typedef mng_bool (MNG_DECL *mng_processmend) (mng_handle hHandle,
+ mng_uint32 iIterationsdone,
+ mng_uint32 iIterationsleft);
+typedef mng_bool (MNG_DECL *mng_processunknown) (mng_handle hHandle,
+ mng_chunkid iChunkid,
+ mng_uint32 iRawlen,
+ mng_ptr pRawdata);
+typedef mng_bool (MNG_DECL *mng_processterm) (mng_handle hHandle,
+ mng_uint8 iTermaction,
+ mng_uint8 iIteraction,
+ mng_uint32 iDelay,
+ mng_uint32 iItermax);
+
+ /* display processing callbacks */
+typedef mng_ptr (MNG_DECL *mng_getcanvasline) (mng_handle hHandle,
+ mng_uint32 iLinenr);
+typedef mng_ptr (MNG_DECL *mng_getbkgdline) (mng_handle hHandle,
+ mng_uint32 iLinenr);
+typedef mng_ptr (MNG_DECL *mng_getalphaline) (mng_handle hHandle,
+ mng_uint32 iLinenr);
+typedef mng_bool (MNG_DECL *mng_refresh) (mng_handle hHandle,
+ mng_uint32 iX,
+ mng_uint32 iY,
+ mng_uint32 iWidth,
+ mng_uint32 iHeight);
+
+ /* timer management callbacks */
+typedef mng_uint32 (MNG_DECL *mng_gettickcount) (mng_handle hHandle);
+typedef mng_bool (MNG_DECL *mng_settimer) (mng_handle hHandle,
+ mng_uint32 iMsecs);
+
+ /* color management callbacks */
+typedef mng_bool (MNG_DECL *mng_processgamma) (mng_handle hHandle,
+ mng_uint32 iGamma);
+typedef mng_bool (MNG_DECL *mng_processchroma) (mng_handle hHandle,
+ mng_uint32 iWhitepointx,
+ mng_uint32 iWhitepointy,
+ mng_uint32 iRedx,
+ mng_uint32 iRedy,
+ mng_uint32 iGreenx,
+ mng_uint32 iGreeny,
+ mng_uint32 iBluex,
+ mng_uint32 iBluey);
+typedef mng_bool (MNG_DECL *mng_processsrgb) (mng_handle hHandle,
+ mng_uint8 iRenderingintent);
+typedef mng_bool (MNG_DECL *mng_processiccp) (mng_handle hHandle,
+ mng_uint32 iProfilesize,
+ mng_ptr pProfile);
+typedef mng_bool (MNG_DECL *mng_processarow) (mng_handle hHandle,
+ mng_uint32 iRowsamples,
+ mng_bool bIsRGBA16,
+ mng_ptr pRow);
+
+ /* chunk access callback(s) */
+typedef mng_bool (MNG_DECL *mng_iteratechunk) (mng_handle hHandle,
+ mng_handle hChunk,
+ mng_chunkid iChunkid,
+ mng_uint32 iChunkseq);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_types_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_write.c b/Source/LibMNG/libmng_write.c
new file mode 100644
index 0000000..79ff544
--- /dev/null
+++ b/Source/LibMNG/libmng_write.c
@@ -0,0 +1,198 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_write.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : Write management (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the write management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * 0.5.1 - 05/16/2000 - G.Juyn * */
+/* * - moved the actual write_graphic functionality from * */
+/* * mng_hlapi to its appropriate function here * */
+/* * * */
+/* * 0.9.1 - 07/19/2000 - G.Juyn * */
+/* * - fixed writing of signature * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.8 - 07/06/2004 - G.R-P * */
+/* * - added conditionals around openstream/closestream * */
+/* * - defend against using undefined Open/Closestream function * */
+/* * 1.0.8 - 08/02/2004 - G.Juyn * */
+/* * - added conditional to allow easier writing of large MNG's * */
+/* * * */
+/* * 1.0.9 - 09/25/2004 - G.Juyn * */
+/* * - replaced MNG_TWEAK_LARGE_FILES with permanent solution * */
+/* * 1.0.9 - 12/20/2004 - G.Juyn * */
+/* * - cleaned up macro-invocations (thanks to D. Airlie) * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_chunks.h"
+#include "libmng_chunk_io.h"
+#include "libmng_write.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#if defined(MNG_SUPPORT_READ) || defined(MNG_SUPPORT_WRITE)
+mng_retcode mng_drop_chunks (mng_datap pData)
+{
+ mng_chunkp pChunk;
+ mng_chunkp pNext;
+ mng_cleanupchunk fCleanup;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_CHUNKS, MNG_LC_START);
+#endif
+
+ pChunk = pData->pFirstchunk; /* and get first stored chunk (if any) */
+
+ while (pChunk) /* more chunks to discard ? */
+ {
+ pNext = ((mng_chunk_headerp)pChunk)->pNext;
+ /* call appropriate cleanup */
+ fCleanup = ((mng_chunk_headerp)pChunk)->fCleanup;
+ fCleanup (pData, pChunk);
+
+ pChunk = pNext; /* neeeext */
+ }
+
+ pData->pFirstchunk = MNG_NULL;
+ pData->pLastchunk = MNG_NULL;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_DROP_CHUNKS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_READ || MNG_SUPPORT_WRITE */
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_WRITE_PROCS
+
+/* ************************************************************************** */
+
+mng_retcode mng_write_graphic (mng_datap pData)
+{
+ mng_chunkp pChunk;
+ mng_retcode iRetcode;
+ mng_uint32 iWritten;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_GRAPHIC, MNG_LC_START);
+#endif
+
+ pChunk = pData->pFirstchunk; /* we'll start with the first, thank you */
+
+ if (pChunk) /* is there anything to write ? */
+ { /* open the file */
+ if (!pData->bWriting)
+ {
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ if (pData->fOpenstream && !pData->fOpenstream ((mng_handle)pData))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+#endif
+ {
+ pData->bWriting = MNG_TRUE; /* indicate writing */
+ pData->iWritebufsize = 32768; /* get a temporary write buffer */
+ /* reserve 12 bytes for length, chunkname & crc */
+ MNG_ALLOC (pData, pData->pWritebuf, pData->iWritebufsize+12);
+
+ /* write the signature */
+ if (((mng_chunk_headerp)pChunk)->iChunkname == MNG_UINT_IHDR)
+ mng_put_uint32 (pData->pWritebuf, PNG_SIG);
+ else
+ if (((mng_chunk_headerp)pChunk)->iChunkname == MNG_UINT_JHDR)
+ mng_put_uint32 (pData->pWritebuf, JNG_SIG);
+ else
+ mng_put_uint32 (pData->pWritebuf, MNG_SIG);
+
+ mng_put_uint32 (pData->pWritebuf+4, POST_SIG);
+
+ if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, 8, &iWritten))
+ {
+ MNG_FREE (pData, pData->pWritebuf, pData->iWritebufsize+12);
+ MNG_ERROR (pData, MNG_APPIOERROR);
+ }
+
+ if (iWritten != 8) /* disk full ? */
+ {
+ MNG_FREE (pData, pData->pWritebuf, pData->iWritebufsize+12);
+ MNG_ERROR (pData, MNG_OUTPUTERROR);
+ }
+ }
+ }
+
+ while (pChunk) /* so long as there's something to write */
+ { /* let's call its output routine */
+ iRetcode = ((mng_chunk_headerp)pChunk)->fWrite (pData, pChunk);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ /* neeeext */
+ pChunk = ((mng_chunk_headerp)pChunk)->pNext;
+ }
+
+ if (!pData->bCreating)
+ { /* free the temporary buffer */
+ MNG_FREE (pData, pData->pWritebuf, pData->iWritebufsize+12);
+
+ pData->bWriting = MNG_FALSE; /* done writing */
+ /* close the stream now */
+#ifndef MNG_NO_OPEN_CLOSE_STREAM
+ if (pData->fClosestream && !pData->fClosestream ((mng_handle)pData))
+ MNG_ERROR (pData, MNG_APPIOERROR);
+#endif
+
+ } else {
+ /* cleanup the written chunks */
+ iRetcode = mng_drop_chunks (pData);
+ if (iRetcode) /* on error bail out */
+ return iRetcode;
+ }
+ }
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_WRITE_GRAPHIC, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_WRITE_PROCS */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
+
diff --git a/Source/LibMNG/libmng_write.h b/Source/LibMNG/libmng_write.h
new file mode 100644
index 0000000..df058fb
--- /dev/null
+++ b/Source/LibMNG/libmng_write.h
@@ -0,0 +1,49 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_write.h copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : Write management (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the write management routines * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * * */
+/* * 1.0.9 - 09/25/2004 - G.Juyn * */
+/* * - replaced MNG_TWEAK_LARGE_FILES with permanent solution * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_write_h_
+#define _libmng_write_h_
+
+/* ************************************************************************** */
+
+mng_retcode mng_drop_chunks (mng_datap pData);
+
+mng_retcode mng_write_graphic (mng_datap pData);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_write_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibMNG/libmng_zlib.c b/Source/LibMNG/libmng_zlib.c
new file mode 100644
index 0000000..7d102e1
--- /dev/null
+++ b/Source/LibMNG/libmng_zlib.c
@@ -0,0 +1,607 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_zlib.c copyright (c) 2000-2004 G.Juyn * */
+/* * version : 1.0.9 * */
+/* * * */
+/* * purpose : ZLIB library interface (implementation) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : implementation of the ZLIB library interface * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * 0.5.1 - 05/11/2000 - G.Juyn * */
+/* * - filled the deflatedata routine * */
+/* * 0.5.1 - 05/12/2000 - G.Juyn * */
+/* * - changed trace to macro for callback error-reporting * */
+/* * * */
+/* * 0.5.2 - 05/20/2000 - G.Juyn * */
+/* * - fixed for JNG alpha handling * */
+/* * 0.5.2 - 05/24/2000 - G.Juyn * */
+/* * - moved init of default zlib parms from here to * */
+/* * "mng_hlapi.c" * */
+/* * * */
+/* * 0.5.3 - 06/16/2000 - G.Juyn * */
+/* * - changed progressive-display processing * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* * 0.9.3 - 08/08/2000 - G.Juyn * */
+/* * - fixed compiler-warnings from Mozilla * */
+/* * 0.9.3 - 09/07/2000 - G.Juyn * */
+/* * - added support for new filter_types * */
+/* * * */
+/* * 1.0.5 - 08/07/2002 - G.Juyn * */
+/* * - added test-option for PNG filter method 193 (=no filter) * */
+/* * 1.0.5 - 08/19/2002 - G.Juyn * */
+/* * - B597134 - libmng pollutes the linker namespace * */
+/* * 1.0.5 - 09/19/2002 - G.Juyn * */
+/* * - added warning for too much IDAT data * */
+/* * * */
+/* * 1.0.6 - 07/07/2003 - G.R-P * */
+/* * - added MNG_NO_16BIT_SUPPORT support * */
+/* * * */
+/* * 1.0.9 - 10/09/2004 - G.R-P * */
+/* * - added MNG_NO_1_2_4BIT_SUPPORT support * */
+/* * * */
+/* ************************************************************************** */
+
+#include "libmng.h"
+#include "libmng_data.h"
+#include "libmng_error.h"
+#include "libmng_trace.h"
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+#include "libmng_memory.h"
+#include "libmng_pixels.h"
+#include "libmng_filter.h"
+#include "libmng_zlib.h"
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+/* ************************************************************************** */
+
+#ifdef MNG_INCLUDE_ZLIB
+
+/* ************************************************************************** */
+
+voidpf mngzlib_alloc (voidpf pData,
+ uInt iCount,
+ uInt iSize)
+{
+ voidpf pPtr; /* temporary space */
+
+#ifdef MNG_INTERNAL_MEMMNGMT
+ pPtr = calloc (iCount, iSize); /* local allocation */
+#else
+ if (((mng_datap)pData)->fMemalloc) /* callback function set ? */
+ pPtr = ((mng_datap)pData)->fMemalloc (iCount * iSize);
+ else
+ pPtr = Z_NULL; /* can't allocate! */
+#endif
+
+ return pPtr; /* return the result */
+}
+
+/* ************************************************************************** */
+
+void mngzlib_free (voidpf pData,
+ voidpf pAddress)
+{
+#ifdef MNG_INTERNAL_MEMMNGMT
+ free (pAddress); /* free locally */
+#else
+ if (((mng_datap)pData)->fMemfree) /* callback set? */
+ ((mng_datap)pData)->fMemfree (pAddress, 1);
+#endif
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_initialize (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INITIALIZE, MNG_LC_START);
+#endif
+
+#ifdef MNG_INTERNAL_MEMMNGMT
+ pData->sZlib.zalloc = Z_NULL; /* let zlib figure out memory management */
+ pData->sZlib.zfree = Z_NULL;
+ pData->sZlib.opaque = Z_NULL;
+#else /* use user-provided callbacks */
+ pData->sZlib.zalloc = mngzlib_alloc;
+ pData->sZlib.zfree = mngzlib_free;
+ pData->sZlib.opaque = (voidpf)pData;
+#endif
+
+ pData->bInflating = MNG_FALSE; /* not performing any action yet */
+ pData->bDeflating = MNG_FALSE;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INITIALIZE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_cleanup (mng_datap pData)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_CLEANUP, MNG_LC_START);
+#endif
+
+ if (pData->bInflating) /* force zlib cleanup */
+ mngzlib_inflatefree (pData);
+ if (pData->bDeflating)
+ mngzlib_deflatefree (pData);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_CLEANUP, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_inflateinit (mng_datap pData)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEINIT, MNG_LC_START);
+#endif
+ /* initialize zlib structures and such */
+ iZrslt = inflateInit (&pData->sZlib);
+
+ if (iZrslt != Z_OK) /* on error bail out */
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+ pData->bInflating = MNG_TRUE; /* really inflating something now */
+ pData->sZlib.next_out = 0; /* force JIT initialization */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEINIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#ifdef MNG_SUPPORT_DISPLAY
+mng_retcode mngzlib_inflaterows (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata)
+{
+ int iZrslt;
+ mng_retcode iRslt;
+ mng_ptr pSwap;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEROWS, MNG_LC_START);
+#endif
+
+ pData->sZlib.next_in = pIndata; /* let zlib know where to get stuff */
+ pData->sZlib.avail_in = (uInt)iInlen;
+
+ if (pData->sZlib.next_out == 0) /* initialize output variables ? */
+ { /* let zlib know where to store stuff */
+ pData->sZlib.next_out = pData->pWorkrow;
+ pData->sZlib.avail_out = (uInt)(pData->iRowsize + pData->iPixelofs);
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iPNGdepth < 8)
+ pData->sZlib.avail_out = (uInt)((pData->iPNGdepth*pData->iRowsize + 7)/8
+ + pData->iPixelofs);
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iPNGdepth > 8)
+ pData->sZlib.avail_out = (uInt)(2*pData->iRowsize + pData->iPixelofs);
+#endif
+ }
+
+ do
+ { /* now inflate a row */
+ iZrslt = inflate (&pData->sZlib, Z_SYNC_FLUSH);
+ /* produced a full row ? */
+ if (((iZrslt == Z_OK) || (iZrslt == Z_STREAM_END)) &&
+ (pData->sZlib.avail_out == 0))
+ { /* image not completed yet ? */
+ if (pData->iRow < (mng_int32)pData->iDataheight)
+ {
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iPNGdepth == 1)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (pData->iRowsize+7)/8;
+
+ for (iX = ((pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>7)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>6)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>5)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>4)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>3)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>2)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>1)&1);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&1);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ else if (pData->iPNGdepth == 2)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (2*pData->iRowsize+7)/8;
+
+ for (iX = ((2*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (2*pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>6)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>4)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc)>>2)&3);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&3);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ else if (pData->iPNGdepth == 4)
+ {
+ /* Inflate Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc + pData->iRowsize - (4*pData->iRowsize+7)/8;
+
+ for (iX = ((4*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
+ *pDest++ = *pSrc++;
+
+ pDest = pData->pWorkrow+1;
+ pSrc = pDest + pData->iRowsize - (4*pData->iRowsize+7)/8;
+ for (iX = pData->iRowsize; ;)
+ {
+ *pDest++ = (((*pSrc)>>4)&0x0f);
+ if (iX-- <= 0)
+ break;
+ *pDest++ = (((*pSrc) )&0x0f);
+ if (iX-- <= 0)
+ break;
+ pSrc++;
+ }
+ }
+ if (pData->iPNGdepth < 8 && pData->iColortype == 0)
+ {
+ /* Expand samples to 8-bit by LBR */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1};
+
+ for (iX = pData->iRowsize; iX > 0; iX--)
+ *pSrc++ *= multiplier[pData->iPNGdepth];
+ }
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iPNGdepth > 8)
+ {
+ /* Reduce Workrow to 8-bit */
+ mng_int32 iX;
+ mng_uint8p pSrc = pData->pWorkrow+1;
+ mng_uint8p pDest = pSrc;
+
+ for (iX = pData->iRowsize; iX > 0; iX--)
+ {
+ *pDest = *pSrc;
+ pDest++;
+ pSrc+=2;
+ }
+ }
+#endif
+
+#ifdef FILTER192 /* has leveling info ? */
+ if (pData->iFilterofs == MNG_FILTER_DIFFERING)
+ iRslt = init_rowdiffering (pData);
+ else
+#endif
+ iRslt = MNG_NOERROR;
+ /* filter the row if necessary */
+ if ((!iRslt) && (pData->iFilterofs < pData->iPixelofs ) &&
+ (*(pData->pWorkrow + pData->iFilterofs)) )
+ iRslt = mng_filter_a_row (pData);
+ else
+ iRslt = MNG_NOERROR;
+ /* additional leveling/differing ? */
+ if ((!iRslt) && (pData->fDifferrow))
+ {
+ iRslt = ((mng_differrow)pData->fDifferrow) (pData);
+
+ pSwap = pData->pWorkrow;
+ pData->pWorkrow = pData->pPrevrow;
+ pData->pPrevrow = pSwap; /* make sure we're processing the right data */
+ }
+
+ if (!iRslt)
+ {
+#ifdef MNG_INCLUDE_JNG
+ if (pData->bHasJHDR) /* is JNG alpha-channel ? */
+ { /* just store in object ? */
+ if ((!iRslt) && (pData->fStorerow))
+ iRslt = ((mng_storerow)pData->fStorerow) (pData);
+ }
+ else
+#endif /* MNG_INCLUDE_JNG */
+ { /* process this row */
+ if ((!iRslt) && (pData->fProcessrow))
+ iRslt = ((mng_processrow)pData->fProcessrow) (pData);
+ /* store in object ? */
+ if ((!iRslt) && (pData->fStorerow))
+ iRslt = ((mng_storerow)pData->fStorerow) (pData);
+ /* color correction ? */
+ if ((!iRslt) && (pData->fCorrectrow))
+ iRslt = ((mng_correctrow)pData->fCorrectrow) (pData);
+ /* slap onto canvas ? */
+ if ((!iRslt) && (pData->fDisplayrow))
+ {
+ iRslt = ((mng_displayrow)pData->fDisplayrow) (pData);
+
+ if (!iRslt) /* check progressive display refresh */
+ iRslt = mng_display_progressive_check (pData);
+
+ }
+ }
+ }
+
+ if (iRslt) /* on error bail out */
+ MNG_ERROR (pData, iRslt);
+
+ if (!pData->fDifferrow) /* swap row-pointers */
+ {
+ pSwap = pData->pWorkrow;
+ pData->pWorkrow = pData->pPrevrow;
+ pData->pPrevrow = pSwap; /* so prev points to the processed row! */
+ }
+
+ iRslt = mng_next_row (pData); /* adjust variables for next row */
+
+ if (iRslt) /* on error bail out */
+ MNG_ERROR (pData, iRslt);
+ }
+ /* let zlib know where to store next output */
+ pData->sZlib.next_out = pData->pWorkrow;
+ pData->sZlib.avail_out = (uInt)(pData->iRowsize + pData->iPixelofs);
+#ifdef MNG_NO_1_2_4BIT_SUPPORT
+ if (pData->iPNGdepth < 8)
+ pData->sZlib.avail_out = (uInt)((pData->iPNGdepth*pData->iRowsize + 7)/8
+ + pData->iPixelofs);
+#endif
+#ifdef MNG_NO_16BIT_SUPPORT
+ if (pData->iPNGdepth > 8)
+ pData->sZlib.avail_out = (uInt)(2*pData->iRowsize + pData->iPixelofs);
+#endif
+ }
+ } /* until some error or EOI
+ or all pixels received */
+ while ( (iZrslt == Z_OK) && (pData->sZlib.avail_in > 0) &&
+ ( (pData->iRow < (mng_int32)pData->iDataheight) ||
+ ( (pData->iPass >= 0) && (pData->iPass < 7) ) ) );
+ /* on error bail out */
+ if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+ /* too much data ? */
+ if ((iZrslt == Z_OK) && (pData->sZlib.avail_in > 0))
+ MNG_WARNING (pData, MNG_TOOMUCHIDAT);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEROWS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+#endif /* MNG_SUPPORT_DISPLAY */
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_inflatedata (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEDATA, MNG_LC_START);
+#endif
+ /* let zlib know where to get stuff */
+ pData->sZlib.next_in = pIndata;
+ pData->sZlib.avail_in = (uInt)iInlen;
+ /* now inflate the data in one go! */
+ iZrslt = inflate (&pData->sZlib, Z_FINISH);
+ /* not enough room in output-buffer ? */
+ if ((iZrslt == Z_BUF_ERROR) || (pData->sZlib.avail_in > 0))
+ return MNG_BUFOVERFLOW;
+ /* on error bail out */
+ if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_inflatefree (mng_datap pData)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEFREE, MNG_LC_START);
+#endif
+
+ pData->bInflating = MNG_FALSE; /* stopped it */
+
+ iZrslt = inflateEnd (&pData->sZlib); /* let zlib cleanup its own stuff */
+
+ if (iZrslt != Z_OK) /* on error bail out */
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEFREE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_deflateinit (mng_datap pData)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEINIT, MNG_LC_START);
+#endif
+ /* initialize zlib structures and such */
+ iZrslt = deflateInit2 (&pData->sZlib, pData->iZlevel, pData->iZmethod,
+ pData->iZwindowbits, pData->iZmemlevel,
+ pData->iZstrategy);
+
+ if (iZrslt != Z_OK) /* on error bail out */
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+ pData->bDeflating = MNG_TRUE; /* really deflating something now */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEINIT, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_deflaterows (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata)
+{
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEROWS, MNG_LC_START);
+#endif
+
+
+
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEROWS, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_deflatedata (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEDATA, MNG_LC_START);
+#endif
+
+ pData->sZlib.next_in = pIndata; /* let zlib know where to get stuff */
+ pData->sZlib.avail_in = (uInt)iInlen;
+ /* now deflate the data in one go! */
+ iZrslt = deflate (&pData->sZlib, Z_FINISH);
+ /* not enough room in output-buffer ? */
+ if ((iZrslt == Z_BUF_ERROR) || (pData->sZlib.avail_in > 0))
+ return MNG_BUFOVERFLOW;
+ /* on error bail out */
+ if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEDATA, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR;
+}
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_deflatefree (mng_datap pData)
+{
+ int iZrslt;
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEFREE, MNG_LC_START);
+#endif
+
+ iZrslt = deflateEnd (&pData->sZlib); /* let zlib cleanup its own stuff */
+
+ if (iZrslt != Z_OK) /* on error bail out */
+ MNG_ERRORZ (pData, (mng_uint32)iZrslt);
+
+ pData->bDeflating = MNG_FALSE; /* stopped it */
+
+#ifdef MNG_SUPPORT_TRACE
+ MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEFREE, MNG_LC_END);
+#endif
+
+ return MNG_NOERROR; /* done */
+}
+
+/* ************************************************************************** */
+
+#endif /* MNG_INCLUDE_ZLIB */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
+
diff --git a/Source/LibMNG/libmng_zlib.h b/Source/LibMNG/libmng_zlib.h
new file mode 100644
index 0000000..cfc3918
--- /dev/null
+++ b/Source/LibMNG/libmng_zlib.h
@@ -0,0 +1,60 @@
+/* ************************************************************************** */
+/* * For conditions of distribution and use, * */
+/* * see copyright notice in libmng.h * */
+/* ************************************************************************** */
+/* * * */
+/* * project : libmng * */
+/* * file : libmng_zlib.h copyright (c) 2000-2002 G.Juyn * */
+/* * version : 1.0.0 * */
+/* * * */
+/* * purpose : ZLIB package interface (definition) * */
+/* * * */
+/* * author : G.Juyn * */
+/* * * */
+/* * comment : Definition of the ZLIB package interface * */
+/* * * */
+/* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
+/* * - changed strict-ANSI stuff * */
+/* * * */
+/* * 0.9.2 - 08/05/2000 - G.Juyn * */
+/* * - changed file-prefixes * */
+/* * * */
+/* ************************************************************************** */
+
+#if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
+#pragma option -A /* force ANSI-C */
+#endif
+
+#ifndef _libmng_zlib_h_
+#define _libmng_zlib_h_
+
+/* ************************************************************************** */
+
+mng_retcode mngzlib_initialize (mng_datap pData);
+mng_retcode mngzlib_cleanup (mng_datap pData);
+
+mng_retcode mngzlib_inflateinit (mng_datap pData);
+mng_retcode mngzlib_inflaterows (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata);
+mng_retcode mngzlib_inflatedata (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata);
+mng_retcode mngzlib_inflatefree (mng_datap pData);
+
+mng_retcode mngzlib_deflateinit (mng_datap pData);
+mng_retcode mngzlib_deflaterows (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata);
+mng_retcode mngzlib_deflatedata (mng_datap pData,
+ mng_uint32 iInlen,
+ mng_uint8p pIndata);
+mng_retcode mngzlib_deflatefree (mng_datap pData);
+
+/* ************************************************************************** */
+
+#endif /* _libmng_zlib_h_ */
+
+/* ************************************************************************** */
+/* * end of file * */
+/* ************************************************************************** */
diff --git a/Source/LibOpenJPEG/ChangeLog b/Source/LibOpenJPEG/ChangeLog
new file mode 100644
index 0000000..cbb97f3
--- /dev/null
+++ b/Source/LibOpenJPEG/ChangeLog
@@ -0,0 +1,553 @@
+What's New for OpenJPEG
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+August 21, 2008
+* [antonin] found a bug in tcd.c that was preventing to find the correct threshold in tcd_rateallocate.c for high-precision images. Applied a temporary patch but a better solution should be found.
+
+August 21, 2008
+* [antonin] fixed a bug in image_to_j2k.c that was preventing the 'r' option to work properly (everything was compressed lossless regardless of the specified rate).
+
+August 8, 2008
+! [FOD] Modified the way raw images with more that 8bpp are read and written
+
+July 9, 2008
++ [Parvatha] Added the default lossless parameter to opj_set_default_encoder_parameters in openjpeg.c.
+
+June 12, 2008
+* [antonin] fixed a bug in dirent.h that prevented codec on Linux Alpha Systems to compile correctly. Thanks to RobinC.
+
+May 22, 2008
+* [antonin] fixed a bug in j2k.c (j2k_write_sod) that allowed to get negative rates, thanks zhong1985624 for pointing this.
+
+May 22, 2008
+* [antonin] additional test to avoid crash due to invalid image size, patch by Christopher Layne
+
+May 20, 2008
+* [antonin] memory leak fixed in openjpeg.c (opj_destroy_cstr_info()), patch by Carsten Juttner
+
+March 12, 2008
++ [GB] help line for the -F option in j2k_to_image
+
+March 4, 2008
+! [FOD] Changed Java files copyright in JavaOpenJPEG module
+
+February 28, 2008
+* [FOD] Fixed openjpeg.c for proper initialization of codec context structures (dinfo in opj_create_compress()
+ and opj_create_decompress(). Bug fix suggested by Andrey V. Kiselev
+* [FOD] Clean up of opj_aligned_malloc(), to just forgo the use of posix_memalign(),
+ as apparently memalign() is what is working better for everyone. Patch by Callum.
+
+February 28, 2008
+- [FOD] Removed the J2KViewer module, which has been replaced by OPJViewer
+* [FOD] Fixed the error handling of j2k_decode in jp2.c, thanks to Robin Cornelius
+
+February 11, 2008
+* [GB] Minor style modifications to comply with c99 compiler flag; removed Microsoft-specific "union-in-struct" syntax; Re-enabled cstr_info struct creation when -W switch is specified
+! [GB] Changed a number of things in opjviewer (e.g., decoding thread does not execute GUI calls anymore), to have it running under linux --> it is better than before, but still crashes
+
+February 5, 2008
+! [Parvatha] In convert.c, corrected imagetobmp() conversion for grayscale. In tcd.c, corrected Rate modification in
+ tcd_init_encode(). Thanks to Jeremy Furtek and Jérôme Fimes.
+
+January 31, 2008
+! [GB] In opjviewer, unification of JPEG 2000 family handlers (*.jp2, *.mj2, *.j2k) in a single file
+
+January 22, 2008
+! [FOD] In image.c, changed the opj_image_create0() memory allocation from malloc() to calloc() in order
+ to avoid segfaults when freeing the memory allocated for the coding of bad images.
+ Thanks to Christopher Layne for this improvement.
+
+January 17, 2008
++ [antonin] Initial commit of Xcode project directory (XCode 2.5 for macosx)
+ available targets : libopenjpeg (stat and dyn), image_to_j2k, j2k_to_image
+
+January 16, 2008
+* [antonin] fixed opj_malloc.h for macosx (bugfix provided by janpeder, thanks)
+
+January 11, 2008
++ [FOD] Added missing files to JavaOpenJPEG project (files from Patrick Piscaglia)
+
+January 4, 2008
+* [Parvatha] Patch by Callum Lerwick. Fixed bug during encoding using tile option in tcd.c
+
+----------------------
+December 21, 2007
+VERSION 1.3.0 RELEASED
+----------------------
+
+December 21, 2007
+* [FOD] Bug fixed by David Bruken. Fixed memory allocation issue in opj_malloc.h
+! [FOD] Possible errors in pi_create_encode handled
+
+December 19, 2007
+* [Antonin] changed variables names alpha, beta, gamma, delta in dwt.c to avoid re-declarations on Macosx
+! [Parvatha] In pi.c, removed the Recursive function pi_check_next_level() and modified the code.
+* [FOD] Fixed allocation problem in pi.c
+
+December 19, 2007
++ [FOD] In mqc.h, changed MQC_NUMCTXS from 32 to 19 as there are only 19 possible contexts
+
+December 10, 2007
++ [FOD] First import of JAVAOpenJPEG, a Java wrapper of OpenJPEG, developed by Patrick Piscaglia of Telemis (www.telemis.com).
+ Thank you Patrick for this new module !
+
+November 29, 2007
+! [GB] Added index.h and index.c in VC6 projects; wrapped index.h in the C++ preprocessor; modified OPJViewer project and some files.
+
+November 14, 2007
++ [FOD] Created the file index.c in the codec directory. This file handles the creation of index files,
+ at encoding and decoding.
+* [FOD] Fixed bugs during the creation of the index (PCRL progression order)
+* [FOD] Fixed the maximum number of resolutions a user can discard while decoding.
+ Added an error state in J2K_STATE (j2k.c)
+
+November 14, 2007
+! [FOD] - First Patch by Callum Lerwick. Instead of reinventing realloc, j2k_read_sod now just uses opj_realloc in j2k.c
+ - Second Patch by Callum Lerwick. This patch rearranges the largest memory allocations so they're allocated as
+ late as possible, and freed as soon as possible. This cuts memory usage by about half on two large test images.
+ - Third Patch by Callum Lerwick. The opj_tcd_cblk array is one of the largest allocations, because it
+ contains a bunch of static buffers. This also makes it a major source of cache thrashing. This patch allocates
+ the buffers from the heap, and dynamically sizes them in the decoder. I have not yet managed to dynamically size
+ them in the encoder, getting the decoder to do it was tricky enough... I also split opj_tcd_cblk_t into separate
+ encode and decode versions. A lot of fields were not used by both, so this cuts its size even further.
+
+* [FOD] Avoided ABI breakage
+
+November 13, 2007
+! [FOD] Patch by Dzonatas and Callum Lerwick.
+ Fp/vectorization patch which basically converts most of the irreversible decode codepath to floating point,
+ eliminating a few rounds of int/fp conversion, resulting in a vast performance improvement,
+ and an increase in accuracy.
+
+November 8, 2007
+! [FOD] In t1.c, small change to avoid calling twice t1_getwmsedec()
+ Patches from Callum Lewick:
+ - Basic gcc optimization flags in cmake and makefile match.
+ - Fixed some spelling errors in dwt.c.
+
+November 5, 2007
+*+ [GB] Fixed a bug which prevented JPWL from working on multi-tiled images; added some more fields in the interface info structures
+(keep a list of markers, save start packet number for each tile)
+
+October 23, 2007
+* [GB] Improved success for the linux build; OPJViewer shows all the COM contents
+
+October 18, 2007
+* [FOD] Changed the ROI parameter in the image_to_j2k codec to make it correspond to the documentation (i.e. -ROI c=0,U=25)
+* [FOD] Patch from Callum Lewick. Memset patch.
+ The main idea of the patch is that currently opj_malloc clears all allocations, which unnecessarily
+ dirties up the cache and eats bandwidth. This patch makes it no longer do so, and I've painstakingly determined which allocations actually need
+ to be cleared and changed them to use opj_calloc() instead. I previously tried to just get rid of the opj_*alloc wrappers but that
+ idea was nixed, so this time I'm trying it with macros. I also put in a gcc pragma that helps enforce their use. Which got messy. :) It caught a
+ few places they weren't used but it also revealed that the mj2 tools are not very cleanly separated from the library. It includes all the
+ internal headers, but it wasn't using the malloc wrappers. I figured the binaries should be "external" and have minimal knowledge of the
+ internals of the library. I patched them to not include opj_includes.h, and include only the internal headers they actually need. However,
+ they're using the opj_clock() function, which is in with the malloc wrappers. So I decided to move the malloc wrappers to their own header.
+ But mj2.c seems to want to be "internal", so I patched it to use the wrappers. Note that this patch changes the semantics of opj_malloc, it no longer
+ clears the memory it allocates. If you need it to be cleared, you must use opj_calloc instead, or memset it yourself. It is also somewhat
+ invasive, please test it extensively. I've been pounding on it all summer with my test suite, Second Life, and valgrind, and it checks out clean.
+
+October 12, 2007
+* [FOD] Changed the way the image structure is allocated when the decoding parameters include some resolutions to discard.
+ This should have a significant impact for the decoding of huge images when some resolutions are discarder (-r parameter)
+ Warning: The output image size is now reduced when discarding resolutions !
+
+October 10, 2007
+* [FOD] Patch from Callum Lewick. Clean up of j2klib.h for the aligned malloc stuff.
+ It makes it work right with mingw, as _mm_malloc() isn't a macro, attempts to pave the way to using cmake
+ to check for this stuff and combines a patch from Dana Fagerstrom at Sun that makes it use memalign() on Solaris
+ convert.c: Changed some error comments for TIFF images
+
+September 27, 2007
+* [FOD] Patch from Callum Lewick. Fixed dwt.c where an alignment in buffer was problematic under x86_64.
+
+September 25, 2007
+* [Mathieu Malaterre] BUG: Fix previous patch from Callum Lerwick. I have no
+ clue what CMAKE_INSTALL_LIBDIR refers too. Bump up cmake 2.2 restriction to
+ cmake 2.4 because of previous patch (not backward compatible). Properly set the SOVERSION in a cross plateform way (yes WIN32 is a platform)
+
+September 19, 2007
+* [Parvatha] Fixed issues with generation of SOP marker.
+
+September 18, 2007
+* [Parvatha] Fixed issues with Reading and Writing TIF images in convert.c to avoid segmentation fault.
+* [Parvatha] Fixed issues relating to using user specified rates for CINEMA option for multiple images.
+
+September 17, 2007
+* [FOD] Fixed issues with cstr_info when codestream has components with different number of resolutions.
+! [FOD] OpenJPEG library interface modified to retain compatibility with version 1.2
+
+September 12, 2007
+* [FOD] Patch from Callum Lerwick.
+ Fixed the library linking so it links with the soversion properly set.
+ Fixes up the install targets so that it interacts properly with RPM.
+ Install target for MJ2. Sets some necessary and useful CFLAGS if gcc is in use.
+* [FOD] Updated the MJ2 codec to be compatible with the recent changes in the OpenJPEG library
+
+September 11, 2007
+* [GB] JPWL encoding is finalized correctly into the JP2 file format; added an additional structure in opj_codestream_info, to keep a record of the written markers
+
+September 8, 2007
+* [GB] Adapted the JPWL and OPJViewer code to new interface; fixed a samll bug in JPWL which created large EPBs even when null protection was specified
+
+September 7, 2007
++ [FOD] Indexes can now be generated when decoding J2K codestreams.
+* [Mathieu Malaterre] Upon failure, properly return error code (!=0).
+* [Mathieu Malaterre] CMake: Add cmake code to do testing if user has properly setup a testimages directory
+
+September 6, 2007
++ [Mathieu Malaterre] CMake: start compiling mj2, jpwl and jp3d
++ [Mathieu Malaterre] CMake: output all executable/libs into one single directory
++ [Mathieu Malaterre] CMake: start compiling index_create
++ [Mathieu Malaterre] OpenJPEG.rc update copyright year
++ [Mathieu Malaterre] CMake: add Java j2kviewer but do not compile it using cmake since cmake has too poor support for Java. Should create a custom command running ant instead.
++ [Mathieu Malaterre] CMake: Add doxygen output
++ [GB] One more field in the codestream_info struct for recording the number of packets per tile part; JPWL now distributes the EPBs in all the tile part headers
++ [Mathieu Malaterre] CMake: Add very simple tests (simply run command line with no option)
+* [Mathieu Malaterre] Fix unitialized read in img_fol (we may need a smarter initialize than memset)
+
+September 4, 2007
++ [GB] Added some fields in the codestream_info structure: they are used to record the position of single tile parts.
+ Changed also the write_index function in the codec, to reflect the presence of this new information.
+
+September 3, 2007
++ [GB] Added the knowledge of JPSEC SEC and INSEC markers (you have to compile the JPWL project). Management of these markers is limited to skipping them without crashing:
+ no real security function at this stage. Deprecated USE_JPSEC will be removed next
+
+August 31, 2007
+* [GB] Fixed save capabilities in OPJViewer due to recent code upgrade
+
+August 30, 2007
+* [FOD] Changed the OpenJPEG library interface to enable users to access information regarding the codestream (also called codestream index).
+ This index is usefull for all applications requiring to have a scalable acces to the codestream (like JPIP applications, ...)
+ Currently, this information is only available when encoding an image.
++ [FOD] Added the information regarding the end of packet position in the index
+
+August 28, 2007
+* [FOD] Fixed wrong destructors called in openjpeg.c
+* [FOD] Fixed bug in j2k_decode_jpt_stream
+
+August 24, 2007
+* [Parvatha] The end of main header is calculated after TLM and POC marker for Dcinema.
+
+August 21, 2007
++ [FOD] Added support for Visual Studio 2005
+* [FOD] Robustified MJ2 codecs
+* [Parvatha] Solved problems with codec reading from image file directory when filename had more than one "." in name
+* [Callum Lerwick] Minor cleanup patch, that gets rid of a bunch of "old style declaration" warnings from Intel's compiler
+* [Callum Lerwick] Aligned malloc using Intel's _mm_malloc(). Cleanup on the t1 memory allocation, getting rid of some leftover debug code
+* [Callum Lerwick] Memory leaks fixed
+* [Callum Lerwick] Reworks of t1_updateflags to get rid of the shift operation
+* [Callum Lerwick] mqc_setcurctx moved to the header to allow it to be inlined into the t1.
+* [Callum Lerwick] Consolidated some calls to mqc_setcurctx.
+* [Callum Lerwick] Cleaned up t1_generate_luts to output the proper types.
+* [Callum Lerwick] Replaced the large ctxno_mag lookup table with a small bit of inline-able branchless code
+* [Callum Lerwick] Moved the orient flipping into the ctxno_zc table.
+
+August 20, 2007
++ [FOD] Added support for the TGA file format in the codec
+
+August 08, 2007
+* [Parvatha] Fixed the DCinema filesize allocation. It now includes the SOT marker size
+
+August 02, 2007
++ [GB] Added a basic saving capability to OPJViewer
+
+July 18, 2007
+! [FOD] Updated libtiff library version to 3.8.2 (for WIN32)
+* [FOD] Updated BMP and PxM truncation when decoding J2K files with more than 8 bits
+
+July 17, 2007
+* [FOD] Fixed raw option for images with more than three components
+
+July 17, 2007
++ [FOD] Added support for RAW images. This module has been developped by the University of Perugia team. Thanks to them ! [image_to_j2k.c j2k_to_image.c convert.c convert.h]
+
+July 13, 2007
+! [FOD] Modified the memory allocation for codestreams containing multiple tiles. The memory is now allocated for each tile indenpendently,
+ leading to an important decrease of the virtual memory needed. [j2k.c tcd.h tcd.c]
+! [FOD] Modified old comments about the ability to decode mega-images and comments about the disk size necessary to do this. [image_to_j2k.c and frames_to_mj2.c]
+* [FOD] Added 2000 bytes for the memory allocation in cio.c for the minimum size of headers (useful in case of very small images) [cio.c]
+
+July 12, 2007
+* [GB] fixed a bug in JPWL module, which prevented to exploit the full error correction capability of RS codes (e.g. it gave up at 5 errors,
+ even if 6 were correctable); defined a JPWL_MAXIMUM_EPB_ROOM for better customization of the maximum dimension of EPBs (the dimension
+ is pre-calculated on an hypothesis, if it goes beyond 65535 there will be problems, thus we give a little less than the max, let's say 65450)
+
+July 8, 2007
+* [ANTONIN] fixed the size of the memory allocation in cio.c (confusion between bits and bytes)
+
+June 21, 2007
+* [FOD] Output image color space set when decoding a JP2 file in jp2.c
++ [GB] Previous, home, and next frame buttons for exploring MJ2 files in OPJViewer
+
+June 18, 2007
+* [GB] Reload image doesn't crash in OPJViewer; more settings saved to registry
+
+June 16, 2007
++ [GB] Possibility to disable parsing in OPJViewer; also, saves common settings to the registry
+
+June 15, 2007
+* [FOD] Fixed the generation of index files
+
+
+----------------------
+MAY 4, 2007
+VERSION 1.2.0 RELEASED
+----------------------
+
+May 4, 2007
+* [FOD] Bugs corrected in decoding of command line (getopt.c), in the handling of 16 bit files (t1.c and tcd.c) and the calculation of elapsed time for multiple tiles parts (tcd.c and tdc.h).
+
+June 2, 2007
++ [GB] OPJViewer opens now BMP, PNG, GIF, PNM, TIFF (with wxWidgets internals); added an encoder settings tab, for future integration with "save file as..." in JPEG 2000 format
+
+May 31, 2007
+* [FOD] Fixed the handling of 16bit TIFF files for cinema compression. Modified "convert.c"
+* [FOD] Fixed the parameters used for cinema compression (9-7 transform used instead of 5-3). Modified "image_to_j2k.c"
+
+May 24, 2007
+* [FOD] Bug fixed by Sylvain Munaut. Change in the reading of the POC marker. Since COD/COC can be anywhere in the header, the decoder cannot always know while decoding the POC marker
+ the value of numlayers and numresolution.
+
+May 23, 2007
+! [FOD] Patch suggested by Callum Lerwick <seg@haxxed.com>: "This makes the t1 data arrays dynamic, which greatly reduces cache thrashing. Also, some minor cleanup to prevent unnecessary casts"
+
+May 22, 2007
+! [FOD] Patch suggested by Callum Lerwick <seg@haxxed.com>: "Some formatting cleanups,
+ so that the long function definitions and calls fit on screen. Use of prefix increment which is theoretically faster, in practice any sane compiler can optimize a postfix
+ increment but its best not to count on such things. Consolidation of some redundant calculations in the inner loops, which becomes very useful in the future autovectorize patch."
+! [FOD] Patch suggested by Callum Lerwick <seg@haxxed.com>: "This changes the flag code in t1 to use a flag_t type, which can then be changed to reduce RAM usage. It is now typedef to a short."
+! [FOD] Patch suggested by Callum Lerwick <seg@haxxed.com>: "This patch makes the t1 LUTs static. I actually intend this as a prelude to possibly eliminating some or all of the LUTs entirely."
+
+May 11, 2007
+- [FOD] JP3D library Binaries removed from SVN.
+! [FOD] MJ2 codec updated from LibOpenJPEG version 0.97 to LibOpenJPEG version 1. Hence, the MJ2 codec will now take advantage of all the improvements and optimizations done on the LibOpenJPEG library.
+! [FOD] Possibility to choose to apply MCT (multiple component transform) enabled, and new decoding_limit: DECODE_ALL_BUT_PACKETS (openjpeg.h)
+
+April 26, 2007
++ [gdcm] Add basic steps on how to use CMake for building examples (README.cmake)
+
+April 25, 2007
++ [FOD] Modification of the openjpeg.h file to avoid and ABI break with v1.1, removed the dangerous #IFDEF JPWL and added tcp_mct in cparameters.
+
+April 23, 2007
++ [GB] Enable/disable image decoding in OPJViewer
+
+April 12,2007
+* [Parvatha] Fixed Error in tiftoimage(). Modification in convert.c.
+
+April 10,2007
++ [Parvatha] Accepting "j2c" as format for Encoding and Decoding. Modification in image_to_j2k.c.
+* [Parvatha] Modified imagetotif() to read images with signed data. Modification in convert.c.
+
+April 5, 2007
+! [FOD] fix.h optimized. Thanks a lot to Dzonatas <dzonatas at dzonux.net> !
+! [FOD] dwt.c optimized. Thanks a lot to Dzonatas <dzonatas at dzonux.net> !
+! [FOD] t1.c optimized. Thanks a lot to Callum Lerwick <seg at haxxed.com> !
+
+April 4,2007
++ [Parvatha] Digital cinema compliance for 4K chosen by "-cinema4K" option. Modification in image_to_j2k.c.
++ [Parvatha] Bit rate limitation for each color component. Modification in image_to_j2k.c, t2.c.
+* [Parvatha] Modified and tested Progression order change "-POC" option. Modification in image_to_j2k.c, j2k.c, pi.c.
++ [Parvatha] Function j2k_check_poc_val() to check for possible loss of packets in case of wrong POC declaration. Modification in j2k.c.
++ [Parvatha] Structure T2_MODE. This tells if the t2_encode_packets() is called during Threshold calculation or in Final pass. Modification in j2k.h, tcd.c
+
+March 30, 2007
+* [GB] OPJViewer should now work under Linux, at least with not big j2k files. Tested under Suse 10.1 64 bit.
+
+March 29, 2007
+* [Parvatha] Enable accepting file names with `-´ symbol .Modification getopt.c
+* [Parvatha] Rsiz profile name generation to be STD_RSIZ for profiles which are not DCI compliant.Modification in image_to_j2k.c
+! [Parvatha] renamed convert_progression_order to j2k_convert_progression_order. Modification j2k.c
+* [Parvatha] Calculation of number of tile part in each tile in j2k_calculate_tp. Modification j2k.c
+! [Parvatha] j2k_setup_encoder to set bit rate limitation for digital cinema compliance with quality option. Modification in j2k.c
+* [Parvatha] Equation to check multiple tile precincts. Modification pi.c
+! [Parvatha] array size generation of pi->include in pi_initialise_encode().Modification in pi.c
+* [Parvatha] modification in pi_create_encode for tile part generation.Modification in pi.c
++ [Parvatha] In tcd_rateallocate a variable stable_threshold which holds the valid threshold value.
+ This is used to avoid error in case of a wrong threshold value in the last iteration. Modification in tcd.c.
+
+March 28, 2007
+* [FOD] Fixed an historical bug in t1.c that leaded to the inclusion of useless 0xFF in the codestream. Thanks to Sylvain, Pascal and Parvatha !
+
+March 27, 2007
++ [GB] Improved parsing in OPJViewer, as well some minor aesthetic modifications; support for image rendering with bit depths lower than 8 bits;
+ can display an arbitrary frame of an MJ2 file (only in B/W, though); can reload a file; better resizing capabilities
+* [GB] Following to Hervé's suggestions, all the exit() calls, added by JPWL strict checking in t2.c and j2k.c,
+ have been substituted with (object free'ing + opj_evt_message(EVT_ERROR) + return)
++ [GB] Added linking to TIFF library in the JPWL VC6 workspaces
+
+March 23, 2007
+* [antonin] Fixed Makefile.osx and changed Readme.osx accordingly
+
+March 21, 2007
+* [Parvatha] Fixed j2k_prog_order_list[]. Modifications in j2k.c.
+* [Parvatha] Fixed t1_decode_cblks. Modifications in t1.c.
+
+March 20, 2007
++ [Parvatha] Added feature for generation of tile parts. Modifications in image_to_j2k.c, openjpeg.c, j2k.c, pi.c
++ [Parvatha] Added function j2k_write_tlm(),to generate TLM marker for a Digital cinema compliant codestream. Modifications in j2k.c.
+
+March 14, 2007
+* [FOD] Fixed linux makefile, with help from David Fries and Guido
+
+March 7, 2007
++ [Parvatha] Added option for Digital cinema profile compliant codestream. This can be chosen by "-cinema2K" or "-cinema4K" for a 2K and 4K compliance respectively. The feature for tileparts has not been implemented in this version. Modification in image_to_j2k.c
++ [Parvatha] Added the Digital Cinema profiles (CINEMA2K and CINEMA4K) to the list of profiles recognized in the codestream SIZ marker segment. Modification in openjpeg.h,j2k.c
++ [Parvatha] Added feature for constant quality within bitrate defined in Digital cinema standards. Modification in tcd.c
+! [Parvatha] Modified the method of generation of buffer length. Modification in cio.c
+
+
+March 1, 2007
+* [FOD] Modified codec projects (*.dsp) and makefile to include the tiff library (modified codec/image_to_j2k.dsp codec/j2k_to_image.dsp and codec/makefile)
++ [GB] Zoom capability and decoder settings dialog in OPJViewer; modified JPWL library .dsp project in order to create a library with embedded JPWL functions
+
+February 28, 2007
++ [Parvatha] Enabled compression of TIF image format to j2k by tifftoimage() and decompression of codestream to TIF image format using imagetotif(). Modifications in image_to_j2k.c, j2k_to_image.c, convert.c, convert.h
+* [antonin] fixed a bug in context numerotation that prevented the RESET switch to work correctly : mqc_reset_enc in mqc.c
+* [Fod] Corrected codec Makefile by adding the compilation of "compat/getopt.c"
+
+February 27, 2007
+* [Parvatha] Made get_file_format function more robust. Modifications in image_to_j2k.c, j2k_to_image.c, getopt.c, getopt.h
+
+February 26, 2007
++ [Parvatha] Option to read images from a Folder whose path is specified in the Input parameters by "-ImgDir" along with output decod format specified by "-OutFor" . Modifications in image_to_j2k.c, j2k_to_image.c, getopt.c, getopt.h
++ [Parvatha] Enabling use of multi character input parameters in the codec. Modifications in image_to_j2k.c, j2k_to_image.c, getopt.c, getopt.h
+
+----------------------
+February 23, 2007
+VERSION 1.1.1 RELEASED
+----------------------
+
+February 23, 2007
+* [GB] Fixed a copy-and-paste type assignment error (bool instead of int) in the JPWL section of decoder parameters structure in openjpeg.h; minor type-casting in jpwl_lib.c.
+ As a result, now OPJViewer should run correctly when built against the most current SVN trunk of LibOpenJPEG.lib
++ [GB] Linux makefile for the JPWL module; newlines at end of JPWL files
+
+February 22, 2007
++ [FOD] Added the OPJViewer Module (/OPJViewer), developed by Giuseppe Baruffa of the university of Perugia
+
+February 21, 2007
++ [FOD] Algorithmic optimizations in t1.c, thanks to Guido J. !
+
+February 19, 2007
++ [FOD] Added OPJ_LIMIT_DECODING enabling us to limit the decoding to main header (modified openjpeg.c, openjpeg.h, j2k.c and j2k.h)
+
+February 13, 2007
+! [FOD] David Fries suggestions. In image_to_j2k and j2k_to_image, strncpy() functions: instead of specifying the path size macro, let the compiler read the length out of the array entry.
+! [FOD] David Fries suggestions. Makefile modified. -fPIC flag used for 64-bit compilation. Move operation (rather than copy) for the dist library creation, and -p flag added.
+
+January 31, 2007
+! [FOD] Extra tokens at the end of #endif directive corrected in openjpeg.c, j2k.c and image_to_j2k.c -> no more warnings in linux compilation
+! [FOD] Linux Makefile added for the codec
+
+January 30, 2007
+! [FOD] Use of OPJ_PATH_LEN (defined as 4096) to be the maximum allowed size for filenames instead of MAX_PATH which is not always defined. This caused some programs using OpenJPEG to crash. Modifications in openjpeg.h j2k_to_image.c and image_to_j2k.c
+! [FOD] Correction of the syntax usage in MJ2_codec/mj2_to_frames.c
+
+January 23, 2007
+! [FOD] Modification in the context numbers, to reflect what has been specified in standard, in libopenjpeg/t1.h
+
+December 07, 2006
++ [Giuseppe Baruffa] Antonin verified that the MacOS build suffered from a missing definition of the "min" macro; I've added this definition (properly #ifndef'ed) into both jpwl.h and rs.h
+
+December 05, 2006
+* [Giuseppe Baruffa] Better fix of the TPH EPBs bug in JPWL module
+* [GB] Fixed the UEP bug in JPWL module; now, during a UEP specification, RS protection or CRC check can be switched off for selected range of packets, and consequently reswitched on without confusing the decoder
++ [GB] Added some lines in the help of JPWL_image_to_j2k, specifying that when using error protection on data packets, this must be paired with header protection, i.e. there cannot be packet protection without header protection
+
+December 04, 2006
+
++ [Francois-Olivier Devaux] New tag: version1.0 (includes codec and libopenjpeg directories)
+Total update of JPWL module
+ - [FOD] removed directories jpwl/decoder, jpwl/encoder, jpwl/decoder_02, jpwl/encoder_02
+ + [FOD] added in JPWL directory crc.h, jpwl.h, rs.h, crc.c, jpwl.c, jpwl_lib.c, rs.c, JPWL_image_to_j2k.dsp, JPWL_j2k_to_image.dsp, LibOpenJPEG_JPWL.dsp, JPWL_image_to_j2k.dsw, JPWL_j2k_to_image.dsw
+ ! [FOD] Modifications of libopenjpeg to integrate JPWL module (in libopenjpeg directory): j2k.c, j2k.h, openjpeg.c, openjpeg.h, opj_includes.g, t2.c
+ ! [FOD] Modification of codec to integrate JPWL module (in codec directory): image_to_j2k.c, j2k_to_image.c
+* [FOD] Corrected incorrect fprintf() formatting in codec/convert.c
+* [FOD] Code optimization usinq vsprintf() command in libopenjpeg/event.c
+* [Giuseppe Baruffa] Fixed a bug in TPH EPBs parameters: now, "last in current header" information is correctly signaled
+
+October 31, 2006
+* [Antonin] fixed a bug in the computation of the mantissa (mu)
++ [Antonin] added the ability to specify the rate as "float" (before : integer)
+
+August 18, 2006
+* [Antonin] fixed a bug in j2k_to_image.c, that prevented the -l option to work correctly.
+
+August 4, 2006
+* [Antonin] fixed a bug in pi.c, line 473, that appeared when more than 100 precincts were generated in a resolution level.
+
+July 28, 2006
++ [Antonin Descampe] added a readme in /mj2 to warn people that it only works with opj0.97
+
+July 21, 2006
+* [Mathieu Malaterre] Install exe and lib and include correctly
+* [Mathieu Malaterre] Fixed mem leaks and greyscale bmp
+* [Mathieu Malaterre] Fix pgx name length + random memory access
+! [Mathieu Malaterre] API is now const
+
+March 19, 2006
+* [Antonin] fixed a bug in t1.c that prevented in some cases a true lossless compression (thanks to Don Mimlitch for reporting this bug)
+
+February 12, 2006
+- [Herve Drolon] removed unneeded working variables in opj_tcd_t
+
+February 04, 2006
+* [galt] fixed a bug in codec/convert.c::imagetobmp
+
+February 01, 2006
+! [Herve Drolon] changed function definitions of INT and FIX modules to 'inline'
++ [Herve Drolon] added a VERSION resource to the DLL version of OpenJPEG
+
+January 31, 2006
+* [Mathieu Malaterre] Fix compilation using default openjpeg.dsw
+* [Herve Drolon] fixed various minor warnings occuring under icc9 and bcc32
+- [Mathieu Malaterre] Remove all references to OPJ_EXPORT, no declspec in header file anymore
++ [Mathieu Malaterre] Add a def.in file which is a template for Module Definition
++ [Herve Drolon] added MSVC project and compiler directives to build a 'standard' WIN32 DLL
+! [Mathieu Malaterre] Update CMake to match the new shared lib system (no more def file)
+
+January 27, 2006
+* [Antonin Descampe] fixed a two initialization problems in t1.c and tcd.c
+
+January 26, 2006
+* [Herve Drolon] fixed various minor warnings occuring under gcc
+* [__david__] fixed a segfault in codec/image_to_j2k.c & codec/j2k_to_image.c
+* [__david__] fixed help option in codec/j2k_to_image & codec/image_to_j2k
+
+January 25, 2006
+! [Mathieu Malaterre] Sync with ITK repository, also add ref to doxygen
+! [Mathieu Malaterre] Add a lot of comments on the CMake build system
+! [Mathieu Malaterre] Fix MINGW32 and BORLAND compilation problems.
+
+January 25, 2006
+* [Antonin Descampe] fixed a problem in convert.c when multiple comments
++ [Antonin Descampe] added cmake files to the project
+! [Antonin Descampe] fix.c : replaced "WIN32" by "_MSC_VER" for int64
++ [Antonin Descampe] added "OPJ_EXPORT" in openjpeg.h to generate shared lib with win32
+! [Antonin Descampe] removed all CtrlM from files
+
+January 24, 2006
+! [Antonin Descampe] event.c : replaced "WIN32" by "_MSC_VER" for i2a
+
+January 20, 2006
+* [Antonin Descampe] fixed various minor warnings with gdcm patches
+
+January 19, 2006
+* [Herve Drolon] fixed a bug in jp2_read_ihdr (need to allocate jp2->comps)
+
+January 18, 2006
+* [Herve Drolon] changed the name of j2k_realloc to opj_realloc
+* [Herve Drolon] fixed a bug in opj_cio_open when saving 48-bit images (wrong buffer size calculation)
+
+December 8, 2005
+* [Antonin Descampe] fixed a bug when specifying a rate '-r' => no distortion info was available in the index
+* [Antonin Descampe] fixed a bug in t1_getwmsedec (stepsize was divided by 8192)
+
+December 5, 2005 - 1.1.0
diff --git a/Source/LibOpenJPEG/LibOpenJPEG.2003.vcproj b/Source/LibOpenJPEG/LibOpenJPEG.2003.vcproj
new file mode 100644
index 0000000..9165dab
--- /dev/null
+++ b/Source/LibOpenJPEG/LibOpenJPEG.2003.vcproj
@@ -0,0 +1,527 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="LibOpenJPEG"
+ ProjectGUID="{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;OPJ_STATIC"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ EnableFunctionLevelLinking="FALSE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/LibOpenJPEG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibOpenJPEG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;OPJ_STATIC"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/LibOpenJPEG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibOpenJPEG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="bio.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cio.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dwt.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="event.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="image.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k_lib.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jp2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jpt.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mct.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mqc.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="openjpeg.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pi.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="raw.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t1.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t2.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tcd.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tgt.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="bio.h">
+ </File>
+ <File
+ RelativePath="cio.h">
+ </File>
+ <File
+ RelativePath="dwt.h">
+ </File>
+ <File
+ RelativePath="event.h">
+ </File>
+ <File
+ RelativePath="fix.h">
+ </File>
+ <File
+ RelativePath="image.h">
+ </File>
+ <File
+ RelativePath="int.h">
+ </File>
+ <File
+ RelativePath="j2k.h">
+ </File>
+ <File
+ RelativePath="j2k_lib.h">
+ </File>
+ <File
+ RelativePath="jp2.h">
+ </File>
+ <File
+ RelativePath="jpt.h">
+ </File>
+ <File
+ RelativePath="mct.h">
+ </File>
+ <File
+ RelativePath="mqc.h">
+ </File>
+ <File
+ RelativePath="openjpeg.h">
+ </File>
+ <File
+ RelativePath="opj_includes.h">
+ </File>
+ <File
+ RelativePath=".\opj_malloc.h">
+ </File>
+ <File
+ RelativePath="pi.h">
+ </File>
+ <File
+ RelativePath="raw.h">
+ </File>
+ <File
+ RelativePath="t1.h">
+ </File>
+ <File
+ RelativePath="t2.h">
+ </File>
+ <File
+ RelativePath="tcd.h">
+ </File>
+ <File
+ RelativePath="tgt.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibOpenJPEG/LibOpenJPEG.2005.vcproj b/Source/LibOpenJPEG/LibOpenJPEG.2005.vcproj
new file mode 100644
index 0000000..70fb7a9
--- /dev/null
+++ b/Source/LibOpenJPEG/LibOpenJPEG.2005.vcproj
@@ -0,0 +1,688 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibOpenJPEG"
+ ProjectGUID="{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+ RootNamespace="LibOpenJPEG"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/LibOpenJPEG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibOpenJPEG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ StructMemberAlignment="0"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/LibOpenJPEG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibOpenJPEG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="bio.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cio.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dwt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="event.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="image.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k_lib.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jp2.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jpt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mct.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mqc.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="openjpeg.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pi.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="raw.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t1.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t2.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tcd.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tgt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="bio.h"
+ >
+ </File>
+ <File
+ RelativePath="cio.h"
+ >
+ </File>
+ <File
+ RelativePath="dwt.h"
+ >
+ </File>
+ <File
+ RelativePath="event.h"
+ >
+ </File>
+ <File
+ RelativePath="fix.h"
+ >
+ </File>
+ <File
+ RelativePath="image.h"
+ >
+ </File>
+ <File
+ RelativePath="int.h"
+ >
+ </File>
+ <File
+ RelativePath="j2k.h"
+ >
+ </File>
+ <File
+ RelativePath="j2k_lib.h"
+ >
+ </File>
+ <File
+ RelativePath="jp2.h"
+ >
+ </File>
+ <File
+ RelativePath="jpt.h"
+ >
+ </File>
+ <File
+ RelativePath="mct.h"
+ >
+ </File>
+ <File
+ RelativePath="mqc.h"
+ >
+ </File>
+ <File
+ RelativePath="openjpeg.h"
+ >
+ </File>
+ <File
+ RelativePath="opj_includes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\opj_malloc.h"
+ >
+ </File>
+ <File
+ RelativePath="pi.h"
+ >
+ </File>
+ <File
+ RelativePath="raw.h"
+ >
+ </File>
+ <File
+ RelativePath="t1.h"
+ >
+ </File>
+ <File
+ RelativePath="t2.h"
+ >
+ </File>
+ <File
+ RelativePath="tcd.h"
+ >
+ </File>
+ <File
+ RelativePath="tgt.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibOpenJPEG/LibOpenJPEG.2008.vcproj b/Source/LibOpenJPEG/LibOpenJPEG.2008.vcproj
new file mode 100644
index 0000000..3ae59aa
--- /dev/null
+++ b/Source/LibOpenJPEG/LibOpenJPEG.2008.vcproj
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibOpenJPEG"
+ ProjectGUID="{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+ RootNamespace="LibOpenJPEG"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ PrecompiledHeaderFile=".\Release/LibOpenJPEG.pch"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;OPJ_STATIC;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ StructMemberAlignment="0"
+ PrecompiledHeaderFile=".\Debug/LibOpenJPEG.pch"
+ Detect64BitPortabilityProblems="false"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="bio.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="cio.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="dwt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="event.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="image.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="j2k_lib.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jp2.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="jpt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mct.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mqc.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="openjpeg.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="pi.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="raw.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t1.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="t2.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tcd.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="tgt.c"
+ >
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="bio.h"
+ >
+ </File>
+ <File
+ RelativePath="cio.h"
+ >
+ </File>
+ <File
+ RelativePath="dwt.h"
+ >
+ </File>
+ <File
+ RelativePath="event.h"
+ >
+ </File>
+ <File
+ RelativePath="fix.h"
+ >
+ </File>
+ <File
+ RelativePath="image.h"
+ >
+ </File>
+ <File
+ RelativePath="int.h"
+ >
+ </File>
+ <File
+ RelativePath="j2k.h"
+ >
+ </File>
+ <File
+ RelativePath="j2k_lib.h"
+ >
+ </File>
+ <File
+ RelativePath="jp2.h"
+ >
+ </File>
+ <File
+ RelativePath="jpt.h"
+ >
+ </File>
+ <File
+ RelativePath="mct.h"
+ >
+ </File>
+ <File
+ RelativePath="mqc.h"
+ >
+ </File>
+ <File
+ RelativePath="openjpeg.h"
+ >
+ </File>
+ <File
+ RelativePath="opj_includes.h"
+ >
+ </File>
+ <File
+ RelativePath="pi.h"
+ >
+ </File>
+ <File
+ RelativePath="raw.h"
+ >
+ </File>
+ <File
+ RelativePath="t1.h"
+ >
+ </File>
+ <File
+ RelativePath="t2.h"
+ >
+ </File>
+ <File
+ RelativePath="tcd.h"
+ >
+ </File>
+ <File
+ RelativePath="tgt.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibOpenJPEG/bio.c b/Source/LibOpenJPEG/bio.c
new file mode 100644
index 0000000..4c02f46
--- /dev/null
+++ b/Source/LibOpenJPEG/bio.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup BIO BIO - Individual bit input-output stream */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Write a bit
+@param bio BIO handle
+@param b Bit to write (0 or 1)
+*/
+static void bio_putbit(opj_bio_t *bio, int b);
+/**
+Read a bit
+@param bio BIO handle
+@return Returns the read bit
+*/
+static int bio_getbit(opj_bio_t *bio);
+/**
+Write a byte
+@param bio BIO handle
+@return Returns 0 if successful, returns 1 otherwise
+*/
+static int bio_byteout(opj_bio_t *bio);
+/**
+Read a byte
+@param bio BIO handle
+@return Returns 0 if successful, returns 1 otherwise
+*/
+static int bio_bytein(opj_bio_t *bio);
+
+/*@}*/
+
+/*@}*/
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+static int bio_byteout(opj_bio_t *bio) {
+ bio->buf = (bio->buf << 8) & 0xffff;
+ bio->ct = bio->buf == 0xff00 ? 7 : 8;
+ if (bio->bp >= bio->end) {
+ return 1;
+ }
+ *bio->bp++ = bio->buf >> 8;
+ return 0;
+}
+
+static int bio_bytein(opj_bio_t *bio) {
+ bio->buf = (bio->buf << 8) & 0xffff;
+ bio->ct = bio->buf == 0xff00 ? 7 : 8;
+ if (bio->bp >= bio->end) {
+ return 1;
+ }
+ bio->buf |= *bio->bp++;
+ return 0;
+}
+
+static void bio_putbit(opj_bio_t *bio, int b) {
+ if (bio->ct == 0) {
+ bio_byteout(bio);
+ }
+ bio->ct--;
+ bio->buf |= b << bio->ct;
+}
+
+static int bio_getbit(opj_bio_t *bio) {
+ if (bio->ct == 0) {
+ bio_bytein(bio);
+ }
+ bio->ct--;
+ return (bio->buf >> bio->ct) & 1;
+}
+
+/*
+==========================================================
+ Bit Input/Output interface
+==========================================================
+*/
+
+opj_bio_t* bio_create(void) {
+ opj_bio_t *bio = (opj_bio_t*)opj_malloc(sizeof(opj_bio_t));
+ return bio;
+}
+
+void bio_destroy(opj_bio_t *bio) {
+ if(bio) {
+ opj_free(bio);
+ }
+}
+
+int bio_numbytes(opj_bio_t *bio) {
+ return (bio->bp - bio->start);
+}
+
+void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len) {
+ bio->start = bp;
+ bio->end = bp + len;
+ bio->bp = bp;
+ bio->buf = 0;
+ bio->ct = 8;
+}
+
+void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len) {
+ bio->start = bp;
+ bio->end = bp + len;
+ bio->bp = bp;
+ bio->buf = 0;
+ bio->ct = 0;
+}
+
+void bio_write(opj_bio_t *bio, int v, int n) {
+ int i;
+ for (i = n - 1; i >= 0; i--) {
+ bio_putbit(bio, (v >> i) & 1);
+ }
+}
+
+int bio_read(opj_bio_t *bio, int n) {
+ int i, v;
+ v = 0;
+ for (i = n - 1; i >= 0; i--) {
+ v += bio_getbit(bio) << i;
+ }
+ return v;
+}
+
+int bio_flush(opj_bio_t *bio) {
+ bio->ct = 0;
+ if (bio_byteout(bio)) {
+ return 1;
+ }
+ if (bio->ct == 7) {
+ bio->ct = 0;
+ if (bio_byteout(bio)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int bio_inalign(opj_bio_t *bio) {
+ bio->ct = 0;
+ if ((bio->buf & 0xff) == 0xff) {
+ if (bio_bytein(bio)) {
+ return 1;
+ }
+ bio->ct = 0;
+ }
+ return 0;
+}
diff --git a/Source/LibOpenJPEG/bio.h b/Source/LibOpenJPEG/bio.h
new file mode 100644
index 0000000..764d7cb
--- /dev/null
+++ b/Source/LibOpenJPEG/bio.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BIO_H
+#define __BIO_H
+/**
+@file bio.h
+@brief Implementation of an individual bit input-output (BIO)
+
+The functions in BIO.C have for goal to realize an individual bit input - output.
+*/
+
+/** @defgroup BIO BIO - Individual bit input-output stream */
+/*@{*/
+
+/**
+Individual bit input-output stream (BIO)
+*/
+typedef struct opj_bio {
+ /** pointer to the start of the buffer */
+ unsigned char *start;
+ /** pointer to the end of the buffer */
+ unsigned char *end;
+ /** pointer to the present position in the buffer */
+ unsigned char *bp;
+ /** temporary place where each byte is read or written */
+ unsigned int buf;
+ /** coder : number of bits free to write. decoder : number of bits read */
+ int ct;
+} opj_bio_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new BIO handle
+@return Returns a new BIO handle if successful, returns NULL otherwise
+*/
+opj_bio_t* bio_create(void);
+/**
+Destroy a previously created BIO handle
+@param bio BIO handle to destroy
+*/
+void bio_destroy(opj_bio_t *bio);
+/**
+Number of bytes written.
+@param bio BIO handle
+@return Returns the number of bytes written
+*/
+int bio_numbytes(opj_bio_t *bio);
+/**
+Init encoder
+@param bio BIO handle
+@param bp Output buffer
+@param len Output buffer length
+*/
+void bio_init_enc(opj_bio_t *bio, unsigned char *bp, int len);
+/**
+Init decoder
+@param bio BIO handle
+@param bp Input buffer
+@param len Input buffer length
+*/
+void bio_init_dec(opj_bio_t *bio, unsigned char *bp, int len);
+/**
+Write bits
+@param bio BIO handle
+@param v Value of bits
+@param n Number of bits to write
+*/
+void bio_write(opj_bio_t *bio, int v, int n);
+/**
+Read bits
+@param bio BIO handle
+@param n Number of bits to read
+@return Returns the corresponding read number
+*/
+int bio_read(opj_bio_t *bio, int n);
+/**
+Flush bits
+@param bio BIO handle
+@return Returns 1 if successful, returns 0 otherwise
+*/
+int bio_flush(opj_bio_t *bio);
+/**
+Passes the ending bits (coming from flushing)
+@param bio BIO handle
+@return Returns 1 if successful, returns 0 otherwise
+*/
+int bio_inalign(opj_bio_t *bio);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __BIO_H */
+
diff --git a/Source/LibOpenJPEG/cio.c b/Source/LibOpenJPEG/cio.c
new file mode 100644
index 0000000..2ac262a
--- /dev/null
+++ b/Source/LibOpenJPEG/cio.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* ----------------------------------------------------------------------- */
+
+opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length) {
+ opj_cp_t *cp = NULL;
+ opj_cio_t *cio = (opj_cio_t*)opj_malloc(sizeof(opj_cio_t));
+ if(!cio) return NULL;
+ cio->cinfo = cinfo;
+ if(buffer && length) {
+ /* wrap a user buffer containing the encoded image */
+ cio->openmode = OPJ_STREAM_READ;
+ cio->buffer = buffer;
+ cio->length = length;
+ }
+ else if(!buffer && !length && cinfo) {
+ /* allocate a buffer for the encoded image */
+ cio->openmode = OPJ_STREAM_WRITE;
+ switch(cinfo->codec_format) {
+ case CODEC_J2K:
+ cp = ((opj_j2k_t*)cinfo->j2k_handle)->cp;
+ break;
+ case CODEC_JP2:
+ cp = ((opj_jp2_t*)cinfo->jp2_handle)->j2k->cp;
+ break;
+ default:
+ opj_free(cio);
+ return NULL;
+ }
+ cio->length = (unsigned int) (0.1625 * cp->img_size + 2000); /* 0.1625 = 1.3/8 and 2000 bytes as a minimum for headers */
+ cio->buffer = (unsigned char *)opj_malloc(cio->length);
+ if(!cio->buffer) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "Error allocating memory for compressed bitstream\n");
+ opj_free(cio);
+ return NULL;
+ }
+ }
+ else {
+ opj_free(cio);
+ return NULL;
+ }
+
+ /* Initialize byte IO */
+ cio->start = cio->buffer;
+ cio->end = cio->buffer + cio->length;
+ cio->bp = cio->buffer;
+
+ return cio;
+}
+
+void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio) {
+ if(cio) {
+ if(cio->openmode == OPJ_STREAM_WRITE) {
+ /* destroy the allocated buffer */
+ opj_free(cio->buffer);
+ }
+ /* destroy the cio */
+ opj_free(cio);
+ }
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+/*
+ * Get position in byte stream.
+ */
+int OPJ_CALLCONV cio_tell(opj_cio_t *cio) {
+ return cio->bp - cio->start;
+}
+
+/*
+ * Set position in byte stream.
+ *
+ * pos : position, in number of bytes, from the beginning of the stream
+ */
+void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos) {
+ cio->bp = cio->start + pos;
+}
+
+/*
+ * Number of bytes left before the end of the stream.
+ */
+int cio_numbytesleft(opj_cio_t *cio) {
+ return cio->end - cio->bp;
+}
+
+/*
+ * Get pointer to the current position in the stream.
+ */
+unsigned char *cio_getbp(opj_cio_t *cio) {
+ return cio->bp;
+}
+
+/*
+ * Write a byte.
+ */
+bool cio_byteout(opj_cio_t *cio, unsigned char v) {
+ if (cio->bp >= cio->end) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "write error\n");
+ return false;
+ }
+ *cio->bp++ = v;
+ return true;
+}
+
+/*
+ * Read a byte.
+ */
+unsigned char cio_bytein(opj_cio_t *cio) {
+ if (cio->bp >= cio->end) {
+ opj_event_msg(cio->cinfo, EVT_ERROR, "read error: passed the end of the codestream (start = %d, current = %d, end = %d\n", cio->start, cio->bp, cio->end);
+ return 0;
+ }
+ return *cio->bp++;
+}
+
+/*
+ * Write some bytes.
+ *
+ * v : value to write
+ * n : number of bytes to write
+ */
+unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n) {
+ int i;
+ for (i = n - 1; i >= 0; i--) {
+ if( !cio_byteout(cio, (unsigned char) ((v >> (i << 3)) & 0xff)) )
+ return 0;
+ }
+ return n;
+}
+
+/*
+ * Read some bytes.
+ *
+ * n : number of bytes to read
+ *
+ * return : value of the n bytes read
+ */
+unsigned int cio_read(opj_cio_t *cio, int n) {
+ int i;
+ unsigned int v;
+ v = 0;
+ for (i = n - 1; i >= 0; i--) {
+ v += cio_bytein(cio) << (i << 3);
+ }
+ return v;
+}
+
+/*
+ * Skip some bytes.
+ *
+ * n : number of bytes to skip
+ */
+void cio_skip(opj_cio_t *cio, int n) {
+ cio->bp += n;
+}
+
+
+
diff --git a/Source/LibOpenJPEG/cio.h b/Source/LibOpenJPEG/cio.h
new file mode 100644
index 0000000..580bf9c
--- /dev/null
+++ b/Source/LibOpenJPEG/cio.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CIO_H
+#define __CIO_H
+/**
+@file cio.h
+@brief Implementation of a byte input-output process (CIO)
+
+The functions in CIO.C have for goal to realize a byte input / output process.
+*/
+
+/** @defgroup CIO CIO - byte input-output stream */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Number of bytes left before the end of the stream
+@param cio CIO handle
+@return Returns the number of bytes before the end of the stream
+*/
+int cio_numbytesleft(opj_cio_t *cio);
+/**
+Get pointer to the current position in the stream
+@param cio CIO handle
+@return Returns a pointer to the current position
+*/
+unsigned char *cio_getbp(opj_cio_t *cio);
+/**
+Write some bytes
+@param cio CIO handle
+@param v Value to write
+@param n Number of bytes to write
+@return Returns the number of bytes written or 0 if an error occured
+*/
+unsigned int cio_write(opj_cio_t *cio, unsigned int v, int n);
+/**
+Read some bytes
+@param cio CIO handle
+@param n Number of bytes to read
+@return Returns the value of the n bytes read
+*/
+unsigned int cio_read(opj_cio_t *cio, int n);
+/**
+Skip some bytes
+@param cio CIO handle
+@param n Number of bytes to skip
+*/
+void cio_skip(opj_cio_t *cio, int n);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __CIO_H */
+
diff --git a/Source/LibOpenJPEG/dwt.c b/Source/LibOpenJPEG/dwt.c
new file mode 100644
index 0000000..78d18d1
--- /dev/null
+++ b/Source/LibOpenJPEG/dwt.c
@@ -0,0 +1,825 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2007, Jonathan Ballard <dzonatas@dzonux.net>
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#include "opj_includes.h"
+
+/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
+/*@{*/
+
+#define WS(i) v->mem[(i)*2]
+#define WD(i) v->mem[(1+(i)*2)]
+
+/** @name Local data structures */
+/*@{*/
+
+typedef struct dwt_local {
+ int* mem;
+ int dn;
+ int sn;
+ int cas;
+} dwt_t;
+
+typedef union {
+ float f[4];
+} v4;
+
+typedef struct v4dwt_local {
+ v4* wavelet ;
+ int dn ;
+ int sn ;
+ int cas ;
+} v4dwt_t ;
+
+static const float dwt_alpha = 1.586134342f; // 12994
+static const float dwt_beta = 0.052980118f; // 434
+static const float dwt_gamma = -0.882911075f; // -7233
+static const float dwt_delta = -0.443506852f; // -3633
+
+static const float K = 1.230174105f; // 10078
+/* FIXME: What is this constant? */
+static const float c13318 = 1.625732422f;
+
+/*@}*/
+
+/**
+Virtual function type for wavelet transform in 1-D
+*/
+typedef void (*DWT1DFN)(dwt_t* v);
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Forward lazy transform (horizontal)
+*/
+static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas);
+/**
+Forward lazy transform (vertical)
+*/
+static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas);
+/**
+Inverse lazy transform (horizontal)
+*/
+static void dwt_interleave_h(dwt_t* h, int *a);
+/**
+Inverse lazy transform (vertical)
+*/
+static void dwt_interleave_v(dwt_t* v, int *a, int x);
+/**
+Forward 5-3 wavelet transform in 1-D
+*/
+static void dwt_encode_1(int *a, int dn, int sn, int cas);
+/**
+Inverse 5-3 wavelet transform in 1-D
+*/
+static void dwt_decode_1(dwt_t *v);
+/**
+Forward 9-7 wavelet transform in 1-D
+*/
+static void dwt_encode_1_real(int *a, int dn, int sn, int cas);
+/**
+Explicit calculation of the Quantization Stepsizes
+*/
+static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize);
+/**
+Inverse wavelet transform in 2-D.
+*/
+static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int i, DWT1DFN fn);
+
+/*@}*/
+
+/*@}*/
+
+#define S(i) a[(i)*2]
+#define D(i) a[(1+(i)*2)]
+#define S_(i) ((i)<0?S(0):((i)>=sn?S(sn-1):S(i)))
+#define D_(i) ((i)<0?D(0):((i)>=dn?D(dn-1):D(i)))
+/* new */
+#define SS_(i) ((i)<0?S(0):((i)>=dn?S(dn-1):S(i)))
+#define DD_(i) ((i)<0?D(0):((i)>=sn?D(sn-1):D(i)))
+
+/* <summary> */
+/* This table contains the norms of the 5-3 wavelets for different bands. */
+/* </summary> */
+static const double dwt_norms[4][10] = {
+ {1.000, 1.500, 2.750, 5.375, 10.68, 21.34, 42.67, 85.33, 170.7, 341.3},
+ {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
+ {1.038, 1.592, 2.919, 5.703, 11.33, 22.64, 45.25, 90.48, 180.9},
+ {.7186, .9218, 1.586, 3.043, 6.019, 12.01, 24.00, 47.97, 95.93}
+};
+
+/* <summary> */
+/* This table contains the norms of the 9-7 wavelets for different bands. */
+/* </summary> */
+static const double dwt_norms_real[4][10] = {
+ {1.000, 1.965, 4.177, 8.403, 16.90, 33.84, 67.69, 135.3, 270.6, 540.9},
+ {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0},
+ {2.022, 3.989, 8.355, 17.04, 34.27, 68.63, 137.3, 274.6, 549.0},
+ {2.080, 3.865, 8.307, 17.18, 34.71, 69.59, 139.3, 278.6, 557.2}
+};
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+/* <summary> */
+/* Forward lazy transform (horizontal). */
+/* </summary> */
+static void dwt_deinterleave_h(int *a, int *b, int dn, int sn, int cas) {
+ int i;
+ for (i=0; i<sn; i++) b[i]=a[2*i+cas];
+ for (i=0; i<dn; i++) b[sn+i]=a[(2*i+1-cas)];
+}
+
+/* <summary> */
+/* Forward lazy transform (vertical). */
+/* </summary> */
+static void dwt_deinterleave_v(int *a, int *b, int dn, int sn, int x, int cas) {
+ int i;
+ for (i=0; i<sn; i++) b[i*x]=a[2*i+cas];
+ for (i=0; i<dn; i++) b[(sn+i)*x]=a[(2*i+1-cas)];
+}
+
+/* <summary> */
+/* Inverse lazy transform (horizontal). */
+/* </summary> */
+static void dwt_interleave_h(dwt_t* h, int *a) {
+ int *ai = a;
+ int *bi = h->mem + h->cas;
+ int i = h->sn;
+ while( i-- ) {
+ *bi = *(ai++);
+ bi += 2;
+ }
+ ai = a + h->sn;
+ bi = h->mem + 1 - h->cas;
+ i = h->dn ;
+ while( i-- ) {
+ *bi = *(ai++);
+ bi += 2;
+ }
+}
+
+/* <summary> */
+/* Inverse lazy transform (vertical). */
+/* </summary> */
+static void dwt_interleave_v(dwt_t* v, int *a, int x) {
+ int *ai = a;
+ int *bi = v->mem + v->cas;
+ int i = v->sn;
+ while( i-- ) {
+ *bi = *ai;
+ bi += 2;
+ ai += x;
+ }
+ ai = a + (v->sn * x);
+ bi = v->mem + 1 - v->cas;
+ i = v->dn ;
+ while( i-- ) {
+ *bi = *ai;
+ bi += 2;
+ ai += x;
+ }
+}
+
+
+/* <summary> */
+/* Forward 5-3 wavelet transform in 1-D. */
+/* </summary> */
+static void dwt_encode_1(int *a, int dn, int sn, int cas) {
+ int i;
+
+ if (!cas) {
+ if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */
+ for (i = 0; i < dn; i++) D(i) -= (S_(i) + S_(i + 1)) >> 1;
+ for (i = 0; i < sn; i++) S(i) += (D_(i - 1) + D_(i) + 2) >> 2;
+ }
+ } else {
+ if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */
+ S(0) *= 2;
+ else {
+ for (i = 0; i < dn; i++) S(i) -= (DD_(i) + DD_(i - 1)) >> 1;
+ for (i = 0; i < sn; i++) D(i) += (SS_(i) + SS_(i + 1) + 2) >> 2;
+ }
+ }
+}
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 1-D. */
+/* </summary> */
+static void dwt_decode_1_(int *a, int dn, int sn, int cas) {
+ int i;
+
+ if (!cas) {
+ if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */
+ for (i = 0; i < sn; i++) S(i) -= (D_(i - 1) + D_(i) + 2) >> 2;
+ for (i = 0; i < dn; i++) D(i) += (S_(i) + S_(i + 1)) >> 1;
+ }
+ } else {
+ if (!sn && dn == 1) /* NEW : CASE ONE ELEMENT */
+ S(0) /= 2;
+ else {
+ for (i = 0; i < sn; i++) D(i) -= (SS_(i) + SS_(i + 1) + 2) >> 2;
+ for (i = 0; i < dn; i++) S(i) += (DD_(i) + DD_(i - 1)) >> 1;
+ }
+ }
+}
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 1-D. */
+/* </summary> */
+static void dwt_decode_1(dwt_t *v) {
+ dwt_decode_1_(v->mem, v->dn, v->sn, v->cas);
+}
+
+/* <summary> */
+/* Forward 9-7 wavelet transform in 1-D. */
+/* </summary> */
+static void dwt_encode_1_real(int *a, int dn, int sn, int cas) {
+ int i;
+ if (!cas) {
+ if ((dn > 0) || (sn > 1)) { /* NEW : CASE ONE ELEMENT */
+ for (i = 0; i < dn; i++)
+ D(i) -= fix_mul(S_(i) + S_(i + 1), 12993);
+ for (i = 0; i < sn; i++)
+ S(i) -= fix_mul(D_(i - 1) + D_(i), 434);
+ for (i = 0; i < dn; i++)
+ D(i) += fix_mul(S_(i) + S_(i + 1), 7233);
+ for (i = 0; i < sn; i++)
+ S(i) += fix_mul(D_(i - 1) + D_(i), 3633);
+ for (i = 0; i < dn; i++)
+ D(i) = fix_mul(D(i), 5038); /*5038 */
+ for (i = 0; i < sn; i++)
+ S(i) = fix_mul(S(i), 6659); /*6660 */
+ }
+ } else {
+ if ((sn > 0) || (dn > 1)) { /* NEW : CASE ONE ELEMENT */
+ for (i = 0; i < dn; i++)
+ S(i) -= fix_mul(DD_(i) + DD_(i - 1), 12993);
+ for (i = 0; i < sn; i++)
+ D(i) -= fix_mul(SS_(i) + SS_(i + 1), 434);
+ for (i = 0; i < dn; i++)
+ S(i) += fix_mul(DD_(i) + DD_(i - 1), 7233);
+ for (i = 0; i < sn; i++)
+ D(i) += fix_mul(SS_(i) + SS_(i + 1), 3633);
+ for (i = 0; i < dn; i++)
+ S(i) = fix_mul(S(i), 5038); /*5038 */
+ for (i = 0; i < sn; i++)
+ D(i) = fix_mul(D(i), 6659); /*6660 */
+ }
+ }
+}
+
+static void dwt_encode_stepsize(int stepsize, int numbps, opj_stepsize_t *bandno_stepsize) {
+ int p, n;
+ p = int_floorlog2(stepsize) - 13;
+ n = 11 - int_floorlog2(stepsize);
+ bandno_stepsize->mant = (n < 0 ? stepsize >> -n : stepsize << n) & 0x7ff;
+ bandno_stepsize->expn = numbps - p;
+}
+
+/*
+==========================================================
+ DWT interface
+==========================================================
+*/
+
+/* <summary> */
+/* Forward 5-3 wavelet transform in 2-D. */
+/* </summary> */
+void dwt_encode(opj_tcd_tilecomp_t * tilec) {
+ int i, j, k;
+ int *a = NULL;
+ int *aj = NULL;
+ int *bj = NULL;
+ int w, l;
+
+ w = tilec->x1-tilec->x0;
+ l = tilec->numresolutions-1;
+ a = tilec->data;
+
+ for (i = 0; i < l; i++) {
+ int rw; /* width of the resolution level computed */
+ int rh; /* height of the resolution level computed */
+ int rw1; /* width of the resolution level once lower than computed one */
+ int rh1; /* height of the resolution level once lower than computed one */
+ int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+ int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */
+ int dn, sn;
+
+ rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+ rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+ rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+ rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+
+ cas_row = tilec->resolutions[l - i].x0 % 2;
+ cas_col = tilec->resolutions[l - i].y0 % 2;
+
+ sn = rh1;
+ dn = rh - rh1;
+ bj = (int*)opj_malloc(rh * sizeof(int));
+ for (j = 0; j < rw; j++) {
+ aj = a + j;
+ for (k = 0; k < rh; k++) bj[k] = aj[k*w];
+ dwt_encode_1(bj, dn, sn, cas_col);
+ dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+ }
+ opj_free(bj);
+
+ sn = rw1;
+ dn = rw - rw1;
+ bj = (int*)opj_malloc(rw * sizeof(int));
+ for (j = 0; j < rh; j++) {
+ aj = a + j * w;
+ for (k = 0; k < rw; k++) bj[k] = aj[k];
+ dwt_encode_1(bj, dn, sn, cas_row);
+ dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+ }
+ opj_free(bj);
+ }
+}
+
+
+/* <summary> */
+/* Inverse 5-3 wavelet transform in 2-D. */
+/* </summary> */
+void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres) {
+ dwt_decode_tile(tilec, numres, &dwt_decode_1);
+}
+
+
+/* <summary> */
+/* Get gain of 5-3 wavelet transform. */
+/* </summary> */
+int dwt_getgain(int orient) {
+ if (orient == 0)
+ return 0;
+ if (orient == 1 || orient == 2)
+ return 1;
+ return 2;
+}
+
+/* <summary> */
+/* Get norm of 5-3 wavelet. */
+/* </summary> */
+double dwt_getnorm(int level, int orient) {
+ return dwt_norms[orient][level];
+}
+
+/* <summary> */
+/* Forward 9-7 wavelet transform in 2-D. */
+/* </summary> */
+
+void dwt_encode_real(opj_tcd_tilecomp_t * tilec) {
+ int i, j, k;
+ int *a = NULL;
+ int *aj = NULL;
+ int *bj = NULL;
+ int w, l;
+
+ w = tilec->x1-tilec->x0;
+ l = tilec->numresolutions-1;
+ a = tilec->data;
+
+ for (i = 0; i < l; i++) {
+ int rw; /* width of the resolution level computed */
+ int rh; /* height of the resolution level computed */
+ int rw1; /* width of the resolution level once lower than computed one */
+ int rh1; /* height of the resolution level once lower than computed one */
+ int cas_col; /* 0 = non inversion on horizontal filtering 1 = inversion between low-pass and high-pass filtering */
+ int cas_row; /* 0 = non inversion on vertical filtering 1 = inversion between low-pass and high-pass filtering */
+ int dn, sn;
+
+ rw = tilec->resolutions[l - i].x1 - tilec->resolutions[l - i].x0;
+ rh = tilec->resolutions[l - i].y1 - tilec->resolutions[l - i].y0;
+ rw1= tilec->resolutions[l - i - 1].x1 - tilec->resolutions[l - i - 1].x0;
+ rh1= tilec->resolutions[l - i - 1].y1 - tilec->resolutions[l - i - 1].y0;
+
+ cas_row = tilec->resolutions[l - i].x0 % 2;
+ cas_col = tilec->resolutions[l - i].y0 % 2;
+
+ sn = rh1;
+ dn = rh - rh1;
+ bj = (int*)opj_malloc(rh * sizeof(int));
+ for (j = 0; j < rw; j++) {
+ aj = a + j;
+ for (k = 0; k < rh; k++) bj[k] = aj[k*w];
+ dwt_encode_1_real(bj, dn, sn, cas_col);
+ dwt_deinterleave_v(bj, aj, dn, sn, w, cas_col);
+ }
+ opj_free(bj);
+
+ sn = rw1;
+ dn = rw - rw1;
+ bj = (int*)opj_malloc(rw * sizeof(int));
+ for (j = 0; j < rh; j++) {
+ aj = a + j * w;
+ for (k = 0; k < rw; k++) bj[k] = aj[k];
+ dwt_encode_1_real(bj, dn, sn, cas_row);
+ dwt_deinterleave_h(bj, aj, dn, sn, cas_row);
+ }
+ opj_free(bj);
+ }
+}
+
+
+/* <summary> */
+/* Get gain of 9-7 wavelet transform. */
+/* </summary> */
+int dwt_getgain_real(int orient) {
+ (void)orient;
+ return 0;
+}
+
+/* <summary> */
+/* Get norm of 9-7 wavelet. */
+/* </summary> */
+double dwt_getnorm_real(int level, int orient) {
+ return dwt_norms_real[orient][level];
+}
+
+void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec) {
+ int numbands, bandno;
+ numbands = 3 * tccp->numresolutions - 2;
+ for (bandno = 0; bandno < numbands; bandno++) {
+ double stepsize;
+ int resno, level, orient, gain;
+
+ resno = (bandno == 0) ? 0 : ((bandno - 1) / 3 + 1);
+ orient = (bandno == 0) ? 0 : ((bandno - 1) % 3 + 1);
+ level = tccp->numresolutions - 1 - resno;
+ gain = (tccp->qmfbid == 0) ? 0 : ((orient == 0) ? 0 : (((orient == 1) || (orient == 2)) ? 1 : 2));
+ if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+ stepsize = 1.0;
+ } else {
+ double norm = dwt_norms_real[orient][level];
+ stepsize = (1 << (gain)) / norm;
+ }
+ dwt_encode_stepsize((int) floor(stepsize * 8192.0), prec + gain, &tccp->stepsizes[bandno]);
+ }
+}
+
+
+/* <summary> */
+/* Determine maximum computed resolution level for inverse wavelet transform */
+/* </summary> */
+static int dwt_decode_max_resolution(opj_tcd_resolution_t* restrict r, int i) {
+ int mr = 1;
+ int w;
+ while( --i ) {
+ r++;
+ if( mr < ( w = r->x1 - r->x0 ) )
+ mr = w ;
+ if( mr < ( w = r->y1 - r->y0 ) )
+ mr = w ;
+ }
+ return mr ;
+}
+
+
+/* <summary> */
+/* Inverse wavelet transform in 2-D. */
+/* </summary> */
+static void dwt_decode_tile(opj_tcd_tilecomp_t* tilec, int numres, DWT1DFN dwt_1D) {
+ dwt_t h;
+ dwt_t v;
+
+ opj_tcd_resolution_t* tr = tilec->resolutions;
+
+ int rw = tr->x1 - tr->x0; /* width of the resolution level computed */
+ int rh = tr->y1 - tr->y0; /* height of the resolution level computed */
+
+ int w = tilec->x1 - tilec->x0;
+
+ h.mem = opj_aligned_malloc(dwt_decode_max_resolution(tr, numres) * sizeof(int));
+ v.mem = h.mem;
+
+ while( --numres) {
+ int * restrict tiledp = tilec->data;
+ int j;
+
+ ++tr;
+ h.sn = rw;
+ v.sn = rh;
+
+ rw = tr->x1 - tr->x0;
+ rh = tr->y1 - tr->y0;
+
+ h.dn = rw - h.sn;
+ h.cas = tr->x0 % 2;
+
+ for(j = 0; j < rh; ++j) {
+ dwt_interleave_h(&h, &tiledp[j*w]);
+ (dwt_1D)(&h);
+ memcpy(&tiledp[j*w], h.mem, rw * sizeof(int));
+ }
+
+ v.dn = rh - v.sn;
+ v.cas = tr->y0 % 2;
+
+ for(j = 0; j < rw; ++j){
+ int k;
+ dwt_interleave_v(&v, &tiledp[j], w);
+ (dwt_1D)(&v);
+ for(k = 0; k < rh; ++k) {
+ tiledp[k * w + j] = v.mem[k];
+ }
+ }
+ }
+ opj_aligned_free(h.mem);
+}
+
+static void v4dwt_interleave_h(v4dwt_t* restrict w, float* restrict a, int x, int size){
+ float* restrict bi = (float*) (w->wavelet + w->cas);
+ int count = w->sn;
+ int i, k;
+ for(k = 0; k < 2; ++k){
+ for(i = 0; i < count; ++i){
+ int j = i;
+ bi[i*8 ] = a[j];
+ j += x;
+ if(j > size) continue;
+ bi[i*8 + 1] = a[j];
+ j += x;
+ if(j > size) continue;
+ bi[i*8 + 2] = a[j];
+ j += x;
+ if(j > size) continue;
+ bi[i*8 + 3] = a[j];
+ }
+ bi = (float*) (w->wavelet + 1 - w->cas);
+ a += w->sn;
+ size -= w->sn;
+ count = w->dn;
+ }
+}
+
+static void v4dwt_interleave_v(v4dwt_t* restrict v , float* restrict a , int x){
+ v4* restrict bi = v->wavelet + v->cas;
+ int i;
+ for(i = 0; i < v->sn; ++i){
+ memcpy(&bi[i*2], &a[i*x], 4 * sizeof(float));
+ }
+ a += v->sn * x;
+ bi = v->wavelet + 1 - v->cas;
+ for(i = 0; i < v->dn; ++i){
+ memcpy(&bi[i*2], &a[i*x], 4 * sizeof(float));
+ }
+}
+
+#ifdef __SSE__
+
+static void v4dwt_decode_step1_sse(v4* w, int count, const __m128 c){
+ __m128* restrict vw = (__m128*) w;
+ int i;
+ for(i = 0; i < count; ++i){
+ __m128 tmp = vw[i*2];
+ vw[i*2] = tmp * c;
+ }
+}
+
+static void v4dwt_decode_step2_sse(v4* l, v4* w, int k, int m, __m128 c){
+ __m128* restrict vl = (__m128*) l;
+ __m128* restrict vw = (__m128*) w;
+ int i;
+ for(i = 0; i < m; ++i){
+ __m128 tmp1 = vl[ 0];
+ __m128 tmp2 = vw[-1];
+ __m128 tmp3 = vw[ 0];
+ vw[-1] = tmp2 + ((tmp1 + tmp3) * c);
+ vl = vw;
+ vw += 2;
+ }
+ if(m >= k){
+ return;
+ }
+ c += c;
+ c *= vl[0];
+ for(; m < k; ++m){
+ __m128 tmp = vw[-1];
+ vw[-1] = tmp + c;
+ vw += 2;
+ }
+}
+
+#else
+
+static void v4dwt_decode_step1(v4* w, int count, const float c){
+ float* restrict fw = (float*) w;
+ int i;
+ for(i = 0; i < count; ++i){
+ float tmp1 = fw[i*8 ];
+ float tmp2 = fw[i*8 + 1];
+ float tmp3 = fw[i*8 + 2];
+ float tmp4 = fw[i*8 + 3];
+ fw[i*8 ] = tmp1 * c;
+ fw[i*8 + 1] = tmp2 * c;
+ fw[i*8 + 2] = tmp3 * c;
+ fw[i*8 + 3] = tmp4 * c;
+ }
+}
+
+static void v4dwt_decode_step2(v4* l, v4* w, int k, int m, float c){
+ float* restrict fl = (float*) l;
+ float* restrict fw = (float*) w;
+ int i;
+ for(i = 0; i < m; ++i){
+ float tmp1_1 = fl[0];
+ float tmp1_2 = fl[1];
+ float tmp1_3 = fl[2];
+ float tmp1_4 = fl[3];
+ float tmp2_1 = fw[-4];
+ float tmp2_2 = fw[-3];
+ float tmp2_3 = fw[-2];
+ float tmp2_4 = fw[-1];
+ float tmp3_1 = fw[0];
+ float tmp3_2 = fw[1];
+ float tmp3_3 = fw[2];
+ float tmp3_4 = fw[3];
+ fw[-4] = tmp2_1 + ((tmp1_1 + tmp3_1) * c);
+ fw[-3] = tmp2_2 + ((tmp1_2 + tmp3_2) * c);
+ fw[-2] = tmp2_3 + ((tmp1_3 + tmp3_3) * c);
+ fw[-1] = tmp2_4 + ((tmp1_4 + tmp3_4) * c);
+ fl = fw;
+ fw += 8;
+ }
+ if(m < k){
+ float c1;
+ float c2;
+ float c3;
+ float c4;
+ c += c;
+ c1 = fl[0] * c;
+ c2 = fl[1] * c;
+ c3 = fl[2] * c;
+ c4 = fl[3] * c;
+ for(; m < k; ++m){
+ float tmp1 = fw[-4];
+ float tmp2 = fw[-3];
+ float tmp3 = fw[-2];
+ float tmp4 = fw[-1];
+ fw[-4] = tmp1 + c1;
+ fw[-3] = tmp2 + c2;
+ fw[-2] = tmp3 + c3;
+ fw[-1] = tmp4 + c4;
+ fw += 8;
+ }
+ }
+}
+
+#endif
+
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 1-D. */
+/* </summary> */
+static void v4dwt_decode(v4dwt_t* restrict dwt){
+ int a, b;
+ if(dwt->cas == 0) {
+ if(!((dwt->dn > 0) || (dwt->sn > 1))){
+ return;
+ }
+ a = 0;
+ b = 1;
+ }else{
+ if(!((dwt->sn > 0) || (dwt->dn > 1))) {
+ return;
+ }
+ a = 1;
+ b = 0;
+ }
+#ifdef __SSE__
+ v4dwt_decode_step1_sse(dwt->wavelet+a, dwt->sn, _mm_set1_ps(K));
+ v4dwt_decode_step1_sse(dwt->wavelet+b, dwt->dn, _mm_set1_ps(c13318));
+ v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_delta));
+ v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_gamma));
+ v4dwt_decode_step2_sse(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), _mm_set1_ps(dwt_beta));
+ v4dwt_decode_step2_sse(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), _mm_set1_ps(dwt_alpha));
+#else
+ v4dwt_decode_step1(dwt->wavelet+a, dwt->sn, K);
+ v4dwt_decode_step1(dwt->wavelet+b, dwt->dn, c13318);
+ v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_delta);
+ v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_gamma);
+ v4dwt_decode_step2(dwt->wavelet+b, dwt->wavelet+a+1, dwt->sn, int_min(dwt->sn, dwt->dn-a), dwt_beta);
+ v4dwt_decode_step2(dwt->wavelet+a, dwt->wavelet+b+1, dwt->dn, int_min(dwt->dn, dwt->sn-b), dwt_alpha);
+#endif
+}
+
+/* <summary> */
+/* Inverse 9-7 wavelet transform in 2-D. */
+/* </summary> */
+void dwt_decode_real(opj_tcd_tilecomp_t* restrict tilec, int numres){
+ v4dwt_t h;
+ v4dwt_t v;
+
+ opj_tcd_resolution_t* res = tilec->resolutions;
+
+ int rw = res->x1 - res->x0; /* width of the resolution level computed */
+ int rh = res->y1 - res->y0; /* height of the resolution level computed */
+
+ int w = tilec->x1 - tilec->x0;
+
+ h.wavelet = (v4*) opj_aligned_malloc((dwt_decode_max_resolution(res, numres)+5) * sizeof(v4));
+ v.wavelet = h.wavelet;
+
+ while( --numres) {
+ float * restrict aj = (float*) tilec->data;
+ int bufsize = (tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0);
+ int j;
+
+ h.sn = rw;
+ v.sn = rh;
+
+ ++res;
+
+ rw = res->x1 - res->x0; /* width of the resolution level computed */
+ rh = res->y1 - res->y0; /* height of the resolution level computed */
+
+ h.dn = rw - h.sn;
+ h.cas = res->x0 % 2;
+
+ for(j = rh; j > 0; j -= 4){
+ v4dwt_interleave_h(&h, aj, w, bufsize);
+ v4dwt_decode(&h);
+ if(j >= 4){
+ int k;
+ for(k = rw; --k >= 0;){
+ aj[k ] = h.wavelet[k].f[0];
+ aj[k+w ] = h.wavelet[k].f[1];
+ aj[k+w*2] = h.wavelet[k].f[2];
+ aj[k+w*3] = h.wavelet[k].f[3];
+ }
+ }else{
+ int k;
+ for(k = rw; --k >= 0;){
+ switch(j) {
+ case 3: aj[k+w*2] = h.wavelet[k].f[2];
+ case 2: aj[k+w ] = h.wavelet[k].f[1];
+ case 1: aj[k ] = h.wavelet[k].f[0];
+ }
+ }
+ }
+ aj += w*4;
+ bufsize -= w*4;
+ }
+
+ v.dn = rh - v.sn;
+ v.cas = res->y0 % 2;
+
+ aj = (float*) tilec->data;
+ for(j = rw; j > 0; j -= 4){
+ v4dwt_interleave_v(&v, aj, w);
+ v4dwt_decode(&v);
+ if(j >= 4){
+ int k;
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], 4 * sizeof(float));
+ }
+ }else{
+ int k;
+ for(k = 0; k < rh; ++k){
+ memcpy(&aj[k*w], &v.wavelet[k], j * sizeof(float));
+ }
+ }
+ aj += 4;
+ }
+ }
+
+ opj_aligned_free(h.wavelet);
+}
+
diff --git a/Source/LibOpenJPEG/dwt.h b/Source/LibOpenJPEG/dwt.h
new file mode 100644
index 0000000..adf73e5
--- /dev/null
+++ b/Source/LibOpenJPEG/dwt.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DWT_H
+#define __DWT_H
+/**
+@file dwt.h
+@brief Implementation of a discrete wavelet transform (DWT)
+
+The functions in DWT.C have for goal to realize forward and inverse discret wavelet
+transform with filter 5-3 (reversible) and filter 9-7 (irreversible). The functions in
+DWT.C are used by some function in TCD.C.
+*/
+
+/** @defgroup DWT DWT - Implementation of a discrete wavelet transform */
+/*@{*/
+
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Forward 5-3 wavelet tranform in 2-D.
+Apply a reversible DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+*/
+void dwt_encode(opj_tcd_tilecomp_t * tilec);
+/**
+Inverse 5-3 wavelet tranform in 2-D.
+Apply a reversible inverse DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+@param numres Number of resolution levels to decode
+*/
+void dwt_decode(opj_tcd_tilecomp_t* tilec, int numres);
+/**
+Get the gain of a subband for the reversible 5-3 DWT.
+@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
+@return Returns 0 if orient = 0, returns 1 if orient = 1 or 2, returns 2 otherwise
+*/
+int dwt_getgain(int orient);
+/**
+Get the norm of a wavelet function of a subband at a specified level for the reversible 5-3 DWT.
+@param level Level of the wavelet function
+@param orient Band of the wavelet function
+@return Returns the norm of the wavelet function
+*/
+double dwt_getnorm(int level, int orient);
+/**
+Forward 9-7 wavelet transform in 2-D.
+Apply an irreversible DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+*/
+void dwt_encode_real(opj_tcd_tilecomp_t * tilec);
+/**
+Inverse 9-7 wavelet transform in 2-D.
+Apply an irreversible inverse DWT transform to a component of an image.
+@param tilec Tile component information (current tile)
+@param numres Number of resolution levels to decode
+*/
+void dwt_decode_real(opj_tcd_tilecomp_t* tilec, int numres);
+/**
+Get the gain of a subband for the irreversible 9-7 DWT.
+@param orient Number that identifies the subband (0->LL, 1->HL, 2->LH, 3->HH)
+@return Returns the gain of the 9-7 wavelet transform
+*/
+int dwt_getgain_real(int orient);
+/**
+Get the norm of a wavelet function of a subband at a specified level for the irreversible 9-7 DWT
+@param level Level of the wavelet function
+@param orient Band of the wavelet function
+@return Returns the norm of the 9-7 wavelet
+*/
+double dwt_getnorm_real(int level, int orient);
+/**
+Explicit calculation of the Quantization Stepsizes
+@param tccp Tile-component coding parameters
+@param prec Precint analyzed
+*/
+void dwt_calc_explicit_stepsizes(opj_tccp_t * tccp, int prec);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __DWT_H */
diff --git a/Source/LibOpenJPEG/event.c b/Source/LibOpenJPEG/event.c
new file mode 100644
index 0000000..291ff58
--- /dev/null
+++ b/Source/LibOpenJPEG/event.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* ==========================================================
+ Utility functions
+ ==========================================================*/
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+static char*
+i2a(unsigned i, char *a, unsigned r) {
+ if (i/r > 0) a = i2a(i/r,a,r);
+ *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
+ return a+1;
+}
+
+/**
+ Transforms integer i into an ascii string and stores the result in a;
+ string is encoded in the base indicated by r.
+ @param i Number to be converted
+ @param a String result
+ @param r Base of value; must be in the range 2 - 36
+ @return Returns a
+*/
+static char *
+_itoa(int i, char *a, int r) {
+ r = ((r < 2) || (r > 36)) ? 10 : r;
+ if(i < 0) {
+ *a = '-';
+ *i2a(-i, a+1, r) = 0;
+ }
+ else *i2a(i, a, r) = 0;
+ return a;
+}
+
+#endif /* !WIN32 */
+
+/* ----------------------------------------------------------------------- */
+
+opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context) {
+ if(cinfo) {
+ opj_event_mgr_t *previous = cinfo->event_mgr;
+ cinfo->event_mgr = event_mgr;
+ cinfo->client_data = context;
+ return previous;
+ }
+
+ return NULL;
+}
+
+bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...) {
+#define MSG_SIZE 512 /* 512 bytes should be more than enough for a short message */
+ opj_msg_callback msg_handler = NULL;
+
+ opj_event_mgr_t *event_mgr = cinfo->event_mgr;
+ if(event_mgr != NULL) {
+ switch(event_type) {
+ case EVT_ERROR:
+ msg_handler = event_mgr->error_handler;
+ break;
+ case EVT_WARNING:
+ msg_handler = event_mgr->warning_handler;
+ break;
+ case EVT_INFO:
+ msg_handler = event_mgr->info_handler;
+ break;
+ default:
+ break;
+ }
+ if(msg_handler == NULL) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ if ((fmt != NULL) && (event_mgr != NULL)) {
+ va_list arg;
+ int str_length/*, i, j*/; /* UniPG */
+ char message[MSG_SIZE];
+ memset(message, 0, MSG_SIZE);
+ /* initialize the optional parameter list */
+ va_start(arg, fmt);
+ /* check the length of the format string */
+ str_length = (strlen(fmt) > MSG_SIZE) ? MSG_SIZE : strlen(fmt);
+ /* parse the format string and put the result in 'message' */
+ vsprintf(message, fmt, arg); /* UniPG */
+ /* deinitialize the optional parameter list */
+ va_end(arg);
+
+ /* output the message to the user program */
+ msg_handler(message, cinfo->client_data);
+ }
+
+ return true;
+}
+
diff --git a/Source/LibOpenJPEG/event.h b/Source/LibOpenJPEG/event.h
new file mode 100644
index 0000000..11910b0
--- /dev/null
+++ b/Source/LibOpenJPEG/event.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __EVENT_H
+#define __EVENT_H
+/**
+@file event.h
+@brief Implementation of a event callback system
+
+The functions in EVENT.C have for goal to send output messages (errors, warnings, debug) to the user.
+*/
+
+#define EVT_ERROR 1 /**< Error event type */
+#define EVT_WARNING 2 /**< Warning event type */
+#define EVT_INFO 4 /**< Debug event type */
+
+/** @defgroup EVENT EVENT - Implementation of a event callback system */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Write formatted data to a string and send the string to a user callback.
+@param cinfo Codec context info
+@param event_type Event type or callback to use to send the message
+@param fmt Format-control string (plus optionnal arguments)
+@return Returns true if successful, returns false otherwise
+*/
+bool opj_event_msg(opj_common_ptr cinfo, int event_type, const char *fmt, ...);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __EVENT_H */
diff --git a/Source/LibOpenJPEG/fix.h b/Source/LibOpenJPEG/fix.h
new file mode 100644
index 0000000..bcb2acb
--- /dev/null
+++ b/Source/LibOpenJPEG/fix.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FIX_H
+#define __FIX_H
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+#define int64 __int64
+#else
+#define int64 long long
+#endif
+
+/**
+@file fix.h
+@brief Implementation of operations of specific multiplication (FIX)
+
+The functions in FIX.H have for goal to realize specific multiplication.
+*/
+
+/** @defgroup FIX FIX - Implementation of operations of specific multiplication */
+/*@{*/
+
+/**
+Multiply two fixed-precision rational numbers.
+@param a
+@param b
+@return Returns a * b
+*/
+static INLINE int fix_mul(int a, int b) {
+ int64 temp = (int64) a * (int64) b ;
+ temp += temp & 4096;
+ return (int) (temp >> 13) ;
+}
+
+/*@}*/
+
+#endif /* __FIX_H */
diff --git a/Source/LibOpenJPEG/image.c b/Source/LibOpenJPEG/image.c
new file mode 100644
index 0000000..30b7d13
--- /dev/null
+++ b/Source/LibOpenJPEG/image.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+opj_image_t* opj_image_create0(void) {
+ opj_image_t *image = (opj_image_t*)opj_calloc(1, sizeof(opj_image_t));
+ return image;
+}
+
+opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc) {
+ int compno;
+ opj_image_t *image = NULL;
+
+ image = (opj_image_t*) opj_calloc(1, sizeof(opj_image_t));
+ if(image) {
+ image->color_space = clrspc;
+ image->numcomps = numcmpts;
+ /* allocate memory for the per-component information */
+ image->comps = (opj_image_comp_t*)opj_malloc(image->numcomps * sizeof(opj_image_comp_t));
+ if(!image->comps) {
+ fprintf(stderr,"Unable to allocate memory for image.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ /* create the individual image components */
+ for(compno = 0; compno < numcmpts; compno++) {
+ opj_image_comp_t *comp = &image->comps[compno];
+ comp->dx = cmptparms[compno].dx;
+ comp->dy = cmptparms[compno].dy;
+ comp->w = cmptparms[compno].w;
+ comp->h = cmptparms[compno].h;
+ comp->x0 = cmptparms[compno].x0;
+ comp->y0 = cmptparms[compno].y0;
+ comp->prec = cmptparms[compno].prec;
+ comp->bpp = cmptparms[compno].bpp;
+ comp->sgnd = cmptparms[compno].sgnd;
+ comp->data = (int*) opj_calloc(comp->w * comp->h, sizeof(int));
+ if(!comp->data) {
+ fprintf(stderr,"Unable to allocate memory for image.\n");
+ opj_image_destroy(image);
+ return NULL;
+ }
+ }
+ }
+
+ return image;
+}
+
+void OPJ_CALLCONV opj_image_destroy(opj_image_t *image) {
+ int i;
+ if(image) {
+ if(image->comps) {
+ /* image components */
+ for(i = 0; i < image->numcomps; i++) {
+ opj_image_comp_t *image_comp = &image->comps[i];
+ if(image_comp->data) {
+ opj_free(image_comp->data);
+ }
+ }
+ opj_free(image->comps);
+ }
+ opj_free(image);
+ }
+}
+
diff --git a/Source/LibOpenJPEG/image.h b/Source/LibOpenJPEG/image.h
new file mode 100644
index 0000000..04c362e
--- /dev/null
+++ b/Source/LibOpenJPEG/image.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __IMAGE_H
+#define __IMAGE_H
+/**
+@file image.h
+@brief Implementation of operations on images (IMAGE)
+
+The functions in IMAGE.C have for goal to realize operations on images.
+*/
+
+/** @defgroup IMAGE IMAGE - Implementation of operations on images */
+/*@{*/
+
+/**
+Create an empty image
+@todo this function should be removed
+@return returns an empty image if successful, returns NULL otherwise
+*/
+opj_image_t* opj_image_create0(void);
+
+/*@}*/
+
+#endif /* __IMAGE_H */
+
diff --git a/Source/LibOpenJPEG/int.h b/Source/LibOpenJPEG/int.h
new file mode 100644
index 0000000..4e5fe08
--- /dev/null
+++ b/Source/LibOpenJPEG/int.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __INT_H
+#define __INT_H
+/**
+@file int.h
+@brief Implementation of operations on integers (INT)
+
+The functions in INT.H have for goal to realize operations on integers.
+*/
+
+/** @defgroup INT INT - Implementation of operations on integers */
+/*@{*/
+
+/** @name Exported functions (see also openjpeg.h) */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Get the minimum of two integers
+@return Returns a if a < b else b
+*/
+static INLINE int int_min(int a, int b) {
+ return a < b ? a : b;
+}
+/**
+Get the maximum of two integers
+@return Returns a if a > b else b
+*/
+static INLINE int int_max(int a, int b) {
+ return (a > b) ? a : b;
+}
+/**
+Clamp an integer inside an interval
+@return
+<ul>
+<li>Returns a if (min < a < max)
+<li>Returns max if (a > max)
+<li>Returns min if (a < min)
+</ul>
+*/
+static INLINE int int_clamp(int a, int min, int max) {
+ if (a < min)
+ return min;
+ if (a > max)
+ return max;
+ return a;
+}
+/**
+@return Get absolute value of integer
+*/
+static INLINE int int_abs(int a) {
+ return a < 0 ? -a : a;
+}
+/**
+Divide an integer and round upwards
+@return Returns a divided by b
+*/
+static INLINE int int_ceildiv(int a, int b) {
+ return (a + b - 1) / b;
+}
+/**
+Divide an integer by a power of 2 and round upwards
+@return Returns a divided by 2^b
+*/
+static INLINE int int_ceildivpow2(int a, int b) {
+ return (a + (1 << b) - 1) >> b;
+}
+/**
+Divide an integer by a power of 2 and round downwards
+@return Returns a divided by 2^b
+*/
+static INLINE int int_floordivpow2(int a, int b) {
+ return a >> b;
+}
+/**
+Get logarithm of an integer and round downwards
+@return Returns log2(a)
+*/
+static INLINE int int_floorlog2(int a) {
+ int l;
+ for (l = 0; a > 1; l++) {
+ a >>= 1;
+ }
+ return l;
+}
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif
diff --git a/Source/LibOpenJPEG/j2k.c b/Source/LibOpenJPEG/j2k.c
new file mode 100644
index 0000000..563efd6
--- /dev/null
+++ b/Source/LibOpenJPEG/j2k.c
@@ -0,0 +1,2509 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Write the SOC marker (Start Of Codestream)
+@param j2k J2K handle
+*/
+static void j2k_write_soc(opj_j2k_t *j2k);
+/**
+Read the SOC marker (Start of Codestream)
+@param j2k J2K handle
+*/
+static void j2k_read_soc(opj_j2k_t *j2k);
+/**
+Write the SIZ marker (image and tile size)
+@param j2k J2K handle
+*/
+static void j2k_write_siz(opj_j2k_t *j2k);
+/**
+Read the SIZ marker (image and tile size)
+@param j2k J2K handle
+*/
+static void j2k_read_siz(opj_j2k_t *j2k);
+/**
+Write the COM marker (comment)
+@param j2k J2K handle
+*/
+static void j2k_write_com(opj_j2k_t *j2k);
+/**
+Read the COM marker (comment)
+@param j2k J2K handle
+*/
+static void j2k_read_com(opj_j2k_t *j2k);
+/**
+Write the value concerning the specified component in the marker COD and COC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_cox(opj_j2k_t *j2k, int compno);
+/**
+Read the value concerning the specified component in the marker COD and COC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information read
+*/
+static void j2k_read_cox(opj_j2k_t *j2k, int compno);
+/**
+Write the COD marker (coding style default)
+@param j2k J2K handle
+*/
+static void j2k_write_cod(opj_j2k_t *j2k);
+/**
+Read the COD marker (coding style default)
+@param j2k J2K handle
+*/
+static void j2k_read_cod(opj_j2k_t *j2k);
+/**
+Write the COC marker (coding style component)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_coc(opj_j2k_t *j2k, int compno);
+/**
+Read the COC marker (coding style component)
+@param j2k J2K handle
+*/
+static void j2k_read_coc(opj_j2k_t *j2k);
+/**
+Write the value concerning the specified component in the marker QCD and QCC
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_qcx(opj_j2k_t *j2k, int compno);
+/**
+Read the value concerning the specified component in the marker QCD and QCC
+@param j2k J2K handle
+@param compno Number of the component concern by the information read
+@param len Length of the information in the QCX part of the marker QCD/QCC
+*/
+static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len);
+/**
+Write the QCD marker (quantization default)
+@param j2k J2K handle
+*/
+static void j2k_write_qcd(opj_j2k_t *j2k);
+/**
+Read the QCD marker (quantization default)
+@param j2k J2K handle
+*/
+static void j2k_read_qcd(opj_j2k_t *j2k);
+/**
+Write the QCC marker (quantization component)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+*/
+static void j2k_write_qcc(opj_j2k_t *j2k, int compno);
+/**
+Read the QCC marker (quantization component)
+@param j2k J2K handle
+*/
+static void j2k_read_qcc(opj_j2k_t *j2k);
+/**
+Write the POC marker (progression order change)
+@param j2k J2K handle
+*/
+static void j2k_write_poc(opj_j2k_t *j2k);
+/**
+Read the POC marker (progression order change)
+@param j2k J2K handle
+*/
+static void j2k_read_poc(opj_j2k_t *j2k);
+/**
+Read the CRG marker (component registration)
+@param j2k J2K handle
+*/
+static void j2k_read_crg(opj_j2k_t *j2k);
+/**
+Read the TLM marker (tile-part lengths)
+@param j2k J2K handle
+*/
+static void j2k_read_tlm(opj_j2k_t *j2k);
+/**
+Read the PLM marker (packet length, main header)
+@param j2k J2K handle
+*/
+static void j2k_read_plm(opj_j2k_t *j2k);
+/**
+Read the PLT marker (packet length, tile-part header)
+@param j2k J2K handle
+*/
+static void j2k_read_plt(opj_j2k_t *j2k);
+/**
+Read the PPM marker (packet packet headers, main header)
+@param j2k J2K handle
+*/
+static void j2k_read_ppm(opj_j2k_t *j2k);
+/**
+Read the PPT marker (packet packet headers, tile-part header)
+@param j2k J2K handle
+*/
+static void j2k_read_ppt(opj_j2k_t *j2k);
+/**
+Write the TLM marker (Mainheader)
+@param j2k J2K handle
+*/
+static void j2k_write_tlm(opj_j2k_t *j2k);
+/**
+Write the SOT marker (start of tile-part)
+@param j2k J2K handle
+*/
+static void j2k_write_sot(opj_j2k_t *j2k);
+/**
+Read the SOT marker (start of tile-part)
+@param j2k J2K handle
+*/
+static void j2k_read_sot(opj_j2k_t *j2k);
+/**
+Write the SOD marker (start of data)
+@param j2k J2K handle
+@param tile_coder Pointer to a TCD handle
+*/
+static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder);
+/**
+Read the SOD marker (start of data)
+@param j2k J2K handle
+*/
+static void j2k_read_sod(opj_j2k_t *j2k);
+/**
+Write the RGN marker (region-of-interest)
+@param j2k J2K handle
+@param compno Number of the component concerned by the information written
+@param tileno Number of the tile concerned by the information written
+*/
+static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno);
+/**
+Read the RGN marker (region-of-interest)
+@param j2k J2K handle
+*/
+static void j2k_read_rgn(opj_j2k_t *j2k);
+/**
+Write the EOC marker (end of codestream)
+@param j2k J2K handle
+*/
+static void j2k_write_eoc(opj_j2k_t *j2k);
+/**
+Read the EOC marker (end of codestream)
+@param j2k J2K handle
+*/
+static void j2k_read_eoc(opj_j2k_t *j2k);
+/**
+Read an unknown marker
+@param j2k J2K handle
+*/
+static void j2k_read_unk(opj_j2k_t *j2k);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+typedef struct j2k_prog_order{
+ OPJ_PROG_ORDER enum_prog;
+ char str_prog[4];
+}j2k_prog_order_t;
+
+j2k_prog_order_t j2k_prog_order_list[] = {
+ {CPRL, "CPRL"},
+ {LRCP, "LRCP"},
+ {PCRL, "PCRL"},
+ {RLCP, "RLCP"},
+ {RPCL, "RPCL"},
+ {-1, ""}
+};
+
+char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order){
+ j2k_prog_order_t *po;
+ for(po = j2k_prog_order_list; po->enum_prog != -1; po++ ){
+ if(po->enum_prog == prg_order){
+ break;
+ }
+ }
+ return po->str_prog;
+}
+
+void j2k_dump_image(FILE *fd, opj_image_t * img) {
+ int compno;
+ fprintf(fd, "image {\n");
+ fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d\n", img->x0, img->y0, img->x1, img->y1);
+ fprintf(fd, " numcomps=%d\n", img->numcomps);
+ for (compno = 0; compno < img->numcomps; compno++) {
+ opj_image_comp_t *comp = &img->comps[compno];
+ fprintf(fd, " comp %d {\n", compno);
+ fprintf(fd, " dx=%d, dy=%d\n", comp->dx, comp->dy);
+ fprintf(fd, " prec=%d\n", comp->prec);
+ fprintf(fd, " sgnd=%d\n", comp->sgnd);
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, "}\n");
+}
+
+void j2k_dump_cp(FILE *fd, opj_image_t * img, opj_cp_t * cp) {
+ int tileno, compno, layno, bandno, resno, numbands;
+ fprintf(fd, "coding parameters {\n");
+ fprintf(fd, " tx0=%d, ty0=%d\n", cp->tx0, cp->ty0);
+ fprintf(fd, " tdx=%d, tdy=%d\n", cp->tdx, cp->tdy);
+ fprintf(fd, " tw=%d, th=%d\n", cp->tw, cp->th);
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ fprintf(fd, " tile %d {\n", tileno);
+ fprintf(fd, " csty=%x\n", tcp->csty);
+ fprintf(fd, " prg=%d\n", tcp->prg);
+ fprintf(fd, " numlayers=%d\n", tcp->numlayers);
+ fprintf(fd, " mct=%d\n", tcp->mct);
+ fprintf(fd, " rates=");
+ for (layno = 0; layno < tcp->numlayers; layno++) {
+ fprintf(fd, "%.1f ", tcp->rates[layno]);
+ }
+ fprintf(fd, "\n");
+ for (compno = 0; compno < img->numcomps; compno++) {
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ fprintf(fd, " comp %d {\n", compno);
+ fprintf(fd, " csty=%x\n", tccp->csty);
+ fprintf(fd, " numresolutions=%d\n", tccp->numresolutions);
+ fprintf(fd, " cblkw=%d\n", tccp->cblkw);
+ fprintf(fd, " cblkh=%d\n", tccp->cblkh);
+ fprintf(fd, " cblksty=%x\n", tccp->cblksty);
+ fprintf(fd, " qmfbid=%d\n", tccp->qmfbid);
+ fprintf(fd, " qntsty=%d\n", tccp->qntsty);
+ fprintf(fd, " numgbits=%d\n", tccp->numgbits);
+ fprintf(fd, " roishift=%d\n", tccp->roishift);
+ fprintf(fd, " stepsizes=");
+ numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2;
+ for (bandno = 0; bandno < numbands; bandno++) {
+ fprintf(fd, "(%d,%d) ", tccp->stepsizes[bandno].mant,
+ tccp->stepsizes[bandno].expn);
+ }
+ fprintf(fd, "\n");
+
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ fprintf(fd, " prcw=");
+ for (resno = 0; resno < tccp->numresolutions; resno++) {
+ fprintf(fd, "%d ", tccp->prcw[resno]);
+ }
+ fprintf(fd, "\n");
+ fprintf(fd, " prch=");
+ for (resno = 0; resno < tccp->numresolutions; resno++) {
+ fprintf(fd, "%d ", tccp->prch[resno]);
+ }
+ fprintf(fd, "\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, "}\n");
+}
+
+/* ----------------------------------------------------------------------- */
+static int j2k_get_num_tp(opj_cp_t *cp,int pino,int tileno){
+ char *prog;
+ int i;
+ int tpnum=1,tpend=0;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ prog = j2k_convert_progression_order(tcp->prg);
+
+ if(cp->tp_on == 1){
+ for(i=0;i<4;i++){
+ if(tpend!=1){
+ if( cp->tp_flag == prog[i] ){
+ tpend=1;cp->tp_pos=i;
+ }
+ switch(prog[i]){
+ case 'C':
+ tpnum= tpnum * tcp->pocs[pino].compE;
+ break;
+ case 'R':
+ tpnum= tpnum * tcp->pocs[pino].resE;
+ break;
+ case 'P':
+ tpnum= tpnum * tcp->pocs[pino].prcE;
+ break;
+ case 'L':
+ tpnum= tpnum * tcp->pocs[pino].layE;
+ break;
+ }
+ }
+ }
+ }else{
+ tpnum=1;
+ }
+ return tpnum;
+}
+
+/** mem allocation for TLM marker*/
+int j2k_calculate_tp(opj_cp_t *cp,int img_numcomp,opj_image_t *image,opj_j2k_t *j2k ){
+ int pino,tileno,totnum_tp=0;
+ j2k->cur_totnum_tp = (int *) opj_malloc(cp->tw * cp->th * sizeof(int));
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ int cur_totnum_tp = 0;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ for(pino = 0; pino <= tcp->numpocs; pino++) {
+ int tp_num=0;
+ opj_pi_iterator_t *pi = pi_initialise_encode(image, cp, tileno,FINAL_PASS);
+ if(!pi) { return -1;}
+ tp_num = j2k_get_num_tp(cp,pino,tileno);
+ totnum_tp = totnum_tp + tp_num;
+ cur_totnum_tp = cur_totnum_tp + tp_num;
+ pi_destroy(pi, cp, tileno);
+ }
+ j2k->cur_totnum_tp[tileno] = cur_totnum_tp;
+ /* INDEX >> */
+ if (j2k->cstr_info) {
+ j2k->cstr_info->tile[tileno].num_tps = cur_totnum_tp;
+ j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(cur_totnum_tp * sizeof(opj_tp_info_t));
+ }
+ /* << INDEX */
+ }
+ return totnum_tp;
+}
+
+static void j2k_write_soc(opj_j2k_t *j2k) {
+ opj_cio_t *cio = j2k->cio;
+ cio_write(cio, J2K_MS_SOC, 2);
+
+/* UniPG>> */
+#ifdef USE_JPWL
+
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_SOC, cio_tell(cio) - 2, 2);
+
+#endif /* USE_JPWL */
+/* <<UniPG */
+}
+
+static void j2k_read_soc(opj_j2k_t *j2k) {
+ j2k->state = J2K_STATE_MHSIZ;
+ /* Index */
+ if (j2k->cstr_info) {
+ j2k->cstr_info->main_head_start = cio_tell(j2k->cio) - 2;
+ j2k->cstr_info->codestream_size = cio_numbytesleft(j2k->cio) + 2 - j2k->cstr_info->main_head_start;
+ }
+}
+
+static void j2k_write_siz(opj_j2k_t *j2k) {
+ int i;
+ int lenp, len;
+
+ opj_cio_t *cio = j2k->cio;
+ opj_image_t *image = j2k->image;
+ opj_cp_t *cp = j2k->cp;
+
+ cio_write(cio, J2K_MS_SIZ, 2); /* SIZ */
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+ cio_write(cio, cp->rsiz, 2); /* Rsiz (capabilities) */
+ cio_write(cio, image->x1, 4); /* Xsiz */
+ cio_write(cio, image->y1, 4); /* Ysiz */
+ cio_write(cio, image->x0, 4); /* X0siz */
+ cio_write(cio, image->y0, 4); /* Y0siz */
+ cio_write(cio, cp->tdx, 4); /* XTsiz */
+ cio_write(cio, cp->tdy, 4); /* YTsiz */
+ cio_write(cio, cp->tx0, 4); /* XT0siz */
+ cio_write(cio, cp->ty0, 4); /* YT0siz */
+ cio_write(cio, image->numcomps, 2); /* Csiz */
+ for (i = 0; i < image->numcomps; i++) {
+ cio_write(cio, image->comps[i].prec - 1 + (image->comps[i].sgnd << 7), 1); /* Ssiz_i */
+ cio_write(cio, image->comps[i].dx, 1); /* XRsiz_i */
+ cio_write(cio, image->comps[i].dy, 1); /* YRsiz_i */
+ }
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lsiz */
+ cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_siz(opj_j2k_t *j2k) {
+ int len, i;
+
+ opj_cio_t *cio = j2k->cio;
+ opj_image_t *image = j2k->image;
+ opj_cp_t *cp = j2k->cp;
+
+ len = cio_read(cio, 2); /* Lsiz */
+ cio_read(cio, 2); /* Rsiz (capabilities) */
+ image->x1 = cio_read(cio, 4); /* Xsiz */
+ image->y1 = cio_read(cio, 4); /* Ysiz */
+ image->x0 = cio_read(cio, 4); /* X0siz */
+ image->y0 = cio_read(cio, 4); /* Y0siz */
+ cp->tdx = cio_read(cio, 4); /* XTsiz */
+ cp->tdy = cio_read(cio, 4); /* YTsiz */
+ cp->tx0 = cio_read(cio, 4); /* XT0siz */
+ cp->ty0 = cio_read(cio, 4); /* YT0siz */
+
+ if ((image->x0<0)||(image->x1<0)||(image->y0<0)||(image->y1<0)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "%s: invalid image size (x0:%d, x1:%d, y0:%d, y1:%d)\n",
+ image->x0,image->x1,image->y0,image->y1);
+ return;
+ }
+
+ image->numcomps = cio_read(cio, 2); /* Csiz */
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters */
+ if (!(image->x1 * image->y1)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: bad image size (%d x %d)\n",
+ image->x1, image->y1);
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ }
+ if (image->numcomps != ((len - 38) / 3)) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: Csiz is %d => space in SIZ only for %d comps.!!!\n",
+ image->numcomps, ((len - 38) / 3));
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n");
+ if (image->numcomps < ((len - 38) / 3)) {
+ len = 38 + 3 * image->numcomps;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting Lsiz to %d => HYPOTHESIS!!!\n",
+ len);
+ } else {
+ image->numcomps = ((len - 38) / 3);
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting Csiz to %d => HYPOTHESIS!!!\n",
+ image->numcomps);
+ }
+ }
+
+ /* update components number in the jpwl_exp_comps filed */
+ cp->exp_comps = image->numcomps;
+ }
+#endif /* USE_JPWL */
+
+ image->comps = (opj_image_comp_t*) opj_calloc(image->numcomps, sizeof(opj_image_comp_t));
+ for (i = 0; i < image->numcomps; i++) {
+ int tmp, w, h;
+ tmp = cio_read(cio, 1); /* Ssiz_i */
+ image->comps[i].prec = (tmp & 0x7f) + 1;
+ image->comps[i].sgnd = tmp >> 7;
+ image->comps[i].dx = cio_read(cio, 1); /* XRsiz_i */
+ image->comps[i].dy = cio_read(cio, 1); /* YRsiz_i */
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters, again */
+ if (!(image->comps[i].dx * image->comps[i].dy)) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad XRsiz_%d/YRsiz_%d (%d x %d)\n",
+ i, i, image->comps[i].dx, image->comps[i].dy);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n");
+ if (!image->comps[i].dx) {
+ image->comps[i].dx = 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting XRsiz_%d to %d => HYPOTHESIS!!!\n",
+ i, image->comps[i].dx);
+ }
+ if (!image->comps[i].dy) {
+ image->comps[i].dy = 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting YRsiz_%d to %d => HYPOTHESIS!!!\n",
+ i, image->comps[i].dy);
+ }
+ }
+
+ }
+#endif /* USE_JPWL */
+
+ /* TODO: unused ? */
+ w = int_ceildiv(image->x1 - image->x0, image->comps[i].dx);
+ h = int_ceildiv(image->y1 - image->y0, image->comps[i].dy);
+
+ image->comps[i].resno_decoded = 0; /* number of resolution decoded */
+ image->comps[i].factor = cp->reduce; /* reducing factor per component */
+ }
+
+ cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx);
+ cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy);
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ /* if JPWL is on, we check whether TX errors have damaged
+ too much the SIZ parameters */
+ if ((cp->tw < 1) || (cp->th < 1) || (cp->tw > cp->max_tiles) || (cp->th > cp->max_tiles)) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad number of tiles (%d x %d)\n",
+ cp->tw, cp->th);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n");
+ if (cp->tw < 1) {
+ cp->tw= 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting %d tiles in x => HYPOTHESIS!!!\n",
+ cp->tw);
+ }
+ if (cp->tw > cp->max_tiles) {
+ cp->tw= 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- too large x, increase expectance of %d\n"
+ "- setting %d tiles in x => HYPOTHESIS!!!\n",
+ cp->max_tiles, cp->tw);
+ }
+ if (cp->th < 1) {
+ cp->th= 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- setting %d tiles in y => HYPOTHESIS!!!\n",
+ cp->th);
+ }
+ if (cp->th > cp->max_tiles) {
+ cp->th= 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- too large y, increase expectance of %d to continue\n",
+ "- setting %d tiles in y => HYPOTHESIS!!!\n",
+ cp->max_tiles, cp->th);
+ }
+ }
+ }
+#endif /* USE_JPWL */
+
+ cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t));
+ cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int));
+ cp->tileno_size = 0;
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ if (!cp->tcps) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: could not alloc tcps field of cp\n");
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ }
+ }
+#endif /* USE_JPWL */
+
+ for (i = 0; i < cp->tw * cp->th; i++) {
+ cp->tcps[i].POC = 0;
+ cp->tcps[i].numpocs = 0;
+ cp->tcps[i].first = 1;
+ }
+
+ /* Initialization for PPM marker */
+ cp->ppm = 0;
+ cp->ppm_data = NULL;
+ cp->ppm_data_first = NULL;
+ cp->ppm_previous = 0;
+ cp->ppm_store = 0;
+
+ j2k->default_tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t));
+ for (i = 0; i < cp->tw * cp->th; i++) {
+ cp->tcps[i].tccps = (opj_tccp_t*) opj_malloc(image->numcomps * sizeof(opj_tccp_t));
+ }
+ j2k->tile_data = (unsigned char**) opj_calloc(cp->tw * cp->th, sizeof(unsigned char*));
+ j2k->tile_len = (int*) opj_calloc(cp->tw * cp->th, sizeof(int));
+ j2k->state = J2K_STATE_MH;
+
+ /* Index */
+ if (j2k->cstr_info) {
+ opj_codestream_info_t *cstr_info = j2k->cstr_info;
+ cstr_info->image_w = image->x1 - image->x0;
+ cstr_info->image_h = image->y1 - image->y0;
+ cstr_info->numcomps = image->numcomps;
+ cstr_info->tw = cp->tw;
+ cstr_info->th = cp->th;
+ cstr_info->tile_x = cp->tdx;
+ cstr_info->tile_y = cp->tdy;
+ cstr_info->tile_Ox = cp->tx0;
+ cstr_info->tile_Oy = cp->ty0;
+ cstr_info->tile = (opj_tile_info_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tile_info_t));
+ }
+}
+
+static void j2k_write_com(opj_j2k_t *j2k) {
+ unsigned int i;
+ int lenp, len;
+
+ if(j2k->cp->comment) {
+ opj_cio_t *cio = j2k->cio;
+ char *comment = j2k->cp->comment;
+
+ cio_write(cio, J2K_MS_COM, 2);
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+ cio_write(cio, 1, 2); /* General use (IS 8859-15:1999 (Latin) values) */
+ for (i = 0; i < strlen(comment); i++) {
+ cio_write(cio, comment[i], 1);
+ }
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2);
+ cio_seek(cio, lenp + len);
+ }
+}
+
+static void j2k_read_com(opj_j2k_t *j2k) {
+ int len;
+
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2);
+ cio_skip(cio, len - 2);
+}
+
+static void j2k_write_cox(opj_j2k_t *j2k, int compno) {
+ int i;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, tccp->numresolutions - 1, 1); /* SPcox (D) */
+ cio_write(cio, tccp->cblkw - 2, 1); /* SPcox (E) */
+ cio_write(cio, tccp->cblkh - 2, 1); /* SPcox (F) */
+ cio_write(cio, tccp->cblksty, 1); /* SPcox (G) */
+ cio_write(cio, tccp->qmfbid, 1); /* SPcox (H) */
+
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ for (i = 0; i < tccp->numresolutions; i++) {
+ cio_write(cio, tccp->prcw[i] + (tccp->prch[i] << 4), 1); /* SPcox (I_i) */
+ }
+ }
+}
+
+static void j2k_read_cox(opj_j2k_t *j2k, int compno) {
+ int i;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_cio_t *cio = j2k->cio;
+
+ tccp->numresolutions = cio_read(cio, 1) + 1; /* SPcox (D) */
+
+ // If user wants to remove more resolutions than the codestream contains, return error
+ if (cp->reduce >= tccp->numresolutions) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Error decoding component %d.\nThe number of resolutions to remove is higher than the number "
+ "of resolutions of this component\nModify the cp_reduce parameter.\n\n", compno);
+ j2k->state |= J2K_STATE_ERR;
+ }
+
+ tccp->cblkw = cio_read(cio, 1) + 2; /* SPcox (E) */
+ tccp->cblkh = cio_read(cio, 1) + 2; /* SPcox (F) */
+ tccp->cblksty = cio_read(cio, 1); /* SPcox (G) */
+ tccp->qmfbid = cio_read(cio, 1); /* SPcox (H) */
+ if (tccp->csty & J2K_CP_CSTY_PRT) {
+ for (i = 0; i < tccp->numresolutions; i++) {
+ int tmp = cio_read(cio, 1); /* SPcox (I_i) */
+ tccp->prcw[i] = tmp & 0xf;
+ tccp->prch[i] = tmp >> 4;
+ }
+ }
+
+ /* INDEX >> */
+ if(j2k->cstr_info && compno == 0) {
+ for (i = 0; i < tccp->numresolutions; i++) {
+ if (tccp->csty & J2K_CP_CSTY_PRT) {
+ j2k->cstr_info->tile[j2k->curtileno].pdx[i] = tccp->prcw[i];
+ j2k->cstr_info->tile[j2k->curtileno].pdy[i] = tccp->prch[i];
+ }
+ else {
+ j2k->cstr_info->tile[j2k->curtileno].pdx[i] = 15;
+ j2k->cstr_info->tile[j2k->curtileno].pdx[i] = 15;
+ }
+ }
+ }
+ /* << INDEX */
+}
+
+static void j2k_write_cod(opj_j2k_t *j2k) {
+ opj_cp_t *cp = NULL;
+ opj_tcp_t *tcp = NULL;
+ int lenp, len;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_COD, 2); /* COD */
+
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+
+ cp = j2k->cp;
+ tcp = &cp->tcps[j2k->curtileno];
+
+ cio_write(cio, tcp->csty, 1); /* Scod */
+ cio_write(cio, tcp->prg, 1); /* SGcod (A) */
+ cio_write(cio, tcp->numlayers, 2); /* SGcod (B) */
+ cio_write(cio, tcp->mct, 1); /* SGcod (C) */
+
+ j2k_write_cox(j2k, 0);
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lcod */
+ cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_cod(opj_j2k_t *j2k) {
+ int len, i, pos;
+
+ opj_cio_t *cio = j2k->cio;
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_image_t *image = j2k->image;
+
+ len = cio_read(cio, 2); /* Lcod */
+ tcp->csty = cio_read(cio, 1); /* Scod */
+ tcp->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* SGcod (A) */
+ tcp->numlayers = cio_read(cio, 2); /* SGcod (B) */
+ tcp->mct = cio_read(cio, 1); /* SGcod (C) */
+
+ pos = cio_tell(cio);
+ for (i = 0; i < image->numcomps; i++) {
+ tcp->tccps[i].csty = tcp->csty & J2K_CP_CSTY_PRT;
+ cio_seek(cio, pos);
+ j2k_read_cox(j2k, i);
+ }
+
+ /* Index */
+ if (j2k->cstr_info) {
+ opj_codestream_info_t *cstr_info = j2k->cstr_info;
+ cstr_info->prog = tcp->prg;
+ cstr_info->numlayers = tcp->numlayers;
+ cstr_info->numdecompos = (int*) opj_malloc(image->numcomps * sizeof(int));
+ for (i = 0; i < image->numcomps; i++) {
+ cstr_info->numdecompos[i] = tcp->tccps[i].numresolutions - 1;
+ }
+ }
+}
+
+static void j2k_write_coc(opj_j2k_t *j2k, int compno) {
+ int lenp, len;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+ opj_image_t *image = j2k->image;
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_COC, 2); /* COC */
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+ cio_write(cio, compno, image->numcomps <= 256 ? 1 : 2); /* Ccoc */
+ cio_write(cio, tcp->tccps[compno].csty, 1); /* Scoc */
+ j2k_write_cox(j2k, compno);
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lcoc */
+ cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_coc(opj_j2k_t *j2k) {
+ int len, compno;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_image_t *image = j2k->image;
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2); /* Lcoc */
+ compno = cio_read(cio, image->numcomps <= 256 ? 1 : 2); /* Ccoc */
+ tcp->tccps[compno].csty = cio_read(cio, 1); /* Scoc */
+ j2k_read_cox(j2k, compno);
+}
+
+static void j2k_write_qcx(opj_j2k_t *j2k, int compno) {
+ int bandno, numbands;
+ int expn, mant;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, tccp->qntsty + (tccp->numgbits << 5), 1); /* Sqcx */
+ numbands = tccp->qntsty == J2K_CCP_QNTSTY_SIQNT ? 1 : tccp->numresolutions * 3 - 2;
+
+ for (bandno = 0; bandno < numbands; bandno++) {
+ expn = tccp->stepsizes[bandno].expn;
+ mant = tccp->stepsizes[bandno].mant;
+
+ if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+ cio_write(cio, expn << 3, 1); /* SPqcx_i */
+ } else {
+ cio_write(cio, (expn << 11) + mant, 2); /* SPqcx_i */
+ }
+ }
+}
+
+static void j2k_read_qcx(opj_j2k_t *j2k, int compno, int len) {
+ int tmp;
+ int bandno, numbands;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_cio_t *cio = j2k->cio;
+
+ tmp = cio_read(cio, 1); /* Sqcx */
+ tccp->qntsty = tmp & 0x1f;
+ tccp->numgbits = tmp >> 5;
+ numbands = (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) ?
+ 1 : ((tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) ? len - 1 : (len - 1) / 2);
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+
+ /* if JPWL is on, we check whether there are too many subbands */
+ if ((numbands < 0) || (numbands >= J2K_MAXBANDS)) {
+ opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,
+ "JPWL: bad number of subbands in Sqcx (%d)\n",
+ numbands);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ numbands = 1;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust them\n"
+ "- setting number of bands to %d => HYPOTHESIS!!!\n",
+ numbands);
+ };
+
+ };
+#endif /* USE_JPWL */
+
+ for (bandno = 0; bandno < numbands; bandno++) {
+ int expn, mant;
+ if (tccp->qntsty == J2K_CCP_QNTSTY_NOQNT) {
+ expn = cio_read(cio, 1) >> 3; /* SPqcx_i */
+ mant = 0;
+ } else {
+ tmp = cio_read(cio, 2); /* SPqcx_i */
+ expn = tmp >> 11;
+ mant = tmp & 0x7ff;
+ }
+ tccp->stepsizes[bandno].expn = expn;
+ tccp->stepsizes[bandno].mant = mant;
+ }
+
+ /* Add Antonin : if scalar_derived -> compute other stepsizes */
+ if (tccp->qntsty == J2K_CCP_QNTSTY_SIQNT) {
+ for (bandno = 1; bandno < J2K_MAXBANDS; bandno++) {
+ tccp->stepsizes[bandno].expn =
+ ((tccp->stepsizes[0].expn) - ((bandno - 1) / 3) > 0) ?
+ (tccp->stepsizes[0].expn) - ((bandno - 1) / 3) : 0;
+ tccp->stepsizes[bandno].mant = tccp->stepsizes[0].mant;
+ }
+ }
+ /* ddA */
+}
+
+static void j2k_write_qcd(opj_j2k_t *j2k) {
+ int lenp, len;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_QCD, 2); /* QCD */
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+ j2k_write_qcx(j2k, 0);
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lqcd */
+ cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_qcd(opj_j2k_t *j2k) {
+ int len, i, pos;
+
+ opj_cio_t *cio = j2k->cio;
+ opj_image_t *image = j2k->image;
+
+ len = cio_read(cio, 2); /* Lqcd */
+ pos = cio_tell(cio);
+ for (i = 0; i < image->numcomps; i++) {
+ cio_seek(cio, pos);
+ j2k_read_qcx(j2k, i, len - 2);
+ }
+}
+
+static void j2k_write_qcc(opj_j2k_t *j2k, int compno) {
+ int lenp, len;
+
+ opj_cio_t *cio = j2k->cio;
+
+ cio_write(cio, J2K_MS_QCC, 2); /* QCC */
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2);
+ cio_write(cio, compno, j2k->image->numcomps <= 256 ? 1 : 2); /* Cqcc */
+ j2k_write_qcx(j2k, compno);
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lqcc */
+ cio_seek(cio, lenp + len);
+}
+
+static void j2k_read_qcc(opj_j2k_t *j2k) {
+ int len, compno;
+ int numcomp = j2k->image->numcomps;
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2); /* Lqcc */
+ compno = cio_read(cio, numcomp <= 256 ? 1 : 2); /* Cqcc */
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+
+ static int backup_compno = 0;
+
+ /* compno is negative or larger than the number of components!!! */
+ if ((compno < 0) || (compno >= numcomp)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: bad component number in QCC (%d out of a maximum of %d)\n",
+ compno, numcomp);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ compno = backup_compno % numcomp;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"
+ "- setting component number to %d\n",
+ compno);
+ }
+
+ /* keep your private count of tiles */
+ backup_compno++;
+ };
+#endif /* USE_JPWL */
+
+ j2k_read_qcx(j2k, compno, len - 2 - (numcomp <= 256 ? 1 : 2));
+}
+
+static void j2k_write_poc(opj_j2k_t *j2k) {
+ int len, numpchgs, i;
+
+ int numcomps = j2k->image->numcomps;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = &cp->tcps[j2k->curtileno];
+ opj_tccp_t *tccp = &tcp->tccps[0];
+ opj_cio_t *cio = j2k->cio;
+
+ numpchgs = 1 + tcp->numpocs;
+ cio_write(cio, J2K_MS_POC, 2); /* POC */
+ len = 2 + (5 + 2 * (numcomps <= 256 ? 1 : 2)) * numpchgs;
+ cio_write(cio, len, 2); /* Lpoc */
+ for (i = 0; i < numpchgs; i++) {
+ opj_poc_t *poc = &tcp->pocs[i];
+ cio_write(cio, poc->resno0, 1); /* RSpoc_i */
+ cio_write(cio, poc->compno0, (numcomps <= 256 ? 1 : 2)); /* CSpoc_i */
+ cio_write(cio, poc->layno1, 2); /* LYEpoc_i */
+ poc->layno1 = int_min(poc->layno1, tcp->numlayers);
+ cio_write(cio, poc->resno1, 1); /* REpoc_i */
+ poc->resno1 = int_min(poc->resno1, tccp->numresolutions);
+ cio_write(cio, poc->compno1, (numcomps <= 256 ? 1 : 2)); /* CEpoc_i */
+ poc->compno1 = int_min(poc->compno1, numcomps);
+ cio_write(cio, poc->prg, 1); /* Ppoc_i */
+ }
+}
+
+static void j2k_read_poc(opj_j2k_t *j2k) {
+ int len, numpchgs, i, old_poc;
+
+ int numcomps = j2k->image->numcomps;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_cio_t *cio = j2k->cio;
+
+ old_poc = tcp->POC ? tcp->numpocs + 1 : 0;
+ tcp->POC = 1;
+ len = cio_read(cio, 2); /* Lpoc */
+ numpchgs = (len - 2) / (5 + 2 * (numcomps <= 256 ? 1 : 2));
+
+ for (i = old_poc; i < numpchgs + old_poc; i++) {
+ opj_poc_t *poc;
+ poc = &tcp->pocs[i];
+ poc->resno0 = cio_read(cio, 1); /* RSpoc_i */
+ poc->compno0 = cio_read(cio, numcomps <= 256 ? 1 : 2); /* CSpoc_i */
+ poc->layno1 = cio_read(cio, 2); /* LYEpoc_i */
+ poc->resno1 = cio_read(cio, 1); /* REpoc_i */
+ poc->compno1 = int_min(
+ cio_read(cio, numcomps <= 256 ? 1 : 2), (unsigned int) numcomps); /* CEpoc_i */
+ poc->prg = (OPJ_PROG_ORDER)cio_read(cio, 1); /* Ppoc_i */
+ }
+
+ tcp->numpocs = numpchgs + old_poc - 1;
+}
+
+static void j2k_read_crg(opj_j2k_t *j2k) {
+ int len, i, Xcrg_i, Ycrg_i;
+
+ opj_cio_t *cio = j2k->cio;
+ int numcomps = j2k->image->numcomps;
+
+ len = cio_read(cio, 2); /* Lcrg */
+ for (i = 0; i < numcomps; i++) {
+ Xcrg_i = cio_read(cio, 2); /* Xcrg_i */
+ Ycrg_i = cio_read(cio, 2); /* Ycrg_i */
+ }
+}
+
+static void j2k_read_tlm(opj_j2k_t *j2k) {
+ int len, Ztlm, Stlm, ST, SP, tile_tlm, i;
+ long int Ttlm_i, Ptlm_i;
+
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2); /* Ltlm */
+ Ztlm = cio_read(cio, 1); /* Ztlm */
+ Stlm = cio_read(cio, 1); /* Stlm */
+ ST = ((Stlm >> 4) & 0x01) + ((Stlm >> 4) & 0x02);
+ SP = (Stlm >> 6) & 0x01;
+ tile_tlm = (len - 4) / ((SP + 1) * 2 + ST);
+ for (i = 0; i < tile_tlm; i++) {
+ Ttlm_i = cio_read(cio, ST); /* Ttlm_i */
+ Ptlm_i = cio_read(cio, SP ? 4 : 2); /* Ptlm_i */
+ }
+}
+
+static void j2k_read_plm(opj_j2k_t *j2k) {
+ int len, i, Zplm, Nplm, add, packet_len = 0;
+
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2); /* Lplm */
+ Zplm = cio_read(cio, 1); /* Zplm */
+ len -= 3;
+ while (len > 0) {
+ Nplm = cio_read(cio, 4); /* Nplm */
+ len -= 4;
+ for (i = Nplm; i > 0; i--) {
+ add = cio_read(cio, 1);
+ len--;
+ packet_len = (packet_len << 7) + add; /* Iplm_ij */
+ if ((add & 0x80) == 0) {
+ /* New packet */
+ packet_len = 0;
+ }
+ if (len <= 0)
+ break;
+ }
+ }
+}
+
+static void j2k_read_plt(opj_j2k_t *j2k) {
+ int len, i, Zplt, packet_len = 0, add;
+
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2); /* Lplt */
+ Zplt = cio_read(cio, 1); /* Zplt */
+ for (i = len - 3; i > 0; i--) {
+ add = cio_read(cio, 1);
+ packet_len = (packet_len << 7) + add; /* Iplt_i */
+ if ((add & 0x80) == 0) {
+ /* New packet */
+ packet_len = 0;
+ }
+ }
+}
+
+static void j2k_read_ppm(opj_j2k_t *j2k) {
+ int len, Z_ppm, i, j;
+ int N_ppm;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2);
+ cp->ppm = 1;
+
+ Z_ppm = cio_read(cio, 1); /* Z_ppm */
+ len -= 3;
+ while (len > 0) {
+ if (cp->ppm_previous == 0) {
+ N_ppm = cio_read(cio, 4); /* N_ppm */
+ len -= 4;
+ } else {
+ N_ppm = cp->ppm_previous;
+ }
+ j = cp->ppm_store;
+ if (Z_ppm == 0) { /* First PPM marker */
+ cp->ppm_data = (unsigned char *) opj_malloc(N_ppm * sizeof(unsigned char));
+ cp->ppm_data_first = cp->ppm_data;
+ cp->ppm_len = N_ppm;
+ } else { /* NON-first PPM marker */
+ cp->ppm_data = (unsigned char *) opj_realloc(cp->ppm_data, (N_ppm + cp->ppm_store) * sizeof(unsigned char));
+
+#ifdef USE_JPWL
+ /* this memory allocation check could be done even in non-JPWL cases */
+ if (cp->correct) {
+ if (!cp->ppm_data) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: failed memory allocation during PPM marker parsing (pos. %x)\n",
+ cio_tell(cio));
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_free(cp->ppm_data);
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ }
+ }
+#endif
+
+ cp->ppm_data_first = cp->ppm_data;
+ cp->ppm_len = N_ppm + cp->ppm_store;
+ }
+ for (i = N_ppm; i > 0; i--) { /* Read packet header */
+ cp->ppm_data[j] = cio_read(cio, 1);
+ j++;
+ len--;
+ if (len == 0)
+ break; /* Case of non-finished packet header in present marker but finished in next one */
+ }
+ cp->ppm_previous = i - 1;
+ cp->ppm_store = j;
+ }
+}
+
+static void j2k_read_ppt(opj_j2k_t *j2k) {
+ int len, Z_ppt, i, j = 0;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = cp->tcps + j2k->curtileno;
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2);
+ Z_ppt = cio_read(cio, 1);
+ tcp->ppt = 1;
+ if (Z_ppt == 0) { /* First PPT marker */
+ tcp->ppt_data = (unsigned char *) opj_malloc((len - 3) * sizeof(unsigned char));
+ tcp->ppt_data_first = tcp->ppt_data;
+ tcp->ppt_store = 0;
+ tcp->ppt_len = len - 3;
+ } else { /* NON-first PPT marker */
+ tcp->ppt_data = (unsigned char *) opj_realloc(tcp->ppt_data, (len - 3 + tcp->ppt_store) * sizeof(unsigned char));
+ tcp->ppt_data_first = tcp->ppt_data;
+ tcp->ppt_len = len - 3 + tcp->ppt_store;
+ }
+ j = tcp->ppt_store;
+ for (i = len - 3; i > 0; i--) {
+ tcp->ppt_data[j] = cio_read(cio, 1);
+ j++;
+ }
+ tcp->ppt_store = j;
+}
+
+static void j2k_write_tlm(opj_j2k_t *j2k){
+ int lenp;
+ opj_cio_t *cio = j2k->cio;
+ j2k->tlm_start = cio_tell(cio);
+ cio_write(cio, J2K_MS_TLM, 2);/* TLM */
+ lenp = 4 + (5*j2k->totnum_tp);
+ cio_write(cio,lenp,2); /* Ltlm */
+ cio_write(cio, 0,1); /* Ztlm=0*/
+ cio_write(cio,80,1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */
+ cio_skip(cio,5*j2k->totnum_tp);
+}
+
+static void j2k_write_sot(opj_j2k_t *j2k) {
+ int lenp, len;
+
+ opj_cio_t *cio = j2k->cio;
+
+ j2k->sot_start = cio_tell(cio);
+ cio_write(cio, J2K_MS_SOT, 2); /* SOT */
+ lenp = cio_tell(cio);
+ cio_skip(cio, 2); /* Lsot (further) */
+ cio_write(cio, j2k->curtileno, 2); /* Isot */
+ cio_skip(cio, 4); /* Psot (further in j2k_write_sod) */
+ cio_write(cio, j2k->cur_tp_num , 1); /* TPsot */
+ cio_write(cio, j2k->cur_totnum_tp[j2k->curtileno], 1); /* TNsot */
+ len = cio_tell(cio) - lenp;
+ cio_seek(cio, lenp);
+ cio_write(cio, len, 2); /* Lsot */
+ cio_seek(cio, lenp + len);
+
+ /* UniPG>> */
+#ifdef USE_JPWL
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_SOT, j2k->sot_start, len + 2);
+#endif /* USE_JPWL */
+ /* <<UniPG */
+}
+
+static void j2k_read_sot(opj_j2k_t *j2k) {
+ int len, tileno, totlen, partno, numparts, i;
+ opj_tcp_t *tcp = NULL;
+ char status = 0;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_cio_t *cio = j2k->cio;
+
+ len = cio_read(cio, 2);
+ tileno = cio_read(cio, 2);
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+
+ static int backup_tileno = 0;
+
+ /* tileno is negative or larger than the number of tiles!!! */
+ if ((tileno < 0) || (tileno > (cp->tw * cp->th))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: bad tile number (%d out of a maximum of %d)\n",
+ tileno, (cp->tw * cp->th));
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ tileno = backup_tileno;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"
+ "- setting tile number to %d\n",
+ tileno);
+ }
+
+ /* keep your private count of tiles */
+ backup_tileno++;
+ };
+#endif /* USE_JPWL */
+
+ if (cp->tileno_size == 0) {
+ cp->tileno[cp->tileno_size] = tileno;
+ cp->tileno_size++;
+ } else {
+ i = 0;
+ while (i < cp->tileno_size && status == 0) {
+ status = cp->tileno[i] == tileno ? 1 : 0;
+ i++;
+ }
+ if (status == 0) {
+ cp->tileno[cp->tileno_size] = tileno;
+ cp->tileno_size++;
+ }
+ }
+
+ totlen = cio_read(cio, 4);
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+
+ /* totlen is negative or larger than the bytes left!!! */
+ if ((totlen < 0) || (totlen > (cio_numbytesleft(cio) + 8))) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: bad tile byte size (%d bytes against %d bytes left)\n",
+ totlen, cio_numbytesleft(cio) + 8);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ /* we try to correct */
+ totlen = 0;
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "- trying to adjust this\n"
+ "- setting Psot to %d => assuming it is the last tile\n",
+ totlen);
+ }
+
+ };
+#endif /* USE_JPWL */
+
+ if (!totlen)
+ totlen = cio_numbytesleft(cio) + 8;
+
+ partno = cio_read(cio, 1);
+ numparts = cio_read(cio, 1);
+
+ j2k->curtileno = tileno;
+ j2k->cur_tp_num = partno;
+ j2k->eot = cio_getbp(cio) - 12 + totlen;
+ j2k->state = J2K_STATE_TPH;
+ tcp = &cp->tcps[j2k->curtileno];
+
+ /* Index */
+ if (j2k->cstr_info) {
+ if (tcp->first) {
+ if (tileno == 0)
+ j2k->cstr_info->main_head_end = cio_tell(cio) - 13;
+ j2k->cstr_info->tile[tileno].tileno = tileno;
+ j2k->cstr_info->tile[tileno].start_pos = cio_tell(cio) - 12;
+ j2k->cstr_info->tile[tileno].end_pos = j2k->cstr_info->tile[tileno].start_pos + totlen - 1;
+ j2k->cstr_info->tile[tileno].num_tps = numparts;
+ if (numparts)
+ j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(numparts * sizeof(opj_tp_info_t));
+ else
+ j2k->cstr_info->tile[tileno].tp = (opj_tp_info_t *) opj_malloc(10 * sizeof(opj_tp_info_t)); // Fixme (10)
+ }
+ else {
+ j2k->cstr_info->tile[tileno].end_pos += totlen;
+ }
+ j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos = cio_tell(cio) - 12;
+ j2k->cstr_info->tile[tileno].tp[partno].tp_end_pos =
+ j2k->cstr_info->tile[tileno].tp[partno].tp_start_pos + totlen - 1;
+ }
+
+ if (tcp->first == 1) {
+ /* Initialization PPT */
+ opj_tccp_t *tmp = tcp->tccps;
+ memcpy(tcp, j2k->default_tcp, sizeof(opj_tcp_t));
+ tcp->ppt = 0;
+ tcp->ppt_data = NULL;
+ tcp->ppt_data_first = NULL;
+ tcp->tccps = tmp;
+
+ for (i = 0; i < j2k->image->numcomps; i++) {
+ tcp->tccps[i] = j2k->default_tcp->tccps[i];
+ }
+ cp->tcps[j2k->curtileno].first = 0;
+ }
+}
+
+static void j2k_write_sod(opj_j2k_t *j2k, void *tile_coder) {
+ int l, layno;
+ int totlen;
+ opj_tcp_t *tcp = NULL;
+ opj_codestream_info_t *cstr_info = NULL;
+
+ opj_tcd_t *tcd = (opj_tcd_t*)tile_coder; /* cast is needed because of conflicts in header inclusions */
+ opj_cp_t *cp = j2k->cp;
+ opj_cio_t *cio = j2k->cio;
+
+ tcd->tp_num = j2k->tp_num ;
+ tcd->cur_tp_num = j2k->cur_tp_num;
+
+ cio_write(cio, J2K_MS_SOD, 2);
+ if (j2k->curtileno == 0) {
+ j2k->sod_start = cio_tell(cio) + j2k->pos_correction;
+ }
+
+ /* INDEX >> */
+ cstr_info = j2k->cstr_info;
+ if (cstr_info) {
+ if (!j2k->cur_tp_num ) {
+ cstr_info->tile[j2k->curtileno].end_header = cio_tell(cio) + j2k->pos_correction - 1;
+ j2k->cstr_info->tile[j2k->curtileno].tileno = j2k->curtileno;
+ }
+ else{
+ if(cstr_info->tile[j2k->curtileno].packet[cstr_info->packno - 1].end_pos < cio_tell(cio))
+ cstr_info->tile[j2k->curtileno].packet[cstr_info->packno].start_pos = cio_tell(cio);
+ }
+ /* UniPG>> */
+#ifdef USE_JPWL
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_SOD, j2k->sod_start, 2);
+#endif /* USE_JPWL */
+ /* <<UniPG */
+ }
+ /* << INDEX */
+
+ tcp = &cp->tcps[j2k->curtileno];
+ for (layno = 0; layno < tcp->numlayers; layno++) {
+ if (tcp->rates[layno]>(j2k->sod_start / (cp->th * cp->tw))) {
+ tcp->rates[layno]-=(j2k->sod_start / (cp->th * cp->tw));
+ } else if (tcp->rates[layno]) {
+ tcp->rates[layno]=1;
+ }
+ }
+ if(j2k->cur_tp_num == 0){
+ tcd->tcd_image->tiles->packno = 0;
+ if(cstr_info)
+ cstr_info->packno = 0;
+ }
+
+ l = tcd_encode_tile(tcd, j2k->curtileno, cio_getbp(cio), cio_numbytesleft(cio) - 2, cstr_info);
+
+ /* Writing Psot in SOT marker */
+ totlen = cio_tell(cio) + l - j2k->sot_start;
+ cio_seek(cio, j2k->sot_start + 6);
+ cio_write(cio, totlen, 4);
+ cio_seek(cio, j2k->sot_start + totlen);
+ /* Writing Ttlm and Ptlm in TLM marker */
+ if(cp->cinema){
+ cio_seek(cio, j2k->tlm_start + 6 + (5*j2k->cur_tp_num));
+ cio_write(cio, j2k->curtileno, 1);
+ cio_write(cio, totlen, 4);
+ }
+ cio_seek(cio, j2k->sot_start + totlen);
+}
+
+static void j2k_read_sod(opj_j2k_t *j2k) {
+ int len, truncate = 0, i;
+ unsigned char *data = NULL, *data_ptr = NULL;
+
+ opj_cio_t *cio = j2k->cio;
+ int curtileno = j2k->curtileno;
+
+ /* Index */
+ if (j2k->cstr_info) {
+ j2k->cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_header =
+ cio_tell(cio) + j2k->pos_correction - 1;
+ if (j2k->cur_tp_num == 0)
+ j2k->cstr_info->tile[j2k->curtileno].end_header = cio_tell(cio) + j2k->pos_correction - 1;
+ j2k->cstr_info->packno = 0;
+ }
+
+ len = int_min(j2k->eot - cio_getbp(cio), cio_numbytesleft(cio) + 1);
+
+ if (len == cio_numbytesleft(cio) + 1) {
+ truncate = 1; /* Case of a truncate codestream */
+ }
+
+ data = j2k->tile_data[curtileno];
+ data = (unsigned char*) opj_realloc(data, (j2k->tile_len[curtileno] + len) * sizeof(unsigned char));
+
+ data_ptr = data + j2k->tile_len[curtileno];
+ for (i = 0; i < len; i++) {
+ data_ptr[i] = cio_read(cio, 1);
+ }
+
+ j2k->tile_len[curtileno] += len;
+ j2k->tile_data[curtileno] = data;
+
+ if (!truncate) {
+ j2k->state = J2K_STATE_TPHSOT;
+ } else {
+ j2k->state = J2K_STATE_NEOC; /* RAJOUTE !! */
+ }
+ j2k->cur_tp_num++;
+}
+
+static void j2k_write_rgn(opj_j2k_t *j2k, int compno, int tileno) {
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ opj_cio_t *cio = j2k->cio;
+ int numcomps = j2k->image->numcomps;
+
+ cio_write(cio, J2K_MS_RGN, 2); /* RGN */
+ cio_write(cio, numcomps <= 256 ? 5 : 6, 2); /* Lrgn */
+ cio_write(cio, compno, numcomps <= 256 ? 1 : 2); /* Crgn */
+ cio_write(cio, 0, 1); /* Srgn */
+ cio_write(cio, tcp->tccps[compno].roishift, 1); /* SPrgn */
+}
+
+static void j2k_read_rgn(opj_j2k_t *j2k) {
+ int len, compno, roisty;
+
+ opj_cp_t *cp = j2k->cp;
+ opj_tcp_t *tcp = j2k->state == J2K_STATE_TPH ? &cp->tcps[j2k->curtileno] : j2k->default_tcp;
+ opj_cio_t *cio = j2k->cio;
+ int numcomps = j2k->image->numcomps;
+
+ len = cio_read(cio, 2); /* Lrgn */
+ compno = cio_read(cio, numcomps <= 256 ? 1 : 2); /* Crgn */
+ roisty = cio_read(cio, 1); /* Srgn */
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ /* totlen is negative or larger than the bytes left!!! */
+ if (compno >= numcomps) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: bad component number in RGN (%d when there are only %d)\n",
+ compno, numcomps);
+ if (!JPWL_ASSUME || JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return;
+ }
+ }
+ };
+#endif /* USE_JPWL */
+
+ tcp->tccps[compno].roishift = cio_read(cio, 1); /* SPrgn */
+}
+
+static void j2k_write_eoc(opj_j2k_t *j2k) {
+ opj_cio_t *cio = j2k->cio;
+ /* opj_event_msg(j2k->cinfo, "%.8x: EOC\n", cio_tell(cio) + j2k->pos_correction); */
+ cio_write(cio, J2K_MS_EOC, 2);
+
+/* UniPG>> */
+#ifdef USE_JPWL
+ /* update markers struct */
+ j2k_add_marker(j2k->cstr_info, J2K_MS_EOC, cio_tell(cio) - 2, 2);
+#endif /* USE_JPWL */
+/* <<UniPG */
+}
+
+static void j2k_read_eoc(opj_j2k_t *j2k) {
+ int i, tileno;
+ bool success;
+
+ /* if packets should be decoded */
+ if (j2k->cp->limit_decoding != DECODE_ALL_BUT_PACKETS) {
+ opj_tcd_t *tcd = tcd_create(j2k->cinfo);
+ tcd_malloc_decode(tcd, j2k->image, j2k->cp);
+ for (i = 0; i < j2k->cp->tileno_size; i++) {
+ tcd_malloc_decode_tile(tcd, j2k->image, j2k->cp, i, j2k->cstr_info);
+ tileno = j2k->cp->tileno[i];
+ success = tcd_decode_tile(tcd, j2k->tile_data[tileno], j2k->tile_len[tileno], tileno, j2k->cstr_info);
+ opj_free(j2k->tile_data[tileno]);
+ j2k->tile_data[tileno] = NULL;
+ tcd_free_decode_tile(tcd, i);
+ if (success == false) {
+ j2k->state |= J2K_STATE_ERR;
+ break;
+ }
+ }
+ tcd_free_decode(tcd);
+ tcd_destroy(tcd);
+ }
+ /* if packets should not be decoded */
+ else {
+ for (i = 0; i < j2k->cp->tileno_size; i++) {
+ tileno = j2k->cp->tileno[i];
+ opj_free(j2k->tile_data[tileno]);
+ j2k->tile_data[tileno] = NULL;
+ }
+ }
+ if (j2k->state & J2K_STATE_ERR)
+ j2k->state = J2K_STATE_MT + J2K_STATE_ERR;
+ else
+ j2k->state = J2K_STATE_MT;
+}
+
+typedef struct opj_dec_mstabent {
+ /** marker value */
+ int id;
+ /** value of the state when the marker can appear */
+ int states;
+ /** action linked to the marker */
+ void (*handler) (opj_j2k_t *j2k);
+} opj_dec_mstabent_t;
+
+opj_dec_mstabent_t j2k_dec_mstab[] = {
+ {J2K_MS_SOC, J2K_STATE_MHSOC, j2k_read_soc},
+ {J2K_MS_SOT, J2K_STATE_MH | J2K_STATE_TPHSOT, j2k_read_sot},
+ {J2K_MS_SOD, J2K_STATE_TPH, j2k_read_sod},
+ {J2K_MS_EOC, J2K_STATE_TPHSOT, j2k_read_eoc},
+ {J2K_MS_SIZ, J2K_STATE_MHSIZ, j2k_read_siz},
+ {J2K_MS_COD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_cod},
+ {J2K_MS_COC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_coc},
+ {J2K_MS_RGN, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_rgn},
+ {J2K_MS_QCD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcd},
+ {J2K_MS_QCC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_qcc},
+ {J2K_MS_POC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_poc},
+ {J2K_MS_TLM, J2K_STATE_MH, j2k_read_tlm},
+ {J2K_MS_PLM, J2K_STATE_MH, j2k_read_plm},
+ {J2K_MS_PLT, J2K_STATE_TPH, j2k_read_plt},
+ {J2K_MS_PPM, J2K_STATE_MH, j2k_read_ppm},
+ {J2K_MS_PPT, J2K_STATE_TPH, j2k_read_ppt},
+ {J2K_MS_SOP, 0, 0},
+ {J2K_MS_CRG, J2K_STATE_MH, j2k_read_crg},
+ {J2K_MS_COM, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_com},
+
+#ifdef USE_JPWL
+ {J2K_MS_EPC, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epc},
+ {J2K_MS_EPB, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_epb},
+ {J2K_MS_ESD, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_esd},
+ {J2K_MS_RED, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_red},
+#endif /* USE_JPWL */
+#ifdef USE_JPSEC
+ {J2K_MS_SEC, J2K_STATE_MH, j2k_read_sec},
+ {J2K_MS_INSEC, 0, j2k_read_insec},
+#endif /* USE_JPSEC */
+
+ {0, J2K_STATE_MH | J2K_STATE_TPH, j2k_read_unk}
+};
+
+static void j2k_read_unk(opj_j2k_t *j2k) {
+ opj_event_msg(j2k->cinfo, EVT_WARNING, "Unknown marker\n");
+
+#ifdef USE_JPWL
+ if (j2k->cp->correct) {
+ int m = 0, id, i;
+ int min_id = 0, min_dist = 17, cur_dist = 0, tmp_id;
+ cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+ id = cio_read(j2k->cio, 2);
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "JPWL: really don't know this marker %x\n",
+ id);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "- possible synch loss due to uncorrectable codestream errors => giving up\n");
+ return;
+ }
+ /* OK, activate this at your own risk!!! */
+ /* we look for the marker at the minimum hamming distance from this */
+ while (j2k_dec_mstab[m].id) {
+
+ /* 1's where they differ */
+ tmp_id = j2k_dec_mstab[m].id ^ id;
+
+ /* compute the hamming distance between our id and the current */
+ cur_dist = 0;
+ for (i = 0; i < 16; i++) {
+ if ((tmp_id >> i) & 0x0001) {
+ cur_dist++;
+ }
+ }
+
+ /* if current distance is smaller, set the minimum */
+ if (cur_dist < min_dist) {
+ min_dist = cur_dist;
+ min_id = j2k_dec_mstab[m].id;
+ }
+
+ /* jump to the next marker */
+ m++;
+ }
+
+ /* do we substitute the marker? */
+ if (min_dist < JPWL_MAXIMUM_HAMMING) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "- marker %x is at distance %d from the read %x\n",
+ min_id, min_dist, id);
+ opj_event_msg(j2k->cinfo, EVT_ERROR,
+ "- trying to substitute in place and crossing fingers!\n");
+ cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+ cio_write(j2k->cio, min_id, 2);
+
+ /* rewind */
+ cio_seek(j2k->cio, cio_tell(j2k->cio) - 2);
+
+ }
+
+ };
+#endif /* USE_JPWL */
+
+}
+
+/**
+Read the lookup table containing all the marker, status and action
+@param id Marker value
+*/
+static opj_dec_mstabent_t *j2k_dec_mstab_lookup(int id) {
+ opj_dec_mstabent_t *e;
+ for (e = j2k_dec_mstab; e->id != 0; e++) {
+ if (e->id == id) {
+ break;
+ }
+ }
+ return e;
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K / JPT decoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo) {
+ opj_j2k_t *j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t));
+ if(!j2k)
+ return NULL;
+
+ j2k->default_tcp = (opj_tcp_t*) opj_calloc(1, sizeof(opj_tcp_t));
+ if(!j2k->default_tcp) {
+ opj_free(j2k);
+ return NULL;
+ }
+
+ j2k->cinfo = cinfo;
+ j2k->tile_data = NULL;
+
+ return j2k;
+}
+
+void j2k_destroy_decompress(opj_j2k_t *j2k) {
+ int i = 0;
+
+ if(j2k->tile_len != NULL) {
+ opj_free(j2k->tile_len);
+ }
+ if(j2k->tile_data != NULL) {
+ opj_free(j2k->tile_data);
+ }
+ if(j2k->default_tcp != NULL) {
+ opj_tcp_t *default_tcp = j2k->default_tcp;
+ if(default_tcp->ppt_data_first != NULL) {
+ opj_free(default_tcp->ppt_data_first);
+ }
+ if(j2k->default_tcp->tccps != NULL) {
+ opj_free(j2k->default_tcp->tccps);
+ }
+ opj_free(j2k->default_tcp);
+ }
+ if(j2k->cp != NULL) {
+ opj_cp_t *cp = j2k->cp;
+ if(cp->tcps != NULL) {
+ for(i = 0; i < cp->tw * cp->th; i++) {
+ if(cp->tcps[i].ppt_data_first != NULL) {
+ opj_free(cp->tcps[i].ppt_data_first);
+ }
+ if(cp->tcps[i].tccps != NULL) {
+ opj_free(cp->tcps[i].tccps);
+ }
+ }
+ opj_free(cp->tcps);
+ }
+ if(cp->ppm_data_first != NULL) {
+ opj_free(cp->ppm_data_first);
+ }
+ if(cp->tileno != NULL) {
+ opj_free(cp->tileno);
+ }
+ if(cp->comment != NULL) {
+ opj_free(cp->comment);
+ }
+
+ opj_free(cp);
+ }
+ opj_free(j2k);
+}
+
+void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters) {
+ if(j2k && parameters) {
+ /* create and initialize the coding parameters structure */
+ opj_cp_t *cp = (opj_cp_t*) opj_calloc(1, sizeof(opj_cp_t));
+ cp->reduce = parameters->cp_reduce;
+ cp->layer = parameters->cp_layer;
+ cp->limit_decoding = parameters->cp_limit_decoding;
+
+#ifdef USE_JPWL
+ cp->correct = parameters->jpwl_correct;
+ cp->exp_comps = parameters->jpwl_exp_comps;
+ cp->max_tiles = parameters->jpwl_max_tiles;
+#endif /* USE_JPWL */
+
+
+ /* keep a link to cp so that we can destroy it later in j2k_destroy_decompress */
+ j2k->cp = cp;
+ }
+}
+
+opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info) {
+ opj_image_t *image = NULL;
+
+ opj_common_ptr cinfo = j2k->cinfo;
+
+ j2k->cio = cio;
+ j2k->cstr_info = cstr_info;
+ if (cstr_info)
+ memset(cstr_info, 0, sizeof(opj_codestream_info_t));
+
+ /* create an empty image */
+ image = opj_image_create0();
+ j2k->image = image;
+
+ j2k->state = J2K_STATE_MHSOC;
+
+ for (;;) {
+ opj_dec_mstabent_t *e;
+ int id = cio_read(cio, 2);
+
+#ifdef USE_JPWL
+ /* we try to honor JPWL correction power */
+ if (j2k->cp->correct) {
+
+ int orig_pos = cio_tell(cio);
+ bool status;
+
+ /* call the corrector */
+ status = jpwl_correct(j2k);
+
+ /* go back to where you were */
+ cio_seek(cio, orig_pos - 2);
+
+ /* re-read the marker */
+ id = cio_read(cio, 2);
+
+ /* check whether it begins with ff */
+ if (id >> 8 != 0xff) {
+ opj_event_msg(cinfo, EVT_ERROR,
+ "JPWL: possible bad marker %x at %d\n",
+ id, cio_tell(cio) - 2);
+ if (!JPWL_ASSUME) {
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return 0;
+ }
+ /* we try to correct */
+ id = id | 0xff00;
+ cio_seek(cio, cio_tell(cio) - 2);
+ cio_write(cio, id, 2);
+ opj_event_msg(cinfo, EVT_WARNING, "- trying to adjust this\n"
+ "- setting marker to %x\n",
+ id);
+ }
+
+ }
+#endif /* USE_JPWL */
+
+ if (id >> 8 != 0xff) {
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+ return 0;
+ }
+ e = j2k_dec_mstab_lookup(id);
+ // Check if the marker is known
+ if (!(j2k->state & e->states)) {
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id);
+ return 0;
+ }
+ // Check if the decoding is limited to the main header
+ if (e->id == J2K_MS_SOT && j2k->cp->limit_decoding == LIMIT_TO_MAIN_HEADER) {
+ opj_event_msg(cinfo, EVT_INFO, "Main Header decoded.\n");
+ return image;
+ }
+
+ if (e->handler) {
+ (*e->handler)(j2k);
+ }
+ if (j2k->state & J2K_STATE_ERR)
+ return NULL;
+
+ if (j2k->state == J2K_STATE_MT) {
+ break;
+ }
+ if (j2k->state == J2K_STATE_NEOC) {
+ break;
+ }
+ }
+ if (j2k->state == J2K_STATE_NEOC) {
+ j2k_read_eoc(j2k);
+ }
+
+ if (j2k->state != J2K_STATE_MT) {
+ opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n");
+ }
+
+ return image;
+}
+
+/*
+* Read a JPT-stream and decode file
+*
+*/
+opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info) {
+ opj_image_t *image = NULL;
+ opj_jpt_msg_header_t header;
+ int position;
+
+ opj_common_ptr cinfo = j2k->cinfo;
+
+ j2k->cio = cio;
+
+ /* create an empty image */
+ image = opj_image_create0();
+ j2k->image = image;
+
+ j2k->state = J2K_STATE_MHSOC;
+
+ /* Initialize the header */
+ jpt_init_msg_header(&header);
+ /* Read the first header of the message */
+ jpt_read_msg_header(cinfo, cio, &header);
+
+ position = cio_tell(cio);
+ if (header.Class_Id != 6) { /* 6 : Main header data-bin message */
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Main header first [class_Id %d] !\n", header.Class_Id);
+ return 0;
+ }
+
+ for (;;) {
+ opj_dec_mstabent_t *e = NULL;
+ int id;
+
+ if (!cio_numbytesleft(cio)) {
+ j2k_read_eoc(j2k);
+ return image;
+ }
+ /* data-bin read -> need to read a new header */
+ if ((unsigned int) (cio_tell(cio) - position) == header.Msg_length) {
+ jpt_read_msg_header(cinfo, cio, &header);
+ position = cio_tell(cio);
+ if (header.Class_Id != 4) { /* 4 : Tile data-bin message */
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "[JPT-stream] : Expecting Tile info !\n");
+ return 0;
+ }
+ }
+
+ id = cio_read(cio, 2);
+ if (id >> 8 != 0xff) {
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "%.8x: expected a marker instead of %x\n", cio_tell(cio) - 2, id);
+ return 0;
+ }
+ e = j2k_dec_mstab_lookup(id);
+ if (!(j2k->state & e->states)) {
+ opj_image_destroy(image);
+ opj_event_msg(cinfo, EVT_ERROR, "%.8x: unexpected marker %x\n", cio_tell(cio) - 2, id);
+ return 0;
+ }
+ if (e->handler) {
+ (*e->handler)(j2k);
+ }
+ if (j2k->state == J2K_STATE_MT) {
+ break;
+ }
+ if (j2k->state == J2K_STATE_NEOC) {
+ break;
+ }
+ }
+ if (j2k->state == J2K_STATE_NEOC) {
+ j2k_read_eoc(j2k);
+ }
+
+ if (j2k->state != J2K_STATE_MT) {
+ opj_event_msg(cinfo, EVT_WARNING, "Incomplete bitstream\n");
+ }
+
+ return image;
+}
+
+/* ----------------------------------------------------------------------- */
+/* J2K encoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo) {
+ opj_j2k_t *j2k = (opj_j2k_t*) opj_calloc(1, sizeof(opj_j2k_t));
+ if(j2k) {
+ j2k->cinfo = cinfo;
+ }
+ return j2k;
+}
+
+void j2k_destroy_compress(opj_j2k_t *j2k) {
+ int tileno;
+
+ if(!j2k) return;
+ if(j2k->cp != NULL) {
+ opj_cp_t *cp = j2k->cp;
+
+ if(cp->comment) {
+ opj_free(cp->comment);
+ }
+ if(cp->matrice) {
+ opj_free(cp->matrice);
+ }
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ opj_free(cp->tcps[tileno].tccps);
+ }
+ opj_free(cp->tcps);
+ opj_free(cp);
+ }
+
+ opj_free(j2k);
+}
+
+void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image) {
+ int i, j, tileno, numpocs_tile;
+ opj_cp_t *cp = NULL;
+
+ if(!j2k || !parameters || ! image) {
+ return;
+ }
+
+ /* create and initialize the coding parameters structure */
+ cp = (opj_cp_t*) opj_calloc(1, sizeof(opj_cp_t));
+
+ /* keep a link to cp so that we can destroy it later in j2k_destroy_compress */
+ j2k->cp = cp;
+
+ /* set default values for cp */
+ cp->tw = 1;
+ cp->th = 1;
+
+ /*
+ copy user encoding parameters
+ */
+ cp->cinema = parameters->cp_cinema;
+ cp->max_comp_size = parameters->max_comp_size;
+ cp->rsiz = parameters->cp_rsiz;
+ cp->disto_alloc = parameters->cp_disto_alloc;
+ cp->fixed_alloc = parameters->cp_fixed_alloc;
+ cp->fixed_quality = parameters->cp_fixed_quality;
+
+ /* mod fixed_quality */
+ if(parameters->cp_matrice) {
+ size_t array_size = parameters->tcp_numlayers * parameters->numresolution * 3 * sizeof(int);
+ cp->matrice = (int *) opj_malloc(array_size);
+ memcpy(cp->matrice, parameters->cp_matrice, array_size);
+ }
+
+ /* tiles */
+ cp->tdx = parameters->cp_tdx;
+ cp->tdy = parameters->cp_tdy;
+
+ /* tile offset */
+ cp->tx0 = parameters->cp_tx0;
+ cp->ty0 = parameters->cp_ty0;
+
+ /* comment string */
+ if(parameters->cp_comment) {
+ cp->comment = (char*)opj_malloc(strlen(parameters->cp_comment) + 1);
+ if(cp->comment) {
+ strcpy(cp->comment, parameters->cp_comment);
+ }
+ }
+
+ /*
+ calculate other encoding parameters
+ */
+
+ if (parameters->tile_size_on) {
+ cp->tw = int_ceildiv(image->x1 - cp->tx0, cp->tdx);
+ cp->th = int_ceildiv(image->y1 - cp->ty0, cp->tdy);
+ } else {
+ cp->tdx = image->x1 - cp->tx0;
+ cp->tdy = image->y1 - cp->ty0;
+ }
+
+ if(parameters->tp_on){
+ cp->tp_flag = parameters->tp_flag;
+ cp->tp_on = 1;
+ }
+
+ cp->img_size = 0;
+ for(i=0;i<image->numcomps ;i++){
+ cp->img_size += (image->comps[i].w *image->comps[i].h * image->comps[i].prec);
+ }
+
+
+#ifdef USE_JPWL
+ /*
+ calculate JPWL encoding parameters
+ */
+
+ if (parameters->jpwl_epc_on) {
+ int i;
+
+ /* set JPWL on */
+ cp->epc_on = true;
+ cp->info_on = false; /* no informative technique */
+
+ /* set EPB on */
+ if ((parameters->jpwl_hprot_MH > 0) || (parameters->jpwl_hprot_TPH[0] > 0)) {
+ cp->epb_on = true;
+
+ cp->hprot_MH = parameters->jpwl_hprot_MH;
+ for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) {
+ cp->hprot_TPH_tileno[i] = parameters->jpwl_hprot_TPH_tileno[i];
+ cp->hprot_TPH[i] = parameters->jpwl_hprot_TPH[i];
+ }
+ /* if tile specs are not specified, copy MH specs */
+ if (cp->hprot_TPH[0] == -1) {
+ cp->hprot_TPH_tileno[0] = 0;
+ cp->hprot_TPH[0] = parameters->jpwl_hprot_MH;
+ }
+ for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) {
+ cp->pprot_tileno[i] = parameters->jpwl_pprot_tileno[i];
+ cp->pprot_packno[i] = parameters->jpwl_pprot_packno[i];
+ cp->pprot[i] = parameters->jpwl_pprot[i];
+ }
+ }
+
+ /* set ESD writing */
+ if ((parameters->jpwl_sens_size == 1) || (parameters->jpwl_sens_size == 2)) {
+ cp->esd_on = true;
+
+ cp->sens_size = parameters->jpwl_sens_size;
+ cp->sens_addr = parameters->jpwl_sens_addr;
+ cp->sens_range = parameters->jpwl_sens_range;
+
+ cp->sens_MH = parameters->jpwl_sens_MH;
+ for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) {
+ cp->sens_TPH_tileno[i] = parameters->jpwl_sens_TPH_tileno[i];
+ cp->sens_TPH[i] = parameters->jpwl_sens_TPH[i];
+ }
+ }
+
+ /* always set RED writing to false: we are at the encoder */
+ cp->red_on = false;
+
+ } else {
+ cp->epc_on = false;
+ }
+#endif /* USE_JPWL */
+
+
+ /* initialize the mutiple tiles */
+ /* ---------------------------- */
+ cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t));
+
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ tcp->numlayers = parameters->tcp_numlayers;
+ for (j = 0; j < tcp->numlayers; j++) {
+ if(cp->cinema){
+ if (cp->fixed_quality) {
+ tcp->distoratio[j] = parameters->tcp_distoratio[j];
+ }
+ tcp->rates[j] = parameters->tcp_rates[j];
+ }else{
+ if (cp->fixed_quality) { /* add fixed_quality */
+ tcp->distoratio[j] = parameters->tcp_distoratio[j];
+ } else {
+ tcp->rates[j] = parameters->tcp_rates[j];
+ }
+ }
+ }
+ tcp->csty = parameters->csty;
+ tcp->prg = parameters->prog_order;
+ tcp->mct = parameters->tcp_mct;
+
+ numpocs_tile = 0;
+ tcp->POC = 0;
+ if (parameters->numpocs) {
+ /* initialisation of POC */
+ tcp->POC = 1;
+ for (i = 0; i < parameters->numpocs; i++) {
+ if((tileno == parameters->POC[i].tile - 1) || (parameters->POC[i].tile == -1)) {
+ opj_poc_t *tcp_poc = &tcp->pocs[numpocs_tile];
+ tcp_poc->resno0 = parameters->POC[numpocs_tile].resno0;
+ tcp_poc->compno0 = parameters->POC[numpocs_tile].compno0;
+ tcp_poc->layno1 = parameters->POC[numpocs_tile].layno1;
+ tcp_poc->resno1 = parameters->POC[numpocs_tile].resno1;
+ tcp_poc->compno1 = parameters->POC[numpocs_tile].compno1;
+ tcp_poc->prg1 = parameters->POC[numpocs_tile].prg1;
+ tcp_poc->tile = parameters->POC[numpocs_tile].tile;
+ numpocs_tile++;
+ }
+ }
+ tcp->numpocs = numpocs_tile -1 ;
+ }else{
+ tcp->numpocs = 0;
+ }
+
+ tcp->tccps = (opj_tccp_t*) opj_calloc(image->numcomps, sizeof(opj_tccp_t));
+
+ for (i = 0; i < image->numcomps; i++) {
+ opj_tccp_t *tccp = &tcp->tccps[i];
+ tccp->csty = parameters->csty & 0x01; /* 0 => one precinct || 1 => custom precinct */
+ tccp->numresolutions = parameters->numresolution;
+ tccp->cblkw = int_floorlog2(parameters->cblockw_init);
+ tccp->cblkh = int_floorlog2(parameters->cblockh_init);
+ tccp->cblksty = parameters->mode;
+ tccp->qmfbid = parameters->irreversible ? 0 : 1;
+ tccp->qntsty = parameters->irreversible ? J2K_CCP_QNTSTY_SEQNT : J2K_CCP_QNTSTY_NOQNT;
+ tccp->numgbits = 2;
+ if (i == parameters->roi_compno) {
+ tccp->roishift = parameters->roi_shift;
+ } else {
+ tccp->roishift = 0;
+ }
+
+ if(parameters->cp_cinema)
+ {
+ //Precinct size for lowest frequency subband=128
+ tccp->prcw[0] = 7;
+ tccp->prch[0] = 7;
+ //Precinct size at all other resolutions = 256
+ for (j = 1; j < tccp->numresolutions; j++) {
+ tccp->prcw[j] = 8;
+ tccp->prch[j] = 8;
+ }
+ }else{
+ if (parameters->csty & J2K_CCP_CSTY_PRT) {
+ int p = 0;
+ for (j = tccp->numresolutions - 1; j >= 0; j--) {
+ if (p < parameters->res_spec) {
+
+ if (parameters->prcw_init[p] < 1) {
+ tccp->prcw[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(parameters->prcw_init[p]);
+ }
+
+ if (parameters->prch_init[p] < 1) {
+ tccp->prch[j] = 1;
+ }else {
+ tccp->prch[j] = int_floorlog2(parameters->prch_init[p]);
+ }
+
+ } else {
+ int res_spec = parameters->res_spec;
+ int size_prcw = parameters->prcw_init[res_spec - 1] >> (p - (res_spec - 1));
+ int size_prch = parameters->prch_init[res_spec - 1] >> (p - (res_spec - 1));
+
+ if (size_prcw < 1) {
+ tccp->prcw[j] = 1;
+ } else {
+ tccp->prcw[j] = int_floorlog2(size_prcw);
+ }
+
+ if (size_prch < 1) {
+ tccp->prch[j] = 1;
+ } else {
+ tccp->prch[j] = int_floorlog2(size_prch);
+ }
+ }
+ p++;
+ /*printf("\nsize precinct for level %d : %d,%d\n", j,tccp->prcw[j], tccp->prch[j]); */
+ } //end for
+ } else {
+ for (j = 0; j < tccp->numresolutions; j++) {
+ tccp->prcw[j] = 15;
+ tccp->prch[j] = 15;
+ }
+ }
+ }
+
+ dwt_calc_explicit_stepsizes(tccp, image->comps[i].prec);
+ }
+ }
+}
+
+bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+ int tileno, compno;
+ opj_cp_t *cp = NULL;
+
+ opj_tcd_t *tcd = NULL; /* TCD component */
+
+ j2k->cio = cio;
+ j2k->image = image;
+
+ cp = j2k->cp;
+
+ /* j2k_dump_cp(stdout, image, cp); */
+
+ /* INDEX >> */
+ j2k->cstr_info = cstr_info;
+ if (cstr_info) {
+ int compno;
+ cstr_info->tile = (opj_tile_info_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tile_info_t));
+ cstr_info->image_w = image->x1 - image->x0;
+ cstr_info->image_h = image->y1 - image->y0;
+ cstr_info->prog = (&cp->tcps[0])->prg;
+ cstr_info->tw = cp->tw;
+ cstr_info->th = cp->th;
+ cstr_info->tile_x = cp->tdx; /* new version parser */
+ cstr_info->tile_y = cp->tdy; /* new version parser */
+ cstr_info->tile_Ox = cp->tx0; /* new version parser */
+ cstr_info->tile_Oy = cp->ty0; /* new version parser */
+ cstr_info->numcomps = image->numcomps;
+ cstr_info->numlayers = (&cp->tcps[0])->numlayers;
+ cstr_info->numdecompos = (int*) opj_malloc(image->numcomps * sizeof(int));
+ for (compno=0; compno < image->numcomps; compno++) {
+ cstr_info->numdecompos[compno] = (&cp->tcps[0])->tccps->numresolutions - 1;
+ }
+ cstr_info->D_max = 0.0; /* ADD Marcela */
+ cstr_info->main_head_start = cio_tell(cio); /* position of SOC */
+ cstr_info->maxmarknum = 100;
+ cstr_info->marker = (opj_marker_info_t *) opj_malloc(cstr_info->maxmarknum * sizeof(opj_marker_info_t));
+ cstr_info->marknum = 0;
+ }
+ /* << INDEX */
+
+ j2k_write_soc(j2k);
+ j2k_write_siz(j2k);
+ j2k_write_cod(j2k);
+ j2k_write_qcd(j2k);
+
+ if(cp->cinema){
+ for (compno = 1; compno < image->numcomps; compno++) {
+ j2k_write_coc(j2k, compno);
+ j2k_write_qcc(j2k, compno);
+ }
+ }
+
+ for (compno = 0; compno < image->numcomps; compno++) {
+ opj_tcp_t *tcp = &cp->tcps[0];
+ if (tcp->tccps[compno].roishift)
+ j2k_write_rgn(j2k, compno, 0);
+ }
+ if (cp->comment != NULL) {
+ j2k_write_com(j2k);
+ }
+
+ j2k->totnum_tp = j2k_calculate_tp(cp,image->numcomps,image,j2k);
+ /* TLM Marker*/
+ if(cp->cinema){
+ j2k_write_tlm(j2k);
+ if (cp->cinema == CINEMA4K_24) {
+ j2k_write_poc(j2k);
+ }
+ }
+
+ /* uncomment only for testing JPSEC marker writing */
+ /* j2k_write_sec(j2k); */
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->main_head_end = cio_tell(cio) - 1;
+ }
+ /* << INDEX */
+ /**** Main Header ENDS here ***/
+
+ /* create the tile encoder */
+ tcd = tcd_create(j2k->cinfo);
+
+ /* encode each tile */
+ for (tileno = 0; tileno < cp->tw * cp->th; tileno++) {
+ int pino;
+ int tilepartno=0;
+ /* UniPG>> */
+ int acc_pack_num = 0;
+ /* <<UniPG */
+
+
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ opj_event_msg(j2k->cinfo, EVT_INFO, "tile number %d / %d\n", tileno + 1, cp->tw * cp->th);
+
+ j2k->curtileno = tileno;
+ j2k->cur_tp_num = 0;
+ tcd->cur_totnum_tp = j2k->cur_totnum_tp[j2k->curtileno];
+ /* initialisation before tile encoding */
+ if (tileno == 0) {
+ tcd_malloc_encode(tcd, image, cp, j2k->curtileno);
+ } else {
+ tcd_init_encode(tcd, image, cp, j2k->curtileno);
+ }
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].start_pos = cio_tell(cio) + j2k->pos_correction;
+ }
+ /* << INDEX */
+
+ for(pino = 0; pino <= tcp->numpocs; pino++) {
+ int tot_num_tp;
+ tcd->cur_pino=pino;
+
+ /*Get number of tile parts*/
+ tot_num_tp = j2k_get_num_tp(cp,pino,tileno);
+ tcd->tp_pos = cp->tp_pos;
+
+ for(tilepartno = 0; tilepartno < tot_num_tp ; tilepartno++){
+ j2k->tp_num = tilepartno;
+ /* INDEX >> */
+ if(cstr_info)
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pos =
+ cio_tell(cio) + j2k->pos_correction;
+ /* << INDEX */
+ j2k_write_sot(j2k);
+
+ if(j2k->cur_tp_num == 0 && cp->cinema == 0){
+ for (compno = 1; compno < image->numcomps; compno++) {
+ j2k_write_coc(j2k, compno);
+ j2k_write_qcc(j2k, compno);
+ }
+ if (cp->tcps[tileno].numpocs) {
+ j2k_write_poc(j2k);
+ }
+ }
+
+ /* INDEX >> */
+ if(cstr_info)
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_header =
+ cio_tell(cio) + j2k->pos_correction + 1;
+ /* << INDEX */
+
+ j2k_write_sod(j2k, tcd);
+
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_end_pos =
+ cio_tell(cio) + j2k->pos_correction - 1;
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_start_pack =
+ acc_pack_num;
+ cstr_info->tile[j2k->curtileno].tp[j2k->cur_tp_num].tp_numpacks =
+ cstr_info->packno - acc_pack_num;
+ acc_pack_num = cstr_info->packno;
+ }
+ /* << INDEX */
+
+ j2k->cur_tp_num++;
+ }
+ }
+ if(cstr_info) {
+ cstr_info->tile[j2k->curtileno].end_pos = cio_tell(cio) + j2k->pos_correction - 1;
+ }
+
+
+ /*
+ if (tile->PPT) { // BAD PPT !!!
+ FILE *PPT_file;
+ int i;
+ PPT_file=fopen("PPT","rb");
+ fprintf(stderr,"%c%c%c%c",255,97,tile->len_ppt/256,tile->len_ppt%256);
+ for (i=0;i<tile->len_ppt;i++) {
+ unsigned char elmt;
+ fread(&elmt, 1, 1, PPT_file);
+ fwrite(&elmt,1,1,f);
+ }
+ fclose(PPT_file);
+ unlink("PPT");
+ }
+ */
+
+ }
+
+ /* destroy the tile encoder */
+ tcd_free_encode(tcd);
+ tcd_destroy(tcd);
+
+ opj_free(j2k->cur_totnum_tp);
+
+ j2k_write_eoc(j2k);
+
+ if(cstr_info) {
+ cstr_info->codestream_size = cio_tell(cio) + j2k->pos_correction;
+ /* UniPG>> */
+ /* The following adjustment is done to adjust the codestream size */
+ /* if SOD is not at 0 in the buffer. Useful in case of JP2, where */
+ /* the first bunch of bytes is not in the codestream */
+ cstr_info->codestream_size -= cstr_info->main_head_start;
+ /* <<UniPG */
+ }
+
+#ifdef USE_JPWL
+ /*
+ preparation of JPWL marker segments
+ */
+ if(cp->epc_on) {
+
+ /* encode according to JPWL */
+ jpwl_encode(j2k, cio, image);
+
+ }
+#endif /* USE_JPWL */
+
+ return true;
+}
+
+
+
+
+
+
diff --git a/Source/LibOpenJPEG/j2k.h b/Source/LibOpenJPEG/j2k.h
new file mode 100644
index 0000000..5599be4
--- /dev/null
+++ b/Source/LibOpenJPEG/j2k.h
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __J2K_H
+#define __J2K_H
+/**
+@file j2k.h
+@brief The JPEG-2000 Codestream Reader/Writer (J2K)
+
+The functions in J2K.C have for goal to read/write the several parts of the codestream: markers and data.
+*/
+
+/** @defgroup J2K J2K - JPEG-2000 codestream reader/writer */
+/*@{*/
+
+#define J2K_CP_CSTY_PRT 0x01
+#define J2K_CP_CSTY_SOP 0x02
+#define J2K_CP_CSTY_EPH 0x04
+#define J2K_CCP_CSTY_PRT 0x01
+#define J2K_CCP_CBLKSTY_LAZY 0x01
+#define J2K_CCP_CBLKSTY_RESET 0x02
+#define J2K_CCP_CBLKSTY_TERMALL 0x04
+#define J2K_CCP_CBLKSTY_VSC 0x08
+#define J2K_CCP_CBLKSTY_PTERM 0x10
+#define J2K_CCP_CBLKSTY_SEGSYM 0x20
+#define J2K_CCP_QNTSTY_NOQNT 0
+#define J2K_CCP_QNTSTY_SIQNT 1
+#define J2K_CCP_QNTSTY_SEQNT 2
+
+/* ----------------------------------------------------------------------- */
+
+#define J2K_MS_SOC 0xff4f /**< SOC marker value */
+#define J2K_MS_SOT 0xff90 /**< SOT marker value */
+#define J2K_MS_SOD 0xff93 /**< SOD marker value */
+#define J2K_MS_EOC 0xffd9 /**< EOC marker value */
+#define J2K_MS_SIZ 0xff51 /**< SIZ marker value */
+#define J2K_MS_COD 0xff52 /**< COD marker value */
+#define J2K_MS_COC 0xff53 /**< COC marker value */
+#define J2K_MS_RGN 0xff5e /**< RGN marker value */
+#define J2K_MS_QCD 0xff5c /**< QCD marker value */
+#define J2K_MS_QCC 0xff5d /**< QCC marker value */
+#define J2K_MS_POC 0xff5f /**< POC marker value */
+#define J2K_MS_TLM 0xff55 /**< TLM marker value */
+#define J2K_MS_PLM 0xff57 /**< PLM marker value */
+#define J2K_MS_PLT 0xff58 /**< PLT marker value */
+#define J2K_MS_PPM 0xff60 /**< PPM marker value */
+#define J2K_MS_PPT 0xff61 /**< PPT marker value */
+#define J2K_MS_SOP 0xff91 /**< SOP marker value */
+#define J2K_MS_EPH 0xff92 /**< EPH marker value */
+#define J2K_MS_CRG 0xff63 /**< CRG marker value */
+#define J2K_MS_COM 0xff64 /**< COM marker value */
+/* UniPG>> */
+#ifdef USE_JPWL
+#define J2K_MS_EPC 0xff68 /**< EPC marker value (Part 11: JPEG 2000 for Wireless) */
+#define J2K_MS_EPB 0xff66 /**< EPB marker value (Part 11: JPEG 2000 for Wireless) */
+#define J2K_MS_ESD 0xff67 /**< ESD marker value (Part 11: JPEG 2000 for Wireless) */
+#define J2K_MS_RED 0xff69 /**< RED marker value (Part 11: JPEG 2000 for Wireless) */
+#endif /* USE_JPWL */
+#ifdef USE_JPSEC
+#define J2K_MS_SEC 0xff65 /**< SEC marker value (Part 8: Secure JPEG 2000) */
+#define J2K_MS_INSEC 0xff94 /**< INSEC marker value (Part 8: Secure JPEG 2000) */
+#endif /* USE_JPSEC */
+/* <<UniPG */
+
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Values that specify the status of the decoding process when decoding the main header.
+These values may be combined with a | operator.
+*/
+typedef enum J2K_STATUS {
+ J2K_STATE_MHSOC = 0x0001, /**< a SOC marker is expected */
+ J2K_STATE_MHSIZ = 0x0002, /**< a SIZ marker is expected */
+ J2K_STATE_MH = 0x0004, /**< the decoding process is in the main header */
+ J2K_STATE_TPHSOT = 0x0008, /**< the decoding process is in a tile part header and expects a SOT marker */
+ J2K_STATE_TPH = 0x0010, /**< the decoding process is in a tile part header */
+ J2K_STATE_MT = 0x0020, /**< the EOC marker has just been read */
+ J2K_STATE_NEOC = 0x0040, /**< the decoding process must not expect a EOC marker because the codestream is truncated */
+ J2K_STATE_ERR = 0x0080 /**< the decoding process has encountered an error */
+} J2K_STATUS;
+
+/* ----------------------------------------------------------------------- */
+
+/**
+T2 encoding mode
+*/
+typedef enum T2_MODE {
+ THRESH_CALC = 0, /** Function called in Rate allocation process*/
+ FINAL_PASS = 1 /** Function called in Tier 2 process*/
+}J2K_T2_MODE;
+
+/**
+Quantization stepsize
+*/
+typedef struct opj_stepsize {
+ /** exponent */
+ int expn;
+ /** mantissa */
+ int mant;
+} opj_stepsize_t;
+
+/**
+Tile-component coding parameters
+*/
+typedef struct opj_tccp {
+ /** coding style */
+ int csty;
+ /** number of resolutions */
+ int numresolutions;
+ /** code-blocks width */
+ int cblkw;
+ /** code-blocks height */
+ int cblkh;
+ /** code-block coding style */
+ int cblksty;
+ /** discrete wavelet transform identifier */
+ int qmfbid;
+ /** quantisation style */
+ int qntsty;
+ /** stepsizes used for quantization */
+ opj_stepsize_t stepsizes[J2K_MAXBANDS];
+ /** number of guard bits */
+ int numgbits;
+ /** Region Of Interest shift */
+ int roishift;
+ /** precinct width */
+ int prcw[J2K_MAXRLVLS];
+ /** precinct height */
+ int prch[J2K_MAXRLVLS];
+} opj_tccp_t;
+
+/**
+Tile coding parameters :
+this structure is used to store coding/decoding parameters common to all
+tiles (information like COD, COC in main header)
+*/
+typedef struct opj_tcp {
+ /** 1 : first part-tile of a tile */
+ int first;
+ /** coding style */
+ int csty;
+ /** progression order */
+ OPJ_PROG_ORDER prg;
+ /** number of layers */
+ int numlayers;
+ /** multi-component transform identifier */
+ int mct;
+ /** rates of layers */
+ float rates[100];
+ /** number of progression order changes */
+ int numpocs;
+ /** indicates if a POC marker has been used O:NO, 1:YES */
+ int POC;
+ /** progression order changes */
+ opj_poc_t pocs[32];
+ /** packet header store there for futur use in t2_decode_packet */
+ unsigned char *ppt_data;
+ /** pointer remaining on the first byte of the first header if ppt is used */
+ unsigned char *ppt_data_first;
+ /** If ppt == 1 --> there was a PPT marker for the present tile */
+ int ppt;
+ /** used in case of multiple marker PPT (number of info already stored) */
+ int ppt_store;
+ /** ppmbug1 */
+ int ppt_len;
+ /** add fixed_quality */
+ float distoratio[100];
+ /** tile-component coding parameters */
+ opj_tccp_t *tccps;
+} opj_tcp_t;
+
+/**
+Coding parameters
+*/
+typedef struct opj_cp {
+ /** Digital cinema profile*/
+ OPJ_CINEMA_MODE cinema;
+ /** Maximum rate for each component. If == 0, component size limitation is not considered */
+ int max_comp_size;
+ /** Size of the image in bits*/
+ int img_size;
+ /** Rsiz*/
+ OPJ_RSIZ_CAPABILITIES rsiz;
+ /** Enabling Tile part generation*/
+ char tp_on;
+ /** Flag determining tile part generation*/
+ char tp_flag;
+ /** Position of tile part flag in progression order*/
+ int tp_pos;
+ /** allocation by rate/distortion */
+ int disto_alloc;
+ /** allocation by fixed layer */
+ int fixed_alloc;
+ /** add fixed_quality */
+ int fixed_quality;
+ /** if != 0, then original dimension divided by 2^(reduce); if == 0 or not used, image is decoded to the full resolution */
+ int reduce;
+ /** if != 0, then only the first "layer" layers are decoded; if == 0 or not used, all the quality layers are decoded */
+ int layer;
+ /** if == NO_LIMITATION, decode entire codestream; if == LIMIT_TO_MAIN_HEADER then only decode the main header */
+ OPJ_LIMIT_DECODING limit_decoding;
+ /** XTOsiz */
+ int tx0;
+ /** YTOsiz */
+ int ty0;
+ /** XTsiz */
+ int tdx;
+ /** YTsiz */
+ int tdy;
+ /** comment for coding */
+ char *comment;
+ /** number of tiles in width */
+ int tw;
+ /** number of tiles in heigth */
+ int th;
+ /** ID number of the tiles present in the codestream */
+ int *tileno;
+ /** size of the vector tileno */
+ int tileno_size;
+ /** packet header store there for futur use in t2_decode_packet */
+ unsigned char *ppm_data;
+ /** pointer remaining on the first byte of the first header if ppm is used */
+ unsigned char *ppm_data_first;
+ /** if ppm == 1 --> there was a PPM marker for the present tile */
+ int ppm;
+ /** use in case of multiple marker PPM (number of info already store) */
+ int ppm_store;
+ /** use in case of multiple marker PPM (case on non-finished previous info) */
+ int ppm_previous;
+ /** ppmbug1 */
+ int ppm_len;
+ /** tile coding parameters */
+ opj_tcp_t *tcps;
+ /** fixed layer */
+ int *matrice;
+/* UniPG>> */
+#ifdef USE_JPWL
+ /** enables writing of EPC in MH, thus activating JPWL */
+ bool epc_on;
+ /** enables writing of EPB, in case of activated JPWL */
+ bool epb_on;
+ /** enables writing of ESD, in case of activated JPWL */
+ bool esd_on;
+ /** enables writing of informative techniques of ESD, in case of activated JPWL */
+ bool info_on;
+ /** enables writing of RED, in case of activated JPWL */
+ bool red_on;
+ /** error protection method for MH (0,1,16,32,37-128) */
+ int hprot_MH;
+ /** tile number of header protection specification (>=0) */
+ int hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS];
+ /** error protection methods for TPHs (0,1,16,32,37-128) */
+ int hprot_TPH[JPWL_MAX_NO_TILESPECS];
+ /** tile number of packet protection specification (>=0) */
+ int pprot_tileno[JPWL_MAX_NO_PACKSPECS];
+ /** packet number of packet protection specification (>=0) */
+ int pprot_packno[JPWL_MAX_NO_PACKSPECS];
+ /** error protection methods for packets (0,1,16,32,37-128) */
+ int pprot[JPWL_MAX_NO_PACKSPECS];
+ /** enables writing of ESD, (0/2/4 bytes) */
+ int sens_size;
+ /** sensitivity addressing size (0=auto/2/4 bytes) */
+ int sens_addr;
+ /** sensitivity range (0-3) */
+ int sens_range;
+ /** sensitivity method for MH (-1,0-7) */
+ int sens_MH;
+ /** tile number of sensitivity specification (>=0) */
+ int sens_TPH_tileno[JPWL_MAX_NO_TILESPECS];
+ /** sensitivity methods for TPHs (-1,0-7) */
+ int sens_TPH[JPWL_MAX_NO_TILESPECS];
+ /** enables JPWL correction at the decoder */
+ bool correct;
+ /** expected number of components at the decoder */
+ int exp_comps;
+ /** maximum number of tiles at the decoder */
+ int max_tiles;
+#endif /* USE_JPWL */
+/* <<UniPG */
+} opj_cp_t;
+
+/**
+JPEG-2000 codestream reader/writer
+*/
+typedef struct opj_j2k {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** locate in which part of the codestream the decoder is (main header, tile header, end) */
+ int state;
+ /** number of the tile curently concern by coding/decoding */
+ int curtileno;
+ /** Tile part number*/
+ int tp_num;
+ /** Tilepart number currently coding*/
+ int cur_tp_num;
+ /** Total number of tileparts of the current tile*/
+ int *cur_totnum_tp;
+ /**
+ locate the start position of the TLM marker
+ after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
+ */
+ int tlm_start;
+ /** Total num of tile parts in whole image = num tiles* num tileparts in each tile*/
+ /** used in TLMmarker*/
+ int totnum_tp;
+ /**
+ locate the position of the end of the tile in the codestream,
+ used to detect a truncated codestream (in j2k_read_sod)
+ */
+ unsigned char *eot;
+ /**
+ locate the start position of the SOT marker of the current coded tile:
+ after encoding the tile, a jump (in j2k_write_sod) is done to the SOT marker to store the value of its length.
+ */
+ int sot_start;
+ int sod_start;
+ /**
+ as the J2K-file is written in several parts during encoding,
+ it enables to make the right correction in position return by cio_tell
+ */
+ int pos_correction;
+ /** array used to store the data of each tile */
+ unsigned char **tile_data;
+ /** array used to store the length of each tile */
+ int *tile_len;
+ /**
+ decompression only :
+ store decoding parameters common to all tiles (information like COD, COC in main header)
+ */
+ opj_tcp_t *default_tcp;
+ /** pointer to the encoded / decoded image */
+ opj_image_t *image;
+ /** pointer to the coding parameters */
+ opj_cp_t *cp;
+ /** helper used to write the index file */
+ opj_codestream_info_t *cstr_info;
+ /** pointer to the byte i/o stream */
+ opj_cio_t *cio;
+} opj_j2k_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Creates a J2K decompression structure
+@param cinfo Codec context info
+@return Returns a handle to a J2K decompressor if successful, returns NULL otherwise
+*/
+opj_j2k_t* j2k_create_decompress(opj_common_ptr cinfo);
+/**
+Destroy a J2K decompressor handle
+@param j2k J2K decompressor handle to destroy
+*/
+void j2k_destroy_decompress(opj_j2k_t *j2k);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in j2k->cp.
+@param j2k J2K decompressor handle
+@param parameters decompression parameters
+*/
+void j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 codestream
+@param j2k J2K decompressor handle
+@param cio Input buffer stream
+@param cstr_info Codestream information structure if required, NULL otherwise
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
+/**
+Decode an image form a JPT-stream (JPEG 2000, JPIP)
+@param j2k J2K decompressor handle
+@param cio Input buffer stream
+@param cstr_info Codestream information structure if required, NULL otherwise
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* j2k_decode_jpt_stream(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
+/**
+Creates a J2K compression structure
+@param cinfo Codec context info
+@return Returns a handle to a J2K compressor if successful, returns NULL otherwise
+*/
+opj_j2k_t* j2k_create_compress(opj_common_ptr cinfo);
+/**
+Destroy a J2K compressor handle
+@param j2k J2K compressor handle to destroy
+*/
+void j2k_destroy_compress(opj_j2k_t *j2k);
+/**
+Setup the encoder parameters using the current image and using user parameters.
+Coding parameters are returned in j2k->cp.
+@param j2k J2K compressor handle
+@param parameters compression parameters
+@param image input filled image
+*/
+void j2k_setup_encoder(opj_j2k_t *j2k, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Converts an enum type progression order to string type
+*/
+char *j2k_convert_progression_order(OPJ_PROG_ORDER prg_order);
+/**
+Encode an image into a JPEG-2000 codestream
+@param j2k J2K compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param cstr_info Codestream information structure if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+bool j2k_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __J2K_H */
diff --git a/Source/LibOpenJPEG/j2k_lib.c b/Source/LibOpenJPEG/j2k_lib.c
new file mode 100644
index 0000000..91aee00
--- /dev/null
+++ b/Source/LibOpenJPEG/j2k_lib.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/times.h>
+#endif /* WIN32 */
+#include "opj_includes.h"
+
+double opj_clock(void) {
+#ifdef WIN32
+ /* WIN32: use QueryPerformance (very accurate) */
+ LARGE_INTEGER freq , t ;
+ /* freq is the clock speed of the CPU */
+ QueryPerformanceFrequency(&freq) ;
+ /* cout << "freq = " << ((double) freq.QuadPart) << endl; */
+ /* t is the high resolution performance counter (see MSDN) */
+ QueryPerformanceCounter ( & t ) ;
+ return ( t.QuadPart /(double) freq.QuadPart ) ;
+#else
+ /* Unix or Linux: use resource usage */
+ struct rusage t;
+ double procTime;
+ /* (1) Get the rusage data structure at this moment (man getrusage) */
+ getrusage(0,&t);
+ /* (2) What is the elapsed time ? - CPU time = User time + System time */
+ /* (2a) Get the seconds */
+ procTime = t.ru_utime.tv_sec + t.ru_stime.tv_sec;
+ /* (2b) More precisely! Get the microseconds part ! */
+ return ( procTime + (t.ru_utime.tv_usec + t.ru_stime.tv_usec) * 1e-6 ) ;
+#endif
+}
+
diff --git a/Source/LibOpenJPEG/j2k_lib.h b/Source/LibOpenJPEG/j2k_lib.h
new file mode 100644
index 0000000..7df4d36
--- /dev/null
+++ b/Source/LibOpenJPEG/j2k_lib.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __J2K_LIB_H
+#define __J2K_LIB_H
+/**
+@file j2k_lib.h
+@brief Internal functions
+
+The functions in J2K_LIB.C are internal utilities mainly used for timing.
+*/
+
+/** @defgroup MISC MISC - Miscellaneous internal functions */
+/*@{*/
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Difference in successive opj_clock() calls tells you the elapsed time
+@return Returns time in seconds
+*/
+double opj_clock(void);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __J2K_LIB_H */
+
diff --git a/Source/LibOpenJPEG/jp2.c b/Source/LibOpenJPEG/jp2.c
new file mode 100644
index 0000000..b2831cf
--- /dev/null
+++ b/Source/LibOpenJPEG/jp2.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Read box headers
+@param cinfo Codec context info
+@param cio Input stream
+@param box
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box);
+/*static void jp2_write_url(opj_cio_t *cio, char *Idx_file);*/
+/**
+Read the IHDR box - Image Header box
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio);
+static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio);
+static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio);
+static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Write the FTYP box - File type box
+@param jp2 JP2 handle
+@param cio Output buffer stream
+*/
+static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Read the FTYP box - File type box
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio);
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
+static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset);
+static void jp2_write_jp(opj_cio_t *cio);
+/**
+Read the JP box - JPEG 2000 signature
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Decode the structure of a JP2 file
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box) {
+ box->init_pos = cio_tell(cio);
+ box->length = cio_read(cio, 4);
+ box->type = cio_read(cio, 4);
+ if (box->length == 1) {
+ if (cio_read(cio, 4) != 0) {
+ opj_event_msg(cinfo, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n");
+ return false;
+ }
+ box->length = cio_read(cio, 4);
+ if (box->length == 0)
+ box->length = cio_numbytesleft(cio) + 12;
+ }
+ else if (box->length == 0) {
+ box->length = cio_numbytesleft(cio) + 8;
+ }
+
+ return true;
+}
+
+#if 0
+static void jp2_write_url(opj_cio_t *cio, char *Idx_file) {
+ unsigned int i;
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_URL, 4); /* DBTL */
+ cio_write(cio, 0, 1); /* VERS */
+ cio_write(cio, 0, 3); /* FLAG */
+
+ if(Idx_file) {
+ for (i = 0; i < strlen(Idx_file); i++) {
+ cio_write(cio, Idx_file[i], 1);
+ }
+ }
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+#endif
+
+static bool jp2_read_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ if (JP2_IHDR != box.type) {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected IHDR Marker\n");
+ return false;
+ }
+
+ jp2->h = cio_read(cio, 4); /* HEIGHT */
+ jp2->w = cio_read(cio, 4); /* WIDTH */
+ jp2->numcomps = cio_read(cio, 2); /* NC */
+ jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
+
+ jp2->bpc = cio_read(cio, 1); /* BPC */
+
+ jp2->C = cio_read(cio, 1); /* C */
+ jp2->UnkC = cio_read(cio, 1); /* UnkC */
+ jp2->IPR = cio_read(cio, 1); /* IPR */
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with IHDR Box\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void jp2_write_ihdr(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_IHDR, 4); /* IHDR */
+
+ cio_write(cio, jp2->h, 4); /* HEIGHT */
+ cio_write(cio, jp2->w, 4); /* WIDTH */
+ cio_write(cio, jp2->numcomps, 2); /* NC */
+
+ cio_write(cio, jp2->bpc, 1); /* BPC */
+
+ cio_write(cio, jp2->C, 1); /* C : Always 7 */
+ cio_write(cio, jp2->UnkC, 1); /* UnkC, colorspace unknown */
+ cio_write(cio, jp2->IPR, 1); /* IPR, no intellectual property */
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+static void jp2_write_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) {
+ unsigned int i;
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_BPCC, 4); /* BPCC */
+
+ for (i = 0; i < jp2->numcomps; i++) {
+ cio_write(cio, jp2->comps[i].bpcc, 1);
+ }
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+
+static bool jp2_read_bpcc(opj_jp2_t *jp2, opj_cio_t *cio) {
+ unsigned int i;
+ opj_jp2_box_t box;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ if (JP2_BPCC != box.type) {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected BPCC Marker\n");
+ return false;
+ }
+
+ for (i = 0; i < jp2->numcomps; i++) {
+ jp2->comps[i].bpcc = cio_read(cio, 1);
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n");
+ return false;
+ }
+
+ return true;
+}
+
+static void jp2_write_colr(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_COLR, 4); /* COLR */
+
+ cio_write(cio, jp2->meth, 1); /* METH */
+ cio_write(cio, jp2->precedence, 1); /* PRECEDENCE */
+ cio_write(cio, jp2->approx, 1); /* APPROX */
+
+ if (jp2->meth == 1) {
+ cio_write(cio, jp2->enumcs, 4); /* EnumCS */
+ } else {
+ cio_write(cio, 0, 1); /* PROFILE (??) */
+ }
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_colr(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+ int skip_len;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ do {
+ if (JP2_COLR != box.type) {
+ cio_skip(cio, box.length - 8);
+ jp2_read_boxhdr(cinfo, cio, &box);
+ }
+ } while(JP2_COLR != box.type);
+
+ jp2->meth = cio_read(cio, 1); /* METH */
+ jp2->precedence = cio_read(cio, 1); /* PRECEDENCE */
+ jp2->approx = cio_read(cio, 1); /* APPROX */
+
+ if (jp2->meth == 1) {
+ jp2->enumcs = cio_read(cio, 4); /* EnumCS */
+ } else {
+ /* skip PROFILE */
+ skip_len = box.init_pos + box.length - cio_tell(cio);
+ if (skip_len < 0) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H box size\n");
+ return false;
+ }
+ cio_skip(cio, box.init_pos + box.length - cio_tell(cio));
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with BPCC Box\n");
+ return false;
+ }
+ return true;
+}
+
+void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_JP2H, 4); /* JP2H */
+
+ jp2_write_ihdr(jp2, cio);
+
+ if (jp2->bpc == 255) {
+ jp2_write_bpcc(jp2, cio);
+ }
+ jp2_write_colr(jp2, cio);
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+ int skip_len;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ do {
+ if (JP2_JP2H != box.type) {
+ if (box.type == JP2_JP2C) {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected JP2H Marker\n");
+ return false;
+ }
+ cio_skip(cio, box.length - 8);
+ jp2_read_boxhdr(cinfo, cio, &box);
+ }
+ } while(JP2_JP2H != box.type);
+
+ if (!jp2_read_ihdr(jp2, cio))
+ return false;
+
+ if (jp2->bpc == 255) {
+ if (!jp2_read_bpcc(jp2, cio))
+ return false;
+ }
+ if (!jp2_read_colr(jp2, cio))
+ return false;
+
+ skip_len = box.init_pos + box.length - cio_tell(cio);
+ if (skip_len < 0) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with JP2H Box\n");
+ return false;
+ }
+ cio_skip(cio, box.init_pos + box.length - cio_tell(cio));
+
+ return true;
+}
+
+static void jp2_write_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
+ unsigned int i;
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_FTYP, 4); /* FTYP */
+
+ cio_write(cio, jp2->brand, 4); /* BR */
+ cio_write(cio, jp2->minversion, 4); /* MinV */
+
+ for (i = 0; i < jp2->numcl; i++) {
+ cio_write(cio, jp2->cl[i], 4); /* CL */
+ }
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_ftyp(opj_jp2_t *jp2, opj_cio_t *cio) {
+ int i;
+ opj_jp2_box_t box;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+
+ if (JP2_FTYP != box.type) {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected FTYP Marker\n");
+ return false;
+ }
+
+ jp2->brand = cio_read(cio, 4); /* BR */
+ jp2->minversion = cio_read(cio, 4); /* MinV */
+ jp2->numcl = (box.length - 16) / 4;
+ jp2->cl = (unsigned int *) opj_malloc(jp2->numcl * sizeof(unsigned int));
+
+ for (i = 0; i < (int)jp2->numcl; i++) {
+ jp2->cl[i] = cio_read(cio, 4); /* CLi */
+ }
+
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with FTYP Box\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int jp2_write_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+ unsigned int j2k_codestream_offset, j2k_codestream_length;
+ opj_jp2_box_t box;
+
+ opj_j2k_t *j2k = jp2->j2k;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_JP2C, 4); /* JP2C */
+
+ /* J2K encoding */
+ j2k_codestream_offset = cio_tell(cio);
+ if(!j2k_encode(j2k, cio, image, cstr_info)) {
+ opj_event_msg(j2k->cinfo, EVT_ERROR, "Failed to encode image\n");
+ return 0;
+ }
+ j2k_codestream_length = cio_tell(cio) - j2k_codestream_offset;
+
+ jp2->j2k_codestream_offset = j2k_codestream_offset;
+ jp2->j2k_codestream_length = j2k_codestream_length;
+
+ box.length = 8 + jp2->j2k_codestream_length;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+
+ return box.length;
+}
+
+static bool jp2_read_jp2c(opj_jp2_t *jp2, opj_cio_t *cio, unsigned int *j2k_codestream_length, unsigned int *j2k_codestream_offset) {
+ opj_jp2_box_t box;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ do {
+ if(JP2_JP2C != box.type) {
+ cio_skip(cio, box.length - 8);
+ jp2_read_boxhdr(cinfo, cio, &box);
+ }
+ } while(JP2_JP2C != box.type);
+
+ *j2k_codestream_offset = cio_tell(cio);
+ *j2k_codestream_length = box.length - 8;
+
+ return true;
+}
+
+static void jp2_write_jp(opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ box.init_pos = cio_tell(cio);
+ cio_skip(cio, 4);
+ cio_write(cio, JP2_JP, 4); /* JP2 signature */
+ cio_write(cio, 0x0d0a870a, 4);
+
+ box.length = cio_tell(cio) - box.init_pos;
+ cio_seek(cio, box.init_pos);
+ cio_write(cio, box.length, 4); /* L */
+ cio_seek(cio, box.init_pos + box.length);
+}
+
+static bool jp2_read_jp(opj_jp2_t *jp2, opj_cio_t *cio) {
+ opj_jp2_box_t box;
+
+ opj_common_ptr cinfo = jp2->cinfo;
+
+ jp2_read_boxhdr(cinfo, cio, &box);
+ if (JP2_JP != box.type) {
+ opj_event_msg(cinfo, EVT_ERROR, "Expected JP Marker\n");
+ return false;
+ }
+ if (0x0d0a870a != cio_read(cio, 4)) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with JP Marker\n");
+ return false;
+ }
+ if (cio_tell(cio) - box.init_pos != box.length) {
+ opj_event_msg(cinfo, EVT_ERROR, "Error with JP Box size\n");
+ return false;
+ }
+
+ return true;
+}
+
+
+static bool jp2_read_struct(opj_jp2_t *jp2, opj_cio_t *cio) {
+ if (!jp2_read_jp(jp2, cio))
+ return false;
+ if (!jp2_read_ftyp(jp2, cio))
+ return false;
+ if (!jp2_read_jp2h(jp2, cio))
+ return false;
+ if (!jp2_read_jp2c(jp2, cio, &jp2->j2k_codestream_length, &jp2->j2k_codestream_offset))
+ return false;
+
+ return true;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 decoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo) {
+ opj_jp2_t *jp2 = (opj_jp2_t*) opj_calloc(1, sizeof(opj_jp2_t));
+ if(jp2) {
+ jp2->cinfo = cinfo;
+ /* create the J2K codec */
+ jp2->j2k = j2k_create_decompress(cinfo);
+ if(jp2->j2k == NULL) {
+ jp2_destroy_decompress(jp2);
+ return NULL;
+ }
+ }
+ return jp2;
+}
+
+void jp2_destroy_decompress(opj_jp2_t *jp2) {
+ if(jp2) {
+ /* destroy the J2K codec */
+ j2k_destroy_decompress(jp2->j2k);
+
+ if(jp2->comps) {
+ opj_free(jp2->comps);
+ }
+ if(jp2->cl) {
+ opj_free(jp2->cl);
+ }
+ opj_free(jp2);
+ }
+}
+
+void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters) {
+ /* setup the J2K codec */
+ j2k_setup_decoder(jp2->j2k, parameters);
+ /* further JP2 initializations go here */
+}
+
+opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info) {
+ opj_common_ptr cinfo;
+ opj_image_t *image = NULL;
+
+ if(!jp2 || !cio) {
+ return NULL;
+ }
+
+ cinfo = jp2->cinfo;
+
+ /* JP2 decoding */
+ if(!jp2_read_struct(jp2, cio)) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to decode jp2 structure\n");
+ return NULL;
+ }
+
+ /* J2K decoding */
+ image = j2k_decode(jp2->j2k, cio, cstr_info);
+ if(!image) {
+ opj_event_msg(cinfo, EVT_ERROR, "Failed to decode J2K image\n");
+ return NULL;
+ }
+
+ /* Set Image Color Space */
+ if (jp2->enumcs == 16)
+ image->color_space = CLRSPC_SRGB;
+ else if (jp2->enumcs == 17)
+ image->color_space = CLRSPC_GRAY;
+ else if (jp2->enumcs == 18)
+ image->color_space = CLRSPC_SYCC;
+ else
+ image->color_space = CLRSPC_UNKNOWN;
+
+ return image;
+}
+
+/* ----------------------------------------------------------------------- */
+/* JP2 encoder interface */
+/* ----------------------------------------------------------------------- */
+
+opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo) {
+ opj_jp2_t *jp2 = (opj_jp2_t*)opj_malloc(sizeof(opj_jp2_t));
+ if(jp2) {
+ jp2->cinfo = cinfo;
+ /* create the J2K codec */
+ jp2->j2k = j2k_create_compress(cinfo);
+ if(jp2->j2k == NULL) {
+ jp2_destroy_compress(jp2);
+ return NULL;
+ }
+ }
+ return jp2;
+}
+
+void jp2_destroy_compress(opj_jp2_t *jp2) {
+ if(jp2) {
+ /* destroy the J2K codec */
+ j2k_destroy_compress(jp2->j2k);
+
+ if(jp2->comps) {
+ opj_free(jp2->comps);
+ }
+ if(jp2->cl) {
+ opj_free(jp2->cl);
+ }
+ opj_free(jp2);
+ }
+}
+
+void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image) {
+ int i;
+ int depth_0, sign;
+
+ if(!jp2 || !parameters || !image)
+ return;
+
+ /* setup the J2K codec */
+ /* ------------------- */
+
+ /* Check if number of components respects standard */
+ if (image->numcomps < 1 || image->numcomps > 16384) {
+ opj_event_msg(jp2->cinfo, EVT_ERROR, "Invalid number of components specified while setting up JP2 encoder\n");
+ return;
+ }
+
+ j2k_setup_encoder(jp2->j2k, parameters, image);
+
+ /* setup the JP2 codec */
+ /* ------------------- */
+
+ /* Profile box */
+
+ jp2->brand = JP2_JP2; /* BR */
+ jp2->minversion = 0; /* MinV */
+ jp2->numcl = 1;
+ jp2->cl = (unsigned int*) opj_malloc(jp2->numcl * sizeof(unsigned int));
+ jp2->cl[0] = JP2_JP2; /* CL0 : JP2 */
+
+ /* Image Header box */
+
+ jp2->numcomps = image->numcomps; /* NC */
+ jp2->comps = (opj_jp2_comps_t*) opj_malloc(jp2->numcomps * sizeof(opj_jp2_comps_t));
+ jp2->h = image->y1 - image->y0; /* HEIGHT */
+ jp2->w = image->x1 - image->x0; /* WIDTH */
+ /* BPC */
+ depth_0 = image->comps[0].prec - 1;
+ sign = image->comps[0].sgnd;
+ jp2->bpc = depth_0 + (sign << 7);
+ for (i = 1; i < image->numcomps; i++) {
+ int depth = image->comps[i].prec - 1;
+ sign = image->comps[i].sgnd;
+ if (depth_0 != depth)
+ jp2->bpc = 255;
+ }
+ jp2->C = 7; /* C : Always 7 */
+ jp2->UnkC = 0; /* UnkC, colorspace specified in colr box */
+ jp2->IPR = 0; /* IPR, no intellectual property */
+
+ /* BitsPerComponent box */
+
+ for (i = 0; i < image->numcomps; i++) {
+ jp2->comps[i].bpcc = image->comps[i].prec - 1 + (image->comps[i].sgnd << 7);
+ }
+
+ /* Colour Specification box */
+
+ if ((image->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) {
+ jp2->meth = 1; /* METH: Enumerated colourspace */
+ } else {
+ jp2->meth = 2; /* METH: Restricted ICC profile */
+ }
+ if (jp2->meth == 1) {
+ if (image->color_space == 1)
+ jp2->enumcs = 16; /* sRGB as defined by IEC 61966–2–1 */
+ else if (image->color_space == 2)
+ jp2->enumcs = 17; /* greyscale */
+ else if (image->color_space == 3)
+ jp2->enumcs = 18; /* YUV */
+ } else {
+ jp2->enumcs = 0; /* PROFILE (??) */
+ }
+ jp2->precedence = 0; /* PRECEDENCE */
+ jp2->approx = 0; /* APPROX */
+
+}
+
+bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+
+ /* JP2 encoding */
+
+ /* JPEG 2000 Signature box */
+ jp2_write_jp(cio);
+ /* File Type box */
+ jp2_write_ftyp(jp2, cio);
+ /* JP2 Header box */
+ jp2_write_jp2h(jp2, cio);
+
+ /* J2K encoding */
+
+ if(!jp2_write_jp2c(jp2, cio, image, cstr_info)) {
+ opj_event_msg(jp2->cinfo, EVT_ERROR, "Failed to encode image\n");
+ return false;
+ }
+
+ return true;
+}
+
+
diff --git a/Source/LibOpenJPEG/jp2.h b/Source/LibOpenJPEG/jp2.h
new file mode 100644
index 0000000..7e363be
--- /dev/null
+++ b/Source/LibOpenJPEG/jp2.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __JP2_H
+#define __JP2_H
+/**
+@file jp2.h
+@brief The JPEG-2000 file format Reader/Writer (JP2)
+
+*/
+
+/** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
+/*@{*/
+
+#define JPIP_JPIP 0x6a706970
+
+#define JP2_JP 0x6a502020 /**< JPEG 2000 signature box */
+#define JP2_FTYP 0x66747970 /**< File type box */
+#define JP2_JP2H 0x6a703268 /**< JP2 header box */
+#define JP2_IHDR 0x69686472 /**< Image header box */
+#define JP2_COLR 0x636f6c72 /**< Colour specification box */
+#define JP2_JP2C 0x6a703263 /**< Contiguous codestream box */
+#define JP2_URL 0x75726c20 /**< URL box */
+#define JP2_DBTL 0x6474626c /**< ??? */
+#define JP2_BPCC 0x62706363 /**< Bits per component box */
+#define JP2_JP2 0x6a703220 /**< File type fields */
+
+/* ----------------------------------------------------------------------- */
+
+/**
+JP2 component
+*/
+typedef struct opj_jp2_comps {
+ int depth;
+ int sgnd;
+ int bpcc;
+} opj_jp2_comps_t;
+
+/**
+JPEG-2000 file format reader/writer
+*/
+typedef struct opj_jp2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+ /** handle to the J2K codec */
+ opj_j2k_t *j2k;
+ unsigned int w;
+ unsigned int h;
+ unsigned int numcomps;
+ unsigned int bpc;
+ unsigned int C;
+ unsigned int UnkC;
+ unsigned int IPR;
+ unsigned int meth;
+ unsigned int approx;
+ unsigned int enumcs;
+ unsigned int precedence;
+ unsigned int brand;
+ unsigned int minversion;
+ unsigned int numcl;
+ unsigned int *cl;
+ opj_jp2_comps_t *comps;
+ unsigned int j2k_codestream_offset;
+ unsigned int j2k_codestream_length;
+} opj_jp2_t;
+
+/**
+JP2 Box
+*/
+typedef struct opj_jp2_box {
+ int length;
+ int type;
+ int init_pos;
+} opj_jp2_box_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Write the JP2H box - JP2 Header box (used in MJ2)
+@param jp2 JP2 handle
+@param cio Output buffer stream
+*/
+void jp2_write_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Read the JP2H box - JP2 Header box (used in MJ2)
+@param jp2 JP2 handle
+@param cio Input buffer stream
+@return Returns true if successful, returns false otherwise
+*/
+bool jp2_read_jp2h(opj_jp2_t *jp2, opj_cio_t *cio);
+/**
+Creates a JP2 decompression structure
+@param cinfo Codec context info
+@return Returns a handle to a JP2 decompressor if successful, returns NULL otherwise
+*/
+opj_jp2_t* jp2_create_decompress(opj_common_ptr cinfo);
+/**
+Destroy a JP2 decompressor handle
+@param jp2 JP2 decompressor handle to destroy
+*/
+void jp2_destroy_decompress(opj_jp2_t *jp2);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in jp2->j2k->cp.
+@param jp2 JP2 decompressor handle
+@param parameters decompression parameters
+*/
+void jp2_setup_decoder(opj_jp2_t *jp2, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 file stream
+@param jp2 JP2 decompressor handle
+@param cio Input buffer stream
+@param cstr_info Codestream information structure if required, NULL otherwise
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+opj_image_t* jp2_decode(opj_jp2_t *jp2, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
+/**
+Creates a JP2 compression structure
+@param cinfo Codec context info
+@return Returns a handle to a JP2 compressor if successful, returns NULL otherwise
+*/
+opj_jp2_t* jp2_create_compress(opj_common_ptr cinfo);
+/**
+Destroy a JP2 compressor handle
+@param jp2 JP2 compressor handle to destroy
+*/
+void jp2_destroy_compress(opj_jp2_t *jp2);
+/**
+Setup the encoder parameters using the current image and using user parameters.
+Coding parameters are returned in jp2->j2k->cp.
+@param jp2 JP2 compressor handle
+@param parameters compression parameters
+@param image input filled image
+*/
+void jp2_setup_encoder(opj_jp2_t *jp2, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Encode an image into a JPEG-2000 file stream
+@param jp2 JP2 compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param cstr_info Codestream information structure if required, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+bool jp2_encode(opj_jp2_t *jp2, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __JP2_H */
+
diff --git a/Source/LibOpenJPEG/jpt.c b/Source/LibOpenJPEG/jpt.c
new file mode 100644
index 0000000..a2566ea
--- /dev/null
+++ b/Source/LibOpenJPEG/jpt.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/*
+ * Read the information contains in VBAS [JPP/JPT stream message header]
+ * Store information (7 bits) in value
+ *
+ */
+unsigned int jpt_read_VBAS_info(opj_cio_t *cio, unsigned int value) {
+ unsigned char elmt;
+
+ elmt = cio_read(cio, 1);
+ while ((elmt >> 7) == 1) {
+ value = (value << 7);
+ value |= (elmt & 0x7f);
+ elmt = cio_read(cio, 1);
+ }
+ value = (value << 7);
+ value |= (elmt & 0x7f);
+
+ return value;
+}
+
+/*
+ * Initialize the value of the message header structure
+ *
+ */
+void jpt_init_msg_header(opj_jpt_msg_header_t * header) {
+ header->Id = 0; /* In-class Identifier */
+ header->last_byte = 0; /* Last byte information */
+ header->Class_Id = 0; /* Class Identifier */
+ header->CSn_Id = 0; /* CSn : index identifier */
+ header->Msg_offset = 0; /* Message offset */
+ header->Msg_length = 0; /* Message length */
+ header->Layer_nb = 0; /* Auxiliary for JPP case */
+}
+
+/*
+ * Re-initialize the value of the message header structure
+ *
+ * Only parameters always present in message header
+ *
+ */
+void jpt_reinit_msg_header(opj_jpt_msg_header_t * header) {
+ header->Id = 0; /* In-class Identifier */
+ header->last_byte = 0; /* Last byte information */
+ header->Msg_offset = 0; /* Message offset */
+ header->Msg_length = 0; /* Message length */
+}
+
+/*
+ * Read the message header for a JPP/JPT - stream
+ *
+ */
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header) {
+ unsigned char elmt, Class = 0, CSn = 0;
+ jpt_reinit_msg_header(header);
+
+ /* ------------- */
+ /* VBAS : Bin-ID */
+ /* ------------- */
+ elmt = cio_read(cio, 1);
+
+ /* See for Class and CSn */
+ switch ((elmt >> 5) & 0x03) {
+ case 0:
+ opj_event_msg(cinfo, EVT_ERROR, "Forbidden value encounter in message header !!\n");
+ break;
+ case 1:
+ Class = 0;
+ CSn = 0;
+ break;
+ case 2:
+ Class = 1;
+ CSn = 0;
+ break;
+ case 3:
+ Class = 1;
+ CSn = 1;
+ break;
+ default:
+ break;
+ }
+
+ /* see information on bits 'c' [p 10 : A.2.1 general, ISO/IEC FCD 15444-9] */
+ if (((elmt >> 4) & 0x01) == 1)
+ header->last_byte = 1;
+
+ /* In-class identifier */
+ header->Id |= (elmt & 0x0f);
+ if ((elmt >> 7) == 1)
+ header->Id = jpt_read_VBAS_info(cio, header->Id);
+
+ /* ------------ */
+ /* VBAS : Class */
+ /* ------------ */
+ if (Class == 1) {
+ header->Class_Id = 0;
+ header->Class_Id = jpt_read_VBAS_info(cio, header->Class_Id);
+ }
+
+ /* ---------- */
+ /* VBAS : CSn */
+ /* ---------- */
+ if (CSn == 1) {
+ header->CSn_Id = 0;
+ header->CSn_Id = jpt_read_VBAS_info(cio, header->CSn_Id);
+ }
+
+ /* ----------------- */
+ /* VBAS : Msg_offset */
+ /* ----------------- */
+ header->Msg_offset = jpt_read_VBAS_info(cio, header->Msg_offset);
+
+ /* ----------------- */
+ /* VBAS : Msg_length */
+ /* ----------------- */
+ header->Msg_length = jpt_read_VBAS_info(cio, header->Msg_length);
+
+ /* ---------- */
+ /* VBAS : Aux */
+ /* ---------- */
+ if ((header->Class_Id & 0x01) == 1) {
+ header->Layer_nb = 0;
+ header->Layer_nb = jpt_read_VBAS_info(cio, header->Layer_nb);
+ }
+}
diff --git a/Source/LibOpenJPEG/jpt.h b/Source/LibOpenJPEG/jpt.h
new file mode 100644
index 0000000..eb01f98
--- /dev/null
+++ b/Source/LibOpenJPEG/jpt.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __JPT_H
+#define __JPT_H
+/**
+@file jpt.h
+@brief JPT-stream reader (JPEG 2000, JPIP)
+
+JPT-stream functions are implemented in J2K.C.
+*/
+
+/**
+Message Header JPT stream structure
+*/
+typedef struct opj_jpt_msg_header {
+ /** In-class Identifier */
+ unsigned int Id;
+ /** Last byte information */
+ unsigned int last_byte;
+ /** Class Identifier */
+ unsigned int Class_Id;
+ /** CSn : index identifier */
+ unsigned int CSn_Id;
+ /** Message offset */
+ unsigned int Msg_offset;
+ /** Message length */
+ unsigned int Msg_length;
+ /** Auxiliary for JPP case */
+ unsigned int Layer_nb;
+} opj_jpt_msg_header_t;
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Initialize the value of the message header structure
+@param header Message header structure
+*/
+void jpt_init_msg_header(opj_jpt_msg_header_t * header);
+
+/**
+Read the message header for a JPP/JPT - stream
+@param cinfo Codec context info
+@param cio CIO handle
+@param header Message header structure
+*/
+void jpt_read_msg_header(opj_common_ptr cinfo, opj_cio_t *cio, opj_jpt_msg_header_t *header);
+
+#endif
diff --git a/Source/LibOpenJPEG/libopenjpeg.xcodeproj/project.pbxproj b/Source/LibOpenJPEG/libopenjpeg.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..45b5b7c
--- /dev/null
+++ b/Source/LibOpenJPEG/libopenjpeg.xcodeproj/project.pbxproj
@@ -0,0 +1,341 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D7BAB34E0E27FD7800F54103 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3250E27FD7800F54103 /* raw.c */; };
+ D7BAB34F0E27FD7800F54103 /* bio.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3260E27FD7800F54103 /* bio.c */; };
+ D7BAB3500E27FD7800F54103 /* event.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3270E27FD7800F54103 /* event.c */; };
+ D7BAB3510E27FD7800F54103 /* raw.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3280E27FD7800F54103 /* raw.h */; };
+ D7BAB3520E27FD7800F54103 /* openjpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3290E27FD7800F54103 /* openjpeg.c */; };
+ D7BAB3530E27FD7800F54103 /* mqc.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB32A0E27FD7800F54103 /* mqc.c */; };
+ D7BAB3540E27FD7800F54103 /* t1.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB32B0E27FD7800F54103 /* t1.h */; };
+ D7BAB3550E27FD7800F54103 /* j2k.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB32C0E27FD7800F54103 /* j2k.c */; };
+ D7BAB3560E27FD7800F54103 /* fix.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB32D0E27FD7800F54103 /* fix.h */; };
+ D7BAB3570E27FD7800F54103 /* j2k.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB32E0E27FD7800F54103 /* j2k.h */; };
+ D7BAB3580E27FD7800F54103 /* jpt.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB32F0E27FD7800F54103 /* jpt.h */; };
+ D7BAB3590E27FD7800F54103 /* image.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3300E27FD7800F54103 /* image.h */; };
+ D7BAB35A0E27FD7800F54103 /* dwt.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3310E27FD7800F54103 /* dwt.c */; };
+ D7BAB35B0E27FD7800F54103 /* openjpeg.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3320E27FD7800F54103 /* openjpeg.h */; };
+ D7BAB35C0E27FD7800F54103 /* int.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3330E27FD7800F54103 /* int.h */; };
+ D7BAB35D0E27FD7800F54103 /* t2.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3340E27FD7800F54103 /* t2.c */; };
+ D7BAB35E0E27FD7800F54103 /* cio.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3350E27FD7800F54103 /* cio.h */; };
+ D7BAB35F0E27FD7800F54103 /* dwt.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3360E27FD7800F54103 /* dwt.h */; };
+ D7BAB3600E27FD7800F54103 /* cio.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3370E27FD7800F54103 /* cio.c */; };
+ D7BAB3610E27FD7800F54103 /* jp2.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3380E27FD7800F54103 /* jp2.c */; };
+ D7BAB3620E27FD7800F54103 /* jp2.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3390E27FD7800F54103 /* jp2.h */; };
+ D7BAB3630E27FD7800F54103 /* tcd.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB33A0E27FD7800F54103 /* tcd.c */; };
+ D7BAB3640E27FD7800F54103 /* image.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB33B0E27FD7800F54103 /* image.c */; };
+ D7BAB3650E27FD7800F54103 /* jpt.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB33C0E27FD7800F54103 /* jpt.c */; };
+ D7BAB3660E27FD7800F54103 /* tgt.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB33D0E27FD7800F54103 /* tgt.h */; };
+ D7BAB3670E27FD7800F54103 /* t1.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB33E0E27FD7800F54103 /* t1.c */; };
+ D7BAB3680E27FD7800F54103 /* j2k_lib.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB33F0E27FD7800F54103 /* j2k_lib.h */; };
+ D7BAB3690E27FD7800F54103 /* pi.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3400E27FD7800F54103 /* pi.h */; };
+ D7BAB36A0E27FD7800F54103 /* mqc.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3410E27FD7800F54103 /* mqc.h */; };
+ D7BAB36B0E27FD7800F54103 /* pi.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3420E27FD7800F54103 /* pi.c */; };
+ D7BAB36C0E27FD7800F54103 /* t2.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3430E27FD7800F54103 /* t2.h */; };
+ D7BAB36D0E27FD7800F54103 /* t1_luts.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3440E27FD7800F54103 /* t1_luts.h */; };
+ D7BAB36E0E27FD7800F54103 /* tcd.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3450E27FD7800F54103 /* tcd.h */; };
+ D7BAB36F0E27FD7800F54103 /* bio.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3460E27FD7800F54103 /* bio.h */; };
+ D7BAB3700E27FD7800F54103 /* mct.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB3470E27FD7800F54103 /* mct.h */; };
+ D7BAB3710E27FD7800F54103 /* j2k_lib.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3480E27FD7800F54103 /* j2k_lib.c */; };
+ D7BAB3720E27FD7800F54103 /* tgt.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB3490E27FD7800F54103 /* tgt.c */; };
+ D7BAB3730E27FD7800F54103 /* event.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB34A0E27FD7800F54103 /* event.h */; };
+ D7BAB3740E27FD7800F54103 /* mct.c in Sources */ = {isa = PBXBuildFile; fileRef = D7BAB34B0E27FD7800F54103 /* mct.c */; };
+ D7BAB3750E27FD7800F54103 /* opj_includes.h in Headers */ = {isa = PBXBuildFile; fileRef = D7BAB34C0E27FD7800F54103 /* opj_includes.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libopenjpeg.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libopenjpeg.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D79FEFEC0E27FD31009E8D13 /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../../../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D79FEFED0E27FD31009E8D13 /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../../../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D7BAB3250E27FD7800F54103 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3260E27FD7800F54103 /* bio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bio.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3270E27FD7800F54103 /* event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = event.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3280E27FD7800F54103 /* raw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = raw.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3290E27FD7800F54103 /* openjpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = openjpeg.c; sourceTree = SOURCE_ROOT; };
+ D7BAB32A0E27FD7800F54103 /* mqc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mqc.c; sourceTree = SOURCE_ROOT; };
+ D7BAB32B0E27FD7800F54103 /* t1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = t1.h; sourceTree = SOURCE_ROOT; };
+ D7BAB32C0E27FD7800F54103 /* j2k.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = j2k.c; sourceTree = SOURCE_ROOT; };
+ D7BAB32D0E27FD7800F54103 /* fix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fix.h; sourceTree = SOURCE_ROOT; };
+ D7BAB32E0E27FD7800F54103 /* j2k.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = j2k.h; sourceTree = SOURCE_ROOT; };
+ D7BAB32F0E27FD7800F54103 /* jpt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jpt.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3300E27FD7800F54103 /* image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3310E27FD7800F54103 /* dwt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dwt.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3320E27FD7800F54103 /* openjpeg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = openjpeg.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3330E27FD7800F54103 /* int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = int.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3340E27FD7800F54103 /* t2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = t2.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3350E27FD7800F54103 /* cio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cio.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3360E27FD7800F54103 /* dwt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dwt.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3370E27FD7800F54103 /* cio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cio.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3380E27FD7800F54103 /* jp2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jp2.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3390E27FD7800F54103 /* jp2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jp2.h; sourceTree = SOURCE_ROOT; };
+ D7BAB33A0E27FD7800F54103 /* tcd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tcd.c; sourceTree = SOURCE_ROOT; };
+ D7BAB33B0E27FD7800F54103 /* image.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = image.c; sourceTree = SOURCE_ROOT; };
+ D7BAB33C0E27FD7800F54103 /* jpt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jpt.c; sourceTree = SOURCE_ROOT; };
+ D7BAB33D0E27FD7800F54103 /* tgt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tgt.h; sourceTree = SOURCE_ROOT; };
+ D7BAB33E0E27FD7800F54103 /* t1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = t1.c; sourceTree = SOURCE_ROOT; };
+ D7BAB33F0E27FD7800F54103 /* j2k_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = j2k_lib.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3400E27FD7800F54103 /* pi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pi.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3410E27FD7800F54103 /* mqc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mqc.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3420E27FD7800F54103 /* pi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pi.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3430E27FD7800F54103 /* t2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = t2.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3440E27FD7800F54103 /* t1_luts.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = t1_luts.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3450E27FD7800F54103 /* tcd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tcd.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3460E27FD7800F54103 /* bio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bio.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3470E27FD7800F54103 /* mct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mct.h; sourceTree = SOURCE_ROOT; };
+ D7BAB3480E27FD7800F54103 /* j2k_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = j2k_lib.c; sourceTree = SOURCE_ROOT; };
+ D7BAB3490E27FD7800F54103 /* tgt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tgt.c; sourceTree = SOURCE_ROOT; };
+ D7BAB34A0E27FD7800F54103 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = SOURCE_ROOT; };
+ D7BAB34B0E27FD7800F54103 /* mct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mct.c; sourceTree = SOURCE_ROOT; };
+ D7BAB34C0E27FD7800F54103 /* opj_includes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opj_includes.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libopenjpeg */ = {
+ isa = PBXGroup;
+ children = (
+ D79FEFEC0E27FD31009E8D13 /* MacConfigExternalDebug.xcconfig */,
+ D79FEFED0E27FD31009E8D13 /* MacConfigExternalRelease.xcconfig */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libopenjpeg;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D7BAB3250E27FD7800F54103 /* raw.c */,
+ D7BAB3260E27FD7800F54103 /* bio.c */,
+ D7BAB3270E27FD7800F54103 /* event.c */,
+ D7BAB3280E27FD7800F54103 /* raw.h */,
+ D7BAB3290E27FD7800F54103 /* openjpeg.c */,
+ D7BAB32A0E27FD7800F54103 /* mqc.c */,
+ D7BAB32B0E27FD7800F54103 /* t1.h */,
+ D7BAB32C0E27FD7800F54103 /* j2k.c */,
+ D7BAB32D0E27FD7800F54103 /* fix.h */,
+ D7BAB32E0E27FD7800F54103 /* j2k.h */,
+ D7BAB32F0E27FD7800F54103 /* jpt.h */,
+ D7BAB3300E27FD7800F54103 /* image.h */,
+ D7BAB3310E27FD7800F54103 /* dwt.c */,
+ D7BAB3320E27FD7800F54103 /* openjpeg.h */,
+ D7BAB3330E27FD7800F54103 /* int.h */,
+ D7BAB3340E27FD7800F54103 /* t2.c */,
+ D7BAB3350E27FD7800F54103 /* cio.h */,
+ D7BAB3360E27FD7800F54103 /* dwt.h */,
+ D7BAB3370E27FD7800F54103 /* cio.c */,
+ D7BAB3380E27FD7800F54103 /* jp2.c */,
+ D7BAB3390E27FD7800F54103 /* jp2.h */,
+ D7BAB33A0E27FD7800F54103 /* tcd.c */,
+ D7BAB33B0E27FD7800F54103 /* image.c */,
+ D7BAB33C0E27FD7800F54103 /* jpt.c */,
+ D7BAB33D0E27FD7800F54103 /* tgt.h */,
+ D7BAB33E0E27FD7800F54103 /* t1.c */,
+ D7BAB33F0E27FD7800F54103 /* j2k_lib.h */,
+ D7BAB3400E27FD7800F54103 /* pi.h */,
+ D7BAB3410E27FD7800F54103 /* mqc.h */,
+ D7BAB3420E27FD7800F54103 /* pi.c */,
+ D7BAB3430E27FD7800F54103 /* t2.h */,
+ D7BAB3440E27FD7800F54103 /* t1_luts.h */,
+ D7BAB3450E27FD7800F54103 /* tcd.h */,
+ D7BAB3460E27FD7800F54103 /* bio.h */,
+ D7BAB3470E27FD7800F54103 /* mct.h */,
+ D7BAB3480E27FD7800F54103 /* j2k_lib.c */,
+ D7BAB3490E27FD7800F54103 /* tgt.c */,
+ D7BAB34A0E27FD7800F54103 /* event.h */,
+ D7BAB34B0E27FD7800F54103 /* mct.c */,
+ D7BAB34C0E27FD7800F54103 /* opj_includes.h */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libopenjpeg.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7BAB3510E27FD7800F54103 /* raw.h in Headers */,
+ D7BAB3540E27FD7800F54103 /* t1.h in Headers */,
+ D7BAB3560E27FD7800F54103 /* fix.h in Headers */,
+ D7BAB3570E27FD7800F54103 /* j2k.h in Headers */,
+ D7BAB3580E27FD7800F54103 /* jpt.h in Headers */,
+ D7BAB3590E27FD7800F54103 /* image.h in Headers */,
+ D7BAB35B0E27FD7800F54103 /* openjpeg.h in Headers */,
+ D7BAB35C0E27FD7800F54103 /* int.h in Headers */,
+ D7BAB35E0E27FD7800F54103 /* cio.h in Headers */,
+ D7BAB35F0E27FD7800F54103 /* dwt.h in Headers */,
+ D7BAB3620E27FD7800F54103 /* jp2.h in Headers */,
+ D7BAB3660E27FD7800F54103 /* tgt.h in Headers */,
+ D7BAB3680E27FD7800F54103 /* j2k_lib.h in Headers */,
+ D7BAB3690E27FD7800F54103 /* pi.h in Headers */,
+ D7BAB36A0E27FD7800F54103 /* mqc.h in Headers */,
+ D7BAB36C0E27FD7800F54103 /* t2.h in Headers */,
+ D7BAB36D0E27FD7800F54103 /* t1_luts.h in Headers */,
+ D7BAB36E0E27FD7800F54103 /* tcd.h in Headers */,
+ D7BAB36F0E27FD7800F54103 /* bio.h in Headers */,
+ D7BAB3700E27FD7800F54103 /* mct.h in Headers */,
+ D7BAB3730E27FD7800F54103 /* event.h in Headers */,
+ D7BAB3750E27FD7800F54103 /* opj_includes.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libopenjpeg */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libopenjpeg" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libopenjpeg;
+ productName = libopenjpeg;
+ productReference = D2AAC046055464E500DB518D /* libopenjpeg.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libopenjpeg" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libopenjpeg */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libopenjpeg */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D7BAB34E0E27FD7800F54103 /* raw.c in Sources */,
+ D7BAB34F0E27FD7800F54103 /* bio.c in Sources */,
+ D7BAB3500E27FD7800F54103 /* event.c in Sources */,
+ D7BAB3520E27FD7800F54103 /* openjpeg.c in Sources */,
+ D7BAB3530E27FD7800F54103 /* mqc.c in Sources */,
+ D7BAB3550E27FD7800F54103 /* j2k.c in Sources */,
+ D7BAB35A0E27FD7800F54103 /* dwt.c in Sources */,
+ D7BAB35D0E27FD7800F54103 /* t2.c in Sources */,
+ D7BAB3600E27FD7800F54103 /* cio.c in Sources */,
+ D7BAB3610E27FD7800F54103 /* jp2.c in Sources */,
+ D7BAB3630E27FD7800F54103 /* tcd.c in Sources */,
+ D7BAB3640E27FD7800F54103 /* image.c in Sources */,
+ D7BAB3650E27FD7800F54103 /* jpt.c in Sources */,
+ D7BAB3670E27FD7800F54103 /* t1.c in Sources */,
+ D7BAB36B0E27FD7800F54103 /* pi.c in Sources */,
+ D7BAB3710E27FD7800F54103 /* j2k_lib.c in Sources */,
+ D7BAB3720E27FD7800F54103 /* tgt.c in Sources */,
+ D7BAB3740E27FD7800F54103 /* mct.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = openjpeg;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = openjpeg;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D79FEFEC0E27FD31009E8D13 /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DOPJ_STATIC",
+ );
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D79FEFED0E27FD31009E8D13 /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DOPJ_STATIC",
+ );
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libopenjpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libopenjpeg" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Source/LibOpenJPEG/license.txt b/Source/LibOpenJPEG/license.txt
new file mode 100644
index 0000000..d1e5b6a
--- /dev/null
+++ b/Source/LibOpenJPEG/license.txt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */ \ No newline at end of file
diff --git a/Source/LibOpenJPEG/mct.c b/Source/LibOpenJPEG/mct.c
new file mode 100644
index 0000000..ca21744
--- /dev/null
+++ b/Source/LibOpenJPEG/mct.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/* <summary> */
+/* This table contains the norms of the basis function of the reversible MCT. */
+/* </summary> */
+static const double mct_norms[3] = { 1.732, .8292, .8292 };
+
+/* <summary> */
+/* This table contains the norms of the basis function of the irreversible MCT. */
+/* </summary> */
+static const double mct_norms_real[3] = { 1.732, 1.805, 1.573 };
+
+/* <summary> */
+/* Foward reversible MCT. */
+/* </summary> */
+void mct_encode(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for(i = 0; i < n; ++i) {
+ int r = c0[i];
+ int g = c1[i];
+ int b = c2[i];
+ int y = (r + (g * 2) + b) >> 2;
+ int u = b - g;
+ int v = r - g;
+ c0[i] = y;
+ c1[i] = u;
+ c2[i] = v;
+ }
+}
+
+/* <summary> */
+/* Inverse reversible MCT. */
+/* </summary> */
+void mct_decode(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for (i = 0; i < n; ++i) {
+ int y = c0[i];
+ int u = c1[i];
+ int v = c2[i];
+ int g = y - ((u + v) >> 2);
+ int r = v + g;
+ int b = u + g;
+ c0[i] = r;
+ c1[i] = g;
+ c2[i] = b;
+ }
+}
+
+/* <summary> */
+/* Get norm of basis function of reversible MCT. */
+/* </summary> */
+double mct_getnorm(int compno) {
+ return mct_norms[compno];
+}
+
+/* <summary> */
+/* Foward irreversible MCT. */
+/* </summary> */
+void mct_encode_real(
+ int* restrict c0,
+ int* restrict c1,
+ int* restrict c2,
+ int n)
+{
+ int i;
+ for(i = 0; i < n; ++i) {
+ int r = c0[i];
+ int g = c1[i];
+ int b = c2[i];
+ int y = fix_mul(r, 2449) + fix_mul(g, 4809) + fix_mul(b, 934);
+ int u = -fix_mul(r, 1382) - fix_mul(g, 2714) + fix_mul(b, 4096);
+ int v = fix_mul(r, 4096) - fix_mul(g, 3430) - fix_mul(b, 666);
+ c0[i] = y;
+ c1[i] = u;
+ c2[i] = v;
+ }
+}
+
+/* <summary> */
+/* Inverse irreversible MCT. */
+/* </summary> */
+void mct_decode_real(
+ float* restrict c0,
+ float* restrict c1,
+ float* restrict c2,
+ int n)
+{
+ int i;
+ for(i = 0; i < n; ++i) {
+ float y = c0[i];
+ float u = c1[i];
+ float v = c2[i];
+ float r = y + (v * 1.402f);
+ float g = y - (u * 0.34413f) - (v * (0.71414f));
+ float b = y + (u * 1.772f);
+ c0[i] = r;
+ c1[i] = g;
+ c2[i] = b;
+ }
+}
+
+/* <summary> */
+/* Get norm of basis function of irreversible MCT. */
+/* </summary> */
+double mct_getnorm_real(int compno) {
+ return mct_norms_real[compno];
+}
diff --git a/Source/LibOpenJPEG/mct.h b/Source/LibOpenJPEG/mct.h
new file mode 100644
index 0000000..84e3f8a
--- /dev/null
+++ b/Source/LibOpenJPEG/mct.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MCT_H
+#define __MCT_H
+/**
+@file mct.h
+@brief Implementation of a multi-component transforms (MCT)
+
+The functions in MCT.C have for goal to realize reversible and irreversible multicomponent
+transform. The functions in MCT.C are used by some function in TCD.C.
+*/
+
+/** @defgroup MCT MCT - Implementation of a multi-component transform */
+/*@{*/
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Apply a reversible multi-component transform to an image
+@param c0 Samples for red component
+@param c1 Samples for green component
+@param c2 Samples blue component
+@param n Number of samples for each component
+*/
+void mct_encode(int *c0, int *c1, int *c2, int n);
+/**
+Apply a reversible multi-component inverse transform to an image
+@param c0 Samples for luminance component
+@param c1 Samples for red chrominance component
+@param c2 Samples for blue chrominance component
+@param n Number of samples for each component
+*/
+void mct_decode(int *c0, int *c1, int *c2, int n);
+/**
+Get norm of the basis function used for the reversible multi-component transform
+@param compno Number of the component (0->Y, 1->U, 2->V)
+@return
+*/
+double mct_getnorm(int compno);
+
+/**
+Apply an irreversible multi-component transform to an image
+@param c0 Samples for red component
+@param c1 Samples for green component
+@param c2 Samples blue component
+@param n Number of samples for each component
+*/
+void mct_encode_real(int *c0, int *c1, int *c2, int n);
+/**
+Apply an irreversible multi-component inverse transform to an image
+@param c0 Samples for luminance component
+@param c1 Samples for red chrominance component
+@param c2 Samples for blue chrominance component
+@param n Number of samples for each component
+*/
+void mct_decode_real(float* c0, float* c1, float* c2, int n);
+/**
+Get norm of the basis function used for the irreversible multi-component transform
+@param compno Number of the component (0->Y, 1->U, 2->V)
+@return
+*/
+double mct_getnorm_real(int compno);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MCT_H */
diff --git a/Source/LibOpenJPEG/mqc.c b/Source/LibOpenJPEG/mqc.c
new file mode 100644
index 0000000..9aa9d2c
--- /dev/null
+++ b/Source/LibOpenJPEG/mqc.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup MQC MQC - Implementation of an MQ-Coder */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Output a byte, doing bit-stuffing if necessary.
+After a 0xff byte, the next byte must be smaller than 0x90.
+@param mqc MQC handle
+*/
+static void mqc_byteout(opj_mqc_t *mqc);
+/**
+Renormalize mqc->a and mqc->c while encoding, so that mqc->a stays between 0x8000 and 0x10000
+@param mqc MQC handle
+*/
+static void mqc_renorme(opj_mqc_t *mqc);
+/**
+Encode the most probable symbol
+@param mqc MQC handle
+*/
+static void mqc_codemps(opj_mqc_t *mqc);
+/**
+Encode the most least symbol
+@param mqc MQC handle
+*/
+static void mqc_codelps(opj_mqc_t *mqc);
+/**
+Fill mqc->c with 1's for flushing
+@param mqc MQC handle
+*/
+static void mqc_setbits(opj_mqc_t *mqc);
+/**
+FIXME: documentation ???
+@param mqc MQC handle
+@return
+*/
+static int mqc_mpsexchange(opj_mqc_t *mqc);
+/**
+FIXME: documentation ???
+@param mqc MQC handle
+@return
+*/
+static int mqc_lpsexchange(opj_mqc_t *mqc);
+/**
+Input a byte
+@param mqc MQC handle
+*/
+static void mqc_bytein(opj_mqc_t *mqc);
+/**
+Renormalize mqc->a and mqc->c while decoding
+@param mqc MQC handle
+*/
+static void mqc_renormd(opj_mqc_t *mqc);
+
+/*@}*/
+
+/*@}*/
+
+/* <summary> */
+/* This array defines all the possible states for a context. */
+/* </summary> */
+static opj_mqc_state_t mqc_states[47 * 2] = {
+ {0x5601, 0, &mqc_states[2], &mqc_states[3]},
+ {0x5601, 1, &mqc_states[3], &mqc_states[2]},
+ {0x3401, 0, &mqc_states[4], &mqc_states[12]},
+ {0x3401, 1, &mqc_states[5], &mqc_states[13]},
+ {0x1801, 0, &mqc_states[6], &mqc_states[18]},
+ {0x1801, 1, &mqc_states[7], &mqc_states[19]},
+ {0x0ac1, 0, &mqc_states[8], &mqc_states[24]},
+ {0x0ac1, 1, &mqc_states[9], &mqc_states[25]},
+ {0x0521, 0, &mqc_states[10], &mqc_states[58]},
+ {0x0521, 1, &mqc_states[11], &mqc_states[59]},
+ {0x0221, 0, &mqc_states[76], &mqc_states[66]},
+ {0x0221, 1, &mqc_states[77], &mqc_states[67]},
+ {0x5601, 0, &mqc_states[14], &mqc_states[13]},
+ {0x5601, 1, &mqc_states[15], &mqc_states[12]},
+ {0x5401, 0, &mqc_states[16], &mqc_states[28]},
+ {0x5401, 1, &mqc_states[17], &mqc_states[29]},
+ {0x4801, 0, &mqc_states[18], &mqc_states[28]},
+ {0x4801, 1, &mqc_states[19], &mqc_states[29]},
+ {0x3801, 0, &mqc_states[20], &mqc_states[28]},
+ {0x3801, 1, &mqc_states[21], &mqc_states[29]},
+ {0x3001, 0, &mqc_states[22], &mqc_states[34]},
+ {0x3001, 1, &mqc_states[23], &mqc_states[35]},
+ {0x2401, 0, &mqc_states[24], &mqc_states[36]},
+ {0x2401, 1, &mqc_states[25], &mqc_states[37]},
+ {0x1c01, 0, &mqc_states[26], &mqc_states[40]},
+ {0x1c01, 1, &mqc_states[27], &mqc_states[41]},
+ {0x1601, 0, &mqc_states[58], &mqc_states[42]},
+ {0x1601, 1, &mqc_states[59], &mqc_states[43]},
+ {0x5601, 0, &mqc_states[30], &mqc_states[29]},
+ {0x5601, 1, &mqc_states[31], &mqc_states[28]},
+ {0x5401, 0, &mqc_states[32], &mqc_states[28]},
+ {0x5401, 1, &mqc_states[33], &mqc_states[29]},
+ {0x5101, 0, &mqc_states[34], &mqc_states[30]},
+ {0x5101, 1, &mqc_states[35], &mqc_states[31]},
+ {0x4801, 0, &mqc_states[36], &mqc_states[32]},
+ {0x4801, 1, &mqc_states[37], &mqc_states[33]},
+ {0x3801, 0, &mqc_states[38], &mqc_states[34]},
+ {0x3801, 1, &mqc_states[39], &mqc_states[35]},
+ {0x3401, 0, &mqc_states[40], &mqc_states[36]},
+ {0x3401, 1, &mqc_states[41], &mqc_states[37]},
+ {0x3001, 0, &mqc_states[42], &mqc_states[38]},
+ {0x3001, 1, &mqc_states[43], &mqc_states[39]},
+ {0x2801, 0, &mqc_states[44], &mqc_states[38]},
+ {0x2801, 1, &mqc_states[45], &mqc_states[39]},
+ {0x2401, 0, &mqc_states[46], &mqc_states[40]},
+ {0x2401, 1, &mqc_states[47], &mqc_states[41]},
+ {0x2201, 0, &mqc_states[48], &mqc_states[42]},
+ {0x2201, 1, &mqc_states[49], &mqc_states[43]},
+ {0x1c01, 0, &mqc_states[50], &mqc_states[44]},
+ {0x1c01, 1, &mqc_states[51], &mqc_states[45]},
+ {0x1801, 0, &mqc_states[52], &mqc_states[46]},
+ {0x1801, 1, &mqc_states[53], &mqc_states[47]},
+ {0x1601, 0, &mqc_states[54], &mqc_states[48]},
+ {0x1601, 1, &mqc_states[55], &mqc_states[49]},
+ {0x1401, 0, &mqc_states[56], &mqc_states[50]},
+ {0x1401, 1, &mqc_states[57], &mqc_states[51]},
+ {0x1201, 0, &mqc_states[58], &mqc_states[52]},
+ {0x1201, 1, &mqc_states[59], &mqc_states[53]},
+ {0x1101, 0, &mqc_states[60], &mqc_states[54]},
+ {0x1101, 1, &mqc_states[61], &mqc_states[55]},
+ {0x0ac1, 0, &mqc_states[62], &mqc_states[56]},
+ {0x0ac1, 1, &mqc_states[63], &mqc_states[57]},
+ {0x09c1, 0, &mqc_states[64], &mqc_states[58]},
+ {0x09c1, 1, &mqc_states[65], &mqc_states[59]},
+ {0x08a1, 0, &mqc_states[66], &mqc_states[60]},
+ {0x08a1, 1, &mqc_states[67], &mqc_states[61]},
+ {0x0521, 0, &mqc_states[68], &mqc_states[62]},
+ {0x0521, 1, &mqc_states[69], &mqc_states[63]},
+ {0x0441, 0, &mqc_states[70], &mqc_states[64]},
+ {0x0441, 1, &mqc_states[71], &mqc_states[65]},
+ {0x02a1, 0, &mqc_states[72], &mqc_states[66]},
+ {0x02a1, 1, &mqc_states[73], &mqc_states[67]},
+ {0x0221, 0, &mqc_states[74], &mqc_states[68]},
+ {0x0221, 1, &mqc_states[75], &mqc_states[69]},
+ {0x0141, 0, &mqc_states[76], &mqc_states[70]},
+ {0x0141, 1, &mqc_states[77], &mqc_states[71]},
+ {0x0111, 0, &mqc_states[78], &mqc_states[72]},
+ {0x0111, 1, &mqc_states[79], &mqc_states[73]},
+ {0x0085, 0, &mqc_states[80], &mqc_states[74]},
+ {0x0085, 1, &mqc_states[81], &mqc_states[75]},
+ {0x0049, 0, &mqc_states[82], &mqc_states[76]},
+ {0x0049, 1, &mqc_states[83], &mqc_states[77]},
+ {0x0025, 0, &mqc_states[84], &mqc_states[78]},
+ {0x0025, 1, &mqc_states[85], &mqc_states[79]},
+ {0x0015, 0, &mqc_states[86], &mqc_states[80]},
+ {0x0015, 1, &mqc_states[87], &mqc_states[81]},
+ {0x0009, 0, &mqc_states[88], &mqc_states[82]},
+ {0x0009, 1, &mqc_states[89], &mqc_states[83]},
+ {0x0005, 0, &mqc_states[90], &mqc_states[84]},
+ {0x0005, 1, &mqc_states[91], &mqc_states[85]},
+ {0x0001, 0, &mqc_states[90], &mqc_states[86]},
+ {0x0001, 1, &mqc_states[91], &mqc_states[87]},
+ {0x5601, 0, &mqc_states[92], &mqc_states[92]},
+ {0x5601, 1, &mqc_states[93], &mqc_states[93]},
+};
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+static void mqc_byteout(opj_mqc_t *mqc) {
+ if (*mqc->bp == 0xff) {
+ mqc->bp++;
+ *mqc->bp = mqc->c >> 20;
+ mqc->c &= 0xfffff;
+ mqc->ct = 7;
+ } else {
+ if ((mqc->c & 0x8000000) == 0) { /* ((mqc->c&0x8000000)==0) CHANGE */
+ mqc->bp++;
+ *mqc->bp = mqc->c >> 19;
+ mqc->c &= 0x7ffff;
+ mqc->ct = 8;
+ } else {
+ (*mqc->bp)++;
+ if (*mqc->bp == 0xff) {
+ mqc->c &= 0x7ffffff;
+ mqc->bp++;
+ *mqc->bp = mqc->c >> 20;
+ mqc->c &= 0xfffff;
+ mqc->ct = 7;
+ } else {
+ mqc->bp++;
+ *mqc->bp = mqc->c >> 19;
+ mqc->c &= 0x7ffff;
+ mqc->ct = 8;
+ }
+ }
+ }
+}
+
+static void mqc_renorme(opj_mqc_t *mqc) {
+ do {
+ mqc->a <<= 1;
+ mqc->c <<= 1;
+ mqc->ct--;
+ if (mqc->ct == 0) {
+ mqc_byteout(mqc);
+ }
+ } while ((mqc->a & 0x8000) == 0);
+}
+
+static void mqc_codemps(opj_mqc_t *mqc) {
+ mqc->a -= (*mqc->curctx)->qeval;
+ if ((mqc->a & 0x8000) == 0) {
+ if (mqc->a < (*mqc->curctx)->qeval) {
+ mqc->a = (*mqc->curctx)->qeval;
+ } else {
+ mqc->c += (*mqc->curctx)->qeval;
+ }
+ *mqc->curctx = (*mqc->curctx)->nmps;
+ mqc_renorme(mqc);
+ } else {
+ mqc->c += (*mqc->curctx)->qeval;
+ }
+}
+
+static void mqc_codelps(opj_mqc_t *mqc) {
+ mqc->a -= (*mqc->curctx)->qeval;
+ if (mqc->a < (*mqc->curctx)->qeval) {
+ mqc->c += (*mqc->curctx)->qeval;
+ } else {
+ mqc->a = (*mqc->curctx)->qeval;
+ }
+ *mqc->curctx = (*mqc->curctx)->nlps;
+ mqc_renorme(mqc);
+}
+
+static void mqc_setbits(opj_mqc_t *mqc) {
+ unsigned int tempc = mqc->c + mqc->a;
+ mqc->c |= 0xffff;
+ if (mqc->c >= tempc) {
+ mqc->c -= 0x8000;
+ }
+}
+
+static int mqc_mpsexchange(opj_mqc_t *mqc) {
+ int d;
+ if (mqc->a < (*mqc->curctx)->qeval) {
+ d = 1 - (*mqc->curctx)->mps;
+ *mqc->curctx = (*mqc->curctx)->nlps;
+ } else {
+ d = (*mqc->curctx)->mps;
+ *mqc->curctx = (*mqc->curctx)->nmps;
+ }
+
+ return d;
+}
+
+static int mqc_lpsexchange(opj_mqc_t *mqc) {
+ int d;
+ if (mqc->a < (*mqc->curctx)->qeval) {
+ mqc->a = (*mqc->curctx)->qeval;
+ d = (*mqc->curctx)->mps;
+ *mqc->curctx = (*mqc->curctx)->nmps;
+ } else {
+ mqc->a = (*mqc->curctx)->qeval;
+ d = 1 - (*mqc->curctx)->mps;
+ *mqc->curctx = (*mqc->curctx)->nlps;
+ }
+
+ return d;
+}
+
+static void mqc_bytein(opj_mqc_t *mqc) {
+ if (mqc->bp != mqc->end) {
+ unsigned int c;
+ if (mqc->bp + 1 != mqc->end) {
+ c = *(mqc->bp + 1);
+ } else {
+ c = 0xff;
+ }
+ if (*mqc->bp == 0xff) {
+ if (c > 0x8f) {
+ mqc->c += 0xff00;
+ mqc->ct = 8;
+ } else {
+ mqc->bp++;
+ mqc->c += c << 9;
+ mqc->ct = 7;
+ }
+ } else {
+ mqc->bp++;
+ mqc->c += c << 8;
+ mqc->ct = 8;
+ }
+ } else {
+ mqc->c += 0xff00;
+ mqc->ct = 8;
+ }
+}
+
+static void mqc_renormd(opj_mqc_t *mqc) {
+ do {
+ if (mqc->ct == 0) {
+ mqc_bytein(mqc);
+ }
+ mqc->a <<= 1;
+ mqc->c <<= 1;
+ mqc->ct--;
+ } while (mqc->a < 0x8000);
+}
+
+/*
+==========================================================
+ MQ-Coder interface
+==========================================================
+*/
+
+opj_mqc_t* mqc_create(void) {
+ opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t));
+ return mqc;
+}
+
+void mqc_destroy(opj_mqc_t *mqc) {
+ if(mqc) {
+ opj_free(mqc);
+ }
+}
+
+int mqc_numbytes(opj_mqc_t *mqc) {
+ return mqc->bp - mqc->start;
+}
+
+void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp) {
+ mqc_setcurctx(mqc, 0);
+ mqc->a = 0x8000;
+ mqc->c = 0;
+ mqc->bp = bp - 1;
+ mqc->ct = 12;
+ if (*mqc->bp == 0xff) {
+ mqc->ct = 13;
+ }
+ mqc->start = bp;
+}
+
+void mqc_encode(opj_mqc_t *mqc, int d) {
+ if ((*mqc->curctx)->mps == d) {
+ mqc_codemps(mqc);
+ } else {
+ mqc_codelps(mqc);
+ }
+}
+
+void mqc_flush(opj_mqc_t *mqc) {
+ mqc_setbits(mqc);
+ mqc->c <<= mqc->ct;
+ mqc_byteout(mqc);
+ mqc->c <<= mqc->ct;
+ mqc_byteout(mqc);
+
+ if (*mqc->bp != 0xff) {
+ mqc->bp++;
+ }
+}
+
+void mqc_bypass_init_enc(opj_mqc_t *mqc) {
+ mqc->c = 0;
+ mqc->ct = 8;
+ /*if (*mqc->bp == 0xff) {
+ mqc->ct = 7;
+ } */
+}
+
+void mqc_bypass_enc(opj_mqc_t *mqc, int d) {
+ mqc->ct--;
+ mqc->c = mqc->c + (d << mqc->ct);
+ if (mqc->ct == 0) {
+ mqc->bp++;
+ *mqc->bp = mqc->c;
+ mqc->ct = 8;
+ if (*mqc->bp == 0xff) {
+ mqc->ct = 7;
+ }
+ mqc->c = 0;
+ }
+}
+
+int mqc_bypass_flush_enc(opj_mqc_t *mqc) {
+ unsigned char bit_padding;
+
+ bit_padding = 0;
+
+ if (mqc->ct != 0) {
+ while (mqc->ct > 0) {
+ mqc->ct--;
+ mqc->c += bit_padding << mqc->ct;
+ bit_padding = (bit_padding + 1) & 0x01;
+ }
+ mqc->bp++;
+ *mqc->bp = mqc->c;
+ mqc->ct = 8;
+ mqc->c = 0;
+ }
+
+ return 1;
+}
+
+void mqc_reset_enc(opj_mqc_t *mqc) {
+ mqc_resetstates(mqc);
+ mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+ mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+ mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+}
+
+int mqc_restart_enc(opj_mqc_t *mqc) {
+ int correction = 1;
+
+ /* <flush part> */
+ int n = 27 - 15 - mqc->ct;
+ mqc->c <<= mqc->ct;
+ while (n > 0) {
+ mqc_byteout(mqc);
+ n -= mqc->ct;
+ mqc->c <<= mqc->ct;
+ }
+ mqc_byteout(mqc);
+
+ return correction;
+}
+
+void mqc_restart_init_enc(opj_mqc_t *mqc) {
+ /* <Re-init part> */
+ mqc_setcurctx(mqc, 0);
+ mqc->a = 0x8000;
+ mqc->c = 0;
+ mqc->ct = 12;
+ mqc->bp--;
+ if (*mqc->bp == 0xff) {
+ mqc->ct = 13;
+ }
+}
+
+void mqc_erterm_enc(opj_mqc_t *mqc) {
+ int k = 11 - mqc->ct + 1;
+
+ while (k > 0) {
+ mqc->c <<= mqc->ct;
+ mqc->ct = 0;
+ mqc_byteout(mqc);
+ k -= mqc->ct;
+ }
+
+ if (*mqc->bp != 0xff) {
+ mqc_byteout(mqc);
+ }
+}
+
+void mqc_segmark_enc(opj_mqc_t *mqc) {
+ int i;
+ mqc_setcurctx(mqc, 18);
+
+ for (i = 1; i < 5; i++) {
+ mqc_encode(mqc, i % 2);
+ }
+}
+
+void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len) {
+ mqc_setcurctx(mqc, 0);
+ mqc->start = bp;
+ mqc->end = bp + len;
+ mqc->bp = bp;
+ if (len==0) mqc->c = 0xff << 16;
+ else mqc->c = *mqc->bp << 16;
+ mqc_bytein(mqc);
+ mqc->c <<= 7;
+ mqc->ct -= 7;
+ mqc->a = 0x8000;
+}
+
+int mqc_decode(opj_mqc_t *mqc) {
+ int d;
+ mqc->a -= (*mqc->curctx)->qeval;
+ if ((mqc->c >> 16) < (*mqc->curctx)->qeval) {
+ d = mqc_lpsexchange(mqc);
+ mqc_renormd(mqc);
+ } else {
+ mqc->c -= (*mqc->curctx)->qeval << 16;
+ if ((mqc->a & 0x8000) == 0) {
+ d = mqc_mpsexchange(mqc);
+ mqc_renormd(mqc);
+ } else {
+ d = (*mqc->curctx)->mps;
+ }
+ }
+
+ return d;
+}
+
+void mqc_resetstates(opj_mqc_t *mqc) {
+ int i;
+ for (i = 0; i < MQC_NUMCTXS; i++) {
+ mqc->ctxs[i] = mqc_states;
+ }
+}
+
+void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob) {
+ mqc->ctxs[ctxno] = &mqc_states[msb + (prob << 1)];
+}
+
+
diff --git a/Source/LibOpenJPEG/mqc.h b/Source/LibOpenJPEG/mqc.h
new file mode 100644
index 0000000..8cc8c93
--- /dev/null
+++ b/Source/LibOpenJPEG/mqc.h
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __MQC_H
+#define __MQC_H
+/**
+@file mqc.h
+@brief Implementation of an MQ-Coder (MQC)
+
+The functions in MQC.C have for goal to realize the MQ-coder operations. The functions
+in MQC.C are used by some function in T1.C.
+*/
+
+/** @defgroup MQC MQC - Implementation of an MQ-Coder */
+/*@{*/
+
+/**
+This struct defines the state of a context.
+*/
+typedef struct opj_mqc_state {
+ /** the probability of the Least Probable Symbol (0.75->0x8000, 1.5->0xffff) */
+ unsigned int qeval;
+ /** the Most Probable Symbol (0 or 1) */
+ int mps;
+ /** next state if the next encoded symbol is the MPS */
+ struct opj_mqc_state *nmps;
+ /** next state if the next encoded symbol is the LPS */
+ struct opj_mqc_state *nlps;
+} opj_mqc_state_t;
+
+#define MQC_NUMCTXS 19
+
+/**
+MQ coder
+*/
+typedef struct opj_mqc {
+ unsigned int c;
+ unsigned int a;
+ unsigned int ct;
+ unsigned char *bp;
+ unsigned char *start;
+ unsigned char *end;
+ opj_mqc_state_t *ctxs[MQC_NUMCTXS];
+ opj_mqc_state_t **curctx;
+} opj_mqc_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new MQC handle
+@return Returns a new MQC handle if successful, returns NULL otherwise
+*/
+opj_mqc_t* mqc_create(void);
+/**
+Destroy a previously created MQC handle
+@param mqc MQC handle to destroy
+*/
+void mqc_destroy(opj_mqc_t *mqc);
+/**
+Return the number of bytes written/read since initialisation
+@param mqc MQC handle
+@return Returns the number of bytes already encoded
+*/
+int mqc_numbytes(opj_mqc_t *mqc);
+/**
+Reset the states of all the context of the coder/decoder
+(each context is set to a state where 0 and 1 are more or less equiprobable)
+@param mqc MQC handle
+*/
+void mqc_resetstates(opj_mqc_t *mqc);
+/**
+Set the state of a particular context
+@param mqc MQC handle
+@param ctxno Number that identifies the context
+@param msb The MSB of the new state of the context
+@param prob Number that identifies the probability of the symbols for the new state of the context
+*/
+void mqc_setstate(opj_mqc_t *mqc, int ctxno, int msb, int prob);
+/**
+Initialize the encoder
+@param mqc MQC handle
+@param bp Pointer to the start of the buffer where the bytes will be written
+*/
+void mqc_init_enc(opj_mqc_t *mqc, unsigned char *bp);
+/**
+Set the current context used for coding/decoding
+@param mqc MQC handle
+@param ctxno Number that identifies the context
+*/
+#define mqc_setcurctx(mqc, ctxno) (mqc)->curctx = &(mqc)->ctxs[(int)(ctxno)]
+/**
+Encode a symbol using the MQ-coder
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+void mqc_encode(opj_mqc_t *mqc, int d);
+/**
+Flush the encoder, so that all remaining data is written
+@param mqc MQC handle
+*/
+void mqc_flush(opj_mqc_t *mqc);
+/**
+BYPASS mode switch, initialization operation.
+JPEG 2000 p 505.
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+*/
+void mqc_bypass_init_enc(opj_mqc_t *mqc);
+/**
+BYPASS mode switch, coding operation.
+JPEG 2000 p 505.
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@param d The symbol to be encoded (0 or 1)
+*/
+void mqc_bypass_enc(opj_mqc_t *mqc, int d);
+/**
+BYPASS mode switch, flush operation
+<h2>Not fully implemented and tested !!</h2>
+@param mqc MQC handle
+@return Returns 1 (always)
+*/
+int mqc_bypass_flush_enc(opj_mqc_t *mqc);
+/**
+RESET mode switch
+@param mqc MQC handle
+*/
+void mqc_reset_enc(opj_mqc_t *mqc);
+/**
+RESTART mode switch (TERMALL)
+@param mqc MQC handle
+@return Returns 1 (always)
+*/
+int mqc_restart_enc(opj_mqc_t *mqc);
+/**
+RESTART mode switch (TERMALL) reinitialisation
+@param mqc MQC handle
+*/
+void mqc_restart_init_enc(opj_mqc_t *mqc);
+/**
+ERTERM mode switch (PTERM)
+@param mqc MQC handle
+*/
+void mqc_erterm_enc(opj_mqc_t *mqc);
+/**
+SEGMARK mode switch (SEGSYM)
+@param mqc MQC handle
+*/
+void mqc_segmark_enc(opj_mqc_t *mqc);
+/**
+Initialize the decoder
+@param mqc MQC handle
+@param bp Pointer to the start of the buffer from which the bytes will be read
+@param len Length of the input buffer
+*/
+void mqc_init_dec(opj_mqc_t *mqc, unsigned char *bp, int len);
+/**
+Decode a symbol
+@param mqc MQC handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int mqc_decode(opj_mqc_t *mqc);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __MQC_H */
diff --git a/Source/LibOpenJPEG/openjpeg.c b/Source/LibOpenJPEG/openjpeg.c
new file mode 100644
index 0000000..88d44fd
--- /dev/null
+++ b/Source/LibOpenJPEG/openjpeg.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#endif /* WIN32 */
+
+#include "opj_includes.h"
+
+/* ---------------------------------------------------------------------- */
+#ifdef WIN32
+#ifndef OPJ_STATIC
+BOOL APIENTRY
+DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
+ switch (ul_reason_for_call) {
+ case DLL_PROCESS_ATTACH :
+ break;
+ case DLL_PROCESS_DETACH :
+ break;
+ case DLL_THREAD_ATTACH :
+ case DLL_THREAD_DETACH :
+ break;
+ }
+
+ return TRUE;
+}
+#endif /* OPJ_STATIC */
+#endif /* WIN32 */
+
+/* ---------------------------------------------------------------------- */
+
+
+const char* OPJ_CALLCONV opj_version(void) {
+ return OPENJPEG_VERSION;
+}
+
+opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format) {
+ opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_calloc(1, sizeof(opj_dinfo_t));
+ if(!dinfo) return NULL;
+ dinfo->is_decompressor = true;
+ switch(format) {
+ case CODEC_J2K:
+ case CODEC_JPT:
+ /* get a J2K decoder handle */
+ dinfo->j2k_handle = (void*)j2k_create_decompress((opj_common_ptr)dinfo);
+ if(!dinfo->j2k_handle) {
+ opj_free(dinfo);
+ return NULL;
+ }
+ break;
+ case CODEC_JP2:
+ /* get a JP2 decoder handle */
+ dinfo->jp2_handle = (void*)jp2_create_decompress((opj_common_ptr)dinfo);
+ if(!dinfo->jp2_handle) {
+ opj_free(dinfo);
+ return NULL;
+ }
+ break;
+ case CODEC_UNKNOWN:
+ default:
+ opj_free(dinfo);
+ return NULL;
+ }
+
+ dinfo->codec_format = format;
+
+ return dinfo;
+}
+
+void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo) {
+ if(dinfo) {
+ /* destroy the codec */
+ switch(dinfo->codec_format) {
+ case CODEC_J2K:
+ case CODEC_JPT:
+ j2k_destroy_decompress((opj_j2k_t*)dinfo->j2k_handle);
+ break;
+ case CODEC_JP2:
+ jp2_destroy_decompress((opj_jp2_t*)dinfo->jp2_handle);
+ break;
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ /* destroy the decompressor */
+ opj_free(dinfo);
+ }
+}
+
+void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters) {
+ if(parameters) {
+ memset(parameters, 0, sizeof(opj_dparameters_t));
+ /* default decoding parameters */
+ parameters->cp_layer = 0;
+ parameters->cp_reduce = 0;
+ parameters->cp_limit_decoding = NO_LIMITATION;
+
+ parameters->decod_format = -1;
+ parameters->cod_format = -1;
+/* UniPG>> */
+#ifdef USE_JPWL
+ parameters->jpwl_correct = false;
+ parameters->jpwl_exp_comps = JPWL_EXPECTED_COMPONENTS;
+ parameters->jpwl_max_tiles = JPWL_MAXIMUM_TILES;
+#endif /* USE_JPWL */
+/* <<UniPG */
+ }
+}
+
+void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters) {
+ if(dinfo && parameters) {
+ switch(dinfo->codec_format) {
+ case CODEC_J2K:
+ case CODEC_JPT:
+ j2k_setup_decoder((opj_j2k_t*)dinfo->j2k_handle, parameters);
+ break;
+ case CODEC_JP2:
+ jp2_setup_decoder((opj_jp2_t*)dinfo->jp2_handle, parameters);
+ break;
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ }
+}
+
+opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio) {
+ return opj_decode_with_info(dinfo, cio, NULL);
+}
+
+opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *cio, opj_codestream_info_t *cstr_info) {
+ if(dinfo && cio) {
+ switch(dinfo->codec_format) {
+ case CODEC_J2K:
+ return j2k_decode((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info);
+ case CODEC_JPT:
+ return j2k_decode_jpt_stream((opj_j2k_t*)dinfo->j2k_handle, cio, cstr_info);
+ case CODEC_JP2:
+ return jp2_decode((opj_jp2_t*)dinfo->jp2_handle, cio, cstr_info);
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format) {
+ opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_calloc(1, sizeof(opj_cinfo_t));
+ if(!cinfo) return NULL;
+ cinfo->is_decompressor = false;
+ switch(format) {
+ case CODEC_J2K:
+ /* get a J2K coder handle */
+ cinfo->j2k_handle = (void*)j2k_create_compress((opj_common_ptr)cinfo);
+ if(!cinfo->j2k_handle) {
+ opj_free(cinfo);
+ return NULL;
+ }
+ break;
+ case CODEC_JP2:
+ /* get a JP2 coder handle */
+ cinfo->jp2_handle = (void*)jp2_create_compress((opj_common_ptr)cinfo);
+ if(!cinfo->jp2_handle) {
+ opj_free(cinfo);
+ return NULL;
+ }
+ break;
+ case CODEC_JPT:
+ case CODEC_UNKNOWN:
+ default:
+ opj_free(cinfo);
+ return NULL;
+ }
+
+ cinfo->codec_format = format;
+
+ return cinfo;
+}
+
+void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo) {
+ if(cinfo) {
+ /* destroy the codec */
+ switch(cinfo->codec_format) {
+ case CODEC_J2K:
+ j2k_destroy_compress((opj_j2k_t*)cinfo->j2k_handle);
+ break;
+ case CODEC_JP2:
+ jp2_destroy_compress((opj_jp2_t*)cinfo->jp2_handle);
+ break;
+ case CODEC_JPT:
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ /* destroy the decompressor */
+ opj_free(cinfo);
+ }
+}
+
+void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters) {
+ if(parameters) {
+ memset(parameters, 0, sizeof(opj_cparameters_t));
+ /* default coding parameters */
+ parameters->cp_cinema = OFF;
+ parameters->max_comp_size = 0;
+ parameters->numresolution = 6;
+ parameters->cp_rsiz = STD_RSIZ;
+ parameters->cblockw_init = 64;
+ parameters->cblockh_init = 64;
+ parameters->prog_order = LRCP;
+ parameters->roi_compno = -1; /* no ROI */
+ parameters->subsampling_dx = 1;
+ parameters->subsampling_dy = 1;
+ parameters->tp_on = 0;
+ parameters->decod_format = -1;
+ parameters->cod_format = -1;
+ parameters->tcp_rates[0] = 0;
+ parameters->tcp_numlayers = 1;
+ parameters->cp_disto_alloc = 1;
+
+/* UniPG>> */
+#ifdef USE_JPWL
+ parameters->jpwl_epc_on = false;
+ parameters->jpwl_hprot_MH = -1; /* -1 means unassigned */
+ {
+ int i;
+ for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) {
+ parameters->jpwl_hprot_TPH_tileno[i] = -1; /* unassigned */
+ parameters->jpwl_hprot_TPH[i] = 0; /* absent */
+ }
+ };
+ {
+ int i;
+ for (i = 0; i < JPWL_MAX_NO_PACKSPECS; i++) {
+ parameters->jpwl_pprot_tileno[i] = -1; /* unassigned */
+ parameters->jpwl_pprot_packno[i] = -1; /* unassigned */
+ parameters->jpwl_pprot[i] = 0; /* absent */
+ }
+ };
+ parameters->jpwl_sens_size = 0; /* 0 means no ESD */
+ parameters->jpwl_sens_addr = 0; /* 0 means auto */
+ parameters->jpwl_sens_range = 0; /* 0 means packet */
+ parameters->jpwl_sens_MH = -1; /* -1 means unassigned */
+ {
+ int i;
+ for (i = 0; i < JPWL_MAX_NO_TILESPECS; i++) {
+ parameters->jpwl_sens_TPH_tileno[i] = -1; /* unassigned */
+ parameters->jpwl_sens_TPH[i] = -1; /* absent */
+ }
+ };
+#endif /* USE_JPWL */
+/* <<UniPG */
+ }
+}
+
+void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image) {
+ if(cinfo && parameters && image) {
+ switch(cinfo->codec_format) {
+ case CODEC_J2K:
+ j2k_setup_encoder((opj_j2k_t*)cinfo->j2k_handle, parameters, image);
+ break;
+ case CODEC_JP2:
+ jp2_setup_encoder((opj_jp2_t*)cinfo->jp2_handle, parameters, image);
+ break;
+ case CODEC_JPT:
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ }
+}
+
+bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index) {
+ if (index != NULL)
+ opj_event_msg((opj_common_ptr)cinfo, EVT_WARNING, "Set index to NULL when calling the opj_encode function.\n"
+ "To extract the index, use the opj_encode_with_info() function.\n"
+ "No index will be generated during this encoding\n");
+ return opj_encode_with_info(cinfo, cio, image, NULL);
+}
+
+bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info) {
+ if(cinfo && cio && image) {
+ switch(cinfo->codec_format) {
+ case CODEC_J2K:
+ return j2k_encode((opj_j2k_t*)cinfo->j2k_handle, cio, image, cstr_info);
+ case CODEC_JP2:
+ return jp2_encode((opj_jp2_t*)cinfo->jp2_handle, cio, image, cstr_info);
+ case CODEC_JPT:
+ case CODEC_UNKNOWN:
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info) {
+ if (cstr_info) {
+ int tileno;
+ for (tileno = 0; tileno < cstr_info->tw * cstr_info->th; tileno++) {
+ opj_tile_info_t *tile_info = &cstr_info->tile[tileno];
+ opj_free(tile_info->thresh);
+ opj_free(tile_info->packet);
+ opj_free(tile_info->tp);
+ }
+ opj_free(cstr_info->tile);
+ opj_free(cstr_info->marker);
+ opj_free(cstr_info->numdecompos);
+ }
+}
diff --git a/Source/LibOpenJPEG/openjpeg.h b/Source/LibOpenJPEG/openjpeg.h
new file mode 100644
index 0000000..a490e99
--- /dev/null
+++ b/Source/LibOpenJPEG/openjpeg.h
@@ -0,0 +1,911 @@
+ /*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPENJPEG_H
+#define OPENJPEG_H
+
+#define OPENJPEG_VERSION "1.3.0"
+
+/*
+==========================================================
+ Compiler directives
+==========================================================
+*/
+
+#if defined(OPJ_STATIC) || !(defined(WIN32) || defined(__WIN32__))
+#define OPJ_API
+#define OPJ_CALLCONV
+#else
+#define OPJ_CALLCONV __stdcall
+/*
+The following ifdef block is the standard way of creating macros which make exporting
+from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS
+symbol defined on the command line. this symbol should not be defined on any project
+that uses this DLL. This way any other project whose source files include this file see
+OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
+defined with this macro as being exported.
+*/
+#ifdef OPJ_EXPORTS
+#define OPJ_API __declspec(dllexport)
+#else
+#define OPJ_API __declspec(dllimport)
+#endif /* OPJ_EXPORTS */
+#endif /* !OPJ_STATIC || !WIN32 */
+
+#ifndef __cplusplus
+#if defined(HAVE_STDBOOL_H) || defined(__APPLE__)
+/*
+The C language implementation does correctly provide the standard header
+file "stdbool.h".
+ */
+#include <stdbool.h>
+#else
+/*
+The C language implementation does not provide the standard header file
+"stdbool.h" as required by ISO/IEC 9899:1999. Try to compensate for this
+braindamage below.
+*/
+#if !defined(bool)
+#define bool int
+#endif
+#if !defined(true)
+#define true 1
+#endif
+#if !defined(false)
+#define false 0
+#endif
+#endif
+#endif /* __cplusplus */
+
+/*
+==========================================================
+ Useful constant definitions
+==========================================================
+*/
+
+#define OPJ_PATH_LEN 4096 /**< Maximum allowed size for filenames */
+
+#define J2K_MAXRLVLS 33 /**< Number of maximum resolution level authorized */
+#define J2K_MAXBANDS (3*J2K_MAXRLVLS-2) /**< Number of maximum sub-band linked to number of resolution level */
+
+/* UniPG>> */
+#define JPWL_MAX_NO_TILESPECS 16 /**< Maximum number of tile parts expected by JPWL: increase at your will */
+#define JPWL_MAX_NO_PACKSPECS 16 /**< Maximum number of packet parts expected by JPWL: increase at your will */
+#define JPWL_MAX_NO_MARKERS 512 /**< Maximum number of JPWL markers: increase at your will */
+#define JPWL_PRIVATEINDEX_NAME "jpwl_index_privatefilename" /**< index file name used when JPWL is on */
+#define JPWL_EXPECTED_COMPONENTS 3 /**< Expect this number of components, so you'll find better the first EPB */
+#define JPWL_MAXIMUM_TILES 8192 /**< Expect this maximum number of tiles, to avoid some crashes */
+#define JPWL_MAXIMUM_HAMMING 2 /**< Expect this maximum number of bit errors in marker id's */
+#define JPWL_MAXIMUM_EPB_ROOM 65450 /**< Expect this maximum number of bytes for composition of EPBs */
+/* <<UniPG */
+
+/*
+==========================================================
+ enum definitions
+==========================================================
+*/
+/**
+Rsiz Capabilities
+*/
+typedef enum RSIZ_CAPABILITIES {
+ STD_RSIZ = 0, /** Standard JPEG2000 profile*/
+ CINEMA2K = 3, /** Profile name for a 2K image*/
+ CINEMA4K = 4 /** Profile name for a 4K image*/
+} OPJ_RSIZ_CAPABILITIES;
+
+/**
+Digital cinema operation mode
+*/
+typedef enum CINEMA_MODE {
+ OFF = 0, /** Not Digital Cinema*/
+ CINEMA2K_24 = 1, /** 2K Digital Cinema at 24 fps*/
+ CINEMA2K_48 = 2, /** 2K Digital Cinema at 48 fps*/
+ CINEMA4K_24 = 3 /** 4K Digital Cinema at 24 fps*/
+}OPJ_CINEMA_MODE;
+
+/**
+Progression order
+*/
+typedef enum PROG_ORDER {
+ PROG_UNKNOWN = -1, /**< place-holder */
+ LRCP = 0, /**< layer-resolution-component-precinct order */
+ RLCP = 1, /**< resolution-layer-component-precinct order */
+ RPCL = 2, /**< resolution-precinct-component-layer order */
+ PCRL = 3, /**< precinct-component-resolution-layer order */
+ CPRL = 4 /**< component-precinct-resolution-layer order */
+} OPJ_PROG_ORDER;
+
+/**
+Supported image color spaces
+*/
+typedef enum COLOR_SPACE {
+ CLRSPC_UNKNOWN = -1, /**< place-holder */
+ CLRSPC_SRGB = 1, /**< sRGB */
+ CLRSPC_GRAY = 2, /**< grayscale */
+ CLRSPC_SYCC = 3 /**< YUV */
+} OPJ_COLOR_SPACE;
+
+/**
+Supported codec
+*/
+typedef enum CODEC_FORMAT {
+ CODEC_UNKNOWN = -1, /**< place-holder */
+ CODEC_J2K = 0, /**< JPEG-2000 codestream : read/write */
+ CODEC_JPT = 1, /**< JPT-stream (JPEG 2000, JPIP) : read only */
+ CODEC_JP2 = 2 /**< JPEG-2000 file format : read/write */
+} OPJ_CODEC_FORMAT;
+
+/**
+Limit decoding to certain portions of the codestream.
+*/
+typedef enum LIMIT_DECODING {
+ NO_LIMITATION = 0, /**< No limitation for the decoding. The entire codestream will de decoded */
+ LIMIT_TO_MAIN_HEADER = 1, /**< The decoding is limited to the Main Header */
+ DECODE_ALL_BUT_PACKETS = 2 /**< Decode everything except the JPEG 2000 packets */
+} OPJ_LIMIT_DECODING;
+
+/*
+==========================================================
+ event manager typedef definitions
+==========================================================
+*/
+
+/**
+Callback function prototype for events
+@param msg Event message
+@param client_data
+*/
+typedef void (*opj_msg_callback) (const char *msg, void *client_data);
+
+/**
+Message handler object
+used for
+<ul>
+<li>Error messages
+<li>Warning messages
+<li>Debugging messages
+</ul>
+*/
+typedef struct opj_event_mgr {
+ /** Error message callback if available, NULL otherwise */
+ opj_msg_callback error_handler;
+ /** Warning message callback if available, NULL otherwise */
+ opj_msg_callback warning_handler;
+ /** Debug message callback if available, NULL otherwise */
+ opj_msg_callback info_handler;
+} opj_event_mgr_t;
+
+
+/*
+==========================================================
+ codec typedef definitions
+==========================================================
+*/
+
+/**
+Progression order changes
+*/
+typedef struct opj_poc {
+ /** Resolution num start, Component num start, given by POC */
+ int resno0, compno0;
+ /** Layer num end,Resolution num end, Component num end, given by POC */
+ int layno1, resno1, compno1;
+ /** Layer num start,Precinct num start, Precinct num end */
+ int layno0, precno0, precno1;
+ /** Progression order enum*/
+ OPJ_PROG_ORDER prg1,prg;
+ /** Progression order string*/
+ char progorder[5];
+ /** Tile number */
+ int tile;
+ /** Start and end values for Tile width and height*/
+ int tx0,tx1,ty0,ty1;
+ /** Start value, initialised in pi_initialise_encode*/
+ int layS, resS, compS, prcS;
+ /** End value, initialised in pi_initialise_encode */
+ int layE, resE, compE, prcE;
+ /** Start and end values of Tile width and height, initialised in pi_initialise_encode*/
+ int txS,txE,tyS,tyE,dx,dy;
+ /** Temporary values for Tile parts, initialised in pi_create_encode */
+ int lay_t, res_t, comp_t, prc_t,tx0_t,ty0_t;
+} opj_poc_t;
+
+/**
+Compression parameters
+*/
+typedef struct opj_cparameters {
+ /** size of tile: tile_size_on = false (not in argument) or = true (in argument) */
+ bool tile_size_on;
+ /** XTOsiz */
+ int cp_tx0;
+ /** YTOsiz */
+ int cp_ty0;
+ /** XTsiz */
+ int cp_tdx;
+ /** YTsiz */
+ int cp_tdy;
+ /** allocation by rate/distortion */
+ int cp_disto_alloc;
+ /** allocation by fixed layer */
+ int cp_fixed_alloc;
+ /** add fixed_quality */
+ int cp_fixed_quality;
+ /** fixed layer */
+ int *cp_matrice;
+ /** comment for coding */
+ char *cp_comment;
+ /** csty : coding style */
+ int csty;
+ /** progression order (default LRCP) */
+ OPJ_PROG_ORDER prog_order;
+ /** progression order changes */
+ opj_poc_t POC[32];
+ /** number of progression order changes (POC), default to 0 */
+ int numpocs;
+ /** number of layers */
+ int tcp_numlayers;
+ /** rates of layers */
+ float tcp_rates[100];
+ /** different psnr for successive layers */
+ float tcp_distoratio[100];
+ /** number of resolutions */
+ int numresolution;
+ /** initial code block width, default to 64 */
+ int cblockw_init;
+ /** initial code block height, default to 64 */
+ int cblockh_init;
+ /** mode switch (cblk_style) */
+ int mode;
+ /** 1 : use the irreversible DWT 9-7, 0 : use lossless compression (default) */
+ int irreversible;
+ /** region of interest: affected component in [0..3], -1 means no ROI */
+ int roi_compno;
+ /** region of interest: upshift value */
+ int roi_shift;
+ /* number of precinct size specifications */
+ int res_spec;
+ /** initial precinct width */
+ int prcw_init[J2K_MAXRLVLS];
+ /** initial precinct height */
+ int prch_init[J2K_MAXRLVLS];
+
+ /**@name command line encoder parameters (not used inside the library) */
+ /*@{*/
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */
+ int index_on;
+ /** DEPRECATED. Index generation is now handeld with the opj_encode_with_info() function. Set to NULL */
+ char index[OPJ_PATH_LEN];
+ /** subimage encoding: origin image offset in x direction */
+ int image_offset_x0;
+ /** subimage encoding: origin image offset in y direction */
+ int image_offset_y0;
+ /** subsampling value for dx */
+ int subsampling_dx;
+ /** subsampling value for dy */
+ int subsampling_dy;
+ /** input file format 0: PGX, 1: PxM, 2: BMP 3:TIF*/
+ int decod_format;
+ /** output file format 0: J2K, 1: JP2, 2: JPT */
+ int cod_format;
+ /*@}*/
+
+/* UniPG>> */
+ /**@name JPWL encoding parameters */
+ /*@{*/
+ /** enables writing of EPC in MH, thus activating JPWL */
+ bool jpwl_epc_on;
+ /** error protection method for MH (0,1,16,32,37-128) */
+ int jpwl_hprot_MH;
+ /** tile number of header protection specification (>=0) */
+ int jpwl_hprot_TPH_tileno[JPWL_MAX_NO_TILESPECS];
+ /** error protection methods for TPHs (0,1,16,32,37-128) */
+ int jpwl_hprot_TPH[JPWL_MAX_NO_TILESPECS];
+ /** tile number of packet protection specification (>=0) */
+ int jpwl_pprot_tileno[JPWL_MAX_NO_PACKSPECS];
+ /** packet number of packet protection specification (>=0) */
+ int jpwl_pprot_packno[JPWL_MAX_NO_PACKSPECS];
+ /** error protection methods for packets (0,1,16,32,37-128) */
+ int jpwl_pprot[JPWL_MAX_NO_PACKSPECS];
+ /** enables writing of ESD, (0=no/1/2 bytes) */
+ int jpwl_sens_size;
+ /** sensitivity addressing size (0=auto/2/4 bytes) */
+ int jpwl_sens_addr;
+ /** sensitivity range (0-3) */
+ int jpwl_sens_range;
+ /** sensitivity method for MH (-1=no,0-7) */
+ int jpwl_sens_MH;
+ /** tile number of sensitivity specification (>=0) */
+ int jpwl_sens_TPH_tileno[JPWL_MAX_NO_TILESPECS];
+ /** sensitivity methods for TPHs (-1=no,0-7) */
+ int jpwl_sens_TPH[JPWL_MAX_NO_TILESPECS];
+ /*@}*/
+/* <<UniPG */
+
+ /** Digital Cinema compliance 0-not compliant, 1-compliant*/
+ OPJ_CINEMA_MODE cp_cinema;
+ /** Maximum rate for each component. If == 0, component size limitation is not considered */
+ int max_comp_size;
+ /** Profile name*/
+ OPJ_RSIZ_CAPABILITIES cp_rsiz;
+ /** Tile part generation*/
+ char tp_on;
+ /** Flag for Tile part generation*/
+ char tp_flag;
+ /** MCT (multiple component transform) */
+ char tcp_mct;
+} opj_cparameters_t;
+
+/**
+Decompression parameters
+*/
+typedef struct opj_dparameters {
+ /**
+ Set the number of highest resolution levels to be discarded.
+ The image resolution is effectively divided by 2 to the power of the number of discarded levels.
+ The reduce factor is limited by the smallest total number of decomposition levels among tiles.
+ if != 0, then original dimension divided by 2^(reduce);
+ if == 0 or not used, image is decoded to the full resolution
+ */
+ int cp_reduce;
+ /**
+ Set the maximum number of quality layers to decode.
+ If there are less quality layers than the specified number, all the quality layers are decoded.
+ if != 0, then only the first "layer" layers are decoded;
+ if == 0 or not used, all the quality layers are decoded
+ */
+ int cp_layer;
+
+ /**@name command line encoder parameters (not used inside the library) */
+ /*@{*/
+ /** input file name */
+ char infile[OPJ_PATH_LEN];
+ /** output file name */
+ char outfile[OPJ_PATH_LEN];
+ /** input file format 0: J2K, 1: JP2, 2: JPT */
+ int decod_format;
+ /** output file format 0: PGX, 1: PxM, 2: BMP */
+ int cod_format;
+ /*@}*/
+
+/* UniPG>> */
+ /**@name JPWL decoding parameters */
+ /*@{*/
+ /** activates the JPWL correction capabilities */
+ bool jpwl_correct;
+ /** expected number of components */
+ int jpwl_exp_comps;
+ /** maximum number of tiles */
+ int jpwl_max_tiles;
+ /*@}*/
+/* <<UniPG */
+
+ /**
+ Specify whether the decoding should be done on the entire codestream, or be limited to the main header
+ Limiting the decoding to the main header makes it possible to extract the characteristics of the codestream
+ if == NO_LIMITATION, the entire codestream is decoded;
+ if == LIMIT_TO_MAIN_HEADER, only the main header is decoded;
+ */
+ OPJ_LIMIT_DECODING cp_limit_decoding;
+
+} opj_dparameters_t;
+
+/** Common fields between JPEG-2000 compression and decompression master structs. */
+
+#define opj_common_fields \
+ opj_event_mgr_t *event_mgr; /**< pointer to the event manager */\
+ void * client_data; /**< Available for use by application */\
+ bool is_decompressor; /**< So common code can tell which is which */\
+ OPJ_CODEC_FORMAT codec_format; /**< selected codec */\
+ void *j2k_handle; /**< pointer to the J2K codec */\
+ void *jp2_handle; /**< pointer to the JP2 codec */\
+ void *mj2_handle /**< pointer to the MJ2 codec */
+
+/* Routines that are to be used by both halves of the library are declared
+ * to receive a pointer to this structure. There are no actual instances of
+ * opj_common_struct_t, only of opj_cinfo_t and opj_dinfo_t.
+ */
+typedef struct opj_common_struct {
+ opj_common_fields; /* Fields common to both master struct types */
+ /* Additional fields follow in an actual opj_cinfo_t or
+ * opj_dinfo_t. All three structs must agree on these
+ * initial fields! (This would be a lot cleaner in C++.)
+ */
+} opj_common_struct_t;
+
+typedef opj_common_struct_t * opj_common_ptr;
+
+/**
+Compression context info
+*/
+typedef struct opj_cinfo {
+ /** Fields shared with opj_dinfo_t */
+ opj_common_fields;
+ /* other specific fields go here */
+} opj_cinfo_t;
+
+/**
+Decompression context info
+*/
+typedef struct opj_dinfo {
+ /** Fields shared with opj_cinfo_t */
+ opj_common_fields;
+ /* other specific fields go here */
+} opj_dinfo_t;
+
+/*
+==========================================================
+ I/O stream typedef definitions
+==========================================================
+*/
+
+/*
+ * Stream open flags.
+ */
+/** The stream was opened for reading. */
+#define OPJ_STREAM_READ 0x0001
+/** The stream was opened for writing. */
+#define OPJ_STREAM_WRITE 0x0002
+
+/**
+Byte input-output stream (CIO)
+*/
+typedef struct opj_cio {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** open mode (read/write) either OPJ_STREAM_READ or OPJ_STREAM_WRITE */
+ int openmode;
+ /** pointer to the start of the buffer */
+ unsigned char *buffer;
+ /** buffer size in bytes */
+ int length;
+
+ /** pointer to the start of the stream */
+ unsigned char *start;
+ /** pointer to the end of the stream */
+ unsigned char *end;
+ /** pointer to the current position */
+ unsigned char *bp;
+} opj_cio_t;
+
+/*
+==========================================================
+ image typedef definitions
+==========================================================
+*/
+
+/**
+Defines a single image component
+*/
+typedef struct opj_image_comp {
+ /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+ int dx;
+ /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+ int dy;
+ /** data width */
+ int w;
+ /** data height */
+ int h;
+ /** x component offset compared to the whole image */
+ int x0;
+ /** y component offset compared to the whole image */
+ int y0;
+ /** precision */
+ int prec;
+ /** image depth in bits */
+ int bpp;
+ /** signed (1) / unsigned (0) */
+ int sgnd;
+ /** number of decoded resolution */
+ int resno_decoded;
+ /** number of division by 2 of the out image compared to the original size of image */
+ int factor;
+ /** image component data */
+ int *data;
+} opj_image_comp_t;
+
+/**
+Defines image data and characteristics
+*/
+typedef struct opj_image {
+ /** XOsiz: horizontal offset from the origin of the reference grid to the left side of the image area */
+ int x0;
+ /** YOsiz: vertical offset from the origin of the reference grid to the top side of the image area */
+ int y0;
+ /** Xsiz: width of the reference grid */
+ int x1;
+ /** Ysiz: height of the reference grid */
+ int y1;
+ /** number of components in the image */
+ int numcomps;
+ /** color space: sRGB, Greyscale or YUV */
+ OPJ_COLOR_SPACE color_space;
+ /** image components */
+ opj_image_comp_t *comps;
+} opj_image_t;
+
+/**
+Component parameters structure used by the opj_image_create function
+*/
+typedef struct opj_image_comptparm {
+ /** XRsiz: horizontal separation of a sample of ith component with respect to the reference grid */
+ int dx;
+ /** YRsiz: vertical separation of a sample of ith component with respect to the reference grid */
+ int dy;
+ /** data width */
+ int w;
+ /** data height */
+ int h;
+ /** x component offset compared to the whole image */
+ int x0;
+ /** y component offset compared to the whole image */
+ int y0;
+ /** precision */
+ int prec;
+ /** image depth in bits */
+ int bpp;
+ /** signed (1) / unsigned (0) */
+ int sgnd;
+} opj_image_cmptparm_t;
+
+/*
+==========================================================
+ Information on the JPEG 2000 codestream
+==========================================================
+*/
+
+/**
+Index structure : Information concerning a packet inside tile
+*/
+typedef struct opj_packet_info {
+ /** packet start position (including SOP marker if it exists) */
+ int start_pos;
+ /** end of packet header position (including EPH marker if it exists)*/
+ int end_ph_pos;
+ /** packet end position */
+ int end_pos;
+ /** packet distorsion */
+ double disto;
+} opj_packet_info_t;
+
+/**
+Index structure : Information concerning tile-parts
+*/
+typedef struct opj_tp_info {
+ /** start position of tile part */
+ int tp_start_pos;
+ /** end position of tile part header */
+ int tp_end_header;
+ /** end position of tile part */
+ int tp_end_pos;
+ /** start packet of tile part */
+ int tp_start_pack;
+ /** number of packets of tile part */
+ int tp_numpacks;
+} opj_tp_info_t;
+
+/**
+Index structure : information regarding tiles
+*/
+typedef struct opj_tile_info {
+ /** value of thresh for each layer by tile cfr. Marcela */
+ double *thresh;
+ /** number of tile */
+ int tileno;
+ /** start position */
+ int start_pos;
+ /** end position of the header */
+ int end_header;
+ /** end position */
+ int end_pos;
+ /** precinct number for each resolution level (width) */
+ int pw[33];
+ /** precinct number for each resolution level (height) */
+ int ph[33];
+ /** precinct size (in power of 2), in X for each resolution level */
+ int pdx[33];
+ /** precinct size (in power of 2), in Y for each resolution level */
+ int pdy[33];
+ /** information concerning packets inside tile */
+ opj_packet_info_t *packet;
+ /** add fixed_quality */
+ int numpix;
+ /** add fixed_quality */
+ double distotile;
+ /** number of tile parts */
+ int num_tps;
+ /** information concerning tile parts */
+ opj_tp_info_t *tp;
+} opj_tile_info_t;
+
+/* UniPG>> */
+/**
+Marker structure
+*/
+typedef struct opj_marker_info_t {
+ /** marker type */
+ unsigned short int type;
+ /** position in codestream */
+ int pos;
+ /** length, marker val included */
+ int len;
+} opj_marker_info_t;
+/* <<UniPG */
+
+/**
+Index structure of the codestream
+*/
+typedef struct opj_codestream_info {
+ /** maximum distortion reduction on the whole image (add for Marcela) */
+ double D_max;
+ /** packet number */
+ int packno;
+ /** writing the packet in the index with t2_encode_packets */
+ int index_write;
+ /** image width */
+ int image_w;
+ /** image height */
+ int image_h;
+ /** progression order */
+ OPJ_PROG_ORDER prog;
+ /** tile size in x */
+ int tile_x;
+ /** tile size in y */
+ int tile_y;
+ /** */
+ int tile_Ox;
+ /** */
+ int tile_Oy;
+ /** number of tiles in X */
+ int tw;
+ /** number of tiles in Y */
+ int th;
+ /** component numbers */
+ int numcomps;
+ /** number of layer */
+ int numlayers;
+ /** number of decomposition for each component */
+ int *numdecompos;
+/* UniPG>> */
+ /** number of markers */
+ int marknum;
+ /** list of markers */
+ opj_marker_info_t *marker;
+ /** actual size of markers array */
+ int maxmarknum;
+/* <<UniPG */
+ /** main header position */
+ int main_head_start;
+ /** main header position */
+ int main_head_end;
+ /** codestream's size */
+ int codestream_size;
+ /** information regarding tiles inside image */
+ opj_tile_info_t *tile;
+} opj_codestream_info_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+==========================================================
+ openjpeg version
+==========================================================
+*/
+
+OPJ_API const char * OPJ_CALLCONV opj_version(void);
+
+/*
+==========================================================
+ image functions definitions
+==========================================================
+*/
+
+/**
+Create an image
+@param numcmpts number of components
+@param cmptparms components parameters
+@param clrspc image color space
+@return returns a new image structure if successful, returns NULL otherwise
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_image_create(int numcmpts, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc);
+
+/**
+Deallocate any resources associated with an image
+@param image image to be destroyed
+*/
+OPJ_API void OPJ_CALLCONV opj_image_destroy(opj_image_t *image);
+
+/*
+==========================================================
+ stream functions definitions
+==========================================================
+*/
+
+/**
+Open and allocate a memory stream for read / write.
+On reading, the user must provide a buffer containing encoded data. The buffer will be
+wrapped by the returned CIO handle.
+On writing, buffer parameters must be set to 0: a buffer will be allocated by the library
+to contain encoded data.
+@param cinfo Codec context info
+@param buffer Reading: buffer address. Writing: NULL
+@param length Reading: buffer length. Writing: 0
+@return Returns a CIO handle if successful, returns NULL otherwise
+*/
+OPJ_API opj_cio_t* OPJ_CALLCONV opj_cio_open(opj_common_ptr cinfo, unsigned char *buffer, int length);
+
+/**
+Close and free a CIO handle
+@param cio CIO handle to free
+*/
+OPJ_API void OPJ_CALLCONV opj_cio_close(opj_cio_t *cio);
+
+/**
+Get position in byte stream
+@param cio CIO handle
+@return Returns the position in bytes
+*/
+OPJ_API int OPJ_CALLCONV cio_tell(opj_cio_t *cio);
+/**
+Set position in byte stream
+@param cio CIO handle
+@param pos Position, in number of bytes, from the beginning of the stream
+*/
+OPJ_API void OPJ_CALLCONV cio_seek(opj_cio_t *cio, int pos);
+
+/*
+==========================================================
+ event manager functions definitions
+==========================================================
+*/
+
+OPJ_API opj_event_mgr_t* OPJ_CALLCONV opj_set_event_mgr(opj_common_ptr cinfo, opj_event_mgr_t *event_mgr, void *context);
+
+/*
+==========================================================
+ codec functions definitions
+==========================================================
+*/
+/**
+Creates a J2K/JPT/JP2 decompression structure
+@param format Decoder to select
+@return Returns a handle to a decompressor if successful, returns NULL otherwise
+*/
+OPJ_API opj_dinfo_t* OPJ_CALLCONV opj_create_decompress(OPJ_CODEC_FORMAT format);
+/**
+Destroy a decompressor handle
+@param dinfo decompressor handle to destroy
+*/
+OPJ_API void OPJ_CALLCONV opj_destroy_decompress(opj_dinfo_t *dinfo);
+/**
+Set decoding parameters to default values
+@param parameters Decompression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_set_default_decoder_parameters(opj_dparameters_t *parameters);
+/**
+Setup the decoder decoding parameters using user parameters.
+Decoding parameters are returned in j2k->cp.
+@param dinfo decompressor handle
+@param parameters decompression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_setup_decoder(opj_dinfo_t *dinfo, opj_dparameters_t *parameters);
+/**
+Decode an image from a JPEG-2000 codestream
+@param dinfo decompressor handle
+@param cio Input buffer stream
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_decode(opj_dinfo_t *dinfo, opj_cio_t *cio);
+
+/**
+Decode an image from a JPEG-2000 codestream and extract the codestream information
+@param dinfo decompressor handle
+@param cio Input buffer stream
+@param cstr_info Codestream information structure if needed afterwards, NULL otherwise
+@return Returns a decoded image if successful, returns NULL otherwise
+*/
+OPJ_API opj_image_t* OPJ_CALLCONV opj_decode_with_info(opj_dinfo_t *dinfo, opj_cio_t *cio, opj_codestream_info_t *cstr_info);
+/**
+Creates a J2K/JP2 compression structure
+@param format Coder to select
+@return Returns a handle to a compressor if successful, returns NULL otherwise
+*/
+OPJ_API opj_cinfo_t* OPJ_CALLCONV opj_create_compress(OPJ_CODEC_FORMAT format);
+/**
+Destroy a compressor handle
+@param cinfo compressor handle to destroy
+*/
+OPJ_API void OPJ_CALLCONV opj_destroy_compress(opj_cinfo_t *cinfo);
+/**
+Set encoding parameters to default values, that means :
+<ul>
+<li>Lossless
+<li>1 tile
+<li>Size of precinct : 2^15 x 2^15 (means 1 precinct)
+<li>Size of code-block : 64 x 64
+<li>Number of resolutions: 6
+<li>No SOP marker in the codestream
+<li>No EPH marker in the codestream
+<li>No sub-sampling in x or y direction
+<li>No mode switch activated
+<li>Progression order: LRCP
+<li>No index file
+<li>No ROI upshifted
+<li>No offset of the origin of the image
+<li>No offset of the origin of the tiles
+<li>Reversible DWT 5-3
+</ul>
+@param parameters Compression parameters
+*/
+OPJ_API void OPJ_CALLCONV opj_set_default_encoder_parameters(opj_cparameters_t *parameters);
+/**
+Setup the encoder parameters using the current image and using user parameters.
+@param cinfo Compressor handle
+@param parameters Compression parameters
+@param image Input filled image
+*/
+OPJ_API void OPJ_CALLCONV opj_setup_encoder(opj_cinfo_t *cinfo, opj_cparameters_t *parameters, opj_image_t *image);
+/**
+Encode an image into a JPEG-2000 codestream
+@param cinfo compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param index Depreacted -> Set to NULL. To extract index, used opj_encode_wci()
+@return Returns true if successful, returns false otherwise
+*/
+OPJ_API bool OPJ_CALLCONV opj_encode(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, char *index);
+/**
+Encode an image into a JPEG-2000 codestream and extract the codestream information
+@param cinfo compressor handle
+@param cio Output buffer stream
+@param image Image to encode
+@param cstr_info Codestream information structure if needed afterwards, NULL otherwise
+@return Returns true if successful, returns false otherwise
+*/
+OPJ_API bool OPJ_CALLCONV opj_encode_with_info(opj_cinfo_t *cinfo, opj_cio_t *cio, opj_image_t *image, opj_codestream_info_t *cstr_info);
+/**
+Destroy Codestream information after compression or decompression
+@param cstr_info Codestream information structure
+*/
+OPJ_API void OPJ_CALLCONV opj_destroy_cstr_info(opj_codestream_info_t *cstr_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPENJPEG_H */
diff --git a/Source/LibOpenJPEG/opj_includes.h b/Source/LibOpenJPEG/opj_includes.h
new file mode 100644
index 0000000..8383897
--- /dev/null
+++ b/Source/LibOpenJPEG/opj_includes.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPJ_INCLUDES_H
+#define OPJ_INCLUDES_H
+
+/*
+ ==========================================================
+ Standard includes used by the library
+ ==========================================================
+*/
+#include <memory.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+/*
+ ==========================================================
+ OpenJPEG interface
+ ==========================================================
+ */
+#include "openjpeg.h"
+
+/*
+ ==========================================================
+ OpenJPEG modules
+ ==========================================================
+*/
+
+/* Ignore GCC attributes if this is not GCC */
+#ifndef __GNUC__
+ #define __attribute__(x) /* __attribute__(x) */
+#endif
+
+/*
+The inline keyword is supported by C99 but not by C90.
+Most compilers implement their own version of this keyword ...
+*/
+#ifndef INLINE
+ #if defined(_MSC_VER)
+ #define INLINE __inline
+ #elif defined(__GNUC__)
+ #define INLINE __inline__
+ #elif defined(__MWERKS__)
+ #define INLINE inline
+ #else
+ /* add other compilers here ... */
+ #define INLINE
+ #endif /* defined(<Compiler>) */
+#endif /* INLINE */
+
+/* Are restricted pointers available? (C99) */
+#if (__STDC_VERSION__ != 199901L)
+ /* Not a C99 compiler */
+ #ifdef __GNUC__
+ #define restrict __restrict__
+ #else
+ #define restrict /* restrict */
+ #endif
+#endif
+
+/* MSVC does not have lrintf */
+#ifdef _MSC_VER
+static INLINE long lrintf(float f){
+#ifdef _M_X64
+ return (long)((f > 0.0f) ? (f + 0.5f) : (f - 0.5f));
+#else
+ int i;
+ _asm{
+ fld f
+ fistp i
+ };
+ return i;
+#endif // _M_X64
+}
+#endif // _MSC_VER
+
+#include "j2k_lib.h"
+#include "opj_malloc.h"
+#include "event.h"
+#include "cio.h"
+
+#include "image.h"
+#include "j2k.h"
+#include "jp2.h"
+#include "jpt.h"
+
+#include "mqc.h"
+#include "raw.h"
+#include "bio.h"
+#include "tgt.h"
+#include "pi.h"
+#include "tcd.h"
+#include "t1.h"
+#include "dwt.h"
+#include "t2.h"
+#include "mct.h"
+#include "int.h"
+#include "fix.h"
+
+/* JPWL>> */
+#ifdef USE_JPWL
+#include "../jpwl/jpwl.h"
+#endif /* USE_JPWL */
+/* <<JPWL */
+
+#endif /* OPJ_INCLUDES_H */
diff --git a/Source/LibOpenJPEG/opj_malloc.h b/Source/LibOpenJPEG/opj_malloc.h
new file mode 100644
index 0000000..5de681d
--- /dev/null
+++ b/Source/LibOpenJPEG/opj_malloc.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2005, Hervé Drolon, FreeImage Team
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __OPJ_MALLOC_H
+#define __OPJ_MALLOC_H
+/**
+@file opj_malloc.h
+@brief Internal functions
+
+The functions in opj_malloc.h are internal utilities used for memory management.
+*/
+
+/** @defgroup MISC MISC - Miscellaneous internal functions */
+/*@{*/
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Allocate an uninitialized memory block
+@param size Bytes to allocate
+@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+*/
+#define opj_malloc(size) malloc(size)
+
+/**
+Allocate a memory block with elements initialized to 0
+@param num Blocks to allocate
+@param size Bytes per block to allocate
+@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+*/
+#define opj_calloc(num, size) calloc(num, size)
+
+/**
+Allocate memory aligned to a 16 byte boundry
+@param size Bytes to allocate
+@return Returns a void pointer to the allocated space, or NULL if there is insufficient memory available
+*/
+/* FIXME: These should be set with cmake tests, but we're currently not requiring use of cmake */
+#ifdef WIN32
+ /* Someone should tell the mingw people that their malloc.h ought to provide _mm_malloc() */
+ #ifdef __GNUC__
+ #include <mm_malloc.h>
+ #define HAVE_MM_MALLOC
+ #else /* MSVC, Intel C++ */
+ #include <malloc.h>
+ #ifdef _mm_malloc
+ #define HAVE_MM_MALLOC
+ #endif
+ #endif
+#else /* Not WIN32 */
+ #if defined(__sun)
+ #define HAVE_MEMALIGN
+ /* Linux x86_64 and OSX always align allocations to 16 bytes */
+ #elif !defined(__amd64__) && !defined(__APPLE__)
+ #define HAVE_MEMALIGN
+ #include <malloc.h>
+ #endif
+#endif
+
+#define opj_aligned_malloc(size) malloc(size)
+#define opj_aligned_free(m) free(m)
+
+#ifdef HAVE_MM_MALLOC
+ #undef opj_aligned_malloc
+ #define opj_aligned_malloc(size) _mm_malloc(size, 16)
+ #undef opj_aligned_free
+ #define opj_aligned_free(m) _mm_free(m)
+#endif
+
+#ifdef HAVE_MEMALIGN
+ extern void* memalign(size_t, size_t);
+ #undef opj_aligned_malloc
+ #define opj_aligned_malloc(size) memalign(16, (size))
+ #undef opj_aligned_free
+ #define opj_aligned_free(m) free(m)
+#endif
+
+#ifdef HAVE_POSIX_MEMALIGN
+ #undef opj_aligned_malloc
+ extern int posix_memalign(void**, size_t, size_t);
+
+ static INLINE void* __attribute__ ((malloc)) opj_aligned_malloc(size_t size){
+ void* mem = NULL;
+ posix_memalign(&mem, 16, size);
+ return mem;
+ }
+ #undef opj_aligned_free
+ #define opj_aligned_free(m) free(m)
+#endif
+
+/**
+Reallocate memory blocks.
+@param memblock Pointer to previously allocated memory block
+@param size New size in bytes
+@return Returns a void pointer to the reallocated (and possibly moved) memory block
+*/
+#define opj_realloc(m, s) realloc(m, s)
+
+/**
+Deallocates or frees a memory block.
+@param memblock Previously allocated memory block to be freed
+*/
+#define opj_free(m) free(m)
+
+#ifdef __GNUC__
+#pragma GCC poison malloc calloc realloc free
+#endif
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __OPJ_MALLOC_H */
+
diff --git a/Source/LibOpenJPEG/pi.c b/Source/LibOpenJPEG/pi.c
new file mode 100644
index 0000000..ac7654c
--- /dev/null
+++ b/Source/LibOpenJPEG/pi.c
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup PI PI - Implementation of a packet iterator */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+/**
+Get next packet in layer-resolution-component-precinct order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true
+*/
+static bool pi_next_lrcp(opj_pi_iterator_t * pi);
+/**
+Get next packet in resolution-layer-component-precinct order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true
+*/
+static bool pi_next_rlcp(opj_pi_iterator_t * pi);
+/**
+Get next packet in resolution-precinct-component-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true
+*/
+static bool pi_next_rpcl(opj_pi_iterator_t * pi);
+/**
+Get next packet in precinct-component-resolution-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true
+*/
+static bool pi_next_pcrl(opj_pi_iterator_t * pi);
+/**
+Get next packet in component-precinct-resolution-layer order.
+@param pi packet iterator to modify
+@return returns false if pi pointed to the last packet or else returns true
+*/
+static bool pi_next_cprl(opj_pi_iterator_t * pi);
+
+/*@}*/
+
+/*@}*/
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+static bool pi_next_lrcp(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ comp = &pi->comps[pi->compno];
+ res = &comp->resolutions[pi->resno];
+ goto LABEL_SKIP;
+ } else {
+ pi->first = 0;
+ }
+
+ for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
+ for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1;
+ pi->resno++) {
+ for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+ comp = &pi->comps[pi->compno];
+ if (pi->resno >= comp->numresolutions) {
+ continue;
+ }
+ res = &comp->resolutions[pi->resno];
+ if (!pi->tp_on){
+ pi->poc.precno1 = res->pw * res->ph;
+ }
+ for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
+ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+ if (!pi->include[index]) {
+ pi->include[index] = 1;
+ return true;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool pi_next_rlcp(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ comp = &pi->comps[pi->compno];
+ res = &comp->resolutions[pi->resno];
+ goto LABEL_SKIP;
+ } else {
+ pi->first = 0;
+ }
+
+ for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
+ for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
+ for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+ comp = &pi->comps[pi->compno];
+ if (pi->resno >= comp->numresolutions) {
+ continue;
+ }
+ res = &comp->resolutions[pi->resno];
+ if(!pi->tp_on){
+ pi->poc.precno1 = res->pw * res->ph;
+ }
+ for (pi->precno = pi->poc.precno0; pi->precno < pi->poc.precno1; pi->precno++) {
+ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+ if (!pi->include[index]) {
+ pi->include[index] = 1;
+ return true;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool pi_next_rpcl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ goto LABEL_SKIP;
+ } else {
+ int compno, resno;
+ pi->first = 0;
+ pi->dx = 0;
+ pi->dy = 0;
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ comp = &pi->comps[compno];
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int dx, dy;
+ res = &comp->resolutions[resno];
+ dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+ dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+ pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+ pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+ }
+ }
+ }
+if (!pi->tp_on){
+ pi->poc.ty0 = pi->ty0;
+ pi->poc.tx0 = pi->tx0;
+ pi->poc.ty1 = pi->ty1;
+ pi->poc.tx1 = pi->tx1;
+ }
+ for (pi->resno = pi->poc.resno0; pi->resno < pi->poc.resno1; pi->resno++) {
+ for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+ for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+ for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int prci, prcj;
+ comp = &pi->comps[pi->compno];
+ if (pi->resno >= comp->numresolutions) {
+ continue;
+ }
+ res = &comp->resolutions[pi->resno];
+ levelno = comp->numresolutions - 1 - pi->resno;
+ trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+ try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+ trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+ try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+ rpx = res->pdx + levelno;
+ rpy = res->pdy + levelno;
+ if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+ if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+
+ if ((res->pw==0)||(res->pw==0)) continue;
+
+ if ((trx0==trx1)||(try0==try1)) continue;
+
+ prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
+ - int_floordivpow2(trx0, res->pdx);
+ prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
+ - int_floordivpow2(try0, res->pdy);
+ pi->precno = prci + prcj * res->pw;
+ for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
+ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+ if (!pi->include[index]) {
+ pi->include[index] = 1;
+ return true;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool pi_next_pcrl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ comp = &pi->comps[pi->compno];
+ goto LABEL_SKIP;
+ } else {
+ int compno, resno;
+ pi->first = 0;
+ pi->dx = 0;
+ pi->dy = 0;
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ comp = &pi->comps[compno];
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int dx, dy;
+ res = &comp->resolutions[resno];
+ dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+ dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+ pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+ pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+ }
+ }
+ }
+ if (!pi->tp_on){
+ pi->poc.ty0 = pi->ty0;
+ pi->poc.tx0 = pi->tx0;
+ pi->poc.ty1 = pi->ty1;
+ pi->poc.tx1 = pi->tx1;
+ }
+ for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+ for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+ for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+ comp = &pi->comps[pi->compno];
+ for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int prci, prcj;
+ res = &comp->resolutions[pi->resno];
+ levelno = comp->numresolutions - 1 - pi->resno;
+ trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+ try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+ trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+ try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+ rpx = res->pdx + levelno;
+ rpy = res->pdy + levelno;
+ if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+ if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+
+ if ((res->pw==0)||(res->pw==0)) continue;
+
+ if ((trx0==trx1)||(try0==try1)) continue;
+
+ prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
+ - int_floordivpow2(trx0, res->pdx);
+ prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
+ - int_floordivpow2(try0, res->pdy);
+ pi->precno = prci + prcj * res->pw;
+ for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
+ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+ if (!pi->include[index]) {
+ pi->include[index] = 1;
+ return true;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool pi_next_cprl(opj_pi_iterator_t * pi) {
+ opj_pi_comp_t *comp = NULL;
+ opj_pi_resolution_t *res = NULL;
+ long index = 0;
+
+ if (!pi->first) {
+ comp = &pi->comps[pi->compno];
+ goto LABEL_SKIP;
+ } else {
+ pi->first = 0;
+ }
+
+ for (pi->compno = pi->poc.compno0; pi->compno < pi->poc.compno1; pi->compno++) {
+ int resno;
+ comp = &pi->comps[pi->compno];
+ pi->dx = 0;
+ pi->dy = 0;
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int dx, dy;
+ res = &comp->resolutions[resno];
+ dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+ dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+ pi->dx = !pi->dx ? dx : int_min(pi->dx, dx);
+ pi->dy = !pi->dy ? dy : int_min(pi->dy, dy);
+ }
+ if (!pi->tp_on){
+ pi->poc.ty0 = pi->ty0;
+ pi->poc.tx0 = pi->tx0;
+ pi->poc.ty1 = pi->ty1;
+ pi->poc.tx1 = pi->tx1;
+ }
+ for (pi->y = pi->poc.ty0; pi->y < pi->poc.ty1; pi->y += pi->dy - (pi->y % pi->dy)) {
+ for (pi->x = pi->poc.tx0; pi->x < pi->poc.tx1; pi->x += pi->dx - (pi->x % pi->dx)) {
+ for (pi->resno = pi->poc.resno0; pi->resno < int_min(pi->poc.resno1, comp->numresolutions); pi->resno++) {
+ int levelno;
+ int trx0, try0;
+ int trx1, try1;
+ int rpx, rpy;
+ int prci, prcj;
+ res = &comp->resolutions[pi->resno];
+ levelno = comp->numresolutions - 1 - pi->resno;
+ trx0 = int_ceildiv(pi->tx0, comp->dx << levelno);
+ try0 = int_ceildiv(pi->ty0, comp->dy << levelno);
+ trx1 = int_ceildiv(pi->tx1, comp->dx << levelno);
+ try1 = int_ceildiv(pi->ty1, comp->dy << levelno);
+ rpx = res->pdx + levelno;
+ rpy = res->pdy + levelno;
+ if (!((pi->y % (comp->dy << rpy) == 0) || ((pi->y == pi->ty0) && ((try0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+ if (!((pi->x % (comp->dx << rpx) == 0) || ((pi->x == pi->tx0) && ((trx0 << levelno) % (1 << rpx))))){
+ continue;
+ }
+
+ if ((res->pw==0)||(res->pw==0)) continue;
+
+ if ((trx0==trx1)||(try0==try1)) continue;
+
+ prci = int_floordivpow2(int_ceildiv(pi->x, comp->dx << levelno), res->pdx)
+ - int_floordivpow2(trx0, res->pdx);
+ prcj = int_floordivpow2(int_ceildiv(pi->y, comp->dy << levelno), res->pdy)
+ - int_floordivpow2(try0, res->pdy);
+ pi->precno = prci + prcj * res->pw;
+ for (pi->layno = pi->poc.layno0; pi->layno < pi->poc.layno1; pi->layno++) {
+ index = pi->layno * pi->step_l + pi->resno * pi->step_r + pi->compno * pi->step_c + pi->precno * pi->step_p;
+ if (!pi->include[index]) {
+ pi->include[index] = 1;
+ return true;
+ }
+LABEL_SKIP:;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/*
+==========================================================
+ Packet iterator interface
+==========================================================
+*/
+
+opj_pi_iterator_t *pi_create_decode(opj_image_t *image, opj_cp_t *cp, int tileno) {
+ int p, q;
+ int compno, resno, pino;
+ opj_pi_iterator_t *pi = NULL;
+ opj_tcp_t *tcp = NULL;
+ opj_tccp_t *tccp = NULL;
+
+ tcp = &cp->tcps[tileno];
+
+ pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t));
+ if(!pi) {
+ /* TODO: throw an error */
+ return NULL;
+ }
+
+ for (pino = 0; pino < tcp->numpocs + 1; pino++) { /* change */
+ int maxres = 0;
+ int maxprec = 0;
+ p = tileno % cp->tw;
+ q = tileno / cp->tw;
+
+ pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+ pi[pino].numcomps = image->numcomps;
+
+ pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t));
+ if(!pi[pino].comps) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ int tcx0, tcy0, tcx1, tcy1;
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ tccp = &tcp->tccps[compno];
+ comp->dx = image->comps[compno].dx;
+ comp->dy = image->comps[compno].dy;
+ comp->numresolutions = tccp->numresolutions;
+
+ comp->resolutions = (opj_pi_resolution_t*) opj_calloc(comp->numresolutions, sizeof(opj_pi_resolution_t));
+ if(!comp->resolutions) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ tcx0 = int_ceildiv(pi->tx0, comp->dx);
+ tcy0 = int_ceildiv(pi->ty0, comp->dy);
+ tcx1 = int_ceildiv(pi->tx1, comp->dx);
+ tcy1 = int_ceildiv(pi->ty1, comp->dy);
+ if (comp->numresolutions > maxres) {
+ maxres = comp->numresolutions;
+ }
+
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int levelno;
+ int rx0, ry0, rx1, ry1;
+ int px0, py0, px1, py1;
+ opj_pi_resolution_t *res = &comp->resolutions[resno];
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ res->pdx = tccp->prcw[resno];
+ res->pdy = tccp->prch[resno];
+ } else {
+ res->pdx = 15;
+ res->pdy = 15;
+ }
+ levelno = comp->numresolutions - 1 - resno;
+ rx0 = int_ceildivpow2(tcx0, levelno);
+ ry0 = int_ceildivpow2(tcy0, levelno);
+ rx1 = int_ceildivpow2(tcx1, levelno);
+ ry1 = int_ceildivpow2(tcy1, levelno);
+ px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
+ py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
+ px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
+ py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
+ res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
+ res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
+
+ if (res->pw*res->ph > maxprec) {
+ maxprec = res->pw*res->ph;
+ }
+
+ }
+ }
+
+ tccp = &tcp->tccps[0];
+ pi[pino].step_p = 1;
+ pi[pino].step_c = maxprec * pi[pino].step_p;
+ pi[pino].step_r = image->numcomps * pi[pino].step_c;
+ pi[pino].step_l = maxres * pi[pino].step_r;
+
+ if (pino == 0) {
+ pi[pino].include = (short int*) opj_calloc(image->numcomps * maxres * tcp->numlayers * maxprec, sizeof(short int));
+ if(!pi[pino].include) {
+ /* TODO: throw an error */
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+ }
+ else {
+ pi[pino].include = pi[pino - 1].include;
+ }
+
+ if (tcp->POC == 0) {
+ pi[pino].first = 1;
+ pi[pino].poc.resno0 = 0;
+ pi[pino].poc.compno0 = 0;
+ pi[pino].poc.layno1 = tcp->numlayers;
+ pi[pino].poc.resno1 = maxres;
+ pi[pino].poc.compno1 = image->numcomps;
+ pi[pino].poc.prg = tcp->prg;
+ } else {
+ pi[pino].first = 1;
+ pi[pino].poc.resno0 = tcp->pocs[pino].resno0;
+ pi[pino].poc.compno0 = tcp->pocs[pino].compno0;
+ pi[pino].poc.layno1 = tcp->pocs[pino].layno1;
+ pi[pino].poc.resno1 = tcp->pocs[pino].resno1;
+ pi[pino].poc.compno1 = tcp->pocs[pino].compno1;
+ pi[pino].poc.prg = tcp->pocs[pino].prg;
+ }
+ pi[pino].poc.layno0 = 0;
+ pi[pino].poc.precno0 = 0;
+ pi[pino].poc.precno1 = maxprec;
+
+ }
+
+ return pi;
+}
+
+
+opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno, J2K_T2_MODE t2_mode){
+ int p, q, pino;
+ int compno, resno;
+ int maxres = 0;
+ int maxprec = 0;
+ opj_pi_iterator_t *pi = NULL;
+ opj_tcp_t *tcp = NULL;
+ opj_tccp_t *tccp = NULL;
+
+ tcp = &cp->tcps[tileno];
+
+ pi = (opj_pi_iterator_t*) opj_calloc((tcp->numpocs + 1), sizeof(opj_pi_iterator_t));
+ if(!pi) { return NULL;}
+ pi->tp_on = cp->tp_on;
+
+ for(pino = 0;pino < tcp->numpocs+1 ; pino ++){
+ p = tileno % cp->tw;
+ q = tileno / cp->tw;
+
+ pi[pino].tx0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ pi[pino].ty0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ pi[pino].tx1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ pi[pino].ty1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+ pi[pino].numcomps = image->numcomps;
+
+ pi[pino].comps = (opj_pi_comp_t*) opj_calloc(image->numcomps, sizeof(opj_pi_comp_t));
+ if(!pi[pino].comps) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ for (compno = 0; compno < pi[pino].numcomps; compno++) {
+ int tcx0, tcy0, tcx1, tcy1;
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ tccp = &tcp->tccps[compno];
+ comp->dx = image->comps[compno].dx;
+ comp->dy = image->comps[compno].dy;
+ comp->numresolutions = tccp->numresolutions;
+
+ comp->resolutions = (opj_pi_resolution_t*) opj_malloc(comp->numresolutions * sizeof(opj_pi_resolution_t));
+ if(!comp->resolutions) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+
+ tcx0 = int_ceildiv(pi[pino].tx0, comp->dx);
+ tcy0 = int_ceildiv(pi[pino].ty0, comp->dy);
+ tcx1 = int_ceildiv(pi[pino].tx1, comp->dx);
+ tcy1 = int_ceildiv(pi[pino].ty1, comp->dy);
+ if (comp->numresolutions > maxres) {
+ maxres = comp->numresolutions;
+ }
+
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int levelno;
+ int rx0, ry0, rx1, ry1;
+ int px0, py0, px1, py1;
+ opj_pi_resolution_t *res = &comp->resolutions[resno];
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ res->pdx = tccp->prcw[resno];
+ res->pdy = tccp->prch[resno];
+ } else {
+ res->pdx = 15;
+ res->pdy = 15;
+ }
+ levelno = comp->numresolutions - 1 - resno;
+ rx0 = int_ceildivpow2(tcx0, levelno);
+ ry0 = int_ceildivpow2(tcy0, levelno);
+ rx1 = int_ceildivpow2(tcx1, levelno);
+ ry1 = int_ceildivpow2(tcy1, levelno);
+ px0 = int_floordivpow2(rx0, res->pdx) << res->pdx;
+ py0 = int_floordivpow2(ry0, res->pdy) << res->pdy;
+ px1 = int_ceildivpow2(rx1, res->pdx) << res->pdx;
+ py1 = int_ceildivpow2(ry1, res->pdy) << res->pdy;
+ res->pw = (rx0==rx1)?0:((px1 - px0) >> res->pdx);
+ res->ph = (ry0==ry1)?0:((py1 - py0) >> res->pdy);
+
+ if (res->pw*res->ph > maxprec) {
+ maxprec = res->pw * res->ph;
+ }
+ }
+ }
+
+ tccp = &tcp->tccps[0];
+ pi[pino].step_p = 1;
+ pi[pino].step_c = maxprec * pi[pino].step_p;
+ pi[pino].step_r = image->numcomps * pi[pino].step_c;
+ pi[pino].step_l = maxres * pi[pino].step_r;
+
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ opj_pi_comp_t *comp = &pi->comps[compno];
+ for (resno = 0; resno < comp->numresolutions; resno++) {
+ int dx, dy;
+ opj_pi_resolution_t *res = &comp->resolutions[resno];
+ dx = comp->dx * (1 << (res->pdx + comp->numresolutions - 1 - resno));
+ dy = comp->dy * (1 << (res->pdy + comp->numresolutions - 1 - resno));
+ pi[pino].dx = !pi->dx ? dx : int_min(pi->dx, dx);
+ pi[pino].dy = !pi->dy ? dy : int_min(pi->dy, dy);
+ }
+ }
+
+ if (pino == 0) {
+ pi[pino].include = (short int*) opj_calloc(tcp->numlayers * pi[pino].step_l, sizeof(short int));
+ if(!pi[pino].include) {
+ pi_destroy(pi, cp, tileno);
+ return NULL;
+ }
+ }
+ else {
+ pi[pino].include = pi[pino - 1].include;
+ }
+
+ /* Generation of boundaries for each prog flag*/
+ if(tcp->POC && ( cp->cinema || ((!cp->cinema) && (t2_mode == FINAL_PASS)))){
+ tcp->pocs[pino].compS= tcp->pocs[pino].compno0;
+ tcp->pocs[pino].compE= tcp->pocs[pino].compno1;
+ tcp->pocs[pino].resS = tcp->pocs[pino].resno0;
+ tcp->pocs[pino].resE = tcp->pocs[pino].resno1;
+ tcp->pocs[pino].layE = tcp->pocs[pino].layno1;
+ tcp->pocs[pino].prg = tcp->pocs[pino].prg1;
+ if (pino > 0)
+ tcp->pocs[pino].layS = (tcp->pocs[pino].layE > tcp->pocs[pino - 1].layE) ? tcp->pocs[pino - 1].layE : 0;
+ }else {
+ tcp->pocs[pino].compS= 0;
+ tcp->pocs[pino].compE= image->numcomps;
+ tcp->pocs[pino].resS = 0;
+ tcp->pocs[pino].resE = maxres;
+ tcp->pocs[pino].layS = 0;
+ tcp->pocs[pino].layE = tcp->numlayers;
+ tcp->pocs[pino].prg = tcp->prg;
+ }
+ tcp->pocs[pino].prcS = 0;
+ tcp->pocs[pino].prcE = maxprec;;
+ tcp->pocs[pino].txS = pi[pino].tx0;
+ tcp->pocs[pino].txE = pi[pino].tx1;
+ tcp->pocs[pino].tyS = pi[pino].ty0;
+ tcp->pocs[pino].tyE = pi[pino].ty1;
+ tcp->pocs[pino].dx = pi[pino].dx;
+ tcp->pocs[pino].dy = pi[pino].dy;
+ }
+ return pi;
+ }
+
+
+
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno) {
+ int compno, pino;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ if(pi) {
+ for (pino = 0; pino < tcp->numpocs + 1; pino++) {
+ if(pi[pino].comps) {
+ for (compno = 0; compno < pi->numcomps; compno++) {
+ opj_pi_comp_t *comp = &pi[pino].comps[compno];
+ if(comp->resolutions) {
+ opj_free(comp->resolutions);
+ }
+ }
+ opj_free(pi[pino].comps);
+ }
+ }
+ if(pi->include) {
+ opj_free(pi->include);
+ }
+ opj_free(pi);
+ }
+}
+
+bool pi_next(opj_pi_iterator_t * pi) {
+ switch (pi->poc.prg) {
+ case LRCP:
+ return pi_next_lrcp(pi);
+ case RLCP:
+ return pi_next_rlcp(pi);
+ case RPCL:
+ return pi_next_rpcl(pi);
+ case PCRL:
+ return pi_next_pcrl(pi);
+ case CPRL:
+ return pi_next_cprl(pi);
+ case PROG_UNKNOWN:
+ return false;
+ }
+
+ return false;
+}
+
+bool pi_create_encode( opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp){
+ char prog[4];
+ int i;
+ int incr_top=1,resetX=0;
+ opj_tcp_t *tcps =&cp->tcps[tileno];
+ opj_poc_t *tcp= &tcps->pocs[pino];
+
+ pi[pino].first = 1;
+ pi[pino].poc.prg = tcp->prg;
+
+ switch(tcp->prg){
+ case CPRL: strncpy(prog, "CPRL",4);
+ break;
+ case LRCP: strncpy(prog, "LRCP",4);
+ break;
+ case PCRL: strncpy(prog, "PCRL",4);
+ break;
+ case RLCP: strncpy(prog, "RLCP",4);
+ break;
+ case RPCL: strncpy(prog, "RPCL",4);
+ break;
+ case PROG_UNKNOWN:
+ return true;
+ }
+
+ if(!(cp->tp_on && ((!cp->cinema && (t2_mode == FINAL_PASS)) || cp->cinema))){
+ pi[pino].poc.resno0 = tcp->resS;
+ pi[pino].poc.resno1 = tcp->resE;
+ pi[pino].poc.compno0 = tcp->compS;
+ pi[pino].poc.compno1 = tcp->compE;
+ pi[pino].poc.layno0 = tcp->layS;
+ pi[pino].poc.layno1 = tcp->layE;
+ pi[pino].poc.precno0 = tcp->prcS;
+ pi[pino].poc.precno1 = tcp->prcE;
+ pi[pino].poc.tx0 = tcp->txS;
+ pi[pino].poc.ty0 = tcp->tyS;
+ pi[pino].poc.tx1 = tcp->txE;
+ pi[pino].poc.ty1 = tcp->tyE;
+ }else {
+ if( tpnum < cur_totnum_tp){
+ for(i=3;i>=0;i--){
+ switch(prog[i]){
+ case 'C':
+ if (i > tppos){
+ pi[pino].poc.compno0 = tcp->compS;
+ pi[pino].poc.compno1 = tcp->compE;
+ }else{
+ if (tpnum == 0){
+ tcp->comp_t = tcp->compS;
+ pi[pino].poc.compno0 = tcp->comp_t;
+ pi[pino].poc.compno1 = tcp->comp_t+1;
+ tcp->comp_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->comp_t ==tcp->compE){
+ tcp->comp_t = tcp->compS;
+ pi[pino].poc.compno0 = tcp->comp_t;
+ pi[pino].poc.compno1 = tcp->comp_t+1;
+ tcp->comp_t+=1;
+ incr_top=1;
+ }else{
+ pi[pino].poc.compno0 = tcp->comp_t;
+ pi[pino].poc.compno1 = tcp->comp_t+1;
+ tcp->comp_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.compno0 = tcp->comp_t-1;
+ pi[pino].poc.compno1 = tcp->comp_t;
+ }
+ }
+ }
+ break;
+
+ case 'R':
+ if (i > tppos){
+ pi[pino].poc.resno0 = tcp->resS;
+ pi[pino].poc.resno1 = tcp->resE;
+ }else{
+ if (tpnum == 0){
+ tcp->res_t = tcp->resS;
+ pi[pino].poc.resno0 = tcp->res_t;
+ pi[pino].poc.resno1 = tcp->res_t+1;
+ tcp->res_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->res_t==tcp->resE){
+ tcp->res_t = tcp->resS;
+ pi[pino].poc.resno0 = tcp->res_t;
+ pi[pino].poc.resno1 = tcp->res_t+1;
+ tcp->res_t+=1;
+ incr_top=1;
+ }else{
+ pi[pino].poc.resno0 = tcp->res_t;
+ pi[pino].poc.resno1 = tcp->res_t+1;
+ tcp->res_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.resno0 = tcp->res_t - 1;
+ pi[pino].poc.resno1 = tcp->res_t;
+ }
+ }
+ }
+ break;
+
+ case 'L':
+ if (i > tppos){
+ pi[pino].poc.layno0 = tcp->layS;
+ pi[pino].poc.layno1 = tcp->layE;
+ }else{
+ if (tpnum == 0){
+ tcp->lay_t = tcp->layS;
+ pi[pino].poc.layno0 = tcp->lay_t;
+ pi[pino].poc.layno1 = tcp->lay_t+1;
+ tcp->lay_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->lay_t == tcp->layE){
+ tcp->lay_t = tcp->layS;
+ pi[pino].poc.layno0 = tcp->lay_t;
+ pi[pino].poc.layno1 = tcp->lay_t+1;
+ tcp->lay_t+=1;
+ incr_top=1;
+ }else{
+ pi[pino].poc.layno0 = tcp->lay_t;
+ pi[pino].poc.layno1 = tcp->lay_t+1;
+ tcp->lay_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.layno0 = tcp->lay_t - 1;
+ pi[pino].poc.layno1 = tcp->lay_t;
+ }
+ }
+ }
+ break;
+
+ case 'P':
+ switch(tcp->prg){
+ case LRCP:
+ case RLCP:
+ if (i > tppos){
+ pi[pino].poc.precno0 = tcp->prcS;
+ pi[pino].poc.precno1 = tcp->prcE;
+ }else{
+ if (tpnum == 0){
+ tcp->prc_t = tcp->prcS;
+ pi[pino].poc.precno0 = tcp->prc_t;
+ pi[pino].poc.precno1 = tcp->prc_t+1;
+ tcp->prc_t+=1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->prc_t == tcp->prcE){
+ tcp->prc_t = tcp->prcS;
+ pi[pino].poc.precno0 = tcp->prc_t;
+ pi[pino].poc.precno1 = tcp->prc_t+1;
+ tcp->prc_t+=1;
+ incr_top=1;
+ }else{
+ pi[pino].poc.precno0 = tcp->prc_t;
+ pi[pino].poc.precno1 = tcp->prc_t+1;
+ tcp->prc_t+=1;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.precno0 = tcp->prc_t - 1;
+ pi[pino].poc.precno1 = tcp->prc_t;
+ }
+ }
+ }
+ break;
+ default:
+ if (i > tppos){
+ pi[pino].poc.tx0 = tcp->txS;
+ pi[pino].poc.ty0 = tcp->tyS;
+ pi[pino].poc.tx1 = tcp->txE;
+ pi[pino].poc.ty1 = tcp->tyE;
+ }else{
+ if (tpnum == 0){
+ tcp->tx0_t = tcp->txS;
+ tcp->ty0_t = tcp->tyS;
+ pi[pino].poc.tx0 = tcp->tx0_t;
+ pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx - (tcp->tx0_t % tcp->dx);
+ pi[pino].poc.ty0 = tcp->ty0_t;
+ pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+ tcp->tx0_t = pi[pino].poc.tx1;
+ tcp->ty0_t = pi[pino].poc.ty1;
+ }else{
+ if (incr_top == 1){
+ if(tcp->tx0_t >= tcp->txE){
+ if(tcp->ty0_t >= tcp->tyE){
+ tcp->ty0_t = tcp->tyS;
+ pi[pino].poc.ty0 = tcp->ty0_t;
+ pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+ tcp->ty0_t = pi[pino].poc.ty1;
+ incr_top=1;resetX=1;
+ }else{
+ pi[pino].poc.ty0 = tcp->ty0_t;
+ pi[pino].poc.ty1 = tcp->ty0_t + tcp->dy - (tcp->ty0_t % tcp->dy);
+ tcp->ty0_t = pi[pino].poc.ty1;
+ incr_top=0;resetX=1;
+ }
+ if(resetX==1){
+ tcp->tx0_t = tcp->txS;
+ pi[pino].poc.tx0 = tcp->tx0_t;
+ pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx);
+ tcp->tx0_t = pi[pino].poc.tx1;
+ }
+ }else{
+ pi[pino].poc.tx0 = tcp->tx0_t;
+ pi[pino].poc.tx1 = tcp->tx0_t + tcp->dx- (tcp->tx0_t % tcp->dx);
+ tcp->tx0_t = pi[pino].poc.tx1;
+ pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy);
+ pi[pino].poc.ty1 = tcp->ty0_t ;
+ incr_top=0;
+ }
+ }else{
+ pi[pino].poc.tx0 = tcp->tx0_t - tcp->dx - (tcp->tx0_t % tcp->dx);
+ pi[pino].poc.tx1 = tcp->tx0_t ;
+ pi[pino].poc.ty0 = tcp->ty0_t - tcp->dy - (tcp->ty0_t % tcp->dy);
+ pi[pino].poc.ty1 = tcp->ty0_t ;
+ }
+ }
+ }
+ break;
+ }
+ break;
+ }
+ }
+ }
+ }
+ return false;
+}
+
diff --git a/Source/LibOpenJPEG/pi.h b/Source/LibOpenJPEG/pi.h
new file mode 100644
index 0000000..b5e0f6a
--- /dev/null
+++ b/Source/LibOpenJPEG/pi.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __PI_H
+#define __PI_H
+/**
+@file pi.h
+@brief Implementation of a packet iterator (PI)
+
+The functions in PI.C have for goal to realize a packet iterator that permits to get the next
+packet following the progression order and change of it. The functions in PI.C are used
+by some function in T2.C.
+*/
+
+/** @defgroup PI PI - Implementation of a packet iterator */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_resolution {
+ int pdx, pdy;
+ int pw, ph;
+} opj_pi_resolution_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_pi_comp {
+ int dx, dy;
+ /** number of resolution levels */
+ int numresolutions;
+ opj_pi_resolution_t *resolutions;
+} opj_pi_comp_t;
+
+/**
+Packet iterator
+*/
+typedef struct opj_pi_iterator {
+ /** Enabling Tile part generation*/
+ char tp_on;
+ /** precise if the packet has been already used (usefull for progression order change) */
+ short int *include;
+ /** layer step used to localize the packet in the include vector */
+ int step_l;
+ /** resolution step used to localize the packet in the include vector */
+ int step_r;
+ /** component step used to localize the packet in the include vector */
+ int step_c;
+ /** precinct step used to localize the packet in the include vector */
+ int step_p;
+ /** component that identify the packet */
+ int compno;
+ /** resolution that identify the packet */
+ int resno;
+ /** precinct that identify the packet */
+ int precno;
+ /** layer that identify the packet */
+ int layno;
+ /** 0 if the first packet */
+ int first;
+ /** progression order change information */
+ opj_poc_t poc;
+ /** number of components in the image */
+ int numcomps;
+ /** Components*/
+ opj_pi_comp_t *comps;
+ int tx0, ty0, tx1, ty1;
+ int x, y, dx, dy;
+} opj_pi_iterator_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a packet iterator for Encoder
+@param image Raw image for which the packets will be listed
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which to list the packets
+@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
+@return Returns a packet iterator that points to the first packet of the tile
+@see pi_destroy
+*/
+opj_pi_iterator_t *pi_initialise_encode(opj_image_t *image, opj_cp_t *cp, int tileno,J2K_T2_MODE t2_mode);
+/**
+Modify the packet iterator for enabling tile part generation
+@param pi Handle to the packet iterator generated in pi_initialise_encode
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which to list the packets
+@param tpnum Tile part number of the current tile
+@param tppos The position of the tile part flag in the progression order
+@param cur_totnum_tp The total number of tile parts in the current tile
+@return Returns true if an error is detected
+*/
+bool pi_create_encode(opj_pi_iterator_t *pi, opj_cp_t *cp,int tileno, int pino,int tpnum, int tppos, J2K_T2_MODE t2_mode,int cur_totnum_tp);
+/**
+Create a packet iterator for Decoder
+@param image Raw image for which the packets will be listed
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which to list the packets
+@return Returns a packet iterator that points to the first packet of the tile
+@see pi_destroy
+*/
+opj_pi_iterator_t *pi_create_decode(opj_image_t * image, opj_cp_t * cp, int tileno);
+
+/**
+Destroy a packet iterator
+@param pi Previously created packet iterator
+@param cp Coding parameters
+@param tileno Number that identifies the tile for which the packets were listed
+@see pi_create
+*/
+void pi_destroy(opj_pi_iterator_t *pi, opj_cp_t *cp, int tileno);
+
+/**
+Modify the packet iterator to point to the next packet
+@param pi Packet iterator to modify
+@return Returns false if pi pointed to the last packet or else returns true
+*/
+bool pi_next(opj_pi_iterator_t * pi);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __PI_H */
diff --git a/Source/LibOpenJPEG/raw.c b/Source/LibOpenJPEG/raw.c
new file mode 100644
index 0000000..3d231bf
--- /dev/null
+++ b/Source/LibOpenJPEG/raw.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/*
+==========================================================
+ local functions
+==========================================================
+*/
+
+
+/*
+==========================================================
+ RAW encoding interface
+==========================================================
+*/
+
+opj_raw_t* raw_create(void) {
+ opj_raw_t *raw = (opj_raw_t*)opj_malloc(sizeof(opj_raw_t));
+ return raw;
+}
+
+void raw_destroy(opj_raw_t *raw) {
+ if(raw) {
+ opj_free(raw);
+ }
+}
+
+int raw_numbytes(opj_raw_t *raw) {
+ return raw->bp - raw->start;
+}
+
+void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len) {
+ raw->start = bp;
+ raw->lenmax = len;
+ raw->len = 0;
+ raw->c = 0;
+ raw->ct = 0;
+}
+
+int raw_decode(opj_raw_t *raw) {
+ int d;
+ if (raw->ct == 0) {
+ raw->ct = 8;
+ if (raw->len == raw->lenmax) {
+ raw->c = 0xff;
+ } else {
+ if (raw->c == 0xff) {
+ raw->ct = 7;
+ }
+ raw->c = *(raw->start + raw->len);
+ raw->len++;
+ }
+ }
+ raw->ct--;
+ d = (raw->c >> raw->ct) & 0x01;
+
+ return d;
+}
+
diff --git a/Source/LibOpenJPEG/raw.h b/Source/LibOpenJPEG/raw.h
new file mode 100644
index 0000000..3c4b372
--- /dev/null
+++ b/Source/LibOpenJPEG/raw.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __RAW_H
+#define __RAW_H
+/**
+@file raw.h
+@brief Implementation of operations for raw encoding (RAW)
+
+The functions in RAW.C have for goal to realize the operation of raw encoding linked
+with the corresponding mode switch.
+*/
+
+/** @defgroup RAW RAW - Implementation of operations for raw encoding */
+/*@{*/
+
+/**
+RAW encoding operations
+*/
+typedef struct opj_raw {
+ /** temporary buffer where bits are coded or decoded */
+ unsigned char c;
+ /** number of bits already read or free to write */
+ unsigned int ct;
+ /** maximum length to decode */
+ unsigned int lenmax;
+ /** length decoded */
+ unsigned int len;
+ /** pointer to the current position in the buffer */
+ unsigned char *bp;
+ /** pointer to the start of the buffer */
+ unsigned char *start;
+ /** pointer to the end of the buffer */
+ unsigned char *end;
+} opj_raw_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new RAW handle
+@return Returns a new RAW handle if successful, returns NULL otherwise
+*/
+opj_raw_t* raw_create(void);
+/**
+Destroy a previously created RAW handle
+@param raw RAW handle to destroy
+*/
+void raw_destroy(opj_raw_t *raw);
+/**
+Return the number of bytes written/read since initialisation
+@param raw RAW handle to destroy
+@return Returns the number of bytes already encoded
+*/
+int raw_numbytes(opj_raw_t *raw);
+/**
+Initialize the decoder
+@param raw RAW handle
+@param bp Pointer to the start of the buffer from which the bytes will be read
+@param len Length of the input buffer
+*/
+void raw_init_dec(opj_raw_t *raw, unsigned char *bp, int len);
+/**
+Decode a symbol using raw-decoder. Cfr p.506 TAUBMAN
+@param raw RAW handle
+@return Returns the decoded symbol (0 or 1)
+*/
+int raw_decode(opj_raw_t *raw);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __RAW_H */
diff --git a/Source/LibOpenJPEG/t1.c b/Source/LibOpenJPEG/t1.c
new file mode 100644
index 0000000..ad1c6a8
--- /dev/null
+++ b/Source/LibOpenJPEG/t1.c
@@ -0,0 +1,1208 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+#include "t1_luts.h"
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static INLINE char t1_getctxno_zc(int f, int orient);
+static char t1_getctxno_sc(int f);
+static INLINE int t1_getctxno_mag(int f);
+static char t1_getspb(int f);
+static short t1_getnmsedec_sig(int x, int bitpos);
+static short t1_getnmsedec_ref(int x, int bitpos);
+static void t1_updateflags(flag_t *flagsp, int s, int stride);
+/**
+Encode significant pass
+*/
+static void t1_enc_sigpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int bpno,
+ int one,
+ int *nmsedec,
+ char type,
+ int vsc);
+/**
+Decode significant pass
+*/
+static void t1_dec_sigpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ char type,
+ int vsc);
+/**
+Encode significant pass
+*/
+static void t1_enc_sigpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int *nmsedec,
+ char type,
+ int cblksty);
+/**
+Decode significant pass
+*/
+static void t1_dec_sigpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ char type,
+ int cblksty);
+/**
+Encode refinement pass
+*/
+static void t1_enc_refpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int bpno,
+ int one,
+ int *nmsedec,
+ char type,
+ int vsc);
+/**
+Decode refinement pass
+*/
+static void t1_dec_refpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int poshalf,
+ int neghalf,
+ char type,
+ int vsc);
+/**
+Encode refinement pass
+*/
+static void t1_enc_refpass(
+ opj_t1_t *t1,
+ int bpno,
+ int *nmsedec,
+ char type,
+ int cblksty);
+/**
+Decode refinement pass
+*/
+static void t1_dec_refpass(
+ opj_t1_t *t1,
+ int bpno,
+ char type,
+ int cblksty);
+/**
+Encode clean-up pass
+*/
+static void t1_enc_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int bpno,
+ int one,
+ int *nmsedec,
+ int partial,
+ int vsc);
+/**
+Decode clean-up pass
+*/
+static void t1_dec_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ int partial,
+ int vsc);
+/**
+Encode clean-up pass
+*/
+static void t1_enc_clnpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int *nmsedec,
+ int cblksty);
+/**
+Decode clean-up pass
+*/
+static void t1_dec_clnpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int cblksty);
+static double t1_getwmsedec(
+ int nmsedec,
+ int compno,
+ int level,
+ int orient,
+ int bpno,
+ int qmfbid,
+ double stepsize,
+ int numcomps);
+/**
+Encode 1 code-block
+@param t1 T1 handle
+@param cblk Code-block coding parameters
+@param orient
+@param compno Component number
+@param level
+@param qmfbid
+@param stepsize
+@param cblksty Code-block style
+@param numcomps
+@param tile
+*/
+static void t1_encode_cblk(
+ opj_t1_t *t1,
+ opj_tcd_cblk_enc_t* cblk,
+ int orient,
+ int compno,
+ int level,
+ int qmfbid,
+ double stepsize,
+ int cblksty,
+ int numcomps,
+ opj_tcd_tile_t * tile);
+/**
+Decode 1 code-block
+@param t1 T1 handle
+@param cblk Code-block coding parameters
+@param orient
+@param roishift Region of interest shifting value
+@param cblksty Code-block style
+*/
+static void t1_decode_cblk(
+ opj_t1_t *t1,
+ opj_tcd_cblk_dec_t* cblk,
+ int orient,
+ int roishift,
+ int cblksty);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+static char t1_getctxno_zc(int f, int orient) {
+ return lut_ctxno_zc[(orient << 8) | (f & T1_SIG_OTH)];
+}
+
+static char t1_getctxno_sc(int f) {
+ return lut_ctxno_sc[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+static int t1_getctxno_mag(int f) {
+ int tmp1 = (f & T1_SIG_OTH) ? T1_CTXNO_MAG + 1 : T1_CTXNO_MAG;
+ int tmp2 = (f & T1_REFINE) ? T1_CTXNO_MAG + 2 : tmp1;
+ return (tmp2);
+}
+
+static char t1_getspb(int f) {
+ return lut_spb[(f & (T1_SIG_PRIM | T1_SGN)) >> 4];
+}
+
+static short t1_getnmsedec_sig(int x, int bitpos) {
+ if (bitpos > T1_NMSEDEC_FRACBITS) {
+ return lut_nmsedec_sig[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+ }
+
+ return lut_nmsedec_sig0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
+}
+
+static short t1_getnmsedec_ref(int x, int bitpos) {
+ if (bitpos > T1_NMSEDEC_FRACBITS) {
+ return lut_nmsedec_ref[(x >> (bitpos - T1_NMSEDEC_FRACBITS)) & ((1 << T1_NMSEDEC_BITS) - 1)];
+ }
+
+ return lut_nmsedec_ref0[x & ((1 << T1_NMSEDEC_BITS) - 1)];
+}
+
+static void t1_updateflags(flag_t *flagsp, int s, int stride) {
+ flag_t *np = flagsp - stride;
+ flag_t *sp = flagsp + stride;
+
+ static const flag_t mod[] = {
+ T1_SIG_S, T1_SIG_S|T1_SGN_S,
+ T1_SIG_E, T1_SIG_E|T1_SGN_E,
+ T1_SIG_W, T1_SIG_W|T1_SGN_W,
+ T1_SIG_N, T1_SIG_N|T1_SGN_N
+ };
+
+ np[-1] |= T1_SIG_SE;
+ np[0] |= mod[s];
+ np[1] |= T1_SIG_SW;
+
+ flagsp[-1] |= mod[s+2];
+ flagsp[0] |= T1_SIG;
+ flagsp[1] |= mod[s+4];
+
+ sp[-1] |= T1_SIG_NE;
+ sp[0] |= mod[s+6];
+ sp[1] |= T1_SIG_NW;
+}
+
+static void t1_enc_sigpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int bpno,
+ int one,
+ int *nmsedec,
+ char type,
+ int vsc)
+{
+ int v, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
+ v = int_abs(*datap) & one ? 1 : 0;
+ mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient)); /* ESSAI */
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
+ mqc_bypass_enc(mqc, v);
+ } else {
+ mqc_encode(mqc, v);
+ }
+ if (v) {
+ v = *datap < 0 ? 1 : 0;
+ *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ mqc_setcurctx(mqc, t1_getctxno_sc(flag)); /* ESSAI */
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
+ mqc_bypass_enc(mqc, v);
+ } else {
+ mqc_encode(mqc, v ^ t1_getspb(flag));
+ }
+ t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ *flagsp |= T1_VISIT;
+ }
+}
+
+static void t1_dec_sigpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ char type,
+ int vsc)
+{
+ int v, flag;
+
+ opj_raw_t *raw = t1->raw; /* RAW component */
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if ((flag & T1_SIG_OTH) && !(flag & (T1_SIG | T1_VISIT))) {
+ if (type == T1_TYPE_RAW) {
+ if (raw_decode(raw)) {
+ v = raw_decode(raw); /* ESSAI */
+ *datap = v ? -oneplushalf : oneplushalf;
+ t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ } else {
+ mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
+ if (mqc_decode(mqc)) {
+ mqc_setcurctx(mqc, t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp |= T1_VISIT;
+ }
+} /* VSC and BYPASS by Antonin */
+
+static void t1_enc_sigpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int *nmsedec,
+ char type,
+ int cblksty)
+{
+ int i, j, k, one, vsc;
+ *nmsedec = 0;
+ one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ for (j = k; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_enc_sigpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ orient,
+ bpno,
+ one,
+ nmsedec,
+ type,
+ vsc);
+ }
+ }
+ }
+}
+
+static void t1_dec_sigpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ char type,
+ int cblksty)
+{
+ int i, j, k, one, half, oneplushalf, vsc;
+ one = 1 << bpno;
+ half = one >> 1;
+ oneplushalf = one | half;
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ for (j = k; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_dec_sigpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ orient,
+ oneplushalf,
+ type,
+ vsc);
+ }
+ }
+ }
+} /* VSC and BYPASS by Antonin */
+
+static void t1_enc_refpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int bpno,
+ int one,
+ int *nmsedec,
+ char type,
+ int vsc)
+{
+ int v, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
+ *nmsedec += t1_getnmsedec_ref(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ v = int_abs(*datap) & one ? 1 : 0;
+ mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */
+ if (type == T1_TYPE_RAW) { /* BYPASS/LAZY MODE */
+ mqc_bypass_enc(mqc, v);
+ } else {
+ mqc_encode(mqc, v);
+ }
+ *flagsp |= T1_REFINE;
+ }
+}
+
+static void t1_dec_refpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int poshalf,
+ int neghalf,
+ char type,
+ int vsc)
+{
+ int v, t, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+ opj_raw_t *raw = t1->raw; /* RAW component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if ((flag & (T1_SIG | T1_VISIT)) == T1_SIG) {
+ mqc_setcurctx(mqc, t1_getctxno_mag(flag)); /* ESSAI */
+ if (type == T1_TYPE_RAW) {
+ v = raw_decode(raw);
+ } else {
+ v = mqc_decode(mqc);
+ }
+ t = v ? poshalf : neghalf;
+ *datap += *datap < 0 ? -t : t;
+ *flagsp |= T1_REFINE;
+ }
+} /* VSC and BYPASS by Antonin */
+
+static void t1_enc_refpass(
+ opj_t1_t *t1,
+ int bpno,
+ int *nmsedec,
+ char type,
+ int cblksty)
+{
+ int i, j, k, one, vsc;
+ *nmsedec = 0;
+ one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ for (j = k; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_enc_refpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ bpno,
+ one,
+ nmsedec,
+ type,
+ vsc);
+ }
+ }
+ }
+}
+
+static void t1_dec_refpass(
+ opj_t1_t *t1,
+ int bpno,
+ char type,
+ int cblksty)
+{
+ int i, j, k, one, poshalf, neghalf;
+ int vsc;
+ one = 1 << bpno;
+ poshalf = one >> 1;
+ neghalf = bpno > 0 ? -poshalf : -1;
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ for (j = k; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_dec_refpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ poshalf,
+ neghalf,
+ type,
+ vsc);
+ }
+ }
+ }
+} /* VSC and BYPASS by Antonin */
+
+static void t1_enc_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int bpno,
+ int one,
+ int *nmsedec,
+ int partial,
+ int vsc)
+{
+ int v, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if (partial) {
+ goto LABEL_PARTIAL;
+ }
+ if (!(*flagsp & (T1_SIG | T1_VISIT))) {
+ mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
+ v = int_abs(*datap) & one ? 1 : 0;
+ mqc_encode(mqc, v);
+ if (v) {
+LABEL_PARTIAL:
+ *nmsedec += t1_getnmsedec_sig(int_abs(*datap), bpno + T1_NMSEDEC_FRACBITS);
+ mqc_setcurctx(mqc, t1_getctxno_sc(flag));
+ v = *datap < 0 ? 1 : 0;
+ mqc_encode(mqc, v ^ t1_getspb(flag));
+ t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp &= ~T1_VISIT;
+}
+
+static void t1_dec_clnpass_step(
+ opj_t1_t *t1,
+ flag_t *flagsp,
+ int *datap,
+ int orient,
+ int oneplushalf,
+ int partial,
+ int vsc)
+{
+ int v, flag;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ flag = vsc ? ((*flagsp) & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) : (*flagsp);
+ if (partial) {
+ goto LABEL_PARTIAL;
+ }
+ if (!(flag & (T1_SIG | T1_VISIT))) {
+ mqc_setcurctx(mqc, t1_getctxno_zc(flag, orient));
+ if (mqc_decode(mqc)) {
+LABEL_PARTIAL:
+ mqc_setcurctx(mqc, t1_getctxno_sc(flag));
+ v = mqc_decode(mqc) ^ t1_getspb(flag);
+ *datap = v ? -oneplushalf : oneplushalf;
+ t1_updateflags(flagsp, v, t1->flags_stride);
+ }
+ }
+ *flagsp &= ~T1_VISIT;
+} /* VSC and BYPASS by Antonin */
+
+static void t1_enc_clnpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int *nmsedec,
+ int cblksty)
+{
+ int i, j, k, one, agg, runlen, vsc;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ *nmsedec = 0;
+ one = 1 << (bpno + T1_NMSEDEC_FRACBITS);
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ if (k + 3 < t1->h) {
+ if (cblksty & J2K_CCP_CBLKSTY_VSC) {
+ agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || (MACRO_t1_flags(1 + k + 3,1 + i)
+ & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+ } else {
+ agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+ }
+ } else {
+ agg = 0;
+ }
+ if (agg) {
+ for (runlen = 0; runlen < 4; ++runlen) {
+ if (int_abs(t1->data[((k + runlen)*t1->w) + i]) & one)
+ break;
+ }
+ mqc_setcurctx(mqc, T1_CTXNO_AGG);
+ mqc_encode(mqc, runlen != 4);
+ if (runlen == 4) {
+ continue;
+ }
+ mqc_setcurctx(mqc, T1_CTXNO_UNI);
+ mqc_encode(mqc, runlen >> 1);
+ mqc_encode(mqc, runlen & 1);
+ } else {
+ runlen = 0;
+ }
+ for (j = k + runlen; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_enc_clnpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ orient,
+ bpno,
+ one,
+ nmsedec,
+ agg && (j == k + runlen),
+ vsc);
+ }
+ }
+ }
+}
+
+static void t1_dec_clnpass(
+ opj_t1_t *t1,
+ int bpno,
+ int orient,
+ int cblksty)
+{
+ int i, j, k, one, half, oneplushalf, agg, runlen, vsc;
+ int segsym = cblksty & J2K_CCP_CBLKSTY_SEGSYM;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ one = 1 << bpno;
+ half = one >> 1;
+ oneplushalf = one | half;
+ for (k = 0; k < t1->h; k += 4) {
+ for (i = 0; i < t1->w; ++i) {
+ if (k + 3 < t1->h) {
+ if (cblksty & J2K_CCP_CBLKSTY_VSC) {
+ agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || (MACRO_t1_flags(1 + k + 3,1 + i)
+ & (~(T1_SIG_S | T1_SIG_SE | T1_SIG_SW | T1_SGN_S))) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+ } else {
+ agg = !(MACRO_t1_flags(1 + k,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 1,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 2,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH)
+ || MACRO_t1_flags(1 + k + 3,1 + i) & (T1_SIG | T1_VISIT | T1_SIG_OTH));
+ }
+ } else {
+ agg = 0;
+ }
+ if (agg) {
+ mqc_setcurctx(mqc, T1_CTXNO_AGG);
+ if (!mqc_decode(mqc)) {
+ continue;
+ }
+ mqc_setcurctx(mqc, T1_CTXNO_UNI);
+ runlen = mqc_decode(mqc);
+ runlen = (runlen << 1) | mqc_decode(mqc);
+ } else {
+ runlen = 0;
+ }
+ for (j = k + runlen; j < k + 4 && j < t1->h; ++j) {
+ vsc = ((cblksty & J2K_CCP_CBLKSTY_VSC) && (j == k + 3 || j == t1->h - 1)) ? 1 : 0;
+ t1_dec_clnpass_step(
+ t1,
+ &t1->flags[((j+1) * t1->flags_stride) + i + 1],
+ &t1->data[(j * t1->w) + i],
+ orient,
+ oneplushalf,
+ agg && (j == k + runlen),
+ vsc);
+ }
+ }
+ }
+ if (segsym) {
+ int v = 0;
+ mqc_setcurctx(mqc, T1_CTXNO_UNI);
+ v = mqc_decode(mqc);
+ v = (v << 1) | mqc_decode(mqc);
+ v = (v << 1) | mqc_decode(mqc);
+ v = (v << 1) | mqc_decode(mqc);
+ /*
+ if (v!=0xa) {
+ opj_event_msg(t1->cinfo, EVT_WARNING, "Bad segmentation symbol %x\n", v);
+ }
+ */
+ }
+} /* VSC and BYPASS by Antonin */
+
+
+/** mod fixed_quality */
+static double t1_getwmsedec(
+ int nmsedec,
+ int compno,
+ int level,
+ int orient,
+ int bpno,
+ int qmfbid,
+ double stepsize,
+ int numcomps)
+{
+ double w1, w2, wmsedec;
+ if (qmfbid == 1) {
+ w1 = (numcomps > 1) ? mct_getnorm(compno) : 1.0;
+ w2 = dwt_getnorm(level, orient);
+ } else { /* if (qmfbid == 0) */
+ w1 = (numcomps > 1) ? mct_getnorm_real(compno) : 1.0;
+ w2 = dwt_getnorm_real(level, orient);
+ }
+ wmsedec = w1 * w2 * stepsize * (1 << bpno);
+ wmsedec *= wmsedec * nmsedec / 8192.0;
+
+ return wmsedec;
+}
+
+static bool allocate_buffers(
+ opj_t1_t *t1,
+ int w,
+ int h)
+{
+ int datasize=w * h;
+ int flagssize;
+
+ if(datasize > t1->datasize){
+ opj_aligned_free(t1->data);
+ t1->data = (int*) opj_aligned_malloc(datasize * sizeof(int));
+ if(!t1->data){
+ return false;
+ }
+ t1->datasize=datasize;
+ }
+ memset(t1->data,0,datasize * sizeof(int));
+
+ t1->flags_stride=w+2;
+ flagssize=t1->flags_stride * (h+2);
+
+ if(flagssize > t1->flagssize){
+ opj_aligned_free(t1->flags);
+ t1->flags = (flag_t*) opj_aligned_malloc(flagssize * sizeof(flag_t));
+ if(!t1->flags){
+ return false;
+ }
+ t1->flagssize=flagssize;
+ }
+ memset(t1->flags,0,flagssize * sizeof(flag_t));
+
+ t1->w=w;
+ t1->h=h;
+
+ return true;
+}
+
+/** mod fixed_quality */
+static void t1_encode_cblk(
+ opj_t1_t *t1,
+ opj_tcd_cblk_enc_t* cblk,
+ int orient,
+ int compno,
+ int level,
+ int qmfbid,
+ double stepsize,
+ int cblksty,
+ int numcomps,
+ opj_tcd_tile_t * tile)
+{
+ double cumwmsedec = 0.0;
+
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ int passno, bpno, passtype;
+ int nmsedec = 0;
+ int i, max;
+ char type = T1_TYPE_MQ;
+ double tempwmsedec;
+
+ max = 0;
+ for (i = 0; i < t1->w * t1->h; ++i) {
+ int tmp = abs(t1->data[i]);
+ max = int_max(max, tmp);
+ }
+
+ cblk->numbps = max ? (int_floorlog2(max) + 1) - T1_NMSEDEC_FRACBITS : 0;
+
+ bpno = cblk->numbps - 1;
+ passtype = 2;
+
+ mqc_resetstates(mqc);
+ mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+ mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+ mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+ mqc_init_enc(mqc, cblk->data);
+
+ for (passno = 0; bpno >= 0; ++passno) {
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ int correction = 3;
+ type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+
+ switch (passtype) {
+ case 0:
+ t1_enc_sigpass(t1, bpno, orient, &nmsedec, type, cblksty);
+ break;
+ case 1:
+ t1_enc_refpass(t1, bpno, &nmsedec, type, cblksty);
+ break;
+ case 2:
+ t1_enc_clnpass(t1, bpno, orient, &nmsedec, cblksty);
+ /* code switch SEGMARK (i.e. SEGSYM) */
+ if (cblksty & J2K_CCP_CBLKSTY_SEGSYM)
+ mqc_segmark_enc(mqc);
+ break;
+ }
+
+ /* fixed_quality */
+ tempwmsedec = t1_getwmsedec(nmsedec, compno, level, orient, bpno, qmfbid, stepsize, numcomps);
+ cumwmsedec += tempwmsedec;
+ tile->distotile += tempwmsedec;
+
+ /* Code switch "RESTART" (i.e. TERMALL) */
+ if ((cblksty & J2K_CCP_CBLKSTY_TERMALL) && !((passtype == 2) && (bpno - 1 < 0))) {
+ if (type == T1_TYPE_RAW) {
+ mqc_flush(mqc);
+ correction = 1;
+ /* correction = mqc_bypass_flush_enc(); */
+ } else { /* correction = mqc_restart_enc(); */
+ mqc_flush(mqc);
+ correction = 1;
+ }
+ pass->term = 1;
+ } else {
+ if (((bpno < (cblk->numbps - 4) && (passtype > 0))
+ || ((bpno == (cblk->numbps - 4)) && (passtype == 2))) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) {
+ if (type == T1_TYPE_RAW) {
+ mqc_flush(mqc);
+ correction = 1;
+ /* correction = mqc_bypass_flush_enc(); */
+ } else { /* correction = mqc_restart_enc(); */
+ mqc_flush(mqc);
+ correction = 1;
+ }
+ pass->term = 1;
+ } else {
+ pass->term = 0;
+ }
+ }
+
+ if (++passtype == 3) {
+ passtype = 0;
+ bpno--;
+ }
+
+ if (pass->term && bpno > 0) {
+ type = ((bpno < (cblk->numbps - 4)) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+ if (type == T1_TYPE_RAW)
+ mqc_bypass_init_enc(mqc);
+ else
+ mqc_restart_init_enc(mqc);
+ }
+
+ pass->distortiondec = cumwmsedec;
+ pass->rate = mqc_numbytes(mqc) + correction; /* FIXME */
+
+ /* Code-switch "RESET" */
+ if (cblksty & J2K_CCP_CBLKSTY_RESET)
+ mqc_reset_enc(mqc);
+ }
+
+ /* Code switch "ERTERM" (i.e. PTERM) */
+ if (cblksty & J2K_CCP_CBLKSTY_PTERM)
+ mqc_erterm_enc(mqc);
+ else /* Default coding */ if (!(cblksty & J2K_CCP_CBLKSTY_LAZY))
+ mqc_flush(mqc);
+
+ cblk->totalpasses = passno;
+
+ for (passno = 0; passno<cblk->totalpasses; passno++) {
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ if (pass->rate > mqc_numbytes(mqc))
+ pass->rate = mqc_numbytes(mqc);
+ /*Preventing generation of FF as last data byte of a pass*/
+ if((pass->rate>1) && (cblk->data[pass->rate - 1] == 0xFF)){
+ pass->rate--;
+ }
+ pass->len = pass->rate - (passno == 0 ? 0 : cblk->passes[passno - 1].rate);
+ }
+}
+
+static void t1_decode_cblk(
+ opj_t1_t *t1,
+ opj_tcd_cblk_dec_t* cblk,
+ int orient,
+ int roishift,
+ int cblksty)
+{
+ opj_raw_t *raw = t1->raw; /* RAW component */
+ opj_mqc_t *mqc = t1->mqc; /* MQC component */
+
+ int bpno, passtype;
+ int segno, passno;
+ char type = T1_TYPE_MQ; /* BYPASS mode */
+
+ if(!allocate_buffers(
+ t1,
+ cblk->x1 - cblk->x0,
+ cblk->y1 - cblk->y0))
+ {
+ return;
+ }
+
+ bpno = roishift + cblk->numbps - 1;
+ passtype = 2;
+
+ mqc_resetstates(mqc);
+ mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+ mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+ mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+
+ for (segno = 0; segno < cblk->numsegs; ++segno) {
+ opj_tcd_seg_t *seg = &cblk->segs[segno];
+
+ /* BYPASS mode */
+ type = ((bpno <= (cblk->numbps - 1) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
+ /* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */
+ if(seg->data == NULL){
+ continue;
+ }
+ if (type == T1_TYPE_RAW) {
+ raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len);
+ } else {
+ mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len);
+ }
+
+ for (passno = 0; passno < seg->numpasses; ++passno) {
+ switch (passtype) {
+ case 0:
+ t1_dec_sigpass(t1, bpno+1, orient, type, cblksty);
+ break;
+ case 1:
+ t1_dec_refpass(t1, bpno+1, type, cblksty);
+ break;
+ case 2:
+ t1_dec_clnpass(t1, bpno+1, orient, cblksty);
+ break;
+ }
+
+ if ((cblksty & J2K_CCP_CBLKSTY_RESET) && type == T1_TYPE_MQ) {
+ mqc_resetstates(mqc);
+ mqc_setstate(mqc, T1_CTXNO_UNI, 0, 46);
+ mqc_setstate(mqc, T1_CTXNO_AGG, 0, 3);
+ mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
+ }
+ if (++passtype == 3) {
+ passtype = 0;
+ bpno--;
+ }
+ }
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+opj_t1_t* t1_create(opj_common_ptr cinfo) {
+ opj_t1_t *t1 = (opj_t1_t*) opj_malloc(sizeof(opj_t1_t));
+ if(!t1)
+ return NULL;
+
+ t1->cinfo = cinfo;
+ /* create MQC and RAW handles */
+ t1->mqc = mqc_create();
+ t1->raw = raw_create();
+
+ t1->data=NULL;
+ t1->flags=NULL;
+ t1->datasize=0;
+ t1->flagssize=0;
+
+ return t1;
+}
+
+void t1_destroy(opj_t1_t *t1) {
+ if(t1) {
+ /* destroy MQC and RAW handles */
+ mqc_destroy(t1->mqc);
+ raw_destroy(t1->raw);
+ opj_aligned_free(t1->data);
+ opj_aligned_free(t1->flags);
+ opj_free(t1);
+ }
+}
+
+void t1_encode_cblks(
+ opj_t1_t *t1,
+ opj_tcd_tile_t *tile,
+ opj_tcp_t *tcp)
+{
+ int compno, resno, bandno, precno, cblkno;
+
+ tile->distotile = 0; /* fixed_quality */
+
+ for (compno = 0; compno < tile->numcomps; ++compno) {
+ opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
+ opj_tccp_t* tccp = &tcp->tccps[compno];
+ int tile_w = tilec->x1 - tilec->x0;
+
+ for (resno = 0; resno < tilec->numresolutions; ++resno) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_t* restrict band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; ++precno) {
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; ++cblkno) {
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+ int* restrict datap;
+ int* restrict tiledp;
+ int cblk_w;
+ int cblk_h;
+ int i, j;
+
+ int x = cblk->x0 - band->x0;
+ int y = cblk->y0 - band->y0;
+ if (band->bandno & 1) {
+ opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+ x += pres->x1 - pres->x0;
+ }
+ if (band->bandno & 2) {
+ opj_tcd_resolution_t *pres = &tilec->resolutions[resno - 1];
+ y += pres->y1 - pres->y0;
+ }
+
+ if(!allocate_buffers(
+ t1,
+ cblk->x1 - cblk->x0,
+ cblk->y1 - cblk->y0))
+ {
+ return;
+ }
+
+ datap=t1->data;
+ cblk_w = t1->w;
+ cblk_h = t1->h;
+
+ tiledp=&tilec->data[(y * tile_w) + x];
+ if (tccp->qmfbid == 1) {
+ for (j = 0; j < cblk_h; ++j) {
+ for (i = 0; i < cblk_w; ++i) {
+ int tmp = tiledp[(j * tile_w) + i];
+ datap[(j * cblk_w) + i] = tmp << T1_NMSEDEC_FRACBITS;
+ }
+ }
+ } else { /* if (tccp->qmfbid == 0) */
+ for (j = 0; j < cblk_h; ++j) {
+ for (i = 0; i < cblk_w; ++i) {
+ int tmp = tiledp[(j * tile_w) + i];
+ datap[(j * cblk_w) + i] =
+ fix_mul(
+ tmp,
+ 8192 * 8192 / ((int) floor(band->stepsize * 8192))) >> (11 - T1_NMSEDEC_FRACBITS);
+ }
+ }
+ }
+
+ t1_encode_cblk(
+ t1,
+ cblk,
+ band->bandno,
+ compno,
+ tilec->numresolutions - 1 - resno,
+ tccp->qmfbid,
+ band->stepsize,
+ tccp->cblksty,
+ tile->numcomps,
+ tile);
+
+ } /* cblkno */
+ } /* precno */
+ } /* bandno */
+ } /* resno */
+ } /* compno */
+}
+
+void t1_decode_cblks(
+ opj_t1_t* t1,
+ opj_tcd_tilecomp_t* tilec,
+ opj_tccp_t* tccp)
+{
+ int resno, bandno, precno, cblkno;
+
+ int tile_w = tilec->x1 - tilec->x0;
+
+ for (resno = 0; resno < tilec->numresolutions; ++resno) {
+ opj_tcd_resolution_t* res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; ++bandno) {
+ opj_tcd_band_t* restrict band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; ++precno) {
+ opj_tcd_precinct_t* precinct = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < precinct->cw * precinct->ch; ++cblkno) {
+ opj_tcd_cblk_dec_t* cblk = &precinct->cblks.dec[cblkno];
+ int* restrict datap;
+ void* restrict tiledp;
+ int cblk_w, cblk_h;
+ int x, y;
+ int i, j;
+
+ t1_decode_cblk(
+ t1,
+ cblk,
+ band->bandno,
+ tccp->roishift,
+ tccp->cblksty);
+
+ x = cblk->x0 - band->x0;
+ y = cblk->y0 - band->y0;
+ if (band->bandno & 1) {
+ opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
+ x += pres->x1 - pres->x0;
+ }
+ if (band->bandno & 2) {
+ opj_tcd_resolution_t* pres = &tilec->resolutions[resno - 1];
+ y += pres->y1 - pres->y0;
+ }
+
+ datap=t1->data;
+ cblk_w = t1->w;
+ cblk_h = t1->h;
+
+ if (tccp->roishift) {
+ int thresh = 1 << tccp->roishift;
+ for (j = 0; j < cblk_h; ++j) {
+ for (i = 0; i < cblk_w; ++i) {
+ int val = datap[(j * cblk_w) + i];
+ int mag = abs(val);
+ if (mag >= thresh) {
+ mag >>= tccp->roishift;
+ datap[(j * cblk_w) + i] = val < 0 ? -mag : mag;
+ }
+ }
+ }
+ }
+
+ tiledp=(void*)&tilec->data[(y * tile_w) + x];
+ if (tccp->qmfbid == 1) {
+ for (j = 0; j < cblk_h; ++j) {
+ for (i = 0; i < cblk_w; ++i) {
+ int tmp = datap[(j * cblk_w) + i];
+ ((int*)tiledp)[(j * tile_w) + i] = tmp / 2;
+ }
+ }
+ } else { /* if (tccp->qmfbid == 0) */
+ for (j = 0; j < cblk_h; ++j) {
+ for (i = 0; i < cblk_w; ++i) {
+ float tmp = datap[(j * cblk_w) + i] * band->stepsize;
+ ((float*)tiledp)[(j * tile_w) + i] = tmp;
+ }
+ }
+ }
+ opj_free(cblk->data);
+ opj_free(cblk->segs);
+ } /* cblkno */
+ opj_free(precinct->cblks.dec);
+ } /* precno */
+ } /* bandno */
+ } /* resno */
+}
+
diff --git a/Source/LibOpenJPEG/t1.h b/Source/LibOpenJPEG/t1.h
new file mode 100644
index 0000000..0b4294e
--- /dev/null
+++ b/Source/LibOpenJPEG/t1.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __T1_H
+#define __T1_H
+/**
+@file t1.h
+@brief Implementation of the tier-1 coding (coding of code-block coefficients) (T1)
+
+The functions in T1.C have for goal to realize the tier-1 coding operation. The functions
+in T1.C are used by some function in TCD.C.
+*/
+
+/** @defgroup T1 T1 - Implementation of the tier-1 coding */
+/*@{*/
+
+/* ----------------------------------------------------------------------- */
+#define T1_NMSEDEC_BITS 7
+
+#define T1_SIG_NE 0x0001 /**< Context orientation : North-East direction */
+#define T1_SIG_SE 0x0002 /**< Context orientation : South-East direction */
+#define T1_SIG_SW 0x0004 /**< Context orientation : South-West direction */
+#define T1_SIG_NW 0x0008 /**< Context orientation : North-West direction */
+#define T1_SIG_N 0x0010 /**< Context orientation : North direction */
+#define T1_SIG_E 0x0020 /**< Context orientation : East direction */
+#define T1_SIG_S 0x0040 /**< Context orientation : South direction */
+#define T1_SIG_W 0x0080 /**< Context orientation : West direction */
+#define T1_SIG_OTH (T1_SIG_N|T1_SIG_NE|T1_SIG_E|T1_SIG_SE|T1_SIG_S|T1_SIG_SW|T1_SIG_W|T1_SIG_NW)
+#define T1_SIG_PRIM (T1_SIG_N|T1_SIG_E|T1_SIG_S|T1_SIG_W)
+
+#define T1_SGN_N 0x0100
+#define T1_SGN_E 0x0200
+#define T1_SGN_S 0x0400
+#define T1_SGN_W 0x0800
+#define T1_SGN (T1_SGN_N|T1_SGN_E|T1_SGN_S|T1_SGN_W)
+
+#define T1_SIG 0x1000
+#define T1_REFINE 0x2000
+#define T1_VISIT 0x4000
+
+#define T1_NUMCTXS_ZC 9
+#define T1_NUMCTXS_SC 5
+#define T1_NUMCTXS_MAG 3
+#define T1_NUMCTXS_AGG 1
+#define T1_NUMCTXS_UNI 1
+
+#define T1_CTXNO_ZC 0
+#define T1_CTXNO_SC (T1_CTXNO_ZC+T1_NUMCTXS_ZC)
+#define T1_CTXNO_MAG (T1_CTXNO_SC+T1_NUMCTXS_SC)
+#define T1_CTXNO_AGG (T1_CTXNO_MAG+T1_NUMCTXS_MAG)
+#define T1_CTXNO_UNI (T1_CTXNO_AGG+T1_NUMCTXS_AGG)
+#define T1_NUMCTXS (T1_CTXNO_UNI+T1_NUMCTXS_UNI)
+
+#define T1_NMSEDEC_FRACBITS (T1_NMSEDEC_BITS-1)
+
+#define T1_TYPE_MQ 0 /**< Normal coding using entropy coder */
+#define T1_TYPE_RAW 1 /**< No encoding the information is store under raw format in codestream (mode switch RAW)*/
+
+/* ----------------------------------------------------------------------- */
+
+typedef short flag_t;
+
+/**
+Tier-1 coding (coding of code-block coefficients)
+*/
+typedef struct opj_t1 {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** MQC component */
+ opj_mqc_t *mqc;
+ /** RAW component */
+ opj_raw_t *raw;
+
+ int *data;
+ flag_t *flags;
+ int w;
+ int h;
+ int datasize;
+ int flagssize;
+ int flags_stride;
+} opj_t1_t;
+
+#define MACRO_t1_flags(x,y) t1->flags[((x)*(t1->flags_stride))+(y)]
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a new T1 handle
+and initialize the look-up tables of the Tier-1 coder/decoder
+@return Returns a new T1 handle if successful, returns NULL otherwise
+@see t1_init_luts
+*/
+opj_t1_t* t1_create(opj_common_ptr cinfo);
+/**
+Destroy a previously created T1 handle
+@param t1 T1 handle to destroy
+*/
+void t1_destroy(opj_t1_t *t1);
+/**
+Encode the code-blocks of a tile
+@param t1 T1 handle
+@param tile The tile to encode
+@param tcp Tile coding parameters
+*/
+void t1_encode_cblks(opj_t1_t *t1, opj_tcd_tile_t *tile, opj_tcp_t *tcp);
+/**
+Decode the code-blocks of a tile
+@param t1 T1 handle
+@param tile The tile to decode
+@param tcp Tile coding parameters
+*/
+void t1_decode_cblks(opj_t1_t* t1, opj_tcd_tilecomp_t* tilec, opj_tccp_t* tccp);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T1_H */
diff --git a/Source/LibOpenJPEG/t1_generate_luts.c b/Source/LibOpenJPEG/t1_generate_luts.c
new file mode 100644
index 0000000..1925b95
--- /dev/null
+++ b/Source/LibOpenJPEG/t1_generate_luts.c
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2007, Callum Lerwick <seg@haxxed.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+#include <math.h>
+
+static int t1_init_ctxno_zc(int f, int orient) {
+ int h, v, d, n, t, hv;
+ n = 0;
+ h = ((f & T1_SIG_W) != 0) + ((f & T1_SIG_E) != 0);
+ v = ((f & T1_SIG_N) != 0) + ((f & T1_SIG_S) != 0);
+ d = ((f & T1_SIG_NW) != 0) + ((f & T1_SIG_NE) != 0) + ((f & T1_SIG_SE) != 0) + ((f & T1_SIG_SW) != 0);
+
+ switch (orient) {
+ case 2:
+ t = h;
+ h = v;
+ v = t;
+ case 0:
+ case 1:
+ if (!h) {
+ if (!v) {
+ if (!d)
+ n = 0;
+ else if (d == 1)
+ n = 1;
+ else
+ n = 2;
+ } else if (v == 1) {
+ n = 3;
+ } else {
+ n = 4;
+ }
+ } else if (h == 1) {
+ if (!v) {
+ if (!d)
+ n = 5;
+ else
+ n = 6;
+ } else {
+ n = 7;
+ }
+ } else
+ n = 8;
+ break;
+ case 3:
+ hv = h + v;
+ if (!d) {
+ if (!hv) {
+ n = 0;
+ } else if (hv == 1) {
+ n = 1;
+ } else {
+ n = 2;
+ }
+ } else if (d == 1) {
+ if (!hv) {
+ n = 3;
+ } else if (hv == 1) {
+ n = 4;
+ } else {
+ n = 5;
+ }
+ } else if (d == 2) {
+ if (!hv) {
+ n = 6;
+ } else {
+ n = 7;
+ }
+ } else {
+ n = 8;
+ }
+ break;
+ }
+
+ return (T1_CTXNO_ZC + n);
+}
+
+static int t1_init_ctxno_sc(int f) {
+ int hc, vc, n;
+ n = 0;
+
+ hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+ T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W),
+ 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+ (T1_SIG_E | T1_SGN_E)) +
+ ((f & (T1_SIG_W | T1_SGN_W)) ==
+ (T1_SIG_W | T1_SGN_W)), 1);
+
+ vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+ T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S),
+ 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+ (T1_SIG_N | T1_SGN_N)) +
+ ((f & (T1_SIG_S | T1_SGN_S)) ==
+ (T1_SIG_S | T1_SGN_S)), 1);
+
+ if (hc < 0) {
+ hc = -hc;
+ vc = -vc;
+ }
+ if (!hc) {
+ if (vc == -1)
+ n = 1;
+ else if (!vc)
+ n = 0;
+ else
+ n = 1;
+ } else if (hc == 1) {
+ if (vc == -1)
+ n = 2;
+ else if (!vc)
+ n = 3;
+ else
+ n = 4;
+ }
+
+ return (T1_CTXNO_SC + n);
+}
+
+static int t1_init_spb(int f) {
+ int hc, vc, n;
+
+ hc = int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+ T1_SIG_E) + ((f & (T1_SIG_W | T1_SGN_W)) == T1_SIG_W),
+ 1) - int_min(((f & (T1_SIG_E | T1_SGN_E)) ==
+ (T1_SIG_E | T1_SGN_E)) +
+ ((f & (T1_SIG_W | T1_SGN_W)) ==
+ (T1_SIG_W | T1_SGN_W)), 1);
+
+ vc = int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+ T1_SIG_N) + ((f & (T1_SIG_S | T1_SGN_S)) == T1_SIG_S),
+ 1) - int_min(((f & (T1_SIG_N | T1_SGN_N)) ==
+ (T1_SIG_N | T1_SGN_N)) +
+ ((f & (T1_SIG_S | T1_SGN_S)) ==
+ (T1_SIG_S | T1_SGN_S)), 1);
+
+ if (!hc && !vc)
+ n = 0;
+ else
+ n = (!(hc > 0 || (!hc && vc > 0)));
+
+ return n;
+}
+
+void dump_array16(int array[],int size){
+ int i;
+ --size;
+ for (i = 0; i < size; ++i) {
+ printf("0x%04x, ", array[i]);
+ if(!((i+1)&0x7))
+ printf("\n ");
+ }
+ printf("0x%04x\n};\n\n", array[size]);
+}
+
+int main(){
+ int i, j;
+ double u, v, t;
+
+ int lut_ctxno_zc[1024];
+ int lut_nmsedec_sig[1 << T1_NMSEDEC_BITS];
+ int lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS];
+ int lut_nmsedec_ref[1 << T1_NMSEDEC_BITS];
+ int lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS];
+
+ printf("/* This file was automatically generated by t1_generate_luts.c */\n\n");
+
+ // lut_ctxno_zc
+ for (j = 0; j < 4; ++j) {
+ for (i = 0; i < 256; ++i) {
+ int orient = j;
+ if (orient == 2) {
+ orient = 1;
+ } else if (orient == 1) {
+ orient = 2;
+ }
+ lut_ctxno_zc[(orient << 8) | i] = t1_init_ctxno_zc(i, j);
+ }
+ }
+
+ printf("static char lut_ctxno_zc[1024] = {\n ");
+ for (i = 0; i < 1023; ++i) {
+ printf("%i, ", lut_ctxno_zc[i]);
+ if(!((i+1)&0x1f))
+ printf("\n ");
+ }
+ printf("%i\n};\n\n", lut_ctxno_zc[1023]);
+
+ // lut_ctxno_sc
+ printf("static char lut_ctxno_sc[256] = {\n ");
+ for (i = 0; i < 255; ++i) {
+ printf("0x%x, ", t1_init_ctxno_sc(i << 4));
+ if(!((i+1)&0xf))
+ printf("\n ");
+ }
+ printf("0x%x\n};\n\n", t1_init_ctxno_sc(255 << 4));
+
+ // lut_spb
+ printf("static char lut_spb[256] = {\n ");
+ for (i = 0; i < 255; ++i) {
+ printf("%i, ", t1_init_spb(i << 4));
+ if(!((i+1)&0x1f))
+ printf("\n ");
+ }
+ printf("%i\n};\n\n", t1_init_spb(255 << 4));
+
+ /* FIXME FIXME FIXME */
+ /* fprintf(stdout,"nmsedec luts:\n"); */
+ for (i = 0; i < (1 << T1_NMSEDEC_BITS); ++i) {
+ t = i / pow(2, T1_NMSEDEC_FRACBITS);
+ u = t;
+ v = t - 1.5;
+ lut_nmsedec_sig[i] =
+ int_max(0,
+ (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+ lut_nmsedec_sig0[i] =
+ int_max(0,
+ (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+ u = t - 1.0;
+ if (i & (1 << (T1_NMSEDEC_BITS - 1))) {
+ v = t - 1.5;
+ } else {
+ v = t - 0.5;
+ }
+ lut_nmsedec_ref[i] =
+ int_max(0,
+ (int) (floor((u * u - v * v) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+ lut_nmsedec_ref0[i] =
+ int_max(0,
+ (int) (floor((u * u) * pow(2, T1_NMSEDEC_FRACBITS) + 0.5) / pow(2, T1_NMSEDEC_FRACBITS) * 8192.0));
+ }
+
+ printf("static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {\n ");
+ dump_array16(&lut_nmsedec_sig, 1 << T1_NMSEDEC_BITS);
+
+ printf("static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {\n ");
+ dump_array16(&lut_nmsedec_sig0, 1 << T1_NMSEDEC_BITS);
+
+ printf("static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {\n ");
+ dump_array16(&lut_nmsedec_ref, 1 << T1_NMSEDEC_BITS);
+
+ printf("static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {\n ");
+ dump_array16(&lut_nmsedec_ref0, 1 << T1_NMSEDEC_BITS);
+
+ return 0;
+}
diff --git a/Source/LibOpenJPEG/t1_luts.h b/Source/LibOpenJPEG/t1_luts.h
new file mode 100644
index 0000000..e5e33f6
--- /dev/null
+++ b/Source/LibOpenJPEG/t1_luts.h
@@ -0,0 +1,143 @@
+/* This file was automatically generated by t1_generate_luts.c */
+
+static char lut_ctxno_zc[1024] = {
+ 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 0, 1, 1, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 0, 3, 3, 6, 3, 6, 6, 8, 3, 6, 6, 8, 6, 8, 8, 8, 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8,
+ 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 1, 4, 4, 7, 4, 7, 7, 8, 4, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8,
+ 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8, 2, 5, 5, 7, 5, 7, 7, 8, 5, 7, 7, 8, 7, 8, 8, 8
+};
+
+static char lut_ctxno_sc[256] = {
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xb, 0x9, 0xa, 0xb, 0xb, 0xa, 0xa,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xd, 0x9, 0xa, 0xb, 0xc, 0xa, 0x9,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xb, 0xc, 0xb, 0xb, 0xb, 0xb, 0xb,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xd, 0xc, 0xd, 0xb, 0xc, 0xb, 0xc,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0x9, 0xb, 0xc, 0xc, 0xb, 0x9, 0xa, 0xd, 0xc, 0xa, 0x9,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0xa, 0xb, 0xb, 0xc, 0xd, 0x9, 0xa, 0xd, 0xd, 0xa, 0xa,
+ 0x9, 0xa, 0xc, 0xb, 0xa, 0x9, 0xd, 0xc, 0xc, 0xb, 0xc, 0xb, 0xd, 0xc, 0xd, 0xc,
+ 0x9, 0xa, 0xc, 0xd, 0xa, 0xa, 0xd, 0xd, 0xc, 0xd, 0xc, 0xd, 0xd, 0xd, 0xd, 0xd
+};
+
+static char lut_spb[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0,
+ 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+static short lut_nmsedec_sig[1 << T1_NMSEDEC_BITS] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0180, 0x0300, 0x0480, 0x0600, 0x0780, 0x0900, 0x0a80,
+ 0x0c00, 0x0d80, 0x0f00, 0x1080, 0x1200, 0x1380, 0x1500, 0x1680,
+ 0x1800, 0x1980, 0x1b00, 0x1c80, 0x1e00, 0x1f80, 0x2100, 0x2280,
+ 0x2400, 0x2580, 0x2700, 0x2880, 0x2a00, 0x2b80, 0x2d00, 0x2e80,
+ 0x3000, 0x3180, 0x3300, 0x3480, 0x3600, 0x3780, 0x3900, 0x3a80,
+ 0x3c00, 0x3d80, 0x3f00, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680,
+ 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5100, 0x5280,
+ 0x5400, 0x5580, 0x5700, 0x5880, 0x5a00, 0x5b80, 0x5d00, 0x5e80,
+ 0x6000, 0x6180, 0x6300, 0x6480, 0x6600, 0x6780, 0x6900, 0x6a80,
+ 0x6c00, 0x6d80, 0x6f00, 0x7080, 0x7200, 0x7380, 0x7500, 0x7680
+};
+
+static short lut_nmsedec_sig0[1 << T1_NMSEDEC_BITS] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080,
+ 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200,
+ 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400,
+ 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780,
+ 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00,
+ 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180,
+ 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780,
+ 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00,
+ 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x2680, 0x2780,
+ 0x2880, 0x2980, 0x2b00, 0x2c00, 0x2d00, 0x2e80, 0x2f80, 0x3100,
+ 0x3200, 0x3380, 0x3480, 0x3600, 0x3700, 0x3880, 0x3a00, 0x3b00,
+ 0x3c80, 0x3e00, 0x3f80, 0x4080, 0x4200, 0x4380, 0x4500, 0x4680,
+ 0x4800, 0x4980, 0x4b00, 0x4c80, 0x4e00, 0x4f80, 0x5180, 0x5300,
+ 0x5480, 0x5600, 0x5800, 0x5980, 0x5b00, 0x5d00, 0x5e80, 0x6080,
+ 0x6200, 0x6400, 0x6580, 0x6780, 0x6900, 0x6b00, 0x6d00, 0x6e80,
+ 0x7080, 0x7280, 0x7480, 0x7600, 0x7800, 0x7a00, 0x7c00, 0x7e00
+};
+
+static short lut_nmsedec_ref[1 << T1_NMSEDEC_BITS] = {
+ 0x1800, 0x1780, 0x1700, 0x1680, 0x1600, 0x1580, 0x1500, 0x1480,
+ 0x1400, 0x1380, 0x1300, 0x1280, 0x1200, 0x1180, 0x1100, 0x1080,
+ 0x1000, 0x0f80, 0x0f00, 0x0e80, 0x0e00, 0x0d80, 0x0d00, 0x0c80,
+ 0x0c00, 0x0b80, 0x0b00, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880,
+ 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0500, 0x0480,
+ 0x0400, 0x0380, 0x0300, 0x0280, 0x0200, 0x0180, 0x0100, 0x0080,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380,
+ 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780,
+ 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b00, 0x0b80,
+ 0x0c00, 0x0c80, 0x0d00, 0x0d80, 0x0e00, 0x0e80, 0x0f00, 0x0f80,
+ 0x1000, 0x1080, 0x1100, 0x1180, 0x1200, 0x1280, 0x1300, 0x1380,
+ 0x1400, 0x1480, 0x1500, 0x1580, 0x1600, 0x1680, 0x1700, 0x1780
+};
+
+static short lut_nmsedec_ref0[1 << T1_NMSEDEC_BITS] = {
+ 0x2000, 0x1f00, 0x1e00, 0x1d00, 0x1c00, 0x1b00, 0x1a80, 0x1980,
+ 0x1880, 0x1780, 0x1700, 0x1600, 0x1500, 0x1480, 0x1380, 0x1300,
+ 0x1200, 0x1180, 0x1080, 0x1000, 0x0f00, 0x0e80, 0x0e00, 0x0d00,
+ 0x0c80, 0x0c00, 0x0b80, 0x0a80, 0x0a00, 0x0980, 0x0900, 0x0880,
+ 0x0800, 0x0780, 0x0700, 0x0680, 0x0600, 0x0580, 0x0580, 0x0500,
+ 0x0480, 0x0400, 0x0400, 0x0380, 0x0300, 0x0300, 0x0280, 0x0280,
+ 0x0200, 0x0200, 0x0180, 0x0180, 0x0100, 0x0100, 0x0100, 0x0080,
+ 0x0080, 0x0080, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0080,
+ 0x0080, 0x0080, 0x0100, 0x0100, 0x0100, 0x0180, 0x0180, 0x0200,
+ 0x0200, 0x0280, 0x0280, 0x0300, 0x0300, 0x0380, 0x0400, 0x0400,
+ 0x0480, 0x0500, 0x0580, 0x0580, 0x0600, 0x0680, 0x0700, 0x0780,
+ 0x0800, 0x0880, 0x0900, 0x0980, 0x0a00, 0x0a80, 0x0b80, 0x0c00,
+ 0x0c80, 0x0d00, 0x0e00, 0x0e80, 0x0f00, 0x1000, 0x1080, 0x1180,
+ 0x1200, 0x1300, 0x1380, 0x1480, 0x1500, 0x1600, 0x1700, 0x1780,
+ 0x1880, 0x1980, 0x1a80, 0x1b00, 0x1c00, 0x1d00, 0x1e00, 0x1f00
+};
+
diff --git a/Source/LibOpenJPEG/t2.c b/Source/LibOpenJPEG/t2.c
new file mode 100644
index 0000000..be9b42a
--- /dev/null
+++ b/Source/LibOpenJPEG/t2.c
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/** @name Local static functions */
+/*@{*/
+
+static void t2_putcommacode(opj_bio_t *bio, int n);
+static int t2_getcommacode(opj_bio_t *bio);
+/**
+Variable length code for signalling delta Zil (truncation point)
+@param bio Bit Input/Output component
+@param n delta Zil
+*/
+static void t2_putnumpasses(opj_bio_t *bio, int n);
+static int t2_getnumpasses(opj_bio_t *bio);
+/**
+Encode a packet of a tile to a destination buffer
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@param dest Destination buffer
+@param len Length of the destination buffer
+@param cstr_info Codestream information structure
+@param tileno Number of the tile encoded
+@return
+*/
+static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterator_t *pi, unsigned char *dest, int len, opj_codestream_info_t *cstr_info, int tileno);
+/**
+@param seg
+@param cblksty
+@param first
+*/
+static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
+/**
+Decode a packet of a tile from a source buffer
+@param t2 T2 handle
+@param src Source buffer
+@param len Length of the source buffer
+@param tile Tile for which to write the packets
+@param tcp Tile coding parameters
+@param pi Packet identity
+@return
+*/
+static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
+ opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info);
+
+/*@}*/
+
+/*@}*/
+
+/* ----------------------------------------------------------------------- */
+
+/* #define RESTART 0x04 */
+
+static void t2_putcommacode(opj_bio_t *bio, int n) {
+ while (--n >= 0) {
+ bio_write(bio, 1, 1);
+ }
+ bio_write(bio, 0, 1);
+}
+
+static int t2_getcommacode(opj_bio_t *bio) {
+ int n;
+ for (n = 0; bio_read(bio, 1); n++) {
+ ;
+ }
+ return n;
+}
+
+static void t2_putnumpasses(opj_bio_t *bio, int n) {
+ if (n == 1) {
+ bio_write(bio, 0, 1);
+ } else if (n == 2) {
+ bio_write(bio, 2, 2);
+ } else if (n <= 5) {
+ bio_write(bio, 0xc | (n - 3), 4);
+ } else if (n <= 36) {
+ bio_write(bio, 0x1e0 | (n - 6), 9);
+ } else if (n <= 164) {
+ bio_write(bio, 0xff80 | (n - 37), 16);
+ }
+}
+
+static int t2_getnumpasses(opj_bio_t *bio) {
+ int n;
+ if (!bio_read(bio, 1))
+ return 1;
+ if (!bio_read(bio, 1))
+ return 2;
+ if ((n = bio_read(bio, 2)) != 3)
+ return (3 + n);
+ if ((n = bio_read(bio, 5)) != 31)
+ return (6 + n);
+ return (37 + bio_read(bio, 7));
+}
+
+static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_iterator_t *pi, unsigned char *dest, int length, opj_codestream_info_t *cstr_info, int tileno) {
+ int bandno, cblkno;
+ unsigned char *c = dest;
+
+ int compno = pi->compno; /* component value */
+ int resno = pi->resno; /* resolution level value */
+ int precno = pi->precno; /* precinct value */
+ int layno = pi->layno; /* quality layer value */
+
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ opj_bio_t *bio = NULL; /* BIO component */
+
+ /* <SOP 0xff91> */
+ if (tcp->csty & J2K_CP_CSTY_SOP) {
+ c[0] = 255;
+ c[1] = 145;
+ c[2] = 0;
+ c[3] = 4;
+ c[4] = (tile->packno % 65536) / 256;
+ c[5] = (tile->packno % 65536) % 256;
+ c += 6;
+ }
+ /* </SOP> */
+
+ if (!layno) {
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ tgt_reset(prc->incltree);
+ tgt_reset(prc->imsbtree);
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+ cblk->numpasses = 0;
+ tgt_setvalue(prc->imsbtree, cblkno, band->numbps - cblk->numbps);
+ }
+ }
+ }
+
+ bio = bio_create();
+ bio_init_enc(bio, c, length);
+ bio_write(bio, 1, 1); /* Empty header bit */
+
+ /* Writing Packet header */
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+ opj_tcd_layer_t *layer = &cblk->layers[layno];
+ if (!cblk->numpasses && layer->numpasses) {
+ tgt_setvalue(prc->incltree, cblkno, layno);
+ }
+ }
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+ opj_tcd_layer_t *layer = &cblk->layers[layno];
+ int increment = 0;
+ int nump = 0;
+ int len = 0, passno;
+ /* cblk inclusion bits */
+ if (!cblk->numpasses) {
+ tgt_encode(bio, prc->incltree, cblkno, layno + 1);
+ } else {
+ bio_write(bio, layer->numpasses != 0, 1);
+ }
+ /* if cblk not included, go to the next cblk */
+ if (!layer->numpasses) {
+ continue;
+ }
+ /* if first instance of cblk --> zero bit-planes information */
+ if (!cblk->numpasses) {
+ cblk->numlenbits = 3;
+ tgt_encode(bio, prc->imsbtree, cblkno, 999);
+ }
+ /* number of coding passes included */
+ t2_putnumpasses(bio, layer->numpasses);
+
+ /* computation of the increase of the length indicator and insertion in the header */
+ for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) {
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ nump++;
+ len += pass->len;
+ if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+ increment = int_max(increment, int_floorlog2(len) + 1 - (cblk->numlenbits + int_floorlog2(nump)));
+ len = 0;
+ nump = 0;
+ }
+ }
+ t2_putcommacode(bio, increment);
+
+ /* computation of the new Length indicator */
+ cblk->numlenbits += increment;
+
+ /* insertion of the codeword segment length */
+ for (passno = cblk->numpasses; passno < cblk->numpasses + layer->numpasses; passno++) {
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ nump++;
+ len += pass->len;
+ if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
+ bio_write(bio, len, cblk->numlenbits + int_floorlog2(nump));
+ len = 0;
+ nump = 0;
+ }
+ }
+ }
+ }
+
+ if (bio_flush(bio)) {
+ bio_destroy(bio);
+ return -999; /* modified to eliminate longjmp !! */
+ }
+
+ c += bio_numbytes(bio);
+ bio_destroy(bio);
+
+ /* <EPH 0xff92> */
+ if (tcp->csty & J2K_CP_CSTY_EPH) {
+ c[0] = 255;
+ c[1] = 146;
+ c += 2;
+ }
+ /* </EPH> */
+
+ /* << INDEX */
+ // End of packet header position. Currently only represents the distance to start of packet
+ // Will be updated later by incrementing with packet start value
+ if(cstr_info && cstr_info->index_write) {
+ opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
+ info_PK->end_ph_pos = (int)(c - dest);
+ }
+ /* INDEX >> */
+
+ /* Writing the packet body */
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+ opj_tcd_layer_t *layer = &cblk->layers[layno];
+ if (!layer->numpasses) {
+ continue;
+ }
+ if (c + layer->len > dest + length) {
+ return -999;
+ }
+
+ memcpy(c, layer->data, layer->len);
+ cblk->numpasses += layer->numpasses;
+ c += layer->len;
+ /* << INDEX */
+ if(cstr_info && cstr_info->index_write) {
+ opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
+ info_PK->disto += layer->disto;
+ if (cstr_info->D_max < info_PK->disto) {
+ cstr_info->D_max = info_PK->disto;
+ }
+ }
+ /* INDEX >> */
+ }
+ }
+
+ return (c - dest);
+}
+
+static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
+ opj_tcd_seg_t* seg;
+ cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
+ seg = &cblk->segs[index];
+ seg->data = NULL;
+ seg->dataindex = 0;
+ seg->numpasses = 0;
+ seg->len = 0;
+ if (cblksty & J2K_CCP_CBLKSTY_TERMALL) {
+ seg->maxpasses = 1;
+ }
+ else if (cblksty & J2K_CCP_CBLKSTY_LAZY) {
+ if (first) {
+ seg->maxpasses = 10;
+ } else {
+ seg->maxpasses = (((seg - 1)->maxpasses == 1) || ((seg - 1)->maxpasses == 10)) ? 2 : 1;
+ }
+ } else {
+ seg->maxpasses = 109;
+ }
+}
+
+static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
+ opj_tcp_t *tcp, opj_pi_iterator_t *pi, opj_packet_info_t *pack_info) {
+ int bandno, cblkno;
+ unsigned char *c = src;
+
+ opj_cp_t *cp = t2->cp;
+
+ int compno = pi->compno; /* component value */
+ int resno = pi->resno; /* resolution level value */
+ int precno = pi->precno; /* precinct value */
+ int layno = pi->layno; /* quality layer value */
+
+ opj_tcd_resolution_t* res = &tile->comps[compno].resolutions[resno];
+
+ unsigned char *hd = NULL;
+ int present;
+
+ opj_bio_t *bio = NULL; /* BIO component */
+
+ if (layno == 0) {
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+
+ tgt_reset(prc->incltree);
+ tgt_reset(prc->imsbtree);
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno];
+ cblk->numsegs = 0;
+ }
+ }
+ }
+
+ /* SOP markers */
+
+ if (tcp->csty & J2K_CP_CSTY_SOP) {
+ if ((*c) != 0xff || (*(c + 1) != 0x91)) {
+ opj_event_msg(t2->cinfo, EVT_WARNING, "Expected SOP marker\n");
+ } else {
+ c += 6;
+ }
+
+ /** TODO : check the Nsop value */
+ }
+
+ /*
+ When the marker PPT/PPM is used the packet header are store in PPT/PPM marker
+ This part deal with this caracteristic
+ step 1: Read packet header in the saved structure
+ step 2: Return to codestream for decoding
+ */
+
+ bio = bio_create();
+
+ if (cp->ppm == 1) { /* PPM */
+ hd = cp->ppm_data;
+ bio_init_dec(bio, hd, cp->ppm_len);
+ } else if (tcp->ppt == 1) { /* PPT */
+ hd = tcp->ppt_data;
+ bio_init_dec(bio, hd, tcp->ppt_len);
+ } else { /* Normal Case */
+ hd = c;
+ bio_init_dec(bio, hd, src+len-hd);
+ }
+
+ present = bio_read(bio, 1);
+
+ if (!present) {
+ bio_inalign(bio);
+ hd += bio_numbytes(bio);
+ bio_destroy(bio);
+
+ /* EPH markers */
+
+ if (tcp->csty & J2K_CP_CSTY_EPH) {
+ if ((*hd) != 0xff || (*(hd + 1) != 0x92)) {
+ printf("Error : expected EPH marker\n");
+ } else {
+ hd += 2;
+ }
+ }
+
+ /* << INDEX */
+ // End of packet header position. Currently only represents the distance to start of packet
+ // Will be updated later by incrementing with packet start value
+ if(pack_info) {
+ pack_info->end_ph_pos = (int)(c - src);
+ }
+ /* INDEX >> */
+
+ if (cp->ppm == 1) { /* PPM case */
+ cp->ppm_len += cp->ppm_data-hd;
+ cp->ppm_data = hd;
+ return (c - src);
+ }
+ if (tcp->ppt == 1) { /* PPT case */
+ tcp->ppt_len+=tcp->ppt_data-hd;
+ tcp->ppt_data = hd;
+ return (c - src);
+ }
+
+ return (hd - src);
+ }
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ int included, increment, n, segno;
+ opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno];
+ /* if cblk not yet included before --> inclusion tagtree */
+ if (!cblk->numsegs) {
+ included = tgt_decode(bio, prc->incltree, cblkno, layno + 1);
+ /* else one bit */
+ } else {
+ included = bio_read(bio, 1);
+ }
+ /* if cblk not included */
+ if (!included) {
+ cblk->numnewpasses = 0;
+ continue;
+ }
+ /* if cblk not yet included --> zero-bitplane tagtree */
+ if (!cblk->numsegs) {
+ int i, numimsbs;
+ for (i = 0; !tgt_decode(bio, prc->imsbtree, cblkno, i); i++) {
+ ;
+ }
+ numimsbs = i - 1;
+ cblk->numbps = band->numbps - numimsbs;
+ cblk->numlenbits = 3;
+ }
+ /* number of coding passes */
+ cblk->numnewpasses = t2_getnumpasses(bio);
+ increment = t2_getcommacode(bio);
+ /* length indicator increment */
+ cblk->numlenbits += increment;
+ segno = 0;
+ if (!cblk->numsegs) {
+ t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1);
+ } else {
+ segno = cblk->numsegs - 1;
+ if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) {
+ ++segno;
+ t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
+ }
+ }
+ n = cblk->numnewpasses;
+
+ do {
+ cblk->segs[segno].numnewpasses = int_min(cblk->segs[segno].maxpasses - cblk->segs[segno].numpasses, n);
+ cblk->segs[segno].newlen = bio_read(bio, cblk->numlenbits + int_floorlog2(cblk->segs[segno].numnewpasses));
+ n -= cblk->segs[segno].numnewpasses;
+ if (n > 0) {
+ ++segno;
+ t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0);
+ }
+ } while (n > 0);
+ }
+ }
+
+ if (bio_inalign(bio)) {
+ bio_destroy(bio);
+ return -999;
+ }
+
+ hd += bio_numbytes(bio);
+ bio_destroy(bio);
+
+ /* EPH markers */
+ if (tcp->csty & J2K_CP_CSTY_EPH) {
+ if ((*hd) != 0xff || (*(hd + 1) != 0x92)) {
+ opj_event_msg(t2->cinfo, EVT_ERROR, "Expected EPH marker\n");
+ } else {
+ hd += 2;
+ }
+ }
+
+ /* << INDEX */
+ // End of packet header position. Currently only represents the distance to start of packet
+ // Will be updated later by incrementing with packet start value
+ if(pack_info) {
+ pack_info->end_ph_pos = (int)(hd - src);
+ }
+ /* INDEX >> */
+
+ if (cp->ppm==1) {
+ cp->ppm_len+=cp->ppm_data-hd;
+ cp->ppm_data = hd;
+ } else if (tcp->ppt == 1) {
+ tcp->ppt_len+=tcp->ppt_data-hd;
+ tcp->ppt_data = hd;
+ } else {
+ c=hd;
+ }
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ if ((band->x1-band->x0 == 0)||(band->y1-band->y0 == 0)) continue;
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno];
+ opj_tcd_seg_t *seg = NULL;
+ if (!cblk->numnewpasses)
+ continue;
+ if (!cblk->numsegs) {
+ seg = &cblk->segs[0];
+ cblk->numsegs++;
+ cblk->len = 0;
+ } else {
+ seg = &cblk->segs[cblk->numsegs - 1];
+ if (seg->numpasses == seg->maxpasses) {
+ seg++;
+ cblk->numsegs++;
+ }
+ }
+
+ do {
+ if (c + seg->newlen > src + len) {
+ return -999;
+ }
+
+#ifdef USE_JPWL
+ /* we need here a j2k handle to verify if making a check to
+ the validity of cblocks parameters is selected from user (-W) */
+
+ /* let's check that we are not exceeding */
+ if ((cblk->len + seg->newlen) > 8192) {
+ opj_event_msg(t2->cinfo, EVT_WARNING,
+ "JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
+ seg->newlen, cblkno, precno, bandno, resno, compno);
+ if (!JPWL_ASSUME) {
+ opj_event_msg(t2->cinfo, EVT_ERROR, "JPWL: giving up\n");
+ return -999;
+ }
+ seg->newlen = 8192 - cblk->len;
+ opj_event_msg(t2->cinfo, EVT_WARNING, " - truncating segment to %d\n", seg->newlen);
+ break;
+ };
+
+#endif /* USE_JPWL */
+
+ cblk->data = (unsigned char*) opj_realloc(cblk->data, (cblk->len + seg->newlen) * sizeof(unsigned char*));
+ memcpy(cblk->data + cblk->len, c, seg->newlen);
+ if (seg->numpasses == 0) {
+ seg->data = &cblk->data;
+ seg->dataindex = cblk->len;
+ }
+ c += seg->newlen;
+ cblk->len += seg->newlen;
+ seg->len += seg->newlen;
+ seg->numpasses += seg->numnewpasses;
+ cblk->numnewpasses -= seg->numnewpasses;
+ if (cblk->numnewpasses > 0) {
+ seg++;
+ cblk->numsegs++;
+ }
+ } while (cblk->numnewpasses > 0);
+ }
+ }
+
+ return (c - src);
+}
+
+/* ----------------------------------------------------------------------- */
+
+int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_codestream_info_t *cstr_info,int tpnum, int tppos,int pino, J2K_T2_MODE t2_mode, int cur_totnum_tp){
+ unsigned char *c = dest;
+ int e = 0;
+ int compno;
+ opj_pi_iterator_t *pi = NULL;
+ int poc;
+ opj_image_t *image = t2->image;
+ opj_cp_t *cp = t2->cp;
+ opj_tcp_t *tcp = &cp->tcps[tileno];
+ int pocno = cp->cinema == CINEMA4K_24? 2: 1;
+ int maxcomp = cp->max_comp_size > 0 ? image->numcomps : 1;
+
+ pi = pi_initialise_encode(image, cp, tileno, t2_mode);
+ if(!pi) {
+ /* TODO: throw an error */
+ return -999;
+ }
+
+ if(t2_mode == THRESH_CALC ){ /* Calculating threshold */
+ for(compno = 0; compno < maxcomp; compno++ ){
+ for(poc = 0; poc < pocno ; poc++){
+ int comp_len = 0;
+ int tpnum = compno;
+ if (pi_create_encode(pi, cp,tileno,poc,tpnum,tppos,t2_mode,cur_totnum_tp)) {
+ opj_event_msg(t2->cinfo, EVT_ERROR, "Error initializing Packet Iterator\n");
+ return -999;
+ }
+ while (pi_next(&pi[poc])) {
+ if (pi[poc].layno < maxlayers) {
+ e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[poc], c, dest + len - c, cstr_info, tileno);
+ comp_len = comp_len + e;
+ if (e == -999) {
+ break;
+ } else {
+ c += e;
+ }
+ }
+ }
+ if (e == -999) break;
+ if (cp->max_comp_size){
+ if (comp_len > cp->max_comp_size){
+ e = -999;
+ break;
+ }
+ }
+ }
+ if (e == -999) break;
+ }
+ }else{ /* t2_mode == FINAL_PASS */
+ pi_create_encode(pi, cp,tileno,pino,tpnum,tppos,t2_mode,cur_totnum_tp);
+ while (pi_next(&pi[pino])) {
+ if (pi[pino].layno < maxlayers) {
+ e = t2_encode_packet(tile, &cp->tcps[tileno], &pi[pino], c, dest + len - c, cstr_info, tileno);
+ if (e == -999) {
+ break;
+ } else {
+ c += e;
+ }
+ /* INDEX >> */
+ if(cstr_info) {
+ if(cstr_info->index_write) {
+ opj_tile_info_t *info_TL = &cstr_info->tile[tileno];
+ opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno];
+ if (!cstr_info->packno) {
+ info_PK->start_pos = info_TL->end_header + 1;
+ } else {
+ info_PK->start_pos = ((cp->tp_on | tcp->POC)&& info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1;
+ }
+ info_PK->end_pos = info_PK->start_pos + e - 1;
+ info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance
+ // to start of packet is incremented by value of start of packet
+ }
+
+ cstr_info->packno++;
+ }
+ /* << INDEX */
+ tile->packno++;
+ }
+ }
+ }
+
+ pi_destroy(pi, cp, tileno);
+
+ if (e == -999) {
+ return e;
+ }
+
+ return (c - dest);
+}
+
+int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info) {
+ unsigned char *c = src;
+ opj_pi_iterator_t *pi;
+ int pino, e = 0;
+ int n = 0, curtp = 0;
+ int tp_start_packno;
+
+ opj_image_t *image = t2->image;
+ opj_cp_t *cp = t2->cp;
+
+ /* create a packet iterator */
+ pi = pi_create_decode(image, cp, tileno);
+ if(!pi) {
+ /* TODO: throw an error */
+ return -999;
+ }
+
+ tp_start_packno = 0;
+
+ for (pino = 0; pino <= cp->tcps[tileno].numpocs; pino++) {
+ while (pi_next(&pi[pino])) {
+ if ((cp->layer==0) || (cp->layer>=((pi[pino].layno)+1))) {
+ opj_packet_info_t *pack_info;
+ if (cstr_info)
+ pack_info = &cstr_info->tile[tileno].packet[cstr_info->packno];
+ else
+ pack_info = NULL;
+ e = t2_decode_packet(t2, c, src + len - c, tile, &cp->tcps[tileno], &pi[pino], pack_info);
+ } else {
+ e = 0;
+ }
+
+ /* progression in resolution */
+ image->comps[pi[pino].compno].resno_decoded =
+ (e > 0) ?
+ int_max(pi[pino].resno, image->comps[pi[pino].compno].resno_decoded)
+ : image->comps[pi[pino].compno].resno_decoded;
+ n++;
+
+ /* INDEX >> */
+ if(cstr_info) {
+ opj_tile_info_t *info_TL = &cstr_info->tile[tileno];
+ opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno];
+ if (!cstr_info->packno) {
+ info_PK->start_pos = info_TL->end_header + 1;
+ } else if (info_TL->packet[cstr_info->packno-1].end_pos >= (int)cstr_info->tile[tileno].tp[curtp].tp_end_pos){ // New tile part
+ info_TL->tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in previous tile-part
+ tp_start_packno = cstr_info->packno;
+ curtp++;
+ info_PK->start_pos = cstr_info->tile[tileno].tp[curtp].tp_end_header+1;
+ } else {
+ info_PK->start_pos = (cp->tp_on && info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno - 1].end_pos + 1;
+ }
+ info_PK->end_pos = info_PK->start_pos + e - 1;
+ info_PK->end_ph_pos += info_PK->start_pos - 1; // End of packet header which now only represents the distance
+ // to start of packet is incremented by value of start of packet
+ cstr_info->packno++;
+ }
+ /* << INDEX */
+
+ if (e == -999) { /* ADD */
+ break;
+ } else {
+ c += e;
+ }
+ }
+ }
+ /* INDEX >> */
+ if(cstr_info) {
+ cstr_info->tile[tileno].tp[curtp].tp_numpacks = cstr_info->packno - tp_start_packno; // Number of packets in last tile-part
+ }
+ /* << INDEX */
+
+ /* don't forget to release pi */
+ pi_destroy(pi, cp, tileno);
+
+ if (e == -999) {
+ return e;
+ }
+
+ return (c - src);
+}
+
+/* ----------------------------------------------------------------------- */
+
+opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp) {
+ /* create the tcd structure */
+ opj_t2_t *t2 = (opj_t2_t*)opj_malloc(sizeof(opj_t2_t));
+ if(!t2) return NULL;
+ t2->cinfo = cinfo;
+ t2->image = image;
+ t2->cp = cp;
+
+ return t2;
+}
+
+void t2_destroy(opj_t2_t *t2) {
+ if(t2) {
+ opj_free(t2);
+ }
+}
+
+
+
+
+
diff --git a/Source/LibOpenJPEG/t2.h b/Source/LibOpenJPEG/t2.h
new file mode 100644
index 0000000..b15b752
--- /dev/null
+++ b/Source/LibOpenJPEG/t2.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __T2_H
+#define __T2_H
+/**
+@file t2.h
+@brief Implementation of a tier-2 coding (packetization of code-block data) (T2)
+
+*/
+
+/** @defgroup T2 T2 - Implementation of a tier-2 coding */
+/*@{*/
+
+/**
+Tier-2 coding
+*/
+typedef struct opj_t2 {
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** Encoding: pointer to the src image. Decoding: pointer to the dst image. */
+ opj_image_t *image;
+ /** pointer to the image coding parameters */
+ opj_cp_t *cp;
+} opj_t2_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Encode the packets of a tile to a destination buffer
+@param t2 T2 handle
+@param tileno number of the tile encoded
+@param tile the tile for which to write the packets
+@param maxlayers maximum number of layers
+@param dest the destination buffer
+@param len the length of the destination buffer
+@param cstr_info Codestream information structure
+@param tpnum Tile part number of the current tile
+@param tppos The position of the tile part flag in the progression order
+@param t2_mode If == 0 In Threshold calculation ,If == 1 Final pass
+@param cur_totnum_tp The total number of tile parts in the current tile
+*/
+int t2_encode_packets(opj_t2_t* t2,int tileno, opj_tcd_tile_t *tile, int maxlayers, unsigned char *dest, int len, opj_codestream_info_t *cstr_info,int tpnum, int tppos,int pino,J2K_T2_MODE t2_mode,int cur_totnum_tp);
+/**
+Decode the packets of a tile from a source buffer
+@param t2 T2 handle
+@param src the source buffer
+@param len length of the source buffer
+@param tileno number that identifies the tile for which to decode the packets
+@param tile tile for which to decode the packets
+ */
+int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj_tcd_tile_t *tile, opj_codestream_info_t *cstr_info);
+
+/**
+Create a T2 handle
+@param cinfo Codec context info
+@param image Source or destination image
+@param cp Image coding parameters
+@return Returns a new T2 handle if successful, returns NULL otherwise
+*/
+opj_t2_t* t2_create(opj_common_ptr cinfo, opj_image_t *image, opj_cp_t *cp);
+/**
+Destroy a T2 handle
+@param t2 T2 handle to destroy
+*/
+void t2_destroy(opj_t2_t *t2);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __T2_H */
diff --git a/Source/LibOpenJPEG/tcd.c b/Source/LibOpenJPEG/tcd.c
new file mode 100644
index 0000000..7f154f4
--- /dev/null
+++ b/Source/LibOpenJPEG/tcd.c
@@ -0,0 +1,1516 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * Copyright (c) 2006-2007, Parvatha Elangovan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
+ int tileno, compno, resno, bandno, precno;//, cblkno;
+
+ fprintf(fd, "image {\n");
+ fprintf(fd, " tw=%d, th=%d x0=%d x1=%d y0=%d y1=%d\n",
+ img->tw, img->th, tcd->image->x0, tcd->image->x1, tcd->image->y0, tcd->image->y1);
+
+ for (tileno = 0; tileno < img->th * img->tw; tileno++) {
+ opj_tcd_tile_t *tile = &tcd->tcd_image->tiles[tileno];
+ fprintf(fd, " tile {\n");
+ fprintf(fd, " x0=%d, y0=%d, x1=%d, y1=%d, numcomps=%d\n",
+ tile->x0, tile->y0, tile->x1, tile->y1, tile->numcomps);
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ fprintf(fd, " tilec {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, numresolutions=%d\n",
+ tilec->x0, tilec->y0, tilec->x1, tilec->y1, tilec->numresolutions);
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+ fprintf(fd, "\n res {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, pw=%d, ph=%d, numbands=%d\n",
+ res->x0, res->y0, res->x1, res->y1, res->pw, res->ph, res->numbands);
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ fprintf(fd, " band {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, stepsize=%f, numbps=%d\n",
+ band->x0, band->y0, band->x1, band->y1, band->stepsize, band->numbps);
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prec = &band->precincts[precno];
+ fprintf(fd, " prec {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d, cw=%d, ch=%d\n",
+ prec->x0, prec->y0, prec->x1, prec->y1, prec->cw, prec->ch);
+ /*
+ for (cblkno = 0; cblkno < prec->cw * prec->ch; cblkno++) {
+ opj_tcd_cblk_t *cblk = &prec->cblks[cblkno];
+ fprintf(fd, " cblk {\n");
+ fprintf(fd,
+ " x0=%d, y0=%d, x1=%d, y1=%d\n",
+ cblk->x0, cblk->y0, cblk->x1, cblk->y1);
+ fprintf(fd, " }\n");
+ }
+ */
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, " }\n");
+ }
+ fprintf(fd, "}\n");
+}
+
+/* ----------------------------------------------------------------------- */
+
+/**
+Create a new TCD handle
+*/
+opj_tcd_t* tcd_create(opj_common_ptr cinfo) {
+ /* create the tcd structure */
+ opj_tcd_t *tcd = (opj_tcd_t*)opj_malloc(sizeof(opj_tcd_t));
+ if(!tcd) return NULL;
+ tcd->cinfo = cinfo;
+ tcd->tcd_image = (opj_tcd_image_t*)opj_malloc(sizeof(opj_tcd_image_t));
+ if(!tcd->tcd_image) {
+ opj_free(tcd);
+ return NULL;
+ }
+
+ return tcd;
+}
+
+/**
+Destroy a previously created TCD handle
+*/
+void tcd_destroy(opj_tcd_t *tcd) {
+ if(tcd) {
+ opj_free(tcd->tcd_image);
+ opj_free(tcd);
+ }
+}
+
+/* ----------------------------------------------------------------------- */
+
+void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) {
+ int tileno, compno, resno, bandno, precno, cblkno;
+
+ tcd->image = image;
+ tcd->cp = cp;
+ tcd->tcd_image->tw = cp->tw;
+ tcd->tcd_image->th = cp->th;
+ tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(sizeof(opj_tcd_tile_t));
+
+ for (tileno = 0; tileno < 1; tileno++) {
+ opj_tcp_t *tcp = &cp->tcps[curtileno];
+ int j;
+
+ /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+ int p = curtileno % cp->tw; /* si numerotation matricielle .. */
+ int q = curtileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */
+
+ /* opj_tcd_tile_t *tile=&tcd->tcd_image->tiles[tileno]; */
+ opj_tcd_tile_t *tile = tcd->tcd_image->tiles;
+
+ /* 4 borders of the tile rescale on the image if necessary */
+ tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+ tile->numcomps = image->numcomps;
+ /* tile->PPT=image->PPT; */
+
+ /* Modification of the RATE >> */
+ for (j = 0; j < tcp->numlayers; j++) {
+ tcp->rates[j] = tcp->rates[j] ?
+ cp->tp_on ?
+ (((float) (tile->numcomps
+ * (tile->x1 - tile->x0)
+ * (tile->y1 - tile->y0)
+ * image->comps[0].prec))
+ /(tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) - (((tcd->cur_totnum_tp - 1) * 14 )/ tcp->numlayers)
+ :
+ ((float) (tile->numcomps
+ * (tile->x1 - tile->x0)
+ * (tile->y1 - tile->y0)
+ * image->comps[0].prec))/
+ (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)
+ : 0;
+
+ if (tcp->rates[j]) {
+ if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) {
+ tcp->rates[j] = tcp->rates[j - 1] + 20;
+ } else {
+ if (!j && tcp->rates[j] < 30)
+ tcp->rates[j] = 30;
+ }
+
+ if(j == (tcp->numlayers-1)){
+ tcp->rates[j] = tcp->rates[j]- 2;
+ }
+ }
+ }
+ /* << Modification of the RATE */
+
+ tile->comps = (opj_tcd_tilecomp_t *) opj_malloc(image->numcomps * sizeof(opj_tcd_tilecomp_t));
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+ /* border of each tile component (global) */
+ tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+ tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+ tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+ tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+
+ tilec->data = (int *) opj_aligned_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int));
+ tilec->numresolutions = tccp->numresolutions;
+
+ tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t));
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ int pdx, pdy;
+ int levelno = tilec->numresolutions - 1 - resno;
+ int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+ int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+ int cbgwidthexpn, cbgheightexpn;
+ int cblkwidthexpn, cblkheightexpn;
+
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ /* border for each resolution level (global) */
+ res->x0 = int_ceildivpow2(tilec->x0, levelno);
+ res->y0 = int_ceildivpow2(tilec->y0, levelno);
+ res->x1 = int_ceildivpow2(tilec->x1, levelno);
+ res->y1 = int_ceildivpow2(tilec->y1, levelno);
+
+ res->numbands = resno == 0 ? 1 : 3;
+ /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ pdx = tccp->prcw[resno];
+ pdy = tccp->prch[resno];
+ } else {
+ pdx = 15;
+ pdy = 15;
+ }
+ /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+ tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+
+ brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+ brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+
+ res->pw = (brprcxend - tlprcxstart) >> pdx;
+ res->ph = (brprcyend - tlprcystart) >> pdy;
+
+ if (resno == 0) {
+ tlcbgxstart = tlprcxstart;
+ tlcbgystart = tlprcystart;
+ brcbgxend = brprcxend;
+ brcbgyend = brprcyend;
+ cbgwidthexpn = pdx;
+ cbgheightexpn = pdy;
+ } else {
+ tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+ tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+ brcbgxend = int_ceildivpow2(brprcxend, 1);
+ brcbgyend = int_ceildivpow2(brprcyend, 1);
+ cbgwidthexpn = pdx - 1;
+ cbgheightexpn = pdy - 1;
+ }
+
+ cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+ cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ int x0b, y0b, i;
+ int gain, numbps;
+ opj_stepsize_t *ss = NULL;
+
+ opj_tcd_band_t *band = &res->bands[bandno];
+
+ band->bandno = resno == 0 ? 0 : bandno + 1;
+ x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+ y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+
+ if (band->bandno == 0) {
+ /* band border (global) */
+ band->x0 = int_ceildivpow2(tilec->x0, levelno);
+ band->y0 = int_ceildivpow2(tilec->y0, levelno);
+ band->x1 = int_ceildivpow2(tilec->x1, levelno);
+ band->y1 = int_ceildivpow2(tilec->y1, levelno);
+ } else {
+ /* band border (global) */
+ band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+ band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+ band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+ band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+ }
+
+ ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+ gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);
+ numbps = image->comps[compno].prec + gain;
+
+ band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn));
+ band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */
+
+ band->precincts = (opj_tcd_precinct_t *) opj_malloc(3 * res->pw * res->ph * sizeof(opj_tcd_precinct_t));
+
+ for (i = 0; i < res->pw * res->ph * 3; i++) {
+ band->precincts[i].imsbtree = NULL;
+ band->precincts[i].incltree = NULL;
+ }
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+
+ int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+ int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+ int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+ int cbgyend = cbgystart + (1 << cbgheightexpn);
+
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ /* precinct size (global) */
+ prc->x0 = int_max(cbgxstart, band->x0);
+ prc->y0 = int_max(cbgystart, band->y0);
+ prc->x1 = int_min(cbgxend, band->x1);
+ prc->y1 = int_min(cbgyend, band->y1);
+
+ tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+ tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+ brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+ brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+ prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+ prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+
+ prc->cblks.enc = (opj_tcd_cblk_enc_t*) opj_calloc((prc->cw * prc->ch), sizeof(opj_tcd_cblk_enc_t));
+ prc->incltree = tgt_create(prc->cw, prc->ch);
+ prc->imsbtree = tgt_create(prc->cw, prc->ch);
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+ int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+ int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+ int cblkyend = cblkystart + (1 << cblkheightexpn);
+
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+
+ /* code-block size (global) */
+ cblk->x0 = int_max(cblkxstart, prc->x0);
+ cblk->y0 = int_max(cblkystart, prc->y0);
+ cblk->x1 = int_min(cblkxend, prc->x1);
+ cblk->y1 = int_min(cblkyend, prc->y1);
+ cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
+ /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
+ cblk->data += 2;
+ cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
+ cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+}
+
+void tcd_free_encode(opj_tcd_t *tcd) {
+ int tileno, compno, resno, bandno, precno, cblkno;
+
+ for (tileno = 0; tileno < 1; tileno++) {
+ opj_tcd_tile_t *tile = tcd->tcd_image->tiles;
+
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ if (prc->incltree != NULL) {
+ tgt_destroy(prc->incltree);
+ prc->incltree = NULL;
+ }
+ if (prc->imsbtree != NULL) {
+ tgt_destroy(prc->imsbtree);
+ prc->imsbtree = NULL;
+ }
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_free(prc->cblks.enc[cblkno].data - 2);
+ opj_free(prc->cblks.enc[cblkno].layers);
+ opj_free(prc->cblks.enc[cblkno].passes);
+ }
+ opj_free(prc->cblks.enc);
+ } /* for (precno */
+ opj_free(band->precincts);
+ band->precincts = NULL;
+ } /* for (bandno */
+ } /* for (resno */
+ opj_free(tilec->resolutions);
+ tilec->resolutions = NULL;
+ } /* for (compno */
+ opj_free(tile->comps);
+ tile->comps = NULL;
+ } /* for (tileno */
+ opj_free(tcd->tcd_image->tiles);
+ tcd->tcd_image->tiles = NULL;
+}
+
+void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno) {
+ int tileno, compno, resno, bandno, precno, cblkno;
+
+ for (tileno = 0; tileno < 1; tileno++) {
+ opj_tcp_t *tcp = &cp->tcps[curtileno];
+ int j;
+ /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+ int p = curtileno % cp->tw;
+ int q = curtileno / cp->tw;
+
+ opj_tcd_tile_t *tile = tcd->tcd_image->tiles;
+
+ /* 4 borders of the tile rescale on the image if necessary */
+ tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+
+ tile->numcomps = image->numcomps;
+ /* tile->PPT=image->PPT; */
+
+ /* Modification of the RATE >> */
+ for (j = 0; j < tcp->numlayers; j++) {
+ tcp->rates[j] = tcp->rates[j] ?
+ cp->tp_on ?
+ (((float) (tile->numcomps
+ * (tile->x1 - tile->x0)
+ * (tile->y1 - tile->y0)
+ * image->comps[0].prec))
+ /(tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)) - (((tcd->cur_totnum_tp - 1) * 14 )/ tcp->numlayers)
+ :
+ ((float) (tile->numcomps
+ * (tile->x1 - tile->x0)
+ * (tile->y1 - tile->y0)
+ * image->comps[0].prec))/
+ (tcp->rates[j] * 8 * image->comps[0].dx * image->comps[0].dy)
+ : 0;
+
+ if (tcp->rates[j]) {
+ if (j && tcp->rates[j] < tcp->rates[j - 1] + 10) {
+ tcp->rates[j] = tcp->rates[j - 1] + 20;
+ } else {
+ if (!j && tcp->rates[j] < 30)
+ tcp->rates[j] = 30;
+ }
+ }
+ }
+ /* << Modification of the RATE */
+
+ /* tile->comps=(opj_tcd_tilecomp_t*)opj_realloc(tile->comps,image->numcomps*sizeof(opj_tcd_tilecomp_t)); */
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+ /* border of each tile component (global) */
+ tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+ tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+ tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+ tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+
+ tilec->data = (int *) opj_aligned_malloc((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0) * sizeof(int));
+ tilec->numresolutions = tccp->numresolutions;
+ /* tilec->resolutions=(opj_tcd_resolution_t*)opj_realloc(tilec->resolutions,tilec->numresolutions*sizeof(opj_tcd_resolution_t)); */
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ int pdx, pdy;
+
+ int levelno = tilec->numresolutions - 1 - resno;
+ int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+ int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+ int cbgwidthexpn, cbgheightexpn;
+ int cblkwidthexpn, cblkheightexpn;
+
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ /* border for each resolution level (global) */
+ res->x0 = int_ceildivpow2(tilec->x0, levelno);
+ res->y0 = int_ceildivpow2(tilec->y0, levelno);
+ res->x1 = int_ceildivpow2(tilec->x1, levelno);
+ res->y1 = int_ceildivpow2(tilec->y1, levelno);
+ res->numbands = resno == 0 ? 1 : 3;
+
+ /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ pdx = tccp->prcw[resno];
+ pdy = tccp->prch[resno];
+ } else {
+ pdx = 15;
+ pdy = 15;
+ }
+ /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+ tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+ brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+ brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+
+ res->pw = (brprcxend - tlprcxstart) >> pdx;
+ res->ph = (brprcyend - tlprcystart) >> pdy;
+
+ if (resno == 0) {
+ tlcbgxstart = tlprcxstart;
+ tlcbgystart = tlprcystart;
+ brcbgxend = brprcxend;
+ brcbgyend = brprcyend;
+ cbgwidthexpn = pdx;
+ cbgheightexpn = pdy;
+ } else {
+ tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+ tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+ brcbgxend = int_ceildivpow2(brprcxend, 1);
+ brcbgyend = int_ceildivpow2(brprcyend, 1);
+ cbgwidthexpn = pdx - 1;
+ cbgheightexpn = pdy - 1;
+ }
+
+ cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+ cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ int x0b, y0b;
+ int gain, numbps;
+ opj_stepsize_t *ss = NULL;
+
+ opj_tcd_band_t *band = &res->bands[bandno];
+
+ band->bandno = resno == 0 ? 0 : bandno + 1;
+ x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+ y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+
+ if (band->bandno == 0) {
+ /* band border */
+ band->x0 = int_ceildivpow2(tilec->x0, levelno);
+ band->y0 = int_ceildivpow2(tilec->y0, levelno);
+ band->x1 = int_ceildivpow2(tilec->x1, levelno);
+ band->y1 = int_ceildivpow2(tilec->y1, levelno);
+ } else {
+ band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+ band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+ band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+ band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+ }
+
+ ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+ gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);
+ numbps = image->comps[compno].prec + gain;
+ band->stepsize = (float)((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn));
+ band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+
+ int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+ int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+ int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+ int cbgyend = cbgystart + (1 << cbgheightexpn);
+
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ /* precinct size (global) */
+ prc->x0 = int_max(cbgxstart, band->x0);
+ prc->y0 = int_max(cbgystart, band->y0);
+ prc->x1 = int_min(cbgxend, band->x1);
+ prc->y1 = int_min(cbgyend, band->y1);
+
+ tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+ tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+ brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+ brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+ prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+ prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+
+ opj_free(prc->cblks.enc);
+ prc->cblks.enc = (opj_tcd_cblk_enc_t*) opj_calloc(prc->cw * prc->ch, sizeof(opj_tcd_cblk_enc_t));
+
+ if (prc->incltree != NULL) {
+ tgt_destroy(prc->incltree);
+ }
+ if (prc->imsbtree != NULL) {
+ tgt_destroy(prc->imsbtree);
+ }
+
+ prc->incltree = tgt_create(prc->cw, prc->ch);
+ prc->imsbtree = tgt_create(prc->cw, prc->ch);
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+ int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+ int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+ int cblkyend = cblkystart + (1 << cblkheightexpn);
+
+ opj_tcd_cblk_enc_t* cblk = &prc->cblks.enc[cblkno];
+
+ /* code-block size (global) */
+ cblk->x0 = int_max(cblkxstart, prc->x0);
+ cblk->y0 = int_max(cblkystart, prc->y0);
+ cblk->x1 = int_min(cblkxend, prc->x1);
+ cblk->y1 = int_min(cblkyend, prc->y1);
+ cblk->data = (unsigned char*) opj_calloc(8192+2, sizeof(unsigned char));
+ /* FIXME: mqc_init_enc and mqc_byteout underrun the buffer if we don't do this. Why? */
+ cblk->data += 2;
+ cblk->layers = (opj_tcd_layer_t*) opj_calloc(100, sizeof(opj_tcd_layer_t));
+ cblk->passes = (opj_tcd_pass_t*) opj_calloc(100, sizeof(opj_tcd_pass_t));
+ }
+ } /* precno */
+ } /* bandno */
+ } /* resno */
+ } /* compno */
+ } /* tileno */
+
+ /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+}
+
+void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
+ int i, j, tileno, p, q;
+ unsigned int x0 = 0, y0 = 0, x1 = 0, y1 = 0, w, h;
+
+ tcd->image = image;
+ tcd->tcd_image->tw = cp->tw;
+ tcd->tcd_image->th = cp->th;
+ tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t));
+
+ /*
+ Allocate place to store the decoded data = final image
+ Place limited by the tile really present in the codestream
+ */
+
+ for (j = 0; j < cp->tileno_size; j++) {
+ opj_tcd_tile_t *tile;
+
+ tileno = cp->tileno[j];
+ tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]);
+ tile->numcomps = image->numcomps;
+ tile->comps = (opj_tcd_tilecomp_t*) opj_calloc(image->numcomps, sizeof(opj_tcd_tilecomp_t));
+ }
+
+ for (i = 0; i < image->numcomps; i++) {
+ for (j = 0; j < cp->tileno_size; j++) {
+ opj_tcd_tile_t *tile;
+ opj_tcd_tilecomp_t *tilec;
+
+ /* cfr p59 ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+
+ tileno = cp->tileno[j];
+
+ tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]);
+ tilec = &tile->comps[i];
+
+ p = tileno % cp->tw; /* si numerotation matricielle .. */
+ q = tileno / cp->tw; /* .. coordonnees de la tile (q,p) q pour ligne et p pour colonne */
+
+ /* 4 borders of the tile rescale on the image if necessary */
+ tile->x0 = int_max(cp->tx0 + p * cp->tdx, image->x0);
+ tile->y0 = int_max(cp->ty0 + q * cp->tdy, image->y0);
+ tile->x1 = int_min(cp->tx0 + (p + 1) * cp->tdx, image->x1);
+ tile->y1 = int_min(cp->ty0 + (q + 1) * cp->tdy, image->y1);
+
+ tilec->x0 = int_ceildiv(tile->x0, image->comps[i].dx);
+ tilec->y0 = int_ceildiv(tile->y0, image->comps[i].dy);
+ tilec->x1 = int_ceildiv(tile->x1, image->comps[i].dx);
+ tilec->y1 = int_ceildiv(tile->y1, image->comps[i].dy);
+
+ x0 = j == 0 ? tilec->x0 : int_min(x0, (unsigned int) tilec->x0);
+ y0 = j == 0 ? tilec->y0 : int_min(y0, (unsigned int) tilec->x0);
+ x1 = j == 0 ? tilec->x1 : int_max(x1, (unsigned int) tilec->x1);
+ y1 = j == 0 ? tilec->y1 : int_max(y1, (unsigned int) tilec->y1);
+ }
+
+ w = int_ceildivpow2(x1 - x0, image->comps[i].factor);
+ h = int_ceildivpow2(y1 - y0, image->comps[i].factor);
+
+ image->comps[i].w = w;
+ image->comps[i].h = h;
+ image->comps[i].x0 = x0;
+ image->comps[i].y0 = y0;
+ }
+}
+
+void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int tileno, opj_codestream_info_t *cstr_info) {
+ int compno, resno, bandno, precno, cblkno;
+ opj_tcp_t *tcp;
+ opj_tcd_tile_t *tile;
+
+ tcd->cp = cp;
+
+ tcp = &(cp->tcps[cp->tileno[tileno]]);
+ tile = &(tcd->tcd_image->tiles[cp->tileno[tileno]]);
+
+ tileno = cp->tileno[tileno];
+
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+
+ /* border of each tile component (global) */
+ tilec->x0 = int_ceildiv(tile->x0, image->comps[compno].dx);
+ tilec->y0 = int_ceildiv(tile->y0, image->comps[compno].dy);
+ tilec->x1 = int_ceildiv(tile->x1, image->comps[compno].dx);
+ tilec->y1 = int_ceildiv(tile->y1, image->comps[compno].dy);
+
+ tilec->numresolutions = tccp->numresolutions;
+ tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(tilec->numresolutions * sizeof(opj_tcd_resolution_t));
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ int pdx, pdy;
+ int levelno = tilec->numresolutions - 1 - resno;
+ int tlprcxstart, tlprcystart, brprcxend, brprcyend;
+ int tlcbgxstart, tlcbgystart, brcbgxend, brcbgyend;
+ int cbgwidthexpn, cbgheightexpn;
+ int cblkwidthexpn, cblkheightexpn;
+
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ /* border for each resolution level (global) */
+ res->x0 = int_ceildivpow2(tilec->x0, levelno);
+ res->y0 = int_ceildivpow2(tilec->y0, levelno);
+ res->x1 = int_ceildivpow2(tilec->x1, levelno);
+ res->y1 = int_ceildivpow2(tilec->y1, levelno);
+ res->numbands = resno == 0 ? 1 : 3;
+
+ /* p. 35, table A-23, ISO/IEC FDIS154444-1 : 2000 (18 august 2000) */
+ if (tccp->csty & J2K_CCP_CSTY_PRT) {
+ pdx = tccp->prcw[resno];
+ pdy = tccp->prch[resno];
+ } else {
+ pdx = 15;
+ pdy = 15;
+ }
+
+ /* p. 64, B.6, ISO/IEC FDIS15444-1 : 2000 (18 august 2000) */
+ tlprcxstart = int_floordivpow2(res->x0, pdx) << pdx;
+ tlprcystart = int_floordivpow2(res->y0, pdy) << pdy;
+ brprcxend = int_ceildivpow2(res->x1, pdx) << pdx;
+ brprcyend = int_ceildivpow2(res->y1, pdy) << pdy;
+
+ res->pw = (res->x0 == res->x1) ? 0 : ((brprcxend - tlprcxstart) >> pdx);
+ res->ph = (res->y0 == res->y1) ? 0 : ((brprcyend - tlprcystart) >> pdy);
+
+ if (resno == 0) {
+ tlcbgxstart = tlprcxstart;
+ tlcbgystart = tlprcystart;
+ brcbgxend = brprcxend;
+ brcbgyend = brprcyend;
+ cbgwidthexpn = pdx;
+ cbgheightexpn = pdy;
+ } else {
+ tlcbgxstart = int_ceildivpow2(tlprcxstart, 1);
+ tlcbgystart = int_ceildivpow2(tlprcystart, 1);
+ brcbgxend = int_ceildivpow2(brprcxend, 1);
+ brcbgyend = int_ceildivpow2(brprcyend, 1);
+ cbgwidthexpn = pdx - 1;
+ cbgheightexpn = pdy - 1;
+ }
+
+ cblkwidthexpn = int_min(tccp->cblkw, cbgwidthexpn);
+ cblkheightexpn = int_min(tccp->cblkh, cbgheightexpn);
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ int x0b, y0b;
+ int gain, numbps;
+ opj_stepsize_t *ss = NULL;
+
+ opj_tcd_band_t *band = &res->bands[bandno];
+ band->bandno = resno == 0 ? 0 : bandno + 1;
+ x0b = (band->bandno == 1) || (band->bandno == 3) ? 1 : 0;
+ y0b = (band->bandno == 2) || (band->bandno == 3) ? 1 : 0;
+
+ if (band->bandno == 0) {
+ /* band border (global) */
+ band->x0 = int_ceildivpow2(tilec->x0, levelno);
+ band->y0 = int_ceildivpow2(tilec->y0, levelno);
+ band->x1 = int_ceildivpow2(tilec->x1, levelno);
+ band->y1 = int_ceildivpow2(tilec->y1, levelno);
+ } else {
+ /* band border (global) */
+ band->x0 = int_ceildivpow2(tilec->x0 - (1 << levelno) * x0b, levelno + 1);
+ band->y0 = int_ceildivpow2(tilec->y0 - (1 << levelno) * y0b, levelno + 1);
+ band->x1 = int_ceildivpow2(tilec->x1 - (1 << levelno) * x0b, levelno + 1);
+ band->y1 = int_ceildivpow2(tilec->y1 - (1 << levelno) * y0b, levelno + 1);
+ }
+
+ ss = &tccp->stepsizes[resno == 0 ? 0 : 3 * (resno - 1) + bandno + 1];
+ gain = tccp->qmfbid == 0 ? dwt_getgain_real(band->bandno) : dwt_getgain(band->bandno);
+ numbps = image->comps[compno].prec + gain;
+ band->stepsize = (float)(((1.0 + ss->mant / 2048.0) * pow(2.0, numbps - ss->expn)) * 0.5);
+ band->numbps = ss->expn + tccp->numgbits - 1; /* WHY -1 ? */
+
+ band->precincts = (opj_tcd_precinct_t *) opj_malloc(res->pw * res->ph * sizeof(opj_tcd_precinct_t));
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ int tlcblkxstart, tlcblkystart, brcblkxend, brcblkyend;
+ int cbgxstart = tlcbgxstart + (precno % res->pw) * (1 << cbgwidthexpn);
+ int cbgystart = tlcbgystart + (precno / res->pw) * (1 << cbgheightexpn);
+ int cbgxend = cbgxstart + (1 << cbgwidthexpn);
+ int cbgyend = cbgystart + (1 << cbgheightexpn);
+
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ /* precinct size (global) */
+ prc->x0 = int_max(cbgxstart, band->x0);
+ prc->y0 = int_max(cbgystart, band->y0);
+ prc->x1 = int_min(cbgxend, band->x1);
+ prc->y1 = int_min(cbgyend, band->y1);
+
+ tlcblkxstart = int_floordivpow2(prc->x0, cblkwidthexpn) << cblkwidthexpn;
+ tlcblkystart = int_floordivpow2(prc->y0, cblkheightexpn) << cblkheightexpn;
+ brcblkxend = int_ceildivpow2(prc->x1, cblkwidthexpn) << cblkwidthexpn;
+ brcblkyend = int_ceildivpow2(prc->y1, cblkheightexpn) << cblkheightexpn;
+ prc->cw = (brcblkxend - tlcblkxstart) >> cblkwidthexpn;
+ prc->ch = (brcblkyend - tlcblkystart) >> cblkheightexpn;
+
+ prc->cblks.dec = (opj_tcd_cblk_dec_t*) opj_malloc(prc->cw * prc->ch * sizeof(opj_tcd_cblk_dec_t));
+
+ prc->incltree = tgt_create(prc->cw, prc->ch);
+ prc->imsbtree = tgt_create(prc->cw, prc->ch);
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ int cblkxstart = tlcblkxstart + (cblkno % prc->cw) * (1 << cblkwidthexpn);
+ int cblkystart = tlcblkystart + (cblkno / prc->cw) * (1 << cblkheightexpn);
+ int cblkxend = cblkxstart + (1 << cblkwidthexpn);
+ int cblkyend = cblkystart + (1 << cblkheightexpn);
+
+ opj_tcd_cblk_dec_t* cblk = &prc->cblks.dec[cblkno];
+ cblk->data = NULL;
+ cblk->segs = NULL;
+ /* code-block size (global) */
+ cblk->x0 = int_max(cblkxstart, prc->x0);
+ cblk->y0 = int_max(cblkystart, prc->y0);
+ cblk->x1 = int_min(cblkxend, prc->x1);
+ cblk->y1 = int_min(cblkyend, prc->y1);
+ cblk->numsegs = 0;
+ }
+ } /* precno */
+ } /* bandno */
+ } /* resno */
+ } /* compno */
+ /* tcd_dump(stdout, tcd, &tcd->tcd_image); */
+}
+
+void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final) {
+ int compno, resno, bandno, precno, cblkno;
+ int value; /*, matrice[tcd_tcp->numlayers][tcd_tile->comps[0].numresolutions][3]; */
+ int matrice[10][10][3];
+ int i, j, k;
+
+ opj_cp_t *cp = tcd->cp;
+ opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+ opj_tcp_t *tcd_tcp = tcd->tcp;
+
+ /*matrice=(int*)opj_malloc(tcd_tcp->numlayers*tcd_tile->comps[0].numresolutions*3*sizeof(int)); */
+
+ for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+ for (i = 0; i < tcd_tcp->numlayers; i++) {
+ for (j = 0; j < tilec->numresolutions; j++) {
+ for (k = 0; k < 3; k++) {
+ matrice[i][j][k] =
+ (int) (cp->matrice[i * tilec->numresolutions * 3 + j * 3 + k]
+ * (float) (tcd->image->comps[compno].prec / 16.0));
+ }
+ }
+ }
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno];
+ opj_tcd_layer_t *layer = &cblk->layers[layno];
+ int n;
+ int imsb = tcd->image->comps[compno].prec - cblk->numbps; /* number of bit-plan equal to zero */
+ /* Correction of the matrix of coefficient to include the IMSB information */
+ if (layno == 0) {
+ value = matrice[layno][resno][bandno];
+ if (imsb >= value) {
+ value = 0;
+ } else {
+ value -= imsb;
+ }
+ } else {
+ value = matrice[layno][resno][bandno] - matrice[layno - 1][resno][bandno];
+ if (imsb >= matrice[layno - 1][resno][bandno]) {
+ value -= (imsb - matrice[layno - 1][resno][bandno]);
+ if (value < 0) {
+ value = 0;
+ }
+ }
+ }
+
+ if (layno == 0) {
+ cblk->numpassesinlayers = 0;
+ }
+
+ n = cblk->numpassesinlayers;
+ if (cblk->numpassesinlayers == 0) {
+ if (value != 0) {
+ n = 3 * value - 2 + cblk->numpassesinlayers;
+ } else {
+ n = cblk->numpassesinlayers;
+ }
+ } else {
+ n = 3 * value + cblk->numpassesinlayers;
+ }
+
+ layer->numpasses = n - cblk->numpassesinlayers;
+
+ if (!layer->numpasses)
+ continue;
+
+ if (cblk->numpassesinlayers == 0) {
+ layer->len = cblk->passes[n - 1].rate;
+ layer->data = cblk->data;
+ } else {
+ layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate;
+ layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+ }
+ if (final)
+ cblk->numpassesinlayers = n;
+ }
+ }
+ }
+ }
+ }
+}
+
+void tcd_rateallocate_fixed(opj_tcd_t *tcd) {
+ int layno;
+ for (layno = 0; layno < tcd->tcp->numlayers; layno++) {
+ tcd_makelayer_fixed(tcd, layno, 1);
+ }
+}
+
+void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final) {
+ int compno, resno, bandno, precno, cblkno, passno;
+
+ opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+
+ tcd_tile->distolayer[layno] = 0; /* fixed_quality */
+
+ for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno];
+ opj_tcd_layer_t *layer = &cblk->layers[layno];
+
+ int n;
+ if (layno == 0) {
+ cblk->numpassesinlayers = 0;
+ }
+ n = cblk->numpassesinlayers;
+ for (passno = cblk->numpassesinlayers; passno < cblk->totalpasses; passno++) {
+ int dr;
+ double dd;
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ if (n == 0) {
+ dr = pass->rate;
+ dd = pass->distortiondec;
+ } else {
+ dr = pass->rate - cblk->passes[n - 1].rate;
+ dd = pass->distortiondec - cblk->passes[n - 1].distortiondec;
+ }
+ if (!dr) {
+ if (dd != 0)
+ n = passno + 1;
+ continue;
+ }
+ if (dd / dr >= thresh)
+ n = passno + 1;
+ }
+ layer->numpasses = n - cblk->numpassesinlayers;
+
+ if (!layer->numpasses) {
+ layer->disto = 0;
+ continue;
+ }
+ if (cblk->numpassesinlayers == 0) {
+ layer->len = cblk->passes[n - 1].rate;
+ layer->data = cblk->data;
+ layer->disto = cblk->passes[n - 1].distortiondec;
+ } else {
+ layer->len = cblk->passes[n - 1].rate - cblk->passes[cblk->numpassesinlayers - 1].rate;
+ layer->data = cblk->data + cblk->passes[cblk->numpassesinlayers - 1].rate;
+ layer->disto = cblk->passes[n - 1].distortiondec - cblk->passes[cblk->numpassesinlayers - 1].distortiondec;
+ }
+
+ tcd_tile->distolayer[layno] += layer->disto; /* fixed_quality */
+
+ if (final)
+ cblk->numpassesinlayers = n;
+ }
+ }
+ }
+ }
+ }
+}
+
+bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
+ int compno, resno, bandno, precno, cblkno, passno, layno;
+ double min, max;
+ double cumdisto[100]; /* fixed_quality */
+ const double K = 1; /* 1.1; fixed_quality */
+ double maxSE = 0;
+
+ opj_cp_t *cp = tcd->cp;
+ opj_tcd_tile_t *tcd_tile = tcd->tcd_tile;
+ opj_tcp_t *tcd_tcp = tcd->tcp;
+
+ min = DBL_MAX;
+ max = 0;
+
+ tcd_tile->numpix = 0; /* fixed_quality */
+
+ for (compno = 0; compno < tcd_tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tcd_tile->comps[compno];
+ tilec->numpix = 0;
+
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+
+ for (precno = 0; precno < res->pw * res->ph; precno++) {
+ opj_tcd_precinct_t *prc = &band->precincts[precno];
+
+ for (cblkno = 0; cblkno < prc->cw * prc->ch; cblkno++) {
+ opj_tcd_cblk_enc_t *cblk = &prc->cblks.enc[cblkno];
+
+ for (passno = 0; passno < cblk->totalpasses; passno++) {
+ opj_tcd_pass_t *pass = &cblk->passes[passno];
+ int dr;
+ double dd, rdslope;
+ if (passno == 0) {
+ dr = pass->rate;
+ dd = pass->distortiondec;
+ } else {
+ dr = pass->rate - cblk->passes[passno - 1].rate;
+ dd = pass->distortiondec - cblk->passes[passno - 1].distortiondec;
+ }
+ if (dr == 0) {
+ continue;
+ }
+ rdslope = dd / dr;
+ if (rdslope < min) {
+ min = rdslope;
+ }
+ if (rdslope > max) {
+ max = rdslope;
+ }
+ } /* passno */
+
+ /* fixed_quality */
+ tcd_tile->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+ tilec->numpix += ((cblk->x1 - cblk->x0) * (cblk->y1 - cblk->y0));
+ } /* cbklno */
+ } /* precno */
+ } /* bandno */
+ } /* resno */
+
+ maxSE += (((double)(1 << tcd->image->comps[compno].prec) - 1.0)
+ * ((double)(1 << tcd->image->comps[compno].prec) -1.0))
+ * ((double)(tilec->numpix));
+ } /* compno */
+
+ /* index file */
+ if(cstr_info) {
+ opj_tile_info_t *tile_info = &cstr_info->tile[tcd->tcd_tileno];
+ tile_info->numpix = tcd_tile->numpix;
+ tile_info->distotile = tcd_tile->distotile;
+ tile_info->thresh = (double *) opj_malloc(tcd_tcp->numlayers * sizeof(double));
+ }
+
+ for (layno = 0; layno < tcd_tcp->numlayers; layno++) {
+ double lo = min;
+ double hi = max;
+ int success = 0;
+ int maxlen = tcd_tcp->rates[layno] ? int_min(((int) ceil(tcd_tcp->rates[layno])), len) : len;
+ double goodthresh = 0;
+ double stable_thresh = 0;
+ int i;
+ double distotarget; /* fixed_quality */
+
+ /* fixed_quality */
+ distotarget = tcd_tile->distotile - ((K * maxSE) / pow((float)10, tcd_tcp->distoratio[layno] / 10));
+
+ /* Don't try to find an optimal threshold but rather take everything not included yet, if
+ -r xx,yy,zz,0 (disto_alloc == 1 and rates == 0)
+ -q xx,yy,zz,0 (fixed_quality == 1 and distoratio == 0)
+ ==> possible to have some lossy layers and the last layer for sure lossless */
+ if ( ((cp->disto_alloc==1) && (tcd_tcp->rates[layno]>0)) || ((cp->fixed_quality==1) && (tcd_tcp->distoratio[layno]>0))) {
+ opj_t2_t *t2 = t2_create(tcd->cinfo, tcd->image, cp);
+ double thresh = 0;
+
+ for (i = 0; i < 128; i++) {
+ int l = 0;
+ double distoachieved = 0; /* fixed_quality */
+ thresh = (lo + hi) / 2;
+
+ tcd_makelayer(tcd, layno, thresh, 0);
+
+ if (cp->fixed_quality) { /* fixed_quality */
+ if(cp->cinema){
+ l = t2_encode_packets(t2,tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC, tcd->cur_totnum_tp);
+ if (l == -999) {
+ lo = thresh;
+ continue;
+ }else{
+ distoachieved = layno == 0 ?
+ tcd_tile->distolayer[0] : cumdisto[layno - 1] + tcd_tile->distolayer[layno];
+ if (distoachieved < distotarget) {
+ hi=thresh;
+ stable_thresh = thresh;
+ continue;
+ }else{
+ lo=thresh;
+ }
+ }
+ }else{
+ distoachieved = (layno == 0) ?
+ tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
+ if (distoachieved < distotarget) {
+ hi = thresh;
+ stable_thresh = thresh;
+ continue;
+ }
+ lo = thresh;
+ }
+ } else {
+ l = t2_encode_packets(t2, tcd->tcd_tileno, tcd_tile, layno + 1, dest, maxlen, cstr_info,tcd->cur_tp_num,tcd->tp_pos,tcd->cur_pino,THRESH_CALC, tcd->cur_totnum_tp);
+ /* TODO: what to do with l ??? seek / tell ??? */
+ /* opj_event_msg(tcd->cinfo, EVT_INFO, "rate alloc: len=%d, max=%d\n", l, maxlen); */
+ if (l == -999) {
+ lo = thresh;
+ continue;
+ }
+ hi = thresh;
+ stable_thresh = thresh;
+ }
+ }
+ success = 1;
+ goodthresh = stable_thresh == 0? thresh : stable_thresh;
+ t2_destroy(t2);
+ } else {
+ success = 1;
+ goodthresh = min;
+ }
+
+ if (!success) {
+ return false;
+ }
+
+ if(cstr_info) { /* Threshold for Marcela Index */
+ cstr_info->tile[tcd->tcd_tileno].thresh[layno] = goodthresh;
+ }
+ tcd_makelayer(tcd, layno, goodthresh, 1);
+
+ /* fixed_quality */
+ cumdisto[layno] = (layno == 0) ? tcd_tile->distolayer[0] : (cumdisto[layno - 1] + tcd_tile->distolayer[layno]);
+ }
+
+ return true;
+}
+
+int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info) {
+ int compno;
+ int l, i, numpacks = 0;
+ opj_tcd_tile_t *tile = NULL;
+ opj_tcp_t *tcd_tcp = NULL;
+ opj_cp_t *cp = NULL;
+
+ opj_tcp_t *tcp = &tcd->cp->tcps[0];
+ opj_tccp_t *tccp = &tcp->tccps[0];
+ opj_image_t *image = tcd->image;
+
+ opj_t1_t *t1 = NULL; /* T1 component */
+ opj_t2_t *t2 = NULL; /* T2 component */
+
+ tcd->tcd_tileno = tileno;
+ tcd->tcd_tile = tcd->tcd_image->tiles;
+ tcd->tcp = &tcd->cp->tcps[tileno];
+
+ tile = tcd->tcd_tile;
+ tcd_tcp = tcd->tcp;
+ cp = tcd->cp;
+
+ if(tcd->cur_tp_num == 0){
+ tcd->encoding_time = opj_clock(); /* time needed to encode a tile */
+ /* INDEX >> "Precinct_nb_X et Precinct_nb_Y" */
+ if(cstr_info) {
+ opj_tcd_tilecomp_t *tilec_idx = &tile->comps[0]; /* based on component 0 */
+ for (i = 0; i < tilec_idx->numresolutions; i++) {
+ opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[i];
+
+ cstr_info->tile[tileno].pw[i] = res_idx->pw;
+ cstr_info->tile[tileno].ph[i] = res_idx->ph;
+
+ numpacks += res_idx->pw * res_idx->ph;
+
+ cstr_info->tile[tileno].pdx[i] = tccp->prcw[i];
+ cstr_info->tile[tileno].pdy[i] = tccp->prch[i];
+ }
+ cstr_info->tile[tileno].packet = (opj_packet_info_t*) opj_calloc(cstr_info->numcomps * cstr_info->numlayers * numpacks, sizeof(opj_packet_info_t));
+ }
+ /* << INDEX */
+
+ /*---------------TILE-------------------*/
+
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ int x, y;
+
+ int adjust = image->comps[compno].sgnd ? 0 : 1 << (image->comps[compno].prec - 1);
+ int offset_x = int_ceildiv(image->x0, image->comps[compno].dx);
+ int offset_y = int_ceildiv(image->y0, image->comps[compno].dy);
+
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ int tw = tilec->x1 - tilec->x0;
+ int w = int_ceildiv(image->x1 - image->x0, image->comps[compno].dx);
+
+ /* extract tile data */
+
+ if (tcd_tcp->tccps[compno].qmfbid == 1) {
+ for (y = tilec->y0; y < tilec->y1; y++) {
+ /* start of the src tile scanline */
+ int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+ /* start of the dst tile scanline */
+ int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+ for (x = tilec->x0; x < tilec->x1; x++) {
+ *tile_data++ = *data++ - adjust;
+ }
+ }
+ } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
+ for (y = tilec->y0; y < tilec->y1; y++) {
+ /* start of the src tile scanline */
+ int *data = &image->comps[compno].data[(tilec->x0 - offset_x) + (y - offset_y) * w];
+ /* start of the dst tile scanline */
+ int *tile_data = &tilec->data[(y - tilec->y0) * tw];
+ for (x = tilec->x0; x < tilec->x1; x++) {
+ *tile_data++ = (*data++ - adjust) << 11;
+ }
+
+ }
+ }
+ }
+
+ /*----------------MCT-------------------*/
+ if (tcd_tcp->mct) {
+ int samples = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
+ if (tcd_tcp->tccps[0].qmfbid == 0) {
+ mct_encode_real(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+ } else {
+ mct_encode(tile->comps[0].data, tile->comps[1].data, tile->comps[2].data, samples);
+ }
+ }
+
+ /*----------------DWT---------------------*/
+
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ if (tcd_tcp->tccps[compno].qmfbid == 1) {
+ dwt_encode(tilec);
+ } else if (tcd_tcp->tccps[compno].qmfbid == 0) {
+ dwt_encode_real(tilec);
+ }
+ }
+
+ /*------------------TIER1-----------------*/
+ t1 = t1_create(tcd->cinfo);
+ t1_encode_cblks(t1, tile, tcd_tcp);
+ t1_destroy(t1);
+
+ /*-----------RATE-ALLOCATE------------------*/
+
+ /* INDEX */
+ if(cstr_info) {
+ cstr_info->index_write = 0;
+ }
+ if (cp->disto_alloc || cp->fixed_quality) { /* fixed_quality */
+ /* Normal Rate/distortion allocation */
+ tcd_rateallocate(tcd, dest, len, cstr_info);
+ } else {
+ /* Fixed layer allocation */
+ tcd_rateallocate_fixed(tcd);
+ }
+ }
+ /*--------------TIER2------------------*/
+
+ /* INDEX */
+ if(cstr_info) {
+ cstr_info->index_write = 1;
+ }
+
+ t2 = t2_create(tcd->cinfo, image, cp);
+ l = t2_encode_packets(t2,tileno, tile, tcd_tcp->numlayers, dest, len, cstr_info,tcd->tp_num,tcd->tp_pos,tcd->cur_pino,FINAL_PASS,tcd->cur_totnum_tp);
+ t2_destroy(t2);
+
+ /*---------------CLEAN-------------------*/
+
+
+ if(tcd->cur_tp_num == tcd->cur_totnum_tp - 1){
+ tcd->encoding_time = opj_clock() - tcd->encoding_time;
+ opj_event_msg(tcd->cinfo, EVT_INFO, "- tile encoded in %f s\n", tcd->encoding_time);
+
+ /* cleaning memory */
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ opj_aligned_free(tilec->data);
+ }
+ }
+
+ return l;
+}
+
+bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info) {
+ int l;
+ int compno;
+ int eof = 0;
+ double tile_time, t1_time, dwt_time;
+ opj_tcd_tile_t *tile = NULL;
+
+ opj_t1_t *t1 = NULL; /* T1 component */
+ opj_t2_t *t2 = NULL; /* T2 component */
+
+ tcd->tcd_tileno = tileno;
+ tcd->tcd_tile = &(tcd->tcd_image->tiles[tileno]);
+ tcd->tcp = &(tcd->cp->tcps[tileno]);
+ tile = tcd->tcd_tile;
+
+ tile_time = opj_clock(); /* time needed to decode a tile */
+ opj_event_msg(tcd->cinfo, EVT_INFO, "tile %d of %d\n", tileno + 1, tcd->cp->tw * tcd->cp->th);
+
+ /* INDEX >> */
+ if(cstr_info) {
+ int resno, compno, numprec = 0;
+ for (compno = 0; compno < cstr_info->numcomps; compno++) {
+ opj_tcp_t *tcp = &tcd->cp->tcps[0];
+ opj_tccp_t *tccp = &tcp->tccps[compno];
+ opj_tcd_tilecomp_t *tilec_idx = &tile->comps[compno];
+ for (resno = 0; resno < tilec_idx->numresolutions; resno++) {
+ opj_tcd_resolution_t *res_idx = &tilec_idx->resolutions[resno];
+ cstr_info->tile[tileno].pw[resno] = res_idx->pw;
+ cstr_info->tile[tileno].ph[resno] = res_idx->ph;
+ numprec += res_idx->pw * res_idx->ph;
+ if (tccp->csty & J2K_CP_CSTY_PRT) {
+ cstr_info->tile[tileno].pdx[resno] = tccp->prcw[resno];
+ cstr_info->tile[tileno].pdy[resno] = tccp->prch[resno];
+ }
+ else {
+ cstr_info->tile[tileno].pdx[resno] = 15;
+ cstr_info->tile[tileno].pdx[resno] = 15;
+ }
+ }
+ }
+ cstr_info->tile[tileno].packet = (opj_packet_info_t *) opj_malloc(cstr_info->numlayers * numprec * sizeof(opj_packet_info_t));
+ cstr_info->packno = 0;
+ }
+ /* << INDEX */
+
+ /*--------------TIER2------------------*/
+
+ t2 = t2_create(tcd->cinfo, tcd->image, tcd->cp);
+ l = t2_decode_packets(t2, src, len, tileno, tile, cstr_info);
+ t2_destroy(t2);
+
+ if (l == -999) {
+ eof = 1;
+ opj_event_msg(tcd->cinfo, EVT_ERROR, "tcd_decode: incomplete bistream\n");
+ }
+
+ /*------------------TIER1-----------------*/
+
+ t1_time = opj_clock(); /* time needed to decode a tile */
+ t1 = t1_create(tcd->cinfo);
+ for (compno = 0; compno < tile->numcomps; ++compno) {
+ opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
+ /* The +3 is headroom required by the vectorized DWT */
+ tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int));
+ t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]);
+ }
+ t1_destroy(t1);
+ t1_time = opj_clock() - t1_time;
+ opj_event_msg(tcd->cinfo, EVT_INFO, "- tiers-1 took %f s\n", t1_time);
+
+ /*----------------DWT---------------------*/
+
+ dwt_time = opj_clock(); /* time needed to decode a tile */
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ int numres2decode;
+
+ if (tcd->cp->reduce != 0) {
+ tcd->image->comps[compno].resno_decoded =
+ tile->comps[compno].numresolutions - tcd->cp->reduce - 1;
+ if (tcd->image->comps[compno].resno_decoded < 0) {
+ opj_event_msg(tcd->cinfo, EVT_ERROR, "Error decoding tile. The number of resolutions to remove [%d+1] is higher than the number "
+ " of resolutions in the original codestream [%d]\nModify the cp_reduce parameter.\n", tcd->cp->reduce, tile->comps[compno].numresolutions);
+ return false;
+ }
+ }
+
+ numres2decode = tcd->image->comps[compno].resno_decoded + 1;
+ if(numres2decode > 0){
+ if (tcd->tcp->tccps[compno].qmfbid == 1) {
+ dwt_decode(tilec, numres2decode);
+ } else {
+ dwt_decode_real(tilec, numres2decode);
+ }
+ }
+ }
+ dwt_time = opj_clock() - dwt_time;
+ opj_event_msg(tcd->cinfo, EVT_INFO, "- dwt took %f s\n", dwt_time);
+
+ /*----------------MCT-------------------*/
+
+ if (tcd->tcp->mct) {
+ int n = (tile->comps[0].x1 - tile->comps[0].x0) * (tile->comps[0].y1 - tile->comps[0].y0);
+ if (tcd->tcp->tccps[0].qmfbid == 1) {
+ mct_decode(
+ tile->comps[0].data,
+ tile->comps[1].data,
+ tile->comps[2].data,
+ n);
+ } else {
+ mct_decode_real(
+ (float*)tile->comps[0].data,
+ (float*)tile->comps[1].data,
+ (float*)tile->comps[2].data,
+ n);
+ }
+ }
+
+ /*---------------TILE-------------------*/
+
+ for (compno = 0; compno < tile->numcomps; ++compno) {
+ opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
+ opj_image_comp_t* imagec = &tcd->image->comps[compno];
+ opj_tcd_resolution_t* res = &tilec->resolutions[imagec->resno_decoded];
+ int adjust = imagec->sgnd ? 0 : 1 << (imagec->prec - 1);
+ int min = imagec->sgnd ? -(1 << (imagec->prec - 1)) : 0;
+ int max = imagec->sgnd ? (1 << (imagec->prec - 1)) - 1 : (1 << imagec->prec) - 1;
+
+ int tw = tilec->x1 - tilec->x0;
+ int w = imagec->w;
+
+ int offset_x = int_ceildivpow2(imagec->x0, imagec->factor);
+ int offset_y = int_ceildivpow2(imagec->y0, imagec->factor);
+
+ int i, j;
+ if(!imagec->data){
+ imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int));
+ }
+ if(tcd->tcp->tccps[compno].qmfbid == 1) {
+ for(j = res->y0; j < res->y1; ++j) {
+ for(i = res->x0; i < res->x1; ++i) {
+ int v = tilec->data[i - res->x0 + (j - res->y0) * tw];
+ v += adjust;
+ imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max);
+ }
+ }
+ }else{
+ for(j = res->y0; j < res->y1; ++j) {
+ for(i = res->x0; i < res->x1; ++i) {
+ float tmp = ((float*)tilec->data)[i - res->x0 + (j - res->y0) * tw];
+ int v = lrintf(tmp);
+ v += adjust;
+ imagec->data[(i - offset_x) + (j - offset_y) * w] = int_clamp(v, min, max);
+ }
+ }
+ }
+ opj_aligned_free(tilec->data);
+ }
+
+ tile_time = opj_clock() - tile_time; /* time needed to decode a tile */
+ opj_event_msg(tcd->cinfo, EVT_INFO, "- tile decoded in %f s\n", tile_time);
+
+ if (eof) {
+ return false;
+ }
+
+ return true;
+}
+
+void tcd_free_decode(opj_tcd_t *tcd) {
+ opj_tcd_image_t *tcd_image = tcd->tcd_image;
+ opj_free(tcd_image->tiles);
+}
+
+void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) {
+ int compno,resno,bandno,precno;
+
+ opj_tcd_image_t *tcd_image = tcd->tcd_image;
+
+ opj_tcd_tile_t *tile = &tcd_image->tiles[tileno];
+ for (compno = 0; compno < tile->numcomps; compno++) {
+ opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
+ for (resno = 0; resno < tilec->numresolutions; resno++) {
+ opj_tcd_resolution_t *res = &tilec->resolutions[resno];
+ for (bandno = 0; bandno < res->numbands; bandno++) {
+ opj_tcd_band_t *band = &res->bands[bandno];
+ for (precno = 0; precno < res->ph * res->pw; precno++) {
+ opj_tcd_precinct_t *prec = &band->precincts[precno];
+ if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
+ if (prec->incltree != NULL) tgt_destroy(prec->incltree);
+ }
+ opj_free(band->precincts);
+ }
+ }
+ opj_free(tilec->resolutions);
+ }
+ opj_free(tile->comps);
+}
+
+
+
diff --git a/Source/LibOpenJPEG/tcd.h b/Source/LibOpenJPEG/tcd.h
new file mode 100644
index 0000000..f0ac561
--- /dev/null
+++ b/Source/LibOpenJPEG/tcd.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __TCD_H
+#define __TCD_H
+/**
+@file tcd.h
+@brief Implementation of a tile coder/decoder (TCD)
+
+The functions in TCD.C have for goal to encode or decode each tile independently from
+each other. The functions in TCD.C are used by some function in J2K.C.
+*/
+
+/** @defgroup TCD TCD - Implementation of a tile coder/decoder */
+/*@{*/
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_seg {
+ unsigned char** data;
+ int dataindex;
+ int numpasses;
+ int len;
+ int maxpasses;
+ int numnewpasses;
+ int newlen;
+} opj_tcd_seg_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_pass {
+ int rate;
+ double distortiondec;
+ int term, len;
+} opj_tcd_pass_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_layer {
+ int numpasses; /* Number of passes in the layer */
+ int len; /* len of information */
+ double disto; /* add for index (Cfr. Marcela) */
+ unsigned char *data; /* data */
+} opj_tcd_layer_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_cblk_enc {
+ unsigned char* data; /* Data */
+ opj_tcd_layer_t* layers; /* layer information */
+ opj_tcd_pass_t* passes; /* information about the passes */
+ int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numbps;
+ int numlenbits;
+ int numpasses; /* number of pass already done for the code-blocks */
+ int numpassesinlayers; /* number of passes in the layer */
+ int totalpasses; /* total number of passes */
+} opj_tcd_cblk_enc_t;
+
+typedef struct opj_tcd_cblk_dec {
+ unsigned char* data; /* Data */
+ opj_tcd_seg_t* segs; /* segments informations */
+ int x0, y0, x1, y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numbps;
+ int numlenbits;
+ int len; /* length */
+ int numnewpasses; /* number of pass added to the code-blocks */
+ int numsegs; /* number of segments */
+} opj_tcd_cblk_dec_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_precinct {
+ int x0, y0, x1, y1; /* dimension of the precinct : left upper corner (x0, y0) right low corner (x1,y1) */
+ int cw, ch; /* number of precinct in width and heigth */
+ union{ /* code-blocks informations */
+ opj_tcd_cblk_enc_t* enc;
+ opj_tcd_cblk_dec_t* dec;
+ } cblks;
+ opj_tgt_tree_t *incltree; /* inclusion tree */
+ opj_tgt_tree_t *imsbtree; /* IMSB tree */
+} opj_tcd_precinct_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_band {
+ int x0, y0, x1, y1; /* dimension of the subband : left upper corner (x0, y0) right low corner (x1,y1) */
+ int bandno;
+ opj_tcd_precinct_t *precincts; /* precinct information */
+ int numbps;
+ float stepsize;
+} opj_tcd_band_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_resolution {
+ int x0, y0, x1, y1; /* dimension of the resolution level : left upper corner (x0, y0) right low corner (x1,y1) */
+ int pw, ph;
+ int numbands; /* number sub-band for the resolution level */
+ opj_tcd_band_t bands[3]; /* subband information */
+} opj_tcd_resolution_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tilecomp {
+ int x0, y0, x1, y1; /* dimension of component : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numresolutions; /* number of resolutions level */
+ opj_tcd_resolution_t *resolutions; /* resolutions information */
+ int *data; /* data of the component */
+ int numpix; /* add fixed_quality */
+} opj_tcd_tilecomp_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_tile {
+ int x0, y0, x1, y1; /* dimension of the tile : left upper corner (x0, y0) right low corner (x1,y1) */
+ int numcomps; /* number of components in tile */
+ opj_tcd_tilecomp_t *comps; /* Components information */
+ int numpix; /* add fixed_quality */
+ double distotile; /* add fixed_quality */
+ double distolayer[100]; /* add fixed_quality */
+ /** packet number */
+ int packno;
+} opj_tcd_tile_t;
+
+/**
+FIXME: documentation
+*/
+typedef struct opj_tcd_image {
+ int tw, th; /* number of tiles in width and heigth */
+ opj_tcd_tile_t *tiles; /* Tiles information */
+} opj_tcd_image_t;
+
+/**
+Tile coder/decoder
+*/
+typedef struct opj_tcd {
+ /** Position of the tilepart flag in Progression order*/
+ int tp_pos;
+ /** Tile part number*/
+ int tp_num;
+ /** Current tile part number*/
+ int cur_tp_num;
+ /** Total number of tileparts of the current tile*/
+ int cur_totnum_tp;
+ /** Current Packet iterator number */
+ int cur_pino;
+ /** codec context */
+ opj_common_ptr cinfo;
+
+ /** info on each image tile */
+ opj_tcd_image_t *tcd_image;
+ /** image */
+ opj_image_t *image;
+ /** coding parameters */
+ opj_cp_t *cp;
+ /** pointer to the current encoded/decoded tile */
+ opj_tcd_tile_t *tcd_tile;
+ /** coding/decoding parameters common to all tiles */
+ opj_tcp_t *tcp;
+ /** current encoded/decoded tile */
+ int tcd_tileno;
+ /** Time taken to encode a tile*/
+ double encoding_time;
+} opj_tcd_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+
+/**
+Dump the content of a tcd structure
+*/
+void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t *img);
+/**
+Create a new TCD handle
+@param cinfo Codec context info
+@return Returns a new TCD handle if successful returns NULL otherwise
+*/
+opj_tcd_t* tcd_create(opj_common_ptr cinfo);
+/**
+Destroy a previously created TCD handle
+@param tcd TCD handle to destroy
+*/
+void tcd_destroy(opj_tcd_t *tcd);
+/**
+Initialize the tile coder (allocate the memory)
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+@param curtileno Number that identifies the tile that will be encoded
+*/
+void tcd_malloc_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno);
+/**
+Free the memory allocated for encoding
+@param tcd TCD handle
+*/
+void tcd_free_encode(opj_tcd_t *tcd);
+/**
+Initialize the tile coder (reuses the memory allocated by tcd_malloc_encode)
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+@param curtileno Number that identifies the tile that will be encoded
+*/
+void tcd_init_encode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int curtileno);
+/**
+Initialize the tile decoder
+@param tcd TCD handle
+@param image Raw image
+@param cp Coding parameters
+*/
+void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp);
+void tcd_malloc_decode_tile(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp, int tileno, opj_codestream_info_t *cstr_info);
+void tcd_makelayer_fixed(opj_tcd_t *tcd, int layno, int final);
+void tcd_rateallocate_fixed(opj_tcd_t *tcd);
+void tcd_makelayer(opj_tcd_t *tcd, int layno, double thresh, int final);
+bool tcd_rateallocate(opj_tcd_t *tcd, unsigned char *dest, int len, opj_codestream_info_t *cstr_info);
+/**
+Encode a tile from the raw image into a buffer
+@param tcd TCD handle
+@param tileno Number that identifies one of the tiles to be encoded
+@param dest Destination buffer
+@param len Length of destination buffer
+@param cstr_info Codestream information structure
+@return
+*/
+int tcd_encode_tile(opj_tcd_t *tcd, int tileno, unsigned char *dest, int len, opj_codestream_info_t *cstr_info);
+/**
+Decode a tile from a buffer into a raw image
+@param tcd TCD handle
+@param src Source buffer
+@param len Length of source buffer
+@param tileno Number that identifies one of the tiles to be decoded
+*/
+bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno, opj_codestream_info_t *cstr_info);
+/**
+Free the memory allocated for decoding
+@param tcd TCD handle
+*/
+void tcd_free_decode(opj_tcd_t *tcd);
+void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno);
+
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TCD_H */
diff --git a/Source/LibOpenJPEG/tgt.c b/Source/LibOpenJPEG/tgt.c
new file mode 100644
index 0000000..a5dbcd3
--- /dev/null
+++ b/Source/LibOpenJPEG/tgt.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opj_includes.h"
+
+/*
+==========================================================
+ Tag-tree coder interface
+==========================================================
+*/
+
+opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv) {
+ int nplh[32];
+ int nplv[32];
+ opj_tgt_node_t *node = NULL;
+ opj_tgt_node_t *parentnode = NULL;
+ opj_tgt_node_t *parentnode0 = NULL;
+ opj_tgt_tree_t *tree = NULL;
+ int i, j, k;
+ int numlvls;
+ int n;
+
+ tree = (opj_tgt_tree_t *) opj_malloc(sizeof(opj_tgt_tree_t));
+ if(!tree) return NULL;
+ tree->numleafsh = numleafsh;
+ tree->numleafsv = numleafsv;
+
+ numlvls = 0;
+ nplh[0] = numleafsh;
+ nplv[0] = numleafsv;
+ tree->numnodes = 0;
+ do {
+ n = nplh[numlvls] * nplv[numlvls];
+ nplh[numlvls + 1] = (nplh[numlvls] + 1) / 2;
+ nplv[numlvls + 1] = (nplv[numlvls] + 1) / 2;
+ tree->numnodes += n;
+ ++numlvls;
+ } while (n > 1);
+
+ /* ADD */
+ if (tree->numnodes == 0) {
+ opj_free(tree);
+ return NULL;
+ }
+
+ tree->nodes = (opj_tgt_node_t*) opj_calloc(tree->numnodes, sizeof(opj_tgt_node_t));
+ if(!tree->nodes) {
+ opj_free(tree);
+ return NULL;
+ }
+
+ node = tree->nodes;
+ parentnode = &tree->nodes[tree->numleafsh * tree->numleafsv];
+ parentnode0 = parentnode;
+
+ for (i = 0; i < numlvls - 1; ++i) {
+ for (j = 0; j < nplv[i]; ++j) {
+ k = nplh[i];
+ while (--k >= 0) {
+ node->parent = parentnode;
+ ++node;
+ if (--k >= 0) {
+ node->parent = parentnode;
+ ++node;
+ }
+ ++parentnode;
+ }
+ if ((j & 1) || j == nplv[i] - 1) {
+ parentnode0 = parentnode;
+ } else {
+ parentnode = parentnode0;
+ parentnode0 += nplh[i];
+ }
+ }
+ }
+ node->parent = 0;
+
+ tgt_reset(tree);
+
+ return tree;
+}
+
+void tgt_destroy(opj_tgt_tree_t *tree) {
+ opj_free(tree->nodes);
+ opj_free(tree);
+}
+
+void tgt_reset(opj_tgt_tree_t *tree) {
+ int i;
+
+ if (NULL == tree)
+ return;
+
+ for (i = 0; i < tree->numnodes; i++) {
+ tree->nodes[i].value = 999;
+ tree->nodes[i].low = 0;
+ tree->nodes[i].known = 0;
+ }
+}
+
+void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value) {
+ opj_tgt_node_t *node;
+ node = &tree->nodes[leafno];
+ while (node && node->value > value) {
+ node->value = value;
+ node = node->parent;
+ }
+}
+
+void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) {
+ opj_tgt_node_t *stk[31];
+ opj_tgt_node_t **stkptr;
+ opj_tgt_node_t *node;
+ int low;
+
+ stkptr = stk;
+ node = &tree->nodes[leafno];
+ while (node->parent) {
+ *stkptr++ = node;
+ node = node->parent;
+ }
+
+ low = 0;
+ for (;;) {
+ if (low > node->low) {
+ node->low = low;
+ } else {
+ low = node->low;
+ }
+
+ while (low < threshold) {
+ if (low >= node->value) {
+ if (!node->known) {
+ bio_write(bio, 1, 1);
+ node->known = 1;
+ }
+ break;
+ }
+ bio_write(bio, 0, 1);
+ ++low;
+ }
+
+ node->low = low;
+ if (stkptr == stk)
+ break;
+ node = *--stkptr;
+ }
+}
+
+int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold) {
+ opj_tgt_node_t *stk[31];
+ opj_tgt_node_t **stkptr;
+ opj_tgt_node_t *node;
+ int low;
+
+ stkptr = stk;
+ node = &tree->nodes[leafno];
+ while (node->parent) {
+ *stkptr++ = node;
+ node = node->parent;
+ }
+
+ low = 0;
+ for (;;) {
+ if (low > node->low) {
+ node->low = low;
+ } else {
+ low = node->low;
+ }
+ while (low < threshold && low < node->value) {
+ if (bio_read(bio, 1)) {
+ node->value = low;
+ } else {
+ ++low;
+ }
+ }
+ node->low = low;
+ if (stkptr == stk) {
+ break;
+ }
+ node = *--stkptr;
+ }
+
+ return (node->value < threshold) ? 1 : 0;
+}
diff --git a/Source/LibOpenJPEG/tgt.h b/Source/LibOpenJPEG/tgt.h
new file mode 100644
index 0000000..c08c8da
--- /dev/null
+++ b/Source/LibOpenJPEG/tgt.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
+ * Copyright (c) 2002-2007, Professor Benoit Macq
+ * Copyright (c) 2001-2003, David Janssens
+ * Copyright (c) 2002-2003, Yannick Verschueren
+ * Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe
+ * Copyright (c) 2005, Herve Drolon, FreeImage Team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TGT_H
+#define __TGT_H
+/**
+@file tgt.h
+@brief Implementation of a tag-tree coder (TGT)
+
+The functions in TGT.C have for goal to realize a tag-tree coder. The functions in TGT.C
+are used by some function in T2.C.
+*/
+
+/** @defgroup TGT TGT - Implementation of a tag-tree coder */
+/*@{*/
+
+/**
+Tag node
+*/
+typedef struct opj_tgt_node {
+ struct opj_tgt_node *parent;
+ int value;
+ int low;
+ int known;
+} opj_tgt_node_t;
+
+/**
+Tag tree
+*/
+typedef struct opj_tgt_tree {
+ int numleafsh;
+ int numleafsv;
+ int numnodes;
+ opj_tgt_node_t *nodes;
+} opj_tgt_tree_t;
+
+/** @name Exported functions */
+/*@{*/
+/* ----------------------------------------------------------------------- */
+/**
+Create a tag-tree
+@param numleafsh Width of the array of leafs of the tree
+@param numleafsv Height of the array of leafs of the tree
+@return Returns a new tag-tree if successful, returns NULL otherwise
+*/
+opj_tgt_tree_t *tgt_create(int numleafsh, int numleafsv);
+/**
+Destroy a tag-tree, liberating memory
+@param tree Tag-tree to destroy
+*/
+void tgt_destroy(opj_tgt_tree_t *tree);
+/**
+Reset a tag-tree (set all leaves to 0)
+@param tree Tag-tree to reset
+*/
+void tgt_reset(opj_tgt_tree_t *tree);
+/**
+Set the value of a leaf of a tag-tree
+@param tree Tag-tree to modify
+@param leafno Number that identifies the leaf to modify
+@param value New value of the leaf
+*/
+void tgt_setvalue(opj_tgt_tree_t *tree, int leafno, int value);
+/**
+Encode the value of a leaf of the tag-tree up to a given threshold
+@param bio Pointer to a BIO handle
+@param tree Tag-tree to modify
+@param leafno Number that identifies the leaf to encode
+@param threshold Threshold to use when encoding value of the leaf
+*/
+void tgt_encode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold);
+/**
+Decode the value of a leaf of the tag-tree up to a given threshold
+@param bio Pointer to a BIO handle
+@param tree Tag-tree to decode
+@param leafno Number that identifies the leaf to decode
+@param threshold Threshold to use when decoding value of the leaf
+@return Returns 1 if the node's value < threshold, returns 0 otherwise
+*/
+int tgt_decode(opj_bio_t *bio, opj_tgt_tree_t *tree, int leafno, int threshold);
+/* ----------------------------------------------------------------------- */
+/*@}*/
+
+/*@}*/
+
+#endif /* __TGT_H */
diff --git a/Source/LibPNG/ANNOUNCE b/Source/LibPNG/ANNOUNCE
new file mode 100644
index 0000000..5fab72a
--- /dev/null
+++ b/Source/LibPNG/ANNOUNCE
@@ -0,0 +1,55 @@
+
+Libpng 1.2.49 - March 29, 2012
+
+This is a public release of libpng, intended for use in production codes.
+
+Files available for download:
+
+Source files with LF line endings (for Unix/Linux) and with a
+"configure" script
+
+ libpng-1.2.49.tar.xz (LZMA-compressed, recommended)
+ libpng-1.2.49.tar.gz
+ libpng-1.2.49.tar.bz2
+
+Source files with LF line endings (for Unix/Linux) without the
+"configure" script
+
+ libpng-1.2.49-no-config.tar.xz (LZMA-compressed, recommended)
+ libpng-1.2.49-no-config.tar.gz
+ libpng-1.2.49-no-config.tar.bz2
+
+Source files with CRLF line endings (for Windows), without the
+"configure" script
+
+ lpng1249.zip
+ lpng1249.7z
+ lpng1249.tar.bz2
+
+Project files
+
+ libpng-1.2.49-project-netware.zip
+ libpng-1.2.49-project-wince.zip
+
+Other information:
+
+ libpng-1.2.49-README.txt
+ libpng-1.2.49-KNOWNBUGS.txt
+ libpng-1.2.49-LICENSE.txt
+ libpng-1.2.49-Y2K-compliance.txt
+ libpng-1.2.49-[previous version]-diff.txt
+
+Changes since the last public release (1.2.48):
+
+version 1.2.49 [March 29, 2012]
+
+ Revised png_set_text_2() to avoid potential memory corruption (fixes
+ CVE-2011-3048).
+ Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
+
+Send comments/corrections/commendations to png-mng-implement at lists.sf.net
+(subscription required; visit
+https://lists.sourceforge.net/lists/listinfo/png-mng-implement
+to subscribe) or to glennrp at users.sourceforge.net
+
+Glenn R-P
diff --git a/Source/LibPNG/CHANGES b/Source/LibPNG/CHANGES
new file mode 100644
index 0000000..ad90e51
--- /dev/null
+++ b/Source/LibPNG/CHANGES
@@ -0,0 +1,2785 @@
+#if 0
+CHANGES - changes for libpng
+
+version 0.2
+ added reader into png.h
+ fixed small problems in stub file
+
+version 0.3
+ added pull reader
+ split up pngwrite.c to several files
+ added pnglib.txt
+ added example.c
+ cleaned up writer, adding a few new transformations
+ fixed some bugs in writer
+ interfaced with zlib 0.5
+ added K&R support
+ added check for 64 KB blocks for 16 bit machines
+
+version 0.4
+ cleaned up code and commented code
+ simplified time handling into png_time
+ created png_color_16 and png_color_8 to handle color needs
+ cleaned up color type defines
+ fixed various bugs
+ made various names more consistent
+ interfaced with zlib 0.71
+ cleaned up zTXt reader and writer (using zlib's Reset functions)
+ split transformations into pngrtran.c and pngwtran.c
+
+version 0.5
+ interfaced with zlib 0.8
+ fixed many reading and writing bugs
+ saved using 3 spaces instead of tabs
+
+version 0.6
+ added png_large_malloc() and png_large_free()
+ added png_size_t
+ cleaned up some compiler warnings
+ added png_start_read_image()
+
+version 0.7
+ cleaned up lots of bugs
+ finished dithering and other stuff
+ added test program
+ changed name from pnglib to libpng
+
+version 0.71 [June, 1995]
+ changed pngtest.png for zlib 0.93
+ fixed error in libpng.txt and example.c
+
+version 0.8
+ cleaned up some bugs
+ added png_set_filler()
+ split up pngstub.c into pngmem.c, pngio.c, and pngerror.c
+ added #define's to remove unwanted code
+ moved png_info_init() to png.c
+ added old_size into png_realloc()
+ added functions to manually set filtering and compression info
+ changed compression parameters based on image type
+ optimized filter selection code
+ added version info
+ changed external functions passing floats to doubles (k&r problems?)
+ put all the configurable stuff in pngconf.h
+ enabled png_set_shift to work with paletted images on read
+ added png_read_update_info() - updates info structure with
+ transformations
+
+version 0.81 [August, 1995]
+ incorporated Tim Wegner's medium model code (thanks, Tim)
+
+version 0.82 [September, 1995]
+ [unspecified changes]
+
+version 0.85 [December, 1995]
+ added more medium model code (almost everything's a far)
+ added i/o, error, and memory callback functions
+ fixed some bugs (16 bit, 4 bit interlaced, etc.)
+ added first run progressive reader (barely tested)
+
+version 0.86 [January, 1996]
+ fixed bugs
+ improved documentation
+
+version 0.87 [January, 1996]
+ fixed medium model bugs
+ fixed other bugs introduced in 0.85 and 0.86
+ added some minor documentation
+
+version 0.88 [January, 1996]
+ fixed progressive bugs
+ replaced tabs with spaces
+ cleaned up documentation
+ added callbacks for read/write and warning/error functions
+
+version 0.89 [July, 1996]
+ added new initialization API to make libpng work better with shared libs
+ we now have png_create_read_struct(), png_create_write_struct(),
+ png_create_info_struct(), png_destroy_read_struct(), and
+ png_destroy_write_struct() instead of the separate calls to
+ malloc and png_read_init(), png_info_init(), and png_write_init()
+ changed warning/error callback functions to fix bug - this means you
+ should use the new initialization API if you were using the old
+ png_set_message_fn() calls, and that the old API no longer exists
+ so that people are aware that they need to change their code
+ changed filter selection API to allow selection of multiple filters
+ since it didn't work in previous versions of libpng anyways
+ optimized filter selection code
+ fixed png_set_background() to allow using an arbitrary RGB color for
+ paletted images
+ fixed gamma and background correction for paletted images, so
+ png_correct_palette is not needed unless you are correcting an
+ external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED
+ in pngconf.h) - if nobody uses this, it may disappear in the future.
+ fixed bug with Borland 64K memory allocation (Alexander Lehmann)
+ fixed bug in interlace handling (Smarasderagd, I think)
+ added more error checking for writing and image to reduce invalid files
+ separated read and write functions so that they won't both be linked
+ into a binary when only reading or writing functionality is used
+ new pngtest image also has interlacing and zTXt
+ updated documentation to reflect new API
+
+version 0.90 [January, 1997]
+ made CRC errors/warnings on critical and ancillary chunks configurable
+ libpng will use the zlib CRC routines by (compile-time) default
+ changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner)
+ added external C++ wrapper statements to png.h (Gilles Dauphin)
+ allow PNG file to be read when some or all of file signature has already
+ been read from the beginning of the stream. ****This affects the size
+ of info_struct and invalidates all programs that use a shared libpng****
+ fixed png_filler() declarations
+ fixed? background color conversions
+ fixed order of error function pointers to match documentation
+ current chunk name is now available in png_struct to reduce the number
+ of nearly identical error messages (will simplify multi-lingual
+ support when available)
+ try to get ready for unknown-chunk callback functions:
+ - previously read critical chunks are flagged, so the chunk handling
+ routines can determine if the chunk is in the right place
+ - all chunk handling routines have the same prototypes, so we will
+ be able to handle all chunks via a callback mechanism
+ try to fix Linux "setjmp" buffer size problems
+ removed png_large_malloc, png_large_free, and png_realloc functions.
+
+version 0.95 [March, 1997]
+ fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never
+ fixed bug in PNG file signature compares when start != 0
+ changed parameter type of png_set_filler(...filler...) from png_byte
+ to png_uint_32
+ added test for MACOS to ensure that both math.h and fp.h are not #included
+ added macros for libpng to be compiled as a Windows DLL (Andreas Kupries)
+ added "packswap" transformation, which changes the endianness of
+ packed-pixel bytes (Kevin Bracey)
+ added "strip_alpha" transformation, which removes the alpha channel of
+ input images without using it (not necessarily a good idea)
+ added "swap_alpha" transformation, which puts the alpha channel in front
+ of the color bytes instead of after
+ removed all implicit variable tests which assume NULL == 0 (I think)
+ changed several variables to "png_size_t" to show 16/32-bit limitations
+ added new pCAL chunk read/write support
+ added experimental filter selection weighting (Greg Roelofs)
+ removed old png_set_rgbx() and png_set_xrgb() functions that have been
+ obsolete for about 2 years now (use png_set_filler() instead)
+ added macros to read 16- and 32-bit ints directly from buffer, to be
+ used only on those systems that support it (namely PowerPC and 680x0)
+ With some testing, this may become the default for MACOS/PPC systems.
+ only calculate CRC on data if we are going to use it
+ added macros for zTXt compression type PNG_zTXt_COMPRESSION_???
+ added macros for simple libpng debugging output selectable at compile time
+ removed PNG_READ_END_MODE in progressive reader (Smarasderagd)
+ more description of info_struct in libpng.txt and png.h
+ more instructions in example.c
+ more chunk types tested in pngtest.c
+ renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be
+ png_set_<chunk>. We now have corresponding png_get_<chunk>
+ functions in pngget.c to get information in info_ptr. This isolates
+ the application from the internal organization of png_info_struct
+ (good for shared library implementations).
+
+version 0.96 [May, 1997]
+ fixed serious bug with < 8bpp images introduced in 0.95
+ fixed 256-color transparency bug (Greg Roelofs)
+ fixed up documentation (Greg Roelofs, Laszlo Nyul)
+ fixed "error" in pngconf.h for Linux setjmp() behaviour
+ fixed DOS medium model support (Tim Wegner)
+ fixed png_check_keyword() for case with error in static string text
+ added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul)
+ added typecasts to quiet compiler errors
+ added more debugging info
+
+version 0.97 [January, 1998]
+ removed PNG_USE_OWN_CRC capability
+ relocated png_set_crc_action from pngrutil.c to pngrtran.c
+ fixed typecasts of "new_key", etc. (Andreas Dilger)
+ added RFC 1152 [sic] date support
+ fixed bug in gamma handling of 4-bit grayscale
+ added 2-bit grayscale gamma handling (Glenn R-P)
+ added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P)
+ minor corrections in libpng.txt
+ added simple sRGB support (Glenn R-P)
+ easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED;
+ all configurable options can be selected from command-line instead
+ of having to edit pngconf.h (Glenn R-P)
+ fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P)
+ added more conditions for png_do_background, to avoid changing
+ black pixels to background when a background is supplied and
+ no pixels are transparent
+ repaired PNG_NO_STDIO behaviour
+ tested NODIV support and made it default behaviour (Greg Roelofs)
+ added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler)
+ regularized version numbering scheme and bumped shared-library major
+ version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs)
+
+version 0.98 [January, 1998]
+ cleaned up some typos in libpng.txt and in code documentation
+ fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler)
+ cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c
+ changed recommendation about file_gamma for PC images to .51 from .45,
+ in example.c and libpng.txt, added comments to distinguish between
+ screen_gamma, viewing_gamma, and display_gamma.
+ changed all references to RFC1152 to read RFC1123 and changed the
+ PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED
+ added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent)
+ changed srgb_intent from png_byte to int to avoid compiler bugs
+
+version 0.99 [January 30, 1998]
+ free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler)
+ fixed a longstanding "packswap" bug in pngtrans.c
+ fixed some inconsistencies in pngconf.h that prevented compiling with
+ PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined
+ fixed some typos and made other minor rearrangement of libpng.txt (Andreas)
+ changed recommendation about file_gamma for PC images to .50 from .51 in
+ example.c and libpng.txt, and changed file_gamma for sRGB images to .45
+ added a number of functions to access information from the png structure
+ png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit)
+ added TARGET_MACOS similar to zlib-1.0.8
+ define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined
+ added type casting to all png_malloc() function calls
+version 0.99a [January 31, 1998]
+ Added type casts and parentheses to all returns that return a value.(Tim W.)
+version 0.99b [February 4, 1998]
+ Added type cast png_uint_32 on malloc function calls where needed.
+ Changed type of num_hist from png_uint_32 to int (same as num_palette).
+ Added checks for rowbytes overflow, in case png_size_t is less than 32 bits.
+ Renamed makefile.elf to makefile.lnx.
+version 0.99c [February 7, 1998]
+ More type casting. Removed erroneous overflow test in pngmem.c.
+ Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes.
+ Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5.
+version 0.99d [February 11, 1998]
+ Renamed "far_to_near()" "png_far_to_near()"
+ Revised libpng.3
+ Version 99c "buffered" operations didn't work as intended. Replaced them
+ with png_memcpy_check() and png_memset_check().
+ Added many "if (png_ptr == NULL) return" to quell compiler warnings about
+ unused png_ptr, mostly in pngget.c and pngset.c.
+ Check for overlength tRNS chunk present when indexed-color PLTE is read.
+ Cleaned up spelling errors in libpng.3/libpng.txt
+ Corrected a problem with png_get_tRNS() which returned undefined trans array
+version 0.99e [February 28, 1998]
+ Corrected png_get_tRNS() again.
+ Add parentheses for easier reading of pngget.c, fixed "||" should be "&&".
+ Touched up example.c to make more of it compileable, although the entire
+ file still can't be compiled (Willem van Schaik)
+ Fixed a bug in png_do_shift() (Bryan Tsai)
+ Added a space in png.h prototype for png_write_chunk_start()
+ Replaced pngtest.png with one created with zlib 1.1.1
+ Changed pngtest to report PASS even when file size is different (Jean-loup G.)
+ Corrected some logic errors in png_do_invert_alpha() (Chris Patterson)
+version 0.99f [March 5, 1998]
+ Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey)
+ Moved makefiles into a "scripts" directory, and added INSTALL instruction file
+ Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok)
+ Added pointers to "note on libpng versions" in makefile.lnx and README
+ Added row callback feature when reading and writing nonprogressive rows
+ and added a test of this feature in pngtest.c
+ Added user transform callbacks, with test of the feature in pngtest.c
+version 0.99g [March 6, 1998, morning]
+ Minor changes to pngtest.c to suppress compiler warnings.
+ Removed "beta" language from documentation.
+version 0.99h [March 6, 1998, evening]
+ Minor changes to previous minor changes to pngtest.c
+ Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED
+ and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro
+ Added user transform capability
+
+version 1.00 [March 7, 1998]
+ Changed several typedefs in pngrutil.c
+ Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik)
+ replaced "while(1)" with "for(;;)"
+ added PNGARG() to prototypes in pngtest.c and removed some prototypes
+ updated some of the makefiles (Tom Lane)
+ changed some typedefs (s_start, etc.) in pngrutil.c
+ fixed dimensions of "short_months" array in pngwrite.c
+ Replaced ansi2knr.c with the one from jpeg-v6
+
+version 1.0.0 [March 8, 1998]
+ Changed name from 1.00 to 1.0.0 (Adam Costello)
+ Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert)
+version 1.0.0a [March 9, 1998]
+ Fixed three bugs in pngrtran.c to make gamma+background handling consistent
+ (Greg Roelofs)
+ Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz
+ for major, minor, and bugfix releases. This is 10001. (Adam Costello,
+ Tom Lane)
+ Make months range from 1-12 in png_convert_to_rfc1123
+version 1.0.0b [March 13, 1998]
+ Quieted compiler complaints about two empty "for" loops in pngrutil.c
+ Minor changes to makefile.s2x
+ Removed #ifdef/#endif around a png_free() in pngread.c
+
+version 1.0.1 [March 14, 1998]
+ Changed makefile.s2x to reduce security risk of using a relative pathname
+ Fixed some typos in the documentation (Greg).
+ Fixed a problem with value of "channels" returned by png_read_update_info()
+version 1.0.1a [April 21, 1998]
+ Optimized Paeth calculations by replacing abs() function calls with intrinsics
+ plus other loop optimizations. Improves avg decoding speed by about 20%.
+ Commented out i386istic "align" compiler flags in makefile.lnx.
+ Reduced the default warning level in some makefiles, to make them consistent.
+ Removed references to IJG and JPEG in the ansi2knr.c copyright statement.
+ Fixed a bug in png_do_strip_filler with XXRRGGBB => RRGGBB transformation.
+ Added grayscale and 16-bit capability to png_do_read_filler().
+ Fixed a bug in pngset.c, introduced in version 0.99c, that sets rowbytes
+ too large when writing an image with bit_depth < 8 (Bob Dellaca).
+ Corrected some bugs in the experimental weighted filtering heuristics.
+ Moved a misplaced pngrutil code block that truncates tRNS if it has more
+ than num_palette entries -- test was done before num_palette was defined.
+ Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins).
+ Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen).
+version 1.0.1b [May 2, 1998]
+ Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg).
+ Relocated the png_composite macros from pngrtran.c to png.h (Greg).
+ Added makefile.sco (contributed by Mike Hopkirk).
+ Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a.
+ Fixed a bug in pngrtran.c that would set channels=5 under some circumstances.
+ More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert).
+ More work on loop optimization which may help when compiled with C++ compilers.
+ Added warnings when people try to use transforms they've defined out.
+ Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran.
+ Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg)
+version 1.0.1c [May 11, 1998]
+ Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for
+ filler bytes should have been 0xff instead of 0xf.
+ Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images.
+ Moved PNG_WRITE_WEIGHTED_FILTER_SUPPORTED and PNG_WRITE_FLUSH_SUPPORTED
+ out of the PNG_WRITE_TRANSFORMS_NOT_SUPPORTED block of pngconf.h
+ Added "PNG_NO_WRITE_TRANSFORMS" etc., as alternatives for *_NOT_SUPPORTED,
+ for consistency, in pngconf.h
+ Added individual "ifndef PNG_NO_[CAPABILITY]" in pngconf.h to make it easier
+ to remove unwanted capabilities via the compile line
+ Made some corrections to grammar (which, it's) in documentation (Greg).
+ Corrected example.c, use of row_pointers in png_write_image().
+version 1.0.1d [May 24, 1998]
+ Corrected several statements that used side effects illegally in pngrutil.c
+ and pngtrans.c, that were introduced in version 1.0.1b
+ Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert)
+ More corrections to example.c, use of row_pointers in png_write_image()
+ and png_read_rows().
+ Added pngdll.mak and pngdef.pas to scripts directory, contributed by
+ Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5
+ Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.)
+ Changed several loops from count-down to count-up, for consistency.
+version 1.0.1e [June 6, 1998]
+ Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and
+ added warnings when people try to set png_read_fn and png_write_fn in
+ the same structure.
+ Added a test such that png_do_gamma will be done when num_trans==0
+ for truecolor images that have defined a background. This corrects an
+ error that was introduced in libpng-0.90 that can cause gamma processing
+ to be skipped.
+ Added tests in png.h to include "trans" and "trans_values" in structures
+ when PNG_READ_BACKGROUND_SUPPORTED or PNG_READ_EXPAND_SUPPORTED is defined.
+ Add png_free(png_ptr->time_buffer) in png_destroy_read_struct()
+ Moved png_convert_to_rfc_1123() from pngwrite.c to png.c
+ Added capability for user-provided malloc_fn() and free_fn() functions,
+ and revised pngtest.c to demonstrate their use, replacing the
+ PNGTEST_DEBUG_MEM feature.
+ Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner).
+
+version 1.0.2 [June 14, 1998]
+ Fixed two bugs in makefile.bor .
+version 1.0.2a [December 30, 1998]
+ Replaced and extended code that was removed from png_set_filler() in 1.0.1a.
+ Fixed a bug in png_do_filler() that made it fail to write filler bytes in
+ the left-most pixel of each row (Kevin Bracey).
+ Changed "static pngcharp tIME_string" to "static char tIME_string[30]"
+ in pngtest.c (Duncan Simpson).
+ Fixed a bug in pngtest.c that caused pngtest to try to write a tIME chunk
+ even when no tIME chunk was present in the source file.
+ Fixed a problem in pngrutil.c: gray_to_rgb didn't always work with 16-bit.
+ Fixed a problem in png_read_push_finish_row(), which would not skip some
+ passes that it should skip, for images that are less than 3 pixels high.
+ Interchanged the order of calls to png_do_swap() and png_do_shift()
+ in pngwtran.c (John Cromer).
+ Added #ifdef PNG_DEBUG/#endif surrounding use of PNG_DEBUG in png.h .
+ Changed "bad adaptive filter type" from error to warning in pngrutil.c .
+ Fixed a documentation error about default filtering with 8-bit indexed-color.
+ Separated the PNG_NO_STDIO macro into PNG_NO_STDIO and PNG_NO_CONSOLE_IO
+ (L. Peter Deutsch).
+ Added png_set_rgb_to_gray() and png_get_rgb_to_gray_status() functions.
+ Added png_get_copyright() and png_get_header_version() functions.
+ Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c
+ Added information about debugging in libpng.txt and libpng.3 .
+ Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco.
+ Removed lines after Dynamic Dependencies" in makefile.aco .
+ Revised makefile.dec to make a shared library (Jeremie Petit).
+ Removed trailing blanks from all files.
+version 1.0.2a [January 6, 1999]
+ Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h
+ Added "if" tests to silence complaints about unused png_ptr in png.h and png.c
+ Changed "check_if_png" function in example.c to return true (nonzero) if PNG.
+ Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig()
+ which is obsolete.
+
+version 1.0.3 [January 14, 1999]
+ Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice)
+ Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO.
+version 1.0.3a [August 12, 1999]
+ Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning
+ if an attempt is made to read an interlaced image when it's not supported.
+ Added check if png_ptr->trans is defined before freeing it in pngread.c
+ Modified the Y2K statement to include versions back to version 0.71
+ Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c
+ Modified makefile.wat (added -zp8 flag, ".symbolic", changed some comments)
+ Replaced leading blanks with tab characters in makefile.hux
+ Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents.
+ Changed (float)red and (float)green to (double)red, (double)green
+ in png_set_rgb_to_gray() to avoid "promotion" problems in AIX.
+ Fixed a bug in pngconf.h that omitted <stdio.h> when PNG_DEBUG==0 (K Bracey).
+ Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt).
+ Updated documentation to refer to the PNG-1.2 specification.
+ Removed ansi2knr.c and left pointers to the latest source for ansi2knr.c
+ in makefile.knr, INSTALL, and README (L. Peter Deutsch)
+ Fixed bugs in calculation of the length of rowbytes when adding alpha
+ channels to 16-bit images, in pngrtran.c (Chris Nokleberg)
+ Added function png_set_user_transform_info() to store user_transform_ptr,
+ user_depth, and user_channels into the png_struct, and a function
+ png_get_user_transform_ptr() to retrieve the pointer (Chris Nokleberg)
+ Added function png_set_empty_plte_permitted() to make libpng useable
+ in MNG applications.
+ Corrected the typedef for png_free_ptr in png.h (Jesse Jones).
+ Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be
+ consistent with PNG-1.2, and allow variance of 500 before complaining.
+ Added assembler code contributed by Intel in file pngvcrd.c and modified
+ makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant)
+ Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy.
+ Added some aliases for png_set_expand() in pngrtran.c, namely
+ png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS()
+ (Greg Roelofs, in "PNG: The Definitive Guide").
+ Added makefile.beo for BEOS on X86, contributed by Sander Stok.
+version 1.0.3b [August 26, 1999]
+ Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h
+ Changed leading blanks to tabs in all makefiles.
+ Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code.
+ Made alternate versions of png_set_expand() in pngrtran.c, namely
+ png_set_gray_1_2_4_to_8, png_set_palette_to_rgb, and png_set_tRNS_to_alpha
+ (Greg Roelofs, in "PNG: The Definitive Guide"). Deleted the 1.0.3a aliases.
+ Relocated start of 'extern "C"' block in png.h so it doesn't include pngconf.h
+ Revised calculation of num_blocks in pngmem.c to avoid a potentially
+ negative shift distance, whose results are undefined in the C language.
+ Added a check in pngset.c to prevent writing multiple tIME chunks.
+ Added a check in pngwrite.c to detect invalid small window_bits sizes.
+version 1.0.3d [September 4, 1999]
+ Fixed type casting of igamma in pngrutil.c
+ Added new png_expand functions to scripts/pngdef.pas and pngos2.def
+ Added a demo read_user_transform_fn that examines the row filters in pngtest.c
+
+version 1.0.4 [September 24, 1999]
+ Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined
+ Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h
+ Made several minor corrections to pngtest.c
+ Renamed the makefiles with longer but more user friendly extensions.
+ Copied the PNG copyright and license to a separate LICENSE file.
+ Revised documentation, png.h, and example.c to remove reference to
+ "viewing_gamma" which no longer appears in the PNG specification.
+ Revised pngvcrd.c to use MMX code for interlacing only on the final pass.
+ Updated pngvcrd.c to use the faster C filter algorithms from libpng-1.0.1a
+ Split makefile.win32vc into two versions, makefile.vcawin32 (uses MMX
+ assembler code) and makefile.vcwin32 (doesn't).
+ Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING)
+ Added a copy of pngnow.png to the distribution.
+version 1.0.4a [September 25, 1999]
+ Increase max_pixel_depth in pngrutil.c if a user transform needs it.
+ Changed several division operations to right-shifts in pngvcrd.c
+version 1.0.4b [September 30, 1999]
+ Added parentheses in line 3732 of pngvcrd.c
+ Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1
+version 1.0.4c [October 1, 1999]
+ Added a "png_check_version" function in png.c and pngtest.c that will generate
+ a helpful compiler error if an old png.h is found in the search path.
+ Changed type of png_user_transform_depth|channels from int to png_byte.
+version 1.0.4d [October 6, 1999]
+ Changed 0.45 to 0.45455 in png_set_sRGB()
+ Removed unused PLTE entries from pngnow.png
+ Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly.
+version 1.0.4e [October 10, 1999]
+ Fixed sign error in pngvcrd.c (Greg Roelofs)
+ Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P)
+version 1.0.4f [October 15, 1999]
+ Surrounded example.c code with #if 0 .. #endif to prevent people from
+ inadvertently trying to compile it.
+ Changed png_get_header_version() from a function to a macro in png.h
+ Added type casting mostly in pngrtran.c and pngwtran.c
+ Removed some pointless "ptr = NULL" in pngmem.c
+ Added a "contrib" directory containing the source code from Greg's book.
+
+version 1.0.5 [October 15, 1999]
+ Minor editing of the INSTALL and README files.
+version 1.0.5a [October 23, 1999]
+ Added contrib/pngsuite and contrib/pngminus (Willem van Schaik)
+ Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans)
+ Further optimization and bugfix of pngvcrd.c
+ Revised pngset.c so that it does not allocate or free memory in the user's
+ text_ptr structure. Instead, it makes its own copy.
+ Created separate write_end_info_struct in pngtest.c for a more severe test.
+ Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak.
+version 1.0.5b [November 23, 1999]
+ Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and
+ PNG_FLAG_WROTE_tIME from flags to mode.
+ Added png_write_info_before_PLTE() function.
+ Fixed some typecasting in contrib/gregbook/*.c
+ Updated scripts/makevms.com and added makevms.com to contrib/gregbook
+ and contrib/pngminus (Martin Zinser)
+version 1.0.5c [November 26, 1999]
+ Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr.
+ Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to
+ accommodate making DLL's: Moved usr_png_ver from global variable to function
+ png_get_header_ver() in png.c. Moved png_sig to png_sig_bytes in png.c and
+ eliminated use of png_sig in pngwutil.c. Moved the various png_CHNK arrays
+ into pngtypes.h. Eliminated use of global png_pass arrays. Declared the
+ png_CHNK and png_pass arrays to be "const". Made the global arrays
+ available to applications (although none are used in libpng itself) when
+ PNG_NO_GLOBAL_ARRAYS is not defined or when PNG_GLOBAL_ARRAYS is defined.
+ Removed some extraneous "-I" from contrib/pngminus/makefile.std
+ Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2.
+ Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3
+version 1.0.5d [November 29, 1999]
+ Add type cast (png_const_charp) two places in png.c
+ Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays.
+ Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available
+ to applications a macro "PNG_USE_LOCAL_ARRAYS".
+ Remove all the new declarations with #ifdef/#endif when
+ PNG_USE_GLOBAL_ARRAYS is defined.
+ Added PNG_EXPORT_VAR macro to accommodate making DLL's.
+version 1.0.5e [November 30, 1999]
+ Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text
+ structure; refactored the inflate/deflate support to make adding new chunks
+ with trailing compressed parts easier in the future, and added new functions
+ png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP,
+ png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond).
+ NOTE: Applications that write text chunks MUST define png_text->lang
+ before calling png_set_text(). It must be set to NULL if you want to
+ write tEXt or zTXt chunks. If you want your application to be able to
+ run with older versions of libpng, use
+
+ #ifdef PNG_iTXt_SUPPORTED
+ png_text[i].lang = NULL;
+ #endif
+
+ Changed png_get_oFFs() and png_set_oFFs() to use signed rather than unsigned
+ offsets (Eric S. Raymond).
+ Combined PNG_READ_cHNK_SUPPORTED and PNG_WRITE_cHNK_SUPPORTED macros into
+ PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED
+ macros, leaving the separate macros also available.
+ Removed comments on #endifs at the end of many short, non-nested #if-blocks.
+version 1.0.5f [December 6, 1999]
+ Changed makefile.solaris to issue a warning about potential problems when
+ the ucb "ld" is in the path ahead of the ccs "ld".
+ Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3.
+ Added sCAL chunk support (Eric S. Raymond).
+version 1.0.5g [December 7, 1999]
+ Fixed "png_free_spallettes" typo in png.h
+ Added code to handle new chunks in pngpread.c
+ Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block
+ Added "translated_key" to png_text structure and png_write_iTXt().
+ Added code in pngwrite.c to work around a newly discovered zlib bug.
+version 1.0.5h [December 10, 1999]
+ NOTE: regarding the note for version 1.0.5e, the following must also
+ be included in your code:
+ png_text[i].translated_key = NULL;
+ Unknown chunk handling is now supported.
+ Option to eliminate all floating point support was added. Some new
+ fixed-point functions such as png_set_gAMA_fixed() were added.
+ Expanded tabs and removed trailing blanks in source files.
+version 1.0.5i [December 13, 1999]
+ Added some type casts to silence compiler warnings.
+ Renamed "png_free_spalette" to "png_free_spalettes" for consistency.
+ Removed leading blanks from a #define in pngvcrd.c
+ Added some parameters to the new png_set_keep_unknown_chunks() function.
+ Added a test for up->location != 0 in the first instance of writing
+ unknown chunks in pngwrite.c
+ Changed "num" to "i" in png_free_spalettes() and png_free_unknowns() to
+ prevent recursion.
+ Added png_free_hIST() function.
+ Various patches to fix bugs in the sCAL and integer cHRM processing,
+ and to add some convenience macros for use with sCAL.
+version 1.0.5j [December 21, 1999]
+ Changed "unit" parameter of png_write_sCAL from png_byte to int, to work
+ around buggy compilers.
+ Added new type "png_fixed_point" for integers that hold float*100000 values
+ Restored backward compatibility of tEXt/zTXt chunk processing:
+ Restored the first four members of png_text to the same order as v.1.0.5d.
+ Added members "lang_key" and "itxt_length" to png_text struct. Set
+ text_length=0 when "text" contains iTXt data. Use the "compression"
+ member to distinguish among tEXt/zTXt/iTXt types. Added
+ PNG_ITXT_COMPRESSION_NONE (1) and PNG_ITXT_COMPRESSION_zTXt(2) macros.
+ The "Note" above, about backward incompatibility of libpng-1.0.5e, no
+ longer applies.
+ Fixed png_read|write_iTXt() to read|write parameters in the right order,
+ and to write the iTXt chunk after IDAT if it appears in the end_ptr.
+ Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs)
+ Reversed the order of trying to write floating-point and fixed-point gAMA.
+version 1.0.5k [December 27, 1999]
+ Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))"
+ Added png_handle_as_unknown() function (Glenn)
+ Added png_free_chunk_list() function and chunk_list and num_chunk_list members
+ of png_ptr.
+ Eliminated erroneous warnings about multiple sPLT chunks and sPLT-after-PLTE.
+ Fixed a libpng-1.0.5h bug in pngrutil.c that was issuing erroneous warnings
+ about ignoring incorrect gAMA with sRGB (gAMA was in fact not ignored)
+ Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR).
+ Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is.
+ Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP().
+version 1.0.5l [January 1, 2000]
+ Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr()
+ for setting a callback function to handle unknown chunks and for
+ retrieving the associated user pointer (Glenn).
+version 1.0.5m [January 7, 2000]
+ Added high-level functions png_read_png(), png_write_png(), png_free_pixels().
+version 1.0.5n [January 9, 2000]
+ Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its
+ own memory for info_ptr->palette. This makes it safe for the calling
+ application to free its copy of the palette any time after it calls
+ png_set_PLTE().
+version 1.0.5o [January 20, 2000]
+ Cosmetic changes only (removed some trailing blanks and TABs)
+version 1.0.5p [January 31, 2000]
+ Renamed pngdll.mak to makefile.bd32
+ Cosmetic changes in pngtest.c
+version 1.0.5q [February 5, 2000]
+ Relocated the makefile.solaris warning about PATH problems.
+ Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg)
+ Revised makefile.gcmmx
+ Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros
+version 1.0.5r [February 7, 2000]
+ Removed superfluous prototype for png_get_itxt from png.h
+ Fixed a bug in pngrtran.c that improperly expanded the background color.
+ Return *num_text=0 from png_get_text() when appropriate, and fix documentation
+ of png_get_text() in libpng.txt/libpng.3.
+version 1.0.5s [February 18, 2000]
+ Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the
+ new error handler that's planned for the next libpng release, and changed
+ example.c, pngtest.c, and contrib programs to use this macro.
+ Revised some of the DLL-export macros in pngconf.h (Greg Roelofs)
+ Fixed a bug in png_read_png() that caused it to fail to expand some images
+ that it should have expanded.
+ Fixed some mistakes in the unused and undocumented INCH_CONVERSIONS functions
+ in pngget.c
+ Changed the allocation of palette, history, and trans arrays back to
+ the version 1.0.5 method (linking instead of copying) which restores
+ backward compatibility with version 1.0.5. Added some remarks about
+ that in example.c. Added "free_me" member to info_ptr and png_ptr
+ and added png_free_data() function.
+ Updated makefile.linux and makefile.gccmmx to make directories conditionally.
+ Made cosmetic changes to pngasmrd.h
+ Added png_set_rows() and png_get_rows(), for use with png_read|write_png().
+ Modified png_read_png() to allocate info_ptr->row_pointers only if it
+ hasn't already been allocated.
+version 1.0.5t [March 4, 2000]
+ Changed png_jmp_env() migration aiding macro to png_jmpbuf().
+ Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c
+ Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when
+ PNG_FLAG_HAVE_CHUNK_HEADER was moved into png_ptr->mode in version 1.0.5b
+ Files in contrib/gregbook were revised to use png_jmpbuf() and to select
+ a 24-bit visual if one is available, and to allow abbreviated options.
+ Files in contrib/pngminus were revised to use the png_jmpbuf() macro.
+ Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s
+version 1.0.5u [March 5, 2000]
+ Simplified the code that detects old png.h in png.c and pngtest.c
+ Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp)
+ Increased precision of rgb_to_gray calculations from 8 to 15 bits and
+ added png_set_rgb_to_gray_fixed() function.
+ Added makefile.bc32 (32-bit Borland C++, C mode)
+version 1.0.5v [March 11, 2000]
+ Added some parentheses to the png_jmpbuf macro definition.
+ Updated references to the zlib home page, which has moved to freesoftware.com.
+ Corrected bugs in documentation regarding png_read_row() and png_write_row().
+ Updated documentation of png_rgb_to_gray calculations in libpng.3/libpng.txt.
+ Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3,
+ revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin)
+
+version 1.0.6 [March 20, 2000]
+ Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c
+ Added makefile.sggcc (SGI IRIX with gcc)
+version 1.0.6d [April 7, 2000]
+ Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO
+ Added data_length parameter to png_decompress_chunk() function
+ Revised documentation to remove reference to abandoned png_free_chnk functions
+ Fixed an error in png_rgb_to_gray_fixed()
+ Revised example.c, usage of png_destroy_write_struct().
+ Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file
+ Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c
+ Simplify png_sig_bytes() function to remove use of non-ISO-C strdup().
+version 1.0.6e [April 9, 2000]
+ Added png_data_freer() function.
+ In the code that checks for over-length tRNS chunks, added check of
+ info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann)
+ Minor revisions of libpng.txt/libpng.3.
+ Check for existing data and free it if the free_me flag is set, in png_set_*()
+ and png_handle_*().
+ Only define PNG_WEIGHTED_FILTERS_SUPPORTED when PNG_FLOATING_POINT_SUPPORTED
+ is defined.
+ Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c
+ and mentioned the purposes of the two macros in libpng.txt/libpng.3.
+version 1.0.6f [April 14, 2000]
+ Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data.
+ Add checks in png_set_text() for NULL members of the input text structure.
+ Revised libpng.txt/libpng.3.
+ Removed superfluous prototype for png_set_itxt from png.h
+ Removed "else" from pngread.c, after png_error(), and changed "0" to "length".
+ Changed several png_errors about malformed ancillary chunks to png_warnings.
+version 1.0.6g [April 24, 2000]
+ Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined.
+ Relocated paragraph about png_set_background() in libpng.3/libpng.txt
+ and other revisions (Matthias Benckmann)
+ Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and
+ png_ptr members to restore binary compatibility with libpng-1.0.5
+ (breaks compatibility with libpng-1.0.6).
+version 1.0.6h [April 24, 2000]
+ Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds
+ libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h)
+ This is a temporary change for test purposes.
+version 1.0.6i [May 2, 2000]
+ Rearranged some members at the end of png_info and png_struct, to put
+ unknown_chunks_num and free_me within the original size of the png_structs
+ and free_me, png_read_user_fn, and png_free_fn within the original png_info,
+ because some old applications allocate the structs directly instead of
+ using png_create_*().
+ Added documentation of user memory functions in libpng.txt/libpng.3
+ Modified png_read_png so that it will use user_allocated row_pointers
+ if present, unless free_me directs that it be freed, and added description
+ of the use of png_set_rows() and png_get_rows() in libpng.txt/libpng.3.
+ Added PNG_LEGACY_SUPPORTED macro, and #ifdef out all new (since version
+ 1.00) members of png_struct and png_info, to regain binary compatibility
+ when you define this macro. Capabilities lost in this event
+ are user transforms (new in version 1.0.0),the user transform pointer
+ (new in version 1.0.2), rgb_to_gray (new in 1.0.5), iCCP, sCAL, sPLT,
+ the high-level interface, and unknown chunks support (all new in 1.0.6).
+ This was necessary because of old applications that allocate the structs
+ directly as authors were instructed to do in libpng-0.88 and earlier,
+ instead of using png_create_*().
+ Added modes PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT which
+ can be used to detect codes that directly allocate the structs, and
+ code to check these modes in png_read_init() and png_write_init() and
+ generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED
+ was not defined.
+ Added makefile.intel and updated makefile.watcom (Pawel Mrochen)
+version 1.0.6j [May 3, 2000]
+ Overloaded png_read_init() and png_write_init() with macros that convert
+ calls to png_read_init_2() or png_write_init_2() that check the version
+ and structure sizes.
+version 1.0.7beta11 [May 7, 2000]
+ Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes
+ which are no longer used.
+ Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is
+ defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED
+ is defined.
+ Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory
+ overrun when old applications fill the info_ptr->text structure directly.
+ Added PNGAPI macro, and added it to the definitions of all exported functions.
+ Relocated version macro definitions ahead of the includes of zlib.h and
+ pngconf.h in png.h.
+version 1.0.7beta12 [May 12, 2000]
+ Revised pngset.c to avoid a problem with expanding the png_debug macro.
+ Deleted some extraneous defines from pngconf.h
+ Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined.
+ Use MSC _RPTn debugging instead of fprintf if _MSC_VER is defined.
+ Added png_access_version_number() function.
+ Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data().
+ Expanded libpng.3/libpng.txt information about png_data_freer().
+version 1.0.7beta14 [May 17, 2000] (beta13 was not published)
+ Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as
+ warnings instead of errors, as pngrutil.c does.
+ Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png()
+ will actually write IDATs.
+ Made the default PNG_USE_LOCAL_ARRAYS depend on PNG_DLL instead of WIN32.
+ Make png_free_data() ignore its final parameter except when freeing data
+ that can have multiple instances (text, sPLT, unknowns).
+ Fixed a new bug in png_set_rows().
+ Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5.
+ Added png_set_invalid() function.
+ Fixed incorrect illustrations of png_destroy_write_struct() in example.c.
+version 1.0.7beta15 [May 30, 2000]
+ Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce
+ fewer error messages.
+ Rearranged checks for Z_OK to check the most likely path first in pngpread.c
+ and pngwutil.c.
+ Added checks in pngtest.c for png_create_*() returning NULL, and mentioned
+ in libpng.txt/libpng.3 the need for applications to check this.
+ Changed names of png_default_*() functions in pngtest to pngtest_*().
+ Changed return type of png_get_x|y_offset_*() from png_uint_32 to png_int_32.
+ Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c
+ Set each pointer to NULL after freeing it in png_free_data().
+ Worked around a problem in pngconf.h; AIX's strings.h defines an "index"
+ macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos)
+ Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux).
+version 1.0.7beta16 [June 4, 2000]
+ Revised the workaround of AIX string.h "index" bug.
+ Added a check for overlength PLTE chunk in pngrutil.c.
+ Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer
+ indexing in pngrutil.c and pngwutil.c to accommodate a buggy compiler.
+ Added a warning in png_decompress_chunk() when it runs out of data, e.g.
+ when it tries to read an erroneous PhotoShop iCCP chunk.
+ Added PNG_USE_DLL macro.
+ Revised the copyright/disclaimer/license notice.
+ Added contrib/msvctest directory
+version 1.0.7rc1 [June 9, 2000]
+ Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200)
+ Added contrib/visupng directory (Willem van Schaik)
+version 1.0.7beta18 [June 23, 2000]
+ Revised PNGAPI definition, and pngvcrd.c to work with __GCC__
+ and do not redefine PNGAPI if it is passed in via a compiler directive.
+ Revised visupng/PngFile.c to remove returns from within the Try block.
+ Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros.
+ Updated contrib/visupng/cexcept.h to version 1.0.0.
+ Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks.
+version 1.0.7rc2 [June 28, 2000]
+ Updated license to include disclaimers required by UCITA.
+ Fixed "DJBPP" typo in pnggccrd.c introduced in beta18.
+
+version 1.0.7 [July 1, 2000]
+ Revised the definition of "trans_values" in libpng.3/libpng.txt
+version 1.0.8beta1 [July 8, 2000]
+ Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks.
+ Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and
+ pngwutil.c.
+ Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h.
+ Removed unused "#include <assert.h>" from png.c
+ Added WindowsCE support.
+ Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment.
+version 1.0.8beta2 [July 10, 2000]
+ Added project files to the wince directory and made further revisions
+ of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE.
+version 1.0.8beta3 [July 11, 2000]
+ Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS()
+ for indexed-color input files to avoid potential double-freeing trans array
+ under some unusual conditions; problem was introduced in version 1.0.6f.
+ Further revisions to pngtest.c and files in the wince subdirectory.
+version 1.0.8beta4 [July 14, 2000]
+ Added the files pngbar.png and pngbar.jpg to the distribution.
+ Added makefile.cygwin, and cygwin support in pngconf.h
+ Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory)
+version 1.0.8rc1 [July 16, 2000]
+ Revised png_debug() macros and statements to eliminate compiler warnings.
+
+version 1.0.8 [July 24, 2000]
+ Added png_flush() in pngwrite.c, after png_write_IEND().
+ Updated makefile.hpux to build a shared library.
+version 1.0.9beta1 [November 10, 2000]
+ Fixed typo in scripts/makefile.hpux
+ Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser)
+ Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser)
+ Changed "cdrom.com" in documentation to "libpng.org"
+ Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg).
+ Changed type of "params" from voidp to png_voidp in png_read|write_png().
+ Make sure PNGAPI and PNG_IMPEXP are defined in pngconf.h.
+ Revised the 3 instances of WRITEFILE in pngtest.c.
+ Relocated "msvc" and "wince" project subdirectories into "dll" subdirectory.
+ Updated png.rc in dll/msvc project
+ Revised makefile.dec to define and use LIBPATH and INCPATH
+ Increased size of global png_libpng_ver[] array from 12 to 18 chars.
+ Made global png_libpng_ver[], png_sig[] and png_pass_*[] arrays const.
+ Removed duplicate png_crc_finish() from png_handle_bKGD() function.
+ Added a warning when application calls png_read_update_info() multiple times.
+ Revised makefile.cygwin
+ Fixed bugs in iCCP support in pngrutil.c and pngwutil.c.
+ Replaced png_set_empty_plte_permitted() with png_permit_mng_features().
+version 1.0.9beta2 [November 19, 2000]
+ Renamed the "dll" subdirectory "projects".
+ Added borland project files to "projects" subdirectory.
+ Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate.
+ Add error message in png_set_compression_buffer_size() when malloc fails.
+version 1.0.9beta3 [November 23, 2000]
+ Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project.
+ Removed the png_flush() in pngwrite.c that crashes some applications
+ that don't set png_output_flush_fn.
+ Added makefile.macosx and makefile.aix to scripts directory.
+version 1.0.9beta4 [December 1, 2000]
+ Change png_chunk_warning to png_warning in png_check_keyword().
+ Increased the first part of msg buffer from 16 to 18 in png_chunk_error().
+version 1.0.9beta5 [December 15, 2000]
+ Added support for filter method 64 (for PNG datastreams embedded in MNG).
+version 1.0.9beta6 [December 18, 2000]
+ Revised png_set_filter() to accept filter method 64 when appropriate.
+ Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to
+ help prevent applications from using MNG features in PNG datastreams.
+ Added png_permit_mng_features() function.
+ Revised libpng.3/libpng.txt. Changed "filter type" to "filter method".
+version 1.0.9rc1 [December 23, 2000]
+ Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c
+ Fixed error handling of unknown compression type in png_decompress_chunk().
+ In pngconf.h, define __cdecl when _MSC_VER is defined.
+version 1.0.9beta7 [December 28, 2000]
+ Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places.
+ Revised memory management in png_set_hIST and png_handle_hIST in a backward
+ compatible manner. PLTE and tRNS were revised similarly.
+ Revised the iCCP chunk reader to ignore trailing garbage.
+version 1.0.9beta8 [January 12, 2001]
+ Moved pngasmrd.h into pngconf.h.
+ Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop.
+version 1.0.9beta9 [January 15, 2001]
+ Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to
+ wince and msvc project module definition files.
+ Minor revision of makefile.cygwin.
+ Fixed bug with progressive reading of narrow interlaced images in pngpread.c
+version 1.0.9beta10 [January 16, 2001]
+ Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined.
+ Fixed "png_mmx_supported" typo in project definition files.
+version 1.0.9beta11 [January 19, 2001]
+ Updated makefile.sgi to make shared library.
+ Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED
+ by default, for the benefit of DLL forward compatibility. These will
+ be re-enabled in version 1.2.0.
+version 1.0.9rc2 [January 22, 2001]
+ Revised cygwin support.
+
+version 1.0.9 [January 31, 2001]
+ Added check of cygwin's ALL_STATIC in pngconf.h
+ Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos.
+version 1.0.10beta1 [March 14, 2001]
+ Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc.
+ Reformatted libpng.3 to eliminate bad line breaks.
+ Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c
+ Added prototype for png_mmx_support() near the top of pnggccrd.c
+ Moved some error checking from png_handle_IHDR to png_set_IHDR.
+ Added PNG_NO_READ_SUPPORTED and PNG_NO_WRITE_SUPPORTED macros.
+ Revised png_mmx_support() function in pnggccrd.c
+ Restored version 1.0.8 PNG_WRITE_EMPTY_PLTE_SUPPORTED behavior in pngwutil.c
+ Fixed memory leak in contrib/visupng/PngFile.c
+ Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version)
+ Added warnings when retrieving or setting gamma=0.
+ Increased the first part of msg buffer from 16 to 18 in png_chunk_warning().
+version 1.0.10rc1 [March 23, 2001]
+ Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy,
+ and png_strlen.
+ Revised png_mmx_supported() function in pnggccrd.c to return proper value.
+ Fixed bug in progressive reading (pngpread.c) with small images (height < 8).
+
+version 1.0.10 [March 30, 2001]
+ Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin
+ Added beos project files (Chris Herborth)
+version 1.0.11beta1 [April 3, 2001]
+ Added type casts on several png_malloc() calls (Dimitri Papadapoulos).
+ Removed a no-longer needed AIX work-around from pngconf.h
+ Changed several "//" single-line comments to C-style in pnggccrd.c
+version 1.0.11beta2 [April 11, 2001]
+ Removed PNGAPI from several functions whose prototypes did not have PNGAPI.
+ Updated scripts/pngos2.def
+version 1.0.11beta3 [April 14, 2001]
+ Added checking the results of many instances of png_malloc() for NULL
+version 1.0.11beta4 [April 20, 2001]
+ Undid the changes from version 1.0.11beta3. Added a check for NULL return
+ from user's malloc_fn().
+ Removed some useless type casts of the NULL pointer.
+ Added makefile.netbsd
+
+version 1.0.11 [April 27, 2001]
+ Revised makefile.netbsd
+version 1.0.12beta1 [May 14, 2001]
+ Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot)
+ Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h
+ Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings.
+ Eliminated the png_error about apps using png_read|write_init(). Instead,
+ libpng will reallocate the png_struct and info_struct if they are too small.
+ This retains future binary compatibility for old applications written for
+ libpng-0.88 and earlier.
+version 1.2.0beta1 [May 6, 2001]
+ Bumped DLLNUM to 2.
+ Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED
+ by default.
+ Added runtime selection of MMX features.
+ Added png_set_strip_error_numbers function and related macros.
+version 1.2.0beta2 [May 7, 2001]
+ Finished merging 1.2.0beta1 with version 1.0.11
+ Added a check for attempts to read or write PLTE in grayscale PNG datastreams.
+version 1.2.0beta3 [May 17, 2001]
+ Enabled user memory function by default.
+ Modified png_create_struct so it passes user mem_ptr to user memory allocator.
+ Increased png_mng_features flag from png_byte to png_uint_32.
+ Bumped shared-library (so-number) and dll-number to 3.
+version 1.2.0beta4 [June 23, 2001]
+ Check for missing profile length field in iCCP chunk and free chunk_data
+ in case of truncated iCCP chunk.
+ Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc
+ Bumped dll-number from 2 to 3 in makefile.cygwin
+ Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly
+ if user attempts to run it on an 8-bit display.
+ Updated contrib/gregbook
+ Use png_malloc instead of png_zalloc to allocate palette in pngset.c
+ Updated makefile.ibmc
+ Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes
+ of png_write_oFFS width and height from png_uint_32 to png_int_32.
+ Updated example.c
+ Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c
+version 1.2.0beta5 [August 8, 2001]
+ Revised contrib/gregbook
+ Revised makefile.gcmmx
+ Revised pnggccrd.c to conditionally compile some thread-unsafe code only
+ when PNG_THREAD_UNSAFE_OK is defined.
+ Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with
+ value exceeding 2^bit_depth-1
+ Revised makefile.sgi and makefile.sggcc
+ Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c
+ Removed restriction that do_invert_mono only operate on 1-bit opaque files
+
+version 1.2.0 [September 1, 2001]
+ Changed a png_warning() to png_debug() in pnggccrd.c
+ Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC().
+version 1.2.1beta1 [October 19, 2001]
+ Revised makefile.std in contrib/pngminus
+ Include background_1 in png_struct regardless of gamma support.
+ Revised makefile.netbsd and makefile.macosx, added makefile.darwin.
+ Revised example.c to provide more details about using row_callback().
+version 1.2.1beta2 [October 25, 2001]
+ Added type cast to each NULL appearing in a function call, except for
+ WINCE functions.
+ Added makefile.so9.
+version 1.2.1beta3 [October 27, 2001]
+ Removed type casts from all NULLs.
+ Simplified png_create_struct_2().
+version 1.2.1beta4 [November 7, 2001]
+ Revised png_create_info_struct() and png_creat_struct_2().
+ Added error message if png_write_info() was omitted.
+ Type cast NULLs appearing in function calls when _NO_PROTO or
+ PNG_TYPECAST_NULL is defined.
+version 1.2.1rc1 [November 24, 2001]
+ Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL
+ is defined.
+ Changed typecast of "size" argument to png_size_t in pngmem.c calls to
+ the user malloc_fn, to agree with the prototype in png.h
+ Added a pop/push operation to pnggccrd.c, to preserve Eflag (Maxim Sobolev)
+ Updated makefile.sgi to recognize LIBPATH and INCPATH.
+ Updated various makefiles so "make clean" does not remove previous major
+ version of the shared library.
+version 1.2.1rc2 [December 4, 2001]
+ Always allocate 256-entry internal palette, hist, and trans arrays, to
+ avoid out-of-bounds memory reference caused by invalid PNG datastreams.
+ Added a check for prefix_length > data_length in iCCP chunk handler.
+
+version 1.2.1 [December 7, 2001]
+ None.
+version 1.2.2beta1 [February 22, 2002]
+ Fixed a bug with reading the length of iCCP profiles (Larry Reeves).
+ Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate
+ libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h
+ Revised makefile.darwin to remove "-undefined suppress" option.
+ Added checks for gamma and chromaticity values over 21474.83, which exceed
+ the limit for PNG unsigned 32-bit integers when encoded.
+ Revised calls to png_create_read_struct() and png_create_write_struct()
+ for simpler debugging.
+ Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK)
+version 1.2.2beta2 [February 23, 2002]
+ Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths.
+ Check for invalid image dimensions in png_get_IHDR.
+ Added missing "fi;" in the install target of the SGI makefiles.
+ Added install-static to all makefiles that make shared libraries.
+ Always do gamma compensation when image is partially transparent.
+version 1.2.2beta3 [March 7, 2002]
+ Compute background.gray and background_1.gray even when color_type is RGB
+ in case image gets reduced to gray later.
+ Modified shared-library makefiles to install pkgconfig/libpngNN.pc.
+ Export (with PNGAPI) png_zalloc, png_zfree, and png_handle_as_unknown
+ Removed unused png_write_destroy_info prototype from png.h
+ Eliminated incorrect use of width_mmx from pnggccrd.c in pixel_bytes == 8 case
+ Added install-shared target to all makefiles that make shared libraries.
+ Stopped a double free of palette, hist, and trans when not using free_me.
+ Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64.
+version 1.2.2beta4 [March 8, 2002]
+ Compute background.gray and background_1.gray even when color_type is RGB
+ in case image gets reduced to gray later (Jason Summers).
+ Relocated a misplaced /bin/rm in the "install-shared" makefile targets
+ Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library.
+version 1.2.2beta5 [March 26, 2002]
+ Added missing PNGAPI to several function definitions.
+ Check for invalid bit_depth or color_type in png_get_IHDR(), and
+ check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen).
+ Revised iTXt support to accept NULL for lang and lang_key.
+ Compute gamma for color components of background even when color_type is gray.
+ Changed "()" to "{}" in scripts/libpng.pc.in.
+ Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN
+ Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so
+version 1.2.2beta6 [March 31, 2002]
+version 1.0.13beta1 [March 31, 2002]
+ Prevent png_zalloc() from trying to memset memory that it failed to acquire.
+ Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate).
+ Ensure that the right function (user or default) is used to free the
+ png_struct after an error in png_create_read_struct_2().
+version 1.2.2rc1 [April 7, 2002]
+version 1.0.13rc1 [April 7, 2002]
+ Save the ebx register in pnggccrd.c (Sami Farin)
+ Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner).
+ Updated makefiles to put headers in include/libpng and remove old include/*.h.
+
+version 1.2.2 [April 15, 2002]
+version 1.0.13 [April 15, 2002]
+ Revised description of png_set_filter() in libpng.3/libpng.txt.
+ Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd
+version 1.0.13patch01 [April 17, 2002]
+version 1.2.2patch01 [April 17, 2002]
+ Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc
+ Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install
+ Added install: target to makefile.32sunu and makefile.64sunu
+version 1.0.13patch03 [April 18, 2002]
+version 1.2.2patch03 [April 18, 2002]
+ Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng
+ subdirectory to libpngNN subdirectory without the full pathname.
+ Moved generation of libpng.pc from "install" to "all" in 15 makefiles.
+version 1.2.3rc1 [April 28, 2002]
+ Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos).
+ Added $(DESTDIR) feature to 24 makefiles (Tim Mooney)
+ Fixed bug with $prefix, should be $(prefix) in makefile.hpux.
+ Updated cygwin-specific portion of pngconf.h and revised makefile.cygwin
+ Added a link from libpngNN.pc to libpng.pc in 15 makefiles.
+ Added links from include/libpngNN/*.h to include/*.h in 24 makefiles.
+ Revised makefile.darwin to make relative links without full pathname.
+ Added setjmp() at the end of png_create_*_struct_2() in case user forgets
+ to put one in their application.
+ Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and
+ removed them from module definition files.
+version 1.2.3rc2 [May 1, 2002]
+ Fixed bug in reporting number of channels in pngget.c and pngset.c,
+ that was introduced in version 1.2.2beta5.
+ Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(),
+ png_default_flush(), and png_push_fill_buffer() and included them in
+ module definition files.
+ Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles.
+version 1.2.3rc3 [May 1, 2002]
+ Revised prototype for png_default_flush()
+ Remove old libpng.pc and libpngNN.pc before installing new ones.
+version 1.2.3rc4 [May 2, 2002]
+ Typos in *.def files (png_default_read|write -> png_default_read|write_data)
+ In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc
+ Added libpng-config and libpngNN-config and modified makefiles to install them.
+ Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles
+ Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp
+version 1.2.3rc5 [May 11, 2002]
+ Changed "error" and "message" in prototypes to "error_message" and
+ "warning_message" to avoid namespace conflict.
+ Revised 15 makefiles to build libpng-config from libpng-config-*.in
+ Once more restored png_zalloc and png_zfree to regular nonexported form.
+ Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer
+ to nonexported form, but with PNGAPI, and removed them from module def files.
+version 1.2.3rc6 [May 14, 2002]
+ Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c
+ Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp.
+ Removed leftover libpng-config "sed" script from four makefiles.
+ Revised libpng-config creating script in 16 makefiles.
+
+version 1.2.3 [May 22, 2002]
+ Revised libpng-config target in makefile.cygwin.
+ Removed description of png_set_mem_fn() from documentation.
+ Revised makefile.freebsd.
+ Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR).
+ Revised projects/msvc/README.txt
+ Changed -lpng to -lpngNN in LDFLAGS in several makefiles.
+version 1.2.4beta1 [May 24, 2002]
+ Added libpng.pc and libpng-config to "all:" target in 16 makefiles.
+ Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH)
+ Added missing "\" before closing double quote in makefile.gcmmx.
+ Plugged various memory leaks; added png_malloc_warn() and png_set_text_2()
+ functions.
+version 1.2.4beta2 [June 25, 2002]
+ Plugged memory leak of png_ptr->current_text (Matt Holgate).
+ Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison)
+ Added -soname to the loader flags in makefile.dec, makefile.sgi, and
+ makefile.sggcc.
+ Added "test-installed" target to makefile.linux, makefile.gcmmx,
+ makefile.sgi, and makefile.sggcc.
+version 1.2.4beta3 [June 28, 2002]
+ Plugged memory leak of row_buf in pngtest.c when there is a png_error().
+ Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data.
+ Added "test-installed" target to makefile.32sunu, makefile.64sunu,
+ makefile.beos, makefile.darwin, makefile.dec, makefile.macosx,
+ makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9.
+version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002]
+ Added "test-installed" target to makefile.cygwin and makefile.sco.
+ Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro.
+
+version 1.2.4 and 1.0.14 [July 8, 2002]
+ Changed png_warning() to png_error() when width is too large to process.
+version 1.2.4patch01 [July 20, 2002]
+ Revised makefile.cygwin to use DLL number 12 instead of 13.
+version 1.2.5beta1 [August 6, 2002]
+ Added code to contrib/gregbook/readpng2.c to ignore unused chunks.
+ Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11)
+ Removed some stray *.o files from contrib/gregbook.
+ Changed png_error() to png_warning() about "Too much data" in pngpread.c
+ and about "Extra compressed data" in pngrutil.c.
+ Prevent png_ptr->pass from exceeding 7 in png_push_finish_row().
+ Updated makefile.hpgcc
+ Updated png.c and pnggccrd.c handling of return from png_mmx_support()
+version 1.2.5beta2 [August 15, 2002]
+ Only issue png_warning() about "Too much data" in pngpread.c when avail_in
+ is nonzero.
+ Updated makefiles to install a separate libpng.so.3 with its own rpath.
+version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002]
+ Revised makefiles to not remove previous minor versions of shared libraries.
+version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002]
+ Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared
+ library loader directive.
+ Added missing "$OBJSDLL" line to makefile.gcmmx.
+ Added missing "; fi" to makefile.32sunu.
+version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002]
+ Revised libpng-config script.
+
+version 1.2.5 and 1.0.15 [October 3, 2002]
+ Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux,
+ and makefile.aix.
+ Relocated two misplaced PNGAPI lines in pngtest.c
+version 1.2.6beta1 [October 22, 2002]
+ Commented out warning about uninitialized mmx_support in pnggccrd.c.
+ Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h.
+ Relocated two more misplaced PNGAPI lines in pngtest.c
+ Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams,
+ introduced in version 1.0.2.
+ Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu.
+version 1.2.6beta2 [November 1, 2002]
+ Added libpng-config "--ldopts" output.
+ Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)"
+ in makefiles.
+version 1.2.6beta3 [July 18, 2004]
+ Reverted makefile changes from version 1.2.6beta2 and some of the changes
+ from version 1.2.6beta1; these will be postponed until version 1.2.7.
+ Version 1.2.6 is going to be a simple bugfix release.
+ Changed the one instance of "ln -sf" to "ln -f -s" in each Sun makefile.
+ Fixed potential overrun in pngerror.c by using strncpy instead of memcpy.
+ Added "#!/bin/sh" at the top of configure, for recognition of the
+ 'x' flag under Cygwin (Cosmin).
+ Optimized vacuous tests that silence compiler warnings, in png.c (Cosmin).
+ Added support for PNG_USER_CONFIG, in pngconf.h (Cosmin).
+ Fixed the special memory handler for Borland C under DOS, in pngmem.c
+ (Cosmin).
+ Removed some spurious assignments in pngrutil.c (Cosmin).
+ Replaced 65536 with 65536L, and 0xffff with 0xffffL, to silence warnings
+ on 16-bit platforms (Cosmin).
+ Enclosed shift op expressions in parentheses, to silence warnings (Cosmin).
+ Used proper type png_fixed_point, to avoid problems on 16-bit platforms,
+ in png_handle_sRGB() (Cosmin).
+ Added compression_type to png_struct, and optimized the window size
+ inside the deflate stream (Cosmin).
+ Fixed definition of isnonalpha(), in pngerror.c and pngrutil.c (Cosmin).
+ Fixed handling of unknown chunks that come after IDAT (Cosmin).
+ Allowed png_error() and png_warning() to work even if png_ptr == NULL
+ (Cosmin).
+ Replaced row_info->rowbytes with row_bytes in png_write_find_filter()
+ (Cosmin).
+ Fixed definition of PNG_LIBPNG_VER_DLLNUM (Simon-Pierre).
+ Used PNG_LIBPNG_VER and PNG_LIBPNG_VER_STRING instead of the hardcoded
+ values in png.c (Simon-Pierre, Cosmin).
+ Initialized png_libpng_ver[] with PNG_LIBPNG_VER_STRING (Simon-Pierre).
+ Replaced PNG_LIBPNG_VER_MAJOR with PNG_LIBPNG_VER_DLLNUM in png.rc
+ (Simon-Pierre).
+ Moved the definition of PNG_HEADER_VERSION_STRING near the definitions
+ of the other PNG_LIBPNG_VER_... symbols in png.h (Cosmin).
+ Relocated #ifndef PNGAPI guards in pngconf.h (Simon-Pierre, Cosmin).
+ Updated scripts/makefile.vc(a)win32 (Cosmin).
+ Updated the MSVC project (Simon-Pierre, Cosmin).
+ Updated the Borland C++ Builder project (Cosmin).
+ Avoided access to asm_flags in pngvcrd.c, if PNG_1_0_X is defined (Cosmin).
+ Commented out warning about uninitialized mmx_support in pngvcrd.c (Cosmin).
+ Removed scripts/makefile.bd32 and scripts/pngdef.pas (Cosmin).
+ Added extra guard around inclusion of Turbo C memory headers, in pngconf.h
+ (Cosmin).
+ Renamed projects/msvc/ to projects/visualc6/, and projects/borland/ to
+ projects/cbuilder5/ (Cosmin).
+ Moved projects/visualc6/png32ms.def to scripts/pngw32.def,
+ and projects/visualc6/png.rc to scripts/pngw32.rc (Cosmin).
+ Added projects/visualc6/pngtest.dsp; removed contrib/msvctest/ (Cosmin).
+ Changed line endings to DOS style in cbuilder5 and visualc6 files, even
+ in the tar.* distributions (Cosmin).
+ Updated contrib/visupng/VisualPng.dsp (Cosmin).
+ Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin).
+ Added a separate distribution with "configure" and supporting files (Junichi).
+version 1.2.6beta4 [July 28, 2004]
+ Added user ability to change png_size_t via a PNG_SIZE_T macro.
+ Added png_sizeof() and png_convert_size() functions.
+ Added PNG_SIZE_MAX (maximum value of a png_size_t variable.
+ Added check in png_malloc_default() for (size_t)size != (png_uint_32)size
+ which would indicate an overflow.
+ Changed sPLT failure action from png_error to png_warning and abandon chunk.
+ Changed sCAL and iCCP failures from png_error to png_warning and abandon.
+ Added png_get_uint_31(png_ptr, buf) function.
+ Added PNG_UINT_32_MAX macro.
+ Renamed PNG_MAX_UINT to PNG_UINT_31_MAX.
+ Made png_zalloc() issue a png_warning and return NULL on potential
+ overflow.
+ Turn on PNG_NO_ZALLOC_ZERO by default in version 1.2.x
+ Revised "clobber list" in pnggccrd.c so it will compile under gcc-3.4.
+ Revised Borland portion of png_malloc() to return NULL or issue
+ png_error() according to setting of PNG_FLAG_MALLOC_NULL_MEM_OK.
+ Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove
+ sequential read support.
+ Added some "#if PNG_WRITE_SUPPORTED" blocks.
+ Removed some redundancy with #ifdef/#endif in png_malloc_default().
+ Use png_malloc instead of png_zalloc to allocate the pallete.
+version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004]
+ Fixed buffer overflow vulnerability in png_handle_tRNS()
+ Fixed integer arithmetic overflow vulnerability in png_read_png().
+ Fixed some harmless bugs in png_handle_sBIT, etc, that would cause
+ duplicate chunk types to go undetected.
+ Fixed some timestamps in the -config version
+ Rearranged order of processing of color types in png_handle_tRNS().
+ Added ROWBYTES macro to calculate rowbytes without integer overflow.
+ Updated makefile.darwin and removed makefile.macosx from scripts directory.
+ Imposed default one million column, one-million row limits on the image
+ dimensions, and added png_set_user_limits() function to override them.
+ Revised use of PNG_SET_USER_LIMITS_SUPPORTED macro.
+ Fixed wrong cast of returns from png_get_user_width|height_max().
+ Changed some "keep the compiler happy" from empty statements to returns,
+ Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution
+version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004]
+ Revised makefile.darwin and makefile.solaris. Removed makefile.macosx.
+ Revised pngtest's png_debug_malloc() to use png_malloc() instead of
+ png_malloc_default() which is not supposed to be exported.
+ Fixed off-by-one error in one of the conversions to PNG_ROWBYTES() in
+ pngpread.c. Bug was introduced in 1.2.6rc1.
+ Fixed bug in RGB to RGBX transformation introduced in 1.2.6rc1.
+ Fixed old bug in RGB to Gray transformation.
+ Fixed problem with 64-bit compilers by casting arguments to abs()
+ to png_int_32.
+ Changed "ln -sf" to "ln -f -s" in three makefiles (solaris, sco, so9).
+ Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin)
+ Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles.
+ Added code to update the row_info->colortype in png_do_read_filler() (MSB).
+version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004]
+ Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid
+ trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro.
+ Revised documentation of png_set_keep_unknown_chunks().
+ Check handle_as_unknown status in pngpread.c, as in pngread.c previously.
+ Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h
+ Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c
+version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004]
+ Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of
+ "pinfo" was out of place).
+version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004]
+ Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED
+ section of png.h where they were inadvertently placed in version rc3.
+
+version 1.2.6 and 1.0.16 [August 15, 2004]
+ Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1.
+version 1.2.7beta1 [August 26, 2004]
+ Removed unused pngasmrd.h file.
+ Removed references to uu.net for archived files. Added references to
+ PNG Spec (second edition) and the PNG ISO/IEC Standard.
+ Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR.
+ Fixed bug with "optimized window size" in the IDAT datastream, that
+ causes libpng to write PNG files with incorrect zlib header bytes.
+version 1.2.7beta2 [August 28, 2004]
+ Fixed bug with sCAL chunk and big-endian machines (David Munro).
+ Undid new code added in 1.2.6rc2 to update the color_type in
+ png_set_filler().
+ Added png_set_add_alpha() that updates color type.
+version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004]
+ Revised png_set_strip_filler() to not remove alpha if color_type has alpha.
+
+version 1.2.7 and 1.0.17 [September 12, 2004]
+ Added makefile.hp64
+ Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin
+version 1.2.8beta1 [November 1, 2004]
+ Fixed bug in png_text_compress() that would fail to complete a large block.
+ Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during
+ strip alpha operation in png_do_strip_filler().
+ Added PNG_1_2_X definition in pngconf.h
+ Comment out with #ifdef/#endif png_info_init in png.c and png_read_init
+ in pngread.c (as of 1.3.0)
+version 1.2.8beta2 [November 2, 2004]
+ Reduce color_type to a nonalpha type after strip alpha operation in
+ png_do_strip_filler().
+version 1.2.8beta3 [November 3, 2004]
+ Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM
+version 1.2.8beta4 [November 12, 2004]
+ Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin).
+ Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin).
+ Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection
+ of data type in deflate (Cosmin).
+ Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of
+ PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING.
+version 1.2.8beta5 [November 20, 2004]
+ Use png_ptr->flags instead of png_ptr->transformations to pass
+ PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI
+ compatibility.
+ Revised handling of SPECIALBUILD, PRIVATEBUILD,
+ PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING.
+version 1.2.8rc1 [November 24, 2004]
+ Moved handling of BUILD macros from pngconf.h to png.h
+ Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently
+ omitted from beta5.
+ Revised scripts/pngw32.rc
+ Despammed mailing addresses by masking "@" with "at".
+ Inadvertently installed a supposedly faster test version of pngrutil.c
+version 1.2.8rc2 [November 26, 2004]
+ Added two missing "\" in png.h
+ Change tests in pngread.c and pngpread.c to
+ if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
+ png_do_read_transformations(png_ptr);
+version 1.2.8rc3 [November 28, 2004]
+ Reverted pngrutil.c to version libpng-1.2.8beta5.
+ Added scripts/makefile.elf with supporting code in pngconf.h for symbol
+ versioning (John Bowler).
+version 1.2.8rc4 [November 29, 2004]
+ Added projects/visualc7 (Simon-pierre).
+version 1.2.8rc5 [November 29, 2004]
+ Fixed new typo in scripts/pngw32.rc
+
+version 1.2.8 [December 3, 2004]
+ Removed projects/visualc7, added projects/visualc71.
+
+version 1.2.9beta1 [February 21, 2006]
+
+ Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints
+ Revised man page and libpng.txt to make it clear that one should not call
+ png_read_end or png_write_end after png_read_png or png_write_png.
+ Updated references to png-mng-implement mailing list.
+ Fixed an incorrect typecast in pngrutil.c
+ Added PNG_NO_READ_SUPPORTED conditional for making a write-only library.
+ Added PNG_NO_WRITE_INTERLACING_SUPPORTED conditional.
+ Optimized alpha-inversion loops in pngwtran.c
+ Moved test for nonzero gamma outside of png_build_gamma_table() in pngrtran.c
+ Make sure num_trans is <= 256 before copying data in png_set_tRNS().
+ Make sure num_palette is <= 256 before copying data in png_set_PLTE().
+ Interchanged order of write_swap_alpha and write_invert_alpha transforms.
+ Added parentheses in the definition of PNG_LIBPNG_BUILD_TYPE (Cosmin).
+ Optimized zlib window flag (CINFO) in contrib/pngsuite/*.png (Cosmin).
+ Updated scripts/makefile.bc32 for Borland C++ 5.6 (Cosmin).
+ Exported png_get_uint_32, png_save_uint_32, png_get_uint_16, png_save_uint_16,
+ png_get_int_32, png_save_int_32, png_get_uint_31 (Cosmin).
+ Added type cast (png_byte) in png_write_sCAL() (Cosmin).
+ Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin).
+ Default iTXt support was inadvertently enabled.
+
+version 1.2.9beta2 [February 21, 2006]
+
+ Check for png_rgb_to_gray and png_gray_to_rgb read transformations before
+ checking for png_read_dither in pngrtran.c
+ Revised checking of chromaticity limits to accommodate extended RGB
+ colorspace (John Denker).
+ Changed line endings in some of the project files to CRLF, even in the
+ "Unix" tar distributions (Cosmin).
+ Made png_get_int_32 and png_save_int_32 always available (Cosmin).
+ Updated scripts/pngos2.def, scripts/pngw32.def and projects/wince/png32ce.def
+ with the newly exported functions.
+ Eliminated distributions without the "configure" script.
+ Updated INSTALL instructions.
+
+version 1.2.9beta3 [February 24, 2006]
+
+ Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp
+ Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler)
+ Removed reference to pngasmrd.h from Makefile.am
+ Renamed CHANGES to ChangeLog.
+ Renamed LICENSE to COPYING.
+ Renamed ANNOUNCE to NEWS.
+ Created AUTHORS file.
+
+version 1.2.9beta4 [March 3, 2006]
+
+ Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac
+ Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING.
+ Removed newline from the end of some error and warning messages.
+ Removed test for sqrt() from configure.ac and configure.
+ Made swap tables in pngtrans.c PNG_CONST (Carlo Bramix).
+ Disabled default iTXt support that was inadvertently enabled in
+ libpng-1.2.9beta1.
+ Added "OS2" to list of systems that don't need underscores, in pnggccrd.c
+ Removed libpng version and date from *.c files.
+
+version 1.2.9beta5 [March 4, 2006]
+ Removed trailing blanks from source files.
+ Put version and date of latest change in each source file, and changed
+ copyright year accordingly.
+ More cleanup of configure.ac, Makefile.am, and associated scripts.
+ Restored scripts/makefile.elf which was inadvertently deleted.
+
+version 1.2.9beta6 [March 6, 2006]
+ Fixed typo (RELEASE) in configuration files.
+
+version 1.2.9beta7 [March 7, 2006]
+ Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am
+ Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s()
+ in png.h.
+ Updated makefile.elf as suggested by debian.
+ Made cosmetic changes to some makefiles, adding LN_SF and other macros.
+ Made some makefiles accept "exec_prefix".
+
+version 1.2.9beta8 [March 9, 2006]
+ Fixed some "#if defined (..." which should be "#if defined(..."
+ Bug introduced in libpng-1.2.8.
+ Fixed inconsistency in definition of png_default_read_data()
+ Restored blank that was lost from makefile.sggcc "clean" target in beta7.
+ Revised calculation of "current" and "major" for irix in ltmain.sh
+ Changed "mkdir" to "MKDIR_P" in some makefiles.
+ Separated PNG_EXPAND and PNG_EXPAND_tRNS.
+ Added png_set_expand_gray_1_2_4_to_8() and deprecated
+ png_set_gray_1_2_4_to_8() which also expands tRNS to alpha.
+
+version 1.2.9beta9 [March 10, 2006]
+ Include "config.h" in pngconf.h when available.
+ Added some checks for NULL png_ptr or NULL info_ptr (timeless)
+
+version 1.2.9beta10 [March 20, 2006]
+ Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin)
+ Made pnggccrd.c PIC-compliant (Christian Aichinger).
+ Added makefile.mingw (Wolfgang Glas).
+ Revised pngconf.h MMX checking.
+
+version 1.2.9beta11 [March 22, 2006]
+ Fixed out-of-order declaration in pngwrite.c that was introduced in beta9
+ Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros.
+
+version 1.2.9rc1 [March 31, 2006]
+ Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin).
+ Removed nonsensical assertion check from pngtest.c (Cosmin).
+
+version 1.2.9 [April 14, 2006]
+ Revised makefile.beos and added "none" selector in ltmain.sh
+
+version 1.2.10beta1 [April 15, 2006]
+ Renamed "config.h" to "png_conf.h" and revised Makefile.am to add
+ -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h
+ to include png_conf.h only when PNG_BUILDING_LIBPNG is defined.
+
+version 1.2.10beta2 [April 15, 2006]
+ Manually updated Makefile.in and configure. Changed png_conf.h.in
+ back to config.h.
+
+version 1.2.10beta3 [April 15, 2006]
+ Change png_conf.h back to config.h in pngconf.h.
+
+version 1.2.10beta4 [April 16, 2006]
+ Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*.
+
+version 1.2.10beta5 [April 16, 2006]
+ Added a configure check for compiling assembler code in pnggccrd.c
+
+version 1.2.10beta6 [April 17, 2006]
+ Revised the configure check for pnggccrd.c
+ Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@
+ Added @LIBPNG_DEFINES@ to arguments when building libpng.sym
+
+version 1.2.10beta7 [April 18, 2006]
+ Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles.
+
+version 1.2.10rc1 [April 19, 2006]
+ Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD
+ Fixed "LN_FS" typo in makefile.sco and makefile.solaris.
+
+version 1.2.10rc2 [April 20, 2006]
+ Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE
+ in configure.ac and configure
+ Made the configure warning about versioned symbols less arrogant.
+
+version 1.2.10rc3 [April 21, 2006]
+ Added a note in libpng.txt that png_set_sig_bytes(8) can be used when
+ writing an embedded PNG without the 8-byte signature.
+ Revised makefiles and configure to avoid making links to libpng.so.*
+
+version 1.2.10 [April 23, 2006]
+ Reverted configure to "rc2" state.
+
+version 1.2.11beta1 [May 31, 2006]
+ scripts/libpng.pc.in contained "configure" style version info and would
+ not work with makefiles.
+ The shared-library makefiles were linking to libpng.so.0 instead of
+ libpng.so.3 compatibility as the library.
+
+version 1.2.11beta2 [June 2, 2006]
+ Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid
+ buffer overflow.
+ Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb)
+
+version 1.2.11beta3 [June 5, 2006]
+ Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin).
+ Removed the accidental leftover Makefile.in~ (Cosmin).
+ Avoided potential buffer overflow and optimized buffer in
+ png_write_sCAL(), png_write_sCAL_s() (Cosmin).
+ Removed the include directories and libraries from CFLAGS and LDFLAGS
+ in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin).
+
+version 1.2.11beta4 [June 6, 2006]
+ Allow zero-length IDAT chunks after the entire zlib datastream, but not
+ after another intervening chunk type.
+
+version 1.0.19rc1, 1.2.11rc1 [June 13, 2006]
+ Deleted extraneous square brackets from [config.h] in configure.ac
+
+version 1.0.19rc2, 1.2.11rc2 [June 14, 2006]
+ Added prototypes for PNG_INCH_CONVERSIONS functions to png.h
+ Revised INSTALL and autogen.sh
+ Fixed typo in several makefiles (-W1 should be -Wl)
+ Added typedef for png_int_32 and png_uint_32 on 64-bit systems.
+
+version 1.0.19rc3, 1.2.11rc3 [June 15, 2006]
+ Removed the new typedefs for 64-bit systems (delay until version 1.4.0)
+ Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid
+ reading out of bounds.
+
+version 1.0.19rc4, 1.2.11rc4 [June 15, 2006]
+ Really removed the new typedefs for 64-bit systems.
+
+version 1.0.19rc5, 1.2.11rc5 [June 22, 2006]
+ Removed png_sig_bytes entry from scripts/pngw32.def
+
+version 1.0.19, 1.2.11 [June 26, 2006]
+ None.
+
+version 1.0.20, 1.2.12 [June 27, 2006]
+ Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid
+ buffer overflow.
+
+version 1.2.13beta1 [October 2, 2006]
+ Removed AC_FUNC_MALLOC from configure.ac
+ Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h
+ Change "logical" to "bitwise" throughout documentation.
+ Detect and fix attempt to write wrong iCCP profile length.
+
+version 1.0.21, 1.2.13 [November 14, 2006]
+ Fix potential buffer overflow in sPLT chunk handler.
+ Fix Makefile.am to not try to link to noexistent files.
+ Check all exported functions for NULL png_ptr.
+
+version 1.2.14beta1 [November 17, 2006]
+ Relocated three misplaced tests for NULL png_ptr.
+ Built Makefile.in with automake-1.9.6 instead of 1.9.2.
+ Build configure with autoconf-2.60 instead of 2.59
+
+version 1.2.14beta2 [November 17, 2006]
+ Added some typecasts in png_zalloc().
+
+version 1.2.14rc1 [November 20, 2006]
+ Changed "strtod" to "png_strtod" in pngrutil.c
+
+version 1.0.22, 1.2.14 [November 27, 2006]
+ Added missing "$(srcdir)" in Makefile.am and Makefile.in
+
+version 1.2.15beta1 [December 3, 2006]
+ Generated configure with autoconf-2.61 instead of 2.60
+ Revised configure.ac to update libpng.pc and libpng-config.
+
+version 1.2.15beta2 [December 3, 2006]
+ Always export MMX asm functions, just stubs if not building pnggccrd.c
+
+version 1.2.15beta3 [December 4, 2006]
+ Add "png_bytep" typecast to profile while calculating length in pngwutil.c
+
+version 1.2.15beta4 [December 7, 2006]
+ Added scripts/CMakeLists.txt
+ Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta
+
+version 1.2.15beta5 [December 7, 2006]
+ Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c
+ Revised scripts/CMakeLists.txt
+
+version 1.2.15beta6 [December 13, 2006]
+ Revised scripts/CMakeLists.txt and configure.ac
+
+version 1.2.15rc1 [December 18, 2006]
+ Revised scripts/CMakeLists.txt
+
+version 1.2.15rc2 [December 21, 2006]
+ Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers.
+ Added scripts/makefile.nommx
+
+version 1.2.15rc3 [December 25, 2006]
+ Fixed shared library numbering error that was introduced in 1.2.15beta6.
+
+version 1.2.15rc4 [December 27, 2006]
+ Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set.
+
+version 1.2.15rc5 [December 31, 2006]
+ Revised handling of rgb_to_gray.
+
+version 1.0.23, 1.2.15 [January 5, 2007]
+ Added some (unsigned long) typecasts in pngtest.c to avoid printing errors.
+
+version 1.2.16beta1 [January 6, 2007]
+ Fix bugs in makefile.nommx
+
+version 1.2.16beta2 [January 16, 2007]
+ Revised scripts/CMakeLists.txt
+
+version 1.0.24, 1.2.16 [January 31, 2007]
+ No changes.
+
+version 1.2.17beta1 [March 6, 2007]
+ Revised scripts/CMakeLists.txt to install both shared and static libraries.
+ Deleted a redundant line from pngset.c.
+
+version 1.2.17beta2 [April 26, 2007]
+ Relocated misplaced test for png_ptr == NULL in pngpread.c
+ Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN
+ flags.
+ Changed remaining instances of PNG_ASSEMBLER_* to PNG_MMX_*
+ Added pngerror() when write_IHDR fails in deflateInit2().
+ Added "const" to some array declarations.
+ Mention examples of libpng usage in the libpng*.txt and libpng.3 documents.
+
+version 1.2.17rc1 [May 4, 2007]
+ No changes.
+
+version 1.2.17rc2 [May 8, 2007]
+ Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications
+ calling set_unknown_chunk_location() need them.
+ Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in
+ png_set_expand_gray_1_2_4_to_8().
+ Added png_ptr->unknown_chunk to hold working unknown chunk data, so it
+ can be free'ed in case of error. Revised unknown chunk handling in
+ pngrutil.c and pngpread.c to use this structure.
+
+version 1.2.17rc3 [May 8, 2007]
+ Revised symbol-handling in configure script.
+
+version 1.2.17rc4 [May 10, 2007]
+ Revised unknown chunk handling to avoid storing unknown critical chunks.
+
+version 1.0.25 [May 15, 2007]
+version 1.2.17 [May 15, 2007]
+ Added "png_ptr->num_trans=0" before error return in png_handle_tRNS,
+ to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664)
+
+version 1.0.26 [May 15, 2007]
+version 1.2.18 [May 15, 2007]
+ Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script
+
+version 1.2.19beta1 [May 18, 2007]
+ Changed "const static" to "static PNG_CONST" everywhere, mostly undoing
+ change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST"
+ Changed some handling of unused parameters, to avoid compiler warnings.
+ "if (unused == NULL) return;" becomes "unused = unused".
+
+version 1.2.19beta2 [May 18, 2007]
+ Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier)
+
+version 1.2.19beta3 [May 19, 2007]
+ Add some "png_byte" typecasts in png_check_keyword() and write new_key
+ instead of key in zTXt chunk (Kevin Ryde).
+
+version 1.2.19beta4 [May 21, 2007]
+ Add png_snprintf() function and use it in place of sprint() for improved
+ defense against buffer overflows.
+
+version 1.2.19beta5 [May 21, 2007]
+ Fixed png_handle_tRNS() to only use the valid bits of tRNS value.
+ Changed handling of more unused parameters, to avoid compiler warnings.
+ Removed some PNG_CONST in pngwutil.c to avoid compiler warnings.
+
+version 1.2.19beta6 [May 22, 2007]
+ Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c
+ Added a special "_MSC_VER" case that defines png_snprintf to _snprintf
+
+version 1.2.19beta7 [May 22, 2007]
+ Squelched png_squelch_warnings() in pnggccrd.c and added
+ an #ifdef PNG_MMX_CODE_SUPPORTED/#endif block around the declarations
+ that caused the warnings that png_squelch_warnings was squelching.
+
+version 1.2.19beta8 [May 22, 2007]
+ Removed __MMX__ from test in pngconf.h.
+
+version 1.2.19beta9 [May 23, 2007]
+ Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro.
+ Revised png_squelch_warnings() so it might work.
+ Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86.
+
+version 1.2.19beta10 [May 24, 2007]
+ Resquelched png_squelch_warnings(), use "__attribute__((used))" instead.
+
+version 1.2.19beta11 [May 28, 2007]
+ Return 0 from png_get_sPLT() and png_get_unknown_chunks() if png_ptr is NULL;
+ changed three remaining instances of png_strcpy() to png_strncpy() (David
+ Hill).
+ Make test for NULL row_buf at the beginning of png_do_read_transformations
+ unconditional.
+
+version 1.2.19beta12 [May 28, 2007]
+ Revised pnggccrd.c.
+
+version 1.2.19beta13 [June 14, 2007]
+ Prefer PNG_USE_PNGVCRD when _MSC_VER is defined in pngconf.h
+
+version 1.2.19beta14 [June 16, 2007]
+ Fix bug with handling of 16-bit transparency, introduced in 1.2.19beta2
+
+version 1.2.19beta15 [June 17, 2007]
+ Revised pnggccrd.c.
+
+version 1.2.19beta16 [June 18, 2007]
+ Revised pnggccrd.c again.
+ Updated contrib/gregbook.
+ Changed '#include "pnggccrd.c"' to 'include "$srcdir/pnggccrd.c"'
+ in configure.ac
+
+version 1.2.19beta17 [June 19, 2007]
+ Revised many of the makefiles, to set -DPNG_NO_MMX_CODE where needed
+ and to not use -O3 unless -DPNG_NO_MMX_CODE is also set.
+
+version 1.2.19beta18 [June 23, 2007]
+ Replaced some C++ style comments with C style comments in pnggccrd.c.
+ Copied optimized C code from pnggccrd.c to pngrutil.c, removed dependency
+ on pnggccrd.o from many makefiles.
+ Added sl and dylib to list of extensions be installed by Makefile.am
+
+version 1.2.19beta19 [June 28, 2007]
+ Fixed testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN in pngrtran.c
+ More cleanup of pnggccrd.c and pngvcrd.c
+
+version 1.2.19beta20 [June 29, 2007]
+ Rebuilt Makefile.in and configure using libtool-1.5.24.
+ Fixed typo in pnggccrd.c
+
+version 1.2.19beta21 [June 30, 2007]
+ More revision of pnggccrd.c
+ Added "test" target to Makefile.in and Makefile.am
+
+version 1.2.19beta22 [July 3, 2007]
+ Added info about pngrutil/pnggccrd/pngvcrd to png_get_header_version()
+ Fix type definition of dummy_value_a, b in pnggccrd.c
+
+version 1.2.19beta23 [July 10, 2007]
+ Revert change to type definition of dummy_value_a, b in pnggccrd.c
+ Make sure __PIC__ is defined in pnggccrd.c when PIC is defined.
+ Require gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW on x86_64 platforms
+
+version 1.2.19beta24 [July 14, 2007]
+ Added PNG_NO_READ_FILTER, PNG_NO_WRITE_FILTER, PNG_NO_WARNING macros.
+ Added contrib/pngminim to demonstrate building minimal encoder and decoder
+
+version 1.2.19beta25 [July 15, 2007]
+ Removed the new PNG_NO_READ_FILTER macro since it would make the library
+ unable to read valid PNG files, and filtering is at the heart of the
+ PNG format.
+
+version 1.2.19beta26 [July 16, 2007]
+ Changed "png_free(str)" to "png_free(png_ptr,str)" in pngrutil.c WinCE
+ code (Yves Piguet). This bug was introduced in libpng-1.2.14.
+ Updated scripts/CMakeLists.txt
+ Relocated a misplaced #endif in pnggccrd.c
+
+version 1.2.19beta27 [July 17, 2007]
+ Fixed incorrect stride and number of bytes copied (was 4 instead of
+ 6 bytes) in the cleanup loop of pnggccrd.c and pngvcrd.c for handling
+ the end of 48-bit interlaced rows (Glenn R-P).
+
+version 1.2.19beta28 [July 19, 2007]
+ Removed requirement for gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW
+ on x86_64 platforms
+ Added png_warning() in pngrutil.c for short iCCP, iTXt, sPLT, or zTXT chunks.
+ Revised pngtest.c so warnings are displayed regardless of PNG_NO_STDIO.
+
+version 1.2.19beta29 [July 20, 2007]
+ Fix typo in pnggccrd.c (%%eax should be %%ax in secondloop48)
+
+version 1.2.19beta30 [July 26, 2007]
+ Revised pnggccrd.c
+
+version 1.2.19beta31 [July 27, 2007]
+ Fix typos in pnggccrd.c
+
+version 1.0.27rc1 and 1.2.19rc1 [July 31, 2007]
+ Disable PNG_MMX_CODE_SUPPORTED when PNG_ASSEMBLER_CODE_SUPPORTED is off.
+ Enable PNG_MMX_READ_FILTER_* by default, except when gcc-3.x is being
+ used (they were inadvertently disabled in libpng-1.2.19beta23).
+ Fix some debugging statements in pnggccrd.c and pngrutil.c
+ Added information about disabling the MMX code in libpng documentation.
+
+version 1.0.27rc2 and 1.2.19rc2 [August 4, 2007]
+ Removed some "#if 0" blocks.
+ Made a global struct local in pngvcrd.c to make it thread safe.
+ Issue a png_error() if application attempts to transform a row tht
+ has not been initialized.
+
+version 1.0.27rc3 and 1.2.19rc3 [August 9, 2007]
+ Slightly revised pngvcrd.c
+
+version 1.0.27rc4 and 1.2.19rc4 [August 9, 2007]
+ Revised pnggccrd.c debugging change of rc1, which was broken.
+ Revised scripts/CMakeLists.txt
+ Change default to PNG_NO_GLOBAL_ARRAYS for MSVC.
+ Turn off PNG_FLAG_ROW_INIT flag when setting transforms that expand pixels.
+
+version 1.0.27rc5 and 1.2.19rc5 [August 10, 2007]
+ Fix typo (missing '"') in pnggccrd.c
+ Revise handling of png_strtod in recent versions of WINCE
+
+version 1.0.27rc6 and 1.2.19rc6 [August 15, 2007]
+ Fix typo (missing ',') in contrib/gregbook/readpng2.c
+ Undid row initialization error exit added to rc2 and rc4.
+
+version 1.0.27 and 1.2.19 [August 18, 2007]
+ Conditionally restored row initialization error exit.
+
+version 1.2.20beta01 [August 19, 2007]
+ Fixed problem with compiling pnggccrd.c on Intel-Apple platforms.
+ Changed png_malloc() to png_malloc_warn() in png_set_sPLT().
+ Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim
+ Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */
+ because it caused some trouble.
+
+version 1.2.20beta02 [August 20, 2007]
+ Avoid compiling pnggccrd.c on Intel-Apple platforms.
+
+version 1.2.20beta03 [August 20, 2007]
+ Added "/D PNG_NO_MMX_CODE" to the non-mmx builds of projects/visualc6
+ and visualc71.
+
+version 1.2.20beta04 [August 21, 2007]
+ Revised pngvcrd.c for improved efficiency (Steve Snyder).
+
+version 1.2.20rc1 [August 23, 2007]
+ Revised pngconf.h to set PNG_NO_MMX_CODE for gcc-3.x compilers.
+
+version 1.2.20rc2 [August 27, 2007]
+ Revised scripts/CMakeLists.txt
+ Revised #ifdefs to ensure one and only one of pnggccrd.c, pngvcrd.c,
+ or part of pngrutil.c is selected.
+
+version 1.2.20rc3 [August 30, 2007]
+ Remove a little more code in pngwutil.c when PNG_NO_WRITE_FILTER is selected.
+ Added /D _CRT_SECURE_NO_WARNINGS to visual6c and visualc71 projects.
+ Compile png_mmx_support() in png.c even when PNG_NO_MMX_CODE is defined.
+ Restored a "superfluous" #ifdef that was removed from 1.2.20rc2 pnggccrd.c,
+ breaking the png_mmx_support() function.
+
+version 1.2.20rc4 [September 1, 2007]
+ Removed Intel contributions (MMX, Optimized C).
+
+version 1.2.20rc5 [September 2, 2007]
+ Restored configure and Makefile.in to rc3 and put a snippet of code in
+ pnggccrd.c, to ensure configure makes the same PNG_NO_MMX_CODE selection
+
+version 1.2.20rc6 [September 2, 2007]
+ Fixed bugs in scripts/CMakeLists.txt
+ Removed pngvcrd.c references from msvc projects.
+
+version 1.0.28 and 1.2.20 [September 8, 2007]
+ Removed "(NO READ SUPPORT)" from png_get_header_version() string.
+
+version 1.2.21beta1 [September 14, 2007]
+ Fixed various mistakes reported by George Cook and Jeff Phillips:
+ logical vs bitwise NOT in pngrtran.c, bug introduced in 1.2.19rc2
+ 16-bit cheap transparency expansion, bug introduced in 1.2.19beta2
+ errors with sizeof(unknown_chunk.name), bugs introduced in 1.2.19beta11
+ <= compare with unsigned var in pngset.c, should be ==.
+
+version 1.2.21beta2 [September 18, 2007]
+ Removed some extraneous typecasts.
+
+version 1.2.21rc1 [September 25, 2007]
+ Fixed potential out-of-bounds reads in png_handle_pCAL() and
+ png_handle_ztXt() ("flayer" results reported by Tavis Ormandy).
+
+version 1.2.21rc2 [September 26, 2007]
+ Fixed potential out-of-bounds reads in png_handle_sCAL(),
+ png_handle_iTXt(), and png_push_read_tEXt().
+ Remove some PNG_CONST declarations from pngwutil.c to avoid compiler warnings
+ Revised makefiles to update paths in libpng.pc properly.
+
+version 1.2.21rc3 [September 27, 2007]
+ Revised makefiles to update "Libs" in libpng.pc properly.
+
+version 1.0.29 and 1.2.21rc3 [October 4, 2007]
+ No changes.
+
+version 1.2.22beta1 [October 4, 2007]
+ Again, fixed logical vs bitwise NOT in pngrtran.c, bug introduced
+ in 1.2.19rc2
+
+version 1.2.22beta2 [October 5, 2007]
+ Fixed string length error in pngset.c (caused crashes while decoding iCCP)
+ Add terminating NULL after each instance of png_strncpy().
+
+version 1.2.22beta3 [October 6, 2007]
+ Fix two off-by-one terminating NULL after png_strncpy().
+
+version 1.2.22beta4 [October 7, 2007]
+ Changed some 0 to '\0'.
+
+version 1.0.30rc1 and 1.2.22rc1 [October 8, 2007]
+ No changes.
+
+version 1.0.30 and 1.2.22 [October 13, 2007]
+ No changes.
+
+version 1.2.23beta01 [October 15, 2007]
+ Reduced number of invocations of png_strlen() in pngset.c.
+ Changed [azAZ09_] to [_abcde...89] in Makefile.am for better localization.
+
+version 1.2.23beta02 [October 16, 2007]
+ Eliminated png_strncpy() and png_strcpy() (Pierre Poissinger)
+ Changed $AN to $(AN) in Makefile.am.
+
+version 1.2.23beta03 [October 16, 2007]
+ Fixed off-by-one error in pngset.c
+ Restore statement to set last character of buffer to \0 in pngerror.c
+
+version 1.2.23beta04 [October 23, 2007]
+ Reject attempt to set all-zero cHRM values.
+
+version 1.2.23beta05 [October 26, 2007]
+ Add missing quotes in projects/visualc6, lost in version 1.2.20rc3
+
+version 1.2.23rc01 [November 2, 2007]
+ No changes.
+
+version 1.2.23 [November 6, 2007]
+ No changes.
+
+version 1.2.24beta01 [November 19, 2007]
+ Moved misplaced test for malloc failure in png_set_sPLT(). This bug was
+ introduced in libpng-1.2.20beta01.
+ Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER
+ Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct()
+ when png_ptr is NULL (Marshall Clow).
+ Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike
+ Frysinger).
+
+version 1.2.24beta02 [November 30, 2007]
+ Removed a useless test and fixed incorrect test in png_set_cHRM_fixed()
+ (David Hill).
+
+version 1.2.24rc01 [December 7, 2007]
+ No changes.
+
+version 1.2.24 [December 14, 2007]
+ Make sure not to redefine _BSD_SOURCE in pngconf.h
+ Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling
+ unused files.
+
+version 1.2.25beta01 [January 7, 2008]
+ Fixed bug with unknown chunk handling, introduced in version 1.2.17rc2
+
+version 1.2.25beta02 [January 10, 2008]
+ Prevent gamma from being applied twice.
+
+version 1.2.25rc01 [January 17, 2008]
+ No changes.
+
+version 1.2.25beta03 [January 22, 2008]
+ Fixed some continue-after-malloc-failure errors in pngset.c (David Hill)
+ Check for info_ptr == NULL in png_read_info() and png_process_data().
+ Check for possible use of NULL user_png_ver[] in png_create_read_struct().
+ Change "if (swidth == NULL)" to "if (sheight == NULL)" in png_handle_sCAL
+ (bug introduced in libpng-1.2.4/1.0.13).
+ Return from png_destroy_read_struct() if png_ptr_ptr is NULL.
+ Fix overflow of "msg" in png_decompress_chunk().
+
+version 1.2.25beta04 [January 26, 2008]
+ Work around Coverity bug report by slightly refactoring
+ png_read_push_finish_row()
+
+version 1.2.25beta05 [January 31, 2008]
+ Added libpng-1.2.25beta05.tar.lzma to distribution. Get the lzma codec
+ from <http://tukaani.org/lzma>.
+ Added lp1225b05.7z to distribution. Get the 7-zip decoder from
+ from <http://www.7-zip.org>.
+ Fixed some broken links in the README file.
+
+version 1.2.25beta06 [February 6, 2008]
+ Refactored png_read_push_finish_row() again, trying to satisfy Coverity.
+ Fixed potential NULL dereference of png_ptr in png_destroy_write_struct();
+ clarified potential NULL dereference of png_ptr in png_destroy_read_struct();
+ fixed potential NULL dereference of info_ptr in png_handle_bKGD();
+ fixed potential NULL dereference of user_png_ver[] in
+ png_create_write_struct_2(). (Coverity)
+
+version 1.2.25rc02 [February 10, 2008]
+ Reset png_ptr->pass in png_read_push_finish_row() before break.
+ Changed "pass" from png_byte to int.
+
+version 1.2.25 and 1.0.31 [February 18, 2008]
+ No changes.
+
+version 1.2.26beta01 [February 21, 2008]
+ Added missing "(" in pngmem.c. Bug introduced in libpng-1.2.2/1.0.13
+
+version 1.2.26beta02 [March 12, 2008]
+ Refined error message returned from deflateInit2 in pngwutil.c
+ Check IHDR length in png_push_read_chunk() before saving it.
+
+version 1.2.26beta03 [March 16, 2008]
+ Revised contrib/gregbook to handle premature end-of-file and file
+ read errors correctly.
+
+version 1.2.26beta04 [March 18, 2008]
+ Free png_ptr->big_row_buf and png_ptr->prev_row before allocating
+ new copies in png_read_start_row(). Bug introduced in libpng-1.2.22.
+
+version 1.2.26beta05 [March 19, 2008]
+ Removed extra png_free() added in libpng-1.2.26beta04.
+
+version 1.2.26beta06 [March 19, 2008]
+ Avoid reallocating big_row_buf and prev_row when the size does not increase.
+
+version 1.2.26rc01 [March 26, 2008]
+ Ifdef out some code that is unused when interlacing is not supported.
+
+versions 1.0.32 and 1.2.26 [April 2, 2008]
+ No changes.
+
+version 1.2.27beta01 [April 12, 2008]
+ Fixed bug (introduced in libpng-1.0.5h) with handling zero-length
+ unknown chunks.
+ Added more information about png_set_keep_unknown_chunks() to the
+ documentation.
+ Reject tRNS chunk with out-of-range samples instead of masking off
+ the invalid high bits as done in since libpng-1.2.19beta5.
+
+version 1.2.27beta02 [April 13, 2008]
+ Revised documentation about unknown chunk and user chunk handling.
+ Keep tRNS chunk with out-of-range samples and issue a png_warning().
+
+version 1.2.27beta03 [April 14, 2008]
+ Added check for NULL ptr in TURBOC version of png_free_default().
+ Removed several unnecessary checks for NULL before calling png_free().
+ Revised png_set_tRNS() so that calling it twice removes and invalidates
+ the previous call.
+ Revised pngtest to check for out-of-range tRNS samples.
+
+version 1.2.27beta04 [April 18, 2008]
+ Added AC_LIBTOOL_WIN32_DLL to configure.ac
+ Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.62
+
+version 1.2.27beta05 [April 19, 2008]
+ Added MAINTAINERCLEANFILES variable to Makefile.am
+
+version 1.2.27beta06 [April 21, 2008]
+ Avoid changing color_type from GRAY to RGB by
+ png_set_expand_gray_1_2_4_to_8().
+
+version 1.2.27rc01 [April 23, 2008]
+ Fix broken URL for rfc2083 in png.5 and libpng-*.txt
+
+version 1.0.33 and 1.2.27 [April 30, 2008]
+ No changes.
+
+version 1.0.34 and 1.2.28 [April 30, 2008]
+ Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.61
+ due to backward incompatibilities.
+ Removed a stray object file from contrib/gregbook
+
+version 1.2.29beta01 [May 1, 2008]
+ Removed some stray *.diff and *.orig files
+
+version 1.2.29beta02 [May 1, 2008]
+ Reverted Makefile.in, aclocal.m4, and configure to the libpng-1.2.26
+ versions.
+
+version 1.2.29beta03 [May 2, 2008]
+ Added --force to autogen libtoolize options and --force-missing to
+ automake options.
+ Changed $(ECHO) to echo in Makefile.am and Makefile.in
+ Updated all configure files to autoconf-2.62
+ Comment out pnggcrd.c code with #ifdef/#endif if using MSC_VER
+
+version 1.2.29rc01 [May 4, 2008]
+ No changes.
+
+version 1.0.35 and 1.2.29 [May 8, 2008]
+ No changes.
+
+version 1.0.37 [May 9, 2008]
+ Updated Makefile.in and configure (omitted version 1.0.36).
+
+version 1.2.30beta01 [May 29, 2008]
+ Updated libpng.pc-configure.in and libpng-config.in per debian bug reports.
+
+version 1.2.30beta02 [June 25, 2008]
+ Restored png_flush(png_ptr) at the end of png_write_end(), that was
+ removed from libpng-1.0.9beta03.
+
+version 1.2.30beta03 [July 6, 2008]
+ Merged some cosmetic whitespace changes from libpng-1.4.0beta19.
+ Inline call of png_get_uint_32() in png_get_uint_31(), as in 1.4.0beta19.
+ Added demo of decoding vpAg and sTER chunks to pngtest.c, from 1.4.0beta19.
+ Changed PNGMAJ from 0 to 12 in makefile.darwin, which does not like 0.
+ Added new private function png_read_chunk_header() from 1.4.0beta19.
+ Merge reading of chunk length and chunk type into a single 8-byte read.
+ Merge writing of chunk length and chunk type into a single 8-byte write.
+
+version 1.2.30beta04 [July 10, 2008]
+ Merged more cosmetic whitespace changes from libpng-1.4.0beta19.
+
+version 1.0.38rc01, 1.2.30rc01 [July 18, 2008]
+ No changes.
+
+version 1.0.38rc02, 1.2.30rc02 [July 21, 2008]
+ Moved local array "chunkdata" from pngrutil.c to the png_struct, so
+ it will be freed by png_read_destroy() in case of a read error (Kurt
+ Christensen).
+
+version 1.0.38rc03, 1.2.30rc03 [July 21, 2008]
+ Changed "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking.
+
+version 1.0.38rc04, 1.2.30rc04 [July 22, 2008]
+ Changed "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in
+ png_decompress_chunk().
+
+version 1.0.38rc05, 1.2.30rc05 [July 25, 2008]
+ Changed all remaining "chunkdata" to "png_ptr->chunkdata" in
+ png_decompress_chunk() and remove chunkdata from parameter list.
+ Put a call to png_check_chunk_name() in png_read_chunk_header().
+ Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte.
+ Removed two calls to png_check_chunk_name() occuring later in the process.
+
+version 1.0.38rc06, 1.2.30rc06 [July 29, 2008]
+ Added a call to png_check_chunk_name() in pngpread.c
+ Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte.
+
+version 1.0.38r07, 1.2.30r07 [August 2, 2008]
+ Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta)
+ Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings.
+ Added code in pngset.c to quiet compiler warnings.
+ Updated contrib/visupng/cexcept.h to version 2.0.1
+ Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c
+
+version 1.0.38r08, 1.2.30r08 [August 2, 2008]
+ Enclose "volatile" declarations in #ifdef PNG_SETJMP_SUPPORTED (Cosmin).
+
+version 1.0.38, 1.2.30 [August 14, 2008]
+ No changes.
+
+version 1.2.31rc01 [August 19, 2008]
+ Removed extra crc check at the end of png_handle_cHRM(). Bug introduced
+ in libpng-1.2.30beta03 (Heiko Nitzsche).
+
+version 1.2.31rc02 [August 19, 2008]
+ Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call.
+
+version 1.2.31rc03 [August 19, 2008]
+ Added PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED block, off by default, around
+ new png_flush().
+
+version 1.0.39, 1.2.31 [August 21, 2008]
+ No changes.
+
+version 1.2.32beta01 [September 6, 2008]
+ Shortened tIME_string to 29 bytes in pngtest.c (bug introduced in
+ libpng-1.2.22).
+ Fixed off-by-one error introduced in png_push_read_zTXt() function in
+ libpng-1.2.30beta04/pngpread.c (Harald van Dijk)
+ These bugs have been given the vulnerability id CVE-2008-3964.
+
+version 1.0.40, 1.2.32 [September 18, 2008]
+ No changes.
+
+version 1.2.33beta01 [October 6, 2008]
+ Revised makefile.darwin to fix shared library numbering.
+ Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8()
+ in example.c (debian bug report)
+
+version 1.2.33rc01 [October 15, 2008]
+ No changes.
+
+version 1.0.41rc01, version 1.2.33rc02 [October 23, 2008]
+ Changed remaining "key" to "png_ptr->chunkdata" in png_handle_tEXt()
+ to avoid memory leak after memory failure while reading tEXt chunk.`
+
+version 1.2.33 [October 31, 2008]
+ No changes.
+
+version 1.2.34beta01 [November 27, 2008]
+ Revised png_warning() to write its message on standard output by default
+ when warning_fn is NULL. This was the behavior prior to libpng-1.2.9beta9.
+ Fixed string vs pointer-to-string error in png_check_keyword().
+ Added png_check_cHRM_fixed() in png.c and moved checking from pngget.c,
+ pngrutil.c, and pngwrite.c, and eliminated floating point cHRM checking.
+ Added check for zero-area RGB cHRM triangle in png_check_cHRM_fixed().
+ In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant
+ check for all-zero coordinates that is detected by the triangle check.
+ Revised png_warning() to write its message on standard output by default
+ when warning_fn is NULL.
+
+version 1.2.34beta02 [November 28, 2008]
+ Corrected off-by-one error in bKGD validity check in png_write_bKGD()
+ and in png_handle_bKGD().
+
+version 1.2.34beta03 [December 1, 2008]
+ Revised bKGD validity check to use >= x instead of > x + 1
+ Merged with png_debug from libpng-1.4.0 to remove newlines.
+
+version 1.2.34beta04 [December 2, 2008]
+ More merging with png_debug from libpng-1.4.0 to remove newlines.
+
+version 1.2.34beta05 [December 5, 2008]
+ Removed redundant check for key==NULL before calling png_check_keyword()
+ to ensure that new_key gets initialized and removed extra warning
+ (Arvan Pritchard).
+
+version 1.2.34beta06 [December 9, 2008]
+ In png_write_png(), respect the placement of the filler bytes in an earlier
+ call to png_set_filler() (Jim Barry).
+
+version 1.2.34beta07 [December 9, 2008]
+ Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and
+ PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated
+ PNG_TRANSFORM_STRIP_FILLER (Jim Barry).
+
+version 1.0.42rc01, 1.2.34rc01 [December 11, 2008]
+ No changes.
+
+version 1.0.42, 1.2.34 [December 18, 2008]
+ No changes.
+
+version 1.2.35beta01 [February 4, 2009]
+ Zero out some arrays of pointers after png_malloc(). (Tavis Ormandy)
+
+version 1.2.35beta02 [February 4, 2009]
+ Zero out more arrays of pointers after png_malloc().
+
+version 1.2.35beta03 [February 5, 2009]
+ Use png_memset() instead of a loop to intialize pointers. We realize
+ this will not work on platforms where the NULL pointer is not all zeroes.
+
+version 1.2.35rc01 [February 11, 2009]
+ No changes.
+
+version 1.2.35rc02 [February 12, 2009]
+ Fix typo in new png_memset call in pngset.c (png_color should be png_charp)
+
+version 1.0.43 and 1.2.35 [February 14, 2009]
+ No changes.
+
+version 1.2.36beta01 [February 28, 2009]
+ Revised comments in png_set_read_fn() and png_set_write_fn().
+ Revised order of #ifdef's and indentation in png_debug definitions of png.h
+ bug introduced in libpng-1.2.34.
+
+version 1.2.36beta02 [March 21, 2009]
+ Use png_memset() after png_malloc() of big_row_buf when reading an
+ interlaced file, to avoid a possible UMR.
+ Undid recent revision of PNG_NO_STDIO version of png_write_flush(). Users
+ having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined.
+ Revised libpng*.txt documentation about use of png_write_flush().
+ Removed fflush() from pngtest.c.
+ Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h
+
+version 1.2.36beta03 [March 27, 2009]
+ Relocated misplaced PNG_1_0_X define in png.h that caused the prototype
+ for png_set_strip_error_numbers() to be omitted from PNG_NO_ASSEMBLER_CODE
+ builds. This bug was introduced in libpng-1.2.15beta4.
+ Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt
+
+version 1.2.36beta04 [April 5, 2009]
+ Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles)
+
+version 1.2.36beta05 [April 24, 2009]
+ Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow
+ application code writers to bypass the check for multiple inclusion
+ of setjmp.h when they know that it is safe to ignore the situation.
+ Made some cosmetic changes to whitespace in pngtest output.
+ Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress
+ "shadowed declaration" warning from gcc-4.3.3.
+ Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration"
+ warning about a global "gamma" variable in math.h on some platforms.
+
+version 1.2.36rc01 [April 30, 2009]
+ No changes.
+
+version 1.0.44 and 1.2.36 [May 7, 2009]
+ No changes.
+
+version 1.2.37beta01 [May 14, 2009]
+ Fixed inconsistency in pngrutil.c, introduced in libpng-1.2.36. The
+ memset() was using "png_ptr->rowbytes" instead of "row_bytes", which
+ the corresponding png_malloc() uses (Joe Drew).
+ Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri)
+ Updated some of the makefiles in the scripts directory (merged with
+ those in libpng-1.4.0beta57).
+
+version 1.2.37beta02 [May 19, 2009]
+ Fixed typo in libpng documentation (FILTER_AVE should be FILTER_AVG)
+ Relocated misplaced #endif in pngwrite.c, sCAL chunk handler.
+ Conditionally compile png_read_finish_row() which is not used by
+ progressive readers.
+ Added contrib/pngminim/preader to demonstrate building minimal progressive
+ decoder, based on contrib/gregbook with embedded libpng and zlib.
+
+version 1.2.37beta03 [May 20, 2009]
+ In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there
+ is only one makefile in those directories, and revised the README files
+ accordingly.
+ Reformated sources in libpng style (3-space indentation, comment format)
+
+version 1.2.37rc01 [May 27, 2009]
+ No changes.
+
+versions 1.2.37 and 1.0.45 [June 4, 2009]
+ Reformatted several remaining "else statement;" and "if () statement;" into
+ two lines.
+ Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h
+ and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h
+ Added sections about the git repository and our coding style to the
+ documentation (merged from libpng-1.4.0beta62)
+ Added a section to the libpng documentation about using png_get_io_ptr()
+ in configure scripts to detect the presence of libpng.
+
+version 1.2.38beta01 [June 17, 2009]
+ Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR()
+ multiple times and to specify the sample order in the tRNS chunk,
+ because the ISO PNG specification has a typo in the tRNS table.
+ Changed several PNG_UNKNOWN_CHUNK_SUPPORTED to
+ PNG_HANDLE_AS_UNKNOWN_SUPPORTED, to make the png_set_keep mechanism
+ available for ignoring known chunks even when not saving unknown chunks.
+ Adopted preference for consistent use of "#ifdef" and "#ifndef" versus
+ "#if defined()" and "if !defined()" where possible.
+ Added PNG_NO_HANDLE_AS_UNKNOWN in the PNG_LEGACY_SUPPORTED block of
+ pngconf.h, and moved the various unknown chunk macro definitions
+ outside of the PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks.
+
+version 1.0.46 [June 18, 2009]
+ Removed some editing cruft from scripts/libpng.pc.in and some makefiles.
+
+version 1.2.38rc01 [June 24, 2009]
+ No changes.
+
+version 1.2.38rc02 [June 29, 2009]
+ Added a reference to the libpng license in each source file.
+
+version 1.2.38rc03 [July 11, 2009]
+ Revised references to the libpng license in pngconf.h and contrib/visupng
+ source files.
+ Rebuilt configure scripts with autoconf-2.63.
+
+version 1.0.47 and 1.2.38 [July 16, 2009]
+ No changes.
+
+version 1.2.39beta01 [July 25, 2009]
+ Added a prototype for png_64bit_product() in png.c
+
+version 1.2.39beta02 [July 27, 2009]
+ Avoid a possible NULL dereference in debug build, in png_set_text_2().
+ (bug introduced in libpng-0.95, discovered by Evan Rouault)
+
+version 1.2.39beta03 [July 29, 2009]
+ Relocated new png_64_bit_product() prototype into png.h
+ Expanded the information about prototypes in the libpng style section of
+ the documentation.
+ Rebuilt configure scripts with autoconf-2.64.
+
+version 1.2.39beta04 [August 1, 2009]
+ Replaced *.tar.lzma with *.txz in distribution. Get the xz codec
+ from <http://tukaani.org/xz>.
+
+version 1.2.39beta05 [August 1, 2009]
+ Reject attempt to write iCCP chunk with negative embedded profile length
+ (JD Chen)
+
+version 1.2.39c01 [August 6, 2009]
+ No changes.
+
+version 1.2.39 and 1.0.48 [August 13, 2009]
+ No changes.
+
+version 1.2.40beta01 [August 20, 2009]
+ Removed an extra png_debug() recently added to png_write_find_filter().
+ Fixed incorrect #ifdef in pngset.c regarding unknown chunk support.
+
+version 1.2.40rc01 [September 2, 2009]
+ Various bugfixes and improvements to CMakeLists.txt (Philip Lowman)
+
+version 1.2.40 and 1.0.49 [September 2, 2009]
+ No changes.
+
+version 1.0.50 [September 10, 2009]
+ Removed some editing cruft from pngset.c and pngwutil.c.
+
+version 1.2.41beta01 [September 25, 2009]
+ Moved redundant IHDR checking into new png_check_IHDR() in png.c
+ and report all errors found in the IHDR data.
+ Eliminated useless call to png_check_cHRM() from pngset.c
+ Expanded TAB characters in pngrtran.c
+
+version 1.2.41beta02 [September 30, 2009]
+ Revised png_check_IHDR().
+
+version 1.2.41beta03 [October 1, 2009]
+ Revised png_check_IHDR() again, to check info_ptr members instead of
+ the contents of the returned parameters.
+
+version 1.2.41beta04 [October 7, 2009]
+ Added "xcode" project similar one already in libpng-1.4.0beta (Alam Arias).
+ Ported some cosmetic changes from libpng-1.4.0beta86.
+ Eliminated a shadowed declaration of "pp" in png_handle_sPLT().
+
+version 1.2.41beta05 [October 17, 2009]
+ Revised pngconf.h to make it easier to enable iTXt support. From libpng
+ version 1.2.9 through 1.2.40, defining PNG_iTXt_SUPPORTED did not work
+ as expected.
+ Ported some cosmetic changes from libpng-1.4.0beta87, changing
+ many "#if defined(x)" to "#ifdef x".
+
+version 1.2.41beta06 [October 18, 2009]
+ Restored PNG_USE_LOCAL_ARRAYS code in pngread.c that was inadvertently
+ deleted in libpng-1.2.41beta05.
+ Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h
+ as in libpng-1.4.0beta78 and later.
+
+version 1.2.41beta07 [October 21, 2009]
+ Ported some cosmetic changes from libpng-1.4.0rc01, changing
+ many "#if defined(x)" to "#ifdef x" in png.h and pngconf.h.
+
+version 1.2.41beta08 [October 30, 2009]
+ Ported from libpng-1.4.0rc01: png_calloc(), png_get_io_chunk_name(),
+ png_get_io_state(), png_set_user_cache_max(), png_get_user_cache_max(),
+ png_set_premultiply_alpha, and png_do_read_premultiply_alpha().
+ Relocated png_do_chop() ahead of building gamma tables in pngrtran.c
+ This avoids building 16-bit gamma tables unnecessarily.
+
+version 1.2.41beta09 [November 1, 2009]
+ Removed a harmless extra png_set_invert_alpha() from pngwrite.c
+ More bugfixes and improvements to CMakeLists.txt (Philip Lowman)
+ Moved CMakeLists.txt from scripts into the main libpng directory.
+ Apply png_user_chunk_cache_max within png_decompress_chunk().
+ Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate.
+
+version 1.2.41beta10 [November 1, 2009]
+ Enabled iTXt support by default. To ensure binary compatibility with
+ previous versions, the "lang" and "lang_key" members will be assumed
+ to be omitted from previous versions unless the current libpng
+ version was built with PNG_iTXt_SUPPORTED (which is otherwise no
+ longer necessary to gain iTXt support), as a signal that the user has
+ been building previous versions with PNG_iTXt_SUPPORTED as well.
+
+version 1.2.41beta11 [November 2, 2009]
+ Store user's user_png_ver in new png_ptr->user_png_ver element.
+ Revised iTXt support. To ensure binary compatibility with
+ previous versions, the "lang" and "lang_key" members will be assumed
+ to be omitted from versions prior to 1.2.41beta11 whenever there is a
+ library mismatch.
+
+version 1.2.41beta12 [November 2, 2009]
+ Free png_ptr->user_png_ver when destroying png_ptr.
+
+version 1.2.41beta13 [November 3, 2009]
+ Updated scripts/pngw32.def and projects/wince/png32ce.def
+ Copied projects/wince/png32ce.def to the scripts directory.
+ Added scripts/makefile.wce
+ Patched ltmain.sh for wince support.
+ Added PNG_CONVERT_tIME_SUPPORTED macro.
+
+version 1.2.41beta14 [November 8, 2009]
+ versions 1.2.41beta05 through 1.2.41beta13 were abandoned.
+ The 1.0.x/1.2.x series will only receive security updates from now on.
+ Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED
+ Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED
+ Reverted iTXt compatibility stuff from 1.2.41beta05, 1.2.41beta11, and
+ 1.2.41beta12.
+ Reverted IOSTATE feature, user_cache_max, and premultiply_alpha features
+ from 1.2.41beta08.
+ Retained png_calloc() from 1.2.41beta08 but as a non-exported function,
+ and removed reference to png_calloc from scripts/*.def
+
+version 1.2.41beta15 [November 8, 2009]
+ Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and
+ PNG_ALLOCATED macros to detect deprecated direct access to the
+ png_struct or info_struct members and other deprecated usage in
+ applications (John Bowler).
+ Updated scripts/makefile* to add "-DPNG_CONFIGURE_LIBPNG" to CFLAGS,
+ to prevent warnings about direct access to png structs by libpng
+ functions while building libpng. They need to be tested, especially
+ those using compilers other than gcc.
+ Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG".
+
+version 1.2.41beta16 [November 9, 2009]
+ Removed three direct references to read_info_ptr members in pngtest.c
+ that were detected by the new PNG_DEPSTRUCT macro.
+ Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined.
+
+version 1.2.41beta17 [November 10, 2009]
+ Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions.
+ Marked deprecated function prototypes with PNG_DEPRECATED.
+ Marked memory allocation function prototypes with PNG_ALLOCATED.
+ Changed png_check_sig() to !png_sig_cmp() in contrib programs.
+ Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c
+ Added "-DPNG_CONFIGURE_LIBPNG" to the contrib/pngminum makefiles.
+
+version 1.2.41beta18 [November 11, 2009]
+ Renamed scripts/makefile.wce to scripts/makefile.cegcc
+ Marked nonexported functions with PNG_PRIVATE macro.
+
+version 1.2.41rc01 and 1.0.51rc01 [November 18, 2009]
+ Revised scripts/*.def to reflect functions actually exported by libpng.
+ Updated the copyright year in scripts/pngw32.rc from 2004 to 2009.
+ Moved descriptions of makefiles and other scripts out of INSTALL into
+ scripts/README.txt
+
+version 1.2.41rc02 [November 22, 2009]
+ Rebuilt the configure scripts with autoconf-2.65
+
+version 1.2.41rc03 [November 25, 2009]
+ Disabled the new pedantic warnings about deprecated function use
+ and deprecated structure access unless the user defines
+ PNG_PEDANTIC_WARNINGS.
+ Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files.
+ Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects.
+
+version 1.2.41 and 1.0.51 [December 3, 2009]
+ Updated the list of files and made some cosmetic changes in README.
+
+version 1.2.42beta01 [December 4, 2009]
+ Removed "#define PNG_NO_ERROR_NUMBERS" that was inadvertently added
+ to pngconf.h in version 1.2.41.
+ Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco
+ to put png.h and pngconf.h in $prefix/include, like the other scripts,
+ instead of in $prefix/include/libpng. Also revised makefile.sco
+ to put them in $prefix/include/libpng12 instead of in
+ $prefix/include/libpng/libpng12.
+ Removed leftover "-DPNG_CONFIGURE_LIBPNG" from scripts/makefile.darwin
+
+version 1.2.42beta02 [December 11, 2009]
+ Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile
+ Relocated png_do_chop() to its original position in pngrtran.c. The
+ change in version 1.2.41beta08 caused transparency to be handled wrong
+ in some 16-bit datastreams (Yusaku Sugai).
+
+version 1.2.42rc01 [December 17, 2009]
+ No changes.
+
+version 1.2.42rc02 [December 22, 2009]
+ Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt
+ (revising changes made in 1.2.41beta17 and 1.2.41rc01)
+
+version 1.2.42rc03 [December 25, 2009]
+ Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ in pngset.c to be consistent with other changes in version 1.2.38.
+
+version 1.2.42rc04 [January 1, 2010]
+ Marked png_memcpy_check() and png_memset_check() PNG_DEPRECATED.
+ Updated copyright year.
+
+version 1.2.42rc05 [January 2, 2010]
+ Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr
+ in pngtest.c
+
+version 1.2.42 and 1.0.52 [January 3, 2010]
+ No changes.
+
+version 1.2.43beta01 [January 27, 2010]
+ Updated CMakeLists.txt for consistent indentation and to avoid an
+ unclosed if-statement warning (Philip Lowman).
+ Removed "#ifdef PNG_1_0_X / #endif" surrounding
+ PNG_READ_16_TO_8_SUPPORTED and PNG_READ_GRAY_TO_RGB_SUPPORTED
+ in pngconf.h. These were added in libpng-1.2.41beta08 and libpng-1.0.51,
+ which introduced a binary incompatibility with libpng-1.0.50.
+ Backported new png_decompress_chunk() algorithm from libpng-1.4.1.
+
+version 1.2.43beta02 [February 1, 2010]
+ Backported two-pass png_decompress_chunk() algorithm from libpng-1.4.1.
+
+version 1.2.43beta03 [February 6, 2010]
+ Backported fast png_push_save_buffer() algorithm from libpng-1.4.1.
+ Backported some cosmetic changes from libpng-1.4.1.
+
+version 1.2.43beta04 [February 8, 2010]
+ Reverted recent changes to png_push_save-buffer().
+ Removed PNGAPI declaration of png_calloc() and png_write_sig() in
+ 1ibpng-1.2.X, introduced by mistake in libpng-1.2.41.
+ Return allocated "old_buffer" in png_push_save_buffer() before png_error()
+ to avoid a potential memory leak.
+
+version 1.2.43beta05 [February 8, 2010]
+ Ported rewritten png_decompress_chunk() by John Bowler from libpng-1.4.1.
+
+version 1.0.53rc01 and 1.2.43rc01 [February 18, 2010]
+ No changes.
+
+version 1.0.53rc02 and 1.2.43rc02 [February 19, 2010]
+ Define _ALL_SOURCE in configure.ac, makefile.aix, and CMakeLists.txt
+ when using AIX compiler.
+
+version 1.0.53 and 1.2.43 [February 25, 2010]
+ Removed unused gzio.c from contrib/pngminim gather and makefile scripts
+
+version 1.2.44beta01 [June 18, 2010]
+ In pngpread.c: png_push_have_row() add check for new_row > height
+ Removed the now-redundant check for out-of-bounds new_row from example.c
+
+version 1.2.44beta02 [June 19, 2010]
+ In pngpread.c: png_push_process_row() add check for too many rows.
+ Removed the now-redundant check for new_row > height in png_push_have_row().
+
+version 1.2.44beta03 [June 20, 2010]
+ Rewrote png_process_IDAT_data() to consistently treat extra data as warnings
+ and handle end conditions more cleanly.
+ Removed the new (beta02) check in png_push_process_row().
+
+version 1.2.44rc01 [June 21, 2010]
+ Revised some comments in png_process_IDAT_data().
+
+version 1.2.44rc02 [June 22, 2010]
+ Stop memory leak when reading a malformed sCAL chunk.
+
+version 1.2.44rc03 [June 23, 2010]
+ Revised pngpread.c patch of beta05 to avoid an endless loop.
+
+version 1.2.44 [June 26, 2010]
+ Updated some of the "last changed" dates.
+
+version 1.2.45beta01 [June 7, 2011]
+ Fixed uninitialized memory read in png_format_buffer() (Bug
+ report by Frank Busse, related to CVE-2004-0421).
+ Pass "" instead of '\0' to png_default_error() in png_err(). This mistake
+ was introduced in libpng-1.2.20beta01.
+ Check for up->location !PNG_AFTER_IDAT when writing unknown chunks
+ before IDAT.
+ Ported bugfix in pngrtran.c from 1.5.3: when expanding a paletted image,
+ always expand to RGBA if transparency is present.
+
+version 1.2.45beta02 [June 8, 2011]
+ Check for integer overflow in png_set_rgb_to_gray().
+
+version 1.2.45beta03 [June 19, 2011]
+ Check for sCAL chunk too short.
+
+version 1.2.45rc01 and 1.0.55rc01 [June 30, 2011]
+ Updated "last changed" dates and copyright year.
+
+version 1.2.45 and 1.0.55 [July 7, 2011]
+ No changes.
+
+version 1.2.46rc01 and 1.0.56rc01 [July 8, 2011]
+ Reverted changes to Makefile.am and Makefile.in to libpng-1.2.44 versions.
+
+version 1.2.46rc02 and 1.0.56rc02 [July 8, 2011]
+ Added CMakeLists.txt, projects/xcode, and pnggccrd.c to EXTRA_DIST in
+ Makefile.am and Makefile.in
+
+version 1.2.46 and 1.0.56 [July 9, 2011]
+ Udated copyright year to 2011.
+
+version 1.2.47beta01 [February 17, 2012]
+ Updated contrib/pngminus/makefile.std (Samuli Souminen)
+
+version 1.0.57rc01 and 1.2.47rc01 [February 17, 2012]
+ Fixed CVE-2011-3026 buffer overrun bug.
+ Fixed CVE-2011-3026 buffer overrun bug. This bug was introduced when
+ iCCP chunk support was added at libpng-1.0.6.
+
+version 1.0.57 and 1.2.47 [February 18, 2012]
+ No changes.
+
+version 1.2.48beta01 [February 27, 2012]
+ Removed two useless #ifdef directives from pngread.c and one from pngrutil.c
+ Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from
+ pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c;
+ now that png_ptr->buffer is inaccessible to applications, the special
+ handling is no longer useful.
+ Fixed bug with png_handle_hIST with odd chunk length (Frank Busse).
+ Fixed incorrect type (int copy should be png_size_t copy) in png_inflate().
+ Fixed off-by-one bug in png_handle_sCAL() when using fixed point arithmetic,
+ causing out-of-bounds read in png_set_sCAL() because of failure to copy
+ the string terminators. This bug was introduced in libpng-1.0.6 (Frank
+ Busse).
+
+version 1.2.48rc01 [March 2, 2012]
+ Removed the png_free() of unused png_ptr->current_text from pngread.c.
+ Added libpng license text to pnggccrd.c and pngvcrd.c (requested by Chrome).
+
+version 1.2.48rc02 [March 2, 2012]
+ Removed all of the assembler code from pnggccrd.c and just "return 2;".
+
+version 1.0.58 and 1.2.48 [March 8, 2012]
+ No changes.
+
+version 1.2.49rc01 [March 29, 2012]
+ Revised png_set_text_2() to avoid potential memory corruption (fixes
+ CVE-2011-3048).
+ Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
+
+Send comments/corrections/commendations to png-mng-implement at lists.sf.net
+(subscription required; visit
+https://lists.sourceforge.net/lists/listinfo/png-mng-implement
+to subscribe)
+or to glennrp at users.sourceforge.net
+
+Glenn R-P
+#endif
diff --git a/Source/LibPNG/CMakeLists.txt b/Source/LibPNG/CMakeLists.txt
new file mode 100644
index 0000000..c8c0d0b
--- /dev/null
+++ b/Source/LibPNG/CMakeLists.txt
@@ -0,0 +1,284 @@
+cmake_minimum_required(VERSION 2.4.3)
+set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+
+if(UNIX AND NOT DEFINED CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
+ "Choose the type of build, options are:
+ None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used)
+ Debug
+ Release
+ RelWithDebInfo
+ MinSizeRel.")
+endif()
+
+project(libpng C)
+enable_testing()
+
+# Copyright (C) 2007-2010 Glenn Randers-Pehrson
+
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+set(PNGLIB_MAJOR 1)
+set(PNGLIB_MINOR 2)
+set(PNGLIB_RELEASE 49)
+set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
+set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
+
+# needed packages
+find_package(ZLIB REQUIRED)
+include_directories(${ZLIB_INCLUDE_DIR})
+
+if(NOT WIN32)
+ find_library(M_LIBRARY
+ NAMES m
+ PATHS /usr/lib /usr/local/lib
+ )
+ if(NOT M_LIBRARY)
+ message(STATUS
+ "math library 'libm' not found - floating point support disabled")
+ endif()
+else()
+ # not needed on windows
+ set(M_LIBRARY "")
+endif()
+
+# COMMAND LINE OPTIONS
+if(DEFINED PNG_SHARED)
+ option(PNG_SHARED "Build shared lib" ${PNG_SHARED})
+else()
+ option(PNG_SHARED "Build shared lib" ON)
+endif()
+if(DEFINED PNG_STATIC)
+ option(PNG_STATIC "Build static lib" ${PNG_STATIC})
+else()
+ option(PNG_STATIC "Build static lib" ON)
+endif()
+
+if(MINGW)
+ option(PNG_TESTS "Build pngtest" NO)
+else()
+ option(PNG_TESTS "Build pngtest" YES)
+endif()
+
+option(PNG_NO_CONSOLE_IO "FIXME" YES)
+option(PNG_NO_STDIO "FIXME" YES)
+option(PNG_DEBUG "Build with debug output" NO)
+option(PNGARG "FIXME" YES)
+#TODO:
+# PNG_CONSOLE_IO_SUPPORTED
+
+# maybe needs improving, but currently I don't know when we can enable what :)
+set(png_asm_tmp "OFF")
+if(NOT WIN32)
+ find_program(uname_executable NAMES uname PATHS /bin /usr/bin /usr/local/bin)
+ if(uname_executable)
+ exec_program(${uname_executable}
+ ARGS --machine OUTPUT_VARIABLE uname_output)
+ if("uname_output" MATCHES "^.*i[1-9]86.*$")
+ set(png_asm_tmp "ON")
+ else("uname_output" MATCHES "^.*i[1-9]86.*$")
+ set(png_asm_tmp "OFF")
+ endif("uname_output" MATCHES "^.*i[1-9]86.*$")
+ endif(uname_executable)
+else()
+ # this env var is normally only set on win64
+ set(TEXT "ProgramFiles(x86)")
+ if("$ENV{${TEXT}}" STREQUAL "")
+ set(png_asm_tmp "ON")
+ endif("$ENV{${TEXT}}" STREQUAL "")
+endif()
+
+# SET LIBNAME
+set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR})
+
+# to distinguish between debug and release lib
+set(CMAKE_DEBUG_POSTFIX "d")
+
+
+# OUR SOURCES
+set(libpng_sources
+ png.h
+ pngconf.h
+ png.c
+ pngerror.c
+ pngget.c
+ pngmem.c
+ pngpread.c
+ pngread.c
+ pngrio.c
+ pngrtran.c
+ pngrutil.c
+ pngset.c
+ pngtrans.c
+ pngwio.c
+ pngwrite.c
+ pngwtran.c
+ pngwutil.c
+)
+set(pngtest_sources
+ pngtest.c
+)
+# SOME NEEDED DEFINITIONS
+
+add_definitions(-DPNG_CONFIGURE_LIBPNG)
+
+if(_AIX)
+ add_definitions(-D_ALL_SOURCE)
+endif(_AIX)
+
+if(MSVC)
+ add_definitions(-DPNG_NO_MODULEDEF -D_CRT_SECURE_NO_DEPRECATE)
+endif(MSVC)
+
+if(PNG_SHARED OR NOT MSVC)
+ #if building msvc static this has NOT to be defined
+ add_definitions(-DZLIB_DLL)
+endif()
+
+add_definitions(-DLIBPNG_NO_MMX)
+add_definitions(-DPNG_NO_MMX_CODE)
+
+
+if(PNG_CONSOLE_IO_SUPPORTED)
+ add_definitions(-DPNG_CONSOLE_IO_SUPPORTED)
+endif()
+
+if(PNG_NO_CONSOLE_IO)
+ add_definitions(-DPNG_NO_CONSOLE_IO)
+endif()
+
+if(PNG_NO_STDIO)
+ add_definitions(-DPNG_NO_STDIO)
+endif()
+
+if(PNG_DEBUG)
+ add_definitions(-DPNG_DEBUG)
+endif()
+
+if(NOT M_LIBRARY AND NOT WIN32)
+ add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED)
+endif()
+
+# NOW BUILD OUR TARGET
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR})
+
+if(PNG_SHARED)
+ add_library(${PNG_LIB_NAME} SHARED ${libpng_sources})
+ if(MSVC)
+ # msvc does not append 'lib' - do it here to have consistent name
+ set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib")
+ endif()
+ target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY})
+endif()
+
+if(PNG_STATIC)
+# does not work without changing name
+ set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static)
+ add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources})
+ if(MSVC)
+ # msvc does not append 'lib' - do it here to have consistent name
+ set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib")
+ endif()
+endif()
+
+
+if(PNG_SHARED AND WIN32)
+ set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
+endif()
+
+if(PNG_TESTS AND PNG_SHARED)
+ # does not work with msvc due to png_lib_ver issue
+ add_executable(pngtest ${pngtest_sources})
+ target_link_libraries(pngtest ${PNG_LIB_NAME})
+ add_test(pngtest pngtest ${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png)
+endif()
+
+
+# CREATE PKGCONFIG FILES
+# we use the same files like ./configure, so we have to set its vars
+set(prefix ${CMAKE_INSTALL_PREFIX})
+set(exec_prefix ${CMAKE_INSTALL_PREFIX})
+set(libdir ${CMAKE_INSTALL_PREFIX}/lib)
+set(includedir ${CMAKE_INSTALL_PREFIX}/include)
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng-config.in
+ ${CMAKE_CURRENT_BINARY_DIR}/libpng-config)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng.pc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng-config.in
+ ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config)
+
+# SET UP LINKS
+if(PNG_SHARED)
+ set_target_properties(${PNG_LIB_NAME} PROPERTIES
+# VERSION 0.${PNGLIB_RELEASE}.1.2.49
+ VERSION 0.${PNGLIB_RELEASE}.0
+ SOVERSION 0
+ CLEAN_DIRECT_OUTPUT 1)
+endif()
+if(PNG_STATIC)
+ if(NOT WIN32)
+ # that's uncool on win32 - it overwrites our static import lib...
+ set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES
+ OUTPUT_NAME ${PNG_LIB_NAME}
+ CLEAN_DIRECT_OUTPUT 1)
+ endif()
+endif()
+
+# INSTALL
+if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
+ if(PNG_SHARED)
+ install(TARGETS ${PNG_LIB_NAME}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+ endif()
+ if(PNG_STATIC)
+ install(TARGETS ${PNG_LIB_NAME_STATIC}
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+ endif()
+endif()
+
+if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
+ install(FILES png.h pngconf.h DESTINATION include)
+ install(FILES png.h pngconf.h DESTINATION include/${PNGLIB_NAME})
+endif()
+if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL )
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin)
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config
+ DESTINATION bin)
+endif()
+if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
+ # Install man pages
+ install(FILES libpng.3 libpngpf.3 DESTINATION man/man3)
+ install(FILES png.5 DESTINATION man/man5)
+ # Install pkg-config files
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc
+ DESTINATION lib/pkgconfig)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng-config
+ DESTINATION bin)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc
+ DESTINATION lib/pkgconfig)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config
+ DESTINATION bin)
+endif()
+
+# what's with libpng.txt and all the extra files?
+
+
+# UNINSTALL
+# do we need this?
+
+
+# DIST
+# do we need this?
+
+# to create msvc import lib for mingw compiled shared lib
+# pexports libpng.dll > libpng.def
+# lib /def:libpng.def /machine:x86
+
diff --git a/Source/LibPNG/INSTALL b/Source/LibPNG/INSTALL
new file mode 100644
index 0000000..e516334
--- /dev/null
+++ b/Source/LibPNG/INSTALL
@@ -0,0 +1,143 @@
+
+Installing libpng version 1.2.49 - March 29, 2012
+
+On Unix/Linux and similar systems, you can simply type
+
+ ./configure [--prefix=/path]
+ make check
+ make install
+
+and ignore the rest of this document.
+
+If configure does not work on your system and you have a reasonably
+up-to-date set of tools, running ./autogen.sh before running ./configure
+may fix the problem. You can also run the individual commands in
+autogen.sh with the --force option, if supported by your version of
+the tools. If you run 'libtoolize --force', though, this will replace
+the distributed, patched, version of ltmain.sh with an unpatched version
+and your shared library builds may fail to produce libraries with the
+correct version numbers.
+
+Instead, you can use one of the custom-built makefiles in the
+"scripts" directory
+
+ cp scripts/makefile.system makefile
+ make test
+ make install
+
+The files that are presently available in the scripts directory
+are listed and described in scripts/README.txt.
+
+Or you can use one of the "projects" in the "projects" directory.
+
+Before installing libpng, you must first install zlib, if it
+is not already on your system. zlib can usually be found
+wherever you got libpng. zlib can be placed in another directory,
+at the same level as libpng.
+
+If you want to use "cmake" (see www.cmake.org), type
+
+ cmake . -DCMAKE_INSTALL_PREFIX=/path
+ make
+ make install
+
+If your system already has a preinstalled zlib you will still need
+to have access to the zlib.h and zconf.h include files that
+correspond to the version of zlib that's installed.
+
+You can rename the directories that you downloaded (they
+might be called "libpng-1.2.49" or "libpng12" and "zlib-1.2.3"
+or "zlib123") so that you have directories called "zlib" and "libpng".
+
+Your directory structure should look like this:
+
+ .. (the parent directory)
+ libpng (this directory)
+ INSTALL (this file)
+ README
+ *.h
+ *.c
+ CMakeLists.txt => "cmake" script
+ configuration files:
+ configure.ac, configure, Makefile.am, Makefile.in,
+ autogen.sh, config.guess, ltmain.sh, missing,
+ aclocal.m4, config.h.in, config.sub,
+ depcomp, install-sh, mkinstalldirs, test-pngtest.sh
+ contrib
+ gregbook
+ pngminim
+ pngminus
+ pngsuite
+ visupng
+ projects
+ cbuilder5 (Borland)
+ visualc6 (msvc)
+ visualc71
+ xcode
+ scripts
+ makefile.*
+ *.def (module definition files)
+ pngtest.png
+ etc.
+ zlib
+ README
+ *.h
+ *.c
+ contrib
+ etc.
+
+If the line endings in the files look funny, you may wish to get the other
+distribution of libpng. It is available in both tar.gz (UNIX style line
+endings) and zip (DOS style line endings) formats.
+
+If you are building libpng with MSVC, you can enter the
+libpng projects\visualc6 or visualc71 directory and follow the instructions
+in README.txt.
+
+Otherwise enter the zlib directory and follow the instructions in zlib/README,
+then come back here and run "configure" or choose the appropriate
+makefile.sys in the scripts directory.
+
+Copy the file (or files) that you need from the
+scripts directory into this directory, for example
+
+ MSDOS example: copy scripts\makefile.msc makefile
+ UNIX example: cp scripts/makefile.std makefile
+
+Read the makefile to see if you need to change any source or
+target directories to match your preferences.
+
+Then read pngconf.h to see if you want to make any configuration
+changes.
+
+Then just run "make" which will create the libpng library in
+this directory and "make test" which will run a quick test that reads
+the "pngtest.png" file and writes a "pngout.png" file that should be
+identical to it. Look for "9782 zero samples" in the output of the
+test. For more confidence, you can run another test by typing
+"pngtest pngnow.png" and looking for "289 zero samples" in the output.
+Also, you can run "pngtest -m contrib/pngsuite/*.png" and compare
+your output with the result shown in contrib/pngsuite/README.
+
+Most of the makefiles will allow you to run "make install" to
+put the library in its final resting place (if you want to
+do that, run "make install" in the zlib directory first if necessary).
+Some also allow you to run "make test-installed" after you have
+run "make install".
+
+If you encounter a compiler error message complaining about the
+lines
+
+ __png.h__ already includes setjmp.h;
+ __dont__ include it again.;
+
+this means you have compiled another module that includes setjmp.h,
+which is hazardous because the two modules might not include exactly
+the same setjmp.h. If you are sure that you know what you are doing
+and that they are exactly the same, then you can comment out or
+delete the two lines. Better yet, use the cexcept interface
+instead, as demonstrated in contrib/visupng of the libpng distribution.
+
+Further information can be found in the README and libpng.txt
+files, in the individual makefiles, in png.h, and the manual pages
+libpng.3 and png.5.
diff --git a/Source/LibPNG/KNOWNBUG b/Source/LibPNG/KNOWNBUG
new file mode 100644
index 0000000..066c837
--- /dev/null
+++ b/Source/LibPNG/KNOWNBUG
@@ -0,0 +1,22 @@
+
+Known bugs in libpng version 1.2.49
+
+1. February 23, 2006: The custom makefiles don't build libpng with -lz.
+
+ STATUS: This is a subject of debate. The change will probably be made
+ as a part of a major overhaul of the makefiles in libpng version 1.4.0.
+
+2. February 24, 2006: The Makefile generated by the "configure" script
+ fails to install symbolic links
+ libpng12.so => libpng12.so.0.1.2.9betaN
+ that are generated by the custom makefiles.
+
+3. September 4, 2007: There is a report that pngtest crashes on MacOS 10.
+
+ STATUS: workarounds are
+ 1) Compile without optimization (crashes are observed with
+ -arch i386 and -O2 or -O3, using gcc-4.0.1).
+ 2) Compile pngtest.c with PNG_DEBUG defined (the bug goes away if
+ you try to look at it).
+ 3) Ignore the crash. The library itself seems to be OK.
+
diff --git a/Source/LibPNG/LICENSE b/Source/LibPNG/LICENSE
new file mode 100644
index 0000000..c04d730
--- /dev/null
+++ b/Source/LibPNG/LICENSE
@@ -0,0 +1,111 @@
+
+This copy of the libpng notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file png.h that is
+included in the libpng distribution, the latter shall prevail.
+
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+If you modify libpng you may insert additional notices immediately following
+this sentence.
+
+This code is released under the libpng license.
+
+libpng versions 1.2.6, August 15, 2004, through 1.2.49, March 29, 2012, are
+Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.2.5
+with the following individual added to the list of Contributing Authors
+
+ Cosmin Truta
+
+libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
+Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.0.6
+with the following individuals added to the list of Contributing Authors
+
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Gilles Vollant
+
+and with the following additions to the disclaimer:
+
+ There is no warranty against interference with your enjoyment of the
+ library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is with
+ the user.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-0.96,
+with the following individuals added to the list of Contributing Authors:
+
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996, 1997 Andreas Dilger
+Distributed according to the same disclaimer and license as libpng-0.88,
+with the following individuals added to the list of Contributing Authors:
+
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose. The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+1. The origin of this source code must not be misrepresented.
+
+2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
+
+3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit, without
+fee, and encourage the use of this source code as a component to
+supporting the PNG file format in commercial products. If you use this
+source code in a product, acknowledgment is not required but would be
+appreciated.
+
+
+A "png_get_copyright" function is available, for convenient use in "about"
+boxes and the like:
+
+ printf("%s",png_get_copyright(NULL));
+
+Also, the PNG logo (in PNG format, of course) is supplied in the
+files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a
+certification mark of the Open Source Initiative.
+
+Glenn Randers-Pehrson
+glennrp at users.sourceforge.net
+March 29, 2012
diff --git a/Source/LibPNG/LibPNG.2003.vcproj b/Source/LibPNG/LibPNG.2003.vcproj
new file mode 100644
index 0000000..8a9f2b1
--- /dev/null
+++ b/Source/LibPNG/LibPNG.2003.vcproj
@@ -0,0 +1,194 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="LibPNG"
+ SccProjectName="&quot;$/FreeImage/LibPNG&quot;, PJAAAAAA"
+ SccLocalPath=".">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/LibPNG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibPNG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/LibPNG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibPNG.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="png.c">
+ </File>
+ <File
+ RelativePath="pngerror.c">
+ </File>
+ <File
+ RelativePath="pnggccrd.c">
+ </File>
+ <File
+ RelativePath="pngget.c">
+ </File>
+ <File
+ RelativePath="pngmem.c">
+ </File>
+ <File
+ RelativePath="pngpread.c">
+ </File>
+ <File
+ RelativePath="pngread.c">
+ </File>
+ <File
+ RelativePath="pngrio.c">
+ </File>
+ <File
+ RelativePath="pngrtran.c">
+ </File>
+ <File
+ RelativePath="pngrutil.c">
+ </File>
+ <File
+ RelativePath="pngset.c">
+ </File>
+ <File
+ RelativePath="pngtrans.c">
+ </File>
+ <File
+ RelativePath="pngvcrd.c">
+ </File>
+ <File
+ RelativePath="pngwio.c">
+ </File>
+ <File
+ RelativePath="pngwrite.c">
+ </File>
+ <File
+ RelativePath="pngwtran.c">
+ </File>
+ <File
+ RelativePath="pngwutil.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="png.h">
+ </File>
+ <File
+ RelativePath="pngconf.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibPNG/LibPNG.2005.vcproj b/Source/LibPNG/LibPNG.2005.vcproj
new file mode 100644
index 0000000..61f3097
--- /dev/null
+++ b/Source/LibPNG/LibPNG.2005.vcproj
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibPNG"
+ ProjectGUID="{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+ RootNamespace="LibPNG"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/LibPNG.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibPNG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/LibPNG.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibPNG.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="png.c"
+ >
+ </File>
+ <File
+ RelativePath="pngerror.c"
+ >
+ </File>
+ <File
+ RelativePath="pnggccrd.c"
+ >
+ </File>
+ <File
+ RelativePath="pngget.c"
+ >
+ </File>
+ <File
+ RelativePath="pngmem.c"
+ >
+ </File>
+ <File
+ RelativePath="pngpread.c"
+ >
+ </File>
+ <File
+ RelativePath="pngread.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrio.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrtran.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrutil.c"
+ >
+ </File>
+ <File
+ RelativePath="pngset.c"
+ >
+ </File>
+ <File
+ RelativePath="pngtrans.c"
+ >
+ </File>
+ <File
+ RelativePath="pngvcrd.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwio.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwrite.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwtran.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwutil.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="png.h"
+ >
+ </File>
+ <File
+ RelativePath="pngconf.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibPNG/LibPNG.2008.vcproj b/Source/LibPNG/LibPNG.2008.vcproj
new file mode 100644
index 0000000..d347421
--- /dev/null
+++ b/Source/LibPNG/LibPNG.2008.vcproj
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibPNG"
+ ProjectGUID="{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+ RootNamespace="LibPNG"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ PrecompiledHeaderFile=".\Release/LibPNG.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ PrecompiledHeaderFile=".\Debug/LibPNG.pch"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="png.c"
+ >
+ </File>
+ <File
+ RelativePath="pngerror.c"
+ >
+ </File>
+ <File
+ RelativePath="pnggccrd.c"
+ >
+ </File>
+ <File
+ RelativePath="pngget.c"
+ >
+ </File>
+ <File
+ RelativePath="pngmem.c"
+ >
+ </File>
+ <File
+ RelativePath="pngpread.c"
+ >
+ </File>
+ <File
+ RelativePath="pngread.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrio.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrtran.c"
+ >
+ </File>
+ <File
+ RelativePath="pngrutil.c"
+ >
+ </File>
+ <File
+ RelativePath="pngset.c"
+ >
+ </File>
+ <File
+ RelativePath="pngtrans.c"
+ >
+ </File>
+ <File
+ RelativePath="pngvcrd.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwio.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwrite.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwtran.c"
+ >
+ </File>
+ <File
+ RelativePath="pngwutil.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="png.h"
+ >
+ </File>
+ <File
+ RelativePath="pngconf.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibPNG/README b/Source/LibPNG/README
new file mode 100644
index 0000000..9559685
--- /dev/null
+++ b/Source/LibPNG/README
@@ -0,0 +1,275 @@
+README for libpng version 1.2.49 - March 29, 2012 (shared library 12.0)
+See the note about version numbers near the top of png.h
+
+See INSTALL for instructions on how to install libpng.
+
+Libpng comes in several distribution formats. Get libpng-*.tar.gz,
+libpng-*.tar.xz, or libpng-*.tar.bz2 if you want UNIX-style line
+endings in the text files, or lpng*.7z or lpng*.zip if you want DOS-style
+line endings. You can get UNIX-style line endings from the *.zip file
+by using "unzip -a" but there seems to be no simple way to recover
+UNIX-style line endings from the *.7z file. The *.tar.xz file is
+recommended for *NIX users instead.
+
+Version 0.89 was the first official release of libpng. Don't let the
+fact that it's the first release fool you. The libpng library has been in
+extensive use and testing since mid-1995. By late 1997 it had
+finally gotten to the stage where there hadn't been significant
+changes to the API in some time, and people have a bad feeling about
+libraries with versions < 1.0. Version 1.0.0 was released in
+March 1998.
+
+****
+Note that some of the changes to the png_info structure render this
+version of the library binary incompatible with libpng-0.89 or
+earlier versions if you are using a shared library. The type of the
+"filler" parameter for png_set_filler() has changed from png_byte to
+png_uint_32, which will affect shared-library applications that use
+this function.
+
+To avoid problems with changes to the internals of png_info_struct,
+new APIs have been made available in 0.95 to avoid direct application
+access to info_ptr. These functions are the png_set_<chunk> and
+png_get_<chunk> functions. These functions should be used when
+accessing/storing the info_struct data, rather than manipulating it
+directly, to avoid such problems in the future.
+
+It is important to note that the APIs do not make current programs
+that access the info struct directly incompatible with the new
+library. However, it is strongly suggested that new programs use
+the new APIs (as shown in example.c and pngtest.c), and older programs
+be converted to the new format, to facilitate upgrades in the future.
+****
+
+Additions since 0.90 include the ability to compile libpng as a
+Windows DLL, and new APIs for accessing data in the info struct.
+Experimental functions include the ability to set weighting and cost
+factors for row filter selection, direct reads of integers from buffers
+on big-endian processors that support misaligned data access, faster
+methods of doing alpha composition, and more accurate 16->8 bit color
+conversion.
+
+The additions since 0.89 include the ability to read from a PNG stream
+which has had some (or all) of the signature bytes read by the calling
+application. This also allows the reading of embedded PNG streams that
+do not have the PNG file signature. As well, it is now possible to set
+the library action on the detection of chunk CRC errors. It is possible
+to set different actions based on whether the CRC error occurred in a
+critical or an ancillary chunk.
+
+The changes made to the library, and bugs fixed are based on discussions
+on the png-mng-implement mailing list and not on material submitted
+privately to Guy, Andreas, or Glenn. They will forward any good
+suggestions to the list.
+
+For a detailed description on using libpng, read libpng.txt. For
+examples of libpng in a program, see example.c and pngtest.c. For usage
+information and restrictions (what little they are) on libpng, see
+png.h. For a description on using zlib (the compression library used by
+libpng) and zlib's restrictions, see zlib.h
+
+I have included a general makefile, as well as several machine and
+compiler specific ones, but you may have to modify one for your own needs.
+
+You should use zlib 1.0.4 or later to run this, but it MAY work with
+versions as old as zlib 0.95. Even so, there are bugs in older zlib
+versions which can cause the output of invalid compression streams for
+some images. You will definitely need zlib 1.0.4 or later if you are
+taking advantage of the MS-DOS "far" structure allocation for the small
+and medium memory models. You should also note that zlib is a
+compression library that is useful for more things than just PNG files.
+You can use zlib as a drop-in replacement for fread() and fwrite() if
+you are so inclined.
+
+zlib should be available at the same place that libpng is, or at
+ftp://ftp.simplesystems.org/pub/png/src/
+
+You may also want a copy of the PNG specification. It is available
+as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
+these at http://www.libpng.org/pub/png/pngdocs.html
+
+This code is currently being archived at libpng.sf.net in the
+[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT)
+at GO GRAPHSUP. If you can't find it in any of those places,
+e-mail me, and I'll help you find it.
+
+If you have any code changes, requests, problems, etc., please e-mail
+them to me. Also, I'd appreciate any make files or project files,
+and any modifications you needed to make to get libpng to compile,
+along with a #define variable to tell what compiler/system you are on.
+If you needed to add transformations to libpng, or wish libpng would
+provide the image in a different way, drop me a note (and code, if
+possible), so I can consider supporting the transformation.
+Finally, if you get any warning messages when compiling libpng
+(note: not zlib), and they are easy to fix, I'd appreciate the
+fix. Please mention "libpng" somewhere in the subject line. Thanks.
+
+This release was created and will be supported by myself (of course
+based in a large way on Guy's and Andreas' earlier work), and the PNG
+development group.
+
+Send comments/corrections/commendations to png-mng-implement at lists.sf.net
+(subscription required; visit
+https://lists.sourceforge.net/lists/listinfo/png-mng-implement
+to subscribe) or to glennrp at users.sourceforge.net
+
+You can't reach Guy, the original libpng author, at the addresses
+given in previous versions of this document. He and Andreas will
+read mail addressed to the png-mng-implement list, however.
+
+Please do not send general questions about PNG. Send them to
+the (png-mng-misc at lists.sourceforge.net, subscription required, visit
+https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
+subscribe). On the other hand, please do not send libpng questions to
+that address, send them to me or to the png-mng-implement list. I'll
+get them in the end anyway. If you have a question about something
+in the PNG specification that is related to using libpng, send it
+to me. Send me any questions that start with "I was using libpng,
+and ...". If in doubt, send questions to me. I'll bounce them
+to others, if necessary.
+
+Please do not send suggestions on how to change PNG. We have
+been discussing PNG for twelve years now, and it is official and
+finished. If you have suggestions for libpng, however, I'll
+gladly listen. Even if your suggestion is not used immediately,
+it may be used later.
+
+Files in this distribution:
+
+ ANNOUNCE => Announcement of this version, with recent changes
+ CHANGES => Description of changes between libpng versions
+ KNOWNBUG => List of known bugs and deficiencies
+ LICENSE => License to use and redistribute libpng
+ README => This file
+ TODO => Things not implemented in the current library
+ Y2KINFO => Statement of Y2K compliance
+ example.c => Example code for using libpng functions
+ libpng-*-*-diff.txt => Diff from previous release
+ libpng.3 => manual page for libpng (includes libpng.txt)
+ libpng.txt => Description of libpng and its functions
+ libpngpf.3 => manual page for libpng's private functions
+ png.5 => manual page for the PNG format
+ png.c => Basic interface functions common to library
+ png.h => Library function and interface declarations
+ pngconf.h => System specific library configuration
+ pngerror.c => Error/warning message I/O functions
+ pngget.c => Functions for retrieving info from struct
+ pngmem.c => Memory handling functions
+ pngbar.png => PNG logo, 88x31
+ pngnow.png => PNG logo, 98x31
+ pngpread.c => Progressive reading functions
+ pngread.c => Read data/helper high-level functions
+ pngrio.c => Lowest-level data read I/O functions
+ pngrtran.c => Read data transformation functions
+ pngrutil.c => Read data utility functions
+ pngset.c => Functions for storing data into the info_struct
+ pngtest.c => Library test program
+ pngtest.png => Library test sample image
+ pngtrans.c => Common data transformation functions
+ pngwio.c => Lowest-level write I/O functions
+ pngwrite.c => High-level write functions
+ pngwtran.c => Write data transformations
+ pngwutil.c => Write utility functions
+ contrib => Contributions
+ gregbook => source code for PNG reading and writing, from
+ Greg Roelofs' "PNG: The Definitive Guide",
+ O'Reilly, 1999
+ msvctest => Builds and runs pngtest using a MSVC workspace
+ pngminim => Simple pnm2pngm and png2pnmm programs
+ pngminus => Simple pnm2png and png2pnm programs
+ pngsuite => Test images
+ visupng => Contains a MSVC workspace for VisualPng
+ projects => Contains project files and workspaces for
+ building a DLL
+ beos => Contains a Beos workspace for building libpng
+ c5builder => Contains a Borland workspace for building
+ libpng and zlib
+ netware.txt => Contains instructions for downloading a set
+ of project files for building libpng and
+ zlib on Netware.
+ visualc6 => Contains a Microsoft Visual C++ (MSVC)
+ workspace for building libpng and zlib
+ wince.txt => Contains instructions for downloading a
+ Microsoft Visual C++ (Windows CD Toolkit)
+ workspace for building libpng and zlib on
+ WindowsCE
+ xcode => Contains xcode project files
+ scripts => Directory containing scripts for building libpng:
+ descrip.mms => VMS makefile for MMS or MMK
+ makefile.std => Generic UNIX makefile (cc, creates static
+ libpng.a)
+ makefile.elf => Linux/ELF gcc makefile symbol versioning,
+ creates libpng12.so.0.1.2.49)
+ makefile.linux => Linux/ELF makefile (gcc, creates
+ libpng12.so.0.1.2.49)
+ makefile.gcmmx => Linux/ELF makefile (gcc, creates
+ libpng12.so.0.1.2.49, previously
+ used assembler code tuned for Intel MMX
+ platform)
+ makefile.gcc => Generic makefile (gcc, creates static
+ libpng.a)
+ makefile.knr => Archaic UNIX Makefile that converts files
+ with ansi2knr (Requires ansi2knr.c from
+ ftp://ftp.cs.wisc.edu/ghost)
+ makefile.aix => AIX makefile
+ makefile.cygwin => Cygwin/gcc makefile
+ makefile.darwin => Darwin makefile
+ makefile.dec => DEC Alpha UNIX makefile
+ makefile.freebsd => FreeBSD makefile
+ makefile.hpgcc => HPUX makefile using gcc
+ makefile.hpux => HPUX (10.20 and 11.00) makefile
+ makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit
+ makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2
+ (static)
+ makefile.intel => Intel C/C++ version 4.0 and later
+ libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later
+ makefile.netbsd => NetBSD/cc makefile, makes libpng.so.
+ makefile.ne12bsd => NetBSD/cc makefile, makes libpng12.so
+ makefile.openbsd => OpenBSD makefile
+ makefile.sgi => Silicon Graphics IRIX (cc, creates static lib)
+ makefile.sggcc => Silicon Graphics
+ (gcc, creates libpng12.so.0.1.2.49)
+ makefile.sunos => Sun makefile
+ makefile.solaris => Solaris 2.X makefile
+ (gcc, creates libpng12.so.0.1.2.49)
+ makefile.so9 => Solaris 9 makefile
+ (gcc, creates libpng12.so.0.1.2.49)
+ makefile.32sunu => Sun Ultra 32-bit makefile
+ makefile.64sunu => Sun Ultra 64-bit makefile
+ makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc
+ makefile.mips => MIPS makefile
+ makefile.acorn => Acorn makefile
+ makefile.amiga => Amiga makefile
+ smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC
+ compiler (Requires SCOPTIONS, copied from
+ scripts/SCOPTIONS.ppc)
+ makefile.atari => Atari makefile
+ makefile.beos => BEOS makefile for X86
+ makefile.bor => Borland makefile (uses bcc)
+ makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode)
+ makefile.tc3 => Turbo C 3.0 makefile
+ makefile.dj2 => DJGPP 2 makefile
+ makefile.msc => Microsoft C makefile
+ makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and
+ later (previously used assembler code tuned
+ for Intel MMX platform)
+ makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and
+ later (does not use assembler code)
+ makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def)
+ pngos2.def => OS/2 module definition file used by makefile.os2
+ makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model
+ makevms.com => VMS build script
+ SCOPTIONS.ppc => Used with smakefile.ppc
+
+Good luck, and happy coding.
+
+-Glenn Randers-Pehrson (current maintainer, since 1998)
+ Internet: glennrp at users.sourceforge.net
+
+-Andreas Eric Dilger (former maintainer, 1996-1997)
+ Internet: adilger at enel.ucalgary.ca
+ Web: http://members.shaw.ca/adilger/
+
+-Guy Eric Schalnat (original author and former maintainer, 1995-1996)
+ (formerly of Group 42, Inc)
+ Internet: gschal at infinet.com
diff --git a/Source/LibPNG/TODO b/Source/LibPNG/TODO
new file mode 100644
index 0000000..face765
--- /dev/null
+++ b/Source/LibPNG/TODO
@@ -0,0 +1,25 @@
+TODO - list of things to do for libpng:
+
+Final bug fixes.
+Improve API by hiding the png_struct and png_info structs.
+Finish work on the no-floating-point version (including gamma compensation)
+Better C++ wrapper/full C++ implementation?
+Fix problem with C++ and EXTERN "C".
+cHRM transformation.
+Improve setjmp/longjmp usage or remove it in favor of returning error codes.
+Add "grayscale->palette" transformation and "palette->grayscale" detection.
+Improved dithering.
+Multi-lingual error and warning message support.
+Complete sRGB transformation (presently it simply uses gamma=0.45455).
+Man pages for function calls.
+Better documentation.
+Better filter selection
+ (counting huffman bits/precompression? filter inertia? filter costs?).
+Histogram creation.
+Text conversion between different code pages (Latin-1 -> Mac and DOS).
+Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety?
+Build gamma tables using fixed point (and do away with floating point entirely).
+Use greater precision when changing to linear gamma for compositing against
+ background and doing rgb-to-gray transformation.
+Investigate pre-incremented loop counters and other loop constructions.
+Add interpolated method of handling interlacing.
diff --git a/Source/LibPNG/Y2KINFO b/Source/LibPNG/Y2KINFO
new file mode 100644
index 0000000..6e46b68
--- /dev/null
+++ b/Source/LibPNG/Y2KINFO
@@ -0,0 +1,55 @@
+ Y2K compliance in libpng:
+ =========================
+
+ March 29, 2012
+
+ Since the PNG Development group is an ad-hoc body, we can't make
+ an official declaration.
+
+ This is your unofficial assurance that libpng from version 0.71 and
+ upward through 1.2.49 are Y2K compliant. It is my belief that earlier
+ versions were also Y2K compliant.
+
+ Libpng only has three year fields. One is a 2-byte unsigned integer
+ that will hold years up to 65535. The other two hold the date in text
+ format, and will hold years up to 9999.
+
+ The integer is
+ "png_uint_16 year" in png_time_struct.
+
+ The strings are
+ "png_charp time_buffer" in png_struct and
+ "near_time_buffer", which is a local character string in png.c.
+
+ There are seven time-related functions:
+
+ png_convert_to_rfc_1123() in png.c
+ (formerly png_convert_to_rfc_1152() in error)
+ png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+ png_convert_from_time_t() in pngwrite.c
+ png_get_tIME() in pngget.c
+ png_handle_tIME() in pngrutil.c, called in pngread.c
+ png_set_tIME() in pngset.c
+ png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+ All appear to handle dates properly in a Y2K environment. The
+ png_convert_from_time_t() function calls gmtime() to convert from system
+ clock time, which returns (year - 1900), which we properly convert to
+ the full 4-digit year. There is a possibility that applications using
+ libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ function, or that they are incorrectly passing only a 2-digit year
+ instead of "year - 1900" into the png_convert_from_struct_tm() function,
+ but this is not under our control. The libpng documentation has always
+ stated that it works with 4-digit years, and the APIs have been
+ documented as such.
+
+ The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
+ integer to hold the year, and can hold years as large as 65535.
+
+ zlib, upon which libpng depends, is also Y2K compliant. It contains
+ no date-related code.
+
+
+ Glenn Randers-Pehrson
+ libpng maintainer
+ PNG Development Group
diff --git a/Source/LibPNG/config.h b/Source/LibPNG/config.h
new file mode 100755
index 0000000..6c46df9
--- /dev/null
+++ b/Source/LibPNG/config.h
@@ -0,0 +1,88 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+#ifndef __APPLE__
+ERROR! This file was generated for Mac Intel and PPC only
+#endif
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+/* #undef HAVE_LIBM */
+
+/* Define to 1 if you have the `z' library (-lz). */
+#define HAVE_LIBZ 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `pow' function. */
+#define HAVE_POW 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "libpng"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "png-mng-implement@lists.sourceforge.net"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libpng"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libpng 1.2.29beta03"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libpng"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.2.29beta03"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "1.2.29beta03"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
diff --git a/Source/LibPNG/configure b/Source/LibPNG/configure
new file mode 100755
index 0000000..ce58abb
--- /dev/null
+++ b/Source/LibPNG/configure
@@ -0,0 +1,13 @@
+#!/bin/sh
+echo "
+ There is no \"configure\" script in this distribution of
+ libpng-1.2.49.
+
+ Instead, please copy the appropriate makefile for your system from the
+ \"scripts\" directory. Read the INSTALL file for more details.
+
+ Update, July 2004: you can get a \"configure\" based distribution
+ from the libpng distribution sites. Download the file
+ libpng-1.2.49.tar.gz, libpng-1.2.49.tar.xz, or libpng-1.2.49.tar.bz2
+"
+
diff --git a/Source/LibPNG/example.c b/Source/LibPNG/example.c
new file mode 100644
index 0000000..49b8724
--- /dev/null
+++ b/Source/LibPNG/example.c
@@ -0,0 +1,832 @@
+
+#if 0 /* in case someone actually tries to compile this */
+
+/* example.c - an example of using libpng
+ * Last changed in libpng 1.2.37 [June 4, 2009]
+ * This file has been placed in the public domain by the authors.
+ * Maintained 1998-2010 Glenn Randers-Pehrson
+ * Maintained 1996, 1997 Andreas Dilger)
+ * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ */
+
+/* This is an example of how to use libpng to read and write PNG files.
+ * The file libpng.txt is much more verbose then this. If you have not
+ * read it, do so first. This was designed to be a starting point of an
+ * implementation. This is not officially part of libpng, is hereby placed
+ * in the public domain, and therefore does not require a copyright notice.
+ *
+ * This file does not currently compile, because it is missing certain
+ * parts, like allocating memory to hold an image. You will have to
+ * supply these parts to get it to compile. For an example of a minimal
+ * working PNG reader/writer, see pngtest.c, included in this distribution;
+ * see also the programs in the contrib directory.
+ */
+
+#include "png.h"
+
+ /* The png_jmpbuf() macro, used in error handling, became available in
+ * libpng version 1.0.6. If you want to be able to run your code with older
+ * versions of libpng, you must define the macro yourself (but only if it
+ * is not already defined by libpng!).
+ */
+
+#ifndef png_jmpbuf
+# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#endif
+
+/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp()
+ * returns zero if the image is a PNG and nonzero if it isn't a PNG.
+ *
+ * The function check_if_png() shown here, but not used, returns nonzero (true)
+ * if the file can be opened and is a PNG, 0 (false) otherwise.
+ *
+ * If this call is successful, and you are going to keep the file open,
+ * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
+ * you have created the png_ptr, so that libpng knows your application
+ * has read that many bytes from the start of the file. Make sure you
+ * don't call png_set_sig_bytes() with more than 8 bytes read or give it
+ * an incorrect number of bytes read, or you will either have read too
+ * many bytes (your fault), or you are telling libpng to read the wrong
+ * number of magic bytes (also your fault).
+ *
+ * Many applications already read the first 2 or 4 bytes from the start
+ * of the image to determine the file type, so it would be easiest just
+ * to pass the bytes to png_sig_cmp() or even skip that if you know
+ * you have a PNG file, and call png_set_sig_bytes().
+ */
+#define PNG_BYTES_TO_CHECK 4
+int check_if_png(char *file_name, FILE **fp)
+{
+ char buf[PNG_BYTES_TO_CHECK];
+
+ /* Open the prospective PNG file. */
+ if ((*fp = fopen(file_name, "rb")) == NULL)
+ return 0;
+
+ /* Read in some of the signature bytes */
+ if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
+ return 0;
+
+ /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
+ Return nonzero (true) if they match */
+
+ return(!png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK));
+}
+
+/* Read a PNG file. You may want to return an error code if the read
+ * fails (depending upon the failure). There are two "prototypes" given
+ * here - one where we are given the filename, and we need to open the
+ * file, and the other where we are given an open file (possibly with
+ * some or all of the magic bytes read - see comments above).
+ */
+#ifdef open_file /* prototype 1 */
+void read_png(char *file_name) /* We need to open the file */
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned int sig_read = 0;
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type;
+ FILE *fp;
+
+ if ((fp = fopen(file_name, "rb")) == NULL)
+ return (ERROR);
+
+#else no_open_file /* prototype 2 */
+void read_png(FILE *fp, unsigned int sig_read) /* File is already open */
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type;
+#endif no_open_file /* Only use one prototype! */
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also supply the
+ * the compiler header file version, so that we know if the application
+ * was compiled with a compatible version of the library. REQUIRED
+ */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+ if (png_ptr == NULL)
+ {
+ fclose(fp);
+ return (ERROR);
+ }
+
+ /* Allocate/initialize the memory for image information. REQUIRED. */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL)
+ {
+ fclose(fp);
+ png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
+ return (ERROR);
+ }
+
+ /* Set error handling if you are using the setjmp/longjmp method (this is
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
+ fclose(fp);
+ /* If we get here, we had a problem reading the file */
+ return (ERROR);
+ }
+
+ /* One of the following I/O initialization methods is REQUIRED */
+#ifdef streams /* PNG file I/O method 1 */
+ /* Set up the input control if you are using standard C streams */
+ png_init_io(png_ptr, fp);
+
+#else no_streams /* PNG file I/O method 2 */
+ /* If you are using replacement read functions, instead of calling
+ * png_init_io() here you would call:
+ */
+ png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
+ /* where user_io_ptr is a structure you want available to the callbacks */
+#endif no_streams /* Use only one I/O method! */
+
+ /* If we have already read some of the signature */
+ png_set_sig_bytes(png_ptr, sig_read);
+
+#ifdef hilevel
+ /*
+ * If you have enough memory to read in the entire image at once,
+ * and you need to specify only transforms that can be controlled
+ * with one of the PNG_TRANSFORM_* bits (this presently excludes
+ * dithering, filling, setting background, and doing gamma
+ * adjustment), then you can read the entire image (including
+ * pixels) into the info structure with this call:
+ */
+ png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
+
+#else
+ /* OK, you're doing it the hard way, with the lower-level functions */
+
+ /* The call to png_read_info() gives us all of the information from the
+ * PNG file before the first IDAT (image data chunk). REQUIRED
+ */
+ png_read_info(png_ptr, info_ptr);
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, int_p_NULL, int_p_NULL);
+
+ /* Set up the data transformations you want. Note that these are all
+ * optional. Only call them if you want/need them. Many of the
+ * transformations only work on specific types of images, and many
+ * are mutually exclusive.
+ */
+
+ /* Tell libpng to strip 16 bit/color files down to 8 bits/color */
+ png_set_strip_16(png_ptr);
+
+ /* Strip alpha bytes from the input data without combining with the
+ * background (not recommended).
+ */
+ png_set_strip_alpha(png_ptr);
+
+ /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
+ * byte into separate bytes (useful for paletted and grayscale images).
+ */
+ png_set_packing(png_ptr);
+
+ /* Change the order of packed pixels to least significant bit first
+ * (not useful if you are using png_set_packing). */
+ png_set_packswap(png_ptr);
+
+ /* Expand paletted colors into true RGB triplets */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+ /* Expand paletted or RGB images with transparency to full alpha channels
+ * so the data will be available as RGBA quartets.
+ */
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png_ptr);
+
+ /* Set the background color to draw transparent and alpha images over.
+ * It is possible to set the red, green, and blue components directly
+ * for paletted images instead of supplying a palette index. Note that
+ * even if the PNG file supplies a background, you are not required to
+ * use it - you should use the (solid) application background if it has one.
+ */
+
+ png_color_16 my_background, *image_background;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+ png_set_background(png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ png_set_background(png_ptr, &my_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+ /* Some suggestions as to how to get a screen gamma value
+ *
+ * Note that screen gamma is the display_exponent, which includes
+ * the CRT_exponent and any correction for viewing conditions
+ */
+ if (/* We have a user-defined screen gamma value */)
+ {
+ screen_gamma = user-defined screen_gamma;
+ }
+ /* This is one way that applications share the same screen gamma value */
+ else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL)
+ {
+ screen_gamma = atof(gamma_str);
+ }
+ /* If we don't have another value */
+ else
+ {
+ screen_gamma = 2.2; /* A good guess for a PC monitor in a dimly
+ lit room */
+ screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */
+ }
+
+ /* Tell libpng to handle the gamma conversion for you. The final call
+ * is a good guess for PC generated images, but it should be configurable
+ * by the user at run time by the user. It is strongly suggested that
+ * your application support gamma correction.
+ */
+
+ int intent;
+
+ if (png_get_sRGB(png_ptr, info_ptr, &intent))
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+ else
+ {
+ double image_gamma;
+ if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
+ png_set_gamma(png_ptr, screen_gamma, image_gamma);
+ else
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+ }
+
+ /* Dither RGB files down to 8 bit palette or reduce palettes
+ * to the number of colors available on your screen.
+ */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ int num_palette;
+ png_colorp palette;
+
+ /* This reduces the image to the application supplied palette */
+ if (/* We have our own palette */)
+ {
+ /* An array of colors to which the image should be dithered */
+ png_color std_color_cube[MAX_SCREEN_COLORS];
+
+ png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
+ MAX_SCREEN_COLORS, png_uint_16p_NULL, 0);
+ }
+ /* This reduces the image to the palette supplied in the file */
+ else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette))
+ {
+ png_uint_16p histogram = NULL;
+
+ png_get_hIST(png_ptr, info_ptr, &histogram);
+
+ png_set_dither(png_ptr, palette, num_palette,
+ max_screen_colors, histogram, 0);
+ }
+ }
+
+ /* Invert monochrome files to have 0 as white and 1 as black */
+ png_set_invert_mono(png_ptr);
+
+ /* If you want to shift the pixel values from the range [0,255] or
+ * [0,65535] to the original [0,7] or [0,31], or whatever range the
+ * colors were originally in:
+ */
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
+ {
+ png_color_8p sig_bit_p;
+
+ png_get_sBIT(png_ptr, info_ptr, &sig_bit_p);
+ png_set_shift(png_ptr, sig_bit_p);
+ }
+
+ /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ png_set_bgr(png_ptr);
+
+ /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
+ png_set_swap_alpha(png_ptr);
+
+ /* Swap bytes of 16 bit files to least significant byte first */
+ png_set_swap(png_ptr);
+
+ /* Add filler (or alpha) byte (before/after each RGB triplet) */
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ /* Turn on interlace handling. REQUIRED if you are not using
+ * png_read_image(). To see how to handle interlacing passes,
+ * see the png_read_row() method below:
+ */
+ number_passes = png_set_interlace_handling(png_ptr);
+
+ /* Optional call to gamma correct and add the background to the palette
+ * and update info structure. REQUIRED if you are expecting libpng to
+ * update the palette for you (ie you selected such a transform above).
+ */
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* Allocate the memory to hold the image using the fields of info_ptr. */
+
+ /* The easiest way to read the image: */
+ png_bytep row_pointers[height];
+
+ /* Clear the pointer array */
+ for (row = 0; row < height; row++)
+ row_pointers[row] = NULL;
+
+ for (row = 0; row < height; row++)
+ row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
+ info_ptr));
+
+ /* Now it's time to read the image. One of these methods is REQUIRED */
+#ifdef entire /* Read the entire image in one go */
+ png_read_image(png_ptr, row_pointers);
+
+#else no_entire /* Read the image one or more scanlines at a time */
+ /* The other way to read images - deal with interlacing: */
+
+ for (pass = 0; pass < number_passes; pass++)
+ {
+#ifdef single /* Read the image a single row at a time */
+ for (y = 0; y < height; y++)
+ {
+ png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL, 1);
+ }
+
+#else no_single /* Read the image several rows at a time */
+ for (y = 0; y < height; y += number_of_rows)
+ {
+#ifdef sparkle /* Read the image using the "sparkle" effect. */
+ png_read_rows(png_ptr, &row_pointers[y], png_bytepp_NULL,
+ number_of_rows);
+#else no_sparkle /* Read the image using the "rectangle" effect */
+ png_read_rows(png_ptr, png_bytepp_NULL, &row_pointers[y],
+ number_of_rows);
+#endif no_sparkle /* Use only one of these two methods */
+ }
+
+ /* If you want to display the image after every pass, do so here */
+#endif no_single /* Use only one of these two methods */
+ }
+#endif no_entire /* Use only one of these two methods */
+
+ /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
+ png_read_end(png_ptr, info_ptr);
+#endif hilevel
+
+ /* At this point you have read the entire image */
+
+ /* Clean up after the read, and free any memory allocated - REQUIRED */
+ png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
+
+ /* Close the file */
+ fclose(fp);
+
+ /* That's it */
+ return (OK);
+}
+
+/* Progressively read a file */
+
+int
+initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
+{
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible in case we are using dynamically
+ * linked libraries.
+ */
+ *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+ if (*png_ptr == NULL)
+ {
+ *info_ptr = NULL;
+ return (ERROR);
+ }
+
+ *info_ptr = png_create_info_struct(png_ptr);
+
+ if (*info_ptr == NULL)
+ {
+ png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
+ return (ERROR);
+ }
+
+ if (setjmp(png_jmpbuf((*png_ptr))))
+ {
+ png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
+ return (ERROR);
+ }
+
+ /* This one's new. You will need to provide all three
+ * function callbacks, even if you aren't using them all.
+ * If you aren't using all functions, you can specify NULL
+ * parameters. Even when all three functions are NULL,
+ * you need to call png_set_progressive_read_fn().
+ * These functions shouldn't be dependent on global or
+ * static variables if you are decoding several images
+ * simultaneously. You should store stream specific data
+ * in a separate struct, given as the second parameter,
+ * and retrieve the pointer from inside the callbacks using
+ * the function png_get_progressive_ptr(png_ptr).
+ */
+ png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
+ info_callback, row_callback, end_callback);
+
+ return (OK);
+}
+
+int
+process_data(png_structp *png_ptr, png_infop *info_ptr,
+ png_bytep buffer, png_uint_32 length)
+{
+ if (setjmp(png_jmpbuf((*png_ptr))))
+ {
+ /* Free the png_ptr and info_ptr memory on error */
+ png_destroy_read_struct(png_ptr, info_ptr, png_infopp_NULL);
+ return (ERROR);
+ }
+
+ /* This one's new also. Simply give it chunks of data as
+ * they arrive from the data stream (in order, of course).
+ * On segmented machines, don't give it any more than 64K.
+ * The library seems to run fine with sizes of 4K, although
+ * you can give it much less if necessary (I assume you can
+ * give it chunks of 1 byte, but I haven't tried with less
+ * than 256 bytes yet). When this function returns, you may
+ * want to display any rows that were generated in the row
+ * callback, if you aren't already displaying them there.
+ */
+ png_process_data(*png_ptr, *info_ptr, buffer, length);
+ return (OK);
+}
+
+info_callback(png_structp png_ptr, png_infop info)
+{
+ /* Do any setup here, including setting any of the transformations
+ * mentioned in the Reading PNG files section. For now, you _must_
+ * call either png_start_read_image() or png_read_update_info()
+ * after all the transformations are set (even if you don't set
+ * any). You may start getting rows before png_process_data()
+ * returns, so this is your last chance to prepare for that.
+ */
+}
+
+row_callback(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+{
+ /*
+ * This function is called for every row in the image. If the
+ * image is interlaced, and you turned on the interlace handler,
+ * this function will be called for every row in every pass.
+ *
+ * In this function you will receive a pointer to new row data from
+ * libpng called new_row that is to replace a corresponding row (of
+ * the same data format) in a buffer allocated by your application.
+ *
+ * The new row data pointer "new_row" may be NULL, indicating there is
+ * no new data to be replaced (in cases of interlace loading).
+ *
+ * If new_row is not NULL then you need to call
+ * png_progressive_combine_row() to replace the corresponding row as
+ * shown below:
+ */
+
+ /* Get pointer to corresponding row in our
+ * PNG read buffer.
+ */
+ png_bytep old_row = ((png_bytep *)our_data)[row_num];
+
+ /* If both rows are allocated then copy the new row
+ * data to the corresponding row data.
+ */
+ if ((old_row != NULL) && (new_row != NULL))
+ png_progressive_combine_row(png_ptr, old_row, new_row);
+
+ /*
+ * The rows and passes are called in order, so you don't really
+ * need the row_num and pass, but I'm supplying them because it
+ * may make your life easier.
+ *
+ * For the non-NULL rows of interlaced images, you must call
+ * png_progressive_combine_row() passing in the new row and the
+ * old row, as demonstrated above. You can call this function for
+ * NULL rows (it will just return) and for non-interlaced images
+ * (it just does the png_memcpy for you) if it will make the code
+ * easier. Thus, you can just do this for all cases:
+ */
+
+ png_progressive_combine_row(png_ptr, old_row, new_row);
+
+ /* where old_row is what was displayed for previous rows. Note
+ * that the first pass (pass == 0 really) will completely cover
+ * the old row, so the rows do not have to be initialized. After
+ * the first pass (and only for interlaced images), you will have
+ * to pass the current row as new_row, and the function will combine
+ * the old row and the new row.
+ */
+}
+
+end_callback(png_structp png_ptr, png_infop info)
+{
+ /* This function is called when the whole image has been read,
+ * including any chunks after the image (up to and including
+ * the IEND). You will usually have the same info chunk as you
+ * had in the header, although some data may have been added
+ * to the comments and time fields.
+ *
+ * Most people won't do much here, perhaps setting a flag that
+ * marks the image as finished.
+ */
+}
+
+/* Write a png file */
+void write_png(char *file_name /* , ... other image information ... */)
+{
+ FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_colorp palette;
+
+ /* Open the file */
+ fp = fopen(file_name, "wb");
+ if (fp == NULL)
+ return (ERROR);
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also check that
+ * the library version is compatible with the one used at compile time,
+ * in case we are using dynamically linked libraries. REQUIRED.
+ */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ png_voidp user_error_ptr, user_error_fn, user_warning_fn);
+
+ if (png_ptr == NULL)
+ {
+ fclose(fp);
+ return (ERROR);
+ }
+
+ /* Allocate/initialize the image information data. REQUIRED */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (info_ptr == NULL)
+ {
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, png_infopp_NULL);
+ return (ERROR);
+ }
+
+ /* Set error handling. REQUIRED if you aren't supplying your own
+ * error handling functions in the png_create_write_struct() call.
+ */
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ /* If we get here, we had a problem writing the file */
+ fclose(fp);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ return (ERROR);
+ }
+
+ /* One of the following I/O initialization functions is REQUIRED */
+
+#ifdef streams /* I/O initialization method 1 */
+ /* Set up the output control if you are using standard C streams */
+ png_init_io(png_ptr, fp);
+
+#else no_streams /* I/O initialization method 2 */
+ /* If you are using replacement write functions, instead of calling
+ * png_init_io() here you would call
+ */
+ png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
+ user_IO_flush_function);
+ /* where user_io_ptr is a structure you want available to the callbacks */
+#endif no_streams /* Only use one initialization method */
+
+#ifdef hilevel
+ /* This is the easy way. Use it if you already have all the
+ * image info living in the structure. You could "|" many
+ * PNG_TRANSFORM flags into the png_transforms integer here.
+ */
+ png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
+
+#else
+ /* This is the hard way */
+
+ /* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+ */
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???,
+ PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ /* Set the palette if there is one. REQUIRED for indexed-color images */
+ palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH
+ * png_sizeof(png_color));
+ /* ... Set palette colors ... */
+ png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH);
+ /* You must not free palette here, because png_set_PLTE only makes a link to
+ * the palette that you malloced. Wait until you are about to destroy
+ * the png structure.
+ */
+
+ /* Optional significant bit (sBIT) chunk */
+ png_color_8 sig_bit;
+ /* If we are dealing with a grayscale image then */
+ sig_bit.gray = true_bit_depth;
+ /* Otherwise, if we are dealing with a color image then */
+ sig_bit.red = true_red_bit_depth;
+ sig_bit.green = true_green_bit_depth;
+ sig_bit.blue = true_blue_bit_depth;
+ /* If the image has an alpha channel then */
+ sig_bit.alpha = true_alpha_bit_depth;
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+
+ /* Optional gamma chunk is strongly suggested if you have any guess
+ * as to the correct gamma of the image.
+ */
+ png_set_gAMA(png_ptr, info_ptr, gamma);
+
+ /* Optionally write comments into the image */
+ text_ptr[0].key = "Title";
+ text_ptr[0].text = "Mona Lisa";
+ text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[1].key = "Author";
+ text_ptr[1].text = "Leonardo DaVinci";
+ text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr[2].key = "Description";
+ text_ptr[2].text = "<long text>";
+ text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
+#ifdef PNG_iTXt_SUPPORTED
+ text_ptr[0].lang = NULL;
+ text_ptr[1].lang = NULL;
+ text_ptr[2].lang = NULL;
+#endif
+ png_set_text(png_ptr, info_ptr, text_ptr, 3);
+
+ /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs */
+
+ /* Note that if sRGB is present the gAMA and cHRM chunks must be ignored
+ * on read and, if your application chooses to write them, they must
+ * be written in accordance with the sRGB profile
+ */
+
+ /* Write the file header information. REQUIRED */
+ png_write_info(png_ptr, info_ptr);
+
+ /* If you want, you can write the info in two steps, in case you need to
+ * write your private chunk ahead of PLTE:
+ *
+ * png_write_info_before_PLTE(write_ptr, write_info_ptr);
+ * write_my_chunk();
+ * png_write_info(png_ptr, info_ptr);
+ *
+ * However, given the level of known- and unknown-chunk support in 1.2.0
+ * and up, this should no longer be necessary.
+ */
+
+ /* Once we write out the header, the compression type on the text
+ * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+ * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+ * at the end.
+ */
+
+ /* Set up the transformations you want. Note that these are
+ * all optional. Only call them if you want them.
+ */
+
+ /* Invert monochrome pixels */
+ png_set_invert_mono(png_ptr);
+
+ /* Shift the pixels up to a legal bit depth and fill in
+ * as appropriate to correctly scale the image.
+ */
+ png_set_shift(png_ptr, &sig_bit);
+
+ /* Pack pixels into bytes */
+ png_set_packing(png_ptr);
+
+ /* Swap location of alpha bytes from ARGB to RGBA */
+ png_set_swap_alpha(png_ptr);
+
+ /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
+ * RGB (4 channels -> 3 channels). The second parameter is not used.
+ */
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+ /* Flip BGR pixels to RGB */
+ png_set_bgr(png_ptr);
+
+ /* Swap bytes of 16-bit files to most significant byte first */
+ png_set_swap(png_ptr);
+
+ /* Swap bits of 1, 2, 4 bit packed pixel formats */
+ png_set_packswap(png_ptr);
+
+ /* Turn on interlace handling if you are not using png_write_image() */
+ if (interlacing)
+ number_passes = png_set_interlace_handling(png_ptr);
+ else
+ number_passes = 1;
+
+ /* The easiest way to write the image (you may have a different memory
+ * layout, however, so choose what fits your needs best). You need to
+ * use the first method if you aren't handling interlacing yourself.
+ */
+ png_uint_32 k, height, width;
+ png_byte image[height][width*bytes_per_pixel];
+ png_bytep row_pointers[height];
+
+ if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
+ png_error (png_ptr, "Image is too tall to process in memory");
+
+ for (k = 0; k < height; k++)
+ row_pointers[k] = image + k*width*bytes_per_pixel;
+
+ /* One of the following output methods is REQUIRED */
+
+#ifdef entire /* Write out the entire image data in one call */
+ png_write_image(png_ptr, row_pointers);
+
+ /* The other way to write the image - deal with interlacing */
+
+#else no_entire /* Write out the image data by one or more scanlines */
+
+ /* The number of passes is either 1 for non-interlaced images,
+ * or 7 for interlaced images.
+ */
+ for (pass = 0; pass < number_passes; pass++)
+ {
+ /* Write a few rows at a time. */
+ png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows);
+
+ /* If you are only writing one row at a time, this works */
+ for (y = 0; y < height; y++)
+ png_write_rows(png_ptr, &row_pointers[y], 1);
+ }
+#endif no_entire /* Use only one output method */
+
+ /* You can write optional chunks like tEXt, zTXt, and tIME at the end
+ * as well. Shouldn't be necessary in 1.2.0 and up as all the public
+ * chunks are supported and you can use png_set_unknown_chunks() to
+ * register unknown chunks into the info structure to be written out.
+ */
+
+ /* It is REQUIRED to call this to finish writing the rest of the file */
+ png_write_end(png_ptr, info_ptr);
+#endif hilevel
+
+ /* If you png_malloced a palette, free it here (don't free info_ptr->palette,
+ * as recommended in versions 1.0.5m and earlier of this example; if
+ * libpng mallocs info_ptr->palette, libpng will free it). If you
+ * allocated it with malloc() instead of png_malloc(), use free() instead
+ * of png_free().
+ */
+ png_free(png_ptr, palette);
+ palette = NULL;
+
+ /* Similarly, if you png_malloced any data that you passed in with
+ * png_set_something(), such as a hist or trans array, free it here,
+ * when you can be sure that libpng is through with it.
+ */
+ png_free(png_ptr, trans);
+ trans = NULL;
+ /* Whenever you use png_free() it is a good idea to set the pointer to
+ * NULL in case your application inadvertently tries to png_free() it
+ * again. When png_free() sees a NULL it returns without action, thus
+ * avoiding the double-free security problem.
+ */
+
+ /* Clean up after the write, and free any memory allocated */
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ /* Close the file */
+ fclose(fp);
+
+ /* That's it */
+ return (OK);
+}
+
+#endif /* if 0 */
diff --git a/Source/LibPNG/libpng-1.2.49.txt b/Source/LibPNG/libpng-1.2.49.txt
new file mode 100644
index 0000000..194fe41
--- /dev/null
+++ b/Source/LibPNG/libpng-1.2.49.txt
@@ -0,0 +1,3234 @@
+libpng.txt - A description on how to use and modify libpng
+
+ libpng version 1.2.49 - March 29, 2012
+ Updated and distributed by Glenn Randers-Pehrson
+ <glennrp at users.sourceforge.net>
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ This document is released under the libpng license.
+ For conditions of distribution and use, see the disclaimer
+ and license in png.h
+
+ Based on:
+
+ libpng versions 0.97, January 1998, through 1.2.49 - March 29, 2012
+ Updated and distributed by Glenn Randers-Pehrson
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ libpng 1.0 beta 6 version 0.96 May 28, 1997
+ Updated and distributed by Andreas Dilger
+ Copyright (c) 1996, 1997 Andreas Dilger
+
+ libpng 1.0 beta 2 - version 0.88 January 26, 1996
+ For conditions of distribution and use, see copyright
+ notice in png.h. Copyright (c) 1995, 1996 Guy Eric
+ Schalnat, Group 42, Inc.
+
+ Updated/rewritten per request in the libpng FAQ
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
+
+I. Introduction
+
+This file describes how to use and modify the PNG reference library
+(known as libpng) for your own use. There are five sections to this
+file: introduction, structures, reading, writing, and modification and
+configuration notes for various special platforms. In addition to this
+file, example.c is a good starting point for using the library, as
+it is heavily commented and should include everything most people
+will need. We assume that libpng is already installed; see the
+INSTALL file for instructions on how to install libpng.
+
+For examples of libpng usage, see the files "example.c", "pngtest.c",
+and the files in the "contrib" directory, all of which are included in
+the libpng distribution.
+
+Libpng was written as a companion to the PNG specification, as a way
+of reducing the amount of time and effort it takes to support the PNG
+file format in application programs.
+
+The PNG specification (second edition), November 2003, is available as
+a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at
+<http://www.w3.org/TR/2003/REC-PNG-20031110/
+The W3C and ISO documents have identical technical content.
+
+The PNG-1.2 specification is available at
+<http://www.libpng.org/pub/png/documents/>. It is technically equivalent
+to the PNG specification (second edition) but has some additional material.
+
+The PNG-1.0 specification is available
+as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a
+W3C Recommendation <http://www.w3.org/TR/REC.png.html>.
+
+Some additional chunks are described in the special-purpose public chunks
+documents at <http://www.libpng.org/pub/png/documents/>.
+
+Other information
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.libpng.org/pub/png/>.
+
+Most users will not have to modify the library significantly; advanced
+users may want to modify it more. All attempts were made to make it as
+complete as possible, while keeping the code easy to understand.
+Currently, this library only supports C. Support for other languages
+is being considered.
+
+Libpng has been designed to handle multiple sessions at one time,
+to be easily modifiable, to be portable to the vast majority of
+machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
+to use. The ultimate goal of libpng is to promote the acceptance of
+the PNG file format in whatever way possible. While there is still
+work to be done (see the TODO file), libpng should cover the
+majority of the needs of its users.
+
+Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
+The zlib compression utility is a general purpose utility that is
+useful for more than PNG files, and can be used without libpng.
+See the documentation delivered with zlib for more details.
+You can usually find the source files for the zlib utility wherever you
+find the libpng source files.
+
+Libpng is thread safe, provided the threads are using different
+instances of the structures. Each thread should have its own
+png_struct and png_info instances, and thus its own image.
+Libpng does not protect itself against two threads using the
+same instance of a structure.
+
+II. Structures
+
+There are two main structures that are important to libpng, png_struct
+and png_info. The first, png_struct, is an internal structure that
+will not, for the most part, be used by a user except as the first
+variable passed to every libpng function call.
+
+The png_info structure is designed to provide information about the
+PNG file. At one time, the fields of png_info were intended to be
+directly accessible to the user. However, this tended to cause problems
+with applications using dynamically loaded libraries, and as a result
+a set of interface functions for png_info (the png_get_*() and png_set_*()
+functions) was developed. The fields of png_info are still available for
+older applications, but it is suggested that applications use the new
+interfaces if at all possible.
+
+Applications that do make direct access to the members of png_struct (except
+for png_ptr->jmpbuf) must be recompiled whenever the library is updated,
+and applications that make direct access to the members of png_info must
+be recompiled if they were compiled or loaded with libpng version 1.0.6,
+in which the members were in a different order. In version 1.0.7, the
+members of the png_info structure reverted to the old order, as they were
+in versions 0.97c through 1.0.5. Starting with version 2.0.0, both
+structures are going to be hidden, and the contents of the structures will
+only be accessible through the png_get/png_set functions.
+
+The png.h header file is an invaluable reference for programming with libpng.
+And while I'm on the topic, make sure you include the libpng header file:
+
+#include <png.h>
+
+III. Reading
+
+We'll now walk you through the possible functions to call when reading
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one. See example.c and png.h for more detail. While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+Setup
+
+You will want to do the I/O initialization(*) before you get into libpng,
+so if it doesn't work, you don't have much to undo. Of course, you
+will also want to insure that you are, in fact, dealing with a PNG
+file. Libpng provides a simple check to see if a file is a PNG file.
+To use it, pass in the first 1 to 8 bytes of the file to the function
+png_sig_cmp(), and it will return 0 (false) if the bytes match the
+corresponding bytes of the PNG signature, or nonzero (true) otherwise.
+Of course, the more bytes you pass in, the greater the accuracy of the
+prediction.
+
+If you are intending to keep the file pointer open for use in libpng,
+you must ensure you don't read more than 8 bytes from the beginning
+of the file, and you also have to make a call to png_set_sig_bytes_read()
+with the number of bytes you read from the beginning. Libpng will
+then only check the bytes (if any) that your program didn't read.
+
+(*): If you are not using the standard I/O functions, you will need
+to replace them with custom functions. See the discussion under
+Customizing libpng.
+
+
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+ fread(header, 1, number, fp);
+ is_png = !png_sig_cmp(header, 0, number);
+ if (!is_png)
+ {
+ return (NOT_PNG);
+ }
+
+
+Next, png_struct and png_info need to be allocated and initialized. In
+order to ensure that the size of these structures is correct even with a
+dynamically linked libpng, there are functions to initialize and
+allocate the structures. We also pass the library version, optional
+pointers to error handling functions, and a pointer to a data struct for
+use by the error functions, if necessary (the pointer and functions can
+be NULL if the default error handlers are to be used). See the section
+on Changes to Libpng below regarding the old initialization functions.
+The structure allocation functions quietly return NULL if they fail to
+create the structure, so your application should check for that.
+
+ png_structp png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr,
+ (png_infopp)NULL, (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+ png_structp png_ptr = png_create_read_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
+
+When libpng encounters an error, it expects to longjmp back
+to your routine. Therefore, you will need to call setjmp and pass
+your png_jmpbuf(png_ptr). If you read the file from different
+routines, you will need to update the jmpbuf field every time you enter
+a new routine that will call a png_*() function.
+
+See your documentation of setjmp/longjmp for your compiler for more
+information on setjmp/longjmp. See the discussion on libpng error
+handling in the Customizing Libpng section below for more information
+on the libpng error handling. If an error occurs, and libpng longjmp's
+back to your setjmp, you will want to call png_destroy_read_struct() to
+free any memory.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+ fclose(fp);
+ return (ERROR);
+ }
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the input code. The default for libpng is to
+use the C function fread(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. If you wish to handle reading data in another
+way, you need not call the png_init_io() function, but you must then
+implement the libpng I/O methods discussed in the Customizing Libpng
+section below.
+
+ png_init_io(png_ptr, fp);
+
+If you had previously opened the file and read any of the signature from
+the beginning in order to see if this was a PNG file, you need to let
+libpng know that there are some bytes missing from the start of the file.
+
+ png_set_sig_bytes(png_ptr, number);
+
+Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+ read_chunk_callback(png_ptr ptr,
+ png_unknown_chunkp chunk);
+ {
+ /* The unknown chunk structure contains your
+ chunk data, along with similar data for any other
+ unknown chunks: */
+
+ png_byte name[5];
+ png_byte *data;
+ png_size_t size;
+
+ /* Note that libpng has already taken care of
+ the CRC handling */
+
+ /* put your code here. Search for your chunk in the
+ unknown chunk structure, process it, and return one
+ of the following: */
+
+ return (-n); /* chunk had an error */
+ return (0); /* did not recognize */
+ return (n); /* success */
+ }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+ read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+ png_get_user_chunk_ptr(png_ptr);
+
+If you call the png_set_read_user_chunk_fn() function, then all unknown
+chunks will be saved when read, in case your callback function will need
+one or more of them. This behavior can be changed with the
+png_set_keep_unknown_chunks() function, described below.
+
+At this point, you can set up a callback function that will be
+called after each row has been read, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void read_row_callback(png_ptr ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "read_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_status_fn(png_ptr, read_row_callback);
+
+Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read. Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members while unknown chunks will be discarded. This
+behavior can be wasteful if your application will never use some known
+chunk types. To change this, you can call:
+
+ png_set_keep_unknown_chunks(png_ptr, keep,
+ chunk_list, num_chunks);
+ keep - 0: default unknown chunk handling
+ 1: ignore; do not keep
+ 2: keep only if safe-to-copy
+ 3: keep even if unsafe-to-copy
+ You can use these definitions:
+ PNG_HANDLE_CHUNK_AS_DEFAULT 0
+ PNG_HANDLE_CHUNK_NEVER 1
+ PNG_HANDLE_CHUNK_IF_SAFE 2
+ PNG_HANDLE_CHUNK_ALWAYS 3
+ chunk_list - list of chunks affected (a byte string,
+ five bytes per chunk, NULL or '\0' if
+ num_chunks is 0)
+ num_chunks - number of chunks affected; if 0, all
+ unknown chunks are affected. If nonzero,
+ only the chunks in the list are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures. If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive. If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence. The IHDR and IEND chunks should not be named in
+chunk_list; if they are, libpng will process them normally anyway.
+
+Here is an example of the usage of png_set_keep_unknown_chunks(),
+where the private "vpAg" chunk will later be processed by a user chunk
+callback function:
+
+ png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'};
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ png_byte unused_chunks[]=
+ {
+ 104, 73, 83, 84, (png_byte) '\0', /* hIST */
+ 105, 84, 88, 116, (png_byte) '\0', /* iTXt */
+ 112, 67, 65, 76, (png_byte) '\0', /* pCAL */
+ 115, 67, 65, 76, (png_byte) '\0', /* sCAL */
+ 115, 80, 76, 84, (png_byte) '\0', /* sPLT */
+ 116, 73, 77, 69, (png_byte) '\0', /* tIME */
+ };
+ #endif
+
+ ...
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ /* ignore all unknown chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+ /* except for vpAg: */
+ png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
+ /* also ignore unused known chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
+ (int)sizeof(unused_chunks)/5);
+ #endif
+
+User limits
+
+The PNG specification allows the width and height of an image to be as
+large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.
+Since very few applications really need to process such large images,
+we have imposed an arbitrary 1-million limit on rows and columns.
+Larger images will be rejected immediately with a png_error() call. If
+you wish to override this limit, you can use
+
+ png_set_user_limits(png_ptr, width_max, height_max);
+
+to set your own limits, or use width_max = height_max = 0x7fffffffL
+to allow all valid dimensions (libpng may reject some very large images
+anyway because of potential buffer overflow conditions).
+
+You should put this statement after you create the PNG structure and
+before calling png_read_info(), png_read_png(), or png_process_data().
+If you need to retrieve the limits that are being applied, use
+
+ width_max = png_get_user_width_max(png_ptr);
+ height_max = png_get_user_height_max(png_ptr);
+
+The PNG specification sets no limit on the number of ancillary chunks
+allowed in a PNG datastream. You can impose a limit on the total number
+of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with
+
+ png_set_chunk_cache_max(png_ptr, user_chunk_cache_max);
+
+where 0x7fffffffL means unlimited. You can retrieve this limit with
+
+ chunk_cache_max = png_get_chunk_cache_max(png_ptr);
+
+This limit also applies to the number of buffers that can be allocated
+by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
+
+The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to
+ 8 bits
+ PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel
+ PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit
+ samples to bytes
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_EXPAND Perform set_expand()
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+ PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples
+ to RGB (or GA to RGBA)
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.) If this is the case, simply do this:
+
+ png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of some
+set of transformation flags. This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+then png_read_image(), and finally png_read_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future input transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_read_png().
+
+After you have called png_read_png(), you can retrieve the image data
+with
+
+ row_pointers = png_get_rows(png_ptr, info_ptr);
+
+where row_pointers is an array of pointers to the pixel data for each row:
+
+ png_bytep row_pointers[height];
+
+If you know your image size and pixel size ahead of time, you can allocate
+row_pointers prior to calling png_read_png() with
+
+ if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+ png_error (png_ptr,
+ "Image is too tall to process in memory");
+ if (width > PNG_UINT_32_MAX/pixel_size)
+ png_error (png_ptr,
+ "Image is too wide to process in memory");
+ row_pointers = png_malloc(png_ptr,
+ height*png_sizeof(png_bytep));
+ for (int i=0; i<height, i++)
+ row_pointers[i]=NULL; /* security precaution */
+ for (int i=0; i<height, i++)
+ row_pointers[i]=png_malloc(png_ptr,
+ width*pixel_size);
+ png_set_rows(png_ptr, info_ptr, &row_pointers);
+
+Alternatively you could allocate your image in one big block and define
+row_pointers[i] to point into the proper places in your block.
+
+If you use png_set_rows(), the application is responsible for freeing
+row_pointers (and row_pointers[i], if they were separately allocated).
+
+If you don't allocate row_pointers ahead of time, png_read_png() will
+do it, and it'll be free'ed when you call png_destroy_*().
+
+The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data. You do this with a
+call to png_read_info().
+
+ png_read_info(png_ptr, info_ptr);
+
+This will process all chunks up to but not including the image data.
+
+Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read. Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_method);
+
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels. (valid values are
+ 1, 2, 4, 8, 16 and depend also on
+ the color_type. See also
+ significant bits (sBIT) below).
+ color_type - describes which color/alpha channels
+ are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ filter_method - (must be PNG_FILTER_TYPE_BASE
+ for PNG 1.0, and can also be
+ PNG_INTRAPIXEL_DIFFERENCING if
+ the PNG datastream is embedded in
+ a MNG-1.0 datastream)
+ compression_type - (must be PNG_COMPRESSION_TYPE_BASE
+ for PNG 1.0)
+ interlace_type - (PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7)
+
+ Any or all of interlace_type, compression_type, or
+ filter_method can be NULL if you are
+ not interested in their values.
+
+ Note that png_get_IHDR() returns 32-bit data into
+ the application's width and height variables.
+ This is an unsafe situation if these are 16-bit
+ variables. In such situations, the
+ png_get_image_width() and png_get_image_height()
+ functions described below are safer.
+
+ width = png_get_image_width(png_ptr,
+ info_ptr);
+ height = png_get_image_height(png_ptr,
+ info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr,
+ info_ptr);
+ color_type = png_get_color_type(png_ptr,
+ info_ptr);
+ filter_method = png_get_filter_type(png_ptr,
+ info_ptr);
+ compression_type = png_get_compression_type(png_ptr,
+ info_ptr);
+ interlace_type = png_get_interlace_type(png_ptr,
+ info_ptr);
+
+ channels = png_get_channels(png_ptr, info_ptr);
+ channels - number of channels of info for the
+ color type (valid values are 1 (GRAY,
+ PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
+ 4 (RGB_ALPHA or RGB + filler byte))
+ rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ rowbytes - number of bytes needed to hold a row
+
+ signature = png_get_signature(png_ptr, info_ptr);
+ signature - holds the signature read from the
+ file (if any). The data is kept in
+ the same offset it would be if the
+ whole signature were read (i.e. if an
+ application had already read in 4
+ bytes of signature before starting
+ libpng, the remaining 4 bytes would
+ be in signature[4] through signature[7]
+ (see png_set_sig_bytes())).
+
+These are also important, but their validity depends on whether the chunk
+has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
+png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
+data has been read, or zero if it is missing. The parameters to the
+png_get_<chunk> are set directly if they are simple data types, or a
+pointer into the info_ptr is returned for any complex types.
+
+ png_get_PLTE(png_ptr, info_ptr, &palette,
+ &num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_get_gAMA(png_ptr, info_ptr, &gamma);
+ gamma - the gamma the file is written
+ at (PNG_INFO_gAMA)
+
+ png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
+ srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ The presence of the sRGB chunk
+ means that the pixel data is in the
+ sRGB color space. This chunk also
+ implies specific values of gAMA and
+ cHRM.
+
+ png_get_iCCP(png_ptr, info_ptr, &name,
+ &compression_type, &profile, &proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray,
+ red, green, and blue channels,
+ whichever are appropriate for the
+ given color type (png_color_16)
+
+ png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
+ &trans_values);
+ trans - array of transparent
+ entries for palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values of
+ the single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_get_hIST(png_ptr, info_ptr, &hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_get_tIME(png_ptr, info_ptr, &mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_get_bKGD(png_ptr, info_ptr, &background);
+ background - background color (PNG_VALID_bKGD)
+ valid 16-bit red, green and blue
+ values, regardless of color_type
+
+ num_comments = png_get_text(png_ptr, info_ptr,
+ &text_ptr, &num_text);
+ num_comments - number of comments
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (empty
+ string for unknown).
+ text_ptr[i].lang_key - keyword in UTF-8
+ (empty string for unknown).
+ Note that the itxt_length, lang, and lang_key
+ members of the text_ptr structure only exist
+ when the library is built with iTXt chunk support.
+
+ num_text - number of comments (same as
+ num_comments; you can put NULL here
+ to avoid the duplication)
+ Note while png_set_text() will accept text, language,
+ and translated keywords that can be NULL pointers, the
+ structure returned by png_get_text will always contain
+ regular zero-terminated C strings. They might be
+ empty strings but they will never be NULL pointers.
+
+ num_spalettes = png_get_sPLT(png_ptr, info_ptr,
+ &palette_ptr);
+ palette_ptr - array of palette structures holding
+ contents of one or more sPLT chunks
+ read.
+ num_spalettes - number of sPLT chunks read.
+
+ png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
+ &unit_type);
+ offset_x - positive offset from the left edge
+ of the screen
+ offset_y - positive offset from the top edge
+ of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
+ &unit_type);
+ res_x - pixels/unit physical resolution in
+ x direction
+ res_y - pixels/unit physical resolution in
+ x direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_get_sCAL(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ num_unknown_chunks = png_get_unknown_chunks(png_ptr,
+ info_ptr, &unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position of chunk in file
+
+ The value of "i" corresponds to the order in which the
+ chunks were read from the PNG file or inserted with the
+ png_set_unknown_chunks() function.
+
+The data from the pHYs chunk can be retrieved in several convenient
+forms:
+
+ res_x = png_get_x_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x = png_get_x_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_inch(png_ptr,
+ info_ptr)
+ aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
+ info_ptr)
+
+ (Each of these returns 0 [signifying "unknown"] if
+ the data is not present or if res_x is 0;
+ res_x_and_y is 0 if res_x != res_y)
+
+The data from the oFFs chunk can be retrieved in several convenient
+forms:
+
+ x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
+ x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_inches(png_ptr, info_ptr);
+
+ (Each of these returns 0 [signifying "unknown" if both
+ x and y are 0] if the data is not present or if the
+ chunk is present but the unit is the pixel)
+
+For more information, see the png_info definition in png.h and the
+PNG specification for chunk contents. Be careful with trusting
+rowbytes, as some of the transformations could increase the space
+needed to hold a row (expand, filler, gray_to_rgb, etc.).
+See png_read_update_info(), below.
+
+A quick word about text_ptr and num_text. PNG stores comments in
+keyword/text pairs, one pair per chunk, with no limit on the number
+of text chunks, and a 2^31 byte limit on their size. While there are
+suggested keywords, there is no requirement to restrict the use to these
+strings. It is strongly suggested that keywords and text be sensible
+to humans (that's the point), so don't use abbreviations. Non-printing
+symbols are not allowed. See the PNG specification for more details.
+There is also no requirement to have text after the keyword.
+
+Keywords should be limited to 79 Latin-1 characters without leading or
+trailing spaces, but non-consecutive spaces are allowed within the
+keyword. It is possible to have the same keyword any number of times.
+The text_ptr is an array of png_text structures, each holding a
+pointer to a language string, a pointer to a keyword and a pointer to
+a text string. The text string, language code, and translated
+keyword may be empty or NULL pointers. The keyword/text
+pairs are put into the array in the order that they are received.
+However, some or all of the text chunks may be after the image, so, to
+make sure you have read all the text chunks, don't mess with these
+until after you read the stuff after the image. This will be
+mentioned again below in the discussion that goes with png_read_end().
+
+Input transformations
+
+After you've read the header information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+The colors used for the background and transparency values should be
+supplied in the same format/depth as the current image data. They
+are stored in the same format/depth as the image data in a bKGD or tRNS
+chunk, so this is what libpng expects for this data. The colors are
+transformed to keep in sync with the image data when an application
+calls the png_read_update_info() routine (see below).
+
+Data will be decoded into the supplied row buffers packed into bytes
+unless the library has been told to transform it into another format.
+For example, 4 bit/pixel paletted or grayscale data will be returned
+2 pixels/byte with the leftmost pixel in the high-order bits of the
+byte, unless png_set_packing() is called. 8-bit RGB data will be stored
+in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha()
+is called to insert filler bytes, either before or after each RGB triplet.
+16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant
+byte of the color value first, unless png_set_strip_16() is called to
+transform it to regular RGB RGB triplets, or png_set_filler() or
+png_set_add alpha() is called to insert filler bytes, either before or
+after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can
+be modified with
+png_set_filler(), png_set_add_alpha(), or png_set_strip_16().
+
+The following code transforms grayscale images of less than 8 to 8 bits,
+changes paletted images to RGB, and adds a full alpha channel if there is
+transparency information in a tRNS chunk. This is most useful on
+grayscale images with bit depths of 2 or 4 or if there is a multiple-image
+viewing application that wishes to treat all images in the same way.
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ if (color_type == PNG_COLOR_TYPE_GRAY &&
+ bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
+
+These three functions are actually aliases for png_set_expand(), added
+in libpng version 1.0.4, with the function names expanded to improve code
+readability. In some future version they may actually do different
+things.
+
+As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was
+added. It expands the sample depth without changing tRNS to alpha.
+
+As of libpng version 1.2.49, not all possible expansions are supported.
+
+In the following table, the 01 means grayscale with depth<8, 31 means
+indexed with depth<8, other numerals represent the color type, "T" means
+the tRNS chunk is present, A means an alpha channel is present, and O
+means tRNS or alpha is present but all pixels in the image are opaque.
+
+ FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O
+ TO
+ 01 -
+ 31 -
+ 0 1 -
+ 0T -
+ 0O -
+ 2 GX -
+ 2T -
+ 2O -
+ 3 1 -
+ 3T -
+ 3O -
+ 4A T -
+ 4O -
+ 6A GX TX TX -
+ 6O GX TX -
+
+Within the matrix,
+ "-" means the transformation is not supported.
+ "X" means the transformation is obtained by png_set_expand().
+ "1" means the transformation is obtained by
+ png_set_expand_gray_1_2_4_to_8
+ "G" means the transformation is obtained by
+ png_set_gray_to_rgb().
+ "P" means the transformation is obtained by
+ png_set_expand_palette_to_rgb().
+ "T" means the transformation is obtained by
+ png_set_tRNS_to_alpha().
+
+PNG can have files with 16 bits per channel. If you only can handle
+8 bits per channel, this will strip the pixels down to 8 bit.
+
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+If, for some reason, you don't need the alpha channel on an image,
+and you want to remove it rather than combining it with the background
+(but the image author certainly had in mind that you *would* combine
+it with the background, so that's what you should probably do):
+
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_ptr);
+
+In PNG files, the alpha channel in an image
+is the level of opacity. If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
+
+ png_set_invert_alpha(png_ptr);
+
+The PNG format only supports pixels with postmultiplied alpha.
+If you want to replace the pixels, after reading them, with pixels
+that have premultiplied color samples, you can do this with
+
+ png_set_premultiply_alpha(png_ptr);
+
+If you do this, any input with a tRNS chunk will be expanded to
+have an alpha channel.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit
+files. This code expands to 1 pixel per byte without changing the
+values of the pixels:
+
+ if (bit_depth < 8)
+ png_set_packing(png_ptr);
+
+PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels
+stored in a PNG image have been "scaled" or "shifted" up to the next
+higher possible bit depth (e.g. from 5 bits/sample in the range [0,31]
+to 8 bits/sample in the range [0, 255]). However, it is also possible
+to convert the PNG pixel data back to the original bit depth of the
+image. This call reduces the pixels back down to the original bit depth:
+
+ png_color_8p sig_bit;
+
+ if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+ png_set_shift(png_ptr, sig_bit);
+
+PNG files store 3-color pixels in red, green, blue order. This code
+changes the storage of the pixels to blue, green, red:
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_bgr(png_ptr);
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them
+into 4 or 8 bytes for windowing systems that need them in this format:
+
+ if (color_type == PNG_COLOR_TYPE_RGB)
+ png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
+
+where "filler" is the 8 or 16-bit number to fill with, and the location is
+either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
+you want the filler before the RGB or after. This transformation
+does not affect images that already have full alpha channels. To add an
+opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which
+will generate RGBA pixels.
+
+Note that png_set_filler() does not change the color type. If you want
+to do that, you can add a true alpha channel with
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
+
+where "filler" contains the alpha value to assign to each pixel.
+This function was added in libpng-1.2.7.
+
+If you are reading an image with an alpha channel, and you need the
+data as ARGB instead of the normal PNG format RGBA:
+
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_swap_alpha(png_ptr);
+
+For some uses, you may want a grayscale image to be represented as
+RGB. This code will do that conversion:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_rgb_to_gray_fixed(png_ptr, error_action,
+ int red_weight, int green_weight);
+
+ error_action = 1: silently do the conversion
+ error_action = 2: issue a warning if the original
+ image has any pixel where
+ red != green or red != blue
+ error_action = 3: issue an error and abort the
+ conversion if the original
+ image has any pixel where
+ red != green or red != blue
+
+ red_weight: weight of red component times 100000
+ green_weight: weight of green component times 100000
+ If either weight is negative, default
+ weights (21268, 71514) are used.
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels. bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With red_weight+green_weight<=100000,
+the normalized graylevel is computed:
+
+ int rw = red_weight * 65536;
+ int gw = green_weight * 65536;
+ int bw = 65536 - (rw + gw);
+ gray = (rw*red + gw*green + bw*blue)/65536;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net>
+
+ Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+ Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
+
+which can be expressed with integers as
+
+ Y = (6969 * R + 23434 * G + 2365 * B)/32768
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
+If you have a grayscale and you are using png_set_expand_depth(),
+png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0). Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
+
+ png_color_16 my_background;
+ png_color_16p image_background;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+ png_set_background(png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ png_set_background(png_ptr, &my_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+The png_set_background() function tells libpng to composite images
+with alpha or simple transparency against the supplied background
+color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
+you may use this color, or supply another color more suitable for
+the current display (e.g., the background color from a web page). You
+need to tell libpng whether the color is in the gamma space of the
+display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
+(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
+that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
+know why anyone would use this, but it's here).
+
+To properly display PNG images on any kind of system, the application needs
+to know what the display gamma is. Ideally, the user will know this, and
+the application will allow them to set it. One method of allowing the user
+to set the display gamma separately for each system is to check for a
+SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
+correctly set.
+
+Note that display_gamma is the overall gamma correction required to produce
+pleasing results, which depends on the lighting conditions in the surrounding
+environment. In a dim or brightly lit room, no compensation other than
+the physical gamma exponent of the monitor is needed, while in a dark room
+a slightly smaller exponent is better.
+
+ double gamma, screen_gamma;
+
+ if (/* We have a user-defined screen
+ gamma value */)
+ {
+ screen_gamma = user_defined_screen_gamma;
+ }
+ /* One way that applications can share the same
+ screen gamma value */
+ else if ((gamma_str = getenv("SCREEN_GAMMA"))
+ != NULL)
+ {
+ screen_gamma = (double)atof(gamma_str);
+ }
+ /* If we don't have another value */
+ else
+ {
+ screen_gamma = 2.2; /* A good guess for a
+ PC monitor in a bright office or a dim room */
+ screen_gamma = 2.0; /* A good guess for a
+ PC monitor in a dark room */
+ screen_gamma = 1.7 or 1.0; /* A good
+ guess for Mac systems */
+ }
+
+The png_set_gamma() function handles gamma transformations of the data.
+Pass both the file gamma and the current screen_gamma. If the file does
+not have a gamma value, you can pass one anyway if you have an idea what
+it is (usually 0.45455 is a good guess for GIF images on PCs). Note
+that file gammas are inverted from screen gammas. See the discussions
+on gamma in the PNG specification for an excellent description of what
+gamma is, and why all applications should support it. It is strongly
+recommended that PNG viewers support gamma correction.
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, screen_gamma, gamma);
+ else
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+If you need to reduce an RGB file to a paletted file, or if a paletted
+file has more entries then will fit on your screen, png_set_dither()
+will do that. Note that this is a simple match dither that merely
+finds the closest color available. This should work fairly well with
+optimized palettes, and fairly badly with linear color cubes. If you
+pass a palette that is larger then maximum_colors, the file will
+reduce the number of colors in the palette so it will fit into
+maximum_colors. If there is a histogram, it will use it to make
+more intelligent choices when reducing the palette. If there is no
+histogram, it may not do as good a job.
+
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_PLTE))
+ {
+ png_uint_16p histogram = NULL;
+
+ png_get_hIST(png_ptr, info_ptr,
+ &histogram);
+ png_set_dither(png_ptr, palette, num_palette,
+ max_screen_colors, histogram, 1);
+ }
+ else
+ {
+ png_color std_color_cube[MAX_SCREEN_COLORS] =
+ { ... colors ... };
+
+ png_set_dither(png_ptr, std_color_cube,
+ MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
+ NULL,0);
+ }
+ }
+
+PNG files describe monochrome as black being zero and white being one.
+The following code will reverse this (make black be one and white be
+zero):
+
+ if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_invert_mono(png_ptr);
+
+This function can also be used to invert grayscale and gray-alpha images:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_invert_mono(png_ptr);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code changes the storage to the
+other way (little-endian, i.e. least significant bits first, the
+way PCs store them):
+
+ if (bit_depth == 16)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_read_user_transform_fn(png_ptr,
+ read_transform_fn);
+
+You must supply the function
+
+ void read_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+after all of the other transformations have been processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function, and you can inform libpng that your transform
+function will change the number of channels or bit depth with the
+function
+
+ png_set_user_transform_info(png_ptr, user_ptr,
+ user_depth, user_channels);
+
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
+
+You can retrieve the pointer via the function
+png_get_user_transform_ptr(). For example:
+
+ voidp read_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+The last thing to handle is interlacing; this is covered in detail below,
+but you must call the function here if you want libpng to handle expansion
+of the interlaced image.
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+
+After setting the transformations, libpng can update your png_info
+structure to reflect any transformations you've requested with this
+call. This is most useful to update the info structure's rowbytes
+field so you can use it to allocate your image memory. This function
+will also update your palette with the correct screen_gamma and
+background if these have been given with the calls above.
+
+ png_read_update_info(png_ptr, info_ptr);
+
+After you call png_read_update_info(), you can allocate any
+memory you need to hold the image. The row data is simply
+raw byte data for all forms of images. As the actual allocation
+varies among applications, no example will be given. If you
+are allocating one large chunk, you will need to build an
+array of pointers to each row, as it will be needed for some
+of the functions below.
+
+Reading image data
+
+After you've allocated memory, you can read the image data.
+The simplest way to do this is in one function call. If you are
+allocating enough memory to hold the whole image, you can just
+call png_read_image() and libpng will read in all the image data
+and put it in the memory area supplied. You will need to pass in
+an array of pointers to each row.
+
+This function automatically handles interlacing, so you don't need
+to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_read_rows().
+
+ png_read_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_bytep row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to read in the whole image at once, you can
+use png_read_rows() instead. If there is no interlacing (check
+interlace_type == PNG_INTERLACE_NONE), this is simple:
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+where row_pointers is the same as in the png_read_image() call.
+
+If you are doing this just one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+ png_read_row(png_ptr, row_pointer, NULL);
+
+If the file is interlaced (interlace_type != 0 in the IHDR chunk), things
+get somewhat harder. The only current (PNG Specification version 1.2)
+interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7)
+is a somewhat complicated 2D interlace scheme, known as Adam7, that
+breaks down an image into seven smaller images of varying size, based
+on an 8x8 grid.
+
+libpng can fill out those images or it can give them to you "as is".
+If you want them filled out, there are two ways to do that. The one
+mentioned in the PNG specification is to expand each pixel to cover
+those pixels that have not been read yet (the "rectangle" method).
+This results in a blocky image for the first pass, which gradually
+smooths out as more pixels are read. The other method is the "sparkle"
+method, where pixels are drawn only in their final locations, with the
+rest of the image remaining whatever colors they were initialized to
+before the start of the read. The first method usually looks better,
+but tends to be slower, as there are more pixels to put in the rows.
+
+If you don't want libpng to handle the interlacing details, just call
+png_read_rows() seven times to read in all seven images. Each of the
+images is a valid image by itself, or they can all be combined on an
+8x8 grid to form a single image (although if you intend to combine them
+you would be far better off using the libpng interlace handling).
+
+The first pass will return an image 1/8 as wide as the entire image
+(every 8th column starting in column 0) and 1/8 as high as the original
+(every 8th row starting in row 0), the second will be 1/8 as wide
+(starting in column 4) and 1/8 as high (also starting in row 0). The
+third pass will be 1/4 as wide (every 4th pixel starting in column 0) and
+1/8 as high (every 8th row starting in row 4), and the fourth pass will
+be 1/4 as wide and 1/4 as high (every 4th column starting in column 2,
+and every 4th row starting in row 0). The fifth pass will return an
+image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2),
+while the sixth pass will be 1/2 as wide and 1/2 as high as the original
+(starting in column 1 and row 0). The seventh and final pass will be as
+wide as the original, and 1/2 as high, containing all of the odd
+numbered scanlines. Phew!
+
+If you want libpng to expand the images, call this before calling
+png_start_read_image() or png_read_update_info():
+
+ if (interlace_type == PNG_INTERLACE_ADAM7)
+ number_of_passes
+ = png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this
+is seven, but may change if another interlace type is added.
+This function can be called even if the file is not interlaced,
+where it will return one pass.
+
+If you are not going to display the image after each pass, but are
+going to wait until the entire image is read in, use the sparkle
+effect. This effect is faster and the end result of either method
+is exactly the same. If you are planning on displaying the image
+after each pass, the "rectangle" effect is generally considered the
+better looking one.
+
+If you only want the "sparkle" effect, just call png_read_rows() as
+normal, with the third parameter NULL. Make sure you make pass over
+the image number_of_passes times, and you don't change the data in the
+rows between calls. You can change the locations of the data, just
+not the data. Each pass only writes the pixels appropriate for that
+pass, and assumes the data from previous passes is still valid.
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+If you only want the first effect (the rectangles), do the same as
+before except pass the row buffer in the third parameter, and leave
+the second parameter NULL.
+
+ png_read_rows(png_ptr, NULL, row_pointers,
+ number_of_rows);
+
+Finishing a sequential read
+
+After you are finished reading the image through the
+low-level interface, you can finish reading the file. If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate. If you are not interested, you can pass NULL.
+
+ png_read_end(png_ptr, end_info);
+
+When you are done, you can free all memory allocated by libpng like this:
+
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those cases do nothing.
+The "seq" parameter is ignored if only one item of the selected data
+type, such as PLTE, is allowed. If "seq" is not -1, and multiple items
+are allowed for the data type identified in the mask, such as text or
+sPLT, only the n'th item in the structure is freed, where n is "seq".
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+This function only affects data that has already been allocated.
+You can call this function after reading the PNG data but before calling
+any png_set_*() functions, to control whether the user or the png_set_*()
+function is responsible for freeing any existing data that might be present,
+and again after the png_set_*() functions to control whether the user
+or png_destroy_*() is supposed to free the data. When the user assumes
+responsibility for libpng-allocated data, the application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated your row_pointers in a single block, as suggested above in
+the description of the high level read interface, you must not transfer
+responsibility for freeing it to the png_set_rows or png_read_destroy function,
+because they would also try to free the individual row_pointers[i].
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+
+The png_free_data() function will turn off the "valid" flag for anything
+it frees. If you need to turn the flag off for a chunk that was freed by
+your application instead of by libpng, you can use
+
+ png_set_invalid(png_ptr, info_ptr, mask);
+ mask - identifies the chunks to be made invalid,
+ containing the bitwise OR of one or
+ more of
+ PNG_INFO_gAMA, PNG_INFO_sBIT,
+ PNG_INFO_cHRM, PNG_INFO_PLTE,
+ PNG_INFO_tRNS, PNG_INFO_bKGD,
+ PNG_INFO_hIST, PNG_INFO_pHYs,
+ PNG_INFO_oFFs, PNG_INFO_tIME,
+ PNG_INFO_pCAL, PNG_INFO_sRGB,
+ PNG_INFO_iCCP, PNG_INFO_sPLT,
+ PNG_INFO_sCAL, PNG_INFO_IDAT
+
+For a more compact example of reading a PNG image, see the file example.c.
+
+Reading PNG files progressively
+
+The progressive reader is slightly different then the non-progressive
+reader. Instead of calling png_read_info(), png_read_rows(), and
+png_read_end(), you make one call to png_process_data(), which calls
+callbacks when it has the info, a row, or the end of the image. You
+set up these callbacks with png_set_progressive_read_fn(). You don't
+have to worry about the input/output functions of libpng, as you are
+giving the library the data directly in png_process_data(). I will
+assume that you have read the section on reading PNG files above,
+so I will only highlight the differences (although I will show
+all of the code).
+
+png_structp png_ptr;
+png_infop info_ptr;
+
+ /* An example code fragment of how you would
+ initialize the progressive reader in your
+ application. */
+ int
+ initialize_png_reader()
+ {
+ png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new. You can provide functions
+ to be called when the header info is valid,
+ when each row is completed, and when the image
+ is finished. If you aren't using all functions,
+ you can specify NULL parameters. Even when all
+ three functions are NULL, you need to call
+ png_set_progressive_read_fn(). You can use
+ any struct as the user_ptr (cast to a void pointer
+ for the function call), and retrieve the pointer
+ from inside the callbacks using the function
+
+ png_get_progressive_ptr(png_ptr);
+
+ which will return a void pointer, which you have
+ to cast appropriately.
+ */
+ png_set_progressive_read_fn(png_ptr, (void *)user_ptr,
+ info_callback, row_callback, end_callback);
+
+ return 0;
+ }
+
+ /* A code fragment that you call as you receive blocks
+ of data */
+ int
+ process_data(png_bytep buffer, png_uint_32 length)
+ {
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new also. Simply give it a chunk
+ of data from the file stream (in order, of
+ course). On machines with segmented memory
+ models machines, don't give it any more than
+ 64K. The library seems to run fine with sizes
+ of 4K. Although you can give it much less if
+ necessary (I assume you can give it chunks of
+ 1 byte, I haven't tried less then 256 bytes
+ yet). When this function returns, you may
+ want to display any rows that were generated
+ in the row callback if you don't already do
+ so there.
+ */
+ png_process_data(png_ptr, info_ptr, buffer, length);
+ return 0;
+ }
+
+ /* This function is called (as set by
+ png_set_progressive_read_fn() above) when enough data
+ has been supplied so all of the header has been
+ read.
+ */
+ void
+ info_callback(png_structp png_ptr, png_infop info)
+ {
+ /* Do any setup here, including setting any of
+ the transformations mentioned in the Reading
+ PNG files section. For now, you _must_ call
+ either png_start_read_image() or
+ png_read_update_info() after all the
+ transformations are set (even if you don't set
+ any). You may start getting rows before
+ png_process_data() returns, so this is your
+ last chance to prepare for that.
+ */
+ }
+
+ /* This function is called when each row of image
+ data is complete */
+ void
+ row_callback(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+ {
+ /* If the image is interlaced, and you turned
+ on the interlace handler, this function will
+ be called for every row in every pass. Some
+ of these rows will not be changed from the
+ previous pass. When the row is not changed,
+ the new_row variable will be NULL. The rows
+ and passes are called in order, so you don't
+ really need the row_num and pass, but I'm
+ supplying them because it may make your life
+ easier.
+
+ For the non-NULL rows of interlaced images,
+ you must call png_progressive_combine_row()
+ passing in the row and the old row. You can
+ call this function for NULL rows (it will just
+ return) and for non-interlaced images (it just
+ does the memcpy for you) if it will make the
+ code easier. Thus, you can just do this for
+ all cases:
+ */
+
+ png_progressive_combine_row(png_ptr, old_row,
+ new_row);
+
+ /* where old_row is what was displayed for
+ previously for the row. Note that the first
+ pass (pass == 0, really) will completely cover
+ the old row, so the rows do not have to be
+ initialized. After the first pass (and only
+ for interlaced images), you will have to pass
+ the current row, and the function will combine
+ the old row and the new row.
+ */
+ }
+
+ void
+ end_callback(png_structp png_ptr, png_infop info)
+ {
+ /* This function is called after the whole image
+ has been read, including any chunks after the
+ image (up to and including the IEND). You
+ will usually have the same info chunk as you
+ had in the header, although some data may have
+ been added to the comments and time fields.
+
+ Most people won't do much here, perhaps setting
+ a flag that marks the image as finished.
+ */
+ }
+
+
+
+IV. Writing
+
+Much of this is very similar to reading. However, everything of
+importance is repeated here, so you won't have to constantly look
+back up in the reading section to understand writing.
+
+Setup
+
+You will want to do the I/O initialization before you get into libpng,
+so if it doesn't work, you don't have anything to undo. If you are not
+using the standard I/O functions, you will need to replace them with
+custom writing functions. See the discussion under Customizing libpng.
+
+ FILE *fp = fopen(file_name, "wb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+
+Next, png_struct and png_info need to be allocated and initialized.
+As these can be both relatively large, you may not want to store these
+on the stack, unless you have stack space to spare. Of course, you
+will want to check if they return NULL. If you are also reading,
+you won't want to name your read structure and your write structure
+both "png_ptr"; you can call them anything you like, such as
+"read_ptr" and "write_ptr". Look at pngtest.c, for example.
+
+ png_structp png_ptr = png_create_write_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_write_struct(&png_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_write_struct():
+
+ png_structp png_ptr = png_create_write_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+After you have these structures, you will need to set up the
+error handling. When libpng encounters an error, it expects to
+longjmp() back to your routine. Therefore, you will need to call
+setjmp() and pass the png_jmpbuf(png_ptr). If you
+write the file from different routines, you will need to update
+the png_jmpbuf(png_ptr) every time you enter a new routine that will
+call a png_*() function. See your documentation of setjmp/longjmp
+for your compiler for more information on setjmp/longjmp. See
+the discussion on libpng error handling in the Customizing Libpng
+section below for more information on the libpng error handling.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(fp);
+ return (ERROR);
+ }
+ ...
+ return;
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the output code. The default for libpng is to
+use the C function fwrite(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. Again, if you wish to handle writing data in
+another way, see the discussion on libpng I/O handling in the Customizing
+Libpng section below.
+
+ png_init_io(png_ptr, fp);
+
+If you are embedding your PNG into a datastream such as MNG, and don't
+want libpng to write the 8-byte signature, or if you have already
+written the signature in your application, use
+
+ png_set_sig_bytes(png_ptr, 8);
+
+to inform libpng that it should not write a signature.
+
+Write callbacks
+
+At this point, you can set up a callback function that will be
+called after each row has been written, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void write_row_callback(png_ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "write_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_write_status_fn(png_ptr, write_row_callback);
+
+You now have the option of modifying how the compression library will
+run. The following functions are mainly for testing, but may be useful
+in some cases, like if you need to write PNG files extremely fast and
+are willing to give up some compression, or if you want to get the
+maximum possible compression at the expense of slower writing. If you
+have no special needs in this area, let the library do what it wants by
+not calling this function at all, as it has been tuned to deliver a good
+speed/compression ratio. The second parameter to png_set_filter() is
+the filter method, for which the only valid values are 0 (as of the
+July 1999 PNG specification, version 1.2) or 64 (if you are writing
+a PNG datastream that is to be embedded in a MNG datastream). The third
+parameter is a flag that indicates which filter type(s) are to be tested
+for each scanline. See the PNG specification for details on the specific
+filter types.
+
+
+ /* turn on or off filtering, and/or choose
+ specific filters. You can use either a single
+ PNG_FILTER_VALUE_NAME or the bitwise OR of one
+ or more PNG_FILTER_NAME masks. */
+ png_set_filter(png_ptr, 0,
+ PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE |
+ PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB |
+ PNG_FILTER_UP | PNG_FILTER_VALUE_UP |
+ PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG |
+ PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+ PNG_ALL_FILTERS);
+
+If an application
+wants to start and stop using particular filters during compression,
+it should start out with all of the filters (to ensure that the previous
+row of pixels will be stored in case it's needed later), and then add
+and remove them after the start of compression.
+
+If you are writing a PNG datastream that is to be embedded in a MNG
+datastream, the second parameter can be either 0 or 64.
+
+The png_set_compression_*() functions interface to the zlib compression
+library, and should mostly be ignored unless you really know what you are
+doing. The only generally useful call is png_set_compression_level()
+which changes how much time zlib spends on trying to compress the image
+data. See the Compression Library (zlib.h and algorithm.txt, distributed
+with zlib) for details on the compression levels.
+
+ /* set the zlib compression level */
+ png_set_compression_level(png_ptr,
+ Z_BEST_COMPRESSION);
+
+ /* set other zlib parameters */
+ png_set_compression_mem_level(png_ptr, 8);
+ png_set_compression_strategy(png_ptr,
+ Z_DEFAULT_STRATEGY);
+ png_set_compression_window_bits(png_ptr, 15);
+ png_set_compression_method(png_ptr, 8);
+ png_set_compression_buffer_size(png_ptr, 8192)
+
+extern PNG_EXPORT(void,png_set_zbuf_size)
+
+Setting the contents of info for output
+
+You now need to fill in the png_info structure with all the data you
+wish to write before the actual image. Note that the only thing you
+are allowed to write after the image is the text chunks and the time
+chunk (as of PNG Specification 1.2, anyway). See png_write_end() and
+the latest PNG specification for more information on that. If you
+wish to write them before the image, fill them in now, and flag that
+data as being valid. If you want to wait until after the data, don't
+fill them until png_write_end(). For all the fields in png_info and
+their data types, see png.h. For explanations of what the fields
+contain, see the PNG specification.
+
+Some of the more important parts of the png_info are:
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ bit_depth, color_type, interlace_type,
+ compression_type, filter_method)
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels.
+ (valid values are 1, 2, 4, 8, 16
+ and depend also on the
+ color_type. See also significant
+ bits (sBIT) below).
+ color_type - describes which color/alpha
+ channels are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ interlace_type - PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7
+ compression_type - (must be
+ PNG_COMPRESSION_TYPE_DEFAULT)
+ filter_method - (must be PNG_FILTER_TYPE_DEFAULT
+ or, if you are writing a PNG to
+ be embedded in a MNG datastream,
+ can also be
+ PNG_INTRAPIXEL_DIFFERENCING)
+
+If you call png_set_IHDR(), the call must appear before any of the
+other png_set_*() functions, because they might require access to some of
+the IHDR settings. The remaining png_set_*() functions can be called
+in any order.
+
+If you wish, you can reset the compression_type, interlace_type, or
+filter_method later by calling png_set_IHDR() again; if you do this, the
+width, height, bit_depth, and color_type must be the same in each call.
+
+ png_set_PLTE(png_ptr, info_ptr, palette,
+ num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_set_gAMA(png_ptr, info_ptr, gamma);
+ gamma - the gamma the image was created
+ at (PNG_INFO_gAMA)
+
+ png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of
+ the sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This chunk also implies specific
+ values of gAMA and cHRM. Rendering
+ intent is the CSS-1 property that
+ has been defined by the International
+ Color Consortium
+ (http://www.color.org).
+ It can be one of
+ PNG_sRGB_INTENT_SATURATION,
+ PNG_sRGB_INTENT_PERCEPTUAL,
+ PNG_sRGB_INTENT_ABSOLUTE, or
+ PNG_sRGB_INTENT_RELATIVE.
+
+
+ png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
+ srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of the
+ sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This function also causes gAMA and
+ cHRM chunks with the specific values
+ that are consistent with sRGB to be
+ written.
+
+ png_set_iCCP(png_ptr, info_ptr, name, compression_type,
+ profile, proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_set_sBIT(png_ptr, info_ptr, sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray, red,
+ green, and blue channels, whichever are
+ appropriate for the given color type
+ (png_color_16)
+
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans,
+ trans_values);
+ trans - array of transparent
+ entries for palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values
+ (in order red, green, blue) of the
+ single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_set_hIST(png_ptr, info_ptr, hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_set_tIME(png_ptr, info_ptr, mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_set_bKGD(png_ptr, info_ptr, background);
+ background - background color (PNG_VALID_bKGD)
+
+ png_set_text(png_ptr, info_ptr, text_ptr, num_text);
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be NULL or empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (NULL or
+ empty for unknown).
+ text_ptr[i].translated_keyword - keyword in UTF-8 (NULL
+ or empty for unknown).
+ Note that the itxt_length, lang, and lang_key
+ members of the text_ptr structure only exist
+ when the library is built with iTXt chunk support.
+
+ num_text - number of comments
+
+ png_set_sPLT(png_ptr, info_ptr, &palette_ptr,
+ num_spalettes);
+ palette_ptr - array of png_sPLT_struct structures
+ to be added to the list of palettes
+ in the info structure.
+ num_spalettes - number of palette structures to be
+ added.
+
+ png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y,
+ unit_type);
+ offset_x - positive offset from the left
+ edge of the screen
+ offset_y - positive offset from the top
+ edge of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
+ unit_type);
+ res_x - pixels/unit physical resolution
+ in x direction
+ res_y - pixels/unit physical resolution
+ in y direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_set_sCAL(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_set_sCAL_s(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ png_set_unknown_chunks(png_ptr, info_ptr, &unknowns,
+ num_unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position to write chunk in file
+ 0: do not write chunk
+ PNG_HAVE_IHDR: before PLTE
+ PNG_HAVE_PLTE: before IDAT
+ PNG_AFTER_IDAT: after IDAT
+
+The "location" member is set automatically according to
+what part of the output file has already been written.
+You can change its value after calling png_set_unknown_chunks()
+as demonstrated in pngtest.c. Within each of the "locations",
+the chunks are sequenced according to their position in the
+structure (that is, the value of "i", which is the order in which
+the chunk was either read from the input file or defined with
+png_set_unknown_chunks).
+
+A quick word about text and num_text. text is an array of png_text
+structures. num_text is the number of valid structures in the array.
+Each png_text structure holds a language code, a keyword, a text value,
+and a compression type.
+
+The compression types have the same valid numbers as the compression
+types of the image data. Currently, the only valid number is zero.
+However, you can store text either compressed or uncompressed, unlike
+images, which always have to be compressed. So if you don't want the
+text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
+Because tEXt and zTXt chunks don't have a language field, if you
+specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt
+any language code or translated keyword will not be written out.
+
+Until text gets around 1000 bytes, it is not worth compressing it.
+After the text has been written out to the file, the compression type
+is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
+so that it isn't written out again at the end (in case you are calling
+png_write_end() with the same struct.
+
+The keywords that are given in the PNG Specification are:
+
+ Title Short (one line) title or
+ caption for image
+ Author Name of image's creator
+ Description Description of image (possibly long)
+ Copyright Copyright notice
+ Creation Time Time of original image creation
+ (usually RFC 1123 format, see below)
+ Software Software used to create the image
+ Disclaimer Legal disclaimer
+ Warning Warning of nature of content
+ Source Device used to create the image
+ Comment Miscellaneous comment; conversion
+ from other image format
+
+The keyword-text pairs work like this. Keywords should be short
+simple descriptions of what the comment is about. Some typical
+keywords are found in the PNG specification, as is some recommendations
+on keywords. You can repeat keywords in a file. You can even write
+some text before the image and some after. For example, you may want
+to put a description of the image before the image, but leave the
+disclaimer until after, so viewers working over modem connections
+don't have to wait for the disclaimer to go over the modem before
+they start seeing the image. Finally, keywords should be full
+words, not abbreviations. Keywords and text are in the ISO 8859-1
+(Latin-1) character set (a superset of regular ASCII) and can not
+contain NUL characters, and should not contain control or other
+unprintable characters. To make the comments widely readable, stick
+with basic ASCII, and avoid machine specific character set extensions
+like the IBM-PC character set. The keyword must be present, but
+you can leave off the text string on non-compressed pairs.
+Compressed pairs must have a text string, as only the text string
+is compressed anyway, so the compression would be meaningless.
+
+PNG supports modification time via the png_time structure. Two
+conversion routines are provided, png_convert_from_time_t() for
+time_t and png_convert_from_struct_tm() for struct tm. The
+time_t routine uses gmtime(). You don't have to use either of
+these, but if you wish to fill in the png_time structure directly,
+you should provide the time in universal time (GMT) if possible
+instead of your local time. Note that the year number is the full
+year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and
+that months start with 1.
+
+If you want to store the time of the original image creation, you should
+use a plain tEXt chunk with the "Creation Time" keyword. This is
+necessary because the "creation time" of a PNG image is somewhat vague,
+depending on whether you mean the PNG file, the time the image was
+created in a non-PNG format, a still photo from which the image was
+scanned, or possibly the subject matter itself. In order to facilitate
+machine-readable dates, it is recommended that the "Creation Time"
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
+although this isn't a requirement. Unlike the tIME chunk, the
+"Creation Time" tEXt chunk is not expected to be automatically changed
+by the software. To facilitate the use of RFC 1123 dates, a function
+png_convert_to_rfc1123(png_timep) is provided to convert from PNG
+time to an RFC 1123 format string.
+
+Writing unknown chunks
+
+You can use the png_set_unknown_chunks function to queue up chunks
+for writing. You give it a chunk name, raw data, and a size; that's
+all there is to it. The chunks will be written by the next following
+png_write_info_before_PLTE, png_write_info, or png_write_end function.
+Any chunks previously read into the info structure's unknown-chunk
+list will also be written out in a sequence that satisfies the PNG
+specification's ordering rules.
+
+The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+in the info structure. All defined output
+transformations are permitted, enabled by the following masks.
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+ PNG_TRANSFORM_STRIP_FILLER Strip out filler
+ bytes (deprecated).
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading
+ filler bytes
+ PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing
+ filler bytes
+
+If you have valid image data in the info structure (you can use
+png_set_rows() to put image data in the info structure), simply do this:
+
+ png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of some set of
+transformation flags. This call is equivalent to png_write_info(),
+followed the set of transformations indicated by the transform mask,
+then png_write_image(), and finally png_write_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future output transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_write_png().
+
+The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data. You do
+this with a call to png_write_info().
+
+ png_write_info(png_ptr, info_ptr);
+
+Note that there is one transformation you may need to do before
+png_write_info(). In PNG files, the alpha channel in an image is the
+level of opacity. If your data is supplied as a level of transparency,
+you can invert the alpha channel before you write it, so that 0 is
+fully transparent and 255 (in 8-bit or paletted images) or 65535
+(in 16-bit images) is fully opaque, with
+
+ png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written. If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
+If you need to write a private chunk that you want to appear before
+the PLTE chunk when PLTE is present, you can write the PNG info in
+two steps, and insert code to write your own chunk between them:
+
+ png_write_info_before_PLTE(png_ptr, info_ptr);
+ png_set_unknown_chunks(png_ptr, info_ptr, ...);
+ png_write_info(png_ptr, info_ptr);
+
+After you've written the file information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code tells
+the library to strip input data that has 4 or 8 bytes per pixel down
+to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2
+bytes per pixel).
+
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+where the 0 is unused, and the location is either PNG_FILLER_BEFORE or
+PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel
+is stored XRGB or RGBX.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit files.
+If the data is supplied at 1 pixel per byte, use this code, which will
+correctly pack the pixels into a single byte:
+
+ png_set_packing(png_ptr);
+
+PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your
+data is of another bit depth, you can write an sBIT chunk into the
+file so that decoders can recover the original data if desired.
+
+ /* Set the true bit depth of the image data */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ sig_bit.red = true_bit_depth;
+ sig_bit.green = true_bit_depth;
+ sig_bit.blue = true_bit_depth;
+ }
+ else
+ {
+ sig_bit.gray = true_bit_depth;
+ }
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ sig_bit.alpha = true_bit_depth;
+ }
+
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+If the data is stored in the row buffer in a bit depth other than
+one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG),
+this will scale the values to appear to be the correct bit depth as
+is required by PNG.
+
+ png_set_shift(png_ptr, &sig_bit);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code would be used if they are
+supplied the other way (little-endian, i.e. least significant bits
+first, the way PCs store them):
+
+ if (bit_depth > 8)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+PNG files store 3 color pixels in red, green, blue order. This code
+would be used if they are supplied as blue, green, red:
+
+ png_set_bgr(png_ptr);
+
+PNG files describe monochrome as black being zero and white being
+one. This code would be used if the pixels are supplied with this reversed
+(black being one and white being zero):
+
+ png_set_invert_mono(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_write_user_transform_fn(png_ptr,
+ write_transform_fn);
+
+You must supply the function
+
+ void write_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+before any of the other transformations are processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function.
+
+ png_set_user_transform_info(png_ptr, user_ptr, 0, 0);
+
+The user_channels and user_depth parameters of this function are ignored
+when writing; you can set them to zero as shown.
+
+You can retrieve the pointer via the function png_get_user_transform_ptr().
+For example:
+
+ voidp write_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+It is possible to have libpng flush any pending output, either manually,
+or automatically after a certain number of lines have been written. To
+flush the output stream a single time call:
+
+ png_write_flush(png_ptr);
+
+and to have libpng flush the output stream periodically after a certain
+number of scanlines have been written, call:
+
+ png_set_flush(png_ptr, nrows);
+
+Note that the distance between rows is from the last time png_write_flush()
+was called, or the first row of the image if it has never been called.
+So if you write 50 lines, and then png_set_flush 25, it will flush the
+output on the next scanline, and every 25 lines thereafter, unless
+png_write_flush() is called before 25 more lines have been written.
+If nrows is too small (less than about 10 lines for a 640 pixel wide
+RGB image) the image compression may decrease noticeably (although this
+may be acceptable for real-time applications). Infrequent flushing will
+only degrade the compression performance by a few percent over images
+that do not use flushing.
+
+Writing the image data
+
+That's it for the transformations. Now you can write the image data.
+The simplest way to do this is in one function call. If you have the
+whole image in memory, you can just call png_write_image() and libpng
+will write the image. You will need to pass in an array of pointers to
+each row. This function automatically handles interlacing, so you don't
+need to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_write_rows().
+
+ png_write_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_byte *row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to write the whole image at once, you can
+use png_write_rows() instead. If the file is not interlaced,
+this is simple:
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+row_pointers is the same as in the png_write_image() call.
+
+If you are just writing one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+
+ png_write_row(png_ptr, row_pointer);
+
+When the file is interlaced, things can get a good deal more complicated.
+The only currently (as of the PNG Specification version 1.2, dated July
+1999) defined interlacing scheme for PNG files is the "Adam7" interlace
+scheme, that breaks down an image into seven smaller images of varying
+size. libpng will build these images for you, or you can do them
+yourself. If you want to build them yourself, see the PNG specification
+for details of which pixels to write when.
+
+If you don't want libpng to handle the interlacing details, just
+use png_set_interlace_handling() and call png_write_rows() the
+correct number of times to write all seven sub-images.
+
+If you want libpng to build the sub-images, call this before you start
+writing any rows:
+
+ number_of_passes =
+ png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this is seven,
+but may change if another interlace type is added.
+
+Then write the complete image number_of_passes times.
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+As some of these rows are not used, and thus return immediately, you may
+want to read about interlacing in the PNG specification, and only update
+the rows that are actually used.
+
+Finishing a sequential write
+
+After you are finished writing the image, you should finish writing
+the file. If you are interested in writing comments or time, you should
+pass an appropriately filled png_info pointer. If you are not interested,
+you can pass NULL.
+
+ png_write_end(png_ptr, info_ptr);
+
+When you are done, you can free all memory used by libpng like this:
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those cases do nothing.
+The "seq" parameter is ignored if only one item of the selected data
+type, such as PLTE, is allowed. If "seq" is not -1, and multiple items
+are allowed for the data type identified in the mask, such as text or
+sPLT, only the n'th item in the structure is freed, where n is "seq".
+
+If you allocated data such as a palette that you passed in to libpng
+with png_set_*, you must not free it until just before the call to
+png_destroy_write_struct().
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+For example, to transfer responsibility for some data from a read structure
+to a write structure, you could use
+
+ png_data_freer(read_ptr, read_info_ptr,
+ PNG_USER_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+ png_data_freer(write_ptr, write_info_ptr,
+ PNG_DESTROY_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+
+thereby briefly reassigning responsibility for freeing to the user but
+immediately afterwards reassigning it once more to the write_destroy
+function. Having done this, it would then be safe to destroy the read
+structure and continue to use the PLTE, tRNS, and hIST data in the write
+structure.
+
+This function only affects data that has already been allocated.
+You can call this function before calling after the png_set_*() functions
+to control whether the user or png_destroy_*() is supposed to free the data.
+When the user assumes responsibility for libpng-allocated data, the
+application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+For a more compact example of writing a PNG image, see the file example.c.
+
+V. Modifying/Customizing libpng:
+
+There are two issues here. The first is changing how libpng does
+standard things like memory allocation, input/output, and error handling.
+The second deals with more complicated things like adding new chunks,
+adding new transformations, and generally changing how libpng works.
+Both of those are compile-time issues; that is, they are generally
+determined at the time the code is written, and there is rarely a need
+to provide the user with a means of changing them.
+
+Memory allocation, input/output, and error handling
+
+All of the memory allocation, input/output, and error handling in libpng
+goes through callbacks that are user-settable. The default routines are
+in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change
+these functions, call the appropriate png_set_*_fn() function.
+
+Memory allocation is done through the functions png_malloc(), png_calloc(),
+and png_free(). These currently just call the standard C functions.
+png_calloc() calls png_malloc() and then png_memset() to clear the newly
+allocated memory to zero. If your pointers can't access more then 64K
+at a time, you will want to set MAXSEG_64K in zlib.h. Since it is
+unlikely that the method of handling memory allocation on a platform
+will change between applications, these functions must be modified in
+the library at compile time. If you prefer to use a different method
+of allocating and freeing data, you can use png_create_read_struct_2() or
+png_create_write_struct_2() to register your own functions as described
+above. These functions also provide a void pointer that can be retrieved
+via
+
+ mem_ptr=png_get_mem_ptr(png_ptr);
+
+Your replacement memory functions must have prototypes as follows:
+
+ png_voidp malloc_fn(png_structp png_ptr,
+ png_size_t size);
+ void free_fn(png_structp png_ptr, png_voidp ptr);
+
+Your malloc_fn() must return NULL in case of failure. The png_malloc()
+function will normally call png_error() if it receives a NULL from the
+system memory allocator or from your replacement malloc_fn().
+
+Your free_fn() will never be called with a NULL ptr, since libpng's
+png_free() checks for NULL before calling free_fn().
+
+Input/Output in libpng is done through png_read() and png_write(),
+which currently just call fread() and fwrite(). The FILE * is stored in
+png_struct and is initialized via png_init_io(). If you wish to change
+the method of I/O, the library supplies callbacks that you can set
+through the function png_set_read_fn() and png_set_write_fn() at run
+time, instead of calling the png_init_io() function. These functions
+also provide a void pointer that can be retrieved via the function
+png_get_io_ptr(). For example:
+
+ png_set_read_fn(png_structp read_ptr,
+ voidp read_io_ptr, png_rw_ptr read_data_fn)
+
+ png_set_write_fn(png_structp write_ptr,
+ voidp write_io_ptr, png_rw_ptr write_data_fn,
+ png_flush_ptr output_flush_fn);
+
+ voidp read_io_ptr = png_get_io_ptr(read_ptr);
+ voidp write_io_ptr = png_get_io_ptr(write_ptr);
+
+The replacement I/O functions must have prototypes as follows:
+
+ void user_read_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_write_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_flush_data(png_structp png_ptr);
+
+The user_read_data() function is responsible for detecting and
+handling end-of-data errors.
+
+Supplying NULL for the read, write, or flush functions sets them back
+to using the default C stream functions, which expect the io_ptr to
+point to a standard *FILE structure. It is probably a mistake
+to use NULL for one of write_data_fn and output_flush_fn but not both
+of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined.
+It is an error to read from a write stream, and vice versa.
+
+Error handling in libpng is done through png_error() and png_warning().
+Errors handled through png_error() are fatal, meaning that png_error()
+should never return to its caller. Currently, this is handled via
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
+to print a warning message, and then control returns to the calling code.
+By default png_error() and png_warning() print a message on stderr via
+fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined
+(because you don't want the messages) or PNG_NO_STDIO defined (because
+fprintf() isn't available). If you wish to change the behavior of the error
+functions, you will need to set up your own message callbacks. These
+functions are normally supplied at the time that the png_struct is created.
+It is also possible to redirect errors and warnings to your own replacement
+functions after png_create_*_struct() has been called by calling:
+
+ png_set_error_fn(png_structp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn,
+ png_error_ptr warning_fn);
+
+ png_voidp error_ptr = png_get_error_ptr(png_ptr);
+
+If NULL is supplied for either error_fn or warning_fn, then the libpng
+default function will be used, calling fprintf() and/or longjmp() if a
+problem is encountered. The replacement error functions should have
+parameters as follows:
+
+ void user_error_fn(png_structp png_ptr,
+ png_const_charp error_msg);
+ void user_warning_fn(png_structp png_ptr,
+ png_const_charp warning_msg);
+
+The motivation behind using setjmp() and longjmp() is the C++ throw and
+catch exception handling methods. This makes the code much easier to write,
+as there is no need to check every return code of every function call.
+However, there are some uncertainties about the status of local variables
+after a longjmp, so the user may want to be careful about doing anything
+after setjmp returns non-zero besides returning itself. Consult your
+compiler documentation for more details. For an alternative approach, you
+may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net).
+
+Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code. The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks. However, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of understanding of how it works.
+Pay particular attention to the sections that describe chunk names,
+and look at how other chunks were designed, so you can do things
+similarly. Second, check out the sections of libpng that read and
+write chunks. Try to find a chunk that is similar to yours and use
+it as a template. More details can be found in the comments inside
+the code. It is best to handle unknown chunks in a generic method,
+via callback functions, instead of by modifying libpng functions.
+
+If you wish to write your own transformation for the data, look through
+the part of the code that does the transformations, and check out some of
+the simpler ones to get an idea of how they work. Try to find a similar
+transformation to the one you want to add and copy off of it. More details
+can be found in the comments inside the code itself.
+
+Configuring for 16 bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more then 64K at a time. Even if you can, the memory
+won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call. See zlib.h or zconf.h in the zlib library for more information.
+
+Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set. Everything in the library (except for zlib's structure) is
+expecting far data. You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful). Make
+note that the rows of data are defined as png_bytepp, which is an
+unsigned char far * far *.
+
+Configuring for gui/windowing platforms:
+
+You will need to write new error and warning functions that use the GUI
+interface, as described previously, and set them to be the error and
+warning functions at the time that png_create_*_struct() is called,
+in order to have them available during the structure initialization.
+They can be changed later via png_set_error_fn(). On some compilers,
+you may also have to change the memory allocators (png_malloc, etc.).
+
+Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h. If you need to add, change
+or delete an include, this is the place to do it.
+The includes that are not needed outside libpng are protected by the
+PNG_INTERNAL definition, which is only defined for those routines inside
+libpng itself. The files in libpng proper only include png.h, which
+includes pngconf.h.
+
+Configuring zlib:
+
+There are special functions to configure the compression. Perhaps the
+most useful one changes the compression level, which currently uses
+input compression values in the range 0 - 9. The library normally
+uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests
+have shown that for a large majority of images, compression values in
+the range 3-6 compress nearly as well as higher levels, and do so much
+faster. For online applications it may be desirable to have maximum speed
+(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also
+specify no compression (Z_NO_COMPRESSION = 0), but this would create
+files larger than just storing the raw bitmap. You can specify the
+compression level by calling:
+
+ png_set_compression_level(png_ptr, level);
+
+Another useful one is to reduce the memory level used by the library.
+The memory level defaults to 8, but it can be lowered if you are
+short on memory (running DOS, for example, where you only have 640K).
+Note that the memory level does have an effect on compression; among
+other things, lower levels will result in sections of incompressible
+data being emitted in smaller stored blocks, with a correspondingly
+larger relative overhead of up to 15% in the worst case.
+
+ png_set_compression_mem_level(png_ptr, level);
+
+The other functions are for configuring zlib. They are not recommended
+for normal use and may result in writing an invalid PNG file. See
+zlib.h for more information on what these mean.
+
+ png_set_compression_strategy(png_ptr,
+ strategy);
+ png_set_compression_window_bits(png_ptr,
+ window_bits);
+ png_set_compression_method(png_ptr, method);
+ png_set_compression_buffer_size(png_ptr, size);
+
+Controlling row filtering
+
+If you want to control whether libpng uses filtering or not, which
+filters are used, and how it goes about picking row filters, you
+can call one of these functions. The selection and configuration
+of row filters can have a significant impact on the size and
+encoding speed and a somewhat lesser impact on the decoding speed
+of an image. Filtering is enabled by default for RGB and grayscale
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
+
+The 'method' parameter sets the main filtering method, which is
+currently only '0' in the PNG 1.2 specification. The 'filters'
+parameter sets which filter(s), if any, should be used for each
+scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
+to turn filtering on and off, respectively.
+
+Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
+PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
+ORed together with '|' to specify one or more filters to use.
+These filters are described in more detail in the PNG specification.
+If you intend to change the filter type during the course of writing
+the image, you should start with flags set for all of the filters
+you intend to use so that libpng can initialize its internal
+structures appropriately for all of the filter types. (Note that this
+means the first row must always be adaptively filtered, because libpng
+currently does not allocate the filter buffers until png_write_row()
+is called for the first time.)
+
+ filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+ PNG_FILTER_UP | PNG_FILTER_AVG |
+ PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
+ filters);
+ The second parameter can also be
+ PNG_INTRAPIXEL_DIFFERENCING if you are
+ writing a PNG to be embedded in a MNG
+ datastream. This parameter must be the
+ same as the value of filter_method used
+ in png_set_IHDR().
+
+It is also possible to influence how libpng chooses from among the
+available filters. This is done in one or both of two ways - by
+telling it how important it is to keep the same filter for successive
+rows, and by telling it the relative computational costs of the filters.
+
+ double weights[3] = {1.5, 1.3, 1.1},
+ costs[PNG_FILTER_VALUE_LAST] =
+ {1.0, 1.3, 1.3, 1.5, 1.7};
+
+ png_set_filter_heuristics(png_ptr,
+ PNG_FILTER_HEURISTIC_WEIGHTED, 3,
+ weights, costs);
+
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter. In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+"sum of absolute differences" 1.5 x 1.3 times higher than other filters
+and still be chosen, while the NONE filter could have a sum 1.1 times
+higher than other filters and still be chosen. Unspecified weights are
+taken to be 1.0, and the specified weights should probably be declining
+like those above in order to emphasize recent filters over older filters.
+
+The filter costs specify for each filter type a relative decoding cost
+to be considered when selecting row filters. This means that filters
+with higher costs are less likely to be chosen over filters with lower
+costs, unless their "sum of absolute differences" is that much smaller.
+The costs do not necessarily reflect the exact computational speeds of
+the various filters, since this would unduly influence the final image
+size.
+
+Note that the numbers above were invented purely for this example and
+are given only to help explain the function usage. Little testing has
+been done to find optimum values for either the costs or the weights.
+
+Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled. All the defines end in _SUPPORTED. If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
+along with directives to turn on any of the capabilities that you do
+want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra
+transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks. Use of the
+PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
+that is incapable of reading or writing ancillary chunks. If you are
+not using the progressive reading capability, you can turn that off
+with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
+capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs. However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with pngr and all the writing files start with
+pngw. The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+Requesting debug printout
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout. Set it to an integer value in the range 0 to 3. Higher
+numbers result in increasing amounts of debugging information. The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+ png_debug(level, message)
+ png_debug1(level, message, p1)
+ png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives. For example,
+
+ png_debug1(2, "foo=%d\n", foo);
+
+is expanded to
+
+ if(PNG_DEBUG > 2)
+ fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+ #ifdef PNG_DEBUG
+ fprintf(stderr, ...
+ #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed. There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+VI. MNG support
+
+The MNG specification (available at http://www.libpng.org/pub/mng) allows
+certain extensions to PNG for PNG images that are embedded in MNG datastreams.
+Libpng can support some of these extensions. To enable them, use the
+png_permit_mng_features() function:
+
+ feature_set = png_permit_mng_features(png_ptr, mask)
+ mask is a png_uint_32 containing the bitwise OR of the
+ features you want to enable. These include
+ PNG_FLAG_MNG_EMPTY_PLTE
+ PNG_FLAG_MNG_FILTER_64
+ PNG_ALL_MNG_FEATURES
+ feature_set is a png_uint_32 that is the bitwise AND of
+ your mask with the set of MNG features that is
+ supported by the version of libpng that you are using.
+
+It is an error to use this function when reading or writing a standalone
+PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped
+in a MNG datastream. As a minimum, it must have the MNG 8-byte signature
+and the MHDR and MEND chunks. Libpng does not provide support for these
+or any other MNG chunks; your application must provide its own support for
+them. You may wish to consider using libmng (available at
+http://www.libmng.com) instead.
+
+VII. Changes to Libpng from version 0.88
+
+It should be noted that versions of libpng later than 0.96 are not
+distributed by the original libpng author, Guy Schalnat, nor by
+Andreas Dilger, who had taken over from Guy during 1996 and 1997, and
+distributed versions 0.89 through 0.96, but rather by another member
+of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are
+still alive and well, but they have moved on to other things.
+
+The old libpng functions png_read_init(), png_write_init(),
+png_info_init(), png_read_destroy(), and png_write_destroy() have been
+moved to PNG_INTERNAL in version 0.95 to discourage their use. These
+functions will be removed from libpng version 2.0.0.
+
+The preferred method of creating and initializing the libpng structures is
+via the png_create_read_struct(), png_create_write_struct(), and
+png_create_info_struct() because they isolate the size of the structures
+from the application, allow version error checking, and also allow the
+use of custom error handling routines during the initialization, which
+the old functions do not. The functions png_read_destroy() and
+png_write_destroy() do not actually free the memory that libpng
+allocated for these structs, but just reset the data structures, so they
+can be used instead of png_destroy_read_struct() and
+png_destroy_write_struct() if you feel there is too much system overhead
+allocating and freeing the png_struct for each image read.
+
+Setting the error callbacks via png_set_message_fn() before
+png_read_init() as was suggested in libpng-0.88 is no longer supported
+because this caused applications that do not use custom error functions
+to fail if the png_ptr was not initialized to zero. It is still possible
+to set the error callbacks AFTER png_read_init(), or to change them with
+png_set_error_fn(), which is essentially the same function, but with a new
+name to force compilation errors with applications that try to use the old
+method.
+
+Starting with version 1.0.7, you can find out which version of the library
+you are using at run-time:
+
+ png_uint_32 libpng_vn = png_access_version_number();
+
+The number libpng_vn is constructed from the major version, minor
+version with leading zero, and release number with leading zero,
+(e.g., libpng_vn for version 1.0.7 is 10007).
+
+You can also check which version of png.h you used when compiling your
+application:
+
+ png_uint_32 application_vn = PNG_LIBPNG_VER;
+
+VIII. Changes to Libpng from version 1.0.x to 1.2.x
+
+Support for user memory management was enabled by default. To
+accomplish this, the functions png_create_read_struct_2(),
+png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(),
+png_malloc_default(), and png_free_default() were added.
+
+Support for the iTXt chunk has been enabled by default as of
+version 1.2.41.
+
+Support for certain MNG features was enabled.
+
+Support for numbered error messages was added. However, we never got
+around to actually numbering the error messages. The function
+png_set_strip_error_numbers() was added (Note: the prototype for this
+function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE
+builds of libpng-1.2.15. It was restored in libpng-1.2.36).
+
+The png_malloc_warn() function was added at libpng-1.2.3. This issues
+a png_warning and returns NULL instead of aborting when it fails to
+acquire the requested memory allocation.
+
+Support for setting user limits on image width and height was enabled
+by default. The functions png_set_user_limits(), png_get_user_width_max(),
+and png_get_user_height_max() were added at libpng-1.2.6.
+
+The png_set_add_alpha() function was added at libpng-1.2.7.
+
+The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9.
+Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the
+tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is
+deprecated.
+
+A number of macro definitions in support of runtime selection of
+assembler code features (especially Intel MMX code support) were
+added at libpng-1.2.0:
+
+ PNG_ASM_FLAG_MMX_SUPPORT_COMPILED
+ PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU
+ PNG_ASM_FLAG_MMX_READ_COMBINE_ROW
+ PNG_ASM_FLAG_MMX_READ_INTERLACE
+ PNG_ASM_FLAG_MMX_READ_FILTER_SUB
+ PNG_ASM_FLAG_MMX_READ_FILTER_UP
+ PNG_ASM_FLAG_MMX_READ_FILTER_AVG
+ PNG_ASM_FLAG_MMX_READ_FILTER_PAETH
+ PNG_ASM_FLAGS_INITIALIZED
+ PNG_MMX_READ_FLAGS
+ PNG_MMX_FLAGS
+ PNG_MMX_WRITE_FLAGS
+ PNG_MMX_FLAGS
+
+We added the following functions in support of runtime
+selection of assembler code features:
+
+ png_get_mmx_flagmask()
+ png_set_mmx_thresholds()
+ png_get_asm_flags()
+ png_get_mmx_bitdepth_threshold()
+ png_get_mmx_rowbytes_threshold()
+ png_set_asm_flags()
+
+We replaced all of these functions with simple stubs in libpng-1.2.20,
+when the Intel assembler code was removed due to a licensing issue.
+
+These macros are deprecated:
+
+ PNG_READ_TRANSFORMS_NOT_SUPPORTED
+ PNG_PROGRESSIVE_READ_NOT_SUPPORTED
+ PNG_NO_SEQUENTIAL_READ_SUPPORTED
+ PNG_WRITE_TRANSFORMS_NOT_SUPPORTED
+ PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED
+ PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED
+
+They have been replaced, respectively, by:
+
+ PNG_NO_READ_TRANSFORMS
+ PNG_NO_PROGRESSIVE_READ
+ PNG_NO_SEQUENTIAL_READ
+ PNG_NO_WRITE_TRANSFORMS
+ PNG_NO_READ_ANCILLARY_CHUNKS
+ PNG_NO_WRITE_ANCILLARY_CHUNKS
+
+PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been
+deprecated since libpng-1.0.16 and libpng-1.2.6.
+
+The function
+ png_check_sig(sig, num)
+was replaced with
+ !png_sig_cmp(sig, 0, num)
+It has been deprecated since libpng-0.90.
+
+The function
+ png_set_gray_1_2_4_to_8()
+which also expands tRNS to alpha was replaced with
+ png_set_expand_gray_1_2_4_to_8()
+which does not. It has been deprecated since libpng-1.0.18 and 1.2.9.
+
+IX. (Omitted)
+
+
+X. Detecting libpng
+
+The png_get_io_ptr() function has been present since libpng-0.88, has never
+changed, and is unaffected by conditional compilation macros. It is the
+best choice for use in configure scripts for detecting the presence of any
+libpng version since 0.88. In an autoconf "configure.in" you could use
+
+ AC_CHECK_LIB(png, png_get_io_ptr, ...
+
+XI. Source code repository
+
+Since about February 2009, version 1.2.34, libpng has been under "git" source
+control. The git repository was built from old libpng-x.y.z.tar.gz files
+going back to version 0.70. You can access the git repository (read only)
+at
+
+ git://libpng.git.sourceforge.net/gitroot/libpng
+
+or you can browse it via "gitweb" at
+
+ http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng
+
+Patches can be sent to glennrp at users.sourceforge.net or to
+png-mng-implement at lists.sourceforge.net or you can upload them to
+the libpng bug tracker at
+
+ http://libpng.sourceforge.net
+
+XII. Coding style
+
+Our coding style is similar to the "Allman" style, with curly
+braces on separate lines:
+
+ if (condition)
+ {
+ action;
+ }
+
+ else if (another condition)
+ {
+ another action;
+ }
+
+The braces can be omitted from simple one-line actions:
+
+ if (condition)
+ return (0);
+
+We use 3-space indentation, except for continued statements which
+are usually indented the same as the first line of the statement
+plus four more spaces.
+
+For macro definitions we use 2-space indentation, always leaving the "#"
+in the first column.
+
+ #ifndef PNG_NO_FEATURE
+ # ifndef PNG_FEATURE_SUPPORTED
+ # define PNG_FEATURE_SUPPORTED
+ # endif
+ #endif
+
+Comments appear with the leading "/*" at the same indentation as
+the statement that follows the comment:
+
+ /* Single-line comment */
+ statement;
+
+ /* Multiple-line
+ * comment
+ */
+ statement;
+
+Very short comments can be placed at the end of the statement
+to which they pertain:
+
+ statement; /* comment */
+
+We don't use C++ style ("//") comments. We have, however,
+used them in the past in some now-abandoned MMX assembler
+code.
+
+Functions and their curly braces are not indented, and
+exported functions are marked with PNGAPI:
+
+ /* This is a public function that is visible to
+ * application programers. It does thus-and-so.
+ */
+ void PNGAPI
+ png_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for all exported functions appear in png.h,
+above the comment that says
+
+ /* Maintainer: Put new public prototypes here ... */
+
+We mark all non-exported functions with "/* PRIVATE */"":
+
+ void /* PRIVATE */
+ png_non_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for non-exported functions (except for those in
+pngtest) appear in
+the PNG_INTERNAL section of png.h
+above the comment that says
+
+ /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+The names of all exported functions and variables begin
+with "png_", and all publicly visible C preprocessor
+macros begin with "PNG".
+
+We put a space after each comma and after each semicolon
+in "for" statments, and we put spaces before and after each
+C binary operator and after "for" or "while". We don't
+put a space between a typecast and the expression being
+cast, nor do we put one between a function name and the
+left parenthesis that follows it:
+
+ for (i = 2; i > 0; --i)
+ y[i] = a(x) + (int)b;
+
+We prefer #ifdef and #ifndef to #if defined() and if !defined()
+when there is only one macro being tested.
+
+We do not use the TAB character for indentation in the C sources.
+
+Lines do not exceed 80 characters.
+
+Other rules can be inferred by inspecting the libpng source.
+
+XIII. Y2K Compliance in libpng
+
+March 29, 2012
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.71 and
+upward through 1.2.49 are Y2K compliant. It is my belief that earlier
+versions were also Y2K compliant.
+
+Libpng only has three year fields. One is a 2-byte unsigned integer that
+will hold years up to 65535. The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+ "png_uint_16 year" in png_time_struct.
+
+The strings are
+ "png_charp time_buffer" in png_struct and
+ "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+ png_convert_to_rfc_1123() in png.c
+ (formerly png_convert_to_rfc_1152() in error)
+ png_convert_from_struct_tm() in pngwrite.c, called
+ in pngwrite.c
+ png_convert_from_time_t() in pngwrite.c
+ png_get_tIME() in pngget.c
+ png_handle_tIME() in pngrutil.c, called in pngread.c
+ png_set_tIME() in pngset.c
+ png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment. The
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year. There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or that they are incorrectly passing only a 2-digit year
+instead of "year - 1900" into the png_convert_from_struct_tm() function,
+but this is not under our control. The libpng documentation has always
+stated that it works with 4-digit years, and the APIs have been
+documented as such.
+
+The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+zlib, upon which libpng depends, is also Y2K compliant. It contains
+no date-related code.
+
+
+ Glenn Randers-Pehrson
+ libpng maintainer
+ PNG Development Group
diff --git a/Source/LibPNG/libpng.3 b/Source/LibPNG/libpng.3
new file mode 100644
index 0000000..61e0017
--- /dev/null
+++ b/Source/LibPNG/libpng.3
@@ -0,0 +1,4510 @@
+.TH LIBPNG 3 "March 29, 2012"
+.SH NAME
+libpng \- Portable Network Graphics (PNG) Reference Library 1.2.49
+.SH SYNOPSIS
+\fI\fB
+
+\fB#include <png.h>\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_access_version_number \fI(void\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_check_sig (png_bytep \fP\fIsig\fP\fB, int \fInum\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_chunk_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_chunk_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_convert_from_struct_tm (png_timep \fP\fIptime\fP\fB, struct tm FAR * \fIttime\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_convert_from_time_t (png_timep \fP\fIptime\fP\fB, time_t \fIttime\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_charp png_convert_to_rfc1123 (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fIptime\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_infop png_create_info_struct (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_read_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_read_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_write_struct (png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarn_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_structp png_create_write_struct_2(png_const_charp \fP\fIuser_png_ver\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fP\fIwarn_fn\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug(int \fP\fIlevel\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug1(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fIp1\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_debug2(int \fP\fIlevel\fP\fB, png_const_charp \fP\fImessage\fP\fB, \fP\fIp1\fP\fB, \fIp2\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_info_struct (png_structp \fP\fIpng_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_read_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fP\fIinfo_ptr_ptr\fP\fB, png_infopp \fIend_info_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_destroy_write_struct (png_structpp \fP\fIpng_ptr_ptr\fP\fB, png_infopp \fIinfo_ptr_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_error (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fIerror\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_chunk_list (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_default(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fIptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_free_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fInum\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_bit_depth (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fI*background\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_channels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fI*white_x\fP\fB, double \fP\fI*white_y\fP\fB, double \fP\fI*red_x\fP\fB, double \fP\fI*red_y\fP\fB, double \fP\fI*green_x\fP\fB, double \fP\fI*green_y\fP\fB, double \fP\fI*blue_x\fP\fB, double \fI*blue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*white_x\fP\fB, png_uint_32 \fP\fI*white_y\fP\fB, png_uint_32 \fP\fI*red_x\fP\fB, png_uint_32 \fP\fI*red_y\fP\fB, png_uint_32 \fP\fI*green_x\fP\fB, png_uint_32 \fP\fI*green_y\fP\fB, png_uint_32 \fP\fI*blue_x\fP\fB, png_uint_32 \fI*blue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_color_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_compression_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_copyright (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_error_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_filter_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fI*file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fI*int_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_header_ver (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_header_version (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fI*hist\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charpp \fP\fIname\fP\fB, int \fP\fI*compression_type\fP\fB, png_charpp \fP\fIprofile\fP\fB, png_uint_32 \fI*proflen\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*width\fP\fB, png_uint_32 \fP\fI*height\fP\fB, int \fP\fI*bit_depth\fP\fB, int \fP\fI*color_type\fP\fB, int \fP\fI*interlace_type\fP\fB, int \fP\fI*compression_type\fP\fB, int \fI*filter_type\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_image_height (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_image_width (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fB#if \fI!defined(PNG_1_0_X)
+
+\fBpng_int_32 png_get_int_32 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB#endif
+
+\fI\fB
+
+\fBpng_byte png_get_interlace_type (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_io_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_libpng_ver (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_mem_ptr(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*offset_x\fP\fB, png_uint_32 \fP\fI*offset_y\fP\fB, int \fI*unit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fI*purpose\fP\fB, png_int_32 \fP\fI*X0\fP\fB, png_int_32 \fP\fI*X1\fP\fB, int \fP\fI*type\fP\fB, int \fP\fI*nparams\fP\fB, png_charp \fP\fI*units\fP\fB, png_charpp \fI*params\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fI*res_x\fP\fB, png_uint_32 \fP\fI*res_y\fP\fB, int \fI*unit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBfloat png_get_pixel_aspect_ratio (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_progressive_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fI*palette\fP\fB, int \fI*num_palette\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_byte png_get_rgb_to_gray_status (png_structp \fIpng_ptr)
+
+\fBpng_uint_32 png_get_rowbytes (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_bytepp png_get_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fI*sig_bit\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_bytep png_get_signature (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fI*splt_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fI*intent\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fI*text_ptr\fP\fB, int \fI*num_text\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fI*mod_time\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fI*trans\fP\fB, int \fP\fI*num_trans\fP\fB, png_color_16p \fI*trans_values\fP\fB);\fP
+
+\fI\fB
+
+\fB#if \fI!defined(PNG_1_0_X)
+
+\fBpng_uint_16 png_get_uint_16 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_uint_31 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_uint_32 (png_bytep \fIbuf\fP\fB);\fP
+
+\fI\fB#endif
+
+\fI\fB
+
+\fBpng_uint_32 png_get_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkpp \fIunknowns\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_user_chunk_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_user_height_max( png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_get_user_transform_ptr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_user_width_max (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_valid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIflag\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_x_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_x_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_x_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_y_offset_microns (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_int_32 png_get_y_offset_pixels (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_y_pixels_per_meter (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_get_compression_buffer_size (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_handle_as_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_init_io (png_structp \fP\fIpng_ptr\fP\fB, FILE \fI*fp\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_info_init (png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_info_init_2 (png_infopp \fP\fIptr_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_malloc (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_malloc_default(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidp png_memcpy (png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_size_t \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_memcpy_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, png_voidp \fP\fIs2\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidp png_memset (png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_size_t \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_voidp png_memset_check (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIs1\fP\fB, int \fP\fIvalue\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_permit_empty_plte (png_structp \fP\fIpng_ptr\fP\fB, int \fIempty_plte_permitted\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_process_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_progressive_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIold_row\fP\fB, png_bytep \fInew_row\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_infop \fIend_info_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_read_init (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_read_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fIdisplay_row\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_bytepp \fP\fIdisplay_row\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_read_update_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fB#if \fI!defined(PNG_1_0_X)
+
+\fBpng_save_int_32 (png_bytep \fP\fIbuf\fP\fB, png_int_32 \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_save_uint_16 (png_bytep \fP\fIbuf\fP\fB, unsigned int \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_save_uint_32 (png_bytep \fP\fIbuf\fP\fB, png_uint_32 \fIi\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_add_alpha (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP
+
+\fI\fB#endif
+
+\fI\fB
+
+\fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_bgr (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_16p \fIbackground\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_method (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_crc_action (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcrit_action\fP\fB, int \fIancil_action\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_dither (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fP\fInum_palette\fP\fB, int \fP\fImaximum_colors\fP\fB, png_uint_16p \fP\fIhistogram\fP\fB, int \fIfull_dither\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_error_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIerror_ptr\fP\fB, png_error_ptr \fP\fIerror_fn\fP\fB, png_error_ptr \fIwarning_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_expand (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_expand_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filler (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, int \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filter (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImethod\fP\fB, int \fIfilters\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_filter_heuristics (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIheuristic_method\fP\fB, int \fP\fInum_weights\fP\fB, png_doublep \fP\fIfilter_weights\fP\fB, png_doublep \fIfilter_costs\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_flush (png_structp \fP\fIpng_ptr\fP\fB, int \fInrows\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gamma (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIscreen_gamma\fP\fB, double \fIdefault_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gray_1_2_4_to_8(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_gray_to_rgb (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_16p \fIhist\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, png_uint_32 \fIproflen\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_set_interlace_handling (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invalid (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fImask\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invert_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_invert_mono (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_keep_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIkeep\fP\fB, png_bytep \fP\fIchunk_list\fP\fB, int \fInum_chunks\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_mem_fn(png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fImem_ptr\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_free_ptr \fIfree_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIoffset_x\fP\fB, png_uint_32 \fP\fIoffset_y\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_packing (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_packswap (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_palette_to_rgb(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fP\fIres_x\fP\fB, png_uint_32 \fP\fIres_y\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_progressive_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIprogressive_ptr\fP\fB, png_progressive_info_ptr \fP\fIinfo_fn\fP\fB, png_progressive_row_ptr \fP\fIrow_fn\fP\fB, png_progressive_end_ptr \fIend_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fIread_data_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_read_status_ptr \fIread_row_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIread_user_transform_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rgb_to_gray (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIerror_action\fP\fB, double \fP\fIred\fP\fB, double \fIgreen\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rgb_to_gray_fixed (png_structp \fP\fIpng_ptr\fP\fB, int error_action png_fixed_point \fP\fIred\fP\fB, png_fixed_point \fIgreen\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_rows (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytepp \fIrow_pointers\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_color_8p \fIsig_bit\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sig_bytes (png_structp \fP\fIpng_ptr\fP\fB, int \fInum_bytes\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_spalette_p \fP\fIsplt_ptr\fP\fB, int \fInum_spalettes\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_sRGB_gAMA_and_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_strip_16 (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_strip_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_swap (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_swap_alpha (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_text (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fP\fInum_trans\fP\fB, png_color_16p \fItrans_values\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_tRNS_to_alpha(png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBpng_uint_32 png_set_unknown_chunks (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_unknown_chunkp \fP\fIunknowns\fP\fB, int \fP\fInum\fP\fB, int \fIlocation\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_unknown_chunk_location(png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fIchunk\fP\fB, int \fIlocation\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_read_user_chunk_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_chunk_ptr\fP\fB, png_user_chunk_ptr \fIread_user_chunk_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_user_limits (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIuser_width_max\fP\fB, png_uint_32 \fIuser_height_max\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_user_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIuser_transform_ptr\fP\fB, int \fP\fIuser_transform_depth\fP\fB, int \fIuser_transform_channels\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_fn (png_structp \fP\fIpng_ptr\fP\fB, png_voidp \fP\fIio_ptr\fP\fB, png_rw_ptr \fP\fIwrite_data_fn\fP\fB, png_flush_ptr \fIoutput_flush_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_status_fn (png_structp \fP\fIpng_ptr\fP\fB, png_write_status_ptr \fIwrite_row_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_write_user_transform_fn (png_structp \fP\fIpng_ptr\fP\fB, png_user_transform_ptr \fIwrite_user_transform_fn\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_set_compression_buffer_size(png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBint png_sig_cmp (png_bytep \fP\fIsig\fP\fB, png_size_t \fP\fIstart\fP\fB, png_size_t \fInum_to_check\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_start_read_image (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_warning (png_structp \fP\fIpng_ptr\fP\fB, png_const_charp \fImessage\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_end (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_chunk_start (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIchunk_name\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_destroy (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_flush (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_image (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fIimage\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_write_init (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBDEPRECATED: void png_write_init_2 (png_structpp \fP\fIptr_ptr\fP\fB, png_const_charp \fP\fIuser_png_ver\fP\fB, png_size_t \fP\fIpng_struct_size\fP\fB, png_size_t \fIpng_info_size\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_info_before_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_png (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, int \fP\fItransforms\fP\fB, png_voidp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_write_rows (png_structp \fP\fIpng_ptr\fP\fB, png_bytepp \fP\fIrow\fP\fB, png_uint_32 \fInum_rows\fP\fB);\fP
+
+\fI\fB
+
+\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP
+
+\fI\fB
+
+.SH DESCRIPTION
+The
+.I libpng
+library supports encoding, decoding, and various manipulations of
+the Portable Network Graphics (PNG) format image files. It uses the
+.IR zlib(3)
+compression library.
+Following is a copy of the libpng.txt file that accompanies libpng.
+.SH LIBPNG.TXT
+libpng.txt - A description on how to use and modify libpng
+
+ libpng version 1.2.49 - March 29, 2012
+ Updated and distributed by Glenn Randers-Pehrson
+ <glennrp at users.sourceforge.net>
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ This document is released under the libpng license.
+ For conditions of distribution and use, see the disclaimer
+ and license in png.h
+
+ Based on:
+
+ libpng versions 0.97, January 1998, through 1.2.49 - March 29, 2012
+ Updated and distributed by Glenn Randers-Pehrson
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ libpng 1.0 beta 6 version 0.96 May 28, 1997
+ Updated and distributed by Andreas Dilger
+ Copyright (c) 1996, 1997 Andreas Dilger
+
+ libpng 1.0 beta 2 - version 0.88 January 26, 1996
+ For conditions of distribution and use, see copyright
+ notice in png.h. Copyright (c) 1995, 1996 Guy Eric
+ Schalnat, Group 42, Inc.
+
+ Updated/rewritten per request in the libpng FAQ
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
+
+.SH I. Introduction
+
+This file describes how to use and modify the PNG reference library
+(known as libpng) for your own use. There are five sections to this
+file: introduction, structures, reading, writing, and modification and
+configuration notes for various special platforms. In addition to this
+file, example.c is a good starting point for using the library, as
+it is heavily commented and should include everything most people
+will need. We assume that libpng is already installed; see the
+INSTALL file for instructions on how to install libpng.
+
+For examples of libpng usage, see the files "example.c", "pngtest.c",
+and the files in the "contrib" directory, all of which are included in
+the libpng distribution.
+
+Libpng was written as a companion to the PNG specification, as a way
+of reducing the amount of time and effort it takes to support the PNG
+file format in application programs.
+
+The PNG specification (second edition), November 2003, is available as
+a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at
+<http://www.w3.org/TR/2003/REC-PNG-20031110/
+The W3C and ISO documents have identical technical content.
+
+The PNG-1.2 specification is available at
+<http://www.libpng.org/pub/png/documents/>. It is technically equivalent
+to the PNG specification (second edition) but has some additional material.
+
+The PNG-1.0 specification is available
+as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a
+W3C Recommendation <http://www.w3.org/TR/REC.png.html>.
+
+Some additional chunks are described in the special-purpose public chunks
+documents at <http://www.libpng.org/pub/png/documents/>.
+
+Other information
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.libpng.org/pub/png/>.
+
+Most users will not have to modify the library significantly; advanced
+users may want to modify it more. All attempts were made to make it as
+complete as possible, while keeping the code easy to understand.
+Currently, this library only supports C. Support for other languages
+is being considered.
+
+Libpng has been designed to handle multiple sessions at one time,
+to be easily modifiable, to be portable to the vast majority of
+machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
+to use. The ultimate goal of libpng is to promote the acceptance of
+the PNG file format in whatever way possible. While there is still
+work to be done (see the TODO file), libpng should cover the
+majority of the needs of its users.
+
+Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
+The zlib compression utility is a general purpose utility that is
+useful for more than PNG files, and can be used without libpng.
+See the documentation delivered with zlib for more details.
+You can usually find the source files for the zlib utility wherever you
+find the libpng source files.
+
+Libpng is thread safe, provided the threads are using different
+instances of the structures. Each thread should have its own
+png_struct and png_info instances, and thus its own image.
+Libpng does not protect itself against two threads using the
+same instance of a structure.
+
+.SH II. Structures
+
+There are two main structures that are important to libpng, png_struct
+and png_info. The first, png_struct, is an internal structure that
+will not, for the most part, be used by a user except as the first
+variable passed to every libpng function call.
+
+The png_info structure is designed to provide information about the
+PNG file. At one time, the fields of png_info were intended to be
+directly accessible to the user. However, this tended to cause problems
+with applications using dynamically loaded libraries, and as a result
+a set of interface functions for png_info (the png_get_*() and png_set_*()
+functions) was developed. The fields of png_info are still available for
+older applications, but it is suggested that applications use the new
+interfaces if at all possible.
+
+Applications that do make direct access to the members of png_struct (except
+for png_ptr->jmpbuf) must be recompiled whenever the library is updated,
+and applications that make direct access to the members of png_info must
+be recompiled if they were compiled or loaded with libpng version 1.0.6,
+in which the members were in a different order. In version 1.0.7, the
+members of the png_info structure reverted to the old order, as they were
+in versions 0.97c through 1.0.5. Starting with version 2.0.0, both
+structures are going to be hidden, and the contents of the structures will
+only be accessible through the png_get/png_set functions.
+
+The png.h header file is an invaluable reference for programming with libpng.
+And while I'm on the topic, make sure you include the libpng header file:
+
+#include <png.h>
+
+.SH III. Reading
+
+We'll now walk you through the possible functions to call when reading
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one. See example.c and png.h for more detail. While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+.SS Setup
+
+You will want to do the I/O initialization(*) before you get into libpng,
+so if it doesn't work, you don't have much to undo. Of course, you
+will also want to insure that you are, in fact, dealing with a PNG
+file. Libpng provides a simple check to see if a file is a PNG file.
+To use it, pass in the first 1 to 8 bytes of the file to the function
+png_sig_cmp(), and it will return 0 (false) if the bytes match the
+corresponding bytes of the PNG signature, or nonzero (true) otherwise.
+Of course, the more bytes you pass in, the greater the accuracy of the
+prediction.
+
+If you are intending to keep the file pointer open for use in libpng,
+you must ensure you don't read more than 8 bytes from the beginning
+of the file, and you also have to make a call to png_set_sig_bytes_read()
+with the number of bytes you read from the beginning. Libpng will
+then only check the bytes (if any) that your program didn't read.
+
+(*): If you are not using the standard I/O functions, you will need
+to replace them with custom functions. See the discussion under
+Customizing libpng.
+
+
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+ fread(header, 1, number, fp);
+ is_png = !png_sig_cmp(header, 0, number);
+ if (!is_png)
+ {
+ return (NOT_PNG);
+ }
+
+
+Next, png_struct and png_info need to be allocated and initialized. In
+order to ensure that the size of these structures is correct even with a
+dynamically linked libpng, there are functions to initialize and
+allocate the structures. We also pass the library version, optional
+pointers to error handling functions, and a pointer to a data struct for
+use by the error functions, if necessary (the pointer and functions can
+be NULL if the default error handlers are to be used). See the section
+on Changes to Libpng below regarding the old initialization functions.
+The structure allocation functions quietly return NULL if they fail to
+create the structure, so your application should check for that.
+
+ png_structp png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr,
+ (png_infopp)NULL, (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+ png_structp png_ptr = png_create_read_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
+
+When libpng encounters an error, it expects to longjmp back
+to your routine. Therefore, you will need to call setjmp and pass
+your png_jmpbuf(png_ptr). If you read the file from different
+routines, you will need to update the jmpbuf field every time you enter
+a new routine that will call a png_*() function.
+
+See your documentation of setjmp/longjmp for your compiler for more
+information on setjmp/longjmp. See the discussion on libpng error
+handling in the Customizing Libpng section below for more information
+on the libpng error handling. If an error occurs, and libpng longjmp's
+back to your setjmp, you will want to call png_destroy_read_struct() to
+free any memory.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+ fclose(fp);
+ return (ERROR);
+ }
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the input code. The default for libpng is to
+use the C function fread(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. If you wish to handle reading data in another
+way, you need not call the png_init_io() function, but you must then
+implement the libpng I/O methods discussed in the Customizing Libpng
+section below.
+
+ png_init_io(png_ptr, fp);
+
+If you had previously opened the file and read any of the signature from
+the beginning in order to see if this was a PNG file, you need to let
+libpng know that there are some bytes missing from the start of the file.
+
+ png_set_sig_bytes(png_ptr, number);
+
+.SS Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+ read_chunk_callback(png_ptr ptr,
+ png_unknown_chunkp chunk);
+ {
+ /* The unknown chunk structure contains your
+ chunk data, along with similar data for any other
+ unknown chunks: */
+
+ png_byte name[5];
+ png_byte *data;
+ png_size_t size;
+
+ /* Note that libpng has already taken care of
+ the CRC handling */
+
+ /* put your code here. Search for your chunk in the
+ unknown chunk structure, process it, and return one
+ of the following: */
+
+ return (-n); /* chunk had an error */
+ return (0); /* did not recognize */
+ return (n); /* success */
+ }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+ read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+ png_get_user_chunk_ptr(png_ptr);
+
+If you call the png_set_read_user_chunk_fn() function, then all unknown
+chunks will be saved when read, in case your callback function will need
+one or more of them. This behavior can be changed with the
+png_set_keep_unknown_chunks() function, described below.
+
+At this point, you can set up a callback function that will be
+called after each row has been read, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void read_row_callback(png_ptr ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "read_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_status_fn(png_ptr, read_row_callback);
+
+.SS Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read. Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members while unknown chunks will be discarded. This
+behavior can be wasteful if your application will never use some known
+chunk types. To change this, you can call:
+
+ png_set_keep_unknown_chunks(png_ptr, keep,
+ chunk_list, num_chunks);
+ keep - 0: default unknown chunk handling
+ 1: ignore; do not keep
+ 2: keep only if safe-to-copy
+ 3: keep even if unsafe-to-copy
+ You can use these definitions:
+ PNG_HANDLE_CHUNK_AS_DEFAULT 0
+ PNG_HANDLE_CHUNK_NEVER 1
+ PNG_HANDLE_CHUNK_IF_SAFE 2
+ PNG_HANDLE_CHUNK_ALWAYS 3
+ chunk_list - list of chunks affected (a byte string,
+ five bytes per chunk, NULL or '\0' if
+ num_chunks is 0)
+ num_chunks - number of chunks affected; if 0, all
+ unknown chunks are affected. If nonzero,
+ only the chunks in the list are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures. If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive. If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence. The IHDR and IEND chunks should not be named in
+chunk_list; if they are, libpng will process them normally anyway.
+
+Here is an example of the usage of png_set_keep_unknown_chunks(),
+where the private "vpAg" chunk will later be processed by a user chunk
+callback function:
+
+ png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'};
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ png_byte unused_chunks[]=
+ {
+ 104, 73, 83, 84, (png_byte) '\0', /* hIST */
+ 105, 84, 88, 116, (png_byte) '\0', /* iTXt */
+ 112, 67, 65, 76, (png_byte) '\0', /* pCAL */
+ 115, 67, 65, 76, (png_byte) '\0', /* sCAL */
+ 115, 80, 76, 84, (png_byte) '\0', /* sPLT */
+ 116, 73, 77, 69, (png_byte) '\0', /* tIME */
+ };
+ #endif
+
+ ...
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ /* ignore all unknown chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+ /* except for vpAg: */
+ png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
+ /* also ignore unused known chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
+ (int)sizeof(unused_chunks)/5);
+ #endif
+
+.SS User limits
+
+The PNG specification allows the width and height of an image to be as
+large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.
+Since very few applications really need to process such large images,
+we have imposed an arbitrary 1-million limit on rows and columns.
+Larger images will be rejected immediately with a png_error() call. If
+you wish to override this limit, you can use
+
+ png_set_user_limits(png_ptr, width_max, height_max);
+
+to set your own limits, or use width_max = height_max = 0x7fffffffL
+to allow all valid dimensions (libpng may reject some very large images
+anyway because of potential buffer overflow conditions).
+
+You should put this statement after you create the PNG structure and
+before calling png_read_info(), png_read_png(), or png_process_data().
+If you need to retrieve the limits that are being applied, use
+
+ width_max = png_get_user_width_max(png_ptr);
+ height_max = png_get_user_height_max(png_ptr);
+
+The PNG specification sets no limit on the number of ancillary chunks
+allowed in a PNG datastream. You can impose a limit on the total number
+of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with
+
+ png_set_chunk_cache_max(png_ptr, user_chunk_cache_max);
+
+where 0x7fffffffL means unlimited. You can retrieve this limit with
+
+ chunk_cache_max = png_get_chunk_cache_max(png_ptr);
+
+This limit also applies to the number of buffers that can be allocated
+by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
+
+.SS The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to
+ 8 bits
+ PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel
+ PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit
+ samples to bytes
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_EXPAND Perform set_expand()
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+ PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples
+ to RGB (or GA to RGBA)
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.) If this is the case, simply do this:
+
+ png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of some
+set of transformation flags. This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+then png_read_image(), and finally png_read_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future input transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_read_png().
+
+After you have called png_read_png(), you can retrieve the image data
+with
+
+ row_pointers = png_get_rows(png_ptr, info_ptr);
+
+where row_pointers is an array of pointers to the pixel data for each row:
+
+ png_bytep row_pointers[height];
+
+If you know your image size and pixel size ahead of time, you can allocate
+row_pointers prior to calling png_read_png() with
+
+ if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+ png_error (png_ptr,
+ "Image is too tall to process in memory");
+ if (width > PNG_UINT_32_MAX/pixel_size)
+ png_error (png_ptr,
+ "Image is too wide to process in memory");
+ row_pointers = png_malloc(png_ptr,
+ height*png_sizeof(png_bytep));
+ for (int i=0; i<height, i++)
+ row_pointers[i]=NULL; /* security precaution */
+ for (int i=0; i<height, i++)
+ row_pointers[i]=png_malloc(png_ptr,
+ width*pixel_size);
+ png_set_rows(png_ptr, info_ptr, &row_pointers);
+
+Alternatively you could allocate your image in one big block and define
+row_pointers[i] to point into the proper places in your block.
+
+If you use png_set_rows(), the application is responsible for freeing
+row_pointers (and row_pointers[i], if they were separately allocated).
+
+If you don't allocate row_pointers ahead of time, png_read_png() will
+do it, and it'll be free'ed when you call png_destroy_*().
+
+.SS The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data. You do this with a
+call to png_read_info().
+
+ png_read_info(png_ptr, info_ptr);
+
+This will process all chunks up to but not including the image data.
+
+.SS Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read. Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_method);
+
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels. (valid values are
+ 1, 2, 4, 8, 16 and depend also on
+ the color_type. See also
+ significant bits (sBIT) below).
+ color_type - describes which color/alpha channels
+ are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ filter_method - (must be PNG_FILTER_TYPE_BASE
+ for PNG 1.0, and can also be
+ PNG_INTRAPIXEL_DIFFERENCING if
+ the PNG datastream is embedded in
+ a MNG-1.0 datastream)
+ compression_type - (must be PNG_COMPRESSION_TYPE_BASE
+ for PNG 1.0)
+ interlace_type - (PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7)
+
+ Any or all of interlace_type, compression_type, or
+ filter_method can be NULL if you are
+ not interested in their values.
+
+ Note that png_get_IHDR() returns 32-bit data into
+ the application's width and height variables.
+ This is an unsafe situation if these are 16-bit
+ variables. In such situations, the
+ png_get_image_width() and png_get_image_height()
+ functions described below are safer.
+
+ width = png_get_image_width(png_ptr,
+ info_ptr);
+ height = png_get_image_height(png_ptr,
+ info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr,
+ info_ptr);
+ color_type = png_get_color_type(png_ptr,
+ info_ptr);
+ filter_method = png_get_filter_type(png_ptr,
+ info_ptr);
+ compression_type = png_get_compression_type(png_ptr,
+ info_ptr);
+ interlace_type = png_get_interlace_type(png_ptr,
+ info_ptr);
+
+ channels = png_get_channels(png_ptr, info_ptr);
+ channels - number of channels of info for the
+ color type (valid values are 1 (GRAY,
+ PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
+ 4 (RGB_ALPHA or RGB + filler byte))
+ rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ rowbytes - number of bytes needed to hold a row
+
+ signature = png_get_signature(png_ptr, info_ptr);
+ signature - holds the signature read from the
+ file (if any). The data is kept in
+ the same offset it would be if the
+ whole signature were read (i.e. if an
+ application had already read in 4
+ bytes of signature before starting
+ libpng, the remaining 4 bytes would
+ be in signature[4] through signature[7]
+ (see png_set_sig_bytes())).
+
+These are also important, but their validity depends on whether the chunk
+has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
+png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
+data has been read, or zero if it is missing. The parameters to the
+png_get_<chunk> are set directly if they are simple data types, or a
+pointer into the info_ptr is returned for any complex types.
+
+ png_get_PLTE(png_ptr, info_ptr, &palette,
+ &num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_get_gAMA(png_ptr, info_ptr, &gamma);
+ gamma - the gamma the file is written
+ at (PNG_INFO_gAMA)
+
+ png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
+ srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ The presence of the sRGB chunk
+ means that the pixel data is in the
+ sRGB color space. This chunk also
+ implies specific values of gAMA and
+ cHRM.
+
+ png_get_iCCP(png_ptr, info_ptr, &name,
+ &compression_type, &profile, &proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray,
+ red, green, and blue channels,
+ whichever are appropriate for the
+ given color type (png_color_16)
+
+ png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
+ &trans_values);
+ trans - array of transparent
+ entries for palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values of
+ the single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_get_hIST(png_ptr, info_ptr, &hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_get_tIME(png_ptr, info_ptr, &mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_get_bKGD(png_ptr, info_ptr, &background);
+ background - background color (PNG_VALID_bKGD)
+ valid 16-bit red, green and blue
+ values, regardless of color_type
+
+ num_comments = png_get_text(png_ptr, info_ptr,
+ &text_ptr, &num_text);
+ num_comments - number of comments
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (empty
+ string for unknown).
+ text_ptr[i].lang_key - keyword in UTF-8
+ (empty string for unknown).
+ Note that the itxt_length, lang, and lang_key
+ members of the text_ptr structure only exist
+ when the library is built with iTXt chunk support.
+
+ num_text - number of comments (same as
+ num_comments; you can put NULL here
+ to avoid the duplication)
+ Note while png_set_text() will accept text, language,
+ and translated keywords that can be NULL pointers, the
+ structure returned by png_get_text will always contain
+ regular zero-terminated C strings. They might be
+ empty strings but they will never be NULL pointers.
+
+ num_spalettes = png_get_sPLT(png_ptr, info_ptr,
+ &palette_ptr);
+ palette_ptr - array of palette structures holding
+ contents of one or more sPLT chunks
+ read.
+ num_spalettes - number of sPLT chunks read.
+
+ png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
+ &unit_type);
+ offset_x - positive offset from the left edge
+ of the screen
+ offset_y - positive offset from the top edge
+ of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
+ &unit_type);
+ res_x - pixels/unit physical resolution in
+ x direction
+ res_y - pixels/unit physical resolution in
+ x direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_get_sCAL(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ num_unknown_chunks = png_get_unknown_chunks(png_ptr,
+ info_ptr, &unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position of chunk in file
+
+ The value of "i" corresponds to the order in which the
+ chunks were read from the PNG file or inserted with the
+ png_set_unknown_chunks() function.
+
+The data from the pHYs chunk can be retrieved in several convenient
+forms:
+
+ res_x = png_get_x_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x = png_get_x_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_inch(png_ptr,
+ info_ptr)
+ aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
+ info_ptr)
+
+ (Each of these returns 0 [signifying "unknown"] if
+ the data is not present or if res_x is 0;
+ res_x_and_y is 0 if res_x != res_y)
+
+The data from the oFFs chunk can be retrieved in several convenient
+forms:
+
+ x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
+ x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_inches(png_ptr, info_ptr);
+
+ (Each of these returns 0 [signifying "unknown" if both
+ x and y are 0] if the data is not present or if the
+ chunk is present but the unit is the pixel)
+
+For more information, see the png_info definition in png.h and the
+PNG specification for chunk contents. Be careful with trusting
+rowbytes, as some of the transformations could increase the space
+needed to hold a row (expand, filler, gray_to_rgb, etc.).
+See png_read_update_info(), below.
+
+A quick word about text_ptr and num_text. PNG stores comments in
+keyword/text pairs, one pair per chunk, with no limit on the number
+of text chunks, and a 2^31 byte limit on their size. While there are
+suggested keywords, there is no requirement to restrict the use to these
+strings. It is strongly suggested that keywords and text be sensible
+to humans (that's the point), so don't use abbreviations. Non-printing
+symbols are not allowed. See the PNG specification for more details.
+There is also no requirement to have text after the keyword.
+
+Keywords should be limited to 79 Latin-1 characters without leading or
+trailing spaces, but non-consecutive spaces are allowed within the
+keyword. It is possible to have the same keyword any number of times.
+The text_ptr is an array of png_text structures, each holding a
+pointer to a language string, a pointer to a keyword and a pointer to
+a text string. The text string, language code, and translated
+keyword may be empty or NULL pointers. The keyword/text
+pairs are put into the array in the order that they are received.
+However, some or all of the text chunks may be after the image, so, to
+make sure you have read all the text chunks, don't mess with these
+until after you read the stuff after the image. This will be
+mentioned again below in the discussion that goes with png_read_end().
+
+.SS Input transformations
+
+After you've read the header information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+The colors used for the background and transparency values should be
+supplied in the same format/depth as the current image data. They
+are stored in the same format/depth as the image data in a bKGD or tRNS
+chunk, so this is what libpng expects for this data. The colors are
+transformed to keep in sync with the image data when an application
+calls the png_read_update_info() routine (see below).
+
+Data will be decoded into the supplied row buffers packed into bytes
+unless the library has been told to transform it into another format.
+For example, 4 bit/pixel paletted or grayscale data will be returned
+2 pixels/byte with the leftmost pixel in the high-order bits of the
+byte, unless png_set_packing() is called. 8-bit RGB data will be stored
+in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha()
+is called to insert filler bytes, either before or after each RGB triplet.
+16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant
+byte of the color value first, unless png_set_strip_16() is called to
+transform it to regular RGB RGB triplets, or png_set_filler() or
+png_set_add alpha() is called to insert filler bytes, either before or
+after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can
+be modified with
+png_set_filler(), png_set_add_alpha(), or png_set_strip_16().
+
+The following code transforms grayscale images of less than 8 to 8 bits,
+changes paletted images to RGB, and adds a full alpha channel if there is
+transparency information in a tRNS chunk. This is most useful on
+grayscale images with bit depths of 2 or 4 or if there is a multiple-image
+viewing application that wishes to treat all images in the same way.
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ if (color_type == PNG_COLOR_TYPE_GRAY &&
+ bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
+
+These three functions are actually aliases for png_set_expand(), added
+in libpng version 1.0.4, with the function names expanded to improve code
+readability. In some future version they may actually do different
+things.
+
+As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was
+added. It expands the sample depth without changing tRNS to alpha.
+
+As of libpng version 1.2.49, not all possible expansions are supported.
+
+In the following table, the 01 means grayscale with depth<8, 31 means
+indexed with depth<8, other numerals represent the color type, "T" means
+the tRNS chunk is present, A means an alpha channel is present, and O
+means tRNS or alpha is present but all pixels in the image are opaque.
+
+ FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O
+ TO
+ 01 -
+ 31 -
+ 0 1 -
+ 0T -
+ 0O -
+ 2 GX -
+ 2T -
+ 2O -
+ 3 1 -
+ 3T -
+ 3O -
+ 4A T -
+ 4O -
+ 6A GX TX TX -
+ 6O GX TX -
+
+Within the matrix,
+ "-" means the transformation is not supported.
+ "X" means the transformation is obtained by png_set_expand().
+ "1" means the transformation is obtained by
+ png_set_expand_gray_1_2_4_to_8
+ "G" means the transformation is obtained by
+ png_set_gray_to_rgb().
+ "P" means the transformation is obtained by
+ png_set_expand_palette_to_rgb().
+ "T" means the transformation is obtained by
+ png_set_tRNS_to_alpha().
+
+PNG can have files with 16 bits per channel. If you only can handle
+8 bits per channel, this will strip the pixels down to 8 bit.
+
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+If, for some reason, you don't need the alpha channel on an image,
+and you want to remove it rather than combining it with the background
+(but the image author certainly had in mind that you *would* combine
+it with the background, so that's what you should probably do):
+
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_ptr);
+
+In PNG files, the alpha channel in an image
+is the level of opacity. If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
+
+ png_set_invert_alpha(png_ptr);
+
+The PNG format only supports pixels with postmultiplied alpha.
+If you want to replace the pixels, after reading them, with pixels
+that have premultiplied color samples, you can do this with
+
+ png_set_premultiply_alpha(png_ptr);
+
+If you do this, any input with a tRNS chunk will be expanded to
+have an alpha channel.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit
+files. This code expands to 1 pixel per byte without changing the
+values of the pixels:
+
+ if (bit_depth < 8)
+ png_set_packing(png_ptr);
+
+PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels
+stored in a PNG image have been "scaled" or "shifted" up to the next
+higher possible bit depth (e.g. from 5 bits/sample in the range [0,31]
+to 8 bits/sample in the range [0, 255]). However, it is also possible
+to convert the PNG pixel data back to the original bit depth of the
+image. This call reduces the pixels back down to the original bit depth:
+
+ png_color_8p sig_bit;
+
+ if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+ png_set_shift(png_ptr, sig_bit);
+
+PNG files store 3-color pixels in red, green, blue order. This code
+changes the storage of the pixels to blue, green, red:
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_bgr(png_ptr);
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them
+into 4 or 8 bytes for windowing systems that need them in this format:
+
+ if (color_type == PNG_COLOR_TYPE_RGB)
+ png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
+
+where "filler" is the 8 or 16-bit number to fill with, and the location is
+either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
+you want the filler before the RGB or after. This transformation
+does not affect images that already have full alpha channels. To add an
+opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which
+will generate RGBA pixels.
+
+Note that png_set_filler() does not change the color type. If you want
+to do that, you can add a true alpha channel with
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
+
+where "filler" contains the alpha value to assign to each pixel.
+This function was added in libpng-1.2.7.
+
+If you are reading an image with an alpha channel, and you need the
+data as ARGB instead of the normal PNG format RGBA:
+
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_swap_alpha(png_ptr);
+
+For some uses, you may want a grayscale image to be represented as
+RGB. This code will do that conversion:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_rgb_to_gray_fixed(png_ptr, error_action,
+ int red_weight, int green_weight);
+
+ error_action = 1: silently do the conversion
+ error_action = 2: issue a warning if the original
+ image has any pixel where
+ red != green or red != blue
+ error_action = 3: issue an error and abort the
+ conversion if the original
+ image has any pixel where
+ red != green or red != blue
+
+ red_weight: weight of red component times 100000
+ green_weight: weight of green component times 100000
+ If either weight is negative, default
+ weights (21268, 71514) are used.
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels. bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With red_weight+green_weight<=100000,
+the normalized graylevel is computed:
+
+ int rw = red_weight * 65536;
+ int gw = green_weight * 65536;
+ int bw = 65536 - (rw + gw);
+ gray = (rw*red + gw*green + bw*blue)/65536;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net>
+
+ Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+ Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
+
+which can be expressed with integers as
+
+ Y = (6969 * R + 23434 * G + 2365 * B)/32768
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
+If you have a grayscale and you are using png_set_expand_depth(),
+png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0). Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
+
+ png_color_16 my_background;
+ png_color_16p image_background;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+ png_set_background(png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ png_set_background(png_ptr, &my_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+The png_set_background() function tells libpng to composite images
+with alpha or simple transparency against the supplied background
+color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
+you may use this color, or supply another color more suitable for
+the current display (e.g., the background color from a web page). You
+need to tell libpng whether the color is in the gamma space of the
+display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
+(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
+that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
+know why anyone would use this, but it's here).
+
+To properly display PNG images on any kind of system, the application needs
+to know what the display gamma is. Ideally, the user will know this, and
+the application will allow them to set it. One method of allowing the user
+to set the display gamma separately for each system is to check for a
+SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
+correctly set.
+
+Note that display_gamma is the overall gamma correction required to produce
+pleasing results, which depends on the lighting conditions in the surrounding
+environment. In a dim or brightly lit room, no compensation other than
+the physical gamma exponent of the monitor is needed, while in a dark room
+a slightly smaller exponent is better.
+
+ double gamma, screen_gamma;
+
+ if (/* We have a user-defined screen
+ gamma value */)
+ {
+ screen_gamma = user_defined_screen_gamma;
+ }
+ /* One way that applications can share the same
+ screen gamma value */
+ else if ((gamma_str = getenv("SCREEN_GAMMA"))
+ != NULL)
+ {
+ screen_gamma = (double)atof(gamma_str);
+ }
+ /* If we don't have another value */
+ else
+ {
+ screen_gamma = 2.2; /* A good guess for a
+ PC monitor in a bright office or a dim room */
+ screen_gamma = 2.0; /* A good guess for a
+ PC monitor in a dark room */
+ screen_gamma = 1.7 or 1.0; /* A good
+ guess for Mac systems */
+ }
+
+The png_set_gamma() function handles gamma transformations of the data.
+Pass both the file gamma and the current screen_gamma. If the file does
+not have a gamma value, you can pass one anyway if you have an idea what
+it is (usually 0.45455 is a good guess for GIF images on PCs). Note
+that file gammas are inverted from screen gammas. See the discussions
+on gamma in the PNG specification for an excellent description of what
+gamma is, and why all applications should support it. It is strongly
+recommended that PNG viewers support gamma correction.
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, screen_gamma, gamma);
+ else
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+If you need to reduce an RGB file to a paletted file, or if a paletted
+file has more entries then will fit on your screen, png_set_dither()
+will do that. Note that this is a simple match dither that merely
+finds the closest color available. This should work fairly well with
+optimized palettes, and fairly badly with linear color cubes. If you
+pass a palette that is larger then maximum_colors, the file will
+reduce the number of colors in the palette so it will fit into
+maximum_colors. If there is a histogram, it will use it to make
+more intelligent choices when reducing the palette. If there is no
+histogram, it may not do as good a job.
+
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_PLTE))
+ {
+ png_uint_16p histogram = NULL;
+
+ png_get_hIST(png_ptr, info_ptr,
+ &histogram);
+ png_set_dither(png_ptr, palette, num_palette,
+ max_screen_colors, histogram, 1);
+ }
+ else
+ {
+ png_color std_color_cube[MAX_SCREEN_COLORS] =
+ { ... colors ... };
+
+ png_set_dither(png_ptr, std_color_cube,
+ MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
+ NULL,0);
+ }
+ }
+
+PNG files describe monochrome as black being zero and white being one.
+The following code will reverse this (make black be one and white be
+zero):
+
+ if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_invert_mono(png_ptr);
+
+This function can also be used to invert grayscale and gray-alpha images:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_invert_mono(png_ptr);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code changes the storage to the
+other way (little-endian, i.e. least significant bits first, the
+way PCs store them):
+
+ if (bit_depth == 16)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_read_user_transform_fn(png_ptr,
+ read_transform_fn);
+
+You must supply the function
+
+ void read_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+after all of the other transformations have been processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function, and you can inform libpng that your transform
+function will change the number of channels or bit depth with the
+function
+
+ png_set_user_transform_info(png_ptr, user_ptr,
+ user_depth, user_channels);
+
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
+
+You can retrieve the pointer via the function
+png_get_user_transform_ptr(). For example:
+
+ voidp read_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+The last thing to handle is interlacing; this is covered in detail below,
+but you must call the function here if you want libpng to handle expansion
+of the interlaced image.
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+
+After setting the transformations, libpng can update your png_info
+structure to reflect any transformations you've requested with this
+call. This is most useful to update the info structure's rowbytes
+field so you can use it to allocate your image memory. This function
+will also update your palette with the correct screen_gamma and
+background if these have been given with the calls above.
+
+ png_read_update_info(png_ptr, info_ptr);
+
+After you call png_read_update_info(), you can allocate any
+memory you need to hold the image. The row data is simply
+raw byte data for all forms of images. As the actual allocation
+varies among applications, no example will be given. If you
+are allocating one large chunk, you will need to build an
+array of pointers to each row, as it will be needed for some
+of the functions below.
+
+.SS Reading image data
+
+After you've allocated memory, you can read the image data.
+The simplest way to do this is in one function call. If you are
+allocating enough memory to hold the whole image, you can just
+call png_read_image() and libpng will read in all the image data
+and put it in the memory area supplied. You will need to pass in
+an array of pointers to each row.
+
+This function automatically handles interlacing, so you don't need
+to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_read_rows().
+
+ png_read_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_bytep row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to read in the whole image at once, you can
+use png_read_rows() instead. If there is no interlacing (check
+interlace_type == PNG_INTERLACE_NONE), this is simple:
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+where row_pointers is the same as in the png_read_image() call.
+
+If you are doing this just one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+ png_read_row(png_ptr, row_pointer, NULL);
+
+If the file is interlaced (interlace_type != 0 in the IHDR chunk), things
+get somewhat harder. The only current (PNG Specification version 1.2)
+interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7)
+is a somewhat complicated 2D interlace scheme, known as Adam7, that
+breaks down an image into seven smaller images of varying size, based
+on an 8x8 grid.
+
+libpng can fill out those images or it can give them to you "as is".
+If you want them filled out, there are two ways to do that. The one
+mentioned in the PNG specification is to expand each pixel to cover
+those pixels that have not been read yet (the "rectangle" method).
+This results in a blocky image for the first pass, which gradually
+smooths out as more pixels are read. The other method is the "sparkle"
+method, where pixels are drawn only in their final locations, with the
+rest of the image remaining whatever colors they were initialized to
+before the start of the read. The first method usually looks better,
+but tends to be slower, as there are more pixels to put in the rows.
+
+If you don't want libpng to handle the interlacing details, just call
+png_read_rows() seven times to read in all seven images. Each of the
+images is a valid image by itself, or they can all be combined on an
+8x8 grid to form a single image (although if you intend to combine them
+you would be far better off using the libpng interlace handling).
+
+The first pass will return an image 1/8 as wide as the entire image
+(every 8th column starting in column 0) and 1/8 as high as the original
+(every 8th row starting in row 0), the second will be 1/8 as wide
+(starting in column 4) and 1/8 as high (also starting in row 0). The
+third pass will be 1/4 as wide (every 4th pixel starting in column 0) and
+1/8 as high (every 8th row starting in row 4), and the fourth pass will
+be 1/4 as wide and 1/4 as high (every 4th column starting in column 2,
+and every 4th row starting in row 0). The fifth pass will return an
+image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2),
+while the sixth pass will be 1/2 as wide and 1/2 as high as the original
+(starting in column 1 and row 0). The seventh and final pass will be as
+wide as the original, and 1/2 as high, containing all of the odd
+numbered scanlines. Phew!
+
+If you want libpng to expand the images, call this before calling
+png_start_read_image() or png_read_update_info():
+
+ if (interlace_type == PNG_INTERLACE_ADAM7)
+ number_of_passes
+ = png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this
+is seven, but may change if another interlace type is added.
+This function can be called even if the file is not interlaced,
+where it will return one pass.
+
+If you are not going to display the image after each pass, but are
+going to wait until the entire image is read in, use the sparkle
+effect. This effect is faster and the end result of either method
+is exactly the same. If you are planning on displaying the image
+after each pass, the "rectangle" effect is generally considered the
+better looking one.
+
+If you only want the "sparkle" effect, just call png_read_rows() as
+normal, with the third parameter NULL. Make sure you make pass over
+the image number_of_passes times, and you don't change the data in the
+rows between calls. You can change the locations of the data, just
+not the data. Each pass only writes the pixels appropriate for that
+pass, and assumes the data from previous passes is still valid.
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+If you only want the first effect (the rectangles), do the same as
+before except pass the row buffer in the third parameter, and leave
+the second parameter NULL.
+
+ png_read_rows(png_ptr, NULL, row_pointers,
+ number_of_rows);
+
+.SS Finishing a sequential read
+
+After you are finished reading the image through the
+low-level interface, you can finish reading the file. If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate. If you are not interested, you can pass NULL.
+
+ png_read_end(png_ptr, end_info);
+
+When you are done, you can free all memory allocated by libpng like this:
+
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those cases do nothing.
+The "seq" parameter is ignored if only one item of the selected data
+type, such as PLTE, is allowed. If "seq" is not -1, and multiple items
+are allowed for the data type identified in the mask, such as text or
+sPLT, only the n'th item in the structure is freed, where n is "seq".
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+This function only affects data that has already been allocated.
+You can call this function after reading the PNG data but before calling
+any png_set_*() functions, to control whether the user or the png_set_*()
+function is responsible for freeing any existing data that might be present,
+and again after the png_set_*() functions to control whether the user
+or png_destroy_*() is supposed to free the data. When the user assumes
+responsibility for libpng-allocated data, the application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated your row_pointers in a single block, as suggested above in
+the description of the high level read interface, you must not transfer
+responsibility for freeing it to the png_set_rows or png_read_destroy function,
+because they would also try to free the individual row_pointers[i].
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+
+The png_free_data() function will turn off the "valid" flag for anything
+it frees. If you need to turn the flag off for a chunk that was freed by
+your application instead of by libpng, you can use
+
+ png_set_invalid(png_ptr, info_ptr, mask);
+ mask - identifies the chunks to be made invalid,
+ containing the bitwise OR of one or
+ more of
+ PNG_INFO_gAMA, PNG_INFO_sBIT,
+ PNG_INFO_cHRM, PNG_INFO_PLTE,
+ PNG_INFO_tRNS, PNG_INFO_bKGD,
+ PNG_INFO_hIST, PNG_INFO_pHYs,
+ PNG_INFO_oFFs, PNG_INFO_tIME,
+ PNG_INFO_pCAL, PNG_INFO_sRGB,
+ PNG_INFO_iCCP, PNG_INFO_sPLT,
+ PNG_INFO_sCAL, PNG_INFO_IDAT
+
+For a more compact example of reading a PNG image, see the file example.c.
+
+.SS Reading PNG files progressively
+
+The progressive reader is slightly different then the non-progressive
+reader. Instead of calling png_read_info(), png_read_rows(), and
+png_read_end(), you make one call to png_process_data(), which calls
+callbacks when it has the info, a row, or the end of the image. You
+set up these callbacks with png_set_progressive_read_fn(). You don't
+have to worry about the input/output functions of libpng, as you are
+giving the library the data directly in png_process_data(). I will
+assume that you have read the section on reading PNG files above,
+so I will only highlight the differences (although I will show
+all of the code).
+
+png_structp png_ptr;
+png_infop info_ptr;
+
+ /* An example code fragment of how you would
+ initialize the progressive reader in your
+ application. */
+ int
+ initialize_png_reader()
+ {
+ png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new. You can provide functions
+ to be called when the header info is valid,
+ when each row is completed, and when the image
+ is finished. If you aren't using all functions,
+ you can specify NULL parameters. Even when all
+ three functions are NULL, you need to call
+ png_set_progressive_read_fn(). You can use
+ any struct as the user_ptr (cast to a void pointer
+ for the function call), and retrieve the pointer
+ from inside the callbacks using the function
+
+ png_get_progressive_ptr(png_ptr);
+
+ which will return a void pointer, which you have
+ to cast appropriately.
+ */
+ png_set_progressive_read_fn(png_ptr, (void *)user_ptr,
+ info_callback, row_callback, end_callback);
+
+ return 0;
+ }
+
+ /* A code fragment that you call as you receive blocks
+ of data */
+ int
+ process_data(png_bytep buffer, png_uint_32 length)
+ {
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new also. Simply give it a chunk
+ of data from the file stream (in order, of
+ course). On machines with segmented memory
+ models machines, don't give it any more than
+ 64K. The library seems to run fine with sizes
+ of 4K. Although you can give it much less if
+ necessary (I assume you can give it chunks of
+ 1 byte, I haven't tried less then 256 bytes
+ yet). When this function returns, you may
+ want to display any rows that were generated
+ in the row callback if you don't already do
+ so there.
+ */
+ png_process_data(png_ptr, info_ptr, buffer, length);
+ return 0;
+ }
+
+ /* This function is called (as set by
+ png_set_progressive_read_fn() above) when enough data
+ has been supplied so all of the header has been
+ read.
+ */
+ void
+ info_callback(png_structp png_ptr, png_infop info)
+ {
+ /* Do any setup here, including setting any of
+ the transformations mentioned in the Reading
+ PNG files section. For now, you _must_ call
+ either png_start_read_image() or
+ png_read_update_info() after all the
+ transformations are set (even if you don't set
+ any). You may start getting rows before
+ png_process_data() returns, so this is your
+ last chance to prepare for that.
+ */
+ }
+
+ /* This function is called when each row of image
+ data is complete */
+ void
+ row_callback(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+ {
+ /* If the image is interlaced, and you turned
+ on the interlace handler, this function will
+ be called for every row in every pass. Some
+ of these rows will not be changed from the
+ previous pass. When the row is not changed,
+ the new_row variable will be NULL. The rows
+ and passes are called in order, so you don't
+ really need the row_num and pass, but I'm
+ supplying them because it may make your life
+ easier.
+
+ For the non-NULL rows of interlaced images,
+ you must call png_progressive_combine_row()
+ passing in the row and the old row. You can
+ call this function for NULL rows (it will just
+ return) and for non-interlaced images (it just
+ does the memcpy for you) if it will make the
+ code easier. Thus, you can just do this for
+ all cases:
+ */
+
+ png_progressive_combine_row(png_ptr, old_row,
+ new_row);
+
+ /* where old_row is what was displayed for
+ previously for the row. Note that the first
+ pass (pass == 0, really) will completely cover
+ the old row, so the rows do not have to be
+ initialized. After the first pass (and only
+ for interlaced images), you will have to pass
+ the current row, and the function will combine
+ the old row and the new row.
+ */
+ }
+
+ void
+ end_callback(png_structp png_ptr, png_infop info)
+ {
+ /* This function is called after the whole image
+ has been read, including any chunks after the
+ image (up to and including the IEND). You
+ will usually have the same info chunk as you
+ had in the header, although some data may have
+ been added to the comments and time fields.
+
+ Most people won't do much here, perhaps setting
+ a flag that marks the image as finished.
+ */
+ }
+
+
+
+.SH IV. Writing
+
+Much of this is very similar to reading. However, everything of
+importance is repeated here, so you won't have to constantly look
+back up in the reading section to understand writing.
+
+.SS Setup
+
+You will want to do the I/O initialization before you get into libpng,
+so if it doesn't work, you don't have anything to undo. If you are not
+using the standard I/O functions, you will need to replace them with
+custom writing functions. See the discussion under Customizing libpng.
+
+ FILE *fp = fopen(file_name, "wb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+
+Next, png_struct and png_info need to be allocated and initialized.
+As these can be both relatively large, you may not want to store these
+on the stack, unless you have stack space to spare. Of course, you
+will want to check if they return NULL. If you are also reading,
+you won't want to name your read structure and your write structure
+both "png_ptr"; you can call them anything you like, such as
+"read_ptr" and "write_ptr". Look at pngtest.c, for example.
+
+ png_structp png_ptr = png_create_write_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_write_struct(&png_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_write_struct():
+
+ png_structp png_ptr = png_create_write_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+After you have these structures, you will need to set up the
+error handling. When libpng encounters an error, it expects to
+longjmp() back to your routine. Therefore, you will need to call
+setjmp() and pass the png_jmpbuf(png_ptr). If you
+write the file from different routines, you will need to update
+the png_jmpbuf(png_ptr) every time you enter a new routine that will
+call a png_*() function. See your documentation of setjmp/longjmp
+for your compiler for more information on setjmp/longjmp. See
+the discussion on libpng error handling in the Customizing Libpng
+section below for more information on the libpng error handling.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(fp);
+ return (ERROR);
+ }
+ ...
+ return;
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the output code. The default for libpng is to
+use the C function fwrite(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. Again, if you wish to handle writing data in
+another way, see the discussion on libpng I/O handling in the Customizing
+Libpng section below.
+
+ png_init_io(png_ptr, fp);
+
+If you are embedding your PNG into a datastream such as MNG, and don't
+want libpng to write the 8-byte signature, or if you have already
+written the signature in your application, use
+
+ png_set_sig_bytes(png_ptr, 8);
+
+to inform libpng that it should not write a signature.
+
+.SS Write callbacks
+
+At this point, you can set up a callback function that will be
+called after each row has been written, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void write_row_callback(png_ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "write_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_write_status_fn(png_ptr, write_row_callback);
+
+You now have the option of modifying how the compression library will
+run. The following functions are mainly for testing, but may be useful
+in some cases, like if you need to write PNG files extremely fast and
+are willing to give up some compression, or if you want to get the
+maximum possible compression at the expense of slower writing. If you
+have no special needs in this area, let the library do what it wants by
+not calling this function at all, as it has been tuned to deliver a good
+speed/compression ratio. The second parameter to png_set_filter() is
+the filter method, for which the only valid values are 0 (as of the
+July 1999 PNG specification, version 1.2) or 64 (if you are writing
+a PNG datastream that is to be embedded in a MNG datastream). The third
+parameter is a flag that indicates which filter type(s) are to be tested
+for each scanline. See the PNG specification for details on the specific
+filter types.
+
+
+ /* turn on or off filtering, and/or choose
+ specific filters. You can use either a single
+ PNG_FILTER_VALUE_NAME or the bitwise OR of one
+ or more PNG_FILTER_NAME masks. */
+ png_set_filter(png_ptr, 0,
+ PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE |
+ PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB |
+ PNG_FILTER_UP | PNG_FILTER_VALUE_UP |
+ PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG |
+ PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+ PNG_ALL_FILTERS);
+
+If an application
+wants to start and stop using particular filters during compression,
+it should start out with all of the filters (to ensure that the previous
+row of pixels will be stored in case it's needed later), and then add
+and remove them after the start of compression.
+
+If you are writing a PNG datastream that is to be embedded in a MNG
+datastream, the second parameter can be either 0 or 64.
+
+The png_set_compression_*() functions interface to the zlib compression
+library, and should mostly be ignored unless you really know what you are
+doing. The only generally useful call is png_set_compression_level()
+which changes how much time zlib spends on trying to compress the image
+data. See the Compression Library (zlib.h and algorithm.txt, distributed
+with zlib) for details on the compression levels.
+
+ /* set the zlib compression level */
+ png_set_compression_level(png_ptr,
+ Z_BEST_COMPRESSION);
+
+ /* set other zlib parameters */
+ png_set_compression_mem_level(png_ptr, 8);
+ png_set_compression_strategy(png_ptr,
+ Z_DEFAULT_STRATEGY);
+ png_set_compression_window_bits(png_ptr, 15);
+ png_set_compression_method(png_ptr, 8);
+ png_set_compression_buffer_size(png_ptr, 8192)
+
+extern PNG_EXPORT(void,png_set_zbuf_size)
+
+.SS Setting the contents of info for output
+
+You now need to fill in the png_info structure with all the data you
+wish to write before the actual image. Note that the only thing you
+are allowed to write after the image is the text chunks and the time
+chunk (as of PNG Specification 1.2, anyway). See png_write_end() and
+the latest PNG specification for more information on that. If you
+wish to write them before the image, fill them in now, and flag that
+data as being valid. If you want to wait until after the data, don't
+fill them until png_write_end(). For all the fields in png_info and
+their data types, see png.h. For explanations of what the fields
+contain, see the PNG specification.
+
+Some of the more important parts of the png_info are:
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ bit_depth, color_type, interlace_type,
+ compression_type, filter_method)
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels.
+ (valid values are 1, 2, 4, 8, 16
+ and depend also on the
+ color_type. See also significant
+ bits (sBIT) below).
+ color_type - describes which color/alpha
+ channels are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ interlace_type - PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7
+ compression_type - (must be
+ PNG_COMPRESSION_TYPE_DEFAULT)
+ filter_method - (must be PNG_FILTER_TYPE_DEFAULT
+ or, if you are writing a PNG to
+ be embedded in a MNG datastream,
+ can also be
+ PNG_INTRAPIXEL_DIFFERENCING)
+
+If you call png_set_IHDR(), the call must appear before any of the
+other png_set_*() functions, because they might require access to some of
+the IHDR settings. The remaining png_set_*() functions can be called
+in any order.
+
+If you wish, you can reset the compression_type, interlace_type, or
+filter_method later by calling png_set_IHDR() again; if you do this, the
+width, height, bit_depth, and color_type must be the same in each call.
+
+ png_set_PLTE(png_ptr, info_ptr, palette,
+ num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_set_gAMA(png_ptr, info_ptr, gamma);
+ gamma - the gamma the image was created
+ at (PNG_INFO_gAMA)
+
+ png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of
+ the sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This chunk also implies specific
+ values of gAMA and cHRM. Rendering
+ intent is the CSS-1 property that
+ has been defined by the International
+ Color Consortium
+ (http://www.color.org).
+ It can be one of
+ PNG_sRGB_INTENT_SATURATION,
+ PNG_sRGB_INTENT_PERCEPTUAL,
+ PNG_sRGB_INTENT_ABSOLUTE, or
+ PNG_sRGB_INTENT_RELATIVE.
+
+
+ png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
+ srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of the
+ sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This function also causes gAMA and
+ cHRM chunks with the specific values
+ that are consistent with sRGB to be
+ written.
+
+ png_set_iCCP(png_ptr, info_ptr, name, compression_type,
+ profile, proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_set_sBIT(png_ptr, info_ptr, sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray, red,
+ green, and blue channels, whichever are
+ appropriate for the given color type
+ (png_color_16)
+
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans,
+ trans_values);
+ trans - array of transparent
+ entries for palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values
+ (in order red, green, blue) of the
+ single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_set_hIST(png_ptr, info_ptr, hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_set_tIME(png_ptr, info_ptr, mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_set_bKGD(png_ptr, info_ptr, background);
+ background - background color (PNG_VALID_bKGD)
+
+ png_set_text(png_ptr, info_ptr, text_ptr, num_text);
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be NULL or empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (NULL or
+ empty for unknown).
+ text_ptr[i].translated_keyword - keyword in UTF-8 (NULL
+ or empty for unknown).
+ Note that the itxt_length, lang, and lang_key
+ members of the text_ptr structure only exist
+ when the library is built with iTXt chunk support.
+
+ num_text - number of comments
+
+ png_set_sPLT(png_ptr, info_ptr, &palette_ptr,
+ num_spalettes);
+ palette_ptr - array of png_sPLT_struct structures
+ to be added to the list of palettes
+ in the info structure.
+ num_spalettes - number of palette structures to be
+ added.
+
+ png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y,
+ unit_type);
+ offset_x - positive offset from the left
+ edge of the screen
+ offset_y - positive offset from the top
+ edge of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
+ unit_type);
+ res_x - pixels/unit physical resolution
+ in x direction
+ res_y - pixels/unit physical resolution
+ in y direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_set_sCAL(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_set_sCAL_s(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ png_set_unknown_chunks(png_ptr, info_ptr, &unknowns,
+ num_unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position to write chunk in file
+ 0: do not write chunk
+ PNG_HAVE_IHDR: before PLTE
+ PNG_HAVE_PLTE: before IDAT
+ PNG_AFTER_IDAT: after IDAT
+
+The "location" member is set automatically according to
+what part of the output file has already been written.
+You can change its value after calling png_set_unknown_chunks()
+as demonstrated in pngtest.c. Within each of the "locations",
+the chunks are sequenced according to their position in the
+structure (that is, the value of "i", which is the order in which
+the chunk was either read from the input file or defined with
+png_set_unknown_chunks).
+
+A quick word about text and num_text. text is an array of png_text
+structures. num_text is the number of valid structures in the array.
+Each png_text structure holds a language code, a keyword, a text value,
+and a compression type.
+
+The compression types have the same valid numbers as the compression
+types of the image data. Currently, the only valid number is zero.
+However, you can store text either compressed or uncompressed, unlike
+images, which always have to be compressed. So if you don't want the
+text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
+Because tEXt and zTXt chunks don't have a language field, if you
+specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt
+any language code or translated keyword will not be written out.
+
+Until text gets around 1000 bytes, it is not worth compressing it.
+After the text has been written out to the file, the compression type
+is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
+so that it isn't written out again at the end (in case you are calling
+png_write_end() with the same struct.
+
+The keywords that are given in the PNG Specification are:
+
+ Title Short (one line) title or
+ caption for image
+ Author Name of image's creator
+ Description Description of image (possibly long)
+ Copyright Copyright notice
+ Creation Time Time of original image creation
+ (usually RFC 1123 format, see below)
+ Software Software used to create the image
+ Disclaimer Legal disclaimer
+ Warning Warning of nature of content
+ Source Device used to create the image
+ Comment Miscellaneous comment; conversion
+ from other image format
+
+The keyword-text pairs work like this. Keywords should be short
+simple descriptions of what the comment is about. Some typical
+keywords are found in the PNG specification, as is some recommendations
+on keywords. You can repeat keywords in a file. You can even write
+some text before the image and some after. For example, you may want
+to put a description of the image before the image, but leave the
+disclaimer until after, so viewers working over modem connections
+don't have to wait for the disclaimer to go over the modem before
+they start seeing the image. Finally, keywords should be full
+words, not abbreviations. Keywords and text are in the ISO 8859-1
+(Latin-1) character set (a superset of regular ASCII) and can not
+contain NUL characters, and should not contain control or other
+unprintable characters. To make the comments widely readable, stick
+with basic ASCII, and avoid machine specific character set extensions
+like the IBM-PC character set. The keyword must be present, but
+you can leave off the text string on non-compressed pairs.
+Compressed pairs must have a text string, as only the text string
+is compressed anyway, so the compression would be meaningless.
+
+PNG supports modification time via the png_time structure. Two
+conversion routines are provided, png_convert_from_time_t() for
+time_t and png_convert_from_struct_tm() for struct tm. The
+time_t routine uses gmtime(). You don't have to use either of
+these, but if you wish to fill in the png_time structure directly,
+you should provide the time in universal time (GMT) if possible
+instead of your local time. Note that the year number is the full
+year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and
+that months start with 1.
+
+If you want to store the time of the original image creation, you should
+use a plain tEXt chunk with the "Creation Time" keyword. This is
+necessary because the "creation time" of a PNG image is somewhat vague,
+depending on whether you mean the PNG file, the time the image was
+created in a non-PNG format, a still photo from which the image was
+scanned, or possibly the subject matter itself. In order to facilitate
+machine-readable dates, it is recommended that the "Creation Time"
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
+although this isn't a requirement. Unlike the tIME chunk, the
+"Creation Time" tEXt chunk is not expected to be automatically changed
+by the software. To facilitate the use of RFC 1123 dates, a function
+png_convert_to_rfc1123(png_timep) is provided to convert from PNG
+time to an RFC 1123 format string.
+
+.SS Writing unknown chunks
+
+You can use the png_set_unknown_chunks function to queue up chunks
+for writing. You give it a chunk name, raw data, and a size; that's
+all there is to it. The chunks will be written by the next following
+png_write_info_before_PLTE, png_write_info, or png_write_end function.
+Any chunks previously read into the info structure's unknown-chunk
+list will also be written out in a sequence that satisfies the PNG
+specification's ordering rules.
+
+.SS The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+in the info structure. All defined output
+transformations are permitted, enabled by the following masks.
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+ PNG_TRANSFORM_STRIP_FILLER Strip out filler
+ bytes (deprecated).
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading
+ filler bytes
+ PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing
+ filler bytes
+
+If you have valid image data in the info structure (you can use
+png_set_rows() to put image data in the info structure), simply do this:
+
+ png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of some set of
+transformation flags. This call is equivalent to png_write_info(),
+followed the set of transformations indicated by the transform mask,
+then png_write_image(), and finally png_write_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future output transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_write_png().
+
+.SS The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data. You do
+this with a call to png_write_info().
+
+ png_write_info(png_ptr, info_ptr);
+
+Note that there is one transformation you may need to do before
+png_write_info(). In PNG files, the alpha channel in an image is the
+level of opacity. If your data is supplied as a level of transparency,
+you can invert the alpha channel before you write it, so that 0 is
+fully transparent and 255 (in 8-bit or paletted images) or 65535
+(in 16-bit images) is fully opaque, with
+
+ png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written. If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
+If you need to write a private chunk that you want to appear before
+the PLTE chunk when PLTE is present, you can write the PNG info in
+two steps, and insert code to write your own chunk between them:
+
+ png_write_info_before_PLTE(png_ptr, info_ptr);
+ png_set_unknown_chunks(png_ptr, info_ptr, ...);
+ png_write_info(png_ptr, info_ptr);
+
+After you've written the file information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code tells
+the library to strip input data that has 4 or 8 bytes per pixel down
+to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2
+bytes per pixel).
+
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+where the 0 is unused, and the location is either PNG_FILLER_BEFORE or
+PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel
+is stored XRGB or RGBX.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit files.
+If the data is supplied at 1 pixel per byte, use this code, which will
+correctly pack the pixels into a single byte:
+
+ png_set_packing(png_ptr);
+
+PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your
+data is of another bit depth, you can write an sBIT chunk into the
+file so that decoders can recover the original data if desired.
+
+ /* Set the true bit depth of the image data */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ sig_bit.red = true_bit_depth;
+ sig_bit.green = true_bit_depth;
+ sig_bit.blue = true_bit_depth;
+ }
+ else
+ {
+ sig_bit.gray = true_bit_depth;
+ }
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ sig_bit.alpha = true_bit_depth;
+ }
+
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+If the data is stored in the row buffer in a bit depth other than
+one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG),
+this will scale the values to appear to be the correct bit depth as
+is required by PNG.
+
+ png_set_shift(png_ptr, &sig_bit);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code would be used if they are
+supplied the other way (little-endian, i.e. least significant bits
+first, the way PCs store them):
+
+ if (bit_depth > 8)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+PNG files store 3 color pixels in red, green, blue order. This code
+would be used if they are supplied as blue, green, red:
+
+ png_set_bgr(png_ptr);
+
+PNG files describe monochrome as black being zero and white being
+one. This code would be used if the pixels are supplied with this reversed
+(black being one and white being zero):
+
+ png_set_invert_mono(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_write_user_transform_fn(png_ptr,
+ write_transform_fn);
+
+You must supply the function
+
+ void write_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+before any of the other transformations are processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function.
+
+ png_set_user_transform_info(png_ptr, user_ptr, 0, 0);
+
+The user_channels and user_depth parameters of this function are ignored
+when writing; you can set them to zero as shown.
+
+You can retrieve the pointer via the function png_get_user_transform_ptr().
+For example:
+
+ voidp write_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+It is possible to have libpng flush any pending output, either manually,
+or automatically after a certain number of lines have been written. To
+flush the output stream a single time call:
+
+ png_write_flush(png_ptr);
+
+and to have libpng flush the output stream periodically after a certain
+number of scanlines have been written, call:
+
+ png_set_flush(png_ptr, nrows);
+
+Note that the distance between rows is from the last time png_write_flush()
+was called, or the first row of the image if it has never been called.
+So if you write 50 lines, and then png_set_flush 25, it will flush the
+output on the next scanline, and every 25 lines thereafter, unless
+png_write_flush() is called before 25 more lines have been written.
+If nrows is too small (less than about 10 lines for a 640 pixel wide
+RGB image) the image compression may decrease noticeably (although this
+may be acceptable for real-time applications). Infrequent flushing will
+only degrade the compression performance by a few percent over images
+that do not use flushing.
+
+.SS Writing the image data
+
+That's it for the transformations. Now you can write the image data.
+The simplest way to do this is in one function call. If you have the
+whole image in memory, you can just call png_write_image() and libpng
+will write the image. You will need to pass in an array of pointers to
+each row. This function automatically handles interlacing, so you don't
+need to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_write_rows().
+
+ png_write_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_byte *row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to write the whole image at once, you can
+use png_write_rows() instead. If the file is not interlaced,
+this is simple:
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+row_pointers is the same as in the png_write_image() call.
+
+If you are just writing one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+
+ png_write_row(png_ptr, row_pointer);
+
+When the file is interlaced, things can get a good deal more complicated.
+The only currently (as of the PNG Specification version 1.2, dated July
+1999) defined interlacing scheme for PNG files is the "Adam7" interlace
+scheme, that breaks down an image into seven smaller images of varying
+size. libpng will build these images for you, or you can do them
+yourself. If you want to build them yourself, see the PNG specification
+for details of which pixels to write when.
+
+If you don't want libpng to handle the interlacing details, just
+use png_set_interlace_handling() and call png_write_rows() the
+correct number of times to write all seven sub-images.
+
+If you want libpng to build the sub-images, call this before you start
+writing any rows:
+
+ number_of_passes =
+ png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this is seven,
+but may change if another interlace type is added.
+
+Then write the complete image number_of_passes times.
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+As some of these rows are not used, and thus return immediately, you may
+want to read about interlacing in the PNG specification, and only update
+the rows that are actually used.
+
+.SS Finishing a sequential write
+
+After you are finished writing the image, you should finish writing
+the file. If you are interested in writing comments or time, you should
+pass an appropriately filled png_info pointer. If you are not interested,
+you can pass NULL.
+
+ png_write_end(png_ptr, info_ptr);
+
+When you are done, you can free all memory used by libpng like this:
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those cases do nothing.
+The "seq" parameter is ignored if only one item of the selected data
+type, such as PLTE, is allowed. If "seq" is not -1, and multiple items
+are allowed for the data type identified in the mask, such as text or
+sPLT, only the n'th item in the structure is freed, where n is "seq".
+
+If you allocated data such as a palette that you passed in to libpng
+with png_set_*, you must not free it until just before the call to
+png_destroy_write_struct().
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+For example, to transfer responsibility for some data from a read structure
+to a write structure, you could use
+
+ png_data_freer(read_ptr, read_info_ptr,
+ PNG_USER_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+ png_data_freer(write_ptr, write_info_ptr,
+ PNG_DESTROY_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+
+thereby briefly reassigning responsibility for freeing to the user but
+immediately afterwards reassigning it once more to the write_destroy
+function. Having done this, it would then be safe to destroy the read
+structure and continue to use the PLTE, tRNS, and hIST data in the write
+structure.
+
+This function only affects data that has already been allocated.
+You can call this function before calling after the png_set_*() functions
+to control whether the user or png_destroy_*() is supposed to free the data.
+When the user assumes responsibility for libpng-allocated data, the
+application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+For a more compact example of writing a PNG image, see the file example.c.
+
+.SH V. Modifying/Customizing libpng:
+
+There are two issues here. The first is changing how libpng does
+standard things like memory allocation, input/output, and error handling.
+The second deals with more complicated things like adding new chunks,
+adding new transformations, and generally changing how libpng works.
+Both of those are compile-time issues; that is, they are generally
+determined at the time the code is written, and there is rarely a need
+to provide the user with a means of changing them.
+
+Memory allocation, input/output, and error handling
+
+All of the memory allocation, input/output, and error handling in libpng
+goes through callbacks that are user-settable. The default routines are
+in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change
+these functions, call the appropriate png_set_*_fn() function.
+
+Memory allocation is done through the functions png_malloc(), png_calloc(),
+and png_free(). These currently just call the standard C functions.
+png_calloc() calls png_malloc() and then png_memset() to clear the newly
+allocated memory to zero. If your pointers can't access more then 64K
+at a time, you will want to set MAXSEG_64K in zlib.h. Since it is
+unlikely that the method of handling memory allocation on a platform
+will change between applications, these functions must be modified in
+the library at compile time. If you prefer to use a different method
+of allocating and freeing data, you can use png_create_read_struct_2() or
+png_create_write_struct_2() to register your own functions as described
+above. These functions also provide a void pointer that can be retrieved
+via
+
+ mem_ptr=png_get_mem_ptr(png_ptr);
+
+Your replacement memory functions must have prototypes as follows:
+
+ png_voidp malloc_fn(png_structp png_ptr,
+ png_size_t size);
+ void free_fn(png_structp png_ptr, png_voidp ptr);
+
+Your malloc_fn() must return NULL in case of failure. The png_malloc()
+function will normally call png_error() if it receives a NULL from the
+system memory allocator or from your replacement malloc_fn().
+
+Your free_fn() will never be called with a NULL ptr, since libpng's
+png_free() checks for NULL before calling free_fn().
+
+Input/Output in libpng is done through png_read() and png_write(),
+which currently just call fread() and fwrite(). The FILE * is stored in
+png_struct and is initialized via png_init_io(). If you wish to change
+the method of I/O, the library supplies callbacks that you can set
+through the function png_set_read_fn() and png_set_write_fn() at run
+time, instead of calling the png_init_io() function. These functions
+also provide a void pointer that can be retrieved via the function
+png_get_io_ptr(). For example:
+
+ png_set_read_fn(png_structp read_ptr,
+ voidp read_io_ptr, png_rw_ptr read_data_fn)
+
+ png_set_write_fn(png_structp write_ptr,
+ voidp write_io_ptr, png_rw_ptr write_data_fn,
+ png_flush_ptr output_flush_fn);
+
+ voidp read_io_ptr = png_get_io_ptr(read_ptr);
+ voidp write_io_ptr = png_get_io_ptr(write_ptr);
+
+The replacement I/O functions must have prototypes as follows:
+
+ void user_read_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_write_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_flush_data(png_structp png_ptr);
+
+The user_read_data() function is responsible for detecting and
+handling end-of-data errors.
+
+Supplying NULL for the read, write, or flush functions sets them back
+to using the default C stream functions, which expect the io_ptr to
+point to a standard *FILE structure. It is probably a mistake
+to use NULL for one of write_data_fn and output_flush_fn but not both
+of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined.
+It is an error to read from a write stream, and vice versa.
+
+Error handling in libpng is done through png_error() and png_warning().
+Errors handled through png_error() are fatal, meaning that png_error()
+should never return to its caller. Currently, this is handled via
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
+to print a warning message, and then control returns to the calling code.
+By default png_error() and png_warning() print a message on stderr via
+fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined
+(because you don't want the messages) or PNG_NO_STDIO defined (because
+fprintf() isn't available). If you wish to change the behavior of the error
+functions, you will need to set up your own message callbacks. These
+functions are normally supplied at the time that the png_struct is created.
+It is also possible to redirect errors and warnings to your own replacement
+functions after png_create_*_struct() has been called by calling:
+
+ png_set_error_fn(png_structp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn,
+ png_error_ptr warning_fn);
+
+ png_voidp error_ptr = png_get_error_ptr(png_ptr);
+
+If NULL is supplied for either error_fn or warning_fn, then the libpng
+default function will be used, calling fprintf() and/or longjmp() if a
+problem is encountered. The replacement error functions should have
+parameters as follows:
+
+ void user_error_fn(png_structp png_ptr,
+ png_const_charp error_msg);
+ void user_warning_fn(png_structp png_ptr,
+ png_const_charp warning_msg);
+
+The motivation behind using setjmp() and longjmp() is the C++ throw and
+catch exception handling methods. This makes the code much easier to write,
+as there is no need to check every return code of every function call.
+However, there are some uncertainties about the status of local variables
+after a longjmp, so the user may want to be careful about doing anything
+after setjmp returns non-zero besides returning itself. Consult your
+compiler documentation for more details. For an alternative approach, you
+may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net).
+
+.SS Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code. The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks. However, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of understanding of how it works.
+Pay particular attention to the sections that describe chunk names,
+and look at how other chunks were designed, so you can do things
+similarly. Second, check out the sections of libpng that read and
+write chunks. Try to find a chunk that is similar to yours and use
+it as a template. More details can be found in the comments inside
+the code. It is best to handle unknown chunks in a generic method,
+via callback functions, instead of by modifying libpng functions.
+
+If you wish to write your own transformation for the data, look through
+the part of the code that does the transformations, and check out some of
+the simpler ones to get an idea of how they work. Try to find a similar
+transformation to the one you want to add and copy off of it. More details
+can be found in the comments inside the code itself.
+
+.SS Configuring for 16 bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more then 64K at a time. Even if you can, the memory
+won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+.SS Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call. See zlib.h or zconf.h in the zlib library for more information.
+
+.SS Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set. Everything in the library (except for zlib's structure) is
+expecting far data. You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful). Make
+note that the rows of data are defined as png_bytepp, which is an
+unsigned char far * far *.
+
+.SS Configuring for gui/windowing platforms:
+
+You will need to write new error and warning functions that use the GUI
+interface, as described previously, and set them to be the error and
+warning functions at the time that png_create_*_struct() is called,
+in order to have them available during the structure initialization.
+They can be changed later via png_set_error_fn(). On some compilers,
+you may also have to change the memory allocators (png_malloc, etc.).
+
+.SS Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h. If you need to add, change
+or delete an include, this is the place to do it.
+The includes that are not needed outside libpng are protected by the
+PNG_INTERNAL definition, which is only defined for those routines inside
+libpng itself. The files in libpng proper only include png.h, which
+includes pngconf.h.
+
+.SS Configuring zlib:
+
+There are special functions to configure the compression. Perhaps the
+most useful one changes the compression level, which currently uses
+input compression values in the range 0 - 9. The library normally
+uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests
+have shown that for a large majority of images, compression values in
+the range 3-6 compress nearly as well as higher levels, and do so much
+faster. For online applications it may be desirable to have maximum speed
+(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also
+specify no compression (Z_NO_COMPRESSION = 0), but this would create
+files larger than just storing the raw bitmap. You can specify the
+compression level by calling:
+
+ png_set_compression_level(png_ptr, level);
+
+Another useful one is to reduce the memory level used by the library.
+The memory level defaults to 8, but it can be lowered if you are
+short on memory (running DOS, for example, where you only have 640K).
+Note that the memory level does have an effect on compression; among
+other things, lower levels will result in sections of incompressible
+data being emitted in smaller stored blocks, with a correspondingly
+larger relative overhead of up to 15% in the worst case.
+
+ png_set_compression_mem_level(png_ptr, level);
+
+The other functions are for configuring zlib. They are not recommended
+for normal use and may result in writing an invalid PNG file. See
+zlib.h for more information on what these mean.
+
+ png_set_compression_strategy(png_ptr,
+ strategy);
+ png_set_compression_window_bits(png_ptr,
+ window_bits);
+ png_set_compression_method(png_ptr, method);
+ png_set_compression_buffer_size(png_ptr, size);
+
+.SS Controlling row filtering
+
+If you want to control whether libpng uses filtering or not, which
+filters are used, and how it goes about picking row filters, you
+can call one of these functions. The selection and configuration
+of row filters can have a significant impact on the size and
+encoding speed and a somewhat lesser impact on the decoding speed
+of an image. Filtering is enabled by default for RGB and grayscale
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
+
+The 'method' parameter sets the main filtering method, which is
+currently only '0' in the PNG 1.2 specification. The 'filters'
+parameter sets which filter(s), if any, should be used for each
+scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
+to turn filtering on and off, respectively.
+
+Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
+PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
+ORed together with '|' to specify one or more filters to use.
+These filters are described in more detail in the PNG specification.
+If you intend to change the filter type during the course of writing
+the image, you should start with flags set for all of the filters
+you intend to use so that libpng can initialize its internal
+structures appropriately for all of the filter types. (Note that this
+means the first row must always be adaptively filtered, because libpng
+currently does not allocate the filter buffers until png_write_row()
+is called for the first time.)
+
+ filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+ PNG_FILTER_UP | PNG_FILTER_AVG |
+ PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
+ filters);
+ The second parameter can also be
+ PNG_INTRAPIXEL_DIFFERENCING if you are
+ writing a PNG to be embedded in a MNG
+ datastream. This parameter must be the
+ same as the value of filter_method used
+ in png_set_IHDR().
+
+It is also possible to influence how libpng chooses from among the
+available filters. This is done in one or both of two ways - by
+telling it how important it is to keep the same filter for successive
+rows, and by telling it the relative computational costs of the filters.
+
+ double weights[3] = {1.5, 1.3, 1.1},
+ costs[PNG_FILTER_VALUE_LAST] =
+ {1.0, 1.3, 1.3, 1.5, 1.7};
+
+ png_set_filter_heuristics(png_ptr,
+ PNG_FILTER_HEURISTIC_WEIGHTED, 3,
+ weights, costs);
+
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter. In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+"sum of absolute differences" 1.5 x 1.3 times higher than other filters
+and still be chosen, while the NONE filter could have a sum 1.1 times
+higher than other filters and still be chosen. Unspecified weights are
+taken to be 1.0, and the specified weights should probably be declining
+like those above in order to emphasize recent filters over older filters.
+
+The filter costs specify for each filter type a relative decoding cost
+to be considered when selecting row filters. This means that filters
+with higher costs are less likely to be chosen over filters with lower
+costs, unless their "sum of absolute differences" is that much smaller.
+The costs do not necessarily reflect the exact computational speeds of
+the various filters, since this would unduly influence the final image
+size.
+
+Note that the numbers above were invented purely for this example and
+are given only to help explain the function usage. Little testing has
+been done to find optimum values for either the costs or the weights.
+
+.SS Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled. All the defines end in _SUPPORTED. If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
+along with directives to turn on any of the capabilities that you do
+want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra
+transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks. Use of the
+PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
+that is incapable of reading or writing ancillary chunks. If you are
+not using the progressive reading capability, you can turn that off
+with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
+capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs. However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with pngr and all the writing files start with
+pngw. The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+.SS Requesting debug printout
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout. Set it to an integer value in the range 0 to 3. Higher
+numbers result in increasing amounts of debugging information. The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+ png_debug(level, message)
+ png_debug1(level, message, p1)
+ png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives. For example,
+
+ png_debug1(2, "foo=%d\n", foo);
+
+is expanded to
+
+ if(PNG_DEBUG > 2)
+ fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+ #ifdef PNG_DEBUG
+ fprintf(stderr, ...
+ #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed. There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+.SH VI. MNG support
+
+The MNG specification (available at http://www.libpng.org/pub/mng) allows
+certain extensions to PNG for PNG images that are embedded in MNG datastreams.
+Libpng can support some of these extensions. To enable them, use the
+png_permit_mng_features() function:
+
+ feature_set = png_permit_mng_features(png_ptr, mask)
+ mask is a png_uint_32 containing the bitwise OR of the
+ features you want to enable. These include
+ PNG_FLAG_MNG_EMPTY_PLTE
+ PNG_FLAG_MNG_FILTER_64
+ PNG_ALL_MNG_FEATURES
+ feature_set is a png_uint_32 that is the bitwise AND of
+ your mask with the set of MNG features that is
+ supported by the version of libpng that you are using.
+
+It is an error to use this function when reading or writing a standalone
+PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped
+in a MNG datastream. As a minimum, it must have the MNG 8-byte signature
+and the MHDR and MEND chunks. Libpng does not provide support for these
+or any other MNG chunks; your application must provide its own support for
+them. You may wish to consider using libmng (available at
+http://www.libmng.com) instead.
+
+.SH VII. Changes to Libpng from version 0.88
+
+It should be noted that versions of libpng later than 0.96 are not
+distributed by the original libpng author, Guy Schalnat, nor by
+Andreas Dilger, who had taken over from Guy during 1996 and 1997, and
+distributed versions 0.89 through 0.96, but rather by another member
+of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are
+still alive and well, but they have moved on to other things.
+
+The old libpng functions png_read_init(), png_write_init(),
+png_info_init(), png_read_destroy(), and png_write_destroy() have been
+moved to PNG_INTERNAL in version 0.95 to discourage their use. These
+functions will be removed from libpng version 2.0.0.
+
+The preferred method of creating and initializing the libpng structures is
+via the png_create_read_struct(), png_create_write_struct(), and
+png_create_info_struct() because they isolate the size of the structures
+from the application, allow version error checking, and also allow the
+use of custom error handling routines during the initialization, which
+the old functions do not. The functions png_read_destroy() and
+png_write_destroy() do not actually free the memory that libpng
+allocated for these structs, but just reset the data structures, so they
+can be used instead of png_destroy_read_struct() and
+png_destroy_write_struct() if you feel there is too much system overhead
+allocating and freeing the png_struct for each image read.
+
+Setting the error callbacks via png_set_message_fn() before
+png_read_init() as was suggested in libpng-0.88 is no longer supported
+because this caused applications that do not use custom error functions
+to fail if the png_ptr was not initialized to zero. It is still possible
+to set the error callbacks AFTER png_read_init(), or to change them with
+png_set_error_fn(), which is essentially the same function, but with a new
+name to force compilation errors with applications that try to use the old
+method.
+
+Starting with version 1.0.7, you can find out which version of the library
+you are using at run-time:
+
+ png_uint_32 libpng_vn = png_access_version_number();
+
+The number libpng_vn is constructed from the major version, minor
+version with leading zero, and release number with leading zero,
+(e.g., libpng_vn for version 1.0.7 is 10007).
+
+You can also check which version of png.h you used when compiling your
+application:
+
+ png_uint_32 application_vn = PNG_LIBPNG_VER;
+
+.SH VIII. Changes to Libpng from version 1.0.x to 1.2.x
+
+Support for user memory management was enabled by default. To
+accomplish this, the functions png_create_read_struct_2(),
+png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(),
+png_malloc_default(), and png_free_default() were added.
+
+Support for the iTXt chunk has been enabled by default as of
+version 1.2.41.
+
+Support for certain MNG features was enabled.
+
+Support for numbered error messages was added. However, we never got
+around to actually numbering the error messages. The function
+png_set_strip_error_numbers() was added (Note: the prototype for this
+function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE
+builds of libpng-1.2.15. It was restored in libpng-1.2.36).
+
+The png_malloc_warn() function was added at libpng-1.2.3. This issues
+a png_warning and returns NULL instead of aborting when it fails to
+acquire the requested memory allocation.
+
+Support for setting user limits on image width and height was enabled
+by default. The functions png_set_user_limits(), png_get_user_width_max(),
+and png_get_user_height_max() were added at libpng-1.2.6.
+
+The png_set_add_alpha() function was added at libpng-1.2.7.
+
+The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9.
+Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the
+tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is
+deprecated.
+
+A number of macro definitions in support of runtime selection of
+assembler code features (especially Intel MMX code support) were
+added at libpng-1.2.0:
+
+ PNG_ASM_FLAG_MMX_SUPPORT_COMPILED
+ PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU
+ PNG_ASM_FLAG_MMX_READ_COMBINE_ROW
+ PNG_ASM_FLAG_MMX_READ_INTERLACE
+ PNG_ASM_FLAG_MMX_READ_FILTER_SUB
+ PNG_ASM_FLAG_MMX_READ_FILTER_UP
+ PNG_ASM_FLAG_MMX_READ_FILTER_AVG
+ PNG_ASM_FLAG_MMX_READ_FILTER_PAETH
+ PNG_ASM_FLAGS_INITIALIZED
+ PNG_MMX_READ_FLAGS
+ PNG_MMX_FLAGS
+ PNG_MMX_WRITE_FLAGS
+ PNG_MMX_FLAGS
+
+We added the following functions in support of runtime
+selection of assembler code features:
+
+ png_get_mmx_flagmask()
+ png_set_mmx_thresholds()
+ png_get_asm_flags()
+ png_get_mmx_bitdepth_threshold()
+ png_get_mmx_rowbytes_threshold()
+ png_set_asm_flags()
+
+We replaced all of these functions with simple stubs in libpng-1.2.20,
+when the Intel assembler code was removed due to a licensing issue.
+
+These macros are deprecated:
+
+ PNG_READ_TRANSFORMS_NOT_SUPPORTED
+ PNG_PROGRESSIVE_READ_NOT_SUPPORTED
+ PNG_NO_SEQUENTIAL_READ_SUPPORTED
+ PNG_WRITE_TRANSFORMS_NOT_SUPPORTED
+ PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED
+ PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED
+
+They have been replaced, respectively, by:
+
+ PNG_NO_READ_TRANSFORMS
+ PNG_NO_PROGRESSIVE_READ
+ PNG_NO_SEQUENTIAL_READ
+ PNG_NO_WRITE_TRANSFORMS
+ PNG_NO_READ_ANCILLARY_CHUNKS
+ PNG_NO_WRITE_ANCILLARY_CHUNKS
+
+PNG_MAX_UINT was replaced with PNG_UINT_31_MAX. It has been
+deprecated since libpng-1.0.16 and libpng-1.2.6.
+
+The function
+ png_check_sig(sig, num)
+was replaced with
+ !png_sig_cmp(sig, 0, num)
+It has been deprecated since libpng-0.90.
+
+The function
+ png_set_gray_1_2_4_to_8()
+which also expands tRNS to alpha was replaced with
+ png_set_expand_gray_1_2_4_to_8()
+which does not. It has been deprecated since libpng-1.0.18 and 1.2.9.
+
+.SH IX. (Omitted)
+
+
+.SH X. Detecting libpng
+
+The png_get_io_ptr() function has been present since libpng-0.88, has never
+changed, and is unaffected by conditional compilation macros. It is the
+best choice for use in configure scripts for detecting the presence of any
+libpng version since 0.88. In an autoconf "configure.in" you could use
+
+ AC_CHECK_LIB(png, png_get_io_ptr, ...
+
+.SH XI. Source code repository
+
+Since about February 2009, version 1.2.34, libpng has been under "git" source
+control. The git repository was built from old libpng-x.y.z.tar.gz files
+going back to version 0.70. You can access the git repository (read only)
+at
+
+ git://libpng.git.sourceforge.net/gitroot/libpng
+
+or you can browse it via "gitweb" at
+
+ http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng
+
+Patches can be sent to glennrp at users.sourceforge.net or to
+png-mng-implement at lists.sourceforge.net or you can upload them to
+the libpng bug tracker at
+
+ http://libpng.sourceforge.net
+
+.SH XII. Coding style
+
+Our coding style is similar to the "Allman" style, with curly
+braces on separate lines:
+
+ if (condition)
+ {
+ action;
+ }
+
+ else if (another condition)
+ {
+ another action;
+ }
+
+The braces can be omitted from simple one-line actions:
+
+ if (condition)
+ return (0);
+
+We use 3-space indentation, except for continued statements which
+are usually indented the same as the first line of the statement
+plus four more spaces.
+
+For macro definitions we use 2-space indentation, always leaving the "#"
+in the first column.
+
+ #ifndef PNG_NO_FEATURE
+ # ifndef PNG_FEATURE_SUPPORTED
+ # define PNG_FEATURE_SUPPORTED
+ # endif
+ #endif
+
+Comments appear with the leading "/*" at the same indentation as
+the statement that follows the comment:
+
+ /* Single-line comment */
+ statement;
+
+ /* Multiple-line
+ * comment
+ */
+ statement;
+
+Very short comments can be placed at the end of the statement
+to which they pertain:
+
+ statement; /* comment */
+
+We don't use C++ style ("//") comments. We have, however,
+used them in the past in some now-abandoned MMX assembler
+code.
+
+Functions and their curly braces are not indented, and
+exported functions are marked with PNGAPI:
+
+ /* This is a public function that is visible to
+ * application programers. It does thus-and-so.
+ */
+ void PNGAPI
+ png_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for all exported functions appear in png.h,
+above the comment that says
+
+ /* Maintainer: Put new public prototypes here ... */
+
+We mark all non-exported functions with "/* PRIVATE */"":
+
+ void /* PRIVATE */
+ png_non_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for non-exported functions (except for those in
+pngtest) appear in
+the PNG_INTERNAL section of png.h
+above the comment that says
+
+ /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+The names of all exported functions and variables begin
+with "png_", and all publicly visible C preprocessor
+macros begin with "PNG".
+
+We put a space after each comma and after each semicolon
+in "for" statments, and we put spaces before and after each
+C binary operator and after "for" or "while". We don't
+put a space between a typecast and the expression being
+cast, nor do we put one between a function name and the
+left parenthesis that follows it:
+
+ for (i = 2; i > 0; --i)
+ y[i] = a(x) + (int)b;
+
+We prefer #ifdef and #ifndef to #if defined() and if !defined()
+when there is only one macro being tested.
+
+We do not use the TAB character for indentation in the C sources.
+
+Lines do not exceed 80 characters.
+
+Other rules can be inferred by inspecting the libpng source.
+
+.SH XIII. Y2K Compliance in libpng
+
+March 29, 2012
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.71 and
+upward through 1.2.49 are Y2K compliant. It is my belief that earlier
+versions were also Y2K compliant.
+
+Libpng only has three year fields. One is a 2-byte unsigned integer that
+will hold years up to 65535. The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+ "png_uint_16 year" in png_time_struct.
+
+The strings are
+ "png_charp time_buffer" in png_struct and
+ "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+ png_convert_to_rfc_1123() in png.c
+ (formerly png_convert_to_rfc_1152() in error)
+ png_convert_from_struct_tm() in pngwrite.c, called
+ in pngwrite.c
+ png_convert_from_time_t() in pngwrite.c
+ png_get_tIME() in pngget.c
+ png_handle_tIME() in pngrutil.c, called in pngread.c
+ png_set_tIME() in pngset.c
+ png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment. The
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year. There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or that they are incorrectly passing only a 2-digit year
+instead of "year - 1900" into the png_convert_from_struct_tm() function,
+but this is not under our control. The libpng documentation has always
+stated that it works with 4-digit years, and the APIs have been
+documented as such.
+
+The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+zlib, upon which libpng depends, is also Y2K compliant. It contains
+no date-related code.
+
+
+ Glenn Randers-Pehrson
+ libpng maintainer
+ PNG Development Group
+
+.SH NOTE
+
+Note about libpng version numbers:
+
+Due to various miscommunications, unforeseen code incompatibilities
+and occasional factors outside the authors' control, version numbering
+on the library has not always been consistent and straightforward.
+The following table summarizes matters since version 0.89c, which was
+the first widely used release:
+
+ source png.h png.h shared-lib
+ version string int version
+ ------- ------ ----- ----------
+ 0.89c ("beta 3") 0.89 89 1.0.89
+ 0.90 ("beta 4") 0.90 90 0.90
+ 0.95 ("beta 5") 0.95 95 0.95
+ 0.96 ("beta 6") 0.96 96 0.96
+ 0.97b ("beta 7") 1.00.97 97 1.0.1
+ 0.97c 0.97 97 2.0.97
+ 0.98 0.98 98 2.0.98
+ 0.99 0.99 98 2.0.99
+ 0.99a-m 0.99 99 2.0.99
+ 1.00 1.00 100 2.1.0
+ 1.0.0 1.0.0 100 2.1.0
+ 1.0.0 (from here on, the 100 2.1.0
+ 1.0.1 png.h string is 10001 2.1.0
+ 1.0.1a-e identical to the 10002 from here on, the
+ 1.0.2 source version) 10002 shared library is 2.V
+ 1.0.2a-b 10003 where V is the source
+ 1.0.1 10001 code version except as
+ 1.0.1a-e 10002 2.1.0.1a-e noted.
+ 1.0.2 10002 2.1.0.2
+ 1.0.2a-b 10003 2.1.0.2a-b
+ 1.0.3 10003 2.1.0.3
+ 1.0.3a-d 10004 2.1.0.3a-d
+ 1.0.4 10004 2.1.0.4
+ 1.0.4a-f 10005 2.1.0.4a-f
+ 1.0.5 (+ 2 patches) 10005 2.1.0.5
+ 1.0.5a-d 10006 2.1.0.5a-d
+ 1.0.5e-r 10100 2.1.0.5e-r
+ 1.0.5s-v 10006 2.1.0.5s-v
+ 1.0.6 (+ 3 patches) 10006 2.1.0.6
+ 1.0.6d-g 10007 2.1.0.6d-g
+ 1.0.6h 10007 10.6h
+ 1.0.6i 10007 10.6i
+ 1.0.6j 10007 2.1.0.6j
+ 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14
+ 1.0.7beta15-18 1 10007 2.1.0.7beta15-18
+ 1.0.7rc1-2 1 10007 2.1.0.7rc1-2
+ 1.0.7 1 10007 2.1.0.7
+ 1.0.8beta1-4 1 10008 2.1.0.8beta1-4
+ 1.0.8rc1 1 10008 2.1.0.8rc1
+ 1.0.8 1 10008 2.1.0.8
+ 1.0.9beta1-6 1 10009 2.1.0.9beta1-6
+ 1.0.9rc1 1 10009 2.1.0.9rc1
+ 1.0.9beta7-10 1 10009 2.1.0.9beta7-10
+ 1.0.9rc2 1 10009 2.1.0.9rc2
+ 1.0.9 1 10009 2.1.0.9
+ 1.0.10beta1 1 10010 2.1.0.10beta1
+ 1.0.10rc1 1 10010 2.1.0.10rc1
+ 1.0.10 1 10010 2.1.0.10
+ 1.0.11beta1-3 1 10011 2.1.0.11beta1-3
+ 1.0.11rc1 1 10011 2.1.0.11rc1
+ 1.0.11 1 10011 2.1.0.11
+ 1.0.12beta1-2 2 10012 2.1.0.12beta1-2
+ 1.0.12rc1 2 10012 2.1.0.12rc1
+ 1.0.12 2 10012 2.1.0.12
+ 1.1.0a-f - 10100 2.1.1.0a-f abandoned
+ 1.2.0beta1-2 2 10200 2.1.2.0beta1-2
+ 1.2.0beta3-5 3 10200 3.1.2.0beta3-5
+ 1.2.0rc1 3 10200 3.1.2.0rc1
+ 1.2.0 3 10200 3.1.2.0
+ 1.2.1beta-4 3 10201 3.1.2.1beta1-4
+ 1.2.1rc1-2 3 10201 3.1.2.1rc1-2
+ 1.2.1 3 10201 3.1.2.1
+ 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6
+ 1.0.13beta1 10 10013 10.so.0.1.0.13beta1
+ 1.0.13rc1 10 10013 10.so.0.1.0.13rc1
+ 1.2.2rc1 12 10202 12.so.0.1.2.2rc1
+ 1.0.13 10 10013 10.so.0.1.0.13
+ 1.2.2 12 10202 12.so.0.1.2.2
+ 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6
+ 1.2.3 12 10203 12.so.0.1.2.3
+ 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3
+ 1.2.4rc1 13 10204 12.so.0.1.2.4rc1
+ 1.0.14 10 10014 10.so.0.1.0.14
+ 1.2.4 13 10204 12.so.0.1.2.4
+ 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2
+ 1.0.15rc1 10 10015 10.so.0.1.0.15rc1
+ 1.0.15 10 10015 10.so.0.1.0.15
+ 1.2.5 13 10205 12.so.0.1.2.5
+ 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4
+ 1.2.6rc1-5 13 10206 12.so.0.1.2.6rc1-5
+ 1.0.16 10 10016 10.so.0.1.0.16
+ 1.2.6 13 10206 12.so.0.1.2.6
+ 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2
+ 1.0.17rc1 10 10017 10.so.0.1.0.17rc1
+ 1.2.7rc1 13 10207 12.so.0.1.2.7rc1
+ 1.0.17 10 10017 10.so.0.1.0.17
+ 1.2.7 13 10207 12.so.0.1.2.7
+ 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5
+ 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5
+ 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5
+ 1.0.18 10 10018 10.so.0.1.0.18
+ 1.2.8 13 10208 12.so.0.1.2.8
+ 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3
+ 1.2.9beta4-11 13 10209 12.so.0.9[.0]
+ 1.2.9rc1 13 10209 12.so.0.9[.0]
+ 1.2.9 13 10209 12.so.0.9[.0]
+ 1.2.10beta1-8 13 10210 12.so.0.10[.0]
+ 1.2.10rc1-3 13 10210 12.so.0.10[.0]
+ 1.2.10 13 10210 12.so.0.10[.0]
+ 1.2.11beta1-4 13 10211 12.so.0.11[.0]
+ 1.0.19rc1-5 10 10019 10.so.0.19[.0]
+ 1.2.11rc1-5 13 10211 12.so.0.11[.0]
+ 1.0.19 10 10019 10.so.0.19[.0]
+ 1.2.11 13 10211 12.so.0.11[.0]
+ 1.0.20 10 10020 10.so.0.20[.0]
+ 1.2.12 13 10212 12.so.0.12[.0]
+ 1.2.13beta1 13 10213 12.so.0.13[.0]
+ 1.0.21 10 10021 10.so.0.21[.0]
+ 1.2.13 13 10213 12.so.0.13[.0]
+ 1.2.14beta1-2 13 10214 12.so.0.14[.0]
+ 1.0.22rc1 10 10022 10.so.0.22[.0]
+ 1.2.14rc1 13 10214 12.so.0.14[.0]
+ 1.2.15beta1-6 13 10215 12.so.0.15[.0]
+ 1.0.23rc1-5 10 10023 10.so.0.23[.0]
+ 1.2.15rc1-5 13 10215 12.so.0.15[.0]
+ 1.0.23 10 10023 10.so.0.23[.0]
+ 1.2.15 13 10215 12.so.0.15[.0]
+ 1.2.16beta1-2 13 10216 12.so.0.16[.0]
+ 1.2.16rc1 13 10216 12.so.0.16[.0]
+ 1.0.24 10 10024 10.so.0.24[.0]
+ 1.2.16 13 10216 12.so.0.16[.0]
+ 1.2.17beta1-2 13 10217 12.so.0.17[.0]
+ 1.0.25rc1 10 10025 10.so.0.25[.0]
+ 1.2.17rc1-3 13 10217 12.so.0.17[.0]
+ 1.0.25 10 10025 10.so.0.25[.0]
+ 1.2.17 13 10217 12.so.0.17[.0]
+ 1.0.26 10 10026 10.so.0.26[.0]
+ 1.2.18 13 10218 12.so.0.18[.0]
+ 1.2.19beta1-31 13 10219 12.so.0.19[.0]
+ 1.0.27rc1-6 10 10027 10.so.0.27[.0]
+ 1.2.19rc1-6 13 10219 12.so.0.19[.0]
+ 1.0.27 10 10027 10.so.0.27[.0]
+ 1.2.19 13 10219 12.so.0.19[.0]
+ 1.2.20beta01-04 13 10220 12.so.0.20[.0]
+ 1.0.28rc1-6 10 10028 10.so.0.28[.0]
+ 1.2.20rc1-6 13 10220 12.so.0.20[.0]
+ 1.0.28 10 10028 10.so.0.28[.0]
+ 1.2.20 13 10220 12.so.0.20[.0]
+ 1.2.21beta1-2 13 10221 12.so.0.21[.0]
+ 1.2.21rc1-3 13 10221 12.so.0.21[.0]
+ 1.0.29 10 10029 10.so.0.29[.0]
+ 1.2.21 13 10221 12.so.0.21[.0]
+ 1.2.22beta1-4 13 10222 12.so.0.22[.0]
+ 1.0.30rc1 13 10030 10.so.0.30[.0]
+ 1.2.22rc1 13 10222 12.so.0.22[.0]
+ 1.0.30 10 10030 10.so.0.30[.0]
+ 1.2.22 13 10222 12.so.0.22[.0]
+ 1.2.23beta01-05 13 10223 12.so.0.23[.0]
+ 1.2.23rc01 13 10223 12.so.0.23[.0]
+ 1.2.23 13 10223 12.so.0.23[.0]
+ 1.2.24beta01-02 13 10224 12.so.0.24[.0]
+ 1.2.24rc01 13 10224 12.so.0.24[.0]
+ 1.2.24 13 10224 12.so.0.24[.0]
+ 1.2.25beta01-06 13 10225 12.so.0.25[.0]
+ 1.2.25rc01-02 13 10225 12.so.0.25[.0]
+ 1.0.31 10 10031 10.so.0.31[.0]
+ 1.2.25 13 10225 12.so.0.25[.0]
+ 1.2.26beta01-06 13 10226 12.so.0.26[.0]
+ 1.2.26rc01 13 10226 12.so.0.26[.0]
+ 1.2.26 13 10226 12.so.0.26[.0]
+ 1.0.32 10 10032 10.so.0.32[.0]
+ 1.2.27beta01-06 13 10227 12.so.0.27[.0]
+ 1.2.27rc01 13 10227 12.so.0.27[.0]
+ 1.0.33 10 10033 10.so.0.33[.0]
+ 1.2.27 13 10227 12.so.0.27[.0]
+ 1.0.34 10 10034 10.so.0.34[.0]
+ 1.2.28 13 10228 12.so.0.28[.0]
+ 1.2.29beta01-03 13 10229 12.so.0.29[.0]
+ 1.2.29rc01 13 10229 12.so.0.29[.0]
+ 1.0.35 10 10035 10.so.0.35[.0]
+ 1.2.29 13 10229 12.so.0.29[.0]
+ 1.0.37 10 10037 10.so.0.37[.0]
+ 1.2.30beta01-04 13 10230 12.so.0.30[.0]
+ 1.0.38rc01-08 10 10038 10.so.0.38[.0]
+ 1.2.30rc01-08 13 10230 12.so.0.30[.0]
+ 1.0.38 10 10038 10.so.0.38[.0]
+ 1.2.30 13 10230 12.so.0.30[.0]
+ 1.0.39rc01-03 10 10039 10.so.0.39[.0]
+ 1.2.31rc01-03 13 10231 12.so.0.31[.0]
+ 1.0.39 10 10039 10.so.0.39[.0]
+ 1.2.31 13 10231 12.so.0.31[.0]
+ 1.2.32beta01-02 13 10232 12.so.0.32[.0]
+ 1.0.40rc01 10 10040 10.so.0.40[.0]
+ 1.2.32rc01 13 10232 12.so.0.32[.0]
+ 1.0.40 10 10040 10.so.0.40[.0]
+ 1.2.32 13 10232 12.so.0.32[.0]
+ 1.2.33beta01-02 13 10233 12.so.0.33[.0]
+ 1.2.33rc01-02 13 10233 12.so.0.33[.0]
+ 1.0.41rc01 10 10041 10.so.0.41[.0]
+ 1.2.33 13 10233 12.so.0.33[.0]
+ 1.0.41 10 10041 10.so.0.41[.0]
+ 1.2.34beta01-07 13 10234 12.so.0.34[.0]
+ 1.0.42rc01 10 10042 10.so.0.42[.0]
+ 1.2.34rc01 13 10234 12.so.0.34[.0]
+ 1.0.42 10 10042 10.so.0.42[.0]
+ 1.2.34 13 10234 12.so.0.34[.0]
+ 1.2.35beta01-03 13 10235 12.so.0.35[.0]
+ 1.0.43rc01-02 10 10043 10.so.0.43[.0]
+ 1.2.35rc01-02 13 10235 12.so.0.35[.0]
+ 1.0.43 10 10043 10.so.0.43[.0]
+ 1.2.35 13 10235 12.so.0.35[.0]
+ 1.2.36beta01-05 13 10236 12.so.0.36[.0]
+ 1.2.36rc01 13 10236 12.so.0.36[.0]
+ 1.0.44 10 10044 10.so.0.44[.0]
+ 1.2.36 13 10236 12.so.0.36[.0]
+ 1.2.37beta01-03 13 10237 12.so.0.37[.0]
+ 1.2.37rc01 13 10237 12.so.0.37[.0]
+ 1.2.37 13 10237 12.so.0.37[.0]
+ 1.0.45 10 10045 12.so.0.45[.0]
+ 1.0.46 10 10046 10.so.0.46[.0]
+ 1.2.38beta01 13 10238 12.so.0.38[.0]
+ 1.2.38rc01-03 13 10238 12.so.0.38[.0]
+ 1.0.47 10 10047 10.so.0.47[.0]
+ 1.2.38 13 10238 12.so.0.38[.0]
+ 1.2.39beta01-05 13 10239 12.so.0.39[.0]
+ 1.2.39rc01 13 10239 12.so.0.39[.0]
+ 1.0.48 10 10048 10.so.0.48[.0]
+ 1.2.39 13 10239 12.so.0.39[.0]
+ 1.2.40beta01 13 10240 12.so.0.40[.0]
+ 1.2.40rc01 13 10240 12.so.0.40[.0]
+ 1.0.49 10 10049 10.so.0.49[.0]
+ 1.2.40 13 10240 12.so.0.40[.0]
+ 1.0.50 10 10050 10.so.0.50[.0]
+ 1.2.41beta01-18 13 10241 12.so.0.41[.0]
+ 1.0.51rc01 10 10051 10.so.0.51[.0]
+ 1.2.41rc01-03 13 10241 12.so.0.41[.0]
+ 1.0.51 10 10051 10.so.0.51[.0]
+ 1.2.41 13 10241 12.so.0.41[.0]
+ 1.2.42beta01-02 13 10242 12.so.0.42[.0]
+ 1.2.42rc01-05 13 10242 12.so.0.42[.0]
+ 1.0.52 10 10052 10.so.0.52[.0]
+ 1.2.42 13 10242 12.so.0.42[.0]
+ 1.2.43beta01-05 13 10243 12.so.0.43[.0]
+ 1.0.53rc01-02 10 10053 10.so.0.53[.0]
+ 1.2.43rc01-02 13 10243 12.so.0.43[.0]
+ 1.0.53 10 10053 10.so.0.53[.0]
+ 1.2.43 13 10243 12.so.0.43[.0]
+ 1.2.44beta01-03 13 10244 12.so.0.44[.0]
+ 1.2.44rc01-03 13 10244 12.so.0.44[.0]
+ 1.2.44 13 10244 12.so.0.44[.0]
+ 1.2.45beta01-03 13 10245 12.so.0.45[.0]
+ 1.0.55rc01 10 10055 10.so.0.55[.0]
+ 1.2.45rc01 13 10245 12.so.0.45[.0]
+ 1.0.55 10 10055 10.so.0.55[.0]
+ 1.2.45 13 10245 12.so.0.45[.0]
+ 1.2.46rc01-02 13 10246 12.so.0.46[.0]
+ 1.0.56 10 10056 10.so.0.56[.0]
+ 1.2.46 13 10246 12.so.0.46[.0]
+ 1.2.47beta01 13 10247 12.so.0.47[.0]
+ 1.2.47rc01 13 10247 12.so.0.47[.0]
+ 1.0.57rc01 10 10057 10.so.0.57[.0]
+ 1.2.47 13 10247 12.so.0.47[.0]
+ 1.0.57 10 10057 10.so.0.57[.0]
+ 1.2.48beta01 13 10248 12.so.0.48[.0]
+ 1.2.48rc01-02 13 10248 12.so.0.48[.0]
+ 1.0.58 10 10058 10.so.0.58[.0]
+ 1.2.48 13 10248 12.so.0.48[.0]
+ 1.2.49rc01 13 10249 12.so.0.49[.0]
+ 1.0.59 10 10059 10.so.0.59[.0]
+ 1.2.49 13 10249 12.so.0.49[.0]
+
+Henceforth the source version will match the shared-library minor
+and patch numbers; the shared-library major version number will be
+used for changes in backward compatibility, as it is intended. The
+PNG_PNGLIB_VER macro, which is not used within libpng but is available
+for applications, is an unsigned integer of the form xyyzz corresponding
+to the source version x.y.z (leading zeros in y and z). Beta versions
+were given the previous public release number plus a letter, until
+version 1.0.6j; from then on they were given the upcoming public
+release number plus "betaNN" or "rcNN".
+
+.SH "SEE ALSO"
+.IR libpngpf(3) ", " png(5)
+.LP
+.IR libpng :
+.IP
+http://libpng.sourceforge.net (follow the [DOWNLOAD] link)
+http://www.libpng.org/pub/png
+
+.LP
+.IR zlib :
+.IP
+(generally) at the same location as
+.I libpng
+or at
+.br
+ftp://ftp.info-zip.org/pub/infozip/zlib
+
+.LP
+.IR PNG specification: RFC 2083
+.IP
+(generally) at the same location as
+.I libpng
+or at
+.br
+ftp://ftp.rfc-editor.org:/in-notes/rfc2083.txt
+.br
+or (as a W3C Recommendation) at
+.br
+http://www.w3.org/TR/REC-png.html
+
+.LP
+In the case of any inconsistency between the PNG specification
+and this library, the specification takes precedence.
+
+.SH AUTHORS
+This man page: Glenn Randers-Pehrson
+<glennrp at users.sourceforge.net>
+
+The contributing authors would like to thank all those who helped
+with testing, bug fixes, and patience. This wouldn't have been
+possible without all of you.
+
+Thanks to Frank J. T. Wojcik for helping with the documentation.
+
+Libpng version 1.2.49 - March 29, 2012:
+Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
+Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
+
+Supported by the PNG development group
+.br
+png-mng-implement at lists.sf.net
+(subscription required; visit
+png-mng-implement at lists.sourceforge.net (subscription required; visit
+https://lists.sourceforge.net/lists/listinfo/png-mng-implement
+to subscribe).
+
+.SH COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+
+(This copy of the libpng notices is provided for your convenience. In case of
+any discrepancy between this copy and the notices in the file png.h that is
+included in the libpng distribution, the latter shall prevail.)
+
+If you modify libpng you may insert additional notices immediately following
+this sentence.
+
+This code is released under the libpng license.
+
+libpng versions 1.2.6, August 15, 2004, through 1.2.49, March 29, 2012, are
+Copyright (c) 2004,2006-2008 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.2.5
+with the following individual added to the list of Contributing Authors
+
+ Cosmin Truta
+
+libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are
+Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+distributed according to the same disclaimer and license as libpng-1.0.6
+with the following individuals added to the list of Contributing Authors
+
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Gilles Vollant
+
+and with the following additions to the disclaimer:
+
+ There is no warranty against interference with your
+ enjoyment of the library or against infringement.
+ There is no warranty that our efforts or the library
+ will fulfill any of your particular purposes or needs.
+ This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and
+ effort is with the user.
+
+libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+Copyright (c) 1998, 1999 Glenn Randers-Pehrson
+Distributed according to the same disclaimer and license as libpng-0.96,
+with the following individuals added to the list of Contributing Authors:
+
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
+
+libpng versions 0.89, June 1996, through 0.96, May 1997, are
+Copyright (c) 1996, 1997 Andreas Dilger
+Distributed according to the same disclaimer and license as libpng-0.88,
+with the following individuals added to the list of Contributing Authors:
+
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
+
+libpng versions 0.5, May 1995, through 0.88, January 1996, are
+Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+
+For the purposes of this copyright and license, "Contributing Authors"
+is defined as the following set of individuals:
+
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing Authors
+and Group 42, Inc. disclaim all warranties, expressed or implied,
+including, without limitation, the warranties of merchantability and of
+fitness for any purpose. The Contributing Authors and Group 42, Inc.
+assume no liability for direct, indirect, incidental, special, exemplary,
+or consequential damages, which may result from the use of the PNG
+Reference Library, even if advised of the possibility of such damage.
+
+Permission is hereby granted to use, copy, modify, and distribute this
+source code, or portions hereof, for any purpose, without fee, subject
+to the following restrictions:
+
+1. The origin of this source code must not be misrepresented.
+
+2. Altered versions must be plainly marked as such and
+ must not be misrepresented as being the original source.
+
+3. This Copyright notice may not be removed or altered from
+ any source or altered source distribution.
+
+The Contributing Authors and Group 42, Inc. specifically permit, without
+fee, and encourage the use of this source code as a component to
+supporting the PNG file format in commercial products. If you use this
+source code in a product, acknowledgment is not required but would be
+appreciated.
+
+
+A "png_get_copyright" function is available, for convenient use in "about"
+boxes and the like:
+
+ printf("%s",png_get_copyright(NULL));
+
+Also, the PNG logo (in PNG format, of course) is supplied in the
+files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+
+Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a
+certification mark of the Open Source Initiative.
+
+Glenn Randers-Pehrson
+glennrp at users.sourceforge.net
+March 29, 2012
+
+.\" end of man page
+
diff --git a/Source/LibPNG/libpng.txt b/Source/LibPNG/libpng.txt
new file mode 100644
index 0000000..019c886
--- /dev/null
+++ b/Source/LibPNG/libpng.txt
@@ -0,0 +1,3112 @@
+libpng.txt - A description on how to use and modify libpng
+
+ libpng version 1.2.40 - September 10, 2009
+ Updated and distributed by Glenn Randers-Pehrson
+ <glennrp at users.sourceforge.net>
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ This document is released under the libpng license.
+ For conditions of distribution and use, see the disclaimer
+ and license in png.h
+
+ Based on:
+
+ libpng versions 0.97, January 1998, through 1.2.40 - September 10, 2009
+ Updated and distributed by Glenn Randers-Pehrson
+ Copyright (c) 1998-2009 Glenn Randers-Pehrson
+
+ libpng 1.0 beta 6 version 0.96 May 28, 1997
+ Updated and distributed by Andreas Dilger
+ Copyright (c) 1996, 1997 Andreas Dilger
+
+ libpng 1.0 beta 2 - version 0.88 January 26, 1996
+ For conditions of distribution and use, see copyright
+ notice in png.h. Copyright (c) 1995, 1996 Guy Eric
+ Schalnat, Group 42, Inc.
+
+ Updated/rewritten per request in the libpng FAQ
+ Copyright (c) 1995, 1996 Frank J. T. Wojcik
+ December 18, 1995 & January 20, 1996
+
+I. Introduction
+
+This file describes how to use and modify the PNG reference library
+(known as libpng) for your own use. There are five sections to this
+file: introduction, structures, reading, writing, and modification and
+configuration notes for various special platforms. In addition to this
+file, example.c is a good starting point for using the library, as
+it is heavily commented and should include everything most people
+will need. We assume that libpng is already installed; see the
+INSTALL file for instructions on how to install libpng.
+
+For examples of libpng usage, see the files "example.c", "pngtest.c",
+and the files in the "contrib" directory, all of which are included in the
+libpng distribution.
+
+Libpng was written as a companion to the PNG specification, as a way
+of reducing the amount of time and effort it takes to support the PNG
+file format in application programs.
+
+The PNG specification (second edition), November 2003, is available as
+a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at
+<http://www.w3.org/TR/2003/REC-PNG-20031110/
+The W3C and ISO documents have identical technical content.
+
+The PNG-1.2 specification is available at
+<http://www.libpng.org/pub/png/documents/>. It is technically equivalent
+to the PNG specification (second edition) but has some additional material.
+
+The PNG-1.0 specification is available
+as RFC 2083 <http://www.libpng.org/pub/png/documents/> and as a
+W3C Recommendation <http://www.w3.org/TR/REC.png.html>.
+
+Some additional chunks are described in the special-purpose public chunks
+documents at <http://www.libpng.org/pub/png/documents/>.
+
+Other information
+about PNG, and the latest version of libpng, can be found at the PNG home
+page, <http://www.libpng.org/pub/png/>.
+
+Most users will not have to modify the library significantly; advanced
+users may want to modify it more. All attempts were made to make it as
+complete as possible, while keeping the code easy to understand.
+Currently, this library only supports C. Support for other languages
+is being considered.
+
+Libpng has been designed to handle multiple sessions at one time,
+to be easily modifiable, to be portable to the vast majority of
+machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
+to use. The ultimate goal of libpng is to promote the acceptance of
+the PNG file format in whatever way possible. While there is still
+work to be done (see the TODO file), libpng should cover the
+majority of the needs of its users.
+
+Libpng uses zlib for its compression and decompression of PNG files.
+Further information about zlib, and the latest version of zlib, can
+be found at the zlib home page, <http://www.info-zip.org/pub/infozip/zlib/>.
+The zlib compression utility is a general purpose utility that is
+useful for more than PNG files, and can be used without libpng.
+See the documentation delivered with zlib for more details.
+You can usually find the source files for the zlib utility wherever you
+find the libpng source files.
+
+Libpng is thread safe, provided the threads are using different
+instances of the structures. Each thread should have its own
+png_struct and png_info instances, and thus its own image.
+Libpng does not protect itself against two threads using the
+same instance of a structure.
+
+II. Structures
+
+There are two main structures that are important to libpng, png_struct
+and png_info. The first, png_struct, is an internal structure that
+will not, for the most part, be used by a user except as the first
+variable passed to every libpng function call.
+
+The png_info structure is designed to provide information about the
+PNG file. At one time, the fields of png_info were intended to be
+directly accessible to the user. However, this tended to cause problems
+with applications using dynamically loaded libraries, and as a result
+a set of interface functions for png_info (the png_get_*() and png_set_*()
+functions) was developed. The fields of png_info are still available for
+older applications, but it is suggested that applications use the new
+interfaces if at all possible.
+
+Applications that do make direct access to the members of png_struct (except
+for png_ptr->jmpbuf) must be recompiled whenever the library is updated,
+and applications that make direct access to the members of png_info must
+be recompiled if they were compiled or loaded with libpng version 1.0.6,
+in which the members were in a different order. In version 1.0.7, the
+members of the png_info structure reverted to the old order, as they were
+in versions 0.97c through 1.0.5. Starting with version 2.0.0, both
+structures are going to be hidden, and the contents of the structures will
+only be accessible through the png_get/png_set functions.
+
+The png.h header file is an invaluable reference for programming with libpng.
+And while I'm on the topic, make sure you include the libpng header file:
+
+#include <png.h>
+
+III. Reading
+
+We'll now walk you through the possible functions to call when reading
+in a PNG file sequentially, briefly explaining the syntax and purpose
+of each one. See example.c and png.h for more detail. While
+progressive reading is covered in the next section, you will still
+need some of the functions discussed in this section to read a PNG
+file.
+
+Setup
+
+You will want to do the I/O initialization(*) before you get into libpng,
+so if it doesn't work, you don't have much to undo. Of course, you
+will also want to insure that you are, in fact, dealing with a PNG
+file. Libpng provides a simple check to see if a file is a PNG file.
+To use it, pass in the first 1 to 8 bytes of the file to the function
+png_sig_cmp(), and it will return 0 (false) if the bytes match the
+corresponding bytes of the PNG signature, or nonzero (true) otherwise.
+Of course, the more bytes you pass in, the greater the accuracy of the
+prediction.
+
+If you are intending to keep the file pointer open for use in libpng,
+you must ensure you don't read more than 8 bytes from the beginning
+of the file, and you also have to make a call to png_set_sig_bytes_read()
+with the number of bytes you read from the beginning. Libpng will
+then only check the bytes (if any) that your program didn't read.
+
+(*): If you are not using the standard I/O functions, you will need
+to replace them with custom functions. See the discussion under
+Customizing libpng.
+
+
+ FILE *fp = fopen(file_name, "rb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+ fread(header, 1, number, fp);
+ is_png = !png_sig_cmp(header, 0, number);
+ if (!is_png)
+ {
+ return (NOT_PNG);
+ }
+
+
+Next, png_struct and png_info need to be allocated and initialized. In
+order to ensure that the size of these structures is correct even with a
+dynamically linked libpng, there are functions to initialize and
+allocate the structures. We also pass the library version, optional
+pointers to error handling functions, and a pointer to a data struct for
+use by the error functions, if necessary (the pointer and functions can
+be NULL if the default error handlers are to be used). See the section
+on Changes to Libpng below regarding the old initialization functions.
+The structure allocation functions quietly return NULL if they fail to
+create the structure, so your application should check for that.
+
+ png_structp png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr,
+ (png_infopp)NULL, (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ png_infop end_info = png_create_info_struct(png_ptr);
+ if (!end_info)
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_read_struct_2() instead of png_create_read_struct():
+
+ png_structp png_ptr = png_create_read_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+The error handling routines passed to png_create_read_struct()
+and the memory alloc/free routines passed to png_create_struct_2()
+are only necessary if you are not using the libpng supplied error
+handling and memory alloc/free functions.
+
+When libpng encounters an error, it expects to longjmp back
+to your routine. Therefore, you will need to call setjmp and pass
+your png_jmpbuf(png_ptr). If you read the file from different
+routines, you will need to update the jmpbuf field every time you enter
+a new routine that will call a png_*() function.
+
+See your documentation of setjmp/longjmp for your compiler for more
+information on setjmp/longjmp. See the discussion on libpng error
+handling in the Customizing Libpng section below for more information
+on the libpng error handling. If an error occurs, and libpng longjmp's
+back to your setjmp, you will want to call png_destroy_read_struct() to
+free any memory.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+ fclose(fp);
+ return (ERROR);
+ }
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the input code. The default for libpng is to
+use the C function fread(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. If you wish to handle reading data in another
+way, you need not call the png_init_io() function, but you must then
+implement the libpng I/O methods discussed in the Customizing Libpng
+section below.
+
+ png_init_io(png_ptr, fp);
+
+If you had previously opened the file and read any of the signature from
+the beginning in order to see if this was a PNG file, you need to let
+libpng know that there are some bytes missing from the start of the file.
+
+ png_set_sig_bytes(png_ptr, number);
+
+Setting up callback code
+
+You can set up a callback function to handle any unknown chunks in the
+input stream. You must supply the function
+
+ read_chunk_callback(png_ptr ptr,
+ png_unknown_chunkp chunk);
+ {
+ /* The unknown chunk structure contains your
+ chunk data, along with similar data for any other
+ unknown chunks: */
+
+ png_byte name[5];
+ png_byte *data;
+ png_size_t size;
+
+ /* Note that libpng has already taken care of
+ the CRC handling */
+
+ /* put your code here. Search for your chunk in the
+ unknown chunk structure, process it, and return one
+ of the following: */
+
+ return (-n); /* chunk had an error */
+ return (0); /* did not recognize */
+ return (n); /* success */
+ }
+
+(You can give your function another name that you like instead of
+"read_chunk_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr,
+ read_chunk_callback);
+
+This names not only the callback function, but also a user pointer that
+you can retrieve with
+
+ png_get_user_chunk_ptr(png_ptr);
+
+If you call the png_set_read_user_chunk_fn() function, then all unknown
+chunks will be saved when read, in case your callback function will need
+one or more of them. This behavior can be changed with the
+png_set_keep_unknown_chunks() function, described below.
+
+At this point, you can set up a callback function that will be
+called after each row has been read, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void read_row_callback(png_ptr ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "read_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_read_status_fn(png_ptr, read_row_callback);
+
+Unknown-chunk handling
+
+Now you get to set the way the library processes unknown chunks in the
+input PNG stream. Both known and unknown chunks will be read. Normal
+behavior is that known chunks will be parsed into information in
+various info_ptr members while unknown chunks will be discarded. This
+behavior can be wasteful if your application will never use some known
+chunk types. To change this, you can call:
+
+ png_set_keep_unknown_chunks(png_ptr, keep,
+ chunk_list, num_chunks);
+ keep - 0: default unknown chunk handling
+ 1: ignore; do not keep
+ 2: keep only if safe-to-copy
+ 3: keep even if unsafe-to-copy
+ You can use these definitions:
+ PNG_HANDLE_CHUNK_AS_DEFAULT 0
+ PNG_HANDLE_CHUNK_NEVER 1
+ PNG_HANDLE_CHUNK_IF_SAFE 2
+ PNG_HANDLE_CHUNK_ALWAYS 3
+ chunk_list - list of chunks affected (a byte string,
+ five bytes per chunk, NULL or '\0' if
+ num_chunks is 0)
+ num_chunks - number of chunks affected; if 0, all
+ unknown chunks are affected. If nonzero,
+ only the chunks in the list are affected
+
+Unknown chunks declared in this way will be saved as raw data onto a
+list of png_unknown_chunk structures. If a chunk that is normally
+known to libpng is named in the list, it will be handled as unknown,
+according to the "keep" directive. If a chunk is named in successive
+instances of png_set_keep_unknown_chunks(), the final instance will
+take precedence. The IHDR and IEND chunks should not be named in
+chunk_list; if they are, libpng will process them normally anyway.
+
+Here is an example of the usage of png_set_keep_unknown_chunks(),
+where the private "vpAg" chunk will later be processed by a user chunk
+callback function:
+
+ png_byte vpAg[5]={118, 112, 65, 103, (png_byte) '\0'};
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ png_byte unused_chunks[]=
+ {
+ 104, 73, 83, 84, (png_byte) '\0', /* hIST */
+ 105, 84, 88, 116, (png_byte) '\0', /* iTXt */
+ 112, 67, 65, 76, (png_byte) '\0', /* pCAL */
+ 115, 67, 65, 76, (png_byte) '\0', /* sCAL */
+ 115, 80, 76, 84, (png_byte) '\0', /* sPLT */
+ 116, 73, 77, 69, (png_byte) '\0', /* tIME */
+ };
+ #endif
+
+ ...
+
+ #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
+ /* ignore all unknown chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+ /* except for vpAg: */
+ png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
+ /* also ignore unused known chunks: */
+ png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
+ (int)sizeof(unused_chunks)/5);
+ #endif
+
+User limits
+
+The PNG specification allows the width and height of an image to be as
+large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.
+Since very few applications really need to process such large images,
+we have imposed an arbitrary 1-million limit on rows and columns.
+Larger images will be rejected immediately with a png_error() call. If
+you wish to override this limit, you can use
+
+ png_set_user_limits(png_ptr, width_max, height_max);
+
+to set your own limits, or use width_max = height_max = 0x7fffffffL
+to allow all valid dimensions (libpng may reject some very large images
+anyway because of potential buffer overflow conditions).
+
+You should put this statement after you create the PNG structure and
+before calling png_read_info(), png_read_png(), or png_process_data().
+If you need to retrieve the limits that are being applied, use
+
+ width_max = png_get_user_width_max(png_ptr);
+ height_max = png_get_user_height_max(png_ptr);
+
+The high-level read interface
+
+At this point there are two ways to proceed; through the high-level
+read interface, or through a sequence of low-level read operations.
+You can use the high-level interface if (a) you are willing to read
+the entire image into memory, and (b) the input transformations
+you want to do are limited to the following set:
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to
+ 8 bits
+ PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel
+ PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit
+ samples to bytes
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_EXPAND Perform set_expand()
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+
+(This excludes setting a background color, doing gamma transformation,
+dithering, and setting filler.) If this is the case, simply do this:
+
+ png_read_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of
+some set of transformation flags. This call is equivalent to png_read_info(),
+followed the set of transformations indicated by the transform mask,
+then png_read_image(), and finally png_read_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future input transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_read_png().
+
+After you have called png_read_png(), you can retrieve the image data
+with
+
+ row_pointers = png_get_rows(png_ptr, info_ptr);
+
+where row_pointers is an array of pointers to the pixel data for each row:
+
+ png_bytep row_pointers[height];
+
+If you know your image size and pixel size ahead of time, you can allocate
+row_pointers prior to calling png_read_png() with
+
+ if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+ png_error (png_ptr,
+ "Image is too tall to process in memory");
+ if (width > PNG_UINT_32_MAX/pixel_size)
+ png_error (png_ptr,
+ "Image is too wide to process in memory");
+ row_pointers = png_malloc(png_ptr,
+ height*png_sizeof(png_bytep));
+ for (int i=0; i<height, i++)
+ row_pointers[i]=NULL; /* security precaution */
+ for (int i=0; i<height, i++)
+ row_pointers[i]=png_malloc(png_ptr,
+ width*pixel_size);
+ png_set_rows(png_ptr, info_ptr, &row_pointers);
+
+Alternatively you could allocate your image in one big block and define
+row_pointers[i] to point into the proper places in your block.
+
+If you use png_set_rows(), the application is responsible for freeing
+row_pointers (and row_pointers[i], if they were separately allocated).
+
+If you don't allocate row_pointers ahead of time, png_read_png() will
+do it, and it'll be free'ed when you call png_destroy_*().
+
+The low-level read interface
+
+If you are going the low-level route, you are now ready to read all
+the file information up to the actual image data. You do this with a
+call to png_read_info().
+
+ png_read_info(png_ptr, info_ptr);
+
+This will process all chunks up to but not including the image data.
+
+Querying the info structure
+
+Functions are used to get the information from the info_ptr once it
+has been read. Note that these fields may not be completely filled
+in until png_read_end() has read the chunk data following the image.
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height,
+ &bit_depth, &color_type, &interlace_type,
+ &compression_type, &filter_method);
+
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels. (valid values are
+ 1, 2, 4, 8, 16 and depend also on
+ the color_type. See also
+ significant bits (sBIT) below).
+ color_type - describes which color/alpha channels
+ are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ filter_method - (must be PNG_FILTER_TYPE_BASE
+ for PNG 1.0, and can also be
+ PNG_INTRAPIXEL_DIFFERENCING if
+ the PNG datastream is embedded in
+ a MNG-1.0 datastream)
+ compression_type - (must be PNG_COMPRESSION_TYPE_BASE
+ for PNG 1.0)
+ interlace_type - (PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7)
+ Any or all of interlace_type, compression_type, of
+ filter_method can be NULL if you are
+ not interested in their values.
+
+ channels = png_get_channels(png_ptr, info_ptr);
+ channels - number of channels of info for the
+ color type (valid values are 1 (GRAY,
+ PALETTE), 2 (GRAY_ALPHA), 3 (RGB),
+ 4 (RGB_ALPHA or RGB + filler byte))
+ rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+ rowbytes - number of bytes needed to hold a row
+
+ signature = png_get_signature(png_ptr, info_ptr);
+ signature - holds the signature read from the
+ file (if any). The data is kept in
+ the same offset it would be if the
+ whole signature were read (i.e. if an
+ application had already read in 4
+ bytes of signature before starting
+ libpng, the remaining 4 bytes would
+ be in signature[4] through signature[7]
+ (see png_set_sig_bytes())).
+
+
+ width = png_get_image_width(png_ptr,
+ info_ptr);
+ height = png_get_image_height(png_ptr,
+ info_ptr);
+ bit_depth = png_get_bit_depth(png_ptr,
+ info_ptr);
+ color_type = png_get_color_type(png_ptr,
+ info_ptr);
+ filter_method = png_get_filter_type(png_ptr,
+ info_ptr);
+ compression_type = png_get_compression_type(png_ptr,
+ info_ptr);
+ interlace_type = png_get_interlace_type(png_ptr,
+ info_ptr);
+
+
+These are also important, but their validity depends on whether the chunk
+has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
+png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
+data has been read, or zero if it is missing. The parameters to the
+png_get_<chunk> are set directly if they are simple data types, or a pointer
+into the info_ptr is returned for any complex types.
+
+ png_get_PLTE(png_ptr, info_ptr, &palette,
+ &num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_get_gAMA(png_ptr, info_ptr, &gamma);
+ gamma - the gamma the file is written
+ at (PNG_INFO_gAMA)
+
+ png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
+ srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ The presence of the sRGB chunk
+ means that the pixel data is in the
+ sRGB color space. This chunk also
+ implies specific values of gAMA and
+ cHRM.
+
+ png_get_iCCP(png_ptr, info_ptr, &name,
+ &compression_type, &profile, &proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray,
+ red, green, and blue channels,
+ whichever are appropriate for the
+ given color type (png_color_16)
+
+ png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans,
+ &trans_values);
+ trans - array of transparent entries for
+ palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values of
+ the single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_get_hIST(png_ptr, info_ptr, &hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_get_tIME(png_ptr, info_ptr, &mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_get_bKGD(png_ptr, info_ptr, &background);
+ background - background color (PNG_VALID_bKGD)
+ valid 16-bit red, green and blue
+ values, regardless of color_type
+
+ num_comments = png_get_text(png_ptr, info_ptr,
+ &text_ptr, &num_text);
+ num_comments - number of comments
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (empty
+ string for unknown).
+ text_ptr[i].lang_key - keyword in UTF-8
+ (empty string for unknown).
+ num_text - number of comments (same as
+ num_comments; you can put NULL here
+ to avoid the duplication)
+ Note while png_set_text() will accept text, language,
+ and translated keywords that can be NULL pointers, the
+ structure returned by png_get_text will always contain
+ regular zero-terminated C strings. They might be
+ empty strings but they will never be NULL pointers.
+
+ num_spalettes = png_get_sPLT(png_ptr, info_ptr,
+ &palette_ptr);
+ palette_ptr - array of palette structures holding
+ contents of one or more sPLT chunks
+ read.
+ num_spalettes - number of sPLT chunks read.
+
+ png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y,
+ &unit_type);
+ offset_x - positive offset from the left edge
+ of the screen
+ offset_y - positive offset from the top edge
+ of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y,
+ &unit_type);
+ res_x - pixels/unit physical resolution in
+ x direction
+ res_y - pixels/unit physical resolution in
+ x direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_get_sCAL(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_get_sCAL_s(png_ptr, info_ptr, &unit, &width,
+ &height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ num_unknown_chunks = png_get_unknown_chunks(png_ptr,
+ info_ptr, &unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position of chunk in file
+
+ The value of "i" corresponds to the order in which the
+ chunks were read from the PNG file or inserted with the
+ png_set_unknown_chunks() function.
+
+The data from the pHYs chunk can be retrieved in several convenient
+forms:
+
+ res_x = png_get_x_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_meter(png_ptr,
+ info_ptr)
+ res_x = png_get_x_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_y = png_get_y_pixels_per_inch(png_ptr,
+ info_ptr)
+ res_x_and_y = png_get_pixels_per_inch(png_ptr,
+ info_ptr)
+ aspect_ratio = png_get_pixel_aspect_ratio(png_ptr,
+ info_ptr)
+
+ (Each of these returns 0 [signifying "unknown"] if
+ the data is not present or if res_x is 0;
+ res_x_and_y is 0 if res_x != res_y)
+
+The data from the oFFs chunk can be retrieved in several convenient
+forms:
+
+ x_offset = png_get_x_offset_microns(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_microns(png_ptr, info_ptr);
+ x_offset = png_get_x_offset_inches(png_ptr, info_ptr);
+ y_offset = png_get_y_offset_inches(png_ptr, info_ptr);
+
+ (Each of these returns 0 [signifying "unknown" if both
+ x and y are 0] if the data is not present or if the
+ chunk is present but the unit is the pixel)
+
+For more information, see the png_info definition in png.h and the
+PNG specification for chunk contents. Be careful with trusting
+rowbytes, as some of the transformations could increase the space
+needed to hold a row (expand, filler, gray_to_rgb, etc.).
+See png_read_update_info(), below.
+
+A quick word about text_ptr and num_text. PNG stores comments in
+keyword/text pairs, one pair per chunk, with no limit on the number
+of text chunks, and a 2^31 byte limit on their size. While there are
+suggested keywords, there is no requirement to restrict the use to these
+strings. It is strongly suggested that keywords and text be sensible
+to humans (that's the point), so don't use abbreviations. Non-printing
+symbols are not allowed. See the PNG specification for more details.
+There is also no requirement to have text after the keyword.
+
+Keywords should be limited to 79 Latin-1 characters without leading or
+trailing spaces, but non-consecutive spaces are allowed within the
+keyword. It is possible to have the same keyword any number of times.
+The text_ptr is an array of png_text structures, each holding a
+pointer to a language string, a pointer to a keyword and a pointer to
+a text string. The text string, language code, and translated
+keyword may be empty or NULL pointers. The keyword/text
+pairs are put into the array in the order that they are received.
+However, some or all of the text chunks may be after the image, so, to
+make sure you have read all the text chunks, don't mess with these
+until after you read the stuff after the image. This will be
+mentioned again below in the discussion that goes with png_read_end().
+
+Input transformations
+
+After you've read the header information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+The colors used for the background and transparency values should be
+supplied in the same format/depth as the current image data. They
+are stored in the same format/depth as the image data in a bKGD or tRNS
+chunk, so this is what libpng expects for this data. The colors are
+transformed to keep in sync with the image data when an application
+calls the png_read_update_info() routine (see below).
+
+Data will be decoded into the supplied row buffers packed into bytes
+unless the library has been told to transform it into another format.
+For example, 4 bit/pixel paletted or grayscale data will be returned
+2 pixels/byte with the leftmost pixel in the high-order bits of the
+byte, unless png_set_packing() is called. 8-bit RGB data will be stored
+in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha()
+is called to insert filler bytes, either before or after each RGB triplet.
+16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant
+byte of the color value first, unless png_set_strip_16() is called to
+transform it to regular RGB RGB triplets, or png_set_filler() or
+png_set_add alpha() is called to insert filler bytes, either before or
+after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can
+be modified with
+png_set_filler(), png_set_add_alpha(), or png_set_strip_16().
+
+The following code transforms grayscale images of less than 8 to 8 bits,
+changes paletted images to RGB, and adds a full alpha channel if there is
+transparency information in a tRNS chunk. This is most useful on
+grayscale images with bit depths of 2 or 4 or if there is a multiple-image
+viewing application that wishes to treat all images in the same way.
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png_ptr);
+
+ if (color_type == PNG_COLOR_TYPE_GRAY &&
+ bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
+
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
+
+These three functions are actually aliases for png_set_expand(), added
+in libpng version 1.0.4, with the function names expanded to improve code
+readability. In some future version they may actually do different
+things.
+
+As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was
+added. It expands the sample depth without changing tRNS to alpha.
+
+PNG can have files with 16 bits per channel. If you only can handle
+8 bits per channel, this will strip the pixels down to 8 bit.
+
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+If, for some reason, you don't need the alpha channel on an image,
+and you want to remove it rather than combining it with the background
+(but the image author certainly had in mind that you *would* combine
+it with the background, so that's what you should probably do):
+
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ png_set_strip_alpha(png_ptr);
+
+In PNG files, the alpha channel in an image
+is the level of opacity. If you need the alpha channel in an image to
+be the level of transparency instead of opacity, you can invert the
+alpha channel (or the tRNS chunk data) after it's read, so that 0 is
+fully opaque and 255 (in 8-bit or paletted images) or 65535 (in 16-bit
+images) is fully transparent, with
+
+ png_set_invert_alpha(png_ptr);
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit
+files. This code expands to 1 pixel per byte without changing the
+values of the pixels:
+
+ if (bit_depth < 8)
+ png_set_packing(png_ptr);
+
+PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels
+stored in a PNG image have been "scaled" or "shifted" up to the next
+higher possible bit depth (e.g. from 5 bits/sample in the range [0,31] to
+8 bits/sample in the range [0, 255]). However, it is also possible to
+convert the PNG pixel data back to the original bit depth of the image.
+This call reduces the pixels back down to the original bit depth:
+
+ png_color_8p sig_bit;
+
+ if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
+ png_set_shift(png_ptr, sig_bit);
+
+PNG files store 3-color pixels in red, green, blue order. This code
+changes the storage of the pixels to blue, green, red:
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_bgr(png_ptr);
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code expands them
+into 4 or 8 bytes for windowing systems that need them in this format:
+
+ if (color_type == PNG_COLOR_TYPE_RGB)
+ png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
+
+where "filler" is the 8 or 16-bit number to fill with, and the location is
+either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
+you want the filler before the RGB or after. This transformation
+does not affect images that already have full alpha channels. To add an
+opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which
+will generate RGBA pixels.
+
+Note that png_set_filler() does not change the color type. If you want
+to do that, you can add a true alpha channel with
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER);
+
+where "filler" contains the alpha value to assign to each pixel.
+This function was added in libpng-1.2.7.
+
+If you are reading an image with an alpha channel, and you need the
+data as ARGB instead of the normal PNG format RGBA:
+
+ if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_swap_alpha(png_ptr);
+
+For some uses, you may want a grayscale image to be represented as
+RGB. This code will do that conversion:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+Conversely, you can convert an RGB or RGBA image to grayscale or grayscale
+with alpha.
+
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_rgb_to_gray_fixed(png_ptr, error_action,
+ int red_weight, int green_weight);
+
+ error_action = 1: silently do the conversion
+ error_action = 2: issue a warning if the original
+ image has any pixel where
+ red != green or red != blue
+ error_action = 3: issue an error and abort the
+ conversion if the original
+ image has any pixel where
+ red != green or red != blue
+
+ red_weight: weight of red component times 100000
+ green_weight: weight of green component times 100000
+ If either weight is negative, default
+ weights (21268, 71514) are used.
+
+If you have set error_action = 1 or 2, you can
+later check whether the image really was gray, after processing
+the image rows, with the png_get_rgb_to_gray_status(png_ptr) function.
+It will return a png_byte that is zero if the image was gray or
+1 if there were any non-gray pixels. bKGD and sBIT data
+will be silently converted to grayscale, using the green channel
+data, regardless of the error_action setting.
+
+With red_weight+green_weight<=100000,
+the normalized graylevel is computed:
+
+ int rw = red_weight * 65536;
+ int gw = green_weight * 65536;
+ int bw = 65536 - (rw + gw);
+ gray = (rw*red + gw*green + bw*blue)/65536;
+
+The default values approximate those recommended in the Charles
+Poynton's Color FAQ, <http://www.inforamp.net/~poynton/>
+Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net>
+
+ Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+
+Libpng approximates this with
+
+ Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
+
+which can be expressed with integers as
+
+ Y = (6969 * R + 23434 * G + 2365 * B)/32768
+
+The calculation is done in a linear colorspace, if the image gamma
+is known.
+
+If you have a grayscale and you are using png_set_expand_depth(),
+png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to
+a higher bit-depth, you must either supply the background color as a gray
+value at the original file bit-depth (need_expand = 1) or else supply the
+background color as an RGB triplet at the final, expanded bit depth
+(need_expand = 0). Similarly, if you are reading a paletted image, you
+must either supply the background color as a palette index (need_expand = 1)
+or as an RGB triplet that may or may not be in the palette (need_expand = 0).
+
+ png_color_16 my_background;
+ png_color_16p image_background;
+
+ if (png_get_bKGD(png_ptr, info_ptr, &image_background))
+ png_set_background(png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ png_set_background(png_ptr, &my_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+
+The png_set_background() function tells libpng to composite images
+with alpha or simple transparency against the supplied background
+color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
+you may use this color, or supply another color more suitable for
+the current display (e.g., the background color from a web page). You
+need to tell libpng whether the color is in the gamma space of the
+display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
+(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
+that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
+know why anyone would use this, but it's here).
+
+To properly display PNG images on any kind of system, the application needs
+to know what the display gamma is. Ideally, the user will know this, and
+the application will allow them to set it. One method of allowing the user
+to set the display gamma separately for each system is to check for a
+SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be
+correctly set.
+
+Note that display_gamma is the overall gamma correction required to produce
+pleasing results, which depends on the lighting conditions in the surrounding
+environment. In a dim or brightly lit room, no compensation other than
+the physical gamma exponent of the monitor is needed, while in a dark room
+a slightly smaller exponent is better.
+
+ double gamma, screen_gamma;
+
+ if (/* We have a user-defined screen
+ gamma value */)
+ {
+ screen_gamma = user_defined_screen_gamma;
+ }
+ /* One way that applications can share the same
+ screen gamma value */
+ else if ((gamma_str = getenv("SCREEN_GAMMA"))
+ != NULL)
+ {
+ screen_gamma = (double)atof(gamma_str);
+ }
+ /* If we don't have another value */
+ else
+ {
+ screen_gamma = 2.2; /* A good guess for a
+ PC monitor in a bright office or a dim room */
+ screen_gamma = 2.0; /* A good guess for a
+ PC monitor in a dark room */
+ screen_gamma = 1.7 or 1.0; /* A good
+ guess for Mac systems */
+ }
+
+The png_set_gamma() function handles gamma transformations of the data.
+Pass both the file gamma and the current screen_gamma. If the file does
+not have a gamma value, you can pass one anyway if you have an idea what
+it is (usually 0.45455 is a good guess for GIF images on PCs). Note
+that file gammas are inverted from screen gammas. See the discussions
+on gamma in the PNG specification for an excellent description of what
+gamma is, and why all applications should support it. It is strongly
+recommended that PNG viewers support gamma correction.
+
+ if (png_get_gAMA(png_ptr, info_ptr, &gamma))
+ png_set_gamma(png_ptr, screen_gamma, gamma);
+ else
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+
+If you need to reduce an RGB file to a paletted file, or if a paletted
+file has more entries then will fit on your screen, png_set_dither()
+will do that. Note that this is a simple match dither that merely
+finds the closest color available. This should work fairly well with
+optimized palettes, and fairly badly with linear color cubes. If you
+pass a palette that is larger then maximum_colors, the file will
+reduce the number of colors in the palette so it will fit into
+maximum_colors. If there is a histogram, it will use it to make
+more intelligent choices when reducing the palette. If there is no
+histogram, it may not do as good a job.
+
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ if (png_get_valid(png_ptr, info_ptr,
+ PNG_INFO_PLTE))
+ {
+ png_uint_16p histogram = NULL;
+
+ png_get_hIST(png_ptr, info_ptr,
+ &histogram);
+ png_set_dither(png_ptr, palette, num_palette,
+ max_screen_colors, histogram, 1);
+ }
+ else
+ {
+ png_color std_color_cube[MAX_SCREEN_COLORS] =
+ { ... colors ... };
+
+ png_set_dither(png_ptr, std_color_cube,
+ MAX_SCREEN_COLORS, MAX_SCREEN_COLORS,
+ NULL,0);
+ }
+ }
+
+PNG files describe monochrome as black being zero and white being one.
+The following code will reverse this (make black be one and white be
+zero):
+
+ if (bit_depth == 1 && color_type == PNG_COLOR_TYPE_GRAY)
+ png_set_invert_mono(png_ptr);
+
+This function can also be used to invert grayscale and gray-alpha images:
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_invert_mono(png_ptr);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code changes the storage to the
+other way (little-endian, i.e. least significant bits first, the
+way PCs store them):
+
+ if (bit_depth == 16)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_read_user_transform_fn(png_ptr,
+ read_transform_fn);
+
+You must supply the function
+
+ void read_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+after all of the other transformations have been processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function, and you can inform libpng that your transform
+function will change the number of channels or bit depth with the
+function
+
+ png_set_user_transform_info(png_ptr, user_ptr,
+ user_depth, user_channels);
+
+The user's application, not libpng, is responsible for allocating and
+freeing any memory required for the user structure.
+
+You can retrieve the pointer via the function
+png_get_user_transform_ptr(). For example:
+
+ voidp read_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+The last thing to handle is interlacing; this is covered in detail below,
+but you must call the function here if you want libpng to handle expansion
+of the interlaced image.
+
+ number_of_passes = png_set_interlace_handling(png_ptr);
+
+After setting the transformations, libpng can update your png_info
+structure to reflect any transformations you've requested with this
+call. This is most useful to update the info structure's rowbytes
+field so you can use it to allocate your image memory. This function
+will also update your palette with the correct screen_gamma and
+background if these have been given with the calls above.
+
+ png_read_update_info(png_ptr, info_ptr);
+
+After you call png_read_update_info(), you can allocate any
+memory you need to hold the image. The row data is simply
+raw byte data for all forms of images. As the actual allocation
+varies among applications, no example will be given. If you
+are allocating one large chunk, you will need to build an
+array of pointers to each row, as it will be needed for some
+of the functions below.
+
+Reading image data
+
+After you've allocated memory, you can read the image data.
+The simplest way to do this is in one function call. If you are
+allocating enough memory to hold the whole image, you can just
+call png_read_image() and libpng will read in all the image data
+and put it in the memory area supplied. You will need to pass in
+an array of pointers to each row.
+
+This function automatically handles interlacing, so you don't need
+to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_read_rows().
+
+ png_read_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_bytep row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to read in the whole image at once, you can
+use png_read_rows() instead. If there is no interlacing (check
+interlace_type == PNG_INTERLACE_NONE), this is simple:
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+where row_pointers is the same as in the png_read_image() call.
+
+If you are doing this just one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+ png_read_row(png_ptr, row_pointer, NULL);
+
+If the file is interlaced (interlace_type != 0 in the IHDR chunk), things
+get somewhat harder. The only current (PNG Specification version 1.2)
+interlacing type for PNG is (interlace_type == PNG_INTERLACE_ADAM7)
+is a somewhat complicated 2D interlace scheme, known as Adam7, that
+breaks down an image into seven smaller images of varying size, based
+on an 8x8 grid.
+
+libpng can fill out those images or it can give them to you "as is".
+If you want them filled out, there are two ways to do that. The one
+mentioned in the PNG specification is to expand each pixel to cover
+those pixels that have not been read yet (the "rectangle" method).
+This results in a blocky image for the first pass, which gradually
+smooths out as more pixels are read. The other method is the "sparkle"
+method, where pixels are drawn only in their final locations, with the
+rest of the image remaining whatever colors they were initialized to
+before the start of the read. The first method usually looks better,
+but tends to be slower, as there are more pixels to put in the rows.
+
+If you don't want libpng to handle the interlacing details, just call
+png_read_rows() seven times to read in all seven images. Each of the
+images is a valid image by itself, or they can all be combined on an
+8x8 grid to form a single image (although if you intend to combine them
+you would be far better off using the libpng interlace handling).
+
+The first pass will return an image 1/8 as wide as the entire image
+(every 8th column starting in column 0) and 1/8 as high as the original
+(every 8th row starting in row 0), the second will be 1/8 as wide
+(starting in column 4) and 1/8 as high (also starting in row 0). The
+third pass will be 1/4 as wide (every 4th pixel starting in column 0) and
+1/8 as high (every 8th row starting in row 4), and the fourth pass will
+be 1/4 as wide and 1/4 as high (every 4th column starting in column 2,
+and every 4th row starting in row 0). The fifth pass will return an
+image 1/2 as wide, and 1/4 as high (starting at column 0 and row 2),
+while the sixth pass will be 1/2 as wide and 1/2 as high as the original
+(starting in column 1 and row 0). The seventh and final pass will be as
+wide as the original, and 1/2 as high, containing all of the odd
+numbered scanlines. Phew!
+
+If you want libpng to expand the images, call this before calling
+png_start_read_image() or png_read_update_info():
+
+ if (interlace_type == PNG_INTERLACE_ADAM7)
+ number_of_passes
+ = png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this
+is seven, but may change if another interlace type is added.
+This function can be called even if the file is not interlaced,
+where it will return one pass.
+
+If you are not going to display the image after each pass, but are
+going to wait until the entire image is read in, use the sparkle
+effect. This effect is faster and the end result of either method
+is exactly the same. If you are planning on displaying the image
+after each pass, the "rectangle" effect is generally considered the
+better looking one.
+
+If you only want the "sparkle" effect, just call png_read_rows() as
+normal, with the third parameter NULL. Make sure you make pass over
+the image number_of_passes times, and you don't change the data in the
+rows between calls. You can change the locations of the data, just
+not the data. Each pass only writes the pixels appropriate for that
+pass, and assumes the data from previous passes is still valid.
+
+ png_read_rows(png_ptr, row_pointers, NULL,
+ number_of_rows);
+
+If you only want the first effect (the rectangles), do the same as
+before except pass the row buffer in the third parameter, and leave
+the second parameter NULL.
+
+ png_read_rows(png_ptr, NULL, row_pointers,
+ number_of_rows);
+
+Finishing a sequential read
+
+After you are finished reading the image through the
+low-level interface, you can finish reading the file. If you are
+interested in comments or time, which may be stored either before or
+after the image data, you should pass the separate png_info struct if
+you want to keep the comments from before and after the image
+separate. If you are not interested, you can pass NULL.
+
+ png_read_end(png_ptr, end_info);
+
+When you are done, you can free all memory allocated by libpng like this:
+
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ &end_info);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those
+cases do nothing. The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed. If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+This function only affects data that has already been allocated.
+You can call this function after reading the PNG data but before calling
+any png_set_*() functions, to control whether the user or the png_set_*()
+function is responsible for freeing any existing data that might be present,
+and again after the png_set_*() functions to control whether the user
+or png_destroy_*() is supposed to free the data. When the user assumes
+responsibility for libpng-allocated data, the application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated your row_pointers in a single block, as suggested above in
+the description of the high level read interface, you must not transfer
+responsibility for freeing it to the png_set_rows or png_read_destroy function,
+because they would also try to free the individual row_pointers[i].
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+
+The png_free_data() function will turn off the "valid" flag for anything
+it frees. If you need to turn the flag off for a chunk that was freed by your
+application instead of by libpng, you can use
+
+ png_set_invalid(png_ptr, info_ptr, mask);
+ mask - identifies the chunks to be made invalid,
+ containing the bitwise OR of one or
+ more of
+ PNG_INFO_gAMA, PNG_INFO_sBIT,
+ PNG_INFO_cHRM, PNG_INFO_PLTE,
+ PNG_INFO_tRNS, PNG_INFO_bKGD,
+ PNG_INFO_hIST, PNG_INFO_pHYs,
+ PNG_INFO_oFFs, PNG_INFO_tIME,
+ PNG_INFO_pCAL, PNG_INFO_sRGB,
+ PNG_INFO_iCCP, PNG_INFO_sPLT,
+ PNG_INFO_sCAL, PNG_INFO_IDAT
+
+For a more compact example of reading a PNG image, see the file example.c.
+
+Reading PNG files progressively
+
+The progressive reader is slightly different then the non-progressive
+reader. Instead of calling png_read_info(), png_read_rows(), and
+png_read_end(), you make one call to png_process_data(), which calls
+callbacks when it has the info, a row, or the end of the image. You
+set up these callbacks with png_set_progressive_read_fn(). You don't
+have to worry about the input/output functions of libpng, as you are
+giving the library the data directly in png_process_data(). I will
+assume that you have read the section on reading PNG files above,
+so I will only highlight the differences (although I will show
+all of the code).
+
+png_structp png_ptr;
+png_infop info_ptr;
+
+ /* An example code fragment of how you would
+ initialize the progressive reader in your
+ application. */
+ int
+ initialize_png_reader()
+ {
+ png_ptr = png_create_read_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new. You can provide functions
+ to be called when the header info is valid,
+ when each row is completed, and when the image
+ is finished. If you aren't using all functions,
+ you can specify NULL parameters. Even when all
+ three functions are NULL, you need to call
+ png_set_progressive_read_fn(). You can use
+ any struct as the user_ptr (cast to a void pointer
+ for the function call), and retrieve the pointer
+ from inside the callbacks using the function
+
+ png_get_progressive_ptr(png_ptr);
+
+ which will return a void pointer, which you have
+ to cast appropriately.
+ */
+ png_set_progressive_read_fn(png_ptr, (void *)user_ptr,
+ info_callback, row_callback, end_callback);
+
+ return 0;
+ }
+
+ /* A code fragment that you call as you receive blocks
+ of data */
+ int
+ process_data(png_bytep buffer, png_uint_32 length)
+ {
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_read_struct(&png_ptr, &info_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+ /* This one's new also. Simply give it a chunk
+ of data from the file stream (in order, of
+ course). On machines with segmented memory
+ models machines, don't give it any more than
+ 64K. The library seems to run fine with sizes
+ of 4K. Although you can give it much less if
+ necessary (I assume you can give it chunks of
+ 1 byte, I haven't tried less then 256 bytes
+ yet). When this function returns, you may
+ want to display any rows that were generated
+ in the row callback if you don't already do
+ so there.
+ */
+ png_process_data(png_ptr, info_ptr, buffer, length);
+ return 0;
+ }
+
+ /* This function is called (as set by
+ png_set_progressive_read_fn() above) when enough data
+ has been supplied so all of the header has been
+ read.
+ */
+ void
+ info_callback(png_structp png_ptr, png_infop info)
+ {
+ /* Do any setup here, including setting any of
+ the transformations mentioned in the Reading
+ PNG files section. For now, you _must_ call
+ either png_start_read_image() or
+ png_read_update_info() after all the
+ transformations are set (even if you don't set
+ any). You may start getting rows before
+ png_process_data() returns, so this is your
+ last chance to prepare for that.
+ */
+ }
+
+ /* This function is called when each row of image
+ data is complete */
+ void
+ row_callback(png_structp png_ptr, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+ {
+ /* If the image is interlaced, and you turned
+ on the interlace handler, this function will
+ be called for every row in every pass. Some
+ of these rows will not be changed from the
+ previous pass. When the row is not changed,
+ the new_row variable will be NULL. The rows
+ and passes are called in order, so you don't
+ really need the row_num and pass, but I'm
+ supplying them because it may make your life
+ easier.
+
+ For the non-NULL rows of interlaced images,
+ you must call png_progressive_combine_row()
+ passing in the row and the old row. You can
+ call this function for NULL rows (it will just
+ return) and for non-interlaced images (it just
+ does the memcpy for you) if it will make the
+ code easier. Thus, you can just do this for
+ all cases:
+ */
+
+ png_progressive_combine_row(png_ptr, old_row,
+ new_row);
+
+ /* where old_row is what was displayed for
+ previously for the row. Note that the first
+ pass (pass == 0, really) will completely cover
+ the old row, so the rows do not have to be
+ initialized. After the first pass (and only
+ for interlaced images), you will have to pass
+ the current row, and the function will combine
+ the old row and the new row.
+ */
+ }
+
+ void
+ end_callback(png_structp png_ptr, png_infop info)
+ {
+ /* This function is called after the whole image
+ has been read, including any chunks after the
+ image (up to and including the IEND). You
+ will usually have the same info chunk as you
+ had in the header, although some data may have
+ been added to the comments and time fields.
+
+ Most people won't do much here, perhaps setting
+ a flag that marks the image as finished.
+ */
+ }
+
+
+
+IV. Writing
+
+Much of this is very similar to reading. However, everything of
+importance is repeated here, so you won't have to constantly look
+back up in the reading section to understand writing.
+
+Setup
+
+You will want to do the I/O initialization before you get into libpng,
+so if it doesn't work, you don't have anything to undo. If you are not
+using the standard I/O functions, you will need to replace them with
+custom writing functions. See the discussion under Customizing libpng.
+
+ FILE *fp = fopen(file_name, "wb");
+ if (!fp)
+ {
+ return (ERROR);
+ }
+
+Next, png_struct and png_info need to be allocated and initialized.
+As these can be both relatively large, you may not want to store these
+on the stack, unless you have stack space to spare. Of course, you
+will want to check if they return NULL. If you are also reading,
+you won't want to name your read structure and your write structure
+both "png_ptr"; you can call them anything you like, such as
+"read_ptr" and "write_ptr". Look at pngtest.c, for example.
+
+ png_structp png_ptr = png_create_write_struct
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn);
+ if (!png_ptr)
+ return (ERROR);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_write_struct(&png_ptr,
+ (png_infopp)NULL);
+ return (ERROR);
+ }
+
+If you want to use your own memory allocation routines,
+define PNG_USER_MEM_SUPPORTED and use
+png_create_write_struct_2() instead of png_create_write_struct():
+
+ png_structp png_ptr = png_create_write_struct_2
+ (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
+ user_error_fn, user_warning_fn, (png_voidp)
+ user_mem_ptr, user_malloc_fn, user_free_fn);
+
+After you have these structures, you will need to set up the
+error handling. When libpng encounters an error, it expects to
+longjmp() back to your routine. Therefore, you will need to call
+setjmp() and pass the png_jmpbuf(png_ptr). If you
+write the file from different routines, you will need to update
+the png_jmpbuf(png_ptr) every time you enter a new routine that will
+call a png_*() function. See your documentation of setjmp/longjmp
+for your compiler for more information on setjmp/longjmp. See
+the discussion on libpng error handling in the Customizing Libpng
+section below for more information on the libpng error handling.
+
+ if (setjmp(png_jmpbuf(png_ptr)))
+ {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(fp);
+ return (ERROR);
+ }
+ ...
+ return;
+
+If you would rather avoid the complexity of setjmp/longjmp issues,
+you can compile libpng with PNG_SETJMP_NOT_SUPPORTED, in which case
+errors will result in a call to PNG_ABORT() which defaults to abort().
+
+Now you need to set up the output code. The default for libpng is to
+use the C function fwrite(). If you use this, you will need to pass a
+valid FILE * in the function png_init_io(). Be sure that the file is
+opened in binary mode. Again, if you wish to handle writing data in
+another way, see the discussion on libpng I/O handling in the Customizing
+Libpng section below.
+
+ png_init_io(png_ptr, fp);
+
+If you are embedding your PNG into a datastream such as MNG, and don't
+want libpng to write the 8-byte signature, or if you have already
+written the signature in your application, use
+
+ png_set_sig_bytes(png_ptr, 8);
+
+to inform libpng that it should not write a signature.
+
+Write callbacks
+
+At this point, you can set up a callback function that will be
+called after each row has been written, which you can use to control
+a progress meter or the like. It's demonstrated in pngtest.c.
+You must supply a function
+
+ void write_row_callback(png_ptr, png_uint_32 row,
+ int pass);
+ {
+ /* put your code here */
+ }
+
+(You can give it another name that you like instead of "write_row_callback")
+
+To inform libpng about your function, use
+
+ png_set_write_status_fn(png_ptr, write_row_callback);
+
+You now have the option of modifying how the compression library will
+run. The following functions are mainly for testing, but may be useful
+in some cases, like if you need to write PNG files extremely fast and
+are willing to give up some compression, or if you want to get the
+maximum possible compression at the expense of slower writing. If you
+have no special needs in this area, let the library do what it wants by
+not calling this function at all, as it has been tuned to deliver a good
+speed/compression ratio. The second parameter to png_set_filter() is
+the filter method, for which the only valid values are 0 (as of the
+July 1999 PNG specification, version 1.2) or 64 (if you are writing
+a PNG datastream that is to be embedded in a MNG datastream). The third
+parameter is a flag that indicates which filter type(s) are to be tested
+for each scanline. See the PNG specification for details on the specific filter
+types.
+
+
+ /* turn on or off filtering, and/or choose
+ specific filters. You can use either a single
+ PNG_FILTER_VALUE_NAME or the bitwise OR of one
+ or more PNG_FILTER_NAME masks. */
+ png_set_filter(png_ptr, 0,
+ PNG_FILTER_NONE | PNG_FILTER_VALUE_NONE |
+ PNG_FILTER_SUB | PNG_FILTER_VALUE_SUB |
+ PNG_FILTER_UP | PNG_FILTER_VALUE_UP |
+ PNG_FILTER_AVG | PNG_FILTER_VALUE_AVG |
+ PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH|
+ PNG_ALL_FILTERS);
+
+If an application
+wants to start and stop using particular filters during compression,
+it should start out with all of the filters (to ensure that the previous
+row of pixels will be stored in case it's needed later), and then add
+and remove them after the start of compression.
+
+If you are writing a PNG datastream that is to be embedded in a MNG
+datastream, the second parameter can be either 0 or 64.
+
+The png_set_compression_*() functions interface to the zlib compression
+library, and should mostly be ignored unless you really know what you are
+doing. The only generally useful call is png_set_compression_level()
+which changes how much time zlib spends on trying to compress the image
+data. See the Compression Library (zlib.h and algorithm.txt, distributed
+with zlib) for details on the compression levels.
+
+ /* set the zlib compression level */
+ png_set_compression_level(png_ptr,
+ Z_BEST_COMPRESSION);
+
+ /* set other zlib parameters */
+ png_set_compression_mem_level(png_ptr, 8);
+ png_set_compression_strategy(png_ptr,
+ Z_DEFAULT_STRATEGY);
+ png_set_compression_window_bits(png_ptr, 15);
+ png_set_compression_method(png_ptr, 8);
+ png_set_compression_buffer_size(png_ptr, 8192)
+
+extern PNG_EXPORT(void,png_set_zbuf_size)
+
+Setting the contents of info for output
+
+You now need to fill in the png_info structure with all the data you
+wish to write before the actual image. Note that the only thing you
+are allowed to write after the image is the text chunks and the time
+chunk (as of PNG Specification 1.2, anyway). See png_write_end() and
+the latest PNG specification for more information on that. If you
+wish to write them before the image, fill them in now, and flag that
+data as being valid. If you want to wait until after the data, don't
+fill them until png_write_end(). For all the fields in png_info and
+their data types, see png.h. For explanations of what the fields
+contain, see the PNG specification.
+
+Some of the more important parts of the png_info are:
+
+ png_set_IHDR(png_ptr, info_ptr, width, height,
+ bit_depth, color_type, interlace_type,
+ compression_type, filter_method)
+ width - holds the width of the image
+ in pixels (up to 2^31).
+ height - holds the height of the image
+ in pixels (up to 2^31).
+ bit_depth - holds the bit depth of one of the
+ image channels.
+ (valid values are 1, 2, 4, 8, 16
+ and depend also on the
+ color_type. See also significant
+ bits (sBIT) below).
+ color_type - describes which color/alpha
+ channels are present.
+ PNG_COLOR_TYPE_GRAY
+ (bit depths 1, 2, 4, 8, 16)
+ PNG_COLOR_TYPE_GRAY_ALPHA
+ (bit depths 8, 16)
+ PNG_COLOR_TYPE_PALETTE
+ (bit depths 1, 2, 4, 8)
+ PNG_COLOR_TYPE_RGB
+ (bit_depths 8, 16)
+ PNG_COLOR_TYPE_RGB_ALPHA
+ (bit_depths 8, 16)
+
+ PNG_COLOR_MASK_PALETTE
+ PNG_COLOR_MASK_COLOR
+ PNG_COLOR_MASK_ALPHA
+
+ interlace_type - PNG_INTERLACE_NONE or
+ PNG_INTERLACE_ADAM7
+ compression_type - (must be
+ PNG_COMPRESSION_TYPE_DEFAULT)
+ filter_method - (must be PNG_FILTER_TYPE_DEFAULT
+ or, if you are writing a PNG to
+ be embedded in a MNG datastream,
+ can also be
+ PNG_INTRAPIXEL_DIFFERENCING)
+
+If you call png_set_IHDR(), the call must appear before any of the
+other png_set_*() functions, because they might require access to some of
+the IHDR settings. The remaining png_set_*() functions can be called
+in any order.
+
+If you wish, you can reset the compression_type, interlace_type, or
+filter_method later by calling png_set_IHDR() again; if you do this, the
+width, height, bit_depth, and color_type must be the same in each call.
+
+ png_set_PLTE(png_ptr, info_ptr, palette,
+ num_palette);
+ palette - the palette for the file
+ (array of png_color)
+ num_palette - number of entries in the palette
+
+ png_set_gAMA(png_ptr, info_ptr, gamma);
+ gamma - the gamma the image was created
+ at (PNG_INFO_gAMA)
+
+ png_set_sRGB(png_ptr, info_ptr, srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of
+ the sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This chunk also implies specific
+ values of gAMA and cHRM. Rendering
+ intent is the CSS-1 property that
+ has been defined by the International
+ Color Consortium
+ (http://www.color.org).
+ It can be one of
+ PNG_sRGB_INTENT_SATURATION,
+ PNG_sRGB_INTENT_PERCEPTUAL,
+ PNG_sRGB_INTENT_ABSOLUTE, or
+ PNG_sRGB_INTENT_RELATIVE.
+
+
+ png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr,
+ srgb_intent);
+ srgb_intent - the rendering intent
+ (PNG_INFO_sRGB) The presence of the
+ sRGB chunk means that the pixel
+ data is in the sRGB color space.
+ This function also causes gAMA and
+ cHRM chunks with the specific values
+ that are consistent with sRGB to be
+ written.
+
+ png_set_iCCP(png_ptr, info_ptr, name, compression_type,
+ profile, proflen);
+ name - The profile name.
+ compression - The compression type; always
+ PNG_COMPRESSION_TYPE_BASE for PNG 1.0.
+ You may give NULL to this argument to
+ ignore it.
+ profile - International Color Consortium color
+ profile data. May contain NULs.
+ proflen - length of profile data in bytes.
+
+ png_set_sBIT(png_ptr, info_ptr, sig_bit);
+ sig_bit - the number of significant bits for
+ (PNG_INFO_sBIT) each of the gray, red,
+ green, and blue channels, whichever are
+ appropriate for the given color type
+ (png_color_16)
+
+ png_set_tRNS(png_ptr, info_ptr, trans, num_trans,
+ trans_values);
+ trans - array of transparent entries for
+ palette (PNG_INFO_tRNS)
+ trans_values - graylevel or color sample values
+ (in order red, green, blue) of the
+ single transparent color for
+ non-paletted images (PNG_INFO_tRNS)
+ num_trans - number of transparent entries
+ (PNG_INFO_tRNS)
+
+ png_set_hIST(png_ptr, info_ptr, hist);
+ (PNG_INFO_hIST)
+ hist - histogram of palette (array of
+ png_uint_16)
+
+ png_set_tIME(png_ptr, info_ptr, mod_time);
+ mod_time - time image was last modified
+ (PNG_VALID_tIME)
+
+ png_set_bKGD(png_ptr, info_ptr, background);
+ background - background color (PNG_VALID_bKGD)
+
+ png_set_text(png_ptr, info_ptr, text_ptr, num_text);
+ text_ptr - array of png_text holding image
+ comments
+ text_ptr[i].compression - type of compression used
+ on "text" PNG_TEXT_COMPRESSION_NONE
+ PNG_TEXT_COMPRESSION_zTXt
+ PNG_ITXT_COMPRESSION_NONE
+ PNG_ITXT_COMPRESSION_zTXt
+ text_ptr[i].key - keyword for comment. Must contain
+ 1-79 characters.
+ text_ptr[i].text - text comments for current
+ keyword. Can be NULL or empty.
+ text_ptr[i].text_length - length of text string,
+ after decompression, 0 for iTXt
+ text_ptr[i].itxt_length - length of itxt string,
+ after decompression, 0 for tEXt/zTXt
+ text_ptr[i].lang - language of comment (NULL or
+ empty for unknown).
+ text_ptr[i].translated_keyword - keyword in UTF-8 (NULL
+ or empty for unknown).
+ num_text - number of comments
+
+ png_set_sPLT(png_ptr, info_ptr, &palette_ptr,
+ num_spalettes);
+ palette_ptr - array of png_sPLT_struct structures
+ to be added to the list of palettes
+ in the info structure.
+ num_spalettes - number of palette structures to be
+ added.
+
+ png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y,
+ unit_type);
+ offset_x - positive offset from the left
+ edge of the screen
+ offset_y - positive offset from the top
+ edge of the screen
+ unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
+
+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y,
+ unit_type);
+ res_x - pixels/unit physical resolution
+ in x direction
+ res_y - pixels/unit physical resolution
+ in y direction
+ unit_type - PNG_RESOLUTION_UNKNOWN,
+ PNG_RESOLUTION_METER
+
+ png_set_sCAL(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are doubles)
+
+ png_set_sCAL_s(png_ptr, info_ptr, unit, width, height)
+ unit - physical scale units (an integer)
+ width - width of a pixel in physical scale units
+ height - height of a pixel in physical scale units
+ (width and height are strings like "2.54")
+
+ png_set_unknown_chunks(png_ptr, info_ptr, &unknowns,
+ num_unknowns)
+ unknowns - array of png_unknown_chunk
+ structures holding unknown chunks
+ unknowns[i].name - name of unknown chunk
+ unknowns[i].data - data of unknown chunk
+ unknowns[i].size - size of unknown chunk's data
+ unknowns[i].location - position to write chunk in file
+ 0: do not write chunk
+ PNG_HAVE_IHDR: before PLTE
+ PNG_HAVE_PLTE: before IDAT
+ PNG_AFTER_IDAT: after IDAT
+
+The "location" member is set automatically according to
+what part of the output file has already been written.
+You can change its value after calling png_set_unknown_chunks()
+as demonstrated in pngtest.c. Within each of the "locations",
+the chunks are sequenced according to their position in the
+structure (that is, the value of "i", which is the order in which
+the chunk was either read from the input file or defined with
+png_set_unknown_chunks).
+
+A quick word about text and num_text. text is an array of png_text
+structures. num_text is the number of valid structures in the array.
+Each png_text structure holds a language code, a keyword, a text value,
+and a compression type.
+
+The compression types have the same valid numbers as the compression
+types of the image data. Currently, the only valid number is zero.
+However, you can store text either compressed or uncompressed, unlike
+images, which always have to be compressed. So if you don't want the
+text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
+Because tEXt and zTXt chunks don't have a language field, if you
+specify PNG_TEXT_COMPRESSION_NONE or PNG_TEXT_COMPRESSION_zTXt
+any language code or translated keyword will not be written out.
+
+Until text gets around 1000 bytes, it is not worth compressing it.
+After the text has been written out to the file, the compression type
+is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
+so that it isn't written out again at the end (in case you are calling
+png_write_end() with the same struct.
+
+The keywords that are given in the PNG Specification are:
+
+ Title Short (one line) title or
+ caption for image
+ Author Name of image's creator
+ Description Description of image (possibly long)
+ Copyright Copyright notice
+ Creation Time Time of original image creation
+ (usually RFC 1123 format, see below)
+ Software Software used to create the image
+ Disclaimer Legal disclaimer
+ Warning Warning of nature of content
+ Source Device used to create the image
+ Comment Miscellaneous comment; conversion
+ from other image format
+
+The keyword-text pairs work like this. Keywords should be short
+simple descriptions of what the comment is about. Some typical
+keywords are found in the PNG specification, as is some recommendations
+on keywords. You can repeat keywords in a file. You can even write
+some text before the image and some after. For example, you may want
+to put a description of the image before the image, but leave the
+disclaimer until after, so viewers working over modem connections
+don't have to wait for the disclaimer to go over the modem before
+they start seeing the image. Finally, keywords should be full
+words, not abbreviations. Keywords and text are in the ISO 8859-1
+(Latin-1) character set (a superset of regular ASCII) and can not
+contain NUL characters, and should not contain control or other
+unprintable characters. To make the comments widely readable, stick
+with basic ASCII, and avoid machine specific character set extensions
+like the IBM-PC character set. The keyword must be present, but
+you can leave off the text string on non-compressed pairs.
+Compressed pairs must have a text string, as only the text string
+is compressed anyway, so the compression would be meaningless.
+
+PNG supports modification time via the png_time structure. Two
+conversion routines are provided, png_convert_from_time_t() for
+time_t and png_convert_from_struct_tm() for struct tm. The
+time_t routine uses gmtime(). You don't have to use either of
+these, but if you wish to fill in the png_time structure directly,
+you should provide the time in universal time (GMT) if possible
+instead of your local time. Note that the year number is the full
+year (e.g. 1998, rather than 98 - PNG is year 2000 compliant!), and
+that months start with 1.
+
+If you want to store the time of the original image creation, you should
+use a plain tEXt chunk with the "Creation Time" keyword. This is
+necessary because the "creation time" of a PNG image is somewhat vague,
+depending on whether you mean the PNG file, the time the image was
+created in a non-PNG format, a still photo from which the image was
+scanned, or possibly the subject matter itself. In order to facilitate
+machine-readable dates, it is recommended that the "Creation Time"
+tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
+although this isn't a requirement. Unlike the tIME chunk, the
+"Creation Time" tEXt chunk is not expected to be automatically changed
+by the software. To facilitate the use of RFC 1123 dates, a function
+png_convert_to_rfc1123(png_timep) is provided to convert from PNG
+time to an RFC 1123 format string.
+
+Writing unknown chunks
+
+You can use the png_set_unknown_chunks function to queue up chunks
+for writing. You give it a chunk name, raw data, and a size; that's
+all there is to it. The chunks will be written by the next following
+png_write_info_before_PLTE, png_write_info, or png_write_end function.
+Any chunks previously read into the info structure's unknown-chunk
+list will also be written out in a sequence that satisfies the PNG
+specification's ordering rules.
+
+The high-level write interface
+
+At this point there are two ways to proceed; through the high-level
+write interface, or through a sequence of low-level write operations.
+You can use the high-level interface if your image data is present
+in the info structure. All defined output
+transformations are permitted, enabled by the following masks.
+
+ PNG_TRANSFORM_IDENTITY No transformation
+ PNG_TRANSFORM_PACKING Pack 1, 2 and 4-bit samples
+ PNG_TRANSFORM_PACKSWAP Change order of packed
+ pixels to LSB first
+ PNG_TRANSFORM_INVERT_MONO Invert monochrome images
+ PNG_TRANSFORM_SHIFT Normalize pixels to the
+ sBIT depth
+ PNG_TRANSFORM_BGR Flip RGB to BGR, RGBA
+ to BGRA
+ PNG_TRANSFORM_SWAP_ALPHA Flip RGBA to ARGB or GA
+ to AG
+ PNG_TRANSFORM_INVERT_ALPHA Change alpha from opacity
+ to transparency
+ PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples
+ PNG_TRANSFORM_STRIP_FILLER Strip out filler
+ bytes (deprecated).
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE Strip out leading
+ filler bytes
+ PNG_TRANSFORM_STRIP_FILLER_AFTER Strip out trailing
+ filler bytes
+
+If you have valid image data in the info structure (you can use
+png_set_rows() to put image data in the info structure), simply do this:
+
+ png_write_png(png_ptr, info_ptr, png_transforms, NULL)
+
+where png_transforms is an integer containing the bitwise OR of some set of
+transformation flags. This call is equivalent to png_write_info(),
+followed the set of transformations indicated by the transform mask,
+then png_write_image(), and finally png_write_end().
+
+(The final parameter of this call is not yet used. Someday it might point
+to transformation parameters required by some future output transform.)
+
+You must use png_transforms and not call any png_set_transform() functions
+when you use png_write_png().
+
+The low-level write interface
+
+If you are going the low-level route instead, you are now ready to
+write all the file information up to the actual image data. You do
+this with a call to png_write_info().
+
+ png_write_info(png_ptr, info_ptr);
+
+Note that there is one transformation you may need to do before
+png_write_info(). In PNG files, the alpha channel in an image is the
+level of opacity. If your data is supplied as a level of
+transparency, you can invert the alpha channel before you write it, so
+that 0 is fully transparent and 255 (in 8-bit or paletted images) or
+65535 (in 16-bit images) is fully opaque, with
+
+ png_set_invert_alpha(png_ptr);
+
+This must appear before png_write_info() instead of later with the
+other transformations because in the case of paletted images the tRNS
+chunk data has to be inverted before the tRNS chunk is written. If
+your image is not a paletted image, the tRNS data (which in such cases
+represents a single color to be rendered as transparent) won't need to
+be changed, and you can safely do this transformation after your
+png_write_info() call.
+
+If you need to write a private chunk that you want to appear before
+the PLTE chunk when PLTE is present, you can write the PNG info in
+two steps, and insert code to write your own chunk between them:
+
+ png_write_info_before_PLTE(png_ptr, info_ptr);
+ png_set_unknown_chunks(png_ptr, info_ptr, ...);
+ png_write_info(png_ptr, info_ptr);
+
+After you've written the file information, you can set up the library
+to handle any special transformations of the image data. The various
+ways to transform the data will be described in the order that they
+should occur. This is important, as some of these change the color
+type and/or bit depth of the data, and some others only work on
+certain color types and bit depths. Even though each transformation
+checks to see if it has data that it can do something with, you should
+make sure to only enable a transformation if it will be valid for the
+data. For example, don't swap red and blue on grayscale data.
+
+PNG files store RGB pixels packed into 3 or 6 bytes. This code tells
+the library to strip input data that has 4 or 8 bytes per pixel down
+to 3 or 6 bytes (or strip 2 or 4-byte grayscale+filler data to 1 or 2
+bytes per pixel).
+
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+
+where the 0 is unused, and the location is either PNG_FILLER_BEFORE or
+PNG_FILLER_AFTER, depending upon whether the filler byte in the pixel
+is stored XRGB or RGBX.
+
+PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
+they can, resulting in, for example, 8 pixels per byte for 1 bit files.
+If the data is supplied at 1 pixel per byte, use this code, which will
+correctly pack the pixels into a single byte:
+
+ png_set_packing(png_ptr);
+
+PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your
+data is of another bit depth, you can write an sBIT chunk into the
+file so that decoders can recover the original data if desired.
+
+ /* Set the true bit depth of the image data */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ sig_bit.red = true_bit_depth;
+ sig_bit.green = true_bit_depth;
+ sig_bit.blue = true_bit_depth;
+ }
+ else
+ {
+ sig_bit.gray = true_bit_depth;
+ }
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ sig_bit.alpha = true_bit_depth;
+ }
+
+ png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+If the data is stored in the row buffer in a bit depth other than
+one supported by PNG (e.g. 3 bit data in the range 0-7 for a 4-bit PNG),
+this will scale the values to appear to be the correct bit depth as
+is required by PNG.
+
+ png_set_shift(png_ptr, &sig_bit);
+
+PNG files store 16 bit pixels in network byte order (big-endian,
+ie. most significant bits first). This code would be used if they are
+supplied the other way (little-endian, i.e. least significant bits
+first, the way PCs store them):
+
+ if (bit_depth > 8)
+ png_set_swap(png_ptr);
+
+If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
+need to change the order the pixels are packed into bytes, you can use:
+
+ if (bit_depth < 8)
+ png_set_packswap(png_ptr);
+
+PNG files store 3 color pixels in red, green, blue order. This code
+would be used if they are supplied as blue, green, red:
+
+ png_set_bgr(png_ptr);
+
+PNG files describe monochrome as black being zero and white being
+one. This code would be used if the pixels are supplied with this reversed
+(black being one and white being zero):
+
+ png_set_invert_mono(png_ptr);
+
+Finally, you can write your own transformation function if none of
+the existing ones meets your needs. This is done by setting a callback
+with
+
+ png_set_write_user_transform_fn(png_ptr,
+ write_transform_fn);
+
+You must supply the function
+
+ void write_transform_fn(png_ptr ptr, row_info_ptr
+ row_info, png_bytep data)
+
+See pngtest.c for a working example. Your function will be called
+before any of the other transformations are processed.
+
+You can also set up a pointer to a user structure for use by your
+callback function.
+
+ png_set_user_transform_info(png_ptr, user_ptr, 0, 0);
+
+The user_channels and user_depth parameters of this function are ignored
+when writing; you can set them to zero as shown.
+
+You can retrieve the pointer via the function png_get_user_transform_ptr().
+For example:
+
+ voidp write_user_transform_ptr =
+ png_get_user_transform_ptr(png_ptr);
+
+It is possible to have libpng flush any pending output, either manually,
+or automatically after a certain number of lines have been written. To
+flush the output stream a single time call:
+
+ png_write_flush(png_ptr);
+
+and to have libpng flush the output stream periodically after a certain
+number of scanlines have been written, call:
+
+ png_set_flush(png_ptr, nrows);
+
+Note that the distance between rows is from the last time png_write_flush()
+was called, or the first row of the image if it has never been called.
+So if you write 50 lines, and then png_set_flush 25, it will flush the
+output on the next scanline, and every 25 lines thereafter, unless
+png_write_flush() is called before 25 more lines have been written.
+If nrows is too small (less than about 10 lines for a 640 pixel wide
+RGB image) the image compression may decrease noticeably (although this
+may be acceptable for real-time applications). Infrequent flushing will
+only degrade the compression performance by a few percent over images
+that do not use flushing.
+
+Writing the image data
+
+That's it for the transformations. Now you can write the image data.
+The simplest way to do this is in one function call. If you have the
+whole image in memory, you can just call png_write_image() and libpng
+will write the image. You will need to pass in an array of pointers to
+each row. This function automatically handles interlacing, so you don't
+need to call png_set_interlace_handling() or call this function multiple
+times, or any of that other stuff necessary with png_write_rows().
+
+ png_write_image(png_ptr, row_pointers);
+
+where row_pointers is:
+
+ png_byte *row_pointers[height];
+
+You can point to void or char or whatever you use for pixels.
+
+If you don't want to write the whole image at once, you can
+use png_write_rows() instead. If the file is not interlaced,
+this is simple:
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+row_pointers is the same as in the png_write_image() call.
+
+If you are just writing one row at a time, you can do this with
+a single row_pointer instead of an array of row_pointers:
+
+ png_bytep row_pointer = row;
+
+ png_write_row(png_ptr, row_pointer);
+
+When the file is interlaced, things can get a good deal more
+complicated. The only currently (as of the PNG Specification
+version 1.2, dated July 1999) defined interlacing scheme for PNG files
+is the "Adam7" interlace scheme, that breaks down an
+image into seven smaller images of varying size. libpng will build
+these images for you, or you can do them yourself. If you want to
+build them yourself, see the PNG specification for details of which
+pixels to write when.
+
+If you don't want libpng to handle the interlacing details, just
+use png_set_interlace_handling() and call png_write_rows() the
+correct number of times to write all seven sub-images.
+
+If you want libpng to build the sub-images, call this before you start
+writing any rows:
+
+ number_of_passes =
+ png_set_interlace_handling(png_ptr);
+
+This will return the number of passes needed. Currently, this
+is seven, but may change if another interlace type is added.
+
+Then write the complete image number_of_passes times.
+
+ png_write_rows(png_ptr, row_pointers,
+ number_of_rows);
+
+As some of these rows are not used, and thus return immediately,
+you may want to read about interlacing in the PNG specification,
+and only update the rows that are actually used.
+
+Finishing a sequential write
+
+After you are finished writing the image, you should finish writing
+the file. If you are interested in writing comments or time, you should
+pass an appropriately filled png_info pointer. If you are not interested,
+you can pass NULL.
+
+ png_write_end(png_ptr, info_ptr);
+
+When you are done, you can free all memory used by libpng like this:
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+It is also possible to individually free the info_ptr members that
+point to libpng-allocated storage with the following function:
+
+ png_free_data(png_ptr, info_ptr, mask, seq)
+ mask - identifies data to be freed, a mask
+ containing the bitwise OR of one or
+ more of
+ PNG_FREE_PLTE, PNG_FREE_TRNS,
+ PNG_FREE_HIST, PNG_FREE_ICCP,
+ PNG_FREE_PCAL, PNG_FREE_ROWS,
+ PNG_FREE_SCAL, PNG_FREE_SPLT,
+ PNG_FREE_TEXT, PNG_FREE_UNKN,
+ or simply PNG_FREE_ALL
+ seq - sequence number of item to be freed
+ (-1 for all items)
+
+This function may be safely called when the relevant storage has
+already been freed, or has not yet been allocated, or was allocated
+by the user and not by libpng, and will in those
+cases do nothing. The "seq" parameter is ignored if only one item
+of the selected data type, such as PLTE, is allowed. If "seq" is not
+-1, and multiple items are allowed for the data type identified in
+the mask, such as text or sPLT, only the n'th item in the structure
+is freed, where n is "seq".
+
+If you allocated data such as a palette that you passed
+in to libpng with png_set_*, you must not free it until just before the call to
+png_destroy_write_struct().
+
+The default behavior is only to free data that was allocated internally
+by libpng. This can be changed, so that libpng will not free the data,
+or so that it will free data that was allocated by the user with png_malloc()
+or png_zalloc() and passed in via a png_set_*() function, with
+
+ png_data_freer(png_ptr, info_ptr, freer, mask)
+ mask - which data elements are affected
+ same choices as in png_free_data()
+ freer - one of
+ PNG_DESTROY_WILL_FREE_DATA
+ PNG_SET_WILL_FREE_DATA
+ PNG_USER_WILL_FREE_DATA
+
+For example, to transfer responsibility for some data from a read structure
+to a write structure, you could use
+
+ png_data_freer(read_ptr, read_info_ptr,
+ PNG_USER_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+ png_data_freer(write_ptr, write_info_ptr,
+ PNG_DESTROY_WILL_FREE_DATA,
+ PNG_FREE_PLTE|PNG_FREE_tRNS|PNG_FREE_hIST)
+
+thereby briefly reassigning responsibility for freeing to the user but
+immediately afterwards reassigning it once more to the write_destroy
+function. Having done this, it would then be safe to destroy the read
+structure and continue to use the PLTE, tRNS, and hIST data in the write
+structure.
+
+This function only affects data that has already been allocated.
+You can call this function before calling after the png_set_*() functions
+to control whether the user or png_destroy_*() is supposed to free the data.
+When the user assumes responsibility for libpng-allocated data, the
+application must use
+png_free() to free it, and when the user transfers responsibility to libpng
+for data that the user has allocated, the user must have used png_malloc()
+or png_zalloc() to allocate it.
+
+If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
+separately, do not transfer responsibility for freeing text_ptr to libpng,
+because when libpng fills a png_text structure it combines these members with
+the key member, and png_free_data() will free only text_ptr.key. Similarly,
+if you transfer responsibility for free'ing text_ptr from libpng to your
+application, your application must not separately free those members.
+For a more compact example of writing a PNG image, see the file example.c.
+
+V. Modifying/Customizing libpng:
+
+There are two issues here. The first is changing how libpng does
+standard things like memory allocation, input/output, and error handling.
+The second deals with more complicated things like adding new chunks,
+adding new transformations, and generally changing how libpng works.
+Both of those are compile-time issues; that is, they are generally
+determined at the time the code is written, and there is rarely a need
+to provide the user with a means of changing them.
+
+Memory allocation, input/output, and error handling
+
+All of the memory allocation, input/output, and error handling in libpng
+goes through callbacks that are user-settable. The default routines are
+in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change
+these functions, call the appropriate png_set_*_fn() function.
+
+Memory allocation is done through the functions png_malloc()
+and png_free(). These currently just call the standard C functions. If
+your pointers can't access more then 64K at a time, you will want to set
+MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling
+memory allocation on a platform will change between applications, these
+functions must be modified in the library at compile time. If you prefer
+to use a different method of allocating and freeing data, you can use
+png_create_read_struct_2() or png_create_write_struct_2() to register
+your own functions as described above.
+These functions also provide a void pointer that can be retrieved via
+
+ mem_ptr=png_get_mem_ptr(png_ptr);
+
+Your replacement memory functions must have prototypes as follows:
+
+ png_voidp malloc_fn(png_structp png_ptr,
+ png_size_t size);
+ void free_fn(png_structp png_ptr, png_voidp ptr);
+
+Your malloc_fn() must return NULL in case of failure. The png_malloc()
+function will normally call png_error() if it receives a NULL from the
+system memory allocator or from your replacement malloc_fn().
+
+Your free_fn() will never be called with a NULL ptr, since libpng's
+png_free() checks for NULL before calling free_fn().
+
+Input/Output in libpng is done through png_read() and png_write(),
+which currently just call fread() and fwrite(). The FILE * is stored in
+png_struct and is initialized via png_init_io(). If you wish to change
+the method of I/O, the library supplies callbacks that you can set
+through the function png_set_read_fn() and png_set_write_fn() at run
+time, instead of calling the png_init_io() function. These functions
+also provide a void pointer that can be retrieved via the function
+png_get_io_ptr(). For example:
+
+ png_set_read_fn(png_structp read_ptr,
+ voidp read_io_ptr, png_rw_ptr read_data_fn)
+
+ png_set_write_fn(png_structp write_ptr,
+ voidp write_io_ptr, png_rw_ptr write_data_fn,
+ png_flush_ptr output_flush_fn);
+
+ voidp read_io_ptr = png_get_io_ptr(read_ptr);
+ voidp write_io_ptr = png_get_io_ptr(write_ptr);
+
+The replacement I/O functions must have prototypes as follows:
+
+ void user_read_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_write_data(png_structp png_ptr,
+ png_bytep data, png_size_t length);
+ void user_flush_data(png_structp png_ptr);
+
+The user_read_data() function is responsible for detecting and
+handling end-of-data errors.
+
+Supplying NULL for the read, write, or flush functions sets them back
+to using the default C stream functions, which expect the io_ptr to
+point to a standard *FILE structure. It is probably a mistake
+to use NULL for one of write_data_fn and output_flush_fn but not both
+of them, unless you have built libpng with PNG_NO_WRITE_FLUSH defined.
+It is an error to read from a write stream, and vice versa.
+
+Error handling in libpng is done through png_error() and png_warning().
+Errors handled through png_error() are fatal, meaning that png_error()
+should never return to its caller. Currently, this is handled via
+setjmp() and longjmp() (unless you have compiled libpng with
+PNG_SETJMP_NOT_SUPPORTED, in which case it is handled via PNG_ABORT()),
+but you could change this to do things like exit() if you should wish.
+
+On non-fatal errors, png_warning() is called
+to print a warning message, and then control returns to the calling code.
+By default png_error() and png_warning() print a message on stderr via
+fprintf() unless the library is compiled with PNG_NO_CONSOLE_IO defined
+(because you don't want the messages) or PNG_NO_STDIO defined (because
+fprintf() isn't available). If you wish to change the behavior of the error
+functions, you will need to set up your own message callbacks. These
+functions are normally supplied at the time that the png_struct is created.
+It is also possible to redirect errors and warnings to your own replacement
+functions after png_create_*_struct() has been called by calling:
+
+ png_set_error_fn(png_structp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn,
+ png_error_ptr warning_fn);
+
+ png_voidp error_ptr = png_get_error_ptr(png_ptr);
+
+If NULL is supplied for either error_fn or warning_fn, then the libpng
+default function will be used, calling fprintf() and/or longjmp() if a
+problem is encountered. The replacement error functions should have
+parameters as follows:
+
+ void user_error_fn(png_structp png_ptr,
+ png_const_charp error_msg);
+ void user_warning_fn(png_structp png_ptr,
+ png_const_charp warning_msg);
+
+The motivation behind using setjmp() and longjmp() is the C++ throw and
+catch exception handling methods. This makes the code much easier to write,
+as there is no need to check every return code of every function call.
+However, there are some uncertainties about the status of local variables
+after a longjmp, so the user may want to be careful about doing anything after
+setjmp returns non-zero besides returning itself. Consult your compiler
+documentation for more details. For an alternative approach, you may wish
+to use the "cexcept" facility (see http://cexcept.sourceforge.net).
+
+Custom chunks
+
+If you need to read or write custom chunks, you may need to get deeper
+into the libpng code. The library now has mechanisms for storing
+and writing chunks of unknown type; you can even declare callbacks
+for custom chunks. However, this may not be good enough if the
+library code itself needs to know about interactions between your
+chunk and existing `intrinsic' chunks.
+
+If you need to write a new intrinsic chunk, first read the PNG
+specification. Acquire a first level of
+understanding of how it works. Pay particular attention to the
+sections that describe chunk names, and look at how other chunks were
+designed, so you can do things similarly. Second, check out the
+sections of libpng that read and write chunks. Try to find a chunk
+that is similar to yours and use it as a template. More details can
+be found in the comments inside the code. It is best to handle unknown
+chunks in a generic method, via callback functions, instead of by
+modifying libpng functions.
+
+If you wish to write your own transformation for the data, look through
+the part of the code that does the transformations, and check out some of
+the simpler ones to get an idea of how they work. Try to find a similar
+transformation to the one you want to add and copy off of it. More details
+can be found in the comments inside the code itself.
+
+Configuring for 16 bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more then 64K at a time. Even if you can, the memory
+won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call. See zlib.h or zconf.h in the zlib library for more information.
+
+Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set. Everything in the library (except for zlib's structure) is
+expecting far data. You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful). Make
+note that the rows of data are defined as png_bytepp, which is an
+unsigned char far * far *.
+
+Configuring for gui/windowing platforms:
+
+You will need to write new error and warning functions that use the GUI
+interface, as described previously, and set them to be the error and
+warning functions at the time that png_create_*_struct() is called,
+in order to have them available during the structure initialization.
+They can be changed later via png_set_error_fn(). On some compilers,
+you may also have to change the memory allocators (png_malloc, etc.).
+
+Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h. If you need to add, change
+or delete an include, this is the place to do it.
+The includes that are not needed outside libpng are protected by the
+PNG_INTERNAL definition, which is only defined for those routines inside
+libpng itself. The files in libpng proper only include png.h, which
+includes pngconf.h.
+
+Configuring zlib:
+
+There are special functions to configure the compression. Perhaps the
+most useful one changes the compression level, which currently uses
+input compression values in the range 0 - 9. The library normally
+uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests
+have shown that for a large majority of images, compression values in
+the range 3-6 compress nearly as well as higher levels, and do so much
+faster. For online applications it may be desirable to have maximum speed
+(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also
+specify no compression (Z_NO_COMPRESSION = 0), but this would create
+files larger than just storing the raw bitmap. You can specify the
+compression level by calling:
+
+ png_set_compression_level(png_ptr, level);
+
+Another useful one is to reduce the memory level used by the library.
+The memory level defaults to 8, but it can be lowered if you are
+short on memory (running DOS, for example, where you only have 640K).
+Note that the memory level does have an effect on compression; among
+other things, lower levels will result in sections of incompressible
+data being emitted in smaller stored blocks, with a correspondingly
+larger relative overhead of up to 15% in the worst case.
+
+ png_set_compression_mem_level(png_ptr, level);
+
+The other functions are for configuring zlib. They are not recommended
+for normal use and may result in writing an invalid PNG file. See
+zlib.h for more information on what these mean.
+
+ png_set_compression_strategy(png_ptr,
+ strategy);
+ png_set_compression_window_bits(png_ptr,
+ window_bits);
+ png_set_compression_method(png_ptr, method);
+ png_set_compression_buffer_size(png_ptr, size);
+
+Controlling row filtering
+
+If you want to control whether libpng uses filtering or not, which
+filters are used, and how it goes about picking row filters, you
+can call one of these functions. The selection and configuration
+of row filters can have a significant impact on the size and
+encoding speed and a somewhat lesser impact on the decoding speed
+of an image. Filtering is enabled by default for RGB and grayscale
+images (with and without alpha), but not for paletted images nor
+for any images with bit depths less than 8 bits/pixel.
+
+The 'method' parameter sets the main filtering method, which is
+currently only '0' in the PNG 1.2 specification. The 'filters'
+parameter sets which filter(s), if any, should be used for each
+scanline. Possible values are PNG_ALL_FILTERS and PNG_NO_FILTERS
+to turn filtering on and off, respectively.
+
+Individual filter types are PNG_FILTER_NONE, PNG_FILTER_SUB,
+PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH, which can be bitwise
+ORed together with '|' to specify one or more filters to use.
+These filters are described in more detail in the PNG specification.
+If you intend to change the filter type during the course of writing
+the image, you should start with flags set for all of the filters
+you intend to use so that libpng can initialize its internal
+structures appropriately for all of the filter types. (Note that this
+means the first row must always be adaptively filtered, because libpng
+currently does not allocate the filter buffers until png_write_row()
+is called for the first time.)
+
+ filters = PNG_FILTER_NONE | PNG_FILTER_SUB
+ PNG_FILTER_UP | PNG_FILTER_AVG |
+ PNG_FILTER_PAETH | PNG_ALL_FILTERS;
+
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE,
+ filters);
+ The second parameter can also be
+ PNG_INTRAPIXEL_DIFFERENCING if you are
+ writing a PNG to be embedded in a MNG
+ datastream. This parameter must be the
+ same as the value of filter_method used
+ in png_set_IHDR().
+
+It is also possible to influence how libpng chooses from among the
+available filters. This is done in one or both of two ways - by
+telling it how important it is to keep the same filter for successive
+rows, and by telling it the relative computational costs of the filters.
+
+ double weights[3] = {1.5, 1.3, 1.1},
+ costs[PNG_FILTER_VALUE_LAST] =
+ {1.0, 1.3, 1.3, 1.5, 1.7};
+
+ png_set_filter_heuristics(png_ptr,
+ PNG_FILTER_HEURISTIC_WEIGHTED, 3,
+ weights, costs);
+
+The weights are multiplying factors that indicate to libpng that the
+row filter should be the same for successive rows unless another row filter
+is that many times better than the previous filter. In the above example,
+if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
+"sum of absolute differences" 1.5 x 1.3 times higher than other filters
+and still be chosen, while the NONE filter could have a sum 1.1 times
+higher than other filters and still be chosen. Unspecified weights are
+taken to be 1.0, and the specified weights should probably be declining
+like those above in order to emphasize recent filters over older filters.
+
+The filter costs specify for each filter type a relative decoding cost
+to be considered when selecting row filters. This means that filters
+with higher costs are less likely to be chosen over filters with lower
+costs, unless their "sum of absolute differences" is that much smaller.
+The costs do not necessarily reflect the exact computational speeds of
+the various filters, since this would unduly influence the final image
+size.
+
+Note that the numbers above were invented purely for this example and
+are given only to help explain the function usage. Little testing has
+been done to find optimum values for either the costs or the weights.
+
+Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled. All the defines end in _SUPPORTED. If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four,
+along with directives to turn on any of the capabilities that you do
+want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable
+the extra transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks
+Use of the PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive
+produces a library that is incapable of reading or writing ancillary chunks.
+If you are not using the progressive reading capability, you can
+turn that off with PNG_NO_PROGRESSIVE_READ (don't confuse
+this with the INTERLACING capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs. However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with pngr and all the writing files start with
+pngw. The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+Requesting debug printout
+
+The macro definition PNG_DEBUG can be used to request debugging
+printout. Set it to an integer value in the range 0 to 3. Higher
+numbers result in increasing amounts of debugging information. The
+information is printed to the "stderr" file, unless another file
+name is specified in the PNG_DEBUG_FILE macro definition.
+
+When PNG_DEBUG > 0, the following functions (macros) become available:
+
+ png_debug(level, message)
+ png_debug1(level, message, p1)
+ png_debug2(level, message, p1, p2)
+
+in which "level" is compared to PNG_DEBUG to decide whether to print
+the message, "message" is the formatted string to be printed,
+and p1 and p2 are parameters that are to be embedded in the string
+according to printf-style formatting directives. For example,
+
+ png_debug1(2, "foo=%d\n", foo);
+
+is expanded to
+
+ if(PNG_DEBUG > 2)
+ fprintf(PNG_DEBUG_FILE, "foo=%d\n", foo);
+
+When PNG_DEBUG is defined but is zero, the macros aren't defined, but you
+can still use PNG_DEBUG to control your own debugging:
+
+ #ifdef PNG_DEBUG
+ fprintf(stderr, ...
+ #endif
+
+When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
+having level = 0 will be printed. There aren't any such statements in
+this version of libpng, but if you insert some they will be printed.
+
+VI. MNG support
+
+The MNG specification (available at http://www.libpng.org/pub/mng) allows
+certain extensions to PNG for PNG images that are embedded in MNG datastreams.
+Libpng can support some of these extensions. To enable them, use the
+png_permit_mng_features() function:
+
+ feature_set = png_permit_mng_features(png_ptr, mask)
+ mask is a png_uint_32 containing the bitwise OR of the
+ features you want to enable. These include
+ PNG_FLAG_MNG_EMPTY_PLTE
+ PNG_FLAG_MNG_FILTER_64
+ PNG_ALL_MNG_FEATURES
+ feature_set is a png_uint_32 that is the bitwise AND of
+ your mask with the set of MNG features that is
+ supported by the version of libpng that you are using.
+
+It is an error to use this function when reading or writing a standalone
+PNG file with the PNG 8-byte signature. The PNG datastream must be wrapped
+in a MNG datastream. As a minimum, it must have the MNG 8-byte signature
+and the MHDR and MEND chunks. Libpng does not provide support for these
+or any other MNG chunks; your application must provide its own support for
+them. You may wish to consider using libmng (available at
+http://www.libmng.com) instead.
+
+VII. Changes to Libpng from version 0.88
+
+It should be noted that versions of libpng later than 0.96 are not
+distributed by the original libpng author, Guy Schalnat, nor by
+Andreas Dilger, who had taken over from Guy during 1996 and 1997, and
+distributed versions 0.89 through 0.96, but rather by another member
+of the original PNG Group, Glenn Randers-Pehrson. Guy and Andreas are
+still alive and well, but they have moved on to other things.
+
+The old libpng functions png_read_init(), png_write_init(),
+png_info_init(), png_read_destroy(), and png_write_destroy() have been
+moved to PNG_INTERNAL in version 0.95 to discourage their use. These
+functions will be removed from libpng version 2.0.0.
+
+The preferred method of creating and initializing the libpng structures is
+via the png_create_read_struct(), png_create_write_struct(), and
+png_create_info_struct() because they isolate the size of the structures
+from the application, allow version error checking, and also allow the
+use of custom error handling routines during the initialization, which
+the old functions do not. The functions png_read_destroy() and
+png_write_destroy() do not actually free the memory that libpng
+allocated for these structs, but just reset the data structures, so they
+can be used instead of png_destroy_read_struct() and
+png_destroy_write_struct() if you feel there is too much system overhead
+allocating and freeing the png_struct for each image read.
+
+Setting the error callbacks via png_set_message_fn() before
+png_read_init() as was suggested in libpng-0.88 is no longer supported
+because this caused applications that do not use custom error functions
+to fail if the png_ptr was not initialized to zero. It is still possible
+to set the error callbacks AFTER png_read_init(), or to change them with
+png_set_error_fn(), which is essentially the same function, but with a new
+name to force compilation errors with applications that try to use the old
+method.
+
+Starting with version 1.0.7, you can find out which version of the library
+you are using at run-time:
+
+ png_uint_32 libpng_vn = png_access_version_number();
+
+The number libpng_vn is constructed from the major version, minor
+version with leading zero, and release number with leading zero,
+(e.g., libpng_vn for version 1.0.7 is 10007).
+
+You can also check which version of png.h you used when compiling your
+application:
+
+ png_uint_32 application_vn = PNG_LIBPNG_VER;
+
+VIII. Changes to Libpng from version 1.0.x to 1.2.x
+
+Support for user memory management was enabled by default. To
+accomplish this, the functions png_create_read_struct_2(),
+png_create_write_struct_2(), png_set_mem_fn(), png_get_mem_ptr(),
+png_malloc_default(), and png_free_default() were added.
+
+Support for certain MNG features was enabled.
+
+Support for numbered error messages was added. However, we never got
+around to actually numbering the error messages. The function
+png_set_strip_error_numbers() was added (Note: the prototype for this
+function was inadvertently removed from png.h in PNG_NO_ASSEMBLER_CODE
+builds of libpng-1.2.15. It was restored in libpng-1.2.36).
+
+The png_malloc_warn() function was added at libpng-1.2.3. This issues
+a png_warning and returns NULL instead of aborting when it fails to
+acquire the requested memory allocation.
+
+Support for setting user limits on image width and height was enabled
+by default. The functions png_set_user_limits(), png_get_user_width_max(),
+and png_get_user_height_max() were added at libpng-1.2.6.
+
+The png_set_add_alpha() function was added at libpng-1.2.7.
+
+The function png_set_expand_gray_1_2_4_to_8() was added at libpng-1.2.9.
+Unlike png_set_gray_1_2_4_to_8(), the new function does not expand the
+tRNS chunk to alpha. The png_set_gray_1_2_4_to_8() function is
+deprecated.
+
+A number of macro definitions in support of runtime selection of
+assembler code features (especially Intel MMX code support) were
+added at libpng-1.2.0:
+
+ PNG_ASM_FLAG_MMX_SUPPORT_COMPILED
+ PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU
+ PNG_ASM_FLAG_MMX_READ_COMBINE_ROW
+ PNG_ASM_FLAG_MMX_READ_INTERLACE
+ PNG_ASM_FLAG_MMX_READ_FILTER_SUB
+ PNG_ASM_FLAG_MMX_READ_FILTER_UP
+ PNG_ASM_FLAG_MMX_READ_FILTER_AVG
+ PNG_ASM_FLAG_MMX_READ_FILTER_PAETH
+ PNG_ASM_FLAGS_INITIALIZED
+ PNG_MMX_READ_FLAGS
+ PNG_MMX_FLAGS
+ PNG_MMX_WRITE_FLAGS
+ PNG_MMX_FLAGS
+
+We added the following functions in support of runtime
+selection of assembler code features:
+
+ png_get_mmx_flagmask()
+ png_set_mmx_thresholds()
+ png_get_asm_flags()
+ png_get_mmx_bitdepth_threshold()
+ png_get_mmx_rowbytes_threshold()
+ png_set_asm_flags()
+
+We replaced all of these functions with simple stubs in libpng-1.2.20,
+when the Intel assembler code was removed due to a licensing issue.
+
+IX. (Omitted)
+
+X. Detecting libpng
+
+The png_get_io_ptr() function has been present since libpng-0.88, has never
+changed, and is unaffected by conditional compilation macros. It is the
+best choice for use in configure scripts for detecting the presence of any
+libpng version since 0.88. In an autoconf "configure.in" you could use
+
+ AC_CHECK_LIB(png, png_get_io_ptr, ...
+
+XI. Source code repository
+
+Since about February 2009, version 1.2.34, libpng has been under "git" source
+control. The git repository was built from old libpng-x.y.z.tar.gz files
+going back to version 0.70. You can access the git repository (read only)
+at
+
+ git://libpng.git.sourceforge.net/gitroot/libpng
+
+or you can browse it via "gitweb" at
+
+ http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng
+
+Patches can be sent to glennrp at users.sourceforge.net or to
+png-mng-implement at lists.sourceforge.net or you can upload them to
+the libpng bug tracker at
+
+ http://libpng.sourceforge.net
+
+XII. Coding style
+
+Our coding style is similar to the "Allman" style, with curly
+braces on separate lines:
+
+ if (condition)
+ {
+ action;
+ }
+
+ else if (another condition)
+ {
+ another action;
+ }
+
+The braces can be omitted from simple one-line actions:
+
+ if (condition)
+ return (0);
+
+We use 3-space indentation, except for continued statements which
+are usually indented the same as the first line of the statement
+plus four more spaces.
+
+Comments appear with the leading "/*" at the same indentation as
+the statement that follows the comment:
+
+ /* Single-line comment */
+ statement;
+
+ /* Multiple-line
+ * comment
+ */
+ statement;
+
+Very short comments can be placed at the end of the statement
+to which they pertain:
+
+ statement; /* comment */
+
+We don't use C++ style ("//") comments. We have, however,
+used them in the past in some now-abandoned MMX assembler
+code.
+
+Functions and their curly braces are not indented, and
+exported functions are marked with PNGAPI:
+
+ /* This is a public function that is visible to
+ * application programers. It does thus-and-so.
+ */
+ void PNGAPI
+ png_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for all exported functions appear in png.h,
+above the comment that says
+
+ /* Maintainer: Put new public prototypes here ... */
+
+We mark all non-exported functions with "/* PRIVATE */"":
+
+ void /* PRIVATE */
+ png_non_exported_function(png_ptr, png_info, foo)
+ {
+ body;
+ }
+
+The prototypes for non-exported functions (except for those in
+pngtest) appear in
+the PNG_INTERNAL section of png.h
+above the comment that says
+
+ /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+The names of all exported functions and variables begin
+with "png_", and all publicly visible C preprocessor
+macros begin with "PNG_".
+
+We put a space after each comma and after each semicolon
+in "for" statments, and we put spaces before and after each
+C binary operator and after "for" or "while". We don't
+put a space between a typecast and the expression being
+cast, nor do we put one between a function name and the
+left parenthesis that follows it:
+
+ for (i = 2; i > 0; --i)
+ x[i] = a(x) + (int)b;
+
+We prefer #ifdef and #ifndef to #if defined() and if !defined()
+when there is only one macro being tested.
+
+Other rules can be inferred by inspecting the libpng
+source.
+
+XIII. Y2K Compliance in libpng
+
+September 10, 2009
+
+Since the PNG Development group is an ad-hoc body, we can't make
+an official declaration.
+
+This is your unofficial assurance that libpng from version 0.71 and
+upward through 1.2.40 are Y2K compliant. It is my belief that earlier
+versions were also Y2K compliant.
+
+Libpng only has three year fields. One is a 2-byte unsigned integer that
+will hold years up to 65535. The other two hold the date in text
+format, and will hold years up to 9999.
+
+The integer is
+ "png_uint_16 year" in png_time_struct.
+
+The strings are
+ "png_charp time_buffer" in png_struct and
+ "near_time_buffer", which is a local character string in png.c.
+
+There are seven time-related functions:
+
+ png_convert_to_rfc_1123() in png.c
+ (formerly png_convert_to_rfc_1152() in error)
+ png_convert_from_struct_tm() in pngwrite.c, called
+ in pngwrite.c
+ png_convert_from_time_t() in pngwrite.c
+ png_get_tIME() in pngget.c
+ png_handle_tIME() in pngrutil.c, called in pngread.c
+ png_set_tIME() in pngset.c
+ png_write_tIME() in pngwutil.c, called in pngwrite.c
+
+All appear to handle dates properly in a Y2K environment. The
+png_convert_from_time_t() function calls gmtime() to convert from system
+clock time, which returns (year - 1900), which we properly convert to
+the full 4-digit year. There is a possibility that applications using
+libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+function, or that they are incorrectly passing only a 2-digit year
+instead of "year - 1900" into the png_convert_from_struct_tm() function,
+but this is not under our control. The libpng documentation has always
+stated that it works with 4-digit years, and the APIs have been
+documented as such.
+
+The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
+integer to hold the year, and can hold years as large as 65535.
+
+zlib, upon which libpng depends, is also Y2K compliant. It contains
+no date-related code.
+
+
+ Glenn Randers-Pehrson
+ libpng maintainer
+ PNG Development Group
diff --git a/Source/LibPNG/libpng.xcodeproj/project.pbxproj b/Source/LibPNG/libpng.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..27dc9df
--- /dev/null
+++ b/Source/LibPNG/libpng.xcodeproj/project.pbxproj
@@ -0,0 +1,359 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D727B91E0E0ACF84009F51A1 /* pngconf.h in Headers */ = {isa = PBXBuildFile; fileRef = D727B9080E0ACF84009F51A1 /* pngconf.h */; };
+ D727B91F0E0ACF84009F51A1 /* png.h in Headers */ = {isa = PBXBuildFile; fileRef = D727B9090E0ACF84009F51A1 /* png.h */; };
+ D727B9200E0ACF84009F51A1 /* png.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B90A0E0ACF84009F51A1 /* png.c */; };
+ D727B9210E0ACF84009F51A1 /* pngmem.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B90B0E0ACF84009F51A1 /* pngmem.c */; };
+ D727B9220E0ACF84009F51A1 /* pngget.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B90C0E0ACF84009F51A1 /* pngget.c */; };
+ D727B9240E0ACF84009F51A1 /* pngerror.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B90E0E0ACF84009F51A1 /* pngerror.c */; };
+ D727B9260E0ACF84009F51A1 /* pngtrans.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9100E0ACF84009F51A1 /* pngtrans.c */; };
+ D727B9270E0ACF84009F51A1 /* pngwutil.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9110E0ACF84009F51A1 /* pngwutil.c */; };
+ D727B9280E0ACF84009F51A1 /* pngwtran.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9120E0ACF84009F51A1 /* pngwtran.c */; };
+ D727B9290E0ACF84009F51A1 /* pngwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9130E0ACF84009F51A1 /* pngwrite.c */; };
+ D727B92A0E0ACF84009F51A1 /* pngwio.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9140E0ACF84009F51A1 /* pngwio.c */; };
+ D727B92C0E0ACF84009F51A1 /* pngset.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9160E0ACF84009F51A1 /* pngset.c */; };
+ D727B92D0E0ACF84009F51A1 /* pngrutil.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9170E0ACF84009F51A1 /* pngrutil.c */; };
+ D727B92E0E0ACF84009F51A1 /* pngrtran.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9180E0ACF84009F51A1 /* pngrtran.c */; };
+ D727B92F0E0ACF84009F51A1 /* pngrio.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B9190E0ACF84009F51A1 /* pngrio.c */; };
+ D727B9310E0ACF84009F51A1 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = D727B91B0E0ACF84009F51A1 /* config.h */; };
+ D727B9320E0ACF84009F51A1 /* pngread.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B91C0E0ACF84009F51A1 /* pngread.c */; };
+ D727B9330E0ACF84009F51A1 /* pngpread.c in Sources */ = {isa = PBXBuildFile; fileRef = D727B91D0E0ACF84009F51A1 /* pngpread.c */; };
+ D74E47C50E0AD26700402A94 /* pngtest.c in Sources */ = {isa = PBXBuildFile; fileRef = D74E47C30E0AD25800402A94 /* pngtest.c */; };
+ D789EFD80E0AD6AC00C4A068 /* libpng.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libpng.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ D74E47BE0E0AD22E00402A94 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC045055464E500DB518D;
+ remoteInfo = libpng;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libpng.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpng.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D727B9080E0ACF84009F51A1 /* pngconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pngconf.h; sourceTree = SOURCE_ROOT; };
+ D727B9090E0ACF84009F51A1 /* png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = png.h; sourceTree = SOURCE_ROOT; };
+ D727B90A0E0ACF84009F51A1 /* png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = png.c; sourceTree = SOURCE_ROOT; };
+ D727B90B0E0ACF84009F51A1 /* pngmem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngmem.c; sourceTree = SOURCE_ROOT; };
+ D727B90C0E0ACF84009F51A1 /* pngget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngget.c; sourceTree = SOURCE_ROOT; };
+ D727B90E0E0ACF84009F51A1 /* pngerror.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngerror.c; sourceTree = SOURCE_ROOT; };
+ D727B9100E0ACF84009F51A1 /* pngtrans.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngtrans.c; sourceTree = SOURCE_ROOT; };
+ D727B9110E0ACF84009F51A1 /* pngwutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwutil.c; sourceTree = SOURCE_ROOT; };
+ D727B9120E0ACF84009F51A1 /* pngwtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwtran.c; sourceTree = SOURCE_ROOT; };
+ D727B9130E0ACF84009F51A1 /* pngwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwrite.c; sourceTree = SOURCE_ROOT; };
+ D727B9140E0ACF84009F51A1 /* pngwio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngwio.c; sourceTree = SOURCE_ROOT; };
+ D727B9160E0ACF84009F51A1 /* pngset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngset.c; sourceTree = SOURCE_ROOT; };
+ D727B9170E0ACF84009F51A1 /* pngrutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngrutil.c; sourceTree = SOURCE_ROOT; };
+ D727B9180E0ACF84009F51A1 /* pngrtran.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngrtran.c; sourceTree = SOURCE_ROOT; };
+ D727B9190E0ACF84009F51A1 /* pngrio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngrio.c; sourceTree = SOURCE_ROOT; };
+ D727B91B0E0ACF84009F51A1 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = SOURCE_ROOT; };
+ D727B91C0E0ACF84009F51A1 /* pngread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngread.c; sourceTree = SOURCE_ROOT; };
+ D727B91D0E0ACF84009F51A1 /* pngpread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngpread.c; sourceTree = SOURCE_ROOT; };
+ D727B9340E0ACFDF009F51A1 /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../../../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D727B9350E0ACFDF009F51A1 /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../../../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D74E47BA0E0AD22000402A94 /* pngtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pngtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ D74E47C30E0AD25800402A94 /* pngtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pngtest.c; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D74E47B80E0AD22000402A94 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D789EFD80E0AD6AC00C4A068 /* libpng.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libpng */ = {
+ isa = PBXGroup;
+ children = (
+ D727B9340E0ACFDF009F51A1 /* MacConfigExternalDebug.xcconfig */,
+ D727B9350E0ACFDF009F51A1 /* MacConfigExternalRelease.xcconfig */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ D74E47C00E0AD23A00402A94 /* Test only */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libpng;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D727B9080E0ACF84009F51A1 /* pngconf.h */,
+ D727B9090E0ACF84009F51A1 /* png.h */,
+ D727B90A0E0ACF84009F51A1 /* png.c */,
+ D727B90B0E0ACF84009F51A1 /* pngmem.c */,
+ D727B90C0E0ACF84009F51A1 /* pngget.c */,
+ D727B90E0E0ACF84009F51A1 /* pngerror.c */,
+ D727B9100E0ACF84009F51A1 /* pngtrans.c */,
+ D727B9110E0ACF84009F51A1 /* pngwutil.c */,
+ D727B9120E0ACF84009F51A1 /* pngwtran.c */,
+ D727B9130E0ACF84009F51A1 /* pngwrite.c */,
+ D727B9140E0ACF84009F51A1 /* pngwio.c */,
+ D727B9160E0ACF84009F51A1 /* pngset.c */,
+ D727B9170E0ACF84009F51A1 /* pngrutil.c */,
+ D727B9180E0ACF84009F51A1 /* pngrtran.c */,
+ D727B9190E0ACF84009F51A1 /* pngrio.c */,
+ D727B91B0E0ACF84009F51A1 /* config.h */,
+ D727B91C0E0ACF84009F51A1 /* pngread.c */,
+ D727B91D0E0ACF84009F51A1 /* pngpread.c */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libpng.a */,
+ D74E47BA0E0AD22000402A94 /* pngtest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+ D74E47C00E0AD23A00402A94 /* Test only */ = {
+ isa = PBXGroup;
+ children = (
+ D74E47C30E0AD25800402A94 /* pngtest.c */,
+ );
+ name = "Test only";
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D727B91E0E0ACF84009F51A1 /* pngconf.h in Headers */,
+ D727B91F0E0ACF84009F51A1 /* png.h in Headers */,
+ D727B9310E0ACF84009F51A1 /* config.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libpng */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libpng" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libpng;
+ productName = libpng;
+ productReference = D2AAC046055464E500DB518D /* libpng.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ D74E47B90E0AD22000402A94 /* pngtest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D74E47C10E0AD23A00402A94 /* Build configuration list for PBXNativeTarget "pngtest" */;
+ buildPhases = (
+ D74E47B70E0AD22000402A94 /* Sources */,
+ D74E47B80E0AD22000402A94 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ D74E47BF0E0AD22E00402A94 /* PBXTargetDependency */,
+ );
+ name = pngtest;
+ productName = pngtest;
+ productReference = D74E47BA0E0AD22000402A94 /* pngtest */;
+ productType = "com.apple.product-type.tool";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libpng" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libpng */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libpng */,
+ D74E47B90E0AD22000402A94 /* pngtest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D727B9200E0ACF84009F51A1 /* png.c in Sources */,
+ D727B9210E0ACF84009F51A1 /* pngmem.c in Sources */,
+ D727B9220E0ACF84009F51A1 /* pngget.c in Sources */,
+ D727B9240E0ACF84009F51A1 /* pngerror.c in Sources */,
+ D727B9260E0ACF84009F51A1 /* pngtrans.c in Sources */,
+ D727B9270E0ACF84009F51A1 /* pngwutil.c in Sources */,
+ D727B9280E0ACF84009F51A1 /* pngwtran.c in Sources */,
+ D727B9290E0ACF84009F51A1 /* pngwrite.c in Sources */,
+ D727B92A0E0ACF84009F51A1 /* pngwio.c in Sources */,
+ D727B92C0E0ACF84009F51A1 /* pngset.c in Sources */,
+ D727B92D0E0ACF84009F51A1 /* pngrutil.c in Sources */,
+ D727B92E0E0ACF84009F51A1 /* pngrtran.c in Sources */,
+ D727B92F0E0ACF84009F51A1 /* pngrio.c in Sources */,
+ D727B9320E0ACF84009F51A1 /* pngread.c in Sources */,
+ D727B9330E0ACF84009F51A1 /* pngpread.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D74E47B70E0AD22000402A94 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D74E47C50E0AD26700402A94 /* pngtest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ D74E47BF0E0AD22E00402A94 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC045055464E500DB518D /* libpng */;
+ targetProxy = D74E47BE0E0AD22E00402A94 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = png;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = png;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D727B9340E0ACFDF009F51A1 /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DHAVE_CONFIG_H",
+ "-DPNG_CONFIGURE_LIBPNG",
+ );
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D727B9350E0ACFDF009F51A1 /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ OTHER_CFLAGS = (
+ "$(inherited)",
+ "-DHAVE_CONFIG_H",
+ "-DPNG_CONFIGURE_LIBPNG",
+ );
+ };
+ name = Release;
+ };
+ D74E47BC0E0AD22000402A94 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_MODEL_TUNING = G5;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = pngtest;
+ ZERO_LINK = NO;
+ };
+ name = Debug;
+ };
+ D74E47BD0E0AD22000402A94 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+ GCC_MODEL_TUNING = G5;
+ INSTALL_PATH = /usr/local/bin;
+ PREBINDING = NO;
+ PRODUCT_NAME = pngtest;
+ ZERO_LINK = NO;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libpng" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libpng" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D74E47C10E0AD23A00402A94 /* Build configuration list for PBXNativeTarget "pngtest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D74E47BC0E0AD22000402A94 /* Debug */,
+ D74E47BD0E0AD22000402A94 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Source/LibPNG/libpngpf.3 b/Source/LibPNG/libpngpf.3
new file mode 100644
index 0000000..9a2c2ef
--- /dev/null
+++ b/Source/LibPNG/libpngpf.3
@@ -0,0 +1,806 @@
+.TH LIBPNGPF 3 "March 29, 2012"
+.SH NAME
+libpng \- Portable Network Graphics (PNG) Reference Library 1.2.49
+(private functions)
+.SH SYNOPSIS
+\fB#include <png.h>\fP
+
+\fI\fB
+
+\fBvoid png_64bit_product (long \fP\fIv1\fP\fB, long \fP\fIv2\fP\fB, unsigned long \fI*hi_product,
+
+\fBunsigned long \fI*lo_product\fP\fB);\fP
+
+\fI\fB
+
+\fBvoid png_build_gamma_table (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_build_grayscale_palette (int \fP\fIbit_depth\fP\fB, png_colorp \fIpalette\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_calculate_crc (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIptr\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBint png_check_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_fixed_point \fP\fIint_white_x\fP\fB, png_fixed_point \fP\fIint_white_y\fP\fB, png_fixed_point \fP\fIint_red_x\fP\fB, png_fixed_point \fP\fIint_red_y\fP\fB, png_fixed_point \fP\fIint_green_x\fP\fB, png_fixed_point \fP\fIint_green_y\fP\fB, png_fixed_point \fP\fIint_blue_x\fP\fB, png_fixed_point \fIint_blue_y\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_check_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIinterlace_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fIfilter_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_check_chunk_name (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIchunk_name\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBpng_size_t png_check_keyword (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charpp \fInew_key\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_combine_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fImask\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_correct_palette (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, int \fInum_palette\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBint png_crc_error (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBint png_crc_finish (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIskip\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_crc_read (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuf\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBpng_voidp png_create_struct (int \fItype\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBpng_voidp png_create_struct_2 (int \fP\fItype\fP\fB, png_malloc_ptr \fP\fImalloc_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_decompress_chunk (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcomp_type\fP\fB, png_charp \fP\fIchunkdata\fP\fB, png_size_t \fP\fIchunklength\fP\fB, png_size_t \fP\fIprefix_length\fP\fB, png_size_t \fI*data_length\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_destroy_struct (png_voidp \fIstruct_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_destroy_struct_2 (png_voidp \fP\fIstruct_ptr\fP\fB, png_free_ptr \fP\fIfree_fn\fP\fB, png_voidp \fImem_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_background (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fP\fItrans_values\fP\fB, png_color_16p \fP\fIbackground\fP\fB, png_color_16p \fP\fIbackground_1\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_bytep \fP\fIgamma_from_1\fP\fB, png_bytep \fP\fIgamma_to_1\fP\fB, png_uint_16pp \fP\fIgamma_16\fP\fB, png_uint_16pp \fP\fIgamma_16_from_1\fP\fB, png_uint_16pp \fP\fIgamma_16_to_1\fP\fB, int \fIgamma_shift\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_bgr (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_chop (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_dither (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIpalette_lookup\fP\fB, png_bytep \fIdither_lookup\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_expand (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_16p \fItrans_value\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_expand_palette (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_bytep \fP\fItrans\fP\fB, int \fInum_trans\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_gamma (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIgamma_table\fP\fB, png_uint_16pp \fP\fIgamma_16_table\fP\fB, int \fIgamma_shift\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_gray_to_rgb (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_invert (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_pack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIbit_depth\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_packswap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_read_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fP\fIfiller\fP\fB, png_uint_32 \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_read_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fP\fIpass\fP\fB, png_uint_32 \fItransformations\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_read_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_read_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBint png_do_rgb_to_gray (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_shift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIbit_depth\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_strip_filler (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_uint_32 \fIflags\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_swap (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_unpack (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_unshift (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_color_8p \fIsig_bits\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_write_interlace (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, int \fIpass\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_write_invert_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_write_swap_alpha (png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_do_write_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid *png_far_to_near (png_structp png_ptr,png_voidp \fP\fIptr\fP\fB, int \fIcheck\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_flush (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_bKGD (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_cHRM (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_gAMA (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_IEND (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_iTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_sRGB (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_info_destroy (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_init_mmx_flags (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_init_read_transformations (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_process_IDAT_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_process_some_data (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_check_crc (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_crc_finish (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_crc_skip (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_fill_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_handle_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_handle_unknown (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_handle_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_uint_32 \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_have_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_have_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_have_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIrow\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_process_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_chunk (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_end (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_IDAT (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_sig (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_read_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_restore_buffer (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIbuffer\fP\fB, png_size_t \fIbuffer_length\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_push_save_buffer (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBpng_uint_32 png_read_chunk_header (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_filter_row (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fP\fIrow_info\fP\fB, png_bytep \fP\fIrow\fP\fB, png_bytep \fP\fIprev_row\fP\fB, int \fIfilter\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_push_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_start_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_read_transform_info (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fIinfo_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_reset_crc (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBint png_set_text_2 (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_textp \fP\fItext_ptr\fP\fB, int \fInum_text\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_cHRM (png_structp \fP\fIpng_ptr\fP\fB, double \fP\fIwhite_x\fP\fB, double \fP\fIwhite_y\fP\fB, double \fP\fIred_x\fP\fB, double \fP\fIred_y\fP\fB, double \fP\fIgreen_x\fP\fB, double \fP\fIgreen_y\fP\fB, double \fP\fIblue_x\fP\fB, double \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_cHRM_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwhite_x\fP\fB, png_uint_32 \fP\fIwhite_y\fP\fB, png_uint_32 \fP\fIred_x\fP\fB, png_uint_32 \fP\fIred_y\fP\fB, png_uint_32 \fP\fIgreen_x\fP\fB, png_uint_32 \fP\fIgreen_y\fP\fB, png_uint_32 \fP\fIblue_x\fP\fB, png_uint_32 \fIblue_y\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_data (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_filtered_row (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fIfiltered_row\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_find_filter (png_structp \fP\fIpng_ptr\fP\fB, png_row_infop \fIrow_info\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_finish_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_gAMA (png_structp \fP\fIpng_ptr\fP\fB, double \fIfile_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_gAMA_fixed (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fIint_file_gamma\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_hIST (png_structp \fP\fIpng_ptr\fP\fB, png_uint_16p \fP\fIhist\fP\fB, int \fInum_hist\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_iCCP (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIname\fP\fB, int \fP\fIcompression_type\fP\fB, png_charp \fP\fIprofile\fP\fB, int \fIproflen\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_IDAT (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fIdata\fP\fB, png_size_t \fIlength\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_IEND (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_IHDR (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIwidth\fP\fB, png_uint_32 \fP\fIheight\fP\fB, int \fP\fIbit_depth\fP\fB, int \fP\fIcolor_type\fP\fB, int \fP\fIcompression_type\fP\fB, int \fP\fIfilter_type\fP\fB, int \fIinterlace_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_iTXt (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fIcompression\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fIlang\fP\fB, png_charp \fP\fItranslated_key\fP\fB, png_charp \fItext\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_oFFs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_offset\fP\fB, png_uint_32 \fP\fIy_offset\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_pCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIpurpose\fP\fB, png_int_32 \fP\fIX0\fP\fB, png_int_32 \fP\fIX1\fP\fB, int \fP\fItype\fP\fB, int \fP\fInparams\fP\fB, png_charp \fP\fIunits\fP\fB, png_charpp \fIparams\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_pHYs (png_structp \fP\fIpng_ptr\fP\fB, png_uint_32 \fP\fIx_pixels_per_unit\fP\fB, png_uint_32 \fP\fIy_pixels_per_unit\fP\fB, int \fIunit_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_PLTE (png_structp \fP\fIpng_ptr\fP\fB, png_colorp \fP\fIpalette\fP\fB, png_uint_32 \fInum_pal\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sBIT (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fP\fIsbit\fP\fB, int \fIcolor_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sCAL (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, double \fP\fIwidth\fP\fB, double \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sCAL_s (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIunit\fP\fB, png_charp \fP\fIwidth\fP\fB, png_charp \fIheight\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sig (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sRGB (png_structp \fP\fIpng_ptr\fP\fB, int \fIintent\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_sPLT (png_structp \fP\fIpng_ptr\fP\fB, png_spalette_p \fIpalette\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_start_row (png_structp \fIpng_ptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_tEXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fItext_len\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_tRNS (png_structp \fP\fIpng_ptr\fP\fB, png_bytep \fP\fItrans\fP\fB, png_color_16p \fP\fIvalues\fP\fB, int \fP\fInumber\fP\fB, int \fIcolor_type\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_write_zTXt (png_structp \fP\fIpng_ptr\fP\fB, png_charp \fP\fIkey\fP\fB, png_charp \fP\fItext\fP\fB, png_size_t \fP\fItext_len\fP\fB, int \fIcompression\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoidpf png_zalloc (voidpf \fP\fIpng_ptr\fP\fB, uInt \fP\fIitems\fP\fB, uInt \fIsize\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+\fBvoid png_zfree (voidpf \fP\fIpng_ptr\fP\fB, voidpf \fIptr\fP\fB);\fP
+
+\fI\fB
+
+\fI\fB
+
+.SH DESCRIPTION
+The functions listed above are used privately by libpng
+and are not recommended for use by applications. They are
+not "exported" to applications using shared libraries. They
+are listed alphabetically here as an aid to libpng maintainers.
+See png.h for more information on these functions.
+
+.SH SEE ALSO
+.IR libpng(3) ", " png(5)
+.SH AUTHOR
+Glenn Randers-Pehrson
diff --git a/Source/LibPNG/png.5 b/Source/LibPNG/png.5
new file mode 100644
index 0000000..e16d303
--- /dev/null
+++ b/Source/LibPNG/png.5
@@ -0,0 +1,74 @@
+.TH PNG 5 "March 29, 2012"
+.SH NAME
+png \- Portable Network Graphics (PNG) format
+.SH DESCRIPTION
+PNG (Portable Network Graphics) is an extensible file format for the
+lossless, portable, well-compressed storage of raster images. PNG provides
+a patent-free replacement for GIF and can also replace many
+common uses of TIFF. Indexed-color, grayscale, and truecolor images are
+supported, plus an optional alpha channel. Sample depths range from
+1 to 16 bits.
+.br
+
+PNG is designed to work well in online viewing applications, such as the
+World Wide Web, so it is fully streamable with a progressive display
+option. PNG is robust, providing both full file integrity checking and
+fast, simple detection of common transmission errors. Also, PNG can store
+gamma and chromaticity data for improved color matching on heterogeneous
+platforms.
+
+.SH "SEE ALSO"
+.IR libpng(3) ", " zlib(3) ", " deflate(5) ", and " zlib(5)
+.LP
+PNG specification (second edition), November 2003:
+.IP
+.br
+ <http://www.w3.org/TR/2003/REC-PNG-20031110/
+PNG 1.2 specification, July 1999:
+.IP
+.br
+http://www.libpng.org/pub/png
+.LP
+PNG 1.0 specification, October 1996:
+.IP
+.br
+RFC 2083
+.IP
+.br
+ftp://ftp.rfc-editor.org:/in-notes/rfc2083.txt
+.br
+or (as a W3C Recommendation) at
+.br
+http://www.w3.org/TR/REC-png.html
+.SH AUTHORS
+This man page: Glenn Randers-Pehrson
+.LP
+Portable Network Graphics (PNG) Specification (Second Edition)
+Information technology - Computer graphics and image processing -
+Portable Network Graphics (PNG): Functional specification.
+ISO/IEC 15948:2003 (E) (November 10, 2003): David Duce and others.
+.LP
+Portable Network Graphics (PNG) Specification Version 1.2 (July 8, 1999):
+Glenn Randers-Pehrson and others (png-list).
+.LP
+Portable Network Graphics (PNG) Specification Version 1.0 (October 1, 1996):
+Thomas Boutell and others (png-list).
+.LP
+
+
+.SH COPYRIGHT NOTICE
+.LP
+This man page is Copyright (c) 1998-2006 Glenn Randers-Pehrson. See png.h
+for conditions of use and distribution.
+.LP
+The PNG Specification (Second Edition) is
+Copyright (c) 2003 W3C. (MIT, ERCIM, Keio), All Rights Reserved.
+.LP
+The PNG-1.2 specification is copyright (c) 1999 Glenn Randers-Pehrson.
+See the specification for conditions of use and distribution.
+.LP
+The PNG-1.0 specification is copyright (c) 1996 Massachusetts Institute of
+Technology. See the specification for conditions of use and distribution.
+.LP
+.\" end of man page
+
diff --git a/Source/LibPNG/png.c b/Source/LibPNG/png.c
new file mode 100644
index 0000000..8d98612
--- /dev/null
+++ b/Source/LibPNG/png.c
@@ -0,0 +1,1100 @@
+
+/* png.c - location for general purpose libpng functions
+ *
+ * Last changed in libpng 1.2.46 [February 25, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_EXTERN
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_2_49 Your_png_h_is_not_version_1_2_49;
+
+/* Version information for C files. This had better match the version
+ * string defined in png.h.
+ */
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* png_libpng_ver was changed to a function in version 1.0.5c */
+PNG_CONST char png_libpng_ver[18] = PNG_LIBPNG_VER_STRING;
+
+#ifdef PNG_READ_SUPPORTED
+
+/* png_sig was changed to a function in version 1.0.5c */
+/* Place to hold the signature string for a PNG file. */
+PNG_CONST png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+#endif /* PNG_READ_SUPPORTED */
+
+/* Invoke global declarations for constant strings for known chunk types */
+PNG_IHDR;
+PNG_IDAT;
+PNG_IEND;
+PNG_PLTE;
+PNG_bKGD;
+PNG_cHRM;
+PNG_gAMA;
+PNG_hIST;
+PNG_iCCP;
+PNG_iTXt;
+PNG_oFFs;
+PNG_pCAL;
+PNG_sCAL;
+PNG_pHYs;
+PNG_sBIT;
+PNG_sPLT;
+PNG_sRGB;
+PNG_tEXt;
+PNG_tIME;
+PNG_tRNS;
+PNG_zTXt;
+
+#ifdef PNG_READ_SUPPORTED
+/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+/* Start of interlace block */
+PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+/* Offset to next interlace block */
+PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+/* Start of interlace block in the y direction */
+PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+/* Offset to next interlace block in the y direction */
+PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+/* Height of interlace block. This is not currently used - if you need
+ * it, uncomment it here and in png.h
+PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+*/
+
+/* Mask to determine which pixels are valid in a pass */
+PNG_CONST int FARDATA png_pass_mask[] =
+ {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+
+/* Mask to determine which pixels to overwrite while displaying */
+PNG_CONST int FARDATA png_pass_dsp_mask[]
+ = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+
+#endif /* PNG_READ_SUPPORTED */
+#endif /* PNG_USE_GLOBAL_ARRAYS */
+
+/* Tells libpng that we have already handled the first "num_bytes" bytes
+ * of the PNG file signature. If the PNG data is embedded into another
+ * stream we can set num_bytes = 8 so that libpng will not attempt to read
+ * or write any of the magic bytes before it starts on the IHDR.
+ */
+
+#ifdef PNG_READ_SUPPORTED
+void PNGAPI
+png_set_sig_bytes(png_structp png_ptr, int num_bytes)
+{
+ png_debug(1, "in png_set_sig_bytes");
+
+ if (png_ptr == NULL)
+ return;
+
+ if (num_bytes > 8)
+ png_error(png_ptr, "Too many bytes for PNG signature.");
+
+ png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+}
+
+/* Checks whether the supplied bytes match the PNG signature. We allow
+ * checking less than the full 8-byte signature so that those apps that
+ * already read the first few bytes of a file to determine the file type
+ * can simply check the remaining bytes for extra assurance. Returns
+ * an integer less than, equal to, or greater than zero if sig is found,
+ * respectively, to be less than, to match, or be greater than the correct
+ * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
+ */
+int PNGAPI
+png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
+{
+ png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+ if (num_to_check > 8)
+ num_to_check = 8;
+ else if (num_to_check < 1)
+ return (-1);
+
+ if (start > 7)
+ return (-1);
+
+ if (start + num_to_check > 8)
+ num_to_check = 8 - start;
+
+ return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
+}
+
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+/* (Obsolete) function to check signature bytes. It does not allow one
+ * to check a partial signature. This function might be removed in the
+ * future - use png_sig_cmp(). Returns true (nonzero) if the file is PNG.
+ */
+int PNGAPI
+png_check_sig(png_bytep sig, int num)
+{
+ return ((int)!png_sig_cmp(sig, (png_size_t)0, (png_size_t)num));
+}
+#endif
+#endif /* PNG_READ_SUPPORTED */
+
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+/* Function to allocate memory for zlib and clear it to 0. */
+#ifdef PNG_1_0_X
+voidpf PNGAPI
+#else
+voidpf /* PRIVATE */
+#endif
+png_zalloc(voidpf png_ptr, uInt items, uInt size)
+{
+ png_voidp ptr;
+ png_structp p=(png_structp)png_ptr;
+ png_uint_32 save_flags=p->flags;
+ png_uint_32 num_bytes;
+
+ if (png_ptr == NULL)
+ return (NULL);
+ if (items > PNG_UINT_32_MAX/size)
+ {
+ png_warning (p, "Potential overflow in png_zalloc()");
+ return (NULL);
+ }
+ num_bytes = (png_uint_32)items * size;
+
+ p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
+ ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
+ p->flags=save_flags;
+
+#if defined(PNG_1_0_X) && !defined(PNG_NO_ZALLOC_ZERO)
+ if (ptr == NULL)
+ return ((voidpf)ptr);
+
+ if (num_bytes > (png_uint_32)0x8000L)
+ {
+ png_memset(ptr, 0, (png_size_t)0x8000L);
+ png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
+ (png_size_t)(num_bytes - (png_uint_32)0x8000L));
+ }
+ else
+ {
+ png_memset(ptr, 0, (png_size_t)num_bytes);
+ }
+#endif
+ return ((voidpf)ptr);
+}
+
+/* Function to free memory for zlib */
+#ifdef PNG_1_0_X
+void PNGAPI
+#else
+void /* PRIVATE */
+#endif
+png_zfree(voidpf png_ptr, voidpf ptr)
+{
+ png_free((png_structp)png_ptr, (png_voidp)ptr);
+}
+
+/* Reset the CRC variable to 32 bits of 1's. Care must be taken
+ * in case CRC is > 32 bits to leave the top bits 0.
+ */
+void /* PRIVATE */
+png_reset_crc(png_structp png_ptr)
+{
+ png_ptr->crc = crc32(0, Z_NULL, 0);
+}
+
+/* Calculate the CRC over a section of data. We can only pass as
+ * much data to this routine as the largest single buffer size. We
+ * also check that this data will actually be used before going to the
+ * trouble of calculating it.
+ */
+void /* PRIVATE */
+png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
+{
+ int need_crc = 1;
+
+ if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
+ {
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+ (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+ need_crc = 0;
+ }
+ else /* critical */
+ {
+ if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ need_crc = 0;
+ }
+
+ if (need_crc)
+ png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
+}
+
+/* Allocate the memory for an info_struct for the application. We don't
+ * really need the png_ptr, but it could potentially be useful in the
+ * future. This should be used in favour of malloc(png_sizeof(png_info))
+ * and png_info_init() so that applications that want to use a shared
+ * libpng don't have to be recompiled if png_info changes size.
+ */
+png_infop PNGAPI
+png_create_info_struct(png_structp png_ptr)
+{
+ png_infop info_ptr;
+
+ png_debug(1, "in png_create_info_struct");
+
+ if (png_ptr == NULL)
+ return (NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
+ png_ptr->malloc_fn, png_ptr->mem_ptr);
+#else
+ info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+#endif
+ if (info_ptr != NULL)
+ png_info_init_3(&info_ptr, png_sizeof(png_info));
+
+ return (info_ptr);
+}
+
+/* This function frees the memory associated with a single info struct.
+ * Normally, one would use either png_destroy_read_struct() or
+ * png_destroy_write_struct() to free an info struct, but this may be
+ * useful for some applications.
+ */
+void PNGAPI
+png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
+{
+ png_infop info_ptr = NULL;
+
+ png_debug(1, "in png_destroy_info_struct");
+
+ if (png_ptr == NULL)
+ return;
+
+ if (info_ptr_ptr != NULL)
+ info_ptr = *info_ptr_ptr;
+
+ if (info_ptr != NULL)
+ {
+ png_info_destroy(png_ptr, info_ptr);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
+ png_ptr->mem_ptr);
+#else
+ png_destroy_struct((png_voidp)info_ptr);
+#endif
+ *info_ptr_ptr = NULL;
+ }
+}
+
+/* Initialize the info structure. This is now an internal function (0.89)
+ * and applications using it are urged to use png_create_info_struct()
+ * instead.
+ */
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+#undef png_info_init
+void PNGAPI
+png_info_init(png_infop info_ptr)
+{
+ /* We only come here via pre-1.0.12-compiled applications */
+ png_info_init_3(&info_ptr, 0);
+}
+#endif
+
+void PNGAPI
+png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+{
+ png_infop info_ptr = *ptr_ptr;
+
+ png_debug(1, "in png_info_init_3");
+
+ if (info_ptr == NULL)
+ return;
+
+ if (png_sizeof(png_info) > png_info_struct_size)
+ {
+ png_destroy_struct(info_ptr);
+ info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+ *ptr_ptr = info_ptr;
+ }
+
+ /* Set everything to 0 */
+ png_memset(info_ptr, 0, png_sizeof(png_info));
+}
+
+#ifdef PNG_FREE_ME_SUPPORTED
+void PNGAPI
+png_data_freer(png_structp png_ptr, png_infop info_ptr,
+ int freer, png_uint_32 mask)
+{
+ png_debug(1, "in png_data_freer");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (freer == PNG_DESTROY_WILL_FREE_DATA)
+ info_ptr->free_me |= mask;
+ else if (freer == PNG_USER_WILL_FREE_DATA)
+ info_ptr->free_me &= ~mask;
+ else
+ png_warning(png_ptr,
+ "Unknown freer parameter in png_data_freer.");
+}
+#endif
+
+void PNGAPI
+png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
+ int num)
+{
+ png_debug(1, "in png_free_data");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+#ifdef PNG_TEXT_SUPPORTED
+ /* Free text item num or (if num == -1) all text items */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_TEXT)
+#endif
+ {
+ if (num != -1)
+ {
+ if (info_ptr->text && info_ptr->text[num].key)
+ {
+ png_free(png_ptr, info_ptr->text[num].key);
+ info_ptr->text[num].key = NULL;
+ }
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < info_ptr->num_text; i++)
+ png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+ png_free(png_ptr, info_ptr->text);
+ info_ptr->text = NULL;
+ info_ptr->num_text=0;
+ }
+ }
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+ /* Free any tRNS entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+#else
+ if ((mask & PNG_FREE_TRNS) && (png_ptr->flags & PNG_FLAG_FREE_TRNS))
+#endif
+ {
+ png_free(png_ptr, info_ptr->trans);
+ info_ptr->trans = NULL;
+ info_ptr->valid &= ~PNG_INFO_tRNS;
+#ifndef PNG_FREE_ME_SUPPORTED
+ png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
+#endif
+ }
+#endif
+
+#ifdef PNG_sCAL_SUPPORTED
+ /* Free any sCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_SCAL)
+#endif
+ {
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, info_ptr->scal_s_width);
+ png_free(png_ptr, info_ptr->scal_s_height);
+ info_ptr->scal_s_width = NULL;
+ info_ptr->scal_s_height = NULL;
+#endif
+ info_ptr->valid &= ~PNG_INFO_sCAL;
+ }
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+ /* Free any pCAL entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_PCAL)
+#endif
+ {
+ png_free(png_ptr, info_ptr->pcal_purpose);
+ png_free(png_ptr, info_ptr->pcal_units);
+ info_ptr->pcal_purpose = NULL;
+ info_ptr->pcal_units = NULL;
+ if (info_ptr->pcal_params != NULL)
+ {
+ int i;
+ for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
+ {
+ png_free(png_ptr, info_ptr->pcal_params[i]);
+ info_ptr->pcal_params[i] = NULL;
+ }
+ png_free(png_ptr, info_ptr->pcal_params);
+ info_ptr->pcal_params = NULL;
+ }
+ info_ptr->valid &= ~PNG_INFO_pCAL;
+ }
+#endif
+
+#ifdef PNG_iCCP_SUPPORTED
+ /* Free any iCCP entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_ICCP)
+#endif
+ {
+ png_free(png_ptr, info_ptr->iccp_name);
+ png_free(png_ptr, info_ptr->iccp_profile);
+ info_ptr->iccp_name = NULL;
+ info_ptr->iccp_profile = NULL;
+ info_ptr->valid &= ~PNG_INFO_iCCP;
+ }
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+ /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_SPLT)
+#endif
+ {
+ if (num != -1)
+ {
+ if (info_ptr->splt_palettes)
+ {
+ png_free(png_ptr, info_ptr->splt_palettes[num].name);
+ png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+ info_ptr->splt_palettes[num].name = NULL;
+ info_ptr->splt_palettes[num].entries = NULL;
+ }
+ }
+ else
+ {
+ if (info_ptr->splt_palettes_num)
+ {
+ int i;
+ for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+ png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+
+ png_free(png_ptr, info_ptr->splt_palettes);
+ info_ptr->splt_palettes = NULL;
+ info_ptr->splt_palettes_num = 0;
+ }
+ info_ptr->valid &= ~PNG_INFO_sPLT;
+ }
+ }
+#endif
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+ if (png_ptr->unknown_chunk.data)
+ {
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+ }
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_UNKN)
+#endif
+ {
+ if (num != -1)
+ {
+ if (info_ptr->unknown_chunks)
+ {
+ png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+ info_ptr->unknown_chunks[num].data = NULL;
+ }
+ }
+ else
+ {
+ int i;
+
+ if (info_ptr->unknown_chunks_num)
+ {
+ for (i = 0; i < (int)info_ptr->unknown_chunks_num; i++)
+ png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+
+ png_free(png_ptr, info_ptr->unknown_chunks);
+ info_ptr->unknown_chunks = NULL;
+ info_ptr->unknown_chunks_num = 0;
+ }
+ }
+ }
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+ /* Free any hIST entry */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
+#else
+ if ((mask & PNG_FREE_HIST) && (png_ptr->flags & PNG_FLAG_FREE_HIST))
+#endif
+ {
+ png_free(png_ptr, info_ptr->hist);
+ info_ptr->hist = NULL;
+ info_ptr->valid &= ~PNG_INFO_hIST;
+#ifndef PNG_FREE_ME_SUPPORTED
+ png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
+#endif
+ }
+#endif
+
+ /* Free any PLTE entry that was internally allocated */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+#else
+ if ((mask & PNG_FREE_PLTE) && (png_ptr->flags & PNG_FLAG_FREE_PLTE))
+#endif
+ {
+ png_zfree(png_ptr, info_ptr->palette);
+ info_ptr->palette = NULL;
+ info_ptr->valid &= ~PNG_INFO_PLTE;
+#ifndef PNG_FREE_ME_SUPPORTED
+ png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
+#endif
+ info_ptr->num_palette = 0;
+ }
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+ /* Free any image bits attached to the info structure */
+#ifdef PNG_FREE_ME_SUPPORTED
+ if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+#else
+ if (mask & PNG_FREE_ROWS)
+#endif
+ {
+ if (info_ptr->row_pointers)
+ {
+ int row;
+ for (row = 0; row < (int)info_ptr->height; row++)
+ {
+ png_free(png_ptr, info_ptr->row_pointers[row]);
+ info_ptr->row_pointers[row] = NULL;
+ }
+ png_free(png_ptr, info_ptr->row_pointers);
+ info_ptr->row_pointers = NULL;
+ }
+ info_ptr->valid &= ~PNG_INFO_IDAT;
+ }
+#endif
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ if (num == -1)
+ info_ptr->free_me &= ~mask;
+ else
+ info_ptr->free_me &= ~(mask & ~PNG_FREE_MUL);
+#endif
+}
+
+/* This is an internal routine to free any memory that the info struct is
+ * pointing to before re-using it or freeing the struct itself. Recall
+ * that png_free() checks for NULL pointers for us.
+ */
+void /* PRIVATE */
+png_info_destroy(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_info_destroy");
+
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_ptr->num_chunk_list)
+ {
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
+ png_ptr->num_chunk_list = 0;
+ }
+#endif
+
+ png_info_init_3(&info_ptr, png_sizeof(png_info));
+}
+#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+/* This function returns a pointer to the io_ptr associated with the user
+ * functions. The application should free any memory associated with this
+ * pointer before png_write_destroy() or png_read_destroy() are called.
+ */
+png_voidp PNGAPI
+png_get_io_ptr(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return (NULL);
+ return (png_ptr->io_ptr);
+}
+
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+#ifdef PNG_STDIO_SUPPORTED
+/* Initialize the default input/output functions for the PNG file. If you
+ * use your own read or write routines, you can call either png_set_read_fn()
+ * or png_set_write_fn() instead of png_init_io(). If you have defined
+ * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
+ * necessarily available.
+ */
+void PNGAPI
+png_init_io(png_structp png_ptr, png_FILE_p fp)
+{
+ png_debug(1, "in png_init_io");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->io_ptr = (png_voidp)fp;
+}
+#endif
+
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+/* Convert the supplied time into an RFC 1123 string suitable for use in
+ * a "Creation Time" or other text-based time string.
+ */
+png_charp PNGAPI
+png_convert_to_rfc1123(png_structp png_ptr, png_timep ptime)
+{
+ static PNG_CONST char short_months[12][4] =
+ {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ if (png_ptr == NULL)
+ return (NULL);
+ if (png_ptr->time_buffer == NULL)
+ {
+ png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
+ png_sizeof(char)));
+ }
+
+#ifdef _WIN32_WCE
+ {
+ wchar_t time_buf[29];
+ wsprintf(time_buf, TEXT("%d %S %d %02d:%02d:%02d +0000"),
+ ptime->day % 32, short_months[(ptime->month - 1) % 12],
+ ptime->year, ptime->hour % 24, ptime->minute % 60,
+ ptime->second % 61);
+ WideCharToMultiByte(CP_ACP, 0, time_buf, -1, png_ptr->time_buffer,
+ 29, NULL, NULL);
+ }
+#else
+#ifdef USE_FAR_KEYWORD
+ {
+ char near_time_buf[29];
+ png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000",
+ ptime->day % 32, short_months[(ptime->month - 1) % 12],
+ ptime->year, ptime->hour % 24, ptime->minute % 60,
+ ptime->second % 61);
+ png_memcpy(png_ptr->time_buffer, near_time_buf,
+ 29*png_sizeof(char));
+ }
+#else
+ png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000",
+ ptime->day % 32, short_months[(ptime->month - 1) % 12],
+ ptime->year, ptime->hour % 24, ptime->minute % 60,
+ ptime->second % 61);
+#endif
+#endif /* _WIN32_WCE */
+ return ((png_charp)png_ptr->time_buffer);
+}
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+
+#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+png_charp PNGAPI
+png_get_copyright(png_structp png_ptr)
+{
+ png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */
+#ifdef PNG_STRING_COPYRIGHT
+ return PNG_STRING_COPYRIGHT
+#else
+#ifdef __STDC__
+ return ((png_charp) PNG_STRING_NEWLINE \
+ "libpng version 1.2.49 - March 29, 2012" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
+ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
+ PNG_STRING_NEWLINE);
+#else
+ return ((png_charp) "libpng version 1.2.49 - March 29, 2012\
+ Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+ Copyright (c) 1996-1997 Andreas Dilger\
+ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.");
+#endif
+#endif
+}
+
+/* The following return the library version as a short string in the
+ * format 1.0.0 through 99.99.99zz. To get the version of *.h files
+ * used with your application, print out PNG_LIBPNG_VER_STRING, which
+ * is defined in png.h.
+ * Note: now there is no difference between png_get_libpng_ver() and
+ * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard,
+ * it is guaranteed that png.c uses the correct version of png.h.
+ */
+png_charp PNGAPI
+png_get_libpng_ver(png_structp png_ptr)
+{
+ /* Version of *.c files used when building libpng */
+ png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */
+ return ((png_charp) PNG_LIBPNG_VER_STRING);
+}
+
+png_charp PNGAPI
+png_get_header_ver(png_structp png_ptr)
+{
+ /* Version of *.h files used when building libpng */
+ png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */
+ return ((png_charp) PNG_LIBPNG_VER_STRING);
+}
+
+png_charp PNGAPI
+png_get_header_version(png_structp png_ptr)
+{
+ /* Returns longer string containing both version and date */
+ png_ptr = png_ptr; /* Silence compiler warning about unused png_ptr */
+#ifdef __STDC__
+ return ((png_charp) PNG_HEADER_VERSION_STRING
+#ifndef PNG_READ_SUPPORTED
+ " (NO READ SUPPORT)"
+#endif
+ PNG_STRING_NEWLINE);
+#else
+ return ((png_charp) PNG_HEADER_VERSION_STRING);
+#endif
+}
+
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+int PNGAPI
+png_handle_as_unknown(png_structp png_ptr, png_bytep chunk_name)
+{
+ /* Check chunk_name and return "keep" value if it's on the list, else 0 */
+ int i;
+ png_bytep p;
+ if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
+ return 0;
+ p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5;
+ for (i = png_ptr->num_chunk_list; i; i--, p -= 5)
+ if (!png_memcmp(chunk_name, p, 4))
+ return ((int)*(p + 4));
+ return 0;
+}
+#endif
+
+/* This function, added to libpng-1.0.6g, is untested. */
+int PNGAPI
+png_reset_zstream(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return Z_STREAM_ERROR;
+ return (inflateReset(&png_ptr->zstream));
+}
+#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+/* This function was added to libpng-1.0.7 */
+png_uint_32 PNGAPI
+png_access_version_number(void)
+{
+ /* Version of *.c files used when building libpng */
+ return((png_uint_32) PNG_LIBPNG_VER);
+}
+
+
+#if defined(PNG_READ_SUPPORTED) && defined(PNG_ASSEMBLER_CODE_SUPPORTED)
+#ifndef PNG_1_0_X
+/* This function was added to libpng 1.2.0 */
+int PNGAPI
+png_mmx_support(void)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ return -1;
+}
+#endif /* PNG_1_0_X */
+#endif /* PNG_READ_SUPPORTED && PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+#ifdef PNG_SIZE_T
+/* Added at libpng version 1.2.6 */
+ PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size));
+png_size_t PNGAPI
+png_convert_size(size_t size)
+{
+ if (size > (png_size_t)-1)
+ PNG_ABORT(); /* We haven't got access to png_ptr, so no png_error() */
+ return ((png_size_t)size);
+}
+#endif /* PNG_SIZE_T */
+
+/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+
+/*
+ * Multiply two 32-bit numbers, V1 and V2, using 32-bit
+ * arithmetic, to produce a 64 bit result in the HI/LO words.
+ *
+ * A B
+ * x C D
+ * ------
+ * AD || BD
+ * AC || CB || 0
+ *
+ * where A and B are the high and low 16-bit words of V1,
+ * C and D are the 16-bit words of V2, AD is the product of
+ * A and D, and X || Y is (X << 16) + Y.
+*/
+
+void /* PRIVATE */
+png_64bit_product (long v1, long v2, unsigned long *hi_product,
+ unsigned long *lo_product)
+{
+ int a, b, c, d;
+ long lo, hi, x, y;
+
+ a = (v1 >> 16) & 0xffff;
+ b = v1 & 0xffff;
+ c = (v2 >> 16) & 0xffff;
+ d = v2 & 0xffff;
+
+ lo = b * d; /* BD */
+ x = a * d + c * b; /* AD + CB */
+ y = ((lo >> 16) & 0xffff) + x;
+
+ lo = (lo & 0xffff) | ((y & 0xffff) << 16);
+ hi = (y >> 16) & 0xffff;
+
+ hi += a * c; /* AC */
+
+ *hi_product = (unsigned long)hi;
+ *lo_product = (unsigned long)lo;
+}
+
+int /* PRIVATE */
+png_check_cHRM_fixed(png_structp png_ptr,
+ png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+ png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+ png_fixed_point blue_x, png_fixed_point blue_y)
+{
+ int ret = 1;
+ unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
+
+ png_debug(1, "in function png_check_cHRM_fixed");
+
+ if (png_ptr == NULL)
+ return 0;
+
+ if (white_x < 0 || white_y <= 0 ||
+ red_x < 0 || red_y < 0 ||
+ green_x < 0 || green_y < 0 ||
+ blue_x < 0 || blue_y < 0)
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set negative chromaticity value");
+ ret = 0;
+ }
+ if (white_x > (png_fixed_point) PNG_UINT_31_MAX ||
+ white_y > (png_fixed_point) PNG_UINT_31_MAX ||
+ red_x > (png_fixed_point) PNG_UINT_31_MAX ||
+ red_y > (png_fixed_point) PNG_UINT_31_MAX ||
+ green_x > (png_fixed_point) PNG_UINT_31_MAX ||
+ green_y > (png_fixed_point) PNG_UINT_31_MAX ||
+ blue_x > (png_fixed_point) PNG_UINT_31_MAX ||
+ blue_y > (png_fixed_point) PNG_UINT_31_MAX )
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set chromaticity value exceeding 21474.83");
+ ret = 0;
+ }
+ if (white_x > 100000L - white_y)
+ {
+ png_warning(png_ptr, "Invalid cHRM white point");
+ ret = 0;
+ }
+ if (red_x > 100000L - red_y)
+ {
+ png_warning(png_ptr, "Invalid cHRM red point");
+ ret = 0;
+ }
+ if (green_x > 100000L - green_y)
+ {
+ png_warning(png_ptr, "Invalid cHRM green point");
+ ret = 0;
+ }
+ if (blue_x > 100000L - blue_y)
+ {
+ png_warning(png_ptr, "Invalid cHRM blue point");
+ ret = 0;
+ }
+
+ png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
+ png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
+
+ if (xy_hi == yx_hi && xy_lo == yx_lo)
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to set cHRM RGB triangle with zero area");
+ ret = 0;
+ }
+
+ return ret;
+}
+#endif /* PNG_CHECK_cHRM_SUPPORTED */
+#endif /* PNG_cHRM_SUPPORTED */
+
+void /* PRIVATE */
+png_check_IHDR(png_structp png_ptr,
+ png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_type, int compression_type,
+ int filter_type)
+{
+ int error = 0;
+
+ /* Check for width and height valid values */
+ if (width == 0)
+ {
+ png_warning(png_ptr, "Image width is zero in IHDR");
+ error = 1;
+ }
+
+ if (height == 0)
+ {
+ png_warning(png_ptr, "Image height is zero in IHDR");
+ error = 1;
+ }
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX)
+#else
+ if (width > PNG_USER_WIDTH_MAX)
+#endif
+ {
+ png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+ error = 1;
+ }
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX)
+#else
+ if (height > PNG_USER_HEIGHT_MAX)
+#endif
+ {
+ png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ error = 1;
+ }
+
+ if (width > PNG_UINT_31_MAX)
+ {
+ png_warning(png_ptr, "Invalid image width in IHDR");
+ error = 1;
+ }
+
+ if ( height > PNG_UINT_31_MAX)
+ {
+ png_warning(png_ptr, "Invalid image height in IHDR");
+ error = 1;
+ }
+
+ if ( width > (PNG_UINT_32_MAX
+ >> 3) /* 8-byte RGBA pixels */
+ - 64 /* bigrowbuf hack */
+ - 1 /* filter byte */
+ - 7*8 /* rounding of width to multiple of 8 pixels */
+ - 8) /* extra max_pixel_depth pad */
+ png_warning(png_ptr, "Width is too large for libpng to process pixels");
+
+ /* Check other values */
+ if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
+ bit_depth != 8 && bit_depth != 16)
+ {
+ png_warning(png_ptr, "Invalid bit depth in IHDR");
+ error = 1;
+ }
+
+ if (color_type < 0 || color_type == 1 ||
+ color_type == 5 || color_type > 6)
+ {
+ png_warning(png_ptr, "Invalid color type in IHDR");
+ error = 1;
+ }
+
+ if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
+ ((color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
+ {
+ png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
+ error = 1;
+ }
+
+ if (interlace_type >= PNG_INTERLACE_LAST)
+ {
+ png_warning(png_ptr, "Unknown interlace method in IHDR");
+ error = 1;
+ }
+
+ if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ {
+ png_warning(png_ptr, "Unknown compression method in IHDR");
+ error = 1;
+ }
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ /* Accept filter_method 64 (intrapixel differencing) only if
+ * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ * 2. Libpng did not read a PNG signature (this filter_method is only
+ * used in PNG datastreams that are embedded in MNG datastreams) and
+ * 3. The application called png_permit_mng_features with a mask that
+ * included PNG_FLAG_MNG_FILTER_64 and
+ * 4. The filter_method is 64 and
+ * 5. The color_type is RGB or RGBA
+ */
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
+ png_ptr->mng_features_permitted)
+ png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
+
+ if (filter_type != PNG_FILTER_TYPE_BASE)
+ {
+ if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
+ ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
+ (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
+ {
+ png_warning(png_ptr, "Unknown filter method in IHDR");
+ error = 1;
+ }
+
+ if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
+ {
+ png_warning(png_ptr, "Invalid filter method in IHDR");
+ error = 1;
+ }
+ }
+
+#else
+ if (filter_type != PNG_FILTER_TYPE_BASE)
+ {
+ png_warning(png_ptr, "Unknown filter method in IHDR");
+ error = 1;
+ }
+#endif
+
+ if (error == 1)
+ png_error(png_ptr, "Invalid IHDR data");
+}
+#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
diff --git a/Source/LibPNG/png.h b/Source/LibPNG/png.h
new file mode 100644
index 0000000..b58c458
--- /dev/null
+++ b/Source/LibPNG/png.h
@@ -0,0 +1,3808 @@
+/* png.h - header file for PNG reference library
+ *
+ * libpng version 1.2.49 - March 29, 2012
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license (See LICENSE, below)
+ *
+ * Authors and maintainers:
+ * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
+ * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
+ * libpng versions 0.97, January 1998, through 1.2.49 - March 29, 2012: Glenn
+ * See also "Contributing Authors", below.
+ *
+ * Note about libpng version numbers:
+ *
+ * Due to various miscommunications, unforeseen code incompatibilities
+ * and occasional factors outside the authors' control, version numbering
+ * on the library has not always been consistent and straightforward.
+ * The following table summarizes matters since version 0.89c, which was
+ * the first widely used release:
+ *
+ * source png.h png.h shared-lib
+ * version string int version
+ * ------- ------ ----- ----------
+ * 0.89c "1.0 beta 3" 0.89 89 1.0.89
+ * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90]
+ * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95]
+ * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96]
+ * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97]
+ * 0.97c 0.97 97 2.0.97
+ * 0.98 0.98 98 2.0.98
+ * 0.99 0.99 98 2.0.99
+ * 0.99a-m 0.99 99 2.0.99
+ * 1.00 1.00 100 2.1.0 [100 should be 10000]
+ * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000]
+ * 1.0.1 png.h string is 10001 2.1.0
+ * 1.0.1a-e identical to the 10002 from here on, the shared library
+ * 1.0.2 source version) 10002 is 2.V where V is the source code
+ * 1.0.2a-b 10003 version, except as noted.
+ * 1.0.3 10003
+ * 1.0.3a-d 10004
+ * 1.0.4 10004
+ * 1.0.4a-f 10005
+ * 1.0.5 (+ 2 patches) 10005
+ * 1.0.5a-d 10006
+ * 1.0.5e-r 10100 (not source compatible)
+ * 1.0.5s-v 10006 (not binary compatible)
+ * 1.0.6 (+ 3 patches) 10006 (still binary incompatible)
+ * 1.0.6d-f 10007 (still binary incompatible)
+ * 1.0.6g 10007
+ * 1.0.6h 10007 10.6h (testing xy.z so-numbering)
+ * 1.0.6i 10007 10.6i
+ * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0)
+ * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible)
+ * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible)
+ * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
+ * 1.0.7 1 10007 (still compatible)
+ * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4
+ * 1.0.8rc1 1 10008 2.1.0.8rc1
+ * 1.0.8 1 10008 2.1.0.8
+ * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6
+ * 1.0.9rc1 1 10009 2.1.0.9rc1
+ * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10
+ * 1.0.9rc2 1 10009 2.1.0.9rc2
+ * 1.0.9 1 10009 2.1.0.9
+ * 1.0.10beta1 1 10010 2.1.0.10beta1
+ * 1.0.10rc1 1 10010 2.1.0.10rc1
+ * 1.0.10 1 10010 2.1.0.10
+ * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3
+ * 1.0.11rc1 1 10011 2.1.0.11rc1
+ * 1.0.11 1 10011 2.1.0.11
+ * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2
+ * 1.0.12rc1 2 10012 2.1.0.12rc1
+ * 1.0.12 2 10012 2.1.0.12
+ * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned)
+ * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2
+ * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5
+ * 1.2.0rc1 3 10200 3.1.2.0rc1
+ * 1.2.0 3 10200 3.1.2.0
+ * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4
+ * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2
+ * 1.2.1 3 10201 3.1.2.1
+ * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6
+ * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1
+ * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1
+ * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1
+ * 1.0.13 10 10013 10.so.0.1.0.13
+ * 1.2.2 12 10202 12.so.0.1.2.2
+ * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6
+ * 1.2.3 12 10203 12.so.0.1.2.3
+ * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3
+ * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1
+ * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1
+ * 1.0.14 10 10014 10.so.0.1.0.14
+ * 1.2.4 13 10204 12.so.0.1.2.4
+ * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2
+ * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3
+ * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3
+ * 1.0.15 10 10015 10.so.0.1.0.15
+ * 1.2.5 13 10205 12.so.0.1.2.5
+ * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4
+ * 1.0.16 10 10016 10.so.0.1.0.16
+ * 1.2.6 13 10206 12.so.0.1.2.6
+ * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2
+ * 1.0.17rc1 10 10017 10.so.0.1.0.17rc1
+ * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1
+ * 1.0.17 10 10017 10.so.0.1.0.17
+ * 1.2.7 13 10207 12.so.0.1.2.7
+ * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5
+ * 1.0.18rc1-5 10 10018 10.so.0.1.0.18rc1-5
+ * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5
+ * 1.0.18 10 10018 10.so.0.1.0.18
+ * 1.2.8 13 10208 12.so.0.1.2.8
+ * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3
+ * 1.2.9beta4-11 13 10209 12.so.0.9[.0]
+ * 1.2.9rc1 13 10209 12.so.0.9[.0]
+ * 1.2.9 13 10209 12.so.0.9[.0]
+ * 1.2.10beta1-8 13 10210 12.so.0.10[.0]
+ * 1.2.10rc1-3 13 10210 12.so.0.10[.0]
+ * 1.2.10 13 10210 12.so.0.10[.0]
+ * 1.2.11beta1-4 13 10211 12.so.0.11[.0]
+ * 1.0.19rc1-5 10 10019 10.so.0.19[.0]
+ * 1.2.11rc1-5 13 10211 12.so.0.11[.0]
+ * 1.0.19 10 10019 10.so.0.19[.0]
+ * 1.2.11 13 10211 12.so.0.11[.0]
+ * 1.0.20 10 10020 10.so.0.20[.0]
+ * 1.2.12 13 10212 12.so.0.12[.0]
+ * 1.2.13beta1 13 10213 12.so.0.13[.0]
+ * 1.0.21 10 10021 10.so.0.21[.0]
+ * 1.2.13 13 10213 12.so.0.13[.0]
+ * 1.2.14beta1-2 13 10214 12.so.0.14[.0]
+ * 1.0.22rc1 10 10022 10.so.0.22[.0]
+ * 1.2.14rc1 13 10214 12.so.0.14[.0]
+ * 1.0.22 10 10022 10.so.0.22[.0]
+ * 1.2.14 13 10214 12.so.0.14[.0]
+ * 1.2.15beta1-6 13 10215 12.so.0.15[.0]
+ * 1.0.23rc1-5 10 10023 10.so.0.23[.0]
+ * 1.2.15rc1-5 13 10215 12.so.0.15[.0]
+ * 1.0.23 10 10023 10.so.0.23[.0]
+ * 1.2.15 13 10215 12.so.0.15[.0]
+ * 1.2.16beta1-2 13 10216 12.so.0.16[.0]
+ * 1.2.16rc1 13 10216 12.so.0.16[.0]
+ * 1.0.24 10 10024 10.so.0.24[.0]
+ * 1.2.16 13 10216 12.so.0.16[.0]
+ * 1.2.17beta1-2 13 10217 12.so.0.17[.0]
+ * 1.0.25rc1 10 10025 10.so.0.25[.0]
+ * 1.2.17rc1-3 13 10217 12.so.0.17[.0]
+ * 1.0.25 10 10025 10.so.0.25[.0]
+ * 1.2.17 13 10217 12.so.0.17[.0]
+ * 1.0.26 10 10026 10.so.0.26[.0]
+ * 1.2.18 13 10218 12.so.0.18[.0]
+ * 1.2.19beta1-31 13 10219 12.so.0.19[.0]
+ * 1.0.27rc1-6 10 10027 10.so.0.27[.0]
+ * 1.2.19rc1-6 13 10219 12.so.0.19[.0]
+ * 1.0.27 10 10027 10.so.0.27[.0]
+ * 1.2.19 13 10219 12.so.0.19[.0]
+ * 1.2.20beta01-04 13 10220 12.so.0.20[.0]
+ * 1.0.28rc1-6 10 10028 10.so.0.28[.0]
+ * 1.2.20rc1-6 13 10220 12.so.0.20[.0]
+ * 1.0.28 10 10028 10.so.0.28[.0]
+ * 1.2.20 13 10220 12.so.0.20[.0]
+ * 1.2.21beta1-2 13 10221 12.so.0.21[.0]
+ * 1.2.21rc1-3 13 10221 12.so.0.21[.0]
+ * 1.0.29 10 10029 10.so.0.29[.0]
+ * 1.2.21 13 10221 12.so.0.21[.0]
+ * 1.2.22beta1-4 13 10222 12.so.0.22[.0]
+ * 1.0.30rc1 10 10030 10.so.0.30[.0]
+ * 1.2.22rc1 13 10222 12.so.0.22[.0]
+ * 1.0.30 10 10030 10.so.0.30[.0]
+ * 1.2.22 13 10222 12.so.0.22[.0]
+ * 1.2.23beta01-05 13 10223 12.so.0.23[.0]
+ * 1.2.23rc01 13 10223 12.so.0.23[.0]
+ * 1.2.23 13 10223 12.so.0.23[.0]
+ * 1.2.24beta01-02 13 10224 12.so.0.24[.0]
+ * 1.2.24rc01 13 10224 12.so.0.24[.0]
+ * 1.2.24 13 10224 12.so.0.24[.0]
+ * 1.2.25beta01-06 13 10225 12.so.0.25[.0]
+ * 1.2.25rc01-02 13 10225 12.so.0.25[.0]
+ * 1.0.31 10 10031 10.so.0.31[.0]
+ * 1.2.25 13 10225 12.so.0.25[.0]
+ * 1.2.26beta01-06 13 10226 12.so.0.26[.0]
+ * 1.2.26rc01 13 10226 12.so.0.26[.0]
+ * 1.2.26 13 10226 12.so.0.26[.0]
+ * 1.0.32 10 10032 10.so.0.32[.0]
+ * 1.2.27beta01-06 13 10227 12.so.0.27[.0]
+ * 1.2.27rc01 13 10227 12.so.0.27[.0]
+ * 1.0.33 10 10033 10.so.0.33[.0]
+ * 1.2.27 13 10227 12.so.0.27[.0]
+ * 1.0.34 10 10034 10.so.0.34[.0]
+ * 1.2.28 13 10228 12.so.0.28[.0]
+ * 1.2.29beta01-03 13 10229 12.so.0.29[.0]
+ * 1.2.29rc01 13 10229 12.so.0.29[.0]
+ * 1.0.35 10 10035 10.so.0.35[.0]
+ * 1.2.29 13 10229 12.so.0.29[.0]
+ * 1.0.37 10 10037 10.so.0.37[.0]
+ * 1.2.30beta01-04 13 10230 12.so.0.30[.0]
+ * 1.0.38rc01-08 10 10038 10.so.0.38[.0]
+ * 1.2.30rc01-08 13 10230 12.so.0.30[.0]
+ * 1.0.38 10 10038 10.so.0.38[.0]
+ * 1.2.30 13 10230 12.so.0.30[.0]
+ * 1.0.39rc01-03 10 10039 10.so.0.39[.0]
+ * 1.2.31rc01-03 13 10231 12.so.0.31[.0]
+ * 1.0.39 10 10039 10.so.0.39[.0]
+ * 1.2.31 13 10231 12.so.0.31[.0]
+ * 1.2.32beta01-02 13 10232 12.so.0.32[.0]
+ * 1.0.40rc01 10 10040 10.so.0.40[.0]
+ * 1.2.32rc01 13 10232 12.so.0.32[.0]
+ * 1.0.40 10 10040 10.so.0.40[.0]
+ * 1.2.32 13 10232 12.so.0.32[.0]
+ * 1.2.33beta01-02 13 10233 12.so.0.33[.0]
+ * 1.2.33rc01-02 13 10233 12.so.0.33[.0]
+ * 1.0.41rc01 10 10041 10.so.0.41[.0]
+ * 1.2.33 13 10233 12.so.0.33[.0]
+ * 1.0.41 10 10041 10.so.0.41[.0]
+ * 1.2.34beta01-07 13 10234 12.so.0.34[.0]
+ * 1.0.42rc01 10 10042 10.so.0.42[.0]
+ * 1.2.34rc01 13 10234 12.so.0.34[.0]
+ * 1.0.42 10 10042 10.so.0.42[.0]
+ * 1.2.34 13 10234 12.so.0.34[.0]
+ * 1.2.35beta01-03 13 10235 12.so.0.35[.0]
+ * 1.0.43rc01-02 10 10043 10.so.0.43[.0]
+ * 1.2.35rc01-02 13 10235 12.so.0.35[.0]
+ * 1.0.43 10 10043 10.so.0.43[.0]
+ * 1.2.35 13 10235 12.so.0.35[.0]
+ * 1.2.36beta01-05 13 10236 12.so.0.36[.0]
+ * 1.2.36rc01 13 10236 12.so.0.36[.0]
+ * 1.0.44 10 10044 10.so.0.44[.0]
+ * 1.2.36 13 10236 12.so.0.36[.0]
+ * 1.2.37beta01-03 13 10237 12.so.0.37[.0]
+ * 1.2.37rc01 13 10237 12.so.0.37[.0]
+ * 1.2.37 13 10237 12.so.0.37[.0]
+ * 1.0.45 10 10045 12.so.0.45[.0]
+ * 1.0.46 10 10046 10.so.0.46[.0]
+ * 1.2.38beta01 13 10238 12.so.0.38[.0]
+ * 1.2.38rc01-03 13 10238 12.so.0.38[.0]
+ * 1.0.47 10 10047 10.so.0.47[.0]
+ * 1.2.38 13 10238 12.so.0.38[.0]
+ * 1.2.39beta01-05 13 10239 12.so.0.39[.0]
+ * 1.2.39rc01 13 10239 12.so.0.39[.0]
+ * 1.0.48 10 10048 10.so.0.48[.0]
+ * 1.2.39 13 10239 12.so.0.39[.0]
+ * 1.2.40beta01 13 10240 12.so.0.40[.0]
+ * 1.2.40rc01 13 10240 12.so.0.40[.0]
+ * 1.0.49 10 10049 10.so.0.49[.0]
+ * 1.2.40 13 10240 12.so.0.40[.0]
+ * 1.2.41beta01-18 13 10241 12.so.0.41[.0]
+ * 1.0.51rc01 10 10051 10.so.0.51[.0]
+ * 1.2.41rc01-03 13 10241 12.so.0.41[.0]
+ * 1.0.51 10 10051 10.so.0.51[.0]
+ * 1.2.41 13 10241 12.so.0.41[.0]
+ * 1.2.42beta01-02 13 10242 12.so.0.42[.0]
+ * 1.2.42rc01-05 13 10242 12.so.0.42[.0]
+ * 1.0.52 10 10052 10.so.0.52[.0]
+ * 1.2.42 13 10242 12.so.0.42[.0]
+ * 1.2.43beta01-05 13 10243 12.so.0.43[.0]
+ * 1.0.53rc01-02 10 10053 10.so.0.53[.0]
+ * 1.2.43rc01-02 13 10243 12.so.0.43[.0]
+ * 1.0.53 10 10053 10.so.0.53[.0]
+ * 1.2.43 13 10243 12.so.0.43[.0]
+ * 1.2.44beta01-03 13 10244 12.so.0.44[.0]
+ * 1.2.44rc01-03 13 10244 12.so.0.44[.0]
+ * 1.2.44 13 10244 12.so.0.44[.0]
+ * 1.2.45beta01-03 13 10245 12.so.0.45[.0]
+ * 1.0.55rc01 10 10055 10.so.0.55[.0]
+ * 1.2.45rc01 13 10245 12.so.0.45[.0]
+ * 1.0.55 10 10055 10.so.0.55[.0]
+ * 1.2.45 13 10245 12.so.0.45[.0]
+ * 1.2.46rc01-02 13 10246 12.so.0.46[.0]
+ * 1.0.56 10 10056 10.so.0.56[.0]
+ * 1.2.46 13 10246 12.so.0.46[.0]
+ * 1.2.47beta01 13 10247 12.so.0.47[.0]
+ * 1.2.47rc01 13 10247 12.so.0.47[.0]
+ * 1.0.57rc01 10 10057 10.so.0.57[.0]
+ * 1.2.47 13 10247 12.so.0.47[.0]
+ * 1.0.57 10 10057 10.so.0.57[.0]
+ * 1.2.48beta01 13 10248 12.so.0.48[.0]
+ * 1.2.48rc01-02 13 10248 12.so.0.48[.0]
+ * 1.0.58 10 10058 10.so.0.58[.0]
+ * 1.2.48 13 10248 12.so.0.48[.0]
+ * 1.2.49rc01 13 10249 12.so.0.49[.0]
+ * 1.0.59 10 10059 10.so.0.59[.0]
+ * 1.2.49 13 10249 12.so.0.49[.0]
+ *
+ * Henceforth the source version will match the shared-library major
+ * and minor numbers; the shared-library major version number will be
+ * used for changes in backward compatibility, as it is intended. The
+ * PNG_LIBPNG_VER macro, which is not used within libpng but is available
+ * for applications, is an unsigned integer of the form xyyzz corresponding
+ * to the source version x.y.z (leading zeros in y and z). Beta versions
+ * were given the previous public release number plus a letter, until
+ * version 1.0.6j; from then on they were given the upcoming public
+ * release number plus "betaNN" or "rcNN".
+ *
+ * Binary incompatibility exists only when applications make direct access
+ * to the info_ptr or png_ptr members through png.h, and the compiled
+ * application is loaded with a different version of the library.
+ *
+ * DLLNUM will change each time there are forward or backward changes
+ * in binary compatibility (e.g., when a new feature is added).
+ *
+ * See libpng.txt or libpng.3 for more information. The PNG specification
+ * is available as a W3C Recommendation and as an ISO Specification,
+ * <http://www.w3.org/TR/2003/REC-PNG-20031110/
+ */
+
+/*
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ *
+ * If you modify libpng you may insert additional notices immediately following
+ * this sentence.
+ *
+ * This code is released under the libpng license.
+ *
+ * libpng versions 1.2.6, August 15, 2004, through 1.2.49, March 29, 2012, are
+ * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.2.5
+ * with the following individual added to the list of Contributing Authors:
+ *
+ * Cosmin Truta
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.2.5, October 3, 2002, are
+ * Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-1.0.6
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Gilles Vollant
+ *
+ * and with the following additions to the disclaimer:
+ *
+ * There is no warranty against interference with your enjoyment of the
+ * library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is with
+ * the user.
+ *
+ * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
+ * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are
+ * distributed according to the same disclaimer and license as libpng-0.96,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
+ *
+ * libpng versions 0.89, June 1996, through 0.96, May 1997, are
+ * Copyright (c) 1996, 1997 Andreas Dilger
+ * Distributed according to the same disclaimer and license as libpng-0.88,
+ * with the following individuals added to the list of Contributing Authors:
+ *
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
+ *
+ * libpng versions 0.5, May 1995, through 0.88, January 1996, are
+ * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * For the purposes of this copyright and license, "Contributing Authors"
+ * is defined as the following set of individuals:
+ *
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing Authors
+ * and Group 42, Inc. disclaim all warranties, expressed or implied,
+ * including, without limitation, the warranties of merchantability and of
+ * fitness for any purpose. The Contributing Authors and Group 42, Inc.
+ * assume no liability for direct, indirect, incidental, special, exemplary,
+ * or consequential damages, which may result from the use of the PNG
+ * Reference Library, even if advised of the possibility of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute this
+ * source code, or portions hereof, for any purpose, without fee, subject
+ * to the following restrictions:
+ *
+ * 1. The origin of this source code must not be misrepresented.
+ *
+ * 2. Altered versions must be plainly marked as such and
+ * must not be misrepresented as being the original source.
+ *
+ * 3. This Copyright notice may not be removed or altered from
+ * any source or altered source distribution.
+ *
+ * The Contributing Authors and Group 42, Inc. specifically permit, without
+ * fee, and encourage the use of this source code as a component to
+ * supporting the PNG file format in commercial products. If you use this
+ * source code in a product, acknowledgment is not required but would be
+ * appreciated.
+ */
+
+/*
+ * A "png_get_copyright" function is available, for convenient use in "about"
+ * boxes and the like:
+ *
+ * printf("%s",png_get_copyright(NULL));
+ *
+ * Also, the PNG logo (in PNG format, of course) is supplied in the
+ * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+ */
+
+/*
+ * Libpng is OSI Certified Open Source Software. OSI Certified is a
+ * certification mark of the Open Source Initiative.
+ */
+
+/*
+ * The contributing authors would like to thank all those who helped
+ * with testing, bug fixes, and patience. This wouldn't have been
+ * possible without all of you.
+ *
+ * Thanks to Frank J. T. Wojcik for helping with the documentation.
+ */
+
+/*
+ * Y2K compliance in libpng:
+ * =========================
+ *
+ * March 29, 2012
+ *
+ * Since the PNG Development group is an ad-hoc body, we can't make
+ * an official declaration.
+ *
+ * This is your unofficial assurance that libpng from version 0.71 and
+ * upward through 1.2.49 are Y2K compliant. It is my belief that earlier
+ * versions were also Y2K compliant.
+ *
+ * Libpng only has three year fields. One is a 2-byte unsigned integer
+ * that will hold years up to 65535. The other two hold the date in text
+ * format, and will hold years up to 9999.
+ *
+ * The integer is
+ * "png_uint_16 year" in png_time_struct.
+ *
+ * The strings are
+ * "png_charp time_buffer" in png_struct and
+ * "near_time_buffer", which is a local character string in png.c.
+ *
+ * There are seven time-related functions:
+ * png.c: png_convert_to_rfc_1123() in png.c
+ * (formerly png_convert_to_rfc_1152() in error)
+ * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
+ * png_convert_from_time_t() in pngwrite.c
+ * png_get_tIME() in pngget.c
+ * png_handle_tIME() in pngrutil.c, called in pngread.c
+ * png_set_tIME() in pngset.c
+ * png_write_tIME() in pngwutil.c, called in pngwrite.c
+ *
+ * All handle dates properly in a Y2K environment. The
+ * png_convert_from_time_t() function calls gmtime() to convert from system
+ * clock time, which returns (year - 1900), which we properly convert to
+ * the full 4-digit year. There is a possibility that applications using
+ * libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ * function, or that they are incorrectly passing only a 2-digit year
+ * instead of "year - 1900" into the png_convert_from_struct_tm() function,
+ * but this is not under our control. The libpng documentation has always
+ * stated that it works with 4-digit years, and the APIs have been
+ * documented as such.
+ *
+ * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
+ * integer to hold the year, and can hold years as large as 65535.
+ *
+ * zlib, upon which libpng depends, is also Y2K compliant. It contains
+ * no date-related code.
+ *
+ * Glenn Randers-Pehrson
+ * libpng maintainer
+ * PNG Development Group
+ */
+
+#ifndef PNG_H
+#define PNG_H
+
+/* This is not the place to learn how to use libpng. The file libpng.txt
+ * describes how to use libpng, and the file example.c summarizes it
+ * with some code on which to build. This file is useful for looking
+ * at the actual function definitions and structure components.
+ */
+
+/* Version information for png.h - this should match the version in png.c */
+#define PNG_LIBPNG_VER_STRING "1.2.49"
+#define PNG_HEADER_VERSION_STRING \
+ " libpng version 1.2.49 - March 29, 2012\n"
+
+#define PNG_LIBPNG_VER_SONUM 0
+#define PNG_LIBPNG_VER_DLLNUM 13
+
+/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
+#define PNG_LIBPNG_VER_MAJOR 1
+#define PNG_LIBPNG_VER_MINOR 2
+#define PNG_LIBPNG_VER_RELEASE 49
+/* This should match the numeric part of the final component of
+ * PNG_LIBPNG_VER_STRING, omitting any leading zero:
+ */
+
+#define PNG_LIBPNG_VER_BUILD 0
+
+/* Release Status */
+#define PNG_LIBPNG_BUILD_ALPHA 1
+#define PNG_LIBPNG_BUILD_BETA 2
+#define PNG_LIBPNG_BUILD_RC 3
+#define PNG_LIBPNG_BUILD_STABLE 4
+#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7
+
+/* Release-Specific Flags */
+#define PNG_LIBPNG_BUILD_PATCH 8 /* Can be OR'ed with
+ PNG_LIBPNG_BUILD_STABLE only */
+#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with
+ PNG_LIBPNG_BUILD_SPECIAL */
+#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
+ PNG_LIBPNG_BUILD_PRIVATE */
+
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
+
+/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
+ * We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
+ * version 1.0.0 was mis-numbered 100 instead of 10000). From
+ * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
+ */
+#define PNG_LIBPNG_VER 10249 /* 1.2.49 */
+
+#ifndef PNG_VERSION_INFO_ONLY
+/* Include the compression library's header */
+#include "zlib.h"
+#endif
+
+/* Include all user configurable info, including optional assembler routines */
+#include "pngconf.h"
+
+/*
+ * Added at libpng-1.2.8 */
+/* Ref MSDN: Private as priority over Special
+ * VS_FF_PRIVATEBUILD File *was not* built using standard release
+ * procedures. If this value is given, the StringFileInfo block must
+ * contain a PrivateBuild string.
+ *
+ * VS_FF_SPECIALBUILD File *was* built by the original company using
+ * standard release procedures but is a variation of the standard
+ * file of the same version number. If this value is given, the
+ * StringFileInfo block must contain a SpecialBuild string.
+ */
+
+#ifdef PNG_USER_PRIVATEBUILD
+# define PNG_LIBPNG_BUILD_TYPE \
+ (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE)
+#else
+# ifdef PNG_LIBPNG_SPECIALBUILD
+# define PNG_LIBPNG_BUILD_TYPE \
+ (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL)
+# else
+# define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE)
+# endif
+#endif
+
+#ifndef PNG_VERSION_INFO_ONLY
+
+/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* This file is arranged in several sections. The first section contains
+ * structure and type definitions. The second section contains the external
+ * library functions, while the third has the internal library functions,
+ * which applications aren't expected to use directly.
+ */
+
+#ifndef PNG_NO_TYPECAST_NULL
+#define int_p_NULL (int *)NULL
+#define png_bytep_NULL (png_bytep)NULL
+#define png_bytepp_NULL (png_bytepp)NULL
+#define png_doublep_NULL (png_doublep)NULL
+#define png_error_ptr_NULL (png_error_ptr)NULL
+#define png_flush_ptr_NULL (png_flush_ptr)NULL
+#define png_free_ptr_NULL (png_free_ptr)NULL
+#define png_infopp_NULL (png_infopp)NULL
+#define png_malloc_ptr_NULL (png_malloc_ptr)NULL
+#define png_read_status_ptr_NULL (png_read_status_ptr)NULL
+#define png_rw_ptr_NULL (png_rw_ptr)NULL
+#define png_structp_NULL (png_structp)NULL
+#define png_uint_16p_NULL (png_uint_16p)NULL
+#define png_voidp_NULL (png_voidp)NULL
+#define png_write_status_ptr_NULL (png_write_status_ptr)NULL
+#else
+#define int_p_NULL NULL
+#define png_bytep_NULL NULL
+#define png_bytepp_NULL NULL
+#define png_doublep_NULL NULL
+#define png_error_ptr_NULL NULL
+#define png_flush_ptr_NULL NULL
+#define png_free_ptr_NULL NULL
+#define png_infopp_NULL NULL
+#define png_malloc_ptr_NULL NULL
+#define png_read_status_ptr_NULL NULL
+#define png_rw_ptr_NULL NULL
+#define png_structp_NULL NULL
+#define png_uint_16p_NULL NULL
+#define png_voidp_NULL NULL
+#define png_write_status_ptr_NULL NULL
+#endif
+
+/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* Version information for C files, stored in png.c. This had better match
+ * the version above.
+ */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (PNG_CONST char) png_libpng_ver[18];
+ /* Need room for 99.99.99beta99z */
+#else
+#define png_libpng_ver png_get_header_ver(NULL)
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+/* This was removed in version 1.0.5c */
+/* Structures to facilitate easy interlacing. See png.c for more details */
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_start[7];
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_inc[7];
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_ystart[7];
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_yinc[7];
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_mask[7];
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_dsp_mask[7];
+/* This isn't currently used. If you need it, see png.c for more details.
+PNG_EXPORT_VAR (PNG_CONST int FARDATA) png_pass_height[7];
+*/
+#endif
+
+#endif /* PNG_NO_EXTERN */
+
+/* Three color definitions. The order of the red, green, and blue, (and the
+ * exact size) is not important, although the size of the fields need to
+ * be png_byte or png_uint_16 (as defined below).
+ */
+typedef struct png_color_struct
+{
+ png_byte red;
+ png_byte green;
+ png_byte blue;
+} png_color;
+typedef png_color FAR * png_colorp;
+typedef png_color FAR * FAR * png_colorpp;
+
+typedef struct png_color_16_struct
+{
+ png_byte index; /* used for palette files */
+ png_uint_16 red; /* for use in red green blue files */
+ png_uint_16 green;
+ png_uint_16 blue;
+ png_uint_16 gray; /* for use in grayscale files */
+} png_color_16;
+typedef png_color_16 FAR * png_color_16p;
+typedef png_color_16 FAR * FAR * png_color_16pp;
+
+typedef struct png_color_8_struct
+{
+ png_byte red; /* for use in red green blue files */
+ png_byte green;
+ png_byte blue;
+ png_byte gray; /* for use in grayscale files */
+ png_byte alpha; /* for alpha channel files */
+} png_color_8;
+typedef png_color_8 FAR * png_color_8p;
+typedef png_color_8 FAR * FAR * png_color_8pp;
+
+/*
+ * The following two structures are used for the in-core representation
+ * of sPLT chunks.
+ */
+typedef struct png_sPLT_entry_struct
+{
+ png_uint_16 red;
+ png_uint_16 green;
+ png_uint_16 blue;
+ png_uint_16 alpha;
+ png_uint_16 frequency;
+} png_sPLT_entry;
+typedef png_sPLT_entry FAR * png_sPLT_entryp;
+typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp;
+
+/* When the depth of the sPLT palette is 8 bits, the color and alpha samples
+ * occupy the LSB of their respective members, and the MSB of each member
+ * is zero-filled. The frequency member always occupies the full 16 bits.
+ */
+
+typedef struct png_sPLT_struct
+{
+ png_charp name; /* palette name */
+ png_byte depth; /* depth of palette samples */
+ png_sPLT_entryp entries; /* palette entries */
+ png_int_32 nentries; /* number of palette entries */
+} png_sPLT_t;
+typedef png_sPLT_t FAR * png_sPLT_tp;
+typedef png_sPLT_t FAR * FAR * png_sPLT_tpp;
+
+#ifdef PNG_TEXT_SUPPORTED
+/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
+ * and whether that contents is compressed or not. The "key" field
+ * points to a regular zero-terminated C string. The "text", "lang", and
+ * "lang_key" fields can be regular C strings, empty strings, or NULL pointers.
+ * However, the * structure returned by png_get_text() will always contain
+ * regular zero-terminated C strings (possibly empty), never NULL pointers,
+ * so they can be safely used in printf() and other string-handling functions.
+ */
+typedef struct png_text_struct
+{
+ int compression; /* compression value:
+ -1: tEXt, none
+ 0: zTXt, deflate
+ 1: iTXt, none
+ 2: iTXt, deflate */
+ png_charp key; /* keyword, 1-79 character description of "text" */
+ png_charp text; /* comment, may be an empty string (ie "")
+ or a NULL pointer */
+ png_size_t text_length; /* length of the text string */
+#ifdef PNG_iTXt_SUPPORTED
+ png_size_t itxt_length; /* length of the itxt string */
+ png_charp lang; /* language code, 0-79 characters
+ or a NULL pointer */
+ png_charp lang_key; /* keyword translated UTF-8 string, 0 or more
+ chars or a NULL pointer */
+#endif
+} png_text;
+typedef png_text FAR * png_textp;
+typedef png_text FAR * FAR * png_textpp;
+#endif
+
+/* Supported compression types for text in PNG files (tEXt, and zTXt).
+ * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed.
+ */
+#define PNG_TEXT_COMPRESSION_NONE_WR -3
+#define PNG_TEXT_COMPRESSION_zTXt_WR -2
+#define PNG_TEXT_COMPRESSION_NONE -1
+#define PNG_TEXT_COMPRESSION_zTXt 0
+#define PNG_ITXT_COMPRESSION_NONE 1
+#define PNG_ITXT_COMPRESSION_zTXt 2
+#define PNG_TEXT_COMPRESSION_LAST 3 /* Not a valid value */
+
+/* png_time is a way to hold the time in an machine independent way.
+ * Two conversions are provided, both from time_t and struct tm. There
+ * is no portable way to convert to either of these structures, as far
+ * as I know. If you know of a portable way, send it to me. As a side
+ * note - PNG has always been Year 2000 compliant!
+ */
+typedef struct png_time_struct
+{
+ png_uint_16 year; /* full year, as in, 1995 */
+ png_byte month; /* month of year, 1 - 12 */
+ png_byte day; /* day of month, 1 - 31 */
+ png_byte hour; /* hour of day, 0 - 23 */
+ png_byte minute; /* minute of hour, 0 - 59 */
+ png_byte second; /* second of minute, 0 - 60 (for leap seconds) */
+} png_time;
+typedef png_time FAR * png_timep;
+typedef png_time FAR * FAR * png_timepp;
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+/* png_unknown_chunk is a structure to hold queued chunks for which there is
+ * no specific support. The idea is that we can use this to queue
+ * up private chunks for output even though the library doesn't actually
+ * know about their semantics.
+ */
+#define PNG_CHUNK_NAME_LENGTH 5
+typedef struct png_unknown_chunk_t
+{
+ png_byte name[PNG_CHUNK_NAME_LENGTH];
+ png_byte *data;
+ png_size_t size;
+
+ /* libpng-using applications should NOT directly modify this byte. */
+ png_byte location; /* mode of operation at read time */
+}
+png_unknown_chunk;
+typedef png_unknown_chunk FAR * png_unknown_chunkp;
+typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
+#endif
+
+/* png_info is a structure that holds the information in a PNG file so
+ * that the application can find out the characteristics of the image.
+ * If you are reading the file, this structure will tell you what is
+ * in the PNG file. If you are writing the file, fill in the information
+ * you want to put into the PNG file, then call png_write_info().
+ * The names chosen should be very close to the PNG specification, so
+ * consult that document for information about the meaning of each field.
+ *
+ * With libpng < 0.95, it was only possible to directly set and read the
+ * the values in the png_info_struct, which meant that the contents and
+ * order of the values had to remain fixed. With libpng 0.95 and later,
+ * however, there are now functions that abstract the contents of
+ * png_info_struct from the application, so this makes it easier to use
+ * libpng with dynamic libraries, and even makes it possible to use
+ * libraries that don't have all of the libpng ancillary chunk-handing
+ * functionality.
+ *
+ * In any case, the order of the parameters in png_info_struct should NOT
+ * be changed for as long as possible to keep compatibility with applications
+ * that use the old direct-access method with png_info_struct.
+ *
+ * The following members may have allocated storage attached that should be
+ * cleaned up before the structure is discarded: palette, trans, text,
+ * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
+ * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these
+ * are automatically freed when the info structure is deallocated, if they were
+ * allocated internally by libpng. This behavior can be changed by means
+ * of the png_data_freer() function.
+ *
+ * More allocation details: all the chunk-reading functions that
+ * change these members go through the corresponding png_set_*
+ * functions. A function to clear these members is available: see
+ * png_free_data(). The png_set_* functions do not depend on being
+ * able to point info structure members to any of the storage they are
+ * passed (they make their own copies), EXCEPT that the png_set_text
+ * functions use the same storage passed to them in the text_ptr or
+ * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
+ * functions do not make their own copies.
+ */
+typedef struct png_info_struct
+{
+ /* The following are necessary for every PNG file */
+ png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels (from IHDR) */
+ png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels (from IHDR) */
+ png_uint_32 valid PNG_DEPSTRUCT; /* valid chunk data (see PNG_INFO_ below) */
+ png_uint_32 rowbytes PNG_DEPSTRUCT; /* bytes needed to hold an untransformed row */
+ png_colorp palette PNG_DEPSTRUCT; /* array of color values (valid & PNG_INFO_PLTE) */
+ png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in "palette" (PLTE) */
+ png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparent palette color (tRNS) */
+ png_byte bit_depth PNG_DEPSTRUCT; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
+ png_byte color_type PNG_DEPSTRUCT; /* see PNG_COLOR_TYPE_ below (from IHDR) */
+ /* The following three should have been named *_method not *_type */
+ png_byte compression_type PNG_DEPSTRUCT; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
+ png_byte filter_type PNG_DEPSTRUCT; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
+ png_byte interlace_type PNG_DEPSTRUCT; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+
+ /* The following is informational only on read, and not used on writes. */
+ png_byte channels PNG_DEPSTRUCT; /* number of data channels per pixel (1, 2, 3, 4) */
+ png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */
+ png_byte spare_byte PNG_DEPSTRUCT; /* to align the data, and for future use */
+ png_byte signature[8] PNG_DEPSTRUCT; /* magic bytes read by libpng from start of file */
+
+ /* The rest of the data is optional. If you are reading, check the
+ * valid field to see if the information in these are valid. If you
+ * are writing, set the valid field to those chunks you want written,
+ * and initialize the appropriate fields below.
+ */
+
+#if defined(PNG_gAMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+ /* The gAMA chunk describes the gamma characteristics of the system
+ * on which the image was created, normally in the range [1.0, 2.5].
+ * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
+ */
+ float gamma PNG_DEPSTRUCT; /* gamma value of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+ /* GR-P, 0.96a */
+ /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
+ png_byte srgb_intent PNG_DEPSTRUCT; /* sRGB rendering intent [0, 1, 2, or 3] */
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED
+ /* The tEXt, and zTXt chunks contain human-readable textual data in
+ * uncompressed, compressed, and optionally compressed forms, respectively.
+ * The data in "text" is an array of pointers to uncompressed,
+ * null-terminated C strings. Each chunk has a keyword that describes the
+ * textual data contained in that chunk. Keywords are not required to be
+ * unique, and the text string may be empty. Any number of text chunks may
+ * be in an image.
+ */
+ int num_text PNG_DEPSTRUCT; /* number of comments read/to write */
+ int max_text PNG_DEPSTRUCT; /* current size of text array */
+ png_textp text PNG_DEPSTRUCT; /* array of comments read/to write */
+#endif /* PNG_TEXT_SUPPORTED */
+
+#ifdef PNG_tIME_SUPPORTED
+ /* The tIME chunk holds the last time the displayed image data was
+ * modified. See the png_time struct for the contents of this struct.
+ */
+ png_time mod_time PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_sBIT_SUPPORTED
+ /* The sBIT chunk specifies the number of significant high-order bits
+ * in the pixel data. Values are in the range [1, bit_depth], and are
+ * only specified for the channels in the pixel data. The contents of
+ * the low-order bits is not specified. Data is valid if
+ * (valid & PNG_INFO_sBIT) is non-zero.
+ */
+ png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in color channels */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
+defined(PNG_READ_BACKGROUND_SUPPORTED)
+ /* The tRNS chunk supplies transparency data for paletted images and
+ * other image types that don't need a full alpha channel. There are
+ * "num_trans" transparency values for a paletted image, stored in the
+ * same order as the palette colors, starting from index 0. Values
+ * for the data are in the range [0, 255], ranging from fully transparent
+ * to fully opaque, respectively. For non-paletted images, there is a
+ * single color specified that should be treated as fully transparent.
+ * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
+ */
+ png_bytep trans PNG_DEPSTRUCT; /* transparent values for paletted image */
+ png_color_16 trans_values PNG_DEPSTRUCT; /* transparent color for non-palette image */
+#endif
+
+#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ /* The bKGD chunk gives the suggested image background color if the
+ * display program does not have its own background color and the image
+ * is needs to composited onto a background before display. The colors
+ * in "background" are normally in the same color space/depth as the
+ * pixel data. Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
+ */
+ png_color_16 background PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_oFFs_SUPPORTED
+ /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
+ * and downwards from the top-left corner of the display, page, or other
+ * application-specific co-ordinate space. See the PNG_OFFSET_ defines
+ * below for the unit types. Valid if (valid & PNG_INFO_oFFs) non-zero.
+ */
+ png_int_32 x_offset PNG_DEPSTRUCT; /* x offset on page */
+ png_int_32 y_offset PNG_DEPSTRUCT; /* y offset on page */
+ png_byte offset_unit_type PNG_DEPSTRUCT; /* offset units type */
+#endif
+
+#ifdef PNG_pHYs_SUPPORTED
+ /* The pHYs chunk gives the physical pixel density of the image for
+ * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
+ * defines below). Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
+ */
+ png_uint_32 x_pixels_per_unit PNG_DEPSTRUCT; /* horizontal pixel density */
+ png_uint_32 y_pixels_per_unit PNG_DEPSTRUCT; /* vertical pixel density */
+ png_byte phys_unit_type PNG_DEPSTRUCT; /* resolution type (see PNG_RESOLUTION_ below) */
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+ /* The hIST chunk contains the relative frequency or importance of the
+ * various palette entries, so that a viewer can intelligently select a
+ * reduced-color palette, if required. Data is an array of "num_palette"
+ * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
+ * is non-zero.
+ */
+ png_uint_16p hist PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+ /* The cHRM chunk describes the CIE color characteristics of the monitor
+ * on which the PNG was created. This data allows the viewer to do gamut
+ * mapping of the input image to ensure that the viewer sees the same
+ * colors in the image as the creator. Values are in the range
+ * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero.
+ */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float x_white PNG_DEPSTRUCT;
+ float y_white PNG_DEPSTRUCT;
+ float x_red PNG_DEPSTRUCT;
+ float y_red PNG_DEPSTRUCT;
+ float x_green PNG_DEPSTRUCT;
+ float y_green PNG_DEPSTRUCT;
+ float x_blue PNG_DEPSTRUCT;
+ float y_blue PNG_DEPSTRUCT;
+#endif
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+ /* The pCAL chunk describes a transformation between the stored pixel
+ * values and original physical data values used to create the image.
+ * The integer range [0, 2^bit_depth - 1] maps to the floating-point
+ * range given by [pcal_X0, pcal_X1], and are further transformed by a
+ * (possibly non-linear) transformation function given by "pcal_type"
+ * and "pcal_params" into "pcal_units". Please see the PNG_EQUATION_
+ * defines below, and the PNG-Group's PNG extensions document for a
+ * complete description of the transformations and how they should be
+ * implemented, and for a description of the ASCII parameter strings.
+ * Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
+ */
+ png_charp pcal_purpose PNG_DEPSTRUCT; /* pCAL chunk description string */
+ png_int_32 pcal_X0 PNG_DEPSTRUCT; /* minimum value */
+ png_int_32 pcal_X1 PNG_DEPSTRUCT; /* maximum value */
+ png_charp pcal_units PNG_DEPSTRUCT; /* Latin-1 string giving physical units */
+ png_charpp pcal_params PNG_DEPSTRUCT; /* ASCII strings containing parameter values */
+ png_byte pcal_type PNG_DEPSTRUCT; /* equation type (see PNG_EQUATION_ below) */
+ png_byte pcal_nparams PNG_DEPSTRUCT; /* number of parameters given in pcal_params */
+#endif
+
+/* New members added in libpng-1.0.6 */
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is responsible for freeing */
+#endif
+
+#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+ /* Storage for unknown chunks that the library doesn't recognize. */
+ png_unknown_chunkp unknown_chunks PNG_DEPSTRUCT;
+ png_size_t unknown_chunks_num PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_iCCP_SUPPORTED
+ /* iCCP chunk data. */
+ png_charp iccp_name PNG_DEPSTRUCT; /* profile name */
+ png_charp iccp_profile PNG_DEPSTRUCT; /* International Color Consortium profile data */
+ /* Note to maintainer: should be png_bytep */
+ png_uint_32 iccp_proflen PNG_DEPSTRUCT; /* ICC profile data length */
+ png_byte iccp_compression PNG_DEPSTRUCT; /* Always zero */
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+ /* Data on sPLT chunks (there may be more than one). */
+ png_sPLT_tp splt_palettes PNG_DEPSTRUCT;
+ png_uint_32 splt_palettes_num PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_sCAL_SUPPORTED
+ /* The sCAL chunk describes the actual physical dimensions of the
+ * subject matter of the graphic. The chunk contains a unit specification
+ * a byte value, and two ASCII strings representing floating-point
+ * values. The values are width and height corresponsing to one pixel
+ * in the image. This external representation is converted to double
+ * here. Data values are valid if (valid & PNG_INFO_sCAL) is non-zero.
+ */
+ png_byte scal_unit PNG_DEPSTRUCT; /* unit of physical scale */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ double scal_pixel_width PNG_DEPSTRUCT; /* width of one pixel */
+ double scal_pixel_height PNG_DEPSTRUCT; /* height of one pixel */
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_charp scal_s_width PNG_DEPSTRUCT; /* string containing height */
+ png_charp scal_s_height PNG_DEPSTRUCT; /* string containing width */
+#endif
+#endif
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+ /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */
+ /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
+ png_bytepp row_pointers PNG_DEPSTRUCT; /* the image bits */
+#endif
+
+#if defined(PNG_FIXED_POINT_SUPPORTED) && defined(PNG_gAMA_SUPPORTED)
+ png_fixed_point int_gamma PNG_DEPSTRUCT; /* gamma of image, if (valid & PNG_INFO_gAMA) */
+#endif
+
+#if defined(PNG_cHRM_SUPPORTED) && defined(PNG_FIXED_POINT_SUPPORTED)
+ png_fixed_point int_x_white PNG_DEPSTRUCT;
+ png_fixed_point int_y_white PNG_DEPSTRUCT;
+ png_fixed_point int_x_red PNG_DEPSTRUCT;
+ png_fixed_point int_y_red PNG_DEPSTRUCT;
+ png_fixed_point int_x_green PNG_DEPSTRUCT;
+ png_fixed_point int_y_green PNG_DEPSTRUCT;
+ png_fixed_point int_x_blue PNG_DEPSTRUCT;
+ png_fixed_point int_y_blue PNG_DEPSTRUCT;
+#endif
+
+} png_info;
+
+typedef png_info FAR * png_infop;
+typedef png_info FAR * FAR * png_infopp;
+
+/* Maximum positive integer used in PNG is (2^31)-1 */
+#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
+#define PNG_UINT_32_MAX ((png_uint_32)(-1))
+#define PNG_SIZE_MAX ((png_size_t)(-1))
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* PNG_MAX_UINT is deprecated; use PNG_UINT_31_MAX instead. */
+#define PNG_MAX_UINT PNG_UINT_31_MAX
+#endif
+
+/* These describe the color_type field in png_info. */
+/* color type masks */
+#define PNG_COLOR_MASK_PALETTE 1
+#define PNG_COLOR_MASK_COLOR 2
+#define PNG_COLOR_MASK_ALPHA 4
+
+/* color types. Note that not all combinations are legal */
+#define PNG_COLOR_TYPE_GRAY 0
+#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
+#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
+#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
+#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
+/* aliases */
+#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
+#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA
+
+/* This is for compression type. PNG 1.0-1.2 only define the single type. */
+#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */
+#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
+
+/* This is for filter type. PNG 1.0-1.2 only define the single type. */
+#define PNG_FILTER_TYPE_BASE 0 /* Single row per-byte filtering */
+#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */
+#define PNG_FILTER_TYPE_DEFAULT PNG_FILTER_TYPE_BASE
+
+/* These are for the interlacing type. These values should NOT be changed. */
+#define PNG_INTERLACE_NONE 0 /* Non-interlaced image */
+#define PNG_INTERLACE_ADAM7 1 /* Adam7 interlacing */
+#define PNG_INTERLACE_LAST 2 /* Not a valid value */
+
+/* These are for the oFFs chunk. These values should NOT be changed. */
+#define PNG_OFFSET_PIXEL 0 /* Offset in pixels */
+#define PNG_OFFSET_MICROMETER 1 /* Offset in micrometers (1/10^6 meter) */
+#define PNG_OFFSET_LAST 2 /* Not a valid value */
+
+/* These are for the pCAL chunk. These values should NOT be changed. */
+#define PNG_EQUATION_LINEAR 0 /* Linear transformation */
+#define PNG_EQUATION_BASE_E 1 /* Exponential base e transform */
+#define PNG_EQUATION_ARBITRARY 2 /* Arbitrary base exponential transform */
+#define PNG_EQUATION_HYPERBOLIC 3 /* Hyperbolic sine transformation */
+#define PNG_EQUATION_LAST 4 /* Not a valid value */
+
+/* These are for the sCAL chunk. These values should NOT be changed. */
+#define PNG_SCALE_UNKNOWN 0 /* unknown unit (image scale) */
+#define PNG_SCALE_METER 1 /* meters per pixel */
+#define PNG_SCALE_RADIAN 2 /* radians per pixel */
+#define PNG_SCALE_LAST 3 /* Not a valid value */
+
+/* These are for the pHYs chunk. These values should NOT be changed. */
+#define PNG_RESOLUTION_UNKNOWN 0 /* pixels/unknown unit (aspect ratio) */
+#define PNG_RESOLUTION_METER 1 /* pixels/meter */
+#define PNG_RESOLUTION_LAST 2 /* Not a valid value */
+
+/* These are for the sRGB chunk. These values should NOT be changed. */
+#define PNG_sRGB_INTENT_PERCEPTUAL 0
+#define PNG_sRGB_INTENT_RELATIVE 1
+#define PNG_sRGB_INTENT_SATURATION 2
+#define PNG_sRGB_INTENT_ABSOLUTE 3
+#define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */
+
+/* This is for text chunks */
+#define PNG_KEYWORD_MAX_LENGTH 79
+
+/* Maximum number of entries in PLTE/sPLT/tRNS arrays */
+#define PNG_MAX_PALETTE_LENGTH 256
+
+/* These determine if an ancillary chunk's data has been successfully read
+ * from the PNG header, or if the application has filled in the corresponding
+ * data in the info_struct to be written into the output file. The values
+ * of the PNG_INFO_<chunk> defines should NOT be changed.
+ */
+#define PNG_INFO_gAMA 0x0001
+#define PNG_INFO_sBIT 0x0002
+#define PNG_INFO_cHRM 0x0004
+#define PNG_INFO_PLTE 0x0008
+#define PNG_INFO_tRNS 0x0010
+#define PNG_INFO_bKGD 0x0020
+#define PNG_INFO_hIST 0x0040
+#define PNG_INFO_pHYs 0x0080
+#define PNG_INFO_oFFs 0x0100
+#define PNG_INFO_tIME 0x0200
+#define PNG_INFO_pCAL 0x0400
+#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */
+#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */
+#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */
+#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */
+
+/* This is used for the transformation routines, as some of them
+ * change these values for the row. It also should enable using
+ * the routines for other purposes.
+ */
+typedef struct png_row_info_struct
+{
+ png_uint_32 width; /* width of row */
+ png_uint_32 rowbytes; /* number of bytes in row */
+ png_byte color_type; /* color type of row */
+ png_byte bit_depth; /* bit depth of row */
+ png_byte channels; /* number of channels (1, 2, 3, or 4) */
+ png_byte pixel_depth; /* bits per pixel (depth * channels) */
+} png_row_info;
+
+typedef png_row_info FAR * png_row_infop;
+typedef png_row_info FAR * FAR * png_row_infopp;
+
+/* These are the function types for the I/O functions and for the functions
+ * that allow the user to override the default I/O functions with his or her
+ * own. The png_error_ptr type should match that of user-supplied warning
+ * and error functions, while the png_rw_ptr type should match that of the
+ * user read/write data functions.
+ */
+typedef struct png_struct_def png_struct;
+typedef png_struct FAR * png_structp;
+
+typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp));
+typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t));
+typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp));
+typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32,
+ int));
+typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32,
+ int));
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop));
+typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
+ png_uint_32, int));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED)
+typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp,
+ png_row_infop, png_bytep));
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, png_unknown_chunkp));
+#endif
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp));
+#endif
+
+/* Transform masks for the high-level interface */
+#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */
+#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */
+#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */
+#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */
+#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */
+#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */
+#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */
+#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */
+#define PNG_TRANSFORM_BGR 0x0080 /* read and write */
+#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */
+#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */
+#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */
+#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only, deprecated */
+/* Added to libpng-1.2.34 */
+#define PNG_TRANSFORM_STRIP_FILLER_BEFORE 0x0800 /* write only */
+#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */
+/* Added to libpng-1.2.41 */
+#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */
+
+/* Flags for MNG supported features */
+#define PNG_FLAG_MNG_EMPTY_PLTE 0x01
+#define PNG_FLAG_MNG_FILTER_64 0x04
+#define PNG_ALL_MNG_FEATURES 0x05
+
+typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_size_t));
+typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp));
+
+/* The structure that holds the information to read and write PNG files.
+ * The only people who need to care about what is inside of this are the
+ * people who will be modifying the library for their own special needs.
+ * It should NOT be accessed directly by an application, except to store
+ * the jmp_buf.
+ */
+
+struct png_struct_def
+{
+#ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf jmpbuf; /* used in png_error */
+#endif
+ png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing errors and aborting */
+ png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing warnings */
+ png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for error functions */
+ png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing output data */
+ png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading input data */
+ png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct for I/O functions */
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read transform */
+#endif
+
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write transform */
+#endif
+
+/* These were added in libpng-1.0.2 */
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+ png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct for user transform */
+ png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user transformed pixels */
+ png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user transformed pixels */
+#endif
+#endif
+
+ png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in the PNG file */
+ png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various things to libpng */
+ png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations to perform */
+
+ z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression structure (below) */
+ png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */
+ png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */
+ int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */
+ int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */
+ int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window bits */
+ int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory level */
+ int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression strategy */
+
+ png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */
+ png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */
+ png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */
+ png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */
+ png_uint_32 rowbytes PNG_DEPSTRUCT; /* size of row in bytes */
+#if 0 /* Replaced with the following in libpng-1.2.43 */
+ png_size_t irowbytes PNG_DEPSTRUCT;
+#endif
+/* Added in libpng-1.2.43 */
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
+ * chunks that can be stored (0 means unlimited).
+ */
+ png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT;
+#endif
+ png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced row in pixels */
+ png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */
+ png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous (unfiltered) row */
+ png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current (unfiltered) row */
+#ifndef PNG_NO_WRITE_FILTER
+ png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row when filtering */
+ png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row when filtering */
+ png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row when filtering */
+ png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row when filtering */
+#endif
+ png_row_info row_info PNG_DEPSTRUCT; /* used for transformation routines */
+
+ png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */
+ png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */
+ png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */
+ png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in palette */
+ png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */
+ png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current chunk */
+ png_byte compression PNG_DEPSTRUCT; /* file compression type (always 0) */
+ png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */
+ png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
+ png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */
+ png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see PNG_FILTER_ below ) */
+ png_byte color_type PNG_DEPSTRUCT; /* color type of file */
+ png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */
+ png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */
+ png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */
+ png_byte channels PNG_DEPSTRUCT; /* number of channels in file */
+ png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */
+ png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from start of file */
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+#ifdef PNG_LEGACY_SUPPORTED
+ png_byte filler PNG_DEPSTRUCT; /* filler byte for pixel expansion */
+#else
+ png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel expansion */
+#endif
+#endif
+
+#ifdef PNG_bKGD_SUPPORTED
+ png_byte background_gamma_type PNG_DEPSTRUCT;
+# ifdef PNG_FLOATING_POINT_SUPPORTED
+ float background_gamma PNG_DEPSTRUCT;
+# endif
+ png_color_16 background PNG_DEPSTRUCT; /* background color in screen gamma space */
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized to gamma 1.0 */
+#endif
+#endif /* PNG_bKGD_SUPPORTED */
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+ png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing output */
+ png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, 0 - no flush */
+ png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since last flush */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits 16-bit gamma */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float gamma PNG_DEPSTRUCT; /* file gamma value */
+ float screen_gamma PNG_DEPSTRUCT; /* screen gamma value (display_exponent) */
+#endif
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit depth files */
+ png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */
+ png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */
+ png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit depth files */
+ png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */
+ png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
+ png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each available channel */
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+ png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit tranformation */
+#endif
+
+#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
+ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ png_bytep trans PNG_DEPSTRUCT; /* transparency values for paletted files */
+ png_color_16 trans_values PNG_DEPSTRUCT; /* transparency values for non-paletted files */
+#endif
+
+ png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each row is decoded */
+ png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each row is encoded */
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+ png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header data fully read */
+ png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each prog. row is decoded */
+ png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image is complete */
+ png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in save_buffer */
+ png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously read data */
+ png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in current_buffer */
+ png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently used data */
+ png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input chunk */
+ png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in input data */
+ png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now in save_buffer */
+ png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of save_buffer */
+ png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of available input data */
+ png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now in current_buffer */
+ int process_mode PNG_DEPSTRUCT; /* what push library is currently doing */
+ int cur_palette PNG_DEPSTRUCT; /* current push library palette index */
+
+# ifdef PNG_TEXT_SUPPORTED
+ png_size_t current_text_size PNG_DEPSTRUCT; /* current size of text input data */
+ png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left to read in input */
+ png_charp current_text PNG_DEPSTRUCT; /* current text chunk buffer */
+ png_charp current_text_ptr PNG_DEPSTRUCT; /* current location in current_text */
+# endif /* PNG_TEXT_SUPPORTED */
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* for the Borland special 64K segment handler */
+ png_bytepp offset_table_ptr PNG_DEPSTRUCT;
+ png_bytep offset_table PNG_DEPSTRUCT;
+ png_uint_16 offset_table_number PNG_DEPSTRUCT;
+ png_uint_16 offset_table_count PNG_DEPSTRUCT;
+ png_uint_16 offset_table_count_free PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+ png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for dithering */
+ png_bytep dither_index PNG_DEPSTRUCT; /* index translation for palette files */
+#endif
+
+#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
+ png_uint_16p hist PNG_DEPSTRUCT; /* histogram */
+#endif
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row filter selection */
+ png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights for previous rows */
+ png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of previous row(s) */
+ png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous line(s) */
+ png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for previous line(s) */
+ png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter calculation cost */
+ png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter calculation cost */
+#endif
+
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */
+#endif
+
+/* New members added in libpng-1.0.6 */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is responsible for freeing */
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+ png_voidp user_chunk_ptr PNG_DEPSTRUCT;
+ png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read chunk handler */
+#endif
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int num_chunk_list PNG_DEPSTRUCT;
+ png_bytep chunk_list PNG_DEPSTRUCT;
+#endif
+
+/* New members added in libpng-1.0.3 */
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ png_byte rgb_to_gray_status PNG_DEPSTRUCT;
+ /* These were changed from png_byte in libpng-1.0.6 */
+ png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT;
+ png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT;
+ png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT;
+#endif
+
+/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
+#if defined(PNG_MNG_FEATURES_SUPPORTED) || \
+ defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+ defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* Changed from png_byte to png_uint_32 at version 1.2.0 */
+#ifdef PNG_1_0_X
+ png_byte mng_features_permitted PNG_DEPSTRUCT;
+#else
+ png_uint_32 mng_features_permitted PNG_DEPSTRUCT;
+#endif /* PNG_1_0_X */
+#endif
+
+/* New member added in libpng-1.0.7 */
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ png_fixed_point int_gamma PNG_DEPSTRUCT;
+#endif
+
+/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ png_byte filter_type PNG_DEPSTRUCT;
+#endif
+
+#ifdef PNG_1_0_X
+/* New member added in libpng-1.0.10, ifdef'ed out in 1.2.0 */
+ png_uint_32 row_buf_size PNG_DEPSTRUCT;
+#endif
+
+/* New members added in libpng-1.2.0 */
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+# ifndef PNG_1_0_X
+# ifdef PNG_MMX_CODE_SUPPORTED
+ png_byte mmx_bitdepth_threshold PNG_DEPSTRUCT;
+ png_uint_32 mmx_rowbytes_threshold PNG_DEPSTRUCT;
+# endif
+ png_uint_32 asm_flags PNG_DEPSTRUCT;
+# endif
+#endif
+
+/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for mem functions */
+ png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for allocating memory */
+ png_free_ptr free_fn PNG_DEPSTRUCT; /* function for freeing memory */
+#endif
+
+/* New member added in libpng-1.0.13 and 1.2.0 */
+ png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current (unfiltered) row */
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+/* The following three members were added at version 1.0.14 and 1.2.4 */
+ png_bytep dither_sort PNG_DEPSTRUCT; /* working sort array */
+ png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original index currently is */
+ /* in the palette */
+ png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index points to this */
+ /* palette color */
+#endif
+
+/* New members added in libpng-1.0.16 and 1.2.6 */
+ png_byte compression_type PNG_DEPSTRUCT;
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ png_uint_32 user_width_max PNG_DEPSTRUCT;
+ png_uint_32 user_height_max PNG_DEPSTRUCT;
+#endif
+
+/* New member added in libpng-1.0.25 and 1.2.17 */
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+ /* Storage for unknown chunk that the library doesn't recognize. */
+ png_unknown_chunk unknown_chunk PNG_DEPSTRUCT;
+#endif
+
+/* New members added in libpng-1.2.26 */
+ png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT;
+ png_uint_32 old_prev_row_size PNG_DEPSTRUCT;
+
+/* New member added in libpng-1.2.30 */
+ png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */
+
+
+};
+
+
+/* This triggers a compiler error in png.c, if png.c and png.h
+ * do not agree upon the version number.
+ */
+typedef png_structp version_1_2_49;
+
+typedef png_struct FAR * FAR * png_structpp;
+
+/* Here are the function definitions most commonly used. This is not
+ * the place to find out how to use libpng. See libpng.txt for the
+ * full explanation, see example.c for the summary. This just provides
+ * a simple one line description of the use of each function.
+ */
+
+/* Returns the version number of the library */
+extern PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void));
+
+/* Tell lib we have already handled the first <num_bytes> magic bytes.
+ * Handling more than 8 bytes from the beginning of the file is an error.
+ */
+extern PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr,
+ int num_bytes));
+
+/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
+ * PNG file. Returns zero if the supplied bytes match the 8-byte PNG
+ * signature, and non-zero otherwise. Having num_to_check == 0 or
+ * start > 7 will always fail (ie return non-zero).
+ */
+extern PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start,
+ png_size_t num_to_check));
+
+/* Simple signature checking function. This is the same as calling
+ * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
+ */
+extern PNG_EXPORT(int,png_check_sig) PNGARG((png_bytep sig, int num)) PNG_DEPRECATED;
+
+/* Allocate and initialize png_ptr struct for reading, and any other memory. */
+extern PNG_EXPORT(png_structp,png_create_read_struct)
+ PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
+
+/* Allocate and initialize png_ptr struct for writing, and any other memory */
+extern PNG_EXPORT(png_structp,png_create_write_struct)
+ PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED;
+
+#ifdef PNG_WRITE_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_compression_buffer_size)
+ PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+extern PNG_EXPORT(void,png_set_compression_buffer_size)
+ PNGARG((png_structp png_ptr, png_uint_32 size));
+#endif
+
+/* Reset the compression stream */
+extern PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr));
+
+/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_structp,png_create_read_struct_2)
+ PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
+extern PNG_EXPORT(png_structp,png_create_write_struct_2)
+ PNGARG((png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED;
+#endif
+
+/* Write a PNG chunk - size, type, (optional) data, CRC. */
+extern PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr,
+ png_bytep chunk_name, png_bytep data, png_size_t length));
+
+/* Write the start of a PNG chunk - length and chunk name. */
+extern PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr,
+ png_bytep chunk_name, png_uint_32 length));
+
+/* Write the data of a PNG chunk started with png_write_chunk_start(). */
+extern PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr,
+ png_bytep data, png_size_t length));
+
+/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
+extern PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr));
+
+/* Allocate and initialize the info structure */
+extern PNG_EXPORT(png_infop,png_create_info_struct)
+ PNGARG((png_structp png_ptr)) PNG_ALLOCATED;
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Initialize the info structure (old interface - DEPRECATED) */
+extern PNG_EXPORT(void,png_info_init) PNGARG((png_infop info_ptr))
+ PNG_DEPRECATED;
+#undef png_info_init
+#define png_info_init(info_ptr) png_info_init_3(&info_ptr,\
+ png_sizeof(png_info));
+#endif
+
+extern PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr,
+ png_size_t png_info_struct_size));
+
+/* Writes all the PNG information before the image. */
+extern PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+extern PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read the information before the actual image data. */
+extern PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+#endif
+
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+extern PNG_EXPORT(png_charp,png_convert_to_rfc1123)
+ PNGARG((png_structp png_ptr, png_timep ptime));
+#endif
+
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+/* Convert from a struct tm to png_time */
+extern PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime,
+ struct tm FAR * ttime));
+
+/* Convert from time_t to png_time. Uses gmtime() */
+extern PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime,
+ time_t ttime));
+#endif /* PNG_CONVERT_tIME_SUPPORTED */
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
+extern PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr));
+#ifndef PNG_1_0_X
+extern PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp
+ png_ptr));
+#endif
+extern PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr));
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Deprecated */
+extern PNG_EXPORT(void,png_set_gray_1_2_4_to_8) PNGARG((png_structp
+ png_ptr)) PNG_DEPRECATED;
+#endif
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* Use blue, green, red order for pixels. */
+extern PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+/* Expand the grayscale to 24-bit RGB if necessary. */
+extern PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+/* Reduce RGB to grayscale. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr,
+ int error_action, double red, double green ));
+#endif
+extern PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr,
+ int error_action, png_fixed_point red, png_fixed_point green ));
+extern PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp
+ png_ptr));
+#endif
+
+extern PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth,
+ png_colorp palette));
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+extern PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+extern PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */
+extern PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr,
+ png_uint_32 filler, int flags));
+/* The values of the PNG_FILLER_ defines should NOT be changed */
+#define PNG_FILLER_BEFORE 0
+#define PNG_FILLER_AFTER 1
+/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
+#ifndef PNG_1_0_X
+extern PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr,
+ png_uint_32 filler, int flags));
+#endif
+#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* Swap bytes in 16-bit depth files. */
+extern PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
+extern PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* Swap packing order of pixels in bytes. */
+extern PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+/* Converts files to legal bit depths. */
+extern PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr,
+ png_color_8p true_bits));
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+ defined(PNG_WRITE_INTERLACING_SUPPORTED)
+/* Have the code handle the interlacing. Returns the number of passes. */
+extern PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+/* Invert monochrome files */
+extern PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+/* Handle alpha and tRNS by replacing with a background color. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr,
+ png_color_16p background_color, int background_gamma_code,
+ int need_expand, double background_gamma));
+#endif
+#define PNG_BACKGROUND_GAMMA_UNKNOWN 0
+#define PNG_BACKGROUND_GAMMA_SCREEN 1
+#define PNG_BACKGROUND_GAMMA_FILE 2
+#define PNG_BACKGROUND_GAMMA_UNIQUE 3
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Strip the second byte of information from a 16-bit depth file. */
+extern PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+/* Turn on dithering, and reduce the palette to the number of colors available. */
+extern PNG_EXPORT(void,png_set_dither) PNGARG((png_structp png_ptr,
+ png_colorp palette, int num_palette, int maximum_colors,
+ png_uint_16p histogram, int full_dither));
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+/* Handle gamma correction. Screen_gamma=(display_exponent) */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr,
+ double screen_gamma, double default_file_gamma));
+#endif
+#endif
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+ defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+/* Permit or disallow empty PLTE (0: not permitted, 1: permitted) */
+/* Deprecated and will be removed. Use png_permit_mng_features() instead. */
+extern PNG_EXPORT(void,png_permit_empty_plte) PNGARG((png_structp png_ptr,
+ int empty_plte_permitted)) PNG_DEPRECATED;
+#endif
+#endif
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+/* Set how many lines between output flushes - 0 for no flushing */
+extern PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows));
+/* Flush the current PNG output buffer */
+extern PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr));
+#endif
+
+/* Optional update palette with requested transformations */
+extern PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr));
+
+/* Optional call to update the users info structure */
+extern PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+/* Read one or more rows of image data. */
+extern PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr,
+ png_bytepp row, png_bytepp display_row, png_uint_32 num_rows));
+#endif
+
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+/* Read a row of data. */
+extern PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr,
+ png_bytep row,
+ png_bytep display_row));
+#endif
+
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+/* Read the whole image into memory at once. */
+extern PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr,
+ png_bytepp image));
+#endif
+
+/* Write a row of image data */
+extern PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr,
+ png_bytep row));
+
+/* Write a few rows of image data */
+extern PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr,
+ png_bytepp row, png_uint_32 num_rows));
+
+/* Write the image data */
+extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
+ png_bytepp image));
+
+/* Writes the end of the PNG file. */
+extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+
+#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
+/* Read the end of the PNG file. */
+extern PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr,
+ png_infop info_ptr));
+#endif
+
+/* Free any memory associated with the png_info_struct */
+extern PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr,
+ png_infopp info_ptr_ptr));
+
+/* Free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp
+ png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
+
+/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
+extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_infop end_info_ptr)) PNG_DEPRECATED;
+
+/* Free any memory associated with the png_struct and the png_info_structs */
+extern PNG_EXPORT(void,png_destroy_write_struct)
+ PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr));
+
+/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
+extern void png_write_destroy PNGARG((png_structp png_ptr)) PNG_DEPRECATED;
+
+/* Set the libpng method of handling chunk CRC errors */
+extern PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr,
+ int crit_action, int ancil_action));
+
+/* Values for png_set_crc_action() to say how to handle CRC errors in
+ * ancillary and critical chunks, and whether to use the data contained
+ * therein. Note that it is impossible to "discard" data in a critical
+ * chunk. For versions prior to 0.90, the action was always error/quit,
+ * whereas in version 0.90 and later, the action for CRC errors in ancillary
+ * chunks is warn/discard. These values should NOT be changed.
+ *
+ * value action:critical action:ancillary
+ */
+#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */
+#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */
+#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */
+#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */
+#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */
+#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */
+
+/* These functions give the user control over the scan-line filtering in
+ * libpng and the compression methods used by zlib. These functions are
+ * mainly useful for testing, as the defaults should work with most users.
+ * Those users who are tight on memory or want faster performance at the
+ * expense of compression can modify them. See the compression library
+ * header file (zlib.h) for an explination of the compression functions.
+ */
+
+/* Set the filtering method(s) used by libpng. Currently, the only valid
+ * value for "method" is 0.
+ */
+extern PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method,
+ int filters));
+
+/* Flags for png_set_filter() to say which filters to use. The flags
+ * are chosen so that they don't conflict with real filter types
+ * below, in case they are supplied instead of the #defined constants.
+ * These values should NOT be changed.
+ */
+#define PNG_NO_FILTERS 0x00
+#define PNG_FILTER_NONE 0x08
+#define PNG_FILTER_SUB 0x10
+#define PNG_FILTER_UP 0x20
+#define PNG_FILTER_AVG 0x40
+#define PNG_FILTER_PAETH 0x80
+#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
+ PNG_FILTER_AVG | PNG_FILTER_PAETH)
+
+/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
+ * These defines should NOT be changed.
+ */
+#define PNG_FILTER_VALUE_NONE 0
+#define PNG_FILTER_VALUE_SUB 1
+#define PNG_FILTER_VALUE_UP 2
+#define PNG_FILTER_VALUE_AVG 3
+#define PNG_FILTER_VALUE_PAETH 4
+#define PNG_FILTER_VALUE_LAST 5
+
+#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* EXPERIMENTAL */
+/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
+ * defines, either the default (minimum-sum-of-absolute-differences), or
+ * the experimental method (weighted-minimum-sum-of-absolute-differences).
+ *
+ * Weights are factors >= 1.0, indicating how important it is to keep the
+ * filter type consistent between rows. Larger numbers mean the current
+ * filter is that many times as likely to be the same as the "num_weights"
+ * previous filters. This is cumulative for each previous row with a weight.
+ * There needs to be "num_weights" values in "filter_weights", or it can be
+ * NULL if the weights aren't being specified. Weights have no influence on
+ * the selection of the first row filter. Well chosen weights can (in theory)
+ * improve the compression for a given image.
+ *
+ * Costs are factors >= 1.0 indicating the relative decoding costs of a
+ * filter type. Higher costs indicate more decoding expense, and are
+ * therefore less likely to be selected over a filter with lower computational
+ * costs. There needs to be a value in "filter_costs" for each valid filter
+ * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't
+ * setting the costs. Costs try to improve the speed of decompression without
+ * unduly increasing the compressed image size.
+ *
+ * A negative weight or cost indicates the default value is to be used, and
+ * values in the range [0.0, 1.0) indicate the value is to remain unchanged.
+ * The default values for both weights and costs are currently 1.0, but may
+ * change if good general weighting/cost heuristics can be found. If both
+ * the weights and costs are set to 1.0, this degenerates the WEIGHTED method
+ * to the UNWEIGHTED method, but with added encoding time/computation.
+ */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr,
+ int heuristic_method, int num_weights, png_doublep filter_weights,
+ png_doublep filter_costs));
+#endif
+#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+/* Heuristic used for row filter selection. These defines should NOT be
+ * changed.
+ */
+#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */
+#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */
+#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */
+#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */
+
+/* Set the library compression level. Currently, valid values range from
+ * 0 - 9, corresponding directly to the zlib compression levels 0 - 9
+ * (0 - no compression, 9 - "maximal" compression). Note that tests have
+ * shown that zlib compression levels 3-6 usually perform as well as level 9
+ * for PNG images, and do considerably fewer caclulations. In the future,
+ * these values may not correspond directly to the zlib compression levels.
+ */
+extern PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr,
+ int level));
+
+extern PNG_EXPORT(void,png_set_compression_mem_level)
+ PNGARG((png_structp png_ptr, int mem_level));
+
+extern PNG_EXPORT(void,png_set_compression_strategy)
+ PNGARG((png_structp png_ptr, int strategy));
+
+extern PNG_EXPORT(void,png_set_compression_window_bits)
+ PNGARG((png_structp png_ptr, int window_bits));
+
+extern PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr,
+ int method));
+
+/* These next functions are called for input/output, memory, and error
+ * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
+ * and call standard C I/O routines such as fread(), fwrite(), and
+ * fprintf(). These functions can be made to use other I/O routines
+ * at run time for those applications that need to handle I/O in a
+ * different manner by calling png_set_???_fn(). See libpng.txt for
+ * more information.
+ */
+
+#ifdef PNG_STDIO_SUPPORTED
+/* Initialize the input/output for the PNG file to the default functions. */
+extern PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, png_FILE_p fp));
+#endif
+
+/* Replace the (error and abort), and warning functions with user
+ * supplied functions. If no messages are to be printed you must still
+ * write and use replacement functions. The replacement error_fn should
+ * still do a longjmp to the last setjmp location if you are using this
+ * method of error handling. If error_fn or warning_fn is NULL, the
+ * default function will be used.
+ */
+
+extern PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
+
+/* Return the user pointer associated with the error functions */
+extern PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr));
+
+/* Replace the default data output functions with a user supplied one(s).
+ * If buffered output is not used, then output_flush_fn can be set to NULL.
+ * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
+ * output_flush_fn will be ignored (and thus can be NULL).
+ * It is probably a mistake to use NULL for output_flush_fn if
+ * write_data_fn is not also NULL unless you have built libpng with
+ * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's
+ * default flush function, which uses the standard *FILE structure, will
+ * be used.
+ */
+extern PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr,
+ png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
+
+/* Replace the default data input function with a user supplied one. */
+extern PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr,
+ png_voidp io_ptr, png_rw_ptr read_data_fn));
+
+/* Return the user pointer associated with the I/O functions */
+extern PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr));
+
+extern PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr,
+ png_read_status_ptr read_row_fn));
+
+extern PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr,
+ png_write_status_ptr write_row_fn));
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* Replace the default memory allocation functions with user supplied one(s). */
+extern PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr,
+ png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn));
+/* Return the user pointer associated with the memory functions */
+extern PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp
+ png_ptr, png_user_transform_ptr read_user_transform_fn));
+#endif
+
+#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp
+ png_ptr, png_user_transform_ptr write_user_transform_fn));
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED)
+extern PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp
+ png_ptr, png_voidp user_transform_ptr, int user_transform_depth,
+ int user_transform_channels));
+/* Return the user pointer associated with the user transform functions */
+extern PNG_EXPORT(png_voidp,png_get_user_transform_ptr)
+ PNGARG((png_structp png_ptr));
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+extern PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr,
+ png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
+extern PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp
+ png_ptr));
+#endif
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+/* Sets the function callbacks for the push reader, and a pointer to a
+ * user-defined structure available to the callback functions.
+ */
+extern PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr,
+ png_voidp progressive_ptr,
+ png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+ png_progressive_end_ptr end_fn));
+
+/* Returns the user pointer associated with the push read functions */
+extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
+ PNGARG((png_structp png_ptr));
+
+/* Function to be called when data becomes available */
+extern PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_bytep buffer, png_size_t buffer_size));
+
+/* Function that combines rows. Not very much different than the
+ * png_combine_row() call. Is this even used?????
+ */
+extern PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr,
+ png_bytep old_row, png_bytep new_row));
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+extern PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr,
+ png_uint_32 size)) PNG_ALLOCATED;
+
+#ifdef PNG_1_0_X
+# define png_malloc_warn png_malloc
+#else
+/* Added at libpng version 1.2.4 */
+extern PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr,
+ png_uint_32 size)) PNG_ALLOCATED;
+#endif
+
+/* Frees a pointer allocated by png_malloc() */
+extern PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr));
+
+#ifdef PNG_1_0_X
+/* Function to allocate memory for zlib. */
+extern PNG_EXPORT(voidpf,png_zalloc) PNGARG((voidpf png_ptr, uInt items,
+ uInt size));
+
+/* Function to free memory for zlib */
+extern PNG_EXPORT(void,png_zfree) PNGARG((voidpf png_ptr, voidpf ptr));
+#endif
+
+/* Free data that was allocated internally */
+extern PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 free_me, int num));
+#ifdef PNG_FREE_ME_SUPPORTED
+/* Reassign responsibility for freeing existing data, whether allocated
+ * by libpng or by the application
+ */
+extern PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int freer, png_uint_32 mask));
+#endif
+/* Assignments for png_data_freer */
+#define PNG_DESTROY_WILL_FREE_DATA 1
+#define PNG_SET_WILL_FREE_DATA 1
+#define PNG_USER_WILL_FREE_DATA 2
+/* Flags for png_ptr->free_me and info_ptr->free_me */
+#define PNG_FREE_HIST 0x0008
+#define PNG_FREE_ICCP 0x0010
+#define PNG_FREE_SPLT 0x0020
+#define PNG_FREE_ROWS 0x0040
+#define PNG_FREE_PCAL 0x0080
+#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_UNKN 0x0200
+#define PNG_FREE_LIST 0x0400
+#define PNG_FREE_PLTE 0x1000
+#define PNG_FREE_TRNS 0x2000
+#define PNG_FREE_TEXT 0x4000
+#define PNG_FREE_ALL 0x7fff
+#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+
+#ifdef PNG_USER_MEM_SUPPORTED
+extern PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr,
+ png_uint_32 size)) PNG_ALLOCATED;
+extern PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr,
+ png_voidp ptr));
+#endif
+
+extern PNG_EXPORT(png_voidp,png_memcpy_check) PNGARG((png_structp png_ptr,
+ png_voidp s1, png_voidp s2, png_uint_32 size)) PNG_DEPRECATED;
+
+extern PNG_EXPORT(png_voidp,png_memset_check) PNGARG((png_structp png_ptr,
+ png_voidp s1, int value, png_uint_32 size)) PNG_DEPRECATED;
+
+#if defined(USE_FAR_KEYWORD) /* memory model conversion function */
+extern void *png_far_to_near PNGARG((png_structp png_ptr,png_voidp ptr,
+ int check));
+#endif /* USE_FAR_KEYWORD */
+
+#ifndef PNG_NO_ERROR_TEXT
+/* Fatal error in PNG image of libpng - can't continue */
+extern PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr,
+ png_const_charp error_message)) PNG_NORETURN;
+
+/* The same, but the chunk name is prepended to the error string. */
+extern PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr,
+ png_const_charp error_message)) PNG_NORETURN;
+#else
+/* Fatal error in PNG image of libpng - can't continue */
+extern PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN;
+#endif
+
+#ifndef PNG_NO_WARNINGS
+/* Non-fatal error in libpng. Can continue, but may have a problem. */
+extern PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr,
+ png_const_charp warning_message));
+
+#ifdef PNG_READ_SUPPORTED
+/* Non-fatal error in libpng, chunk name is prepended to message. */
+extern PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr,
+ png_const_charp warning_message));
+#endif /* PNG_READ_SUPPORTED */
+#endif /* PNG_NO_WARNINGS */
+
+/* The png_set_<chunk> functions are for storing values in the png_info_struct.
+ * Similarly, the png_get_<chunk> calls are used to read values from the
+ * png_info_struct, either storing the parameters in the passed variables, or
+ * setting pointers into the png_info_struct where the data is stored. The
+ * png_get_<chunk> functions return a non-zero value if the data was available
+ * in info_ptr, or return zero and do not change any of the parameters if the
+ * data was not available.
+ *
+ * These functions should be used instead of directly accessing png_info
+ * to avoid problems with future changes in the size and internal layout of
+ * png_info_struct.
+ */
+/* Returns "flag" if chunk data is valid in info_ptr. */
+extern PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr,
+png_infop info_ptr, png_uint_32 flag));
+
+/* Returns number of bytes needed to hold a transformed row. */
+extern PNG_EXPORT(png_uint_32,png_get_rowbytes) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+/* Returns row_pointers, which is an array of pointers to scanlines that was
+ * returned from png_read_png().
+ */
+extern PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+/* Set row_pointers, which is an array of pointers to scanlines for use
+ * by png_write_png().
+ */
+extern PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_bytepp row_pointers));
+#endif
+
+/* Returns number of color channels in image. */
+extern PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* Returns image width in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image height in pixels. */
+extern PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image bit_depth. */
+extern PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image color_type. */
+extern PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image filter_type. */
+extern PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image interlace_type. */
+extern PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image compression_type. */
+extern PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns image resolution in pixels per meter, from pHYs chunk data. */
+extern PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+/* Returns pixel aspect ratio, computed from pHYs chunk data. */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+#endif
+
+/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
+extern PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+extern PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp
+png_ptr, png_infop info_ptr));
+
+#endif /* PNG_EASY_ACCESS_SUPPORTED */
+
+/* Returns pointer to signature string read from PNG header */
+extern PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_bKGD_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_color_16p *background));
+#endif
+
+#ifdef PNG_bKGD_SUPPORTED
+extern PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_color_16p background));
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, double *white_x, double *white_y, double *red_x,
+ double *red_y, double *green_x, double *green_y, double *blue_x,
+ double *blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point
+ *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y,
+ png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point
+ *int_blue_x, png_fixed_point *int_blue_y));
+#endif
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, double white_x, double white_y, double red_x,
+ double red_y, double green_x, double green_y, double blue_x, double blue_y));
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y,
+ png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+ int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+ png_fixed_point int_blue_y));
+#endif
+#endif
+
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, double *file_gamma));
+#endif
+extern PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point *int_file_gamma));
+#endif
+
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, double file_gamma));
+#endif
+extern PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_fixed_point int_file_gamma));
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_16p *hist));
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+extern PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_16p hist));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
+ int *bit_depth, int *color_type, int *interlace_method,
+ int *compression_method, int *filter_method));
+
+extern PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_method, int compression_method,
+ int filter_method));
+
+#ifdef PNG_oFFs_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+ int *unit_type));
+#endif
+
+#ifdef PNG_oFFs_SUPPORTED
+extern PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y,
+ int unit_type));
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1,
+ int *type, int *nparams, png_charp *units, png_charpp *params));
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+extern PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1,
+ int type, int nparams, png_charp units, png_charpp params));
+#endif
+
+#ifdef PNG_pHYs_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+#endif
+
+#ifdef PNG_pHYs_SUPPORTED
+extern PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+#endif
+
+extern PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_colorp *palette, int *num_palette));
+
+extern PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_colorp palette, int num_palette));
+
+#ifdef PNG_sBIT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_color_8p *sig_bit));
+#endif
+
+#ifdef PNG_sBIT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_color_8p sig_bit));
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int *intent));
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+extern PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int intent));
+extern PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int intent));
+#endif
+
+#ifdef PNG_iCCP_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_charpp name, int *compression_type,
+ png_charpp profile, png_uint_32 *proflen));
+ /* Note to maintainer: profile should be png_bytepp */
+#endif
+
+#ifdef PNG_iCCP_SUPPORTED
+extern PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_charp name, int compression_type,
+ png_charp profile, png_uint_32 proflen));
+ /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_sPLT_tpp entries));
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_sPLT_tp entries, int nentries));
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED
+/* png_get_text also returns the number of text chunks in *num_text */
+extern PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_textp *text_ptr, int *num_text));
+#endif
+
+/*
+ * Note while png_set_text() will accept a structure whose text,
+ * language, and translated keywords are NULL pointers, the structure
+ * returned by png_get_text will always contain regular
+ * zero-terminated C strings. They might be empty strings but
+ * they will never be NULL pointers.
+ */
+
+#ifdef PNG_TEXT_SUPPORTED
+extern PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_textp text_ptr, int num_text));
+#endif
+
+#ifdef PNG_tIME_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_timep *mod_time));
+#endif
+
+#ifdef PNG_tIME_SUPPORTED
+extern PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_timep mod_time));
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_bytep *trans, int *num_trans,
+ png_color_16p *trans_values));
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+extern PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_bytep trans, int num_trans,
+ png_color_16p trans_values));
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+#endif
+
+#ifdef PNG_sCAL_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int *unit, double *width, double *height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight));
+#endif
+#endif
+#endif /* PNG_sCAL_SUPPORTED */
+
+#ifdef PNG_sCAL_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int unit, double width, double height));
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+extern PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int unit, png_charp swidth, png_charp sheight));
+#endif
+#endif
+#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+/* Provide a list of chunks and how they are to be handled, if the built-in
+ handling or default unknown chunk handling is not desired. Any chunks not
+ listed will be handled in the default manner. The IHDR and IEND chunks
+ must not be listed.
+ keep = 0: follow default behaviour
+ = 1: do not keep
+ = 2: keep only if safe-to-copy
+ = 3: keep even if unsafe-to-copy
+*/
+extern PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp
+ png_ptr, int keep, png_bytep chunk_list, int num_chunks));
+PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep
+ chunk_name));
+#endif
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+extern PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns));
+extern PNG_EXPORT(void, png_set_unknown_chunk_location)
+ PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location));
+extern PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp
+ png_ptr, png_infop info_ptr, png_unknown_chunkpp entries));
+#endif
+
+/* Png_free_data() will turn off the "valid" flag for anything it frees.
+ * If you need to turn it off for a chunk that your application has freed,
+ * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
+ */
+extern PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr,
+ png_infop info_ptr, int mask));
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+/* The "params" pointer is currently not used and is for future expansion. */
+extern PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr,
+ png_infop info_ptr,
+ int transforms,
+ png_voidp params));
+extern PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr,
+ png_infop info_ptr,
+ int transforms,
+ png_voidp params));
+#endif
+
+/* Define PNG_DEBUG at compile time for debugging information. Higher
+ * numbers for PNG_DEBUG mean more debugging information. This has
+ * only been added since version 0.95 so it is not implemented throughout
+ * libpng yet, but more support will be added as needed.
+ */
+#ifdef PNG_DEBUG
+#if (PNG_DEBUG > 0)
+#if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
+#include <crtdbg.h>
+#if (PNG_DEBUG > 1)
+#ifndef _DEBUG
+# define _DEBUG
+#endif
+#ifndef png_debug
+#define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
+#endif
+#ifndef png_debug1
+#define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
+#endif
+#ifndef png_debug2
+#define png_debug2(l,m,p1,p2) _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
+#endif
+#endif
+#else /* PNG_DEBUG_FILE || !_MSC_VER */
+#ifndef PNG_DEBUG_FILE
+#define PNG_DEBUG_FILE stderr
+#endif /* PNG_DEBUG_FILE */
+
+#if (PNG_DEBUG > 1)
+/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on non-ISO
+ * compilers.
+ */
+# ifdef __STDC__
+# ifndef png_debug
+# define png_debug(l,m) \
+ { \
+ int num_tabs=l; \
+ fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+ }
+# endif
+# ifndef png_debug1
+# define png_debug1(l,m,p1) \
+ { \
+ int num_tabs=l; \
+ fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+ }
+# endif
+# ifndef png_debug2
+# define png_debug2(l,m,p1,p2) \
+ { \
+ int num_tabs=l; \
+ fprintf(PNG_DEBUG_FILE,"%s"m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+ }
+# endif
+# else /* __STDC __ */
+# ifndef png_debug
+# define png_debug(l,m) \
+ { \
+ int num_tabs=l; \
+ char format[256]; \
+ snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+ m,PNG_STRING_NEWLINE); \
+ fprintf(PNG_DEBUG_FILE,format); \
+ }
+# endif
+# ifndef png_debug1
+# define png_debug1(l,m,p1) \
+ { \
+ int num_tabs=l; \
+ char format[256]; \
+ snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+ m,PNG_STRING_NEWLINE); \
+ fprintf(PNG_DEBUG_FILE,format,p1); \
+ }
+# endif
+# ifndef png_debug2
+# define png_debug2(l,m,p1,p2) \
+ { \
+ int num_tabs=l; \
+ char format[256]; \
+ snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
+ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
+ m,PNG_STRING_NEWLINE); \
+ fprintf(PNG_DEBUG_FILE,format,p1,p2); \
+ }
+# endif
+# endif /* __STDC __ */
+#endif /* (PNG_DEBUG > 1) */
+
+#endif /* _MSC_VER */
+#endif /* (PNG_DEBUG > 0) */
+#endif /* PNG_DEBUG */
+#ifndef png_debug
+#define png_debug(l, m)
+#endif
+#ifndef png_debug1
+#define png_debug1(l, m, p1)
+#endif
+#ifndef png_debug2
+#define png_debug2(l, m, p1, p2)
+#endif
+
+extern PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp png_ptr));
+extern PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr));
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+extern PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp
+ png_ptr, png_uint_32 mng_features_permitted));
+#endif
+
+/* For use in png_set_keep_unknown, added to version 1.2.6 */
+#define PNG_HANDLE_CHUNK_AS_DEFAULT 0
+#define PNG_HANDLE_CHUNK_NEVER 1
+#define PNG_HANDLE_CHUNK_IF_SAFE 2
+#define PNG_HANDLE_CHUNK_ALWAYS 3
+
+/* Added to version 1.2.0 */
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#ifdef PNG_MMX_CODE_SUPPORTED
+#define PNG_ASM_FLAG_MMX_SUPPORT_COMPILED 0x01 /* not user-settable */
+#define PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU 0x02 /* not user-settable */
+#define PNG_ASM_FLAG_MMX_READ_COMBINE_ROW 0x04
+#define PNG_ASM_FLAG_MMX_READ_INTERLACE 0x08
+#define PNG_ASM_FLAG_MMX_READ_FILTER_SUB 0x10
+#define PNG_ASM_FLAG_MMX_READ_FILTER_UP 0x20
+#define PNG_ASM_FLAG_MMX_READ_FILTER_AVG 0x40
+#define PNG_ASM_FLAG_MMX_READ_FILTER_PAETH 0x80
+#define PNG_ASM_FLAGS_INITIALIZED 0x80000000 /* not user-settable */
+
+#define PNG_MMX_READ_FLAGS ( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \
+ | PNG_ASM_FLAG_MMX_READ_INTERLACE \
+ | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \
+ | PNG_ASM_FLAG_MMX_READ_FILTER_UP \
+ | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \
+ | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH )
+#define PNG_MMX_WRITE_FLAGS ( 0 )
+
+#define PNG_MMX_FLAGS ( PNG_ASM_FLAG_MMX_SUPPORT_COMPILED \
+ | PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU \
+ | PNG_MMX_READ_FLAGS \
+ | PNG_MMX_WRITE_FLAGS )
+
+#define PNG_SELECT_READ 1
+#define PNG_SELECT_WRITE 2
+#endif /* PNG_MMX_CODE_SUPPORTED */
+
+#ifndef PNG_1_0_X
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_mmx_flagmask)
+ PNGARG((int flag_select, int *compilerID));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_asm_flagmask)
+ PNGARG((int flag_select));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_asm_flags)
+ PNGARG((png_structp png_ptr));
+
+/* pngget.c */
+extern PNG_EXPORT(png_byte,png_get_mmx_bitdepth_threshold)
+ PNGARG((png_structp png_ptr));
+
+/* pngget.c */
+extern PNG_EXPORT(png_uint_32,png_get_mmx_rowbytes_threshold)
+ PNGARG((png_structp png_ptr));
+
+/* pngset.c */
+extern PNG_EXPORT(void,png_set_asm_flags)
+ PNGARG((png_structp png_ptr, png_uint_32 asm_flags));
+
+/* pngset.c */
+extern PNG_EXPORT(void,png_set_mmx_thresholds)
+ PNGARG((png_structp png_ptr, png_byte mmx_bitdepth_threshold,
+ png_uint_32 mmx_rowbytes_threshold));
+
+#endif /* PNG_1_0_X */
+
+#ifndef PNG_1_0_X
+/* png.c, pnggccrd.c, or pngvcrd.c */
+extern PNG_EXPORT(int,png_mmx_support) PNGARG((void));
+#endif /* PNG_1_0_X */
+#endif /* PNG_ASSEMBLER_CODE_SUPPORTED */
+
+/* Strip the prepended error numbers ("#nnn ") from error and warning
+ * messages before passing them to the error or warning handler.
+ */
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+extern PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp
+ png_ptr, png_uint_32 strip_mode));
+#endif
+
+/* Added at libpng-1.2.6 */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+extern PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp
+ png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max));
+extern PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp
+ png_ptr));
+extern PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp
+ png_ptr));
+#endif
+/* Maintainer: Put new public prototypes here ^, in libpng.3, and in
+ * project defs
+ */
+
+#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
+/* With these routines we avoid an integer divide, which will be slower on
+ * most machines. However, it does take more operations than the corresponding
+ * divide method, so it may be slower on a few RISC systems. There are two
+ * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
+ *
+ * Note that the rounding factors are NOT supposed to be the same! 128 and
+ * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
+ * standard method.
+ *
+ * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
+ */
+
+ /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
+
+# define png_composite(composite, fg, alpha, bg) \
+ { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) * (png_uint_16)(alpha) \
+ + (png_uint_16)(bg)*(png_uint_16)(255 - \
+ (png_uint_16)(alpha)) + (png_uint_16)128); \
+ (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+
+# define png_composite_16(composite, fg, alpha, bg) \
+ { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) * (png_uint_32)(alpha) \
+ + (png_uint_32)(bg)*(png_uint_32)(65535L - \
+ (png_uint_32)(alpha)) + (png_uint_32)32768L); \
+ (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+
+#else /* Standard method using integer division */
+
+# define png_composite(composite, fg, alpha, bg) \
+ (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
+ (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
+ (png_uint_16)127) / 255)
+
+# define png_composite_16(composite, fg, alpha, bg) \
+ (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+ (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \
+ (png_uint_32)32767) / (png_uint_32)65535L)
+
+#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
+
+/* Inline macros to do direct reads of bytes from the input buffer. These
+ * require that you are using an architecture that uses PNG byte ordering
+ * (MSB first) and supports unaligned data storage. I think that PowerPC
+ * in big-endian mode and 680x0 are the only ones that will support this.
+ * The x86 line of processors definitely do not. The png_get_int_32()
+ * routine also assumes we are using two's complement format for negative
+ * values, which is almost certainly true.
+ */
+#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
+# define png_get_uint_32(buf) ( *((png_uint_32p) (buf)))
+# define png_get_uint_16(buf) ( *((png_uint_16p) (buf)))
+# define png_get_int_32(buf) ( *((png_int_32p) (buf)))
+#else
+extern PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf));
+extern PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf));
+extern PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf));
+#endif /* !PNG_READ_BIG_ENDIAN_SUPPORTED */
+extern PNG_EXPORT(png_uint_32,png_get_uint_31)
+ PNGARG((png_structp png_ptr, png_bytep buf));
+/* No png_get_int_16 -- may be added if there's a real need for it. */
+
+/* Place a 32-bit number into a buffer in PNG byte order (big-endian).
+ */
+extern PNG_EXPORT(void,png_save_uint_32)
+ PNGARG((png_bytep buf, png_uint_32 i));
+extern PNG_EXPORT(void,png_save_int_32)
+ PNGARG((png_bytep buf, png_int_32 i));
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+extern PNG_EXPORT(void,png_save_uint_16)
+ PNGARG((png_bytep buf, unsigned int i));
+/* No png_save_int_16 -- may be added if there's a real need for it. */
+
+/* ************************************************************************* */
+
+/* These next functions are used internally in the code. They generally
+ * shouldn't be used unless you are writing code to add or replace some
+ * functionality in libpng. More information about most functions can
+ * be found in the files where the functions are located.
+ */
+
+
+/* Various modes of operation, that are visible to applications because
+ * they are used for unknown chunk location.
+ */
+#define PNG_HAVE_IHDR 0x01
+#define PNG_HAVE_PLTE 0x02
+#define PNG_HAVE_IDAT 0x04
+#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */
+#define PNG_HAVE_IEND 0x10
+
+#ifdef PNG_INTERNAL
+
+/* More modes of operation. Note that after an init, mode is set to
+ * zero automatically when the structure is created.
+ */
+#define PNG_HAVE_gAMA 0x20
+#define PNG_HAVE_cHRM 0x40
+#define PNG_HAVE_sRGB 0x80
+#define PNG_HAVE_CHUNK_HEADER 0x100
+#define PNG_WROTE_tIME 0x200
+#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
+#define PNG_BACKGROUND_IS_GRAY 0x800
+#define PNG_HAVE_PNG_SIGNATURE 0x1000
+#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
+
+/* Flags for the transformations the PNG library does on the image data */
+#define PNG_BGR 0x0001
+#define PNG_INTERLACE 0x0002
+#define PNG_PACK 0x0004
+#define PNG_SHIFT 0x0008
+#define PNG_SWAP_BYTES 0x0010
+#define PNG_INVERT_MONO 0x0020
+#define PNG_DITHER 0x0040
+#define PNG_BACKGROUND 0x0080
+#define PNG_BACKGROUND_EXPAND 0x0100
+ /* 0x0200 unused */
+#define PNG_16_TO_8 0x0400
+#define PNG_RGBA 0x0800
+#define PNG_EXPAND 0x1000
+#define PNG_GAMMA 0x2000
+#define PNG_GRAY_TO_RGB 0x4000
+#define PNG_FILLER 0x8000L
+#define PNG_PACKSWAP 0x10000L
+#define PNG_SWAP_ALPHA 0x20000L
+#define PNG_STRIP_ALPHA 0x40000L
+#define PNG_INVERT_ALPHA 0x80000L
+#define PNG_USER_TRANSFORM 0x100000L
+#define PNG_RGB_TO_GRAY_ERR 0x200000L
+#define PNG_RGB_TO_GRAY_WARN 0x400000L
+#define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */
+ /* 0x800000L Unused */
+#define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */
+#define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */
+#define PNG_PREMULTIPLY_ALPHA 0x4000000L /* Added to libpng-1.2.41 */
+ /* by volker */
+ /* 0x8000000L unused */
+ /* 0x10000000L unused */
+ /* 0x20000000L unused */
+ /* 0x40000000L unused */
+
+/* Flags for png_create_struct */
+#define PNG_STRUCT_PNG 0x0001
+#define PNG_STRUCT_INFO 0x0002
+
+/* Scaling factor for filter heuristic weighting calculations */
+#define PNG_WEIGHT_SHIFT 8
+#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT))
+#define PNG_COST_SHIFT 3
+#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT))
+
+/* Flags for the png_ptr->flags rather than declaring a byte for each one */
+#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001
+#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002
+#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004
+#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008
+#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010
+#define PNG_FLAG_ZLIB_FINISHED 0x0020
+#define PNG_FLAG_ROW_INIT 0x0040
+#define PNG_FLAG_FILLER_AFTER 0x0080
+#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
+#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200
+#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
+#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
+#define PNG_FLAG_FREE_PLTE 0x1000
+#define PNG_FLAG_FREE_TRNS 0x2000
+#define PNG_FLAG_FREE_HIST 0x4000
+#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L
+#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L
+#define PNG_FLAG_LIBRARY_MISMATCH 0x20000L
+#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L
+#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L
+#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L
+#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */
+#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */
+ /* 0x800000L unused */
+ /* 0x1000000L unused */
+ /* 0x2000000L unused */
+ /* 0x4000000L unused */
+ /* 0x8000000L unused */
+ /* 0x10000000L unused */
+ /* 0x20000000L unused */
+ /* 0x40000000L unused */
+
+#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
+ PNG_FLAG_CRC_ANCILLARY_NOWARN)
+
+#define PNG_FLAG_CRC_CRITICAL_MASK (PNG_FLAG_CRC_CRITICAL_USE | \
+ PNG_FLAG_CRC_CRITICAL_IGNORE)
+
+#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \
+ PNG_FLAG_CRC_CRITICAL_MASK)
+
+/* Save typing and make code easier to understand */
+
+#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
+ abs((int)((c1).green) - (int)((c2).green)) + \
+ abs((int)((c1).blue) - (int)((c2).blue)))
+
+/* Added to libpng-1.2.6 JB */
+#define PNG_ROWBYTES(pixel_bits, width) \
+ ((pixel_bits) >= 8 ? \
+ ((width) * (((png_uint_32)(pixel_bits)) >> 3)) : \
+ (( ((width) * ((png_uint_32)(pixel_bits))) + 7) >> 3) )
+
+/* PNG_OUT_OF_RANGE returns true if value is outside the range
+ * ideal-delta..ideal+delta. Each argument is evaluated twice.
+ * "ideal" and "delta" should be constants, normally simple
+ * integers, "value" a variable. Added to libpng-1.2.6 JB
+ */
+#define PNG_OUT_OF_RANGE(value, ideal, delta) \
+ ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) )
+
+/* Variables declared in png.c - only it needs to define PNG_NO_EXTERN */
+#if !defined(PNG_NO_EXTERN) || defined(PNG_ALWAYS_EXTERN)
+/* Place to hold the signature string for a PNG file. */
+#ifdef PNG_USE_GLOBAL_ARRAYS
+ PNG_EXPORT_VAR (PNG_CONST png_byte FARDATA) png_sig[8];
+#else
+#endif
+#endif /* PNG_NO_EXTERN */
+
+/* Constant strings for known chunk types. If you need to add a chunk,
+ * define the name here, and add an invocation of the macro in png.c and
+ * wherever it's needed.
+ */
+#define PNG_IHDR png_byte png_IHDR[5] = { 73, 72, 68, 82, '\0'}
+#define PNG_IDAT png_byte png_IDAT[5] = { 73, 68, 65, 84, '\0'}
+#define PNG_IEND png_byte png_IEND[5] = { 73, 69, 78, 68, '\0'}
+#define PNG_PLTE png_byte png_PLTE[5] = { 80, 76, 84, 69, '\0'}
+#define PNG_bKGD png_byte png_bKGD[5] = { 98, 75, 71, 68, '\0'}
+#define PNG_cHRM png_byte png_cHRM[5] = { 99, 72, 82, 77, '\0'}
+#define PNG_gAMA png_byte png_gAMA[5] = {103, 65, 77, 65, '\0'}
+#define PNG_hIST png_byte png_hIST[5] = {104, 73, 83, 84, '\0'}
+#define PNG_iCCP png_byte png_iCCP[5] = {105, 67, 67, 80, '\0'}
+#define PNG_iTXt png_byte png_iTXt[5] = {105, 84, 88, 116, '\0'}
+#define PNG_oFFs png_byte png_oFFs[5] = {111, 70, 70, 115, '\0'}
+#define PNG_pCAL png_byte png_pCAL[5] = {112, 67, 65, 76, '\0'}
+#define PNG_sCAL png_byte png_sCAL[5] = {115, 67, 65, 76, '\0'}
+#define PNG_pHYs png_byte png_pHYs[5] = {112, 72, 89, 115, '\0'}
+#define PNG_sBIT png_byte png_sBIT[5] = {115, 66, 73, 84, '\0'}
+#define PNG_sPLT png_byte png_sPLT[5] = {115, 80, 76, 84, '\0'}
+#define PNG_sRGB png_byte png_sRGB[5] = {115, 82, 71, 66, '\0'}
+#define PNG_tEXt png_byte png_tEXt[5] = {116, 69, 88, 116, '\0'}
+#define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'}
+#define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'}
+#define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'}
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_IDAT[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_IEND[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_PLTE[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_bKGD[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_cHRM[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_gAMA[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_hIST[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_iCCP[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_iTXt[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_oFFs[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_pCAL[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_sCAL[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_pHYs[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_sBIT[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_sPLT[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_sRGB[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_tEXt[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5];
+PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5];
+#endif /* PNG_USE_GLOBAL_ARRAYS */
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Initialize png_ptr struct for reading, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_read_struct instead).
+ */
+extern PNG_EXPORT(void,png_read_init) PNGARG((png_structp png_ptr))
+ PNG_DEPRECATED;
+#undef png_read_init
+#define png_read_init(png_ptr) png_read_init_3(&png_ptr, \
+ PNG_LIBPNG_VER_STRING, png_sizeof(png_struct));
+#endif
+
+extern PNG_EXPORT(void,png_read_init_3) PNGARG((png_structpp ptr_ptr,
+ png_const_charp user_png_ver, png_size_t png_struct_size));
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+extern PNG_EXPORT(void,png_read_init_2) PNGARG((png_structp png_ptr,
+ png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+ png_info_size));
+#endif
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Initialize png_ptr struct for writing, and allocate any other memory.
+ * (old interface - DEPRECATED - use png_create_write_struct instead).
+ */
+extern PNG_EXPORT(void,png_write_init) PNGARG((png_structp png_ptr))
+ PNG_DEPRECATED;
+#undef png_write_init
+#define png_write_init(png_ptr) png_write_init_3(&png_ptr, \
+ PNG_LIBPNG_VER_STRING, png_sizeof(png_struct));
+#endif
+
+extern PNG_EXPORT(void,png_write_init_3) PNGARG((png_structpp ptr_ptr,
+ png_const_charp user_png_ver, png_size_t png_struct_size));
+extern PNG_EXPORT(void,png_write_init_2) PNGARG((png_structp png_ptr,
+ png_const_charp user_png_ver, png_size_t png_struct_size, png_size_t
+ png_info_size));
+
+/* Allocate memory for an internal libpng struct */
+PNG_EXTERN png_voidp png_create_struct PNGARG((int type)) PNG_PRIVATE;
+
+/* Free memory from internal libpng struct */
+PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr)) PNG_PRIVATE;
+
+PNG_EXTERN png_voidp png_create_struct_2 PNGARG((int type, png_malloc_ptr
+ malloc_fn, png_voidp mem_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
+ png_free_ptr free_fn, png_voidp mem_ptr)) PNG_PRIVATE;
+
+/* Free any memory that info_ptr points to and reset struct. */
+PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+
+#ifndef PNG_1_0_X
+/* Function to allocate memory for zlib. */
+PNG_EXTERN voidpf png_zalloc PNGARG((voidpf png_ptr, uInt items,
+ uInt size)) PNG_PRIVATE;
+
+/* Function to free memory for zlib */
+PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr)) PNG_PRIVATE;
+
+#ifdef PNG_SIZE_T
+/* Function to convert a sizeof an item to png_sizeof item */
+ PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size))
+ PNG_PRIVATE;
+#endif
+
+/* Next four functions are used internally as callbacks. PNGAPI is required
+ * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3.
+ */
+
+PNG_EXTERN void PNGAPI png_default_read_data PNGARG((png_structp png_ptr,
+ png_bytep data, png_size_t length)) PNG_PRIVATE;
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXTERN void PNGAPI png_push_fill_buffer PNGARG((png_structp png_ptr,
+ png_bytep buffer, png_size_t length)) PNG_PRIVATE;
+#endif
+
+PNG_EXTERN void PNGAPI png_default_write_data PNGARG((png_structp png_ptr,
+ png_bytep data, png_size_t length)) PNG_PRIVATE;
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
+PNG_EXTERN void PNGAPI png_default_flush PNGARG((png_structp png_ptr))
+ PNG_PRIVATE;
+#endif
+#endif
+#else /* PNG_1_0_X */
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXTERN void png_push_fill_buffer PNGARG((png_structp png_ptr,
+ png_bytep buffer, png_size_t length)) PNG_PRIVATE;
+#endif
+#endif /* PNG_1_0_X */
+
+/* Reset the CRC variable */
+PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Write the "data" buffer to whatever output you are using. */
+PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr, png_bytep data,
+ png_size_t length)) PNG_PRIVATE;
+
+/* Read data from whatever input you are using into the "data" buffer */
+PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
+ png_size_t length)) PNG_PRIVATE;
+
+/* Read bytes into buf, and update png_ptr->crc */
+PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
+ png_size_t length)) PNG_PRIVATE;
+
+/* Decompress data in a chunk that uses compression */
+#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \
+ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr,
+ int comp_type, png_size_t chunklength,
+ png_size_t prefix_length, png_size_t *data_length)) PNG_PRIVATE;
+#endif
+
+/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
+PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip)
+ PNG_PRIVATE);
+
+/* Read the CRC from the file and compare it to the libpng calculated CRC */
+PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Calculate the CRC over a section of data. Note that we are only
+ * passing a maximum of 64K on systems that have this as a memory limit,
+ * since this is the maximum buffer size we can specify.
+ */
+PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
+ png_size_t length)) PNG_PRIVATE;
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+PNG_EXTERN void png_flush PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#endif
+
+/* Simple function to write the signature */
+PNG_EXTERN void png_write_sig PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Write various chunks */
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information.
+ */
+PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
+ png_uint_32 height,
+ int bit_depth, int color_type, int compression_method, int filter_method,
+ int interlace_method)) PNG_PRIVATE;
+
+PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr, png_colorp palette,
+ png_uint_32 num_pal)) PNG_PRIVATE;
+
+PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
+ png_size_t length)) PNG_PRIVATE;
+
+PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+#ifdef PNG_WRITE_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma))
+ PNG_PRIVATE;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
+ png_fixed_point file_gamma)) PNG_PRIVATE;
+#endif
+#endif
+
+#ifdef PNG_WRITE_sBIT_SUPPORTED
+PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr, png_color_8p sbit,
+ int color_type)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
+ double white_x, double white_y,
+ double red_x, double red_y, double green_x, double green_y,
+ double blue_x, double blue_y)) PNG_PRIVATE;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
+ png_fixed_point int_white_x, png_fixed_point int_white_y,
+ png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+ int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+ png_fixed_point int_blue_y)) PNG_PRIVATE;
+#endif
+#endif
+
+#ifdef PNG_WRITE_sRGB_SUPPORTED
+PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
+ int intent)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_iCCP_SUPPORTED
+PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
+ png_charp name, int compression_type,
+ png_charp profile, int proflen)) PNG_PRIVATE;
+ /* Note to maintainer: profile should be png_bytep */
+#endif
+
+#ifdef PNG_WRITE_sPLT_SUPPORTED
+PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
+ png_sPLT_tp palette)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_tRNS_SUPPORTED
+PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr, png_bytep trans,
+ png_color_16p values, int number, int color_type)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_bKGD_SUPPORTED
+PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
+ png_color_16p values, int color_type)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_hIST_SUPPORTED
+PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_uint_16p hist,
+ int num_hist)) PNG_PRIVATE;
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+ defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
+ png_charp key, png_charpp new_key)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_charp key,
+ png_charp text, png_size_t text_len)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_charp key,
+ png_charp text, png_size_t text_len, int compression)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
+ int compression, png_charp key, png_charp lang, png_charp lang_key,
+ png_charp text)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */
+PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_textp text_ptr, int num_text)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_oFFs_SUPPORTED
+PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
+ png_int_32 x_offset, png_int_32 y_offset, int unit_type)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_pCAL_SUPPORTED
+PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
+ png_int_32 X0, png_int_32 X1, int type, int nparams,
+ png_charp units, png_charpp params)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_pHYs_SUPPORTED
+PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
+ png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
+ int unit_type)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_tIME_SUPPORTED
+PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
+ png_timep mod_time)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_sCAL_SUPPORTED
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
+PNG_EXTERN void png_write_sCAL PNGARG((png_structp png_ptr,
+ int unit, double width, double height)) PNG_PRIVATE;
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
+ int unit, png_charp width, png_charp height)) PNG_PRIVATE;
+#endif
+#endif
+#endif
+
+/* Called when finished processing a row of data */
+PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Internal use only. Called before first row of data */
+PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#endif
+
+/* Combine a row of data, dealing with alpha, etc. if requested */
+PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
+ int mask)) PNG_PRIVATE;
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+/* Expand an interlaced row */
+/* OLD pre-1.0.9 interface:
+PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
+ png_bytep row, int pass, png_uint_32 transformations)) PNG_PRIVATE;
+ */
+PNG_EXTERN void png_do_read_interlace PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#endif
+
+/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+/* Grab pixels out of a row for an interlaced pass */
+PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
+ png_bytep row, int pass)) PNG_PRIVATE;
+#endif
+
+/* Unfilter a row */
+PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr,
+ png_row_infop row_info, png_bytep row, png_bytep prev_row,
+ int filter)) PNG_PRIVATE;
+
+/* Choose the best filter to use and filter the row data */
+PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
+ png_row_infop row_info)) PNG_PRIVATE;
+
+/* Write out the filtered row. */
+PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr,
+ png_bytep filtered_row)) PNG_PRIVATE;
+/* Finish a row while reading, dealing with interlacing passes, etc. */
+PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
+
+/* Initialize the row buffers, etc. */
+PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+/* Optional call to update the users info structure */
+PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+
+/* These are the functions that do the transformations */
+#ifdef PNG_READ_FILLER_SUPPORTED
+PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
+ png_bytep row, png_uint_32 filler, png_uint_32 flags)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+ defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info,
+ png_bytep row, png_uint_32 flags)) PNG_PRIVATE;
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED) || defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr, png_row_infop
+ row_info, png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info, png_bytep row,
+ png_color_8p sig_bits)) PNG_PRIVATE;
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+PNG_EXTERN void png_do_dither PNGARG((png_row_infop row_info,
+ png_bytep row, png_bytep palette_lookup,
+ png_bytep dither_lookup)) PNG_PRIVATE;
+
+# ifdef PNG_CORRECT_PALETTE_SUPPORTED
+PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
+ png_colorp palette, int num_palette)) PNG_PRIVATE;
+# endif
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_PACK_SUPPORTED
+PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
+ png_bytep row, png_uint_32 bit_depth)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row,
+ png_color_8p bit_depth)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+#ifdef PNG_READ_GAMMA_SUPPORTED
+PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
+ png_color_16p trans_values, png_color_16p background,
+ png_color_16p background_1,
+ png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+ png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+ png_uint_16pp gamma_16_to_1, int gamma_shift)) PNG_PRIVATE;
+#else
+PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, png_bytep row,
+ png_color_16p trans_values, png_color_16p background)) PNG_PRIVATE;
+#endif
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, png_bytep row,
+ png_bytep gamma_table, png_uint_16pp gamma_16_table,
+ int gamma_shift)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
+ png_bytep row, png_colorp palette, png_bytep trans,
+ int num_trans)) PNG_PRIVATE;
+PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
+ png_bytep row, png_color_16p trans_value)) PNG_PRIVATE;
+#endif
+
+/* The following decodes the appropriate chunks, and does error correction,
+ * then calls the appropriate callback for the chunk if it is valid.
+ */
+
+/* Decode the IHDR chunk */
+PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length));
+PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length));
+
+#ifdef PNG_READ_bKGD_SUPPORTED
+PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_cHRM_SUPPORTED
+PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_gAMA_SUPPORTED
+PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_hIST_SUPPORTED
+PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_iCCP_SUPPORTED
+extern void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length));
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#ifdef PNG_READ_iTXt_SUPPORTED
+PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_oFFs_SUPPORTED
+PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_pCAL_SUPPORTED
+PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_pHYs_SUPPORTED
+PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_sBIT_SUPPORTED
+PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_sCAL_SUPPORTED
+PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_sPLT_SUPPORTED
+extern void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#ifdef PNG_READ_sRGB_SUPPORTED
+PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_tEXt_SUPPORTED
+PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_tIME_SUPPORTED
+PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_tRNS_SUPPORTED
+PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_READ_zTXt_SUPPORTED
+PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+#endif
+
+PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
+
+PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
+ png_bytep chunk_name)) PNG_PRIVATE;
+
+/* Handle the transformations for reading and writing */
+PNG_EXTERN void png_do_read_transformations
+ PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_do_write_transformations
+ PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+PNG_EXTERN void png_init_read_transformations
+ PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
+ png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
+ png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
+ png_bytep buffer, png_size_t buffer_length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr,
+ png_bytep row)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+PNG_EXTERN void png_read_push_finish_row
+ PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#ifdef PNG_READ_tEXt_SUPPORTED
+PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr, png_uint_32 length)) PNG_PRIVATE;
+PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
+ png_infop info_ptr)) PNG_PRIVATE;
+#endif
+
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
+ png_bytep row)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#ifdef PNG_MMX_CODE_SUPPORTED
+/* png.c */ /* PRIVATE */
+PNG_EXTERN void png_init_mmx_flags PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+#endif
+#endif
+
+
+/* The following six functions will be exported in libpng-1.4.0. */
+#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
+PNG_EXTERN png_uint_32 png_get_pixels_per_inch PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+PNG_EXTERN png_uint_32 png_get_x_pixels_per_inch PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+PNG_EXTERN png_uint_32 png_get_y_pixels_per_inch PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+PNG_EXTERN float png_get_x_offset_inches PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+PNG_EXTERN float png_get_y_offset_inches PNGARG((png_structp png_ptr,
+png_infop info_ptr));
+
+#ifdef PNG_pHYs_SUPPORTED
+PNG_EXTERN png_uint_32 png_get_pHYs_dpi PNGARG((png_structp png_ptr,
+png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+#endif /* PNG_pHYs_SUPPORTED */
+#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
+
+/* Read the chunk header (length + type name) */
+PNG_EXTERN png_uint_32 png_read_chunk_header
+ PNGARG((png_structp png_ptr)) PNG_PRIVATE;
+
+/* Added at libpng version 1.2.34 */
+#ifdef PNG_cHRM_SUPPORTED
+PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
+ png_fixed_point int_white_x, png_fixed_point int_white_y,
+ png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
+ int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
+ png_fixed_point int_blue_y)) PNG_PRIVATE;
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+/* Added at libpng version 1.2.34 */
+PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
+ unsigned long *hi_product, unsigned long *lo_product)) PNG_PRIVATE;
+#endif
+#endif
+
+/* Added at libpng version 1.2.41 */
+PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
+ png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_type, int compression_type,
+ int filter_type)) PNG_PRIVATE;
+
+/* Added at libpng version 1.2.41 */
+PNG_EXTERN png_voidp png_calloc PNGARG((png_structp png_ptr,
+ png_uint_32 size));
+
+/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+
+#endif /* PNG_INTERNAL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PNG_VERSION_INFO_ONLY */
+/* Do not put anything past this line */
+#endif /* PNG_H */
diff --git a/Source/LibPNG/pngbar.jpg b/Source/LibPNG/pngbar.jpg
new file mode 100644
index 0000000..70ba8d8
--- /dev/null
+++ b/Source/LibPNG/pngbar.jpg
Binary files differ
diff --git a/Source/LibPNG/pngbar.png b/Source/LibPNG/pngbar.png
new file mode 100644
index 0000000..49798c8
--- /dev/null
+++ b/Source/LibPNG/pngbar.png
Binary files differ
diff --git a/Source/LibPNG/pngconf.h b/Source/LibPNG/pngconf.h
new file mode 100644
index 0000000..7070fea
--- /dev/null
+++ b/Source/LibPNG/pngconf.h
@@ -0,0 +1,1681 @@
+
+/* pngconf.h - machine configurable file for libpng
+ *
+ * libpng version 1.2.49 - March 29, 2012
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+/* Any machine specific code is near the front of this file, so if you
+ * are configuring libpng for a machine, you may want to read the section
+ * starting here down to where it starts to typedef png_color, png_text,
+ * and png_info.
+ */
+
+#ifndef PNGCONF_H
+#define PNGCONF_H
+
+#define PNG_1_2_X
+
+/* ------------------------------------------------ */
+/** Added by FreeImage
+*/
+#define PNG_iTXt_SUPPORTED
+#define PNG_READ_iTXt_SUPPORTED
+#define PNG_WRITE_iTXt_SUPPORTED
+
+#if defined(_MSC_VER) || (defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__)) && defined(__GNUC__)
+#define PNG_ASSEMBLER_CODE_SUPPORTED
+#else
+#undef PNG_ASSEMBLER_CODE_SUPPORTED
+#define PNG_NO_ASSEMBLER_CODE
+#define PNG_NO_MMX_CODE
+#endif // i386 || x86_64
+/* ------------------------------------------------ */
+
+/*
+ * PNG_USER_CONFIG has to be defined on the compiler command line. This
+ * includes the resource compiler for Windows DLL configurations.
+ */
+#ifdef PNG_USER_CONFIG
+# ifndef PNG_USER_PRIVATEBUILD
+# define PNG_USER_PRIVATEBUILD
+# endif
+#include "pngusr.h"
+#endif
+
+/* PNG_CONFIGURE_LIBPNG is set by the "configure" script. */
+#ifdef PNG_CONFIGURE_LIBPNG
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#endif
+
+/*
+ * Added at libpng-1.2.8
+ *
+ * If you create a private DLL you need to define in "pngusr.h" the followings:
+ * #define PNG_USER_PRIVATEBUILD <Describes by whom and why this version of
+ * the DLL was built>
+ * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons."
+ * #define PNG_USER_DLLFNAME_POSTFIX <two-letter postfix that serve to
+ * distinguish your DLL from those of the official release. These
+ * correspond to the trailing letters that come after the version
+ * number and must match your private DLL name>
+ * e.g. // private DLL "libpng13gx.dll"
+ * #define PNG_USER_DLLFNAME_POSTFIX "gx"
+ *
+ * The following macros are also at your disposal if you want to complete the
+ * DLL VERSIONINFO structure.
+ * - PNG_USER_VERSIONINFO_COMMENTS
+ * - PNG_USER_VERSIONINFO_COMPANYNAME
+ * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS
+ */
+
+#ifdef __STDC__
+#ifdef SPECIALBUILD
+# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\
+ are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.")
+#endif
+
+#ifdef PRIVATEBUILD
+# pragma message("PRIVATEBUILD is deprecated.\
+ Use PNG_USER_PRIVATEBUILD instead.")
+# define PNG_USER_PRIVATEBUILD PRIVATEBUILD
+#endif
+#endif /* __STDC__ */
+
+#ifndef PNG_VERSION_INFO_ONLY
+
+/* End of material added to libpng-1.2.8 */
+
+/* Added at libpng-1.2.19, removed at libpng-1.2.20 because it caused trouble
+ Restored at libpng-1.2.21 */
+#if !defined(PNG_NO_WARN_UNINITIALIZED_ROW) && \
+ !defined(PNG_WARN_UNINITIALIZED_ROW)
+# define PNG_WARN_UNINITIALIZED_ROW 1
+#endif
+/* End of material added at libpng-1.2.19/1.2.21 */
+
+/* This is the size of the compression buffer, and thus the size of
+ * an IDAT chunk. Make this whatever size you feel is best for your
+ * machine. One of these will be allocated per png_struct. When this
+ * is full, it writes the data to the disk, and does some other
+ * calculations. Making this an extremely small size will slow
+ * the library down, but you may want to experiment to determine
+ * where it becomes significant, if you are concerned with memory
+ * usage. Note that zlib allocates at least 32Kb also. For readers,
+ * this describes the size of the buffer available to read the data in.
+ * Unless this gets smaller than the size of a row (compressed),
+ * it should not make much difference how big this is.
+ */
+
+#ifndef PNG_ZBUF_SIZE
+# define PNG_ZBUF_SIZE 8192
+#endif
+
+/* Enable if you want a write-only libpng */
+
+#ifndef PNG_NO_READ_SUPPORTED
+# define PNG_READ_SUPPORTED
+#endif
+
+/* Enable if you want a read-only libpng */
+
+#ifndef PNG_NO_WRITE_SUPPORTED
+# define PNG_WRITE_SUPPORTED
+#endif
+
+/* Enabled in 1.2.41. */
+#ifdef PNG_ALLOW_BENIGN_ERRORS
+# define png_benign_error png_warning
+# define png_chunk_benign_error png_chunk_warning
+#else
+# ifndef PNG_BENIGN_ERRORS_SUPPORTED
+# define png_benign_error png_error
+# define png_chunk_benign_error png_chunk_error
+# endif
+#endif
+
+/* Added in libpng-1.2.41 */
+#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED)
+# define PNG_WARNINGS_SUPPORTED
+#endif
+
+#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED)
+# define PNG_ERROR_TEXT_SUPPORTED
+#endif
+
+#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED)
+# define PNG_CHECK_cHRM_SUPPORTED
+#endif
+
+/* Enabled by default in 1.2.0. You can disable this if you don't need to
+ * support PNGs that are embedded in MNG datastreams
+ */
+#if !defined(PNG_1_0_X) && !defined(PNG_NO_MNG_FEATURES)
+# ifndef PNG_MNG_FEATURES_SUPPORTED
+# define PNG_MNG_FEATURES_SUPPORTED
+# endif
+#endif
+
+#ifndef PNG_NO_FLOATING_POINT_SUPPORTED
+# ifndef PNG_FLOATING_POINT_SUPPORTED
+# define PNG_FLOATING_POINT_SUPPORTED
+# endif
+#endif
+
+/* If you are running on a machine where you cannot allocate more
+ * than 64K of memory at once, uncomment this. While libpng will not
+ * normally need that much memory in a chunk (unless you load up a very
+ * large file), zlib needs to know how big of a chunk it can use, and
+ * libpng thus makes sure to check any memory allocation to verify it
+ * will fit into memory.
+#define PNG_MAX_MALLOC_64K
+ */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+# define PNG_MAX_MALLOC_64K
+#endif
+
+/* Special munging to support doing things the 'cygwin' way:
+ * 'Normal' png-on-win32 defines/defaults:
+ * PNG_BUILD_DLL -- building dll
+ * PNG_USE_DLL -- building an application, linking to dll
+ * (no define) -- building static library, or building an
+ * application and linking to the static lib
+ * 'Cygwin' defines/defaults:
+ * PNG_BUILD_DLL -- (ignored) building the dll
+ * (no define) -- (ignored) building an application, linking to the dll
+ * PNG_STATIC -- (ignored) building the static lib, or building an
+ * application that links to the static lib.
+ * ALL_STATIC -- (ignored) building various static libs, or building an
+ * application that links to the static libs.
+ * Thus,
+ * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and
+ * this bit of #ifdefs will define the 'correct' config variables based on
+ * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but
+ * unnecessary.
+ *
+ * Also, the precedence order is:
+ * ALL_STATIC (since we can't #undef something outside our namespace)
+ * PNG_BUILD_DLL
+ * PNG_STATIC
+ * (nothing) == PNG_USE_DLL
+ *
+ * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent
+ * of auto-import in binutils, we no longer need to worry about
+ * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore,
+ * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes
+ * to __declspec() stuff. However, we DO need to worry about
+ * PNG_BUILD_DLL and PNG_STATIC because those change some defaults
+ * such as CONSOLE_IO and whether GLOBAL_ARRAYS are allowed.
+ */
+#ifdef __CYGWIN__
+# ifdef ALL_STATIC
+# ifdef PNG_BUILD_DLL
+# undef PNG_BUILD_DLL
+# endif
+# ifdef PNG_USE_DLL
+# undef PNG_USE_DLL
+# endif
+# ifdef PNG_DLL
+# undef PNG_DLL
+# endif
+# ifndef PNG_STATIC
+# define PNG_STATIC
+# endif
+# else
+# ifdef PNG_BUILD_DLL
+# ifdef PNG_STATIC
+# undef PNG_STATIC
+# endif
+# ifdef PNG_USE_DLL
+# undef PNG_USE_DLL
+# endif
+# ifndef PNG_DLL
+# define PNG_DLL
+# endif
+# else
+# ifdef PNG_STATIC
+# ifdef PNG_USE_DLL
+# undef PNG_USE_DLL
+# endif
+# ifdef PNG_DLL
+# undef PNG_DLL
+# endif
+# else
+# ifndef PNG_USE_DLL
+# define PNG_USE_DLL
+# endif
+# ifndef PNG_DLL
+# define PNG_DLL
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* This protects us against compilers that run on a windowing system
+ * and thus don't have or would rather us not use the stdio types:
+ * stdin, stdout, and stderr. The only one currently used is stderr
+ * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will
+ * prevent these from being compiled and used. #defining PNG_NO_STDIO
+ * will also prevent these, plus will prevent the entire set of stdio
+ * macros and functions (FILE *, printf, etc.) from being compiled and used,
+ * unless (PNG_DEBUG > 0) has been #defined.
+ *
+ * #define PNG_NO_CONSOLE_IO
+ * #define PNG_NO_STDIO
+ */
+
+#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED)
+# define PNG_STDIO_SUPPORTED
+#endif
+
+#ifdef _WIN32_WCE
+# include <windows.h>
+ /* Console I/O functions are not supported on WindowsCE */
+# define PNG_NO_CONSOLE_IO
+ /* abort() may not be supported on some/all Windows CE platforms */
+# define PNG_ABORT() exit(-1)
+# ifdef PNG_DEBUG
+# undef PNG_DEBUG
+# endif
+#endif
+
+#ifdef PNG_BUILD_DLL
+# ifndef PNG_CONSOLE_IO_SUPPORTED
+# ifndef PNG_NO_CONSOLE_IO
+# define PNG_NO_CONSOLE_IO
+# endif
+# endif
+#endif
+
+# ifdef PNG_NO_STDIO
+# ifndef PNG_NO_CONSOLE_IO
+# define PNG_NO_CONSOLE_IO
+# endif
+# ifdef PNG_DEBUG
+# if (PNG_DEBUG > 0)
+# include <stdio.h>
+# endif
+# endif
+# else
+# ifndef _WIN32_WCE
+/* "stdio.h" functions are not supported on WindowsCE */
+# include <stdio.h>
+# endif
+# endif
+
+#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED)
+# define PNG_CONSOLE_IO_SUPPORTED
+#endif
+
+/* This macro protects us against machines that don't have function
+ * prototypes (ie K&R style headers). If your compiler does not handle
+ * function prototypes, define this macro and use the included ansi2knr.
+ * I've always been able to use _NO_PROTO as the indicator, but you may
+ * need to drag the empty declaration out in front of here, or change the
+ * ifdef to suit your own needs.
+ */
+#ifndef PNGARG
+
+#ifdef OF /* zlib prototype munger */
+# define PNGARG(arglist) OF(arglist)
+#else
+
+#ifdef _NO_PROTO
+# define PNGARG(arglist) ()
+# ifndef PNG_TYPECAST_NULL
+# define PNG_TYPECAST_NULL
+# endif
+#else
+# define PNGARG(arglist) arglist
+#endif /* _NO_PROTO */
+
+
+#endif /* OF */
+
+#endif /* PNGARG */
+
+/* Try to determine if we are compiling on a Mac. Note that testing for
+ * just __MWERKS__ is not good enough, because the Codewarrior is now used
+ * on non-Mac platforms.
+ */
+#ifndef MACOS
+# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
+ defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
+# define MACOS
+# endif
+#endif
+
+/* enough people need this for various reasons to include it here */
+#if !defined(MACOS) && !defined(RISCOS) && !defined(_WIN32_WCE)
+# include <sys/types.h>
+#endif
+
+#if !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED)
+# define PNG_SETJMP_SUPPORTED
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+/* This is an attempt to force a single setjmp behaviour on Linux. If
+ * the X config stuff didn't define _BSD_SOURCE we wouldn't need this.
+ *
+ * You can bypass this test if you know that your application uses exactly
+ * the same setjmp.h that was included when libpng was built. Only define
+ * PNG_SKIP_SETJMP_CHECK while building your application, prior to the
+ * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK
+ * while building a separate libpng library for general use.
+ */
+
+# ifndef PNG_SKIP_SETJMP_CHECK
+# ifdef __linux__
+# ifdef _BSD_SOURCE
+# define PNG_SAVE_BSD_SOURCE
+# undef _BSD_SOURCE
+# endif
+# ifdef _SETJMP_H
+ /* If you encounter a compiler error here, see the explanation
+ * near the end of INSTALL.
+ */
+ __pngconf.h__ in libpng already includes setjmp.h;
+ __dont__ include it again.;
+# endif
+# endif /* __linux__ */
+# endif /* PNG_SKIP_SETJMP_CHECK */
+
+ /* include setjmp.h for error handling */
+# include <setjmp.h>
+
+# ifdef __linux__
+# ifdef PNG_SAVE_BSD_SOURCE
+# ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+# endif
+# undef PNG_SAVE_BSD_SOURCE
+# endif
+# endif /* __linux__ */
+#endif /* PNG_SETJMP_SUPPORTED */
+
+#ifdef BSD
+# include <strings.h>
+#else
+# include <string.h>
+#endif
+
+/* Other defines for things like memory and the like can go here. */
+#ifdef PNG_INTERNAL
+
+#include <stdlib.h>
+
+/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which
+ * aren't usually used outside the library (as far as I know), so it is
+ * debatable if they should be exported at all. In the future, when it is
+ * possible to have run-time registry of chunk-handling functions, some of
+ * these will be made available again.
+#define PNG_EXTERN extern
+ */
+#define PNG_EXTERN
+
+/* Other defines specific to compilers can go here. Try to keep
+ * them inside an appropriate ifdef/endif pair for portability.
+ */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+# ifdef MACOS
+ /* We need to check that <math.h> hasn't already been included earlier
+ * as it seems it doesn't agree with <fp.h>, yet we should really use
+ * <fp.h> if possible.
+ */
+# if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
+# include <fp.h>
+# endif
+# else
+# include <math.h>
+# endif
+# if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
+ /* Amiga SAS/C: We must include builtin FPU functions when compiling using
+ * MATH=68881
+ */
+# include <m68881.h>
+# endif
+#endif
+
+/* Codewarrior on NT has linking problems without this. */
+#if (defined(__MWERKS__) && defined(WIN32)) || defined(__STDC__)
+# define PNG_ALWAYS_EXTERN
+#endif
+
+/* This provides the non-ANSI (far) memory allocation routines. */
+#if defined(__TURBOC__) && defined(__MSDOS__)
+# include <mem.h>
+# include <alloc.h>
+#endif
+
+/* I have no idea why is this necessary... */
+#if defined(_MSC_VER) && (defined(WIN32) || defined(_Windows) || \
+ defined(_WINDOWS) || defined(_WIN32) || defined(__WIN32__))
+# include <malloc.h>
+#endif
+
+/* This controls how fine the dithering gets. As this allocates
+ * a largish chunk of memory (32K), those who are not as concerned
+ * with dithering quality can decrease some or all of these.
+ */
+#ifndef PNG_DITHER_RED_BITS
+# define PNG_DITHER_RED_BITS 5
+#endif
+#ifndef PNG_DITHER_GREEN_BITS
+# define PNG_DITHER_GREEN_BITS 5
+#endif
+#ifndef PNG_DITHER_BLUE_BITS
+# define PNG_DITHER_BLUE_BITS 5
+#endif
+
+/* This controls how fine the gamma correction becomes when you
+ * are only interested in 8 bits anyway. Increasing this value
+ * results in more memory being used, and more pow() functions
+ * being called to fill in the gamma tables. Don't set this value
+ * less then 8, and even that may not work (I haven't tested it).
+ */
+
+#ifndef PNG_MAX_GAMMA_8
+# define PNG_MAX_GAMMA_8 11
+#endif
+
+/* This controls how much a difference in gamma we can tolerate before
+ * we actually start doing gamma conversion.
+ */
+#ifndef PNG_GAMMA_THRESHOLD
+# define PNG_GAMMA_THRESHOLD 0.05
+#endif
+
+#endif /* PNG_INTERNAL */
+
+/* The following uses const char * instead of char * for error
+ * and warning message functions, so some compilers won't complain.
+ * If you do not want to use const, define PNG_NO_CONST here.
+ */
+
+#ifndef PNG_NO_CONST
+# define PNG_CONST const
+#else
+# define PNG_CONST
+#endif
+
+/* The following defines give you the ability to remove code from the
+ * library that you will not be using. I wish I could figure out how to
+ * automate this, but I can't do that without making it seriously hard
+ * on the users. So if you are not using an ability, change the #define
+ * to and #undef, and that part of the library will not be compiled. If
+ * your linker can't find a function, you may want to make sure the
+ * ability is defined here. Some of these depend upon some others being
+ * defined. I haven't figured out all the interactions here, so you may
+ * have to experiment awhile to get everything to compile. If you are
+ * creating or using a shared library, you probably shouldn't touch this,
+ * as it will affect the size of the structures, and this will cause bad
+ * things to happen if the library and/or application ever change.
+ */
+
+/* Any features you will not be using can be undef'ed here */
+
+/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user
+ * to turn it off with "*TRANSFORMS_NOT_SUPPORTED" or *PNG_NO_*_TRANSFORMS
+ * on the compile line, then pick and choose which ones to define without
+ * having to edit this file. It is safe to use the *TRANSFORMS_NOT_SUPPORTED
+ * if you only want to have a png-compliant reader/writer but don't need
+ * any of the extra transformations. This saves about 80 kbytes in a
+ * typical installation of the library. (PNG_NO_* form added in version
+ * 1.0.1c, for consistency)
+ */
+
+/* The size of the png_text structure changed in libpng-1.0.6 when
+ * iTXt support was added. iTXt support was turned off by default through
+ * libpng-1.2.x, to support old apps that malloc the png_text structure
+ * instead of calling png_set_text() and letting libpng malloc it. It
+ * will be turned on by default in libpng-1.4.0.
+ */
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+# ifndef PNG_NO_iTXt_SUPPORTED
+# define PNG_NO_iTXt_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_iTXt
+# define PNG_NO_READ_iTXt
+# endif
+# ifndef PNG_NO_WRITE_iTXt
+# define PNG_NO_WRITE_iTXt
+# endif
+#endif
+
+#if !defined(PNG_NO_iTXt_SUPPORTED)
+# if !defined(PNG_READ_iTXt_SUPPORTED) && !defined(PNG_NO_READ_iTXt)
+# define PNG_READ_iTXt
+# endif
+# if !defined(PNG_WRITE_iTXt_SUPPORTED) && !defined(PNG_NO_WRITE_iTXt)
+# define PNG_WRITE_iTXt
+# endif
+#endif
+
+/* The following support, added after version 1.0.0, can be turned off here en
+ * masse by defining PNG_LEGACY_SUPPORTED in case you need binary compatibility
+ * with old applications that require the length of png_struct and png_info
+ * to remain unchanged.
+ */
+
+#ifdef PNG_LEGACY_SUPPORTED
+# define PNG_NO_FREE_ME
+# define PNG_NO_READ_UNKNOWN_CHUNKS
+# define PNG_NO_WRITE_UNKNOWN_CHUNKS
+# define PNG_NO_HANDLE_AS_UNKNOWN
+# define PNG_NO_READ_USER_CHUNKS
+# define PNG_NO_READ_iCCP
+# define PNG_NO_WRITE_iCCP
+# define PNG_NO_READ_iTXt
+# define PNG_NO_WRITE_iTXt
+# define PNG_NO_READ_sCAL
+# define PNG_NO_WRITE_sCAL
+# define PNG_NO_READ_sPLT
+# define PNG_NO_WRITE_sPLT
+# define PNG_NO_INFO_IMAGE
+# define PNG_NO_READ_RGB_TO_GRAY
+# define PNG_NO_READ_USER_TRANSFORM
+# define PNG_NO_WRITE_USER_TRANSFORM
+# define PNG_NO_USER_MEM
+# define PNG_NO_READ_EMPTY_PLTE
+# define PNG_NO_MNG_FEATURES
+# define PNG_NO_FIXED_POINT_SUPPORTED
+#endif
+
+/* Ignore attempt to turn off both floating and fixed point support */
+#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \
+ !defined(PNG_NO_FIXED_POINT_SUPPORTED)
+# define PNG_FIXED_POINT_SUPPORTED
+#endif
+
+#ifndef PNG_NO_FREE_ME
+# define PNG_FREE_ME_SUPPORTED
+#endif
+
+#ifdef PNG_READ_SUPPORTED
+
+#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \
+ !defined(PNG_NO_READ_TRANSFORMS)
+# define PNG_READ_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+# ifndef PNG_NO_READ_EXPAND
+# define PNG_READ_EXPAND_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_SHIFT
+# define PNG_READ_SHIFT_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_PACK
+# define PNG_READ_PACK_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_BGR
+# define PNG_READ_BGR_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_SWAP
+# define PNG_READ_SWAP_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_PACKSWAP
+# define PNG_READ_PACKSWAP_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_INVERT
+# define PNG_READ_INVERT_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_DITHER
+# define PNG_READ_DITHER_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_BACKGROUND
+# define PNG_READ_BACKGROUND_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_16_TO_8
+# define PNG_READ_16_TO_8_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_FILLER
+# define PNG_READ_FILLER_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_GAMMA
+# define PNG_READ_GAMMA_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_GRAY_TO_RGB
+# define PNG_READ_GRAY_TO_RGB_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_SWAP_ALPHA
+# define PNG_READ_SWAP_ALPHA_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_INVERT_ALPHA
+# define PNG_READ_INVERT_ALPHA_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_STRIP_ALPHA
+# define PNG_READ_STRIP_ALPHA_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_USER_TRANSFORM
+# define PNG_READ_USER_TRANSFORM_SUPPORTED
+# endif
+# ifndef PNG_NO_READ_RGB_TO_GRAY
+# define PNG_READ_RGB_TO_GRAY_SUPPORTED
+# endif
+#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+
+/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */
+#if !defined(PNG_NO_PROGRESSIVE_READ) && \
+ !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */
+# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */
+#endif /* about interlacing capability! You'll */
+ /* still have interlacing unless you change the following define: */
+#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */
+
+/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */
+#if !defined(PNG_NO_SEQUENTIAL_READ) && \
+ !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \
+ !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED)
+# define PNG_SEQUENTIAL_READ_SUPPORTED
+#endif
+
+#define PNG_READ_INTERLACING_SUPPORTED /* required in PNG-compliant decoders */
+
+#ifndef PNG_NO_READ_COMPOSITE_NODIV
+# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */
+# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */
+# endif
+#endif
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Deprecated, will be removed from version 2.0.0.
+ Use PNG_MNG_FEATURES_SUPPORTED instead. */
+#ifndef PNG_NO_READ_EMPTY_PLTE
+# define PNG_READ_EMPTY_PLTE_SUPPORTED
+#endif
+#endif
+
+#endif /* PNG_READ_SUPPORTED */
+
+#ifdef PNG_WRITE_SUPPORTED
+
+# if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \
+ !defined(PNG_NO_WRITE_TRANSFORMS)
+# define PNG_WRITE_TRANSFORMS_SUPPORTED
+#endif
+
+#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
+# ifndef PNG_NO_WRITE_SHIFT
+# define PNG_WRITE_SHIFT_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_PACK
+# define PNG_WRITE_PACK_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_BGR
+# define PNG_WRITE_BGR_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_SWAP
+# define PNG_WRITE_SWAP_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_PACKSWAP
+# define PNG_WRITE_PACKSWAP_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_INVERT
+# define PNG_WRITE_INVERT_SUPPORTED
+# endif
+# ifndef PNG_NO_WRITE_FILLER
+# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */
+# endif
+# ifndef PNG_NO_WRITE_SWAP_ALPHA
+# define PNG_WRITE_SWAP_ALPHA_SUPPORTED
+# endif
+#ifndef PNG_1_0_X
+# ifndef PNG_NO_WRITE_INVERT_ALPHA
+# define PNG_WRITE_INVERT_ALPHA_SUPPORTED
+# endif
+#endif
+# ifndef PNG_NO_WRITE_USER_TRANSFORM
+# define PNG_WRITE_USER_TRANSFORM_SUPPORTED
+# endif
+#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
+
+#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \
+ !defined(PNG_WRITE_INTERLACING_SUPPORTED)
+#define PNG_WRITE_INTERLACING_SUPPORTED /* not required for PNG-compliant
+ encoders, but can cause trouble
+ if left undefined */
+#endif
+
+#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \
+ !defined(PNG_WRITE_WEIGHTED_FILTER) && \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
+# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#endif
+
+#ifndef PNG_NO_WRITE_FLUSH
+# define PNG_WRITE_FLUSH_SUPPORTED
+#endif
+
+#if defined(PNG_1_0_X) || defined (PNG_1_2_X)
+/* Deprecated, see PNG_MNG_FEATURES_SUPPORTED, above */
+#ifndef PNG_NO_WRITE_EMPTY_PLTE
+# define PNG_WRITE_EMPTY_PLTE_SUPPORTED
+#endif
+#endif
+
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef PNG_1_0_X
+# ifndef PNG_NO_ERROR_NUMBERS
+# define PNG_ERROR_NUMBERS_SUPPORTED
+# endif
+#endif /* PNG_1_0_X */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+# ifndef PNG_NO_USER_TRANSFORM_PTR
+# define PNG_USER_TRANSFORM_PTR_SUPPORTED
+# endif
+#endif
+
+#ifndef PNG_NO_STDIO
+# define PNG_TIME_RFC1123_SUPPORTED
+#endif
+
+/* This adds extra functions in pngget.c for accessing data from the
+ * info pointer (added in version 0.99)
+ * png_get_image_width()
+ * png_get_image_height()
+ * png_get_bit_depth()
+ * png_get_color_type()
+ * png_get_compression_type()
+ * png_get_filter_type()
+ * png_get_interlace_type()
+ * png_get_pixel_aspect_ratio()
+ * png_get_pixels_per_meter()
+ * png_get_x_offset_pixels()
+ * png_get_y_offset_pixels()
+ * png_get_x_offset_microns()
+ * png_get_y_offset_microns()
+ */
+#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED)
+# define PNG_EASY_ACCESS_SUPPORTED
+#endif
+
+/* PNG_ASSEMBLER_CODE was enabled by default in version 1.2.0
+ * and removed from version 1.2.20. The following will be removed
+ * from libpng-1.4.0
+*/
+
+#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_OPTIMIZED_CODE)
+# ifndef PNG_OPTIMIZED_CODE_SUPPORTED
+# define PNG_OPTIMIZED_CODE_SUPPORTED
+# endif
+#endif
+
+#if defined(PNG_READ_SUPPORTED) && !defined(PNG_NO_ASSEMBLER_CODE)
+# ifndef PNG_ASSEMBLER_CODE_SUPPORTED
+# define PNG_ASSEMBLER_CODE_SUPPORTED
+# endif
+
+# if defined(__GNUC__) && defined(__x86_64__) && (__GNUC__ < 4)
+ /* work around 64-bit gcc compiler bugs in gcc-3.x */
+# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+# define PNG_NO_MMX_CODE
+# endif
+# endif
+
+# ifdef __APPLE__
+# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+# define PNG_NO_MMX_CODE
+# endif
+# endif
+
+# if (defined(__MWERKS__) && ((__MWERKS__ < 0x0900) || macintosh))
+# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+# define PNG_NO_MMX_CODE
+# endif
+# endif
+
+# if !defined(PNG_MMX_CODE_SUPPORTED) && !defined(PNG_NO_MMX_CODE)
+# define PNG_MMX_CODE_SUPPORTED
+# endif
+
+#endif
+/* end of obsolete code to be removed from libpng-1.4.0 */
+
+/* Added at libpng-1.2.0 */
+#ifndef PNG_1_0_X
+#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED)
+# define PNG_USER_MEM_SUPPORTED
+#endif
+#endif /* PNG_1_0_X */
+
+/* Added at libpng-1.2.6 */
+#ifndef PNG_1_0_X
+# ifndef PNG_SET_USER_LIMITS_SUPPORTED
+# ifndef PNG_NO_SET_USER_LIMITS
+# define PNG_SET_USER_LIMITS_SUPPORTED
+# endif
+# endif
+#endif /* PNG_1_0_X */
+
+/* Added at libpng-1.0.53 and 1.2.43 */
+#ifndef PNG_USER_LIMITS_SUPPORTED
+# ifndef PNG_NO_USER_LIMITS
+# define PNG_USER_LIMITS_SUPPORTED
+# endif
+#endif
+
+/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGS no matter
+ * how large, set these limits to 0x7fffffffL
+ */
+#ifndef PNG_USER_WIDTH_MAX
+# define PNG_USER_WIDTH_MAX 1000000L
+#endif
+#ifndef PNG_USER_HEIGHT_MAX
+# define PNG_USER_HEIGHT_MAX 1000000L
+#endif
+
+/* Added at libpng-1.2.43. To accept all valid PNGs no matter
+ * how large, set these two limits to 0.
+ */
+#ifndef PNG_USER_CHUNK_CACHE_MAX
+# define PNG_USER_CHUNK_CACHE_MAX 0
+#endif
+
+/* Added at libpng-1.2.43 */
+#ifndef PNG_USER_CHUNK_MALLOC_MAX
+# define PNG_USER_CHUNK_MALLOC_MAX 0
+#endif
+
+#ifndef PNG_LITERAL_SHARP
+# define PNG_LITERAL_SHARP 0x23
+#endif
+#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
+# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
+#endif
+#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
+# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
+#endif
+
+/* Added at libpng-1.2.34 */
+#ifndef PNG_STRING_NEWLINE
+#define PNG_STRING_NEWLINE "\n"
+#endif
+
+/* These are currently experimental features, define them if you want */
+
+/* very little testing */
+/*
+#ifdef PNG_READ_SUPPORTED
+# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+# endif
+#endif
+*/
+
+/* This is only for PowerPC big-endian and 680x0 systems */
+/* some testing */
+/*
+#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
+# define PNG_READ_BIG_ENDIAN_SUPPORTED
+#endif
+*/
+
+/* Buggy compilers (e.g., gcc 2.7.2.2) need this */
+/*
+#define PNG_NO_POINTER_INDEXING
+*/
+
+#if !defined(PNG_NO_POINTER_INDEXING) && \
+ !defined(PNG_POINTER_INDEXING_SUPPORTED)
+# define PNG_POINTER_INDEXING_SUPPORTED
+#endif
+
+/* These functions are turned off by default, as they will be phased out. */
+/*
+#define PNG_USELESS_TESTS_SUPPORTED
+#define PNG_CORRECT_PALETTE_SUPPORTED
+*/
+
+/* Any chunks you are not interested in, you can undef here. The
+ * ones that allocate memory may be expecially important (hIST,
+ * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info
+ * a bit smaller.
+ */
+
+#if defined(PNG_READ_SUPPORTED) && \
+ !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+ !defined(PNG_NO_READ_ANCILLARY_CHUNKS)
+# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#if defined(PNG_WRITE_SUPPORTED) && \
+ !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \
+ !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS)
+# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+#endif
+
+#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
+
+#ifdef PNG_NO_READ_TEXT
+# define PNG_NO_READ_iTXt
+# define PNG_NO_READ_tEXt
+# define PNG_NO_READ_zTXt
+#endif
+#ifndef PNG_NO_READ_bKGD
+# define PNG_READ_bKGD_SUPPORTED
+# define PNG_bKGD_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_cHRM
+# define PNG_READ_cHRM_SUPPORTED
+# define PNG_cHRM_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_gAMA
+# define PNG_READ_gAMA_SUPPORTED
+# define PNG_gAMA_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_hIST
+# define PNG_READ_hIST_SUPPORTED
+# define PNG_hIST_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iCCP
+# define PNG_READ_iCCP_SUPPORTED
+# define PNG_iCCP_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_iTXt
+# ifndef PNG_READ_iTXt_SUPPORTED
+# define PNG_READ_iTXt_SUPPORTED
+# endif
+# ifndef PNG_iTXt_SUPPORTED
+# define PNG_iTXt_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_READ_oFFs
+# define PNG_READ_oFFs_SUPPORTED
+# define PNG_oFFs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pCAL
+# define PNG_READ_pCAL_SUPPORTED
+# define PNG_pCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sCAL
+# define PNG_READ_sCAL_SUPPORTED
+# define PNG_sCAL_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_pHYs
+# define PNG_READ_pHYs_SUPPORTED
+# define PNG_pHYs_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sBIT
+# define PNG_READ_sBIT_SUPPORTED
+# define PNG_sBIT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sPLT
+# define PNG_READ_sPLT_SUPPORTED
+# define PNG_sPLT_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_sRGB
+# define PNG_READ_sRGB_SUPPORTED
+# define PNG_sRGB_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tEXt
+# define PNG_READ_tEXt_SUPPORTED
+# define PNG_tEXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tIME
+# define PNG_READ_tIME_SUPPORTED
+# define PNG_tIME_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_tRNS
+# define PNG_READ_tRNS_SUPPORTED
+# define PNG_tRNS_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_zTXt
+# define PNG_READ_zTXt_SUPPORTED
+# define PNG_zTXt_SUPPORTED
+#endif
+#ifndef PNG_NO_READ_OPT_PLTE
+# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */
+#endif /* optional PLTE chunk in RGB and RGBA images */
+#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \
+ defined(PNG_READ_zTXt_SUPPORTED)
+# define PNG_READ_TEXT_SUPPORTED
+# define PNG_TEXT_SUPPORTED
+#endif
+
+#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */
+
+#ifndef PNG_NO_READ_UNKNOWN_CHUNKS
+# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+# define PNG_UNKNOWN_CHUNKS_SUPPORTED
+# endif
+#endif
+#if !defined(PNG_NO_READ_USER_CHUNKS) && \
+ defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+# define PNG_READ_USER_CHUNKS_SUPPORTED
+# define PNG_USER_CHUNKS_SUPPORTED
+# ifdef PNG_NO_READ_UNKNOWN_CHUNKS
+# undef PNG_NO_READ_UNKNOWN_CHUNKS
+# endif
+# ifdef PNG_NO_HANDLE_AS_UNKNOWN
+# undef PNG_NO_HANDLE_AS_UNKNOWN
+# endif
+#endif
+
+#ifndef PNG_NO_HANDLE_AS_UNKNOWN
+# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# endif
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
+
+#ifdef PNG_NO_WRITE_TEXT
+# define PNG_NO_WRITE_iTXt
+# define PNG_NO_WRITE_tEXt
+# define PNG_NO_WRITE_zTXt
+#endif
+#ifndef PNG_NO_WRITE_bKGD
+# define PNG_WRITE_bKGD_SUPPORTED
+# ifndef PNG_bKGD_SUPPORTED
+# define PNG_bKGD_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_cHRM
+# define PNG_WRITE_cHRM_SUPPORTED
+# ifndef PNG_cHRM_SUPPORTED
+# define PNG_cHRM_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_gAMA
+# define PNG_WRITE_gAMA_SUPPORTED
+# ifndef PNG_gAMA_SUPPORTED
+# define PNG_gAMA_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_hIST
+# define PNG_WRITE_hIST_SUPPORTED
+# ifndef PNG_hIST_SUPPORTED
+# define PNG_hIST_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_iCCP
+# define PNG_WRITE_iCCP_SUPPORTED
+# ifndef PNG_iCCP_SUPPORTED
+# define PNG_iCCP_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_iTXt
+# ifndef PNG_WRITE_iTXt_SUPPORTED
+# define PNG_WRITE_iTXt_SUPPORTED
+# endif
+# ifndef PNG_iTXt_SUPPORTED
+# define PNG_iTXt_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_oFFs
+# define PNG_WRITE_oFFs_SUPPORTED
+# ifndef PNG_oFFs_SUPPORTED
+# define PNG_oFFs_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_pCAL
+# define PNG_WRITE_pCAL_SUPPORTED
+# ifndef PNG_pCAL_SUPPORTED
+# define PNG_pCAL_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_sCAL
+# define PNG_WRITE_sCAL_SUPPORTED
+# ifndef PNG_sCAL_SUPPORTED
+# define PNG_sCAL_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_pHYs
+# define PNG_WRITE_pHYs_SUPPORTED
+# ifndef PNG_pHYs_SUPPORTED
+# define PNG_pHYs_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_sBIT
+# define PNG_WRITE_sBIT_SUPPORTED
+# ifndef PNG_sBIT_SUPPORTED
+# define PNG_sBIT_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_sPLT
+# define PNG_WRITE_sPLT_SUPPORTED
+# ifndef PNG_sPLT_SUPPORTED
+# define PNG_sPLT_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_sRGB
+# define PNG_WRITE_sRGB_SUPPORTED
+# ifndef PNG_sRGB_SUPPORTED
+# define PNG_sRGB_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_tEXt
+# define PNG_WRITE_tEXt_SUPPORTED
+# ifndef PNG_tEXt_SUPPORTED
+# define PNG_tEXt_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_tIME
+# define PNG_WRITE_tIME_SUPPORTED
+# ifndef PNG_tIME_SUPPORTED
+# define PNG_tIME_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_tRNS
+# define PNG_WRITE_tRNS_SUPPORTED
+# ifndef PNG_tRNS_SUPPORTED
+# define PNG_tRNS_SUPPORTED
+# endif
+#endif
+#ifndef PNG_NO_WRITE_zTXt
+# define PNG_WRITE_zTXt_SUPPORTED
+# ifndef PNG_zTXt_SUPPORTED
+# define PNG_zTXt_SUPPORTED
+# endif
+#endif
+#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
+ defined(PNG_WRITE_zTXt_SUPPORTED)
+# define PNG_WRITE_TEXT_SUPPORTED
+# ifndef PNG_TEXT_SUPPORTED
+# define PNG_TEXT_SUPPORTED
+# endif
+#endif
+
+#ifdef PNG_WRITE_tIME_SUPPORTED
+# ifndef PNG_NO_CONVERT_tIME
+# ifndef _WIN32_WCE
+/* The "tm" structure is not supported on WindowsCE */
+# ifndef PNG_CONVERT_tIME_SUPPORTED
+# define PNG_CONVERT_tIME_SUPPORTED
+# endif
+# endif
+# endif
+#endif
+
+#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */
+
+#if !defined(PNG_NO_WRITE_FILTER) && !defined(PNG_WRITE_FILTER_SUPPORTED)
+# define PNG_WRITE_FILTER_SUPPORTED
+#endif
+
+#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS
+# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED
+# define PNG_UNKNOWN_CHUNKS_SUPPORTED
+# endif
+#endif
+
+#ifndef PNG_NO_HANDLE_AS_UNKNOWN
+# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# endif
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
+
+/* Turn this off to disable png_read_png() and
+ * png_write_png() and leave the row_pointers member
+ * out of the info structure.
+ */
+#ifndef PNG_NO_INFO_IMAGE
+# define PNG_INFO_IMAGE_SUPPORTED
+#endif
+
+/* Need the time information for converting tIME chunks */
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+ /* "time.h" functions are not supported on WindowsCE */
+# include <time.h>
+#endif
+
+/* Some typedefs to get us started. These should be safe on most of the
+ * common platforms. The typedefs should be at least as large as the
+ * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
+ * don't have to be exactly that size. Some compilers dislike passing
+ * unsigned shorts as function parameters, so you may be better off using
+ * unsigned int for png_uint_16. Likewise, for 64-bit systems, you may
+ * want to have unsigned int for png_uint_32 instead of unsigned long.
+ */
+
+typedef unsigned long png_uint_32;
+typedef long png_int_32;
+typedef unsigned short png_uint_16;
+typedef short png_int_16;
+typedef unsigned char png_byte;
+
+/* This is usually size_t. It is typedef'ed just in case you need it to
+ change (I'm not sure if you will or not, so I thought I'd be safe) */
+#ifdef PNG_SIZE_T
+ typedef PNG_SIZE_T png_size_t;
+# define png_sizeof(x) png_convert_size(sizeof(x))
+#else
+ typedef size_t png_size_t;
+# define png_sizeof(x) sizeof(x)
+#endif
+
+/* The following is needed for medium model support. It cannot be in the
+ * PNG_INTERNAL section. Needs modification for other compilers besides
+ * MSC. Model independent support declares all arrays and pointers to be
+ * large using the far keyword. The zlib version used must also support
+ * model independent data. As of version zlib 1.0.4, the necessary changes
+ * have been made in zlib. The USE_FAR_KEYWORD define triggers other
+ * changes that are needed. (Tim Wegner)
+ */
+
+/* Separate compiler dependencies (problem here is that zlib.h always
+ defines FAR. (SJT) */
+#ifdef __BORLANDC__
+# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
+# define LDATA 1
+# else
+# define LDATA 0
+# endif
+ /* GRR: why is Cygwin in here? Cygwin is not Borland C... */
+# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
+# define PNG_MAX_MALLOC_64K
+# if (LDATA != 1)
+# ifndef FAR
+# define FAR __far
+# endif
+# define USE_FAR_KEYWORD
+# endif /* LDATA != 1 */
+ /* Possibly useful for moving data out of default segment.
+ * Uncomment it if you want. Could also define FARDATA as
+ * const if your compiler supports it. (SJT)
+# define FARDATA FAR
+ */
+# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
+#endif /* __BORLANDC__ */
+
+
+/* Suggest testing for specific compiler first before testing for
+ * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
+ * making reliance oncertain keywords suspect. (SJT)
+ */
+
+/* MSC Medium model */
+#ifdef FAR
+# ifdef M_I86MM
+# define USE_FAR_KEYWORD
+# define FARDATA FAR
+# include <dos.h>
+# endif
+#endif
+
+/* SJT: default case */
+#ifndef FAR
+# define FAR
+#endif
+
+/* At this point FAR is always defined */
+#ifndef FARDATA
+# define FARDATA
+#endif
+
+/* Typedef for floating-point numbers that are converted
+ to fixed-point with a multiple of 100,000, e.g., int_gamma */
+typedef png_int_32 png_fixed_point;
+
+/* Add typedefs for pointers */
+typedef void FAR * png_voidp;
+typedef png_byte FAR * png_bytep;
+typedef png_uint_32 FAR * png_uint_32p;
+typedef png_int_32 FAR * png_int_32p;
+typedef png_uint_16 FAR * png_uint_16p;
+typedef png_int_16 FAR * png_int_16p;
+typedef PNG_CONST char FAR * png_const_charp;
+typedef char FAR * png_charp;
+typedef png_fixed_point FAR * png_fixed_point_p;
+
+#ifndef PNG_NO_STDIO
+#ifdef _WIN32_WCE
+typedef HANDLE png_FILE_p;
+#else
+typedef FILE * png_FILE_p;
+#endif
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+typedef double FAR * png_doublep;
+#endif
+
+/* Pointers to pointers; i.e. arrays */
+typedef png_byte FAR * FAR * png_bytepp;
+typedef png_uint_32 FAR * FAR * png_uint_32pp;
+typedef png_int_32 FAR * FAR * png_int_32pp;
+typedef png_uint_16 FAR * FAR * png_uint_16pp;
+typedef png_int_16 FAR * FAR * png_int_16pp;
+typedef PNG_CONST char FAR * FAR * png_const_charpp;
+typedef char FAR * FAR * png_charpp;
+typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+typedef double FAR * FAR * png_doublepp;
+#endif
+
+/* Pointers to pointers to pointers; i.e., pointer to array */
+typedef char FAR * FAR * FAR * png_charppp;
+
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+/* SPC - Is this stuff deprecated? */
+/* It'll be removed as of libpng-1.4.0 - GR-P */
+/* libpng typedefs for types in zlib. If zlib changes
+ * or another compression library is used, then change these.
+ * Eliminates need to change all the source files.
+ */
+typedef charf * png_zcharp;
+typedef charf * FAR * png_zcharpp;
+typedef z_stream FAR * png_zstreamp;
+#endif /* (PNG_1_0_X) || defined(PNG_1_2_X) */
+
+/*
+ * Define PNG_BUILD_DLL if the module being built is a Windows
+ * LIBPNG DLL.
+ *
+ * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL.
+ * It is equivalent to Microsoft predefined macro _DLL that is
+ * automatically defined when you compile using the share
+ * version of the CRT (C Run-Time library)
+ *
+ * The cygwin mods make this behavior a little different:
+ * Define PNG_BUILD_DLL if you are building a dll for use with cygwin
+ * Define PNG_STATIC if you are building a static library for use with cygwin,
+ * -or- if you are building an application that you want to link to the
+ * static library.
+ * PNG_USE_DLL is defined by default (no user action needed) unless one of
+ * the other flags is defined.
+ */
+
+#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL))
+# define PNG_DLL
+#endif
+/* If CYGWIN, then disallow GLOBAL ARRAYS unless building a static lib.
+ * When building a static lib, default to no GLOBAL ARRAYS, but allow
+ * command-line override
+ */
+#ifdef __CYGWIN__
+# ifndef PNG_STATIC
+# ifdef PNG_USE_GLOBAL_ARRAYS
+# undef PNG_USE_GLOBAL_ARRAYS
+# endif
+# ifndef PNG_USE_LOCAL_ARRAYS
+# define PNG_USE_LOCAL_ARRAYS
+# endif
+# else
+# if defined(PNG_USE_LOCAL_ARRAYS) || defined(PNG_NO_GLOBAL_ARRAYS)
+# ifdef PNG_USE_GLOBAL_ARRAYS
+# undef PNG_USE_GLOBAL_ARRAYS
+# endif
+# endif
+# endif
+# if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+# define PNG_USE_LOCAL_ARRAYS
+# endif
+#endif
+
+/* Do not use global arrays (helps with building DLL's)
+ * They are no longer used in libpng itself, since version 1.0.5c,
+ * but might be required for some pre-1.0.5c applications.
+ */
+#if !defined(PNG_USE_LOCAL_ARRAYS) && !defined(PNG_USE_GLOBAL_ARRAYS)
+# if defined(PNG_NO_GLOBAL_ARRAYS) || \
+ (defined(__GNUC__) && defined(PNG_DLL)) || defined(_MSC_VER)
+# define PNG_USE_LOCAL_ARRAYS
+# else
+# define PNG_USE_GLOBAL_ARRAYS
+# endif
+#endif
+
+#ifdef __CYGWIN__
+# undef PNGAPI
+# define PNGAPI __cdecl
+# undef PNG_IMPEXP
+# define PNG_IMPEXP
+#endif
+
+/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall",
+ * you may get warnings regarding the linkage of png_zalloc and png_zfree.
+ * Don't ignore those warnings; you must also reset the default calling
+ * convention in your compiler to match your PNGAPI, and you must build
+ * zlib and your applications the same way you build libpng.
+ */
+
+#if defined(__MINGW32__) && !defined(PNG_MODULEDEF)
+# ifndef PNG_NO_MODULEDEF
+# define PNG_NO_MODULEDEF
+# endif
+#endif
+
+#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF)
+# define PNG_IMPEXP
+#endif
+
+#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \
+ (( defined(_Windows) || defined(_WINDOWS) || \
+ defined(WIN32) || defined(_WIN32) || defined(__WIN32__) ))
+
+# ifndef PNGAPI
+# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+# define PNGAPI __cdecl
+# else
+# define PNGAPI _cdecl
+# endif
+# endif
+
+# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \
+ 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */)
+# define PNG_IMPEXP
+# endif
+
+# ifndef PNG_IMPEXP
+
+# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol
+# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol
+
+ /* Borland/Microsoft */
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500)
+# define PNG_EXPORT PNG_EXPORT_TYPE1
+# else
+# define PNG_EXPORT PNG_EXPORT_TYPE2
+# ifdef PNG_BUILD_DLL
+# define PNG_IMPEXP __export
+# else
+# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in
+ VC++ */
+# endif /* Exists in Borland C++ for
+ C++ classes (== huge) */
+# endif
+# endif
+
+# ifndef PNG_IMPEXP
+# ifdef PNG_BUILD_DLL
+# define PNG_IMPEXP __declspec(dllexport)
+# else
+# define PNG_IMPEXP __declspec(dllimport)
+# endif
+# endif
+# endif /* PNG_IMPEXP */
+#else /* !(DLL || non-cygwin WINDOWS) */
+# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
+# ifndef PNGAPI
+# define PNGAPI _System
+# endif
+# else
+# if 0 /* ... other platforms, with other meanings */
+# endif
+# endif
+#endif
+
+#ifndef PNGAPI
+# define PNGAPI
+#endif
+#ifndef PNG_IMPEXP
+# define PNG_IMPEXP
+#endif
+
+#ifdef PNG_BUILDSYMS
+# ifndef PNG_EXPORT
+# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END
+# endif
+# ifdef PNG_USE_GLOBAL_ARRAYS
+# ifndef PNG_EXPORT_VAR
+# define PNG_EXPORT_VAR(type) PNG_DATA_EXPORT
+# endif
+# endif
+#endif
+
+#ifndef PNG_EXPORT
+# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol
+#endif
+
+#ifdef PNG_USE_GLOBAL_ARRAYS
+# ifndef PNG_EXPORT_VAR
+# define PNG_EXPORT_VAR(type) extern PNG_IMPEXP type
+# endif
+#endif
+
+#ifdef PNG_PEDANTIC_WARNINGS
+# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
+# define PNG_PEDANTIC_WARNINGS_SUPPORTED
+# endif
+#endif
+
+#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
+/* Support for compiler specific function attributes. These are used
+ * so that where compiler support is available incorrect use of API
+ * functions in png.h will generate compiler warnings. Added at libpng
+ * version 1.2.41.
+ */
+# ifdef __GNUC__
+# ifndef PNG_USE_RESULT
+# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
+# endif
+# ifndef PNG_NORETURN
+# define PNG_NORETURN __attribute__((__noreturn__))
+# endif
+# ifndef PNG_ALLOCATED
+# define PNG_ALLOCATED __attribute__((__malloc__))
+# endif
+
+ /* This specifically protects structure members that should only be
+ * accessed from within the library, therefore should be empty during
+ * a library build.
+ */
+# ifndef PNG_DEPRECATED
+# define PNG_DEPRECATED __attribute__((__deprecated__))
+# endif
+# ifndef PNG_DEPSTRUCT
+# define PNG_DEPSTRUCT __attribute__((__deprecated__))
+# endif
+# ifndef PNG_PRIVATE
+# if 0 /* Doesn't work so we use deprecated instead*/
+# define PNG_PRIVATE \
+ __attribute__((warning("This function is not exported by libpng.")))
+# else
+# define PNG_PRIVATE \
+ __attribute__((__deprecated__))
+# endif
+# endif /* PNG_PRIVATE */
+# endif /* __GNUC__ */
+#endif /* PNG_PEDANTIC_WARNINGS */
+
+#ifndef PNG_DEPRECATED
+# define PNG_DEPRECATED /* Use of this function is deprecated */
+#endif
+#ifndef PNG_USE_RESULT
+# define PNG_USE_RESULT /* The result of this function must be checked */
+#endif
+#ifndef PNG_NORETURN
+# define PNG_NORETURN /* This function does not return */
+#endif
+#ifndef PNG_ALLOCATED
+# define PNG_ALLOCATED /* The result of the function is new memory */
+#endif
+#ifndef PNG_DEPSTRUCT
+# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */
+#endif
+#ifndef PNG_PRIVATE
+# define PNG_PRIVATE /* This is a private libpng function */
+#endif
+
+/* User may want to use these so they are not in PNG_INTERNAL. Any library
+ * functions that are passed far data must be model independent.
+ */
+
+#ifndef PNG_ABORT
+# define PNG_ABORT() abort()
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
+#else
+# define png_jmpbuf(png_ptr) \
+ (LIBPNG_WAS_COMPILED_WITH__PNG_SETJMP_NOT_SUPPORTED)
+#endif
+
+#ifdef USE_FAR_KEYWORD /* memory model independent fns */
+/* Use this to make far-to-near assignments */
+# define CHECK 1
+# define NOCHECK 0
+# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
+# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
+# define png_snprintf _fsnprintf /* Added to v 1.2.19 */
+# define png_strlen _fstrlen
+# define png_memcmp _fmemcmp /* SJT: added */
+# define png_memcpy _fmemcpy
+# define png_memset _fmemset
+#else /* Use the usual functions */
+# define CVT_PTR(ptr) (ptr)
+# define CVT_PTR_NOCHECK(ptr) (ptr)
+# ifndef PNG_NO_SNPRINTF
+# ifdef _MSC_VER
+# define png_snprintf _snprintf /* Added to v 1.2.19 */
+# define png_snprintf2 _snprintf
+# define png_snprintf6 _snprintf
+# else
+# define png_snprintf snprintf /* Added to v 1.2.19 */
+# define png_snprintf2 snprintf
+# define png_snprintf6 snprintf
+# endif
+# else
+ /* You don't have or don't want to use snprintf(). Caution: Using
+ * sprintf instead of snprintf exposes your application to accidental
+ * or malevolent buffer overflows. If you don't have snprintf()
+ * as a general rule you should provide one (you can get one from
+ * Portable OpenSSH).
+ */
+# define png_snprintf(s1,n,fmt,x1) sprintf(s1,fmt,x1)
+# define png_snprintf2(s1,n,fmt,x1,x2) sprintf(s1,fmt,x1,x2)
+# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \
+ sprintf(s1,fmt,x1,x2,x3,x4,x5,x6)
+# endif
+# define png_strlen strlen
+# define png_memcmp memcmp /* SJT: added */
+# define png_memcpy memcpy
+# define png_memset memset
+#endif
+/* End of memory model independent support */
+
+/* Just a little check that someone hasn't tried to define something
+ * contradictory.
+ */
+#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
+# undef PNG_ZBUF_SIZE
+# define PNG_ZBUF_SIZE 65536L
+#endif
+
+/* Added at libpng-1.2.8 */
+#endif /* PNG_VERSION_INFO_ONLY */
+
+#endif /* PNGCONF_H */
diff --git a/Source/LibPNG/pngerror.c b/Source/LibPNG/pngerror.c
new file mode 100644
index 0000000..025d52e
--- /dev/null
+++ b/Source/LibPNG/pngerror.c
@@ -0,0 +1,396 @@
+
+/* pngerror.c - stub functions for i/o and memory allocation
+ *
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file provides a location for all error handling. Users who
+ * need special error handling are expected to write replacement functions
+ * and use png_set_error_fn() to use those functions. See the instructions
+ * at each function.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
+static void /* PRIVATE */
+png_default_error PNGARG((png_structp png_ptr,
+ png_const_charp error_message)) PNG_NORETURN;
+#ifdef PNG_WARNINGS_SUPPORTED
+static void /* PRIVATE */
+png_default_warning PNGARG((png_structp png_ptr,
+ png_const_charp warning_message));
+#endif /* PNG_WARNINGS_SUPPORTED */
+
+/* This function is called whenever there is a fatal error. This function
+ * should not be changed. If there is a need to handle errors differently,
+ * you should supply a replacement error function and use png_set_error_fn()
+ * to replace the error function at run-time.
+ */
+#ifdef PNG_ERROR_TEXT_SUPPORTED
+void PNGAPI
+png_error(png_structp png_ptr, png_const_charp error_message)
+{
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ char msg[16];
+ if (png_ptr != NULL)
+ {
+ if (png_ptr->flags&
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+ {
+ if (*error_message == PNG_LITERAL_SHARP)
+ {
+ /* Strip "#nnnn " from beginning of error message. */
+ int offset;
+ for (offset = 1; offset<15; offset++)
+ if (error_message[offset] == ' ')
+ break;
+ if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ {
+ int i;
+ for (i = 0; i < offset - 1; i++)
+ msg[i] = error_message[i + 1];
+ msg[i - 1] = '\0';
+ error_message = msg;
+ }
+ else
+ error_message += offset;
+ }
+ else
+ {
+ if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ {
+ msg[0] = '0';
+ msg[1] = '\0';
+ error_message = msg;
+ }
+ }
+ }
+ }
+#endif
+ if (png_ptr != NULL && png_ptr->error_fn != NULL)
+ (*(png_ptr->error_fn))(png_ptr, error_message);
+
+ /* If the custom handler doesn't exist, or if it returns,
+ use the default handler, which will not return. */
+ png_default_error(png_ptr, error_message);
+}
+#else
+void PNGAPI
+png_err(png_structp png_ptr)
+{
+ /* Prior to 1.2.45 the error_fn received a NULL pointer, expressed
+ * erroneously as '\0', instead of the empty string "". This was
+ * apparently an error, introduced in libpng-1.2.20, and png_default_error
+ * will crash in this case.
+ */
+ if (png_ptr != NULL && png_ptr->error_fn != NULL)
+ (*(png_ptr->error_fn))(png_ptr, "");
+
+ /* If the custom handler doesn't exist, or if it returns,
+ use the default handler, which will not return. */
+ png_default_error(png_ptr, "");
+}
+#endif /* PNG_ERROR_TEXT_SUPPORTED */
+
+#ifdef PNG_WARNINGS_SUPPORTED
+/* This function is called whenever there is a non-fatal error. This function
+ * should not be changed. If there is a need to handle warnings differently,
+ * you should supply a replacement warning function and use
+ * png_set_error_fn() to replace the warning function at run-time.
+ */
+void PNGAPI
+png_warning(png_structp png_ptr, png_const_charp warning_message)
+{
+ int offset = 0;
+ if (png_ptr != NULL)
+ {
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ if (png_ptr->flags&
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+#endif
+ {
+ if (*warning_message == PNG_LITERAL_SHARP)
+ {
+ for (offset = 1; offset < 15; offset++)
+ if (warning_message[offset] == ' ')
+ break;
+ }
+ }
+ }
+ if (png_ptr != NULL && png_ptr->warning_fn != NULL)
+ (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
+ else
+ png_default_warning(png_ptr, warning_message + offset);
+}
+#endif /* PNG_WARNINGS_SUPPORTED */
+
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_benign_error(png_structp png_ptr, png_const_charp error_message)
+{
+ if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ png_warning(png_ptr, error_message);
+ else
+ png_error(png_ptr, error_message);
+}
+#endif
+
+/* These utilities are used internally to build an error message that relates
+ * to the current chunk. The chunk name comes from png_ptr->chunk_name,
+ * this is used to prefix the message. The message is limited in length
+ * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * if the character is invalid.
+ */
+#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
+static PNG_CONST char png_digit[16] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+#define PNG_MAX_ERROR_TEXT 64
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
+static void /* PRIVATE */
+png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
+ error_message)
+{
+ int iout = 0, iin = 0;
+
+ while (iin < 4)
+ {
+ int c = png_ptr->chunk_name[iin++];
+ if (isnonalpha(c))
+ {
+ buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
+ buffer[iout++] = png_digit[(c & 0xf0) >> 4];
+ buffer[iout++] = png_digit[c & 0x0f];
+ buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
+ }
+ else
+ {
+ buffer[iout++] = (png_byte)c;
+ }
+ }
+
+ if (error_message == NULL)
+ buffer[iout] = '\0';
+ else
+ {
+ buffer[iout++] = ':';
+ buffer[iout++] = ' ';
+
+ iin = 0;
+ while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
+ buffer[iout++] = error_message[iin++];
+
+ /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
+ buffer[iout] = '\0';
+ }
+}
+
+#ifdef PNG_READ_SUPPORTED
+void PNGAPI
+png_chunk_error(png_structp png_ptr, png_const_charp error_message)
+{
+ char msg[18+PNG_MAX_ERROR_TEXT];
+ if (png_ptr == NULL)
+ png_error(png_ptr, error_message);
+ else
+ {
+ png_format_buffer(png_ptr, msg, error_message);
+ png_error(png_ptr, msg);
+ }
+}
+#endif /* PNG_READ_SUPPORTED */
+#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */
+
+#ifdef PNG_WARNINGS_SUPPORTED
+void PNGAPI
+png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
+{
+ char msg[18+PNG_MAX_ERROR_TEXT];
+ if (png_ptr == NULL)
+ png_warning(png_ptr, warning_message);
+ else
+ {
+ png_format_buffer(png_ptr, msg, warning_message);
+ png_warning(png_ptr, msg);
+ }
+}
+#endif /* PNG_WARNINGS_SUPPORTED */
+
+#ifdef PNG_READ_SUPPORTED
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message)
+{
+ if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ png_chunk_warning(png_ptr, error_message);
+ else
+ png_chunk_error(png_ptr, error_message);
+}
+#endif
+#endif /* PNG_READ_SUPPORTED */
+
+/* This is the default error handling function. Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash. This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void /* PRIVATE */
+png_default_error(png_structp png_ptr, png_const_charp error_message)
+{
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ if (*error_message == PNG_LITERAL_SHARP)
+ {
+ /* Strip "#nnnn " from beginning of error message. */
+ int offset;
+ char error_number[16];
+ for (offset = 0; offset<15; offset++)
+ {
+ error_number[offset] = error_message[offset + 1];
+ if (error_message[offset] == ' ')
+ break;
+ }
+ if ((offset > 1) && (offset < 15))
+ {
+ error_number[offset - 1] = '\0';
+ fprintf(stderr, "libpng error no. %s: %s",
+ error_number, error_message + offset + 1);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+ else
+ {
+ fprintf(stderr, "libpng error: %s, offset=%d",
+ error_message, offset);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+ }
+ else
+#endif
+ {
+ fprintf(stderr, "libpng error: %s", error_message);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ if (png_ptr)
+ {
+# ifdef USE_FAR_KEYWORD
+ {
+ jmp_buf jmpbuf;
+ png_memcpy(jmpbuf, png_ptr->jmpbuf, png_sizeof(jmp_buf));
+ longjmp(jmpbuf,1);
+ }
+# else
+ longjmp(png_ptr->jmpbuf, 1);
+# endif
+ }
+#endif
+ /* Here if not setjmp support or if png_ptr is null. */
+ PNG_ABORT();
+#ifndef PNG_CONSOLE_IO_SUPPORTED
+ error_message = error_message; /* Make compiler happy */
+#endif
+}
+
+#ifdef PNG_WARNINGS_SUPPORTED
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway. Replacement functions don't have to do anything
+ * here if you don't want them to. In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void /* PRIVATE */
+png_default_warning(png_structp png_ptr, png_const_charp warning_message)
+{
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+# ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ if (*warning_message == PNG_LITERAL_SHARP)
+ {
+ int offset;
+ char warning_number[16];
+ for (offset = 0; offset < 15; offset++)
+ {
+ warning_number[offset] = warning_message[offset + 1];
+ if (warning_message[offset] == ' ')
+ break;
+ }
+ if ((offset > 1) && (offset < 15))
+ {
+ warning_number[offset + 1] = '\0';
+ fprintf(stderr, "libpng warning no. %s: %s",
+ warning_number, warning_message + offset);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+ else
+ {
+ fprintf(stderr, "libpng warning: %s",
+ warning_message);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+ }
+ else
+# endif
+ {
+ fprintf(stderr, "libpng warning: %s", warning_message);
+ fprintf(stderr, PNG_STRING_NEWLINE);
+ }
+#else
+ warning_message = warning_message; /* Make compiler happy */
+#endif
+ png_ptr = png_ptr; /* Make compiler happy */
+}
+#endif /* PNG_WARNINGS_SUPPORTED */
+
+/* This function is called when the application wants to use another method
+ * of handling errors and warnings. Note that the error function MUST NOT
+ * return to the calling routine or serious problems will occur. The return
+ * method used in the default routine calls longjmp(png_ptr->jmpbuf, 1)
+ */
+void PNGAPI
+png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warning_fn)
+{
+ if (png_ptr == NULL)
+ return;
+ png_ptr->error_ptr = error_ptr;
+ png_ptr->error_fn = error_fn;
+ png_ptr->warning_fn = warning_fn;
+}
+
+
+/* This function returns a pointer to the error_ptr associated with the user
+ * functions. The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_error_ptr(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return NULL;
+ return ((png_voidp)png_ptr->error_ptr);
+}
+
+
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+void PNGAPI
+png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
+{
+ if (png_ptr != NULL)
+ {
+ png_ptr->flags &=
+ ((~(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
+ }
+}
+#endif
+#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pnggccrd.c b/Source/LibPNG/pnggccrd.c
new file mode 100644
index 0000000..cdaebc2
--- /dev/null
+++ b/Source/LibPNG/pnggccrd.c
@@ -0,0 +1,26 @@
+/* pnggccrd.c
+ *
+ * Last changed in libpng 1.2.48 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This code snippet is for use by configure's compilation test. Most of the
+ * remainder of the file was removed from libpng-1.2.20, and all of the
+ * assembler code was removed from libpng-1.2.48.
+ */
+
+#if (!defined _MSC_VER) && \
+ defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \
+ defined(PNG_MMX_CODE_SUPPORTED)
+
+int PNGAPI png_dummy_mmx_support(void);
+
+int PNGAPI png_dummy_mmx_support(void)
+{
+ /* 0: no MMX; 1: MMX supported; 2: not tested */
+ return 2;
+}
+#endif
diff --git a/Source/LibPNG/pngget.c b/Source/LibPNG/pngget.c
new file mode 100644
index 0000000..d397329
--- /dev/null
+++ b/Source/LibPNG/pngget.c
@@ -0,0 +1,944 @@
+
+/* pngget.c - retrieval of values from info struct
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
+png_uint_32 PNGAPI
+png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return(info_ptr->valid & flag);
+
+ else
+ return(0);
+}
+
+png_uint_32 PNGAPI
+png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return(info_ptr->rowbytes);
+
+ else
+ return(0);
+}
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+png_bytepp PNGAPI
+png_get_rows(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return(info_ptr->row_pointers);
+
+ else
+ return(0);
+}
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+/* Easy access to info, added in libpng-0.99 */
+png_uint_32 PNGAPI
+png_get_image_width(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->width;
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_image_height(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->height;
+
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_bit_depth(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->bit_depth;
+
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_color_type(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->color_type;
+
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_filter_type(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->filter_type;
+
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_interlace_type(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->interlace_type;
+
+ return (0);
+}
+
+png_byte PNGAPI
+png_get_compression_type(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return info_ptr->compression_type;
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+#ifdef PNG_pHYs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_pHYs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_x_pixels_per_meter");
+
+ if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+ return (0);
+
+ else
+ return (info_ptr->x_pixels_per_unit);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+#ifdef PNG_pHYs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_pHYs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_y_pixels_per_meter");
+
+ if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER)
+ return (0);
+
+ else
+ return (info_ptr->y_pixels_per_unit);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_pixels_per_meter(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+#ifdef PNG_pHYs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_pHYs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
+
+ if (info_ptr->phys_unit_type != PNG_RESOLUTION_METER ||
+ info_ptr->x_pixels_per_unit != info_ptr->y_pixels_per_unit)
+ return (0);
+
+ else
+ return (info_ptr->x_pixels_per_unit);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+float PNGAPI
+png_get_pixel_aspect_ratio(png_structp png_ptr, png_infop info_ptr)
+ {
+ if (png_ptr != NULL && info_ptr != NULL)
+#ifdef PNG_pHYs_SUPPORTED
+
+ if (info_ptr->valid & PNG_INFO_pHYs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
+
+ if (info_ptr->x_pixels_per_unit == 0)
+ return ((float)0.0);
+
+ else
+ return ((float)((float)info_ptr->y_pixels_per_unit
+ /(float)info_ptr->x_pixels_per_unit));
+ }
+#else
+ return (0.0);
+#endif
+ return ((float)0.0);
+}
+#endif
+
+png_int_32 PNGAPI
+png_get_x_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+#ifdef PNG_oFFs_SUPPORTED
+
+ if (info_ptr->valid & PNG_INFO_oFFs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
+
+ if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+ return (0);
+
+ else
+ return (info_ptr->x_offset);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_microns(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+
+#ifdef PNG_oFFs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_oFFs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
+
+ if (info_ptr->offset_unit_type != PNG_OFFSET_MICROMETER)
+ return (0);
+
+ else
+ return (info_ptr->y_offset);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+png_int_32 PNGAPI
+png_get_x_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+
+#ifdef PNG_oFFs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_oFFs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
+
+ if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+ return (0);
+
+ else
+ return (info_ptr->x_offset);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+png_int_32 PNGAPI
+png_get_y_offset_pixels(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+
+#ifdef PNG_oFFs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_oFFs)
+ {
+ png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
+
+ if (info_ptr->offset_unit_type != PNG_OFFSET_PIXEL)
+ return (0);
+
+ else
+ return (info_ptr->y_offset);
+ }
+#else
+ return (0);
+#endif
+ return (0);
+}
+
+#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED)
+png_uint_32 PNGAPI
+png_get_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+ return ((png_uint_32)((float)png_get_pixels_per_meter(png_ptr, info_ptr)
+ *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_x_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+ return ((png_uint_32)((float)png_get_x_pixels_per_meter(png_ptr, info_ptr)
+ *.0254 +.5));
+}
+
+png_uint_32 PNGAPI
+png_get_y_pixels_per_inch(png_structp png_ptr, png_infop info_ptr)
+{
+ return ((png_uint_32)((float)png_get_y_pixels_per_meter(png_ptr, info_ptr)
+ *.0254 +.5));
+}
+
+float PNGAPI
+png_get_x_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+ return ((float)png_get_x_offset_microns(png_ptr, info_ptr)
+ *.00003937);
+}
+
+float PNGAPI
+png_get_y_offset_inches(png_structp png_ptr, png_infop info_ptr)
+{
+ return ((float)png_get_y_offset_microns(png_ptr, info_ptr)
+ *.00003937);
+}
+
+#ifdef PNG_pHYs_SUPPORTED
+png_uint_32 PNGAPI
+png_get_pHYs_dpi(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+ png_uint_32 retval = 0;
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ {
+ png_debug1(1, "in %s retrieval function", "pHYs");
+
+ if (res_x != NULL)
+ {
+ *res_x = info_ptr->x_pixels_per_unit;
+ retval |= PNG_INFO_pHYs;
+ }
+ if (res_y != NULL)
+ {
+ *res_y = info_ptr->y_pixels_per_unit;
+ retval |= PNG_INFO_pHYs;
+ }
+ if (unit_type != NULL)
+ {
+ *unit_type = (int)info_ptr->phys_unit_type;
+ retval |= PNG_INFO_pHYs;
+ if (*unit_type == 1)
+ {
+ if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
+ if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
+ }
+ }
+ }
+ return (retval);
+}
+#endif /* PNG_pHYs_SUPPORTED */
+#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */
+
+/* png_get_channels really belongs in here, too, but it's been around longer */
+
+#endif /* PNG_EASY_ACCESS_SUPPORTED */
+
+png_byte PNGAPI
+png_get_channels(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return(info_ptr->channels);
+ else
+ return (0);
+}
+
+png_bytep PNGAPI
+png_get_signature(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr != NULL && info_ptr != NULL)
+ return(info_ptr->signature);
+ else
+ return (NULL);
+}
+
+#ifdef PNG_bKGD_SUPPORTED
+png_uint_32 PNGAPI
+png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
+ png_color_16p *background)
+{
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
+ && background != NULL)
+ {
+ png_debug1(1, "in %s retrieval function", "bKGD");
+
+ *background = &(info_ptr->background);
+ return (PNG_INFO_bKGD);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
+ double *white_x, double *white_y, double *red_x, double *red_y,
+ double *green_x, double *green_y, double *blue_x, double *blue_y)
+{
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ {
+ png_debug1(1, "in %s retrieval function", "cHRM");
+
+ if (white_x != NULL)
+ *white_x = (double)info_ptr->x_white;
+ if (white_y != NULL)
+ *white_y = (double)info_ptr->y_white;
+ if (red_x != NULL)
+ *red_x = (double)info_ptr->x_red;
+ if (red_y != NULL)
+ *red_y = (double)info_ptr->y_red;
+ if (green_x != NULL)
+ *green_x = (double)info_ptr->x_green;
+ if (green_y != NULL)
+ *green_y = (double)info_ptr->y_green;
+ if (blue_x != NULL)
+ *blue_x = (double)info_ptr->x_blue;
+ if (blue_y != NULL)
+ *blue_y = (double)info_ptr->y_blue;
+ return (PNG_INFO_cHRM);
+ }
+ return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+ png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
+ png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
+ png_fixed_point *blue_x, png_fixed_point *blue_y)
+{
+ png_debug1(1, "in %s retrieval function", "cHRM");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ {
+ if (white_x != NULL)
+ *white_x = info_ptr->int_x_white;
+ if (white_y != NULL)
+ *white_y = info_ptr->int_y_white;
+ if (red_x != NULL)
+ *red_x = info_ptr->int_x_red;
+ if (red_y != NULL)
+ *red_y = info_ptr->int_y_red;
+ if (green_x != NULL)
+ *green_x = info_ptr->int_x_green;
+ if (green_y != NULL)
+ *green_y = info_ptr->int_y_green;
+ if (blue_x != NULL)
+ *blue_x = info_ptr->int_x_blue;
+ if (blue_y != NULL)
+ *blue_y = info_ptr->int_y_blue;
+ return (PNG_INFO_cHRM);
+ }
+ return (0);
+}
+#endif
+#endif
+
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
+{
+ png_debug1(1, "in %s retrieval function", "gAMA");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+ && file_gamma != NULL)
+ {
+ *file_gamma = (double)info_ptr->gamma;
+ return (PNG_INFO_gAMA);
+ }
+ return (0);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA_fixed(png_structp png_ptr, png_infop info_ptr,
+ png_fixed_point *int_file_gamma)
+{
+ png_debug1(1, "in %s retrieval function", "gAMA");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+ && int_file_gamma != NULL)
+ {
+ *int_file_gamma = info_ptr->int_gamma;
+ return (PNG_INFO_gAMA);
+ }
+ return (0);
+}
+#endif
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sRGB(png_structp png_ptr, png_infop info_ptr, int *file_srgb_intent)
+{
+ png_debug1(1, "in %s retrieval function", "sRGB");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
+ && file_srgb_intent != NULL)
+ {
+ *file_srgb_intent = (int)info_ptr->srgb_intent;
+ return (PNG_INFO_sRGB);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_iCCP_SUPPORTED
+png_uint_32 PNGAPI
+png_get_iCCP(png_structp png_ptr, png_infop info_ptr,
+ png_charpp name, int *compression_type,
+ png_charpp profile, png_uint_32 *proflen)
+{
+ png_debug1(1, "in %s retrieval function", "iCCP");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
+ && name != NULL && profile != NULL && proflen != NULL)
+ {
+ *name = info_ptr->iccp_name;
+ *profile = info_ptr->iccp_profile;
+ /* Compression_type is a dummy so the API won't have to change
+ * if we introduce multiple compression types later.
+ */
+ *proflen = (int)info_ptr->iccp_proflen;
+ *compression_type = (int)info_ptr->iccp_compression;
+ return (PNG_INFO_iCCP);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sPLT(png_structp png_ptr, png_infop info_ptr,
+ png_sPLT_tpp spalettes)
+{
+ if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
+ {
+ *spalettes = info_ptr->splt_palettes;
+ return ((png_uint_32)info_ptr->splt_palettes_num);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+png_uint_32 PNGAPI
+png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
+{
+ png_debug1(1, "in %s retrieval function", "hIST");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
+ && hist != NULL)
+ {
+ *hist = info_ptr->hist;
+ return (PNG_INFO_hIST);
+ }
+ return (0);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 *width, png_uint_32 *height, int *bit_depth,
+ int *color_type, int *interlace_type, int *compression_type,
+ int *filter_type)
+
+{
+ png_debug1(1, "in %s retrieval function", "IHDR");
+
+ if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
+ height == NULL || bit_depth == NULL || color_type == NULL)
+ return (0);
+
+ *width = info_ptr->width;
+ *height = info_ptr->height;
+ *bit_depth = info_ptr->bit_depth;
+ *color_type = info_ptr->color_type;
+
+ if (compression_type != NULL)
+ *compression_type = info_ptr->compression_type;
+
+ if (filter_type != NULL)
+ *filter_type = info_ptr->filter_type;
+
+ if (interlace_type != NULL)
+ *interlace_type = info_ptr->interlace_type;
+
+ /* This is redundant if we can be sure that the info_ptr values were all
+ * assigned in png_set_IHDR(). We do the check anyhow in case an
+ * application has ignored our advice not to mess with the members
+ * of info_ptr directly.
+ */
+ png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+ info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
+ info_ptr->compression_type, info_ptr->filter_type);
+
+ return (1);
+}
+
+#ifdef PNG_oFFs_SUPPORTED
+png_uint_32 PNGAPI
+png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
+ png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
+{
+ png_debug1(1, "in %s retrieval function", "oFFs");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
+ && offset_x != NULL && offset_y != NULL && unit_type != NULL)
+ {
+ *offset_x = info_ptr->x_offset;
+ *offset_y = info_ptr->y_offset;
+ *unit_type = (int)info_ptr->offset_unit_type;
+ return (PNG_INFO_oFFs);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+png_uint_32 PNGAPI
+png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
+ png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
+ png_charp *units, png_charpp *params)
+{
+ png_debug1(1, "in %s retrieval function", "pCAL");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
+ && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+ nparams != NULL && units != NULL && params != NULL)
+ {
+ *purpose = info_ptr->pcal_purpose;
+ *X0 = info_ptr->pcal_X0;
+ *X1 = info_ptr->pcal_X1;
+ *type = (int)info_ptr->pcal_type;
+ *nparams = (int)info_ptr->pcal_nparams;
+ *units = info_ptr->pcal_units;
+ *params = info_ptr->pcal_params;
+ return (PNG_INFO_pCAL);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_sCAL_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL(png_structp png_ptr, png_infop info_ptr,
+ int *unit, double *width, double *height)
+{
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sCAL))
+ {
+ *unit = info_ptr->scal_unit;
+ *width = info_ptr->scal_pixel_width;
+ *height = info_ptr->scal_pixel_height;
+ return (PNG_INFO_sCAL);
+ }
+ return(0);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+ int *unit, png_charpp width, png_charpp height)
+{
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sCAL))
+ {
+ *unit = info_ptr->scal_unit;
+ *width = info_ptr->scal_s_width;
+ *height = info_ptr->scal_s_height;
+ return (PNG_INFO_sCAL);
+ }
+ return(0);
+}
+#endif
+#endif
+#endif
+
+#ifdef PNG_pHYs_SUPPORTED
+png_uint_32 PNGAPI
+png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
+{
+ png_uint_32 retval = 0;
+
+ png_debug1(1, "in %s retrieval function", "pHYs");
+
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs))
+ {
+ if (res_x != NULL)
+ {
+ *res_x = info_ptr->x_pixels_per_unit;
+ retval |= PNG_INFO_pHYs;
+ }
+
+ if (res_y != NULL)
+ {
+ *res_y = info_ptr->y_pixels_per_unit;
+ retval |= PNG_INFO_pHYs;
+ }
+
+ if (unit_type != NULL)
+ {
+ *unit_type = (int)info_ptr->phys_unit_type;
+ retval |= PNG_INFO_pHYs;
+ }
+ }
+ return (retval);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
+ int *num_palette)
+{
+ png_debug1(1, "in %s retrieval function", "PLTE");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
+ && palette != NULL)
+ {
+ *palette = info_ptr->palette;
+ *num_palette = info_ptr->num_palette;
+ png_debug1(3, "num_palette = %d", *num_palette);
+ return (PNG_INFO_PLTE);
+ }
+ return (0);
+}
+
+#ifdef PNG_sBIT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
+{
+ png_debug1(1, "in %s retrieval function", "sBIT");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
+ && sig_bit != NULL)
+ {
+ *sig_bit = &(info_ptr->sig_bit);
+ return (PNG_INFO_sBIT);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
+ int *num_text)
+{
+ if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
+ {
+ png_debug1(1, "in %s retrieval function",
+ (png_ptr->chunk_name[0] == '\0' ? "text"
+ : (png_const_charp)png_ptr->chunk_name));
+
+ if (text_ptr != NULL)
+ *text_ptr = info_ptr->text;
+
+ if (num_text != NULL)
+ *num_text = info_ptr->num_text;
+
+ return ((png_uint_32)info_ptr->num_text);
+ }
+ if (num_text != NULL)
+ *num_text = 0;
+ return(0);
+}
+#endif
+
+#ifdef PNG_tIME_SUPPORTED
+png_uint_32 PNGAPI
+png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
+{
+ png_debug1(1, "in %s retrieval function", "tIME");
+
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
+ && mod_time != NULL)
+ {
+ *mod_time = &(info_ptr->mod_time);
+ return (PNG_INFO_tIME);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+png_uint_32 PNGAPI
+png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
+ png_bytep *trans, int *num_trans, png_color_16p *trans_values)
+{
+ png_uint_32 retval = 0;
+ if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ {
+ png_debug1(1, "in %s retrieval function", "tRNS");
+
+ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (trans != NULL)
+ {
+ *trans = info_ptr->trans;
+ retval |= PNG_INFO_tRNS;
+ }
+
+ if (trans_values != NULL)
+ *trans_values = &(info_ptr->trans_values);
+ }
+ else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
+ {
+ if (trans_values != NULL)
+ {
+ *trans_values = &(info_ptr->trans_values);
+ retval |= PNG_INFO_tRNS;
+ }
+
+ if (trans != NULL)
+ *trans = NULL;
+ }
+ if (num_trans != NULL)
+ {
+ *num_trans = info_ptr->num_trans;
+ retval |= PNG_INFO_tRNS;
+ }
+ }
+ return (retval);
+}
+#endif
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+png_uint_32 PNGAPI
+png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
+ png_unknown_chunkpp unknowns)
+{
+ if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
+ {
+ *unknowns = info_ptr->unknown_chunks;
+ return ((png_uint_32)info_ptr->unknown_chunks_num);
+ }
+ return (0);
+}
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+png_byte PNGAPI
+png_get_rgb_to_gray_status (png_structp png_ptr)
+{
+ return (png_byte)(png_ptr? png_ptr->rgb_to_gray_status : 0);
+}
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+png_voidp PNGAPI
+png_get_user_chunk_ptr(png_structp png_ptr)
+{
+ return (png_ptr? png_ptr->user_chunk_ptr : NULL);
+}
+#endif
+
+png_uint_32 PNGAPI
+png_get_compression_buffer_size(png_structp png_ptr)
+{
+ return (png_uint_32)(png_ptr? png_ptr->zbuf_size : 0L);
+}
+
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+#ifndef PNG_1_0_X
+/* This function was added to libpng 1.2.0 and should exist by default */
+png_uint_32 PNGAPI
+png_get_asm_flags (png_structp png_ptr)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ return (png_ptr? 0L: 0L);
+}
+
+/* This function was added to libpng 1.2.0 and should exist by default */
+png_uint_32 PNGAPI
+png_get_asm_flagmask (int flag_select)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ flag_select=flag_select;
+ return 0L;
+}
+
+ /* GRR: could add this: && defined(PNG_MMX_CODE_SUPPORTED) */
+/* This function was added to libpng 1.2.0 */
+png_uint_32 PNGAPI
+png_get_mmx_flagmask (int flag_select, int *compilerID)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ flag_select=flag_select;
+ *compilerID = -1; /* unknown (i.e., no asm/MMX code compiled) */
+ return 0L;
+}
+
+/* This function was added to libpng 1.2.0 */
+png_byte PNGAPI
+png_get_mmx_bitdepth_threshold (png_structp png_ptr)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ return (png_ptr? 0: 0);
+}
+
+/* This function was added to libpng 1.2.0 */
+png_uint_32 PNGAPI
+png_get_mmx_rowbytes_threshold (png_structp png_ptr)
+{
+ /* Obsolete, to be removed from libpng-1.4.0 */
+ return (png_ptr? 0L: 0L);
+}
+#endif /* ?PNG_1_0_X */
+#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+/* These functions were added to libpng 1.2.6 but not enabled
+* by default. They will be enabled in libpng-1.4.0 */
+png_uint_32 PNGAPI
+png_get_user_width_max (png_structp png_ptr)
+{
+ return (png_ptr? png_ptr->user_width_max : 0);
+}
+png_uint_32 PNGAPI
+png_get_user_height_max (png_structp png_ptr)
+{
+ return (png_ptr? png_ptr->user_height_max : 0);
+}
+#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+
+#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngmem.c b/Source/LibPNG/pngmem.c
new file mode 100644
index 0000000..a18719b
--- /dev/null
+++ b/Source/LibPNG/pngmem.c
@@ -0,0 +1,641 @@
+
+/* pngmem.c - stub functions for memory allocation
+ *
+ * Last changed in libpng 1.2.41 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file provides a location for all memory allocation. Users who
+ * need special memory handling are expected to supply replacement
+ * functions for png_malloc() and png_free(), and to use
+ * png_create_read_struct_2() and png_create_write_struct_2() to
+ * identify the replacement functions.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
+/* Borland DOS special memory handler */
+#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
+/* If you change this, be sure to change the one in png.h also */
+
+/* Allocate memory for a png_struct. The malloc and memset can be replaced
+ by a single call to calloc() if this is thought to improve performance. */
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+ return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
+}
+
+/* Alternate version of png_create_struct, for use with user-defined malloc. */
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+ png_size_t size;
+ png_voidp struct_ptr;
+
+ if (type == PNG_STRUCT_INFO)
+ size = png_sizeof(png_info);
+ else if (type == PNG_STRUCT_PNG)
+ size = png_sizeof(png_struct);
+ else
+ return (png_get_copyright(NULL));
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (malloc_fn != NULL)
+ {
+ png_struct dummy_struct;
+ png_structp png_ptr = &dummy_struct;
+ png_ptr->mem_ptr=mem_ptr;
+ struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
+ }
+ else
+#endif /* PNG_USER_MEM_SUPPORTED */
+ struct_ptr = (png_voidp)farmalloc(size);
+ if (struct_ptr != NULL)
+ png_memset(struct_ptr, 0, size);
+ return (struct_ptr);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+ png_voidp mem_ptr)
+{
+#endif
+ if (struct_ptr != NULL)
+ {
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (free_fn != NULL)
+ {
+ png_struct dummy_struct;
+ png_structp png_ptr = &dummy_struct;
+ png_ptr->mem_ptr=mem_ptr;
+ (*(free_fn))(png_ptr, struct_ptr);
+ return;
+ }
+#endif /* PNG_USER_MEM_SUPPORTED */
+ farfree (struct_ptr);
+ }
+}
+
+/* Allocate memory. For reasonable files, size should never exceed
+ * 64K. However, zlib may allocate more then 64K if you don't tell
+ * it not to. See zconf.h and png.h for more information. zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ *
+ * Borland seems to have a problem in DOS mode for exactly 64K.
+ * It gives you a segment with an offset of 8 (perhaps to store its
+ * memory stuff). zlib doesn't like this at all, so we have to
+ * detect and deal with it. This code should not be needed in
+ * Windows or OS/2 modes, and only in 16 bit mode. This code has
+ * been updated by Alexander Lehmann for version 0.89 to waste less
+ * memory.
+ *
+ * Note that we can't use png_size_t for the "size" declaration,
+ * since on some systems a png_size_t is a 16-bit quantity, and as a
+ * result, we would be truncating potentially larger memory requests
+ * (which should cause a fatal error) and introducing major problems.
+ */
+png_voidp /* PRIVATE */
+png_calloc(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+
+ ret = (png_malloc(png_ptr, size));
+ if (ret != NULL)
+ png_memset(ret,0,(png_size_t)size);
+ return (ret);
+}
+
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+
+ if (png_ptr == NULL || size == 0)
+ return (NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr->malloc_fn != NULL)
+ ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+ else
+ ret = (png_malloc_default(png_ptr, size));
+ if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out of memory!");
+ return (ret);
+}
+
+png_voidp PNGAPI
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+ if (png_ptr == NULL || size == 0)
+ return (NULL);
+
+#ifdef PNG_MAX_MALLOC_64K
+ if (size > (png_uint_32)65536L)
+ {
+ png_warning(png_ptr, "Cannot Allocate > 64K");
+ ret = NULL;
+ }
+ else
+#endif
+
+ if (size != (size_t)size)
+ ret = NULL;
+ else if (size == (png_uint_32)65536L)
+ {
+ if (png_ptr->offset_table == NULL)
+ {
+ /* Try to see if we need to do any of this fancy stuff */
+ ret = farmalloc(size);
+ if (ret == NULL || ((png_size_t)ret & 0xffff))
+ {
+ int num_blocks;
+ png_uint_32 total_size;
+ png_bytep table;
+ int i;
+ png_byte huge * hptr;
+
+ if (ret != NULL)
+ {
+ farfree(ret);
+ ret = NULL;
+ }
+
+ if (png_ptr->zlib_window_bits > 14)
+ num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
+ else
+ num_blocks = 1;
+ if (png_ptr->zlib_mem_level >= 7)
+ num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
+ else
+ num_blocks++;
+
+ total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
+
+ table = farmalloc(total_size);
+
+ if (table == NULL)
+ {
+#ifndef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out Of Memory."); /* Note "O", "M" */
+ else
+ png_warning(png_ptr, "Out Of Memory.");
+#endif
+ return (NULL);
+ }
+
+ if ((png_size_t)table & 0xfff0)
+ {
+#ifndef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr,
+ "Farmalloc didn't return normalized pointer");
+ else
+ png_warning(png_ptr,
+ "Farmalloc didn't return normalized pointer");
+#endif
+ return (NULL);
+ }
+
+ png_ptr->offset_table = table;
+ png_ptr->offset_table_ptr = farmalloc(num_blocks *
+ png_sizeof(png_bytep));
+
+ if (png_ptr->offset_table_ptr == NULL)
+ {
+#ifndef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out Of memory."); /* Note "O", "m" */
+ else
+ png_warning(png_ptr, "Out Of memory.");
+#endif
+ return (NULL);
+ }
+
+ hptr = (png_byte huge *)table;
+ if ((png_size_t)hptr & 0xf)
+ {
+ hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
+ hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
+ }
+ for (i = 0; i < num_blocks; i++)
+ {
+ png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
+ hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
+ }
+
+ png_ptr->offset_table_number = num_blocks;
+ png_ptr->offset_table_count = 0;
+ png_ptr->offset_table_count_free = 0;
+ }
+ }
+
+ if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
+ {
+#ifndef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out of Memory."); /* Note "o" and "M" */
+ else
+ png_warning(png_ptr, "Out of Memory.");
+#endif
+ return (NULL);
+ }
+
+ ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
+ }
+ else
+ ret = farmalloc(size);
+
+#ifndef PNG_USER_MEM_SUPPORTED
+ if (ret == NULL)
+ {
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out of memory."); /* Note "o" and "m" */
+ else
+ png_warning(png_ptr, "Out of memory."); /* Note "o" and "m" */
+ }
+#endif
+
+ return (ret);
+}
+
+/* Free a pointer allocated by png_malloc(). In the default
+ * configuration, png_ptr is not used, but is passed in case it
+ * is needed. If ptr is NULL, return without taking any action.
+ */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+ if (png_ptr == NULL || ptr == NULL)
+ return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr->free_fn != NULL)
+ {
+ (*(png_ptr->free_fn))(png_ptr, ptr);
+ return;
+ }
+ else
+ png_free_default(png_ptr, ptr);
+}
+
+void PNGAPI
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+ if (png_ptr == NULL || ptr == NULL)
+ return;
+
+ if (png_ptr->offset_table != NULL)
+ {
+ int i;
+
+ for (i = 0; i < png_ptr->offset_table_count; i++)
+ {
+ if (ptr == png_ptr->offset_table_ptr[i])
+ {
+ ptr = NULL;
+ png_ptr->offset_table_count_free++;
+ break;
+ }
+ }
+ if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
+ {
+ farfree(png_ptr->offset_table);
+ farfree(png_ptr->offset_table_ptr);
+ png_ptr->offset_table = NULL;
+ png_ptr->offset_table_ptr = NULL;
+ }
+ }
+
+ if (ptr != NULL)
+ {
+ farfree(ptr);
+ }
+}
+
+#else /* Not the Borland DOS special memory handler */
+
+/* Allocate memory for a png_struct or a png_info. The malloc and
+ memset can be replaced by a single call to calloc() if this is thought
+ to improve performance noticably. */
+png_voidp /* PRIVATE */
+png_create_struct(int type)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+ return (png_create_struct_2(type, png_malloc_ptr_NULL, png_voidp_NULL));
+}
+
+/* Allocate memory for a png_struct or a png_info. The malloc and
+ memset can be replaced by a single call to calloc() if this is thought
+ to improve performance noticably. */
+png_voidp /* PRIVATE */
+png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+ png_size_t size;
+ png_voidp struct_ptr;
+
+ if (type == PNG_STRUCT_INFO)
+ size = png_sizeof(png_info);
+ else if (type == PNG_STRUCT_PNG)
+ size = png_sizeof(png_struct);
+ else
+ return (NULL);
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (malloc_fn != NULL)
+ {
+ png_struct dummy_struct;
+ png_structp png_ptr = &dummy_struct;
+ png_ptr->mem_ptr=mem_ptr;
+ struct_ptr = (*(malloc_fn))(png_ptr, size);
+ if (struct_ptr != NULL)
+ png_memset(struct_ptr, 0, size);
+ return (struct_ptr);
+ }
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+ struct_ptr = (png_voidp)farmalloc(size);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+ struct_ptr = (png_voidp)halloc(size, 1);
+# else
+ struct_ptr = (png_voidp)malloc(size);
+# endif
+#endif
+ if (struct_ptr != NULL)
+ png_memset(struct_ptr, 0, size);
+
+ return (struct_ptr);
+}
+
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct(png_voidp struct_ptr)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2(struct_ptr, png_free_ptr_NULL, png_voidp_NULL);
+}
+
+/* Free memory allocated by a png_create_struct() call */
+void /* PRIVATE */
+png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
+ png_voidp mem_ptr)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+ if (struct_ptr != NULL)
+ {
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (free_fn != NULL)
+ {
+ png_struct dummy_struct;
+ png_structp png_ptr = &dummy_struct;
+ png_ptr->mem_ptr=mem_ptr;
+ (*(free_fn))(png_ptr, struct_ptr);
+ return;
+ }
+#endif /* PNG_USER_MEM_SUPPORTED */
+#if defined(__TURBOC__) && !defined(__FLAT__)
+ farfree(struct_ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+ hfree(struct_ptr);
+# else
+ free(struct_ptr);
+# endif
+#endif
+ }
+}
+
+/* Allocate memory. For reasonable files, size should never exceed
+ * 64K. However, zlib may allocate more then 64K if you don't tell
+ * it not to. See zconf.h and png.h for more information. zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ */
+
+png_voidp /* PRIVATE */
+png_calloc(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+
+ ret = (png_malloc(png_ptr, size));
+ if (ret != NULL)
+ png_memset(ret,0,(png_size_t)size);
+ return (ret);
+}
+
+png_voidp PNGAPI
+png_malloc(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr == NULL || size == 0)
+ return (NULL);
+
+ if (png_ptr->malloc_fn != NULL)
+ ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+ else
+ ret = (png_malloc_default(png_ptr, size));
+ if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out of Memory!");
+ return (ret);
+}
+
+png_voidp PNGAPI
+png_malloc_default(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ret;
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+ if (png_ptr == NULL || size == 0)
+ return (NULL);
+
+#ifdef PNG_MAX_MALLOC_64K
+ if (size > (png_uint_32)65536L)
+ {
+#ifndef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Cannot Allocate > 64K");
+ else
+#endif
+ return NULL;
+ }
+#endif
+
+ /* Check for overflow */
+#if defined(__TURBOC__) && !defined(__FLAT__)
+ if (size != (unsigned long)size)
+ ret = NULL;
+ else
+ ret = farmalloc(size);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+ if (size != (unsigned long)size)
+ ret = NULL;
+ else
+ ret = halloc(size, 1);
+# else
+ if (size != (size_t)size)
+ ret = NULL;
+ else
+ ret = malloc((size_t)size);
+# endif
+#endif
+
+#ifndef PNG_USER_MEM_SUPPORTED
+ if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
+ png_error(png_ptr, "Out of Memory");
+#endif
+
+ return (ret);
+}
+
+/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
+ * without taking any action.
+ */
+void PNGAPI
+png_free(png_structp png_ptr, png_voidp ptr)
+{
+ if (png_ptr == NULL || ptr == NULL)
+ return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr->free_fn != NULL)
+ {
+ (*(png_ptr->free_fn))(png_ptr, ptr);
+ return;
+ }
+ else
+ png_free_default(png_ptr, ptr);
+}
+void PNGAPI
+png_free_default(png_structp png_ptr, png_voidp ptr)
+{
+ if (png_ptr == NULL || ptr == NULL)
+ return;
+
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#if defined(__TURBOC__) && !defined(__FLAT__)
+ farfree(ptr);
+#else
+# if defined(_MSC_VER) && defined(MAXSEG_64K)
+ hfree(ptr);
+# else
+ free(ptr);
+# endif
+#endif
+}
+
+#endif /* Not Borland DOS special memory handler */
+
+#ifdef PNG_1_0_X
+# define png_malloc_warn png_malloc
+#else
+/* This function was added at libpng version 1.2.3. The png_malloc_warn()
+ * function will set up png_malloc() to issue a png_warning and return NULL
+ * instead of issuing a png_error, if it fails to allocate the requested
+ * memory.
+ */
+png_voidp PNGAPI
+png_malloc_warn(png_structp png_ptr, png_uint_32 size)
+{
+ png_voidp ptr;
+ png_uint_32 save_flags;
+ if (png_ptr == NULL)
+ return (NULL);
+
+ save_flags = png_ptr->flags;
+ png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
+ ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
+ png_ptr->flags=save_flags;
+ return(ptr);
+}
+#endif
+
+png_voidp PNGAPI
+png_memcpy_check (png_structp png_ptr, png_voidp s1, png_voidp s2,
+ png_uint_32 length)
+{
+ png_size_t size;
+
+ size = (png_size_t)length;
+ if ((png_uint_32)size != length)
+ png_error(png_ptr, "Overflow in png_memcpy_check.");
+
+ return(png_memcpy (s1, s2, size));
+}
+
+png_voidp PNGAPI
+png_memset_check (png_structp png_ptr, png_voidp s1, int value,
+ png_uint_32 length)
+{
+ png_size_t size;
+
+ size = (png_size_t)length;
+ if ((png_uint_32)size != length)
+ png_error(png_ptr, "Overflow in png_memset_check.");
+
+ return (png_memset (s1, value, size));
+
+}
+
+#ifdef PNG_USER_MEM_SUPPORTED
+/* This function is called when the application wants to use another method
+ * of allocating and freeing memory.
+ */
+void PNGAPI
+png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+ malloc_fn, png_free_ptr free_fn)
+{
+ if (png_ptr != NULL)
+ {
+ png_ptr->mem_ptr = mem_ptr;
+ png_ptr->malloc_fn = malloc_fn;
+ png_ptr->free_fn = free_fn;
+ }
+}
+
+/* This function returns a pointer to the mem_ptr associated with the user
+ * functions. The application should free any memory associated with this
+ * pointer before png_write_destroy and png_read_destroy are called.
+ */
+png_voidp PNGAPI
+png_get_mem_ptr(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return (NULL);
+ return ((png_voidp)png_ptr->mem_ptr);
+}
+#endif /* PNG_USER_MEM_SUPPORTED */
+#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngnow.png b/Source/LibPNG/pngnow.png
new file mode 100644
index 0000000..82793eb
--- /dev/null
+++ b/Source/LibPNG/pngnow.png
Binary files differ
diff --git a/Source/LibPNG/pngpread.c b/Source/LibPNG/pngpread.c
new file mode 100644
index 0000000..5af209d
--- /dev/null
+++ b/Source/LibPNG/pngpread.c
@@ -0,0 +1,1241 @@
+
+/* pngpread.c - read a png file in push mode
+ *
+ * Last changed in libpng 1.2.44 [June 26, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+
+/* Push model modes */
+#define PNG_READ_SIG_MODE 0
+#define PNG_READ_CHUNK_MODE 1
+#define PNG_READ_IDAT_MODE 2
+#define PNG_SKIP_MODE 3
+#define PNG_READ_tEXt_MODE 4
+#define PNG_READ_zTXt_MODE 5
+#define PNG_READ_DONE_MODE 6
+#define PNG_READ_iTXt_MODE 7
+#define PNG_ERROR_MODE 8
+
+void PNGAPI
+png_process_data(png_structp png_ptr, png_infop info_ptr,
+ png_bytep buffer, png_size_t buffer_size)
+{
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ png_push_restore_buffer(png_ptr, buffer, buffer_size);
+
+ while (png_ptr->buffer_size)
+ {
+ png_process_some_data(png_ptr, info_ptr);
+ }
+}
+
+/* What we do with the incoming data depends on what we were previously
+ * doing before we ran out of data...
+ */
+void /* PRIVATE */
+png_process_some_data(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr == NULL)
+ return;
+
+ switch (png_ptr->process_mode)
+ {
+ case PNG_READ_SIG_MODE:
+ {
+ png_push_read_sig(png_ptr, info_ptr);
+ break;
+ }
+
+ case PNG_READ_CHUNK_MODE:
+ {
+ png_push_read_chunk(png_ptr, info_ptr);
+ break;
+ }
+
+ case PNG_READ_IDAT_MODE:
+ {
+ png_push_read_IDAT(png_ptr);
+ break;
+ }
+
+ case PNG_SKIP_MODE:
+ {
+ png_push_crc_finish(png_ptr);
+ break;
+ }
+
+ default:
+ {
+ png_ptr->buffer_size = 0;
+ break;
+ }
+ }
+}
+
+/* Read any remaining signature bytes from the stream and compare them with
+ * the correct PNG signature. It is possible that this routine is called
+ * with bytes already read from the signature, either because they have been
+ * checked by the calling application, or because of multiple calls to this
+ * routine.
+ */
+void /* PRIVATE */
+png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
+{
+ png_size_t num_checked = png_ptr->sig_bytes,
+ num_to_check = 8 - num_checked;
+
+ if (png_ptr->buffer_size < num_to_check)
+ {
+ num_to_check = png_ptr->buffer_size;
+ }
+
+ png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
+ num_to_check);
+ png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
+
+ if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+ {
+ if (num_checked < 4 &&
+ png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+ png_error(png_ptr, "Not a PNG file");
+ else
+ png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+ }
+ else
+ {
+ if (png_ptr->sig_bytes >= 8)
+ {
+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+ }
+ }
+}
+
+void /* PRIVATE */
+png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IHDR;
+ PNG_CONST PNG_IDAT;
+ PNG_CONST PNG_IEND;
+ PNG_CONST PNG_PLTE;
+#ifdef PNG_READ_bKGD_SUPPORTED
+ PNG_CONST PNG_bKGD;
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ PNG_CONST PNG_cHRM;
+#endif
+#ifdef PNG_READ_gAMA_SUPPORTED
+ PNG_CONST PNG_gAMA;
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ PNG_CONST PNG_hIST;
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ PNG_CONST PNG_iCCP;
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ PNG_CONST PNG_iTXt;
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ PNG_CONST PNG_oFFs;
+#endif
+#ifdef PNG_READ_pCAL_SUPPORTED
+ PNG_CONST PNG_pCAL;
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ PNG_CONST PNG_pHYs;
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ PNG_CONST PNG_sBIT;
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ PNG_CONST PNG_sCAL;
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ PNG_CONST PNG_sRGB;
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ PNG_CONST PNG_sPLT;
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ PNG_CONST PNG_tEXt;
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ PNG_CONST PNG_tIME;
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ PNG_CONST PNG_tRNS;
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ PNG_CONST PNG_zTXt;
+#endif
+#endif /* PNG_USE_LOCAL_ARRAYS */
+
+ /* First we make sure we have enough data for the 4 byte chunk name
+ * and the 4 byte chunk length before proceeding with decoding the
+ * chunk data. To fully decode each of these chunks, we also make
+ * sure we have enough data in the buffer for the 4 byte CRC at the
+ * end of every chunk (except IDAT, which is handled separately).
+ */
+ if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ {
+ png_byte chunk_length[4];
+
+ if (png_ptr->buffer_size < 8)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_push_fill_buffer(png_ptr, chunk_length, 4);
+ png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
+ png_reset_crc(png_ptr);
+ png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+ png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+ png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+ }
+
+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ if (png_ptr->mode & PNG_AFTER_IDAT)
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
+ if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
+ {
+ if (png_ptr->push_length != 13)
+ png_error(png_ptr, "Invalid IHDR length");
+
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+ else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
+
+ png_ptr->process_mode = PNG_READ_DONE_MODE;
+ png_push_have_end(png_ptr, info_ptr);
+ }
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ png_ptr->mode |= PNG_HAVE_IDAT;
+
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+
+ if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+ png_ptr->mode |= PNG_HAVE_PLTE;
+
+ else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ {
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ !(png_ptr->mode & PNG_HAVE_PLTE))
+ png_error(png_ptr, "Missing PLTE before IDAT");
+ }
+ }
+
+#endif
+ else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+ png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+ else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ {
+ /* If we reach an IDAT chunk, this means we have read all of the
+ * header chunks, and we can start reading the image (or if this
+ * is called after the image has been read - we have an error).
+ */
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ !(png_ptr->mode & PNG_HAVE_PLTE))
+ png_error(png_ptr, "Missing PLTE before IDAT");
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ if (png_ptr->push_length == 0)
+ return;
+
+ if (png_ptr->mode & PNG_AFTER_IDAT)
+ png_error(png_ptr, "Too many IDAT's found");
+ }
+
+ png_ptr->idat_size = png_ptr->push_length;
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
+ png_push_have_info(png_ptr, info_ptr);
+ png_ptr->zstream.avail_out =
+ (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1;
+ png_ptr->zstream.next_out = png_ptr->row_buf;
+ return;
+ }
+
+#ifdef PNG_READ_gAMA_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_bKGD_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
+ }
+#endif
+
+#ifdef PNG_READ_pCAL_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+#endif
+ else
+ {
+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ }
+
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+}
+
+void /* PRIVATE */
+png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
+{
+ png_ptr->process_mode = PNG_SKIP_MODE;
+ png_ptr->skip_length = skip;
+}
+
+void /* PRIVATE */
+png_push_crc_finish(png_structp png_ptr)
+{
+ if (png_ptr->skip_length && png_ptr->save_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
+ save_size = (png_size_t)png_ptr->skip_length;
+ else
+ save_size = png_ptr->save_buffer_size;
+
+ png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+ png_ptr->skip_length -= save_size;
+ png_ptr->buffer_size -= save_size;
+ png_ptr->save_buffer_size -= save_size;
+ png_ptr->save_buffer_ptr += save_size;
+ }
+ if (png_ptr->skip_length && png_ptr->current_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
+ save_size = (png_size_t)png_ptr->skip_length;
+ else
+ save_size = png_ptr->current_buffer_size;
+
+ png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+ png_ptr->skip_length -= save_size;
+ png_ptr->buffer_size -= save_size;
+ png_ptr->current_buffer_size -= save_size;
+ png_ptr->current_buffer_ptr += save_size;
+ }
+ if (!png_ptr->skip_length)
+ {
+ if (png_ptr->buffer_size < 4)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_crc_finish(png_ptr, 0);
+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+ }
+}
+
+void PNGAPI
+png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
+{
+ png_bytep ptr;
+
+ if (png_ptr == NULL)
+ return;
+
+ ptr = buffer;
+ if (png_ptr->save_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (length < png_ptr->save_buffer_size)
+ save_size = length;
+ else
+ save_size = png_ptr->save_buffer_size;
+
+ png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
+ length -= save_size;
+ ptr += save_size;
+ png_ptr->buffer_size -= save_size;
+ png_ptr->save_buffer_size -= save_size;
+ png_ptr->save_buffer_ptr += save_size;
+ }
+ if (length && png_ptr->current_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (length < png_ptr->current_buffer_size)
+ save_size = length;
+
+ else
+ save_size = png_ptr->current_buffer_size;
+
+ png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
+ png_ptr->buffer_size -= save_size;
+ png_ptr->current_buffer_size -= save_size;
+ png_ptr->current_buffer_ptr += save_size;
+ }
+}
+
+void /* PRIVATE */
+png_push_save_buffer(png_structp png_ptr)
+{
+ if (png_ptr->save_buffer_size)
+ {
+ if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
+ {
+ png_size_t i, istop;
+ png_bytep sp;
+ png_bytep dp;
+
+ istop = png_ptr->save_buffer_size;
+ for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
+ i < istop; i++, sp++, dp++)
+ {
+ *dp = *sp;
+ }
+ }
+ }
+ if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
+ png_ptr->save_buffer_max)
+ {
+ png_size_t new_max;
+ png_bytep old_buffer;
+
+ if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
+ (png_ptr->current_buffer_size + 256))
+ {
+ png_error(png_ptr, "Potential overflow of save_buffer");
+ }
+
+ new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
+ old_buffer = png_ptr->save_buffer;
+ png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
+ (png_uint_32)new_max);
+ if (png_ptr->save_buffer == NULL)
+ {
+ png_free(png_ptr, old_buffer);
+ png_error(png_ptr, "Insufficient memory for save_buffer");
+ }
+ png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+ png_free(png_ptr, old_buffer);
+ png_ptr->save_buffer_max = new_max;
+ }
+ if (png_ptr->current_buffer_size)
+ {
+ png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
+ png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
+ png_ptr->save_buffer_size += png_ptr->current_buffer_size;
+ png_ptr->current_buffer_size = 0;
+ }
+ png_ptr->save_buffer_ptr = png_ptr->save_buffer;
+ png_ptr->buffer_size = 0;
+}
+
+void /* PRIVATE */
+png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
+ png_size_t buffer_length)
+{
+ png_ptr->current_buffer = buffer;
+ png_ptr->current_buffer_size = buffer_length;
+ png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
+ png_ptr->current_buffer_ptr = png_ptr->current_buffer;
+}
+
+void /* PRIVATE */
+png_push_read_IDAT(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IDAT;
+#endif
+ if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ {
+ png_byte chunk_length[4];
+
+ if (png_ptr->buffer_size < 8)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_push_fill_buffer(png_ptr, chunk_length, 4);
+ png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
+ png_reset_crc(png_ptr);
+ png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+ png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
+
+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ {
+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ png_error(png_ptr, "Not enough compressed data");
+ return;
+ }
+
+ png_ptr->idat_size = png_ptr->push_length;
+ }
+ if (png_ptr->idat_size && png_ptr->save_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
+ {
+ save_size = (png_size_t)png_ptr->idat_size;
+
+ /* Check for overflow */
+ if ((png_uint_32)save_size != png_ptr->idat_size)
+ png_error(png_ptr, "save_size overflowed in pngpread");
+ }
+ else
+ save_size = png_ptr->save_buffer_size;
+
+ png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+ png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
+
+ png_ptr->idat_size -= save_size;
+ png_ptr->buffer_size -= save_size;
+ png_ptr->save_buffer_size -= save_size;
+ png_ptr->save_buffer_ptr += save_size;
+ }
+ if (png_ptr->idat_size && png_ptr->current_buffer_size)
+ {
+ png_size_t save_size;
+
+ if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
+ {
+ save_size = (png_size_t)png_ptr->idat_size;
+
+ /* Check for overflow */
+ if ((png_uint_32)save_size != png_ptr->idat_size)
+ png_error(png_ptr, "save_size overflowed in pngpread");
+ }
+ else
+ save_size = png_ptr->current_buffer_size;
+
+ png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+ png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
+
+ png_ptr->idat_size -= save_size;
+ png_ptr->buffer_size -= save_size;
+ png_ptr->current_buffer_size -= save_size;
+ png_ptr->current_buffer_ptr += save_size;
+ }
+ if (!png_ptr->idat_size)
+ {
+ if (png_ptr->buffer_size < 4)
+ {
+ png_push_save_buffer(png_ptr);
+ return;
+ }
+
+ png_crc_finish(png_ptr, 0);
+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ }
+}
+
+void /* PRIVATE */
+png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
+ png_size_t buffer_length)
+{
+ /* The caller checks for a non-zero buffer length. */
+ if (!(buffer_length > 0) || buffer == NULL)
+ png_error(png_ptr, "No IDAT data (internal error)");
+
+ /* This routine must process all the data it has been given
+ * before returning, calling the row callback as required to
+ * handle the uncompressed results.
+ */
+ png_ptr->zstream.next_in = buffer;
+ png_ptr->zstream.avail_in = (uInt)buffer_length;
+
+ /* Keep going until the decompressed data is all processed
+ * or the stream marked as finished.
+ */
+ while (png_ptr->zstream.avail_in > 0 &&
+ !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ {
+ int ret;
+
+ /* We have data for zlib, but we must check that zlib
+ * has somewhere to put the results. It doesn't matter
+ * if we don't expect any results -- it may be the input
+ * data is just the LZ end code.
+ */
+ if (!(png_ptr->zstream.avail_out > 0))
+ {
+ png_ptr->zstream.avail_out =
+ (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1;
+ png_ptr->zstream.next_out = png_ptr->row_buf;
+ }
+
+ /* Using Z_SYNC_FLUSH here means that an unterminated
+ * LZ stream can still be handled (a stream with a missing
+ * end code), otherwise (Z_NO_FLUSH) a future zlib
+ * implementation might defer output and, therefore,
+ * change the current behavior. (See comments in inflate.c
+ * for why this doesn't happen at present with zlib 1.2.5.)
+ */
+ ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+
+ /* Check for any failure before proceeding. */
+ if (ret != Z_OK && ret != Z_STREAM_END)
+ {
+ /* Terminate the decompression. */
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+
+ /* This may be a truncated stream (missing or
+ * damaged end code). Treat that as a warning.
+ */
+ if (png_ptr->row_number >= png_ptr->num_rows ||
+ png_ptr->pass > 6)
+ png_warning(png_ptr, "Truncated compressed data in IDAT");
+ else
+ png_error(png_ptr, "Decompression error in IDAT");
+
+ /* Skip the check on unprocessed input */
+ return;
+ }
+
+ /* Did inflate output any data? */
+ if (png_ptr->zstream.next_out != png_ptr->row_buf)
+ {
+ /* Is this unexpected data after the last row?
+ * If it is, artificially terminate the LZ output
+ * here.
+ */
+ if (png_ptr->row_number >= png_ptr->num_rows ||
+ png_ptr->pass > 6)
+ {
+ /* Extra data. */
+ png_warning(png_ptr, "Extra compressed data in IDAT");
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ /* Do no more processing; skip the unprocessed
+ * input check below.
+ */
+ return;
+ }
+
+ /* Do we have a complete row? */
+ if (png_ptr->zstream.avail_out == 0)
+ png_push_process_row(png_ptr);
+ }
+
+ /* And check for the end of the stream. */
+ if (ret == Z_STREAM_END)
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ }
+
+ /* All the data should have been processed, if anything
+ * is left at this point we have bytes of IDAT data
+ * after the zlib end code.
+ */
+ if (png_ptr->zstream.avail_in > 0)
+ png_warning(png_ptr, "Extra compression data");
+}
+
+void /* PRIVATE */
+png_push_process_row(png_structp png_ptr)
+{
+ png_ptr->row_info.color_type = png_ptr->color_type;
+ png_ptr->row_info.width = png_ptr->iwidth;
+ png_ptr->row_info.channels = png_ptr->channels;
+ png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+ png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+
+ png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
+ png_ptr->row_info.width);
+
+ png_read_filter_row(png_ptr, &(png_ptr->row_info),
+ png_ptr->row_buf + 1, png_ptr->prev_row + 1,
+ (int)(png_ptr->row_buf[0]));
+
+ png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+ png_ptr->rowbytes + 1);
+
+ if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
+ png_do_read_transformations(png_ptr);
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* Blow up interlaced rows to full size */
+ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ {
+ if (png_ptr->pass < 6)
+/* old interface (pre-1.0.9):
+ png_do_read_interlace(&(png_ptr->row_info),
+ png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+ png_do_read_interlace(png_ptr);
+
+ switch (png_ptr->pass)
+ {
+ case 0:
+ {
+ int i;
+ for (i = 0; i < 8 && png_ptr->pass == 0; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
+ }
+
+ if (png_ptr->pass == 2) /* Pass 1 might be empty */
+ {
+ for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+
+ if (png_ptr->pass == 4 && png_ptr->height <= 4)
+ {
+ for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+
+ if (png_ptr->pass == 6 && png_ptr->height <= 4)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ break;
+ }
+
+ case 1:
+ {
+ int i;
+ for (i = 0; i < 8 && png_ptr->pass == 1; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ if (png_ptr->pass == 2) /* Skip top 4 generated rows */
+ {
+ for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+
+ break;
+ }
+
+ case 2:
+ {
+ int i;
+
+ for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ for (i = 0; i < 4 && png_ptr->pass == 2; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ if (png_ptr->pass == 4) /* Pass 3 might be empty */
+ {
+ for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ int i;
+
+ for (i = 0; i < 4 && png_ptr->pass == 3; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ if (png_ptr->pass == 4) /* Skip top two generated rows */
+ {
+ for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ int i;
+
+ for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ for (i = 0; i < 2 && png_ptr->pass == 4; i++)
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ if (png_ptr->pass == 6) /* Pass 5 might be empty */
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ break;
+ }
+
+ case 5:
+ {
+ int i;
+
+ for (i = 0; i < 2 && png_ptr->pass == 5; i++)
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ if (png_ptr->pass == 6) /* Skip top generated row */
+ {
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+
+ break;
+ }
+ case 6:
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+
+ if (png_ptr->pass != 6)
+ break;
+
+ png_push_have_row(png_ptr, png_bytep_NULL);
+ png_read_push_finish_row(png_ptr);
+ }
+ }
+ }
+ else
+#endif
+ {
+ png_push_have_row(png_ptr, png_ptr->row_buf + 1);
+ png_read_push_finish_row(png_ptr);
+ }
+}
+
+void /* PRIVATE */
+png_read_push_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+
+ /* Height of interlace block. This is not currently used - if you need
+ * it, uncomment it here and in png.h
+ PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ */
+#endif
+
+ png_ptr->row_number++;
+ if (png_ptr->row_number < png_ptr->num_rows)
+ return;
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ if (png_ptr->interlaced)
+ {
+ png_ptr->row_number = 0;
+ png_memset_check(png_ptr, png_ptr->prev_row, 0,
+ png_ptr->rowbytes + 1);
+ do
+ {
+ png_ptr->pass++;
+ if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
+ (png_ptr->pass == 3 && png_ptr->width < 3) ||
+ (png_ptr->pass == 5 && png_ptr->width < 2))
+ png_ptr->pass++;
+
+ if (png_ptr->pass > 7)
+ png_ptr->pass--;
+
+ if (png_ptr->pass >= 7)
+ break;
+
+ png_ptr->iwidth = (png_ptr->width +
+ png_pass_inc[png_ptr->pass] - 1 -
+ png_pass_start[png_ptr->pass]) /
+ png_pass_inc[png_ptr->pass];
+
+ if (png_ptr->transformations & PNG_INTERLACE)
+ break;
+
+ png_ptr->num_rows = (png_ptr->height +
+ png_pass_yinc[png_ptr->pass] - 1 -
+ png_pass_ystart[png_ptr->pass]) /
+ png_pass_yinc[png_ptr->pass];
+
+ } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
+ }
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+}
+
+void /* PRIVATE */
+png_push_have_info(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr->info_fn != NULL)
+ (*(png_ptr->info_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_end(png_structp png_ptr, png_infop info_ptr)
+{
+ if (png_ptr->end_fn != NULL)
+ (*(png_ptr->end_fn))(png_ptr, info_ptr);
+}
+
+void /* PRIVATE */
+png_push_have_row(png_structp png_ptr, png_bytep row)
+{
+ if (png_ptr->row_fn != NULL)
+ (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
+ (int)png_ptr->pass);
+}
+
+void PNGAPI
+png_progressive_combine_row (png_structp png_ptr,
+ png_bytep old_row, png_bytep new_row)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST int FARDATA png_pass_dsp_mask[7] =
+ {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
+#endif
+
+ if (png_ptr == NULL)
+ return;
+
+ if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */
+ png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
+}
+
+void PNGAPI
+png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
+ png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
+ png_progressive_end_ptr end_fn)
+{
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->info_fn = info_fn;
+ png_ptr->row_fn = row_fn;
+ png_ptr->end_fn = end_fn;
+
+ png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
+}
+
+png_voidp PNGAPI
+png_get_progressive_ptr(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return (NULL);
+
+ return png_ptr->io_ptr;
+}
+#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
diff --git a/Source/LibPNG/pngread.c b/Source/LibPNG/pngread.c
new file mode 100644
index 0000000..0a075df
--- /dev/null
+++ b/Source/LibPNG/pngread.c
@@ -0,0 +1,1515 @@
+
+/* pngread.c - read a PNG file
+ *
+ * Last changed in libpng 1.2.48 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file contains routines that an application calls directly to
+ * read a PNG file or stream.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_READ_SUPPORTED
+
+/* Create a PNG structure for reading, and allocate any memory needed. */
+png_structp PNGAPI
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
+}
+
+/* Alternate create PNG structure for reading, and allocate any memory
+ * needed.
+ */
+png_structp PNGAPI
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
+#ifdef PNG_SETJMP_SUPPORTED
+ volatile
+#endif
+ png_structp png_ptr;
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+ jmp_buf jmpbuf;
+#endif
+#endif
+
+ int i;
+
+ png_debug(1, "in png_create_read_struct");
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+ (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
+#else
+ png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+#endif
+ if (png_ptr == NULL)
+ return (NULL);
+
+ /* Added at libpng-1.2.6 */
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+ png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+ /* Added at libpng-1.2.43 and 1.4.0 */
+ png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+#else
+ if (setjmp(png_ptr->jmpbuf))
+#endif
+ {
+ png_free(png_ptr, png_ptr->zbuf);
+ png_ptr->zbuf = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)png_ptr,
+ (png_free_ptr)free_fn, (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)png_ptr);
+#endif
+ return (NULL);
+ }
+#ifdef USE_FAR_KEYWORD
+ png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
+#endif
+#endif /* PNG_SETJMP_SUPPORTED */
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif
+
+ png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+ if (user_png_ver)
+ {
+ i = 0;
+ do
+ {
+ if (user_png_ver[i] != png_libpng_ver[i])
+ png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+ } while (png_libpng_ver[i++]);
+ }
+ else
+ png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+
+
+ if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+ {
+ /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+ * we must recompile any applications that use any older library version.
+ * For versions after libpng 1.0, we will be compatible, so we need
+ * only check the first digit.
+ */
+ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+ (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+ (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char msg[80];
+ if (user_png_ver)
+ {
+ png_snprintf(msg, 80,
+ "Application was compiled with png.h from libpng-%.20s",
+ user_png_ver);
+ png_warning(png_ptr, msg);
+ }
+ png_snprintf(msg, 80,
+ "Application is running with png.c from libpng-%.20s",
+ png_libpng_ver);
+ png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "Incompatible libpng version in application and library");
+ }
+ }
+
+ /* Initialize zbuf - compression buffer */
+ png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+ png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+ png_ptr->zstream.zalloc = png_zalloc;
+ png_ptr->zstream.zfree = png_zfree;
+ png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+ switch (inflateInit(&png_ptr->zstream))
+ {
+ case Z_OK: /* Do nothing */ break;
+ case Z_MEM_ERROR:
+ case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error");
+ break;
+ case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
+ break;
+ default: png_error(png_ptr, "Unknown zlib error");
+ }
+
+
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+ png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
+
+#ifdef PNG_SETJMP_SUPPORTED
+/* Applications that neglect to set up their own setjmp() and then
+ encounter a png_error() will longjmp here. Since the jmpbuf is
+ then meaningless we abort instead of returning. */
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+ PNG_ABORT();
+ png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
+#else
+ if (setjmp(png_ptr->jmpbuf))
+ PNG_ABORT();
+#endif
+#endif /* PNG_SETJMP_SUPPORTED */
+
+ return (png_ptr);
+}
+
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+/* Initialize PNG structure for reading, and allocate any memory needed.
+ * This interface is deprecated in favour of the png_create_read_struct(),
+ * and it will disappear as of libpng-1.3.0.
+ */
+#undef png_read_init
+void PNGAPI
+png_read_init(png_structp png_ptr)
+{
+ /* We only come here via pre-1.0.7-compiled applications */
+ png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+void PNGAPI
+png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+ png_size_t png_struct_size, png_size_t png_info_size)
+{
+ /* We only come here via pre-1.0.12-compiled applications */
+ if (png_ptr == NULL)
+ return;
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ if (png_sizeof(png_struct) > png_struct_size ||
+ png_sizeof(png_info) > png_info_size)
+ {
+ char msg[80];
+ png_ptr->warning_fn = NULL;
+ if (user_png_ver)
+ {
+ png_snprintf(msg, 80,
+ "Application was compiled with png.h from libpng-%.20s",
+ user_png_ver);
+ png_warning(png_ptr, msg);
+ }
+ png_snprintf(msg, 80,
+ "Application is running with png.c from libpng-%.20s",
+ png_libpng_ver);
+ png_warning(png_ptr, msg);
+ }
+#endif
+ if (png_sizeof(png_struct) > png_struct_size)
+ {
+ png_ptr->error_fn = NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "The png struct allocated by the application for reading is"
+ " too small.");
+ }
+ if (png_sizeof(png_info) > png_info_size)
+ {
+ png_ptr->error_fn = NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "The info struct allocated by application for reading is"
+ " too small.");
+ }
+ png_read_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+#endif /* PNG_1_0_X || PNG_1_2_X */
+
+void PNGAPI
+png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+ png_size_t png_struct_size)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf tmp_jmp; /* to save current jump buffer */
+#endif
+
+ int i = 0;
+
+ png_structp png_ptr=*ptr_ptr;
+
+ if (png_ptr == NULL)
+ return;
+
+ do
+ {
+ if (user_png_ver[i] != png_libpng_ver[i])
+ {
+#ifdef PNG_LEGACY_SUPPORTED
+ png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+ png_ptr->warning_fn = NULL;
+ png_warning(png_ptr,
+ "Application uses deprecated png_read_init() and should be"
+ " recompiled.");
+ break;
+#endif
+ }
+ } while (png_libpng_ver[i++]);
+
+ png_debug(1, "in png_read_init_3");
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Save jump buffer and error functions */
+ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
+#endif
+
+ if (png_sizeof(png_struct) > png_struct_size)
+ {
+ png_destroy_struct(png_ptr);
+ *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+ png_ptr = *ptr_ptr;
+ }
+
+ /* Reset all variables to 0 */
+ png_memset(png_ptr, 0, png_sizeof(png_struct));
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Restore jump buffer */
+ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
+#endif
+
+ /* Added at libpng-1.2.6 */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+ png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+#endif
+
+ /* Initialize zbuf - compression buffer */
+ png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+ png_ptr->zstream.zalloc = png_zalloc;
+ png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+ png_ptr->zstream.zalloc = png_zalloc;
+ png_ptr->zstream.zfree = png_zfree;
+ png_ptr->zstream.opaque = (voidpf)png_ptr;
+
+ switch (inflateInit(&png_ptr->zstream))
+ {
+ case Z_OK: /* Do nothing */ break;
+ case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
+ case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error");
+ break;
+ default: png_error(png_ptr, "Unknown zlib error");
+ }
+
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+
+ png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
+}
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read the information before the actual image data. This has been
+ * changed in v0.90 to allow reading a file that already has the magic
+ * bytes read from the stream. You can tell libpng how many bytes have
+ * been read from the beginning of the stream (up to the maximum of 8)
+ * via png_set_sig_bytes(), and we will only check the remaining bytes
+ * here. The application can then have access to the signature bytes we
+ * read if it is determined that this isn't a valid PNG file.
+ */
+void PNGAPI
+png_read_info(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_read_info");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ /* If we haven't checked all of the PNG signature bytes, do so now. */
+ if (png_ptr->sig_bytes < 8)
+ {
+ png_size_t num_checked = png_ptr->sig_bytes,
+ num_to_check = 8 - num_checked;
+
+ png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
+ png_ptr->sig_bytes = 8;
+
+ if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+ {
+ if (num_checked < 4 &&
+ png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
+ png_error(png_ptr, "Not a PNG file");
+ else
+ png_error(png_ptr, "PNG file corrupted by ASCII conversion");
+ }
+ if (num_checked < 3)
+ png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+ }
+
+ for (;;)
+ {
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IHDR;
+ PNG_CONST PNG_IDAT;
+ PNG_CONST PNG_IEND;
+ PNG_CONST PNG_PLTE;
+#ifdef PNG_READ_bKGD_SUPPORTED
+ PNG_CONST PNG_bKGD;
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ PNG_CONST PNG_cHRM;
+#endif
+#ifdef PNG_READ_gAMA_SUPPORTED
+ PNG_CONST PNG_gAMA;
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ PNG_CONST PNG_hIST;
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ PNG_CONST PNG_iCCP;
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ PNG_CONST PNG_iTXt;
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ PNG_CONST PNG_oFFs;
+#endif
+#ifdef PNG_READ_pCAL_SUPPORTED
+ PNG_CONST PNG_pCAL;
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ PNG_CONST PNG_pHYs;
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ PNG_CONST PNG_sBIT;
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ PNG_CONST PNG_sCAL;
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ PNG_CONST PNG_sPLT;
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ PNG_CONST PNG_sRGB;
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ PNG_CONST PNG_tEXt;
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ PNG_CONST PNG_tIME;
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ PNG_CONST PNG_tRNS;
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ PNG_CONST PNG_zTXt;
+#endif
+#endif /* PNG_USE_LOCAL_ARRAYS */
+ png_uint_32 length = png_read_chunk_header(png_ptr);
+ PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
+
+ /* This should be a binary subdivision search or a hash for
+ * matching the chunk name rather than a linear search.
+ */
+ if (!png_memcmp(chunk_name, png_IDAT, 4))
+ if (png_ptr->mode & PNG_AFTER_IDAT)
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
+ if (!png_memcmp(chunk_name, png_IHDR, 4))
+ png_handle_IHDR(png_ptr, info_ptr, length);
+ else if (!png_memcmp(chunk_name, png_IEND, 4))
+ png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ else if (png_handle_as_unknown(png_ptr, chunk_name))
+ {
+ if (!png_memcmp(chunk_name, png_IDAT, 4))
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_handle_unknown(png_ptr, info_ptr, length);
+ if (!png_memcmp(chunk_name, png_PLTE, 4))
+ png_ptr->mode |= PNG_HAVE_PLTE;
+ else if (!png_memcmp(chunk_name, png_IDAT, 4))
+ {
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before IDAT");
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ !(png_ptr->mode & PNG_HAVE_PLTE))
+ png_error(png_ptr, "Missing PLTE before IDAT");
+ break;
+ }
+ }
+#endif
+ else if (!png_memcmp(chunk_name, png_PLTE, 4))
+ png_handle_PLTE(png_ptr, info_ptr, length);
+ else if (!png_memcmp(chunk_name, png_IDAT, 4))
+ {
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before IDAT");
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ !(png_ptr->mode & PNG_HAVE_PLTE))
+ png_error(png_ptr, "Missing PLTE before IDAT");
+
+ png_ptr->idat_size = length;
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ break;
+ }
+#ifdef PNG_READ_bKGD_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_bKGD, 4))
+ png_handle_bKGD(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_cHRM, 4))
+ png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_gAMA_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_gAMA, 4))
+ png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_hIST, 4))
+ png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_oFFs, 4))
+ png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_pCAL_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_pCAL, 4))
+ png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sCAL, 4))
+ png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_pHYs, 4))
+ png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sBIT, 4))
+ png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sRGB, 4))
+ png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_iCCP, 4))
+ png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sPLT, 4))
+ png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tEXt, 4))
+ png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tIME, 4))
+ png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tRNS, 4))
+ png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_zTXt, 4))
+ png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_iTXt, 4))
+ png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+ else
+ png_handle_unknown(png_ptr, info_ptr, length);
+ }
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+/* Optional call to update the users info_ptr structure */
+void PNGAPI
+png_read_update_info(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_read_update_info");
+
+ if (png_ptr == NULL)
+ return;
+ if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ png_read_start_row(png_ptr);
+ else
+ png_warning(png_ptr,
+ "Ignoring extra png_read_update_info() call; row buffer not reallocated");
+
+ png_read_transform_info(png_ptr, info_ptr);
+}
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Initialize palette, background, etc, after transformations
+ * are set, but before any reading takes place. This allows
+ * the user to obtain a gamma-corrected palette, for example.
+ * If the user doesn't call this, we will do it ourselves.
+ */
+void PNGAPI
+png_start_read_image(png_structp png_ptr)
+{
+ png_debug(1, "in png_start_read_image");
+
+ if (png_ptr == NULL)
+ return;
+ if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ png_read_start_row(png_ptr);
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+void PNGAPI
+png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
+{
+ PNG_CONST PNG_IDAT;
+ PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
+ 0xff};
+ PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
+ int ret;
+
+ if (png_ptr == NULL)
+ return;
+
+ png_debug2(1, "in png_read_row (row %lu, pass %d)",
+ png_ptr->row_number, png_ptr->pass);
+
+ if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ png_read_start_row(png_ptr);
+ if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+ {
+ /* Check for transforms that have been set but were defined out */
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
+ if (png_ptr->transformations & PNG_FILLER)
+ png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
+ !defined(PNG_READ_PACKSWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACK)
+ png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
+ if (png_ptr->transformations & PNG_SHIFT)
+ png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
+ if (png_ptr->transformations & PNG_BGR)
+ png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_SWAP_BYTES)
+ png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
+#endif
+ }
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* If interlaced and we do not need a new row, combine row and return */
+ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ {
+ switch (png_ptr->pass)
+ {
+ case 0:
+ if (png_ptr->row_number & 0x07)
+ {
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 1:
+ if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+ {
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 2:
+ if ((png_ptr->row_number & 0x07) != 4)
+ {
+ if (dsp_row != NULL && (png_ptr->row_number & 4))
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 3:
+ if ((png_ptr->row_number & 3) || png_ptr->width < 3)
+ {
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 4:
+ if ((png_ptr->row_number & 3) != 2)
+ {
+ if (dsp_row != NULL && (png_ptr->row_number & 2))
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 5:
+ if ((png_ptr->row_number & 1) || png_ptr->width < 2)
+ {
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 6:
+ if (!(png_ptr->row_number & 1))
+ {
+ png_read_finish_row(png_ptr);
+ return;
+ }
+ break;
+ }
+ }
+#endif
+
+ if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ png_error(png_ptr, "Invalid attempt to read row data");
+
+ png_ptr->zstream.next_out = png_ptr->row_buf;
+ png_ptr->zstream.avail_out =
+ (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1);
+ do
+ {
+ if (!(png_ptr->zstream.avail_in))
+ {
+ while (!png_ptr->idat_size)
+ {
+ png_crc_finish(png_ptr, 0);
+
+ png_ptr->idat_size = png_read_chunk_header(png_ptr);
+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ png_error(png_ptr, "Not enough image data");
+ }
+ png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_in = png_ptr->zbuf;
+ if (png_ptr->zbuf_size > png_ptr->idat_size)
+ png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+ png_crc_read(png_ptr, png_ptr->zbuf,
+ (png_size_t)png_ptr->zstream.avail_in);
+ png_ptr->idat_size -= png_ptr->zstream.avail_in;
+ }
+ ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+ if (ret == Z_STREAM_END)
+ {
+ if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
+ png_ptr->idat_size)
+ png_error(png_ptr, "Extra compressed data");
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ break;
+ }
+ if (ret != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+ "Decompression error");
+
+ } while (png_ptr->zstream.avail_out);
+
+ png_ptr->row_info.color_type = png_ptr->color_type;
+ png_ptr->row_info.width = png_ptr->iwidth;
+ png_ptr->row_info.channels = png_ptr->channels;
+ png_ptr->row_info.bit_depth = png_ptr->bit_depth;
+ png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
+ png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
+ png_ptr->row_info.width);
+
+ if (png_ptr->row_buf[0])
+ png_read_filter_row(png_ptr, &(png_ptr->row_info),
+ png_ptr->row_buf + 1, png_ptr->prev_row + 1,
+ (int)(png_ptr->row_buf[0]));
+
+ png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
+ png_ptr->rowbytes + 1);
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+ {
+ /* Intrapixel differencing */
+ png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ }
+#endif
+
+
+ if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
+ png_do_read_transformations(png_ptr);
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* Blow up interlaced rows to full size */
+ if (png_ptr->interlaced &&
+ (png_ptr->transformations & PNG_INTERLACE))
+ {
+ if (png_ptr->pass < 6)
+ /* Old interface (pre-1.0.9):
+ * png_do_read_interlace(&(png_ptr->row_info),
+ * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
+ */
+ png_do_read_interlace(png_ptr);
+
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row,
+ png_pass_dsp_mask[png_ptr->pass]);
+ if (row != NULL)
+ png_combine_row(png_ptr, row,
+ png_pass_mask[png_ptr->pass]);
+ }
+ else
+#endif
+ {
+ if (row != NULL)
+ png_combine_row(png_ptr, row, 0xff);
+ if (dsp_row != NULL)
+ png_combine_row(png_ptr, dsp_row, 0xff);
+ }
+ png_read_finish_row(png_ptr);
+
+ if (png_ptr->read_row_fn != NULL)
+ (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read one or more rows of image data. If the image is interlaced,
+ * and png_set_interlace_handling() has been called, the rows need to
+ * contain the contents of the rows from the previous pass. If the
+ * image has alpha or transparency, and png_handle_alpha()[*] has been
+ * called, the rows contents must be initialized to the contents of the
+ * screen.
+ *
+ * "row" holds the actual image, and pixels are placed in it
+ * as they arrive. If the image is displayed after each pass, it will
+ * appear to "sparkle" in. "display_row" can be used to display a
+ * "chunky" progressive image, with finer detail added as it becomes
+ * available. If you do not want this "chunky" display, you may pass
+ * NULL for display_row. If you do not want the sparkle display, and
+ * you have not called png_handle_alpha(), you may pass NULL for rows.
+ * If you have called png_handle_alpha(), and the image has either an
+ * alpha channel or a transparency chunk, you must provide a buffer for
+ * rows. In this case, you do not have to provide a display_row buffer
+ * also, but you may. If the image is not interlaced, or if you have
+ * not called png_set_interlace_handling(), the display_row buffer will
+ * be ignored, so pass NULL to it.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of this version of libpng
+ */
+
+void PNGAPI
+png_read_rows(png_structp png_ptr, png_bytepp row,
+ png_bytepp display_row, png_uint_32 num_rows)
+{
+ png_uint_32 i;
+ png_bytepp rp;
+ png_bytepp dp;
+
+ png_debug(1, "in png_read_rows");
+
+ if (png_ptr == NULL)
+ return;
+ rp = row;
+ dp = display_row;
+ if (rp != NULL && dp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep rptr = *rp++;
+ png_bytep dptr = *dp++;
+
+ png_read_row(png_ptr, rptr, dptr);
+ }
+ else if (rp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep rptr = *rp;
+ png_read_row(png_ptr, rptr, png_bytep_NULL);
+ rp++;
+ }
+ else if (dp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep dptr = *dp;
+ png_read_row(png_ptr, png_bytep_NULL, dptr);
+ dp++;
+ }
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read the entire image. If the image has an alpha channel or a tRNS
+ * chunk, and you have called png_handle_alpha()[*], you will need to
+ * initialize the image to the current image that PNG will be overlaying.
+ * We set the num_rows again here, in case it was incorrectly set in
+ * png_read_start_row() by a call to png_read_update_info() or
+ * png_start_read_image() if png_set_interlace_handling() wasn't called
+ * prior to either of these functions like it should have been. You can
+ * only call this function once. If you desire to have an image for
+ * each pass of a interlaced image, use png_read_rows() instead.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of this version of libpng
+ */
+void PNGAPI
+png_read_image(png_structp png_ptr, png_bytepp image)
+{
+ png_uint_32 i, image_height;
+ int pass, j;
+ png_bytepp rp;
+
+ png_debug(1, "in png_read_image");
+
+ if (png_ptr == NULL)
+ return;
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ pass = png_set_interlace_handling(png_ptr);
+#else
+ if (png_ptr->interlaced)
+ png_error(png_ptr,
+ "Cannot read interlaced image -- interlace handler disabled.");
+ pass = 1;
+#endif
+
+
+ image_height=png_ptr->height;
+ png_ptr->num_rows = image_height; /* Make sure this is set correctly */
+
+ for (j = 0; j < pass; j++)
+ {
+ rp = image;
+ for (i = 0; i < image_height; i++)
+ {
+ png_read_row(png_ptr, *rp, png_bytep_NULL);
+ rp++;
+ }
+ }
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+/* Read the end of the PNG file. Will not read past the end of the
+ * file, will verify the end is accurate, and will read any comments
+ * or time information at the end of the file, if info is not NULL.
+ */
+void PNGAPI
+png_read_end(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_read_end");
+
+ if (png_ptr == NULL)
+ return;
+ png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+
+ do
+ {
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IHDR;
+ PNG_CONST PNG_IDAT;
+ PNG_CONST PNG_IEND;
+ PNG_CONST PNG_PLTE;
+#ifdef PNG_READ_bKGD_SUPPORTED
+ PNG_CONST PNG_bKGD;
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ PNG_CONST PNG_cHRM;
+#endif
+#ifdef PNG_READ_gAMA_SUPPORTED
+ PNG_CONST PNG_gAMA;
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ PNG_CONST PNG_hIST;
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ PNG_CONST PNG_iCCP;
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ PNG_CONST PNG_iTXt;
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ PNG_CONST PNG_oFFs;
+#endif
+#ifdef PNG_READ_pCAL_SUPPORTED
+ PNG_CONST PNG_pCAL;
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ PNG_CONST PNG_pHYs;
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ PNG_CONST PNG_sBIT;
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ PNG_CONST PNG_sCAL;
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ PNG_CONST PNG_sPLT;
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ PNG_CONST PNG_sRGB;
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ PNG_CONST PNG_tEXt;
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ PNG_CONST PNG_tIME;
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ PNG_CONST PNG_tRNS;
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ PNG_CONST PNG_zTXt;
+#endif
+#endif /* PNG_USE_LOCAL_ARRAYS */
+ png_uint_32 length = png_read_chunk_header(png_ptr);
+ PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
+
+ if (!png_memcmp(chunk_name, png_IHDR, 4))
+ png_handle_IHDR(png_ptr, info_ptr, length);
+ else if (!png_memcmp(chunk_name, png_IEND, 4))
+ png_handle_IEND(png_ptr, info_ptr, length);
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ else if (png_handle_as_unknown(png_ptr, chunk_name))
+ {
+ if (!png_memcmp(chunk_name, png_IDAT, 4))
+ {
+ if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ png_error(png_ptr, "Too many IDAT's found");
+ }
+ png_handle_unknown(png_ptr, info_ptr, length);
+ if (!png_memcmp(chunk_name, png_PLTE, 4))
+ png_ptr->mode |= PNG_HAVE_PLTE;
+ }
+#endif
+ else if (!png_memcmp(chunk_name, png_IDAT, 4))
+ {
+ /* Zero length IDATs are legal after the last IDAT has been
+ * read, but not after other chunks have been read.
+ */
+ if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ png_error(png_ptr, "Too many IDAT's found");
+ png_crc_finish(png_ptr, length);
+ }
+ else if (!png_memcmp(chunk_name, png_PLTE, 4))
+ png_handle_PLTE(png_ptr, info_ptr, length);
+#ifdef PNG_READ_bKGD_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_bKGD, 4))
+ png_handle_bKGD(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_cHRM_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_cHRM, 4))
+ png_handle_cHRM(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_gAMA_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_gAMA, 4))
+ png_handle_gAMA(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_hIST, 4))
+ png_handle_hIST(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_oFFs_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_oFFs, 4))
+ png_handle_oFFs(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_pCAL_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_pCAL, 4))
+ png_handle_pCAL(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sCAL_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sCAL, 4))
+ png_handle_sCAL(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_pHYs_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_pHYs, 4))
+ png_handle_pHYs(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sBIT_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sBIT, 4))
+ png_handle_sBIT(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sRGB_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sRGB, 4))
+ png_handle_sRGB(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_iCCP_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_iCCP, 4))
+ png_handle_iCCP(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_sPLT_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_sPLT, 4))
+ png_handle_sPLT(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tEXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tEXt, 4))
+ png_handle_tEXt(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tIME_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tIME, 4))
+ png_handle_tIME(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_tRNS_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_tRNS, 4))
+ png_handle_tRNS(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_zTXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_zTXt, 4))
+ png_handle_zTXt(png_ptr, info_ptr, length);
+#endif
+#ifdef PNG_READ_iTXt_SUPPORTED
+ else if (!png_memcmp(chunk_name, png_iTXt, 4))
+ png_handle_iTXt(png_ptr, info_ptr, length);
+#endif
+ else
+ png_handle_unknown(png_ptr, info_ptr, length);
+ } while (!(png_ptr->mode & PNG_HAVE_IEND));
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+/* Free all memory used by the read */
+void PNGAPI
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
+ png_infopp end_info_ptr_ptr)
+{
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL, end_info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn = NULL;
+ png_voidp mem_ptr = NULL;
+#endif
+
+ png_debug(1, "in png_destroy_read_struct");
+
+ if (png_ptr_ptr != NULL)
+ png_ptr = *png_ptr_ptr;
+ if (png_ptr == NULL)
+ return;
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+ mem_ptr = png_ptr->mem_ptr;
+#endif
+
+ if (info_ptr_ptr != NULL)
+ info_ptr = *info_ptr_ptr;
+
+ if (end_info_ptr_ptr != NULL)
+ end_info_ptr = *end_info_ptr_ptr;
+
+ png_read_destroy(png_ptr, info_ptr, end_info_ptr);
+
+ if (info_ptr != NULL)
+ {
+#ifdef PNG_TEXT_SUPPORTED
+ png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+ (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)info_ptr);
+#endif
+ *info_ptr_ptr = NULL;
+ }
+
+ if (end_info_ptr != NULL)
+ {
+#ifdef PNG_READ_TEXT_SUPPORTED
+ png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
+#endif
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
+ (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)end_info_ptr);
+#endif
+ *end_info_ptr_ptr = NULL;
+ }
+
+ if (png_ptr != NULL)
+ {
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+ (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)png_ptr);
+#endif
+ *png_ptr_ptr = NULL;
+ }
+}
+
+/* Free all memory used by the read (old method) */
+void /* PRIVATE */
+png_read_destroy(png_structp png_ptr, png_infop info_ptr,
+ png_infop end_info_ptr)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf tmp_jmp;
+#endif
+ png_error_ptr error_fn;
+ png_error_ptr warning_fn;
+ png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn;
+#endif
+
+ png_debug(1, "in png_read_destroy");
+
+ if (info_ptr != NULL)
+ png_info_destroy(png_ptr, info_ptr);
+
+ if (end_info_ptr != NULL)
+ png_info_destroy(png_ptr, end_info_ptr);
+
+ png_free(png_ptr, png_ptr->zbuf);
+ png_free(png_ptr, png_ptr->big_row_buf);
+ png_free(png_ptr, png_ptr->prev_row);
+ png_free(png_ptr, png_ptr->chunkdata);
+#ifdef PNG_READ_DITHER_SUPPORTED
+ png_free(png_ptr, png_ptr->palette_lookup);
+ png_free(png_ptr, png_ptr->dither_index);
+#endif
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ png_free(png_ptr, png_ptr->gamma_table);
+#endif
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ png_free(png_ptr, png_ptr->gamma_from_1);
+ png_free(png_ptr, png_ptr->gamma_to_1);
+#endif
+#ifdef PNG_FREE_ME_SUPPORTED
+ if (png_ptr->free_me & PNG_FREE_PLTE)
+ png_zfree(png_ptr, png_ptr->palette);
+ png_ptr->free_me &= ~PNG_FREE_PLTE;
+#else
+ if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
+ png_zfree(png_ptr, png_ptr->palette);
+ png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
+#endif
+#if defined(PNG_tRNS_SUPPORTED) || \
+ defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_FREE_ME_SUPPORTED
+ if (png_ptr->free_me & PNG_FREE_TRNS)
+ png_free(png_ptr, png_ptr->trans);
+ png_ptr->free_me &= ~PNG_FREE_TRNS;
+#else
+ if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
+ png_free(png_ptr, png_ptr->trans);
+ png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
+#endif
+#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+#ifdef PNG_FREE_ME_SUPPORTED
+ if (png_ptr->free_me & PNG_FREE_HIST)
+ png_free(png_ptr, png_ptr->hist);
+ png_ptr->free_me &= ~PNG_FREE_HIST;
+#else
+ if (png_ptr->flags & PNG_FLAG_FREE_HIST)
+ png_free(png_ptr, png_ptr->hist);
+ png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
+#endif
+#endif
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (png_ptr->gamma_16_table != NULL)
+ {
+ int i;
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
+ {
+ png_free(png_ptr, png_ptr->gamma_16_table[i]);
+ }
+ png_free(png_ptr, png_ptr->gamma_16_table);
+ }
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ if (png_ptr->gamma_16_from_1 != NULL)
+ {
+ int i;
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
+ {
+ png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
+ }
+ png_free(png_ptr, png_ptr->gamma_16_from_1);
+ }
+ if (png_ptr->gamma_16_to_1 != NULL)
+ {
+ int i;
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
+ {
+ png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
+ }
+ png_free(png_ptr, png_ptr->gamma_16_to_1);
+ }
+#endif
+#endif
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+ inflateEnd(&png_ptr->zstream);
+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
+ png_free(png_ptr, png_ptr->save_buffer);
+#endif
+
+ /* Save the important info out of the png_struct, in case it is
+ * being used again.
+ */
+#ifdef PNG_SETJMP_SUPPORTED
+ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
+#endif
+
+ error_fn = png_ptr->error_fn;
+ warning_fn = png_ptr->warning_fn;
+ error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+#endif
+
+ png_memset(png_ptr, 0, png_sizeof(png_struct));
+
+ png_ptr->error_fn = error_fn;
+ png_ptr->warning_fn = warning_fn;
+ png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_ptr->free_fn = free_fn;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
+#endif
+
+}
+
+void PNGAPI
+png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
+{
+ if (png_ptr == NULL)
+ return;
+ png_ptr->read_row_fn = read_row_fn;
+}
+
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+void PNGAPI
+png_read_png(png_structp png_ptr, png_infop info_ptr,
+ int transforms,
+ voidp params)
+{
+ int row;
+
+ if (png_ptr == NULL)
+ return;
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ /* Invert the alpha channel from opacity to transparency
+ */
+ if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ png_set_invert_alpha(png_ptr);
+#endif
+
+ /* png_read_info() gives us all of the information from the
+ * PNG file before the first IDAT (image data chunk).
+ */
+ png_read_info(png_ptr, info_ptr);
+ if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
+ png_error(png_ptr, "Image is too high to process with png_read_png()");
+
+ /* -------------- image transformations start here ------------------- */
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+ /* Tell libpng to strip 16 bit/color files down to 8 bits per color.
+ */
+ if (transforms & PNG_TRANSFORM_STRIP_16)
+ png_set_strip_16(png_ptr);
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ /* Strip alpha bytes from the input data without combining with
+ * the background (not recommended).
+ */
+ if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+ png_set_strip_alpha(png_ptr);
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
+ /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
+ * byte into separate bytes (useful for paletted and grayscale images).
+ */
+ if (transforms & PNG_TRANSFORM_PACKING)
+ png_set_packing(png_ptr);
+#endif
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ /* Change the order of packed pixels to least significant bit first
+ * (not useful if you are using png_set_packing).
+ */
+ if (transforms & PNG_TRANSFORM_PACKSWAP)
+ png_set_packswap(png_ptr);
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ /* Expand paletted colors into true RGB triplets
+ * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
+ * Expand paletted or RGB images with transparency to full alpha
+ * channels so the data will be available as RGBA quartets.
+ */
+ if (transforms & PNG_TRANSFORM_EXPAND)
+ if ((png_ptr->bit_depth < 8) ||
+ (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
+ (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
+ png_set_expand(png_ptr);
+#endif
+
+ /* We don't handle background color or gamma transformation or dithering.
+ */
+
+#ifdef PNG_READ_INVERT_SUPPORTED
+ /* Invert monochrome files to have 0 as white and 1 as black
+ */
+ if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ png_set_invert_mono(png_ptr);
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ /* If you want to shift the pixel values from the range [0,255] or
+ * [0,65535] to the original [0,7] or [0,31], or whatever range the
+ * colors were originally in:
+ */
+ if ((transforms & PNG_TRANSFORM_SHIFT)
+ && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
+ {
+ png_color_8p sig_bit;
+
+ png_get_sBIT(png_ptr, info_ptr, &sig_bit);
+ png_set_shift(png_ptr, sig_bit);
+ }
+#endif
+
+#ifdef PNG_READ_BGR_SUPPORTED
+ /* Flip the RGB pixels to BGR (or RGBA to BGRA)
+ */
+ if (transforms & PNG_TRANSFORM_BGR)
+ png_set_bgr(png_ptr);
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+ /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)
+ */
+ if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ png_set_swap_alpha(png_ptr);
+#endif
+
+#ifdef PNG_READ_SWAP_SUPPORTED
+ /* Swap bytes of 16 bit files to least significant byte first
+ */
+ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ png_set_swap(png_ptr);
+#endif
+
+/* Added at libpng-1.2.41 */
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ /* Invert the alpha channel from opacity to transparency
+ */
+ if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ png_set_invert_alpha(png_ptr);
+#endif
+
+/* Added at libpng-1.2.41 */
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* Expand grayscale image to RGB
+ */
+ if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
+ png_set_gray_to_rgb(png_ptr);
+#endif
+
+ /* We don't handle adding filler bytes */
+
+ /* Optional call to gamma correct and add the background to the palette
+ * and update info structure. REQUIRED if you are expecting libpng to
+ * update the palette for you (i.e., you selected such a transform above).
+ */
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* -------------- image transformations end here ------------------- */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+#endif
+ if (info_ptr->row_pointers == NULL)
+ {
+ info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
+ info_ptr->height * png_sizeof(png_bytep));
+ png_memset(info_ptr->row_pointers, 0, info_ptr->height
+ * png_sizeof(png_bytep));
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_ROWS;
+#endif
+
+ for (row = 0; row < (int)info_ptr->height; row++)
+ info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
+ png_get_rowbytes(png_ptr, info_ptr));
+ }
+
+ png_read_image(png_ptr, info_ptr->row_pointers);
+ info_ptr->valid |= PNG_INFO_IDAT;
+
+ /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
+ png_read_end(png_ptr, info_ptr);
+
+ transforms = transforms; /* Quiet compiler warnings */
+ params = params;
+
+}
+#endif /* PNG_INFO_IMAGE_SUPPORTED */
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* PNG_READ_SUPPORTED */
diff --git a/Source/LibPNG/pngrio.c b/Source/LibPNG/pngrio.c
new file mode 100644
index 0000000..6978682
--- /dev/null
+++ b/Source/LibPNG/pngrio.c
@@ -0,0 +1,180 @@
+
+/* pngrio.c - functions for data input
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file provides a location for all input. Users who need
+ * special handling are expected to write a function that has the same
+ * arguments as this and performs a similar function, but that possibly
+ * has a different input method. Note that you shouldn't change this
+ * function, but rather write a replacement function and then make
+ * libpng use it at run time with png_set_read_fn(...).
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_READ_SUPPORTED
+
+/* Read the data from whatever input you are using. The default routine
+ * reads from a file pointer. Note that this routine sometimes gets called
+ * with very small lengths, so you should implement some kind of simple
+ * buffering if you are using unbuffered reads. This should never be asked
+ * to read more then 64K on a 16 bit machine.
+ */
+void /* PRIVATE */
+png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_debug1(4, "reading %d bytes", (int)length);
+
+ if (png_ptr->read_data_fn != NULL)
+ (*(png_ptr->read_data_fn))(png_ptr, data, length);
+ else
+ png_error(png_ptr, "Call to NULL read function");
+}
+
+#ifdef PNG_STDIO_SUPPORTED
+/* This is the function that does the actual reading of data. If you are
+ * not reading from a standard C stream, you should create a replacement
+ * read_data function and use it at run time with png_set_read_fn(), rather
+ * than changing the library.
+ */
+#ifndef USE_FAR_KEYWORD
+void PNGAPI
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_size_t check;
+
+ if (png_ptr == NULL)
+ return;
+ /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+ * instead of an int, which is what fread() actually returns.
+ */
+#ifdef _WIN32_WCE
+ if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+ check = 0;
+#else
+ check = (png_size_t)fread(data, (png_size_t)1, length,
+ (png_FILE_p)png_ptr->io_ptr);
+#endif
+
+ if (check != length)
+ png_error(png_ptr, "Read Error");
+}
+#else
+/* This is the model-independent version. Since the standard I/O library
+ can't handle far buffers in the medium and small models, we have to copy
+ the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void PNGAPI
+png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ int check;
+ png_byte *n_data;
+ png_FILE_p io_ptr;
+
+ if (png_ptr == NULL)
+ return;
+ /* Check if data really is near. If so, use usual code. */
+ n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+ io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+ if ((png_bytep)n_data == data)
+ {
+#ifdef _WIN32_WCE
+ if ( !ReadFile((HANDLE)(png_ptr->io_ptr), data, length, &check,
+ NULL) )
+ check = 0;
+#else
+ check = fread(n_data, 1, length, io_ptr);
+#endif
+ }
+ else
+ {
+ png_byte buf[NEAR_BUF_SIZE];
+ png_size_t read, remaining, err;
+ check = 0;
+ remaining = length;
+ do
+ {
+ read = MIN(NEAR_BUF_SIZE, remaining);
+#ifdef _WIN32_WCE
+ if ( !ReadFile((HANDLE)(io_ptr), buf, read, &err, NULL) )
+ err = 0;
+#else
+ err = fread(buf, (png_size_t)1, read, io_ptr);
+#endif
+ png_memcpy(data, buf, read); /* copy far buffer to near buffer */
+ if (err != read)
+ break;
+ else
+ check += err;
+ data += read;
+ remaining -= read;
+ }
+ while (remaining != 0);
+ }
+ if ((png_uint_32)check != (png_uint_32)length)
+ png_error(png_ptr, "read Error");
+}
+#endif
+#endif
+
+/* This function allows the application to supply a new input function
+ * for libpng if standard C streams aren't being used.
+ *
+ * This function takes as its arguments:
+ * png_ptr - pointer to a png input data structure
+ * io_ptr - pointer to user supplied structure containing info about
+ * the input functions. May be NULL.
+ * read_data_fn - pointer to a new input function that takes as its
+ * arguments a pointer to a png_struct, a pointer to
+ * a location where input data can be stored, and a 32-bit
+ * unsigned int that is the number of bytes to be read.
+ * To exit and output any fatal error messages the new write
+ * function should call png_error(png_ptr, "Error msg").
+ * May be NULL, in which case libpng's default function will
+ * be used.
+ */
+void PNGAPI
+png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
+ png_rw_ptr read_data_fn)
+{
+ if (png_ptr == NULL)
+ return;
+ png_ptr->io_ptr = io_ptr;
+
+#ifdef PNG_STDIO_SUPPORTED
+ if (read_data_fn != NULL)
+ png_ptr->read_data_fn = read_data_fn;
+ else
+ png_ptr->read_data_fn = png_default_read_data;
+#else
+ png_ptr->read_data_fn = read_data_fn;
+#endif
+
+ /* It is an error to write to a read device */
+ if (png_ptr->write_data_fn != NULL)
+ {
+ png_ptr->write_data_fn = NULL;
+ png_warning(png_ptr,
+ "It's an error to set both read_data_fn and write_data_fn in the ");
+ png_warning(png_ptr,
+ "same structure. Resetting write_data_fn to NULL.");
+ }
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+ png_ptr->output_flush_fn = NULL;
+#endif
+}
+#endif /* PNG_READ_SUPPORTED */
diff --git a/Source/LibPNG/pngrtran.c b/Source/LibPNG/pngrtran.c
new file mode 100644
index 0000000..c486930
--- /dev/null
+++ b/Source/LibPNG/pngrtran.c
@@ -0,0 +1,4470 @@
+
+/* pngrtran.c - transforms the data in a row for PNG readers
+ *
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file contains functions optionally called by an application
+ * in order to tell libpng how to handle data when reading a PNG.
+ * Transformations that are used in both reading and writing are
+ * in pngtrans.c.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_READ_SUPPORTED
+
+/* Set the action on getting a CRC error for an ancillary or critical chunk. */
+void PNGAPI
+png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+{
+ png_debug(1, "in png_set_crc_action");
+
+ if (png_ptr == NULL)
+ return;
+
+ /* Tell libpng how we react to CRC errors in critical chunks */
+ switch (crit_action)
+ {
+ case PNG_CRC_NO_CHANGE: /* Leave setting as is */
+ break;
+
+ case PNG_CRC_WARN_USE: /* Warn/use data */
+ png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+ png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
+ break;
+
+ case PNG_CRC_QUIET_USE: /* Quiet/use data */
+ png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+ png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
+ PNG_FLAG_CRC_CRITICAL_IGNORE;
+ break;
+
+ case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
+ png_warning(png_ptr,
+ "Can't discard critical data on CRC error.");
+ case PNG_CRC_ERROR_QUIT: /* Error/quit */
+
+ case PNG_CRC_DEFAULT:
+ default:
+ png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
+ break;
+ }
+
+ /* Tell libpng how we react to CRC errors in ancillary chunks */
+ switch (ancil_action)
+ {
+ case PNG_CRC_NO_CHANGE: /* Leave setting as is */
+ break;
+
+ case PNG_CRC_WARN_USE: /* Warn/use data */
+ png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+ png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
+ break;
+
+ case PNG_CRC_QUIET_USE: /* Quiet/use data */
+ png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+ png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
+ PNG_FLAG_CRC_ANCILLARY_NOWARN;
+ break;
+
+ case PNG_CRC_ERROR_QUIT: /* Error/quit */
+ png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+ png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
+ break;
+
+ case PNG_CRC_WARN_DISCARD: /* Warn/discard data */
+
+ case PNG_CRC_DEFAULT:
+ default:
+ png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
+ break;
+ }
+}
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Handle alpha and tRNS via a background color */
+void PNGAPI
+png_set_background(png_structp png_ptr,
+ png_color_16p background_color, int background_gamma_code,
+ int need_expand, double background_gamma)
+{
+ png_debug(1, "in png_set_background");
+
+ if (png_ptr == NULL)
+ return;
+ if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
+ {
+ png_warning(png_ptr, "Application must supply a known background gamma");
+ return;
+ }
+
+ png_ptr->transformations |= PNG_BACKGROUND;
+ png_memcpy(&(png_ptr->background), background_color,
+ png_sizeof(png_color_16));
+ png_ptr->background_gamma = (float)background_gamma;
+ png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
+ png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
+}
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Strip 16 bit depth files to 8 bit depth */
+void PNGAPI
+png_set_strip_16(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_strip_16");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_16_TO_8;
+}
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+void PNGAPI
+png_set_strip_alpha(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_strip_alpha");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
+}
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+/* Dither file to 8 bit. Supply a palette, the current number
+ * of elements in the palette, the maximum number of elements
+ * allowed, and a histogram if possible. If the current number
+ * of colors is greater then the maximum number, the palette will be
+ * modified to fit in the maximum number. "full_dither" indicates
+ * whether we need a dithering cube set up for RGB images, or if we
+ * simply are reducing the number of colors in a paletted image.
+ */
+
+typedef struct png_dsort_struct
+{
+ struct png_dsort_struct FAR * next;
+ png_byte left;
+ png_byte right;
+} png_dsort;
+typedef png_dsort FAR * png_dsortp;
+typedef png_dsort FAR * FAR * png_dsortpp;
+
+void PNGAPI
+png_set_dither(png_structp png_ptr, png_colorp palette,
+ int num_palette, int maximum_colors, png_uint_16p histogram,
+ int full_dither)
+{
+ png_debug(1, "in png_set_dither");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_DITHER;
+
+ if (!full_dither)
+ {
+ int i;
+
+ png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ for (i = 0; i < num_palette; i++)
+ png_ptr->dither_index[i] = (png_byte)i;
+ }
+
+ if (num_palette > maximum_colors)
+ {
+ if (histogram != NULL)
+ {
+ /* This is easy enough, just throw out the least used colors.
+ * Perhaps not the best solution, but good enough.
+ */
+
+ int i;
+
+ /* Initialize an array to sort colors */
+ png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(num_palette * png_sizeof(png_byte)));
+
+ /* Initialize the dither_sort array */
+ for (i = 0; i < num_palette; i++)
+ png_ptr->dither_sort[i] = (png_byte)i;
+
+ /* Find the least used palette entries by starting a
+ * bubble sort, and running it until we have sorted
+ * out enough colors. Note that we don't care about
+ * sorting all the colors, just finding which are
+ * least used.
+ */
+
+ for (i = num_palette - 1; i >= maximum_colors; i--)
+ {
+ int done; /* To stop early if the list is pre-sorted */
+ int j;
+
+ done = 1;
+ for (j = 0; j < i; j++)
+ {
+ if (histogram[png_ptr->dither_sort[j]]
+ < histogram[png_ptr->dither_sort[j + 1]])
+ {
+ png_byte t;
+
+ t = png_ptr->dither_sort[j];
+ png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
+ png_ptr->dither_sort[j + 1] = t;
+ done = 0;
+ }
+ }
+ if (done)
+ break;
+ }
+
+ /* Swap the palette around, and set up a table, if necessary */
+ if (full_dither)
+ {
+ int j = num_palette;
+
+ /* Put all the useful colors within the max, but don't
+ * move the others.
+ */
+ for (i = 0; i < maximum_colors; i++)
+ {
+ if ((int)png_ptr->dither_sort[i] >= maximum_colors)
+ {
+ do
+ j--;
+ while ((int)png_ptr->dither_sort[j] >= maximum_colors);
+ palette[i] = palette[j];
+ }
+ }
+ }
+ else
+ {
+ int j = num_palette;
+
+ /* Move all the used colors inside the max limit, and
+ * develop a translation table.
+ */
+ for (i = 0; i < maximum_colors; i++)
+ {
+ /* Only move the colors we need to */
+ if ((int)png_ptr->dither_sort[i] >= maximum_colors)
+ {
+ png_color tmp_color;
+
+ do
+ j--;
+ while ((int)png_ptr->dither_sort[j] >= maximum_colors);
+
+ tmp_color = palette[j];
+ palette[j] = palette[i];
+ palette[i] = tmp_color;
+ /* Indicate where the color went */
+ png_ptr->dither_index[j] = (png_byte)i;
+ png_ptr->dither_index[i] = (png_byte)j;
+ }
+ }
+
+ /* Find closest color for those colors we are not using */
+ for (i = 0; i < num_palette; i++)
+ {
+ if ((int)png_ptr->dither_index[i] >= maximum_colors)
+ {
+ int min_d, k, min_k, d_index;
+
+ /* Find the closest color to one we threw out */
+ d_index = png_ptr->dither_index[i];
+ min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
+ for (k = 1, min_k = 0; k < maximum_colors; k++)
+ {
+ int d;
+
+ d = PNG_COLOR_DIST(palette[d_index], palette[k]);
+
+ if (d < min_d)
+ {
+ min_d = d;
+ min_k = k;
+ }
+ }
+ /* Point to closest color */
+ png_ptr->dither_index[i] = (png_byte)min_k;
+ }
+ }
+ }
+ png_free(png_ptr, png_ptr->dither_sort);
+ png_ptr->dither_sort = NULL;
+ }
+ else
+ {
+ /* This is much harder to do simply (and quickly). Perhaps
+ * we need to go through a median cut routine, but those
+ * don't always behave themselves with only a few colors
+ * as input. So we will just find the closest two colors,
+ * and throw out one of them (chosen somewhat randomly).
+ * [We don't understand this at all, so if someone wants to
+ * work on improving it, be our guest - AED, GRP]
+ */
+ int i;
+ int max_d;
+ int num_new_palette;
+ png_dsortp t;
+ png_dsortpp hash;
+
+ t = NULL;
+
+ /* Initialize palette index arrays */
+ png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(num_palette * png_sizeof(png_byte)));
+
+ /* Initialize the sort array */
+ for (i = 0; i < num_palette; i++)
+ {
+ png_ptr->index_to_palette[i] = (png_byte)i;
+ png_ptr->palette_to_index[i] = (png_byte)i;
+ }
+
+ hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
+ png_sizeof(png_dsortp)));
+
+ num_new_palette = num_palette;
+
+ /* Initial wild guess at how far apart the farthest pixel
+ * pair we will be eliminating will be. Larger
+ * numbers mean more areas will be allocated, Smaller
+ * numbers run the risk of not saving enough data, and
+ * having to do this all over again.
+ *
+ * I have not done extensive checking on this number.
+ */
+ max_d = 96;
+
+ while (num_new_palette > maximum_colors)
+ {
+ for (i = 0; i < num_new_palette - 1; i++)
+ {
+ int j;
+
+ for (j = i + 1; j < num_new_palette; j++)
+ {
+ int d;
+
+ d = PNG_COLOR_DIST(palette[i], palette[j]);
+
+ if (d <= max_d)
+ {
+
+ t = (png_dsortp)png_malloc_warn(png_ptr,
+ (png_uint_32)(png_sizeof(png_dsort)));
+ if (t == NULL)
+ break;
+ t->next = hash[d];
+ t->left = (png_byte)i;
+ t->right = (png_byte)j;
+ hash[d] = t;
+ }
+ }
+ if (t == NULL)
+ break;
+ }
+
+ if (t != NULL)
+ for (i = 0; i <= max_d; i++)
+ {
+ if (hash[i] != NULL)
+ {
+ png_dsortp p;
+
+ for (p = hash[i]; p; p = p->next)
+ {
+ if ((int)png_ptr->index_to_palette[p->left]
+ < num_new_palette &&
+ (int)png_ptr->index_to_palette[p->right]
+ < num_new_palette)
+ {
+ int j, next_j;
+
+ if (num_new_palette & 0x01)
+ {
+ j = p->left;
+ next_j = p->right;
+ }
+ else
+ {
+ j = p->right;
+ next_j = p->left;
+ }
+
+ num_new_palette--;
+ palette[png_ptr->index_to_palette[j]]
+ = palette[num_new_palette];
+ if (!full_dither)
+ {
+ int k;
+
+ for (k = 0; k < num_palette; k++)
+ {
+ if (png_ptr->dither_index[k] ==
+ png_ptr->index_to_palette[j])
+ png_ptr->dither_index[k] =
+ png_ptr->index_to_palette[next_j];
+ if ((int)png_ptr->dither_index[k] ==
+ num_new_palette)
+ png_ptr->dither_index[k] =
+ png_ptr->index_to_palette[j];
+ }
+ }
+
+ png_ptr->index_to_palette[png_ptr->palette_to_index
+ [num_new_palette]] = png_ptr->index_to_palette[j];
+ png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
+ = png_ptr->palette_to_index[num_new_palette];
+
+ png_ptr->index_to_palette[j] =
+ (png_byte)num_new_palette;
+ png_ptr->palette_to_index[num_new_palette] =
+ (png_byte)j;
+ }
+ if (num_new_palette <= maximum_colors)
+ break;
+ }
+ if (num_new_palette <= maximum_colors)
+ break;
+ }
+ }
+
+ for (i = 0; i < 769; i++)
+ {
+ if (hash[i] != NULL)
+ {
+ png_dsortp p = hash[i];
+ while (p)
+ {
+ t = p->next;
+ png_free(png_ptr, p);
+ p = t;
+ }
+ }
+ hash[i] = 0;
+ }
+ max_d += 96;
+ }
+ png_free(png_ptr, hash);
+ png_free(png_ptr, png_ptr->palette_to_index);
+ png_free(png_ptr, png_ptr->index_to_palette);
+ png_ptr->palette_to_index = NULL;
+ png_ptr->index_to_palette = NULL;
+ }
+ num_palette = maximum_colors;
+ }
+ if (png_ptr->palette == NULL)
+ {
+ png_ptr->palette = palette;
+ }
+ png_ptr->num_palette = (png_uint_16)num_palette;
+
+ if (full_dither)
+ {
+ int i;
+ png_bytep distance;
+ int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
+ PNG_DITHER_BLUE_BITS;
+ int num_red = (1 << PNG_DITHER_RED_BITS);
+ int num_green = (1 << PNG_DITHER_GREEN_BITS);
+ int num_blue = (1 << PNG_DITHER_BLUE_BITS);
+ png_size_t num_entries = ((png_size_t)1 << total_bits);
+
+ png_ptr->palette_lookup = (png_bytep )png_calloc(png_ptr,
+ (png_uint_32)(num_entries * png_sizeof(png_byte)));
+
+ distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
+ png_sizeof(png_byte)));
+ png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
+
+ for (i = 0; i < num_palette; i++)
+ {
+ int ir, ig, ib;
+ int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
+ int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
+ int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
+
+ for (ir = 0; ir < num_red; ir++)
+ {
+ /* int dr = abs(ir - r); */
+ int dr = ((ir > r) ? ir - r : r - ir);
+ int index_r = (ir << (PNG_DITHER_BLUE_BITS +
+ PNG_DITHER_GREEN_BITS));
+
+ for (ig = 0; ig < num_green; ig++)
+ {
+ /* int dg = abs(ig - g); */
+ int dg = ((ig > g) ? ig - g : g - ig);
+ int dt = dr + dg;
+ int dm = ((dr > dg) ? dr : dg);
+ int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
+
+ for (ib = 0; ib < num_blue; ib++)
+ {
+ int d_index = index_g | ib;
+ /* int db = abs(ib - b); */
+ int db = ((ib > b) ? ib - b : b - ib);
+ int dmax = ((dm > db) ? dm : db);
+ int d = dmax + dt + db;
+
+ if (d < (int)distance[d_index])
+ {
+ distance[d_index] = (png_byte)d;
+ png_ptr->palette_lookup[d_index] = (png_byte)i;
+ }
+ }
+ }
+ }
+ }
+
+ png_free(png_ptr, distance);
+ }
+}
+#endif
+
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+/* Transform the image from the file_gamma to the screen_gamma. We
+ * only do transformations on images where the file_gamma and screen_gamma
+ * are not close reciprocals, otherwise it slows things down slightly, and
+ * also needlessly introduces small errors.
+ *
+ * We will turn off gamma transformation later if no semitransparent entries
+ * are present in the tRNS array for palette images. We can't do it here
+ * because we don't necessarily have the tRNS chunk yet.
+ */
+void PNGAPI
+png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+{
+ png_debug(1, "in png_set_gamma");
+
+ if (png_ptr == NULL)
+ return;
+
+ if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
+ (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
+ png_ptr->transformations |= PNG_GAMMA;
+ png_ptr->gamma = (float)file_gamma;
+ png_ptr->screen_gamma = (float)scrn_gamma;
+}
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+/* Expand paletted images to RGB, expand grayscale images of
+ * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
+ * to alpha channels.
+ */
+void PNGAPI
+png_set_expand(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_expand");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+}
+
+/* GRR 19990627: the following three functions currently are identical
+ * to png_set_expand(). However, it is entirely reasonable that someone
+ * might wish to expand an indexed image to RGB but *not* expand a single,
+ * fully transparent palette entry to a full alpha channel--perhaps instead
+ * convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
+ * the transparent color with a particular RGB value, or drop tRNS entirely.
+ * IOW, a future version of the library may make the transformations flag
+ * a bit more fine-grained, with separate bits for each of these three
+ * functions.
+ *
+ * More to the point, these functions make it obvious what libpng will be
+ * doing, whereas "expand" can (and does) mean any number of things.
+ *
+ * GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
+ * to expand only the sample depth but not to expand the tRNS to alpha
+ * and its name was changed to png_set_expand_gray_1_2_4_to_8().
+ */
+
+/* Expand paletted images to RGB. */
+void PNGAPI
+png_set_palette_to_rgb(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_palette_to_rgb");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+}
+
+#ifndef PNG_1_0_X
+/* Expand grayscale images of less than 8-bit depth to 8 bits. */
+void PNGAPI
+png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->transformations |= PNG_EXPAND;
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+}
+#endif
+
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+/* Expand grayscale images of less than 8-bit depth to 8 bits. */
+/* Deprecated as of libpng-1.2.9 */
+void PNGAPI
+png_set_gray_1_2_4_to_8(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_gray_1_2_4_to_8");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
+}
+#endif
+
+
+/* Expand tRNS chunks to alpha channels. */
+void PNGAPI
+png_set_tRNS_to_alpha(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_tRNS_to_alpha");
+
+ png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+}
+#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+void PNGAPI
+png_set_gray_to_rgb(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_gray_to_rgb");
+
+ png_ptr->transformations |= PNG_GRAY_TO_RGB;
+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
+}
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+/* Convert a RGB image to a grayscale of the same width. This allows us,
+ * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
+ */
+
+void PNGAPI
+png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+ double green)
+{
+ int red_fixed, green_fixed;
+ if (png_ptr == NULL)
+ return;
+ if (red > 21474.83647 || red < -21474.83648 ||
+ green > 21474.83647 || green < -21474.83648)
+ {
+ png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+ red_fixed = -1;
+ green_fixed = -1;
+ }
+ else
+ {
+ red_fixed = (int)((float)red*100000.0 + 0.5);
+ green_fixed = (int)((float)green*100000.0 + 0.5);
+ }
+ png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
+}
+#endif
+
+void PNGAPI
+png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+ png_fixed_point red, png_fixed_point green)
+{
+ png_debug(1, "in png_set_rgb_to_gray");
+
+ if (png_ptr == NULL)
+ return;
+
+ switch(error_action)
+ {
+ case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
+ break;
+
+ case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
+ break;
+
+ case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
+ }
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ png_ptr->transformations |= PNG_EXPAND;
+#else
+ {
+ png_warning(png_ptr,
+ "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
+ png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+ }
+#endif
+ {
+ png_uint_16 red_int, green_int;
+ if (red < 0 || green < 0)
+ {
+ red_int = 6968; /* .212671 * 32768 + .5 */
+ green_int = 23434; /* .715160 * 32768 + .5 */
+ }
+ else if (red + green < 100000L)
+ {
+ red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
+ green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
+ }
+ else
+ {
+ png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
+ red_int = 6968;
+ green_int = 23434;
+ }
+ png_ptr->rgb_to_gray_red_coeff = red_int;
+ png_ptr->rgb_to_gray_green_coeff = green_int;
+ png_ptr->rgb_to_gray_blue_coeff =
+ (png_uint_16)(32768 - red_int - green_int);
+ }
+}
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+void PNGAPI
+png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+ read_user_transform_fn)
+{
+ png_debug(1, "in png_set_read_user_transform_fn");
+
+ if (png_ptr == NULL)
+ return;
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ png_ptr->transformations |= PNG_USER_TRANSFORM;
+ png_ptr->read_user_transform_fn = read_user_transform_fn;
+#endif
+#ifdef PNG_LEGACY_SUPPORTED
+ if (read_user_transform_fn)
+ png_warning(png_ptr,
+ "This version of libpng does not support user transforms");
+#endif
+}
+#endif
+
+/* Initialize everything needed for the read. This includes modifying
+ * the palette.
+ */
+void /* PRIVATE */
+png_init_read_transformations(png_structp png_ptr)
+{
+ png_debug(1, "in png_init_read_transformations");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (png_ptr != NULL)
+#endif
+ {
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_SHIFT_SUPPORTED) || \
+ defined(PNG_READ_GAMMA_SUPPORTED)
+ int color_type = png_ptr->color_type;
+#endif
+
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* Detect gray background and attempt to enable optimization
+ * for gray --> RGB case
+ *
+ * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
+ * RGB_ALPHA (in which case need_expand is superfluous anyway), the
+ * background color might actually be gray yet not be flagged as such.
+ * This is not a problem for the current code, which uses
+ * PNG_BACKGROUND_IS_GRAY only to decide when to do the
+ * png_do_gray_to_rgb() transformation.
+ */
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+ !(color_type & PNG_COLOR_MASK_COLOR))
+ {
+ png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
+ } else if ((png_ptr->transformations & PNG_BACKGROUND) &&
+ !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+ (png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+ png_ptr->background.red == png_ptr->background.green &&
+ png_ptr->background.red == png_ptr->background.blue)
+ {
+ png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
+ png_ptr->background.gray = png_ptr->background.red;
+ }
+#endif
+
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
+ (png_ptr->transformations & PNG_EXPAND))
+ {
+ if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */
+ {
+ /* Expand background and tRNS chunks */
+ switch (png_ptr->bit_depth)
+ {
+ case 1:
+ png_ptr->background.gray *= (png_uint_16)0xff;
+ png_ptr->background.red = png_ptr->background.green
+ = png_ptr->background.blue = png_ptr->background.gray;
+ if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ {
+ png_ptr->trans_values.gray *= (png_uint_16)0xff;
+ png_ptr->trans_values.red = png_ptr->trans_values.green
+ = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
+ }
+ break;
+
+ case 2:
+ png_ptr->background.gray *= (png_uint_16)0x55;
+ png_ptr->background.red = png_ptr->background.green
+ = png_ptr->background.blue = png_ptr->background.gray;
+ if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ {
+ png_ptr->trans_values.gray *= (png_uint_16)0x55;
+ png_ptr->trans_values.red = png_ptr->trans_values.green
+ = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
+ }
+ break;
+
+ case 4:
+ png_ptr->background.gray *= (png_uint_16)0x11;
+ png_ptr->background.red = png_ptr->background.green
+ = png_ptr->background.blue = png_ptr->background.gray;
+ if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ {
+ png_ptr->trans_values.gray *= (png_uint_16)0x11;
+ png_ptr->trans_values.red = png_ptr->trans_values.green
+ = png_ptr->trans_values.blue = png_ptr->trans_values.gray;
+ }
+ break;
+
+ case 8:
+
+ case 16:
+ png_ptr->background.red = png_ptr->background.green
+ = png_ptr->background.blue = png_ptr->background.gray;
+ break;
+ }
+ }
+ else if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_ptr->background.red =
+ png_ptr->palette[png_ptr->background.index].red;
+ png_ptr->background.green =
+ png_ptr->palette[png_ptr->background.index].green;
+ png_ptr->background.blue =
+ png_ptr->palette[png_ptr->background.index].blue;
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_ALPHA)
+ {
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+#endif
+ {
+ /* Invert the alpha channel (in tRNS) unless the pixels are
+ * going to be expanded, in which case leave it for later
+ */
+ int i, istop;
+ istop=(int)png_ptr->num_trans;
+ for (i=0; i<istop; i++)
+ png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
+ }
+ }
+#endif
+
+ }
+ }
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
+ png_ptr->background_1 = png_ptr->background;
+#endif
+#if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
+
+ if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
+ && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
+ < PNG_GAMMA_THRESHOLD))
+ {
+ int i, k;
+ k=0;
+ for (i=0; i<png_ptr->num_trans; i++)
+ {
+ if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
+ k=1; /* Partial transparency is present */
+ }
+ if (k == 0)
+ png_ptr->transformations &= ~PNG_GAMMA;
+ }
+
+ if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) &&
+ png_ptr->gamma != 0.0)
+ {
+ png_build_gamma_table(png_ptr);
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ if (png_ptr->transformations & PNG_BACKGROUND)
+ {
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ /* Could skip if no transparency */
+ png_color back, back_1;
+ png_colorp palette = png_ptr->palette;
+ int num_palette = png_ptr->num_palette;
+ int i;
+ if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+ {
+ back.red = png_ptr->gamma_table[png_ptr->background.red];
+ back.green = png_ptr->gamma_table[png_ptr->background.green];
+ back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+ back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+ back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+ back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+ }
+ else
+ {
+ double g, gs;
+
+ switch (png_ptr->background_gamma_type)
+ {
+ case PNG_BACKGROUND_GAMMA_SCREEN:
+ g = (png_ptr->screen_gamma);
+ gs = 1.0;
+ break;
+
+ case PNG_BACKGROUND_GAMMA_FILE:
+ g = 1.0 / (png_ptr->gamma);
+ gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+ break;
+
+ case PNG_BACKGROUND_GAMMA_UNIQUE:
+ g = 1.0 / (png_ptr->background_gamma);
+ gs = 1.0 / (png_ptr->background_gamma *
+ png_ptr->screen_gamma);
+ break;
+ default:
+ g = 1.0; /* back_1 */
+ gs = 1.0; /* back */
+ }
+
+ if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
+ {
+ back.red = (png_byte)png_ptr->background.red;
+ back.green = (png_byte)png_ptr->background.green;
+ back.blue = (png_byte)png_ptr->background.blue;
+ }
+ else
+ {
+ back.red = (png_byte)(pow(
+ (double)png_ptr->background.red/255, gs) * 255.0 + .5);
+ back.green = (png_byte)(pow(
+ (double)png_ptr->background.green/255, gs) * 255.0
+ + .5);
+ back.blue = (png_byte)(pow(
+ (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
+ }
+
+ back_1.red = (png_byte)(pow(
+ (double)png_ptr->background.red/255, g) * 255.0 + .5);
+ back_1.green = (png_byte)(pow(
+ (double)png_ptr->background.green/255, g) * 255.0 + .5);
+ back_1.blue = (png_byte)(pow(
+ (double)png_ptr->background.blue/255, g) * 255.0 + .5);
+ }
+ for (i = 0; i < num_palette; i++)
+ {
+ if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+ {
+ if (png_ptr->trans[i] == 0)
+ {
+ palette[i] = back;
+ }
+ else /* if (png_ptr->trans[i] != 0xff) */
+ {
+ png_byte v, w;
+
+ v = png_ptr->gamma_to_1[palette[i].red];
+ png_composite(w, v, png_ptr->trans[i], back_1.red);
+ palette[i].red = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[palette[i].green];
+ png_composite(w, v, png_ptr->trans[i], back_1.green);
+ palette[i].green = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[palette[i].blue];
+ png_composite(w, v, png_ptr->trans[i], back_1.blue);
+ palette[i].blue = png_ptr->gamma_from_1[w];
+ }
+ }
+ else
+ {
+ palette[i].red = png_ptr->gamma_table[palette[i].red];
+ palette[i].green = png_ptr->gamma_table[palette[i].green];
+ palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+ }
+ }
+ /* Prevent the transformations being done again, and make sure
+ * that the now spurious alpha channel is stripped - the code
+ * has just reduced background composition and gamma correction
+ * to a simple alpha channel strip.
+ */
+ png_ptr->transformations &= ~PNG_BACKGROUND;
+ png_ptr->transformations &= ~PNG_GAMMA;
+ png_ptr->transformations |= PNG_STRIP_ALPHA;
+ }
+ /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
+ else
+ /* color_type != PNG_COLOR_TYPE_PALETTE */
+ {
+ double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
+ double g = 1.0;
+ double gs = 1.0;
+
+ switch (png_ptr->background_gamma_type)
+ {
+ case PNG_BACKGROUND_GAMMA_SCREEN:
+ g = (png_ptr->screen_gamma);
+ gs = 1.0;
+ break;
+
+ case PNG_BACKGROUND_GAMMA_FILE:
+ g = 1.0 / (png_ptr->gamma);
+ gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+ break;
+
+ case PNG_BACKGROUND_GAMMA_UNIQUE:
+ g = 1.0 / (png_ptr->background_gamma);
+ gs = 1.0 / (png_ptr->background_gamma *
+ png_ptr->screen_gamma);
+ break;
+ }
+
+ png_ptr->background_1.gray = (png_uint_16)(pow(
+ (double)png_ptr->background.gray / m, g) * m + .5);
+ png_ptr->background.gray = (png_uint_16)(pow(
+ (double)png_ptr->background.gray / m, gs) * m + .5);
+
+ if ((png_ptr->background.red != png_ptr->background.green) ||
+ (png_ptr->background.red != png_ptr->background.blue) ||
+ (png_ptr->background.red != png_ptr->background.gray))
+ {
+ /* RGB or RGBA with color background */
+ png_ptr->background_1.red = (png_uint_16)(pow(
+ (double)png_ptr->background.red / m, g) * m + .5);
+ png_ptr->background_1.green = (png_uint_16)(pow(
+ (double)png_ptr->background.green / m, g) * m + .5);
+ png_ptr->background_1.blue = (png_uint_16)(pow(
+ (double)png_ptr->background.blue / m, g) * m + .5);
+ png_ptr->background.red = (png_uint_16)(pow(
+ (double)png_ptr->background.red / m, gs) * m + .5);
+ png_ptr->background.green = (png_uint_16)(pow(
+ (double)png_ptr->background.green / m, gs) * m + .5);
+ png_ptr->background.blue = (png_uint_16)(pow(
+ (double)png_ptr->background.blue / m, gs) * m + .5);
+ }
+ else
+ {
+ /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
+ png_ptr->background_1.red = png_ptr->background_1.green
+ = png_ptr->background_1.blue = png_ptr->background_1.gray;
+ png_ptr->background.red = png_ptr->background.green
+ = png_ptr->background.blue = png_ptr->background.gray;
+ }
+ }
+ }
+ else
+ /* Transformation does not include PNG_BACKGROUND */
+#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_colorp palette = png_ptr->palette;
+ int num_palette = png_ptr->num_palette;
+ int i;
+
+ for (i = 0; i < num_palette; i++)
+ {
+ palette[i].red = png_ptr->gamma_table[palette[i].red];
+ palette[i].green = png_ptr->gamma_table[palette[i].green];
+ palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+ }
+
+ /* Done the gamma correction. */
+ png_ptr->transformations &= ~PNG_GAMMA;
+ }
+ }
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ else
+#endif
+#endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ /* No GAMMA transformation */
+ if ((png_ptr->transformations & PNG_BACKGROUND) &&
+ (color_type == PNG_COLOR_TYPE_PALETTE))
+ {
+ int i;
+ int istop = (int)png_ptr->num_trans;
+ png_color back;
+ png_colorp palette = png_ptr->palette;
+
+ back.red = (png_byte)png_ptr->background.red;
+ back.green = (png_byte)png_ptr->background.green;
+ back.blue = (png_byte)png_ptr->background.blue;
+
+ for (i = 0; i < istop; i++)
+ {
+ if (png_ptr->trans[i] == 0)
+ {
+ palette[i] = back;
+ }
+ else if (png_ptr->trans[i] != 0xff)
+ {
+ /* The png_composite() macro is defined in png.h */
+ png_composite(palette[i].red, palette[i].red,
+ png_ptr->trans[i], back.red);
+ png_composite(palette[i].green, palette[i].green,
+ png_ptr->trans[i], back.green);
+ png_composite(palette[i].blue, palette[i].blue,
+ png_ptr->trans[i], back.blue);
+ }
+ }
+
+ /* Handled alpha, still need to strip the channel. */
+ png_ptr->transformations &= ~PNG_BACKGROUND;
+ png_ptr->transformations |= PNG_STRIP_ALPHA;
+ }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) &&
+ !(png_ptr->transformations & PNG_EXPAND) &&
+ (color_type == PNG_COLOR_TYPE_PALETTE))
+ {
+ png_uint_16 i;
+ png_uint_16 istop = png_ptr->num_palette;
+ int sr = 8 - png_ptr->sig_bit.red;
+ int sg = 8 - png_ptr->sig_bit.green;
+ int sb = 8 - png_ptr->sig_bit.blue;
+
+ if (sr < 0 || sr > 8)
+ sr = 0;
+ if (sg < 0 || sg > 8)
+ sg = 0;
+ if (sb < 0 || sb > 8)
+ sb = 0;
+ for (i = 0; i < istop; i++)
+ {
+ png_ptr->palette[i].red >>= sr;
+ png_ptr->palette[i].green >>= sg;
+ png_ptr->palette[i].blue >>= sb;
+ }
+
+ png_ptr->transformations &= ~PNG_SHIFT;
+ }
+#endif /* PNG_READ_SHIFT_SUPPORTED */
+ }
+#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
+ && !defined(PNG_READ_BACKGROUND_SUPPORTED)
+ if (png_ptr)
+ return;
+#endif
+}
+
+/* Modify the info structure to reflect the transformations. The
+ * info should be updated so a PNG file could be written with it,
+ * assuming the transformations result in valid PNG data.
+ */
+void /* PRIVATE */
+png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_read_transform_info");
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if (png_ptr->transformations & PNG_EXPAND)
+ {
+ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (png_ptr->num_trans)
+ info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ else
+ info_ptr->color_type = PNG_COLOR_TYPE_RGB;
+ info_ptr->bit_depth = 8;
+ info_ptr->num_trans = 0;
+ }
+ else
+ {
+ if (png_ptr->num_trans)
+ {
+ if (png_ptr->transformations & PNG_EXPAND_tRNS)
+ info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+ }
+ if (info_ptr->bit_depth < 8)
+ info_ptr->bit_depth = 8;
+ info_ptr->num_trans = 0;
+ }
+ }
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ if (png_ptr->transformations & PNG_BACKGROUND)
+ {
+ info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+ info_ptr->num_trans = 0;
+ info_ptr->background = png_ptr->background;
+ }
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (png_ptr->transformations & PNG_GAMMA)
+ {
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ info_ptr->gamma = png_ptr->gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ info_ptr->int_gamma = png_ptr->int_gamma;
+#endif
+ }
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+ if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
+ info_ptr->bit_depth = 8;
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+ if (png_ptr->transformations & PNG_DITHER)
+ {
+ if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
+ png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+ {
+ info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
+ }
+ }
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+ info_ptr->bit_depth = 8;
+#endif
+
+ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ info_ptr->channels = 1;
+ else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ info_ptr->channels = 3;
+ else
+ info_ptr->channels = 1;
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
+ info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
+#endif
+
+ if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ info_ptr->channels++;
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ /* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
+ if ((png_ptr->transformations & PNG_FILLER) &&
+ ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
+ {
+ info_ptr->channels++;
+ /* If adding a true alpha channel not just filler */
+#ifndef PNG_1_0_X
+ if (png_ptr->transformations & PNG_ADD_ALPHA)
+ info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
+#endif
+ }
+#endif
+
+#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
+defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
+ if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ {
+ if (info_ptr->bit_depth < png_ptr->user_transform_depth)
+ info_ptr->bit_depth = png_ptr->user_transform_depth;
+ if (info_ptr->channels < png_ptr->user_transform_channels)
+ info_ptr->channels = png_ptr->user_transform_channels;
+ }
+#endif
+
+ info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
+ info_ptr->bit_depth);
+
+ info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
+
+#ifndef PNG_READ_EXPAND_SUPPORTED
+ if (png_ptr)
+ return;
+#endif
+}
+
+/* Transform the row. The order of transformations is significant,
+ * and is very touchy. If you add a transformation, take care to
+ * decide how it fits in with the other transformations here.
+ */
+void /* PRIVATE */
+png_do_read_transformations(png_structp png_ptr)
+{
+ png_debug(1, "in png_do_read_transformations");
+
+ if (png_ptr->row_buf == NULL)
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char msg[50];
+
+ png_snprintf2(msg, 50,
+ "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number,
+ png_ptr->pass);
+ png_error(png_ptr, msg);
+#else
+ png_error(png_ptr, "NULL row buffer");
+#endif
+ }
+#ifdef PNG_WARN_UNINITIALIZED_ROW
+ if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ /* Application has failed to call either png_read_start_image()
+ * or png_read_update_info() after setting transforms that expand
+ * pixels. This check added to libpng-1.2.19
+ */
+#if (PNG_WARN_UNINITIALIZED_ROW==1)
+ png_error(png_ptr, "Uninitialized row");
+#else
+ png_warning(png_ptr, "Uninitialized row");
+#endif
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if (png_ptr->transformations & PNG_EXPAND)
+ {
+ if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
+ }
+ else
+ {
+ if (png_ptr->num_trans &&
+ (png_ptr->transformations & PNG_EXPAND_tRNS))
+ png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ &(png_ptr->trans_values));
+ else
+ png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ NULL);
+ }
+ }
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
+ png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ {
+ int rgb_error =
+ png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info),
+ png_ptr->row_buf + 1);
+ if (rgb_error)
+ {
+ png_ptr->rgb_to_gray_status=1;
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_WARN)
+ png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_ERR)
+ png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
+ }
+ }
+#endif
+
+/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
+ *
+ * In most cases, the "simple transparency" should be done prior to doing
+ * gray-to-RGB, or you will have to test 3x as many bytes to check if a
+ * pixel is transparent. You would also need to make sure that the
+ * transparency information is upgraded to RGB.
+ *
+ * To summarize, the current flow is:
+ * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+ * with background "in place" if transparent,
+ * convert to RGB if necessary
+ * - Gray + alpha -> composite with gray background and remove alpha bytes,
+ * convert to RGB if necessary
+ *
+ * To support RGB backgrounds for gray images we need:
+ * - Gray + simple transparency -> convert to RGB + simple transparency,
+ * compare 3 or 6 bytes and composite with
+ * background "in place" if transparent
+ * (3x compare/pixel compared to doing
+ * composite with gray bkgrnd)
+ * - Gray + alpha -> convert to RGB + alpha, composite with background and
+ * remove alpha bytes (3x float
+ * operations/pixel compared with composite
+ * on gray background)
+ *
+ * Greg's change will do this. The reason it wasn't done before is for
+ * performance, as this increases the per-pixel operations. If we would check
+ * in advance if the background was gray or RGB, and position the gray-to-RGB
+ * transform appropriately, then it would save a lot of work/time.
+ */
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* If gray -> RGB, do so now only if background is non-gray; else do later
+ * for performance reasons
+ */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+ !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
+ png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ if ((png_ptr->transformations & PNG_BACKGROUND) &&
+ ((png_ptr->num_trans != 0 ) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
+ png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ &(png_ptr->trans_values), &(png_ptr->background)
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ , &(png_ptr->background_1),
+ png_ptr->gamma_table, png_ptr->gamma_from_1,
+ png_ptr->gamma_to_1, png_ptr->gamma_16_table,
+ png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
+ png_ptr->gamma_shift
+#endif
+);
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if ((png_ptr->transformations & PNG_GAMMA) &&
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ !((png_ptr->transformations & PNG_BACKGROUND) &&
+ ((png_ptr->num_trans != 0) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
+#endif
+ (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+ png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_ptr->gamma_table, png_ptr->gamma_16_table,
+ png_ptr->gamma_shift);
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+ if (png_ptr->transformations & PNG_16_TO_8)
+ png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+ if (png_ptr->transformations & PNG_DITHER)
+ {
+ png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_ptr->palette_lookup, png_ptr->dither_index);
+ if (png_ptr->row_info.rowbytes == (png_uint_32)0)
+ png_error(png_ptr, "png_do_dither returned rowbytes=0");
+ }
+#endif
+
+#ifdef PNG_READ_INVERT_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if (png_ptr->transformations & PNG_SHIFT)
+ png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if (png_ptr->transformations & PNG_PACK)
+ png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_BGR_SUPPORTED
+ if (png_ptr->transformations & PNG_BGR)
+ png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* If gray -> RGB, do so now only if we did not do so above */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
+ png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ if (png_ptr->transformations & PNG_FILLER)
+ png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_ALPHA)
+ png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+ if (png_ptr->transformations & PNG_SWAP_ALPHA)
+ png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_SWAP_BYTES)
+ png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ {
+ if (png_ptr->read_user_transform_fn != NULL)
+ (*(png_ptr->read_user_transform_fn)) /* User read transform function */
+ (png_ptr, /* png_ptr */
+ &(png_ptr->row_info), /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_uint_32 rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+ if (png_ptr->user_transform_depth)
+ png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
+ if (png_ptr->user_transform_channels)
+ png_ptr->row_info.channels = png_ptr->user_transform_channels;
+#endif
+ png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+ png_ptr->row_info.channels);
+ png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
+ png_ptr->row_info.width);
+ }
+#endif
+
+}
+
+#ifdef PNG_READ_PACK_SUPPORTED
+/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
+ * without changing the actual values. Thus, if you had a row with
+ * a bit depth of 1, you would end up with bytes that only contained
+ * the numbers 0 or 1. If you would rather they contain 0 and 255, use
+ * png_do_shift() after this.
+ */
+void /* PRIVATE */
+png_do_unpack(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_unpack");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
+#else
+ if (row_info->bit_depth < 8)
+#endif
+ {
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
+ png_bytep dp = row + (png_size_t)row_width - 1;
+ png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
+ for (i = 0; i < row_width; i++)
+ {
+ *dp = (png_byte)((*sp >> shift) & 0x01);
+ if (shift == 7)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift++;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 2:
+ {
+
+ png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
+ png_bytep dp = row + (png_size_t)row_width - 1;
+ png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+ for (i = 0; i < row_width; i++)
+ {
+ *dp = (png_byte)((*sp >> shift) & 0x03);
+ if (shift == 6)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift += 2;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 4:
+ {
+ png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
+ png_bytep dp = row + (png_size_t)row_width - 1;
+ png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
+ for (i = 0; i < row_width; i++)
+ {
+ *dp = (png_byte)((*sp >> shift) & 0x0f);
+ if (shift == 4)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift = 4;
+
+ dp--;
+ }
+ break;
+ }
+ }
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+ row_info->rowbytes = row_width * row_info->channels;
+ }
+}
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+/* Reverse the effects of png_do_shift. This routine merely shifts the
+ * pixels back to their significant bits values. Thus, if you have
+ * a row of bit depth 8, but only 5 are significant, this will shift
+ * the values back to 0 through 31.
+ */
+void /* PRIVATE */
+png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
+{
+ png_debug(1, "in png_do_unshift");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL && sig_bits != NULL &&
+#endif
+ row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+ {
+ int shift[4];
+ int channels = 0;
+ int c;
+ png_uint_16 value = 0;
+ png_uint_32 row_width = row_info->width;
+
+ if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ {
+ shift[channels++] = row_info->bit_depth - sig_bits->red;
+ shift[channels++] = row_info->bit_depth - sig_bits->green;
+ shift[channels++] = row_info->bit_depth - sig_bits->blue;
+ }
+ else
+ {
+ shift[channels++] = row_info->bit_depth - sig_bits->gray;
+ }
+ if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ shift[channels++] = row_info->bit_depth - sig_bits->alpha;
+ }
+
+ for (c = 0; c < channels; c++)
+ {
+ if (shift[c] <= 0)
+ shift[c] = 0;
+ else
+ value = 1;
+ }
+
+ if (!value)
+ return;
+
+ switch (row_info->bit_depth)
+ {
+ case 2:
+ {
+ png_bytep bp;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+
+ for (bp = row, i = 0; i < istop; i++)
+ {
+ *bp >>= 1;
+ *bp++ &= 0x55;
+ }
+ break;
+ }
+
+ case 4:
+ {
+ png_bytep bp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+ png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
+ (png_byte)((int)0xf >> shift[0]));
+
+ for (i = 0; i < istop; i++)
+ {
+ *bp >>= shift[0];
+ *bp++ &= mask;
+ }
+ break;
+ }
+
+ case 8:
+ {
+ png_bytep bp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_width * channels;
+
+ for (i = 0; i < istop; i++)
+ {
+ *bp++ >>= shift[i%channels];
+ }
+ break;
+ }
+
+ case 16:
+ {
+ png_bytep bp = row;
+ png_uint_32 i;
+ png_uint_32 istop = channels * row_width;
+
+ for (i = 0; i < istop; i++)
+ {
+ value = (png_uint_16)((*bp << 8) + *(bp + 1));
+ value >>= shift[i%channels];
+ *bp++ = (png_byte)(value >> 8);
+ *bp++ = (png_byte)(value & 0xff);
+ }
+ break;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_16_TO_8_SUPPORTED
+/* Chop rows of bit depth 16 down to 8 */
+void /* PRIVATE */
+png_do_chop(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_chop");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
+#else
+ if (row_info->bit_depth == 16)
+#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->width * row_info->channels;
+
+ for (i = 0; i<istop; i++, sp += 2, dp++)
+ {
+#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+ /* This does a more accurate scaling of the 16-bit color
+ * value, rather than a simple low-byte truncation.
+ *
+ * What the ideal calculation should be:
+ * *dp = (((((png_uint_32)(*sp) << 8) |
+ * (png_uint_32)(*(sp + 1))) * 255 + 127)
+ * / (png_uint_32)65535L;
+ *
+ * GRR: no, I think this is what it really should be:
+ * *dp = (((((png_uint_32)(*sp) << 8) |
+ * (png_uint_32)(*(sp + 1))) + 128L)
+ * / (png_uint_32)257L;
+ *
+ * GRR: here's the exact calculation with shifts:
+ * temp = (((png_uint_32)(*sp) << 8) |
+ * (png_uint_32)(*(sp + 1))) + 128L;
+ * *dp = (temp - (temp >> 8)) >> 8;
+ *
+ * Approximate calculation with shift/add instead of multiply/divide:
+ * *dp = ((((png_uint_32)(*sp) << 8) |
+ * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
+ *
+ * What we actually do to avoid extra shifting and conversion:
+ */
+
+ *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
+#else
+ /* Simply discard the low order byte */
+ *dp = *sp;
+#endif
+ }
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = (png_byte)(8 * row_info->channels);
+ row_info->rowbytes = row_info->width * row_info->channels;
+ }
+}
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+void /* PRIVATE */
+png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_read_swap_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ png_uint_32 row_width = row_info->width;
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ /* This converts from RGBA to ARGB */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_byte save;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ save = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = save;
+ }
+ }
+ /* This converts from RRGGBBAA to AARRGGBB */
+ else
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_byte save[2];
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ save[0] = *(--sp);
+ save[1] = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = save[0];
+ *(--dp) = save[1];
+ }
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ /* This converts from GA to AG */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_byte save;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ save = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = save;
+ }
+ }
+ /* This converts from GGAA to AAGG */
+ else
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_byte save[2];
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ save[0] = *(--sp);
+ save[1] = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = save[0];
+ *(--dp) = save[1];
+ }
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+void /* PRIVATE */
+png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_read_invert_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ png_uint_32 row_width = row_info->width;
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ /* This inverts the alpha channel in RGBA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = (png_byte)(255 - *(--sp));
+
+/* This does nothing:
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ We can replace it with:
+*/
+ sp-=3;
+ dp=sp;
+ }
+ }
+ /* This inverts the alpha channel in RRGGBBAA */
+ else
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = (png_byte)(255 - *(--sp));
+ *(--dp) = (png_byte)(255 - *(--sp));
+
+/* This does nothing:
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ We can replace it with:
+*/
+ sp-=6;
+ dp=sp;
+ }
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ /* This inverts the alpha channel in GA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = (png_byte)(255 - *(--sp));
+ *(--dp) = *(--sp);
+ }
+ }
+ /* This inverts the alpha channel in GGAA */
+ else
+ {
+ png_bytep sp = row + row_info->rowbytes;
+ png_bytep dp = sp;
+ png_uint_32 i;
+
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = (png_byte)(255 - *(--sp));
+ *(--dp) = (png_byte)(255 - *(--sp));
+/*
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+*/
+ sp-=2;
+ dp=sp;
+ }
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+/* Add filler channel if we have RGB color */
+void /* PRIVATE */
+png_do_read_filler(png_row_infop row_info, png_bytep row,
+ png_uint_32 filler, png_uint_32 flags)
+{
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+ png_byte lo_filler = (png_byte)(filler & 0xff);
+
+ png_debug(1, "in png_do_read_filler");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ row_info->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ /* This changes the data from G to GX */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ png_bytep sp = row + (png_size_t)row_width;
+ png_bytep dp = sp + (png_size_t)row_width;
+ for (i = 1; i < row_width; i++)
+ {
+ *(--dp) = lo_filler;
+ *(--dp) = *(--sp);
+ }
+ *(--dp) = lo_filler;
+ row_info->channels = 2;
+ row_info->pixel_depth = 16;
+ row_info->rowbytes = row_width * 2;
+ }
+ /* This changes the data from G to XG */
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width;
+ png_bytep dp = sp + (png_size_t)row_width;
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = *(--sp);
+ *(--dp) = lo_filler;
+ }
+ row_info->channels = 2;
+ row_info->pixel_depth = 16;
+ row_info->rowbytes = row_width * 2;
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ /* This changes the data from GG to GGXX */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ png_bytep sp = row + (png_size_t)row_width * 2;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 1; i < row_width; i++)
+ {
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ }
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ row_info->channels = 2;
+ row_info->pixel_depth = 32;
+ row_info->rowbytes = row_width * 4;
+ }
+ /* This changes the data from GG to XXGG */
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width * 2;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ }
+ row_info->channels = 2;
+ row_info->pixel_depth = 32;
+ row_info->rowbytes = row_width * 4;
+ }
+ }
+ } /* COLOR_TYPE == GRAY */
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ /* This changes the data from RGB to RGBX */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ png_bytep sp = row + (png_size_t)row_width * 3;
+ png_bytep dp = sp + (png_size_t)row_width;
+ for (i = 1; i < row_width; i++)
+ {
+ *(--dp) = lo_filler;
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ }
+ *(--dp) = lo_filler;
+ row_info->channels = 4;
+ row_info->pixel_depth = 32;
+ row_info->rowbytes = row_width * 4;
+ }
+ /* This changes the data from RGB to XRGB */
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width * 3;
+ png_bytep dp = sp + (png_size_t)row_width;
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = lo_filler;
+ }
+ row_info->channels = 4;
+ row_info->pixel_depth = 32;
+ row_info->rowbytes = row_width * 4;
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ /* This changes the data from RRGGBB to RRGGBBXX */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ png_bytep sp = row + (png_size_t)row_width * 6;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 1; i < row_width; i++)
+ {
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ }
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ row_info->channels = 4;
+ row_info->pixel_depth = 64;
+ row_info->rowbytes = row_width * 8;
+ }
+ /* This changes the data from RRGGBB to XXRRGGBB */
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width * 6;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 0; i < row_width; i++)
+ {
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = *(--sp);
+ *(--dp) = hi_filler;
+ *(--dp) = lo_filler;
+ }
+ row_info->channels = 4;
+ row_info->pixel_depth = 64;
+ row_info->rowbytes = row_width * 8;
+ }
+ }
+ } /* COLOR_TYPE == RGB */
+}
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+/* Expand grayscale files to RGB, with or without alpha */
+void /* PRIVATE */
+png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
+{
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ png_debug(1, "in png_do_gray_to_rgb");
+
+ if (row_info->bit_depth >= 8 &&
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + (png_size_t)row_width - 1;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 0; i < row_width; i++)
+ {
+ *(dp--) = *sp;
+ *(dp--) = *sp;
+ *(dp--) = *(sp--);
+ }
+ }
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+ png_bytep dp = sp + (png_size_t)row_width * 4;
+ for (i = 0; i < row_width; i++)
+ {
+ *(dp--) = *sp;
+ *(dp--) = *(sp - 1);
+ *(dp--) = *sp;
+ *(dp--) = *(sp - 1);
+ *(dp--) = *(sp--);
+ *(dp--) = *(sp--);
+ }
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp = row + (png_size_t)row_width * 2 - 1;
+ png_bytep dp = sp + (png_size_t)row_width * 2;
+ for (i = 0; i < row_width; i++)
+ {
+ *(dp--) = *(sp--);
+ *(dp--) = *sp;
+ *(dp--) = *sp;
+ *(dp--) = *(sp--);
+ }
+ }
+ else
+ {
+ png_bytep sp = row + (png_size_t)row_width * 4 - 1;
+ png_bytep dp = sp + (png_size_t)row_width * 4;
+ for (i = 0; i < row_width; i++)
+ {
+ *(dp--) = *(sp--);
+ *(dp--) = *(sp--);
+ *(dp--) = *sp;
+ *(dp--) = *(sp - 1);
+ *(dp--) = *sp;
+ *(dp--) = *(sp - 1);
+ *(dp--) = *(sp--);
+ *(dp--) = *(sp--);
+ }
+ }
+ }
+ row_info->channels += (png_byte)2;
+ row_info->color_type |= PNG_COLOR_MASK_COLOR;
+ row_info->pixel_depth = (png_byte)(row_info->channels *
+ row_info->bit_depth);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+}
+#endif
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+/* Reduce RGB files to grayscale, with or without alpha
+ * using the equation given in Poynton's ColorFAQ at
+ * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008)
+ * New link:
+ * <http://www.poynton.com/notes/colour_and_gamma/>
+ * Charles Poynton poynton at poynton.com
+ *
+ * Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
+ *
+ * We approximate this with
+ *
+ * Y = 0.21268 * R + 0.7151 * G + 0.07217 * B
+ *
+ * which can be expressed with integers as
+ *
+ * Y = (6969 * R + 23434 * G + 2365 * B)/32768
+ *
+ * The calculation is to be done in a linear colorspace.
+ *
+ * Other integer coefficents can be used via png_set_rgb_to_gray().
+ */
+int /* PRIVATE */
+png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+
+{
+ png_uint_32 i;
+
+ png_uint_32 row_width = row_info->width;
+ int rgb_error = 0;
+
+ png_debug(1, "in png_do_rgb_to_gray");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ {
+ png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ if (row_info->bit_depth == 8)
+ {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte red = png_ptr->gamma_to_1[*(sp++)];
+ png_byte green = png_ptr->gamma_to_1[*(sp++)];
+ png_byte blue = png_ptr->gamma_to_1[*(sp++)];
+ if (red != green || red != blue)
+ {
+ rgb_error |= 1;
+ *(dp++) = png_ptr->gamma_from_1[
+ (rc*red + gc*green + bc*blue)>>15];
+ }
+ else
+ *(dp++) = *(sp - 1);
+ }
+ }
+ else
+#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte red = *(sp++);
+ png_byte green = *(sp++);
+ png_byte blue = *(sp++);
+ if (red != green || red != blue)
+ {
+ rgb_error |= 1;
+ *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
+ }
+ else
+ *(dp++) = *(sp - 1);
+ }
+ }
+ }
+
+ else /* RGB bit_depth == 16 */
+ {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ if (png_ptr->gamma_16_to_1 != NULL &&
+ png_ptr->gamma_16_from_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 red, green, blue, w;
+
+ red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+ if (red == green && red == blue)
+ w = red;
+ else
+ {
+ png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
+ png_ptr->gamma_shift][red>>8];
+ png_uint_16 green_1 =
+ png_ptr->gamma_16_to_1[(green&0xff) >>
+ png_ptr->gamma_shift][green>>8];
+ png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
+ png_ptr->gamma_shift][blue>>8];
+ png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
+ + bc*blue_1)>>15);
+ w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ png_ptr->gamma_shift][gray16 >> 8];
+ rgb_error |= 1;
+ }
+
+ *(dp++) = (png_byte)((w>>8) & 0xff);
+ *(dp++) = (png_byte)(w & 0xff);
+ }
+ }
+ else
+#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 red, green, blue, gray16;
+
+ red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+ if (red != green || red != blue)
+ rgb_error |= 1;
+ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+ *(dp++) = (png_byte)((gray16>>8) & 0xff);
+ *(dp++) = (png_byte)(gray16 & 0xff);
+ }
+ }
+ }
+ }
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ if (row_info->bit_depth == 8)
+ {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte red = png_ptr->gamma_to_1[*(sp++)];
+ png_byte green = png_ptr->gamma_to_1[*(sp++)];
+ png_byte blue = png_ptr->gamma_to_1[*(sp++)];
+ if (red != green || red != blue)
+ rgb_error |= 1;
+ *(dp++) = png_ptr->gamma_from_1
+ [(rc*red + gc*green + bc*blue)>>15];
+ *(dp++) = *(sp++); /* alpha */
+ }
+ }
+ else
+#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte red = *(sp++);
+ png_byte green = *(sp++);
+ png_byte blue = *(sp++);
+ if (red != green || red != blue)
+ rgb_error |= 1;
+ *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
+ *(dp++) = *(sp++); /* alpha */
+ }
+ }
+ }
+ else /* RGBA bit_depth == 16 */
+ {
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+ if (png_ptr->gamma_16_to_1 != NULL &&
+ png_ptr->gamma_16_from_1 != NULL)
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 red, green, blue, w;
+
+ red = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+ blue = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
+
+ if (red == green && red == blue)
+ w = red;
+ else
+ {
+ png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) >>
+ png_ptr->gamma_shift][red>>8];
+ png_uint_16 green_1 =
+ png_ptr->gamma_16_to_1[(green&0xff) >>
+ png_ptr->gamma_shift][green>>8];
+ png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) >>
+ png_ptr->gamma_shift][blue>>8];
+ png_uint_16 gray16 = (png_uint_16)((rc * red_1
+ + gc * green_1 + bc * blue_1)>>15);
+ w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ png_ptr->gamma_shift][gray16 >> 8];
+ rgb_error |= 1;
+ }
+
+ *(dp++) = (png_byte)((w>>8) & 0xff);
+ *(dp++) = (png_byte)(w & 0xff);
+ *(dp++) = *(sp++); /* alpha */
+ *(dp++) = *(sp++);
+ }
+ }
+ else
+#endif
+ {
+ png_bytep sp = row;
+ png_bytep dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 red, green, blue, gray16;
+ red = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+ green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+ blue = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
+ if (red != green || red != blue)
+ rgb_error |= 1;
+ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
+ *(dp++) = (png_byte)((gray16>>8) & 0xff);
+ *(dp++) = (png_byte)(gray16 & 0xff);
+ *(dp++) = *(sp++); /* alpha */
+ *(dp++) = *(sp++);
+ }
+ }
+ }
+ }
+ row_info->channels -= (png_byte)2;
+ row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
+ row_info->pixel_depth = (png_byte)(row_info->channels *
+ row_info->bit_depth);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+ return rgb_error;
+}
+#endif
+
+/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
+ * large of png_color. This lets grayscale images be treated as
+ * paletted. Most useful for gamma correction and simplification
+ * of code.
+ */
+void PNGAPI
+png_build_grayscale_palette(int bit_depth, png_colorp palette)
+{
+ int num_palette;
+ int color_inc;
+ int i;
+ int v;
+
+ png_debug(1, "in png_do_build_grayscale_palette");
+
+ if (palette == NULL)
+ return;
+
+ switch (bit_depth)
+ {
+ case 1:
+ num_palette = 2;
+ color_inc = 0xff;
+ break;
+
+ case 2:
+ num_palette = 4;
+ color_inc = 0x55;
+ break;
+
+ case 4:
+ num_palette = 16;
+ color_inc = 0x11;
+ break;
+
+ case 8:
+ num_palette = 256;
+ color_inc = 1;
+ break;
+
+ default:
+ num_palette = 0;
+ color_inc = 0;
+ break;
+ }
+
+ for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+ {
+ palette[i].red = (png_byte)v;
+ palette[i].green = (png_byte)v;
+ palette[i].blue = (png_byte)v;
+ }
+}
+
+/* This function is currently unused. Do we really need it? */
+#if defined(PNG_READ_DITHER_SUPPORTED) && \
+ defined(PNG_CORRECT_PALETTE_SUPPORTED)
+void /* PRIVATE */
+png_correct_palette(png_structp png_ptr, png_colorp palette,
+ int num_palette)
+{
+ png_debug(1, "in png_correct_palette");
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
+ defined(PNG_READ_GAMMA_SUPPORTED) && \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
+ if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
+ {
+ png_color back, back_1;
+
+ if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
+ {
+ back.red = png_ptr->gamma_table[png_ptr->background.red];
+ back.green = png_ptr->gamma_table[png_ptr->background.green];
+ back.blue = png_ptr->gamma_table[png_ptr->background.blue];
+
+ back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
+ back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
+ back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
+ }
+ else
+ {
+ double g;
+
+ g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
+
+ if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN
+ || fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
+ {
+ back.red = png_ptr->background.red;
+ back.green = png_ptr->background.green;
+ back.blue = png_ptr->background.blue;
+ }
+ else
+ {
+ back.red =
+ (png_byte)(pow((double)png_ptr->background.red/255, g) *
+ 255.0 + 0.5);
+ back.green =
+ (png_byte)(pow((double)png_ptr->background.green/255, g) *
+ 255.0 + 0.5);
+ back.blue =
+ (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+ 255.0 + 0.5);
+ }
+
+ g = 1.0 / png_ptr->background_gamma;
+
+ back_1.red =
+ (png_byte)(pow((double)png_ptr->background.red/255, g) *
+ 255.0 + 0.5);
+ back_1.green =
+ (png_byte)(pow((double)png_ptr->background.green/255, g) *
+ 255.0 + 0.5);
+ back_1.blue =
+ (png_byte)(pow((double)png_ptr->background.blue/255, g) *
+ 255.0 + 0.5);
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_uint_32 i;
+
+ for (i = 0; i < (png_uint_32)num_palette; i++)
+ {
+ if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
+ {
+ palette[i] = back;
+ }
+ else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
+ {
+ png_byte v, w;
+
+ v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
+ png_composite(w, v, png_ptr->trans[i], back_1.red);
+ palette[i].red = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
+ png_composite(w, v, png_ptr->trans[i], back_1.green);
+ palette[i].green = png_ptr->gamma_from_1[w];
+
+ v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
+ png_composite(w, v, png_ptr->trans[i], back_1.blue);
+ palette[i].blue = png_ptr->gamma_from_1[w];
+ }
+ else
+ {
+ palette[i].red = png_ptr->gamma_table[palette[i].red];
+ palette[i].green = png_ptr->gamma_table[palette[i].green];
+ palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+ }
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < num_palette; i++)
+ {
+ if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
+ {
+ palette[i] = back;
+ }
+ else
+ {
+ palette[i].red = png_ptr->gamma_table[palette[i].red];
+ palette[i].green = png_ptr->gamma_table[palette[i].green];
+ palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+ }
+ }
+ }
+ }
+ else
+#endif
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (png_ptr->transformations & PNG_GAMMA)
+ {
+ int i;
+
+ for (i = 0; i < num_palette; i++)
+ {
+ palette[i].red = png_ptr->gamma_table[palette[i].red];
+ palette[i].green = png_ptr->gamma_table[palette[i].green];
+ palette[i].blue = png_ptr->gamma_table[palette[i].blue];
+ }
+ }
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ else
+#endif
+#endif
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+ if (png_ptr->transformations & PNG_BACKGROUND)
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_color back;
+
+ back.red = (png_byte)png_ptr->background.red;
+ back.green = (png_byte)png_ptr->background.green;
+ back.blue = (png_byte)png_ptr->background.blue;
+
+ for (i = 0; i < (int)png_ptr->num_trans; i++)
+ {
+ if (png_ptr->trans[i] == 0)
+ {
+ palette[i].red = back.red;
+ palette[i].green = back.green;
+ palette[i].blue = back.blue;
+ }
+ else if (png_ptr->trans[i] != 0xff)
+ {
+ png_composite(palette[i].red, png_ptr->palette[i].red,
+ png_ptr->trans[i], back.red);
+ png_composite(palette[i].green, png_ptr->palette[i].green,
+ png_ptr->trans[i], back.green);
+ png_composite(palette[i].blue, png_ptr->palette[i].blue,
+ png_ptr->trans[i], back.blue);
+ }
+ }
+ }
+ else /* Assume grayscale palette (what else could it be?) */
+ {
+ int i;
+
+ for (i = 0; i < num_palette; i++)
+ {
+ if (i == (png_byte)png_ptr->trans_values.gray)
+ {
+ palette[i].red = (png_byte)png_ptr->background.red;
+ palette[i].green = (png_byte)png_ptr->background.green;
+ palette[i].blue = (png_byte)png_ptr->background.blue;
+ }
+ }
+ }
+ }
+#endif
+}
+#endif
+
+#ifdef PNG_READ_BACKGROUND_SUPPORTED
+/* Replace any alpha or transparency with the supplied background color.
+ * "background" is already in the screen gamma, while "background_1" is
+ * at a gamma of 1.0. Paletted files have already been taken care of.
+ */
+void /* PRIVATE */
+png_do_background(png_row_infop row_info, png_bytep row,
+ png_color_16p trans_values, png_color_16p background
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ , png_color_16p background_1,
+ png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
+ png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
+ png_uint_16pp gamma_16_to_1, int gamma_shift
+#endif
+ )
+{
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+ int shift;
+
+ png_debug(1, "in png_do_background");
+
+ if (background != NULL &&
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
+ (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
+ {
+ switch (row_info->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ {
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ sp = row;
+ shift = 7;
+ for (i = 0; i < row_width; i++)
+ {
+ if ((png_uint_16)((*sp >> shift) & 0x01)
+ == trans_values->gray)
+ {
+ *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+ *sp |= (png_byte)(background->gray << shift);
+ }
+ if (!shift)
+ {
+ shift = 7;
+ sp++;
+ }
+ else
+ shift--;
+ }
+ break;
+ }
+
+ case 2:
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_table != NULL)
+ {
+ sp = row;
+ shift = 6;
+ for (i = 0; i < row_width; i++)
+ {
+ if ((png_uint_16)((*sp >> shift) & 0x03)
+ == trans_values->gray)
+ {
+ *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+ *sp |= (png_byte)(background->gray << shift);
+ }
+ else
+ {
+ png_byte p = (png_byte)((*sp >> shift) & 0x03);
+ png_byte g = (png_byte)((gamma_table [p | (p << 2) |
+ (p << 4) | (p << 6)] >> 6) & 0x03);
+ *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+ *sp |= (png_byte)(g << shift);
+ }
+ if (!shift)
+ {
+ shift = 6;
+ sp++;
+ }
+ else
+ shift -= 2;
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ shift = 6;
+ for (i = 0; i < row_width; i++)
+ {
+ if ((png_uint_16)((*sp >> shift) & 0x03)
+ == trans_values->gray)
+ {
+ *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+ *sp |= (png_byte)(background->gray << shift);
+ }
+ if (!shift)
+ {
+ shift = 6;
+ sp++;
+ }
+ else
+ shift -= 2;
+ }
+ }
+ break;
+ }
+
+ case 4:
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_table != NULL)
+ {
+ sp = row;
+ shift = 4;
+ for (i = 0; i < row_width; i++)
+ {
+ if ((png_uint_16)((*sp >> shift) & 0x0f)
+ == trans_values->gray)
+ {
+ *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+ *sp |= (png_byte)(background->gray << shift);
+ }
+ else
+ {
+ png_byte p = (png_byte)((*sp >> shift) & 0x0f);
+ png_byte g = (png_byte)((gamma_table[p |
+ (p << 4)] >> 4) & 0x0f);
+ *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+ *sp |= (png_byte)(g << shift);
+ }
+ if (!shift)
+ {
+ shift = 4;
+ sp++;
+ }
+ else
+ shift -= 4;
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ shift = 4;
+ for (i = 0; i < row_width; i++)
+ {
+ if ((png_uint_16)((*sp >> shift) & 0x0f)
+ == trans_values->gray)
+ {
+ *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+ *sp |= (png_byte)(background->gray << shift);
+ }
+ if (!shift)
+ {
+ shift = 4;
+ sp++;
+ }
+ else
+ shift -= 4;
+ }
+ }
+ break;
+ }
+
+ case 8:
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_table != NULL)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp++)
+ {
+ if (*sp == trans_values->gray)
+ {
+ *sp = (png_byte)background->gray;
+ }
+ else
+ {
+ *sp = gamma_table[*sp];
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp++)
+ {
+ if (*sp == trans_values->gray)
+ {
+ *sp = (png_byte)background->gray;
+ }
+ }
+ }
+ break;
+ }
+
+ case 16:
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_16 != NULL)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 2)
+ {
+ png_uint_16 v;
+
+ v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+ if (v == trans_values->gray)
+ {
+ /* Background is already in screen gamma */
+ *sp = (png_byte)((background->gray >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(background->gray & 0xff);
+ }
+ else
+ {
+ v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 2)
+ {
+ png_uint_16 v;
+
+ v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+ if (v == trans_values->gray)
+ {
+ *sp = (png_byte)((background->gray >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(background->gray & 0xff);
+ }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_RGB:
+ {
+ if (row_info->bit_depth == 8)
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_table != NULL)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 3)
+ {
+ if (*sp == trans_values->red &&
+ *(sp + 1) == trans_values->green &&
+ *(sp + 2) == trans_values->blue)
+ {
+ *sp = (png_byte)background->red;
+ *(sp + 1) = (png_byte)background->green;
+ *(sp + 2) = (png_byte)background->blue;
+ }
+ else
+ {
+ *sp = gamma_table[*sp];
+ *(sp + 1) = gamma_table[*(sp + 1)];
+ *(sp + 2) = gamma_table[*(sp + 2)];
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 3)
+ {
+ if (*sp == trans_values->red &&
+ *(sp + 1) == trans_values->green &&
+ *(sp + 2) == trans_values->blue)
+ {
+ *sp = (png_byte)background->red;
+ *(sp + 1) = (png_byte)background->green;
+ *(sp + 2) = (png_byte)background->blue;
+ }
+ }
+ }
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_16 != NULL)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 6)
+ {
+ png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+ png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+ png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+ if (r == trans_values->red && g == trans_values->green &&
+ b == trans_values->blue)
+ {
+ /* Background is already in screen gamma */
+ *sp = (png_byte)((background->red >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(background->red & 0xff);
+ *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+ *(sp + 3) = (png_byte)(background->green & 0xff);
+ *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+ *(sp + 5) = (png_byte)(background->blue & 0xff);
+ }
+ else
+ {
+ png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+ *(sp + 2) = (png_byte)((v >> 8) & 0xff);
+ *(sp + 3) = (png_byte)(v & 0xff);
+ v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+ *(sp + 4) = (png_byte)((v >> 8) & 0xff);
+ *(sp + 5) = (png_byte)(v & 0xff);
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp += 6)
+ {
+ png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
+ png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+ png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
+
+ if (r == trans_values->red && g == trans_values->green &&
+ b == trans_values->blue)
+ {
+ *sp = (png_byte)((background->red >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(background->red & 0xff);
+ *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
+ *(sp + 3) = (png_byte)(background->green & 0xff);
+ *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+ *(sp + 5) = (png_byte)(background->blue & 0xff);
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ {
+ if (row_info->bit_depth == 8)
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+ gamma_table != NULL)
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 2, dp++)
+ {
+ png_uint_16 a = *(sp + 1);
+
+ if (a == 0xff)
+ {
+ *dp = gamma_table[*sp];
+ }
+ else if (a == 0)
+ {
+ /* Background is already in screen gamma */
+ *dp = (png_byte)background->gray;
+ }
+ else
+ {
+ png_byte v, w;
+
+ v = gamma_to_1[*sp];
+ png_composite(w, v, a, background_1->gray);
+ *dp = gamma_from_1[w];
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 2, dp++)
+ {
+ png_byte a = *(sp + 1);
+
+ if (a == 0xff)
+ {
+ *dp = *sp;
+ }
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ else if (a == 0)
+ {
+ *dp = (png_byte)background->gray;
+ }
+ else
+ {
+ png_composite(*dp, *sp, a, background_1->gray);
+ }
+#else
+ *dp = (png_byte)background->gray;
+#endif
+ }
+ }
+ }
+ else /* if (png_ptr->bit_depth == 16) */
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+ gamma_16_to_1 != NULL)
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+ {
+ png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+
+ if (a == (png_uint_16)0xffff)
+ {
+ png_uint_16 v;
+
+ v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+ *dp = (png_byte)((v >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(v & 0xff);
+ }
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ else if (a == 0)
+#else
+ else
+#endif
+ {
+ /* Background is already in screen gamma */
+ *dp = (png_byte)((background->gray >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(background->gray & 0xff);
+ }
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ else
+ {
+ png_uint_16 g, v, w;
+
+ g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+ png_composite_16(v, g, a, background_1->gray);
+ w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
+ *dp = (png_byte)((w >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(w & 0xff);
+ }
+#endif
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 4, dp += 2)
+ {
+ png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
+ if (a == (png_uint_16)0xffff)
+ {
+ png_memcpy(dp, sp, 2);
+ }
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ else if (a == 0)
+#else
+ else
+#endif
+ {
+ *dp = (png_byte)((background->gray >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(background->gray & 0xff);
+ }
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ else
+ {
+ png_uint_16 g, v;
+
+ g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+ png_composite_16(v, g, a, background_1->gray);
+ *dp = (png_byte)((v >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(v & 0xff);
+ }
+#endif
+ }
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ {
+ if (row_info->bit_depth == 8)
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
+ gamma_table != NULL)
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+ {
+ png_byte a = *(sp + 3);
+
+ if (a == 0xff)
+ {
+ *dp = gamma_table[*sp];
+ *(dp + 1) = gamma_table[*(sp + 1)];
+ *(dp + 2) = gamma_table[*(sp + 2)];
+ }
+ else if (a == 0)
+ {
+ /* Background is already in screen gamma */
+ *dp = (png_byte)background->red;
+ *(dp + 1) = (png_byte)background->green;
+ *(dp + 2) = (png_byte)background->blue;
+ }
+ else
+ {
+ png_byte v, w;
+
+ v = gamma_to_1[*sp];
+ png_composite(w, v, a, background_1->red);
+ *dp = gamma_from_1[w];
+ v = gamma_to_1[*(sp + 1)];
+ png_composite(w, v, a, background_1->green);
+ *(dp + 1) = gamma_from_1[w];
+ v = gamma_to_1[*(sp + 2)];
+ png_composite(w, v, a, background_1->blue);
+ *(dp + 2) = gamma_from_1[w];
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 4, dp += 3)
+ {
+ png_byte a = *(sp + 3);
+
+ if (a == 0xff)
+ {
+ *dp = *sp;
+ *(dp + 1) = *(sp + 1);
+ *(dp + 2) = *(sp + 2);
+ }
+ else if (a == 0)
+ {
+ *dp = (png_byte)background->red;
+ *(dp + 1) = (png_byte)background->green;
+ *(dp + 2) = (png_byte)background->blue;
+ }
+ else
+ {
+ png_composite(*dp, *sp, a, background->red);
+ png_composite(*(dp + 1), *(sp + 1), a,
+ background->green);
+ png_composite(*(dp + 2), *(sp + 2), a,
+ background->blue);
+ }
+ }
+ }
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
+ gamma_16_to_1 != NULL)
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+ {
+ png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+ << 8) + (png_uint_16)(*(sp + 7)));
+ if (a == (png_uint_16)0xffff)
+ {
+ png_uint_16 v;
+
+ v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
+ *dp = (png_byte)((v >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(v & 0xff);
+ v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
+ *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+ *(dp + 3) = (png_byte)(v & 0xff);
+ v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
+ *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+ *(dp + 5) = (png_byte)(v & 0xff);
+ }
+ else if (a == 0)
+ {
+ /* Background is already in screen gamma */
+ *dp = (png_byte)((background->red >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(background->red & 0xff);
+ *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+ *(dp + 3) = (png_byte)(background->green & 0xff);
+ *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+ *(dp + 5) = (png_byte)(background->blue & 0xff);
+ }
+ else
+ {
+ png_uint_16 v, w, x;
+
+ v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
+ png_composite_16(w, v, a, background_1->red);
+ x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ *dp = (png_byte)((x >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(x & 0xff);
+ v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
+ png_composite_16(w, v, a, background_1->green);
+ x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ *(dp + 2) = (png_byte)((x >> 8) & 0xff);
+ *(dp + 3) = (png_byte)(x & 0xff);
+ v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
+ png_composite_16(w, v, a, background_1->blue);
+ x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
+ *(dp + 4) = (png_byte)((x >> 8) & 0xff);
+ *(dp + 5) = (png_byte)(x & 0xff);
+ }
+ }
+ }
+ else
+#endif
+ {
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++, sp += 8, dp += 6)
+ {
+ png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
+ << 8) + (png_uint_16)(*(sp + 7)));
+ if (a == (png_uint_16)0xffff)
+ {
+ png_memcpy(dp, sp, 6);
+ }
+ else if (a == 0)
+ {
+ *dp = (png_byte)((background->red >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(background->red & 0xff);
+ *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
+ *(dp + 3) = (png_byte)(background->green & 0xff);
+ *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
+ *(dp + 5) = (png_byte)(background->blue & 0xff);
+ }
+ else
+ {
+ png_uint_16 v;
+
+ png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
+ png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
+ + *(sp + 3));
+ png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
+ + *(sp + 5));
+
+ png_composite_16(v, r, a, background->red);
+ *dp = (png_byte)((v >> 8) & 0xff);
+ *(dp + 1) = (png_byte)(v & 0xff);
+ png_composite_16(v, g, a, background->green);
+ *(dp + 2) = (png_byte)((v >> 8) & 0xff);
+ *(dp + 3) = (png_byte)(v & 0xff);
+ png_composite_16(v, b, a, background->blue);
+ *(dp + 4) = (png_byte)((v >> 8) & 0xff);
+ *(dp + 5) = (png_byte)(v & 0xff);
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+
+ if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+ row_info->channels--;
+ row_info->pixel_depth = (png_byte)(row_info->channels *
+ row_info->bit_depth);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+/* Gamma correct the image, avoiding the alpha channel. Make sure
+ * you do this after you deal with the transparency issue on grayscale
+ * or RGB images. If your bit depth is 8, use gamma_table, if it
+ * is 16, use gamma_16_table and gamma_shift. Build these with
+ * build_gamma_table().
+ */
+void /* PRIVATE */
+png_do_gamma(png_row_infop row_info, png_bytep row,
+ png_bytep gamma_table, png_uint_16pp gamma_16_table,
+ int gamma_shift)
+{
+ png_bytep sp;
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+
+ png_debug(1, "in png_do_gamma");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
+ (row_info->bit_depth == 16 && gamma_16_table != NULL)))
+ {
+ switch (row_info->color_type)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ {
+ if (row_info->bit_depth == 8)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ *sp = gamma_table[*sp];
+ sp++;
+ *sp = gamma_table[*sp];
+ sp++;
+ *sp = gamma_table[*sp];
+ sp++;
+ }
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 v;
+
+ v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ {
+ if (row_info->bit_depth == 8)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ *sp = gamma_table[*sp];
+ sp++;
+ *sp = gamma_table[*sp];
+ sp++;
+ *sp = gamma_table[*sp];
+ sp++;
+ sp++;
+ }
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 4;
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ {
+ if (row_info->bit_depth == 8)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ *sp = gamma_table[*sp];
+ sp += 2;
+ }
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 4;
+ }
+ }
+ break;
+ }
+
+ case PNG_COLOR_TYPE_GRAY:
+ {
+ if (row_info->bit_depth == 2)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i += 4)
+ {
+ int a = *sp & 0xc0;
+ int b = *sp & 0x30;
+ int c = *sp & 0x0c;
+ int d = *sp & 0x03;
+
+ *sp = (png_byte)(
+ ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)|
+ ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
+ ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
+ ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
+ sp++;
+ }
+ }
+
+ if (row_info->bit_depth == 4)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i += 2)
+ {
+ int msb = *sp & 0xf0;
+ int lsb = *sp & 0x0f;
+
+ *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
+ | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
+ sp++;
+ }
+ }
+
+ else if (row_info->bit_depth == 8)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ *sp = gamma_table[*sp];
+ sp++;
+ }
+ }
+
+ else if (row_info->bit_depth == 16)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
+ *sp = (png_byte)((v >> 8) & 0xff);
+ *(sp + 1) = (png_byte)(v & 0xff);
+ sp += 2;
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+/* Expands a palette row to an RGB or RGBA row depending
+ * upon whether you supply trans and num_trans.
+ */
+void /* PRIVATE */
+png_do_expand_palette(png_row_infop row_info, png_bytep row,
+ png_colorp palette, png_bytep trans, int num_trans)
+{
+ int shift, value;
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+
+ png_debug(1, "in png_do_expand_palette");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ row_info->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (row_info->bit_depth < 8)
+ {
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ sp = row + (png_size_t)((row_width - 1) >> 3);
+ dp = row + (png_size_t)row_width - 1;
+ shift = 7 - (int)((row_width + 7) & 0x07);
+ for (i = 0; i < row_width; i++)
+ {
+ if ((*sp >> shift) & 0x01)
+ *dp = 1;
+ else
+ *dp = 0;
+ if (shift == 7)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift++;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 2:
+ {
+ sp = row + (png_size_t)((row_width - 1) >> 2);
+ dp = row + (png_size_t)row_width - 1;
+ shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+ for (i = 0; i < row_width; i++)
+ {
+ value = (*sp >> shift) & 0x03;
+ *dp = (png_byte)value;
+ if (shift == 6)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift += 2;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 4:
+ {
+ sp = row + (png_size_t)((row_width - 1) >> 1);
+ dp = row + (png_size_t)row_width - 1;
+ shift = (int)((row_width & 0x01) << 2);
+ for (i = 0; i < row_width; i++)
+ {
+ value = (*sp >> shift) & 0x0f;
+ *dp = (png_byte)value;
+ if (shift == 4)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift += 4;
+
+ dp--;
+ }
+ break;
+ }
+ }
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = 8;
+ row_info->rowbytes = row_width;
+ }
+ switch (row_info->bit_depth)
+ {
+ case 8:
+ {
+ if (trans != NULL)
+ {
+ sp = row + (png_size_t)row_width - 1;
+ dp = row + (png_size_t)(row_width << 2) - 1;
+
+ for (i = 0; i < row_width; i++)
+ {
+ if ((int)(*sp) >= num_trans)
+ *dp-- = 0xff;
+ else
+ *dp-- = trans[*sp];
+ *dp-- = palette[*sp].blue;
+ *dp-- = palette[*sp].green;
+ *dp-- = palette[*sp].red;
+ sp--;
+ }
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = 32;
+ row_info->rowbytes = row_width * 4;
+ row_info->color_type = 6;
+ row_info->channels = 4;
+ }
+ else
+ {
+ sp = row + (png_size_t)row_width - 1;
+ dp = row + (png_size_t)(row_width * 3) - 1;
+
+ for (i = 0; i < row_width; i++)
+ {
+ *dp-- = palette[*sp].blue;
+ *dp-- = palette[*sp].green;
+ *dp-- = palette[*sp].red;
+ sp--;
+ }
+
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = 24;
+ row_info->rowbytes = row_width * 3;
+ row_info->color_type = 2;
+ row_info->channels = 3;
+ }
+ break;
+ }
+ }
+ }
+}
+
+/* If the bit depth < 8, it is expanded to 8. Also, if the already
+ * expanded transparency value is supplied, an alpha channel is built.
+ */
+void /* PRIVATE */
+png_do_expand(png_row_infop row_info, png_bytep row,
+ png_color_16p trans_value)
+{
+ int shift, value;
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+
+ png_debug(1, "in png_do_expand");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
+
+ if (row_info->bit_depth < 8)
+ {
+ switch (row_info->bit_depth)
+ {
+ case 1:
+ {
+ gray = (png_uint_16)((gray&0x01)*0xff);
+ sp = row + (png_size_t)((row_width - 1) >> 3);
+ dp = row + (png_size_t)row_width - 1;
+ shift = 7 - (int)((row_width + 7) & 0x07);
+ for (i = 0; i < row_width; i++)
+ {
+ if ((*sp >> shift) & 0x01)
+ *dp = 0xff;
+ else
+ *dp = 0;
+ if (shift == 7)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift++;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 2:
+ {
+ gray = (png_uint_16)((gray&0x03)*0x55);
+ sp = row + (png_size_t)((row_width - 1) >> 2);
+ dp = row + (png_size_t)row_width - 1;
+ shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
+ for (i = 0; i < row_width; i++)
+ {
+ value = (*sp >> shift) & 0x03;
+ *dp = (png_byte)(value | (value << 2) | (value << 4) |
+ (value << 6));
+ if (shift == 6)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift += 2;
+
+ dp--;
+ }
+ break;
+ }
+
+ case 4:
+ {
+ gray = (png_uint_16)((gray&0x0f)*0x11);
+ sp = row + (png_size_t)((row_width - 1) >> 1);
+ dp = row + (png_size_t)row_width - 1;
+ shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
+ for (i = 0; i < row_width; i++)
+ {
+ value = (*sp >> shift) & 0x0f;
+ *dp = (png_byte)(value | (value << 4));
+ if (shift == 4)
+ {
+ shift = 0;
+ sp--;
+ }
+ else
+ shift = 4;
+
+ dp--;
+ }
+ break;
+ }
+ }
+
+ row_info->bit_depth = 8;
+ row_info->pixel_depth = 8;
+ row_info->rowbytes = row_width;
+ }
+
+ if (trans_value != NULL)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ gray = gray & 0xff;
+ sp = row + (png_size_t)row_width - 1;
+ dp = row + (png_size_t)(row_width << 1) - 1;
+ for (i = 0; i < row_width; i++)
+ {
+ if (*sp == gray)
+ *dp-- = 0;
+ else
+ *dp-- = 0xff;
+ *dp-- = *sp--;
+ }
+ }
+
+ else if (row_info->bit_depth == 16)
+ {
+ png_byte gray_high = (gray >> 8) & 0xff;
+ png_byte gray_low = gray & 0xff;
+ sp = row + row_info->rowbytes - 1;
+ dp = row + (row_info->rowbytes << 1) - 1;
+ for (i = 0; i < row_width; i++)
+ {
+ if (*(sp - 1) == gray_high && *(sp) == gray_low)
+ {
+ *dp-- = 0;
+ *dp-- = 0;
+ }
+ else
+ {
+ *dp-- = 0xff;
+ *dp-- = 0xff;
+ }
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ }
+ }
+
+ row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
+ row_info->channels = 2;
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+ row_width);
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ png_byte red = trans_value->red & 0xff;
+ png_byte green = trans_value->green & 0xff;
+ png_byte blue = trans_value->blue & 0xff;
+ sp = row + (png_size_t)row_info->rowbytes - 1;
+ dp = row + (png_size_t)(row_width << 2) - 1;
+ for (i = 0; i < row_width; i++)
+ {
+ if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
+ *dp-- = 0;
+ else
+ *dp-- = 0xff;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ png_byte red_high = (trans_value->red >> 8) & 0xff;
+ png_byte green_high = (trans_value->green >> 8) & 0xff;
+ png_byte blue_high = (trans_value->blue >> 8) & 0xff;
+ png_byte red_low = trans_value->red & 0xff;
+ png_byte green_low = trans_value->green & 0xff;
+ png_byte blue_low = trans_value->blue & 0xff;
+ sp = row + row_info->rowbytes - 1;
+ dp = row + (png_size_t)(row_width << 3) - 1;
+ for (i = 0; i < row_width; i++)
+ {
+ if (*(sp - 5) == red_high &&
+ *(sp - 4) == red_low &&
+ *(sp - 3) == green_high &&
+ *(sp - 2) == green_low &&
+ *(sp - 1) == blue_high &&
+ *(sp ) == blue_low)
+ {
+ *dp-- = 0;
+ *dp-- = 0;
+ }
+ else
+ {
+ *dp-- = 0xff;
+ *dp-- = 0xff;
+ }
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ *dp-- = *sp--;
+ }
+ }
+ row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ row_info->channels = 4;
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+ }
+}
+#endif
+
+#ifdef PNG_READ_DITHER_SUPPORTED
+void /* PRIVATE */
+png_do_dither(png_row_infop row_info, png_bytep row,
+ png_bytep palette_lookup, png_bytep dither_lookup)
+{
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width=row_info->width;
+
+ png_debug(1, "in png_do_dither");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+ palette_lookup && row_info->bit_depth == 8)
+ {
+ int r, g, b, p;
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ r = *sp++;
+ g = *sp++;
+ b = *sp++;
+
+ /* This looks real messy, but the compiler will reduce
+ * it down to a reasonable formula. For example, with
+ * 5 bits per color, we get:
+ * p = (((r >> 3) & 0x1f) << 10) |
+ * (((g >> 3) & 0x1f) << 5) |
+ * ((b >> 3) & 0x1f);
+ */
+ p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+ ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+ (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+ (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+ ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+ (PNG_DITHER_BLUE_BITS)) |
+ ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+ ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+ *dp++ = palette_lookup[p];
+ }
+ row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+ row_info->channels = 1;
+ row_info->pixel_depth = row_info->bit_depth;
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+ palette_lookup != NULL && row_info->bit_depth == 8)
+ {
+ int r, g, b, p;
+ sp = row;
+ dp = row;
+ for (i = 0; i < row_width; i++)
+ {
+ r = *sp++;
+ g = *sp++;
+ b = *sp++;
+ sp++;
+
+ p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
+ ((1 << PNG_DITHER_RED_BITS) - 1)) <<
+ (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
+ (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
+ ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
+ (PNG_DITHER_BLUE_BITS)) |
+ ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
+ ((1 << PNG_DITHER_BLUE_BITS) - 1));
+
+ *dp++ = palette_lookup[p];
+ }
+ row_info->color_type = PNG_COLOR_TYPE_PALETTE;
+ row_info->channels = 1;
+ row_info->pixel_depth = row_info->bit_depth;
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ dither_lookup && row_info->bit_depth == 8)
+ {
+ sp = row;
+ for (i = 0; i < row_width; i++, sp++)
+ {
+ *sp = dither_lookup[*sp];
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+#ifdef PNG_READ_GAMMA_SUPPORTED
+static PNG_CONST int png_gamma_shift[] =
+ {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0, 0x00};
+
+/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit
+ * tables, we don't make a full table if we are reducing to 8-bit in
+ * the future. Note also how the gamma_16 tables are segmented so that
+ * we don't need to allocate > 64K chunks for a full 16-bit table.
+ *
+ * See the PNG extensions document for an integer algorithm for creating
+ * the gamma tables. Maybe we will implement that here someday.
+ *
+ * We should only reach this point if
+ *
+ * the file_gamma is known (i.e., the gAMA or sRGB chunk is present,
+ * or the application has provided a file_gamma)
+ *
+ * AND
+ * {
+ * the screen_gamma is known
+ * OR
+ *
+ * RGB_to_gray transformation is being performed
+ * }
+ *
+ * AND
+ * {
+ * the screen_gamma is different from the reciprocal of the
+ * file_gamma by more than the specified threshold
+ *
+ * OR
+ *
+ * a background color has been specified and the file_gamma
+ * and screen_gamma are not 1.0, within the specified threshold.
+ * }
+ */
+
+void /* PRIVATE */
+png_build_gamma_table(png_structp png_ptr)
+{
+ png_debug(1, "in png_build_gamma_table");
+
+ if (png_ptr->bit_depth <= 8)
+ {
+ int i;
+ double g;
+
+ if (png_ptr->screen_gamma > .000001)
+ g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+
+ else
+ g = 1.0;
+
+ png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)256);
+
+ for (i = 0; i < 256; i++)
+ {
+ png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
+ g) * 255.0 + .5);
+ }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+ if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
+ {
+
+ g = 1.0 / (png_ptr->gamma);
+
+ png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)256);
+
+ for (i = 0; i < 256; i++)
+ {
+ png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
+ g) * 255.0 + .5);
+ }
+
+
+ png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)256);
+
+ if (png_ptr->screen_gamma > 0.000001)
+ g = 1.0 / png_ptr->screen_gamma;
+
+ else
+ g = png_ptr->gamma; /* Probably doing rgb_to_gray */
+
+ for (i = 0; i < 256; i++)
+ {
+ png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
+ g) * 255.0 + .5);
+
+ }
+ }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+ }
+ else
+ {
+ double g;
+ int i, j, shift, num;
+ int sig_bit;
+ png_uint_32 ig;
+
+ if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ {
+ sig_bit = (int)png_ptr->sig_bit.red;
+
+ if ((int)png_ptr->sig_bit.green > sig_bit)
+ sig_bit = png_ptr->sig_bit.green;
+
+ if ((int)png_ptr->sig_bit.blue > sig_bit)
+ sig_bit = png_ptr->sig_bit.blue;
+ }
+ else
+ {
+ sig_bit = (int)png_ptr->sig_bit.gray;
+ }
+
+ if (sig_bit > 0)
+ shift = 16 - sig_bit;
+
+ else
+ shift = 0;
+
+ if (png_ptr->transformations & PNG_16_TO_8)
+ {
+ if (shift < (16 - PNG_MAX_GAMMA_8))
+ shift = (16 - PNG_MAX_GAMMA_8);
+ }
+
+ if (shift > 8)
+ shift = 8;
+
+ if (shift < 0)
+ shift = 0;
+
+ png_ptr->gamma_shift = (png_byte)shift;
+
+ num = (1 << (8 - shift));
+
+ if (png_ptr->screen_gamma > .000001)
+ g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
+ else
+ g = 1.0;
+
+ png_ptr->gamma_16_table = (png_uint_16pp)png_calloc(png_ptr,
+ (png_uint_32)(num * png_sizeof(png_uint_16p)));
+
+ if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
+ {
+ double fin, fout;
+ png_uint_32 last, max;
+
+ for (i = 0; i < num; i++)
+ {
+ png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(256 * png_sizeof(png_uint_16)));
+ }
+
+ g = 1.0 / g;
+ last = 0;
+ for (i = 0; i < 256; i++)
+ {
+ fout = ((double)i + 0.5) / 256.0;
+ fin = pow(fout, g);
+ max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
+ while (last <= max)
+ {
+ png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+ [(int)(last >> (8 - shift))] = (png_uint_16)(
+ (png_uint_16)i | ((png_uint_16)i << 8));
+ last++;
+ }
+ }
+ while (last < ((png_uint_32)num << 8))
+ {
+ png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
+ [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
+ last++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < num; i++)
+ {
+ png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(256 * png_sizeof(png_uint_16)));
+
+ ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
+
+ for (j = 0; j < 256; j++)
+ {
+ png_ptr->gamma_16_table[i][j] =
+ (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+ 65535.0, g) * 65535.0 + .5);
+ }
+ }
+ }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+ if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+ {
+
+ g = 1.0 / (png_ptr->gamma);
+
+ png_ptr->gamma_16_to_1 = (png_uint_16pp)png_calloc(png_ptr,
+ (png_uint_32)(num * png_sizeof(png_uint_16p )));
+
+ for (i = 0; i < num; i++)
+ {
+ png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(256 * png_sizeof(png_uint_16)));
+
+ ig = (((png_uint_32)i *
+ (png_uint_32)png_gamma_shift[shift]) >> 4);
+ for (j = 0; j < 256; j++)
+ {
+ png_ptr->gamma_16_to_1[i][j] =
+ (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+ 65535.0, g) * 65535.0 + .5);
+ }
+ }
+
+ if (png_ptr->screen_gamma > 0.000001)
+ g = 1.0 / png_ptr->screen_gamma;
+
+ else
+ g = png_ptr->gamma; /* Probably doing rgb_to_gray */
+
+ png_ptr->gamma_16_from_1 = (png_uint_16pp)png_calloc(png_ptr,
+ (png_uint_32)(num * png_sizeof(png_uint_16p)));
+
+ for (i = 0; i < num; i++)
+ {
+ png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(256 * png_sizeof(png_uint_16)));
+
+ ig = (((png_uint_32)i *
+ (png_uint_32)png_gamma_shift[shift]) >> 4);
+
+ for (j = 0; j < 256; j++)
+ {
+ png_ptr->gamma_16_from_1[i][j] =
+ (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
+ 65535.0, g) * 65535.0 + .5);
+ }
+ }
+ }
+#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+ }
+}
+#endif
+/* To do: install integer version of png_build_gamma_table here */
+#endif
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing */
+void /* PRIVATE */
+png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_read_intrapixel");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
+ *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 red = (png_uint_32)((s0 + s1 + 65536L) & 0xffffL);
+ png_uint_32 blue = (png_uint_32)((s2 + s1 + 65536L) & 0xffffL);
+ *(rp ) = (png_byte)((red >> 8) & 0xff);
+ *(rp+1) = (png_byte)(red & 0xff);
+ *(rp+4) = (png_byte)((blue >> 8) & 0xff);
+ *(rp+5) = (png_byte)(blue & 0xff);
+ }
+ }
+ }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
+#endif /* PNG_READ_SUPPORTED */
diff --git a/Source/LibPNG/pngrutil.c b/Source/LibPNG/pngrutil.c
new file mode 100644
index 0000000..952f30b
--- /dev/null
+++ b/Source/LibPNG/pngrutil.c
@@ -0,0 +1,3386 @@
+
+/* pngrutil.c - utilities to read a PNG file
+ *
+ * Last changed in libpng 1.2.48 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file contains routines that are only called from within
+ * libpng itself during the course of reading an image.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_READ_SUPPORTED
+
+#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
+# define WIN32_WCE_OLD
+#endif
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+# ifdef WIN32_WCE_OLD
+/* The strtod() function is not supported on WindowsCE */
+__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
+ char **endptr)
+{
+ double result = 0;
+ int len;
+ wchar_t *str, *end;
+
+ len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
+ str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
+ if ( NULL != str )
+ {
+ MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
+ result = wcstod(str, &end);
+ len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
+ *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
+ png_free(png_ptr, str);
+ }
+ return result;
+}
+# else
+# define png_strtod(p,a,b) strtod(a,b)
+# endif
+#endif
+
+png_uint_32 PNGAPI
+png_get_uint_31(png_structp png_ptr, png_bytep buf)
+{
+#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
+ png_uint_32 i = png_get_uint_32(buf);
+#else
+ /* Avoid an extra function call by inlining the result. */
+ png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+ ((png_uint_32)(*(buf + 1)) << 16) +
+ ((png_uint_32)(*(buf + 2)) << 8) +
+ (png_uint_32)(*(buf + 3));
+#endif
+ if (i > PNG_UINT_31_MAX)
+ png_error(png_ptr, "PNG unsigned integer out of range.");
+ return (i);
+}
+#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
+/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
+png_uint_32 PNGAPI
+png_get_uint_32(png_bytep buf)
+{
+ png_uint_32 i = ((png_uint_32)(*buf) << 24) +
+ ((png_uint_32)(*(buf + 1)) << 16) +
+ ((png_uint_32)(*(buf + 2)) << 8) +
+ (png_uint_32)(*(buf + 3));
+
+ return (i);
+}
+
+/* Grab a signed 32-bit integer from a buffer in big-endian format. The
+ * data is stored in the PNG file in two's complement format, and it is
+ * assumed that the machine format for signed integers is the same.
+ */
+png_int_32 PNGAPI
+png_get_int_32(png_bytep buf)
+{
+ png_int_32 i = ((png_int_32)(*buf) << 24) +
+ ((png_int_32)(*(buf + 1)) << 16) +
+ ((png_int_32)(*(buf + 2)) << 8) +
+ (png_int_32)(*(buf + 3));
+
+ return (i);
+}
+
+/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
+png_uint_16 PNGAPI
+png_get_uint_16(png_bytep buf)
+{
+ png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
+ (png_uint_16)(*(buf + 1)));
+
+ return (i);
+}
+#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
+
+/* Read the chunk header (length + type name).
+ * Put the type name into png_ptr->chunk_name, and return the length.
+ */
+png_uint_32 /* PRIVATE */
+png_read_chunk_header(png_structp png_ptr)
+{
+ png_byte buf[8];
+ png_uint_32 length;
+
+ /* Read the length and the chunk name */
+ png_read_data(png_ptr, buf, 8);
+ length = png_get_uint_31(png_ptr, buf);
+
+ /* Put the chunk name into png_ptr->chunk_name */
+ png_memcpy(png_ptr->chunk_name, buf + 4, 4);
+
+ png_debug2(0, "Reading %s chunk, length = %lu",
+ png_ptr->chunk_name, length);
+
+ /* Reset the crc and run it over the chunk name */
+ png_reset_crc(png_ptr);
+ png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
+
+ /* Check to see if chunk name is valid */
+ png_check_chunk_name(png_ptr, png_ptr->chunk_name);
+
+ return length;
+}
+
+/* Read data, and (optionally) run it through the CRC. */
+void /* PRIVATE */
+png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
+{
+ if (png_ptr == NULL)
+ return;
+ png_read_data(png_ptr, buf, length);
+ png_calculate_crc(png_ptr, buf, length);
+}
+
+/* Optionally skip data and then check the CRC. Depending on whether we
+ * are reading a ancillary or critical chunk, and how the program has set
+ * things up, we may calculate the CRC on the data and print a message.
+ * Returns '1' if there was a CRC error, '0' otherwise.
+ */
+int /* PRIVATE */
+png_crc_finish(png_structp png_ptr, png_uint_32 skip)
+{
+ png_size_t i;
+ png_size_t istop = png_ptr->zbuf_size;
+
+ for (i = (png_size_t)skip; i > istop; i -= istop)
+ {
+ png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+ }
+ if (i)
+ {
+ png_crc_read(png_ptr, png_ptr->zbuf, i);
+ }
+
+ if (png_crc_error(png_ptr))
+ {
+ if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
+ !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
+ (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
+ (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
+ {
+ png_chunk_warning(png_ptr, "CRC error");
+ }
+ else
+ {
+ png_chunk_error(png_ptr, "CRC error");
+ }
+ return (1);
+ }
+
+ return (0);
+}
+
+/* Compare the CRC stored in the PNG file with that calculated by libpng from
+ * the data it has read thus far.
+ */
+int /* PRIVATE */
+png_crc_error(png_structp png_ptr)
+{
+ png_byte crc_bytes[4];
+ png_uint_32 crc;
+ int need_crc = 1;
+
+ if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
+ {
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
+ (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
+ need_crc = 0;
+ }
+ else /* critical */
+ {
+ if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ need_crc = 0;
+ }
+
+ png_read_data(png_ptr, crc_bytes, 4);
+
+ if (need_crc)
+ {
+ crc = png_get_uint_32(crc_bytes);
+ return ((int)(crc != png_ptr->crc));
+ }
+ else
+ return (0);
+}
+
+#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
+ defined(PNG_READ_iCCP_SUPPORTED)
+static png_size_t
+png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
+ png_bytep output, png_size_t output_size)
+{
+ png_size_t count = 0;
+
+ png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
+ png_ptr->zstream.avail_in = size;
+
+ while (1)
+ {
+ int ret, avail;
+
+ /* Reset the output buffer each time round - we empty it
+ * after every inflate call.
+ */
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = png_ptr->zbuf_size;
+
+ ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
+ avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+
+ /* First copy/count any new output - but only if we didn't
+ * get an error code.
+ */
+ if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
+ {
+ if (output != 0 && output_size > count)
+ {
+ png_size_t copy = output_size - count;
+ if ((png_size_t) avail < copy) copy = (png_size_t) avail;
+ png_memcpy(output + count, png_ptr->zbuf, copy);
+ }
+ count += avail;
+ }
+
+ if (ret == Z_OK)
+ continue;
+
+ /* Termination conditions - always reset the zstream, it
+ * must be left in inflateInit state.
+ */
+ png_ptr->zstream.avail_in = 0;
+ inflateReset(&png_ptr->zstream);
+
+ if (ret == Z_STREAM_END)
+ return count; /* NOTE: may be zero. */
+
+ /* Now handle the error codes - the API always returns 0
+ * and the error message is dumped into the uncompressed
+ * buffer if available.
+ */
+ {
+ PNG_CONST char *msg;
+ if (png_ptr->zstream.msg != 0)
+ msg = png_ptr->zstream.msg;
+ else
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char umsg[52];
+
+ switch (ret)
+ {
+ case Z_BUF_ERROR:
+ msg = "Buffer error in compressed datastream in %s chunk";
+ break;
+ case Z_DATA_ERROR:
+ msg = "Data error in compressed datastream in %s chunk";
+ break;
+ default:
+ msg = "Incomplete compressed datastream in %s chunk";
+ break;
+ }
+
+ png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
+ msg = umsg;
+#else
+ msg = "Damaged compressed datastream in chunk other than IDAT";
+#endif
+ }
+
+ png_warning(png_ptr, msg);
+ }
+
+ /* 0 means an error - notice that this code simple ignores
+ * zero length compressed chunks as a result.
+ */
+ return 0;
+ }
+}
+
+/*
+ * Decompress trailing data in a chunk. The assumption is that chunkdata
+ * points at an allocated area holding the contents of a chunk with a
+ * trailing compressed part. What we get back is an allocated area
+ * holding the original prefix part and an uncompressed version of the
+ * trailing part (the malloc area passed in is freed).
+ */
+void /* PRIVATE */
+png_decompress_chunk(png_structp png_ptr, int comp_type,
+ png_size_t chunklength,
+ png_size_t prefix_size, png_size_t *newlength)
+{
+ /* The caller should guarantee this */
+ if (prefix_size > chunklength)
+ {
+ /* The recovery is to delete the chunk. */
+ png_warning(png_ptr, "invalid chunklength");
+ prefix_size = 0; /* To delete everything */
+ }
+
+ else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+ {
+ png_size_t expanded_size = png_inflate(png_ptr,
+ (png_bytep)(png_ptr->chunkdata + prefix_size),
+ chunklength - prefix_size,
+ 0/*output*/, 0/*output size*/);
+
+ /* Now check the limits on this chunk - if the limit fails the
+ * compressed data will be removed, the prefix will remain.
+ */
+ if (prefix_size >= (~(png_size_t)0) - 1 ||
+ expanded_size >= (~(png_size_t)0) - 1 - prefix_size
+#ifdef PNG_USER_CHUNK_MALLOC_MAX
+ || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
+ prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
+#endif
+ )
+ png_warning(png_ptr, "Exceeded size limit while expanding chunk");
+
+ /* If the size is zero either there was an error and a message
+ * has already been output (warning) or the size really is zero
+ * and we have nothing to do - the code will exit through the
+ * error case below.
+ */
+ else if (expanded_size > 0)
+ {
+ /* Success (maybe) - really uncompress the chunk. */
+ png_size_t new_size = 0;
+
+ png_charp text = png_malloc_warn(png_ptr,
+ prefix_size + expanded_size + 1);
+
+ if (text != NULL)
+ {
+ png_memcpy(text, png_ptr->chunkdata, prefix_size);
+ new_size = png_inflate(png_ptr,
+ (png_bytep)(png_ptr->chunkdata + prefix_size),
+ chunklength - prefix_size,
+ (png_bytep)(text + prefix_size), expanded_size);
+ text[prefix_size + expanded_size] = 0; /* just in case */
+
+ if (new_size == expanded_size)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = text;
+ *newlength = prefix_size + expanded_size;
+ return; /* The success return! */
+ }
+
+ png_warning(png_ptr, "png_inflate logic error");
+ png_free(png_ptr, text);
+ }
+ else
+ png_warning(png_ptr, "Not enough memory to decompress chunk.");
+ }
+ }
+
+ else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char umsg[50];
+
+ png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
+ comp_type);
+ png_warning(png_ptr, umsg);
+#else
+ png_warning(png_ptr, "Unknown zTXt compression type");
+#endif
+
+ /* The recovery is to simply drop the data. */
+ }
+
+ /* Generic error return - leave the prefix, delete the compressed
+ * data, reallocate the chunkdata to remove the potentially large
+ * amount of compressed data.
+ */
+ {
+ png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
+ if (text != NULL)
+ {
+ if (prefix_size > 0)
+ png_memcpy(text, png_ptr->chunkdata, prefix_size);
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = text;
+
+ /* This is an extra zero in the 'uncompressed' part. */
+ *(png_ptr->chunkdata + prefix_size) = 0x00;
+ }
+ /* Ignore a malloc error here - it is safe. */
+ }
+
+ *newlength = prefix_size;
+}
+#endif
+
+/* Read and check the IDHR chunk */
+void /* PRIVATE */
+png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte buf[13];
+ png_uint_32 width, height;
+ int bit_depth, color_type, compression_type, filter_type;
+ int interlace_type;
+
+ png_debug(1, "in png_handle_IHDR");
+
+ if (png_ptr->mode & PNG_HAVE_IHDR)
+ png_error(png_ptr, "Out of place IHDR");
+
+ /* Check the length */
+ if (length != 13)
+ png_error(png_ptr, "Invalid IHDR chunk");
+
+ png_ptr->mode |= PNG_HAVE_IHDR;
+
+ png_crc_read(png_ptr, buf, 13);
+ png_crc_finish(png_ptr, 0);
+
+ width = png_get_uint_31(png_ptr, buf);
+ height = png_get_uint_31(png_ptr, buf + 4);
+ bit_depth = buf[8];
+ color_type = buf[9];
+ compression_type = buf[10];
+ filter_type = buf[11];
+ interlace_type = buf[12];
+
+ /* Set internal variables */
+ png_ptr->width = width;
+ png_ptr->height = height;
+ png_ptr->bit_depth = (png_byte)bit_depth;
+ png_ptr->interlaced = (png_byte)interlace_type;
+ png_ptr->color_type = (png_byte)color_type;
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ png_ptr->filter_type = (png_byte)filter_type;
+#endif
+ png_ptr->compression_type = (png_byte)compression_type;
+
+ /* Find number of channels */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ case PNG_COLOR_TYPE_PALETTE:
+ png_ptr->channels = 1;
+ break;
+
+ case PNG_COLOR_TYPE_RGB:
+ png_ptr->channels = 3;
+ break;
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ png_ptr->channels = 2;
+ break;
+
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ png_ptr->channels = 4;
+ break;
+ }
+
+ /* Set up other useful info */
+ png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
+ png_ptr->channels);
+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
+ png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
+ png_debug1(3, "channels = %d", png_ptr->channels);
+ png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
+ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
+ color_type, interlace_type, compression_type, filter_type);
+}
+
+/* Read and check the palette */
+void /* PRIVATE */
+png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_color palette[PNG_MAX_PALETTE_LENGTH];
+ int num, i;
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ png_colorp pal_ptr;
+#endif
+
+ png_debug(1, "in png_handle_PLTE");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before PLTE");
+
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid PLTE after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ png_error(png_ptr, "Duplicate PLTE chunk");
+
+ png_ptr->mode |= PNG_HAVE_PLTE;
+
+ if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ {
+ png_warning(png_ptr,
+ "Ignoring PLTE chunk in grayscale PNG");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+ if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+#endif
+
+ if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
+ {
+ if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+ {
+ png_warning(png_ptr, "Invalid palette chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ else
+ {
+ png_error(png_ptr, "Invalid palette chunk");
+ }
+ }
+
+ num = (int)length / 3;
+
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
+ {
+ png_byte buf[3];
+
+ png_crc_read(png_ptr, buf, 3);
+ pal_ptr->red = buf[0];
+ pal_ptr->green = buf[1];
+ pal_ptr->blue = buf[2];
+ }
+#else
+ for (i = 0; i < num; i++)
+ {
+ png_byte buf[3];
+
+ png_crc_read(png_ptr, buf, 3);
+ /* Don't depend upon png_color being any order */
+ palette[i].red = buf[0];
+ palette[i].green = buf[1];
+ palette[i].blue = buf[2];
+ }
+#endif
+
+ /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
+ * whatever the normal CRC configuration tells us. However, if we
+ * have an RGB image, the PLTE can be considered ancillary, so
+ * we will act as though it is.
+ */
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+#endif
+ {
+ png_crc_finish(png_ptr, 0);
+ }
+#ifndef PNG_READ_OPT_PLTE_SUPPORTED
+ else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
+ {
+ /* If we don't want to use the data from an ancillary chunk,
+ we have two options: an error abort, or a warning and we
+ ignore the data in this chunk (which should be OK, since
+ it's considered ancillary for a RGB or RGBA image). */
+ if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+ {
+ if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
+ {
+ png_chunk_error(png_ptr, "CRC error");
+ }
+ else
+ {
+ png_chunk_warning(png_ptr, "CRC error");
+ return;
+ }
+ }
+ /* Otherwise, we (optionally) emit a warning and use the chunk. */
+ else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
+ {
+ png_chunk_warning(png_ptr, "CRC error");
+ }
+ }
+#endif
+
+ png_set_PLTE(png_ptr, info_ptr, palette, num);
+
+#ifdef PNG_READ_tRNS_SUPPORTED
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ {
+ if (png_ptr->num_trans > (png_uint_16)num)
+ {
+ png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
+ png_ptr->num_trans = (png_uint_16)num;
+ }
+ if (info_ptr->num_trans > (png_uint_16)num)
+ {
+ png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
+ info_ptr->num_trans = (png_uint_16)num;
+ }
+ }
+ }
+#endif
+
+}
+
+void /* PRIVATE */
+png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_debug(1, "in png_handle_IEND");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
+ {
+ png_error(png_ptr, "No image in file");
+ }
+
+ png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
+
+ if (length != 0)
+ {
+ png_warning(png_ptr, "Incorrect IEND chunk length");
+ }
+ png_crc_finish(png_ptr, length);
+
+ info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
+}
+
+#ifdef PNG_READ_gAMA_SUPPORTED
+void /* PRIVATE */
+png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_fixed_point igamma;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float file_gamma;
+#endif
+ png_byte buf[4];
+
+ png_debug(1, "in png_handle_gAMA");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before gAMA");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid gAMA after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ /* Should be an error, but we can cope with it */
+ png_warning(png_ptr, "Out of place gAMA chunk");
+
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
+#ifdef PNG_READ_sRGB_SUPPORTED
+ && !(info_ptr->valid & PNG_INFO_sRGB)
+#endif
+ )
+ {
+ png_warning(png_ptr, "Duplicate gAMA chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length != 4)
+ {
+ png_warning(png_ptr, "Incorrect gAMA chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 4);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ igamma = (png_fixed_point)png_get_uint_32(buf);
+ /* Check for zero gamma */
+ if (igamma == 0)
+ {
+ png_warning(png_ptr,
+ "Ignoring gAMA chunk with gamma=0");
+ return;
+ }
+
+#ifdef PNG_READ_sRGB_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
+ if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
+ {
+ png_warning(png_ptr,
+ "Ignoring incorrect gAMA value when sRGB is also present");
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+ fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
+#endif
+ return;
+ }
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ file_gamma = (float)igamma / (float)100000.0;
+# ifdef PNG_READ_GAMMA_SUPPORTED
+ png_ptr->gamma = file_gamma;
+# endif
+ png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
+#endif
+}
+#endif
+
+#ifdef PNG_READ_sBIT_SUPPORTED
+void /* PRIVATE */
+png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_size_t truelen;
+ png_byte buf[4];
+
+ png_debug(1, "in png_handle_sBIT");
+
+ buf[0] = buf[1] = buf[2] = buf[3] = 0;
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before sBIT");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid sBIT after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ {
+ /* Should be an error, but we can cope with it */
+ png_warning(png_ptr, "Out of place sBIT chunk");
+ }
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
+ {
+ png_warning(png_ptr, "Duplicate sBIT chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ truelen = 3;
+ else
+ truelen = (png_size_t)png_ptr->channels;
+
+ if (length != truelen || length > 4)
+ {
+ png_warning(png_ptr, "Incorrect sBIT chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, truelen);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ {
+ png_ptr->sig_bit.red = buf[0];
+ png_ptr->sig_bit.green = buf[1];
+ png_ptr->sig_bit.blue = buf[2];
+ png_ptr->sig_bit.alpha = buf[3];
+ }
+ else
+ {
+ png_ptr->sig_bit.gray = buf[0];
+ png_ptr->sig_bit.red = buf[0];
+ png_ptr->sig_bit.green = buf[0];
+ png_ptr->sig_bit.blue = buf[0];
+ png_ptr->sig_bit.alpha = buf[1];
+ }
+ png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
+}
+#endif
+
+#ifdef PNG_READ_cHRM_SUPPORTED
+void /* PRIVATE */
+png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte buf[32];
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+ png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+ int_y_green, int_x_blue, int_y_blue;
+
+ png_uint_32 uint_x, uint_y;
+
+ png_debug(1, "in png_handle_cHRM");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before cHRM");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid cHRM after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ /* Should be an error, but we can cope with it */
+ png_warning(png_ptr, "Missing PLTE before cHRM");
+
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
+#ifdef PNG_READ_sRGB_SUPPORTED
+ && !(info_ptr->valid & PNG_INFO_sRGB)
+#endif
+ )
+ {
+ png_warning(png_ptr, "Duplicate cHRM chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length != 32)
+ {
+ png_warning(png_ptr, "Incorrect cHRM chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 32);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ uint_x = png_get_uint_32(buf);
+ uint_y = png_get_uint_32(buf + 4);
+ int_x_white = (png_fixed_point)uint_x;
+ int_y_white = (png_fixed_point)uint_y;
+
+ uint_x = png_get_uint_32(buf + 8);
+ uint_y = png_get_uint_32(buf + 12);
+ int_x_red = (png_fixed_point)uint_x;
+ int_y_red = (png_fixed_point)uint_y;
+
+ uint_x = png_get_uint_32(buf + 16);
+ uint_y = png_get_uint_32(buf + 20);
+ int_x_green = (png_fixed_point)uint_x;
+ int_y_green = (png_fixed_point)uint_y;
+
+ uint_x = png_get_uint_32(buf + 24);
+ uint_y = png_get_uint_32(buf + 28);
+ int_x_blue = (png_fixed_point)uint_x;
+ int_y_blue = (png_fixed_point)uint_y;
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ white_x = (float)int_x_white / (float)100000.0;
+ white_y = (float)int_y_white / (float)100000.0;
+ red_x = (float)int_x_red / (float)100000.0;
+ red_y = (float)int_y_red / (float)100000.0;
+ green_x = (float)int_x_green / (float)100000.0;
+ green_y = (float)int_y_green / (float)100000.0;
+ blue_x = (float)int_x_blue / (float)100000.0;
+ blue_y = (float)int_y_blue / (float)100000.0;
+#endif
+
+#ifdef PNG_READ_sRGB_SUPPORTED
+ if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
+ {
+ if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
+ PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
+ PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
+ PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
+ PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
+ PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
+ PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
+ PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
+ {
+ png_warning(png_ptr,
+ "Ignoring incorrect cHRM value when sRGB is also present");
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
+ white_x, white_y, red_x, red_y);
+ fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
+ green_x, green_y, blue_x, blue_y);
+#else
+ fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
+ (long)int_x_white, (long)int_y_white,
+ (long)int_x_red, (long)int_y_red);
+ fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
+ (long)int_x_green, (long)int_y_green,
+ (long)int_x_blue, (long)int_y_blue);
+#endif
+#endif /* PNG_CONSOLE_IO_SUPPORTED */
+ }
+ return;
+ }
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_set_cHRM(png_ptr, info_ptr,
+ white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_set_cHRM_fixed(png_ptr, info_ptr,
+ int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
+ int_y_green, int_x_blue, int_y_blue);
+#endif
+}
+#endif
+
+#ifdef PNG_READ_sRGB_SUPPORTED
+void /* PRIVATE */
+png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ int intent;
+ png_byte buf[1];
+
+ png_debug(1, "in png_handle_sRGB");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before sRGB");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid sRGB after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ /* Should be an error, but we can cope with it */
+ png_warning(png_ptr, "Out of place sRGB chunk");
+
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
+ {
+ png_warning(png_ptr, "Duplicate sRGB chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length != 1)
+ {
+ png_warning(png_ptr, "Incorrect sRGB chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 1);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ intent = buf[0];
+ /* Check for bad intent */
+ if (intent >= PNG_sRGB_INTENT_LAST)
+ {
+ png_warning(png_ptr, "Unknown sRGB intent");
+ return;
+ }
+
+#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
+ {
+ png_fixed_point igamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ igamma=info_ptr->int_gamma;
+#else
+# ifdef PNG_FLOATING_POINT_SUPPORTED
+ igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
+# endif
+#endif
+ if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
+ {
+ png_warning(png_ptr,
+ "Ignoring incorrect gAMA value when sRGB is also present");
+#ifdef PNG_CONSOLE_IO_SUPPORTED
+# ifdef PNG_FIXED_POINT_SUPPORTED
+ fprintf(stderr, "incorrect gamma=(%d/100000)\n",
+ (int)png_ptr->int_gamma);
+# else
+# ifdef PNG_FLOATING_POINT_SUPPORTED
+ fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
+# endif
+# endif
+#endif
+ }
+ }
+#endif /* PNG_READ_gAMA_SUPPORTED */
+
+#ifdef PNG_READ_cHRM_SUPPORTED
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
+ PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
+ {
+ png_warning(png_ptr,
+ "Ignoring incorrect cHRM value when sRGB is also present");
+ }
+#endif /* PNG_FIXED_POINT_SUPPORTED */
+#endif /* PNG_READ_cHRM_SUPPORTED */
+
+ png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
+}
+#endif /* PNG_READ_sRGB_SUPPORTED */
+
+#ifdef PNG_READ_iCCP_SUPPORTED
+void /* PRIVATE */
+png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+ png_byte compression_type;
+ png_bytep pC;
+ png_charp profile;
+ png_uint_32 skip = 0;
+ png_uint_32 profile_size, profile_length;
+ png_size_t slength, prefix_length, data_length;
+
+ png_debug(1, "in png_handle_iCCP");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before iCCP");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid iCCP after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->mode & PNG_HAVE_PLTE)
+ /* Should be an error, but we can cope with it */
+ png_warning(png_ptr, "Out of place iCCP chunk");
+
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
+ {
+ png_warning(png_ptr, "Duplicate iCCP chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+#ifdef PNG_MAX_MALLOC_64K
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "iCCP chunk too large to fit in memory");
+ skip = length - (png_uint_32)65535L;
+ length = (png_uint_32)65535L;
+ }
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+
+ if (png_crc_finish(png_ptr, skip))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00;
+
+ for (profile = png_ptr->chunkdata; *profile; profile++)
+ /* Empty loop to find end of name */ ;
+
+ ++profile;
+
+ /* There should be at least one zero (the compression type byte)
+ * following the separator, and we should be on it
+ */
+ if ( profile >= png_ptr->chunkdata + slength - 1)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "Malformed iCCP chunk");
+ return;
+ }
+
+ /* Compression_type should always be zero */
+ compression_type = *profile++;
+ if (compression_type)
+ {
+ png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
+ compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
+ wrote nonzero) */
+ }
+
+ prefix_length = profile - png_ptr->chunkdata;
+ png_decompress_chunk(png_ptr, compression_type,
+ slength, prefix_length, &data_length);
+
+ profile_length = data_length - prefix_length;
+
+ if ( prefix_length > data_length || profile_length < 4)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "Profile size field missing from iCCP chunk");
+ return;
+ }
+
+ /* Check the profile_size recorded in the first 32 bits of the ICC profile */
+ pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
+ profile_size = ((*(pC ))<<24) |
+ ((*(pC + 1))<<16) |
+ ((*(pC + 2))<< 8) |
+ ((*(pC + 3)) );
+
+ if (profile_size < profile_length)
+ profile_length = profile_size;
+
+ if (profile_size > profile_length)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "Ignoring truncated iCCP profile.");
+ return;
+ }
+
+ png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
+ compression_type, png_ptr->chunkdata + prefix_length, profile_length);
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+}
+#endif /* PNG_READ_iCCP_SUPPORTED */
+
+#ifdef PNG_READ_sPLT_SUPPORTED
+void /* PRIVATE */
+png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+{
+ png_bytep entry_start;
+ png_sPLT_t new_palette;
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ png_sPLT_entryp pp;
+#endif
+ int data_length, entry_size, i;
+ png_uint_32 skip = 0;
+ png_size_t slength;
+
+ png_debug(1, "in png_handle_sPLT");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+
+ if (png_ptr->user_chunk_cache_max != 0)
+ {
+ if (png_ptr->user_chunk_cache_max == 1)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (--png_ptr->user_chunk_cache_max == 1)
+ {
+ png_warning(png_ptr, "No space in chunk cache for sPLT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ }
+#endif
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before sPLT");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid sPLT after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+#ifdef PNG_MAX_MALLOC_64K
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "sPLT chunk too large to fit in memory");
+ skip = length - (png_uint_32)65535L;
+ length = (png_uint_32)65535L;
+ }
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+
+ if (png_crc_finish(png_ptr, skip))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00;
+
+ for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
+ entry_start++)
+ /* Empty loop to find end of name */ ;
+ ++entry_start;
+
+ /* A sample depth should follow the separator, and we should be on it */
+ if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "malformed sPLT chunk");
+ return;
+ }
+
+ new_palette.depth = *entry_start++;
+ entry_size = (new_palette.depth == 8 ? 6 : 10);
+ data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
+
+ /* Integrity-check the data length */
+ if (data_length % entry_size)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "sPLT chunk has bad length");
+ return;
+ }
+
+ new_palette.nentries = (png_int_32) ( data_length / entry_size);
+ if ((png_uint_32) new_palette.nentries >
+ (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
+ {
+ png_warning(png_ptr, "sPLT chunk too long");
+ return;
+ }
+ new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
+ png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
+ if (new_palette.entries == NULL)
+ {
+ png_warning(png_ptr, "sPLT chunk requires too much memory");
+ return;
+ }
+
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ for (i = 0; i < new_palette.nentries; i++)
+ {
+ pp = new_palette.entries + i;
+
+ if (new_palette.depth == 8)
+ {
+ pp->red = *entry_start++;
+ pp->green = *entry_start++;
+ pp->blue = *entry_start++;
+ pp->alpha = *entry_start++;
+ }
+ else
+ {
+ pp->red = png_get_uint_16(entry_start); entry_start += 2;
+ pp->green = png_get_uint_16(entry_start); entry_start += 2;
+ pp->blue = png_get_uint_16(entry_start); entry_start += 2;
+ pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
+ }
+ pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+ }
+#else
+ pp = new_palette.entries;
+ for (i = 0; i < new_palette.nentries; i++)
+ {
+
+ if (new_palette.depth == 8)
+ {
+ pp[i].red = *entry_start++;
+ pp[i].green = *entry_start++;
+ pp[i].blue = *entry_start++;
+ pp[i].alpha = *entry_start++;
+ }
+ else
+ {
+ pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
+ pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
+ pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
+ pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
+ }
+ pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
+ }
+#endif
+
+ /* Discard all chunk data except the name and stash that */
+ new_palette.name = png_ptr->chunkdata;
+
+ png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_free(png_ptr, new_palette.entries);
+}
+#endif /* PNG_READ_sPLT_SUPPORTED */
+
+#ifdef PNG_READ_tRNS_SUPPORTED
+void /* PRIVATE */
+png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
+
+ png_debug(1, "in png_handle_tRNS");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before tRNS");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid tRNS after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ {
+ png_warning(png_ptr, "Duplicate tRNS chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ png_byte buf[2];
+
+ if (length != 2)
+ {
+ png_warning(png_ptr, "Incorrect tRNS chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 2);
+ png_ptr->num_trans = 1;
+ png_ptr->trans_values.gray = png_get_uint_16(buf);
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ png_byte buf[6];
+
+ if (length != 6)
+ {
+ png_warning(png_ptr, "Incorrect tRNS chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ png_crc_read(png_ptr, buf, (png_size_t)length);
+ png_ptr->num_trans = 1;
+ png_ptr->trans_values.red = png_get_uint_16(buf);
+ png_ptr->trans_values.green = png_get_uint_16(buf + 2);
+ png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ {
+ /* Should be an error, but we can cope with it. */
+ png_warning(png_ptr, "Missing PLTE before tRNS");
+ }
+ if (length > (png_uint_32)png_ptr->num_palette ||
+ length > PNG_MAX_PALETTE_LENGTH)
+ {
+ png_warning(png_ptr, "Incorrect tRNS chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (length == 0)
+ {
+ png_warning(png_ptr, "Zero length tRNS chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ png_crc_read(png_ptr, readbuf, (png_size_t)length);
+ png_ptr->num_trans = (png_uint_16)length;
+ }
+ else
+ {
+ png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (png_crc_finish(png_ptr, 0))
+ {
+ png_ptr->num_trans = 0;
+ return;
+ }
+
+ png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
+ &(png_ptr->trans_values));
+}
+#endif
+
+#ifdef PNG_READ_bKGD_SUPPORTED
+void /* PRIVATE */
+png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_size_t truelen;
+ png_byte buf[6];
+
+ png_debug(1, "in png_handle_bKGD");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before bKGD");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid bKGD after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ !(png_ptr->mode & PNG_HAVE_PLTE))
+ {
+ png_warning(png_ptr, "Missing PLTE before bKGD");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
+ {
+ png_warning(png_ptr, "Duplicate bKGD chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ truelen = 1;
+ else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ truelen = 6;
+ else
+ truelen = 2;
+
+ if (length != truelen)
+ {
+ png_warning(png_ptr, "Incorrect bKGD chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, truelen);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ /* We convert the index value into RGB components so that we can allow
+ * arbitrary RGB values for background when we have transparency, and
+ * so it is easy to determine the RGB values of the background color
+ * from the info_ptr struct. */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_ptr->background.index = buf[0];
+ if (info_ptr && info_ptr->num_palette)
+ {
+ if (buf[0] >= info_ptr->num_palette)
+ {
+ png_warning(png_ptr, "Incorrect bKGD chunk index value");
+ return;
+ }
+ png_ptr->background.red =
+ (png_uint_16)png_ptr->palette[buf[0]].red;
+ png_ptr->background.green =
+ (png_uint_16)png_ptr->palette[buf[0]].green;
+ png_ptr->background.blue =
+ (png_uint_16)png_ptr->palette[buf[0]].blue;
+ }
+ }
+ else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+ {
+ png_ptr->background.red =
+ png_ptr->background.green =
+ png_ptr->background.blue =
+ png_ptr->background.gray = png_get_uint_16(buf);
+ }
+ else
+ {
+ png_ptr->background.red = png_get_uint_16(buf);
+ png_ptr->background.green = png_get_uint_16(buf + 2);
+ png_ptr->background.blue = png_get_uint_16(buf + 4);
+ }
+
+ png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
+}
+#endif
+
+#ifdef PNG_READ_hIST_SUPPORTED
+void /* PRIVATE */
+png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ unsigned int num, i;
+ png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
+
+ png_debug(1, "in png_handle_hIST");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before hIST");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid hIST after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ {
+ png_warning(png_ptr, "Missing PLTE before hIST");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
+ {
+ png_warning(png_ptr, "Duplicate hIST chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length > 2*PNG_MAX_PALETTE_LENGTH ||
+ length != (unsigned int) (2*png_ptr->num_palette))
+ {
+ png_warning(png_ptr, "Incorrect hIST chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ num = length / 2 ;
+
+ for (i = 0; i < num; i++)
+ {
+ png_byte buf[2];
+
+ png_crc_read(png_ptr, buf, 2);
+ readbuf[i] = png_get_uint_16(buf);
+ }
+
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ png_set_hIST(png_ptr, info_ptr, readbuf);
+}
+#endif
+
+#ifdef PNG_READ_pHYs_SUPPORTED
+void /* PRIVATE */
+png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte buf[9];
+ png_uint_32 res_x, res_y;
+ int unit_type;
+
+ png_debug(1, "in png_handle_pHYs");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before pHYs");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid pHYs after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ {
+ png_warning(png_ptr, "Duplicate pHYs chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length != 9)
+ {
+ png_warning(png_ptr, "Incorrect pHYs chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 9);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ res_x = png_get_uint_32(buf);
+ res_y = png_get_uint_32(buf + 4);
+ unit_type = buf[8];
+ png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
+}
+#endif
+
+#ifdef PNG_READ_oFFs_SUPPORTED
+void /* PRIVATE */
+png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte buf[9];
+ png_int_32 offset_x, offset_y;
+ int unit_type;
+
+ png_debug(1, "in png_handle_oFFs");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before oFFs");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid oFFs after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ {
+ png_warning(png_ptr, "Duplicate oFFs chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (length != 9)
+ {
+ png_warning(png_ptr, "Incorrect oFFs chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 9);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ offset_x = png_get_int_32(buf);
+ offset_y = png_get_int_32(buf + 4);
+ unit_type = buf[8];
+ png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
+}
+#endif
+
+#ifdef PNG_READ_pCAL_SUPPORTED
+/* Read the pCAL chunk (described in the PNG Extensions document) */
+void /* PRIVATE */
+png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_int_32 X0, X1;
+ png_byte type, nparams;
+ png_charp buf, units, endptr;
+ png_charpp params;
+ png_size_t slength;
+ int i;
+
+ png_debug(1, "in png_handle_pCAL");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before pCAL");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid pCAL after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+ {
+ png_warning(png_ptr, "Duplicate pCAL chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
+ length + 1);
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ if (png_ptr->chunkdata == NULL)
+ {
+ png_warning(png_ptr, "No memory for pCAL purpose.");
+ return;
+ }
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+
+ if (png_crc_finish(png_ptr, 0))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+
+ png_debug(3, "Finding end of pCAL purpose string");
+ for (buf = png_ptr->chunkdata; *buf; buf++)
+ /* Empty loop */ ;
+
+ endptr = png_ptr->chunkdata + slength;
+
+ /* We need to have at least 12 bytes after the purpose string
+ in order to get the parameter information. */
+ if (endptr <= buf + 12)
+ {
+ png_warning(png_ptr, "Invalid pCAL data");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
+ X0 = png_get_int_32((png_bytep)buf+1);
+ X1 = png_get_int_32((png_bytep)buf+5);
+ type = buf[9];
+ nparams = buf[10];
+ units = buf + 11;
+
+ png_debug(3, "Checking pCAL equation type and number of parameters");
+ /* Check that we have the right number of parameters for known
+ equation types. */
+ if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
+ (type == PNG_EQUATION_BASE_E && nparams != 3) ||
+ (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
+ (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
+ {
+ png_warning(png_ptr, "Invalid pCAL parameters for equation type");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ else if (type >= PNG_EQUATION_LAST)
+ {
+ png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ }
+
+ for (buf = units; *buf; buf++)
+ /* Empty loop to move past the units string. */ ;
+
+ png_debug(3, "Allocating pCAL parameters array");
+ params = (png_charpp)png_malloc_warn(png_ptr,
+ (png_uint_32)(nparams * png_sizeof(png_charp))) ;
+ if (params == NULL)
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_warning(png_ptr, "No memory for pCAL params.");
+ return;
+ }
+
+ /* Get pointers to the start of each parameter string. */
+ for (i = 0; i < (int)nparams; i++)
+ {
+ buf++; /* Skip the null string terminator from previous parameter. */
+
+ png_debug1(3, "Reading pCAL parameter %d", i);
+ for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
+ /* Empty loop to move past each parameter string */ ;
+
+ /* Make sure we haven't run out of data yet */
+ if (buf > endptr)
+ {
+ png_warning(png_ptr, "Invalid pCAL data");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_free(png_ptr, params);
+ return;
+ }
+ }
+
+ png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
+ units, params);
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_free(png_ptr, params);
+}
+#endif
+
+#ifdef PNG_READ_sCAL_SUPPORTED
+/* Read the sCAL chunk */
+void /* PRIVATE */
+png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_charp ep;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ double width, height;
+ png_charp vp;
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_charp swidth, sheight;
+#endif
+#endif
+ png_size_t slength;
+
+ png_debug(1, "in png_handle_sCAL");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before sCAL");
+ else if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+ png_warning(png_ptr, "Invalid sCAL after IDAT");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+ {
+ png_warning(png_ptr, "Duplicate sCAL chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ /* Need unit type, width, \0, height: minimum 4 bytes */
+ else if (length < 4)
+ {
+ png_warning(png_ptr, "sCAL chunk too short");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
+ length + 1);
+ png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ if (png_ptr->chunkdata == NULL)
+ {
+ png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+
+ if (png_crc_finish(png_ptr, 0))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+
+ ep = png_ptr->chunkdata + 1; /* Skip unit byte */
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ width = png_strtod(png_ptr, ep, &vp);
+ if (*vp)
+ {
+ png_warning(png_ptr, "malformed width string in sCAL chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
+ if (swidth == NULL)
+ {
+ png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ png_memcpy(swidth, ep, (png_size_t)png_strlen(ep) + 1);
+#endif
+#endif
+
+ for (ep = png_ptr->chunkdata + 1; *ep; ep++)
+ /* Empty loop */ ;
+ ep++;
+
+ if (png_ptr->chunkdata + slength < ep)
+ {
+ png_warning(png_ptr, "Truncated sCAL chunk");
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, swidth);
+#endif
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ height = png_strtod(png_ptr, ep, &vp);
+ if (*vp)
+ {
+ png_warning(png_ptr, "malformed height string in sCAL chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, swidth);
+#endif
+ return;
+ }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
+ if (sheight == NULL)
+ {
+ png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, swidth);
+#endif
+ return;
+ }
+ png_memcpy(sheight, ep, (png_size_t)png_strlen(ep) + 1);
+#endif
+#endif
+
+ if (png_ptr->chunkdata + slength < ep
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ || width <= 0. || height <= 0.
+#endif
+ )
+ {
+ png_warning(png_ptr, "Invalid sCAL data");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, swidth);
+ png_free(png_ptr, sheight);
+#endif
+ return;
+ }
+
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
+#endif
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
+ png_free(png_ptr, swidth);
+ png_free(png_ptr, sheight);
+#endif
+}
+#endif
+
+#ifdef PNG_READ_tIME_SUPPORTED
+void /* PRIVATE */
+png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_byte buf[7];
+ png_time mod_time;
+
+ png_debug(1, "in png_handle_tIME");
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Out of place tIME chunk");
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
+ {
+ png_warning(png_ptr, "Duplicate tIME chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+
+ if (length != 7)
+ {
+ png_warning(png_ptr, "Incorrect tIME chunk length");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+
+ png_crc_read(png_ptr, buf, 7);
+ if (png_crc_finish(png_ptr, 0))
+ return;
+
+ mod_time.second = buf[6];
+ mod_time.minute = buf[5];
+ mod_time.hour = buf[4];
+ mod_time.day = buf[3];
+ mod_time.month = buf[2];
+ mod_time.year = png_get_uint_16(buf);
+
+ png_set_tIME(png_ptr, info_ptr, &mod_time);
+}
+#endif
+
+#ifdef PNG_READ_tEXt_SUPPORTED
+/* Note: this does not properly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_textp text_ptr;
+ png_charp key;
+ png_charp text;
+ png_uint_32 skip = 0;
+ png_size_t slength;
+ int ret;
+
+ png_debug(1, "in png_handle_tEXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_cache_max != 0)
+ {
+ if (png_ptr->user_chunk_cache_max == 1)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (--png_ptr->user_chunk_cache_max == 1)
+ {
+ png_warning(png_ptr, "No space in chunk cache for tEXt");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ }
+#endif
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before tEXt");
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "tEXt chunk too large to fit in memory");
+ skip = length - (png_uint_32)65535L;
+ length = (png_uint_32)65535L;
+ }
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+
+ png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ if (png_ptr->chunkdata == NULL)
+ {
+ png_warning(png_ptr, "No memory to process text chunk.");
+ return;
+ }
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+
+ if (png_crc_finish(png_ptr, skip))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ key = png_ptr->chunkdata;
+
+ key[slength] = 0x00;
+
+ for (text = key; *text; text++)
+ /* Empty loop to find end of key */ ;
+
+ if (text != key + slength)
+ text++;
+
+ text_ptr = (png_textp)png_malloc_warn(png_ptr,
+ (png_uint_32)png_sizeof(png_text));
+ if (text_ptr == NULL)
+ {
+ png_warning(png_ptr, "Not enough memory to process text chunk.");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
+ text_ptr->key = key;
+#ifdef PNG_iTXt_SUPPORTED
+ text_ptr->lang = NULL;
+ text_ptr->lang_key = NULL;
+ text_ptr->itxt_length = 0;
+#endif
+ text_ptr->text = text;
+ text_ptr->text_length = png_strlen(text);
+
+ ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ png_free(png_ptr, text_ptr);
+ if (ret)
+ png_warning(png_ptr, "Insufficient memory to process text chunk.");
+}
+#endif
+
+#ifdef PNG_READ_zTXt_SUPPORTED
+/* Note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_textp text_ptr;
+ png_charp text;
+ int comp_type;
+ int ret;
+ png_size_t slength, prefix_len, data_len;
+
+ png_debug(1, "in png_handle_zTXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_cache_max != 0)
+ {
+ if (png_ptr->user_chunk_cache_max == 1)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (--png_ptr->user_chunk_cache_max == 1)
+ {
+ png_warning(png_ptr, "No space in chunk cache for zTXt");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ }
+#endif
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before zTXt");
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+ /* We will no doubt have problems with chunks even half this size, but
+ there is no hard and fast rule to tell us where to stop. */
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "zTXt chunk too large to fit in memory");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ if (png_ptr->chunkdata == NULL)
+ {
+ png_warning(png_ptr, "Out of memory processing zTXt chunk.");
+ return;
+ }
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ if (png_crc_finish(png_ptr, 0))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00;
+
+ for (text = png_ptr->chunkdata; *text; text++)
+ /* Empty loop */ ;
+
+ /* zTXt must have some text after the chunkdataword */
+ if (text >= png_ptr->chunkdata + slength - 2)
+ {
+ png_warning(png_ptr, "Truncated zTXt chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ else
+ {
+ comp_type = *(++text);
+ if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
+ {
+ png_warning(png_ptr, "Unknown compression type in zTXt chunk");
+ comp_type = PNG_TEXT_COMPRESSION_zTXt;
+ }
+ text++; /* Skip the compression_method byte */
+ }
+ prefix_len = text - png_ptr->chunkdata;
+
+ png_decompress_chunk(png_ptr, comp_type,
+ (png_size_t)length, prefix_len, &data_len);
+
+ text_ptr = (png_textp)png_malloc_warn(png_ptr,
+ (png_uint_32)png_sizeof(png_text));
+ if (text_ptr == NULL)
+ {
+ png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ text_ptr->compression = comp_type;
+ text_ptr->key = png_ptr->chunkdata;
+#ifdef PNG_iTXt_SUPPORTED
+ text_ptr->lang = NULL;
+ text_ptr->lang_key = NULL;
+ text_ptr->itxt_length = 0;
+#endif
+ text_ptr->text = png_ptr->chunkdata + prefix_len;
+ text_ptr->text_length = data_len;
+
+ ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+
+ png_free(png_ptr, text_ptr);
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ if (ret)
+ png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
+}
+#endif
+
+#ifdef PNG_READ_iTXt_SUPPORTED
+/* Note: this does not correctly handle chunks that are > 64K under DOS */
+void /* PRIVATE */
+png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_textp text_ptr;
+ png_charp key, lang, text, lang_key;
+ int comp_flag;
+ int comp_type = 0;
+ int ret;
+ png_size_t slength, prefix_len, data_len;
+
+ png_debug(1, "in png_handle_iTXt");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_cache_max != 0)
+ {
+ if (png_ptr->user_chunk_cache_max == 1)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (--png_ptr->user_chunk_cache_max == 1)
+ {
+ png_warning(png_ptr, "No space in chunk cache for iTXt");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ }
+#endif
+
+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
+ png_error(png_ptr, "Missing IHDR before iTXt");
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+
+#ifdef PNG_MAX_MALLOC_64K
+ /* We will no doubt have problems with chunks even half this size, but
+ there is no hard and fast rule to tell us where to stop. */
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "iTXt chunk too large to fit in memory");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+#endif
+
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ if (png_ptr->chunkdata == NULL)
+ {
+ png_warning(png_ptr, "No memory to process iTXt chunk.");
+ return;
+ }
+ slength = (png_size_t)length;
+ png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ if (png_crc_finish(png_ptr, 0))
+ {
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ png_ptr->chunkdata[slength] = 0x00;
+
+ for (lang = png_ptr->chunkdata; *lang; lang++)
+ /* Empty loop */ ;
+ lang++; /* Skip NUL separator */
+
+ /* iTXt must have a language tag (possibly empty), two compression bytes,
+ * translated keyword (possibly empty), and possibly some text after the
+ * keyword
+ */
+
+ if (lang >= png_ptr->chunkdata + slength - 3)
+ {
+ png_warning(png_ptr, "Truncated iTXt chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ else
+ {
+ comp_flag = *lang++;
+ comp_type = *lang++;
+ }
+
+ for (lang_key = lang; *lang_key; lang_key++)
+ /* Empty loop */ ;
+ lang_key++; /* Skip NUL separator */
+
+ if (lang_key >= png_ptr->chunkdata + slength)
+ {
+ png_warning(png_ptr, "Truncated iTXt chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ for (text = lang_key; *text; text++)
+ /* Empty loop */ ;
+ text++; /* Skip NUL separator */
+ if (text >= png_ptr->chunkdata + slength)
+ {
+ png_warning(png_ptr, "Malformed iTXt chunk");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+
+ prefix_len = text - png_ptr->chunkdata;
+
+ key=png_ptr->chunkdata;
+ if (comp_flag)
+ png_decompress_chunk(png_ptr, comp_type,
+ (size_t)length, prefix_len, &data_len);
+ else
+ data_len = png_strlen(png_ptr->chunkdata + prefix_len);
+ text_ptr = (png_textp)png_malloc_warn(png_ptr,
+ (png_uint_32)png_sizeof(png_text));
+ if (text_ptr == NULL)
+ {
+ png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ return;
+ }
+ text_ptr->compression = (int)comp_flag + 1;
+ text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
+ text_ptr->lang = png_ptr->chunkdata + (lang - key);
+ text_ptr->itxt_length = data_len;
+ text_ptr->text_length = 0;
+ text_ptr->key = png_ptr->chunkdata;
+ text_ptr->text = png_ptr->chunkdata + prefix_len;
+
+ ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+
+ png_free(png_ptr, text_ptr);
+ png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->chunkdata = NULL;
+ if (ret)
+ png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
+}
+#endif
+
+/* This function is called when we haven't found a handler for a
+ chunk. If there isn't a problem with the chunk itself (ie bad
+ chunk name, CRC, or a critical chunk), the chunk is silently ignored
+ -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
+ case it will be saved away to be written out later. */
+void /* PRIVATE */
+png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+{
+ png_uint_32 skip = 0;
+
+ png_debug(1, "in png_handle_unknown");
+
+#ifdef PNG_USER_LIMITS_SUPPORTED
+ if (png_ptr->user_chunk_cache_max != 0)
+ {
+ if (png_ptr->user_chunk_cache_max == 1)
+ {
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ if (--png_ptr->user_chunk_cache_max == 1)
+ {
+ png_warning(png_ptr, "No space in chunk cache for unknown chunk");
+ png_crc_finish(png_ptr, length);
+ return;
+ }
+ }
+#endif
+
+ if (png_ptr->mode & PNG_HAVE_IDAT)
+ {
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IDAT;
+#endif
+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ }
+
+ if (!(png_ptr->chunk_name[0] & 0x20))
+ {
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+ PNG_HANDLE_CHUNK_ALWAYS
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ && png_ptr->read_user_chunk_fn == NULL
+#endif
+ )
+#endif
+ png_chunk_error(png_ptr, "unknown critical chunk");
+ }
+
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ || (png_ptr->read_user_chunk_fn != NULL)
+#endif
+ )
+ {
+#ifdef PNG_MAX_MALLOC_64K
+ if (length > (png_uint_32)65535L)
+ {
+ png_warning(png_ptr, "unknown chunk too large to fit in memory");
+ skip = length - (png_uint_32)65535L;
+ length = (png_uint_32)65535L;
+ }
+#endif
+ png_memcpy((png_charp)png_ptr->unknown_chunk.name,
+ (png_charp)png_ptr->chunk_name,
+ png_sizeof(png_ptr->unknown_chunk.name));
+ png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
+ = '\0';
+ png_ptr->unknown_chunk.size = (png_size_t)length;
+ if (length == 0)
+ png_ptr->unknown_chunk.data = NULL;
+ else
+ {
+ png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
+ png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
+ }
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ if (png_ptr->read_user_chunk_fn != NULL)
+ {
+ /* Callback to user unknown chunk handler */
+ int ret;
+ ret = (*(png_ptr->read_user_chunk_fn))
+ (png_ptr, &png_ptr->unknown_chunk);
+ if (ret < 0)
+ png_chunk_error(png_ptr, "error in user chunk");
+ if (ret == 0)
+ {
+ if (!(png_ptr->chunk_name[0] & 0x20))
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
+ PNG_HANDLE_CHUNK_ALWAYS)
+#endif
+ png_chunk_error(png_ptr, "unknown critical chunk");
+ png_set_unknown_chunks(png_ptr, info_ptr,
+ &png_ptr->unknown_chunk, 1);
+ }
+ }
+ else
+#endif
+ png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+ }
+ else
+#endif
+ skip = length;
+
+ png_crc_finish(png_ptr, skip);
+
+#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
+ info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
+#endif
+}
+
+/* This function is called to verify that a chunk name is valid.
+ This function can't have the "critical chunk check" incorporated
+ into it, since in the future we will need to be able to call user
+ functions to handle unknown critical chunks after we check that
+ the chunk name itself is valid. */
+
+#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
+
+void /* PRIVATE */
+png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
+{
+ png_debug(1, "in png_check_chunk_name");
+ if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
+ isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
+ {
+ png_chunk_error(png_ptr, "invalid chunk type");
+ }
+}
+
+/* Combines the row recently read in with the existing pixels in the
+ row. This routine takes care of alpha and transparency if requested.
+ This routine also handles the two methods of progressive display
+ of interlaced images, depending on the mask value.
+ The mask value describes which pixels are to be combined with
+ the row. The pattern always repeats every 8 pixels, so just 8
+ bits are needed. A one indicates the pixel is to be combined,
+ a zero indicates the pixel is to be skipped. This is in addition
+ to any alpha or transparency value associated with the pixel. If
+ you want all pixels to be combined, pass 0xff (255) in mask. */
+
+void /* PRIVATE */
+png_combine_row(png_structp png_ptr, png_bytep row, int mask)
+{
+ png_debug(1, "in png_combine_row");
+ if (mask == 0xff)
+ {
+ png_memcpy(row, png_ptr->row_buf + 1,
+ PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
+ }
+ else
+ {
+ switch (png_ptr->row_info.pixel_depth)
+ {
+ case 1:
+ {
+ png_bytep sp = png_ptr->row_buf + 1;
+ png_bytep dp = row;
+ int s_inc, s_start, s_end;
+ int m = 0x80;
+ int shift;
+ png_uint_32 i;
+ png_uint_32 row_width = png_ptr->width;
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ {
+ s_start = 0;
+ s_end = 7;
+ s_inc = 1;
+ }
+ else
+#endif
+ {
+ s_start = 7;
+ s_end = 0;
+ s_inc = -1;
+ }
+
+ shift = s_start;
+
+ for (i = 0; i < row_width; i++)
+ {
+ if (m & mask)
+ {
+ int value;
+
+ value = (*sp >> shift) & 0x01;
+ *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
+ *dp |= (png_byte)(value << shift);
+ }
+
+ if (shift == s_end)
+ {
+ shift = s_start;
+ sp++;
+ dp++;
+ }
+ else
+ shift += s_inc;
+
+ if (m == 1)
+ m = 0x80;
+ else
+ m >>= 1;
+ }
+ break;
+ }
+ case 2:
+ {
+ png_bytep sp = png_ptr->row_buf + 1;
+ png_bytep dp = row;
+ int s_start, s_end, s_inc;
+ int m = 0x80;
+ int shift;
+ png_uint_32 i;
+ png_uint_32 row_width = png_ptr->width;
+ int value;
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ {
+ s_start = 0;
+ s_end = 6;
+ s_inc = 2;
+ }
+ else
+#endif
+ {
+ s_start = 6;
+ s_end = 0;
+ s_inc = -2;
+ }
+
+ shift = s_start;
+
+ for (i = 0; i < row_width; i++)
+ {
+ if (m & mask)
+ {
+ value = (*sp >> shift) & 0x03;
+ *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
+ *dp |= (png_byte)(value << shift);
+ }
+
+ if (shift == s_end)
+ {
+ shift = s_start;
+ sp++;
+ dp++;
+ }
+ else
+ shift += s_inc;
+ if (m == 1)
+ m = 0x80;
+ else
+ m >>= 1;
+ }
+ break;
+ }
+ case 4:
+ {
+ png_bytep sp = png_ptr->row_buf + 1;
+ png_bytep dp = row;
+ int s_start, s_end, s_inc;
+ int m = 0x80;
+ int shift;
+ png_uint_32 i;
+ png_uint_32 row_width = png_ptr->width;
+ int value;
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ {
+ s_start = 0;
+ s_end = 4;
+ s_inc = 4;
+ }
+ else
+#endif
+ {
+ s_start = 4;
+ s_end = 0;
+ s_inc = -4;
+ }
+ shift = s_start;
+
+ for (i = 0; i < row_width; i++)
+ {
+ if (m & mask)
+ {
+ value = (*sp >> shift) & 0xf;
+ *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
+ *dp |= (png_byte)(value << shift);
+ }
+
+ if (shift == s_end)
+ {
+ shift = s_start;
+ sp++;
+ dp++;
+ }
+ else
+ shift += s_inc;
+ if (m == 1)
+ m = 0x80;
+ else
+ m >>= 1;
+ }
+ break;
+ }
+ default:
+ {
+ png_bytep sp = png_ptr->row_buf + 1;
+ png_bytep dp = row;
+ png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
+ png_uint_32 i;
+ png_uint_32 row_width = png_ptr->width;
+ png_byte m = 0x80;
+
+
+ for (i = 0; i < row_width; i++)
+ {
+ if (m & mask)
+ {
+ png_memcpy(dp, sp, pixel_bytes);
+ }
+
+ sp += pixel_bytes;
+ dp += pixel_bytes;
+
+ if (m == 1)
+ m = 0x80;
+ else
+ m >>= 1;
+ }
+ break;
+ }
+ }
+ }
+}
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+/* OLD pre-1.0.9 interface:
+void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
+ png_uint_32 transformations)
+ */
+void /* PRIVATE */
+png_do_read_interlace(png_structp png_ptr)
+{
+ png_row_infop row_info = &(png_ptr->row_info);
+ png_bytep row = png_ptr->row_buf + 1;
+ int pass = png_ptr->pass;
+ png_uint_32 transformations = png_ptr->transformations;
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+ /* Offset to next interlace block */
+ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ png_debug(1, "in png_do_read_interlace");
+ if (row != NULL && row_info != NULL)
+ {
+ png_uint_32 final_width;
+
+ final_width = row_info->width * png_pass_inc[pass];
+
+ switch (row_info->pixel_depth)
+ {
+ case 1:
+ {
+ png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
+ png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
+ int sshift, dshift;
+ int s_start, s_end, s_inc;
+ int jstop = png_pass_inc[pass];
+ png_byte v;
+ png_uint_32 i;
+ int j;
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (transformations & PNG_PACKSWAP)
+ {
+ sshift = (int)((row_info->width + 7) & 0x07);
+ dshift = (int)((final_width + 7) & 0x07);
+ s_start = 7;
+ s_end = 0;
+ s_inc = -1;
+ }
+ else
+#endif
+ {
+ sshift = 7 - (int)((row_info->width + 7) & 0x07);
+ dshift = 7 - (int)((final_width + 7) & 0x07);
+ s_start = 0;
+ s_end = 7;
+ s_inc = 1;
+ }
+
+ for (i = 0; i < row_info->width; i++)
+ {
+ v = (png_byte)((*sp >> sshift) & 0x01);
+ for (j = 0; j < jstop; j++)
+ {
+ *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
+ *dp |= (png_byte)(v << dshift);
+ if (dshift == s_end)
+ {
+ dshift = s_start;
+ dp--;
+ }
+ else
+ dshift += s_inc;
+ }
+ if (sshift == s_end)
+ {
+ sshift = s_start;
+ sp--;
+ }
+ else
+ sshift += s_inc;
+ }
+ break;
+ }
+ case 2:
+ {
+ png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
+ png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
+ int sshift, dshift;
+ int s_start, s_end, s_inc;
+ int jstop = png_pass_inc[pass];
+ png_uint_32 i;
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (transformations & PNG_PACKSWAP)
+ {
+ sshift = (int)(((row_info->width + 3) & 0x03) << 1);
+ dshift = (int)(((final_width + 3) & 0x03) << 1);
+ s_start = 6;
+ s_end = 0;
+ s_inc = -2;
+ }
+ else
+#endif
+ {
+ sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
+ dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
+ s_start = 0;
+ s_end = 6;
+ s_inc = 2;
+ }
+
+ for (i = 0; i < row_info->width; i++)
+ {
+ png_byte v;
+ int j;
+
+ v = (png_byte)((*sp >> sshift) & 0x03);
+ for (j = 0; j < jstop; j++)
+ {
+ *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
+ *dp |= (png_byte)(v << dshift);
+ if (dshift == s_end)
+ {
+ dshift = s_start;
+ dp--;
+ }
+ else
+ dshift += s_inc;
+ }
+ if (sshift == s_end)
+ {
+ sshift = s_start;
+ sp--;
+ }
+ else
+ sshift += s_inc;
+ }
+ break;
+ }
+ case 4:
+ {
+ png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
+ png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
+ int sshift, dshift;
+ int s_start, s_end, s_inc;
+ png_uint_32 i;
+ int jstop = png_pass_inc[pass];
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if (transformations & PNG_PACKSWAP)
+ {
+ sshift = (int)(((row_info->width + 1) & 0x01) << 2);
+ dshift = (int)(((final_width + 1) & 0x01) << 2);
+ s_start = 4;
+ s_end = 0;
+ s_inc = -4;
+ }
+ else
+#endif
+ {
+ sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
+ dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
+ s_start = 0;
+ s_end = 4;
+ s_inc = 4;
+ }
+
+ for (i = 0; i < row_info->width; i++)
+ {
+ png_byte v = (png_byte)((*sp >> sshift) & 0xf);
+ int j;
+
+ for (j = 0; j < jstop; j++)
+ {
+ *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
+ *dp |= (png_byte)(v << dshift);
+ if (dshift == s_end)
+ {
+ dshift = s_start;
+ dp--;
+ }
+ else
+ dshift += s_inc;
+ }
+ if (sshift == s_end)
+ {
+ sshift = s_start;
+ sp--;
+ }
+ else
+ sshift += s_inc;
+ }
+ break;
+ }
+ default:
+ {
+ png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
+ png_bytep sp = row + (png_size_t)(row_info->width - 1)
+ * pixel_bytes;
+ png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
+
+ int jstop = png_pass_inc[pass];
+ png_uint_32 i;
+
+ for (i = 0; i < row_info->width; i++)
+ {
+ png_byte v[8];
+ int j;
+
+ png_memcpy(v, sp, pixel_bytes);
+ for (j = 0; j < jstop; j++)
+ {
+ png_memcpy(dp, v, pixel_bytes);
+ dp -= pixel_bytes;
+ }
+ sp -= pixel_bytes;
+ }
+ break;
+ }
+ }
+ row_info->width = final_width;
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
+ }
+#ifndef PNG_READ_PACKSWAP_SUPPORTED
+ transformations = transformations; /* Silence compiler warning */
+#endif
+}
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+void /* PRIVATE */
+png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
+ png_bytep prev_row, int filter)
+{
+ png_debug(1, "in png_read_filter_row");
+ png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
+ switch (filter)
+ {
+ case PNG_FILTER_VALUE_NONE:
+ break;
+ case PNG_FILTER_VALUE_SUB:
+ {
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+ png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+ png_bytep rp = row + bpp;
+ png_bytep lp = row;
+
+ for (i = bpp; i < istop; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
+ rp++;
+ }
+ break;
+ }
+ case PNG_FILTER_VALUE_UP:
+ {
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+ png_bytep rp = row;
+ png_bytep pp = prev_row;
+
+ for (i = 0; i < istop; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+ rp++;
+ }
+ break;
+ }
+ case PNG_FILTER_VALUE_AVG:
+ {
+ png_uint_32 i;
+ png_bytep rp = row;
+ png_bytep pp = prev_row;
+ png_bytep lp = row;
+ png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+ png_uint_32 istop = row_info->rowbytes - bpp;
+
+ for (i = 0; i < bpp; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) +
+ ((int)(*pp++) / 2 )) & 0xff);
+ rp++;
+ }
+
+ for (i = 0; i < istop; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) +
+ (int)(*pp++ + *lp++) / 2 ) & 0xff);
+ rp++;
+ }
+ break;
+ }
+ case PNG_FILTER_VALUE_PAETH:
+ {
+ png_uint_32 i;
+ png_bytep rp = row;
+ png_bytep pp = prev_row;
+ png_bytep lp = row;
+ png_bytep cp = prev_row;
+ png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
+ png_uint_32 istop=row_info->rowbytes - bpp;
+
+ for (i = 0; i < bpp; i++)
+ {
+ *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+ rp++;
+ }
+
+ for (i = 0; i < istop; i++) /* Use leftover rp,pp */
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ a = *lp++;
+ b = *pp++;
+ c = *cp++;
+
+ p = b - c;
+ pc = a - c;
+
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+ /*
+ if (pa <= pb && pa <= pc)
+ p = a;
+ else if (pb <= pc)
+ p = b;
+ else
+ p = c;
+ */
+
+ p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
+
+ *rp = (png_byte)(((int)(*rp) + p) & 0xff);
+ rp++;
+ }
+ break;
+ }
+ default:
+ png_warning(png_ptr, "Ignoring bad adaptive filter type");
+ *row = 0;
+ break;
+ }
+}
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+void /* PRIVATE */
+png_read_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+ png_debug(1, "in png_read_finish_row");
+ png_ptr->row_number++;
+ if (png_ptr->row_number < png_ptr->num_rows)
+ return;
+
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ if (png_ptr->interlaced)
+ {
+ png_ptr->row_number = 0;
+ png_memset_check(png_ptr, png_ptr->prev_row, 0,
+ png_ptr->rowbytes + 1);
+ do
+ {
+ png_ptr->pass++;
+ if (png_ptr->pass >= 7)
+ break;
+ png_ptr->iwidth = (png_ptr->width +
+ png_pass_inc[png_ptr->pass] - 1 -
+ png_pass_start[png_ptr->pass]) /
+ png_pass_inc[png_ptr->pass];
+
+ if (!(png_ptr->transformations & PNG_INTERLACE))
+ {
+ png_ptr->num_rows = (png_ptr->height +
+ png_pass_yinc[png_ptr->pass] - 1 -
+ png_pass_ystart[png_ptr->pass]) /
+ png_pass_yinc[png_ptr->pass];
+ if (!(png_ptr->num_rows))
+ continue;
+ }
+ else /* if (png_ptr->transformations & PNG_INTERLACE) */
+ break;
+ } while (png_ptr->iwidth == 0);
+
+ if (png_ptr->pass < 7)
+ return;
+ }
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ {
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_CONST PNG_IDAT;
+#endif
+ char extra;
+ int ret;
+
+ png_ptr->zstream.next_out = (Byte *)&extra;
+ png_ptr->zstream.avail_out = (uInt)1;
+ for (;;)
+ {
+ if (!(png_ptr->zstream.avail_in))
+ {
+ while (!png_ptr->idat_size)
+ {
+ png_byte chunk_length[4];
+
+ png_crc_finish(png_ptr, 0);
+
+ png_read_data(png_ptr, chunk_length, 4);
+ png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
+ png_reset_crc(png_ptr);
+ png_crc_read(png_ptr, png_ptr->chunk_name, 4);
+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
+ png_error(png_ptr, "Not enough image data");
+
+ }
+ png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_in = png_ptr->zbuf;
+ if (png_ptr->zbuf_size > png_ptr->idat_size)
+ png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
+ png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
+ png_ptr->idat_size -= png_ptr->zstream.avail_in;
+ }
+ ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
+ if (ret == Z_STREAM_END)
+ {
+ if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
+ png_ptr->idat_size)
+ png_warning(png_ptr, "Extra compressed data.");
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ break;
+ }
+ if (ret != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
+ "Decompression Error");
+
+ if (!(png_ptr->zstream.avail_out))
+ {
+ png_warning(png_ptr, "Extra compressed data.");
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ break;
+ }
+
+ }
+ png_ptr->zstream.avail_out = 0;
+ }
+
+ if (png_ptr->idat_size || png_ptr->zstream.avail_in)
+ png_warning(png_ptr, "Extra compression data.");
+
+ inflateReset(&png_ptr->zstream);
+
+ png_ptr->mode |= PNG_AFTER_IDAT;
+}
+#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+
+void /* PRIVATE */
+png_read_start_row(png_structp png_ptr)
+{
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+ int max_pixel_depth;
+ png_size_t row_bytes;
+
+ png_debug(1, "in png_read_start_row");
+ png_ptr->zstream.avail_in = 0;
+ png_init_read_transformations(png_ptr);
+#ifdef PNG_READ_INTERLACING_SUPPORTED
+ if (png_ptr->interlaced)
+ {
+ if (!(png_ptr->transformations & PNG_INTERLACE))
+ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+ png_pass_ystart[0]) / png_pass_yinc[0];
+ else
+ png_ptr->num_rows = png_ptr->height;
+
+ png_ptr->iwidth = (png_ptr->width +
+ png_pass_inc[png_ptr->pass] - 1 -
+ png_pass_start[png_ptr->pass]) /
+ png_pass_inc[png_ptr->pass];
+ }
+ else
+#endif /* PNG_READ_INTERLACING_SUPPORTED */
+ {
+ png_ptr->num_rows = png_ptr->height;
+ png_ptr->iwidth = png_ptr->width;
+ }
+ max_pixel_depth = png_ptr->pixel_depth;
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+ max_pixel_depth = 8;
+#endif
+
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if (png_ptr->transformations & PNG_EXPAND)
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (png_ptr->num_trans)
+ max_pixel_depth = 32;
+ else
+ max_pixel_depth = 24;
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ if (max_pixel_depth < 8)
+ max_pixel_depth = 8;
+ if (png_ptr->num_trans)
+ max_pixel_depth *= 2;
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ if (png_ptr->num_trans)
+ {
+ max_pixel_depth *= 4;
+ max_pixel_depth /= 3;
+ }
+ }
+ }
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ if (png_ptr->transformations & (PNG_FILLER))
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ max_pixel_depth = 32;
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ if (max_pixel_depth <= 8)
+ max_pixel_depth = 16;
+ else
+ max_pixel_depth = 32;
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ if (max_pixel_depth <= 32)
+ max_pixel_depth = 32;
+ else
+ max_pixel_depth = 64;
+ }
+ }
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ {
+ if (
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+#endif
+#ifdef PNG_READ_FILLER_SUPPORTED
+ (png_ptr->transformations & (PNG_FILLER)) ||
+#endif
+ png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ if (max_pixel_depth <= 16)
+ max_pixel_depth = 32;
+ else
+ max_pixel_depth = 64;
+ }
+ else
+ {
+ if (max_pixel_depth <= 8)
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ max_pixel_depth = 32;
+ else
+ max_pixel_depth = 24;
+ }
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ max_pixel_depth = 64;
+ else
+ max_pixel_depth = 48;
+ }
+ }
+#endif
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
+defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
+ if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ {
+ int user_pixel_depth = png_ptr->user_transform_depth*
+ png_ptr->user_transform_channels;
+ if (user_pixel_depth > max_pixel_depth)
+ max_pixel_depth=user_pixel_depth;
+ }
+#endif
+
+ /* Align the width on the next larger 8 pixels. Mainly used
+ * for interlacing
+ */
+ row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
+ /* Calculate the maximum bytes needed, adding a byte and a pixel
+ * for safety's sake
+ */
+ row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
+ 1 + ((max_pixel_depth + 7) >> 3);
+#ifdef PNG_MAX_MALLOC_64K
+ if (row_bytes > (png_uint_32)65536L)
+ png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+
+ if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
+ {
+ png_free(png_ptr, png_ptr->big_row_buf);
+ if (png_ptr->interlaced)
+ png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
+ row_bytes + 64);
+ else
+ png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
+ row_bytes + 64);
+ png_ptr->old_big_row_buf_size = row_bytes + 64;
+
+ /* Use 32 bytes of padding before and after row_buf. */
+ png_ptr->row_buf = png_ptr->big_row_buf + 32;
+ png_ptr->old_big_row_buf_size = row_bytes + 64;
+ }
+
+#ifdef PNG_MAX_MALLOC_64K
+ if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
+ png_error(png_ptr, "This image requires a row greater than 64KB");
+#endif
+ if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
+ png_error(png_ptr, "Row has too many bytes to allocate in memory.");
+
+ if (row_bytes + 1 > png_ptr->old_prev_row_size)
+ {
+ png_free(png_ptr, png_ptr->prev_row);
+ png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
+ row_bytes + 1));
+ png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
+ png_ptr->old_prev_row_size = row_bytes + 1;
+ }
+
+ png_ptr->rowbytes = row_bytes;
+
+ png_debug1(3, "width = %lu,", png_ptr->width);
+ png_debug1(3, "height = %lu,", png_ptr->height);
+ png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
+ png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
+ png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
+ png_debug1(3, "irowbytes = %lu",
+ PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
+
+ png_ptr->flags |= PNG_FLAG_ROW_INIT;
+}
+#endif /* PNG_READ_SUPPORTED */
diff --git a/Source/LibPNG/pngset.c b/Source/LibPNG/pngset.c
new file mode 100644
index 0000000..c9ab8f6
--- /dev/null
+++ b/Source/LibPNG/pngset.c
@@ -0,0 +1,1236 @@
+
+/* pngset.c - storage of image information into info struct
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * The functions here are used during reads to store data from the file
+ * into the info struct, and during writes to store application data
+ * into the info struct for writing into the file. This abstracts the
+ * info struct and allows us to change the structure in the future.
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
+#ifdef PNG_bKGD_SUPPORTED
+void PNGAPI
+png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
+{
+ png_debug1(1, "in %s storage function", "bKGD");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
+ info_ptr->valid |= PNG_INFO_bKGD;
+}
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+ double white_x, double white_y, double red_x, double red_y,
+ double green_x, double green_y, double blue_x, double blue_y)
+{
+ png_debug1(1, "in %s storage function", "cHRM");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->x_white = (float)white_x;
+ info_ptr->y_white = (float)white_y;
+ info_ptr->x_red = (float)red_x;
+ info_ptr->y_red = (float)red_y;
+ info_ptr->x_green = (float)green_x;
+ info_ptr->y_green = (float)green_y;
+ info_ptr->x_blue = (float)blue_x;
+ info_ptr->y_blue = (float)blue_y;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);
+ info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);
+ info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5);
+ info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5);
+ info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);
+ info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);
+ info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5);
+ info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5);
+#endif
+ info_ptr->valid |= PNG_INFO_cHRM;
+}
+#endif /* PNG_FLOATING_POINT_SUPPORTED */
+
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+ png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
+ png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
+ png_fixed_point blue_x, png_fixed_point blue_y)
+{
+ png_debug1(1, "in %s storage function", "cHRM fixed");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+ if (png_check_cHRM_fixed(png_ptr,
+ white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
+#endif
+ {
+ info_ptr->int_x_white = white_x;
+ info_ptr->int_y_white = white_y;
+ info_ptr->int_x_red = red_x;
+ info_ptr->int_y_red = red_y;
+ info_ptr->int_x_green = green_x;
+ info_ptr->int_y_green = green_y;
+ info_ptr->int_x_blue = blue_x;
+ info_ptr->int_y_blue = blue_y;
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ info_ptr->x_white = (float)(white_x/100000.);
+ info_ptr->y_white = (float)(white_y/100000.);
+ info_ptr->x_red = (float)( red_x/100000.);
+ info_ptr->y_red = (float)( red_y/100000.);
+ info_ptr->x_green = (float)(green_x/100000.);
+ info_ptr->y_green = (float)(green_y/100000.);
+ info_ptr->x_blue = (float)( blue_x/100000.);
+ info_ptr->y_blue = (float)( blue_y/100000.);
+#endif
+ info_ptr->valid |= PNG_INFO_cHRM;
+ }
+}
+#endif /* PNG_FIXED_POINT_SUPPORTED */
+#endif /* PNG_cHRM_SUPPORTED */
+
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+{
+ double png_gamma;
+
+ png_debug1(1, "in %s storage function", "gAMA");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ /* Check for overflow */
+ if (file_gamma > 21474.83)
+ {
+ png_warning(png_ptr, "Limiting gamma to 21474.83");
+ png_gamma=21474.83;
+ }
+ else
+ png_gamma = file_gamma;
+ info_ptr->gamma = (float)png_gamma;
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ info_ptr->int_gamma = (int)(png_gamma*100000.+.5);
+#endif
+ info_ptr->valid |= PNG_INFO_gAMA;
+ if (png_gamma == 0.0)
+ png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+void PNGAPI
+png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
+ int_gamma)
+{
+ png_fixed_point png_gamma;
+
+ png_debug1(1, "in %s storage function", "gAMA");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (int_gamma > (png_fixed_point)PNG_UINT_31_MAX)
+ {
+ png_warning(png_ptr, "Limiting gamma to 21474.83");
+ png_gamma=PNG_UINT_31_MAX;
+ }
+ else
+ {
+ if (int_gamma < 0)
+ {
+ png_warning(png_ptr, "Setting negative gamma to zero");
+ png_gamma = 0;
+ }
+ else
+ png_gamma = int_gamma;
+ }
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ info_ptr->gamma = (float)(png_gamma/100000.);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ info_ptr->int_gamma = png_gamma;
+#endif
+ info_ptr->valid |= PNG_INFO_gAMA;
+ if (png_gamma == 0)
+ png_warning(png_ptr, "Setting gamma=0");
+}
+#endif
+
+#ifdef PNG_hIST_SUPPORTED
+void PNGAPI
+png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
+{
+ int i;
+
+ png_debug1(1, "in %s storage function", "hIST");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (info_ptr->num_palette == 0 || info_ptr->num_palette
+ > PNG_MAX_PALETTE_LENGTH)
+ {
+ png_warning(png_ptr,
+ "Invalid palette size, hIST allocation skipped.");
+ return;
+ }
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
+#endif
+ /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
+ * version 1.2.1
+ */
+ png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
+ (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)));
+ if (png_ptr->hist == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for hIST chunk data.");
+ return;
+ }
+
+ for (i = 0; i < info_ptr->num_palette; i++)
+ png_ptr->hist[i] = hist[i];
+ info_ptr->hist = png_ptr->hist;
+ info_ptr->valid |= PNG_INFO_hIST;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_HIST;
+#else
+ png_ptr->flags |= PNG_FLAG_FREE_HIST;
+#endif
+}
+#endif
+
+void PNGAPI
+png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_type, int compression_type,
+ int filter_type)
+{
+ png_debug1(1, "in %s storage function", "IHDR");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->width = width;
+ info_ptr->height = height;
+ info_ptr->bit_depth = (png_byte)bit_depth;
+ info_ptr->color_type = (png_byte)color_type;
+ info_ptr->compression_type = (png_byte)compression_type;
+ info_ptr->filter_type = (png_byte)filter_type;
+ info_ptr->interlace_type = (png_byte)interlace_type;
+
+ png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+ info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
+ info_ptr->compression_type, info_ptr->filter_type);
+
+ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ info_ptr->channels = 1;
+ else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ info_ptr->channels = 3;
+ else
+ info_ptr->channels = 1;
+ if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ info_ptr->channels++;
+ info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
+
+ /* Check for potential overflow */
+ if (width > (PNG_UINT_32_MAX
+ >> 3) /* 8-byte RGBA pixels */
+ - 64 /* bigrowbuf hack */
+ - 1 /* filter byte */
+ - 7*8 /* rounding of width to multiple of 8 pixels */
+ - 8) /* extra max_pixel_depth pad */
+ info_ptr->rowbytes = (png_size_t)0;
+ else
+ info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
+}
+
+#ifdef PNG_oFFs_SUPPORTED
+void PNGAPI
+png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
+ png_int_32 offset_x, png_int_32 offset_y, int unit_type)
+{
+ png_debug1(1, "in %s storage function", "oFFs");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->x_offset = offset_x;
+ info_ptr->y_offset = offset_y;
+ info_ptr->offset_unit_type = (png_byte)unit_type;
+ info_ptr->valid |= PNG_INFO_oFFs;
+}
+#endif
+
+#ifdef PNG_pCAL_SUPPORTED
+void PNGAPI
+png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+ png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+ png_charp units, png_charpp params)
+{
+ png_uint_32 length;
+ int i;
+
+ png_debug1(1, "in %s storage function", "pCAL");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ length = png_strlen(purpose) + 1;
+ png_debug1(3, "allocating purpose for info (%lu bytes)",
+ (unsigned long)length);
+ info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
+ if (info_ptr->pcal_purpose == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
+ return;
+ }
+ png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
+
+ png_debug(3, "storing X0, X1, type, and nparams in info");
+ info_ptr->pcal_X0 = X0;
+ info_ptr->pcal_X1 = X1;
+ info_ptr->pcal_type = (png_byte)type;
+ info_ptr->pcal_nparams = (png_byte)nparams;
+
+ length = png_strlen(units) + 1;
+ png_debug1(3, "allocating units for info (%lu bytes)",
+ (unsigned long)length);
+ info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
+ if (info_ptr->pcal_units == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for pCAL units.");
+ return;
+ }
+ png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
+
+ info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
+ (png_uint_32)((nparams + 1) * png_sizeof(png_charp)));
+ if (info_ptr->pcal_params == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for pCAL params.");
+ return;
+ }
+
+ png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
+
+ for (i = 0; i < nparams; i++)
+ {
+ length = png_strlen(params[i]) + 1;
+ png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
+ (unsigned long)length);
+ info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
+ if (info_ptr->pcal_params[i] == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory for pCAL parameter.");
+ return;
+ }
+ png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
+ }
+
+ info_ptr->valid |= PNG_INFO_pCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_PCAL;
+#endif
+}
+#endif
+
+#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
+ int unit, double width, double height)
+{
+ png_debug1(1, "in %s storage function", "sCAL");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->scal_unit = (png_byte)unit;
+ info_ptr->scal_pixel_width = width;
+ info_ptr->scal_pixel_height = height;
+
+ info_ptr->valid |= PNG_INFO_sCAL;
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void PNGAPI
+png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+ int unit, png_charp swidth, png_charp sheight)
+{
+ png_uint_32 length;
+
+ png_debug1(1, "in %s storage function", "sCAL");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->scal_unit = (png_byte)unit;
+
+ length = png_strlen(swidth) + 1;
+ png_debug1(3, "allocating unit for info (%u bytes)",
+ (unsigned int)length);
+ info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);
+ if (info_ptr->scal_s_width == NULL)
+ {
+ png_warning(png_ptr,
+ "Memory allocation failed while processing sCAL.");
+ return;
+ }
+ png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
+
+ length = png_strlen(sheight) + 1;
+ png_debug1(3, "allocating unit for info (%u bytes)",
+ (unsigned int)length);
+ info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length);
+ if (info_ptr->scal_s_height == NULL)
+ {
+ png_free (png_ptr, info_ptr->scal_s_width);
+ info_ptr->scal_s_width = NULL;
+ png_warning(png_ptr,
+ "Memory allocation failed while processing sCAL.");
+ return;
+ }
+ png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
+ info_ptr->valid |= PNG_INFO_sCAL;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_SCAL;
+#endif
+}
+#endif
+#endif
+#endif
+
+#ifdef PNG_pHYs_SUPPORTED
+void PNGAPI
+png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+ png_uint_32 res_x, png_uint_32 res_y, int unit_type)
+{
+ png_debug1(1, "in %s storage function", "pHYs");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->x_pixels_per_unit = res_x;
+ info_ptr->y_pixels_per_unit = res_y;
+ info_ptr->phys_unit_type = (png_byte)unit_type;
+ info_ptr->valid |= PNG_INFO_pHYs;
+}
+#endif
+
+void PNGAPI
+png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+ png_colorp palette, int num_palette)
+{
+
+ png_debug1(1, "in %s storage function", "PLTE");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
+ {
+ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ png_error(png_ptr, "Invalid palette length");
+ else
+ {
+ png_warning(png_ptr, "Invalid palette length");
+ return;
+ }
+ }
+
+ /* It may not actually be necessary to set png_ptr->palette here;
+ * we do it for backward compatibility with the way the png_handle_tRNS
+ * function used to do the allocation.
+ */
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
+#endif
+
+ /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
+ * of num_palette entries, in case of an invalid PNG file that has
+ * too-large sample values.
+ */
+ png_ptr->palette = (png_colorp)png_calloc(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
+ png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
+ info_ptr->palette = png_ptr->palette;
+ info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_PLTE;
+#else
+ png_ptr->flags |= PNG_FLAG_FREE_PLTE;
+#endif
+
+ info_ptr->valid |= PNG_INFO_PLTE;
+}
+
+#ifdef PNG_sBIT_SUPPORTED
+void PNGAPI
+png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+ png_color_8p sig_bit)
+{
+ png_debug1(1, "in %s storage function", "sBIT");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
+ info_ptr->valid |= PNG_INFO_sBIT;
+}
+#endif
+
+#ifdef PNG_sRGB_SUPPORTED
+void PNGAPI
+png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
+{
+ png_debug1(1, "in %s storage function", "sRGB");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ info_ptr->srgb_intent = (png_byte)intent;
+ info_ptr->valid |= PNG_INFO_sRGB;
+}
+
+void PNGAPI
+png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+ int intent)
+{
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float file_gamma;
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_fixed_point int_file_gamma;
+#endif
+#endif
+#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
+#endif
+ png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+ int_green_y, int_blue_x, int_blue_y;
+#endif
+ png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ png_set_sRGB(png_ptr, info_ptr, intent);
+
+#ifdef PNG_gAMA_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ file_gamma = (float).45455;
+ png_set_gAMA(png_ptr, info_ptr, file_gamma);
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ int_file_gamma = 45455L;
+ png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
+#endif
+#endif
+
+#ifdef PNG_cHRM_SUPPORTED
+ int_white_x = 31270L;
+ int_white_y = 32900L;
+ int_red_x = 64000L;
+ int_red_y = 33000L;
+ int_green_x = 30000L;
+ int_green_y = 60000L;
+ int_blue_x = 15000L;
+ int_blue_y = 6000L;
+
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ white_x = (float).3127;
+ white_y = (float).3290;
+ red_x = (float).64;
+ red_y = (float).33;
+ green_x = (float).30;
+ green_y = (float).60;
+ blue_x = (float).15;
+ blue_y = (float).06;
+#endif
+
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_set_cHRM_fixed(png_ptr, info_ptr,
+ int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
+ int_green_y, int_blue_x, int_blue_y);
+#endif
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_set_cHRM(png_ptr, info_ptr,
+ white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
+#endif
+#endif /* cHRM */
+}
+#endif /* sRGB */
+
+
+#ifdef PNG_iCCP_SUPPORTED
+void PNGAPI
+png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+ png_charp name, int compression_type,
+ png_charp profile, png_uint_32 proflen)
+{
+ png_charp new_iccp_name;
+ png_charp new_iccp_profile;
+ png_uint_32 length;
+
+ png_debug1(1, "in %s storage function", "iCCP");
+
+ if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
+ return;
+
+ length = png_strlen(name)+1;
+ new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
+ if (new_iccp_name == NULL)
+ {
+ png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");
+ return;
+ }
+ png_memcpy(new_iccp_name, name, length);
+ new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen);
+ if (new_iccp_profile == NULL)
+ {
+ png_free (png_ptr, new_iccp_name);
+ png_warning(png_ptr,
+ "Insufficient memory to process iCCP profile.");
+ return;
+ }
+ png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
+
+ info_ptr->iccp_proflen = proflen;
+ info_ptr->iccp_name = new_iccp_name;
+ info_ptr->iccp_profile = new_iccp_profile;
+ /* Compression is always zero but is here so the API and info structure
+ * does not have to change if we introduce multiple compression types
+ */
+ info_ptr->iccp_compression = (png_byte)compression_type;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_ICCP;
+#endif
+ info_ptr->valid |= PNG_INFO_iCCP;
+}
+#endif
+
+#ifdef PNG_TEXT_SUPPORTED
+void PNGAPI
+png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
+ int num_text)
+{
+ int ret;
+ ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
+ if (ret)
+ png_error(png_ptr, "Insufficient memory to store text");
+}
+
+int /* PRIVATE */
+png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
+ int num_text)
+{
+ int i;
+
+ png_debug1(1, "in %s storage function", ((png_ptr == NULL ||
+ png_ptr->chunk_name[0] == '\0') ?
+ "text" : (png_const_charp)png_ptr->chunk_name));
+
+ if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+ return(0);
+
+ /* Make sure we have enough space in the "text" array in info_struct
+ * to hold all of the incoming text_ptr objects.
+ */
+ if (info_ptr->num_text + num_text > info_ptr->max_text)
+ {
+ int old_max_text = info_ptr->max_text;
+ int old_num_text = info_ptr->num_text;
+
+ if (info_ptr->text != NULL)
+ {
+ png_textp old_text;
+
+ info_ptr->max_text = info_ptr->num_text + num_text + 8;
+ old_text = info_ptr->text;
+
+ info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
+ (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
+ if (info_ptr->text == NULL)
+ {
+ /* Restore to previous condition */
+ info_ptr->max_text = old_max_text;
+ info_ptr->text = old_text;
+ return(1);
+ }
+ png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
+ png_sizeof(png_text)));
+ png_free(png_ptr, old_text);
+ }
+ else
+ {
+ info_ptr->max_text = num_text + 8;
+ info_ptr->num_text = 0;
+ info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
+ (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));
+ if (info_ptr->text == NULL)
+ {
+ /* Restore to previous condition */
+ info_ptr->num_text = old_num_text;
+ info_ptr->max_text = old_max_text;
+ return(1);
+ }
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_TEXT;
+#endif
+ }
+ png_debug1(3, "allocated %d entries for info_ptr->text",
+ info_ptr->max_text);
+ }
+
+ for (i = 0; i < num_text; i++)
+ {
+ png_size_t text_length, key_len;
+ png_size_t lang_len, lang_key_len;
+ png_textp textp = &(info_ptr->text[info_ptr->num_text]);
+
+ if (text_ptr[i].key == NULL)
+ continue;
+
+ key_len = png_strlen(text_ptr[i].key);
+
+ if (text_ptr[i].compression <= 0)
+ {
+ lang_len = 0;
+ lang_key_len = 0;
+ }
+
+ else
+#ifdef PNG_iTXt_SUPPORTED
+ {
+ /* Set iTXt data */
+
+ if (text_ptr[i].lang != NULL)
+ lang_len = png_strlen(text_ptr[i].lang);
+ else
+ lang_len = 0;
+ if (text_ptr[i].lang_key != NULL)
+ lang_key_len = png_strlen(text_ptr[i].lang_key);
+ else
+ lang_key_len = 0;
+ }
+#else /* PNG_iTXt_SUPPORTED */
+ {
+ png_warning(png_ptr, "iTXt chunk not supported.");
+ continue;
+ }
+#endif
+
+ if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
+ {
+ text_length = 0;
+#ifdef PNG_iTXt_SUPPORTED
+ if (text_ptr[i].compression > 0)
+ textp->compression = PNG_ITXT_COMPRESSION_NONE;
+ else
+#endif
+ textp->compression = PNG_TEXT_COMPRESSION_NONE;
+ }
+
+ else
+ {
+ text_length = png_strlen(text_ptr[i].text);
+ textp->compression = text_ptr[i].compression;
+ }
+
+ textp->key = (png_charp)png_malloc_warn(png_ptr,
+ (png_uint_32)
+ (key_len + text_length + lang_len + lang_key_len + 4));
+ if (textp->key == NULL)
+ return(1);
+ png_debug2(2, "Allocated %lu bytes at %x in png_set_text",
+ (png_uint_32)
+ (key_len + lang_len + lang_key_len + text_length + 4),
+ (int)textp->key);
+
+ png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
+ *(textp->key + key_len) = '\0';
+#ifdef PNG_iTXt_SUPPORTED
+ if (text_ptr[i].compression > 0)
+ {
+ textp->lang = textp->key + key_len + 1;
+ png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
+ *(textp->lang + lang_len) = '\0';
+ textp->lang_key = textp->lang + lang_len + 1;
+ png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+ *(textp->lang_key + lang_key_len) = '\0';
+ textp->text = textp->lang_key + lang_key_len + 1;
+ }
+ else
+#endif
+ {
+#ifdef PNG_iTXt_SUPPORTED
+ textp->lang=NULL;
+ textp->lang_key=NULL;
+#endif
+ textp->text = textp->key + key_len + 1;
+ }
+ if (text_length)
+ png_memcpy(textp->text, text_ptr[i].text,
+ (png_size_t)(text_length));
+ *(textp->text + text_length) = '\0';
+
+#ifdef PNG_iTXt_SUPPORTED
+ if (textp->compression > 0)
+ {
+ textp->text_length = 0;
+ textp->itxt_length = text_length;
+ }
+ else
+#endif
+
+ {
+ textp->text_length = text_length;
+#ifdef PNG_iTXt_SUPPORTED
+ textp->itxt_length = 0;
+#endif
+ }
+ info_ptr->num_text++;
+ png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
+ }
+ return(0);
+}
+#endif
+
+#ifdef PNG_tIME_SUPPORTED
+void PNGAPI
+png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
+{
+ png_debug1(1, "in %s storage function", "tIME");
+
+ if (png_ptr == NULL || info_ptr == NULL ||
+ (png_ptr->mode & PNG_WROTE_tIME))
+ return;
+
+ png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
+ info_ptr->valid |= PNG_INFO_tIME;
+}
+#endif
+
+#ifdef PNG_tRNS_SUPPORTED
+void PNGAPI
+png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
+ png_bytep trans, int num_trans, png_color_16p trans_values)
+{
+ png_debug1(1, "in %s storage function", "tRNS");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (trans != NULL)
+ {
+ /* It may not actually be necessary to set png_ptr->trans here;
+ * we do it for backward compatibility with the way the png_handle_tRNS
+ * function used to do the allocation.
+ */
+
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
+#endif
+
+ /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
+ png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)PNG_MAX_PALETTE_LENGTH);
+ if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+ png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
+ }
+
+ if (trans_values != NULL)
+ {
+ int sample_max = (1 << info_ptr->bit_depth);
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+ (int)trans_values->gray > sample_max) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ ((int)trans_values->red > sample_max ||
+ (int)trans_values->green > sample_max ||
+ (int)trans_values->blue > sample_max)))
+ png_warning(png_ptr,
+ "tRNS chunk has out-of-range samples for bit_depth");
+ png_memcpy(&(info_ptr->trans_values), trans_values,
+ png_sizeof(png_color_16));
+ if (num_trans == 0)
+ num_trans = 1;
+ }
+
+ info_ptr->num_trans = (png_uint_16)num_trans;
+ if (num_trans != 0)
+ {
+ info_ptr->valid |= PNG_INFO_tRNS;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_TRNS;
+#else
+ png_ptr->flags |= PNG_FLAG_FREE_TRNS;
+#endif
+ }
+}
+#endif
+
+#ifdef PNG_sPLT_SUPPORTED
+void PNGAPI
+png_set_sPLT(png_structp png_ptr,
+ png_infop info_ptr, png_sPLT_tp entries, int nentries)
+/*
+ * entries - array of png_sPLT_t structures
+ * to be added to the list of palettes
+ * in the info structure.
+ * nentries - number of palette structures to be
+ * added.
+ */
+{
+ png_sPLT_tp np;
+ int i;
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ np = (png_sPLT_tp)png_malloc_warn(png_ptr,
+ (info_ptr->splt_palettes_num + nentries) *
+ (png_uint_32)png_sizeof(png_sPLT_t));
+ if (np == NULL)
+ {
+ png_warning(png_ptr, "No memory for sPLT palettes.");
+ return;
+ }
+
+ png_memcpy(np, info_ptr->splt_palettes,
+ info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
+ png_free(png_ptr, info_ptr->splt_palettes);
+ info_ptr->splt_palettes=NULL;
+
+ for (i = 0; i < nentries; i++)
+ {
+ png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
+ png_sPLT_tp from = entries + i;
+ png_uint_32 length;
+
+ length = png_strlen(from->name) + 1;
+ to->name = (png_charp)png_malloc_warn(png_ptr, length);
+ if (to->name == NULL)
+ {
+ png_warning(png_ptr,
+ "Out of memory while processing sPLT chunk");
+ continue;
+ }
+ png_memcpy(to->name, from->name, length);
+ to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
+ (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry)));
+ if (to->entries == NULL)
+ {
+ png_warning(png_ptr,
+ "Out of memory while processing sPLT chunk");
+ png_free(png_ptr, to->name);
+ to->name = NULL;
+ continue;
+ }
+ png_memcpy(to->entries, from->entries,
+ from->nentries * png_sizeof(png_sPLT_entry));
+ to->nentries = from->nentries;
+ to->depth = from->depth;
+ }
+
+ info_ptr->splt_palettes = np;
+ info_ptr->splt_palettes_num += nentries;
+ info_ptr->valid |= PNG_INFO_sPLT;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_SPLT;
+#endif
+}
+#endif /* PNG_sPLT_SUPPORTED */
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+void PNGAPI
+png_set_unknown_chunks(png_structp png_ptr,
+ png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
+{
+ png_unknown_chunkp np;
+ int i;
+
+ if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+ return;
+
+ np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
+ (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) *
+ png_sizeof(png_unknown_chunk)));
+ if (np == NULL)
+ {
+ png_warning(png_ptr,
+ "Out of memory while processing unknown chunk.");
+ return;
+ }
+
+ png_memcpy(np, info_ptr->unknown_chunks,
+ info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
+ png_free(png_ptr, info_ptr->unknown_chunks);
+ info_ptr->unknown_chunks = NULL;
+
+ for (i = 0; i < num_unknowns; i++)
+ {
+ png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
+ png_unknown_chunkp from = unknowns + i;
+
+ png_memcpy((png_charp)to->name, (png_charp)from->name,
+ png_sizeof(from->name));
+ to->name[png_sizeof(to->name)-1] = '\0';
+ to->size = from->size;
+ /* Note our location in the read or write sequence */
+ to->location = (png_byte)(png_ptr->mode & 0xff);
+
+ if (from->size == 0)
+ to->data=NULL;
+ else
+ {
+ to->data = (png_bytep)png_malloc_warn(png_ptr,
+ (png_uint_32)from->size);
+ if (to->data == NULL)
+ {
+ png_warning(png_ptr,
+ "Out of memory while processing unknown chunk.");
+ to->size = 0;
+ }
+ else
+ png_memcpy(to->data, from->data, from->size);
+ }
+ }
+
+ info_ptr->unknown_chunks = np;
+ info_ptr->unknown_chunks_num += num_unknowns;
+#ifdef PNG_FREE_ME_SUPPORTED
+ info_ptr->free_me |= PNG_FREE_UNKN;
+#endif
+}
+void PNGAPI
+png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+ int chunk, int location)
+{
+ if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
+ (int)info_ptr->unknown_chunks_num)
+ info_ptr->unknown_chunks[chunk].location = (png_byte)location;
+}
+#endif
+
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
+ defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
+void PNGAPI
+png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
+{
+ /* This function is deprecated in favor of png_permit_mng_features()
+ and will be removed from libpng-1.3.0 */
+
+ png_debug(1, "in png_permit_empty_plte, DEPRECATED.");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->mng_features_permitted = (png_byte)
+ ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) |
+ ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
+}
+#endif
+#endif
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+png_uint_32 PNGAPI
+png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
+{
+ png_debug(1, "in png_permit_mng_features");
+
+ if (png_ptr == NULL)
+ return (png_uint_32)0;
+ png_ptr->mng_features_permitted =
+ (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+ return (png_uint_32)png_ptr->mng_features_permitted;
+}
+#endif
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+void PNGAPI
+png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
+ chunk_list, int num_chunks)
+{
+ png_bytep new_list, p;
+ int i, old_num_chunks;
+ if (png_ptr == NULL)
+ return;
+ if (num_chunks == 0)
+ {
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
+ png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+ else
+ png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS)
+ png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ else
+ png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ return;
+ }
+ if (chunk_list == NULL)
+ return;
+ old_num_chunks = png_ptr->num_chunk_list;
+ new_list=(png_bytep)png_malloc(png_ptr,
+ (png_uint_32)
+ (5*(num_chunks + old_num_chunks)));
+ if (png_ptr->chunk_list != NULL)
+ {
+ png_memcpy(new_list, png_ptr->chunk_list,
+ (png_size_t)(5*old_num_chunks));
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list=NULL;
+ }
+ png_memcpy(new_list + 5*old_num_chunks, chunk_list,
+ (png_size_t)(5*num_chunks));
+ for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
+ *p=(png_byte)keep;
+ png_ptr->num_chunk_list = old_num_chunks + num_chunks;
+ png_ptr->chunk_list = new_list;
+#ifdef PNG_FREE_ME_SUPPORTED
+ png_ptr->free_me |= PNG_FREE_LIST;
+#endif
+}
+#endif
+
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+void PNGAPI
+png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
+ png_user_chunk_ptr read_user_chunk_fn)
+{
+ png_debug(1, "in png_set_read_user_chunk_fn");
+
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->read_user_chunk_fn = read_user_chunk_fn;
+ png_ptr->user_chunk_ptr = user_chunk_ptr;
+}
+#endif
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+void PNGAPI
+png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+{
+ png_debug1(1, "in %s storage function", "rows");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
+ info_ptr->row_pointers = row_pointers;
+ if (row_pointers)
+ info_ptr->valid |= PNG_INFO_IDAT;
+}
+#endif
+
+void PNGAPI
+png_set_compression_buffer_size(png_structp png_ptr,
+ png_uint_32 size)
+{
+ if (png_ptr == NULL)
+ return;
+ png_free(png_ptr, png_ptr->zbuf);
+ png_ptr->zbuf_size = (png_size_t)size;
+ png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+}
+
+void PNGAPI
+png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+{
+ if (png_ptr && info_ptr)
+ info_ptr->valid &= ~mask;
+}
+
+
+#ifndef PNG_1_0_X
+#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
+/* Function was added to libpng 1.2.0 and should always exist by default */
+void PNGAPI
+png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
+{
+/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
+ if (png_ptr != NULL)
+ png_ptr->asm_flags = 0;
+ asm_flags = asm_flags; /* Quiet the compiler */
+}
+
+/* This function was added to libpng 1.2.0 */
+void PNGAPI
+png_set_mmx_thresholds (png_structp png_ptr,
+ png_byte mmx_bitdepth_threshold,
+ png_uint_32 mmx_rowbytes_threshold)
+{
+/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
+ if (png_ptr == NULL)
+ return;
+ /* Quiet the compiler */
+ mmx_bitdepth_threshold = mmx_bitdepth_threshold;
+ mmx_rowbytes_threshold = mmx_rowbytes_threshold;
+}
+#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
+
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+/* This function was added to libpng 1.2.6 */
+void PNGAPI
+png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
+ png_uint_32 user_height_max)
+{
+ /* Images with dimensions larger than these limits will be
+ * rejected by png_set_IHDR(). To accept any PNG datastream
+ * regardless of dimensions, set both limits to 0x7ffffffL.
+ */
+ if (png_ptr == NULL)
+ return;
+ png_ptr->user_width_max = user_width_max;
+ png_ptr->user_height_max = user_height_max;
+}
+#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+
+
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+void PNGAPI
+png_set_benign_errors(png_structp png_ptr, int allowed)
+{
+ png_debug(1, "in png_set_benign_errors");
+
+ if (allowed)
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+ else
+ png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
+}
+#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
+#endif /* ?PNG_1_0_X */
+#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngtest.c b/Source/LibPNG/pngtest.c
new file mode 100644
index 0000000..1b5a5f9
--- /dev/null
+++ b/Source/LibPNG/pngtest.c
@@ -0,0 +1,1705 @@
+
+/* pngtest.c - a simple test program to test libpng
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This program reads in a PNG image, writes it out again, and then
+ * compares the two files. If the files are identical, this shows that
+ * the basic chunk handling, filtering, and (de)compression code is working
+ * properly. It does not currently test all of the transforms, although
+ * it probably should.
+ *
+ * The program will report "FAIL" in certain legitimate cases:
+ * 1) when the compression level or filter selection method is changed.
+ * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
+ * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks
+ * exist in the input file.
+ * 4) others not listed here...
+ * In these cases, it is best to check with another tool such as "pngcheck"
+ * to see what the differences between the two files are.
+ *
+ * If a filename is given on the command-line, then this file is used
+ * for the input, rather than the default "pngtest.png". This allows
+ * testing a wide variety of files easily. You can also test a number
+ * of files at once by typing "pngtest -m file1.png file2.png ..."
+ */
+
+#define PNG_PEDANTIC_WARNINGS
+#include "png.h"
+
+#ifdef _WIN32_WCE
+# if _WIN32_WCE < 211
+ __error__ (f|w)printf functions are not supported on old WindowsCE.;
+# endif
+# include <windows.h>
+# include <stdlib.h>
+# define READFILE(file, data, length, check) \
+ if (ReadFile(file, data, length, &check, NULL)) check = 0
+# define WRITEFILE(file, data, length, check)) \
+ if (WriteFile(file, data, length, &check, NULL)) check = 0
+# define FCLOSE(file) CloseHandle(file)
+#else
+# include <stdio.h>
+# include <stdlib.h>
+# define READFILE(file, data, length, check) \
+ check=(png_size_t)fread(data, (png_size_t)1, length, file)
+# define WRITEFILE(file, data, length, check) \
+ check=(png_size_t)fwrite(data, (png_size_t)1, length, file)
+# define FCLOSE(file) fclose(file)
+#endif
+
+#ifndef PNG_STDIO_SUPPORTED
+# ifdef _WIN32_WCE
+ typedef HANDLE png_FILE_p;
+# else
+ typedef FILE * png_FILE_p;
+# endif
+#endif
+
+/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
+#ifndef PNG_DEBUG
+# define PNG_DEBUG 0
+#endif
+
+#if !PNG_DEBUG
+# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */
+#endif
+
+/* Turn on CPU timing
+#define PNGTEST_TIMING
+*/
+
+#ifndef PNG_FLOATING_POINT_SUPPORTED
+#undef PNGTEST_TIMING
+#endif
+
+#ifdef PNGTEST_TIMING
+static float t_start, t_stop, t_decode, t_encode, t_misc;
+#include <time.h>
+#endif
+
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+#define PNG_tIME_STRING_LENGTH 29
+static int tIME_chunk_present = 0;
+static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
+#endif
+
+static int verbose = 0;
+
+int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname));
+
+#ifdef __TURBOC__
+#include <mem.h>
+#endif
+
+/* Defined so I can write to a file on gui/windowing platforms */
+/* #define STDERR stderr */
+#define STDERR stdout /* For DOS */
+
+/* In case a system header (e.g., on AIX) defined jmpbuf */
+#ifdef jmpbuf
+# undef jmpbuf
+#endif
+
+/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
+#ifndef png_jmpbuf
+# define png_jmpbuf(png_ptr) png_ptr->jmpbuf
+#endif
+
+/* Example of using row callbacks to make a simple progress meter */
+static int status_pass = 1;
+static int status_dots_requested = 0;
+static int status_dots = 1;
+
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+ if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)
+ return;
+ if (status_pass != pass)
+ {
+ fprintf(stdout, "\n Pass %d: ", pass);
+ status_pass = pass;
+ status_dots = 31;
+ }
+ status_dots--;
+ if (status_dots == 0)
+ {
+ fprintf(stdout, "\n ");
+ status_dots=30;
+ }
+ fprintf(stdout, "r");
+}
+
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
+{
+ if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)
+ return;
+ fprintf(stdout, "w");
+}
+
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+/* Example of using user transform callback (we don't transform anything,
+ * but merely examine the row filters. We set this to 256 rather than
+ * 5 in case illegal filter values are present.)
+ */
+static png_uint_32 filters_used[256];
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+ if (png_ptr != NULL && row_info != NULL)
+ ++filters_used[*(data - 1)];
+}
+#endif
+
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+/* Example of using user transform callback (we don't transform anything,
+ * but merely count the zero samples)
+ */
+
+static png_uint_32 zero_samples;
+
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data);
+void
+#ifdef PNG_1_0_X
+PNGAPI
+#endif
+count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
+{
+ png_bytep dp = data;
+ if (png_ptr == NULL)return;
+
+ /* Contents of row_info:
+ * png_uint_32 width width of row
+ * png_uint_32 rowbytes number of bytes in row
+ * png_byte color_type color type of pixels
+ * png_byte bit_depth bit depth of samples
+ * png_byte channels number of channels (1-4)
+ * png_byte pixel_depth bits per pixel (depth*channels)
+ */
+
+ /* Counts the number of zero samples (or zero pixels if color_type is 3 */
+
+ if (row_info->color_type == 0 || row_info->color_type == 3)
+ {
+ int pos = 0;
+ png_uint_32 n, nstop;
+ for (n = 0, nstop=row_info->width; n<nstop; n++)
+ {
+ if (row_info->bit_depth == 1)
+ {
+ if (((*dp << pos++ ) & 0x80) == 0)
+ zero_samples++;
+ if (pos == 8)
+ {
+ pos = 0;
+ dp++;
+ }
+ }
+ if (row_info->bit_depth == 2)
+ {
+ if (((*dp << (pos+=2)) & 0xc0) == 0)
+ zero_samples++;
+ if (pos == 8)
+ {
+ pos = 0;
+ dp++;
+ }
+ }
+ if (row_info->bit_depth == 4)
+ {
+ if (((*dp << (pos+=4)) & 0xf0) == 0)
+ zero_samples++;
+ if (pos == 8)
+ {
+ pos = 0;
+ dp++;
+ }
+ }
+ if (row_info->bit_depth == 8)
+ if (*dp++ == 0)
+ zero_samples++;
+ if (row_info->bit_depth == 16)
+ {
+ if ((*dp | *(dp+1)) == 0)
+ zero_samples++;
+ dp+=2;
+ }
+ }
+ }
+ else /* Other color types */
+ {
+ png_uint_32 n, nstop;
+ int channel;
+ int color_channels = row_info->channels;
+ if (row_info->color_type > 3)color_channels--;
+
+ for (n = 0, nstop=row_info->width; n<nstop; n++)
+ {
+ for (channel = 0; channel < color_channels; channel++)
+ {
+ if (row_info->bit_depth == 8)
+ if (*dp++ == 0)
+ zero_samples++;
+ if (row_info->bit_depth == 16)
+ {
+ if ((*dp | *(dp+1)) == 0)
+ zero_samples++;
+ dp+=2;
+ }
+ }
+ if (row_info->color_type > 3)
+ {
+ dp++;
+ if (row_info->bit_depth == 16)
+ dp++;
+ }
+ }
+ }
+}
+#endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
+
+static int wrote_question = 0;
+
+#ifndef PNG_STDIO_SUPPORTED
+/* START of code to validate stdio-free compilation */
+/* These copies of the default read/write functions come from pngrio.c and
+ * pngwio.c. They allow "don't include stdio" testing of the library.
+ * This is the function that does the actual reading of data. If you are
+ * not reading from a standard C stream, you should create a replacement
+ * read_data function and use it at run time with png_set_read_fn(), rather
+ * than changing the library.
+ */
+
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_size_t check = 0;
+ png_voidp io_ptr;
+
+ /* fread() returns 0 on error, so it is OK to store this in a png_size_t
+ * instead of an int, which is what fread() actually returns.
+ */
+ io_ptr = png_get_io_ptr(png_ptr);
+ if (io_ptr != NULL)
+ {
+ READFILE((png_FILE_p)io_ptr, data, length, check);
+ }
+
+ if (check != length)
+ {
+ png_error(png_ptr, "Read Error!");
+ }
+}
+#else
+/* This is the model-independent version. Since the standard I/O library
+ can't handle far buffers in the medium and small models, we have to copy
+ the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ int check;
+ png_byte *n_data;
+ png_FILE_p io_ptr;
+
+ /* Check if data really is near. If so, use usual code. */
+ n_data = (png_byte *)CVT_PTR_NOCHECK(data);
+ io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+ if ((png_bytep)n_data == data)
+ {
+ READFILE(io_ptr, n_data, length, check);
+ }
+ else
+ {
+ png_byte buf[NEAR_BUF_SIZE];
+ png_size_t read, remaining, err;
+ check = 0;
+ remaining = length;
+ do
+ {
+ read = MIN(NEAR_BUF_SIZE, remaining);
+ READFILE(io_ptr, buf, 1, err);
+ png_memcpy(data, buf, read); /* Copy far buffer to near buffer */
+ if (err != read)
+ break;
+ else
+ check += err;
+ data += read;
+ remaining -= read;
+ }
+ while (remaining != 0);
+ }
+ if (check != length)
+ png_error(png_ptr, "read Error");
+}
+#endif /* USE_FAR_KEYWORD */
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+static void
+pngtest_flush(png_structp png_ptr)
+{
+ /* Do nothing; fflush() is said to be just a waste of energy. */
+ png_ptr = png_ptr; /* Stifle compiler warning */
+}
+#endif
+
+/* This is the function that does the actual writing of data. If you are
+ * not writing to a standard C stream, you should create a replacement
+ * write_data function and use it at run time with png_set_write_fn(), rather
+ * than changing the library.
+ */
+#ifndef USE_FAR_KEYWORD
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_uint_32 check;
+
+ WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check);
+ if (check != length)
+ {
+ png_error(png_ptr, "Write Error");
+ }
+}
+#else
+/* This is the model-independent version. Since the standard I/O library
+ can't handle far buffers in the medium and small models, we have to copy
+ the data.
+*/
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+static void
+pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_uint_32 check;
+ png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
+ png_FILE_p io_ptr;
+
+ /* Check if data really is near. If so, use usual code. */
+ near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+ io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+ if ((png_bytep)near_data == data)
+ {
+ WRITEFILE(io_ptr, near_data, length, check);
+ }
+ else
+ {
+ png_byte buf[NEAR_BUF_SIZE];
+ png_size_t written, remaining, err;
+ check = 0;
+ remaining = length;
+ do
+ {
+ written = MIN(NEAR_BUF_SIZE, remaining);
+ png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
+ WRITEFILE(io_ptr, buf, written, err);
+ if (err != written)
+ break;
+ else
+ check += err;
+ data += written;
+ remaining -= written;
+ }
+ while (remaining != 0);
+ }
+ if (check != length)
+ {
+ png_error(png_ptr, "Write Error");
+ }
+}
+#endif /* USE_FAR_KEYWORD */
+
+/* This function is called when there is a warning, but the library thinks
+ * it can continue anyway. Replacement functions don't have to do anything
+ * here if you don't want to. In the default configuration, png_ptr is
+ * not used, but it is passed in case it may be useful.
+ */
+static void
+pngtest_warning(png_structp png_ptr, png_const_charp message)
+{
+ PNG_CONST char *name = "UNKNOWN (ERROR!)";
+ char *test;
+ test = png_get_error_ptr(png_ptr);
+ if (test == NULL)
+ fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
+ else
+ fprintf(STDERR, "%s: libpng warning: %s\n", test, message);
+}
+
+/* This is the default error handling function. Note that replacements for
+ * this function MUST NOT RETURN, or the program will likely crash. This
+ * function is used by default, or if the program supplies NULL for the
+ * error function pointer in png_set_error_fn().
+ */
+static void
+pngtest_error(png_structp png_ptr, png_const_charp message)
+{
+ pngtest_warning(png_ptr, message);
+ /* We can return because png_error calls the default handler, which is
+ * actually OK in this case.
+ */
+}
+#endif /* !PNG_STDIO_SUPPORTED */
+/* END of code to validate stdio-free compilation */
+
+/* START of code to validate memory allocation and deallocation */
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+
+/* Allocate memory. For reasonable files, size should never exceed
+ * 64K. However, zlib may allocate more then 64K if you don't tell
+ * it not to. See zconf.h and png.h for more information. zlib does
+ * need to allocate exactly 64K, so whatever you call here must
+ * have the ability to do that.
+ *
+ * This piece of code can be compiled to validate max 64K allocations
+ * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K.
+ */
+typedef struct memory_information
+{
+ png_uint_32 size;
+ png_voidp pointer;
+ struct memory_information FAR *next;
+} memory_information;
+typedef memory_information FAR *memory_infop;
+
+static memory_infop pinformation = NULL;
+static int current_allocation = 0;
+static int maximum_allocation = 0;
+static int total_allocation = 0;
+static int num_allocations = 0;
+
+png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size));
+void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
+
+png_voidp
+png_debug_malloc(png_structp png_ptr, png_uint_32 size)
+{
+
+ /* png_malloc has already tested for NULL; png_create_struct calls
+ * png_debug_malloc directly, with png_ptr == NULL which is OK
+ */
+
+ if (size == 0)
+ return (NULL);
+
+ /* This calls the library allocator twice, once to get the requested
+ buffer and once to get a new free list entry. */
+ {
+ /* Disable malloc_fn and free_fn */
+ memory_infop pinfo;
+ png_set_mem_fn(png_ptr, NULL, NULL, NULL);
+ pinfo = (memory_infop)png_malloc(png_ptr,
+ (png_uint_32)png_sizeof(*pinfo));
+ pinfo->size = size;
+ current_allocation += size;
+ total_allocation += size;
+ num_allocations ++;
+ if (current_allocation > maximum_allocation)
+ maximum_allocation = current_allocation;
+ pinfo->pointer = (png_voidp)png_malloc(png_ptr, size);
+ /* Restore malloc_fn and free_fn */
+ png_set_mem_fn(png_ptr,
+ png_voidp_NULL, (png_malloc_ptr)png_debug_malloc,
+ (png_free_ptr)png_debug_free);
+ if (size != 0 && pinfo->pointer == NULL)
+ {
+ current_allocation -= size;
+ total_allocation -= size;
+ png_error(png_ptr,
+ "out of memory in pngtest->png_debug_malloc.");
+ }
+ pinfo->next = pinformation;
+ pinformation = pinfo;
+ /* Make sure the caller isn't assuming zeroed memory. */
+ png_memset(pinfo->pointer, 0xdd, pinfo->size);
+ if (verbose)
+ printf("png_malloc %lu bytes at %x\n", (unsigned long)size,
+ pinfo->pointer);
+ return (png_voidp)(pinfo->pointer);
+ }
+}
+
+/* Free a pointer. It is removed from the list at the same time. */
+void
+png_debug_free(png_structp png_ptr, png_voidp ptr)
+{
+ if (png_ptr == NULL)
+ fprintf(STDERR, "NULL pointer to png_debug_free.\n");
+ if (ptr == 0)
+ {
+#if 0 /* This happens all the time. */
+ fprintf(STDERR, "WARNING: freeing NULL pointer\n");
+#endif
+ return;
+ }
+
+ /* Unlink the element from the list. */
+ {
+ memory_infop FAR *ppinfo = &pinformation;
+ for (;;)
+ {
+ memory_infop pinfo = *ppinfo;
+ if (pinfo->pointer == ptr)
+ {
+ *ppinfo = pinfo->next;
+ current_allocation -= pinfo->size;
+ if (current_allocation < 0)
+ fprintf(STDERR, "Duplicate free of memory\n");
+ /* We must free the list element too, but first kill
+ the memory that is to be freed. */
+ png_memset(ptr, 0x55, pinfo->size);
+ png_free_default(png_ptr, pinfo);
+ pinfo = NULL;
+ break;
+ }
+ if (pinfo->next == NULL)
+ {
+ fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
+ break;
+ }
+ ppinfo = &pinfo->next;
+ }
+ }
+
+ /* Finally free the data. */
+ if (verbose)
+ printf("Freeing %x\n", ptr);
+ png_free_default(png_ptr, ptr);
+ ptr = NULL;
+}
+#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */
+/* END of code to test memory allocation/deallocation */
+
+
+/* Demonstration of user chunk support of the sTER and vpAg chunks */
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+
+/* (sTER is a public chunk not yet known by libpng. vpAg is a private
+chunk used in ImageMagick to store "virtual page" size). */
+
+static png_uint_32 user_chunk_data[4];
+
+ /* 0: sTER mode + 1
+ * 1: vpAg width
+ * 2: vpAg height
+ * 3: vpAg units
+ */
+
+static int read_user_chunk_callback(png_struct *png_ptr,
+ png_unknown_chunkp chunk)
+{
+ png_uint_32
+ *my_user_chunk_data;
+
+ /* Return one of the following:
+ * return (-n); chunk had an error
+ * return (0); did not recognize
+ * return (n); success
+ *
+ * The unknown chunk structure contains the chunk data:
+ * png_byte name[5];
+ * png_byte *data;
+ * png_size_t size;
+ *
+ * Note that libpng has already taken care of the CRC handling.
+ */
+
+ if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */
+ chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */
+ {
+ /* Found sTER chunk */
+ if (chunk->size != 1)
+ return (-1); /* Error return */
+ if (chunk->data[0] != 0 && chunk->data[0] != 1)
+ return (-1); /* Invalid mode */
+ my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr);
+ my_user_chunk_data[0]=chunk->data[0]+1;
+ return (1);
+ }
+
+ if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */
+ chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */
+ return (0); /* Did not recognize */
+
+ /* Found ImageMagick vpAg chunk */
+
+ if (chunk->size != 9)
+ return (-1); /* Error return */
+
+ my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr);
+
+ my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data);
+ my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4);
+ my_user_chunk_data[3]=(png_uint_32)chunk->data[8];
+
+ return (1);
+
+}
+#endif
+/* END of code to demonstrate user chunk support */
+
+/* Test one file */
+int
+test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
+{
+ static png_FILE_p fpin;
+ static png_FILE_p fpout; /* "static" prevents setjmp corruption */
+ png_structp read_ptr;
+ png_infop read_info_ptr, end_info_ptr;
+#ifdef PNG_WRITE_SUPPORTED
+ png_structp write_ptr;
+ png_infop write_info_ptr;
+ png_infop write_end_info_ptr;
+#else
+ png_structp write_ptr = NULL;
+ png_infop write_info_ptr = NULL;
+ png_infop write_end_info_ptr = NULL;
+#endif
+ png_bytep row_buf;
+ png_uint_32 y;
+ png_uint_32 width, height;
+ int num_pass, pass;
+ int bit_depth, color_type;
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+ jmp_buf jmpbuf;
+#endif
+#endif
+
+#ifdef _WIN32_WCE
+ TCHAR path[MAX_PATH];
+#endif
+ char inbuf[256], outbuf[256];
+
+ row_buf = NULL;
+
+#ifdef _WIN32_WCE
+ MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+ if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0,
+ NULL)) == INVALID_HANDLE_VALUE)
+#else
+ if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+ {
+ fprintf(STDERR, "Could not find input file %s\n", inname);
+ return (1);
+ }
+
+#ifdef _WIN32_WCE
+ MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+ if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+ 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+ if ((fpout = fopen(outname, "wb")) == NULL)
+#endif
+ {
+ fprintf(STDERR, "Could not open output file %s\n", outname);
+ FCLOSE(fpin);
+ return (1);
+ }
+
+ png_debug(0, "Allocating read and write structures");
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ read_ptr =
+ png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
+ png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
+ (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+ read_ptr =
+ png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
+ png_error_ptr_NULL, png_error_ptr_NULL);
+#endif
+#ifndef PNG_STDIO_SUPPORTED
+ png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
+ pngtest_warning);
+#endif
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+ user_chunk_data[0] = 0;
+ user_chunk_data[1] = 0;
+ user_chunk_data[2] = 0;
+ user_chunk_data[3] = 0;
+ png_set_read_user_chunk_fn(read_ptr, user_chunk_data,
+ read_user_chunk_callback);
+
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ write_ptr =
+ png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
+ png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
+ (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
+#else
+ write_ptr =
+ png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
+ png_error_ptr_NULL, png_error_ptr_NULL);
+#endif
+#ifndef PNG_STDIO_SUPPORTED
+ png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
+ pngtest_warning);
+#endif
+#endif
+ png_debug(0, "Allocating read_info, write_info and end_info structures");
+ read_info_ptr = png_create_info_struct(read_ptr);
+ end_info_ptr = png_create_info_struct(read_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+ write_info_ptr = png_create_info_struct(write_ptr);
+ write_end_info_ptr = png_create_info_struct(write_ptr);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ png_debug(0, "Setting jmpbuf for read struct");
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+#else
+ if (setjmp(png_jmpbuf(read_ptr)))
+#endif
+ {
+ fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
+ png_free(read_ptr, row_buf);
+ row_buf = NULL;
+ png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+ png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+ png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+ return (1);
+ }
+#ifdef USE_FAR_KEYWORD
+ png_memcpy(png_jmpbuf(read_ptr), jmpbuf, png_sizeof(jmp_buf));
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+ png_debug(0, "Setting jmpbuf for write struct");
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+#else
+ if (setjmp(png_jmpbuf(write_ptr)))
+#endif
+ {
+ fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
+ png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+ png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+ png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+ return (1);
+ }
+#ifdef USE_FAR_KEYWORD
+ png_memcpy(png_jmpbuf(write_ptr), jmpbuf, png_sizeof(jmp_buf));
+#endif
+#endif
+#endif
+
+ png_debug(0, "Initializing input and output streams");
+#ifdef PNG_STDIO_SUPPORTED
+ png_init_io(read_ptr, fpin);
+# ifdef PNG_WRITE_SUPPORTED
+ png_init_io(write_ptr, fpout);
+# endif
+#else
+ png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
+# ifdef PNG_WRITE_SUPPORTED
+ png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data,
+# ifdef PNG_WRITE_FLUSH_SUPPORTED
+ pngtest_flush);
+# else
+ NULL);
+# endif
+# endif
+#endif
+ if (status_dots_requested == 1)
+ {
+#ifdef PNG_WRITE_SUPPORTED
+ png_set_write_status_fn(write_ptr, write_row_callback);
+#endif
+ png_set_read_status_fn(read_ptr, read_row_callback);
+ }
+ else
+ {
+#ifdef PNG_WRITE_SUPPORTED
+ png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL);
+#endif
+ png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
+ }
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ {
+ int i;
+ for (i = 0; i<256; i++)
+ filters_used[i] = 0;
+ png_set_read_user_transform_fn(read_ptr, count_filters);
+ }
+#endif
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ zero_samples = 0;
+ png_set_write_user_transform_fn(write_ptr, count_zero_samples);
+#endif
+
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+# ifndef PNG_HANDLE_CHUNK_ALWAYS
+# define PNG_HANDLE_CHUNK_ALWAYS 3
+# endif
+ png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
+ png_bytep_NULL, 0);
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+# ifndef PNG_HANDLE_CHUNK_IF_SAFE
+# define PNG_HANDLE_CHUNK_IF_SAFE 2
+# endif
+ png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE,
+ png_bytep_NULL, 0);
+#endif
+
+ png_debug(0, "Reading info struct");
+ png_read_info(read_ptr, read_info_ptr);
+
+ png_debug(0, "Transferring info struct");
+ {
+ int interlace_type, compression_type, filter_type;
+
+ if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
+ &color_type, &interlace_type, &compression_type, &filter_type))
+ {
+ png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ color_type, interlace_type, compression_type, filter_type);
+#else
+ color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
+#endif
+ }
+ }
+#ifdef PNG_FIXED_POINT_SUPPORTED
+#ifdef PNG_cHRM_SUPPORTED
+ {
+ png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+ blue_y;
+ if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
+ &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y))
+ {
+ png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
+ red_y, green_x, green_y, blue_x, blue_y);
+ }
+ }
+#endif
+#ifdef PNG_gAMA_SUPPORTED
+ {
+ png_fixed_point gamma;
+
+ if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
+ png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
+ }
+#endif
+#else /* Use floating point versions */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+#ifdef PNG_cHRM_SUPPORTED
+ {
+ double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
+ blue_y;
+ if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
+ &red_y, &green_x, &green_y, &blue_x, &blue_y))
+ {
+ png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
+ red_y, green_x, green_y, blue_x, blue_y);
+ }
+ }
+#endif
+#ifdef PNG_gAMA_SUPPORTED
+ {
+ double gamma;
+
+ if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
+ png_set_gAMA(write_ptr, write_info_ptr, gamma);
+ }
+#endif
+#endif /* Floating point */
+#endif /* Fixed point */
+#ifdef PNG_iCCP_SUPPORTED
+ {
+ png_charp name;
+ png_charp profile;
+ png_uint_32 proflen;
+ int compression_type;
+
+ if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
+ &profile, &proflen))
+ {
+ png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
+ profile, proflen);
+ }
+ }
+#endif
+#ifdef PNG_sRGB_SUPPORTED
+ {
+ int intent;
+
+ if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
+ png_set_sRGB(write_ptr, write_info_ptr, intent);
+ }
+#endif
+ {
+ png_colorp palette;
+ int num_palette;
+
+ if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
+ png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
+ }
+#ifdef PNG_bKGD_SUPPORTED
+ {
+ png_color_16p background;
+
+ if (png_get_bKGD(read_ptr, read_info_ptr, &background))
+ {
+ png_set_bKGD(write_ptr, write_info_ptr, background);
+ }
+ }
+#endif
+#ifdef PNG_hIST_SUPPORTED
+ {
+ png_uint_16p hist;
+
+ if (png_get_hIST(read_ptr, read_info_ptr, &hist))
+ png_set_hIST(write_ptr, write_info_ptr, hist);
+ }
+#endif
+#ifdef PNG_oFFs_SUPPORTED
+ {
+ png_int_32 offset_x, offset_y;
+ int unit_type;
+
+ if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
+ &unit_type))
+ {
+ png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
+ }
+ }
+#endif
+#ifdef PNG_pCAL_SUPPORTED
+ {
+ png_charp purpose, units;
+ png_charpp params;
+ png_int_32 X0, X1;
+ int type, nparams;
+
+ if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
+ &nparams, &units, &params))
+ {
+ png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
+ nparams, units, params);
+ }
+ }
+#endif
+#ifdef PNG_pHYs_SUPPORTED
+ {
+ png_uint_32 res_x, res_y;
+ int unit_type;
+
+ if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
+ png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
+ }
+#endif
+#ifdef PNG_sBIT_SUPPORTED
+ {
+ png_color_8p sig_bit;
+
+ if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
+ png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
+ }
+#endif
+#ifdef PNG_sCAL_SUPPORTED
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ {
+ int unit;
+ double scal_width, scal_height;
+
+ if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
+ &scal_height))
+ {
+ png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
+ }
+ }
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ {
+ int unit;
+ png_charp scal_width, scal_height;
+
+ if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
+ &scal_height))
+ {
+ png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
+ scal_height);
+ }
+ }
+#endif
+#endif
+#endif
+#ifdef PNG_TEXT_SUPPORTED
+ {
+ png_textp text_ptr;
+ int num_text;
+
+ if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
+ {
+ png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text);
+ png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
+ }
+ }
+#endif
+#ifdef PNG_tIME_SUPPORTED
+ {
+ png_timep mod_time;
+
+ if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
+ {
+ png_set_tIME(write_ptr, write_info_ptr, mod_time);
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ /* We have to use png_memcpy instead of "=" because the string
+ * pointed to by png_convert_to_rfc1123() gets free'ed before
+ * we use it.
+ */
+ png_memcpy(tIME_string,
+ png_convert_to_rfc1123(read_ptr, mod_time),
+ png_sizeof(tIME_string));
+ tIME_string[png_sizeof(tIME_string) - 1] = '\0';
+ tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+ }
+ }
+#endif
+#ifdef PNG_tRNS_SUPPORTED
+ {
+ png_bytep trans;
+ int num_trans;
+ png_color_16p trans_values;
+
+ if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
+ &trans_values))
+ {
+ int sample_max = (1 << bit_depth);
+ /* libpng doesn't reject a tRNS chunk with out-of-range samples */
+ if (!((color_type == PNG_COLOR_TYPE_GRAY &&
+ (int)trans_values->gray > sample_max) ||
+ (color_type == PNG_COLOR_TYPE_RGB &&
+ ((int)trans_values->red > sample_max ||
+ (int)trans_values->green > sample_max ||
+ (int)trans_values->blue > sample_max))))
+ png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
+ trans_values);
+ }
+ }
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ {
+ png_unknown_chunkp unknowns;
+ int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
+ &unknowns);
+ if (num_unknowns)
+ {
+ png_size_t i;
+ png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
+ num_unknowns);
+ /* Copy the locations from the read_info_ptr. The automatically
+ * generated locations in write_info_ptr are wrong because we
+ * haven't written anything yet.
+ */
+ for (i = 0; i < (png_size_t)num_unknowns; i++)
+ png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
+ unknowns[i].location);
+ }
+ }
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+ png_debug(0, "Writing info struct");
+
+/* If we wanted, we could write info in two steps:
+ * png_write_info_before_PLTE(write_ptr, write_info_ptr);
+ */
+ png_write_info(write_ptr, write_info_ptr);
+
+#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+ if (user_chunk_data[0] != 0)
+ {
+ png_byte png_sTER[5] = {115, 84, 69, 82, '\0'};
+
+ unsigned char
+ ster_chunk_data[1];
+
+ if (verbose)
+ fprintf(STDERR, "\n stereo mode = %lu\n",
+ (unsigned long)(user_chunk_data[0] - 1));
+ ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1);
+ png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1);
+ }
+ if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0)
+ {
+ png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'};
+
+ unsigned char
+ vpag_chunk_data[9];
+
+ if (verbose)
+ fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n",
+ (unsigned long)user_chunk_data[1],
+ (unsigned long)user_chunk_data[2],
+ (unsigned long)user_chunk_data[3]);
+ png_save_uint_32(vpag_chunk_data, user_chunk_data[1]);
+ png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]);
+ vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff);
+ png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9);
+ }
+
+#endif
+#endif
+
+#ifdef SINGLE_ROWBUF_ALLOC
+ png_debug(0, "Allocating row buffer...");
+ row_buf = (png_bytep)png_malloc(read_ptr,
+ png_get_rowbytes(read_ptr, read_info_ptr));
+ png_debug1(0, "0x%08lx", (unsigned long)row_buf);
+#endif /* SINGLE_ROWBUF_ALLOC */
+ png_debug(0, "Writing row data");
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+ defined(PNG_WRITE_INTERLACING_SUPPORTED)
+ num_pass = png_set_interlace_handling(read_ptr);
+# ifdef PNG_WRITE_SUPPORTED
+ png_set_interlace_handling(write_ptr);
+# endif
+#else
+ num_pass = 1;
+#endif
+
+#ifdef PNGTEST_TIMING
+ t_stop = (float)clock();
+ t_misc += (t_stop - t_start);
+ t_start = t_stop;
+#endif
+ for (pass = 0; pass < num_pass; pass++)
+ {
+ png_debug1(0, "Writing row data for pass %d", pass);
+ for (y = 0; y < height; y++)
+ {
+#ifndef SINGLE_ROWBUF_ALLOC
+ png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y);
+ row_buf = (png_bytep)png_malloc(read_ptr,
+ png_get_rowbytes(read_ptr, read_info_ptr));
+ png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf,
+ png_get_rowbytes(read_ptr, read_info_ptr));
+#endif /* !SINGLE_ROWBUF_ALLOC */
+ png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1);
+
+#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNGTEST_TIMING
+ t_stop = (float)clock();
+ t_decode += (t_stop - t_start);
+ t_start = t_stop;
+#endif
+ png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
+#ifdef PNGTEST_TIMING
+ t_stop = (float)clock();
+ t_encode += (t_stop - t_start);
+ t_start = t_stop;
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
+
+#ifndef SINGLE_ROWBUF_ALLOC
+ png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y);
+ png_free(read_ptr, row_buf);
+ row_buf = NULL;
+#endif /* !SINGLE_ROWBUF_ALLOC */
+ }
+ }
+
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
+#endif
+
+ png_debug(0, "Reading and writing end_info data");
+
+ png_read_end(read_ptr, end_info_ptr);
+#ifdef PNG_TEXT_SUPPORTED
+ {
+ png_textp text_ptr;
+ int num_text;
+
+ if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
+ {
+ png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text);
+ png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
+ }
+ }
+#endif
+#ifdef PNG_tIME_SUPPORTED
+ {
+ png_timep mod_time;
+
+ if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
+ {
+ png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ /* We have to use png_memcpy instead of "=" because the string
+ pointed to by png_convert_to_rfc1123() gets free'ed before
+ we use it */
+ png_memcpy(tIME_string,
+ png_convert_to_rfc1123(read_ptr, mod_time),
+ png_sizeof(tIME_string));
+ tIME_string[png_sizeof(tIME_string) - 1] = '\0';
+ tIME_chunk_present++;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+ }
+ }
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ {
+ png_unknown_chunkp unknowns;
+ int num_unknowns;
+ num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
+ &unknowns);
+ if (num_unknowns)
+ {
+ png_size_t i;
+ png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
+ num_unknowns);
+ /* Copy the locations from the read_info_ptr. The automatically
+ * generated locations in write_end_info_ptr are wrong because we
+ * haven't written the end_info yet.
+ */
+ for (i = 0; i < (png_size_t)num_unknowns; i++)
+ png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
+ unknowns[i].location);
+ }
+ }
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+ png_write_end(write_ptr, write_end_info_ptr);
+#endif
+
+#ifdef PNG_EASY_ACCESS_SUPPORTED
+ if (verbose)
+ {
+ png_uint_32 iwidth, iheight;
+ iwidth = png_get_image_width(write_ptr, write_info_ptr);
+ iheight = png_get_image_height(write_ptr, write_info_ptr);
+ fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
+ (unsigned long)iwidth, (unsigned long)iheight);
+ }
+#endif
+
+ png_debug(0, "Destroying data structs");
+#ifdef SINGLE_ROWBUF_ALLOC
+ png_debug(1, "destroying row_buf for read_ptr");
+ png_free(read_ptr, row_buf);
+ row_buf = NULL;
+#endif /* SINGLE_ROWBUF_ALLOC */
+ png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr");
+ png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
+#ifdef PNG_WRITE_SUPPORTED
+ png_debug(1, "destroying write_end_info_ptr");
+ png_destroy_info_struct(write_ptr, &write_end_info_ptr);
+ png_debug(1, "destroying write_ptr, write_info_ptr");
+ png_destroy_write_struct(&write_ptr, &write_info_ptr);
+#endif
+ png_debug(0, "Destruction complete.");
+
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+
+ png_debug(0, "Opening files for comparison");
+#ifdef _WIN32_WCE
+ MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
+ if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+ if ((fpin = fopen(inname, "rb")) == NULL)
+#endif
+ {
+ fprintf(STDERR, "Could not find file %s\n", inname);
+ return (1);
+ }
+
+#ifdef _WIN32_WCE
+ MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
+ if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+ 0, NULL)) == INVALID_HANDLE_VALUE)
+#else
+ if ((fpout = fopen(outname, "rb")) == NULL)
+#endif
+ {
+ fprintf(STDERR, "Could not find file %s\n", outname);
+ FCLOSE(fpin);
+ return (1);
+ }
+
+ for (;;)
+ {
+ png_size_t num_in, num_out;
+
+ READFILE(fpin, inbuf, 1, num_in);
+ READFILE(fpout, outbuf, 1, num_out);
+
+ if (num_in != num_out)
+ {
+ fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
+ inname, outname);
+ if (wrote_question == 0)
+ {
+ fprintf(STDERR,
+ " Was %s written with the same maximum IDAT chunk size (%d bytes),",
+ inname, PNG_ZBUF_SIZE);
+ fprintf(STDERR,
+ "\n filtering heuristic (libpng default), compression");
+ fprintf(STDERR,
+ " level (zlib default),\n and zlib version (%s)?\n\n",
+ ZLIB_VERSION);
+ wrote_question = 1;
+ }
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+ return (0);
+ }
+
+ if (!num_in)
+ break;
+
+ if (png_memcmp(inbuf, outbuf, num_in))
+ {
+ fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
+ if (wrote_question == 0)
+ {
+ fprintf(STDERR,
+ " Was %s written with the same maximum IDAT chunk size (%d bytes),",
+ inname, PNG_ZBUF_SIZE);
+ fprintf(STDERR,
+ "\n filtering heuristic (libpng default), compression");
+ fprintf(STDERR,
+ " level (zlib default),\n and zlib version (%s)?\n\n",
+ ZLIB_VERSION);
+ wrote_question = 1;
+ }
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+ return (0);
+ }
+ }
+
+ FCLOSE(fpin);
+ FCLOSE(fpout);
+
+ return (0);
+}
+
+/* Input and output filenames */
+#ifdef RISCOS
+static PNG_CONST char *inname = "pngtest/png";
+static PNG_CONST char *outname = "pngout/png";
+#else
+static PNG_CONST char *inname = "pngtest.png";
+static PNG_CONST char *outname = "pngout.png";
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ int multiple = 0;
+ int ierror = 0;
+
+ fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
+ fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION);
+ fprintf(STDERR, "%s", png_get_copyright(NULL));
+ /* Show the version of libpng used in building the library */
+ fprintf(STDERR, " library (%lu):%s",
+ (unsigned long)png_access_version_number(),
+ png_get_header_version(NULL));
+ /* Show the version of libpng used in building the application */
+ fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
+ PNG_HEADER_VERSION_STRING);
+ fprintf(STDERR, " sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n",
+ (long)png_sizeof(png_struct), (long)png_sizeof(png_info));
+
+ /* Do some consistency checking on the memory allocation settings, I'm
+ * not sure this matters, but it is nice to know, the first of these
+ * tests should be impossible because of the way the macros are set
+ * in pngconf.h
+ */
+#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
+ fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
+#endif
+ /* I think the following can happen. */
+#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
+ fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
+#endif
+
+ if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
+ {
+ fprintf(STDERR,
+ "Warning: versions are different between png.h and png.c\n");
+ fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING);
+ fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
+ ++ierror;
+ }
+
+ if (argc > 1)
+ {
+ if (strcmp(argv[1], "-m") == 0)
+ {
+ multiple = 1;
+ status_dots_requested = 0;
+ }
+ else if (strcmp(argv[1], "-mv") == 0 ||
+ strcmp(argv[1], "-vm") == 0 )
+ {
+ multiple = 1;
+ verbose = 1;
+ status_dots_requested = 1;
+ }
+ else if (strcmp(argv[1], "-v") == 0)
+ {
+ verbose = 1;
+ status_dots_requested = 1;
+ inname = argv[2];
+ }
+ else
+ {
+ inname = argv[1];
+ status_dots_requested = 0;
+ }
+ }
+
+ if (!multiple && argc == 3 + verbose)
+ outname = argv[2 + verbose];
+
+ if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2))
+ {
+ fprintf(STDERR,
+ "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
+ argv[0], argv[0]);
+ fprintf(STDERR,
+ " reads/writes one PNG file (without -m) or multiple files (-m)\n");
+ fprintf(STDERR,
+ " with -m %s is used as a temporary file\n", outname);
+ exit(1);
+ }
+
+ if (multiple)
+ {
+ int i;
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ int allocation_now = current_allocation;
+#endif
+ for (i=2; i<argc; ++i)
+ {
+ int kerror;
+ fprintf(STDERR, "\n Testing %s:", argv[i]);
+ kerror = test_one_file(argv[i], outname);
+ if (kerror == 0)
+ {
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ int k;
+#endif
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ fprintf(STDERR, "\n PASS (%lu zero samples)\n",
+ (unsigned long)zero_samples);
+#else
+ fprintf(STDERR, " PASS\n");
+#endif
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ for (k = 0; k<256; k++)
+ if (filters_used[k])
+ fprintf(STDERR, " Filter %d was used %lu times\n",
+ k, (unsigned long)filters_used[k]);
+#endif
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ if (tIME_chunk_present != 0)
+ fprintf(STDERR, " tIME = %s\n", tIME_string);
+ tIME_chunk_present = 0;
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+ }
+ else
+ {
+ fprintf(STDERR, " FAIL\n");
+ ierror += kerror;
+ }
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ if (allocation_now != current_allocation)
+ fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+ current_allocation - allocation_now);
+ if (current_allocation != 0)
+ {
+ memory_infop pinfo = pinformation;
+
+ fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+ current_allocation);
+ while (pinfo != NULL)
+ {
+ fprintf(STDERR, " %lu bytes at %x\n",
+ (unsigned long)pinfo->size,
+ (unsigned int) pinfo->pointer);
+ pinfo = pinfo->next;
+ }
+ }
+#endif
+ }
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+ current_allocation);
+ fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+ maximum_allocation);
+ fprintf(STDERR, " Total memory allocation: %10d bytes\n",
+ total_allocation);
+ fprintf(STDERR, " Number of allocations: %10d\n",
+ num_allocations);
+#endif
+ }
+ else
+ {
+ int i;
+ for (i = 0; i<3; ++i)
+ {
+ int kerror;
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ int allocation_now = current_allocation;
+#endif
+ if (i == 1) status_dots_requested = 1;
+ else if (verbose == 0)status_dots_requested = 0;
+ if (i == 0 || verbose == 1 || ierror != 0)
+ fprintf(STDERR, "\n Testing %s:", inname);
+ kerror = test_one_file(inname, outname);
+ if (kerror == 0)
+ {
+ if (verbose == 1 || i == 2)
+ {
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ int k;
+#endif
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ fprintf(STDERR, "\n PASS (%lu zero samples)\n",
+ (unsigned long)zero_samples);
+#else
+ fprintf(STDERR, " PASS\n");
+#endif
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ for (k = 0; k<256; k++)
+ if (filters_used[k])
+ fprintf(STDERR, " Filter %d was used %lu times\n",
+ k, (unsigned long)filters_used[k]);
+#endif
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ if (tIME_chunk_present != 0)
+ fprintf(STDERR, " tIME = %s\n", tIME_string);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
+ }
+ }
+ else
+ {
+ if (verbose == 0 && i != 2)
+ fprintf(STDERR, "\n Testing %s:", inname);
+ fprintf(STDERR, " FAIL\n");
+ ierror += kerror;
+ }
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ if (allocation_now != current_allocation)
+ fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
+ current_allocation - allocation_now);
+ if (current_allocation != 0)
+ {
+ memory_infop pinfo = pinformation;
+
+ fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
+ current_allocation);
+ while (pinfo != NULL)
+ {
+ fprintf(STDERR, " %lu bytes at %x\n",
+ (unsigned long)pinfo->size, (unsigned int)pinfo->pointer);
+ pinfo = pinfo->next;
+ }
+ }
+#endif
+ }
+#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
+ fprintf(STDERR, " Current memory allocation: %10d bytes\n",
+ current_allocation);
+ fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
+ maximum_allocation);
+ fprintf(STDERR, " Total memory allocation: %10d bytes\n",
+ total_allocation);
+ fprintf(STDERR, " Number of allocations: %10d\n",
+ num_allocations);
+#endif
+ }
+
+#ifdef PNGTEST_TIMING
+ t_stop = (float)clock();
+ t_misc += (t_stop - t_start);
+ t_start = t_stop;
+ fprintf(STDERR, " CPU time used = %.3f seconds",
+ (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
+ fprintf(STDERR, " (decoding %.3f,\n",
+ t_decode/(float)CLOCKS_PER_SEC);
+ fprintf(STDERR, " encoding %.3f ,",
+ t_encode/(float)CLOCKS_PER_SEC);
+ fprintf(STDERR, " other %.3f seconds)\n\n",
+ t_misc/(float)CLOCKS_PER_SEC);
+#endif
+
+ if (ierror == 0)
+ fprintf(STDERR, " libpng passes test\n");
+ else
+ fprintf(STDERR, " libpng FAILS test\n");
+ return (int)(ierror != 0);
+}
+
+/* Generate a compiler error if there is an old png.h in the search path. */
+typedef version_1_2_49 your_png_h_is_not_version_1_2_49;
diff --git a/Source/LibPNG/pngtest.png b/Source/LibPNG/pngtest.png
new file mode 100644
index 0000000..f3a6df4
--- /dev/null
+++ b/Source/LibPNG/pngtest.png
Binary files differ
diff --git a/Source/LibPNG/pngtrans.c b/Source/LibPNG/pngtrans.c
new file mode 100644
index 0000000..6ad9dcf
--- /dev/null
+++ b/Source/LibPNG/pngtrans.c
@@ -0,0 +1,699 @@
+
+/* pngtrans.c - transforms the data in a row (used by both readers and writers)
+ *
+ * Last changed in libpng 1.2.41 [December 3, 2009]
+ * Copyright (c) 1998-2009 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* Turn on BGR-to-RGB mapping */
+void PNGAPI
+png_set_bgr(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_bgr");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_BGR;
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* Turn on 16 bit byte swapping */
+void PNGAPI
+png_set_swap(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_swap");
+
+ if (png_ptr == NULL)
+ return;
+ if (png_ptr->bit_depth == 16)
+ png_ptr->transformations |= PNG_SWAP_BYTES;
+}
+#endif
+
+#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
+/* Turn on pixel packing */
+void PNGAPI
+png_set_packing(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_packing");
+
+ if (png_ptr == NULL)
+ return;
+ if (png_ptr->bit_depth < 8)
+ {
+ png_ptr->transformations |= PNG_PACK;
+ png_ptr->usr_bit_depth = 8;
+ }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+/* Turn on packed pixel swapping */
+void PNGAPI
+png_set_packswap(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_packswap");
+
+ if (png_ptr == NULL)
+ return;
+ if (png_ptr->bit_depth < 8)
+ png_ptr->transformations |= PNG_PACKSWAP;
+}
+#endif
+
+#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
+void PNGAPI
+png_set_shift(png_structp png_ptr, png_color_8p true_bits)
+{
+ png_debug(1, "in png_set_shift");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_SHIFT;
+ png_ptr->shift = *true_bits;
+}
+#endif
+
+#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
+ defined(PNG_WRITE_INTERLACING_SUPPORTED)
+int PNGAPI
+png_set_interlace_handling(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_interlace handling");
+
+ if (png_ptr && png_ptr->interlaced)
+ {
+ png_ptr->transformations |= PNG_INTERLACE;
+ return (7);
+ }
+
+ return (1);
+}
+#endif
+
+#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
+/* Add a filler byte on read, or remove a filler or alpha byte on write.
+ * The filler type has changed in v0.95 to allow future 2-byte fillers
+ * for 48-bit input data, as well as to avoid problems with some compilers
+ * that don't like bytes as parameters.
+ */
+void PNGAPI
+png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+{
+ png_debug(1, "in png_set_filler");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_FILLER;
+#ifdef PNG_LEGACY_SUPPORTED
+ png_ptr->filler = (png_byte)filler;
+#else
+ png_ptr->filler = (png_uint_16)filler;
+#endif
+ if (filler_loc == PNG_FILLER_AFTER)
+ png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
+ else
+ png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
+
+ /* This should probably go in the "do_read_filler" routine.
+ * I attempted to do that in libpng-1.0.1a but that caused problems
+ * so I restored it in libpng-1.0.2a
+ */
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ png_ptr->usr_channels = 4;
+ }
+
+ /* Also I added this in libpng-1.0.2a (what happens when we expand
+ * a less-than-8-bit grayscale to GA? */
+
+ if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
+ {
+ png_ptr->usr_channels = 2;
+ }
+}
+
+#ifndef PNG_1_0_X
+/* Added to libpng-1.2.7 */
+void PNGAPI
+png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+{
+ png_debug(1, "in png_set_add_alpha");
+
+ if (png_ptr == NULL)
+ return;
+ png_set_filler(png_ptr, filler, filler_loc);
+ png_ptr->transformations |= PNG_ADD_ALPHA;
+}
+#endif
+
+#endif
+
+#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
+ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_swap_alpha(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_swap_alpha");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_SWAP_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
+ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
+void PNGAPI
+png_set_invert_alpha(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_invert_alpha");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_INVERT_ALPHA;
+}
+#endif
+
+#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
+void PNGAPI
+png_set_invert_mono(png_structp png_ptr)
+{
+ png_debug(1, "in png_set_invert_mono");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_INVERT_MONO;
+}
+
+/* Invert monochrome grayscale data */
+void /* PRIVATE */
+png_do_invert(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_invert");
+
+ /* This test removed from libpng version 1.0.13 and 1.2.0:
+ * if (row_info->bit_depth == 1 &&
+ */
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row == NULL || row_info == NULL)
+ return;
+#endif
+ if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ png_bytep rp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+
+ for (i = 0; i < istop; i++)
+ {
+ *rp = (png_byte)(~(*rp));
+ rp++;
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+ row_info->bit_depth == 8)
+ {
+ png_bytep rp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+
+ for (i = 0; i < istop; i+=2)
+ {
+ *rp = (png_byte)(~(*rp));
+ rp+=2;
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+ row_info->bit_depth == 16)
+ {
+ png_bytep rp = row;
+ png_uint_32 i;
+ png_uint_32 istop = row_info->rowbytes;
+
+ for (i = 0; i < istop; i+=4)
+ {
+ *rp = (png_byte)(~(*rp));
+ *(rp+1) = (png_byte)(~(*(rp+1)));
+ rp+=4;
+ }
+ }
+}
+#endif
+
+#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
+/* Swaps byte order on 16 bit depth images */
+void /* PRIVATE */
+png_do_swap(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_swap");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ row_info->bit_depth == 16)
+ {
+ png_bytep rp = row;
+ png_uint_32 i;
+ png_uint_32 istop= row_info->width * row_info->channels;
+
+ for (i = 0; i < istop; i++, rp += 2)
+ {
+ png_byte t = *rp;
+ *rp = *(rp + 1);
+ *(rp + 1) = t;
+ }
+ }
+}
+#endif
+
+#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
+static PNG_CONST png_byte onebppswaptable[256] = {
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+static PNG_CONST png_byte twobppswaptable[256] = {
+ 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
+ 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
+ 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
+ 0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
+ 0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
+ 0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
+ 0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
+ 0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
+ 0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
+ 0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
+ 0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
+ 0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
+ 0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
+ 0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
+ 0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
+ 0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
+ 0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
+ 0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
+ 0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
+ 0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
+ 0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
+ 0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
+ 0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
+ 0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
+ 0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
+ 0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
+ 0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
+ 0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
+ 0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
+ 0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
+ 0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
+ 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
+};
+
+static PNG_CONST png_byte fourbppswaptable[256] = {
+ 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
+ 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
+ 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
+ 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
+ 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
+ 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
+ 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
+ 0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
+ 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
+ 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
+ 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
+ 0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
+ 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
+ 0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
+ 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
+ 0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
+ 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
+ 0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
+ 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
+ 0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
+ 0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
+ 0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
+ 0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
+ 0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
+ 0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
+ 0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
+ 0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
+ 0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
+ 0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
+ 0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
+ 0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
+ 0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
+};
+
+/* Swaps pixel packing order within bytes */
+void /* PRIVATE */
+png_do_packswap(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_packswap");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ row_info->bit_depth < 8)
+ {
+ png_bytep rp, end, table;
+
+ end = row + row_info->rowbytes;
+
+ if (row_info->bit_depth == 1)
+ table = (png_bytep)onebppswaptable;
+ else if (row_info->bit_depth == 2)
+ table = (png_bytep)twobppswaptable;
+ else if (row_info->bit_depth == 4)
+ table = (png_bytep)fourbppswaptable;
+ else
+ return;
+
+ for (rp = row; rp < end; rp++)
+ *rp = table[*rp];
+ }
+}
+#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+
+#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
+ defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
+/* Remove filler or alpha byte(s) */
+void /* PRIVATE */
+png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
+{
+ png_debug(1, "in png_do_strip_filler");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ png_bytep sp=row;
+ png_bytep dp=row;
+ png_uint_32 row_width=row_info->width;
+ png_uint_32 i;
+
+ if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+ (flags & PNG_FLAG_STRIP_ALPHA))) &&
+ row_info->channels == 4)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ /* This converts from RGBX or RGBA to RGB */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ dp+=3; sp+=4;
+ for (i = 1; i < row_width; i++)
+ {
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ sp++;
+ }
+ }
+ /* This converts from XRGB or ARGB to RGB */
+ else
+ {
+ for (i = 0; i < row_width; i++)
+ {
+ sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ }
+ }
+ row_info->pixel_depth = 24;
+ row_info->rowbytes = row_width * 3;
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
+ sp += 8; dp += 6;
+ for (i = 1; i < row_width; i++)
+ {
+ /* This could be (although png_memcpy is probably slower):
+ png_memcpy(dp, sp, 6);
+ sp += 8;
+ dp += 6;
+ */
+
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ sp += 2;
+ }
+ }
+ else
+ {
+ /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
+ for (i = 0; i < row_width; i++)
+ {
+ /* This could be (although png_memcpy is probably slower):
+ png_memcpy(dp, sp, 6);
+ sp += 8;
+ dp += 6;
+ */
+
+ sp+=2;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ }
+ }
+ row_info->pixel_depth = 48;
+ row_info->rowbytes = row_width * 6;
+ }
+ row_info->channels = 3;
+ }
+ else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
+ (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+ (flags & PNG_FLAG_STRIP_ALPHA))) &&
+ row_info->channels == 2)
+ {
+ if (row_info->bit_depth == 8)
+ {
+ /* This converts from GX or GA to G */
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ for (i = 0; i < row_width; i++)
+ {
+ *dp++ = *sp++;
+ sp++;
+ }
+ }
+ /* This converts from XG or AG to G */
+ else
+ {
+ for (i = 0; i < row_width; i++)
+ {
+ sp++;
+ *dp++ = *sp++;
+ }
+ }
+ row_info->pixel_depth = 8;
+ row_info->rowbytes = row_width;
+ }
+ else /* if (row_info->bit_depth == 16) */
+ {
+ if (flags & PNG_FLAG_FILLER_AFTER)
+ {
+ /* This converts from GGXX or GGAA to GG */
+ sp += 4; dp += 2;
+ for (i = 1; i < row_width; i++)
+ {
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ sp += 2;
+ }
+ }
+ else
+ {
+ /* This converts from XXGG or AAGG to GG */
+ for (i = 0; i < row_width; i++)
+ {
+ sp += 2;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ }
+ }
+ row_info->pixel_depth = 16;
+ row_info->rowbytes = row_width * 2;
+ }
+ row_info->channels = 1;
+ }
+ if (flags & PNG_FLAG_STRIP_ALPHA)
+ row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
+ }
+}
+#endif
+
+#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
+/* Swaps red and blue bytes within a pixel */
+void /* PRIVATE */
+png_do_bgr(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_bgr");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ {
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += 3)
+ {
+ png_byte save = *rp;
+ *rp = *(rp + 2);
+ *(rp + 2) = save;
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += 4)
+ {
+ png_byte save = *rp;
+ *rp = *(rp + 2);
+ *(rp + 2) = save;
+ }
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += 6)
+ {
+ png_byte save = *rp;
+ *rp = *(rp + 4);
+ *(rp + 4) = save;
+ save = *(rp + 1);
+ *(rp + 1) = *(rp + 5);
+ *(rp + 5) = save;
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += 8)
+ {
+ png_byte save = *rp;
+ *rp = *(rp + 4);
+ *(rp + 4) = save;
+ save = *(rp + 1);
+ *(rp + 1) = *(rp + 5);
+ *(rp + 5) = save;
+ }
+ }
+ }
+ }
+}
+#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+
+#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
+ defined(PNG_LEGACY_SUPPORTED) || \
+ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
+void PNGAPI
+png_set_user_transform_info(png_structp png_ptr, png_voidp
+ user_transform_ptr, int user_transform_depth, int user_transform_channels)
+{
+ png_debug(1, "in png_set_user_transform_info");
+
+ if (png_ptr == NULL)
+ return;
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+ png_ptr->user_transform_ptr = user_transform_ptr;
+ png_ptr->user_transform_depth = (png_byte)user_transform_depth;
+ png_ptr->user_transform_channels = (png_byte)user_transform_channels;
+#else
+ if (user_transform_ptr || user_transform_depth || user_transform_channels)
+ png_warning(png_ptr,
+ "This version of libpng does not support user transform info");
+#endif
+}
+#endif
+
+/* This function returns a pointer to the user_transform_ptr associated with
+ * the user transform functions. The application should free any memory
+ * associated with this pointer before png_write_destroy and png_read_destroy
+ * are called.
+ */
+png_voidp PNGAPI
+png_get_user_transform_ptr(png_structp png_ptr)
+{
+ if (png_ptr == NULL)
+ return (NULL);
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+ return ((png_voidp)png_ptr->user_transform_ptr);
+#else
+ return (NULL);
+#endif
+}
+#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngvcrd.c b/Source/LibPNG/pngvcrd.c
new file mode 100644
index 0000000..d0670c4
--- /dev/null
+++ b/Source/LibPNG/pngvcrd.c
@@ -0,0 +1,12 @@
+/* pngvcrd.c
+ *
+ * Last changed in libpng 1.2.48 [March 29, 2012]
+ * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This nearly empty file is for use by configure's compilation test. The
+ * remainder of the file was removed from libpng-1.2.20.
+ */
diff --git a/Source/LibPNG/pngwio.c b/Source/LibPNG/pngwio.c
new file mode 100644
index 0000000..44e5ea9
--- /dev/null
+++ b/Source/LibPNG/pngwio.c
@@ -0,0 +1,260 @@
+
+/* pngwio.c - functions for data output
+ *
+ * Last changed in libpng 1.2.41 [December 3, 2009]
+ * Copyright (c) 1998-2009 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This file provides a location for all output. Users who need
+ * special handling are expected to write functions that have the same
+ * arguments as these and perform similar functions, but that possibly
+ * use different output methods. Note that you shouldn't change these
+ * functions, but rather write replacement functions and then change
+ * them at run time with png_set_write_fn(...).
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Write the data to whatever output you are using. The default routine
+ * writes to a file pointer. Note that this routine sometimes gets called
+ * with very small lengths, so you should implement some kind of simple
+ * buffering if you are using unbuffered writes. This should never be asked
+ * to write more than 64K on a 16 bit machine.
+ */
+
+void /* PRIVATE */
+png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ if (png_ptr->write_data_fn != NULL )
+ (*(png_ptr->write_data_fn))(png_ptr, data, length);
+ else
+ png_error(png_ptr, "Call to NULL write function");
+}
+
+#ifdef PNG_STDIO_SUPPORTED
+/* This is the function that does the actual writing of data. If you are
+ * not writing to a standard C stream, you should create a replacement
+ * write_data function and use it at run time with png_set_write_fn(), rather
+ * than changing the library.
+ */
+#ifndef USE_FAR_KEYWORD
+void PNGAPI
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_uint_32 check;
+
+ if (png_ptr == NULL)
+ return;
+#ifdef _WIN32_WCE
+ if ( !WriteFile((HANDLE)(png_ptr->io_ptr), data, length, &check, NULL) )
+ check = 0;
+#else
+ check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
+#endif
+ if (check != length)
+ png_error(png_ptr, "Write Error");
+}
+#else
+/* This is the model-independent version. Since the standard I/O library
+ * can't handle far buffers in the medium and small models, we have to copy
+ * the data.
+ */
+
+#define NEAR_BUF_SIZE 1024
+#define MIN(a,b) (a <= b ? a : b)
+
+void PNGAPI
+png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ png_uint_32 check;
+ png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
+ png_FILE_p io_ptr;
+
+ if (png_ptr == NULL)
+ return;
+ /* Check if data really is near. If so, use usual code. */
+ near_data = (png_byte *)CVT_PTR_NOCHECK(data);
+ io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
+ if ((png_bytep)near_data == data)
+ {
+#ifdef _WIN32_WCE
+ if ( !WriteFile(io_ptr, near_data, length, &check, NULL) )
+ check = 0;
+#else
+ check = fwrite(near_data, 1, length, io_ptr);
+#endif
+ }
+ else
+ {
+ png_byte buf[NEAR_BUF_SIZE];
+ png_size_t written, remaining, err;
+ check = 0;
+ remaining = length;
+ do
+ {
+ written = MIN(NEAR_BUF_SIZE, remaining);
+ png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
+#ifdef _WIN32_WCE
+ if ( !WriteFile(io_ptr, buf, written, &err, NULL) )
+ err = 0;
+#else
+ err = fwrite(buf, 1, written, io_ptr);
+#endif
+ if (err != written)
+ break;
+
+ else
+ check += err;
+
+ data += written;
+ remaining -= written;
+ }
+ while (remaining != 0);
+ }
+ if (check != length)
+ png_error(png_ptr, "Write Error");
+}
+
+#endif
+#endif
+
+/* This function is called to output any data pending writing (normally
+ * to disk). After png_flush is called, there should be no data pending
+ * writing in any buffers.
+ */
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+void /* PRIVATE */
+png_flush(png_structp png_ptr)
+{
+ if (png_ptr->output_flush_fn != NULL)
+ (*(png_ptr->output_flush_fn))(png_ptr);
+}
+
+#ifdef PNG_STDIO_SUPPORTED
+void PNGAPI
+png_default_flush(png_structp png_ptr)
+{
+#ifndef _WIN32_WCE
+ png_FILE_p io_ptr;
+#endif
+ if (png_ptr == NULL)
+ return;
+#ifndef _WIN32_WCE
+ io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+ fflush(io_ptr);
+#endif
+}
+#endif
+#endif
+
+/* This function allows the application to supply new output functions for
+ * libpng if standard C streams aren't being used.
+ *
+ * This function takes as its arguments:
+ * png_ptr - pointer to a png output data structure
+ * io_ptr - pointer to user supplied structure containing info about
+ * the output functions. May be NULL.
+ * write_data_fn - pointer to a new output function that takes as its
+ * arguments a pointer to a png_struct, a pointer to
+ * data to be written, and a 32-bit unsigned int that is
+ * the number of bytes to be written. The new write
+ * function should call png_error(png_ptr, "Error msg")
+ * to exit and output any fatal error messages. May be
+ * NULL, in which case libpng's default function will
+ * be used.
+ * flush_data_fn - pointer to a new flush function that takes as its
+ * arguments a pointer to a png_struct. After a call to
+ * the flush function, there should be no data in any buffers
+ * or pending transmission. If the output method doesn't do
+ * any buffering of output, a function prototype must still be
+ * supplied although it doesn't have to do anything. If
+ * PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
+ * time, output_flush_fn will be ignored, although it must be
+ * supplied for compatibility. May be NULL, in which case
+ * libpng's default function will be used, if
+ * PNG_WRITE_FLUSH_SUPPORTED is defined. This is not
+ * a good idea if io_ptr does not point to a standard
+ * *FILE structure.
+ */
+void PNGAPI
+png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+ png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
+{
+ if (png_ptr == NULL)
+ return;
+
+ png_ptr->io_ptr = io_ptr;
+
+#ifdef PNG_STDIO_SUPPORTED
+ if (write_data_fn != NULL)
+ png_ptr->write_data_fn = write_data_fn;
+
+ else
+ png_ptr->write_data_fn = png_default_write_data;
+#else
+ png_ptr->write_data_fn = write_data_fn;
+#endif
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
+ if (output_flush_fn != NULL)
+ png_ptr->output_flush_fn = output_flush_fn;
+
+ else
+ png_ptr->output_flush_fn = png_default_flush;
+#else
+ png_ptr->output_flush_fn = output_flush_fn;
+#endif
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+ /* It is an error to read while writing a png file */
+ if (png_ptr->read_data_fn != NULL)
+ {
+ png_ptr->read_data_fn = NULL;
+ png_warning(png_ptr,
+ "Attempted to set both read_data_fn and write_data_fn in");
+ png_warning(png_ptr,
+ "the same structure. Resetting read_data_fn to NULL.");
+ }
+}
+
+#ifdef USE_FAR_KEYWORD
+#ifdef _MSC_VER
+void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
+{
+ void *near_ptr;
+ void FAR *far_ptr;
+ FP_OFF(near_ptr) = FP_OFF(ptr);
+ far_ptr = (void FAR *)near_ptr;
+
+ if (check != 0)
+ if (FP_SEG(ptr) != FP_SEG(far_ptr))
+ png_error(png_ptr, "segment lost in conversion");
+
+ return(near_ptr);
+}
+# else
+void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
+{
+ void *near_ptr;
+ void FAR *far_ptr;
+ near_ptr = (void FAR *)ptr;
+ far_ptr = (void FAR *)near_ptr;
+
+ if (check != 0)
+ if (far_ptr != ptr)
+ png_error(png_ptr, "segment lost in conversion");
+
+ return(near_ptr);
+}
+# endif
+# endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngwrite.c b/Source/LibPNG/pngwrite.c
new file mode 100644
index 0000000..1d8c53f
--- /dev/null
+++ b/Source/LibPNG/pngwrite.c
@@ -0,0 +1,1593 @@
+
+/* pngwrite.c - general routines to write a PNG file
+ *
+ * Last changed in libpng 1.2.45 [July 7, 2011]
+ * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+/* Get internal access to png.h */
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Writes all the PNG information. This is the suggested way to use the
+ * library. If you have a new chunk to add, make a function to write it,
+ * and put it in the correct location here. If you want the chunk written
+ * after the image data, put it in png_write_end(). I strongly encourage
+ * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
+ * the chunk, as that will keep the code from breaking if you want to just
+ * write a plain PNG file. If you have long comments, I suggest writing
+ * them in png_write_end(), and compressing them.
+ */
+void PNGAPI
+png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_write_info_before_PLTE");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+ if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ {
+ /* Write PNG signature */
+ png_write_sig(png_ptr);
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
+ (png_ptr->mng_features_permitted))
+ {
+ png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
+ png_ptr->mng_features_permitted = 0;
+ }
+#endif
+ /* Write IHDR information. */
+ png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
+ info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
+ info_ptr->filter_type,
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ info_ptr->interlace_type);
+#else
+ 0);
+#endif
+ /* The rest of these check to see if the valid field has the appropriate
+ * flag set, and if it does, writes the chunk.
+ */
+#ifdef PNG_WRITE_gAMA_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_gAMA)
+ {
+# ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_write_gAMA(png_ptr, info_ptr->gamma);
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
+# endif
+#endif
+ }
+#endif
+#ifdef PNG_WRITE_sRGB_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sRGB)
+ png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+#endif
+#ifdef PNG_WRITE_iCCP_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_iCCP)
+ png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
+ info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
+#endif
+#ifdef PNG_WRITE_sBIT_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sBIT)
+ png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
+#endif
+#ifdef PNG_WRITE_cHRM_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_cHRM)
+ {
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+ png_write_cHRM(png_ptr,
+ info_ptr->x_white, info_ptr->y_white,
+ info_ptr->x_red, info_ptr->y_red,
+ info_ptr->x_green, info_ptr->y_green,
+ info_ptr->x_blue, info_ptr->y_blue);
+#else
+# ifdef PNG_FIXED_POINT_SUPPORTED
+ png_write_cHRM_fixed(png_ptr,
+ info_ptr->int_x_white, info_ptr->int_y_white,
+ info_ptr->int_x_red, info_ptr->int_y_red,
+ info_ptr->int_x_green, info_ptr->int_y_green,
+ info_ptr->int_x_blue, info_ptr->int_y_blue);
+# endif
+#endif
+ }
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ if (info_ptr->unknown_chunks_num)
+ {
+ png_unknown_chunk *up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ up++)
+ {
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ up->location && !(up->location & PNG_HAVE_PLTE) &&
+ !(up->location & PNG_HAVE_IDAT) &&
+ ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+ {
+ if (up->size == 0)
+ png_warning(png_ptr, "Writing zero-length unknown chunk");
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
+ }
+ }
+#endif
+ png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
+ }
+}
+
+void PNGAPI
+png_write_info(png_structp png_ptr, png_infop info_ptr)
+{
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+ int i;
+#endif
+
+ png_debug(1, "in png_write_info");
+
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ png_write_info_before_PLTE(png_ptr, info_ptr);
+
+ if (info_ptr->valid & PNG_INFO_PLTE)
+ png_write_PLTE(png_ptr, info_ptr->palette,
+ (png_uint_32)info_ptr->num_palette);
+ else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ png_error(png_ptr, "Valid palette required for paletted images");
+
+#ifdef PNG_WRITE_tRNS_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_tRNS)
+ {
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ /* Invert the alpha channel (in tRNS) */
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+ info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ int j;
+ for (j = 0; j<(int)info_ptr->num_trans; j++)
+ info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
+ }
+#endif
+ png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
+ info_ptr->num_trans, info_ptr->color_type);
+ }
+#endif
+#ifdef PNG_WRITE_bKGD_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_bKGD)
+ png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
+#endif
+#ifdef PNG_WRITE_hIST_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_hIST)
+ png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
+#endif
+#ifdef PNG_WRITE_oFFs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_oFFs)
+ png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
+ info_ptr->offset_unit_type);
+#endif
+#ifdef PNG_WRITE_pCAL_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_pCAL)
+ png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
+ info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
+ info_ptr->pcal_units, info_ptr->pcal_params);
+#endif
+
+#ifdef PNG_sCAL_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sCAL)
+#ifdef PNG_WRITE_sCAL_SUPPORTED
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+ png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
+ info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
+#else /* !FLOATING_POINT */
+#ifdef PNG_FIXED_POINT_SUPPORTED
+ png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
+ info_ptr->scal_s_width, info_ptr->scal_s_height);
+#endif /* FIXED_POINT */
+#endif /* FLOATING_POINT */
+#else /* !WRITE_sCAL */
+ png_warning(png_ptr,
+ "png_write_sCAL not supported; sCAL chunk not written.");
+#endif /* WRITE_sCAL */
+#endif /* sCAL */
+
+#ifdef PNG_WRITE_pHYs_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_pHYs)
+ png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
+ info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
+#endif /* pHYs */
+
+#ifdef PNG_WRITE_tIME_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_tIME)
+ {
+ png_write_tIME(png_ptr, &(info_ptr->mod_time));
+ png_ptr->mode |= PNG_WROTE_tIME;
+ }
+#endif /* tIME */
+
+#ifdef PNG_WRITE_sPLT_SUPPORTED
+ if (info_ptr->valid & PNG_INFO_sPLT)
+ for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
+ png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
+#endif /* sPLT */
+
+#ifdef PNG_WRITE_TEXT_SUPPORTED
+ /* Check to see if we need to write text chunks */
+ for (i = 0; i < info_ptr->num_text; i++)
+ {
+ png_debug2(2, "Writing header text chunk %d, type %d", i,
+ info_ptr->text[i].compression);
+ /* An internationalized chunk? */
+ if (info_ptr->text[i].compression > 0)
+ {
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+ /* Write international chunk */
+ png_write_iTXt(png_ptr,
+ info_ptr->text[i].compression,
+ info_ptr->text[i].key,
+ info_ptr->text[i].lang,
+ info_ptr->text[i].lang_key,
+ info_ptr->text[i].text);
+#else
+ png_warning(png_ptr, "Unable to write international text");
+#endif
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ }
+ /* If we want a compressed text chunk */
+ else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
+ {
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+ /* Write compressed chunk */
+ png_write_zTXt(png_ptr, info_ptr->text[i].key,
+ info_ptr->text[i].text, 0,
+ info_ptr->text[i].compression);
+#else
+ png_warning(png_ptr, "Unable to write compressed text");
+#endif
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+ }
+ else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ {
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+ /* Write uncompressed chunk */
+ png_write_tEXt(png_ptr, info_ptr->text[i].key,
+ info_ptr->text[i].text,
+ 0);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+#else
+ /* Can't get here */
+ png_warning(png_ptr, "Unable to write uncompressed text");
+#endif
+ }
+ }
+#endif /* tEXt */
+
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ if (info_ptr->unknown_chunks_num)
+ {
+ png_unknown_chunk *up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ up++)
+ {
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ up->location && (up->location & PNG_HAVE_PLTE) &&
+ !(up->location & PNG_HAVE_IDAT) &&
+ !(up->location & PNG_AFTER_IDAT) &&
+ ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+ {
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
+ }
+ }
+#endif
+}
+
+/* Writes the end of the PNG file. If you don't want to write comments or
+ * time information, you can pass NULL for info. If you already wrote these
+ * in png_write_info(), do not write them again here. If you have long
+ * comments, I suggest writing them here, and compressing them.
+ */
+void PNGAPI
+png_write_end(png_structp png_ptr, png_infop info_ptr)
+{
+ png_debug(1, "in png_write_end");
+
+ if (png_ptr == NULL)
+ return;
+ if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ png_error(png_ptr, "No IDATs written into file");
+
+ /* See if user wants us to write information chunks */
+ if (info_ptr != NULL)
+ {
+#ifdef PNG_WRITE_TEXT_SUPPORTED
+ int i; /* local index variable */
+#endif
+#ifdef PNG_WRITE_tIME_SUPPORTED
+ /* Check to see if user has supplied a time chunk */
+ if ((info_ptr->valid & PNG_INFO_tIME) &&
+ !(png_ptr->mode & PNG_WROTE_tIME))
+ png_write_tIME(png_ptr, &(info_ptr->mod_time));
+#endif
+#ifdef PNG_WRITE_TEXT_SUPPORTED
+ /* Loop through comment chunks */
+ for (i = 0; i < info_ptr->num_text; i++)
+ {
+ png_debug2(2, "Writing trailer text chunk %d, type %d", i,
+ info_ptr->text[i].compression);
+ /* An internationalized chunk? */
+ if (info_ptr->text[i].compression > 0)
+ {
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+ /* Write international chunk */
+ png_write_iTXt(png_ptr,
+ info_ptr->text[i].compression,
+ info_ptr->text[i].key,
+ info_ptr->text[i].lang,
+ info_ptr->text[i].lang_key,
+ info_ptr->text[i].text);
+#else
+ png_warning(png_ptr, "Unable to write international text");
+#endif
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ }
+ else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
+ {
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+ /* Write compressed chunk */
+ png_write_zTXt(png_ptr, info_ptr->text[i].key,
+ info_ptr->text[i].text, 0,
+ info_ptr->text[i].compression);
+#else
+ png_warning(png_ptr, "Unable to write compressed text");
+#endif
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
+ }
+ else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ {
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+ /* Write uncompressed chunk */
+ png_write_tEXt(png_ptr, info_ptr->text[i].key,
+ info_ptr->text[i].text, 0);
+#else
+ png_warning(png_ptr, "Unable to write uncompressed text");
+#endif
+
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ }
+ }
+#endif
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ if (info_ptr->unknown_chunks_num)
+ {
+ png_unknown_chunk *up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ up++)
+ {
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ up->location && (up->location & PNG_AFTER_IDAT) &&
+ ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
+ {
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
+ }
+ }
+#endif
+ }
+
+ png_ptr->mode |= PNG_AFTER_IDAT;
+
+ /* Write end of PNG file */
+ png_write_IEND(png_ptr);
+ /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
+ * and restored again in libpng-1.2.30, may cause some applications that
+ * do not set png_ptr->output_flush_fn to crash. If your application
+ * experiences a problem, please try building libpng with
+ * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
+ * png-mng-implement at lists.sf.net .
+ */
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
+ png_flush(png_ptr);
+# endif
+#endif
+}
+
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+/* "tm" structure is not supported on WindowsCE */
+void PNGAPI
+png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
+{
+ png_debug(1, "in png_convert_from_struct_tm");
+
+ ptime->year = (png_uint_16)(1900 + ttime->tm_year);
+ ptime->month = (png_byte)(ttime->tm_mon + 1);
+ ptime->day = (png_byte)ttime->tm_mday;
+ ptime->hour = (png_byte)ttime->tm_hour;
+ ptime->minute = (png_byte)ttime->tm_min;
+ ptime->second = (png_byte)ttime->tm_sec;
+}
+
+void PNGAPI
+png_convert_from_time_t(png_timep ptime, time_t ttime)
+{
+ struct tm *tbuf;
+
+ png_debug(1, "in png_convert_from_time_t");
+
+ tbuf = gmtime(&ttime);
+ png_convert_from_struct_tm(ptime, tbuf);
+}
+#endif
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn)
+{
+#ifdef PNG_USER_MEM_SUPPORTED
+ return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
+}
+
+/* Alternate initialize png_ptr structure, and allocate any memory needed */
+png_structp PNGAPI
+png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+#ifdef PNG_SETJMP_SUPPORTED
+ volatile
+#endif
+ png_structp png_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+ jmp_buf jmpbuf;
+#endif
+#endif
+ int i;
+
+ png_debug(1, "in png_create_write_struct");
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+ (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
+#else
+ png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+#endif /* PNG_USER_MEM_SUPPORTED */
+ if (png_ptr == NULL)
+ return (NULL);
+
+ /* Added at libpng-1.2.6 */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+ png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+#else
+ if (setjmp(png_ptr->jmpbuf))
+#endif
+ {
+ png_free(png_ptr, png_ptr->zbuf);
+ png_ptr->zbuf = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)png_ptr,
+ (png_free_ptr)free_fn, (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)png_ptr);
+#endif
+ return (NULL);
+ }
+#ifdef USE_FAR_KEYWORD
+ png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
+#endif
+#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif /* PNG_USER_MEM_SUPPORTED */
+ png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
+
+ if (user_png_ver)
+ {
+ i = 0;
+ do
+ {
+ if (user_png_ver[i] != png_libpng_ver[i])
+ png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+ } while (png_libpng_ver[i++]);
+ }
+
+ if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+ {
+ /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+ * we must recompile any applications that use any older library version.
+ * For versions after libpng 1.0, we will be compatible, so we need
+ * only check the first digit.
+ */
+ if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+ (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+ (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char msg[80];
+ if (user_png_ver)
+ {
+ png_snprintf(msg, 80,
+ "Application was compiled with png.h from libpng-%.20s",
+ user_png_ver);
+ png_warning(png_ptr, msg);
+ }
+ png_snprintf(msg, 80,
+ "Application is running with png.c from libpng-%.20s",
+ png_libpng_ver);
+ png_warning(png_ptr, msg);
+#endif
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "Incompatible libpng version in application and library");
+ }
+ }
+
+ /* Initialize zbuf - compression buffer */
+ png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+ png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+
+ png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
+ png_flush_ptr_NULL);
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+ 1, png_doublep_NULL, png_doublep_NULL);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Applications that neglect to set up their own setjmp() and then
+ * encounter a png_error() will longjmp here. Since the jmpbuf is
+ * then meaningless we abort instead of returning.
+ */
+#ifdef USE_FAR_KEYWORD
+ if (setjmp(jmpbuf))
+ PNG_ABORT();
+ png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
+#else
+ if (setjmp(png_ptr->jmpbuf))
+ PNG_ABORT();
+#endif
+#endif
+ return (png_ptr);
+}
+
+/* Initialize png_ptr structure, and allocate any memory needed */
+#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
+/* Deprecated. */
+#undef png_write_init
+void PNGAPI
+png_write_init(png_structp png_ptr)
+{
+ /* We only come here via pre-1.0.7-compiled applications */
+ png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
+}
+
+void PNGAPI
+png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver,
+ png_size_t png_struct_size, png_size_t png_info_size)
+{
+ /* We only come here via pre-1.0.12-compiled applications */
+ if (png_ptr == NULL) return;
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ if (png_sizeof(png_struct) > png_struct_size ||
+ png_sizeof(png_info) > png_info_size)
+ {
+ char msg[80];
+ png_ptr->warning_fn = NULL;
+ if (user_png_ver)
+ {
+ png_snprintf(msg, 80,
+ "Application was compiled with png.h from libpng-%.20s",
+ user_png_ver);
+ png_warning(png_ptr, msg);
+ }
+ png_snprintf(msg, 80,
+ "Application is running with png.c from libpng-%.20s",
+ png_libpng_ver);
+ png_warning(png_ptr, msg);
+ }
+#endif
+ if (png_sizeof(png_struct) > png_struct_size)
+ {
+ png_ptr->error_fn = NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "The png struct allocated by the application for writing is"
+ " too small.");
+ }
+ if (png_sizeof(png_info) > png_info_size)
+ {
+ png_ptr->error_fn = NULL;
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+ png_ptr->flags = 0;
+#endif
+ png_error(png_ptr,
+ "The info struct allocated by the application for writing is"
+ " too small.");
+ }
+ png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
+}
+#endif /* PNG_1_0_X || PNG_1_2_X */
+
+
+void PNGAPI
+png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
+ png_size_t png_struct_size)
+{
+ png_structp png_ptr = *ptr_ptr;
+#ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf tmp_jmp; /* to save current jump buffer */
+#endif
+
+ int i = 0;
+
+ if (png_ptr == NULL)
+ return;
+
+ do
+ {
+ if (user_png_ver[i] != png_libpng_ver[i])
+ {
+#ifdef PNG_LEGACY_SUPPORTED
+ png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+#else
+ png_ptr->warning_fn = NULL;
+ png_warning(png_ptr,
+ "Application uses deprecated png_write_init() and should be recompiled.");
+#endif
+ }
+ } while (png_libpng_ver[i++]);
+
+ png_debug(1, "in png_write_init_3");
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Save jump buffer and error functions */
+ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
+#endif
+
+ if (png_sizeof(png_struct) > png_struct_size)
+ {
+ png_destroy_struct(png_ptr);
+ png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
+ *ptr_ptr = png_ptr;
+ }
+
+ /* Reset all variables to 0 */
+ png_memset(png_ptr, 0, png_sizeof(png_struct));
+
+ /* Added at libpng-1.2.6 */
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
+ png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Restore jump buffer */
+ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
+#endif
+
+ png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
+ png_flush_ptr_NULL);
+
+ /* Initialize zbuf - compression buffer */
+ png_ptr->zbuf_size = PNG_ZBUF_SIZE;
+ png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
+ 1, png_doublep_NULL, png_doublep_NULL);
+#endif
+}
+
+/* Write a few rows of image data. If the image is interlaced,
+ * either you will have to write the 7 sub images, or, if you
+ * have called png_set_interlace_handling(), you will have to
+ * "write" the image seven times.
+ */
+void PNGAPI
+png_write_rows(png_structp png_ptr, png_bytepp row,
+ png_uint_32 num_rows)
+{
+ png_uint_32 i; /* row counter */
+ png_bytepp rp; /* row pointer */
+
+ png_debug(1, "in png_write_rows");
+
+ if (png_ptr == NULL)
+ return;
+
+ /* Loop through the rows */
+ for (i = 0, rp = row; i < num_rows; i++, rp++)
+ {
+ png_write_row(png_ptr, *rp);
+ }
+}
+
+/* Write the image. You only need to call this function once, even
+ * if you are writing an interlaced image.
+ */
+void PNGAPI
+png_write_image(png_structp png_ptr, png_bytepp image)
+{
+ png_uint_32 i; /* row index */
+ int pass, num_pass; /* pass variables */
+ png_bytepp rp; /* points to current row */
+
+ if (png_ptr == NULL)
+ return;
+
+ png_debug(1, "in png_write_image");
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* Initialize interlace handling. If image is not interlaced,
+ * this will set pass to 1
+ */
+ num_pass = png_set_interlace_handling(png_ptr);
+#else
+ num_pass = 1;
+#endif
+ /* Loop through passes */
+ for (pass = 0; pass < num_pass; pass++)
+ {
+ /* Loop through image */
+ for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
+ {
+ png_write_row(png_ptr, *rp);
+ }
+ }
+}
+
+/* Called by user to write a row of image data */
+void PNGAPI
+png_write_row(png_structp png_ptr, png_bytep row)
+{
+ if (png_ptr == NULL)
+ return;
+
+ png_debug2(1, "in png_write_row (row %ld, pass %d)",
+ png_ptr->row_number, png_ptr->pass);
+
+ /* Initialize transformations and other stuff if first time */
+ if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+ {
+ /* Make sure we wrote the header info */
+ if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ png_error(png_ptr,
+ "png_write_info was never called before png_write_row.");
+
+ /* Check for transforms that have been set but were defined out */
+#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_warning(png_ptr,
+ "PNG_WRITE_INVERT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
+ if (png_ptr->transformations & PNG_FILLER)
+ png_warning(png_ptr,
+ "PNG_WRITE_FILLER_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
+ defined(PNG_READ_PACKSWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_warning(png_ptr,
+ "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACK)
+ png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
+ if (png_ptr->transformations & PNG_SHIFT)
+ png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
+ if (png_ptr->transformations & PNG_BGR)
+ png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
+#endif
+#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_SWAP_BYTES)
+ png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
+#endif
+
+ png_write_start_row(png_ptr);
+ }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* If interlaced and not interested in row, return */
+ if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ {
+ switch (png_ptr->pass)
+ {
+ case 0:
+ if (png_ptr->row_number & 0x07)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 1:
+ if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 2:
+ if ((png_ptr->row_number & 0x07) != 4)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 3:
+ if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 4:
+ if ((png_ptr->row_number & 0x03) != 2)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 5:
+ if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ case 6:
+ if (!(png_ptr->row_number & 0x01))
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ break;
+ }
+ }
+#endif
+
+ /* Set up row info for transformations */
+ png_ptr->row_info.color_type = png_ptr->color_type;
+ png_ptr->row_info.width = png_ptr->usr_width;
+ png_ptr->row_info.channels = png_ptr->usr_channels;
+ png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
+ png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
+ png_ptr->row_info.channels);
+
+ png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
+ png_ptr->row_info.width);
+
+ png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type);
+ png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width);
+ png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels);
+ png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
+ png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
+ png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes);
+
+ /* Copy user's row into buffer, leaving room for filter byte. */
+ png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
+ png_ptr->row_info.rowbytes);
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* Handle interlacing */
+ if (png_ptr->interlaced && png_ptr->pass < 6 &&
+ (png_ptr->transformations & PNG_INTERLACE))
+ {
+ png_do_write_interlace(&(png_ptr->row_info),
+ png_ptr->row_buf + 1, png_ptr->pass);
+ /* This should always get caught above, but still ... */
+ if (!(png_ptr->row_info.width))
+ {
+ png_write_finish_row(png_ptr);
+ return;
+ }
+ }
+#endif
+
+ /* Handle other transformations */
+ if (png_ptr->transformations)
+ png_do_write_transformations(png_ptr);
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ /* Write filter_method 64 (intrapixel differencing) only if
+ * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ * 2. Libpng did not write a PNG signature (this filter_method is only
+ * used in PNG datastreams that are embedded in MNG datastreams) and
+ * 3. The application called png_permit_mng_features with a mask that
+ * included PNG_FLAG_MNG_FILTER_64 and
+ * 4. The filter_method is 64 and
+ * 5. The color_type is RGB or RGBA
+ */
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
+ {
+ /* Intrapixel differencing */
+ png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
+ }
+#endif
+
+ /* Find a filter if necessary, filter the row and write it out. */
+ png_write_find_filter(png_ptr, &(png_ptr->row_info));
+
+ if (png_ptr->write_row_fn != NULL)
+ (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+}
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+/* Set the automatic flush interval or 0 to turn flushing off */
+void PNGAPI
+png_set_flush(png_structp png_ptr, int nrows)
+{
+ png_debug(1, "in png_set_flush");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
+}
+
+/* Flush the current output buffers now */
+void PNGAPI
+png_write_flush(png_structp png_ptr)
+{
+ int wrote_IDAT;
+
+ png_debug(1, "in png_write_flush");
+
+ if (png_ptr == NULL)
+ return;
+ /* We have already written out all of the data */
+ if (png_ptr->row_number >= png_ptr->num_rows)
+ return;
+
+ do
+ {
+ int ret;
+
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
+ wrote_IDAT = 0;
+
+ /* Check for compression errors */
+ if (ret != Z_OK)
+ {
+ if (png_ptr->zstream.msg != NULL)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ else
+ png_error(png_ptr, "zlib error");
+ }
+
+ if (!(png_ptr->zstream.avail_out))
+ {
+ /* Write the IDAT and reset the zlib output buffer */
+ png_write_IDAT(png_ptr, png_ptr->zbuf,
+ png_ptr->zbuf_size);
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ wrote_IDAT = 1;
+ }
+ } while(wrote_IDAT == 1);
+
+ /* If there is any data left to be output, write it into a new IDAT */
+ if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
+ {
+ /* Write the IDAT and reset the zlib output buffer */
+ png_write_IDAT(png_ptr, png_ptr->zbuf,
+ png_ptr->zbuf_size - png_ptr->zstream.avail_out);
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ }
+ png_ptr->flush_rows = 0;
+ png_flush(png_ptr);
+}
+#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+
+/* Free all memory used by the write */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn = NULL;
+ png_voidp mem_ptr = NULL;
+#endif
+
+ png_debug(1, "in png_destroy_write_struct");
+
+ if (png_ptr_ptr != NULL)
+ {
+ png_ptr = *png_ptr_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+ mem_ptr = png_ptr->mem_ptr;
+#endif
+ }
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr != NULL)
+ {
+ free_fn = png_ptr->free_fn;
+ mem_ptr = png_ptr->mem_ptr;
+ }
+#endif
+
+ if (info_ptr_ptr != NULL)
+ info_ptr = *info_ptr_ptr;
+
+ if (info_ptr != NULL)
+ {
+ if (png_ptr != NULL)
+ {
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_ptr->num_chunk_list)
+ {
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
+ png_ptr->num_chunk_list = 0;
+ }
+#endif
+ }
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
+ (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)info_ptr);
+#endif
+ *info_ptr_ptr = NULL;
+ }
+
+ if (png_ptr != NULL)
+ {
+ png_write_destroy(png_ptr);
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
+ (png_voidp)mem_ptr);
+#else
+ png_destroy_struct((png_voidp)png_ptr);
+#endif
+ *png_ptr_ptr = NULL;
+ }
+}
+
+
+/* Free any memory used in png_ptr struct (old method) */
+void /* PRIVATE */
+png_write_destroy(png_structp png_ptr)
+{
+#ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf tmp_jmp; /* Save jump buffer */
+#endif
+ png_error_ptr error_fn;
+ png_error_ptr warning_fn;
+ png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn;
+#endif
+
+ png_debug(1, "in png_write_destroy");
+
+ /* Free any memory zlib uses */
+ deflateEnd(&png_ptr->zstream);
+
+ /* Free our memory. png_free checks NULL for us. */
+ png_free(png_ptr, png_ptr->zbuf);
+ png_free(png_ptr, png_ptr->row_buf);
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ png_free(png_ptr, png_ptr->prev_row);
+ png_free(png_ptr, png_ptr->sub_row);
+ png_free(png_ptr, png_ptr->up_row);
+ png_free(png_ptr, png_ptr->avg_row);
+ png_free(png_ptr, png_ptr->paeth_row);
+#endif
+
+#ifdef PNG_TIME_RFC1123_SUPPORTED
+ png_free(png_ptr, png_ptr->time_buffer);
+#endif
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ png_free(png_ptr, png_ptr->prev_filters);
+ png_free(png_ptr, png_ptr->filter_weights);
+ png_free(png_ptr, png_ptr->inv_filter_weights);
+ png_free(png_ptr, png_ptr->filter_costs);
+ png_free(png_ptr, png_ptr->inv_filter_costs);
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Reset structure */
+ png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
+#endif
+
+ error_fn = png_ptr->error_fn;
+ warning_fn = png_ptr->warning_fn;
+ error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+#endif
+
+ png_memset(png_ptr, 0, png_sizeof(png_struct));
+
+ png_ptr->error_fn = error_fn;
+ png_ptr->warning_fn = warning_fn;
+ png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_ptr->free_fn = free_fn;
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
+#endif
+}
+
+/* Allow the application to select one or more row filters to use. */
+void PNGAPI
+png_set_filter(png_structp png_ptr, int method, int filters)
+{
+ png_debug(1, "in png_set_filter");
+
+ if (png_ptr == NULL)
+ return;
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ (method == PNG_INTRAPIXEL_DIFFERENCING))
+ method = PNG_FILTER_TYPE_BASE;
+#endif
+ if (method == PNG_FILTER_TYPE_BASE)
+ {
+ switch (filters & (PNG_ALL_FILTERS | 0x07))
+ {
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ case 5:
+ case 6:
+ case 7: png_warning(png_ptr, "Unknown row filter for method 0");
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ case PNG_FILTER_VALUE_NONE:
+ png_ptr->do_filter = PNG_FILTER_NONE; break;
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ case PNG_FILTER_VALUE_SUB:
+ png_ptr->do_filter = PNG_FILTER_SUB; break;
+ case PNG_FILTER_VALUE_UP:
+ png_ptr->do_filter = PNG_FILTER_UP; break;
+ case PNG_FILTER_VALUE_AVG:
+ png_ptr->do_filter = PNG_FILTER_AVG; break;
+ case PNG_FILTER_VALUE_PAETH:
+ png_ptr->do_filter = PNG_FILTER_PAETH; break;
+ default: png_ptr->do_filter = (png_byte)filters; break;
+#else
+ default: png_warning(png_ptr, "Unknown row filter for method 0");
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ }
+
+ /* If we have allocated the row_buf, this means we have already started
+ * with the image and we should have allocated all of the filter buffers
+ * that have been selected. If prev_row isn't already allocated, then
+ * it is too late to start using the filters that need it, since we
+ * will be missing the data in the previous row. If an application
+ * wants to start and stop using particular filters during compression,
+ * it should start out with all of the filters, and then add and
+ * remove them after the start of compression.
+ */
+ if (png_ptr->row_buf != NULL)
+ {
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
+ {
+ png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
+ (png_ptr->rowbytes + 1));
+ png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
+ }
+
+ if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
+ {
+ if (png_ptr->prev_row == NULL)
+ {
+ png_warning(png_ptr, "Can't add Up filter after starting");
+ png_ptr->do_filter &= ~PNG_FILTER_UP;
+ }
+ else
+ {
+ png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
+ (png_ptr->rowbytes + 1));
+ png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+ }
+ }
+
+ if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
+ {
+ if (png_ptr->prev_row == NULL)
+ {
+ png_warning(png_ptr, "Can't add Average filter after starting");
+ png_ptr->do_filter &= ~PNG_FILTER_AVG;
+ }
+ else
+ {
+ png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+ (png_ptr->rowbytes + 1));
+ png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+ }
+ }
+
+ if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
+ png_ptr->paeth_row == NULL)
+ {
+ if (png_ptr->prev_row == NULL)
+ {
+ png_warning(png_ptr, "Can't add Paeth filter after starting");
+ png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
+ }
+ else
+ {
+ png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
+ (png_ptr->rowbytes + 1));
+ png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+ }
+ }
+
+ if (png_ptr->do_filter == PNG_NO_FILTERS)
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ png_ptr->do_filter = PNG_FILTER_NONE;
+ }
+ }
+ else
+ png_error(png_ptr, "Unknown custom filter method");
+}
+
+/* This allows us to influence the way in which libpng chooses the "best"
+ * filter for the current scanline. While the "minimum-sum-of-absolute-
+ * differences metric is relatively fast and effective, there is some
+ * question as to whether it can be improved upon by trying to keep the
+ * filtered data going to zlib more consistent, hopefully resulting in
+ * better compression.
+ */
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
+void PNGAPI
+png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+ int num_weights, png_doublep filter_weights,
+ png_doublep filter_costs)
+{
+ int i;
+
+ png_debug(1, "in png_set_filter_heuristics");
+
+ if (png_ptr == NULL)
+ return;
+ if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
+ {
+ png_warning(png_ptr, "Unknown filter heuristic method");
+ return;
+ }
+
+ if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
+ {
+ heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
+ }
+
+ if (num_weights < 0 || filter_weights == NULL ||
+ heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
+ {
+ num_weights = 0;
+ }
+
+ png_ptr->num_prev_filters = (png_byte)num_weights;
+ png_ptr->heuristic_method = (png_byte)heuristic_method;
+
+ if (num_weights > 0)
+ {
+ if (png_ptr->prev_filters == NULL)
+ {
+ png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(png_sizeof(png_byte) * num_weights));
+
+ /* To make sure that the weighting starts out fairly */
+ for (i = 0; i < num_weights; i++)
+ {
+ png_ptr->prev_filters[i] = 255;
+ }
+ }
+
+ if (png_ptr->filter_weights == NULL)
+ {
+ png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+
+ png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ for (i = 0; i < num_weights; i++)
+ {
+ png_ptr->inv_filter_weights[i] =
+ png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+ }
+ }
+
+ for (i = 0; i < num_weights; i++)
+ {
+ if (filter_weights[i] < 0.0)
+ {
+ png_ptr->inv_filter_weights[i] =
+ png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
+ }
+ else
+ {
+ png_ptr->inv_filter_weights[i] =
+ (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
+ png_ptr->filter_weights[i] =
+ (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
+ }
+ }
+ }
+
+ /* If, in the future, there are other filter methods, this would
+ * need to be based on png_ptr->filter.
+ */
+ if (png_ptr->filter_costs == NULL)
+ {
+ png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+ png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
+ (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+
+ for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+ {
+ png_ptr->inv_filter_costs[i] =
+ png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+ }
+ }
+
+ /* Here is where we set the relative costs of the different filters. We
+ * should take the desired compression level into account when setting
+ * the costs, so that Paeth, for instance, has a high relative cost at low
+ * compression levels, while it has a lower relative cost at higher
+ * compression settings. The filter types are in order of increasing
+ * relative cost, so it would be possible to do this with an algorithm.
+ */
+ for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
+ {
+ if (filter_costs == NULL || filter_costs[i] < 0.0)
+ {
+ png_ptr->inv_filter_costs[i] =
+ png_ptr->filter_costs[i] = PNG_COST_FACTOR;
+ }
+ else if (filter_costs[i] >= 1.0)
+ {
+ png_ptr->inv_filter_costs[i] =
+ (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
+ png_ptr->filter_costs[i] =
+ (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
+ }
+ }
+}
+#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+
+void PNGAPI
+png_set_compression_level(png_structp png_ptr, int level)
+{
+ png_debug(1, "in png_set_compression_level");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
+ png_ptr->zlib_level = level;
+}
+
+void PNGAPI
+png_set_compression_mem_level(png_structp png_ptr, int mem_level)
+{
+ png_debug(1, "in png_set_compression_mem_level");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
+ png_ptr->zlib_mem_level = mem_level;
+}
+
+void PNGAPI
+png_set_compression_strategy(png_structp png_ptr, int strategy)
+{
+ png_debug(1, "in png_set_compression_strategy");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
+ png_ptr->zlib_strategy = strategy;
+}
+
+void PNGAPI
+png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+{
+ if (png_ptr == NULL)
+ return;
+ if (window_bits > 15)
+ png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ else if (window_bits < 8)
+ png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+#ifndef WBITS_8_OK
+ /* Avoid libpng bug with 256-byte windows */
+ if (window_bits == 8)
+ {
+ png_warning(png_ptr, "Compression window is being reset to 512");
+ window_bits = 9;
+ }
+#endif
+ png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
+ png_ptr->zlib_window_bits = window_bits;
+}
+
+void PNGAPI
+png_set_compression_method(png_structp png_ptr, int method)
+{
+ png_debug(1, "in png_set_compression_method");
+
+ if (png_ptr == NULL)
+ return;
+ if (method != 8)
+ png_warning(png_ptr, "Only compression method 8 is supported by PNG");
+ png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
+ png_ptr->zlib_method = method;
+}
+
+void PNGAPI
+png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+{
+ if (png_ptr == NULL)
+ return;
+ png_ptr->write_row_fn = write_row_fn;
+}
+
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+void PNGAPI
+png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+ write_user_transform_fn)
+{
+ png_debug(1, "in png_set_write_user_transform_fn");
+
+ if (png_ptr == NULL)
+ return;
+ png_ptr->transformations |= PNG_USER_TRANSFORM;
+ png_ptr->write_user_transform_fn = write_user_transform_fn;
+}
+#endif
+
+
+#ifdef PNG_INFO_IMAGE_SUPPORTED
+void PNGAPI
+png_write_png(png_structp png_ptr, png_infop info_ptr,
+ int transforms, voidp params)
+{
+ if (png_ptr == NULL || info_ptr == NULL)
+ return;
+
+ /* Write the file header information. */
+ png_write_info(png_ptr, info_ptr);
+
+ /* ------ these transformations don't touch the info structure ------- */
+
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ /* Invert monochrome pixels */
+ if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ png_set_invert_mono(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ /* Shift the pixels up to a legal bit depth and fill in
+ * as appropriate to correctly scale the image.
+ */
+ if ((transforms & PNG_TRANSFORM_SHIFT)
+ && (info_ptr->valid & PNG_INFO_sBIT))
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#endif
+
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ /* Pack pixels into bytes */
+ if (transforms & PNG_TRANSFORM_PACKING)
+ png_set_packing(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+ /* Swap location of alpha bytes from ARGB to RGBA */
+ if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ png_set_swap_alpha(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+ /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
+ if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#endif
+
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ /* Flip BGR pixels to RGB */
+ if (transforms & PNG_TRANSFORM_BGR)
+ png_set_bgr(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+ /* Swap bytes of 16-bit files to most significant byte first */
+ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ png_set_swap(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ /* Swap bits of 1, 2, 4 bit packed pixel formats */
+ if (transforms & PNG_TRANSFORM_PACKSWAP)
+ png_set_packswap(png_ptr);
+#endif
+
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ /* Invert the alpha channel from opacity to transparency */
+ if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ png_set_invert_alpha(png_ptr);
+#endif
+
+ /* ----------------------- end of transformations ------------------- */
+
+ /* Write the bits */
+ if (info_ptr->valid & PNG_INFO_IDAT)
+ png_write_image(png_ptr, info_ptr->row_pointers);
+
+ /* It is REQUIRED to call this to finish writing the rest of the file */
+ png_write_end(png_ptr, info_ptr);
+
+ transforms = transforms; /* Quiet compiler warnings */
+ params = params;
+}
+#endif
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngwtran.c b/Source/LibPNG/pngwtran.c
new file mode 100644
index 0000000..0ce9b9b
--- /dev/null
+++ b/Source/LibPNG/pngwtran.c
@@ -0,0 +1,582 @@
+
+/* pngwtran.c - transforms the data in a row for PNG writers
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Transform the data according to the user's wishes. The order of
+ * transformations is significant.
+ */
+void /* PRIVATE */
+png_do_write_transformations(png_structp png_ptr)
+{
+ png_debug(1, "in png_do_write_transformations");
+
+ if (png_ptr == NULL)
+ return;
+
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if (png_ptr->write_user_transform_fn != NULL)
+ (*(png_ptr->write_user_transform_fn)) /* User write transform
+ function */
+ (png_ptr, /* png_ptr */
+ &(png_ptr->row_info), /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_uint_32 rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#endif
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+ if (png_ptr->transformations & PNG_FILLER)
+ png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ png_ptr->flags);
+#endif
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ if (png_ptr->transformations & PNG_PACK)
+ png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->bit_depth);
+#endif
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+ if (png_ptr->transformations & PNG_SWAP_BYTES)
+ png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if (png_ptr->transformations & PNG_SHIFT)
+ png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+ if (png_ptr->transformations & PNG_SWAP_ALPHA)
+ png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_ALPHA)
+ png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ if (png_ptr->transformations & PNG_BGR)
+ png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
+#endif
+}
+
+#ifdef PNG_WRITE_PACK_SUPPORTED
+/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
+ * row_info bit depth should be 8 (one pixel per byte). The channels
+ * should be 1 (this only happens on grayscale and paletted images).
+ */
+void /* PRIVATE */
+png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
+{
+ png_debug(1, "in png_do_pack");
+
+ if (row_info->bit_depth == 8 &&
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ row_info->channels == 1)
+ {
+ switch ((int)bit_depth)
+ {
+ case 1:
+ {
+ png_bytep sp, dp;
+ int mask, v;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ sp = row;
+ dp = row;
+ mask = 0x80;
+ v = 0;
+
+ for (i = 0; i < row_width; i++)
+ {
+ if (*sp != 0)
+ v |= mask;
+ sp++;
+ if (mask > 1)
+ mask >>= 1;
+ else
+ {
+ mask = 0x80;
+ *dp = (png_byte)v;
+ dp++;
+ v = 0;
+ }
+ }
+ if (mask != 0x80)
+ *dp = (png_byte)v;
+ break;
+ }
+ case 2:
+ {
+ png_bytep sp, dp;
+ int shift, v;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ sp = row;
+ dp = row;
+ shift = 6;
+ v = 0;
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte value;
+
+ value = (png_byte)(*sp & 0x03);
+ v |= (value << shift);
+ if (shift == 0)
+ {
+ shift = 6;
+ *dp = (png_byte)v;
+ dp++;
+ v = 0;
+ }
+ else
+ shift -= 2;
+ sp++;
+ }
+ if (shift != 6)
+ *dp = (png_byte)v;
+ break;
+ }
+ case 4:
+ {
+ png_bytep sp, dp;
+ int shift, v;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ sp = row;
+ dp = row;
+ shift = 4;
+ v = 0;
+ for (i = 0; i < row_width; i++)
+ {
+ png_byte value;
+
+ value = (png_byte)(*sp & 0x0f);
+ v |= (value << shift);
+
+ if (shift == 0)
+ {
+ shift = 4;
+ *dp = (png_byte)v;
+ dp++;
+ v = 0;
+ }
+ else
+ shift -= 4;
+
+ sp++;
+ }
+ if (shift != 4)
+ *dp = (png_byte)v;
+ break;
+ }
+ }
+ row_info->bit_depth = (png_byte)bit_depth;
+ row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+ row_info->width);
+ }
+}
+#endif
+
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+/* Shift pixel values to take advantage of whole range. Pass the
+ * true number of bits in bit_depth. The row should be packed
+ * according to row_info->bit_depth. Thus, if you had a row of
+ * bit depth 4, but the pixels only had values from 0 to 7, you
+ * would pass 3 as bit_depth, and this routine would translate the
+ * data to 0 to 15.
+ */
+void /* PRIVATE */
+png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
+{
+ png_debug(1, "in png_do_shift");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL &&
+#else
+ if (
+#endif
+ row_info->color_type != PNG_COLOR_TYPE_PALETTE)
+ {
+ int shift_start[4], shift_dec[4];
+ int channels = 0;
+
+ if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ {
+ shift_start[channels] = row_info->bit_depth - bit_depth->red;
+ shift_dec[channels] = bit_depth->red;
+ channels++;
+ shift_start[channels] = row_info->bit_depth - bit_depth->green;
+ shift_dec[channels] = bit_depth->green;
+ channels++;
+ shift_start[channels] = row_info->bit_depth - bit_depth->blue;
+ shift_dec[channels] = bit_depth->blue;
+ channels++;
+ }
+ else
+ {
+ shift_start[channels] = row_info->bit_depth - bit_depth->gray;
+ shift_dec[channels] = bit_depth->gray;
+ channels++;
+ }
+ if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
+ shift_dec[channels] = bit_depth->alpha;
+ channels++;
+ }
+
+ /* With low row depths, could only be grayscale, so one channel */
+ if (row_info->bit_depth < 8)
+ {
+ png_bytep bp = row;
+ png_uint_32 i;
+ png_byte mask;
+ png_uint_32 row_bytes = row_info->rowbytes;
+
+ if (bit_depth->gray == 1 && row_info->bit_depth == 2)
+ mask = 0x55;
+ else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
+ mask = 0x11;
+ else
+ mask = 0xff;
+
+ for (i = 0; i < row_bytes; i++, bp++)
+ {
+ png_uint_16 v;
+ int j;
+
+ v = *bp;
+ *bp = 0;
+ for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
+ {
+ if (j > 0)
+ *bp |= (png_byte)((v << j) & 0xff);
+ else
+ *bp |= (png_byte)((v >> (-j)) & mask);
+ }
+ }
+ }
+ else if (row_info->bit_depth == 8)
+ {
+ png_bytep bp = row;
+ png_uint_32 i;
+ png_uint_32 istop = channels * row_info->width;
+
+ for (i = 0; i < istop; i++, bp++)
+ {
+
+ png_uint_16 v;
+ int j;
+ int c = (int)(i%channels);
+
+ v = *bp;
+ *bp = 0;
+ for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+ {
+ if (j > 0)
+ *bp |= (png_byte)((v << j) & 0xff);
+ else
+ *bp |= (png_byte)((v >> (-j)) & 0xff);
+ }
+ }
+ }
+ else
+ {
+ png_bytep bp;
+ png_uint_32 i;
+ png_uint_32 istop = channels * row_info->width;
+
+ for (bp = row, i = 0; i < istop; i++)
+ {
+ int c = (int)(i%channels);
+ png_uint_16 value, v;
+ int j;
+
+ v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+ value = 0;
+ for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
+ {
+ if (j > 0)
+ value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+ else
+ value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+ }
+ *bp++ = (png_byte)(value >> 8);
+ *bp++ = (png_byte)(value & 0xff);
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+void /* PRIVATE */
+png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_write_swap_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ /* This converts from ARGB to RGBA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ png_byte save = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = save;
+ }
+ }
+ /* This converts from AARRGGBB to RRGGBBAA */
+ else
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ png_byte save[2];
+ save[0] = *(sp++);
+ save[1] = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = save[0];
+ *(dp++) = save[1];
+ }
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ /* This converts from AG to GA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ png_byte save = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = save;
+ }
+ }
+ /* This converts from AAGG to GGAA */
+ else
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ png_byte save[2];
+ save[0] = *(sp++);
+ save[1] = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = save[0];
+ *(dp++) = save[1];
+ }
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+void /* PRIVATE */
+png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_write_invert_alpha");
+
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL)
+#endif
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ /* This inverts the alpha channel in RGBA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ /* Does nothing
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ */
+ sp+=3; dp = sp;
+ *(dp++) = (png_byte)(255 - *(sp++));
+ }
+ }
+ /* This inverts the alpha channel in RRGGBBAA */
+ else
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ /* Does nothing
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ */
+ sp+=6; dp = sp;
+ *(dp++) = (png_byte)(255 - *(sp++));
+ *(dp++) = (png_byte)(255 - *(sp++));
+ }
+ }
+ }
+ else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ /* This inverts the alpha channel in GA */
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ *(dp++) = *(sp++);
+ *(dp++) = (png_byte)(255 - *(sp++));
+ }
+ }
+ /* This inverts the alpha channel in GGAA */
+ else
+ {
+ png_bytep sp, dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ for (i = 0, sp = dp = row; i < row_width; i++)
+ {
+ /* Does nothing
+ *(dp++) = *(sp++);
+ *(dp++) = *(sp++);
+ */
+ sp+=2; dp = sp;
+ *(dp++) = (png_byte)(255 - *(sp++));
+ *(dp++) = (png_byte)(255 - *(sp++));
+ }
+ }
+ }
+ }
+}
+#endif
+
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing */
+void /* PRIVATE */
+png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_write_intrapixel");
+
+ if (
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ row != NULL && row_info != NULL &&
+#endif
+ (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)((*rp - *(rp+1))&0xff);
+ *(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
+ png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
+ png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
+ png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
+ png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
+ *(rp ) = (png_byte)((red >> 8) & 0xff);
+ *(rp+1) = (png_byte)(red & 0xff);
+ *(rp+4) = (png_byte)((blue >> 8) & 0xff);
+ *(rp+5) = (png_byte)(blue & 0xff);
+ }
+ }
+ }
+}
+#endif /* PNG_MNG_FEATURES_SUPPORTED */
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Source/LibPNG/pngwutil.c b/Source/LibPNG/pngwutil.c
new file mode 100644
index 0000000..c75f53e
--- /dev/null
+++ b/Source/LibPNG/pngwutil.c
@@ -0,0 +1,2832 @@
+
+/* pngwutil.c - utilities to write a PNG file
+ *
+ * Last changed in libpng 1.2.43 [February 25, 2010]
+ * Copyright (c) 1998-2010 Glenn Randers-Pehrson
+ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
+ * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#define PNG_INTERNAL
+#define PNG_NO_PEDANTIC_WARNINGS
+#include "png.h"
+#ifdef PNG_WRITE_SUPPORTED
+
+/* Place a 32-bit number into a buffer in PNG byte order. We work
+ * with unsigned numbers for convenience, although one supported
+ * ancillary chunk uses signed (two's complement) numbers.
+ */
+void PNGAPI
+png_save_uint_32(png_bytep buf, png_uint_32 i)
+{
+ buf[0] = (png_byte)((i >> 24) & 0xff);
+ buf[1] = (png_byte)((i >> 16) & 0xff);
+ buf[2] = (png_byte)((i >> 8) & 0xff);
+ buf[3] = (png_byte)(i & 0xff);
+}
+
+/* The png_save_int_32 function assumes integers are stored in two's
+ * complement format. If this isn't the case, then this routine needs to
+ * be modified to write data in two's complement format.
+ */
+void PNGAPI
+png_save_int_32(png_bytep buf, png_int_32 i)
+{
+ buf[0] = (png_byte)((i >> 24) & 0xff);
+ buf[1] = (png_byte)((i >> 16) & 0xff);
+ buf[2] = (png_byte)((i >> 8) & 0xff);
+ buf[3] = (png_byte)(i & 0xff);
+}
+
+/* Place a 16-bit number into a buffer in PNG byte order.
+ * The parameter is declared unsigned int, not png_uint_16,
+ * just to avoid potential problems on pre-ANSI C compilers.
+ */
+void PNGAPI
+png_save_uint_16(png_bytep buf, unsigned int i)
+{
+ buf[0] = (png_byte)((i >> 8) & 0xff);
+ buf[1] = (png_byte)(i & 0xff);
+}
+
+/* Simple function to write the signature. If we have already written
+ * the magic bytes of the signature, or more likely, the PNG stream is
+ * being embedded into another stream and doesn't need its own signature,
+ * we should call png_set_sig_bytes() to tell libpng how many of the
+ * bytes have already been written.
+ */
+void /* PRIVATE */
+png_write_sig(png_structp png_ptr)
+{
+ png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
+
+ /* Write the rest of the 8 byte signature */
+ png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
+ (png_size_t)(8 - png_ptr->sig_bytes));
+ if (png_ptr->sig_bytes < 3)
+ png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
+}
+
+/* Write a PNG chunk all at once. The type is an array of ASCII characters
+ * representing the chunk name. The array must be at least 4 bytes in
+ * length, and does not need to be null terminated. To be safe, pass the
+ * pre-defined chunk names here, and if you need a new one, define it
+ * where the others are defined. The length is the length of the data.
+ * All the data must be present. If that is not possible, use the
+ * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
+ * functions instead.
+ */
+void PNGAPI
+png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
+ png_bytep data, png_size_t length)
+{
+ if (png_ptr == NULL)
+ return;
+ png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
+ png_write_chunk_data(png_ptr, data, (png_size_t)length);
+ png_write_chunk_end(png_ptr);
+}
+
+/* Write the start of a PNG chunk. The type is the chunk type.
+ * The total_length is the sum of the lengths of all the data you will be
+ * passing in png_write_chunk_data().
+ */
+void PNGAPI
+png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
+ png_uint_32 length)
+{
+ png_byte buf[8];
+
+ png_debug2(0, "Writing %s chunk, length = %lu", chunk_name,
+ (unsigned long)length);
+
+ if (png_ptr == NULL)
+ return;
+
+
+ /* Write the length and the chunk name */
+ png_save_uint_32(buf, length);
+ png_memcpy(buf + 4, chunk_name, 4);
+ png_write_data(png_ptr, buf, (png_size_t)8);
+ /* Put the chunk name into png_ptr->chunk_name */
+ png_memcpy(png_ptr->chunk_name, chunk_name, 4);
+ /* Reset the crc and run it over the chunk name */
+ png_reset_crc(png_ptr);
+ png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
+}
+
+/* Write the data of a PNG chunk started with png_write_chunk_start().
+ * Note that multiple calls to this function are allowed, and that the
+ * sum of the lengths from these calls *must* add up to the total_length
+ * given to png_write_chunk_start().
+ */
+void PNGAPI
+png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ /* Write the data, and run the CRC over it */
+ if (png_ptr == NULL)
+ return;
+ if (data != NULL && length > 0)
+ {
+ png_write_data(png_ptr, data, length);
+ /* Update the CRC after writing the data,
+ * in case that the user I/O routine alters it.
+ */
+ png_calculate_crc(png_ptr, data, length);
+ }
+}
+
+/* Finish a chunk started with png_write_chunk_start(). */
+void PNGAPI
+png_write_chunk_end(png_structp png_ptr)
+{
+ png_byte buf[4];
+
+ if (png_ptr == NULL) return;
+
+ /* Write the crc in a single operation */
+ png_save_uint_32(buf, png_ptr->crc);
+
+ png_write_data(png_ptr, buf, (png_size_t)4);
+}
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
+/* This pair of functions encapsulates the operation of (a) compressing a
+ * text string, and (b) issuing it later as a series of chunk data writes.
+ * The compression_state structure is shared context for these functions
+ * set up by the caller in order to make the whole mess thread-safe.
+ */
+
+typedef struct
+{
+ char *input; /* The uncompressed input data */
+ int input_len; /* Its length */
+ int num_output_ptr; /* Number of output pointers used */
+ int max_output_ptr; /* Size of output_ptr */
+ png_charpp output_ptr; /* Array of pointers to output */
+} compression_state;
+
+/* Compress given text into storage in the png_ptr structure */
+static int /* PRIVATE */
+png_text_compress(png_structp png_ptr,
+ png_charp text, png_size_t text_len, int compression,
+ compression_state *comp)
+{
+ int ret;
+
+ comp->num_output_ptr = 0;
+ comp->max_output_ptr = 0;
+ comp->output_ptr = NULL;
+ comp->input = NULL;
+ comp->input_len = 0;
+
+ /* We may just want to pass the text right through */
+ if (compression == PNG_TEXT_COMPRESSION_NONE)
+ {
+ comp->input = text;
+ comp->input_len = text_len;
+ return((int)text_len);
+ }
+
+ if (compression >= PNG_TEXT_COMPRESSION_LAST)
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char msg[50];
+ png_snprintf(msg, 50, "Unknown compression type %d", compression);
+ png_warning(png_ptr, msg);
+#else
+ png_warning(png_ptr, "Unknown compression type");
+#endif
+ }
+
+ /* We can't write the chunk until we find out how much data we have,
+ * which means we need to run the compressor first and save the
+ * output. This shouldn't be a problem, as the vast majority of
+ * comments should be reasonable, but we will set up an array of
+ * malloc'd pointers to be sure.
+ *
+ * If we knew the application was well behaved, we could simplify this
+ * greatly by assuming we can always malloc an output buffer large
+ * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
+ * and malloc this directly. The only time this would be a bad idea is
+ * if we can't malloc more than 64K and we have 64K of random input
+ * data, or if the input string is incredibly large (although this
+ * wouldn't cause a failure, just a slowdown due to swapping).
+ */
+
+ /* Set up the compression buffers */
+ png_ptr->zstream.avail_in = (uInt)text_len;
+ png_ptr->zstream.next_in = (Bytef *)text;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
+
+ /* This is the same compression loop as in png_write_row() */
+ do
+ {
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+ if (ret != Z_OK)
+ {
+ /* Error */
+ if (png_ptr->zstream.msg != NULL)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ else
+ png_error(png_ptr, "zlib error");
+ }
+ /* Check to see if we need more room */
+ if (!(png_ptr->zstream.avail_out))
+ {
+ /* Make sure the output array has room */
+ if (comp->num_output_ptr >= comp->max_output_ptr)
+ {
+ int old_max;
+
+ old_max = comp->max_output_ptr;
+ comp->max_output_ptr = comp->num_output_ptr + 4;
+ if (comp->output_ptr != NULL)
+ {
+ png_charpp old_ptr;
+
+ old_ptr = comp->output_ptr;
+ comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+ (png_uint_32)
+ (comp->max_output_ptr * png_sizeof(png_charpp)));
+ png_memcpy(comp->output_ptr, old_ptr, old_max
+ * png_sizeof(png_charp));
+ png_free(png_ptr, old_ptr);
+ }
+ else
+ comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+ (png_uint_32)
+ (comp->max_output_ptr * png_sizeof(png_charp)));
+ }
+
+ /* Save the data */
+ comp->output_ptr[comp->num_output_ptr] =
+ (png_charp)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+ png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+ png_ptr->zbuf_size);
+ comp->num_output_ptr++;
+
+ /* and reset the buffer */
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ }
+ /* Continue until we don't have any more to compress */
+ } while (png_ptr->zstream.avail_in);
+
+ /* Finish the compression */
+ do
+ {
+ /* Tell zlib we are finished */
+ ret = deflate(&png_ptr->zstream, Z_FINISH);
+
+ if (ret == Z_OK)
+ {
+ /* Check to see if we need more room */
+ if (!(png_ptr->zstream.avail_out))
+ {
+ /* Check to make sure our output array has room */
+ if (comp->num_output_ptr >= comp->max_output_ptr)
+ {
+ int old_max;
+
+ old_max = comp->max_output_ptr;
+ comp->max_output_ptr = comp->num_output_ptr + 4;
+ if (comp->output_ptr != NULL)
+ {
+ png_charpp old_ptr;
+
+ old_ptr = comp->output_ptr;
+ /* This could be optimized to realloc() */
+ comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof(png_charp)));
+ png_memcpy(comp->output_ptr, old_ptr,
+ old_max * png_sizeof(png_charp));
+ png_free(png_ptr, old_ptr);
+ }
+ else
+ comp->output_ptr = (png_charpp)png_malloc(png_ptr,
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof(png_charp)));
+ }
+
+ /* Save the data */
+ comp->output_ptr[comp->num_output_ptr] =
+ (png_charp)png_malloc(png_ptr,
+ (png_uint_32)png_ptr->zbuf_size);
+ png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
+ png_ptr->zbuf_size);
+ comp->num_output_ptr++;
+
+ /* and reset the buffer pointers */
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ }
+ }
+ else if (ret != Z_STREAM_END)
+ {
+ /* We got an error */
+ if (png_ptr->zstream.msg != NULL)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ else
+ png_error(png_ptr, "zlib error");
+ }
+ } while (ret != Z_STREAM_END);
+
+ /* Text length is number of buffers plus last buffer */
+ text_len = png_ptr->zbuf_size * comp->num_output_ptr;
+ if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+ text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+
+ return((int)text_len);
+}
+
+/* Ship the compressed text out via chunk writes */
+static void /* PRIVATE */
+png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
+{
+ int i;
+
+ /* Handle the no-compression case */
+ if (comp->input)
+ {
+ png_write_chunk_data(png_ptr, (png_bytep)comp->input,
+ (png_size_t)comp->input_len);
+ return;
+ }
+
+ /* Write saved output buffers, if any */
+ for (i = 0; i < comp->num_output_ptr; i++)
+ {
+ png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
+ (png_size_t)png_ptr->zbuf_size);
+ png_free(png_ptr, comp->output_ptr[i]);
+ comp->output_ptr[i]=NULL;
+ }
+ if (comp->max_output_ptr != 0)
+ png_free(png_ptr, comp->output_ptr);
+ comp->output_ptr=NULL;
+ /* Write anything left in zbuf */
+ if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
+ png_write_chunk_data(png_ptr, png_ptr->zbuf,
+ (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
+
+ /* Reset zlib for another zTXt/iTXt or image data */
+ deflateReset(&png_ptr->zstream);
+ png_ptr->zstream.data_type = Z_BINARY;
+}
+#endif
+
+/* Write the IHDR chunk, and update the png_struct with the necessary
+ * information. Note that the rest of this code depends upon this
+ * information being correct.
+ */
+void /* PRIVATE */
+png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+ int bit_depth, int color_type, int compression_type, int filter_type,
+ int interlace_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_IHDR;
+#endif
+ int ret;
+
+ png_byte buf[13]; /* Buffer to store the IHDR info */
+
+ png_debug(1, "in png_write_IHDR");
+
+ /* Check that we have valid input data from the application info */
+ switch (color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ switch (bit_depth)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16: png_ptr->channels = 1; break;
+ default: png_error(png_ptr,
+ "Invalid bit depth for grayscale image");
+ }
+ break;
+ case PNG_COLOR_TYPE_RGB:
+ if (bit_depth != 8 && bit_depth != 16)
+ png_error(png_ptr, "Invalid bit depth for RGB image");
+ png_ptr->channels = 3;
+ break;
+ case PNG_COLOR_TYPE_PALETTE:
+ switch (bit_depth)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8: png_ptr->channels = 1; break;
+ default: png_error(png_ptr, "Invalid bit depth for paletted image");
+ }
+ break;
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ if (bit_depth != 8 && bit_depth != 16)
+ png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
+ png_ptr->channels = 2;
+ break;
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ if (bit_depth != 8 && bit_depth != 16)
+ png_error(png_ptr, "Invalid bit depth for RGBA image");
+ png_ptr->channels = 4;
+ break;
+ default:
+ png_error(png_ptr, "Invalid image color type specified");
+ }
+
+ if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ {
+ png_warning(png_ptr, "Invalid compression type specified");
+ compression_type = PNG_COMPRESSION_TYPE_BASE;
+ }
+
+ /* Write filter_method 64 (intrapixel differencing) only if
+ * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
+ * 2. Libpng did not write a PNG signature (this filter_method is only
+ * used in PNG datastreams that are embedded in MNG datastreams) and
+ * 3. The application called png_permit_mng_features with a mask that
+ * included PNG_FLAG_MNG_FILTER_64 and
+ * 4. The filter_method is 64 and
+ * 5. The color_type is RGB or RGBA
+ */
+ if (
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+ (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
+ (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
+#endif
+ filter_type != PNG_FILTER_TYPE_BASE)
+ {
+ png_warning(png_ptr, "Invalid filter type specified");
+ filter_type = PNG_FILTER_TYPE_BASE;
+ }
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ if (interlace_type != PNG_INTERLACE_NONE &&
+ interlace_type != PNG_INTERLACE_ADAM7)
+ {
+ png_warning(png_ptr, "Invalid interlace type specified");
+ interlace_type = PNG_INTERLACE_ADAM7;
+ }
+#else
+ interlace_type=PNG_INTERLACE_NONE;
+#endif
+
+ /* Save the relevent information */
+ png_ptr->bit_depth = (png_byte)bit_depth;
+ png_ptr->color_type = (png_byte)color_type;
+ png_ptr->interlaced = (png_byte)interlace_type;
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ png_ptr->filter_type = (png_byte)filter_type;
+#endif
+ png_ptr->compression_type = (png_byte)compression_type;
+ png_ptr->width = width;
+ png_ptr->height = height;
+
+ png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
+ /* Set the usr info, so any transformations can modify it */
+ png_ptr->usr_width = png_ptr->width;
+ png_ptr->usr_bit_depth = png_ptr->bit_depth;
+ png_ptr->usr_channels = png_ptr->channels;
+
+ /* Pack the header information into the buffer */
+ png_save_uint_32(buf, width);
+ png_save_uint_32(buf + 4, height);
+ buf[8] = (png_byte)bit_depth;
+ buf[9] = (png_byte)color_type;
+ buf[10] = (png_byte)compression_type;
+ buf[11] = (png_byte)filter_type;
+ buf[12] = (png_byte)interlace_type;
+
+ /* Write the chunk */
+ png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
+
+ /* Initialize zlib with PNG info */
+ png_ptr->zstream.zalloc = png_zalloc;
+ png_ptr->zstream.zfree = png_zfree;
+ png_ptr->zstream.opaque = (voidpf)png_ptr;
+ if (!(png_ptr->do_filter))
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+ png_ptr->bit_depth < 8)
+ png_ptr->do_filter = PNG_FILTER_NONE;
+ else
+ png_ptr->do_filter = PNG_ALL_FILTERS;
+ }
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
+ {
+ if (png_ptr->do_filter != PNG_FILTER_NONE)
+ png_ptr->zlib_strategy = Z_FILTERED;
+ else
+ png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
+ }
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
+ png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
+ png_ptr->zlib_mem_level = 8;
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
+ png_ptr->zlib_window_bits = 15;
+ if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
+ png_ptr->zlib_method = 8;
+ ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
+ png_ptr->zlib_method, png_ptr->zlib_window_bits,
+ png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
+ if (ret != Z_OK)
+ {
+ if (ret == Z_VERSION_ERROR) png_error(png_ptr,
+ "zlib failed to initialize compressor -- version error");
+ if (ret == Z_STREAM_ERROR) png_error(png_ptr,
+ "zlib failed to initialize compressor -- stream error");
+ if (ret == Z_MEM_ERROR) png_error(png_ptr,
+ "zlib failed to initialize compressor -- mem error");
+ png_error(png_ptr, "zlib failed to initialize compressor");
+ }
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ /* libpng is not interested in zstream.data_type */
+ /* Set it to a predefined value, to avoid its evaluation inside zlib */
+ png_ptr->zstream.data_type = Z_BINARY;
+
+ png_ptr->mode = PNG_HAVE_IHDR;
+}
+
+/* Write the palette. We are careful not to trust png_color to be in the
+ * correct order for PNG, so people can redefine it to any convenient
+ * structure.
+ */
+void /* PRIVATE */
+png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_PLTE;
+#endif
+ png_uint_32 i;
+ png_colorp pal_ptr;
+ png_byte buf[3];
+
+ png_debug(1, "in png_write_PLTE");
+
+ if ((
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+#endif
+ num_pal == 0) || num_pal > 256)
+ {
+ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_error(png_ptr, "Invalid number of colors in palette");
+ }
+ else
+ {
+ png_warning(png_ptr, "Invalid number of colors in palette");
+ return;
+ }
+ }
+
+ if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ {
+ png_warning(png_ptr,
+ "Ignoring request to write a PLTE chunk in grayscale PNG");
+ return;
+ }
+
+ png_ptr->num_palette = (png_uint_16)num_pal;
+ png_debug1(3, "num_palette = %d", png_ptr->num_palette);
+
+ png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
+ (png_uint_32)(num_pal * 3));
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
+ {
+ buf[0] = pal_ptr->red;
+ buf[1] = pal_ptr->green;
+ buf[2] = pal_ptr->blue;
+ png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+ }
+#else
+ /* This is a little slower but some buggy compilers need to do this
+ * instead
+ */
+ pal_ptr=palette;
+ for (i = 0; i < num_pal; i++)
+ {
+ buf[0] = pal_ptr[i].red;
+ buf[1] = pal_ptr[i].green;
+ buf[2] = pal_ptr[i].blue;
+ png_write_chunk_data(png_ptr, buf, (png_size_t)3);
+ }
+#endif
+ png_write_chunk_end(png_ptr);
+ png_ptr->mode |= PNG_HAVE_PLTE;
+}
+
+/* Write an IDAT chunk */
+void /* PRIVATE */
+png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_IDAT;
+#endif
+
+ png_debug(1, "in png_write_IDAT");
+
+ /* Optimize the CMF field in the zlib stream. */
+ /* This hack of the zlib stream is compliant to the stream specification. */
+ if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ {
+ unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+ if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ {
+ /* Avoid memory underflows and multiplication overflows.
+ *
+ * The conditions below are practically always satisfied;
+ * however, they still must be checked.
+ */
+ if (length >= 2 &&
+ png_ptr->height < 16384 && png_ptr->width < 16384)
+ {
+ png_uint_32 uncompressed_idat_size = png_ptr->height *
+ ((png_ptr->width *
+ png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
+ unsigned int z_cinfo = z_cmf >> 4;
+ unsigned int half_z_window_size = 1 << (z_cinfo + 7);
+ while (uncompressed_idat_size <= half_z_window_size &&
+ half_z_window_size >= 256)
+ {
+ z_cinfo--;
+ half_z_window_size >>= 1;
+ }
+ z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ if (data[0] != (png_byte)z_cmf)
+ {
+ data[0] = (png_byte)z_cmf;
+ data[1] &= 0xe0;
+ data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
+ }
+ }
+ }
+ else
+ png_error(png_ptr,
+ "Invalid zlib compression method or flags in IDAT");
+ }
+
+ png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
+ png_ptr->mode |= PNG_HAVE_IDAT;
+}
+
+/* Write an IEND chunk */
+void /* PRIVATE */
+png_write_IEND(png_structp png_ptr)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_IEND;
+#endif
+
+ png_debug(1, "in png_write_IEND");
+
+ png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
+ (png_size_t)0);
+ png_ptr->mode |= PNG_HAVE_IEND;
+}
+
+#ifdef PNG_WRITE_gAMA_SUPPORTED
+/* Write a gAMA chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA(png_structp png_ptr, double file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_gAMA;
+#endif
+ png_uint_32 igamma;
+ png_byte buf[4];
+
+ png_debug(1, "in png_write_gAMA");
+
+ /* file_gamma is saved in 1/100,000ths */
+ igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
+ png_save_uint_32(buf, igamma);
+ png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_gAMA;
+#endif
+ png_byte buf[4];
+
+ png_debug(1, "in png_write_gAMA");
+
+ /* file_gamma is saved in 1/100,000ths */
+ png_save_uint_32(buf, (png_uint_32)file_gamma);
+ png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
+}
+#endif
+#endif
+
+#ifdef PNG_WRITE_sRGB_SUPPORTED
+/* Write a sRGB chunk */
+void /* PRIVATE */
+png_write_sRGB(png_structp png_ptr, int srgb_intent)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_sRGB;
+#endif
+ png_byte buf[1];
+
+ png_debug(1, "in png_write_sRGB");
+
+ if (srgb_intent >= PNG_sRGB_INTENT_LAST)
+ png_warning(png_ptr,
+ "Invalid sRGB rendering intent specified");
+ buf[0]=(png_byte)srgb_intent;
+ png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
+}
+#endif
+
+#ifdef PNG_WRITE_iCCP_SUPPORTED
+/* Write an iCCP chunk */
+void /* PRIVATE */
+png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
+ png_charp profile, int profile_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_iCCP;
+#endif
+ png_size_t name_len;
+ png_charp new_name;
+ compression_state comp;
+ int embedded_profile_len = 0;
+
+ png_debug(1, "in png_write_iCCP");
+
+ comp.num_output_ptr = 0;
+ comp.max_output_ptr = 0;
+ comp.output_ptr = NULL;
+ comp.input = NULL;
+ comp.input_len = 0;
+
+ if ((name_len = png_check_keyword(png_ptr, name,
+ &new_name)) == 0)
+ return;
+
+ if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ png_warning(png_ptr, "Unknown compression type in iCCP chunk");
+
+ if (profile == NULL)
+ profile_len = 0;
+
+ if (profile_len > 3)
+ embedded_profile_len =
+ ((*( (png_bytep)profile ))<<24) |
+ ((*( (png_bytep)profile + 1))<<16) |
+ ((*( (png_bytep)profile + 2))<< 8) |
+ ((*( (png_bytep)profile + 3)) );
+
+ if (embedded_profile_len < 0)
+ {
+ png_warning(png_ptr,
+ "Embedded profile length in iCCP chunk is negative");
+ png_free(png_ptr, new_name);
+ return;
+ }
+
+ if (profile_len < embedded_profile_len)
+ {
+ png_warning(png_ptr,
+ "Embedded profile length too large in iCCP chunk");
+ png_free(png_ptr, new_name);
+ return;
+ }
+
+ if (profile_len > embedded_profile_len)
+ {
+ png_warning(png_ptr,
+ "Truncating profile to actual length in iCCP chunk");
+ profile_len = embedded_profile_len;
+ }
+
+ if (profile_len)
+ profile_len = png_text_compress(png_ptr, profile,
+ (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
+
+ /* Make sure we include the NULL after the name and the compression type */
+ png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
+ (png_uint_32)(name_len + profile_len + 2));
+ new_name[name_len + 1] = 0x00;
+ png_write_chunk_data(png_ptr, (png_bytep)new_name,
+ (png_size_t)(name_len + 2));
+
+ if (profile_len)
+ png_write_compressed_data_out(png_ptr, &comp);
+
+ png_write_chunk_end(png_ptr);
+ png_free(png_ptr, new_name);
+}
+#endif
+
+#ifdef PNG_WRITE_sPLT_SUPPORTED
+/* Write a sPLT chunk */
+void /* PRIVATE */
+png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_sPLT;
+#endif
+ png_size_t name_len;
+ png_charp new_name;
+ png_byte entrybuf[10];
+ int entry_size = (spalette->depth == 8 ? 6 : 10);
+ int palette_size = entry_size * spalette->nentries;
+ png_sPLT_entryp ep;
+#ifndef PNG_POINTER_INDEXING_SUPPORTED
+ int i;
+#endif
+
+ png_debug(1, "in png_write_sPLT");
+
+ if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
+ return;
+
+ /* Make sure we include the NULL after the name */
+ png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
+ (png_uint_32)(name_len + 2 + palette_size));
+ png_write_chunk_data(png_ptr, (png_bytep)new_name,
+ (png_size_t)(name_len + 1));
+ png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
+
+ /* Loop through each palette entry, writing appropriately */
+#ifdef PNG_POINTER_INDEXING_SUPPORTED
+ for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
+ {
+ if (spalette->depth == 8)
+ {
+ entrybuf[0] = (png_byte)ep->red;
+ entrybuf[1] = (png_byte)ep->green;
+ entrybuf[2] = (png_byte)ep->blue;
+ entrybuf[3] = (png_byte)ep->alpha;
+ png_save_uint_16(entrybuf + 4, ep->frequency);
+ }
+ else
+ {
+ png_save_uint_16(entrybuf + 0, ep->red);
+ png_save_uint_16(entrybuf + 2, ep->green);
+ png_save_uint_16(entrybuf + 4, ep->blue);
+ png_save_uint_16(entrybuf + 6, ep->alpha);
+ png_save_uint_16(entrybuf + 8, ep->frequency);
+ }
+ png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ }
+#else
+ ep=spalette->entries;
+ for (i=0; i>spalette->nentries; i++)
+ {
+ if (spalette->depth == 8)
+ {
+ entrybuf[0] = (png_byte)ep[i].red;
+ entrybuf[1] = (png_byte)ep[i].green;
+ entrybuf[2] = (png_byte)ep[i].blue;
+ entrybuf[3] = (png_byte)ep[i].alpha;
+ png_save_uint_16(entrybuf + 4, ep[i].frequency);
+ }
+ else
+ {
+ png_save_uint_16(entrybuf + 0, ep[i].red);
+ png_save_uint_16(entrybuf + 2, ep[i].green);
+ png_save_uint_16(entrybuf + 4, ep[i].blue);
+ png_save_uint_16(entrybuf + 6, ep[i].alpha);
+ png_save_uint_16(entrybuf + 8, ep[i].frequency);
+ }
+ png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ }
+#endif
+
+ png_write_chunk_end(png_ptr);
+ png_free(png_ptr, new_name);
+}
+#endif
+
+#ifdef PNG_WRITE_sBIT_SUPPORTED
+/* Write the sBIT chunk */
+void /* PRIVATE */
+png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_sBIT;
+#endif
+ png_byte buf[4];
+ png_size_t size;
+
+ png_debug(1, "in png_write_sBIT");
+
+ /* Make sure we don't depend upon the order of PNG_COLOR_8 */
+ if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ png_byte maxbits;
+
+ maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
+ png_ptr->usr_bit_depth);
+ if (sbit->red == 0 || sbit->red > maxbits ||
+ sbit->green == 0 || sbit->green > maxbits ||
+ sbit->blue == 0 || sbit->blue > maxbits)
+ {
+ png_warning(png_ptr, "Invalid sBIT depth specified");
+ return;
+ }
+ buf[0] = sbit->red;
+ buf[1] = sbit->green;
+ buf[2] = sbit->blue;
+ size = 3;
+ }
+ else
+ {
+ if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
+ {
+ png_warning(png_ptr, "Invalid sBIT depth specified");
+ return;
+ }
+ buf[0] = sbit->gray;
+ size = 1;
+ }
+
+ if (color_type & PNG_COLOR_MASK_ALPHA)
+ {
+ if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
+ {
+ png_warning(png_ptr, "Invalid sBIT depth specified");
+ return;
+ }
+ buf[size++] = sbit->alpha;
+ }
+
+ png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
+}
+#endif
+
+#ifdef PNG_WRITE_cHRM_SUPPORTED
+/* Write the cHRM chunk */
+#ifdef PNG_FLOATING_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
+ double red_x, double red_y, double green_x, double green_y,
+ double blue_x, double blue_y)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_cHRM;
+#endif
+ png_byte buf[32];
+
+ png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
+ int_green_x, int_green_y, int_blue_x, int_blue_y;
+
+ png_debug(1, "in png_write_cHRM");
+
+ int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5);
+ int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5);
+ int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5);
+ int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5);
+ int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
+ int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
+ int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5);
+ int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5);
+
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+ if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
+ int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
+#endif
+ {
+ /* Each value is saved in 1/100,000ths */
+
+ png_save_uint_32(buf, int_white_x);
+ png_save_uint_32(buf + 4, int_white_y);
+
+ png_save_uint_32(buf + 8, int_red_x);
+ png_save_uint_32(buf + 12, int_red_y);
+
+ png_save_uint_32(buf + 16, int_green_x);
+ png_save_uint_32(buf + 20, int_green_y);
+
+ png_save_uint_32(buf + 24, int_blue_x);
+ png_save_uint_32(buf + 28, int_blue_y);
+
+ png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+ }
+}
+#endif
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
+ png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
+ png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
+ png_fixed_point blue_y)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_cHRM;
+#endif
+ png_byte buf[32];
+
+ png_debug(1, "in png_write_cHRM");
+
+ /* Each value is saved in 1/100,000ths */
+#ifdef PNG_CHECK_cHRM_SUPPORTED
+ if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
+ green_x, green_y, blue_x, blue_y))
+#endif
+ {
+ png_save_uint_32(buf, (png_uint_32)white_x);
+ png_save_uint_32(buf + 4, (png_uint_32)white_y);
+
+ png_save_uint_32(buf + 8, (png_uint_32)red_x);
+ png_save_uint_32(buf + 12, (png_uint_32)red_y);
+
+ png_save_uint_32(buf + 16, (png_uint_32)green_x);
+ png_save_uint_32(buf + 20, (png_uint_32)green_y);
+
+ png_save_uint_32(buf + 24, (png_uint_32)blue_x);
+ png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+
+ png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
+ }
+}
+#endif
+#endif
+
+#ifdef PNG_WRITE_tRNS_SUPPORTED
+/* Write the tRNS chunk */
+void /* PRIVATE */
+png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
+ int num_trans, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_tRNS;
+#endif
+ png_byte buf[6];
+
+ png_debug(1, "in png_write_tRNS");
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
+ {
+ png_warning(png_ptr, "Invalid number of transparent colors specified");
+ return;
+ }
+ /* Write the chunk out as it is */
+ png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans,
+ (png_size_t)num_trans);
+ }
+ else if (color_type == PNG_COLOR_TYPE_GRAY)
+ {
+ /* One 16 bit value */
+ if (tran->gray >= (1 << png_ptr->bit_depth))
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
+ return;
+ }
+ png_save_uint_16(buf, tran->gray);
+ png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
+ }
+ else if (color_type == PNG_COLOR_TYPE_RGB)
+ {
+ /* Three 16 bit values */
+ png_save_uint_16(buf, tran->red);
+ png_save_uint_16(buf + 2, tran->green);
+ png_save_uint_16(buf + 4, tran->blue);
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
+ return;
+ }
+ png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
+ }
+ else
+ {
+ png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+ }
+}
+#endif
+
+#ifdef PNG_WRITE_bKGD_SUPPORTED
+/* Write the background chunk */
+void /* PRIVATE */
+png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_bKGD;
+#endif
+ png_byte buf[6];
+
+ png_debug(1, "in png_write_bKGD");
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ if (
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+ (png_ptr->num_palette ||
+ (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+#endif
+ back->index >= png_ptr->num_palette)
+ {
+ png_warning(png_ptr, "Invalid background palette index");
+ return;
+ }
+ buf[0] = back->index;
+ png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
+ }
+ else if (color_type & PNG_COLOR_MASK_COLOR)
+ {
+ png_save_uint_16(buf, back->red);
+ png_save_uint_16(buf + 2, back->green);
+ png_save_uint_16(buf + 4, back->blue);
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
+ return;
+ }
+ png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
+ }
+ else
+ {
+ if (back->gray >= (1 << png_ptr->bit_depth))
+ {
+ png_warning(png_ptr,
+ "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
+ return;
+ }
+ png_save_uint_16(buf, back->gray);
+ png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
+ }
+}
+#endif
+
+#ifdef PNG_WRITE_hIST_SUPPORTED
+/* Write the histogram */
+void /* PRIVATE */
+png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_hIST;
+#endif
+ int i;
+ png_byte buf[3];
+
+ png_debug(1, "in png_write_hIST");
+
+ if (num_hist > (int)png_ptr->num_palette)
+ {
+ png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
+ png_ptr->num_palette);
+ png_warning(png_ptr, "Invalid number of histogram entries specified");
+ return;
+ }
+
+ png_write_chunk_start(png_ptr, (png_bytep)png_hIST,
+ (png_uint_32)(num_hist * 2));
+ for (i = 0; i < num_hist; i++)
+ {
+ png_save_uint_16(buf, hist[i]);
+ png_write_chunk_data(png_ptr, buf, (png_size_t)2);
+ }
+ png_write_chunk_end(png_ptr);
+}
+#endif
+
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+ defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The new_key is allocated to hold the corrected keyword and must be freed
+ * by the calling routine. This avoids problems with trying to write to
+ * static keywords without having to have duplicate copies of the strings.
+ */
+png_size_t /* PRIVATE */
+png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
+{
+ png_size_t key_len;
+ png_charp kp, dp;
+ int kflag;
+ int kwarn=0;
+
+ png_debug(1, "in png_check_keyword");
+
+ *new_key = NULL;
+
+ if (key == NULL || (key_len = png_strlen(key)) == 0)
+ {
+ png_warning(png_ptr, "zero length keyword");
+ return ((png_size_t)0);
+ }
+
+ png_debug1(2, "Keyword to be checked is '%s'", key);
+
+ *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
+ if (*new_key == NULL)
+ {
+ png_warning(png_ptr, "Out of memory while procesing keyword");
+ return ((png_size_t)0);
+ }
+
+ /* Replace non-printing characters with a blank and print a warning */
+ for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
+ {
+ if ((png_byte)*kp < 0x20 ||
+ ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
+ {
+#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
+ char msg[40];
+
+ png_snprintf(msg, 40,
+ "invalid keyword character 0x%02X", (png_byte)*kp);
+ png_warning(png_ptr, msg);
+#else
+ png_warning(png_ptr, "invalid character in keyword");
+#endif
+ *dp = ' ';
+ }
+ else
+ {
+ *dp = *kp;
+ }
+ }
+ *dp = '\0';
+
+ /* Remove any trailing white space. */
+ kp = *new_key + key_len - 1;
+ if (*kp == ' ')
+ {
+ png_warning(png_ptr, "trailing spaces removed from keyword");
+
+ while (*kp == ' ')
+ {
+ *(kp--) = '\0';
+ key_len--;
+ }
+ }
+
+ /* Remove any leading white space. */
+ kp = *new_key;
+ if (*kp == ' ')
+ {
+ png_warning(png_ptr, "leading spaces removed from keyword");
+
+ while (*kp == ' ')
+ {
+ kp++;
+ key_len--;
+ }
+ }
+
+ png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
+
+ /* Remove multiple internal spaces. */
+ for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
+ {
+ if (*kp == ' ' && kflag == 0)
+ {
+ *(dp++) = *kp;
+ kflag = 1;
+ }
+ else if (*kp == ' ')
+ {
+ key_len--;
+ kwarn=1;
+ }
+ else
+ {
+ *(dp++) = *kp;
+ kflag = 0;
+ }
+ }
+ *dp = '\0';
+ if (kwarn)
+ png_warning(png_ptr, "extra interior spaces removed from keyword");
+
+ if (key_len == 0)
+ {
+ png_free(png_ptr, *new_key);
+ *new_key=NULL;
+ png_warning(png_ptr, "Zero length keyword");
+ }
+
+ if (key_len > 79)
+ {
+ png_warning(png_ptr, "keyword length must be 1 - 79 characters");
+ (*new_key)[79] = '\0';
+ key_len = 79;
+ }
+
+ return (key_len);
+}
+#endif
+
+#ifdef PNG_WRITE_tEXt_SUPPORTED
+/* Write a tEXt chunk */
+void /* PRIVATE */
+png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
+ png_size_t text_len)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_tEXt;
+#endif
+ png_size_t key_len;
+ png_charp new_key;
+
+ png_debug(1, "in png_write_tEXt");
+
+ if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+ return;
+
+ if (text == NULL || *text == '\0')
+ text_len = 0;
+ else
+ text_len = png_strlen(text);
+
+ /* Make sure we include the 0 after the key */
+ png_write_chunk_start(png_ptr, (png_bytep)png_tEXt,
+ (png_uint_32)(key_len + text_len + 1));
+ /*
+ * We leave it to the application to meet PNG-1.0 requirements on the
+ * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
+ * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+ */
+ png_write_chunk_data(png_ptr, (png_bytep)new_key,
+ (png_size_t)(key_len + 1));
+ if (text_len)
+ png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len);
+
+ png_write_chunk_end(png_ptr);
+ png_free(png_ptr, new_key);
+}
+#endif
+
+#ifdef PNG_WRITE_zTXt_SUPPORTED
+/* Write a compressed text chunk */
+void /* PRIVATE */
+png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
+ png_size_t text_len, int compression)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_zTXt;
+#endif
+ png_size_t key_len;
+ char buf[1];
+ png_charp new_key;
+ compression_state comp;
+
+ png_debug(1, "in png_write_zTXt");
+
+ comp.num_output_ptr = 0;
+ comp.max_output_ptr = 0;
+ comp.output_ptr = NULL;
+ comp.input = NULL;
+ comp.input_len = 0;
+
+ if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+ {
+ png_free(png_ptr, new_key);
+ return;
+ }
+
+ if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
+ {
+ png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
+ png_free(png_ptr, new_key);
+ return;
+ }
+
+ text_len = png_strlen(text);
+
+ /* Compute the compressed data; do it now for the length */
+ text_len = png_text_compress(png_ptr, text, text_len, compression,
+ &comp);
+
+ /* Write start of chunk */
+ png_write_chunk_start(png_ptr, (png_bytep)png_zTXt,
+ (png_uint_32)(key_len+text_len + 2));
+ /* Write key */
+ png_write_chunk_data(png_ptr, (png_bytep)new_key,
+ (png_size_t)(key_len + 1));
+ png_free(png_ptr, new_key);
+
+ buf[0] = (png_byte)compression;
+ /* Write compression */
+ png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
+ /* Write the compressed data */
+ png_write_compressed_data_out(png_ptr, &comp);
+
+ /* Close the chunk */
+ png_write_chunk_end(png_ptr);
+}
+#endif
+
+#ifdef PNG_WRITE_iTXt_SUPPORTED
+/* Write an iTXt chunk */
+void /* PRIVATE */
+png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
+ png_charp lang, png_charp lang_key, png_charp text)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_iTXt;
+#endif
+ png_size_t lang_len, key_len, lang_key_len, text_len;
+ png_charp new_lang;
+ png_charp new_key = NULL;
+ png_byte cbuf[2];
+ compression_state comp;
+
+ png_debug(1, "in png_write_iTXt");
+
+ comp.num_output_ptr = 0;
+ comp.max_output_ptr = 0;
+ comp.output_ptr = NULL;
+ comp.input = NULL;
+
+ if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
+ return;
+
+ if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
+ {
+ png_warning(png_ptr, "Empty language field in iTXt chunk");
+ new_lang = NULL;
+ lang_len = 0;
+ }
+
+ if (lang_key == NULL)
+ lang_key_len = 0;
+ else
+ lang_key_len = png_strlen(lang_key);
+
+ if (text == NULL)
+ text_len = 0;
+ else
+ text_len = png_strlen(text);
+
+ /* Compute the compressed data; do it now for the length */
+ text_len = png_text_compress(png_ptr, text, text_len, compression-2,
+ &comp);
+
+
+ /* Make sure we include the compression flag, the compression byte,
+ * and the NULs after the key, lang, and lang_key parts */
+
+ png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
+ (png_uint_32)(
+ 5 /* comp byte, comp flag, terminators for key, lang and lang_key */
+ + key_len
+ + lang_len
+ + lang_key_len
+ + text_len));
+
+ /* We leave it to the application to meet PNG-1.0 requirements on the
+ * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
+ * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+ */
+ png_write_chunk_data(png_ptr, (png_bytep)new_key,
+ (png_size_t)(key_len + 1));
+
+ /* Set the compression flag */
+ if (compression == PNG_ITXT_COMPRESSION_NONE || \
+ compression == PNG_TEXT_COMPRESSION_NONE)
+ cbuf[0] = 0;
+ else /* compression == PNG_ITXT_COMPRESSION_zTXt */
+ cbuf[0] = 1;
+ /* Set the compression method */
+ cbuf[1] = 0;
+ png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
+
+ cbuf[0] = 0;
+ png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf),
+ (png_size_t)(lang_len + 1));
+ png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf),
+ (png_size_t)(lang_key_len + 1));
+ png_write_compressed_data_out(png_ptr, &comp);
+
+ png_write_chunk_end(png_ptr);
+ png_free(png_ptr, new_key);
+ png_free(png_ptr, new_lang);
+}
+#endif
+
+#ifdef PNG_WRITE_oFFs_SUPPORTED
+/* Write the oFFs chunk */
+void /* PRIVATE */
+png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
+ int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_oFFs;
+#endif
+ png_byte buf[9];
+
+ png_debug(1, "in png_write_oFFs");
+
+ if (unit_type >= PNG_OFFSET_LAST)
+ png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
+
+ png_save_int_32(buf, x_offset);
+ png_save_int_32(buf + 4, y_offset);
+ buf[8] = (png_byte)unit_type;
+
+ png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
+}
+#endif
+#ifdef PNG_WRITE_pCAL_SUPPORTED
+/* Write the pCAL chunk (described in the PNG extensions document) */
+void /* PRIVATE */
+png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
+ png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_pCAL;
+#endif
+ png_size_t purpose_len, units_len, total_len;
+ png_uint_32p params_len;
+ png_byte buf[10];
+ png_charp new_purpose;
+ int i;
+
+ png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
+
+ if (type >= PNG_EQUATION_LAST)
+ png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+ purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
+ png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
+ units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
+ png_debug1(3, "pCAL units length = %d", (int)units_len);
+ total_len = purpose_len + units_len + 10;
+
+ params_len = (png_uint_32p)png_malloc(png_ptr,
+ (png_uint_32)(nparams * png_sizeof(png_uint_32)));
+
+ /* Find the length of each parameter, making sure we don't count the
+ null terminator for the last parameter. */
+ for (i = 0; i < nparams; i++)
+ {
+ params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+ png_debug2(3, "pCAL parameter %d length = %lu", i,
+ (unsigned long) params_len[i]);
+ total_len += (png_size_t)params_len[i];
+ }
+
+ png_debug1(3, "pCAL total length = %d", (int)total_len);
+ png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
+ png_write_chunk_data(png_ptr, (png_bytep)new_purpose,
+ (png_size_t)purpose_len);
+ png_save_int_32(buf, X0);
+ png_save_int_32(buf + 4, X1);
+ buf[8] = (png_byte)type;
+ buf[9] = (png_byte)nparams;
+ png_write_chunk_data(png_ptr, buf, (png_size_t)10);
+ png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
+
+ png_free(png_ptr, new_purpose);
+
+ for (i = 0; i < nparams; i++)
+ {
+ png_write_chunk_data(png_ptr, (png_bytep)params[i],
+ (png_size_t)params_len[i]);
+ }
+
+ png_free(png_ptr, params_len);
+ png_write_chunk_end(png_ptr);
+}
+#endif
+
+#ifdef PNG_WRITE_sCAL_SUPPORTED
+/* Write the sCAL chunk */
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+void /* PRIVATE */
+png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_sCAL;
+#endif
+ char buf[64];
+ png_size_t total_len;
+
+ png_debug(1, "in png_write_sCAL");
+
+ buf[0] = (char)unit;
+#ifdef _WIN32_WCE
+/* sprintf() function is not supported on WindowsCE */
+ {
+ wchar_t wc_buf[32];
+ size_t wc_len;
+ swprintf(wc_buf, TEXT("%12.12e"), width);
+ wc_len = wcslen(wc_buf);
+ WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL,
+ NULL);
+ total_len = wc_len + 2;
+ swprintf(wc_buf, TEXT("%12.12e"), height);
+ wc_len = wcslen(wc_buf);
+ WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len,
+ NULL, NULL);
+ total_len += wc_len;
+ }
+#else
+ png_snprintf(buf + 1, 63, "%12.12e", width);
+ total_len = 1 + png_strlen(buf + 1) + 1;
+ png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
+ total_len += png_strlen(buf + total_len);
+#endif
+
+ png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
+ png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
+}
+#else
+#ifdef PNG_FIXED_POINT_SUPPORTED
+void /* PRIVATE */
+png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
+ png_charp height)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_sCAL;
+#endif
+ png_byte buf[64];
+ png_size_t wlen, hlen, total_len;
+
+ png_debug(1, "in png_write_sCAL_s");
+
+ wlen = png_strlen(width);
+ hlen = png_strlen(height);
+ total_len = wlen + hlen + 2;
+ if (total_len > 64)
+ {
+ png_warning(png_ptr, "Can't write sCAL (buffer too small)");
+ return;
+ }
+
+ buf[0] = (png_byte)unit;
+ png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
+ png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
+
+ png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
+ png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len);
+}
+#endif
+#endif
+#endif
+
+#ifdef PNG_WRITE_pHYs_SUPPORTED
+/* Write the pHYs chunk */
+void /* PRIVATE */
+png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
+ png_uint_32 y_pixels_per_unit,
+ int unit_type)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_pHYs;
+#endif
+ png_byte buf[9];
+
+ png_debug(1, "in png_write_pHYs");
+
+ if (unit_type >= PNG_RESOLUTION_LAST)
+ png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
+
+ png_save_uint_32(buf, x_pixels_per_unit);
+ png_save_uint_32(buf + 4, y_pixels_per_unit);
+ buf[8] = (png_byte)unit_type;
+
+ png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
+}
+#endif
+
+#ifdef PNG_WRITE_tIME_SUPPORTED
+/* Write the tIME chunk. Use either png_convert_from_struct_tm()
+ * or png_convert_from_time_t(), or fill in the structure yourself.
+ */
+void /* PRIVATE */
+png_write_tIME(png_structp png_ptr, png_timep mod_time)
+{
+#ifdef PNG_USE_LOCAL_ARRAYS
+ PNG_tIME;
+#endif
+ png_byte buf[7];
+
+ png_debug(1, "in png_write_tIME");
+
+ if (mod_time->month > 12 || mod_time->month < 1 ||
+ mod_time->day > 31 || mod_time->day < 1 ||
+ mod_time->hour > 23 || mod_time->second > 60)
+ {
+ png_warning(png_ptr, "Invalid time specified for tIME chunk");
+ return;
+ }
+
+ png_save_uint_16(buf, mod_time->year);
+ buf[2] = mod_time->month;
+ buf[3] = mod_time->day;
+ buf[4] = mod_time->hour;
+ buf[5] = mod_time->minute;
+ buf[6] = mod_time->second;
+
+ png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
+}
+#endif
+
+/* Initializes the row writing capability of libpng */
+void /* PRIVATE */
+png_write_start_row(png_structp png_ptr)
+{
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+ png_size_t buf_size;
+
+ png_debug(1, "in png_write_start_row");
+
+ buf_size = (png_size_t)(PNG_ROWBYTES(
+ png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
+
+ /* Set up row buffer */
+ png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)buf_size);
+ png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
+
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ /* Set up filtering buffer, if using this filter */
+ if (png_ptr->do_filter & PNG_FILTER_SUB)
+ {
+ png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(png_ptr->rowbytes + 1));
+ png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
+ }
+
+ /* We only need to keep the previous row if we are using one of these. */
+ if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
+ {
+ /* Set up previous row buffer */
+ png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
+ (png_uint_32)buf_size);
+
+ if (png_ptr->do_filter & PNG_FILTER_UP)
+ {
+ png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(png_ptr->rowbytes + 1));
+ png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
+ }
+
+ if (png_ptr->do_filter & PNG_FILTER_AVG)
+ {
+ png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(png_ptr->rowbytes + 1));
+ png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
+ }
+
+ if (png_ptr->do_filter & PNG_FILTER_PAETH)
+ {
+ png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
+ (png_uint_32)(png_ptr->rowbytes + 1));
+ png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
+ }
+ }
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* If interlaced, we need to set up width and height of pass */
+ if (png_ptr->interlaced)
+ {
+ if (!(png_ptr->transformations & PNG_INTERLACE))
+ {
+ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
+ png_pass_ystart[0]) / png_pass_yinc[0];
+ png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
+ png_pass_start[0]) / png_pass_inc[0];
+ }
+ else
+ {
+ png_ptr->num_rows = png_ptr->height;
+ png_ptr->usr_width = png_ptr->width;
+ }
+ }
+ else
+#endif
+ {
+ png_ptr->num_rows = png_ptr->height;
+ png_ptr->usr_width = png_ptr->width;
+ }
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+}
+
+/* Internal use only. Called when finished processing a row of data. */
+void /* PRIVATE */
+png_write_finish_row(png_structp png_ptr)
+{
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ /* Start of interlace block in the y direction */
+ int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+
+ /* Offset to next interlace block in the y direction */
+ int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+#endif
+
+ int ret;
+
+ png_debug(1, "in png_write_finish_row");
+
+ /* Next row */
+ png_ptr->row_number++;
+
+ /* See if we are done */
+ if (png_ptr->row_number < png_ptr->num_rows)
+ return;
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+ /* If interlaced, go to next pass */
+ if (png_ptr->interlaced)
+ {
+ png_ptr->row_number = 0;
+ if (png_ptr->transformations & PNG_INTERLACE)
+ {
+ png_ptr->pass++;
+ }
+ else
+ {
+ /* Loop until we find a non-zero width or height pass */
+ do
+ {
+ png_ptr->pass++;
+ if (png_ptr->pass >= 7)
+ break;
+ png_ptr->usr_width = (png_ptr->width +
+ png_pass_inc[png_ptr->pass] - 1 -
+ png_pass_start[png_ptr->pass]) /
+ png_pass_inc[png_ptr->pass];
+ png_ptr->num_rows = (png_ptr->height +
+ png_pass_yinc[png_ptr->pass] - 1 -
+ png_pass_ystart[png_ptr->pass]) /
+ png_pass_yinc[png_ptr->pass];
+ if (png_ptr->transformations & PNG_INTERLACE)
+ break;
+ } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
+
+ }
+
+ /* Reset the row above the image for the next pass */
+ if (png_ptr->pass < 7)
+ {
+ if (png_ptr->prev_row != NULL)
+ png_memset(png_ptr->prev_row, 0,
+ (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
+ png_ptr->usr_bit_depth, png_ptr->width)) + 1);
+ return;
+ }
+ }
+#endif
+
+ /* If we get here, we've just written the last row, so we need
+ to flush the compressor */
+ do
+ {
+ /* Tell the compressor we are done */
+ ret = deflate(&png_ptr->zstream, Z_FINISH);
+ /* Check for an error */
+ if (ret == Z_OK)
+ {
+ /* Check to see if we need more room */
+ if (!(png_ptr->zstream.avail_out))
+ {
+ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ }
+ }
+ else if (ret != Z_STREAM_END)
+ {
+ if (png_ptr->zstream.msg != NULL)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ else
+ png_error(png_ptr, "zlib error");
+ }
+ } while (ret != Z_STREAM_END);
+
+ /* Write any extra space */
+ if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
+ {
+ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
+ png_ptr->zstream.avail_out);
+ }
+
+ deflateReset(&png_ptr->zstream);
+ png_ptr->zstream.data_type = Z_BINARY;
+}
+
+#ifdef PNG_WRITE_INTERLACING_SUPPORTED
+/* Pick out the correct pixels for the interlace pass.
+ * The basic idea here is to go through the row with a source
+ * pointer and a destination pointer (sp and dp), and copy the
+ * correct pixels for the pass. As the row gets compacted,
+ * sp will always be >= dp, so we should never overwrite anything.
+ * See the default: case for the easiest code to understand.
+ */
+void /* PRIVATE */
+png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
+{
+ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
+
+ /* Start of interlace block */
+ int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+
+ /* Offset to next interlace block */
+ int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+
+ png_debug(1, "in png_do_write_interlace");
+
+ /* We don't have to do anything on the last pass (6) */
+#ifdef PNG_USELESS_TESTS_SUPPORTED
+ if (row != NULL && row_info != NULL && pass < 6)
+#else
+ if (pass < 6)
+#endif
+ {
+ /* Each pixel depth is handled separately */
+ switch (row_info->pixel_depth)
+ {
+ case 1:
+ {
+ png_bytep sp;
+ png_bytep dp;
+ int shift;
+ int d;
+ int value;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ dp = row;
+ d = 0;
+ shift = 7;
+ for (i = png_pass_start[pass]; i < row_width;
+ i += png_pass_inc[pass])
+ {
+ sp = row + (png_size_t)(i >> 3);
+ value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
+ d |= (value << shift);
+
+ if (shift == 0)
+ {
+ shift = 7;
+ *dp++ = (png_byte)d;
+ d = 0;
+ }
+ else
+ shift--;
+
+ }
+ if (shift != 7)
+ *dp = (png_byte)d;
+ break;
+ }
+ case 2:
+ {
+ png_bytep sp;
+ png_bytep dp;
+ int shift;
+ int d;
+ int value;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ dp = row;
+ shift = 6;
+ d = 0;
+ for (i = png_pass_start[pass]; i < row_width;
+ i += png_pass_inc[pass])
+ {
+ sp = row + (png_size_t)(i >> 2);
+ value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
+ d |= (value << shift);
+
+ if (shift == 0)
+ {
+ shift = 6;
+ *dp++ = (png_byte)d;
+ d = 0;
+ }
+ else
+ shift -= 2;
+ }
+ if (shift != 6)
+ *dp = (png_byte)d;
+ break;
+ }
+ case 4:
+ {
+ png_bytep sp;
+ png_bytep dp;
+ int shift;
+ int d;
+ int value;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+
+ dp = row;
+ shift = 4;
+ d = 0;
+ for (i = png_pass_start[pass]; i < row_width;
+ i += png_pass_inc[pass])
+ {
+ sp = row + (png_size_t)(i >> 1);
+ value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
+ d |= (value << shift);
+
+ if (shift == 0)
+ {
+ shift = 4;
+ *dp++ = (png_byte)d;
+ d = 0;
+ }
+ else
+ shift -= 4;
+ }
+ if (shift != 4)
+ *dp = (png_byte)d;
+ break;
+ }
+ default:
+ {
+ png_bytep sp;
+ png_bytep dp;
+ png_uint_32 i;
+ png_uint_32 row_width = row_info->width;
+ png_size_t pixel_bytes;
+
+ /* Start at the beginning */
+ dp = row;
+ /* Find out how many bytes each pixel takes up */
+ pixel_bytes = (row_info->pixel_depth >> 3);
+ /* Loop through the row, only looking at the pixels that
+ matter */
+ for (i = png_pass_start[pass]; i < row_width;
+ i += png_pass_inc[pass])
+ {
+ /* Find out where the original pixel is */
+ sp = row + (png_size_t)i * pixel_bytes;
+ /* Move the pixel */
+ if (dp != sp)
+ png_memcpy(dp, sp, pixel_bytes);
+ /* Next pixel */
+ dp += pixel_bytes;
+ }
+ break;
+ }
+ }
+ /* Set new row width */
+ row_info->width = (row_info->width +
+ png_pass_inc[pass] - 1 -
+ png_pass_start[pass]) /
+ png_pass_inc[pass];
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+ row_info->width);
+ }
+}
+#endif
+
+/* This filters the row, chooses which filter to use, if it has not already
+ * been specified by the application, and then writes the row out with the
+ * chosen filter.
+ */
+#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
+#define PNG_HISHIFT 10
+#define PNG_LOMASK ((png_uint_32)0xffffL)
+#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
+void /* PRIVATE */
+png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
+{
+ png_bytep best_row;
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ png_bytep prev_row, row_buf;
+ png_uint_32 mins, bpp;
+ png_byte filter_to_do = png_ptr->do_filter;
+ png_uint_32 row_bytes = row_info->rowbytes;
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ int num_p_filters = (int)png_ptr->num_prev_filters;
+#endif
+
+ png_debug(1, "in png_write_find_filter");
+
+#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
+ {
+ /* These will never be selected so we need not test them. */
+ filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
+ }
+#endif
+
+ /* Find out how many bytes offset each pixel is */
+ bpp = (row_info->pixel_depth + 7) >> 3;
+
+ prev_row = png_ptr->prev_row;
+#endif
+ best_row = png_ptr->row_buf;
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+ row_buf = best_row;
+ mins = PNG_MAXSUM;
+
+ /* The prediction method we use is to find which method provides the
+ * smallest value when summing the absolute values of the distances
+ * from zero, using anything >= 128 as negative numbers. This is known
+ * as the "minimum sum of absolute differences" heuristic. Other
+ * heuristics are the "weighted minimum sum of absolute differences"
+ * (experimental and can in theory improve compression), and the "zlib
+ * predictive" method (not implemented yet), which does test compressions
+ * of lines using different filter methods, and then chooses the
+ * (series of) filter(s) that give minimum compressed data size (VERY
+ * computationally expensive).
+ *
+ * GRR 980525: consider also
+ * (1) minimum sum of absolute differences from running average (i.e.,
+ * keep running sum of non-absolute differences & count of bytes)
+ * [track dispersion, too? restart average if dispersion too large?]
+ * (1b) minimum sum of absolute differences from sliding average, probably
+ * with window size <= deflate window (usually 32K)
+ * (2) minimum sum of squared differences from zero or running average
+ * (i.e., ~ root-mean-square approach)
+ */
+
+
+ /* We don't need to test the 'no filter' case if this is the only filter
+ * that has been chosen, as it doesn't actually do anything to the data.
+ */
+ if ((filter_to_do & PNG_FILTER_NONE) &&
+ filter_to_do != PNG_FILTER_NONE)
+ {
+ png_bytep rp;
+ png_uint_32 sum = 0;
+ png_uint_32 i;
+ int v;
+
+ for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
+ {
+ v = *rp;
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ png_uint_32 sumhi, sumlo;
+ int j;
+ sumlo = sum & PNG_LOMASK;
+ sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
+
+ /* Reduce the sum if we match any of the previous rows */
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+ {
+ sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ /* Factor in the cost of this filter (this is here for completeness,
+ * but it makes no sense to have a "cost" for the NONE filter, as
+ * it has the minimum possible computational cost - none).
+ */
+ sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+ PNG_COST_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
+ PNG_COST_SHIFT;
+
+ if (sumhi > PNG_HIMASK)
+ sum = PNG_MAXSUM;
+ else
+ sum = (sumhi << PNG_HISHIFT) + sumlo;
+ }
+#endif
+ mins = sum;
+ }
+
+ /* Sub filter */
+ if (filter_to_do == PNG_FILTER_SUB)
+ /* It's the only filter so no testing is needed */
+ {
+ png_bytep rp, lp, dp;
+ png_uint_32 i;
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+ i++, rp++, dp++)
+ {
+ *dp = *rp;
+ }
+ for (lp = row_buf + 1; i < row_bytes;
+ i++, rp++, lp++, dp++)
+ {
+ *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+ }
+ best_row = png_ptr->sub_row;
+ }
+
+ else if (filter_to_do & PNG_FILTER_SUB)
+ {
+ png_bytep rp, dp, lp;
+ png_uint_32 sum = 0, lmins = mins;
+ png_uint_32 i;
+ int v;
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ /* We temporarily increase the "minimum sum" by the factor we
+ * would reduce the sum of this filter, so that we can do the
+ * early exit comparison without scaling the sum each time.
+ */
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 lmhi, lmlo;
+ lmlo = lmins & PNG_LOMASK;
+ lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+ {
+ lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+ PNG_COST_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+ PNG_COST_SHIFT;
+
+ if (lmhi > PNG_HIMASK)
+ lmins = PNG_MAXSUM;
+ else
+ lmins = (lmhi << PNG_HISHIFT) + lmlo;
+ }
+#endif
+
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
+ i++, rp++, dp++)
+ {
+ v = *dp = *rp;
+
+ sum += (v < 128) ? v : 256 - v;
+ }
+ for (lp = row_buf + 1; i < row_bytes;
+ i++, rp++, lp++, dp++)
+ {
+ v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 sumhi, sumlo;
+ sumlo = sum & PNG_LOMASK;
+ sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
+ {
+ sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+ PNG_COST_SHIFT;
+ sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
+ PNG_COST_SHIFT;
+
+ if (sumhi > PNG_HIMASK)
+ sum = PNG_MAXSUM;
+ else
+ sum = (sumhi << PNG_HISHIFT) + sumlo;
+ }
+#endif
+
+ if (sum < mins)
+ {
+ mins = sum;
+ best_row = png_ptr->sub_row;
+ }
+ }
+
+ /* Up filter */
+ if (filter_to_do == PNG_FILTER_UP)
+ {
+ png_bytep rp, dp, pp;
+ png_uint_32 i;
+
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+ pp = prev_row + 1; i < row_bytes;
+ i++, rp++, pp++, dp++)
+ {
+ *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+ }
+ best_row = png_ptr->up_row;
+ }
+
+ else if (filter_to_do & PNG_FILTER_UP)
+ {
+ png_bytep rp, dp, pp;
+ png_uint_32 sum = 0, lmins = mins;
+ png_uint_32 i;
+ int v;
+
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 lmhi, lmlo;
+ lmlo = lmins & PNG_LOMASK;
+ lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+ {
+ lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+ PNG_COST_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
+ PNG_COST_SHIFT;
+
+ if (lmhi > PNG_HIMASK)
+ lmins = PNG_MAXSUM;
+ else
+ lmins = (lmhi << PNG_HISHIFT) + lmlo;
+ }
+#endif
+
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
+ pp = prev_row + 1; i < row_bytes; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 sumhi, sumlo;
+ sumlo = sum & PNG_LOMASK;
+ sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
+ {
+ sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+ PNG_COST_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
+ PNG_COST_SHIFT;
+
+ if (sumhi > PNG_HIMASK)
+ sum = PNG_MAXSUM;
+ else
+ sum = (sumhi << PNG_HISHIFT) + sumlo;
+ }
+#endif
+
+ if (sum < mins)
+ {
+ mins = sum;
+ best_row = png_ptr->up_row;
+ }
+ }
+
+ /* Avg filter */
+ if (filter_to_do == PNG_FILTER_AVG)
+ {
+ png_bytep rp, dp, pp, lp;
+ png_uint_32 i;
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+ pp = prev_row + 1; i < bpp; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+ }
+ for (lp = row_buf + 1; i < row_bytes; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+ & 0xff);
+ }
+ best_row = png_ptr->avg_row;
+ }
+
+ else if (filter_to_do & PNG_FILTER_AVG)
+ {
+ png_bytep rp, dp, pp, lp;
+ png_uint_32 sum = 0, lmins = mins;
+ png_uint_32 i;
+ int v;
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 lmhi, lmlo;
+ lmlo = lmins & PNG_LOMASK;
+ lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
+ {
+ lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+ PNG_COST_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
+ PNG_COST_SHIFT;
+
+ if (lmhi > PNG_HIMASK)
+ lmins = PNG_MAXSUM;
+ else
+ lmins = (lmhi << PNG_HISHIFT) + lmlo;
+ }
+#endif
+
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
+ pp = prev_row + 1; i < bpp; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+ }
+ for (lp = row_buf + 1; i < row_bytes; i++)
+ {
+ v = *dp++ =
+ (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 sumhi, sumlo;
+ sumlo = sum & PNG_LOMASK;
+ sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
+ {
+ sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+ PNG_COST_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
+ PNG_COST_SHIFT;
+
+ if (sumhi > PNG_HIMASK)
+ sum = PNG_MAXSUM;
+ else
+ sum = (sumhi << PNG_HISHIFT) + sumlo;
+ }
+#endif
+
+ if (sum < mins)
+ {
+ mins = sum;
+ best_row = png_ptr->avg_row;
+ }
+ }
+
+ /* Paeth filter */
+ if (filter_to_do == PNG_FILTER_PAETH)
+ {
+ png_bytep rp, dp, pp, cp, lp;
+ png_uint_32 i;
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+ pp = prev_row + 1; i < bpp; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+ }
+
+ for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ b = *pp++;
+ c = *cp++;
+ a = *lp++;
+
+ p = b - c;
+ pc = a - c;
+
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+ p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+ *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+ }
+ best_row = png_ptr->paeth_row;
+ }
+
+ else if (filter_to_do & PNG_FILTER_PAETH)
+ {
+ png_bytep rp, dp, pp, cp, lp;
+ png_uint_32 sum = 0, lmins = mins;
+ png_uint_32 i;
+ int v;
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 lmhi, lmlo;
+ lmlo = lmins & PNG_LOMASK;
+ lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+ {
+ lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+ PNG_COST_SHIFT;
+ lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+ PNG_COST_SHIFT;
+
+ if (lmhi > PNG_HIMASK)
+ lmins = PNG_MAXSUM;
+ else
+ lmins = (lmhi << PNG_HISHIFT) + lmlo;
+ }
+#endif
+
+ for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
+ pp = prev_row + 1; i < bpp; i++)
+ {
+ v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+ }
+
+ for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ b = *pp++;
+ c = *cp++;
+ a = *lp++;
+
+#ifndef PNG_SLOW_PAETH
+ p = b - c;
+ pc = a - c;
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+ p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+#else /* PNG_SLOW_PAETH */
+ p = a + b - c;
+ pa = abs(p - a);
+ pb = abs(p - b);
+ pc = abs(p - c);
+ if (pa <= pb && pa <= pc)
+ p = a;
+ else if (pb <= pc)
+ p = b;
+ else
+ p = c;
+#endif /* PNG_SLOW_PAETH */
+
+ v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+
+ sum += (v < 128) ? v : 256 - v;
+
+ if (sum > lmins) /* We are already worse, don't continue. */
+ break;
+ }
+
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
+ {
+ int j;
+ png_uint_32 sumhi, sumlo;
+ sumlo = sum & PNG_LOMASK;
+ sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
+
+ for (j = 0; j < num_p_filters; j++)
+ {
+ if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
+ {
+ sumlo = (sumlo * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_weights[j]) >>
+ PNG_WEIGHT_SHIFT;
+ }
+ }
+
+ sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+ PNG_COST_SHIFT;
+ sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
+ PNG_COST_SHIFT;
+
+ if (sumhi > PNG_HIMASK)
+ sum = PNG_MAXSUM;
+ else
+ sum = (sumhi << PNG_HISHIFT) + sumlo;
+ }
+#endif
+
+ if (sum < mins)
+ {
+ best_row = png_ptr->paeth_row;
+ }
+ }
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ /* Do the actual writing of the filtered row data from the chosen filter. */
+
+ png_write_filtered_row(png_ptr, best_row);
+
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+ /* Save the type of filter we picked this time for future calculations */
+ if (png_ptr->num_prev_filters > 0)
+ {
+ int j;
+ for (j = 1; j < num_p_filters; j++)
+ {
+ png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
+ }
+ png_ptr->prev_filters[j] = best_row[0];
+ }
+#endif
+#endif /* PNG_WRITE_FILTER_SUPPORTED */
+}
+
+
+/* Do the actual writing of a previously filtered row. */
+void /* PRIVATE */
+png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
+{
+ png_debug(1, "in png_write_filtered_row");
+
+ png_debug1(2, "filter = %d", filtered_row[0]);
+ /* Set up the zlib input buffer */
+
+ png_ptr->zstream.next_in = filtered_row;
+ png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
+ /* Repeat until we have compressed all the data */
+ do
+ {
+ int ret; /* Return of zlib */
+
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+ /* Check for compression errors */
+ if (ret != Z_OK)
+ {
+ if (png_ptr->zstream.msg != NULL)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ else
+ png_error(png_ptr, "zlib error");
+ }
+
+ /* See if it is time to write another IDAT */
+ if (!(png_ptr->zstream.avail_out))
+ {
+ /* Write the IDAT and reset the zlib output buffer */
+ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
+ png_ptr->zstream.next_out = png_ptr->zbuf;
+ png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
+ }
+ /* Repeat until all data has been compressed */
+ } while (png_ptr->zstream.avail_in);
+
+ /* Swap the current and previous rows */
+ if (png_ptr->prev_row != NULL)
+ {
+ png_bytep tptr;
+
+ tptr = png_ptr->prev_row;
+ png_ptr->prev_row = png_ptr->row_buf;
+ png_ptr->row_buf = tptr;
+ }
+
+ /* Finish row - updates counters and flushes zlib if last row */
+ png_write_finish_row(png_ptr);
+
+#ifdef PNG_WRITE_FLUSH_SUPPORTED
+ png_ptr->flush_rows++;
+
+ if (png_ptr->flush_dist > 0 &&
+ png_ptr->flush_rows >= png_ptr->flush_dist)
+ {
+ png_write_flush(png_ptr);
+ }
+#endif
+}
+#endif /* PNG_WRITE_SUPPORTED */
diff --git a/Source/LibRawLite/COPYRIGHT b/Source/LibRawLite/COPYRIGHT
new file mode 100644
index 0000000..10574f9
--- /dev/null
+++ b/Source/LibRawLite/COPYRIGHT
@@ -0,0 +1,483 @@
+
+ ** LibRaw-lite: Raw images processing library **
+
+ Copyright (C) 2008-2009 LibRaw LLC <info@libraw.org>
+
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
+dcraw.c is copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net.
+
+========================================================================
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/Source/LibRawLite/Changelog.txt b/Source/LibRawLite/Changelog.txt
new file mode 100644
index 0000000..d30e4b2
--- /dev/null
+++ b/Source/LibRawLite/Changelog.txt
@@ -0,0 +1,2 @@
+2009-05-04 Alex Tutubalin <lexa@lexa.ru>
+ * Initial release of LibRaw-Lite based on LibRaw-0.7.2
diff --git a/Source/LibRawLite/LibRawLite.2003.vcproj b/Source/LibRawLite/LibRawLite.2003.vcproj
new file mode 100644
index 0000000..0348433
--- /dev/null
+++ b/Source/LibRawLite/LibRawLite.2003.vcproj
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="LibRawLite"
+ ProjectGUID="{1B0A722E-A6A5-4DF2-9A7F-DE24E20E6937}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="./"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;LIBRAW_NODLL;LIBRAW_LIBRARY_BUILD;NO_LCMS"
+ StringPooling="TRUE"
+ MinimalRebuild="FALSE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/LibRawLite.pch"
+ ExpandAttributedSource="FALSE"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibRawLite.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="./"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;LIBRAW_NODLL;NO_LCMS;LIBRAW_LIBRARY_BUILD"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/LibRawLite.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="0"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibRawLite.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <Filter
+ Name="internal"
+ Filter="">
+ <File
+ RelativePath=".\internal\dcraw_common.cpp">
+ </File>
+ <File
+ RelativePath=".\internal\dcraw_fileio.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="libraw"
+ Filter="">
+ <File
+ RelativePath=".\src\libraw_c_api.cpp">
+ </File>
+ <File
+ RelativePath=".\src\libraw_cxx.cpp">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <Filter
+ Name="internal"
+ Filter="">
+ <File
+ RelativePath=".\internal\defines.h">
+ </File>
+ <File
+ RelativePath=".\internal\libraw_internal_funcs.h">
+ </File>
+ <File
+ RelativePath=".\internal\var_defines.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="libraw"
+ Filter="">
+ <File
+ RelativePath=".\libraw\libraw.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_alloc.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_const.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_datastream.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_internal.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_types.h">
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_version.h">
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibRawLite/LibRawLite.2005.vcproj b/Source/LibRawLite/LibRawLite.2005.vcproj
new file mode 100644
index 0000000..5eb150a
--- /dev/null
+++ b/Source/LibRawLite/LibRawLite.2005.vcproj
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibRawLite"
+ ProjectGUID="{07F662C1-1323-42AB-B6AF-FBFD34A7437A}"
+ RootNamespace="LibRawLite"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="./"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;LIBRAW_NODLL;LIBRAW_LIBRARY_BUILD;NO_LCMS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibRawLite.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ WholeProgramOptimization="false"
+ AdditionalIncludeDirectories="./"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;LIBRAW_NODLL;NO_LCMS;LIBRAW_LIBRARY_BUILD"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="0"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibRawLite.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <Filter
+ Name="internal"
+ >
+ <File
+ RelativePath=".\internal\dcraw_common.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\internal\dcraw_fileio.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="libraw"
+ >
+ <File
+ RelativePath=".\src\libraw_c_api.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\src\libraw_cxx.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <Filter
+ Name="internal"
+ >
+ <File
+ RelativePath=".\internal\defines.h"
+ >
+ </File>
+ <File
+ RelativePath=".\internal\libraw_internal_funcs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\internal\var_defines.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="libraw"
+ >
+ <File
+ RelativePath=".\libraw\libraw.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_alloc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_const.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_datastream.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_internal.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_types.h"
+ >
+ </File>
+ <File
+ RelativePath=".\libraw\libraw_version.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibRawLite/dcraw/dcraw.c b/Source/LibRawLite/dcraw/dcraw.c
new file mode 100644
index 0000000..9bb9ee9
--- /dev/null
+++ b/Source/LibRawLite/dcraw/dcraw.c
@@ -0,0 +1,8680 @@
+/*
+ dcraw.c -- Dave Coffin's raw photo decoder
+ Copyright 1997-2009 by Dave Coffin, dcoffin a cybercom o net
+
+ This is a command-line ANSI C program to convert raw photos from
+ any digital camera on any computer running any operating system.
+
+ No license is required to download and use dcraw.c. However,
+ to lawfully redistribute dcraw, you must either (a) offer, at
+ no extra charge, full source code* for all executable files
+ containing RESTRICTED functions, (b) distribute this code under
+ the GPL Version 2 or later, (c) remove all RESTRICTED functions,
+ re-implement them, or copy them from an earlier, unrestricted
+ Revision of dcraw.c, or (d) purchase a license from the author.
+
+ The functions that process Foveon images have been RESTRICTED
+ since Revision 1.237. All other code remains free for all uses.
+
+ *If you have not modified dcraw.c in any way, a link to my
+ homepage qualifies as "full source code".
+
+ $Revision: 1.1 $
+ $Date: 2009/07/12 15:41:52 $
+ */
+
+#define VERSION "8.93"
+
+#define _GNU_SOURCE
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+/*
+ NO_JPEG disables decoding of compressed Kodak DC120 files.
+ NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include "../LibJPEG/jpeglib.h"
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#ifdef DJGPP
+#define fseeko fseek
+#define ftello ftell
+#else
+#define fgetc getc_unlocked
+#endif
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+
+#define ushort UshORt
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+/*
+ All global variables are defined here, and all functions that
+ access them are prefixed with "CLASS". Note that a thread-safe
+ C++ class cannot have non-const static local variables.
+ */
+FILE *ifp;
+short order;
+char *ifname, *meta_data;
+char cdesc[5], desc[512], make[64], model[64], model2[64], artist[64];
+float flash_used, canon_ev, iso_speed, shutter, aperture, focal_len;
+time_t timestamp;
+unsigned shot_order, kodak_cbpp, filters, exif_cfa, unique_id;
+off_t strip_offset, data_offset;
+off_t thumb_offset, meta_offset, profile_offset;
+unsigned thumb_length, meta_length, profile_length;
+unsigned thumb_misc, *oprof, fuji_layout, shot_select=0, multi_out=0;
+unsigned tiff_nifds, tiff_samples, tiff_bps, tiff_compress;
+unsigned black, maximum, mix_green, raw_color, use_gamma, zero_is_bad;
+unsigned zero_after_ff, is_raw, dng_version, is_foveon, data_error;
+unsigned tile_width, tile_length, gpsdata[32], load_flags;
+ushort raw_height, raw_width, height, width, top_margin, left_margin;
+ushort shrink, iheight, iwidth, fuji_width, thumb_width, thumb_height;
+int flip, tiff_flip, colors;
+double pixel_aspect, aber[4]={1,1,1,1}, gamm[5]={ 0.45,4.5,0,0,0 };
+ushort (*image)[4], white[8][8], curve[0x4001], cr2_slice[3], sraw_mul[4];
+float bright=1, user_mul[4]={0,0,0,0}, threshold=0;
+int half_size=0, four_color_rgb=0, document_mode=0, highlight=0;
+int verbose=0, use_auto_wb=0, use_camera_wb=0, use_camera_matrix=-1;
+int output_color=1, output_bps=8, output_tiff=0, med_passes=0;
+int no_auto_bright=0;
+unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
+float cam_mul[4], pre_mul[4], cmatrix[3][4], rgb_cam[3][4];
+const double xyz_rgb[3][3] = { /* XYZ from RGB */
+ { 0.412453, 0.357580, 0.180423 },
+ { 0.212671, 0.715160, 0.072169 },
+ { 0.019334, 0.119193, 0.950227 } };
+const float d65_white[3] = { 0.950456, 1, 1.088754 };
+int histogram[4][0x2000];
+void (*write_thumb)(FILE *), (*write_fun)(FILE *);
+void (*load_raw)(), (*thumb_load_raw)();
+jmp_buf failure;
+
+struct decode {
+ struct decode *branch[2];
+ int leaf;
+} first_decode[2048], *second_decode, *free_decode;
+
+struct {
+ int width, height, bps, comp, phint, offset, flip, samples, bytes;
+} tiff_ifd[10];
+
+struct {
+ int format, key_off, black, black_off, split_col, tag_21a;
+ float tag_210;
+} ph1;
+
+#define CLASS
+
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+ In order to inline this calculation, I make the risky
+ assumption that all filter patterns can be described
+ by a repeating pattern of eight rows and two columns
+
+ Do not use the FC or BAYER macros with the Leaf CatchLight,
+ because its pattern is 16x16, not 2x8.
+
+ Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+ PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
+ 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
+
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
+ 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
+ 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
+ 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
+ 4 C Y C Y C Y 4 Y C Y C Y C
+ PowerShot A5 5 G M G M G M 5 G M G M G M
+ 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
+ 7 M G M G M G 7 M G M G M G
+ 0 1 2 3 4 5
+ 0 C Y C Y C Y
+ 1 G M G M G M
+ 2 C Y C Y C Y
+ 3 M G M G M G
+
+ All RGB cameras use one of these Bayer grids:
+
+ 0x16161616: 0x61616161: 0x49494949: 0x94949494:
+
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
+ 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
+ 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
+ 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
+ */
+
+#define FC(row,col) \
+ (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)
+
+#define BAYER(row,col) \
+ image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+
+#define BAYER2(row,col) \
+ image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
+
+int CLASS fc (int row, int col)
+{
+ static const char filter[16][16] =
+ { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+ { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+ { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+ { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+ { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+ { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+ { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+ { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+ { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+ { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+ { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+ { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+ { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+ { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+ { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+ { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+
+ if (filters != 1) return FC(row,col);
+ return filter[(row+top_margin) & 15][(col+left_margin) & 15];
+}
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+ char *needle, size_t needlelen)
+{
+ char *c;
+ for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+ if (!memcmp (c, needle, needlelen))
+ return c;
+ return 0;
+}
+#define memmem my_memmem
+#endif
+
+void CLASS merror (void *ptr, char *where)
+{
+ if (ptr) return;
+ fprintf (stderr,_("%s: Out of memory in %s\n"), ifname, where);
+ longjmp (failure, 1);
+}
+
+void CLASS derror()
+{
+ if (!data_error) {
+ fprintf (stderr, "%s: ", ifname);
+ if (feof(ifp))
+ fprintf (stderr,_("Unexpected end of file\n"));
+ else
+ fprintf (stderr,_("Corrupt data near 0x%llx\n"), (INT64) ftello(ifp));
+ }
+ data_error = 1;
+}
+
+ushort CLASS sget2 (uchar *s)
+{
+ if (order == 0x4949) /* "II" means little-endian */
+ return s[0] | s[1] << 8;
+ else /* "MM" means big-endian */
+ return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+ uchar str[2] = { 0xff,0xff };
+ fread (str, 1, 2, ifp);
+ return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+ if (order == 0x4949)
+ return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ else
+ return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+ uchar str[4] = { 0xff,0xff,0xff,0xff };
+ fread (str, 1, 4, ifp);
+ return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+ return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+ union { int i; float f; } u;
+ u.i = i;
+ return u.f;
+}
+
+double CLASS getreal (int type)
+{
+ union { char c[8]; double d; } u;
+ int i, rev;
+
+ switch (type) {
+ case 3: return (unsigned short) get2();
+ case 4: return (unsigned int) get4();
+ case 5: u.d = (unsigned int) get4();
+ return u.d / (unsigned int) get4();
+ case 8: return (signed short) get2();
+ case 9: return (signed int) get4();
+ case 10: u.d = (signed int) get4();
+ return u.d / (signed int) get4();
+ case 11: return int_to_float (get4());
+ case 12:
+ rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+ for (i=0; i < 8; i++)
+ u.c[i ^ rev] = fgetc(ifp);
+ return u.d;
+ default: return fgetc(ifp);
+ }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+ if (fread (pixel, 2, count, ifp) < count) derror();
+ if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+ swab (pixel, pixel, count*2);
+}
+
+void CLASS canon_black (double dark[2])
+{
+ int c, diff, row, col;
+
+ if (raw_width < width+4) return;
+ FORC(2) dark[c] /= (raw_width-width-2) * height >> 1;
+ if ((diff = dark[0] - dark[1]))
+ for (row=0; row < height; row++)
+ for (col=1; col < width; col+=2)
+ BAYER(row,col) += diff;
+ dark[1] += diff;
+ black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+ static const short mul[4][5] = {
+ { 667, 358,397,565,452 },
+ { 731, 390,367,499,517 },
+ { 1119, 396,348,448,537 },
+ { 1399, 485,431,508,688 } };
+ int lo, hi, i;
+ float frac=0;
+
+ for (lo=4; --lo; )
+ if (*mul[lo] <= temp) break;
+ for (hi=0; hi < 3; hi++)
+ if (*mul[hi] >= temp) break;
+ if (lo != hi)
+ frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+ for (i=1; i < 5; i++)
+ pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+}
+
+/* Return values: 0 = white 1 = near white 2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+ int clipped=0, target, miss;
+
+ if (flash_used) {
+ if (ratio[1] < -104)
+ { ratio[1] = -104; clipped = 1; }
+ if (ratio[1] > 12)
+ { ratio[1] = 12; clipped = 1; }
+ } else {
+ if (ratio[1] < -264 || ratio[1] > 461) return 2;
+ if (ratio[1] < -50)
+ { ratio[1] = -50; clipped = 1; }
+ if (ratio[1] > 307)
+ { ratio[1] = 307; clipped = 1; }
+ }
+ target = flash_used || ratio[1] < 197
+ ? -38 - (398 * ratio[1] >> 10)
+ : -123 + (48 * ratio[1] >> 10);
+ if (target - mar <= ratio[0] &&
+ target + 20 >= ratio[0] && !clipped) return 0;
+ miss = target - ratio[0];
+ if (abs(miss) >= mar*4) return 2;
+ if (miss < -20) miss = -20;
+ if (miss > mar) miss = mar;
+ ratio[0] = target - miss;
+ return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+ int mar, row, col, i, j, st, count[] = { 0,0 };
+ int test[8], total[2][8], ratio[2][2], stat[2];
+
+ memset (&total, 0, sizeof total);
+ i = canon_ev + 0.5;
+ if (i < 10) mar = 150;
+ else if (i > 12) mar = 20;
+ else mar = 280 - 20 * i;
+ if (flash_used) mar = 80;
+ for (row=14; row < height-14; row+=4)
+ for (col=10; col < width; col+=2) {
+ for (i=0; i < 8; i++)
+ test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+ BAYER(row+(i >> 1),col+(i & 1));
+ for (i=0; i < 8; i++)
+ if (test[i] < 150 || test[i] > 1500) goto next;
+ for (i=0; i < 4; i++)
+ if (abs(test[i] - test[i+4]) > 50) goto next;
+ for (i=0; i < 2; i++) {
+ for (j=0; j < 4; j+=2)
+ ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+ stat[i] = canon_600_color (ratio[i], mar);
+ }
+ if ((st = stat[0] | stat[1]) > 1) goto next;
+ for (i=0; i < 2; i++)
+ if (stat[i])
+ for (j=0; j < 2; j++)
+ test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+ for (i=0; i < 8; i++)
+ total[st][i] += test[i];
+ count[st]++;
+next: ;
+ }
+ if (count[0] | count[1]) {
+ st = count[0]*200 < count[1];
+ for (i=0; i < 4; i++)
+ pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+ }
+}
+
+void CLASS canon_600_coeff()
+{
+ static const short table[6][12] = {
+ { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
+ { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
+ { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
+ { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
+ { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
+ { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
+ int t=0, i, c;
+ float mc, yc;
+
+ mc = pre_mul[1] / pre_mul[2];
+ yc = pre_mul[3] / pre_mul[2];
+ if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+ if (mc > 1.28 && mc <= 2) {
+ if (yc < 0.8789) t=3;
+ else if (yc <= 2) t=4;
+ }
+ if (flash_used) t=5;
+ for (raw_color = i=0; i < 3; i++)
+ FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+}
+
+void CLASS canon_600_load_raw()
+{
+ uchar data[1120], *dp;
+ ushort pixel[896], *pix;
+ int irow, row, col, val;
+ static const short mul[4][2] =
+ { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+ for (irow=row=0; irow < height; irow++) {
+ if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+ for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+ pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
+ pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+ pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+ pix[3] = (dp[4] << 2) + (dp[1] & 3);
+ pix[4] = (dp[5] << 2) + (dp[9] & 3);
+ pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+ pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+ pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = pixel[col];
+ for (col=width; col < raw_width; col++)
+ black += pixel[col];
+ if ((row+=2) > height) row = 1;
+ }
+ if (raw_width > width)
+ black = black / ((raw_width - width) * height) - 4;
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ if ((val = BAYER(row,col) - black) < 0) val = 0;
+ val = val * mul[row & 3][col & 1] >> 9;
+ BAYER(row,col) = val;
+ }
+ canon_600_fixed_wb(1311);
+ canon_600_auto_wb();
+ canon_600_coeff();
+ maximum = (0x3ff - black) * 1109 >> 9;
+ black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+ unsigned row, col, tot, n, r, c;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ if (BAYER(row,col) == 0) {
+ tot = n = 0;
+ for (r = row-2; r <= row+2; r++)
+ for (c = col-2; c <= col+2; c++)
+ if (r < height && c < width &&
+ FC(r,c) == FC(row,col) && BAYER(r,c))
+ tot += (n++,BAYER(r,c));
+ if (n) BAYER(row,col) = tot/n;
+ }
+}
+
+int CLASS canon_s2is()
+{
+ unsigned row;
+
+ for (row=0; row < 100; row++) {
+ fseek (ifp, row*3340 + 3284, SEEK_SET);
+ if (getc(ifp) > 15) return 1;
+ }
+ return 0;
+}
+
+void CLASS canon_a5_load_raw()
+{
+ ushort data[2565], *dp, pixel;
+ int vbits=0, buf=0, row, col, bc=0;
+
+ order = 0x4949;
+ for (row=-top_margin; row < raw_height-top_margin; row++) {
+ read_shorts (dp=data, raw_width * 10 / 16);
+ for (col=-left_margin; col < raw_width-left_margin; col++) {
+ if ((vbits -= 10) < 0)
+ buf = (vbits += 16, (buf << 16) + *dp++);
+ pixel = buf >> vbits & 0x3ff;
+ if ((unsigned) row < height && (unsigned) col < width)
+ BAYER(row,col) = pixel;
+ else if (col > 1-left_margin && col != width)
+ black += (bc++,pixel);
+ }
+ }
+ if (bc) black /= bc;
+ maximum = 0x3ff;
+ if (raw_width > 1600) remove_zeroes();
+}
+
+/*
+ getbits(-1) initializes the buffer
+ getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbits (int nbits)
+{
+ static unsigned bitbuf=0;
+ static int vbits=0, reset=0;
+ unsigned c;
+
+ if (nbits == -1)
+ return bitbuf = vbits = reset = 0;
+ if (nbits == 0 || reset) return 0;
+ while (vbits < nbits) {
+ if ((c = fgetc(ifp)) == EOF) derror();
+ if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
+ bitbuf = (bitbuf << 8) + (uchar) c;
+ vbits += 8;
+ }
+ vbits -= nbits;
+ return bitbuf << (32-nbits-vbits) >> (32-nbits);
+}
+
+void CLASS init_decoder()
+{
+ memset (first_decode, 0, sizeof first_decode);
+ free_decode = first_decode;
+}
+
+/*
+ Construct a decode tree according the specification in *source.
+ The first 16 bytes specify how many codes should be 1-bit, 2-bit
+ 3-bit, etc. Bytes after that are the leaf values.
+
+ For example, if the source is
+
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+ 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
+
+ then the code is
+
+ 00 0x04
+ 010 0x03
+ 011 0x05
+ 100 0x06
+ 101 0x02
+ 1100 0x07
+ 1101 0x01
+ 11100 0x08
+ 11101 0x09
+ 11110 0x00
+ 111110 0x0a
+ 1111110 0x0b
+ 1111111 0xff
+ */
+uchar * CLASS make_decoder (const uchar *source, int level)
+{
+ struct decode *cur;
+ static int leaf;
+ int i, next;
+
+ if (level==0) leaf=0;
+ cur = free_decode++;
+ if (free_decode > first_decode+2048) {
+ fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+ longjmp (failure, 2);
+ }
+ for (i=next=0; i <= leaf && next < 16; )
+ i += source[next++];
+ if (i > leaf) {
+ if (level < next) {
+ cur->branch[0] = free_decode;
+ make_decoder (source, level+1);
+ cur->branch[1] = free_decode;
+ make_decoder (source, level+1);
+ } else
+ cur->leaf = source[16 + leaf++];
+ }
+ return (uchar *) source + 16 + leaf;
+}
+
+void CLASS crw_init_tables (unsigned table)
+{
+ static const uchar first_tree[3][29] = {
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+ 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
+ { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
+ 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
+ { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
+ 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
+ };
+ static const uchar second_tree[3][180] = {
+ { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
+ 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
+ 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
+ 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
+ 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
+ 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
+ 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
+ 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
+ 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
+ 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
+ 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
+ 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
+ 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
+ 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
+ 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
+ { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
+ 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
+ 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
+ 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
+ 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
+ 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
+ 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
+ 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
+ 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
+ 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
+ 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
+ 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
+ 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
+ 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
+ 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
+ { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
+ 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
+ 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
+ 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
+ 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
+ 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
+ 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
+ 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
+ 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
+ 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
+ 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
+ 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
+ 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
+ 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
+ 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
+ };
+ if (table > 2) table = 2;
+ init_decoder();
+ make_decoder ( first_tree[table], 0);
+ second_decode = free_decode;
+ make_decoder (second_tree[table], 0);
+}
+
+/*
+ Return 0 if the image starts with compressed data,
+ 1 if it starts with uncompressed low-order bits.
+
+ In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+ uchar test[0x4000];
+ int ret=1, i;
+
+ fseek (ifp, 0, SEEK_SET);
+ fread (test, 1, sizeof test, ifp);
+ for (i=540; i < sizeof test - 1; i++)
+ if (test[i] == 0xff) {
+ if (test[i+1]) return 1;
+ ret=0;
+ }
+ return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+ ushort *pixel, *prow;
+ int nblocks, lowbits, i, row, r, col, save, val;
+ unsigned irow, icol;
+ struct decode *decode, *dindex;
+ int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+ double dark[2] = { 0,0 };
+ uchar c;
+
+ crw_init_tables (tiff_compress);
+ pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+ merror (pixel, "canon_compressed_load_raw()");
+ lowbits = canon_has_lowbits();
+ if (!lowbits) maximum = 0x3ff;
+ fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+ zero_after_ff = 1;
+ getbits(-1);
+ for (row=0; row < raw_height; row+=8) {
+ nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+ for (block=0; block < nblocks; block++) {
+ memset (diffbuf, 0, sizeof diffbuf);
+ decode = first_decode;
+ for (i=0; i < 64; i++ ) {
+ for (dindex=decode; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ leaf = dindex->leaf;
+ decode = second_decode;
+ if (leaf == 0 && i) break;
+ if (leaf == 0xff) continue;
+ i += leaf >> 4;
+ len = leaf & 15;
+ if (len == 0) continue;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ if (i < 64) diffbuf[i] = diff;
+ }
+ diffbuf[0] += carry;
+ carry = diffbuf[0];
+ for (i=0; i < 64; i++ ) {
+ if (pnum++ % raw_width == 0)
+ base[0] = base[1] = 512;
+ if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+ derror();
+ }
+ }
+ if (lowbits) {
+ save = ftell(ifp);
+ fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+ for (prow=pixel, i=0; i < raw_width*2; i++) {
+ c = fgetc(ifp);
+ for (r=0; r < 8; r+=2, prow++) {
+ val = (*prow << 2) + ((c >> r) & 3);
+ if (raw_width == 2672 && val < 512) val += 2;
+ *prow = val;
+ }
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ for (r=0; r < 8; r++) {
+ irow = row - top_margin + r;
+ if (irow >= height) continue;
+ for (col=0; col < raw_width; col++) {
+ icol = col - left_margin;
+ if (icol < width)
+ BAYER(irow,icol) = pixel[r*raw_width+col];
+ else if (col > 1)
+ dark[icol & 1] += pixel[r*raw_width+col];
+ }
+ }
+ }
+ free (pixel);
+ canon_black (dark);
+}
+
+/*
+ Not a full implementation of Lossless JPEG, just
+ enough to decode Canon, Kodak and Adobe DNG images.
+ */
+struct jhead {
+ int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+ struct CLASS decode *huff[6];
+ ushort *row;
+};
+
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+ int c, tag, len;
+ uchar data[0x10000], *dp;
+
+ if (!info_only) init_decoder();
+ memset (jh, 0, sizeof *jh);
+ FORC(6) jh->huff[c] = free_decode;
+ jh->restart = INT_MAX;
+ fread (data, 2, 1, ifp);
+ if (data[1] != 0xd8) return 0;
+ do {
+ fread (data, 2, 2, ifp);
+ tag = data[0] << 8 | data[1];
+ len = (data[2] << 8 | data[3]) - 2;
+ if (tag <= 0xff00) return 0;
+ fread (data, 1, len, ifp);
+ switch (tag) {
+ case 0xffc3:
+ jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+ case 0xffc0:
+ jh->bits = data[0];
+ jh->high = data[1] << 8 | data[2];
+ jh->wide = data[3] << 8 | data[4];
+ jh->clrs = data[5] + jh->sraw;
+ if (len == 9 && !dng_version) getc(ifp);
+ break;
+ case 0xffc4:
+ if (info_only) break;
+ for (dp = data; dp < data+len && *dp < 4; ) {
+ jh->huff[*dp] = free_decode;
+ dp = make_decoder (++dp, 0);
+ }
+ break;
+ case 0xffda:
+ jh->psv = data[1+data[0]*2];
+ jh->bits -= data[3+data[0]*2] & 15;
+ break;
+ case 0xffdd:
+ jh->restart = data[0] << 8 | data[1];
+ }
+ } while (tag != 0xffda);
+ if (info_only) return 1;
+ if (jh->sraw) {
+ FORC(4) jh->huff[2+c] = jh->huff[1];
+ FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+ }
+ jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+ merror (jh->row, "ljpeg_start()");
+ return zero_after_ff = 1;
+}
+
+int CLASS ljpeg_diff (struct decode *dindex)
+{
+ int len, diff;
+
+ while (dindex->branch[0])
+ dindex = dindex->branch[getbits(1)];
+ len = dindex->leaf;
+ if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+ return -32768;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+ int col, c, diff, pred, spred=0;
+ ushort mark=0, *row[3];
+
+ if (jrow * jh->wide % jh->restart == 0) {
+ FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+ if (jrow)
+ do mark = (mark << 8) + (c = fgetc(ifp));
+ while (c != EOF && mark >> 4 != 0xffd);
+ getbits(-1);
+ }
+ FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+ for (col=0; col < jh->wide; col++)
+ FORC(jh->clrs) {
+ diff = ljpeg_diff (jh->huff[c]);
+ if (jh->sraw && c <= jh->sraw && (col | c))
+ pred = spred;
+ else if (col) pred = row[0][-jh->clrs];
+ else pred = (jh->vpred[c] += diff) - diff;
+ if (jrow && col) switch (jh->psv) {
+ case 1: break;
+ case 2: pred = row[1][0]; break;
+ case 3: pred = row[1][-jh->clrs]; break;
+ case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
+ case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
+ case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
+ case 7: pred = (pred + row[1][0]) >> 1; break;
+ default: pred = 0;
+ }
+ if ((**row = pred + diff) >> jh->bits) derror();
+ if (c <= jh->sraw) spred = **row;
+ row[0]++; row[1]++;
+ }
+ return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+ int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
+ double dark[2] = { 0,0 };
+ struct jhead jh;
+ int min=INT_MAX;
+ ushort *rp;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ jwide = jh.wide * jh.clrs;
+
+ for (jrow=0; jrow < jh.high; jrow++) {
+ rp = ljpeg_row (jrow, &jh);
+ for (jcol=0; jcol < jwide; jcol++) {
+ val = *rp++;
+ if (jh.bits <= 12)
+ val = curve[val & 0xfff];
+ if (cr2_slice[0]) {
+ jidx = jrow*jwide + jcol;
+ i = jidx / (cr2_slice[1]*jh.high);
+ if ((j = i >= cr2_slice[0]))
+ i = cr2_slice[0];
+ jidx -= i * (cr2_slice[1]*jh.high);
+ row = jidx / cr2_slice[1+j];
+ col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+ }
+ if (raw_width == 3984 && (col -= 2) < 0)
+ col += (row--,raw_width);
+ if ((unsigned) (row-top_margin) < height) {
+ if ((unsigned) (col-left_margin) < width) {
+ BAYER(row-top_margin,col-left_margin) = val;
+ if (min > val) min = val;
+ } else if (col > 1)
+ dark[(col-left_margin) & 1] += val;
+ }
+ if (++col >= raw_width)
+ col = (row++,0);
+ }
+ }
+ free (jh.row);
+ canon_black (dark);
+ if (!strcasecmp(make,"KODAK"))
+ black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+ struct jhead jh;
+ short *rp=0, (*ip)[4];
+ int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+ int v[3]={0,0,0}, ver, hue;
+ char *cp;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ jwide = (jh.wide >>= 1) * jh.clrs;
+
+ for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+ scol = ecol;
+ ecol += cr2_slice[1] * 2 / jh.clrs;
+ if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+ for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+ ip = (short (*)[4]) image + row*width;
+ for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+ if ((jcol %= jwide) == 0)
+ rp = (short *) ljpeg_row (jrow++, &jh);
+ if (col >= width) continue;
+ FORC (jh.clrs-2)
+ ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+ ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+ ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+ }
+ }
+ }
+ for (cp=model2; *cp && !isdigit(*cp); cp++);
+ sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+ ver = (v[0]*1000 + v[1])*1000 + v[2];
+ hue = (jh.sraw+1) << 2;
+ if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+ hue = jh.sraw << 1;
+ ip = (short (*)[4]) image;
+ rp = ip[0];
+ for (row=0; row < height; row++, ip+=width) {
+ if (row & (jh.sraw >> 1))
+ for (col=0; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (row == height-1)
+ ip[col][c] = ip[col-width][c];
+ else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+ for (col=1; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (col == width-1)
+ ip[col][c] = ip[col-1][c];
+ else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+ }
+ for ( ; rp < ip[0]; rp+=4) {
+ if (unique_id < 0x80000200) {
+ pix[0] = rp[0] + rp[2] - 512;
+ pix[2] = rp[0] + rp[1] - 512;
+ pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+ } else {
+ rp[1] = (rp[1] << 2) + hue;
+ rp[2] = (rp[2] << 2) + hue;
+ pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
+ pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+ pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
+ }
+ FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+ }
+ free (jh.row);
+ maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+ unsigned r, c;
+
+ r = row -= top_margin;
+ c = col -= left_margin;
+ if (is_raw == 2 && shot_select) (*rp)++;
+ if (filters) {
+ if (fuji_width) {
+ r = row + fuji_width - 1 - (col >> 1);
+ c = row + ((col+1) >> 1);
+ }
+ if (r < height && c < width)
+ BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+ *rp += is_raw;
+ } else {
+ if (r < height && c < width)
+ FORC(tiff_samples)
+ image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+ *rp += tiff_samples;
+ }
+ if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+ unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+ struct jhead jh;
+ ushort *rp;
+
+ while (trow < raw_height) {
+ save = ftell(ifp);
+ if (tile_length < INT_MAX)
+ fseek (ifp, get4(), SEEK_SET);
+ if (!ljpeg_start (&jh, 0)) break;
+ jwide = jh.wide;
+ if (filters) jwide *= jh.clrs;
+ jwide /= is_raw;
+ for (row=col=jrow=0; jrow < jh.high; jrow++) {
+ rp = ljpeg_row (jrow, &jh);
+ for (jcol=0; jcol < jwide; jcol++) {
+ adobe_copy_pixel (trow+row, tcol+col, &rp);
+ if (++col >= tile_width || col >= raw_width)
+ row += 1 + (col = 0);
+ }
+ }
+ fseek (ifp, save+4, SEEK_SET);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ free (jh.row);
+ }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+ ushort *pixel, *rp;
+ int row, col;
+
+ pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+ merror (pixel, "adobe_dng_load_raw_nc()");
+ for (row=0; row < raw_height; row++) {
+ if (tiff_bps == 16)
+ read_shorts (pixel, raw_width * tiff_samples);
+ else {
+ getbits(-1);
+ for (col=0; col < raw_width * tiff_samples; col++)
+ pixel[col] = getbits(tiff_bps);
+ }
+ for (rp=pixel, col=0; col < raw_width; col++)
+ adobe_copy_pixel (row, col, &rp);
+ }
+ free (pixel);
+}
+
+void CLASS pentax_tree()
+{
+ ushort bit[2][13];
+ struct decode *cur;
+ int c, i, j;
+
+ init_decoder();
+ FORC(13) bit[0][c] = get2();
+ FORC(13) bit[1][c] = fgetc(ifp) & 15;
+ FORC(13) {
+ cur = first_decode;
+ for (i=0; i < bit[1][c]; i++) {
+ j = bit[0][c] >> (11-i) & 1;
+ if (!cur->branch[j]) cur->branch[j] = ++free_decode;
+ cur = cur->branch[j];
+ }
+ cur->leaf = c;
+ }
+}
+
+void CLASS pentax_k10_load_raw()
+{
+ int row, col, diff;
+ ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+ getbits(-1);
+ for (row=0; row < height; row++)
+ for (col=0; col < raw_width; col++) {
+ diff = ljpeg_diff (first_decode);
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ if (col < width)
+ BAYER(row,col) = hpred[col & 1];
+ if (hpred[col & 1] >> 12) derror();
+ }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+ static const uchar nikon_tree[][32] = {
+ { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
+ 5,4,3,6,2,7,1,0,8,9,11,10,12 },
+ { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
+ 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
+ 5,4,6,3,7,2,8,1,9,0,10,11,12 },
+ { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
+ 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+ { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
+ 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+ { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
+ 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+ struct decode *dindex;
+ ushort ver0, ver1, vpred[2][2], hpred[2], csize;
+ int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff;
+
+ fseek (ifp, meta_offset, SEEK_SET);
+ ver0 = fgetc(ifp);
+ ver1 = fgetc(ifp);
+ if (ver0 == 0x49 || ver1 == 0x58)
+ fseek (ifp, 2110, SEEK_CUR);
+ if (ver0 == 0x46) huff = 2;
+ if (tiff_bps == 14) huff += 3;
+ read_shorts (vpred[0], 4);
+ max = 1 << tiff_bps & 0x7fff;
+ if ((csize = get2()) > 1)
+ step = max / (csize-1);
+ if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+ for (i=0; i < csize; i++)
+ curve[i*step] = get2();
+ for (i=0; i < max; i++)
+ curve[i] = ( curve[i-i%step]*(step-i%step) +
+ curve[i-i%step+step]*(i%step) ) / step;
+ fseek (ifp, meta_offset+562, SEEK_SET);
+ split = get2();
+ } else if (ver0 != 0x46 && csize <= 0x4001)
+ read_shorts (curve, max=csize);
+ while (curve[max-2] == curve[max-1]) max--;
+ init_decoder();
+ make_decoder (nikon_tree[huff], 0);
+ fseek (ifp, data_offset, SEEK_SET);
+ getbits(-1);
+ for (min=row=0; row < height; row++) {
+ if (split && row == split) {
+ init_decoder();
+ make_decoder (nikon_tree[huff+1], 0);
+ max += (min = 16) << 1;
+ }
+ for (col=0; col < raw_width; col++) {
+ for (dindex=first_decode; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ len = dindex->leaf & 15;
+ shl = dindex->leaf >> 4;
+ diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - !shl;
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ if ((ushort)(hpred[col & 1] + min) >= max) derror();
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
+ }
+ }
+}
+
+/*
+ Figure out if a NEF file is compressed. These fancy heuristics
+ are only needed for the D100, thanks to a bug in some cameras
+ that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+ uchar test[256];
+ int i;
+
+ fseek (ifp, data_offset, SEEK_SET);
+ fread (test, 1, 256, ifp);
+ for (i=15; i < 256; i+=16)
+ if (test[i]) return 1;
+ return 0;
+}
+
+/*
+ Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+ int i, histo[256];
+ const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+ memset (histo, 0, sizeof histo);
+ fseek (ifp, -2000, SEEK_END);
+ for (i=0; i < 2000; i++)
+ histo[fgetc(ifp)]++;
+ for (i=0; i < 4; i++)
+ if (histo[often[i]] < 200)
+ return 0;
+ return 1;
+}
+
+/*
+ Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+ uchar t[12];
+ int i;
+
+ fseek (ifp, 0, SEEK_SET);
+ for (i=0; i < 1024; i++) {
+ fread (t, 1, 12, ifp);
+ if (((t[2] & t[4] & t[7] & t[9]) >> 4
+ & t[1] & t[6] & t[8] & t[11] & 3) != 3)
+ return 0;
+ }
+ return 1;
+}
+
+void CLASS nikon_3700()
+{
+ int bits, i;
+ uchar dp[24];
+ static const struct {
+ int bits;
+ char make[12], model[15];
+ } table[] = {
+ { 0x00, "PENTAX", "Optio 33WR" },
+ { 0x03, "NIKON", "E3200" },
+ { 0x32, "NIKON", "E3700" },
+ { 0x33, "OLYMPUS", "C740UZ" } };
+
+ fseek (ifp, 3072, SEEK_SET);
+ fread (dp, 1, 24, ifp);
+ bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (bits == table[i].bits) {
+ strcpy (make, table[i].make );
+ strcpy (model, table[i].model);
+ }
+}
+
+/*
+ Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+ int i, nz;
+ char tail[424];
+
+ fseek (ifp, -sizeof tail, SEEK_END);
+ fread (tail, 1, sizeof tail, ifp);
+ for (nz=i=0; i < sizeof tail; i++)
+ if (tail[i]) nz++;
+ return nz > 20;
+}
+
+/* Here raw_width is in bytes, not pixels. */
+void CLASS nikon_e900_load_raw()
+{
+ int offset=0, irow, row, col;
+
+ for (irow=0; irow < height; irow++) {
+ row = irow * 2 % height;
+ if (row == 1)
+ offset = - (-offset & -4096);
+ fseek (ifp, offset, SEEK_SET);
+ offset += raw_width;
+ getbits(-1);
+ for (col=0; col < width; col++)
+ BAYER(row,col) = getbits(10);
+ }
+}
+
+/*
+ The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+ ushort *pixel;
+ int wide, row, col, r, c;
+
+ fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+ wide = fuji_width << !fuji_layout;
+ pixel = (ushort *) calloc (wide, sizeof *pixel);
+ merror (pixel, "fuji_load_raw()");
+ for (row=0; row < raw_height; row++) {
+ read_shorts (pixel, wide);
+ fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+ for (col=0; col < wide; col++) {
+ if (fuji_layout) {
+ r = fuji_width - 1 - col + (row >> 1);
+ c = col + ((row+1) >> 1);
+ } else {
+ r = fuji_width - 1 + row - (col >> 1);
+ c = row + ((col+1) >> 1);
+ }
+ BAYER(r,c) = pixel[col];
+ }
+ }
+ free (pixel);
+}
+
+void CLASS jpeg_thumb (FILE *tfp);
+
+void CLASS ppm_thumb (FILE *tfp)
+{
+ char *thumb;
+ thumb_length = thumb_width*thumb_height*3;
+ thumb = (char *) malloc (thumb_length);
+ merror (thumb, "ppm_thumb()");
+ fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fread (thumb, 1, thumb_length, ifp);
+ fwrite (thumb, 1, thumb_length, tfp);
+ free (thumb);
+}
+
+void CLASS layer_thumb (FILE *tfp)
+{
+ int i, c;
+ char *thumb, map[][4] = { "012","102" };
+
+ colors = thumb_misc >> 5 & 7;
+ thumb_length = thumb_width*thumb_height;
+ thumb = (char *) calloc (colors, thumb_length);
+ merror (thumb, "layer_thumb()");
+ fprintf (tfp, "P%d\n%d %d\n255\n",
+ 5 + (colors >> 1), thumb_width, thumb_height);
+ fread (thumb, thumb_length, colors, ifp);
+ for (i=0; i < thumb_length; i++)
+ FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp);
+ free (thumb);
+}
+
+void CLASS rollei_thumb (FILE *tfp)
+{
+ unsigned i;
+ ushort *thumb;
+
+ thumb_length = thumb_width * thumb_height;
+ thumb = (ushort *) calloc (thumb_length, 2);
+ merror (thumb, "rollei_thumb()");
+ fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ read_shorts (thumb, thumb_length);
+ for (i=0; i < thumb_length; i++) {
+ putc (thumb[i] << 3, tfp);
+ putc (thumb[i] >> 5 << 2, tfp);
+ putc (thumb[i] >> 11 << 3, tfp);
+ }
+ free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+ uchar pixel[10];
+ unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+ isix = raw_width * raw_height * 5 / 8;
+ while (fread (pixel, 1, 10, ifp) == 10) {
+ for (i=0; i < 10; i+=2) {
+ todo[i] = iten++;
+ todo[i+1] = pixel[i] << 8 | pixel[i+1];
+ buffer = pixel[i] >> 2 | buffer << 6;
+ }
+ for ( ; i < 16; i+=2) {
+ todo[i] = isix++;
+ todo[i+1] = buffer >> (14-i)*5;
+ }
+ for (i=0; i < 16; i+=2) {
+ row = todo[i] / raw_width - top_margin;
+ col = todo[i] % raw_width - left_margin;
+ if (row < height && col < width)
+ BAYER(row,col) = (todo[i+1] & 0x3ff);
+ }
+ }
+ maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+ return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+ ushort head[8];
+ unsigned wide, y, x, c, rend, cend, row, col;
+ float *mrow, num, mult[4];
+
+ read_shorts (head, 8);
+ wide = head[2] / head[4];
+ mrow = (float *) calloc (nc*wide, sizeof *mrow);
+ merror (mrow, "phase_one_flat_field()");
+ for (y=0; y < head[3] / head[5]; y++) {
+ for (x=0; x < wide; x++)
+ for (c=0; c < nc; c+=2) {
+ num = is_float ? getreal(11) : get2()/32768.0;
+ if (y==0) mrow[c*wide+x] = num;
+ else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+ }
+ if (y==0) continue;
+ rend = head[1]-top_margin + y*head[5];
+ for (row = rend-head[5]; row < height && row < rend; row++) {
+ for (x=1; x < wide; x++) {
+ for (c=0; c < nc; c+=2) {
+ mult[c] = mrow[c*wide+x-1];
+ mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+ }
+ cend = head[0]-left_margin + x*head[4];
+ for (col = cend-head[4]; col < width && col < cend; col++) {
+ c = nc > 2 ? FC(row,col) : 0;
+ if (!(c & 1)) {
+ c = BAYER(row,col) * mult[c];
+ BAYER(row,col) = LIM(c,0,65535);
+ }
+ for (c=0; c < nc; c+=2)
+ mult[c] += mult[c+1];
+ }
+ }
+ for (x=0; x < wide; x++)
+ for (c=0; c < nc; c+=2)
+ mrow[c*wide+x] += mrow[(c+1)*wide+x];
+ }
+ }
+ free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+ unsigned entries, tag, data, save, col, row, type;
+ int len, i, j, k, cip, val[4], dev[4], sum, max;
+ int head[9], diff, mindiff=INT_MAX, off_412=0;
+ static const signed char dir[12][2] =
+ { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+ {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+ float poly[8], num, cfrac, frac, mult[2], *yval[2];
+ ushort curve[0x10000], *xval[2];
+
+ if (half_size || !meta_length) return;
+ if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+ fseek (ifp, meta_offset, SEEK_SET);
+ order = get2();
+ fseek (ifp, 6, SEEK_CUR);
+ fseek (ifp, meta_offset+get4(), SEEK_SET);
+ entries = get4(); get4();
+ while (entries--) {
+ tag = get4();
+ len = get4();
+ data = get4();
+ save = ftell(ifp);
+ fseek (ifp, meta_offset+data, SEEK_SET);
+ if (tag == 0x419) { /* Polynomial curve */
+ for (get4(), i=0; i < 8; i++)
+ poly[i] = getreal(11);
+ poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+ for (i=0; i < 0x10000; i++) {
+ num = (poly[5]*i + poly[3])*i + poly[1];
+ curve[i] = LIM(num,0,65535);
+ } goto apply; /* apply to right half */
+ } else if (tag == 0x41a) { /* Polynomial curve */
+ for (i=0; i < 4; i++)
+ poly[i] = getreal(11);
+ for (i=0; i < 0x10000; i++) {
+ for (num=0, j=4; j--; )
+ num = num * i + poly[j];
+ curve[i] = LIM(num+i,0,65535);
+ } apply: /* apply to whole image */
+ for (row=0; row < height; row++)
+ for (col = (tag & 1)*ph1.split_col; col < width; col++)
+ BAYER(row,col) = curve[BAYER(row,col)];
+ } else if (tag == 0x400) { /* Sensor defects */
+ while ((len -= 8) >= 0) {
+ col = get2() - left_margin;
+ row = get2() - top_margin;
+ type = get2(); get2();
+ if (col >= width) continue;
+ if (type == 131) /* Bad column */
+ for (row=0; row < height; row++)
+ if (FC(row,col) == 1) {
+ for (sum=i=0; i < 4; i++)
+ sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+ for (max=i=0; i < 4; i++) {
+ dev[i] = abs((val[i] << 2) - sum);
+ if (dev[max] < dev[i]) max = i;
+ }
+ BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+ } else {
+ for (sum=0, i=8; i < 12; i++)
+ sum += bayer (row+dir[i][0], col+dir[i][1]);
+ BAYER(row,col) = 0.5 + sum * 0.0732233 +
+ (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+ }
+ else if (type == 129) { /* Bad pixel */
+ if (row >= height) continue;
+ j = (FC(row,col) != 1) * 4;
+ for (sum=0, i=j; i < j+8; i++)
+ sum += bayer (row+dir[i][0], col+dir[i][1]);
+ BAYER(row,col) = (sum + 4) >> 3;
+ }
+ }
+ } else if (tag == 0x401) { /* All-color flat fields */
+ phase_one_flat_field (1, 2);
+ } else if (tag == 0x416 || tag == 0x410) {
+ phase_one_flat_field (0, 2);
+ } else if (tag == 0x40b) { /* Red+blue flat field */
+ phase_one_flat_field (0, 4);
+ } else if (tag == 0x412) {
+ fseek (ifp, 36, SEEK_CUR);
+ diff = abs (get2() - ph1.tag_21a);
+ if (mindiff > diff) {
+ mindiff = diff;
+ off_412 = ftell(ifp) - 38;
+ }
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ if (off_412) {
+ fseek (ifp, off_412, SEEK_SET);
+ for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+ yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+ merror (yval[0], "phase_one_correct()");
+ yval[1] = (float *) (yval[0] + head[1]*head[3]);
+ xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+ xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+ get2();
+ for (i=0; i < 2; i++)
+ for (j=0; j < head[i+1]*head[i+3]; j++)
+ yval[i][j] = getreal(11);
+ for (i=0; i < 2; i++)
+ for (j=0; j < head[i+1]*head[i+3]; j++)
+ xval[i][j] = get2();
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ cfrac = (float) col * head[3] / raw_width;
+ cfrac -= cip = cfrac;
+ num = BAYER(row,col) * 0.5;
+ for (i=cip; i < cip+2; i++) {
+ for (k=j=0; j < head[1]; j++)
+ if (num < xval[0][k = head[1]*i+j]) break;
+ frac = (j == 0 || j == head[1]) ? 0 :
+ (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+ mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+ }
+ i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+ * (row + top_margin) + num) * 2;
+ BAYER(row,col) = LIM(i,0,65535);
+ }
+ free (yval[0]);
+ }
+}
+
+void CLASS phase_one_load_raw()
+{
+ int row, col, a, b;
+ ushort *pixel, akey, bkey, mask;
+
+ fseek (ifp, ph1.key_off, SEEK_SET);
+ akey = get2();
+ bkey = get2();
+ mask = ph1.format == 1 ? 0x5555:0x1354;
+ fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "phase_one_load_raw()");
+ for (row=0; row < height; row++) {
+ read_shorts (pixel, raw_width);
+ for (col=0; col < raw_width; col+=2) {
+ a = pixel[col+0] ^ akey;
+ b = pixel[col+1] ^ bkey;
+ pixel[col+0] = (a & mask) | (b & ~mask);
+ pixel[col+1] = (b & mask) | (a & ~mask);
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = pixel[col+left_margin];
+ }
+ free (pixel);
+ phase_one_correct();
+}
+
+unsigned CLASS ph1_bits (int nbits)
+{
+ static UINT64 bitbuf=0;
+ static int vbits=0;
+
+ if (nbits == -1)
+ return bitbuf = vbits = 0;
+ if (nbits == 0) return 0;
+ if ((vbits -= nbits) < 0) {
+ bitbuf = bitbuf << 32 | get4();
+ vbits += 32;
+ }
+ return bitbuf << (64-nbits-vbits) >> (64-nbits);
+}
+
+void CLASS phase_one_load_raw_c()
+{
+ static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+ int *offset, len[2], pred[2], row, col, i, j;
+ ushort *pixel;
+ short (*black)[2];
+
+ pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+ merror (pixel, "phase_one_load_raw_c()");
+ offset = (int *) (pixel + raw_width);
+ fseek (ifp, strip_offset, SEEK_SET);
+ for (row=0; row < raw_height; row++)
+ offset[row] = get4();
+ black = (short (*)[2]) offset + raw_height;
+ fseek (ifp, ph1.black_off, SEEK_SET);
+ if (ph1.black_off)
+ read_shorts ((ushort *) black[0], raw_height*2);
+ for (i=0; i < 256; i++)
+ curve[i] = i*i / 3.969 + 0.5;
+ for (row=0; row < raw_height; row++) {
+ fseek (ifp, data_offset + offset[row], SEEK_SET);
+ ph1_bits(-1);
+ pred[0] = pred[1] = 0;
+ for (col=0; col < raw_width; col++) {
+ if (col >= (raw_width & -8))
+ len[0] = len[1] = 14;
+ else if ((col & 7) == 0)
+ for (i=0; i < 2; i++) {
+ for (j=0; j < 5 && !ph1_bits(1); j++);
+ if (j--) len[i] = length[j*2 + ph1_bits(1)];
+ }
+ if ((i = len[col & 1]) == 14)
+ pixel[col] = pred[col & 1] = ph1_bits(16);
+ else
+ pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+ if (pred[col & 1] >> 16) derror();
+ if (ph1.format == 5 && pixel[col] < 256)
+ pixel[col] = curve[pixel[col]];
+ }
+ if ((unsigned) (row-top_margin) < height)
+ for (col=0; col < width; col++) {
+ i = (pixel[col+left_margin] << 2)
+ - ph1.black + black[row][col >= ph1.split_col];
+ if (i > 0) BAYER(row-top_margin,col) = i;
+ }
+ }
+ free (pixel);
+ phase_one_correct();
+ maximum = 0xfffc - ph1.black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+ struct jhead jh;
+ struct decode *dindex;
+ int row, col, pred[2], len[2], diff, i;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ free (jh.row);
+ order = 0x4949;
+ ph1_bits(-1);
+ for (row=-top_margin; row < height; row++) {
+ pred[0] = pred[1] = 0x8000;
+ for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+ for (i=0; i < 2; i++) {
+ for (dindex=jh.huff[0]; dindex->branch[0]; )
+ dindex = dindex->branch[ph1_bits(1)];
+ len[i] = dindex->leaf;
+ }
+ for (i=0; i < 2; i++) {
+ diff = ph1_bits(len[i]);
+ if ((diff & (1 << (len[i]-1))) == 0)
+ diff -= (1 << len[i]) - 1;
+ if (diff == 65535) diff = -32768;
+ pred[i] += diff;
+ if (row >= 0 && (unsigned)(col+i) < width)
+ BAYER(row,col+i) = pred[i];
+ }
+ }
+ }
+ maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+ ushort *pixel;
+ unsigned tile=0, r, c, row, col;
+
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "leaf_hdr_load_raw()");
+ FORC(tiff_samples)
+ for (r=0; r < raw_height; r++) {
+ if (r % tile_length == 0) {
+ fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+ fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+ }
+ if (filters && c != shot_select) continue;
+ read_shorts (pixel, raw_width);
+ if ((row = r - top_margin) >= height) continue;
+ for (col=0; col < width; col++)
+ if (filters) BAYER(row,col) = pixel[col];
+ else image[row*width+col][c] = pixel[col];
+ }
+ free (pixel);
+ if (!filters) {
+ maximum = 0xffff;
+ raw_color = 1;
+ }
+}
+
+void CLASS unpacked_load_raw();
+
+void CLASS sinar_4shot_load_raw()
+{
+ ushort *pixel;
+ unsigned shot, row, col, r, c;
+
+ if ((shot = shot_select) || half_size) {
+ if (shot) shot--;
+ if (shot > 3) shot = 3;
+ fseek (ifp, data_offset + shot*4, SEEK_SET);
+ fseek (ifp, get4(), SEEK_SET);
+ unpacked_load_raw();
+ return;
+ }
+ free (image);
+ image = (ushort (*)[4])
+ calloc ((iheight=height)*(iwidth=width), sizeof *image);
+ merror (image, "sinar_4shot_load_raw()");
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "sinar_4shot_load_raw()");
+ for (shot=0; shot < 4; shot++) {
+ fseek (ifp, data_offset + shot*4, SEEK_SET);
+ fseek (ifp, get4(), SEEK_SET);
+ for (row=0; row < raw_height; row++) {
+ read_shorts (pixel, raw_width);
+ if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+ for (col=0; col < raw_width; col++) {
+ if ((c = col-left_margin - (shot & 1)) >= width) continue;
+ image[r*width+c][FC(row,col)] = pixel[col];
+ }
+ }
+ }
+ free (pixel);
+ shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+ int row, col;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ read_shorts (image[row*width+col], 3);
+}
+
+void CLASS packed_12_load_raw()
+{
+ int vbits=0, rbits=0, irow, row, col;
+ UINT64 bitbuf=0;
+
+ if (raw_width * 2 >= width * 3) { /* If raw_width is in bytes, */
+ rbits = raw_width * 8;
+ raw_width = raw_width * 2 / 3; /* convert it to pixels and */
+ rbits -= raw_width * 12; /* save the remainder. */
+ }
+ order = load_flags & 1 ? 0x4949 : 0x4d4d;
+ for (irow=0; irow < height; irow++) {
+ row = irow;
+ if (load_flags & 2 &&
+ (row = irow * 2 % height + irow / (height/2)) == 1 &&
+ load_flags & 4) {
+ if (vbits=0, tiff_compress)
+ fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET);
+ else {
+ fseek (ifp, 0, SEEK_END);
+ fseek (ifp, ftell(ifp)/2, SEEK_SET);
+ }
+ }
+ for (col=0; col < raw_width; col++) {
+ if ((vbits -= 12) < 0) {
+ bitbuf = bitbuf << 32 | get4();
+ vbits += 32;
+ }
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = bitbuf << (52-vbits) >> 52;
+ if (load_flags & 8 && (col % 10) == 9)
+ if (vbits=0, bitbuf & 255) derror();
+ }
+ vbits -= rbits;
+ }
+ if (!strcmp(make,"OLYMPUS")) black >>= 4;
+}
+
+void CLASS unpacked_load_raw()
+{
+ ushort *pixel;
+ int row, col, bits=0;
+
+ while (1 << ++bits < maximum);
+ fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+ pixel = (ushort *) calloc (width, sizeof *pixel);
+ merror (pixel, "unpacked_load_raw()");
+ for (row=0; row < height; row++) {
+ read_shorts (pixel, width);
+ fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+ for (col=0; col < width; col++)
+ if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+ }
+ free (pixel);
+}
+
+void CLASS nokia_load_raw()
+{
+ uchar *data, *dp;
+ ushort *pixel, *pix;
+ int dwide, row, c;
+
+ dwide = raw_width * 5 / 4;
+ data = (uchar *) malloc (dwide + raw_width*2);
+ merror (data, "nokia_load_raw()");
+ pixel = (ushort *) (data + dwide);
+ for (row=0; row < raw_height; row++) {
+ if (fread (data, 1, dwide, ifp) < dwide) derror();
+ for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+ FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+ if (row < top_margin)
+ FORC(width) black += pixel[c];
+ else
+ FORC(width) BAYER(row-top_margin,c) = pixel[c];
+ }
+ free (data);
+ if (top_margin) black /= top_margin * width;
+ maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+ static uchar buf[0x4000];
+ static int vbits;
+ int byte;
+
+ if (!nbits) return vbits=0;
+ if (!vbits) {
+ fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+ fread (buf, 1, load_flags, ifp);
+ }
+ vbits = (vbits - nbits) & 0x1ffff;
+ byte = vbits >> 3 ^ 0x3ff0;
+ return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+}
+
+void CLASS panasonic_load_raw()
+{
+ int row, col, i, j, sh=0, pred[2], nonz[2];
+
+ pana_bits(0);
+ for (row=0; row < height; row++)
+ for (col=0; col < raw_width; col++) {
+ if ((i = col % 14) == 0)
+ pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+ if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+ if (nonz[i & 1]) {
+ if ((j = pana_bits(8))) {
+ if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+ pred[i & 1] &= ~(-1 << sh);
+ pred[i & 1] += j << sh;
+ }
+ } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+ pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+ if (col < width)
+ if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+ }
+}
+
+void CLASS olympus_e300_load_raw()
+{
+ uchar *data, *dp;
+ ushort *pixel, *pix;
+ int dwide, row, col;
+
+ dwide = raw_width * 16 / 10;
+ fseek (ifp, dwide*top_margin, SEEK_CUR);
+ data = (uchar *) malloc (dwide + raw_width*2);
+ merror (data, "olympus_e300_load_raw()");
+ pixel = (ushort *) (data + dwide);
+ for (row=0; row < height; row++) {
+ if (fread (data, 1, dwide, ifp) < dwide) derror();
+ for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) {
+ if (((dp-data) & 15) == 15)
+ if (*dp++ && pix < pixel+width+left_margin) derror();
+ pix[0] = dp[1] << 8 | dp[0];
+ pix[1] = dp[2] << 4 | dp[1] >> 4;
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (pixel[col+left_margin] & 0xfff);
+ }
+ free (data);
+ maximum >>= 4;
+ black >>= 4;
+}
+
+void CLASS olympus_e410_load_raw()
+{
+ int row, col, nbits, sign, low, high, i, w, n, nw;
+ int acarry[2][3], *carry, pred, diff;
+
+ fseek (ifp, 7, SEEK_CUR);
+ getbits(-1);
+ for (row=0; row < height; row++) {
+ memset (acarry, 0, sizeof acarry);
+ for (col=0; col < width; col++) {
+ carry = acarry[col & 1];
+ i = 2 * (carry[2] < 3);
+ for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+ sign = getbits(1) * -1;
+ low = getbits(2);
+ for (high=0; high < 12; high++)
+ if (getbits(1)) break;
+ if (high == 12)
+ high = getbits(16-nbits) >> 1;
+ carry[0] = (high << nbits) | getbits(nbits);
+ diff = (carry[0] ^ sign) + carry[1];
+ carry[1] = (diff*3 + carry[1]) >> 5;
+ carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+ if (row < 2 && col < 2) pred = 0;
+ else if (row < 2) pred = BAYER(row,col-2);
+ else if (col < 2) pred = BAYER(row-2,col);
+ else {
+ w = BAYER(row,col-2);
+ n = BAYER(row-2,col);
+ nw = BAYER(row-2,col-2);
+ if ((w < nw && nw < n) || (n < nw && nw < w)) {
+ if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+ pred = w + n - nw;
+ else pred = (w + n) >> 1;
+ } else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+ }
+ if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+ }
+ }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+ uchar pixel[768];
+ unsigned irow, box, row, col;
+
+ for (irow=0; irow < 1481; irow++) {
+ if (fread (pixel, 1, 768, ifp) < 768) derror();
+ box = irow / 82;
+ row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+ switch (irow) {
+ case 1477: case 1479: continue;
+ case 1476: row = 984; break;
+ case 1480: row = 985; break;
+ case 1478: row = 985; box = 1;
+ }
+ if ((box < 12) && (box & 1)) {
+ for (col=0; col < 1533; col++, row ^= 1)
+ if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+ pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+ BAYER(row,1) = pixel[1] << 1;
+ BAYER(row,1533) = pixel[765] << 1;
+ } else
+ for (col=row & 1; col < 1534; col+=2)
+ BAYER(row,col) = pixel[col/2] << 1;
+ }
+ maximum = 0xff << 1;
+}
+
+void CLASS casio_qv5700_load_raw()
+{
+ uchar data[3232], *dp;
+ ushort pixel[2576], *pix;
+ int row, col;
+
+ for (row=0; row < height; row++) {
+ fread (data, 1, 3232, ifp);
+ for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
+ pix[0] = (dp[0] << 2) + (dp[1] >> 6);
+ pix[1] = (dp[1] << 4) + (dp[2] >> 4);
+ pix[2] = (dp[2] << 6) + (dp[3] >> 2);
+ pix[3] = (dp[3] << 8) + (dp[4] );
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (pixel[col] & 0x3ff);
+ }
+ maximum = 0x3fc;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+ uchar pixel[484][644];
+ static const short gstep[16] =
+ { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+ static const short rstep[6][4] =
+ { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 },
+ { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+ static const short curve[256] =
+ { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
+ 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
+ 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
+ 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
+ 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
+ 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
+ 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
+ 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
+ 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
+ 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
+ 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
+ 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
+ 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
+ int rb, row, col, sharp, val=0;
+
+ getbits(-1);
+ memset (pixel, 0x80, sizeof pixel);
+ for (row=2; row < height+2; row++) {
+ for (col=2+(row & 1); col < width+2; col+=2) {
+ val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+ pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+ pixel[row][col] = val = LIM(val,0,255);
+ if (col < 4)
+ pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+ if (row == 2)
+ pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+ }
+ pixel[row][col] = val;
+ }
+ for (rb=0; rb < 2; rb++)
+ for (row=2+rb; row < height+2; row+=2)
+ for (col=3-(row & 1); col < width+2; col+=2) {
+ if (row < 4 || col < 4) sharp = 2;
+ else {
+ val = ABS(pixel[row-2][col] - pixel[row][col-2])
+ + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+ + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+ sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 :
+ val < 32 ? 3 : val < 48 ? 4 : 5;
+ }
+ val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+ + rstep[sharp][getbits(2)];
+ pixel[row][col] = val = LIM(val,0,255);
+ if (row < 4) pixel[row-2][col+2] = val;
+ if (col < 4) pixel[row+2][col-2] = val;
+ }
+ for (row=2; row < height+2; row++)
+ for (col=3-(row & 1); col < width+2; col+=2) {
+ val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+ pixel[row][col+1]) >> 1) - 0x100;
+ pixel[row][col] = LIM(val,0,255);
+ }
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ BAYER(row,col) = curve[pixel[row+2][col+2]];
+ maximum = 0x3ff;
+}
+
+const int * CLASS make_decoder_int (const int *source, int level)
+{
+ struct decode *cur;
+
+ cur = free_decode++;
+ if (level < source[0]) {
+ cur->branch[0] = free_decode;
+ source = make_decoder_int (source, level+1);
+ cur->branch[1] = free_decode;
+ source = make_decoder_int (source, level+1);
+ } else {
+ cur->leaf = source[1];
+ source += 2;
+ }
+ return source;
+}
+
+int CLASS radc_token (int tree)
+{
+ int t;
+ static struct decode *dstart[18], *dindex;
+ static const int *s, source[] = {
+ 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
+ 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
+ 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
+ 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
+ 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
+ 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
+ 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
+ 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
+ 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
+ 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
+ 1,0, 2,2, 2,-2,
+ 1,-3, 1,3,
+ 2,-17, 2,-5, 2,5, 2,17,
+ 2,-7, 2,2, 2,9, 2,18,
+ 2,-18, 2,-9, 2,-2, 2,7,
+ 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
+ 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
+ 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
+ };
+
+ if (free_decode == first_decode)
+ for (s=source, t=0; t < 18; t++) {
+ dstart[t] = free_decode;
+ s = make_decoder_int (s, 0);
+ }
+ if (tree == 18) {
+ if (kodak_cbpp == 243)
+ return (getbits(6) << 2) + 2; /* most DC50 photos */
+ else
+ return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */
+ }
+ for (dindex = dstart[tree]; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ return dindex->leaf;
+}
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+ int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+ short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+
+ init_decoder();
+ getbits(-1);
+ for (i=0; i < sizeof(buf)/sizeof(short); i++)
+ buf[0][0][i] = 2048;
+ for (row=0; row < height; row+=4) {
+ FORC3 mul[c] = getbits(6);
+ FORC3 {
+ val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+ s = val > 65564 ? 10:12;
+ x = ~(-1 << (s-1));
+ val <<= 12-s;
+ for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+ buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+ last[c] = mul[c];
+ for (r=0; r <= !c; r++) {
+ buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+ for (tree=1, col=width/2; col > 0; ) {
+ if ((tree = radc_token(tree))) {
+ col -= 2;
+ if (tree == 8)
+ FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
+ else
+ FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+ } else
+ do {
+ nreps = (col > 2) ? radc_token(9) + 1 : 1;
+ for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+ col -= 2;
+ FORYX buf[c][y][x] = PREDICTOR;
+ if (rep & 1) {
+ step = radc_token(10) << 4;
+ FORYX buf[c][y][x] += step;
+ }
+ }
+ } while (nreps == 9);
+ }
+ for (y=0; y < 2; y++)
+ for (x=0; x < width/2; x++) {
+ val = (buf[c][y+1][x] << 4) / mul[c];
+ if (val < 0) val = 0;
+ if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+ else BAYER(row+r*2+y,x*2+y) = val;
+ }
+ memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+ }
+ }
+ for (y=row; y < row+4; y++)
+ for (x=0; x < width; x++)
+ if ((x+y) & 1) {
+ r = x ? x-1 : x+1;
+ s = x+1 < width ? x+1 : x-1;
+ val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+ if (val < 0) val = 0;
+ BAYER(y,x) = val;
+ }
+ }
+ maximum = 0xfff;
+ use_gamma = 0;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+ static uchar jpeg_buffer[4096];
+ size_t nbytes;
+
+ nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+ swab (jpeg_buffer, jpeg_buffer, nbytes);
+ cinfo->src->next_input_byte = jpeg_buffer;
+ cinfo->src->bytes_in_buffer = nbytes;
+ return TRUE;
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPARRAY buf;
+ JSAMPLE (*pixel)[3];
+ int row, col;
+
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_decompress (&cinfo);
+ jpeg_stdio_src (&cinfo, ifp);
+ cinfo.src->fill_input_buffer = fill_input_buffer;
+ jpeg_read_header (&cinfo, TRUE);
+ jpeg_start_decompress (&cinfo);
+ if ((cinfo.output_width != width ) ||
+ (cinfo.output_height*2 != height ) ||
+ (cinfo.output_components != 3 )) {
+ fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+ jpeg_destroy_decompress (&cinfo);
+ longjmp (failure, 3);
+ }
+ buf = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ row = cinfo.output_scanline * 2;
+ jpeg_read_scanlines (&cinfo, buf, 1);
+ pixel = (JSAMPLE (*)[3]) buf[0];
+ for (col=0; col < width; col+=2) {
+ BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+ BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+ BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+ BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+ }
+ }
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+ maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+ static const int mul[4] = { 162, 192, 187, 92 };
+ static const int add[4] = { 0, 636, 424, 212 };
+ uchar pixel[848];
+ int row, shift, col;
+
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 1, 848, ifp) < 848) derror();
+ shift = row * mul[row & 3] + add[row & 3];
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+ }
+ maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+ uchar *pixel;
+ unsigned row, col, val, lblack=0;
+
+ pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "eight_bit_load_raw()");
+ fseek (ifp, top_margin*raw_width, SEEK_CUR);
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+ for (col=0; col < raw_width; col++) {
+ val = curve[pixel[col]];
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = val;
+ else lblack += val;
+ }
+ }
+ free (pixel);
+ if (raw_width > width+1)
+ black = lblack / ((raw_width - width) * height);
+ if (!strncmp(model,"DC2",3))
+ black = 0;
+ maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+ uchar *pixel;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+ merror (pixel, "kodak_yrgb_load_raw()");
+ for (row=0; row < height; row++) {
+ if (~row & 1)
+ if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+ for (col=0; col < raw_width; col++) {
+ y = pixel[width*2*(row & 1) + col];
+ cb = pixel[width + (col & -2)] - 128;
+ cr = pixel[width + (col & -2)+1] - 128;
+ rgb[1] = y-((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row*width+col][c] = LIM(rgb[c],0,255);
+ }
+ }
+ free (pixel);
+ use_gamma = 0;
+}
+
+void CLASS kodak_262_load_raw()
+{
+ static const uchar kodak_tree[2][26] =
+ { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+ { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+ struct decode *decode[2];
+ uchar *pixel;
+ int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+ init_decoder();
+ for (i=0; i < 2; i++) {
+ decode[i] = free_decode;
+ make_decoder (kodak_tree[i], 0);
+ }
+ ns = (raw_height+63) >> 5;
+ pixel = (uchar *) malloc (raw_width*32 + ns*4);
+ merror (pixel, "kodak_262_load_raw()");
+ strip = (int *) (pixel + raw_width*32);
+ order = 0x4d4d;
+ for (i=0; i < ns; i++)
+ strip[i] = get4();
+ for (row=0; row < raw_height; row++) {
+ if ((row & 31) == 0) {
+ fseek (ifp, strip[row >> 5], SEEK_SET);
+ getbits(-1);
+ pi = 0;
+ }
+ for (col=0; col < raw_width; col++) {
+ chess = (row + col) & 1;
+ pi1 = chess ? pi-2 : pi-raw_width-1;
+ pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+ if (col <= chess) pi1 = -1;
+ if (pi1 < 0) pi1 = pi2;
+ if (pi2 < 0) pi2 = pi1;
+ if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+ pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+ pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
+ if (val >> 8) derror();
+ val = curve[pixel[pi++]];
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = val;
+ else black += val;
+ }
+ }
+ free (pixel);
+ if (raw_width > width)
+ black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+ uchar c, blen[768];
+ ushort raw[6];
+ INT64 bitbuf=0;
+ int save, bits=0, i, j, len, diff;
+
+ save = ftell(ifp);
+ bsize = (bsize + 3) & -4;
+ for (i=0; i < bsize; i+=2) {
+ c = fgetc(ifp);
+ if ((blen[i ] = c & 15) > 12 ||
+ (blen[i+1] = c >> 4) > 12 ) {
+ fseek (ifp, save, SEEK_SET);
+ for (i=0; i < bsize; i+=8) {
+ read_shorts (raw, 6);
+ out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+ out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+ for (j=0; j < 6; j++)
+ out[i+2+j] = raw[j] & 0xfff;
+ }
+ return 1;
+ }
+ }
+ if ((bsize & 7) == 4) {
+ bitbuf = fgetc(ifp) << 8;
+ bitbuf += fgetc(ifp);
+ bits = 16;
+ }
+ for (i=0; i < bsize; i++) {
+ len = blen[i];
+ if (bits < len) {
+ for (j=0; j < 32; j+=8)
+ bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+ bits += 32;
+ }
+ diff = bitbuf & (0xffff >> (16-len));
+ bitbuf >>= len;
+ bits -= len;
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ out[i] = diff;
+ }
+ return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+ short buf[256];
+ int row, col, len, pred[2], ret, i;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col+=256) {
+ pred[0] = pred[1] = 0;
+ len = MIN (256, width-col);
+ ret = kodak_65000_decode (buf, len);
+ for (i=0; i < len; i++)
+ if ((BAYER(row,col+i) = curve[ret ? buf[i] :
+ (pred[i & 1] += buf[i])]) >> 12) derror();
+ }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+ short buf[384], *bp;
+ int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+ ushort *ip;
+
+ for (row=0; row < height; row+=2)
+ for (col=0; col < width; col+=128) {
+ len = MIN (128, width-col);
+ kodak_65000_decode (buf, len*3);
+ y[0][1] = y[1][1] = cb = cr = 0;
+ for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+ cb += bp[4];
+ cr += bp[5];
+ rgb[1] = -((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ for (j=0; j < 2; j++)
+ for (k=0; k < 2; k++) {
+ if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+ ip = image[(row+j)*width + col+i+k];
+ FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+ }
+ }
+ }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+ short buf[768], *bp;
+ int row, col, len, c, i, rgb[3];
+ ushort *ip=image[0];
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col+=256) {
+ len = MIN (256, width-col);
+ kodak_65000_decode (buf, len*3);
+ memset (rgb, 0, sizeof rgb);
+ for (bp=buf, i=0; i < len; i++, ip+=4)
+ FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+ }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+ int row, col;
+ colors = thumb_misc >> 5;
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ read_shorts (image[row*width+col], colors);
+ maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+ static unsigned pad[128], p;
+
+ if (start) {
+ for (p=0; p < 4; p++)
+ pad[p] = key = key * 48828125 + 1;
+ pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+ for (p=4; p < 127; p++)
+ pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+ for (p=0; p < 127; p++)
+ pad[p] = htonl(pad[p]);
+ }
+ while (len--)
+ *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+}
+
+void CLASS sony_load_raw()
+{
+ uchar head[40];
+ ushort *pixel;
+ unsigned i, key, row, col;
+
+ fseek (ifp, 200896, SEEK_SET);
+ fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+ order = 0x4d4d;
+ key = get4();
+ fseek (ifp, 164600, SEEK_SET);
+ fread (head, 1, 40, ifp);
+ sony_decrypt ((unsigned int *) head, 10, 1, key);
+ for (i=26; i-- > 22; )
+ key = key << 8 | head[i];
+ fseek (ifp, data_offset, SEEK_SET);
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "sony_load_raw()");
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+ sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+ for (col=9; col < left_margin; col++)
+ black += ntohs(pixel[col]);
+ for (col=0; col < width; col++)
+ if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+ derror();
+ }
+ free (pixel);
+ if (left_margin > 9)
+ black /= (left_margin-9) * height;
+ maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+ int col, row, len, diff, sum=0;
+
+ getbits(-1);
+ for (col = raw_width; col--; )
+ for (row=0; row < raw_height+1; row+=2) {
+ if (row == raw_height) row = 1;
+ len = 4 - getbits(2);
+ if (len == 3 && getbits(1)) len = 0;
+ if (len == 4)
+ while (len < 17 && !getbits(1)) len++;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ if ((sum += diff) >> 12) derror();
+ if (row < height) BAYER(row,col) = sum;
+ }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+ uchar *data, *dp;
+ ushort pix[16];
+ int row, col, val, max, min, imax, imin, sh, bit, i;
+
+ data = (uchar *) malloc (raw_width*tiff_bps >> 3);
+ merror (data, "sony_arw2_load_raw()");
+ for (row=0; row < height; row++) {
+ fread (data, 1, raw_width*tiff_bps >> 3, ifp);
+ if (tiff_bps == 8) {
+ for (dp=data, col=0; col < width-30; dp+=16) {
+ max = 0x7ff & (val = sget4(dp));
+ min = 0x7ff & val >> 11;
+ imax = 0x0f & val >> 22;
+ imin = 0x0f & val >> 26;
+ for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+ for (bit=30, i=0; i < 16; i++)
+ if (i == imax) pix[i] = max;
+ else if (i == imin) pix[i] = min;
+ else {
+ pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+ if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+ bit += 7;
+ }
+ for (i=0; i < 16; i++, col+=2)
+ BAYER(row,col) = curve[pix[i] << 1] >> 1;
+ col -= col & 1 ? 1:31;
+ }
+ } else if (tiff_bps == 12)
+ for (dp=data, col=0; col < width; dp+=3, col+=2) {
+ BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1;
+ BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1;
+ }
+ }
+ free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+ uchar hist[3][13] = {
+ { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+ { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+ { 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
+ int low, high=0xff, carry=0, nbits=8;
+ int s, count, bin, next, i, sym[3];
+ uchar diff, pred[]={0,0};
+ ushort data=0, range=0;
+ unsigned pix, row, col;
+
+ fseek (ifp, seg[0][1]+1, SEEK_SET);
+ getbits(-1);
+ for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+ for (s=0; s < 3; s++) {
+ data = data << nbits | getbits(nbits);
+ if (carry < 0)
+ carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+ while (--nbits >= 0)
+ if ((data >> nbits & 0xff) == 0xff) break;
+ if (nbits > 0)
+ data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+ ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+ if (nbits >= 0) {
+ data += getbits(1);
+ carry = nbits - 8;
+ }
+ count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+ for (bin=0; hist[s][bin+5] > count; bin++);
+ low = hist[s][bin+5] * (high >> 4) >> 2;
+ if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+ high -= low;
+ for (nbits=0; high << nbits < 128; nbits++);
+ range = (range+low) << nbits;
+ high <<= nbits;
+ next = hist[s][1];
+ if (++hist[s][2] > hist[s][3]) {
+ next = (next+1) & hist[s][0];
+ hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+ hist[s][2] = 1;
+ }
+ if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+ if (bin < hist[s][1])
+ for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+ else if (next <= bin)
+ for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+ }
+ hist[s][1] = next;
+ sym[s] = bin;
+ }
+ diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+ if (sym[0] & 4)
+ diff = diff ? -diff : 0x80;
+ if (ftell(ifp) + 12 >= seg[1][1])
+ diff = 0;
+ pred[pix & 1] += diff;
+ row = pix / raw_width - top_margin;
+ col = pix % raw_width - left_margin;
+ if (row < height && col < width)
+ BAYER(row,col) = pred[pix & 1];
+ if (!(pix & 1) && HOLE(row)) pix += 2;
+ }
+ maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+ unsigned seg[2][2];
+
+ fseek (ifp, 16, SEEK_SET);
+ seg[0][0] = 0;
+ seg[0][1] = get2();
+ seg[1][0] = raw_width * raw_height;
+ seg[1][1] = INT_MAX;
+ smal_decode_segment (seg, 0);
+ use_gamma = 0;
+}
+
+int CLASS median4 (int *p)
+{
+ int min, max, sum, i;
+
+ min = max = sum = p[0];
+ for (i=1; i < 4; i++) {
+ sum += p[i];
+ if (min > p[i]) min = p[i];
+ if (max < p[i]) max = p[i];
+ }
+ return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+ int row, col, val[4];
+
+ for (row=2; row < height-2; row++) {
+ if (!HOLE(row)) continue;
+ for (col=1; col < width-1; col+=4) {
+ val[0] = BAYER(row-1,col-1);
+ val[1] = BAYER(row-1,col+1);
+ val[2] = BAYER(row+1,col-1);
+ val[3] = BAYER(row+1,col+1);
+ BAYER(row,col) = median4(val);
+ }
+ for (col=2; col < width-2; col+=4)
+ if (HOLE(row-2) || HOLE(row+2))
+ BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+ else {
+ val[0] = BAYER(row,col-2);
+ val[1] = BAYER(row,col+2);
+ val[2] = BAYER(row-2,col);
+ val[3] = BAYER(row+2,col);
+ BAYER(row,col) = median4(val);
+ }
+ }
+}
+
+void CLASS smal_v9_load_raw()
+{
+ unsigned seg[256][2], offset, nseg, holes, i;
+
+ fseek (ifp, 67, SEEK_SET);
+ offset = get4();
+ nseg = fgetc(ifp);
+ fseek (ifp, offset, SEEK_SET);
+ for (i=0; i < nseg*2; i++)
+ seg[0][i] = get4() + data_offset*(i & 1);
+ fseek (ifp, 78, SEEK_SET);
+ holes = fgetc(ifp);
+ fseek (ifp, 88, SEEK_SET);
+ seg[nseg][0] = raw_height * raw_width;
+ seg[nseg][1] = get4() + data_offset;
+ for (i=0; i < nseg; i++)
+ smal_decode_segment (seg+i, holes);
+ if (holes) fill_holes (holes);
+}
+
+/* RESTRICTED code starts here */
+
+void CLASS foveon_decoder (unsigned size, unsigned code)
+{
+ static unsigned huff[1024];
+ struct decode *cur;
+ int i, len;
+
+ if (!code) {
+ for (i=0; i < size; i++)
+ huff[i] = get4();
+ init_decoder();
+ }
+ cur = free_decode++;
+ if (free_decode > first_decode+2048) {
+ fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+ longjmp (failure, 2);
+ }
+ if (code)
+ for (i=0; i < size; i++)
+ if (huff[i] == code) {
+ cur->leaf = i;
+ return;
+ }
+ if ((len = code >> 27) > 26) return;
+ code = (len+1) << 27 | (code & 0x3ffffff) << 1;
+
+ cur->branch[0] = free_decode;
+ foveon_decoder (size, code);
+ cur->branch[1] = free_decode;
+ foveon_decoder (size, code+1);
+}
+
+void CLASS foveon_thumb (FILE *tfp)
+{
+ unsigned bwide, row, col, bitbuf=0, bit=1, c, i;
+ char *buf;
+ struct decode *dindex;
+ short pred[3];
+
+ bwide = get4();
+ fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ if (bwide > 0) {
+ if (bwide < thumb_width*3) return;
+ buf = (char *) malloc (bwide);
+ merror (buf, "foveon_thumb()");
+ for (row=0; row < thumb_height; row++) {
+ fread (buf, 1, bwide, ifp);
+ fwrite (buf, 3, thumb_width, tfp);
+ }
+ free (buf);
+ return;
+ }
+ foveon_decoder (256, 0);
+
+ for (row=0; row < thumb_height; row++) {
+ memset (pred, 0, sizeof pred);
+ if (!bit) get4();
+ for (bit=col=0; col < thumb_width; col++)
+ FORC3 {
+ for (dindex=first_decode; dindex->branch[0]; ) {
+ if ((bit = (bit-1) & 31) == 31)
+ for (i=0; i < 4; i++)
+ bitbuf = (bitbuf << 8) + fgetc(ifp);
+ dindex = dindex->branch[bitbuf >> bit & 1];
+ }
+ pred[c] += dindex->leaf;
+ fputc (pred[c], tfp);
+ }
+ }
+}
+
+void CLASS foveon_load_camf()
+{
+ unsigned key, i, val;
+
+ fseek (ifp, meta_offset, SEEK_SET);
+ key = get4();
+ fread (meta_data, 1, meta_length, ifp);
+ for (i=0; i < meta_length; i++) {
+ key = (key * 1597 + 51749) % 244944;
+ val = key * (INT64) 301593171 >> 24;
+ meta_data[i] ^= ((((key << 8) - val) >> 1) + val) >> 17;
+ }
+}
+
+void CLASS foveon_load_raw()
+{
+ struct decode *dindex;
+ short diff[1024];
+ unsigned bitbuf=0;
+ int pred[3], fixed, row, col, bit=-1, c, i;
+
+ fixed = get4();
+ read_shorts ((ushort *) diff, 1024);
+ if (!fixed) foveon_decoder (1024, 0);
+
+ for (row=0; row < height; row++) {
+ memset (pred, 0, sizeof pred);
+ if (!bit && !fixed && atoi(model+2) < 14) get4();
+ for (col=bit=0; col < width; col++) {
+ if (fixed) {
+ bitbuf = get4();
+ FORC3 pred[2-c] += diff[bitbuf >> c*10 & 0x3ff];
+ }
+ else FORC3 {
+ for (dindex=first_decode; dindex->branch[0]; ) {
+ if ((bit = (bit-1) & 31) == 31)
+ for (i=0; i < 4; i++)
+ bitbuf = (bitbuf << 8) + fgetc(ifp);
+ dindex = dindex->branch[bitbuf >> bit & 1];
+ }
+ pred[c] += diff[dindex->leaf];
+ if (pred[c] >> 16 && ~pred[c] >> 16) derror();
+ }
+ FORC3 image[row*width+col][c] = pred[c];
+ }
+ }
+ if (document_mode)
+ for (i=0; i < height*width*4; i++)
+ if ((short) image[0][i] < 0) image[0][i] = 0;
+ foveon_load_camf();
+}
+
+const char * CLASS foveon_camf_param (const char *block, const char *param)
+{
+ unsigned idx, num;
+ char *pos, *cp, *dp;
+
+ for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+ pos = meta_data + idx;
+ if (strncmp (pos, "CMb", 3)) break;
+ if (pos[3] != 'P') continue;
+ if (strcmp (block, pos+sget4(pos+12))) continue;
+ cp = pos + sget4(pos+16);
+ num = sget4(cp);
+ dp = pos + sget4(cp+4);
+ while (num--) {
+ cp += 8;
+ if (!strcmp (param, dp+sget4(cp)))
+ return dp+sget4(cp+4);
+ }
+ }
+ return 0;
+}
+
+void * CLASS foveon_camf_matrix (unsigned dim[3], const char *name)
+{
+ unsigned i, idx, type, ndim, size, *mat;
+ char *pos, *cp, *dp;
+ double dsize;
+
+ for (idx=0; idx < meta_length; idx += sget4(pos+8)) {
+ pos = meta_data + idx;
+ if (strncmp (pos, "CMb", 3)) break;
+ if (pos[3] != 'M') continue;
+ if (strcmp (name, pos+sget4(pos+12))) continue;
+ dim[0] = dim[1] = dim[2] = 1;
+ cp = pos + sget4(pos+16);
+ type = sget4(cp);
+ if ((ndim = sget4(cp+4)) > 3) break;
+ dp = pos + sget4(cp+8);
+ for (i=ndim; i--; ) {
+ cp += 12;
+ dim[i] = sget4(cp);
+ }
+ if ((dsize = (double) dim[0]*dim[1]*dim[2]) > meta_length/4) break;
+ mat = (unsigned *) malloc ((size = dsize) * 4);
+ merror (mat, "foveon_camf_matrix()");
+ for (i=0; i < size; i++)
+ if (type && type != 6)
+ mat[i] = sget4(dp + i*4);
+ else
+ mat[i] = sget4(dp + i*2) & 0xffff;
+ return mat;
+ }
+ fprintf (stderr,_("%s: \"%s\" matrix not found!\n"), ifname, name);
+ return 0;
+}
+
+int CLASS foveon_fixed (void *ptr, int size, const char *name)
+{
+ void *dp;
+ unsigned dim[3];
+
+ dp = foveon_camf_matrix (dim, name);
+ if (!dp) return 0;
+ memcpy (ptr, dp, size*4);
+ free (dp);
+ return 1;
+}
+
+float CLASS foveon_avg (short *pix, int range[2], float cfilt)
+{
+ int i;
+ float val, min=FLT_MAX, max=-FLT_MAX, sum=0;
+
+ for (i=range[0]; i <= range[1]; i++) {
+ sum += val = pix[i*4] + (pix[i*4]-pix[(i-1)*4]) * cfilt;
+ if (min > val) min = val;
+ if (max < val) max = val;
+ }
+ if (range[1] - range[0] == 1) return sum/2;
+ return (sum - min - max) / (range[1] - range[0] - 1);
+}
+
+short * CLASS foveon_make_curve (double max, double mul, double filt)
+{
+ short *curve;
+ unsigned i, size;
+ double x;
+
+ if (!filt) filt = 0.8;
+ size = 4*M_PI*max / filt;
+ if (size == UINT_MAX) size--;
+ curve = (short *) calloc (size+1, sizeof *curve);
+ merror (curve, "foveon_make_curve()");
+ curve[0] = size;
+ for (i=0; i < size; i++) {
+ x = i*filt/max/4;
+ curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5;
+ }
+ return curve;
+}
+
+void CLASS foveon_make_curves
+ (short **curvep, float dq[3], float div[3], float filt)
+{
+ double mul[3], max=0;
+ int c;
+
+ FORC3 mul[c] = dq[c]/div[c];
+ FORC3 if (max < mul[c]) max = mul[c];
+ FORC3 curvep[c] = foveon_make_curve (max, mul[c], filt);
+}
+
+int CLASS foveon_apply_curve (short *curve, int i)
+{
+ if (abs(i) >= curve[0]) return 0;
+ return i < 0 ? -curve[1-i] : curve[1+i];
+}
+
+#define image ((short (*)[4]) image)
+
+void CLASS foveon_interpolate()
+{
+ static const short hood[] = { -1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0, 1,1 };
+ short *pix, prev[3], *curve[8], (*shrink)[3];
+ float cfilt=0, ddft[3][3][2], ppm[3][3][3];
+ float cam_xyz[3][3], correct[3][3], last[3][3], trans[3][3];
+ float chroma_dq[3], color_dq[3], diag[3][3], div[3];
+ float (*black)[3], (*sgain)[3], (*sgrow)[3];
+ float fsum[3], val, frow, num;
+ int row, col, c, i, j, diff, sgx, irow, sum, min, max, limit;
+ int dscr[2][2], dstb[4], (*smrow[7])[3], total[4], ipix[3];
+ int work[3][3], smlast, smred, smred_p=0, dev[3];
+ int satlev[3], keep[4], active[4];
+ unsigned dim[3], *badpix;
+ double dsum=0, trsum[3];
+ char str[128];
+ const char* cp;
+
+ if (verbose)
+ fprintf (stderr,_("Foveon interpolation...\n"));
+
+ foveon_fixed (dscr, 4, "DarkShieldColRange");
+ foveon_fixed (ppm[0][0], 27, "PostPolyMatrix");
+ foveon_fixed (satlev, 3, "SaturationLevel");
+ foveon_fixed (keep, 4, "KeepImageArea");
+ foveon_fixed (active, 4, "ActiveImageArea");
+ foveon_fixed (chroma_dq, 3, "ChromaDQ");
+ foveon_fixed (color_dq, 3,
+ foveon_camf_param ("IncludeBlocks", "ColorDQ") ?
+ "ColorDQ" : "ColorDQCamRGB");
+ if (foveon_camf_param ("IncludeBlocks", "ColumnFilter"))
+ foveon_fixed (&cfilt, 1, "ColumnFilter");
+
+ memset (ddft, 0, sizeof ddft);
+ if (!foveon_camf_param ("IncludeBlocks", "DarkDrift")
+ || !foveon_fixed (ddft[1][0], 12, "DarkDrift"))
+ for (i=0; i < 2; i++) {
+ foveon_fixed (dstb, 4, i ? "DarkShieldBottom":"DarkShieldTop");
+ for (row = dstb[1]; row <= dstb[3]; row++)
+ for (col = dstb[0]; col <= dstb[2]; col++)
+ FORC3 ddft[i+1][c][1] += (short) image[row*width+col][c];
+ FORC3 ddft[i+1][c][1] /= (dstb[3]-dstb[1]+1) * (dstb[2]-dstb[0]+1);
+ }
+
+ if (!(cp = foveon_camf_param ("WhiteBalanceIlluminants", model2)))
+ { fprintf (stderr,_("%s: Invalid white balance \"%s\"\n"), ifname, model2);
+ return; }
+ foveon_fixed (cam_xyz, 9, cp);
+ foveon_fixed (correct, 9,
+ foveon_camf_param ("WhiteBalanceCorrections", model2));
+ memset (last, 0, sizeof last);
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++)
+ FORC3 last[i][j] += correct[i][c] * cam_xyz[c][j];
+
+ #define LAST(x,y) last[(i+x)%3][(c+y)%3]
+ for (i=0; i < 3; i++)
+ FORC3 diag[c][i] = LAST(1,1)*LAST(2,2) - LAST(1,2)*LAST(2,1);
+ #undef LAST
+ FORC3 div[c] = diag[c][0]*0.3127 + diag[c][1]*0.329 + diag[c][2]*0.3583;
+ sprintf (str, "%sRGBNeutral", model2);
+ if (foveon_camf_param ("IncludeBlocks", str))
+ foveon_fixed (div, 3, str);
+ num = 0;
+ FORC3 if (num < div[c]) num = div[c];
+ FORC3 div[c] /= num;
+
+ memset (trans, 0, sizeof trans);
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++)
+ FORC3 trans[i][j] += rgb_cam[i][c] * last[c][j] * div[j];
+ FORC3 trsum[c] = trans[c][0] + trans[c][1] + trans[c][2];
+ dsum = (6*trsum[0] + 11*trsum[1] + 3*trsum[2]) / 20;
+ for (i=0; i < 3; i++)
+ FORC3 last[i][c] = trans[i][c] * dsum / trsum[i];
+ memset (trans, 0, sizeof trans);
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++)
+ FORC3 trans[i][j] += (i==c ? 32 : -1) * last[c][j] / 30;
+
+ foveon_make_curves (curve, color_dq, div, cfilt);
+ FORC3 chroma_dq[c] /= 3;
+ foveon_make_curves (curve+3, chroma_dq, div, cfilt);
+ FORC3 dsum += chroma_dq[c] / div[c];
+ curve[6] = foveon_make_curve (dsum, dsum, cfilt);
+ curve[7] = foveon_make_curve (dsum*2, dsum*2, cfilt);
+
+ sgain = (float (*)[3]) foveon_camf_matrix (dim, "SpatialGain");
+ if (!sgain) return;
+ sgrow = (float (*)[3]) calloc (dim[1], sizeof *sgrow);
+ sgx = (width + dim[1]-2) / (dim[1]-1);
+
+ black = (float (*)[3]) calloc (height, sizeof *black);
+ for (row=0; row < height; row++) {
+ for (i=0; i < 6; i++)
+ ddft[0][0][i] = ddft[1][0][i] +
+ row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+ FORC3 black[row][c] =
+ ( foveon_avg (image[row*width]+c, dscr[0], cfilt) +
+ foveon_avg (image[row*width]+c, dscr[1], cfilt) * 3
+ - ddft[0][c][0] ) / 4 - ddft[0][c][1];
+ }
+ memcpy (black, black+8, sizeof *black*8);
+ memcpy (black+height-11, black+height-22, 11*sizeof *black);
+ memcpy (last, black, sizeof last);
+
+ for (row=1; row < height-1; row++) {
+ FORC3 if (last[1][c] > last[0][c]) {
+ if (last[1][c] > last[2][c])
+ black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c];
+ } else
+ if (last[1][c] < last[2][c])
+ black[row][c] = (last[0][c] < last[2][c]) ? last[0][c]:last[2][c];
+ memmove (last, last+1, 2*sizeof last[0]);
+ memcpy (last[2], black[row+1], sizeof last[2]);
+ }
+ FORC3 black[row][c] = (last[0][c] + last[1][c])/2;
+ FORC3 black[0][c] = (black[1][c] + black[3][c])/2;
+
+ val = 1 - exp(-1/24.0);
+ memcpy (fsum, black, sizeof fsum);
+ for (row=1; row < height; row++)
+ FORC3 fsum[c] += black[row][c] =
+ (black[row][c] - black[row-1][c])*val + black[row-1][c];
+ memcpy (last[0], black[height-1], sizeof last[0]);
+ FORC3 fsum[c] /= height;
+ for (row = height; row--; )
+ FORC3 last[0][c] = black[row][c] =
+ (black[row][c] - fsum[c] - last[0][c])*val + last[0][c];
+
+ memset (total, 0, sizeof total);
+ for (row=2; row < height; row+=4)
+ for (col=2; col < width; col+=4) {
+ FORC3 total[c] += (short) image[row*width+col][c];
+ total[3]++;
+ }
+ for (row=0; row < height; row++)
+ FORC3 black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0);
+
+ for (row=0; row < height; row++) {
+ for (i=0; i < 6; i++)
+ ddft[0][0][i] = ddft[1][0][i] +
+ row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]);
+ pix = image[row*width];
+ memcpy (prev, pix, sizeof prev);
+ frow = row / (height-1.0) * (dim[2]-1);
+ if ((irow = frow) == dim[2]-1) irow--;
+ frow -= irow;
+ for (i=0; i < dim[1]; i++)
+ FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) +
+ sgain[(irow+1)*dim[1]+i][c] * frow;
+ for (col=0; col < width; col++) {
+ FORC3 {
+ diff = pix[c] - prev[c];
+ prev[c] = pix[c];
+ ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt
+ - ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5)
+ - black[row][c] );
+ }
+ FORC3 {
+ work[0][c] = ipix[c] * ipix[c] >> 14;
+ work[2][c] = ipix[c] * work[0][c] >> 14;
+ work[1][2-c] = ipix[(c+1) % 3] * ipix[(c+2) % 3] >> 14;
+ }
+ FORC3 {
+ for (val=i=0; i < 3; i++)
+ for ( j=0; j < 3; j++)
+ val += ppm[c][i][j] * work[i][j];
+ ipix[c] = floor ((ipix[c] + floor(val)) *
+ ( sgrow[col/sgx ][c] * (sgx - col%sgx) +
+ sgrow[col/sgx+1][c] * (col%sgx) ) / sgx / div[c]);
+ if (ipix[c] > 32000) ipix[c] = 32000;
+ pix[c] = ipix[c];
+ }
+ pix += 4;
+ }
+ }
+ free (black);
+ free (sgrow);
+ free (sgain);
+
+ if ((badpix = (unsigned int *) foveon_camf_matrix (dim, "BadPixels"))) {
+ for (i=0; i < dim[0]; i++) {
+ col = (badpix[i] >> 8 & 0xfff) - keep[0];
+ row = (badpix[i] >> 20 ) - keep[1];
+ if ((unsigned)(row-1) > height-3 || (unsigned)(col-1) > width-3)
+ continue;
+ memset (fsum, 0, sizeof fsum);
+ for (sum=j=0; j < 8; j++)
+ if (badpix[i] & (1 << j)) {
+ FORC3 fsum[c] += (short)
+ image[(row+hood[j*2])*width+col+hood[j*2+1]][c];
+ sum++;
+ }
+ if (sum) FORC3 image[row*width+col][c] = fsum[c]/sum;
+ }
+ free (badpix);
+ }
+
+ /* Array for 5x5 Gaussian averaging of red values */
+ smrow[6] = (int (*)[3]) calloc (width*5, sizeof **smrow);
+ merror (smrow[6], "foveon_interpolate()");
+ for (i=0; i < 5; i++)
+ smrow[i] = smrow[6] + i*width;
+
+ /* Sharpen the reds against these Gaussian averages */
+ for (smlast=-1, row=2; row < height-2; row++) {
+ while (smlast < row+2) {
+ for (i=0; i < 6; i++)
+ smrow[(i+5) % 6] = smrow[i];
+ pix = image[++smlast*width+2];
+ for (col=2; col < width-2; col++) {
+ smrow[4][col][0] =
+ (pix[0]*6 + (pix[-4]+pix[4])*4 + pix[-8]+pix[8] + 8) >> 4;
+ pix += 4;
+ }
+ }
+ pix = image[row*width+2];
+ for (col=2; col < width-2; col++) {
+ smred = ( 6 * smrow[2][col][0]
+ + 4 * (smrow[1][col][0] + smrow[3][col][0])
+ + smrow[0][col][0] + smrow[4][col][0] + 8 ) >> 4;
+ if (col == 2)
+ smred_p = smred;
+ i = pix[0] + ((pix[0] - ((smred*7 + smred_p) >> 3)) >> 3);
+ if (i > 32000) i = 32000;
+ pix[0] = i;
+ smred_p = smred;
+ pix += 4;
+ }
+ }
+
+ /* Adjust the brighter pixels for better linearity */
+ min = 0xffff;
+ FORC3 {
+ i = satlev[c] / div[c];
+ if (min > i) min = i;
+ }
+ limit = min * 9 >> 4;
+ for (pix=image[0]; pix < image[height*width]; pix+=4) {
+ if (pix[0] <= limit || pix[1] <= limit || pix[2] <= limit)
+ continue;
+ min = max = pix[0];
+ for (c=1; c < 3; c++) {
+ if (min > pix[c]) min = pix[c];
+ if (max < pix[c]) max = pix[c];
+ }
+ if (min >= limit*2) {
+ pix[0] = pix[1] = pix[2] = max;
+ } else {
+ i = 0x4000 - ((min - limit) << 14) / limit;
+ i = 0x4000 - (i*i >> 14);
+ i = i*i >> 14;
+ FORC3 pix[c] += (max - pix[c]) * i >> 14;
+ }
+ }
+/*
+ Because photons that miss one detector often hit another,
+ the sum R+G+B is much less noisy than the individual colors.
+ So smooth the hues without smoothing the total.
+ */
+ for (smlast=-1, row=2; row < height-2; row++) {
+ while (smlast < row+2) {
+ for (i=0; i < 6; i++)
+ smrow[(i+5) % 6] = smrow[i];
+ pix = image[++smlast*width+2];
+ for (col=2; col < width-2; col++) {
+ FORC3 smrow[4][col][c] = (pix[c-4]+2*pix[c]+pix[c+4]+2) >> 2;
+ pix += 4;
+ }
+ }
+ pix = image[row*width+2];
+ for (col=2; col < width-2; col++) {
+ FORC3 dev[c] = -foveon_apply_curve (curve[7], pix[c] -
+ ((smrow[1][col][c] + 2*smrow[2][col][c] + smrow[3][col][c]) >> 2));
+ sum = (dev[0] + dev[1] + dev[2]) >> 3;
+ FORC3 pix[c] += dev[c] - sum;
+ pix += 4;
+ }
+ }
+ for (smlast=-1, row=2; row < height-2; row++) {
+ while (smlast < row+2) {
+ for (i=0; i < 6; i++)
+ smrow[(i+5) % 6] = smrow[i];
+ pix = image[++smlast*width+2];
+ for (col=2; col < width-2; col++) {
+ FORC3 smrow[4][col][c] =
+ (pix[c-8]+pix[c-4]+pix[c]+pix[c+4]+pix[c+8]+2) >> 2;
+ pix += 4;
+ }
+ }
+ pix = image[row*width+2];
+ for (col=2; col < width-2; col++) {
+ for (total[3]=375, sum=60, c=0; c < 3; c++) {
+ for (total[c]=i=0; i < 5; i++)
+ total[c] += smrow[i][col][c];
+ total[3] += total[c];
+ sum += pix[c];
+ }
+ if (sum < 0) sum = 0;
+ j = total[3] > 375 ? (sum << 16) / total[3] : sum * 174;
+ FORC3 pix[c] += foveon_apply_curve (curve[6],
+ ((j*total[c] + 0x8000) >> 16) - pix[c]);
+ pix += 4;
+ }
+ }
+
+ /* Transform the image to a different colorspace */
+ for (pix=image[0]; pix < image[height*width]; pix+=4) {
+ FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]);
+ sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2;
+ FORC3 pix[c] -= foveon_apply_curve (curve[c], pix[c]-sum);
+ FORC3 {
+ for (dsum=i=0; i < 3; i++)
+ dsum += trans[c][i] * pix[i];
+ if (dsum < 0) dsum = 0;
+ if (dsum > 24000) dsum = 24000;
+ ipix[c] = dsum + 0.5;
+ }
+ FORC3 pix[c] = ipix[c];
+ }
+
+ /* Smooth the image bottom-to-top and save at 1/4 scale */
+ shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *shrink);
+ merror (shrink, "foveon_interpolate()");
+ for (row = height/4; row--; )
+ for (col=0; col < width/4; col++) {
+ ipix[0] = ipix[1] = ipix[2] = 0;
+ for (i=0; i < 4; i++)
+ for (j=0; j < 4; j++)
+ FORC3 ipix[c] += image[(row*4+i)*width+col*4+j][c];
+ FORC3
+ if (row+2 > height/4)
+ shrink[row*(width/4)+col][c] = ipix[c] >> 4;
+ else
+ shrink[row*(width/4)+col][c] =
+ (shrink[(row+1)*(width/4)+col][c]*1840 + ipix[c]*141 + 2048) >> 12;
+ }
+ /* From the 1/4-scale image, smooth right-to-left */
+ for (row=0; row < (height & ~3); row++) {
+ ipix[0] = ipix[1] = ipix[2] = 0;
+ if ((row & 3) == 0)
+ for (col = width & ~3 ; col--; )
+ FORC3 smrow[0][col][c] = ipix[c] =
+ (shrink[(row/4)*(width/4)+col/4][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+ /* Then smooth left-to-right */
+ ipix[0] = ipix[1] = ipix[2] = 0;
+ for (col=0; col < (width & ~3); col++)
+ FORC3 smrow[1][col][c] = ipix[c] =
+ (smrow[0][col][c]*1485 + ipix[c]*6707 + 4096) >> 13;
+
+ /* Smooth top-to-bottom */
+ if (row == 0)
+ memcpy (smrow[2], smrow[1], sizeof **smrow * width);
+ else
+ for (col=0; col < (width & ~3); col++)
+ FORC3 smrow[2][col][c] =
+ (smrow[2][col][c]*6707 + smrow[1][col][c]*1485 + 4096) >> 13;
+
+ /* Adjust the chroma toward the smooth values */
+ for (col=0; col < (width & ~3); col++) {
+ for (i=j=30, c=0; c < 3; c++) {
+ i += smrow[2][col][c];
+ j += image[row*width+col][c];
+ }
+ j = (j << 16) / i;
+ for (sum=c=0; c < 3; c++) {
+ ipix[c] = foveon_apply_curve (curve[c+3],
+ ((smrow[2][col][c] * j + 0x8000) >> 16) - image[row*width+col][c]);
+ sum += ipix[c];
+ }
+ sum >>= 3;
+ FORC3 {
+ i = image[row*width+col][c] + ipix[c] - sum;
+ if (i < 0) i = 0;
+ image[row*width+col][c] = i;
+ }
+ }
+ }
+ free (shrink);
+ free (smrow[6]);
+ for (i=0; i < 8; i++)
+ free (curve[i]);
+
+ /* Trim off the black border */
+ active[1] -= keep[1];
+ active[3] -= 2;
+ i = active[2] - active[0];
+ for (row=0; row < active[3]-active[1]; row++)
+ memcpy (image[row*i], image[(row+active[1])*width+active[0]],
+ i * sizeof *image);
+ width = i;
+ height = row;
+}
+#undef image
+
+/* RESTRICTED code ends here */
+
+/*
+ Seach from the current directory up to the root looking for
+ a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (char *fname)
+{
+ FILE *fp=0;
+ char *cp, line[128];
+ int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+ if (!filters) return;
+ if (fname)
+ fp = fopen (fname, "r");
+ else {
+ for (len=32 ; ; len *= 2) {
+ fname = (char *) malloc (len);
+ if (!fname) return;
+ if (getcwd (fname, len-16)) break;
+ free (fname);
+ if (errno != ERANGE) return;
+ }
+#if defined(WIN32) || defined(DJGPP)
+ if (fname[1] == ':')
+ memmove (fname, fname+2, len-2);
+ for (cp=fname; *cp; cp++)
+ if (*cp == '\\') *cp = '/';
+#endif
+ cp = fname + strlen(fname);
+ if (cp[-1] == '/') cp--;
+ while (*fname == '/') {
+ strcpy (cp, "/.badpixels");
+ if ((fp = fopen (fname, "r"))) break;
+ if (cp == fname) break;
+ while (*--cp != '/');
+ }
+ free (fname);
+ }
+ if (!fp) return;
+ while (fgets (line, 128, fp)) {
+ cp = strchr (line, '#');
+ if (cp) *cp = 0;
+ if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+ if ((unsigned) col >= width || (unsigned) row >= height) continue;
+ if (time > timestamp) continue;
+ for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+ for (r = row-rad; r <= row+rad; r++)
+ for (c = col-rad; c <= col+rad; c++)
+ if ((unsigned) r < height && (unsigned) c < width &&
+ (r != row || c != col) && fc(r,c) == fc(row,col)) {
+ tot += BAYER2(r,c);
+ n++;
+ }
+ BAYER2(row,col) = tot/n;
+ if (verbose) {
+ if (!fixed++)
+ fprintf (stderr,_("Fixed dead pixels at:"));
+ fprintf (stderr, " %d,%d", col, row);
+ }
+ }
+ if (fixed) fputc ('\n', stderr);
+ fclose (fp);
+}
+
+void CLASS subtract (char *fname)
+{
+ FILE *fp;
+ int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+ ushort *pixel;
+
+ if (!(fp = fopen (fname, "rb"))) {
+ perror (fname); return;
+ }
+ if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+ while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+ if (c == '#') comment = 1;
+ if (c == '\n') comment = 0;
+ if (comment) continue;
+ if (isdigit(c)) number = 1;
+ if (number) {
+ if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+ else if (isspace(c)) {
+ number = 0; nd++;
+ } else error = 1;
+ }
+ }
+ if (error || nd < 3) {
+ fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+ fclose (fp); return;
+ } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+ fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+ fclose (fp); return;
+ }
+ pixel = (ushort *) calloc (width, sizeof *pixel);
+ merror (pixel, "subtract()");
+ for (row=0; row < height; row++) {
+ fread (pixel, 2, width, fp);
+ for (col=0; col < width; col++)
+ BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+ }
+ free (pixel);
+ black = 0;
+}
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+ double work[3][6], num;
+ int i, j, k;
+
+ for (i=0; i < 3; i++) {
+ for (j=0; j < 6; j++)
+ work[i][j] = j == i+3;
+ for (j=0; j < 3; j++)
+ for (k=0; k < size; k++)
+ work[i][j] += in[k][i] * in[k][j];
+ }
+ for (i=0; i < 3; i++) {
+ num = work[i][i];
+ for (j=0; j < 6; j++)
+ work[i][j] /= num;
+ for (k=0; k < 3; k++) {
+ if (k==i) continue;
+ num = work[k][i];
+ for (j=0; j < 6; j++)
+ work[k][j] -= work[i][j] * num;
+ }
+ }
+ for (i=0; i < size; i++)
+ for (j=0; j < 3; j++)
+ for (out[i][j]=k=0; k < 3; k++)
+ out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+ double cam_rgb[4][3], inverse[4][3], num;
+ int i, j, k;
+
+ for (i=0; i < colors; i++) /* Multiply out XYZ colorspace */
+ for (j=0; j < 3; j++)
+ for (cam_rgb[i][j] = k=0; k < 3; k++)
+ cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+ for (i=0; i < colors; i++) { /* Normalize cam_rgb so that */
+ for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
+ num += cam_rgb[i][j];
+ for (j=0; j < 3; j++)
+ cam_rgb[i][j] /= num;
+ pre_mul[i] = 1 / num;
+ }
+ pseudoinverse (cam_rgb, inverse, colors);
+ for (raw_color = i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ rgb_cam[i][j] = inverse[j][i];
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+ static const int cut[NSQ][4] = {
+ { 241, 231, 234, 274 },
+ { 251, 235, 534, 274 },
+ { 255, 239, 838, 272 },
+ { 255, 240, 1146, 274 },
+ { 251, 237, 1452, 278 },
+ { 243, 238, 1758, 288 },
+ { 253, 253, 218, 558 },
+ { 255, 249, 524, 562 },
+ { 261, 253, 830, 562 },
+ { 260, 255, 1144, 564 },
+ { 261, 255, 1450, 566 },
+ { 247, 247, 1764, 576 },
+ { 255, 251, 212, 862 },
+ { 259, 259, 518, 862 },
+ { 263, 261, 826, 864 },
+ { 265, 263, 1138, 866 },
+ { 265, 257, 1450, 872 },
+ { 257, 255, 1762, 874 },
+ { 257, 253, 212, 1164 },
+ { 262, 251, 516, 1172 },
+ { 263, 257, 826, 1172 },
+ { 263, 255, 1136, 1176 },
+ { 255, 252, 1452, 1182 },
+ { 257, 253, 1760, 1180 } };
+// ColorChecker Chart under 6500-kelvin illumination
+ static const double gmb_xyY[NSQ][3] = {
+ { 0.400, 0.350, 10.1 }, // Dark Skin
+ { 0.377, 0.345, 35.8 }, // Light Skin
+ { 0.247, 0.251, 19.3 }, // Blue Sky
+ { 0.337, 0.422, 13.3 }, // Foliage
+ { 0.265, 0.240, 24.3 }, // Blue Flower
+ { 0.261, 0.343, 43.1 }, // Bluish Green
+ { 0.506, 0.407, 30.1 }, // Orange
+ { 0.211, 0.175, 12.0 }, // Purplish Blue
+ { 0.453, 0.306, 19.8 }, // Moderate Red
+ { 0.285, 0.202, 6.6 }, // Purple
+ { 0.380, 0.489, 44.3 }, // Yellow Green
+ { 0.473, 0.438, 43.1 }, // Orange Yellow
+ { 0.187, 0.129, 6.1 }, // Blue
+ { 0.305, 0.478, 23.4 }, // Green
+ { 0.539, 0.313, 12.0 }, // Red
+ { 0.448, 0.470, 59.1 }, // Yellow
+ { 0.364, 0.233, 19.8 }, // Magenta
+ { 0.196, 0.252, 19.8 }, // Cyan
+ { 0.310, 0.316, 90.0 }, // White
+ { 0.310, 0.316, 59.1 }, // Neutral 8
+ { 0.310, 0.316, 36.2 }, // Neutral 6.5
+ { 0.310, 0.316, 19.8 }, // Neutral 5
+ { 0.310, 0.316, 9.0 }, // Neutral 3.5
+ { 0.310, 0.316, 3.1 } }; // Black
+ double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+ double inverse[NSQ][3], cam_xyz[4][3], num;
+ int c, i, j, k, sq, row, col, count[4];
+
+ memset (gmb_cam, 0, sizeof gmb_cam);
+ for (sq=0; sq < NSQ; sq++) {
+ FORCC count[c] = 0;
+ for (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+ for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+ c = FC(row,col);
+ if (c >= colors) c -= 2;
+ gmb_cam[sq][c] += BAYER(row,col);
+ count[c]++;
+ }
+ FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+ gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+ gmb_xyz[sq][1] = gmb_xyY[sq][2];
+ gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+ (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+ }
+ pseudoinverse (gmb_xyz, inverse, NSQ);
+ for (i=0; i < colors; i++)
+ for (j=0; j < 3; j++)
+ for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+ cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+ cam_xyz_coeff (cam_xyz);
+ if (verbose) {
+ printf (" { \"%s %s\", %d,\n\t{", make, model, black);
+ num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+ FORCC for (j=0; j < 3; j++)
+ printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+ puts (" } },");
+ }
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+ int i;
+ for (i=0; i < sc; i++)
+ temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+ for (; i+sc < size; i++)
+ temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+ for (; i < size; i++)
+ temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+void CLASS wavelet_denoise()
+{
+ float *fimg=0, *temp, thold, mul[2], avg, diff;
+ int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+ ushort *window[4];
+ static const float noise[] =
+ { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+ if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+
+ while (maximum << scale < 0x10000) scale++;
+ maximum <<= --scale;
+ black <<= scale;
+ if ((size = iheight*iwidth) < 0x15550000)
+ fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+ merror (fimg, "wavelet_denoise()");
+ temp = fimg + size*3;
+ if ((nc = colors) == 3 && filters) nc++;
+ FORC(nc) { /* denoise R,G1,B,G3 individually */
+ for (i=0; i < size; i++)
+ fimg[i] = 256 * sqrt(image[i][c] << scale);
+ for (hpass=lev=0; lev < 5; lev++) {
+ lpass = size*((lev & 1)+1);
+ for (row=0; row < iheight; row++) {
+ hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+ for (col=0; col < iwidth; col++)
+ fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+ }
+ for (col=0; col < iwidth; col++) {
+ hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+ for (row=0; row < iheight; row++)
+ fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+ }
+ thold = threshold * noise[lev];
+ for (i=0; i < size; i++) {
+ fimg[hpass+i] -= fimg[lpass+i];
+ if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+ else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold;
+ else fimg[hpass+i] = 0;
+ if (hpass) fimg[i] += fimg[hpass+i];
+ }
+ hpass = lpass;
+ }
+ for (i=0; i < size; i++)
+ image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+ }
+ if (filters && colors == 3) { /* pull G1 and G3 closer together */
+ for (row=0; row < 2; row++)
+ mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+ for (i=0; i < 4; i++)
+ window[i] = (ushort *) fimg + width*i;
+ for (wlast=-1, row=1; row < height-1; row++) {
+ while (wlast < row+1) {
+ for (wlast++, i=0; i < 4; i++)
+ window[(i+3) & 3] = window[i];
+ for (col = FC(wlast,1) & 1; col < width; col+=2)
+ window[2][col] = BAYER(wlast,col);
+ }
+ thold = threshold/512;
+ for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+ avg = ( window[0][col-1] + window[0][col+1] +
+ window[2][col-1] + window[2][col+1] - black*4 )
+ * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+ avg = avg < 0 ? 0 : sqrt(avg);
+ diff = sqrt(BAYER(row,col)) - avg;
+ if (diff < -thold) diff += thold;
+ else if (diff > thold) diff -= thold;
+ else diff = 0;
+ BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+ }
+ }
+ }
+ free (fimg);
+}
+
+void CLASS scale_colors()
+{
+ unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+ int val, dark, sat;
+ double dsum[8], dmin, dmax;
+ float scale_mul[4], fr, fc;
+ ushort *img=0, *pix;
+
+ if (user_mul[0])
+ memcpy (pre_mul, user_mul, sizeof pre_mul);
+ if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+ memset (dsum, 0, sizeof dsum);
+ bottom = MIN (greybox[1]+greybox[3], height);
+ right = MIN (greybox[0]+greybox[2], width);
+ for (row=greybox[1]; row < bottom; row += 8)
+ for (col=greybox[0]; col < right; col += 8) {
+ memset (sum, 0, sizeof sum);
+ for (y=row; y < row+8 && y < bottom; y++)
+ for (x=col; x < col+8 && x < right; x++)
+ FORC4 {
+ if (filters) {
+ c = FC(y,x);
+ val = BAYER(y,x);
+ } else
+ val = image[y*width+x][c];
+ if (val > maximum-25) goto skip_block;
+ if ((val -= black) < 0) val = 0;
+ sum[c] += val;
+ sum[c+4]++;
+ if (filters) break;
+ }
+ FORC(8) dsum[c] += sum[c];
+skip_block: ;
+ }
+ FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+ }
+ if (use_camera_wb && cam_mul[0] != -1) {
+ memset (sum, 0, sizeof sum);
+ for (row=0; row < 8; row++)
+ for (col=0; col < 8; col++) {
+ c = FC(row,col);
+ if ((val = white[row][col] - black) > 0)
+ sum[c] += val;
+ sum[c+4]++;
+ }
+ if (sum[0] && sum[1] && sum[2] && sum[3])
+ FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+ else if (cam_mul[0] && cam_mul[2])
+ memcpy (pre_mul, cam_mul, sizeof pre_mul);
+ else
+ fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+ }
+ if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+ dark = black;
+ sat = maximum;
+ if (threshold) wavelet_denoise();
+ maximum -= black;
+ for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+ if (dmin > pre_mul[c])
+ dmin = pre_mul[c];
+ if (dmax < pre_mul[c])
+ dmax = pre_mul[c];
+ }
+ if (!highlight) dmax = dmin;
+ FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+ if (verbose) {
+ fprintf (stderr,
+ _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+ FORC4 fprintf (stderr, " %f", pre_mul[c]);
+ fputc ('\n', stderr);
+ }
+ size = iheight*iwidth;
+ for (i=0; i < size*4; i++) {
+ val = image[0][i];
+ if (!val) continue;
+ val -= black;
+ val *= scale_mul[i & 3];
+ image[0][i] = CLIP(val);
+ }
+ if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+ if (verbose)
+ fprintf (stderr,_("Correcting chromatic aberration...\n"));
+ for (c=0; c < 4; c+=2) {
+ if (aber[c] == 1) continue;
+ img = (ushort *) malloc (size * sizeof *img);
+ merror (img, "scale_colors()");
+ for (i=0; i < size; i++)
+ img[i] = image[i][c];
+ for (row=0; row < iheight; row++) {
+ ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+ if (ur > iheight-2) continue;
+ fr -= ur;
+ for (col=0; col < iwidth; col++) {
+ uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+ if (uc > iwidth-2) continue;
+ fc -= uc;
+ pix = img + ur*iwidth + uc;
+ image[row*iwidth+col][c] =
+ (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) +
+ (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+ }
+ }
+ free(img);
+ }
+ }
+}
+
+void CLASS pre_interpolate()
+{
+ ushort (*img)[4];
+ int row, col, c;
+
+ if (shrink) {
+ if (half_size) {
+ height = iheight;
+ width = iwidth;
+ } else {
+ img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+ merror (img, "pre_interpolate()");
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ c = fc(row,col);
+ img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+ }
+ free (image);
+ image = img;
+ shrink = 0;
+ }
+ }
+ if (filters && colors == 3) {
+ if ((mix_green = four_color_rgb)) colors++;
+ else {
+ for (row = FC(1,0) >> 1; row < height; row+=2)
+ for (col = FC(row,1) & 1; col < width; col+=2)
+ image[row*width+col][1] = image[row*width+col][3];
+ filters &= ~((filters & 0x55555555) << 1);
+ }
+ }
+ if (half_size) filters = 0;
+}
+
+void CLASS border_interpolate (int border)
+{
+ unsigned row, col, y, x, f, c, sum[8];
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ if (col==border && row >= border && row < height-border)
+ col = width-border;
+ memset (sum, 0, sizeof sum);
+ for (y=row-1; y != row+2; y++)
+ for (x=col-1; x != col+2; x++)
+ if (y < height && x < width) {
+ f = fc(y,x);
+ sum[f] += image[y*width+x][f];
+ sum[f+4]++;
+ }
+ f = fc(row,col);
+ FORCC if (c != f && sum[c+4])
+ image[row*width+col][c] = sum[c] / sum[c+4];
+ }
+}
+
+void CLASS lin_interpolate()
+{
+ int code[16][16][32], *ip, sum[4];
+ int c, i, x, y, row, col, shift, color;
+ ushort *pix;
+
+ if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+
+ border_interpolate(1);
+ for (row=0; row < 16; row++)
+ for (col=0; col < 16; col++) {
+ ip = code[row][col];
+ memset (sum, 0, sizeof sum);
+ for (y=-1; y <= 1; y++)
+ for (x=-1; x <= 1; x++) {
+ shift = (y==0) + (x==0);
+ if (shift == 2) continue;
+ color = fc(row+y,col+x);
+ *ip++ = (width*y + x)*4 + color;
+ *ip++ = shift;
+ *ip++ = color;
+ sum[color] += 1 << shift;
+ }
+ FORCC
+ if (c != fc(row,col)) {
+ *ip++ = c;
+ *ip++ = 256 / sum[c];
+ }
+ }
+ for (row=1; row < height-1; row++)
+ for (col=1; col < width-1; col++) {
+ pix = image[row*width+col];
+ ip = code[row & 15][col & 15];
+ memset (sum, 0, sizeof sum);
+ for (i=8; i--; ip+=3)
+ sum[ip[2]] += pix[ip[0]] << ip[1];
+ for (i=colors; --i; ip+=2)
+ pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+ }
+}
+
+/*
+ This algorithm is officially called:
+
+ "Interpolation using a Threshold-based variable number of gradients"
+
+ described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+ I've extended the basic idea to work with non-Bayer filter arrays.
+ Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+ static const signed char *cp, terms[] = {
+ -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+ -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+ -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+ -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+ -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+ -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+ -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+ -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+ -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+ -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+ -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+ -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+ -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+ +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+ +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+ +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+ +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+ +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+ +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+ +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+ +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+ +1,+0,+2,+1,0,0x10
+ }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+ ushort (*brow[5])[4], *pix;
+ int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+ int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+ int g, diff, thold, num, c;
+
+ lin_interpolate();
+ if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+
+ if (filters == 1) prow = pcol = 15;
+ ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+ merror (ip, "vng_interpolate()");
+ for (row=0; row <= prow; row++) /* Precalculate for VNG */
+ for (col=0; col <= pcol; col++) {
+ code[row][col] = ip;
+ for (cp=terms, t=0; t < 64; t++) {
+ y1 = *cp++; x1 = *cp++;
+ y2 = *cp++; x2 = *cp++;
+ weight = *cp++;
+ grads = *cp++;
+ color = fc(row+y1,col+x1);
+ if (fc(row+y2,col+x2) != color) continue;
+ diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+ if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+ *ip++ = (y1*width + x1)*4 + color;
+ *ip++ = (y2*width + x2)*4 + color;
+ *ip++ = weight;
+ for (g=0; g < 8; g++)
+ if (grads & 1<<g) *ip++ = g;
+ *ip++ = -1;
+ }
+ *ip++ = INT_MAX;
+ for (cp=chood, g=0; g < 8; g++) {
+ y = *cp++; x = *cp++;
+ *ip++ = (y*width + x) * 4;
+ color = fc(row,col);
+ if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+ *ip++ = (y*width + x) * 8 + color;
+ else
+ *ip++ = 0;
+ }
+ }
+ brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+ merror (brow[4], "vng_interpolate()");
+ for (row=0; row < 3; row++)
+ brow[row] = brow[4] + row*width;
+ for (row=2; row < height-2; row++) { /* Do VNG interpolation */
+ for (col=2; col < width-2; col++) {
+ pix = image[row*width+col];
+ ip = code[row & prow][col & pcol];
+ memset (gval, 0, sizeof gval);
+ while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
+ diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+ gval[ip[3]] += diff;
+ ip += 5;
+ if ((g = ip[-1]) == -1) continue;
+ gval[g] += diff;
+ while ((g = *ip++) != -1)
+ gval[g] += diff;
+ }
+ ip++;
+ gmin = gmax = gval[0]; /* Choose a threshold */
+ for (g=1; g < 8; g++) {
+ if (gmin > gval[g]) gmin = gval[g];
+ if (gmax < gval[g]) gmax = gval[g];
+ }
+ if (gmax == 0) {
+ memcpy (brow[2][col], pix, sizeof *image);
+ continue;
+ }
+ thold = gmin + (gmax >> 1);
+ memset (sum, 0, sizeof sum);
+ color = fc(row,col);
+ for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
+ if (gval[g] <= thold) {
+ FORCC
+ if (c == color && ip[1])
+ sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+ else
+ sum[c] += pix[ip[0] + c];
+ num++;
+ }
+ }
+ FORCC { /* Save to buffer */
+ t = pix[color];
+ if (c != color)
+ t += (sum[c] - sum[color]) / num;
+ brow[2][col][c] = CLIP(t);
+ }
+ }
+ if (row > 3) /* Write buffer to image */
+ memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+ for (g=0; g < 4; g++)
+ brow[(g-1) & 3] = brow[g];
+ }
+ memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+ memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+ free (brow[4]);
+ free (code[0][0]);
+}
+
+/*
+ Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+ int dir[5] = { 1, width, -1, -width, 1 };
+ int row, col, diff[2], guess[2], c, d, i;
+ ushort (*pix)[4];
+
+ border_interpolate(3);
+ if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+
+/* Fill in the green layer with gradients and pattern recognition: */
+ for (row=3; row < height-3; row++)
+ for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]) > 0; i++) {
+ guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+ - pix[-2*d][c] - pix[2*d][c];
+ diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+ ABS(pix[ 2*d][c] - pix[ 0][c]) +
+ ABS(pix[ -d][1] - pix[ d][1]) ) * 3 +
+ ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+ ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+ }
+ d = dir[i = diff[0] > diff[1]];
+ pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+ }
+/* Calculate red and blue for each green pixel: */
+ for (row=1; row < height-1; row++)
+ for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+ pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+ - pix[-d][1] - pix[d][1]) >> 1);
+ }
+/* Calculate blue for red pixels and vice versa: */
+ for (row=1; row < height-1; row++)
+ for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+ diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+ ABS(pix[-d][1] - pix[0][1]) +
+ ABS(pix[ d][1] - pix[0][1]);
+ guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+ - pix[-d][1] - pix[d][1];
+ }
+ if (diff[0] != diff[1])
+ pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+ else
+ pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+ }
+}
+
+/*
+ Adaptive Homogeneity-Directed interpolation is based on
+ the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256 /* Tile Size */
+
+void CLASS ahd_interpolate()
+{
+ int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+ ushort (*pix)[4], (*rix)[3];
+ static const int dir[4] = { -1, 1, -TS, TS };
+ unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+ float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+ ushort (*rgb)[TS][TS][3];
+ short (*lab)[TS][TS][3], (*lix)[3];
+ char (*homo)[TS][TS], *buffer;
+
+ if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+
+ for (i=0; i < 0x10000; i++) {
+ r = i / 65535.0;
+ cbrt[i] = r > 0.008856 ? pow(r,1/3.0) : 7.787*r + 16/116.0;
+ }
+ for (i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ for (xyz_cam[i][j] = k=0; k < 3; k++)
+ xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+ border_interpolate(5);
+ buffer = (char *) malloc (26*TS*TS); /* 1664 kB */
+ merror (buffer, "ahd_interpolate()");
+ rgb = (ushort(*)[TS][TS][3]) buffer;
+ lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+ homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
+
+ for (top=2; top < height-5; top += TS-6)
+ for (left=2; left < width-5; left += TS-6) {
+
+/* Interpolate green horizontally and vertically: */
+ for (row = top; row < top+TS && row < height-2; row++) {
+ col = left + (FC(row,left) & 1);
+ for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+ pix = image + row*width+col;
+ val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+ - pix[-2][c] - pix[2][c]) >> 2;
+ rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+ val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+ - pix[-2*width][c] - pix[2*width][c]) >> 2;
+ rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+ }
+ }
+/* Interpolate red and blue, and convert to CIELab: */
+ for (d=0; d < 2; d++)
+ for (row=top+1; row < top+TS-1 && row < height-3; row++)
+ for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+ pix = image + row*width+col;
+ rix = &rgb[d][row-top][col-left];
+ lix = &lab[d][row-top][col-left];
+ if ((c = 2 - FC(row,col)) == 1) {
+ c = FC(row+1,col);
+ val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+ - rix[-1][1] - rix[1][1] ) >> 1);
+ rix[0][2-c] = CLIP(val);
+ val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+ - rix[-TS][1] - rix[TS][1] ) >> 1);
+ } else
+ val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+ + pix[+width-1][c] + pix[+width+1][c]
+ - rix[-TS-1][1] - rix[-TS+1][1]
+ - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+ rix[0][c] = CLIP(val);
+ c = FC(row,col);
+ rix[0][c] = pix[0][c];
+ xyz[0] = xyz[1] = xyz[2] = 0.5;
+ FORCC {
+ xyz[0] += xyz_cam[0][c] * rix[0][c];
+ xyz[1] += xyz_cam[1][c] * rix[0][c];
+ xyz[2] += xyz_cam[2][c] * rix[0][c];
+ }
+ xyz[0] = cbrt[CLIP((int) xyz[0])];
+ xyz[1] = cbrt[CLIP((int) xyz[1])];
+ xyz[2] = cbrt[CLIP((int) xyz[2])];
+ lix[0][0] = 64 * (116 * xyz[1] - 16);
+ lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+ lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+ }
+/* Build homogeneity maps from the CIELab images: */
+ memset (homo, 0, 2*TS*TS);
+ for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+ tr = row-top;
+ for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+ tc = col-left;
+ for (d=0; d < 2; d++) {
+ lix = &lab[d][tr][tc];
+ for (i=0; i < 4; i++) {
+ ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+ abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+ + SQR(lix[0][2]-lix[dir[i]][2]);
+ }
+ }
+ leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+ MAX(ldiff[1][2],ldiff[1][3]));
+ abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+ MAX(abdiff[1][2],abdiff[1][3]));
+ for (d=0; d < 2; d++)
+ for (i=0; i < 4; i++)
+ if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+ homo[d][tr][tc]++;
+ }
+ }
+/* Combine the most homogenous pixels for the final result: */
+ for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+ tr = row-top;
+ for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+ tc = col-left;
+ for (d=0; d < 2; d++)
+ for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+ for (j=tc-1; j <= tc+1; j++)
+ hm[d] += homo[d][i][j];
+ if (hm[0] != hm[1])
+ FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+ else
+ FORC3 image[row*width+col][c] =
+ (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+ }
+ }
+ }
+ free (buffer);
+}
+#undef TS
+
+void CLASS median_filter()
+{
+ ushort (*pix)[4];
+ int pass, c, i, j, k, med[9];
+ static const uchar opt[] = /* Optimal 9-element median search */
+ { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+ 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+ for (pass=1; pass <= med_passes; pass++) {
+ if (verbose)
+ fprintf (stderr,_("Median filter pass %d...\n"), pass);
+ for (c=0; c < 3; c+=2) {
+ for (pix = image; pix < image+width*height; pix++)
+ pix[0][3] = pix[0][c];
+ for (pix = image+width; pix < image+width*(height-1); pix++) {
+ if ((pix-image+1) % width < 2) continue;
+ for (k=0, i = -width; i <= width; i += width)
+ for (j = i-1; j <= i+1; j++)
+ med[k++] = pix[j][3] - pix[j][1];
+ for (i=0; i < sizeof opt; i+=2)
+ if (med[opt[i]] > med[opt[i+1]])
+ SWAP (med[opt[i]] , med[opt[i+1]]);
+ pix[0][c] = CLIP(med[4] + pix[0][1]);
+ }
+ }
+ }
+}
+
+void CLASS blend_highlights()
+{
+ int clip=INT_MAX, row, col, c, i, j;
+ static const float trans[2][4][4] =
+ { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+ { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+ static const float itrans[2][4][4] =
+ { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+ { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+ float cam[2][4], lab[2][4], sum[2], chratio;
+
+ if ((unsigned) (colors-3) > 1) return;
+ if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+ FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ FORCC if (image[row*width+col][c] > clip) break;
+ if (c == colors) continue;
+ FORCC {
+ cam[0][c] = image[row*width+col][c];
+ cam[1][c] = MIN(cam[0][c],clip);
+ }
+ for (i=0; i < 2; i++) {
+ FORCC for (lab[i][c]=j=0; j < colors; j++)
+ lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+ for (sum[i]=0,c=1; c < colors; c++)
+ sum[i] += SQR(lab[i][c]);
+ }
+ chratio = sqrt(sum[1]/sum[0]);
+ for (c=1; c < colors; c++)
+ lab[0][c] *= chratio;
+ FORCC for (cam[0][c]=j=0; j < colors; j++)
+ cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+ FORCC image[row*width+col][c] = cam[0][c] / colors;
+ }
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+ float *map, sum, wgt, grow;
+ int hsat[4], count, spread, change, val, i;
+ unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+ ushort *pixel;
+ static const signed char dir[8][2] =
+ { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+ if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+
+ grow = pow (2, 4-highlight);
+ FORCC hsat[c] = 32000 * pre_mul[c];
+ for (kc=0, c=1; c < colors; c++)
+ if (pre_mul[kc] < pre_mul[c]) kc = c;
+ high = height / SCALE;
+ wide = width / SCALE;
+ map = (float *) calloc (high*wide, sizeof *map);
+ merror (map, "recover_highlights()");
+ FORCC if (c != kc) {
+ memset (map, 0, high*wide*sizeof *map);
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ sum = wgt = count = 0;
+ for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+ for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+ pixel = image[row*width+col];
+ if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+ sum += pixel[c];
+ wgt += pixel[kc];
+ count++;
+ }
+ }
+ if (count == SCALE*SCALE)
+ map[mrow*wide+mcol] = sum / wgt;
+ }
+ for (spread = 32/grow; spread--; ) {
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ if (map[mrow*wide+mcol]) continue;
+ sum = count = 0;
+ for (d=0; d < 8; d++) {
+ y = mrow + dir[d][0];
+ x = mcol + dir[d][1];
+ if (y < high && x < wide && map[y*wide+x] > 0) {
+ sum += (1 + (d & 1)) * map[y*wide+x];
+ count += 1 + (d & 1);
+ }
+ }
+ if (count > 3)
+ map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+ }
+ for (change=i=0; i < high*wide; i++)
+ if (map[i] < 0) {
+ map[i] = -map[i];
+ change = 1;
+ }
+ if (!change) break;
+ }
+ for (i=0; i < high*wide; i++)
+ if (map[i] == 0) map[i] = 1;
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+ for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+ pixel = image[row*width+col];
+ if (pixel[c] / hsat[c] > 1) {
+ val = pixel[kc] * map[mrow*wide+mcol];
+ if (pixel[c] < val) pixel[c] = CLIP(val);
+ }
+ }
+ }
+ }
+ free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+ unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+ *tag = get2();
+ *type = get2();
+ *len = get4();
+ *save = ftell(ifp) + 4;
+ if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+ fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+ unsigned entries, tag, type, len, save;
+
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ if (tag == toff) thumb_offset = get4()+base;
+ if (tag == tlen) thumb_length = get4();
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+int CLASS parse_tiff_ifd (int base);
+
+void CLASS parse_makernote (int base, int uptag)
+{
+ static const uchar xlat[2][256] = {
+ { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
+ 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
+ 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
+ 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
+ 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
+ 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
+ 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
+ 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
+ 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
+ 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
+ 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
+ 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
+ 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
+ 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
+ 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
+ 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
+ { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
+ 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
+ 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
+ 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
+ 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
+ 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
+ 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
+ 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
+ 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
+ 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
+ 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
+ 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
+ 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
+ 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
+ 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
+ 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
+ unsigned offset=0, entries, tag, type, len, save, c;
+ unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+ uchar buf97[324], ci, cj, ck;
+ short sorder=order;
+ char buf[10];
+/*
+ The MakerNote might have its own TIFF header (possibly with
+ its own byte-order!), or it might just be a table.
+ */
+ fread (buf, 1, 10, ifp);
+ if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
+ !strncmp (buf,"VER" ,3) ||
+ !strncmp (buf,"IIII",4) ||
+ !strncmp (buf,"MMMM",4)) return;
+ if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */
+ !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */
+ order = 0x4d4d;
+ while ((i=ftell(ifp)) < data_offset && i < 16384) {
+ wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3];
+ wb[3] = get2();
+ if (wb[1] == 256 && wb[3] == 256 &&
+ wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+ FORC4 cam_mul[c] = wb[c];
+ }
+ goto quit;
+ }
+ if (!strcmp (buf,"Nikon")) {
+ base = ftell(ifp);
+ order = get2();
+ if (get2() != 42) goto quit;
+ offset = get4();
+ fseek (ifp, offset-8, SEEK_CUR);
+ } else if (!strcmp (buf,"OLYMPUS")) {
+ base = ftell(ifp)-10;
+ fseek (ifp, -2, SEEK_CUR);
+ order = get2(); get2();
+ } else if (!strncmp (buf,"FUJIFILM",8) ||
+ !strncmp (buf,"SONY",4) ||
+ !strcmp (buf,"Panasonic")) {
+ order = 0x4949;
+ fseek (ifp, 2, SEEK_CUR);
+ } else if (!strcmp (buf,"OLYMP") ||
+ !strcmp (buf,"LEICA") ||
+ !strcmp (buf,"Ricoh") ||
+ !strcmp (buf,"EPSON"))
+ fseek (ifp, -2, SEEK_CUR);
+ else if (!strcmp (buf,"AOC") ||
+ !strcmp (buf,"QVC"))
+ fseek (ifp, -4, SEEK_CUR);
+ else fseek (ifp, -10, SEEK_CUR);
+
+ entries = get2();
+ if (entries > 1000) return;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ tag |= uptag << 16;
+ if (tag == 2 && strstr(make,"NIKON"))
+ iso_speed = (get2(),get2());
+ if (tag == 4 && len > 26 && len < 35) {
+ if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+ iso_speed = 50 * pow (2, i/32.0 - 4);
+ if ((i=(get2(),get2())) != 0x7fff && !aperture)
+ aperture = pow (2, i/64.0);
+ if ((i=get2()) != 0xffff && !shutter)
+ shutter = pow (2, (short) i/-32.0);
+ wbi = (get2(),get2());
+ shot_order = (get2(),get2());
+ }
+ if (tag == 7 && type == 2 && len > 20)
+ fgets (model2, 64, ifp);
+ if (tag == 8 && type == 4)
+ shot_order = get4();
+ if (tag == 9 && !strcmp(make,"Canon"))
+ fread (artist, 64, 1, ifp);
+ if (tag == 0xc && len == 4) {
+ cam_mul[0] = getreal(type);
+ cam_mul[2] = getreal(type);
+ }
+ if (tag == 0x10 && type == 4)
+ unique_id = get4();
+ if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_tiff_ifd (base);
+ }
+ if (tag == 0x14 && len == 2560 && type == 7) {
+ fseek (ifp, 1248, SEEK_CUR);
+ goto get2_256;
+ }
+ if (tag == 0x15 && type == 2 && is_raw)
+ fread (model, 64, 1, ifp);
+ if (strstr(make,"PENTAX")) {
+ if (tag == 0x1b) tag = 0x1018;
+ if (tag == 0x1c) tag = 0x1017;
+ }
+ if (tag == 0x1d)
+ while ((c = fgetc(ifp)) && c != EOF)
+ serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+ if (tag == 0x81 && type == 4) {
+ data_offset = get4();
+ fseek (ifp, data_offset + 41, SEEK_SET);
+ raw_height = get2() * 2;
+ raw_width = get2();
+ filters = 0x61616161;
+ }
+ if (tag == 0x29 && type == 1) {
+ c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+ fseek (ifp, 8 + c*32, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+ }
+ if ((tag == 0x81 && type == 7) ||
+ (tag == 0x100 && type == 7) ||
+ (tag == 0x280 && type == 1)) {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+ thumb_offset += base;
+ if (tag == 0x89 && type == 4)
+ thumb_length = get4();
+ if (tag == 0x8c || tag == 0x96)
+ meta_offset = ftell(ifp);
+ if (tag == 0x97) {
+ for (i=0; i < 4; i++)
+ ver97 = ver97 * 10 + fgetc(ifp)-'0';
+ switch (ver97) {
+ case 100:
+ fseek (ifp, 68, SEEK_CUR);
+ FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+ break;
+ case 102:
+ fseek (ifp, 6, SEEK_CUR);
+ goto get2_rggb;
+ case 103:
+ fseek (ifp, 16, SEEK_CUR);
+ FORC4 cam_mul[c] = get2();
+ }
+ if (ver97 >= 200) {
+ if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+ fread (buf97, 324, 1, ifp);
+ }
+ }
+ if (tag == 0xa4 && type == 3) {
+ fseek (ifp, wbi*48, SEEK_CUR);
+ FORC3 cam_mul[c] = get2();
+ }
+ if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+ ci = xlat[0][serial & 0xff];
+ cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+ ck = 0x60;
+ for (i=0; i < 324; i++)
+ buf97[i] ^= (cj += ci * ck++);
+ i = "66666>666;6A"[ver97-200] - '0';
+ FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+ sget2 (buf97 + (i & -2) + c*2);
+ }
+ if (tag == 0x200 && len == 3)
+ shot_order = (get4(),get4());
+ if (tag == 0x200 && len == 4)
+ black = (get2()+get2()+get2()+get2())/4;
+ if (tag == 0x201 && len == 4)
+ goto get2_rggb;
+ if (tag == 0x220 && len == 53) {
+ fseek (ifp, 14, SEEK_CUR);
+ pentax_tree();
+ }
+ if (tag == 0x401 && len == 4) {
+ black = (get4()+get4()+get4()+get4())/4;
+ }
+ if (tag == 0xe01) { /* Nikon Capture Note */
+ type = order;
+ order = 0x4949;
+ fseek (ifp, 22, SEEK_CUR);
+ for (offset=22; offset+22 < len; offset += 22+i) {
+ tag = get4();
+ fseek (ifp, 14, SEEK_CUR);
+ i = get4()-4;
+ if (tag == 0x76a43207) flip = get2();
+ else fseek (ifp, i, SEEK_CUR);
+ }
+ order = type;
+ }
+ if (tag == 0xe80 && len == 256 && type == 7) {
+ fseek (ifp, 48, SEEK_CUR);
+ cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+ cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+ }
+ if (tag == 0xf00 && type == 7) {
+ if (len == 614)
+ fseek (ifp, 176, SEEK_CUR);
+ else if (len == 734 || len == 1502)
+ fseek (ifp, 148, SEEK_CUR);
+ else goto next;
+ goto get2_256;
+ }
+ if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+ for (i=0; i < 3; i++)
+ FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+ if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+ for (black = i=0; i < 4; i++)
+ black += get2() << 2;
+ if (tag == 0x1017 || tag == 0x20400100)
+ cam_mul[0] = get2() / 256.0;
+ if (tag == 0x1018 || tag == 0x20400100)
+ cam_mul[2] = get2() / 256.0;
+ if (tag == 0x2011 && len == 2) {
+get2_256:
+ order = 0x4d4d;
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ }
+ if ((tag | 0x70) == 0x2070 && type == 4)
+ fseek (ifp, get4()+base, SEEK_SET);
+ if (tag == 0x2010 && type != 7)
+ load_raw = &CLASS olympus_e410_load_raw;
+ if (tag == 0x2020)
+ parse_thumb_note (base, 257, 258);
+ if (tag == 0x2040)
+ parse_makernote (base, 0x2040);
+ if (tag == 0xb028) {
+ fseek (ifp, get4(), SEEK_SET);
+ parse_thumb_note (base, 136, 137);
+ }
+ if (tag == 0x4001 && len > 500) {
+ i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+ fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ fseek (ifp, 22, SEEK_CUR);
+ FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+ }
+next:
+ fseek (ifp, save, SEEK_SET);
+ }
+quit:
+ order = sorder;
+}
+
+/*
+ Since the TIFF DateTime string has no timezone information,
+ assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+ struct tm t;
+ char str[20];
+ int i;
+
+ str[19] = 0;
+ if (reversed)
+ for (i=19; i--; ) str[i] = fgetc(ifp);
+ else
+ fread (str, 19, 1, ifp);
+ memset (&t, 0, sizeof t);
+ if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+ &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+ return;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+ unsigned kodak, entries, tag, type, len, save, c;
+ double expo;
+
+ kodak = !strncmp(make,"EASTMAN",7);
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 33434: shutter = getreal(type); break;
+ case 33437: aperture = getreal(type); break;
+ case 34855: iso_speed = get2(); break;
+ case 36867:
+ case 36868: get_timestamp(0); break;
+ case 37377: if ((expo = -getreal(type)) < 128)
+ shutter = pow (2, expo); break;
+ case 37378: aperture = pow (2, getreal(type)/2); break;
+ case 37386: focal_len = getreal(type); break;
+ case 37500: parse_makernote (base, 0); break;
+ case 40962: if (kodak) raw_width = get4(); break;
+ case 40963: if (kodak) raw_height = get4(); break;
+ case 41730:
+ if (get4() == 0x20002)
+ for (exif_cfa=c=0; c < 8; c+=2)
+ exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS parse_gps (int base)
+{
+ unsigned entries, tag, type, len, save, c;
+
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 1: case 3: case 5:
+ gpsdata[29+tag/2] = getc(ifp); break;
+ case 2: case 4: case 7:
+ FORC(6) gpsdata[tag/3*6+c] = get4(); break;
+ case 6:
+ FORC(2) gpsdata[18+c] = get4(); break;
+ case 18: case 29:
+ fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+ static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
+ { { 2.034193, -0.727420, -0.306766 },
+ { -0.228811, 1.231729, -0.002922 },
+ { -0.008565, -0.153273, 1.161839 } };
+ int i, j, k;
+
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++)
+ for (cmatrix[i][j] = k=0; k < 3; k++)
+ cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+}
+
+void CLASS parse_mos (int offset)
+{
+ char data[40];
+ int skip, from, i, c, neut[4], planes=0, frot=0;
+ static const char *mod[] =
+ { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+ "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+ "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+ float romm_cam[3][3];
+
+ fseek (ifp, offset, SEEK_SET);
+ while (1) {
+ if (get4() != 0x504b5453) break;
+ get4();
+ fread (data, 1, 40, ifp);
+ skip = get4();
+ from = ftell(ifp);
+ if (!strcmp(data,"JPEG_preview_data")) {
+ thumb_offset = from;
+ thumb_length = skip;
+ }
+ if (!strcmp(data,"icc_camera_profile")) {
+ profile_offset = from;
+ profile_length = skip;
+ }
+ if (!strcmp(data,"ShootObj_back_type")) {
+ fscanf (ifp, "%d", &i);
+ if ((unsigned) i < sizeof mod / sizeof (*mod))
+ strcpy (model, mod[i]);
+ }
+ if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+ for (i=0; i < 9; i++)
+ romm_cam[0][i] = int_to_float(get4());
+ romm_coeff (romm_cam);
+ }
+ if (!strcmp(data,"CaptProf_color_matrix")) {
+ for (i=0; i < 9; i++)
+ fscanf (ifp, "%f", &romm_cam[0][i]);
+ romm_coeff (romm_cam);
+ }
+ if (!strcmp(data,"CaptProf_number_of_planes"))
+ fscanf (ifp, "%d", &planes);
+ if (!strcmp(data,"CaptProf_raw_data_rotation"))
+ fscanf (ifp, "%d", &flip);
+ if (!strcmp(data,"CaptProf_mosaic_pattern"))
+ FORC4 {
+ fscanf (ifp, "%d", &i);
+ if (i == 1) frot = c ^ (c >> 1);
+ }
+ if (!strcmp(data,"ImgProf_rotation_angle")) {
+ fscanf (ifp, "%d", &i);
+ flip = i - flip;
+ }
+ if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+ FORC4 fscanf (ifp, "%d", neut+c);
+ FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+ }
+ parse_mos (from);
+ fseek (ifp, skip+from, SEEK_SET);
+ }
+ if (planes)
+ filters = (planes == 1) * 0x01010101 *
+ (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+ int i;
+ if (len > 0x1000) len = 0x1000;
+ read_shorts (curve, len);
+ for (i=len; i < 0x1000; i++)
+ curve[i] = curve[i-1];
+ maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+ unsigned entries, tag, type, len, save;
+ int i, c, wbi=-2, wbtemp=6500;
+ float mul[3], num;
+
+ entries = get2();
+ if (entries > 1024) return;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ if (tag == 1020) wbi = getint(type);
+ if (tag == 1021 && len == 72) { /* WB set in software */
+ fseek (ifp, 40, SEEK_CUR);
+ FORC3 cam_mul[c] = 2048.0 / get2();
+ wbi = -2;
+ }
+ if (tag == 2118) wbtemp = getint(type);
+ if (tag == 2130 + wbi)
+ FORC3 mul[c] = getreal(type);
+ if (tag == 2140 + wbi && wbi >= 0)
+ FORC3 {
+ for (num=i=0; i < 4; i++)
+ num += getreal(type) * pow (wbtemp/100.0, i);
+ cam_mul[c] = 2048 / (num * mul[c]);
+ }
+ if (tag == 2317) linear_table (len);
+ if (tag == 6020) iso_speed = getint(type);
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS parse_minolta (int base);
+
+int CLASS parse_tiff_ifd (int base)
+{
+ unsigned entries, tag, type, len, plen=16, save;
+ int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+ char software[64], *cbuf, *cp;
+ uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+ double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+ double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+ unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+ unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+ struct jhead jh;
+ FILE *sfp;
+
+ if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+ return 1;
+ ifd = tiff_nifds++;
+ for (j=0; j < 4; j++)
+ for (i=0; i < 4; i++)
+ cc[j][i] = i == j;
+ entries = get2();
+ if (entries > 512) return 1;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 17: case 18:
+ if (type == 3 && len == 1)
+ cam_mul[(tag-17)*2] = get2() / 256.0;
+ break;
+ case 23:
+ if (type == 3) iso_speed = get2();
+ break;
+ case 36: case 37: case 38:
+ cam_mul[tag-0x24] = get2();
+ break;
+ case 39:
+ if (len < 50 || cam_mul[0]) break;
+ fseek (ifp, 12, SEEK_CUR);
+ FORC3 cam_mul[c] = get2();
+ break;
+ case 46:
+ if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+ thumb_offset = ftell(ifp) - 2;
+ thumb_length = len;
+ break;
+ case 2: case 256: /* ImageWidth */
+ tiff_ifd[ifd].width = getint(type);
+ break;
+ case 3: case 257: /* ImageHeight */
+ tiff_ifd[ifd].height = getint(type);
+ break;
+ case 258: /* BitsPerSample */
+ tiff_ifd[ifd].samples = len & 7;
+ tiff_ifd[ifd].bps = get2();
+ break;
+ case 259: /* Compression */
+ tiff_ifd[ifd].comp = get2();
+ break;
+ case 262: /* PhotometricInterpretation */
+ tiff_ifd[ifd].phint = get2();
+ break;
+ case 270: /* ImageDescription */
+ fread (desc, 512, 1, ifp);
+ break;
+ case 271: /* Make */
+ fgets (make, 64, ifp);
+ break;
+ case 272: /* Model */
+ fgets (model, 64, ifp);
+ break;
+ case 280: /* Panasonic RW2 offset */
+ if (type != 4) break;
+ load_raw = &CLASS panasonic_load_raw;
+ load_flags = 0x2008;
+ case 273: /* StripOffset */
+ case 513:
+ tiff_ifd[ifd].offset = get4()+base;
+ if (!tiff_ifd[ifd].bps) {
+ fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ tiff_ifd[ifd].comp = 6;
+ tiff_ifd[ifd].width = jh.wide << (jh.clrs == 2);
+ tiff_ifd[ifd].height = jh.high;
+ tiff_ifd[ifd].bps = jh.bits;
+ tiff_ifd[ifd].samples = jh.clrs;
+ }
+ }
+ break;
+ case 274: /* Orientation */
+ tiff_ifd[ifd].flip = "50132467"[get2() & 7]-'0';
+ break;
+ case 277: /* SamplesPerPixel */
+ tiff_ifd[ifd].samples = getint(type) & 7;
+ break;
+ case 279: /* StripByteCounts */
+ case 514:
+ tiff_ifd[ifd].bytes = get4();
+ break;
+ case 305: case 11: /* Software */
+ fgets (software, 64, ifp);
+ if (!strncmp(software,"Adobe",5) ||
+ !strncmp(software,"dcraw",5) ||
+ !strncmp(software,"UFRaw",5) ||
+ !strncmp(software,"Bibble",6) ||
+ !strncmp(software,"Nikon Scan",10) ||
+ !strcmp (software,"Digital Photo Professional"))
+ is_raw = 0;
+ break;
+ case 306: /* DateTime */
+ get_timestamp(0);
+ break;
+ case 315: /* Artist */
+ fread (artist, 64, 1, ifp);
+ break;
+ case 322: /* TileWidth */
+ tile_width = getint(type);
+ break;
+ case 323: /* TileLength */
+ tile_length = getint(type);
+ break;
+ case 324: /* TileOffsets */
+ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+ if (len == 4) {
+ load_raw = &CLASS sinar_4shot_load_raw;
+ is_raw = 5;
+ }
+ break;
+ case 330: /* SubIFDs */
+ if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].width == 3872) {
+ load_raw = &CLASS sony_arw_load_raw;
+ data_offset = get4()+base;
+ ifd++; break;
+ }
+ while (len--) {
+ i = ftell(ifp);
+ fseek (ifp, get4()+base, SEEK_SET);
+ if (parse_tiff_ifd (base)) break;
+ fseek (ifp, i+4, SEEK_SET);
+ }
+ break;
+ case 400:
+ strcpy (make, "Sarnoff");
+ maximum = 0xfff;
+ break;
+ case 28688:
+ FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+ for (i=0; i < 5; i++)
+ for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+ curve[j] = curve[j-1] + (1 << i);
+ break;
+ case 29184: sony_offset = get4(); break;
+ case 29185: sony_length = get4(); break;
+ case 29217: sony_key = get4(); break;
+ case 29264:
+ parse_minolta (ftell(ifp));
+ raw_width = 0;
+ break;
+ case 29443:
+ FORC4 cam_mul[c ^ (c < 2)] = get2();
+ break;
+ case 29459:
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ break;
+ case 33405: /* Model2 */
+ fgets (model2, 64, ifp);
+ break;
+ case 33422: /* CFAPattern */
+ case 64777: /* Kodak P-series */
+ if ((plen=len) > 16) plen = 16;
+ fread (cfa_pat, 1, plen, ifp);
+ for (colors=cfa=i=0; i < plen; i++) {
+ colors += !(cfa & (1 << cfa_pat[i]));
+ cfa |= 1 << cfa_pat[i];
+ }
+ if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */
+ if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */
+ goto guess_cfa_pc;
+ case 33424:
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_kodak_ifd (base);
+ break;
+ case 33434: /* ExposureTime */
+ shutter = getreal(type);
+ break;
+ case 33437: /* FNumber */
+ aperture = getreal(type);
+ break;
+ case 34306: /* Leaf white balance */
+ FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+ break;
+ case 34307: /* Leaf CatchLight color matrix */
+ fread (software, 1, 7, ifp);
+ if (strncmp(software,"MATRIX",6)) break;
+ colors = 4;
+ for (raw_color = i=0; i < 3; i++) {
+ FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+ if (!use_camera_wb) continue;
+ num = 0;
+ FORC4 num += rgb_cam[i][c];
+ FORC4 rgb_cam[i][c] /= num;
+ }
+ break;
+ case 34310: /* Leaf metadata */
+ parse_mos (ftell(ifp));
+ case 34303:
+ strcpy (make, "Leaf");
+ break;
+ case 34665: /* EXIF tag */
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_exif (base);
+ break;
+ case 34853: /* GPSInfo tag */
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_gps (base);
+ break;
+ case 34675: /* InterColorProfile */
+ case 50831: /* AsShotICCProfile */
+ profile_offset = ftell(ifp);
+ profile_length = len;
+ break;
+ case 37122: /* CompressedBitsPerPixel */
+ kodak_cbpp = get4();
+ break;
+ case 37386: /* FocalLength */
+ focal_len = getreal(type);
+ break;
+ case 37393: /* ImageNumber */
+ shot_order = getint(type);
+ break;
+ case 37400: /* old Kodak KDC tag */
+ for (raw_color = i=0; i < 3; i++) {
+ getreal(type);
+ FORC3 rgb_cam[i][c] = getreal(type);
+ }
+ break;
+ case 46275: /* Imacon tags */
+ strcpy (make, "Imacon");
+ data_offset = ftell(ifp);
+ ima_len = len;
+ break;
+ case 46279:
+ if (!ima_len) break;
+ fseek (ifp, 78, SEEK_CUR);
+ raw_width = get4();
+ raw_height = get4();
+ left_margin = get4() & 7;
+ width = raw_width - left_margin - (get4() & 7);
+ top_margin = get4() & 7;
+ height = raw_height - top_margin - (get4() & 7);
+ if (raw_width == 7262) {
+ height = 5444;
+ width = 7244;
+ left_margin = 7;
+ }
+ fseek (ifp, 52, SEEK_CUR);
+ FORC3 cam_mul[c] = getreal(11);
+ fseek (ifp, 114, SEEK_CUR);
+ flip = (get2() >> 7) * 90;
+ if (width * height * 6 == ima_len) {
+ if (flip % 180 == 90) SWAP(width,height);
+ filters = flip = 0;
+ }
+ sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+ load_raw = &CLASS imacon_full_load_raw;
+ if (filters) {
+ if (left_margin & 1) filters = 0x61616161;
+ load_raw = &CLASS unpacked_load_raw;
+ }
+ maximum = 0xffff;
+ break;
+ case 50454: /* Sinar tag */
+ case 50455:
+ if (!(cbuf = (char *) malloc(len))) break;
+ fread (cbuf, 1, len, ifp);
+ for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+ if (!strncmp (++cp,"Neutral ",8))
+ sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+ free (cbuf);
+ break;
+ case 50458:
+ if (!make[0]) strcpy (make, "Hasselblad");
+ break;
+ case 50459: /* Hasselblad tag */
+ i = order;
+ j = ftell(ifp);
+ c = tiff_nifds;
+ order = get2();
+ fseek (ifp, j+(get2(),get4()), SEEK_SET);
+ parse_tiff_ifd (j);
+ maximum = 0xffff;
+ tiff_nifds = c;
+ order = i;
+ break;
+ case 50706: /* DNGVersion */
+ FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+ if (!make[0]) strcpy (make, "DNG");
+ is_raw = 1;
+ break;
+ case 50710: /* CFAPlaneColor */
+ if (len > 4) len = 4;
+ colors = len;
+ fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+ FORCC tab[cfa_pc[c]] = c;
+ cdesc[c] = 0;
+ for (i=16; i--; )
+ filters = filters << 2 | tab[cfa_pat[i % plen]];
+ break;
+ case 50711: /* CFALayout */
+ if (get2() == 2) {
+ fuji_width = 1;
+ filters = 0x49494949;
+ }
+ break;
+ case 291:
+ case 50712: /* LinearizationTable */
+ linear_table (len);
+ break;
+ case 50714: /* BlackLevel */
+ case 50715: /* BlackLevelDeltaH */
+ case 50716: /* BlackLevelDeltaV */
+ for (dblack=i=0; i < len; i++)
+ dblack += getreal(type);
+ black += dblack/len + 0.5;
+ break;
+ case 50717: /* WhiteLevel */
+ maximum = getint(type);
+ break;
+ case 50718: /* DefaultScale */
+ pixel_aspect = getreal(type);
+ pixel_aspect /= getreal(type);
+ break;
+ case 50721: /* ColorMatrix1 */
+ case 50722: /* ColorMatrix2 */
+ FORCC for (j=0; j < 3; j++)
+ cm[c][j] = getreal(type);
+ use_cm = 1;
+ break;
+ case 50723: /* CameraCalibration1 */
+ case 50724: /* CameraCalibration2 */
+ for (i=0; i < colors; i++)
+ FORCC cc[i][c] = getreal(type);
+ case 50727: /* AnalogBalance */
+ FORCC ab[c] = getreal(type);
+ break;
+ case 50728: /* AsShotNeutral */
+ FORCC asn[c] = getreal(type);
+ break;
+ case 50729: /* AsShotWhiteXY */
+ xyz[0] = getreal(type);
+ xyz[1] = getreal(type);
+ xyz[2] = 1 - xyz[0] - xyz[1];
+ FORC3 xyz[c] /= d65_white[c];
+ break;
+ case 50740: /* DNGPrivateData */
+ if (dng_version) break;
+ parse_minolta (j = get4()+base);
+ fseek (ifp, j, SEEK_SET);
+ parse_tiff_ifd (base);
+ break;
+ case 50752:
+ read_shorts (cr2_slice, 3);
+ break;
+ case 50829: /* ActiveArea */
+ top_margin = getint(type);
+ left_margin = getint(type);
+ height = getint(type) - top_margin;
+ width = getint(type) - left_margin;
+ break;
+ case 64772: /* Kodak P-series */
+ fseek (ifp, 16, SEEK_CUR);
+ data_offset = get4();
+ fseek (ifp, 28, SEEK_CUR);
+ data_offset += get4();
+ load_raw = &CLASS packed_12_load_raw;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+ fseek (ifp, sony_offset, SEEK_SET);
+ fread (buf, sony_length, 1, ifp);
+ sony_decrypt (buf, sony_length/4, 1, sony_key);
+ sfp = ifp;
+ if ((ifp = tmpfile())) {
+ fwrite (buf, sony_length, 1, ifp);
+ fseek (ifp, 0, SEEK_SET);
+ parse_tiff_ifd (-sony_offset);
+ fclose (ifp);
+ }
+ ifp = sfp;
+ free (buf);
+ }
+ for (i=0; i < colors; i++)
+ FORCC cc[i][c] *= ab[i];
+ if (use_cm) {
+ FORCC for (i=0; i < 3; i++)
+ for (cam_xyz[c][i]=j=0; j < colors; j++)
+ cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+ cam_xyz_coeff (cam_xyz);
+ }
+ if (asn[0]) {
+ cam_mul[3] = 0;
+ FORCC cam_mul[c] = 1 / asn[c];
+ }
+ if (!use_cm)
+ FORCC pre_mul[c] /= cc[c][c];
+ return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+ int doff, max_samp=0, raw=-1, thm=-1, i;
+ struct jhead jh;
+
+ fseek (ifp, base, SEEK_SET);
+ order = get2();
+ if (order != 0x4949 && order != 0x4d4d) return;
+ get2();
+ memset (tiff_ifd, 0, sizeof tiff_ifd);
+ tiff_nifds = 0;
+ while ((doff = get4())) {
+ fseek (ifp, doff+base, SEEK_SET);
+ if (parse_tiff_ifd (base)) break;
+ }
+ thumb_misc = 16;
+ if (thumb_offset) {
+ fseek (ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ thumb_misc = jh.bits;
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+ for (i=0; i < tiff_nifds; i++) {
+ if (max_samp < tiff_ifd[i].samples)
+ max_samp = tiff_ifd[i].samples;
+ if (max_samp > 3) max_samp = 3;
+ if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+ tiff_ifd[i].width*tiff_ifd[i].height > raw_width*raw_height) {
+ raw_width = tiff_ifd[i].width;
+ raw_height = tiff_ifd[i].height;
+ tiff_bps = tiff_ifd[i].bps;
+ tiff_compress = tiff_ifd[i].comp;
+ data_offset = tiff_ifd[i].offset;
+ tiff_flip = tiff_ifd[i].flip;
+ tiff_samples = tiff_ifd[i].samples;
+ raw = i;
+ }
+ }
+ fuji_width *= (raw_width+1)/2;
+ if (tiff_ifd[0].flip) tiff_flip = tiff_ifd[0].flip;
+ if (raw >= 0 && !load_raw)
+ switch (tiff_compress) {
+ case 0: case 1:
+ switch (tiff_bps) {
+ case 8: load_raw = &CLASS eight_bit_load_raw; break;
+ case 12: load_raw = &CLASS packed_12_load_raw;
+ if (tiff_ifd[raw].phint == 2)
+ load_flags = 6;
+ if (strncmp(make,"PENTAX",6)) break;
+ case 14:
+ case 16: load_raw = &CLASS unpacked_load_raw; break;
+ }
+ if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8)
+ load_raw = &CLASS olympus_e300_load_raw;
+ break;
+ case 6: case 7: case 99:
+ load_raw = &CLASS lossless_jpeg_load_raw; break;
+ case 262:
+ load_raw = &CLASS kodak_262_load_raw; break;
+ case 32767:
+ load_raw = &CLASS sony_arw2_load_raw;
+ if (tiff_ifd[raw].bytes*8 == raw_width*raw_height*tiff_bps)
+ break;
+ raw_height += 8;
+ load_raw = &CLASS sony_arw_load_raw; break;
+ case 32769:
+ load_flags = 8;
+ case 32773:
+ load_raw = &CLASS packed_12_load_raw; break;
+ case 34713:
+ load_raw = &CLASS nikon_compressed_load_raw; break;
+ case 65535:
+ load_raw = &CLASS pentax_k10_load_raw; break;
+ case 65000:
+ switch (tiff_ifd[raw].phint) {
+ case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break;
+ case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break;
+ case 32803: load_raw = &CLASS kodak_65000_load_raw;
+ }
+ case 32867: break;
+ default: is_raw = 0;
+ }
+ if (!dng_version && tiff_samples == 3)
+ if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048)
+ is_raw = 0;
+ if (!dng_version && tiff_bps == 8 && tiff_compress == 1 &&
+ tiff_ifd[raw].phint == 1) is_raw = 0;
+ if (tiff_bps == 8 && tiff_samples == 4) is_raw = 0;
+ for (i=0; i < tiff_nifds; i++)
+ if (i != raw && tiff_ifd[i].samples == max_samp &&
+ tiff_ifd[i].width * tiff_ifd[i].height / SQR(tiff_ifd[i].bps+1) >
+ thumb_width * thumb_height / SQR(thumb_misc+1)) {
+ thumb_width = tiff_ifd[i].width;
+ thumb_height = tiff_ifd[i].height;
+ thumb_offset = tiff_ifd[i].offset;
+ thumb_length = tiff_ifd[i].bytes;
+ thumb_misc = tiff_ifd[i].bps;
+ thm = i;
+ }
+ if (thm >= 0) {
+ thumb_misc |= tiff_ifd[thm].samples << 5;
+ switch (tiff_ifd[thm].comp) {
+ case 0:
+ write_thumb = &CLASS layer_thumb;
+ break;
+ case 1:
+ if (tiff_ifd[thm].bps > 8)
+ thumb_load_raw = &CLASS kodak_thumb_load_raw;
+ else
+ write_thumb = &CLASS ppm_thumb;
+ break;
+ case 65000:
+ thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+ &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+ }
+ }
+}
+
+void CLASS parse_minolta (int base)
+{
+ int save, tag, len, offset, high=0, wide=0, i, c;
+ short sorder=order;
+
+ fseek (ifp, base, SEEK_SET);
+ if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+ order = fgetc(ifp) * 0x101;
+ offset = base + get4() + 8;
+ while ((save=ftell(ifp)) < offset) {
+ for (tag=i=0; i < 4; i++)
+ tag = tag << 8 | fgetc(ifp);
+ len = get4();
+ switch (tag) {
+ case 0x505244: /* PRD */
+ fseek (ifp, 8, SEEK_CUR);
+ high = get2();
+ wide = get2();
+ break;
+ case 0x574247: /* WBG */
+ get4();
+ i = strcmp(model,"DiMAGE A200") ? 0:3;
+ FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+ break;
+ case 0x545457: /* TTW */
+ parse_tiff (ftell(ifp));
+ data_offset = offset;
+ }
+ fseek (ifp, save+len+8, SEEK_SET);
+ }
+ raw_height = high;
+ raw_width = wide;
+ order = sorder;
+}
+
+/*
+ Many cameras have a "debug mode" that writes JPEG and raw
+ at the same time. The raw file has no header, so try to
+ to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+ char *file, *ext, *jname, *jfile, *jext;
+ FILE *save=ifp;
+
+ ext = strrchr (ifname, '.');
+ file = strrchr (ifname, '/');
+ if (!file) file = strrchr (ifname, '\\');
+ if (!file) file = ifname-1;
+ file++;
+ if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+ jname = (char *) malloc (strlen(ifname) + 1);
+ merror (jname, "parse_external_jpeg()");
+ strcpy (jname, ifname);
+ jfile = file - ifname + jname;
+ jext = ext - ifname + jname;
+ if (strcasecmp (ext, ".jpg")) {
+ strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+ if (isdigit(*file)) {
+ memcpy (jfile, file+4, 4);
+ memcpy (jfile+4, file, 4);
+ }
+ } else
+ while (isdigit(*--jext)) {
+ if (*jext != '9') {
+ (*jext)++;
+ break;
+ }
+ *jext = '0';
+ }
+ if (strcmp (jname, ifname)) {
+ if ((ifp = fopen (jname, "rb"))) {
+ if (verbose)
+ fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+ parse_tiff (12);
+ thumb_offset = 0;
+ is_raw = 1;
+ fclose (ifp);
+ }
+ }
+ if (!timestamp)
+ fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+ free (jname);
+ ifp = save;
+}
+
+/*
+ CIFF block 0x1030 contains an 8x8 white sample.
+ Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+ static const ushort key[] = { 0x410, 0x45f3 };
+ int i, bpp, row, col, vbits=0;
+ unsigned long bitbuf=0;
+
+ if ((get2(),get4()) != 0x80008 || !get4()) return;
+ bpp = get2();
+ if (bpp != 10 && bpp != 12) return;
+ for (i=row=0; row < 8; row++)
+ for (col=0; col < 8; col++) {
+ if (vbits < bpp) {
+ bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+ vbits += 16;
+ }
+ white[row][col] =
+ bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+ vbits -= bpp;
+ }
+}
+
+/*
+ Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+ int tboff, nrecs, c, type, len, save, wbi=-1;
+ ushort key[] = { 0x410, 0x45f3 };
+
+ fseek (ifp, offset+length-4, SEEK_SET);
+ tboff = get4() + offset;
+ fseek (ifp, tboff, SEEK_SET);
+ nrecs = get2();
+ if (nrecs > 100) return;
+ while (nrecs--) {
+ type = get2();
+ len = get4();
+ save = ftell(ifp) + 4;
+ fseek (ifp, offset+get4(), SEEK_SET);
+ if ((((type >> 8) + 8) | 8) == 0x38)
+ parse_ciff (ftell(ifp), len); /* Parse a sub-table */
+
+ if (type == 0x0810)
+ fread (artist, 64, 1, ifp);
+ if (type == 0x080a) {
+ fread (make, 64, 1, ifp);
+ fseek (ifp, strlen(make) - 63, SEEK_CUR);
+ fread (model, 64, 1, ifp);
+ }
+ if (type == 0x1810) {
+ fseek (ifp, 12, SEEK_CUR);
+ flip = get4();
+ }
+ if (type == 0x1835) /* Get the decoder table */
+ tiff_compress = get4();
+ if (type == 0x2007) {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ if (type == 0x1818) {
+ shutter = pow (2, -int_to_float((get4(),get4())));
+ aperture = pow (2, int_to_float(get4())/2);
+ }
+ if (type == 0x102a) {
+ iso_speed = pow (2, (get4(),get2())/32.0 - 4) * 50;
+ aperture = pow (2, (get2(),(short)get2())/64.0);
+ shutter = pow (2,-((short)get2())/32.0);
+ wbi = (get2(),get2());
+ if (wbi > 17) wbi = 0;
+ fseek (ifp, 32, SEEK_CUR);
+ if (shutter > 1e6) shutter = get2()/10.0;
+ }
+ if (type == 0x102c) {
+ if (get2() > 512) { /* Pro90, G1 */
+ fseek (ifp, 118, SEEK_CUR);
+ FORC4 cam_mul[c ^ 2] = get2();
+ } else { /* G2, S30, S40 */
+ fseek (ifp, 98, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+ }
+ }
+ if (type == 0x0032) {
+ if (len == 768) { /* EOS D30 */
+ fseek (ifp, 72, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+ if (!wbi) cam_mul[0] = -1; /* use my auto white balance */
+ } else if (!cam_mul[0]) {
+ if (get2() == key[0]) /* Pro1, G6, S60, S70 */
+ c = (strstr(model,"Pro1") ?
+ "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+ else { /* G3, G5, S45, S50 */
+ c = "023457000000006000"[wbi]-'0';
+ key[0] = key[1] = 0;
+ }
+ fseek (ifp, 78 + c*8, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+ if (!wbi) cam_mul[0] = -1;
+ }
+ }
+ if (type == 0x10a9) { /* D60, 10D, 300D, and clones */
+ if (len > 66) wbi = "0134567028"[wbi]-'0';
+ fseek (ifp, 2 + wbi*8, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ }
+ if (type == 0x1030 && (0x18040 >> wbi & 1))
+ ciff_block_1030(); /* all that don't have 0x10a9 */
+ if (type == 0x1031) {
+ raw_width = (get2(),get2());
+ raw_height = get2();
+ }
+ if (type == 0x5029) {
+ focal_len = len >> 16;
+ if ((len & 0xffff) == 2) focal_len /= 32;
+ }
+ if (type == 0x5813) flash_used = int_to_float(len);
+ if (type == 0x5814) canon_ev = int_to_float(len);
+ if (type == 0x5817) shot_order = len;
+ if (type == 0x5834) unique_id = len;
+ if (type == 0x580e) timestamp = len;
+ if (type == 0x180e) timestamp = get4();
+#ifdef LOCALTIME
+ if ((type | 0x4000) == 0x580e)
+ timestamp = mktime (gmtime (&timestamp));
+#endif
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS parse_rollei()
+{
+ char line[128], *val;
+ struct tm t;
+
+ fseek (ifp, 0, SEEK_SET);
+ memset (&t, 0, sizeof t);
+ do {
+ fgets (line, 128, ifp);
+ if ((val = strchr(line,'=')))
+ *val++ = 0;
+ else
+ val = line + strlen(line);
+ if (!strcmp(line,"DAT"))
+ sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+ if (!strcmp(line,"TIM"))
+ sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+ if (!strcmp(line,"HDR"))
+ thumb_offset = atoi(val);
+ if (!strcmp(line,"X "))
+ raw_width = atoi(val);
+ if (!strcmp(line,"Y "))
+ raw_height = atoi(val);
+ if (!strcmp(line,"TX "))
+ thumb_width = atoi(val);
+ if (!strcmp(line,"TY "))
+ thumb_height = atoi(val);
+ } while (strncmp(line,"EOHD",4));
+ data_offset = thumb_offset + thumb_width * thumb_height * 2;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ strcpy (make, "Rollei");
+ strcpy (model,"d530flex");
+ write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+ int entries, off;
+ char str[8], *cp;
+
+ order = 0x4949;
+ fseek (ifp, 4, SEEK_SET);
+ entries = get4();
+ fseek (ifp, get4(), SEEK_SET);
+ while (entries--) {
+ off = get4(); get4();
+ fread (str, 8, 1, ifp);
+ if (!strcmp(str,"META")) meta_offset = off;
+ if (!strcmp(str,"THUMB")) thumb_offset = off;
+ if (!strcmp(str,"RAW0")) data_offset = off;
+ }
+ fseek (ifp, meta_offset+20, SEEK_SET);
+ fread (make, 64, 1, ifp);
+ make[63] = 0;
+ if ((cp = strchr(make,' '))) {
+ strcpy (model, cp+1);
+ *cp = 0;
+ }
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &CLASS unpacked_load_raw;
+ thumb_width = (get4(),get2());
+ thumb_height = get2();
+ write_thumb = &CLASS ppm_thumb;
+ maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+ unsigned entries, tag, type, len, data, save, i, c;
+ float romm_cam[3][3];
+ char *cp;
+
+ memset (&ph1, 0, sizeof ph1);
+ fseek (ifp, base, SEEK_SET);
+ order = get4() & 0xffff;
+ if (get4() >> 8 != 0x526177) return; /* "Raw" */
+ fseek (ifp, get4()+base, SEEK_SET);
+ entries = get4();
+ get4();
+ while (entries--) {
+ tag = get4();
+ type = get4();
+ len = get4();
+ data = get4();
+ save = ftell(ifp);
+ fseek (ifp, base+data, SEEK_SET);
+ switch (tag) {
+ case 0x100: flip = "0653"[data & 3]-'0'; break;
+ case 0x106:
+ for (i=0; i < 9; i++)
+ romm_cam[0][i] = getreal(11);
+ romm_coeff (romm_cam);
+ break;
+ case 0x107:
+ FORC3 cam_mul[c] = getreal(11);
+ break;
+ case 0x108: raw_width = data; break;
+ case 0x109: raw_height = data; break;
+ case 0x10a: left_margin = data; break;
+ case 0x10b: top_margin = data; break;
+ case 0x10c: width = data; break;
+ case 0x10d: height = data; break;
+ case 0x10e: ph1.format = data; break;
+ case 0x10f: data_offset = data+base; break;
+ case 0x110: meta_offset = data+base;
+ meta_length = len; break;
+ case 0x112: ph1.key_off = save - 4; break;
+ case 0x210: ph1.tag_210 = int_to_float(data); break;
+ case 0x21a: ph1.tag_21a = data; break;
+ case 0x21c: strip_offset = data+base; break;
+ case 0x21d: ph1.black = data; break;
+ case 0x222: ph1.split_col = data - left_margin; break;
+ case 0x223: ph1.black_off = data+base; break;
+ case 0x301:
+ model[63] = 0;
+ fread (model, 1, 63, ifp);
+ if ((cp = strstr(model," camera"))) *cp = 0;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ load_raw = ph1.format < 3 ?
+ &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+ maximum = 0xffff;
+ strcpy (make, "Phase One");
+ if (model[0]) return;
+ switch (raw_height) {
+ case 2060: strcpy (model,"LightPhase"); break;
+ case 2682: strcpy (model,"H 10"); break;
+ case 4128: strcpy (model,"H 20"); break;
+ case 5488: strcpy (model,"H 25"); break;
+ }
+}
+
+void CLASS parse_fuji (int offset)
+{
+ unsigned entries, tag, len, save, c;
+
+ fseek (ifp, offset, SEEK_SET);
+ entries = get4();
+ if (entries > 255) return;
+ while (entries--) {
+ tag = get2();
+ len = get2();
+ save = ftell(ifp);
+ if (tag == 0x100) {
+ raw_height = get2();
+ raw_width = get2();
+ } else if (tag == 0x121) {
+ height = get2();
+ if ((width = get2()) == 4284) width += 3;
+ } else if (tag == 0x130)
+ fuji_layout = fgetc(ifp) >> 7;
+ if (tag == 0x2ff0)
+ FORC4 cam_mul[c ^ 1] = get2();
+ fseek (ifp, save+len, SEEK_SET);
+ }
+ height <<= fuji_layout;
+ width >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+ int len, save, hlen, mark;
+
+ fseek (ifp, offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+ while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+ order = 0x4d4d;
+ len = get2() - 2;
+ save = ftell(ifp);
+ if (mark == 0xc0 || mark == 0xc3) {
+ fgetc(ifp);
+ raw_height = get2();
+ raw_width = get2();
+ }
+ order = get2();
+ hlen = get4();
+ if (get4() == 0x48454150) /* "HEAP" */
+ parse_ciff (save+hlen, len-hlen);
+ parse_tiff (save+6);
+ fseek (ifp, save+len, SEEK_SET);
+ }
+ return 1;
+}
+
+void CLASS parse_riff()
+{
+ unsigned i, size, end;
+ char tag[4], date[64], month[64];
+ static const char mon[12][4] =
+ { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+ struct tm t;
+
+ order = 0x4949;
+ fread (tag, 4, 1, ifp);
+ size = get4();
+ end = ftell(ifp) + size;
+ if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+ get4();
+ while (ftell(ifp)+7 < end)
+ parse_riff();
+ } else if (!memcmp(tag,"nctg",4)) {
+ while (ftell(ifp)+7 < end) {
+ i = get2();
+ size = get2();
+ if ((i+1) >> 1 == 10 && size == 20)
+ get_timestamp(0);
+ else fseek (ifp, size, SEEK_CUR);
+ }
+ } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+ fread (date, 64, 1, ifp);
+ date[size] = 0;
+ memset (&t, 0, sizeof t);
+ if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+ &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+ for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+ t.tm_mon = i;
+ t.tm_year -= 1900;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ }
+ } else
+ fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+ int ver;
+
+ fseek (ifp, offset+2, SEEK_SET);
+ order = 0x4949;
+ ver = fgetc(ifp);
+ if (ver == 6)
+ fseek (ifp, 5, SEEK_CUR);
+ if (get4() != fsize) return;
+ if (ver > 6) data_offset = get4();
+ raw_height = height = get2();
+ raw_width = width = get2();
+ strcpy (make, "SMaL");
+ sprintf (model, "v%d %dx%d", ver, width, height);
+ if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+ if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+ unsigned off_head, off_setup, off_image, i;
+
+ order = 0x4949;
+ fseek (ifp, 4, SEEK_SET);
+ is_raw = get2() == 2;
+ fseek (ifp, 14, SEEK_CUR);
+ is_raw *= get4();
+ off_head = get4();
+ off_setup = get4();
+ off_image = get4();
+ timestamp = get4();
+ if ((i = get4())) timestamp = i;
+ fseek (ifp, off_head+4, SEEK_SET);
+ raw_width = get4();
+ raw_height = get4();
+ switch (get2(),get2()) {
+ case 8: load_raw = &CLASS eight_bit_load_raw; break;
+ case 16: load_raw = &CLASS unpacked_load_raw;
+ }
+ fseek (ifp, off_setup+792, SEEK_SET);
+ strcpy (make, "CINE");
+ sprintf (model, "%d", get4());
+ fseek (ifp, 12, SEEK_CUR);
+ switch ((i=get4()) & 0xffffff) {
+ case 3: filters = 0x94949494; break;
+ case 4: filters = 0x49494949; break;
+ default: is_raw = 0;
+ }
+ fseek (ifp, 72, SEEK_CUR);
+ switch ((get4()+3600) % 360) {
+ case 270: flip = 4; break;
+ case 180: flip = 1; break;
+ case 90: flip = 7; break;
+ case 0: flip = 2;
+ }
+ cam_mul[0] = getreal(11);
+ cam_mul[2] = getreal(11);
+ maximum = ~(-1 << get4());
+ fseek (ifp, 668, SEEK_CUR);
+ shutter = get4()/1000000000.0;
+ fseek (ifp, off_image, SEEK_SET);
+ if (shot_select < is_raw)
+ fseek (ifp, shot_select*8, SEEK_CUR);
+ data_offset = (INT64) get4() + 8;
+ data_offset += (INT64) get4() << 32;
+}
+
+char * CLASS foveon_gets (int offset, char *str, int len)
+{
+ int i;
+ fseek (ifp, offset, SEEK_SET);
+ for (i=0; i < len-1; i++)
+ if ((str[i] = get2()) == 0) break;
+ str[i] = 0;
+ return str;
+}
+
+void CLASS parse_foveon()
+{
+ int entries, img=0, off, len, tag, save, i, wide, high, pent, poff[256][2];
+ char name[64], value[64];
+
+ order = 0x4949; /* Little-endian */
+ fseek (ifp, 36, SEEK_SET);
+ flip = get4();
+ fseek (ifp, -4, SEEK_END);
+ fseek (ifp, get4(), SEEK_SET);
+ if (get4() != 0x64434553) return; /* SECd */
+ entries = (get4(),get4());
+ while (entries--) {
+ off = get4();
+ len = get4();
+ tag = get4();
+ save = ftell(ifp);
+ fseek (ifp, off, SEEK_SET);
+ if (get4() != (0x20434553 | (tag << 24))) return;
+ switch (tag) {
+ case 0x47414d49: /* IMAG */
+ case 0x32414d49: /* IMA2 */
+ fseek (ifp, 12, SEEK_CUR);
+ wide = get4();
+ high = get4();
+ if (wide > raw_width && high > raw_height) {
+ raw_width = wide;
+ raw_height = high;
+ data_offset = off+24;
+ }
+ fseek (ifp, off+28, SEEK_SET);
+ if (fgetc(ifp) == 0xff && fgetc(ifp) == 0xd8
+ && thumb_length < len-28) {
+ thumb_offset = off+28;
+ thumb_length = len-28;
+ write_thumb = &CLASS jpeg_thumb;
+ }
+ if (++img == 2 && !thumb_length) {
+ thumb_offset = off+24;
+ thumb_width = wide;
+ thumb_height = high;
+ write_thumb = &CLASS foveon_thumb;
+ }
+ break;
+ case 0x464d4143: /* CAMF */
+ meta_offset = off+24;
+ meta_length = len-28;
+ if (meta_length > 0x20000)
+ meta_length = 0x20000;
+ break;
+ case 0x504f5250: /* PROP */
+ pent = (get4(),get4());
+ fseek (ifp, 12, SEEK_CUR);
+ off += pent*8 + 24;
+ if ((unsigned) pent > 256) pent=256;
+ for (i=0; i < pent*2; i++)
+ poff[0][i] = off + get4()*2;
+ for (i=0; i < pent; i++) {
+ foveon_gets (poff[i][0], name, 64);
+ foveon_gets (poff[i][1], value, 64);
+ if (!strcmp (name, "ISO"))
+ iso_speed = atoi(value);
+ if (!strcmp (name, "CAMMANUF"))
+ strcpy (make, value);
+ if (!strcmp (name, "CAMMODEL"))
+ strcpy (model, value);
+ if (!strcmp (name, "WB_DESC"))
+ strcpy (model2, value);
+ if (!strcmp (name, "TIME"))
+ timestamp = atoi(value);
+ if (!strcmp (name, "EXPTIME"))
+ shutter = atoi(value) / 1000000.0;
+ if (!strcmp (name, "APERTURE"))
+ aperture = atof(value);
+ if (!strcmp (name, "FLENGTH"))
+ focal_len = atof(value);
+ }
+#ifdef LOCALTIME
+ timestamp = mktime (gmtime (&timestamp));
+#endif
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ is_foveon = 1;
+}
+
+/*
+ Thanks to Adobe for providing these excellent CAM -> XYZ matrices!
+ */
+void CLASS adobe_coeff (char *make, char *model)
+{
+ static const struct {
+ const char *prefix;
+ short black, maximum, trans[12];
+ } table[] = {
+ { "Apple QuickTake", 0, 0, /* DJC */
+ { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } },
+ { "Canon EOS D2000", 0, 0,
+ { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+ { "Canon EOS D6000", 0, 0,
+ { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+ { "Canon EOS D30", 0, 0,
+ { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+ { "Canon EOS D60", 0, 0xfa0,
+ { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+ { "Canon EOS 5D Mark II", 0, 0x3cf0,
+ { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+ { "Canon EOS 5D", 0, 0xe6c,
+ { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+ { "Canon EOS 10D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 20Da", 0, 0,
+ { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+ { "Canon EOS 20D", 0, 0xfff,
+ { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+ { "Canon EOS 30D", 0, 0,
+ { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+ { "Canon EOS 40D", 0, 0x3f60,
+ { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+ { "Canon EOS 50D", 0, 0x3d93,
+ { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+ { "Canon EOS 300D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 350D", 0, 0xfff,
+ { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+ { "Canon EOS 400D", 0, 0xe8e,
+ { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+ { "Canon EOS 450D", 0, 0x390d,
+ { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+ { "Canon EOS 1000D", 0, 0xe43,
+ { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+ { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+ { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+ { "Canon EOS-1Ds Mark II", 0, 0xe80,
+ { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+ { "Canon EOS-1D Mark II N", 0, 0xe80,
+ { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+ { "Canon EOS-1D Mark III", 0, 0x3bb0,
+ { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+ { "Canon EOS-1D Mark II", 0, 0xe80,
+ { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+ { "Canon EOS-1DS", 0, 0xe20,
+ { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+ { "Canon EOS-1D", 0, 0xe20,
+ { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+ { "Canon EOS", 0, 0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon PowerShot A50", 0, 0,
+ { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+ { "Canon PowerShot A5", 0, 0,
+ { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+ { "Canon PowerShot G10", 0, 0,
+ { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+ { "Canon PowerShot G1", 0, 0,
+ { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+ { "Canon PowerShot G2", 0, 0,
+ { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+ { "Canon PowerShot G3", 0, 0,
+ { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+ { "Canon PowerShot G5", 0, 0,
+ { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+ { "Canon PowerShot G6", 0, 0,
+ { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+ { "Canon PowerShot G9", 0, 0,
+ { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+ { "Canon PowerShot Pro1", 0, 0,
+ { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+ { "Canon PowerShot Pro70", 34, 0,
+ { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+ { "Canon PowerShot Pro90", 0, 0,
+ { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+ { "Canon PowerShot S30", 0, 0,
+ { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+ { "Canon PowerShot S40", 0, 0,
+ { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+ { "Canon PowerShot S45", 0, 0,
+ { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+ { "Canon PowerShot S50", 0, 0,
+ { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+ { "Canon PowerShot S60", 0, 0,
+ { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+ { "Canon PowerShot S70", 0, 0,
+ { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+ { "Canon PowerShot A610", 0, 0, /* DJC */
+ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+ { "Canon PowerShot A620", 0, 0, /* DJC */
+ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+ { "Canon PowerShot A630", 0, 0, /* DJC */
+ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+ { "Canon PowerShot A640", 0, 0, /* DJC */
+ { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+ { "Canon PowerShot A650", 0, 0, /* DJC */
+ { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+ { "Canon PowerShot A720", 0, 0, /* DJC */
+ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+ { "Canon PowerShot S3 IS", 0, 0, /* DJC */
+ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+ { "CINE 650", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { "CINE 660", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { "CINE", 0, 0,
+ { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+ { "Contax N Digital", 0, 0xf1e,
+ { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+ { "EPSON R-D1", 0, 0,
+ { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+ { "FUJIFILM FinePix E550", 0, 0,
+ { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+ { "FUJIFILM FinePix E900", 0, 0,
+ { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+ { "FUJIFILM FinePix F8", 0, 0,
+ { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+ { "FUJIFILM FinePix F7", 0, 0,
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { "FUJIFILM FinePix S100FS", 514, 0,
+ { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+ { "FUJIFILM FinePix S20Pro", 0, 0,
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { "FUJIFILM FinePix S2Pro", 128, 0,
+ { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+ { "FUJIFILM FinePix S3Pro", 0, 0,
+ { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+ { "FUJIFILM FinePix S5Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+ { "FUJIFILM FinePix S5000", 0, 0,
+ { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+ { "FUJIFILM FinePix S5100", 0, 0x3e00,
+ { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+ { "FUJIFILM FinePix S5500", 0, 0x3e00,
+ { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+ { "FUJIFILM FinePix S5200", 0, 0,
+ { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+ { "FUJIFILM FinePix S5600", 0, 0,
+ { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+ { "FUJIFILM FinePix S6", 0, 0,
+ { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+ { "FUJIFILM FinePix S7000", 0, 0,
+ { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+ { "FUJIFILM FinePix S9000", 0, 0,
+ { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+ { "FUJIFILM FinePix S9500", 0, 0,
+ { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+ { "FUJIFILM FinePix S9100", 0, 0,
+ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+ { "FUJIFILM FinePix S9600", 0, 0,
+ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+ { "FUJIFILM IS-1", 0, 0,
+ { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+ { "FUJIFILM IS Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+ { "Imacon Ixpress", 0, 0, /* DJC */
+ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+ { "KODAK NC2000", 0, 0,
+ { 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+ { "Kodak DCS315C", 8, 0,
+ { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+ { "Kodak DCS330C", 8, 0,
+ { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+ { "KODAK DCS420", 0, 0,
+ { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+ { "KODAK DCS460", 0, 0,
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { "KODAK EOSDCS1", 0, 0,
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { "KODAK EOSDCS3B", 0, 0,
+ { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+ { "Kodak DCS520C", 180, 0,
+ { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+ { "Kodak DCS560C", 188, 0,
+ { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+ { "Kodak DCS620C", 180, 0,
+ { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+ { "Kodak DCS620X", 185, 0,
+ { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+ { "Kodak DCS660C", 214, 0,
+ { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+ { "Kodak DCS720X", 0, 0,
+ { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+ { "Kodak DCS760C", 0, 0,
+ { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+ { "Kodak DCS Pro SLR", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { "Kodak DCS Pro 14nx", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { "Kodak DCS Pro 14", 0, 0,
+ { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+ { "Kodak ProBack645", 0, 0,
+ { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+ { "Kodak ProBack", 0, 0,
+ { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+ { "KODAK P712", 0, 0,
+ { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+ { "KODAK P850", 0, 0xf7c,
+ { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+ { "KODAK P880", 0, 0xfff,
+ { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+ { "Leaf CMost", 0, 0,
+ { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+ { "Leaf Valeo 6", 0, 0,
+ { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+ { "Leaf Aptus 54S", 0, 0,
+ { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+ { "Leaf Aptus 65", 0, 0,
+ { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+ { "Leaf Aptus 75", 0, 0,
+ { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+ { "Leaf", 0, 0,
+ { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+ { "Mamiya ZD", 0, 0,
+ { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+ { "Micron 2010", 110, 0, /* DJC */
+ { 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+ { "Minolta DiMAGE 5", 0, 0xf7d,
+ { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+ { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+ { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+ { "Minolta DiMAGE 7", 0, 0xf7d,
+ { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+ { "Minolta DiMAGE A1", 0, 0xf8b,
+ { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+ { "MINOLTA DiMAGE A200", 0, 0,
+ { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+ { "Minolta DiMAGE A2", 0, 0xf8f,
+ { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+ { "Minolta DiMAGE Z2", 0, 0, /* DJC */
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+ { "MINOLTA DYNAX 5", 0, 0xffb,
+ { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+ { "MINOLTA DYNAX 7", 0, 0xffb,
+ { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+ { "NIKON D100", 0, 0,
+ { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+ { "NIKON D1H", 0, 0,
+ { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+ { "NIKON D1X", 0, 0,
+ { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+ { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+ { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+ { "NIKON D2H", 0, 0,
+ { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+ { "NIKON D2X", 0, 0,
+ { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+ { "NIKON D40X", 0, 0,
+ { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+ { "NIKON D40", 0, 0,
+ { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+ { "NIKON D50", 0, 0,
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { "NIKON D60", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { "NIKON D700", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "NIKON D70", 0, 0,
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { "NIKON D80", 0, 0,
+ { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+ { "NIKON D90", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+ { "NIKON D200", 0, 0xfbc,
+ { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+ { "NIKON D300", 0, 0,
+ { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+ { "NIKON D3", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "NIKON E950", 0, 0x3dd, /* DJC */
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+ { "NIKON E995", 0, 0, /* copied from E5000 */
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */
+ { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+ { "NIKON E2500", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+ { "NIKON E4500", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E5000", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E5400", 0, 0,
+ { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+ { "NIKON E5700", 0, 0,
+ { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+ { "NIKON E8400", 0, 0,
+ { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+ { "NIKON E8700", 0, 0,
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+ { "NIKON E8800", 0, 0,
+ { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+ { "NIKON COOLPIX P6000", 0, 0,
+ { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+ { "OLYMPUS C5050", 0, 0,
+ { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+ { "OLYMPUS C5060", 0, 0,
+ { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+ { "OLYMPUS C7070", 0, 0,
+ { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+ { "OLYMPUS C70", 0, 0,
+ { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+ { "OLYMPUS C80", 0, 0,
+ { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+ { "OLYMPUS E-10", 0, 0xffc0,
+ { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+ { "OLYMPUS E-1", 0, 0xfff0,
+ { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+ { "OLYMPUS E-20", 0, 0xffc0,
+ { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+ { "OLYMPUS E-300", 0, 0,
+ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+ { "OLYMPUS E-330", 0, 0,
+ { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+ { "OLYMPUS E-3", 0, 0xf99,
+ { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+ { "OLYMPUS E-400", 0, 0xfff0,
+ { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+ { "OLYMPUS E-410", 0, 0xf6a,
+ { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+ { "OLYMPUS E-420", 0, 0xfd7,
+ { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+ { "OLYMPUS E-500", 0, 0,
+ { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+ { "OLYMPUS E-510", 0, 0xf6a,
+ { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+ { "OLYMPUS E-520", 0, 0xfd2,
+ { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+ { "OLYMPUS SP350", 0, 0,
+ { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+ { "OLYMPUS SP3", 0, 0,
+ { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+ { "OLYMPUS SP500UZ", 0, 0xfff,
+ { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+ { "OLYMPUS SP510UZ", 0, 0xffe,
+ { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+ { "OLYMPUS SP550UZ", 0, 0xffe,
+ { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+ { "OLYMPUS SP560UZ", 0, 0xff9,
+ { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+ { "OLYMPUS SP570UZ", 0, 0,
+ { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+ { "PENTAX *ist DL2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "PENTAX *ist DL", 0, 0,
+ { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+ { "PENTAX *ist DS2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "PENTAX *ist DS", 0, 0,
+ { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+ { "PENTAX *ist D", 0, 0,
+ { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+ { "PENTAX K10D", 0, 0,
+ { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+ { "PENTAX K1", 0, 0,
+ { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+ { "PENTAX K20D", 0, 0,
+ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+ { "PENTAX K200D", 0, 0,
+ { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+ { "PENTAX K2000", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "PENTAX K-m", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "Panasonic DMC-FZ8", 0, 0xf7f0,
+ { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+ { "Panasonic DMC-FZ18", 0, 0,
+ { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+ { "Panasonic DMC-FZ28", 15, 0xfff,
+ { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+ { "Panasonic DMC-FZ30", 0, 0xf94c,
+ { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+ { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */
+ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+ { "Panasonic DMC-L10", 15, 0xf96,
+ { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+ { "Panasonic DMC-L1", 0, 0xf7fc, /* aka "LEICA DIGILUX 3" */
+ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+ { "Panasonic DMC-LC1", 0, 0, /* aka "LEICA DIGILUX 2" */
+ { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+ { "Panasonic DMC-LX1", 0, 0xf7f0, /* aka "LEICA D-LUX2" */
+ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+ { "Panasonic DMC-LX2", 0, 0, /* aka "LEICA D-LUX3" */
+ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+ { "Panasonic DMC-LX3", 15, 0xfff, /* aka "LEICA D-LUX4" */
+ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+ { "Panasonic DMC-FX150", 15, 0xfff,
+ { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+ { "Panasonic DMC-G1", 15, 0xfff,
+ { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+ { "Phase One H 20", 0, 0, /* DJC */
+ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+ { "Phase One P 2", 0, 0,
+ { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+ { "Phase One P 30", 0, 0,
+ { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+ { "Phase One P 45", 0, 0,
+ { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+ { "SAMSUNG GX-1", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "Sinar", 0, 0, /* DJC */
+ { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+ { "SONY DSC-F828", 491, 0,
+ { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+ { "SONY DSC-R1", 512, 0,
+ { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+ { "SONY DSC-V3", 0, 0,
+ { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+ { "SONY DSLR-A100", 0, 0xfeb,
+ { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+ { "SONY DSLR-A200", 0, 0,
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { "SONY DSLR-A300", 0, 0,
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { "SONY DSLR-A350", 0, 0xffc,
+ { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+ { "SONY DSLR-A700", 254, 0x1ffe,
+ { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+ { "SONY DSLR-A900", 254, 0x1ffe,
+ { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+ };
+ double cam_xyz[4][3];
+ char name[130];
+ int i, j;
+
+ sprintf (name, "%s %s", make, model);
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+ if (table[i].black) black = (ushort) table[i].black;
+ if (table[i].maximum) maximum = (ushort) table[i].maximum;
+ for (j=0; j < 12; j++)
+ cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+ cam_xyz_coeff (cam_xyz);
+ break;
+ }
+}
+
+void CLASS simple_coeff (int index)
+{
+ static const float table[][12] = {
+ /* index 0 -- all Foveon cameras */
+ { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+ /* index 1 -- Kodak DC20 and DC25 */
+ { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+ /* index 2 -- Logitech Fotoman Pixtura */
+ { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+ /* index 3 -- Nikon E880, E900, and E990 */
+ { -1.936280, 1.800443, -1.448486, 2.584324,
+ 1.405365, -0.524955, -0.289090, 0.408680,
+ -1.204965, 1.082304, 2.941367, -1.818705 }
+ };
+ int i, c;
+
+ for (raw_color = i=0; i < 3; i++)
+ FORCC rgb_cam[i][c] = table[index][i*colors+c];
+}
+
+short CLASS guess_byte_order (int words)
+{
+ uchar test[4][2];
+ int t=2, msb;
+ double diff, sum[2] = {0,0};
+
+ fread (test[0], 2, 2, ifp);
+ for (words-=2; words--; ) {
+ fread (test[t], 2, 1, ifp);
+ for (msb=0; msb < 2; msb++) {
+ diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+ - (test[t ][msb] << 8 | test[t ][!msb]);
+ sum[msb] += diff*diff;
+ }
+ t = (t+1) & 3;
+ }
+ return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+/*
+ Identify which camera created this file, and set global variables
+ accordingly.
+ */
+void CLASS identify()
+{
+ char head[32], *cp;
+ unsigned hlen, fsize, i, c, is_canon;
+ struct jhead jh;
+ static const struct {
+ int fsize;
+ char make[12], model[19], withjpeg;
+ } table[] = {
+ { 62464, "Kodak", "DC20" ,0 },
+ { 124928, "Kodak", "DC20" ,0 },
+ { 1652736, "Kodak", "DCS200" ,0 },
+ { 4159302, "Kodak", "C330" ,0 },
+ { 4162462, "Kodak", "C330" ,0 },
+ { 460800, "Kodak", "C603v" ,0 },
+ { 614400, "Kodak", "C603v" ,0 },
+ { 6163328, "Kodak", "C603" ,0 },
+ { 6166488, "Kodak", "C603" ,0 },
+ { 9116448, "Kodak", "C603y" ,0 },
+ { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
+ { 614400, "Kodak", "KAI-0340" ,0 },
+ { 787456, "Creative", "PC-CAM 600" ,0 },
+ { 1138688, "Minolta", "RD175" ,0 },
+ { 3840000, "Foculus", "531C" ,0 },
+ { 786432, "AVT", "F-080C" ,0 },
+ { 1447680, "AVT", "F-145C" ,0 },
+ { 1920000, "AVT", "F-201C" ,0 },
+ { 5067304, "AVT", "F-510C" ,0 },
+ { 10134608, "AVT", "F-510C" ,0 },
+ { 16157136, "AVT", "F-810C" ,0 },
+ { 1409024, "Sony", "XCD-SX910CR" ,0 },
+ { 2818048, "Sony", "XCD-SX910CR" ,0 },
+ { 3884928, "Micron", "2010" ,0 },
+ { 6624000, "Pixelink", "A782" ,0 },
+ { 13248000, "Pixelink", "A782" ,0 },
+ { 6291456, "RoverShot","3320AF" ,0 },
+ { 6553440, "Canon", "PowerShot A460" ,0 },
+ { 6653280, "Canon", "PowerShot A530" ,0 },
+ { 6573120, "Canon", "PowerShot A610" ,0 },
+ { 9219600, "Canon", "PowerShot A620" ,0 },
+ { 10341600, "Canon", "PowerShot A720" ,0 },
+ { 10383120, "Canon", "PowerShot A630" ,0 },
+ { 12945240, "Canon", "PowerShot A640" ,0 },
+ { 15636240, "Canon", "PowerShot A650" ,0 },
+ { 5298000, "Canon", "PowerShot SD300" ,0 },
+ { 7710960, "Canon", "PowerShot S3 IS" ,0 },
+ { 5939200, "OLYMPUS", "C770UZ" ,0 },
+ { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
+ { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
+ { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
+ { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
+ { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
+ { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
+ { 5865472, "NIKON", "E4500" ,1 },
+ { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
+ { 8998912, "NIKON", "COOLPIX S6" ,1 },
+ { 1976352, "CASIO", "QV-2000UX" ,1 },
+ { 3217760, "CASIO", "QV-3*00EX" ,1 },
+ { 6218368, "CASIO", "QV-5700" ,1 },
+ { 6054400, "CASIO", "QV-R41" ,1 },
+ { 7530816, "CASIO", "QV-R51" ,1 },
+ { 7684000, "CASIO", "QV-4000" ,1 },
+ { 4948608, "CASIO", "EX-S100" ,1 },
+ { 7542528, "CASIO", "EX-Z50" ,1 },
+ { 7753344, "CASIO", "EX-Z55" ,1 },
+ { 7426656, "CASIO", "EX-P505" ,1 },
+ { 9313536, "CASIO", "EX-P600" ,1 },
+ { 10979200, "CASIO", "EX-P700" ,1 },
+ { 3178560, "PENTAX", "Optio S" ,1 },
+ { 4841984, "PENTAX", "Optio S" ,1 },
+ { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
+ { 10702848, "PENTAX", "Optio 750Z" ,1 },
+ { 16098048, "SAMSUNG", "S85" ,1 },
+ { 16215552, "SAMSUNG", "S85" ,1 },
+ { 12582980, "Sinar", "" ,0 },
+ { 33292868, "Sinar", "" ,0 },
+ { 44390468, "Sinar", "" ,0 } };
+ static const char *corp[] =
+ { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+ "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+ "SAMSUNG", "Mamiya" };
+
+ tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */
+ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+ maximum = height = width = top_margin = left_margin = 0;
+ cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+ iso_speed = shutter = aperture = focal_len = unique_id = 0;
+ memset (gpsdata, 0, sizeof gpsdata);
+ memset (white, 0, sizeof white);
+ thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+ load_raw = thumb_load_raw = 0;
+ write_thumb = &CLASS jpeg_thumb;
+ data_offset = meta_length = tiff_bps = tiff_compress = 0;
+ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+ timestamp = shot_order = tiff_samples = black = is_foveon = 0;
+ mix_green = profile_length = data_error = zero_is_bad = 0;
+ pixel_aspect = is_raw = raw_color = use_gamma = 1;
+ tile_width = tile_length = INT_MAX;
+ for (i=0; i < 4; i++) {
+ cam_mul[i] = i == 1;
+ pre_mul[i] = i < 3;
+ FORC3 cmatrix[c][i] = 0;
+ FORC3 rgb_cam[c][i] = c == i;
+ }
+ colors = 3;
+ tiff_bps = 12;
+ for (i=0; i < 0x4000; i++) curve[i] = i;
+
+ order = get2();
+ hlen = get4();
+ fseek (ifp, 0, SEEK_SET);
+ fread (head, 1, 32, ifp);
+ fseek (ifp, 0, SEEK_END);
+ fsize = ftell(ifp);
+ if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
+ (cp = (char *) memmem (head, 32, "IIII", 4))) {
+ parse_phase_one (cp-head);
+ if (cp-head) parse_tiff(0);
+ } else if (order == 0x4949 || order == 0x4d4d) {
+ if (!memcmp (head+6,"HEAPCCDR",8)) {
+ data_offset = hlen;
+ parse_ciff (hlen, fsize - hlen);
+ } else {
+ parse_tiff(0);
+ }
+ } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+ !memcmp (head+6,"Exif",4)) {
+ fseek (ifp, 4, SEEK_SET);
+ data_offset = 4 + get2();
+ fseek (ifp, data_offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff)
+ parse_tiff(12);
+ thumb_offset = 0;
+ } else if (!memcmp (head+25,"ARECOYK",7)) {
+ strcpy (make, "Contax");
+ strcpy (model,"N Digital");
+ fseek (ifp, 33, SEEK_SET);
+ get_timestamp(1);
+ fseek (ifp, 60, SEEK_SET);
+ FORC4 cam_mul[c ^ (c >> 1)] = get4();
+ } else if (!strcmp (head, "PXN")) {
+ strcpy (make, "Logitech");
+ strcpy (model,"Fotoman Pixtura");
+ } else if (!strcmp (head, "qktk")) {
+ strcpy (make, "Apple");
+ strcpy (model,"QuickTake 100");
+ } else if (!strcmp (head, "qktn")) {
+ strcpy (make, "Apple");
+ strcpy (model,"QuickTake 150");
+ } else if (!memcmp (head,"FUJIFILM",8)) {
+ fseek (ifp, 84, SEEK_SET);
+ thumb_offset = get4();
+ thumb_length = get4();
+ fseek (ifp, 92, SEEK_SET);
+ parse_fuji (get4());
+ if (thumb_offset > 120) {
+ fseek (ifp, 120, SEEK_SET);
+ is_raw += (i = get4()) && 1;
+ if (is_raw == 2 && shot_select)
+ parse_fuji (i);
+ }
+ fseek (ifp, 100, SEEK_SET);
+ data_offset = get4();
+ parse_tiff (thumb_offset+12);
+ } else if (!memcmp (head,"RIFF",4)) {
+ fseek (ifp, 0, SEEK_SET);
+ parse_riff();
+ } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+ fseek (ifp, 6, SEEK_SET);
+ fread (make, 1, 8, ifp);
+ fread (model, 1, 8, ifp);
+ fread (model2, 1, 16, ifp);
+ data_offset = get2();
+ get2();
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &CLASS nokia_load_raw;
+ filters = 0x61616161;
+ } else if (!memcmp (head,"DSC-Image",9))
+ parse_rollei();
+ else if (!memcmp (head,"PWAD",4))
+ parse_sinar_ia();
+ else if (!memcmp (head,"\0MRM",4))
+ parse_minolta(0);
+ else if (!memcmp (head,"FOVb",4))
+ parse_foveon();
+ else if (!memcmp (head,"CI",2))
+ parse_cine();
+ else
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (fsize == table[i].fsize) {
+ strcpy (make, table[i].make );
+ strcpy (model, table[i].model);
+ if (table[i].withjpeg)
+ parse_external_jpeg();
+ }
+ if (make[0] == 0) parse_smal (0, fsize);
+ if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+ for (i=0; i < sizeof corp / sizeof *corp; i++)
+ if (strstr (make, corp[i])) /* Simplify company names */
+ strcpy (make, corp[i]);
+ if (!strncmp (make,"KODAK",5))
+ make[16] = model[16] = 0;
+ cp = make + strlen(make); /* Remove trailing spaces */
+ while (*--cp == ' ') *cp = 0;
+ cp = model + strlen(model);
+ while (*--cp == ' ') *cp = 0;
+ i = strlen(make); /* Remove make from model */
+ if (!strncasecmp (model, make, i) && model[i++] == ' ')
+ memmove (model, model+i, 64-i);
+ if (!strncmp (model,"Digital Camera ",15))
+ strcpy (model, model+15);
+ desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+ if (!is_raw) goto notraw;
+
+ if (!maximum) maximum = (1 << tiff_bps) - 1;
+ if (!height) height = raw_height;
+ if (!width) width = raw_width;
+ if (fuji_width) {
+ width = height + fuji_width;
+ height = width - 1;
+ pixel_aspect = 1;
+ }
+ if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */
+ { height = 2616; width = 3896; }
+ if (height == 3136 && width == 4864) /* Pentax K20D */
+ { height = 3124; width = 4688; }
+ if (height == 3014 && width == 4096) /* Ricoh GX200 */
+ width = 4014;
+ if (dng_version) {
+ if (filters == UINT_MAX) filters = 0;
+ if (filters) is_raw = tiff_samples;
+ else colors = tiff_samples;
+ if (tiff_compress == 1)
+ load_raw = &CLASS adobe_dng_load_raw_nc;
+ if (tiff_compress == 7)
+ load_raw = &CLASS adobe_dng_load_raw_lj;
+ goto dng_skip;
+ }
+ if ((is_canon = !strcmp(make,"Canon")))
+ load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+ &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+ if (!strcmp(make,"NIKON")) {
+ if (!load_raw)
+ load_raw = &CLASS packed_12_load_raw;
+ if (model[0] == 'E')
+ load_flags |= !data_offset << 2 | 2;
+ }
+ if (!strcmp(make,"CASIO")) {
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7f;
+ }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+ if (is_foveon) {
+ if (height*2 < width) pixel_aspect = 0.5;
+ if (height > width) pixel_aspect = 2;
+ filters = 0;
+ load_raw = &CLASS foveon_load_raw;
+ simple_coeff(0);
+ } else if (is_canon && tiff_bps == 15) {
+ switch (width) {
+ case 3344: width -= 66;
+ case 3872: width -= 6;
+ }
+ filters = 0;
+ load_raw = &CLASS canon_sraw_load_raw;
+ } else if (!strcmp(model,"PowerShot 600")) {
+ height = 613;
+ width = 854;
+ raw_width = 896;
+ pixel_aspect = 607/628.0;
+ colors = 4;
+ filters = 0xe1e4e1e4;
+ load_raw = &CLASS canon_600_load_raw;
+ } else if (!strcmp(model,"PowerShot A5") ||
+ !strcmp(model,"PowerShot A5 Zoom")) {
+ height = 773;
+ width = 960;
+ raw_width = 992;
+ pixel_aspect = 256/235.0;
+ colors = 4;
+ filters = 0x1e4e1e4e;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A50")) {
+ height = 968;
+ width = 1290;
+ raw_width = 1320;
+ colors = 4;
+ filters = 0x1b4e4b1e;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot Pro70")) {
+ height = 1024;
+ width = 1552;
+ colors = 4;
+ filters = 0x1e4b4e1b;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot SD300")) {
+ height = 1752;
+ width = 2344;
+ raw_height = 1766;
+ raw_width = 2400;
+ top_margin = 12;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A460")) {
+ height = 1960;
+ width = 2616;
+ raw_height = 1968;
+ raw_width = 2664;
+ top_margin = 4;
+ left_margin = 4;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A530")) {
+ height = 1984;
+ width = 2620;
+ raw_height = 1992;
+ raw_width = 2672;
+ top_margin = 6;
+ left_margin = 10;
+ load_raw = &CLASS canon_a5_load_raw;
+ raw_color = 0;
+ } else if (!strcmp(model,"PowerShot A610")) {
+ if (canon_s2is()) strcpy (model+10, "S2 IS");
+ height = 1960;
+ width = 2616;
+ raw_height = 1968;
+ raw_width = 2672;
+ top_margin = 8;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A620")) {
+ height = 2328;
+ width = 3112;
+ raw_height = 2340;
+ raw_width = 3152;
+ top_margin = 12;
+ left_margin = 36;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A720")) {
+ height = 2472;
+ width = 3298;
+ raw_height = 2480;
+ raw_width = 3336;
+ top_margin = 5;
+ left_margin = 6;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A630")) {
+ height = 2472;
+ width = 3288;
+ raw_height = 2484;
+ raw_width = 3344;
+ top_margin = 6;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A640")) {
+ height = 2760;
+ width = 3672;
+ raw_height = 2772;
+ raw_width = 3736;
+ top_margin = 6;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A650")) {
+ height = 3024;
+ width = 4032;
+ raw_height = 3048;
+ raw_width = 4104;
+ top_margin = 12;
+ left_margin = 48;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot S3 IS")) {
+ height = 2128;
+ width = 2840;
+ raw_height = 2136;
+ raw_width = 2888;
+ top_margin = 8;
+ left_margin = 44;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+ width = 1896;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (is_canon && raw_width == 2144) {
+ height = 1550;
+ width = 2088;
+ top_margin = 8;
+ left_margin = 4;
+ if (!strcmp(model,"PowerShot G1")) {
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ }
+ } else if (is_canon && raw_width == 2224) {
+ height = 1448;
+ width = 2176;
+ top_margin = 6;
+ left_margin = 48;
+ } else if (is_canon && raw_width == 2376) {
+ height = 1720;
+ width = 2312;
+ top_margin = 6;
+ left_margin = 12;
+ } else if (is_canon && raw_width == 2672) {
+ height = 1960;
+ width = 2616;
+ top_margin = 6;
+ left_margin = 12;
+ } else if (is_canon && raw_width == 3152) {
+ height = 2056;
+ width = 3088;
+ top_margin = 12;
+ left_margin = 64;
+ if (unique_id == 0x80000170)
+ adobe_coeff ("Canon","EOS 300D");
+ } else if (is_canon && raw_width == 3160) {
+ height = 2328;
+ width = 3112;
+ top_margin = 12;
+ left_margin = 44;
+ } else if (is_canon && raw_width == 3344) {
+ height = 2472;
+ width = 3288;
+ top_margin = 6;
+ left_margin = 4;
+ } else if (!strcmp(model,"EOS D2000C")) {
+ filters = 0x61616161;
+ black = curve[200];
+ } else if (is_canon && raw_width == 3516) {
+ top_margin = 14;
+ left_margin = 42;
+ if (unique_id == 0x80000189)
+ adobe_coeff ("Canon","EOS 350D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3596) {
+ top_margin = 12;
+ left_margin = 74;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3944) {
+ height = 2602;
+ width = 3908;
+ top_margin = 18;
+ left_margin = 30;
+ } else if (is_canon && raw_width == 3948) {
+ top_margin = 18;
+ left_margin = 42;
+ height -= 2;
+ if (unique_id == 0x80000236)
+ adobe_coeff ("Canon","EOS 400D");
+ if (unique_id == 0x80000254)
+ adobe_coeff ("Canon","EOS 1000D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3984) {
+ top_margin = 20;
+ left_margin = 76;
+ height -= 2;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4104) {
+ height = 3024;
+ width = 4032;
+ top_margin = 12;
+ left_margin = 48;
+ } else if (is_canon && raw_width == 4312) {
+ top_margin = 18;
+ left_margin = 22;
+ height -= 2;
+ if (unique_id == 0x80000176)
+ adobe_coeff ("Canon","EOS 450D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4476) {
+ top_margin = 34;
+ left_margin = 90;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4480) {
+ height = 3326;
+ width = 4432;
+ top_margin = 10;
+ left_margin = 12;
+ filters = 0x49494949;
+ } else if (is_canon && raw_width == 1208) {
+ top_margin = 51;
+ left_margin = 62;
+ raw_width = width *= 4;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 1448) {
+ top_margin = 51;
+ left_margin = 158;
+ raw_width = width *= 4;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 5108) {
+ top_margin = 13;
+ left_margin = 98;
+canon_cr2:
+ height -= top_margin;
+ width -= left_margin;
+ } else if (is_canon && raw_width == 5712) {
+ height = 3752;
+ width = 5640;
+ top_margin = 20;
+ left_margin = 62;
+ } else if (!strcmp(model,"D1")) {
+ cam_mul[0] *= 256/527.0;
+ cam_mul[2] *= 256/317.0;
+ } else if (!strcmp(model,"D1X")) {
+ width -= 4;
+ pixel_aspect = 0.5;
+ } else if (!strcmp(model,"D40X") ||
+ !strcmp(model,"D60") ||
+ !strcmp(model,"D80")) {
+ height -= 3;
+ width -= 4;
+ } else if (!strcmp(model,"D3") ||
+ !strcmp(model,"D700")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strncmp(model,"D40",3) ||
+ !strncmp(model,"D50",3) ||
+ !strncmp(model,"D70",3)) {
+ width--;
+ } else if (!strcmp(model,"D90")) {
+ width -= 42;
+ } else if (!strcmp(model,"D100")) {
+ if (tiff_compress == 34713 && !nikon_is_compressed()) {
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags |= 8;
+ raw_width = (width += 3) + 3;
+ }
+ } else if (!strcmp(model,"D200")) {
+ left_margin = 1;
+ width -= 4;
+ filters = 0x94949494;
+ } else if (!strncmp(model,"D2H",3)) {
+ left_margin = 6;
+ width -= 14;
+ } else if (!strncmp(model,"D2X",3)) {
+ if (width == 3264) width -= 32;
+ else width -= 8;
+ } else if (!strcmp(model,"D300")) {
+ width -= 32;
+ } else if (!strcmp(model,"COOLPIX P6000")) {
+ load_flags = 1;
+ filters = 0x94949494;
+ } else if (fsize == 1581060) {
+ height = 963;
+ width = 1287;
+ raw_width = 1632;
+ load_raw = &CLASS nikon_e900_load_raw;
+ maximum = 0x3f4;
+ colors = 4;
+ filters = 0x1e1e1e1e;
+ simple_coeff(3);
+ pre_mul[0] = 1.2085;
+ pre_mul[1] = 1.0943;
+ pre_mul[3] = 1.1103;
+ } else if (fsize == 2465792) {
+ height = 1203;
+ width = 1616;
+ raw_width = 2048;
+ load_raw = &CLASS nikon_e900_load_raw;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ adobe_coeff ("NIKON","E950");
+ } else if (fsize == 4771840) {
+ height = 1540;
+ width = 2064;
+ colors = 4;
+ filters = 0xe1e1e1e1;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 6;
+ if (!timestamp && nikon_e995())
+ strcpy (model, "E995");
+ if (strcmp(model,"E995")) {
+ filters = 0xb4b4b4b4;
+ simple_coeff(3);
+ pre_mul[0] = 1.196;
+ pre_mul[1] = 1.246;
+ pre_mul[2] = 1.018;
+ }
+ } else if (!strcmp(model,"E2100")) {
+ if (!timestamp && !nikon_e2100()) goto cp_e2500;
+ height = 1206;
+ width = 1616;
+ load_flags = 7;
+ } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+ strcpy (model, "E2500");
+ height = 1204;
+ width = 1616;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ } else if (fsize == 4775936) {
+ height = 1542;
+ width = 2064;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ pre_mul[0] = 1.818;
+ pre_mul[2] = 1.618;
+ if (!timestamp) nikon_3700();
+ if (model[0] == 'E' && atoi(model+1) < 3700)
+ filters = 0x49494949;
+ if (!strcmp(model,"Optio 33WR")) {
+ flip = 1;
+ filters = 0x16161616;
+ pre_mul[0] = 1.331;
+ pre_mul[2] = 1.820;
+ }
+ } else if (fsize == 5869568) {
+ height = 1710;
+ width = 2288;
+ filters = 0x16161616;
+ if (!timestamp && minolta_z2()) {
+ strcpy (make, "Minolta");
+ strcpy (model,"DiMAGE Z2");
+ }
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 6 + (make[0] == 'M');
+ } else if (!strcmp(model,"E4500")) {
+ height = 1708;
+ width = 2288;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (fsize == 7438336) {
+ height = 1924;
+ width = 2576;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (fsize == 8998912) {
+ height = 2118;
+ width = 2832;
+ maximum = 0xf83;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(model,"FinePix S5100") ||
+ !strcmp(model,"FinePix S5500")) {
+ load_raw = &CLASS unpacked_load_raw;
+ } else if (!strcmp(make,"FUJIFILM")) {
+ if (!strcmp(model+7,"S2Pro")) {
+ strcpy (model+7," S2Pro");
+ height = 2144;
+ width = 2880;
+ flip = 6;
+ } else
+ maximum = 0x3e00;
+ if (is_raw == 2 && shot_select)
+ maximum = 0x2f00;
+ top_margin = (raw_height - height)/2;
+ left_margin = (raw_width - width )/2;
+ if (is_raw == 2)
+ data_offset += (shot_select > 0) * ( fuji_layout ?
+ (raw_width *= 2) : raw_height*raw_width*2 );
+ fuji_width = width >> !fuji_layout;
+ width = (height >> fuji_layout) + fuji_width;
+ raw_height = height;
+ height = width - 1;
+ load_raw = &CLASS fuji_load_raw;
+ if (!(fuji_width & 1)) filters = 0x49494949;
+ } else if (!strcmp(model,"RD175")) {
+ height = 986;
+ width = 1534;
+ data_offset = 513;
+ filters = 0x61616161;
+ load_raw = &CLASS minolta_rd175_load_raw;
+ } else if (!strcmp(model,"KD-400Z")) {
+ height = 1712;
+ width = 2312;
+ raw_width = 2336;
+ goto konica_400z;
+ } else if (!strcmp(model,"KD-510Z")) {
+ goto konica_510z;
+ } else if (!strcasecmp(make,"MINOLTA")) {
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xfff;
+ if (!strncmp(model,"DiMAGE A",8)) {
+ if (!strcmp(model,"DiMAGE A200"))
+ filters = 0x49494949;
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strncmp(model,"ALPHA",5) ||
+ !strncmp(model,"DYNAX",5) ||
+ !strncmp(model,"MAXXUM",6)) {
+ sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+ adobe_coeff (make, model+20);
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strncmp(model,"DiMAGE G",8)) {
+ if (model[8] == '4') {
+ height = 1716;
+ width = 2304;
+ } else if (model[8] == '5') {
+konica_510z:
+ height = 1956;
+ width = 2607;
+ raw_width = 2624;
+ } else if (model[8] == '6') {
+ height = 2136;
+ width = 2848;
+ }
+ data_offset += 14;
+ filters = 0x61616161;
+konica_400z:
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3df;
+ order = 0x4d4d;
+ }
+ } else if (!strcmp(model,"*ist DS")) {
+ height -= 2;
+ } else if (!strcmp(model,"K20D")) {
+ filters = 0x16161616;
+ } else if (!strcmp(model,"Optio S")) {
+ if (fsize == 3178560) {
+ height = 1540;
+ width = 2064;
+ load_raw = &CLASS eight_bit_load_raw;
+ cam_mul[0] *= 4;
+ cam_mul[2] *= 4;
+ pre_mul[0] = 1.391;
+ pre_mul[2] = 1.188;
+ } else {
+ height = 1544;
+ width = 2068;
+ raw_width = 3136;
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7c;
+ pre_mul[0] = 1.137;
+ pre_mul[2] = 1.453;
+ }
+ } else if (fsize == 6114240) {
+ height = 1737;
+ width = 2324;
+ raw_width = 3520;
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7a;
+ pre_mul[0] = 1.980;
+ pre_mul[2] = 1.570;
+ } else if (!strcmp(model,"Optio 750Z")) {
+ height = 2302;
+ width = 3072;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(model,"S85")) {
+ height = 2448;
+ width = 3264;
+ raw_width = fsize/height/2;
+ order = 0x4d4d;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xffff;
+ } else if (!strcmp(model,"STV680 VGA")) {
+ height = 484;
+ width = 644;
+ load_raw = &CLASS eight_bit_load_raw;
+ flip = 2;
+ filters = 0x16161616;
+ black = 16;
+ pre_mul[0] = 1.097;
+ pre_mul[2] = 1.128;
+ } else if (!strcmp(model,"KAI-0340")) {
+ height = 477;
+ width = 640;
+ order = 0x4949;
+ data_offset = 3840;
+ load_raw = &CLASS unpacked_load_raw;
+ pre_mul[0] = 1.561;
+ pre_mul[2] = 2.454;
+ } else if (!strcmp(model,"N95")) {
+ height = raw_height - (top_margin = 2);
+ } else if (!strcmp(model,"531C")) {
+ height = 1200;
+ width = 1600;
+ load_raw = &CLASS unpacked_load_raw;
+ filters = 0x49494949;
+ pre_mul[1] = 1.218;
+ } else if (!strcmp(model,"F-080C")) {
+ height = 768;
+ width = 1024;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-145C")) {
+ height = 1040;
+ width = 1392;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-201C")) {
+ height = 1200;
+ width = 1600;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-510C")) {
+ height = 1958;
+ width = 2588;
+ load_raw = fsize < 7500000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ maximum = 0xfff0;
+ } else if (!strcmp(model,"F-810C")) {
+ height = 2469;
+ width = 3272;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xfff0;
+ } else if (!strcmp(model,"XCD-SX910CR")) {
+ height = 1024;
+ width = 1375;
+ raw_width = 1376;
+ filters = 0x49494949;
+ maximum = 0x3ff;
+ load_raw = fsize < 2000000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ } else if (!strcmp(model,"2010")) {
+ height = 1207;
+ width = 1608;
+ order = 0x4949;
+ filters = 0x16161616;
+ data_offset = 3212;
+ maximum = 0x3ff;
+ load_raw = &CLASS unpacked_load_raw;
+ } else if (!strcmp(model,"A782")) {
+ height = 3000;
+ width = 2208;
+ filters = 0x61616161;
+ load_raw = fsize < 10000000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ maximum = 0xffc0;
+ } else if (!strcmp(model,"3320AF")) {
+ height = 1536;
+ raw_width = width = 2048;
+ filters = 0x61616161;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3ff;
+ pre_mul[0] = 1.717;
+ pre_mul[2] = 1.138;
+ fseek (ifp, 0x300000, SEEK_SET);
+ if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+ height -= (top_margin = 16);
+ width -= (left_margin = 28);
+ maximum = 0xf5c0;
+ strcpy (make, "ISG");
+ model[0] = 0;
+ }
+ } else if (!strcmp(make,"Hasselblad")) {
+ if (load_raw == &CLASS lossless_jpeg_load_raw)
+ load_raw = &CLASS hasselblad_load_raw;
+ if (raw_width == 7262) {
+ height = 5444;
+ width = 7248;
+ top_margin = 4;
+ left_margin = 7;
+ filters = 0x61616161;
+ } else if (raw_width == 4090) {
+ strcpy (model, "V96C");
+ height -= (top_margin = 6);
+ width -= (left_margin = 3) + 7;
+ filters = 0x61616161;
+ }
+ } else if (!strcmp(make,"Sinar")) {
+ if (!memcmp(head,"8BPS",4)) {
+ fseek (ifp, 14, SEEK_SET);
+ height = get4();
+ width = get4();
+ filters = 0x61616161;
+ data_offset = 68;
+ }
+ if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3fff;
+ } else if (!strcmp(make,"Leaf")) {
+ maximum = 0x3fff;
+ fseek (ifp, data_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1) && jh.bits == 15)
+ maximum = 0x1fff;
+ if (tiff_samples > 1) filters = 0;
+ if (tiff_samples > 1 || tile_length < raw_height)
+ load_raw = &CLASS leaf_hdr_load_raw;
+ if ((width | height) == 2048) {
+ if (tiff_samples == 1) {
+ filters = 1;
+ strcpy (cdesc, "RBTG");
+ strcpy (model, "CatchLight");
+ top_margin = 8; left_margin = 18; height = 2032; width = 2016;
+ } else {
+ strcpy (model, "DCB2");
+ top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+ }
+ } else if (width+height == 3144+2060) {
+ if (!model[0]) strcpy (model, "Cantare");
+ if (width > height) {
+ top_margin = 6; left_margin = 32; height = 2048; width = 3072;
+ filters = 0x61616161;
+ } else {
+ left_margin = 6; top_margin = 32; width = 2048; height = 3072;
+ filters = 0x16161616;
+ }
+ if (!cam_mul[0] || model[0] == 'V') filters = 0;
+ else is_raw = tiff_samples;
+ } else if (width == 2116) {
+ strcpy (model, "Valeo 6");
+ height -= 2 * (top_margin = 30);
+ width -= 2 * (left_margin = 55);
+ filters = 0x49494949;
+ } else if (width == 3171) {
+ strcpy (model, "Valeo 6");
+ height -= 2 * (top_margin = 24);
+ width -= 2 * (left_margin = 24);
+ filters = 0x16161616;
+ }
+ } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+ maximum = 0xfff0;
+ if ((fsize-data_offset) / (width*8/7) == height)
+ load_raw = &CLASS panasonic_load_raw;
+ if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+ switch (width) {
+ case 2568:
+ adobe_coeff ("Panasonic","DMC-LC1"); break;
+ case 3130:
+ left_margin = -14;
+ case 3170:
+ left_margin += 18;
+ width = 3096;
+ if (height > 2326) {
+ height = 2326;
+ top_margin = 13;
+ filters = 0x49494949;
+ }
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ8"); break;
+ case 3213:
+ width -= 27;
+ case 3177:
+ width -= 10;
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-L1"); break;
+ case 3304:
+ width -= 17;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ30"); break;
+ case 3330:
+ width += 43;
+ left_margin = -6;
+ maximum = 0xf7f0;
+ case 3370:
+ width -= 82;
+ left_margin += 15;
+ if (height > 2480)
+ height = 2480 - (top_margin = 10);
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ18"); break;
+ case 3690:
+ height -= 2;
+ left_margin = -14;
+ maximum = 0xf7f0;
+ case 3770:
+ width = 3672;
+ if (--height == 2798 && (height = 2760))
+ top_margin = 15;
+ else filters = 0x49494949;
+ left_margin += 17;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ50"); break;
+ case 3710:
+ width = 3682;
+ filters = 0x49494949;
+ adobe_coeff ("Panasonic","DMC-L10"); break;
+ case 3724:
+ width -= 14;
+ case 3836:
+ width -= 42;
+lx3: filters = 0x16161616;
+ if (make[0] != 'P')
+ adobe_coeff ("Panasonic","DMC-LX3");
+ break;
+ case 3880:
+ width -= 22;
+ left_margin = 6;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-LX1"); break;
+ case 4060:
+ width = 3982;
+ if (height == 2250) goto lx3;
+ width = 4018;
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-G1"); break;
+ case 4290:
+ height += 38;
+ left_margin = -14;
+ filters = 0x49494949;
+ case 4330:
+ width = 4248;
+ if ((height -= 39) == 2400)
+ top_margin = 15;
+ left_margin += 17;
+ adobe_coeff ("Panasonic","DMC-LX2"); break;
+ case 4508:
+ height -= 6;
+ width = 4429;
+ filters = 0x16161616;
+ adobe_coeff ("Panasonic","DMC-FX150"); break;
+ }
+ } else if (!strcmp(model,"C770UZ")) {
+ height = 1718;
+ width = 2304;
+ filters = 0x16161616;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(make,"OLYMPUS")) {
+ height += height & 1;
+ filters = exif_cfa;
+ if (load_raw == &CLASS olympus_e410_load_raw) {
+ black >>= 4;
+ } else if (!strcmp(model,"E-10") ||
+ !strncmp(model,"E-20",4)) {
+ black <<= 2;
+ } else if (!strcmp(model,"E-300") ||
+ !strcmp(model,"E-500")) {
+ width -= 20;
+ if (load_raw == &CLASS unpacked_load_raw) {
+ maximum = 0xfc30;
+ black = 0;
+ }
+ } else if (!strcmp(model,"E-330")) {
+ width -= 30;
+ if (load_raw == &CLASS unpacked_load_raw)
+ maximum = 0xf790;
+ } else if (!strcmp(model,"SP550UZ")) {
+ thumb_length = fsize - (thumb_offset = 0xa39800);
+ thumb_height = 480;
+ thumb_width = 640;
+ }
+ } else if (!strcmp(model,"N Digital")) {
+ height = 2047;
+ width = 3072;
+ filters = 0x61616161;
+ data_offset = 0x1a00;
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strcmp(model,"DSC-F828")) {
+ width = 3288;
+ left_margin = 5;
+ data_offset = 862144;
+ load_raw = &CLASS sony_load_raw;
+ filters = 0x9c9c9c9c;
+ colors = 4;
+ strcpy (cdesc, "RGBE");
+ } else if (!strcmp(model,"DSC-V3")) {
+ width = 3109;
+ left_margin = 59;
+ data_offset = 787392;
+ load_raw = &CLASS sony_load_raw;
+ } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+ adobe_coeff ("SONY","DSC-R1");
+ width = 3925;
+ order = 0x4d4d;
+ } else if (!strcmp(model,"DSLR-A100")) {
+ height--;
+ } else if (!strcmp(model,"DSLR-A350")) {
+ height -= 4;
+ } else if (!strcmp(model,"C603v")) {
+ height = 480;
+ width = 640;
+ goto c603v;
+ } else if (!strcmp(model,"C603y")) {
+ height = 2134;
+ width = 2848;
+c603v:
+ filters = 0;
+ load_raw = &CLASS kodak_yrgb_load_raw;
+ } else if (!strcmp(model,"C603")) {
+ raw_height = height = 2152;
+ raw_width = width = 2864;
+ goto c603;
+ } else if (!strcmp(model,"C330")) {
+ height = 1744;
+ width = 2336;
+ raw_height = 1779;
+ raw_width = 2338;
+ top_margin = 33;
+ left_margin = 1;
+c603:
+ order = 0x4949;
+ if ((data_offset = fsize - raw_height*raw_width)) {
+ fseek (ifp, 168, SEEK_SET);
+ read_shorts (curve, 256);
+ } else use_gamma = 0;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcasecmp(make,"KODAK")) {
+ if (filters == UINT_MAX) filters = 0x61616161;
+ if (!strncmp(model,"NC2000",6)) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"EOSDCS3B")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"EOSDCS1")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS420")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS460")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS460A")) {
+ width -= 4;
+ left_margin = 2;
+ colors = 1;
+ filters = 0;
+ } else if (!strcmp(model,"DCS660M")) {
+ black = 214;
+ colors = 1;
+ filters = 0;
+ } else if (!strcmp(model,"DCS760M")) {
+ colors = 1;
+ filters = 0;
+ }
+ if (!strcmp(model+4,"20X"))
+ strcpy (cdesc, "MYCY");
+ if (strstr(model,"DC25")) {
+ strcpy (model, "DC25");
+ data_offset = 15424;
+ }
+ if (!strncmp(model,"DC2",3)) {
+ height = 242;
+ if (fsize < 100000) {
+ raw_width = 256; width = 249;
+ pixel_aspect = (4.0*height) / (3.0*width);
+ } else {
+ raw_width = 512; width = 501;
+ pixel_aspect = (493.0*height) / (373.0*width);
+ }
+ data_offset += raw_width + 1;
+ colors = 4;
+ filters = 0x8d8d8d8d;
+ simple_coeff(1);
+ pre_mul[1] = 1.179;
+ pre_mul[2] = 1.209;
+ pre_mul[3] = 1.036;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"40")) {
+ strcpy (model, "DC40");
+ height = 512;
+ width = 768;
+ data_offset = 1152;
+ load_raw = &CLASS kodak_radc_load_raw;
+ } else if (strstr(model,"DC50")) {
+ strcpy (model, "DC50");
+ height = 512;
+ width = 768;
+ data_offset = 19712;
+ load_raw = &CLASS kodak_radc_load_raw;
+ } else if (strstr(model,"DC120")) {
+ strcpy (model, "DC120");
+ height = 976;
+ width = 848;
+ pixel_aspect = height/0.75/width;
+ load_raw = tiff_compress == 7 ?
+ &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+ } else if (!strcmp(model,"DCS200")) {
+ thumb_height = 128;
+ thumb_width = 192;
+ thumb_offset = 6144;
+ thumb_misc = 360;
+ write_thumb = &CLASS layer_thumb;
+ height = 1024;
+ width = 1536;
+ data_offset = 79872;
+ load_raw = &CLASS eight_bit_load_raw;
+ black = 17;
+ }
+ } else if (!strcmp(model,"Fotoman Pixtura")) {
+ height = 512;
+ width = 768;
+ data_offset = 3632;
+ load_raw = &CLASS kodak_radc_load_raw;
+ filters = 0x61616161;
+ simple_coeff(2);
+ } else if (!strcmp(model,"QuickTake 100")) {
+ fseek (ifp, 544, SEEK_SET);
+ height = get2();
+ width = get2();
+ data_offset = (get4(),get2()) == 30 ? 738:736;
+ if (height > width) {
+ SWAP(height,width);
+ fseek (ifp, data_offset-6, SEEK_SET);
+ flip = ~get2() & 3 ? 5:6;
+ }
+ load_raw = &CLASS quicktake_100_load_raw;
+ filters = 0x61616161;
+ } else if (!strcmp(model,"QuickTake 150")) {
+ data_offset = 738 - head[5];
+ if (head[5]) strcpy (model+10, "200");
+ load_raw = &CLASS kodak_radc_load_raw;
+ height = 480;
+ width = 640;
+ filters = 0x61616161;
+ } else if (!strcmp(make,"Rollei") && !load_raw) {
+ switch (raw_width) {
+ case 1316:
+ height = 1030;
+ width = 1300;
+ top_margin = 1;
+ left_margin = 6;
+ break;
+ case 2568:
+ height = 1960;
+ width = 2560;
+ top_margin = 2;
+ left_margin = 8;
+ }
+ filters = 0x16161616;
+ load_raw = &CLASS rollei_load_raw;
+ pre_mul[0] = 1.8;
+ pre_mul[2] = 1.3;
+ } else if (!strcmp(model,"PC-CAM 600")) {
+ height = 768;
+ data_offset = width = 1024;
+ filters = 0x49494949;
+ load_raw = &CLASS eight_bit_load_raw;
+ pre_mul[0] = 1.14;
+ pre_mul[2] = 2.73;
+ } else if (!strcmp(model,"QV-2000UX")) {
+ height = 1208;
+ width = 1632;
+ data_offset = width * 2;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (fsize == 3217760) {
+ height = 1546;
+ width = 2070;
+ raw_width = 2080;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"QV-4000")) {
+ height = 1700;
+ width = 2260;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xffff;
+ } else if (!strcmp(model,"QV-5700")) {
+ height = 1924;
+ width = 2576;
+ load_raw = &CLASS casio_qv5700_load_raw;
+ } else if (!strcmp(model,"QV-R41")) {
+ height = 1720;
+ width = 2312;
+ raw_width = 3520;
+ left_margin = 2;
+ } else if (!strcmp(model,"QV-R51")) {
+ height = 1926;
+ width = 2580;
+ raw_width = 3904;
+ pre_mul[0] = 1.340;
+ pre_mul[2] = 1.672;
+ } else if (!strcmp(model,"EX-S100")) {
+ height = 1544;
+ width = 2058;
+ raw_width = 3136;
+ pre_mul[0] = 1.631;
+ pre_mul[2] = 1.106;
+ } else if (!strcmp(model,"EX-Z50")) {
+ height = 1931;
+ width = 2570;
+ raw_width = 3904;
+ pre_mul[0] = 2.529;
+ pre_mul[2] = 1.185;
+ } else if (!strcmp(model,"EX-Z55")) {
+ height = 1960;
+ width = 2570;
+ raw_width = 3904;
+ pre_mul[0] = 1.520;
+ pre_mul[2] = 1.316;
+ } else if (!strcmp(model,"EX-P505")) {
+ height = 1928;
+ width = 2568;
+ raw_width = 3852;
+ maximum = 0xfff;
+ pre_mul[0] = 2.07;
+ pre_mul[2] = 1.88;
+ } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */
+ height = 2142;
+ width = 2844;
+ raw_width = 4288;
+ pre_mul[0] = 1.797;
+ pre_mul[2] = 1.219;
+ } else if (!strcmp(model,"EX-P700")) {
+ height = 2318;
+ width = 3082;
+ raw_width = 4672;
+ pre_mul[0] = 1.758;
+ pre_mul[2] = 1.504;
+ }
+ if (!model[0])
+ sprintf (model, "%dx%d", width, height);
+ if (filters == UINT_MAX) filters = 0x94949494;
+ if (raw_color) adobe_coeff (make, model);
+ if (thumb_offset && !thumb_height) {
+ fseek (ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+dng_skip:
+ if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+ if (load_raw == &CLASS kodak_jpeg_load_raw) {
+ fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+ is_raw = 0;
+ }
+#endif
+ if (!cdesc[0])
+ strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+ if (!raw_height) raw_height = height;
+ if (!raw_width ) raw_width = width;
+ if (filters && colors == 3)
+ for (i=0; i < 32; i+=4) {
+ if ((filters >> i & 15) == 9)
+ filters |= 2 << i;
+ if ((filters >> i & 15) == 6)
+ filters |= 8 << i;
+ }
+notraw:
+ if (flip == -1) flip = tiff_flip;
+ if (flip == -1) flip = 0;
+}
+
+#ifndef NO_LCMS
+void CLASS apply_profile (char *input, char *output)
+{
+ char *prof;
+ cmsHPROFILE hInProfile=0, hOutProfile=0;
+ cmsHTRANSFORM hTransform;
+ FILE *fp;
+ unsigned size;
+
+ cmsErrorAction (LCMS_ERROR_SHOW);
+ if (strcmp (input, "embed"))
+ hInProfile = cmsOpenProfileFromFile (input, "r");
+ else if (profile_length) {
+ prof = (char *) malloc (profile_length);
+ merror (prof, "apply_profile()");
+ fseek (ifp, profile_offset, SEEK_SET);
+ fread (prof, 1, profile_length, ifp);
+ hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+ free (prof);
+ } else
+ fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+ if (!hInProfile) return;
+ if (!output)
+ hOutProfile = cmsCreate_sRGBProfile();
+ else if ((fp = fopen (output, "rb"))) {
+ fread (&size, 4, 1, fp);
+ fseek (fp, 0, SEEK_SET);
+ oprof = (unsigned *) malloc (size = ntohl(size));
+ merror (oprof, "apply_profile()");
+ fread (oprof, 1, size, fp);
+ fclose (fp);
+ if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+ free (oprof);
+ oprof = 0;
+ }
+ } else
+ fprintf (stderr,_("Cannot open file %s!\n"), output);
+ if (!hOutProfile) goto quit;
+ if (verbose)
+ fprintf (stderr,_("Applying color profile...\n"));
+ hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+ hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+ cmsDoTransform (hTransform, image, image, width*height);
+ raw_color = 1; /* Don't use rgb_cam with a profile */
+ cmsDeleteTransform (hTransform);
+ cmsCloseProfile (hOutProfile);
+quit:
+ cmsCloseProfile (hInProfile);
+}
+#endif
+
+void CLASS convert_to_rgb()
+{
+ int row, col, c, i, j, k;
+ ushort *img;
+ float out[3], out_cam[3][4];
+ double num, inverse[3][3], bnd[2]={0,0};
+ static const double xyzd50_srgb[3][3] =
+ { { 0.436083, 0.385083, 0.143055 },
+ { 0.222507, 0.716888, 0.060608 },
+ { 0.013930, 0.097097, 0.714022 } };
+ static const double rgb_rgb[3][3] =
+ { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+ static const double adobe_rgb[3][3] =
+ { { 0.715146, 0.284856, 0.000000 },
+ { 0.000000, 1.000000, 0.000000 },
+ { 0.000000, 0.041166, 0.958839 } };
+ static const double wide_rgb[3][3] =
+ { { 0.593087, 0.404710, 0.002206 },
+ { 0.095413, 0.843149, 0.061439 },
+ { 0.011621, 0.069091, 0.919288 } };
+ static const double prophoto_rgb[3][3] =
+ { { 0.529317, 0.330092, 0.140588 },
+ { 0.098368, 0.873465, 0.028169 },
+ { 0.016879, 0.117663, 0.865457 } };
+ static const double (*out_rgb[])[3] =
+ { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+ static const char *name[] =
+ { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+ static const unsigned phead[] =
+ { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+ 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+ unsigned pbody[] =
+ { 10, 0x63707274, 0, 36, /* cprt */
+ 0x64657363, 0, 40, /* desc */
+ 0x77747074, 0, 20, /* wtpt */
+ 0x626b7074, 0, 20, /* bkpt */
+ 0x72545243, 0, 14, /* rTRC */
+ 0x67545243, 0, 14, /* gTRC */
+ 0x62545243, 0, 14, /* bTRC */
+ 0x7258595a, 0, 20, /* rXYZ */
+ 0x6758595a, 0, 20, /* gXYZ */
+ 0x6258595a, 0, 20 }; /* bXYZ */
+ static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+ unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+ bnd[gamm[1] >= 1] = 1;
+ if (gamm[1] && (gamm[1]-1)*(gamm[0]-1) <= 0) {
+ for (i=0; i < 36; i++) {
+ gamm[2] = (bnd[0] + bnd[1])/2;
+ bnd[(pow(gamm[2]/gamm[1],-gamm[0])-1)/gamm[0]-1/gamm[2] > -1] = gamm[2];
+ }
+ gamm[3] = gamm[2]*(1/gamm[0]-1);
+ gamm[2] /= gamm[1];
+ }
+ gamm[4] = 1 / (gamm[1]/2*SQR(gamm[2]) - gamm[3]*(1-gamm[2]) +
+ (1-pow(gamm[2],1+gamm[0]))*(1+gamm[3])/(1+gamm[0])) - 1;
+
+ memcpy (out_cam, rgb_cam, sizeof out_cam);
+ raw_color |= colors == 1 || document_mode ||
+ output_color < 1 || output_color > 5;
+ if (!raw_color) {
+ oprof = (unsigned *) calloc (phead[0], 1);
+ merror (oprof, "convert_to_rgb()");
+ memcpy (oprof, phead, sizeof phead);
+ if (output_color == 5) oprof[4] = oprof[5];
+ oprof[0] = 132 + 12*pbody[0];
+ for (i=0; i < pbody[0]; i++) {
+ oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+ pbody[i*3+2] = oprof[0];
+ oprof[0] += (pbody[i*3+3] + 3) & -4;
+ }
+ memcpy (oprof+32, pbody, sizeof pbody);
+ oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+ memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+ if (output_bps == 8)
+ pcurve[3] = (short)(256/gamm[4]+0.5) << 16;
+ for (i=4; i < 7; i++)
+ memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+ pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++) {
+ for (num = k=0; k < 3; k++)
+ num += xyzd50_srgb[i][k] * inverse[j][k];
+ oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+ }
+ for (i=0; i < phead[0]/4; i++)
+ oprof[i] = htonl(oprof[i]);
+ strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+ strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+ for (i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ for (out_cam[i][j] = k=0; k < 3; k++)
+ out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+ }
+ if (verbose)
+ fprintf (stderr, raw_color ? _("Building histograms...\n") :
+ _("Converting to %s colorspace...\n"), name[output_color-1]);
+
+ memset (histogram, 0, sizeof histogram);
+ for (img=image[0], row=0; row < height; row++)
+ for (col=0; col < width; col++, img+=4) {
+ if (!raw_color) {
+ out[0] = out[1] = out[2] = 0;
+ FORCC {
+ out[0] += out_cam[0][c] * img[c];
+ out[1] += out_cam[1][c] * img[c];
+ out[2] += out_cam[2][c] * img[c];
+ }
+ FORC3 img[c] = CLIP((int) out[c]);
+ }
+ else if (document_mode)
+ img[0] = img[FC(row,col)];
+ FORCC histogram[c][img[c] >> 3]++;
+ }
+ if (colors == 4 && output_color) colors = 3;
+ if (document_mode && filters) colors = 1;
+}
+
+void CLASS fuji_rotate()
+{
+ int i, row, col;
+ double step;
+ float r, c, fr, fc;
+ unsigned ur, uc;
+ ushort wide, high, (*img)[4], (*pix)[4];
+
+ if (!fuji_width) return;
+ if (verbose)
+ fprintf (stderr,_("Rotating image 45 degrees...\n"));
+ fuji_width = (fuji_width - 1 + shrink) >> shrink;
+ step = sqrt(0.5);
+ wide = fuji_width / step;
+ high = (height - fuji_width) / step;
+ img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+ merror (img, "fuji_rotate()");
+
+ for (row=0; row < high; row++)
+ for (col=0; col < wide; col++) {
+ ur = r = fuji_width + (row-col)*step;
+ uc = c = (row+col)*step;
+ if (ur > height-2 || uc > width-2) continue;
+ fr = r - ur;
+ fc = c - uc;
+ pix = image + ur*width + uc;
+ for (i=0; i < colors; i++)
+ img[row*wide+col][i] =
+ (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) +
+ (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+ }
+ free (image);
+ width = wide;
+ height = high;
+ image = img;
+ fuji_width = 0;
+}
+
+void CLASS stretch()
+{
+ ushort newdim, (*img)[4], *pix0, *pix1;
+ int row, col, c;
+ double rc, frac;
+
+ if (pixel_aspect == 1) return;
+ if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+ if (pixel_aspect < 1) {
+ newdim = height / pixel_aspect + 0.5;
+ img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+ merror (img, "stretch()");
+ for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c*width];
+ if (c+1 < height) pix1 += width*4;
+ for (col=0; col < width; col++, pix0+=4, pix1+=4)
+ FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+ }
+ height = newdim;
+ } else {
+ newdim = width * pixel_aspect + 0.5;
+ img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+ merror (img, "stretch()");
+ for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c];
+ if (c+1 < width) pix1 += 4;
+ for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+ FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+ }
+ width = newdim;
+ }
+ free (image);
+ image = img;
+}
+
+int CLASS flip_index (int row, int col)
+{
+ if (flip & 4) SWAP(row,col);
+ if (flip & 2) row = iheight - 1 - row;
+ if (flip & 1) col = iwidth - 1 - col;
+ return row * iwidth + col;
+}
+
+void CLASS gamma_lut (uchar lut[0x10000])
+{
+ int perc, c, val, total, i;
+ float white=0, r;
+
+ perc = width * height * 0.01; /* 99th percentile white level */
+ if (fuji_width) perc /= 2;
+ if ((highlight & ~2) || no_auto_bright) perc = -1;
+ FORCC {
+ for (val=0x2000, total=0; --val > 32; )
+ if ((total += histogram[c][val]) > perc) break;
+ if (white < val) white = val;
+ }
+ white *= 8 / bright;
+ for (i=0; i < 0x10000; i++) {
+ r = i / white;
+ val = 256 * ( !use_gamma ? r :
+ r <= gamm[2] ? r*gamm[1] : pow(r,gamm[0])*(1+gamm[3])-gamm[3]);
+ if (val > 255) val = 255;
+ lut[i] = val;
+ }
+}
+
+struct tiff_tag {
+ ushort tag, type;
+ int count;
+ union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+ ushort order, magic;
+ int ifd;
+ ushort pad, ntag;
+ struct tiff_tag tag[23];
+ int nextifd;
+ ushort pad2, nexif;
+ struct tiff_tag exif[4];
+ ushort pad3, ngps;
+ struct tiff_tag gpst[10];
+ short bps[4];
+ int rat[10];
+ unsigned gps[26];
+ char desc[512], make[64], model[64], soft[32], date[20], artist[64];
+};
+
+void CLASS tiff_set (ushort *ntag,
+ ushort tag, ushort type, int count, int val)
+{
+ struct tiff_tag *tt;
+ int c;
+
+ tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+ tt->tag = tag;
+ tt->type = type;
+ tt->count = count;
+ if (type < 3 && count <= 4)
+ FORC(4) tt->val.c[c] = val >> (c << 3);
+ else if (type == 3 && count <= 2)
+ FORC(2) tt->val.s[c] = val >> (c << 4);
+ else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+ int c, psize=0;
+ struct tm *t;
+
+ memset (th, 0, sizeof *th);
+ th->order = htonl(0x4d4d4949) >> 16;
+ th->magic = 42;
+ th->ifd = 10;
+ if (full) {
+ tiff_set (&th->ntag, 254, 4, 1, 0);
+ tiff_set (&th->ntag, 256, 4, 1, width);
+ tiff_set (&th->ntag, 257, 4, 1, height);
+ tiff_set (&th->ntag, 258, 3, colors, output_bps);
+ if (colors > 2)
+ th->tag[th->ntag-1].val.i = TOFF(th->bps);
+ FORC4 th->bps[c] = output_bps;
+ tiff_set (&th->ntag, 259, 3, 1, 1);
+ tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+ }
+ tiff_set (&th->ntag, 270, 2, 512, TOFF(th->desc));
+ tiff_set (&th->ntag, 271, 2, 64, TOFF(th->make));
+ tiff_set (&th->ntag, 272, 2, 64, TOFF(th->model));
+ if (full) {
+ if (oprof) psize = ntohl(oprof[0]);
+ tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+ tiff_set (&th->ntag, 277, 3, 1, colors);
+ tiff_set (&th->ntag, 278, 4, 1, height);
+ tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+ } else
+ tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+ tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+ tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+ tiff_set (&th->ntag, 284, 3, 1, 1);
+ tiff_set (&th->ntag, 296, 3, 1, 2);
+ tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+ tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+ tiff_set (&th->ntag, 315, 2, 64, TOFF(th->artist));
+ tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+ if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+ tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+ tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+ tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+ tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+ if (gpsdata[1]) {
+ tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+ tiff_set (&th->ngps, 0, 1, 4, 0x202);
+ tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]);
+ tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0]));
+ tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]);
+ tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6]));
+ tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]);
+ tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18]));
+ tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12]));
+ tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+ tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+ memcpy (th->gps, gpsdata, sizeof th->gps);
+ }
+ th->rat[0] = th->rat[2] = 300;
+ th->rat[1] = th->rat[3] = 1;
+ FORC(6) th->rat[4+c] = 1000000;
+ th->rat[4] *= shutter;
+ th->rat[6] *= aperture;
+ th->rat[8] *= focal_len;
+ strncpy (th->desc, desc, 512);
+ strncpy (th->make, make, 64);
+ strncpy (th->model, model, 64);
+ strcpy (th->soft, "dcraw v"VERSION);
+ t = gmtime (&timestamp);
+ sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+ t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+ strncpy (th->artist, artist, 64);
+}
+
+void CLASS jpeg_thumb (FILE *tfp)
+{
+ char *thumb;
+ ushort exif[5];
+ struct tiff_hdr th;
+
+ thumb = (char *) malloc (thumb_length);
+ merror (thumb, "jpeg_thumb()");
+ fread (thumb, 1, thumb_length, ifp);
+ fputc (0xff, tfp);
+ fputc (0xd8, tfp);
+ if (strcmp (thumb+6, "Exif")) {
+ memcpy (exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons (8 + sizeof th);
+ fwrite (exif, 1, sizeof exif, tfp);
+ tiff_head (&th, 0);
+ fwrite (&th, 1, sizeof th, tfp);
+ }
+ fwrite (thumb+2, 1, thumb_length-2, tfp);
+ free (thumb);
+}
+
+void CLASS write_ppm_tiff (FILE *ofp)
+{
+ struct tiff_hdr th;
+ uchar *ppm, lut[0x10000];
+ ushort *ppm2;
+ int c, row, col, soff, rstep, cstep;
+
+ iheight = height;
+ iwidth = width;
+ if (flip & 4) SWAP(height,width);
+ ppm = (uchar *) calloc (width, colors*output_bps/8);
+ ppm2 = (ushort *) ppm;
+ merror (ppm, "write_ppm_tiff()");
+ if (output_tiff) {
+ tiff_head (&th, 1);
+ fwrite (&th, sizeof th, 1, ofp);
+ if (oprof)
+ fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+ } else if (colors > 3)
+ fprintf (ofp,
+ "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+ width, height, colors, (1 << output_bps)-1, cdesc);
+ else
+ fprintf (ofp, "P%d\n%d %d\n%d\n",
+ colors/2+5, width, height, (1 << output_bps)-1);
+
+ if (output_bps == 8) gamma_lut (lut);
+ soff = flip_index (0, 0);
+ cstep = flip_index (0, 1) - soff;
+ rstep = flip_index (1, 0) - flip_index (0, width);
+ for (row=0; row < height; row++, soff += rstep) {
+ for (col=0; col < width; col++, soff += cstep)
+ if (output_bps == 8)
+ FORCC ppm [col*colors+c] = lut[image[soff][c]];
+ else FORCC ppm2[col*colors+c] = image[soff][c];
+ if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+ swab (ppm2, ppm2, width*colors*2);
+ fwrite (ppm, colors*output_bps/8, width, ofp);
+ }
+ free (ppm);
+}
+
+int CLASS main (int argc, char **argv)
+{
+ int arg, status=0;
+ int timestamp_only=0, thumbnail_only=0, identify_only=0;
+ int user_qual=-1, user_black=-1, user_sat=-1, user_flip=-1;
+ int use_fuji_rotate=1, write_to_stdout=0, quality, i, c;
+ char opm, opt, *ofname, *sp, *cp, *bpfile=0, *dark_frame=0;
+ const char *write_ext;
+ struct utimbuf ut;
+ FILE *ofp;
+#ifndef NO_LCMS
+ char *cam_profile=0, *out_profile=0;
+#endif
+
+#ifndef LOCALTIME
+ putenv ("TZ=UTC");
+#endif
+#ifdef LOCALEDIR
+ setlocale (LC_CTYPE, "");
+ setlocale (LC_MESSAGES, "");
+ bindtextdomain ("dcraw", LOCALEDIR);
+ textdomain ("dcraw");
+#endif
+
+ if (argc == 1) {
+ printf(_("\nRaw photo decoder \"dcraw\" v%s"), VERSION);
+ printf(_("\nby Dave Coffin, dcoffin a cybercom o net\n"));
+ printf(_("\nUsage: %s [OPTION]... [FILE]...\n\n"), argv[0]);
+ puts(_("-v Print verbose messages"));
+ puts(_("-c Write image data to standard output"));
+ puts(_("-e Extract embedded thumbnail image"));
+ puts(_("-i Identify files without decoding them"));
+ puts(_("-i -v Identify files and show metadata"));
+ puts(_("-z Change file dates to camera timestamp"));
+ puts(_("-w Use camera white balance, if possible"));
+ puts(_("-a Average the whole image for white balance"));
+ puts(_("-A <x y w h> Average a grey box for white balance"));
+ puts(_("-r <r g b g> Set custom white balance"));
+ puts(_("+M/-M Use/don't use an embedded color matrix"));
+ puts(_("-C <r b> Correct chromatic aberration"));
+ puts(_("-P <file> Fix the dead pixels listed in this file"));
+ puts(_("-K <file> Subtract dark frame (16-bit raw PGM)"));
+ puts(_("-k <num> Set the darkness level"));
+ puts(_("-S <num> Set the saturation level"));
+ puts(_("-n <num> Set threshold for wavelet denoising"));
+ puts(_("-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)"));
+ puts(_("-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)"));
+ puts(_("-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)"));
+#ifndef NO_LCMS
+ puts(_("-o <file> Apply output ICC profile from file"));
+ puts(_("-p <file> Apply camera ICC profile from file or \"embed\""));
+#endif
+ puts(_("-d Document mode (no color, no interpolation)"));
+ puts(_("-D Document mode without scaling (totally raw)"));
+ puts(_("-j Don't stretch or rotate raw pixels"));
+ puts(_("-W Don't automatically brighten the image"));
+ puts(_("-b <num> Adjust brightness (default = 1.0)"));
+ puts(_("-g <p ts> Set custom gamma curve (default = 2.222 4.5)"));
+ puts(_("-q [0-3] Set the interpolation quality"));
+ puts(_("-h Half-size color image (twice as fast as \"-q 0\")"));
+ puts(_("-f Interpolate RGGB as four colors"));
+ puts(_("-m <num> Apply a 3x3 median filter to R-G and B-G"));
+ puts(_("-s [0..N-1] Select one raw image or \"all\" from each file"));
+ puts(_("-4 Write 16-bit linear instead of 8-bit with gamma"));
+ puts(_("-T Write TIFF instead of PPM"));
+ puts("");
+ return 1;
+ }
+ argv[argc] = "";
+ for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) {
+ opt = argv[arg++][1];
+ if ((cp = strchr (sp="nbrkStqmHACg", opt)))
+ for (i=0; i < "114111111422"[cp-sp]-'0'; i++)
+ if (!isdigit(argv[arg+i][0])) {
+ fprintf (stderr,_("Non-numeric argument to \"-%c\"\n"), opt);
+ return 1;
+ }
+ switch (opt) {
+ case 'n': threshold = atof(argv[arg++]); break;
+ case 'b': bright = atof(argv[arg++]); break;
+ case 'r':
+ FORC4 user_mul[c] = atof(argv[arg++]); break;
+ case 'C': aber[0] = 1 / atof(argv[arg++]);
+ aber[2] = 1 / atof(argv[arg++]); break;
+ case 'g': gamm[0] = 1 / atof(argv[arg++]);
+ gamm[1] = atof(argv[arg++]); break;
+ case 'k': user_black = atoi(argv[arg++]); break;
+ case 'S': user_sat = atoi(argv[arg++]); break;
+ case 't': user_flip = atoi(argv[arg++]); break;
+ case 'q': user_qual = atoi(argv[arg++]); break;
+ case 'm': med_passes = atoi(argv[arg++]); break;
+ case 'H': highlight = atoi(argv[arg++]); break;
+ case 's':
+ shot_select = abs(atoi(argv[arg]));
+ multi_out = !strcmp(argv[arg++],"all");
+ break;
+ case 'o':
+ if (isdigit(argv[arg][0]) && !argv[arg][1])
+ output_color = atoi(argv[arg++]);
+#ifndef NO_LCMS
+ else out_profile = argv[arg++];
+ break;
+ case 'p': cam_profile = argv[arg++];
+#endif
+ break;
+ case 'P': bpfile = argv[arg++]; break;
+ case 'K': dark_frame = argv[arg++]; break;
+ case 'z': timestamp_only = 1; break;
+ case 'e': thumbnail_only = 1; break;
+ case 'i': identify_only = 1; break;
+ case 'c': write_to_stdout = 1; break;
+ case 'v': verbose = 1; break;
+ case 'h': half_size = 1; /* "-h" implies "-f" */
+ case 'f': four_color_rgb = 1; break;
+ case 'A': FORC4 greybox[c] = atoi(argv[arg++]);
+ case 'a': use_auto_wb = 1; break;
+ case 'w': use_camera_wb = 1; break;
+ case 'M': use_camera_matrix = (opm == '+'); break;
+ case 'D':
+ case 'd': document_mode = 1 + (opt == 'D');
+ case 'j': use_fuji_rotate = 0; break;
+ case 'W': no_auto_bright = 1; break;
+ case 'T': output_tiff = 1; break;
+ case '4': output_bps = 16; break;
+ default:
+ fprintf (stderr,_("Unknown option \"-%c\".\n"), opt);
+ return 1;
+ }
+ }
+ if (use_camera_matrix < 0)
+ use_camera_matrix = use_camera_wb;
+ if (arg == argc) {
+ fprintf (stderr,_("No files to process.\n"));
+ return 1;
+ }
+ if (write_to_stdout) {
+ if (isatty(1)) {
+ fprintf (stderr,_("Will not write an image to the terminal!\n"));
+ return 1;
+ }
+#if defined(WIN32) || defined(DJGPP) || defined(__CYGWIN__)
+ if (setmode(1,O_BINARY) < 0) {
+ perror ("setmode()");
+ return 1;
+ }
+#endif
+ }
+ for ( ; arg < argc; arg++) {
+ status = 1;
+ image = 0;
+ oprof = 0;
+ meta_data = ofname = 0;
+ ofp = stdout;
+ if (setjmp (failure)) {
+ if (fileno(ifp) > 2) fclose(ifp);
+ if (fileno(ofp) > 2) fclose(ofp);
+ status = 1;
+ goto cleanup;
+ }
+ ifname = argv[arg];
+ if (!(ifp = fopen (ifname, "rb"))) {
+ perror (ifname);
+ continue;
+ }
+ status = (identify(),!is_raw);
+ if (user_flip >= 0)
+ flip = user_flip;
+ switch ((flip+3600) % 360) {
+ case 270: flip = 5; break;
+ case 180: flip = 3; break;
+ case 90: flip = 6;
+ }
+ if (timestamp_only) {
+ if ((status = !timestamp))
+ fprintf (stderr,_("%s has no timestamp.\n"), ifname);
+ else if (identify_only)
+ printf ("%10ld%10d %s\n", (long) timestamp, shot_order, ifname);
+ else {
+ if (verbose)
+ fprintf (stderr,_("%s time set to %d.\n"), ifname, (int) timestamp);
+ ut.actime = ut.modtime = timestamp;
+ utime (ifname, &ut);
+ }
+ goto next;
+ }
+ write_fun = &CLASS write_ppm_tiff;
+ if (thumbnail_only) {
+ if ((status = !thumb_offset)) {
+ fprintf (stderr,_("%s has no thumbnail.\n"), ifname);
+ goto next;
+ } else if (thumb_load_raw) {
+ load_raw = thumb_load_raw;
+ data_offset = thumb_offset;
+ height = thumb_height;
+ width = thumb_width;
+ filters = 0;
+ } else {
+ fseek (ifp, thumb_offset, SEEK_SET);
+ write_fun = write_thumb;
+ goto thumbnail;
+ }
+ }
+ if (load_raw == &CLASS kodak_ycbcr_load_raw) {
+ height += height & 1;
+ width += width & 1;
+ }
+ if (identify_only && verbose && make[0]) {
+ printf (_("\nFilename: %s\n"), ifname);
+ printf (_("Timestamp: %s"), ctime(&timestamp));
+ printf (_("Camera: %s %s\n"), make, model);
+ if (artist[0])
+ printf (_("Owner: %s\n"), artist);
+ if (dng_version) {
+ printf (_("DNG Version: "));
+ for (i=24; i >= 0; i -= 8)
+ printf ("%d%c", dng_version >> i & 255, i ? '.':'\n');
+ }
+ printf (_("ISO speed: %d\n"), (int) iso_speed);
+ printf (_("Shutter: "));
+ if (shutter > 0 && shutter < 1)
+ shutter = (printf ("1/"), 1 / shutter);
+ printf (_("%0.1f sec\n"), shutter);
+ printf (_("Aperture: f/%0.1f\n"), aperture);
+ printf (_("Focal length: %0.1f mm\n"), focal_len);
+ printf (_("Embedded ICC profile: %s\n"), profile_length ? _("yes"):_("no"));
+ printf (_("Number of raw images: %d\n"), is_raw);
+ if (pixel_aspect != 1)
+ printf (_("Pixel Aspect Ratio: %0.6f\n"), pixel_aspect);
+ if (thumb_offset)
+ printf (_("Thumb size: %4d x %d\n"), thumb_width, thumb_height);
+ printf (_("Full size: %4d x %d\n"), raw_width, raw_height);
+ } else if (!is_raw)
+ fprintf (stderr,_("Cannot decode file %s\n"), ifname);
+ if (!is_raw) goto next;
+ shrink = filters &&
+ (half_size || threshold || aber[0] != 1 || aber[2] != 1);
+ iheight = (height + shrink) >> shrink;
+ iwidth = (width + shrink) >> shrink;
+ if (identify_only) {
+ if (verbose) {
+ if (use_fuji_rotate) {
+ if (fuji_width) {
+ fuji_width = (fuji_width - 1 + shrink) >> shrink;
+ iwidth = fuji_width / sqrt(0.5);
+ iheight = (iheight - fuji_width) / sqrt(0.5);
+ } else {
+ if (pixel_aspect < 1) iheight = iheight / pixel_aspect + 0.5;
+ if (pixel_aspect > 1) iwidth = iwidth * pixel_aspect + 0.5;
+ }
+ }
+ if (flip & 4)
+ SWAP(iheight,iwidth);
+ printf (_("Image size: %4d x %d\n"), width, height);
+ printf (_("Output size: %4d x %d\n"), iwidth, iheight);
+ printf (_("Raw colors: %d"), colors);
+ if (filters) {
+ printf (_("\nFilter pattern: "));
+ if (!cdesc[3]) cdesc[3] = 'G';
+ for (i=0; i < 16; i++)
+ putchar (cdesc[fc(i >> 1,i & 1)]);
+ }
+ printf (_("\nDaylight multipliers:"));
+ FORCC printf (" %f", pre_mul[c]);
+ if (cam_mul[0] > 0) {
+ printf (_("\nCamera multipliers:"));
+ FORC4 printf (" %f", cam_mul[c]);
+ }
+ putchar ('\n');
+ } else
+ printf (_("%s is a %s %s image.\n"), ifname, make, model);
+next:
+ fclose(ifp);
+ continue;
+ }
+ if (use_camera_matrix && cmatrix[0][0] > 0.25) {
+ memcpy (rgb_cam, cmatrix, sizeof cmatrix);
+ raw_color = 0;
+ }
+ image = (ushort (*)[4]) calloc (iheight*iwidth, sizeof *image);
+ merror (image, "main()");
+ if (meta_length) {
+ meta_data = (char *) malloc (meta_length);
+ merror (meta_data, "main()");
+ }
+ if (verbose)
+ fprintf (stderr,_("Loading %s %s image from %s ...\n"),
+ make, model, ifname);
+ if (shot_select >= is_raw)
+ fprintf (stderr,_("%s: \"-s %d\" requests a nonexistent image!\n"),
+ ifname, shot_select);
+ fseeko (ifp, data_offset, SEEK_SET);
+ (*load_raw)();
+ if (zero_is_bad) remove_zeroes();
+ bad_pixels (bpfile);
+ if (dark_frame) subtract (dark_frame);
+ quality = 2 + !fuji_width;
+ if (user_qual >= 0) quality = user_qual;
+ if (user_black >= 0) black = user_black;
+ if (user_sat > 0) maximum = user_sat;
+#ifdef COLORCHECK
+ colorcheck();
+#endif
+ if (is_foveon && !document_mode) foveon_interpolate();
+ if (!is_foveon && document_mode < 2) scale_colors();
+ pre_interpolate();
+ if (filters && !document_mode) {
+ if (quality == 0)
+ lin_interpolate();
+ else if (quality == 1 || colors > 3)
+ vng_interpolate();
+ else if (quality == 2)
+ ppg_interpolate();
+ else ahd_interpolate();
+ }
+ if (mix_green)
+ for (colors=3, i=0; i < height*width; i++)
+ image[i][1] = (image[i][1] + image[i][3]) >> 1;
+ if (!is_foveon && colors == 3) median_filter();
+ if (!is_foveon && highlight == 2) blend_highlights();
+ if (!is_foveon && highlight > 2) recover_highlights();
+ if (use_fuji_rotate) fuji_rotate();
+#ifndef NO_LCMS
+ if (cam_profile) apply_profile (cam_profile, out_profile);
+#endif
+ convert_to_rgb();
+ if (use_fuji_rotate) stretch();
+thumbnail:
+ if (write_fun == &CLASS jpeg_thumb)
+ write_ext = ".jpg";
+ else if (output_tiff && write_fun == &CLASS write_ppm_tiff)
+ write_ext = ".tiff";
+ else
+ write_ext = ".pgm\0.ppm\0.ppm\0.pam" + colors*5-5;
+ ofname = (char *) malloc (strlen(ifname) + 64);
+ merror (ofname, "main()");
+ if (write_to_stdout)
+ strcpy (ofname,_("standard output"));
+ else {
+ strcpy (ofname, ifname);
+ if ((cp = strrchr (ofname, '.'))) *cp = 0;
+ if (multi_out)
+ sprintf (ofname+strlen(ofname), "_%0*d",
+ snprintf(0,0,"%d",is_raw-1), shot_select);
+ if (thumbnail_only)
+ strcat (ofname, ".thumb");
+ strcat (ofname, write_ext);
+ ofp = fopen (ofname, "wb");
+ if (!ofp) {
+ status = 1;
+ perror (ofname);
+ goto cleanup;
+ }
+ }
+ if (verbose)
+ fprintf (stderr,_("Writing data to %s ...\n"), ofname);
+ (*write_fun)(ofp);
+ fclose(ifp);
+ if (ofp != stdout) fclose(ofp);
+cleanup:
+ if (meta_data) free (meta_data);
+ if (ofname) free (ofname);
+ if (oprof) free (oprof);
+ if (image) free (image);
+ if (multi_out) {
+ if (++shot_select < is_raw) arg--;
+ else shot_select = 0;
+ }
+ }
+ return status;
+}
diff --git a/Source/LibRawLite/internal/dcraw_common.cpp b/Source/LibRawLite/internal/dcraw_common.cpp
new file mode 100644
index 0000000..2e5b82c
--- /dev/null
+++ b/Source/LibRawLite/internal/dcraw_common.cpp
@@ -0,0 +1,7449 @@
+/*
+ GENERATED FILE, DO NOT EDIT
+ Generated from dcraw/dcraw.c at Mon May 4 22:14:56 2009
+ Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+ for copyright information.
+*/
+
+#line 257 "dcraw/dcraw.c"
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#define LIBRAW_IO_REDEFINED
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+
+#line 267 "dcraw/dcraw.c"
+
+#ifndef __GLIBC__
+char *my_memmem (char *haystack, size_t haystacklen,
+ char *needle, size_t needlelen)
+{
+ char *c;
+ for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
+ if (!memcmp (c, needle, needlelen))
+ return c;
+ return 0;
+}
+#define memmem my_memmem
+#endif
+
+#line 301 "dcraw/dcraw.c"
+
+ushort CLASS sget2 (uchar *s)
+{
+ if (order == 0x4949) /* "II" means little-endian */
+ return s[0] | s[1] << 8;
+ else /* "MM" means big-endian */
+ return s[0] << 8 | s[1];
+}
+
+ushort CLASS get2()
+{
+ uchar str[2] = { 0xff,0xff };
+ fread (str, 1, 2, ifp);
+ return sget2(str);
+}
+
+unsigned CLASS sget4 (uchar *s)
+{
+ if (order == 0x4949)
+ return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
+ else
+ return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
+}
+#define sget4(s) sget4((uchar *)s)
+
+unsigned CLASS get4()
+{
+ uchar str[4] = { 0xff,0xff,0xff,0xff };
+ fread (str, 1, 4, ifp);
+ return sget4(str);
+}
+
+unsigned CLASS getint (int type)
+{
+ return type == 3 ? get2() : get4();
+}
+
+float CLASS int_to_float (int i)
+{
+ union { int i; float f; } u;
+ u.i = i;
+ return u.f;
+}
+
+double CLASS getreal (int type)
+{
+ union { char c[8]; double d; } u;
+ int i, rev;
+
+ switch (type) {
+ case 3: return (unsigned short) get2();
+ case 4: return (unsigned int) get4();
+ case 5: u.d = (unsigned int) get4();
+ return u.d / (unsigned int) get4();
+ case 8: return (signed short) get2();
+ case 9: return (signed int) get4();
+ case 10: u.d = (signed int) get4();
+ return u.d / (signed int) get4();
+ case 11: return int_to_float (get4());
+ case 12:
+ rev = 7 * ((order == 0x4949) == (ntohs(0x1234) == 0x1234));
+ for (i=0; i < 8; i++)
+ u.c[i ^ rev] = fgetc(ifp);
+ return u.d;
+ default: return fgetc(ifp);
+ }
+}
+
+void CLASS read_shorts (ushort *pixel, int count)
+{
+ if (fread (pixel, 2, count, ifp) < count) derror();
+ if ((order == 0x4949) == (ntohs(0x1234) == 0x1234))
+ swab ((char*)pixel, (char*)pixel, count*2);
+}
+#line 378 "dcraw/dcraw.c"
+void CLASS canon_black (double dark[2])
+{
+ int c, diff, row, col;
+
+ if (raw_width < width+4) return;
+ FORC(2) dark[c] /= (raw_width-width-2) * height >> 1;
+ if ((diff = dark[0] - dark[1]))
+ for (row=0; row < height; row++)
+ for (col=1; col < width; col+=2)
+ BAYER(row,col) += diff;
+ dark[1] += diff;
+ black = (dark[0] + dark[1] + 1) / 2;
+}
+
+void CLASS canon_600_fixed_wb (int temp)
+{
+ static const short mul[4][5] = {
+ { 667, 358,397,565,452 },
+ { 731, 390,367,499,517 },
+ { 1119, 396,348,448,537 },
+ { 1399, 485,431,508,688 } };
+ int lo, hi, i;
+ float frac=0;
+
+ for (lo=4; --lo; )
+ if (*mul[lo] <= temp) break;
+ for (hi=0; hi < 3; hi++)
+ if (*mul[hi] >= temp) break;
+ if (lo != hi)
+ frac = (float) (temp - *mul[lo]) / (*mul[hi] - *mul[lo]);
+ for (i=1; i < 5; i++)
+ pre_mul[i-1] = 1 / (frac * mul[hi][i] + (1-frac) * mul[lo][i]);
+}
+
+/* Return values: 0 = white 1 = near white 2 = not white */
+int CLASS canon_600_color (int ratio[2], int mar)
+{
+ int clipped=0, target, miss;
+
+ if (flash_used) {
+ if (ratio[1] < -104)
+ { ratio[1] = -104; clipped = 1; }
+ if (ratio[1] > 12)
+ { ratio[1] = 12; clipped = 1; }
+ } else {
+ if (ratio[1] < -264 || ratio[1] > 461) return 2;
+ if (ratio[1] < -50)
+ { ratio[1] = -50; clipped = 1; }
+ if (ratio[1] > 307)
+ { ratio[1] = 307; clipped = 1; }
+ }
+ target = flash_used || ratio[1] < 197
+ ? -38 - (398 * ratio[1] >> 10)
+ : -123 + (48 * ratio[1] >> 10);
+ if (target - mar <= ratio[0] &&
+ target + 20 >= ratio[0] && !clipped) return 0;
+ miss = target - ratio[0];
+ if (abs(miss) >= mar*4) return 2;
+ if (miss < -20) miss = -20;
+ if (miss > mar) miss = mar;
+ ratio[0] = target - miss;
+ return 1;
+}
+
+void CLASS canon_600_auto_wb()
+{
+ int mar, row, col, i, j, st, count[] = { 0,0 };
+ int test[8], total[2][8], ratio[2][2], stat[2];
+
+ memset (&total, 0, sizeof total);
+ i = canon_ev + 0.5;
+ if (i < 10) mar = 150;
+ else if (i > 12) mar = 20;
+ else mar = 280 - 20 * i;
+ if (flash_used) mar = 80;
+ for (row=14; row < height-14; row+=4)
+ for (col=10; col < width; col+=2) {
+ for (i=0; i < 8; i++)
+ test[(i & 4) + FC(row+(i >> 1),col+(i & 1))] =
+ BAYER(row+(i >> 1),col+(i & 1));
+ for (i=0; i < 8; i++)
+ if (test[i] < 150 || test[i] > 1500) goto next;
+ for (i=0; i < 4; i++)
+ if (abs(test[i] - test[i+4]) > 50) goto next;
+ for (i=0; i < 2; i++) {
+ for (j=0; j < 4; j+=2)
+ ratio[i][j >> 1] = ((test[i*4+j+1]-test[i*4+j]) << 10) / test[i*4+j];
+ stat[i] = canon_600_color (ratio[i], mar);
+ }
+ if ((st = stat[0] | stat[1]) > 1) goto next;
+ for (i=0; i < 2; i++)
+ if (stat[i])
+ for (j=0; j < 2; j++)
+ test[i*4+j*2+1] = test[i*4+j*2] * (0x400 + ratio[i][j]) >> 10;
+ for (i=0; i < 8; i++)
+ total[st][i] += test[i];
+ count[st]++;
+next: ;
+ }
+ if (count[0] | count[1]) {
+ st = count[0]*200 < count[1];
+ for (i=0; i < 4; i++)
+ pre_mul[i] = 1.0 / (total[st][i] + total[st][i+4]);
+ }
+}
+
+void CLASS canon_600_coeff()
+{
+ static const short table[6][12] = {
+ { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
+ { -1203,1715,-1136,1648, 1388,-876,267,245, -1641,2153,3921,-3409 },
+ { -615,1127,-1563,2075, 1437,-925,509,3, -756,1268,2519,-2007 },
+ { -190,702,-1886,2398, 2153,-1641,763,-251, -452,964,3040,-2528 },
+ { -190,702,-1878,2390, 1861,-1349,905,-393, -432,944,2617,-2105 },
+ { -807,1319,-1785,2297, 1388,-876,769,-257, -230,742,2067,-1555 } };
+ int t=0, i, c;
+ float mc, yc;
+
+ mc = pre_mul[1] / pre_mul[2];
+ yc = pre_mul[3] / pre_mul[2];
+ if (mc > 1 && mc <= 1.28 && yc < 0.8789) t=1;
+ if (mc > 1.28 && mc <= 2) {
+ if (yc < 0.8789) t=3;
+ else if (yc <= 2) t=4;
+ }
+ if (flash_used) t=5;
+ for (raw_color = i=0; i < 3; i++)
+ FORCC rgb_cam[i][c] = table[t][i*4 + c] / 1024.0;
+}
+
+void CLASS canon_600_load_raw()
+{
+ uchar data[1120], *dp;
+ ushort pixel[896], *pix;
+ int irow, row, col, val;
+ static const short mul[4][2] =
+ { { 1141,1145 }, { 1128,1109 }, { 1178,1149 }, { 1128,1109 } };
+
+ for (irow=row=0; irow < height; irow++) {
+ if (fread (data, 1, raw_width*5/4, ifp) < raw_width*5/4) derror();
+ for (dp=data, pix=pixel; dp < data+1120; dp+=10, pix+=8) {
+ pix[0] = (dp[0] << 2) + (dp[1] >> 6 );
+ pix[1] = (dp[2] << 2) + (dp[1] >> 4 & 3);
+ pix[2] = (dp[3] << 2) + (dp[1] >> 2 & 3);
+ pix[3] = (dp[4] << 2) + (dp[1] & 3);
+ pix[4] = (dp[5] << 2) + (dp[9] & 3);
+ pix[5] = (dp[6] << 2) + (dp[9] >> 2 & 3);
+ pix[6] = (dp[7] << 2) + (dp[9] >> 4 & 3);
+ pix[7] = (dp[8] << 2) + (dp[9] >> 6 );
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = pixel[col];
+ for (col=width; col < raw_width; col++)
+ {
+ black += pixel[col];
+ }
+ if ((row+=2) > height) row = 1;
+ }
+ if (raw_width > width)
+ black = black / ((raw_width - width) * height) - 4;
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ if ((val = BAYER(row,col) - black) < 0) val = 0;
+ val = val * mul[row & 3][col & 1] >> 9;
+ BAYER(row,col) = val;
+ }
+ canon_600_fixed_wb(1311);
+ canon_600_auto_wb();
+ canon_600_coeff();
+ maximum = (0x3ff - black) * 1109 >> 9;
+ black = 0;
+}
+
+void CLASS remove_zeroes()
+{
+ unsigned row, col, tot, n, r, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,0,2);
+#endif
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ if (BAYER(row,col) == 0) {
+ tot = n = 0;
+ for (r = row-2; r <= row+2; r++)
+ for (c = col-2; c <= col+2; c++)
+ if (r < height && c < width &&
+ FC(r,c) == FC(row,col) && BAYER(r,c))
+ tot += (n++,BAYER(r,c));
+ if (n) BAYER(row,col) = tot/n;
+ }
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,1,2);
+#endif
+}
+
+int CLASS canon_s2is()
+{
+ unsigned row;
+
+ for (row=0; row < 100; row++) {
+ fseek (ifp, row*3340 + 3284, SEEK_SET);
+ if (getc(ifp) > 15) return 1;
+ }
+ return 0;
+}
+
+void CLASS canon_a5_load_raw()
+{
+ ushort data[2565], *dp, pixel;
+ int vbits=0, buf=0, row, col, bc=0;
+
+ order = 0x4949;
+ for (row=-top_margin; row < raw_height-top_margin; row++) {
+ read_shorts (dp=data, raw_width * 10 / 16);
+ for (col=-left_margin; col < raw_width-left_margin; col++) {
+ if ((vbits -= 10) < 0)
+ buf = (vbits += 16, (buf << 16) + *dp++);
+ pixel = buf >> vbits & 0x3ff;
+ if ((unsigned) row < height && (unsigned) col < width)
+ BAYER(row,col) = pixel;
+ else if (col > 1-left_margin && col != width)
+ black += (bc++,pixel);
+ }
+ }
+ if (bc) black /= bc;
+ maximum = 0x3ff;
+
+ if (raw_width > 1600) remove_zeroes();
+}
+
+/*
+ getbits(-1) initializes the buffer
+ getbits(n) where 0 <= n <= 25 returns an n-bit integer
+ */
+unsigned CLASS getbits (int nbits)
+{
+#ifdef LIBRAW_NOTHREADS
+ static unsigned bitbuf=0;
+ static int vbits=0, reset=0;
+#else
+#define bitbuf tls->getbits.bitbuf
+#define vbits tls->getbits.vbits
+#define reset tls->getbits.reset
+#endif
+ unsigned c;
+
+ if (nbits == -1)
+ return bitbuf = vbits = reset = 0;
+ if (nbits == 0 || reset) return 0;
+ while (vbits < nbits) {
+ if ((c = fgetc(ifp)) == EOF) derror();
+ if ((reset = zero_after_ff && c == 0xff && fgetc(ifp))) return 0;
+ bitbuf = (bitbuf << 8) + (uchar) c;
+ vbits += 8;
+ }
+ vbits -= nbits;
+ return bitbuf << (32-nbits-vbits) >> (32-nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#undef reset
+#endif
+}
+
+void CLASS init_decoder()
+{
+ memset (first_decode, 0, sizeof first_decode);
+ free_decode = first_decode;
+}
+
+/*
+ Construct a decode tree according to the specification in *source.
+ The first 16 bytes specify how many codes should be 1-bit, 2-bit
+ 3-bit, etc. Bytes after that are the leaf values.
+
+ For example, if the source is
+
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+ 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
+
+ then the code is
+
+ 00 0x04
+ 010 0x03
+ 011 0x05
+ 100 0x06
+ 101 0x02
+ 1100 0x07
+ 1101 0x01
+ 11100 0x08
+ 11101 0x09
+ 11110 0x00
+ 111110 0x0a
+ 1111110 0x0b
+ 1111111 0xff
+ */
+uchar * CLASS make_decoder (const uchar *source, int level)
+{
+ struct decode *cur;
+#ifndef LIBRAW_NOTHREADS
+#define t_leaf tls->make_decoder_leaf
+#else
+ static int t_leaf;
+#endif
+ int i, next;
+
+ if (level==0) t_leaf=0;
+ cur = free_decode++;
+ if (free_decode > first_decode+2048) {
+#ifdef LIBRAW_LIBRARY_BUILD
+ throw LIBRAW_EXCEPTION_DECODE_RAW;
+#else
+ fprintf (stderr,_("%s: decoder table overflow\n"), ifname);
+ longjmp (failure, 2);
+#endif
+ }
+ for (i=next=0; i <= t_leaf && next < 16; )
+ i += source[next++];
+ if (i > t_leaf) {
+ if (level < next) {
+ cur->branch[0] = free_decode;
+ make_decoder (source, level+1);
+ cur->branch[1] = free_decode;
+ make_decoder (source, level+1);
+ } else
+ cur->leaf = source[16 + t_leaf++];
+ }
+ return (uchar *) source + 16 + t_leaf;
+#ifndef LIBRAW_NOTHREADS
+#undef t_leaf
+#endif
+}
+
+void CLASS crw_init_tables (unsigned table)
+{
+ static const uchar first_tree[3][29] = {
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0,
+ 0x04,0x03,0x05,0x06,0x02,0x07,0x01,0x08,0x09,0x00,0x0a,0x0b,0xff },
+ { 0,2,2,3,1,1,1,1,2,0,0,0,0,0,0,0,
+ 0x03,0x02,0x04,0x01,0x05,0x00,0x06,0x07,0x09,0x08,0x0a,0x0b,0xff },
+ { 0,0,6,3,1,1,2,0,0,0,0,0,0,0,0,0,
+ 0x06,0x05,0x07,0x04,0x08,0x03,0x09,0x02,0x00,0x0a,0x01,0x0b,0xff },
+ };
+ static const uchar second_tree[3][180] = {
+ { 0,2,2,2,1,4,2,1,2,5,1,1,0,0,0,139,
+ 0x03,0x04,0x02,0x05,0x01,0x06,0x07,0x08,
+ 0x12,0x13,0x11,0x14,0x09,0x15,0x22,0x00,0x21,0x16,0x0a,0xf0,
+ 0x23,0x17,0x24,0x31,0x32,0x18,0x19,0x33,0x25,0x41,0x34,0x42,
+ 0x35,0x51,0x36,0x37,0x38,0x29,0x79,0x26,0x1a,0x39,0x56,0x57,
+ 0x28,0x27,0x52,0x55,0x58,0x43,0x76,0x59,0x77,0x54,0x61,0xf9,
+ 0x71,0x78,0x75,0x96,0x97,0x49,0xb7,0x53,0xd7,0x74,0xb6,0x98,
+ 0x47,0x48,0x95,0x69,0x99,0x91,0xfa,0xb8,0x68,0xb5,0xb9,0xd6,
+ 0xf7,0xd8,0x67,0x46,0x45,0x94,0x89,0xf8,0x81,0xd5,0xf6,0xb4,
+ 0x88,0xb1,0x2a,0x44,0x72,0xd9,0x87,0x66,0xd4,0xf5,0x3a,0xa7,
+ 0x73,0xa9,0xa8,0x86,0x62,0xc7,0x65,0xc8,0xc9,0xa1,0xf4,0xd1,
+ 0xe9,0x5a,0x92,0x85,0xa6,0xe7,0x93,0xe8,0xc1,0xc6,0x7a,0x64,
+ 0xe1,0x4a,0x6a,0xe6,0xb3,0xf1,0xd3,0xa5,0x8a,0xb2,0x9a,0xba,
+ 0x84,0xa4,0x63,0xe5,0xc5,0xf3,0xd2,0xc4,0x82,0xaa,0xda,0xe4,
+ 0xf2,0xca,0x83,0xa3,0xa2,0xc3,0xea,0xc2,0xe2,0xe3,0xff,0xff },
+ { 0,2,2,1,4,1,4,1,3,3,1,0,0,0,0,140,
+ 0x02,0x03,0x01,0x04,0x05,0x12,0x11,0x06,
+ 0x13,0x07,0x08,0x14,0x22,0x09,0x21,0x00,0x23,0x15,0x31,0x32,
+ 0x0a,0x16,0xf0,0x24,0x33,0x41,0x42,0x19,0x17,0x25,0x18,0x51,
+ 0x34,0x43,0x52,0x29,0x35,0x61,0x39,0x71,0x62,0x36,0x53,0x26,
+ 0x38,0x1a,0x37,0x81,0x27,0x91,0x79,0x55,0x45,0x28,0x72,0x59,
+ 0xa1,0xb1,0x44,0x69,0x54,0x58,0xd1,0xfa,0x57,0xe1,0xf1,0xb9,
+ 0x49,0x47,0x63,0x6a,0xf9,0x56,0x46,0xa8,0x2a,0x4a,0x78,0x99,
+ 0x3a,0x75,0x74,0x86,0x65,0xc1,0x76,0xb6,0x96,0xd6,0x89,0x85,
+ 0xc9,0xf5,0x95,0xb4,0xc7,0xf7,0x8a,0x97,0xb8,0x73,0xb7,0xd8,
+ 0xd9,0x87,0xa7,0x7a,0x48,0x82,0x84,0xea,0xf4,0xa6,0xc5,0x5a,
+ 0x94,0xa4,0xc6,0x92,0xc3,0x68,0xb5,0xc8,0xe4,0xe5,0xe6,0xe9,
+ 0xa2,0xa3,0xe3,0xc2,0x66,0x67,0x93,0xaa,0xd4,0xd5,0xe7,0xf8,
+ 0x88,0x9a,0xd7,0x77,0xc4,0x64,0xe2,0x98,0xa5,0xca,0xda,0xe8,
+ 0xf3,0xf6,0xa9,0xb2,0xb3,0xf2,0xd2,0x83,0xba,0xd3,0xff,0xff },
+ { 0,0,6,2,1,3,3,2,5,1,2,2,8,10,0,117,
+ 0x04,0x05,0x03,0x06,0x02,0x07,0x01,0x08,
+ 0x09,0x12,0x13,0x14,0x11,0x15,0x0a,0x16,0x17,0xf0,0x00,0x22,
+ 0x21,0x18,0x23,0x19,0x24,0x32,0x31,0x25,0x33,0x38,0x37,0x34,
+ 0x35,0x36,0x39,0x79,0x57,0x58,0x59,0x28,0x56,0x78,0x27,0x41,
+ 0x29,0x77,0x26,0x42,0x76,0x99,0x1a,0x55,0x98,0x97,0xf9,0x48,
+ 0x54,0x96,0x89,0x47,0xb7,0x49,0xfa,0x75,0x68,0xb6,0x67,0x69,
+ 0xb9,0xb8,0xd8,0x52,0xd7,0x88,0xb5,0x74,0x51,0x46,0xd9,0xf8,
+ 0x3a,0xd6,0x87,0x45,0x7a,0x95,0xd5,0xf6,0x86,0xb4,0xa9,0x94,
+ 0x53,0x2a,0xa8,0x43,0xf5,0xf7,0xd4,0x66,0xa7,0x5a,0x44,0x8a,
+ 0xc9,0xe8,0xc8,0xe7,0x9a,0x6a,0x73,0x4a,0x61,0xc7,0xf4,0xc6,
+ 0x65,0xe9,0x72,0xe6,0x71,0x91,0x93,0xa6,0xda,0x92,0x85,0x62,
+ 0xf3,0xc5,0xb2,0xa4,0x84,0xba,0x64,0xa5,0xb3,0xd2,0x81,0xe5,
+ 0xd3,0xaa,0xc4,0xca,0xf2,0xb1,0xe4,0xd1,0x83,0x63,0xea,0xc3,
+ 0xe2,0x82,0xf1,0xa3,0xc2,0xa1,0xc1,0xe3,0xa2,0xe1,0xff,0xff }
+ };
+ if (table > 2) table = 2;
+ init_decoder();
+ make_decoder ( first_tree[table], 0);
+ second_decode = free_decode;
+ make_decoder (second_tree[table], 0);
+}
+
+/*
+ Return 0 if the image starts with compressed data,
+ 1 if it starts with uncompressed low-order bits.
+
+ In Canon compressed data, 0xff is always followed by 0x00.
+ */
+int CLASS canon_has_lowbits()
+{
+ uchar test[0x4000];
+ int ret=1, i;
+
+ fseek (ifp, 0, SEEK_SET);
+ fread (test, 1, sizeof test, ifp);
+ for (i=540; i < sizeof test - 1; i++)
+ if (test[i] == 0xff) {
+ if (test[i+1]) return 1;
+ ret=0;
+ }
+ return ret;
+}
+
+void CLASS canon_compressed_load_raw()
+{
+ ushort *pixel, *prow;
+ int nblocks, lowbits, i, row, r, col, save, val;
+ unsigned irow, icol;
+ struct decode *decode, *dindex;
+ int block, diffbuf[64], leaf, len, diff, carry=0, pnum=0, base[2];
+ double dark[2] = { 0,0 };
+ uchar c;
+
+ crw_init_tables (tiff_compress);
+ pixel = (ushort *) calloc (raw_width*8, sizeof *pixel);
+ merror (pixel, "canon_compressed_load_raw()");
+ lowbits = canon_has_lowbits();
+ if (!lowbits) maximum = 0x3ff;
+ fseek (ifp, 540 + lowbits*raw_height*raw_width/4, SEEK_SET);
+ zero_after_ff = 1;
+ getbits(-1);
+ for (row=0; row < raw_height; row+=8) {
+ nblocks = MIN (8, raw_height-row) * raw_width >> 6;
+ for (block=0; block < nblocks; block++) {
+ memset (diffbuf, 0, sizeof diffbuf);
+ decode = first_decode;
+ for (i=0; i < 64; i++ ) {
+ for (dindex=decode; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ leaf = dindex->leaf;
+ decode = second_decode;
+ if (leaf == 0 && i) break;
+ if (leaf == 0xff) continue;
+ i += leaf >> 4;
+ len = leaf & 15;
+ if (len == 0) continue;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ if (i < 64) diffbuf[i] = diff;
+ }
+ diffbuf[0] += carry;
+ carry = diffbuf[0];
+ for (i=0; i < 64; i++ ) {
+ if (pnum++ % raw_width == 0)
+ base[0] = base[1] = 512;
+ if ((pixel[(block << 6) + i] = base[i & 1] += diffbuf[i]) >> 10)
+ derror();
+ }
+ }
+ if (lowbits) {
+ save = ftell(ifp);
+ fseek (ifp, 26 + row*raw_width/4, SEEK_SET);
+ for (prow=pixel, i=0; i < raw_width*2; i++) {
+ c = fgetc(ifp);
+ for (r=0; r < 8; r+=2, prow++) {
+ val = (*prow << 2) + ((c >> r) & 3);
+ if (raw_width == 2672 && val < 512) val += 2;
+ *prow = val;
+ }
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ for (r=0; r < 8; r++) {
+ irow = row - top_margin + r;
+ if (irow >= height) continue;
+ for (col=0; col < raw_width; col++) {
+ icol = col - left_margin;
+ if (icol < width)
+ BAYER(irow,icol) = pixel[r*raw_width+col];
+ else if (col > 1)
+ dark[icol & 1] += pixel[r*raw_width+col];
+ }
+ }
+ }
+ free (pixel);
+ canon_black (dark);
+}
+
+#line 885 "dcraw/dcraw.c"
+int CLASS ljpeg_start (struct jhead *jh, int info_only)
+{
+ int c, tag, len;
+ uchar data[0x10000], *dp;
+
+ if (!info_only) init_decoder();
+ memset (jh, 0, sizeof *jh);
+ FORC(6) jh->huff[c] = free_decode;
+ jh->restart = INT_MAX;
+ fread (data, 2, 1, ifp);
+ if (data[1] != 0xd8) return 0;
+ do {
+ fread (data, 2, 2, ifp);
+ tag = data[0] << 8 | data[1];
+ len = (data[2] << 8 | data[3]) - 2;
+ if (tag <= 0xff00) return 0;
+ fread (data, 1, len, ifp);
+ switch (tag) {
+ case 0xffc3:
+ jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3;
+ case 0xffc0:
+ jh->bits = data[0];
+ jh->high = data[1] << 8 | data[2];
+ jh->wide = data[3] << 8 | data[4];
+ jh->clrs = data[5] + jh->sraw;
+ if (len == 9 && !dng_version) getc(ifp);
+ break;
+ case 0xffc4:
+ if (info_only) break;
+ for (dp = data; dp < data+len && *dp < 4; ) {
+ jh->huff[*dp] = free_decode;
+ dp = make_decoder (++dp, 0);
+ }
+ break;
+ case 0xffda:
+ jh->psv = data[1+data[0]*2];
+ jh->bits -= data[3+data[0]*2] & 15;
+ break;
+ case 0xffdd:
+ jh->restart = data[0] << 8 | data[1];
+ }
+ } while (tag != 0xffda);
+ if (info_only) return 1;
+ if (jh->sraw) {
+ FORC(4) jh->huff[2+c] = jh->huff[1];
+ FORC(jh->sraw) jh->huff[1+c] = jh->huff[0];
+ }
+ jh->row = (ushort *) calloc (jh->wide*jh->clrs, 4);
+ merror (jh->row, "ljpeg_start()");
+ return zero_after_ff = 1;
+}
+
+int CLASS ljpeg_diff (struct decode *dindex)
+{
+ int len, diff;
+
+ while (dindex->branch[0])
+ dindex = dindex->branch[getbits(1)];
+ len = dindex->leaf;
+ if (len == 16 && (!dng_version || dng_version >= 0x1010000))
+ return -32768;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ return diff;
+}
+
+ushort * CLASS ljpeg_row (int jrow, struct jhead *jh)
+{
+ int col, c, diff, pred, spred=0;
+ ushort mark=0, *row[3];
+
+ if (jrow * jh->wide % jh->restart == 0) {
+ FORC(6) jh->vpred[c] = 1 << (jh->bits-1);
+ if (jrow)
+ do mark = (mark << 8) + (c = fgetc(ifp));
+ while (c != EOF && mark >> 4 != 0xffd);
+ getbits(-1);
+ }
+ FORC3 row[c] = jh->row + jh->wide*jh->clrs*((jrow+c) & 1);
+ for (col=0; col < jh->wide; col++)
+ FORC(jh->clrs) {
+ diff = ljpeg_diff (jh->huff[c]);
+ if (jh->sraw && c <= jh->sraw && (col | c))
+ pred = spred;
+ else if (col) pred = row[0][-jh->clrs];
+ else pred = (jh->vpred[c] += diff) - diff;
+ if (jrow && col) switch (jh->psv) {
+ case 1: break;
+ case 2: pred = row[1][0]; break;
+ case 3: pred = row[1][-jh->clrs]; break;
+ case 4: pred = pred + row[1][0] - row[1][-jh->clrs]; break;
+ case 5: pred = pred + ((row[1][0] - row[1][-jh->clrs]) >> 1); break;
+ case 6: pred = row[1][0] + ((pred - row[1][-jh->clrs]) >> 1); break;
+ case 7: pred = (pred + row[1][0]) >> 1; break;
+ default: pred = 0;
+ }
+ if ((**row = pred + diff) >> jh->bits) derror();
+ if (c <= jh->sraw) spred = **row;
+ row[0]++; row[1]++;
+ }
+ return row[2];
+}
+
+void CLASS lossless_jpeg_load_raw()
+{
+ int jwide, jrow, jcol, val, jidx, i, j, row=0, col=0;
+ double dark[2] = { 0,0 };
+ struct jhead jh;
+ int min=INT_MAX;
+ ushort *rp;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ jwide = jh.wide * jh.clrs;
+
+ for (jrow=0; jrow < jh.high; jrow++) {
+ rp = ljpeg_row (jrow, &jh);
+ for (jcol=0; jcol < jwide; jcol++) {
+ val = *rp++;
+ if (jh.bits <= 12)
+ val = curve[val & 0xfff];
+ if (cr2_slice[0]) {
+ jidx = jrow*jwide + jcol;
+ i = jidx / (cr2_slice[1]*jh.high);
+ if ((j = i >= cr2_slice[0]))
+ i = cr2_slice[0];
+ jidx -= i * (cr2_slice[1]*jh.high);
+ row = jidx / cr2_slice[1+j];
+ col = jidx % cr2_slice[1+j] + i*cr2_slice[1];
+ }
+ if (raw_width == 3984 && (col -= 2) < 0)
+ col += (row--,raw_width);
+ if ((unsigned) (row-top_margin) < height) {
+ if ((unsigned) (col-left_margin) < width) {
+ BAYER(row-top_margin,col-left_margin) = val;
+ if (min > val) min = val;
+ } else if (col > 1)
+ dark[(col-left_margin) & 1] += val;
+ }
+ if (++col >= raw_width)
+ col = (row++,0);
+ }
+ }
+ free (jh.row);
+ canon_black (dark);
+ if (!strcasecmp(make,"KODAK"))
+ black = min;
+}
+
+void CLASS canon_sraw_load_raw()
+{
+ struct jhead jh;
+ short *rp=0, (*ip)[4];
+ int jwide, slice, scol, ecol, row, col, jrow=0, jcol=0, pix[3], c;
+ int v[3]={0,0,0}, ver, hue;
+ char *cp;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ jwide = (jh.wide >>= 1) * jh.clrs;
+
+ for (ecol=slice=0; slice <= cr2_slice[0]; slice++) {
+ scol = ecol;
+ ecol += cr2_slice[1] * 2 / jh.clrs;
+ if (!cr2_slice[0] || ecol > raw_width-1) ecol = raw_width & -2;
+ for (row=0; row < height; row += (jh.clrs >> 1) - 1) {
+ ip = (short (*)[4]) image + row*width;
+ for (col=scol; col < ecol; col+=2, jcol+=jh.clrs) {
+ if ((jcol %= jwide) == 0)
+ rp = (short *) ljpeg_row (jrow++, &jh);
+ if (col >= width) continue;
+ FORC (jh.clrs-2)
+ ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c];
+ ip[col][1] = rp[jcol+jh.clrs-2] - 16384;
+ ip[col][2] = rp[jcol+jh.clrs-1] - 16384;
+ }
+ }
+ }
+ for (cp=model2; *cp && !isdigit(*cp); cp++);
+ sscanf (cp, "%d.%d.%d", v, v+1, v+2);
+ ver = (v[0]*1000 + v[1])*1000 + v[2];
+ hue = (jh.sraw+1) << 2;
+ if (unique_id == 0x80000218 && ver > 1000006 && ver < 3000000)
+ hue = jh.sraw << 1;
+ ip = (short (*)[4]) image;
+ rp = ip[0];
+ for (row=0; row < height; row++, ip+=width) {
+ if (row & (jh.sraw >> 1))
+ for (col=0; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (row == height-1)
+ ip[col][c] = ip[col-width][c];
+ else ip[col][c] = (ip[col-width][c] + ip[col+width][c] + 1) >> 1;
+ for (col=1; col < width; col+=2)
+ for (c=1; c < 3; c++)
+ if (col == width-1)
+ ip[col][c] = ip[col-1][c];
+ else ip[col][c] = (ip[col-1][c] + ip[col+1][c] + 1) >> 1;
+ }
+ for ( ; rp < ip[0]; rp+=4) {
+ if (unique_id < 0x80000200) {
+ pix[0] = rp[0] + rp[2] - 512;
+ pix[2] = rp[0] + rp[1] - 512;
+ pix[1] = rp[0] + ((-778*rp[1] - (rp[2] << 11)) >> 12) - 512;
+ } else {
+ rp[1] = (rp[1] << 2) + hue;
+ rp[2] = (rp[2] << 2) + hue;
+ pix[0] = rp[0] + (( 200*rp[1] + 22929*rp[2]) >> 14);
+ pix[1] = rp[0] + ((-5640*rp[1] - 11751*rp[2]) >> 14);
+ pix[2] = rp[0] + ((29040*rp[1] - 101*rp[2]) >> 14);
+ }
+ FORC3 rp[c] = CLIP(pix[c] * sraw_mul[c] >> 10);
+ }
+ free (jh.row);
+ maximum = 0x3fff;
+}
+
+void CLASS adobe_copy_pixel (int row, int col, ushort **rp)
+{
+ unsigned r, c;
+
+ r = row -= top_margin;
+ c = col -= left_margin;
+ if (is_raw == 2 && shot_select) (*rp)++;
+ if (filters) {
+ if (fuji_width) {
+ r = row + fuji_width - 1 - (col >> 1);
+ c = row + ((col+1) >> 1);
+ }
+ if (r < height && c < width)
+ BAYER(r,c) = **rp < 0x1000 ? curve[**rp] : **rp;
+ *rp += is_raw;
+ } else {
+ if (r < height && c < width)
+ FORC(tiff_samples)
+ image[row*width+col][c] = (*rp)[c] < 0x1000 ? curve[(*rp)[c]]:(*rp)[c];
+ *rp += tiff_samples;
+ }
+ if (is_raw == 2 && shot_select) (*rp)--;
+}
+
+void CLASS adobe_dng_load_raw_lj()
+{
+ unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col;
+ struct jhead jh;
+ ushort *rp;
+
+ while (trow < raw_height) {
+ save = ftell(ifp);
+ if (tile_length < INT_MAX)
+ fseek (ifp, get4(), SEEK_SET);
+ if (!ljpeg_start (&jh, 0)) break;
+ jwide = jh.wide;
+ if (filters) jwide *= jh.clrs;
+ jwide /= is_raw;
+ for (row=col=jrow=0; jrow < jh.high; jrow++) {
+ rp = ljpeg_row (jrow, &jh);
+ for (jcol=0; jcol < jwide; jcol++) {
+ adobe_copy_pixel (trow+row, tcol+col, &rp);
+ if (++col >= tile_width || col >= raw_width)
+ row += 1 + (col = 0);
+ }
+ }
+ fseek (ifp, save+4, SEEK_SET);
+ if ((tcol += tile_width) >= raw_width)
+ trow += tile_length + (tcol = 0);
+ free (jh.row);
+ }
+}
+
+void CLASS adobe_dng_load_raw_nc()
+{
+ ushort *pixel, *rp;
+ int row, col;
+
+ pixel = (ushort *) calloc (raw_width * tiff_samples, sizeof *pixel);
+ merror (pixel, "adobe_dng_load_raw_nc()");
+ for (row=0; row < raw_height; row++) {
+ if (tiff_bps == 16)
+ read_shorts (pixel, raw_width * tiff_samples);
+ else {
+ getbits(-1);
+ for (col=0; col < raw_width * tiff_samples; col++)
+ pixel[col] = getbits(tiff_bps);
+ }
+ for (rp=pixel, col=0; col < raw_width; col++)
+ adobe_copy_pixel (row, col, &rp);
+ }
+ free (pixel);
+}
+
+void CLASS pentax_tree()
+{
+ ushort bit[2][13];
+ struct decode *cur;
+ int c, i, j;
+
+ init_decoder();
+ FORC(13) bit[0][c] = get2();
+ FORC(13) bit[1][c] = fgetc(ifp) & 15;
+ FORC(13) {
+ cur = first_decode;
+ for (i=0; i < bit[1][c]; i++) {
+ j = bit[0][c] >> (11-i) & 1;
+ if (!cur->branch[j]) cur->branch[j] = ++free_decode;
+ cur = cur->branch[j];
+ }
+ cur->leaf = c;
+ }
+}
+
+void CLASS pentax_k10_load_raw()
+{
+ int row, col, diff;
+ ushort vpred[2][2] = {{0,0},{0,0}}, hpred[2];
+
+ getbits(-1);
+ for (row=0; row < raw_height; row++)
+ {
+ if(row >= height) break;
+ for (col=0; col < raw_width; col++) {
+ diff = ljpeg_diff (first_decode);
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ if (col < width && row < height)
+ BAYER(row,col) = hpred[col & 1];
+ if (hpred[col & 1] >> 12) derror();
+ }
+ }
+}
+
+void CLASS nikon_compressed_load_raw()
+{
+ static const uchar nikon_tree[][32] = {
+ { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy */
+ 5,4,3,6,2,7,1,0,8,9,11,10,12 },
+ { 0,1,5,1,1,1,1,1,1,2,0,0,0,0,0,0, /* 12-bit lossy after split */
+ 0x39,0x5a,0x38,0x27,0x16,5,4,3,2,1,0,11,12,12 },
+ { 0,1,4,2,3,1,2,0,0,0,0,0,0,0,0,0, /* 12-bit lossless */
+ 5,4,6,3,7,2,8,1,9,0,10,11,12 },
+ { 0,1,4,3,1,1,1,1,1,2,0,0,0,0,0,0, /* 14-bit lossy */
+ 5,6,4,7,8,3,9,2,1,0,10,11,12,13,14 },
+ { 0,1,5,1,1,1,1,1,1,1,2,0,0,0,0,0, /* 14-bit lossy after split */
+ 8,0x5c,0x4b,0x3a,0x29,7,6,5,4,3,2,1,0,13,14 },
+ { 0,1,4,2,2,3,1,2,0,0,0,0,0,0,0,0, /* 14-bit lossless */
+ 7,6,8,5,9,4,10,3,11,12,2,0,1,13,14 } };
+ struct decode *dindex;
+ ushort ver0, ver1, vpred[2][2], hpred[2], csize;
+ int i, min, max, step=0, huff=0, split=0, row, col, len, shl, diff;
+
+ fseek (ifp, meta_offset, SEEK_SET);
+ ver0 = fgetc(ifp);
+ ver1 = fgetc(ifp);
+ if (ver0 == 0x49 || ver1 == 0x58)
+ fseek (ifp, 2110, SEEK_CUR);
+ if (ver0 == 0x46) huff = 2;
+ if (tiff_bps == 14) huff += 3;
+ read_shorts (vpred[0], 4);
+ max = 1 << tiff_bps & 0x7fff;
+ if ((csize = get2()) > 1)
+ step = max / (csize-1);
+ if (ver0 == 0x44 && ver1 == 0x20 && step > 0) {
+ for (i=0; i < csize; i++)
+ curve[i*step] = get2();
+ for (i=0; i < max; i++)
+ curve[i] = ( curve[i-i%step]*(step-i%step) +
+ curve[i-i%step+step]*(i%step) ) / step;
+ fseek (ifp, meta_offset+562, SEEK_SET);
+ split = get2();
+ } else if (ver0 != 0x46 && csize <= 0x4001)
+ {
+ read_shorts (curve, max=csize);
+ }
+ while (curve[max-2] == curve[max-1]) max--;
+ init_decoder();
+ make_decoder (nikon_tree[huff], 0);
+ fseek (ifp, data_offset, SEEK_SET);
+ getbits(-1);
+ for (min=row=0; row < height; row++) {
+ if (split && row == split) {
+ init_decoder();
+ make_decoder (nikon_tree[huff+1], 0);
+ max += (min = 16) << 1;
+ }
+ for (col=0; col < raw_width; col++) {
+ for (dindex=first_decode; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ len = dindex->leaf & 15;
+ shl = dindex->leaf >> 4;
+ diff = ((getbits(len-shl) << 1) + 1) << shl >> 1;
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - !shl;
+ if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
+ else hpred[col & 1] += diff;
+ if ((ushort)(hpred[col & 1] + min) >= max) derror();
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = curve[LIM((short)hpred[col & 1],0,0x3fff)];
+
+ }
+ }
+}
+
+/*
+ Figure out if a NEF file is compressed. These fancy heuristics
+ are only needed for the D100, thanks to a bug in some cameras
+ that tags all images as "compressed".
+ */
+int CLASS nikon_is_compressed()
+{
+ uchar test[256];
+ int i;
+
+ fseek (ifp, data_offset, SEEK_SET);
+ fread (test, 1, 256, ifp);
+ for (i=15; i < 256; i+=16)
+ if (test[i]) return 1;
+ return 0;
+}
+
+/*
+ Returns 1 for a Coolpix 995, 0 for anything else.
+ */
+int CLASS nikon_e995()
+{
+ int i, histo[256];
+ const uchar often[] = { 0x00, 0x55, 0xaa, 0xff };
+
+ memset (histo, 0, sizeof histo);
+ fseek (ifp, -2000, SEEK_END);
+ for (i=0; i < 2000; i++)
+ histo[fgetc(ifp)]++;
+ for (i=0; i < 4; i++)
+ if (histo[often[i]] < 200)
+ return 0;
+ return 1;
+}
+
+/*
+ Returns 1 for a Coolpix 2100, 0 for anything else.
+ */
+int CLASS nikon_e2100()
+{
+ uchar t[12];
+ int i;
+
+ fseek (ifp, 0, SEEK_SET);
+ for (i=0; i < 1024; i++) {
+ fread (t, 1, 12, ifp);
+ if (((t[2] & t[4] & t[7] & t[9]) >> 4
+ & t[1] & t[6] & t[8] & t[11] & 3) != 3)
+ return 0;
+ }
+ return 1;
+}
+
+void CLASS nikon_3700()
+{
+ int bits, i;
+ uchar dp[24];
+ static const struct {
+ int bits;
+ char t_make[12], t_model[15];
+ } table[] = {
+ { 0x00, "PENTAX", "Optio 33WR" },
+ { 0x03, "NIKON", "E3200" },
+ { 0x32, "NIKON", "E3700" },
+ { 0x33, "OLYMPUS", "C740UZ" } };
+
+ fseek (ifp, 3072, SEEK_SET);
+ fread (dp, 1, 24, ifp);
+ bits = (dp[8] & 3) << 4 | (dp[20] & 3);
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (bits == table[i].bits) {
+ strcpy (make, table[i].t_make );
+ strcpy (model, table[i].t_model);
+ }
+}
+
+/*
+ Separates a Minolta DiMAGE Z2 from a Nikon E4300.
+ */
+int CLASS minolta_z2()
+{
+ int i, nz;
+ char tail[424];
+
+ fseek (ifp, -sizeof tail, SEEK_END);
+ fread (tail, 1, sizeof tail, ifp);
+ for (nz=i=0; i < sizeof tail; i++)
+ if (tail[i]) nz++;
+ return nz > 20;
+}
+
+/* Here raw_width is in bytes, not pixels. */
+void CLASS nikon_e900_load_raw()
+{
+ int offset=0, irow, row, col;
+
+ for (irow=0; irow < height; irow++) {
+ row = irow * 2 % height;
+ if (row == 1)
+ offset = - (-offset & -4096);
+ fseek (ifp, offset, SEEK_SET);
+ offset += raw_width;
+ getbits(-1);
+ for (col=0; col < width; col++)
+ BAYER(row,col) = getbits(10);
+ }
+}
+
+/*
+ The Fuji Super CCD is just a Bayer grid rotated 45 degrees.
+ */
+void CLASS fuji_load_raw()
+{
+ ushort *pixel;
+ int wide, row, col, r, c;
+
+ fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+ wide = fuji_width << !fuji_layout;
+ pixel = (ushort *) calloc (wide, sizeof *pixel);
+ merror (pixel, "fuji_load_raw()");
+ for (row=0; row < raw_height; row++) {
+ read_shorts (pixel, wide);
+ fseek (ifp, 2*(raw_width - wide), SEEK_CUR);
+ for (col=0; col < wide; col++) {
+ if (fuji_layout) {
+ r = fuji_width - 1 - col + (row >> 1);
+ c = col + ((row+1) >> 1);
+ } else {
+ r = fuji_width - 1 + row - (col >> 1);
+ c = row + ((col+1) >> 1);
+ }
+ BAYER(r,c) = pixel[col];
+ }
+ }
+ free (pixel);
+}
+#line 1427 "dcraw/dcraw.c"
+void CLASS ppm_thumb (FILE *tfp)
+{
+ char *thumb;
+ thumb_length = thumb_width*thumb_height*3;
+ thumb = (char *) malloc (thumb_length);
+ merror (thumb, "ppm_thumb()");
+ fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ fread (thumb, 1, thumb_length, ifp);
+ fwrite (thumb, 1, thumb_length, tfp);
+ free (thumb);
+}
+
+void CLASS layer_thumb (FILE *tfp)
+{
+ int i, c;
+ char *thumb, map[][4] = { "012","102" };
+
+ colors = thumb_misc >> 5 & 7;
+ thumb_length = thumb_width*thumb_height;
+ thumb = (char *) calloc (colors, thumb_length);
+ merror (thumb, "layer_thumb()");
+ fprintf (tfp, "P%d\n%d %d\n255\n",
+ 5 + (colors >> 1), thumb_width, thumb_height);
+ fread (thumb, thumb_length, colors, ifp);
+ for (i=0; i < thumb_length; i++)
+ FORCC putc (thumb[i+thumb_length*(map[thumb_misc >> 8][c]-'0')], tfp);
+ free (thumb);
+}
+
+void CLASS rollei_thumb (FILE *tfp)
+{
+ unsigned i;
+ ushort *thumb;
+
+ thumb_length = thumb_width * thumb_height;
+ thumb = (ushort *) calloc (thumb_length, 2);
+ merror (thumb, "rollei_thumb()");
+ fprintf (tfp, "P6\n%d %d\n255\n", thumb_width, thumb_height);
+ read_shorts (thumb, thumb_length);
+ for (i=0; i < thumb_length; i++) {
+ putc (thumb[i] << 3, tfp);
+ putc (thumb[i] >> 5 << 2, tfp);
+ putc (thumb[i] >> 11 << 3, tfp);
+ }
+ free (thumb);
+}
+
+void CLASS rollei_load_raw()
+{
+ uchar pixel[10];
+ unsigned iten=0, isix, i, buffer=0, row, col, todo[16];
+
+ isix = raw_width * raw_height * 5 / 8;
+ while (fread (pixel, 1, 10, ifp) == 10) {
+ for (i=0; i < 10; i+=2) {
+ todo[i] = iten++;
+ todo[i+1] = pixel[i] << 8 | pixel[i+1];
+ buffer = pixel[i] >> 2 | buffer << 6;
+ }
+ for ( ; i < 16; i+=2) {
+ todo[i] = isix++;
+ todo[i+1] = buffer >> (14-i)*5;
+ }
+ for (i=0; i < 16; i+=2) {
+ row = todo[i] / raw_width - top_margin;
+ col = todo[i] % raw_width - left_margin;
+ if (row < height && col < width)
+ BAYER(row,col) = (todo[i+1] & 0x3ff);
+ }
+ }
+ maximum = 0x3ff;
+}
+
+int CLASS bayer (unsigned row, unsigned col)
+{
+ return (row < height && col < width) ? BAYER(row,col) : 0;
+}
+
+void CLASS phase_one_flat_field (int is_float, int nc)
+{
+ ushort head[8];
+ unsigned wide, y, x, c, rend, cend, row, col;
+ float *mrow, num, mult[4];
+
+ read_shorts (head, 8);
+ wide = head[2] / head[4];
+ mrow = (float *) calloc (nc*wide, sizeof *mrow);
+ merror (mrow, "phase_one_flat_field()");
+ for (y=0; y < head[3] / head[5]; y++) {
+ for (x=0; x < wide; x++)
+ for (c=0; c < nc; c+=2) {
+ num = is_float ? getreal(11) : get2()/32768.0;
+ if (y==0) mrow[c*wide+x] = num;
+ else mrow[(c+1)*wide+x] = (num - mrow[c*wide+x]) / head[5];
+ }
+ if (y==0) continue;
+ rend = head[1]-top_margin + y*head[5];
+ for (row = rend-head[5]; row < height && row < rend; row++) {
+ for (x=1; x < wide; x++) {
+ for (c=0; c < nc; c+=2) {
+ mult[c] = mrow[c*wide+x-1];
+ mult[c+1] = (mrow[c*wide+x] - mult[c]) / head[4];
+ }
+ cend = head[0]-left_margin + x*head[4];
+ for (col = cend-head[4]; col < width && col < cend; col++) {
+ c = nc > 2 ? FC(row,col) : 0;
+ if (!(c & 1)) {
+ c = BAYER(row,col) * mult[c];
+ BAYER(row,col) = LIM(c,0,65535);
+ }
+ for (c=0; c < nc; c+=2)
+ mult[c] += mult[c+1];
+ }
+ }
+ for (x=0; x < wide; x++)
+ for (c=0; c < nc; c+=2)
+ mrow[c*wide+x] += mrow[(c+1)*wide+x];
+ }
+ }
+ free (mrow);
+}
+
+void CLASS phase_one_correct()
+{
+ unsigned entries, tag, data, save, col, row, type;
+ int len, i, j, k, cip, val[4], dev[4], sum, max;
+ int head[9], diff, mindiff=INT_MAX, off_412=0;
+ static const signed char dir[12][2] =
+ { {-1,-1}, {-1,1}, {1,-1}, {1,1}, {-2,0}, {0,-2}, {0,2}, {2,0},
+ {-2,-2}, {-2,2}, {2,-2}, {2,2} };
+ float poly[8], num, cfrac, frac, mult[2], *yval[2];
+ ushort t_curve[0x10000], *xval[2];
+
+ if (half_size || !meta_length) return;
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Phase One correction...\n"));
+#endif
+ fseek (ifp, meta_offset, SEEK_SET);
+ order = get2();
+ fseek (ifp, 6, SEEK_CUR);
+ fseek (ifp, meta_offset+get4(), SEEK_SET);
+ entries = get4(); get4();
+ while (entries--) {
+ tag = get4();
+ len = get4();
+ data = get4();
+ save = ftell(ifp);
+ fseek (ifp, meta_offset+data, SEEK_SET);
+ if (tag == 0x419) { /* Polynomial curve */
+ for (get4(), i=0; i < 8; i++)
+ poly[i] = getreal(11);
+ poly[3] += (ph1.tag_210 - poly[7]) * poly[6] + 1;
+ for (i=0; i < 0x10000; i++) {
+ num = (poly[5]*i + poly[3])*i + poly[1];
+ t_curve[i] = LIM(num,0,65535);
+ } goto apply; /* apply to right half */
+ } else if (tag == 0x41a) { /* Polynomial curve */
+ for (i=0; i < 4; i++)
+ poly[i] = getreal(11);
+ for (i=0; i < 0x10000; i++) {
+ for (num=0, j=4; j--; )
+ num = num * i + poly[j];
+ t_curve[i] = LIM(num+i,0,65535);
+ } apply: /* apply to whole image */
+ for (row=0; row < height; row++)
+ for (col = (tag & 1)*ph1.split_col; col < width; col++)
+ BAYER(row,col) = t_curve[BAYER(row,col)];
+ } else if (tag == 0x400) { /* Sensor defects */
+ while ((len -= 8) >= 0) {
+ col = get2() - left_margin;
+ row = get2() - top_margin;
+ type = get2(); get2();
+ if (col >= width) continue;
+ if (type == 131) /* Bad column */
+ for (row=0; row < height; row++)
+ if (FC(row,col) == 1) {
+ for (sum=i=0; i < 4; i++)
+ sum += val[i] = bayer (row+dir[i][0], col+dir[i][1]);
+ for (max=i=0; i < 4; i++) {
+ dev[i] = abs((val[i] << 2) - sum);
+ if (dev[max] < dev[i]) max = i;
+ }
+ BAYER(row,col) = (sum - val[max])/3.0 + 0.5;
+ } else {
+ for (sum=0, i=8; i < 12; i++)
+ sum += bayer (row+dir[i][0], col+dir[i][1]);
+ BAYER(row,col) = 0.5 + sum * 0.0732233 +
+ (bayer(row,col-2) + bayer(row,col+2)) * 0.3535534;
+ }
+ else if (type == 129) { /* Bad pixel */
+ if (row >= height) continue;
+ j = (FC(row,col) != 1) * 4;
+ for (sum=0, i=j; i < j+8; i++)
+ sum += bayer (row+dir[i][0], col+dir[i][1]);
+ BAYER(row,col) = (sum + 4) >> 3;
+ }
+ }
+ } else if (tag == 0x401) { /* All-color flat fields */
+ phase_one_flat_field (1, 2);
+ } else if (tag == 0x416 || tag == 0x410) {
+ phase_one_flat_field (0, 2);
+ } else if (tag == 0x40b) { /* Red+blue flat field */
+ phase_one_flat_field (0, 4);
+ } else if (tag == 0x412) {
+ fseek (ifp, 36, SEEK_CUR);
+ diff = abs (get2() - ph1.tag_21a);
+ if (mindiff > diff) {
+ mindiff = diff;
+ off_412 = ftell(ifp) - 38;
+ }
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ if (off_412) {
+ fseek (ifp, off_412, SEEK_SET);
+ for (i=0; i < 9; i++) head[i] = get4() & 0x7fff;
+ yval[0] = (float *) calloc (head[1]*head[3] + head[2]*head[4], 6);
+ merror (yval[0], "phase_one_correct()");
+ yval[1] = (float *) (yval[0] + head[1]*head[3]);
+ xval[0] = (ushort *) (yval[1] + head[2]*head[4]);
+ xval[1] = (ushort *) (xval[0] + head[1]*head[3]);
+ get2();
+ for (i=0; i < 2; i++)
+ for (j=0; j < head[i+1]*head[i+3]; j++)
+ yval[i][j] = getreal(11);
+ for (i=0; i < 2; i++)
+ for (j=0; j < head[i+1]*head[i+3]; j++)
+ xval[i][j] = get2();
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ cfrac = (float) col * head[3] / raw_width;
+ cfrac -= cip = cfrac;
+ num = BAYER(row,col) * 0.5;
+ for (i=cip; i < cip+2; i++) {
+ for (k=j=0; j < head[1]; j++)
+ if (num < xval[0][k = head[1]*i+j]) break;
+ frac = (j == 0 || j == head[1]) ? 0 :
+ (xval[0][k] - num) / (xval[0][k] - xval[0][k-1]);
+ mult[i-cip] = yval[0][k-1] * frac + yval[0][k] * (1-frac);
+ }
+ i = ((mult[0] * (1-cfrac) + mult[1] * cfrac)
+ * (row + top_margin) + num) * 2;
+ BAYER(row,col) = LIM(i,0,65535);
+ }
+ free (yval[0]);
+ }
+}
+
+void CLASS phase_one_load_raw()
+{
+ int row, col, a, b;
+ ushort *pixel, akey, bkey, mask;
+
+ fseek (ifp, ph1.key_off, SEEK_SET);
+ akey = get2();
+ bkey = get2();
+ mask = ph1.format == 1 ? 0x5555:0x1354;
+ fseek (ifp, data_offset + top_margin*raw_width*2, SEEK_SET);
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "phase_one_load_raw()");
+ for (row=0; row < height; row++) {
+ read_shorts (pixel, raw_width);
+ for (col=0; col < raw_width; col+=2) {
+ a = pixel[col+0] ^ akey;
+ b = pixel[col+1] ^ bkey;
+ pixel[col+0] = (a & mask) | (b & ~mask);
+ pixel[col+1] = (b & mask) | (a & ~mask);
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = pixel[col+left_margin];
+ }
+ free (pixel);
+ phase_one_correct();
+}
+
+unsigned CLASS ph1_bits (int nbits)
+{
+#ifndef LIBRAW_NOTHREADS
+#define bitbuf tls->ph1_bits.bitbuf
+#define vbits tls->ph1_bits.vbits
+#else
+ static UINT64 bitbuf=0;
+ static int vbits=0;
+#endif
+ if (nbits == -1)
+ return bitbuf = vbits = 0;
+ if (nbits == 0) return 0;
+ if ((vbits -= nbits) < 0) {
+ bitbuf = bitbuf << 32 | get4();
+ vbits += 32;
+ }
+ return bitbuf << (64-nbits-vbits) >> (64-nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef bitbuf
+#undef vbits
+#endif
+}
+
+void CLASS phase_one_load_raw_c()
+{
+ static const int length[] = { 8,7,6,9,11,10,5,12,14,13 };
+ int *offset, len[2], pred[2], row, col, i, j;
+ ushort *pixel;
+ short (*t_black)[2];
+
+ pixel = (ushort *) calloc (raw_width + raw_height*4, 2);
+ merror (pixel, "phase_one_load_raw_c()");
+ offset = (int *) (pixel + raw_width);
+ fseek (ifp, strip_offset, SEEK_SET);
+ for (row=0; row < raw_height; row++)
+ offset[row] = get4();
+ t_black = (short (*)[2]) offset + raw_height;
+ fseek (ifp, ph1.black_off, SEEK_SET);
+ if (ph1.black_off)
+ read_shorts ((ushort *) t_black[0], raw_height*2);
+ for (i=0; i < 256; i++)
+ curve[i] = i*i / 3.969 + 0.5;
+ for (row=0; row < raw_height; row++) {
+ fseek (ifp, data_offset + offset[row], SEEK_SET);
+ ph1_bits(-1);
+ pred[0] = pred[1] = 0;
+ for (col=0; col < raw_width; col++) {
+ if (col >= (raw_width & -8))
+ len[0] = len[1] = 14;
+ else if ((col & 7) == 0)
+ for (i=0; i < 2; i++) {
+ for (j=0; j < 5 && !ph1_bits(1); j++);
+ if (j--) len[i] = length[j*2 + ph1_bits(1)];
+ }
+ if ((i = len[col & 1]) == 14)
+ pixel[col] = pred[col & 1] = ph1_bits(16);
+ else
+ pixel[col] = pred[col & 1] += ph1_bits(i) + 1 - (1 << (i - 1));
+ if (pred[col & 1] >> 16) derror();
+ if (ph1.format == 5 && pixel[col] < 256)
+ pixel[col] = curve[pixel[col]];
+ }
+ if ((unsigned) (row-top_margin) < height)
+ for (col=0; col < width; col++) {
+ i = (pixel[col+left_margin] << 2)
+ - ph1.t_black + t_black[row][col >= ph1.split_col];
+ if (i > 0) BAYER(row-top_margin,col) = i;
+ }
+ }
+ free (pixel);
+ phase_one_correct();
+ maximum = 0xfffc - ph1.t_black;
+}
+
+void CLASS hasselblad_load_raw()
+{
+ struct jhead jh;
+ struct decode *dindex;
+ int row, col, pred[2], len[2], diff, i;
+
+ if (!ljpeg_start (&jh, 0)) return;
+ free (jh.row);
+ order = 0x4949;
+ ph1_bits(-1);
+ for (row=-top_margin; row < raw_height-top_margin; row++) {
+ pred[0] = pred[1] = 0x8000;
+ for (col=-left_margin; col < raw_width-left_margin; col+=2) {
+ for (i=0; i < 2; i++) {
+ for (dindex=jh.huff[0]; dindex->branch[0]; )
+ dindex = dindex->branch[ph1_bits(1)];
+ len[i] = dindex->leaf;
+ }
+ for (i=0; i < 2; i++) {
+ diff = ph1_bits(len[i]);
+ if ((diff & (1 << (len[i]-1))) == 0)
+ diff -= (1 << len[i]) - 1;
+ if (diff == 65535) diff = -32768;
+ pred[i] += diff;
+ if (row >= 0 && row < height && (unsigned)(col+i) < width)
+ BAYER(row,col+i) = pred[i];
+ }
+ }
+ }
+ maximum = 0xffff;
+}
+
+void CLASS leaf_hdr_load_raw()
+{
+ ushort *pixel;
+ unsigned tile=0, r, c, row, col;
+
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "leaf_hdr_load_raw()");
+ FORC(tiff_samples)
+ for (r=0; r < raw_height; r++) {
+ if (r % tile_length == 0) {
+ fseek (ifp, data_offset + 4*tile++, SEEK_SET);
+ fseek (ifp, get4() + 2*left_margin, SEEK_SET);
+ }
+ if (filters && c != shot_select) continue;
+ read_shorts (pixel, raw_width);
+ if ((row = r - top_margin) >= height) continue;
+ for (col=0; col < width; col++)
+ if (filters) BAYER(row,col) = pixel[col];
+ else image[row*width+col][c] = pixel[col];
+ }
+ free (pixel);
+ if (!filters) {
+ maximum = 0xffff;
+ raw_color = 1;
+ }
+}
+
+#line 1839 "dcraw/dcraw.c"
+void CLASS sinar_4shot_load_raw()
+{
+ ushort *pixel;
+ unsigned shot, row, col, r, c;
+
+ if ((shot = shot_select) || half_size) {
+ if (shot) shot--;
+ if (shot > 3) shot = 3;
+ fseek (ifp, data_offset + shot*4, SEEK_SET);
+ fseek (ifp, get4(), SEEK_SET);
+ unpacked_load_raw();
+ return;
+ }
+ free (image);
+ image = (ushort (*)[4])
+ calloc ((iheight=height)*(iwidth=width), sizeof *image);
+ merror (image, "sinar_4shot_load_raw()");
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "sinar_4shot_load_raw()");
+ for (shot=0; shot < 4; shot++) {
+ fseek (ifp, data_offset + shot*4, SEEK_SET);
+ fseek (ifp, get4(), SEEK_SET);
+ for (row=0; row < raw_height; row++) {
+ read_shorts (pixel, raw_width);
+ if ((r = row-top_margin - (shot >> 1 & 1)) >= height) continue;
+ for (col=0; col < raw_width; col++) {
+ if ((c = col-left_margin - (shot & 1)) >= width) continue;
+ image[r*width+c][FC(row,col)] = pixel[col];
+ }
+ }
+ }
+ free (pixel);
+ shrink = filters = 0;
+}
+
+void CLASS imacon_full_load_raw()
+{
+ int row, col;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ read_shorts (image[row*width+col], 3);
+}
+
+void CLASS packed_12_load_raw()
+{
+ int vbits=0, rbits=0, irow, row, col;
+ UINT64 bitbuf=0;
+
+ if (raw_width * 2 >= width * 3) { /* If raw_width is in bytes, */
+ rbits = raw_width * 8;
+ raw_width = raw_width * 2 / 3; /* convert it to pixels and */
+ rbits -= raw_width * 12; /* save the remainder. */
+ }
+ order = load_flags & 1 ? 0x4949 : 0x4d4d;
+ for (irow=0; irow < height; irow++) {
+ row = irow;
+ if (load_flags & 2 &&
+ (row = irow * 2 % height + irow / (height/2)) == 1 &&
+ load_flags & 4) {
+ if (vbits=0, tiff_compress)
+ fseek (ifp, data_offset - (-width*height*3/4 & -2048), SEEK_SET);
+ else {
+ fseek (ifp, 0, SEEK_END);
+ fseek (ifp, ftell(ifp)/2, SEEK_SET);
+ }
+ }
+ for (col=0; col < raw_width; col++) {
+ if ((vbits -= 12) < 0) {
+ bitbuf = bitbuf << 32 | get4();
+ vbits += 32;
+ }
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = bitbuf << (52-vbits) >> 52;
+ if (load_flags & 8 && (col % 10) == 9)
+ if (vbits=0, bitbuf & 255) derror();
+ }
+ vbits -= rbits;
+ }
+ if (!strcmp(make,"OLYMPUS")) black >>= 4;
+}
+
+void CLASS unpacked_load_raw()
+{
+ ushort *pixel;
+ int row, col, bits=0;
+
+ while (1 << ++bits < maximum);
+ fseek (ifp, (top_margin*raw_width + left_margin) * 2, SEEK_CUR);
+ pixel = (ushort *) calloc (width, sizeof *pixel);
+ merror (pixel, "unpacked_load_raw()");
+ for (row=0; row < height; row++) {
+ read_shorts (pixel, width);
+ fseek (ifp, 2*(raw_width - width), SEEK_CUR);
+ for (col=0; col < width; col++)
+ if ((BAYER2(row,col) = pixel[col]) >> bits) derror();
+ }
+ free (pixel);
+}
+
+void CLASS nokia_load_raw()
+{
+ uchar *data, *dp;
+ ushort *pixel, *pix;
+ int dwide, row, c;
+
+ dwide = raw_width * 5 / 4;
+ data = (uchar *) malloc (dwide + raw_width*2);
+ merror (data, "nokia_load_raw()");
+ pixel = (ushort *) (data + dwide);
+ for (row=0; row < raw_height; row++) {
+ if (fread (data, 1, dwide, ifp) < dwide) derror();
+ for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=5, pix+=4)
+ FORC4 pix[c] = (dp[c] << 2) | (dp[4] >> (c << 1) & 3);
+ if (row < top_margin)
+ FORC(width) black += pixel[c];
+ else
+ FORC(width) BAYER(row-top_margin,c) = pixel[c];
+ }
+ free (data);
+ if (top_margin) black /= top_margin * width;
+ maximum = 0x3ff;
+}
+
+unsigned CLASS pana_bits (int nbits)
+{
+#ifndef LIBRAW_NOTHREADS
+#define buf tls->pana_bits.buf
+#define vbits tls->pana_bits.vbits
+#else
+ static uchar buf[0x4000];
+ static int vbits;
+#endif
+ int byte;
+
+ if (!nbits) return vbits=0;
+ if (!vbits) {
+ fread (buf+load_flags, 1, 0x4000-load_flags, ifp);
+ fread (buf, 1, load_flags, ifp);
+ }
+ vbits = (vbits - nbits) & 0x1ffff;
+ byte = vbits >> 3 ^ 0x3ff0;
+ return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~(-1 << nbits);
+#ifndef LIBRAW_NOTHREADS
+#undef buf
+#undef vbits
+#endif
+}
+
+void CLASS panasonic_load_raw()
+{
+ int row, col, i, j, sh=0, pred[2], nonz[2];
+
+ pana_bits(0);
+ for (row=0; row < height; row++)
+ for (col=0; col < raw_width; col++) {
+ if ((i = col % 14) == 0)
+ pred[0] = pred[1] = nonz[0] = nonz[1] = 0;
+ if (i % 3 == 2) sh = 4 >> (3 - pana_bits(2));
+ if (nonz[i & 1]) {
+ if ((j = pana_bits(8))) {
+ if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4)
+ pred[i & 1] &= ~(-1 << sh);
+ pred[i & 1] += j << sh;
+ }
+ } else if ((nonz[i & 1] = pana_bits(8)) || i > 11)
+ pred[i & 1] = nonz[i & 1] << 4 | pana_bits(4);
+ if (col < width)
+ if ((BAYER(row,col) = pred[col & 1]) > 4098) derror();
+ }
+}
+
+void CLASS olympus_e300_load_raw()
+{
+ uchar *data, *dp;
+ ushort *pixel, *pix;
+ int dwide, row, col;
+
+ dwide = raw_width * 16 / 10;
+ fseek (ifp, dwide*top_margin, SEEK_CUR);
+ data = (uchar *) malloc (dwide + raw_width*2);
+ merror (data, "olympus_e300_load_raw()");
+ pixel = (ushort *) (data + dwide);
+ for (row=0; row < height; row++){
+ if (fread (data, 1, dwide, ifp) < dwide) derror();
+ for (dp=data, pix=pixel; pix < pixel+raw_width; dp+=3, pix+=2) {
+ if (((dp-data) & 15) == 15)
+ if (*dp++ && pix < pixel+width+left_margin) derror();
+ pix[0] = dp[1] << 8 | dp[0];
+ pix[1] = dp[2] << 4 | dp[1] >> 4;
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (pixel[col+left_margin] & 0xfff);
+ }
+ free (data);
+ maximum >>= 4;
+ black >>= 4;
+}
+
+void CLASS olympus_e410_load_raw()
+{
+ int row, col, nbits, sign, low, high, i, w, n, nw;
+ int acarry[2][3], *carry, pred, diff;
+
+ fseek (ifp, 7, SEEK_CUR);
+ getbits(-1);
+ for (row=0; row < height; row++) {
+ memset (acarry, 0, sizeof acarry);
+ for (col=0; col < width; col++) {
+ carry = acarry[col & 1];
+ i = 2 * (carry[2] < 3);
+ for (nbits=2+i; (ushort) carry[0] >> (nbits+i); nbits++);
+ sign = getbits(1) * -1;
+ low = getbits(2);
+ for (high=0; high < 12; high++)
+ if (getbits(1)) break;
+ if (high == 12)
+ high = getbits(16-nbits) >> 1;
+ carry[0] = (high << nbits) | getbits(nbits);
+ diff = (carry[0] ^ sign) + carry[1];
+ carry[1] = (diff*3 + carry[1]) >> 5;
+ carry[2] = carry[0] > 16 ? 0 : carry[2]+1;
+ if (row < 2 && col < 2) pred = 0;
+ else if (row < 2) pred = BAYER(row,col-2);
+ else if (col < 2) pred = BAYER(row-2,col);
+ else {
+ w = BAYER(row,col-2);
+ n = BAYER(row-2,col);
+ nw = BAYER(row-2,col-2);
+ if ((w < nw && nw < n) || (n < nw && nw < w)) {
+ if (ABS(w-nw) > 32 || ABS(n-nw) > 32)
+ pred = w + n - nw;
+ else pred = (w + n) >> 1;
+ } else pred = ABS(w-nw) > ABS(n-nw) ? w : n;
+ }
+ if ((BAYER(row,col) = pred + ((diff << 2) | low)) >> 12) derror();
+ }
+ }
+}
+
+void CLASS minolta_rd175_load_raw()
+{
+ uchar pixel[768];
+ unsigned irow, box, row, col;
+
+ for (irow=0; irow < 1481; irow++) {
+ if (fread (pixel, 1, 768, ifp) < 768) derror();
+ box = irow / 82;
+ row = irow % 82 * 12 + ((box < 12) ? box | 1 : (box-12)*2);
+ switch (irow) {
+ case 1477: case 1479: continue;
+ case 1476: row = 984; break;
+ case 1480: row = 985; break;
+ case 1478: row = 985; box = 1;
+ }
+ if ((box < 12) && (box & 1)) {
+ for (col=0; col < 1533; col++, row ^= 1)
+ if (col != 1) BAYER(row,col) = (col+1) & 2 ?
+ pixel[col/2-1] + pixel[col/2+1] : pixel[col/2] << 1;
+ BAYER(row,1) = pixel[1] << 1;
+ BAYER(row,1533) = pixel[765] << 1;
+ } else
+ for (col=row & 1; col < 1534; col+=2)
+ BAYER(row,col) = pixel[col/2] << 1;
+ }
+ maximum = 0xff << 1;
+}
+
+void CLASS casio_qv5700_load_raw()
+{
+ uchar data[3232], *dp;
+ ushort pixel[2576], *pix;
+ int row, col;
+
+ for (row=0; row < height; row++) {
+ fread (data, 1, 3232, ifp);
+ for (dp=data, pix=pixel; dp < data+3220; dp+=5, pix+=4) {
+ pix[0] = (dp[0] << 2) + (dp[1] >> 6);
+ pix[1] = (dp[1] << 4) + (dp[2] >> 4);
+ pix[2] = (dp[2] << 6) + (dp[3] >> 2);
+ pix[3] = (dp[3] << 8) + (dp[4] );
+ }
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (pixel[col] & 0x3ff);
+ }
+ maximum = 0x3fc;
+}
+
+void CLASS quicktake_100_load_raw()
+{
+ uchar pixel[484][644];
+ static const short gstep[16] =
+ { -89,-60,-44,-32,-22,-15,-8,-2,2,8,15,22,32,44,60,89 };
+ static const short rstep[6][4] =
+ { { -3,-1,1,3 }, { -5,-1,1,5 }, { -8,-2,2,8 },
+ { -13,-3,3,13 }, { -19,-4,4,19 }, { -28,-6,6,28 } };
+ static const short t_curve[256] =
+ { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,
+ 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53,
+ 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78,
+ 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116,
+ 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155,
+ 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195,
+ 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244,
+ 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322,
+ 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400,
+ 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479,
+ 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643,
+ 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844,
+ 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 };
+ int rb, row, col, sharp, val=0;
+
+ getbits(-1);
+ memset (pixel, 0x80, sizeof pixel);
+ for (row=2; row < height+2; row++) {
+ for (col=2+(row & 1); col < width+2; col+=2) {
+ val = ((pixel[row-1][col-1] + 2*pixel[row-1][col+1] +
+ pixel[row][col-2]) >> 2) + gstep[getbits(4)];
+ pixel[row][col] = val = LIM(val,0,255);
+ if (col < 4)
+ pixel[row][col-2] = pixel[row+1][~row & 1] = val;
+ if (row == 2)
+ pixel[row-1][col+1] = pixel[row-1][col+3] = val;
+ }
+ pixel[row][col] = val;
+ }
+ for (rb=0; rb < 2; rb++)
+ for (row=2+rb; row < height+2; row+=2)
+ for (col=3-(row & 1); col < width+2; col+=2) {
+ if (row < 4 || col < 4) sharp = 2;
+ else {
+ val = ABS(pixel[row-2][col] - pixel[row][col-2])
+ + ABS(pixel[row-2][col] - pixel[row-2][col-2])
+ + ABS(pixel[row][col-2] - pixel[row-2][col-2]);
+ sharp = val < 4 ? 0 : val < 8 ? 1 : val < 16 ? 2 :
+ val < 32 ? 3 : val < 48 ? 4 : 5;
+ }
+ val = ((pixel[row-2][col] + pixel[row][col-2]) >> 1)
+ + rstep[sharp][getbits(2)];
+ pixel[row][col] = val = LIM(val,0,255);
+ if (row < 4) pixel[row-2][col+2] = val;
+ if (col < 4) pixel[row+2][col-2] = val;
+ }
+ for (row=2; row < height+2; row++)
+ for (col=3-(row & 1); col < width+2; col+=2) {
+ val = ((pixel[row][col-1] + (pixel[row][col] << 2) +
+ pixel[row][col+1]) >> 1) - 0x100;
+ pixel[row][col] = LIM(val,0,255);
+ }
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ BAYER(row,col) = t_curve[pixel[row+2][col+2]];
+ maximum = 0x3ff;
+}
+
+const int * CLASS make_decoder_int (const int *source, int level)
+{
+ struct decode *cur;
+
+ cur = free_decode++;
+ if (level < source[0]) {
+ cur->branch[0] = free_decode;
+ source = make_decoder_int (source, level+1);
+ cur->branch[1] = free_decode;
+ source = make_decoder_int (source, level+1);
+ } else {
+ cur->leaf = source[1];
+ source += 2;
+ }
+ return source;
+}
+
+int CLASS radc_token (int tree)
+{
+ int t;
+#ifndef LIBRAW_NOTHREADS
+#define dstart tls->radc_token.dstart
+#define dindex tls->radc_token.dindex
+#define s tls->radc_token.s
+
+ static const int source[] = {
+#else
+ static struct decode *dstart[18], *dindex;
+ static const int *s, source[] = {
+#endif
+ 1,1, 2,3, 3,4, 4,2, 5,7, 6,5, 7,6, 7,8,
+ 1,0, 2,1, 3,3, 4,4, 5,2, 6,7, 7,6, 8,5, 8,8,
+ 2,1, 2,3, 3,0, 3,2, 3,4, 4,6, 5,5, 6,7, 6,8,
+ 2,0, 2,1, 2,3, 3,2, 4,4, 5,6, 6,7, 7,5, 7,8,
+ 2,1, 2,4, 3,0, 3,2, 3,3, 4,7, 5,5, 6,6, 6,8,
+ 2,3, 3,1, 3,2, 3,4, 3,5, 3,6, 4,7, 5,0, 5,8,
+ 2,3, 2,6, 3,0, 3,1, 4,4, 4,5, 4,7, 5,2, 5,8,
+ 2,4, 2,7, 3,3, 3,6, 4,1, 4,2, 4,5, 5,0, 5,8,
+ 2,6, 3,1, 3,3, 3,5, 3,7, 3,8, 4,0, 5,2, 5,4,
+ 2,0, 2,1, 3,2, 3,3, 4,4, 4,5, 5,6, 5,7, 4,8,
+ 1,0, 2,2, 2,-2,
+ 1,-3, 1,3,
+ 2,-17, 2,-5, 2,5, 2,17,
+ 2,-7, 2,2, 2,9, 2,18,
+ 2,-18, 2,-9, 2,-2, 2,7,
+ 2,-28, 2,28, 3,-49, 3,-9, 3,9, 4,49, 5,-79, 5,79,
+ 2,-1, 2,13, 2,26, 3,39, 4,-16, 5,55, 6,-37, 6,76,
+ 2,-26, 2,-13, 2,1, 3,-39, 4,16, 5,-55, 6,-76, 6,37
+ };
+
+ if (free_decode == first_decode)
+ for (s=source, t=0; t < 18; t++) {
+ dstart[t] = free_decode;
+ s = make_decoder_int (s, 0);
+ }
+ if (tree == 18) {
+ if (kodak_cbpp == 243)
+ return (getbits(6) << 2) + 2; /* most DC50 photos */
+ else
+ return (getbits(5) << 3) + 4; /* DC40, Fotoman Pixtura */
+ }
+ for (dindex = dstart[tree]; dindex->branch[0]; )
+ dindex = dindex->branch[getbits(1)];
+ return dindex->leaf;
+
+#ifndef LIBRAW_NOTHREADS
+#undef dstart
+#undef dindex
+#undef s
+#endif
+}
+
+#define FORYX for (y=1; y < 3; y++) for (x=col+1; x >= col; x--)
+
+#define PREDICTOR (c ? (buf[c][y-1][x] + buf[c][y][x+1]) / 2 \
+: (buf[c][y-1][x+1] + 2*buf[c][y-1][x] + buf[c][y][x+1]) / 4)
+
+void CLASS kodak_radc_load_raw()
+{
+ int row, col, tree, nreps, rep, step, i, c, s, r, x, y, val;
+ short last[3] = { 16,16,16 }, mul[3], buf[3][3][386];
+
+ init_decoder();
+ getbits(-1);
+ for (i=0; i < sizeof(buf)/sizeof(short); i++)
+ buf[0][0][i] = 2048;
+ for (row=0; row < height; row+=4) {
+ FORC3 mul[c] = getbits(6);
+ FORC3 {
+ val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
+ s = val > 65564 ? 10:12;
+ x = ~(-1 << (s-1));
+ val <<= 12-s;
+ for (i=0; i < sizeof(buf[0])/sizeof(short); i++)
+ buf[c][0][i] = (buf[c][0][i] * val + x) >> s;
+ last[c] = mul[c];
+ for (r=0; r <= !c; r++) {
+ buf[c][1][width/2] = buf[c][2][width/2] = mul[c] << 7;
+ for (tree=1, col=width/2; col > 0; ) {
+ if ((tree = radc_token(tree))) {
+ col -= 2;
+ if (tree == 8)
+ FORYX buf[c][y][x] = radc_token(tree+10) * mul[c];
+ else
+ FORYX buf[c][y][x] = radc_token(tree+10) * 16 + PREDICTOR;
+ } else
+ do {
+ nreps = (col > 2) ? radc_token(9) + 1 : 1;
+ for (rep=0; rep < 8 && rep < nreps && col > 0; rep++) {
+ col -= 2;
+ FORYX buf[c][y][x] = PREDICTOR;
+ if (rep & 1) {
+ step = radc_token(10) << 4;
+ FORYX buf[c][y][x] += step;
+ }
+ }
+ } while (nreps == 9);
+ }
+ for (y=0; y < 2; y++)
+ for (x=0; x < width/2; x++) {
+ val = (buf[c][y+1][x] << 4) / mul[c];
+ if (val < 0) val = 0;
+ if (c) BAYER(row+y*2+c-1,x*2+2-c) = val;
+ else BAYER(row+r*2+y,x*2+y) = val;
+ }
+ memcpy (buf[c][0]+!c, buf[c][2], sizeof buf[c][0]-2*!c);
+ }
+ }
+ for (y=row; y < row+4; y++)
+ for (x=0; x < width; x++)
+ if ((x+y) & 1) {
+ r = x ? x-1 : x+1;
+ s = x+1 < width ? x+1 : x-1;
+ val = (BAYER(y,x)-2048)*2 + (BAYER(y,r)+BAYER(y,s))/2;
+ if (val < 0) val = 0;
+ BAYER(y,x) = val;
+ }
+ }
+ maximum = 0xfff;
+ use_gamma = 0;
+}
+
+#undef FORYX
+#undef PREDICTOR
+
+#ifdef NO_JPEG
+void CLASS kodak_jpeg_load_raw() {}
+#else
+
+METHODDEF(boolean)
+fill_input_buffer (j_decompress_ptr cinfo)
+{
+#ifndef LIBRAW_NOTHREADS
+#define jpeg_buffer tls->jpeg_buffer
+#else
+ static uchar jpeg_buffer[4096];
+#endif
+ size_t nbytes;
+
+ nbytes = fread (jpeg_buffer, 1, 4096, ifp);
+ swab (jpeg_buffer, jpeg_buffer, nbytes);
+ cinfo->src->next_input_byte = jpeg_buffer;
+ cinfo->src->bytes_in_buffer = nbytes;
+ return TRUE;
+#ifndef LIBRAW_NOTHREADS
+#undef jpeg_buffer
+#endif
+}
+
+void CLASS kodak_jpeg_load_raw()
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPARRAY buf;
+ JSAMPLE (*pixel)[3];
+ int row, col;
+
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_decompress (&cinfo);
+ jpeg_stdio_src (&cinfo, ifp);
+ cinfo.src->fill_input_buffer = fill_input_buffer;
+ jpeg_read_header (&cinfo, TRUE);
+ jpeg_start_decompress (&cinfo);
+ if ((cinfo.output_width != width ) ||
+ (cinfo.output_height*2 != height ) ||
+ (cinfo.output_components != 3 )) {
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("%s: incorrect JPEG dimensions\n"), ifname);
+#endif
+ jpeg_destroy_decompress (&cinfo);
+#ifdef LIBRAW_LIBRARY_BUILD
+ throw LIBRAW_EXCEPTION_DECODE_JPEG;
+#else
+ longjmp (failure, 3);
+#endif
+ }
+ buf = (*cinfo.mem->alloc_sarray)
+ ((j_common_ptr) &cinfo, JPOOL_IMAGE, width*3, 1);
+
+ while (cinfo.output_scanline < cinfo.output_height) {
+ row = cinfo.output_scanline * 2;
+ jpeg_read_scanlines (&cinfo, buf, 1);
+ pixel = (JSAMPLE (*)[3]) buf[0];
+ for (col=0; col < width; col+=2) {
+ BAYER(row+0,col+0) = pixel[col+0][1] << 1;
+ BAYER(row+1,col+1) = pixel[col+1][1] << 1;
+ BAYER(row+0,col+1) = pixel[col][0] + pixel[col+1][0];
+ BAYER(row+1,col+0) = pixel[col][2] + pixel[col+1][2];
+ }
+ }
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+ maximum = 0xff << 1;
+}
+#endif
+
+void CLASS kodak_dc120_load_raw()
+{
+ static const int mul[4] = { 162, 192, 187, 92 };
+ static const int add[4] = { 0, 636, 424, 212 };
+ uchar pixel[848];
+ int row, shift, col;
+
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 1, 848, ifp) < 848) derror();
+ shift = row * mul[row & 3] + add[row & 3];
+ for (col=0; col < width; col++)
+ BAYER(row,col) = (ushort) pixel[(col + shift) % 848];
+ }
+ maximum = 0xff;
+}
+
+void CLASS eight_bit_load_raw()
+{
+ uchar *pixel;
+ unsigned row, col, val, lblack=0;
+
+ pixel = (uchar *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "eight_bit_load_raw()");
+ fseek (ifp, top_margin*raw_width, SEEK_CUR);
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 1, raw_width, ifp) < raw_width) derror();
+ for (col=0; col < raw_width; col++) {
+ val = curve[pixel[col]];
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = val;
+ else lblack += val;
+ }
+ }
+
+ free (pixel);
+ if (raw_width > width+1)
+ black = lblack / ((raw_width - width) * height);
+ if (!strncmp(model,"DC2",3))
+ black = 0;
+ maximum = curve[0xff];
+}
+
+void CLASS kodak_yrgb_load_raw()
+{
+ uchar *pixel;
+ int row, col, y, cb, cr, rgb[3], c;
+
+ pixel = (uchar *) calloc (raw_width, 3*sizeof *pixel);
+ merror (pixel, "kodak_yrgb_load_raw()");
+ for (row=0; row < height; row++) {
+ if (~row & 1)
+ if (fread (pixel, raw_width, 3, ifp) < 3) derror();
+ for (col=0; col < raw_width; col++) {
+ y = pixel[width*2*(row & 1) + col];
+ cb = pixel[width + (col & -2)] - 128;
+ cr = pixel[width + (col & -2)+1] - 128;
+ rgb[1] = y-((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ FORC3 image[row*width+col][c] = LIM(rgb[c],0,255);
+ }
+ }
+ free (pixel);
+ use_gamma = 0;
+}
+
+void CLASS kodak_262_load_raw()
+{
+ static const uchar kodak_tree[2][26] =
+ { { 0,1,5,1,1,2,0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 },
+ { 0,3,1,1,1,1,1,2,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,9 } };
+ struct decode *decode[2];
+ uchar *pixel;
+ int *strip, ns, i, row, col, chess, pi=0, pi1, pi2, pred, val;
+
+ init_decoder();
+ for (i=0; i < 2; i++) {
+ decode[i] = free_decode;
+ make_decoder (kodak_tree[i], 0);
+ }
+ ns = (raw_height+63) >> 5;
+ pixel = (uchar *) malloc (raw_width*32 + ns*4);
+ merror (pixel, "kodak_262_load_raw()");
+ strip = (int *) (pixel + raw_width*32);
+ order = 0x4d4d;
+ for (i=0; i < ns; i++)
+ strip[i] = get4();
+ for (row=0; row < raw_height; row++) {
+ if ((row & 31) == 0) {
+ fseek (ifp, strip[row >> 5], SEEK_SET);
+ getbits(-1);
+ pi = 0;
+ }
+ for (col=0; col < raw_width; col++) {
+ chess = (row + col) & 1;
+ pi1 = chess ? pi-2 : pi-raw_width-1;
+ pi2 = chess ? pi-2*raw_width : pi-raw_width+1;
+ if (col <= chess) pi1 = -1;
+ if (pi1 < 0) pi1 = pi2;
+ if (pi2 < 0) pi2 = pi1;
+ if (pi1 < 0 && col > 1) pi1 = pi2 = pi-2;
+ pred = (pi1 < 0) ? 0 : (pixel[pi1] + pixel[pi2]) >> 1;
+ pixel[pi] = val = pred + ljpeg_diff (decode[chess]);
+ if (val >> 8) derror();
+ val = curve[pixel[pi++]];
+ if ((unsigned) (col-left_margin) < width)
+ BAYER(row,col-left_margin) = val;
+ else
+ black += val;
+ }
+ }
+ free (pixel);
+ if (raw_width > width)
+ black /= (raw_width - width) * height;
+}
+
+int CLASS kodak_65000_decode (short *out, int bsize)
+{
+ uchar c, blen[768];
+ ushort raw[6];
+ INT64 bitbuf=0;
+ int save, bits=0, i, j, len, diff;
+
+ save = ftell(ifp);
+ bsize = (bsize + 3) & -4;
+ for (i=0; i < bsize; i+=2) {
+ c = fgetc(ifp);
+ if ((blen[i ] = c & 15) > 12 ||
+ (blen[i+1] = c >> 4) > 12 ) {
+ fseek (ifp, save, SEEK_SET);
+ for (i=0; i < bsize; i+=8) {
+ read_shorts (raw, 6);
+ out[i ] = raw[0] >> 12 << 8 | raw[2] >> 12 << 4 | raw[4] >> 12;
+ out[i+1] = raw[1] >> 12 << 8 | raw[3] >> 12 << 4 | raw[5] >> 12;
+ for (j=0; j < 6; j++)
+ out[i+2+j] = raw[j] & 0xfff;
+ }
+ return 1;
+ }
+ }
+ if ((bsize & 7) == 4) {
+ bitbuf = fgetc(ifp) << 8;
+ bitbuf += fgetc(ifp);
+ bits = 16;
+ }
+ for (i=0; i < bsize; i++) {
+ len = blen[i];
+ if (bits < len) {
+ for (j=0; j < 32; j+=8)
+ bitbuf += (INT64) fgetc(ifp) << (bits+(j^8));
+ bits += 32;
+ }
+ diff = bitbuf & (0xffff >> (16-len));
+ bitbuf >>= len;
+ bits -= len;
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ out[i] = diff;
+ }
+ return 0;
+}
+
+void CLASS kodak_65000_load_raw()
+{
+ short buf[256];
+ int row, col, len, pred[2], ret, i;
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col+=256) {
+ pred[0] = pred[1] = 0;
+ len = MIN (256, width-col);
+ ret = kodak_65000_decode (buf, len);
+ for (i=0; i < len; i++)
+ if ((BAYER(row,col+i) = curve[ret ? buf[i] :
+ (pred[i & 1] += buf[i])]) >> 12) derror();
+ }
+}
+
+void CLASS kodak_ycbcr_load_raw()
+{
+ short buf[384], *bp;
+ int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3];
+ ushort *ip;
+
+ for (row=0; row < height; row+=2)
+ for (col=0; col < width; col+=128) {
+ len = MIN (128, width-col);
+ kodak_65000_decode (buf, len*3);
+ y[0][1] = y[1][1] = cb = cr = 0;
+ for (bp=buf, i=0; i < len; i+=2, bp+=2) {
+ cb += bp[4];
+ cr += bp[5];
+ rgb[1] = -((cb + cr + 2) >> 2);
+ rgb[2] = rgb[1] + cb;
+ rgb[0] = rgb[1] + cr;
+ for (j=0; j < 2; j++)
+ for (k=0; k < 2; k++) {
+ if ((y[j][k] = y[j][k^1] + *bp++) >> 10) derror();
+ ip = image[(row+j)*width + col+i+k];
+ FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)];
+ }
+ }
+ }
+}
+
+void CLASS kodak_rgb_load_raw()
+{
+ short buf[768], *bp;
+ int row, col, len, c, i, rgb[3];
+ ushort *ip=image[0];
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col+=256) {
+ len = MIN (256, width-col);
+ kodak_65000_decode (buf, len*3);
+ memset (rgb, 0, sizeof rgb);
+ for (bp=buf, i=0; i < len; i++, ip+=4)
+ FORC3 if ((ip[c] = rgb[c] += *bp++) >> 12) derror();
+ }
+}
+
+void CLASS kodak_thumb_load_raw()
+{
+ int row, col;
+ colors = thumb_misc >> 5;
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++)
+ read_shorts (image[row*width+col], colors);
+ maximum = (1 << (thumb_misc & 31)) - 1;
+}
+
+void CLASS sony_decrypt (unsigned *data, int len, int start, int key)
+{
+#ifndef LIBRAW_NOTHREADS
+#define pad tls->sony_decrypt.pad
+#define p tls->sony_decrypt.p
+#else
+ static unsigned pad[128], p;
+#endif
+
+ if (start) {
+ for (p=0; p < 4; p++)
+ pad[p] = key = key * 48828125 + 1;
+ pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
+ for (p=4; p < 127; p++)
+ pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
+ for (p=0; p < 127; p++)
+ pad[p] = htonl(pad[p]);
+ }
+ while (len--)
+ *data++ ^= pad[p++ & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127];
+#ifndef LIBRAW_NOTHREADS
+#undef pad
+#undef p
+#endif
+}
+
+void CLASS sony_load_raw()
+{
+ uchar head[40];
+ ushort *pixel;
+ unsigned i, key, row, col;
+
+ fseek (ifp, 200896, SEEK_SET);
+ fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR);
+ order = 0x4d4d;
+ key = get4();
+ fseek (ifp, 164600, SEEK_SET);
+ fread (head, 1, 40, ifp);
+ sony_decrypt ((unsigned int *) head, 10, 1, key);
+ for (i=26; i-- > 22; )
+ key = key << 8 | head[i];
+ fseek (ifp, data_offset, SEEK_SET);
+ pixel = (ushort *) calloc (raw_width, sizeof *pixel);
+ merror (pixel, "sony_load_raw()");
+ for (row=0; row < height; row++) {
+ if (fread (pixel, 2, raw_width, ifp) < raw_width) derror();
+ sony_decrypt ((unsigned int *) pixel, raw_width/2, !row, key);
+ for (col=9; col < left_margin; col++)
+ black += ntohs(pixel[col]);
+ for (col=0; col < width; col++)
+ if ((BAYER(row,col) = ntohs(pixel[col+left_margin])) >> 14)
+ derror();
+ }
+ free (pixel);
+ if (left_margin > 9)
+ black /= (left_margin-9) * height;
+ maximum = 0x3ff0;
+}
+
+void CLASS sony_arw_load_raw()
+{
+ int col, row, len, diff, sum=0;
+
+ getbits(-1);
+ for (col = raw_width; col--; )
+ for (row=0; row < raw_height+1; row+=2) {
+ if (row == raw_height) row = 1;
+ len = 4 - getbits(2);
+ if (len == 3 && getbits(1)) len = 0;
+ if (len == 4)
+ while (len < 17 && !getbits(1)) len++;
+ diff = getbits(len);
+ if ((diff & (1 << (len-1))) == 0)
+ diff -= (1 << len) - 1;
+ if ((sum += diff) >> 12) derror();
+ if (row < height) BAYER(row,col) = sum;
+ }
+}
+
+void CLASS sony_arw2_load_raw()
+{
+ uchar *data, *dp;
+ ushort pix[16];
+ int row, col, val, max, min, imax, imin, sh, bit, i;
+
+ data = (uchar *) malloc (raw_width*tiff_bps >> 3);
+ merror (data, "sony_arw2_load_raw()");
+ for (row=0; row < height; row++) {
+ fread (data, 1, raw_width*tiff_bps >> 3, ifp);
+ if (tiff_bps == 8) {
+ for (dp=data, col=0; col < width-30; dp+=16) {
+ max = 0x7ff & (val = sget4(dp));
+ min = 0x7ff & val >> 11;
+ imax = 0x0f & val >> 22;
+ imin = 0x0f & val >> 26;
+ for (sh=0; sh < 4 && 0x80 << sh <= max-min; sh++);
+ for (bit=30, i=0; i < 16; i++)
+ if (i == imax) pix[i] = max;
+ else if (i == imin) pix[i] = min;
+ else {
+ pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min;
+ if (pix[i] > 0x7ff) pix[i] = 0x7ff;
+ bit += 7;
+ }
+ for (i=0; i < 16; i++, col+=2)
+ BAYER(row,col) = curve[pix[i] << 1] >> 1;
+ col -= col & 1 ? 1:31;
+ }
+ } else if (tiff_bps == 12)
+ for (dp=data, col=0; col < width; dp+=3, col+=2) {
+ BAYER(row,col) = ((dp[1] << 8 | dp[0]) & 0xfff) << 1;
+ BAYER(row,col+1) = (dp[2] << 4 | dp[1] >> 4) << 1;
+ }
+ }
+ free (data);
+}
+
+#define HOLE(row) ((holes >> (((row) - raw_height) & 7)) & 1)
+
+/* Kudos to Rich Taylor for figuring out SMaL's compression algorithm. */
+void CLASS smal_decode_segment (unsigned seg[2][2], int holes)
+{
+ uchar hist[3][13] = {
+ { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+ { 7, 7, 0, 0, 63, 55, 47, 39, 31, 23, 15, 7, 0 },
+ { 3, 3, 0, 0, 63, 47, 31, 15, 0 } };
+ int low, high=0xff, carry=0, nbits=8;
+ int s, count, bin, next, i, sym[3];
+ uchar diff, pred[]={0,0};
+ ushort data=0, range=0;
+ unsigned pix, row, col;
+
+ fseek (ifp, seg[0][1]+1, SEEK_SET);
+ getbits(-1);
+ for (pix=seg[0][0]; pix < seg[1][0]; pix++) {
+ for (s=0; s < 3; s++) {
+ data = data << nbits | getbits(nbits);
+ if (carry < 0)
+ carry = (nbits += carry+1) < 1 ? nbits-1 : 0;
+ while (--nbits >= 0)
+ if ((data >> nbits & 0xff) == 0xff) break;
+ if (nbits > 0)
+ data = ((data & ((1 << (nbits-1)) - 1)) << 1) |
+ ((data + (((data & (1 << (nbits-1)))) << 1)) & (-1 << nbits));
+ if (nbits >= 0) {
+ data += getbits(1);
+ carry = nbits - 8;
+ }
+ count = ((((data-range+1) & 0xffff) << 2) - 1) / (high >> 4);
+ for (bin=0; hist[s][bin+5] > count; bin++);
+ low = hist[s][bin+5] * (high >> 4) >> 2;
+ if (bin) high = hist[s][bin+4] * (high >> 4) >> 2;
+ high -= low;
+ for (nbits=0; high << nbits < 128; nbits++);
+ range = (range+low) << nbits;
+ high <<= nbits;
+ next = hist[s][1];
+ if (++hist[s][2] > hist[s][3]) {
+ next = (next+1) & hist[s][0];
+ hist[s][3] = (hist[s][next+4] - hist[s][next+5]) >> 2;
+ hist[s][2] = 1;
+ }
+ if (hist[s][hist[s][1]+4] - hist[s][hist[s][1]+5] > 1) {
+ if (bin < hist[s][1])
+ for (i=bin; i < hist[s][1]; i++) hist[s][i+5]--;
+ else if (next <= bin)
+ for (i=hist[s][1]; i < bin; i++) hist[s][i+5]++;
+ }
+ hist[s][1] = next;
+ sym[s] = bin;
+ }
+ diff = sym[2] << 5 | sym[1] << 2 | (sym[0] & 3);
+ if (sym[0] & 4)
+ diff = diff ? -diff : 0x80;
+ if (ftell(ifp) + 12 >= seg[1][1])
+ diff = 0;
+ pred[pix & 1] += diff;
+ row = pix / raw_width - top_margin;
+ col = pix % raw_width - left_margin;
+ if (row < height && col < width)
+ BAYER(row,col) = pred[pix & 1];
+ if (!(pix & 1) && HOLE(row)) pix += 2;
+ }
+ maximum = 0xff;
+}
+
+void CLASS smal_v6_load_raw()
+{
+ unsigned seg[2][2];
+
+ fseek (ifp, 16, SEEK_SET);
+ seg[0][0] = 0;
+ seg[0][1] = get2();
+ seg[1][0] = raw_width * raw_height;
+ seg[1][1] = INT_MAX;
+ smal_decode_segment (seg, 0);
+ use_gamma = 0;
+}
+
+int CLASS median4 (int *p)
+{
+ int min, max, sum, i;
+
+ min = max = sum = p[0];
+ for (i=1; i < 4; i++) {
+ sum += p[i];
+ if (min > p[i]) min = p[i];
+ if (max < p[i]) max = p[i];
+ }
+ return (sum - min - max) >> 1;
+}
+
+void CLASS fill_holes (int holes)
+{
+ int row, col, val[4];
+
+ for (row=2; row < height-2; row++) {
+ if (!HOLE(row)) continue;
+ for (col=1; col < width-1; col+=4) {
+ val[0] = BAYER(row-1,col-1);
+ val[1] = BAYER(row-1,col+1);
+ val[2] = BAYER(row+1,col-1);
+ val[3] = BAYER(row+1,col+1);
+ BAYER(row,col) = median4(val);
+ }
+ for (col=2; col < width-2; col+=4)
+ if (HOLE(row-2) || HOLE(row+2))
+ BAYER(row,col) = (BAYER(row,col-2) + BAYER(row,col+2)) >> 1;
+ else {
+ val[0] = BAYER(row,col-2);
+ val[1] = BAYER(row,col+2);
+ val[2] = BAYER(row-2,col);
+ val[3] = BAYER(row+2,col);
+ BAYER(row,col) = median4(val);
+ }
+ }
+}
+
+void CLASS smal_v9_load_raw()
+{
+ unsigned seg[256][2], offset, nseg, holes, i;
+
+ fseek (ifp, 67, SEEK_SET);
+ offset = get4();
+ nseg = fgetc(ifp);
+ fseek (ifp, offset, SEEK_SET);
+ for (i=0; i < nseg*2; i++)
+ seg[0][i] = get4() + data_offset*(i & 1);
+ fseek (ifp, 78, SEEK_SET);
+ holes = fgetc(ifp);
+ fseek (ifp, 88, SEEK_SET);
+ seg[nseg][0] = raw_height * raw_width;
+ seg[nseg][1] = get4() + data_offset;
+ for (i=0; i < nseg; i++)
+ smal_decode_segment (seg+i, holes);
+ if (holes) fill_holes (holes);
+}
+#line 3772 "dcraw/dcraw.c"
+
+void CLASS pseudoinverse (double (*in)[3], double (*out)[3], int size)
+{
+ double work[3][6], num;
+ int i, j, k;
+
+ for (i=0; i < 3; i++) {
+ for (j=0; j < 6; j++)
+ work[i][j] = j == i+3;
+ for (j=0; j < 3; j++)
+ for (k=0; k < size; k++)
+ work[i][j] += in[k][i] * in[k][j];
+ }
+ for (i=0; i < 3; i++) {
+ num = work[i][i];
+ for (j=0; j < 6; j++)
+ work[i][j] /= num;
+ for (k=0; k < 3; k++) {
+ if (k==i) continue;
+ num = work[k][i];
+ for (j=0; j < 6; j++)
+ work[k][j] -= work[i][j] * num;
+ }
+ }
+ for (i=0; i < size; i++)
+ for (j=0; j < 3; j++)
+ for (out[i][j]=k=0; k < 3; k++)
+ out[i][j] += work[j][k+3] * in[i][k];
+}
+
+void CLASS cam_xyz_coeff (double cam_xyz[4][3])
+{
+ double cam_rgb[4][3], inverse[4][3], num;
+ int i, j, k;
+
+ for (i=0; i < colors; i++) /* Multiply out XYZ colorspace */
+ for (j=0; j < 3; j++)
+ for (cam_rgb[i][j] = k=0; k < 3; k++)
+ cam_rgb[i][j] += cam_xyz[i][k] * xyz_rgb[k][j];
+
+ for (i=0; i < colors; i++) { /* Normalize cam_rgb so that */
+ for (num=j=0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
+ num += cam_rgb[i][j];
+ for (j=0; j < 3; j++)
+ cam_rgb[i][j] /= num;
+ pre_mul[i] = 1 / num;
+ }
+ pseudoinverse (cam_rgb, inverse, colors);
+ for (raw_color = i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ rgb_cam[i][j] = inverse[j][i];
+}
+
+#ifdef COLORCHECK
+void CLASS colorcheck()
+{
+#define NSQ 24
+// Coordinates of the GretagMacbeth ColorChecker squares
+// width, height, 1st_column, 1st_row
+ static const int cut[NSQ][4] = {
+ { 241, 231, 234, 274 },
+ { 251, 235, 534, 274 },
+ { 255, 239, 838, 272 },
+ { 255, 240, 1146, 274 },
+ { 251, 237, 1452, 278 },
+ { 243, 238, 1758, 288 },
+ { 253, 253, 218, 558 },
+ { 255, 249, 524, 562 },
+ { 261, 253, 830, 562 },
+ { 260, 255, 1144, 564 },
+ { 261, 255, 1450, 566 },
+ { 247, 247, 1764, 576 },
+ { 255, 251, 212, 862 },
+ { 259, 259, 518, 862 },
+ { 263, 261, 826, 864 },
+ { 265, 263, 1138, 866 },
+ { 265, 257, 1450, 872 },
+ { 257, 255, 1762, 874 },
+ { 257, 253, 212, 1164 },
+ { 262, 251, 516, 1172 },
+ { 263, 257, 826, 1172 },
+ { 263, 255, 1136, 1176 },
+ { 255, 252, 1452, 1182 },
+ { 257, 253, 1760, 1180 } };
+// ColorChecker Chart under 6500-kelvin illumination
+ static const double gmb_xyY[NSQ][3] = {
+ { 0.400, 0.350, 10.1 }, // Dark Skin
+ { 0.377, 0.345, 35.8 }, // Light Skin
+ { 0.247, 0.251, 19.3 }, // Blue Sky
+ { 0.337, 0.422, 13.3 }, // Foliage
+ { 0.265, 0.240, 24.3 }, // Blue Flower
+ { 0.261, 0.343, 43.1 }, // Bluish Green
+ { 0.506, 0.407, 30.1 }, // Orange
+ { 0.211, 0.175, 12.0 }, // Purplish Blue
+ { 0.453, 0.306, 19.8 }, // Moderate Red
+ { 0.285, 0.202, 6.6 }, // Purple
+ { 0.380, 0.489, 44.3 }, // Yellow Green
+ { 0.473, 0.438, 43.1 }, // Orange Yellow
+ { 0.187, 0.129, 6.1 }, // Blue
+ { 0.305, 0.478, 23.4 }, // Green
+ { 0.539, 0.313, 12.0 }, // Red
+ { 0.448, 0.470, 59.1 }, // Yellow
+ { 0.364, 0.233, 19.8 }, // Magenta
+ { 0.196, 0.252, 19.8 }, // Cyan
+ { 0.310, 0.316, 90.0 }, // White
+ { 0.310, 0.316, 59.1 }, // Neutral 8
+ { 0.310, 0.316, 36.2 }, // Neutral 6.5
+ { 0.310, 0.316, 19.8 }, // Neutral 5
+ { 0.310, 0.316, 9.0 }, // Neutral 3.5
+ { 0.310, 0.316, 3.1 } }; // Black
+ double gmb_cam[NSQ][4], gmb_xyz[NSQ][3];
+ double inverse[NSQ][3], cam_xyz[4][3], num;
+ int c, i, j, k, sq, row, col, count[4];
+
+ memset (gmb_cam, 0, sizeof gmb_cam);
+ for (sq=0; sq < NSQ; sq++) {
+ FORCC count[c] = 0;
+ for (row=cut[sq][3]; row < cut[sq][3]+cut[sq][1]; row++)
+ for (col=cut[sq][2]; col < cut[sq][2]+cut[sq][0]; col++) {
+ c = FC(row,col);
+ if (c >= colors) c -= 2;
+ gmb_cam[sq][c] += BAYER(row,col);
+ count[c]++;
+ }
+ FORCC gmb_cam[sq][c] = gmb_cam[sq][c]/count[c] - black;
+ gmb_xyz[sq][0] = gmb_xyY[sq][2] * gmb_xyY[sq][0] / gmb_xyY[sq][1];
+ gmb_xyz[sq][1] = gmb_xyY[sq][2];
+ gmb_xyz[sq][2] = gmb_xyY[sq][2] *
+ (1 - gmb_xyY[sq][0] - gmb_xyY[sq][1]) / gmb_xyY[sq][1];
+ }
+ pseudoinverse (gmb_xyz, inverse, NSQ);
+ for (i=0; i < colors; i++)
+ for (j=0; j < 3; j++)
+ for (cam_xyz[i][j] = k=0; k < NSQ; k++)
+ cam_xyz[i][j] += gmb_cam[k][i] * inverse[k][j];
+ cam_xyz_coeff (cam_xyz);
+#ifdef DCRAW_VERBOSE
+ if (verbose) {
+ printf (" { \"%s %s\", %d,\n\t{", make, model, black);
+ num = 10000 / (cam_xyz[1][0] + cam_xyz[1][1] + cam_xyz[1][2]);
+ FORCC for (j=0; j < 3; j++)
+ printf ("%c%d", (c | j) ? ',':' ', (int) (cam_xyz[c][j] * num + 0.5));
+ puts (" } },");
+ }
+#endif
+#undef NSQ
+}
+#endif
+
+void CLASS hat_transform (float *temp, float *base, int st, int size, int sc)
+{
+ int i;
+ for (i=0; i < sc; i++)
+ temp[i] = 2*base[st*i] + base[st*(sc-i)] + base[st*(i+sc)];
+ for (; i+sc < size; i++)
+ temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(i+sc)];
+ for (; i < size; i++)
+ temp[i] = 2*base[st*i] + base[st*(i-sc)] + base[st*(2*size-2-(i+sc))];
+}
+
+void CLASS wavelet_denoise()
+{
+ float *fimg=0, *temp, thold, mul[2], avg, diff;
+ int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast;
+ ushort *window[4];
+ static const float noise[] =
+ { 0.8002,0.2735,0.1202,0.0585,0.0291,0.0152,0.0080,0.0044 };
+
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Wavelet denoising...\n"));
+#endif
+
+ while (maximum << scale < 0x10000) scale++;
+ maximum <<= --scale;
+ black <<= scale;
+ if ((size = iheight*iwidth) < 0x15550000)
+ fimg = (float *) malloc ((size*3 + iheight + iwidth) * sizeof *fimg);
+ merror (fimg, "wavelet_denoise()");
+ temp = fimg + size*3;
+ if ((nc = colors) == 3 && filters) nc++;
+ FORC(nc) { /* denoise R,G1,B,G3 individually */
+ for (i=0; i < size; i++)
+ fimg[i] = 256 * sqrt((double)(image[i][c] << scale));
+ for (hpass=lev=0; lev < 5; lev++) {
+ lpass = size*((lev & 1)+1);
+ for (row=0; row < iheight; row++) {
+ hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev);
+ for (col=0; col < iwidth; col++)
+ fimg[lpass + row*iwidth + col] = temp[col] * 0.25;
+ }
+ for (col=0; col < iwidth; col++) {
+ hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev);
+ for (row=0; row < iheight; row++)
+ fimg[lpass + row*iwidth + col] = temp[row] * 0.25;
+ }
+ thold = threshold * noise[lev];
+ for (i=0; i < size; i++) {
+ fimg[hpass+i] -= fimg[lpass+i];
+ if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold;
+ else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold;
+ else fimg[hpass+i] = 0;
+ if (hpass) fimg[i] += fimg[hpass+i];
+ }
+ hpass = lpass;
+ }
+ for (i=0; i < size; i++)
+ image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000);
+ }
+ if (filters && colors == 3) { /* pull G1 and G3 closer together */
+ for (row=0; row < 2; row++)
+ mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1];
+ for (i=0; i < 4; i++)
+ window[i] = (ushort *) fimg + width*i;
+ for (wlast=-1, row=1; row < height-1; row++) {
+ while (wlast < row+1) {
+ for (wlast++, i=0; i < 4; i++)
+ window[(i+3) & 3] = window[i];
+ for (col = FC(wlast,1) & 1; col < width; col+=2)
+ window[2][col] = BAYER(wlast,col);
+ }
+ thold = threshold/512;
+ for (col = (FC(row,0) & 1)+1; col < width-1; col+=2) {
+ avg = ( window[0][col-1] + window[0][col+1] +
+ window[2][col-1] + window[2][col+1] - black*4 )
+ * mul[row & 1] + (window[1][col] - black) * 0.5 + black;
+ avg = avg < 0 ? 0 : sqrt(avg);
+ diff = sqrt((double)(BAYER(row,col))) - avg;
+ if (diff < -thold) diff += thold;
+ else if (diff > thold) diff -= thold;
+ else diff = 0;
+ BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5);
+ }
+ }
+ }
+ free (fimg);
+}
+
+void CLASS scale_colors()
+{
+ unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
+ int val, dark, sat;
+ double dsum[8], dmin, dmax;
+ float scale_mul[4], fr, fc;
+ ushort *img=0, *pix;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,0,2);
+#endif
+
+ if (user_mul[0])
+ memcpy (pre_mul, user_mul, sizeof pre_mul);
+ if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
+ memset (dsum, 0, sizeof dsum);
+ bottom = MIN (greybox[1]+greybox[3], height);
+ right = MIN (greybox[0]+greybox[2], width);
+ for (row=greybox[1]; row < bottom; row += 8)
+ for (col=greybox[0]; col < right; col += 8) {
+ memset (sum, 0, sizeof sum);
+ for (y=row; y < row+8 && y < bottom; y++)
+ for (x=col; x < col+8 && x < right; x++)
+ FORC4 {
+ if (filters) {
+ c = FC(y,x);
+ val = BAYER(y,x);
+ } else
+ val = image[y*width+x][c];
+ if (val > maximum-25) goto skip_block;
+ if ((val -= black) < 0) val = 0;
+ sum[c] += val;
+ sum[c+4]++;
+ if (filters) break;
+ }
+ FORC(8) dsum[c] += sum[c];
+skip_block: ;
+ }
+ FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
+ }
+ if (use_camera_wb && cam_mul[0] != -1) {
+ memset (sum, 0, sizeof sum);
+ for (row=0; row < 8; row++)
+ for (col=0; col < 8; col++) {
+ c = FC(row,col);
+ if ((val = white[row][col] - black) > 0)
+ sum[c] += val;
+ sum[c+4]++;
+ }
+ if (sum[0] && sum[1] && sum[2] && sum[3])
+ {
+ FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
+ }
+ else if (cam_mul[0] && cam_mul[2])
+ {
+ memcpy (pre_mul, cam_mul, sizeof pre_mul);
+ }
+ else
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB;
+#endif
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
+#endif
+ }
+ }
+ if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
+ dark = black;
+ sat = maximum;
+ if (threshold) wavelet_denoise();
+ maximum -= black;
+ for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
+ if (dmin > pre_mul[c])
+ dmin = pre_mul[c];
+ if (dmax < pre_mul[c])
+ dmax = pre_mul[c];
+ }
+ if (!highlight) dmax = dmin;
+ FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
+#ifdef DCRAW_VERBOSE
+ if (verbose) {
+ fprintf (stderr,
+ _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
+ FORC4 fprintf (stderr, " %f", pre_mul[c]);
+ fputc ('\n', stderr);
+ }
+#endif
+ size = iheight*iwidth;
+ for (i=0; i < size*4; i++) {
+ val = image[0][i];
+ if (!val) continue;
+ val -= black;
+ val *= scale_mul[i & 3];
+ image[0][i] = CLIP(val);
+ }
+ if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr,_("Correcting chromatic aberration...\n"));
+#endif
+ for (c=0; c < 4; c+=2) {
+ if (aber[c] == 1) continue;
+ img = (ushort *) malloc (size * sizeof *img);
+ merror (img, "scale_colors()");
+ for (i=0; i < size; i++)
+ img[i] = image[i][c];
+ for (row=0; row < iheight; row++) {
+ ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
+ if (ur > iheight-2) continue;
+ fr -= ur;
+ for (col=0; col < iwidth; col++) {
+ uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
+ if (uc > iwidth-2) continue;
+ fc -= uc;
+ pix = img + ur*iwidth + uc;
+ image[row*iwidth+col][c] =
+ (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) +
+ (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
+ }
+ }
+ free(img);
+ }
+ }
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,1,2);
+#endif
+}
+
+void CLASS pre_interpolate()
+{
+ ushort (*img)[4];
+ int row, col, c;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,0,2);
+#endif
+ if (shrink) {
+ if (half_size) {
+ height = iheight;
+ width = iwidth;
+ } else {
+ img = (ushort (*)[4]) calloc (height*width, sizeof *img);
+ merror (img, "pre_interpolate()");
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ c = fc(row,col);
+ img[row*width+col][c] = image[(row >> 1)*iwidth+(col >> 1)][c];
+ }
+ free (image);
+ image = img;
+ shrink = 0;
+ }
+ }
+ if (filters && colors == 3) {
+ if ((mix_green = four_color_rgb)) colors++;
+ else {
+ for (row = FC(1,0) >> 1; row < height; row+=2)
+ for (col = FC(row,1) & 1; col < width; col+=2)
+ image[row*width+col][1] = image[row*width+col][3];
+ filters &= ~((filters & 0x55555555) << 1);
+ }
+ }
+ if (half_size) filters = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,1,2);
+#endif
+}
+
+void CLASS border_interpolate (int border)
+{
+ unsigned row, col, y, x, f, c, sum[8];
+
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ if (col==border && row >= border && row < height-border)
+ col = width-border;
+ memset (sum, 0, sizeof sum);
+ for (y=row-1; y != row+2; y++)
+ for (x=col-1; x != col+2; x++)
+ if (y < height && x < width) {
+ f = fc(y,x);
+ sum[f] += image[y*width+x][f];
+ sum[f+4]++;
+ }
+ f = fc(row,col);
+ FORCC if (c != f && sum[c+4])
+ image[row*width+col][c] = sum[c] / sum[c+4];
+ }
+}
+
+void CLASS lin_interpolate()
+{
+ int code[16][16][32], *ip, sum[4];
+ int c, i, x, y, row, col, shift, color;
+ ushort *pix;
+
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Bilinear interpolation...\n"));
+#endif
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+ border_interpolate(1);
+ for (row=0; row < 16; row++)
+ for (col=0; col < 16; col++) {
+ ip = code[row][col];
+ memset (sum, 0, sizeof sum);
+ for (y=-1; y <= 1; y++)
+ for (x=-1; x <= 1; x++) {
+ shift = (y==0) + (x==0);
+ if (shift == 2) continue;
+ color = fc(row+y,col+x);
+ *ip++ = (width*y + x)*4 + color;
+ *ip++ = shift;
+ *ip++ = color;
+ sum[color] += 1 << shift;
+ }
+ FORCC
+ if (c != fc(row,col)) {
+ *ip++ = c;
+ *ip++ = 256 / sum[c];
+ }
+ }
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+ for (row=1; row < height-1; row++)
+ for (col=1; col < width-1; col++) {
+ pix = image[row*width+col];
+ ip = code[row & 15][col & 15];
+ memset (sum, 0, sizeof sum);
+ for (i=8; i--; ip+=3)
+ sum[ip[2]] += pix[ip[0]] << ip[1];
+ for (i=colors; --i; ip+=2)
+ pix[ip[0]] = sum[ip[0]] * ip[1] >> 8;
+ }
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+}
+
+/*
+ This algorithm is officially called:
+
+ "Interpolation using a Threshold-based variable number of gradients"
+
+ described in http://scien.stanford.edu/class/psych221/projects/99/tingchen/algodep/vargra.html
+
+ I've extended the basic idea to work with non-Bayer filter arrays.
+ Gradients are numbered clockwise from NW=0 to W=7.
+ */
+void CLASS vng_interpolate()
+{
+ static const signed char *cp, terms[] = {
+ -2,-2,+0,-1,0,0x01, -2,-2,+0,+0,1,0x01, -2,-1,-1,+0,0,0x01,
+ -2,-1,+0,-1,0,0x02, -2,-1,+0,+0,0,0x03, -2,-1,+0,+1,1,0x01,
+ -2,+0,+0,-1,0,0x06, -2,+0,+0,+0,1,0x02, -2,+0,+0,+1,0,0x03,
+ -2,+1,-1,+0,0,0x04, -2,+1,+0,-1,1,0x04, -2,+1,+0,+0,0,0x06,
+ -2,+1,+0,+1,0,0x02, -2,+2,+0,+0,1,0x04, -2,+2,+0,+1,0,0x04,
+ -1,-2,-1,+0,0,0x80, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01,
+ -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,0x88, -1,-1,+1,-2,0,0x40,
+ -1,-1,+1,-1,0,0x22, -1,-1,+1,+0,0,0x33, -1,-1,+1,+1,1,0x11,
+ -1,+0,-1,+2,0,0x08, -1,+0,+0,-1,0,0x44, -1,+0,+0,+1,0,0x11,
+ -1,+0,+1,-2,1,0x40, -1,+0,+1,-1,0,0x66, -1,+0,+1,+0,1,0x22,
+ -1,+0,+1,+1,0,0x33, -1,+0,+1,+2,1,0x10, -1,+1,+1,-1,1,0x44,
+ -1,+1,+1,+0,0,0x66, -1,+1,+1,+1,0,0x22, -1,+1,+1,+2,0,0x10,
+ -1,+2,+0,+1,0,0x04, -1,+2,+1,+0,1,0x04, -1,+2,+1,+1,0,0x04,
+ +0,-2,+0,+0,1,0x80, +0,-1,+0,+1,1,0x88, +0,-1,+1,-2,0,0x40,
+ +0,-1,+1,+0,0,0x11, +0,-1,+2,-2,0,0x40, +0,-1,+2,-1,0,0x20,
+ +0,-1,+2,+0,0,0x30, +0,-1,+2,+1,1,0x10, +0,+0,+0,+2,1,0x08,
+ +0,+0,+2,-2,1,0x40, +0,+0,+2,-1,0,0x60, +0,+0,+2,+0,1,0x20,
+ +0,+0,+2,+1,0,0x30, +0,+0,+2,+2,1,0x10, +0,+1,+1,+0,0,0x44,
+ +0,+1,+1,+2,0,0x10, +0,+1,+2,-1,1,0x40, +0,+1,+2,+0,0,0x60,
+ +0,+1,+2,+1,0,0x20, +0,+1,+2,+2,0,0x10, +1,-2,+1,+0,0,0x80,
+ +1,-1,+1,+1,0,0x88, +1,+0,+1,+2,0,0x08, +1,+0,+2,-1,0,0x40,
+ +1,+0,+2,+1,0,0x10
+ }, chood[] = { -1,-1, -1,0, -1,+1, 0,+1, +1,+1, +1,0, +1,-1, 0,-1 };
+ ushort (*brow[5])[4], *pix;
+ int prow=7, pcol=1, *ip, *code[16][16], gval[8], gmin, gmax, sum[4];
+ int row, col, x, y, x1, x2, y1, y2, t, weight, grads, color, diag;
+ int g, diff, thold, num, c;
+ lin_interpolate();
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("VNG interpolation...\n"));
+#endif
+
+ if (filters == 1) prow = pcol = 15;
+ ip = (int *) calloc ((prow+1)*(pcol+1), 1280);
+ merror (ip, "vng_interpolate()");
+ for (row=0; row <= prow; row++) /* Precalculate for VNG */
+ for (col=0; col <= pcol; col++) {
+ code[row][col] = ip;
+ for (cp=terms, t=0; t < 64; t++) {
+ y1 = *cp++; x1 = *cp++;
+ y2 = *cp++; x2 = *cp++;
+ weight = *cp++;
+ grads = *cp++;
+ color = fc(row+y1,col+x1);
+ if (fc(row+y2,col+x2) != color) continue;
+ diag = (fc(row,col+1) == color && fc(row+1,col) == color) ? 2:1;
+ if (abs(y1-y2) == diag && abs(x1-x2) == diag) continue;
+ *ip++ = (y1*width + x1)*4 + color;
+ *ip++ = (y2*width + x2)*4 + color;
+ *ip++ = weight;
+ for (g=0; g < 8; g++)
+ if (grads & 1<<g) *ip++ = g;
+ *ip++ = -1;
+ }
+ *ip++ = INT_MAX;
+ for (cp=chood, g=0; g < 8; g++) {
+ y = *cp++; x = *cp++;
+ *ip++ = (y*width + x) * 4;
+ color = fc(row,col);
+ if (fc(row+y,col+x) != color && fc(row+y*2,col+x*2) == color)
+ *ip++ = (y*width + x) * 8 + color;
+ else
+ *ip++ = 0;
+ }
+ }
+ brow[4] = (ushort (*)[4]) calloc (width*3, sizeof **brow);
+ merror (brow[4], "vng_interpolate()");
+ for (row=0; row < 3; row++)
+ brow[row] = brow[4] + row*width;
+ for (row=2; row < height-2; row++) { /* Do VNG interpolation */
+#ifdef LIBRAW_LIBRARY_BUILD
+ if(!((row-2)%256))RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(row-2)/256+1,((height-3)/256)+1);
+#endif
+ for (col=2; col < width-2; col++) {
+ pix = image[row*width+col];
+ ip = code[row & prow][col & pcol];
+ memset (gval, 0, sizeof gval);
+ while ((g = ip[0]) != INT_MAX) { /* Calculate gradients */
+ diff = ABS(pix[g] - pix[ip[1]]) << ip[2];
+ gval[ip[3]] += diff;
+ ip += 5;
+ if ((g = ip[-1]) == -1) continue;
+ gval[g] += diff;
+ while ((g = *ip++) != -1)
+ gval[g] += diff;
+ }
+ ip++;
+ gmin = gmax = gval[0]; /* Choose a threshold */
+ for (g=1; g < 8; g++) {
+ if (gmin > gval[g]) gmin = gval[g];
+ if (gmax < gval[g]) gmax = gval[g];
+ }
+ if (gmax == 0) {
+ memcpy (brow[2][col], pix, sizeof *image);
+ continue;
+ }
+ thold = gmin + (gmax >> 1);
+ memset (sum, 0, sizeof sum);
+ color = fc(row,col);
+ for (num=g=0; g < 8; g++,ip+=2) { /* Average the neighbors */
+ if (gval[g] <= thold) {
+ FORCC
+ if (c == color && ip[1])
+ sum[c] += (pix[c] + pix[ip[1]]) >> 1;
+ else
+ sum[c] += pix[ip[0] + c];
+ num++;
+ }
+ }
+ FORCC { /* Save to buffer */
+ t = pix[color];
+ if (c != color)
+ t += (sum[c] - sum[color]) / num;
+ brow[2][col][c] = CLIP(t);
+ }
+ }
+ if (row > 3) /* Write buffer to image */
+ memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+ for (g=0; g < 4; g++)
+ brow[(g-1) & 3] = brow[g];
+ }
+ memcpy (image[(row-2)*width+2], brow[0]+2, (width-4)*sizeof *image);
+ memcpy (image[(row-1)*width+2], brow[1]+2, (width-4)*sizeof *image);
+ free (brow[4]);
+ free (code[0][0]);
+}
+
+/*
+ Patterned Pixel Grouping Interpolation by Alain Desbiolles
+*/
+void CLASS ppg_interpolate()
+{
+ int dir[5] = { 1, width, -1, -width, 1 };
+ int row, col, diff[2], guess[2], c, d, i;
+ ushort (*pix)[4];
+
+ border_interpolate(3);
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("PPG interpolation...\n"));
+#endif
+
+/* Fill in the green layer with gradients and pattern recognition: */
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3);
+#endif
+ for (row=3; row < height-3; row++)
+ for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]) > 0; i++) {
+ guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2
+ - pix[-2*d][c] - pix[2*d][c];
+ diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) +
+ ABS(pix[ 2*d][c] - pix[ 0][c]) +
+ ABS(pix[ -d][1] - pix[ d][1]) ) * 3 +
+ ( ABS(pix[ 3*d][1] - pix[ d][1]) +
+ ABS(pix[-3*d][1] - pix[-d][1]) ) * 2;
+ }
+ d = dir[i = diff[0] > diff[1]];
+ pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]);
+ }
+/* Calculate red and blue for each green pixel: */
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3);
+#endif
+ for (row=1; row < height-1; row++)
+ for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]) > 0; c=2-c, i++)
+ pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1]
+ - pix[-d][1] - pix[d][1]) >> 1);
+ }
+/* Calculate blue for red pixels and vice versa: */
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3);
+#endif
+ for (row=1; row < height-1; row++)
+ for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) {
+ pix = image + row*width+col;
+ for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) {
+ diff[i] = ABS(pix[-d][c] - pix[d][c]) +
+ ABS(pix[-d][1] - pix[0][1]) +
+ ABS(pix[ d][1] - pix[0][1]);
+ guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1]
+ - pix[-d][1] - pix[d][1];
+ }
+ if (diff[0] != diff[1])
+ pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1);
+ else
+ pix[0][c] = CLIP((guess[0]+guess[1]) >> 2);
+ }
+}
+
+/*
+ Adaptive Homogeneity-Directed interpolation is based on
+ the work of Keigo Hirakawa, Thomas Parks, and Paul Lee.
+ */
+#define TS 256 /* Tile Size */
+void CLASS ahd_interpolate()
+{
+ int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2];
+ ushort (*pix)[4], (*rix)[3];
+ static const int dir[4] = { -1, 1, -TS, TS };
+ unsigned ldiff[2][4], abdiff[2][4], leps, abeps;
+ float r, cbrt[0x10000], xyz[3], xyz_cam[3][4];
+ ushort (*rgb)[TS][TS][3];
+ short (*lab)[TS][TS][3], (*lix)[3];
+ char (*homo)[TS][TS], *buffer;
+
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("AHD interpolation...\n"));
+#endif
+
+ for (i=0; i < 0x10000; i++) {
+ r = i / 65535.0;
+ cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0;
+ }
+ for (i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ for (xyz_cam[i][j] = k=0; k < 3; k++)
+ xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i];
+
+ border_interpolate(5);
+ buffer = (char *) malloc (26*TS*TS); /* 1664 kB */
+ merror (buffer, "ahd_interpolate()");
+ rgb = (ushort(*)[TS][TS][3]) buffer;
+ lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS);
+ homo = (char (*)[TS][TS]) (buffer + 24*TS*TS);
+
+ for (top=2; top < height-5; top += TS-6)
+ {
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,(top-2)/(TS-6),(height-7)/(TS-6)+1);
+#endif
+ for (left=2; left < width-5; left += TS-6) {
+
+/* Interpolate green horizontally and vertically: */
+ for (row = top; row < top+TS && row < height-2; row++) {
+ col = left + (FC(row,left) & 1);
+ for (c = FC(row,col); col < left+TS && col < width-2; col+=2) {
+ pix = image + row*width+col;
+ val = ((pix[-1][1] + pix[0][c] + pix[1][1]) * 2
+ - pix[-2][c] - pix[2][c]) >> 2;
+ rgb[0][row-top][col-left][1] = ULIM(val,pix[-1][1],pix[1][1]);
+ val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2
+ - pix[-2*width][c] - pix[2*width][c]) >> 2;
+ rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]);
+ }
+ }
+/* Interpolate red and blue, and convert to CIELab: */
+ for (d=0; d < 2; d++)
+ for (row=top+1; row < top+TS-1 && row < height-3; row++)
+ for (col=left+1; col < left+TS-1 && col < width-3; col++) {
+ pix = image + row*width+col;
+ rix = &rgb[d][row-top][col-left];
+ lix = &lab[d][row-top][col-left];
+ if ((c = 2 - FC(row,col)) == 1) {
+ c = FC(row+1,col);
+ val = pix[0][1] + (( pix[-1][2-c] + pix[1][2-c]
+ - rix[-1][1] - rix[1][1] ) >> 1);
+ rix[0][2-c] = CLIP(val);
+ val = pix[0][1] + (( pix[-width][c] + pix[width][c]
+ - rix[-TS][1] - rix[TS][1] ) >> 1);
+ } else
+ val = rix[0][1] + (( pix[-width-1][c] + pix[-width+1][c]
+ + pix[+width-1][c] + pix[+width+1][c]
+ - rix[-TS-1][1] - rix[-TS+1][1]
+ - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2);
+ rix[0][c] = CLIP(val);
+ c = FC(row,col);
+ rix[0][c] = pix[0][c];
+ xyz[0] = xyz[1] = xyz[2] = 0.5;
+ FORCC {
+ xyz[0] += xyz_cam[0][c] * rix[0][c];
+ xyz[1] += xyz_cam[1][c] * rix[0][c];
+ xyz[2] += xyz_cam[2][c] * rix[0][c];
+ }
+ xyz[0] = cbrt[CLIP((int) xyz[0])];
+ xyz[1] = cbrt[CLIP((int) xyz[1])];
+ xyz[2] = cbrt[CLIP((int) xyz[2])];
+ lix[0][0] = 64 * (116 * xyz[1] - 16);
+ lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]);
+ lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]);
+ }
+/* Build homogeneity maps from the CIELab images: */
+ memset (homo, 0, 2*TS*TS);
+ for (row=top+2; row < top+TS-2 && row < height-4; row++) {
+ tr = row-top;
+ for (col=left+2; col < left+TS-2 && col < width-4; col++) {
+ tc = col-left;
+ for (d=0; d < 2; d++) {
+ lix = &lab[d][tr][tc];
+ for (i=0; i < 4; i++) {
+ ldiff[d][i] = ABS(lix[0][0]-lix[dir[i]][0]);
+ abdiff[d][i] = SQR(lix[0][1]-lix[dir[i]][1])
+ + SQR(lix[0][2]-lix[dir[i]][2]);
+ }
+ }
+ leps = MIN(MAX(ldiff[0][0],ldiff[0][1]),
+ MAX(ldiff[1][2],ldiff[1][3]));
+ abeps = MIN(MAX(abdiff[0][0],abdiff[0][1]),
+ MAX(abdiff[1][2],abdiff[1][3]));
+ for (d=0; d < 2; d++)
+ for (i=0; i < 4; i++)
+ if (ldiff[d][i] <= leps && abdiff[d][i] <= abeps)
+ homo[d][tr][tc]++;
+ }
+ }
+/* Combine the most homogenous pixels for the final result: */
+ for (row=top+3; row < top+TS-3 && row < height-5; row++) {
+ tr = row-top;
+ for (col=left+3; col < left+TS-3 && col < width-5; col++) {
+ tc = col-left;
+ for (d=0; d < 2; d++)
+ for (hm[d]=0, i=tr-1; i <= tr+1; i++)
+ for (j=tc-1; j <= tc+1; j++)
+ hm[d] += homo[d][i][j];
+ if (hm[0] != hm[1])
+ FORC3 image[row*width+col][c] = rgb[hm[1] > hm[0]][tr][tc][c];
+ else
+ FORC3 image[row*width+col][c] =
+ (rgb[0][tr][tc][c] + rgb[1][tr][tc][c]) >> 1;
+ }
+ }
+ }
+ }
+ free (buffer);
+}
+#undef TS
+
+void CLASS median_filter()
+{
+ ushort (*pix)[4];
+ int pass, c, i, j, k, med[9];
+ static const uchar opt[] = /* Optimal 9-element median search */
+ { 1,2, 4,5, 7,8, 0,1, 3,4, 6,7, 1,2, 4,5, 7,8,
+ 0,3, 5,8, 4,7, 3,6, 1,4, 2,5, 4,7, 4,2, 6,4, 4,2 };
+
+ for (pass=1; pass <= med_passes; pass++) {
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER,pass-1,med_passes);
+#endif
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr,_("Median filter pass %d...\n"), pass);
+#endif
+ for (c=0; c < 3; c+=2) {
+ for (pix = image; pix < image+width*height; pix++)
+ pix[0][3] = pix[0][c];
+ for (pix = image+width; pix < image+width*(height-1); pix++) {
+ if ((pix-image+1) % width < 2) continue;
+ for (k=0, i = -width; i <= width; i += width)
+ for (j = i-1; j <= i+1; j++)
+ med[k++] = pix[j][3] - pix[j][1];
+ for (i=0; i < sizeof opt; i+=2)
+ if (med[opt[i]] > med[opt[i+1]])
+ SWAP (med[opt[i]] , med[opt[i+1]]);
+ pix[0][c] = CLIP(med[4] + pix[0][1]);
+ }
+ }
+ }
+}
+
+void CLASS blend_highlights()
+{
+ int clip=INT_MAX, row, col, c, i, j;
+ static const float trans[2][4][4] =
+ { { { 1,1,1 }, { 1.7320508,-1.7320508,0 }, { -1,-1,2 } },
+ { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+ static const float itrans[2][4][4] =
+ { { { 1,0.8660254,-0.5 }, { 1,-0.8660254,-0.5 }, { 1,0,1 } },
+ { { 1,1,1,1 }, { 1,-1,1,-1 }, { 1,1,-1,-1 }, { 1,-1,-1,1 } } };
+ float cam[2][4], lab[2][4], sum[2], chratio;
+
+ if ((unsigned) (colors-3) > 1) return;
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Blending highlights...\n"));
+#endif
+ FORCC if (clip > (i = 65535*pre_mul[c])) clip = i;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,0,2);
+#endif
+ for (row=0; row < height; row++)
+ for (col=0; col < width; col++) {
+ FORCC if (image[row*width+col][c] > clip) break;
+ if (c == colors) continue;
+ FORCC {
+ cam[0][c] = image[row*width+col][c];
+ cam[1][c] = MIN(cam[0][c],clip);
+ }
+ for (i=0; i < 2; i++) {
+ FORCC for (lab[i][c]=j=0; j < colors; j++)
+ lab[i][c] += trans[colors-3][c][j] * cam[i][j];
+ for (sum[i]=0,c=1; c < colors; c++)
+ sum[i] += SQR(lab[i][c]);
+ }
+ chratio = sqrt(sum[1]/sum[0]);
+ for (c=1; c < colors; c++)
+ lab[0][c] *= chratio;
+ FORCC for (cam[0][c]=j=0; j < colors; j++)
+ cam[0][c] += itrans[colors-3][c][j] * lab[0][j];
+ FORCC image[row*width+col][c] = cam[0][c] / colors;
+ }
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,1,2);
+#endif
+}
+
+#define SCALE (4 >> shrink)
+void CLASS recover_highlights()
+{
+ float *map, sum, wgt, grow;
+ int hsat[4], count, spread, change, val, i;
+ unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x;
+ ushort *pixel;
+ static const signed char dir[8][2] =
+ { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} };
+
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Rebuilding highlights...\n"));
+#endif
+
+ grow = pow (2.0, 4.0-highlight);
+ FORCC hsat[c] = 32000 * pre_mul[c];
+ for (kc=0, c=1; c < colors; c++)
+ if (pre_mul[kc] < pre_mul[c]) kc = c;
+ high = height / SCALE;
+ wide = width / SCALE;
+ map = (float *) calloc (high*wide, sizeof *map);
+ merror (map, "recover_highlights()");
+ FORCC if (c != kc) {
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,c-1,colors-1);
+#endif
+ memset (map, 0, high*wide*sizeof *map);
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ sum = wgt = count = 0;
+ for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+ for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+ pixel = image[row*width+col];
+ if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) {
+ sum += pixel[c];
+ wgt += pixel[kc];
+ count++;
+ }
+ }
+ if (count == SCALE*SCALE)
+ map[mrow*wide+mcol] = sum / wgt;
+ }
+ for (spread = 32/grow; spread--; ) {
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ if (map[mrow*wide+mcol]) continue;
+ sum = count = 0;
+ for (d=0; d < 8; d++) {
+ y = mrow + dir[d][0];
+ x = mcol + dir[d][1];
+ if (y < high && x < wide && map[y*wide+x] > 0) {
+ sum += (1 + (d & 1)) * map[y*wide+x];
+ count += 1 + (d & 1);
+ }
+ }
+ if (count > 3)
+ map[mrow*wide+mcol] = - (sum+grow) / (count+grow);
+ }
+ for (change=i=0; i < high*wide; i++)
+ if (map[i] < 0) {
+ map[i] = -map[i];
+ change = 1;
+ }
+ if (!change) break;
+ }
+ for (i=0; i < high*wide; i++)
+ if (map[i] == 0) map[i] = 1;
+ for (mrow=0; mrow < high; mrow++)
+ for (mcol=0; mcol < wide; mcol++) {
+ for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++)
+ for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) {
+ pixel = image[row*width+col];
+ if (pixel[c] / hsat[c] > 1) {
+ val = pixel[kc] * map[mrow*wide+mcol];
+ if (pixel[c] < val) pixel[c] = CLIP(val);
+ }
+ }
+ }
+ }
+ free (map);
+}
+#undef SCALE
+
+void CLASS tiff_get (unsigned base,
+ unsigned *tag, unsigned *type, unsigned *len, unsigned *save)
+{
+ *tag = get2();
+ *type = get2();
+ *len = get4();
+ *save = ftell(ifp) + 4;
+ if (*len * ("11124811248488"[*type < 14 ? *type:0]-'0') > 4)
+ fseek (ifp, get4()+base, SEEK_SET);
+}
+
+void CLASS parse_thumb_note (int base, unsigned toff, unsigned tlen)
+{
+ unsigned entries, tag, type, len, save;
+
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ if (tag == toff) thumb_offset = get4()+base;
+ if (tag == tlen) thumb_length = get4();
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+#line 4784 "dcraw/dcraw.c"
+void CLASS parse_makernote (int base, int uptag)
+{
+ static const uchar xlat[2][256] = {
+ { 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
+ 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
+ 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
+ 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
+ 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
+ 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
+ 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
+ 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
+ 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
+ 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
+ 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
+ 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
+ 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
+ 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
+ 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
+ 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 },
+ { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
+ 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
+ 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
+ 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
+ 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
+ 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
+ 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
+ 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
+ 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
+ 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
+ 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
+ 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
+ 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
+ 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
+ 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
+ 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f } };
+ unsigned offset=0, entries, tag, type, len, save, c;
+ unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0};
+ uchar buf97[324], ci, cj, ck;
+ short sorder=order;
+ char buf[10];
+/*
+ The MakerNote might have its own TIFF header (possibly with
+ its own byte-order!), or it might just be a table.
+ */
+ fread (buf, 1, 10, ifp);
+ if (!strncmp (buf,"KDK" ,3) || /* these aren't TIFF tables */
+ !strncmp (buf,"VER" ,3) ||
+ !strncmp (buf,"IIII",4) ||
+ !strncmp (buf,"MMMM",4)) return;
+ if (!strncmp (buf,"KC" ,2) || /* Konica KD-400Z, KD-510Z */
+ !strncmp (buf,"MLY" ,3)) { /* Minolta DiMAGE G series */
+ order = 0x4d4d;
+ while ((i=ftell(ifp)) < data_offset && i < 16384) {
+ wb[0] = wb[2]; wb[2] = wb[1]; wb[1] = wb[3];
+ wb[3] = get2();
+ if (wb[1] == 256 && wb[3] == 256 &&
+ wb[0] > 256 && wb[0] < 640 && wb[2] > 256 && wb[2] < 640)
+ FORC4 cam_mul[c] = wb[c];
+ }
+ goto quit;
+ }
+ if (!strcmp (buf,"Nikon")) {
+ base = ftell(ifp);
+ order = get2();
+ if (get2() != 42) goto quit;
+ offset = get4();
+ fseek (ifp, offset-8, SEEK_CUR);
+ } else if (!strcmp (buf,"OLYMPUS")) {
+ base = ftell(ifp)-10;
+ fseek (ifp, -2, SEEK_CUR);
+ order = get2(); get2();
+ } else if (!strncmp (buf,"FUJIFILM",8) ||
+ !strncmp (buf,"SONY",4) ||
+ !strcmp (buf,"Panasonic")) {
+ order = 0x4949;
+ fseek (ifp, 2, SEEK_CUR);
+ } else if (!strcmp (buf,"OLYMP") ||
+ !strcmp (buf,"LEICA") ||
+ !strcmp (buf,"Ricoh") ||
+ !strcmp (buf,"EPSON"))
+ fseek (ifp, -2, SEEK_CUR);
+ else if (!strcmp (buf,"AOC") ||
+ !strcmp (buf,"QVC"))
+ fseek (ifp, -4, SEEK_CUR);
+ else fseek (ifp, -10, SEEK_CUR);
+
+ entries = get2();
+ if (entries > 1000) return;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ tag |= uptag << 16;
+ if (tag == 2 && strstr(make,"NIKON"))
+ iso_speed = (get2(),get2());
+ if (tag == 4 && len > 26 && len < 35) {
+ if ((i=(get4(),get2())) != 0x7fff && !iso_speed)
+ iso_speed = 50 * pow (2.0, i/32.0 - 4);
+ if ((i=(get2(),get2())) != 0x7fff && !aperture)
+ aperture = pow (2.0, i/64.0);
+ if ((i=get2()) != 0xffff && !shutter)
+ shutter = pow (2.0, (short) i/-32.0);
+ wbi = (get2(),get2());
+ shot_order = (get2(),get2());
+ }
+ if (tag == 7 && type == 2 && len > 20)
+ fgets (model2, 64, ifp);
+ if (tag == 8 && type == 4)
+ shot_order = get4();
+ if (tag == 9 && !strcmp(make,"Canon"))
+ fread (artist, 64, 1, ifp);
+ if (tag == 0xc && len == 4) {
+ cam_mul[0] = getreal(type);
+ cam_mul[2] = getreal(type);
+ }
+ if (tag == 0x10 && type == 4)
+ unique_id = get4();
+ if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) {
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_tiff_ifd (base);
+ }
+ if (tag == 0x14 && len == 2560 && type == 7) {
+ fseek (ifp, 1248, SEEK_CUR);
+ goto get2_256;
+ }
+ if (tag == 0x15 && type == 2 && is_raw)
+ fread (model, 64, 1, ifp);
+ if (strstr(make,"PENTAX")) {
+ if (tag == 0x1b) tag = 0x1018;
+ if (tag == 0x1c) tag = 0x1017;
+ }
+ if (tag == 0x1d)
+ while ((c = fgetc(ifp)) && c != EOF)
+ serial = serial*10 + (isdigit(c) ? c - '0' : c % 10);
+ if (tag == 0x81 && type == 4) {
+ data_offset = get4();
+ fseek (ifp, data_offset + 41, SEEK_SET);
+ raw_height = get2() * 2;
+ raw_width = get2();
+ filters = 0x61616161;
+ }
+ if (tag == 0x29 && type == 1) {
+ c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0;
+ fseek (ifp, 8 + c*32, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4();
+ }
+ if ((tag == 0x81 && type == 7) ||
+ (tag == 0x100 && type == 7) ||
+ (tag == 0x280 && type == 1)) {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ if (tag == 0x88 && type == 4 && (thumb_offset = get4()))
+ thumb_offset += base;
+ if (tag == 0x89 && type == 4)
+ thumb_length = get4();
+ if (tag == 0x8c || tag == 0x96)
+ meta_offset = ftell(ifp);
+ if (tag == 0x97) {
+ for (i=0; i < 4; i++)
+ ver97 = ver97 * 10 + fgetc(ifp)-'0';
+ switch (ver97) {
+ case 100:
+ fseek (ifp, 68, SEEK_CUR);
+ FORC4 cam_mul[(c >> 1) | ((c & 1) << 1)] = get2();
+ break;
+ case 102:
+ fseek (ifp, 6, SEEK_CUR);
+ goto get2_rggb;
+ case 103:
+ fseek (ifp, 16, SEEK_CUR);
+ FORC4 cam_mul[c] = get2();
+ }
+ if (ver97 >= 200) {
+ if (ver97 != 205) fseek (ifp, 280, SEEK_CUR);
+ fread (buf97, 324, 1, ifp);
+ }
+ }
+ if (tag == 0xa4 && type == 3) {
+ fseek (ifp, wbi*48, SEEK_CUR);
+ FORC3 cam_mul[c] = get2();
+ }
+ if (tag == 0xa7 && (unsigned) (ver97-200) < 12 && !cam_mul[0]) {
+ ci = xlat[0][serial & 0xff];
+ cj = xlat[1][fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp)];
+ ck = 0x60;
+ for (i=0; i < 324; i++)
+ buf97[i] ^= (cj += ci * ck++);
+ i = "66666>666;6A"[ver97-200] - '0';
+ FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] =
+ sget2 (buf97 + (i & -2) + c*2);
+ }
+ if (tag == 0x200 && len == 3)
+ shot_order = (get4(),get4());
+ if (tag == 0x200 && len == 4)
+ black = (get2()+get2()+get2()+get2())/4;
+ if (tag == 0x201 && len == 4)
+ goto get2_rggb;
+ if (tag == 0x220 && len == 53) {
+ fseek (ifp, 14, SEEK_CUR);
+ pentax_tree();
+ }
+ if (tag == 0x401 && len == 4) {
+ black = (get4()+get4()+get4()+get4())/4;
+ }
+ if (tag == 0xe01) { /* Nikon Capture Note */
+ type = order;
+ order = 0x4949;
+ fseek (ifp, 22, SEEK_CUR);
+ for (offset=22; offset+22 < len; offset += 22+i) {
+ tag = get4();
+ fseek (ifp, 14, SEEK_CUR);
+ i = get4()-4;
+ if (tag == 0x76a43207) flip = get2();
+ else fseek (ifp, i, SEEK_CUR);
+ }
+ order = type;
+ }
+ if (tag == 0xe80 && len == 256 && type == 7) {
+ fseek (ifp, 48, SEEK_CUR);
+ cam_mul[0] = get2() * 508 * 1.078 / 0x10000;
+ cam_mul[2] = get2() * 382 * 1.173 / 0x10000;
+ }
+ if (tag == 0xf00 && type == 7) {
+ if (len == 614)
+ fseek (ifp, 176, SEEK_CUR);
+ else if (len == 734 || len == 1502)
+ fseek (ifp, 148, SEEK_CUR);
+ else goto next;
+ goto get2_256;
+ }
+ if ((tag == 0x1011 && len == 9) || tag == 0x20400200)
+ {
+ for (i=0; i < 3; i++)
+ FORC3 cmatrix[i][c] = ((short) get2()) / 256.0;
+ }
+ if ((tag == 0x1012 || tag == 0x20400600) && len == 4)
+ for (black = i=0; i < 4; i++)
+ black += get2() << 2;
+ if (tag == 0x1017 || tag == 0x20400100)
+ {
+ cam_mul[0] = get2() / 256.0;
+ }
+ if (tag == 0x1018 || tag == 0x20400100)
+ {
+ cam_mul[2] = get2() / 256.0;
+ }
+ if (tag == 0x2011 && len == 2) {
+get2_256:
+ order = 0x4d4d;
+ cam_mul[0] = get2() / 256.0;
+ cam_mul[2] = get2() / 256.0;
+ }
+ if ((tag | 0x70) == 0x2070 && type == 4)
+ fseek (ifp, get4()+base, SEEK_SET);
+ if (tag == 0x2010 && type != 7)
+ load_raw = &CLASS olympus_e410_load_raw;
+ if (tag == 0x2020)
+ parse_thumb_note (base, 257, 258);
+ if (tag == 0x2040)
+ parse_makernote (base, 0x2040);
+ if (tag == 0xb028) {
+ fseek (ifp, get4(), SEEK_SET);
+ parse_thumb_note (base, 136, 137);
+ }
+ if (tag == 0x4001 && len > 500) {
+ i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126;
+ fseek (ifp, i, SEEK_CUR);
+get2_rggb:
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ fseek (ifp, 22, SEEK_CUR);
+ FORC4 sraw_mul[c ^ (c >> 1)] = get2();
+ }
+next:
+ fseek (ifp, save, SEEK_SET);
+ }
+quit:
+ order = sorder;
+}
+
+/*
+ Since the TIFF DateTime string has no timezone information,
+ assume that the camera's clock was set to Universal Time.
+ */
+void CLASS get_timestamp (int reversed)
+{
+ struct tm t;
+ char str[20];
+ int i;
+
+ str[19] = 0;
+ if (reversed)
+ for (i=19; i--; ) str[i] = fgetc(ifp);
+ else
+ fread (str, 19, 1, ifp);
+ memset (&t, 0, sizeof t);
+ if (sscanf (str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon,
+ &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
+ return;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+}
+
+void CLASS parse_exif (int base)
+{
+ unsigned kodak, entries, tag, type, len, save, c;
+ double expo;
+
+ kodak = !strncmp(make,"EASTMAN",7);
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 33434: shutter = getreal(type); break;
+ case 33437: aperture = getreal(type); break;
+ case 34855: iso_speed = get2(); break;
+ case 36867:
+ case 36868: get_timestamp(0); break;
+ case 37377: if ((expo = -getreal(type)) < 128)
+ shutter = pow (2.0, expo); break;
+ case 37378: aperture = pow (2.0, getreal(type)/2); break;
+ case 37386: focal_len = getreal(type); break;
+ case 37500: parse_makernote (base, 0); break;
+ case 40962: if (kodak) raw_width = get4(); break;
+ case 40963: if (kodak) raw_height = get4(); break;
+ case 41730:
+ if (get4() == 0x20002)
+ for (exif_cfa=c=0; c < 8; c+=2)
+ exif_cfa |= fgetc(ifp) * 0x01010101 << c;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS parse_gps (int base)
+{
+ unsigned entries, tag, type, len, save, c;
+
+ entries = get2();
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 1: case 3: case 5:
+ gpsdata[29+tag/2] = getc(ifp); break;
+ case 2: case 4: case 7:
+ FORC(6) gpsdata[tag/3*6+c] = get4(); break;
+ case 6:
+ FORC(2) gpsdata[18+c] = get4(); break;
+ case 18: case 29:
+ fgets ((char *) (gpsdata+14+tag/3), MIN(len,12), ifp);
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS romm_coeff (float romm_cam[3][3])
+{
+ static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
+ { { 2.034193, -0.727420, -0.306766 },
+ { -0.228811, 1.231729, -0.002922 },
+ { -0.008565, -0.153273, 1.161839 } };
+ int i, j, k;
+
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++)
+ for (cmatrix[i][j] = k=0; k < 3; k++)
+ cmatrix[i][j] += rgb_romm[i][k] * romm_cam[k][j];
+}
+
+void CLASS parse_mos (int offset)
+{
+ char data[40];
+ int skip, from, i, c, neut[4], planes=0, frot=0;
+ static const char *mod[] =
+ { "","DCB2","Volare","Cantare","CMost","Valeo 6","Valeo 11","Valeo 22",
+ "Valeo 11p","Valeo 17","","Aptus 17","Aptus 22","Aptus 75","Aptus 65",
+ "Aptus 54S","Aptus 65S","Aptus 75S","AFi 5","AFi 6","AFi 7" };
+ float romm_cam[3][3];
+
+ fseek (ifp, offset, SEEK_SET);
+ while (1) {
+ if (get4() != 0x504b5453) break;
+ get4();
+ fread (data, 1, 40, ifp);
+ skip = get4();
+ from = ftell(ifp);
+ if (!strcmp(data,"JPEG_preview_data")) {
+ thumb_offset = from;
+ thumb_length = skip;
+ }
+ if (!strcmp(data,"icc_camera_profile")) {
+ profile_offset = from;
+ profile_length = skip;
+ }
+ if (!strcmp(data,"ShootObj_back_type")) {
+ fscanf (ifp, "%d", &i);
+ if ((unsigned) i < sizeof mod / sizeof (*mod))
+ strcpy (model, mod[i]);
+ }
+ if (!strcmp(data,"icc_camera_to_tone_matrix")) {
+ for (i=0; i < 9; i++)
+ romm_cam[0][i] = int_to_float(get4());
+ romm_coeff (romm_cam);
+ }
+ if (!strcmp(data,"CaptProf_color_matrix")) {
+ for (i=0; i < 9; i++)
+ fscanf (ifp, "%f", &romm_cam[0][i]);
+ romm_coeff (romm_cam);
+ }
+ if (!strcmp(data,"CaptProf_number_of_planes"))
+ fscanf (ifp, "%d", &planes);
+ if (!strcmp(data,"CaptProf_raw_data_rotation"))
+ fscanf (ifp, "%d", &flip);
+ if (!strcmp(data,"CaptProf_mosaic_pattern"))
+ FORC4 {
+ fscanf (ifp, "%d", &i);
+ if (i == 1) frot = c ^ (c >> 1);
+ }
+ if (!strcmp(data,"ImgProf_rotation_angle")) {
+ fscanf (ifp, "%d", &i);
+ flip = i - flip;
+ }
+ if (!strcmp(data,"NeutObj_neutrals") && !cam_mul[0]) {
+ FORC4 fscanf (ifp, "%d", neut+c);
+ FORC3 cam_mul[c] = (float) neut[0] / neut[c+1];
+ }
+ parse_mos (from);
+ fseek (ifp, skip+from, SEEK_SET);
+ }
+ if (planes)
+ filters = (planes == 1) * 0x01010101 *
+ (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3];
+}
+
+void CLASS linear_table (unsigned len)
+{
+ int i;
+ if (len > 0x1000) len = 0x1000;
+ read_shorts (curve, len);
+ for (i=len; i < 0x1000; i++)
+ curve[i] = curve[i-1];
+ maximum = curve[0xfff];
+}
+
+void CLASS parse_kodak_ifd (int base)
+{
+ unsigned entries, tag, type, len, save;
+ int i, c, wbi=-2, wbtemp=6500;
+ float mul[3], num;
+
+ entries = get2();
+ if (entries > 1024) return;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ if (tag == 1020) wbi = getint(type);
+ if (tag == 1021 && len == 72) { /* WB set in software */
+ fseek (ifp, 40, SEEK_CUR);
+ FORC3 cam_mul[c] = 2048.0 / get2();
+ wbi = -2;
+ }
+ if (tag == 2118) wbtemp = getint(type);
+ if (tag == 2130 + wbi)
+ FORC3 mul[c] = getreal(type);
+ if (tag == 2140 + wbi && wbi >= 0)
+ {
+ FORC3 {
+ for (num=i=0; i < 4; i++)
+ num += getreal(type) * pow (wbtemp/100.0, i);
+ cam_mul[c] = 2048 / (num * mul[c]);
+ }
+ }
+ if (tag == 2317) linear_table (len);
+ if (tag == 6020) iso_speed = getint(type);
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+#line 5265 "dcraw/dcraw.c"
+int CLASS parse_tiff_ifd (int base)
+{
+ unsigned entries, tag, type, len, plen=16, save;
+ int ifd, use_cm=0, cfa, i, j, c, ima_len=0;
+ char software[64], *cbuf, *cp;
+ uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256];
+ double dblack, cc[4][4], cm[4][3], cam_xyz[4][3], num;
+ double ab[]={ 1,1,1,1 }, asn[] = { 0,0,0,0 }, xyz[] = { 1,1,1 };
+ unsigned sony_curve[] = { 0,0,0,0,0,4095 };
+ unsigned *buf, sony_offset=0, sony_length=0, sony_key=0;
+ struct jhead jh;
+ FILE *sfp;
+
+ if (tiff_nifds >= sizeof tiff_ifd / sizeof tiff_ifd[0])
+ return 1;
+ ifd = tiff_nifds++;
+ for (j=0; j < 4; j++)
+ for (i=0; i < 4; i++)
+ cc[j][i] = i == j;
+ entries = get2();
+ if (entries > 512) return 1;
+ while (entries--) {
+ tiff_get (base, &tag, &type, &len, &save);
+ switch (tag) {
+ case 17: case 18:
+ if (type == 3 && len == 1)
+ {
+ cam_mul[(tag-17)*2] = get2() / 256.0;
+ }
+ break;
+ case 23:
+ if (type == 3) iso_speed = get2();
+ break;
+ case 36: case 37: case 38:
+ cam_mul[tag-0x24] = get2();
+ break;
+ case 39:
+ if (len < 50 || cam_mul[0]) break;
+ fseek (ifp, 12, SEEK_CUR);
+ FORC3 cam_mul[c] = get2();
+ break;
+ case 46:
+ if (type != 7 || fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) break;
+ thumb_offset = ftell(ifp) - 2;
+ thumb_length = len;
+ break;
+ case 2: case 256: /* ImageWidth */
+ tiff_ifd[ifd].t_width = getint(type);
+ break;
+ case 3: case 257: /* ImageHeight */
+ tiff_ifd[ifd].t_height = getint(type);
+ break;
+ case 258: /* BitsPerSample */
+ tiff_ifd[ifd].samples = len & 7;
+ tiff_ifd[ifd].bps = get2();
+ break;
+ case 259: /* Compression */
+ tiff_ifd[ifd].comp = get2();
+ break;
+ case 262: /* PhotometricInterpretation */
+ tiff_ifd[ifd].phint = get2();
+ break;
+ case 270: /* ImageDescription */
+ fread (desc, 512, 1, ifp);
+ break;
+ case 271: /* Make */
+ fgets (make, 64, ifp);
+ break;
+ case 272: /* Model */
+ fgets (model, 64, ifp);
+ break;
+ case 280: /* Panasonic RW2 offset */
+ if (type != 4) break;
+ load_raw = &CLASS panasonic_load_raw;
+ load_flags = 0x2008;
+ case 273: /* StripOffset */
+ case 513:
+ tiff_ifd[ifd].offset = get4()+base;
+ if (!tiff_ifd[ifd].bps) {
+ fseek (ifp, tiff_ifd[ifd].offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ tiff_ifd[ifd].comp = 6;
+ tiff_ifd[ifd].t_width = jh.wide << (jh.clrs == 2);
+ tiff_ifd[ifd].t_height = jh.high;
+ tiff_ifd[ifd].bps = jh.bits;
+ tiff_ifd[ifd].samples = jh.clrs;
+ }
+ }
+ break;
+ case 274: /* Orientation */
+ tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0';
+ break;
+ case 277: /* SamplesPerPixel */
+ tiff_ifd[ifd].samples = getint(type) & 7;
+ break;
+ case 279: /* StripByteCounts */
+ case 514:
+ tiff_ifd[ifd].bytes = get4();
+ break;
+ case 305: case 11: /* Software */
+ fgets (software, 64, ifp);
+ if (!strncmp(software,"Adobe",5) ||
+ !strncmp(software,"dcraw",5) ||
+ !strncmp(software,"UFRaw",5) ||
+ !strncmp(software,"Bibble",6) ||
+ !strncmp(software,"Nikon Scan",10) ||
+ !strcmp (software,"Digital Photo Professional"))
+ is_raw = 0;
+ break;
+ case 306: /* DateTime */
+ get_timestamp(0);
+ break;
+ case 315: /* Artist */
+ fread (artist, 64, 1, ifp);
+ break;
+ case 322: /* TileWidth */
+ tile_width = getint(type);
+ break;
+ case 323: /* TileLength */
+ tile_length = getint(type);
+ break;
+ case 324: /* TileOffsets */
+ tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4();
+ if (len == 4) {
+ load_raw = &CLASS sinar_4shot_load_raw;
+ is_raw = 5;
+ }
+ break;
+ case 330: /* SubIFDs */
+ if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) {
+ load_raw = &CLASS sony_arw_load_raw;
+ data_offset = get4()+base;
+ ifd++; break;
+ }
+ while (len--) {
+ i = ftell(ifp);
+ fseek (ifp, get4()+base, SEEK_SET);
+ if (parse_tiff_ifd (base)) break;
+ fseek (ifp, i+4, SEEK_SET);
+ }
+ break;
+ case 400:
+ strcpy (make, "Sarnoff");
+ maximum = 0xfff;
+ break;
+ case 28688:
+ FORC4 sony_curve[c+1] = get2() >> 2 & 0xfff;
+ for (i=0; i < 5; i++)
+ for (j = sony_curve[i]+1; j <= sony_curve[i+1]; j++)
+ curve[j] = curve[j-1] + (1 << i);
+ break;
+ case 29184: sony_offset = get4(); break;
+ case 29185: sony_length = get4(); break;
+ case 29217: sony_key = get4(); break;
+ case 29264:
+ parse_minolta (ftell(ifp));
+ raw_width = 0;
+ break;
+ case 29443:
+ FORC4 cam_mul[c ^ (c < 2)] = get2();
+ break;
+ case 29459:
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ break;
+ case 33405: /* Model2 */
+ fgets (model2, 64, ifp);
+ break;
+ case 33422: /* CFAPattern */
+ case 64777: /* Kodak P-series */
+ if ((plen=len) > 16) plen = 16;
+ fread (cfa_pat, 1, plen, ifp);
+ for (colors=cfa=i=0; i < plen; i++) {
+ colors += !(cfa & (1 << cfa_pat[i]));
+ cfa |= 1 << cfa_pat[i];
+ }
+ if (cfa == 070) memcpy (cfa_pc,"\003\004\005",3); /* CMY */
+ if (cfa == 072) memcpy (cfa_pc,"\005\003\004\001",4); /* GMCY */
+ goto guess_cfa_pc;
+ case 33424:
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_kodak_ifd (base);
+ break;
+ case 33434: /* ExposureTime */
+ shutter = getreal(type);
+ break;
+ case 33437: /* FNumber */
+ aperture = getreal(type);
+ break;
+ case 34306: /* Leaf white balance */
+ FORC4 cam_mul[c ^ 1] = 4096.0 / get2();
+ break;
+ case 34307: /* Leaf CatchLight color matrix */
+ fread (software, 1, 7, ifp);
+ if (strncmp(software,"MATRIX",6)) break;
+ colors = 4;
+ for (raw_color = i=0; i < 3; i++) {
+ FORC4 fscanf (ifp, "%f", &rgb_cam[i][c^1]);
+ if (!use_camera_wb) continue;
+ num = 0;
+ FORC4 num += rgb_cam[i][c];
+ FORC4 rgb_cam[i][c] /= num;
+ }
+ break;
+ case 34310: /* Leaf metadata */
+ parse_mos (ftell(ifp));
+ case 34303:
+ strcpy (make, "Leaf");
+ break;
+ case 34665: /* EXIF tag */
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_exif (base);
+ break;
+ case 34853: /* GPSInfo tag */
+ fseek (ifp, get4()+base, SEEK_SET);
+ parse_gps (base);
+ break;
+ case 34675: /* InterColorProfile */
+ case 50831: /* AsShotICCProfile */
+ profile_offset = ftell(ifp);
+ profile_length = len;
+ break;
+ case 37122: /* CompressedBitsPerPixel */
+ kodak_cbpp = get4();
+ break;
+ case 37386: /* FocalLength */
+ focal_len = getreal(type);
+ break;
+ case 37393: /* ImageNumber */
+ shot_order = getint(type);
+ break;
+ case 37400: /* old Kodak KDC tag */
+ for (raw_color = i=0; i < 3; i++) {
+ getreal(type);
+ FORC3 rgb_cam[i][c] = getreal(type);
+ }
+ break;
+ case 46275: /* Imacon tags */
+ strcpy (make, "Imacon");
+ data_offset = ftell(ifp);
+ ima_len = len;
+ break;
+ case 46279:
+ if (!ima_len) break;
+ fseek (ifp, 78, SEEK_CUR);
+ raw_width = get4();
+ raw_height = get4();
+ left_margin = get4() & 7;
+ width = raw_width - left_margin - (get4() & 7);
+ top_margin = get4() & 7;
+ height = raw_height - top_margin - (get4() & 7);
+ if (raw_width == 7262) {
+ height = 5444;
+ width = 7244;
+ left_margin = 7;
+ }
+ fseek (ifp, 52, SEEK_CUR);
+ FORC3 cam_mul[c] = getreal(11);
+ fseek (ifp, 114, SEEK_CUR);
+ flip = (get2() >> 7) * 90;
+ if (width * height * 6 == ima_len) {
+ if (flip % 180 == 90) SWAP(width,height);
+ filters = flip = 0;
+ }
+ sprintf (model, "Ixpress %d-Mp", height*width/1000000);
+ load_raw = &CLASS imacon_full_load_raw;
+ if (filters) {
+ if (left_margin & 1) filters = 0x61616161;
+ load_raw = &CLASS unpacked_load_raw;
+ }
+ maximum = 0xffff;
+ break;
+ case 50454: /* Sinar tag */
+ case 50455:
+ if (!(cbuf = (char *) malloc(len))) break;
+ fread (cbuf, 1, len, ifp);
+ for (cp = cbuf-1; cp && cp < cbuf+len; cp = strchr(cp,'\n'))
+ if (!strncmp (++cp,"Neutral ",8))
+ {
+ sscanf (cp+8, "%f %f %f", cam_mul, cam_mul+1, cam_mul+2);
+ }
+ free (cbuf);
+ break;
+ case 50458:
+ if (!make[0]) strcpy (make, "Hasselblad");
+ break;
+ case 50459: /* Hasselblad tag */
+ i = order;
+ j = ftell(ifp);
+ c = tiff_nifds;
+ order = get2();
+ fseek (ifp, j+(get2(),get4()), SEEK_SET);
+ parse_tiff_ifd (j);
+ maximum = 0xffff;
+ tiff_nifds = c;
+ order = i;
+ break;
+ case 50706: /* DNGVersion */
+ FORC4 dng_version = (dng_version << 8) + fgetc(ifp);
+ if (!make[0]) strcpy (make, "DNG");
+ is_raw = 1;
+ break;
+ case 50710: /* CFAPlaneColor */
+ if (len > 4) len = 4;
+ colors = len;
+ fread (cfa_pc, 1, colors, ifp);
+guess_cfa_pc:
+ FORCC tab[cfa_pc[c]] = c;
+ cdesc[c] = 0;
+ for (i=16; i--; )
+ filters = filters << 2 | tab[cfa_pat[i % plen]];
+ break;
+ case 50711: /* CFALayout */
+ if (get2() == 2) {
+ fuji_width = 1;
+ filters = 0x49494949;
+ }
+ break;
+ case 291:
+ case 50712: /* LinearizationTable */
+ linear_table (len);
+ break;
+ case 50714: /* BlackLevel */
+ case 50715: /* BlackLevelDeltaH */
+ case 50716: /* BlackLevelDeltaV */
+ for (dblack=i=0; i < len; i++)
+ dblack += getreal(type);
+ black += dblack/len + 0.5;
+ break;
+ case 50717: /* WhiteLevel */
+ maximum = getint(type);
+ break;
+ case 50718: /* DefaultScale */
+ pixel_aspect = getreal(type);
+ pixel_aspect /= getreal(type);
+ break;
+ case 50721: /* ColorMatrix1 */
+ case 50722: /* ColorMatrix2 */
+ FORCC for (j=0; j < 3; j++)
+ cm[c][j] = getreal(type);
+ use_cm = 1;
+ break;
+ case 50723: /* CameraCalibration1 */
+ case 50724: /* CameraCalibration2 */
+ for (i=0; i < colors; i++)
+ FORCC cc[i][c] = getreal(type);
+ case 50727: /* AnalogBalance */
+ FORCC ab[c] = getreal(type);
+ break;
+ case 50728: /* AsShotNeutral */
+ FORCC asn[c] = getreal(type);
+ break;
+ case 50729: /* AsShotWhiteXY */
+ xyz[0] = getreal(type);
+ xyz[1] = getreal(type);
+ xyz[2] = 1 - xyz[0] - xyz[1];
+ FORC3 xyz[c] /= d65_white[c];
+ break;
+ case 50740: /* DNGPrivateData */
+ if (dng_version) break;
+ parse_minolta (j = get4()+base);
+ fseek (ifp, j, SEEK_SET);
+ parse_tiff_ifd (base);
+ break;
+ case 50752:
+ read_shorts (cr2_slice, 3);
+ break;
+ case 50829: /* ActiveArea */
+ top_margin = getint(type);
+ left_margin = getint(type);
+ height = getint(type) - top_margin;
+ width = getint(type) - left_margin;
+ break;
+ case 64772: /* Kodak P-series */
+ fseek (ifp, 16, SEEK_CUR);
+ data_offset = get4();
+ fseek (ifp, 28, SEEK_CUR);
+ data_offset += get4();
+ load_raw = &CLASS packed_12_load_raw;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ if (sony_length && (buf = (unsigned *) malloc(sony_length))) {
+ fseek (ifp, sony_offset, SEEK_SET);
+ fread (buf, sony_length, 1, ifp);
+ sony_decrypt (buf, sony_length/4, 1, sony_key);
+#ifndef LIBRAW_LIBRARY_BUILD
+ sfp = ifp;
+ if ((ifp = tmpfile())) {
+ fwrite (buf, sony_length, 1, ifp);
+ fseek (ifp, 0, SEEK_SET);
+ parse_tiff_ifd (-sony_offset);
+ fclose (ifp);
+ }
+ ifp = sfp;
+#else
+ if( !ifp->tempbuffer_open(buf,sony_length))
+ {
+ parse_tiff_ifd(-sony_offset);
+ ifp->tempbuffer_close();
+ }
+#endif
+ free (buf);
+ }
+ for (i=0; i < colors; i++)
+ FORCC cc[i][c] *= ab[i];
+ if (use_cm) {
+ FORCC for (i=0; i < 3; i++)
+ for (cam_xyz[c][i]=j=0; j < colors; j++)
+ cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i];
+ cam_xyz_coeff (cam_xyz);
+ }
+ if (asn[0]) {
+ cam_mul[3] = 0;
+ FORCC cam_mul[c] = 1 / asn[c];
+ }
+ if (!use_cm)
+ {
+ FORCC pre_mul[c] /= cc[c][c];
+ }
+
+ return 0;
+}
+
+void CLASS parse_tiff (int base)
+{
+ int doff, max_samp=0, raw=-1, thm=-1, i;
+ struct jhead jh;
+
+ fseek (ifp, base, SEEK_SET);
+ order = get2();
+ if (order != 0x4949 && order != 0x4d4d) return;
+ get2();
+ memset (tiff_ifd, 0, sizeof tiff_ifd);
+ tiff_nifds = 0;
+ while ((doff = get4())) {
+ fseek (ifp, doff+base, SEEK_SET);
+ if (parse_tiff_ifd (base)) break;
+ }
+ thumb_misc = 16;
+ if (thumb_offset) {
+ fseek (ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ thumb_misc = jh.bits;
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+ for (i=0; i < tiff_nifds; i++) {
+ if (max_samp < tiff_ifd[i].samples)
+ max_samp = tiff_ifd[i].samples;
+ if (max_samp > 3) max_samp = 3;
+ if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) &&
+ tiff_ifd[i].t_width*tiff_ifd[i].t_height > raw_width*raw_height) {
+ raw_width = tiff_ifd[i].t_width;
+ raw_height = tiff_ifd[i].t_height;
+ tiff_bps = tiff_ifd[i].bps;
+ tiff_compress = tiff_ifd[i].comp;
+ data_offset = tiff_ifd[i].offset;
+ tiff_flip = tiff_ifd[i].t_flip;
+ tiff_samples = tiff_ifd[i].samples;
+ raw = i;
+ }
+ }
+ fuji_width *= (raw_width+1)/2;
+ if (tiff_ifd[0].t_flip) tiff_flip = tiff_ifd[0].t_flip;
+ if (raw >= 0 && !load_raw)
+ switch (tiff_compress) {
+ case 0: case 1:
+ switch (tiff_bps) {
+ case 8: load_raw = &CLASS eight_bit_load_raw; break;
+ case 12: load_raw = &CLASS packed_12_load_raw;
+ if (tiff_ifd[raw].phint == 2)
+ load_flags = 6;
+ if (strncmp(make,"PENTAX",6)) break;
+ case 14:
+ case 16: load_raw = &CLASS unpacked_load_raw; break;
+ }
+ if (tiff_ifd[raw].bytes*5 == raw_width*raw_height*8)
+ load_raw = &CLASS olympus_e300_load_raw;
+ break;
+ case 6: case 7: case 99:
+ load_raw = &CLASS lossless_jpeg_load_raw; break;
+ case 262:
+ load_raw = &CLASS kodak_262_load_raw; break;
+ case 32767:
+ load_raw = &CLASS sony_arw2_load_raw;
+ if (tiff_ifd[raw].bytes*8 == raw_width*raw_height*tiff_bps)
+ break;
+ raw_height += 8;
+ load_raw = &CLASS sony_arw_load_raw; break;
+ case 32769:
+ load_flags = 8;
+ case 32773:
+ load_raw = &CLASS packed_12_load_raw; break;
+ case 34713:
+ load_raw = &CLASS nikon_compressed_load_raw; break;
+ case 65535:
+ load_raw = &CLASS pentax_k10_load_raw; break;
+ case 65000:
+ switch (tiff_ifd[raw].phint) {
+ case 2: load_raw = &CLASS kodak_rgb_load_raw; filters = 0; break;
+ case 6: load_raw = &CLASS kodak_ycbcr_load_raw; filters = 0; break;
+ case 32803: load_raw = &CLASS kodak_65000_load_raw;
+ }
+ case 32867: break;
+ default: is_raw = 0;
+ }
+ if (!dng_version && tiff_samples == 3)
+ if (tiff_ifd[raw].bytes && tiff_bps != 14 && tiff_bps != 2048)
+ is_raw = 0;
+ if (!dng_version && tiff_bps == 8 && tiff_compress == 1 &&
+ tiff_ifd[raw].phint == 1) is_raw = 0;
+ if (tiff_bps == 8 && tiff_samples == 4) is_raw = 0;
+ for (i=0; i < tiff_nifds; i++)
+ if (i != raw && tiff_ifd[i].samples == max_samp &&
+ tiff_ifd[i].t_width * tiff_ifd[i].t_height / SQR(tiff_ifd[i].bps+1) >
+ thumb_width * thumb_height / SQR(thumb_misc+1)) {
+ thumb_width = tiff_ifd[i].t_width;
+ thumb_height = tiff_ifd[i].t_height;
+ thumb_offset = tiff_ifd[i].offset;
+ thumb_length = tiff_ifd[i].bytes;
+ thumb_misc = tiff_ifd[i].bps;
+ thm = i;
+ }
+ if (thm >= 0) {
+ thumb_misc |= tiff_ifd[thm].samples << 5;
+ switch (tiff_ifd[thm].comp) {
+ case 0:
+ write_thumb = &CLASS layer_thumb;
+ break;
+ case 1:
+ if (tiff_ifd[thm].bps > 8)
+ thumb_load_raw = &CLASS kodak_thumb_load_raw;
+ else
+ write_thumb = &CLASS ppm_thumb;
+ break;
+ case 65000:
+ thumb_load_raw = tiff_ifd[thm].phint == 6 ?
+ &CLASS kodak_ycbcr_load_raw : &CLASS kodak_rgb_load_raw;
+ }
+ }
+}
+
+void CLASS parse_minolta (int base)
+{
+ int save, tag, len, offset, high=0, wide=0, i, c;
+ short sorder=order;
+
+ fseek (ifp, base, SEEK_SET);
+ if (fgetc(ifp) || fgetc(ifp)-'M' || fgetc(ifp)-'R') return;
+ order = fgetc(ifp) * 0x101;
+ offset = base + get4() + 8;
+ while ((save=ftell(ifp)) < offset) {
+ for (tag=i=0; i < 4; i++)
+ tag = tag << 8 | fgetc(ifp);
+ len = get4();
+ switch (tag) {
+ case 0x505244: /* PRD */
+ fseek (ifp, 8, SEEK_CUR);
+ high = get2();
+ wide = get2();
+ break;
+ case 0x574247: /* WBG */
+ get4();
+ i = strcmp(model,"DiMAGE A200") ? 0:3;
+ FORC4 cam_mul[c ^ (c >> 1) ^ i] = get2();
+ break;
+ case 0x545457: /* TTW */
+ parse_tiff (ftell(ifp));
+ data_offset = offset;
+ }
+ fseek (ifp, save+len+8, SEEK_SET);
+ }
+ raw_height = high;
+ raw_width = wide;
+ order = sorder;
+}
+
+/*
+ Many cameras have a "debug mode" that writes JPEG and raw
+ at the same time. The raw file has no header, so try to
+ to open the matching JPEG file and read its metadata.
+ */
+void CLASS parse_external_jpeg()
+{
+ char *file, *ext, *jname, *jfile, *jext;
+#ifndef LIBRAW_LIBRARY_BUILD
+ FILE *save=ifp;
+#else
+ if(!ifp->fname())
+ {
+ imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+ return;
+ }
+#endif
+
+ ext = strrchr (ifname, '.');
+ file = strrchr (ifname, '/');
+ if (!file) file = strrchr (ifname, '\\');
+#ifndef LIBRAW_LIBRARY_BUILD
+ if (!file) file = ifname-1;
+#else
+ if (!file) file = (char*)ifname-1;
+#endif
+ file++;
+ if (!ext || strlen(ext) != 4 || ext-file != 8) return;
+ jname = (char *) malloc (strlen(ifname) + 1);
+ merror (jname, "parse_external_jpeg()");
+ strcpy (jname, ifname);
+ jfile = file - ifname + jname;
+ jext = ext - ifname + jname;
+ if (strcasecmp (ext, ".jpg")) {
+ strcpy (jext, isupper(ext[1]) ? ".JPG":".jpg");
+ if (isdigit(*file)) {
+ memcpy (jfile, file+4, 4);
+ memcpy (jfile+4, file, 4);
+ }
+ } else
+ while (isdigit(*--jext)) {
+ if (*jext != '9') {
+ (*jext)++;
+ break;
+ }
+ *jext = '0';
+ }
+#ifndef LIBRAW_LIBRARY_BUILD
+ if (strcmp (jname, ifname)) {
+ if ((ifp = fopen (jname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr,_("Reading metadata from %s ...\n"), jname);
+#endif
+ parse_tiff (12);
+ thumb_offset = 0;
+ is_raw = 1;
+ fclose (ifp);
+ }
+ }
+#else
+ if (strcmp (jname, ifname))
+ {
+ if(!ifp->subfile_open(jname))
+ {
+ parse_tiff (12);
+ thumb_offset = 0;
+ is_raw = 1;
+ ifp->subfile_close();
+ }
+ else
+ imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+ }
+#endif
+ if (!timestamp)
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ;
+#endif
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("Failed to read metadata from %s\n"), jname);
+#endif
+ }
+ free (jname);
+#ifndef LIBRAW_LIBRARY_BUILD
+ ifp = save;
+#endif
+}
+
+/*
+ CIFF block 0x1030 contains an 8x8 white sample.
+ Load this into white[][] for use in scale_colors().
+ */
+void CLASS ciff_block_1030()
+{
+ static const ushort key[] = { 0x410, 0x45f3 };
+ int i, bpp, row, col, vbits=0;
+ unsigned long bitbuf=0;
+
+ if ((get2(),get4()) != 0x80008 || !get4()) return;
+ bpp = get2();
+ if (bpp != 10 && bpp != 12) return;
+ for (i=row=0; row < 8; row++)
+ for (col=0; col < 8; col++) {
+ if (vbits < bpp) {
+ bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
+ vbits += 16;
+ }
+ white[row][col] =
+ bitbuf << (LONG_BIT - vbits) >> (LONG_BIT - bpp);
+ vbits -= bpp;
+ }
+}
+
+/*
+ Parse a CIFF file, better known as Canon CRW format.
+ */
+void CLASS parse_ciff (int offset, int length)
+{
+ int tboff, nrecs, c, type, len, save, wbi=-1;
+ ushort key[] = { 0x410, 0x45f3 };
+
+ fseek (ifp, offset+length-4, SEEK_SET);
+ tboff = get4() + offset;
+ fseek (ifp, tboff, SEEK_SET);
+ nrecs = get2();
+ if (nrecs > 100) return;
+ while (nrecs--) {
+ type = get2();
+ len = get4();
+ save = ftell(ifp) + 4;
+ fseek (ifp, offset+get4(), SEEK_SET);
+ if ((((type >> 8) + 8) | 8) == 0x38)
+ parse_ciff (ftell(ifp), len); /* Parse a sub-table */
+
+ if (type == 0x0810)
+ fread (artist, 64, 1, ifp);
+ if (type == 0x080a) {
+ fread (make, 64, 1, ifp);
+ fseek (ifp, strlen(make) - 63, SEEK_CUR);
+ fread (model, 64, 1, ifp);
+ }
+ if (type == 0x1810) {
+ fseek (ifp, 12, SEEK_CUR);
+ flip = get4();
+ }
+ if (type == 0x1835) /* Get the decoder table */
+ tiff_compress = get4();
+ if (type == 0x2007) {
+ thumb_offset = ftell(ifp);
+ thumb_length = len;
+ }
+ if (type == 0x1818) {
+ shutter = pow (2.0f, -int_to_float((get4(),get4())));
+ aperture = pow (2.0f, int_to_float(get4())/2);
+ }
+ if (type == 0x102a) {
+ iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
+ aperture = pow (2.0, (get2(),(short)get2())/64.0);
+ shutter = pow (2.0,-((short)get2())/32.0);
+ wbi = (get2(),get2());
+ if (wbi > 17) wbi = 0;
+ fseek (ifp, 32, SEEK_CUR);
+ if (shutter > 1e6) shutter = get2()/10.0;
+ }
+ if (type == 0x102c) {
+ if (get2() > 512) { /* Pro90, G1 */
+ fseek (ifp, 118, SEEK_CUR);
+ FORC4 cam_mul[c ^ 2] = get2();
+ } else { /* G2, S30, S40 */
+ fseek (ifp, 98, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2();
+ }
+ }
+ if (type == 0x0032) {
+ if (len == 768) { /* EOS D30 */
+ fseek (ifp, 72, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1)] = 1024.0 / get2();
+ if (!wbi) cam_mul[0] = -1; /* use my auto white balance */
+ } else if (!cam_mul[0]) {
+ if (get2() == key[0]) /* Pro1, G6, S60, S70 */
+ c = (strstr(model,"Pro1") ?
+ "012346000000000000":"01345:000000006008")[wbi]-'0'+ 2;
+ else { /* G3, G5, S45, S50 */
+ c = "023457000000006000"[wbi]-'0';
+ key[0] = key[1] = 0;
+ }
+ fseek (ifp, 78 + c*8, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get2() ^ key[c & 1];
+ if (!wbi) cam_mul[0] = -1;
+ }
+ }
+ if (type == 0x10a9) { /* D60, 10D, 300D, and clones */
+ if (len > 66) wbi = "0134567028"[wbi]-'0';
+ fseek (ifp, 2 + wbi*8, SEEK_CUR);
+ FORC4 cam_mul[c ^ (c >> 1)] = get2();
+ }
+ if (type == 0x1030 && (0x18040 >> wbi & 1))
+ ciff_block_1030(); /* all that don't have 0x10a9 */
+ if (type == 0x1031) {
+ raw_width = (get2(),get2());
+ raw_height = get2();
+ }
+ if (type == 0x5029) {
+ focal_len = len >> 16;
+ if ((len & 0xffff) == 2) focal_len /= 32;
+ }
+ if (type == 0x5813) flash_used = int_to_float(len);
+ if (type == 0x5814) canon_ev = int_to_float(len);
+ if (type == 0x5817) shot_order = len;
+ if (type == 0x5834) unique_id = len;
+ if (type == 0x580e) timestamp = len;
+ if (type == 0x180e) timestamp = get4();
+#ifdef LOCALTIME
+ if ((type | 0x4000) == 0x580e)
+ timestamp = mktime (gmtime (&timestamp));
+#endif
+ fseek (ifp, save, SEEK_SET);
+ }
+}
+
+void CLASS parse_rollei()
+{
+ char line[128], *val;
+ struct tm t;
+
+ fseek (ifp, 0, SEEK_SET);
+ memset (&t, 0, sizeof t);
+ do {
+ fgets (line, 128, ifp);
+ if ((val = strchr(line,'=')))
+ *val++ = 0;
+ else
+ val = line + strlen(line);
+ if (!strcmp(line,"DAT"))
+ sscanf (val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
+ if (!strcmp(line,"TIM"))
+ sscanf (val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
+ if (!strcmp(line,"HDR"))
+ thumb_offset = atoi(val);
+ if (!strcmp(line,"X "))
+ raw_width = atoi(val);
+ if (!strcmp(line,"Y "))
+ raw_height = atoi(val);
+ if (!strcmp(line,"TX "))
+ thumb_width = atoi(val);
+ if (!strcmp(line,"TY "))
+ thumb_height = atoi(val);
+ } while (strncmp(line,"EOHD",4));
+ data_offset = thumb_offset + thumb_width * thumb_height * 2;
+ t.tm_year -= 1900;
+ t.tm_mon -= 1;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ strcpy (make, "Rollei");
+ strcpy (model,"d530flex");
+ write_thumb = &CLASS rollei_thumb;
+}
+
+void CLASS parse_sinar_ia()
+{
+ int entries, off;
+ char str[8], *cp;
+
+ order = 0x4949;
+ fseek (ifp, 4, SEEK_SET);
+ entries = get4();
+ fseek (ifp, get4(), SEEK_SET);
+ while (entries--) {
+ off = get4(); get4();
+ fread (str, 8, 1, ifp);
+ if (!strcmp(str,"META")) meta_offset = off;
+ if (!strcmp(str,"THUMB")) thumb_offset = off;
+ if (!strcmp(str,"RAW0")) data_offset = off;
+ }
+ fseek (ifp, meta_offset+20, SEEK_SET);
+ fread (make, 64, 1, ifp);
+ make[63] = 0;
+ if ((cp = strchr(make,' '))) {
+ strcpy (model, cp+1);
+ *cp = 0;
+ }
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &CLASS unpacked_load_raw;
+ thumb_width = (get4(),get2());
+ thumb_height = get2();
+ write_thumb = &CLASS ppm_thumb;
+ maximum = 0x3fff;
+}
+
+void CLASS parse_phase_one (int base)
+{
+ unsigned entries, tag, type, len, data, save, i, c;
+ float romm_cam[3][3];
+ char *cp;
+
+ memset (&ph1, 0, sizeof ph1);
+ fseek (ifp, base, SEEK_SET);
+ order = get4() & 0xffff;
+ if (get4() >> 8 != 0x526177) return; /* "Raw" */
+ fseek (ifp, get4()+base, SEEK_SET);
+ entries = get4();
+ get4();
+ while (entries--) {
+ tag = get4();
+ type = get4();
+ len = get4();
+ data = get4();
+ save = ftell(ifp);
+ fseek (ifp, base+data, SEEK_SET);
+ switch (tag) {
+ case 0x100: flip = "0653"[data & 3]-'0'; break;
+ case 0x106:
+ for (i=0; i < 9; i++)
+ romm_cam[0][i] = getreal(11);
+ romm_coeff (romm_cam);
+ break;
+ case 0x107:
+ FORC3 cam_mul[c] = getreal(11);
+ break;
+ case 0x108: raw_width = data; break;
+ case 0x109: raw_height = data; break;
+ case 0x10a: left_margin = data; break;
+ case 0x10b: top_margin = data; break;
+ case 0x10c: width = data; break;
+ case 0x10d: height = data; break;
+ case 0x10e: ph1.format = data; break;
+ case 0x10f: data_offset = data+base; break;
+ case 0x110: meta_offset = data+base;
+ meta_length = len; break;
+ case 0x112: ph1.key_off = save - 4; break;
+ case 0x210: ph1.tag_210 = int_to_float(data); break;
+ case 0x21a: ph1.tag_21a = data; break;
+ case 0x21c: strip_offset = data+base; break;
+ case 0x21d: ph1.t_black = data; break;
+ case 0x222: ph1.split_col = data - left_margin; break;
+ case 0x223: ph1.black_off = data+base; break;
+ case 0x301:
+ model[63] = 0;
+ fread (model, 1, 63, ifp);
+ if ((cp = strstr(model," camera"))) *cp = 0;
+ }
+ fseek (ifp, save, SEEK_SET);
+ }
+ load_raw = ph1.format < 3 ?
+ &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c;
+ maximum = 0xffff;
+ strcpy (make, "Phase One");
+ if (model[0]) return;
+ switch (raw_height) {
+ case 2060: strcpy (model,"LightPhase"); break;
+ case 2682: strcpy (model,"H 10"); break;
+ case 4128: strcpy (model,"H 20"); break;
+ case 5488: strcpy (model,"H 25"); break;
+ }
+}
+
+void CLASS parse_fuji (int offset)
+{
+ unsigned entries, tag, len, save, c;
+
+ fseek (ifp, offset, SEEK_SET);
+ entries = get4();
+ if (entries > 255) return;
+ while (entries--) {
+ tag = get2();
+ len = get2();
+ save = ftell(ifp);
+ if (tag == 0x100) {
+ raw_height = get2();
+ raw_width = get2();
+ } else if (tag == 0x121) {
+ height = get2();
+ if ((width = get2()) == 4284) width += 3;
+ } else if (tag == 0x130)
+ fuji_layout = fgetc(ifp) >> 7;
+ if (tag == 0x2ff0)
+ {
+ FORC4 cam_mul[c ^ 1] = get2();
+ }
+ fseek (ifp, save+len, SEEK_SET);
+ }
+ height <<= fuji_layout;
+ width >>= fuji_layout;
+}
+
+int CLASS parse_jpeg (int offset)
+{
+ int len, save, hlen, mark;
+
+ fseek (ifp, offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) return 0;
+
+ while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) {
+ order = 0x4d4d;
+ len = get2() - 2;
+ save = ftell(ifp);
+ if (mark == 0xc0 || mark == 0xc3) {
+ fgetc(ifp);
+ raw_height = get2();
+ raw_width = get2();
+ }
+ order = get2();
+ hlen = get4();
+ if (get4() == 0x48454150) /* "HEAP" */
+ parse_ciff (save+hlen, len-hlen);
+ parse_tiff (save+6);
+ fseek (ifp, save+len, SEEK_SET);
+ }
+ return 1;
+}
+
+void CLASS parse_riff()
+{
+ unsigned i, size, end;
+ char tag[4], date[64], month[64];
+ static const char mon[12][4] =
+ { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
+ struct tm t;
+
+ order = 0x4949;
+ fread (tag, 4, 1, ifp);
+ size = get4();
+ end = ftell(ifp) + size;
+ if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) {
+ get4();
+ while (ftell(ifp)+7 < end)
+ parse_riff();
+ } else if (!memcmp(tag,"nctg",4)) {
+ while (ftell(ifp)+7 < end) {
+ i = get2();
+ size = get2();
+ if ((i+1) >> 1 == 10 && size == 20)
+ get_timestamp(0);
+ else fseek (ifp, size, SEEK_CUR);
+ }
+ } else if (!memcmp(tag,"IDIT",4) && size < 64) {
+ fread (date, 64, 1, ifp);
+ date[size] = 0;
+ memset (&t, 0, sizeof t);
+ if (sscanf (date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday,
+ &t.tm_hour, &t.tm_min, &t.tm_sec, &t.tm_year) == 6) {
+ for (i=0; i < 12 && strcasecmp(mon[i],month); i++);
+ t.tm_mon = i;
+ t.tm_year -= 1900;
+ if (mktime(&t) > 0)
+ timestamp = mktime(&t);
+ }
+ } else
+ fseek (ifp, size, SEEK_CUR);
+}
+
+void CLASS parse_smal (int offset, int fsize)
+{
+ int ver;
+
+ fseek (ifp, offset+2, SEEK_SET);
+ order = 0x4949;
+ ver = fgetc(ifp);
+ if (ver == 6)
+ fseek (ifp, 5, SEEK_CUR);
+ if (get4() != fsize) return;
+ if (ver > 6) data_offset = get4();
+ raw_height = height = get2();
+ raw_width = width = get2();
+ strcpy (make, "SMaL");
+ sprintf (model, "v%d %dx%d", ver, width, height);
+ if (ver == 6) load_raw = &CLASS smal_v6_load_raw;
+ if (ver == 9) load_raw = &CLASS smal_v9_load_raw;
+}
+
+void CLASS parse_cine()
+{
+ unsigned off_head, off_setup, off_image, i;
+
+ order = 0x4949;
+ fseek (ifp, 4, SEEK_SET);
+ is_raw = get2() == 2;
+ fseek (ifp, 14, SEEK_CUR);
+ is_raw *= get4();
+ off_head = get4();
+ off_setup = get4();
+ off_image = get4();
+ timestamp = get4();
+ if ((i = get4())) timestamp = i;
+ fseek (ifp, off_head+4, SEEK_SET);
+ raw_width = get4();
+ raw_height = get4();
+ switch (get2(),get2()) {
+ case 8: load_raw = &CLASS eight_bit_load_raw; break;
+ case 16: load_raw = &CLASS unpacked_load_raw;
+ }
+ fseek (ifp, off_setup+792, SEEK_SET);
+ strcpy (make, "CINE");
+ sprintf (model, "%d", get4());
+ fseek (ifp, 12, SEEK_CUR);
+ switch ((i=get4()) & 0xffffff) {
+ case 3: filters = 0x94949494; break;
+ case 4: filters = 0x49494949; break;
+ default: is_raw = 0;
+ }
+ fseek (ifp, 72, SEEK_CUR);
+ switch ((get4()+3600) % 360) {
+ case 270: flip = 4; break;
+ case 180: flip = 1; break;
+ case 90: flip = 7; break;
+ case 0: flip = 2;
+ }
+ cam_mul[0] = getreal(11);
+ cam_mul[2] = getreal(11);
+ maximum = ~(-1 << get4());
+ fseek (ifp, 668, SEEK_CUR);
+ shutter = get4()/1000000000.0;
+ fseek (ifp, off_image, SEEK_SET);
+ if (shot_select < is_raw)
+ fseek (ifp, shot_select*8, SEEK_CUR);
+ data_offset = (INT64) get4() + 8;
+ data_offset += (INT64) get4() << 32;
+}
+#line 6467 "dcraw/dcraw.c"
+#ifdef LIBRAW_LIBRARY_BUILD
+void CLASS adobe_coeff (const char *p_make, const char *p_model)
+#else
+void CLASS adobe_coeff (char *p_make, char *p_model)
+#endif
+{
+ static const struct {
+ const char *prefix;
+ short t_black, t_maximum, trans[12];
+ } table[] = {
+ { "Apple QuickTake", 0, 0, /* DJC */
+ { 17576,-3191,-3318,5210,6733,-1942,9031,1280,-124 } },
+ { "Canon EOS D2000", 0, 0,
+ { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+ { "Canon EOS D6000", 0, 0,
+ { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+ { "Canon EOS D30", 0, 0,
+ { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
+ { "Canon EOS D60", 0, 0xfa0,
+ { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
+ { "Canon EOS 5D Mark II", 0, 0x3cf0,
+ { 4716,603,-830,-7798,15474,2480,-1496,1937,6651 } },
+ { "Canon EOS 5D", 0, 0xe6c,
+ { 6347,-479,-972,-8297,15954,2480,-1968,2131,7649 } },
+ { "Canon EOS 10D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 20Da", 0, 0,
+ { 14155,-5065,-1382,-6550,14633,2039,-1623,1824,6561 } },
+ { "Canon EOS 20D", 0, 0xfff,
+ { 6599,-537,-891,-8071,15783,2424,-1983,2234,7462 } },
+ { "Canon EOS 30D", 0, 0,
+ { 6257,-303,-1000,-7880,15621,2396,-1714,1904,7046 } },
+ { "Canon EOS 40D", 0, 0x3f60,
+ { 6071,-747,-856,-7653,15365,2441,-2025,2553,7315 } },
+ { "Canon EOS 50D", 0, 0x3d93,
+ { 4920,616,-593,-6493,13964,2784,-1774,3178,7005 } },
+ { "Canon EOS 300D", 0, 0xfa0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon EOS 350D", 0, 0xfff,
+ { 6018,-617,-965,-8645,15881,2975,-1530,1719,7642 } },
+ { "Canon EOS 400D", 0, 0xe8e,
+ { 7054,-1501,-990,-8156,15544,2812,-1278,1414,7796 } },
+ { "Canon EOS 450D", 0, 0x390d,
+ { 5784,-262,-821,-7539,15064,2672,-1982,2681,7427 } },
+ { "Canon EOS 1000D", 0, 0xe43,
+ { 6771,-1139,-977,-7818,15123,2928,-1244,1437,7533 } },
+ { "Canon EOS-1Ds Mark III", 0, 0x3bb0,
+ { 5859,-211,-930,-8255,16017,2353,-1732,1887,7448 } },
+ { "Canon EOS-1Ds Mark II", 0, 0xe80,
+ { 6517,-602,-867,-8180,15926,2378,-1618,1771,7633 } },
+ { "Canon EOS-1D Mark II N", 0, 0xe80,
+ { 6240,-466,-822,-8180,15825,2500,-1801,1938,8042 } },
+ { "Canon EOS-1D Mark III", 0, 0x3bb0,
+ { 6291,-540,-976,-8350,16145,2311,-1714,1858,7326 } },
+ { "Canon EOS-1D Mark II", 0, 0xe80,
+ { 6264,-582,-724,-8312,15948,2504,-1744,1919,8664 } },
+ { "Canon EOS-1DS", 0, 0xe20,
+ { 4374,3631,-1743,-7520,15212,2472,-2892,3632,8161 } },
+ { "Canon EOS-1D", 0, 0xe20,
+ { 6806,-179,-1020,-8097,16415,1687,-3267,4236,7690 } },
+ { "Canon EOS", 0, 0,
+ { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
+ { "Canon PowerShot A50", 0, 0,
+ { -5300,9846,1776,3436,684,3939,-5540,9879,6200,-1404,11175,217 } },
+ { "Canon PowerShot A5", 0, 0,
+ { -4801,9475,1952,2926,1611,4094,-5259,10164,5947,-1554,10883,547 } },
+ { "Canon PowerShot G10", 0, 0,
+ { 11093,-3906,-1028,-5047,12492,2879,-1003,1750,5561 } },
+ { "Canon PowerShot G1", 0, 0,
+ { -4778,9467,2172,4743,-1141,4344,-5146,9908,6077,-1566,11051,557 } },
+ { "Canon PowerShot G2", 0, 0,
+ { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
+ { "Canon PowerShot G3", 0, 0,
+ { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
+ { "Canon PowerShot G5", 0, 0,
+ { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
+ { "Canon PowerShot G6", 0, 0,
+ { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
+ { "Canon PowerShot G9", 0, 0,
+ { 7368,-2141,-598,-5621,13254,2625,-1418,1696,5743 } },
+ { "Canon PowerShot Pro1", 0, 0,
+ { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
+ { "Canon PowerShot Pro70", 34, 0,
+ { -4155,9818,1529,3939,-25,4522,-5521,9870,6610,-2238,10873,1342 } },
+ { "Canon PowerShot Pro90", 0, 0,
+ { -4963,9896,2235,4642,-987,4294,-5162,10011,5859,-1770,11230,577 } },
+ { "Canon PowerShot S30", 0, 0,
+ { 10566,-3652,-1129,-6552,14662,2006,-2197,2581,7670 } },
+ { "Canon PowerShot S40", 0, 0,
+ { 8510,-2487,-940,-6869,14231,2900,-2318,2829,9013 } },
+ { "Canon PowerShot S45", 0, 0,
+ { 8163,-2333,-955,-6682,14174,2751,-2077,2597,8041 } },
+ { "Canon PowerShot S50", 0, 0,
+ { 8882,-2571,-863,-6348,14234,2288,-1516,2172,6569 } },
+ { "Canon PowerShot S60", 0, 0,
+ { 8795,-2482,-797,-7804,15403,2573,-1422,1996,7082 } },
+ { "Canon PowerShot S70", 0, 0,
+ { 9976,-3810,-832,-7115,14463,2906,-901,989,7889 } },
+ { "Canon PowerShot A610", 0, 0, /* DJC */
+ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } },
+ { "Canon PowerShot A620", 0, 0, /* DJC */
+ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } },
+ { "Canon PowerShot A630", 0, 0, /* DJC */
+ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } },
+ { "Canon PowerShot A640", 0, 0, /* DJC */
+ { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } },
+ { "Canon PowerShot A650", 0, 0, /* DJC */
+ { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } },
+ { "Canon PowerShot A720", 0, 0, /* DJC */
+ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } },
+ { "Canon PowerShot S3 IS", 0, 0, /* DJC */
+ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } },
+ { "CINE 650", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { "CINE 660", 0, 0,
+ { 3390,480,-500,-800,3610,340,-550,2336,1192 } },
+ { "CINE", 0, 0,
+ { 20183,-4295,-423,-3940,15330,3985,-280,4870,9800 } },
+ { "Contax N Digital", 0, 0xf1e,
+ { 7777,1285,-1053,-9280,16543,2916,-3677,5679,7060 } },
+ { "EPSON R-D1", 0, 0,
+ { 6827,-1878,-732,-8429,16012,2564,-704,592,7145 } },
+ { "FUJIFILM FinePix E550", 0, 0,
+ { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+ { "FUJIFILM FinePix E900", 0, 0,
+ { 9183,-2526,-1078,-7461,15071,2574,-2022,2440,8639 } },
+ { "FUJIFILM FinePix F8", 0, 0,
+ { 11044,-3888,-1120,-7248,15168,2208,-1531,2277,8069 } },
+ { "FUJIFILM FinePix F7", 0, 0,
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { "FUJIFILM FinePix S100FS", 514, 0,
+ { 11521,-4355,-1065,-6524,13767,3058,-1466,1984,6045 } },
+ { "FUJIFILM FinePix S20Pro", 0, 0,
+ { 10004,-3219,-1201,-7036,15047,2107,-1863,2565,7736 } },
+ { "FUJIFILM FinePix S2Pro", 128, 0,
+ { 12492,-4690,-1402,-7033,15423,1647,-1507,2111,7697 } },
+ { "FUJIFILM FinePix S3Pro", 0, 0,
+ { 11807,-4612,-1294,-8927,16968,1988,-2120,2741,8006 } },
+ { "FUJIFILM FinePix S5Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+ { "FUJIFILM FinePix S5000", 0, 0,
+ { 8754,-2732,-1019,-7204,15069,2276,-1702,2334,6982 } },
+ { "FUJIFILM FinePix S5100", 0, 0x3e00,
+ { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+ { "FUJIFILM FinePix S5500", 0, 0x3e00,
+ { 11940,-4431,-1255,-6766,14428,2542,-993,1165,7421 } },
+ { "FUJIFILM FinePix S5200", 0, 0,
+ { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+ { "FUJIFILM FinePix S5600", 0, 0,
+ { 9636,-2804,-988,-7442,15040,2589,-1803,2311,8621 } },
+ { "FUJIFILM FinePix S6", 0, 0,
+ { 12628,-4887,-1401,-6861,14996,1962,-2198,2782,7091 } },
+ { "FUJIFILM FinePix S7000", 0, 0,
+ { 10190,-3506,-1312,-7153,15051,2238,-2003,2399,7505 } },
+ { "FUJIFILM FinePix S9000", 0, 0,
+ { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+ { "FUJIFILM FinePix S9500", 0, 0,
+ { 10491,-3423,-1145,-7385,15027,2538,-1809,2275,8692 } },
+ { "FUJIFILM FinePix S9100", 0, 0,
+ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+ { "FUJIFILM FinePix S9600", 0, 0,
+ { 12343,-4515,-1285,-7165,14899,2435,-1895,2496,8800 } },
+ { "FUJIFILM IS-1", 0, 0,
+ { 21461,-10807,-1441,-2332,10599,1999,289,875,7703 } },
+ { "FUJIFILM IS Pro", 0, 0,
+ { 12300,-5110,-1304,-9117,17143,1998,-1947,2448,8100 } },
+ { "Imacon Ixpress", 0, 0, /* DJC */
+ { 7025,-1415,-704,-5188,13765,1424,-1248,2742,6038 } },
+ { "KODAK NC2000", 0, 0,
+ { 13891,-6055,-803,-465,9919,642,2121,82,1291 } },
+ { "Kodak DCS315C", 8, 0,
+ { 17523,-4827,-2510,756,8546,-137,6113,1649,2250 } },
+ { "Kodak DCS330C", 8, 0,
+ { 20620,-7572,-2801,-103,10073,-396,3551,-233,2220 } },
+ { "KODAK DCS420", 0, 0,
+ { 10868,-1852,-644,-1537,11083,484,2343,628,2216 } },
+ { "KODAK DCS460", 0, 0,
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { "KODAK EOSDCS1", 0, 0,
+ { 10592,-2206,-967,-1944,11685,230,2206,670,1273 } },
+ { "KODAK EOSDCS3B", 0, 0,
+ { 9898,-2700,-940,-2478,12219,206,1985,634,1031 } },
+ { "Kodak DCS520C", 180, 0,
+ { 24542,-10860,-3401,-1490,11370,-297,2858,-605,3225 } },
+ { "Kodak DCS560C", 188, 0,
+ { 20482,-7172,-3125,-1033,10410,-285,2542,226,3136 } },
+ { "Kodak DCS620C", 180, 0,
+ { 23617,-10175,-3149,-2054,11749,-272,2586,-489,3453 } },
+ { "Kodak DCS620X", 185, 0,
+ { 13095,-6231,154,12221,-21,-2137,895,4602,2258 } },
+ { "Kodak DCS660C", 214, 0,
+ { 18244,-6351,-2739,-791,11193,-521,3711,-129,2802 } },
+ { "Kodak DCS720X", 0, 0,
+ { 11775,-5884,950,9556,1846,-1286,-1019,6221,2728 } },
+ { "Kodak DCS760C", 0, 0,
+ { 16623,-6309,-1411,-4344,13923,323,2285,274,2926 } },
+ { "Kodak DCS Pro SLR", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { "Kodak DCS Pro 14nx", 0, 0,
+ { 5494,2393,-232,-6427,13850,2846,-1876,3997,5445 } },
+ { "Kodak DCS Pro 14", 0, 0,
+ { 7791,3128,-776,-8588,16458,2039,-2455,4006,6198 } },
+ { "Kodak ProBack645", 0, 0,
+ { 16414,-6060,-1470,-3555,13037,473,2545,122,4948 } },
+ { "Kodak ProBack", 0, 0,
+ { 21179,-8316,-2918,-915,11019,-165,3477,-180,4210 } },
+ { "KODAK P712", 0, 0,
+ { 9658,-3314,-823,-5163,12695,2768,-1342,1843,6044 } },
+ { "KODAK P850", 0, 0xf7c,
+ { 10511,-3836,-1102,-6946,14587,2558,-1481,1792,6246 } },
+ { "KODAK P880", 0, 0xfff,
+ { 12805,-4662,-1376,-7480,15267,2360,-1626,2194,7904 } },
+ { "Leaf CMost", 0, 0,
+ { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+ { "Leaf Valeo 6", 0, 0,
+ { 3952,2189,449,-6701,14585,2275,-4536,7349,6536 } },
+ { "Leaf Aptus 54S", 0, 0,
+ { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+ { "Leaf Aptus 65", 0, 0,
+ { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+ { "Leaf Aptus 75", 0, 0,
+ { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } },
+ { "Leaf", 0, 0,
+ { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } },
+ { "Mamiya ZD", 0, 0,
+ { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } },
+ { "Micron 2010", 110, 0, /* DJC */
+ { 16695,-3761,-2151,155,9682,163,3433,951,4904 } },
+ { "Minolta DiMAGE 5", 0, 0xf7d,
+ { 8983,-2942,-963,-6556,14476,2237,-2426,2887,8014 } },
+ { "Minolta DiMAGE 7Hi", 0, 0xf7d,
+ { 11368,-3894,-1242,-6521,14358,2339,-2475,3056,7285 } },
+ { "Minolta DiMAGE 7", 0, 0xf7d,
+ { 9144,-2777,-998,-6676,14556,2281,-2470,3019,7744 } },
+ { "Minolta DiMAGE A1", 0, 0xf8b,
+ { 9274,-2547,-1167,-8220,16323,1943,-2273,2720,8340 } },
+ { "MINOLTA DiMAGE A200", 0, 0,
+ { 8560,-2487,-986,-8112,15535,2771,-1209,1324,7743 } },
+ { "Minolta DiMAGE A2", 0, 0xf8f,
+ { 9097,-2726,-1053,-8073,15506,2762,-966,981,7763 } },
+ { "Minolta DiMAGE Z2", 0, 0, /* DJC */
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+ { "MINOLTA DYNAX 5", 0, 0xffb,
+ { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } },
+ { "MINOLTA DYNAX 7", 0, 0xffb,
+ { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } },
+ { "NIKON D100", 0, 0,
+ { 5902,-933,-782,-8983,16719,2354,-1402,1455,6464 } },
+ { "NIKON D1H", 0, 0,
+ { 7577,-2166,-926,-7454,15592,1934,-2377,2808,8606 } },
+ { "NIKON D1X", 0, 0,
+ { 7702,-2245,-975,-9114,17242,1875,-2679,3055,8521 } },
+ { "NIKON D1", 0, 0, /* multiplied by 2.218750, 1.0, 1.148438 */
+ { 16772,-4726,-2141,-7611,15713,1972,-2846,3494,9521 } },
+ { "NIKON D2H", 0, 0,
+ { 5710,-901,-615,-8594,16617,2024,-2975,4120,6830 } },
+ { "NIKON D2X", 0, 0,
+ { 10231,-2769,-1255,-8301,15900,2552,-797,680,7148 } },
+ { "NIKON D40X", 0, 0,
+ { 8819,-2543,-911,-9025,16928,2151,-1329,1213,8449 } },
+ { "NIKON D40", 0, 0,
+ { 6992,-1668,-806,-8138,15748,2543,-874,850,7897 } },
+ { "NIKON D50", 0, 0,
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { "NIKON D60", 0, 0,
+ { 8736,-2458,-935,-9075,16894,2251,-1354,1242,8263 } },
+ { "NIKON D700", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "NIKON D70", 0, 0,
+ { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } },
+ { "NIKON D80", 0, 0,
+ { 8629,-2410,-883,-9055,16940,2171,-1490,1363,8520 } },
+ { "NIKON D90", 0, 0xf00,
+ { 7309,-1403,-519,-8474,16008,2622,-2434,2826,8064 } },
+ { "NIKON D200", 0, 0xfbc,
+ { 8367,-2248,-763,-8758,16447,2422,-1527,1550,8053 } },
+ { "NIKON D300", 0, 0,
+ { 9030,-1992,-715,-8465,16302,2255,-2689,3217,8069 } },
+ { "NIKON D3", 0, 0,
+ { 8139,-2171,-663,-8747,16541,2295,-1925,2008,8093 } },
+ { "NIKON E950", 0, 0x3dd, /* DJC */
+ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } },
+ { "NIKON E995", 0, 0, /* copied from E5000 */
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E2100", 0, 0, /* copied from Z2, new white balance */
+ { 13142,-4152,-1596,-4655,12374,2282,-1769,2696,6711} },
+ { "NIKON E2500", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */
+ { 11280,-3564,-1370,-4655,12374,2282,-1423,2168,5396 } },
+ { "NIKON E4500", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E5000", 0, 0,
+ { -5547,11762,2189,5814,-558,3342,-4924,9840,5949,688,9083,96 } },
+ { "NIKON E5400", 0, 0,
+ { 9349,-2987,-1001,-7919,15766,2266,-2098,2680,6839 } },
+ { "NIKON E5700", 0, 0,
+ { -5368,11478,2368,5537,-113,3148,-4969,10021,5782,778,9028,211 } },
+ { "NIKON E8400", 0, 0,
+ { 7842,-2320,-992,-8154,15718,2599,-1098,1342,7560 } },
+ { "NIKON E8700", 0, 0,
+ { 8489,-2583,-1036,-8051,15583,2643,-1307,1407,7354 } },
+ { "NIKON E8800", 0, 0,
+ { 7971,-2314,-913,-8451,15762,2894,-1442,1520,7610 } },
+ { "NIKON COOLPIX P6000", 0, 0,
+ { 9698,-3367,-914,-4706,12584,2368,-837,968,5801 } },
+ { "OLYMPUS C5050", 0, 0,
+ { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } },
+ { "OLYMPUS C5060", 0, 0,
+ { 10445,-3362,-1307,-7662,15690,2058,-1135,1176,7602 } },
+ { "OLYMPUS C7070", 0, 0,
+ { 10252,-3531,-1095,-7114,14850,2436,-1451,1723,6365 } },
+ { "OLYMPUS C70", 0, 0,
+ { 10793,-3791,-1146,-7498,15177,2488,-1390,1577,7321 } },
+ { "OLYMPUS C80", 0, 0,
+ { 8606,-2509,-1014,-8238,15714,2703,-942,979,7760 } },
+ { "OLYMPUS E-10", 0, 0xffc0,
+ { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
+ { "OLYMPUS E-1", 0, 0xfff0,
+ { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
+ { "OLYMPUS E-20", 0, 0xffc0,
+ { 13173,-4732,-1499,-5807,14036,1895,-2045,2452,7142 } },
+ { "OLYMPUS E-300", 0, 0,
+ { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
+ { "OLYMPUS E-330", 0, 0,
+ { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
+ { "OLYMPUS E-3", 0, 0xf99,
+ { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
+ { "OLYMPUS E-400", 0, 0xfff0,
+ { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
+ { "OLYMPUS E-410", 0, 0xf6a,
+ { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
+ { "OLYMPUS E-420", 0, 0xfd7,
+ { 8746,-2425,-1095,-7594,15612,2073,-1780,2309,7416 } },
+ { "OLYMPUS E-500", 0, 0,
+ { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
+ { "OLYMPUS E-510", 0, 0xf6a,
+ { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
+ { "OLYMPUS E-520", 0, 0xfd2,
+ { 8344,-2322,-1020,-7596,15635,2048,-1748,2269,7287 } },
+ { "OLYMPUS SP350", 0, 0,
+ { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
+ { "OLYMPUS SP3", 0, 0,
+ { 11766,-4445,-1067,-6901,14421,2707,-1029,1217,7572 } },
+ { "OLYMPUS SP500UZ", 0, 0xfff,
+ { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
+ { "OLYMPUS SP510UZ", 0, 0xffe,
+ { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
+ { "OLYMPUS SP550UZ", 0, 0xffe,
+ { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
+ { "OLYMPUS SP560UZ", 0, 0xff9,
+ { 10915,-3677,-982,-5587,12986,2911,-1168,1968,6223 } },
+ { "OLYMPUS SP570UZ", 0, 0,
+ { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } },
+ { "PENTAX *ist DL2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "PENTAX *ist DL", 0, 0,
+ { 10829,-2838,-1115,-8339,15817,2696,-837,680,11939 } },
+ { "PENTAX *ist DS2", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "PENTAX *ist DS", 0, 0,
+ { 10371,-2333,-1206,-8688,16231,2602,-1230,1116,11282 } },
+ { "PENTAX *ist D", 0, 0,
+ { 9651,-2059,-1189,-8881,16512,2487,-1460,1345,10687 } },
+ { "PENTAX K10D", 0, 0,
+ { 9566,-2863,-803,-7170,15172,2112,-818,803,9705 } },
+ { "PENTAX K1", 0, 0,
+ { 11095,-3157,-1324,-8377,15834,2720,-1108,947,11688 } },
+ { "PENTAX K20D", 0, 0,
+ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } },
+ { "PENTAX K200D", 0, 0,
+ { 9186,-2678,-907,-8693,16517,2260,-1129,1094,8524 } },
+ { "PENTAX K2000", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "PENTAX K-m", 0, 0,
+ { 11057,-3604,-1155,-5152,13046,2329,-282,375,8104 } },
+ { "Panasonic DMC-FZ8", 0, 0xf7f0,
+ { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
+ { "Panasonic DMC-FZ18", 0, 0,
+ { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
+ { "Panasonic DMC-FZ28", 15, 0xfff,
+ { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
+ { "Panasonic DMC-FZ30", 0, 0xf94c,
+ { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
+ { "Panasonic DMC-FZ50", 0, 0xfff0, /* aka "LEICA V-LUX1" */
+ { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
+ { "Panasonic DMC-L10", 15, 0xf96,
+ { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
+ { "Panasonic DMC-L1", 0, 0xf7fc, /* aka "LEICA DIGILUX 3" */
+ { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
+ { "Panasonic DMC-LC1", 0, 0, /* aka "LEICA DIGILUX 2" */
+ { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
+ { "Panasonic DMC-LX1", 0, 0xf7f0, /* aka "LEICA D-LUX2" */
+ { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } },
+ { "Panasonic DMC-LX2", 0, 0, /* aka "LEICA D-LUX3" */
+ { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
+ { "Panasonic DMC-LX3", 15, 0xfff, /* aka "LEICA D-LUX4" */
+ { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
+ { "Panasonic DMC-FX150", 15, 0xfff,
+ { 9082,-2907,-925,-6119,13377,3058,-1797,2641,5609 } },
+ { "Panasonic DMC-G1", 15, 0xfff,
+ { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
+ { "Phase One H 20", 0, 0, /* DJC */
+ { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } },
+ { "Phase One P 2", 0, 0,
+ { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } },
+ { "Phase One P 30", 0, 0,
+ { 4516,-245,-37,-7020,14976,2173,-3206,4671,7087 } },
+ { "Phase One P 45", 0, 0,
+ { 5053,-24,-117,-5684,14076,1702,-2619,4492,5849 } },
+ { "SAMSUNG GX-1", 0, 0,
+ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } },
+ { "Sinar", 0, 0, /* DJC */
+ { 16442,-2956,-2422,-2877,12128,750,-1136,6066,4559 } },
+ { "SONY DSC-F828", 491, 0,
+ { 7924,-1910,-777,-8226,15459,2998,-1517,2199,6818,-7242,11401,3481 } },
+ { "SONY DSC-R1", 512, 0,
+ { 8512,-2641,-694,-8042,15670,2526,-1821,2117,7414 } },
+ { "SONY DSC-V3", 0, 0,
+ { 7511,-2571,-692,-7894,15088,3060,-948,1111,8128 } },
+ { "SONY DSLR-A100", 0, 0xfeb,
+ { 9437,-2811,-774,-8405,16215,2290,-710,596,7181 } },
+ { "SONY DSLR-A200", 0, 0,
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { "SONY DSLR-A300", 0, 0,
+ { 9847,-3091,-928,-8485,16345,2225,-715,595,7103 } },
+ { "SONY DSLR-A350", 0, 0xffc,
+ { 6038,-1484,-578,-9146,16746,2513,-875,746,7217 } },
+ { "SONY DSLR-A700", 254, 0x1ffe,
+ { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } },
+ { "SONY DSLR-A900", 254, 0x1ffe,
+ { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }
+ };
+ double cam_xyz[4][3];
+ char name[130];
+ int i, j;
+
+ sprintf (name, "%s %s", p_make, p_model);
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (!strncmp (name, table[i].prefix, strlen(table[i].prefix))) {
+ if (table[i].t_black) black = (ushort) table[i].t_black;
+ if (table[i].t_maximum) maximum = (ushort) table[i].t_maximum;
+ for (j=0; j < 12; j++)
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.color.cam_xyz[0][j] =
+#endif
+ cam_xyz[0][j] = table[i].trans[j] / 10000.0;
+ cam_xyz_coeff (cam_xyz);
+ break;
+ }
+}
+
+void CLASS simple_coeff (int index)
+{
+ static const float table[][12] = {
+ /* index 0 -- all Foveon cameras */
+ { 1.4032,-0.2231,-0.1016,-0.5263,1.4816,0.017,-0.0112,0.0183,0.9113 },
+ /* index 1 -- Kodak DC20 and DC25 */
+ { 2.25,0.75,-1.75,-0.25,-0.25,0.75,0.75,-0.25,-0.25,-1.75,0.75,2.25 },
+ /* index 2 -- Logitech Fotoman Pixtura */
+ { 1.893,-0.418,-0.476,-0.495,1.773,-0.278,-1.017,-0.655,2.672 },
+ /* index 3 -- Nikon E880, E900, and E990 */
+ { -1.936280, 1.800443, -1.448486, 2.584324,
+ 1.405365, -0.524955, -0.289090, 0.408680,
+ -1.204965, 1.082304, 2.941367, -1.818705 }
+ };
+ int i, c;
+
+ for (raw_color = i=0; i < 3; i++)
+ FORCC rgb_cam[i][c] = table[index][i*colors+c];
+}
+
+short CLASS guess_byte_order (int words)
+{
+ uchar test[4][2];
+ int t=2, msb;
+ double diff, sum[2] = {0,0};
+
+ fread (test[0], 2, 2, ifp);
+ for (words-=2; words--; ) {
+ fread (test[t], 2, 1, ifp);
+ for (msb=0; msb < 2; msb++) {
+ diff = (test[t^2][msb] << 8 | test[t^2][!msb])
+ - (test[t ][msb] << 8 | test[t ][!msb]);
+ sum[msb] += diff*diff;
+ }
+ t = (t+1) & 3;
+ }
+ return sum[0] < sum[1] ? 0x4d4d : 0x4949;
+}
+
+/*
+ Identify which camera created this file, and set global variables
+ accordingly.
+ */
+void CLASS identify()
+{
+ char head[32], *cp;
+ unsigned hlen, fsize, i, c, is_canon;
+ struct jhead jh;
+ static const struct {
+ int fsize;
+ char t_make[12], t_model[19], withjpeg;
+ } table[] = {
+ { 62464, "Kodak", "DC20" ,0 },
+ { 124928, "Kodak", "DC20" ,0 },
+ { 1652736, "Kodak", "DCS200" ,0 },
+ { 4159302, "Kodak", "C330" ,0 },
+ { 4162462, "Kodak", "C330" ,0 },
+ { 460800, "Kodak", "C603v" ,0 },
+ { 614400, "Kodak", "C603v" ,0 },
+ { 6163328, "Kodak", "C603" ,0 },
+ { 6166488, "Kodak", "C603" ,0 },
+ { 9116448, "Kodak", "C603y" ,0 },
+ { 311696, "ST Micro", "STV680 VGA" ,0 }, /* SPYz */
+ { 614400, "Kodak", "KAI-0340" ,0 },
+ { 787456, "Creative", "PC-CAM 600" ,0 },
+ { 1138688, "Minolta", "RD175" ,0 },
+ { 3840000, "Foculus", "531C" ,0 },
+ { 786432, "AVT", "F-080C" ,0 },
+ { 1447680, "AVT", "F-145C" ,0 },
+ { 1920000, "AVT", "F-201C" ,0 },
+ { 5067304, "AVT", "F-510C" ,0 },
+ { 10134608, "AVT", "F-510C" ,0 },
+ { 16157136, "AVT", "F-810C" ,0 },
+ { 1409024, "Sony", "XCD-SX910CR" ,0 },
+ { 2818048, "Sony", "XCD-SX910CR" ,0 },
+ { 3884928, "Micron", "2010" ,0 },
+ { 6624000, "Pixelink", "A782" ,0 },
+ { 13248000, "Pixelink", "A782" ,0 },
+ { 6291456, "RoverShot","3320AF" ,0 },
+ { 6553440, "Canon", "PowerShot A460" ,0 },
+ { 6653280, "Canon", "PowerShot A530" ,0 },
+ { 6573120, "Canon", "PowerShot A610" ,0 },
+ { 9219600, "Canon", "PowerShot A620" ,0 },
+ { 10341600, "Canon", "PowerShot A720" ,0 },
+ { 10383120, "Canon", "PowerShot A630" ,0 },
+ { 12945240, "Canon", "PowerShot A640" ,0 },
+ { 15636240, "Canon", "PowerShot A650" ,0 },
+ { 5298000, "Canon", "PowerShot SD300" ,0 },
+ { 7710960, "Canon", "PowerShot S3 IS" ,0 },
+ { 5939200, "OLYMPUS", "C770UZ" ,0 },
+ { 1581060, "NIKON", "E900" ,1 }, /* or E900s,E910 */
+ { 2465792, "NIKON", "E950" ,1 }, /* or E800,E700 */
+ { 2940928, "NIKON", "E2100" ,1 }, /* or E2500 */
+ { 4771840, "NIKON", "E990" ,1 }, /* or E995, Oly C3030Z */
+ { 4775936, "NIKON", "E3700" ,1 }, /* or Optio 33WR */
+ { 5869568, "NIKON", "E4300" ,1 }, /* or DiMAGE Z2 */
+ { 5865472, "NIKON", "E4500" ,1 },
+ { 7438336, "NIKON", "E5000" ,1 }, /* or E5700 */
+ { 8998912, "NIKON", "COOLPIX S6" ,1 },
+ { 1976352, "CASIO", "QV-2000UX" ,1 },
+ { 3217760, "CASIO", "QV-3*00EX" ,1 },
+ { 6218368, "CASIO", "QV-5700" ,1 },
+ { 6054400, "CASIO", "QV-R41" ,1 },
+ { 7530816, "CASIO", "QV-R51" ,1 },
+ { 7684000, "CASIO", "QV-4000" ,1 },
+ { 4948608, "CASIO", "EX-S100" ,1 },
+ { 7542528, "CASIO", "EX-Z50" ,1 },
+ { 7753344, "CASIO", "EX-Z55" ,1 },
+ { 7426656, "CASIO", "EX-P505" ,1 },
+ { 9313536, "CASIO", "EX-P600" ,1 },
+ { 10979200, "CASIO", "EX-P700" ,1 },
+ { 3178560, "PENTAX", "Optio S" ,1 },
+ { 4841984, "PENTAX", "Optio S" ,1 },
+ { 6114240, "PENTAX", "Optio S4" ,1 }, /* or S4i, CASIO EX-Z4 */
+ { 10702848, "PENTAX", "Optio 750Z" ,1 },
+ { 16098048, "SAMSUNG", "S85" ,1 },
+ { 16215552, "SAMSUNG", "S85" ,1 },
+ { 12582980, "Sinar", "" ,0 },
+ { 33292868, "Sinar", "" ,0 },
+ { 44390468, "Sinar", "" ,0 } };
+ static const char *corp[] =
+ { "Canon", "NIKON", "EPSON", "KODAK", "Kodak", "OLYMPUS", "PENTAX",
+ "MINOLTA", "Minolta", "Konica", "CASIO", "Sinar", "Phase One",
+ "SAMSUNG", "Mamiya" };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,0,2);
+#endif
+
+ tiff_flip = flip = filters = -1; /* 0 is valid, so -1 is unknown */
+ raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
+ maximum = height = width = top_margin = left_margin = 0;
+ cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
+ iso_speed = shutter = aperture = focal_len = unique_id = 0;
+ memset (gpsdata, 0, sizeof gpsdata);
+ memset (white, 0, sizeof white);
+ thumb_offset = thumb_length = thumb_width = thumb_height = 0;
+ load_raw = thumb_load_raw = 0;
+ write_thumb = &CLASS jpeg_thumb;
+ data_offset = meta_length = tiff_bps = tiff_compress = 0;
+ kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
+ timestamp = shot_order = tiff_samples = black = 0;
+ mix_green = profile_length = data_error = zero_is_bad = 0;
+ pixel_aspect = is_raw = raw_color = use_gamma = 1;
+ tile_width = tile_length = INT_MAX;
+ for (i=0; i < 4; i++) {
+ cam_mul[i] = i == 1;
+ pre_mul[i] = i < 3;
+ FORC3 cmatrix[c][i] = 0;
+ FORC3 rgb_cam[c][i] = c == i;
+ }
+ colors = 3;
+ tiff_bps = 12;
+ for (i=0; i < 0x4000; i++) curve[i] = i;
+
+ order = get2();
+ hlen = get4();
+ fseek (ifp, 0, SEEK_SET);
+ fread (head, 1, 32, ifp);
+ fseek (ifp, 0, SEEK_END);
+ fsize = ftell(ifp);
+ if ((cp = (char *) memmem (head, 32, "MMMM", 4)) ||
+ (cp = (char *) memmem (head, 32, "IIII", 4))) {
+ parse_phase_one (cp-head);
+ if (cp-head) parse_tiff(0);
+ } else if (order == 0x4949 || order == 0x4d4d) {
+ if (!memcmp (head+6,"HEAPCCDR",8)) {
+ data_offset = hlen;
+ parse_ciff (hlen, fsize - hlen);
+ } else {
+ parse_tiff(0);
+ }
+ } else if (!memcmp (head,"\xff\xd8\xff\xe1",4) &&
+ !memcmp (head+6,"Exif",4)) {
+ fseek (ifp, 4, SEEK_SET);
+ data_offset = 4 + get2();
+ fseek (ifp, data_offset, SEEK_SET);
+ if (fgetc(ifp) != 0xff)
+ parse_tiff(12);
+ thumb_offset = 0;
+ } else if (!memcmp (head+25,"ARECOYK",7)) {
+ strcpy (make, "Contax");
+ strcpy (model,"N Digital");
+ fseek (ifp, 33, SEEK_SET);
+ get_timestamp(1);
+ fseek (ifp, 60, SEEK_SET);
+ FORC4 cam_mul[c ^ (c >> 1)] = get4();
+ } else if (!strcmp (head, "PXN")) {
+ strcpy (make, "Logitech");
+ strcpy (model,"Fotoman Pixtura");
+ } else if (!strcmp (head, "qktk")) {
+ strcpy (make, "Apple");
+ strcpy (model,"QuickTake 100");
+ } else if (!strcmp (head, "qktn")) {
+ strcpy (make, "Apple");
+ strcpy (model,"QuickTake 150");
+ } else if (!memcmp (head,"FUJIFILM",8)) {
+ fseek (ifp, 84, SEEK_SET);
+ thumb_offset = get4();
+ thumb_length = get4();
+ fseek (ifp, 92, SEEK_SET);
+ parse_fuji (get4());
+ if (thumb_offset > 120) {
+ fseek (ifp, 120, SEEK_SET);
+ is_raw += (i = get4()) && 1;
+ if (is_raw == 2 && shot_select)
+ parse_fuji (i);
+ }
+ fseek (ifp, 100, SEEK_SET);
+ data_offset = get4();
+ parse_tiff (thumb_offset+12);
+ } else if (!memcmp (head,"RIFF",4)) {
+ fseek (ifp, 0, SEEK_SET);
+ parse_riff();
+ } else if (!memcmp (head,"\0\001\0\001\0@",6)) {
+ fseek (ifp, 6, SEEK_SET);
+ fread (make, 1, 8, ifp);
+ fread (model, 1, 8, ifp);
+ fread (model2, 1, 16, ifp);
+ data_offset = get2();
+ get2();
+ raw_width = get2();
+ raw_height = get2();
+ load_raw = &CLASS nokia_load_raw;
+ filters = 0x61616161;
+ } else if (!memcmp (head,"DSC-Image",9))
+ parse_rollei();
+ else if (!memcmp (head,"PWAD",4))
+ parse_sinar_ia();
+ else if (!memcmp (head,"\0MRM",4))
+ parse_minolta(0);
+ else if (!memcmp (head,"CI",2))
+ parse_cine();
+ else
+ for (i=0; i < sizeof table / sizeof *table; i++)
+ if (fsize == table[i].fsize) {
+ strcpy (make, table[i].t_make );
+ strcpy (model, table[i].t_model);
+ if (table[i].withjpeg)
+ parse_external_jpeg();
+ }
+ if (make[0] == 0) parse_smal (0, fsize);
+ if (make[0] == 0) parse_jpeg (is_raw = 0);
+
+ for (i=0; i < sizeof corp / sizeof *corp; i++)
+ if (strstr (make, corp[i])) /* Simplify company names */
+ strcpy (make, corp[i]);
+ if (!strncmp (make,"KODAK",5))
+ make[16] = model[16] = 0;
+ cp = make + strlen(make); /* Remove trailing spaces */
+ while (*--cp == ' ') *cp = 0;
+ cp = model + strlen(model);
+ while (*--cp == ' ') *cp = 0;
+ i = strlen(make); /* Remove make from model */
+ if (!strncasecmp (model, make, i) && model[i++] == ' ')
+ memmove (model, model+i, 64-i);
+ if (!strncmp (model,"Digital Camera ",15))
+ strcpy (model, model+15);
+ desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0;
+ if (!is_raw) goto notraw;
+
+ if (!maximum) maximum = (1 << tiff_bps) - 1;
+ if (!height) height = raw_height;
+ if (!width) width = raw_width;
+ if (fuji_width) {
+ width = height + fuji_width;
+ height = width - 1;
+ pixel_aspect = 1;
+ }
+ if (height == 2624 && width == 3936) /* Pentax K10D and Samsung GX10 */
+ { height = 2616; width = 3896; }
+ if (height == 3136 && width == 4864) /* Pentax K20D */
+ { height = 3124; width = 4688; }
+ if (height == 3014 && width == 4096) /* Ricoh GX200 */
+ width = 4014;
+ if (dng_version) {
+ if (filters == UINT_MAX) filters = 0;
+ if (filters) is_raw = tiff_samples;
+ else colors = tiff_samples;
+ if (tiff_compress == 1)
+ load_raw = &CLASS adobe_dng_load_raw_nc;
+ if (tiff_compress == 7)
+ load_raw = &CLASS adobe_dng_load_raw_lj;
+ goto dng_skip;
+ }
+ if ((is_canon = !strcmp(make,"Canon")))
+ load_raw = memcmp (head+6,"HEAPCCDR",8) ?
+ &CLASS lossless_jpeg_load_raw : &CLASS canon_compressed_load_raw;
+ if (!strcmp(make,"NIKON")) {
+ if (!load_raw)
+ load_raw = &CLASS packed_12_load_raw;
+ if (model[0] == 'E')
+ load_flags |= !data_offset << 2 | 2;
+ }
+ if (!strcmp(make,"CASIO")) {
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7f;
+ }
+
+/* Set parameters based on camera name (for non-DNG files). */
+
+ if (is_canon && tiff_bps == 15) {
+ switch (width) {
+ case 3344: width -= 66;
+ case 3872: width -= 6;
+ }
+ filters = 0;
+ load_raw = &CLASS canon_sraw_load_raw;
+ } else if (!strcmp(model,"PowerShot 600")) {
+ height = 613;
+ width = 854;
+ raw_width = 896;
+ pixel_aspect = 607/628.0;
+ colors = 4;
+ filters = 0xe1e4e1e4;
+ load_raw = &CLASS canon_600_load_raw;
+ } else if (!strcmp(model,"PowerShot A5") ||
+ !strcmp(model,"PowerShot A5 Zoom")) {
+ height = 773;
+ width = 960;
+ raw_width = 992;
+ pixel_aspect = 256/235.0;
+ colors = 4;
+ filters = 0x1e4e1e4e;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A50")) {
+ height = 968;
+ width = 1290;
+ raw_width = 1320;
+ colors = 4;
+ filters = 0x1b4e4b1e;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot Pro70")) {
+ height = 1024;
+ width = 1552;
+ colors = 4;
+ filters = 0x1e4b4e1b;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot SD300")) {
+ height = 1752;
+ width = 2344;
+ raw_height = 1766;
+ raw_width = 2400;
+ top_margin = 12;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A460")) {
+ height = 1960;
+ width = 2616;
+ raw_height = 1968;
+ raw_width = 2664;
+ top_margin = 4;
+ left_margin = 4;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A530")) {
+ height = 1984;
+ width = 2620;
+ raw_height = 1992;
+ raw_width = 2672;
+ top_margin = 6;
+ left_margin = 10;
+ load_raw = &CLASS canon_a5_load_raw;
+ raw_color = 0;
+ } else if (!strcmp(model,"PowerShot A610")) {
+ if (canon_s2is()) strcpy (model+10, "S2 IS");
+ height = 1960;
+ width = 2616;
+ raw_height = 1968;
+ raw_width = 2672;
+ top_margin = 8;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A620")) {
+ height = 2328;
+ width = 3112;
+ raw_height = 2340;
+ raw_width = 3152;
+ top_margin = 12;
+ left_margin = 36;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A720")) {
+ height = 2472;
+ width = 3298;
+ raw_height = 2480;
+ raw_width = 3336;
+ top_margin = 5;
+ left_margin = 6;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A630")) {
+ height = 2472;
+ width = 3288;
+ raw_height = 2484;
+ raw_width = 3344;
+ top_margin = 6;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A640")) {
+ height = 2760;
+ width = 3672;
+ raw_height = 2772;
+ raw_width = 3736;
+ top_margin = 6;
+ left_margin = 12;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot A650")) {
+ height = 3024;
+ width = 4032;
+ raw_height = 3048;
+ raw_width = 4104;
+ top_margin = 12;
+ left_margin = 48;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot S3 IS")) {
+ height = 2128;
+ width = 2840;
+ raw_height = 2136;
+ raw_width = 2888;
+ top_margin = 8;
+ left_margin = 44;
+ load_raw = &CLASS canon_a5_load_raw;
+ } else if (!strcmp(model,"PowerShot Pro90 IS")) {
+ width = 1896;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (is_canon && raw_width == 2144) {
+ height = 1550;
+ width = 2088;
+ top_margin = 8;
+ left_margin = 4;
+ if (!strcmp(model,"PowerShot G1")) {
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ }
+ } else if (is_canon && raw_width == 2224) {
+ height = 1448;
+ width = 2176;
+ top_margin = 6;
+ left_margin = 48;
+ } else if (is_canon && raw_width == 2376) {
+ height = 1720;
+ width = 2312;
+ top_margin = 6;
+ left_margin = 12;
+ } else if (is_canon && raw_width == 2672) {
+ height = 1960;
+ width = 2616;
+ top_margin = 6;
+ left_margin = 12;
+ } else if (is_canon && raw_width == 3152) {
+ height = 2056;
+ width = 3088;
+ top_margin = 12;
+ left_margin = 64;
+ if (unique_id == 0x80000170)
+ adobe_coeff ("Canon","EOS 300D");
+ } else if (is_canon && raw_width == 3160) {
+ height = 2328;
+ width = 3112;
+ top_margin = 12;
+ left_margin = 44;
+ } else if (is_canon && raw_width == 3344) {
+ height = 2472;
+ width = 3288;
+ top_margin = 6;
+ left_margin = 4;
+ } else if (!strcmp(model,"EOS D2000C")) {
+ filters = 0x61616161;
+ black = curve[200];
+ } else if (is_canon && raw_width == 3516) {
+ top_margin = 14;
+ left_margin = 42;
+ if (unique_id == 0x80000189)
+ adobe_coeff ("Canon","EOS 350D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3596) {
+ top_margin = 12;
+ left_margin = 74;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3944) {
+ height = 2602;
+ width = 3908;
+ top_margin = 18;
+ left_margin = 30;
+ } else if (is_canon && raw_width == 3948) {
+ top_margin = 18;
+ left_margin = 42;
+ height -= 2;
+ if (unique_id == 0x80000236)
+ adobe_coeff ("Canon","EOS 400D");
+ if (unique_id == 0x80000254)
+ adobe_coeff ("Canon","EOS 1000D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 3984) {
+ top_margin = 20;
+ left_margin = 76;
+ height -= 2;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4104) {
+ height = 3024;
+ width = 4032;
+ top_margin = 12;
+ left_margin = 48;
+ } else if (is_canon && raw_width == 4312) {
+ top_margin = 18;
+ left_margin = 22;
+ height -= 2;
+ if (unique_id == 0x80000176)
+ adobe_coeff ("Canon","EOS 450D");
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4476) {
+ top_margin = 34;
+ left_margin = 90;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 4480) {
+ height = 3326;
+ width = 4432;
+ top_margin = 10;
+ left_margin = 12;
+ filters = 0x49494949;
+ } else if (is_canon && raw_width == 1208) {
+ top_margin = 51;
+ left_margin = 62;
+ raw_width = width *= 4;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 1448) {
+ top_margin = 51;
+ left_margin = 158;
+ raw_width = width *= 4;
+ goto canon_cr2;
+ } else if (is_canon && raw_width == 5108) {
+ top_margin = 13;
+ left_margin = 98;
+canon_cr2:
+ height -= top_margin;
+ width -= left_margin;
+ } else if (is_canon && raw_width == 5712) {
+ height = 3752;
+ width = 5640;
+ top_margin = 20;
+ left_margin = 62;
+ } else if (!strcmp(model,"D1")) {
+ cam_mul[0] *= 256/527.0;
+ cam_mul[2] *= 256/317.0;
+ } else if (!strcmp(model,"D1X")) {
+ width -= 4;
+ pixel_aspect = 0.5;
+ } else if (!strcmp(model,"D40X") ||
+ !strcmp(model,"D60") ||
+ !strcmp(model,"D80")) {
+ height -= 3;
+ width -= 4;
+ } else if (!strcmp(model,"D3") ||
+ !strcmp(model,"D700")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strncmp(model,"D40",3) ||
+ !strncmp(model,"D50",3) ||
+ !strncmp(model,"D70",3)) {
+ width--;
+ } else if (!strcmp(model,"D90")) {
+ width -= 42;
+ } else if (!strcmp(model,"D100")) {
+ if (tiff_compress == 34713 && !nikon_is_compressed()) {
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags |= 8;
+ raw_width = (width += 3) + 3;
+ }
+ } else if (!strcmp(model,"D200")) {
+ left_margin = 1;
+ width -= 4;
+ filters = 0x94949494;
+ } else if (!strncmp(model,"D2H",3)) {
+ left_margin = 6;
+ width -= 14;
+ } else if (!strncmp(model,"D2X",3)) {
+ if (width == 3264) width -= 32;
+ else width -= 8;
+ } else if (!strcmp(model,"D300")) {
+ width -= 32;
+ } else if (!strcmp(model,"COOLPIX P6000")) {
+ load_flags = 1;
+ filters = 0x94949494;
+ } else if (fsize == 1581060) {
+ height = 963;
+ width = 1287;
+ raw_width = 1632;
+ load_raw = &CLASS nikon_e900_load_raw;
+ maximum = 0x3f4;
+ colors = 4;
+ filters = 0x1e1e1e1e;
+ simple_coeff(3);
+ pre_mul[0] = 1.2085;
+ pre_mul[1] = 1.0943;
+ pre_mul[3] = 1.1103;
+ } else if (fsize == 2465792) {
+ height = 1203;
+ width = 1616;
+ raw_width = 2048;
+ load_raw = &CLASS nikon_e900_load_raw;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ adobe_coeff ("NIKON","E950");
+ } else if (fsize == 4771840) {
+ height = 1540;
+ width = 2064;
+ colors = 4;
+ filters = 0xe1e1e1e1;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 6;
+ if (!timestamp && nikon_e995())
+ strcpy (model, "E995");
+ if (strcmp(model,"E995")) {
+ filters = 0xb4b4b4b4;
+ simple_coeff(3);
+ pre_mul[0] = 1.196;
+ pre_mul[1] = 1.246;
+ pre_mul[2] = 1.018;
+ }
+ } else if (!strcmp(model,"E2100")) {
+ if (!timestamp && !nikon_e2100()) goto cp_e2500;
+ height = 1206;
+ width = 1616;
+ load_flags = 7;
+ } else if (!strcmp(model,"E2500")) {
+cp_e2500:
+ strcpy (model, "E2500");
+ height = 1204;
+ width = 1616;
+ colors = 4;
+ filters = 0x4b4b4b4b;
+ } else if (fsize == 4775936) {
+ height = 1542;
+ width = 2064;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ pre_mul[0] = 1.818;
+ pre_mul[2] = 1.618;
+ if (!timestamp) nikon_3700();
+ if (model[0] == 'E' && atoi(model+1) < 3700)
+ filters = 0x49494949;
+ if (!strcmp(model,"Optio 33WR")) {
+ flip = 1;
+ filters = 0x16161616;
+ pre_mul[0] = 1.331;
+ pre_mul[2] = 1.820;
+ }
+ } else if (fsize == 5869568) {
+ height = 1710;
+ width = 2288;
+ filters = 0x16161616;
+ if (!timestamp && minolta_z2()) {
+ strcpy (make, "Minolta");
+ strcpy (model,"DiMAGE Z2");
+ }
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 6 + (make[0] == 'M');
+ } else if (!strcmp(model,"E4500")) {
+ height = 1708;
+ width = 2288;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (fsize == 7438336) {
+ height = 1924;
+ width = 2576;
+ colors = 4;
+ filters = 0xb4b4b4b4;
+ } else if (fsize == 8998912) {
+ height = 2118;
+ width = 2832;
+ maximum = 0xf83;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(model,"FinePix S5100") ||
+ !strcmp(model,"FinePix S5500")) {
+ load_raw = &CLASS unpacked_load_raw;
+ } else if (!strcmp(make,"FUJIFILM")) {
+ if (!strcmp(model+7,"S2Pro")) {
+ strcpy (model+7," S2Pro");
+ height = 2144;
+ width = 2880;
+ flip = 6;
+ } else
+ maximum = 0x3e00;
+ if (is_raw == 2 && shot_select)
+ maximum = 0x2f00;
+ top_margin = (raw_height - height)/2;
+ left_margin = (raw_width - width )/2;
+ if (is_raw == 2)
+ data_offset += (shot_select > 0) * ( fuji_layout ?
+ (raw_width *= 2) : raw_height*raw_width*2 );
+ fuji_width = width >> !fuji_layout;
+ width = (height >> fuji_layout) + fuji_width;
+ raw_height = height;
+ height = width - 1;
+ load_raw = &CLASS fuji_load_raw;
+ if (!(fuji_width & 1)) filters = 0x49494949;
+ } else if (!strcmp(model,"RD175")) {
+ height = 986;
+ width = 1534;
+ data_offset = 513;
+ filters = 0x61616161;
+ load_raw = &CLASS minolta_rd175_load_raw;
+ } else if (!strcmp(model,"KD-400Z")) {
+ height = 1712;
+ width = 2312;
+ raw_width = 2336;
+ goto konica_400z;
+ } else if (!strcmp(model,"KD-510Z")) {
+ goto konica_510z;
+ } else if (!strcasecmp(make,"MINOLTA")) {
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xfff;
+ if (!strncmp(model,"DiMAGE A",8)) {
+ if (!strcmp(model,"DiMAGE A200"))
+ filters = 0x49494949;
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strncmp(model,"ALPHA",5) ||
+ !strncmp(model,"DYNAX",5) ||
+ !strncmp(model,"MAXXUM",6)) {
+ sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M'));
+ adobe_coeff (make, model+20);
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strncmp(model,"DiMAGE G",8)) {
+ if (model[8] == '4') {
+ height = 1716;
+ width = 2304;
+ } else if (model[8] == '5') {
+konica_510z:
+ height = 1956;
+ width = 2607;
+ raw_width = 2624;
+ } else if (model[8] == '6') {
+ height = 2136;
+ width = 2848;
+ }
+ data_offset += 14;
+ filters = 0x61616161;
+konica_400z:
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3df;
+ order = 0x4d4d;
+ }
+ } else if (!strcmp(model,"*ist DS")) {
+ height -= 2;
+ } else if (!strcmp(model,"K20D")) {
+ filters = 0x16161616;
+ } else if (!strcmp(model,"Optio S")) {
+ if (fsize == 3178560) {
+ height = 1540;
+ width = 2064;
+ load_raw = &CLASS eight_bit_load_raw;
+ cam_mul[0] *= 4;
+ cam_mul[2] *= 4;
+ pre_mul[0] = 1.391;
+ pre_mul[2] = 1.188;
+ } else {
+ height = 1544;
+ width = 2068;
+ raw_width = 3136;
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7c;
+ pre_mul[0] = 1.137;
+ pre_mul[2] = 1.453;
+ }
+ } else if (fsize == 6114240) {
+ height = 1737;
+ width = 2324;
+ raw_width = 3520;
+ load_raw = &CLASS packed_12_load_raw;
+ maximum = 0xf7a;
+ pre_mul[0] = 1.980;
+ pre_mul[2] = 1.570;
+ } else if (!strcmp(model,"Optio 750Z")) {
+ height = 2302;
+ width = 3072;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(model,"S85")) {
+ height = 2448;
+ width = 3264;
+ raw_width = fsize/height/2;
+ order = 0x4d4d;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xffff;
+ } else if (!strcmp(model,"STV680 VGA")) {
+ height = 484;
+ width = 644;
+ load_raw = &CLASS eight_bit_load_raw;
+ flip = 2;
+ filters = 0x16161616;
+ black = 16;
+ pre_mul[0] = 1.097;
+ pre_mul[2] = 1.128;
+ } else if (!strcmp(model,"KAI-0340")) {
+ height = 477;
+ width = 640;
+ order = 0x4949;
+ data_offset = 3840;
+ load_raw = &CLASS unpacked_load_raw;
+ pre_mul[0] = 1.561;
+ pre_mul[2] = 2.454;
+ } else if (!strcmp(model,"N95")) {
+ height = raw_height - (top_margin = 2);
+ } else if (!strcmp(model,"531C")) {
+ height = 1200;
+ width = 1600;
+ load_raw = &CLASS unpacked_load_raw;
+ filters = 0x49494949;
+ pre_mul[1] = 1.218;
+ } else if (!strcmp(model,"F-080C")) {
+ height = 768;
+ width = 1024;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-145C")) {
+ height = 1040;
+ width = 1392;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-201C")) {
+ height = 1200;
+ width = 1600;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"F-510C")) {
+ height = 1958;
+ width = 2588;
+ load_raw = fsize < 7500000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ maximum = 0xfff0;
+ } else if (!strcmp(model,"F-810C")) {
+ height = 2469;
+ width = 3272;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xfff0;
+ } else if (!strcmp(model,"XCD-SX910CR")) {
+ height = 1024;
+ width = 1375;
+ raw_width = 1376;
+ filters = 0x49494949;
+ maximum = 0x3ff;
+ load_raw = fsize < 2000000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ } else if (!strcmp(model,"2010")) {
+ height = 1207;
+ width = 1608;
+ order = 0x4949;
+ filters = 0x16161616;
+ data_offset = 3212;
+ maximum = 0x3ff;
+ load_raw = &CLASS unpacked_load_raw;
+ } else if (!strcmp(model,"A782")) {
+ height = 3000;
+ width = 2208;
+ filters = 0x61616161;
+ load_raw = fsize < 10000000 ?
+ &CLASS eight_bit_load_raw : &CLASS unpacked_load_raw;
+ maximum = 0xffc0;
+ } else if (!strcmp(model,"3320AF")) {
+ height = 1536;
+ raw_width = width = 2048;
+ filters = 0x61616161;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3ff;
+ pre_mul[0] = 1.717;
+ pre_mul[2] = 1.138;
+ fseek (ifp, 0x300000, SEEK_SET);
+ if ((order = guess_byte_order(0x10000)) == 0x4d4d) {
+ height -= (top_margin = 16);
+ width -= (left_margin = 28);
+ maximum = 0xf5c0;
+ strcpy (make, "ISG");
+ model[0] = 0;
+ }
+ } else if (!strcmp(make,"Hasselblad")) {
+ if (load_raw == &CLASS lossless_jpeg_load_raw)
+ load_raw = &CLASS hasselblad_load_raw;
+ if (raw_width == 7262) {
+ height = 5444;
+ width = 7248;
+ top_margin = 4;
+ left_margin = 7;
+ filters = 0x61616161;
+ } else if (raw_width == 4090) {
+ strcpy (model, "V96C");
+ height -= (top_margin = 6);
+ width -= (left_margin = 3) + 7;
+ filters = 0x61616161;
+ }
+ } else if (!strcmp(make,"Sinar")) {
+ if (!memcmp(head,"8BPS",4)) {
+ fseek (ifp, 14, SEEK_SET);
+ height = get4();
+ width = get4();
+ filters = 0x61616161;
+ data_offset = 68;
+ }
+ if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+ maximum = 0x3fff;
+ } else if (!strcmp(make,"Leaf")) {
+ maximum = 0x3fff;
+ fseek (ifp, data_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1) && jh.bits == 15)
+ maximum = 0x1fff;
+ if (tiff_samples > 1) filters = 0;
+ if (tiff_samples > 1 || tile_length < raw_height)
+ load_raw = &CLASS leaf_hdr_load_raw;
+ if ((width | height) == 2048) {
+ if (tiff_samples == 1) {
+ filters = 1;
+ strcpy (cdesc, "RBTG");
+ strcpy (model, "CatchLight");
+ top_margin = 8; left_margin = 18; height = 2032; width = 2016;
+ } else {
+ strcpy (model, "DCB2");
+ top_margin = 10; left_margin = 16; height = 2028; width = 2022;
+ }
+ } else if (width+height == 3144+2060) {
+ if (!model[0]) strcpy (model, "Cantare");
+ if (width > height) {
+ top_margin = 6; left_margin = 32; height = 2048; width = 3072;
+ filters = 0x61616161;
+ } else {
+ left_margin = 6; top_margin = 32; width = 2048; height = 3072;
+ filters = 0x16161616;
+ }
+ if (!cam_mul[0] || model[0] == 'V') filters = 0;
+ else is_raw = tiff_samples;
+ } else if (width == 2116) {
+ strcpy (model, "Valeo 6");
+ height -= 2 * (top_margin = 30);
+ width -= 2 * (left_margin = 55);
+ filters = 0x49494949;
+ } else if (width == 3171) {
+ strcpy (model, "Valeo 6");
+ height -= 2 * (top_margin = 24);
+ width -= 2 * (left_margin = 24);
+ filters = 0x16161616;
+ }
+ } else if (!strcmp(make,"LEICA") || !strcmp(make,"Panasonic")) {
+ maximum = 0xfff0;
+ if ((fsize-data_offset) / (width*8/7) == height)
+ load_raw = &CLASS panasonic_load_raw;
+ if (!load_raw) load_raw = &CLASS unpacked_load_raw;
+ switch (width) {
+ case 2568:
+ adobe_coeff ("Panasonic","DMC-LC1"); break;
+ case 3130:
+ left_margin = -14;
+ case 3170:
+ left_margin += 18;
+ width = 3096;
+ if (height > 2326) {
+ height = 2326;
+ top_margin = 13;
+ filters = 0x49494949;
+ }
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ8"); break;
+ case 3213:
+ width -= 27;
+ case 3177:
+ width -= 10;
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-L1"); break;
+ case 3304:
+ width -= 17;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ30"); break;
+ case 3330:
+ width += 43;
+ left_margin = -6;
+ maximum = 0xf7f0;
+ case 3370:
+ width -= 82;
+ left_margin += 15;
+ if (height > 2480)
+ height = 2480 - (top_margin = 10);
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ18"); break;
+ case 3690:
+ height -= 2;
+ left_margin = -14;
+ maximum = 0xf7f0;
+ case 3770:
+ width = 3672;
+ if (--height == 2798 && (height = 2760))
+ top_margin = 15;
+ else filters = 0x49494949;
+ left_margin += 17;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-FZ50"); break;
+ case 3710:
+ width = 3682;
+ filters = 0x49494949;
+ adobe_coeff ("Panasonic","DMC-L10"); break;
+ case 3724:
+ width -= 14;
+ case 3836:
+ width -= 42;
+lx3: filters = 0x16161616;
+ if (make[0] != 'P')
+ adobe_coeff ("Panasonic","DMC-LX3");
+ break;
+ case 3880:
+ width -= 22;
+ left_margin = 6;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-LX1"); break;
+ case 4060:
+ width = 3982;
+ if (height == 2250) goto lx3;
+ width = 4018;
+ filters = 0x49494949;
+ zero_is_bad = 1;
+ adobe_coeff ("Panasonic","DMC-G1"); break;
+ case 4290:
+ height += 38;
+ left_margin = -14;
+ filters = 0x49494949;
+ case 4330:
+ width = 4248;
+ if ((height -= 39) == 2400)
+ top_margin = 15;
+ left_margin += 17;
+ adobe_coeff ("Panasonic","DMC-LX2"); break;
+ case 4508:
+ height -= 6;
+ width = 4429;
+ filters = 0x16161616;
+ adobe_coeff ("Panasonic","DMC-FX150"); break;
+ }
+ } else if (!strcmp(model,"C770UZ")) {
+ height = 1718;
+ width = 2304;
+ filters = 0x16161616;
+ load_raw = &CLASS packed_12_load_raw;
+ load_flags = 7;
+ } else if (!strcmp(make,"OLYMPUS")) {
+ height += height & 1;
+ filters = exif_cfa;
+ if (load_raw == &CLASS olympus_e410_load_raw) {
+ black >>= 4;
+ } else if (!strcmp(model,"E-10") ||
+ !strncmp(model,"E-20",4)) {
+ black <<= 2;
+ } else if (!strcmp(model,"E-300") ||
+ !strcmp(model,"E-500")) {
+ width -= 20;
+ if (load_raw == &CLASS unpacked_load_raw) {
+ maximum = 0xfc30;
+ black = 0;
+ }
+ } else if (!strcmp(model,"E-330")) {
+ width -= 30;
+ if (load_raw == &CLASS unpacked_load_raw)
+ maximum = 0xf790;
+ } else if (!strcmp(model,"SP550UZ")) {
+ thumb_length = fsize - (thumb_offset = 0xa39800);
+ thumb_height = 480;
+ thumb_width = 640;
+ }
+ } else if (!strcmp(model,"N Digital")) {
+ height = 2047;
+ width = 3072;
+ filters = 0x61616161;
+ data_offset = 0x1a00;
+ load_raw = &CLASS packed_12_load_raw;
+ } else if (!strcmp(model,"DSC-F828")) {
+ width = 3288;
+ left_margin = 5;
+ data_offset = 862144;
+ load_raw = &CLASS sony_load_raw;
+ filters = 0x9c9c9c9c;
+ colors = 4;
+ strcpy (cdesc, "RGBE");
+ } else if (!strcmp(model,"DSC-V3")) {
+ width = 3109;
+ left_margin = 59;
+ data_offset = 787392;
+ load_raw = &CLASS sony_load_raw;
+ } else if (!strcmp(make,"SONY") && raw_width == 3984) {
+ adobe_coeff ("SONY","DSC-R1");
+ width = 3925;
+ order = 0x4d4d;
+ } else if (!strcmp(model,"DSLR-A100")) {
+ height--;
+ } else if (!strcmp(model,"DSLR-A350")) {
+ height -= 4;
+ } else if (!strcmp(model,"C603v")) {
+ height = 480;
+ width = 640;
+ goto c603v;
+ } else if (!strcmp(model,"C603y")) {
+ height = 2134;
+ width = 2848;
+c603v:
+ filters = 0;
+ load_raw = &CLASS kodak_yrgb_load_raw;
+ } else if (!strcmp(model,"C603")) {
+ raw_height = height = 2152;
+ raw_width = width = 2864;
+ goto c603;
+ } else if (!strcmp(model,"C330")) {
+ height = 1744;
+ width = 2336;
+ raw_height = 1779;
+ raw_width = 2338;
+ top_margin = 33;
+ left_margin = 1;
+c603:
+ order = 0x4949;
+ if ((data_offset = fsize - raw_height*raw_width)) {
+ fseek (ifp, 168, SEEK_SET);
+ read_shorts (curve, 256);
+ } else use_gamma = 0;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcasecmp(make,"KODAK")) {
+ if (filters == UINT_MAX) filters = 0x61616161;
+ if (!strncmp(model,"NC2000",6)) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"EOSDCS3B")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"EOSDCS1")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS420")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS460")) {
+ width -= 4;
+ left_margin = 2;
+ } else if (!strcmp(model,"DCS460A")) {
+ width -= 4;
+ left_margin = 2;
+ colors = 1;
+ filters = 0;
+ } else if (!strcmp(model,"DCS660M")) {
+ black = 214;
+ colors = 1;
+ filters = 0;
+ } else if (!strcmp(model,"DCS760M")) {
+ colors = 1;
+ filters = 0;
+ }
+ if (!strcmp(model+4,"20X"))
+ strcpy (cdesc, "MYCY");
+ if (strstr(model,"DC25")) {
+ strcpy (model, "DC25");
+ data_offset = 15424;
+ }
+ if (!strncmp(model,"DC2",3)) {
+ height = 242;
+ if (fsize < 100000) {
+ raw_width = 256; width = 249;
+ pixel_aspect = (4.0*height) / (3.0*width);
+ } else {
+ raw_width = 512; width = 501;
+ pixel_aspect = (493.0*height) / (373.0*width);
+ }
+ data_offset += raw_width + 1;
+ colors = 4;
+ filters = 0x8d8d8d8d;
+ simple_coeff(1);
+ pre_mul[1] = 1.179;
+ pre_mul[2] = 1.209;
+ pre_mul[3] = 1.036;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"40")) {
+ strcpy (model, "DC40");
+ height = 512;
+ width = 768;
+ data_offset = 1152;
+ load_raw = &CLASS kodak_radc_load_raw;
+ } else if (strstr(model,"DC50")) {
+ strcpy (model, "DC50");
+ height = 512;
+ width = 768;
+ data_offset = 19712;
+ load_raw = &CLASS kodak_radc_load_raw;
+ } else if (strstr(model,"DC120")) {
+ strcpy (model, "DC120");
+ height = 976;
+ width = 848;
+ pixel_aspect = height/0.75/width;
+ load_raw = tiff_compress == 7 ?
+ &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw;
+ } else if (!strcmp(model,"DCS200")) {
+ thumb_height = 128;
+ thumb_width = 192;
+ thumb_offset = 6144;
+ thumb_misc = 360;
+ write_thumb = &CLASS layer_thumb;
+ height = 1024;
+ width = 1536;
+ data_offset = 79872;
+ load_raw = &CLASS eight_bit_load_raw;
+ black = 17;
+ }
+ } else if (!strcmp(model,"Fotoman Pixtura")) {
+ height = 512;
+ width = 768;
+ data_offset = 3632;
+ load_raw = &CLASS kodak_radc_load_raw;
+ filters = 0x61616161;
+ simple_coeff(2);
+ } else if (!strcmp(model,"QuickTake 100")) {
+ fseek (ifp, 544, SEEK_SET);
+ height = get2();
+ width = get2();
+ data_offset = (get4(),get2()) == 30 ? 738:736;
+ if (height > width) {
+ SWAP(height,width);
+ fseek (ifp, data_offset-6, SEEK_SET);
+ flip = ~get2() & 3 ? 5:6;
+ }
+ load_raw = &CLASS quicktake_100_load_raw;
+ filters = 0x61616161;
+ } else if (!strcmp(model,"QuickTake 150")) {
+ data_offset = 738 - head[5];
+ if (head[5]) strcpy (model+10, "200");
+ load_raw = &CLASS kodak_radc_load_raw;
+ height = 480;
+ width = 640;
+ filters = 0x61616161;
+ } else if (!strcmp(make,"Rollei") && !load_raw) {
+ switch (raw_width) {
+ case 1316:
+ height = 1030;
+ width = 1300;
+ top_margin = 1;
+ left_margin = 6;
+ break;
+ case 2568:
+ height = 1960;
+ width = 2560;
+ top_margin = 2;
+ left_margin = 8;
+ }
+ filters = 0x16161616;
+ load_raw = &CLASS rollei_load_raw;
+ pre_mul[0] = 1.8;
+ pre_mul[2] = 1.3;
+ } else if (!strcmp(model,"PC-CAM 600")) {
+ height = 768;
+ data_offset = width = 1024;
+ filters = 0x49494949;
+ load_raw = &CLASS eight_bit_load_raw;
+ pre_mul[0] = 1.14;
+ pre_mul[2] = 2.73;
+ } else if (!strcmp(model,"QV-2000UX")) {
+ height = 1208;
+ width = 1632;
+ data_offset = width * 2;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (fsize == 3217760) {
+ height = 1546;
+ width = 2070;
+ raw_width = 2080;
+ load_raw = &CLASS eight_bit_load_raw;
+ } else if (!strcmp(model,"QV-4000")) {
+ height = 1700;
+ width = 2260;
+ load_raw = &CLASS unpacked_load_raw;
+ maximum = 0xffff;
+ } else if (!strcmp(model,"QV-5700")) {
+ height = 1924;
+ width = 2576;
+ load_raw = &CLASS casio_qv5700_load_raw;
+ } else if (!strcmp(model,"QV-R41")) {
+ height = 1720;
+ width = 2312;
+ raw_width = 3520;
+ left_margin = 2;
+ } else if (!strcmp(model,"QV-R51")) {
+ height = 1926;
+ width = 2580;
+ raw_width = 3904;
+ pre_mul[0] = 1.340;
+ pre_mul[2] = 1.672;
+ } else if (!strcmp(model,"EX-S100")) {
+ height = 1544;
+ width = 2058;
+ raw_width = 3136;
+ pre_mul[0] = 1.631;
+ pre_mul[2] = 1.106;
+ } else if (!strcmp(model,"EX-Z50")) {
+ height = 1931;
+ width = 2570;
+ raw_width = 3904;
+ pre_mul[0] = 2.529;
+ pre_mul[2] = 1.185;
+ } else if (!strcmp(model,"EX-Z55")) {
+ height = 1960;
+ width = 2570;
+ raw_width = 3904;
+ pre_mul[0] = 1.520;
+ pre_mul[2] = 1.316;
+ } else if (!strcmp(model,"EX-P505")) {
+ height = 1928;
+ width = 2568;
+ raw_width = 3852;
+ maximum = 0xfff;
+ pre_mul[0] = 2.07;
+ pre_mul[2] = 1.88;
+ } else if (fsize == 9313536) { /* EX-P600 or QV-R61 */
+ height = 2142;
+ width = 2844;
+ raw_width = 4288;
+ pre_mul[0] = 1.797;
+ pre_mul[2] = 1.219;
+ } else if (!strcmp(model,"EX-P700")) {
+ height = 2318;
+ width = 3082;
+ raw_width = 4672;
+ pre_mul[0] = 1.758;
+ pre_mul[2] = 1.504;
+ }
+ if (!model[0])
+ sprintf (model, "%dx%d", width, height);
+ if (filters == UINT_MAX) filters = 0x94949494;
+ if (raw_color) adobe_coeff (make, model);
+ if (thumb_offset && !thumb_height) {
+ fseek (ifp, thumb_offset, SEEK_SET);
+ if (ljpeg_start (&jh, 1)) {
+ thumb_width = jh.wide;
+ thumb_height = jh.high;
+ }
+ }
+dng_skip:
+ if (!load_raw || height < 22) is_raw = 0;
+#ifdef NO_JPEG
+ if (load_raw == &CLASS kodak_jpeg_load_raw) {
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("%s: You must link dcraw with libjpeg!!\n"), ifname);
+#endif
+ is_raw = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB;
+#endif
+ }
+#endif
+ if (!cdesc[0])
+ strcpy (cdesc, colors == 3 ? "RGB":"GMCY");
+ if (!raw_height) raw_height = height;
+ if (!raw_width ) raw_width = width;
+ if (filters && colors == 3)
+ for (i=0; i < 32; i+=4) {
+ if ((filters >> i & 15) == 9)
+ filters |= 2 << i;
+ if ((filters >> i & 15) == 6)
+ filters |= 8 << i;
+ }
+notraw:
+ if (flip == -1) flip = tiff_flip;
+ if (flip == -1) flip = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2);
+#endif
+}
+#line 8372 "dcraw/dcraw.c"
+void CLASS convert_to_rgb()
+{
+ int row, col, c, i, j, k;
+ ushort *img;
+ float out[3], out_cam[3][4];
+ double num, inverse[3][3], bnd[2]={0,0};
+ static const double xyzd50_srgb[3][3] =
+ { { 0.436083, 0.385083, 0.143055 },
+ { 0.222507, 0.716888, 0.060608 },
+ { 0.013930, 0.097097, 0.714022 } };
+ static const double rgb_rgb[3][3] =
+ { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } };
+ static const double adobe_rgb[3][3] =
+ { { 0.715146, 0.284856, 0.000000 },
+ { 0.000000, 1.000000, 0.000000 },
+ { 0.000000, 0.041166, 0.958839 } };
+ static const double wide_rgb[3][3] =
+ { { 0.593087, 0.404710, 0.002206 },
+ { 0.095413, 0.843149, 0.061439 },
+ { 0.011621, 0.069091, 0.919288 } };
+ static const double prophoto_rgb[3][3] =
+ { { 0.529317, 0.330092, 0.140588 },
+ { 0.098368, 0.873465, 0.028169 },
+ { 0.016879, 0.117663, 0.865457 } };
+ static const double (*out_rgb[])[3] =
+ { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb };
+ static const char *name[] =
+ { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ" };
+ static const unsigned phead[] =
+ { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0,
+ 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d };
+ unsigned pbody[] =
+ { 10, 0x63707274, 0, 36, /* cprt */
+ 0x64657363, 0, 40, /* desc */
+ 0x77747074, 0, 20, /* wtpt */
+ 0x626b7074, 0, 20, /* bkpt */
+ 0x72545243, 0, 14, /* rTRC */
+ 0x67545243, 0, 14, /* gTRC */
+ 0x62545243, 0, 14, /* bTRC */
+ 0x7258595a, 0, 20, /* rXYZ */
+ 0x6758595a, 0, 20, /* gXYZ */
+ 0x6258595a, 0, 20 }; /* bXYZ */
+ static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc };
+ unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 };
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,0,2);
+#endif
+
+ bnd[gamm[1] >= 1] = 1;
+ if (gamm[1] && (gamm[1]-1)*(gamm[0]-1) <= 0) {
+ for (i=0; i < 36; i++) {
+ gamm[2] = (bnd[0] + bnd[1])/2;
+ bnd[(pow(gamm[2]/gamm[1],-gamm[0])-1)/gamm[0]-1/gamm[2] > -1] = gamm[2];
+ }
+ gamm[3] = gamm[2]*(1/gamm[0]-1);
+ gamm[2] /= gamm[1];
+ }
+ gamm[4] = 1 / (gamm[1]/2*SQR(gamm[2]) - gamm[3]*(1-gamm[2]) +
+ (1-pow(gamm[2],1+gamm[0]))*(1+gamm[3])/(1+gamm[0])) - 1;
+
+ memcpy (out_cam, rgb_cam, sizeof out_cam);
+ raw_color |= colors == 1 || document_mode ||
+ output_color < 1 || output_color > 5;
+ if (!raw_color) {
+ oprof = (unsigned *) calloc (phead[0], 1);
+ merror (oprof, "convert_to_rgb()");
+ memcpy (oprof, phead, sizeof phead);
+ if (output_color == 5) oprof[4] = oprof[5];
+ oprof[0] = 132 + 12*pbody[0];
+ for (i=0; i < pbody[0]; i++) {
+ oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874;
+ pbody[i*3+2] = oprof[0];
+ oprof[0] += (pbody[i*3+3] + 3) & -4;
+ }
+ memcpy (oprof+32, pbody, sizeof pbody);
+ oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1;
+ memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite);
+ if (output_bps == 8 | gamma_16bit)
+ pcurve[3] = (short)(256/gamm[4]+0.5) << 16;
+ for (i=4; i < 7; i++)
+ memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve);
+ pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3);
+ for (i=0; i < 3; i++)
+ for (j=0; j < 3; j++) {
+ for (num = k=0; k < 3; k++)
+ num += xyzd50_srgb[i][k] * inverse[j][k];
+ oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5;
+ }
+ for (i=0; i < phead[0]/4; i++)
+ oprof[i] = htonl(oprof[i]);
+ strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw");
+ strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]);
+ for (i=0; i < 3; i++)
+ for (j=0; j < colors; j++)
+ for (out_cam[i][j] = k=0; k < 3; k++)
+ out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j];
+ }
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr, raw_color ? _("Building histograms...\n") :
+ _("Converting to %s colorspace...\n"), name[output_color-1]);
+
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+ memset(histogram,0,sizeof(int)*LIBRAW_HISTOGRAM_SIZE*4);
+#else
+ memset (histogram, 0, sizeof histogram);
+#endif
+ for (img=image[0], row=0; row < height; row++)
+ for (col=0; col < width; col++, img+=4) {
+ if (!raw_color) {
+ out[0] = out[1] = out[2] = 0;
+ FORCC {
+ out[0] += out_cam[0][c] * img[c];
+ out[1] += out_cam[1][c] * img[c];
+ out[2] += out_cam[2][c] * img[c];
+ }
+ FORC3 img[c] = CLIP((int) out[c]);
+ }
+ else if (document_mode)
+ img[0] = img[FC(row,col)];
+ FORCC histogram[c][img[c] >> 3]++;
+ }
+ if (colors == 4 && output_color) colors = 3;
+ if (document_mode && filters) colors = 1;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,1,2);
+#endif
+}
+
+void CLASS fuji_rotate()
+{
+ int i, row, col;
+ double step;
+ float r, c, fr, fc;
+ unsigned ur, uc;
+ ushort wide, high, (*img)[4], (*pix)[4];
+
+ if (!fuji_width) return;
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr,_("Rotating image 45 degrees...\n"));
+#endif
+ fuji_width = (fuji_width - 1 + shrink) >> shrink;
+ step = sqrt(0.5);
+ wide = fuji_width / step;
+ high = (height - fuji_width) / step;
+ img = (ushort (*)[4]) calloc (wide*high, sizeof *img);
+ merror (img, "fuji_rotate()");
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,0,2);
+#endif
+
+ for (row=0; row < high; row++)
+ for (col=0; col < wide; col++) {
+ ur = r = fuji_width + (row-col)*step;
+ uc = c = (row+col)*step;
+ if (ur > height-2 || uc > width-2) continue;
+ fr = r - ur;
+ fc = c - uc;
+ pix = image + ur*width + uc;
+ for (i=0; i < colors; i++)
+ img[row*wide+col][i] =
+ (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) +
+ (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr;
+ }
+ free (image);
+ width = wide;
+ height = high;
+ image = img;
+ fuji_width = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,1,2);
+#endif
+}
+
+void CLASS stretch()
+{
+ ushort newdim, (*img)[4], *pix0, *pix1;
+ int row, col, c;
+ double rc, frac;
+
+ if (pixel_aspect == 1) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,0,2);
+#endif
+#ifdef DCRAW_VERBOSE
+ if (verbose) fprintf (stderr,_("Stretching the image...\n"));
+#endif
+ if (pixel_aspect < 1) {
+ newdim = height / pixel_aspect + 0.5;
+ img = (ushort (*)[4]) calloc (width*newdim, sizeof *img);
+ merror (img, "stretch()");
+ for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c*width];
+ if (c+1 < height) pix1 += width*4;
+ for (col=0; col < width; col++, pix0+=4, pix1+=4)
+ FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+ }
+ height = newdim;
+ } else {
+ newdim = width * pixel_aspect + 0.5;
+ img = (ushort (*)[4]) calloc (height*newdim, sizeof *img);
+ merror (img, "stretch()");
+ for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) {
+ frac = rc - (c = rc);
+ pix0 = pix1 = image[c];
+ if (c+1 < width) pix1 += 4;
+ for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4)
+ FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5;
+ }
+ width = newdim;
+ }
+ free (image);
+ image = img;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,1,2);
+#endif
+}
+
+int CLASS flip_index (int row, int col)
+{
+ if (flip & 4) SWAP(row,col);
+ if (flip & 2) row = iheight - 1 - row;
+ if (flip & 1) col = iwidth - 1 - col;
+ return row * iwidth + col;
+}
+
+void CLASS gamma_lut (ushort lut[0x10000])
+{
+ int perc, c, val, total, i;
+ float t_white=0, r;
+
+#ifdef LIBRAW_LIBRARY_BUILD
+ perc = width * height * imgdata.params.auto_bright_thr;
+#else
+ perc = width * height * 0.01; /* 99th percentile white level */
+#endif
+ if (fuji_width) perc /= 2;
+ if ((highlight & ~2) || no_auto_bright) perc = -1;
+ FORCC {
+ for (val=0x2000, total=0; --val > 32; )
+ if ((total += histogram[c][val]) > perc) break;
+ if (t_white < val) t_white = val;
+ }
+ t_white *= 8 / bright;
+ for (i=0; i < 0x10000; i++) {
+ r = i / t_white;
+ val = 65535 * ( !use_gamma ? r :
+ r <= gamm[2] ? r*gamm[1] : pow((double)r,gamm[0])*(1+gamm[3])-gamm[3]);
+ if (val > 65535) val = 65535;
+ lut[i] = val;
+ }
+}
+
+
+#line 8656 "dcraw/dcraw.c"
+void CLASS tiff_set (ushort *ntag,
+ ushort tag, ushort type, int count, int val)
+{
+ struct tiff_tag *tt;
+ int c;
+
+ tt = (struct tiff_tag *)(ntag+1) + (*ntag)++;
+ tt->tag = tag;
+ tt->type = type;
+ tt->count = count;
+ if (type < 3 && count <= 4)
+ FORC(4) tt->val.c[c] = val >> (c << 3);
+ else if (type == 3 && count <= 2)
+ FORC(2) tt->val.s[c] = val >> (c << 4);
+ else tt->val.i = val;
+}
+
+#define TOFF(ptr) ((char *)(&(ptr)) - (char *)th)
+
+void CLASS tiff_head (struct tiff_hdr *th, int full)
+{
+ int c, psize=0;
+ struct tm *t;
+
+ memset (th, 0, sizeof *th);
+ th->t_order = htonl(0x4d4d4949) >> 16;
+ th->magic = 42;
+ th->ifd = 10;
+ if (full) {
+ tiff_set (&th->ntag, 254, 4, 1, 0);
+ tiff_set (&th->ntag, 256, 4, 1, width);
+ tiff_set (&th->ntag, 257, 4, 1, height);
+ tiff_set (&th->ntag, 258, 3, colors, output_bps);
+ if (colors > 2)
+ th->tag[th->ntag-1].val.i = TOFF(th->bps);
+ FORC4 th->bps[c] = output_bps;
+ tiff_set (&th->ntag, 259, 3, 1, 1);
+ tiff_set (&th->ntag, 262, 3, 1, 1 + (colors > 1));
+ }
+ tiff_set (&th->ntag, 270, 2, 512, TOFF(th->t_desc));
+ tiff_set (&th->ntag, 271, 2, 64, TOFF(th->t_make));
+ tiff_set (&th->ntag, 272, 2, 64, TOFF(th->t_model));
+ if (full) {
+ if (oprof) psize = ntohl(oprof[0]);
+ tiff_set (&th->ntag, 273, 4, 1, sizeof *th + psize);
+ tiff_set (&th->ntag, 277, 3, 1, colors);
+ tiff_set (&th->ntag, 278, 4, 1, height);
+ tiff_set (&th->ntag, 279, 4, 1, height*width*colors*output_bps/8);
+ } else
+ tiff_set (&th->ntag, 274, 3, 1, "12435867"[flip]-'0');
+ tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0]));
+ tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2]));
+ tiff_set (&th->ntag, 284, 3, 1, 1);
+ tiff_set (&th->ntag, 296, 3, 1, 2);
+ tiff_set (&th->ntag, 305, 2, 32, TOFF(th->soft));
+ tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date));
+ tiff_set (&th->ntag, 315, 2, 64, TOFF(th->t_artist));
+ tiff_set (&th->ntag, 34665, 4, 1, TOFF(th->nexif));
+ if (psize) tiff_set (&th->ntag, 34675, 7, psize, sizeof *th);
+ tiff_set (&th->nexif, 33434, 5, 1, TOFF(th->rat[4]));
+ tiff_set (&th->nexif, 33437, 5, 1, TOFF(th->rat[6]));
+ tiff_set (&th->nexif, 34855, 3, 1, iso_speed);
+ tiff_set (&th->nexif, 37386, 5, 1, TOFF(th->rat[8]));
+ if (gpsdata[1]) {
+ tiff_set (&th->ntag, 34853, 4, 1, TOFF(th->ngps));
+ tiff_set (&th->ngps, 0, 1, 4, 0x202);
+ tiff_set (&th->ngps, 1, 2, 2, gpsdata[29]);
+ tiff_set (&th->ngps, 2, 5, 3, TOFF(th->gps[0]));
+ tiff_set (&th->ngps, 3, 2, 2, gpsdata[30]);
+ tiff_set (&th->ngps, 4, 5, 3, TOFF(th->gps[6]));
+ tiff_set (&th->ngps, 5, 1, 1, gpsdata[31]);
+ tiff_set (&th->ngps, 6, 5, 1, TOFF(th->gps[18]));
+ tiff_set (&th->ngps, 7, 5, 3, TOFF(th->gps[12]));
+ tiff_set (&th->ngps, 18, 2, 12, TOFF(th->gps[20]));
+ tiff_set (&th->ngps, 29, 2, 12, TOFF(th->gps[23]));
+ memcpy (th->gps, gpsdata, sizeof th->gps);
+ }
+ th->rat[0] = th->rat[2] = 300;
+ th->rat[1] = th->rat[3] = 1;
+ FORC(6) th->rat[4+c] = 1000000;
+ th->rat[4] *= shutter;
+ th->rat[6] *= aperture;
+ th->rat[8] *= focal_len;
+ strncpy (th->t_desc, desc, 512);
+ strncpy (th->t_make, make, 64);
+ strncpy (th->t_model, model, 64);
+ strcpy (th->soft, "dcraw v"VERSION);
+ t = gmtime (&timestamp);
+ sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d",
+ t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec);
+ strncpy (th->t_artist, artist, 64);
+}
+
+void CLASS jpeg_thumb_writer (FILE *tfp,char *t_humb,int t_humb_length)
+{
+ ushort exif[5];
+ struct tiff_hdr th;
+ fputc (0xff, tfp);
+ fputc (0xd8, tfp);
+ if (strcmp (t_humb+6, "Exif")) {
+ memcpy (exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons (8 + sizeof th);
+ fwrite (exif, 1, sizeof exif, tfp);
+ tiff_head (&th, 0);
+ fwrite (&th, 1, sizeof th, tfp);
+ }
+ fwrite (t_humb+2, 1, t_humb_length-2, tfp);
+}
+
+
+void CLASS jpeg_thumb (FILE *tfp)
+{
+ char *thumb;
+ ushort exif[5];
+ struct tiff_hdr th;
+
+ thumb = (char *) malloc (thumb_length);
+ merror (thumb, "jpeg_thumb()");
+ fread (thumb, 1, thumb_length, ifp);
+#if 0
+ fputc (0xff, tfp);
+ fputc (0xd8, tfp);
+ if (strcmp (thumb+6, "Exif")) {
+ memcpy (exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons (8 + sizeof th);
+ fwrite (exif, 1, sizeof exif, tfp);
+ tiff_head (&th, 0);
+ fwrite (&th, 1, sizeof th, tfp);
+ }
+ fwrite (thumb+2, 1, thumb_length-2, tfp);
+#else
+ jpeg_thumb_writer(tfp,thumb,thumb_length);
+#endif
+ free (thumb);
+}
+
+void CLASS write_ppm_tiff (FILE *ofp)
+{
+ struct tiff_hdr th;
+ uchar *ppm;
+ ushort *ppm2,lut16[0x10000];
+ int c, row, col, soff, rstep, cstep;
+
+ iheight = height;
+ iwidth = width;
+ if (flip & 4) SWAP(height,width);
+ ppm = (uchar *) calloc (width, colors*output_bps/8);
+ ppm2 = (ushort *) ppm;
+ merror (ppm, "write_ppm_tiff()");
+ if (output_tiff) {
+ tiff_head (&th, 1);
+ fwrite (&th, sizeof th, 1, ofp);
+ if (oprof)
+ fwrite (oprof, ntohl(oprof[0]), 1, ofp);
+ } else if (colors > 3)
+ fprintf (ofp,
+ "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n",
+ width, height, colors, (1 << output_bps)-1, cdesc);
+ else
+ fprintf (ofp, "P%d\n%d %d\n%d\n",
+ colors/2+5, width, height, (1 << output_bps)-1);
+
+ if (output_bps == 8 || gamma_16bit ) gamma_lut (lut16);
+
+ soff = flip_index (0, 0);
+ cstep = flip_index (0, 1) - soff;
+ rstep = flip_index (1, 0) - flip_index (0, width);
+ for (row=0; row < height; row++, soff += rstep) {
+ for (col=0; col < width; col++, soff += cstep)
+ if (output_bps == 8)
+ FORCC ppm [col*colors+c] = lut16[image[soff][c]]/256;
+ else if(gamma_16bit) FORCC ppm2[col*colors+c] = lut16[image[soff][c]];
+ else FORCC ppm2[col*colors+c] = image[soff][c];
+ if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa)
+ swab ((char*)ppm2, (char*)ppm2, width*colors*2);
+ fwrite (ppm, colors*output_bps/8, width, ofp);
+ }
+ free (ppm);
+}
diff --git a/Source/LibRawLite/internal/dcraw_fileio.cpp b/Source/LibRawLite/internal/dcraw_fileio.cpp
new file mode 100644
index 0000000..5106d31
--- /dev/null
+++ b/Source/LibRawLite/internal/dcraw_fileio.cpp
@@ -0,0 +1,215 @@
+/*
+ GENERATED FILE, DO NOT EDIT
+ Generated from dcraw/dcraw.c at Mon May 4 22:14:58 2009
+ Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+ for copyright information.
+*/
+
+#line 3621 "dcraw/dcraw.c"
+#define CLASS LibRaw::
+#include "libraw/libraw_types.h"
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+#include "internal/defines.h"
+#include "internal/var_defines.h"
+#line 3631 "dcraw/dcraw.c"
+
+/*
+ Seach from the current directory up to the root looking for
+ a ".badpixels" file, and fix those pixels now.
+ */
+void CLASS bad_pixels (char *fname)
+{
+ FILE *fp=0;
+ char *cp, line[128];
+ int len, time, row, col, r, c, rad, tot, n, fixed=0;
+
+ if (!filters) return;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,0,2);
+#endif
+ if (fname)
+ fp = fopen (fname, "r");
+#line 3674 "dcraw/dcraw.c"
+ if (!fp)
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP;
+#endif
+ return;
+ }
+ while (fgets (line, 128, fp)) {
+ cp = strchr (line, '#');
+ if (cp) *cp = 0;
+ if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue;
+ if ((unsigned) col >= width || (unsigned) row >= height) continue;
+ if (time > timestamp) continue;
+ for (tot=n=0, rad=1; rad < 3 && n==0; rad++)
+ for (r = row-rad; r <= row+rad; r++)
+ for (c = col-rad; c <= col+rad; c++)
+ if ((unsigned) r < height && (unsigned) c < width &&
+ (r != row || c != col) && fc(r,c) == fc(row,col)) {
+ tot += BAYER2(r,c);
+ n++;
+ }
+ BAYER2(row,col) = tot/n;
+#ifdef DCRAW_VERBOSE
+ if (verbose) {
+ if (!fixed++)
+ fprintf (stderr,_("Fixed dead pixels at:"));
+ fprintf (stderr, " %d,%d", col, row);
+ }
+#endif
+ }
+#ifdef DCRAW_VERBOSE
+ if (fixed) fputc ('\n', stderr);
+#endif
+ fclose (fp);
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,1,2);
+#endif
+}
+
+void CLASS subtract (char *fname)
+{
+ FILE *fp;
+ int dim[3]={0,0,0}, comment=0, number=0, error=0, nd=0, c, row, col;
+ ushort *pixel;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,0,2);
+#endif
+
+ if (!(fp = fopen (fname, "rb"))) {
+#ifdef DCRAW_VERBOSE
+ perror (fname);
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE;
+#endif
+ return;
+ }
+ if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1;
+ while (!error && nd < 3 && (c = fgetc(fp)) != EOF) {
+ if (c == '#') comment = 1;
+ if (c == '\n') comment = 0;
+ if (comment) continue;
+ if (isdigit(c)) number = 1;
+ if (number) {
+ if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0';
+ else if (isspace(c)) {
+ number = 0; nd++;
+ } else error = 1;
+ }
+ }
+ if (error || nd < 3) {
+ fprintf (stderr,_("%s is not a valid PGM file!\n"), fname);
+ fclose (fp); return;
+ } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) {
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("%s has the wrong dimensions!\n"), fname);
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM;
+#endif
+ fclose (fp); return;
+ }
+ pixel = (ushort *) calloc (width, sizeof *pixel);
+ merror (pixel, "subtract()");
+ for (row=0; row < height; row++) {
+ fread (pixel, 2, width, fp);
+ for (col=0; col < width; col++)
+ BAYER(row,col) = MAX (BAYER(row,col) - ntohs(pixel[col]), 0);
+ }
+ free (pixel);
+ black = 0;
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,1,2);
+#endif
+}
+#line 8283 "dcraw/dcraw.c"
+
+#ifndef NO_LCMS
+void CLASS apply_profile (char *input, char *output)
+{
+ char *prof;
+ cmsHPROFILE hInProfile=0, hOutProfile=0;
+ cmsHTRANSFORM hTransform;
+ FILE *fp;
+ unsigned size;
+
+ cmsErrorAction (LCMS_ERROR_SHOW);
+ if (strcmp (input, "embed"))
+ hInProfile = cmsOpenProfileFromFile (input, "r");
+ else if (profile_length) {
+#ifndef LIBRAW_LIBRARY_BUILD
+ prof = (char *) malloc (profile_length);
+ merror (prof, "apply_profile()");
+ fseek (ifp, profile_offset, SEEK_SET);
+ fread (prof, 1, profile_length, ifp);
+ hInProfile = cmsOpenProfileFromMem (prof, profile_length);
+ free (prof);
+#else
+ hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length);
+#endif
+ } else
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE;
+#endif
+#ifdef DCRAW_VERBOSE
+ fprintf (stderr,_("%s has no embedded profile.\n"), ifname);
+#endif
+ }
+ if (!hInProfile)
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE;
+#endif
+ return;
+ }
+ if (!output)
+ hOutProfile = cmsCreate_sRGBProfile();
+ else if ((fp = fopen (output, "rb"))) {
+ fread (&size, 4, 1, fp);
+ fseek (fp, 0, SEEK_SET);
+ oprof = (unsigned *) malloc (size = ntohl(size));
+ merror (oprof, "apply_profile()");
+ fread (oprof, 1, size, fp);
+ fclose (fp);
+ if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) {
+ free (oprof);
+ oprof = 0;
+ }
+#ifdef DCRAW_VERBOSE
+ } else
+ fprintf (stderr,_("Cannot open file %s!\n"), output);
+#else
+}
+#endif
+ if (!hOutProfile)
+ {
+#ifdef LIBRAW_LIBRARY_BUILD
+ imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE;
+#endif
+ goto quit;
+ }
+#ifdef DCRAW_VERBOSE
+ if (verbose)
+ fprintf (stderr,_("Applying color profile...\n"));
+#endif
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2);
+#endif
+ hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16,
+ hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0);
+ cmsDoTransform (hTransform, image, image, width*height);
+ raw_color = 1; /* Don't use rgb_cam with a profile */
+ cmsDeleteTransform (hTransform);
+ cmsCloseProfile (hOutProfile);
+quit:
+ cmsCloseProfile (hInProfile);
+#ifdef LIBRAW_LIBRARY_BUILD
+ RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2);
+#endif
+}
+#endif
diff --git a/Source/LibRawLite/internal/defines.h b/Source/LibRawLite/internal/defines.h
new file mode 100644
index 0000000..c48bb32
--- /dev/null
+++ b/Source/LibRawLite/internal/defines.h
@@ -0,0 +1,131 @@
+/*
+ GENERATED FILE, DO NOT EDIT
+ Generated from dcraw/dcraw.c at Mon May 4 22:14:56 2009
+ Look into original file (probably http://cybercom.net/~dcoffin/dcraw/dcraw.c)
+ for copyright information.
+*/
+
+#line 28 "dcraw/dcraw.c"
+#define NO_JPEG
+#line 33 "dcraw/dcraw.c"
+#define VERSION "8.93"
+
+#define _GNU_SOURCE
+#define _USE_MATH_DEFINES
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+/*
+ NO_JPEG disables decoding of compressed Kodak DC120 files.
+ NO_LCMS disables the "-p" option.
+ */
+#ifndef NO_JPEG
+#include <jpeglib.h>
+#endif
+#ifndef NO_LCMS
+#include <lcms.h>
+#endif
+#ifdef LOCALEDIR
+#include <libintl.h>
+#define _(String) gettext(String)
+#else
+#define _(String) (String)
+#endif
+#line 73 "dcraw/dcraw.c"
+#ifdef __CYGWIN__
+#include <io.h>
+#endif
+#ifdef WIN32
+#include <sys/utime.h>
+#include <winsock2.h>
+#pragma comment(lib, "ws2_32.lib")
+#define snprintf _snprintf
+#define strcasecmp _stricmp
+#define strncasecmp strnicmp
+typedef __int64 INT64;
+typedef unsigned __int64 UINT64;
+#else
+#include <unistd.h>
+#include <utime.h>
+#include <netinet/in.h>
+typedef long long INT64;
+typedef unsigned long long UINT64;
+#endif
+
+#ifdef LJPEG_DECODE
+#error Please compile dcraw.c by itself.
+#error Do not link it with ljpeg_decode.
+#endif
+
+#ifndef LONG_BIT
+#define LONG_BIT (8 * sizeof (long))
+#endif
+#line 167 "dcraw/dcraw.c"
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORC3 FORC(3)
+#define FORC4 FORC(4)
+#define FORCC FORC(colors)
+
+#define SQR(x) ((x)*(x))
+#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+/*
+ In order to inline this calculation, I make the risky
+ assumption that all filter patterns can be described
+ by a repeating pattern of eight rows and two columns
+
+ Do not use the FC or BAYER macros with the Leaf CatchLight,
+ because its pattern is 16x16, not 2x8.
+
+ Return values are either 0/1/2/3 = G/M/C/Y or 0/1/2/3 = R/G1/B/G2
+
+ PowerShot 600 PowerShot A50 PowerShot Pro70 Pro90 & G1
+ 0xe1e4e1e4: 0x1b4e4b1e: 0x1e4b4e1b: 0xb4b4b4b4:
+
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 G M G M G M 0 C Y C Y C Y 0 Y C Y C Y C 0 G M G M G M
+ 1 C Y C Y C Y 1 M G M G M G 1 M G M G M G 1 Y C Y C Y C
+ 2 M G M G M G 2 Y C Y C Y C 2 C Y C Y C Y
+ 3 C Y C Y C Y 3 G M G M G M 3 G M G M G M
+ 4 C Y C Y C Y 4 Y C Y C Y C
+ PowerShot A5 5 G M G M G M 5 G M G M G M
+ 0x1e4e1e4e: 6 Y C Y C Y C 6 C Y C Y C Y
+ 7 M G M G M G 7 M G M G M G
+ 0 1 2 3 4 5
+ 0 C Y C Y C Y
+ 1 G M G M G M
+ 2 C Y C Y C Y
+ 3 M G M G M G
+
+ All RGB cameras use one of these Bayer grids:
+
+ 0x16161616: 0x61616161: 0x49494949: 0x94949494:
+
+ 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5
+ 0 B G B G B G 0 G R G R G R 0 G B G B G B 0 R G R G R G
+ 1 G R G R G R 1 B G B G B G 1 R G R G R G 1 G B G B G B
+ 2 B G B G B G 2 G R G R G R 2 G B G B G B 2 R G R G R G
+ 3 G R G R G R 3 B G B G B G 3 R G R G R G 3 G B G B G B
+ */
+
+#line 225 "dcraw/dcraw.c"
+#define BAYER(row,col) \
+ image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)]
+
+#define BAYER2(row,col) \
+ image[((row) >> shrink)*iwidth + ((col) >> shrink)][fc(row,col)]
diff --git a/Source/LibRawLite/internal/libraw_internal_funcs.h b/Source/LibRawLite/internal/libraw_internal_funcs.h
new file mode 100644
index 0000000..17cca66
--- /dev/null
+++ b/Source/LibRawLite/internal/libraw_internal_funcs.h
@@ -0,0 +1,198 @@
+/* -*- C++ -*-
+ * File: libraw_internal_funcs.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 14, 2008
+ *
+ * LibRaw-Lite internal data structures (not visible outside)
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+
+#ifndef _LIBRAW_INTERNAL_FUNCS_H
+#define _LIBRAW_INTERNAL_FUNCS_H
+
+#ifndef LIBRAW_LIBRARY_BUILD
+#error "This file should be used only for libraw library build"
+#else
+// inline functions
+ ushort sget2 (uchar *s);
+ ushort get2();
+ unsigned sget4 (uchar *s);
+ unsigned getint (int type);
+ float int_to_float (int i);
+ double getreal (int type);
+ void read_shorts (ushort *pixel, int count);
+
+// Canon P&S cameras
+ void canon_600_fixed_wb (int temp);
+ int canon_600_color (int ratio[2], int mar);
+ void canon_600_auto_wb();
+ void canon_600_coeff();
+ void canon_600_load_raw();
+ int canon_s2is();
+ void canon_a5_load_raw();
+ void parse_ciff (int offset, int length);
+ void ciff_block_1030();
+
+// LJPEG decoder
+ unsigned getbits (int nbits);
+ void init_decoder();
+ uchar * make_decoder (const uchar *source, int level);
+ int ljpeg_start (struct jhead *jh, int info_only);
+ int ljpeg_diff (struct decode *dindex);
+ ushort * ljpeg_row (int jrow, struct jhead *jh);
+
+// Canon DSLRs
+ void crw_init_tables (unsigned table);
+ int canon_has_lowbits();
+ void canon_compressed_load_raw();
+ void lossless_jpeg_load_raw();
+ void canon_sraw_load_raw();
+ void canon_black(double *);
+// Adobe DNG
+ void adobe_copy_pixel (int row, int col, ushort **rp);
+ void adobe_dng_load_raw_lj();
+ void adobe_dng_load_raw_nc();
+
+// Pentax
+ void pentax_k10_load_raw();
+ void pentax_tree();
+
+// Nikon (and Minolta Z2)
+ void nikon_compressed_load_raw();
+ void nikon_load_raw();
+ int nikon_is_compressed();
+ int nikon_e995();
+ int nikon_e2100();
+ void nikon_3700();
+ int minolta_z2();
+ void nikon_e900_load_raw();
+ void nikon_e2100_load_raw();
+
+// Fuji
+ void fuji_load_raw();
+ void parse_fuji (int offset);
+
+
+
+
+// Rollei
+ void rollei_load_raw();
+ void parse_rollei();
+
+// MF backs
+ int bayer (unsigned row, unsigned col);
+ void phase_one_flat_field (int is_float, int nc);
+ void phase_one_correct();
+ void phase_one_load_raw();
+ unsigned ph1_bits (int nbits);
+ void phase_one_load_raw_c();
+ void hasselblad_load_raw();
+ void leaf_hdr_load_raw();
+ void sinar_4shot_load_raw();
+ void imacon_full_load_raw();
+ void packed_12_load_raw();
+ void unpacked_load_raw();
+ void parse_sinar_ia();
+ void parse_phase_one (int base);
+
+// Misc P&S cameras
+ void nokia_load_raw();
+ unsigned pana_bits (int nbits);
+ void panasonic_load_raw();
+ void olympus_e300_load_raw();
+ void olympus_e410_load_raw();
+ void olympus_cseries_load_raw();
+ void minolta_rd175_load_raw();
+ void casio_qv5700_load_raw();
+ void quicktake_100_load_raw();
+ const int* make_decoder_int (const int *source, int level);
+ int radc_token (int tree);
+ void kodak_radc_load_raw();
+ void kodak_jpeg_load_raw();
+ void kodak_dc120_load_raw();
+ void eight_bit_load_raw();
+ void smal_decode_segment (unsigned seg[2][2], int holes);
+ void smal_v6_load_raw();
+ int median4 (int *p);
+ void fill_holes (int holes);
+ void smal_v9_load_raw();
+ void parse_riff();
+ void parse_cine();
+ void parse_smal (int offset, int fsize);
+ int parse_jpeg (int offset);
+
+// Kodak
+ void kodak_262_load_raw();
+ int kodak_65000_decode (short *out, int bsize);
+ void kodak_65000_load_raw();
+ void kodak_rgb_load_raw();
+ void kodak_yrgb_load_raw();
+
+// It's a Sony (and K&M)
+ void sony_decrypt (unsigned *data, int len, int start, int key);
+ void sony_load_raw();
+ void sony_arw_load_raw();
+ void sony_arw2_load_raw();
+ void parse_minolta (int base);
+
+// Foveon/Sigma
+ void foveon_load_camf();
+ void foveon_load_raw();
+ const char* foveon_camf_param (const char *block, const char *param);
+ void * foveon_camf_matrix (unsigned dim[3], const char *name);
+ int foveon_fixed (void *ptr, int size, const char *name);
+ float foveon_avg (short *pix, int range[2], float cfilt);
+ short * foveon_make_curve (double max, double mul, double filt);
+ void foveon_make_curves(short **curvep, float dq[3], float div[3], float filt);
+ int foveon_apply_curve (short *curve, int i);
+ void foveon_interpolate();
+ char * foveon_gets (int offset, char *str, int len);
+ void parse_foveon();
+
+// CAM/RGB
+ void pseudoinverse (double (*in)[3], double (*out)[3], int size);
+ void cam_xyz_coeff (double cam_xyz[4][3]);
+ void adobe_coeff (const char *, const char *);
+ void simple_coeff (int index);
+
+
+// Tiff/Exif parsers
+ void tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save);
+ void parse_thumb_note (int base, unsigned toff, unsigned tlen);
+ void parse_makernote (int base, int uptag);
+ void parse_exif (int base);
+ void linear_table (unsigned len);
+ void parse_kodak_ifd (int base);
+ int parse_tiff_ifd (int base);
+ void parse_tiff (int base);
+ void parse_gps (int base);
+ void romm_coeff (float romm_cam[3][3]);
+ void parse_mos (int offset);
+ void get_timestamp (int reversed);
+
+// External JPEGs, what cameras uses it ?
+ void parse_external_jpeg();
+
+// The identify
+ short guess_byte_order (int words);
+
+// Tiff writer
+ void tiff_set (ushort *ntag, ushort tag, ushort type, int count, int val);
+ void tiff_head (struct tiff_hdr *th, int full);
+#endif
+
+#endif
diff --git a/Source/LibRawLite/internal/var_defines.h b/Source/LibRawLite/internal/var_defines.h
new file mode 100644
index 0000000..dc97381
--- /dev/null
+++ b/Source/LibRawLite/internal/var_defines.h
@@ -0,0 +1,179 @@
+/* -*- C++ -*-
+ * File: var_defines.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8, 2008
+ *
+ * LibRaw redefinitions of dcraw internal variables
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef VAR_DEFINES_H
+#define VAR_DEFINES_H
+
+// imgdata.idata
+#define make (imgdata.idata.make)
+#define model (imgdata.idata.model)
+#define is_raw (imgdata.idata.raw_count)
+#define dng_version (imgdata.idata.dng_version)
+#define is_foveon (imgdata.idata.is_foveon)
+#define colors (imgdata.idata.colors)
+#define cdesc (imgdata.idata.cdesc)
+#define filters (imgdata.idata.filters)
+
+//imgdata image
+#define image (imgdata.image)
+
+// imgdata.sizes
+#define raw_height (imgdata.sizes.raw_height)
+#define raw_width (imgdata.sizes.raw_width)
+#define height (imgdata.sizes.height)
+#define width (imgdata.sizes.width)
+#define top_margin (imgdata.sizes.top_margin)
+#define left_margin (imgdata.sizes.left_margin)
+#define bottom_margin (imgdata.sizes.bottom_margin)
+#define right_margin (imgdata.sizes.right_margin)
+#define iheight (imgdata.sizes.iheight)
+#define iwidth (imgdata.sizes.iwidth)
+#define pixel_aspect (imgdata.sizes.pixel_aspect)
+#define flip (imgdata.sizes.flip)
+
+//imgdata.color
+#define white (imgdata.color.white)
+#define cam_mul (imgdata.color.cam_mul)
+#define pre_mul (imgdata.color.pre_mul)
+#define cmatrix (imgdata.color.cmatrix)
+#define rgb_cam (imgdata.color.rgb_cam)
+#ifndef SRC_USES_CURVE
+#define curve (imgdata.color.curve)
+#endif
+#ifndef SRC_USES_BLACK
+#define black (imgdata.color.black)
+#endif
+#define maximum (imgdata.color.maximum)
+#define profile_length (imgdata.color.profile_length)
+#define color_flags (imgdata.color.color_flags)
+#define ph1 (imgdata.color.phase_one_data)
+#define flash_used (imgdata.color.flash_used)
+#define canon_ev (imgdata.color.canon_ev)
+#define model2 (imgdata.color.model2)
+
+//imgdata.thumbnail
+
+#define thumb_width (imgdata.thumbnail.twidth)
+#define thumb_height (imgdata.thumbnail.theight)
+#define thumb_length (imgdata.thumbnail.tlength)
+
+
+//imgdata.others
+#define iso_speed (imgdata.other.iso_speed)
+#define shutter (imgdata.other.shutter)
+#define aperture (imgdata.other.aperture)
+#define focal_len (imgdata.other.focal_len)
+#define timestamp (imgdata.other.timestamp)
+#define shot_order (imgdata.other.shot_order)
+#define gpsdata (imgdata.other.gpsdata)
+#define desc (imgdata.other.desc)
+#define artist (imgdata.other.artist)
+
+//imgdata.output
+#define greybox (imgdata.params.greybox)
+#define aber (imgdata.params.aber)
+#define gamm (imgdata.params.gamm)
+#define user_mul (imgdata.params.user_mul)
+#define shot_select (imgdata.params.shot_select)
+#define bright (imgdata.params.bright)
+#define threshold (imgdata.params.threshold)
+#define half_size (imgdata.params.half_size)
+#define four_color_rgb (imgdata.params.four_color_rgb)
+#define document_mode (imgdata.params.document_mode)
+#define highlight (imgdata.params.highlight)
+//#define verbose (imgdata.params.verbose)
+#define use_auto_wb (imgdata.params.use_auto_wb)
+#define use_camera_wb (imgdata.params.use_camera_wb)
+#define use_camera_matrix (imgdata.params.use_camera_matrix)
+#define output_color (imgdata.params.output_color)
+#define output_bps (imgdata.params.output_bps)
+#define gamma_16bit (imgdata.params.gamma_16bit)
+#define output_tiff (imgdata.params.output_tiff)
+#define med_passes (imgdata.params.med_passes)
+#define no_auto_bright (imgdata.params.no_auto_bright)
+#define use_fuji_rotate (imgdata.params.use_fuji_rotate)
+
+//rgb_constants
+#define xyz_rgb (rgb_constants.xyz_rgb)
+#define d65_white (rgb_constants.d65_white)
+
+//libraw_internal_data.internal_data
+#define meta_data (libraw_internal_data.internal_data.meta_data)
+#define ifp libraw_internal_data.internal_data.input
+#define ifname ((char*)libraw_internal_data.internal_data.input->fname())
+#define profile_offset (libraw_internal_data.internal_data.profile_offset)
+#define thumb_offset (libraw_internal_data.internal_data.toffset)
+
+//libraw_internal_data.internal_output_params
+#define mix_green (libraw_internal_data.internal_output_params.mix_green)
+#define raw_color (libraw_internal_data.internal_output_params.raw_color)
+#define use_gamma (libraw_internal_data.internal_output_params.use_gamma)
+#define zero_is_bad (libraw_internal_data.internal_output_params.zero_is_bad)
+#ifndef SRC_USES_SHRINK
+#define shrink (libraw_internal_data.internal_output_params.shrink)
+#endif
+#define fuji_width (libraw_internal_data.internal_output_params.fuji_width)
+
+
+//libraw_internal_data.output_data
+#define histogram (libraw_internal_data.output_data.histogram)
+#define oprof (libraw_internal_data.output_data.oprof)
+
+//libraw_internal_data.identify_data
+#define exif_cfa (libraw_internal_data.identify_data.olympus_exif_cfa)
+#define unique_id (libraw_internal_data.identify_data.unique_id)
+#define tiff_nifds (libraw_internal_data.identify_data.tiff_nifds)
+#define tiff_flip (libraw_internal_data.identify_data.tiff_flip)
+
+//libraw_internal_data.unpacker_data
+#define order (libraw_internal_data.unpacker_data.order)
+#define data_error (libraw_internal_data.unpacker_data.data_error)
+#define cr2_slice (libraw_internal_data.unpacker_data.cr2_slice)
+#define sraw_mul (libraw_internal_data.unpacker_data.sraw_mul)
+#define kodak_cbpp (libraw_internal_data.unpacker_data.kodak_cbpp)
+#define strip_offset (libraw_internal_data.unpacker_data.strip_offset)
+#define data_offset (libraw_internal_data.unpacker_data.data_offset)
+#define meta_offset (libraw_internal_data.unpacker_data.meta_offset)
+#define meta_length (libraw_internal_data.unpacker_data.meta_length)
+#define thumb_misc (libraw_internal_data.unpacker_data.thumb_misc)
+#define fuji_layout (libraw_internal_data.unpacker_data.fuji_layout)
+#define tiff_samples (libraw_internal_data.unpacker_data.tiff_samples)
+#define tiff_bps (libraw_internal_data.unpacker_data.tiff_bps)
+#define tiff_compress (libraw_internal_data.unpacker_data.tiff_compress)
+#define zero_after_ff (libraw_internal_data.unpacker_data.zero_after_ff)
+#define tile_width (libraw_internal_data.unpacker_data.tile_width)
+#define tile_length (libraw_internal_data.unpacker_data.tile_length)
+#define load_flags (libraw_internal_data.unpacker_data.load_flags)
+
+#ifdef LIBRAW_IO_REDEFINED
+#define fread(ptr,size,n,stream) stream->read(ptr,size,n)
+#define fseek(stream,o,w) stream->seek(o,w)
+#define fseeko(stream,o,w) stream->seek(o,w)
+#define ftell(stream) stream->tell()
+#define ftello(stream) stream->tell()
+#define getc(stream) stream->get_char()
+#define fgetc(stream) stream->get_char()
+#define fgets(str,n,stream) stream->gets(str,n)
+#define fscanf(stream,fmt,ptr) stream->scanf_one(fmt,ptr)
+#endif
+
+#endif
diff --git a/Source/LibRawLite/libraw/libraw.h b/Source/LibRawLite/libraw/libraw.h
new file mode 100644
index 0000000..57775c4
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw.h
@@ -0,0 +1,207 @@
+/* -*- C++ -*-
+ * File: libraw.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8, 2008
+ *
+ * LibRaw (Lite) C++ interface
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+
+#ifndef _LIBRAW_CLASS_H
+#define _LIBRAW_CLASS_H
+
+#include <limits.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#include "libraw_datastream.h"
+#include "libraw_types.h"
+#include "libraw_const.h"
+#include "libraw_internal.h"
+#include "libraw_alloc.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+DllDef const char *libraw_strerror(int errorcode);
+DllDef const char *libraw_strprogress(enum LibRaw_progress);
+ /* LibRaw C API */
+DllDef libraw_data_t *libraw_init(unsigned int flags);
+DllDef int libraw_open_file(libraw_data_t*, const char *);
+DllDef int libraw_open_buffer(libraw_data_t*, void * buffer, size_t size);
+DllDef int libraw_unpack(libraw_data_t*);
+DllDef int libraw_unpack_thumb(libraw_data_t*);
+DllDef void libraw_recycle(libraw_data_t*);
+DllDef void libraw_close(libraw_data_t*);
+ /* version helpers */
+DllDef const char* libraw_version();
+DllDef int libraw_versionNumber();
+ /* Camera list */
+DllDef const char** libraw_cameraList();
+DllDef int libraw_cameraCount();
+
+DllDef void libraw_set_memerror_handler(libraw_data_t*, memory_callback cb, void *datap);
+DllDef void libraw_set_dataerror_handler(libraw_data_t*,data_callback func,void *datap);
+DllDef void libraw_set_progress_handler(libraw_data_t*,progress_callback cb,void *datap);
+DllDef const char * libraw_unpack_function_name(libraw_data_t* lr);
+
+ /* DCRAW compatibility */
+DllDef int libraw_adjust_sizes_info_only(libraw_data_t*);
+DllDef int libraw_dcraw_document_mode_processing(libraw_data_t*);
+DllDef int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename);
+DllDef int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname);
+DllDef int libraw_dcraw_process(libraw_data_t* lr);
+DllDef libraw_processed_image_t* dcraw_make_mem_image(libraw_data_t* lr, int *errc);
+DllDef libraw_processed_image_t* dcraw_make_mem_thumb(libraw_data_t* lr, int *errc);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+
+class DllDef LibRaw
+{
+ public:
+ libraw_data_t imgdata;
+ int verbose;
+
+ LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE);
+
+ libraw_output_params_t* output_params_ptr() { return &imgdata.params;}
+ int open_file(const char *fname);
+ int open_buffer(void *buffer, size_t size);
+ int open_datastream(LibRaw_abstract_datastream *);
+ int unpack(void);
+ int unpack_thumb(void);
+
+ int adjust_sizes_info_only(void);
+ void set_memerror_handler( memory_callback cb,void *data) {callbacks.memcb_data = data; callbacks.mem_cb = cb; }
+ void set_dataerror_handler(data_callback func, void *data) { callbacks.datacb_data = data; callbacks.data_cb = func;}
+ void set_progress_handler(progress_callback pcb, void *data) { callbacks.progresscb_data = data; callbacks.progress_cb = pcb;}
+
+ /* helpers */
+ static const char* version() { return LIBRAW_VERSION_STR;}
+ static int versionNumber() { return LIBRAW_VERSION; }
+ static const char** cameraList();
+ static int cameraCount();
+ static const char* strprogress(enum LibRaw_progress);
+ static const char* strerror(int p) { return libraw_strerror(p);}
+ /* dcraw emulation */
+ int dcraw_document_mode_processing();
+ int dcraw_ppm_tiff_writer(const char *filename);
+ int dcraw_thumb_writer(const char *fname);
+ int dcraw_process(void);
+ /* memory writers */
+ libraw_processed_image_t* dcraw_make_mem_image(int *errcode=NULL);
+ libraw_processed_image_t* dcraw_make_mem_thumb(int *errcode=NULL);
+
+ /* free all internal data structures */
+ void recycle();
+ ~LibRaw(void) { recycle(); delete tls; }
+
+ int FC(int row,int col) { return (imgdata.idata.filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);}
+ int fc (int row, int col);
+ int add_masked_borders_to_bitmap();
+
+ const char *unpack_function_name();
+
+ private:
+ void* malloc(size_t t);
+ void* calloc(size_t n,size_t t);
+ void free(void *p);
+ void merror (void *ptr, const char *where);
+ void derror();
+
+ LibRaw_TLS *tls;
+ libraw_internal_data_t libraw_internal_data;
+ decode first_decode[2048], *second_decode, *free_decode;
+ tiff_ifd_t tiff_ifd[10];
+ libraw_memmgr memmgr;
+ libraw_callbacks_t callbacks;
+
+ LibRaw_constants rgb_constants;
+ void (LibRaw:: *write_thumb)(FILE *);
+ void (LibRaw:: *write_fun)(FILE *);
+ void (LibRaw:: *load_raw)();
+ void (LibRaw:: *thumb_load_raw)();
+
+ void kodak_thumb_loader();
+ void write_thumb_ppm_tiff(FILE *);
+
+ void identify();
+ void write_ppm_tiff (FILE *ofp);
+ void convert_to_rgb();
+ void kodak_ycbcr_load_raw();
+ void remove_zeroes();
+#ifndef NO_LCMS
+ void apply_profile(char*,char*);
+#endif
+ void pre_interpolate();
+ void border_interpolate (int border);
+ void lin_interpolate();
+ void vng_interpolate();
+ void ppg_interpolate();
+ void ahd_interpolate();
+
+ void bad_pixels(char*);
+ void subtract(char*);
+ void hat_transform (float *temp, float *base, int st, int size, int sc);
+ void wavelet_denoise();
+ void scale_colors();
+ void median_filter ();
+ void blend_highlights();
+ void recover_highlights();
+
+ void fuji_rotate();
+ void stretch();
+
+ void jpeg_thumb_writer (FILE *tfp,char *thumb,int thumb_length);
+ void jpeg_thumb (FILE *tfp);
+ void ppm_thumb (FILE *tfp);
+ void layer_thumb (FILE *tfp);
+ void rollei_thumb (FILE *tfp);
+ void kodak_thumb_load_raw();
+
+ unsigned get4();
+
+ int flip_index (int row, int col);
+ void gamma_lut(ushort lut[0x10000]);
+
+
+#ifdef LIBRAW_LIBRARY_BUILD
+#include "internal/libraw_internal_funcs.h"
+#endif
+
+};
+
+#ifdef LIBRAW_LIBRARY_BUILD
+#define RUN_CALLBACK(stage,iter,expect) if(callbacks.progress_cb) { \
+ int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,stage,iter,expect); \
+ if(rr!=0) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \
+ }
+#endif
+
+
+#endif /* __cplusplus */
+
+
+#endif /* _LIBRAW_CLASS_H */
diff --git a/Source/LibRawLite/libraw/libraw_alloc.h b/Source/LibRawLite/libraw/libraw_alloc.h
new file mode 100644
index 0000000..1d9877b
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_alloc.h
@@ -0,0 +1,96 @@
+/* -*- C++ -*-
+ * File: libraw_alloc.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 22, 2008
+ *
+ * LibRaw (Lite) allocator
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LIBRAW_ALLOC_H
+#define __LIBRAW_ALLOC_H
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef WIN32
+#define bzero(p,sz) memset(p,0,sz)
+#endif
+
+#ifdef __cplusplus
+
+#define MSIZE 32
+
+class libraw_memmgr
+{
+ public:
+ libraw_memmgr()
+ {
+ bzero(mems,sizeof(mems));
+ calloc_cnt=0;
+ }
+ void *malloc(size_t sz)
+ {
+ void *ptr = ::malloc(sz);
+ mem_ptr(ptr);
+ return ptr;
+ }
+ void *calloc(size_t n, size_t sz)
+ {
+ void *ptr = ::calloc(n,sz);
+ mem_ptr(ptr);
+ return ptr;
+ }
+ void free(void *ptr)
+ {
+ ::free(ptr);
+ forget_ptr(ptr);
+ }
+ void cleanup(void)
+ {
+ for(int i = 0; i< MSIZE; i++)
+ if(mems[i])
+ {
+ free(mems[i]);
+ mems[i] = NULL;
+ }
+ }
+
+ private:
+ void *mems[MSIZE];
+ int calloc_cnt;
+ void mem_ptr(void *ptr)
+ {
+ if(ptr)
+ for(int i=0;i < MSIZE; i++)
+ if(!mems[i])
+ {
+ mems[i] = ptr;
+ break;
+ }
+ }
+ void forget_ptr(void *ptr)
+ {
+ if(ptr)
+ for(int i=0;i < MSIZE; i++)
+ if(mems[i] == ptr)
+ mems[i] = NULL;
+ }
+
+};
+
+#endif /* C++ */
+
+#endif
diff --git a/Source/LibRawLite/libraw/libraw_const.h b/Source/LibRawLite/libraw/libraw_const.h
new file mode 100644
index 0000000..de520f1
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_const.h
@@ -0,0 +1,142 @@
+/* -*- C++ -*-
+ * File: libraw_const.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8 , 2008
+ *
+ * LibRaw (Lite) error codes
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LIBRAW_ERRORS_H
+#define _LIBRAW_ERRORS_H
+
+enum LibRaw_constructor_flags
+{
+ LIBRAW_OPTIONS_NONE =0,
+ LIBRAW_OPIONS_NO_MEMERR_CALLBACK=1,
+ LIBRAW_OPIONS_NO_DATAERR_CALLBACK=1<<1
+};
+
+enum LibRaw_warnings
+{
+ LIBRAW_WARN_NONE =0,
+ LIBRAW_WARN_BAD_CAMERA_WB =1<<2,
+ LIBRAW_WARN_NO_METADATA =1<<3,
+ LIBRAW_WARN_NO_JPEGLIB = 1<<4,
+ LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1<<5,
+ LIBRAW_WARN_NO_INPUT_PROFILE = 1<<6,
+ LIBRAW_WARN_BAD_OUTPUT_PROFILE= 1<<7,
+ LIBRAW_WARN_NO_BADPIXELMAP=1<<8,
+ LIBRAW_WARN_BAD_DARKFRAME_FILE=1<<9,
+ LIBRAW_WARN_BAD_DARKFRAME_DIM=1<<10
+};
+
+enum LibRaw_exceptions
+{
+ LIBRAW_EXCEPTION_NONE =0,
+ LIBRAW_EXCEPTION_ALLOC =1,
+ LIBRAW_EXCEPTION_DECODE_RAW =2,
+ LIBRAW_EXCEPTION_DECODE_JPEG=3,
+ LIBRAW_EXCEPTION_IO_EOF =4,
+ LIBRAW_EXCEPTION_IO_CORRUPT =5,
+ LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK=6
+};
+
+
+enum LibRaw_colorstate
+{
+ LIBRAW_COLORSTATE_UNKNOWN =0
+};
+
+enum LibRaw_filtering
+{
+ LIBRAW_FILTERING_DEFAULT =0
+};
+
+
+enum LibRaw_progress
+{
+ LIBRAW_PROGRESS_START = 0,
+ LIBRAW_PROGRESS_OPEN = 1,
+ LIBRAW_PROGRESS_IDENTIFY = 1<<1,
+ LIBRAW_PROGRESS_SIZE_ADJUST = 1<<2,
+ LIBRAW_PROGRESS_LOAD_RAW = 1<<3,
+ LIBRAW_PROGRESS_REMOVE_ZEROES = 1<<4,
+ LIBRAW_PROGRESS_BAD_PIXELS = 1<<5,
+ LIBRAW_PROGRESS_DARK_FRAME = 1<<6,
+ LIBRAW_PROGRESS_SCALE_COLORS = 1<<8,
+ LIBRAW_PROGRESS_PRE_INTERPOLATE = 1<<9,
+ LIBRAW_PROGRESS_INTERPOLATE = 1<<10,
+ LIBRAW_PROGRESS_MIX_GREEN = 1<<11,
+ LIBRAW_PROGRESS_MEDIAN_FILTER = 1<<12,
+ LIBRAW_PROGRESS_HIGHLIGHTS = 1<<13,
+ LIBRAW_PROGRESS_FUJI_ROTATE = 1<<14,
+ LIBRAW_PROGRESS_FLIP = 1<<15,
+ LIBRAW_PROGRESS_APPLY_PROFILE = 1<<16,
+ LIBRAW_PROGRESS_CONVERT_RGB = 1<<17,
+ LIBRAW_PROGRESS_STRETCH = 1<<18,
+/* reserved */
+ LIBRAW_PROGRESS_STAGE19 = 1<<19,
+ LIBRAW_PROGRESS_STAGE20 = 1<<20,
+ LIBRAW_PROGRESS_STAGE21 = 1<<21,
+ LIBRAW_PROGRESS_STAGE22 = 1<<22,
+ LIBRAW_PROGRESS_STAGE23 = 1<<23,
+ LIBRAW_PROGRESS_STAGE24 = 1<<24,
+ LIBRAW_PROGRESS_STAGE25 = 1<<25,
+ LIBRAW_PROGRESS_STAGE26 = 1<<26,
+ LIBRAW_PROGRESS_STAGE27 = 1<<27,
+
+ LIBRAW_PROGRESS_THUMB_LOAD = 1<<28,
+ LIBRAW_PROGRESS_TRESERVED1 = 1<<29,
+ LIBRAW_PROGRESS_TRESERVED2 = 1<<30,
+ LIBRAW_PROGRESS_TRESERVED3 = 1<<31
+};
+#define LIBRAW_PROGRESS_THUMB_MASK 0x0fffffff
+
+enum LibRaw_errors
+{
+ LIBRAW_SUCCESS = 0,
+ LIBRAW_UNSPECIFIED_ERROR=-1,
+ LIBRAW_FILE_UNSUPPORTED = -2,
+ LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE=-3,
+ LIBRAW_OUT_OF_ORDER_CALL=-4,
+ LIBRAW_NO_THUMBNAIL=-5,
+ LIBRAW_UNSUPPORTED_THUMBNAIL=-6,
+ LIBRAW_CANNOT_ADDMASK=-7,
+ LIBRAW_UNSUFFICIENT_MEMORY=-100007,
+ LIBRAW_DATA_ERROR=-100008,
+ LIBRAW_IO_ERROR=-100009,
+ LIBRAW_CANCELLED_BY_CALLBACK=-100010
+};
+
+#define LIBRAW_FATAL_ERROR(ec) ((ec)<-100000)
+
+enum LibRaw_thumbnail_formats
+{
+ LIBRAW_THUMBNAIL_UNKNOWN=0,
+ LIBRAW_THUMBNAIL_JPEG=1,
+ LIBRAW_THUMBNAIL_BITMAP=2,
+ LIBRAW_THUMBNAIL_LAYER=4,
+ LIBRAW_THUMBNAIL_ROLLEI=5
+};
+
+enum LibRaw_image_formats
+{
+ LIBRAW_IMAGE_BITMAP=1,
+ LIBRAW_IMAGE_JPEG=2
+};
+
+#endif
diff --git a/Source/LibRawLite/libraw/libraw_datastream.h b/Source/LibRawLite/libraw/libraw_datastream.h
new file mode 100644
index 0000000..d176573
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_datastream.h
@@ -0,0 +1,300 @@
+/* -*- C -*-
+ * File: libraw_datastream.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sun Jan 18 13:07:35 2009
+ *
+ * LibRaw (Lite) Data stream interface
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __LIBRAW_DATASTREAM_H
+#define __LIBRAW_DATASTREAM_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <string.h>
+
+#ifndef __cplusplus
+
+struct LibRaw_abstract_datastream;
+
+#else /* __cplusplus */
+
+#include "libraw_const.h"
+
+class LibRaw_buffer_datastream;
+
+class LibRaw_abstract_datastream
+{
+ public:
+ LibRaw_abstract_datastream(){substream=0;};
+ virtual ~LibRaw_abstract_datastream(void){if(substream) delete substream;}
+ virtual int valid(){return 0;}
+ virtual int read(void *,size_t, size_t ){ return -1;}
+ virtual int seek(off_t o, int whence){return -1;}
+ virtual int tell(){return -1;}
+ virtual int get_char(){return -1;}
+ virtual char* gets(char *, int){ return NULL;}
+ virtual int scanf_one(const char *, void *){return -1;}
+ virtual int eof(){return -1;}
+
+ virtual const char* fname(){ return NULL;};
+ virtual int subfile_open(const char*){ return EINVAL;}
+ virtual void subfile_close(){}
+ virtual int tempbuffer_open(void*, size_t);
+ virtual void tempbuffer_close()
+ {
+ if(substream) delete substream;
+ substream = NULL;
+ }
+
+ protected:
+ LibRaw_abstract_datastream *substream;
+};
+
+
+class LibRaw_file_datastream : public LibRaw_abstract_datastream
+{
+ public:
+ LibRaw_file_datastream(const char *fname)
+ {
+ if(fname)
+ {filename = fname; f = fopen(fname,"rb");}
+ else
+ {filename=0;f=0;}
+ sav=0;
+ }
+
+ virtual ~LibRaw_file_datastream() {if(f)fclose(f); if(sav)fclose(sav);}
+
+ virtual int valid() { return f?1:0;}
+
+#define CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0)
+ virtual int read(void * ptr,size_t size, size_t nmemb)
+ {
+ CHK();
+ return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f));
+ }
+ virtual int eof()
+ {
+ CHK();
+ return substream?substream->eof():feof(f);
+ }
+ virtual int seek(off_t o, int whence)
+ {
+ CHK();
+ return substream?substream->seek(o,whence):fseek(f,o,whence);
+ }
+ virtual int tell()
+ {
+ CHK();
+ return substream?substream->tell():ftell(f);
+ }
+ virtual int get_char()
+ {
+ CHK();
+ return substream?substream->get_char():fgetc(f);
+ }
+ virtual char* gets(char *str, int sz)
+ {
+ CHK();
+ return substream?substream->gets(str,sz):fgets(str,sz,f);
+ }
+ virtual int scanf_one(const char *fmt, void*val)
+ {
+ CHK();
+ return substream?substream->scanf_one(fmt,val):fscanf(f,fmt,val);
+ }
+
+ virtual const char *fname() { return filename; }
+
+ virtual int subfile_open(const char *fn)
+ {
+ if(sav) return EBUSY;
+ sav = f;
+ f = fopen(fn,"rb");
+ if(!f)
+ {
+ f = sav;
+ sav = NULL;
+ return ENOENT;
+ }
+ else
+ return 0;
+ }
+ virtual void subfile_close()
+ {
+ if(!sav) return;
+ fclose(f);
+ f = sav;
+ sav = 0;
+ }
+
+ private:
+ FILE *f,*sav;
+ const char *filename;
+};
+#undef CHK
+
+class LibRaw_buffer_datastream : public LibRaw_abstract_datastream
+{
+ public:
+ LibRaw_buffer_datastream(void *buffer, size_t bsize)
+ {
+ buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize;
+ }
+ virtual ~LibRaw_buffer_datastream(){}
+ virtual int valid() { return buf?1:0;}
+ virtual int read(void * ptr,size_t sz, size_t nmemb)
+ {
+ if(substream) return substream->read(ptr,sz,nmemb);
+ size_t to_read = sz*nmemb;
+ if(to_read > streamsize - streampos)
+ to_read = streamsize-streampos;
+ if(to_read<1)
+ return 0;
+ memmove(ptr,buf+streampos,to_read);
+ streampos+=to_read;
+ return int((to_read+sz-1)/sz);
+ }
+
+ virtual int eof()
+ {
+ if(substream) return substream->eof();
+ return streampos >= streamsize;
+ }
+
+ virtual int seek(off_t o, int whence)
+ {
+ if(substream) return substream->seek(o,whence);
+ switch(whence)
+ {
+ case SEEK_SET:
+ if(o<0)
+ streampos = 0;
+ else if (size_t(o) > streamsize)
+ streampos = streamsize;
+ else
+ streampos = size_t(o);
+ return 0;
+ case SEEK_CUR:
+ if(o<0)
+ {
+ if(size_t(-o) >= streampos)
+ streampos = 0;
+ else
+ streampos += o;
+ }
+ else if (o>0)
+ {
+ if(o+streampos> streamsize)
+ streampos = streamsize;
+ else
+ streampos += o;
+ }
+ return 0;
+ case SEEK_END:
+ if(o>0)
+ streampos = streamsize;
+ else if ( size_t(-o) > streamsize)
+ streampos = 0;
+ else
+ streampos = streamsize+o;
+ return 0;
+ default:
+ return 0;
+ }
+ }
+
+ virtual int tell()
+ {
+ if(substream) return substream->tell();
+ return int(streampos);
+ }
+
+ virtual int get_char()
+ {
+ if(substream) return substream->get_char();
+ if(streampos>=streamsize)
+ return -1;
+ return buf[streampos++];
+ }
+ virtual char* gets(char *s, int sz)
+ {
+ if (substream) return substream->gets(s,sz);
+ unsigned char *psrc,*pdest,*str;
+ str = (unsigned char *)s;
+ psrc = buf+streampos;
+ pdest = str;
+ while ( (size_t(psrc - buf) < streamsize)
+ &&
+ ((pdest-str)<sz)
+ )
+ {
+ *pdest = *psrc;
+ if(*psrc == '\n')
+ break;
+ psrc++;
+ pdest++;
+ }
+ if(size_t(psrc-buf) < streamsize)
+ psrc++;
+ if((pdest-str)<sz)
+ *(++pdest)=0;
+ streampos = psrc - buf;
+ return s;
+ }
+ virtual int scanf_one(const char *fmt, void* val)
+ {
+ if(substream) return substream->scanf_one(fmt,val);
+ int scanf_res;
+ if(streampos>streamsize) return 0;
+ scanf_res = sscanf((char*)(buf+streampos),fmt,val);
+ if(scanf_res>0)
+ {
+ int xcnt=0;
+ while(streampos<streamsize)
+ {
+ streampos++;
+ xcnt++;
+ if(buf[streampos] == 0
+ || buf[streampos]==' '
+ || buf[streampos]=='\t'
+ || buf[streampos]=='\n'
+ || xcnt>24)
+ break;
+ }
+ }
+ return scanf_res;
+ }
+ private:
+ unsigned char *buf;
+ size_t streampos,streamsize;
+};
+
+inline int LibRaw_abstract_datastream::tempbuffer_open(void *buf, size_t size)
+{
+ if(substream) return EBUSY;
+ substream = new LibRaw_buffer_datastream(buf,size);
+ return substream?0:EINVAL;
+}
+
+
+#endif
+
+#endif
+
diff --git a/Source/LibRawLite/libraw/libraw_internal.h b/Source/LibRawLite/libraw/libraw_internal.h
new file mode 100644
index 0000000..7294f3f
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_internal.h
@@ -0,0 +1,234 @@
+/* -*- C++ -*-
+ * File: libraw_internal.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8 , 2008
+ *
+ * LibRaw (Lite) internal data structures (not visible outside)
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LIBRAW_INTERNAL_TYPES_H
+#define _LIBRAW_INTERNAL_TYPES_H
+
+#include <stdio.h>
+#ifdef __cplusplus
+
+
+#ifndef CLASS
+#define CLASS LibRaw::
+#endif
+
+#else
+#ifndef CLASS
+#define CLASS
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include "libraw_datastream.h"
+
+class LibRaw_TLS
+{
+public:
+ struct
+ {
+ unsigned bitbuf;
+ int vbits, reset;
+ }getbits;
+ struct
+ {
+ UINT64 bitbuf;
+ int vbits;
+
+ }ph1_bits;
+ int make_decoder_leaf;
+ struct
+ {
+ struct decode *dstart[18], *dindex;
+ const int *s;
+ }radc_token;
+ struct
+ {
+ unsigned pad[128], p;
+ }sony_decrypt;
+ uchar jpeg_buffer[4096];
+ struct
+ {
+ uchar buf[0x4000];
+ int vbits, padding;
+ }pana_bits;
+
+ void init()
+ {
+ getbits.bitbuf = 0; getbits.vbits = getbits.reset = 0;
+ ph1_bits.bitbuf = 0; ph1_bits.vbits = 0;
+ pana_bits.vbits = 0;
+ }
+};
+
+
+class LibRaw_constants
+{
+ public:
+ static const float d65_white[3];
+ static const double xyz_rgb[3][3];
+};
+#endif /* __cplusplus */
+
+#ifdef WIN32
+typedef long off_t;
+#endif
+
+typedef struct
+{
+#ifndef __cplusplus
+ struct
+#endif
+ LibRaw_abstract_datastream *input;
+ int input_internal;
+ char *meta_data;
+ off_t profile_offset;
+ off_t toffset;
+
+} internal_data_t;
+
+typedef struct
+{
+ unsigned mix_green;
+ unsigned raw_color;
+ unsigned use_gamma;
+ unsigned zero_is_bad;
+ ushort shrink;
+ ushort fuji_width;
+} internal_output_params_t;
+
+#define LIBRAW_HISTOGRAM_SIZE 0x2000
+typedef struct
+{
+ int (*histogram)[LIBRAW_HISTOGRAM_SIZE];
+ unsigned *oprof;
+} output_data_t;
+
+typedef struct
+{
+ unsigned olympus_exif_cfa;
+ unsigned unique_id;
+ unsigned tiff_nifds;
+ int tiff_flip;
+}identify_data_t;
+
+typedef struct
+{
+ short order;
+ ushort sraw_mul[4],cr2_slice[3];
+ unsigned kodak_cbpp;
+ off_t strip_offset, data_offset;
+ off_t meta_offset;
+ unsigned meta_length;
+ unsigned thumb_misc;
+ unsigned fuji_layout;
+ unsigned tiff_samples;
+ unsigned tiff_bps;
+ unsigned tiff_compress;
+ unsigned zero_after_ff;
+ unsigned tile_width, tile_length,load_flags;
+ unsigned data_error;
+}unpacker_data_t;
+
+
+
+typedef struct
+{
+ internal_data_t internal_data;
+ internal_output_params_t internal_output_params;
+ output_data_t output_data;
+ identify_data_t identify_data;
+ unpacker_data_t unpacker_data;
+} libraw_internal_data_t;
+
+
+struct decode
+{
+ struct decode *branch[2];
+ int leaf;
+};
+
+struct tiff_ifd_t
+{
+ int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes;
+};
+
+
+struct jhead {
+ int bits, high, wide, clrs, sraw, psv, restart, vpred[6];
+ struct decode *huff[6];
+ ushort *row;
+};
+struct tiff_tag {
+ ushort tag, type;
+ int count;
+ union { char c[4]; short s[2]; int i; } val;
+};
+
+struct tiff_hdr {
+ ushort t_order, magic;
+ int ifd;
+ ushort pad, ntag;
+ struct tiff_tag tag[23];
+ int nextifd;
+ ushort pad2, nexif;
+ struct tiff_tag exif[4];
+ ushort pad3, ngps;
+ struct tiff_tag gpst[10];
+ short bps[4];
+ int rat[10];
+ unsigned gps[26];
+ char t_desc[512], t_make[64], t_model[64], soft[32], date[20], t_artist[64];
+};
+
+
+
+#ifdef DEBUG_STAGE_CHECKS
+#define CHECK_ORDER_HIGH(expected_stage) \
+ do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) {fprintf(stderr,"CHECK_HIGH: check %d >= %d\n",imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK,expected_stage);return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+ do { printf("Checking LOW %d/%d : %d\n",imgdata.progress_flags,expected_stage,imgdata.progress_flags<expected_stage); if( (imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage ) { printf("failed!\n"); return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+#define CHECK_ORDER_BIT(expected_stage) \
+ do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage; fprintf(stderr,"SET_FLAG: %d\n",stage); } while (0)
+
+#else
+
+#define CHECK_ORDER_HIGH(expected_stage) \
+ do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \
+ {return LIBRAW_OUT_OF_ORDER_CALL;} } while(0)
+
+#define CHECK_ORDER_LOW(expected_stage) \
+ do { if((imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \
+ return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define CHECK_ORDER_BIT(expected_stage) \
+ do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0)
+
+#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage;} while (0)
+
+#endif
+
+#endif
diff --git a/Source/LibRawLite/libraw/libraw_types.h b/Source/LibRawLite/libraw/libraw_types.h
new file mode 100644
index 0000000..dafe497
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_types.h
@@ -0,0 +1,246 @@
+/* -*- C++ -*-
+ * File: libraw_types.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8 , 2008
+ *
+ * LibRaw (Lite) data structures
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LIBRAW_TYPES_H
+#define _LIBRAW_TYPES_H
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef USE_LCMS
+#define NO_LCMS
+#endif
+
+#include "libraw_const.h"
+#include "libraw_version.h"
+
+typedef long long INT64;
+typedef unsigned long long UINT64;
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+
+#ifdef WIN32
+#ifdef LIBRAW_NODLL
+# define DllDef
+#else
+# ifdef LIBRAW_BUILDLIB
+# define DllDef __declspec( dllexport )
+# else
+# define DllDef __declspec( dllimport )
+# endif
+#endif
+#else
+# define DllDef
+#endif
+
+
+
+typedef void (* memory_callback)(void * data, const char *file, const char *where);
+
+DllDef void default_memory_callback(void *data,const char *file, const char *where);
+
+typedef void (*data_callback)(void *data,const char *file, const int offset);
+
+DllDef void default_data_callback(void *data,const char *file, const int offset);
+
+typedef int (* progress_callback) (void *data,enum LibRaw_progress stage, int iteration,int expected);
+
+typedef struct
+{
+ memory_callback mem_cb;
+ void* memcb_data;
+
+ data_callback data_cb;
+ void* datacb_data;
+
+ progress_callback progress_cb;
+ void *progresscb_data;
+} libraw_callbacks_t;
+
+
+typedef struct
+{
+ enum LibRaw_image_formats type;
+ ushort height,
+ width,
+ colors,
+ bits,
+ gamma_corrected;
+ unsigned int data_size;
+ unsigned char data[1];
+}libraw_processed_image_t;
+
+
+typedef struct
+{
+ char make[64];
+ char model[64];
+
+ unsigned raw_count;
+ unsigned dng_version;
+ int colors;
+
+ unsigned filters;
+ char cdesc[5];
+
+}libraw_iparams_t;
+
+typedef struct
+{
+ ushort raw_height,
+ raw_width,
+ height,
+ width,
+ top_margin,
+ left_margin;
+ ushort iheight,
+ iwidth;
+ double pixel_aspect;
+ int flip;
+
+ ushort right_margin,bottom_margin;
+
+} libraw_image_sizes_t;
+
+struct ph1_t
+{
+ int format, key_off, t_black, black_off, split_col, tag_21a;
+ float tag_210;
+};
+
+
+typedef struct
+{
+ unsigned curve_state : 3;
+ unsigned rgb_cam_state : 3;
+ unsigned cmatrix_state : 3;
+ unsigned pre_mul_state : 3;
+ unsigned cam_mul_state : 3;
+ unsigned filler : 17;
+} color_data_state_t;
+
+typedef struct
+{
+ ushort white[8][8];
+ float cam_mul[4];
+ float pre_mul[4];
+ float cmatrix[3][4];
+ float rgb_cam[3][4];
+ float cam_xyz[4][3];
+ ushort curve[0x4001];
+ unsigned black;
+ unsigned maximum;
+ struct ph1_t phase_one_data;
+ float flash_used;
+ float canon_ev;
+ char model2[64];
+ void *profile;
+ unsigned profile_length;
+}libraw_colordata_t;
+
+typedef struct
+{
+ enum LibRaw_thumbnail_formats tformat;
+ ushort twidth,
+ theight;
+ unsigned tlength;
+ int tcolors;
+
+ char *thumb;
+}libraw_thumbnail_t;
+
+typedef struct
+{
+ float iso_speed;
+ float shutter;
+ float aperture;
+ float focal_len;
+ time_t timestamp;
+ unsigned shot_order;
+ unsigned gpsdata[32];
+ char desc[512],
+ artist[64];
+} libraw_imgother_t;
+
+typedef struct
+{
+ unsigned greybox[4]; /* -A x1 y1 x2 y2 */
+ double aber[4]; /* -C */
+ double gamm[5]; /* -g */
+ float user_mul[4]; /* -r mul0 mul1 mul2 mul3 */
+ unsigned shot_select; /* -s */
+ float bright; /* -b */
+ float threshold; /* -n */
+ int half_size; /* -h */
+ int four_color_rgb; /* -f */
+ int document_mode; /* -d/-D */
+ int highlight; /* -H */
+ int use_auto_wb; /* -a */
+ int use_camera_wb; /* -w */
+ int use_camera_matrix; /* +M/-M */
+ int output_color; /* -o */
+ char *output_profile; /* -o */
+ char *camera_profile; /* -p */
+ char *bad_pixels; /* -P */
+ char *dark_frame; /* -K */
+ int output_bps; /* -4 */
+ int gamma_16bit; /* -1 */
+ int output_tiff; /* -T */
+ int user_flip; /* -t */
+ int user_qual; /* -q */
+ int user_black; /* -k */
+ int user_sat; /* -S */
+
+ int med_passes; /* -m */
+ float auto_bright_thr;
+ int no_auto_bright; /* -W */
+ int use_fuji_rotate;/* -j */
+}libraw_output_params_t;
+
+
+typedef struct
+{
+ unsigned int progress_flags;
+ unsigned int process_warnings;
+ libraw_iparams_t idata;
+ libraw_image_sizes_t sizes;
+ libraw_colordata_t color;
+ libraw_imgother_t other;
+ libraw_thumbnail_t thumbnail;
+ ushort (*image)[4] ;
+ libraw_output_params_t params;
+ void *parent_class;
+} libraw_data_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/Source/LibRawLite/libraw/libraw_version.h b/Source/LibRawLite/libraw/libraw_version.h
new file mode 100644
index 0000000..8be4be6
--- /dev/null
+++ b/Source/LibRawLite/libraw/libraw_version.h
@@ -0,0 +1,46 @@
+/* -*- C++ -*-
+ * File: libraw_version.h
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Mon Sept 8, 2008
+ *
+ * LibRaw (Lite) version info
+ *
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __VERSION_H
+#define __VERSION_H
+
+#define LIBRAW_MAJOR_VERSION 0
+#define LIBRAW_MINOR_VERSION 7
+#define LIBRAW_PATCH_VERSION 2
+#define LIBRAW_VERSION_TAIL Release(Lite)
+
+#define _LIBRAW_VERSION_MAKE(a,b,c,d) #a"."#b"."#c"-"#d
+#define LIBRAW_VERSION_MAKE(a,b,c,d) _LIBRAW_VERSION_MAKE(a,b,c,d)
+
+#define LIBRAW_VERSION_STR LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION,LIBRAW_VERSION_TAIL)
+
+#define LIBRAW_MAKE_VERSION(major,minor,patch) \
+ (((major) << 16) | ((minor) << 8) | (patch))
+
+#define LIBRAW_VERSION \
+ LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION)
+
+#define LIBRAW_CHECK_VERSION(major,minor,patch) \
+ ( LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major,minor,patch) )
+
+
+#endif
diff --git a/Source/LibRawLite/src/libraw_c_api.cpp b/Source/LibRawLite/src/libraw_c_api.cpp
new file mode 100644
index 0000000..370ea08
--- /dev/null
+++ b/Source/LibRawLite/src/libraw_c_api.cpp
@@ -0,0 +1,145 @@
+/* -*- C++ -*-
+ * File: libraw_c_api.cpp
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8 , 2008
+ *
+ * LibRaw (Lite) C interface implementation
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ */
+#include <errno.h>
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ libraw_data_t *libraw_init(unsigned int flags)
+ {
+ LibRaw *ret = new LibRaw(flags);
+ return &(ret->imgdata);
+ }
+
+ const char* libraw_version() { return LibRaw::version();}
+ const char* libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p);}
+ int libraw_versionNumber() { return LibRaw::versionNumber();}
+ const char** libraw_cameraList() { return LibRaw::cameraList();}
+ int libraw_cameraCount() { return LibRaw::cameraCount(); }
+ const char* libraw_unpack_function_name(libraw_data_t* lr)
+ {
+ if(!lr) return "NULL parameter passed";
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->unpack_function_name();
+ }
+
+ int libraw_open_file(libraw_data_t* lr, const char *file)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->open_file(file);
+ }
+ int libraw_open_buffer(libraw_data_t* lr, void *buffer, size_t size)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->open_buffer(buffer,size);
+ }
+ int libraw_unpack(libraw_data_t* lr)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->unpack();
+ }
+ int libraw_unpack_thumb(libraw_data_t* lr)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->unpack_thumb();
+ }
+ void libraw_recycle(libraw_data_t* lr)
+ {
+ if(!lr) return;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ ip->recycle();
+ }
+ void libraw_close(libraw_data_t* lr)
+ {
+ if(!lr) return;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ delete ip;
+ }
+
+ void libraw_set_memerror_handler(libraw_data_t* lr, memory_callback cb,void *data)
+ {
+ if(!lr) return;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ ip->set_memerror_handler(cb,data);
+
+ }
+ void libraw_set_dataerror_handler(libraw_data_t* lr,data_callback func,void *data)
+ {
+ if(!lr) return;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ ip->set_dataerror_handler(func,data);
+
+ }
+ void libraw_set_progress_handler(libraw_data_t* lr, progress_callback cb,void *data)
+ {
+ if(!lr) return;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ ip->set_progress_handler(cb,data);
+
+ }
+
+ // DCRAW
+ int libraw_adjust_sizes_info_only(libraw_data_t* lr)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->adjust_sizes_info_only();
+ }
+
+ int libraw_dcraw_document_mode_processing(libraw_data_t* lr)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->dcraw_document_mode_processing();
+
+ }
+ int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->dcraw_ppm_tiff_writer(filename);
+ }
+ int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->dcraw_thumb_writer(fname);
+
+ }
+ int libraw_dcraw_process(libraw_data_t* lr)
+ {
+ if(!lr) return EINVAL;
+ LibRaw *ip = (LibRaw*) lr->parent_class;
+ return ip->dcraw_process();
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Source/LibRawLite/src/libraw_cxx.cpp b/Source/LibRawLite/src/libraw_cxx.cpp
new file mode 100644
index 0000000..fc3547b
--- /dev/null
+++ b/Source/LibRawLite/src/libraw_cxx.cpp
@@ -0,0 +1,1607 @@
+/* -*- C++ -*-
+ * File: libraw_cxx.cpp
+ * Copyright 2008-2009 LibRaw LLC (info@libraw.org)
+ * Created: Sat Mar 8 , 2008
+ *
+ * LibRaw (Lite) C++ interface (implementation)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <errno.h>
+#include <float.h>
+#include <math.h>
+#ifndef WIN32
+#include <netinet/in.h>
+#else
+#include <winsock2.h>
+#endif
+#define LIBRAW_LIBRARY_BUILD
+#include "libraw/libraw.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ void default_memory_callback(void *,const char *file,const char *where)
+ {
+ fprintf (stderr,"%s: Out of memory in %s\n", file?file:"unknown file", where);
+ }
+
+ void default_data_callback(void*,const char *file, const int offset)
+ {
+ if(offset < 0)
+ fprintf (stderr,"%s: Unexpected end of file\n", file?file:"unknown file");
+ else
+ fprintf (stderr,"%s: data corrupted at %d\n",file?file:"unknown file",offset);
+ }
+ const char *libraw_strerror(int e)
+ {
+ enum LibRaw_errors errorcode = (LibRaw_errors)e;
+ switch(errorcode)
+ {
+ case LIBRAW_SUCCESS:
+ return "No error";
+ case LIBRAW_UNSPECIFIED_ERROR:
+ return "Unspecified error";
+ case LIBRAW_FILE_UNSUPPORTED:
+ return "Unsupported file format or not RAW file";
+ case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE:
+ return "Request for nonexisting image number";
+ case LIBRAW_OUT_OF_ORDER_CALL:
+ return "Out of order call of libraw function";
+ case LIBRAW_NO_THUMBNAIL:
+ return "No thumbnail in file";
+ case LIBRAW_UNSUPPORTED_THUMBNAIL:
+ return "Unsupported thumbnail format";
+ case LIBRAW_CANNOT_ADDMASK:
+ return "Cannot add masked pixels to resized image";
+ case LIBRAW_UNSUFFICIENT_MEMORY:
+ return "Unsufficient memory";
+ case LIBRAW_DATA_ERROR:
+ return "Corrupted data or unexpected EOF";
+ case LIBRAW_IO_ERROR:
+ return "Input/output error";
+ case LIBRAW_CANCELLED_BY_CALLBACK:
+ return "Cancelled by user callback";
+ default:
+ return "Unknown error code";
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+const double LibRaw_constants::xyz_rgb[3][3] =
+{
+ { 0.412453, 0.357580, 0.180423 },
+ { 0.212671, 0.715160, 0.072169 },
+ { 0.019334, 0.119193, 0.950227 }
+};
+
+const float LibRaw_constants::d65_white[3] = { 0.950456, 1, 1.088754 };
+
+#define P1 imgdata.idata
+#define S imgdata.sizes
+#define O imgdata.params
+#define C imgdata.color
+#define T imgdata.thumbnail
+#define IO libraw_internal_data.internal_output_params
+#define ID libraw_internal_data.internal_data
+
+#define EXCEPTION_HANDLER(e) do{ \
+ fprintf(stderr,"Exception %d caught\n",e); \
+ switch(e) \
+ { \
+ case LIBRAW_EXCEPTION_ALLOC: \
+ recycle(); \
+ return LIBRAW_UNSUFFICIENT_MEMORY; \
+ case LIBRAW_EXCEPTION_DECODE_RAW: \
+ case LIBRAW_EXCEPTION_DECODE_JPEG: \
+ recycle(); \
+ return LIBRAW_DATA_ERROR; \
+ case LIBRAW_EXCEPTION_IO_EOF: \
+ case LIBRAW_EXCEPTION_IO_CORRUPT: \
+ recycle(); \
+ return LIBRAW_IO_ERROR; \
+ case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK:\
+ recycle(); \
+ return LIBRAW_CANCELLED_BY_CALLBACK; \
+ default: \
+ return LIBRAW_UNSPECIFIED_ERROR; \
+ } \
+ }while(0)
+
+void LibRaw::derror()
+{
+ if (!libraw_internal_data.unpacker_data.data_error && libraw_internal_data.internal_data.input)
+ {
+ if (libraw_internal_data.internal_data.input->eof())
+ {
+ if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+ libraw_internal_data.internal_data.input->fname(),-1);
+ throw LIBRAW_EXCEPTION_IO_EOF;
+ }
+ else
+ {
+ if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data,
+ libraw_internal_data.internal_data.input->fname(),
+ libraw_internal_data.internal_data.input->tell());
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ }
+ }
+ libraw_internal_data.unpacker_data.data_error = 1;
+}
+LibRaw:: LibRaw(unsigned int flags)
+{
+ double aber[4] = {1,1,1,1};
+ double gamm[5] = { 0.45,4.5,0,0,0 };
+ unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX };
+#ifdef DCRAW_VERBOSE
+ verbose = 1;
+#else
+ verbose = 0;
+#endif
+ bzero(&imgdata,sizeof(imgdata));
+ bzero(&libraw_internal_data,sizeof(libraw_internal_data));
+ bzero(&callbacks,sizeof(callbacks));
+ callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL: &default_memory_callback;
+ callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK)? NULL : &default_data_callback;
+ memmove(&imgdata.params.aber,&aber,sizeof(aber));
+ memmove(&imgdata.params.gamm,&gamm,sizeof(gamm));
+ memmove(&imgdata.params.greybox,&greybox,sizeof(greybox));
+
+ imgdata.params.bright=1;
+ imgdata.params.use_camera_matrix=-1;
+ imgdata.params.user_flip=-1;
+ imgdata.params.user_black=-1;
+ imgdata.params.user_sat=-1;
+ imgdata.params.user_qual=-1;
+ imgdata.params.output_color=1;
+ imgdata.params.output_bps=8;
+ imgdata.params.use_fuji_rotate=1;
+ imgdata.params.auto_bright_thr = 0.01;
+ imgdata.parent_class = this;
+ imgdata.progress_flags = 0;
+ tls = new LibRaw_TLS;
+ tls->init();
+}
+
+
+void* LibRaw:: malloc(size_t t)
+{
+ void *p = memmgr.malloc(t);
+ return p;
+}
+void* LibRaw:: calloc(size_t n,size_t t)
+{
+ void *p = memmgr.calloc(n,t);
+ return p;
+}
+void LibRaw:: free(void *p)
+{
+ memmgr.free(p);
+}
+
+
+int LibRaw:: fc (int row, int col)
+{
+ static const char filter[16][16] =
+ { { 2,1,1,3,2,3,2,0,3,2,3,0,1,2,1,0 },
+ { 0,3,0,2,0,1,3,1,0,1,1,2,0,3,3,2 },
+ { 2,3,3,2,3,1,1,3,3,1,2,1,2,0,0,3 },
+ { 0,1,0,1,0,2,0,2,2,0,3,0,1,3,2,1 },
+ { 3,1,1,2,0,1,0,2,1,3,1,3,0,1,3,0 },
+ { 2,0,0,3,3,2,3,1,2,0,2,0,3,2,2,1 },
+ { 2,3,3,1,2,1,2,1,2,1,1,2,3,0,0,1 },
+ { 1,0,0,2,3,0,0,3,0,3,0,3,2,1,2,3 },
+ { 2,3,3,1,1,2,1,0,3,2,3,0,2,3,1,3 },
+ { 1,0,2,0,3,0,3,2,0,1,1,2,0,1,0,2 },
+ { 0,1,1,3,3,2,2,1,1,3,3,0,2,1,3,2 },
+ { 2,3,2,0,0,1,3,0,2,0,1,2,3,0,1,0 },
+ { 1,3,1,2,3,2,3,2,0,2,0,1,1,0,3,0 },
+ { 0,2,0,3,1,0,0,1,1,3,3,2,3,2,2,1 },
+ { 2,1,3,2,3,1,2,1,0,3,0,2,0,2,0,2 },
+ { 0,3,1,0,0,2,0,3,2,1,3,1,1,3,1,3 } };
+
+ if (imgdata.idata.filters != 1) return FC(row,col);
+ return filter[(row+imgdata.sizes.top_margin) & 15][(col+imgdata.sizes.left_margin) & 15];
+}
+
+void LibRaw:: recycle()
+{
+ if(libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal)
+ {
+ delete libraw_internal_data.internal_data.input;
+ libraw_internal_data.internal_data.input = NULL;
+ }
+ libraw_internal_data.internal_data.input_internal = 0;
+#define FREE(a) do { if(a) { free(a); a = NULL;} }while(0)
+
+ FREE(imgdata.image);
+ FREE(imgdata.thumbnail.thumb);
+ FREE(libraw_internal_data.internal_data.meta_data);
+ FREE(libraw_internal_data.output_data.histogram);
+ FREE(libraw_internal_data.output_data.oprof);
+ FREE(imgdata.color.profile);
+#undef FREE
+#define ZERO(a) bzero(&a,sizeof(a))
+ ZERO(imgdata.sizes);
+ ZERO(libraw_internal_data.internal_output_params);
+#undef ZERO
+ memmgr.cleanup();
+ imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN;
+ imgdata.progress_flags = 0;
+
+ tls->init();
+}
+
+const char * LibRaw::unpack_function_name()
+{
+ if(!load_raw) return "Function not set";
+
+ // sorted names order
+ if (load_raw == &LibRaw::adobe_dng_load_raw_lj) return "adobe_dng_load_raw_lj()";
+ if (load_raw == &LibRaw::adobe_dng_load_raw_nc) return "adobe_dng_load_raw_nc()";
+ if (load_raw == &LibRaw::canon_600_load_raw) return "canon_600_load_raw()";
+
+ if (load_raw == &LibRaw::canon_a5_load_raw) return "canon_a5_load_raw()";
+ if (load_raw == &LibRaw::canon_compressed_load_raw) return "canon_compressed_load_raw()";
+ if (load_raw == &LibRaw::canon_sraw_load_raw) return "canon_sraw_load_raw()";
+
+ if (load_raw == &LibRaw::casio_qv5700_load_raw ) return "casio_qv5700_load_raw()";
+ if (load_raw == &LibRaw::eight_bit_load_raw ) return "eight_bit_load_raw()";
+ if (load_raw == &LibRaw::fuji_load_raw ) return "fuji_load_raw()";
+ // 10
+ if (load_raw == &LibRaw::hasselblad_load_raw ) return "hasselblad_load_raw()";
+ if (load_raw == &LibRaw::imacon_full_load_raw ) return "imacon_full_load_raw()";
+ if (load_raw == &LibRaw::kodak_262_load_raw ) return "kodak_262_load_raw()";
+
+ if (load_raw == &LibRaw::kodak_65000_load_raw ) return "kodak_65000_load_raw()";
+ if (load_raw == &LibRaw::kodak_dc120_load_raw ) return "kodak_dc120_load_raw()";
+ if (load_raw == &LibRaw::kodak_jpeg_load_raw ) return "kodak_jpeg_load_raw()";
+
+ if (load_raw == &LibRaw::kodak_radc_load_raw ) return "kodak_radc_load_raw()";
+ if (load_raw == &LibRaw::kodak_rgb_load_raw ) return "kodak_rgb_load_raw()";
+ if (load_raw == &LibRaw::kodak_yrgb_load_raw ) return "kodak_yrgb_load_raw()";
+ if (load_raw == &LibRaw::kodak_ycbcr_load_raw ) return "kodak_ycbcr_load_raw()";
+ // 20
+ if (load_raw == &LibRaw::leaf_hdr_load_raw ) return "leaf_hdr_load_raw()";
+ if (load_raw == &LibRaw::lossless_jpeg_load_raw) return "lossless_jpeg_load_raw()";
+ if (load_raw == &LibRaw::minolta_rd175_load_raw ) return "minolta_rd175_load_raw()";
+
+ if (load_raw == &LibRaw::nikon_compressed_load_raw) return "nikon_compressed_load_raw()";
+ if (load_raw == &LibRaw::nikon_e900_load_raw ) return "nikon_e900_load_raw()";
+ if (load_raw == &LibRaw::nokia_load_raw ) return "nokia_load_raw()";
+
+ if (load_raw == &LibRaw::olympus_e300_load_raw ) return "olympus_e300_load_raw()";
+ if (load_raw == &LibRaw::olympus_e410_load_raw ) return "olympus_e410_load_raw()";
+ if (load_raw == &LibRaw::packed_12_load_raw ) return "packed_12_load_raw()";
+ if (load_raw == &LibRaw::panasonic_load_raw ) return "panasonic_load_raw()";
+ // 30
+ if (load_raw == &LibRaw::pentax_k10_load_raw ) return "pentax_k10_load_raw()";
+ if (load_raw == &LibRaw::phase_one_load_raw ) return "phase_one_load_raw()";
+ if (load_raw == &LibRaw::phase_one_load_raw_c ) return "phase_one_load_raw_c()";
+
+ if (load_raw == &LibRaw::quicktake_100_load_raw ) return "quicktake_100_load_raw()";
+ if (load_raw == &LibRaw::rollei_load_raw ) return "rollei_load_raw()";
+ if (load_raw == &LibRaw::sinar_4shot_load_raw ) return "sinar_4shot_load_raw()";
+
+ if (load_raw == &LibRaw::smal_v6_load_raw ) return "smal_v6_load_raw()";
+ if (load_raw == &LibRaw::smal_v9_load_raw ) return "smal_v9_load_raw()";
+ if (load_raw == &LibRaw::sony_load_raw ) return "sony_load_raw()";
+ if (load_raw == &LibRaw::sony_arw_load_raw ) return "sony_arw_load_raw()";
+ // 40
+ if (load_raw == &LibRaw::sony_arw2_load_raw ) return "sony_arw2_load_raw()";
+ if (load_raw == &LibRaw::unpacked_load_raw ) return "unpacked_load_raw()";
+ // 42 total
+
+ return "Unknown unpack function";
+}
+
+
+void LibRaw:: merror (void *ptr, const char *where)
+{
+ if (ptr) return;
+ if(callbacks.mem_cb)(*callbacks.mem_cb)(callbacks.memcb_data,
+ libraw_internal_data.internal_data.input
+ ?libraw_internal_data.internal_data.input->fname()
+ :NULL,
+ where);
+ throw LIBRAW_EXCEPTION_ALLOC;
+}
+
+
+int LibRaw::open_file(const char *fname)
+{
+ // this stream will close on recycle()
+ LibRaw_file_datastream *stream = new LibRaw_file_datastream(fname);
+ if(!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal =1 ; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+
+int LibRaw::open_buffer(void *buffer, size_t size)
+{
+ // this stream will close on recycle()
+ if(!buffer || buffer==(void*)-1)
+ return LIBRAW_IO_ERROR;
+
+ LibRaw_buffer_datastream *stream = new LibRaw_buffer_datastream(buffer,size);
+ if(!stream->valid())
+ {
+ delete stream;
+ return LIBRAW_IO_ERROR;
+ }
+ ID.input_internal = 0; // preserve from deletion on error
+ int ret = open_datastream(stream);
+ if (ret == LIBRAW_SUCCESS)
+ {
+ ID.input_internal =1 ; // flag to delete datastream on recycle
+ }
+ else
+ {
+ delete stream;
+ ID.input_internal = 0;
+ }
+ return ret;
+}
+
+
+int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
+{
+
+ if(!stream)
+ return ENOENT;
+ if(!stream->valid())
+ return LIBRAW_IO_ERROR;
+ recycle();
+
+ try {
+ ID.input = stream;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
+
+ if (O.use_camera_matrix < 0)
+ O.use_camera_matrix = O.use_camera_wb;
+
+ identify();
+
+ int saved_raw_width = S.raw_width;
+ int saved_width = S.width;
+ // from packed_12_load_raw
+ if ((load_raw == &LibRaw:: packed_12_load_raw) && (S.raw_width * 2 >= S.width * 3))
+ {
+ // raw_width is in bytes!
+ S.raw_width = S.raw_width * 2 / 3;
+ }
+ else if (S.pixel_aspect < 0.95 || S.pixel_aspect > 1.05)
+ {
+ S.width*=S.pixel_aspect;
+ }
+
+ if(S.raw_width>S.width + S.left_margin)
+ S.right_margin = S.raw_width - S.width - S.left_margin;
+
+ if(S.raw_height > S.height + S.top_margin)
+ S.bottom_margin = S.raw_height - S.height - S.top_margin;
+
+ S.raw_width = saved_raw_width;
+ S.width = saved_width;
+
+ if(C.profile_length)
+ {
+ if(C.profile) free(C.profile);
+ C.profile = malloc(C.profile_length);
+ merror(C.profile,"LibRaw::open_file()");
+ ID.input->seek(ID.profile_offset,SEEK_SET);
+ ID.input->read(C.profile,C.profile_length,1);
+ }
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
+ }
+ catch ( LibRaw_exceptions err) {
+ EXCEPTION_HANDLER(err);
+ }
+
+ if(P1.raw_count < 1)
+ return LIBRAW_FILE_UNSUPPORTED;
+
+ if (O.user_flip >= 0)
+ S.flip = O.user_flip;
+
+ switch ((S.flip+3600) % 360)
+ {
+ case 270: S.flip = 5; break;
+ case 180: S.flip = 3; break;
+ case 90: S.flip = 6; break;
+ }
+
+ write_fun = &LibRaw::write_ppm_tiff;
+
+ if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
+ {
+ S.height += S.height & 1;
+ S.width += S.width & 1;
+ }
+
+ IO.shrink = P1.filters && (O.half_size || O.threshold || O.aber[0] != 1 || O.aber[2] != 1);
+ S.iheight = (S.height + IO.shrink) >> IO.shrink;
+ S.iwidth = (S.width + IO.shrink) >> IO.shrink;
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
+
+
+ return LIBRAW_SUCCESS;
+}
+
+int LibRaw::unpack(void)
+{
+ CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW);
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+ try {
+
+ RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,0,2);
+ if (O.shot_select >= P1.raw_count)
+ return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE;
+
+ if(!load_raw)
+ return LIBRAW_UNSPECIFIED_ERROR;
+
+ if (O.use_camera_matrix && C.cmatrix[0][0] > 0.25)
+ {
+ memcpy (C.rgb_cam, C.cmatrix, sizeof (C.cmatrix));
+ IO.raw_color = 0;
+ }
+ // already allocated ?
+ if(imgdata.image) free(imgdata.image);
+
+ imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+ merror (imgdata.image, "unpack()");
+
+ if (libraw_internal_data.unpacker_data.meta_length)
+ {
+ libraw_internal_data.internal_data.meta_data =
+ (char *) malloc (libraw_internal_data.unpacker_data.meta_length);
+ merror (libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()");
+ }
+ ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
+ // foveon_load_raw produces different data for document_mode, we'll
+ // deal with it in dcraw_document_mode_processing
+ int save_document_mode = O.document_mode;
+ O.document_mode = 0;
+
+ (this->*load_raw)();
+
+ O.document_mode = save_document_mode;
+
+ SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW);
+ RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,1,2);
+
+ return 0;
+ }
+ catch ( LibRaw_exceptions err) {
+ EXCEPTION_HANDLER(err);
+ }
+}
+
+int LibRaw::dcraw_document_mode_processing(void)
+{
+ CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+ try {
+
+ O.document_mode = 2;
+
+ O.use_fuji_rotate = 0;
+ if (IO.zero_is_bad)
+ {
+ remove_zeroes();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+ }
+ if(O.bad_pixels)
+ {
+ bad_pixels(O.bad_pixels);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+ }
+ if (O.dark_frame)
+ {
+ subtract (O.dark_frame);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+ }
+
+ if (O.user_black >= 0)
+ C.black = O.user_black;
+
+ if (O.user_sat > 0)
+ C.maximum = O.user_sat;
+
+ pre_interpolate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+ if (libraw_internal_data.internal_output_params.mix_green)
+ {
+ int i;
+ for (P1.colors=3, i=0; i < S.height*S.width; i++)
+ imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+ }
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+
+ if ( P1.colors == 3)
+ median_filter();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+
+ if ( O.highlight == 2)
+ blend_highlights();
+
+ if ( O.highlight > 2)
+ recover_highlights();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+
+ if (O.use_fuji_rotate)
+ fuji_rotate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+#ifndef NO_LCMS
+ if(O.camera_profile)
+ {
+ apply_profile(O.camera_profile,O.output_profile);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+ }
+#endif
+ if(!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+ merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_document_mode_processing()");
+ }
+ convert_to_rgb();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+ if (O.use_fuji_rotate)
+ stretch();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+
+ return 0;
+ }
+ catch ( LibRaw_exceptions err) {
+ EXCEPTION_HANDLER(err);
+ }
+
+}
+
+#if 1
+#define FORC(cnt) for (c=0; c < cnt; c++)
+#define FORCC FORC(ret->colors)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+libraw_processed_image_t * LibRaw::dcraw_make_mem_thumb(int *errcode)
+{
+ if(!T.thumb)
+ {
+ if ( !ID.toffset)
+ {
+ if(errcode) *errcode= LIBRAW_NO_THUMBNAIL;
+ }
+ else
+ {
+ if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+ }
+ return NULL;
+ }
+
+ if (T.tformat == LIBRAW_THUMBNAIL_BITMAP)
+ {
+ libraw_processed_image_t * ret =
+ (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+T.tlength);
+
+ if(!ret)
+ {
+ if(errcode) *errcode= ENOMEM;
+ return NULL;
+ }
+
+ bzero(ret,sizeof(libraw_processed_image_t));
+ ret->type = LIBRAW_IMAGE_BITMAP;
+ ret->height = T.theight;
+ ret->width = T.twidth;
+ ret->colors = 3;
+ ret->bits = 8;
+ ret->gamma_corrected = 1;
+ ret->data_size = T.tlength;
+ memmove(ret->data,T.thumb,T.tlength);
+ if(errcode) *errcode= 0;
+ return ret;
+ }
+ else if (T.tformat == LIBRAW_THUMBNAIL_JPEG)
+ {
+ ushort exif[5];
+ int mk_exif = 0;
+ if(strcmp(T.thumb+6,"Exif")) mk_exif = 1;
+
+ int dsize = T.tlength + mk_exif * (sizeof(exif)+sizeof(tiff_hdr));
+
+ libraw_processed_image_t * ret =
+ (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+dsize);
+
+ if(!ret)
+ {
+ if(errcode) *errcode= ENOMEM;
+ return NULL;
+ }
+
+ bzero(ret,sizeof(libraw_processed_image_t));
+
+ ret->type = LIBRAW_IMAGE_JPEG;
+ ret->data_size = dsize;
+
+ ret->data[0] = 0xff;
+ ret->data[1] = 0xd8;
+ if(mk_exif)
+ {
+ struct tiff_hdr th;
+ memcpy (exif, "\xff\xe1 Exif\0\0", 10);
+ exif[1] = htons (8 + sizeof th);
+ memmove(ret->data+2,exif,sizeof(exif));
+ tiff_head (&th, 0);
+ memmove(ret->data+(2+sizeof(exif)),&th,sizeof(th));
+ memmove(ret->data+(2+sizeof(exif)+sizeof(th)),T.thumb+2,T.tlength-2);
+ }
+ else
+ {
+ memmove(ret->data+2,T.thumb+2,T.tlength-2);
+ }
+ if(errcode) *errcode= 0;
+ return ret;
+
+ }
+ else
+ {
+ if(errcode) *errcode= LIBRAW_UNSUPPORTED_THUMBNAIL;
+ return NULL;
+
+ }
+}
+
+
+
+libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode)
+{
+ if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE)
+ {
+ if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL;
+ return NULL;
+ }
+
+ if(!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram =
+ (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+ merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_make_mem_image()");
+ }
+
+ unsigned ds = S.height * S.width * (O.output_bps/8) * P1.colors;
+ libraw_processed_image_t *ret = (libraw_processed_image_t*)::malloc(sizeof(libraw_processed_image_t)+ds);
+ if(!ret)
+ {
+ if(errcode) *errcode= ENOMEM;
+ return NULL;
+ }
+ bzero(ret,sizeof(libraw_processed_image_t));
+ // metadata init
+
+ int s_iheight = S.iheight;
+ int s_iwidth = S.iwidth;
+ int s_width = S.width;
+ int s_hwight = S.height;
+
+ S.iheight = S.height;
+ S.iwidth = S.width;
+
+
+ if (S.flip & 4) SWAP(S.height,S.width);
+
+
+ ret->type = LIBRAW_IMAGE_BITMAP;
+ ret->height = S.height;
+ ret->width = S.width;
+ ret->colors = P1.colors;
+ ret->bits = O.output_bps;
+ ret->gamma_corrected = (O.output_bps == 8)?1:O.gamma_16bit;
+
+ ret->data_size = ds;
+
+ // Cut'n'paste from write_tiff_ppm, should be generalized later
+ uchar *bufp = ret->data;
+ uchar *ppm;
+ ushort *ppm2,lut16[0x10000];
+ int c, row, col, soff, rstep, cstep;
+
+
+ if (ret->bits == 8 || ret->gamma_corrected ) gamma_lut (lut16);
+ soff = flip_index (0, 0);
+ cstep = flip_index (0, 1) - soff;
+ rstep = flip_index (1, 0) - flip_index (0, S.width);
+
+
+ for (row=0; row < ret->height; row++, soff += rstep)
+ {
+ ppm2 = (ushort*) (ppm = bufp);
+ for (col=0; col < ret->width; col++, soff += cstep)
+ if (ret->bits == 8)
+ FORCC ppm [col*ret->colors+c] = lut16[imgdata.image[soff][c]]/256;
+ else if(ret->gamma_corrected)
+ FORCC ppm2[col*ret->colors+c] = lut16[imgdata.image[soff][c]];
+ else
+ FORCC ppm2[col*ret->colors+c] = imgdata.image[soff][c];
+ bufp+=ret->colors*(ret->bits/8)*ret->width;
+ }
+ if(errcode) *errcode= 0;
+
+ S.iheight = s_iheight;
+ S.iwidth = s_iwidth;
+ S.width = s_width;
+ S.height = s_hwight;
+
+ return ret;
+}
+
+#undef FORC
+#undef FORCC
+#undef SWAP
+#endif
+
+
+int LibRaw::dcraw_ppm_tiff_writer(const char *filename)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+
+ if(!imgdata.image)
+ return LIBRAW_OUT_OF_ORDER_CALL;
+
+ if(!filename)
+ return ENOENT;
+ FILE *f = fopen(filename,"wb");
+
+ if(!f)
+ return errno;
+
+ try {
+ if(!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram =
+ (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+ merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_ppm_tiff_writer()");
+ }
+ write_ppm_tiff(f);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+ fclose(f);
+ return 0;
+ }
+ catch ( LibRaw_exceptions err) {
+ fclose(f);
+ EXCEPTION_HANDLER(err);
+ }
+}
+
+void LibRaw::kodak_thumb_loader()
+{
+ // some kodak cameras
+ ushort s_height = S.height, s_width = S.width,s_iwidth = S.iwidth,s_iheight=S.iheight;
+ int s_colors = P1.colors;
+ unsigned s_filters = P1.filters;
+ ushort (*s_image)[4] = imgdata.image;
+
+
+ S.height = T.theight;
+ S.width = T.twidth;
+ P1.filters = 0;
+
+ if (thumb_load_raw == &CLASS kodak_ycbcr_load_raw)
+ {
+ S.height += S.height & 1;
+ S.width += S.width & 1;
+ }
+
+ imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image));
+ merror (imgdata.image, "LibRaw::kodak_thumb_loader()");
+
+ ID.input->seek(ID.toffset, SEEK_SET);
+ // read kodak thumbnail into T.image[]
+ (this->*thumb_load_raw)();
+
+ // copy-n-paste from image pipe
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define LIM(x,min,max) MAX(min,MIN(x,max))
+#define CLIP(x) LIM(x,0,65535)
+#define SWAP(a,b) { a ^= b; a ^= (b ^= a); }
+
+ // from scale_colors
+ {
+ double dmax;
+ float scale_mul[4];
+ int c,val;
+ for (dmax=DBL_MAX, c=0; c < 3; c++)
+ if (dmax > C.pre_mul[c])
+ dmax = C.pre_mul[c];
+
+ for( c=0; c< 3; c++)
+ scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
+ scale_mul[3] = scale_mul[1];
+
+ size_t size = S.height * S.width;
+ for (unsigned i=0; i < size*4 ; i++)
+ {
+ val = imgdata.image[0][i];
+ if(!val) continue;
+ val *= scale_mul[i & 3];
+ imgdata.image[0][i] = CLIP(val);
+ }
+ }
+
+ // from convert_to_rgb
+ ushort *img;
+ int row,col;
+
+ int (*t_hist)[LIBRAW_HISTOGRAM_SIZE] = (int (*)[LIBRAW_HISTOGRAM_SIZE]) calloc(sizeof(*t_hist),4);
+ merror (t_hist, "LibRaw::kodak_thumb_loader()");
+
+ float out[3],
+ out_cam[3][4] =
+ {
+ {2.81761312, -1.98369181, 0.166078627, 0},
+ {-0.111855984, 1.73688626, -0.625030339, 0},
+ {-0.0379119813, -0.891268849, 1.92918086, 0}
+ };
+
+ for (img=imgdata.image[0], row=0; row < S.height; row++)
+ for (col=0; col < S.width; col++, img+=4)
+ {
+ out[0] = out[1] = out[2] = 0;
+ for(int c=0;c<3;c++)
+ {
+ out[0] += out_cam[0][c] * img[c];
+ out[1] += out_cam[1][c] * img[c];
+ out[2] += out_cam[2][c] * img[c];
+ }
+ for(int c=0; c<3; c++)
+ img[c] = CLIP((int) out[c]);
+ for(int c=0; c<P1.colors;c++)
+ t_hist[c][img[c] >> 3]++;
+
+ }
+
+ // from gamma_lut
+ int (*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram;
+ libraw_internal_data.output_data.histogram = t_hist;
+
+ ushort *lut16 = (ushort*)calloc(0x10000,sizeof(ushort));
+ merror(lut16,"LibRaw::kodak_thumb_loader()");
+ gamma_lut(lut16);
+
+ libraw_internal_data.output_data.histogram = save_hist;
+
+ free(t_hist);
+
+ // from write_ppm_tiff - copy pixels into bitmap
+
+ S.iheight = S.height;
+ S.iwidth = S.width;
+ if (S.flip & 4) SWAP(S.height,S.width);
+
+ if(T.thumb) free(T.thumb);
+ T.thumb = (char*) calloc (S.width * S.height, P1.colors);
+ merror (T.thumb, "LibRaw::kodak_thumb_loader()");
+ T.tlength = S.width * S.height * P1.colors;
+
+ // from write_tiff_ppm
+ {
+ int soff = flip_index (0, 0);
+ int cstep = flip_index (0, 1) - soff;
+ int rstep = flip_index (1, 0) - flip_index (0, S.width);
+
+ for (int row=0; row < S.height; row++, soff += rstep)
+ {
+ char *ppm = T.thumb + row*S.width*P1.colors;
+ for (int col=0; col < S.width; col++, soff += cstep)
+ for(int c = 0; c < P1.colors; c++)
+ ppm [col*P1.colors+c] = lut16[imgdata.image[soff][c]]/256;
+ }
+ }
+ free(lut16);
+ // restore variables
+ free(imgdata.image);
+ imgdata.image = s_image;
+
+ T.twidth = S.width;
+ S.width = s_width;
+
+ S.iwidth = s_iwidth;
+ S.iheight = s_iheight;
+
+ T.theight = S.height;
+ S.height = s_height;
+
+ T.tcolors = P1.colors;
+ P1.colors = s_colors;
+
+ P1.filters = s_filters;
+}
+#undef MIN
+#undef MAX
+#undef LIM
+#undef CLIP
+#undef SWAP
+
+
+
+
+// Äîñòàåò thumbnail èç ôàéëà, ñòàâèò thumb_format â ñîîòâåòñòâèè ñ ôîðìàòîì
+int LibRaw::unpack_thumb(void)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+ CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD);
+
+ try {
+ if ( !ID.toffset)
+ {
+ return LIBRAW_NO_THUMBNAIL;
+ }
+ else if (thumb_load_raw)
+ {
+ kodak_thumb_loader();
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else
+ {
+ ID.input->seek(ID.toffset, SEEK_SET);
+ if ( write_thumb == &LibRaw::jpeg_thumb)
+ {
+ if(T.thumb) free(T.thumb);
+ T.thumb = (char *) malloc (T.tlength);
+ merror (T.thumb, "jpeg_thumb()");
+ ID.input->read (T.thumb, 1, T.tlength);
+ T.tcolors = 3;
+ T.tformat = LIBRAW_THUMBNAIL_JPEG;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+ }
+ else if (write_thumb == &LibRaw::ppm_thumb)
+ {
+ T.tlength = T.twidth * T.theight*3;
+ if(T.thumb) free(T.thumb);
+
+ T.thumb = (char *) malloc (T.tlength);
+ merror (T.thumb, "ppm_thumb()");
+
+ ID.input->read(T.thumb, 1, T.tlength);
+
+ T.tformat = LIBRAW_THUMBNAIL_BITMAP;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD);
+ return 0;
+
+ }
+ // else if -- all other write_thumb cases!
+ else
+ {
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+ }
+ }
+ // last resort
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+ }
+ catch ( LibRaw_exceptions err) {
+ EXCEPTION_HANDLER(err);
+ }
+
+}
+
+int LibRaw::dcraw_thumb_writer(const char *fname)
+{
+// CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
+
+ if(!fname)
+ return ENOENT;
+
+ FILE *tfp = fopen(fname,"wb");
+
+ if(!tfp)
+ return errno;
+
+ if(!T.thumb)
+ {
+ fclose(tfp);
+ return LIBRAW_OUT_OF_ORDER_CALL;
+ }
+
+ try {
+ switch (T.tformat)
+ {
+ case LIBRAW_THUMBNAIL_JPEG:
+ jpeg_thumb_writer (tfp,T.thumb,T.tlength);
+ break;
+ case LIBRAW_THUMBNAIL_BITMAP:
+ fprintf (tfp, "P6\n%d %d\n255\n", T.twidth, T.theight);
+ fwrite (T.thumb, 1, T.tlength, tfp);
+ break;
+ default:
+ fclose(tfp);
+ return LIBRAW_UNSUPPORTED_THUMBNAIL;
+ }
+ fclose(tfp);
+ return 0;
+ }
+ catch ( LibRaw_exceptions err) {
+ fclose(tfp);
+ EXCEPTION_HANDLER(err);
+ }
+}
+
+int LibRaw::adjust_sizes_info_only(void)
+{
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY);
+ CHECK_ORDER_HIGH(LIBRAW_PROGRESS_FUJI_ROTATE);
+ if (O.use_fuji_rotate)
+ {
+ if (IO.fuji_width)
+ {
+#if 0
+ // restore saved values
+ if(IO.fheight)
+ {
+ S.height = IO.fheight;
+ S.width = IO.fwidth;
+ S.iheight = (S.height + IO.shrink) >> IO.shrink;
+ S.iwidth = (S.width + IO.shrink) >> IO.shrink;
+ S.raw_height -= 2*S.top_margin;
+ IO.fheight = IO.fwidth = 0; // prevent repeated calls
+ }
+#endif
+ // dcraw code
+ IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink;
+ S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5));
+ S.iheight = (ushort)( (S.iheight - IO.fuji_width) / sqrt(0.5));
+ }
+ else
+ {
+ if (S.pixel_aspect < 1) S.iheight = (ushort)( S.iheight / S.pixel_aspect + 0.5);
+ if (S.pixel_aspect > 1) S.iwidth = (ushort) (S.iwidth * S.pixel_aspect + 0.5);
+ }
+ }
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+ if (S.flip & 4)
+ {
+ unsigned short t = S.iheight;
+ S.iheight=S.iwidth;
+ S.iwidth = t;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP);
+ }
+ return 0;
+}
+
+
+
+int LibRaw::dcraw_process(void)
+{
+ int quality,i;
+
+
+ CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
+ CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+ try {
+
+ if(O.half_size)
+ O.four_color_rgb = 1;
+
+ if (IO.zero_is_bad)
+ {
+ remove_zeroes();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
+ }
+ if(O.bad_pixels)
+ {
+ bad_pixels(O.bad_pixels);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
+ }
+ if (O.dark_frame)
+ {
+ subtract (O.dark_frame);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
+ }
+
+ quality = 2 + !IO.fuji_width;
+
+ if (O.user_qual >= 0) quality = O.user_qual;
+ if (O.user_black >= 0) C.black = O.user_black;
+ if (O.user_sat > 0) C.maximum = O.user_sat;
+
+ if ( O.document_mode < 2)
+ {
+ scale_colors();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
+ }
+
+ pre_interpolate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
+
+ if (P1.filters && !O.document_mode)
+ {
+ if (quality == 0)
+ lin_interpolate();
+ else if (quality == 1 || P1.colors > 3)
+ vng_interpolate();
+ else if (quality == 2)
+ ppg_interpolate();
+ else
+ ahd_interpolate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
+ }
+ if (IO.mix_green)
+ {
+ for (P1.colors=3, i=0; i < S.height * S.width; i++)
+ imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
+ }
+
+ if(1)
+ {
+ if (P1.colors == 3)
+ {
+ median_filter();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
+ }
+
+ if (O.highlight == 2)
+ {
+ blend_highlights();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+ }
+
+ if (O.highlight > 2)
+ {
+ recover_highlights();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
+ }
+ }
+ if (O.use_fuji_rotate)
+ {
+ fuji_rotate();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
+ }
+
+ if(!libraw_internal_data.output_data.histogram)
+ {
+ libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4);
+ merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_process()");
+ }
+#ifndef NO_LCMS
+ if(O.camera_profile)
+ {
+ apply_profile(O.camera_profile,O.output_profile);
+ SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
+ }
+#endif
+
+ convert_to_rgb();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
+
+ if (O.use_fuji_rotate)
+ {
+ stretch();
+ SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
+ }
+ return 0;
+ }
+ catch ( LibRaw_exceptions err) {
+ EXCEPTION_HANDLER(err);
+ }
+}
+
+// Supported cameras:
+static const char *static_camera_list[] =
+{
+"Adobe Digital Negative (DNG)",
+"Apple QuickTake 100",
+"Apple QuickTake 150",
+"Apple QuickTake 200",
+"AVT F-080C",
+"AVT F-145C",
+"AVT F-201C",
+"AVT F-510C",
+"AVT F-810C",
+"Canon PowerShot 600",
+"Canon PowerShot A5",
+"Canon PowerShot A5 Zoom",
+"Canon PowerShot A50",
+"Canon PowerShot A460 (CHDK hack)",
+"Canon PowerShot A530 (CHDK hack)",
+"Canon PowerShot A610 (CHDK hack)",
+"Canon PowerShot A620 (CHDK hack)",
+"Canon PowerShot A630 (CHDK hack)",
+"Canon PowerShot A640 (CHDK hack)",
+"Canon PowerShot A650 (CHDK hack)",
+"Canon PowerShot A710 IS (CHDK hack)",
+"Canon PowerShot A720 IS (CHDK hack)",
+"Canon PowerShot Pro70",
+"Canon PowerShot Pro90 IS",
+"Canon PowerShot G1",
+"Canon PowerShot G2",
+"Canon PowerShot G3",
+"Canon PowerShot G5",
+"Canon PowerShot G6",
+"Canon PowerShot G7 (CHDK hack)",
+"Canon PowerShot G9",
+"Canon PowerShot G10",
+"Canon PowerShot S2 IS (CHDK hack)",
+"Canon PowerShot S3 IS (CHDK hack)",
+"Canon PowerShot S5 IS (CHDK hack)",
+"Canon PowerShot SD300 (CHDK hack)",
+"Canon PowerShot S30",
+"Canon PowerShot S40",
+"Canon PowerShot S45",
+"Canon PowerShot S50",
+"Canon PowerShot S60",
+"Canon PowerShot S70",
+"Canon PowerShot Pro1",
+"Canon EOS D30",
+"Canon EOS D60",
+"Canon EOS 5D",
+"Canon EOS 5D Mark II",
+"Canon EOS 10D",
+"Canon EOS 20D",
+"Canon EOS 30D",
+"Canon EOS 40D",
+"Canon EOS 50D",
+"Canon EOS 300D / Digital Rebel / Kiss Digital",
+"Canon EOS 350D / Digital Rebel XT / Kiss Digital N",
+"Canon EOS 400D / Digital Rebel XTi / Kiss Digital X",
+"Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2",
+"Canon EOS 1000D / Digital Rebel XS / Kiss Digital F",
+"Canon EOS D2000C",
+"Canon EOS-1D",
+"Canon EOS-1DS",
+"Canon EOS-1D Mark II",
+"Canon EOS-1D Mark III",
+"Canon EOS-1D Mark II N",
+"Canon EOS-1Ds Mark II",
+"Canon EOS-1Ds Mark III",
+"Casio QV-2000UX",
+"Casio QV-3000EX",
+"Casio QV-3500EX",
+"Casio QV-4000",
+"Casio QV-5700",
+"Casio QV-R41",
+"Casio QV-R51",
+"Casio QV-R61",
+"Casio EX-S100",
+"Casio EX-Z4",
+"Casio EX-Z50",
+"Casio EX-Z55",
+"Casio Exlim Pro 505",
+"Casio Exlim Pro 600",
+"Casio Exlim Pro 700",
+"Contax N Digital",
+"Creative PC-CAM 600",
+"Epson R-D1",
+"Foculus 531C",
+"Fuji FinePix E550",
+"Fuji FinePix E900",
+"Fuji FinePix F700",
+"Fuji FinePix F710",
+"Fuji FinePix F800",
+"Fuji FinePix F810",
+"Fuji FinePix S2Pro",
+"Fuji FinePix S3Pro",
+"Fuji FinePix S5Pro",
+"Fuji FinePix S20Pro",
+"Fuji FinePix S100FS",
+"Fuji FinePix S5000",
+"Fuji FinePix S5100/S5500",
+"Fuji FinePix S5200/S5600",
+"Fuji FinePix S6000fd",
+"Fuji FinePix S7000",
+"Fuji FinePix S9000/S9500",
+"Fuji FinePix S9100/S9600",
+"Fuji IS-1",
+"Hasselblad CFV",
+"Hasselblad H3D",
+"Hasselblad V96C",
+"Imacon Ixpress 16-megapixel",
+"Imacon Ixpress 22-megapixel",
+"Imacon Ixpress 39-megapixel",
+"ISG 2020x1520",
+"Kodak DC20 (see Oliver Hartman's page)",
+"Kodak DC25 (see Jun-ichiro Itoh's page)",
+"Kodak DC40",
+"Kodak DC50",
+"Kodak DC120 (also try kdc2tiff)",
+"Kodak DCS200",
+"Kodak DCS315C",
+"Kodak DCS330C",
+"Kodak DCS420",
+"Kodak DCS460",
+"Kodak DCS460A",
+"Kodak DCS520C",
+"Kodak DCS560C",
+"Kodak DCS620C",
+"Kodak DCS620X",
+"Kodak DCS660C",
+"Kodak DCS660M",
+"Kodak DCS720X",
+"Kodak DCS760C",
+"Kodak DCS760M",
+"Kodak EOSDCS1",
+"Kodak EOSDCS3B",
+"Kodak NC2000F",
+"Kodak ProBack",
+"Kodak PB645C",
+"Kodak PB645H",
+"Kodak PB645M",
+"Kodak DCS Pro 14n",
+"Kodak DCS Pro 14nx",
+"Kodak DCS Pro SLR/c",
+"Kodak DCS Pro SLR/n",
+"Kodak C330",
+"Kodak C603",
+"Kodak P850",
+"Kodak P880",
+"Kodak KAI-0340",
+"Konica KD-400Z",
+"Konica KD-510Z",
+"Leaf AFi 7",
+"Leaf Aptus 17",
+"Leaf Aptus 22",
+"Leaf Aptus 54S",
+"Leaf Aptus 65",
+"Leaf Aptus 75",
+"Leaf Aptus 75S",
+"Leaf Cantare",
+"Leaf CatchLight",
+"Leaf CMost",
+"Leaf DCB2",
+"Leaf Valeo 6",
+"Leaf Valeo 11",
+"Leaf Valeo 17",
+"Leaf Valeo 22",
+"Leaf Volare",
+"Leica Digilux 2",
+"Leica Digilux 3",
+"Leica D-LUX2",
+"Leica D-LUX3",
+"Leica D-LUX4",
+"Leica V-LUX1",
+"Logitech Fotoman Pixtura",
+"Mamiya ZD",
+"Micron 2010",
+"Minolta RD175",
+"Minolta DiMAGE 5",
+"Minolta DiMAGE 7",
+"Minolta DiMAGE 7i",
+"Minolta DiMAGE 7Hi",
+"Minolta DiMAGE A1",
+"Minolta DiMAGE A2",
+"Minolta DiMAGE A200",
+"Minolta DiMAGE G400",
+"Minolta DiMAGE G500",
+"Minolta DiMAGE G530",
+"Minolta DiMAGE G600",
+"Minolta DiMAGE Z2",
+"Minolta Alpha/Dynax/Maxxum 5D",
+"Minolta Alpha/Dynax/Maxxum 7D",
+"Nikon D1",
+"Nikon D1H",
+"Nikon D1X",
+"Nikon D2H",
+"Nikon D2Hs",
+"Nikon D2X",
+"Nikon D2Xs",
+"Nikon D3",
+"Nikon D3X",
+"Nikon D40",
+"Nikon D40X",
+"Nikon D50",
+"Nikon D60",
+"Nikon D70",
+"Nikon D70s",
+"Nikon D80",
+"Nikon D90",
+"Nikon D100",
+"Nikon D200",
+"Nikon D300",
+"Nikon D700",
+"Nikon E700 (\"DIAG RAW\" hack)",
+"Nikon E800 (\"DIAG RAW\" hack)",
+"Nikon E880 (\"DIAG RAW\" hack)",
+"Nikon E900 (\"DIAG RAW\" hack)",
+"Nikon E950 (\"DIAG RAW\" hack)",
+"Nikon E990 (\"DIAG RAW\" hack)",
+"Nikon E995 (\"DIAG RAW\" hack)",
+"Nikon E2100 (\"DIAG RAW\" hack)",
+"Nikon E2500 (\"DIAG RAW\" hack)",
+"Nikon E3200 (\"DIAG RAW\" hack)",
+"Nikon E3700 (\"DIAG RAW\" hack)",
+"Nikon E4300 (\"DIAG RAW\" hack)",
+"Nikon E4500 (\"DIAG RAW\" hack)",
+"Nikon E5000",
+"Nikon E5400",
+"Nikon E5700",
+"Nikon E8400",
+"Nikon E8700",
+"Nikon E8800",
+"Nikon Coolpix P6000",
+"Nikon Coolpix S6 (\"DIAG RAW\" hack)",
+"Nokia N95",
+"Olympus C3030Z",
+"Olympus C5050Z",
+"Olympus C5060WZ",
+"Olympus C7070WZ",
+"Olympus C70Z,C7000Z",
+"Olympus C740UZ",
+"Olympus C770UZ",
+"Olympus C8080WZ",
+"Olympus E-1",
+"Olympus E-3",
+"Olympus E-10",
+"Olympus E-20",
+"Olympus E-300",
+"Olympus E-330",
+"Olympus E-400",
+"Olympus E-410",
+"Olympus E-420",
+"Olympus E-500",
+"Olympus E-510",
+"Olympus E-520",
+"Olympus SP310",
+"Olympus SP320",
+"Olympus SP350",
+"Olympus SP500UZ",
+"Olympus SP510UZ",
+"Olympus SP550UZ",
+"Olympus SP560UZ",
+"Olympus SP570UZ",
+"Panasonic DMC-FZ8",
+"Panasonic DMC-FZ18",
+"Panasonic DMC-FZ28",
+"Panasonic DMC-FZ30",
+"Panasonic DMC-FZ50",
+"Panasonic DMC-FX150",
+"Panasonic DMC-G1",
+"Panasonic DMC-L1",
+"Panasonic DMC-L10",
+"Panasonic DMC-LC1",
+"Panasonic DMC-LX1",
+"Panasonic DMC-LX2",
+"Panasonic DMC-LX3",
+"Pentax *ist D",
+"Pentax *ist DL",
+"Pentax *ist DL2",
+"Pentax *ist DS",
+"Pentax *ist DS2",
+"Pentax K10D",
+"Pentax K20D",
+"Pentax K100D",
+"Pentax K100D Super",
+"Pentax K200D",
+"Pentax K2000/K-m",
+"Pentax Optio S",
+"Pentax Optio S4",
+"Pentax Optio 33WR",
+"Pentax Optio 750Z",
+"Phase One LightPhase",
+"Phase One H 10",
+"Phase One H 20",
+"Phase One H 25",
+"Phase One P 20",
+"Phase One P 25",
+"Phase One P 30",
+"Phase One P 45",
+"Pixelink A782",
+"Rollei d530flex",
+"RoverShot 3320af",
+"Samsung GX-1S",
+"Samsung GX-10",
+"Samsung S85 (hacked)",
+"Sarnoff 4096x5440",
+"Sinar 3072x2048",
+"Sinar 4080x4080",
+"Sinar 4080x5440",
+"Sinar STI format",
+"SMaL Ultra-Pocket 3",
+"SMaL Ultra-Pocket 4",
+"SMaL Ultra-Pocket 5",
+"Sony DSC-F828",
+"Sony DSC-R1",
+"Sony DSC-V3",
+"Sony DSLR-A100",
+"Sony DSLR-A200",
+"Sony DSLR-A300",
+"Sony DSLR-A350",
+"Sony DSLR-A700",
+"Sony DSLR-A900",
+"Sony XCD-SX910CR",
+"STV680 VGA",
+ NULL
+};
+
+const char** LibRaw::cameraList() { return static_camera_list;}
+int LibRaw::cameraCount() { return (sizeof(static_camera_list)/sizeof(static_camera_list[0]))-1; }
+
+
+const char * LibRaw::strprogress(enum LibRaw_progress p)
+{
+ switch(p)
+ {
+ case LIBRAW_PROGRESS_START:
+ return "Starting";
+ case LIBRAW_PROGRESS_OPEN :
+ return "Opening file";
+ case LIBRAW_PROGRESS_IDENTIFY :
+ return "Reading metadata";
+ case LIBRAW_PROGRESS_SIZE_ADJUST:
+ return "Adjusting size";
+ case LIBRAW_PROGRESS_LOAD_RAW:
+ return "Reading RAW data";
+ case LIBRAW_PROGRESS_REMOVE_ZEROES:
+ return "Clearing zero values";
+ case LIBRAW_PROGRESS_BAD_PIXELS :
+ return "Removing dead pixels";
+ case LIBRAW_PROGRESS_DARK_FRAME:
+ return "Subtracting dark frame data";
+ case LIBRAW_PROGRESS_SCALE_COLORS:
+ return "Scaling colors";
+ case LIBRAW_PROGRESS_PRE_INTERPOLATE:
+ return "Pre-interpolating";
+ case LIBRAW_PROGRESS_INTERPOLATE:
+ return "Interpolating";
+ case LIBRAW_PROGRESS_MIX_GREEN :
+ return "Mixing green channels";
+ case LIBRAW_PROGRESS_MEDIAN_FILTER :
+ return "Median filter";
+ case LIBRAW_PROGRESS_HIGHLIGHTS:
+ return "Highlight recovery";
+ case LIBRAW_PROGRESS_FUJI_ROTATE :
+ return "Rotating Fuji diagonal data";
+ case LIBRAW_PROGRESS_FLIP :
+ return "Flipping image";
+ case LIBRAW_PROGRESS_APPLY_PROFILE:
+ return "ICC conversion";
+ case LIBRAW_PROGRESS_CONVERT_RGB:
+ return "Converting to RGB";
+ case LIBRAW_PROGRESS_STRETCH:
+ return "Stretching image";
+ case LIBRAW_PROGRESS_THUMB_LOAD:
+ return "Loading thumbnail";
+ default:
+ return "Some strange things";
+ }
+}
diff --git a/Source/LibTIFF/ChangeLog b/Source/LibTIFF/ChangeLog
new file mode 100644
index 0000000..41c765c
--- /dev/null
+++ b/Source/LibTIFF/ChangeLog
@@ -0,0 +1,4371 @@
+2009-08-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff 3.9.1 released.
+
+2009-08-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirwrite.c: Back out changes from 2007-11-22 that
+ resulted in the final strip not being written in some circumstances.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2088
+
+2009-08-27 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_write.c (TIFFAppendToStrip): Remove cast which
+ caused libtiff to output a wrong last strip with byte-count and
+ strip-offset of zero. This cast was added on the day of the 3.9.0
+ release.
+
+ * libtiff/tif_config.vc.h: tiffiop.h needs the TIFF_INT64_T and
+ TIFF_UINT64_T defines in order to compile. Copy existing
+ definitions from tiffconf.vc.h.
+
+2009-08-21 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/Makefile.am (AUTOMAKE_OPTIONS): Colorized tests was not
+ actually activated since it needed to be enabled in this
+ Makefile.am. Also activated parallel-tests mode since it offers
+ useful features such as per-test .log files and a summary test
+ report .log file.
+
+2009-08-20 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff 3.9.0 released.
+
+ * libtiff/tif_print.c (TIFFPrintDirectory): Applied patch for "tag
+ error may cause segfault in tif_print.c."
+ http://bugzilla.maptools.org/show_bug.cgi?id=1896
+
+ * tools/{rgb2ycbcr.c, tiff2rgba.c}: Applied patch for
+ CVE-2009-2347 libtiff: integer overflows in various inter-color
+ space conversion tools.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2079
+
+ * configure.ac: Updated autotools. Autoconf 2.64, Automake 1.11,
+ libtool 2.2.6. Enabled support for silent build rules
+ (--enable-silent-rules or 'make V=0') and colorized tests.
+
+2009-06-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_luv.c: correct return codes from encoderow to be
+ 1 on success instead of zero.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2069
+
+2009-06-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_lzw.c: Fix buffer underflow bug.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2065
+
+2009-06-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_write.c: do not override the planar configuration to be
+ contig for one sample files if planar configuration is already set.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2057
+
+2009-02-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_luv.c: Fix handling of tiled logluv images.
+ http://bugzilla.maptools.org/show_bug.cgi?id=2005
+
+2009-01-23 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_predict.c: Add support for 32bit integer horz. predictors.
+ http://bugzilla.maptools.org/show_bug.cgi?id=1911
+
+2009-01-20 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiffsplit.c: fix sampleformat to be shortv instead of longv.
+
+2009-01-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2ps.c: Remove spurious message printed to stderr.
+
+2009-01-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiff2ps.c: Incorporated significant functionality update
+ from Richard Nolde. In particular, support for rotating the image
+ by 90, 180, 270, and 'auto' has been added.
+
+ * tools/tiffcrop.c: Incorporated significant functionality update
+ from Richard Nolde.
+
+2009-01-06 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tiffiop.h: Add private type declarations for int64, and
+ uint64 so that bundled utilities (like tiffcrop) can use it when
+ necessary.
+
+2009-01-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: Updated to test for 64-bit types. This version of
+ the library does not require a 64-bit type, but tiffcrop needs it.
+
+2008-12-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * Update to use current FSF autotools versions.
+ * libtiff/tiffio.h: GCC will now validate format specifications
+ for TIFFError(), TIFFErrorExt(), TIFFWarning(), and
+ TIFFWarningExt() in order to reveal bugs. Cleaned up resulting
+ warnings throughout for 32 bit build only.
+
+2008-12-31 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiffcrop.c, man/tiffcrop.1: A major update from Richard
+ Nolde.
+
+2008-12-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Avoid errors if the application writes a full
+ strip for the last partial strip in a jpeg compressed file.
+ http://bugzilla.maptools.org/show_bug.cgi?id=1981
+
+2008-12-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c, tiffio.h: More ABI corrections.
+ Removed SubsamplingHor/Ver from TIFFRGBAImage structure.
+ http://bugzilla.maptools.org/show_bug.cgi?id=1980
+
+2008-12-18 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c,tiffio.h: removed all use of UaToAa and
+ Bitmap16to8 arrays in TIFFRGBAImage structure to restore ABI
+ compatability. These were just an attempt to speed up processing
+ with precalculated tables.
+ http://bugzilla.maptools.org/show_bug.cgi?id=1979
+
+ * libtiff/tif_codec.c: Avoid printing c->name if it does not exist.
+
+2008-10-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_jbig.c: Support the JBIG-KIT 2.0 (compatibility with
+ the older versions retained).
+
+2008-09-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffsplit.c: Use dynamically allocated array instead of static
+ when constructing output file names.
+
+2008-09-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffsplit.c: Get rid of unsafe strcpy()/strcat() calls when
+ doing the filename/path construction.
+
+ * tools/tiff2pdf.c: More appropriate format string in
+ t2p_write_pdf_string(); avoid signed/unsigned mismatch.
+
+ * libtiff/tif_lzw.c: Properly zero out the codetable. As per bug
+
+ http://bugzilla.maptools.org/show_bug.cgi?id=1929
+
+ * libtiff/tif_lzw.c: Properly zero out the string table. Fixes
+ CVE-2008-2327 security issue.
+
+2008-05-24 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_codec.c: Avoid NULL pointer dereferencing for exotic
+ compression codec codes.
+
+ * tif_dirread.c: zero tif->tif_dir after freeing the directory
+ in TIFFReadCustomDirectory(). I don't exactly remember why this
+ was important.
+
+ * tif_dirwrite.c: Fix potential memory leak writing large double
+ tags.
+
+ * tif_dirread.c: Fix unchecked malloc result.
+
+2008-01-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tif_fax3.c: Make find0span() and find1span() non-inline to
+ make MSVC 6.0 compiler happy.
+
+2007-11-26 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_fax3.c: fix leak of FAXCS state (per bug 1603).
+
+2007-11-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.com, libtiff/tif_vms.c: Better OpenVMS support. Patches
+ from Alexey Chupahin.
+
+2007-11-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_write.c: Rip out the fancy logic in TIFFAppendToStrip() for
+ establishing if an existing tile can be rewritten to the same location
+ by comparing the current size to all the other blocks in the same
+ directory. This is dangerous in many situations and can easily
+ corrupt a file. (observed in esoteric GDAL situation that's hard to
+ document). This change involves leaving the stripbytecount[] values
+ unaltered till TIFFAppendToStrip(). Now we only write a block back
+ to the same location it used to be at if the new data is the same
+ size or smaller - otherwise we move it to the end of file.
+
+ * tif_dirwrite.c: Try to avoid writing out a full readbuffer of tile
+ data when writing the directory just because we have BEENWRITING at
+ some point in the past. This was causing odd junk to be written out
+ in a tile of data when a single tile had an interleaving of reading
+ and writing with reading last. (highlighted by gdal
+ autotest/gcore/tif_write.py test 7.
+
+ * tif_predict.c: use working buffer in PredictorEncodeTile to avoid
+ modifying callers buffer.
+ http://trac.osgeo.org/gdal/ticket/1965
+
+ * tif_predict.c/h, tif_lzw.c, tif_zip.c: Improvements so that
+ predictor based encoding and decoding works in read-write update
+ mode properly.
+ http://trac.osgeo.org/gdal/ticket/1948
+
+2007-10-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2pdf.c: Fixed setting of alpha value per report on list.
+
+2007-09-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirinfo.c: _TIFFMergeFields() now only merges in field
+ definitions that are missing. Existing definitions are silently
+ ignored. (Bug #1585)
+
+2007-07-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{Makefile.am, Makefile.v}: Do not distribute tiffconf.h,
+ remove tif_config.h/tiffconf.h during cleaning. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1573
+
+2007-07-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.9.0beta released.
+
+2007-07-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Added missed extern optind as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1567
+
+2007-07-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c: Added support 16-bit images as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1566
+
+ Patch from William Bader.
+
+ * tools/tiff2pdf.c: Fix for TIFFTAG_JPEGTABLES tag fetching and
+ significant upgrade of the whole utility as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1560
+
+ Now we don't need tiffiop.h in tiff2pdf anymore and will open output
+ PDF file using TIFFClientOpen() machinery as it is implemented
+ by Leon Bottou.
+
+2007-06-29 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_dirinfo.c (_TIFFFindFieldInfo): Don't attempt to
+ bsearch() on a NULL fieldinfo list.
+ (_TIFFFindFieldInfoByName): Don't attempt to
+ lfind() on a NULL fieldinfo list.
+
+2007-05-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirwrite.c: Fixed problem introduced with a fix for a
+ byte swapping issue
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1363
+
+ As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1550
+
+2007-04-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Check the tmpfile() return status as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=154
+
+2007-04-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.h, tif_dirread.c, tif_dirinfo.c, tif_jpeg.c,
+ tif_fax3.c, tif_jbig.c, tif_luv.c, tif_ojpeg.c, tif_pixarlog.c,
+ tif_predict.c, tif_zip.c}: Finally fix bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1274
+
+ by introducing _TIFFMergeFieldInfo() returning integer error status
+ instead of void in case of problems with field merging (e.g., if the
+ field with such a tag already registered). TIFFMergeFieldInfo() in
+ public API remains void. Use _TIFFMergeFieldInfo() everywhere and
+ check returned value.
+
+2007-04-07 Frank Warmerdam <warmerdam@pobox.com>
+
+ * contrib/addtiffo/tif_overview.c: Fix problems with odd sized output
+ blocks in TIFF_DownSample_Subsampled() (bug 1542).
+
+2007-04-06 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Changed JPEGInitializeLibJPEG() so that it
+ will convert from decompressor to compressor or compress to decompress
+ if required by the force arguments. This works around a problem in
+ where the JPEGFixupTestSubsampling() may cause a decompressor to
+ be setup on a directory when later a compressor is required with the
+ force flag set. Occurs with the addtiffo program for instance.
+
+2007-04-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirwrite.c: Fixed swapping of byte arrays stored
+ in-place in tag offsets as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1363
+
+ * tools/tiffcrop.c, man/tiffcrop.1: Significant update in
+ functionality from Richard Nolde. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1525
+
+2007-03-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_fax3.c: "inline static" -> "static inline" for IRIC CC.
+
+2007-03-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: workaround for 'Fractional scanline' error reading
+ OJPEG images with rowsperstrip that is not a multiple of vertical subsampling
+ factor. This bug is mentioned in:
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1390
+ http://www.asmail.be/msg0054766825.html
+
+2007-03-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_win32.c: made inclusion of windows.h unconditional
+
+ * libtiff/tif_win32.c: replaced preprocessor indication for consiously
+ unused arguments by standard C indication for the same
+
+2007-02-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Use uint32 type instead of tsize_t in byte
+ counters in TIFFFetchData(). Should finally fix the issue
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=890
+
+2007-02-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffset.c: Properly handle tags with TIFF_VARIABLE writecount.
+ As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1350
+
+ * libtiff/tif_dirread.c: Added special function to handle
+ SubjectDistance EXIF tag as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1362
+
+ * tools/tiff2pdf.c: Do not assume inches when the resolution units
+ do not specified. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1366
+
+ * tools/{tiffcp.c, tiffcrop.c}: Do not change RowsPerStrip value if
+ it was set as infinite. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1368
+
+ * tools/tiffcrop.c, man/tiffcrop.1: New tiffcrop utility contributed
+ by Richard Nolde. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1383
+
+2007-02-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Workaround for incorrect TIFFs with
+ ExtraSamples == 999 produced by Corel Draw. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1490
+
+ * libtiff/{tif_dirread.c, tif_read.c}: Type of the byte counters
+ changed from tsize_t to uint32 to be able to work with data arrays
+ larger than 2GB. Fixes bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=890
+
+ Idea submitted by Matt Hancher.
+
+2007-01-31 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tif2rgba.c: This utility does not work properly on big-endian
+ architectures. It was fixed including the bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1149
+
+2007-01-15 Mateusz Loskot <mateusz@loskot.net>
+
+ * Submitted libtiff port for Windows CE platform
+ * libtiff/tif_config.wince.h: Added configuration header for WinCE.
+ * libtiff/tiffconf.wince.h: Ported old configuration header for WinCE.
+ * libtiff/tif_wince.c: Added WinCE-specific implementation of some
+ functons from tif_win32.c.
+ * libtiff/tif_win32.c: Disabled some functions already reimplemented in tif_wince.c.
+ * libtiff/tiffiop.h, port/lfind.c: Added conditional include of some
+ standard header files for Windows CE build.
+ * tools/tiffinfoce.c: Ported tiffinfo utility for Windows CE.
+
+2006-11-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_write.c: TIFFAppendToStrip() - clear sorted flag if
+ we move a strip.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1359
+
+2006-10-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: More fixes for vulnerabilities, reported
+ in Gentoo bug ():
+
+ http://bugs.gentoo.org/show_bug.cgi?id=142383
+
+ * libtiff/contrib/dbs/xtiff/xtiff.c: Make xtiff utility compilable.
+ Though it is still far from the state of being working and useful.
+
+2006-10-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_fax3.c: Save the state of printdir codec dependent
+ method.
+
+ * libtiff/tif_jpeg.c: Save the state of printdir codec dependent method
+ as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1273
+
+ * libtiff/tif_win32.c: Fixed problem with offset value manipulation
+ as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1322
+
+ * libtiff/{tif_read.c, tif_jpeg.c, tif_dir.c}: More fixes for
+ vulnerabilities, reported in Gentoo bug ():
+
+ http://bugs.gentoo.org/show_bug.cgi?id=142383
+
+2006-09-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_fax3.c, tif_next.c, tif_pixarlog.c}: Fixed multiple
+ vulnerabilities, as per Gentoo bug ():
+
+ http://bugs.gentoo.org/show_bug.cgi?id=142383
+
+2006-09-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_lzw.c, libtiff/tif_zip.c: Fixed problems with mixing
+ encoding and decoding on the same read-write TIFF handle. The LZW
+ code can now maintain encode and decode state at the same time. The
+ ZIP code will switch back and forth as needed.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=757
+
+2006-09-20 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff: Rename config.h.vc and tif_config.h.vc to config.vc.h and
+ tif_config.vc.h for easier identification by folks using an IDE.
+
+2006-07-25 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_msdos.c: Avoid handle leak for failed opens. c/o Thierry Pierron
+
+2006-07-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirwrite.c: take care not to flush out buffer of strip/tile
+ data in _TIFFWriteDirectory if TIFF_BEENWRITING not set. Relates
+ to bug report by Peng Gao with black strip at bottom of images.
+
+2006-07-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirwrite.c: make sure to use uint32 for wordcount in
+ TIFFWriteNormanTag if writecount is VARIABLE2 for ASCII fields.
+ It already seems to have been done for other field types. Needed
+ for "tiffset" on files with geotiff ascii text.
+
+2006-07-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * {configure.ac, libtiff/tif_config.h.vc, libtiff/tif_jbig.c}
+ (JBIGDecode): jbg_newlen is not available in older JBIG-KIT and
+ its use does not appear to be required, so use it only when it is
+ available.
+
+2006-06-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Added missed EXIF tag ColorSpace (40961).
+
+ * libtiff/tif_dirread.c: Move IFD fetching code in the separate
+ function TIFFFetchDirectory() avoiding code duplication in
+ TIFFReadDirectory() and TIFFReadCustomDirectory().
+
+2006-06-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2pdf.c: Fix handling of -q values.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=587
+
+2006-06-17 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_readdir.c: Added case in EstimateStripByteCounts() for tiled
+ files. Modified TIFFReadDirectory() to not invoke
+ EstimateStripByteCounts() for case where entry 0 and 1 are unequal
+ but one of them is zero.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1204
+
+2006-06-08 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_open.c, tif_dirread.c, tiffiop.h}: Move IFD looping
+ checking code in the separate function TIFFCheckDirOffset().
+
+ * libtiff/tif_aux.c: Added _TIFFCheckRealloc() function.
+
+ * tools/tiffcmp.c: Fixed floating point comparison logic as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1191
+
+ * libtiff/tif_fax3.c: Fixed problems in fax decoder as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1194
+
+ * tools/tiff2pdf.c: Fixed buffer overflow condition in
+ t2p_write_pdf_string() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1196
+
+2006-06-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * {configure, configure.ac, libtiff/tif_jbig.c, tools/tiffcp.c}: Added
+ support for JBIG compression scheme (34661 code) contributed by Lee
+ Howard. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=896
+
+ * configure, configure.ac: OJPEG support enabled by default.
+
+ * contrib/ojpeg/: Removed. New OJPEG support does not need this patch.
+
+2006-06-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/{tif_dirinfo.c, tif_print.c} : Fix crash in
+ TIFFPrintDirectory(). Joris Van Damme authored the fix.
+
+2006-04-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Unified line ending characters (always use '\n')
+ as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1163
+
+ * README.vms, Makefile.am, configure.com, libtiff/{Makefile.am,
+ tif_config.h-vms, tif_stream.cxx, tif_vms.c, tiffconf.h-vms}:
+ Added support for OpenVMS by Alexey Chupahin, elvis_75@mail.ru.
+
+2006-04-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/{fax2ps.c, fax2tiff.c, ppm2tiff.c, ras2tiff.c, tiff2pdf.c}:
+ Properly set the binary mode for stdin stream as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1141
+
+ * man/{bmp2tiff.1, fax2ps.1, fax2tiff.1, gif2tiff.1, ras2tiff.1,
+ raw2tiff.1, rgb2ycbcr.1, sgi2tiff.1, tiff2bw.1, tiff2pdf.1, tiff2ps.1,
+ tiff2rgba.1, tiffcmp.1, tiffcp.1, tiffdither.1, tiffdump.1, tiffgt.1,
+ tiffset.1}: Improvements in page formatting as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1140
+
+ * html/tools.html, html/man/Makefile.am, tools/tiff2pdf.c: Fixed
+ typos as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1139
+
+2006-04-18 Frank Warmerdam <warmerdam@pobox.com>
+
+ * nmake.opt: use /EHsc for VS2005 compatibility. Also define
+ _CRT_SECURE_NO_DEPRECATE to avoid noise on VS2005.
+
+2006-04-12 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: Added support for planarconfig separate
+ non-subsampled YCbCr (i.e. separate YCbCr with subsampling [1,1])
+
+2006-04-11 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: Revision of all RGB(A) put routines
+ - Conversion of unassociated alpha to associated alpha now done with
+ more performant LUT, and calculation more correct
+ - Conversion of 16bit data to 8bit data now done with
+ more performant LUT, and calculation more correct
+ - Bugfix of handling of 16bit RGB with unassociated alpha
+
+2006-04-11 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c:
+ - When there is no alpha, gtTileSeparate and gtStripSeparate allocated
+ buffer for alpha strile and filled it, only to never read it back.
+ Removed allocation and fill.
+ - Minor rename of vars in gtTileSeparate and gtStripSeparate
+ anticipating planned functionality extension
+
+2006-04-08 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: renamed pickTileContigCase to PickContigCase
+ and pickTileSeparateCase to PickSeparateCase as both work on strips as
+ well
+
+ * libtiff/tif_getimage.c: moved img->get selection from
+ TIFFRGBAImageBegin into PickContigCase and PickSeparateCase to create
+ logical hook for planned functionality extension
+
+2006-04-08 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_ojpeg.c: resolved memory leak that was a consequence
+ of inappropriate use of jpeg_abort instead of jpeg_destroy
+
+2006-04-07 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: replaced usage of TIFFScanlineSize in
+ gtStripContig with TIFFNewScanlineSize so as to fix buggy behaviour
+ on subsampled images - this ought to get sorted when we feel brave
+ enough to replace TIFFScanlineSize alltogether
+
+ * libtiff/tif_ojpeg.c: fixed bug in OJPEGReadSkip
+
+2006-04-04 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tiffio.h: added new type tstrile_t
+
+ * libtiff/tif_dir.h: changed types of td_stripsperimage and td_nstrips
+ to new tstrile_t, types of td_stripoffset and td_stripbytecount to
+ toff_t*
+
+ * libtiff/tif_ojpeg.c: totally new implementation
+
+ * libtiff/tif_dirread.c: added several hacks to suit new support of
+ OJPEG
+
+ * libtiff/tif_getimage.c: removed TIFFTAG_JPEGCOLORMODE handling
+ of OJPEG images in favor of tif_getimage.c native handling of
+ YCbCr and desubsampling
+
+2006-03-29 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: JPEGVSetField() so that altering the photometric
+ interpretation causes the "upsampled" flag to be recomputed. Fixes
+ peculiar bug where photometric flag had to be set before jpegcolormode
+ flag.
+
+2006-03-25 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_jpeg.c: strip size related bugfix in encode raw
+
+ * libtiff/tif_strip.c: temporarilly added two new versions of
+ TIFFScanlineSize
+ - TIFFNewScanlineSize: proposed new version, after all related
+ issues and side-effects are sorted out
+ - TIFFOldScanlineSize: old version, from prior to 2006-03-21 change
+ This needs further sorting out.
+
+2006-03-25 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * contrib/addtiffo/tif_ovrcache.c: bugfix to correctly pass size
+ of last truncated strip data to TIFFWriteEncodedStrip
+
+2006-03-25 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/{tif_jpeg.c, tif_strip.c}: bugfix of tif_jpeg decode raw
+
+2006-03-25 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tif_getimage.c: bugfix/rewrite of putcontig8bitYCbCr22tile
+
+ * libtiff/tif_getimage.c: added putcontig8bitYCbCr12tile
+
+ * libtiff/tif_read.c: added support for new TIFF_NOREADRAW flag to
+ prepare the path for new tif_ojpeg.c
+
+2006-03-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.8.2 released.
+
+ * tools/Makefile.am: Use runtime paths linker flags when rpath
+ option enabled.
+
+2006-03-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/libtiff.def: Added missed exports as per bug
+ http://bugzilla.remotesensing.org/attachment.cgi?id=337
+
+ * contrib/addtiffo/Makefile.vc, libtiff/Makefile.vc, port/Makefile.vc,
+ tools/Makefile.vc: Makefiles improvements as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1128
+
+ * nmake.opt libtiff/{tif_config.h.vc, tif_unix.c, tiffio.h},
+ tools/{fax2ps.c, fax2tiff.c, tiff2pdf.c}: Fixed win32 I/O functions
+ usage as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1127
+
+ * libtiff/tif_strip.c: Take subsampling in account when calculating
+ TIFFScanlineSize().
+
+ * tools/tiffcp.c: Do not set RowsPerStrip bigger than image length.
+
+2006-03-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c: Fixed wrong TIFFerror() invocations as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1125
+
+ * tools/fax2ps.c: Fixed reading the input stream from stdin as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1124
+
+2006-03-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffiop.h: Added decalration for
+ _TIFFSetDefaultCompressionState().
+
+ * libtiff/{tif_jpeg.c, tif_fax3.c, tif_zip.c, tif_pixarlog.c,
+ tif_lzw.c, tif_luv.c}: Use _TIFFSetDefaultCompressionState() in all
+ codec cleanup methods. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1120
+
+2006-03-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_jpeg.c: Do not cleanup codec state in TIFFInitJPEG(). As
+ per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1119
+
+ * tools/raw2tiff.c: Do not set RowsPerStrip larger than ImageLength.
+ As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1110
+
+ * libtiff/tiffiop.h: dblparam_t typedef removed; GLOBALDATA macro
+ removed; move here the STRIP_SIZE_DEFAULT macro definition.
+
+ * libtiff/{tif_dirread.c, tif_strip.c}: Removed STRIP_SIZE_DEFAULT
+ macro definition.
+
+ * libtiff/tif_dir.c: Use double type instead of dblparam_t.
+
+2006-03-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Do not check the PlanarConfig tag presence
+ in TIFFReadDirectory, because it is always set at the start of
+ function and we allow TIFFs without that tag set.
+
+2005-03-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.8.1 released.
+
+2006-03-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Fixed error reporting in TIFFFetchAnyArray()
+ function as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
+
+ * libtiff/tif_dirread.c: More wise check for integer overflow
+ condition as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
+
+ * libtiff/{tif_jpeg.c, tif_pixarlog.c, tif_fax3.c, tif_zip.c}:
+ Properly restore setfield/getfield methods in cleanup functions. As
+ per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
+
+2006-03-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_predict.c, tif_predict.h}: Added new function
+ TIFFPredictorCleanup() to restore parent decode/encode/field methods.
+
+ * libtiff/{tif_lzw.c, tif_pixarlog.c, tif_zip.c}: Use
+ TIFFPredictorCleanup() in codec cleanup methods. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
+
+ * libtiff/tif_dirread.c: Fixed integer overflow condition in
+ TIFFFetchData() function. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1102
+
+2006-03-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_ojpeg.c: Set the ReferenceBlackWhite with the
+ TIFFSetField() method, not directly. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1043
+
+ * tools/ppm2tiff.c: Added support for PBM files as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1044
+
+2006-02-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_write.c: Small code rearrangement in TIFFWriteScanline()
+ to avoid crash as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1081.
+
+2006-02-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Functions t2p_sample_rgbaa_to_rgb() and
+ t2p_sample_rgba_to_rgb() was used in place of each other, that was
+ resulted in problems with RGBA images with associated alpha.
+ As per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1097
+
+2006-02-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirwrite.c: Properly write TIFFTAG_DOTRANGE tag as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1088.
+
+ * libtiff/tif_print.c: Properly read TIFFTAG_PAGENUMBER,
+ TIFFTAG_HALFTONEHINTS, TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE
+ tags as per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1088.
+
+ * tools/tiff2ps.c: Properly scale all the pages when converting
+ multipage TIFF with /width/height/center options set. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1080
+
+2006-02-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Do not create output file until all option checks
+ will be done. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1072
+
+ * tools/bmp2tiff.c: Added ability to create multipage TIFFs from the
+ list of input files as per bug:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1077
+
+2006-02-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_tile.c: Fix error reporting in TIFFCheckTile() as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1063.
+
+ * tools/tiffgt.c: Avoid crashing in case of image unsupported by
+ TIFFRGBAImage interface.
+
+ * libtiff/tif_color.c: Avoid overflow in case of wrong input as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=1065.
+
+2006-02-07 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2pdf.c: Fixed support for non-YCbCr encoded JPEG
+ compressed TIFF files, per submission from Dan Cobra.
+
+2006-02-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dirread.c, tif_packbits.c, tif_win32.c}: Properly
+ cast values to avoid warnings. As per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
+
+ * libtiff/tif_dirinfo.c: Use TIFF_NOTYPE instead of 0 when
+ appropriate. As per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
+
+ * libtiff/tif_aux.c: Fixed type of temporary variable in
+ _TIFFCheckMalloc() as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1033.
+
+2006-02-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_aux.c: Return static array when fetching default
+ YCbCrCoefficients (another problem, reported a the
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1029 entry).
+
+2006-02-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Special handling for PageNumber, HalftoneHints,
+ YCbCrSubsampling and DotRange tags as per bugs
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1029
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1034
+
+ * libtiff/tif_dirread.c: Use _TIFFGetExifFieldInfo() instead of
+ _TIFFGetFieldInfo() in TIFFReadEXIFDirectory() call as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1026.
+
+2006-01-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtool related stuff updated from the 2.1a branch.
+
+2006-01-11 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/bmp2tiff,pal2rgb,ppm2tiff,ras2tiff,raw2tiff,sgi2tiff,
+ tiff2bw,tiffcp: Fixed jpeg option processing so -c jpeg:r:50 works
+ properly as per bug:
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1025
+
+2006-01-09 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: Fix with_default_strip_size comparison as reported
+ by Norihiko Murase.
+
+2006-01-08 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * test/Makefile.am (LIBTIFF): Due to linking against libtiff
+ incorrectly, tests were not actually testing the uninstalled
+ libtiff. Now they are.
+
+2006-01-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Change definitions for TIFFTAG_ICCPROFILE,
+ TIFFTAG_PHOTOSHOP, TIFFTAG_RICHTIFFIPTC, TIFFTAG_XMLPACKET: readcount
+ should be uint32 value.
+
+2006-01-02 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/man/Makefile.am (htmldoc): Fix htmldoc rule so that it can
+ be used if build directory is not the same as source directory.
+ * man/{TIFFGetField.3tiff, TIFFSetField.3tiff}: Documented
+ TIFFTAG_PHOTOSHOP, TIFFTAG_RICHTIFFIPTC, and TIFFTAG_XMLPACKET,
+ and re-sorted tag names in alphabetical order.
+
+2005-12-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.8.0 released.
+
+2005-12-28 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/bmp2tiff.c (main): Fixed warning regarding returning
+ inconsistent types from a condition.
+ * tools/tiffcmp.c (CheckLongTag): Eliminate warning due to printf
+ format.
+ * tools/bmp2tiff.c: Reduce compilation warnings on big-endian CPUs.
+
+2005-12-28 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * html/{index.html, support.hml, libtiff.html}: Cleaned up HTML
+
+2005-12-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffio.h: Added VC_EXTRALEAN definition before including
+ windows.h, to reduce the compile time.
+
+2005-12-26 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_jpeg.c: Improve compilation under MinGW.
+
+2005-12-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.c, tif_dir.h, tif_dirread.c, tif_dirinfo.c}:
+ tiffFieldInfo and exifFieldInfo arrays definitions moved back to
+ tif_dirinfo.c; added _TIFFGetFieldInfo() and _TIFFGetExifFieldInfo()
+ private functions to retrieve FieldInfo arrays.
+
+2005-12-24 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/build.html: Added some additional instructions for when
+ building using MSVC under Windows. Also fixed two HTML syntax
+ errors and used HTML Tidy to tidy up the HTML syntax and
+ formatting.
+
+2005-12-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_aux.c, tif_dir.c, tif_dir.h, tif_dirwrite.c,
+ tif_print.c, tif_getimage.c}: Make InkSet, NumberOfInks, DotRange and
+ StoNits tags custom.
+
+2005-12-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_aux.c, tif_dir.c, tif_dir.h, tif_print.c}: Make
+ WhitePoint tag custom.
+
+ * libtiff/{tif_dir.h, tiff.h}: More EXIF tags added.
+
+2005-12-23 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/tiffio.h: fixed typo that potentially resulted in
+ redefininition of USE_WIN32_FILEIO
+
+ * libtiff/*: Added more 'dual-mode' error handling: Done TIFFWarning
+ calls in core LibTiff.
+
+2005-12-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.c, tif_dir.h, tif_print.c}: Make RichTIFFIPTC,
+ Photoshop and ICCProfile tags custom.
+
+2005-12-21 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * libtiff/*, contrib/*: Added 'dual-mode' error handling, enabling
+ newer code to get context indicator in error handler and still
+ remain compatible with older code: Done TIFFError calls everywhere
+ except in tools
+
+2005-12-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Added many error reporting messages; fixed integer
+ overflow as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=789
+
+2005-12-16 Frank Warmerdam <warmerdam@pobox.com>
+
+ * contrib/addtiffo/*: Major upgrade by Joris to support subsampled
+ YCbCr images in jpeg compressed TIFF files.
+
+2005-12-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Return non-zero status when reading fails (again).
+
+2005-12-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Return non-zero status when reading fails.
+
+2005-12-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.h, tiff.h}: Added more EXIF tags.
+
+2005-12-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.c, tif_dir.h, tif_print.c}: Make XMLPacket tag
+ custom.
+
+ * tools/tiffinfo.c: Print EXIF directory contents if exist.
+
+ * libtiff/tiff.h: Few EXIF tag numbers added.
+
+ * libtiff/{tif_dirinfo.c, tif_dirread.c, tif_dir.h, tif_dir.c,
+ tiffio.h}: Preliminary support to read custom directories. New
+ functions: TIFFReadCustomDirectory() and TIFFReadEXIFDirectory().
+
+2005-12-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dirinfo.c, tif_dirread.c, tif_dir.h, tif_dir.c}:
+ More work to implement custom directory read support.
+
+ * libtiff/{tif_aux.c, tif_dirinfo.c, tif_dirread.c, tif_dir.h,
+ tif_dir.c, tif_print.c}: Make YCbCrCoefficients and ReferenceBlackWhite
+ tags custom.
+
+2005-12-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: One more workaround for broken
+ StripByteCounts tag. Handle the case when StripByteCounts array filled
+ with completely wrong values.
+
+2005-11-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Release file descriptor in case of failure
+ in the TIFFOpenW() function as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1003
+
+ * libtiff/tif_dirinfo.c: Correctly yse bsearch() and lfind()
+ functions as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1008
+
+2005-11-20 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_open.c, tiff.h, tiffdump.c: Incorporate preliminary support
+ for MS MDI format.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=1002
+
+ * .cvsignore: many files added, and a few update according
+ to suggestion of Brad HArds on tiff mailing list.
+
+2005-11-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/libtiff.def, tiffiop.h, tiffio.h: Made TIFFFreeDirectory
+ public.
+
+2005-10-31 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c: Properly calculate sizes of temporary arrays
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=943
+
+ * tools/fax2tiff.c: Added option '-r' to set RowsPerStrip parameter
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=944
+
+ * tools/tiffdump.c: Fixed typeshift and typemask arrays initialization
+ problem as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=946
+
+ * tools/bmp2tiff.c: Fixed possible integer overflow error as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=965
+
+ * libtiff/tif_dirinfo.c: Make XResolution, YResolution and
+ ResolutionUnit tags modifiable during write process. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=977
+
+ * tools/tiffsplit.c: Copy fax related fields over splitted parts
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=983
+
+2005-10-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirread.c: Don't try and split single strips into "0" strips
+ in ChopUpSingleUncompressedStrip. This happens in some degenerate
+ cases (like 1x1 files with stripbytecounts==0 (gtsmall.jp2 embed tiff)
+
+2005-10-20 Joris Van Damme <joris.at.lebbeke@skynet.be>
+
+ * tif_fax3.c: changed 'at scanline ...' style warning/errors
+ with incorrect use of tif_row, to 'at line ... of
+ strip/tile ...' style
+
+2005-10-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_write.c: fixed setting of planarconfig as per bug report
+ on the mailing list from Joris.
+
+2005-10-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, configure, nmake.opt, libtiff/{tif_config.h,
+ tif_dirread.c}: Make the default strip size configurable via the
+ --with-default-strip-size and STRIP_SIZE_DEFAULT options.
+
+2005-09-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * html/support.html: Fixed link to documentation on Greg Ward's
+ LogLuv TIFF format.
+
+2005-09-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffdump.c: Fixed crash when reading malformed tags.
+
+2005-09-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Added missed 'break' statement as per bug
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=932
+
+2005-09-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.4 released.
+
+ * {configure, configure.ac, Makefile.am, autogen.sh}: Applied patch
+ from Patrick Welche (all scripts moved in the 'config' and 'm4'
+ directories).
+
+2005-09-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: reintroduce seek to avoid problem on solaris.
+
+2005-09-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: When prefreeing tv->value in TIFFSetFieldV
+ also set it to NULL to avoid double free when re-setting custom
+ string fields as per:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=922
+
+2005-08-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_print.c: avoid signed/unsigned warning.
+
+ * libtiff/tif_dirread.c: removed unused variable.
+
+2005-07-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: Fixed up support for swapping "double complex"
+ values (128 bits as 2 64 bits doubles). GDAL gcore tests now
+ pass on bigendian (macosx) system.
+
+2005-07-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_aux.c, tif_dirread.c, tif_fax3.c, tiffiop.h}: Rename
+ CheckMalloc() function to _TIFFCheckMalloc() and make it available
+ globally as an internal helper routine.
+
+2005-07-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: More improvements in the "pass by value" part of
+ the custom tags handling code.
+
+2005-07-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dirread.c, tif_dirinfo.c}: Do not upcast BYTEs to
+ SHORTs in the TIFFFetchByteArray(). Remove TIFFFetchExtraSamples()
+ function, use TIFFFetchNormalTag() instead as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=831
+
+ Remove TIFFFetchExtraSamples() function, use TIFFFetchNormalTag()
+ instead.
+
+ * libtiff/tiffconf.h.in: One more attempt to fix the AIX bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+2005-07-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_print.c: Fixed printing of the BYTE and SBYTE arrays.
+
+ * tools/tiffdump.c: Added support for TIFF_IFD datatype.
+
+2005-07-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_write.c: Do not check the PlanarConfiguration field in
+ the TIFFWriteCheck() function in case of single band images (as per
+ TIFF spec).
+
+2005-07-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * SConstruct, libtiff/SConstruct: Added the first very preliminary
+ support for SCons software building tool (http://www.scons.org/).
+ This is experimental infrastructure and it will exist along with the
+ autotools mechanics.
+
+2005-07-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * port/{getopt.c, strcasecmp.c, strtoul.c}: Update modules from
+ the NetBSD source tree (the old 4-clause BSD license changed to
+ the new 3-clause one).
+
+ * configure.ac, port/lfind.c, libtiff/tiffiop.h: Added lfind()
+ replacement module.
+
+ * port/dummy.c: Make the dummy function static.
+
+2005-07-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Fixed WhitePoint tag copying.
+
+ * libtiff/{tif_dir.c, tif_dir.h, tif_dirinfo.c, tif_print.c}:
+ Make FieldOfViewCotangent, MatrixWorldToScreen, MatrixWorldToCamera,
+ ImageFullWidth, ImageFullLength and PrimaryChromaticities tags custom.
+
+2005-07-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.3 released.
+
+ * configure, configure.ac: Do not use empty -R option when linking
+ with --enable-rpath.
+
+2005-07-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffiop.h, tif_open.c}: Added open option 'h' to avoid
+ reading the first IFD when needed. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=875
+
+ * libtiff/tif_color.c: Better use of TIFFmin() macro to avoid side
+ effects.
+
+2005-06-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Print two characters per loop in the
+ t2p_write_pdf_trailer(). As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=594
+
+ * tools/tiffgt.c: Use MacOS X OpenGL framework when appropriate. As
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=844
+
+ * acinclude.m4: Updated to latest OpenGL test macros versions.
+
+ * libtiff/tiff.h: Use correct int size on Sparc 64bit/Sun compiler
+ platform. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=855
+
+2005-06-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Added support for ClipPath, XClipPathUnits
+ and YClipPathUnits tags.
+
+2005-06-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * contrib/addtiffo/tif_ovrcache.c: Properly extract tile/strip size;
+ use pixel sized shift in contigous case.
+
+2005-06-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * contrib/addtiffo/{tif_overview.c, tif_ovrcache.c, tif_ovrcache.h}:
+ Make overviews working for contiguos images.
+
+2005-06-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_open.c: Replace runtime endianess check with the compile
+ time one.
+
+ * libtiff/tif_predict.c: Floating point predictor now works on
+ big-endian hosts.
+
+2005-06-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Use _TIFFsetString() function when read custom
+ ASCII values.
+
+ * libtiff/{tif_dirinfo.c, tif_dir.h, tif_dir.c, tif_print.c}: Make
+ DocumentName, Artist, HostComputer, ImageDescription, Make, Model,
+ Copyright, DateTime, PageName, TextureFormat, TextureWrapModes and
+ TargetPrinter tags custom.
+
+ * libtiff/tif_jpeg.c: Cleanup the codec state depending on
+ TIFF_CODERSETUP flag (to fix memry leaks).
+
+ * libtiff/tif_jpeg.c: Initialize JPEGTables array with zero after
+ allocating.
+
+2005-05-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, libtiff/Makefile.am: Added workaround for
+ OpenBSD/MirOS soname problem as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=838
+
+ * libtiff/tif_dirwrite.c: Use tdir_count when calling
+ TIFFCvtNativeToIEEEDouble() in the TIFFWriteDoubleArray() function as
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=845
+
+2005-05-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/ppm2tiff.c: Fixed format string when read PPM file header with
+ the fscanf() function. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=861
+
+ * libtiff/{tif_dirinfo.c, tif_print.c}: TIFFFetchByteArray() returns
+ uint16 array when fetching the BYTE and SBYTE filds, so we should
+ consider result as pointer to uint16 array and not as array of chars.
+ As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=831
+
+ * libtiff/tif_dir.c: More efficient custom tags retrieval as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=830
+
+ * libtiff/tif_win32.c: Use FILE_SHARE_READ | FILE_SHARE_WRITE share
+ mode in CreateFile() call as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=829
+
+ * libtiff/Makefile.am: Fixed parallel compilation of the libtiff and
+ libtiffxx libraries as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=826
+
+ * contrib/addtiffo/{tif_overview.c, tif_ovrcache.h}: Sinchronized with
+ GDAL.
+
+2005-05-23 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Substantial fix for addtiffo problems with
+ JPEG encoded TIFF files. Pre-allocate lots of space for jpegtables
+ in directory.
+
+2005-05-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirread.c: Changed the code that computes
+ stripbytecount[0] if it appears bogus to ignore if stripoffset[0] is
+ zero. This is a common case with GDAL indicating a "null" tile/strip.
+
+2005-05-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffsplit.c: Check for JPEGTables tag presence before copying.
+
+2005-05-06 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirread.c: Applied similar change to
+ TIFFFetchPerSampleLongs and TIFFFetchPerSampleAnys.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=843
+
+ * libtiff/tif_jpeg.c: added LIB_JPEG_MK1 support in JPEGDecodeRaw().
+
+2005-05-06 Andrey Kiselev <dron@ak4719.spb.edu>
+ * tools/tiff2pdfr.c, man/tiff2pdf.1: Calculate the tile width properly;
+ added new option '-b' to use interpolation in output PDF files (Bruno
+ Ledoux).
+
+2005-05-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirread.c: Ensure that broken files with too many
+ values in PerSampleShorts work ok instead of crashing.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=843
+
+2005-04-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffdither.c: Copy the PhotometricInterpretation tag from the
+ input file.
+
+2005-04-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_predict.c: Added ability to encode floating point
+ predictor, as per TIFF Technical Note 3.
+
+2005-04-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_predict.h, tif_predict.c}: Added ability to decode
+ floating point predictor, as per TIFF Technical Note 3.
+
+2005-04-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.h, tiffiop.h, tif_dir.c, tif_read.c, tif_swab.c}:
+ Added _TIFFSwab24BitData() and TIFFSwabArrayOfLong() functions used to
+ swap 24-bit floating point values.
+
+ * libtiff/tiff.h: Added predictor constants.
+
+2005-04-08 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffiop.h, tif_dir.c}: Use uint32 type for appropriate
+ values in _TIFFVSetField() function. Inspired by the bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=816
+
+ * man/TIFFSetField.3tiff: Fixed definition of the TIFFTAG_INKNAMES tag
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=816
+
+2005-03-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_open.c: Do not read header in case the output file
+ should be truncated (Ron).
+
+ * libtiff/{tif_dirinfo.c, tif_config.h.vc}: Use lfind() instead
+ of bsearch() in _TIFFFindFieldInfoByName() function (Ron).
+
+ * libtiff/{tiff.h, tif_dirinfo.c}: Fixes in EXIF tag ordering (Ron).
+
+2005-03-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, libtiff/Makefile.am: Use libtool machinery to pass
+ rpath option.
+
+2005-03-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.c, tif_print.c}: Handle all data types in custom
+ tags.
+
+2005-03-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/dirinfo.c: Added DNG tags.
+
+ * libtiff/{tif_dir.c, tif_print.c}: More improvements in custom tag
+ handling code.
+
+ * libtiff/tiff.h: More comments; added missed DNG tag (LensInfo);
+ added DNG 1.1.0.0 tags.
+
+ * tools/tif2pdf.c: Fixed problem with alpha channel handling as per
+ bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=794
+
+ * man/TIFFGetField.3tiff: Add a note about autoregistered tags.
+
+2005-03-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * nmake.opt: Build with Win32 CRT library by default.
+
+ * tools/tiff2ps.c: Fixed typo in page size handling code.
+
+ * libtiff/{tif_dir.c, tif_print.c}: Support for custom tags, passed
+ by value.
+
+ * libtiff/{tiff.h, tif_dirinfo.c, tiffiop.h}: Added EXIF related tags.
+
+2005-03-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.2 released.
+
+2005-03-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcmp.c: Added ability to compare the 32-bit integer and
+ floating point data; complain on unsupported bit depths.
+
+2005-03-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tif_stream.cxx: Use ios namespace instead of ios_base to support
+ GCC 2.95.
+
+ * libtiff/{tiff.h, tif_fax3.tif, tif_jpeg.c}: Applied correct patch from
+ Lee Howard for HylaFax DCS tag
+ (see http://bugzilla.remotesensing.org/show_bug.cgi?id=771)
+
+2005-03-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure, configure.ac: Use -rpath option instead of -R as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=732
+
+ * libtiff/{tiff.h, tif_fax3.tif, tif_jpeg.c}: Applied patch from Lee
+ Howard to support a new tag TIFFTAG_FAXDCS (34911) used in HylaFax
+ software. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=771
+
+ * nmake.opt, html/build.html: Add more comments, change the config
+ file organization a bit as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=764
+
+ * tools/tiffcmp.c: Use properly sized buffer in short arrays comparison
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=785
+
+2005-03-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: More logic to guess missed strip size as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=705
+
+ * tools/fax2ps.c: Replace insecure mktemp() function with the
+ tmpfile() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=786
+
+2005-02-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiff.h: Changed the int8 definition to be always signed char
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=727
+
+ * libtiff/tiffio.h: Move TIFFOpenW() function into the extern "C"{}
+ block as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=763
+
+2005-02-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffgt.c: Fix problem on big-endian CPUs so that images
+ display more correctly. Images display brighter than they should
+ on a Sun workstation.
+
+2005-02-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Estimate strip size in case of wrong or
+ suspicious values in the tags. As per bugs
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=705
+
+ and
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=320
+
+ * tools/tiff2ps.c: Fixed problem with page sizes as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=742
+
+2005-01-31 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tiff.h (TIFFTAG_TILEWIDTH): Corrected description.
+ (TIFFTAG_TILELENGTH): Corrected description.
+
+2005-01-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac: Fixes for --with-docdir option as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=759
+
+ * libtiff/tif_open.c: Remove unnesessary TIFFSeekFile() call as per
+ bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=756
+
+ * libtiff/tif_stream.cxx: Fixes for C++ stream interface from
+ Michael Rinne and Edward Lam.
+
+2005-01-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac: Make the documentation directory location configurable
+ via the --with-docdir option (as suggested by Jeremy C. Reed).
+
+ * libtiff/tif_color.c: Use double as the second argument of pow()
+ function in TIFFCIELabToRGBInit(). As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=741
+
+ * libtiff/tif_pixarlog.c: Avoid warnings when converting float to
+ integer as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=740
+
+ * libtiff/tif_getimage.c: Always fill the error message buffer in
+ TIFFRGBAImageBegin() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=739
+
+2005-01-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_jpeg.c: Added ability to read/write the fax specific
+ TIFFTAG_FAXRECVPARAMS, TIFFTAG_FAXSUBADDRESS and TIFFTAG_FAXRECVTIME
+ tags as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=736
+
+ * libtiff/tif_win32.c: Fixed message formatting in functions
+ Win32WarningHandler() and Win32ErrorHandler() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=735
+
+ * tools/tiff2ps.c: Interpret the -w and -h options independently. As
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=689
+
+2005-01-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffio.h: Move the color conversion routines in the 'extern
+ "C"' section as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=727
+
+ * libtiff/tiff.h: Restore back the workaround for AIX Visual Age C
+ compiler to avoid double definition of BSD types as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+ * libtiff/Makefile.am: Place the C++ stream API in the separate
+ library called libtiffxx to avoid unneeded dependencies. Probably
+ there will be more C++ API in the future. As per bugs
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=733
+
+ and
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=730
+
+2005-01-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffdump.c: Fixed problem when read broken TIFFs with the
+ wrong tag counts (Dmitry V. Levin, Martin Pitt).
+
+ * configure.ac: Replace --disable-c++ with the --disable-cxx option as
+ per bug http://bugzilla.remotesensing.org/show_bug.cgi?id=730
+
+2004-12-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_getimage.c: More fixes for multiple-alpha-channelled
+ RGB-images as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=713
+
+
+ * tools/tiffset.c: Convert character option to integer value as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=725
+
+2004-12-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.1 released.
+
+ * html/tiffset.1.html: Add missed manual page as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=678
+
+ * libtiff/tiff.h: Revert back libtiff data type definitions as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=687
+
+2004-12-19 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Do not forget about TIFF_VARIABLE2 when
+ checking for tag count in TIFFReadDirectory() function. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=713
+
+ * libtiff/{tif_dirread.c, tif_fax3.c}: More argument checking in
+ CheckMallock() function.
+
+ * libtiff/tif_getimage.c: Support for multiple-alpha-channelled
+ RGB-images as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=718
+
+2004-12-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c: #define A1 bracketing for clean build on
+ SunPro compiler.
+
+2004-12-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * autogen.sh: aclocal and autoheader should be executed after
+ libtoolize. Also add '-I .' to aclocal invocation to check
+ current directory for macros.
+
+2004-12-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirwrite.c: Always write TIFFTAG_SUBIFD using LONG type
+ as per bugs
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=703
+
+ and
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=704
+
+2004-12-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * nmake.opt: Link with the user32.lib in windowed mode. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=697
+
+ * libtiff/tif_win32.c: Use char* strings instead of TCHAR in windowed
+ mode as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=697
+
+ * libtiff/tif_config.in.vc: Removed unneded definitions for
+ read/open/close/lseek functions to fix the
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=680
+
+2004-12-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.c, tif_dirread.c}: Remove TIFFReassignTagToIgnore()
+ call from the TIFFReadDirectory() function. TIFFReassignTagToIgnore
+ must be removed in the future, as it was never used properly. As per
+ bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=692
+
+2004-11-30 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_jpeg.c: Added a work-around in order to allow
+ compilation with the heavily modified version of libjpeg delivered
+ with Cygwin.
+
+2004-11-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Properly handle tags, which have the uint32
+ counts. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=693
+
+ * tools/fax2ps.c: Be able to extract the first page (#0). As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=690
+
+2004-11-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_unix.c: Make UNIX module compilable (and usable)
+ on Windows.
+
+ * nmake.opt: Add missed DLLNAME variable.
+
+2004-11-26 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/makefile.vc: make it easier to rename the libtiff DLL.
+
+2004-11-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * man/libtiff.3tiff: Improvements in the "LIST OF ROUTINES" table as
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=545
+
+ * man/tiffset.1: Added manual page for tiffset tool written by Jay
+ Berkenbilt. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=678
+
+2004-11-23 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_error.c: fixed TIFFerror call to be TIFFError.
+
+2004-11-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/document.html: Updated Adobe web links as per email from Joris.
+
+2004-11-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.hxx, tiffio.h}: C++ stream interface moved to new
+ file tiffio.hxx. We don't have any C++ in tiffio.h, those who want to
+ use C++ streams should #include <tiffio.hxx>.
+
+2004-11-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiff.h: Added Adobe DNG tags.
+
+ * libtiff/tif_win32.c: Typo fixed.
+
+ * libtiff/{tif_stream.cxx, tiffio.h}: C++ stream interface updated to
+ be compliant with the latest standard. Appropriate additions in
+ makefiles now completed.
+
+2004-11-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffset.c, libtiff/tif_dirinfo.c: Properly handle the
+ different tag types. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=600
+
+2004-11-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_aux.c: Set the appropriate ReferenceBlackWhite array for
+ YCbCr image which lacks that tag (noted by Hans Petter Selasky).
+
+2004-11-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_color.c: Division by zero fixed (Hans Petter Selasky).
+
+2004-11-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_stream.cxx, tiffio.h}: Added C++ stream interface
+ contributed by Edward Lam (see
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=654 for details).
+ Though no changes in any makefiles yet.
+
+2004-11-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: Removed close() in TIFFClientOpen() if file
+ is bad. This is the callers responsibility.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=651
+
+2004-11-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.h, tif_win32.c, libtiff.def}: Added TIFFOpenW()
+ function to work with the double byte strings (used to represent
+ filenames in some locales). As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=625
+
+ * libtiff/tif_dirread.c: Fixed problem when fetching BitsPerSample and
+ Compression tags of type LONG from broken TIFFS as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=662
+
+ * libtiff/tif_dirinfo.c: Fixed definition for TIFFTAG_RICHTIFFIPTC,
+ the writecount should have uint32 type. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=662
+
+ * libtiff/tif_write.c: Fixed wrong if() statement in
+ TIFFAppendToStrip() function as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=660
+
+2004-11-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Change definition for TIFFTAG_EXTRASAMPLES
+ field. The caller should supply a count when setting this field. As
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=648
+
+ * libtiff/{tif_jpeg.c, tif_ojpeg.c}: TIFFTAG_JPEGTABLES should have
+ uint32 count. Use this type everywhere.
+
+2004-11-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_next.c: avoid use of u_long and u_char types. Bug 653.
+
+2004-11-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2rgba.c: removed extra newlines in usage message.
+
+2004-10-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirwrite.c: Improvements in tag writing code.
+
+ * tools/tiff2ps.c: Fixed wrong variable data type when read Position
+ tags (Tristan Hill).
+
+2004-10-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiffiop.h: added fallback definition of assert() if we
+ don't have assert.h.
+
+2004-10-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_fax3.c: Fixed case with the wrong decode routines
+ choosing when the incorrect Group4Options tag set. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=323
+
+ * libtiff/tif_dirwrite.c: Fixed problem with passing count variable of
+ wrong type when writing the TIFF_BYTE/TIFF_SBYTE tags in
+ TIFFWriteNormalTag().
+
+2004-10-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c: Fixed wrong variable data type when read Resolution
+ tags (Peter Fales).
+
+ * tools/{bmp2tiff.c, raw2tiff.c}: Get rid of stream I/O functions.
+
+2004-10-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2pdf.c: added casts to avoid warnings.
+
+ * libtiff/libtiff.def: Added several more entry points required
+ to link fax2tiff.c against the DLL on windows.
+
+2004-10-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure, configure.ac: Added --enable-rpath option to embed linker
+ paths into library binary.
+
+2004-10-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffset.c: Check the malloc return value (Dmitry V. Levin).
+
+ * libtiff/{tif_strip.c, tif_tile.c}: Zero division problem fixed
+ (Vladimir Nadvornik, Dmitry V. Levin).
+
+2004-10-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.0 released.
+
+2004-10-15 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tif_jpeg.c: There seems to be no need to include stdio.h
+ in this file so its inclusion is removed. Including stdio.h
+ sometimes incurs an INT32 typedef conflict between MinGW's
+ basetsd.h and libjpeg's jmorecfg.h.
+
+2004-10-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * man/bmp2tiff.1: Added manual page for bmp2tiff utility.
+
+2004-10-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffcmp.c (leof): Renamed from 'eof' in order to avoid
+ conflict noticed under MinGW.
+ * ltmain.sh: Fix for MinGW compilation.
+
+2004-10-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * man/tiffsplit.1: Fixed to indicate using aaa-zzz, not aa-zz.
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=635
+
+2004-10-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dirread.c, tif_jpeg.c, tif_luv.c, tif_ojpeg.c,
+ tif_pixarlog.c, tif_write.c}: Handle the zero strip/tile sizes
+ properly (Dmitry V. Levin, Marcus Meissner).
+
+2004-10-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Type of the TIFFTAG_SUBIFD field changed
+ to TIFF_IFD.
+
+2004-10-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/bmp2tif.c: Check the space allocation results.
+
+2004-10-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Initialize td_tilewidth and td_tilelength fields
+ of the TIFFDirectory structure with the 0 instead of -1 to avoid
+ confusing integer overflows in TIFFTileRowSize() for striped images.
+
+ * tools/tiff2pdf.c: Fixed TransferFunction tag handling reported
+ by Ross A. Finlayson.
+
+ * libtiff/tif_dir.c: Fixed custom tags handling as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=629
+
+2004-10-08 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirinfo.c: Fix bug with tif_foundfield and reallocation
+ of tif_fieldinfo.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=630
+
+2004-10-04 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * contrib/iptcutil/README: Added the missing README which goes
+ along with iptcutil.
+
+2004-10-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_compress.c: Improved error reporting in
+ TIFFGetConfiguredCODECs() (Dmitry V. Levin).
+
+2004-10-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.0beta2 released.
+
+ * libtiff/{tif_aux.c, tif_compress.c, tif_dirinfo.c, tif_dirwrite.c,
+ tif_extension.c, tif_fax3.c, tif_luv.c, tif_packbits.c,
+ tif_pixarlog.c, tif_write.c}: Added checks for failed memory
+ allocations and integer overflows (Dmitry V. Levin).
+
+ * libtiff/tiff.h: Missed TIFF_BIGTIFF_VERSION constant added.
+
+2004-10-01 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: added a more informative message if a BigTIFF
+ file is opened.
+
+2004-09-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirinfo.c: changed type of XMLPacket (tag 700) to
+ TIFFTAG_BYTE instead of TIFFTAG_UNDEFINED to comply with the info
+ in the Adobe XMP Specification.
+
+2004-09-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_jpeg.c, tif_pixarlog.c}: Use _TIFFmemset() instead of
+ memset().
+
+ * libtiff/{tif_dirread.c, tif_strip.c, tif_tile.c}: Applied patches
+ from Dmitry V. Levin to fix possible integer overflow problems.
+
+2004-09-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_getimage.c: Check for allocated buffers before clearing
+ (Dmitry V. Levin).
+
+2004-09-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dir.h, tif_dir.c, tif_dirread.c, tif_write.c}:
+ Optimize checking for the strip bounds.
+
+ * libtiff/{tif_dirread.c, tif_strip.c}: TIFFScanlineSize() and
+ TIFFRasterScanlineSize() functions report zero in the case of integer
+ overflow now. Properly handle this case in TIFFReadDirectory()
+ (patches from Dmitry V. Levin).
+
+2004-09-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_dirinfo.c, tif_strip.c, tif_tile.c}: Use TIFFhowmany8()
+ macro where appropriate.
+
+ * tools/tiff2bw.c: Write ImageWidth/Height tags to output file, as
+ noted by Gennady Khokhorin.
+
+ * libtiff/tif_dirread.c: Always check the return values, returned
+ by the _TIFFmalloc() (Dmitry V. Levin).
+
+ * libtiff/tif_dir.c: Fixed possible integer overflow _TIFFset*Array()
+ functions (Dmitry V. Levin).
+
+ * libtiff/{tif_dirread.c, tif_dir.c, tif_write.c}:
+ Potential memory leak fixed in TIFFReadDirectory(), _TIFFVSetField(),
+ TIFFGrowStrips() (found by Dmitry V. Levin).
+
+2004-09-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.h, tif_compress.c}: Added TIFFGetConfiguredCODECs()
+ to get the list of configured codecs.
+
+ * libtiff/{tiffiop.h, tif_dirread.c}: More overflow fixes from
+ Dmitry V. Levin.
+
+2004-09-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Applied patch from Dmitry V. Levin to fix
+ possible integer overflow in CheckMalloc() function.
+
+2004-09-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffiop.h, tif_strip.c}: Use TIFFhowmany8() macro instead
+ of plain TIFFhowmany() where appropriate.
+
+2004-09-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_getimage.c: Initialize arrays after space allocation.
+
+2004-09-19 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.0beta released.
+
+ * libtiff/{tif_luv.c, tif_next.c, tif_thunder.c}: Several buffer
+ overruns fixed, as noted by Chris Evans.
+
+2004-09-14 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * commit: Added a script to make it more convenient to commit
+ updates. The CVS commit message is extracted from this ChangeLog
+ file.
+
+2004-09-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, configure, aclocal.m4, libtiff/{mkspans.c, tif_fax3.c,
+ tif_getimage.c, tif_luv.c, tif_lzw.c, tif_ojpeg.c, tif_packbits.c,
+ tif_predict.c, tif_read.c, tif_swab.c, tif_thunder.c, tif_write.c,
+ tif_dir.c, tif_dirread.c, tif_dirwrite.c, tif_jpeg.c, tif_dirinfo.c,
+ tif_vms.c, tif_print.c, tif_strip.c, tif_tile.c, tif_dir.h,
+ tif_config.h.in, tiffiop.h}:
+ Get rid of BSD data types (u_char, u_short, u_int, u_long).
+
+2004-09-13 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * libtiff/tiff.h: Fix column tagging. Reference current Adobe XMP
+ specification. Reference libtiff bug tracking system to submit
+ private tag additions.
+
+2004-09-12 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * tools/tiffgt.c: Include "tif_config.h".
+
+ * configure.ac: Use AM_PROG_CC_C_O since it is now needed to build
+ tiffgt. This results in the 'compile' script being added to the
+ project.
+
+ * tools/Makefile.am (tiffgt_CFLAGS): Add extra build options
+ required to find OpenGL headers necessary to build tiffgt. Also
+ ensure that the libtiff that we built is used rather than some other
+ libtiff installed on the system.
+
+2004-09-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, acinclude.m4, aclocal.m4: New macros to detect GLUT
+ libraries.
+
+2004-09-11 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
+
+ * configure.ac: Pass library configuration defines via
+ tif_config.h rather than extending CPPFLAGS. Configure a
+ libtiff/tiffconf.h in order to satisfy application requirements
+ (not used by library build). Do not define _POSIX_C_SOURCE=2 since
+ this causes failure to build on systems which properly respect
+ this request.
+
+ * libtiff/tiffconf.h.in: New file to act as the template for the
+ configured tiffconf.h
+
+ * libtiff/files.lst (HDRS): Install the configured tiffconf.h.
+
+2004-09-10 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/internals.html: Split off a discussion of adding new tags
+ into addingtags.html.
+
+2004-09-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * test/{ascii_tag.c, long_tag.c}: Preliminary test suite added.
+
+ * tools/tiff2pdf.c: Fixed reading TransferFunction tag as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=590
+
+ * libtiff/tif_print.c: Fixes in InkNames and NumberOfInks reporting.
+
+ * libtiff/tif_dirread.c: Don't reject to read tags of the
+ SamplesPerPixel size when the tag count is greater than number of
+ samples as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=576
+
+ * libtiff/tiff.h: Use _TIFF_DATA_TYPEDEFS_ guardian to switch off
+ defining int8/uint8/... etc. types. As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=607
+
+2004-09-09 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2ps.c, tools/tiffmedian.c: fiddle with include files
+ to avoid compile warnings about getopt() and a few other things.
+
+2004-09-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Use memcpy() function instead of pointer
+ assigning magic in TIFFFetchFloat().
+
+2004-09-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.h, tif_open.c}: Applied patches from Joris Van Damme
+ to avoid requirement for tiffiop.h inclusion in some applications. See
+ here
+
+ http://www.asmail.be/msg0054799560.html
+
+ for details.
+
+ * tools/fax2tiff.c: Use the new functions in the code.
+
+2004-08-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Initialize arrays properly.
+
+ * tools/tiff2ps.c: Avoid zero division in setupPageState() function;
+ properly initialize array in PSDataBW().
+
+2004-08-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: More fixes for bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=590
+
+ from Ross Finlayson.
+
+2004-08-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c: Fixed problem with uninitialized values.
+
+ * libtiff/tif_dir.c: Initialize tif_foundfield data member in the
+ TIFFDefaultDirectory() (in addition to 2004-08-19 fix).
+
+ * tools/tiff2pdf.c: Fixed a bunch of problems as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=590
+
+2004-08-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Applied patch from Ross Finlayson that checks
+ that the input file has compression, photometric interpretation,
+ etcetra, tags or if not than a more descriptive error is returned.
+
+ * libtiff/tif_dirread.c: Fixed problem in TIFFReadDirectory() in the
+ code, responsible for tag data type checking.
+
+2004-08-19 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffiop.h, tif_dirinfo.c}: Fixed problem with the static
+ variable as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=593
+
+2004-08-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/ras2tiff.c: Fixed issue with missed big-endian checks as per
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=586
+
+2004-08-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_config.h.in, tif_config.h.vc}: config.h.in and
+ config.h.vc files renamed in the tif_config.h.in and tif_config.h.vc.
+
+2004-07-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_lzw.c: LZW compression code is merged back from the
+ separate package. All libtiff tools are updated to not advertise an
+ abcence of LZW support.
+
+2004-07-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffio.h: Revert thandle_t back to void* type.
+
+2004-07-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_read.c, tif_tile.c, tif_strip.c}: Fixes in error
+ messages, as suggested by Bernd Herd.
+
+2004-07-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Call TIFFError() instead of producing warnings
+ when setting custom tags by value. Reported by Eric Fieleke.
+
+2004-06-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/bmp2tiff.c: Add missed RawsPerStrip setting.
+
+2004-06-08 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/bmp2tiff.c: Added new utility to convert Windows BMP files
+ into TIFFs.
+
+2004-06-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.7.0alpha released.
+
+2004-06-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiff.h, tif_dirwrite.c, tif_fax3.c, tif_packbits.c,}: Get rid
+ of ugly 64-bit hacks, replace them with the clever (autoconf based )
+ ones :-).
+
+ * libtiff/tiffio.h: Define thandle_t as int, not void* (may cause
+ problems in 64-bit environment).
+
+2004-06-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffset.c: tiffset now can set any libtiff supported tags.
+ Tags can be supplied by the mnemonic name or number.
+
+ * libtiff/{tiffio.h, tif_dir.h, tif_dirinfo.c,}: Added two new
+ functions TIFFFindFieldInfoByName() and TIFFFieldWithName().
+
+2004-05-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_ojpeg.c: Fixed problem with duplicated SOI and SOF
+ markers as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=581
+
+2004-05-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffsplit.c: Don't forget to copy Photometric
+ Interpretation tag.
+
+2004-05-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_open.c, tiffio.h}: New function added:
+ TIFFIsBigEndian(). Function returns nonzero if given was file written
+ in big-endian order.
+
+ * tools/tiffsplit.c: Fixed problem with unproperly written multibyte
+ files. Now output files will be written using the same byte order
+ flag as in the input image. See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=574
+
+ for details.
+
+2004-05-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_print.c: added (untested) support for printing
+ SSHORT, SLONG and SRATIONAL fields.
+
+ * tools/tiffcp.c: close output file on normal exit.
+
+2004-05-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_fax3.c: Avoid reading CCITT compression options
+ if compression type mismatches. See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=565
+
+2004-04-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_strip.c: Never return 0 from the
+ TIFFNumberOfStrips().
+
+2004-04-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Workaround for broken TIFF writers which
+ store single SampleFormat value for multisampled images. See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=562
+
+2004-04-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure.ac, libtiff/{tiff.h, config.h.in}: Added tests for int8,
+ int16 and int32 types to avoid complains on some compilers. Details at
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+2004-04-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2pdf.c: Fixed problem with unaligned access as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=555
+
+2004-04-14 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_write.c: Allow in-place updating of the compressed
+ images (don't work properly with all codecs). For details see GDAL bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=534
+
+2004-04-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_jpeg.c: Workaround for wrong sampling factors used
+ in the Intergarph JPEG compressed TIFF images as per bug:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=532
+
+2004-04-04 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: close clientdata if TIFFClientOpen() fails
+ via bad2.
+
+2004-03-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Properly set Photometric Interpretation in case of
+ JPEG compression of grayscale images.
+
+ * tools/tiffcp.c: Don't emit warnings when Orientation tag does not
+ present in the input image.
+
+2004-03-19 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * {many}: The first attempt to switch to autotools.
+
+2004-03-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_open.c: Use dummy mmap/munmap functions in
+ TIFFClientOpen() when the appropriate client functions was not
+ supplied by user.
+
+2004-03-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/ycbcr.c: fixed main() declaration as per:
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=513
+
+2004-02-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffsplit.c: Copy JPEGTables tag contents for JPEG compressed
+ images. Reported by Artem Mirolubov.
+
+ * libtiff/tif_dirread.c: Fixed problem with handling TIFF_UNDEFINED
+ tag type in TIFFFetchNormalTag() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=508
+
+2004-02-17 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_codec.c: Fixed typo in TIFFInitPackBits name as per:
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=494
+
+2004-02-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_fax3.c: Fixed problem with CCITT encoding modes as per
+ bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=483
+
+ But we need more work on fax codec to support update mode.
+
+2004-01-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/libtiff.def: Added TIFFCurrentDirOffset, TIFFWriteCheck,
+ TIFFRGBAImageOK, and TIFFNumberOfDirectories as suggested by
+ Scott Reynolds.
+
+2004-01-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiff.h: Fixed tag definitions for TIFFTAG_YCLIPPATHUNITS
+ and TIFFTAG_INDEXED as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=475
+
+ * libtiff/{tif_win32.c, tif_unix.c}: Check whether the pointer is
+ NULL before proceeding further as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=474
+
+ Check results, returned by the TIFFFdOpen() before returning and close
+ file if TIFFFdOpen() failed as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=468
+
+ * libtiff/tif_open.c: More fixes for
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=468
+
+2004-01-28 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{libtiff.def, tif_close.c, tiffio.h, tif_open.c}: Separate
+ TIFFCleanup() from the TIFFClose() in order to fix the bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=468
+
+ * tools/tiffcp.c: Fixed problem with wrong interpretation of the
+ InkNames tag as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=466
+
+ Memory leak fixed.
+
+2004-01-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirwrite.c: Fixed handling of writable ASCII tags that
+ are field_passcount=TRUE properly. Arguably anonymous custom tags
+ should be declared as passcount=FALSE, but I don't want to change
+ that without a careful review.
+
+2004-01-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_write.c: Fixed reporting size of the buffer in case of
+ stripped image in TIFFWriteBufferSetup(). As per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=460
+
+2004-01-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Incomplete cleanup in TIFFFreeDirectory(),
+ patch from Gerben Koopmans.
+
+ * libtiff/tif_dirread.c: Check field_passcount value before setting
+ the value of undefined type, patch from Gerben Koopmans.
+
+2004-01-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Fixed problem with wrong Photometric setting for
+ non-RGB images.
+
+2003-12-31 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_win32.c: Fixed problem with _TIFFrealloc() when the NULL
+ pointer passed. Patch supplied by Larry Grill.
+
+ * libtiff/{tiff.h, tif_fax3.c}:Fixes for AMD 64 platform as
+ suggested by Jeremy C. Reed.
+
+2003-12-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff 3.6.1 released.
+
+2003-12-24 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * config.guess, config.sub: Updated from the recent upstream.
+
+2003-12-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_color, tif_getimage.c, tiffio.h}, man/TIFFcolor.3t:
+ More cleanups in color conversion interface, added appropriate manual
+ page.
+
+2003-12-19 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_extension.c, tif_dirinfo.c, tiff.h}: Warnings fixed as
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=357
+
+ * tools/tiff2ps.c: Added support for alpha channel. Fixes
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=428
+
+ * libtiff/{libtiff.def, tif_color.c, tif_getimage.c, tiffio.h}:
+ Interface for Lab->RGB color conversion is finally cleaned up.
+ Added support for ReferenceBlackWhite tag handling when converted from
+ YCbCr color space. The latter closes
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=120
+
+2003-12-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_getimage.c, tiffio.h}: Avoid warnings.
+
+ * libtiff/makefile.vc, tools/makefile.vc: Support for IJG JPEG
+ library.
+
+2003-12-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_getimage.c, tif_aux.c}: Read WhitePoint tag from the
+ file and properly use it for CIE Lab->RGB transform.
+
+2003-12-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_getimage.c, tif_color.c, tiffio.h}: YCbCr->RGB
+ conversion routines now in the tif_color.c module. New function
+ TIFFYCbCrtoRGB() available in TIFF API.
+
+ * libtiff/tif_dirwrite.c: Handle TIFF_IFD tag type correctly.
+
+2003-12-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_getimage.c, tif_color.c, tiffio.h}: Improvements in
+ CIE Lab conversion code. Start moving YCbCr stuff to the tif_color.c
+ module.
+
+ * libtiff/{tif_getimage.c, tiffio.h}, man{TIFFReadRGBAImage.3t,
+ TIFFReadRGBAStrip.3t, TIFFReadRGBATile.3t, TIFFRGBAImage.3t}:
+ Finally resolved problems with orientation handling. TIFFRGBAImage
+ interface now properly supports all possible orientations, i.e. images
+ will be flipped both in horizontal and vertical directions if
+ required. 'Known bugs' section now removed from the appropriate manual
+ pages. Closed bug entry:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=322
+
+2003-12-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dir.c: Fixed order of the parameters in TIFFError()
+ function calls as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=440
+
+2003-11-28 Ross Finlayson <libtiff@apexinternetsoftware.com>
+
+ * tools/tiff2pdf.c: Some bugs fixed.
+
+2003-11-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_luv.c: Fixed bug in 48-bit to 24-bit conversion routine,
+ reported by Antonio Scuri.
+
+ * man/tiff2pdf.1: Few improvements in page layout.
+
+ * Makefile.in, /man/Makefile.in, /html/man/tiff2pdf.1.html:
+ Added support fpr tiff2pdf manual page.
+
+2003-11-26 Ross Finlayson <libtiff@apexinternetsoftware.com>
+
+ * /man/tiff2pdf.1: File added to repository.
+
+2003-11-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * Makefile.in, /tools/{Makefile.in, makefile.vc}:
+ Added support fpr tiff2pdf utility.
+
+2003-11-25 Ross Finlayson <libtiff@apexinternetsoftware.com>
+
+ * /tools/tiff2pdf.c: File added to repository.
+
+2003-11-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /tools/raw2tiff.c: sqrtf() replaced with sqrt().
+
+2003-11-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /tools/raw2tiff.c: #include <getopt.h> removed.
+
+ * tools/{Makefile.in, tiffgt.c}: Unmaintained and platform dependent
+ sgigt utility removed and replaced with the completely rewritten
+ portable tiffgt tool (depend on OpenGL and GLUT). Initial revision,
+ there is a lot of things to improve.
+
+ * libtiff/tif_ojpeg.c: TIFFVGetField() function now can properly
+ extract the fields from the OJPEG files. Patch supplied by Ross
+ Finlayson.
+
+ * libtiff/{tiffio.h, tif_codec.c}, man/{libtiff.3t, TIFFcodec.3t}:
+ Added new function TIFFIsCODECConfigured(), suggested by Ross
+ Finlayson.
+
+2003-11-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirinfo.c: Implemented binary search in
+ _TIFFMergeFieldInfo(). Patch supplied by Ross Finlayson.
+
+ * libtiff/tif_dir.h: _TIFFFindOrRegisterdInfo declaration replaced
+ with _TIFFFindOrRegisterFieldInfo as reported by Ross Finlayson.
+
+2003-11-17 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirread.c: do not mark all anonymously defined tags to be
+ IGNOREd.
+
+2003-11-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * contrib/pds/{tif_pdsdirread.c, tif_pdsdirwrite.c}: Use
+ TIFFDataWidth() function insted of tiffDataWidth array.
+
+2003-11-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiff.h, tif_dirinfo.c}: Added support for IFD (13)
+ datatype, intruduced in "Adobe PageMaker TIFF Tech. Notes".
+
+2003-11-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Makefile.in: fixed missing backslash for tif_color.c in list.
+
+2003-11-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_color.c, tif_getimage.c, tiffio.h, Makefile.in}:
+ New color space conversion code: CIE L*a*b* 1976 images now supported
+ by the TIFFRGBAImage interface. All introduced routines go to new
+ module tif_color.c. Eventually all color conversion functions should
+ be moved there.
+
+2003-11-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/{ras2tiff.c, rasterfile.h}: Properly determine SUN Rasterfiles
+ with the reverse byte order (it is reported by the magic header
+ field). Problem reported by Andreas Wiesmann.
+
+ * tools/raw2tiff.c, man/raw2tiff.1: Few improvements in correlation
+ calculation function. Guessing mechanics now documented in manual page.
+
+2003-11-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/raw2tiff.c: Implemented image size guessing using
+ correlation coefficient calculation between two neighbour lines.
+
+2003-11-09 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_tile.c: remove spurious use of "s" (sample) in the
+ planarconfig_contig case in TIFFComputeTile().
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=387
+
+2003-11-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffiop.h: New macros: TIFFmax, TIFFmin and TIFFrint.
+
+2003-11-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffio.h, tif_strip.c}, man/{TIFFstrip.3t, libtiff.3t}:
+ Added TIFFRawStripSize() function as suggested by Chris Hanson.
+
+2003-11-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_lzw.c, tif_fax3.c}: Proper support for update mode as
+ per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=424
+
+2003-10-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/libtiff.def: Added TIFFReadRGBAImageOriented.
+
+ * html/build.html: Added note about GNU make requirement.
+
+2003-10-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * Makefile.in: Fixes in using MAKEFLAGS as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=418
+
+ * port/install.sh.in: Option -p added to the mkdir command to create
+ all directory tree structure before installing.
+
+2003-10-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /tools/tiff2ps.c: #include <strings.h> replaced with the
+ #include <string.h>.
+
+2003-10-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * Makefile.in: Add an absolute path to the test_pics.sh call.
+
+2003-10-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tiffcomp.h: #define _BSDTYPES_DEFINED when defining BSD
+ typedefs.
+
+2003-10-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure, libtiff/{Makefile.in, mkversion.c}:
+ Relative buildings fixed.
+
+ * tools/Makefile.in: Added "-I../libtiff" to the tiffset building
+ rule.
+
+2003-10-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * Makefile.in: Added missed v3.6.0.html.
+
+ * libtiff/tiffio.h: Typo fixed: ORIENTATION_BOTTOMLEFT replaced with
+ ORIENTATION_BOTLEFT.
+
+2003-10-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * 3.6.0 final release.
+
+2003-10-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tif_getimage.c, tiffio.h}, man/TIFFReadRGBAImage.3t: New
+ function TIFFReadRGBAImageOriented() implemented to retrieve raster
+ array with user-specified origin position as suggested by Jason Frank.
+ See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=322
+
+ for details.
+
+ * tools/tiff2rgba.c: Switched to use TIFFReadRGBAImageOriented()
+ instead of TIFFReadRGBAImage().
+
+ * tools/tiff2ps.c: Fixed possible endless loop as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=404
+
+2003-09-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Check field counter against number of fields
+ in order to fix
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=366
+
+ * libtiff/tif_fax3.c: Fix wrong line numbering as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=342
+
+2003-09-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/{tiffiop.h, tif_dirread.c, tif_dir.c, tif_open.c,
+ tif_close.c}: Store a list of opened IFD to prevent looping as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=383
+
+2003-09-23 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: More fixes for EstimateStripByteCounts(). See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=358
+
+2003-08-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffmedian.c: int declaration replaced with the uint32 to
+ support large images as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=382
+
+2003-08-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/Makefile.in: Fixed problem with building in different
+ directory.
+
+ * tools/tiff2ps.c: Added missing #include <strings.h>.
+
+ * libtiff/tif_dirwrite.c: More fixes for custom tags code
+ from Ashley Dreier.
+
+2003-08-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c: Added page size setting when creating PS Level 2.
+ Patch submitted by Balatoni Denes (with corrections from Tom
+ Kacvinsky).
+
+ * tools/tiff2ps.c: Fixed PS comment emitted when FlateDecode is
+ being used. Reported by Tom Kacvinsky.
+
+ * libtiff/tif_dirwrite.c: Fixed problem with custom tags writing,
+ reported by Ashley Dreier.
+
+ * libtiff/tif_print.c: Fixed problem with float tags reading, support
+ for printing RATIONAL and BYTE tags added.
+
+2003-08-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_lzw.c: Move LZW codec state block allocation back to
+ TIFFInitLZW(), because its initialization in LZWSetupDecode() cause
+ problems with predictor initialization. Remove O_RDONLY check during
+ state block allocation to be able open LZW compressed files in update
+ mode.
+
+ Problem exist for libtiff version of the tif_lzw.c module. One from
+ lzw-compression-kit hasn't such troubles.
+
+2003-08-04 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_write.c: modified tif_write.c so that the various
+ encoded write functions use tif_postdecode() to apply byte order
+ swapping (swab) to the application passed data buffer if the same
+ would be done when reading. This allows us to write pixel data with
+ more than 8 bits per sample to existing files of a non-native byte
+ order. One side effect of this change is the applications buffer
+ itself is altered in this case by the act of writing.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=171
+
+2003-07-25 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: avoid signed/unsigned casting warning
+ initializing typemask as per patch from J.A. Strother.
+
+ * tools/tiffcp.c: fixed signed/unsigned casting warning.
+
+ * libtiff/tif_print.c: dos2unix conversion.
+
+ * tools/tiffsplit.c: increased the maximum number of pages that
+ can be split. Patch provided by Andrew J. Montalenti.
+
+2003-07-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/raw2tiff.c: Added option `-p' to explicitly select color
+ space of input image data. Closes
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=364
+
+2003-07-08 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_aux.c, tif_codec.c, tif_dir.c, tif_dirread.c, tif_extension.c,
+ tif_fax3.c, tif_getimage.c, tif_luv.c, tif_lzw.c, tif_next.c,
+ tif_packbits.c, tif_predict.c, tif_print.c, tif_swab.c, tif_thunder.c:
+ avoid casting warning at /W4.
+
+2003-07-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/thumbnail.c: Memory leak fixed as reported by Robert S. Kissel.
+
+2003-06-30 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_pixarlog.c: Unused variables removed.
+
+ * libtiff/{tif_dirread.c, tif_dir.c}: Fixed problem with
+ EstimateStripByteCounts() as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=358
+
+ * libtiff/{tif_dirwrite.c, tif_packbits.c}: Fixed compilation on
+ 64-bit architectures as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=357
+
+ * libtiff/tif_dirinfo.c: TIFFDataWidth() returns 0 in case of
+ unknown data type.
+
+2003-06-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_print.c: fixed some serious bugs when printing
+ custom tags ... almost certain to crash.
+
+ * libtiff/tif_dirread.c: Don't ignore custom fields that are
+ autodefined. Not sure how this got to be like this.
+
+2003-06-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * 3.6.0 Beta2 released.
+
+ * tools/tiffcmp.c, man/tiffcmp.1: Fixed problem with unused data
+ comparing as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=349
+
+ `-z' option now can be used to set the number of reported different
+ bytes.
+
+2003-06-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c, man/tiffcp.1: Added possibility to specify value -1
+ to -r option to get the entire image as one strip. See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=343
+
+ for details.
+
+2003-06-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Set the correct RowsPerStrip and PageNumber
+ values as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=343
+
+2003-05-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: modified segment_height calculation to always
+ be a full height tile for tiled images. Also changed error to just
+ be a warning.
+
+2003-05-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c: Page numbering fixed, as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=341
+
+2003-05-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * contrib/ojpeg/{Makefile.in, jdhuff.h, jinclude.h, ojpeg.c, README},
+ configure, Makefile.in: Switched back to the old behaviour. Likely
+ better solution should be found for OJPEG support.
+
+2003-05-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/mkversion.c: Fixed problem with wrong string size when
+ reading RELEASE-DATE file.
+
+2003-05-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c: Fixed bug in Ascii85EncodeBlock() function: array
+ index was out of range.
+
+2003-05-06 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * contrib/ojpeg/{Makefile.in, jdhuff.h, jinclude.h, ojpeg.c, README},
+ configure, Makefile.in: Improved libtiff compilation with OJPEG
+ support. Now no need for patching IJG JPEG library, hack requred by
+ libtiff will be compiled and used in-place. Implemented with
+ suggestion and help from Bill Allombert, Debian's libjpeg maintainer.
+
+ * libtiff/tif_aux.c: Properly handle TIFFTAG_PREDICTOR in
+ TIFFVGetFieldDefaulted() function.
+
+2003-05-05 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/ppm2tiff.c: PPM header parser improved: now able to skip
+ comments.
+
+ * tools/tiffdither.c: Fixed problem with bit fill order tag setting:
+ was not copied from source image.
+
+ * libtiff/getimage.c: Workaround for some images without correct
+ info about alpha channel as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=331
+
+2003-04-29 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps.c, man/tiff2ps.1: Add ability to generate PS Level 3.
+ It basically allows one to use the /flateDecode filter for ZIP
+ compressed TIFF images. Patch supplied by Tom Kacvinsky. Fixes
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=328
+
+ * tools/tiff2ps.c: Force deadzone printing when EPS output specified
+ as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=325
+
+2003-04-17 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Removed additional check for StripByteCounts
+ due to problems with multidirectory images. Quality of error messages
+ improved.
+
+2003-04-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiffcp.c: Fixed problem with colorspace conversion for JPEG
+ encoded images. See bug entries
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=275
+
+ and
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=23
+
+ * libtiff/tif_dirread.c: Additional check for StripByteCounts
+ correctness. Fixes
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=320
+
+2003-03-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/{fax2ps.c, fax2tiff.c, gif2tiff.c, pal2rgb.c, ppm2tiff.c,
+ ras2tiff.c, raw2tiff.c, rgb2ycbcr.c, thumbnail.c, tiff2bw.c,
+ tiff2ps.c, tiff2rgba.c, tiffcp.c, tiffdither.c, tiffinfo.c,
+ tiffmedian.c}: Added library version reporting facility to all tools.
+
+2003-03-06 Frank Warmerdam <warmerdam@pobox.com>
+
+ * port/install.sh.in: Fixed problems with install producing paths
+ like ///usr/local/lib on cygwin.
+
+2003-02-27 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c, man/fax2tiff.1: New switch (-X) to set width of
+ raw input page. Patch supplied by Julien Gaulmin. See
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=293
+
+ for details.
+
+2003-02-26 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: fixed up the tif_postdecode settings
+ responsible for byte swapping complex image data.
+
+ * libtiff/tif_lzw.c: fixed so that decoder state isn't allocated till
+ LZWSetupDecode(). Needed to read LZW files in "r+" mode.
+
+2003-02-07 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/ppm2tiff.c: Fixed problem with too many arguments.
+
+2003-02-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/raw2tiff.c: Memory leak fixed.
+
+2003-02-03 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c, man/fax2tiff.1: Applied patch from Julien Gaulmin
+ (thanks, Julien!). More switches for fax2tiff tool for better control
+ of input and output. Details at
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=272
+
+2003-02-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Modified to defer initialization of jpeg
+ library so that we can check if there is already any tile/strip data
+ before deciding between creating a compressor or a decompressor.
+
+2003-01-31 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_write.c: TIFFWriteCheck() now fails if the image is
+ a pre-existing compressed image. That is, image writing to
+ pre-existing compressed images is not allowed.
+
+ * libtiff/tif_open.c: Removed error if opening a compressed file
+ in update mode.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=198
+
+2003-01-31 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * config.guess, config.sub: Updated to recent upstream versions.
+
+2003-01-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * cut 3.6.0 Beta release.
+
+2002-12-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2ps.c, man/fax2ps.1: Page size was determined
+ in wrong way as per bug
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=239
+
+2002-12-17 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirread.c: Allow wrong sized arrays in
+ TIFFFetchStripThing().
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=49
+
+2002-12-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: fix problem with test on td_customValueCount.
+ Was using realloc even first time. Fix by Igor Venevtsev.
+
+2002-11-30 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dir.c: fixed bug with resetting an existing custom
+ field value.
+
+ * libtiff/tif_dir.c: Fixed potential problem with ascii "custom"
+ tags in TIFFVGetField() ... added missing break.
+
+2002-10-14 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2ps.c: fixes a problem where "tiff2ps -1e" did not make
+ the scanline buffer long enough when writing rgb triplets.
+ The scanline needs to be 3 X the number of dots or else it will
+ contain an incomplete triplet and programs that try to separate
+ the eps by redefining the colorimage operator will get messed up.
+ Patch supplied by William Bader.
+
+ * Makefile.in: added tif_extension.c to file list as per
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=218.
+
+2002-10-11 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * configure, config.site, libtiff/{tif_unix.c, Makefile.in}: Fix for
+ large files (>2GiB) supporting. New option in the config.site:
+ LARGEFILE="yes". Should be enough for I/O of the large files.
+
+2002-10-10 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/html/v3.6.0.html: new release notes.
+
+ * libtiff/index.html: removed faq, cvs snapshot cruft. Added email
+ link for Andrey. Pointer to v3.6.0.html.
+
+ * libtiff/Makefile.in: added direct rule for tiffvers.h for release.
+
+2002-10-07 Andrey Kiselev <dron@ak4719.spb.edu>
+ * tools/tiff2ps.c, man/tiff2ps.1: Applied patch form Sebastian Eken
+ (thanks, Sebastian!). New switches:
+ -b # for a bottom margin of # inches
+ -c center image
+ -l # for a left margin of # inches
+ -r rotate the image by 180 degrees
+ New features merged with code for shrinking/overlapping.
+ Previously added -c and -n switches (for overriding PS units) renamed
+ in -x and -y respectively.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=200
+
+ * html/man/*.html: Updated from actual manual pages.
+
+2002-10-06 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: fixed problem with boolean defined with wrong
+ size on windows. Use #define boolean hack.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=188
+
+ * libtiff/tiff.h: Don't do special type handling in tiff.h unless
+ USING_VISUALAGE is defined.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+2002-10-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiff.h: added COMPRESSION_JP2000.
+
+2002-10-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_dirread.c: Another fix for the fetching SBYTE arrays
+ by the TIFFFetchByteArray() function. Should finally resolve
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=52
+
+ * configure: Set -DPIXARLOG_SUPPORT option along with -DZIP_SUPPORT
+
+ * html/Makefile.in: New targets added: html and groffhtml for
+ producing HTML representations of the manual pages automatically.
+ html target uses man2html tool, groffhtml uses groff tool.
+
+2002-09-29 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure, libtiff/Makefile.in: Added SCO OpenServer 5.0.6 support
+ from John H. DuBois III.
+
+2002-09-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * Makefile.in, /man/{raw2tiff.1, Makefile.in, libtiff.3}: Added
+ manual page for raw2tiff(1) tool.
+
+2002-09-12 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /libtiff/{tiffio.h, tif_dir.h}: TIFFDataWidth() declaration moved to
+ the tiffio.h header file.
+
+ * Makefile.in, /man/{TIFFDataWidth.3t, Makefile.in, libtiff.3}: Added
+ manual page for TIFFDataWidth() function
+
+2002-09-08 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirread.c: Expand v[2] to v[4] in TIFFFetchShortPair()
+ as per http://bugzilla.remotesensing.org/show_bug.cgi?id=196.
+
+ * tools/tiff2ps.c: Don't emit BeginData/EndData DSC comments
+ since we are unable to properly include the amount to skip.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=80
+
+2002-09-02 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /libtiff/tif_dirread.c: Fixed problem with SBYTE type data fetching
+ in TIFFFetchByteArray(). Problem described at
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=52
+
+2002-08-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /libtiff/tif_dirinfo.c: Further additions to free custom fields
+ in _TIFFSetupFieldInfo() function.
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=169 for details.
+
+ * /libtiff/tif_lzw.c: Additional consistency checking added in
+ LZWDecode() and LZWDecodeCompat().
+ Fixes http://bugzilla.remotesensing.org/show_bug.cgi?id=190
+ and http://bugzilla.remotesensing.org/show_bug.cgi?id=100
+
+ * /libtiff/tif_lzw.c:
+ Added check for valid code lengths in LZWDecode() and
+ LZWDecodeCompat(). Fixes
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=115
+
+2002-08-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /libtiff/{Makefile.vc, libtiff.def}:
+ Missed declarations added.
+
+2002-08-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_getimage.c: Ensure that TIFFRGBAImageBegin() returns the
+ return code from the underlying pick function.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=177
+
+ * tif_dir.h: changed FIELD_CODEC to 66 from 64 to avoid overlap
+ with FIELD_CUSTOM as mentioned in bug 169.
+
+ * tif_close.c: added logic to free dynamically created anonymous
+ field definitions to correct a small memory leak.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=169
+
+2002-08-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /tools/{raw2tiff.c, Makefile.in, Makefile.lcc, Makefile.vc}:
+ New tool: raw2tiff --- raw images to TIFF converter. No manual page yet.
+
+2002-07-31 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Fixed problem with setting of nrows in
+ JPEGDecode() as per bugzilla bug (issue 1):
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=129
+
+ * libtiff/{tif_jpeg.c,tif_strip.c,tif_print.c}: Hacked tif_jpeg.c to
+ fetch TIFFTAG_YCBCRSUBSAMPLING from the jpeg data stream if it isn't
+ present in the tiff tags.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=168
+
+ * libtiff/tif_read.c, libtiff/tif_write.c: TIFFReadScanline() and
+ TIFFWriteScanline() now set tif_row explicitly in case the codec has
+ fooled with the value.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=129
+
+2002-06-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * /tools/tiff2ps.c: Added workaround for some software that may crash
+ when last strip of image contains fewer number of scanlines than
+ specified by the `/Height' variable. See
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=164
+ for explanation.
+
+2002-06-21 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps, man/tiff2ps.1: New functionality for tiff2ps utility:
+ splitting long images in several pages. See
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=142 for explanation.
+ Patch granted by John Williams <williams@morinda.com>.
+
+2002-06-11 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/contrib/win95: renamed to contrib/win_dib. Added new
+ Tiffile.cpp example of converting TIFF files into a DIB on Win32.
+ This one is described in:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=143
+
+ * libtiff/tif_ojpeg.c: Major upgrade from Scott. See details at:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=156
+
+2002-05-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps: New commandline switches to override resolution
+ units obtained from the input file. Closes
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=131
+
+2002-04-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/libtiff.def: Added missed declaration.
+
+2002-04-22 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/fax2tiff.c: Updated to reflect latest changes in libtiff.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=125
+
+2002-04-20 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_open.c: Pointers to custom procedures
+ in TIFFClientOpen() are checked to be not NULL-pointers.
+
+2002-04-18 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/libtiff.def: Added missed declarations.
+
+ * libtiff/tif_pixarlog.c: Updated for using tif_tagmethods structure.
+
+2002-04-16 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_lzw.c: Additional checks for data integrity introduced.
+ Should finally close
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=100
+
+2002-04-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/tiff2ps: Division by zero fixed.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=88
+
+2002-04-09 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_dirwrite.c, tif_write.c, tiffio.h:
+ TIFFCheckpointDirectory() routine added.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=124
+
+ * man/: TIFFWriteDirectory.3t, Makefile.in: Added description
+ for the new function.
+
+2002-04-08 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_codec.c, tif_compress.c, tiffiop.h: Introduced
+ additional members tif->tif_decodestatus and tif->tif_encodestatus
+ for correct handling of unconfigured codecs (we should not try to read
+ data or to define data size without correct codecs).
+
+ * libtiff/tif_getimage.c: The way of codecs checking in TIFFRGBAImageOK
+ changed. Now it has used tif->tif_decodestatus and
+ tif->tif_encodestatus.
+ Should fix http://bugzilla.remotesensing.org/show_bug.cgi?id=119 (in
+ case of __cvs_8.tif test image).
+
+ * libtiff/: tif_dirinfo.c, tif_dirread.c: Somebody makes a bug in
+ tif_dirread.c when TIFFCreateAnonFieldInfo was introduced.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=119 in case
+ of _cvs_00000-00.tif, _cvs_00000-01.tif and _cvs_00000-02.tif.
+
+2002-04-04 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_lzw.c: Assertions in LZWDecode and LZWDecodeCompat
+ replaced by warnings. Now libtiff should read corrupted LZW-compressed
+ files by skipping bad strips.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=100
+
+2002-04-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirwrite.c: Removed some dead code.
+
+ * libtiff/*: Cleanup some warnings.
+
+ * libtiff/tif_dir.c: Fixed bug with count returned by TIFFGetField()
+ for variable length FIELD_CUSTOM values. Was int * but should be
+ u_short *.
+
+2002-04-01 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * tools/: tifcp.c: Added support for 'Orientation' tag in tiffcp
+ utility (at cpStripToTile routine).
+
+2002-03-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirread.c: avoid div-by-zero if rowbytes is zero in chop func.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=111
+
+ * tif_print.c: Fixed so that ASCII FIELD_CUSTOM values with
+ passcount set FALSE can be printed (such as TIFFTAG_SOFTWARE).
+
+ * libtiff/tif_dir.c,tif_dirinfo.c,tif_dir.h,tif_ojpeg.c: modified so
+ that TIFFTAG_SOFTWARE uses FIELD_CUSTOM as an example.
+
+2002-03-26 Dwight Kelly <dbmalloc@remotesensing.org>
+
+ * libtiff/: tiff.h, tif_dir.c, tif_dir.h, tif_dirinfo.c, tif_dirread.c,
+ tif_dirwrite.c: Added get/put code for new tag XMLPACKET as defined
+ in Adobe XMP Technote. Added missing INKSET tag value from TIFF 6.0 spec
+ INKSET_MULTIINK (=2). Added missing tags from Adobe TIFF technotes:
+ CLIPPATH, XCLIPPATHUNITS, YCLIPPATHUNITS, OPIIMAGEID, OPIPROXY and
+ INDEXED. Added PHOTOMETRIC tag value from TIFF technote 4 ICCLAB (=9).
+
+2002-03-26 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_getimage.c: TIFFReadRGBAStrip and TIFFReadRGBATile
+ now also uses TIFFRGBAImageOK before reading. This is additional fix
+ for http://bugzilla.remotesensing.org/show_bug.cgi?id=110
+
+2002-03-25 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_getimage.c: Additional check for supported
+ codecs added in TIFFRGBAImageOK and TIFFReadRGBAImage now uses
+ TIFFRGBAImageOK before reading.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=110
+
+2002-03-15 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_dir.c, tif_dir.h, tif_dirinfo.c, tif_dirread.c,
+ tif_dirwrite.c: Added routine TIFFDataWidth for detrmining
+ TIFFDataType sizes instead of working with tiffDataWidth array
+ directly. Should prevent out-of-borders bugs in case of unknown or
+ broken data types. EstimateStripByteCounts routine modified, so it
+ won't work when tags with uknown sizes founded.
+ Closes http://bugzilla.remotesensing.org/show_bug.cgi?id=109
+
+2002-03-13 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/tif_getimage.c: Added support for correct handling
+ `Orientation' tag in gtTileContig. Should be added in other gt*
+ functions as well, but I have not images for testing yet. Partially
+ resolves http://bugzilla.remotesensing.org/show_bug.cgi?id=23
+
+2002-03-10 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/: tif_dirinfo.c, tif_dirwrite.c: Added possibility to
+ read broken TIFFs with LONG type used for TIFFTAG_COMPRESSION,
+ TIFFTAG_BITSPERSAMPLE, TIFFTAG_PHOTOMETRIC. Closes
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=99
+
+2002-03-08 Andrey Kiselev <dron@ak4719.spb.edu>
+
+ * libtiff/Makefile.in, tools/Makefile.in: Shared library will not
+ be stripped when installing, utility binaries will do. Closes
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=93
+
+2002-02-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * man/TIFFGetField: fixed type of TIFFTAG_COPYRIGHT.
+
+ * man/libtiff.3t: added copyright tag info.
+
+2002-02-11 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/{tiff.h,tif_fax3.c}: Add support for __arch64__.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=94
+
+ * man/Makefile.in: Patch DESTDIR handling
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=95
+
+ * configure: OpenBSD changes for Sparc64 and DSO version.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=96
+
+2002-02-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * config.site/configure: added support for OJPEG=yes option to enable
+ OJPEG support from config.site.
+
+2002-01-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/document.html: fixed links for TIFf 6 docs.
+
+2002-01-18 Frank Warmerdam <warmerdam@pobox.com>
+
+ * config.guess, config.sub: Updated from ftp.gnu.org/pub/config.
+
+ * libtiff/tif_read.c: Fixed TIFFReadEncodedStrip() to fail if the
+ decodestrip function returns anything not greater than zero as per
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=97
+
+ * configure: Modify CheckForBigEndian so it can work in a cross
+ compiled situation.
+
+2002-01-16 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiffdump.c: include TIFFTAG_JPEGTABLES in tag list.
+
+ * tools/tiffset.c: fix bug in error reporting.
+
+ * tools/tiffcp.c: fix several warnings that show up with -Wall.
+
+2002-01-04 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: fixed computation of segment_width for
+ tiles files to avoid error about it not matching the
+ cinfo.d.image_width values ("JPEGPreDecode: Improper JPEG strip/tile
+ size.") for ITIFF files. Apparently the problem was incorporated since
+ 3.5.5, presumably during the OJPEG/JPEG work recently.
+
+2001-12-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure, libtiff/Makefile.in: Changes for building on MacOS 10.1.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=94
+
+ * libtiff/tif_getimage.c: If DEFAULT_EXTRASAMPLE_AS_ALPHA is 1
+ (defined in tiffconf.h - 1 by default) then the RGBA interface
+ will assume that a fourth extra sample is ASSOCALPHA if the
+ EXTRASAMPLE value isn't set for it. This changes the behaviour of
+ the library, but makes it work better with RGBA files produced by
+ lots of applications that don't mark the alpha values properly.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=93
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=65
+
+2001-12-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: allow jpeg data stream sampling values to
+ override those from tiff directory. This makes this work with
+ ImageGear generated files.
+
+2001-12-07 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/Makefile.in: added missing images per bug 92.
+
+ * port/Makefile.in: fixed clean target per bug 92.
+
+2001-11-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Reissue 3.5.7 release.
+
+ * libtiff/mkversion.c: Fix output of TIFF_VERSION to be
+ YYYYMMDD so that it is increasing over time.
+
+ * Makefile.in: Ensure that tiffvers.h is regenerated in the
+ make release target.
+
+ * Makefile.in: added libtiff/tiffvers.h to the release file list.
+
+2001-11-23 Frank Warmerdam <warmerdam@pobox.com>
+
+ * added html/v3.5.7.html, updated html/index.html.
+
+ * Makefile.in: added contrib/addtiffo/tif_ovrcache.{c,h}.
+
+2001-11-15 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure: fixed test for -lm.
+
+2001-11-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Added PHOTOMETRIC_ITULAB as per bug 90.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=90
+
+2001-10-10 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiff.h: I have created COMPRESSION_CCITT_T4,
+ COMPRESSION_CCITT_T6, TIFFTAG_T4OPTIONS and TIFFTAG_T6OPTIONS aliases
+ in keeping with TIFF 6.0 standard in tiff.h
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=83
+
+2001-09-26 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirwrite.c: added TIFFRewriteDirectory() function.
+ Updated TIFFWriteDirectory man page to include TIFFRewriteDirectory.
+
+2001-09-24 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_lzw.c: Avoid MS VC++ 5.0 optimization bug.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=78
+
+ * libtiff/tif_lzw.c: added dummy LZWSetupEncode() to report an
+ error about LZW not being available.
+
+ * libtiff/tif_dir.c: propagate failure to initialize compression
+ back from TIFFSetField() as an error status, so applications can
+ detect failure.
+
+ * libtiff/tif_dir.c: removed the auto replacement of
+ COMPRESSION_LZW with COMPRESSION_NONE in _TIFFVSetField().
+
+ * Removed Makefile, tools/Makefile, port/install.sh, man/Makefile
+ from CVS as they are all supposed to be auto-generated by configure.
+
+2001-09-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_ojpeg.c: new update from Scott.
+
+2001-09-09 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtif/tif_fax3.c: Removed #ifdef PURIFY logic, and modified to
+ always use the "safe" version, even if there is a very slight
+ cost in performance.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=54
+
+ * libtiff/Makefile.in: Fixed @DSOSUB_VERSION to be @DSOSUF_VERSION@
+ in two places.
+
+ * libtiff/tif_getimage.c: Fixed problem with reading strips or
+ tiles that don't start on a tile boundary. Fix contributed by
+ Josep Vallverdu (from HP), and further described in bug 47.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=47
+
+ * tools/tiff2ps.c: added OJPEG YCbCr to RGB support.
+
+ * libtiff/tif_ojpeg.c: Applied substantial patch from Scott.
+
+2001-09-06 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_packbits.c: fixed memory overrun error.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=77
+
+2001-08-31 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c: relax handling of contig case where
+ there are extra samples that are supposed to be ignored. This
+ should now work for 8bit greyscale or palletted images.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=75
+
+2001-08-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c: Don't complain for CMYK (separated)
+ images with more than four samples per pixel. See:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=73
+
+2001-08-10 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c: Use memmove() instead of TIFFmemcpy()
+ in TIFFReadRGBATile() to avoid issues in cases of overlapping
+ buffers. See Bug 69 in Bugzilla.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=69
+
+ * tools/tiff2rgba.c: fixed getopt() call so that -b works again.
+
+2001-08-09 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiff.h, libtiff/tif_fax3.c: added check for __LP64__
+ when checking for 64 bit architectures as per bugzilla bug 67.
+
+2001-07-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * man/Makefile.in: add TIFFClientOpen link as per debian submitted
+ bug 66.
+
+2001-07-20 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_jpeg.c: Define HAVE_BOOLEAN on windows if RPCNDR.H
+ has been included.
+
+2001-07-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_open.c: Seek back to zero after failed read,
+ before writing header.
+
+2001-07-18 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_ojpeg.c: updates from Scott. Handles colors
+ much better. Now depends on having patched libjpeg as per
+ patch in contrib/ojpeg/*.
+
+2001-07-17 Frank Warmerdam <warmerdam@pobox.com>
+
+ * */Makefile.in: added DESTDIR support.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=60
+
+2001-07-16 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure, libtiff/Makefile.in: applied OpenBSD patches
+ as per:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=61
+
+2001-06-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_getimage.c: Fixed so that failure is properly
+ reported by gtTileContig, gtStripContig, gtTileSeparate and
+ gtStripSeparate.
+
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=51
+
+ * tiffcmp.c: Fixed multi samples per pixel support for ContigCompare.
+ Updated bug section of tiffcmp.1 to note tiled file issues.
+
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=53
+
+2001-06-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure: Changes for DSO generation on AIX provided by
+ John Marquart <jomarqua@indiana.edu>.
+
+ * configure, libtiff/Makeifle.in: Modified to build DSOs properly
+ on Darwin thanks to Robert Krajewski (rpk@alum.mit.edu) and
+ Keisuke Fujii (fujiik@jlcuxf.kek.jp).
+
+2001-06-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tools/tiff2rgba.c: added -n flag to avoid emitting alpha component.
+
+ * man/tiff2rgba.1: new
+
+2001-05-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Added tiffset and tif_ojpeg to the dist lists in Makefile.in.
+
+2001-05-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tools/thumbnail.c: changed default output compression
+ to packbits from LZW since LZW isn't generally available.
+
+2001-05-12 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_ojpeg.c: New.
+ libtiff/tif_jpeg.c, tiffconf.h, tif_getimage.c: changes related
+ to OJPEG support.
+
+ Scott Marovich <marovich@hpl.hp.com> supplied OJPEG support.
+
+2001-05-11 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tiff.h: removed, it duplicates libtiff/tiff.h.
+
+2001-05-08 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirinfo.c: moved pixar and copyright flags to
+ ensure everything is in order.
+
+ * libtiff/libtiff.def: added TIFFCreateDirectory and
+ TIFFDefaultStripSize as per:
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=46
+
+2001-05-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirinfo.c: Modified the TIFF_BYTE definition for
+ TIFFTAG_PHOTOSHOP to use a writecount of TIFF_VARIABLE2 (-3) to
+ force use of uint32 counts instead of short counts.
+
+ * libtiff/tif_dirwrite.c: Added support for TIFF_VARIABLE2 in the
+ case of writing TIFF_BYTE/TIFF_SBYTE fields.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=43
+
+2001-05-01 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_dirinfo.c: removed duplicate TIFFTAG_PHOTOSHOP as per
+ bug report http://bugzilla.remotesensing.org/show_bug.cgi?id=44
+
+2001-04-05 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tiffio.h: removed C++ style comment.
+
+ * configure: fixed up SCRIPT_SH/SHELL handling.
+
+ * Makefile.in: Fixed SCRIPT_SH/SHELL handling.
+
+ * config.guess: documented more variables as per bug 40.
+
+2001-04-03 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure, *Makefile.in: Various changes to improve configuration
+ for HP/UX specifically, and also in general. They include:
+ - Try to handle /usr/bin/sh instead of /bin/sh where necessary.
+ - Upgrade to HP/UX 10.x+ compiler, linker and dso options.
+ - Fixed mmap() test to avoid MMAP_FIXED ... it isn't available on HP
+ - Use -${MAKEFLAGS} in sub makes from makefiles.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=40
+
+2001-04-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiff.h: Applied hac to try and resolve the problem
+ with the inttypes.h include file on AIX.
+
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+ * VERSION: update to 3.5.7 beta in preparation for release.
+
+ * configure/config.site: modified to check if -lm is needed for
+ MACHDEPLIBS if not supplied by config.site. Needed for Darwin.
+
+ * config.guess: updated wholesale to an FSF version apparently
+ from 1998 (as opposed to 1994). This is mainly inspired by
+ providing for MacOS X support.
+
+2001-03-29 Frank Warmerdam <warmerdam@pobox.com>
+
+ * configure, Makefile.in, etc: added support for OPTIMIZER being
+ set from config.site.
+
+2001-03-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * fax2ps.c: Helge (libtiff at oldach.net) submitted fix:
+
+ Here's a fix for fax2ps that corrects behaviour for non-Letter paper
+ sizes. It fixes two problems:
+
+ Without scaling (-S) the fax is now centered on the page size specified
+ with -H and/or -W. Before, fax2ps was using an obscure and practially
+ useless algorithm to allocate the image relative to Letter sized paper
+ which sometime sled to useless whitespace on the paper, while at the
+ same time cutting of the faxes printable area at the opposite border.
+
+ Second, scaling now preserves aspect ratio, which makes unusual faxes
+ (in particular short ones) print properly.
+
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=35
+
+ * tiff2ps.c/tiff2ps.1: Substantial changes to tiff2ps by
+ Bruce A. Mallett. See check message for detailed information
+ on all the changes, including a faster encoder, fixes for level
+ 2 PostScript, and support for the imagemask operator.
+
+2001-03-27 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tiffio.h: Changed "#if LOGLUV_PUBLIC" to
+ "#ifdef LOGLUV_PUBLIC" so it will work with VisualAge on AIX.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=39
+
+2001-03-16 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_dirinfo.c: moved definition of copyright tag in field list.
+ Apparently they have to be in sorted order by tag id.
+
+2001-03-13 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_getimage.c: Added support for 16bit minisblack/miniswhite
+ images in RGBA interface.
+
+2001-03-02 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Added TIFFTAG_COPYRIGHT support.
+
+2001-02-19 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Brent Roman contributed updated tiffcp utility (and tiffcp.1)
+ with support for extracting subimages with the ,n syntax, and also
+ adding the -b bias removal flag.
+
+2001-02-16 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/libtiff.def: Brent Roman submitted new version adding
+ serveral missing entry points.
+
+ * libtiff/tif_dirinfo.c: don't declare tiffFieldInfo static on VMS.
+ Some sort of weird VMS thing.
+
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=31
+
+ * tif_luv.c/tiff.h/tiffio.h:
+ New version of TIFF LogLuv (SGILOG) modules contributed by Greg Ward
+ (greg@shutterfly.com). He writes:
+
+ 1) I improved the gamut-mapping function in tif_luv.c for imaginary
+ colors, because some images were being super-saturated on the input
+ side and this resulted in some strange color shifts in the output.
+
+ 2) I added a psuedotag in tiff.h to control random dithering during
+ LogLuv encoding. This is turned off by default for 32-bit LogLuv and
+ on for 24-bit LogLuv output. Dithering improves the average color
+ accuracy over the image.
+
+ 3) I added a #define for LOG_LUV_PUBLIC, which is enabled by default in
+ tiffio.h, to expose internal routines for converting between LogLuv and
+ XYZ coordinates. This is helpful for writing more efficient,
+ specialized conversion routines, especially for reading LogLuv files.
+
+ Changes applied with minor edits.
+
+2001-01-23 Frank Warmerdam <warmerdam@pobox.com>
+
+ * tif_fax3.c: keep rw_mode flag internal to fax3 state to remember
+ whether we are encoding or decoding. This is to ensure graceful
+ recovery if TIFFClientOpen() discovers an attempt to open a compressed
+ file for "r+" access, and subsequently close it, as it resets the
+ tif_mode flag to O_RDONLY in this case to avoid writes, confusing the
+ compressor's concept of whether it is in encode or decode mode.
+
+2001-01-08 Mike Welles <mike@bangstate.com>
+
+ * Makefile.in: Now cleaning up after itself after creating the .tar.gz and .zip
+
+2001-01-07 Frank Warmerdam <warmerdam@pobox.com>
+
+ * html/libtiff.html: Fixed arguments in example for TIFFRGBAImageGet()
+ as per bug report by Patrick Connor.
+
+2000-12-28 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Added RELEASE-DATE file to release file list.
+
+ * Fixed libtiff/makefile.vc to make tiffvers.h not version.h.
+
+2000-12-22 Mike Welles <mike@bangstate.com>
+ * added link to CVS mirror from index.html
+
+ * updated html/internals.html to note that LZW compression is
+ not supported by default.
+
+2000-12-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * updated html/libtiff.html to not point at Niles' old JPL web site
+ for the man pages, point at www.libtiff.org.
+
+2000-12-21 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/tif_apple.c: Applied "Carbon" support patches supplied by
+ Leonard Rosenthol <leonardr@lazerware.com>. May interfere
+ with correct building on older systems. If so, please let me know.
+
+2000-12-19 Mike Welles <mike@bangsate.com>
+
+ * Took out LZW Encoding from tif_lzw.c
+
+ * Created HOWTO-RELEASE
+
+ * Created html/v3.5.6.html
+
+ * updated index.html
+
+2000-12-01 Frank Warmerdam <warmerdam@pobox.com>
+
+ * Added patches for EOFB support in tif_fax3.c and tif_fax3.h.
+ Patches supplied by Frank Cringle <fdc@cliwe.ping.de>
+ Example file at: ftp://ftp.remotesensing.org/pub/libtiff/eofb_396.tif
+
+2000-11-24 Frank Warmerdam <warmerdam@pobox.com>
+
+ * libtiff/Makefile.in: Added an installPrivateHdrs and install-private
+ target so that the private headers required by libgeotiff can be
+ installed with the others. They are not installed by default.
+
+ * libtiff/Makefile.in: Added @MACHLIBDEPS@ to LINUXdso and GNULDdso
+ targets so libtiff.so will be built with an explicit dependency
+ on libm.so.
+
+ * libtiff/Makefile.in: Use softlinks to link libtiff.so.3 to
+ libtiff.so.3.5.5.
+
+ * libtiff/Makefile.in & configure: Remove all references to the ALPHA
+ file, or ALPHA version logic. Added stuff about DIST_POINT in
+ place of DIST_TYPE and the alpha release number stuff.
+
+2000-11-22 Frank Warmerdam <warmerdam@pobox.com>
+
+ * I have applied a patch from Steffen Moeller <moeller@ebi.ac.uk> to
+ the configure script so that it now accepts the --prefix, and
+ --exec-prefix directives.
+
+2000-11-13 Frank Warmerdam <warmerda@cs46980-c>
+
+ * I have made a variety of modifications in an effort to ensure the
+ TIFFLIB_VERSION macro is automatically generated from the RELEASE-DATE
+ file which seems to be updated regularly.
+
+ o mkversion.c now reads RELEASE-DATE and emits TIFFLIB_VERSION in
+ version include file.
+ o renamed version.h to tiffvers.h because we now have to install it
+ with the public libtiff include files.
+ o include tiffvers.h in tiffio.h.
+ o updated tif_version.c to use tiffvers.h.
+ o Updated Makefile.in accordingly.
+
+ * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=25
+ I have updated the win32 detection rules in tiffcomp.h.
+
+2000-10-20 Frank Warmerdam <warmerda@cs46980-c>
+
+ * tif_getimage.c: Fixed RGBA translation for YCbCr images for which
+ the strip/tile width and height aren't multiples of the sampling size.
+ See http://bugzilla.remotesensing.org/show_bug.cgi?id=20
+ Some patches from Rick LaMont of Dot C Software.
+
+ * Modified tif_packbits.c encoder to avoid compressing more
+ data than provided if rowsize doesn't factor into provided data
+ (such as occurs for YCbCr).
+
+2000-10-19 Frank Warmerdam <warmerda@cs46980-c>
+
+ * tools/rgb2ycbcr.c: fixed output strip size to account for vertical
+ roundup if rows_per_strip not a multiple of vertical sample size.
+
+2000-10-16 Frank Warmerdam <warmerda@cs46980-c>
+
+ * tif_dir.c: Clear TIFF_ISTILED flag in TIFFDefaultDirectory
+ as per http://bugzilla.remotesensing.org/show_bug.cgi?id=18
+ from vandrove@vc.cvut.cz.
+
+ * Modified tif_packbits.c decoding to avoid overrunning the
+ output buffer, and to issue a warning if data needs to be
+ discarded. See http://bugzilla.remotesensing.org/show_bug.cgi?id=18
+
+2000-10-12 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Modified tiff2bw to ensure portions add to 100%, and that
+ white is properly recovered.
+
+ See bug http://bugzilla.remotesensing.org/show_bug.cgi?id=15
+ Patch c/o Stanislav Brabec <utx@penguin.cz>
+
+2000-09-30 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Modified TIFFClientOpen() to emit an error on an attempt to
+ open a comperessed file for update (O_RDWR/r+) access. This is
+ because the compressor/decompressor code gets very confused when
+ the mode is O_RDWR, assuming this means writing only. See
+ bug http://bugzilla.remotesensing.org/show_bug.cgi?id=13
+
+2000-09-27 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Added GNULDdso target an`d switched linux and freebsd to use it.
+
+2000-09-26 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Applied patch for 0x0000 sequences in tif_fax3.h's definition
+ of EXPAND1D() as per bug 11 (from Roman).
+
+2000-09-25 Frank Warmerdam <warmerda@cs46980-c>
+ * Fixed tiffcomp.h to avoid win32 stuff if unix #defined, to improve
+ cygwin compatibility.
+
+ * Applied patch from Roman Shpount to tif_fax3.c. This seems to
+ be a proper fix to the buffer sizing problem. See
+ http://bugzilla.remotesensing.org/show_bug.cgi?id=11
+
+ * Fixed tif_getimage.c to fix overrun bug with YCbCr images without
+ downsampling. http://bugzilla.remotesensing.org/show_bug.cgi?id=10
+ Thanks to Nick Lamb <njl98r@ecs.soton.ac.uk> for reporting the
+ bug and proving the patch.
+
+2000-09-18 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Fixed tif_jpeg.c so avoid destroying the decompressor before
+ we are done access data thanks to bug report from:
+ Michael Eckstein <eckstein@gepro.cz>.
+
+ * Reverted tif_flush change.
+
+2000-09-14 Frank Warmerdam <warmerda@cs46980-c>
+
+ * tif_flush.c: Changed so that TIFFFlushData() doesn't return an
+ error when TIFF_BEENWRITING is not set. This ensures that the
+ directory contents can still be flushed by TIFFFlush().
+
+2000-08-14 Frank Warmerdam <warmerda@rommel.atlsci.com>
+
+ * tif_open.c: Don't set MMAP for O_RDWR files.
+
+ * tif_open.c: Set STRIPCHOP_DEFAULT for O_RDWR as well as O_RDONLY
+ so that files opened for update can be strip chopped too.
+
+ * tif_read.c: fixed up bug with files missing rowsperstrip and
+ the strips per separation fix done a few weeks ago.
+
+2000-07-17 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Tentatively added support for SAMPLEFORMAT_COMPLEXIEEEFP, and
+ SAMPLEFORMAT_COMPLEXINT.
+
+2000-07-13 Mike Welles <mike@onshore.com>
+
+ * index.html, bugs.html: added bugzilla info.
+
+2000-07-12 Frank Warmerdam <warmerda@rommel.atlsci.com>
+
+ * tif_read.c: fix subtle bug with determining the number of
+ rows for strips that are the last strip in a separation but
+ not the last strip of all in TIFFReadEncodedStrip().
+
+ * Applied 16/32 bit fix to tif_fax3.c. Fix supplied by
+ Peter Skarpetis <peters@serendipity-software.com.au>
+
+2000-06-15 Frank Warmerdam <warmerda@rommel.atlsci.com>
+
+ * Modified tiffio.h logic with regard to including windows.h. It
+ won't include it when building with __CYGWIN__.
+
+2000-05-11 Frank Warmerdam <warmerda@cs46980-c>
+
+ * README: update to mention www.libtiff.org, don't list Sam's old
+ email address.
+
+ * configure: Fixed DSO test for Linux as per patch from
+ Jan Van Buggenhout <chipzz@Ace.ULYSSIS.Student.KULeuven.Ac.Be>.
+
+2000-04-21 Frank Warmerdam <warmerda@rommel.atlsci.com>
+
+ * libtiff/tif_dirread.c: Don't use estimate strip byte count for
+ one tile/strip images with an offset, and byte count of zero. These
+ could be "unpopulated" images.
+
+2000-04-18 Frank Warmerdam <warmerda@rommel.atlsci.com>
+
+ * contrib/addtiffo: Added "averaging" resampling option.
+
+ * tools/tiffsplit.c: Copy TIFFTAG_SAMPLEFORMAT.
+
+Tue Apr 18 16:18:08 2000 Frank Warmerdam <warmerda@esabot.atlsci.com>
+
+ * tools/Makefile.in: Modified to install properly on SGI.
+
+2000-04-12 Mike Welles <mike@onshore.com>
+ * configure: Fixed stupid mistake in libc6 test on Linux
+
+2000-04-04 Mike Welles <mike@onshore.com>
+ * tif_win32.c: Applied patch to fix overreads and ovverwrites
+ caught by BoundsChecker. From Arvan Pritchard
+ <arvan.pritchard@infomatix.co.uk> (untested).
+
+ * tif_getimage.c: Applied patch to silence VC6 warnings. From
+ Arvan Pritchard <arvan.pritchard@informatix.co.uk>
+
+ * tif_lzw.c: Applied patch to silence VC6 warnings. From
+ Arvan Pritchard <arvan.pritchard@informatix.co.uk>
+
+2000-03-28 Frank Warmerdam <warmerda@cs46980-c>
+
+ * Added contrib/stream (stream io) code submitted by Avi Bleiweiss.
+
+2000-03-28 Frank Warmerdam <warmerda@cs46980-c> *** 3.5.5 release ***
+
+ * fax2ps: Fixed mixup of width and height in bounding box statement
+ as per submission by Nalin Dahyabhai <nalin@redhat.com>.
+
+2000-03-27 Mike Welles <mike@onshore.com>
+
+ * fax2ps: Modified printruns to take uint32 instead of uint16.
+ Patch courtesy of Bernt Herd <herd@herdsoft.com>
+
+2000-03-20 Mike Welles <mike@onshore.com>
+
+ * configure: added test for libc6 for linux targets. Bug reported by
+ Stanislav Brabec <utx@k332.feld.cvut.cz>
+
+ * Added 3.5 docs to html/Makefile.in.
+ Thanks to Stanislav Brabec <utx@k332.feld.cvut.cz>
+
+ * configure: fixed bugs in sed scripts
+ (applied sed script s:/@:s;@:;s:/s;;:;: to configure).
+ fix submitted to Stanislav Brabec <utx@k332.feld.cvut.cz>
+
+ * tools/iptcutil was not in files list, and wasn't being
+ added to tar archive. Updated Makefile.in.
+
+2000-03-17 Frank Warmerdam <warmerda@cs46980-c>
+
+ * tif_fax3.c: Fixed serious bug introduced during the uint16->uint32
+ conversion for the run arrays.
+
+2000-03-03 Frank Warmerdam <warmerda@cs46980-c.mtnk1.on.wave.home.com>
+
+ * Set td_sampleformat default to SAMPLEFORMAT_UINT instead of
+ SAMPLEFORMAT_VOID in TIFFDefaultDirectory() in tif_dir.c.
+
+2000-03-02 Frank Warmerdam <warmerda@cs46980-c.mtnk1.on.wave.home.com>
+
+ * Added "GetDefaulted" support for TIFFTAG_SAMPLEFORMAT in tif_aux.c.
+
+ * Patched tif_fax3.c so that dsp->runs is allocated a bit bigger
+ to avoid overruns encountered with frle_bug.tif.
+
+Tue Feb 15 22:01:05 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Fixed tools/tiffcmp so that stopondiff testing works.
+ Patch care of Joseph Orost <joe@sanskrit.lz.att.com>.
+
+2000-01-28 <warmerda@CS46980-B>
+
+ * Modified tif_unix.c to support 2-4GB seeks if USE_64BIT_API is
+ set to 1, and added default (off) setting in tiffconf.h. This
+ should eventually be set by the configure script somehow.
+
+ The original work on all these 2-4GB changes was done by
+ Peter Smith (psmith@creo.com).
+
+ * Modified tif_win32.c to support 2-4GB seeks.
+
+ * tentatively changed toff_t to be unsigned instead of signed to
+ facilitate support for 2-4GB files.
+
+ * Updated a variety of files to use toff_t. Fixed some mixups
+ between toff_t and tsize_t.
+
+Fri Jan 28 10:13:49 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Largely reimplemented contrib/addtiffo to avoid temp files,
+ updating the TIFF file in place. Fixed a few other bugs to.
+
+ * Set tif_rawdatasize to zero when freeing raw data buffer in
+ TIFFWriteDirectory().
+
+ * Enabled "REWRITE_HACK" in tif_write.c by default.
+
+ * Fix bug in tif_write.c when switching between reading one directory
+ and writing to another.
+
+ * Made TIFFWriteCheck() public, and added TIFFCreateDirectory()
+
+Wed Jan 5 12:37:48 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added TIFFmemory(3t) functions to libtiff.def.
+
+Tue Jan 4 13:39:00 2000 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added libtiff/libtiff.def to TIFFILES distribution list.
+
+Mon Dec 27 12:13:39 EST 1999 Mike Welles <mike@onshore.com>
+
+ * Created lzw compression kit, as a new module (libtiff-lzw-compression-kit).
+
+ * Altered descriptions in tools to reflect "by default" lzw not supported
+
+ * Updated index.html to note lzw compression kit.
+
+Tue Dec 21 14:01:51 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added fax3sm_winnt.c to distribution list in Makefile.in.
+
+Tue Dec 21 11:04:45 EST 1999 Mike Welles <mike@onshore.com> *** 3.5.4 release ***
+
+ * Aadded Pixar tag support. Contributed by Phil Beffery <phil@pixar.com>
+
+ * Made one more change to tif_dir.c for removal of LZW compression. Also added notice
+ when LZW compression invoked.
+
+ * Changed default compression in tools to TIFF_PACKBITS, and changed usage descriptions
+ in tools to reflect removal of LZW compression
+
+Mon Dec 20 18:39:02 EST 1999 Mike Welles <mike@onshore.com>
+
+ * Fixed bug that caused LZW (non) compression to segfault. Added
+ warning about LZW compression removed being removed, and why.
+
+ * Added nostrip to install in tools/Makefile.in so that debugging
+ symbols are kept.
+
+Tue Dec 7 12:04:47 EST 1999 Mike Welles <mike@onshore.com>
+
+ * Added patch from Ivo Penzar <ivo.penzar@infolink-software.com>,
+ supporting Adobe ZIP deflate. Untested.
+
+Sat Dec 4 15:47:11 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Made Packbits the default compression in tools/tiff2rgba.c instead
+ of LZW.
+
+Tue Nov 30 14:41:43 1999 Frank Warmerdam <warmerda@gdal.velocet.ca> *** 3.5.3. release ***
+
+ * Added tif_luv to contrib/djgpp/Makefile.lib.
+
+Tue Nov 30 14:15:32 EST 1999 Mike Welles <mike@onshore.com>
+
+ * Added zip creation to relase makefile target
+
+ * Added html for TIFFWriteTile.3t man page.
+
+Tue Nov 30 09:20:16 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added some changes to tif_write.c to support rewriting existing
+ fixed sized tiles and strips. Code mods disabled by default, only
+ enabled if REWRITE_HACK is defined for now.
+
+Mon Nov 29 11:43:42 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added TIFFWriteTile.3t man page.
+
+Sun Nov 28 20:36:18 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added notes on use of makefile.vc in build.html, and fixed
+ email subscription address.
+
+199-11-28 Mike Welles <mike@onshore.com>
+
+ * Fixed apocalypse-inducing y2k bug in contrib/ras/ras2tiff.c
+
+ * Did some casts cleaning up to reduce compiler warnings in tif_fax3.c,
+ from Bruce Carmeron <cameron@petris.com> -- modifications of
+ changes made by Frank (sun cc still complained on cast).
+
+ * Added tiffconf.h to install target per request from Bill
+ Radcliffe <billr@corbis.com>: "We need a way for ImageMagick to
+ know features have been compiled into the TIFF library in order to
+ handle things properly".
+
+Sat Nov 27 16:49:21 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * fixed various VC++ warnings as suggested by Gilles Vollant
+ <info@winimage.com>.
+
+Wed Nov 24 12:08:16 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Modified TIFFquery.3t man pages info on TIFFIsByteSwapped() to
+ not imply applications are responsible for image data swapping.
+
+1999-11-22 Mike Welles <mike@onshore.com>
+ * HTML-ized the man pages, added to html/man
+
+ * Removed LZW Compression to comply with Unisys patent extortion.
+
+1999-09-29 Mike Welles <mike@onshore.com>
+ * Corrected one remaining 16 -> 32 bit value in tif_fax3.c,
+ From Ivo Penzar <ivo.penzar@infolink-software.com.
+
+ * Added patch from Ivo Penzar to have TiffAdvanceDirectory handle
+ memory mapped files. <ivo.penzar@infolink-software.com>
+
+1999-09-26 Mike Welles <mike@onshore.com> *** 3.5.2 release ***
+ * Corrected alpha versioning.
+
+ * Removed distinction between alpha and release targets in Makefile.in.
+
+ * added release.stamp target, which tags cvs tree, and updates
+ "RELEASE-DATE"
+
+ * added releasediff target, which diffs tree with source as of
+ date in "RELEASE-DATE"
+
+ * Ticked up version to 3.5.2 (alpha 01 -- but I think we'll moving
+ away from alpha/non-alpha distinctions).
+
+ * updated html to reflect release
+
+1999-09-23 <warmerda@CS46980-B>
+
+ * Set O_BINARY for tif_unix.c open() ... used on cygwin for instance.
+
+ * Added CYGWIN case in configure.
+
+Fri Sep 17 00:13:51 CEST 1999 Mike Welles <mike@onshore.com>
+
+ * Applied Francois Dagand's patch to handle fax decompression bug.
+ (sizes >= 65536 were failing)
+
+Tue Sep 14 21:31:43 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Applied "a" mode fix to tif_win32.c/TIFFOpen() as suggested
+ by Christopher Lawton <clawton@mathworks.com>
+
+Wed Sep 8 08:19:18 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added IRIX/gcc, and OSF/1 4.x support on behalf of
+ Albert Chin-A-Young <china@thewrittenword.com>
+
+ * Added TIFFReassignTagToIgnore() API on behalf of
+ Bruce Cameron <cameron@petris.com>. Man page still pending.
+
+Wed Aug 25 11:39:07 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added test target in Makefile, test_pics.sh script and pics/*.rpt
+ files to provide for a rudimentary testsuite.
+
+ * Added contrib/tags back from old distribution ... fixed up a bit.
+
+1999-08-16 <warmerda@CS46980-B>
+
+ * Added simple makefile.vc makefiles for building with MS VC++
+ on Windows NT/98/95 in console mode. Stuff in contrib/win* make give
+ better solutions for some users.
+
+Mon Aug 16 21:52:11 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * Added addtiffo (add overviews to a TIFF file) in contrib. Didn't
+ put it in tools since part of it is in C++.
+
+1999-08-16 Michael L. Welles <mike@kurtz.fake>
+
+ * Updated html/index.html with anon CVS instructions.
+
+Mon Aug 16 13:18:41 1999 Frank Warmerdam <warmerda@gdal.velocet.ca>
+
+ * pre-remove so link before softlink in LINUXdso action in
+ libtiff/Makefile.in to avoid failure on LINUXdso builds other than
+ the first.
+
+ * Fixed problem with cvtcmap() in tif_getimage.c modifying the
+ colormaps owned by the TIFF handle itself when trying to fixup wrong
+ (eight bit) colormaps. Corrected by maintaining a private copy of
+ the colormap.
+
+ * Added TIFFReadRGBATile()/TIFFReadRGBAStrip() support in
+ tif_getimage.c.
+
+ * CVS Repository placed at remotesensing.org. ChangeLog added.
diff --git a/Source/LibTIFF/LibTIFF.2003.vcproj b/Source/LibTIFF/LibTIFF.2003.vcproj
new file mode 100644
index 0000000..8c65996
--- /dev/null
+++ b/Source/LibTIFF/LibTIFF.2003.vcproj
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="LibTIFF"
+ SccProjectName="&quot;$/FreeImage/LibTIFF&quot;, MKAAAAAA"
+ SccLocalPath=".">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="..\libtiff\libtiff,..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/LibTIFF.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibTIFF.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\libtiff\libtiff"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/LibTIFF.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibTIFF.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="tif_aux.c">
+ </File>
+ <File
+ RelativePath="tif_close.c">
+ </File>
+ <File
+ RelativePath="tif_codec.c">
+ </File>
+ <File
+ RelativePath="tif_color.c">
+ </File>
+ <File
+ RelativePath="tif_compress.c">
+ </File>
+ <File
+ RelativePath="tif_dir.c">
+ </File>
+ <File
+ RelativePath="tif_dirinfo.c">
+ </File>
+ <File
+ RelativePath="tif_dirread.c">
+ </File>
+ <File
+ RelativePath="tif_dirwrite.c">
+ </File>
+ <File
+ RelativePath="tif_dumpmode.c">
+ </File>
+ <File
+ RelativePath="tif_error.c">
+ </File>
+ <File
+ RelativePath="tif_extension.c">
+ </File>
+ <File
+ RelativePath="tif_fax3.c">
+ </File>
+ <File
+ RelativePath="tif_fax3sm.c">
+ </File>
+ <File
+ RelativePath="tif_flush.c">
+ </File>
+ <File
+ RelativePath="tif_getimage.c">
+ </File>
+ <File
+ RelativePath="tif_jpeg.c">
+ </File>
+ <File
+ RelativePath="tif_luv.c">
+ </File>
+ <File
+ RelativePath="tif_lzw.c">
+ </File>
+ <File
+ RelativePath="tif_next.c">
+ </File>
+ <File
+ RelativePath="tif_open.c">
+ </File>
+ <File
+ RelativePath="tif_packbits.c">
+ </File>
+ <File
+ RelativePath="tif_pixarlog.c">
+ </File>
+ <File
+ RelativePath="tif_predict.c">
+ </File>
+ <File
+ RelativePath="tif_print.c">
+ </File>
+ <File
+ RelativePath="tif_read.c">
+ </File>
+ <File
+ RelativePath="tif_strip.c">
+ </File>
+ <File
+ RelativePath="tif_swab.c">
+ </File>
+ <File
+ RelativePath="tif_thunder.c">
+ </File>
+ <File
+ RelativePath="tif_tile.c">
+ </File>
+ <File
+ RelativePath="tif_version.c">
+ </File>
+ <File
+ RelativePath="tif_warning.c">
+ </File>
+ <File
+ RelativePath="tif_write.c">
+ </File>
+ <File
+ RelativePath="tif_zip.c">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="t4.h">
+ </File>
+ <File
+ RelativePath="tif_config.h">
+ </File>
+ <File
+ RelativePath="tif_dir.h">
+ </File>
+ <File
+ RelativePath="tif_fax3.h">
+ </File>
+ <File
+ RelativePath="tif_predict.h">
+ </File>
+ <File
+ RelativePath="tiff.h">
+ </File>
+ <File
+ RelativePath="tiffio.h">
+ </File>
+ <File
+ RelativePath="tiffiop.h">
+ </File>
+ <File
+ RelativePath="tiffvers.h">
+ </File>
+ <File
+ RelativePath="uvcode.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibTIFF/LibTIFF.2005.vcproj b/Source/LibTIFF/LibTIFF.2005.vcproj
new file mode 100644
index 0000000..3b9f332
--- /dev/null
+++ b/Source/LibTIFF/LibTIFF.2005.vcproj
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="LibTIFF"
+ ProjectGUID="{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+ RootNamespace="LibTIFF"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\libtiff\libtiff,..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/LibTIFF.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\LibTIFF.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\libtiff\libtiff"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/LibTIFF.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\LibTIFF.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="tif_aux.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_close.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_codec.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_color.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_compress.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dir.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirinfo.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirread.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirwrite.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dumpmode.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_error.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_extension.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3sm.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_flush.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_getimage.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_luv.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_lzw.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_next.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_open.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_packbits.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_pixarlog.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_predict.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_print.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_read.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_strip.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_swab.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_thunder.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_tile.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_version.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_warning.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_write.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_zip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="t4.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_config.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_dir.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_predict.h"
+ >
+ </File>
+ <File
+ RelativePath="tiff.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffio.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffiop.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffvers.h"
+ >
+ </File>
+ <File
+ RelativePath="uvcode.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibTIFF/LibTIFF.2008.vcproj b/Source/LibTIFF/LibTIFF.2008.vcproj
new file mode 100644
index 0000000..a5f377a
--- /dev/null
+++ b/Source/LibTIFF/LibTIFF.2008.vcproj
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="LibTIFF"
+ ProjectGUID="{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+ RootNamespace="LibTIFF"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="..\libtiff\libtiff;&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="false"
+ FloatingPointModel="0"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(SolutionDir)..\..\third_party\Win32ConfigExternal$(ConfigurationName).vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\libtiff\libtiff;&quot;$(ProjectDir)\..\..\..\zlib-1.2.3&quot;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;ZLIB_WINAPI;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="false"
+ RuntimeLibrary="3"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ LinkLibraryDependencies="false"
+ SuppressStartupBanner="true"
+ IgnoreAllDefaultLibraries="false"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="tif_aux.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_close.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_codec.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_color.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_compress.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dir.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirinfo.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirread.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dirwrite.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_dumpmode.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_error.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_extension.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3sm.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_flush.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_getimage.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_jpeg.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_luv.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_lzw.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_next.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_open.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_packbits.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_pixarlog.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_predict.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_print.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_read.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_strip.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_swab.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_thunder.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_tile.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_version.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_warning.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_write.c"
+ >
+ </File>
+ <File
+ RelativePath="tif_zip.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="t4.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_config.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_dir.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_fax3.h"
+ >
+ </File>
+ <File
+ RelativePath="tif_predict.h"
+ >
+ </File>
+ <File
+ RelativePath="tiff.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffio.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffiop.h"
+ >
+ </File>
+ <File
+ RelativePath="tiffvers.h"
+ >
+ </File>
+ <File
+ RelativePath="uvcode.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/LibTIFF/Makefile.am b/Source/LibTIFF/Makefile.am
new file mode 100644
index 0000000..b918bb9
--- /dev/null
+++ b/Source/LibTIFF/Makefile.am
@@ -0,0 +1,143 @@
+# Tag Image File Format (TIFF) Software
+#
+# Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+
+# Process this file with automake to produce Makefile.in.
+
+LIBPORT = $(top_builddir)/port/libport.la
+LIBTIFF = $(top_builddir)/libtiff/libtiff.la
+libtiffincludedir = $(includedir)
+
+EXTRA_DIST = Makefile.vc \
+ SConstruct \
+ tif_config.h-vms \
+ tif_config.vc.h \
+ tif_config.wince.h \
+ tiffconf.vc.h \
+ tiffconf.wince.h \
+ libtiff.def \
+ $(EXTRA_SRCS)
+
+libtiffinclude_HEADERS = \
+ tiff.h \
+ tiffio.h \
+ tiffvers.h
+
+if HAVE_CXX
+libtiffinclude_HEADERS += tiffio.hxx
+endif
+
+noinst_HEADERS = \
+ t4.h \
+ tif_dir.h \
+ tif_predict.h \
+ tiffiop.h \
+ uvcode.h
+
+nodist_libtiffinclude_HEADERS = \
+ tiffconf.h
+
+libtiff_la_SOURCES = \
+ tif_aux.c \
+ tif_close.c \
+ tif_codec.c \
+ tif_color.c \
+ tif_compress.c \
+ tif_dir.c \
+ tif_dirinfo.c \
+ tif_dirread.c \
+ tif_dirwrite.c \
+ tif_dumpmode.c \
+ tif_error.c \
+ tif_extension.c \
+ tif_fax3.c \
+ tif_fax3sm.c \
+ tif_flush.c \
+ tif_getimage.c \
+ tif_jbig.c \
+ tif_jpeg.c \
+ tif_luv.c \
+ tif_lzw.c \
+ tif_next.c \
+ tif_ojpeg.c \
+ tif_open.c \
+ tif_packbits.c \
+ tif_pixarlog.c \
+ tif_predict.c \
+ tif_print.c \
+ tif_read.c \
+ tif_strip.c \
+ tif_swab.c \
+ tif_thunder.c \
+ tif_tile.c \
+ tif_unix.c \
+ tif_version.c \
+ tif_warning.c \
+ tif_write.c \
+ tif_zip.c
+
+libtiffxx_la_SOURCES = \
+ tif_stream.cxx
+
+EXTRA_SRCS = \
+ tif_acorn.c \
+ tif_apple.c \
+ tif_atari.c \
+ tif_msdos.c \
+ tif_next.c \
+ tif_win3.c \
+ tif_win32.c
+
+lib_LTLIBRARIES = libtiff.la
+if HAVE_CXX
+lib_LTLIBRARIES += libtiffxx.la
+endif
+
+libtiff_la_LDFLAGS = \
+ -no-undefined \
+ -version-number $(LIBTIFF_VERSION_INFO)
+if HAVE_RPATH
+libtiff_la_LDFLAGS += $(LIBDIR)
+endif
+libtiff_la_LIBADD = $(LIBPORT)
+
+libtiffxx_la_LDFLAGS = \
+ -no-undefined \
+ -version-number $(LIBTIFF_VERSION_INFO)
+if HAVE_RPATH
+libtiffxx_la_LDFLAGS += $(LIBDIR)
+endif
+libtiffxx_la_LIBADD = $(LIBTIFF) $(LIBPORT)
+libtiffxx_la_DEPENDENCIES = libtiff.la
+
+#
+# The finite state machine tables used by the G3/G4 decoders
+# are generated by the mkg3states program. On systems without
+# make these rules have to be manually carried out.
+#
+noinst_PROGRAMS = mkg3states
+mkg3states_SOURCES = mkg3states.c tif_fax3.h
+mkg3states_LDADD = $(LIBPORT)
+
+faxtable: mkg3states
+ (rm -f tif_fax3sm.c && ./mkg3states -b -c const tif_fax3sm.c)
+
diff --git a/Source/LibTIFF/Makefile.in b/Source/LibTIFF/Makefile.in
new file mode 100644
index 0000000..551ff52
--- /dev/null
+++ b/Source/LibTIFF/Makefile.in
@@ -0,0 +1,888 @@
+# Makefile.in generated by automake 1.11 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Tag Image File Format (TIFF) Software
+#
+# Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+
+# Process this file with automake to produce Makefile.in.
+
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@HAVE_CXX_TRUE@am__append_1 = tiffio.hxx
+@HAVE_CXX_TRUE@am__append_2 = libtiffxx.la
+@HAVE_RPATH_TRUE@am__append_3 = $(LIBDIR)
+@HAVE_RPATH_TRUE@am__append_4 = $(LIBDIR)
+noinst_PROGRAMS = mkg3states$(EXEEXT)
+subdir = libtiff
+DIST_COMMON = $(am__libtiffinclude_HEADERS_DIST) $(noinst_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+ $(srcdir)/tif_config.h.in $(srcdir)/tiffconf.h.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
+CONFIG_HEADER = tif_config.h tiffconf.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libtiffincludedir)" \
+ "$(DESTDIR)$(libtiffincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libtiff_la_DEPENDENCIES = $(LIBPORT)
+am_libtiff_la_OBJECTS = tif_aux.lo tif_close.lo tif_codec.lo \
+ tif_color.lo tif_compress.lo tif_dir.lo tif_dirinfo.lo \
+ tif_dirread.lo tif_dirwrite.lo tif_dumpmode.lo tif_error.lo \
+ tif_extension.lo tif_fax3.lo tif_fax3sm.lo tif_flush.lo \
+ tif_getimage.lo tif_jbig.lo tif_jpeg.lo tif_luv.lo tif_lzw.lo \
+ tif_next.lo tif_ojpeg.lo tif_open.lo tif_packbits.lo \
+ tif_pixarlog.lo tif_predict.lo tif_print.lo tif_read.lo \
+ tif_strip.lo tif_swab.lo tif_thunder.lo tif_tile.lo \
+ tif_unix.lo tif_version.lo tif_warning.lo tif_write.lo \
+ tif_zip.lo
+libtiff_la_OBJECTS = $(am_libtiff_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libtiff_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libtiff_la_LDFLAGS) $(LDFLAGS) -o $@
+am_libtiffxx_la_OBJECTS = tif_stream.lo
+libtiffxx_la_OBJECTS = $(am_libtiffxx_la_OBJECTS)
+libtiffxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libtiffxx_la_LDFLAGS) $(LDFLAGS) -o $@
+@HAVE_CXX_TRUE@am_libtiffxx_la_rpath = -rpath $(libdir)
+PROGRAMS = $(noinst_PROGRAMS)
+am_mkg3states_OBJECTS = mkg3states.$(OBJEXT)
+mkg3states_OBJECTS = $(am_mkg3states_OBJECTS)
+mkg3states_DEPENDENCIES = $(LIBPORT)
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/config/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_$(V))
+am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
+am__v_CXX_0 = @echo " CXX " $@;
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_$(V))
+am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libtiff_la_SOURCES) $(libtiffxx_la_SOURCES) \
+ $(mkg3states_SOURCES)
+DIST_SOURCES = $(libtiff_la_SOURCES) $(libtiffxx_la_SOURCES) \
+ $(mkg3states_SOURCES)
+am__libtiffinclude_HEADERS_DIST = tiff.h tiffio.h tiffvers.h \
+ tiffio.hxx
+HEADERS = $(libtiffinclude_HEADERS) $(nodist_libtiffinclude_HEADERS) \
+ $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLUT_CFLAGS = @GLUT_CFLAGS@
+GLUT_LIBS = @GLUT_LIBS@
+GLU_CFLAGS = @GLU_CFLAGS@
+GLU_LIBS = @GLU_LIBS@
+GL_CFLAGS = @GL_CFLAGS@
+GL_LIBS = @GL_LIBS@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDIR = @LIBDIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTIFF_ALPHA_VERSION = @LIBTIFF_ALPHA_VERSION@
+LIBTIFF_DOCDIR = @LIBTIFF_DOCDIR@
+LIBTIFF_MAJOR_VERSION = @LIBTIFF_MAJOR_VERSION@
+LIBTIFF_MICRO_VERSION = @LIBTIFF_MICRO_VERSION@
+LIBTIFF_MINOR_VERSION = @LIBTIFF_MINOR_VERSION@
+LIBTIFF_RELEASE_DATE = @LIBTIFF_RELEASE_DATE@
+LIBTIFF_VERSION = @LIBTIFF_VERSION@
+LIBTIFF_VERSION_INFO = @LIBTIFF_VERSION_INFO@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+XMKMF = @XMKMF@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+acx_pthread_config = @acx_pthread_config@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+LIBPORT = $(top_builddir)/port/libport.la
+LIBTIFF = $(top_builddir)/libtiff/libtiff.la
+libtiffincludedir = $(includedir)
+EXTRA_DIST = Makefile.vc \
+ SConstruct \
+ tif_config.h-vms \
+ tif_config.vc.h \
+ tif_config.wince.h \
+ tiffconf.vc.h \
+ tiffconf.wince.h \
+ libtiff.def \
+ $(EXTRA_SRCS)
+
+libtiffinclude_HEADERS = tiff.h tiffio.h tiffvers.h $(am__append_1)
+noinst_HEADERS = \
+ t4.h \
+ tif_dir.h \
+ tif_predict.h \
+ tiffiop.h \
+ uvcode.h
+
+nodist_libtiffinclude_HEADERS = \
+ tiffconf.h
+
+libtiff_la_SOURCES = \
+ tif_aux.c \
+ tif_close.c \
+ tif_codec.c \
+ tif_color.c \
+ tif_compress.c \
+ tif_dir.c \
+ tif_dirinfo.c \
+ tif_dirread.c \
+ tif_dirwrite.c \
+ tif_dumpmode.c \
+ tif_error.c \
+ tif_extension.c \
+ tif_fax3.c \
+ tif_fax3sm.c \
+ tif_flush.c \
+ tif_getimage.c \
+ tif_jbig.c \
+ tif_jpeg.c \
+ tif_luv.c \
+ tif_lzw.c \
+ tif_next.c \
+ tif_ojpeg.c \
+ tif_open.c \
+ tif_packbits.c \
+ tif_pixarlog.c \
+ tif_predict.c \
+ tif_print.c \
+ tif_read.c \
+ tif_strip.c \
+ tif_swab.c \
+ tif_thunder.c \
+ tif_tile.c \
+ tif_unix.c \
+ tif_version.c \
+ tif_warning.c \
+ tif_write.c \
+ tif_zip.c
+
+libtiffxx_la_SOURCES = \
+ tif_stream.cxx
+
+EXTRA_SRCS = \
+ tif_acorn.c \
+ tif_apple.c \
+ tif_atari.c \
+ tif_msdos.c \
+ tif_next.c \
+ tif_win3.c \
+ tif_win32.c
+
+lib_LTLIBRARIES = libtiff.la $(am__append_2)
+libtiff_la_LDFLAGS = -no-undefined -version-number \
+ $(LIBTIFF_VERSION_INFO) $(am__append_3)
+libtiff_la_LIBADD = $(LIBPORT)
+libtiffxx_la_LDFLAGS = -no-undefined -version-number \
+ $(LIBTIFF_VERSION_INFO) $(am__append_4)
+libtiffxx_la_LIBADD = $(LIBTIFF) $(LIBPORT)
+libtiffxx_la_DEPENDENCIES = libtiff.la
+mkg3states_SOURCES = mkg3states.c tif_fax3.h
+mkg3states_LDADD = $(LIBPORT)
+all: tif_config.h tiffconf.h
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cxx .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libtiff/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign libtiff/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+tif_config.h: stamp-h1
+ @if test ! -f $@; then \
+ rm -f stamp-h1; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+ else :; fi
+
+stamp-h1: $(srcdir)/tif_config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status libtiff/tif_config.h
+$(srcdir)/tif_config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+tiffconf.h: stamp-h2
+ @if test ! -f $@; then \
+ rm -f stamp-h2; \
+ $(MAKE) $(AM_MAKEFLAGS) stamp-h2; \
+ else :; fi
+
+stamp-h2: $(srcdir)/tiffconf.h.in $(top_builddir)/config.status
+ @rm -f stamp-h2
+ cd $(top_builddir) && $(SHELL) ./config.status libtiff/tiffconf.h
+
+distclean-hdr:
+ -rm -f tif_config.h stamp-h1 tiffconf.h stamp-h2
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libtiff.la: $(libtiff_la_OBJECTS) $(libtiff_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libtiff_la_LINK) -rpath $(libdir) $(libtiff_la_OBJECTS) $(libtiff_la_LIBADD) $(LIBS)
+libtiffxx.la: $(libtiffxx_la_OBJECTS) $(libtiffxx_la_DEPENDENCIES)
+ $(AM_V_CXXLD)$(libtiffxx_la_LINK) $(am_libtiffxx_la_rpath) $(libtiffxx_la_OBJECTS) $(libtiffxx_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+mkg3states$(EXEEXT): $(mkg3states_OBJECTS) $(mkg3states_DEPENDENCIES)
+ @rm -f mkg3states$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(mkg3states_OBJECTS) $(mkg3states_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkg3states.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_aux.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_close.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_codec.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_color.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_compress.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_dir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_dirinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_dirread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_dirwrite.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_dumpmode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_error.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_extension.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_fax3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_fax3sm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_flush.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_getimage.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_jbig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_jpeg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_luv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_lzw.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_next.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_ojpeg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_open.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_packbits.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_pixarlog.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_predict.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_print.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_read.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_strip.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_swab.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_thunder.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_tile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_unix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_version.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_warning.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_write.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tif_zip.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+.cxx.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cxx.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cxx.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-libtiffincludeHEADERS: $(libtiffinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libtiffincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libtiffincludedir)"
+ @list='$(libtiffinclude_HEADERS)'; test -n "$(libtiffincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtiffincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtiffincludedir)" || exit $$?; \
+ done
+
+uninstall-libtiffincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libtiffinclude_HEADERS)'; test -n "$(libtiffincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libtiffincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libtiffincludedir)" && rm -f $$files
+install-nodist_libtiffincludeHEADERS: $(nodist_libtiffinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libtiffincludedir)" || $(MKDIR_P) "$(DESTDIR)$(libtiffincludedir)"
+ @list='$(nodist_libtiffinclude_HEADERS)'; test -n "$(libtiffincludedir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libtiffincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libtiffincludedir)" || exit $$?; \
+ done
+
+uninstall-nodist_libtiffincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_libtiffinclude_HEADERS)'; test -n "$(libtiffincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(libtiffincludedir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(libtiffincludedir)" && rm -f $$files
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) tif_config.h.in tiffconf.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) tif_config.h.in tiffconf.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) tif_config.h.in tiffconf.h.in $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) tif_config.h.in tiffconf.h.in $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) tif_config.h \
+ tiffconf.h
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libtiffincludedir)" "$(DESTDIR)$(libtiffincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-hdr distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libtiffincludeHEADERS \
+ install-nodist_libtiffincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-libtiffincludeHEADERS \
+ uninstall-nodist_libtiffincludeHEADERS
+
+.MAKE: all install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES \
+ install-libtiffincludeHEADERS install-man \
+ install-nodist_libtiffincludeHEADERS install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-libLTLIBRARIES \
+ uninstall-libtiffincludeHEADERS \
+ uninstall-nodist_libtiffincludeHEADERS
+
+
+faxtable: mkg3states
+ (rm -f tif_fax3sm.c && ./mkg3states -b -c const tif_fax3sm.c)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/LibTIFF/SConstruct b/Source/LibTIFF/SConstruct
new file mode 100644
index 0000000..1b04d8b
--- /dev/null
+++ b/Source/LibTIFF/SConstruct
@@ -0,0 +1,73 @@
+# $Id: SConstruct,v 1.19 2009/09/06 13:11:26 drolon Exp $
+
+# Tag Image File Format (TIFF) Software
+#
+# Copyright (C) 2005, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+
+# This file contains rules to build software with the SCons tool
+# (see the http://www.scons.org/ for details on SCons).
+
+# Import globally defined options
+Import([ 'env', 'idir_lib' ])
+
+SRCS = [ \
+ 'tif_aux.c', \
+ 'tif_close.c', \
+ 'tif_codec.c', \
+ 'tif_color.c', \
+ 'tif_compress.c', \
+ 'tif_dir.c', \
+ 'tif_dirinfo.c', \
+ 'tif_dirread.c', \
+ 'tif_dirwrite.c', \
+ 'tif_dumpmode.c', \
+ 'tif_error.c', \
+ 'tif_extension.c', \
+ 'tif_fax3.c', \
+ 'tif_fax3sm.c', \
+ 'tif_flush.c', \
+ 'tif_getimage.c', \
+ 'tif_jbig.c', \
+ 'tif_jpeg.c', \
+ 'tif_luv.c', \
+ 'tif_lzw.c', \
+ 'tif_next.c', \
+ 'tif_ojpeg.c', \
+ 'tif_open.c', \
+ 'tif_packbits.c', \
+ 'tif_pixarlog.c', \
+ 'tif_predict.c', \
+ 'tif_print.c', \
+ 'tif_read.c', \
+ 'tif_strip.c', \
+ 'tif_swab.c', \
+ 'tif_thunder.c', \
+ 'tif_tile.c', \
+ 'tif_unix.c', \
+ 'tif_version.c', \
+ 'tif_warning.c', \
+ 'tif_write.c', \
+ 'tif_zip.c' ]
+
+StaticLibrary('tiff', SRCS)
+SharedLibrary('tiff', SRCS)
+
diff --git a/Source/LibTIFF/libtiff.xcodeproj/project.pbxproj b/Source/LibTIFF/libtiff.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..c2b8210
--- /dev/null
+++ b/Source/LibTIFF/libtiff.xcodeproj/project.pbxproj
@@ -0,0 +1,377 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 45;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D79E5E770E28299D0046286C /* tif_extension.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E430E28299D0046286C /* tif_extension.c */; };
+ D79E5E780E28299D0046286C /* tif_pixarlog.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E440E28299D0046286C /* tif_pixarlog.c */; };
+ D79E5E790E28299D0046286C /* tif_warning.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E450E28299D0046286C /* tif_warning.c */; };
+ D79E5E7A0E28299D0046286C /* tif_dir.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E460E28299D0046286C /* tif_dir.h */; };
+ D79E5E7B0E28299D0046286C /* tif_dirwrite.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E470E28299D0046286C /* tif_dirwrite.c */; };
+ D79E5E7C0E28299D0046286C /* tif_write.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E480E28299D0046286C /* tif_write.c */; };
+ D79E5E7D0E28299D0046286C /* tif_tile.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E490E28299D0046286C /* tif_tile.c */; };
+ D79E5E7E0E28299D0046286C /* tif_read.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4A0E28299D0046286C /* tif_read.c */; };
+ D79E5E7F0E28299D0046286C /* tif_ojpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4B0E28299D0046286C /* tif_ojpeg.c */; };
+ D79E5E800E28299D0046286C /* tif_print.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4C0E28299D0046286C /* tif_print.c */; };
+ D79E5E810E28299D0046286C /* tif_error.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4D0E28299D0046286C /* tif_error.c */; };
+ D79E5E820E28299D0046286C /* tif_zip.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4E0E28299D0046286C /* tif_zip.c */; };
+ D79E5E830E28299D0046286C /* tif_luv.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E4F0E28299D0046286C /* tif_luv.c */; };
+ D79E5E840E28299D0046286C /* tif_flush.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E500E28299D0046286C /* tif_flush.c */; };
+ D79E5E850E28299D0046286C /* tif_lzw.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E510E28299D0046286C /* tif_lzw.c */; };
+ D79E5E860E28299D0046286C /* tif_jbig.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E520E28299D0046286C /* tif_jbig.c */; };
+ D79E5E870E28299D0046286C /* tif_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E530E28299D0046286C /* tif_unix.c */; };
+ D79E5E880E28299D0046286C /* tiffvers.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E540E28299D0046286C /* tiffvers.h */; };
+ D79E5E890E28299D0046286C /* tif_dirinfo.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E550E28299D0046286C /* tif_dirinfo.c */; };
+ D79E5E8A0E28299D0046286C /* tif_codec.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E560E28299D0046286C /* tif_codec.c */; };
+ D79E5E8B0E28299D0046286C /* tif_color.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E570E28299D0046286C /* tif_color.c */; };
+ D79E5E8C0E28299D0046286C /* tif_next.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E580E28299D0046286C /* tif_next.c */; };
+ D79E5E8D0E28299D0046286C /* tif_open.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E590E28299D0046286C /* tif_open.c */; };
+ D79E5E8E0E28299D0046286C /* t4.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E5A0E28299D0046286C /* t4.h */; };
+ D79E5E8F0E28299D0046286C /* tif_jpeg.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E5B0E28299D0046286C /* tif_jpeg.c */; };
+ D79E5E900E28299D0046286C /* tiff.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E5C0E28299D0046286C /* tiff.h */; };
+ D79E5E910E28299D0046286C /* tif_config.vc.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E5D0E28299D0046286C /* tif_config.vc.h */; };
+ D79E5E920E28299D0046286C /* tif_dir.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E5E0E28299D0046286C /* tif_dir.c */; };
+ D79E5E930E28299D0046286C /* tif_compress.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E5F0E28299D0046286C /* tif_compress.c */; };
+ D79E5E940E28299D0046286C /* tif_fax3sm.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E600E28299D0046286C /* tif_fax3sm.c */; };
+ D79E5E950E28299D0046286C /* tif_fax3.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E610E28299D0046286C /* tif_fax3.c */; };
+ D79E5E960E28299D0046286C /* tif_close.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E620E28299D0046286C /* tif_close.c */; };
+ D79E5E970E28299D0046286C /* tif_config.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E630E28299D0046286C /* tif_config.h */; };
+ D79E5E980E28299D0046286C /* tiffio.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E640E28299D0046286C /* tiffio.h */; };
+ D79E5E990E28299D0046286C /* tif_predict.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E650E28299D0046286C /* tif_predict.h */; };
+ D79E5E9A0E28299D0046286C /* tif_thunder.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E660E28299D0046286C /* tif_thunder.c */; };
+ D79E5E9B0E28299D0046286C /* tiffconf.wince.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E670E28299D0046286C /* tiffconf.wince.h */; };
+ D79E5E9C0E28299D0046286C /* tiffiop.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E680E28299D0046286C /* tiffiop.h */; };
+ D79E5E9E0E28299D0046286C /* tif_getimage.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E6A0E28299D0046286C /* tif_getimage.c */; };
+ D79E5E9F0E28299D0046286C /* tif_version.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E6B0E28299D0046286C /* tif_version.c */; };
+ D79E5EA00E28299D0046286C /* tif_dirread.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E6C0E28299D0046286C /* tif_dirread.c */; };
+ D79E5EA10E28299D0046286C /* tiffconf.vc.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E6D0E28299D0046286C /* tiffconf.vc.h */; };
+ D79E5EA20E28299D0046286C /* tif_config.wince.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E6E0E28299D0046286C /* tif_config.wince.h */; };
+ D79E5EA30E28299D0046286C /* tif_dumpmode.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E6F0E28299D0046286C /* tif_dumpmode.c */; };
+ D79E5EA40E28299D0046286C /* tif_packbits.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E700E28299D0046286C /* tif_packbits.c */; };
+ D79E5EA50E28299D0046286C /* uvcode.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E710E28299D0046286C /* uvcode.h */; };
+ D79E5EA60E28299D0046286C /* tif_aux.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E720E28299D0046286C /* tif_aux.c */; };
+ D79E5EA70E28299D0046286C /* tif_swab.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E730E28299D0046286C /* tif_swab.c */; };
+ D79E5EA80E28299D0046286C /* tif_predict.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E740E28299D0046286C /* tif_predict.c */; };
+ D79E5EA90E28299D0046286C /* tif_strip.c in Sources */ = {isa = PBXBuildFile; fileRef = D79E5E750E28299D0046286C /* tif_strip.c */; };
+ D79E5EAA0E28299D0046286C /* tif_fax3.h in Headers */ = {isa = PBXBuildFile; fileRef = D79E5E760E28299D0046286C /* tif_fax3.h */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ D2AAC046055464E500DB518D /* libtiff.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libtiff.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ D722DB7A0E2823C700977662 /* MacConfigExternalDebug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalDebug.xcconfig; path = ../../../MacConfigExternalDebug.xcconfig; sourceTree = SOURCE_ROOT; };
+ D722DB7B0E2823C700977662 /* MacConfigExternalRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = MacConfigExternalRelease.xcconfig; path = ../../../MacConfigExternalRelease.xcconfig; sourceTree = SOURCE_ROOT; };
+ D79E5E430E28299D0046286C /* tif_extension.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_extension.c; sourceTree = SOURCE_ROOT; };
+ D79E5E440E28299D0046286C /* tif_pixarlog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_pixarlog.c; sourceTree = SOURCE_ROOT; };
+ D79E5E450E28299D0046286C /* tif_warning.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_warning.c; sourceTree = SOURCE_ROOT; };
+ D79E5E460E28299D0046286C /* tif_dir.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_dir.h; sourceTree = SOURCE_ROOT; };
+ D79E5E470E28299D0046286C /* tif_dirwrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_dirwrite.c; sourceTree = SOURCE_ROOT; };
+ D79E5E480E28299D0046286C /* tif_write.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_write.c; sourceTree = SOURCE_ROOT; };
+ D79E5E490E28299D0046286C /* tif_tile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_tile.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4A0E28299D0046286C /* tif_read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_read.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4B0E28299D0046286C /* tif_ojpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_ojpeg.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4C0E28299D0046286C /* tif_print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_print.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4D0E28299D0046286C /* tif_error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_error.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4E0E28299D0046286C /* tif_zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_zip.c; sourceTree = SOURCE_ROOT; };
+ D79E5E4F0E28299D0046286C /* tif_luv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_luv.c; sourceTree = SOURCE_ROOT; };
+ D79E5E500E28299D0046286C /* tif_flush.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_flush.c; sourceTree = SOURCE_ROOT; };
+ D79E5E510E28299D0046286C /* tif_lzw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_lzw.c; sourceTree = SOURCE_ROOT; };
+ D79E5E520E28299D0046286C /* tif_jbig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_jbig.c; sourceTree = SOURCE_ROOT; };
+ D79E5E530E28299D0046286C /* tif_unix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_unix.c; sourceTree = SOURCE_ROOT; };
+ D79E5E540E28299D0046286C /* tiffvers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiffvers.h; sourceTree = SOURCE_ROOT; };
+ D79E5E550E28299D0046286C /* tif_dirinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_dirinfo.c; sourceTree = SOURCE_ROOT; };
+ D79E5E560E28299D0046286C /* tif_codec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_codec.c; sourceTree = SOURCE_ROOT; };
+ D79E5E570E28299D0046286C /* tif_color.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_color.c; sourceTree = SOURCE_ROOT; };
+ D79E5E580E28299D0046286C /* tif_next.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_next.c; sourceTree = SOURCE_ROOT; };
+ D79E5E590E28299D0046286C /* tif_open.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_open.c; sourceTree = SOURCE_ROOT; };
+ D79E5E5A0E28299D0046286C /* t4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = t4.h; sourceTree = SOURCE_ROOT; };
+ D79E5E5B0E28299D0046286C /* tif_jpeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_jpeg.c; sourceTree = SOURCE_ROOT; };
+ D79E5E5C0E28299D0046286C /* tiff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiff.h; sourceTree = SOURCE_ROOT; };
+ D79E5E5D0E28299D0046286C /* tif_config.vc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_config.vc.h; sourceTree = SOURCE_ROOT; };
+ D79E5E5E0E28299D0046286C /* tif_dir.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_dir.c; sourceTree = SOURCE_ROOT; };
+ D79E5E5F0E28299D0046286C /* tif_compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_compress.c; sourceTree = SOURCE_ROOT; };
+ D79E5E600E28299D0046286C /* tif_fax3sm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_fax3sm.c; sourceTree = SOURCE_ROOT; };
+ D79E5E610E28299D0046286C /* tif_fax3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_fax3.c; sourceTree = SOURCE_ROOT; };
+ D79E5E620E28299D0046286C /* tif_close.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_close.c; sourceTree = SOURCE_ROOT; };
+ D79E5E630E28299D0046286C /* tif_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_config.h; sourceTree = SOURCE_ROOT; };
+ D79E5E640E28299D0046286C /* tiffio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiffio.h; sourceTree = SOURCE_ROOT; };
+ D79E5E650E28299D0046286C /* tif_predict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_predict.h; sourceTree = SOURCE_ROOT; };
+ D79E5E660E28299D0046286C /* tif_thunder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_thunder.c; sourceTree = SOURCE_ROOT; };
+ D79E5E670E28299D0046286C /* tiffconf.wince.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiffconf.wince.h; sourceTree = SOURCE_ROOT; };
+ D79E5E680E28299D0046286C /* tiffiop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiffiop.h; sourceTree = SOURCE_ROOT; };
+ D79E5E6A0E28299D0046286C /* tif_getimage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_getimage.c; sourceTree = SOURCE_ROOT; };
+ D79E5E6B0E28299D0046286C /* tif_version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_version.c; sourceTree = SOURCE_ROOT; };
+ D79E5E6C0E28299D0046286C /* tif_dirread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_dirread.c; sourceTree = SOURCE_ROOT; };
+ D79E5E6D0E28299D0046286C /* tiffconf.vc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tiffconf.vc.h; sourceTree = SOURCE_ROOT; };
+ D79E5E6E0E28299D0046286C /* tif_config.wince.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_config.wince.h; sourceTree = SOURCE_ROOT; };
+ D79E5E6F0E28299D0046286C /* tif_dumpmode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_dumpmode.c; sourceTree = SOURCE_ROOT; };
+ D79E5E700E28299D0046286C /* tif_packbits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_packbits.c; sourceTree = SOURCE_ROOT; };
+ D79E5E710E28299D0046286C /* uvcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uvcode.h; sourceTree = SOURCE_ROOT; };
+ D79E5E720E28299D0046286C /* tif_aux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_aux.c; sourceTree = SOURCE_ROOT; };
+ D79E5E730E28299D0046286C /* tif_swab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_swab.c; sourceTree = SOURCE_ROOT; };
+ D79E5E740E28299D0046286C /* tif_predict.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_predict.c; sourceTree = SOURCE_ROOT; };
+ D79E5E750E28299D0046286C /* tif_strip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tif_strip.c; sourceTree = SOURCE_ROOT; };
+ D79E5E760E28299D0046286C /* tif_fax3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tif_fax3.h; sourceTree = SOURCE_ROOT; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D289987405E68DCB004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libtiff */ = {
+ isa = PBXGroup;
+ children = (
+ D722DB7A0E2823C700977662 /* MacConfigExternalDebug.xcconfig */,
+ D722DB7B0E2823C700977662 /* MacConfigExternalRelease.xcconfig */,
+ 08FB7795FE84155DC02AAC07 /* Source */,
+ C6A0FF2B0290797F04C91782 /* Documentation */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ );
+ name = libtiff;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* Source */ = {
+ isa = PBXGroup;
+ children = (
+ D79E5E430E28299D0046286C /* tif_extension.c */,
+ D79E5E440E28299D0046286C /* tif_pixarlog.c */,
+ D79E5E450E28299D0046286C /* tif_warning.c */,
+ D79E5E460E28299D0046286C /* tif_dir.h */,
+ D79E5E470E28299D0046286C /* tif_dirwrite.c */,
+ D79E5E480E28299D0046286C /* tif_write.c */,
+ D79E5E490E28299D0046286C /* tif_tile.c */,
+ D79E5E4A0E28299D0046286C /* tif_read.c */,
+ D79E5E4B0E28299D0046286C /* tif_ojpeg.c */,
+ D79E5E4C0E28299D0046286C /* tif_print.c */,
+ D79E5E4D0E28299D0046286C /* tif_error.c */,
+ D79E5E4E0E28299D0046286C /* tif_zip.c */,
+ D79E5E4F0E28299D0046286C /* tif_luv.c */,
+ D79E5E500E28299D0046286C /* tif_flush.c */,
+ D79E5E510E28299D0046286C /* tif_lzw.c */,
+ D79E5E520E28299D0046286C /* tif_jbig.c */,
+ D79E5E530E28299D0046286C /* tif_unix.c */,
+ D79E5E540E28299D0046286C /* tiffvers.h */,
+ D79E5E550E28299D0046286C /* tif_dirinfo.c */,
+ D79E5E560E28299D0046286C /* tif_codec.c */,
+ D79E5E570E28299D0046286C /* tif_color.c */,
+ D79E5E580E28299D0046286C /* tif_next.c */,
+ D79E5E590E28299D0046286C /* tif_open.c */,
+ D79E5E5A0E28299D0046286C /* t4.h */,
+ D79E5E5B0E28299D0046286C /* tif_jpeg.c */,
+ D79E5E5C0E28299D0046286C /* tiff.h */,
+ D79E5E5D0E28299D0046286C /* tif_config.vc.h */,
+ D79E5E5E0E28299D0046286C /* tif_dir.c */,
+ D79E5E5F0E28299D0046286C /* tif_compress.c */,
+ D79E5E600E28299D0046286C /* tif_fax3sm.c */,
+ D79E5E610E28299D0046286C /* tif_fax3.c */,
+ D79E5E620E28299D0046286C /* tif_close.c */,
+ D79E5E630E28299D0046286C /* tif_config.h */,
+ D79E5E640E28299D0046286C /* tiffio.h */,
+ D79E5E650E28299D0046286C /* tif_predict.h */,
+ D79E5E660E28299D0046286C /* tif_thunder.c */,
+ D79E5E670E28299D0046286C /* tiffconf.wince.h */,
+ D79E5E680E28299D0046286C /* tiffiop.h */,
+ D79E5E6A0E28299D0046286C /* tif_getimage.c */,
+ D79E5E6B0E28299D0046286C /* tif_version.c */,
+ D79E5E6C0E28299D0046286C /* tif_dirread.c */,
+ D79E5E6D0E28299D0046286C /* tiffconf.vc.h */,
+ D79E5E6E0E28299D0046286C /* tif_config.wince.h */,
+ D79E5E6F0E28299D0046286C /* tif_dumpmode.c */,
+ D79E5E700E28299D0046286C /* tif_packbits.c */,
+ D79E5E710E28299D0046286C /* uvcode.h */,
+ D79E5E720E28299D0046286C /* tif_aux.c */,
+ D79E5E730E28299D0046286C /* tif_swab.c */,
+ D79E5E740E28299D0046286C /* tif_predict.c */,
+ D79E5E750E28299D0046286C /* tif_strip.c */,
+ D79E5E760E28299D0046286C /* tif_fax3.h */,
+ );
+ name = Source;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC046055464E500DB518D /* libtiff.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ C6A0FF2B0290797F04C91782 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC043055464E500DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D79E5E7A0E28299D0046286C /* tif_dir.h in Headers */,
+ D79E5E880E28299D0046286C /* tiffvers.h in Headers */,
+ D79E5E8E0E28299D0046286C /* t4.h in Headers */,
+ D79E5E900E28299D0046286C /* tiff.h in Headers */,
+ D79E5E910E28299D0046286C /* tif_config.vc.h in Headers */,
+ D79E5E970E28299D0046286C /* tif_config.h in Headers */,
+ D79E5E980E28299D0046286C /* tiffio.h in Headers */,
+ D79E5E990E28299D0046286C /* tif_predict.h in Headers */,
+ D79E5E9B0E28299D0046286C /* tiffconf.wince.h in Headers */,
+ D79E5E9C0E28299D0046286C /* tiffiop.h in Headers */,
+ D79E5EA10E28299D0046286C /* tiffconf.vc.h in Headers */,
+ D79E5EA20E28299D0046286C /* tif_config.wince.h in Headers */,
+ D79E5EA50E28299D0046286C /* uvcode.h in Headers */,
+ D79E5EAA0E28299D0046286C /* tif_fax3.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ D2AAC045055464E500DB518D /* libtiff */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libtiff" */;
+ buildPhases = (
+ D2AAC043055464E500DB518D /* Headers */,
+ D2AAC044055464E500DB518D /* Sources */,
+ D289987405E68DCB004EDB86 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = libtiff;
+ productName = libtiff;
+ productReference = D2AAC046055464E500DB518D /* libtiff.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libtiff" */;
+ compatibilityVersion = "Xcode 3.1";
+ hasScannedForEncodings = 1;
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libtiff */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC045055464E500DB518D /* libtiff */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D2AAC044055464E500DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D79E5E770E28299D0046286C /* tif_extension.c in Sources */,
+ D79E5E780E28299D0046286C /* tif_pixarlog.c in Sources */,
+ D79E5E790E28299D0046286C /* tif_warning.c in Sources */,
+ D79E5E7B0E28299D0046286C /* tif_dirwrite.c in Sources */,
+ D79E5E7C0E28299D0046286C /* tif_write.c in Sources */,
+ D79E5E7D0E28299D0046286C /* tif_tile.c in Sources */,
+ D79E5E7E0E28299D0046286C /* tif_read.c in Sources */,
+ D79E5E7F0E28299D0046286C /* tif_ojpeg.c in Sources */,
+ D79E5E800E28299D0046286C /* tif_print.c in Sources */,
+ D79E5E810E28299D0046286C /* tif_error.c in Sources */,
+ D79E5E820E28299D0046286C /* tif_zip.c in Sources */,
+ D79E5E830E28299D0046286C /* tif_luv.c in Sources */,
+ D79E5E840E28299D0046286C /* tif_flush.c in Sources */,
+ D79E5E850E28299D0046286C /* tif_lzw.c in Sources */,
+ D79E5E860E28299D0046286C /* tif_jbig.c in Sources */,
+ D79E5E870E28299D0046286C /* tif_unix.c in Sources */,
+ D79E5E890E28299D0046286C /* tif_dirinfo.c in Sources */,
+ D79E5E8A0E28299D0046286C /* tif_codec.c in Sources */,
+ D79E5E8B0E28299D0046286C /* tif_color.c in Sources */,
+ D79E5E8C0E28299D0046286C /* tif_next.c in Sources */,
+ D79E5E8D0E28299D0046286C /* tif_open.c in Sources */,
+ D79E5E8F0E28299D0046286C /* tif_jpeg.c in Sources */,
+ D79E5E920E28299D0046286C /* tif_dir.c in Sources */,
+ D79E5E930E28299D0046286C /* tif_compress.c in Sources */,
+ D79E5E940E28299D0046286C /* tif_fax3sm.c in Sources */,
+ D79E5E950E28299D0046286C /* tif_fax3.c in Sources */,
+ D79E5E960E28299D0046286C /* tif_close.c in Sources */,
+ D79E5E9A0E28299D0046286C /* tif_thunder.c in Sources */,
+ D79E5E9E0E28299D0046286C /* tif_getimage.c in Sources */,
+ D79E5E9F0E28299D0046286C /* tif_version.c in Sources */,
+ D79E5EA00E28299D0046286C /* tif_dirread.c in Sources */,
+ D79E5EA30E28299D0046286C /* tif_dumpmode.c in Sources */,
+ D79E5EA40E28299D0046286C /* tif_packbits.c in Sources */,
+ D79E5EA60E28299D0046286C /* tif_aux.c in Sources */,
+ D79E5EA70E28299D0046286C /* tif_swab.c in Sources */,
+ D79E5EA80E28299D0046286C /* tif_predict.c in Sources */,
+ D79E5EA90E28299D0046286C /* tif_strip.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB91EC08733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tiff;
+ };
+ name = Debug;
+ };
+ 1DEB91ED08733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = tiff;
+ };
+ name = Release;
+ };
+ 1DEB91F008733DB70010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D722DB7A0E2823C700977662 /* MacConfigExternalDebug.xcconfig */;
+ buildSettings = {
+ };
+ name = Debug;
+ };
+ 1DEB91F108733DB70010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = D722DB7B0E2823C700977662 /* MacConfigExternalRelease.xcconfig */;
+ buildSettings = {
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libtiff" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91EC08733DB70010E9CD /* Debug */,
+ 1DEB91ED08733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libtiff" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB91F008733DB70010E9CD /* Debug */,
+ 1DEB91F108733DB70010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/Source/LibTIFF/makefile.vc b/Source/LibTIFF/makefile.vc
new file mode 100644
index 0000000..1234dc1
--- /dev/null
+++ b/Source/LibTIFF/makefile.vc
@@ -0,0 +1,102 @@
+# $Id: makefile.vc,v 1.27 2009/09/06 13:11:26 drolon Exp $
+#
+# Copyright (C) 2004, Andrey Kiselev <dron@ak4719.spb.edu>
+#
+# Permission to use, copy, modify, distribute, and sell this software and
+# its documentation for any purpose is hereby granted without fee, provided
+# that (i) the above copyright notices and this permission notice appear in
+# all copies of the software and related documentation, and (ii) the names of
+# Sam Leffler and Silicon Graphics may not be used in any advertising or
+# publicity relating to the software without the specific, prior written
+# permission of Sam Leffler and Silicon Graphics.
+#
+# THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+# WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+#
+# IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+# ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+# OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+# LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+# Makefile for MS Visual C and Watcom C compilers.
+#
+# To build:
+# C:\libtiff\libtiff> nmake /f makefile.vc all
+#
+
+!INCLUDE ..\nmake.opt
+
+INCL = -I. $(JPEG_INCLUDE) $(ZLIB_INCLUDE) $(JBIG_INCLUDE)
+
+!IFDEF USE_WIN_CRT_LIB
+OBJ_SYSDEP_MODULE = tif_unix.obj
+!ELSE
+OBJ_SYSDEP_MODULE = tif_win32.obj
+!ENDIF
+
+OBJ = \
+ tif_aux.obj \
+ tif_close.obj \
+ tif_codec.obj \
+ tif_color.obj \
+ tif_compress.obj \
+ tif_dir.obj \
+ tif_dirinfo.obj \
+ tif_dirread.obj \
+ tif_dirwrite.obj \
+ tif_dumpmode.obj \
+ tif_error.obj \
+ tif_extension.obj \
+ tif_fax3.obj \
+ tif_fax3sm.obj \
+ tif_getimage.obj \
+ tif_jbig.obj \
+ tif_jpeg.obj \
+ tif_ojpeg.obj \
+ tif_flush.obj \
+ tif_luv.obj \
+ tif_lzw.obj \
+ tif_next.obj \
+ tif_open.obj \
+ tif_packbits.obj \
+ tif_pixarlog.obj \
+ tif_predict.obj \
+ tif_print.obj \
+ tif_read.obj \
+ tif_stream.obj \
+ tif_swab.obj \
+ tif_strip.obj \
+ tif_thunder.obj \
+ tif_tile.obj \
+ tif_version.obj \
+ tif_warning.obj \
+ tif_write.obj \
+ tif_zip.obj \
+ tif_jbig.obj \
+ $(OBJ_SYSDEP_MODULE)
+
+all: libtiff.lib $(DLLNAME)
+
+tif_config.h: tif_config.vc.h
+ copy tif_config.vc.h tif_config.h
+
+tiffconf.h: tiffconf.vc.h
+ copy tiffconf.vc.h tiffconf.h
+
+libtiff.lib: tif_config.h tiffconf.h $(OBJ)
+ $(AR) /out:libtiff.lib $(OBJ) $(LIBS)
+
+$(DLLNAME): tif_config.h tiffconf.h libtiff.def $(OBJ)
+ $(LD) /debug /dll /def:libtiff.def /out:$(DLLNAME) \
+ /implib:libtiff_i.lib $(OBJ) $(LIBS)
+
+clean:
+ -del tif_config.h tiffconf.h
+ -del *.obj
+ -del *.lib
+ -del *.dll
+ -del *.exe
+ -del *.pdb
diff --git a/Source/LibTIFF/mkg3states.c b/Source/LibTIFF/mkg3states.c
new file mode 100644
index 0000000..dd0a044
--- /dev/null
+++ b/Source/LibTIFF/mkg3states.c
@@ -0,0 +1,444 @@
+/* "$Id: mkg3states.c,v 1.27 2009/09/06 13:11:26 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/* Initialise fax decoder tables
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ * Copyright (C) 1990, 1995 Frank D. Cringle.
+ */
+#include "tif_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "tif_fax3.h"
+
+#ifndef HAVE_GETOPT
+extern int getopt(int, char**, char*);
+#endif
+
+#define streq(a,b) (strcmp(a,b) == 0)
+
+/* NB: can't use names in tif_fax3.h 'cuz they are declared const */
+TIFFFaxTabEnt MainTable[128];
+TIFFFaxTabEnt WhiteTable[4096];
+TIFFFaxTabEnt BlackTable[8192];
+
+struct proto {
+ uint16 code; /* right justified, lsb-first, zero filled */
+ uint16 val; /* (pixel count)<<4 + code width */
+};
+
+static struct proto Pass[] = {
+{ 0x0008, 4 },
+{ 0, 0 }
+};
+
+static struct proto Horiz[] = {
+{ 0x0004, 3 },
+{ 0, 0 }
+};
+
+static struct proto V0[] = {
+{ 0x0001, 1 },
+{ 0, 0 }
+};
+
+static struct proto VR[] = {
+{ 0x0006, (1<<4)+3 },
+{ 0x0030, (2<<4)+6 },
+{ 0x0060, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto VL[] = {
+{ 0x0002, (1<<4)+3 },
+{ 0x0010, (2<<4)+6 },
+{ 0x0020, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto Ext[] = {
+{ 0x0040, 7 },
+{ 0, 0 }
+};
+
+static struct proto EOLV[] = {
+{ 0x0000, 7 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpW[] = {
+{ 0x001b, 1029 },
+{ 0x0009, 2053 },
+{ 0x003a, 3078 },
+{ 0x0076, 4103 },
+{ 0x006c, 5128 },
+{ 0x00ec, 6152 },
+{ 0x0026, 7176 },
+{ 0x00a6, 8200 },
+{ 0x0016, 9224 },
+{ 0x00e6, 10248 },
+{ 0x0066, 11273 },
+{ 0x0166, 12297 },
+{ 0x0096, 13321 },
+{ 0x0196, 14345 },
+{ 0x0056, 15369 },
+{ 0x0156, 16393 },
+{ 0x00d6, 17417 },
+{ 0x01d6, 18441 },
+{ 0x0036, 19465 },
+{ 0x0136, 20489 },
+{ 0x00b6, 21513 },
+{ 0x01b6, 22537 },
+{ 0x0032, 23561 },
+{ 0x0132, 24585 },
+{ 0x00b2, 25609 },
+{ 0x0006, 26630 },
+{ 0x01b2, 27657 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpB[] = {
+{ 0x03c0, 1034 },
+{ 0x0130, 2060 },
+{ 0x0930, 3084 },
+{ 0x0da0, 4108 },
+{ 0x0cc0, 5132 },
+{ 0x02c0, 6156 },
+{ 0x0ac0, 7180 },
+{ 0x06c0, 8205 },
+{ 0x16c0, 9229 },
+{ 0x0a40, 10253 },
+{ 0x1a40, 11277 },
+{ 0x0640, 12301 },
+{ 0x1640, 13325 },
+{ 0x09c0, 14349 },
+{ 0x19c0, 15373 },
+{ 0x05c0, 16397 },
+{ 0x15c0, 17421 },
+{ 0x0dc0, 18445 },
+{ 0x1dc0, 19469 },
+{ 0x0940, 20493 },
+{ 0x1940, 21517 },
+{ 0x0540, 22541 },
+{ 0x1540, 23565 },
+{ 0x0b40, 24589 },
+{ 0x1b40, 25613 },
+{ 0x04c0, 26637 },
+{ 0x14c0, 27661 },
+{ 0, 0 }
+};
+
+static struct proto MakeUp[] = {
+{ 0x0080, 28683 },
+{ 0x0180, 29707 },
+{ 0x0580, 30731 },
+{ 0x0480, 31756 },
+{ 0x0c80, 32780 },
+{ 0x0280, 33804 },
+{ 0x0a80, 34828 },
+{ 0x0680, 35852 },
+{ 0x0e80, 36876 },
+{ 0x0380, 37900 },
+{ 0x0b80, 38924 },
+{ 0x0780, 39948 },
+{ 0x0f80, 40972 },
+{ 0, 0 }
+};
+
+static struct proto TermW[] = {
+{ 0x00ac, 8 },
+{ 0x0038, 22 },
+{ 0x000e, 36 },
+{ 0x0001, 52 },
+{ 0x000d, 68 },
+{ 0x0003, 84 },
+{ 0x0007, 100 },
+{ 0x000f, 116 },
+{ 0x0019, 133 },
+{ 0x0005, 149 },
+{ 0x001c, 165 },
+{ 0x0002, 181 },
+{ 0x0004, 198 },
+{ 0x0030, 214 },
+{ 0x000b, 230 },
+{ 0x002b, 246 },
+{ 0x0015, 262 },
+{ 0x0035, 278 },
+{ 0x0072, 295 },
+{ 0x0018, 311 },
+{ 0x0008, 327 },
+{ 0x0074, 343 },
+{ 0x0060, 359 },
+{ 0x0010, 375 },
+{ 0x000a, 391 },
+{ 0x006a, 407 },
+{ 0x0064, 423 },
+{ 0x0012, 439 },
+{ 0x000c, 455 },
+{ 0x0040, 472 },
+{ 0x00c0, 488 },
+{ 0x0058, 504 },
+{ 0x00d8, 520 },
+{ 0x0048, 536 },
+{ 0x00c8, 552 },
+{ 0x0028, 568 },
+{ 0x00a8, 584 },
+{ 0x0068, 600 },
+{ 0x00e8, 616 },
+{ 0x0014, 632 },
+{ 0x0094, 648 },
+{ 0x0054, 664 },
+{ 0x00d4, 680 },
+{ 0x0034, 696 },
+{ 0x00b4, 712 },
+{ 0x0020, 728 },
+{ 0x00a0, 744 },
+{ 0x0050, 760 },
+{ 0x00d0, 776 },
+{ 0x004a, 792 },
+{ 0x00ca, 808 },
+{ 0x002a, 824 },
+{ 0x00aa, 840 },
+{ 0x0024, 856 },
+{ 0x00a4, 872 },
+{ 0x001a, 888 },
+{ 0x009a, 904 },
+{ 0x005a, 920 },
+{ 0x00da, 936 },
+{ 0x0052, 952 },
+{ 0x00d2, 968 },
+{ 0x004c, 984 },
+{ 0x00cc, 1000 },
+{ 0x002c, 1016 },
+{ 0, 0 }
+};
+
+static struct proto TermB[] = {
+{ 0x03b0, 10 },
+{ 0x0002, 19 },
+{ 0x0003, 34 },
+{ 0x0001, 50 },
+{ 0x0006, 67 },
+{ 0x000c, 84 },
+{ 0x0004, 100 },
+{ 0x0018, 117 },
+{ 0x0028, 134 },
+{ 0x0008, 150 },
+{ 0x0010, 167 },
+{ 0x0050, 183 },
+{ 0x0070, 199 },
+{ 0x0020, 216 },
+{ 0x00e0, 232 },
+{ 0x0030, 249 },
+{ 0x03a0, 266 },
+{ 0x0060, 282 },
+{ 0x0040, 298 },
+{ 0x0730, 315 },
+{ 0x00b0, 331 },
+{ 0x01b0, 347 },
+{ 0x0760, 363 },
+{ 0x00a0, 379 },
+{ 0x0740, 395 },
+{ 0x00c0, 411 },
+{ 0x0530, 428 },
+{ 0x0d30, 444 },
+{ 0x0330, 460 },
+{ 0x0b30, 476 },
+{ 0x0160, 492 },
+{ 0x0960, 508 },
+{ 0x0560, 524 },
+{ 0x0d60, 540 },
+{ 0x04b0, 556 },
+{ 0x0cb0, 572 },
+{ 0x02b0, 588 },
+{ 0x0ab0, 604 },
+{ 0x06b0, 620 },
+{ 0x0eb0, 636 },
+{ 0x0360, 652 },
+{ 0x0b60, 668 },
+{ 0x05b0, 684 },
+{ 0x0db0, 700 },
+{ 0x02a0, 716 },
+{ 0x0aa0, 732 },
+{ 0x06a0, 748 },
+{ 0x0ea0, 764 },
+{ 0x0260, 780 },
+{ 0x0a60, 796 },
+{ 0x04a0, 812 },
+{ 0x0ca0, 828 },
+{ 0x0240, 844 },
+{ 0x0ec0, 860 },
+{ 0x01c0, 876 },
+{ 0x0e40, 892 },
+{ 0x0140, 908 },
+{ 0x01a0, 924 },
+{ 0x09a0, 940 },
+{ 0x0d40, 956 },
+{ 0x0340, 972 },
+{ 0x05a0, 988 },
+{ 0x0660, 1004 },
+{ 0x0e60, 1020 },
+{ 0, 0 }
+};
+
+static struct proto EOLH[] = {
+{ 0x0000, 11 },
+{ 0, 0 }
+};
+
+static void
+FillTable(TIFFFaxTabEnt *T, int Size, struct proto *P, int State)
+{
+ int limit = 1 << Size;
+
+ while (P->val) {
+ int width = P->val & 15;
+ int param = P->val >> 4;
+ int incr = 1 << width;
+ int code;
+ for (code = P->code; code < limit; code += incr) {
+ TIFFFaxTabEnt *E = T+code;
+ E->State = State;
+ E->Width = width;
+ E->Param = param;
+ }
+ P++;
+ }
+}
+
+static char* storage_class = "";
+static char* const_class = "";
+static int packoutput = 1;
+static char* prebrace = "";
+static char* postbrace = "";
+
+void
+WriteTable(FILE* fd, const TIFFFaxTabEnt* T, int Size, const char* name)
+{
+ int i;
+ char* sep;
+
+ fprintf(fd, "%s %s TIFFFaxTabEnt %s[%d] = {",
+ storage_class, const_class, name, Size);
+ if (packoutput) {
+ sep = "\n";
+ for (i = 0; i < Size; i++) {
+ fprintf(fd, "%s%s%d,%d,%d%s",
+ sep, prebrace, T->State, T->Width, (int) T->Param, postbrace);
+ if (((i+1) % 10) == 0)
+ sep = ",\n";
+ else
+ sep = ",";
+ T++;
+ }
+ } else {
+ sep = "\n ";
+ for (i = 0; i < Size; i++) {
+ fprintf(fd, "%s%s%3d,%3d,%4d%s",
+ sep, prebrace, T->State, T->Width, (int) T->Param, postbrace);
+ if (((i+1) % 6) == 0)
+ sep = ",\n ";
+ else
+ sep = ",";
+ T++;
+ }
+ }
+ fprintf(fd, "\n};\n");
+}
+
+/* initialise the huffman code tables */
+int
+main(int argc, char* argv[])
+{
+ FILE* fd;
+ char* outputfile;
+ int c;
+ extern int optind;
+ extern char* optarg;
+
+ while ((c = getopt(argc, argv, "c:s:bp")) != -1)
+ switch (c) {
+ case 'c':
+ const_class = optarg;
+ break;
+ case 's':
+ storage_class = optarg;
+ break;
+ case 'p':
+ packoutput = 0;
+ break;
+ case 'b':
+ prebrace = "{";
+ postbrace = "}";
+ break;
+ case '?':
+ fprintf(stderr,
+ "usage: %s [-c const] [-s storage] [-p] [-b] file\n",
+ argv[0]);
+ return (-1);
+ }
+ outputfile = optind < argc ? argv[optind] : "g3states.h";
+ fd = fopen(outputfile, "w");
+ if (fd == NULL) {
+ fprintf(stderr, "%s: %s: Cannot create output file.\n",
+ argv[0], outputfile);
+ return (-2);
+ }
+ FillTable(MainTable, 7, Pass, S_Pass);
+ FillTable(MainTable, 7, Horiz, S_Horiz);
+ FillTable(MainTable, 7, V0, S_V0);
+ FillTable(MainTable, 7, VR, S_VR);
+ FillTable(MainTable, 7, VL, S_VL);
+ FillTable(MainTable, 7, Ext, S_Ext);
+ FillTable(MainTable, 7, EOLV, S_EOL);
+ FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW);
+ FillTable(WhiteTable, 12, MakeUp, S_MakeUp);
+ FillTable(WhiteTable, 12, TermW, S_TermW);
+ FillTable(WhiteTable, 12, EOLH, S_EOL);
+ FillTable(BlackTable, 13, MakeUpB, S_MakeUpB);
+ FillTable(BlackTable, 13, MakeUp, S_MakeUp);
+ FillTable(BlackTable, 13, TermB, S_TermB);
+ FillTable(BlackTable, 13, EOLH, S_EOL);
+
+ fprintf(fd, "/* WARNING, this file was automatically generated by the\n");
+ fprintf(fd, " mkg3states program */\n");
+ fprintf(fd, "#include \"tiff.h\"\n");
+ fprintf(fd, "#include \"tif_fax3.h\"\n");
+ WriteTable(fd, MainTable, 128, "TIFFFaxMainTable");
+ WriteTable(fd, WhiteTable, 4096, "TIFFFaxWhiteTable");
+ WriteTable(fd, BlackTable, 8192, "TIFFFaxBlackTable");
+ fclose(fd);
+ return (0);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/mkspans.c b/Source/LibTIFF/mkspans.c
new file mode 100644
index 0000000..6eda6c4
--- /dev/null
+++ b/Source/LibTIFF/mkspans.c
@@ -0,0 +1,75 @@
+/* $Id: mkspans.c,v 1.13 2009/07/14 21:10:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Hack program to construct tables used to find
+ * runs of zeros and ones in Group 3 Fax encoding.
+ */
+
+dumparray(name, runs)
+ char *name;
+ unsigned char runs[256];
+{
+ int i;
+ char *sep;
+ printf("static unsigned char %s[256] = {\n", name);
+ sep = " ";
+ for (i = 0; i < 256; i++) {
+ printf("%s%d", sep, runs[i]);
+ if (((i + 1) % 16) == 0) {
+ printf(", /* 0x%02x - 0x%02x */\n", i-15, i);
+ sep = " ";
+ } else
+ sep = ", ";
+ }
+ printf("\n};\n");
+}
+
+main()
+{
+ unsigned char runs[2][256];
+
+ memset(runs[0], 0, 256*sizeof (char));
+ memset(runs[1], 0, 256*sizeof (char));
+ { register int run, runlen, i;
+ runlen = 1;
+ for (run = 0x80; run != 0xff; run = (run>>1)|0x80) {
+ for (i = run-1; i >= 0; i--) {
+ runs[1][run|i] = runlen;
+ runs[0][(~(run|i)) & 0xff] = runlen;
+ }
+ runlen++;
+ }
+ runs[1][0xff] = runs[0][0] = 8;
+ }
+ dumparray("bruns", runs[0]);
+ dumparray("wruns", runs[1]);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/t4.h b/Source/LibTIFF/t4.h
new file mode 100644
index 0000000..88ee23d
--- /dev/null
+++ b/Source/LibTIFF/t4.h
@@ -0,0 +1,285 @@
+/* $Id: t4.h,v 1.27 2009/09/06 13:11:26 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _T4_
+#define _T4_
+/*
+ * CCITT T.4 1D Huffman runlength codes and
+ * related definitions. Given the small sizes
+ * of these tables it does not seem
+ * worthwhile to make code & length 8 bits.
+ */
+typedef struct tableentry {
+ unsigned short length; /* bit length of g3 code */
+ unsigned short code; /* g3 code */
+ short runlen; /* run length in bits */
+} tableentry;
+
+#define EOL 0x001 /* EOL code value - 0000 0000 0000 1 */
+
+/* status values returned instead of a run length */
+#define G3CODE_EOL -1 /* NB: ACT_EOL - ACT_WRUNT */
+#define G3CODE_INVALID -2 /* NB: ACT_INVALID - ACT_WRUNT */
+#define G3CODE_EOF -3 /* end of input data */
+#define G3CODE_INCOMP -4 /* incomplete run code */
+
+/*
+ * Note that these tables are ordered such that the
+ * index into the table is known to be either the
+ * run length, or (run length / 64) + a fixed offset.
+ *
+ * NB: The G3CODE_INVALID entries are only used
+ * during state generation (see mkg3states.c).
+ */
+#ifdef G3CODES
+const tableentry TIFFFaxWhiteCodes[] = {
+ { 8, 0x35, 0 }, /* 0011 0101 */
+ { 6, 0x7, 1 }, /* 0001 11 */
+ { 4, 0x7, 2 }, /* 0111 */
+ { 4, 0x8, 3 }, /* 1000 */
+ { 4, 0xB, 4 }, /* 1011 */
+ { 4, 0xC, 5 }, /* 1100 */
+ { 4, 0xE, 6 }, /* 1110 */
+ { 4, 0xF, 7 }, /* 1111 */
+ { 5, 0x13, 8 }, /* 1001 1 */
+ { 5, 0x14, 9 }, /* 1010 0 */
+ { 5, 0x7, 10 }, /* 0011 1 */
+ { 5, 0x8, 11 }, /* 0100 0 */
+ { 6, 0x8, 12 }, /* 0010 00 */
+ { 6, 0x3, 13 }, /* 0000 11 */
+ { 6, 0x34, 14 }, /* 1101 00 */
+ { 6, 0x35, 15 }, /* 1101 01 */
+ { 6, 0x2A, 16 }, /* 1010 10 */
+ { 6, 0x2B, 17 }, /* 1010 11 */
+ { 7, 0x27, 18 }, /* 0100 111 */
+ { 7, 0xC, 19 }, /* 0001 100 */
+ { 7, 0x8, 20 }, /* 0001 000 */
+ { 7, 0x17, 21 }, /* 0010 111 */
+ { 7, 0x3, 22 }, /* 0000 011 */
+ { 7, 0x4, 23 }, /* 0000 100 */
+ { 7, 0x28, 24 }, /* 0101 000 */
+ { 7, 0x2B, 25 }, /* 0101 011 */
+ { 7, 0x13, 26 }, /* 0010 011 */
+ { 7, 0x24, 27 }, /* 0100 100 */
+ { 7, 0x18, 28 }, /* 0011 000 */
+ { 8, 0x2, 29 }, /* 0000 0010 */
+ { 8, 0x3, 30 }, /* 0000 0011 */
+ { 8, 0x1A, 31 }, /* 0001 1010 */
+ { 8, 0x1B, 32 }, /* 0001 1011 */
+ { 8, 0x12, 33 }, /* 0001 0010 */
+ { 8, 0x13, 34 }, /* 0001 0011 */
+ { 8, 0x14, 35 }, /* 0001 0100 */
+ { 8, 0x15, 36 }, /* 0001 0101 */
+ { 8, 0x16, 37 }, /* 0001 0110 */
+ { 8, 0x17, 38 }, /* 0001 0111 */
+ { 8, 0x28, 39 }, /* 0010 1000 */
+ { 8, 0x29, 40 }, /* 0010 1001 */
+ { 8, 0x2A, 41 }, /* 0010 1010 */
+ { 8, 0x2B, 42 }, /* 0010 1011 */
+ { 8, 0x2C, 43 }, /* 0010 1100 */
+ { 8, 0x2D, 44 }, /* 0010 1101 */
+ { 8, 0x4, 45 }, /* 0000 0100 */
+ { 8, 0x5, 46 }, /* 0000 0101 */
+ { 8, 0xA, 47 }, /* 0000 1010 */
+ { 8, 0xB, 48 }, /* 0000 1011 */
+ { 8, 0x52, 49 }, /* 0101 0010 */
+ { 8, 0x53, 50 }, /* 0101 0011 */
+ { 8, 0x54, 51 }, /* 0101 0100 */
+ { 8, 0x55, 52 }, /* 0101 0101 */
+ { 8, 0x24, 53 }, /* 0010 0100 */
+ { 8, 0x25, 54 }, /* 0010 0101 */
+ { 8, 0x58, 55 }, /* 0101 1000 */
+ { 8, 0x59, 56 }, /* 0101 1001 */
+ { 8, 0x5A, 57 }, /* 0101 1010 */
+ { 8, 0x5B, 58 }, /* 0101 1011 */
+ { 8, 0x4A, 59 }, /* 0100 1010 */
+ { 8, 0x4B, 60 }, /* 0100 1011 */
+ { 8, 0x32, 61 }, /* 0011 0010 */
+ { 8, 0x33, 62 }, /* 0011 0011 */
+ { 8, 0x34, 63 }, /* 0011 0100 */
+ { 5, 0x1B, 64 }, /* 1101 1 */
+ { 5, 0x12, 128 }, /* 1001 0 */
+ { 6, 0x17, 192 }, /* 0101 11 */
+ { 7, 0x37, 256 }, /* 0110 111 */
+ { 8, 0x36, 320 }, /* 0011 0110 */
+ { 8, 0x37, 384 }, /* 0011 0111 */
+ { 8, 0x64, 448 }, /* 0110 0100 */
+ { 8, 0x65, 512 }, /* 0110 0101 */
+ { 8, 0x68, 576 }, /* 0110 1000 */
+ { 8, 0x67, 640 }, /* 0110 0111 */
+ { 9, 0xCC, 704 }, /* 0110 0110 0 */
+ { 9, 0xCD, 768 }, /* 0110 0110 1 */
+ { 9, 0xD2, 832 }, /* 0110 1001 0 */
+ { 9, 0xD3, 896 }, /* 0110 1001 1 */
+ { 9, 0xD4, 960 }, /* 0110 1010 0 */
+ { 9, 0xD5, 1024 }, /* 0110 1010 1 */
+ { 9, 0xD6, 1088 }, /* 0110 1011 0 */
+ { 9, 0xD7, 1152 }, /* 0110 1011 1 */
+ { 9, 0xD8, 1216 }, /* 0110 1100 0 */
+ { 9, 0xD9, 1280 }, /* 0110 1100 1 */
+ { 9, 0xDA, 1344 }, /* 0110 1101 0 */
+ { 9, 0xDB, 1408 }, /* 0110 1101 1 */
+ { 9, 0x98, 1472 }, /* 0100 1100 0 */
+ { 9, 0x99, 1536 }, /* 0100 1100 1 */
+ { 9, 0x9A, 1600 }, /* 0100 1101 0 */
+ { 6, 0x18, 1664 }, /* 0110 00 */
+ { 9, 0x9B, 1728 }, /* 0100 1101 1 */
+ { 11, 0x8, 1792 }, /* 0000 0001 000 */
+ { 11, 0xC, 1856 }, /* 0000 0001 100 */
+ { 11, 0xD, 1920 }, /* 0000 0001 101 */
+ { 12, 0x12, 1984 }, /* 0000 0001 0010 */
+ { 12, 0x13, 2048 }, /* 0000 0001 0011 */
+ { 12, 0x14, 2112 }, /* 0000 0001 0100 */
+ { 12, 0x15, 2176 }, /* 0000 0001 0101 */
+ { 12, 0x16, 2240 }, /* 0000 0001 0110 */
+ { 12, 0x17, 2304 }, /* 0000 0001 0111 */
+ { 12, 0x1C, 2368 }, /* 0000 0001 1100 */
+ { 12, 0x1D, 2432 }, /* 0000 0001 1101 */
+ { 12, 0x1E, 2496 }, /* 0000 0001 1110 */
+ { 12, 0x1F, 2560 }, /* 0000 0001 1111 */
+ { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
+ { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
+ { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
+ { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
+ { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */
+};
+
+const tableentry TIFFFaxBlackCodes[] = {
+ { 10, 0x37, 0 }, /* 0000 1101 11 */
+ { 3, 0x2, 1 }, /* 010 */
+ { 2, 0x3, 2 }, /* 11 */
+ { 2, 0x2, 3 }, /* 10 */
+ { 3, 0x3, 4 }, /* 011 */
+ { 4, 0x3, 5 }, /* 0011 */
+ { 4, 0x2, 6 }, /* 0010 */
+ { 5, 0x3, 7 }, /* 0001 1 */
+ { 6, 0x5, 8 }, /* 0001 01 */
+ { 6, 0x4, 9 }, /* 0001 00 */
+ { 7, 0x4, 10 }, /* 0000 100 */
+ { 7, 0x5, 11 }, /* 0000 101 */
+ { 7, 0x7, 12 }, /* 0000 111 */
+ { 8, 0x4, 13 }, /* 0000 0100 */
+ { 8, 0x7, 14 }, /* 0000 0111 */
+ { 9, 0x18, 15 }, /* 0000 1100 0 */
+ { 10, 0x17, 16 }, /* 0000 0101 11 */
+ { 10, 0x18, 17 }, /* 0000 0110 00 */
+ { 10, 0x8, 18 }, /* 0000 0010 00 */
+ { 11, 0x67, 19 }, /* 0000 1100 111 */
+ { 11, 0x68, 20 }, /* 0000 1101 000 */
+ { 11, 0x6C, 21 }, /* 0000 1101 100 */
+ { 11, 0x37, 22 }, /* 0000 0110 111 */
+ { 11, 0x28, 23 }, /* 0000 0101 000 */
+ { 11, 0x17, 24 }, /* 0000 0010 111 */
+ { 11, 0x18, 25 }, /* 0000 0011 000 */
+ { 12, 0xCA, 26 }, /* 0000 1100 1010 */
+ { 12, 0xCB, 27 }, /* 0000 1100 1011 */
+ { 12, 0xCC, 28 }, /* 0000 1100 1100 */
+ { 12, 0xCD, 29 }, /* 0000 1100 1101 */
+ { 12, 0x68, 30 }, /* 0000 0110 1000 */
+ { 12, 0x69, 31 }, /* 0000 0110 1001 */
+ { 12, 0x6A, 32 }, /* 0000 0110 1010 */
+ { 12, 0x6B, 33 }, /* 0000 0110 1011 */
+ { 12, 0xD2, 34 }, /* 0000 1101 0010 */
+ { 12, 0xD3, 35 }, /* 0000 1101 0011 */
+ { 12, 0xD4, 36 }, /* 0000 1101 0100 */
+ { 12, 0xD5, 37 }, /* 0000 1101 0101 */
+ { 12, 0xD6, 38 }, /* 0000 1101 0110 */
+ { 12, 0xD7, 39 }, /* 0000 1101 0111 */
+ { 12, 0x6C, 40 }, /* 0000 0110 1100 */
+ { 12, 0x6D, 41 }, /* 0000 0110 1101 */
+ { 12, 0xDA, 42 }, /* 0000 1101 1010 */
+ { 12, 0xDB, 43 }, /* 0000 1101 1011 */
+ { 12, 0x54, 44 }, /* 0000 0101 0100 */
+ { 12, 0x55, 45 }, /* 0000 0101 0101 */
+ { 12, 0x56, 46 }, /* 0000 0101 0110 */
+ { 12, 0x57, 47 }, /* 0000 0101 0111 */
+ { 12, 0x64, 48 }, /* 0000 0110 0100 */
+ { 12, 0x65, 49 }, /* 0000 0110 0101 */
+ { 12, 0x52, 50 }, /* 0000 0101 0010 */
+ { 12, 0x53, 51 }, /* 0000 0101 0011 */
+ { 12, 0x24, 52 }, /* 0000 0010 0100 */
+ { 12, 0x37, 53 }, /* 0000 0011 0111 */
+ { 12, 0x38, 54 }, /* 0000 0011 1000 */
+ { 12, 0x27, 55 }, /* 0000 0010 0111 */
+ { 12, 0x28, 56 }, /* 0000 0010 1000 */
+ { 12, 0x58, 57 }, /* 0000 0101 1000 */
+ { 12, 0x59, 58 }, /* 0000 0101 1001 */
+ { 12, 0x2B, 59 }, /* 0000 0010 1011 */
+ { 12, 0x2C, 60 }, /* 0000 0010 1100 */
+ { 12, 0x5A, 61 }, /* 0000 0101 1010 */
+ { 12, 0x66, 62 }, /* 0000 0110 0110 */
+ { 12, 0x67, 63 }, /* 0000 0110 0111 */
+ { 10, 0xF, 64 }, /* 0000 0011 11 */
+ { 12, 0xC8, 128 }, /* 0000 1100 1000 */
+ { 12, 0xC9, 192 }, /* 0000 1100 1001 */
+ { 12, 0x5B, 256 }, /* 0000 0101 1011 */
+ { 12, 0x33, 320 }, /* 0000 0011 0011 */
+ { 12, 0x34, 384 }, /* 0000 0011 0100 */
+ { 12, 0x35, 448 }, /* 0000 0011 0101 */
+ { 13, 0x6C, 512 }, /* 0000 0011 0110 0 */
+ { 13, 0x6D, 576 }, /* 0000 0011 0110 1 */
+ { 13, 0x4A, 640 }, /* 0000 0010 0101 0 */
+ { 13, 0x4B, 704 }, /* 0000 0010 0101 1 */
+ { 13, 0x4C, 768 }, /* 0000 0010 0110 0 */
+ { 13, 0x4D, 832 }, /* 0000 0010 0110 1 */
+ { 13, 0x72, 896 }, /* 0000 0011 1001 0 */
+ { 13, 0x73, 960 }, /* 0000 0011 1001 1 */
+ { 13, 0x74, 1024 }, /* 0000 0011 1010 0 */
+ { 13, 0x75, 1088 }, /* 0000 0011 1010 1 */
+ { 13, 0x76, 1152 }, /* 0000 0011 1011 0 */
+ { 13, 0x77, 1216 }, /* 0000 0011 1011 1 */
+ { 13, 0x52, 1280 }, /* 0000 0010 1001 0 */
+ { 13, 0x53, 1344 }, /* 0000 0010 1001 1 */
+ { 13, 0x54, 1408 }, /* 0000 0010 1010 0 */
+ { 13, 0x55, 1472 }, /* 0000 0010 1010 1 */
+ { 13, 0x5A, 1536 }, /* 0000 0010 1101 0 */
+ { 13, 0x5B, 1600 }, /* 0000 0010 1101 1 */
+ { 13, 0x64, 1664 }, /* 0000 0011 0010 0 */
+ { 13, 0x65, 1728 }, /* 0000 0011 0010 1 */
+ { 11, 0x8, 1792 }, /* 0000 0001 000 */
+ { 11, 0xC, 1856 }, /* 0000 0001 100 */
+ { 11, 0xD, 1920 }, /* 0000 0001 101 */
+ { 12, 0x12, 1984 }, /* 0000 0001 0010 */
+ { 12, 0x13, 2048 }, /* 0000 0001 0011 */
+ { 12, 0x14, 2112 }, /* 0000 0001 0100 */
+ { 12, 0x15, 2176 }, /* 0000 0001 0101 */
+ { 12, 0x16, 2240 }, /* 0000 0001 0110 */
+ { 12, 0x17, 2304 }, /* 0000 0001 0111 */
+ { 12, 0x1C, 2368 }, /* 0000 0001 1100 */
+ { 12, 0x1D, 2432 }, /* 0000 0001 1101 */
+ { 12, 0x1E, 2496 }, /* 0000 0001 1110 */
+ { 12, 0x1F, 2560 }, /* 0000 0001 1111 */
+ { 12, 0x1, G3CODE_EOL }, /* 0000 0000 0001 */
+ { 9, 0x1, G3CODE_INVALID }, /* 0000 0000 1 */
+ { 10, 0x1, G3CODE_INVALID }, /* 0000 0000 01 */
+ { 11, 0x1, G3CODE_INVALID }, /* 0000 0000 001 */
+ { 12, 0x0, G3CODE_INVALID }, /* 0000 0000 0000 */
+};
+#else
+extern const tableentry TIFFFaxWhiteCodes[];
+extern const tableentry TIFFFaxBlackCodes[];
+#endif
+#endif /* _T4_ */
diff --git a/Source/LibTIFF/tif_acorn.c b/Source/LibTIFF/tif_acorn.c
new file mode 100644
index 0000000..8257c19
--- /dev/null
+++ b/Source/LibTIFF/tif_acorn.c
@@ -0,0 +1,519 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_acorn.c,v 1.27 2009/09/06 13:11:26 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library RISC OS specific Routines.
+ * Developed out of the Unix version.
+ * Peter Greenham, May 1995
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+Low-level file handling
+~~~~~~~~~~~~~~~~~~~~~~~
+The functions in osfcn.h are unavailable when compiling under C, as it's a
+C++ header. Therefore they have been implemented here.
+
+Now, why have I done it this way?
+
+The definitive API library for RISC OS is Jonathan Coxhead's OSLib, which
+uses heavily optimised ARM assembler or even plain inline SWI calls for
+maximum performance and minimum runtime size. However, I don't want to make
+LIBTIFF need that to survive. Therefore I have also emulated the functions
+using macros to _swi() and _swix() defined in the swis.h header, and
+borrowing types from kernel.h, which is less efficient but doesn't need any
+third-party libraries.
+ */
+
+#ifdef INCLUDE_OSLIB
+
+#include "osfile.h"
+#include "osgbpb.h"
+#include "osargs.h"
+#include "osfind.h"
+
+#else
+
+/* OSLIB EMULATION STARTS */
+
+#include "kernel.h"
+#include "swis.h"
+
+/* From oslib:types.h */
+typedef unsigned int bits;
+typedef unsigned char byte;
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef SKIP
+#define SKIP 0
+#endif
+
+/* From oslib:os.h */
+typedef _kernel_oserror os_error;
+typedef byte os_f;
+
+/* From oslib:osfile.h */
+#undef OS_File
+#define OS_File 0x8
+
+/* From oslib:osgbpb.h */
+#undef OS_GBPB
+#define OS_GBPB 0xC
+#undef OSGBPB_Write
+#define OSGBPB_Write 0x2
+#undef OSGBPB_Read
+#define OSGBPB_Read 0x4
+
+extern os_error *xosgbpb_write (os_f file,
+ byte *data,
+ int size,
+ int *unwritten);
+extern int osgbpb_write (os_f file,
+ byte *data,
+ int size);
+
+#define xosgbpb_write(file, data, size, unwritten) \
+ (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_IN(4)|_OUT(3), \
+ OSGBPB_WriteAt, \
+ file, \
+ data, \
+ size, \
+ unwritten)
+
+#define osgbpb_write(file, data, size) \
+ _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
+ OSGBPB_Write, \
+ file, \
+ data, \
+ size)
+
+extern os_error *xosgbpb_read (os_f file,
+ byte *buffer,
+ int size,
+ int *unread);
+extern int osgbpb_read (os_f file,
+ byte *buffer,
+ int size);
+
+#define xosgbpb_read(file, buffer, size, unread) \
+ (os_error*) _swix(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_OUT(3), \
+ OSGBPB_Read, \
+ file, \
+ buffer, \
+ size, \
+ unread)
+
+#define osgbpb_read(file, buffer, size) \
+ _swi(OS_GBPB, _IN(0)|_IN(1)|_IN(2)|_IN(3)|_RETURN(3), \
+ OSGBPB_Read, \
+ file, \
+ buffer, \
+ size)
+
+/* From oslib:osfind.h */
+#undef OS_Find
+#define OS_Find 0xD
+#undef OSFind_Openin
+#define OSFind_Openin 0x40
+#undef OSFind_Openout
+#define OSFind_Openout 0x80
+#undef OSFind_Openup
+#define OSFind_Openup 0xC0
+#undef OSFind_Close
+#define OSFind_Close 0x0
+
+#define xosfind_open(reason, file_name, path, file) \
+ (os_error*) _swix(OS_Find, _IN(0)|_IN(1)|_IN(2)|_OUT(0), \
+ reason, file_name, path, file)
+
+#define osfind_open(reason, file_name, path) \
+ (os_f) _swi(OS_Find, _IN(0)|_IN(1)|_IN(2)|_RETURN(0), \
+ reason, file_name, path)
+
+extern os_error *xosfind_openin (bits flags,
+ char *file_name,
+ char *path,
+ os_f *file);
+extern os_f osfind_openin (bits flags,
+ char *file_name,
+ char *path);
+
+#define xosfind_openin(flags, file_name, path, file) \
+ xosfind_open(flags | OSFind_Openin, file_name, path, file)
+
+#define osfind_openin(flags, file_name, path) \
+ osfind_open(flags | OSFind_Openin, file_name, path)
+
+extern os_error *xosfind_openout (bits flags,
+ char *file_name,
+ char *path,
+ os_f *file);
+extern os_f osfind_openout (bits flags,
+ char *file_name,
+ char *path);
+
+#define xosfind_openout(flags, file_name, path, file) \
+ xosfind_open(flags | OSFind_Openout, file_name, path, file)
+
+#define osfind_openout(flags, file_name, path) \
+ osfind_open(flags | OSFind_Openout, file_name, path)
+
+extern os_error *xosfind_openup (bits flags,
+ char *file_name,
+ char *path,
+ os_f *file);
+extern os_f osfind_openup (bits flags,
+ char *file_name,
+ char *path);
+
+#define xosfind_openup(flags, file_name, path, file) \
+ xosfind_open(flags | OSFind_Openup, file_name, path, file)
+
+#define osfind_openup(flags, file_name, path) \
+ osfind_open(flags | OSFind_Openup, file_name, path)
+
+extern os_error *xosfind_close (os_f file);
+extern void osfind_close (os_f file);
+
+#define xosfind_close(file) \
+ (os_error*) _swix(OS_Find, _IN(0)|_IN(1), \
+ OSFind_Close, \
+ file)
+
+#define osfind_close(file) \
+ (void) _swi(OS_Find, _IN(0)|_IN(1), \
+ OSFind_Close, \
+ file)
+
+/* From oslib:osargs.h */
+#undef OS_Args
+#define OS_Args 0x9
+#undef OSArgs_ReadPtr
+#define OSArgs_ReadPtr 0x0
+#undef OSArgs_SetPtr
+#define OSArgs_SetPtr 0x1
+#undef OSArgs_ReadExt
+#define OSArgs_ReadExt 0x2
+
+extern os_error *xosargs_read_ptr (os_f file,
+ int *ptr);
+extern int osargs_read_ptr (os_f file);
+
+#define xosargs_read_ptr(file, ptr) \
+ (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
+ OSArgs_ReadPtr, \
+ file, \
+ ptr)
+
+#define osargs_read_ptr(file) \
+ _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
+ OSArgs_ReadPtr, \
+ file)
+
+extern os_error *xosargs_set_ptr (os_f file,
+ int ptr);
+extern void osargs_set_ptr (os_f file,
+ int ptr);
+
+#define xosargs_set_ptr(file, ptr) \
+ (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_IN(2), \
+ OSArgs_SetPtr, \
+ file, \
+ ptr)
+
+#define osargs_set_ptr(file, ptr) \
+ (void) _swi(OS_Args, _IN(0)|_IN(1)|_IN(2), \
+ OSArgs_SetPtr, \
+ file, \
+ ptr)
+
+extern os_error *xosargs_read_ext (os_f file,
+ int *ext);
+extern int osargs_read_ext (os_f file);
+
+#define xosargs_read_ext(file, ext) \
+ (os_error*) _swix(OS_Args, _IN(0)|_IN(1)|_OUT(2), \
+ OSArgs_ReadExt, \
+ file, \
+ ext)
+
+#define osargs_read_ext(file) \
+ _swi(OS_Args, _IN(0)|_IN(1)|_RETURN(2), \
+ OSArgs_ReadExt, \
+ file)
+
+/* OSLIB EMULATION ENDS */
+
+#endif
+
+#ifndef __osfcn_h
+/* Will be set or not during tiffcomp.h */
+/* You get this to compile under C++? Please say how! */
+
+extern int open(const char* name, int flags, int mode)
+{
+ /* From what I can tell, should return <0 for failure */
+ os_error* e = (os_error*) 1; /* Cheeky way to use a pointer eh? :-) */
+ os_f file = (os_f) -1;
+
+ flags = flags;
+
+ switch(mode)
+ {
+ case O_RDONLY:
+ {
+ e = xosfind_openin(SKIP, name, SKIP, &file);
+ break;
+ }
+ case O_WRONLY:
+ case O_RDWR|O_CREAT:
+ case O_RDWR|O_CREAT|O_TRUNC:
+ {
+ e = xosfind_openout(SKIP, name, SKIP, &file);
+ break;
+ }
+ case O_RDWR:
+ {
+ e = xosfind_openup(SKIP, name, SKIP, &file);
+ break;
+ }
+ }
+ if (e)
+ {
+ file = (os_f) -1;
+ }
+ return (file);
+}
+
+extern int close(int fd)
+{
+ return ((int) xosfind_close((os_f) fd));
+}
+
+extern int write(int fd, const char *buf, int nbytes)
+{
+ /* Returns number of bytes written */
+ return (nbytes - osgbpb_write((os_f) fd, (const byte*) buf, nbytes));
+}
+
+extern int read(int fd, char *buf, int nbytes)
+{
+ /* Returns number of bytes read */
+ return (nbytes - osgbpb_read((os_f) fd, (byte*) buf, nbytes));
+}
+
+extern off_t lseek(int fd, off_t offset, int whence)
+{
+ int absolute = 0;
+
+ switch (whence)
+ {
+ case SEEK_SET:
+ {
+ absolute = (int) offset;
+ break;
+ }
+ case SEEK_CUR:
+ {
+ absolute = osargs_read_ptr((os_f) fd) + (int) offset;
+ break;
+ }
+ case SEEK_END:
+ {
+ absolute = osargs_read_ext((os_f) fd) + (int) offset;
+ break;
+ }
+ }
+
+ osargs_set_ptr((os_f) fd, absolute);
+
+ return ((off_t) osargs_read_ptr((os_f) fd));
+}
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((tsize_t) read((int) fd, buf, (size_t) size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((tsize_t) write((int) fd, buf, (size_t) size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (close((int) fd));
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ return (lseek((int) fd, SEEK_END, SEEK_SET));
+}
+
+#ifdef HAVE_MMAP
+#error "I didn't know Acorn had that!"
+#endif
+
+/* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ (void) fd; (void) pbase; (void) psize;
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ (void) fd; (void) base; (void) size;
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc,
+ _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+ _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ {
+ tif->tif_fd = fd;
+ }
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+
+ m = _TIFFgetMode(mode, module);
+
+ if (m == -1)
+ {
+ return ((TIFF*) 0);
+ }
+
+ fd = open(name, 0, m);
+
+ if (fd < 0)
+ {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF *)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+}
+
+void*
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+void*
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+acornWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ {
+ fprintf(stderr, "%s: ", module);
+ }
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = acornWarningHandler;
+
+static void
+acornErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ {
+ fprintf(stderr, "%s: ", module);
+ }
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = acornErrorHandler;
diff --git a/Source/LibTIFF/tif_apple.c b/Source/LibTIFF/tif_apple.c
new file mode 100644
index 0000000..9bd1cfa
--- /dev/null
+++ b/Source/LibTIFF/tif_apple.c
@@ -0,0 +1,274 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_apple.c,v 1.27 2009/09/06 13:11:26 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Macintosh-specific routines.
+ *
+ * These routines use only Toolbox and high-level File Manager traps.
+ * They make no calls to the THINK C "unix" compatibility library. Also,
+ * malloc is not used directly but it is still referenced internally by
+ * the ANSI library in rare cases. Heap fragmentation by the malloc ring
+ * buffer is therefore minimized.
+ *
+ * O_RDONLY and O_RDWR are treated identically here. The tif_mode flag is
+ * checked in TIFFWriteCheck().
+ *
+ * Create below fills in a blank creator signature and sets the file type
+ * to 'TIFF'. It is much better for the application to do this by Create'ing
+ * the file first and TIFFOpen'ing it later.
+ * ---------
+ * This code has been "Carbonized", and may not work with older MacOS versions.
+ * If so, grab the tif_apple.c out of an older libtiff distribution, like
+ * 3.5.5 from www.libtiff.org.
+ */
+
+#include "tiffiop.h"
+#include <Errors.h>
+#include <Files.h>
+#include <Memory.h>
+#include <Script.h>
+
+#if defined(__PPCC__) || defined(__SC__) || defined(__MRC__) || defined(applec)
+#define CtoPstr c2pstr
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (FSRead((short) fd, (long*) &size, (char*) buf) == noErr ?
+ size : (tsize_t) -1);
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (FSWrite((short) fd, (long*) &size, (char*) buf) == noErr ?
+ size : (tsize_t) -1);
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ long fpos, size;
+
+ if (GetEOF((short) fd, &size) != noErr)
+ return EOF;
+ (void) GetFPos((short) fd, &fpos);
+
+ switch (whence) {
+ case SEEK_CUR:
+ if (off + fpos > size)
+ SetEOF((short) fd, off + fpos);
+ if (SetFPos((short) fd, fsFromMark, off) != noErr)
+ return EOF;
+ break;
+ case SEEK_END:
+ if (off > 0)
+ SetEOF((short) fd, off + size);
+ if (SetFPos((short) fd, fsFromStart, off + size) != noErr)
+ return EOF;
+ break;
+ case SEEK_SET:
+ if (off > size)
+ SetEOF((short) fd, off);
+ if (SetFPos((short) fd, fsFromStart, off) != noErr)
+ return EOF;
+ break;
+ }
+
+ return (toff_t)(GetFPos((short) fd, &fpos) == noErr ? fpos : EOF);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (FSClose((short) fd));
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ long size;
+
+ if (GetEOF((short) fd, &size) != noErr) {
+ TIFFErrorExt(fd, "_tiffSizeProc", "%s: Cannot get file size");
+ return (-1L);
+ }
+ return ((toff_t) size);
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode, (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+static void ourc2pstr( char* inString )
+{
+ int sLen = strlen( inString );
+ BlockMoveData( inString, &inString[1], sLen );
+ inString[0] = sLen;
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ Str255 pname;
+ FInfo finfo;
+ short fref;
+ OSErr err;
+ FSSpec fSpec;
+
+ strcpy((char*) pname, name);
+ ourc2pstr((char*) pname);
+
+ err = FSMakeFSSpec( 0, 0, pname, &fSpec );
+
+ switch (_TIFFgetMode(mode, module)) {
+ default:
+ return ((TIFF*) 0);
+ case O_RDWR | O_CREAT | O_TRUNC:
+ if (FSpGetFInfo(&fSpec, &finfo) == noErr)
+ FSpDelete(&fSpec);
+ /* fall through */
+ case O_RDWR | O_CREAT:
+ if ((err = FSpGetFInfo(&fSpec, &finfo)) == fnfErr) {
+ if (FSpCreate(&fSpec, ' ', 'TIFF', smSystemScript) != noErr)
+ goto badCreate;
+ if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+ goto badOpen;
+ } else if (err == noErr) {
+ if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+ goto badOpen;
+ } else
+ goto badOpen;
+ break;
+ case O_RDONLY:
+ if (FSpOpenDF(&fSpec, fsRdPerm, &fref) != noErr)
+ goto badOpen;
+ break;
+ case O_RDWR:
+ if (FSpOpenDF(&fSpec, fsRdWrPerm, &fref) != noErr)
+ goto badOpen;
+ break;
+ }
+ return (TIFFFdOpen((int) fref, name, mode));
+badCreate:
+ TIFFErrorExt(0, module, "%s: Cannot create", name);
+ return ((TIFF*) 0);
+badOpen:
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF*) 0);
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (NewPtr((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ DisposePtr(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ Ptr n = p;
+
+ SetPtrSize(p, (size_t) s);
+ if (MemError() && (n = NewPtr((size_t) s)) != NULL) {
+ BlockMove(p, n, GetPtrSize(p));
+ DisposePtr(p);
+ }
+ return ((tdata_t) n);
+}
+
+static void
+appleWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = appleWarningHandler;
+
+static void
+appleErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = appleErrorHandler;
diff --git a/Source/LibTIFF/tif_atari.c b/Source/LibTIFF/tif_atari.c
new file mode 100644
index 0000000..e25f787
--- /dev/null
+++ b/Source/LibTIFF/tif_atari.c
@@ -0,0 +1,243 @@
+/* "$Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_atari.c,v 1.27 2009/09/06 13:11:27 drolon Exp $" */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library ATARI-specific Routines.
+ */
+#include "tiffiop.h"
+#if defined(__TURBOC__)
+#include <tos.h>
+#include <stdio.h>
+#else
+#include <osbind.h>
+#include <fcntl.h>
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE 3
+#endif
+
+#include <errno.h>
+
+#define AEFILNF -33
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ long r;
+
+ r = Fread((int) fd, size, buf);
+ if (r < 0) {
+ errno = (int)-r;
+ r = -1;
+ }
+ return r;
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ long r;
+
+ r = Fwrite((int) fd, size, buf);
+ if (r < 0) {
+ errno = (int)-r;
+ r = -1;
+ }
+ return r;
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, off_t off, int whence)
+{
+ char buf[256];
+ long current_off, expected_off, new_off;
+
+ if (whence == SEEK_END || off <= 0)
+ return Fseek(off, (int) fd, whence);
+ current_off = Fseek(0, (int) fd, SEEK_CUR); /* find out where we are */
+ if (whence == SEEK_SET)
+ expected_off = off;
+ else
+ expected_off = off + current_off;
+ new_off = Fseek(off, (int) fd, whence);
+ if (new_off == expected_off)
+ return new_off;
+ /* otherwise extend file -- zero filling the hole */
+ if (new_off < 0) /* error? */
+ new_off = Fseek(0, (int) fd, SEEK_END); /* go to eof */
+ _TIFFmemset(buf, 0, sizeof(buf));
+ while (expected_off > new_off) {
+ off = expected_off - new_off;
+ if (off > sizeof(buf))
+ off = sizeof(buf);
+ if ((current_off = Fwrite((int) fd, off, buf)) != off)
+ return (current_off > 0) ?
+ new_off + current_off : new_off;
+ new_off += off;
+ }
+ return new_off;
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ long r;
+
+ r = Fclose((int) fd);
+ if (r < 0) {
+ errno = (int)-r;
+ r = -1;
+ }
+ return (int)r;
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ long pos, eof;
+
+ pos = Fseek(0, (int) fd, SEEK_CUR);
+ eof = Fseek(0, (int) fd, SEEK_END);
+ Fseek(pos, (int) fd, SEEK_SET);
+ return eof;
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+* Open a TIFF file descriptor for read/writing.
+*/
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+* Open a TIFF file for read/writing.
+*/
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m;
+ long fd;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+ if (m & O_TRUNC) {
+ fd = Fcreate(name, 0);
+ } else {
+ fd = Fopen(name, m & O_ACCMODE);
+ if (fd == AEFILNF && m & O_CREAT)
+ fd = Fcreate(name, 0);
+ }
+ if (fd < 0)
+ errno = (int)fd;
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF*)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+}
+
+#include <stdlib.h>
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, size_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, size_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+atariWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = atariWarningHandler;
+
+static void
+atariErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = atariErrorHandler;
diff --git a/Source/LibTIFF/tif_aux.c b/Source/LibTIFF/tif_aux.c
new file mode 100644
index 0000000..c3a2349
--- /dev/null
+++ b/Source/LibTIFF/tif_aux.c
@@ -0,0 +1,275 @@
+/* $Id: tif_aux.c,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Auxiliary Support Routines.
+ */
+#include "tiffiop.h"
+#include "tif_predict.h"
+#include <math.h>
+
+tdata_t
+_TIFFCheckRealloc(TIFF* tif, tdata_t buffer,
+ size_t nmemb, size_t elem_size, const char* what)
+{
+ tdata_t cp = NULL;
+ tsize_t bytes = nmemb * elem_size;
+
+ /*
+ * XXX: Check for integer overflow.
+ */
+ if (nmemb && elem_size && bytes / elem_size == nmemb)
+ cp = _TIFFrealloc(buffer, bytes);
+
+ if (cp == NULL)
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No space %s", what);
+
+ return cp;
+}
+
+tdata_t
+_TIFFCheckMalloc(TIFF* tif, size_t nmemb, size_t elem_size, const char* what)
+{
+ return _TIFFCheckRealloc(tif, NULL, nmemb, elem_size, what);
+}
+
+static int
+TIFFDefaultTransferFunction(TIFFDirectory* td)
+{
+ uint16 **tf = td->td_transferfunction;
+ tsize_t i, n, nbytes;
+
+ tf[0] = tf[1] = tf[2] = 0;
+ if (td->td_bitspersample >= sizeof(tsize_t) * 8 - 2)
+ return 0;
+
+ n = 1<<td->td_bitspersample;
+ nbytes = n * sizeof (uint16);
+ if (!(tf[0] = (uint16 *)_TIFFmalloc(nbytes)))
+ return 0;
+ tf[0][0] = 0;
+ for (i = 1; i < n; i++) {
+ double t = (double)i/((double) n-1.);
+ tf[0][i] = (uint16)floor(65535.*pow(t, 2.2) + .5);
+ }
+
+ if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+ if (!(tf[1] = (uint16 *)_TIFFmalloc(nbytes)))
+ goto bad;
+ _TIFFmemcpy(tf[1], tf[0], nbytes);
+ if (!(tf[2] = (uint16 *)_TIFFmalloc(nbytes)))
+ goto bad;
+ _TIFFmemcpy(tf[2], tf[0], nbytes);
+ }
+ return 1;
+
+bad:
+ if (tf[0])
+ _TIFFfree(tf[0]);
+ if (tf[1])
+ _TIFFfree(tf[1]);
+ if (tf[2])
+ _TIFFfree(tf[2]);
+ tf[0] = tf[1] = tf[2] = 0;
+ return 0;
+}
+
+/*
+ * Like TIFFGetField, but return any default
+ * value if the tag is not present in the directory.
+ *
+ * NB: We use the value in the directory, rather than
+ * explcit values so that defaults exist only one
+ * place in the library -- in TIFFDefaultDirectory.
+ */
+int
+TIFFVGetFieldDefaulted(TIFF* tif, ttag_t tag, va_list ap)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if (TIFFVGetField(tif, tag, ap))
+ return (1);
+ switch (tag) {
+ case TIFFTAG_SUBFILETYPE:
+ *va_arg(ap, uint32 *) = td->td_subfiletype;
+ return (1);
+ case TIFFTAG_BITSPERSAMPLE:
+ *va_arg(ap, uint16 *) = td->td_bitspersample;
+ return (1);
+ case TIFFTAG_THRESHHOLDING:
+ *va_arg(ap, uint16 *) = td->td_threshholding;
+ return (1);
+ case TIFFTAG_FILLORDER:
+ *va_arg(ap, uint16 *) = td->td_fillorder;
+ return (1);
+ case TIFFTAG_ORIENTATION:
+ *va_arg(ap, uint16 *) = td->td_orientation;
+ return (1);
+ case TIFFTAG_SAMPLESPERPIXEL:
+ *va_arg(ap, uint16 *) = td->td_samplesperpixel;
+ return (1);
+ case TIFFTAG_ROWSPERSTRIP:
+ *va_arg(ap, uint32 *) = td->td_rowsperstrip;
+ return (1);
+ case TIFFTAG_MINSAMPLEVALUE:
+ *va_arg(ap, uint16 *) = td->td_minsamplevalue;
+ return (1);
+ case TIFFTAG_MAXSAMPLEVALUE:
+ *va_arg(ap, uint16 *) = td->td_maxsamplevalue;
+ return (1);
+ case TIFFTAG_PLANARCONFIG:
+ *va_arg(ap, uint16 *) = td->td_planarconfig;
+ return (1);
+ case TIFFTAG_RESOLUTIONUNIT:
+ *va_arg(ap, uint16 *) = td->td_resolutionunit;
+ return (1);
+ case TIFFTAG_PREDICTOR:
+ {
+ TIFFPredictorState* sp = (TIFFPredictorState*) tif->tif_data;
+ *va_arg(ap, uint16*) = (uint16) sp->predictor;
+ return 1;
+ }
+ case TIFFTAG_DOTRANGE:
+ *va_arg(ap, uint16 *) = 0;
+ *va_arg(ap, uint16 *) = (1<<td->td_bitspersample)-1;
+ return (1);
+ case TIFFTAG_INKSET:
+ *va_arg(ap, uint16 *) = INKSET_CMYK;
+ return 1;
+ case TIFFTAG_NUMBEROFINKS:
+ *va_arg(ap, uint16 *) = 4;
+ return (1);
+ case TIFFTAG_EXTRASAMPLES:
+ *va_arg(ap, uint16 *) = td->td_extrasamples;
+ *va_arg(ap, uint16 **) = td->td_sampleinfo;
+ return (1);
+ case TIFFTAG_MATTEING:
+ *va_arg(ap, uint16 *) =
+ (td->td_extrasamples == 1 &&
+ td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
+ return (1);
+ case TIFFTAG_TILEDEPTH:
+ *va_arg(ap, uint32 *) = td->td_tiledepth;
+ return (1);
+ case TIFFTAG_DATATYPE:
+ *va_arg(ap, uint16 *) = td->td_sampleformat-1;
+ return (1);
+ case TIFFTAG_SAMPLEFORMAT:
+ *va_arg(ap, uint16 *) = td->td_sampleformat;
+ return(1);
+ case TIFFTAG_IMAGEDEPTH:
+ *va_arg(ap, uint32 *) = td->td_imagedepth;
+ return (1);
+ case TIFFTAG_YCBCRCOEFFICIENTS:
+ {
+ /* defaults are from CCIR Recommendation 601-1 */
+ static float ycbcrcoeffs[] = { 0.299f, 0.587f, 0.114f };
+ *va_arg(ap, float **) = ycbcrcoeffs;
+ return 1;
+ }
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[0];
+ *va_arg(ap, uint16 *) = td->td_ycbcrsubsampling[1];
+ return (1);
+ case TIFFTAG_YCBCRPOSITIONING:
+ *va_arg(ap, uint16 *) = td->td_ycbcrpositioning;
+ return (1);
+ case TIFFTAG_WHITEPOINT:
+ {
+ static float whitepoint[2];
+
+ /* TIFF 6.0 specification tells that it is no default
+ value for the WhitePoint, but AdobePhotoshop TIFF
+ Technical Note tells that it should be CIE D50. */
+ whitepoint[0] = D50_X0 / (D50_X0 + D50_Y0 + D50_Z0);
+ whitepoint[1] = D50_Y0 / (D50_X0 + D50_Y0 + D50_Z0);
+ *va_arg(ap, float **) = whitepoint;
+ return 1;
+ }
+ case TIFFTAG_TRANSFERFUNCTION:
+ if (!td->td_transferfunction[0] &&
+ !TIFFDefaultTransferFunction(td)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "No space for \"TransferFunction\" tag");
+ return (0);
+ }
+ *va_arg(ap, uint16 **) = td->td_transferfunction[0];
+ if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+ *va_arg(ap, uint16 **) = td->td_transferfunction[1];
+ *va_arg(ap, uint16 **) = td->td_transferfunction[2];
+ }
+ return (1);
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ {
+ int i;
+ static float ycbcr_refblackwhite[] =
+ { 0.0F, 255.0F, 128.0F, 255.0F, 128.0F, 255.0F };
+ static float rgb_refblackwhite[6];
+
+ for (i = 0; i < 3; i++) {
+ rgb_refblackwhite[2 * i + 0] = 0.0F;
+ rgb_refblackwhite[2 * i + 1] =
+ (float)((1L<<td->td_bitspersample)-1L);
+ }
+
+ if (td->td_photometric == PHOTOMETRIC_YCBCR) {
+ /*
+ * YCbCr (Class Y) images must have the
+ * ReferenceBlackWhite tag set. Fix the
+ * broken images, which lacks that tag.
+ */
+ *va_arg(ap, float **) = ycbcr_refblackwhite;
+ } else {
+ /*
+ * Assume RGB (Class R)
+ */
+ *va_arg(ap, float **) = rgb_refblackwhite;
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Like TIFFGetField, but return any default
+ * value if the tag is not present in the directory.
+ */
+int
+TIFFGetFieldDefaulted(TIFF* tif, ttag_t tag, ...)
+{
+ int ok;
+ va_list ap;
+
+ va_start(ap, tag);
+ ok = TIFFVGetFieldDefaulted(tif, tag, ap);
+ va_end(ap);
+ return (ok);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_close.c b/Source/LibTIFF/tif_close.c
new file mode 100644
index 0000000..614b8fc
--- /dev/null
+++ b/Source/LibTIFF/tif_close.c
@@ -0,0 +1,119 @@
+/* $Id: tif_close.c,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+/************************************************************************/
+/* TIFFCleanup() */
+/************************************************************************/
+
+/**
+ * Auxiliary function to free the TIFF structure. Given structure will be
+ * completetly freed, so you should save opened file handle and pointer
+ * to the close procedure in external variables before calling
+ * _TIFFCleanup(), if you will need these ones to close the file.
+ *
+ * @param tif A TIFF pointer.
+ */
+
+void
+TIFFCleanup(TIFF* tif)
+{
+ if (tif->tif_mode != O_RDONLY)
+ /*
+ * Flush buffered data and directory (if dirty).
+ */
+ TIFFFlush(tif);
+ (*tif->tif_cleanup)(tif);
+ TIFFFreeDirectory(tif);
+
+ if (tif->tif_dirlist)
+ _TIFFfree(tif->tif_dirlist);
+
+ /* Clean up client info links */
+ while( tif->tif_clientinfo )
+ {
+ TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+ tif->tif_clientinfo = link->next;
+ _TIFFfree( link->name );
+ _TIFFfree( link );
+ }
+
+ if (tif->tif_rawdata && (tif->tif_flags&TIFF_MYBUFFER))
+ _TIFFfree(tif->tif_rawdata);
+ if (isMapped(tif))
+ TIFFUnmapFileContents(tif, tif->tif_base, tif->tif_size);
+
+ /* Clean up custom fields */
+ if (tif->tif_nfields > 0)
+ {
+ size_t i;
+
+ for (i = 0; i < tif->tif_nfields; i++)
+ {
+ TIFFFieldInfo *fld = tif->tif_fieldinfo[i];
+ if (fld->field_bit == FIELD_CUSTOM &&
+ strncmp("Tag ", fld->field_name, 4) == 0)
+ {
+ _TIFFfree(fld->field_name);
+ _TIFFfree(fld);
+ }
+ }
+
+ _TIFFfree(tif->tif_fieldinfo);
+ }
+
+ _TIFFfree(tif);
+}
+
+/************************************************************************/
+/* TIFFClose() */
+/************************************************************************/
+
+/**
+ * Close a previously opened TIFF file.
+ *
+ * TIFFClose closes a file that was previously opened with TIFFOpen().
+ * Any buffered data are flushed to the file, including the contents of
+ * the current directory (if modified); and all resources are reclaimed.
+ *
+ * @param tif A TIFF pointer.
+ */
+
+void
+TIFFClose(TIFF* tif)
+{
+ TIFFCloseProc closeproc = tif->tif_closeproc;
+ thandle_t fd = tif->tif_clientdata;
+
+ TIFFCleanup(tif);
+ (void) (*closeproc)(fd);
+}
+
diff --git a/Source/LibTIFF/tif_codec.c b/Source/LibTIFF/tif_codec.c
new file mode 100644
index 0000000..2d4986c
--- /dev/null
+++ b/Source/LibTIFF/tif_codec.c
@@ -0,0 +1,153 @@
+/* $Id: tif_codec.c,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Builtin Compression Scheme Configuration Support.
+ */
+#include "tiffiop.h"
+
+static int NotConfigured(TIFF*, int);
+
+#ifndef LZW_SUPPORT
+#define TIFFInitLZW NotConfigured
+#endif
+#ifndef PACKBITS_SUPPORT
+#define TIFFInitPackBits NotConfigured
+#endif
+#ifndef THUNDER_SUPPORT
+#define TIFFInitThunderScan NotConfigured
+#endif
+#ifndef NEXT_SUPPORT
+#define TIFFInitNeXT NotConfigured
+#endif
+#ifndef JPEG_SUPPORT
+#define TIFFInitJPEG NotConfigured
+#endif
+#ifndef OJPEG_SUPPORT
+#define TIFFInitOJPEG NotConfigured
+#endif
+#ifndef CCITT_SUPPORT
+#define TIFFInitCCITTRLE NotConfigured
+#define TIFFInitCCITTRLEW NotConfigured
+#define TIFFInitCCITTFax3 NotConfigured
+#define TIFFInitCCITTFax4 NotConfigured
+#endif
+#ifndef JBIG_SUPPORT
+#define TIFFInitJBIG NotConfigured
+#endif
+#ifndef ZIP_SUPPORT
+#define TIFFInitZIP NotConfigured
+#endif
+#ifndef PIXARLOG_SUPPORT
+#define TIFFInitPixarLog NotConfigured
+#endif
+#ifndef LOGLUV_SUPPORT
+#define TIFFInitSGILog NotConfigured
+#endif
+
+/*
+ * Compression schemes statically built into the library.
+ */
+#ifdef VMS
+const TIFFCodec _TIFFBuiltinCODECS[] = {
+#else
+TIFFCodec _TIFFBuiltinCODECS[] = {
+#endif
+ { "None", COMPRESSION_NONE, TIFFInitDumpMode },
+ { "LZW", COMPRESSION_LZW, TIFFInitLZW },
+ { "PackBits", COMPRESSION_PACKBITS, TIFFInitPackBits },
+ { "ThunderScan", COMPRESSION_THUNDERSCAN,TIFFInitThunderScan },
+ { "NeXT", COMPRESSION_NEXT, TIFFInitNeXT },
+ { "JPEG", COMPRESSION_JPEG, TIFFInitJPEG },
+ { "Old-style JPEG", COMPRESSION_OJPEG, TIFFInitOJPEG },
+ { "CCITT RLE", COMPRESSION_CCITTRLE, TIFFInitCCITTRLE },
+ { "CCITT RLE/W", COMPRESSION_CCITTRLEW, TIFFInitCCITTRLEW },
+ { "CCITT Group 3", COMPRESSION_CCITTFAX3, TIFFInitCCITTFax3 },
+ { "CCITT Group 4", COMPRESSION_CCITTFAX4, TIFFInitCCITTFax4 },
+ { "ISO JBIG", COMPRESSION_JBIG, TIFFInitJBIG },
+ { "Deflate", COMPRESSION_DEFLATE, TIFFInitZIP },
+ { "AdobeDeflate", COMPRESSION_ADOBE_DEFLATE , TIFFInitZIP },
+ { "PixarLog", COMPRESSION_PIXARLOG, TIFFInitPixarLog },
+ { "SGILog", COMPRESSION_SGILOG, TIFFInitSGILog },
+ { "SGILog24", COMPRESSION_SGILOG24, TIFFInitSGILog },
+ { NULL, 0, NULL }
+};
+
+static int
+_notConfigured(TIFF* tif)
+{
+ const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+ char compression_code[20];
+
+ sprintf( compression_code, "%d", tif->tif_dir.td_compression );
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%s compression support is not configured",
+ c ? c->name : compression_code );
+ return (0);
+}
+
+static int
+NotConfigured(TIFF* tif, int scheme)
+{
+ (void) scheme;
+
+ tif->tif_decodestatus = FALSE;
+ tif->tif_setupdecode = _notConfigured;
+ tif->tif_encodestatus = FALSE;
+ tif->tif_setupencode = _notConfigured;
+ return (1);
+}
+
+/************************************************************************/
+/* TIFFIsCODECConfigured() */
+/************************************************************************/
+
+/**
+ * Check whether we have working codec for the specific coding scheme.
+ *
+ * @return returns 1 if the codec is configured and working. Otherwise
+ * 0 will be returned.
+ */
+
+int
+TIFFIsCODECConfigured(uint16 scheme)
+{
+ const TIFFCodec* codec = TIFFFindCODEC(scheme);
+
+ if(codec == NULL) {
+ return 0;
+ }
+ if(codec->init == NULL) {
+ return 0;
+ }
+ if(codec->init != NotConfigured){
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/Source/LibTIFF/tif_color.c b/Source/LibTIFF/tif_color.c
new file mode 100644
index 0000000..f4ddb46
--- /dev/null
+++ b/Source/LibTIFF/tif_color.c
@@ -0,0 +1,275 @@
+/* $Id: tif_color.c,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
+ * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
+ * the permission of John Cupitt, the VIPS author.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Color space conversion routines.
+ */
+
+#include "tiffiop.h"
+#include <math.h>
+
+/*
+ * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
+ */
+void
+TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
+ float *X, float *Y, float *Z)
+{
+ float L = (float)l * 100.0F / 255.0F;
+ float cby, tmp;
+
+ if( L < 8.856F ) {
+ *Y = (L * cielab->Y0) / 903.292F;
+ cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
+ } else {
+ cby = (L + 16.0F) / 116.0F;
+ *Y = cielab->Y0 * cby * cby * cby;
+ }
+
+ tmp = (float)a / 500.0F + cby;
+ if( tmp < 0.2069F )
+ *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
+ else
+ *X = cielab->X0 * tmp * tmp * tmp;
+
+ tmp = cby - (float)b / 200.0F;
+ if( tmp < 0.2069F )
+ *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
+ else
+ *Z = cielab->Z0 * tmp * tmp * tmp;
+}
+
+#define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
+/*
+ * Convert color value from the XYZ space to RGB.
+ */
+void
+TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
+ uint32 *r, uint32 *g, uint32 *b)
+{
+ int i;
+ float Yr, Yg, Yb;
+ float *matrix = &cielab->display.d_mat[0][0];
+
+ /* Multiply through the matrix to get luminosity values. */
+ Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
+ Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
+ Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
+
+ /* Clip input */
+ Yr = TIFFmax(Yr, cielab->display.d_Y0R);
+ Yg = TIFFmax(Yg, cielab->display.d_Y0G);
+ Yb = TIFFmax(Yb, cielab->display.d_Y0B);
+
+ /* Avoid overflow in case of wrong input values */
+ Yr = TIFFmin(Yr, cielab->display.d_YCR);
+ Yg = TIFFmin(Yg, cielab->display.d_YCG);
+ Yb = TIFFmin(Yb, cielab->display.d_YCB);
+
+ /* Turn luminosity to colour value. */
+ i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
+ i = TIFFmin(cielab->range, i);
+ *r = RINT(cielab->Yr2r[i]);
+
+ i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
+ i = TIFFmin(cielab->range, i);
+ *g = RINT(cielab->Yg2g[i]);
+
+ i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
+ i = TIFFmin(cielab->range, i);
+ *b = RINT(cielab->Yb2b[i]);
+
+ /* Clip output. */
+ *r = TIFFmin(*r, cielab->display.d_Vrwr);
+ *g = TIFFmin(*g, cielab->display.d_Vrwg);
+ *b = TIFFmin(*b, cielab->display.d_Vrwb);
+}
+#undef RINT
+
+/*
+ * Allocate conversion state structures and make look_up tables for
+ * the Yr,Yb,Yg <=> r,g,b conversions.
+ */
+int
+TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
+ TIFFDisplay *display, float *refWhite)
+{
+ int i;
+ double gamma;
+
+ cielab->range = CIELABTORGB_TABLE_RANGE;
+
+ _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
+
+ /* Red */
+ gamma = 1.0 / cielab->display.d_gammaR ;
+ cielab->rstep =
+ (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+ for(i = 0; i <= cielab->range; i++) {
+ cielab->Yr2r[i] = cielab->display.d_Vrwr
+ * ((float)pow((double)i / cielab->range, gamma));
+ }
+
+ /* Green */
+ gamma = 1.0 / cielab->display.d_gammaG ;
+ cielab->gstep =
+ (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+ for(i = 0; i <= cielab->range; i++) {
+ cielab->Yg2g[i] = cielab->display.d_Vrwg
+ * ((float)pow((double)i / cielab->range, gamma));
+ }
+
+ /* Blue */
+ gamma = 1.0 / cielab->display.d_gammaB ;
+ cielab->bstep =
+ (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
+ for(i = 0; i <= cielab->range; i++) {
+ cielab->Yb2b[i] = cielab->display.d_Vrwb
+ * ((float)pow((double)i / cielab->range, gamma));
+ }
+
+ /* Init reference white point */
+ cielab->X0 = refWhite[0];
+ cielab->Y0 = refWhite[1];
+ cielab->Z0 = refWhite[2];
+
+ return 0;
+}
+
+/*
+ * Convert color value from the YCbCr space to CIE XYZ.
+ * The colorspace conversion algorithm comes from the IJG v5a code;
+ * see below for more information on how it works.
+ */
+#define SHIFT 16
+#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
+#define ONE_HALF ((int32)(1<<(SHIFT-1)))
+#define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1))
+#define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f))
+#define HICLAMP(f,max) ((f)>(max)?(max):(f))
+
+void
+TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
+ uint32 *r, uint32 *g, uint32 *b)
+{
+ /* XXX: Only 8-bit YCbCr input supported for now */
+ Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255);
+
+ *r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]];
+ *g = ycbcr->clamptab[ycbcr->Y_tab[Y]
+ + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)];
+ *b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]];
+}
+
+/*
+ * Initialize the YCbCr->RGB conversion tables. The conversion
+ * is done according to the 6.0 spec:
+ *
+ * R = Y + Cr*(2 - 2*LumaRed)
+ * B = Y + Cb*(2 - 2*LumaBlue)
+ * G = Y
+ * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
+ * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
+ *
+ * To avoid floating point arithmetic the fractional constants that
+ * come out of the equations are represented as fixed point values
+ * in the range 0...2^16. We also eliminate multiplications by
+ * pre-calculating possible values indexed by Cb and Cr (this code
+ * assumes conversion is being done for 8-bit samples).
+ */
+int
+TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
+{
+ TIFFRGBValue* clamptab;
+ int i;
+
+#define LumaRed luma[0]
+#define LumaGreen luma[1]
+#define LumaBlue luma[2]
+
+ clamptab = (TIFFRGBValue*)(
+ (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)));
+ _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
+ ycbcr->clamptab = (clamptab += 256);
+ for (i = 0; i < 256; i++)
+ clamptab[i] = (TIFFRGBValue) i;
+ _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */
+ ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
+ ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
+ ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
+ ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
+ ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
+
+ { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1);
+ float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2);
+ float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3);
+ float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4);
+ int x;
+
+#undef LumaBlue
+#undef LumaGreen
+#undef LumaRed
+
+ /*
+ * i is the actual input pixel value in the range 0..255
+ * Cb and Cr values are in the range -128..127 (actually
+ * they are in a range defined by the ReferenceBlackWhite
+ * tag) so there is some range shifting to do here when
+ * constructing tables indexed by the raw pixel data.
+ */
+ for (i = 0, x = -128; i < 256; i++, x++) {
+ int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F,
+ refBlackWhite[5] - 128.0F, 127);
+ int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F,
+ refBlackWhite[3] - 128.0F, 127);
+
+ ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
+ ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
+ ycbcr->Cr_g_tab[i] = D2*Cr;
+ ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
+ ycbcr->Y_tab[i] =
+ (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255);
+ }
+ }
+
+ return 0;
+}
+#undef HICLAMP
+#undef CLAMP
+#undef Code2V
+#undef SHIFT
+#undef ONE_HALF
+#undef FIX
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_compress.c b/Source/LibTIFF/tif_compress.c
new file mode 100644
index 0000000..ac58e91
--- /dev/null
+++ b/Source/LibTIFF/tif_compress.c
@@ -0,0 +1,288 @@
+/* $Id: tif_compress.c,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Compression Scheme Configuration Support.
+ */
+#include "tiffiop.h"
+
+static int
+TIFFNoEncode(TIFF* tif, const char* method)
+{
+ const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+ if (c) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%s %s encoding is not implemented",
+ c->name, method);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Compression scheme %u %s encoding is not implemented",
+ tif->tif_dir.td_compression, method);
+ }
+ return (-1);
+}
+
+int
+_TIFFNoRowEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoEncode(tif, "scanline"));
+}
+
+int
+_TIFFNoStripEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoEncode(tif, "strip"));
+}
+
+int
+_TIFFNoTileEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoEncode(tif, "tile"));
+}
+
+static int
+TIFFNoDecode(TIFF* tif, const char* method)
+{
+ const TIFFCodec* c = TIFFFindCODEC(tif->tif_dir.td_compression);
+
+ if (c)
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%s %s decoding is not implemented",
+ c->name, method);
+ else
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Compression scheme %u %s decoding is not implemented",
+ tif->tif_dir.td_compression, method);
+ return (-1);
+}
+
+int
+_TIFFNoRowDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoDecode(tif, "scanline"));
+}
+
+int
+_TIFFNoStripDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoDecode(tif, "strip"));
+}
+
+int
+_TIFFNoTileDecode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) pp; (void) cc; (void) s;
+ return (TIFFNoDecode(tif, "tile"));
+}
+
+int
+_TIFFNoSeek(TIFF* tif, uint32 off)
+{
+ (void) off;
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Compression algorithm does not support random access");
+ return (0);
+}
+
+int
+_TIFFNoPreCode(TIFF* tif, tsample_t s)
+{
+ (void) tif; (void) s;
+ return (1);
+}
+
+static int _TIFFtrue(TIFF* tif) { (void) tif; return (1); }
+static void _TIFFvoid(TIFF* tif) { (void) tif; }
+
+void
+_TIFFSetDefaultCompressionState(TIFF* tif)
+{
+ tif->tif_decodestatus = TRUE;
+ tif->tif_setupdecode = _TIFFtrue;
+ tif->tif_predecode = _TIFFNoPreCode;
+ tif->tif_decoderow = _TIFFNoRowDecode;
+ tif->tif_decodestrip = _TIFFNoStripDecode;
+ tif->tif_decodetile = _TIFFNoTileDecode;
+ tif->tif_encodestatus = TRUE;
+ tif->tif_setupencode = _TIFFtrue;
+ tif->tif_preencode = _TIFFNoPreCode;
+ tif->tif_postencode = _TIFFtrue;
+ tif->tif_encoderow = _TIFFNoRowEncode;
+ tif->tif_encodestrip = _TIFFNoStripEncode;
+ tif->tif_encodetile = _TIFFNoTileEncode;
+ tif->tif_close = _TIFFvoid;
+ tif->tif_seek = _TIFFNoSeek;
+ tif->tif_cleanup = _TIFFvoid;
+ tif->tif_defstripsize = _TIFFDefaultStripSize;
+ tif->tif_deftilesize = _TIFFDefaultTileSize;
+ tif->tif_flags &= ~(TIFF_NOBITREV|TIFF_NOREADRAW);
+}
+
+int
+TIFFSetCompressionScheme(TIFF* tif, int scheme)
+{
+ const TIFFCodec *c = TIFFFindCODEC((uint16) scheme);
+
+ _TIFFSetDefaultCompressionState(tif);
+ /*
+ * Don't treat an unknown compression scheme as an error.
+ * This permits applications to open files with data that
+ * the library does not have builtin support for, but which
+ * may still be meaningful.
+ */
+ return (c ? (*c->init)(tif, scheme) : 1);
+}
+
+/*
+ * Other compression schemes may be registered. Registered
+ * schemes can also override the builtin versions provided
+ * by this library.
+ */
+typedef struct _codec {
+ struct _codec* next;
+ TIFFCodec* info;
+} codec_t;
+static codec_t* registeredCODECS = NULL;
+
+const TIFFCodec*
+TIFFFindCODEC(uint16 scheme)
+{
+ const TIFFCodec* c;
+ codec_t* cd;
+
+ for (cd = registeredCODECS; cd; cd = cd->next)
+ if (cd->info->scheme == scheme)
+ return ((const TIFFCodec*) cd->info);
+ for (c = _TIFFBuiltinCODECS; c->name; c++)
+ if (c->scheme == scheme)
+ return (c);
+ return ((const TIFFCodec*) 0);
+}
+
+TIFFCodec*
+TIFFRegisterCODEC(uint16 scheme, const char* name, TIFFInitMethod init)
+{
+ codec_t* cd = (codec_t*)
+ _TIFFmalloc(sizeof (codec_t) + sizeof (TIFFCodec) + strlen(name)+1);
+
+ if (cd != NULL) {
+ cd->info = (TIFFCodec*) ((tidata_t) cd + sizeof (codec_t));
+ cd->info->name = (char*)
+ ((tidata_t) cd->info + sizeof (TIFFCodec));
+ strcpy(cd->info->name, name);
+ cd->info->scheme = scheme;
+ cd->info->init = init;
+ cd->next = registeredCODECS;
+ registeredCODECS = cd;
+ } else {
+ TIFFErrorExt(0, "TIFFRegisterCODEC",
+ "No space to register compression scheme %s", name);
+ return NULL;
+ }
+ return (cd->info);
+}
+
+void
+TIFFUnRegisterCODEC(TIFFCodec* c)
+{
+ codec_t* cd;
+ codec_t** pcd;
+
+ for (pcd = &registeredCODECS; (cd = *pcd); pcd = &cd->next)
+ if (cd->info == c) {
+ *pcd = cd->next;
+ _TIFFfree(cd);
+ return;
+ }
+ TIFFErrorExt(0, "TIFFUnRegisterCODEC",
+ "Cannot remove compression scheme %s; not registered", c->name);
+}
+
+/************************************************************************/
+/* TIFFGetConfisuredCODECs() */
+/************************************************************************/
+
+/**
+ * Get list of configured codecs, both built-in and registered by user.
+ * Caller is responsible to free this structure.
+ *
+ * @return returns array of TIFFCodec records (the last record should be NULL)
+ * or NULL if function failed.
+ */
+
+TIFFCodec*
+TIFFGetConfiguredCODECs()
+{
+ int i = 1;
+ codec_t *cd;
+ const TIFFCodec *c;
+ TIFFCodec *codecs = NULL, *new_codecs;
+
+ for (cd = registeredCODECS; cd; cd = cd->next) {
+ new_codecs = (TIFFCodec *)
+ _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+ if (!new_codecs) {
+ _TIFFfree (codecs);
+ return NULL;
+ }
+ codecs = new_codecs;
+ _TIFFmemcpy(codecs + i - 1, cd, sizeof(TIFFCodec));
+ i++;
+ }
+ for (c = _TIFFBuiltinCODECS; c->name; c++) {
+ if (TIFFIsCODECConfigured(c->scheme)) {
+ new_codecs = (TIFFCodec *)
+ _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+ if (!new_codecs) {
+ _TIFFfree (codecs);
+ return NULL;
+ }
+ codecs = new_codecs;
+ _TIFFmemcpy(codecs + i - 1, (const tdata_t)c, sizeof(TIFFCodec));
+ i++;
+ }
+ }
+
+ new_codecs = (TIFFCodec *) _TIFFrealloc(codecs, i * sizeof(TIFFCodec));
+ if (!new_codecs) {
+ _TIFFfree (codecs);
+ return NULL;
+ }
+ codecs = new_codecs;
+ _TIFFmemset(codecs + i - 1, 0, sizeof(TIFFCodec));
+
+ return codecs;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_config.h b/Source/LibTIFF/tif_config.h
new file mode 100644
index 0000000..c227a9d
--- /dev/null
+++ b/Source/LibTIFF/tif_config.h
@@ -0,0 +1,264 @@
+/* FreeImage libtiff config */
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* --- byte order --- */
+
+/* Some versions of gcc may have BYTE_ORDER or __BYTE_ORDER defined
+ If your big endian system isn't being detected, add an OS specific check
+*/
+#if (defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN) || \
+ (defined(__BYTE_ORDER) && __BYTE_ORDER==__BIG_ENDIAN) || \
+ defined(__BIG_ENDIAN__)
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_MSB2LSB
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian (Intel) */
+#define WORDS_BIGENDIAN 1
+#else
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian (Intel) */
+#undef WORDS_BIGENDIAN
+#endif // BYTE_ORDER
+
+/* --- compression algorithms --- */
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#define JPEG_SUPPORT 1
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+ fails with unpatched IJG JPEG library) */
+/* #undef OJPEG_SUPPORT */
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+#define PIXARLOG_SUPPORT 1
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#define THUNDER_SUPPORT 1
+
+/* Support Deflate compression */
+#define ZIP_SUPPORT 1
+
+/* --- ``Orthogonal Features'' --- */
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
+#define SUBIFD_SUPPORT 1
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#define CHECK_JPEG_YCBCR_SUBSAMPLING 1
+
+/* --- include files --- */
+
+/* Use the Apple OpenGL framework. */
+/* #undef HAVE_APPLE_OPENGL_FRAMEWORK */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 if you have the `floor' function. */
+#define HAVE_FLOOR 1
+
+/* Define to 1 if you have the `getopt' function. */
+#define HAVE_GETOPT 1
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* Define to 1 if the system has the type `int16'. */
+/* #undef HAVE_INT16 */
+
+/* Define to 1 if the system has the type `int32'. */
+/* #undef HAVE_INT32 */
+
+/* Define to 1 if the system has the type `int8'. */
+/* #undef HAVE_INT8 */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `isascii' function. */
+#define HAVE_ISASCII 1
+
+/* Define to 1 if you have the `c' library (-lc). */
+#define HAVE_LIBC 1
+
+/* Define to 1 if you have the `m' library (-lm). */
+#define HAVE_LIBM 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `mmap' function. */
+#define HAVE_MMAP 1
+
+/* Define to 1 if you have the `pow' function. */
+#define HAVE_POW 1
+
+/* Define if you have POSIX threads libraries and header files. */
+#define HAVE_PTHREAD 1
+
+/* Define to 1 if you have the `sqrt' function. */
+#define HAVE_SQRT 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the <windows.h> header file. */
+/* #undef HAVE_WINDOWS_H */
+
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+
+/* Define to the necessary symbol if this constant uses a non-standard name on
+ your system. */
+/* #undef PTHREAD_CREATE_JOINABLE */
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#define _FILE_OFFSET_BITS 64
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+ #ifdef _MSC_VER
+ #ifndef inline
+ #define inline __inline
+ #endif
+ #else
+ #undef inline
+ #endif // _MSC_VER
+#endif // __cplusplus
+
+#ifdef _MSC_VER
+#define lfind _lfind
+/* Define to 1 if you have the <search.h> header file. */
+#define HAVE_SEARCH_H 1
+#endif // _MSC_VER
+
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+#endif /* _TIFFCONF_ */
diff --git a/Source/LibTIFF/tif_config.h-vms b/Source/LibTIFF/tif_config.h-vms
new file mode 100644
index 0000000..c2cae57
--- /dev/null
+++ b/Source/LibTIFF/tif_config.h-vms
@@ -0,0 +1,46 @@
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+#define HAVE_UNISTD_H 1
+
+#define HAVE_STRING_H 1
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+//#define HAVE_IO_H 1
+
+/* Define to 1 if you have the <search.h> header file. */
+//#define HAVE_SEARCH_H 1
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Set the native cpu bit order */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+/*
+#ifndef __cplusplus
+# ifndef inline
+# define inline __inline
+# endif
+#endif
+*/
+
+// #define lfind _lfind
diff --git a/Source/LibTIFF/tif_config.h.in b/Source/LibTIFF/tif_config.h.in
new file mode 100644
index 0000000..01e54de
--- /dev/null
+++ b/Source/LibTIFF/tif_config.h.in
@@ -0,0 +1,309 @@
+/* libtiff/tif_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Support CCITT Group 3 & 4 algorithms */
+#undef CCITT_SUPPORT
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#undef CHECK_JPEG_YCBCR_SUBSAMPLING
+
+/* Support C++ stream API (requires C++ compiler) */
+#undef CXX_SUPPORT
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#undef DEFAULT_EXTRASAMPLE_AS_ALPHA
+
+/* Use the Apple OpenGL framework. */
+#undef HAVE_APPLE_OPENGL_FRAMEWORK
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the `floor' function. */
+#undef HAVE_FLOOR
+
+/* Define to 1 if you have the `getopt' function. */
+#undef HAVE_GETOPT
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#undef HAVE_IEEEFP
+
+/* Define to 1 if the system has the type `int16'. */
+#undef HAVE_INT16
+
+/* Define to 1 if the system has the type `int32'. */
+#undef HAVE_INT32
+
+/* Define to 1 if the system has the type `int8'. */
+#undef HAVE_INT8
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define to 1 if you have the `isascii' function. */
+#undef HAVE_ISASCII
+
+/* Define to 1 if you have the `jbg_newlen' function. */
+#undef HAVE_JBG_NEWLEN
+
+/* Define to 1 if you have the `lfind' function. */
+#undef HAVE_LFIND
+
+/* Define to 1 if you have the `c' library (-lc). */
+#undef HAVE_LIBC
+
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memmove' function. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the `mmap' function. */
+#undef HAVE_MMAP
+
+/* Define to 1 if you have the `pow' function. */
+#undef HAVE_POW
+
+/* Define if you have POSIX threads libraries and header files. */
+#undef HAVE_PTHREAD
+
+/* Define to 1 if you have the <search.h> header file. */
+#undef HAVE_SEARCH_H
+
+/* Define to 1 if you have the `setmode' function. */
+#undef HAVE_SETMODE
+
+/* Define to 1 if you have the `sqrt' function. */
+#undef HAVE_SQRT
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define to 1 if you have the `strtoul' function. */
+#undef HAVE_STRTOUL
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the <windows.h> header file. */
+#undef HAVE_WINDOWS_H
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
+#undef HOST_BIGENDIAN
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#undef HOST_FILLORDER
+
+/* Support ISO JBIG compression (requires JBIG-KIT library) */
+#undef JBIG_SUPPORT
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#undef JPEG_SUPPORT
+
+/* Support LogLuv high dynamic range encoding */
+#undef LOGLUV_SUPPORT
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Support LZW algorithm */
+#undef LZW_SUPPORT
+
+/* Support Microsoft Document Imaging format */
+#undef MDI_SUPPORT
+
+/* Support NeXT 2-bit RLE algorithm */
+#undef NEXT_SUPPORT
+
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Support Old JPEG compresson (read-only) */
+#undef OJPEG_SUPPORT
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Support Macintosh PackBits algorithm */
+#undef PACKBITS_SUPPORT
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+#undef PIXARLOG_SUPPORT
+
+/* Define to necessary symbol if this constant uses a non-standard name on
+ your system. */
+#undef PTHREAD_CREATE_JOINABLE
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `signed long', as computed by sizeof. */
+#undef SIZEOF_SIGNED_LONG
+
+/* The size of `signed long long', as computed by sizeof. */
+#undef SIZEOF_SIGNED_LONG_LONG
+
+/* The size of `unsigned long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG
+
+/* The size of `unsigned long long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG_LONG
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of specified size to reduce memory usage) */
+#undef STRIPCHOP_DEFAULT
+
+/* Default size of the strip in bytes (when strip chopping enabled) */
+#undef STRIP_SIZE_DEFAULT
+
+/* Enable SubIFD tag (330) support */
+#undef SUBIFD_SUPPORT
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#undef THUNDER_SUPPORT
+
+/* Signed 64-bit type formatter */
+#undef TIFF_INT64_FORMAT
+
+/* Signed 64-bit type */
+#undef TIFF_INT64_T
+
+/* Unsigned 64-bit type formatter */
+#undef TIFF_UINT64_FORMAT
+
+/* Unsigned 64-bit type */
+#undef TIFF_UINT64_T
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Support Deflate compression */
+#undef ZIP_SUPPORT
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to `long int' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/Source/LibTIFF/tif_config.vc.h b/Source/LibTIFF/tif_config.vc.h
new file mode 100644
index 0000000..d9caecf
--- /dev/null
+++ b/Source/LibTIFF/tif_config.vc.h
@@ -0,0 +1,56 @@
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* Define to 1 if you have the `jbg_newlen' function. */
+#define HAVE_JBG_NEWLEN 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define to 1 if you have the <search.h> header file. */
+#define HAVE_SEARCH_H 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Signed 64-bit type */
+#define TIFF_INT64_T signed __int64
+
+/* Unsigned 64-bit type */
+#define TIFF_UINT64_T unsigned __int64
+
+/* Set the native cpu bit order */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+# ifndef inline
+# define inline __inline
+# endif
+#endif
+
+#define lfind _lfind
diff --git a/Source/LibTIFF/tif_config.wince.h b/Source/LibTIFF/tif_config.wince.h
new file mode 100644
index 0000000..fc75fa3
--- /dev/null
+++ b/Source/LibTIFF/tif_config.wince.h
@@ -0,0 +1,67 @@
+/* $Id: tif_config.wince.h,v 1.11 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * TIFF library configuration header for Windows CE platform.
+ */
+#ifndef _WIN32_WCE
+# error This version of tif_config.h header is dedicated for Windows CE platform!
+#endif
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* Define to 1 if you have the `jbg_newlen' function. */
+#define HAVE_JBG_NEWLEN 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#define HAVE_IO_H 1
+
+/* Define to 1 if you have the <search.h> header file. */
+#define HAVE_SEARCH_H 1
+
+/* Define to 1 if you have the `setmode' function. */
+#define HAVE_SETMODE 1
+
+/* Define to 1 if you have the `bsearch' function. */
+#define HAVE_BSEARCH 1
+#define bsearch wceex_bsearch
+
+/* Define to 1 if you have the `lfind' function. */
+#define HAVE_LFIND 1
+#define lfind wceex_lfind
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Set the native cpu bit order */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+# ifndef inline
+# define inline __inline
+# endif
+#endif
+
+
diff --git a/Source/LibTIFF/tif_dir.c b/Source/LibTIFF/tif_dir.c
new file mode 100644
index 0000000..30e0271
--- /dev/null
+++ b/Source/LibTIFF/tif_dir.c
@@ -0,0 +1,1369 @@
+/* $Id: tif_dir.c,v 1.28 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Tag Get & Set Routines.
+ * (and also some miscellaneous stuff)
+ */
+#include "tiffiop.h"
+
+/*
+ * These are used in the backwards compatibility code...
+ */
+#define DATATYPE_VOID 0 /* !untyped data */
+#define DATATYPE_INT 1 /* !signed integer data */
+#define DATATYPE_UINT 2 /* !unsigned integer data */
+#define DATATYPE_IEEEFP 3 /* !IEEE floating point data */
+
+static void
+setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
+{
+ if (*vpp)
+ _TIFFfree(*vpp), *vpp = 0;
+ if (vp) {
+ tsize_t bytes = nmemb * elem_size;
+ if (elem_size && bytes / elem_size == nmemb)
+ *vpp = (void*) _TIFFmalloc(bytes);
+ if (*vpp)
+ _TIFFmemcpy(*vpp, vp, bytes);
+ }
+}
+void _TIFFsetByteArray(void** vpp, void* vp, uint32 n)
+ { setByteArray(vpp, vp, n, 1); }
+void _TIFFsetString(char** cpp, char* cp)
+ { setByteArray((void**) cpp, (void*) cp, strlen(cp)+1, 1); }
+void _TIFFsetNString(char** cpp, char* cp, uint32 n)
+ { setByteArray((void**) cpp, (void*) cp, n, 1); }
+void _TIFFsetShortArray(uint16** wpp, uint16* wp, uint32 n)
+ { setByteArray((void**) wpp, (void*) wp, n, sizeof (uint16)); }
+void _TIFFsetLongArray(uint32** lpp, uint32* lp, uint32 n)
+ { setByteArray((void**) lpp, (void*) lp, n, sizeof (uint32)); }
+void _TIFFsetFloatArray(float** fpp, float* fp, uint32 n)
+ { setByteArray((void**) fpp, (void*) fp, n, sizeof (float)); }
+void _TIFFsetDoubleArray(double** dpp, double* dp, uint32 n)
+ { setByteArray((void**) dpp, (void*) dp, n, sizeof (double)); }
+
+/*
+ * Install extra samples information.
+ */
+static int
+setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
+{
+/* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
+#define EXTRASAMPLE_COREL_UNASSALPHA 999
+
+ uint16* va;
+ uint32 i;
+
+ *v = va_arg(ap, uint32);
+ if ((uint16) *v > td->td_samplesperpixel)
+ return 0;
+ va = va_arg(ap, uint16*);
+ if (*v > 0 && va == NULL) /* typically missing param */
+ return 0;
+ for (i = 0; i < *v; i++) {
+ if (va[i] > EXTRASAMPLE_UNASSALPHA) {
+ /*
+ * XXX: Corel Draw is known to produce incorrect
+ * ExtraSamples tags which must be patched here if we
+ * want to be able to open some of the damaged TIFF
+ * files:
+ */
+ if (va[i] == EXTRASAMPLE_COREL_UNASSALPHA)
+ va[i] = EXTRASAMPLE_UNASSALPHA;
+ else
+ return 0;
+ }
+ }
+ td->td_extrasamples = (uint16) *v;
+ _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
+ return 1;
+
+#undef EXTRASAMPLE_COREL_UNASSALPHA
+}
+
+static uint32
+checkInkNamesString(TIFF* tif, uint32 slen, const char* s)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ uint16 i = td->td_samplesperpixel;
+
+ if (slen > 0) {
+ const char* ep = s+slen;
+ const char* cp = s;
+ for (; i > 0; i--) {
+ for (; *cp != '\0'; cp++)
+ if (cp >= ep)
+ goto bad;
+ cp++; /* skip \0 */
+ }
+ return (cp-s);
+ }
+bad:
+ TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
+ "%s: Invalid InkNames value; expecting %d names, found %d",
+ tif->tif_name,
+ td->td_samplesperpixel,
+ td->td_samplesperpixel-i);
+ return (0);
+}
+
+static int
+_TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ static const char module[] = "_TIFFVSetField";
+
+ TIFFDirectory* td = &tif->tif_dir;
+ int status = 1;
+ uint32 v32, i, v;
+ char* s;
+
+ switch (tag) {
+ case TIFFTAG_SUBFILETYPE:
+ td->td_subfiletype = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_IMAGEWIDTH:
+ td->td_imagewidth = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_IMAGELENGTH:
+ td->td_imagelength = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_BITSPERSAMPLE:
+ td->td_bitspersample = (uint16) va_arg(ap, int);
+ /*
+ * If the data require post-decoding processing to byte-swap
+ * samples, set it up here. Note that since tags are required
+ * to be ordered, compression code can override this behaviour
+ * in the setup method if it wants to roll the post decoding
+ * work in with its normal work.
+ */
+ if (tif->tif_flags & TIFF_SWAB) {
+ if (td->td_bitspersample == 16)
+ tif->tif_postdecode = _TIFFSwab16BitData;
+ else if (td->td_bitspersample == 24)
+ tif->tif_postdecode = _TIFFSwab24BitData;
+ else if (td->td_bitspersample == 32)
+ tif->tif_postdecode = _TIFFSwab32BitData;
+ else if (td->td_bitspersample == 64)
+ tif->tif_postdecode = _TIFFSwab64BitData;
+ else if (td->td_bitspersample == 128) /* two 64's */
+ tif->tif_postdecode = _TIFFSwab64BitData;
+ }
+ break;
+ case TIFFTAG_COMPRESSION:
+ v = va_arg(ap, uint32) & 0xffff;
+ /*
+ * If we're changing the compression scheme, the notify the
+ * previous module so that it can cleanup any state it's
+ * setup.
+ */
+ if (TIFFFieldSet(tif, FIELD_COMPRESSION)) {
+ if (td->td_compression == v)
+ break;
+ (*tif->tif_cleanup)(tif);
+ tif->tif_flags &= ~TIFF_CODERSETUP;
+ }
+ /*
+ * Setup new compression routine state.
+ */
+ if( (status = TIFFSetCompressionScheme(tif, v)) != 0 )
+ td->td_compression = (uint16) v;
+ else
+ status = 0;
+ break;
+ case TIFFTAG_PHOTOMETRIC:
+ td->td_photometric = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_THRESHHOLDING:
+ td->td_threshholding = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_FILLORDER:
+ v = va_arg(ap, uint32);
+ if (v != FILLORDER_LSB2MSB && v != FILLORDER_MSB2LSB)
+ goto badvalue;
+ td->td_fillorder = (uint16) v;
+ break;
+ case TIFFTAG_ORIENTATION:
+ v = va_arg(ap, uint32);
+ if (v < ORIENTATION_TOPLEFT || ORIENTATION_LEFTBOT < v)
+ goto badvalue;
+ else
+ td->td_orientation = (uint16) v;
+ break;
+ case TIFFTAG_SAMPLESPERPIXEL:
+ /* XXX should cross check -- e.g. if pallette, then 1 */
+ v = va_arg(ap, uint32);
+ if (v == 0)
+ goto badvalue;
+ td->td_samplesperpixel = (uint16) v;
+ break;
+ case TIFFTAG_ROWSPERSTRIP:
+ v32 = va_arg(ap, uint32);
+ if (v32 == 0)
+ goto badvalue32;
+ td->td_rowsperstrip = v32;
+ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
+ td->td_tilelength = v32;
+ td->td_tilewidth = td->td_imagewidth;
+ }
+ break;
+ case TIFFTAG_MINSAMPLEVALUE:
+ td->td_minsamplevalue = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_MAXSAMPLEVALUE:
+ td->td_maxsamplevalue = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ td->td_sminsamplevalue = va_arg(ap, double);
+ break;
+ case TIFFTAG_SMAXSAMPLEVALUE:
+ td->td_smaxsamplevalue = va_arg(ap, double);
+ break;
+ case TIFFTAG_XRESOLUTION:
+ td->td_xresolution = (float) va_arg(ap, double);
+ break;
+ case TIFFTAG_YRESOLUTION:
+ td->td_yresolution = (float) va_arg(ap, double);
+ break;
+ case TIFFTAG_PLANARCONFIG:
+ v = va_arg(ap, uint32);
+ if (v != PLANARCONFIG_CONTIG && v != PLANARCONFIG_SEPARATE)
+ goto badvalue;
+ td->td_planarconfig = (uint16) v;
+ break;
+ case TIFFTAG_XPOSITION:
+ td->td_xposition = (float) va_arg(ap, double);
+ break;
+ case TIFFTAG_YPOSITION:
+ td->td_yposition = (float) va_arg(ap, double);
+ break;
+ case TIFFTAG_RESOLUTIONUNIT:
+ v = va_arg(ap, uint32);
+ if (v < RESUNIT_NONE || RESUNIT_CENTIMETER < v)
+ goto badvalue;
+ td->td_resolutionunit = (uint16) v;
+ break;
+ case TIFFTAG_PAGENUMBER:
+ td->td_pagenumber[0] = (uint16) va_arg(ap, int);
+ td->td_pagenumber[1] = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_HALFTONEHINTS:
+ td->td_halftonehints[0] = (uint16) va_arg(ap, int);
+ td->td_halftonehints[1] = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_COLORMAP:
+ v32 = (uint32)(1L<<td->td_bitspersample);
+ _TIFFsetShortArray(&td->td_colormap[0], va_arg(ap, uint16*), v32);
+ _TIFFsetShortArray(&td->td_colormap[1], va_arg(ap, uint16*), v32);
+ _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
+ break;
+ case TIFFTAG_EXTRASAMPLES:
+ if (!setExtraSamples(td, ap, &v))
+ goto badvalue;
+ break;
+ case TIFFTAG_MATTEING:
+ td->td_extrasamples = (uint16) (va_arg(ap, int) != 0);
+ if (td->td_extrasamples) {
+ uint16 sv = EXTRASAMPLE_ASSOCALPHA;
+ _TIFFsetShortArray(&td->td_sampleinfo, &sv, 1);
+ }
+ break;
+ case TIFFTAG_TILEWIDTH:
+ v32 = va_arg(ap, uint32);
+ if (v32 % 16) {
+ if (tif->tif_mode != O_RDONLY)
+ goto badvalue32;
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "Nonstandard tile width %d, convert file", v32);
+ }
+ td->td_tilewidth = v32;
+ tif->tif_flags |= TIFF_ISTILED;
+ break;
+ case TIFFTAG_TILELENGTH:
+ v32 = va_arg(ap, uint32);
+ if (v32 % 16) {
+ if (tif->tif_mode != O_RDONLY)
+ goto badvalue32;
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "Nonstandard tile length %d, convert file", v32);
+ }
+ td->td_tilelength = v32;
+ tif->tif_flags |= TIFF_ISTILED;
+ break;
+ case TIFFTAG_TILEDEPTH:
+ v32 = va_arg(ap, uint32);
+ if (v32 == 0)
+ goto badvalue32;
+ td->td_tiledepth = v32;
+ break;
+ case TIFFTAG_DATATYPE:
+ v = va_arg(ap, uint32);
+ switch (v) {
+ case DATATYPE_VOID: v = SAMPLEFORMAT_VOID; break;
+ case DATATYPE_INT: v = SAMPLEFORMAT_INT; break;
+ case DATATYPE_UINT: v = SAMPLEFORMAT_UINT; break;
+ case DATATYPE_IEEEFP: v = SAMPLEFORMAT_IEEEFP;break;
+ default: goto badvalue;
+ }
+ td->td_sampleformat = (uint16) v;
+ break;
+ case TIFFTAG_SAMPLEFORMAT:
+ v = va_arg(ap, uint32);
+ if (v < SAMPLEFORMAT_UINT || SAMPLEFORMAT_COMPLEXIEEEFP < v)
+ goto badvalue;
+ td->td_sampleformat = (uint16) v;
+
+ /* Try to fix up the SWAB function for complex data. */
+ if( td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
+ && td->td_bitspersample == 32
+ && tif->tif_postdecode == _TIFFSwab32BitData )
+ tif->tif_postdecode = _TIFFSwab16BitData;
+ else if( (td->td_sampleformat == SAMPLEFORMAT_COMPLEXINT
+ || td->td_sampleformat == SAMPLEFORMAT_COMPLEXIEEEFP)
+ && td->td_bitspersample == 64
+ && tif->tif_postdecode == _TIFFSwab64BitData )
+ tif->tif_postdecode = _TIFFSwab32BitData;
+ break;
+ case TIFFTAG_IMAGEDEPTH:
+ td->td_imagedepth = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_SUBIFD:
+ if ((tif->tif_flags & TIFF_INSUBIFD) == 0) {
+ td->td_nsubifd = (uint16) va_arg(ap, int);
+ _TIFFsetLongArray(&td->td_subifd, va_arg(ap, uint32*),
+ (long) td->td_nsubifd);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Sorry, cannot nest SubIFDs",
+ tif->tif_name);
+ status = 0;
+ }
+ break;
+ case TIFFTAG_YCBCRPOSITIONING:
+ td->td_ycbcrpositioning = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ td->td_ycbcrsubsampling[0] = (uint16) va_arg(ap, int);
+ td->td_ycbcrsubsampling[1] = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_TRANSFERFUNCTION:
+ v = (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1;
+ for (i = 0; i < v; i++)
+ _TIFFsetShortArray(&td->td_transferfunction[i],
+ va_arg(ap, uint16*), 1L<<td->td_bitspersample);
+ break;
+ case TIFFTAG_INKNAMES:
+ v = va_arg(ap, uint32);
+ s = va_arg(ap, char*);
+ v = checkInkNamesString(tif, v, s);
+ status = v > 0;
+ if( v > 0 ) {
+ _TIFFsetNString(&td->td_inknames, s, v);
+ td->td_inknameslen = v;
+ }
+ break;
+ default: {
+ TIFFTagValue *tv;
+ int tv_size, iCustom;
+ const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+
+ /*
+ * This can happen if multiple images are open with different
+ * codecs which have private tags. The global tag information
+ * table may then have tags that are valid for one file but not
+ * the other. If the client tries to set a tag that is not valid
+ * for the image's codec then we'll arrive here. This
+ * happens, for example, when tiffcp is used to convert between
+ * compression schemes and codec-specific tags are blindly copied.
+ */
+ if(fip == NULL || fip->field_bit != FIELD_CUSTOM) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Invalid %stag \"%s\" (not supported by codec)",
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "",
+ fip ? fip->field_name : "Unknown");
+ status = 0;
+ break;
+ }
+
+ /*
+ * Find the existing entry for this custom value.
+ */
+ tv = NULL;
+ for (iCustom = 0; iCustom < td->td_customValueCount; iCustom++) {
+ if (td->td_customValues[iCustom].info->field_tag == tag) {
+ tv = td->td_customValues + iCustom;
+ if (tv->value != NULL) {
+ _TIFFfree(tv->value);
+ tv->value = NULL;
+ }
+ break;
+ }
+ }
+
+ /*
+ * Grow the custom list if the entry was not found.
+ */
+ if(tv == NULL) {
+ TIFFTagValue *new_customValues;
+
+ td->td_customValueCount++;
+ new_customValues = (TIFFTagValue *)
+ _TIFFrealloc(td->td_customValues,
+ sizeof(TIFFTagValue) * td->td_customValueCount);
+ if (!new_customValues) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Failed to allocate space for list of custom values",
+ tif->tif_name);
+ status = 0;
+ goto end;
+ }
+
+ td->td_customValues = new_customValues;
+
+ tv = td->td_customValues + (td->td_customValueCount - 1);
+ tv->info = fip;
+ tv->value = NULL;
+ tv->count = 0;
+ }
+
+ /*
+ * Set custom value ... save a copy of the custom tag value.
+ */
+ tv_size = _TIFFDataSize(fip->field_type);
+ if (tv_size == 0) {
+ status = 0;
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Bad field type %d for \"%s\"",
+ tif->tif_name, fip->field_type,
+ fip->field_name);
+ goto end;
+ }
+
+ if(fip->field_passcount) {
+ if (fip->field_writecount == TIFF_VARIABLE2)
+ tv->count = (uint32) va_arg(ap, uint32);
+ else
+ tv->count = (int) va_arg(ap, int);
+ } else if (fip->field_writecount == TIFF_VARIABLE
+ || fip->field_writecount == TIFF_VARIABLE2)
+ tv->count = 1;
+ else if (fip->field_writecount == TIFF_SPP)
+ tv->count = td->td_samplesperpixel;
+ else
+ tv->count = fip->field_writecount;
+
+
+ if (fip->field_type == TIFF_ASCII)
+ _TIFFsetString((char **)&tv->value, va_arg(ap, char *));
+ else {
+ tv->value = _TIFFCheckMalloc(tif, tv_size, tv->count,
+ "Tag Value");
+ if (!tv->value) {
+ status = 0;
+ goto end;
+ }
+
+ if ((fip->field_passcount
+ || fip->field_writecount == TIFF_VARIABLE
+ || fip->field_writecount == TIFF_VARIABLE2
+ || fip->field_writecount == TIFF_SPP
+ || tv->count > 1)
+ && fip->field_tag != TIFFTAG_PAGENUMBER
+ && fip->field_tag != TIFFTAG_HALFTONEHINTS
+ && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
+ && fip->field_tag != TIFFTAG_DOTRANGE) {
+ _TIFFmemcpy(tv->value, va_arg(ap, void *),
+ tv->count * tv_size);
+ } else {
+ /*
+ * XXX: The following loop required to handle
+ * TIFFTAG_PAGENUMBER, TIFFTAG_HALFTONEHINTS,
+ * TIFFTAG_YCBCRSUBSAMPLING and TIFFTAG_DOTRANGE tags.
+ * These tags are actually arrays and should be passed as
+ * array pointers to TIFFSetField() function, but actually
+ * passed as a list of separate values. This behaviour
+ * must be changed in the future!
+ */
+ int i;
+ char *val = (char *)tv->value;
+
+ for (i = 0; i < tv->count; i++, val += tv_size) {
+ switch (fip->field_type) {
+ case TIFF_BYTE:
+ case TIFF_UNDEFINED:
+ {
+ uint8 v = (uint8)va_arg(ap, int);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_SBYTE:
+ {
+ int8 v = (int8)va_arg(ap, int);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_SHORT:
+ {
+ uint16 v = (uint16)va_arg(ap, int);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_SSHORT:
+ {
+ int16 v = (int16)va_arg(ap, int);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_IFD:
+ {
+ uint32 v = va_arg(ap, uint32);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_SLONG:
+ {
+ int32 v = va_arg(ap, int32);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ case TIFF_FLOAT:
+ {
+ float v = (float)va_arg(ap, double);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ case TIFF_DOUBLE:
+ {
+ double v = va_arg(ap, double);
+ _TIFFmemcpy(val, &v, tv_size);
+ }
+ break;
+ default:
+ _TIFFmemset(val, 0, tv_size);
+ status = 0;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (status) {
+ TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ }
+
+end:
+ va_end(ap);
+ return (status);
+badvalue:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Bad value %d for \"%s\" tag",
+ tif->tif_name, v,
+ _TIFFFieldWithTag(tif, tag)->field_name);
+ va_end(ap);
+ return (0);
+badvalue32:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Bad value %u for \"%s\" tag",
+ tif->tif_name, v32,
+ _TIFFFieldWithTag(tif, tag)->field_name);
+ va_end(ap);
+ return (0);
+}
+
+/*
+ * Return 1/0 according to whether or not
+ * it is permissible to set the tag's value.
+ * Note that we allow ImageLength to be changed
+ * so that we can append and extend to images.
+ * Any other tag may not be altered once writing
+ * has commenced, unless its value has no effect
+ * on the format of the data that is written.
+ */
+static int
+OkToChangeTag(TIFF* tif, ttag_t tag)
+{
+ const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+ if (!fip) { /* unknown tag */
+ TIFFErrorExt(tif->tif_clientdata, "TIFFSetField", "%s: Unknown %stag %u",
+ tif->tif_name, isPseudoTag(tag) ? "pseudo-" : "", tag);
+ return (0);
+ }
+ if (tag != TIFFTAG_IMAGELENGTH && (tif->tif_flags & TIFF_BEENWRITING) &&
+ !fip->field_oktochange) {
+ /*
+ * Consult info table to see if tag can be changed
+ * after we've started writing. We only allow changes
+ * to those tags that don't/shouldn't affect the
+ * compression and/or format of the data.
+ */
+ TIFFErrorExt(tif->tif_clientdata, "TIFFSetField",
+ "%s: Cannot modify tag \"%s\" while writing",
+ tif->tif_name, fip->field_name);
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Record the value of a field in the
+ * internal directory structure. The
+ * field will be written to the file
+ * when/if the directory structure is
+ * updated.
+ */
+int
+TIFFSetField(TIFF* tif, ttag_t tag, ...)
+{
+ va_list ap;
+ int status;
+
+ va_start(ap, tag);
+ status = TIFFVSetField(tif, tag, ap);
+ va_end(ap);
+ return (status);
+}
+
+/*
+ * Like TIFFSetField, but taking a varargs
+ * parameter list. This routine is useful
+ * for building higher-level interfaces on
+ * top of the library.
+ */
+int
+TIFFVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ return OkToChangeTag(tif, tag) ?
+ (*tif->tif_tagmethods.vsetfield)(tif, tag, ap) : 0;
+}
+
+static int
+_TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ int ret_val = 1;
+
+ switch (tag) {
+ case TIFFTAG_SUBFILETYPE:
+ *va_arg(ap, uint32*) = td->td_subfiletype;
+ break;
+ case TIFFTAG_IMAGEWIDTH:
+ *va_arg(ap, uint32*) = td->td_imagewidth;
+ break;
+ case TIFFTAG_IMAGELENGTH:
+ *va_arg(ap, uint32*) = td->td_imagelength;
+ break;
+ case TIFFTAG_BITSPERSAMPLE:
+ *va_arg(ap, uint16*) = td->td_bitspersample;
+ break;
+ case TIFFTAG_COMPRESSION:
+ *va_arg(ap, uint16*) = td->td_compression;
+ break;
+ case TIFFTAG_PHOTOMETRIC:
+ *va_arg(ap, uint16*) = td->td_photometric;
+ break;
+ case TIFFTAG_THRESHHOLDING:
+ *va_arg(ap, uint16*) = td->td_threshholding;
+ break;
+ case TIFFTAG_FILLORDER:
+ *va_arg(ap, uint16*) = td->td_fillorder;
+ break;
+ case TIFFTAG_ORIENTATION:
+ *va_arg(ap, uint16*) = td->td_orientation;
+ break;
+ case TIFFTAG_SAMPLESPERPIXEL:
+ *va_arg(ap, uint16*) = td->td_samplesperpixel;
+ break;
+ case TIFFTAG_ROWSPERSTRIP:
+ *va_arg(ap, uint32*) = td->td_rowsperstrip;
+ break;
+ case TIFFTAG_MINSAMPLEVALUE:
+ *va_arg(ap, uint16*) = td->td_minsamplevalue;
+ break;
+ case TIFFTAG_MAXSAMPLEVALUE:
+ *va_arg(ap, uint16*) = td->td_maxsamplevalue;
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ *va_arg(ap, double*) = td->td_sminsamplevalue;
+ break;
+ case TIFFTAG_SMAXSAMPLEVALUE:
+ *va_arg(ap, double*) = td->td_smaxsamplevalue;
+ break;
+ case TIFFTAG_XRESOLUTION:
+ *va_arg(ap, float*) = td->td_xresolution;
+ break;
+ case TIFFTAG_YRESOLUTION:
+ *va_arg(ap, float*) = td->td_yresolution;
+ break;
+ case TIFFTAG_PLANARCONFIG:
+ *va_arg(ap, uint16*) = td->td_planarconfig;
+ break;
+ case TIFFTAG_XPOSITION:
+ *va_arg(ap, float*) = td->td_xposition;
+ break;
+ case TIFFTAG_YPOSITION:
+ *va_arg(ap, float*) = td->td_yposition;
+ break;
+ case TIFFTAG_RESOLUTIONUNIT:
+ *va_arg(ap, uint16*) = td->td_resolutionunit;
+ break;
+ case TIFFTAG_PAGENUMBER:
+ *va_arg(ap, uint16*) = td->td_pagenumber[0];
+ *va_arg(ap, uint16*) = td->td_pagenumber[1];
+ break;
+ case TIFFTAG_HALFTONEHINTS:
+ *va_arg(ap, uint16*) = td->td_halftonehints[0];
+ *va_arg(ap, uint16*) = td->td_halftonehints[1];
+ break;
+ case TIFFTAG_COLORMAP:
+ *va_arg(ap, uint16**) = td->td_colormap[0];
+ *va_arg(ap, uint16**) = td->td_colormap[1];
+ *va_arg(ap, uint16**) = td->td_colormap[2];
+ break;
+ case TIFFTAG_STRIPOFFSETS:
+ case TIFFTAG_TILEOFFSETS:
+ *va_arg(ap, uint32**) = td->td_stripoffset;
+ break;
+ case TIFFTAG_STRIPBYTECOUNTS:
+ case TIFFTAG_TILEBYTECOUNTS:
+ *va_arg(ap, uint32**) = td->td_stripbytecount;
+ break;
+ case TIFFTAG_MATTEING:
+ *va_arg(ap, uint16*) =
+ (td->td_extrasamples == 1 &&
+ td->td_sampleinfo[0] == EXTRASAMPLE_ASSOCALPHA);
+ break;
+ case TIFFTAG_EXTRASAMPLES:
+ *va_arg(ap, uint16*) = td->td_extrasamples;
+ *va_arg(ap, uint16**) = td->td_sampleinfo;
+ break;
+ case TIFFTAG_TILEWIDTH:
+ *va_arg(ap, uint32*) = td->td_tilewidth;
+ break;
+ case TIFFTAG_TILELENGTH:
+ *va_arg(ap, uint32*) = td->td_tilelength;
+ break;
+ case TIFFTAG_TILEDEPTH:
+ *va_arg(ap, uint32*) = td->td_tiledepth;
+ break;
+ case TIFFTAG_DATATYPE:
+ switch (td->td_sampleformat) {
+ case SAMPLEFORMAT_UINT:
+ *va_arg(ap, uint16*) = DATATYPE_UINT;
+ break;
+ case SAMPLEFORMAT_INT:
+ *va_arg(ap, uint16*) = DATATYPE_INT;
+ break;
+ case SAMPLEFORMAT_IEEEFP:
+ *va_arg(ap, uint16*) = DATATYPE_IEEEFP;
+ break;
+ case SAMPLEFORMAT_VOID:
+ *va_arg(ap, uint16*) = DATATYPE_VOID;
+ break;
+ }
+ break;
+ case TIFFTAG_SAMPLEFORMAT:
+ *va_arg(ap, uint16*) = td->td_sampleformat;
+ break;
+ case TIFFTAG_IMAGEDEPTH:
+ *va_arg(ap, uint32*) = td->td_imagedepth;
+ break;
+ case TIFFTAG_SUBIFD:
+ *va_arg(ap, uint16*) = td->td_nsubifd;
+ *va_arg(ap, uint32**) = td->td_subifd;
+ break;
+ case TIFFTAG_YCBCRPOSITIONING:
+ *va_arg(ap, uint16*) = td->td_ycbcrpositioning;
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[0];
+ *va_arg(ap, uint16*) = td->td_ycbcrsubsampling[1];
+ break;
+ case TIFFTAG_TRANSFERFUNCTION:
+ *va_arg(ap, uint16**) = td->td_transferfunction[0];
+ if (td->td_samplesperpixel - td->td_extrasamples > 1) {
+ *va_arg(ap, uint16**) = td->td_transferfunction[1];
+ *va_arg(ap, uint16**) = td->td_transferfunction[2];
+ }
+ break;
+ case TIFFTAG_INKNAMES:
+ *va_arg(ap, char**) = td->td_inknames;
+ break;
+ default:
+ {
+ const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+ int i;
+
+ /*
+ * This can happen if multiple images are open with different
+ * codecs which have private tags. The global tag information
+ * table may then have tags that are valid for one file but not
+ * the other. If the client tries to get a tag that is not valid
+ * for the image's codec then we'll arrive here.
+ */
+ if( fip == NULL || fip->field_bit != FIELD_CUSTOM )
+ {
+ TIFFErrorExt(tif->tif_clientdata, "_TIFFVGetField",
+ "%s: Invalid %stag \"%s\" "
+ "(not supported by codec)",
+ tif->tif_name,
+ isPseudoTag(tag) ? "pseudo-" : "",
+ fip ? fip->field_name : "Unknown");
+ ret_val = 0;
+ break;
+ }
+
+ /*
+ * Do we have a custom value?
+ */
+ ret_val = 0;
+ for (i = 0; i < td->td_customValueCount; i++) {
+ TIFFTagValue *tv = td->td_customValues + i;
+
+ if (tv->info->field_tag != tag)
+ continue;
+
+ if (fip->field_passcount) {
+ if (fip->field_readcount == TIFF_VARIABLE2)
+ *va_arg(ap, uint32*) = (uint32)tv->count;
+ else /* Assume TIFF_VARIABLE */
+ *va_arg(ap, uint16*) = (uint16)tv->count;
+ *va_arg(ap, void **) = tv->value;
+ ret_val = 1;
+ } else {
+ if ((fip->field_type == TIFF_ASCII
+ || fip->field_readcount == TIFF_VARIABLE
+ || fip->field_readcount == TIFF_VARIABLE2
+ || fip->field_readcount == TIFF_SPP
+ || tv->count > 1)
+ && fip->field_tag != TIFFTAG_PAGENUMBER
+ && fip->field_tag != TIFFTAG_HALFTONEHINTS
+ && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
+ && fip->field_tag != TIFFTAG_DOTRANGE) {
+ *va_arg(ap, void **) = tv->value;
+ ret_val = 1;
+ } else {
+ int j;
+ char *val = (char *)tv->value;
+
+ for (j = 0; j < tv->count;
+ j++, val += _TIFFDataSize(tv->info->field_type)) {
+ switch (fip->field_type) {
+ case TIFF_BYTE:
+ case TIFF_UNDEFINED:
+ *va_arg(ap, uint8*) =
+ *(uint8 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SBYTE:
+ *va_arg(ap, int8*) =
+ *(int8 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SHORT:
+ *va_arg(ap, uint16*) =
+ *(uint16 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SSHORT:
+ *va_arg(ap, int16*) =
+ *(int16 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_LONG:
+ case TIFF_IFD:
+ *va_arg(ap, uint32*) =
+ *(uint32 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_SLONG:
+ *va_arg(ap, int32*) =
+ *(int32 *)val;
+ ret_val = 1;
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ case TIFF_FLOAT:
+ *va_arg(ap, float*) =
+ *(float *)val;
+ ret_val = 1;
+ break;
+ case TIFF_DOUBLE:
+ *va_arg(ap, double*) =
+ *(double *)val;
+ ret_val = 1;
+ break;
+ default:
+ ret_val = 0;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ return(ret_val);
+}
+
+/*
+ * Return the value of a field in the
+ * internal directory structure.
+ */
+int
+TIFFGetField(TIFF* tif, ttag_t tag, ...)
+{
+ int status;
+ va_list ap;
+
+ va_start(ap, tag);
+ status = TIFFVGetField(tif, tag, ap);
+ va_end(ap);
+ return (status);
+}
+
+/*
+ * Like TIFFGetField, but taking a varargs
+ * parameter list. This routine is useful
+ * for building higher-level interfaces on
+ * top of the library.
+ */
+int
+TIFFVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+ return (fip && (isPseudoTag(tag) || TIFFFieldSet(tif, fip->field_bit)) ?
+ (*tif->tif_tagmethods.vgetfield)(tif, tag, ap) : 0);
+}
+
+#define CleanupField(member) { \
+ if (td->member) { \
+ _TIFFfree(td->member); \
+ td->member = 0; \
+ } \
+}
+
+/*
+ * Release storage associated with a directory.
+ */
+void
+TIFFFreeDirectory(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ int i;
+
+ _TIFFmemset(td->td_fieldsset, 0, FIELD_SETLONGS);
+ CleanupField(td_colormap[0]);
+ CleanupField(td_colormap[1]);
+ CleanupField(td_colormap[2]);
+ CleanupField(td_sampleinfo);
+ CleanupField(td_subifd);
+ CleanupField(td_inknames);
+ CleanupField(td_transferfunction[0]);
+ CleanupField(td_transferfunction[1]);
+ CleanupField(td_transferfunction[2]);
+ CleanupField(td_stripoffset);
+ CleanupField(td_stripbytecount);
+ TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
+ TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
+
+ /* Cleanup custom tag values */
+ for( i = 0; i < td->td_customValueCount; i++ ) {
+ if (td->td_customValues[i].value)
+ _TIFFfree(td->td_customValues[i].value);
+ }
+
+ td->td_customValueCount = 0;
+ CleanupField(td_customValues);
+}
+#undef CleanupField
+
+/*
+ * Client Tag extension support (from Niles Ritter).
+ */
+static TIFFExtendProc _TIFFextender = (TIFFExtendProc) NULL;
+
+TIFFExtendProc
+TIFFSetTagExtender(TIFFExtendProc extender)
+{
+ TIFFExtendProc prev = _TIFFextender;
+ _TIFFextender = extender;
+ return (prev);
+}
+
+/*
+ * Setup for a new directory. Should we automatically call
+ * TIFFWriteDirectory() if the current one is dirty?
+ *
+ * The newly created directory will not exist on the file till
+ * TIFFWriteDirectory(), TIFFFlush() or TIFFClose() is called.
+ */
+int
+TIFFCreateDirectory(TIFF* tif)
+{
+ TIFFDefaultDirectory(tif);
+ tif->tif_diroff = 0;
+ tif->tif_nextdiroff = 0;
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32) -1;
+ tif->tif_curstrip = (tstrip_t) -1;
+
+ return 0;
+}
+
+/*
+ * Setup a default directory structure.
+ */
+int
+TIFFDefaultDirectory(TIFF* tif)
+{
+ register TIFFDirectory* td = &tif->tif_dir;
+
+ size_t tiffFieldInfoCount;
+ const TIFFFieldInfo *tiffFieldInfo =
+ _TIFFGetFieldInfo(&tiffFieldInfoCount);
+ _TIFFSetupFieldInfo(tif, tiffFieldInfo, tiffFieldInfoCount);
+
+ _TIFFmemset(td, 0, sizeof (*td));
+ td->td_fillorder = FILLORDER_MSB2LSB;
+ td->td_bitspersample = 1;
+ td->td_threshholding = THRESHHOLD_BILEVEL;
+ td->td_orientation = ORIENTATION_TOPLEFT;
+ td->td_samplesperpixel = 1;
+ td->td_rowsperstrip = (uint32) -1;
+ td->td_tilewidth = 0;
+ td->td_tilelength = 0;
+ td->td_tiledepth = 1;
+ td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
+ td->td_resolutionunit = RESUNIT_INCH;
+ td->td_sampleformat = SAMPLEFORMAT_UINT;
+ td->td_imagedepth = 1;
+ td->td_ycbcrsubsampling[0] = 2;
+ td->td_ycbcrsubsampling[1] = 2;
+ td->td_ycbcrpositioning = YCBCRPOSITION_CENTERED;
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ tif->tif_foundfield = NULL;
+ tif->tif_tagmethods.vsetfield = _TIFFVSetField;
+ tif->tif_tagmethods.vgetfield = _TIFFVGetField;
+ tif->tif_tagmethods.printdir = NULL;
+ /*
+ * Give client code a chance to install their own
+ * tag extensions & methods, prior to compression overloads.
+ */
+ if (_TIFFextender)
+ (*_TIFFextender)(tif);
+ (void) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+ /*
+ * NB: The directory is marked dirty as a result of setting
+ * up the default compression scheme. However, this really
+ * isn't correct -- we want TIFF_DIRTYDIRECT to be set only
+ * if the user does something. We could just do the setup
+ * by hand, but it seems better to use the normal mechanism
+ * (i.e. TIFFSetField).
+ */
+ tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+
+ /*
+ * As per http://bugzilla.remotesensing.org/show_bug.cgi?id=19
+ * we clear the ISTILED flag when setting up a new directory.
+ * Should we also be clearing stuff like INSUBIFD?
+ */
+ tif->tif_flags &= ~TIFF_ISTILED;
+
+ return (1);
+}
+
+static int
+TIFFAdvanceDirectory(TIFF* tif, uint32* nextdir, toff_t* off)
+{
+ static const char module[] = "TIFFAdvanceDirectory";
+ uint16 dircount;
+ if (isMapped(tif))
+ {
+ toff_t poff=*nextdir;
+ if (poff+sizeof(uint16) > tif->tif_size)
+ {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
+ tif->tif_name);
+ return (0);
+ }
+ _TIFFmemcpy(&dircount, tif->tif_base+poff, sizeof (uint16));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ poff+=sizeof (uint16)+dircount*sizeof (TIFFDirEntry);
+ if (off != NULL)
+ *off = poff;
+ if (((toff_t) (poff+sizeof (uint32))) > tif->tif_size)
+ {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
+ tif->tif_name);
+ return (0);
+ }
+ _TIFFmemcpy(nextdir, tif->tif_base+poff, sizeof (uint32));
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(nextdir);
+ return (1);
+ }
+ else
+ {
+ if (!SeekOK(tif, *nextdir) ||
+ !ReadOK(tif, &dircount, sizeof (uint16))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory count",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ if (off != NULL)
+ *off = TIFFSeekFile(tif,
+ dircount*sizeof (TIFFDirEntry), SEEK_CUR);
+ else
+ (void) TIFFSeekFile(tif,
+ dircount*sizeof (TIFFDirEntry), SEEK_CUR);
+ if (!ReadOK(tif, nextdir, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Error fetching directory link",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(nextdir);
+ return (1);
+ }
+}
+
+/*
+ * Count the number of directories in a file.
+ */
+tdir_t
+TIFFNumberOfDirectories(TIFF* tif)
+{
+ toff_t nextdir = tif->tif_header.tiff_diroff;
+ tdir_t n = 0;
+
+ while (nextdir != 0 && TIFFAdvanceDirectory(tif, &nextdir, NULL))
+ n++;
+ return (n);
+}
+
+/*
+ * Set the n-th directory as the current directory.
+ * NB: Directories are numbered starting at 0.
+ */
+int
+TIFFSetDirectory(TIFF* tif, tdir_t dirn)
+{
+ toff_t nextdir;
+ tdir_t n;
+
+ nextdir = tif->tif_header.tiff_diroff;
+ for (n = dirn; n > 0 && nextdir != 0; n--)
+ if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
+ return (0);
+ tif->tif_nextdiroff = nextdir;
+ /*
+ * Set curdir to the actual directory index. The
+ * -1 is because TIFFReadDirectory will increment
+ * tif_curdir after successfully reading the directory.
+ */
+ tif->tif_curdir = (dirn - n) - 1;
+ /*
+ * Reset tif_dirnumber counter and start new list of seen directories.
+ * We need this to prevent IFD loops.
+ */
+ tif->tif_dirnumber = 0;
+ return (TIFFReadDirectory(tif));
+}
+
+/*
+ * Set the current directory to be the directory
+ * located at the specified file offset. This interface
+ * is used mainly to access directories linked with
+ * the SubIFD tag (e.g. thumbnail images).
+ */
+int
+TIFFSetSubDirectory(TIFF* tif, uint32 diroff)
+{
+ tif->tif_nextdiroff = diroff;
+ /*
+ * Reset tif_dirnumber counter and start new list of seen directories.
+ * We need this to prevent IFD loops.
+ */
+ tif->tif_dirnumber = 0;
+ return (TIFFReadDirectory(tif));
+}
+
+/*
+ * Return file offset of the current directory.
+ */
+uint32
+TIFFCurrentDirOffset(TIFF* tif)
+{
+ return (tif->tif_diroff);
+}
+
+/*
+ * Return an indication of whether or not we are
+ * at the last directory in the file.
+ */
+int
+TIFFLastDirectory(TIFF* tif)
+{
+ return (tif->tif_nextdiroff == 0);
+}
+
+/*
+ * Unlink the specified directory from the directory chain.
+ */
+int
+TIFFUnlinkDirectory(TIFF* tif, tdir_t dirn)
+{
+ static const char module[] = "TIFFUnlinkDirectory";
+ toff_t nextdir;
+ toff_t off;
+ tdir_t n;
+
+ if (tif->tif_mode == O_RDONLY) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Can not unlink directory in read-only file");
+ return (0);
+ }
+ /*
+ * Go to the directory before the one we want
+ * to unlink and nab the offset of the link
+ * field we'll need to patch.
+ */
+ nextdir = tif->tif_header.tiff_diroff;
+ off = sizeof (uint16) + sizeof (uint16);
+ for (n = dirn-1; n > 0; n--) {
+ if (nextdir == 0) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Directory %d does not exist", dirn);
+ return (0);
+ }
+ if (!TIFFAdvanceDirectory(tif, &nextdir, &off))
+ return (0);
+ }
+ /*
+ * Advance to the directory to be unlinked and fetch
+ * the offset of the directory that follows.
+ */
+ if (!TIFFAdvanceDirectory(tif, &nextdir, NULL))
+ return (0);
+ /*
+ * Go back and patch the link field of the preceding
+ * directory to point to the offset of the directory
+ * that follows.
+ */
+ (void) TIFFSeekFile(tif, off, SEEK_SET);
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir);
+ if (!WriteOK(tif, &nextdir, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link");
+ return (0);
+ }
+ /*
+ * Leave directory state setup safely. We don't have
+ * facilities for doing inserting and removing directories,
+ * so it's safest to just invalidate everything. This
+ * means that the caller can only append to the directory
+ * chain.
+ */
+ (*tif->tif_cleanup)(tif);
+ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_rawdata = NULL;
+ tif->tif_rawcc = 0;
+ }
+ tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP|TIFF_POSTENCODE);
+ TIFFFreeDirectory(tif);
+ TIFFDefaultDirectory(tif);
+ tif->tif_diroff = 0; /* force link on next write */
+ tif->tif_nextdiroff = 0; /* next write must be at end */
+ tif->tif_curoff = 0;
+ tif->tif_row = (uint32) -1;
+ tif->tif_curstrip = (tstrip_t) -1;
+ return (1);
+}
+
+/* [BFC]
+ *
+ * Author: Bruce Cameron <cameron@petris.com>
+ *
+ * Set a table of tags that are to be replaced during directory process by the
+ * 'IGNORE' state - or return TRUE/FALSE for the requested tag such that
+ * 'ReadDirectory' can use the stored information.
+ *
+ * FIXME: this is never used properly. Should be removed in the future.
+ */
+int
+TIFFReassignTagToIgnore (enum TIFFIgnoreSense task, int TIFFtagID)
+{
+ static int TIFFignoretags [FIELD_LAST];
+ static int tagcount = 0 ;
+ int i; /* Loop index */
+ int j; /* Loop index */
+
+ switch (task)
+ {
+ case TIS_STORE:
+ if ( tagcount < (FIELD_LAST - 1) )
+ {
+ for ( j = 0 ; j < tagcount ; ++j )
+ { /* Do not add duplicate tag */
+ if ( TIFFignoretags [j] == TIFFtagID )
+ return (TRUE) ;
+ }
+ TIFFignoretags [tagcount++] = TIFFtagID ;
+ return (TRUE) ;
+ }
+ break ;
+
+ case TIS_EXTRACT:
+ for ( i = 0 ; i < tagcount ; ++i )
+ {
+ if ( TIFFignoretags [i] == TIFFtagID )
+ return (TRUE) ;
+ }
+ break;
+
+ case TIS_EMPTY:
+ tagcount = 0 ; /* Clear the list */
+ return (TRUE) ;
+
+ default:
+ break;
+ }
+
+ return (FALSE);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_dir.h b/Source/LibTIFF/tif_dir.h
new file mode 100644
index 0000000..ba2ae06
--- /dev/null
+++ b/Source/LibTIFF/tif_dir.h
@@ -0,0 +1,202 @@
+/* $Id: tif_dir.h,v 1.27 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFDIR_
+#define _TIFFDIR_
+/*
+ * ``Library-private'' Directory-related Definitions.
+ */
+
+/*
+ * Internal format of a TIFF directory entry.
+ */
+typedef struct {
+#define FIELD_SETLONGS 4
+ /* bit vector of fields that are set */
+ unsigned long td_fieldsset[FIELD_SETLONGS];
+
+ uint32 td_imagewidth, td_imagelength, td_imagedepth;
+ uint32 td_tilewidth, td_tilelength, td_tiledepth;
+ uint32 td_subfiletype;
+ uint16 td_bitspersample;
+ uint16 td_sampleformat;
+ uint16 td_compression;
+ uint16 td_photometric;
+ uint16 td_threshholding;
+ uint16 td_fillorder;
+ uint16 td_orientation;
+ uint16 td_samplesperpixel;
+ uint32 td_rowsperstrip;
+ uint16 td_minsamplevalue, td_maxsamplevalue;
+ double td_sminsamplevalue, td_smaxsamplevalue;
+ float td_xresolution, td_yresolution;
+ uint16 td_resolutionunit;
+ uint16 td_planarconfig;
+ float td_xposition, td_yposition;
+ uint16 td_pagenumber[2];
+ uint16* td_colormap[3];
+ uint16 td_halftonehints[2];
+ uint16 td_extrasamples;
+ uint16* td_sampleinfo;
+ /* even though the name is misleading, td_stripsperimage is the number
+ * of striles (=strips or tiles) per plane, and td_nstrips the total
+ * number of striles */
+ tstrile_t td_stripsperimage;
+ tstrile_t td_nstrips; /* size of offset & bytecount arrays */
+ toff_t* td_stripoffset;
+ toff_t* td_stripbytecount; /* FIXME: it should be tsize_t array */
+ int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
+ uint16 td_nsubifd;
+ uint32* td_subifd;
+ /* YCbCr parameters */
+ uint16 td_ycbcrsubsampling[2];
+ uint16 td_ycbcrpositioning;
+ /* Colorimetry parameters */
+ uint16* td_transferfunction[3];
+ /* CMYK parameters */
+ int td_inknameslen;
+ char* td_inknames;
+
+ int td_customValueCount;
+ TIFFTagValue *td_customValues;
+} TIFFDirectory;
+
+/*
+ * Field flags used to indicate fields that have
+ * been set in a directory, and to reference fields
+ * when manipulating a directory.
+ */
+
+/*
+ * FIELD_IGNORE is used to signify tags that are to
+ * be processed but otherwise ignored. This permits
+ * antiquated tags to be quietly read and discarded.
+ * Note that a bit *is* allocated for ignored tags;
+ * this is understood by the directory reading logic
+ * which uses this fact to avoid special-case handling
+ */
+#define FIELD_IGNORE 0
+
+/* multi-item fields */
+#define FIELD_IMAGEDIMENSIONS 1
+#define FIELD_TILEDIMENSIONS 2
+#define FIELD_RESOLUTION 3
+#define FIELD_POSITION 4
+
+/* single-item fields */
+#define FIELD_SUBFILETYPE 5
+#define FIELD_BITSPERSAMPLE 6
+#define FIELD_COMPRESSION 7
+#define FIELD_PHOTOMETRIC 8
+#define FIELD_THRESHHOLDING 9
+#define FIELD_FILLORDER 10
+#define FIELD_ORIENTATION 15
+#define FIELD_SAMPLESPERPIXEL 16
+#define FIELD_ROWSPERSTRIP 17
+#define FIELD_MINSAMPLEVALUE 18
+#define FIELD_MAXSAMPLEVALUE 19
+#define FIELD_PLANARCONFIG 20
+#define FIELD_RESOLUTIONUNIT 22
+#define FIELD_PAGENUMBER 23
+#define FIELD_STRIPBYTECOUNTS 24
+#define FIELD_STRIPOFFSETS 25
+#define FIELD_COLORMAP 26
+#define FIELD_EXTRASAMPLES 31
+#define FIELD_SAMPLEFORMAT 32
+#define FIELD_SMINSAMPLEVALUE 33
+#define FIELD_SMAXSAMPLEVALUE 34
+#define FIELD_IMAGEDEPTH 35
+#define FIELD_TILEDEPTH 36
+#define FIELD_HALFTONEHINTS 37
+#define FIELD_YCBCRSUBSAMPLING 39
+#define FIELD_YCBCRPOSITIONING 40
+#define FIELD_TRANSFERFUNCTION 44
+#define FIELD_INKNAMES 46
+#define FIELD_SUBIFD 49
+/* FIELD_CUSTOM (see tiffio.h) 65 */
+/* end of support for well-known tags; codec-private tags follow */
+#define FIELD_CODEC 66 /* base of codec-private tags */
+
+
+/*
+ * Pseudo-tags don't normally need field bits since they
+ * are not written to an output file (by definition).
+ * The library also has express logic to always query a
+ * codec for a pseudo-tag so allocating a field bit for
+ * one is a waste. If codec wants to promote the notion
+ * of a pseudo-tag being ``set'' or ``unset'' then it can
+ * do using internal state flags without polluting the
+ * field bit space defined for real tags.
+ */
+#define FIELD_PSEUDO 0
+
+#define FIELD_LAST (32*FIELD_SETLONGS-1)
+
+#define TIFFExtractData(tif, type, v) \
+ ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
+ ((v) >> (tif)->tif_typeshift[type]) & (tif)->tif_typemask[type] : \
+ (v) & (tif)->tif_typemask[type]))
+#define TIFFInsertData(tif, type, v) \
+ ((uint32) ((tif)->tif_header.tiff_magic == TIFF_BIGENDIAN ? \
+ ((v) & (tif)->tif_typemask[type]) << (tif)->tif_typeshift[type] : \
+ (v) & (tif)->tif_typemask[type]))
+
+
+#define BITn(n) (((unsigned long)1L)<<((n)&0x1f))
+#define BITFIELDn(tif, n) ((tif)->tif_dir.td_fieldsset[(n)/32])
+#define TIFFFieldSet(tif, field) (BITFIELDn(tif, field) & BITn(field))
+#define TIFFSetFieldBit(tif, field) (BITFIELDn(tif, field) |= BITn(field))
+#define TIFFClrFieldBit(tif, field) (BITFIELDn(tif, field) &= ~BITn(field))
+
+#define FieldSet(fields, f) (fields[(f)/32] & BITn(f))
+#define ResetFieldBit(fields, f) (fields[(f)/32] &= ~BITn(f))
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern const TIFFFieldInfo *_TIFFGetFieldInfo(size_t *);
+extern const TIFFFieldInfo *_TIFFGetExifFieldInfo(size_t *);
+extern void _TIFFSetupFieldInfo(TIFF*, const TIFFFieldInfo[], size_t);
+extern int _TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int);
+extern void _TIFFPrintFieldInfo(TIFF*, FILE*);
+extern TIFFDataType _TIFFSampleToTagType(TIFF*);
+extern const TIFFFieldInfo* _TIFFFindOrRegisterFieldInfo( TIFF *tif,
+ ttag_t tag,
+ TIFFDataType dt );
+extern TIFFFieldInfo* _TIFFCreateAnonFieldInfo( TIFF *tif, ttag_t tag,
+ TIFFDataType dt );
+
+#define _TIFFFindFieldInfo TIFFFindFieldInfo
+#define _TIFFFindFieldInfoByName TIFFFindFieldInfoByName
+#define _TIFFFieldWithTag TIFFFieldWithTag
+#define _TIFFFieldWithName TIFFFieldWithName
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFDIR_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_dirinfo.c b/Source/LibTIFF/tif_dirinfo.c
new file mode 100644
index 0000000..2a4bd72
--- /dev/null
+++ b/Source/LibTIFF/tif_dirinfo.c
@@ -0,0 +1,880 @@
+/* $Id: tif_dirinfo.c,v 1.28 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Core Directory Tag Support.
+ */
+#include "tiffiop.h"
+#include <stdlib.h>
+
+/*
+ * NB: NB: THIS ARRAY IS ASSUMED TO BE SORTED BY TAG.
+ * If a tag can have both LONG and SHORT types then the LONG must be
+ * placed before the SHORT for writing to work properly.
+ *
+ * NOTE: The second field (field_readcount) and third field (field_writecount)
+ * sometimes use the values TIFF_VARIABLE (-1), TIFF_VARIABLE2 (-3)
+ * and TIFFTAG_SPP (-2). The macros should be used but would throw off
+ * the formatting of the code, so please interprete the -1, -2 and -3
+ * values accordingly.
+ */
+static const TIFFFieldInfo
+tiffFieldInfo[] = {
+ { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_LONG, FIELD_SUBFILETYPE,
+ 1, 0, "SubfileType" },
+/* XXX SHORT for compatibility w/ old versions of the library */
+ { TIFFTAG_SUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE,
+ 1, 0, "SubfileType" },
+ { TIFFTAG_OSUBFILETYPE, 1, 1, TIFF_SHORT, FIELD_SUBFILETYPE,
+ 1, 0, "OldSubfileType" },
+ { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS,
+ 0, 0, "ImageWidth" },
+ { TIFFTAG_IMAGEWIDTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS,
+ 0, 0, "ImageWidth" },
+ { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_LONG, FIELD_IMAGEDIMENSIONS,
+ 1, 0, "ImageLength" },
+ { TIFFTAG_IMAGELENGTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDIMENSIONS,
+ 1, 0, "ImageLength" },
+ { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_SHORT, FIELD_BITSPERSAMPLE,
+ 0, 0, "BitsPerSample" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+ { TIFFTAG_BITSPERSAMPLE, -1,-1, TIFF_LONG, FIELD_BITSPERSAMPLE,
+ 0, 0, "BitsPerSample" },
+ { TIFFTAG_COMPRESSION, -1, 1, TIFF_SHORT, FIELD_COMPRESSION,
+ 0, 0, "Compression" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+ { TIFFTAG_COMPRESSION, -1, 1, TIFF_LONG, FIELD_COMPRESSION,
+ 0, 0, "Compression" },
+ { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_SHORT, FIELD_PHOTOMETRIC,
+ 0, 0, "PhotometricInterpretation" },
+/* XXX LONG for compatibility with some broken TIFF writers */
+ { TIFFTAG_PHOTOMETRIC, 1, 1, TIFF_LONG, FIELD_PHOTOMETRIC,
+ 0, 0, "PhotometricInterpretation" },
+ { TIFFTAG_THRESHHOLDING, 1, 1, TIFF_SHORT, FIELD_THRESHHOLDING,
+ 1, 0, "Threshholding" },
+ { TIFFTAG_CELLWIDTH, 1, 1, TIFF_SHORT, FIELD_IGNORE,
+ 1, 0, "CellWidth" },
+ { TIFFTAG_CELLLENGTH, 1, 1, TIFF_SHORT, FIELD_IGNORE,
+ 1, 0, "CellLength" },
+ { TIFFTAG_FILLORDER, 1, 1, TIFF_SHORT, FIELD_FILLORDER,
+ 0, 0, "FillOrder" },
+ { TIFFTAG_DOCUMENTNAME, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "DocumentName" },
+ { TIFFTAG_IMAGEDESCRIPTION, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "ImageDescription" },
+ { TIFFTAG_MAKE, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "Make" },
+ { TIFFTAG_MODEL, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "Model" },
+ { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_LONG, FIELD_STRIPOFFSETS,
+ 0, 0, "StripOffsets" },
+ { TIFFTAG_STRIPOFFSETS, -1,-1, TIFF_SHORT, FIELD_STRIPOFFSETS,
+ 0, 0, "StripOffsets" },
+ { TIFFTAG_ORIENTATION, 1, 1, TIFF_SHORT, FIELD_ORIENTATION,
+ 0, 0, "Orientation" },
+ { TIFFTAG_SAMPLESPERPIXEL, 1, 1, TIFF_SHORT, FIELD_SAMPLESPERPIXEL,
+ 0, 0, "SamplesPerPixel" },
+ { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_LONG, FIELD_ROWSPERSTRIP,
+ 0, 0, "RowsPerStrip" },
+ { TIFFTAG_ROWSPERSTRIP, 1, 1, TIFF_SHORT, FIELD_ROWSPERSTRIP,
+ 0, 0, "RowsPerStrip" },
+ { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_STRIPBYTECOUNTS,
+ 0, 0, "StripByteCounts" },
+ { TIFFTAG_STRIPBYTECOUNTS, -1,-1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS,
+ 0, 0, "StripByteCounts" },
+ { TIFFTAG_MINSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MINSAMPLEVALUE,
+ 1, 0, "MinSampleValue" },
+ { TIFFTAG_MAXSAMPLEVALUE, -2,-1, TIFF_SHORT, FIELD_MAXSAMPLEVALUE,
+ 1, 0, "MaxSampleValue" },
+ { TIFFTAG_XRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION,
+ 1, 0, "XResolution" },
+ { TIFFTAG_YRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_RESOLUTION,
+ 1, 0, "YResolution" },
+ { TIFFTAG_PLANARCONFIG, 1, 1, TIFF_SHORT, FIELD_PLANARCONFIG,
+ 0, 0, "PlanarConfiguration" },
+ { TIFFTAG_PAGENAME, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "PageName" },
+ { TIFFTAG_XPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION,
+ 1, 0, "XPosition" },
+ { TIFFTAG_YPOSITION, 1, 1, TIFF_RATIONAL, FIELD_POSITION,
+ 1, 0, "YPosition" },
+ { TIFFTAG_FREEOFFSETS, -1,-1, TIFF_LONG, FIELD_IGNORE,
+ 0, 0, "FreeOffsets" },
+ { TIFFTAG_FREEBYTECOUNTS, -1,-1, TIFF_LONG, FIELD_IGNORE,
+ 0, 0, "FreeByteCounts" },
+ { TIFFTAG_GRAYRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE,
+ 1, 0, "GrayResponseUnit" },
+ { TIFFTAG_GRAYRESPONSECURVE,-1,-1, TIFF_SHORT, FIELD_IGNORE,
+ 1, 0, "GrayResponseCurve" },
+ { TIFFTAG_RESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_RESOLUTIONUNIT,
+ 1, 0, "ResolutionUnit" },
+ { TIFFTAG_PAGENUMBER, 2, 2, TIFF_SHORT, FIELD_PAGENUMBER,
+ 1, 0, "PageNumber" },
+ { TIFFTAG_COLORRESPONSEUNIT, 1, 1, TIFF_SHORT, FIELD_IGNORE,
+ 1, 0, "ColorResponseUnit" },
+ { TIFFTAG_TRANSFERFUNCTION, -1,-1, TIFF_SHORT, FIELD_TRANSFERFUNCTION,
+ 1, 0, "TransferFunction" },
+ { TIFFTAG_SOFTWARE, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "Software" },
+ { TIFFTAG_DATETIME, 20,20, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "DateTime" },
+ { TIFFTAG_ARTIST, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "Artist" },
+ { TIFFTAG_HOSTCOMPUTER, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "HostComputer" },
+ { TIFFTAG_WHITEPOINT, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "WhitePoint" },
+ { TIFFTAG_PRIMARYCHROMATICITIES,6,6,TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "PrimaryChromaticities" },
+ { TIFFTAG_COLORMAP, -1,-1, TIFF_SHORT, FIELD_COLORMAP,
+ 1, 0, "ColorMap" },
+ { TIFFTAG_HALFTONEHINTS, 2, 2, TIFF_SHORT, FIELD_HALFTONEHINTS,
+ 1, 0, "HalftoneHints" },
+ { TIFFTAG_TILEWIDTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS,
+ 0, 0, "TileWidth" },
+ { TIFFTAG_TILEWIDTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS,
+ 0, 0, "TileWidth" },
+ { TIFFTAG_TILELENGTH, 1, 1, TIFF_LONG, FIELD_TILEDIMENSIONS,
+ 0, 0, "TileLength" },
+ { TIFFTAG_TILELENGTH, 1, 1, TIFF_SHORT, FIELD_TILEDIMENSIONS,
+ 0, 0, "TileLength" },
+ { TIFFTAG_TILEOFFSETS, -1, 1, TIFF_LONG, FIELD_STRIPOFFSETS,
+ 0, 0, "TileOffsets" },
+ { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_LONG, FIELD_STRIPBYTECOUNTS,
+ 0, 0, "TileByteCounts" },
+ { TIFFTAG_TILEBYTECOUNTS, -1, 1, TIFF_SHORT, FIELD_STRIPBYTECOUNTS,
+ 0, 0, "TileByteCounts" },
+ { TIFFTAG_SUBIFD, -1,-1, TIFF_IFD, FIELD_SUBIFD,
+ 1, 1, "SubIFD" },
+ { TIFFTAG_SUBIFD, -1,-1, TIFF_LONG, FIELD_SUBIFD,
+ 1, 1, "SubIFD" },
+ { TIFFTAG_INKSET, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "InkSet" },
+ { TIFFTAG_INKNAMES, -1,-1, TIFF_ASCII, FIELD_INKNAMES,
+ 1, 1, "InkNames" },
+ { TIFFTAG_NUMBEROFINKS, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "NumberOfInks" },
+ { TIFFTAG_DOTRANGE, 2, 2, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "DotRange" },
+ { TIFFTAG_DOTRANGE, 2, 2, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 0, "DotRange" },
+ { TIFFTAG_TARGETPRINTER, -1,-1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "TargetPrinter" },
+ { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_SHORT, FIELD_EXTRASAMPLES,
+ 0, 1, "ExtraSamples" },
+/* XXX for bogus Adobe Photoshop v2.5 files */
+ { TIFFTAG_EXTRASAMPLES, -1,-1, TIFF_BYTE, FIELD_EXTRASAMPLES,
+ 0, 1, "ExtraSamples" },
+ { TIFFTAG_SAMPLEFORMAT, -1,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT,
+ 0, 0, "SampleFormat" },
+ { TIFFTAG_SMINSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMINSAMPLEVALUE,
+ 1, 0, "SMinSampleValue" },
+ { TIFFTAG_SMAXSAMPLEVALUE, -2,-1, TIFF_ANY, FIELD_SMAXSAMPLEVALUE,
+ 1, 0, "SMaxSampleValue" },
+ { TIFFTAG_CLIPPATH, -1, -3, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 1, "ClipPath" },
+ { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SLONG, FIELD_CUSTOM,
+ 0, 0, "XClipPathUnits" },
+ { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SSHORT, FIELD_CUSTOM,
+ 0, 0, "XClipPathUnits" },
+ { TIFFTAG_XCLIPPATHUNITS, 1, 1, TIFF_SBYTE, FIELD_CUSTOM,
+ 0, 0, "XClipPathUnits" },
+ { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SLONG, FIELD_CUSTOM,
+ 0, 0, "YClipPathUnits" },
+ { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SSHORT, FIELD_CUSTOM,
+ 0, 0, "YClipPathUnits" },
+ { TIFFTAG_YCLIPPATHUNITS, 1, 1, TIFF_SBYTE, FIELD_CUSTOM,
+ 0, 0, "YClipPathUnits" },
+ { TIFFTAG_YCBCRCOEFFICIENTS, 3, 3, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "YCbCrCoefficients" },
+ { TIFFTAG_YCBCRSUBSAMPLING, 2, 2, TIFF_SHORT, FIELD_YCBCRSUBSAMPLING,
+ 0, 0, "YCbCrSubsampling" },
+ { TIFFTAG_YCBCRPOSITIONING, 1, 1, TIFF_SHORT, FIELD_YCBCRPOSITIONING,
+ 0, 0, "YCbCrPositioning" },
+ { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "ReferenceBlackWhite" },
+/* XXX temporarily accept LONG for backwards compatibility */
+ { TIFFTAG_REFERENCEBLACKWHITE, 6, 6, TIFF_LONG, FIELD_CUSTOM,
+ 1, 0, "ReferenceBlackWhite" },
+ { TIFFTAG_XMLPACKET, -3,-3, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 1, "XMLPacket" },
+/* begin SGI tags */
+ { TIFFTAG_MATTEING, 1, 1, TIFF_SHORT, FIELD_EXTRASAMPLES,
+ 0, 0, "Matteing" },
+ { TIFFTAG_DATATYPE, -2,-1, TIFF_SHORT, FIELD_SAMPLEFORMAT,
+ 0, 0, "DataType" },
+ { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_LONG, FIELD_IMAGEDEPTH,
+ 0, 0, "ImageDepth" },
+ { TIFFTAG_IMAGEDEPTH, 1, 1, TIFF_SHORT, FIELD_IMAGEDEPTH,
+ 0, 0, "ImageDepth" },
+ { TIFFTAG_TILEDEPTH, 1, 1, TIFF_LONG, FIELD_TILEDEPTH,
+ 0, 0, "TileDepth" },
+ { TIFFTAG_TILEDEPTH, 1, 1, TIFF_SHORT, FIELD_TILEDEPTH,
+ 0, 0, "TileDepth" },
+/* end SGI tags */
+/* begin Pixar tags */
+ { TIFFTAG_PIXAR_IMAGEFULLWIDTH, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 1, 0, "ImageFullWidth" },
+ { TIFFTAG_PIXAR_IMAGEFULLLENGTH, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 1, 0, "ImageFullLength" },
+ { TIFFTAG_PIXAR_TEXTUREFORMAT, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "TextureFormat" },
+ { TIFFTAG_PIXAR_WRAPMODES, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "TextureWrapModes" },
+ { TIFFTAG_PIXAR_FOVCOT, 1, 1, TIFF_FLOAT, FIELD_CUSTOM,
+ 1, 0, "FieldOfViewCotangent" },
+ { TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN, 16,16, TIFF_FLOAT,
+ FIELD_CUSTOM, 1, 0, "MatrixWorldToScreen" },
+ { TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA, 16,16, TIFF_FLOAT,
+ FIELD_CUSTOM, 1, 0, "MatrixWorldToCamera" },
+ { TIFFTAG_COPYRIGHT, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "Copyright" },
+/* end Pixar tags */
+ { TIFFTAG_RICHTIFFIPTC, -3, -3, TIFF_LONG, FIELD_CUSTOM,
+ 0, 1, "RichTIFFIPTC" },
+ { TIFFTAG_PHOTOSHOP, -3, -3, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 1, "Photoshop" },
+ { TIFFTAG_EXIFIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "EXIFIFDOffset" },
+ { TIFFTAG_ICCPROFILE, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 0, 1, "ICC Profile" },
+ { TIFFTAG_GPSIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "GPSIFDOffset" },
+ { TIFFTAG_STONITS, 1, 1, TIFF_DOUBLE, FIELD_CUSTOM,
+ 0, 0, "StoNits" },
+ { TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "InteroperabilityIFDOffset" },
+/* begin DNG tags */
+ { TIFFTAG_DNGVERSION, 4, 4, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 0, "DNGVersion" },
+ { TIFFTAG_DNGBACKWARDVERSION, 4, 4, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 0, "DNGBackwardVersion" },
+ { TIFFTAG_UNIQUECAMERAMODEL, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "UniqueCameraModel" },
+ { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "LocalizedCameraModel" },
+ { TIFFTAG_LOCALIZEDCAMERAMODEL, -1, -1, TIFF_BYTE, FIELD_CUSTOM,
+ 1, 1, "LocalizedCameraModel" },
+ { TIFFTAG_CFAPLANECOLOR, -1, -1, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 1, "CFAPlaneColor" },
+ { TIFFTAG_CFALAYOUT, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "CFALayout" },
+ { TIFFTAG_LINEARIZATIONTABLE, -1, -1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 1, "LinearizationTable" },
+ { TIFFTAG_BLACKLEVELREPEATDIM, 2, 2, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "BlackLevelRepeatDim" },
+ { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 1, "BlackLevel" },
+ { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 1, "BlackLevel" },
+ { TIFFTAG_BLACKLEVEL, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 1, "BlackLevel" },
+ { TIFFTAG_BLACKLEVELDELTAH, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "BlackLevelDeltaH" },
+ { TIFFTAG_BLACKLEVELDELTAV, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "BlackLevelDeltaV" },
+ { TIFFTAG_WHITELEVEL, -2, -2, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "WhiteLevel" },
+ { TIFFTAG_WHITELEVEL, -2, -2, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "WhiteLevel" },
+ { TIFFTAG_DEFAULTSCALE, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "DefaultScale" },
+ { TIFFTAG_BESTQUALITYSCALE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "BestQualityScale" },
+ { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "DefaultCropOrigin" },
+ { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "DefaultCropOrigin" },
+ { TIFFTAG_DEFAULTCROPORIGIN, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "DefaultCropOrigin" },
+ { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "DefaultCropSize" },
+ { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "DefaultCropSize" },
+ { TIFFTAG_DEFAULTCROPSIZE, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "DefaultCropSize" },
+ { TIFFTAG_COLORMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "ColorMatrix1" },
+ { TIFFTAG_COLORMATRIX2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "ColorMatrix2" },
+ { TIFFTAG_CAMERACALIBRATION1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "CameraCalibration1" },
+ { TIFFTAG_CAMERACALIBRATION2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "CameraCalibration2" },
+ { TIFFTAG_REDUCTIONMATRIX1, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "ReductionMatrix1" },
+ { TIFFTAG_REDUCTIONMATRIX2, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "ReductionMatrix2" },
+ { TIFFTAG_ANALOGBALANCE, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 1, "AnalogBalance" },
+ { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 1, "AsShotNeutral" },
+ { TIFFTAG_ASSHOTNEUTRAL, -1, -1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 1, "AsShotNeutral" },
+ { TIFFTAG_ASSHOTWHITEXY, 2, 2, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "AsShotWhiteXY" },
+ { TIFFTAG_BASELINEEXPOSURE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 0, "BaselineExposure" },
+ { TIFFTAG_BASELINENOISE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "BaselineNoise" },
+ { TIFFTAG_BASELINESHARPNESS, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "BaselineSharpness" },
+ { TIFFTAG_BAYERGREENSPLIT, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "BayerGreenSplit" },
+ { TIFFTAG_LINEARRESPONSELIMIT, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "LinearResponseLimit" },
+ { TIFFTAG_CAMERASERIALNUMBER, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "CameraSerialNumber" },
+ { TIFFTAG_LENSINFO, 4, 4, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "LensInfo" },
+ { TIFFTAG_CHROMABLURRADIUS, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "ChromaBlurRadius" },
+ { TIFFTAG_ANTIALIASSTRENGTH, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "AntiAliasStrength" },
+ { TIFFTAG_SHADOWSCALE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 0, 0, "ShadowScale" },
+ { TIFFTAG_DNGPRIVATEDATA, -1, -1, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 1, "DNGPrivateData" },
+ { TIFFTAG_MAKERNOTESAFETY, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "MakerNoteSafety" },
+ { TIFFTAG_CALIBRATIONILLUMINANT1, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "CalibrationIlluminant1" },
+ { TIFFTAG_CALIBRATIONILLUMINANT2, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "CalibrationIlluminant2" },
+ { TIFFTAG_RAWDATAUNIQUEID, 16, 16, TIFF_BYTE, FIELD_CUSTOM,
+ 0, 0, "RawDataUniqueID" },
+ { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "OriginalRawFileName" },
+ { TIFFTAG_ORIGINALRAWFILENAME, -1, -1, TIFF_BYTE, FIELD_CUSTOM,
+ 1, 1, "OriginalRawFileName" },
+ { TIFFTAG_ORIGINALRAWFILEDATA, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 0, 1, "OriginalRawFileData" },
+ { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_LONG, FIELD_CUSTOM,
+ 0, 0, "ActiveArea" },
+ { TIFFTAG_ACTIVEAREA, 4, 4, TIFF_SHORT, FIELD_CUSTOM,
+ 0, 0, "ActiveArea" },
+ { TIFFTAG_MASKEDAREAS, -1, -1, TIFF_LONG, FIELD_CUSTOM,
+ 0, 1, "MaskedAreas" },
+ { TIFFTAG_ASSHOTICCPROFILE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 0, 1, "AsShotICCProfile" },
+ { TIFFTAG_ASSHOTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "AsShotPreProfileMatrix" },
+ { TIFFTAG_CURRENTICCPROFILE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 0, 1, "CurrentICCProfile" },
+ { TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 0, 1, "CurrentPreProfileMatrix" },
+/* end DNG tags */
+};
+
+static const TIFFFieldInfo
+exifFieldInfo[] = {
+ { EXIFTAG_EXPOSURETIME, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "ExposureTime" },
+ { EXIFTAG_FNUMBER, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "FNumber" },
+ { EXIFTAG_EXPOSUREPROGRAM, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "ExposureProgram" },
+ { EXIFTAG_SPECTRALSENSITIVITY, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "SpectralSensitivity" },
+ { EXIFTAG_ISOSPEEDRATINGS, -1, -1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 1, "ISOSpeedRatings" },
+ { EXIFTAG_OECF, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "OptoelectricConversionFactor" },
+ { EXIFTAG_EXIFVERSION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 0, "ExifVersion" },
+ { EXIFTAG_DATETIMEORIGINAL, 20, 20, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "DateTimeOriginal" },
+ { EXIFTAG_DATETIMEDIGITIZED, 20, 20, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "DateTimeDigitized" },
+ { EXIFTAG_COMPONENTSCONFIGURATION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 0, "ComponentsConfiguration" },
+ { EXIFTAG_COMPRESSEDBITSPERPIXEL, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "CompressedBitsPerPixel" },
+ { EXIFTAG_SHUTTERSPEEDVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 1, 0, "ShutterSpeedValue" },
+ { EXIFTAG_APERTUREVALUE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "ApertureValue" },
+ { EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 1, 0, "BrightnessValue" },
+ { EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, FIELD_CUSTOM,
+ 1, 0, "ExposureBiasValue" },
+ { EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "MaxApertureValue" },
+ { EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "SubjectDistance" },
+ { EXIFTAG_METERINGMODE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "MeteringMode" },
+ { EXIFTAG_LIGHTSOURCE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "LightSource" },
+ { EXIFTAG_FLASH, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "Flash" },
+ { EXIFTAG_FOCALLENGTH, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "FocalLength" },
+ { EXIFTAG_SUBJECTAREA, -1, -1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 1, "SubjectArea" },
+ { EXIFTAG_MAKERNOTE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "MakerNote" },
+ { EXIFTAG_USERCOMMENT, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "UserComment" },
+ { EXIFTAG_SUBSECTIME, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "SubSecTime" },
+ { EXIFTAG_SUBSECTIMEORIGINAL, -1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "SubSecTimeOriginal" },
+ { EXIFTAG_SUBSECTIMEDIGITIZED,-1, -1, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "SubSecTimeDigitized" },
+ { EXIFTAG_FLASHPIXVERSION, 4, 4, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 0, "FlashpixVersion" },
+ { EXIFTAG_COLORSPACE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "ColorSpace" },
+ { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 1, 0, "PixelXDimension" },
+ { EXIFTAG_PIXELXDIMENSION, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "PixelXDimension" },
+ { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_LONG, FIELD_CUSTOM,
+ 1, 0, "PixelYDimension" },
+ { EXIFTAG_PIXELYDIMENSION, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "PixelYDimension" },
+ { EXIFTAG_RELATEDSOUNDFILE, 13, 13, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "RelatedSoundFile" },
+ { EXIFTAG_FLASHENERGY, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "FlashEnergy" },
+ { EXIFTAG_SPATIALFREQUENCYRESPONSE, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "SpatialFrequencyResponse" },
+ { EXIFTAG_FOCALPLANEXRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "FocalPlaneXResolution" },
+ { EXIFTAG_FOCALPLANEYRESOLUTION, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "FocalPlaneYResolution" },
+ { EXIFTAG_FOCALPLANERESOLUTIONUNIT, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "FocalPlaneResolutionUnit" },
+ { EXIFTAG_SUBJECTLOCATION, 2, 2, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "SubjectLocation" },
+ { EXIFTAG_EXPOSUREINDEX, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "ExposureIndex" },
+ { EXIFTAG_SENSINGMETHOD, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "SensingMethod" },
+ { EXIFTAG_FILESOURCE, 1, 1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 0, "FileSource" },
+ { EXIFTAG_SCENETYPE, 1, 1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 0, "SceneType" },
+ { EXIFTAG_CFAPATTERN, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "CFAPattern" },
+ { EXIFTAG_CUSTOMRENDERED, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "CustomRendered" },
+ { EXIFTAG_EXPOSUREMODE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "ExposureMode" },
+ { EXIFTAG_WHITEBALANCE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "WhiteBalance" },
+ { EXIFTAG_DIGITALZOOMRATIO, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "DigitalZoomRatio" },
+ { EXIFTAG_FOCALLENGTHIN35MMFILM, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "FocalLengthIn35mmFilm" },
+ { EXIFTAG_SCENECAPTURETYPE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "SceneCaptureType" },
+ { EXIFTAG_GAINCONTROL, 1, 1, TIFF_RATIONAL, FIELD_CUSTOM,
+ 1, 0, "GainControl" },
+ { EXIFTAG_CONTRAST, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "Contrast" },
+ { EXIFTAG_SATURATION, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "Saturation" },
+ { EXIFTAG_SHARPNESS, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "Sharpness" },
+ { EXIFTAG_DEVICESETTINGDESCRIPTION, -1, -1, TIFF_UNDEFINED, FIELD_CUSTOM,
+ 1, 1, "DeviceSettingDescription" },
+ { EXIFTAG_SUBJECTDISTANCERANGE, 1, 1, TIFF_SHORT, FIELD_CUSTOM,
+ 1, 0, "SubjectDistanceRange" },
+ { EXIFTAG_IMAGEUNIQUEID, 33, 33, TIFF_ASCII, FIELD_CUSTOM,
+ 1, 0, "ImageUniqueID" }
+};
+
+const TIFFFieldInfo *
+_TIFFGetFieldInfo(size_t *size)
+{
+ *size = TIFFArrayCount(tiffFieldInfo);
+ return tiffFieldInfo;
+}
+
+const TIFFFieldInfo *
+_TIFFGetExifFieldInfo(size_t *size)
+{
+ *size = TIFFArrayCount(exifFieldInfo);
+ return exifFieldInfo;
+}
+
+void
+_TIFFSetupFieldInfo(TIFF* tif, const TIFFFieldInfo info[], size_t n)
+{
+ if (tif->tif_fieldinfo) {
+ size_t i;
+
+ for (i = 0; i < tif->tif_nfields; i++)
+ {
+ TIFFFieldInfo *fld = tif->tif_fieldinfo[i];
+ if (fld->field_bit == FIELD_CUSTOM &&
+ strncmp("Tag ", fld->field_name, 4) == 0) {
+ _TIFFfree(fld->field_name);
+ _TIFFfree(fld);
+ }
+ }
+
+ _TIFFfree(tif->tif_fieldinfo);
+ tif->tif_nfields = 0;
+ }
+ if (!_TIFFMergeFieldInfo(tif, info, n))
+ {
+ TIFFErrorExt(tif->tif_clientdata, "_TIFFSetupFieldInfo",
+ "Setting up field info failed");
+ }
+}
+
+static int
+tagCompare(const void* a, const void* b)
+{
+ const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
+ const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
+ /* NB: be careful of return values for 16-bit platforms */
+ if (ta->field_tag != tb->field_tag)
+ return (int)ta->field_tag - (int)tb->field_tag;
+ else
+ return (ta->field_type == TIFF_ANY) ?
+ 0 : ((int)tb->field_type - (int)ta->field_type);
+}
+
+static int
+tagNameCompare(const void* a, const void* b)
+{
+ const TIFFFieldInfo* ta = *(const TIFFFieldInfo**) a;
+ const TIFFFieldInfo* tb = *(const TIFFFieldInfo**) b;
+ int ret = strcmp(ta->field_name, tb->field_name);
+
+ if (ret)
+ return ret;
+ else
+ return (ta->field_type == TIFF_ANY) ?
+ 0 : ((int)tb->field_type - (int)ta->field_type);
+}
+
+void
+TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n)
+{
+ if (_TIFFMergeFieldInfo(tif, info, n) < 0)
+ {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFMergeFieldInfo",
+ "Merging block of %d fields failed", n);
+ }
+}
+
+int
+_TIFFMergeFieldInfo(TIFF* tif, const TIFFFieldInfo info[], int n)
+{
+ static const char module[] = "_TIFFMergeFieldInfo";
+ static const char reason[] = "for field info array";
+ TIFFFieldInfo** tp;
+ int i;
+
+ tif->tif_foundfield = NULL;
+
+ if (tif->tif_nfields > 0) {
+ tif->tif_fieldinfo = (TIFFFieldInfo**)
+ _TIFFCheckRealloc(tif, tif->tif_fieldinfo,
+ (tif->tif_nfields + n),
+ sizeof (TIFFFieldInfo*), reason);
+ } else {
+ tif->tif_fieldinfo = (TIFFFieldInfo**)
+ _TIFFCheckMalloc(tif, n, sizeof (TIFFFieldInfo*),
+ reason);
+ }
+ if (!tif->tif_fieldinfo) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Failed to allocate field info array");
+ return 0;
+ }
+ tp = tif->tif_fieldinfo + tif->tif_nfields;
+ for (i = 0; i < n; i++)
+ {
+ const TIFFFieldInfo *fip =
+ _TIFFFindFieldInfo(tif, info[i].field_tag, info[i].field_type);
+
+ /* only add definitions that aren't already present */
+ if (!fip) {
+ *tp++ = (TIFFFieldInfo*) (info + i);
+ tif->tif_nfields++;
+ }
+ }
+
+ /* Sort the field info by tag number */
+ qsort(tif->tif_fieldinfo, tif->tif_nfields,
+ sizeof (TIFFFieldInfo*), tagCompare);
+
+ return n;
+}
+
+void
+_TIFFPrintFieldInfo(TIFF* tif, FILE* fd)
+{
+ size_t i;
+
+ fprintf(fd, "%s: \n", tif->tif_name);
+ for (i = 0; i < tif->tif_nfields; i++) {
+ const TIFFFieldInfo* fip = tif->tif_fieldinfo[i];
+ fprintf(fd, "field[%2d] %5lu, %2d, %2d, %d, %2d, %5s, %5s, %s\n"
+ , (int)i
+ , (unsigned long) fip->field_tag
+ , fip->field_readcount, fip->field_writecount
+ , fip->field_type
+ , fip->field_bit
+ , fip->field_oktochange ? "TRUE" : "FALSE"
+ , fip->field_passcount ? "TRUE" : "FALSE"
+ , fip->field_name
+ );
+ }
+}
+
+/*
+ * Return size of TIFFDataType in bytes
+ */
+int
+TIFFDataWidth(TIFFDataType type)
+{
+ switch(type)
+ {
+ case 0: /* nothing */
+ case 1: /* TIFF_BYTE */
+ case 2: /* TIFF_ASCII */
+ case 6: /* TIFF_SBYTE */
+ case 7: /* TIFF_UNDEFINED */
+ return 1;
+ case 3: /* TIFF_SHORT */
+ case 8: /* TIFF_SSHORT */
+ return 2;
+ case 4: /* TIFF_LONG */
+ case 9: /* TIFF_SLONG */
+ case 11: /* TIFF_FLOAT */
+ case 13: /* TIFF_IFD */
+ return 4;
+ case 5: /* TIFF_RATIONAL */
+ case 10: /* TIFF_SRATIONAL */
+ case 12: /* TIFF_DOUBLE */
+ return 8;
+ default:
+ return 0; /* will return 0 for unknown types */
+ }
+}
+
+/*
+ * Return size of TIFFDataType in bytes.
+ *
+ * XXX: We need a separate function to determine the space needed
+ * to store the value. For TIFF_RATIONAL values TIFFDataWidth() returns 8,
+ * but we use 4-byte float to represent rationals.
+ */
+int
+_TIFFDataSize(TIFFDataType type)
+{
+ switch (type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ case TIFF_ASCII:
+ case TIFF_UNDEFINED:
+ return 1;
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ return 2;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_FLOAT:
+ case TIFF_IFD:
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ return 4;
+ case TIFF_DOUBLE:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Return nearest TIFFDataType to the sample type of an image.
+ */
+TIFFDataType
+_TIFFSampleToTagType(TIFF* tif)
+{
+ uint32 bps = TIFFhowmany8(tif->tif_dir.td_bitspersample);
+
+ switch (tif->tif_dir.td_sampleformat) {
+ case SAMPLEFORMAT_IEEEFP:
+ return (bps == 4 ? TIFF_FLOAT : TIFF_DOUBLE);
+ case SAMPLEFORMAT_INT:
+ return (bps <= 1 ? TIFF_SBYTE :
+ bps <= 2 ? TIFF_SSHORT : TIFF_SLONG);
+ case SAMPLEFORMAT_UINT:
+ return (bps <= 1 ? TIFF_BYTE :
+ bps <= 2 ? TIFF_SHORT : TIFF_LONG);
+ case SAMPLEFORMAT_VOID:
+ return (TIFF_UNDEFINED);
+ }
+ /*NOTREACHED*/
+ return (TIFF_UNDEFINED);
+}
+
+const TIFFFieldInfo*
+_TIFFFindFieldInfo(TIFF* tif, ttag_t tag, TIFFDataType dt)
+{
+ TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0};
+ TIFFFieldInfo* pkey = &key;
+ const TIFFFieldInfo **ret;
+
+ if (tif->tif_foundfield && tif->tif_foundfield->field_tag == tag &&
+ (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
+ return tif->tif_foundfield;
+
+ /* If we are invoked with no field information, then just return. */
+ if ( !tif->tif_fieldinfo ) {
+ return NULL;
+ }
+
+ /* NB: use sorted search (e.g. binary search) */
+ key.field_tag = tag;
+ key.field_type = dt;
+
+ ret = (const TIFFFieldInfo **) bsearch(&pkey,
+ tif->tif_fieldinfo,
+ tif->tif_nfields,
+ sizeof(TIFFFieldInfo *),
+ tagCompare);
+ return tif->tif_foundfield = (ret ? *ret : NULL);
+}
+
+const TIFFFieldInfo*
+_TIFFFindFieldInfoByName(TIFF* tif, const char *field_name, TIFFDataType dt)
+{
+ TIFFFieldInfo key = {0, 0, 0, TIFF_NOTYPE, 0, 0, 0, 0};
+ TIFFFieldInfo* pkey = &key;
+ const TIFFFieldInfo **ret;
+
+ if (tif->tif_foundfield
+ && streq(tif->tif_foundfield->field_name, field_name)
+ && (dt == TIFF_ANY || dt == tif->tif_foundfield->field_type))
+ return (tif->tif_foundfield);
+
+ /* If we are invoked with no field information, then just return. */
+ if ( !tif->tif_fieldinfo ) {
+ return NULL;
+ }
+
+ /* NB: use sorted search (e.g. binary search) */
+ key.field_name = (char *)field_name;
+ key.field_type = dt;
+
+ ret = (const TIFFFieldInfo **) lfind(&pkey,
+ tif->tif_fieldinfo,
+ &tif->tif_nfields,
+ sizeof(TIFFFieldInfo *),
+ tagNameCompare);
+ return tif->tif_foundfield = (ret ? *ret : NULL);
+}
+
+const TIFFFieldInfo*
+_TIFFFieldWithTag(TIFF* tif, ttag_t tag)
+{
+ const TIFFFieldInfo* fip = _TIFFFindFieldInfo(tif, tag, TIFF_ANY);
+ if (!fip) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithTag",
+ "Internal error, unknown tag 0x%x",
+ (unsigned int) tag);
+ assert(fip != NULL);
+ /*NOTREACHED*/
+ }
+ return (fip);
+}
+
+const TIFFFieldInfo*
+_TIFFFieldWithName(TIFF* tif, const char *field_name)
+{
+ const TIFFFieldInfo* fip =
+ _TIFFFindFieldInfoByName(tif, field_name, TIFF_ANY);
+ if (!fip) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFFieldWithName",
+ "Internal error, unknown tag %s", field_name);
+ assert(fip != NULL);
+ /*NOTREACHED*/
+ }
+ return (fip);
+}
+
+const TIFFFieldInfo*
+_TIFFFindOrRegisterFieldInfo( TIFF *tif, ttag_t tag, TIFFDataType dt )
+
+{
+ const TIFFFieldInfo *fld;
+
+ fld = _TIFFFindFieldInfo( tif, tag, dt );
+ if( fld == NULL )
+ {
+ fld = _TIFFCreateAnonFieldInfo( tif, tag, dt );
+ if (!_TIFFMergeFieldInfo(tif, fld, 1))
+ return NULL;
+ }
+
+ return fld;
+}
+
+TIFFFieldInfo*
+_TIFFCreateAnonFieldInfo(TIFF *tif, ttag_t tag, TIFFDataType field_type)
+{
+ TIFFFieldInfo *fld;
+ (void) tif;
+
+ fld = (TIFFFieldInfo *) _TIFFmalloc(sizeof (TIFFFieldInfo));
+ if (fld == NULL)
+ return NULL;
+ _TIFFmemset( fld, 0, sizeof(TIFFFieldInfo) );
+
+ fld->field_tag = tag;
+ fld->field_readcount = TIFF_VARIABLE2;
+ fld->field_writecount = TIFF_VARIABLE2;
+ fld->field_type = field_type;
+ fld->field_bit = FIELD_CUSTOM;
+ fld->field_oktochange = TRUE;
+ fld->field_passcount = TRUE;
+ fld->field_name = (char *) _TIFFmalloc(32);
+ if (fld->field_name == NULL) {
+ _TIFFfree(fld);
+ return NULL;
+ }
+
+ /*
+ * note that this name is a special sign to TIFFClose() and
+ * _TIFFSetupFieldInfo() to free the field
+ */
+ sprintf(fld->field_name, "Tag %d", (int) tag);
+
+ return fld;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_dirread.c b/Source/LibTIFF/tif_dirread.c
new file mode 100644
index 0000000..72a0807
--- /dev/null
+++ b/Source/LibTIFF/tif_dirread.c
@@ -0,0 +1,2009 @@
+/* $Id: tif_dirread.c,v 1.28 2009/09/06 13:11:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Read Support Routines.
+ */
+#include "tiffiop.h"
+
+#define IGNORE 0 /* tag placeholder used below */
+
+#ifdef HAVE_IEEEFP
+# define TIFFCvtIEEEFloatToNative(tif, n, fp)
+# define TIFFCvtIEEEDoubleToNative(tif, n, dp)
+#else
+extern void TIFFCvtIEEEFloatToNative(TIFF*, uint32, float*);
+extern void TIFFCvtIEEEDoubleToNative(TIFF*, uint32, double*);
+#endif
+
+static TIFFDirEntry* TIFFReadDirectoryFind(TIFFDirEntry* dir,
+ uint16 dircount, uint16 tagid);
+static int EstimateStripByteCounts(TIFF*, TIFFDirEntry*, uint16);
+static void MissingRequired(TIFF*, const char*);
+static int TIFFCheckDirOffset(TIFF*, toff_t);
+static int CheckDirCount(TIFF*, TIFFDirEntry*, uint32);
+static uint16 TIFFFetchDirectory(TIFF*, toff_t, TIFFDirEntry**, toff_t *);
+static tsize_t TIFFFetchData(TIFF*, TIFFDirEntry*, char*);
+static tsize_t TIFFFetchString(TIFF*, TIFFDirEntry*, char*);
+static float TIFFFetchRational(TIFF*, TIFFDirEntry*);
+static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*);
+static int TIFFFetchPerSampleShorts(TIFF*, TIFFDirEntry*, uint16*);
+static int TIFFFetchPerSampleLongs(TIFF*, TIFFDirEntry*, uint32*);
+static int TIFFFetchPerSampleAnys(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchShortArray(TIFF*, TIFFDirEntry*, uint16*);
+static int TIFFFetchStripThing(TIFF*, TIFFDirEntry*, long, uint32**);
+static int TIFFFetchRefBlackWhite(TIFF*, TIFFDirEntry*);
+static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
+static float TIFFFetchFloat(TIFF*, TIFFDirEntry*);
+static int TIFFFetchFloatArray(TIFF*, TIFFDirEntry*, float*);
+static int TIFFFetchDoubleArray(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchAnyArray(TIFF*, TIFFDirEntry*, double*);
+static int TIFFFetchShortPair(TIFF*, TIFFDirEntry*);
+static void ChopUpSingleUncompressedStrip(TIFF*);
+
+/*
+ * Read the next TIFF directory from a file and convert it to the internal
+ * format. We read directories sequentially.
+ */
+int
+TIFFReadDirectory(TIFF* tif)
+{
+ static const char module[] = "TIFFReadDirectory";
+
+ int n;
+ TIFFDirectory* td;
+ TIFFDirEntry *dp, *dir = NULL;
+ uint16 iv;
+ uint32 v;
+ const TIFFFieldInfo* fip;
+ size_t fix;
+ uint16 dircount;
+ int diroutoforderwarning = 0, compressionknown = 0;
+
+ tif->tif_diroff = tif->tif_nextdiroff;
+ /*
+ * Check whether we have the last offset or bad offset (IFD looping).
+ */
+ if (!TIFFCheckDirOffset(tif, tif->tif_nextdiroff))
+ return 0;
+ /*
+ * Cleanup any previous compression state.
+ */
+ (*tif->tif_cleanup)(tif);
+ tif->tif_curdir++;
+ dircount = TIFFFetchDirectory(tif, tif->tif_nextdiroff,
+ &dir, &tif->tif_nextdiroff);
+ if (!dircount) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Failed to read directory at offset %u",
+ tif->tif_name, tif->tif_nextdiroff);
+ return 0;
+ }
+
+ tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */
+ /*
+ * Setup default value and then make a pass over
+ * the fields to check type and tag information,
+ * and to extract info required to size data
+ * structures. A second pass is made afterwards
+ * to read in everthing not taken in the first pass.
+ */
+ td = &tif->tif_dir;
+ /* free any old stuff and reinit */
+ TIFFFreeDirectory(tif);
+ TIFFDefaultDirectory(tif);
+ /*
+ * Electronic Arts writes gray-scale TIFF files
+ * without a PlanarConfiguration directory entry.
+ * Thus we setup a default value here, even though
+ * the TIFF spec says there is no default value.
+ */
+ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
+
+ /*
+ * Sigh, we must make a separate pass through the
+ * directory for the following reason:
+ *
+ * We must process the Compression tag in the first pass
+ * in order to merge in codec-private tag definitions (otherwise
+ * we may get complaints about unknown tags). However, the
+ * Compression tag may be dependent on the SamplesPerPixel
+ * tag value because older TIFF specs permited Compression
+ * to be written as a SamplesPerPixel-count tag entry.
+ * Thus if we don't first figure out the correct SamplesPerPixel
+ * tag value then we may end up ignoring the Compression tag
+ * value because it has an incorrect count value (if the
+ * true value of SamplesPerPixel is not 1).
+ *
+ * It sure would have been nice if Aldus had really thought
+ * this stuff through carefully.
+ */
+ for (dp = dir, n = dircount; n > 0; n--, dp++) {
+ if (tif->tif_flags & TIFF_SWAB) {
+ TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dp->tdir_count, 2);
+ }
+ if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) {
+ if (!TIFFFetchNormalTag(tif, dp))
+ goto bad;
+ dp->tdir_tag = IGNORE;
+ }
+ }
+ /*
+ * First real pass over the directory.
+ */
+ fix = 0;
+ for (dp = dir, n = dircount; n > 0; n--, dp++) {
+
+ if (fix >= tif->tif_nfields || dp->tdir_tag == IGNORE)
+ continue;
+
+ /*
+ * Silicon Beach (at least) writes unordered
+ * directory tags (violating the spec). Handle
+ * it here, but be obnoxious (maybe they'll fix it?).
+ */
+ if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) {
+ if (!diroutoforderwarning) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: invalid TIFF directory; tags are not sorted in ascending order",
+ tif->tif_name);
+ diroutoforderwarning = 1;
+ }
+ fix = 0; /* O(n^2) */
+ }
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+ if (fix >= tif->tif_nfields ||
+ tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
+
+ TIFFWarningExt(tif->tif_clientdata,
+ module,
+ "%s: unknown field with tag %d (0x%x) encountered",
+ tif->tif_name,
+ dp->tdir_tag,
+ dp->tdir_tag);
+
+ if (!_TIFFMergeFieldInfo(tif,
+ _TIFFCreateAnonFieldInfo(tif,
+ dp->tdir_tag,
+ (TIFFDataType) dp->tdir_type),
+ 1))
+ {
+ TIFFWarningExt(tif->tif_clientdata,
+ module,
+ "Registering anonymous field with tag %d (0x%x) failed",
+ dp->tdir_tag,
+ dp->tdir_tag);
+ goto ignore;
+ }
+ fix = 0;
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+ }
+ /*
+ * Null out old tags that we ignore.
+ */
+ if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) {
+ ignore:
+ dp->tdir_tag = IGNORE;
+ continue;
+ }
+ /*
+ * Check data type.
+ */
+ fip = tif->tif_fieldinfo[fix];
+ while (dp->tdir_type != (unsigned short) fip->field_type
+ && fix < tif->tif_nfields) {
+ if (fip->field_type == TIFF_ANY) /* wildcard */
+ break;
+ fip = tif->tif_fieldinfo[++fix];
+ if (fix >= tif->tif_nfields ||
+ fip->field_tag != dp->tdir_tag) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: wrong data type %d for \"%s\"; tag ignored",
+ tif->tif_name, dp->tdir_type,
+ tif->tif_fieldinfo[fix-1]->field_name);
+ goto ignore;
+ }
+ }
+ /*
+ * Check count if known in advance.
+ */
+ if (fip->field_readcount != TIFF_VARIABLE
+ && fip->field_readcount != TIFF_VARIABLE2) {
+ uint32 expected = (fip->field_readcount == TIFF_SPP) ?
+ (uint32) td->td_samplesperpixel :
+ (uint32) fip->field_readcount;
+ if (!CheckDirCount(tif, dp, expected))
+ goto ignore;
+ }
+
+ switch (dp->tdir_tag) {
+ case TIFFTAG_COMPRESSION:
+ /*
+ * The 5.0 spec says the Compression tag has
+ * one value, while earlier specs say it has
+ * one value per sample. Because of this, we
+ * accept the tag if one value is supplied.
+ */
+ if (dp->tdir_count == 1) {
+ v = TIFFExtractData(tif,
+ dp->tdir_type, dp->tdir_offset);
+ if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+ goto bad;
+ else
+ compressionknown = 1;
+ break;
+ /* XXX: workaround for broken TIFFs */
+ } else if (dp->tdir_type == TIFF_LONG) {
+ if (!TIFFFetchPerSampleLongs(tif, dp, &v) ||
+ !TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+ goto bad;
+ } else {
+ if (!TIFFFetchPerSampleShorts(tif, dp, &iv)
+ || !TIFFSetField(tif, dp->tdir_tag, iv))
+ goto bad;
+ }
+ dp->tdir_tag = IGNORE;
+ break;
+ case TIFFTAG_STRIPOFFSETS:
+ case TIFFTAG_STRIPBYTECOUNTS:
+ case TIFFTAG_TILEOFFSETS:
+ case TIFFTAG_TILEBYTECOUNTS:
+ TIFFSetFieldBit(tif, fip->field_bit);
+ break;
+ case TIFFTAG_IMAGEWIDTH:
+ case TIFFTAG_IMAGELENGTH:
+ case TIFFTAG_IMAGEDEPTH:
+ case TIFFTAG_TILELENGTH:
+ case TIFFTAG_TILEWIDTH:
+ case TIFFTAG_TILEDEPTH:
+ case TIFFTAG_PLANARCONFIG:
+ case TIFFTAG_ROWSPERSTRIP:
+ case TIFFTAG_EXTRASAMPLES:
+ if (!TIFFFetchNormalTag(tif, dp))
+ goto bad;
+ dp->tdir_tag = IGNORE;
+ break;
+ }
+ }
+
+ /*
+ * XXX: OJPEG hack.
+ * If a) compression is OJPEG, b) planarconfig tag says it's separate,
+ * c) strip offsets/bytecounts tag are both present and
+ * d) both contain exactly one value, then we consistently find
+ * that the buggy implementation of the buggy compression scheme
+ * matches contig planarconfig best. So we 'fix-up' the tag here
+ */
+ if ((td->td_compression==COMPRESSION_OJPEG) &&
+ (td->td_planarconfig==PLANARCONFIG_SEPARATE)) {
+ dp = TIFFReadDirectoryFind(dir,dircount,TIFFTAG_STRIPOFFSETS);
+ if ((dp!=0) && (dp->tdir_count==1)) {
+ dp = TIFFReadDirectoryFind(dir, dircount,
+ TIFFTAG_STRIPBYTECOUNTS);
+ if ((dp!=0) && (dp->tdir_count==1)) {
+ td->td_planarconfig=PLANARCONFIG_CONTIG;
+ TIFFWarningExt(tif->tif_clientdata,
+ "TIFFReadDirectory",
+ "Planarconfig tag value assumed incorrect, "
+ "assuming data is contig instead of chunky");
+ }
+ }
+ }
+
+ /*
+ * Allocate directory structure and setup defaults.
+ */
+ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
+ MissingRequired(tif, "ImageLength");
+ goto bad;
+ }
+ /*
+ * Setup appropriate structures (by strip or by tile)
+ */
+ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) {
+ td->td_nstrips = TIFFNumberOfStrips(tif);
+ td->td_tilewidth = td->td_imagewidth;
+ td->td_tilelength = td->td_rowsperstrip;
+ td->td_tiledepth = td->td_imagedepth;
+ tif->tif_flags &= ~TIFF_ISTILED;
+ } else {
+ td->td_nstrips = TIFFNumberOfTiles(tif);
+ tif->tif_flags |= TIFF_ISTILED;
+ }
+ if (!td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: cannot handle zero number of %s",
+ tif->tif_name, isTiled(tif) ? "tiles" : "strips");
+ goto bad;
+ }
+ td->td_stripsperimage = td->td_nstrips;
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ td->td_stripsperimage /= td->td_samplesperpixel;
+ if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) {
+ if ((td->td_compression==COMPRESSION_OJPEG) &&
+ (isTiled(tif)==0) &&
+ (td->td_nstrips==1)) {
+ /*
+ * XXX: OJPEG hack.
+ * If a) compression is OJPEG, b) it's not a tiled TIFF,
+ * and c) the number of strips is 1,
+ * then we tolerate the absence of stripoffsets tag,
+ * because, presumably, all required data is in the
+ * JpegInterchangeFormat stream.
+ */
+ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
+ } else {
+ MissingRequired(tif,
+ isTiled(tif) ? "TileOffsets" : "StripOffsets");
+ goto bad;
+ }
+ }
+
+ /*
+ * Second pass: extract other information.
+ */
+ for (dp = dir, n = dircount; n > 0; n--, dp++) {
+ if (dp->tdir_tag == IGNORE)
+ continue;
+ switch (dp->tdir_tag) {
+ case TIFFTAG_MINSAMPLEVALUE:
+ case TIFFTAG_MAXSAMPLEVALUE:
+ case TIFFTAG_BITSPERSAMPLE:
+ case TIFFTAG_DATATYPE:
+ case TIFFTAG_SAMPLEFORMAT:
+ /*
+ * The 5.0 spec says the Compression tag has
+ * one value, while earlier specs say it has
+ * one value per sample. Because of this, we
+ * accept the tag if one value is supplied.
+ *
+ * The MinSampleValue, MaxSampleValue, BitsPerSample
+ * DataType and SampleFormat tags are supposed to be
+ * written as one value/sample, but some vendors
+ * incorrectly write one value only -- so we accept
+ * that as well (yech). Other vendors write correct
+ * value for NumberOfSamples, but incorrect one for
+ * BitsPerSample and friends, and we will read this
+ * too.
+ */
+ if (dp->tdir_count == 1) {
+ v = TIFFExtractData(tif,
+ dp->tdir_type, dp->tdir_offset);
+ if (!TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+ goto bad;
+ /* XXX: workaround for broken TIFFs */
+ } else if (dp->tdir_tag == TIFFTAG_BITSPERSAMPLE
+ && dp->tdir_type == TIFF_LONG) {
+ if (!TIFFFetchPerSampleLongs(tif, dp, &v) ||
+ !TIFFSetField(tif, dp->tdir_tag, (uint16)v))
+ goto bad;
+ } else {
+ if (!TIFFFetchPerSampleShorts(tif, dp, &iv) ||
+ !TIFFSetField(tif, dp->tdir_tag, iv))
+ goto bad;
+ }
+ break;
+ case TIFFTAG_SMINSAMPLEVALUE:
+ case TIFFTAG_SMAXSAMPLEVALUE:
+ {
+ double dv = 0.0;
+ if (!TIFFFetchPerSampleAnys(tif, dp, &dv) ||
+ !TIFFSetField(tif, dp->tdir_tag, dv))
+ goto bad;
+ }
+ break;
+ case TIFFTAG_STRIPOFFSETS:
+ case TIFFTAG_TILEOFFSETS:
+ if (!TIFFFetchStripThing(tif, dp,
+ td->td_nstrips, &td->td_stripoffset))
+ goto bad;
+ break;
+ case TIFFTAG_STRIPBYTECOUNTS:
+ case TIFFTAG_TILEBYTECOUNTS:
+ if (!TIFFFetchStripThing(tif, dp,
+ td->td_nstrips, &td->td_stripbytecount))
+ goto bad;
+ break;
+ case TIFFTAG_COLORMAP:
+ case TIFFTAG_TRANSFERFUNCTION:
+ {
+ char* cp;
+ /*
+ * TransferFunction can have either 1x or 3x
+ * data values; Colormap can have only 3x
+ * items.
+ */
+ v = 1L<<td->td_bitspersample;
+ if (dp->tdir_tag == TIFFTAG_COLORMAP ||
+ dp->tdir_count != v) {
+ if (!CheckDirCount(tif, dp, 3 * v))
+ break;
+ }
+ v *= sizeof(uint16);
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count,
+ sizeof (uint16),
+ "to read \"TransferFunction\" tag");
+ if (cp != NULL) {
+ if (TIFFFetchData(tif, dp, cp)) {
+ /*
+ * This deals with there being
+ * only one array to apply to
+ * all samples.
+ */
+ uint32 c = 1L << td->td_bitspersample;
+ if (dp->tdir_count == c)
+ v = 0L;
+ TIFFSetField(tif, dp->tdir_tag,
+ cp, cp+v, cp+2*v);
+ }
+ _TIFFfree(cp);
+ }
+ break;
+ }
+ case TIFFTAG_PAGENUMBER:
+ case TIFFTAG_HALFTONEHINTS:
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ case TIFFTAG_DOTRANGE:
+ (void) TIFFFetchShortPair(tif, dp);
+ break;
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ (void) TIFFFetchRefBlackWhite(tif, dp);
+ break;
+/* BEGIN REV 4.0 COMPATIBILITY */
+ case TIFFTAG_OSUBFILETYPE:
+ v = 0L;
+ switch (TIFFExtractData(tif, dp->tdir_type,
+ dp->tdir_offset)) {
+ case OFILETYPE_REDUCEDIMAGE:
+ v = FILETYPE_REDUCEDIMAGE;
+ break;
+ case OFILETYPE_PAGE:
+ v = FILETYPE_PAGE;
+ break;
+ }
+ if (v)
+ TIFFSetField(tif, TIFFTAG_SUBFILETYPE, v);
+ break;
+/* END REV 4.0 COMPATIBILITY */
+ default:
+ (void) TIFFFetchNormalTag(tif, dp);
+ break;
+ }
+ }
+ /*
+ * OJPEG hack:
+ * - If a) compression is OJPEG, and b) photometric tag is missing,
+ * then we consistently find that photometric should be YCbCr
+ * - If a) compression is OJPEG, and b) photometric tag says it's RGB,
+ * then we consistently find that the buggy implementation of the
+ * buggy compression scheme matches photometric YCbCr instead.
+ * - If a) compression is OJPEG, and b) bitspersample tag is missing,
+ * then we consistently find bitspersample should be 8.
+ * - If a) compression is OJPEG, b) samplesperpixel tag is missing,
+ * and c) photometric is RGB or YCbCr, then we consistently find
+ * samplesperpixel should be 3
+ * - If a) compression is OJPEG, b) samplesperpixel tag is missing,
+ * and c) photometric is MINISWHITE or MINISBLACK, then we consistently
+ * find samplesperpixel should be 3
+ */
+ if (td->td_compression==COMPRESSION_OJPEG)
+ {
+ if (!TIFFFieldSet(tif,FIELD_PHOTOMETRIC))
+ {
+ TIFFWarningExt(tif->tif_clientdata, "TIFFReadDirectory",
+ "Photometric tag is missing, assuming data is YCbCr");
+ if (!TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_YCBCR))
+ goto bad;
+ }
+ else if (td->td_photometric==PHOTOMETRIC_RGB)
+ {
+ td->td_photometric=PHOTOMETRIC_YCBCR;
+ TIFFWarningExt(tif->tif_clientdata, "TIFFReadDirectory",
+ "Photometric tag value assumed incorrect, "
+ "assuming data is YCbCr instead of RGB");
+ }
+ if (!TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
+ {
+ TIFFWarningExt(tif->tif_clientdata,"TIFFReadDirectory",
+ "BitsPerSample tag is missing, assuming 8 bits per sample");
+ if (!TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,8))
+ goto bad;
+ }
+ if (!TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
+ {
+ if ((td->td_photometric==PHOTOMETRIC_RGB)
+ || (td->td_photometric==PHOTOMETRIC_YCBCR))
+ {
+ TIFFWarningExt(tif->tif_clientdata,
+ "TIFFReadDirectory",
+ "SamplesPerPixel tag is missing, "
+ "assuming correct SamplesPerPixel value is 3");
+ if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,3))
+ goto bad;
+ }
+ else if ((td->td_photometric==PHOTOMETRIC_MINISWHITE)
+ || (td->td_photometric==PHOTOMETRIC_MINISBLACK))
+ {
+ TIFFWarningExt(tif->tif_clientdata,
+ "TIFFReadDirectory",
+ "SamplesPerPixel tag is missing, "
+ "assuming correct SamplesPerPixel value is 1");
+ if (!TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,1))
+ goto bad;
+ }
+ }
+ }
+ /*
+ * Verify Palette image has a Colormap.
+ */
+ if (td->td_photometric == PHOTOMETRIC_PALETTE &&
+ !TIFFFieldSet(tif, FIELD_COLORMAP)) {
+ MissingRequired(tif, "Colormap");
+ goto bad;
+ }
+ /*
+ * OJPEG hack:
+ * We do no further messing with strip/tile offsets/bytecounts in OJPEG
+ * TIFFs
+ */
+ if (td->td_compression!=COMPRESSION_OJPEG)
+ {
+ /*
+ * Attempt to deal with a missing StripByteCounts tag.
+ */
+ if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) {
+ /*
+ * Some manufacturers violate the spec by not giving
+ * the size of the strips. In this case, assume there
+ * is one uncompressed strip of data.
+ */
+ if ((td->td_planarconfig == PLANARCONFIG_CONTIG &&
+ td->td_nstrips > 1) ||
+ (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
+ td->td_nstrips != td->td_samplesperpixel)) {
+ MissingRequired(tif, "StripByteCounts");
+ goto bad;
+ }
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: TIFF directory is missing required "
+ "\"%s\" field, calculating from imagelength",
+ tif->tif_name,
+ _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
+ if (EstimateStripByteCounts(tif, dir, dircount) < 0)
+ goto bad;
+ /*
+ * Assume we have wrong StripByteCount value (in case
+ * of single strip) in following cases:
+ * - it is equal to zero along with StripOffset;
+ * - it is larger than file itself (in case of uncompressed
+ * image);
+ * - it is smaller than the size of the bytes per row
+ * multiplied on the number of rows. The last case should
+ * not be checked in the case of writing new image,
+ * because we may do not know the exact strip size
+ * until the whole image will be written and directory
+ * dumped out.
+ */
+ #define BYTECOUNTLOOKSBAD \
+ ( (td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \
+ (td->td_compression == COMPRESSION_NONE && \
+ td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0]) || \
+ (tif->tif_mode == O_RDONLY && \
+ td->td_compression == COMPRESSION_NONE && \
+ td->td_stripbytecount[0] < TIFFScanlineSize(tif) * td->td_imagelength) )
+
+ } else if (td->td_nstrips == 1
+ && td->td_stripoffset[0] != 0
+ && BYTECOUNTLOOKSBAD) {
+ /*
+ * XXX: Plexus (and others) sometimes give a value of
+ * zero for a tag when they don't know what the
+ * correct value is! Try and handle the simple case
+ * of estimating the size of a one strip image.
+ */
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: Bogus \"%s\" field, ignoring and calculating from imagelength",
+ tif->tif_name,
+ _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
+ if(EstimateStripByteCounts(tif, dir, dircount) < 0)
+ goto bad;
+ } else if (td->td_planarconfig == PLANARCONFIG_CONTIG
+ && td->td_nstrips > 2
+ && td->td_compression == COMPRESSION_NONE
+ && td->td_stripbytecount[0] != td->td_stripbytecount[1]
+ && td->td_stripbytecount[0] != 0
+ && td->td_stripbytecount[1] != 0 ) {
+ /*
+ * XXX: Some vendors fill StripByteCount array with
+ * absolutely wrong values (it can be equal to
+ * StripOffset array, for example). Catch this case
+ * here.
+ */
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: Wrong \"%s\" field, ignoring and calculating from imagelength",
+ tif->tif_name,
+ _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name);
+ if (EstimateStripByteCounts(tif, dir, dircount) < 0)
+ goto bad;
+ }
+ }
+ if (dir) {
+ _TIFFfree((char *)dir);
+ dir = NULL;
+ }
+ if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE))
+ td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1);
+ /*
+ * Setup default compression scheme.
+ */
+
+ /*
+ * XXX: We can optimize checking for the strip bounds using the sorted
+ * bytecounts array. See also comments for TIFFAppendToStrip()
+ * function in tif_write.c.
+ */
+ if (td->td_nstrips > 1) {
+ tstrip_t strip;
+
+ td->td_stripbytecountsorted = 1;
+ for (strip = 1; strip < td->td_nstrips; strip++) {
+ if (td->td_stripoffset[strip - 1] >
+ td->td_stripoffset[strip]) {
+ td->td_stripbytecountsorted = 0;
+ break;
+ }
+ }
+ }
+
+ if (!TIFFFieldSet(tif, FIELD_COMPRESSION))
+ TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
+ /*
+ * Some manufacturers make life difficult by writing
+ * large amounts of uncompressed data as a single strip.
+ * This is contrary to the recommendations of the spec.
+ * The following makes an attempt at breaking such images
+ * into strips closer to the recommended 8k bytes. A
+ * side effect, however, is that the RowsPerStrip tag
+ * value may be changed.
+ */
+ if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE &&
+ (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP)
+ ChopUpSingleUncompressedStrip(tif);
+
+ /*
+ * Reinitialize i/o since we are starting on a new directory.
+ */
+ tif->tif_row = (uint32) -1;
+ tif->tif_curstrip = (tstrip_t) -1;
+ tif->tif_col = (uint32) -1;
+ tif->tif_curtile = (ttile_t) -1;
+ tif->tif_tilesize = (tsize_t) -1;
+
+ tif->tif_scanlinesize = TIFFScanlineSize(tif);
+ if (!tif->tif_scanlinesize) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: cannot handle zero scanline size",
+ tif->tif_name);
+ return (0);
+ }
+
+ if (isTiled(tif)) {
+ tif->tif_tilesize = TIFFTileSize(tif);
+ if (!tif->tif_tilesize) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: cannot handle zero tile size",
+ tif->tif_name);
+ return (0);
+ }
+ } else {
+ if (!TIFFStripSize(tif)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: cannot handle zero strip size",
+ tif->tif_name);
+ return (0);
+ }
+ }
+ return (1);
+bad:
+ if (dir)
+ _TIFFfree(dir);
+ return (0);
+}
+
+static TIFFDirEntry*
+TIFFReadDirectoryFind(TIFFDirEntry* dir, uint16 dircount, uint16 tagid)
+{
+ TIFFDirEntry* m;
+ uint16 n;
+ for (m=dir, n=0; n<dircount; m++, n++)
+ {
+ if (m->tdir_tag==tagid)
+ return(m);
+ }
+ return(0);
+}
+
+/*
+ * Read custom directory from the arbitarry offset.
+ * The code is very similar to TIFFReadDirectory().
+ */
+int
+TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
+ const TIFFFieldInfo info[], size_t n)
+{
+ static const char module[] = "TIFFReadCustomDirectory";
+
+ TIFFDirectory* td = &tif->tif_dir;
+ TIFFDirEntry *dp, *dir = NULL;
+ const TIFFFieldInfo* fip;
+ size_t fix;
+ uint16 i, dircount;
+
+ _TIFFSetupFieldInfo(tif, info, n);
+
+ dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL);
+ if (!dircount) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Failed to read custom directory at offset %u",
+ tif->tif_name, diroff);
+ return 0;
+ }
+
+ TIFFFreeDirectory(tif);
+ _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory));
+
+ fix = 0;
+ for (dp = dir, i = dircount; i > 0; i--, dp++) {
+ if (tif->tif_flags & TIFF_SWAB) {
+ TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dp->tdir_count, 2);
+ }
+
+ if (fix >= tif->tif_nfields || dp->tdir_tag == IGNORE)
+ continue;
+
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+
+ if (fix >= tif->tif_nfields ||
+ tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) {
+
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: unknown field with tag %d (0x%x) encountered",
+ tif->tif_name, dp->tdir_tag, dp->tdir_tag);
+ if (!_TIFFMergeFieldInfo(tif,
+ _TIFFCreateAnonFieldInfo(tif,
+ dp->tdir_tag,
+ (TIFFDataType) dp->tdir_type),
+ 1))
+ {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "Registering anonymous field with tag %d (0x%x) failed",
+ dp->tdir_tag, dp->tdir_tag);
+ goto ignore;
+ }
+
+ fix = 0;
+ while (fix < tif->tif_nfields &&
+ tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag)
+ fix++;
+ }
+ /*
+ * Null out old tags that we ignore.
+ */
+ if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) {
+ ignore:
+ dp->tdir_tag = IGNORE;
+ continue;
+ }
+ /*
+ * Check data type.
+ */
+ fip = tif->tif_fieldinfo[fix];
+ while (dp->tdir_type != (unsigned short) fip->field_type
+ && fix < tif->tif_nfields) {
+ if (fip->field_type == TIFF_ANY) /* wildcard */
+ break;
+ fip = tif->tif_fieldinfo[++fix];
+ if (fix >= tif->tif_nfields ||
+ fip->field_tag != dp->tdir_tag) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: wrong data type %d for \"%s\"; tag ignored",
+ tif->tif_name, dp->tdir_type,
+ tif->tif_fieldinfo[fix-1]->field_name);
+ goto ignore;
+ }
+ }
+ /*
+ * Check count if known in advance.
+ */
+ if (fip->field_readcount != TIFF_VARIABLE
+ && fip->field_readcount != TIFF_VARIABLE2) {
+ uint32 expected = (fip->field_readcount == TIFF_SPP) ?
+ (uint32) td->td_samplesperpixel :
+ (uint32) fip->field_readcount;
+ if (!CheckDirCount(tif, dp, expected))
+ goto ignore;
+ }
+
+ /*
+ * EXIF tags which need to be specifically processed.
+ */
+ switch (dp->tdir_tag) {
+ case EXIFTAG_SUBJECTDISTANCE:
+ (void) TIFFFetchSubjectDistance(tif, dp);
+ break;
+ default:
+ (void) TIFFFetchNormalTag(tif, dp);
+ break;
+ }
+ }
+
+ if (dir)
+ _TIFFfree(dir);
+ return 1;
+}
+
+/*
+ * EXIF is important special case of custom IFD, so we have a special
+ * function to read it.
+ */
+int
+TIFFReadEXIFDirectory(TIFF* tif, toff_t diroff)
+{
+ size_t exifFieldInfoCount;
+ const TIFFFieldInfo *exifFieldInfo =
+ _TIFFGetExifFieldInfo(&exifFieldInfoCount);
+ return TIFFReadCustomDirectory(tif, diroff, exifFieldInfo,
+ exifFieldInfoCount);
+}
+
+static int
+EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
+{
+ static const char module[] = "EstimateStripByteCounts";
+
+ TIFFDirEntry *dp;
+ TIFFDirectory *td = &tif->tif_dir;
+ uint32 strip;
+
+ if (td->td_stripbytecount)
+ _TIFFfree(td->td_stripbytecount);
+ td->td_stripbytecount = (uint32*)
+ _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint32),
+ "for \"StripByteCounts\" array");
+ if( td->td_stripbytecount == NULL )
+ return -1;
+
+ if (td->td_compression != COMPRESSION_NONE) {
+ uint32 space = (uint32)(sizeof (TIFFHeader)
+ + sizeof (uint16)
+ + (dircount * sizeof (TIFFDirEntry))
+ + sizeof (uint32));
+ toff_t filesize = TIFFGetFileSize(tif);
+ uint16 n;
+
+ /* calculate amount of space used by indirect values */
+ for (dp = dir, n = dircount; n > 0; n--, dp++)
+ {
+ uint32 cc = TIFFDataWidth((TIFFDataType) dp->tdir_type);
+ if (cc == 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Cannot determine size of unknown tag type %d",
+ tif->tif_name, dp->tdir_type);
+ return -1;
+ }
+ cc = cc * dp->tdir_count;
+ if (cc > sizeof (uint32))
+ space += cc;
+ }
+ space = filesize - space;
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ space /= td->td_samplesperpixel;
+ for (strip = 0; strip < td->td_nstrips; strip++)
+ td->td_stripbytecount[strip] = space;
+ /*
+ * This gross hack handles the case were the offset to
+ * the last strip is past the place where we think the strip
+ * should begin. Since a strip of data must be contiguous,
+ * it's safe to assume that we've overestimated the amount
+ * of data in the strip and trim this number back accordingly.
+ */
+ strip--;
+ if (((toff_t)(td->td_stripoffset[strip]+
+ td->td_stripbytecount[strip])) > filesize)
+ td->td_stripbytecount[strip] =
+ filesize - td->td_stripoffset[strip];
+ } else if (isTiled(tif)) {
+ uint32 bytespertile = TIFFTileSize(tif);
+
+ for (strip = 0; strip < td->td_nstrips; strip++)
+ td->td_stripbytecount[strip] = bytespertile;
+ } else {
+ uint32 rowbytes = TIFFScanlineSize(tif);
+ uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage;
+ for (strip = 0; strip < td->td_nstrips; strip++)
+ td->td_stripbytecount[strip] = rowbytes * rowsperstrip;
+ }
+ TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
+ if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
+ td->td_rowsperstrip = td->td_imagelength;
+ return 1;
+}
+
+static void
+MissingRequired(TIFF* tif, const char* tagname)
+{
+ static const char module[] = "MissingRequired";
+
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: TIFF directory is missing required \"%s\" field",
+ tif->tif_name, tagname);
+}
+
+/*
+ * Check the directory offset against the list of already seen directory
+ * offsets. This is a trick to prevent IFD looping. The one can create TIFF
+ * file with looped directory pointers. We will maintain a list of already
+ * seen directories and check every IFD offset against that list.
+ */
+static int
+TIFFCheckDirOffset(TIFF* tif, toff_t diroff)
+{
+ uint16 n;
+
+ if (diroff == 0) /* no more directories */
+ return 0;
+
+ for (n = 0; n < tif->tif_dirnumber && tif->tif_dirlist; n++) {
+ if (tif->tif_dirlist[n] == diroff)
+ return 0;
+ }
+
+ tif->tif_dirnumber++;
+
+ if (tif->tif_dirnumber > tif->tif_dirlistsize) {
+ toff_t* new_dirlist;
+
+ /*
+ * XXX: Reduce memory allocation granularity of the dirlist
+ * array.
+ */
+ new_dirlist = (toff_t *)_TIFFCheckRealloc(tif,
+ tif->tif_dirlist,
+ tif->tif_dirnumber,
+ 2 * sizeof(toff_t),
+ "for IFD list");
+ if (!new_dirlist)
+ return 0;
+ tif->tif_dirlistsize = 2 * tif->tif_dirnumber;
+ tif->tif_dirlist = new_dirlist;
+ }
+
+ tif->tif_dirlist[tif->tif_dirnumber - 1] = diroff;
+
+ return 1;
+}
+
+/*
+ * Check the count field of a directory entry against a known value. The
+ * caller is expected to skip/ignore the tag if there is a mismatch.
+ */
+static int
+CheckDirCount(TIFF* tif, TIFFDirEntry* dir, uint32 count)
+{
+ if (count > dir->tdir_count) {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "incorrect count for field \"%s\" (%u, expecting %u); tag ignored",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+ dir->tdir_count, count);
+ return (0);
+ } else if (count < dir->tdir_count) {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "incorrect count for field \"%s\" (%u, expecting %u); tag trimmed",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+ dir->tdir_count, count);
+ return (1);
+ }
+ return (1);
+}
+
+/*
+ * Read IFD structure from the specified offset. If the pointer to
+ * nextdiroff variable has been specified, read it too. Function returns a
+ * number of fields in the directory or 0 if failed.
+ */
+static uint16
+TIFFFetchDirectory(TIFF* tif, toff_t diroff, TIFFDirEntry **pdir,
+ toff_t *nextdiroff)
+{
+ static const char module[] = "TIFFFetchDirectory";
+
+ TIFFDirEntry *dir;
+ uint16 dircount;
+
+ assert(pdir);
+
+ tif->tif_diroff = diroff;
+ if (nextdiroff)
+ *nextdiroff = 0;
+ if (!isMapped(tif)) {
+ if (!SeekOK(tif, tif->tif_diroff)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Seek error accessing TIFF directory",
+ tif->tif_name);
+ return 0;
+ }
+ if (!ReadOK(tif, &dircount, sizeof (uint16))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Can not read TIFF directory count",
+ tif->tif_name);
+ return 0;
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount,
+ sizeof (TIFFDirEntry),
+ "to read TIFF directory");
+ if (dir == NULL)
+ return 0;
+ if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%.100s: Can not read TIFF directory",
+ tif->tif_name);
+ _TIFFfree(dir);
+ return 0;
+ }
+ /*
+ * Read offset to next directory for sequential scans if
+ * needed.
+ */
+ if (nextdiroff)
+ (void) ReadOK(tif, nextdiroff, sizeof(uint32));
+ } else {
+ toff_t off = tif->tif_diroff;
+
+ /*
+ * Check for integer overflow when validating the dir_off,
+ * otherwise a very high offset may cause an OOB read and
+ * crash the client. Make two comparisons instead of
+ *
+ * off + sizeof(uint16) > tif->tif_size
+ *
+ * to avoid overflow.
+ */
+ if (tif->tif_size < sizeof (uint16) ||
+ off > tif->tif_size - sizeof(uint16)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Can not read TIFF directory count",
+ tif->tif_name);
+ return 0;
+ } else {
+ _TIFFmemcpy(&dircount, tif->tif_base + off,
+ sizeof(uint16));
+ }
+ off += sizeof (uint16);
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ dir = (TIFFDirEntry *)_TIFFCheckMalloc(tif, dircount,
+ sizeof(TIFFDirEntry),
+ "to read TIFF directory");
+ if (dir == NULL)
+ return 0;
+ if (off + dircount * sizeof (TIFFDirEntry) > tif->tif_size) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Can not read TIFF directory",
+ tif->tif_name);
+ _TIFFfree(dir);
+ return 0;
+ } else {
+ _TIFFmemcpy(dir, tif->tif_base + off,
+ dircount * sizeof(TIFFDirEntry));
+ }
+ if (nextdiroff) {
+ off += dircount * sizeof (TIFFDirEntry);
+ if (off + sizeof (uint32) <= tif->tif_size) {
+ _TIFFmemcpy(nextdiroff, tif->tif_base + off,
+ sizeof (uint32));
+ }
+ }
+ }
+ if (nextdiroff && tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(nextdiroff);
+ *pdir = dir;
+ return dircount;
+}
+
+/*
+ * Fetch a contiguous directory item.
+ */
+static tsize_t
+TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ uint32 w = TIFFDataWidth((TIFFDataType) dir->tdir_type);
+ /*
+ * FIXME: butecount should have tsize_t type, but for now libtiff
+ * defines tsize_t as a signed 32-bit integer and we are losing
+ * ability to read arrays larger than 2^31 bytes. So we are using
+ * uint32 instead of tsize_t here.
+ */
+ uint32 cc = dir->tdir_count * w;
+
+ /* Check for overflow. */
+ if (!dir->tdir_count || !w || cc / w != dir->tdir_count)
+ goto bad;
+
+ if (!isMapped(tif)) {
+ if (!SeekOK(tif, dir->tdir_offset))
+ goto bad;
+ if (!ReadOK(tif, cp, cc))
+ goto bad;
+ } else {
+ /* Check for overflow. */
+ if (dir->tdir_offset + cc < dir->tdir_offset
+ || dir->tdir_offset + cc < cc
+ || dir->tdir_offset + cc > tif->tif_size)
+ goto bad;
+ _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, cc);
+ }
+ if (tif->tif_flags & TIFF_SWAB) {
+ switch (dir->tdir_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_FLOAT:
+ TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+ break;
+ case TIFF_DOUBLE:
+ TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+ break;
+ }
+ }
+ return (cc);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error fetching data for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return (tsize_t) 0;
+}
+
+/*
+ * Fetch an ASCII item from the file.
+ */
+static tsize_t
+TIFFFetchString(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ if (dir->tdir_count <= 4) {
+ uint32 l = dir->tdir_offset;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&l);
+ _TIFFmemcpy(cp, &l, dir->tdir_count);
+ return (1);
+ }
+ return (TIFFFetchData(tif, dir, cp));
+}
+
+/*
+ * Convert numerator+denominator to float.
+ */
+static int
+cvtRational(TIFF* tif, TIFFDirEntry* dir, uint32 num, uint32 denom, float* rv)
+{
+ if (denom == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%s: Rational with zero denominator (num = %u)",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name, num);
+ return (0);
+ } else {
+ if (dir->tdir_type == TIFF_RATIONAL)
+ *rv = ((float)num / (float)denom);
+ else
+ *rv = ((float)(int32)num / (float)(int32)denom);
+ return (1);
+ }
+}
+
+/*
+ * Fetch a rational item from the file at offset off and return the value as a
+ * floating point number.
+ */
+static float
+TIFFFetchRational(TIFF* tif, TIFFDirEntry* dir)
+{
+ uint32 l[2];
+ float v;
+
+ return (!TIFFFetchData(tif, dir, (char *)l) ||
+ !cvtRational(tif, dir, l[0], l[1], &v) ? 1.0f : v);
+}
+
+/*
+ * Fetch a single floating point value from the offset field and return it as
+ * a native float.
+ */
+static float
+TIFFFetchFloat(TIFF* tif, TIFFDirEntry* dir)
+{
+ float v;
+ int32 l = TIFFExtractData(tif, dir->tdir_type, dir->tdir_offset);
+ _TIFFmemcpy(&v, &l, sizeof(float));
+ TIFFCvtIEEEFloatToNative(tif, 1, &v);
+ return (v);
+}
+
+/*
+ * Fetch an array of BYTE or SBYTE values.
+ */
+static int
+TIFFFetchByteArray(TIFF* tif, TIFFDirEntry* dir, uint8* v)
+{
+ if (dir->tdir_count <= 4) {
+ /*
+ * Extract data from offset field.
+ */
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ if (dir->tdir_type == TIFF_SBYTE)
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset & 0xff;
+ case 3: v[2] = (dir->tdir_offset >> 8) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 16) & 0xff;
+ case 1: v[0] = dir->tdir_offset >> 24;
+ }
+ else
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset & 0xff;
+ case 3: v[2] = (dir->tdir_offset >> 8) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 16) & 0xff;
+ case 1: v[0] = dir->tdir_offset >> 24;
+ }
+ } else {
+ if (dir->tdir_type == TIFF_SBYTE)
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset >> 24;
+ case 3: v[2] = (dir->tdir_offset >> 16) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 8) & 0xff;
+ case 1: v[0] = dir->tdir_offset & 0xff;
+ }
+ else
+ switch (dir->tdir_count) {
+ case 4: v[3] = dir->tdir_offset >> 24;
+ case 3: v[2] = (dir->tdir_offset >> 16) & 0xff;
+ case 2: v[1] = (dir->tdir_offset >> 8) & 0xff;
+ case 1: v[0] = dir->tdir_offset & 0xff;
+ }
+ }
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char*) v) != 0); /* XXX */
+}
+
+/*
+ * Fetch an array of SHORT or SSHORT values.
+ */
+static int
+TIFFFetchShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+ if (dir->tdir_count <= 2) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ switch (dir->tdir_count) {
+ case 2: v[1] = (uint16) (dir->tdir_offset & 0xffff);
+ case 1: v[0] = (uint16) (dir->tdir_offset >> 16);
+ }
+ } else {
+ switch (dir->tdir_count) {
+ case 2: v[1] = (uint16) (dir->tdir_offset >> 16);
+ case 1: v[0] = (uint16) (dir->tdir_offset & 0xffff);
+ }
+ }
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char *)v) != 0);
+}
+
+/*
+ * Fetch a pair of SHORT or BYTE values. Some tags may have either BYTE
+ * or SHORT type and this function works with both ones.
+ */
+static int
+TIFFFetchShortPair(TIFF* tif, TIFFDirEntry* dir)
+{
+ /*
+ * Prevent overflowing the v stack arrays below by performing a sanity
+ * check on tdir_count, this should never be greater than two.
+ */
+ if (dir->tdir_count > 2) {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "unexpected count for field \"%s\", %u, expected 2; ignored",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name,
+ dir->tdir_count);
+ return 0;
+ }
+
+ switch (dir->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ {
+ uint8 v[4];
+ return TIFFFetchByteArray(tif, dir, v)
+ && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]);
+ }
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ {
+ uint16 v[2];
+ return TIFFFetchShortArray(tif, dir, v)
+ && TIFFSetField(tif, dir->tdir_tag, v[0], v[1]);
+ }
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Fetch an array of LONG or SLONG values.
+ */
+static int
+TIFFFetchLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
+{
+ if (dir->tdir_count == 1) {
+ v[0] = dir->tdir_offset;
+ return (1);
+ } else
+ return (TIFFFetchData(tif, dir, (char*) v) != 0);
+}
+
+/*
+ * Fetch an array of RATIONAL or SRATIONAL values.
+ */
+static int
+TIFFFetchRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+ int ok = 0;
+ uint32* l;
+
+ l = (uint32*)_TIFFCheckMalloc(tif,
+ dir->tdir_count, TIFFDataWidth((TIFFDataType) dir->tdir_type),
+ "to fetch array of rationals");
+ if (l) {
+ if (TIFFFetchData(tif, dir, (char *)l)) {
+ uint32 i;
+ for (i = 0; i < dir->tdir_count; i++) {
+ ok = cvtRational(tif, dir,
+ l[2*i+0], l[2*i+1], &v[i]);
+ if (!ok)
+ break;
+ }
+ }
+ _TIFFfree((char *)l);
+ }
+ return (ok);
+}
+
+/*
+ * Fetch an array of FLOAT values.
+ */
+static int
+TIFFFetchFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+
+ if (dir->tdir_count == 1) {
+ v[0] = *(float*) &dir->tdir_offset;
+ TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else if (TIFFFetchData(tif, dir, (char*) v)) {
+ TIFFCvtIEEEFloatToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else
+ return (0);
+}
+
+/*
+ * Fetch an array of DOUBLE values.
+ */
+static int
+TIFFFetchDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+ if (TIFFFetchData(tif, dir, (char*) v)) {
+ TIFFCvtIEEEDoubleToNative(tif, dir->tdir_count, v);
+ return (1);
+ } else
+ return (0);
+}
+
+/*
+ * Fetch an array of ANY values. The actual values are returned as doubles
+ * which should be able hold all the types. Yes, there really should be an
+ * tany_t to avoid this potential non-portability ... Note in particular that
+ * we assume that the double return value vector is large enough to read in
+ * any fundamental type. We use that vector as a buffer to read in the base
+ * type vector and then convert it in place to double (from end to front of
+ * course).
+ */
+static int
+TIFFFetchAnyArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+ int i;
+
+ switch (dir->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ if (!TIFFFetchByteArray(tif, dir, (uint8*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_BYTE) {
+ uint8* vp = (uint8*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int8* vp = (int8*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ if (!TIFFFetchShortArray(tif, dir, (uint16*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_SHORT) {
+ uint16* vp = (uint16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int16* vp = (int16*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ if (!TIFFFetchLongArray(tif, dir, (uint32*) v))
+ return (0);
+ if (dir->tdir_type == TIFF_LONG) {
+ uint32* vp = (uint32*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ } else {
+ int32* vp = (int32*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ if (!TIFFFetchRationalArray(tif, dir, (float*) v))
+ return (0);
+ { float* vp = (float*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_FLOAT:
+ if (!TIFFFetchFloatArray(tif, dir, (float*) v))
+ return (0);
+ { float* vp = (float*) v;
+ for (i = dir->tdir_count-1; i >= 0; i--)
+ v[i] = vp[i];
+ }
+ break;
+ case TIFF_DOUBLE:
+ return (TIFFFetchDoubleArray(tif, dir, (double*) v));
+ default:
+ /* TIFF_NOTYPE */
+ /* TIFF_ASCII */
+ /* TIFF_UNDEFINED */
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "cannot read TIFF_ANY type %d for field \"%s\"",
+ dir->tdir_type,
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Fetch a tag that is not handled by special case code.
+ */
+static int
+TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp)
+{
+ static const char mesg[] = "to fetch tag value";
+ int ok = 0;
+ const TIFFFieldInfo* fip = _TIFFFieldWithTag(tif, dp->tdir_tag);
+
+ if (dp->tdir_count > 1) { /* array of values */
+ char* cp = NULL;
+
+ switch (dp->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (uint8), mesg);
+ ok = cp && TIFFFetchByteArray(tif, dp, (uint8*) cp);
+ break;
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (uint16), mesg);
+ ok = cp && TIFFFetchShortArray(tif, dp, (uint16*) cp);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (uint32), mesg);
+ ok = cp && TIFFFetchLongArray(tif, dp, (uint32*) cp);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (float), mesg);
+ ok = cp && TIFFFetchRationalArray(tif, dp, (float*) cp);
+ break;
+ case TIFF_FLOAT:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (float), mesg);
+ ok = cp && TIFFFetchFloatArray(tif, dp, (float*) cp);
+ break;
+ case TIFF_DOUBLE:
+ cp = (char *)_TIFFCheckMalloc(tif,
+ dp->tdir_count, sizeof (double), mesg);
+ ok = cp && TIFFFetchDoubleArray(tif, dp, (double*) cp);
+ break;
+ case TIFF_ASCII:
+ case TIFF_UNDEFINED: /* bit of a cheat... */
+ /*
+ * Some vendors write strings w/o the trailing
+ * NULL byte, so always append one just in case.
+ */
+ cp = (char *)_TIFFCheckMalloc(tif, dp->tdir_count + 1,
+ 1, mesg);
+ if( (ok = (cp && TIFFFetchString(tif, dp, cp))) != 0 )
+ cp[dp->tdir_count] = '\0'; /* XXX */
+ break;
+ }
+ if (ok) {
+ ok = (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, dp->tdir_count, cp)
+ : TIFFSetField(tif, dp->tdir_tag, cp));
+ }
+ if (cp != NULL)
+ _TIFFfree(cp);
+ } else if (CheckDirCount(tif, dp, 1)) { /* singleton value */
+ switch (dp->tdir_type) {
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ /*
+ * If the tag is also acceptable as a LONG or SLONG
+ * then TIFFSetField will expect an uint32 parameter
+ * passed to it (through varargs). Thus, for machines
+ * where sizeof (int) != sizeof (uint32) we must do
+ * a careful check here. It's hard to say if this
+ * is worth optimizing.
+ *
+ * NB: We use TIFFFieldWithTag here knowing that
+ * it returns us the first entry in the table
+ * for the tag and that that entry is for the
+ * widest potential data type the tag may have.
+ */
+ { TIFFDataType type = fip->field_type;
+ if (type != TIFF_LONG && type != TIFF_SLONG) {
+ uint16 v = (uint16)
+ TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+ ok = (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, 1, &v)
+ : TIFFSetField(tif, dp->tdir_tag, v));
+ break;
+ }
+ }
+ /* fall thru... */
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ { uint32 v32 =
+ TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset);
+ ok = (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, 1, &v32)
+ : TIFFSetField(tif, dp->tdir_tag, v32));
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ case TIFF_FLOAT:
+ { float v = (dp->tdir_type == TIFF_FLOAT ?
+ TIFFFetchFloat(tif, dp)
+ : TIFFFetchRational(tif, dp));
+ ok = (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, 1, &v)
+ : TIFFSetField(tif, dp->tdir_tag, v));
+ }
+ break;
+ case TIFF_DOUBLE:
+ { double v;
+ ok = (TIFFFetchDoubleArray(tif, dp, &v) &&
+ (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, 1, &v)
+ : TIFFSetField(tif, dp->tdir_tag, v))
+ );
+ }
+ break;
+ case TIFF_ASCII:
+ case TIFF_UNDEFINED: /* bit of a cheat... */
+ { char c[2];
+ if( (ok = (TIFFFetchString(tif, dp, c) != 0)) != 0 ) {
+ c[1] = '\0'; /* XXX paranoid */
+ ok = (fip->field_passcount ?
+ TIFFSetField(tif, dp->tdir_tag, 1, c)
+ : TIFFSetField(tif, dp->tdir_tag, c));
+ }
+ }
+ break;
+ }
+ }
+ return (ok);
+}
+
+#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
+/*
+ * Fetch samples/pixel short values for
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleShorts(TIFF* tif, TIFFDirEntry* dir, uint16* pl)
+{
+ uint16 samples = tif->tif_dir.td_samplesperpixel;
+ int status = 0;
+
+ if (CheckDirCount(tif, dir, (uint32) samples)) {
+ uint16 buf[10];
+ uint16* v = buf;
+
+ if (dir->tdir_count > NITEMS(buf))
+ v = (uint16*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint16),
+ "to fetch per-sample values");
+ if (v && TIFFFetchShortArray(tif, dir, v)) {
+ uint16 i;
+ int check_count = dir->tdir_count;
+ if( samples < check_count )
+ check_count = samples;
+
+ for (i = 1; i < check_count; i++)
+ if (v[i] != v[0]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot handle different per-sample values for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ goto bad;
+ }
+ *pl = v[0];
+ status = 1;
+ }
+ bad:
+ if (v && v != buf)
+ _TIFFfree(v);
+ }
+ return (status);
+}
+
+/*
+ * Fetch samples/pixel long values for
+ * the specified tag and verify that
+ * all values are the same.
+ */
+static int
+TIFFFetchPerSampleLongs(TIFF* tif, TIFFDirEntry* dir, uint32* pl)
+{
+ uint16 samples = tif->tif_dir.td_samplesperpixel;
+ int status = 0;
+
+ if (CheckDirCount(tif, dir, (uint32) samples)) {
+ uint32 buf[10];
+ uint32* v = buf;
+
+ if (dir->tdir_count > NITEMS(buf))
+ v = (uint32*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof(uint32),
+ "to fetch per-sample values");
+ if (v && TIFFFetchLongArray(tif, dir, v)) {
+ uint16 i;
+ int check_count = dir->tdir_count;
+
+ if( samples < check_count )
+ check_count = samples;
+ for (i = 1; i < check_count; i++)
+ if (v[i] != v[0]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot handle different per-sample values for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ goto bad;
+ }
+ *pl = v[0];
+ status = 1;
+ }
+ bad:
+ if (v && v != buf)
+ _TIFFfree(v);
+ }
+ return (status);
+}
+
+/*
+ * Fetch samples/pixel ANY values for the specified tag and verify that all
+ * values are the same.
+ */
+static int
+TIFFFetchPerSampleAnys(TIFF* tif, TIFFDirEntry* dir, double* pl)
+{
+ uint16 samples = tif->tif_dir.td_samplesperpixel;
+ int status = 0;
+
+ if (CheckDirCount(tif, dir, (uint32) samples)) {
+ double buf[10];
+ double* v = buf;
+
+ if (dir->tdir_count > NITEMS(buf))
+ v = (double*) _TIFFCheckMalloc(tif, dir->tdir_count, sizeof (double),
+ "to fetch per-sample values");
+ if (v && TIFFFetchAnyArray(tif, dir, v)) {
+ uint16 i;
+ int check_count = dir->tdir_count;
+ if( samples < check_count )
+ check_count = samples;
+
+ for (i = 1; i < check_count; i++)
+ if (v[i] != v[0]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot handle different per-sample values for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ goto bad;
+ }
+ *pl = v[0];
+ status = 1;
+ }
+ bad:
+ if (v && v != buf)
+ _TIFFfree(v);
+ }
+ return (status);
+}
+#undef NITEMS
+
+/*
+ * Fetch a set of offsets or lengths.
+ * While this routine says "strips", in fact it's also used for tiles.
+ */
+static int
+TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, long nstrips, uint32** lpp)
+{
+ register uint32* lp;
+ int status;
+
+ CheckDirCount(tif, dir, (uint32) nstrips);
+
+ /*
+ * Allocate space for strip information.
+ */
+ if (*lpp == NULL &&
+ (*lpp = (uint32 *)_TIFFCheckMalloc(tif,
+ nstrips, sizeof (uint32), "for strip array")) == NULL)
+ return (0);
+ lp = *lpp;
+ _TIFFmemset( lp, 0, sizeof(uint32) * nstrips );
+
+ if (dir->tdir_type == (int)TIFF_SHORT) {
+ /*
+ * Handle uint16->uint32 expansion.
+ */
+ uint16* dp = (uint16*) _TIFFCheckMalloc(tif,
+ dir->tdir_count, sizeof (uint16), "to fetch strip tag");
+ if (dp == NULL)
+ return (0);
+ if( (status = TIFFFetchShortArray(tif, dir, dp)) != 0 ) {
+ int i;
+
+ for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
+ {
+ lp[i] = dp[i];
+ }
+ }
+ _TIFFfree((char*) dp);
+
+ } else if( nstrips != (int) dir->tdir_count ) {
+ /* Special case to correct length */
+
+ uint32* dp = (uint32*) _TIFFCheckMalloc(tif,
+ dir->tdir_count, sizeof (uint32), "to fetch strip tag");
+ if (dp == NULL)
+ return (0);
+
+ status = TIFFFetchLongArray(tif, dir, dp);
+ if( status != 0 ) {
+ int i;
+
+ for( i = 0; i < nstrips && i < (int) dir->tdir_count; i++ )
+ {
+ lp[i] = dp[i];
+ }
+ }
+
+ _TIFFfree( (char *) dp );
+ } else
+ status = TIFFFetchLongArray(tif, dir, lp);
+
+ return (status);
+}
+
+/*
+ * Fetch and set the RefBlackWhite tag.
+ */
+static int
+TIFFFetchRefBlackWhite(TIFF* tif, TIFFDirEntry* dir)
+{
+ static const char mesg[] = "for \"ReferenceBlackWhite\" array";
+ char* cp;
+ int ok;
+
+ if (dir->tdir_type == TIFF_RATIONAL)
+ return (TIFFFetchNormalTag(tif, dir));
+ /*
+ * Handle LONG's for backward compatibility.
+ */
+ cp = (char *)_TIFFCheckMalloc(tif, dir->tdir_count,
+ sizeof (uint32), mesg);
+ if( (ok = (cp && TIFFFetchLongArray(tif, dir, (uint32*) cp))) != 0) {
+ float* fp = (float*)
+ _TIFFCheckMalloc(tif, dir->tdir_count, sizeof (float), mesg);
+ if( (ok = (fp != NULL)) != 0 ) {
+ uint32 i;
+ for (i = 0; i < dir->tdir_count; i++)
+ fp[i] = (float)((uint32*) cp)[i];
+ ok = TIFFSetField(tif, dir->tdir_tag, fp);
+ _TIFFfree((char*) fp);
+ }
+ }
+ if (cp)
+ _TIFFfree(cp);
+ return (ok);
+}
+
+/*
+ * Fetch and set the SubjectDistance EXIF tag.
+ */
+static int
+TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir)
+{
+ uint32 l[2];
+ float v;
+ int ok = 0;
+
+ if (TIFFFetchData(tif, dir, (char *)l)
+ && cvtRational(tif, dir, l[0], l[1], &v)) {
+ /*
+ * XXX: Numerator 0xFFFFFFFF means that we have infinite
+ * distance. Indicate that with a negative floating point
+ * SubjectDistance value.
+ */
+ ok = TIFFSetField(tif, dir->tdir_tag,
+ (l[0] != 0xFFFFFFFF) ? v : -v);
+ }
+
+ return ok;
+}
+
+/*
+ * Replace a single strip (tile) of uncompressed data by multiple strips
+ * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for
+ * dealing with large images or for dealing with machines with a limited
+ * amount memory.
+ */
+static void
+ChopUpSingleUncompressedStrip(TIFF* tif)
+{
+ register TIFFDirectory *td = &tif->tif_dir;
+ uint32 bytecount = td->td_stripbytecount[0];
+ uint32 offset = td->td_stripoffset[0];
+ tsize_t rowbytes = TIFFVTileSize(tif, 1), stripbytes;
+ tstrip_t strip, nstrips, rowsperstrip;
+ uint32* newcounts;
+ uint32* newoffsets;
+
+ /*
+ * Make the rows hold at least one scanline, but fill specified amount
+ * of data if possible.
+ */
+ if (rowbytes > STRIP_SIZE_DEFAULT) {
+ stripbytes = rowbytes;
+ rowsperstrip = 1;
+ } else if (rowbytes > 0 ) {
+ rowsperstrip = STRIP_SIZE_DEFAULT / rowbytes;
+ stripbytes = rowbytes * rowsperstrip;
+ }
+ else
+ return;
+
+ /*
+ * never increase the number of strips in an image
+ */
+ if (rowsperstrip >= td->td_rowsperstrip)
+ return;
+ nstrips = (tstrip_t) TIFFhowmany(bytecount, stripbytes);
+ if( nstrips == 0 ) /* something is wonky, do nothing. */
+ return;
+
+ newcounts = (uint32*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint32),
+ "for chopped \"StripByteCounts\" array");
+ newoffsets = (uint32*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint32),
+ "for chopped \"StripOffsets\" array");
+ if (newcounts == NULL || newoffsets == NULL) {
+ /*
+ * Unable to allocate new strip information, give up and use
+ * the original one strip information.
+ */
+ if (newcounts != NULL)
+ _TIFFfree(newcounts);
+ if (newoffsets != NULL)
+ _TIFFfree(newoffsets);
+ return;
+ }
+ /*
+ * Fill the strip information arrays with new bytecounts and offsets
+ * that reflect the broken-up format.
+ */
+ for (strip = 0; strip < nstrips; strip++) {
+ if ((uint32)stripbytes > bytecount)
+ stripbytes = bytecount;
+ newcounts[strip] = stripbytes;
+ newoffsets[strip] = offset;
+ offset += stripbytes;
+ bytecount -= stripbytes;
+ }
+ /*
+ * Replace old single strip info with multi-strip info.
+ */
+ td->td_stripsperimage = td->td_nstrips = nstrips;
+ TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+
+ _TIFFfree(td->td_stripbytecount);
+ _TIFFfree(td->td_stripoffset);
+ td->td_stripbytecount = newcounts;
+ td->td_stripoffset = newoffsets;
+ td->td_stripbytecountsorted = 1;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_dirwrite.c b/Source/LibTIFF/tif_dirwrite.c
new file mode 100644
index 0000000..ffb9740
--- /dev/null
+++ b/Source/LibTIFF/tif_dirwrite.c
@@ -0,0 +1,1406 @@
+/* $Id: tif_dirwrite.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Write Support Routines.
+ */
+#include "tiffiop.h"
+
+#ifdef HAVE_IEEEFP
+# define TIFFCvtNativeToIEEEFloat(tif, n, fp)
+# define TIFFCvtNativeToIEEEDouble(tif, n, dp)
+#else
+extern void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);
+extern void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);
+#endif
+
+static int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);
+static void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);
+static void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16);
+static int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
+static int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
+static int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
+static int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
+static int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*);
+static int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*);
+static int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*);
+static int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*);
+static int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*);
+static int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
+static int TIFFWriteAnyArray(TIFF*,
+ TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
+static int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);
+static int TIFFWriteInkNames(TIFF*, TIFFDirEntry*);
+static int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
+static int TIFFLinkDirectory(TIFF*);
+
+#define WriteRationalPair(type, tag1, v1, tag2, v2) { \
+ TIFFWriteRational((tif), (type), (tag1), (dir), (v1)) \
+ TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2)) \
+ (dir)++; \
+}
+#define TIFFWriteRational(tif, type, tag, dir, v) \
+ (dir)->tdir_tag = (tag); \
+ (dir)->tdir_type = (type); \
+ (dir)->tdir_count = 1; \
+ if (!TIFFWriteRationalArray((tif), (dir), &(v))) \
+ goto bad;
+
+/*
+ * Write the contents of the current directory
+ * to the specified file. This routine doesn't
+ * handle overwriting a directory with auxiliary
+ * storage that's been changed.
+ */
+static int
+_TIFFWriteDirectory(TIFF* tif, int done)
+{
+ uint16 dircount;
+ toff_t diroff;
+ ttag_t tag;
+ uint32 nfields;
+ tsize_t dirsize;
+ char* data;
+ TIFFDirEntry* dir;
+ TIFFDirectory* td;
+ unsigned long b, fields[FIELD_SETLONGS];
+ int fi, nfi;
+
+ if (tif->tif_mode == O_RDONLY)
+ return (1);
+ /*
+ * Clear write state so that subsequent images with
+ * different characteristics get the right buffers
+ * setup for them.
+ */
+ if (done)
+ {
+ if (tif->tif_flags & TIFF_POSTENCODE) {
+ tif->tif_flags &= ~TIFF_POSTENCODE;
+ if (!(*tif->tif_postencode)(tif)) {
+ TIFFErrorExt(tif->tif_clientdata,
+ tif->tif_name,
+ "Error post-encoding before directory write");
+ return (0);
+ }
+ }
+ (*tif->tif_close)(tif); /* shutdown encoder */
+ /*
+ * Flush any data that might have been written
+ * by the compression close+cleanup routines.
+ */
+ if (tif->tif_rawcc > 0
+ && (tif->tif_flags & TIFF_BEENWRITING) != 0
+ && !TIFFFlushData1(tif)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error flushing data before directory write");
+ return (0);
+ }
+ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_rawdata = NULL;
+ tif->tif_rawcc = 0;
+ tif->tif_rawdatasize = 0;
+ }
+ tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
+ }
+
+ td = &tif->tif_dir;
+ /*
+ * Size the directory so that we can calculate
+ * offsets for the data items that aren't kept
+ * in-place in each field.
+ */
+ nfields = 0;
+ for (b = 0; b <= FIELD_LAST; b++)
+ if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
+ nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
+ nfields += td->td_customValueCount;
+ dirsize = nfields * sizeof (TIFFDirEntry);
+ data = (char*) _TIFFmalloc(dirsize);
+ if (data == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot write directory, out of space");
+ return (0);
+ }
+ /*
+ * Directory hasn't been placed yet, put
+ * it at the end of the file and link it
+ * into the existing directory structure.
+ */
+ if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif))
+ goto bad;
+ tif->tif_dataoff = (toff_t)(
+ tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
+ if (tif->tif_dataoff & 1)
+ tif->tif_dataoff++;
+ (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
+ tif->tif_curdir++;
+ dir = (TIFFDirEntry*) data;
+ /*
+ * Setup external form of directory
+ * entries and write data items.
+ */
+ _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
+ /*
+ * Write out ExtraSamples tag only if
+ * extra samples are present in the data.
+ */
+ if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) {
+ ResetFieldBit(fields, FIELD_EXTRASAMPLES);
+ nfields--;
+ dirsize -= sizeof (TIFFDirEntry);
+ } /*XXX*/
+ for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
+ const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
+
+ /*
+ * For custom fields, we test to see if the custom field
+ * is set or not. For normal fields, we just use the
+ * FieldSet test.
+ */
+ if( fip->field_bit == FIELD_CUSTOM )
+ {
+ int ci, is_set = FALSE;
+
+ for( ci = 0; ci < td->td_customValueCount; ci++ )
+ is_set |= (td->td_customValues[ci].info == fip);
+
+ if( !is_set )
+ continue;
+ }
+ else if (!FieldSet(fields, fip->field_bit))
+ continue;
+
+ /*
+ * Handle other fields.
+ */
+ switch (fip->field_bit)
+ {
+ case FIELD_STRIPOFFSETS:
+ /*
+ * We use one field bit for both strip and tile
+
+ * offsets, and so must be careful in selecting
+ * the appropriate field descriptor (so that tags
+ * are written in sorted order).
+ */
+ tag = isTiled(tif) ?
+ TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
+ if (tag != fip->field_tag)
+ continue;
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (uint16) TIFF_LONG;
+ dir->tdir_count = (uint32) td->td_nstrips;
+ if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset))
+ goto bad;
+ break;
+ case FIELD_STRIPBYTECOUNTS:
+ /*
+ * We use one field bit for both strip and tile
+ * byte counts, and so must be careful in selecting
+ * the appropriate field descriptor (so that tags
+ * are written in sorted order).
+ */
+ tag = isTiled(tif) ?
+ TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
+ if (tag != fip->field_tag)
+ continue;
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (uint16) TIFF_LONG;
+ dir->tdir_count = (uint32) td->td_nstrips;
+ if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount))
+ goto bad;
+ break;
+ case FIELD_ROWSPERSTRIP:
+ TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP,
+ dir, td->td_rowsperstrip);
+ break;
+ case FIELD_COLORMAP:
+ if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir,
+ 3, td->td_colormap))
+ goto bad;
+ break;
+ case FIELD_IMAGEDIMENSIONS:
+ TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH,
+ dir++, td->td_imagewidth);
+ TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
+ dir, td->td_imagelength);
+ break;
+ case FIELD_TILEDIMENSIONS:
+ TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
+ dir++, td->td_tilewidth);
+ TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH,
+ dir, td->td_tilelength);
+ break;
+ case FIELD_COMPRESSION:
+ TIFFSetupShort(tif, TIFFTAG_COMPRESSION,
+ dir, td->td_compression);
+ break;
+ case FIELD_PHOTOMETRIC:
+ TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC,
+ dir, td->td_photometric);
+ break;
+ case FIELD_POSITION:
+ WriteRationalPair(TIFF_RATIONAL,
+ TIFFTAG_XPOSITION, td->td_xposition,
+ TIFFTAG_YPOSITION, td->td_yposition);
+ break;
+ case FIELD_RESOLUTION:
+ WriteRationalPair(TIFF_RATIONAL,
+ TIFFTAG_XRESOLUTION, td->td_xresolution,
+ TIFFTAG_YRESOLUTION, td->td_yresolution);
+ break;
+ case FIELD_BITSPERSAMPLE:
+ case FIELD_MINSAMPLEVALUE:
+ case FIELD_MAXSAMPLEVALUE:
+ case FIELD_SAMPLEFORMAT:
+ if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir))
+ goto bad;
+ break;
+ case FIELD_SMINSAMPLEVALUE:
+ case FIELD_SMAXSAMPLEVALUE:
+ if (!TIFFWritePerSampleAnys(tif,
+ _TIFFSampleToTagType(tif), fip->field_tag, dir))
+ goto bad;
+ break;
+ case FIELD_PAGENUMBER:
+ case FIELD_HALFTONEHINTS:
+ case FIELD_YCBCRSUBSAMPLING:
+ if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
+ goto bad;
+ break;
+ case FIELD_INKNAMES:
+ if (!TIFFWriteInkNames(tif, dir))
+ goto bad;
+ break;
+ case FIELD_TRANSFERFUNCTION:
+ if (!TIFFWriteTransferFunction(tif, dir))
+ goto bad;
+ break;
+ case FIELD_SUBIFD:
+ /*
+ * XXX: Always write this field using LONG type
+ * for backward compatibility.
+ */
+ dir->tdir_tag = (uint16) fip->field_tag;
+ dir->tdir_type = (uint16) TIFF_LONG;
+ dir->tdir_count = (uint32) td->td_nsubifd;
+ if (!TIFFWriteLongArray(tif, dir, td->td_subifd))
+ goto bad;
+ /*
+ * Total hack: if this directory includes a SubIFD
+ * tag then force the next <n> directories to be
+ * written as ``sub directories'' of this one. This
+ * is used to write things like thumbnails and
+ * image masks that one wants to keep out of the
+ * normal directory linkage access mechanism.
+ */
+ if (dir->tdir_count > 0) {
+ tif->tif_flags |= TIFF_INSUBIFD;
+ tif->tif_nsubifd = (uint16) dir->tdir_count;
+ if (dir->tdir_count > 1)
+ tif->tif_subifdoff = dir->tdir_offset;
+ else
+ tif->tif_subifdoff = (uint32)(
+ tif->tif_diroff
+ + sizeof (uint16)
+ + ((char*)&dir->tdir_offset-data));
+ }
+ break;
+ default:
+ /* XXX: Should be fixed and removed. */
+ if (fip->field_tag == TIFFTAG_DOTRANGE) {
+ if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
+ goto bad;
+ }
+ else if (!TIFFWriteNormalTag(tif, dir, fip))
+ goto bad;
+ break;
+ }
+ dir++;
+
+ if( fip->field_bit != FIELD_CUSTOM )
+ ResetFieldBit(fields, fip->field_bit);
+ }
+
+ /*
+ * Write directory.
+ */
+ dircount = (uint16) nfields;
+ diroff = (uint32) tif->tif_nextdiroff;
+ if (tif->tif_flags & TIFF_SWAB) {
+ /*
+ * The file's byte order is opposite to the
+ * native machine architecture. We overwrite
+ * the directory information with impunity
+ * because it'll be released below after we
+ * write it to the file. Note that all the
+ * other tag construction routines assume that
+ * we do this byte-swapping; i.e. they only
+ * byte-swap indirect data.
+ */
+ for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
+ TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dir->tdir_count, 2);
+ }
+ dircount = (uint16) nfields;
+ TIFFSwabShort(&dircount);
+ TIFFSwabLong(&diroff);
+ }
+ (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
+ if (!WriteOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory count");
+ goto bad;
+ }
+ if (!WriteOK(tif, data, dirsize)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory contents");
+ goto bad;
+ }
+ if (!WriteOK(tif, &diroff, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory link");
+ goto bad;
+ }
+ if (done) {
+ TIFFFreeDirectory(tif);
+ tif->tif_flags &= ~TIFF_DIRTYDIRECT;
+ (*tif->tif_cleanup)(tif);
+
+ /*
+ * Reset directory-related state for subsequent
+ * directories.
+ */
+ TIFFCreateDirectory(tif);
+ }
+ _TIFFfree(data);
+ return (1);
+bad:
+ _TIFFfree(data);
+ return (0);
+}
+#undef WriteRationalPair
+
+int
+TIFFWriteDirectory(TIFF* tif)
+{
+ return _TIFFWriteDirectory(tif, TRUE);
+}
+
+/*
+ * Similar to TIFFWriteDirectory(), writes the directory out
+ * but leaves all data structures in memory so that it can be
+ * written again. This will make a partially written TIFF file
+ * readable before it is successfully completed/closed.
+ */
+int
+TIFFCheckpointDirectory(TIFF* tif)
+{
+ int rc;
+ /* Setup the strips arrays, if they haven't already been. */
+ if (tif->tif_dir.td_stripoffset == NULL)
+ (void) TIFFSetupStrips(tif);
+ rc = _TIFFWriteDirectory(tif, FALSE);
+ (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
+ return rc;
+}
+
+static int
+_TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
+{
+ uint16 dircount;
+ uint32 nfields;
+ tsize_t dirsize;
+ char* data;
+ TIFFDirEntry* dir;
+ TIFFDirectory* td;
+ unsigned long b, fields[FIELD_SETLONGS];
+ int fi, nfi;
+
+ if (tif->tif_mode == O_RDONLY)
+ return (1);
+
+ td = &tif->tif_dir;
+ /*
+ * Size the directory so that we can calculate
+ * offsets for the data items that aren't kept
+ * in-place in each field.
+ */
+ nfields = 0;
+ for (b = 0; b <= FIELD_LAST; b++)
+ if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
+ nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
+ nfields += td->td_customValueCount;
+ dirsize = nfields * sizeof (TIFFDirEntry);
+ data = (char*) _TIFFmalloc(dirsize);
+ if (data == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Cannot write directory, out of space");
+ return (0);
+ }
+ /*
+ * Put the directory at the end of the file.
+ */
+ tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+ tif->tif_dataoff = (toff_t)(
+ tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
+ if (tif->tif_dataoff & 1)
+ tif->tif_dataoff++;
+ (void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
+ dir = (TIFFDirEntry*) data;
+ /*
+ * Setup external form of directory
+ * entries and write data items.
+ */
+ _TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
+
+ for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
+ const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
+
+ /*
+ * For custom fields, we test to see if the custom field
+ * is set or not. For normal fields, we just use the
+ * FieldSet test.
+ */
+ if( fip->field_bit == FIELD_CUSTOM )
+ {
+ int ci, is_set = FALSE;
+
+ for( ci = 0; ci < td->td_customValueCount; ci++ )
+ is_set |= (td->td_customValues[ci].info == fip);
+
+ if( !is_set )
+ continue;
+ }
+ else if (!FieldSet(fields, fip->field_bit))
+ continue;
+
+ if( fip->field_bit != FIELD_CUSTOM )
+ ResetFieldBit(fields, fip->field_bit);
+ }
+
+ /*
+ * Write directory.
+ */
+ dircount = (uint16) nfields;
+ *pdiroff = (uint32) tif->tif_nextdiroff;
+ if (tif->tif_flags & TIFF_SWAB) {
+ /*
+ * The file's byte order is opposite to the
+ * native machine architecture. We overwrite
+ * the directory information with impunity
+ * because it'll be released below after we
+ * write it to the file. Note that all the
+ * other tag construction routines assume that
+ * we do this byte-swapping; i.e. they only
+ * byte-swap indirect data.
+ */
+ for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
+ TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
+ TIFFSwabArrayOfLong(&dir->tdir_count, 2);
+ }
+ dircount = (uint16) nfields;
+ TIFFSwabShort(&dircount);
+ TIFFSwabLong(pdiroff);
+ }
+ (void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
+ if (!WriteOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory count");
+ goto bad;
+ }
+ if (!WriteOK(tif, data, dirsize)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory contents");
+ goto bad;
+ }
+ if (!WriteOK(tif, pdiroff, sizeof (uint32))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing directory link");
+ goto bad;
+ }
+ _TIFFfree(data);
+ return (1);
+bad:
+ _TIFFfree(data);
+ return (0);
+}
+
+int
+TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
+{
+ return _TIFFWriteCustomDirectory(tif, pdiroff);
+}
+
+/*
+ * Process tags that are not special cased.
+ */
+static int
+TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
+{
+ uint16 wc = (uint16) fip->field_writecount;
+ uint32 wc2;
+
+ dir->tdir_tag = (uint16) fip->field_tag;
+ dir->tdir_type = (uint16) fip->field_type;
+ dir->tdir_count = wc;
+
+ switch (fip->field_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ if (fip->field_passcount) {
+ uint16* wp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &wp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &wp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteShortArray(tif, dir, wp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ uint16 sv;
+ TIFFGetField(tif, fip->field_tag, &sv);
+ dir->tdir_offset =
+ TIFFInsertData(tif, dir->tdir_type, sv);
+ } else {
+ uint16* wp;
+ TIFFGetField(tif, fip->field_tag, &wp);
+ if (!TIFFWriteShortArray(tif, dir, wp))
+ return 0;
+ }
+ }
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_IFD:
+ if (fip->field_passcount) {
+ uint32* lp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &lp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &lp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteLongArray(tif, dir, lp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ /* XXX handle LONG->SHORT conversion */
+ TIFFGetField(tif, fip->field_tag,
+ &dir->tdir_offset);
+ } else {
+ uint32* lp;
+ TIFFGetField(tif, fip->field_tag, &lp);
+ if (!TIFFWriteLongArray(tif, dir, lp))
+ return 0;
+ }
+ }
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ if (fip->field_passcount) {
+ float* fp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &fp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &fp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteRationalArray(tif, dir, fp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ float fv;
+ TIFFGetField(tif, fip->field_tag, &fv);
+ if (!TIFFWriteRationalArray(tif, dir, &fv))
+ return 0;
+ } else {
+ float* fp;
+ TIFFGetField(tif, fip->field_tag, &fp);
+ if (!TIFFWriteRationalArray(tif, dir, fp))
+ return 0;
+ }
+ }
+ break;
+ case TIFF_FLOAT:
+ if (fip->field_passcount) {
+ float* fp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &fp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &fp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteFloatArray(tif, dir, fp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ float fv;
+ TIFFGetField(tif, fip->field_tag, &fv);
+ if (!TIFFWriteFloatArray(tif, dir, &fv))
+ return 0;
+ } else {
+ float* fp;
+ TIFFGetField(tif, fip->field_tag, &fp);
+ if (!TIFFWriteFloatArray(tif, dir, fp))
+ return 0;
+ }
+ }
+ break;
+ case TIFF_DOUBLE:
+ if (fip->field_passcount) {
+ double* dp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &dp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &dp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteDoubleArray(tif, dir, dp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ double dv;
+ TIFFGetField(tif, fip->field_tag, &dv);
+ if (!TIFFWriteDoubleArray(tif, dir, &dv))
+ return 0;
+ } else {
+ double* dp;
+ TIFFGetField(tif, fip->field_tag, &dp);
+ if (!TIFFWriteDoubleArray(tif, dir, dp))
+ return 0;
+ }
+ }
+ break;
+ case TIFF_ASCII:
+ {
+ char* cp;
+ if (fip->field_passcount)
+ {
+ if( wc == (uint16) TIFF_VARIABLE2 )
+ TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+ else
+ TIFFGetField(tif, fip->field_tag, &wc, &cp);
+ }
+ else
+ TIFFGetField(tif, fip->field_tag, &cp);
+
+ dir->tdir_count = (uint32) (strlen(cp) + 1);
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return (0);
+ }
+ break;
+
+ case TIFF_BYTE:
+ case TIFF_SBYTE:
+ if (fip->field_passcount) {
+ char* cp;
+ if (wc == (uint16) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+ dir->tdir_count = wc2;
+ } else { /* Assume TIFF_VARIABLE */
+ TIFFGetField(tif, fip->field_tag, &wc, &cp);
+ dir->tdir_count = wc;
+ }
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return 0;
+ } else {
+ if (wc == 1) {
+ char cv;
+ TIFFGetField(tif, fip->field_tag, &cv);
+ if (!TIFFWriteByteArray(tif, dir, &cv))
+ return 0;
+ } else {
+ char* cp;
+ TIFFGetField(tif, fip->field_tag, &cp);
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return 0;
+ }
+ }
+ break;
+
+ case TIFF_UNDEFINED:
+ { char* cp;
+ if (wc == (unsigned short) TIFF_VARIABLE) {
+ TIFFGetField(tif, fip->field_tag, &wc, &cp);
+ dir->tdir_count = wc;
+ } else if (wc == (unsigned short) TIFF_VARIABLE2) {
+ TIFFGetField(tif, fip->field_tag, &wc2, &cp);
+ dir->tdir_count = wc2;
+ } else
+ TIFFGetField(tif, fip->field_tag, &cp);
+ if (!TIFFWriteByteArray(tif, dir, cp))
+ return (0);
+ }
+ break;
+
+ case TIFF_NOTYPE:
+ break;
+ }
+ return (1);
+}
+
+/*
+ * Setup a directory entry with either a SHORT
+ * or LONG type according to the value.
+ */
+static void
+TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
+{
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_count = 1;
+ if (v > 0xffffL) {
+ dir->tdir_type = (short) TIFF_LONG;
+ dir->tdir_offset = v;
+ } else {
+ dir->tdir_type = (short) TIFF_SHORT;
+ dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
+ }
+}
+
+/*
+ * Setup a SHORT directory entry
+ */
+static void
+TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v)
+{
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_count = 1;
+ dir->tdir_type = (short) TIFF_SHORT;
+ dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
+}
+#undef MakeShortDirent
+
+#define NITEMS(x) (sizeof (x) / sizeof (x[0]))
+/*
+ * Setup a directory entry that references a
+ * samples/pixel array of SHORT values and
+ * (potentially) write the associated indirect
+ * values.
+ */
+static int
+TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+ uint16 buf[10], v;
+ uint16* w = buf;
+ uint16 i, samples = tif->tif_dir.td_samplesperpixel;
+ int status;
+
+ if (samples > NITEMS(buf)) {
+ w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
+ if (w == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No space to write per-sample shorts");
+ return (0);
+ }
+ }
+ TIFFGetField(tif, tag, &v);
+ for (i = 0; i < samples; i++)
+ w[i] = v;
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (uint16) TIFF_SHORT;
+ dir->tdir_count = samples;
+ status = TIFFWriteShortArray(tif, dir, w);
+ if (w != buf)
+ _TIFFfree((char*) w);
+ return (status);
+}
+
+/*
+ * Setup a directory entry that references a samples/pixel array of ``type''
+ * values and (potentially) write the associated indirect values. The source
+ * data from TIFFGetField() for the specified tag must be returned as double.
+ */
+static int
+TIFFWritePerSampleAnys(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
+{
+ double buf[10], v;
+ double* w = buf;
+ uint16 i, samples = tif->tif_dir.td_samplesperpixel;
+ int status;
+
+ if (samples > NITEMS(buf)) {
+ w = (double*) _TIFFmalloc(samples * sizeof (double));
+ if (w == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No space to write per-sample values");
+ return (0);
+ }
+ }
+ TIFFGetField(tif, tag, &v);
+ for (i = 0; i < samples; i++)
+ w[i] = v;
+ status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
+ if (w != buf)
+ _TIFFfree(w);
+ return (status);
+}
+#undef NITEMS
+
+/*
+ * Setup a pair of shorts that are returned by
+ * value, rather than as a reference to an array.
+ */
+static int
+TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
+{
+ uint16 v[2];
+
+ TIFFGetField(tif, tag, &v[0], &v[1]);
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (uint16) TIFF_SHORT;
+ dir->tdir_count = 2;
+ return (TIFFWriteShortArray(tif, dir, v));
+}
+
+/*
+ * Setup a directory entry for an NxM table of shorts,
+ * where M is known to be 2**bitspersample, and write
+ * the associated indirect data.
+ */
+static int
+TIFFWriteShortTable(TIFF* tif,
+ ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
+{
+ uint32 i, off;
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (short) TIFF_SHORT;
+ /* XXX -- yech, fool TIFFWriteData */
+ dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);
+ off = tif->tif_dataoff;
+ for (i = 0; i < n; i++)
+ if (!TIFFWriteData(tif, dir, (char *)table[i]))
+ return (0);
+ dir->tdir_count *= n;
+ dir->tdir_offset = off;
+ return (1);
+}
+
+/*
+ * Write/copy data associated with an ASCII or opaque tag value.
+ */
+static int
+TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ if (dir->tdir_count <= 4) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ dir->tdir_offset = (uint32)cp[0] << 24;
+ if (dir->tdir_count >= 2)
+ dir->tdir_offset |= (uint32)cp[1] << 16;
+ if (dir->tdir_count >= 3)
+ dir->tdir_offset |= (uint32)cp[2] << 8;
+ if (dir->tdir_count == 4)
+ dir->tdir_offset |= cp[3];
+ } else {
+ dir->tdir_offset = cp[0];
+ if (dir->tdir_count >= 2)
+ dir->tdir_offset |= (uint32) cp[1] << 8;
+ if (dir->tdir_count >= 3)
+ dir->tdir_offset |= (uint32) cp[2] << 16;
+ if (dir->tdir_count == 4)
+ dir->tdir_offset |= (uint32) cp[3] << 24;
+ }
+ return 1;
+ } else
+ return TIFFWriteData(tif, dir, cp);
+}
+
+/*
+ * Setup a directory entry of an array of SHORT
+ * or SSHORT and write the associated indirect values.
+ */
+static int
+TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
+{
+ if (dir->tdir_count <= 2) {
+ if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
+ dir->tdir_offset = (uint32) v[0] << 16;
+ if (dir->tdir_count == 2)
+ dir->tdir_offset |= v[1] & 0xffff;
+ } else {
+ dir->tdir_offset = v[0] & 0xffff;
+ if (dir->tdir_count == 2)
+ dir->tdir_offset |= (uint32) v[1] << 16;
+ }
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of LONG
+ * or SLONG and write the associated indirect values.
+ */
+static int
+TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
+{
+ if (dir->tdir_count == 1) {
+ dir->tdir_offset = v[0];
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Setup a directory entry of an array of RATIONAL
+ * or SRATIONAL and write the associated indirect values.
+ */
+static int
+TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+ uint32 i;
+ uint32* t;
+ int status;
+
+ t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32));
+ if (t == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No space to write RATIONAL array");
+ return (0);
+ }
+ for (i = 0; i < dir->tdir_count; i++) {
+ float fv = v[i];
+ int sign = 1;
+ uint32 den;
+
+ if (fv < 0) {
+ if (dir->tdir_type == TIFF_RATIONAL) {
+ TIFFWarningExt(tif->tif_clientdata,
+ tif->tif_name,
+ "\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
+ _TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,
+ fv);
+ fv = 0;
+ } else
+ fv = -fv, sign = -1;
+ }
+ den = 1L;
+ if (fv > 0) {
+ while (fv < 1L<<(31-3) && den < 1L<<(31-3))
+ fv *= 1<<3, den *= 1L<<3;
+ }
+ t[2*i+0] = (uint32) (sign * (fv + 0.5));
+ t[2*i+1] = den;
+ }
+ status = TIFFWriteData(tif, dir, (char *)t);
+ _TIFFfree((char*) t);
+ return (status);
+}
+
+static int
+TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
+{
+ TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v);
+ if (dir->tdir_count == 1) {
+ dir->tdir_offset = *(uint32*) &v[0];
+ return (1);
+ } else
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+static int
+TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
+{
+ TIFFCvtNativeToIEEEDouble(tif, dir->tdir_count, v);
+ return (TIFFWriteData(tif, dir, (char*) v));
+}
+
+/*
+ * Write an array of ``type'' values for a specified tag (i.e. this is a tag
+ * which is allowed to have different types, e.g. SMaxSampleType).
+ * Internally the data values are represented as double since a double can
+ * hold any of the TIFF tag types (yes, this should really be an abstract
+ * type tany_t for portability). The data is converted into the specified
+ * type in a temporary buffer and then handed off to the appropriate array
+ * writer.
+ */
+static int
+TIFFWriteAnyArray(TIFF* tif,
+ TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
+{
+ char buf[10 * sizeof(double)];
+ char* w = buf;
+ int i, status = 0;
+
+ if (n * TIFFDataWidth(type) > sizeof buf) {
+ w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
+ if (w == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No space to write array");
+ return (0);
+ }
+ }
+
+ dir->tdir_tag = (uint16) tag;
+ dir->tdir_type = (uint16) type;
+ dir->tdir_count = n;
+
+ switch (type) {
+ case TIFF_BYTE:
+ {
+ uint8* bp = (uint8*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (uint8) v[i];
+ if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_SBYTE:
+ {
+ int8* bp = (int8*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (int8) v[i];
+ if (!TIFFWriteByteArray(tif, dir, (char*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_SHORT:
+ {
+ uint16* bp = (uint16*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (uint16) v[i];
+ if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
+ goto out;
+ }
+ break;
+ case TIFF_SSHORT:
+ {
+ int16* bp = (int16*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (int16) v[i];
+ if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
+ goto out;
+ }
+ break;
+ case TIFF_LONG:
+ {
+ uint32* bp = (uint32*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (uint32) v[i];
+ if (!TIFFWriteLongArray(tif, dir, bp))
+ goto out;
+ }
+ break;
+ case TIFF_SLONG:
+ {
+ int32* bp = (int32*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (int32) v[i];
+ if (!TIFFWriteLongArray(tif, dir, (uint32*) bp))
+ goto out;
+ }
+ break;
+ case TIFF_FLOAT:
+ {
+ float* bp = (float*) w;
+ for (i = 0; i < (int) n; i++)
+ bp[i] = (float) v[i];
+ if (!TIFFWriteFloatArray(tif, dir, bp))
+ goto out;
+ }
+ break;
+ case TIFF_DOUBLE:
+ {
+ if( !TIFFWriteDoubleArray(tif, dir, v))
+ goto out;
+ }
+ default:
+ /* TIFF_NOTYPE */
+ /* TIFF_ASCII */
+ /* TIFF_UNDEFINED */
+ /* TIFF_RATIONAL */
+ /* TIFF_SRATIONAL */
+ goto out;
+ }
+ status = 1;
+ out:
+ if (w != buf)
+ _TIFFfree(w);
+ return (status);
+}
+
+static int
+TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16);
+ uint16** tf = td->td_transferfunction;
+ int ncols;
+
+ /*
+ * Check if the table can be written as a single column,
+ * or if it must be written as 3 columns. Note that we
+ * write a 3-column tag if there are 2 samples/pixel and
+ * a single column of data won't suffice--hmm.
+ */
+ switch (td->td_samplesperpixel - td->td_extrasamples) {
+ default: if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; }
+ case 2: if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; }
+ case 1: case 0: ncols = 1;
+ }
+ return (TIFFWriteShortTable(tif,
+ TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf));
+}
+
+static int
+TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+
+ dir->tdir_tag = TIFFTAG_INKNAMES;
+ dir->tdir_type = (short) TIFF_ASCII;
+ dir->tdir_count = td->td_inknameslen;
+ return (TIFFWriteByteArray(tif, dir, td->td_inknames));
+}
+
+/*
+ * Write a contiguous directory item.
+ */
+static int
+TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
+{
+ tsize_t cc;
+
+ if (tif->tif_flags & TIFF_SWAB) {
+ switch (dir->tdir_type) {
+ case TIFF_SHORT:
+ case TIFF_SSHORT:
+ TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
+ break;
+ case TIFF_LONG:
+ case TIFF_SLONG:
+ case TIFF_FLOAT:
+ TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
+ break;
+ case TIFF_RATIONAL:
+ case TIFF_SRATIONAL:
+ TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
+ break;
+ case TIFF_DOUBLE:
+ TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
+ break;
+ }
+ }
+ dir->tdir_offset = tif->tif_dataoff;
+ cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type);
+ if (SeekOK(tif, dir->tdir_offset) &&
+ WriteOK(tif, cp, cc)) {
+ tif->tif_dataoff += (cc + 1) & ~1;
+ return (1);
+ }
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing data for field \"%s\"",
+ _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
+ return (0);
+}
+
+/*
+ * Similar to TIFFWriteDirectory(), but if the directory has already
+ * been written once, it is relocated to the end of the file, in case it
+ * has changed in size. Note that this will result in the loss of the
+ * previously used directory space.
+ */
+
+int
+TIFFRewriteDirectory( TIFF *tif )
+{
+ static const char module[] = "TIFFRewriteDirectory";
+
+ /* We don't need to do anything special if it hasn't been written. */
+ if( tif->tif_diroff == 0 )
+ return TIFFWriteDirectory( tif );
+
+ /*
+ ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
+ ** will cause it to be added after this directories current pre-link.
+ */
+
+ /* Is it the first directory in the file? */
+ if (tif->tif_header.tiff_diroff == tif->tif_diroff)
+ {
+ tif->tif_header.tiff_diroff = 0;
+ tif->tif_diroff = 0;
+
+ TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
+ SEEK_SET);
+ if (!WriteOK(tif, &(tif->tif_header.tiff_diroff),
+ sizeof (tif->tif_diroff)))
+ {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error updating TIFF header");
+ return (0);
+ }
+ }
+ else
+ {
+ toff_t nextdir, off;
+
+ nextdir = tif->tif_header.tiff_diroff;
+ do {
+ uint16 dircount;
+
+ if (!SeekOK(tif, nextdir) ||
+ !ReadOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory count");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ (void) TIFFSeekFile(tif,
+ dircount * sizeof (TIFFDirEntry), SEEK_CUR);
+ if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory link");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir);
+ } while (nextdir != tif->tif_diroff && nextdir != 0);
+ off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
+ (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
+ tif->tif_diroff = 0;
+ if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error writing directory link");
+ return (0);
+ }
+ }
+
+ /*
+ ** Now use TIFFWriteDirectory() normally.
+ */
+
+ return TIFFWriteDirectory( tif );
+}
+
+
+/*
+ * Link the current directory into the directory chain for the file.
+ */
+static int
+TIFFLinkDirectory(TIFF* tif)
+{
+ static const char module[] = "TIFFLinkDirectory";
+ toff_t nextdir;
+ toff_t diroff, off;
+
+ tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
+ diroff = tif->tif_diroff;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&diroff);
+
+ /*
+ * Handle SubIFDs
+ */
+ if (tif->tif_flags & TIFF_INSUBIFD) {
+ (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Error writing SubIFD directory link",
+ tif->tif_name);
+ return (0);
+ }
+ /*
+ * Advance to the next SubIFD or, if this is
+ * the last one configured, revert back to the
+ * normal directory linkage.
+ */
+ if (--tif->tif_nsubifd)
+ tif->tif_subifdoff += sizeof (diroff);
+ else
+ tif->tif_flags &= ~TIFF_INSUBIFD;
+ return (1);
+ }
+
+ if (tif->tif_header.tiff_diroff == 0) {
+ /*
+ * First directory, overwrite offset in header.
+ */
+ tif->tif_header.tiff_diroff = tif->tif_diroff;
+ (void) TIFFSeekFile(tif,
+ (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
+ SEEK_SET);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Error writing TIFF header");
+ return (0);
+ }
+ return (1);
+ }
+ /*
+ * Not the first directory, search to the last and append.
+ */
+ nextdir = tif->tif_header.tiff_diroff;
+ do {
+ uint16 dircount;
+
+ if (!SeekOK(tif, nextdir) ||
+ !ReadOK(tif, &dircount, sizeof (dircount))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory count");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&dircount);
+ (void) TIFFSeekFile(tif,
+ dircount * sizeof (TIFFDirEntry), SEEK_CUR);
+ if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error fetching directory link");
+ return (0);
+ }
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabLong(&nextdir);
+ } while (nextdir != 0);
+ off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
+ (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
+ if (!WriteOK(tif, &diroff, sizeof (diroff))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Error writing directory link");
+ return (0);
+ }
+ return (1);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_dumpmode.c b/Source/LibTIFF/tif_dumpmode.c
new file mode 100644
index 0000000..7729e14
--- /dev/null
+++ b/Source/LibTIFF/tif_dumpmode.c
@@ -0,0 +1,119 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_dumpmode.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * "Null" Compression Algorithm Support.
+ */
+#include "tiffiop.h"
+
+/*
+ * Encode a hunk of pixels.
+ */
+static int
+DumpModeEncode(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) s;
+ while (cc > 0) {
+ tsize_t n;
+
+ n = cc;
+ if (tif->tif_rawcc + n > tif->tif_rawdatasize)
+ n = tif->tif_rawdatasize - tif->tif_rawcc;
+
+ assert( n > 0 );
+
+ /*
+ * Avoid copy if client has setup raw
+ * data buffer to avoid extra copy.
+ */
+ if (tif->tif_rawcp != pp)
+ _TIFFmemcpy(tif->tif_rawcp, pp, n);
+ tif->tif_rawcp += n;
+ tif->tif_rawcc += n;
+ pp += n;
+ cc -= n;
+ if (tif->tif_rawcc >= tif->tif_rawdatasize &&
+ !TIFFFlushData1(tif))
+ return (-1);
+ }
+ return (1);
+}
+
+/*
+ * Decode a hunk of pixels.
+ */
+static int
+DumpModeDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ (void) s;
+/* fprintf(stderr,"DumpModeDecode: scanline %ld, expected %ld bytes, got %ld bytes\n", */
+/* (long) tif->tif_row, (long) tif->tif_rawcc, (long) cc); */
+ if (tif->tif_rawcc < cc) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "DumpModeDecode: Not enough data for scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ /*
+ * Avoid copy if client has setup raw
+ * data buffer to avoid extra copy.
+ */
+ if (tif->tif_rawcp != buf)
+ _TIFFmemcpy(buf, tif->tif_rawcp, cc);
+ tif->tif_rawcp += cc;
+ tif->tif_rawcc -= cc;
+ return (1);
+}
+
+/*
+ * Seek forwards nrows in the current strip.
+ */
+static int
+DumpModeSeek(TIFF* tif, uint32 nrows)
+{
+ tif->tif_rawcp += nrows * tif->tif_scanlinesize;
+ tif->tif_rawcc -= nrows * tif->tif_scanlinesize;
+ return (1);
+}
+
+/*
+ * Initialize dump mode.
+ */
+int
+TIFFInitDumpMode(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ tif->tif_decoderow = DumpModeDecode;
+ tif->tif_decodestrip = DumpModeDecode;
+ tif->tif_decodetile = DumpModeDecode;
+ tif->tif_encoderow = DumpModeEncode;
+ tif->tif_encodestrip = DumpModeEncode;
+ tif->tif_encodetile = DumpModeEncode;
+ tif->tif_seek = DumpModeSeek;
+ return (1);
+}
diff --git a/Source/LibTIFF/tif_error.c b/Source/LibTIFF/tif_error.c
new file mode 100644
index 0000000..23b8534
--- /dev/null
+++ b/Source/LibTIFF/tif_error.c
@@ -0,0 +1,73 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_error.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+TIFFErrorHandlerExt _TIFFerrorHandlerExt = NULL;
+
+TIFFErrorHandler
+TIFFSetErrorHandler(TIFFErrorHandler handler)
+{
+ TIFFErrorHandler prev = _TIFFerrorHandler;
+ _TIFFerrorHandler = handler;
+ return (prev);
+}
+
+TIFFErrorHandlerExt
+TIFFSetErrorHandlerExt(TIFFErrorHandlerExt handler)
+{
+ TIFFErrorHandlerExt prev = _TIFFerrorHandlerExt;
+ _TIFFerrorHandlerExt = handler;
+ return (prev);
+}
+
+void
+TIFFError(const char* module, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (_TIFFerrorHandler)
+ (*_TIFFerrorHandler)(module, fmt, ap);
+ if (_TIFFerrorHandlerExt)
+ (*_TIFFerrorHandlerExt)(0, module, fmt, ap);
+ va_end(ap);
+}
+
+void
+TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (_TIFFerrorHandler)
+ (*_TIFFerrorHandler)(module, fmt, ap);
+ if (_TIFFerrorHandlerExt)
+ (*_TIFFerrorHandlerExt)(fd, module, fmt, ap);
+ va_end(ap);
+}
+
diff --git a/Source/LibTIFF/tif_extension.c b/Source/LibTIFF/tif_extension.c
new file mode 100644
index 0000000..0168a06
--- /dev/null
+++ b/Source/LibTIFF/tif_extension.c
@@ -0,0 +1,111 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_extension.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Various routines support external extension of the tag set, and other
+ * application extension capabilities.
+ */
+
+#include "tiffiop.h"
+
+int TIFFGetTagListCount( TIFF *tif )
+
+{
+ TIFFDirectory* td = &tif->tif_dir;
+
+ return td->td_customValueCount;
+}
+
+ttag_t TIFFGetTagListEntry( TIFF *tif, int tag_index )
+
+{
+ TIFFDirectory* td = &tif->tif_dir;
+
+ if( tag_index < 0 || tag_index >= td->td_customValueCount )
+ return (ttag_t) -1;
+ else
+ return td->td_customValues[tag_index].info->field_tag;
+}
+
+/*
+** This provides read/write access to the TIFFTagMethods within the TIFF
+** structure to application code without giving access to the private
+** TIFF structure.
+*/
+TIFFTagMethods *TIFFAccessTagMethods( TIFF *tif )
+
+{
+ return &(tif->tif_tagmethods);
+}
+
+void *TIFFGetClientInfo( TIFF *tif, const char *name )
+
+{
+ TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+ while( link != NULL && strcmp(link->name,name) != 0 )
+ link = link->next;
+
+ if( link != NULL )
+ return link->data;
+ else
+ return NULL;
+}
+
+void TIFFSetClientInfo( TIFF *tif, void *data, const char *name )
+
+{
+ TIFFClientInfoLink *link = tif->tif_clientinfo;
+
+ /*
+ ** Do we have an existing link with this name? If so, just
+ ** set it.
+ */
+ while( link != NULL && strcmp(link->name,name) != 0 )
+ link = link->next;
+
+ if( link != NULL )
+ {
+ link->data = data;
+ return;
+ }
+
+ /*
+ ** Create a new link.
+ */
+
+ link = (TIFFClientInfoLink *) _TIFFmalloc(sizeof(TIFFClientInfoLink));
+ assert (link != NULL);
+ link->next = tif->tif_clientinfo;
+ link->name = (char *) _TIFFmalloc(strlen(name)+1);
+ assert (link->name != NULL);
+ strcpy(link->name, name);
+ link->data = data;
+
+ tif->tif_clientinfo = link;
+}
diff --git a/Source/LibTIFF/tif_fax3.c b/Source/LibTIFF/tif_fax3.c
new file mode 100644
index 0000000..0a84523
--- /dev/null
+++ b/Source/LibTIFF/tif_fax3.c
@@ -0,0 +1,1603 @@
+/* $Id: tif_fax3.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1990-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef CCITT_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * CCITT Group 3 (T.4) and Group 4 (T.6) Compression Support.
+ *
+ * This file contains support for decoding and encoding TIFF
+ * compression algorithms 2, 3, 4, and 32771.
+ *
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ * Copyright (C) 1990, 1995 Frank D. Cringle.
+ */
+#include "tif_fax3.h"
+#define G3CODES
+#include "t4.h"
+#include <stdio.h>
+
+/*
+ * Compression+decompression state blocks are
+ * derived from this ``base state'' block.
+ */
+typedef struct {
+ int rw_mode; /* O_RDONLY for decode, else encode */
+ int mode; /* operating mode */
+ uint32 rowbytes; /* bytes in a decoded scanline */
+ uint32 rowpixels; /* pixels in a scanline */
+
+ uint16 cleanfaxdata; /* CleanFaxData tag */
+ uint32 badfaxrun; /* BadFaxRun tag */
+ uint32 badfaxlines; /* BadFaxLines tag */
+ uint32 groupoptions; /* Group 3/4 options tag */
+ uint32 recvparams; /* encoded Class 2 session params */
+ char* subaddress; /* subaddress string */
+ uint32 recvtime; /* time spent receiving (secs) */
+ char* faxdcs; /* Table 2/T.30 encoded session params */
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+ TIFFPrintMethod printdir; /* super-class method */
+} Fax3BaseState;
+#define Fax3State(tif) ((Fax3BaseState*) (tif)->tif_data)
+
+typedef enum { G3_1D, G3_2D } Ttag;
+typedef struct {
+ Fax3BaseState b;
+
+ /* Decoder state info */
+ const unsigned char* bitmap; /* bit reversal table */
+ uint32 data; /* current i/o byte/word */
+ int bit; /* current i/o bit in byte */
+ int EOLcnt; /* count of EOL codes recognized */
+ TIFFFaxFillFunc fill; /* fill routine */
+ uint32* runs; /* b&w runs for current/previous row */
+ uint32* refruns; /* runs for reference line */
+ uint32* curruns; /* runs for current line */
+
+ /* Encoder state info */
+ Ttag tag; /* encoding state */
+ unsigned char* refline; /* reference line for 2d decoding */
+ int k; /* #rows left that can be 2d encoded */
+ int maxk; /* max #rows that can be 2d encoded */
+
+ int line;
+} Fax3CodecState;
+#define DecoderState(tif) ((Fax3CodecState*) Fax3State(tif))
+#define EncoderState(tif) ((Fax3CodecState*) Fax3State(tif))
+
+#define is2DEncoding(sp) \
+ (sp->b.groupoptions & GROUP3OPT_2DENCODING)
+#define isAligned(p,t) ((((unsigned long)(p)) & (sizeof (t)-1)) == 0)
+
+/*
+ * Group 3 and Group 4 Decoding.
+ */
+
+/*
+ * These macros glue the TIFF library state to
+ * the state expected by Frank's decoder.
+ */
+#define DECLARE_STATE(tif, sp, mod) \
+ static const char module[] = mod; \
+ Fax3CodecState* sp = DecoderState(tif); \
+ int a0; /* reference element */ \
+ int lastx = sp->b.rowpixels; /* last element in row */ \
+ uint32 BitAcc; /* bit accumulator */ \
+ int BitsAvail; /* # valid bits in BitAcc */ \
+ int RunLength; /* length of current run */ \
+ unsigned char* cp; /* next byte of input data */ \
+ unsigned char* ep; /* end of input data */ \
+ uint32* pa; /* place to stuff next run */ \
+ uint32* thisrun; /* current row's run array */ \
+ int EOLcnt; /* # EOL codes recognized */ \
+ const unsigned char* bitmap = sp->bitmap; /* input data bit reverser */ \
+ const TIFFFaxTabEnt* TabEnt
+#define DECLARE_STATE_2D(tif, sp, mod) \
+ DECLARE_STATE(tif, sp, mod); \
+ int b1; /* next change on prev line */ \
+ uint32* pb /* next run in reference line */\
+/*
+ * Load any state that may be changed during decoding.
+ */
+#define CACHE_STATE(tif, sp) do { \
+ BitAcc = sp->data; \
+ BitsAvail = sp->bit; \
+ EOLcnt = sp->EOLcnt; \
+ cp = (unsigned char*) tif->tif_rawcp; \
+ ep = cp + tif->tif_rawcc; \
+} while (0)
+/*
+ * Save state possibly changed during decoding.
+ */
+#define UNCACHE_STATE(tif, sp) do { \
+ sp->bit = BitsAvail; \
+ sp->data = BitAcc; \
+ sp->EOLcnt = EOLcnt; \
+ tif->tif_rawcc -= (tidata_t) cp - tif->tif_rawcp; \
+ tif->tif_rawcp = (tidata_t) cp; \
+} while (0)
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+Fax3PreDecode(TIFF* tif, tsample_t s)
+{
+ Fax3CodecState* sp = DecoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ sp->bit = 0; /* force initial read */
+ sp->data = 0;
+ sp->EOLcnt = 0; /* force initial scan for EOL */
+ /*
+ * Decoder assumes lsb-to-msb bit order. Note that we select
+ * this here rather than in Fax3SetupState so that viewers can
+ * hold the image open, fiddle with the FillOrder tag value,
+ * and then re-decode the image. Otherwise they'd need to close
+ * and open the image to get the state reset.
+ */
+ sp->bitmap =
+ TIFFGetBitRevTable(tif->tif_dir.td_fillorder != FILLORDER_LSB2MSB);
+ if (sp->refruns) { /* init reference line to white */
+ sp->refruns[0] = (uint32) sp->b.rowpixels;
+ sp->refruns[1] = 0;
+ }
+ sp->line = 0;
+ return (1);
+}
+
+/*
+ * Routine for handling various errors/conditions.
+ * Note how they are "glued into the decoder" by
+ * overriding the definitions used by the decoder.
+ */
+
+static void
+Fax3Unexpected(const char* module, TIFF* tif, uint32 line, uint32 a0)
+{
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Bad code word at line %u of %s %u (x %u)",
+ tif->tif_name, line, isTiled(tif) ? "tile" : "strip",
+ (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+ a0);
+}
+#define unexpected(table, a0) Fax3Unexpected(module, tif, sp->line, a0)
+
+static void
+Fax3Extension(const char* module, TIFF* tif, uint32 line, uint32 a0)
+{
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Uncompressed data (not supported) at line %u of %s %u (x %u)",
+ tif->tif_name, line, isTiled(tif) ? "tile" : "strip",
+ (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+ a0);
+}
+#define extension(a0) Fax3Extension(module, tif, sp->line, a0)
+
+static void
+Fax3BadLength(const char* module, TIFF* tif, uint32 line, uint32 a0, uint32 lastx)
+{
+ TIFFWarningExt(tif->tif_clientdata, module, "%s: %s at line %u of %s %u (got %u, expected %u)",
+ tif->tif_name,
+ a0 < lastx ? "Premature EOL" : "Line length mismatch",
+ line, isTiled(tif) ? "tile" : "strip",
+ (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+ a0, lastx);
+}
+#define badlength(a0,lastx) Fax3BadLength(module, tif, sp->line, a0, lastx)
+
+static void
+Fax3PrematureEOF(const char* module, TIFF* tif, uint32 line, uint32 a0)
+{
+ TIFFWarningExt(tif->tif_clientdata, module, "%s: Premature EOF at line %u of %s %u (x %u)",
+ tif->tif_name,
+ line, isTiled(tif) ? "tile" : "strip",
+ (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip),
+ a0);
+}
+#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0)
+
+#define Nop
+
+/*
+ * Decode the requested amount of G3 1D-encoded data.
+ */
+static int
+Fax3Decode1D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ DECLARE_STATE(tif, sp, "Fax3Decode1D");
+
+ (void) s;
+ CACHE_STATE(tif, sp);
+ thisrun = sp->curruns;
+ while ((long)occ > 0) {
+ a0 = 0;
+ RunLength = 0;
+ pa = thisrun;
+#ifdef FAX3_DEBUG
+ printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", tif->tif_row);
+ fflush(stdout);
+#endif
+ SYNC_EOL(EOF1D);
+ EXPAND1D(EOF1Da);
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ buf += sp->b.rowbytes;
+ occ -= sp->b.rowbytes;
+ sp->line++;
+ continue;
+ EOF1D: /* premature EOF */
+ CLEANUP_RUNS();
+ EOF1Da: /* premature EOF */
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ UNCACHE_STATE(tif, sp);
+ return (-1);
+ }
+ UNCACHE_STATE(tif, sp);
+ return (1);
+}
+
+#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; }
+/*
+ * Decode the requested amount of G3 2D-encoded data.
+ */
+static int
+Fax3Decode2D(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ DECLARE_STATE_2D(tif, sp, "Fax3Decode2D");
+ int is1D; /* current line is 1d/2d-encoded */
+
+ (void) s;
+ CACHE_STATE(tif, sp);
+ while ((long)occ > 0) {
+ a0 = 0;
+ RunLength = 0;
+ pa = thisrun = sp->curruns;
+#ifdef FAX3_DEBUG
+ printf("\nBitAcc=%08X, BitsAvail = %d EOLcnt = %d",
+ BitAcc, BitsAvail, EOLcnt);
+#endif
+ SYNC_EOL(EOF2D);
+ NeedBits8(1, EOF2D);
+ is1D = GetBits(1); /* 1D/2D-encoding tag bit */
+ ClrBits(1);
+#ifdef FAX3_DEBUG
+ printf(" %s\n-------------------- %d\n",
+ is1D ? "1D" : "2D", tif->tif_row);
+ fflush(stdout);
+#endif
+ pb = sp->refruns;
+ b1 = *pb++;
+ if (is1D)
+ EXPAND1D(EOF2Da);
+ else
+ EXPAND2D(EOF2Da);
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ SETVALUE(0); /* imaginary change for reference */
+ SWAP(uint32*, sp->curruns, sp->refruns);
+ buf += sp->b.rowbytes;
+ occ -= sp->b.rowbytes;
+ sp->line++;
+ continue;
+ EOF2D: /* premature EOF */
+ CLEANUP_RUNS();
+ EOF2Da: /* premature EOF */
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ UNCACHE_STATE(tif, sp);
+ return (-1);
+ }
+ UNCACHE_STATE(tif, sp);
+ return (1);
+}
+#undef SWAP
+
+/*
+ * The ZERO & FILL macros must handle spans < 2*sizeof(long) bytes.
+ * For machines with 64-bit longs this is <16 bytes; otherwise
+ * this is <8 bytes. We optimize the code here to reflect the
+ * machine characteristics.
+ */
+#if SIZEOF_LONG == 8
+# define FILL(n, cp) \
+ switch (n) { \
+ case 15:(cp)[14] = 0xff; case 14:(cp)[13] = 0xff; case 13: (cp)[12] = 0xff;\
+ case 12:(cp)[11] = 0xff; case 11:(cp)[10] = 0xff; case 10: (cp)[9] = 0xff;\
+ case 9: (cp)[8] = 0xff; case 8: (cp)[7] = 0xff; case 7: (cp)[6] = 0xff;\
+ case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; case 4: (cp)[3] = 0xff;\
+ case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \
+ case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \
+ }
+# define ZERO(n, cp) \
+ switch (n) { \
+ case 15:(cp)[14] = 0; case 14:(cp)[13] = 0; case 13: (cp)[12] = 0; \
+ case 12:(cp)[11] = 0; case 11:(cp)[10] = 0; case 10: (cp)[9] = 0; \
+ case 9: (cp)[8] = 0; case 8: (cp)[7] = 0; case 7: (cp)[6] = 0; \
+ case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; case 4: (cp)[3] = 0; \
+ case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \
+ case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \
+ }
+#else
+# define FILL(n, cp) \
+ switch (n) { \
+ case 7: (cp)[6] = 0xff; case 6: (cp)[5] = 0xff; case 5: (cp)[4] = 0xff; \
+ case 4: (cp)[3] = 0xff; case 3: (cp)[2] = 0xff; case 2: (cp)[1] = 0xff; \
+ case 1: (cp)[0] = 0xff; (cp) += (n); case 0: ; \
+ }
+# define ZERO(n, cp) \
+ switch (n) { \
+ case 7: (cp)[6] = 0; case 6: (cp)[5] = 0; case 5: (cp)[4] = 0; \
+ case 4: (cp)[3] = 0; case 3: (cp)[2] = 0; case 2: (cp)[1] = 0; \
+ case 1: (cp)[0] = 0; (cp) += (n); case 0: ; \
+ }
+#endif
+
+/*
+ * Bit-fill a row according to the white/black
+ * runs generated during G3/G4 decoding.
+ */
+void
+_TIFFFax3fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
+{
+ static const unsigned char _fillmasks[] =
+ { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
+ unsigned char* cp;
+ uint32 x, bx, run;
+ int32 n, nw;
+ long* lp;
+
+ if ((erun-runs)&1)
+ *erun++ = 0;
+ x = 0;
+ for (; runs < erun; runs += 2) {
+ run = runs[0];
+ if (x+run > lastx || run > lastx )
+ run = runs[0] = (uint32) (lastx - x);
+ if (run) {
+ cp = buf + (x>>3);
+ bx = x&7;
+ if (run > 8-bx) {
+ if (bx) { /* align to byte boundary */
+ *cp++ &= 0xff << (8-bx);
+ run -= 8-bx;
+ }
+ if( (n = run >> 3) != 0 ) { /* multiple bytes to fill */
+ if ((n/sizeof (long)) > 1) {
+ /*
+ * Align to longword boundary and fill.
+ */
+ for (; n && !isAligned(cp, long); n--)
+ *cp++ = 0x00;
+ lp = (long*) cp;
+ nw = (int32)(n / sizeof (long));
+ n -= nw * sizeof (long);
+ do {
+ *lp++ = 0L;
+ } while (--nw);
+ cp = (unsigned char*) lp;
+ }
+ ZERO(n, cp);
+ run &= 7;
+ }
+ if (run)
+ cp[0] &= 0xff >> run;
+ } else
+ cp[0] &= ~(_fillmasks[run]>>bx);
+ x += runs[0];
+ }
+ run = runs[1];
+ if (x+run > lastx || run > lastx )
+ run = runs[1] = lastx - x;
+ if (run) {
+ cp = buf + (x>>3);
+ bx = x&7;
+ if (run > 8-bx) {
+ if (bx) { /* align to byte boundary */
+ *cp++ |= 0xff >> bx;
+ run -= 8-bx;
+ }
+ if( (n = run>>3) != 0 ) { /* multiple bytes to fill */
+ if ((n/sizeof (long)) > 1) {
+ /*
+ * Align to longword boundary and fill.
+ */
+ for (; n && !isAligned(cp, long); n--)
+ *cp++ = 0xff;
+ lp = (long*) cp;
+ nw = (int32)(n / sizeof (long));
+ n -= nw * sizeof (long);
+ do {
+ *lp++ = -1L;
+ } while (--nw);
+ cp = (unsigned char*) lp;
+ }
+ FILL(n, cp);
+ run &= 7;
+ }
+ if (run)
+ cp[0] |= 0xff00 >> run;
+ } else
+ cp[0] |= _fillmasks[run]>>bx;
+ x += runs[1];
+ }
+ }
+ assert(x == lastx);
+}
+#undef ZERO
+#undef FILL
+
+/*
+ * Setup G3/G4-related compression/decompression state
+ * before data is processed. This routine is called once
+ * per image -- it sets up different state based on whether
+ * or not decoding or encoding is being done and whether
+ * 1D- or 2D-encoded data is involved.
+ */
+static int
+Fax3SetupState(TIFF* tif)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ Fax3BaseState* sp = Fax3State(tif);
+ int needsRefLine;
+ Fax3CodecState* dsp = (Fax3CodecState*) Fax3State(tif);
+ uint32 rowbytes, rowpixels, nruns;
+
+ if (td->td_bitspersample != 1) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Bits/sample must be 1 for Group 3/4 encoding/decoding");
+ return (0);
+ }
+ /*
+ * Calculate the scanline/tile widths.
+ */
+ if (isTiled(tif)) {
+ rowbytes = TIFFTileRowSize(tif);
+ rowpixels = td->td_tilewidth;
+ } else {
+ rowbytes = TIFFScanlineSize(tif);
+ rowpixels = td->td_imagewidth;
+ }
+ sp->rowbytes = (uint32) rowbytes;
+ sp->rowpixels = (uint32) rowpixels;
+ /*
+ * Allocate any additional space required for decoding/encoding.
+ */
+ needsRefLine = (
+ (sp->groupoptions & GROUP3OPT_2DENCODING) ||
+ td->td_compression == COMPRESSION_CCITTFAX4
+ );
+
+ nruns = needsRefLine ? 2*TIFFroundup(rowpixels,32) : rowpixels;
+ nruns += 3;
+ dsp->runs = (uint32*) _TIFFCheckMalloc(tif, 2*nruns, sizeof (uint32),
+ "for Group 3/4 run arrays");
+ if (dsp->runs == NULL)
+ return (0);
+ dsp->curruns = dsp->runs;
+ if (needsRefLine)
+ dsp->refruns = dsp->runs + nruns;
+ else
+ dsp->refruns = NULL;
+ if (td->td_compression == COMPRESSION_CCITTFAX3
+ && is2DEncoding(dsp)) { /* NB: default is 1D routine */
+ tif->tif_decoderow = Fax3Decode2D;
+ tif->tif_decodestrip = Fax3Decode2D;
+ tif->tif_decodetile = Fax3Decode2D;
+ }
+
+ if (needsRefLine) { /* 2d encoding */
+ Fax3CodecState* esp = EncoderState(tif);
+ /*
+ * 2d encoding requires a scanline
+ * buffer for the ``reference line''; the
+ * scanline against which delta encoding
+ * is referenced. The reference line must
+ * be initialized to be ``white'' (done elsewhere).
+ */
+ esp->refline = (unsigned char*) _TIFFmalloc(rowbytes);
+ if (esp->refline == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, "Fax3SetupState",
+ "%s: No space for Group 3/4 reference line",
+ tif->tif_name);
+ return (0);
+ }
+ } else /* 1d encoding */
+ EncoderState(tif)->refline = NULL;
+
+ return (1);
+}
+
+/*
+ * CCITT Group 3 FAX Encoding.
+ */
+
+#define Fax3FlushBits(tif, sp) { \
+ if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
+ (void) TIFFFlushData1(tif); \
+ *(tif)->tif_rawcp++ = (tidataval_t) (sp)->data; \
+ (tif)->tif_rawcc++; \
+ (sp)->data = 0, (sp)->bit = 8; \
+}
+#define _FlushBits(tif) { \
+ if ((tif)->tif_rawcc >= (tif)->tif_rawdatasize) \
+ (void) TIFFFlushData1(tif); \
+ *(tif)->tif_rawcp++ = (tidataval_t) data; \
+ (tif)->tif_rawcc++; \
+ data = 0, bit = 8; \
+}
+static const int _msbmask[9] =
+ { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
+#define _PutBits(tif, bits, length) { \
+ while (length > bit) { \
+ data |= bits >> (length - bit); \
+ length -= bit; \
+ _FlushBits(tif); \
+ } \
+ data |= (bits & _msbmask[length]) << (bit - length); \
+ bit -= length; \
+ if (bit == 0) \
+ _FlushBits(tif); \
+}
+
+/*
+ * Write a variable-length bit-value to
+ * the output stream. Values are
+ * assumed to be at most 16 bits.
+ */
+static void
+Fax3PutBits(TIFF* tif, unsigned int bits, unsigned int length)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+ unsigned int bit = sp->bit;
+ int data = sp->data;
+
+ _PutBits(tif, bits, length);
+
+ sp->data = data;
+ sp->bit = bit;
+}
+
+/*
+ * Write a code to the output stream.
+ */
+#define putcode(tif, te) Fax3PutBits(tif, (te)->code, (te)->length)
+
+#ifdef FAX3_DEBUG
+#define DEBUG_COLOR(w) (tab == TIFFFaxWhiteCodes ? w "W" : w "B")
+#define DEBUG_PRINT(what,len) { \
+ int t; \
+ printf("%08X/%-2d: %s%5d\t", data, bit, DEBUG_COLOR(what), len); \
+ for (t = length-1; t >= 0; t--) \
+ putchar(code & (1<<t) ? '1' : '0'); \
+ putchar('\n'); \
+}
+#endif
+
+/*
+ * Write the sequence of codes that describes
+ * the specified span of zero's or one's. The
+ * appropriate table that holds the make-up and
+ * terminating codes is supplied.
+ */
+static void
+putspan(TIFF* tif, int32 span, const tableentry* tab)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+ unsigned int bit = sp->bit;
+ int data = sp->data;
+ unsigned int code, length;
+
+ while (span >= 2624) {
+ const tableentry* te = &tab[63 + (2560>>6)];
+ code = te->code, length = te->length;
+#ifdef FAX3_DEBUG
+ DEBUG_PRINT("MakeUp", te->runlen);
+#endif
+ _PutBits(tif, code, length);
+ span -= te->runlen;
+ }
+ if (span >= 64) {
+ const tableentry* te = &tab[63 + (span>>6)];
+ assert(te->runlen == 64*(span>>6));
+ code = te->code, length = te->length;
+#ifdef FAX3_DEBUG
+ DEBUG_PRINT("MakeUp", te->runlen);
+#endif
+ _PutBits(tif, code, length);
+ span -= te->runlen;
+ }
+ code = tab[span].code, length = tab[span].length;
+#ifdef FAX3_DEBUG
+ DEBUG_PRINT(" Term", tab[span].runlen);
+#endif
+ _PutBits(tif, code, length);
+
+ sp->data = data;
+ sp->bit = bit;
+}
+
+/*
+ * Write an EOL code to the output stream. The zero-fill
+ * logic for byte-aligning encoded scanlines is handled
+ * here. We also handle writing the tag bit for the next
+ * scanline when doing 2d encoding.
+ */
+static void
+Fax3PutEOL(TIFF* tif)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+ unsigned int bit = sp->bit;
+ int data = sp->data;
+ unsigned int code, length, tparm;
+
+ if (sp->b.groupoptions & GROUP3OPT_FILLBITS) {
+ /*
+ * Force bit alignment so EOL will terminate on
+ * a byte boundary. That is, force the bit alignment
+ * to 16-12 = 4 before putting out the EOL code.
+ */
+ int align = 8 - 4;
+ if (align != sp->bit) {
+ if (align > sp->bit)
+ align = sp->bit + (8 - align);
+ else
+ align = sp->bit - align;
+ code = 0;
+ tparm=align;
+ _PutBits(tif, 0, tparm);
+ }
+ }
+ code = EOL, length = 12;
+ if (is2DEncoding(sp))
+ code = (code<<1) | (sp->tag == G3_1D), length++;
+ _PutBits(tif, code, length);
+
+ sp->data = data;
+ sp->bit = bit;
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+Fax3PreEncode(TIFF* tif, tsample_t s)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ sp->bit = 8;
+ sp->data = 0;
+ sp->tag = G3_1D;
+ /*
+ * This is necessary for Group 4; otherwise it isn't
+ * needed because the first scanline of each strip ends
+ * up being copied into the refline.
+ */
+ if (sp->refline)
+ _TIFFmemset(sp->refline, 0x00, sp->b.rowbytes);
+ if (is2DEncoding(sp)) {
+ float res = tif->tif_dir.td_yresolution;
+ /*
+ * The CCITT spec says that when doing 2d encoding, you
+ * should only do it on K consecutive scanlines, where K
+ * depends on the resolution of the image being encoded
+ * (2 for <= 200 lpi, 4 for > 200 lpi). Since the directory
+ * code initializes td_yresolution to 0, this code will
+ * select a K of 2 unless the YResolution tag is set
+ * appropriately. (Note also that we fudge a little here
+ * and use 150 lpi to avoid problems with units conversion.)
+ */
+ if (tif->tif_dir.td_resolutionunit == RESUNIT_CENTIMETER)
+ res *= 2.54f; /* convert to inches */
+ sp->maxk = (res > 150 ? 4 : 2);
+ sp->k = sp->maxk-1;
+ } else
+ sp->k = sp->maxk = 0;
+ sp->line = 0;
+ return (1);
+}
+
+static const unsigned char zeroruns[256] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, /* 0x00 - 0x0f */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x10 - 0x1f */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x20 - 0x2f */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x30 - 0x3f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40 - 0x4f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50 - 0x5f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60 - 0x6f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70 - 0x7f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 - 0x8f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 - 0x9f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 - 0xaf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 - 0xbf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 - 0xcf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 - 0xdf */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 - 0xef */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 - 0xff */
+};
+static const unsigned char oneruns[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 - 0x0f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 - 0x1f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 - 0x2f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 - 0x6f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 - 0x7f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 - 0x8f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 - 0x9f */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xa0 - 0xaf */
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0xb0 - 0xbf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 - 0xcf */
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 - 0xdf */
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 - 0xef */
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, /* 0xf0 - 0xff */
+};
+
+/*
+ * On certain systems it pays to inline
+ * the routines that find pixel spans.
+ */
+#ifdef VAXC
+static int32 find0span(unsigned char*, int32, int32);
+static int32 find1span(unsigned char*, int32, int32);
+#pragma inline(find0span,find1span)
+#endif
+
+/*
+ * Find a span of ones or zeros using the supplied
+ * table. The ``base'' of the bit string is supplied
+ * along with the start+end bit indices.
+ */
+static int32
+find0span(unsigned char* bp, int32 bs, int32 be)
+{
+ int32 bits = be - bs;
+ int32 n, span;
+
+ bp += bs>>3;
+ /*
+ * Check partial byte on lhs.
+ */
+ if (bits > 0 && (n = (bs & 7))) {
+ span = zeroruns[(*bp << n) & 0xff];
+ if (span > 8-n) /* table value too generous */
+ span = 8-n;
+ if (span > bits) /* constrain span to bit range */
+ span = bits;
+ if (n+span < 8) /* doesn't extend to edge of byte */
+ return (span);
+ bits -= span;
+ bp++;
+ } else
+ span = 0;
+ if (bits >= (int32)(2 * 8 * sizeof(long))) {
+ long* lp;
+ /*
+ * Align to longword boundary and check longwords.
+ */
+ while (!isAligned(bp, long)) {
+ if (*bp != 0x00)
+ return (span + zeroruns[*bp]);
+ span += 8, bits -= 8;
+ bp++;
+ }
+ lp = (long*) bp;
+ while ((bits >= (int32)(8 * sizeof(long))) && (0 == *lp)) {
+ span += 8*sizeof (long), bits -= 8*sizeof (long);
+ lp++;
+ }
+ bp = (unsigned char*) lp;
+ }
+ /*
+ * Scan full bytes for all 0's.
+ */
+ while (bits >= 8) {
+ if (*bp != 0x00) /* end of run */
+ return (span + zeroruns[*bp]);
+ span += 8, bits -= 8;
+ bp++;
+ }
+ /*
+ * Check partial byte on rhs.
+ */
+ if (bits > 0) {
+ n = zeroruns[*bp];
+ span += (n > bits ? bits : n);
+ }
+ return (span);
+}
+
+static int32
+find1span(unsigned char* bp, int32 bs, int32 be)
+{
+ int32 bits = be - bs;
+ int32 n, span;
+
+ bp += bs>>3;
+ /*
+ * Check partial byte on lhs.
+ */
+ if (bits > 0 && (n = (bs & 7))) {
+ span = oneruns[(*bp << n) & 0xff];
+ if (span > 8-n) /* table value too generous */
+ span = 8-n;
+ if (span > bits) /* constrain span to bit range */
+ span = bits;
+ if (n+span < 8) /* doesn't extend to edge of byte */
+ return (span);
+ bits -= span;
+ bp++;
+ } else
+ span = 0;
+ if (bits >= (int32)(2 * 8 * sizeof(long))) {
+ long* lp;
+ /*
+ * Align to longword boundary and check longwords.
+ */
+ while (!isAligned(bp, long)) {
+ if (*bp != 0xff)
+ return (span + oneruns[*bp]);
+ span += 8, bits -= 8;
+ bp++;
+ }
+ lp = (long*) bp;
+ while ((bits >= (int32)(8 * sizeof(long))) && (~0 == *lp)) {
+ span += 8*sizeof (long), bits -= 8*sizeof (long);
+ lp++;
+ }
+ bp = (unsigned char*) lp;
+ }
+ /*
+ * Scan full bytes for all 1's.
+ */
+ while (bits >= 8) {
+ if (*bp != 0xff) /* end of run */
+ return (span + oneruns[*bp]);
+ span += 8, bits -= 8;
+ bp++;
+ }
+ /*
+ * Check partial byte on rhs.
+ */
+ if (bits > 0) {
+ n = oneruns[*bp];
+ span += (n > bits ? bits : n);
+ }
+ return (span);
+}
+
+/*
+ * Return the offset of the next bit in the range
+ * [bs..be] that is different from the specified
+ * color. The end, be, is returned if no such bit
+ * exists.
+ */
+#define finddiff(_cp, _bs, _be, _color) \
+ (_bs + (_color ? find1span(_cp,_bs,_be) : find0span(_cp,_bs,_be)))
+/*
+ * Like finddiff, but also check the starting bit
+ * against the end in case start > end.
+ */
+#define finddiff2(_cp, _bs, _be, _color) \
+ (_bs < _be ? finddiff(_cp,_bs,_be,_color) : _be)
+
+/*
+ * 1d-encode a row of pixels. The encoding is
+ * a sequence of all-white or all-black spans
+ * of pixels encoded with Huffman codes.
+ */
+static int
+Fax3Encode1DRow(TIFF* tif, unsigned char* bp, uint32 bits)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+ int32 span;
+ uint32 bs = 0;
+
+ for (;;) {
+ span = find0span(bp, bs, bits); /* white span */
+ putspan(tif, span, TIFFFaxWhiteCodes);
+ bs += span;
+ if (bs >= bits)
+ break;
+ span = find1span(bp, bs, bits); /* black span */
+ putspan(tif, span, TIFFFaxBlackCodes);
+ bs += span;
+ if (bs >= bits)
+ break;
+ }
+ if (sp->b.mode & (FAXMODE_BYTEALIGN|FAXMODE_WORDALIGN)) {
+ if (sp->bit != 8) /* byte-align */
+ Fax3FlushBits(tif, sp);
+ if ((sp->b.mode&FAXMODE_WORDALIGN) &&
+ !isAligned(tif->tif_rawcp, uint16))
+ Fax3FlushBits(tif, sp);
+ }
+ return (1);
+}
+
+static const tableentry horizcode =
+ { 3, 0x1, 0 }; /* 001 */
+static const tableentry passcode =
+ { 4, 0x1, 0 }; /* 0001 */
+static const tableentry vcodes[7] = {
+ { 7, 0x03, 0 }, /* 0000 011 */
+ { 6, 0x03, 0 }, /* 0000 11 */
+ { 3, 0x03, 0 }, /* 011 */
+ { 1, 0x1, 0 }, /* 1 */
+ { 3, 0x2, 0 }, /* 010 */
+ { 6, 0x02, 0 }, /* 0000 10 */
+ { 7, 0x02, 0 } /* 0000 010 */
+};
+
+/*
+ * 2d-encode a row of pixels. Consult the CCITT
+ * documentation for the algorithm.
+ */
+static int
+Fax3Encode2DRow(TIFF* tif, unsigned char* bp, unsigned char* rp, uint32 bits)
+{
+#define PIXEL(buf,ix) ((((buf)[(ix)>>3]) >> (7-((ix)&7))) & 1)
+ uint32 a0 = 0;
+ uint32 a1 = (PIXEL(bp, 0) != 0 ? 0 : finddiff(bp, 0, bits, 0));
+ uint32 b1 = (PIXEL(rp, 0) != 0 ? 0 : finddiff(rp, 0, bits, 0));
+ uint32 a2, b2;
+
+ for (;;) {
+ b2 = finddiff2(rp, b1, bits, PIXEL(rp,b1));
+ if (b2 >= a1) {
+ int32 d = b1 - a1;
+ if (!(-3 <= d && d <= 3)) { /* horizontal mode */
+ a2 = finddiff2(bp, a1, bits, PIXEL(bp,a1));
+ putcode(tif, &horizcode);
+ if (a0+a1 == 0 || PIXEL(bp, a0) == 0) {
+ putspan(tif, a1-a0, TIFFFaxWhiteCodes);
+ putspan(tif, a2-a1, TIFFFaxBlackCodes);
+ } else {
+ putspan(tif, a1-a0, TIFFFaxBlackCodes);
+ putspan(tif, a2-a1, TIFFFaxWhiteCodes);
+ }
+ a0 = a2;
+ } else { /* vertical mode */
+ putcode(tif, &vcodes[d+3]);
+ a0 = a1;
+ }
+ } else { /* pass mode */
+ putcode(tif, &passcode);
+ a0 = b2;
+ }
+ if (a0 >= bits)
+ break;
+ a1 = finddiff(bp, a0, bits, PIXEL(bp,a0));
+ b1 = finddiff(rp, a0, bits, !PIXEL(bp,a0));
+ b1 = finddiff(rp, b1, bits, PIXEL(bp,a0));
+ }
+ return (1);
+#undef PIXEL
+}
+
+/*
+ * Encode a buffer of pixels.
+ */
+static int
+Fax3Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+
+ (void) s;
+ while ((long)cc > 0) {
+ if ((sp->b.mode & FAXMODE_NOEOL) == 0)
+ Fax3PutEOL(tif);
+ if (is2DEncoding(sp)) {
+ if (sp->tag == G3_1D) {
+ if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels))
+ return (0);
+ sp->tag = G3_2D;
+ } else {
+ if (!Fax3Encode2DRow(tif, bp, sp->refline,
+ sp->b.rowpixels))
+ return (0);
+ sp->k--;
+ }
+ if (sp->k == 0) {
+ sp->tag = G3_1D;
+ sp->k = sp->maxk-1;
+ } else
+ _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
+ } else {
+ if (!Fax3Encode1DRow(tif, bp, sp->b.rowpixels))
+ return (0);
+ }
+ bp += sp->b.rowbytes;
+ cc -= sp->b.rowbytes;
+ }
+ return (1);
+}
+
+static int
+Fax3PostEncode(TIFF* tif)
+{
+ Fax3CodecState* sp = EncoderState(tif);
+
+ if (sp->bit != 8)
+ Fax3FlushBits(tif, sp);
+ return (1);
+}
+
+static void
+Fax3Close(TIFF* tif)
+{
+ if ((Fax3State(tif)->mode & FAXMODE_NORTC) == 0) {
+ Fax3CodecState* sp = EncoderState(tif);
+ unsigned int code = EOL;
+ unsigned int length = 12;
+ int i;
+
+ if (is2DEncoding(sp))
+ code = (code<<1) | (sp->tag == G3_1D), length++;
+ for (i = 0; i < 6; i++)
+ Fax3PutBits(tif, code, length);
+ Fax3FlushBits(tif, sp);
+ }
+}
+
+static void
+Fax3Cleanup(TIFF* tif)
+{
+ Fax3CodecState* sp = DecoderState(tif);
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->b.vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->b.vsetparent;
+ tif->tif_tagmethods.printdir = sp->b.printdir;
+
+ if (sp->runs)
+ _TIFFfree(sp->runs);
+ if (sp->refline)
+ _TIFFfree(sp->refline);
+
+ if (Fax3State(tif)->subaddress)
+ _TIFFfree(Fax3State(tif)->subaddress);
+ if (Fax3State(tif)->faxdcs)
+ _TIFFfree(Fax3State(tif)->faxdcs);
+
+ _TIFFfree(tif->tif_data);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+#define FIELD_BADFAXLINES (FIELD_CODEC+0)
+#define FIELD_CLEANFAXDATA (FIELD_CODEC+1)
+#define FIELD_BADFAXRUN (FIELD_CODEC+2)
+#define FIELD_RECVPARAMS (FIELD_CODEC+3)
+#define FIELD_SUBADDRESS (FIELD_CODEC+4)
+#define FIELD_RECVTIME (FIELD_CODEC+5)
+#define FIELD_FAXDCS (FIELD_CODEC+6)
+
+#define FIELD_OPTIONS (FIELD_CODEC+7)
+
+static const TIFFFieldInfo faxFieldInfo[] = {
+ { TIFFTAG_FAXMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ FALSE, FALSE, "FaxMode" },
+ { TIFFTAG_FAXFILLFUNC, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ FALSE, FALSE, "FaxFillFunc" },
+ { TIFFTAG_BADFAXLINES, 1, 1, TIFF_LONG, FIELD_BADFAXLINES,
+ TRUE, FALSE, "BadFaxLines" },
+ { TIFFTAG_BADFAXLINES, 1, 1, TIFF_SHORT, FIELD_BADFAXLINES,
+ TRUE, FALSE, "BadFaxLines" },
+ { TIFFTAG_CLEANFAXDATA, 1, 1, TIFF_SHORT, FIELD_CLEANFAXDATA,
+ TRUE, FALSE, "CleanFaxData" },
+ { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_LONG, FIELD_BADFAXRUN,
+ TRUE, FALSE, "ConsecutiveBadFaxLines" },
+ { TIFFTAG_CONSECUTIVEBADFAXLINES,1,1, TIFF_SHORT, FIELD_BADFAXRUN,
+ TRUE, FALSE, "ConsecutiveBadFaxLines" },
+ { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS,
+ TRUE, FALSE, "FaxRecvParams" },
+ { TIFFTAG_FAXSUBADDRESS, -1,-1, TIFF_ASCII, FIELD_SUBADDRESS,
+ TRUE, FALSE, "FaxSubAddress" },
+ { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME,
+ TRUE, FALSE, "FaxRecvTime" },
+ { TIFFTAG_FAXDCS, -1,-1, TIFF_ASCII, FIELD_FAXDCS,
+ TRUE, FALSE, "FaxDcs" },
+};
+static const TIFFFieldInfo fax3FieldInfo[] = {
+ { TIFFTAG_GROUP3OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS,
+ FALSE, FALSE, "Group3Options" },
+};
+static const TIFFFieldInfo fax4FieldInfo[] = {
+ { TIFFTAG_GROUP4OPTIONS, 1, 1, TIFF_LONG, FIELD_OPTIONS,
+ FALSE, FALSE, "Group4Options" },
+};
+#define N(a) (sizeof (a) / sizeof (a[0]))
+
+static int
+Fax3VSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ Fax3BaseState* sp = Fax3State(tif);
+ const TIFFFieldInfo* fip;
+
+ assert(sp != 0);
+ assert(sp->vsetparent != 0);
+
+ switch (tag) {
+ case TIFFTAG_FAXMODE:
+ sp->mode = va_arg(ap, int);
+ return 1; /* NB: pseudo tag */
+ case TIFFTAG_FAXFILLFUNC:
+ DecoderState(tif)->fill = va_arg(ap, TIFFFaxFillFunc);
+ return 1; /* NB: pseudo tag */
+ case TIFFTAG_GROUP3OPTIONS:
+ /* XXX: avoid reading options if compression mismatches. */
+ if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX3)
+ sp->groupoptions = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_GROUP4OPTIONS:
+ /* XXX: avoid reading options if compression mismatches. */
+ if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4)
+ sp->groupoptions = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_BADFAXLINES:
+ sp->badfaxlines = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_CLEANFAXDATA:
+ sp->cleanfaxdata = (uint16) va_arg(ap, int);
+ break;
+ case TIFFTAG_CONSECUTIVEBADFAXLINES:
+ sp->badfaxrun = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_FAXRECVPARAMS:
+ sp->recvparams = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_FAXSUBADDRESS:
+ _TIFFsetString(&sp->subaddress, va_arg(ap, char*));
+ break;
+ case TIFFTAG_FAXRECVTIME:
+ sp->recvtime = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_FAXDCS:
+ _TIFFsetString(&sp->faxdcs, va_arg(ap, char*));
+ break;
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+
+ if ((fip = _TIFFFieldWithTag(tif, tag)))
+ TIFFSetFieldBit(tif, fip->field_bit);
+ else
+ return 0;
+
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ return 1;
+}
+
+static int
+Fax3VGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ Fax3BaseState* sp = Fax3State(tif);
+
+ assert(sp != 0);
+
+ switch (tag) {
+ case TIFFTAG_FAXMODE:
+ *va_arg(ap, int*) = sp->mode;
+ break;
+ case TIFFTAG_FAXFILLFUNC:
+ *va_arg(ap, TIFFFaxFillFunc*) = DecoderState(tif)->fill;
+ break;
+ case TIFFTAG_GROUP3OPTIONS:
+ case TIFFTAG_GROUP4OPTIONS:
+ *va_arg(ap, uint32*) = sp->groupoptions;
+ break;
+ case TIFFTAG_BADFAXLINES:
+ *va_arg(ap, uint32*) = sp->badfaxlines;
+ break;
+ case TIFFTAG_CLEANFAXDATA:
+ *va_arg(ap, uint16*) = sp->cleanfaxdata;
+ break;
+ case TIFFTAG_CONSECUTIVEBADFAXLINES:
+ *va_arg(ap, uint32*) = sp->badfaxrun;
+ break;
+ case TIFFTAG_FAXRECVPARAMS:
+ *va_arg(ap, uint32*) = sp->recvparams;
+ break;
+ case TIFFTAG_FAXSUBADDRESS:
+ *va_arg(ap, char**) = sp->subaddress;
+ break;
+ case TIFFTAG_FAXRECVTIME:
+ *va_arg(ap, uint32*) = sp->recvtime;
+ break;
+ case TIFFTAG_FAXDCS:
+ *va_arg(ap, char**) = sp->faxdcs;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return (1);
+}
+
+static void
+Fax3PrintDir(TIFF* tif, FILE* fd, long flags)
+{
+ Fax3BaseState* sp = Fax3State(tif);
+
+ assert(sp != 0);
+
+ (void) flags;
+ if (TIFFFieldSet(tif,FIELD_OPTIONS)) {
+ const char* sep = " ";
+ if (tif->tif_dir.td_compression == COMPRESSION_CCITTFAX4) {
+ fprintf(fd, " Group 4 Options:");
+ if (sp->groupoptions & GROUP4OPT_UNCOMPRESSED)
+ fprintf(fd, "%suncompressed data", sep);
+ } else {
+
+ fprintf(fd, " Group 3 Options:");
+ if (sp->groupoptions & GROUP3OPT_2DENCODING)
+ fprintf(fd, "%s2-d encoding", sep), sep = "+";
+ if (sp->groupoptions & GROUP3OPT_FILLBITS)
+ fprintf(fd, "%sEOL padding", sep), sep = "+";
+ if (sp->groupoptions & GROUP3OPT_UNCOMPRESSED)
+ fprintf(fd, "%suncompressed data", sep);
+ }
+ fprintf(fd, " (%lu = 0x%lx)\n",
+ (unsigned long) sp->groupoptions,
+ (unsigned long) sp->groupoptions);
+ }
+ if (TIFFFieldSet(tif,FIELD_CLEANFAXDATA)) {
+ fprintf(fd, " Fax Data:");
+ switch (sp->cleanfaxdata) {
+ case CLEANFAXDATA_CLEAN:
+ fprintf(fd, " clean");
+ break;
+ case CLEANFAXDATA_REGENERATED:
+ fprintf(fd, " receiver regenerated");
+ break;
+ case CLEANFAXDATA_UNCLEAN:
+ fprintf(fd, " uncorrected errors");
+ break;
+ }
+ fprintf(fd, " (%u = 0x%x)\n",
+ sp->cleanfaxdata, sp->cleanfaxdata);
+ }
+ if (TIFFFieldSet(tif,FIELD_BADFAXLINES))
+ fprintf(fd, " Bad Fax Lines: %lu\n",
+ (unsigned long) sp->badfaxlines);
+ if (TIFFFieldSet(tif,FIELD_BADFAXRUN))
+ fprintf(fd, " Consecutive Bad Fax Lines: %lu\n",
+ (unsigned long) sp->badfaxrun);
+ if (TIFFFieldSet(tif,FIELD_RECVPARAMS))
+ fprintf(fd, " Fax Receive Parameters: %08lx\n",
+ (unsigned long) sp->recvparams);
+ if (TIFFFieldSet(tif,FIELD_SUBADDRESS))
+ fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress);
+ if (TIFFFieldSet(tif,FIELD_RECVTIME))
+ fprintf(fd, " Fax Receive Time: %lu secs\n",
+ (unsigned long) sp->recvtime);
+ if (TIFFFieldSet(tif,FIELD_FAXDCS))
+ fprintf(fd, " Fax DCS: %s\n", sp->faxdcs);
+}
+
+static int
+InitCCITTFax3(TIFF* tif)
+{
+ Fax3BaseState* sp;
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, faxFieldInfo, N(faxFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, "InitCCITTFax3",
+ "Merging common CCITT Fax codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t)
+ _TIFFmalloc(sizeof (Fax3CodecState));
+
+ if (tif->tif_data == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3",
+ "%s: No space for state block", tif->tif_name);
+ return (0);
+ }
+
+ sp = Fax3State(tif);
+ sp->rw_mode = tif->tif_mode;
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = Fax3VGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = Fax3VSetField; /* hook for codec tags */
+ sp->printdir = tif->tif_tagmethods.printdir;
+ tif->tif_tagmethods.printdir = Fax3PrintDir; /* hook for codec tags */
+ sp->groupoptions = 0;
+ sp->recvparams = 0;
+ sp->subaddress = NULL;
+ sp->faxdcs = NULL;
+
+ if (sp->rw_mode == O_RDONLY) /* FIXME: improve for in place update */
+ tif->tif_flags |= TIFF_NOBITREV; /* decoder does bit reversal */
+ DecoderState(tif)->runs = NULL;
+ TIFFSetField(tif, TIFFTAG_FAXFILLFUNC, _TIFFFax3fillruns);
+ EncoderState(tif)->refline = NULL;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = Fax3SetupState;
+ tif->tif_predecode = Fax3PreDecode;
+ tif->tif_decoderow = Fax3Decode1D;
+ tif->tif_decodestrip = Fax3Decode1D;
+ tif->tif_decodetile = Fax3Decode1D;
+ tif->tif_setupencode = Fax3SetupState;
+ tif->tif_preencode = Fax3PreEncode;
+ tif->tif_postencode = Fax3PostEncode;
+ tif->tif_encoderow = Fax3Encode;
+ tif->tif_encodestrip = Fax3Encode;
+ tif->tif_encodetile = Fax3Encode;
+ tif->tif_close = Fax3Close;
+ tif->tif_cleanup = Fax3Cleanup;
+
+ return (1);
+}
+
+int
+TIFFInitCCITTFax3(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ if (InitCCITTFax3(tif)) {
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, fax3FieldInfo, N(fax3FieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax3",
+ "Merging CCITT Fax 3 codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * The default format is Class/F-style w/o RTC.
+ */
+ return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_CLASSF);
+ } else
+ return 01;
+}
+
+/*
+ * CCITT Group 4 (T.6) Facsimile-compatible
+ * Compression Scheme Support.
+ */
+
+#define SWAP(t,a,b) { t x; x = (a); (a) = (b); (b) = x; }
+/*
+ * Decode the requested amount of G4-encoded data.
+ */
+static int
+Fax4Decode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ DECLARE_STATE_2D(tif, sp, "Fax4Decode");
+
+ (void) s;
+ CACHE_STATE(tif, sp);
+ while ((long)occ > 0) {
+ a0 = 0;
+ RunLength = 0;
+ pa = thisrun = sp->curruns;
+ pb = sp->refruns;
+ b1 = *pb++;
+#ifdef FAX3_DEBUG
+ printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", tif->tif_row);
+ fflush(stdout);
+#endif
+ EXPAND2D(EOFG4);
+ if (EOLcnt)
+ goto EOFG4;
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ SETVALUE(0); /* imaginary change for reference */
+ SWAP(uint32*, sp->curruns, sp->refruns);
+ buf += sp->b.rowbytes;
+ occ -= sp->b.rowbytes;
+ sp->line++;
+ continue;
+ EOFG4:
+ NeedBits16( 13, BADG4 );
+ BADG4:
+#ifdef FAX3_DEBUG
+ if( GetBits(13) != 0x1001 )
+ fputs( "Bad RTC\n", stderr );
+#endif
+ ClrBits( 13 );
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ UNCACHE_STATE(tif, sp);
+ return (-1);
+ }
+ UNCACHE_STATE(tif, sp);
+ return (1);
+}
+#undef SWAP
+
+/*
+ * Encode the requested amount of data.
+ */
+static int
+Fax4Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ Fax3CodecState *sp = EncoderState(tif);
+
+ (void) s;
+ while ((long)cc > 0) {
+ if (!Fax3Encode2DRow(tif, bp, sp->refline, sp->b.rowpixels))
+ return (0);
+ _TIFFmemcpy(sp->refline, bp, sp->b.rowbytes);
+ bp += sp->b.rowbytes;
+ cc -= sp->b.rowbytes;
+ }
+ return (1);
+}
+
+static int
+Fax4PostEncode(TIFF* tif)
+{
+ Fax3CodecState *sp = EncoderState(tif);
+
+ /* terminate strip w/ EOFB */
+ Fax3PutBits(tif, EOL, 12);
+ Fax3PutBits(tif, EOL, 12);
+ if (sp->bit != 8)
+ Fax3FlushBits(tif, sp);
+ return (1);
+}
+
+int
+TIFFInitCCITTFax4(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ if (InitCCITTFax3(tif)) { /* reuse G3 support */
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, fax4FieldInfo, N(fax4FieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFInitCCITTFax4",
+ "Merging CCITT Fax 4 codec-specific tags failed");
+ return 0;
+ }
+
+ tif->tif_decoderow = Fax4Decode;
+ tif->tif_decodestrip = Fax4Decode;
+ tif->tif_decodetile = Fax4Decode;
+ tif->tif_encoderow = Fax4Encode;
+ tif->tif_encodestrip = Fax4Encode;
+ tif->tif_encodetile = Fax4Encode;
+ tif->tif_postencode = Fax4PostEncode;
+ /*
+ * Suppress RTC at the end of each strip.
+ */
+ return TIFFSetField(tif, TIFFTAG_FAXMODE, FAXMODE_NORTC);
+ } else
+ return (0);
+}
+
+/*
+ * CCITT Group 3 1-D Modified Huffman RLE Compression Support.
+ * (Compression algorithms 2 and 32771)
+ */
+
+/*
+ * Decode the requested amount of RLE-encoded data.
+ */
+static int
+Fax3DecodeRLE(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ DECLARE_STATE(tif, sp, "Fax3DecodeRLE");
+ int mode = sp->b.mode;
+
+ (void) s;
+ CACHE_STATE(tif, sp);
+ thisrun = sp->curruns;
+ while ((long)occ > 0) {
+ a0 = 0;
+ RunLength = 0;
+ pa = thisrun;
+#ifdef FAX3_DEBUG
+ printf("\nBitAcc=%08X, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", tif->tif_row);
+ fflush(stdout);
+#endif
+ EXPAND1D(EOFRLE);
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ /*
+ * Cleanup at the end of the row.
+ */
+ if (mode & FAXMODE_BYTEALIGN) {
+ int n = BitsAvail - (BitsAvail &~ 7);
+ ClrBits(n);
+ } else if (mode & FAXMODE_WORDALIGN) {
+ int n = BitsAvail - (BitsAvail &~ 15);
+ ClrBits(n);
+ if (BitsAvail == 0 && !isAligned(cp, uint16))
+ cp++;
+ }
+ buf += sp->b.rowbytes;
+ occ -= sp->b.rowbytes;
+ sp->line++;
+ continue;
+ EOFRLE: /* premature EOF */
+ (*sp->fill)(buf, thisrun, pa, lastx);
+ UNCACHE_STATE(tif, sp);
+ return (-1);
+ }
+ UNCACHE_STATE(tif, sp);
+ return (1);
+}
+
+int
+TIFFInitCCITTRLE(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ if (InitCCITTFax3(tif)) { /* reuse G3 support */
+ tif->tif_decoderow = Fax3DecodeRLE;
+ tif->tif_decodestrip = Fax3DecodeRLE;
+ tif->tif_decodetile = Fax3DecodeRLE;
+ /*
+ * Suppress RTC+EOLs when encoding and byte-align data.
+ */
+ return TIFFSetField(tif, TIFFTAG_FAXMODE,
+ FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_BYTEALIGN);
+ } else
+ return (0);
+}
+
+int
+TIFFInitCCITTRLEW(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ if (InitCCITTFax3(tif)) { /* reuse G3 support */
+ tif->tif_decoderow = Fax3DecodeRLE;
+ tif->tif_decodestrip = Fax3DecodeRLE;
+ tif->tif_decodetile = Fax3DecodeRLE;
+ /*
+ * Suppress RTC+EOLs when encoding and word-align data.
+ */
+ return TIFFSetField(tif, TIFFTAG_FAXMODE,
+ FAXMODE_NORTC|FAXMODE_NOEOL|FAXMODE_WORDALIGN);
+ } else
+ return (0);
+}
+#endif /* CCITT_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_fax3.h b/Source/LibTIFF/tif_fax3.h
new file mode 100644
index 0000000..7404397
--- /dev/null
+++ b/Source/LibTIFF/tif_fax3.h
@@ -0,0 +1,525 @@
+/* $Id: tif_fax3.h,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1990-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _FAX3_
+#define _FAX3_
+/*
+ * TIFF Library.
+ *
+ * CCITT Group 3 (T.4) and Group 4 (T.6) Decompression Support.
+ *
+ * Decoder support is derived, with permission, from the code
+ * in Frank Cringle's viewfax program;
+ * Copyright (C) 1990, 1995 Frank D. Cringle.
+ */
+#include "tiff.h"
+
+/*
+ * To override the default routine used to image decoded
+ * spans one can use the pseduo tag TIFFTAG_FAXFILLFUNC.
+ * The routine must have the type signature given below;
+ * for example:
+ *
+ * fillruns(unsigned char* buf, uint32* runs, uint32* erun, uint32 lastx)
+ *
+ * where buf is place to set the bits, runs is the array of b&w run
+ * lengths (white then black), erun is the last run in the array, and
+ * lastx is the width of the row in pixels. Fill routines can assume
+ * the run array has room for at least lastx runs and can overwrite
+ * data in the run array as needed (e.g. to append zero runs to bring
+ * the count up to a nice multiple).
+ */
+typedef void (*TIFFFaxFillFunc)(unsigned char*, uint32*, uint32*, uint32);
+
+/*
+ * The default run filler; made external for other decoders.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern void _TIFFFax3fillruns(unsigned char*, uint32*, uint32*, uint32);
+#if defined(__cplusplus)
+}
+#endif
+
+
+/* finite state machine codes */
+#define S_Null 0
+#define S_Pass 1
+#define S_Horiz 2
+#define S_V0 3
+#define S_VR 4
+#define S_VL 5
+#define S_Ext 6
+#define S_TermW 7
+#define S_TermB 8
+#define S_MakeUpW 9
+#define S_MakeUpB 10
+#define S_MakeUp 11
+#define S_EOL 12
+
+typedef struct { /* state table entry */
+ unsigned char State; /* see above */
+ unsigned char Width; /* width of code in bits */
+ uint32 Param; /* unsigned 32-bit run length in bits */
+} TIFFFaxTabEnt;
+
+extern const TIFFFaxTabEnt TIFFFaxMainTable[];
+extern const TIFFFaxTabEnt TIFFFaxWhiteTable[];
+extern const TIFFFaxTabEnt TIFFFaxBlackTable[];
+
+/*
+ * The following macros define the majority of the G3/G4 decoder
+ * algorithm using the state tables defined elsewhere. To build
+ * a decoder you need some setup code and some glue code. Note
+ * that you may also need/want to change the way the NeedBits*
+ * macros get input data if, for example, you know the data to be
+ * decoded is properly aligned and oriented (doing so before running
+ * the decoder can be a big performance win).
+ *
+ * Consult the decoder in the TIFF library for an idea of what you
+ * need to define and setup to make use of these definitions.
+ *
+ * NB: to enable a debugging version of these macros define FAX3_DEBUG
+ * before including this file. Trace output goes to stdout.
+ */
+
+#ifndef EndOfData
+#define EndOfData() (cp >= ep)
+#endif
+/*
+ * Need <=8 or <=16 bits of input data. Unlike viewfax we
+ * cannot use/assume a word-aligned, properly bit swizzled
+ * input data set because data may come from an arbitrarily
+ * aligned, read-only source such as a memory-mapped file.
+ * Note also that the viewfax decoder does not check for
+ * running off the end of the input data buffer. This is
+ * possible for G3-encoded data because it prescans the input
+ * data to count EOL markers, but can cause problems for G4
+ * data. In any event, we don't prescan and must watch for
+ * running out of data since we can't permit the library to
+ * scan past the end of the input data buffer.
+ *
+ * Finally, note that we must handle remaindered data at the end
+ * of a strip specially. The coder asks for a fixed number of
+ * bits when scanning for the next code. This may be more bits
+ * than are actually present in the data stream. If we appear
+ * to run out of data but still have some number of valid bits
+ * remaining then we makeup the requested amount with zeros and
+ * return successfully. If the returned data is incorrect then
+ * we should be called again and get a premature EOF error;
+ * otherwise we should get the right answer.
+ */
+#ifndef NeedBits8
+#define NeedBits8(n,eoflab) do { \
+ if (BitsAvail < (n)) { \
+ if (EndOfData()) { \
+ if (BitsAvail == 0) /* no valid bits */ \
+ goto eoflab; \
+ BitsAvail = (n); /* pad with zeros */ \
+ } else { \
+ BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
+ BitsAvail += 8; \
+ } \
+ } \
+} while (0)
+#endif
+#ifndef NeedBits16
+#define NeedBits16(n,eoflab) do { \
+ if (BitsAvail < (n)) { \
+ if (EndOfData()) { \
+ if (BitsAvail == 0) /* no valid bits */ \
+ goto eoflab; \
+ BitsAvail = (n); /* pad with zeros */ \
+ } else { \
+ BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
+ if ((BitsAvail += 8) < (n)) { \
+ if (EndOfData()) { \
+ /* NB: we know BitsAvail is non-zero here */ \
+ BitsAvail = (n); /* pad with zeros */ \
+ } else { \
+ BitAcc |= ((uint32) bitmap[*cp++])<<BitsAvail; \
+ BitsAvail += 8; \
+ } \
+ } \
+ } \
+ } \
+} while (0)
+#endif
+#define GetBits(n) (BitAcc & ((1<<(n))-1))
+#define ClrBits(n) do { \
+ BitsAvail -= (n); \
+ BitAcc >>= (n); \
+} while (0)
+
+#ifdef FAX3_DEBUG
+static const char* StateNames[] = {
+ "Null ",
+ "Pass ",
+ "Horiz ",
+ "V0 ",
+ "VR ",
+ "VL ",
+ "Ext ",
+ "TermW ",
+ "TermB ",
+ "MakeUpW",
+ "MakeUpB",
+ "MakeUp ",
+ "EOL ",
+};
+#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
+#define LOOKUP8(wid,tab,eoflab) do { \
+ int t; \
+ NeedBits8(wid,eoflab); \
+ TabEnt = tab + GetBits(wid); \
+ printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \
+ StateNames[TabEnt->State], TabEnt->Param); \
+ for (t = 0; t < TabEnt->Width; t++) \
+ DEBUG_SHOW; \
+ putchar('\n'); \
+ fflush(stdout); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+#define LOOKUP16(wid,tab,eoflab) do { \
+ int t; \
+ NeedBits16(wid,eoflab); \
+ TabEnt = tab + GetBits(wid); \
+ printf("%08lX/%d: %s%5d\t", (long) BitAcc, BitsAvail, \
+ StateNames[TabEnt->State], TabEnt->Param); \
+ for (t = 0; t < TabEnt->Width; t++) \
+ DEBUG_SHOW; \
+ putchar('\n'); \
+ fflush(stdout); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+#define SETVALUE(x) do { \
+ *pa++ = RunLength + (x); \
+ printf("SETVALUE: %d\t%d\n", RunLength + (x), a0); \
+ a0 += x; \
+ RunLength = 0; \
+} while (0)
+#else
+#define LOOKUP8(wid,tab,eoflab) do { \
+ NeedBits8(wid,eoflab); \
+ TabEnt = tab + GetBits(wid); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+#define LOOKUP16(wid,tab,eoflab) do { \
+ NeedBits16(wid,eoflab); \
+ TabEnt = tab + GetBits(wid); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+/*
+ * Append a run to the run length array for the
+ * current row and reset decoding state.
+ */
+#define SETVALUE(x) do { \
+ *pa++ = RunLength + (x); \
+ a0 += (x); \
+ RunLength = 0; \
+} while (0)
+#endif
+
+/*
+ * Synchronize input decoding at the start of each
+ * row by scanning for an EOL (if appropriate) and
+ * skipping any trash data that might be present
+ * after a decoding error. Note that the decoding
+ * done elsewhere that recognizes an EOL only consumes
+ * 11 consecutive zero bits. This means that if EOLcnt
+ * is non-zero then we still need to scan for the final flag
+ * bit that is part of the EOL code.
+ */
+#define SYNC_EOL(eoflab) do { \
+ if (EOLcnt == 0) { \
+ for (;;) { \
+ NeedBits16(11,eoflab); \
+ if (GetBits(11) == 0) \
+ break; \
+ ClrBits(1); \
+ } \
+ } \
+ for (;;) { \
+ NeedBits8(8,eoflab); \
+ if (GetBits(8)) \
+ break; \
+ ClrBits(8); \
+ } \
+ while (GetBits(1) == 0) \
+ ClrBits(1); \
+ ClrBits(1); /* EOL bit */ \
+ EOLcnt = 0; /* reset EOL counter/flag */ \
+} while (0)
+
+/*
+ * Cleanup the array of runs after decoding a row.
+ * We adjust final runs to insure the user buffer is not
+ * overwritten and/or undecoded area is white filled.
+ */
+#define CLEANUP_RUNS() do { \
+ if (RunLength) \
+ SETVALUE(0); \
+ if (a0 != lastx) { \
+ badlength(a0, lastx); \
+ while (a0 > lastx && pa > thisrun) \
+ a0 -= *--pa; \
+ if (a0 < lastx) { \
+ if (a0 < 0) \
+ a0 = 0; \
+ if ((pa-thisrun)&1) \
+ SETVALUE(0); \
+ SETVALUE(lastx - a0); \
+ } else if (a0 > lastx) { \
+ SETVALUE(lastx); \
+ SETVALUE(0); \
+ } \
+ } \
+} while (0)
+
+/*
+ * Decode a line of 1D-encoded data.
+ *
+ * The line expanders are written as macros so that they can be reused
+ * but still have direct access to the local variables of the "calling"
+ * function.
+ *
+ * Note that unlike the original version we have to explicitly test for
+ * a0 >= lastx after each black/white run is decoded. This is because
+ * the original code depended on the input data being zero-padded to
+ * insure the decoder recognized an EOL before running out of data.
+ */
+#define EXPAND1D(eoflab) do { \
+ for (;;) { \
+ for (;;) { \
+ LOOKUP16(12, TIFFFaxWhiteTable, eof1d); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto done1d; \
+ case S_TermW: \
+ SETVALUE(TabEnt->Param); \
+ goto doneWhite1d; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("WhiteTable", a0); \
+ goto done1d; \
+ } \
+ } \
+ doneWhite1d: \
+ if (a0 >= lastx) \
+ goto done1d; \
+ for (;;) { \
+ LOOKUP16(13, TIFFFaxBlackTable, eof1d); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto done1d; \
+ case S_TermB: \
+ SETVALUE(TabEnt->Param); \
+ goto doneBlack1d; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("BlackTable", a0); \
+ goto done1d; \
+ } \
+ } \
+ doneBlack1d: \
+ if (a0 >= lastx) \
+ goto done1d; \
+ if( *(pa-1) == 0 && *(pa-2) == 0 ) \
+ pa -= 2; \
+ } \
+eof1d: \
+ prematureEOF(a0); \
+ CLEANUP_RUNS(); \
+ goto eoflab; \
+done1d: \
+ CLEANUP_RUNS(); \
+} while (0)
+
+/*
+ * Update the value of b1 using the array
+ * of runs for the reference line.
+ */
+#define CHECK_b1 do { \
+ if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \
+ b1 += pb[0] + pb[1]; \
+ pb += 2; \
+ } \
+} while (0)
+
+/*
+ * Expand a row of 2D-encoded data.
+ */
+#define EXPAND2D(eoflab) do { \
+ while (a0 < lastx) { \
+ LOOKUP8(7, TIFFFaxMainTable, eof2d); \
+ switch (TabEnt->State) { \
+ case S_Pass: \
+ CHECK_b1; \
+ b1 += *pb++; \
+ RunLength += b1 - a0; \
+ a0 = b1; \
+ b1 += *pb++; \
+ break; \
+ case S_Horiz: \
+ if ((pa-thisrun)&1) { \
+ for (;;) { /* black first */ \
+ LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVALUE(TabEnt->Param); \
+ goto doneWhite2da; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ goto badBlack2d; \
+ } \
+ } \
+ doneWhite2da:; \
+ for (;;) { /* then white */ \
+ LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVALUE(TabEnt->Param); \
+ goto doneBlack2da; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ goto badWhite2d; \
+ } \
+ } \
+ doneBlack2da:; \
+ } else { \
+ for (;;) { /* white first */ \
+ LOOKUP16(12, TIFFFaxWhiteTable, eof2d); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVALUE(TabEnt->Param); \
+ goto doneWhite2db; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ goto badWhite2d; \
+ } \
+ } \
+ doneWhite2db:; \
+ for (;;) { /* then black */ \
+ LOOKUP16(13, TIFFFaxBlackTable, eof2d); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVALUE(TabEnt->Param); \
+ goto doneBlack2db; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ goto badBlack2d; \
+ } \
+ } \
+ doneBlack2db:; \
+ } \
+ CHECK_b1; \
+ break; \
+ case S_V0: \
+ CHECK_b1; \
+ SETVALUE(b1 - a0); \
+ b1 += *pb++; \
+ break; \
+ case S_VR: \
+ CHECK_b1; \
+ SETVALUE(b1 - a0 + TabEnt->Param); \
+ b1 += *pb++; \
+ break; \
+ case S_VL: \
+ CHECK_b1; \
+ SETVALUE(b1 - a0 - TabEnt->Param); \
+ b1 -= *--pb; \
+ break; \
+ case S_Ext: \
+ *pa++ = lastx - a0; \
+ extension(a0); \
+ goto eol2d; \
+ case S_EOL: \
+ *pa++ = lastx - a0; \
+ NeedBits8(4,eof2d); \
+ if (GetBits(4)) \
+ unexpected("EOL", a0); \
+ ClrBits(4); \
+ EOLcnt = 1; \
+ goto eol2d; \
+ default: \
+ badMain2d: \
+ unexpected("MainTable", a0); \
+ goto eol2d; \
+ badBlack2d: \
+ unexpected("BlackTable", a0); \
+ goto eol2d; \
+ badWhite2d: \
+ unexpected("WhiteTable", a0); \
+ goto eol2d; \
+ eof2d: \
+ prematureEOF(a0); \
+ CLEANUP_RUNS(); \
+ goto eoflab; \
+ } \
+ } \
+ if (RunLength) { \
+ if (RunLength + a0 < lastx) { \
+ /* expect a final V0 */ \
+ NeedBits8(1,eof2d); \
+ if (!GetBits(1)) \
+ goto badMain2d; \
+ ClrBits(1); \
+ } \
+ SETVALUE(0); \
+ } \
+eol2d: \
+ CLEANUP_RUNS(); \
+} while (0)
+#endif /* _FAX3_ */
diff --git a/Source/LibTIFF/tif_fax3sm.c b/Source/LibTIFF/tif_fax3sm.c
new file mode 100644
index 0000000..08ce1ad
--- /dev/null
+++ b/Source/LibTIFF/tif_fax3sm.c
@@ -0,0 +1,1253 @@
+/* WARNING, this file was automatically generated by the
+ mkg3states program */
+#include "tiff.h"
+#include "tif_fax3.h"
+ const TIFFFaxTabEnt TIFFFaxMainTable[128] = {
+{12,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{5,6,2},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{5,7,3},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,6,2},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{6,7,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{5,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},
+{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},{4,7,3},{3,1,0},{5,3,1},{3,1,0},
+{2,3,0},{3,1,0},{4,3,1},{3,1,0},{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},
+{4,3,1},{3,1,0},{4,6,2},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0},
+{1,4,0},{3,1,0},{5,3,1},{3,1,0},{2,3,0},{3,1,0},{4,3,1},{3,1,0}
+};
+ const TIFFFaxTabEnt TIFFFaxWhiteTable[4096] = {
+{12,11,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2112},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2368},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,12,1984},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2240},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2496},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{12,11,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1792},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,11,1856},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2176},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1600},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},
+{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},
+{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},
+{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},{7,8,43},{7,6,17},
+{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},
+{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},
+{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,768},{7,4,6},
+{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2432},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},{7,7,19},{7,5,8},
+{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},
+{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},{9,9,1408},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},
+{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},
+{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},
+{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},
+{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},
+{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,960},{7,4,6},
+{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},
+{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{11,12,2048},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},
+{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},
+{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},{7,8,32},{7,5,8},
+{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},
+{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},
+{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1536},{7,4,5},
+{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},
+{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,11,1920},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},
+{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,896},{7,4,6},
+{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},
+{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},
+{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},{7,8,44},{7,6,17},
+{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},
+{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},
+{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},
+{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},
+{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},
+{7,8,55},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},
+{7,8,53},{7,5,9},{9,8,448},{7,4,6},{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1472},{7,4,5},{7,8,43},{7,6,17},{9,9,1216},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},
+{7,8,61},{7,4,4},{7,4,2},{7,4,7},{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},
+{9,9,960},{7,4,6},{7,8,31},{7,5,8},{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,9,704},{7,4,6},{7,8,37},{9,5,128},
+{7,7,25},{7,6,15},{9,8,320},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},
+{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{11,12,2304},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,7,20},{9,5,128},{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},
+{7,7,27},{7,4,5},{7,8,40},{7,6,16},{9,9,832},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},
+{9,8,512},{7,4,6},{7,8,36},{9,5,128},{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{9,9,1600},{7,4,5},{7,8,44},{7,6,17},{9,9,1344},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},
+{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},
+{7,4,2},{7,4,7},{7,8,48},{7,4,3},{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1088},{7,4,6},
+{7,8,32},{7,5,8},{7,8,58},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},
+{7,5,11},{7,4,5},{7,7,26},{7,5,9},{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},
+{9,8,384},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},
+{9,7,256},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{0,0,0},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},
+{7,7,24},{7,6,14},{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},
+{7,8,39},{7,6,16},{9,8,576},{7,4,6},{7,7,19},{7,5,8},{7,8,55},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,45},{7,4,3},{7,5,11},{7,4,5},{7,8,53},{7,5,9},{9,8,448},{7,4,6},
+{7,8,35},{9,5,128},{7,8,51},{7,6,15},{7,8,63},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},
+{9,9,1536},{7,4,5},{7,8,43},{7,6,17},{9,9,1280},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,8,29},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},
+{9,6,1664},{7,4,6},{7,8,33},{9,5,128},{7,8,49},{7,6,14},{7,8,61},{7,4,4},{7,4,2},{7,4,7},
+{7,8,47},{7,4,3},{7,8,59},{7,4,5},{7,8,41},{7,6,16},{9,9,1024},{7,4,6},{7,8,31},{7,5,8},
+{7,8,57},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},
+{7,7,26},{7,5,9},{9,9,768},{7,4,6},{7,8,37},{9,5,128},{7,7,25},{7,6,15},{9,8,320},{7,4,4},
+{7,4,2},{7,4,7},{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},
+{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},{11,12,2560},{7,4,3},
+{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},{7,7,20},{9,5,128},{7,7,24},{7,6,14},
+{7,7,28},{7,4,4},{7,4,2},{7,4,7},{7,7,23},{7,4,3},{7,7,27},{7,4,5},{7,8,40},{7,6,16},
+{9,9,896},{7,4,6},{7,7,19},{7,5,8},{7,8,56},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7},
+{7,8,46},{7,4,3},{7,5,11},{7,4,5},{7,8,54},{7,5,9},{9,8,512},{7,4,6},{7,8,36},{9,5,128},
+{7,8,52},{7,6,15},{7,8,0},{7,4,4},{7,4,2},{7,4,7},{7,6,13},{7,4,3},{9,9,1728},{7,4,5},
+{7,8,44},{7,6,17},{9,9,1408},{7,4,6},{7,6,1},{7,5,8},{9,6,192},{9,5,64},{7,5,10},{7,4,4},
+{7,4,2},{7,4,7},{7,8,30},{7,4,3},{7,5,11},{7,4,5},{7,6,12},{7,5,9},{9,6,1664},{7,4,6},
+{7,8,34},{9,5,128},{7,8,50},{7,6,14},{7,8,62},{7,4,4},{7,4,2},{7,4,7},{7,8,48},{7,4,3},
+{7,8,60},{7,4,5},{7,8,42},{7,6,16},{9,9,1152},{7,4,6},{7,8,32},{7,5,8},{7,8,58},{9,5,64},
+{7,5,10},{7,4,4},{7,4,2},{7,4,7},{7,7,22},{7,4,3},{7,5,11},{7,4,5},{7,7,26},{7,5,9},
+{9,8,640},{7,4,6},{7,8,38},{9,5,128},{7,7,25},{7,6,15},{9,8,384},{7,4,4},{7,4,2},{7,4,7},
+{7,6,13},{7,4,3},{7,7,18},{7,4,5},{7,7,21},{7,6,17},{9,7,256},{7,4,6},{7,6,1},{7,5,8},
+{9,6,192},{9,5,64},{7,5,10},{7,4,4},{7,4,2},{7,4,7}
+};
+ const TIFFFaxTabEnt TIFFFaxBlackTable[8192] = {
+{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,56},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,30},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2112},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,44},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,60},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,1984},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,34},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1664},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1408},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,61},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,1024},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,768},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,62},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,38},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,512},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2496},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,25},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,12,192},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1280},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,31},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,21},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,896},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,640},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,45},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,12,448},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1536},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,41},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2048},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,51},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,59},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1152},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,63},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,2304},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,39},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,128},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,56},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,30},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,11,1856},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,57},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,54},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,52},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,48},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2112},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,44},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,36},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,384},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,28},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,60},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,40},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,12,2368},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,1984},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,50},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,34},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,1728},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,26},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,1472},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,32},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,61},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,42},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1088},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,832},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,62},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2240},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,46},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,38},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,576},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2496},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{12,11,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,18},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1792},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,23},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,20},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,25},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,192},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1344},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,31},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,11,1856},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,58},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,21},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{10,13,960},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,13,704},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,49},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2176},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,45},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,37},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,448},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,29},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1600},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,41},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{11,12,2432},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,18},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,17},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2048},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,51},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,35},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{10,12,320},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,27},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,59},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,33},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{11,11,1920},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,12,256},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,43},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,13,1216},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{0,0,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,8,13},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,9,15},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,55},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,63},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2304},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,12,47},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,12,39},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,12,53},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,12},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{0,0,0},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,8,13},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,11,19},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,11,24},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,11,22},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{11,12,2560},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,7,10},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,10,16},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2},{8,10,0},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},
+{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{10,10,64},{8,2,3},
+{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,9},{8,2,3},{8,3,1},{8,2,2},
+{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,11},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},
+{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},
+{8,8,14},{8,2,3},{8,3,1},{8,2,2},{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,6,8},{8,2,3},
+{8,3,1},{8,2,2},{8,4,5},{8,2,3},{8,3,4},{8,2,2},{8,7,12},{8,2,3},{8,3,1},{8,2,2},
+{8,4,6},{8,2,3},{8,3,4},{8,2,2},{8,5,7},{8,2,3},{8,3,1},{8,2,2},{8,4,5},{8,2,3},
+{8,3,4},{8,2,2}
+};
diff --git a/Source/LibTIFF/tif_flush.c b/Source/LibTIFF/tif_flush.c
new file mode 100644
index 0000000..43b68f4
--- /dev/null
+++ b/Source/LibTIFF/tif_flush.c
@@ -0,0 +1,67 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_flush.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+int
+TIFFFlush(TIFF* tif)
+{
+
+ if (tif->tif_mode != O_RDONLY) {
+ if (!TIFFFlushData(tif))
+ return (0);
+ if ((tif->tif_flags & TIFF_DIRTYDIRECT) &&
+ !TIFFWriteDirectory(tif))
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Flush buffered data to the file.
+ *
+ * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING
+ * is not set, so that TIFFFlush() will proceed to write out the directory.
+ * The documentation says returning 1 is an error indicator, but not having
+ * been writing isn't exactly a an error. Hopefully this doesn't cause
+ * problems for other people.
+ */
+int
+TIFFFlushData(TIFF* tif)
+{
+ if ((tif->tif_flags & TIFF_BEENWRITING) == 0)
+ return (0);
+ if (tif->tif_flags & TIFF_POSTENCODE) {
+ tif->tif_flags &= ~TIFF_POSTENCODE;
+ if (!(*tif->tif_postencode)(tif))
+ return (0);
+ }
+ return (TIFFFlushData1(tif));
+}
+
diff --git a/Source/LibTIFF/tif_getimage.c b/Source/LibTIFF/tif_getimage.c
new file mode 100644
index 0000000..2c1d6a6
--- /dev/null
+++ b/Source/LibTIFF/tif_getimage.c
@@ -0,0 +1,2669 @@
+/* $Id: tif_getimage.c,v 1.29 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Read and return a packed RGBA image.
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+static int gtTileContig(TIFFRGBAImage*, uint32*, uint32, uint32);
+static int gtTileSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
+static int gtStripContig(TIFFRGBAImage*, uint32*, uint32, uint32);
+static int gtStripSeparate(TIFFRGBAImage*, uint32*, uint32, uint32);
+static int PickContigCase(TIFFRGBAImage*);
+static int PickSeparateCase(TIFFRGBAImage*);
+static const char photoTag[] = "PhotometricInterpretation";
+
+/*
+ * Helper constants used in Orientation tag handling
+ */
+#define FLIP_VERTICALLY 0x01
+#define FLIP_HORIZONTALLY 0x02
+
+/*
+ * Color conversion constants. We will define display types here.
+ */
+
+TIFFDisplay display_sRGB = {
+ { /* XYZ -> luminance matrix */
+ { 3.2410F, -1.5374F, -0.4986F },
+ { -0.9692F, 1.8760F, 0.0416F },
+ { 0.0556F, -0.2040F, 1.0570F }
+ },
+ 100.0F, 100.0F, 100.0F, /* Light o/p for reference white */
+ 255, 255, 255, /* Pixel values for ref. white */
+ 1.0F, 1.0F, 1.0F, /* Residual light o/p for black pixel */
+ 2.4F, 2.4F, 2.4F, /* Gamma values for the three guns */
+};
+
+/*
+ * Check the image to see if TIFFReadRGBAImage can deal with it.
+ * 1/0 is returned according to whether or not the image can
+ * be handled. If 0 is returned, emsg contains the reason
+ * why it is being rejected.
+ */
+int
+TIFFRGBAImageOK(TIFF* tif, char emsg[1024])
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ uint16 photometric;
+ int colorchannels;
+
+ if (!tif->tif_decodestatus) {
+ sprintf(emsg, "Sorry, requested compression method is not configured");
+ return (0);
+ }
+ switch (td->td_bitspersample) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ break;
+ default:
+ sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
+ td->td_bitspersample);
+ return (0);
+ }
+ colorchannels = td->td_samplesperpixel - td->td_extrasamples;
+ if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric)) {
+ switch (colorchannels) {
+ case 1:
+ photometric = PHOTOMETRIC_MINISBLACK;
+ break;
+ case 3:
+ photometric = PHOTOMETRIC_RGB;
+ break;
+ default:
+ sprintf(emsg, "Missing needed %s tag", photoTag);
+ return (0);
+ }
+ }
+ switch (photometric) {
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ case PHOTOMETRIC_PALETTE:
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG
+ && td->td_samplesperpixel != 1
+ && td->td_bitspersample < 8 ) {
+ sprintf(emsg,
+ "Sorry, can not handle contiguous data with %s=%d, "
+ "and %s=%d and Bits/Sample=%d",
+ photoTag, photometric,
+ "Samples/pixel", td->td_samplesperpixel,
+ td->td_bitspersample);
+ return (0);
+ }
+ /*
+ * We should likely validate that any extra samples are either
+ * to be ignored, or are alpha, and if alpha we should try to use
+ * them. But for now we won't bother with this.
+ */
+ break;
+ case PHOTOMETRIC_YCBCR:
+ /*
+ * TODO: if at all meaningful and useful, make more complete
+ * support check here, or better still, refactor to let supporting
+ * code decide whether there is support and what meaningfull
+ * error to return
+ */
+ break;
+ case PHOTOMETRIC_RGB:
+ if (colorchannels < 3) {
+ sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
+ "Color channels", colorchannels);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_SEPARATED:
+ {
+ uint16 inkset;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
+ if (inkset != INKSET_CMYK) {
+ sprintf(emsg,
+ "Sorry, can not handle separated image with %s=%d",
+ "InkSet", inkset);
+ return 0;
+ }
+ if (td->td_samplesperpixel < 4) {
+ sprintf(emsg,
+ "Sorry, can not handle separated image with %s=%d",
+ "Samples/pixel", td->td_samplesperpixel);
+ return 0;
+ }
+ break;
+ }
+ case PHOTOMETRIC_LOGL:
+ if (td->td_compression != COMPRESSION_SGILOG) {
+ sprintf(emsg, "Sorry, LogL data must have %s=%d",
+ "Compression", COMPRESSION_SGILOG);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_LOGLUV:
+ if (td->td_compression != COMPRESSION_SGILOG &&
+ td->td_compression != COMPRESSION_SGILOG24) {
+ sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
+ "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
+ return (0);
+ }
+ if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
+ sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
+ "Planarconfiguration", td->td_planarconfig);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_CIELAB:
+ break;
+ default:
+ sprintf(emsg, "Sorry, can not handle image with %s=%d",
+ photoTag, photometric);
+ return (0);
+ }
+ return (1);
+}
+
+void
+TIFFRGBAImageEnd(TIFFRGBAImage* img)
+{
+ if (img->Map)
+ _TIFFfree(img->Map), img->Map = NULL;
+ if (img->BWmap)
+ _TIFFfree(img->BWmap), img->BWmap = NULL;
+ if (img->PALmap)
+ _TIFFfree(img->PALmap), img->PALmap = NULL;
+ if (img->ycbcr)
+ _TIFFfree(img->ycbcr), img->ycbcr = NULL;
+ if (img->cielab)
+ _TIFFfree(img->cielab), img->cielab = NULL;
+ if( img->redcmap ) {
+ _TIFFfree( img->redcmap );
+ _TIFFfree( img->greencmap );
+ _TIFFfree( img->bluecmap );
+ }
+}
+
+static int
+isCCITTCompression(TIFF* tif)
+{
+ uint16 compress;
+ TIFFGetField(tif, TIFFTAG_COMPRESSION, &compress);
+ return (compress == COMPRESSION_CCITTFAX3 ||
+ compress == COMPRESSION_CCITTFAX4 ||
+ compress == COMPRESSION_CCITTRLE ||
+ compress == COMPRESSION_CCITTRLEW);
+}
+
+int
+TIFFRGBAImageBegin(TIFFRGBAImage* img, TIFF* tif, int stop, char emsg[1024])
+{
+ uint16* sampleinfo;
+ uint16 extrasamples;
+ uint16 planarconfig;
+ uint16 compress;
+ int colorchannels;
+ uint16 *red_orig, *green_orig, *blue_orig;
+ int n_color;
+
+ /* Initialize to normal values */
+ img->row_offset = 0;
+ img->col_offset = 0;
+ img->redcmap = NULL;
+ img->greencmap = NULL;
+ img->bluecmap = NULL;
+ img->req_orientation = ORIENTATION_BOTLEFT; /* It is the default */
+
+ img->tif = tif;
+ img->stoponerr = stop;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &img->bitspersample);
+ switch (img->bitspersample) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ break;
+ default:
+ sprintf(emsg, "Sorry, can not handle images with %d-bit samples",
+ img->bitspersample);
+ return (0);
+ }
+ img->alpha = 0;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &img->samplesperpixel);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_EXTRASAMPLES,
+ &extrasamples, &sampleinfo);
+ if (extrasamples >= 1)
+ {
+ switch (sampleinfo[0]) {
+ case EXTRASAMPLE_UNSPECIFIED: /* Workaround for some images without */
+ if (img->samplesperpixel > 3) /* correct info about alpha channel */
+ img->alpha = EXTRASAMPLE_ASSOCALPHA;
+ break;
+ case EXTRASAMPLE_ASSOCALPHA: /* data is pre-multiplied */
+ case EXTRASAMPLE_UNASSALPHA: /* data is not pre-multiplied */
+ img->alpha = sampleinfo[0];
+ break;
+ }
+ }
+
+#ifdef DEFAULT_EXTRASAMPLE_AS_ALPHA
+ if( !TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric))
+ img->photometric = PHOTOMETRIC_MINISWHITE;
+
+ if( extrasamples == 0
+ && img->samplesperpixel == 4
+ && img->photometric == PHOTOMETRIC_RGB )
+ {
+ img->alpha = EXTRASAMPLE_ASSOCALPHA;
+ extrasamples = 1;
+ }
+#endif
+
+ colorchannels = img->samplesperpixel - extrasamples;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_COMPRESSION, &compress);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
+ if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &img->photometric)) {
+ switch (colorchannels) {
+ case 1:
+ if (isCCITTCompression(tif))
+ img->photometric = PHOTOMETRIC_MINISWHITE;
+ else
+ img->photometric = PHOTOMETRIC_MINISBLACK;
+ break;
+ case 3:
+ img->photometric = PHOTOMETRIC_RGB;
+ break;
+ default:
+ sprintf(emsg, "Missing needed %s tag", photoTag);
+ return (0);
+ }
+ }
+ switch (img->photometric) {
+ case PHOTOMETRIC_PALETTE:
+ if (!TIFFGetField(tif, TIFFTAG_COLORMAP,
+ &red_orig, &green_orig, &blue_orig)) {
+ sprintf(emsg, "Missing required \"Colormap\" tag");
+ return (0);
+ }
+
+ /* copy the colormaps so we can modify them */
+ n_color = (1L << img->bitspersample);
+ img->redcmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+ img->greencmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+ img->bluecmap = (uint16 *) _TIFFmalloc(sizeof(uint16)*n_color);
+ if( !img->redcmap || !img->greencmap || !img->bluecmap ) {
+ sprintf(emsg, "Out of memory for colormap copy");
+ return (0);
+ }
+
+ _TIFFmemcpy( img->redcmap, red_orig, n_color * 2 );
+ _TIFFmemcpy( img->greencmap, green_orig, n_color * 2 );
+ _TIFFmemcpy( img->bluecmap, blue_orig, n_color * 2 );
+
+ /* fall thru... */
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ if (planarconfig == PLANARCONFIG_CONTIG
+ && img->samplesperpixel != 1
+ && img->bitspersample < 8 ) {
+ sprintf(emsg,
+ "Sorry, can not handle contiguous data with %s=%d, "
+ "and %s=%d and Bits/Sample=%d",
+ photoTag, img->photometric,
+ "Samples/pixel", img->samplesperpixel,
+ img->bitspersample);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_YCBCR:
+ /* It would probably be nice to have a reality check here. */
+ if (planarconfig == PLANARCONFIG_CONTIG)
+ /* can rely on libjpeg to convert to RGB */
+ /* XXX should restore current state on exit */
+ switch (compress) {
+ case COMPRESSION_JPEG:
+ /*
+ * TODO: when complete tests verify complete desubsampling
+ * and YCbCr handling, remove use of TIFFTAG_JPEGCOLORMODE in
+ * favor of tif_getimage.c native handling
+ */
+ TIFFSetField(tif, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
+ img->photometric = PHOTOMETRIC_RGB;
+ break;
+ default:
+ /* do nothing */;
+ break;
+ }
+ /*
+ * TODO: if at all meaningful and useful, make more complete
+ * support check here, or better still, refactor to let supporting
+ * code decide whether there is support and what meaningfull
+ * error to return
+ */
+ break;
+ case PHOTOMETRIC_RGB:
+ if (colorchannels < 3) {
+ sprintf(emsg, "Sorry, can not handle RGB image with %s=%d",
+ "Color channels", colorchannels);
+ return (0);
+ }
+ break;
+ case PHOTOMETRIC_SEPARATED:
+ {
+ uint16 inkset;
+ TIFFGetFieldDefaulted(tif, TIFFTAG_INKSET, &inkset);
+ if (inkset != INKSET_CMYK) {
+ sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+ "InkSet", inkset);
+ return (0);
+ }
+ if (img->samplesperpixel < 4) {
+ sprintf(emsg, "Sorry, can not handle separated image with %s=%d",
+ "Samples/pixel", img->samplesperpixel);
+ return (0);
+ }
+ }
+ break;
+ case PHOTOMETRIC_LOGL:
+ if (compress != COMPRESSION_SGILOG) {
+ sprintf(emsg, "Sorry, LogL data must have %s=%d",
+ "Compression", COMPRESSION_SGILOG);
+ return (0);
+ }
+ TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
+ img->photometric = PHOTOMETRIC_MINISBLACK; /* little white lie */
+ img->bitspersample = 8;
+ break;
+ case PHOTOMETRIC_LOGLUV:
+ if (compress != COMPRESSION_SGILOG && compress != COMPRESSION_SGILOG24) {
+ sprintf(emsg, "Sorry, LogLuv data must have %s=%d or %d",
+ "Compression", COMPRESSION_SGILOG, COMPRESSION_SGILOG24);
+ return (0);
+ }
+ if (planarconfig != PLANARCONFIG_CONTIG) {
+ sprintf(emsg, "Sorry, can not handle LogLuv images with %s=%d",
+ "Planarconfiguration", planarconfig);
+ return (0);
+ }
+ TIFFSetField(tif, TIFFTAG_SGILOGDATAFMT, SGILOGDATAFMT_8BIT);
+ img->photometric = PHOTOMETRIC_RGB; /* little white lie */
+ img->bitspersample = 8;
+ break;
+ case PHOTOMETRIC_CIELAB:
+ break;
+ default:
+ sprintf(emsg, "Sorry, can not handle image with %s=%d",
+ photoTag, img->photometric);
+ return (0);
+ }
+ img->Map = NULL;
+ img->BWmap = NULL;
+ img->PALmap = NULL;
+ img->ycbcr = NULL;
+ img->cielab = NULL;
+ TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img->width);
+ TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img->height);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ORIENTATION, &img->orientation);
+ img->isContig =
+ !(planarconfig == PLANARCONFIG_SEPARATE && colorchannels > 1);
+ if (img->isContig) {
+ if (!PickContigCase(img)) {
+ sprintf(emsg, "Sorry, can not handle image");
+ return 0;
+ }
+ } else {
+ if (!PickSeparateCase(img)) {
+ sprintf(emsg, "Sorry, can not handle image");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int
+TIFFRGBAImageGet(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+ if (img->get == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No \"get\" routine setup");
+ return (0);
+ }
+ if (img->put.any == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
+ "No \"put\" routine setupl; probably can not handle image format");
+ return (0);
+ }
+ return (*img->get)(img, raster, w, h);
+}
+
+/*
+ * Read the specified image into an ABGR-format rastertaking in account
+ * specified orientation.
+ */
+int
+TIFFReadRGBAImageOriented(TIFF* tif,
+ uint32 rwidth, uint32 rheight, uint32* raster,
+ int orientation, int stop)
+{
+ char emsg[1024] = "";
+ TIFFRGBAImage img;
+ int ok;
+
+ if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop, emsg)) {
+ img.req_orientation = orientation;
+ /* XXX verify rwidth and rheight against width and height */
+ ok = TIFFRGBAImageGet(&img, raster+(rheight-img.height)*rwidth,
+ rwidth, img.height);
+ TIFFRGBAImageEnd(&img);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
+ ok = 0;
+ }
+ return (ok);
+}
+
+/*
+ * Read the specified image into an ABGR-format raster. Use bottom left
+ * origin for raster by default.
+ */
+int
+TIFFReadRGBAImage(TIFF* tif,
+ uint32 rwidth, uint32 rheight, uint32* raster, int stop)
+{
+ return TIFFReadRGBAImageOriented(tif, rwidth, rheight, raster,
+ ORIENTATION_BOTLEFT, stop);
+}
+
+static int
+setorientation(TIFFRGBAImage* img)
+{
+ switch (img->orientation) {
+ case ORIENTATION_TOPLEFT:
+ case ORIENTATION_LEFTTOP:
+ if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTTOP)
+ return FLIP_HORIZONTALLY;
+ else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTBOT)
+ return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+ img->req_orientation == ORIENTATION_LEFTBOT)
+ return FLIP_VERTICALLY;
+ else
+ return 0;
+ case ORIENTATION_TOPRIGHT:
+ case ORIENTATION_RIGHTTOP:
+ if (img->req_orientation == ORIENTATION_TOPLEFT ||
+ img->req_orientation == ORIENTATION_LEFTTOP)
+ return FLIP_HORIZONTALLY;
+ else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTBOT)
+ return FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+ img->req_orientation == ORIENTATION_LEFTBOT)
+ return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+ else
+ return 0;
+ case ORIENTATION_BOTRIGHT:
+ case ORIENTATION_RIGHTBOT:
+ if (img->req_orientation == ORIENTATION_TOPLEFT ||
+ img->req_orientation == ORIENTATION_LEFTTOP)
+ return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTTOP)
+ return FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_BOTLEFT ||
+ img->req_orientation == ORIENTATION_LEFTBOT)
+ return FLIP_HORIZONTALLY;
+ else
+ return 0;
+ case ORIENTATION_BOTLEFT:
+ case ORIENTATION_LEFTBOT:
+ if (img->req_orientation == ORIENTATION_TOPLEFT ||
+ img->req_orientation == ORIENTATION_LEFTTOP)
+ return FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_TOPRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTTOP)
+ return FLIP_HORIZONTALLY | FLIP_VERTICALLY;
+ else if (img->req_orientation == ORIENTATION_BOTRIGHT ||
+ img->req_orientation == ORIENTATION_RIGHTBOT)
+ return FLIP_HORIZONTALLY;
+ else
+ return 0;
+ default: /* NOTREACHED */
+ return 0;
+ }
+}
+
+/*
+ * Get an tile-organized image that has
+ * PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ * SamplesPerPixel == 1
+ */
+static int
+gtTileContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ tileContigRoutine put = img->put.contig;
+ uint32 col, row, y, rowstoread;
+ uint32 pos;
+ uint32 tw, th;
+ unsigned char* buf;
+ int32 fromskew, toskew;
+ uint32 nrow;
+ int ret = 1, flip;
+
+ buf = (unsigned char*) _TIFFmalloc(TIFFTileSize(tif));
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ _TIFFmemset(buf, 0, TIFFTileSize(tif));
+ TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+ TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+
+ flip = setorientation(img);
+ if (flip & FLIP_VERTICALLY) {
+ y = h - 1;
+ toskew = -(int32)(tw + w);
+ }
+ else {
+ y = 0;
+ toskew = -(int32)(tw - w);
+ }
+
+ for (row = 0; row < h; row += nrow)
+ {
+ rowstoread = th - (row + img->row_offset) % th;
+ nrow = (row + rowstoread > h ? h - row : rowstoread);
+ for (col = 0; col < w; col += tw)
+ {
+ if (TIFFReadTile(tif, buf, col+img->col_offset,
+ row+img->row_offset, 0, 0) < 0 && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+
+ pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+
+ if (col + tw > w)
+ {
+ /*
+ * Tile is clipped horizontally. Calculate
+ * visible portion and skewing factors.
+ */
+ uint32 npix = w - col;
+ fromskew = tw - npix;
+ (*put)(img, raster+y*w+col, col, y,
+ npix, nrow, fromskew, toskew + fromskew, buf + pos);
+ }
+ else
+ {
+ (*put)(img, raster+y*w+col, col, y, tw, nrow, 0, toskew, buf + pos);
+ }
+ }
+
+ y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+ }
+ _TIFFfree(buf);
+
+ if (flip & FLIP_HORIZONTALLY) {
+ uint32 line;
+
+ for (line = 0; line < h; line++) {
+ uint32 *left = raster + (line * w);
+ uint32 *right = left + w - 1;
+
+ while ( left < right ) {
+ uint32 temp = *left;
+ *left = *right;
+ *right = temp;
+ left++, right--;
+ }
+ }
+ }
+
+ return (ret);
+}
+
+/*
+ * Get an tile-organized image that has
+ * SamplesPerPixel > 1
+ * PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */
+static int
+gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ tileSeparateRoutine put = img->put.separate;
+ uint32 col, row, y, rowstoread;
+ uint32 pos;
+ uint32 tw, th;
+ unsigned char* buf;
+ unsigned char* p0;
+ unsigned char* p1;
+ unsigned char* p2;
+ unsigned char* pa;
+ tsize_t tilesize;
+ int32 fromskew, toskew;
+ int alpha = img->alpha;
+ uint32 nrow;
+ int ret = 1, flip;
+
+ tilesize = TIFFTileSize(tif);
+ buf = (unsigned char*) _TIFFmalloc((alpha?4:3)*tilesize);
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ _TIFFmemset(buf, 0, (alpha?4:3)*tilesize);
+ p0 = buf;
+ p1 = p0 + tilesize;
+ p2 = p1 + tilesize;
+ pa = (alpha?(p2+tilesize):NULL);
+ TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tw);
+ TIFFGetField(tif, TIFFTAG_TILELENGTH, &th);
+
+ flip = setorientation(img);
+ if (flip & FLIP_VERTICALLY) {
+ y = h - 1;
+ toskew = -(int32)(tw + w);
+ }
+ else {
+ y = 0;
+ toskew = -(int32)(tw - w);
+ }
+
+ for (row = 0; row < h; row += nrow)
+ {
+ rowstoread = th - (row + img->row_offset) % th;
+ nrow = (row + rowstoread > h ? h - row : rowstoread);
+ for (col = 0; col < w; col += tw)
+ {
+ if (TIFFReadTile(tif, p0, col+img->col_offset,
+ row+img->row_offset,0,0) < 0 && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (TIFFReadTile(tif, p1, col+img->col_offset,
+ row+img->row_offset,0,1) < 0 && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (TIFFReadTile(tif, p2, col+img->col_offset,
+ row+img->row_offset,0,2) < 0 && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (alpha)
+ {
+ if (TIFFReadTile(tif,pa,col+img->col_offset,
+ row+img->row_offset,0,3) < 0 && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ }
+
+ pos = ((row+img->row_offset) % th) * TIFFTileRowSize(tif);
+
+ if (col + tw > w)
+ {
+ /*
+ * Tile is clipped horizontally. Calculate
+ * visible portion and skewing factors.
+ */
+ uint32 npix = w - col;
+ fromskew = tw - npix;
+ (*put)(img, raster+y*w+col, col, y,
+ npix, nrow, fromskew, toskew + fromskew,
+ p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+ } else {
+ (*put)(img, raster+y*w+col, col, y,
+ tw, nrow, 0, toskew, p0 + pos, p1 + pos, p2 + pos, (alpha?(pa+pos):NULL));
+ }
+ }
+
+ y += (flip & FLIP_VERTICALLY ?-(int32) nrow : (int32) nrow);
+ }
+
+ if (flip & FLIP_HORIZONTALLY) {
+ uint32 line;
+
+ for (line = 0; line < h; line++) {
+ uint32 *left = raster + (line * w);
+ uint32 *right = left + w - 1;
+
+ while ( left < right ) {
+ uint32 temp = *left;
+ *left = *right;
+ *right = temp;
+ left++, right--;
+ }
+ }
+ }
+
+ _TIFFfree(buf);
+ return (ret);
+}
+
+/*
+ * Get a strip-organized image that has
+ * PlanarConfiguration contiguous if SamplesPerPixel > 1
+ * or
+ * SamplesPerPixel == 1
+ */
+static int
+gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ tileContigRoutine put = img->put.contig;
+ uint32 row, y, nrow, nrowsub, rowstoread;
+ uint32 pos;
+ unsigned char* buf;
+ uint32 rowsperstrip;
+ uint16 subsamplinghor,subsamplingver;
+ uint32 imagewidth = img->width;
+ tsize_t scanline;
+ int32 fromskew, toskew;
+ int ret = 1, flip;
+
+ buf = (unsigned char*) _TIFFmalloc(TIFFStripSize(tif));
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
+ return (0);
+ }
+ _TIFFmemset(buf, 0, TIFFStripSize(tif));
+
+ flip = setorientation(img);
+ if (flip & FLIP_VERTICALLY) {
+ y = h - 1;
+ toskew = -(int32)(w + w);
+ } else {
+ y = 0;
+ toskew = -(int32)(w - w);
+ }
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, &subsamplinghor, &subsamplingver);
+ scanline = TIFFNewScanlineSize(tif);
+ fromskew = (w < imagewidth ? imagewidth - w : 0);
+ for (row = 0; row < h; row += nrow)
+ {
+ rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
+ nrow = (row + rowstoread > h ? h - row : rowstoread);
+ nrowsub = nrow;
+ if ((nrowsub%subsamplingver)!=0)
+ nrowsub+=subsamplingver-nrowsub%subsamplingver;
+ if (TIFFReadEncodedStrip(tif,
+ TIFFComputeStrip(tif,row+img->row_offset, 0),
+ buf,
+ ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+
+ pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+ (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, buf + pos);
+ y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+ }
+
+ if (flip & FLIP_HORIZONTALLY) {
+ uint32 line;
+
+ for (line = 0; line < h; line++) {
+ uint32 *left = raster + (line * w);
+ uint32 *right = left + w - 1;
+
+ while ( left < right ) {
+ uint32 temp = *left;
+ *left = *right;
+ *right = temp;
+ left++, right--;
+ }
+ }
+ }
+
+ _TIFFfree(buf);
+ return (ret);
+}
+
+/*
+ * Get a strip-organized image with
+ * SamplesPerPixel > 1
+ * PlanarConfiguration separated
+ * We assume that all such images are RGB.
+ */
+static int
+gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
+{
+ TIFF* tif = img->tif;
+ tileSeparateRoutine put = img->put.separate;
+ unsigned char *buf;
+ unsigned char *p0, *p1, *p2, *pa;
+ uint32 row, y, nrow, rowstoread;
+ uint32 pos;
+ tsize_t scanline;
+ uint32 rowsperstrip, offset_row;
+ uint32 imagewidth = img->width;
+ tsize_t stripsize;
+ int32 fromskew, toskew;
+ int alpha = img->alpha;
+ int ret = 1, flip;
+
+ stripsize = TIFFStripSize(tif);
+ p0 = buf = (unsigned char *)_TIFFmalloc((alpha?4:3)*stripsize);
+ if (buf == 0) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for tile buffer");
+ return (0);
+ }
+ _TIFFmemset(buf, 0, (alpha?4:3)*stripsize);
+ p1 = p0 + stripsize;
+ p2 = p1 + stripsize;
+ pa = (alpha?(p2+stripsize):NULL);
+
+ flip = setorientation(img);
+ if (flip & FLIP_VERTICALLY) {
+ y = h - 1;
+ toskew = -(int32)(w + w);
+ }
+ else {
+ y = 0;
+ toskew = -(int32)(w - w);
+ }
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ scanline = TIFFScanlineSize(tif);
+ fromskew = (w < imagewidth ? imagewidth - w : 0);
+ for (row = 0; row < h; row += nrow)
+ {
+ rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
+ nrow = (row + rowstoread > h ? h - row : rowstoread);
+ offset_row = row + img->row_offset;
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
+ p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
+ p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
+ p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ if (alpha)
+ {
+ if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 3),
+ pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) < 0
+ && img->stoponerr)
+ {
+ ret = 0;
+ break;
+ }
+ }
+
+ pos = ((row + img->row_offset) % rowsperstrip) * scanline;
+ (*put)(img, raster+y*w, 0, y, w, nrow, fromskew, toskew, p0 + pos, p1 + pos,
+ p2 + pos, (alpha?(pa+pos):NULL));
+ y += (flip & FLIP_VERTICALLY ? -(int32) nrow : (int32) nrow);
+ }
+
+ if (flip & FLIP_HORIZONTALLY) {
+ uint32 line;
+
+ for (line = 0; line < h; line++) {
+ uint32 *left = raster + (line * w);
+ uint32 *right = left + w - 1;
+
+ while ( left < right ) {
+ uint32 temp = *left;
+ *left = *right;
+ *right = temp;
+ left++, right--;
+ }
+ }
+ }
+
+ _TIFFfree(buf);
+ return (ret);
+}
+
+/*
+ * The following routines move decoded data returned
+ * from the TIFF library into rasters filled with packed
+ * ABGR pixels (i.e. suitable for passing to lrecwrite.)
+ *
+ * The routines have been created according to the most
+ * important cases and optimized. PickContigCase and
+ * PickSeparateCase analyze the parameters and select
+ * the appropriate "get" and "put" routine to use.
+ */
+#define REPEAT8(op) REPEAT4(op); REPEAT4(op)
+#define REPEAT4(op) REPEAT2(op); REPEAT2(op)
+#define REPEAT2(op) op; op
+#define CASE8(x,op) \
+ switch (x) { \
+ case 7: op; case 6: op; case 5: op; \
+ case 4: op; case 3: op; case 2: op; \
+ case 1: op; \
+ }
+#define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; }
+#define NOP
+
+#define UNROLL8(w, op1, op2) { \
+ uint32 _x; \
+ for (_x = w; _x >= 8; _x -= 8) { \
+ op1; \
+ REPEAT8(op2); \
+ } \
+ if (_x > 0) { \
+ op1; \
+ CASE8(_x,op2); \
+ } \
+}
+#define UNROLL4(w, op1, op2) { \
+ uint32 _x; \
+ for (_x = w; _x >= 4; _x -= 4) { \
+ op1; \
+ REPEAT4(op2); \
+ } \
+ if (_x > 0) { \
+ op1; \
+ CASE4(_x,op2); \
+ } \
+}
+#define UNROLL2(w, op1, op2) { \
+ uint32 _x; \
+ for (_x = w; _x >= 2; _x -= 2) { \
+ op1; \
+ REPEAT2(op2); \
+ } \
+ if (_x) { \
+ op1; \
+ op2; \
+ } \
+}
+
+#define SKEW(r,g,b,skew) { r += skew; g += skew; b += skew; }
+#define SKEW4(r,g,b,a,skew) { r += skew; g += skew; b += skew; a+= skew; }
+
+#define A1 (((uint32)0xffL)<<24)
+#define PACK(r,g,b) \
+ ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|A1)
+#define PACK4(r,g,b,a) \
+ ((uint32)(r)|((uint32)(g)<<8)|((uint32)(b)<<16)|((uint32)(a)<<24))
+#define W2B(v) (((v)>>8)&0xff)
+#define PACKW(r,g,b) \
+ ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|A1)
+#define PACKW4(r,g,b,a) \
+ ((uint32)W2B(r)|((uint32)W2B(g)<<8)|((uint32)W2B(b)<<16)|((uint32)W2B(a)<<24))
+
+#define DECLAREContigPutFunc(name) \
+static void name(\
+ TIFFRGBAImage* img, \
+ uint32* cp, \
+ uint32 x, uint32 y, \
+ uint32 w, uint32 h, \
+ int32 fromskew, int32 toskew, \
+ unsigned char* pp \
+)
+
+/*
+ * 8-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put8bitcmaptile)
+{
+ uint32** PALmap = img->PALmap;
+ int samplesperpixel = img->samplesperpixel;
+
+ (void) y;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;)
+ {
+ *cp++ = PALmap[*pp][0];
+ pp += samplesperpixel;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 4-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put4bitcmaptile)
+{
+ uint32** PALmap = img->PALmap;
+
+ (void) x; (void) y;
+ fromskew /= 2;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL2(w, bw = PALmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 2-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put2bitcmaptile)
+{
+ uint32** PALmap = img->PALmap;
+
+ (void) x; (void) y;
+ fromskew /= 4;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL4(w, bw = PALmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 1-bit palette => colormap/RGB
+ */
+DECLAREContigPutFunc(put1bitcmaptile)
+{
+ uint32** PALmap = img->PALmap;
+
+ (void) x; (void) y;
+ fromskew /= 8;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL8(w, bw = PALmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 8-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(putgreytile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint32** BWmap = img->BWmap;
+
+ (void) y;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;)
+ {
+ *cp++ = BWmap[*pp][0];
+ pp += samplesperpixel;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 16-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put16bitbwtile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint32** BWmap = img->BWmap;
+
+ (void) y;
+ while (h-- > 0) {
+ uint16 *wp = (uint16 *) pp;
+
+ for (x = w; x-- > 0;)
+ {
+ /* use high order byte of 16bit value */
+
+ *cp++ = BWmap[*wp >> 8][0];
+ pp += 2 * samplesperpixel;
+ wp += samplesperpixel;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 1-bit bilevel => colormap/RGB
+ */
+DECLAREContigPutFunc(put1bitbwtile)
+{
+ uint32** BWmap = img->BWmap;
+
+ (void) x; (void) y;
+ fromskew /= 8;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL8(w, bw = BWmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 2-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put2bitbwtile)
+{
+ uint32** BWmap = img->BWmap;
+
+ (void) x; (void) y;
+ fromskew /= 4;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL4(w, bw = BWmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 4-bit greyscale => colormap/RGB
+ */
+DECLAREContigPutFunc(put4bitbwtile)
+{
+ uint32** BWmap = img->BWmap;
+
+ (void) x; (void) y;
+ fromskew /= 2;
+ while (h-- > 0) {
+ uint32* bw;
+ UNROLL2(w, bw = BWmap[*pp++], *cp++ = *bw++);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 8-bit packed samples, no Map => RGB
+ */
+DECLAREContigPutFunc(putRGBcontig8bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+
+ (void) x; (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ UNROLL8(w, NOP,
+ *cp++ = PACK(pp[0], pp[1], pp[2]);
+ pp += samplesperpixel);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 8-bit packed samples => RGBA w/ associated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBAAcontig8bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+
+ (void) x; (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ UNROLL8(w, NOP,
+ *cp++ = PACK4(pp[0], pp[1], pp[2], pp[3]);
+ pp += samplesperpixel);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 8-bit packed samples => RGBA w/ unassociated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBUAcontig8bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ uint32 r, g, b, a;
+ for (x = w; x-- > 0;) {
+ a = pp[3];
+ r = (a*pp[0] + 127) / 255;
+ g = (a*pp[1] + 127) / 255;
+ b = (a*pp[2] + 127) / 255;
+ *cp++ = PACK4(r,g,b,a);
+ pp += samplesperpixel;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 16-bit packed samples => RGB
+ */
+DECLAREContigPutFunc(putRGBcontig16bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint16 *wp = (uint16 *)pp;
+ (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;) {
+ *cp++ = PACKW(wp[0],wp[1],wp[2]);
+ wp += samplesperpixel;
+ }
+ cp += toskew;
+ wp += fromskew;
+ }
+}
+
+/*
+ * 16-bit packed samples => RGBA w/ associated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBAAcontig16bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint16 *wp = (uint16 *)pp;
+ (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;) {
+ *cp++ = PACKW4(wp[0],wp[1],wp[2],wp[3]);
+ wp += samplesperpixel;
+ }
+ cp += toskew;
+ wp += fromskew;
+ }
+}
+
+/*
+ * 16-bit packed samples => RGBA w/ unassociated alpha
+ * (known to have Map == NULL)
+ */
+DECLAREContigPutFunc(putRGBUAcontig16bittile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint16 *wp = (uint16 *)pp;
+ (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ uint32 r,g,b,a;
+ for (x = w; x-- > 0;) {
+ a = W2B(wp[3]);
+ r = (a*W2B(wp[0]) + 127) / 255;
+ g = (a*W2B(wp[1]) + 127) / 255;
+ b = (a*W2B(wp[2]) + 127) / 255;
+ *cp++ = PACK4(r,g,b,a);
+ wp += samplesperpixel;
+ }
+ cp += toskew;
+ wp += fromskew;
+ }
+}
+
+/*
+ * 8-bit packed CMYK samples w/o Map => RGB
+ *
+ * NB: The conversion of CMYK->RGB is *very* crude.
+ */
+DECLAREContigPutFunc(putRGBcontig8bitCMYKtile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ uint16 r, g, b, k;
+
+ (void) x; (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ UNROLL8(w, NOP,
+ k = 255 - pp[3];
+ r = (k*(255-pp[0]))/255;
+ g = (k*(255-pp[1]))/255;
+ b = (k*(255-pp[2]))/255;
+ *cp++ = PACK(r, g, b);
+ pp += samplesperpixel);
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * 8-bit packed CMYK samples w/Map => RGB
+ *
+ * NB: The conversion of CMYK->RGB is *very* crude.
+ */
+DECLAREContigPutFunc(putRGBcontig8bitCMYKMaptile)
+{
+ int samplesperpixel = img->samplesperpixel;
+ TIFFRGBValue* Map = img->Map;
+ uint16 r, g, b, k;
+
+ (void) y;
+ fromskew *= samplesperpixel;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;) {
+ k = 255 - pp[3];
+ r = (k*(255-pp[0]))/255;
+ g = (k*(255-pp[1]))/255;
+ b = (k*(255-pp[2]))/255;
+ *cp++ = PACK(Map[r], Map[g], Map[b]);
+ pp += samplesperpixel;
+ }
+ pp += fromskew;
+ cp += toskew;
+ }
+}
+
+#define DECLARESepPutFunc(name) \
+static void name(\
+ TIFFRGBAImage* img,\
+ uint32* cp,\
+ uint32 x, uint32 y, \
+ uint32 w, uint32 h,\
+ int32 fromskew, int32 toskew,\
+ unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a\
+)
+
+/*
+ * 8-bit unpacked samples => RGB
+ */
+DECLARESepPutFunc(putRGBseparate8bittile)
+{
+ (void) img; (void) x; (void) y; (void) a;
+ while (h-- > 0) {
+ UNROLL8(w, NOP, *cp++ = PACK(*r++, *g++, *b++));
+ SKEW(r, g, b, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 8-bit unpacked samples => RGBA w/ associated alpha
+ */
+DECLARESepPutFunc(putRGBAAseparate8bittile)
+{
+ (void) img; (void) x; (void) y;
+ while (h-- > 0) {
+ UNROLL8(w, NOP, *cp++ = PACK4(*r++, *g++, *b++, *a++));
+ SKEW4(r, g, b, a, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 8-bit unpacked samples => RGBA w/ unassociated alpha
+ */
+DECLARESepPutFunc(putRGBUAseparate8bittile)
+{
+ (void) img; (void) y;
+ while (h-- > 0) {
+ uint32 rv, gv, bv, av;
+ for (x = w; x-- > 0;) {
+ av = *a++;
+ rv = (av* *r++ + 127) / 255;
+ gv = (av* *g++ + 127) / 255;
+ bv = (av* *b++ + 127) / 255;
+ *cp++ = PACK4(rv,gv,bv,av);
+ }
+ SKEW4(r, g, b, a, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 16-bit unpacked samples => RGB
+ */
+DECLARESepPutFunc(putRGBseparate16bittile)
+{
+ uint16 *wr = (uint16*) r;
+ uint16 *wg = (uint16*) g;
+ uint16 *wb = (uint16*) b;
+ (void) img; (void) y; (void) a;
+ while (h-- > 0) {
+ for (x = 0; x < w; x++)
+ *cp++ = PACKW(*wr++,*wg++,*wb++);
+ SKEW(wr, wg, wb, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 16-bit unpacked samples => RGBA w/ associated alpha
+ */
+DECLARESepPutFunc(putRGBAAseparate16bittile)
+{
+ uint16 *wr = (uint16*) r;
+ uint16 *wg = (uint16*) g;
+ uint16 *wb = (uint16*) b;
+ uint16 *wa = (uint16*) a;
+ (void) img; (void) y;
+ while (h-- > 0) {
+ for (x = 0; x < w; x++)
+ *cp++ = PACKW4(*wr++,*wg++,*wb++,*wa++);
+ SKEW4(wr, wg, wb, wa, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 16-bit unpacked samples => RGBA w/ unassociated alpha
+ */
+DECLARESepPutFunc(putRGBUAseparate16bittile)
+{
+ uint16 *wr = (uint16*) r;
+ uint16 *wg = (uint16*) g;
+ uint16 *wb = (uint16*) b;
+ uint16 *wa = (uint16*) a;
+ (void) img; (void) y;
+ while (h-- > 0) {
+ uint32 r,g,b,a;
+ for (x = w; x-- > 0;) {
+ a = W2B(*wa++);
+ r = (a*W2B(*wr++) + 127) / 255;
+ g = (a*W2B(*wg++) + 127) / 255;
+ b = (a*W2B(*wb++) + 127) / 255;
+ *cp++ = PACK4(r,g,b,a);
+ }
+ SKEW4(wr, wg, wb, wa, fromskew);
+ cp += toskew;
+ }
+}
+
+/*
+ * 8-bit packed CIE L*a*b 1976 samples => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitCIELab)
+{
+ float X, Y, Z;
+ uint32 r, g, b;
+ (void) y;
+ fromskew *= 3;
+ while (h-- > 0) {
+ for (x = w; x-- > 0;) {
+ TIFFCIELabToXYZ(img->cielab,
+ (unsigned char)pp[0],
+ (signed char)pp[1],
+ (signed char)pp[2],
+ &X, &Y, &Z);
+ TIFFXYZToRGB(img->cielab, X, Y, Z, &r, &g, &b);
+ *cp++ = PACK(r, g, b);
+ pp += 3;
+ }
+ cp += toskew;
+ pp += fromskew;
+ }
+}
+
+/*
+ * YCbCr -> RGB conversion and packing routines.
+ */
+
+#define YCbCrtoRGB(dst, Y) { \
+ uint32 r, g, b; \
+ TIFFYCbCrtoRGB(img->ycbcr, (Y), Cb, Cr, &r, &g, &b); \
+ dst = PACK(r, g, b); \
+}
+
+/*
+ * 8-bit packed YCbCr samples => RGB
+ * This function is generic for different sampling sizes,
+ * and can handle blocks sizes that aren't multiples of the
+ * sampling size. However, it is substantially less optimized
+ * than the specific sampling cases. It is used as a fallback
+ * for difficult blocks.
+ */
+#ifdef notdef
+static void putcontig8bitYCbCrGenericTile(
+ TIFFRGBAImage* img,
+ uint32* cp,
+ uint32 x, uint32 y,
+ uint32 w, uint32 h,
+ int32 fromskew, int32 toskew,
+ unsigned char* pp,
+ int h_group,
+ int v_group )
+
+{
+ uint32* cp1 = cp+w+toskew;
+ uint32* cp2 = cp1+w+toskew;
+ uint32* cp3 = cp2+w+toskew;
+ int32 incr = 3*w+4*toskew;
+ int32 Cb, Cr;
+ int group_size = v_group * h_group + 2;
+
+ (void) y;
+ fromskew = (fromskew * group_size) / h_group;
+
+ for( yy = 0; yy < h; yy++ )
+ {
+ unsigned char *pp_line;
+ int y_line_group = yy / v_group;
+ int y_remainder = yy - y_line_group * v_group;
+
+ pp_line = pp + v_line_group *
+
+
+ for( xx = 0; xx < w; xx++ )
+ {
+ Cb = pp
+ }
+ }
+ for (; h >= 4; h -= 4) {
+ x = w>>2;
+ do {
+ Cb = pp[16];
+ Cr = pp[17];
+
+ YCbCrtoRGB(cp [0], pp[ 0]);
+ YCbCrtoRGB(cp [1], pp[ 1]);
+ YCbCrtoRGB(cp [2], pp[ 2]);
+ YCbCrtoRGB(cp [3], pp[ 3]);
+ YCbCrtoRGB(cp1[0], pp[ 4]);
+ YCbCrtoRGB(cp1[1], pp[ 5]);
+ YCbCrtoRGB(cp1[2], pp[ 6]);
+ YCbCrtoRGB(cp1[3], pp[ 7]);
+ YCbCrtoRGB(cp2[0], pp[ 8]);
+ YCbCrtoRGB(cp2[1], pp[ 9]);
+ YCbCrtoRGB(cp2[2], pp[10]);
+ YCbCrtoRGB(cp2[3], pp[11]);
+ YCbCrtoRGB(cp3[0], pp[12]);
+ YCbCrtoRGB(cp3[1], pp[13]);
+ YCbCrtoRGB(cp3[2], pp[14]);
+ YCbCrtoRGB(cp3[3], pp[15]);
+
+ cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
+ pp += 18;
+ } while (--x);
+ cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+ pp += fromskew;
+ }
+}
+#endif
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,4 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr44tile)
+{
+ uint32* cp1 = cp+w+toskew;
+ uint32* cp2 = cp1+w+toskew;
+ uint32* cp3 = cp2+w+toskew;
+ int32 incr = 3*w+4*toskew;
+
+ (void) y;
+ /* adjust fromskew */
+ fromskew = (fromskew * 18) / 4;
+ if ((h & 3) == 0 && (w & 3) == 0) {
+ for (; h >= 4; h -= 4) {
+ x = w>>2;
+ do {
+ int32 Cb = pp[16];
+ int32 Cr = pp[17];
+
+ YCbCrtoRGB(cp [0], pp[ 0]);
+ YCbCrtoRGB(cp [1], pp[ 1]);
+ YCbCrtoRGB(cp [2], pp[ 2]);
+ YCbCrtoRGB(cp [3], pp[ 3]);
+ YCbCrtoRGB(cp1[0], pp[ 4]);
+ YCbCrtoRGB(cp1[1], pp[ 5]);
+ YCbCrtoRGB(cp1[2], pp[ 6]);
+ YCbCrtoRGB(cp1[3], pp[ 7]);
+ YCbCrtoRGB(cp2[0], pp[ 8]);
+ YCbCrtoRGB(cp2[1], pp[ 9]);
+ YCbCrtoRGB(cp2[2], pp[10]);
+ YCbCrtoRGB(cp2[3], pp[11]);
+ YCbCrtoRGB(cp3[0], pp[12]);
+ YCbCrtoRGB(cp3[1], pp[13]);
+ YCbCrtoRGB(cp3[2], pp[14]);
+ YCbCrtoRGB(cp3[3], pp[15]);
+
+ cp += 4, cp1 += 4, cp2 += 4, cp3 += 4;
+ pp += 18;
+ } while (--x);
+ cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+ pp += fromskew;
+ }
+ } else {
+ while (h > 0) {
+ for (x = w; x > 0;) {
+ int32 Cb = pp[16];
+ int32 Cr = pp[17];
+ switch (x) {
+ default:
+ switch (h) {
+ default: YCbCrtoRGB(cp3[3], pp[15]); /* FALLTHROUGH */
+ case 3: YCbCrtoRGB(cp2[3], pp[11]); /* FALLTHROUGH */
+ case 2: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 3:
+ switch (h) {
+ default: YCbCrtoRGB(cp3[2], pp[14]); /* FALLTHROUGH */
+ case 3: YCbCrtoRGB(cp2[2], pp[10]); /* FALLTHROUGH */
+ case 2: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 2:
+ switch (h) {
+ default: YCbCrtoRGB(cp3[1], pp[13]); /* FALLTHROUGH */
+ case 3: YCbCrtoRGB(cp2[1], pp[ 9]); /* FALLTHROUGH */
+ case 2: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 1:
+ switch (h) {
+ default: YCbCrtoRGB(cp3[0], pp[12]); /* FALLTHROUGH */
+ case 3: YCbCrtoRGB(cp2[0], pp[ 8]); /* FALLTHROUGH */
+ case 2: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ }
+ if (x < 4) {
+ cp += x; cp1 += x; cp2 += x; cp3 += x;
+ x = 0;
+ }
+ else {
+ cp += 4; cp1 += 4; cp2 += 4; cp3 += 4;
+ x -= 4;
+ }
+ pp += 18;
+ }
+ if (h <= 4)
+ break;
+ h -= 4;
+ cp += incr, cp1 += incr, cp2 += incr, cp3 += incr;
+ pp += fromskew;
+ }
+ }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,2 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr42tile)
+{
+ uint32* cp1 = cp+w+toskew;
+ int32 incr = 2*toskew+w;
+
+ (void) y;
+ fromskew = (fromskew * 10) / 4;
+ if ((h & 3) == 0 && (w & 1) == 0) {
+ for (; h >= 2; h -= 2) {
+ x = w>>2;
+ do {
+ int32 Cb = pp[8];
+ int32 Cr = pp[9];
+
+ YCbCrtoRGB(cp [0], pp[0]);
+ YCbCrtoRGB(cp [1], pp[1]);
+ YCbCrtoRGB(cp [2], pp[2]);
+ YCbCrtoRGB(cp [3], pp[3]);
+ YCbCrtoRGB(cp1[0], pp[4]);
+ YCbCrtoRGB(cp1[1], pp[5]);
+ YCbCrtoRGB(cp1[2], pp[6]);
+ YCbCrtoRGB(cp1[3], pp[7]);
+
+ cp += 4, cp1 += 4;
+ pp += 10;
+ } while (--x);
+ cp += incr, cp1 += incr;
+ pp += fromskew;
+ }
+ } else {
+ while (h > 0) {
+ for (x = w; x > 0;) {
+ int32 Cb = pp[8];
+ int32 Cr = pp[9];
+ switch (x) {
+ default:
+ switch (h) {
+ default: YCbCrtoRGB(cp1[3], pp[ 7]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [3], pp[ 3]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 3:
+ switch (h) {
+ default: YCbCrtoRGB(cp1[2], pp[ 6]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [2], pp[ 2]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 2:
+ switch (h) {
+ default: YCbCrtoRGB(cp1[1], pp[ 5]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [1], pp[ 1]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ case 1:
+ switch (h) {
+ default: YCbCrtoRGB(cp1[0], pp[ 4]); /* FALLTHROUGH */
+ case 1: YCbCrtoRGB(cp [0], pp[ 0]); /* FALLTHROUGH */
+ } /* FALLTHROUGH */
+ }
+ if (x < 4) {
+ cp += x; cp1 += x;
+ x = 0;
+ }
+ else {
+ cp += 4; cp1 += 4;
+ x -= 4;
+ }
+ pp += 10;
+ }
+ if (h <= 2)
+ break;
+ h -= 2;
+ cp += incr, cp1 += incr;
+ pp += fromskew;
+ }
+ }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 4,1 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr41tile)
+{
+ (void) y;
+ /* XXX adjust fromskew */
+ do {
+ x = w>>2;
+ do {
+ int32 Cb = pp[4];
+ int32 Cr = pp[5];
+
+ YCbCrtoRGB(cp [0], pp[0]);
+ YCbCrtoRGB(cp [1], pp[1]);
+ YCbCrtoRGB(cp [2], pp[2]);
+ YCbCrtoRGB(cp [3], pp[3]);
+
+ cp += 4;
+ pp += 6;
+ } while (--x);
+
+ if( (w&3) != 0 )
+ {
+ int32 Cb = pp[4];
+ int32 Cr = pp[5];
+
+ switch( (w&3) ) {
+ case 3: YCbCrtoRGB(cp [2], pp[2]);
+ case 2: YCbCrtoRGB(cp [1], pp[1]);
+ case 1: YCbCrtoRGB(cp [0], pp[0]);
+ case 0: break;
+ }
+
+ cp += (w&3);
+ pp += 6;
+ }
+
+ cp += toskew;
+ pp += fromskew;
+ } while (--h);
+
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 2,2 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr22tile)
+{
+ uint32* cp2;
+ (void) y;
+ fromskew = (fromskew / 2) * 6;
+ cp2 = cp+w+toskew;
+ while (h>=2) {
+ x = w;
+ while (x>=2) {
+ uint32 Cb = pp[4];
+ uint32 Cr = pp[5];
+ YCbCrtoRGB(cp[0], pp[0]);
+ YCbCrtoRGB(cp[1], pp[1]);
+ YCbCrtoRGB(cp2[0], pp[2]);
+ YCbCrtoRGB(cp2[1], pp[3]);
+ cp += 2;
+ cp2 += 2;
+ pp += 6;
+ x -= 2;
+ }
+ if (x==1) {
+ uint32 Cb = pp[4];
+ uint32 Cr = pp[5];
+ YCbCrtoRGB(cp[0], pp[0]);
+ YCbCrtoRGB(cp2[0], pp[2]);
+ cp ++ ;
+ cp2 ++ ;
+ pp += 6;
+ }
+ cp += toskew*2+w;
+ cp2 += toskew*2+w;
+ pp += fromskew;
+ h-=2;
+ }
+ if (h==1) {
+ x = w;
+ while (x>=2) {
+ uint32 Cb = pp[4];
+ uint32 Cr = pp[5];
+ YCbCrtoRGB(cp[0], pp[0]);
+ YCbCrtoRGB(cp[1], pp[1]);
+ cp += 2;
+ cp2 += 2;
+ pp += 6;
+ x -= 2;
+ }
+ if (x==1) {
+ uint32 Cb = pp[4];
+ uint32 Cr = pp[5];
+ YCbCrtoRGB(cp[0], pp[0]);
+ }
+ }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 2,1 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr21tile)
+{
+ (void) y;
+ fromskew = (fromskew * 4) / 2;
+ do {
+ x = w>>1;
+ do {
+ int32 Cb = pp[2];
+ int32 Cr = pp[3];
+
+ YCbCrtoRGB(cp[0], pp[0]);
+ YCbCrtoRGB(cp[1], pp[1]);
+
+ cp += 2;
+ pp += 4;
+ } while (--x);
+
+ if( (w&1) != 0 )
+ {
+ int32 Cb = pp[2];
+ int32 Cr = pp[3];
+
+ YCbCrtoRGB(cp[0], pp[0]);
+
+ cp += 1;
+ pp += 4;
+ }
+
+ cp += toskew;
+ pp += fromskew;
+ } while (--h);
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ 1,2 subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr12tile)
+{
+ uint32* cp2;
+ (void) y;
+ fromskew = (fromskew / 2) * 4;
+ cp2 = cp+w+toskew;
+ while (h>=2) {
+ x = w;
+ do {
+ uint32 Cb = pp[2];
+ uint32 Cr = pp[3];
+ YCbCrtoRGB(cp[0], pp[0]);
+ YCbCrtoRGB(cp2[0], pp[1]);
+ cp ++;
+ cp2 ++;
+ pp += 4;
+ } while (--x);
+ cp += toskew*2+w;
+ cp2 += toskew*2+w;
+ pp += fromskew;
+ h-=2;
+ }
+ if (h==1) {
+ x = w;
+ do {
+ uint32 Cb = pp[2];
+ uint32 Cr = pp[3];
+ YCbCrtoRGB(cp[0], pp[0]);
+ cp ++;
+ pp += 4;
+ } while (--x);
+ }
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ no subsampling => RGB
+ */
+DECLAREContigPutFunc(putcontig8bitYCbCr11tile)
+{
+ (void) y;
+ fromskew *= 3;
+ do {
+ x = w; /* was x = w>>1; patched 2000/09/25 warmerda@home.com */
+ do {
+ int32 Cb = pp[1];
+ int32 Cr = pp[2];
+
+ YCbCrtoRGB(*cp++, pp[0]);
+
+ pp += 3;
+ } while (--x);
+ cp += toskew;
+ pp += fromskew;
+ } while (--h);
+}
+
+/*
+ * 8-bit packed YCbCr samples w/ no subsampling => RGB
+ */
+DECLARESepPutFunc(putseparate8bitYCbCr11tile)
+{
+ (void) y;
+ (void) a;
+ /* TODO: naming of input vars is still off, change obfuscating declaration inside define, or resolve obfuscation */
+ while (h-- > 0) {
+ x = w;
+ do {
+ uint32 dr, dg, db;
+ TIFFYCbCrtoRGB(img->ycbcr,*r++,*g++,*b++,&dr,&dg,&db);
+ *cp++ = PACK(dr,dg,db);
+ } while (--x);
+ SKEW(r, g, b, fromskew);
+ cp += toskew;
+ }
+}
+#undef YCbCrtoRGB
+
+static int
+initYCbCrConversion(TIFFRGBAImage* img)
+{
+ static char module[] = "initYCbCrConversion";
+
+ float *luma, *refBlackWhite;
+
+ if (img->ycbcr == NULL) {
+ img->ycbcr = (TIFFYCbCrToRGB*) _TIFFmalloc(
+ TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))
+ + 4*256*sizeof (TIFFRGBValue)
+ + 2*256*sizeof (int)
+ + 3*256*sizeof (int32)
+ );
+ if (img->ycbcr == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, module,
+ "No space for YCbCr->RGB conversion state");
+ return (0);
+ }
+ }
+
+ TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRCOEFFICIENTS, &luma);
+ TIFFGetFieldDefaulted(img->tif, TIFFTAG_REFERENCEBLACKWHITE,
+ &refBlackWhite);
+ if (TIFFYCbCrToRGBInit(img->ycbcr, luma, refBlackWhite) < 0)
+ return(0);
+ return (1);
+}
+
+static tileContigRoutine
+initCIELabConversion(TIFFRGBAImage* img)
+{
+ static char module[] = "initCIELabConversion";
+
+ float *whitePoint;
+ float refWhite[3];
+
+ if (!img->cielab) {
+ img->cielab = (TIFFCIELabToRGB *)
+ _TIFFmalloc(sizeof(TIFFCIELabToRGB));
+ if (!img->cielab) {
+ TIFFErrorExt(img->tif->tif_clientdata, module,
+ "No space for CIE L*a*b*->RGB conversion state.");
+ return NULL;
+ }
+ }
+
+ TIFFGetFieldDefaulted(img->tif, TIFFTAG_WHITEPOINT, &whitePoint);
+ refWhite[1] = 100.0F;
+ refWhite[0] = whitePoint[0] / whitePoint[1] * refWhite[1];
+ refWhite[2] = (1.0F - whitePoint[0] - whitePoint[1])
+ / whitePoint[1] * refWhite[1];
+ if (TIFFCIELabToRGBInit(img->cielab, &display_sRGB, refWhite) < 0) {
+ TIFFErrorExt(img->tif->tif_clientdata, module,
+ "Failed to initialize CIE L*a*b*->RGB conversion state.");
+ _TIFFfree(img->cielab);
+ return NULL;
+ }
+
+ return putcontig8bitCIELab;
+}
+
+/*
+ * Greyscale images with less than 8 bits/sample are handled
+ * with a table to avoid lots of shifts and masks. The table
+ * is setup so that put*bwtile (below) can retrieve 8/bitspersample
+ * pixel values simply by indexing into the table with one
+ * number.
+ */
+static int
+makebwmap(TIFFRGBAImage* img)
+{
+ TIFFRGBValue* Map = img->Map;
+ int bitspersample = img->bitspersample;
+ int nsamples = 8 / bitspersample;
+ int i;
+ uint32* p;
+
+ if( nsamples == 0 )
+ nsamples = 1;
+
+ img->BWmap = (uint32**) _TIFFmalloc(
+ 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
+ if (img->BWmap == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for B&W mapping table");
+ return (0);
+ }
+ p = (uint32*)(img->BWmap + 256);
+ for (i = 0; i < 256; i++) {
+ TIFFRGBValue c;
+ img->BWmap[i] = p;
+ switch (bitspersample) {
+#define GREY(x) c = Map[x]; *p++ = PACK(c,c,c);
+ case 1:
+ GREY(i>>7);
+ GREY((i>>6)&1);
+ GREY((i>>5)&1);
+ GREY((i>>4)&1);
+ GREY((i>>3)&1);
+ GREY((i>>2)&1);
+ GREY((i>>1)&1);
+ GREY(i&1);
+ break;
+ case 2:
+ GREY(i>>6);
+ GREY((i>>4)&3);
+ GREY((i>>2)&3);
+ GREY(i&3);
+ break;
+ case 4:
+ GREY(i>>4);
+ GREY(i&0xf);
+ break;
+ case 8:
+ case 16:
+ GREY(i);
+ break;
+ }
+#undef GREY
+ }
+ return (1);
+}
+
+/*
+ * Construct a mapping table to convert from the range
+ * of the data samples to [0,255] --for display. This
+ * process also handles inverting B&W images when needed.
+ */
+static int
+setupMap(TIFFRGBAImage* img)
+{
+ int32 x, range;
+
+ range = (int32)((1L<<img->bitspersample)-1);
+
+ /* treat 16 bit the same as eight bit */
+ if( img->bitspersample == 16 )
+ range = (int32) 255;
+
+ img->Map = (TIFFRGBValue*) _TIFFmalloc((range+1) * sizeof (TIFFRGBValue));
+ if (img->Map == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif),
+ "No space for photometric conversion table");
+ return (0);
+ }
+ if (img->photometric == PHOTOMETRIC_MINISWHITE) {
+ for (x = 0; x <= range; x++)
+ img->Map[x] = (TIFFRGBValue) (((range - x) * 255) / range);
+ } else {
+ for (x = 0; x <= range; x++)
+ img->Map[x] = (TIFFRGBValue) ((x * 255) / range);
+ }
+ if (img->bitspersample <= 16 &&
+ (img->photometric == PHOTOMETRIC_MINISBLACK ||
+ img->photometric == PHOTOMETRIC_MINISWHITE)) {
+ /*
+ * Use photometric mapping table to construct
+ * unpacking tables for samples <= 8 bits.
+ */
+ if (!makebwmap(img))
+ return (0);
+ /* no longer need Map, free it */
+ _TIFFfree(img->Map), img->Map = NULL;
+ }
+ return (1);
+}
+
+static int
+checkcmap(TIFFRGBAImage* img)
+{
+ uint16* r = img->redcmap;
+ uint16* g = img->greencmap;
+ uint16* b = img->bluecmap;
+ long n = 1L<<img->bitspersample;
+
+ while (n-- > 0)
+ if (*r++ >= 256 || *g++ >= 256 || *b++ >= 256)
+ return (16);
+ return (8);
+}
+
+static void
+cvtcmap(TIFFRGBAImage* img)
+{
+ uint16* r = img->redcmap;
+ uint16* g = img->greencmap;
+ uint16* b = img->bluecmap;
+ long i;
+
+ for (i = (1L<<img->bitspersample)-1; i >= 0; i--) {
+#define CVT(x) ((uint16)((x)>>8))
+ r[i] = CVT(r[i]);
+ g[i] = CVT(g[i]);
+ b[i] = CVT(b[i]);
+#undef CVT
+ }
+}
+
+/*
+ * Palette images with <= 8 bits/sample are handled
+ * with a table to avoid lots of shifts and masks. The table
+ * is setup so that put*cmaptile (below) can retrieve 8/bitspersample
+ * pixel values simply by indexing into the table with one
+ * number.
+ */
+static int
+makecmap(TIFFRGBAImage* img)
+{
+ int bitspersample = img->bitspersample;
+ int nsamples = 8 / bitspersample;
+ uint16* r = img->redcmap;
+ uint16* g = img->greencmap;
+ uint16* b = img->bluecmap;
+ uint32 *p;
+ int i;
+
+ img->PALmap = (uint32**) _TIFFmalloc(
+ 256*sizeof (uint32 *)+(256*nsamples*sizeof(uint32)));
+ if (img->PALmap == NULL) {
+ TIFFErrorExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "No space for Palette mapping table");
+ return (0);
+ }
+ p = (uint32*)(img->PALmap + 256);
+ for (i = 0; i < 256; i++) {
+ TIFFRGBValue c;
+ img->PALmap[i] = p;
+#define CMAP(x) c = (TIFFRGBValue) x; *p++ = PACK(r[c]&0xff, g[c]&0xff, b[c]&0xff);
+ switch (bitspersample) {
+ case 1:
+ CMAP(i>>7);
+ CMAP((i>>6)&1);
+ CMAP((i>>5)&1);
+ CMAP((i>>4)&1);
+ CMAP((i>>3)&1);
+ CMAP((i>>2)&1);
+ CMAP((i>>1)&1);
+ CMAP(i&1);
+ break;
+ case 2:
+ CMAP(i>>6);
+ CMAP((i>>4)&3);
+ CMAP((i>>2)&3);
+ CMAP(i&3);
+ break;
+ case 4:
+ CMAP(i>>4);
+ CMAP(i&0xf);
+ break;
+ case 8:
+ CMAP(i);
+ break;
+ }
+#undef CMAP
+ }
+ return (1);
+}
+
+/*
+ * Construct any mapping table used
+ * by the associated put routine.
+ */
+static int
+buildMap(TIFFRGBAImage* img)
+{
+ switch (img->photometric) {
+ case PHOTOMETRIC_RGB:
+ case PHOTOMETRIC_YCBCR:
+ case PHOTOMETRIC_SEPARATED:
+ if (img->bitspersample == 8)
+ break;
+ /* fall thru... */
+ case PHOTOMETRIC_MINISBLACK:
+ case PHOTOMETRIC_MINISWHITE:
+ if (!setupMap(img))
+ return (0);
+ break;
+ case PHOTOMETRIC_PALETTE:
+ /*
+ * Convert 16-bit colormap to 8-bit (unless it looks
+ * like an old-style 8-bit colormap).
+ */
+ if (checkcmap(img) == 16)
+ cvtcmap(img);
+ else
+ TIFFWarningExt(img->tif->tif_clientdata, TIFFFileName(img->tif), "Assuming 8-bit colormap");
+ /*
+ * Use mapping table and colormap to construct
+ * unpacking tables for samples < 8 bits.
+ */
+ if (img->bitspersample <= 8 && !makecmap(img))
+ return (0);
+ break;
+ }
+ return (1);
+}
+
+/*
+ * Select the appropriate conversion routine for packed data.
+ */
+static int
+PickContigCase(TIFFRGBAImage* img)
+{
+ img->get = TIFFIsTiled(img->tif) ? gtTileContig : gtStripContig;
+ img->put.contig = NULL;
+ switch (img->photometric) {
+ case PHOTOMETRIC_RGB:
+ switch (img->bitspersample) {
+ case 8:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ img->put.contig = putRGBAAcontig8bittile;
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ img->put.contig = putRGBUAcontig8bittile;
+ }
+ else
+ img->put.contig = putRGBcontig8bittile;
+ break;
+ case 16:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ {
+ img->put.contig = putRGBAAcontig16bittile;
+ }
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ img->put.contig = putRGBUAcontig16bittile;
+ }
+ else
+ {
+ img->put.contig = putRGBcontig16bittile;
+ }
+ break;
+ }
+ break;
+ case PHOTOMETRIC_SEPARATED:
+ if (buildMap(img)) {
+ if (img->bitspersample == 8) {
+ if (!img->Map)
+ img->put.contig = putRGBcontig8bitCMYKtile;
+ else
+ img->put.contig = putRGBcontig8bitCMYKMaptile;
+ }
+ }
+ break;
+ case PHOTOMETRIC_PALETTE:
+ if (buildMap(img)) {
+ switch (img->bitspersample) {
+ case 8:
+ img->put.contig = put8bitcmaptile;
+ break;
+ case 4:
+ img->put.contig = put4bitcmaptile;
+ break;
+ case 2:
+ img->put.contig = put2bitcmaptile;
+ break;
+ case 1:
+ img->put.contig = put1bitcmaptile;
+ break;
+ }
+ }
+ break;
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ if (buildMap(img)) {
+ switch (img->bitspersample) {
+ case 16:
+ img->put.contig = put16bitbwtile;
+ break;
+ case 8:
+ img->put.contig = putgreytile;
+ break;
+ case 4:
+ img->put.contig = put4bitbwtile;
+ break;
+ case 2:
+ img->put.contig = put2bitbwtile;
+ break;
+ case 1:
+ img->put.contig = put1bitbwtile;
+ break;
+ }
+ }
+ break;
+ case PHOTOMETRIC_YCBCR:
+ if (img->bitspersample == 8)
+ {
+ if (initYCbCrConversion(img)!=0)
+ {
+ /*
+ * The 6.0 spec says that subsampling must be
+ * one of 1, 2, or 4, and that vertical subsampling
+ * must always be <= horizontal subsampling; so
+ * there are only a few possibilities and we just
+ * enumerate the cases.
+ * Joris: added support for the [1,2] case, nonetheless, to accomodate
+ * some OJPEG files
+ */
+ uint16 SubsamplingHor;
+ uint16 SubsamplingVer;
+ TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &SubsamplingHor, &SubsamplingVer);
+ switch ((SubsamplingHor<<4)|SubsamplingVer) {
+ case 0x44:
+ img->put.contig = putcontig8bitYCbCr44tile;
+ break;
+ case 0x42:
+ img->put.contig = putcontig8bitYCbCr42tile;
+ break;
+ case 0x41:
+ img->put.contig = putcontig8bitYCbCr41tile;
+ break;
+ case 0x22:
+ img->put.contig = putcontig8bitYCbCr22tile;
+ break;
+ case 0x21:
+ img->put.contig = putcontig8bitYCbCr21tile;
+ break;
+ case 0x12:
+ img->put.contig = putcontig8bitYCbCr12tile;
+ break;
+ case 0x11:
+ img->put.contig = putcontig8bitYCbCr11tile;
+ break;
+ }
+ }
+ }
+ break;
+ case PHOTOMETRIC_CIELAB:
+ if (buildMap(img)) {
+ if (img->bitspersample == 8)
+ img->put.contig = initCIELabConversion(img);
+ break;
+ }
+ }
+ return ((img->get!=NULL) && (img->put.contig!=NULL));
+}
+
+/*
+ * Select the appropriate conversion routine for unpacked data.
+ *
+ * NB: we assume that unpacked single channel data is directed
+ * to the "packed routines.
+ */
+static int
+PickSeparateCase(TIFFRGBAImage* img)
+{
+ img->get = TIFFIsTiled(img->tif) ? gtTileSeparate : gtStripSeparate;
+ img->put.separate = NULL;
+ switch (img->photometric) {
+ case PHOTOMETRIC_RGB:
+ switch (img->bitspersample) {
+ case 8:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ img->put.separate = putRGBAAseparate8bittile;
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ img->put.separate = putRGBUAseparate8bittile;
+ }
+ else
+ img->put.separate = putRGBseparate8bittile;
+ break;
+ case 16:
+ if (img->alpha == EXTRASAMPLE_ASSOCALPHA)
+ {
+ img->put.separate = putRGBAAseparate16bittile;
+ }
+ else if (img->alpha == EXTRASAMPLE_UNASSALPHA)
+ {
+ img->put.separate = putRGBUAseparate16bittile;
+ }
+ else
+ {
+ img->put.separate = putRGBseparate16bittile;
+ }
+ break;
+ }
+ break;
+ case PHOTOMETRIC_YCBCR:
+ if ((img->bitspersample==8) && (img->samplesperpixel==3))
+ {
+ if (initYCbCrConversion(img)!=0)
+ {
+ uint16 hs, vs;
+ TIFFGetFieldDefaulted(img->tif, TIFFTAG_YCBCRSUBSAMPLING, &hs, &vs);
+ switch ((hs<<4)|vs) {
+ case 0x11:
+ img->put.separate = putseparate8bitYCbCr11tile;
+ break;
+ /* TODO: add other cases here */
+ }
+ }
+ }
+ break;
+ }
+ return ((img->get!=NULL) && (img->put.separate!=NULL));
+}
+
+/*
+ * Read a whole strip off data from the file, and convert to RGBA form.
+ * If this is the last strip, then it will only contain the portion of
+ * the strip that is actually within the image space. The result is
+ * organized in bottom to top form.
+ */
+
+
+int
+TIFFReadRGBAStrip(TIFF* tif, uint32 row, uint32 * raster )
+
+{
+ char emsg[1024] = "";
+ TIFFRGBAImage img;
+ int ok;
+ uint32 rowsperstrip, rows_to_read;
+
+ if( TIFFIsTiled( tif ) )
+ {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
+ "Can't use TIFFReadRGBAStrip() with tiled file.");
+ return (0);
+ }
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
+ if( (row % rowsperstrip) != 0 )
+ {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
+ "Row passed to TIFFReadRGBAStrip() must be first in a strip.");
+ return (0);
+ }
+
+ if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+
+ img.row_offset = row;
+ img.col_offset = 0;
+
+ if( row + rowsperstrip > img.height )
+ rows_to_read = img.height - row;
+ else
+ rows_to_read = rowsperstrip;
+
+ ok = TIFFRGBAImageGet(&img, raster, img.width, rows_to_read );
+
+ TIFFRGBAImageEnd(&img);
+ } else {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
+ ok = 0;
+ }
+
+ return (ok);
+}
+
+/*
+ * Read a whole tile off data from the file, and convert to RGBA form.
+ * The returned RGBA data is organized from bottom to top of tile,
+ * and may include zeroed areas if the tile extends off the image.
+ */
+
+int
+TIFFReadRGBATile(TIFF* tif, uint32 col, uint32 row, uint32 * raster)
+
+{
+ char emsg[1024] = "";
+ TIFFRGBAImage img;
+ int ok;
+ uint32 tile_xsize, tile_ysize;
+ uint32 read_xsize, read_ysize;
+ uint32 i_row;
+
+ /*
+ * Verify that our request is legal - on a tile file, and on a
+ * tile boundary.
+ */
+
+ if( !TIFFIsTiled( tif ) )
+ {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
+ "Can't use TIFFReadRGBATile() with stripped file.");
+ return (0);
+ }
+
+ TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize);
+ TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize);
+ if( (col % tile_xsize) != 0 || (row % tile_ysize) != 0 )
+ {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
+ "Row/col passed to TIFFReadRGBATile() must be top"
+ "left corner of a tile.");
+ return (0);
+ }
+
+ /*
+ * Setup the RGBA reader.
+ */
+
+ if (!TIFFRGBAImageOK(tif, emsg)
+ || !TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+ TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), emsg);
+ return( 0 );
+ }
+
+ /*
+ * The TIFFRGBAImageGet() function doesn't allow us to get off the
+ * edge of the image, even to fill an otherwise valid tile. So we
+ * figure out how much we can read, and fix up the tile buffer to
+ * a full tile configuration afterwards.
+ */
+
+ if( row + tile_ysize > img.height )
+ read_ysize = img.height - row;
+ else
+ read_ysize = tile_ysize;
+
+ if( col + tile_xsize > img.width )
+ read_xsize = img.width - col;
+ else
+ read_xsize = tile_xsize;
+
+ /*
+ * Read the chunk of imagery.
+ */
+
+ img.row_offset = row;
+ img.col_offset = col;
+
+ ok = TIFFRGBAImageGet(&img, raster, read_xsize, read_ysize );
+
+ TIFFRGBAImageEnd(&img);
+
+ /*
+ * If our read was incomplete we will need to fix up the tile by
+ * shifting the data around as if a full tile of data is being returned.
+ *
+ * This is all the more complicated because the image is organized in
+ * bottom to top format.
+ */
+
+ if( read_xsize == tile_xsize && read_ysize == tile_ysize )
+ return( ok );
+
+ for( i_row = 0; i_row < read_ysize; i_row++ ) {
+ memmove( raster + (tile_ysize - i_row - 1) * tile_xsize,
+ raster + (read_ysize - i_row - 1) * read_xsize,
+ read_xsize * sizeof(uint32) );
+ _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize+read_xsize,
+ 0, sizeof(uint32) * (tile_xsize - read_xsize) );
+ }
+
+ for( i_row = read_ysize; i_row < tile_ysize; i_row++ ) {
+ _TIFFmemset( raster + (tile_ysize - i_row - 1) * tile_xsize,
+ 0, sizeof(uint32) * tile_xsize );
+ }
+
+ return (ok);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_jbig.c b/Source/LibTIFF/tif_jbig.c
new file mode 100644
index 0000000..e63c9a6
--- /dev/null
+++ b/Source/LibTIFF/tif_jbig.c
@@ -0,0 +1,378 @@
+/* $Id: tif_jbig.c,v 1.13 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * JBIG Compression Algorithm Support.
+ * Contributed by Lee Howard <faxguy@deanox.com>
+ *
+ */
+
+#include "tiffiop.h"
+
+#ifdef JBIG_SUPPORT
+#include "jbig.h"
+
+typedef struct
+{
+ uint32 recvparams; /* encoded Class 2 session params */
+ char* subaddress; /* subaddress string */
+ uint32 recvtime; /* time spend receiving in seconds */
+ char* faxdcs; /* encoded fax parameters (DCS, Table 2/T.30) */
+
+ TIFFVGetMethod vgetparent;
+ TIFFVSetMethod vsetparent;
+} JBIGState;
+
+#define GetJBIGState(tif) ((JBIGState*)(tif)->tif_data)
+
+#define FIELD_RECVPARAMS (FIELD_CODEC+0)
+#define FIELD_SUBADDRESS (FIELD_CODEC+1)
+#define FIELD_RECVTIME (FIELD_CODEC+2)
+#define FIELD_FAXDCS (FIELD_CODEC+3)
+
+static const TIFFFieldInfo jbigFieldInfo[] =
+{
+ {TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS, TRUE, FALSE, "FaxRecvParams"},
+ {TIFFTAG_FAXSUBADDRESS, -1, -1, TIFF_ASCII, FIELD_SUBADDRESS, TRUE, FALSE, "FaxSubAddress"},
+ {TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME, TRUE, FALSE, "FaxRecvTime"},
+ {TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, FIELD_FAXDCS, TRUE, FALSE, "FaxDcs"},
+};
+
+static int JBIGSetupDecode(TIFF* tif)
+{
+ if (TIFFNumberOfStrips(tif) != 1)
+ {
+ TIFFError("JBIG", "Multistrip images not supported in decoder");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int JBIGDecode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s)
+{
+ struct jbg_dec_state decoder;
+ int decodeStatus = 0;
+ unsigned char* pImage = NULL;
+ (void) size, (void) s;
+
+ if (isFillOrder(tif, tif->tif_dir.td_fillorder))
+ {
+ TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdatasize);
+ }
+
+ jbg_dec_init(&decoder);
+
+#if defined(HAVE_JBG_NEWLEN)
+ jbg_newlen(tif->tif_rawdata, tif->tif_rawdatasize);
+ /*
+ * I do not check the return status of jbg_newlen because even if this
+ * function fails it does not necessarily mean that decoding the image
+ * will fail. It is generally only needed for received fax images
+ * that do not contain the actual length of the image in the BIE
+ * header. I do not log when an error occurs because that will cause
+ * problems when converting JBIG encoded TIFF's to
+ * PostScript. As long as the actual image length is contained in the
+ * BIE header jbg_dec_in should succeed.
+ */
+#endif /* HAVE_JBG_NEWLEN */
+
+ decodeStatus = jbg_dec_in(&decoder, tif->tif_rawdata,
+ tif->tif_rawdatasize, NULL);
+ if (JBG_EOK != decodeStatus)
+ {
+ /*
+ * XXX: JBG_EN constant was defined in pre-2.0 releases of the
+ * JBIG-KIT. Since the 2.0 the error reporting functions were
+ * changed. We will handle both cases here.
+ */
+ TIFFError("JBIG", "Error (%d) decoding: %s", decodeStatus,
+#if defined(JBG_EN)
+ jbg_strerror(decodeStatus, JBG_EN)
+#else
+ jbg_strerror(decodeStatus)
+#endif
+ );
+ return 0;
+ }
+
+ pImage = jbg_dec_getimage(&decoder, 0);
+ _TIFFmemcpy(buffer, pImage, jbg_dec_getsize(&decoder));
+ jbg_dec_free(&decoder);
+ return 1;
+}
+
+static int JBIGSetupEncode(TIFF* tif)
+{
+ if (TIFFNumberOfStrips(tif) != 1)
+ {
+ TIFFError("JBIG", "Multistrip images not supported in encoder");
+ return 0;
+ }
+
+ return 1;
+}
+
+static int JBIGCopyEncodedData(TIFF* tif, tidata_t pp, tsize_t cc, tsample_t s)
+{
+ (void) s;
+ while (cc > 0)
+ {
+ tsize_t n = cc;
+
+ if (tif->tif_rawcc + n > tif->tif_rawdatasize)
+ {
+ n = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+
+ assert(n > 0);
+ _TIFFmemcpy(tif->tif_rawcp, pp, n);
+ tif->tif_rawcp += n;
+ tif->tif_rawcc += n;
+ pp += n;
+ cc -= n;
+ if (tif->tif_rawcc >= tif->tif_rawdatasize &&
+ !TIFFFlushData1(tif))
+ {
+ return (-1);
+ }
+ }
+
+ return (1);
+}
+
+static void JBIGOutputBie(unsigned char* buffer, size_t len, void *userData)
+{
+ TIFF* tif = (TIFF*)userData;
+
+ if (isFillOrder(tif, tif->tif_dir.td_fillorder))
+ {
+ TIFFReverseBits(buffer, len);
+ }
+
+ JBIGCopyEncodedData(tif, buffer, len, 0);
+}
+
+static int JBIGEncode(TIFF* tif, tidata_t buffer, tsize_t size, tsample_t s)
+{
+ TIFFDirectory* dir = &tif->tif_dir;
+ struct jbg_enc_state encoder;
+
+ (void) size, (void) s;
+
+ jbg_enc_init(&encoder,
+ dir->td_imagewidth,
+ dir->td_imagelength,
+ 1,
+ &buffer,
+ JBIGOutputBie,
+ tif);
+ /*
+ * jbg_enc_out does the "real" encoding. As data is encoded,
+ * JBIGOutputBie is called, which writes the data to the directory.
+ */
+ jbg_enc_out(&encoder);
+ jbg_enc_free(&encoder);
+
+ return 1;
+}
+
+static void JBIGCleanup(TIFF* tif)
+{
+ JBIGState *sp = GetJBIGState(tif);
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ _TIFFfree(tif->tif_data);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static void JBIGPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+ JBIGState* codec = GetJBIGState(tif);
+ (void)flags;
+
+ if (TIFFFieldSet(tif, FIELD_RECVPARAMS))
+ {
+ fprintf(fd,
+ " Fax Receive Parameters: %08lx\n",
+ (unsigned long)codec->recvparams);
+ }
+
+ if (TIFFFieldSet(tif, FIELD_SUBADDRESS))
+ {
+ fprintf(fd,
+ " Fax SubAddress: %s\n",
+ codec->subaddress);
+ }
+
+ if (TIFFFieldSet(tif, FIELD_RECVTIME))
+ {
+ fprintf(fd,
+ " Fax Receive Time: %lu secs\n",
+ (unsigned long)codec->recvtime);
+ }
+
+ if (TIFFFieldSet(tif, FIELD_FAXDCS))
+ {
+ fprintf(fd,
+ " Fax DCS: %s\n",
+ codec->faxdcs);
+ }
+}
+
+static int JBIGVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ JBIGState* codec = GetJBIGState(tif);
+
+ switch (tag)
+ {
+ case TIFFTAG_FAXRECVPARAMS:
+ *va_arg(ap, uint32*) = codec->recvparams;
+ break;
+
+ case TIFFTAG_FAXSUBADDRESS:
+ *va_arg(ap, char**) = codec->subaddress;
+ break;
+
+ case TIFFTAG_FAXRECVTIME:
+ *va_arg(ap, uint32*) = codec->recvtime;
+ break;
+
+ case TIFFTAG_FAXDCS:
+ *va_arg(ap, char**) = codec->faxdcs;
+ break;
+
+ default:
+ return (*codec->vgetparent)(tif, tag, ap);
+ }
+
+ return 1;
+}
+
+static int JBIGVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ JBIGState* codec = GetJBIGState(tif);
+
+ switch (tag)
+ {
+ case TIFFTAG_FAXRECVPARAMS:
+ codec->recvparams = va_arg(ap, uint32);
+ break;
+
+ case TIFFTAG_FAXSUBADDRESS:
+ _TIFFsetString(&codec->subaddress, va_arg(ap, char*));
+ break;
+
+ case TIFFTAG_FAXRECVTIME:
+ codec->recvtime = va_arg(ap, uint32);
+ break;
+
+ case TIFFTAG_FAXDCS:
+ _TIFFsetString(&codec->faxdcs, va_arg(ap, char*));
+ break;
+
+ default:
+ return (*codec->vsetparent)(tif, tag, ap);
+ }
+
+ TIFFSetFieldBit(tif, _TIFFFieldWithTag(tif, tag)->field_bit);
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ return 1;
+}
+
+int TIFFInitJBIG(TIFF* tif, int scheme)
+{
+ JBIGState* codec = NULL;
+
+ assert(scheme == COMPRESSION_JBIG);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, jbigFieldInfo,
+ TIFFArrayCount(jbigFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFInitJBIG",
+ "Merging JBIG codec-specific tags failed");
+ return 0;
+ }
+
+ /* Allocate memory for the JBIGState structure.*/
+ tif->tif_data = (tdata_t)_TIFFmalloc(sizeof(JBIGState));
+ if (tif->tif_data == NULL)
+ {
+ TIFFError("TIFFInitJBIG", "Not enough memory for JBIGState");
+ return 0;
+ }
+ _TIFFmemset(tif->tif_data, 0, sizeof(JBIGState));
+ codec = GetJBIGState(tif);
+
+ /* Initialize codec private fields */
+ codec->recvparams = 0;
+ codec->subaddress = NULL;
+ codec->faxdcs = NULL;
+ codec->recvtime = 0;
+
+ /*
+ * Override parent get/set field methods.
+ */
+ codec->vgetparent = tif->tif_tagmethods.vgetfield;
+ codec->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vgetfield = JBIGVGetField;
+ tif->tif_tagmethods.vsetfield = JBIGVSetField;
+ tif->tif_tagmethods.printdir = JBIGPrintDir;
+
+ /*
+ * These flags are set so the JBIG Codec can control when to reverse
+ * bits and when not to and to allow the jbig decoder and bit reverser
+ * to write to memory when necessary.
+ */
+ tif->tif_flags |= TIFF_NOBITREV;
+ tif->tif_flags &= ~TIFF_MAPPED;
+
+ /* Setup the function pointers for encode, decode, and cleanup. */
+ tif->tif_setupdecode = JBIGSetupDecode;
+ tif->tif_decodestrip = JBIGDecode;
+
+ tif->tif_setupencode = JBIGSetupEncode;
+ tif->tif_encodestrip = JBIGEncode;
+
+ tif->tif_cleanup = JBIGCleanup;
+
+ return 1;
+}
+
+#endif /* JBIG_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
+
diff --git a/Source/LibTIFF/tif_jpeg.c b/Source/LibTIFF/tif_jpeg.c
new file mode 100644
index 0000000..797f67a
--- /dev/null
+++ b/Source/LibTIFF/tif_jpeg.c
@@ -0,0 +1,2035 @@
+/* $Id: tif_jpeg.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1994-1997 Sam Leffler
+ * Copyright (c) 1994-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+
+#include "tiffiop.h"
+#ifdef JPEG_SUPPORT
+
+/*
+ * TIFF Library
+ *
+ * JPEG Compression support per TIFF Technical Note #2
+ * (*not* per the original TIFF 6.0 spec).
+ *
+ * This file is simply an interface to the libjpeg library written by
+ * the Independent JPEG Group. You need release 5 or later of the IJG
+ * code, which you can find on the Internet at ftp.uu.net:/graphics/jpeg/.
+ *
+ * Contributed by Tom Lane <tgl@sss.pgh.pa.us>.
+ */
+#include <setjmp.h>
+
+int TIFFFillStrip(TIFF*, tstrip_t);
+int TIFFFillTile(TIFF*, ttile_t);
+
+/* We undefine FAR to avoid conflict with JPEG definition */
+
+#ifdef FAR
+#undef FAR
+#endif
+
+/*
+ Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is
+ not defined. Unfortunately, the MinGW and Borland compilers include
+ a typedef for INT32, which causes a conflict. MSVC does not include
+ a conficting typedef given the headers which are included.
+*/
+#if defined(__BORLANDC__) || defined(__MINGW32__)
+# define XMD_H 1
+#endif
+
+/*
+ The windows RPCNDR.H file defines boolean, but defines it with the
+ unsigned char size. You should compile JPEG library using appropriate
+ definitions in jconfig.h header, but many users compile library in wrong
+ way. That causes errors of the following type:
+
+ "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432,
+ caller expects 464"
+
+ For such users we wil fix the problem here. See install.doc file from
+ the JPEG library distribution for details.
+*/
+
+/* Define "boolean" as unsigned char, not int, per Windows custom. */
+#if defined(WIN32) && !defined(__MINGW32__)
+# ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
+ typedef unsigned char boolean;
+# endif
+# define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
+#endif
+
+#include "../LibJPEG/jpeglib.h"
+#include "../LibJPEG/jerror.h"
+
+/*
+ * We are using width_in_blocks which is supposed to be private to
+ * libjpeg. Unfortunately, the libjpeg delivered with Cygwin has
+ * renamed this member to width_in_data_units. Since the header has
+ * also renamed a define, use that unique define name in order to
+ * detect the problem header and adjust to suit.
+ */
+#if defined(D_MAX_DATA_UNITS_IN_MCU)
+#define width_in_blocks width_in_data_units
+#endif
+
+/*
+ * On some machines it may be worthwhile to use _setjmp or sigsetjmp
+ * in place of plain setjmp. These macros will make it easier.
+ */
+#define SETJMP(jbuf) setjmp(jbuf)
+#define LONGJMP(jbuf,code) longjmp(jbuf,code)
+#define JMP_BUF jmp_buf
+
+typedef struct jpeg_destination_mgr jpeg_destination_mgr;
+typedef struct jpeg_source_mgr jpeg_source_mgr;
+typedef struct jpeg_error_mgr jpeg_error_mgr;
+
+/*
+ * State block for each open TIFF file using
+ * libjpeg to do JPEG compression/decompression.
+ *
+ * libjpeg's visible state is either a jpeg_compress_struct
+ * or jpeg_decompress_struct depending on which way we
+ * are going. comm can be used to refer to the fields
+ * which are common to both.
+ *
+ * NB: cinfo is required to be the first member of JPEGState,
+ * so we can safely cast JPEGState* -> jpeg_xxx_struct*
+ * and vice versa!
+ */
+typedef struct {
+ union {
+ struct jpeg_compress_struct c;
+ struct jpeg_decompress_struct d;
+ struct jpeg_common_struct comm;
+ } cinfo; /* NB: must be first */
+ int cinfo_initialized;
+
+ jpeg_error_mgr err; /* libjpeg error manager */
+ JMP_BUF exit_jmpbuf; /* for catching libjpeg failures */
+ /*
+ * The following two members could be a union, but
+ * they're small enough that it's not worth the effort.
+ */
+ jpeg_destination_mgr dest; /* data dest for compression */
+ jpeg_source_mgr src; /* data source for decompression */
+ /* private state */
+ TIFF* tif; /* back link needed by some code */
+ uint16 photometric; /* copy of PhotometricInterpretation */
+ uint16 h_sampling; /* luminance sampling factors */
+ uint16 v_sampling;
+ tsize_t bytesperline; /* decompressed bytes per scanline */
+ /* pointers to intermediate buffers when processing downsampled data */
+ JSAMPARRAY ds_buffer[MAX_COMPONENTS];
+ int scancount; /* number of "scanlines" accumulated */
+ int samplesperclump;
+
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+ TIFFPrintMethod printdir; /* super-class method */
+ TIFFStripMethod defsparent; /* super-class method */
+ TIFFTileMethod deftparent; /* super-class method */
+ /* pseudo-tag fields */
+ void* jpegtables; /* JPEGTables tag value, or NULL */
+ uint32 jpegtables_length; /* number of bytes in same */
+ int jpegquality; /* Compression quality level */
+ int jpegcolormode; /* Auto RGB<=>YCbCr convert? */
+ int jpegtablesmode; /* What to put in JPEGTables */
+
+ int ycbcrsampling_fetched;
+ uint32 recvparams; /* encoded Class 2 session params */
+ char* subaddress; /* subaddress string */
+ uint32 recvtime; /* time spent receiving (secs) */
+ char* faxdcs; /* encoded fax parameters (DCS, Table 2/T.30) */
+} JPEGState;
+
+#define JState(tif) ((JPEGState*)(tif)->tif_data)
+
+static int JPEGDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+static int JPEGDecodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);
+static int JPEGEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static int JPEGEncodeRaw(TIFF*, tidata_t, tsize_t, tsample_t);
+static int JPEGInitializeLibJPEG( TIFF * tif,
+ int force_encode, int force_decode );
+
+#define FIELD_JPEGTABLES (FIELD_CODEC+0)
+#define FIELD_RECVPARAMS (FIELD_CODEC+1)
+#define FIELD_SUBADDRESS (FIELD_CODEC+2)
+#define FIELD_RECVTIME (FIELD_CODEC+3)
+#define FIELD_FAXDCS (FIELD_CODEC+4)
+
+static const TIFFFieldInfo jpegFieldInfo[] = {
+ { TIFFTAG_JPEGTABLES, -3,-3, TIFF_UNDEFINED, FIELD_JPEGTABLES,
+ FALSE, TRUE, "JPEGTables" },
+ { TIFFTAG_JPEGQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ TRUE, FALSE, "" },
+ { TIFFTAG_JPEGCOLORMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ FALSE, FALSE, "" },
+ { TIFFTAG_JPEGTABLESMODE, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ FALSE, FALSE, "" },
+ /* Specific for JPEG in faxes */
+ { TIFFTAG_FAXRECVPARAMS, 1, 1, TIFF_LONG, FIELD_RECVPARAMS,
+ TRUE, FALSE, "FaxRecvParams" },
+ { TIFFTAG_FAXSUBADDRESS, -1,-1, TIFF_ASCII, FIELD_SUBADDRESS,
+ TRUE, FALSE, "FaxSubAddress" },
+ { TIFFTAG_FAXRECVTIME, 1, 1, TIFF_LONG, FIELD_RECVTIME,
+ TRUE, FALSE, "FaxRecvTime" },
+ { TIFFTAG_FAXDCS, -1, -1, TIFF_ASCII, FIELD_FAXDCS,
+ TRUE, FALSE, "FaxDcs" },
+};
+#define N(a) (sizeof (a) / sizeof (a[0]))
+
+/*
+ * libjpeg interface layer.
+ *
+ * We use setjmp/longjmp to return control to libtiff
+ * when a fatal error is encountered within the JPEG
+ * library. We also direct libjpeg error and warning
+ * messages through the appropriate libtiff handlers.
+ */
+
+/*
+ * Error handling routines (these replace corresponding
+ * IJG routines from jerror.c). These are used for both
+ * compression and decompression.
+ */
+static void
+TIFFjpeg_error_exit(j_common_ptr cinfo)
+{
+ JPEGState *sp = (JPEGState *) cinfo; /* NB: cinfo assumed first */
+ char buffer[JMSG_LENGTH_MAX];
+
+ (*cinfo->err->format_message) (cinfo, buffer);
+ TIFFErrorExt(sp->tif->tif_clientdata, "JPEGLib", buffer); /* display the error message */
+ jpeg_abort(cinfo); /* clean up libjpeg state */
+ LONGJMP(sp->exit_jmpbuf, 1); /* return to libtiff caller */
+}
+
+/*
+ * This routine is invoked only for warning messages,
+ * since error_exit does its own thing and trace_level
+ * is never set > 0.
+ */
+static void
+TIFFjpeg_output_message(j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+
+ (*cinfo->err->format_message) (cinfo, buffer);
+ TIFFWarningExt(((JPEGState *) cinfo)->tif->tif_clientdata, "JPEGLib", buffer);
+}
+
+/*
+ * Interface routines. This layer of routines exists
+ * primarily to limit side-effects from using setjmp.
+ * Also, normal/error returns are converted into return
+ * values per libtiff practice.
+ */
+#define CALLJPEG(sp, fail, op) (SETJMP((sp)->exit_jmpbuf) ? (fail) : (op))
+#define CALLVJPEG(sp, op) CALLJPEG(sp, 0, ((op),1))
+
+static int
+TIFFjpeg_create_compress(JPEGState* sp)
+{
+ /* initialize JPEG error handling */
+ sp->cinfo.c.err = jpeg_std_error(&sp->err);
+ sp->err.error_exit = TIFFjpeg_error_exit;
+ sp->err.output_message = TIFFjpeg_output_message;
+
+ return CALLVJPEG(sp, jpeg_create_compress(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_create_decompress(JPEGState* sp)
+{
+ /* initialize JPEG error handling */
+ sp->cinfo.d.err = jpeg_std_error(&sp->err);
+ sp->err.error_exit = TIFFjpeg_error_exit;
+ sp->err.output_message = TIFFjpeg_output_message;
+
+ return CALLVJPEG(sp, jpeg_create_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_set_defaults(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_set_defaults(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_set_colorspace(JPEGState* sp, J_COLOR_SPACE colorspace)
+{
+ return CALLVJPEG(sp, jpeg_set_colorspace(&sp->cinfo.c, colorspace));
+}
+
+static int
+TIFFjpeg_set_quality(JPEGState* sp, int quality, boolean force_baseline)
+{
+ return CALLVJPEG(sp,
+ jpeg_set_quality(&sp->cinfo.c, quality, force_baseline));
+}
+
+static int
+TIFFjpeg_suppress_tables(JPEGState* sp, boolean suppress)
+{
+ return CALLVJPEG(sp, jpeg_suppress_tables(&sp->cinfo.c, suppress));
+}
+
+static int
+TIFFjpeg_start_compress(JPEGState* sp, boolean write_all_tables)
+{
+ return CALLVJPEG(sp,
+ jpeg_start_compress(&sp->cinfo.c, write_all_tables));
+}
+
+static int
+TIFFjpeg_write_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int num_lines)
+{
+ return CALLJPEG(sp, -1, (int) jpeg_write_scanlines(&sp->cinfo.c,
+ scanlines, (JDIMENSION) num_lines));
+}
+
+static int
+TIFFjpeg_write_raw_data(JPEGState* sp, JSAMPIMAGE data, int num_lines)
+{
+ return CALLJPEG(sp, -1, (int) jpeg_write_raw_data(&sp->cinfo.c,
+ data, (JDIMENSION) num_lines));
+}
+
+static int
+TIFFjpeg_finish_compress(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_finish_compress(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_write_tables(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_write_tables(&sp->cinfo.c));
+}
+
+static int
+TIFFjpeg_read_header(JPEGState* sp, boolean require_image)
+{
+ return CALLJPEG(sp, -1, jpeg_read_header(&sp->cinfo.d, require_image));
+}
+
+static int
+TIFFjpeg_start_decompress(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_start_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_read_scanlines(JPEGState* sp, JSAMPARRAY scanlines, int max_lines)
+{
+ return CALLJPEG(sp, -1, (int) jpeg_read_scanlines(&sp->cinfo.d,
+ scanlines, (JDIMENSION) max_lines));
+}
+
+static int
+TIFFjpeg_read_raw_data(JPEGState* sp, JSAMPIMAGE data, int max_lines)
+{
+ return CALLJPEG(sp, -1, (int) jpeg_read_raw_data(&sp->cinfo.d,
+ data, (JDIMENSION) max_lines));
+}
+
+static int
+TIFFjpeg_finish_decompress(JPEGState* sp)
+{
+ return CALLJPEG(sp, -1, (int) jpeg_finish_decompress(&sp->cinfo.d));
+}
+
+static int
+TIFFjpeg_abort(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_abort(&sp->cinfo.comm));
+}
+
+static int
+TIFFjpeg_destroy(JPEGState* sp)
+{
+ return CALLVJPEG(sp, jpeg_destroy(&sp->cinfo.comm));
+}
+
+static JSAMPARRAY
+TIFFjpeg_alloc_sarray(JPEGState* sp, int pool_id,
+ JDIMENSION samplesperrow, JDIMENSION numrows)
+{
+ return CALLJPEG(sp, (JSAMPARRAY) NULL,
+ (*sp->cinfo.comm.mem->alloc_sarray)
+ (&sp->cinfo.comm, pool_id, samplesperrow, numrows));
+}
+
+/*
+ * JPEG library destination data manager.
+ * These routines direct compressed data from libjpeg into the
+ * libtiff output buffer.
+ */
+
+static void
+std_init_destination(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+ TIFF* tif = sp->tif;
+
+ sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
+ sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
+}
+
+static boolean
+std_empty_output_buffer(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+ TIFF* tif = sp->tif;
+
+ /* the entire buffer has been filled */
+ tif->tif_rawcc = tif->tif_rawdatasize;
+ TIFFFlushData1(tif);
+ sp->dest.next_output_byte = (JOCTET*) tif->tif_rawdata;
+ sp->dest.free_in_buffer = (size_t) tif->tif_rawdatasize;
+
+ return (TRUE);
+}
+
+static void
+std_term_destination(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+ TIFF* tif = sp->tif;
+
+ tif->tif_rawcp = (tidata_t) sp->dest.next_output_byte;
+ tif->tif_rawcc =
+ tif->tif_rawdatasize - (tsize_t) sp->dest.free_in_buffer;
+ /* NB: libtiff does the final buffer flush */
+}
+
+static void
+TIFFjpeg_data_dest(JPEGState* sp, TIFF* tif)
+{
+ (void) tif;
+ sp->cinfo.c.dest = &sp->dest;
+ sp->dest.init_destination = std_init_destination;
+ sp->dest.empty_output_buffer = std_empty_output_buffer;
+ sp->dest.term_destination = std_term_destination;
+}
+
+/*
+ * Alternate destination manager for outputting to JPEGTables field.
+ */
+
+static void
+tables_init_destination(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+
+ /* while building, jpegtables_length is allocated buffer size */
+ sp->dest.next_output_byte = (JOCTET*) sp->jpegtables;
+ sp->dest.free_in_buffer = (size_t) sp->jpegtables_length;
+}
+
+static boolean
+tables_empty_output_buffer(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+ void* newbuf;
+
+ /* the entire buffer has been filled; enlarge it by 1000 bytes */
+ newbuf = _TIFFrealloc((tdata_t) sp->jpegtables,
+ (tsize_t) (sp->jpegtables_length + 1000));
+ if (newbuf == NULL)
+ ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 100);
+ sp->dest.next_output_byte = (JOCTET*) newbuf + sp->jpegtables_length;
+ sp->dest.free_in_buffer = (size_t) 1000;
+ sp->jpegtables = newbuf;
+ sp->jpegtables_length += 1000;
+ return (TRUE);
+}
+
+static void
+tables_term_destination(j_compress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+
+ /* set tables length to number of bytes actually emitted */
+ sp->jpegtables_length -= sp->dest.free_in_buffer;
+}
+
+static int
+TIFFjpeg_tables_dest(JPEGState* sp, TIFF* tif)
+{
+ (void) tif;
+ /*
+ * Allocate a working buffer for building tables.
+ * Initial size is 1000 bytes, which is usually adequate.
+ */
+ if (sp->jpegtables)
+ _TIFFfree(sp->jpegtables);
+ sp->jpegtables_length = 1000;
+ sp->jpegtables = (void*) _TIFFmalloc((tsize_t) sp->jpegtables_length);
+ if (sp->jpegtables == NULL) {
+ sp->jpegtables_length = 0;
+ TIFFErrorExt(sp->tif->tif_clientdata, "TIFFjpeg_tables_dest", "No space for JPEGTables");
+ return (0);
+ }
+ sp->cinfo.c.dest = &sp->dest;
+ sp->dest.init_destination = tables_init_destination;
+ sp->dest.empty_output_buffer = tables_empty_output_buffer;
+ sp->dest.term_destination = tables_term_destination;
+ return (1);
+}
+
+/*
+ * JPEG library source data manager.
+ * These routines supply compressed data to libjpeg.
+ */
+
+static void
+std_init_source(j_decompress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+ TIFF* tif = sp->tif;
+
+ sp->src.next_input_byte = (const JOCTET*) tif->tif_rawdata;
+ sp->src.bytes_in_buffer = (size_t) tif->tif_rawcc;
+}
+
+static boolean
+std_fill_input_buffer(j_decompress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState* ) cinfo;
+ static const JOCTET dummy_EOI[2] = { 0xFF, JPEG_EOI };
+
+ /*
+ * Should never get here since entire strip/tile is
+ * read into memory before the decompressor is called,
+ * and thus was supplied by init_source.
+ */
+ WARNMS(cinfo, JWRN_JPEG_EOF);
+ /* insert a fake EOI marker */
+ sp->src.next_input_byte = dummy_EOI;
+ sp->src.bytes_in_buffer = 2;
+ return (TRUE);
+}
+
+static void
+std_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+
+ if (num_bytes > 0) {
+ if (num_bytes > (long) sp->src.bytes_in_buffer) {
+ /* oops, buffer overrun */
+ (void) std_fill_input_buffer(cinfo);
+ } else {
+ sp->src.next_input_byte += (size_t) num_bytes;
+ sp->src.bytes_in_buffer -= (size_t) num_bytes;
+ }
+ }
+}
+
+static void
+std_term_source(j_decompress_ptr cinfo)
+{
+ /* No work necessary here */
+ /* Or must we update tif->tif_rawcp, tif->tif_rawcc ??? */
+ /* (if so, need empty tables_term_source!) */
+ (void) cinfo;
+}
+
+static void
+TIFFjpeg_data_src(JPEGState* sp, TIFF* tif)
+{
+ (void) tif;
+ sp->cinfo.d.src = &sp->src;
+ sp->src.init_source = std_init_source;
+ sp->src.fill_input_buffer = std_fill_input_buffer;
+ sp->src.skip_input_data = std_skip_input_data;
+ sp->src.resync_to_restart = jpeg_resync_to_restart;
+ sp->src.term_source = std_term_source;
+ sp->src.bytes_in_buffer = 0; /* for safety */
+ sp->src.next_input_byte = NULL;
+}
+
+/*
+ * Alternate source manager for reading from JPEGTables.
+ * We can share all the code except for the init routine.
+ */
+
+static void
+tables_init_source(j_decompress_ptr cinfo)
+{
+ JPEGState* sp = (JPEGState*) cinfo;
+
+ sp->src.next_input_byte = (const JOCTET*) sp->jpegtables;
+ sp->src.bytes_in_buffer = (size_t) sp->jpegtables_length;
+}
+
+static void
+TIFFjpeg_tables_src(JPEGState* sp, TIFF* tif)
+{
+ TIFFjpeg_data_src(sp, tif);
+ sp->src.init_source = tables_init_source;
+}
+
+/*
+ * Allocate downsampled-data buffers needed for downsampled I/O.
+ * We use values computed in jpeg_start_compress or jpeg_start_decompress.
+ * We use libjpeg's allocator so that buffers will be released automatically
+ * when done with strip/tile.
+ * This is also a handy place to compute samplesperclump, bytesperline.
+ */
+static int
+alloc_downsampled_buffers(TIFF* tif, jpeg_component_info* comp_info,
+ int num_components)
+{
+ JPEGState* sp = JState(tif);
+ int ci;
+ jpeg_component_info* compptr;
+ JSAMPARRAY buf;
+ int samples_per_clump = 0;
+
+ for (ci = 0, compptr = comp_info; ci < num_components;
+ ci++, compptr++) {
+ samples_per_clump += compptr->h_samp_factor *
+ compptr->v_samp_factor;
+ buf = TIFFjpeg_alloc_sarray(sp, JPOOL_IMAGE,
+ compptr->width_in_blocks * DCTSIZE,
+ (JDIMENSION) (compptr->v_samp_factor*DCTSIZE));
+ if (buf == NULL)
+ return (0);
+ sp->ds_buffer[ci] = buf;
+ }
+ sp->samplesperclump = samples_per_clump;
+ return (1);
+}
+
+
+/*
+ * JPEG Decoding.
+ */
+
+static int
+JPEGSetupDecode(TIFF* tif)
+{
+ JPEGState* sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+
+ JPEGInitializeLibJPEG( tif, 0, 1 );
+
+ assert(sp != NULL);
+ assert(sp->cinfo.comm.is_decompressor);
+
+ /* Read JPEGTables if it is present */
+ if (TIFFFieldSet(tif,FIELD_JPEGTABLES)) {
+ TIFFjpeg_tables_src(sp, tif);
+ if(TIFFjpeg_read_header(sp,FALSE) != JPEG_HEADER_TABLES_ONLY) {
+ TIFFErrorExt(tif->tif_clientdata, "JPEGSetupDecode", "Bogus JPEGTables field");
+ return (0);
+ }
+ }
+
+ /* Grab parameters that are same for all strips/tiles */
+ sp->photometric = td->td_photometric;
+ switch (sp->photometric) {
+ case PHOTOMETRIC_YCBCR:
+ sp->h_sampling = td->td_ycbcrsubsampling[0];
+ sp->v_sampling = td->td_ycbcrsubsampling[1];
+ break;
+ default:
+ /* TIFF 6.0 forbids subsampling of all other color spaces */
+ sp->h_sampling = 1;
+ sp->v_sampling = 1;
+ break;
+ }
+
+ /* Set up for reading normal data */
+ TIFFjpeg_data_src(sp, tif);
+ tif->tif_postdecode = _TIFFNoPostDecode; /* override byte swapping */
+ return (1);
+}
+
+/*
+ * Set up for decoding a strip or tile.
+ */
+static int
+JPEGPreDecode(TIFF* tif, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+ static const char module[] = "JPEGPreDecode";
+ uint32 segment_width, segment_height;
+ int downsampled_output;
+ int ci;
+
+ assert(sp != NULL);
+ assert(sp->cinfo.comm.is_decompressor);
+ /*
+ * Reset decoder state from any previous strip/tile,
+ * in case application didn't read the whole strip.
+ */
+ if (!TIFFjpeg_abort(sp))
+ return (0);
+ /*
+ * Read the header for this strip/tile.
+ */
+ if (TIFFjpeg_read_header(sp, TRUE) != JPEG_HEADER_OK)
+ return (0);
+ /*
+ * Check image parameters and set decompression parameters.
+ */
+ segment_width = td->td_imagewidth;
+ segment_height = td->td_imagelength - tif->tif_row;
+ if (isTiled(tif)) {
+ segment_width = td->td_tilewidth;
+ segment_height = td->td_tilelength;
+ sp->bytesperline = TIFFTileRowSize(tif);
+ } else {
+ if (segment_height > td->td_rowsperstrip)
+ segment_height = td->td_rowsperstrip;
+ sp->bytesperline = TIFFOldScanlineSize(tif);
+ }
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
+ /*
+ * For PC 2, scale down the expected strip/tile size
+ * to match a downsampled component
+ */
+ segment_width = TIFFhowmany(segment_width, sp->h_sampling);
+ segment_height = TIFFhowmany(segment_height, sp->v_sampling);
+ }
+ if (sp->cinfo.d.image_width < segment_width ||
+ sp->cinfo.d.image_height < segment_height) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "Improper JPEG strip/tile size, "
+ "expected %dx%d, got %dx%d",
+ segment_width, segment_height,
+ sp->cinfo.d.image_width,
+ sp->cinfo.d.image_height);
+ }
+ if (sp->cinfo.d.image_width > segment_width ||
+ sp->cinfo.d.image_height > segment_height) {
+ /*
+ * This case could be dangerous, if the strip or tile size has
+ * been reported as less than the amount of data jpeg will
+ * return, some potential security issues arise. Catch this
+ * case and error out.
+ */
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "JPEG strip/tile size exceeds expected dimensions,"
+ " expected %dx%d, got %dx%d",
+ segment_width, segment_height,
+ sp->cinfo.d.image_width, sp->cinfo.d.image_height);
+ return (0);
+ }
+ if (sp->cinfo.d.num_components !=
+ (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+ td->td_samplesperpixel : 1)) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG component count");
+ return (0);
+ }
+#ifdef JPEG_LIB_MK1
+ if (12 != td->td_bitspersample && 8 != td->td_bitspersample) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision");
+ return (0);
+ }
+ sp->cinfo.d.data_precision = td->td_bitspersample;
+ sp->cinfo.d.bits_in_jsample = td->td_bitspersample;
+#else
+ if (sp->cinfo.d.data_precision != td->td_bitspersample) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG data precision");
+ return (0);
+ }
+#endif
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ /* Component 0 should have expected sampling factors */
+ if (sp->cinfo.d.comp_info[0].h_samp_factor != sp->h_sampling ||
+ sp->cinfo.d.comp_info[0].v_samp_factor != sp->v_sampling) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "Improper JPEG sampling factors %d,%d\n"
+ "Apparently should be %d,%d.",
+ sp->cinfo.d.comp_info[0].h_samp_factor,
+ sp->cinfo.d.comp_info[0].v_samp_factor,
+ sp->h_sampling, sp->v_sampling);
+
+ /*
+ * There are potential security issues here
+ * for decoders that have already allocated
+ * buffers based on the expected sampling
+ * factors. Lets check the sampling factors
+ * dont exceed what we were expecting.
+ */
+ if (sp->cinfo.d.comp_info[0].h_samp_factor
+ > sp->h_sampling
+ || sp->cinfo.d.comp_info[0].v_samp_factor
+ > sp->v_sampling) {
+ TIFFErrorExt(tif->tif_clientdata,
+ module,
+ "Cannot honour JPEG sampling factors"
+ " that exceed those specified.");
+ return (0);
+ }
+
+ /*
+ * XXX: Files written by the Intergraph software
+ * has different sampling factors stored in the
+ * TIFF tags and in the JPEG structures. We will
+ * try to deduce Intergraph files by the presense
+ * of the tag 33918.
+ */
+ if (!_TIFFFindFieldInfo(tif, 33918, TIFF_ANY)) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "Decompressor will try reading with "
+ "sampling %d,%d.",
+ sp->cinfo.d.comp_info[0].h_samp_factor,
+ sp->cinfo.d.comp_info[0].v_samp_factor);
+
+ sp->h_sampling = (uint16)
+ sp->cinfo.d.comp_info[0].h_samp_factor;
+ sp->v_sampling = (uint16)
+ sp->cinfo.d.comp_info[0].v_samp_factor;
+ }
+ }
+ /* Rest should have sampling factors 1,1 */
+ for (ci = 1; ci < sp->cinfo.d.num_components; ci++) {
+ if (sp->cinfo.d.comp_info[ci].h_samp_factor != 1 ||
+ sp->cinfo.d.comp_info[ci].v_samp_factor != 1) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors");
+ return (0);
+ }
+ }
+ } else {
+ /* PC 2's single component should have sampling factors 1,1 */
+ if (sp->cinfo.d.comp_info[0].h_samp_factor != 1 ||
+ sp->cinfo.d.comp_info[0].v_samp_factor != 1) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Improper JPEG sampling factors");
+ return (0);
+ }
+ }
+ downsampled_output = FALSE;
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+ sp->photometric == PHOTOMETRIC_YCBCR &&
+ sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+ /* Convert YCbCr to RGB */
+ sp->cinfo.d.jpeg_color_space = JCS_YCbCr;
+ sp->cinfo.d.out_color_space = JCS_RGB;
+ } else {
+ /* Suppress colorspace handling */
+ sp->cinfo.d.jpeg_color_space = JCS_UNKNOWN;
+ sp->cinfo.d.out_color_space = JCS_UNKNOWN;
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+ (sp->h_sampling != 1 || sp->v_sampling != 1))
+ downsampled_output = TRUE;
+ /* XXX what about up-sampling? */
+ }
+ if (downsampled_output) {
+ /* Need to use raw-data interface to libjpeg */
+ sp->cinfo.d.raw_data_out = TRUE;
+ tif->tif_decoderow = JPEGDecodeRaw;
+ tif->tif_decodestrip = JPEGDecodeRaw;
+ tif->tif_decodetile = JPEGDecodeRaw;
+ } else {
+ /* Use normal interface to libjpeg */
+ sp->cinfo.d.raw_data_out = FALSE;
+ tif->tif_decoderow = JPEGDecode;
+ tif->tif_decodestrip = JPEGDecode;
+ tif->tif_decodetile = JPEGDecode;
+ }
+ /* Start JPEG decompressor */
+ if (!TIFFjpeg_start_decompress(sp))
+ return (0);
+ /* Allocate downsampled-data buffers if needed */
+ if (downsampled_output) {
+ if (!alloc_downsampled_buffers(tif, sp->cinfo.d.comp_info,
+ sp->cinfo.d.num_components))
+ return (0);
+ sp->scancount = DCTSIZE; /* mark buffer empty */
+ }
+ return (1);
+}
+
+/*
+ * Decode a chunk of pixels.
+ * "Standard" case: returned data is not downsampled.
+ */
+/*ARGSUSED*/ static int
+JPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ tsize_t nrows;
+ (void) s;
+
+ nrows = cc / sp->bytesperline;
+ if (cc % sp->bytesperline)
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline not read");
+
+ if( nrows > (int) sp->cinfo.d.image_height )
+ nrows = sp->cinfo.d.image_height;
+
+ /* data is expected to be read in multiples of a scanline */
+ if (nrows)
+ {
+ JSAMPROW line_work_buf = NULL;
+
+ /*
+ ** For 6B, only use temporary buffer for 12 bit imagery.
+ ** For Mk1 always use it.
+ */
+#if !defined(JPEG_LIB_MK1)
+ if( sp->cinfo.d.data_precision == 12 )
+#endif
+ {
+ line_work_buf = (JSAMPROW)
+ _TIFFmalloc(sizeof(short) * sp->cinfo.d.output_width
+ * sp->cinfo.d.num_components );
+ }
+
+ do {
+ if( line_work_buf != NULL )
+ {
+ /*
+ ** In the MK1 case, we aways read into a 16bit buffer, and then
+ ** pack down to 12bit or 8bit. In 6B case we only read into 16
+ ** bit buffer for 12bit data, which we need to repack.
+ */
+ if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1)
+ return (0);
+
+ if( sp->cinfo.d.data_precision == 12 )
+ {
+ int value_pairs = (sp->cinfo.d.output_width
+ * sp->cinfo.d.num_components) / 2;
+ int iPair;
+
+ for( iPair = 0; iPair < value_pairs; iPair++ )
+ {
+ unsigned char *out_ptr =
+ ((unsigned char *) buf) + iPair * 3;
+ JSAMPLE *in_ptr = line_work_buf + iPair * 2;
+
+ out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
+ out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
+ | ((in_ptr[1] & 0xf00) >> 8);
+ out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
+ }
+ }
+ else if( sp->cinfo.d.data_precision == 8 )
+ {
+ int value_count = (sp->cinfo.d.output_width
+ * sp->cinfo.d.num_components);
+ int iValue;
+
+ for( iValue = 0; iValue < value_count; iValue++ )
+ {
+ ((unsigned char *) buf)[iValue] =
+ line_work_buf[iValue] & 0xff;
+ }
+ }
+ }
+ else
+ {
+ /*
+ ** In the libjpeg6b 8bit case. We read directly into the
+ ** TIFF buffer.
+ */
+ JSAMPROW bufptr = (JSAMPROW)buf;
+
+ if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1)
+ return (0);
+ }
+
+ ++tif->tif_row;
+ buf += sp->bytesperline;
+ cc -= sp->bytesperline;
+ } while (--nrows > 0);
+
+ if( line_work_buf != NULL )
+ _TIFFfree( line_work_buf );
+ }
+
+ /* Close down the decompressor if we've finished the strip or tile. */
+ return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
+ || TIFFjpeg_finish_decompress(sp);
+}
+
+/*
+ * Decode a chunk of pixels.
+ * Returned data is downsampled per sampling factors.
+ */
+/*ARGSUSED*/ static int
+JPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ tsize_t nrows;
+ (void) s;
+
+ /* data is expected to be read in multiples of a scanline */
+ if ( (nrows = sp->cinfo.d.image_height) ) {
+ /* Cb,Cr both have sampling factors 1, so this is correct */
+ JDIMENSION clumps_per_line = sp->cinfo.d.comp_info[1].downsampled_width;
+ int samples_per_clump = sp->samplesperclump;
+
+#ifdef JPEG_LIB_MK1
+ unsigned short* tmpbuf = _TIFFmalloc(sizeof(unsigned short) *
+ sp->cinfo.d.output_width *
+ sp->cinfo.d.num_components);
+#endif
+
+ do {
+ jpeg_component_info *compptr;
+ int ci, clumpoffset;
+
+ /* Reload downsampled-data buffer if needed */
+ if (sp->scancount >= DCTSIZE) {
+ int n = sp->cinfo.d.max_v_samp_factor * DCTSIZE;
+ if (TIFFjpeg_read_raw_data(sp, sp->ds_buffer, n) != n)
+ return (0);
+ sp->scancount = 0;
+ }
+ /*
+ * Fastest way to unseparate data is to make one pass
+ * over the scanline for each row of each component.
+ */
+ clumpoffset = 0; /* first sample in clump */
+ for (ci = 0, compptr = sp->cinfo.d.comp_info;
+ ci < sp->cinfo.d.num_components;
+ ci++, compptr++) {
+ int hsamp = compptr->h_samp_factor;
+ int vsamp = compptr->v_samp_factor;
+ int ypos;
+
+ for (ypos = 0; ypos < vsamp; ypos++) {
+ JSAMPLE *inptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
+#ifdef JPEG_LIB_MK1
+ JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;
+#else
+ JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
+#endif
+ JDIMENSION nclump;
+
+ if (hsamp == 1) {
+ /* fast path for at least Cb and Cr */
+ for (nclump = clumps_per_line; nclump-- > 0; ) {
+ outptr[0] = *inptr++;
+ outptr += samples_per_clump;
+ }
+ } else {
+ int xpos;
+
+ /* general case */
+ for (nclump = clumps_per_line; nclump-- > 0; ) {
+ for (xpos = 0; xpos < hsamp; xpos++)
+ outptr[xpos] = *inptr++;
+ outptr += samples_per_clump;
+ }
+ }
+ clumpoffset += hsamp;
+ }
+ }
+
+#ifdef JPEG_LIB_MK1
+ {
+ if (sp->cinfo.d.data_precision == 8)
+ {
+ int i=0;
+ int len = sp->cinfo.d.output_width * sp->cinfo.d.num_components;
+ for (i=0; i<len; i++)
+ {
+ ((unsigned char*)buf)[i] = tmpbuf[i] & 0xff;
+ }
+ }
+ else
+ { // 12-bit
+ int value_pairs = (sp->cinfo.d.output_width
+ * sp->cinfo.d.num_components) / 2;
+ int iPair;
+ for( iPair = 0; iPair < value_pairs; iPair++ )
+ {
+ unsigned char *out_ptr = ((unsigned char *) buf) + iPair * 3;
+ JSAMPLE *in_ptr = tmpbuf + iPair * 2;
+ out_ptr[0] = (in_ptr[0] & 0xff0) >> 4;
+ out_ptr[1] = ((in_ptr[0] & 0xf) << 4)
+ | ((in_ptr[1] & 0xf00) >> 8);
+ out_ptr[2] = ((in_ptr[1] & 0xff) >> 0);
+ }
+ }
+ }
+#endif
+
+ sp->scancount ++;
+ tif->tif_row += sp->v_sampling;
+ /* increment/decrement of buf and cc is still incorrect, but should not matter
+ * TODO: resolve this */
+ buf += sp->bytesperline;
+ cc -= sp->bytesperline;
+ nrows -= sp->v_sampling;
+ } while (nrows > 0);
+
+#ifdef JPEG_LIB_MK1
+ _TIFFfree(tmpbuf);
+#endif
+
+ }
+
+ /* Close down the decompressor if done. */
+ return sp->cinfo.d.output_scanline < sp->cinfo.d.output_height
+ || TIFFjpeg_finish_decompress(sp);
+}
+
+
+/*
+ * JPEG Encoding.
+ */
+
+static void
+unsuppress_quant_table (JPEGState* sp, int tblno)
+{
+ JQUANT_TBL* qtbl;
+
+ if ((qtbl = sp->cinfo.c.quant_tbl_ptrs[tblno]) != NULL)
+ qtbl->sent_table = FALSE;
+}
+
+static void
+unsuppress_huff_table (JPEGState* sp, int tblno)
+{
+ JHUFF_TBL* htbl;
+
+ if ((htbl = sp->cinfo.c.dc_huff_tbl_ptrs[tblno]) != NULL)
+ htbl->sent_table = FALSE;
+ if ((htbl = sp->cinfo.c.ac_huff_tbl_ptrs[tblno]) != NULL)
+ htbl->sent_table = FALSE;
+}
+
+static int
+prepare_JPEGTables(TIFF* tif)
+{
+ JPEGState* sp = JState(tif);
+
+ JPEGInitializeLibJPEG( tif, 0, 0 );
+
+ /* Initialize quant tables for current quality setting */
+ if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
+ return (0);
+ /* Mark only the tables we want for output */
+ /* NB: chrominance tables are currently used only with YCbCr */
+ if (!TIFFjpeg_suppress_tables(sp, TRUE))
+ return (0);
+ if (sp->jpegtablesmode & JPEGTABLESMODE_QUANT) {
+ unsuppress_quant_table(sp, 0);
+ if (sp->photometric == PHOTOMETRIC_YCBCR)
+ unsuppress_quant_table(sp, 1);
+ }
+ if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF) {
+ unsuppress_huff_table(sp, 0);
+ if (sp->photometric == PHOTOMETRIC_YCBCR)
+ unsuppress_huff_table(sp, 1);
+ }
+ /* Direct libjpeg output into jpegtables */
+ if (!TIFFjpeg_tables_dest(sp, tif))
+ return (0);
+ /* Emit tables-only datastream */
+ if (!TIFFjpeg_write_tables(sp))
+ return (0);
+
+ return (1);
+}
+
+static int
+JPEGSetupEncode(TIFF* tif)
+{
+ JPEGState* sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+ static const char module[] = "JPEGSetupEncode";
+
+ JPEGInitializeLibJPEG( tif, 1, 0 );
+
+ assert(sp != NULL);
+ assert(!sp->cinfo.comm.is_decompressor);
+
+ /*
+ * Initialize all JPEG parameters to default values.
+ * Note that jpeg_set_defaults needs legal values for
+ * in_color_space and input_components.
+ */
+ sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+ sp->cinfo.c.input_components = 1;
+ if (!TIFFjpeg_set_defaults(sp))
+ return (0);
+ /* Set per-file parameters */
+ sp->photometric = td->td_photometric;
+ switch (sp->photometric) {
+ case PHOTOMETRIC_YCBCR:
+ sp->h_sampling = td->td_ycbcrsubsampling[0];
+ sp->v_sampling = td->td_ycbcrsubsampling[1];
+ /*
+ * A ReferenceBlackWhite field *must* be present since the
+ * default value is inappropriate for YCbCr. Fill in the
+ * proper value if application didn't set it.
+ */
+ {
+ float *ref;
+ if (!TIFFGetField(tif, TIFFTAG_REFERENCEBLACKWHITE,
+ &ref)) {
+ float refbw[6];
+ long top = 1L << td->td_bitspersample;
+ refbw[0] = 0;
+ refbw[1] = (float)(top-1L);
+ refbw[2] = (float)(top>>1);
+ refbw[3] = refbw[1];
+ refbw[4] = refbw[2];
+ refbw[5] = refbw[1];
+ TIFFSetField(tif, TIFFTAG_REFERENCEBLACKWHITE,
+ refbw);
+ }
+ }
+ break;
+ case PHOTOMETRIC_PALETTE: /* disallowed by Tech Note */
+ case PHOTOMETRIC_MASK:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "PhotometricInterpretation %d not allowed for JPEG",
+ (int) sp->photometric);
+ return (0);
+ default:
+ /* TIFF 6.0 forbids subsampling of all other color spaces */
+ sp->h_sampling = 1;
+ sp->v_sampling = 1;
+ break;
+ }
+
+ /* Verify miscellaneous parameters */
+
+ /*
+ * This would need work if libtiff ever supports different
+ * depths for different components, or if libjpeg ever supports
+ * run-time selection of depth. Neither is imminent.
+ */
+#ifdef JPEG_LIB_MK1
+ /* BITS_IN_JSAMPLE now permits 8 and 12 --- dgilbert */
+ if (td->td_bitspersample != 8 && td->td_bitspersample != 12)
+#else
+ if (td->td_bitspersample != BITS_IN_JSAMPLE )
+#endif
+ {
+ TIFFErrorExt(tif->tif_clientdata, module, "BitsPerSample %d not allowed for JPEG",
+ (int) td->td_bitspersample);
+ return (0);
+ }
+ sp->cinfo.c.data_precision = td->td_bitspersample;
+#ifdef JPEG_LIB_MK1
+ sp->cinfo.c.bits_in_jsample = td->td_bitspersample;
+#endif
+ if (isTiled(tif)) {
+ if ((td->td_tilelength % (sp->v_sampling * DCTSIZE)) != 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "JPEG tile height must be multiple of %d",
+ sp->v_sampling * DCTSIZE);
+ return (0);
+ }
+ if ((td->td_tilewidth % (sp->h_sampling * DCTSIZE)) != 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "JPEG tile width must be multiple of %d",
+ sp->h_sampling * DCTSIZE);
+ return (0);
+ }
+ } else {
+ if (td->td_rowsperstrip < td->td_imagelength &&
+ (td->td_rowsperstrip % (sp->v_sampling * DCTSIZE)) != 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "RowsPerStrip must be multiple of %d for JPEG",
+ sp->v_sampling * DCTSIZE);
+ return (0);
+ }
+ }
+
+ /* Create a JPEGTables field if appropriate */
+ if (sp->jpegtablesmode & (JPEGTABLESMODE_QUANT|JPEGTABLESMODE_HUFF)) {
+ if (!prepare_JPEGTables(tif))
+ return (0);
+ /* Mark the field present */
+ /* Can't use TIFFSetField since BEENWRITING is already set! */
+ TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ } else {
+ /* We do not support application-supplied JPEGTables, */
+ /* so mark the field not present */
+ TIFFClrFieldBit(tif, FIELD_JPEGTABLES);
+ }
+
+ /* Direct libjpeg output to libtiff's output buffer */
+ TIFFjpeg_data_dest(sp, tif);
+
+ return (1);
+}
+
+/*
+ * Set encoding state at the start of a strip or tile.
+ */
+static int
+JPEGPreEncode(TIFF* tif, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+ static const char module[] = "JPEGPreEncode";
+ uint32 segment_width, segment_height;
+ int downsampled_input;
+
+ assert(sp != NULL);
+ assert(!sp->cinfo.comm.is_decompressor);
+ /*
+ * Set encoding parameters for this strip/tile.
+ */
+ if (isTiled(tif)) {
+ segment_width = td->td_tilewidth;
+ segment_height = td->td_tilelength;
+ sp->bytesperline = TIFFTileRowSize(tif);
+ } else {
+ segment_width = td->td_imagewidth;
+ segment_height = td->td_imagelength - tif->tif_row;
+ if (segment_height > td->td_rowsperstrip)
+ segment_height = td->td_rowsperstrip;
+ sp->bytesperline = TIFFOldScanlineSize(tif);
+ }
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE && s > 0) {
+ /* for PC 2, scale down the strip/tile size
+ * to match a downsampled component
+ */
+ segment_width = TIFFhowmany(segment_width, sp->h_sampling);
+ segment_height = TIFFhowmany(segment_height, sp->v_sampling);
+ }
+ if (segment_width > 65535 || segment_height > 65535) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Strip/tile too large for JPEG");
+ return (0);
+ }
+ sp->cinfo.c.image_width = segment_width;
+ sp->cinfo.c.image_height = segment_height;
+ downsampled_input = FALSE;
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ sp->cinfo.c.input_components = td->td_samplesperpixel;
+ if (sp->photometric == PHOTOMETRIC_YCBCR) {
+ if (sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+ sp->cinfo.c.in_color_space = JCS_RGB;
+ } else {
+ sp->cinfo.c.in_color_space = JCS_YCbCr;
+ if (sp->h_sampling != 1 || sp->v_sampling != 1)
+ downsampled_input = TRUE;
+ }
+ if (!TIFFjpeg_set_colorspace(sp, JCS_YCbCr))
+ return (0);
+ /*
+ * Set Y sampling factors;
+ * we assume jpeg_set_colorspace() set the rest to 1
+ */
+ sp->cinfo.c.comp_info[0].h_samp_factor = sp->h_sampling;
+ sp->cinfo.c.comp_info[0].v_samp_factor = sp->v_sampling;
+ } else {
+ sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+ if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
+ return (0);
+ /* jpeg_set_colorspace set all sampling factors to 1 */
+ }
+ } else {
+ sp->cinfo.c.input_components = 1;
+ sp->cinfo.c.in_color_space = JCS_UNKNOWN;
+ if (!TIFFjpeg_set_colorspace(sp, JCS_UNKNOWN))
+ return (0);
+ sp->cinfo.c.comp_info[0].component_id = s;
+ /* jpeg_set_colorspace() set sampling factors to 1 */
+ if (sp->photometric == PHOTOMETRIC_YCBCR && s > 0) {
+ sp->cinfo.c.comp_info[0].quant_tbl_no = 1;
+ sp->cinfo.c.comp_info[0].dc_tbl_no = 1;
+ sp->cinfo.c.comp_info[0].ac_tbl_no = 1;
+ }
+ }
+ /* ensure libjpeg won't write any extraneous markers */
+ sp->cinfo.c.write_JFIF_header = FALSE;
+ sp->cinfo.c.write_Adobe_marker = FALSE;
+ /* set up table handling correctly */
+ if (! (sp->jpegtablesmode & JPEGTABLESMODE_QUANT)) {
+ if (!TIFFjpeg_set_quality(sp, sp->jpegquality, FALSE))
+ return (0);
+ unsuppress_quant_table(sp, 0);
+ unsuppress_quant_table(sp, 1);
+ }
+ if (sp->jpegtablesmode & JPEGTABLESMODE_HUFF)
+ sp->cinfo.c.optimize_coding = FALSE;
+ else
+ sp->cinfo.c.optimize_coding = TRUE;
+ if (downsampled_input) {
+ /* Need to use raw-data interface to libjpeg */
+ sp->cinfo.c.raw_data_in = TRUE;
+ tif->tif_encoderow = JPEGEncodeRaw;
+ tif->tif_encodestrip = JPEGEncodeRaw;
+ tif->tif_encodetile = JPEGEncodeRaw;
+ } else {
+ /* Use normal interface to libjpeg */
+ sp->cinfo.c.raw_data_in = FALSE;
+ tif->tif_encoderow = JPEGEncode;
+ tif->tif_encodestrip = JPEGEncode;
+ tif->tif_encodetile = JPEGEncode;
+ }
+ /* Start JPEG compressor */
+ if (!TIFFjpeg_start_compress(sp, FALSE))
+ return (0);
+ /* Allocate downsampled-data buffers if needed */
+ if (downsampled_input) {
+ if (!alloc_downsampled_buffers(tif, sp->cinfo.c.comp_info,
+ sp->cinfo.c.num_components))
+ return (0);
+ }
+ sp->scancount = 0;
+
+ return (1);
+}
+
+/*
+ * Encode a chunk of pixels.
+ * "Standard" case: incoming data is not downsampled.
+ */
+static int
+JPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ tsize_t nrows;
+ JSAMPROW bufptr[1];
+
+ (void) s;
+ assert(sp != NULL);
+ /* data is expected to be supplied in multiples of a scanline */
+ nrows = cc / sp->bytesperline;
+ if (cc % sp->bytesperline)
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded");
+
+ /* The last strip will be limited to image size */
+ if( !isTiled(tif) && tif->tif_row+nrows > tif->tif_dir.td_imagelength )
+ nrows = tif->tif_dir.td_imagelength - tif->tif_row;
+
+ while (nrows-- > 0) {
+ bufptr[0] = (JSAMPROW) buf;
+ if (TIFFjpeg_write_scanlines(sp, bufptr, 1) != 1)
+ return (0);
+ if (nrows > 0)
+ tif->tif_row++;
+ buf += sp->bytesperline;
+ }
+ return (1);
+}
+
+/*
+ * Encode a chunk of pixels.
+ * Incoming data is expected to be downsampled per sampling factors.
+ */
+static int
+JPEGEncodeRaw(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ JPEGState *sp = JState(tif);
+ JSAMPLE* inptr;
+ JSAMPLE* outptr;
+ tsize_t nrows;
+ JDIMENSION clumps_per_line, nclump;
+ int clumpoffset, ci, xpos, ypos;
+ jpeg_component_info* compptr;
+ int samples_per_clump = sp->samplesperclump;
+ tsize_t bytesperclumpline;
+
+ (void) s;
+ assert(sp != NULL);
+ /* data is expected to be supplied in multiples of a clumpline */
+ /* a clumpline is equivalent to v_sampling desubsampled scanlines */
+ /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */
+ bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)
+ *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
+ /8;
+
+ nrows = ( cc / bytesperclumpline ) * sp->v_sampling;
+ if (cc % bytesperclumpline)
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name, "fractional scanline discarded");
+
+ /* Cb,Cr both have sampling factors 1, so this is correct */
+ clumps_per_line = sp->cinfo.c.comp_info[1].downsampled_width;
+
+ while (nrows > 0) {
+ /*
+ * Fastest way to separate the data is to make one pass
+ * over the scanline for each row of each component.
+ */
+ clumpoffset = 0; /* first sample in clump */
+ for (ci = 0, compptr = sp->cinfo.c.comp_info;
+ ci < sp->cinfo.c.num_components;
+ ci++, compptr++) {
+ int hsamp = compptr->h_samp_factor;
+ int vsamp = compptr->v_samp_factor;
+ int padding = (int) (compptr->width_in_blocks * DCTSIZE -
+ clumps_per_line * hsamp);
+ for (ypos = 0; ypos < vsamp; ypos++) {
+ inptr = ((JSAMPLE*) buf) + clumpoffset;
+ outptr = sp->ds_buffer[ci][sp->scancount*vsamp + ypos];
+ if (hsamp == 1) {
+ /* fast path for at least Cb and Cr */
+ for (nclump = clumps_per_line; nclump-- > 0; ) {
+ *outptr++ = inptr[0];
+ inptr += samples_per_clump;
+ }
+ } else {
+ /* general case */
+ for (nclump = clumps_per_line; nclump-- > 0; ) {
+ for (xpos = 0; xpos < hsamp; xpos++)
+ *outptr++ = inptr[xpos];
+ inptr += samples_per_clump;
+ }
+ }
+ /* pad each scanline as needed */
+ for (xpos = 0; xpos < padding; xpos++) {
+ *outptr = outptr[-1];
+ outptr++;
+ }
+ clumpoffset += hsamp;
+ }
+ }
+ sp->scancount++;
+ if (sp->scancount >= DCTSIZE) {
+ int n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
+ if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
+ return (0);
+ sp->scancount = 0;
+ }
+ tif->tif_row += sp->v_sampling;
+ buf += sp->bytesperline;
+ nrows -= sp->v_sampling;
+ }
+ return (1);
+}
+
+/*
+ * Finish up at the end of a strip or tile.
+ */
+static int
+JPEGPostEncode(TIFF* tif)
+{
+ JPEGState *sp = JState(tif);
+
+ if (sp->scancount > 0) {
+ /*
+ * Need to emit a partial bufferload of downsampled data.
+ * Pad the data vertically.
+ */
+ int ci, ypos, n;
+ jpeg_component_info* compptr;
+
+ for (ci = 0, compptr = sp->cinfo.c.comp_info;
+ ci < sp->cinfo.c.num_components;
+ ci++, compptr++) {
+ int vsamp = compptr->v_samp_factor;
+ tsize_t row_width = compptr->width_in_blocks * DCTSIZE
+ * sizeof(JSAMPLE);
+ for (ypos = sp->scancount * vsamp;
+ ypos < DCTSIZE * vsamp; ypos++) {
+ _TIFFmemcpy((tdata_t)sp->ds_buffer[ci][ypos],
+ (tdata_t)sp->ds_buffer[ci][ypos-1],
+ row_width);
+
+ }
+ }
+ n = sp->cinfo.c.max_v_samp_factor * DCTSIZE;
+ if (TIFFjpeg_write_raw_data(sp, sp->ds_buffer, n) != n)
+ return (0);
+ }
+
+ return (TIFFjpeg_finish_compress(JState(tif)));
+}
+
+static void
+JPEGCleanup(TIFF* tif)
+{
+ JPEGState *sp = JState(tif);
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+ tif->tif_tagmethods.printdir = sp->printdir;
+
+ if( sp->cinfo_initialized )
+ TIFFjpeg_destroy(sp); /* release libjpeg resources */
+ if (sp->jpegtables) /* tag value */
+ _TIFFfree(sp->jpegtables);
+ _TIFFfree(tif->tif_data); /* release local state */
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static void
+JPEGResetUpsampled( TIFF* tif )
+{
+ JPEGState* sp = JState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ /*
+ * Mark whether returned data is up-sampled or not so TIFFStripSize
+ * and TIFFTileSize return values that reflect the true amount of
+ * data.
+ */
+ tif->tif_flags &= ~TIFF_UPSAMPLED;
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ if (td->td_photometric == PHOTOMETRIC_YCBCR &&
+ sp->jpegcolormode == JPEGCOLORMODE_RGB) {
+ tif->tif_flags |= TIFF_UPSAMPLED;
+ } else {
+#ifdef notdef
+ if (td->td_ycbcrsubsampling[0] != 1 ||
+ td->td_ycbcrsubsampling[1] != 1)
+ ; /* XXX what about up-sampling? */
+#endif
+ }
+ }
+
+ /*
+ * Must recalculate cached tile size in case sampling state changed.
+ * Should we really be doing this now if image size isn't set?
+ */
+ tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+}
+
+static int
+JPEGVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ JPEGState* sp = JState(tif);
+ const TIFFFieldInfo* fip;
+ uint32 v32;
+
+ assert(sp != NULL);
+
+ switch (tag) {
+ case TIFFTAG_JPEGTABLES:
+ v32 = va_arg(ap, uint32);
+ if (v32 == 0) {
+ /* XXX */
+ return (0);
+ }
+ _TIFFsetByteArray(&sp->jpegtables, va_arg(ap, void*),
+ (long) v32);
+ sp->jpegtables_length = v32;
+ TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
+ break;
+ case TIFFTAG_JPEGQUALITY:
+ sp->jpegquality = va_arg(ap, int);
+ return (1); /* pseudo tag */
+ case TIFFTAG_JPEGCOLORMODE:
+ sp->jpegcolormode = va_arg(ap, int);
+ JPEGResetUpsampled( tif );
+ return (1); /* pseudo tag */
+ case TIFFTAG_PHOTOMETRIC:
+ {
+ int ret_value = (*sp->vsetparent)(tif, tag, ap);
+ JPEGResetUpsampled( tif );
+ return ret_value;
+ }
+ case TIFFTAG_JPEGTABLESMODE:
+ sp->jpegtablesmode = va_arg(ap, int);
+ return (1); /* pseudo tag */
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ /* mark the fact that we have a real ycbcrsubsampling! */
+ sp->ycbcrsampling_fetched = 1;
+ /* should we be recomputing upsampling info here? */
+ return (*sp->vsetparent)(tif, tag, ap);
+ case TIFFTAG_FAXRECVPARAMS:
+ sp->recvparams = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_FAXSUBADDRESS:
+ _TIFFsetString(&sp->subaddress, va_arg(ap, char*));
+ break;
+ case TIFFTAG_FAXRECVTIME:
+ sp->recvtime = va_arg(ap, uint32);
+ break;
+ case TIFFTAG_FAXDCS:
+ _TIFFsetString(&sp->faxdcs, va_arg(ap, char*));
+ break;
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+
+ if ((fip = _TIFFFieldWithTag(tif, tag))) {
+ TIFFSetFieldBit(tif, fip->field_bit);
+ } else {
+ return (0);
+ }
+
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ return (1);
+}
+
+/*
+ * Some JPEG-in-TIFF produces do not emit the YCBCRSUBSAMPLING values in
+ * the TIFF tags, but still use non-default (2,2) values within the jpeg
+ * data stream itself. In order for TIFF applications to work properly
+ * - for instance to get the strip buffer size right - it is imperative
+ * that the subsampling be available before we start reading the image
+ * data normally. This function will attempt to load the first strip in
+ * order to get the sampling values from the jpeg data stream. Various
+ * hacks are various places are done to ensure this function gets called
+ * before the td_ycbcrsubsampling values are used from the directory structure,
+ * including calling TIFFGetField() for the YCBCRSUBSAMPLING field from
+ * TIFFStripSize(), and the printing code in tif_print.c.
+ *
+ * Note that JPEGPreDeocode() will produce a fairly loud warning when the
+ * discovered sampling does not match the default sampling (2,2) or whatever
+ * was actually in the tiff tags.
+ *
+ * Problems:
+ * o This code will cause one whole strip/tile of compressed data to be
+ * loaded just to get the tags right, even if the imagery is never read.
+ * It would be more efficient to just load a bit of the header, and
+ * initialize things from that.
+ *
+ * See the bug in bugzilla for details:
+ *
+ * http://bugzilla.remotesensing.org/show_bug.cgi?id=168
+ *
+ * Frank Warmerdam, July 2002
+ */
+
+static void
+JPEGFixupTestSubsampling( TIFF * tif )
+{
+#ifdef CHECK_JPEG_YCBCR_SUBSAMPLING
+ JPEGState *sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+
+ JPEGInitializeLibJPEG( tif, 0, 0 );
+
+ /*
+ * Some JPEG-in-TIFF files don't provide the ycbcrsampling tags,
+ * and use a sampling schema other than the default 2,2. To handle
+ * this we actually have to scan the header of a strip or tile of
+ * jpeg data to get the sampling.
+ */
+ if( !sp->cinfo.comm.is_decompressor
+ || sp->ycbcrsampling_fetched
+ || td->td_photometric != PHOTOMETRIC_YCBCR )
+ return;
+
+ sp->ycbcrsampling_fetched = 1;
+ if( TIFFIsTiled( tif ) )
+ {
+ if( !TIFFFillTile( tif, 0 ) )
+ return;
+ }
+ else
+ {
+ if( !TIFFFillStrip( tif, 0 ) )
+ return;
+ }
+
+ TIFFSetField( tif, TIFFTAG_YCBCRSUBSAMPLING,
+ (uint16) sp->h_sampling, (uint16) sp->v_sampling );
+#endif /* CHECK_JPEG_YCBCR_SUBSAMPLING */
+}
+
+static int
+JPEGVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ JPEGState* sp = JState(tif);
+
+ assert(sp != NULL);
+
+ switch (tag) {
+ case TIFFTAG_JPEGTABLES:
+ *va_arg(ap, uint32*) = sp->jpegtables_length;
+ *va_arg(ap, void**) = sp->jpegtables;
+ break;
+ case TIFFTAG_JPEGQUALITY:
+ *va_arg(ap, int*) = sp->jpegquality;
+ break;
+ case TIFFTAG_JPEGCOLORMODE:
+ *va_arg(ap, int*) = sp->jpegcolormode;
+ break;
+ case TIFFTAG_JPEGTABLESMODE:
+ *va_arg(ap, int*) = sp->jpegtablesmode;
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ JPEGFixupTestSubsampling( tif );
+ return (*sp->vgetparent)(tif, tag, ap);
+ case TIFFTAG_FAXRECVPARAMS:
+ *va_arg(ap, uint32*) = sp->recvparams;
+ break;
+ case TIFFTAG_FAXSUBADDRESS:
+ *va_arg(ap, char**) = sp->subaddress;
+ break;
+ case TIFFTAG_FAXRECVTIME:
+ *va_arg(ap, uint32*) = sp->recvtime;
+ break;
+ case TIFFTAG_FAXDCS:
+ *va_arg(ap, char**) = sp->faxdcs;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return (1);
+}
+
+static void
+JPEGPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+ JPEGState* sp = JState(tif);
+
+ assert(sp != NULL);
+
+ (void) flags;
+ if (TIFFFieldSet(tif,FIELD_JPEGTABLES))
+ fprintf(fd, " JPEG Tables: (%lu bytes)\n",
+ (unsigned long) sp->jpegtables_length);
+ if (TIFFFieldSet(tif,FIELD_RECVPARAMS))
+ fprintf(fd, " Fax Receive Parameters: %08lx\n",
+ (unsigned long) sp->recvparams);
+ if (TIFFFieldSet(tif,FIELD_SUBADDRESS))
+ fprintf(fd, " Fax SubAddress: %s\n", sp->subaddress);
+ if (TIFFFieldSet(tif,FIELD_RECVTIME))
+ fprintf(fd, " Fax Receive Time: %lu secs\n",
+ (unsigned long) sp->recvtime);
+ if (TIFFFieldSet(tif,FIELD_FAXDCS))
+ fprintf(fd, " Fax DCS: %s\n", sp->faxdcs);
+}
+
+static uint32
+JPEGDefaultStripSize(TIFF* tif, uint32 s)
+{
+ JPEGState* sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+
+ s = (*sp->defsparent)(tif, s);
+ if (s < td->td_imagelength)
+ s = TIFFroundup(s, td->td_ycbcrsubsampling[1] * DCTSIZE);
+ return (s);
+}
+
+static void
+JPEGDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+ JPEGState* sp = JState(tif);
+ TIFFDirectory *td = &tif->tif_dir;
+
+ (*sp->deftparent)(tif, tw, th);
+ *tw = TIFFroundup(*tw, td->td_ycbcrsubsampling[0] * DCTSIZE);
+ *th = TIFFroundup(*th, td->td_ycbcrsubsampling[1] * DCTSIZE);
+}
+
+/*
+ * The JPEG library initialized used to be done in TIFFInitJPEG(), but
+ * now that we allow a TIFF file to be opened in update mode it is necessary
+ * to have some way of deciding whether compression or decompression is
+ * desired other than looking at tif->tif_mode. We accomplish this by
+ * examining {TILE/STRIP}BYTECOUNTS to see if there is a non-zero entry.
+ * If so, we assume decompression is desired.
+ *
+ * This is tricky, because TIFFInitJPEG() is called while the directory is
+ * being read, and generally speaking the BYTECOUNTS tag won't have been read
+ * at that point. So we try to defer jpeg library initialization till we
+ * do have that tag ... basically any access that might require the compressor
+ * or decompressor that occurs after the reading of the directory.
+ *
+ * In an ideal world compressors or decompressors would be setup
+ * at the point where a single tile or strip was accessed (for read or write)
+ * so that stuff like update of missing tiles, or replacement of tiles could
+ * be done. However, we aren't trying to crack that nut just yet ...
+ *
+ * NFW, Feb 3rd, 2003.
+ */
+
+static int JPEGInitializeLibJPEG( TIFF * tif, int force_encode, int force_decode )
+{
+ JPEGState* sp = JState(tif);
+ uint32 *byte_counts = NULL;
+ int data_is_empty = TRUE;
+ int decompress;
+
+
+ if(sp->cinfo_initialized)
+ {
+ if( force_encode && sp->cinfo.comm.is_decompressor )
+ TIFFjpeg_destroy( sp );
+ else if( force_decode && !sp->cinfo.comm.is_decompressor )
+ TIFFjpeg_destroy( sp );
+ else
+ return 1;
+
+ sp->cinfo_initialized = 0;
+ }
+
+ /*
+ * Do we have tile data already? Make sure we initialize the
+ * the state in decompressor mode if we have tile data, even if we
+ * are not in read-only file access mode.
+ */
+ if( TIFFIsTiled( tif )
+ && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &byte_counts )
+ && byte_counts != NULL )
+ {
+ data_is_empty = byte_counts[0] == 0;
+ }
+ if( !TIFFIsTiled( tif )
+ && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &byte_counts)
+ && byte_counts != NULL )
+ {
+ data_is_empty = byte_counts[0] == 0;
+ }
+
+ if( force_decode )
+ decompress = 1;
+ else if( force_encode )
+ decompress = 0;
+ else if( tif->tif_mode == O_RDONLY )
+ decompress = 1;
+ else if( data_is_empty )
+ decompress = 0;
+ else
+ decompress = 1;
+
+ /*
+ * Initialize libjpeg.
+ */
+ if ( decompress ) {
+ if (!TIFFjpeg_create_decompress(sp))
+ return (0);
+
+ } else {
+ if (!TIFFjpeg_create_compress(sp))
+ return (0);
+ }
+
+ sp->cinfo_initialized = TRUE;
+
+ return 1;
+}
+
+int
+TIFFInitJPEG(TIFF* tif, int scheme)
+{
+ JPEGState* sp;
+
+ assert(scheme == COMPRESSION_JPEG);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, jpegFieldInfo, N(jpegFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata,
+ "TIFFInitJPEG",
+ "Merging JPEG codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (JPEGState));
+
+ if (tif->tif_data == NULL) {
+ TIFFErrorExt(tif->tif_clientdata,
+ "TIFFInitJPEG", "No space for JPEG state block");
+ return 0;
+ }
+ _TIFFmemset(tif->tif_data, 0, sizeof(JPEGState));
+
+ sp = JState(tif);
+ sp->tif = tif; /* back link */
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = JPEGVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = JPEGVSetField; /* hook for codec tags */
+ sp->printdir = tif->tif_tagmethods.printdir;
+ tif->tif_tagmethods.printdir = JPEGPrintDir; /* hook for codec tags */
+
+ /* Default values for codec-specific fields */
+ sp->jpegtables = NULL;
+ sp->jpegtables_length = 0;
+ sp->jpegquality = 75; /* Default IJG quality */
+ sp->jpegcolormode = JPEGCOLORMODE_RAW;
+ sp->jpegtablesmode = JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF;
+
+ sp->recvparams = 0;
+ sp->subaddress = NULL;
+ sp->faxdcs = NULL;
+
+ sp->ycbcrsampling_fetched = 0;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = JPEGSetupDecode;
+ tif->tif_predecode = JPEGPreDecode;
+ tif->tif_decoderow = JPEGDecode;
+ tif->tif_decodestrip = JPEGDecode;
+ tif->tif_decodetile = JPEGDecode;
+ tif->tif_setupencode = JPEGSetupEncode;
+ tif->tif_preencode = JPEGPreEncode;
+ tif->tif_postencode = JPEGPostEncode;
+ tif->tif_encoderow = JPEGEncode;
+ tif->tif_encodestrip = JPEGEncode;
+ tif->tif_encodetile = JPEGEncode;
+ tif->tif_cleanup = JPEGCleanup;
+ sp->defsparent = tif->tif_defstripsize;
+ tif->tif_defstripsize = JPEGDefaultStripSize;
+ sp->deftparent = tif->tif_deftilesize;
+ tif->tif_deftilesize = JPEGDefaultTileSize;
+ tif->tif_flags |= TIFF_NOBITREV; /* no bit reversal, please */
+
+ sp->cinfo_initialized = FALSE;
+
+ /*
+ ** Create a JPEGTables field if no directory has yet been created.
+ ** We do this just to ensure that sufficient space is reserved for
+ ** the JPEGTables field. It will be properly created the right
+ ** size later.
+ */
+ if( tif->tif_diroff == 0 )
+ {
+#define SIZE_OF_JPEGTABLES 2000
+ TIFFSetFieldBit(tif, FIELD_JPEGTABLES);
+ sp->jpegtables_length = SIZE_OF_JPEGTABLES;
+ sp->jpegtables = (void *) _TIFFmalloc(sp->jpegtables_length);
+ _TIFFmemset(sp->jpegtables, 0, SIZE_OF_JPEGTABLES);
+#undef SIZE_OF_JPEGTABLES
+ }
+
+ /*
+ * Mark the TIFFTAG_YCBCRSAMPLES as present even if it is not
+ * see: JPEGFixupTestSubsampling().
+ */
+ TIFFSetFieldBit( tif, FIELD_YCBCRSUBSAMPLING );
+
+ return 1;
+}
+#endif /* JPEG_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
+
diff --git a/Source/LibTIFF/tif_luv.c b/Source/LibTIFF/tif_luv.c
new file mode 100644
index 0000000..004d85b
--- /dev/null
+++ b/Source/LibTIFF/tif_luv.c
@@ -0,0 +1,1622 @@
+/* $Id: tif_luv.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1997 Greg Ward Larson
+ * Copyright (c) 1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
+ * advertising or publicity relating to the software without the specific,
+ * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
+ * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef LOGLUV_SUPPORT
+
+/*
+ * TIFF Library.
+ * LogLuv compression support for high dynamic range images.
+ *
+ * Contributed by Greg Larson.
+ *
+ * LogLuv image support uses the TIFF library to store 16 or 10-bit
+ * log luminance values with 8 bits each of u and v or a 14-bit index.
+ *
+ * The codec can take as input and produce as output 32-bit IEEE float values
+ * as well as 16-bit integer values. A 16-bit luminance is interpreted
+ * as a sign bit followed by a 15-bit integer that is converted
+ * to and from a linear magnitude using the transformation:
+ *
+ * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit
+ *
+ * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real
+ *
+ * The actual conversion to world luminance units in candelas per sq. meter
+ * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
+ * This value is usually set such that a reasonable exposure comes from
+ * clamping decoded luminances above 1 to 1 in the displayed image.
+ *
+ * The 16-bit values for u and v may be converted to real values by dividing
+ * each by 32768. (This allows for negative values, which aren't useful as
+ * far as we know, but are left in case of future improvements in human
+ * color vision.)
+ *
+ * Conversion from (u,v), which is actually the CIE (u',v') system for
+ * you color scientists, is accomplished by the following transformation:
+ *
+ * u = 4*x / (-2*x + 12*y + 3)
+ * v = 9*y / (-2*x + 12*y + 3)
+ *
+ * x = 9*u / (6*u - 16*v + 12)
+ * y = 4*v / (6*u - 16*v + 12)
+ *
+ * This process is greatly simplified by passing 32-bit IEEE floats
+ * for each of three CIE XYZ coordinates. The codec then takes care
+ * of conversion to and from LogLuv, though the application is still
+ * responsible for interpreting the TIFFTAG_STONITS calibration factor.
+ *
+ * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white
+ * point of (x,y)=(1/3,1/3). However, most color systems assume some other
+ * white point, such as D65, and an absolute color conversion to XYZ then
+ * to another color space with a different white point may introduce an
+ * unwanted color cast to the image. It is often desirable, therefore, to
+ * perform a white point conversion that maps the input white to [1 1 1]
+ * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT
+ * tag value. A decoder that demands absolute color calibration may use
+ * this white point tag to get back the original colors, but usually it
+ * will be ignored and the new white point will be used instead that
+ * matches the output color space.
+ *
+ * Pixel information is compressed into one of two basic encodings, depending
+ * on the setting of the compression tag, which is one of COMPRESSION_SGILOG
+ * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is
+ * stored as:
+ *
+ * 1 15
+ * |-+---------------|
+ *
+ * COMPRESSION_SGILOG color data is stored as:
+ *
+ * 1 15 8 8
+ * |-+---------------|--------+--------|
+ * S Le ue ve
+ *
+ * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
+ *
+ * 10 14
+ * |----------|--------------|
+ * Le' Ce
+ *
+ * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
+ * encoded as an index for optimal color resolution. The 10 log bits are
+ * defined by the following conversions:
+ *
+ * L = 2^((Le'+.5)/64 - 12) # real from 10-bit
+ *
+ * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real
+ *
+ * The 10 bits of the smaller format may be converted into the 15 bits of
+ * the larger format by multiplying by 4 and adding 13314. Obviously,
+ * a smaller range of magnitudes is covered (about 5 orders of magnitude
+ * instead of 38), and the lack of a sign bit means that negative luminances
+ * are not allowed. (Well, they aren't allowed in the real world, either,
+ * but they are useful for certain types of image processing.)
+ *
+ * The desired user format is controlled by the setting the internal
+ * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
+ * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values
+ * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v
+ * Raw data i/o is also possible using:
+ * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel
+ * In addition, the following decoding is provided for ease of display:
+ * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values
+ *
+ * For grayscale images, we provide the following data formats:
+ * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values
+ * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance
+ * SGILOGDATAFMT_8BIT = 8-bit gray monitor values
+ *
+ * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
+ * scheme by separating the logL, u and v bytes for each row and applying
+ * a PackBits type of compression. Since the 24-bit encoding is not
+ * adaptive, the 32-bit color format takes less space in many cases.
+ *
+ * Further control is provided over the conversion from higher-resolution
+ * formats to final encoded values through the pseudo tag
+ * TIFFTAG_SGILOGENCODE:
+ * SGILOGENCODE_NODITHER = do not dither encoded values
+ * SGILOGENCODE_RANDITHER = apply random dithering during encoding
+ *
+ * The default value of this tag is SGILOGENCODE_NODITHER for
+ * COMPRESSION_SGILOG to maximize run-length encoding and
+ * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn
+ * quantization errors into noise.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/*
+ * State block for each open TIFF
+ * file using LogLuv compression/decompression.
+ */
+typedef struct logLuvState LogLuvState;
+
+struct logLuvState {
+ int user_datafmt; /* user data format */
+ int encode_meth; /* encoding method */
+ int pixel_size; /* bytes per pixel */
+
+ tidata_t* tbuf; /* translation buffer */
+ int tbuflen; /* buffer length */
+ void (*tfunc)(LogLuvState*, tidata_t, int);
+
+ TIFFVSetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+};
+
+#define DecoderState(tif) ((LogLuvState*) (tif)->tif_data)
+#define EncoderState(tif) ((LogLuvState*) (tif)->tif_data)
+
+#define SGILOGDATAFMT_UNKNOWN -1
+
+#define MINRUN 4 /* minimum run length */
+
+/*
+ * Decode a string of 16-bit gray pixels.
+ */
+static int
+LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ LogLuvState* sp = DecoderState(tif);
+ int shft, i, npixels;
+ unsigned char* bp;
+ int16* tp;
+ int16 b;
+ int cc, rc;
+
+ assert(s == 0);
+ assert(sp != NULL);
+
+ npixels = occ / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
+ tp = (int16*) op;
+ else {
+ assert(sp->tbuflen >= npixels);
+ tp = (int16*) sp->tbuf;
+ }
+ _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
+
+ bp = (unsigned char*) tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ /* get each byte string */
+ for (shft = 2*8; (shft -= 8) >= 0; ) {
+ for (i = 0; i < npixels && cc > 0; )
+ if (*bp >= 128) { /* run */
+ rc = *bp++ + (2-128);
+ b = (int16)(*bp++ << shft);
+ cc -= 2;
+ while (rc-- && i < npixels)
+ tp[i++] |= b;
+ } else { /* non-run */
+ rc = *bp++; /* nul is noop */
+ while (--cc && rc-- && i < npixels)
+ tp[i++] |= (int16)*bp++ << shft;
+ }
+ if (i != npixels) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LogL16Decode: Not enough data at row %d (short %d pixels)",
+ tif->tif_row, npixels - i);
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ return (0);
+ }
+ }
+ (*sp->tfunc)(sp, op, npixels);
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ return (1);
+}
+
+/*
+ * Decode a string of 24-bit pixels.
+ */
+static int
+LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ LogLuvState* sp = DecoderState(tif);
+ int cc, i, npixels;
+ unsigned char* bp;
+ uint32* tp;
+
+ assert(s == 0);
+ assert(sp != NULL);
+
+ npixels = occ / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+ tp = (uint32 *)op;
+ else {
+ assert(sp->tbuflen >= npixels);
+ tp = (uint32 *) sp->tbuf;
+ }
+ /* copy to array of uint32 */
+ bp = (unsigned char*) tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ for (i = 0; i < npixels && cc > 0; i++) {
+ tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
+ bp += 3;
+ cc -= 3;
+ }
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ if (i != npixels) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LogLuvDecode24: Not enough data at row %d (short %d pixels)",
+ tif->tif_row, npixels - i);
+ return (0);
+ }
+ (*sp->tfunc)(sp, op, npixels);
+ return (1);
+}
+
+/*
+ * Decode a string of 32-bit pixels.
+ */
+static int
+LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ LogLuvState* sp;
+ int shft, i, npixels;
+ unsigned char* bp;
+ uint32* tp;
+ uint32 b;
+ int cc, rc;
+
+ assert(s == 0);
+ sp = DecoderState(tif);
+ assert(sp != NULL);
+
+ npixels = occ / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+ tp = (uint32*) op;
+ else {
+ assert(sp->tbuflen >= npixels);
+ tp = (uint32*) sp->tbuf;
+ }
+ _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
+
+ bp = (unsigned char*) tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ /* get each byte string */
+ for (shft = 4*8; (shft -= 8) >= 0; ) {
+ for (i = 0; i < npixels && cc > 0; )
+ if (*bp >= 128) { /* run */
+ rc = *bp++ + (2-128);
+ b = (uint32)*bp++ << shft;
+ cc -= 2;
+ while (rc-- && i < npixels)
+ tp[i++] |= b;
+ } else { /* non-run */
+ rc = *bp++; /* nul is noop */
+ while (--cc && rc-- && i < npixels)
+ tp[i++] |= (uint32)*bp++ << shft;
+ }
+ if (i != npixels) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LogLuvDecode32: Not enough data at row %d (short %d pixels)",
+ tif->tif_row, npixels - i);
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ return (0);
+ }
+ }
+ (*sp->tfunc)(sp, op, npixels);
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ return (1);
+}
+
+/*
+ * Decode a strip of pixels. We break it into rows to
+ * maintain synchrony with the encode algorithm, which
+ * is row by row.
+ */
+static int
+LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ tsize_t rowlen = TIFFScanlineSize(tif);
+
+ assert(cc%rowlen == 0);
+ while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
+ bp += rowlen, cc -= rowlen;
+ return (cc == 0);
+}
+
+/*
+ * Decode a tile of pixels. We break it into rows to
+ * maintain synchrony with the encode algorithm, which
+ * is row by row.
+ */
+static int
+LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ tsize_t rowlen = TIFFTileRowSize(tif);
+
+ assert(cc%rowlen == 0);
+ while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
+ bp += rowlen, cc -= rowlen;
+ return (cc == 0);
+}
+
+/*
+ * Encode a row of 16-bit pixels.
+ */
+static int
+LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ LogLuvState* sp = EncoderState(tif);
+ int shft, i, j, npixels;
+ tidata_t op;
+ int16* tp;
+ int16 b;
+ int occ, rc=0, mask, beg;
+
+ assert(s == 0);
+ assert(sp != NULL);
+ npixels = cc / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
+ tp = (int16*) bp;
+ else {
+ tp = (int16*) sp->tbuf;
+ assert(sp->tbuflen >= npixels);
+ (*sp->tfunc)(sp, bp, npixels);
+ }
+ /* compress each byte string */
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ for (shft = 2*8; (shft -= 8) >= 0; )
+ for (i = 0; i < npixels; i += rc) {
+ if (occ < 4) {
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+ mask = 0xff << shft; /* find next run */
+ for (beg = i; beg < npixels; beg += rc) {
+ b = (int16) (tp[beg] & mask);
+ rc = 1;
+ while (rc < 127+2 && beg+rc < npixels &&
+ (tp[beg+rc] & mask) == b)
+ rc++;
+ if (rc >= MINRUN)
+ break; /* long enough */
+ }
+ if (beg-i > 1 && beg-i < MINRUN) {
+ b = (int16) (tp[i] & mask);/*check short run */
+ j = i+1;
+ while ((tp[j++] & mask) == b)
+ if (j == beg) {
+ *op++ = (tidataval_t)(128-2+j-i);
+ *op++ = (tidataval_t) (b >> shft);
+ occ -= 2;
+ i = beg;
+ break;
+ }
+ }
+ while (i < beg) { /* write out non-run */
+ if ((j = beg-i) > 127) j = 127;
+ if (occ < j+3) {
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+ *op++ = (tidataval_t) j; occ--;
+ while (j--) {
+ *op++ = (tidataval_t) (tp[i++] >> shft & 0xff);
+ occ--;
+ }
+ }
+ if (rc >= MINRUN) { /* write out run */
+ *op++ = (tidataval_t) (128-2+rc);
+ *op++ = (tidataval_t) (tp[beg] >> shft & 0xff);
+ occ -= 2;
+ } else
+ rc = 0;
+ }
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+ return (1);
+}
+
+/*
+ * Encode a row of 24-bit pixels.
+ */
+static int
+LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ LogLuvState* sp = EncoderState(tif);
+ int i, npixels, occ;
+ tidata_t op;
+ uint32* tp;
+
+ assert(s == 0);
+ assert(sp != NULL);
+ npixels = cc / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+ tp = (uint32*) bp;
+ else {
+ tp = (uint32*) sp->tbuf;
+ assert(sp->tbuflen >= npixels);
+ (*sp->tfunc)(sp, bp, npixels);
+ }
+ /* write out encoded pixels */
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ for (i = npixels; i--; ) {
+ if (occ < 3) {
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+ *op++ = (tidataval_t)(*tp >> 16);
+ *op++ = (tidataval_t)(*tp >> 8 & 0xff);
+ *op++ = (tidataval_t)(*tp++ & 0xff);
+ occ -= 3;
+ }
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+ return (1);
+}
+
+/*
+ * Encode a row of 32-bit pixels.
+ */
+static int
+LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ LogLuvState* sp = EncoderState(tif);
+ int shft, i, j, npixels;
+ tidata_t op;
+ uint32* tp;
+ uint32 b;
+ int occ, rc=0, mask, beg;
+
+ assert(s == 0);
+ assert(sp != NULL);
+
+ npixels = cc / sp->pixel_size;
+
+ if (sp->user_datafmt == SGILOGDATAFMT_RAW)
+ tp = (uint32*) bp;
+ else {
+ tp = (uint32*) sp->tbuf;
+ assert(sp->tbuflen >= npixels);
+ (*sp->tfunc)(sp, bp, npixels);
+ }
+ /* compress each byte string */
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ for (shft = 4*8; (shft -= 8) >= 0; )
+ for (i = 0; i < npixels; i += rc) {
+ if (occ < 4) {
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+ mask = 0xff << shft; /* find next run */
+ for (beg = i; beg < npixels; beg += rc) {
+ b = tp[beg] & mask;
+ rc = 1;
+ while (rc < 127+2 && beg+rc < npixels &&
+ (tp[beg+rc] & mask) == b)
+ rc++;
+ if (rc >= MINRUN)
+ break; /* long enough */
+ }
+ if (beg-i > 1 && beg-i < MINRUN) {
+ b = tp[i] & mask; /* check short run */
+ j = i+1;
+ while ((tp[j++] & mask) == b)
+ if (j == beg) {
+ *op++ = (tidataval_t)(128-2+j-i);
+ *op++ = (tidataval_t)(b >> shft);
+ occ -= 2;
+ i = beg;
+ break;
+ }
+ }
+ while (i < beg) { /* write out non-run */
+ if ((j = beg-i) > 127) j = 127;
+ if (occ < j+3) {
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ occ = tif->tif_rawdatasize - tif->tif_rawcc;
+ }
+ *op++ = (tidataval_t) j; occ--;
+ while (j--) {
+ *op++ = (tidataval_t)(tp[i++] >> shft & 0xff);
+ occ--;
+ }
+ }
+ if (rc >= MINRUN) { /* write out run */
+ *op++ = (tidataval_t) (128-2+rc);
+ *op++ = (tidataval_t)(tp[beg] >> shft & 0xff);
+ occ -= 2;
+ } else
+ rc = 0;
+ }
+ tif->tif_rawcp = op;
+ tif->tif_rawcc = tif->tif_rawdatasize - occ;
+
+ return (1);
+}
+
+/*
+ * Encode a strip of pixels. We break it into rows to
+ * avoid encoding runs across row boundaries.
+ */
+static int
+LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ tsize_t rowlen = TIFFScanlineSize(tif);
+
+ assert(cc%rowlen == 0);
+ while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
+ bp += rowlen, cc -= rowlen;
+ return (cc == 0);
+}
+
+/*
+ * Encode a tile of pixels. We break it into rows to
+ * avoid encoding runs across row boundaries.
+ */
+static int
+LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ tsize_t rowlen = TIFFTileRowSize(tif);
+
+ assert(cc%rowlen == 0);
+ while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
+ bp += rowlen, cc -= rowlen;
+ return (cc == 0);
+}
+
+/*
+ * Encode/Decode functions for converting to and from user formats.
+ */
+
+#include "uvcode.h"
+
+#ifndef UVSCALE
+#define U_NEU 0.210526316
+#define V_NEU 0.473684211
+#define UVSCALE 410.
+#endif
+
+#ifndef M_LN2
+#define M_LN2 0.69314718055994530942
+#endif
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#define log2(x) ((1./M_LN2)*log(x))
+#define exp2(x) exp(M_LN2*(x))
+
+#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \
+ (int)(x) : \
+ (int)((x) + rand()*(1./RAND_MAX) - .5))
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+double
+LogL16toY(int p16) /* compute luminance from 16-bit LogL */
+{
+ int Le = p16 & 0x7fff;
+ double Y;
+
+ if (!Le)
+ return (0.);
+ Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
+ return (!(p16 & 0x8000) ? Y : -Y);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
+{
+ if (Y >= 1.8371976e19)
+ return (0x7fff);
+ if (Y <= -1.8371976e19)
+ return (0xffff);
+ if (Y > 5.4136769e-20)
+ return itrunc(256.*(log2(Y) + 64.), em);
+ if (Y < -5.4136769e-20)
+ return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
+ return (0);
+}
+
+static void
+L16toY(LogLuvState* sp, tidata_t op, int n)
+{
+ int16* l16 = (int16*) sp->tbuf;
+ float* yp = (float*) op;
+
+ while (n-- > 0)
+ *yp++ = (float)LogL16toY(*l16++);
+}
+
+static void
+L16toGry(LogLuvState* sp, tidata_t op, int n)
+{
+ int16* l16 = (int16*) sp->tbuf;
+ uint8* gp = (uint8*) op;
+
+ while (n-- > 0) {
+ double Y = LogL16toY(*l16++);
+ *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
+ }
+}
+
+static void
+L16fromY(LogLuvState* sp, tidata_t op, int n)
+{
+ int16* l16 = (int16*) sp->tbuf;
+ float* yp = (float*) op;
+
+ while (n-- > 0)
+ *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+XYZtoRGB24(float xyz[3], uint8 rgb[3])
+{
+ double r, g, b;
+ /* assume CCIR-709 primaries */
+ r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
+ g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2];
+ b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2];
+ /* assume 2.0 gamma for speed */
+ /* could use integer sqrt approx., but this is probably faster */
+ rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
+ rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
+ rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+double
+LogL10toY(int p10) /* compute luminance from 10-bit LogL */
+{
+ if (p10 == 0)
+ return (0.);
+ return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
+{
+ if (Y >= 15.742)
+ return (0x3ff);
+ else if (Y <= .00024283)
+ return (0);
+ else
+ return itrunc(64.*(log2(Y) + 12.), em);
+}
+
+#define NANGLES 100
+#define uv2ang(u, v) ( (NANGLES*.499999999/M_PI) \
+ * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
+
+static int
+oog_encode(double u, double v) /* encode out-of-gamut chroma */
+{
+ static int oog_table[NANGLES];
+ static int initialized = 0;
+ register int i;
+
+ if (!initialized) { /* set up perimeter table */
+ double eps[NANGLES], ua, va, ang, epsa;
+ int ui, vi, ustep;
+ for (i = NANGLES; i--; )
+ eps[i] = 2.;
+ for (vi = UV_NVS; vi--; ) {
+ va = UV_VSTART + (vi+.5)*UV_SQSIZ;
+ ustep = uv_row[vi].nus-1;
+ if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
+ ustep = 1;
+ for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
+ ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
+ ang = uv2ang(ua, va);
+ i = (int) ang;
+ epsa = fabs(ang - (i+.5));
+ if (epsa < eps[i]) {
+ oog_table[i] = uv_row[vi].ncum + ui;
+ eps[i] = epsa;
+ }
+ }
+ }
+ for (i = NANGLES; i--; ) /* fill any holes */
+ if (eps[i] > 1.5) {
+ int i1, i2;
+ for (i1 = 1; i1 < NANGLES/2; i1++)
+ if (eps[(i+i1)%NANGLES] < 1.5)
+ break;
+ for (i2 = 1; i2 < NANGLES/2; i2++)
+ if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
+ break;
+ if (i1 < i2)
+ oog_table[i] =
+ oog_table[(i+i1)%NANGLES];
+ else
+ oog_table[i] =
+ oog_table[(i+NANGLES-i2)%NANGLES];
+ }
+ initialized = 1;
+ }
+ i = (int) uv2ang(u, v); /* look up hue angle */
+ return (oog_table[i]);
+}
+
+#undef uv2ang
+#undef NANGLES
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
+{
+ register int vi, ui;
+
+ if (v < UV_VSTART)
+ return oog_encode(u, v);
+ vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
+ if (vi >= UV_NVS)
+ return oog_encode(u, v);
+ if (u < uv_row[vi].ustart)
+ return oog_encode(u, v);
+ ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
+ if (ui >= uv_row[vi].nus)
+ return oog_encode(u, v);
+
+ return (uv_row[vi].ncum + ui);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+int
+uv_decode(double *up, double *vp, int c) /* decode (u',v') index */
+{
+ int upper, lower;
+ register int ui, vi;
+
+ if (c < 0 || c >= UV_NDIVS)
+ return (-1);
+ lower = 0; /* binary search */
+ upper = UV_NVS;
+ while (upper - lower > 1) {
+ vi = (lower + upper) >> 1;
+ ui = c - uv_row[vi].ncum;
+ if (ui > 0)
+ lower = vi;
+ else if (ui < 0)
+ upper = vi;
+ else {
+ lower = vi;
+ break;
+ }
+ }
+ vi = lower;
+ ui = c - uv_row[vi].ncum;
+ *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
+ *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
+ return (0);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+LogLuv24toXYZ(uint32 p, float XYZ[3])
+{
+ int Ce;
+ double L, u, v, s, x, y;
+ /* decode luminance */
+ L = LogL10toY(p>>14 & 0x3ff);
+ if (L <= 0.) {
+ XYZ[0] = XYZ[1] = XYZ[2] = 0.;
+ return;
+ }
+ /* decode color */
+ Ce = p & 0x3fff;
+ if (uv_decode(&u, &v, Ce) < 0) {
+ u = U_NEU; v = V_NEU;
+ }
+ s = 1./(6.*u - 16.*v + 12.);
+ x = 9.*u * s;
+ y = 4.*v * s;
+ /* convert to XYZ */
+ XYZ[0] = (float)(x/y * L);
+ XYZ[1] = (float)L;
+ XYZ[2] = (float)((1.-x-y)/y * L);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+uint32
+LogLuv24fromXYZ(float XYZ[3], int em)
+{
+ int Le, Ce;
+ double u, v, s;
+ /* encode luminance */
+ Le = LogL10fromY(XYZ[1], em);
+ /* encode color */
+ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
+ if (!Le || s <= 0.) {
+ u = U_NEU;
+ v = V_NEU;
+ } else {
+ u = 4.*XYZ[0] / s;
+ v = 9.*XYZ[1] / s;
+ }
+ Ce = uv_encode(u, v, em);
+ if (Ce < 0) /* never happens */
+ Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
+ /* combine encodings */
+ return (Le << 14 | Ce);
+}
+
+static void
+Luv24toXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ float* xyz = (float*) op;
+
+ while (n-- > 0) {
+ LogLuv24toXYZ(*luv, xyz);
+ xyz += 3;
+ luv++;
+ }
+}
+
+static void
+Luv24toLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ int16* luv3 = (int16*) op;
+
+ while (n-- > 0) {
+ double u, v;
+
+ *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
+ if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
+ u = U_NEU;
+ v = V_NEU;
+ }
+ *luv3++ = (int16)(u * (1L<<15));
+ *luv3++ = (int16)(v * (1L<<15));
+ luv++;
+ }
+}
+
+static void
+Luv24toRGB(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ uint8* rgb = (uint8*) op;
+
+ while (n-- > 0) {
+ float xyz[3];
+
+ LogLuv24toXYZ(*luv++, xyz);
+ XYZtoRGB24(xyz, rgb);
+ rgb += 3;
+ }
+}
+
+static void
+Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ float* xyz = (float*) op;
+
+ while (n-- > 0) {
+ *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
+ xyz += 3;
+ }
+}
+
+static void
+Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ int16* luv3 = (int16*) op;
+
+ while (n-- > 0) {
+ int Le, Ce;
+
+ if (luv3[0] <= 0)
+ Le = 0;
+ else if (luv3[0] >= (1<<12)+3314)
+ Le = (1<<10) - 1;
+ else if (sp->encode_meth == SGILOGENCODE_NODITHER)
+ Le = (luv3[0]-3314) >> 2;
+ else
+ Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
+
+ Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
+ sp->encode_meth);
+ if (Ce < 0) /* never happens */
+ Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
+ *luv++ = (uint32)Le << 14 | Ce;
+ luv3 += 3;
+ }
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+void
+LogLuv32toXYZ(uint32 p, float XYZ[3])
+{
+ double L, u, v, s, x, y;
+ /* decode luminance */
+ L = LogL16toY((int)p >> 16);
+ if (L <= 0.) {
+ XYZ[0] = XYZ[1] = XYZ[2] = 0.;
+ return;
+ }
+ /* decode color */
+ u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
+ v = 1./UVSCALE * ((p & 0xff) + .5);
+ s = 1./(6.*u - 16.*v + 12.);
+ x = 9.*u * s;
+ y = 4.*v * s;
+ /* convert to XYZ */
+ XYZ[0] = (float)(x/y * L);
+ XYZ[1] = (float)L;
+ XYZ[2] = (float)((1.-x-y)/y * L);
+}
+
+#if !LOGLUV_PUBLIC
+static
+#endif
+uint32
+LogLuv32fromXYZ(float XYZ[3], int em)
+{
+ unsigned int Le, ue, ve;
+ double u, v, s;
+ /* encode luminance */
+ Le = (unsigned int)LogL16fromY(XYZ[1], em);
+ /* encode color */
+ s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
+ if (!Le || s <= 0.) {
+ u = U_NEU;
+ v = V_NEU;
+ } else {
+ u = 4.*XYZ[0] / s;
+ v = 9.*XYZ[1] / s;
+ }
+ if (u <= 0.) ue = 0;
+ else ue = itrunc(UVSCALE*u, em);
+ if (ue > 255) ue = 255;
+ if (v <= 0.) ve = 0;
+ else ve = itrunc(UVSCALE*v, em);
+ if (ve > 255) ve = 255;
+ /* combine encodings */
+ return (Le << 16 | ue << 8 | ve);
+}
+
+static void
+Luv32toXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ float* xyz = (float*) op;
+
+ while (n-- > 0) {
+ LogLuv32toXYZ(*luv++, xyz);
+ xyz += 3;
+ }
+}
+
+static void
+Luv32toLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ int16* luv3 = (int16*) op;
+
+ while (n-- > 0) {
+ double u, v;
+
+ *luv3++ = (int16)(*luv >> 16);
+ u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
+ v = 1./UVSCALE * ((*luv & 0xff) + .5);
+ *luv3++ = (int16)(u * (1L<<15));
+ *luv3++ = (int16)(v * (1L<<15));
+ luv++;
+ }
+}
+
+static void
+Luv32toRGB(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ uint8* rgb = (uint8*) op;
+
+ while (n-- > 0) {
+ float xyz[3];
+
+ LogLuv32toXYZ(*luv++, xyz);
+ XYZtoRGB24(xyz, rgb);
+ rgb += 3;
+ }
+}
+
+static void
+Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ float* xyz = (float*) op;
+
+ while (n-- > 0) {
+ *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
+ xyz += 3;
+ }
+}
+
+static void
+Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n)
+{
+ uint32* luv = (uint32*) sp->tbuf;
+ int16* luv3 = (int16*) op;
+
+ if (sp->encode_meth == SGILOGENCODE_NODITHER) {
+ while (n-- > 0) {
+ *luv++ = (uint32)luv3[0] << 16 |
+ (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
+ (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
+ luv3 += 3;
+ }
+ return;
+ }
+ while (n-- > 0) {
+ *luv++ = (uint32)luv3[0] << 16 |
+ (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
+ (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
+ luv3 += 3;
+ }
+}
+
+static void
+_logLuvNop(LogLuvState* sp, tidata_t op, int n)
+{
+ (void) sp; (void) op; (void) n;
+}
+
+static int
+LogL16GuessDataFmt(TIFFDirectory *td)
+{
+#define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f))
+ switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
+ case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
+ return (SGILOGDATAFMT_FLOAT);
+ case PACK(1, 16, SAMPLEFORMAT_VOID):
+ case PACK(1, 16, SAMPLEFORMAT_INT):
+ case PACK(1, 16, SAMPLEFORMAT_UINT):
+ return (SGILOGDATAFMT_16BIT);
+ case PACK(1, 8, SAMPLEFORMAT_VOID):
+ case PACK(1, 8, SAMPLEFORMAT_UINT):
+ return (SGILOGDATAFMT_8BIT);
+ }
+#undef PACK
+ return (SGILOGDATAFMT_UNKNOWN);
+}
+
+static uint32
+multiply(size_t m1, size_t m2)
+{
+ uint32 bytes = m1 * m2;
+
+ if (m1 && bytes / m1 != m2)
+ bytes = 0;
+
+ return bytes;
+}
+
+static int
+LogL16InitState(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ LogLuvState* sp = DecoderState(tif);
+ static const char module[] = "LogL16InitState";
+
+ assert(sp != NULL);
+ assert(td->td_photometric == PHOTOMETRIC_LOGL);
+
+ /* for some reason, we can't do this in TIFFInitLogL16 */
+ if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
+ sp->user_datafmt = LogL16GuessDataFmt(td);
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->pixel_size = sizeof (float);
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->pixel_size = sizeof (int16);
+ break;
+ case SGILOGDATAFMT_8BIT:
+ sp->pixel_size = sizeof (uint8);
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No support for converting user data format to LogL");
+ return (0);
+ }
+ if( isTiled(tif) )
+ sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength);
+ else
+ sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
+ if (multiply(sp->tbuflen, sizeof (int16)) == 0 ||
+ (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer",
+ tif->tif_name);
+ return (0);
+ }
+ return (1);
+}
+
+static int
+LogLuvGuessDataFmt(TIFFDirectory *td)
+{
+ int guess;
+
+ /*
+ * If the user didn't tell us their datafmt,
+ * take our best guess from the bitspersample.
+ */
+#define PACK(a,b) (((a)<<3)|(b))
+ switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
+ case PACK(32, SAMPLEFORMAT_IEEEFP):
+ guess = SGILOGDATAFMT_FLOAT;
+ break;
+ case PACK(32, SAMPLEFORMAT_VOID):
+ case PACK(32, SAMPLEFORMAT_UINT):
+ case PACK(32, SAMPLEFORMAT_INT):
+ guess = SGILOGDATAFMT_RAW;
+ break;
+ case PACK(16, SAMPLEFORMAT_VOID):
+ case PACK(16, SAMPLEFORMAT_INT):
+ case PACK(16, SAMPLEFORMAT_UINT):
+ guess = SGILOGDATAFMT_16BIT;
+ break;
+ case PACK( 8, SAMPLEFORMAT_VOID):
+ case PACK( 8, SAMPLEFORMAT_UINT):
+ guess = SGILOGDATAFMT_8BIT;
+ break;
+ default:
+ guess = SGILOGDATAFMT_UNKNOWN;
+ break;
+#undef PACK
+ }
+ /*
+ * Double-check samples per pixel.
+ */
+ switch (td->td_samplesperpixel) {
+ case 1:
+ if (guess != SGILOGDATAFMT_RAW)
+ guess = SGILOGDATAFMT_UNKNOWN;
+ break;
+ case 3:
+ if (guess == SGILOGDATAFMT_RAW)
+ guess = SGILOGDATAFMT_UNKNOWN;
+ break;
+ default:
+ guess = SGILOGDATAFMT_UNKNOWN;
+ break;
+ }
+ return (guess);
+}
+
+static int
+LogLuvInitState(TIFF* tif)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ LogLuvState* sp = DecoderState(tif);
+ static const char module[] = "LogLuvInitState";
+
+ assert(sp != NULL);
+ assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
+
+ /* for some reason, we can't do this in TIFFInitLogLuv */
+ if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "SGILog compression cannot handle non-contiguous data");
+ return (0);
+ }
+ if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
+ sp->user_datafmt = LogLuvGuessDataFmt(td);
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->pixel_size = 3*sizeof (float);
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->pixel_size = 3*sizeof (int16);
+ break;
+ case SGILOGDATAFMT_RAW:
+ sp->pixel_size = sizeof (uint32);
+ break;
+ case SGILOGDATAFMT_8BIT:
+ sp->pixel_size = 3*sizeof (uint8);
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "No support for converting user data format to LogLuv");
+ return (0);
+ }
+ if( isTiled(tif) )
+ sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength);
+ else
+ sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
+ if (multiply(sp->tbuflen, sizeof (uint32)) == 0 ||
+ (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer",
+ tif->tif_name);
+ return (0);
+ }
+ return (1);
+}
+
+static int
+LogLuvSetupDecode(TIFF* tif)
+{
+ LogLuvState* sp = DecoderState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ switch (td->td_photometric) {
+ case PHOTOMETRIC_LOGLUV:
+ if (!LogLuvInitState(tif))
+ break;
+ if (td->td_compression == COMPRESSION_SGILOG24) {
+ tif->tif_decoderow = LogLuvDecode24;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = Luv24toXYZ;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->tfunc = Luv24toLuv48;
+ break;
+ case SGILOGDATAFMT_8BIT:
+ sp->tfunc = Luv24toRGB;
+ break;
+ }
+ } else {
+ tif->tif_decoderow = LogLuvDecode32;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = Luv32toXYZ;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->tfunc = Luv32toLuv48;
+ break;
+ case SGILOGDATAFMT_8BIT:
+ sp->tfunc = Luv32toRGB;
+ break;
+ }
+ }
+ return (1);
+ case PHOTOMETRIC_LOGL:
+ if (!LogL16InitState(tif))
+ break;
+ tif->tif_decoderow = LogL16Decode;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = L16toY;
+ break;
+ case SGILOGDATAFMT_8BIT:
+ sp->tfunc = L16toGry;
+ break;
+ }
+ return (1);
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Inappropriate photometric interpretation %d for SGILog compression; %s",
+ td->td_photometric, "must be either LogLUV or LogL");
+ break;
+ }
+ return (0);
+}
+
+static int
+LogLuvSetupEncode(TIFF* tif)
+{
+ LogLuvState* sp = EncoderState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ switch (td->td_photometric) {
+ case PHOTOMETRIC_LOGLUV:
+ if (!LogLuvInitState(tif))
+ break;
+ if (td->td_compression == COMPRESSION_SGILOG24) {
+ tif->tif_encoderow = LogLuvEncode24;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = Luv24fromXYZ;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->tfunc = Luv24fromLuv48;
+ break;
+ case SGILOGDATAFMT_RAW:
+ break;
+ default:
+ goto notsupported;
+ }
+ } else {
+ tif->tif_encoderow = LogLuvEncode32;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = Luv32fromXYZ;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ sp->tfunc = Luv32fromLuv48;
+ break;
+ case SGILOGDATAFMT_RAW:
+ break;
+ default:
+ goto notsupported;
+ }
+ }
+ break;
+ case PHOTOMETRIC_LOGL:
+ if (!LogL16InitState(tif))
+ break;
+ tif->tif_encoderow = LogL16Encode;
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ sp->tfunc = L16fromY;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ break;
+ default:
+ goto notsupported;
+ }
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Inappropriate photometric interpretation %d for SGILog compression; %s",
+ td->td_photometric, "must be either LogLUV or LogL");
+ break;
+ }
+ return (1);
+notsupported:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "SGILog compression supported only for %s, or raw data",
+ td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
+ return (0);
+}
+
+static void
+LogLuvClose(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ /*
+ * For consistency, we always want to write out the same
+ * bitspersample and sampleformat for our TIFF file,
+ * regardless of the data format being used by the application.
+ * Since this routine is called after tags have been set but
+ * before they have been recorded in the file, we reset them here.
+ */
+ td->td_samplesperpixel =
+ (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
+ td->td_bitspersample = 16;
+ td->td_sampleformat = SAMPLEFORMAT_INT;
+}
+
+static void
+LogLuvCleanup(TIFF* tif)
+{
+ LogLuvState* sp = (LogLuvState *)tif->tif_data;
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ if (sp->tbuf)
+ _TIFFfree(sp->tbuf);
+ _TIFFfree(sp);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static int
+LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ LogLuvState* sp = DecoderState(tif);
+ int bps, fmt;
+
+ switch (tag) {
+ case TIFFTAG_SGILOGDATAFMT:
+ sp->user_datafmt = va_arg(ap, int);
+ /*
+ * Tweak the TIFF header so that the rest of libtiff knows what
+ * size of data will be passed between app and library, and
+ * assume that the app knows what it is doing and is not
+ * confused by these header manipulations...
+ */
+ switch (sp->user_datafmt) {
+ case SGILOGDATAFMT_FLOAT:
+ bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
+ break;
+ case SGILOGDATAFMT_16BIT:
+ bps = 16, fmt = SAMPLEFORMAT_INT;
+ break;
+ case SGILOGDATAFMT_RAW:
+ bps = 32, fmt = SAMPLEFORMAT_UINT;
+ TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
+ break;
+ case SGILOGDATAFMT_8BIT:
+ bps = 8, fmt = SAMPLEFORMAT_UINT;
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Unknown data format %d for LogLuv compression",
+ sp->user_datafmt);
+ return (0);
+ }
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
+ /*
+ * Must recalculate sizes should bits/sample change.
+ */
+ tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+ tif->tif_scanlinesize = TIFFScanlineSize(tif);
+ return (1);
+ case TIFFTAG_SGILOGENCODE:
+ sp->encode_meth = va_arg(ap, int);
+ if (sp->encode_meth != SGILOGENCODE_NODITHER &&
+ sp->encode_meth != SGILOGENCODE_RANDITHER) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Unknown encoding %d for LogLuv compression",
+ sp->encode_meth);
+ return (0);
+ }
+ return (1);
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+}
+
+static int
+LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ LogLuvState *sp = (LogLuvState *)tif->tif_data;
+
+ switch (tag) {
+ case TIFFTAG_SGILOGDATAFMT:
+ *va_arg(ap, int*) = sp->user_datafmt;
+ return (1);
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+}
+
+static const TIFFFieldInfo LogLuvFieldInfo[] = {
+ { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, FIELD_PSEUDO,
+ TRUE, FALSE, "SGILogDataFmt"},
+ { TIFFTAG_SGILOGENCODE, 0, 0, TIFF_SHORT, FIELD_PSEUDO,
+ TRUE, FALSE, "SGILogEncode"}
+};
+
+int
+TIFFInitSGILog(TIFF* tif, int scheme)
+{
+ static const char module[] = "TIFFInitSGILog";
+ LogLuvState* sp;
+
+ assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, LogLuvFieldInfo,
+ TIFFArrayCount(LogLuvFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging SGILog codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ sp = (LogLuvState*) tif->tif_data;
+ _TIFFmemset((tdata_t)sp, 0, sizeof (*sp));
+ sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
+ sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
+ SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
+ sp->tfunc = _logLuvNop;
+
+ /*
+ * Install codec methods.
+ * NB: tif_decoderow & tif_encoderow are filled
+ * in at setup time.
+ */
+ tif->tif_setupdecode = LogLuvSetupDecode;
+ tif->tif_decodestrip = LogLuvDecodeStrip;
+ tif->tif_decodetile = LogLuvDecodeTile;
+ tif->tif_setupencode = LogLuvSetupEncode;
+ tif->tif_encodestrip = LogLuvEncodeStrip;
+ tif->tif_encodetile = LogLuvEncodeTile;
+ tif->tif_close = LogLuvClose;
+ tif->tif_cleanup = LogLuvCleanup;
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = LogLuvVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = LogLuvVSetField; /* hook for codec tags */
+
+ return (1);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: No space for LogLuv state block", tif->tif_name);
+ return (0);
+}
+#endif /* LOGLUV_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_lzw.c b/Source/LibTIFF/tif_lzw.c
new file mode 100644
index 0000000..ba59cfc
--- /dev/null
+++ b/Source/LibTIFF/tif_lzw.c
@@ -0,0 +1,1122 @@
+/* $Id: tif_lzw.c,v 1.28 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef LZW_SUPPORT
+/*
+ * TIFF Library.
+ * Rev 5.0 Lempel-Ziv & Welch Compression Support
+ *
+ * This code is derived from the compress program whose code is
+ * derived from software contributed to Berkeley by James A. Woods,
+ * derived from original work by Spencer Thomas and Joseph Orost.
+ *
+ * The original Berkeley copyright notice appears below in its entirety.
+ */
+#include "tif_predict.h"
+
+#include <stdio.h>
+
+/*
+ * NB: The 5.0 spec describes a different algorithm than Aldus
+ * implements. Specifically, Aldus does code length transitions
+ * one code earlier than should be done (for real LZW).
+ * Earlier versions of this library implemented the correct
+ * LZW algorithm, but emitted codes in a bit order opposite
+ * to the TIFF spec. Thus, to maintain compatibility w/ Aldus
+ * we interpret MSB-LSB ordered codes to be images written w/
+ * old versions of this library, but otherwise adhere to the
+ * Aldus "off by one" algorithm.
+ *
+ * Future revisions to the TIFF spec are expected to "clarify this issue".
+ */
+#define LZW_COMPAT /* include backwards compatibility code */
+/*
+ * Each strip of data is supposed to be terminated by a CODE_EOI.
+ * If the following #define is included, the decoder will also
+ * check for end-of-strip w/o seeing this code. This makes the
+ * library more robust, but also slower.
+ */
+#define LZW_CHECKEOS /* include checks for strips w/o EOI code */
+
+#define MAXCODE(n) ((1L<<(n))-1)
+/*
+ * The TIFF spec specifies that encoded bit
+ * strings range from 9 to 12 bits.
+ */
+#define BITS_MIN 9 /* start with 9 bits */
+#define BITS_MAX 12 /* max of 12 bit strings */
+/* predefined codes */
+#define CODE_CLEAR 256 /* code to clear string table */
+#define CODE_EOI 257 /* end-of-information code */
+#define CODE_FIRST 258 /* first free code entry */
+#define CODE_MAX MAXCODE(BITS_MAX)
+#define HSIZE 9001L /* 91% occupancy */
+#define HSHIFT (13-8)
+#ifdef LZW_COMPAT
+/* NB: +1024 is for compatibility with old files */
+#define CSIZE (MAXCODE(BITS_MAX)+1024L)
+#else
+#define CSIZE (MAXCODE(BITS_MAX)+1L)
+#endif
+
+/*
+ * State block for each open TIFF file using LZW
+ * compression/decompression. Note that the predictor
+ * state block must be first in this data structure.
+ */
+typedef struct {
+ TIFFPredictorState predict; /* predictor super class */
+
+ unsigned short nbits; /* # of bits/code */
+ unsigned short maxcode; /* maximum code for lzw_nbits */
+ unsigned short free_ent; /* next free entry in hash table */
+ long nextdata; /* next bits of i/o */
+ long nextbits; /* # of valid bits in lzw_nextdata */
+
+ int rw_mode; /* preserve rw_mode from init */
+} LZWBaseState;
+
+#define lzw_nbits base.nbits
+#define lzw_maxcode base.maxcode
+#define lzw_free_ent base.free_ent
+#define lzw_nextdata base.nextdata
+#define lzw_nextbits base.nextbits
+
+/*
+ * Encoding-specific state.
+ */
+typedef uint16 hcode_t; /* codes fit in 16 bits */
+typedef struct {
+ long hash;
+ hcode_t code;
+} hash_t;
+
+/*
+ * Decoding-specific state.
+ */
+typedef struct code_ent {
+ struct code_ent *next;
+ unsigned short length; /* string len, including this token */
+ unsigned char value; /* data value */
+ unsigned char firstchar; /* first token of string */
+} code_t;
+
+typedef int (*decodeFunc)(TIFF*, tidata_t, tsize_t, tsample_t);
+
+typedef struct {
+ LZWBaseState base;
+
+ /* Decoding specific data */
+ long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */
+ long dec_restart; /* restart count */
+#ifdef LZW_CHECKEOS
+ long dec_bitsleft; /* available bits in raw data */
+#endif
+ decodeFunc dec_decode; /* regular or backwards compatible */
+ code_t* dec_codep; /* current recognized code */
+ code_t* dec_oldcodep; /* previously recognized code */
+ code_t* dec_free_entp; /* next free entry */
+ code_t* dec_maxcodep; /* max available entry */
+ code_t* dec_codetab; /* kept separate for small machines */
+
+ /* Encoding specific data */
+ int enc_oldcode; /* last code encountered */
+ long enc_checkpoint; /* point at which to clear table */
+#define CHECK_GAP 10000 /* enc_ratio check interval */
+ long enc_ratio; /* current compression ratio */
+ long enc_incount; /* (input) data bytes encoded */
+ long enc_outcount; /* encoded (output) bytes */
+ tidata_t enc_rawlimit; /* bound on tif_rawdata buffer */
+ hash_t* enc_hashtab; /* kept separate for small machines */
+} LZWCodecState;
+
+#define LZWState(tif) ((LZWBaseState*) (tif)->tif_data)
+#define DecoderState(tif) ((LZWCodecState*) LZWState(tif))
+#define EncoderState(tif) ((LZWCodecState*) LZWState(tif))
+
+static int LZWDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+#ifdef LZW_COMPAT
+static int LZWDecodeCompat(TIFF*, tidata_t, tsize_t, tsample_t);
+#endif
+static void cl_hash(LZWCodecState*);
+
+/*
+ * LZW Decoder.
+ */
+
+#ifdef LZW_CHECKEOS
+/*
+ * This check shouldn't be necessary because each
+ * strip is suppose to be terminated with CODE_EOI.
+ */
+#define NextCode(_tif, _sp, _bp, _code, _get) { \
+ if ((_sp)->dec_bitsleft < nbits) { \
+ TIFFWarningExt(_tif->tif_clientdata, _tif->tif_name, \
+ "LZWDecode: Strip %d not terminated with EOI code", \
+ _tif->tif_curstrip); \
+ _code = CODE_EOI; \
+ } else { \
+ _get(_sp,_bp,_code); \
+ (_sp)->dec_bitsleft -= nbits; \
+ } \
+}
+#else
+#define NextCode(tif, sp, bp, code, get) get(sp, bp, code)
+#endif
+
+static int
+LZWSetupDecode(TIFF* tif)
+{
+ LZWCodecState* sp = DecoderState(tif);
+ static const char module[] = " LZWSetupDecode";
+ int code;
+
+ if( sp == NULL )
+ {
+ /*
+ * Allocate state block so tag methods have storage to record
+ * values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof(LZWCodecState));
+ if (tif->tif_data == NULL)
+ {
+ TIFFErrorExt(tif->tif_clientdata, "LZWPreDecode", "No space for LZW state block");
+ return (0);
+ }
+
+ DecoderState(tif)->dec_codetab = NULL;
+ DecoderState(tif)->dec_decode = NULL;
+
+ /*
+ * Setup predictor setup.
+ */
+ (void) TIFFPredictorInit(tif);
+
+ sp = DecoderState(tif);
+ }
+
+ assert(sp != NULL);
+
+ if (sp->dec_codetab == NULL) {
+ sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t));
+ if (sp->dec_codetab == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "No space for LZW code table");
+ return (0);
+ }
+ /*
+ * Pre-load the table.
+ */
+ code = 255;
+ do {
+ sp->dec_codetab[code].value = code;
+ sp->dec_codetab[code].firstchar = code;
+ sp->dec_codetab[code].length = 1;
+ sp->dec_codetab[code].next = NULL;
+ } while (code--);
+ /*
+ * Zero-out the unused entries
+ */
+ _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0,
+ (CODE_FIRST - CODE_CLEAR) * sizeof (code_t));
+ }
+ return (1);
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+LZWPreDecode(TIFF* tif, tsample_t s)
+{
+ LZWCodecState *sp = DecoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ if( sp->dec_codetab == NULL )
+ {
+ tif->tif_setupdecode( tif );
+ }
+
+ /*
+ * Check for old bit-reversed codes.
+ */
+ if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) {
+#ifdef LZW_COMPAT
+ if (!sp->dec_decode) {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "Old-style LZW codes, convert file");
+ /*
+ * Override default decoding methods with
+ * ones that deal with the old coding.
+ * Otherwise the predictor versions set
+ * above will call the compatibility routines
+ * through the dec_decode method.
+ */
+ tif->tif_decoderow = LZWDecodeCompat;
+ tif->tif_decodestrip = LZWDecodeCompat;
+ tif->tif_decodetile = LZWDecodeCompat;
+ /*
+ * If doing horizontal differencing, must
+ * re-setup the predictor logic since we
+ * switched the basic decoder methods...
+ */
+ (*tif->tif_setupdecode)(tif);
+ sp->dec_decode = LZWDecodeCompat;
+ }
+ sp->lzw_maxcode = MAXCODE(BITS_MIN);
+#else /* !LZW_COMPAT */
+ if (!sp->dec_decode) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Old-style LZW codes not supported");
+ sp->dec_decode = LZWDecode;
+ }
+ return (0);
+#endif/* !LZW_COMPAT */
+ } else {
+ sp->lzw_maxcode = MAXCODE(BITS_MIN)-1;
+ sp->dec_decode = LZWDecode;
+ }
+ sp->lzw_nbits = BITS_MIN;
+ sp->lzw_nextbits = 0;
+ sp->lzw_nextdata = 0;
+
+ sp->dec_restart = 0;
+ sp->dec_nbitsmask = MAXCODE(BITS_MIN);
+#ifdef LZW_CHECKEOS
+ sp->dec_bitsleft = tif->tif_rawcc << 3;
+#endif
+ sp->dec_free_entp = sp->dec_codetab + CODE_FIRST;
+ /*
+ * Zero entries that are not yet filled in. We do
+ * this to guard against bogus input data that causes
+ * us to index into undefined entries. If you can
+ * come up with a way to safely bounds-check input codes
+ * while decoding then you can remove this operation.
+ */
+ _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t));
+ sp->dec_oldcodep = &sp->dec_codetab[-1];
+ sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1];
+ return (1);
+}
+
+/*
+ * Decode a "hunk of data".
+ */
+#define GetNextCode(sp, bp, code) { \
+ nextdata = (nextdata<<8) | *(bp)++; \
+ nextbits += 8; \
+ if (nextbits < nbits) { \
+ nextdata = (nextdata<<8) | *(bp)++; \
+ nextbits += 8; \
+ } \
+ code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \
+ nextbits -= nbits; \
+}
+
+static void
+codeLoop(TIFF* tif)
+{
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Bogus encoding, loop in the code table; scanline %d",
+ tif->tif_row);
+}
+
+static int
+LZWDecode(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+ LZWCodecState *sp = DecoderState(tif);
+ char *op = (char*) op0;
+ long occ = (long) occ0;
+ char *tp;
+ unsigned char *bp;
+ hcode_t code;
+ int len;
+ long nbits, nextbits, nextdata, nbitsmask;
+ code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+ (void) s;
+ assert(sp != NULL);
+ assert(sp->dec_codetab != NULL);
+ /*
+ * Restart interrupted output operation.
+ */
+ if (sp->dec_restart) {
+ long residue;
+
+ codep = sp->dec_codep;
+ residue = codep->length - sp->dec_restart;
+ if (residue > occ) {
+ /*
+ * Residue from previous decode is sufficient
+ * to satisfy decode request. Skip to the
+ * start of the decoded string, place decoded
+ * values in the output buffer, and return.
+ */
+ sp->dec_restart += occ;
+ do {
+ codep = codep->next;
+ } while (--residue > occ && codep);
+ if (codep) {
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ && codep);
+ }
+ return (1);
+ }
+ /*
+ * Residue satisfies only part of the decode request.
+ */
+ op += residue, occ -= residue;
+ tp = op;
+ do {
+ int t;
+ --tp;
+ t = codep->value;
+ codep = codep->next;
+ *tp = t;
+ } while (--residue && codep);
+ sp->dec_restart = 0;
+ }
+
+ bp = (unsigned char *)tif->tif_rawcp;
+ nbits = sp->lzw_nbits;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ nbitsmask = sp->dec_nbitsmask;
+ oldcodep = sp->dec_oldcodep;
+ free_entp = sp->dec_free_entp;
+ maxcodep = sp->dec_maxcodep;
+
+ while (occ > 0) {
+ NextCode(tif, sp, bp, code, GetNextCode);
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ free_entp = sp->dec_codetab + CODE_FIRST;
+ _TIFFmemset(free_entp, 0,
+ (CSIZE - CODE_FIRST) * sizeof (code_t));
+ nbits = BITS_MIN;
+ nbitsmask = MAXCODE(BITS_MIN);
+ maxcodep = sp->dec_codetab + nbitsmask-1;
+ NextCode(tif, sp, bp, code, GetNextCode);
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ *op++ = (char)code, occ--;
+ oldcodep = sp->dec_codetab + code;
+ continue;
+ }
+ codep = sp->dec_codetab + code;
+
+ /*
+ * Add the new entry to the code table.
+ */
+ if (free_entp < &sp->dec_codetab[0] ||
+ free_entp >= &sp->dec_codetab[CSIZE]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+
+ free_entp->next = oldcodep;
+ if (free_entp->next < &sp->dec_codetab[0] ||
+ free_entp->next >= &sp->dec_codetab[CSIZE]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ free_entp->firstchar = free_entp->next->firstchar;
+ free_entp->length = free_entp->next->length+1;
+ free_entp->value = (codep < free_entp) ?
+ codep->firstchar : free_entp->firstchar;
+ if (++free_entp > maxcodep) {
+ if (++nbits > BITS_MAX) /* should not happen */
+ nbits = BITS_MAX;
+ nbitsmask = MAXCODE(nbits);
+ maxcodep = sp->dec_codetab + nbitsmask-1;
+ }
+ oldcodep = codep;
+ if (code >= 256) {
+ /*
+ * Code maps to a string, copy string
+ * value to output (written in reverse).
+ */
+ if(codep->length == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Wrong length of decoded string: "
+ "data probably corrupted at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ if (codep->length > occ) {
+ /*
+ * String is too long for decode buffer,
+ * locate portion that will fit, copy to
+ * the decode buffer, and setup restart
+ * logic for the next decoding call.
+ */
+ sp->dec_codep = codep;
+ do {
+ codep = codep->next;
+ } while (codep && codep->length > occ);
+ if (codep) {
+ sp->dec_restart = occ;
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ && codep);
+ if (codep)
+ codeLoop(tif);
+ }
+ break;
+ }
+ len = codep->length;
+ tp = op + len;
+ do {
+ int t;
+ --tp;
+ t = codep->value;
+ codep = codep->next;
+ *tp = t;
+ } while (codep && tp > op);
+ if (codep) {
+ codeLoop(tif);
+ break;
+ }
+ op += len, occ -= len;
+ } else
+ *op++ = (char)code, occ--;
+ }
+
+ tif->tif_rawcp = (tidata_t) bp;
+ sp->lzw_nbits = (unsigned short) nbits;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->dec_nbitsmask = nbitsmask;
+ sp->dec_oldcodep = oldcodep;
+ sp->dec_free_entp = free_entp;
+ sp->dec_maxcodep = maxcodep;
+
+ if (occ > 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Not enough data at scanline %d (short %ld bytes)",
+ tif->tif_row, occ);
+ return (0);
+ }
+ return (1);
+}
+
+#ifdef LZW_COMPAT
+/*
+ * Decode a "hunk of data" for old images.
+ */
+#define GetNextCodeCompat(sp, bp, code) { \
+ nextdata |= (unsigned long) *(bp)++ << nextbits; \
+ nextbits += 8; \
+ if (nextbits < nbits) { \
+ nextdata |= (unsigned long) *(bp)++ << nextbits;\
+ nextbits += 8; \
+ } \
+ code = (hcode_t)(nextdata & nbitsmask); \
+ nextdata >>= nbits; \
+ nextbits -= nbits; \
+}
+
+static int
+LZWDecodeCompat(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+ LZWCodecState *sp = DecoderState(tif);
+ char *op = (char*) op0;
+ long occ = (long) occ0;
+ char *tp;
+ unsigned char *bp;
+ int code, nbits;
+ long nextbits, nextdata, nbitsmask;
+ code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+ (void) s;
+ assert(sp != NULL);
+ /*
+ * Restart interrupted output operation.
+ */
+ if (sp->dec_restart) {
+ long residue;
+
+ codep = sp->dec_codep;
+ residue = codep->length - sp->dec_restart;
+ if (residue > occ) {
+ /*
+ * Residue from previous decode is sufficient
+ * to satisfy decode request. Skip to the
+ * start of the decoded string, place decoded
+ * values in the output buffer, and return.
+ */
+ sp->dec_restart += occ;
+ do {
+ codep = codep->next;
+ } while (--residue > occ);
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ);
+ return (1);
+ }
+ /*
+ * Residue satisfies only part of the decode request.
+ */
+ op += residue, occ -= residue;
+ tp = op;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--residue);
+ sp->dec_restart = 0;
+ }
+
+ bp = (unsigned char *)tif->tif_rawcp;
+ nbits = sp->lzw_nbits;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ nbitsmask = sp->dec_nbitsmask;
+ oldcodep = sp->dec_oldcodep;
+ free_entp = sp->dec_free_entp;
+ maxcodep = sp->dec_maxcodep;
+
+ while (occ > 0) {
+ NextCode(tif, sp, bp, code, GetNextCodeCompat);
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ free_entp = sp->dec_codetab + CODE_FIRST;
+ _TIFFmemset(free_entp, 0,
+ (CSIZE - CODE_FIRST) * sizeof (code_t));
+ nbits = BITS_MIN;
+ nbitsmask = MAXCODE(BITS_MIN);
+ maxcodep = sp->dec_codetab + nbitsmask;
+ NextCode(tif, sp, bp, code, GetNextCodeCompat);
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecode: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ *op++ = code, occ--;
+ oldcodep = sp->dec_codetab + code;
+ continue;
+ }
+ codep = sp->dec_codetab + code;
+
+ /*
+ * Add the new entry to the code table.
+ */
+ if (free_entp < &sp->dec_codetab[0] ||
+ free_entp >= &sp->dec_codetab[CSIZE]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecodeCompat: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+
+ free_entp->next = oldcodep;
+ if (free_entp->next < &sp->dec_codetab[0] ||
+ free_entp->next >= &sp->dec_codetab[CSIZE]) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecodeCompat: Corrupted LZW table at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ free_entp->firstchar = free_entp->next->firstchar;
+ free_entp->length = free_entp->next->length+1;
+ free_entp->value = (codep < free_entp) ?
+ codep->firstchar : free_entp->firstchar;
+ if (++free_entp > maxcodep) {
+ if (++nbits > BITS_MAX) /* should not happen */
+ nbits = BITS_MAX;
+ nbitsmask = MAXCODE(nbits);
+ maxcodep = sp->dec_codetab + nbitsmask;
+ }
+ oldcodep = codep;
+ if (code >= 256) {
+ char *op_orig = op;
+ /*
+ * Code maps to a string, copy string
+ * value to output (written in reverse).
+ */
+ if(codep->length == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecodeCompat: Wrong length of decoded "
+ "string: data probably corrupted at scanline %d",
+ tif->tif_row);
+ return (0);
+ }
+ if (codep->length > occ) {
+ /*
+ * String is too long for decode buffer,
+ * locate portion that will fit, copy to
+ * the decode buffer, and setup restart
+ * logic for the next decoding call.
+ */
+ sp->dec_codep = codep;
+ do {
+ codep = codep->next;
+ } while (codep->length > occ);
+ sp->dec_restart = occ;
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ);
+ break;
+ }
+ op += codep->length, occ -= codep->length;
+ tp = op;
+ do {
+ *--tp = codep->value;
+ } while( (codep = codep->next) != NULL && tp > op_orig);
+ } else
+ *op++ = code, occ--;
+ }
+
+ tif->tif_rawcp = (tidata_t) bp;
+ sp->lzw_nbits = nbits;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->dec_nbitsmask = nbitsmask;
+ sp->dec_oldcodep = oldcodep;
+ sp->dec_free_entp = free_entp;
+ sp->dec_maxcodep = maxcodep;
+
+ if (occ > 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "LZWDecodeCompat: Not enough data at scanline %d (short %ld bytes)",
+ tif->tif_row, occ);
+ return (0);
+ }
+ return (1);
+}
+#endif /* LZW_COMPAT */
+
+/*
+ * LZW Encoding.
+ */
+
+static int
+LZWSetupEncode(TIFF* tif)
+{
+ LZWCodecState* sp = EncoderState(tif);
+ static const char module[] = "LZWSetupEncode";
+
+ assert(sp != NULL);
+ sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t));
+ if (sp->enc_hashtab == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module, "No space for LZW hash table");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+LZWPreEncode(TIFF* tif, tsample_t s)
+{
+ LZWCodecState *sp = EncoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+
+ if( sp->enc_hashtab == NULL )
+ {
+ tif->tif_setupencode( tif );
+ }
+
+ sp->lzw_nbits = BITS_MIN;
+ sp->lzw_maxcode = MAXCODE(BITS_MIN);
+ sp->lzw_free_ent = CODE_FIRST;
+ sp->lzw_nextbits = 0;
+ sp->lzw_nextdata = 0;
+ sp->enc_checkpoint = CHECK_GAP;
+ sp->enc_ratio = 0;
+ sp->enc_incount = 0;
+ sp->enc_outcount = 0;
+ /*
+ * The 4 here insures there is space for 2 max-sized
+ * codes in LZWEncode and LZWPostDecode.
+ */
+ sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4;
+ cl_hash(sp); /* clear hash table */
+ sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */
+ return (1);
+}
+
+#define CALCRATIO(sp, rat) { \
+ if (incount > 0x007fffff) { /* NB: shift will overflow */\
+ rat = outcount >> 8; \
+ rat = (rat == 0 ? 0x7fffffff : incount/rat); \
+ } else \
+ rat = (incount<<8) / outcount; \
+}
+#define PutNextCode(op, c) { \
+ nextdata = (nextdata << nbits) | c; \
+ nextbits += nbits; \
+ *op++ = (unsigned char)(nextdata >> (nextbits-8)); \
+ nextbits -= 8; \
+ if (nextbits >= 8) { \
+ *op++ = (unsigned char)(nextdata >> (nextbits-8)); \
+ nextbits -= 8; \
+ } \
+ outcount += nbits; \
+}
+
+/*
+ * Encode a chunk of pixels.
+ *
+ * Uses an open addressing double hashing (no chaining) on the
+ * prefix code/next character combination. We do a variant of
+ * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
+ * relatively-prime secondary probe. Here, the modular division
+ * first probe is gives way to a faster exclusive-or manipulation.
+ * Also do block compression with an adaptive reset, whereby the
+ * code table is cleared when the compression ratio decreases,
+ * but after the table fills. The variable-length output codes
+ * are re-sized at this point, and a CODE_CLEAR is generated
+ * for the decoder.
+ */
+static int
+LZWEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ register LZWCodecState *sp = EncoderState(tif);
+ register long fcode;
+ register hash_t *hp;
+ register int h, c;
+ hcode_t ent;
+ long disp;
+ long incount, outcount, checkpoint;
+ long nextdata, nextbits;
+ int free_ent, maxcode, nbits;
+ tidata_t op, limit;
+
+ (void) s;
+ if (sp == NULL)
+ return (0);
+
+ assert(sp->enc_hashtab != NULL);
+
+ /*
+ * Load local state.
+ */
+ incount = sp->enc_incount;
+ outcount = sp->enc_outcount;
+ checkpoint = sp->enc_checkpoint;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ free_ent = sp->lzw_free_ent;
+ maxcode = sp->lzw_maxcode;
+ nbits = sp->lzw_nbits;
+ op = tif->tif_rawcp;
+ limit = sp->enc_rawlimit;
+ ent = sp->enc_oldcode;
+
+ if (ent == (hcode_t) -1 && cc > 0) {
+ /*
+ * NB: This is safe because it can only happen
+ * at the start of a strip where we know there
+ * is space in the data buffer.
+ */
+ PutNextCode(op, CODE_CLEAR);
+ ent = *bp++; cc--; incount++;
+ }
+ while (cc > 0) {
+ c = *bp++; cc--; incount++;
+ fcode = ((long)c << BITS_MAX) + ent;
+ h = (c << HSHIFT) ^ ent; /* xor hashing */
+#ifdef _WINDOWS
+ /*
+ * Check hash index for an overflow.
+ */
+ if (h >= HSIZE)
+ h -= HSIZE;
+#endif
+ hp = &sp->enc_hashtab[h];
+ if (hp->hash == fcode) {
+ ent = hp->code;
+ continue;
+ }
+ if (hp->hash >= 0) {
+ /*
+ * Primary hash failed, check secondary hash.
+ */
+ disp = HSIZE - h;
+ if (h == 0)
+ disp = 1;
+ do {
+ /*
+ * Avoid pointer arithmetic 'cuz of
+ * wraparound problems with segments.
+ */
+ if ((h -= disp) < 0)
+ h += HSIZE;
+ hp = &sp->enc_hashtab[h];
+ if (hp->hash == fcode) {
+ ent = hp->code;
+ goto hit;
+ }
+ } while (hp->hash >= 0);
+ }
+ /*
+ * New entry, emit code and add to table.
+ */
+ /*
+ * Verify there is space in the buffer for the code
+ * and any potential Clear code that might be emitted
+ * below. The value of limit is setup so that there
+ * are at least 4 bytes free--room for 2 codes.
+ */
+ if (op > limit) {
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ TIFFFlushData1(tif);
+ op = tif->tif_rawdata;
+ }
+ PutNextCode(op, ent);
+ ent = c;
+ hp->code = free_ent++;
+ hp->hash = fcode;
+ if (free_ent == CODE_MAX-1) {
+ /* table is full, emit clear code and reset */
+ cl_hash(sp);
+ sp->enc_ratio = 0;
+ incount = 0;
+ outcount = 0;
+ free_ent = CODE_FIRST;
+ PutNextCode(op, CODE_CLEAR);
+ nbits = BITS_MIN;
+ maxcode = MAXCODE(BITS_MIN);
+ } else {
+ /*
+ * If the next entry is going to be too big for
+ * the code size, then increase it, if possible.
+ */
+ if (free_ent > maxcode) {
+ nbits++;
+ assert(nbits <= BITS_MAX);
+ maxcode = (int) MAXCODE(nbits);
+ } else if (incount >= checkpoint) {
+ long rat;
+ /*
+ * Check compression ratio and, if things seem
+ * to be slipping, clear the hash table and
+ * reset state. The compression ratio is a
+ * 24+8-bit fractional number.
+ */
+ checkpoint = incount+CHECK_GAP;
+ CALCRATIO(sp, rat);
+ if (rat <= sp->enc_ratio) {
+ cl_hash(sp);
+ sp->enc_ratio = 0;
+ incount = 0;
+ outcount = 0;
+ free_ent = CODE_FIRST;
+ PutNextCode(op, CODE_CLEAR);
+ nbits = BITS_MIN;
+ maxcode = MAXCODE(BITS_MIN);
+ } else
+ sp->enc_ratio = rat;
+ }
+ }
+ hit:
+ ;
+ }
+
+ /*
+ * Restore global state.
+ */
+ sp->enc_incount = incount;
+ sp->enc_outcount = outcount;
+ sp->enc_checkpoint = checkpoint;
+ sp->enc_oldcode = ent;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->lzw_free_ent = free_ent;
+ sp->lzw_maxcode = maxcode;
+ sp->lzw_nbits = nbits;
+ tif->tif_rawcp = op;
+ return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+LZWPostEncode(TIFF* tif)
+{
+ register LZWCodecState *sp = EncoderState(tif);
+ tidata_t op = tif->tif_rawcp;
+ long nextbits = sp->lzw_nextbits;
+ long nextdata = sp->lzw_nextdata;
+ long outcount = sp->enc_outcount;
+ int nbits = sp->lzw_nbits;
+
+ if (op > sp->enc_rawlimit) {
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ TIFFFlushData1(tif);
+ op = tif->tif_rawdata;
+ }
+ if (sp->enc_oldcode != (hcode_t) -1) {
+ PutNextCode(op, sp->enc_oldcode);
+ sp->enc_oldcode = (hcode_t) -1;
+ }
+ PutNextCode(op, CODE_EOI);
+ if (nextbits > 0)
+ *op++ = (unsigned char)(nextdata << (8-nextbits));
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ return (1);
+}
+
+/*
+ * Reset encoding hash table.
+ */
+static void
+cl_hash(LZWCodecState* sp)
+{
+ register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
+ register long i = HSIZE-8;
+
+ do {
+ i -= 8;
+ hp[-7].hash = -1;
+ hp[-6].hash = -1;
+ hp[-5].hash = -1;
+ hp[-4].hash = -1;
+ hp[-3].hash = -1;
+ hp[-2].hash = -1;
+ hp[-1].hash = -1;
+ hp[ 0].hash = -1;
+ hp -= 8;
+ } while (i >= 0);
+ for (i += 8; i > 0; i--, hp--)
+ hp->hash = -1;
+}
+
+static void
+LZWCleanup(TIFF* tif)
+{
+ (void)TIFFPredictorCleanup(tif);
+
+ assert(tif->tif_data != 0);
+
+ if (DecoderState(tif)->dec_codetab)
+ _TIFFfree(DecoderState(tif)->dec_codetab);
+
+ if (EncoderState(tif)->enc_hashtab)
+ _TIFFfree(EncoderState(tif)->enc_hashtab);
+
+ _TIFFfree(tif->tif_data);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+int
+TIFFInitLZW(TIFF* tif, int scheme)
+{
+ assert(scheme == COMPRESSION_LZW);
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LZWCodecState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ DecoderState(tif)->dec_codetab = NULL;
+ DecoderState(tif)->dec_decode = NULL;
+ EncoderState(tif)->enc_hashtab = NULL;
+ LZWState(tif)->rw_mode = tif->tif_mode;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = LZWSetupDecode;
+ tif->tif_predecode = LZWPreDecode;
+ tif->tif_decoderow = LZWDecode;
+ tif->tif_decodestrip = LZWDecode;
+ tif->tif_decodetile = LZWDecode;
+ tif->tif_setupencode = LZWSetupEncode;
+ tif->tif_preencode = LZWPreEncode;
+ tif->tif_postencode = LZWPostEncode;
+ tif->tif_encoderow = LZWEncode;
+ tif->tif_encodestrip = LZWEncode;
+ tif->tif_encodetile = LZWEncode;
+ tif->tif_cleanup = LZWCleanup;
+ /*
+ * Setup predictor setup.
+ */
+ (void) TIFFPredictorInit(tif);
+ return (1);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, "TIFFInitLZW",
+ "No space for LZW state block");
+ return (0);
+}
+
+/*
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#endif /* LZW_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_msdos.c b/Source/LibTIFF/tif_msdos.c
new file mode 100644
index 0000000..005a77c
--- /dev/null
+++ b/Source/LibTIFF/tif_msdos.c
@@ -0,0 +1,186 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_msdos.c,v 1.25 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library MSDOS-specific Routines.
+ */
+#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER)
+#include <io.h> /* for open, close, etc. function prototypes */
+#include <stdio.h>
+#endif
+#include "tiffiop.h"
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (read((int) fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (write((int) fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return (lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (close((int) fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ struct stat sb;
+ return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (void*) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+ TIFF *ret;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+ fd = open(name, m|O_BINARY, 0666);
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF*)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+
+ ret = TIFFFdOpen(fd, name, mode);
+
+ if (ret == NULL) close(fd);
+
+ return ret;
+}
+
+#ifdef __GNUC__
+extern char* malloc();
+extern char* realloc();
+#else
+#include <malloc.h>
+#endif
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+msdosWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = msdosWarningHandler;
+
+static void
+msdosErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = msdosErrorHandler;
diff --git a/Source/LibTIFF/tif_next.c b/Source/LibTIFF/tif_next.c
new file mode 100644
index 0000000..a11ceee
--- /dev/null
+++ b/Source/LibTIFF/tif_next.c
@@ -0,0 +1,147 @@
+/* $Id: tif_next.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef NEXT_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * NeXT 2-bit Grey Scale Compression Algorithm Support
+ */
+
+#define SETPIXEL(op, v) { \
+ switch (npixels++ & 3) { \
+ case 0: op[0] = (unsigned char) ((v) << 6); break; \
+ case 1: op[0] |= (v) << 4; break; \
+ case 2: op[0] |= (v) << 2; break; \
+ case 3: *op++ |= (v); break; \
+ } \
+}
+
+#define LITERALROW 0x00
+#define LITERALSPAN 0x40
+#define WHITE ((1<<2)-1)
+
+static int
+NeXTDecode(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ unsigned char *bp, *op;
+ tsize_t cc;
+ tidata_t row;
+ tsize_t scanline, n;
+
+ (void) s;
+ /*
+ * Each scanline is assumed to start off as all
+ * white (we assume a PhotometricInterpretation
+ * of ``min-is-black'').
+ */
+ for (op = buf, cc = occ; cc-- > 0;)
+ *op++ = 0xff;
+
+ bp = (unsigned char *)tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ scanline = tif->tif_scanlinesize;
+ for (row = buf; occ > 0; occ -= scanline, row += scanline) {
+ n = *bp++, cc--;
+ switch (n) {
+ case LITERALROW:
+ /*
+ * The entire scanline is given as literal values.
+ */
+ if (cc < scanline)
+ goto bad;
+ _TIFFmemcpy(row, bp, scanline);
+ bp += scanline;
+ cc -= scanline;
+ break;
+ case LITERALSPAN: {
+ tsize_t off;
+ /*
+ * The scanline has a literal span that begins at some
+ * offset.
+ */
+ off = (bp[0] * 256) + bp[1];
+ n = (bp[2] * 256) + bp[3];
+ if (cc < 4+n || off+n > scanline)
+ goto bad;
+ _TIFFmemcpy(row+off, bp+4, n);
+ bp += 4+n;
+ cc -= 4+n;
+ break;
+ }
+ default: {
+ uint32 npixels = 0, grey;
+ uint32 imagewidth = tif->tif_dir.td_imagewidth;
+
+ /*
+ * The scanline is composed of a sequence of constant
+ * color ``runs''. We shift into ``run mode'' and
+ * interpret bytes as codes of the form
+ * <color><npixels> until we've filled the scanline.
+ */
+ op = row;
+ for (;;) {
+ grey = (n>>6) & 0x3;
+ n &= 0x3f;
+ /*
+ * Ensure the run does not exceed the scanline
+ * bounds, potentially resulting in a security
+ * issue.
+ */
+ while (n-- > 0 && npixels < imagewidth)
+ SETPIXEL(op, grey);
+ if (npixels >= imagewidth)
+ break;
+ if (cc == 0)
+ goto bad;
+ n = *bp++, cc--;
+ }
+ break;
+ }
+ }
+ }
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ return (1);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "NeXTDecode: Not enough data for scanline %ld",
+ (long) tif->tif_row);
+ return (0);
+}
+
+int
+TIFFInitNeXT(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ tif->tif_decoderow = NeXTDecode;
+ tif->tif_decodestrip = NeXTDecode;
+ tif->tif_decodetile = NeXTDecode;
+ return (1);
+}
+#endif /* NEXT_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_ojpeg.c b/Source/LibTIFF/tif_ojpeg.c
new file mode 100644
index 0000000..3442dc0
--- /dev/null
+++ b/Source/LibTIFF/tif_ojpeg.c
@@ -0,0 +1,2424 @@
+/* $Id: tif_ojpeg.c,v 1.25 2009/09/06 13:11:28 drolon Exp $ */
+
+/* WARNING: The type of JPEG encapsulation defined by the TIFF Version 6.0
+ specification is now totally obsolete and deprecated for new applications and
+ images. This file was was created solely in order to read unconverted images
+ still present on some users' computer systems. It will never be extended
+ to write such files. Writing new-style JPEG compressed TIFFs is implemented
+ in tif_jpeg.c.
+
+ The code is carefully crafted to robustly read all gathered JPEG-in-TIFF
+ testfiles, and anticipate as much as possible all other... But still, it may
+ fail on some. If you encounter problems, please report them on the TIFF
+ mailing list and/or to Joris Van Damme <info@awaresystems.be>.
+
+ Please read the file called "TIFF Technical Note #2" if you need to be
+ convinced this compression scheme is bad and breaks TIFF. That document
+ is linked to from the LibTiff site <http://www.remotesensing.org/libtiff/>
+ and from AWare Systems' TIFF section
+ <http://www.awaresystems.be/imaging/tiff.html>. It is also absorbed
+ in Adobe's specification supplements, marked "draft" up to this day, but
+ supported by the TIFF community.
+
+ This file interfaces with Release 6B of the JPEG Library written by the
+ Independent JPEG Group. Previous versions of this file required a hack inside
+ the LibJpeg library. This version no longer requires that. Remember to
+ remove the hack if you update from the old version.
+
+ Copyright (c) Joris Van Damme <info@awaresystems.be>
+ Copyright (c) AWare Systems <http://www.awaresystems.be/>
+
+ The licence agreement for this file is the same as the rest of the LibTiff
+ library.
+
+ IN NO EVENT SHALL JORIS VAN DAMME OR AWARE SYSTEMS BE LIABLE FOR
+ ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ OF THIS SOFTWARE.
+
+ Joris Van Damme and/or AWare Systems may be available for custom
+ developement. If you like what you see, and need anything similar or related,
+ contact <info@awaresystems.be>.
+*/
+
+/* What is what, and what is not?
+
+ This decoder starts with an input stream, that is essentially the JpegInterchangeFormat
+ stream, if any, followed by the strile data, if any. This stream is read in
+ OJPEGReadByte and related functions.
+
+ It analyzes the start of this stream, until it encounters non-marker data, i.e.
+ compressed image data. Some of the header markers it sees have no actual content,
+ like the SOI marker, and APP/COM markers that really shouldn't even be there. Some
+ other markers do have content, and the valuable bits and pieces of information
+ in these markers are saved, checking all to verify that the stream is more or
+ less within expected bounds. This happens inside the OJPEGReadHeaderInfoSecStreamXxx
+ functions.
+
+ Some OJPEG imagery contains no valid JPEG header markers. This situation is picked
+ up on if we've seen no SOF marker when we're at the start of the compressed image
+ data. In this case, the tables are read from JpegXxxTables tags, and the other
+ bits and pieces of information is initialized to its most basic value. This is
+ implemented in the OJPEGReadHeaderInfoSecTablesXxx functions.
+
+ When this is complete, a good and valid JPEG header can be assembled, and this is
+ passed through to LibJpeg. When that's done, the remainder of the input stream, i.e.
+ the compressed image data, can be passed through unchanged. This is done in
+ OJPEGWriteStream functions.
+
+ LibTiff rightly expects to know the subsampling values before decompression. Just like
+ in new-style JPEG-in-TIFF, though, or even more so, actually, the YCbCrsubsampling
+ tag is notoriously unreliable. To correct these tag values with the ones inside
+ the JPEG stream, the first part of the input stream is pre-scanned in
+ OJPEGSubsamplingCorrect, making no note of any other data, reporting no warnings
+ or errors, up to the point where either these values are read, or it's clear they
+ aren't there. This means that some of the data is read twice, but we feel speed
+ in correcting these values is important enough to warrant this sacrifice. Allthough
+ there is currently no define or other configuration mechanism to disable this behaviour,
+ the actual header scanning is build to robustly respond with error report if it
+ should encounter an uncorrected mismatch of subsampling values. See
+ OJPEGReadHeaderInfoSecStreamSof.
+
+ The restart interval and restart markers are the most tricky part... The restart
+ interval can be specified in a tag. It can also be set inside the input JPEG stream.
+ It can be used inside the input JPEG stream. If reading from strile data, we've
+ consistenly discovered the need to insert restart markers in between the different
+ striles, as is also probably the most likely interpretation of the original TIFF 6.0
+ specification. With all this setting of interval, and actual use of markers that is not
+ predictable at the time of valid JPEG header assembly, the restart thing may turn
+ out the Achilles heel of this implementation. Fortunately, most OJPEG writer vendors
+ succeed in reading back what they write, which may be the reason why we've been able
+ to discover ways that seem to work.
+
+ Some special provision is made for planarconfig separate OJPEG files. These seem
+ to consistently contain header info, a SOS marker, a plane, SOS marker, plane, SOS,
+ and plane. This may or may not be a valid JPEG configuration, we don't know and don't
+ care. We want LibTiff to be able to access the planes individually, without huge
+ buffering inside LibJpeg, anyway. So we compose headers to feed to LibJpeg, in this
+ case, that allow us to pass a single plane such that LibJpeg sees a valid
+ single-channel JPEG stream. Locating subsequent SOS markers, and thus subsequent
+ planes, is done inside OJPEGReadSecondarySos.
+
+ The benefit of the scheme is... that it works, basically. We know of no other that
+ does. It works without checking software tag, or otherwise going about things in an
+ OJPEG flavor specific manner. Instead, it is a single scheme, that covers the cases
+ with and without JpegInterchangeFormat, with and without striles, with part of
+ the header in JpegInterchangeFormat and remainder in first strile, etc. It is forgiving
+ and robust, may likely work with OJPEG flavors we've not seen yet, and makes most out
+ of the data.
+
+ Another nice side-effect is that a complete JPEG single valid stream is build if
+ planarconfig is not separate (vast majority). We may one day use that to build
+ converters to JPEG, and/or to new-style JPEG compression inside TIFF.
+
+ A dissadvantage is the lack of random access to the individual striles. This is the
+ reason for much of the complicated restart-and-position stuff inside OJPEGPreDecode.
+ Applications would do well accessing all striles in order, as this will result in
+ a single sequential scan of the input stream, and no restarting of LibJpeg decoding
+ session.
+*/
+
+
+#include "tiffiop.h"
+#ifdef OJPEG_SUPPORT
+
+/* Configuration defines here are:
+ * JPEG_ENCAP_EXTERNAL: The normal way to call libjpeg, uses longjump. In some environments,
+ * like eg LibTiffDelphi, this is not possible. For this reason, the actual calls to
+ * libjpeg, with longjump stuff, are encapsulated in dedicated functions. When
+ * JPEG_ENCAP_EXTERNAL is defined, these encapsulating functions are declared external
+ * to this unit, and can be defined elsewhere to use stuff other then longjump.
+ * The default mode, without JPEG_ENCAP_EXTERNAL, implements the call encapsulators
+ * here, internally, with normal longjump.
+ * SETJMP, LONGJMP, JMP_BUF: On some machines/environments a longjump equivalent is
+ * conviniently available, but still it may be worthwhile to use _setjmp or sigsetjmp
+ * in place of plain setjmp. These macros will make it easier. It is useless
+ * to fiddle with these if you define JPEG_ENCAP_EXTERNAL.
+ * OJPEG_BUFFER: Define the size of the desired buffer here. Should be small enough so as to guarantee
+ * instant processing, optimal streaming and optimal use of processor cache, but also big
+ * enough so as to not result in significant call overhead. It should be at least a few
+ * bytes to accomodate some structures (this is verified in asserts), but it would not be
+ * sensible to make it this small anyway, and it should be at most 64K since it is indexed
+ * with uint16. We recommend 2K.
+ * EGYPTIANWALK: You could also define EGYPTIANWALK here, but it is not used anywhere and has
+ * absolutely no effect. That is why most people insist the EGYPTIANWALK is a bit silly.
+ */
+
+/* #define LIBJPEG_ENCAP_EXTERNAL */
+#define SETJMP(jbuf) setjmp(jbuf)
+#define LONGJMP(jbuf,code) longjmp(jbuf,code)
+#define JMP_BUF jmp_buf
+#define OJPEG_BUFFER 2048
+/* define EGYPTIANWALK */
+
+#define JPEG_MARKER_SOF0 0xC0
+#define JPEG_MARKER_SOF1 0xC1
+#define JPEG_MARKER_SOF3 0xC3
+#define JPEG_MARKER_DHT 0xC4
+#define JPEG_MARKER_RST0 0XD0
+#define JPEG_MARKER_SOI 0xD8
+#define JPEG_MARKER_EOI 0xD9
+#define JPEG_MARKER_SOS 0xDA
+#define JPEG_MARKER_DQT 0xDB
+#define JPEG_MARKER_DRI 0xDD
+#define JPEG_MARKER_APP0 0xE0
+#define JPEG_MARKER_COM 0xFE
+
+#define FIELD_OJPEG_JPEGINTERCHANGEFORMAT (FIELD_CODEC+0)
+#define FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH (FIELD_CODEC+1)
+#define FIELD_OJPEG_JPEGQTABLES (FIELD_CODEC+2)
+#define FIELD_OJPEG_JPEGDCTABLES (FIELD_CODEC+3)
+#define FIELD_OJPEG_JPEGACTABLES (FIELD_CODEC+4)
+#define FIELD_OJPEG_JPEGPROC (FIELD_CODEC+5)
+#define FIELD_OJPEG_JPEGRESTARTINTERVAL (FIELD_CODEC+6)
+#define FIELD_OJPEG_COUNT 7
+
+static const TIFFFieldInfo ojpeg_field_info[] = {
+ {TIFFTAG_JPEGIFOFFSET,1,1,TIFF_LONG,FIELD_OJPEG_JPEGINTERCHANGEFORMAT,TRUE,FALSE,"JpegInterchangeFormat"},
+ {TIFFTAG_JPEGIFBYTECOUNT,1,1,TIFF_LONG,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH,TRUE,FALSE,"JpegInterchangeFormatLength"},
+ {TIFFTAG_JPEGQTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGQTABLES,FALSE,TRUE,"JpegQTables"},
+ {TIFFTAG_JPEGDCTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGDCTABLES,FALSE,TRUE,"JpegDcTables"},
+ {TIFFTAG_JPEGACTABLES,TIFF_VARIABLE,TIFF_VARIABLE,TIFF_LONG,FIELD_OJPEG_JPEGACTABLES,FALSE,TRUE,"JpegAcTables"},
+ {TIFFTAG_JPEGPROC,1,1,TIFF_SHORT,FIELD_OJPEG_JPEGPROC,FALSE,FALSE,"JpegProc"},
+ {TIFFTAG_JPEGRESTARTINTERVAL,1,1,TIFF_SHORT,FIELD_OJPEG_JPEGRESTARTINTERVAL,FALSE,FALSE,"JpegRestartInterval"},
+};
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+#include <setjmp.h>
+#endif
+
+#include "jpeglib.h"
+#include "jerror.h"
+
+typedef struct jpeg_error_mgr jpeg_error_mgr;
+typedef struct jpeg_common_struct jpeg_common_struct;
+typedef struct jpeg_decompress_struct jpeg_decompress_struct;
+typedef struct jpeg_source_mgr jpeg_source_mgr;
+
+typedef enum {
+ osibsNotSetYet,
+ osibsJpegInterchangeFormat,
+ osibsStrile,
+ osibsEof
+} OJPEGStateInBufferSource;
+
+typedef enum {
+ ososSoi,
+ ososQTable0,ososQTable1,ososQTable2,ososQTable3,
+ ososDcTable0,ososDcTable1,ososDcTable2,ososDcTable3,
+ ososAcTable0,ososAcTable1,ososAcTable2,ososAcTable3,
+ ososDri,
+ ososSof,
+ ososSos,
+ ososCompressed,
+ ososRst,
+ ososEoi
+} OJPEGStateOutState;
+
+typedef struct {
+ TIFF* tif;
+ #ifndef LIBJPEG_ENCAP_EXTERNAL
+ JMP_BUF exit_jmpbuf;
+ #endif
+ TIFFVGetMethod vgetparent;
+ TIFFVSetMethod vsetparent;
+ toff_t file_size;
+ uint32 image_width;
+ uint32 image_length;
+ uint32 strile_width;
+ uint32 strile_length;
+ uint32 strile_length_total;
+ uint8 samples_per_pixel;
+ uint8 plane_sample_offset;
+ uint8 samples_per_pixel_per_plane;
+ toff_t jpeg_interchange_format;
+ toff_t jpeg_interchange_format_length;
+ uint8 jpeg_proc;
+ uint8 subsamplingcorrect;
+ uint8 subsamplingcorrect_done;
+ uint8 subsampling_tag;
+ uint8 subsampling_hor;
+ uint8 subsampling_ver;
+ uint8 subsampling_force_desubsampling_inside_decompression;
+ uint8 qtable_offset_count;
+ uint8 dctable_offset_count;
+ uint8 actable_offset_count;
+ toff_t qtable_offset[3];
+ toff_t dctable_offset[3];
+ toff_t actable_offset[3];
+ uint8* qtable[4];
+ uint8* dctable[4];
+ uint8* actable[4];
+ uint16 restart_interval;
+ uint8 restart_index;
+ uint8 sof_log;
+ uint8 sof_marker_id;
+ uint32 sof_x;
+ uint32 sof_y;
+ uint8 sof_c[3];
+ uint8 sof_hv[3];
+ uint8 sof_tq[3];
+ uint8 sos_cs[3];
+ uint8 sos_tda[3];
+ struct {
+ uint8 log;
+ OJPEGStateInBufferSource in_buffer_source;
+ tstrile_t in_buffer_next_strile;
+ toff_t in_buffer_file_pos;
+ toff_t in_buffer_file_togo;
+ } sos_end[3];
+ uint8 readheader_done;
+ uint8 writeheader_done;
+ tsample_t write_cursample;
+ tstrile_t write_curstrile;
+ uint8 libjpeg_session_active;
+ uint8 libjpeg_jpeg_query_style;
+ jpeg_error_mgr libjpeg_jpeg_error_mgr;
+ jpeg_decompress_struct libjpeg_jpeg_decompress_struct;
+ jpeg_source_mgr libjpeg_jpeg_source_mgr;
+ uint8 subsampling_convert_log;
+ uint32 subsampling_convert_ylinelen;
+ uint32 subsampling_convert_ylines;
+ uint32 subsampling_convert_clinelen;
+ uint32 subsampling_convert_clines;
+ uint32 subsampling_convert_ybuflen;
+ uint32 subsampling_convert_cbuflen;
+ uint32 subsampling_convert_ycbcrbuflen;
+ uint8* subsampling_convert_ycbcrbuf;
+ uint8* subsampling_convert_ybuf;
+ uint8* subsampling_convert_cbbuf;
+ uint8* subsampling_convert_crbuf;
+ uint32 subsampling_convert_ycbcrimagelen;
+ uint8** subsampling_convert_ycbcrimage;
+ uint32 subsampling_convert_clinelenout;
+ uint32 subsampling_convert_state;
+ uint32 bytes_per_line; /* if the codec outputs subsampled data, a 'line' in bytes_per_line */
+ uint32 lines_per_strile; /* and lines_per_strile means subsampling_ver desubsampled rows */
+ OJPEGStateInBufferSource in_buffer_source;
+ tstrile_t in_buffer_next_strile;
+ tstrile_t in_buffer_strile_count;
+ toff_t in_buffer_file_pos;
+ uint8 in_buffer_file_pos_log;
+ toff_t in_buffer_file_togo;
+ uint16 in_buffer_togo;
+ uint8* in_buffer_cur;
+ uint8 in_buffer[OJPEG_BUFFER];
+ OJPEGStateOutState out_state;
+ uint8 out_buffer[OJPEG_BUFFER];
+ uint8* skip_buffer;
+} OJPEGState;
+
+static int OJPEGVGetField(TIFF* tif, ttag_t tag, va_list ap);
+static int OJPEGVSetField(TIFF* tif, ttag_t tag, va_list ap);
+static void OJPEGPrintDir(TIFF* tif, FILE* fd, long flags);
+
+static int OJPEGSetupDecode(TIFF* tif);
+static int OJPEGPreDecode(TIFF* tif, tsample_t s);
+static int OJPEGPreDecodeSkipRaw(TIFF* tif);
+static int OJPEGPreDecodeSkipScanlines(TIFF* tif);
+static int OJPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s);
+static int OJPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc);
+static int OJPEGDecodeScanlines(TIFF* tif, tidata_t buf, tsize_t cc);
+static void OJPEGPostDecode(TIFF* tif, tidata_t buf, tsize_t cc);
+static int OJPEGSetupEncode(TIFF* tif);
+static int OJPEGPreEncode(TIFF* tif, tsample_t s);
+static int OJPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s);
+static int OJPEGPostEncode(TIFF* tif);
+static void OJPEGCleanup(TIFF* tif);
+
+static void OJPEGSubsamplingCorrect(TIFF* tif);
+static int OJPEGReadHeaderInfo(TIFF* tif);
+static int OJPEGReadSecondarySos(TIFF* tif, tsample_t s);
+static int OJPEGWriteHeaderInfo(TIFF* tif);
+static void OJPEGLibjpegSessionAbort(TIFF* tif);
+
+static int OJPEGReadHeaderInfoSec(TIFF* tif);
+static int OJPEGReadHeaderInfoSecStreamDri(TIFF* tif);
+static int OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif);
+static int OJPEGReadHeaderInfoSecStreamDht(TIFF* tif);
+static int OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id);
+static int OJPEGReadHeaderInfoSecStreamSos(TIFF* tif);
+static int OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif);
+static int OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif);
+static int OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif);
+
+static int OJPEGReadBufferFill(OJPEGState* sp);
+static int OJPEGReadByte(OJPEGState* sp, uint8* byte);
+static int OJPEGReadBytePeek(OJPEGState* sp, uint8* byte);
+static void OJPEGReadByteAdvance(OJPEGState* sp);
+static int OJPEGReadWord(OJPEGState* sp, uint16* word);
+static int OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem);
+static void OJPEGReadSkip(OJPEGState* sp, uint16 len);
+
+static int OJPEGWriteStream(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
+static void OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
+static void OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len);
+static void OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len);
+static int OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len);
+static void OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len);
+
+#ifdef LIBJPEG_ENCAP_EXTERNAL
+extern int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
+extern int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image);
+extern int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
+extern int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines);
+extern int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines);
+extern void jpeg_encap_unwind(TIFF* tif);
+#else
+static int jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* j);
+static int jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image);
+static int jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo);
+static int jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines);
+static int jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines);
+static void jpeg_encap_unwind(TIFF* tif);
+#endif
+
+static void OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo);
+static void OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo);
+static void OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo);
+static boolean OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo);
+static void OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes);
+static boolean OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired);
+static void OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo);
+
+int
+TIFFInitOJPEG(TIFF* tif, int scheme)
+{
+ static const char module[]="TIFFInitOJPEG";
+ OJPEGState* sp;
+
+ assert(scheme==COMPRESSION_OJPEG);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif,ojpeg_field_info,FIELD_OJPEG_COUNT)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging Old JPEG codec-specific tags failed");
+ return 0;
+ }
+
+ /* state block */
+ sp=_TIFFmalloc(sizeof(OJPEGState));
+ if (sp==NULL)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"No space for OJPEG state block");
+ return(0);
+ }
+ _TIFFmemset(sp,0,sizeof(OJPEGState));
+ sp->tif=tif;
+ sp->jpeg_proc=1;
+ sp->subsampling_hor=2;
+ sp->subsampling_ver=2;
+ TIFFSetField(tif,TIFFTAG_YCBCRSUBSAMPLING,2,2);
+ /* tif codec methods */
+ tif->tif_setupdecode=OJPEGSetupDecode;
+ tif->tif_predecode=OJPEGPreDecode;
+ tif->tif_postdecode=OJPEGPostDecode;
+ tif->tif_decoderow=OJPEGDecode;
+ tif->tif_decodestrip=OJPEGDecode;
+ tif->tif_decodetile=OJPEGDecode;
+ tif->tif_setupencode=OJPEGSetupEncode;
+ tif->tif_preencode=OJPEGPreEncode;
+ tif->tif_postencode=OJPEGPostEncode;
+ tif->tif_encoderow=OJPEGEncode;
+ tif->tif_encodestrip=OJPEGEncode;
+ tif->tif_encodetile=OJPEGEncode;
+ tif->tif_cleanup=OJPEGCleanup;
+ tif->tif_data=(tidata_t)sp;
+ /* tif tag methods */
+ sp->vgetparent=tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield=OJPEGVGetField;
+ sp->vsetparent=tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield=OJPEGVSetField;
+ tif->tif_tagmethods.printdir=OJPEGPrintDir;
+ /* Some OJPEG files don't have strip or tile offsets or bytecounts tags.
+ Some others do, but have totally meaningless or corrupt values
+ in these tags. In these cases, the JpegInterchangeFormat stream is
+ reliable. In any case, this decoder reads the compressed data itself,
+ from the most reliable locations, and we need to notify encapsulating
+ LibTiff not to read raw strips or tiles for us. */
+ tif->tif_flags|=TIFF_NOREADRAW;
+ return(1);
+}
+
+static int
+OJPEGVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ switch(tag)
+ {
+ case TIFFTAG_JPEGIFOFFSET:
+ *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format;
+ break;
+ case TIFFTAG_JPEGIFBYTECOUNT:
+ *va_arg(ap,uint32*)=(uint32)sp->jpeg_interchange_format_length;
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ if (sp->subsamplingcorrect_done==0)
+ OJPEGSubsamplingCorrect(tif);
+ *va_arg(ap,uint16*)=(uint16)sp->subsampling_hor;
+ *va_arg(ap,uint16*)=(uint16)sp->subsampling_ver;
+ break;
+ case TIFFTAG_JPEGQTABLES:
+ *va_arg(ap,uint32*)=(uint32)sp->qtable_offset_count;
+ *va_arg(ap,void**)=(void*)sp->qtable_offset;
+ break;
+ case TIFFTAG_JPEGDCTABLES:
+ *va_arg(ap,uint32*)=(uint32)sp->dctable_offset_count;
+ *va_arg(ap,void**)=(void*)sp->dctable_offset;
+ break;
+ case TIFFTAG_JPEGACTABLES:
+ *va_arg(ap,uint32*)=(uint32)sp->actable_offset_count;
+ *va_arg(ap,void**)=(void*)sp->actable_offset;
+ break;
+ case TIFFTAG_JPEGPROC:
+ *va_arg(ap,uint16*)=(uint16)sp->jpeg_proc;
+ break;
+ case TIFFTAG_JPEGRESTARTINTERVAL:
+ *va_arg(ap,uint16*)=sp->restart_interval;
+ break;
+ default:
+ return (*sp->vgetparent)(tif,tag,ap);
+ }
+ return (1);
+}
+
+static int
+OJPEGVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ static const char module[]="OJPEGVSetField";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint32 ma;
+ uint32* mb;
+ uint32 n;
+ switch(tag)
+ {
+ case TIFFTAG_JPEGIFOFFSET:
+ sp->jpeg_interchange_format=(toff_t)va_arg(ap,uint32);
+ break;
+ case TIFFTAG_JPEGIFBYTECOUNT:
+ sp->jpeg_interchange_format_length=(toff_t)va_arg(ap,uint32);
+ break;
+ case TIFFTAG_YCBCRSUBSAMPLING:
+ sp->subsampling_tag=1;
+ sp->subsampling_hor=(uint8)va_arg(ap,int);
+ sp->subsampling_ver=(uint8)va_arg(ap,int);
+ tif->tif_dir.td_ycbcrsubsampling[0]=sp->subsampling_hor;
+ tif->tif_dir.td_ycbcrsubsampling[1]=sp->subsampling_ver;
+ break;
+ case TIFFTAG_JPEGQTABLES:
+ ma=va_arg(ap,uint32);
+ if (ma!=0)
+ {
+ if (ma>3)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JpegQTables tag has incorrect count");
+ return(0);
+ }
+ sp->qtable_offset_count=(uint8)ma;
+ mb=va_arg(ap,uint32*);
+ for (n=0; n<ma; n++)
+ sp->qtable_offset[n]=(toff_t)mb[n];
+ }
+ break;
+ case TIFFTAG_JPEGDCTABLES:
+ ma=va_arg(ap,uint32);
+ if (ma!=0)
+ {
+ if (ma>3)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JpegDcTables tag has incorrect count");
+ return(0);
+ }
+ sp->dctable_offset_count=(uint8)ma;
+ mb=va_arg(ap,uint32*);
+ for (n=0; n<ma; n++)
+ sp->dctable_offset[n]=(toff_t)mb[n];
+ }
+ break;
+ case TIFFTAG_JPEGACTABLES:
+ ma=va_arg(ap,uint32);
+ if (ma!=0)
+ {
+ if (ma>3)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JpegAcTables tag has incorrect count");
+ return(0);
+ }
+ sp->actable_offset_count=(uint8)ma;
+ mb=va_arg(ap,uint32*);
+ for (n=0; n<ma; n++)
+ sp->actable_offset[n]=(toff_t)mb[n];
+ }
+ break;
+ case TIFFTAG_JPEGPROC:
+ sp->jpeg_proc=(uint8)va_arg(ap,uint32);
+ break;
+ case TIFFTAG_JPEGRESTARTINTERVAL:
+ sp->restart_interval=(uint16)va_arg(ap,uint32);
+ break;
+ default:
+ return (*sp->vsetparent)(tif,tag,ap);
+ }
+ TIFFSetFieldBit(tif,_TIFFFieldWithTag(tif,tag)->field_bit);
+ tif->tif_flags|=TIFF_DIRTYDIRECT;
+ return(1);
+}
+
+static void
+OJPEGPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ (void)flags;
+ assert(sp!=NULL);
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMAT))
+ fprintf(fd," JpegInterchangeFormat: %lu\n",(unsigned long)sp->jpeg_interchange_format);
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGINTERCHANGEFORMATLENGTH))
+ fprintf(fd," JpegInterchangeFormatLength: %lu\n",(unsigned long)sp->jpeg_interchange_format_length);
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGQTABLES))
+ {
+ fprintf(fd," JpegQTables:");
+ for (m=0; m<sp->qtable_offset_count; m++)
+ fprintf(fd," %lu",(unsigned long)sp->qtable_offset[m]);
+ fprintf(fd,"\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGDCTABLES))
+ {
+ fprintf(fd," JpegDcTables:");
+ for (m=0; m<sp->dctable_offset_count; m++)
+ fprintf(fd," %lu",(unsigned long)sp->dctable_offset[m]);
+ fprintf(fd,"\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGACTABLES))
+ {
+ fprintf(fd," JpegAcTables:");
+ for (m=0; m<sp->actable_offset_count; m++)
+ fprintf(fd," %lu",(unsigned long)sp->actable_offset[m]);
+ fprintf(fd,"\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGPROC))
+ fprintf(fd," JpegProc: %u\n",(unsigned int)sp->jpeg_proc);
+ if (TIFFFieldSet(tif,FIELD_OJPEG_JPEGRESTARTINTERVAL))
+ fprintf(fd," JpegRestartInterval: %u\n",(unsigned int)sp->restart_interval);
+}
+
+static int
+OJPEGSetupDecode(TIFF* tif)
+{
+ static const char module[]="OJPEGSetupDecode";
+ TIFFWarningExt(tif->tif_clientdata,module,"Depreciated and troublesome old-style JPEG compression mode, please convert to new-style JPEG compression and notify vendor of writing software");
+ return(1);
+}
+
+static int
+OJPEGPreDecode(TIFF* tif, tsample_t s)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ tstrile_t m;
+ if (sp->subsamplingcorrect_done==0)
+ OJPEGSubsamplingCorrect(tif);
+ if (sp->readheader_done==0)
+ {
+ if (OJPEGReadHeaderInfo(tif)==0)
+ return(0);
+ }
+ if (sp->sos_end[s].log==0)
+ {
+ if (OJPEGReadSecondarySos(tif,s)==0)
+ return(0);
+ }
+ if isTiled(tif)
+ m=(tstrile_t)tif->tif_curtile;
+ else
+ m=(tstrile_t)tif->tif_curstrip;
+ if ((sp->writeheader_done!=0) && ((sp->write_cursample!=s) || (sp->write_curstrile>m)))
+ {
+ if (sp->libjpeg_session_active!=0)
+ OJPEGLibjpegSessionAbort(tif);
+ sp->writeheader_done=0;
+ }
+ if (sp->writeheader_done==0)
+ {
+ sp->plane_sample_offset=s;
+ sp->write_cursample=s;
+ sp->write_curstrile=s*tif->tif_dir.td_stripsperimage;
+ if ((sp->in_buffer_file_pos_log==0) ||
+ (sp->in_buffer_file_pos-sp->in_buffer_togo!=sp->sos_end[s].in_buffer_file_pos))
+ {
+ sp->in_buffer_source=sp->sos_end[s].in_buffer_source;
+ sp->in_buffer_next_strile=sp->sos_end[s].in_buffer_next_strile;
+ sp->in_buffer_file_pos=sp->sos_end[s].in_buffer_file_pos;
+ sp->in_buffer_file_pos_log=0;
+ sp->in_buffer_file_togo=sp->sos_end[s].in_buffer_file_togo;
+ sp->in_buffer_togo=0;
+ sp->in_buffer_cur=0;
+ }
+ if (OJPEGWriteHeaderInfo(tif)==0)
+ return(0);
+ }
+ while (sp->write_curstrile<m)
+ {
+ if (sp->libjpeg_jpeg_query_style==0)
+ {
+ if (OJPEGPreDecodeSkipRaw(tif)==0)
+ return(0);
+ }
+ else
+ {
+ if (OJPEGPreDecodeSkipScanlines(tif)==0)
+ return(0);
+ }
+ sp->write_curstrile++;
+ }
+ return(1);
+}
+
+static int
+OJPEGPreDecodeSkipRaw(TIFF* tif)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint32 m;
+ m=sp->lines_per_strile;
+ if (sp->subsampling_convert_state!=0)
+ {
+ if (sp->subsampling_convert_clines-sp->subsampling_convert_state>=m)
+ {
+ sp->subsampling_convert_state+=m;
+ if (sp->subsampling_convert_state==sp->subsampling_convert_clines)
+ sp->subsampling_convert_state=0;
+ return(1);
+ }
+ m-=sp->subsampling_convert_clines-sp->subsampling_convert_state;
+ sp->subsampling_convert_state=0;
+ }
+ while (m>=sp->subsampling_convert_clines)
+ {
+ if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
+ return(0);
+ m-=sp->subsampling_convert_clines;
+ }
+ if (m>0)
+ {
+ if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
+ return(0);
+ sp->subsampling_convert_state=m;
+ }
+ return(1);
+}
+
+static int
+OJPEGPreDecodeSkipScanlines(TIFF* tif)
+{
+ static const char module[]="OJPEGPreDecodeSkipScanlines";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint32 m;
+ if (sp->skip_buffer==NULL)
+ {
+ sp->skip_buffer=_TIFFmalloc(sp->bytes_per_line);
+ if (sp->skip_buffer==NULL)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ }
+ for (m=0; m<sp->lines_per_strile; m++)
+ {
+ if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&sp->skip_buffer,1)==0)
+ return(0);
+ }
+ return(1);
+}
+
+static int
+OJPEGDecode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ (void)s;
+ if (sp->libjpeg_jpeg_query_style==0)
+ {
+ if (OJPEGDecodeRaw(tif,buf,cc)==0)
+ return(0);
+ }
+ else
+ {
+ if (OJPEGDecodeScanlines(tif,buf,cc)==0)
+ return(0);
+ }
+ return(1);
+}
+
+static int
+OJPEGDecodeRaw(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ static const char module[]="OJPEGDecodeRaw";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8* m;
+ uint32 n;
+ uint8* oy;
+ uint8* ocb;
+ uint8* ocr;
+ uint8* p;
+ uint32 q;
+ uint8* r;
+ uint8 sx,sy;
+ if (cc%sp->bytes_per_line!=0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read");
+ return(0);
+ }
+ assert(cc>0);
+ m=buf;
+ n=cc;
+ do
+ {
+ if (sp->subsampling_convert_state==0)
+ {
+ if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
+ return(0);
+ }
+ oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen;
+ ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
+ ocr=sp->subsampling_convert_crbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
+ p=m;
+ for (q=0; q<sp->subsampling_convert_clinelenout; q++)
+ {
+ r=oy;
+ for (sy=0; sy<sp->subsampling_ver; sy++)
+ {
+ for (sx=0; sx<sp->subsampling_hor; sx++)
+ *p++=*r++;
+ r+=sp->subsampling_convert_ylinelen-sp->subsampling_hor;
+ }
+ oy+=sp->subsampling_hor;
+ *p++=*ocb++;
+ *p++=*ocr++;
+ }
+ sp->subsampling_convert_state++;
+ if (sp->subsampling_convert_state==sp->subsampling_convert_clines)
+ sp->subsampling_convert_state=0;
+ m+=sp->bytes_per_line;
+ n-=sp->bytes_per_line;
+ } while(n>0);
+ return(1);
+}
+
+static int
+OJPEGDecodeScanlines(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ static const char module[]="OJPEGDecodeScanlines";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8* m;
+ uint32 n;
+ if (cc%sp->bytes_per_line!=0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Fractional scanline not read");
+ return(0);
+ }
+ assert(cc>0);
+ m=buf;
+ n=cc;
+ do
+ {
+ if (jpeg_read_scanlines_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),&m,1)==0)
+ return(0);
+ m+=sp->bytes_per_line;
+ n-=sp->bytes_per_line;
+ } while(n>0);
+ return(1);
+}
+
+static void
+OJPEGPostDecode(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ (void)buf;
+ (void)cc;
+ sp->write_curstrile++;
+ if (sp->write_curstrile%tif->tif_dir.td_stripsperimage==0)
+ {
+ assert(sp->libjpeg_session_active!=0);
+ OJPEGLibjpegSessionAbort(tif);
+ sp->writeheader_done=0;
+ }
+}
+
+static int
+OJPEGSetupEncode(TIFF* tif)
+{
+ static const char module[]="OJPEGSetupEncode";
+ TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
+ return(0);
+}
+
+static int
+OJPEGPreEncode(TIFF* tif, tsample_t s)
+{
+ static const char module[]="OJPEGPreEncode";
+ (void)s;
+ TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
+ return(0);
+}
+
+static int
+OJPEGEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ static const char module[]="OJPEGEncode";
+ (void)buf;
+ (void)cc;
+ (void)s;
+ TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
+ return(0);
+}
+
+static int
+OJPEGPostEncode(TIFF* tif)
+{
+ static const char module[]="OJPEGPostEncode";
+ TIFFErrorExt(tif->tif_clientdata,module,"OJPEG encoding not supported; use new-style JPEG compression instead");
+ return(0);
+}
+
+static void
+OJPEGCleanup(TIFF* tif)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ if (sp!=0)
+ {
+ tif->tif_tagmethods.vgetfield=sp->vgetparent;
+ tif->tif_tagmethods.vsetfield=sp->vsetparent;
+ if (sp->qtable[0]!=0)
+ _TIFFfree(sp->qtable[0]);
+ if (sp->qtable[1]!=0)
+ _TIFFfree(sp->qtable[1]);
+ if (sp->qtable[2]!=0)
+ _TIFFfree(sp->qtable[2]);
+ if (sp->qtable[3]!=0)
+ _TIFFfree(sp->qtable[3]);
+ if (sp->dctable[0]!=0)
+ _TIFFfree(sp->dctable[0]);
+ if (sp->dctable[1]!=0)
+ _TIFFfree(sp->dctable[1]);
+ if (sp->dctable[2]!=0)
+ _TIFFfree(sp->dctable[2]);
+ if (sp->dctable[3]!=0)
+ _TIFFfree(sp->dctable[3]);
+ if (sp->actable[0]!=0)
+ _TIFFfree(sp->actable[0]);
+ if (sp->actable[1]!=0)
+ _TIFFfree(sp->actable[1]);
+ if (sp->actable[2]!=0)
+ _TIFFfree(sp->actable[2]);
+ if (sp->actable[3]!=0)
+ _TIFFfree(sp->actable[3]);
+ if (sp->libjpeg_session_active!=0)
+ OJPEGLibjpegSessionAbort(tif);
+ if (sp->subsampling_convert_ycbcrbuf!=0)
+ _TIFFfree(sp->subsampling_convert_ycbcrbuf);
+ if (sp->subsampling_convert_ycbcrimage!=0)
+ _TIFFfree(sp->subsampling_convert_ycbcrimage);
+ if (sp->skip_buffer!=0)
+ _TIFFfree(sp->skip_buffer);
+ _TIFFfree(sp);
+ tif->tif_data=NULL;
+ _TIFFSetDefaultCompressionState(tif);
+ }
+}
+
+static void
+OJPEGSubsamplingCorrect(TIFF* tif)
+{
+ static const char module[]="OJPEGSubsamplingCorrect";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 mh;
+ uint8 mv;
+ assert(sp->subsamplingcorrect_done==0);
+ if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) &&
+ (tif->tif_dir.td_photometric!=PHOTOMETRIC_ITULAB)))
+ {
+ if (sp->subsampling_tag!=0)
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag not appropriate for this Photometric and/or SamplesPerPixel");
+ sp->subsampling_hor=1;
+ sp->subsampling_ver=1;
+ sp->subsampling_force_desubsampling_inside_decompression=0;
+ }
+ else
+ {
+ sp->subsamplingcorrect_done=1;
+ mh=sp->subsampling_hor;
+ mv=sp->subsampling_ver;
+ sp->subsamplingcorrect=1;
+ OJPEGReadHeaderInfoSec(tif);
+ if (sp->subsampling_force_desubsampling_inside_decompression!=0)
+ {
+ sp->subsampling_hor=1;
+ sp->subsampling_ver=1;
+ }
+ sp->subsamplingcorrect=0;
+ if (((sp->subsampling_hor!=mh) || (sp->subsampling_ver!=mv)) && (sp->subsampling_force_desubsampling_inside_decompression==0))
+ {
+ if (sp->subsampling_tag==0)
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data [%d,%d] does not match default values [2,2]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver);
+ else
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data [%d,%d] does not match subsampling tag values [%d,%d]; assuming subsampling inside JPEG data is correct",sp->subsampling_hor,sp->subsampling_ver,mh,mv);
+ }
+ if (sp->subsampling_force_desubsampling_inside_decompression!=0)
+ {
+ if (sp->subsampling_tag==0)
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling tag is not set, yet subsampling inside JPEG data does not match default values [2,2] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression");
+ else
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling inside JPEG data does not match subsampling tag values [%d,%d] (nor any other values allowed in TIFF); assuming subsampling inside JPEG data is correct and desubsampling inside JPEG decompression",mh,mv);
+ }
+ if (sp->subsampling_force_desubsampling_inside_decompression==0)
+ {
+ if (sp->subsampling_hor<sp->subsampling_ver)
+ TIFFWarningExt(tif->tif_clientdata,module,"Subsampling values [%d,%d] are not allowed in TIFF",sp->subsampling_hor,sp->subsampling_ver);
+ }
+ }
+ sp->subsamplingcorrect_done=1;
+}
+
+static int
+OJPEGReadHeaderInfo(TIFF* tif)
+{
+ static const char module[]="OJPEGReadHeaderInfo";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(sp->readheader_done==0);
+ sp->image_width=tif->tif_dir.td_imagewidth;
+ sp->image_length=tif->tif_dir.td_imagelength;
+ if isTiled(tif)
+ {
+ sp->strile_width=tif->tif_dir.td_tilewidth;
+ sp->strile_length=tif->tif_dir.td_tilelength;
+ sp->strile_length_total=((sp->image_length+sp->strile_length-1)/sp->strile_length)*sp->strile_length;
+ }
+ else
+ {
+ sp->strile_width=sp->image_width;
+ sp->strile_length=tif->tif_dir.td_rowsperstrip;
+ sp->strile_length_total=sp->image_length;
+ }
+ sp->samples_per_pixel=tif->tif_dir.td_samplesperpixel;
+ if (sp->samples_per_pixel==1)
+ {
+ sp->plane_sample_offset=0;
+ sp->samples_per_pixel_per_plane=sp->samples_per_pixel;
+ sp->subsampling_hor=1;
+ sp->subsampling_ver=1;
+ }
+ else
+ {
+ if (sp->samples_per_pixel!=3)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"SamplesPerPixel %d not supported for this compression scheme",sp->samples_per_pixel);
+ return(0);
+ }
+ sp->plane_sample_offset=0;
+ if (tif->tif_dir.td_planarconfig==PLANARCONFIG_CONTIG)
+ sp->samples_per_pixel_per_plane=3;
+ else
+ sp->samples_per_pixel_per_plane=1;
+ }
+ if (sp->strile_length<sp->image_length)
+ {
+ if (sp->strile_length%(sp->subsampling_ver*8)!=0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
+ return(0);
+ }
+ sp->restart_interval=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8))*(sp->strile_length/(sp->subsampling_ver*8));
+ }
+ if (OJPEGReadHeaderInfoSec(tif)==0)
+ return(0);
+ sp->sos_end[0].log=1;
+ sp->sos_end[0].in_buffer_source=sp->in_buffer_source;
+ sp->sos_end[0].in_buffer_next_strile=sp->in_buffer_next_strile;
+ sp->sos_end[0].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo;
+ sp->sos_end[0].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo;
+ sp->readheader_done=1;
+ return(1);
+}
+
+static int
+OJPEGReadSecondarySos(TIFF* tif, tsample_t s)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ assert(s>0);
+ assert(s<3);
+ assert(sp->sos_end[0].log!=0);
+ assert(sp->sos_end[s].log==0);
+ sp->plane_sample_offset=s-1;
+ while(sp->sos_end[sp->plane_sample_offset].log==0)
+ sp->plane_sample_offset--;
+ sp->in_buffer_source=sp->sos_end[sp->plane_sample_offset].in_buffer_source;
+ sp->in_buffer_next_strile=sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile;
+ sp->in_buffer_file_pos=sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos;
+ sp->in_buffer_file_pos_log=0;
+ sp->in_buffer_file_togo=sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo;
+ sp->in_buffer_togo=0;
+ sp->in_buffer_cur=0;
+ while(sp->plane_sample_offset<s)
+ {
+ do
+ {
+ if (OJPEGReadByte(sp,&m)==0)
+ return(0);
+ if (m==255)
+ {
+ do
+ {
+ if (OJPEGReadByte(sp,&m)==0)
+ return(0);
+ if (m!=255)
+ break;
+ } while(1);
+ if (m==JPEG_MARKER_SOS)
+ break;
+ }
+ } while(1);
+ sp->plane_sample_offset++;
+ if (OJPEGReadHeaderInfoSecStreamSos(tif)==0)
+ return(0);
+ sp->sos_end[sp->plane_sample_offset].log=1;
+ sp->sos_end[sp->plane_sample_offset].in_buffer_source=sp->in_buffer_source;
+ sp->sos_end[sp->plane_sample_offset].in_buffer_next_strile=sp->in_buffer_next_strile;
+ sp->sos_end[sp->plane_sample_offset].in_buffer_file_pos=sp->in_buffer_file_pos-sp->in_buffer_togo;
+ sp->sos_end[sp->plane_sample_offset].in_buffer_file_togo=sp->in_buffer_file_togo+sp->in_buffer_togo;
+ }
+ return(1);
+}
+
+static int
+OJPEGWriteHeaderInfo(TIFF* tif)
+{
+ static const char module[]="OJPEGWriteHeaderInfo";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8** m;
+ uint32 n;
+ assert(sp->libjpeg_session_active==0);
+ sp->out_state=ososSoi;
+ sp->restart_index=0;
+ jpeg_std_error(&(sp->libjpeg_jpeg_error_mgr));
+ sp->libjpeg_jpeg_error_mgr.output_message=OJPEGLibjpegJpegErrorMgrOutputMessage;
+ sp->libjpeg_jpeg_error_mgr.error_exit=OJPEGLibjpegJpegErrorMgrErrorExit;
+ sp->libjpeg_jpeg_decompress_struct.err=&(sp->libjpeg_jpeg_error_mgr);
+ sp->libjpeg_jpeg_decompress_struct.client_data=(void*)tif;
+ if (jpeg_create_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0)
+ return(0);
+ sp->libjpeg_session_active=1;
+ sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=0;
+ sp->libjpeg_jpeg_source_mgr.init_source=OJPEGLibjpegJpegSourceMgrInitSource;
+ sp->libjpeg_jpeg_source_mgr.fill_input_buffer=OJPEGLibjpegJpegSourceMgrFillInputBuffer;
+ sp->libjpeg_jpeg_source_mgr.skip_input_data=OJPEGLibjpegJpegSourceMgrSkipInputData;
+ sp->libjpeg_jpeg_source_mgr.resync_to_restart=OJPEGLibjpegJpegSourceMgrResyncToRestart;
+ sp->libjpeg_jpeg_source_mgr.term_source=OJPEGLibjpegJpegSourceMgrTermSource;
+ sp->libjpeg_jpeg_decompress_struct.src=&(sp->libjpeg_jpeg_source_mgr);
+ if (jpeg_read_header_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),1)==0)
+ return(0);
+ if ((sp->subsampling_force_desubsampling_inside_decompression==0) && (sp->samples_per_pixel_per_plane>1))
+ {
+ sp->libjpeg_jpeg_decompress_struct.raw_data_out=1;
+ sp->libjpeg_jpeg_query_style=0;
+ if (sp->subsampling_convert_log==0)
+ {
+ assert(sp->subsampling_convert_ycbcrbuf==0);
+ assert(sp->subsampling_convert_ycbcrimage==0);
+ sp->subsampling_convert_ylinelen=((sp->strile_width+sp->subsampling_hor*8-1)/(sp->subsampling_hor*8)*sp->subsampling_hor*8);
+ sp->subsampling_convert_ylines=sp->subsampling_ver*8;
+ sp->subsampling_convert_clinelen=sp->subsampling_convert_ylinelen/sp->subsampling_hor;
+ sp->subsampling_convert_clines=8;
+ sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
+ sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines;
+ sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen;
+ sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen);
+ if (sp->subsampling_convert_ycbcrbuf==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ sp->subsampling_convert_ybuf=sp->subsampling_convert_ycbcrbuf;
+ sp->subsampling_convert_cbbuf=sp->subsampling_convert_ybuf+sp->subsampling_convert_ybuflen;
+ sp->subsampling_convert_crbuf=sp->subsampling_convert_cbbuf+sp->subsampling_convert_cbuflen;
+ sp->subsampling_convert_ycbcrimagelen=3+sp->subsampling_convert_ylines+2*sp->subsampling_convert_clines;
+ sp->subsampling_convert_ycbcrimage=_TIFFmalloc(sp->subsampling_convert_ycbcrimagelen*sizeof(uint8*));
+ if (sp->subsampling_convert_ycbcrimage==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ m=sp->subsampling_convert_ycbcrimage;
+ *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3);
+ *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines);
+ *m++=(uint8*)(sp->subsampling_convert_ycbcrimage+3+sp->subsampling_convert_ylines+sp->subsampling_convert_clines);
+ for (n=0; n<sp->subsampling_convert_ylines; n++)
+ *m++=sp->subsampling_convert_ybuf+n*sp->subsampling_convert_ylinelen;
+ for (n=0; n<sp->subsampling_convert_clines; n++)
+ *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen;
+ for (n=0; n<sp->subsampling_convert_clines; n++)
+ *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen;
+ sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor);
+ sp->subsampling_convert_state=0;
+ sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2);
+ sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver);
+ sp->subsampling_convert_log=1;
+ }
+ }
+ else
+ {
+ sp->libjpeg_jpeg_decompress_struct.jpeg_color_space=JCS_UNKNOWN;
+ sp->libjpeg_jpeg_decompress_struct.out_color_space=JCS_UNKNOWN;
+ sp->libjpeg_jpeg_query_style=1;
+ sp->bytes_per_line=sp->samples_per_pixel_per_plane*sp->strile_width;
+ sp->lines_per_strile=sp->strile_length;
+ }
+ if (jpeg_start_decompress_encap(sp,&(sp->libjpeg_jpeg_decompress_struct))==0)
+ return(0);
+ sp->writeheader_done=1;
+ return(1);
+}
+
+static void
+OJPEGLibjpegSessionAbort(TIFF* tif)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(sp->libjpeg_session_active!=0);
+ jpeg_destroy((jpeg_common_struct*)(&(sp->libjpeg_jpeg_decompress_struct)));
+ sp->libjpeg_session_active=0;
+}
+
+static int
+OJPEGReadHeaderInfoSec(TIFF* tif)
+{
+ static const char module[]="OJPEGReadHeaderInfoSec";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ uint16 n;
+ uint8 o;
+ if (sp->file_size==0)
+ sp->file_size=TIFFGetFileSize(tif);
+ if (sp->jpeg_interchange_format!=0)
+ {
+ if (sp->jpeg_interchange_format>=sp->file_size)
+ {
+ sp->jpeg_interchange_format=0;
+ sp->jpeg_interchange_format_length=0;
+ }
+ else
+ {
+ if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size))
+ sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format;
+ }
+ }
+ sp->in_buffer_source=osibsNotSetYet;
+ sp->in_buffer_next_strile=0;
+ sp->in_buffer_strile_count=tif->tif_dir.td_nstrips;
+ sp->in_buffer_file_togo=0;
+ sp->in_buffer_togo=0;
+ do
+ {
+ if (OJPEGReadBytePeek(sp,&m)==0)
+ return(0);
+ if (m!=255)
+ break;
+ OJPEGReadByteAdvance(sp);
+ do
+ {
+ if (OJPEGReadByte(sp,&m)==0)
+ return(0);
+ } while(m==255);
+ switch(m)
+ {
+ case JPEG_MARKER_SOI:
+ /* this type of marker has no data, and should be skipped */
+ break;
+ case JPEG_MARKER_COM:
+ case JPEG_MARKER_APP0:
+ case JPEG_MARKER_APP0+1:
+ case JPEG_MARKER_APP0+2:
+ case JPEG_MARKER_APP0+3:
+ case JPEG_MARKER_APP0+4:
+ case JPEG_MARKER_APP0+5:
+ case JPEG_MARKER_APP0+6:
+ case JPEG_MARKER_APP0+7:
+ case JPEG_MARKER_APP0+8:
+ case JPEG_MARKER_APP0+9:
+ case JPEG_MARKER_APP0+10:
+ case JPEG_MARKER_APP0+11:
+ case JPEG_MARKER_APP0+12:
+ case JPEG_MARKER_APP0+13:
+ case JPEG_MARKER_APP0+14:
+ case JPEG_MARKER_APP0+15:
+ /* this type of marker has data, but it has no use to us (and no place here) and should be skipped */
+ if (OJPEGReadWord(sp,&n)==0)
+ return(0);
+ if (n<2)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data");
+ return(0);
+ }
+ if (n>2)
+ OJPEGReadSkip(sp,n-2);
+ break;
+ case JPEG_MARKER_DRI:
+ if (OJPEGReadHeaderInfoSecStreamDri(tif)==0)
+ return(0);
+ break;
+ case JPEG_MARKER_DQT:
+ if (OJPEGReadHeaderInfoSecStreamDqt(tif)==0)
+ return(0);
+ break;
+ case JPEG_MARKER_DHT:
+ if (OJPEGReadHeaderInfoSecStreamDht(tif)==0)
+ return(0);
+ break;
+ case JPEG_MARKER_SOF0:
+ case JPEG_MARKER_SOF1:
+ case JPEG_MARKER_SOF3:
+ if (OJPEGReadHeaderInfoSecStreamSof(tif,m)==0)
+ return(0);
+ if (sp->subsamplingcorrect!=0)
+ return(1);
+ break;
+ case JPEG_MARKER_SOS:
+ if (sp->subsamplingcorrect!=0)
+ return(1);
+ assert(sp->plane_sample_offset==0);
+ if (OJPEGReadHeaderInfoSecStreamSos(tif)==0)
+ return(0);
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata,module,"Unknown marker type %d in JPEG data",m);
+ return(0);
+ }
+ } while(m!=JPEG_MARKER_SOS);
+ if (sp->subsamplingcorrect)
+ return(1);
+ if (sp->sof_log==0)
+ {
+ if (OJPEGReadHeaderInfoSecTablesQTable(tif)==0)
+ return(0);
+ sp->sof_marker_id=JPEG_MARKER_SOF0;
+ for (o=0; o<sp->samples_per_pixel; o++)
+ sp->sof_c[o]=o;
+ sp->sof_hv[0]=((sp->subsampling_hor<<4)|sp->subsampling_ver);
+ for (o=1; o<sp->samples_per_pixel; o++)
+ sp->sof_hv[o]=17;
+ sp->sof_x=sp->strile_width;
+ sp->sof_y=sp->strile_length_total;
+ sp->sof_log=1;
+ if (OJPEGReadHeaderInfoSecTablesDcTable(tif)==0)
+ return(0);
+ if (OJPEGReadHeaderInfoSecTablesAcTable(tif)==0)
+ return(0);
+ for (o=1; o<sp->samples_per_pixel; o++)
+ sp->sos_cs[o]=o;
+ }
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecStreamDri(TIFF* tif)
+{
+ /* this could easilly cause trouble in some cases... but no such cases have occured sofar */
+ static const char module[]="OJPEGReadHeaderInfoSecStreamDri";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint16 m;
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ if (m!=4)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DRI marker in JPEG data");
+ return(0);
+ }
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ sp->restart_interval=m;
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecStreamDqt(TIFF* tif)
+{
+ /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */
+ static const char module[]="OJPEGReadHeaderInfoSecStreamDqt";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint16 m;
+ uint32 na;
+ uint8* nb;
+ uint8 o;
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ if (m<=2)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
+ return(0);
+ }
+ if (sp->subsamplingcorrect!=0)
+ OJPEGReadSkip(sp,m-2);
+ else
+ {
+ m-=2;
+ do
+ {
+ if (m<65)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
+ return(0);
+ }
+ na=sizeof(uint32)+69;
+ nb=_TIFFmalloc(na);
+ if (nb==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ *(uint32*)nb=na;
+ nb[sizeof(uint32)]=255;
+ nb[sizeof(uint32)+1]=JPEG_MARKER_DQT;
+ nb[sizeof(uint32)+2]=0;
+ nb[sizeof(uint32)+3]=67;
+ if (OJPEGReadBlock(sp,65,&nb[sizeof(uint32)+4])==0)
+ return(0);
+ o=nb[sizeof(uint32)+4]&15;
+ if (3<o)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DQT marker in JPEG data");
+ return(0);
+ }
+ if (sp->qtable[o]!=0)
+ _TIFFfree(sp->qtable[o]);
+ sp->qtable[o]=nb;
+ m-=65;
+ } while(m>0);
+ }
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecStreamDht(TIFF* tif)
+{
+ /* this is a table marker, and it is to be saved as a whole for exact pushing on the jpeg stream later on */
+ /* TODO: the following assumes there is only one table in this marker... but i'm not quite sure that assumption is guaranteed correct */
+ static const char module[]="OJPEGReadHeaderInfoSecStreamDht";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint16 m;
+ uint32 na;
+ uint8* nb;
+ uint8 o;
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ if (m<=2)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+ return(0);
+ }
+ if (sp->subsamplingcorrect!=0)
+ {
+ OJPEGReadSkip(sp,m-2);
+ }
+ else
+ {
+ na=sizeof(uint32)+2+m;
+ nb=_TIFFmalloc(na);
+ if (nb==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ *(uint32*)nb=na;
+ nb[sizeof(uint32)]=255;
+ nb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
+ nb[sizeof(uint32)+2]=(m>>8);
+ nb[sizeof(uint32)+3]=(m&255);
+ if (OJPEGReadBlock(sp,m-2,&nb[sizeof(uint32)+4])==0)
+ return(0);
+ o=nb[sizeof(uint32)+4];
+ if ((o&240)==0)
+ {
+ if (3<o)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+ return(0);
+ }
+ if (sp->dctable[o]!=0)
+ _TIFFfree(sp->dctable[o]);
+ sp->dctable[o]=nb;
+ }
+ else
+ {
+ if ((o&240)!=16)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+ return(0);
+ }
+ o&=15;
+ if (3<o)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt DHT marker in JPEG data");
+ return(0);
+ }
+ if (sp->actable[o]!=0)
+ _TIFFfree(sp->actable[o]);
+ sp->actable[o]=nb;
+ }
+ }
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecStreamSof(TIFF* tif, uint8 marker_id)
+{
+ /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */
+ static const char module[]="OJPEGReadHeaderInfoSecStreamSof";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint16 m;
+ uint16 n;
+ uint8 o;
+ uint16 p;
+ uint16 q;
+ if (sp->sof_log!=0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JPEG data");
+ return(0);
+ }
+ if (sp->subsamplingcorrect==0)
+ sp->sof_marker_id=marker_id;
+ /* Lf: data length */
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ if (m<11)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
+ return(0);
+ }
+ m-=8;
+ if (m%3!=0)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
+ return(0);
+ }
+ n=m/3;
+ if (sp->subsamplingcorrect==0)
+ {
+ if (n!=sp->samples_per_pixel)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of samples");
+ return(0);
+ }
+ }
+ /* P: Sample precision */
+ if (OJPEGReadByte(sp,&o)==0)
+ return(0);
+ if (o!=8)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected number of bits per sample");
+ return(0);
+ }
+ /* Y: Number of lines, X: Number of samples per line */
+ if (sp->subsamplingcorrect)
+ OJPEGReadSkip(sp,4);
+ else
+ {
+ /* TODO: probably best to also add check on allowed upper bound, especially x, may cause buffer overflow otherwise i think */
+ /* Y: Number of lines */
+ if (OJPEGReadWord(sp,&p)==0)
+ return(0);
+ if ((p<sp->image_length) && (p<sp->strile_length_total))
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected height");
+ return(0);
+ }
+ sp->sof_y=p;
+ /* X: Number of samples per line */
+ if (OJPEGReadWord(sp,&p)==0)
+ return(0);
+ if ((p<sp->image_width) && (p<sp->strile_width))
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected width");
+ return(0);
+ }
+ sp->sof_x=p;
+ }
+ /* Nf: Number of image components in frame */
+ if (OJPEGReadByte(sp,&o)==0)
+ return(0);
+ if (o!=n)
+ {
+ if (sp->subsamplingcorrect==0)
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOF marker in JPEG data");
+ return(0);
+ }
+ /* per component stuff */
+ /* TODO: double-check that flow implies that n cannot be as big as to make us overflow sof_c, sof_hv and sof_tq arrays */
+ for (q=0; q<n; q++)
+ {
+ /* C: Component identifier */
+ if (OJPEGReadByte(sp,&o)==0)
+ return(0);
+ if (sp->subsamplingcorrect==0)
+ sp->sof_c[q]=o;
+ /* H: Horizontal sampling factor, and V: Vertical sampling factor */
+ if (OJPEGReadByte(sp,&o)==0)
+ return(0);
+ if (sp->subsamplingcorrect!=0)
+ {
+ if (q==0)
+ {
+ sp->subsampling_hor=(o>>4);
+ sp->subsampling_ver=(o&15);
+ if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) ||
+ ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4)))
+ sp->subsampling_force_desubsampling_inside_decompression=1;
+ }
+ else
+ {
+ if (o!=17)
+ sp->subsampling_force_desubsampling_inside_decompression=1;
+ }
+ }
+ else
+ {
+ sp->sof_hv[q]=o;
+ if (sp->subsampling_force_desubsampling_inside_decompression==0)
+ {
+ if (q==0)
+ {
+ if (o!=((sp->subsampling_hor<<4)|sp->subsampling_ver))
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values");
+ return(0);
+ }
+ }
+ else
+ {
+ if (o!=17)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"JPEG compressed data indicates unexpected subsampling values");
+ return(0);
+ }
+ }
+ }
+ }
+ /* Tq: Quantization table destination selector */
+ if (OJPEGReadByte(sp,&o)==0)
+ return(0);
+ if (sp->subsamplingcorrect==0)
+ sp->sof_tq[q]=o;
+ }
+ if (sp->subsamplingcorrect==0)
+ sp->sof_log=1;
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecStreamSos(TIFF* tif)
+{
+ /* this marker needs to be checked, and part of its data needs to be saved for regeneration later on */
+ static const char module[]="OJPEGReadHeaderInfoSecStreamSos";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint16 m;
+ uint8 n;
+ uint8 o;
+ assert(sp->subsamplingcorrect==0);
+ if (sp->sof_log==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
+ return(0);
+ }
+ /* Ls */
+ if (OJPEGReadWord(sp,&m)==0)
+ return(0);
+ if (m!=6+sp->samples_per_pixel_per_plane*2)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
+ return(0);
+ }
+ /* Ns */
+ if (OJPEGReadByte(sp,&n)==0)
+ return(0);
+ if (n!=sp->samples_per_pixel_per_plane)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt SOS marker in JPEG data");
+ return(0);
+ }
+ /* Cs, Td, and Ta */
+ for (o=0; o<sp->samples_per_pixel_per_plane; o++)
+ {
+ /* Cs */
+ if (OJPEGReadByte(sp,&n)==0)
+ return(0);
+ sp->sos_cs[sp->plane_sample_offset+o]=n;
+ /* Td and Ta */
+ if (OJPEGReadByte(sp,&n)==0)
+ return(0);
+ sp->sos_tda[sp->plane_sample_offset+o]=n;
+ }
+ /* skip Ss, Se, Ah, en Al -> no check, as per Tom Lane recommendation, as per LibJpeg source */
+ OJPEGReadSkip(sp,3);
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecTablesQTable(TIFF* tif)
+{
+ static const char module[]="OJPEGReadHeaderInfoSecTablesQTable";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ uint8 n;
+ uint32 oa;
+ uint8* ob;
+ uint32 p;
+ if (sp->qtable_offset[0]==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
+ return(0);
+ }
+ sp->in_buffer_file_pos_log=0;
+ for (m=0; m<sp->samples_per_pixel; m++)
+ {
+ if ((sp->qtable_offset[m]!=0) && ((m==0) || (sp->qtable_offset[m]!=sp->qtable_offset[m-1])))
+ {
+ for (n=0; n<m-1; n++)
+ {
+ if (sp->qtable_offset[m]==sp->qtable_offset[n])
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegQTables tag value");
+ return(0);
+ }
+ }
+ oa=sizeof(uint32)+69;
+ ob=_TIFFmalloc(oa);
+ if (ob==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ *(uint32*)ob=oa;
+ ob[sizeof(uint32)]=255;
+ ob[sizeof(uint32)+1]=JPEG_MARKER_DQT;
+ ob[sizeof(uint32)+2]=0;
+ ob[sizeof(uint32)+3]=67;
+ ob[sizeof(uint32)+4]=m;
+ TIFFSeekFile(tif,sp->qtable_offset[m],SEEK_SET);
+ p=TIFFReadFile(tif,&ob[sizeof(uint32)+5],64);
+ if (p!=64)
+ return(0);
+ sp->qtable[m]=ob;
+ sp->sof_tq[m]=m;
+ }
+ else
+ sp->sof_tq[m]=sp->sof_tq[m-1];
+ }
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecTablesDcTable(TIFF* tif)
+{
+ static const char module[]="OJPEGReadHeaderInfoSecTablesDcTable";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ uint8 n;
+ uint8 o[16];
+ uint32 p;
+ uint32 q;
+ uint32 ra;
+ uint8* rb;
+ if (sp->dctable_offset[0]==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
+ return(0);
+ }
+ sp->in_buffer_file_pos_log=0;
+ for (m=0; m<sp->samples_per_pixel; m++)
+ {
+ if ((sp->dctable_offset[m]!=0) && ((m==0) || (sp->dctable_offset[m]!=sp->dctable_offset[m-1])))
+ {
+ for (n=0; n<m-1; n++)
+ {
+ if (sp->dctable_offset[m]==sp->dctable_offset[n])
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegDcTables tag value");
+ return(0);
+ }
+ }
+ TIFFSeekFile(tif,sp->dctable_offset[m],SEEK_SET);
+ p=TIFFReadFile(tif,o,16);
+ if (p!=16)
+ return(0);
+ q=0;
+ for (n=0; n<16; n++)
+ q+=o[n];
+ ra=sizeof(uint32)+21+q;
+ rb=_TIFFmalloc(ra);
+ if (rb==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ *(uint32*)rb=ra;
+ rb[sizeof(uint32)]=255;
+ rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
+ rb[sizeof(uint32)+2]=((19+q)>>8);
+ rb[sizeof(uint32)+3]=((19+q)&255);
+ rb[sizeof(uint32)+4]=m;
+ for (n=0; n<16; n++)
+ rb[sizeof(uint32)+5+n]=o[n];
+ p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
+ if (p!=q)
+ return(0);
+ sp->dctable[m]=rb;
+ sp->sos_tda[m]=(m<<4);
+ }
+ else
+ sp->sos_tda[m]=sp->sos_tda[m-1];
+ }
+ return(1);
+}
+
+static int
+OJPEGReadHeaderInfoSecTablesAcTable(TIFF* tif)
+{
+ static const char module[]="OJPEGReadHeaderInfoSecTablesAcTable";
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ uint8 n;
+ uint8 o[16];
+ uint32 p;
+ uint32 q;
+ uint32 ra;
+ uint8* rb;
+ if (sp->actable_offset[0]==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Missing JPEG tables");
+ return(0);
+ }
+ sp->in_buffer_file_pos_log=0;
+ for (m=0; m<sp->samples_per_pixel; m++)
+ {
+ if ((sp->actable_offset[m]!=0) && ((m==0) || (sp->actable_offset[m]!=sp->actable_offset[m-1])))
+ {
+ for (n=0; n<m-1; n++)
+ {
+ if (sp->actable_offset[m]==sp->actable_offset[n])
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Corrupt JpegAcTables tag value");
+ return(0);
+ }
+ }
+ TIFFSeekFile(tif,sp->actable_offset[m],SEEK_SET);
+ p=TIFFReadFile(tif,o,16);
+ if (p!=16)
+ return(0);
+ q=0;
+ for (n=0; n<16; n++)
+ q+=o[n];
+ ra=sizeof(uint32)+21+q;
+ rb=_TIFFmalloc(ra);
+ if (rb==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+ return(0);
+ }
+ *(uint32*)rb=ra;
+ rb[sizeof(uint32)]=255;
+ rb[sizeof(uint32)+1]=JPEG_MARKER_DHT;
+ rb[sizeof(uint32)+2]=((19+q)>>8);
+ rb[sizeof(uint32)+3]=((19+q)&255);
+ rb[sizeof(uint32)+4]=(16|m);
+ for (n=0; n<16; n++)
+ rb[sizeof(uint32)+5+n]=o[n];
+ p=TIFFReadFile(tif,&(rb[sizeof(uint32)+21]),q);
+ if (p!=q)
+ return(0);
+ sp->actable[m]=rb;
+ sp->sos_tda[m]=(sp->sos_tda[m]|m);
+ }
+ else
+ sp->sos_tda[m]=(sp->sos_tda[m]|(sp->sos_tda[m-1]&15));
+ }
+ return(1);
+}
+
+static int
+OJPEGReadBufferFill(OJPEGState* sp)
+{
+ uint16 m;
+ tsize_t n;
+ /* TODO: double-check: when subsamplingcorrect is set, no call to TIFFErrorExt or TIFFWarningExt should be made
+ * in any other case, seek or read errors should be passed through */
+ do
+ {
+ if (sp->in_buffer_file_togo!=0)
+ {
+ if (sp->in_buffer_file_pos_log==0)
+ {
+ TIFFSeekFile(sp->tif,sp->in_buffer_file_pos,SEEK_SET);
+ sp->in_buffer_file_pos_log=1;
+ }
+ m=OJPEG_BUFFER;
+ if (m>sp->in_buffer_file_togo)
+ m=(uint16)sp->in_buffer_file_togo;
+ n=TIFFReadFile(sp->tif,sp->in_buffer,(tsize_t)m);
+ if (n==0)
+ return(0);
+ assert(n>0);
+ assert(n<=OJPEG_BUFFER);
+ assert(n<65536);
+ assert((uint16)n<=sp->in_buffer_file_togo);
+ m=(uint16)n;
+ sp->in_buffer_togo=m;
+ sp->in_buffer_cur=sp->in_buffer;
+ sp->in_buffer_file_togo-=m;
+ sp->in_buffer_file_pos+=m;
+ break;
+ }
+ sp->in_buffer_file_pos_log=0;
+ switch(sp->in_buffer_source)
+ {
+ case osibsNotSetYet:
+ if (sp->jpeg_interchange_format!=0)
+ {
+ sp->in_buffer_file_pos=sp->jpeg_interchange_format;
+ sp->in_buffer_file_togo=sp->jpeg_interchange_format_length;
+ }
+ sp->in_buffer_source=osibsJpegInterchangeFormat;
+ break;
+ case osibsJpegInterchangeFormat:
+ sp->in_buffer_source=osibsStrile;
+ case osibsStrile:
+ if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
+ sp->in_buffer_source=osibsEof;
+ else
+ {
+ sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile];
+ if (sp->in_buffer_file_pos!=0)
+ {
+ if (sp->in_buffer_file_pos>=sp->file_size)
+ sp->in_buffer_file_pos=0;
+ else
+ {
+ sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
+ if (sp->in_buffer_file_togo==0)
+ sp->in_buffer_file_pos=0;
+ else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size)
+ sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
+ }
+ }
+ sp->in_buffer_next_strile++;
+ }
+ break;
+ default:
+ return(0);
+ }
+ } while (1);
+ return(1);
+}
+
+static int
+OJPEGReadByte(OJPEGState* sp, uint8* byte)
+{
+ if (sp->in_buffer_togo==0)
+ {
+ if (OJPEGReadBufferFill(sp)==0)
+ return(0);
+ assert(sp->in_buffer_togo>0);
+ }
+ *byte=*(sp->in_buffer_cur);
+ sp->in_buffer_cur++;
+ sp->in_buffer_togo--;
+ return(1);
+}
+
+static int
+OJPEGReadBytePeek(OJPEGState* sp, uint8* byte)
+{
+ if (sp->in_buffer_togo==0)
+ {
+ if (OJPEGReadBufferFill(sp)==0)
+ return(0);
+ assert(sp->in_buffer_togo>0);
+ }
+ *byte=*(sp->in_buffer_cur);
+ return(1);
+}
+
+static void
+OJPEGReadByteAdvance(OJPEGState* sp)
+{
+ assert(sp->in_buffer_togo>0);
+ sp->in_buffer_cur++;
+ sp->in_buffer_togo--;
+}
+
+static int
+OJPEGReadWord(OJPEGState* sp, uint16* word)
+{
+ uint8 m;
+ if (OJPEGReadByte(sp,&m)==0)
+ return(0);
+ *word=(m<<8);
+ if (OJPEGReadByte(sp,&m)==0)
+ return(0);
+ *word|=m;
+ return(1);
+}
+
+static int
+OJPEGReadBlock(OJPEGState* sp, uint16 len, void* mem)
+{
+ uint16 mlen;
+ uint8* mmem;
+ uint16 n;
+ assert(len>0);
+ mlen=len;
+ mmem=mem;
+ do
+ {
+ if (sp->in_buffer_togo==0)
+ {
+ if (OJPEGReadBufferFill(sp)==0)
+ return(0);
+ assert(sp->in_buffer_togo>0);
+ }
+ n=mlen;
+ if (n>sp->in_buffer_togo)
+ n=sp->in_buffer_togo;
+ _TIFFmemcpy(mmem,sp->in_buffer_cur,n);
+ sp->in_buffer_cur+=n;
+ sp->in_buffer_togo-=n;
+ mlen-=n;
+ mmem+=n;
+ } while(mlen>0);
+ return(1);
+}
+
+static void
+OJPEGReadSkip(OJPEGState* sp, uint16 len)
+{
+ uint16 m;
+ uint16 n;
+ m=len;
+ n=m;
+ if (n>sp->in_buffer_togo)
+ n=sp->in_buffer_togo;
+ sp->in_buffer_cur+=n;
+ sp->in_buffer_togo-=n;
+ m-=n;
+ if (m>0)
+ {
+ assert(sp->in_buffer_togo==0);
+ n=m;
+ if (n>sp->in_buffer_file_togo)
+ n=sp->in_buffer_file_togo;
+ sp->in_buffer_file_pos+=n;
+ sp->in_buffer_file_togo-=n;
+ sp->in_buffer_file_pos_log=0;
+ /* we don't skip past jpeginterchangeformat/strile block...
+ * if that is asked from us, we're dealing with totally bazurk
+ * data anyway, and we've not seen this happening on any
+ * testfile, so we might as well likely cause some other
+ * meaningless error to be passed at some later time
+ */
+ }
+}
+
+static int
+OJPEGWriteStream(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ *len=0;
+ do
+ {
+ assert(sp->out_state<=ososEoi);
+ switch(sp->out_state)
+ {
+ case ososSoi:
+ OJPEGWriteStreamSoi(tif,mem,len);
+ break;
+ case ososQTable0:
+ OJPEGWriteStreamQTable(tif,0,mem,len);
+ break;
+ case ososQTable1:
+ OJPEGWriteStreamQTable(tif,1,mem,len);
+ break;
+ case ososQTable2:
+ OJPEGWriteStreamQTable(tif,2,mem,len);
+ break;
+ case ososQTable3:
+ OJPEGWriteStreamQTable(tif,3,mem,len);
+ break;
+ case ososDcTable0:
+ OJPEGWriteStreamDcTable(tif,0,mem,len);
+ break;
+ case ososDcTable1:
+ OJPEGWriteStreamDcTable(tif,1,mem,len);
+ break;
+ case ososDcTable2:
+ OJPEGWriteStreamDcTable(tif,2,mem,len);
+ break;
+ case ososDcTable3:
+ OJPEGWriteStreamDcTable(tif,3,mem,len);
+ break;
+ case ososAcTable0:
+ OJPEGWriteStreamAcTable(tif,0,mem,len);
+ break;
+ case ososAcTable1:
+ OJPEGWriteStreamAcTable(tif,1,mem,len);
+ break;
+ case ososAcTable2:
+ OJPEGWriteStreamAcTable(tif,2,mem,len);
+ break;
+ case ososAcTable3:
+ OJPEGWriteStreamAcTable(tif,3,mem,len);
+ break;
+ case ososDri:
+ OJPEGWriteStreamDri(tif,mem,len);
+ break;
+ case ososSof:
+ OJPEGWriteStreamSof(tif,mem,len);
+ break;
+ case ososSos:
+ OJPEGWriteStreamSos(tif,mem,len);
+ break;
+ case ososCompressed:
+ if (OJPEGWriteStreamCompressed(tif,mem,len)==0)
+ return(0);
+ break;
+ case ososRst:
+ OJPEGWriteStreamRst(tif,mem,len);
+ break;
+ case ososEoi:
+ OJPEGWriteStreamEoi(tif,mem,len);
+ break;
+ }
+ } while (*len==0);
+ return(1);
+}
+
+static void
+OJPEGWriteStreamSoi(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(OJPEG_BUFFER>=2);
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=JPEG_MARKER_SOI;
+ *len=2;
+ *mem=(void*)sp->out_buffer;
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamQTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ if (sp->qtable[table_index]!=0)
+ {
+ *mem=(void*)(sp->qtable[table_index]+sizeof(uint32));
+ *len=*((uint32*)sp->qtable[table_index])-sizeof(uint32);
+ }
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamDcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ if (sp->dctable[table_index]!=0)
+ {
+ *mem=(void*)(sp->dctable[table_index]+sizeof(uint32));
+ *len=*((uint32*)sp->dctable[table_index])-sizeof(uint32);
+ }
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamAcTable(TIFF* tif, uint8 table_index, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ if (sp->actable[table_index]!=0)
+ {
+ *mem=(void*)(sp->actable[table_index]+sizeof(uint32));
+ *len=*((uint32*)sp->actable[table_index])-sizeof(uint32);
+ }
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamDri(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(OJPEG_BUFFER>=6);
+ if (sp->restart_interval!=0)
+ {
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=JPEG_MARKER_DRI;
+ sp->out_buffer[2]=0;
+ sp->out_buffer[3]=4;
+ sp->out_buffer[4]=(sp->restart_interval>>8);
+ sp->out_buffer[5]=(sp->restart_interval&255);
+ *len=6;
+ *mem=(void*)sp->out_buffer;
+ }
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamSof(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ assert(OJPEG_BUFFER>=2+8+sp->samples_per_pixel_per_plane*3);
+ assert(255>=8+sp->samples_per_pixel_per_plane*3);
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=sp->sof_marker_id;
+ /* Lf */
+ sp->out_buffer[2]=0;
+ sp->out_buffer[3]=8+sp->samples_per_pixel_per_plane*3;
+ /* P */
+ sp->out_buffer[4]=8;
+ /* Y */
+ sp->out_buffer[5]=(sp->sof_y>>8);
+ sp->out_buffer[6]=(sp->sof_y&255);
+ /* X */
+ sp->out_buffer[7]=(sp->sof_x>>8);
+ sp->out_buffer[8]=(sp->sof_x&255);
+ /* Nf */
+ sp->out_buffer[9]=sp->samples_per_pixel_per_plane;
+ for (m=0; m<sp->samples_per_pixel_per_plane; m++)
+ {
+ /* C */
+ sp->out_buffer[10+m*3]=sp->sof_c[sp->plane_sample_offset+m];
+ /* H and V */
+ sp->out_buffer[10+m*3+1]=sp->sof_hv[sp->plane_sample_offset+m];
+ /* Tq */
+ sp->out_buffer[10+m*3+2]=sp->sof_tq[sp->plane_sample_offset+m];
+ }
+ *len=10+sp->samples_per_pixel_per_plane*3;
+ *mem=(void*)sp->out_buffer;
+ sp->out_state++;
+}
+
+static void
+OJPEGWriteStreamSos(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ uint8 m;
+ assert(OJPEG_BUFFER>=2+6+sp->samples_per_pixel_per_plane*2);
+ assert(255>=6+sp->samples_per_pixel_per_plane*2);
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=JPEG_MARKER_SOS;
+ /* Ls */
+ sp->out_buffer[2]=0;
+ sp->out_buffer[3]=6+sp->samples_per_pixel_per_plane*2;
+ /* Ns */
+ sp->out_buffer[4]=sp->samples_per_pixel_per_plane;
+ for (m=0; m<sp->samples_per_pixel_per_plane; m++)
+ {
+ /* Cs */
+ sp->out_buffer[5+m*2]=sp->sos_cs[sp->plane_sample_offset+m];
+ /* Td and Ta */
+ sp->out_buffer[5+m*2+1]=sp->sos_tda[sp->plane_sample_offset+m];
+ }
+ /* Ss */
+ sp->out_buffer[5+sp->samples_per_pixel_per_plane*2]=0;
+ /* Se */
+ sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+1]=63;
+ /* Ah and Al */
+ sp->out_buffer[5+sp->samples_per_pixel_per_plane*2+2]=0;
+ *len=8+sp->samples_per_pixel_per_plane*2;
+ *mem=(void*)sp->out_buffer;
+ sp->out_state++;
+}
+
+static int
+OJPEGWriteStreamCompressed(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ if (sp->in_buffer_togo==0)
+ {
+ if (OJPEGReadBufferFill(sp)==0)
+ return(0);
+ assert(sp->in_buffer_togo>0);
+ }
+ *len=sp->in_buffer_togo;
+ *mem=(void*)sp->in_buffer_cur;
+ sp->in_buffer_togo=0;
+ if (sp->in_buffer_file_togo==0)
+ {
+ switch(sp->in_buffer_source)
+ {
+ case osibsStrile:
+ if (sp->in_buffer_next_strile<sp->in_buffer_strile_count)
+ sp->out_state=ososRst;
+ else
+ sp->out_state=ososEoi;
+ break;
+ case osibsEof:
+ sp->out_state=ososEoi;
+ break;
+ default:
+ break;
+ }
+ }
+ return(1);
+}
+
+static void
+OJPEGWriteStreamRst(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(OJPEG_BUFFER>=2);
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=JPEG_MARKER_RST0+sp->restart_index;
+ sp->restart_index++;
+ if (sp->restart_index==8)
+ sp->restart_index=0;
+ *len=2;
+ *mem=(void*)sp->out_buffer;
+ sp->out_state=ososCompressed;
+}
+
+static void
+OJPEGWriteStreamEoi(TIFF* tif, void** mem, uint32* len)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ assert(OJPEG_BUFFER>=2);
+ sp->out_buffer[0]=255;
+ sp->out_buffer[1]=JPEG_MARKER_EOI;
+ *len=2;
+ *mem=(void*)sp->out_buffer;
+}
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static int
+jpeg_create_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
+{
+ return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_create_decompress(cinfo),1));
+}
+#endif
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static int
+jpeg_read_header_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, uint8 require_image)
+{
+ return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_header(cinfo,require_image),1));
+}
+#endif
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static int
+jpeg_start_decompress_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo)
+{
+ return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_start_decompress(cinfo),1));
+}
+#endif
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static int
+jpeg_read_scanlines_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* scanlines, uint32 max_lines)
+{
+ return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_scanlines(cinfo,scanlines,max_lines),1));
+}
+#endif
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static int
+jpeg_read_raw_data_encap(OJPEGState* sp, jpeg_decompress_struct* cinfo, void* data, uint32 max_lines)
+{
+ return(SETJMP(sp->exit_jmpbuf)?0:(jpeg_read_raw_data(cinfo,data,max_lines),1));
+}
+#endif
+
+#ifndef LIBJPEG_ENCAP_EXTERNAL
+static void
+jpeg_encap_unwind(TIFF* tif)
+{
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ LONGJMP(sp->exit_jmpbuf,1);
+}
+#endif
+
+static void
+OJPEGLibjpegJpegErrorMgrOutputMessage(jpeg_common_struct* cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo,buffer);
+ TIFFWarningExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg",buffer);
+}
+
+static void
+OJPEGLibjpegJpegErrorMgrErrorExit(jpeg_common_struct* cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ (*cinfo->err->format_message)(cinfo,buffer);
+ TIFFErrorExt(((TIFF*)(cinfo->client_data))->tif_clientdata,"LibJpeg",buffer);
+ jpeg_encap_unwind((TIFF*)(cinfo->client_data));
+}
+
+static void
+OJPEGLibjpegJpegSourceMgrInitSource(jpeg_decompress_struct* cinfo)
+{
+ (void)cinfo;
+}
+
+static boolean
+OJPEGLibjpegJpegSourceMgrFillInputBuffer(jpeg_decompress_struct* cinfo)
+{
+ TIFF* tif=(TIFF*)cinfo->client_data;
+ OJPEGState* sp=(OJPEGState*)tif->tif_data;
+ void* mem=0;
+ uint32 len=0;
+ if (OJPEGWriteStream(tif,&mem,&len)==0)
+ {
+ TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Premature end of JPEG data");
+ jpeg_encap_unwind(tif);
+ }
+ sp->libjpeg_jpeg_source_mgr.bytes_in_buffer=len;
+ sp->libjpeg_jpeg_source_mgr.next_input_byte=mem;
+ return(1);
+}
+
+static void
+OJPEGLibjpegJpegSourceMgrSkipInputData(jpeg_decompress_struct* cinfo, long num_bytes)
+{
+ TIFF* tif=(TIFF*)cinfo->client_data;
+ (void)num_bytes;
+ TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
+ jpeg_encap_unwind(tif);
+}
+
+static boolean
+OJPEGLibjpegJpegSourceMgrResyncToRestart(jpeg_decompress_struct* cinfo, int desired)
+{
+ TIFF* tif=(TIFF*)cinfo->client_data;
+ (void)desired;
+ TIFFErrorExt(tif->tif_clientdata,"LibJpeg","Unexpected error");
+ jpeg_encap_unwind(tif);
+ return(0);
+}
+
+static void
+OJPEGLibjpegJpegSourceMgrTermSource(jpeg_decompress_struct* cinfo)
+{
+ (void)cinfo;
+}
+
+#endif
+
+
diff --git a/Source/LibTIFF/tif_open.c b/Source/LibTIFF/tif_open.c
new file mode 100644
index 0000000..f354716
--- /dev/null
+++ b/Source/LibTIFF/tif_open.c
@@ -0,0 +1,688 @@
+/* $Id: tif_open.c,v 1.27 2009/09/06 13:11:28 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+static const long typemask[13] = {
+ (long)0L, /* TIFF_NOTYPE */
+ (long)0x000000ffL, /* TIFF_BYTE */
+ (long)0xffffffffL, /* TIFF_ASCII */
+ (long)0x0000ffffL, /* TIFF_SHORT */
+ (long)0xffffffffL, /* TIFF_LONG */
+ (long)0xffffffffL, /* TIFF_RATIONAL */
+ (long)0x000000ffL, /* TIFF_SBYTE */
+ (long)0x000000ffL, /* TIFF_UNDEFINED */
+ (long)0x0000ffffL, /* TIFF_SSHORT */
+ (long)0xffffffffL, /* TIFF_SLONG */
+ (long)0xffffffffL, /* TIFF_SRATIONAL */
+ (long)0xffffffffL, /* TIFF_FLOAT */
+ (long)0xffffffffL, /* TIFF_DOUBLE */
+};
+static const int bigTypeshift[13] = {
+ 0, /* TIFF_NOTYPE */
+ 24, /* TIFF_BYTE */
+ 0, /* TIFF_ASCII */
+ 16, /* TIFF_SHORT */
+ 0, /* TIFF_LONG */
+ 0, /* TIFF_RATIONAL */
+ 24, /* TIFF_SBYTE */
+ 24, /* TIFF_UNDEFINED */
+ 16, /* TIFF_SSHORT */
+ 0, /* TIFF_SLONG */
+ 0, /* TIFF_SRATIONAL */
+ 0, /* TIFF_FLOAT */
+ 0, /* TIFF_DOUBLE */
+};
+static const int litTypeshift[13] = {
+ 0, /* TIFF_NOTYPE */
+ 0, /* TIFF_BYTE */
+ 0, /* TIFF_ASCII */
+ 0, /* TIFF_SHORT */
+ 0, /* TIFF_LONG */
+ 0, /* TIFF_RATIONAL */
+ 0, /* TIFF_SBYTE */
+ 0, /* TIFF_UNDEFINED */
+ 0, /* TIFF_SSHORT */
+ 0, /* TIFF_SLONG */
+ 0, /* TIFF_SRATIONAL */
+ 0, /* TIFF_FLOAT */
+ 0, /* TIFF_DOUBLE */
+};
+
+/*
+ * Dummy functions to fill the omitted client procedures.
+ */
+static int
+_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ (void) fd; (void) pbase; (void) psize;
+ return (0);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ (void) fd; (void) base; (void) size;
+}
+
+/*
+ * Initialize the shift & mask tables, and the
+ * byte swapping state according to the file
+ * contents and the machine architecture.
+ */
+static void
+TIFFInitOrder(TIFF* tif, int magic)
+{
+ tif->tif_typemask = typemask;
+ if (magic == TIFF_BIGENDIAN) {
+ tif->tif_typeshift = bigTypeshift;
+#ifndef WORDS_BIGENDIAN
+ tif->tif_flags |= TIFF_SWAB;
+#endif
+ } else {
+ tif->tif_typeshift = litTypeshift;
+#ifdef WORDS_BIGENDIAN
+ tif->tif_flags |= TIFF_SWAB;
+#endif
+ }
+}
+
+int
+_TIFFgetMode(const char* mode, const char* module)
+{
+ int m = -1;
+
+ switch (mode[0]) {
+ case 'r':
+ m = O_RDONLY;
+ if (mode[1] == '+')
+ m = O_RDWR;
+ break;
+ case 'w':
+ case 'a':
+ m = O_RDWR|O_CREAT;
+ if (mode[0] == 'w')
+ m |= O_TRUNC;
+ break;
+ default:
+ TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
+ break;
+ }
+ return (m);
+}
+
+TIFF*
+TIFFClientOpen(
+ const char* name, const char* mode,
+ thandle_t clientdata,
+ TIFFReadWriteProc readproc,
+ TIFFReadWriteProc writeproc,
+ TIFFSeekProc seekproc,
+ TIFFCloseProc closeproc,
+ TIFFSizeProc sizeproc,
+ TIFFMapFileProc mapproc,
+ TIFFUnmapFileProc unmapproc
+)
+{
+ static const char module[] = "TIFFClientOpen";
+ TIFF *tif;
+ int m;
+ const char* cp;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ goto bad2;
+ tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
+ if (tif == NULL) {
+ TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
+ goto bad2;
+ }
+ _TIFFmemset(tif, 0, sizeof (*tif));
+ tif->tif_name = (char *)tif + sizeof (TIFF);
+ strcpy(tif->tif_name, name);
+ tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
+ tif->tif_curdir = (tdir_t) -1; /* non-existent directory */
+ tif->tif_curoff = 0;
+ tif->tif_curstrip = (tstrip_t) -1; /* invalid strip */
+ tif->tif_row = (uint32) -1; /* read/write pre-increment */
+ tif->tif_clientdata = clientdata;
+ if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
+ TIFFErrorExt(clientdata, module,
+ "One of the client procedures is NULL pointer.");
+ goto bad2;
+ }
+ tif->tif_readproc = readproc;
+ tif->tif_writeproc = writeproc;
+ tif->tif_seekproc = seekproc;
+ tif->tif_closeproc = closeproc;
+ tif->tif_sizeproc = sizeproc;
+ if (mapproc)
+ tif->tif_mapproc = mapproc;
+ else
+ tif->tif_mapproc = _tiffDummyMapProc;
+ if (unmapproc)
+ tif->tif_unmapproc = unmapproc;
+ else
+ tif->tif_unmapproc = _tiffDummyUnmapProc;
+ _TIFFSetDefaultCompressionState(tif); /* setup default state */
+ /*
+ * Default is to return data MSB2LSB and enable the
+ * use of memory-mapped files and strip chopping when
+ * a file is opened read-only.
+ */
+ tif->tif_flags = FILLORDER_MSB2LSB;
+ if (m == O_RDONLY )
+ tif->tif_flags |= TIFF_MAPPED;
+
+#ifdef STRIPCHOP_DEFAULT
+ if (m == O_RDONLY || m == O_RDWR)
+ tif->tif_flags |= STRIPCHOP_DEFAULT;
+#endif
+
+ /*
+ * Process library-specific flags in the open mode string.
+ * The following flags may be used to control intrinsic library
+ * behaviour that may or may not be desirable (usually for
+ * compatibility with some application that claims to support
+ * TIFF but only supports some braindead idea of what the
+ * vendor thinks TIFF is):
+ *
+ * 'l' use little-endian byte order for creating a file
+ * 'b' use big-endian byte order for creating a file
+ * 'L' read/write information using LSB2MSB bit order
+ * 'B' read/write information using MSB2LSB bit order
+ * 'H' read/write information using host bit order
+ * 'M' enable use of memory-mapped files when supported
+ * 'm' disable use of memory-mapped files
+ * 'C' enable strip chopping support when reading
+ * 'c' disable strip chopping support
+ * 'h' read TIFF header only, do not load the first IFD
+ *
+ * The use of the 'l' and 'b' flags is strongly discouraged.
+ * These flags are provided solely because numerous vendors,
+ * typically on the PC, do not correctly support TIFF; they
+ * only support the Intel little-endian byte order. This
+ * support is not configured by default because it supports
+ * the violation of the TIFF spec that says that readers *MUST*
+ * support both byte orders. It is strongly recommended that
+ * you not use this feature except to deal with busted apps
+ * that write invalid TIFF. And even in those cases you should
+ * bang on the vendors to fix their software.
+ *
+ * The 'L', 'B', and 'H' flags are intended for applications
+ * that can optimize operations on data by using a particular
+ * bit order. By default the library returns data in MSB2LSB
+ * bit order for compatibiltiy with older versions of this
+ * library. Returning data in the bit order of the native cpu
+ * makes the most sense but also requires applications to check
+ * the value of the FillOrder tag; something they probably do
+ * not do right now.
+ *
+ * The 'M' and 'm' flags are provided because some virtual memory
+ * systems exhibit poor behaviour when large images are mapped.
+ * These options permit clients to control the use of memory-mapped
+ * files on a per-file basis.
+ *
+ * The 'C' and 'c' flags are provided because the library support
+ * for chopping up large strips into multiple smaller strips is not
+ * application-transparent and as such can cause problems. The 'c'
+ * option permits applications that only want to look at the tags,
+ * for example, to get the unadulterated TIFF tag information.
+ */
+ for (cp = mode; *cp; cp++)
+ switch (*cp) {
+ case 'b':
+#ifndef WORDS_BIGENDIAN
+ if (m&O_CREAT)
+ tif->tif_flags |= TIFF_SWAB;
+#endif
+ break;
+ case 'l':
+#ifdef WORDS_BIGENDIAN
+ if ((m&O_CREAT))
+ tif->tif_flags |= TIFF_SWAB;
+#endif
+ break;
+ case 'B':
+ tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+ FILLORDER_MSB2LSB;
+ break;
+ case 'L':
+ tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+ FILLORDER_LSB2MSB;
+ break;
+ case 'H':
+ tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
+ HOST_FILLORDER;
+ break;
+ case 'M':
+ if (m == O_RDONLY)
+ tif->tif_flags |= TIFF_MAPPED;
+ break;
+ case 'm':
+ if (m == O_RDONLY)
+ tif->tif_flags &= ~TIFF_MAPPED;
+ break;
+ case 'C':
+ if (m == O_RDONLY)
+ tif->tif_flags |= TIFF_STRIPCHOP;
+ break;
+ case 'c':
+ if (m == O_RDONLY)
+ tif->tif_flags &= ~TIFF_STRIPCHOP;
+ break;
+ case 'h':
+ tif->tif_flags |= TIFF_HEADERONLY;
+ break;
+ }
+ /*
+ * Read in TIFF header.
+ */
+ if (tif->tif_mode & O_TRUNC ||
+ !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
+ if (tif->tif_mode == O_RDONLY) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "Cannot read TIFF header");
+ goto bad;
+ }
+ /*
+ * Setup header and write.
+ */
+#ifdef WORDS_BIGENDIAN
+ tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
+ ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
+#else
+ tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
+ ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
+#endif
+ tif->tif_header.tiff_version = TIFF_VERSION;
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabShort(&tif->tif_header.tiff_version);
+ tif->tif_header.tiff_diroff = 0; /* filled in later */
+
+
+ /*
+ * The doc for "fopen" for some STD_C_LIBs says that if you
+ * open a file for modify ("+"), then you must fseek (or
+ * fflush?) between any freads and fwrites. This is not
+ * necessary on most systems, but has been shown to be needed
+ * on Solaris.
+ */
+ TIFFSeekFile( tif, 0, SEEK_SET );
+
+ if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "Error writing TIFF header");
+ goto bad;
+ }
+ /*
+ * Setup the byte order handling.
+ */
+ TIFFInitOrder(tif, tif->tif_header.tiff_magic);
+ /*
+ * Setup default directory.
+ */
+ if (!TIFFDefaultDirectory(tif))
+ goto bad;
+ tif->tif_diroff = 0;
+ tif->tif_dirlist = NULL;
+ tif->tif_dirlistsize = 0;
+ tif->tif_dirnumber = 0;
+ return (tif);
+ }
+ /*
+ * Setup the byte order handling.
+ */
+ if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
+ tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN
+#if MDI_SUPPORT
+ &&
+#if HOST_BIGENDIAN
+ tif->tif_header.tiff_magic != MDI_BIGENDIAN
+#else
+ tif->tif_header.tiff_magic != MDI_LITTLEENDIAN
+#endif
+ ) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "Not a TIFF or MDI file, bad magic number %d (0x%x)",
+#else
+ ) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "Not a TIFF file, bad magic number %d (0x%x)",
+#endif
+ tif->tif_header.tiff_magic,
+ tif->tif_header.tiff_magic);
+ goto bad;
+ }
+ TIFFInitOrder(tif, tif->tif_header.tiff_magic);
+ /*
+ * Swap header if required.
+ */
+ if (tif->tif_flags & TIFF_SWAB) {
+ TIFFSwabShort(&tif->tif_header.tiff_version);
+ TIFFSwabLong(&tif->tif_header.tiff_diroff);
+ }
+ /*
+ * Now check version (if needed, it's been byte-swapped).
+ * Note that this isn't actually a version number, it's a
+ * magic number that doesn't change (stupid).
+ */
+ if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "This is a BigTIFF file. This format not supported\n"
+ "by this version of libtiff." );
+ goto bad;
+ }
+ if (tif->tif_header.tiff_version != TIFF_VERSION) {
+ TIFFErrorExt(tif->tif_clientdata, name,
+ "Not a TIFF file, bad version number %d (0x%x)",
+ tif->tif_header.tiff_version,
+ tif->tif_header.tiff_version);
+ goto bad;
+ }
+ tif->tif_flags |= TIFF_MYBUFFER;
+ tif->tif_rawcp = tif->tif_rawdata = 0;
+ tif->tif_rawdatasize = 0;
+
+ /*
+ * Sometimes we do not want to read the first directory (for example,
+ * it may be broken) and want to proceed to other directories. I this
+ * case we use the TIFF_HEADERONLY flag to open file and return
+ * immediately after reading TIFF header.
+ */
+ if (tif->tif_flags & TIFF_HEADERONLY)
+ return (tif);
+
+ /*
+ * Setup initial directory.
+ */
+ switch (mode[0]) {
+ case 'r':
+ tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
+ /*
+ * Try to use a memory-mapped file if the client
+ * has not explicitly suppressed usage with the
+ * 'm' flag in the open mode (see above).
+ */
+ if ((tif->tif_flags & TIFF_MAPPED) &&
+ !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
+ tif->tif_flags &= ~TIFF_MAPPED;
+ if (TIFFReadDirectory(tif)) {
+ tif->tif_rawcc = -1;
+ tif->tif_flags |= TIFF_BUFFERSETUP;
+ return (tif);
+ }
+ break;
+ case 'a':
+ /*
+ * New directories are automatically append
+ * to the end of the directory chain when they
+ * are written out (see TIFFWriteDirectory).
+ */
+ if (!TIFFDefaultDirectory(tif))
+ goto bad;
+ return (tif);
+ }
+bad:
+ tif->tif_mode = O_RDONLY; /* XXX avoid flush */
+ TIFFCleanup(tif);
+bad2:
+ return ((TIFF*)0);
+}
+
+/*
+ * Query functions to access private data.
+ */
+
+/*
+ * Return open file's name.
+ */
+const char *
+TIFFFileName(TIFF* tif)
+{
+ return (tif->tif_name);
+}
+
+/*
+ * Set the file name.
+ */
+const char *
+TIFFSetFileName(TIFF* tif, const char *name)
+{
+ const char* old_name = tif->tif_name;
+ tif->tif_name = (char *)name;
+ return (old_name);
+}
+
+/*
+ * Return open file's I/O descriptor.
+ */
+int
+TIFFFileno(TIFF* tif)
+{
+ return (tif->tif_fd);
+}
+
+/*
+ * Set open file's I/O descriptor, and return previous value.
+ */
+int
+TIFFSetFileno(TIFF* tif, int fd)
+{
+ int old_fd = tif->tif_fd;
+ tif->tif_fd = fd;
+ return old_fd;
+}
+
+/*
+ * Return open file's clientdata.
+ */
+thandle_t
+TIFFClientdata(TIFF* tif)
+{
+ return (tif->tif_clientdata);
+}
+
+/*
+ * Set open file's clientdata, and return previous value.
+ */
+thandle_t
+TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
+{
+ thandle_t m = tif->tif_clientdata;
+ tif->tif_clientdata = newvalue;
+ return m;
+}
+
+/*
+ * Return read/write mode.
+ */
+int
+TIFFGetMode(TIFF* tif)
+{
+ return (tif->tif_mode);
+}
+
+/*
+ * Return read/write mode.
+ */
+int
+TIFFSetMode(TIFF* tif, int mode)
+{
+ int old_mode = tif->tif_mode;
+ tif->tif_mode = mode;
+ return (old_mode);
+}
+
+/*
+ * Return nonzero if file is organized in
+ * tiles; zero if organized as strips.
+ */
+int
+TIFFIsTiled(TIFF* tif)
+{
+ return (isTiled(tif));
+}
+
+/*
+ * Return current row being read/written.
+ */
+uint32
+TIFFCurrentRow(TIFF* tif)
+{
+ return (tif->tif_row);
+}
+
+/*
+ * Return index of the current directory.
+ */
+tdir_t
+TIFFCurrentDirectory(TIFF* tif)
+{
+ return (tif->tif_curdir);
+}
+
+/*
+ * Return current strip.
+ */
+tstrip_t
+TIFFCurrentStrip(TIFF* tif)
+{
+ return (tif->tif_curstrip);
+}
+
+/*
+ * Return current tile.
+ */
+ttile_t
+TIFFCurrentTile(TIFF* tif)
+{
+ return (tif->tif_curtile);
+}
+
+/*
+ * Return nonzero if the file has byte-swapped data.
+ */
+int
+TIFFIsByteSwapped(TIFF* tif)
+{
+ return ((tif->tif_flags & TIFF_SWAB) != 0);
+}
+
+/*
+ * Return nonzero if the data is returned up-sampled.
+ */
+int
+TIFFIsUpSampled(TIFF* tif)
+{
+ return (isUpSampled(tif));
+}
+
+/*
+ * Return nonzero if the data is returned in MSB-to-LSB bit order.
+ */
+int
+TIFFIsMSB2LSB(TIFF* tif)
+{
+ return (isFillOrder(tif, FILLORDER_MSB2LSB));
+}
+
+/*
+ * Return nonzero if given file was written in big-endian order.
+ */
+int
+TIFFIsBigEndian(TIFF* tif)
+{
+ return (tif->tif_header.tiff_magic == TIFF_BIGENDIAN);
+}
+
+/*
+ * Return pointer to file read method.
+ */
+TIFFReadWriteProc
+TIFFGetReadProc(TIFF* tif)
+{
+ return (tif->tif_readproc);
+}
+
+/*
+ * Return pointer to file write method.
+ */
+TIFFReadWriteProc
+TIFFGetWriteProc(TIFF* tif)
+{
+ return (tif->tif_writeproc);
+}
+
+/*
+ * Return pointer to file seek method.
+ */
+TIFFSeekProc
+TIFFGetSeekProc(TIFF* tif)
+{
+ return (tif->tif_seekproc);
+}
+
+/*
+ * Return pointer to file close method.
+ */
+TIFFCloseProc
+TIFFGetCloseProc(TIFF* tif)
+{
+ return (tif->tif_closeproc);
+}
+
+/*
+ * Return pointer to file size requesting method.
+ */
+TIFFSizeProc
+TIFFGetSizeProc(TIFF* tif)
+{
+ return (tif->tif_sizeproc);
+}
+
+/*
+ * Return pointer to memory mapping method.
+ */
+TIFFMapFileProc
+TIFFGetMapFileProc(TIFF* tif)
+{
+ return (tif->tif_mapproc);
+}
+
+/*
+ * Return pointer to memory unmapping method.
+ */
+TIFFUnmapFileProc
+TIFFGetUnmapFileProc(TIFF* tif)
+{
+ return (tif->tif_unmapproc);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_packbits.c b/Source/LibTIFF/tif_packbits.c
new file mode 100644
index 0000000..6d1d4bf
--- /dev/null
+++ b/Source/LibTIFF/tif_packbits.c
@@ -0,0 +1,293 @@
+/* $Id: tif_packbits.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef PACKBITS_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * PackBits Compression Algorithm Support
+ */
+#include <stdio.h>
+
+static int
+PackBitsPreEncode(TIFF* tif, tsample_t s)
+{
+ (void) s;
+
+ if (!(tif->tif_data = (tidata_t)_TIFFmalloc(sizeof(tsize_t))))
+ return (0);
+ /*
+ * Calculate the scanline/tile-width size in bytes.
+ */
+ if (isTiled(tif))
+ *(tsize_t*)tif->tif_data = TIFFTileRowSize(tif);
+ else
+ *(tsize_t*)tif->tif_data = TIFFScanlineSize(tif);
+ return (1);
+}
+
+static int
+PackBitsPostEncode(TIFF* tif)
+{
+ if (tif->tif_data)
+ _TIFFfree(tif->tif_data);
+ return (1);
+}
+
+/*
+ * NB: tidata is the type representing *(tidata_t);
+ * if tidata_t is made signed then this type must
+ * be adjusted accordingly.
+ */
+typedef unsigned char tidata;
+
+/*
+ * Encode a run of pixels.
+ */
+static int
+PackBitsEncode(TIFF* tif, tidata_t buf, tsize_t cc, tsample_t s)
+{
+ unsigned char* bp = (unsigned char*) buf;
+ tidata_t op, ep, lastliteral;
+ long n, slop;
+ int b;
+ enum { BASE, LITERAL, RUN, LITERAL_RUN } state;
+
+ (void) s;
+ op = tif->tif_rawcp;
+ ep = tif->tif_rawdata + tif->tif_rawdatasize;
+ state = BASE;
+ lastliteral = 0;
+ while (cc > 0) {
+ /*
+ * Find the longest string of identical bytes.
+ */
+ b = *bp++, cc--, n = 1;
+ for (; cc > 0 && b == *bp; cc--, bp++)
+ n++;
+ again:
+ if (op + 2 >= ep) { /* insure space for new data */
+ /*
+ * Be careful about writing the last
+ * literal. Must write up to that point
+ * and then copy the remainder to the
+ * front of the buffer.
+ */
+ if (state == LITERAL || state == LITERAL_RUN) {
+ slop = op - lastliteral;
+ tif->tif_rawcc += lastliteral - tif->tif_rawcp;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ while (slop-- > 0)
+ *op++ = *lastliteral++;
+ lastliteral = tif->tif_rawcp;
+ } else {
+ tif->tif_rawcc += op - tif->tif_rawcp;
+ if (!TIFFFlushData1(tif))
+ return (-1);
+ op = tif->tif_rawcp;
+ }
+ }
+ switch (state) {
+ case BASE: /* initial state, set run/literal */
+ if (n > 1) {
+ state = RUN;
+ if (n > 128) {
+ *op++ = (tidata) -127;
+ *op++ = (tidataval_t) b;
+ n -= 128;
+ goto again;
+ }
+ *op++ = (tidataval_t)(-(n-1));
+ *op++ = (tidataval_t) b;
+ } else {
+ lastliteral = op;
+ *op++ = 0;
+ *op++ = (tidataval_t) b;
+ state = LITERAL;
+ }
+ break;
+ case LITERAL: /* last object was literal string */
+ if (n > 1) {
+ state = LITERAL_RUN;
+ if (n > 128) {
+ *op++ = (tidata) -127;
+ *op++ = (tidataval_t) b;
+ n -= 128;
+ goto again;
+ }
+ *op++ = (tidataval_t)(-(n-1)); /* encode run */
+ *op++ = (tidataval_t) b;
+ } else { /* extend literal */
+ if (++(*lastliteral) == 127)
+ state = BASE;
+ *op++ = (tidataval_t) b;
+ }
+ break;
+ case RUN: /* last object was run */
+ if (n > 1) {
+ if (n > 128) {
+ *op++ = (tidata) -127;
+ *op++ = (tidataval_t) b;
+ n -= 128;
+ goto again;
+ }
+ *op++ = (tidataval_t)(-(n-1));
+ *op++ = (tidataval_t) b;
+ } else {
+ lastliteral = op;
+ *op++ = 0;
+ *op++ = (tidataval_t) b;
+ state = LITERAL;
+ }
+ break;
+ case LITERAL_RUN: /* literal followed by a run */
+ /*
+ * Check to see if previous run should
+ * be converted to a literal, in which
+ * case we convert literal-run-literal
+ * to a single literal.
+ */
+ if (n == 1 && op[-2] == (tidata) -1 &&
+ *lastliteral < 126) {
+ state = (((*lastliteral) += 2) == 127 ?
+ BASE : LITERAL);
+ op[-2] = op[-1]; /* replicate */
+ } else
+ state = RUN;
+ goto again;
+ }
+ }
+ tif->tif_rawcc += op - tif->tif_rawcp;
+ tif->tif_rawcp = op;
+ return (1);
+}
+
+/*
+ * Encode a rectangular chunk of pixels. We break it up
+ * into row-sized pieces to insure that encoded runs do
+ * not span rows. Otherwise, there can be problems with
+ * the decoder if data is read, for example, by scanlines
+ * when it was encoded by strips.
+ */
+static int
+PackBitsEncodeChunk(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ tsize_t rowsize = *(tsize_t*)tif->tif_data;
+
+ while ((long)cc > 0) {
+ int chunk = rowsize;
+
+ if( cc < chunk )
+ chunk = cc;
+
+ if (PackBitsEncode(tif, bp, chunk, s) < 0)
+ return (-1);
+ bp += chunk;
+ cc -= chunk;
+ }
+ return (1);
+}
+
+static int
+PackBitsDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ char *bp;
+ tsize_t cc;
+ long n;
+ int b;
+
+ (void) s;
+ bp = (char*) tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ while (cc > 0 && (long)occ > 0) {
+ n = (long) *bp++, cc--;
+ /*
+ * Watch out for compilers that
+ * don't sign extend chars...
+ */
+ if (n >= 128)
+ n -= 256;
+ if (n < 0) { /* replicate next byte -n+1 times */
+ if (n == -128) /* nop */
+ continue;
+ n = -n + 1;
+ if( occ < n )
+ {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "PackBitsDecode: discarding %ld bytes "
+ "to avoid buffer overrun",
+ n - occ);
+ n = occ;
+ }
+ occ -= n;
+ b = *bp++, cc--;
+ while (n-- > 0)
+ *op++ = (tidataval_t) b;
+ } else { /* copy next n+1 bytes literally */
+ if (occ < n + 1)
+ {
+ TIFFWarningExt(tif->tif_clientdata, tif->tif_name,
+ "PackBitsDecode: discarding %ld bytes "
+ "to avoid buffer overrun",
+ n - occ + 1);
+ n = occ - 1;
+ }
+ _TIFFmemcpy(op, bp, ++n);
+ op += n; occ -= n;
+ bp += n; cc -= n;
+ }
+ }
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ if (occ > 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "PackBitsDecode: Not enough data for scanline %ld",
+ (long) tif->tif_row);
+ return (0);
+ }
+ return (1);
+}
+
+int
+TIFFInitPackBits(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ tif->tif_decoderow = PackBitsDecode;
+ tif->tif_decodestrip = PackBitsDecode;
+ tif->tif_decodetile = PackBitsDecode;
+ tif->tif_preencode = PackBitsPreEncode;
+ tif->tif_postencode = PackBitsPostEncode;
+ tif->tif_encoderow = PackBitsEncode;
+ tif->tif_encodestrip = PackBitsEncodeChunk;
+ tif->tif_encodetile = PackBitsEncodeChunk;
+ return (1);
+}
+#endif /* PACKBITS_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_pixarlog.c b/Source/LibTIFF/tif_pixarlog.c
new file mode 100644
index 0000000..ea8926e
--- /dev/null
+++ b/Source/LibTIFF/tif_pixarlog.c
@@ -0,0 +1,1364 @@
+/* $Id: tif_pixarlog.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1996-1997 Sam Leffler
+ * Copyright (c) 1996 Pixar
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Pixar, Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef PIXARLOG_SUPPORT
+
+/*
+ * TIFF Library.
+ * PixarLog Compression Support
+ *
+ * Contributed by Dan McCoy.
+ *
+ * PixarLog film support uses the TIFF library to store companded
+ * 11 bit values into a tiff file, which are compressed using the
+ * zip compressor.
+ *
+ * The codec can take as input and produce as output 32-bit IEEE float values
+ * as well as 16-bit or 8-bit unsigned integer values.
+ *
+ * On writing any of the above are converted into the internal
+ * 11-bit log format. In the case of 8 and 16 bit values, the
+ * input is assumed to be unsigned linear color values that represent
+ * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to
+ * be the normal linear color range, in addition over 1 values are
+ * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
+ * The encoding is lossless for 8-bit values, slightly lossy for the
+ * other bit depths. The actual color precision should be better
+ * than the human eye can perceive with extra room to allow for
+ * error introduced by further image computation. As with any quantized
+ * color format, it is possible to perform image calculations which
+ * expose the quantization error. This format should certainly be less
+ * susceptable to such errors than standard 8-bit encodings, but more
+ * susceptable than straight 16-bit or 32-bit encodings.
+ *
+ * On reading the internal format is converted to the desired output format.
+ * The program can request which format it desires by setting the internal
+ * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
+ * PIXARLOGDATAFMT_FLOAT = provide IEEE float values.
+ * PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values
+ * PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values
+ *
+ * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
+ * values with the difference that if there are exactly three or four channels
+ * (rgb or rgba) it swaps the channel order (bgr or abgr).
+ *
+ * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
+ * packed in 16-bit values. However no tools are supplied for interpreting
+ * these values.
+ *
+ * "hot" (over 1.0) areas written in floating point get clamped to
+ * 1.0 in the integer data types.
+ *
+ * When the file is closed after writing, the bit depth and sample format
+ * are set always to appear as if 8-bit data has been written into it.
+ * That way a naive program unaware of the particulars of the encoding
+ * gets the format it is most likely able to handle.
+ *
+ * The codec does it's own horizontal differencing step on the coded
+ * values so the libraries predictor stuff should be turned off.
+ * The codec also handle byte swapping the encoded values as necessary
+ * since the library does not have the information necessary
+ * to know the bit depth of the raw unencoded buffer.
+ *
+ */
+
+#include "tif_predict.h"
+#include <zlib.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* Tables for converting to/from 11 bit coded values */
+
+#define TSIZE 2048 /* decode table size (11-bit tokens) */
+#define TSIZEP1 2049 /* Plus one for slop */
+#define ONE 1250 /* token value of 1.0 exactly */
+#define RATIO 1.004 /* nominal ratio for log part */
+
+#define CODE_MASK 0x7ff /* 11 bits. */
+
+static float Fltsize;
+static float LogK1, LogK2;
+
+#define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); }
+
+static void
+horizontalAccumulateF(uint16 *wp, int n, int stride, float *op,
+ float *ToLinearF)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+ register float t0, t1, t2, t3;
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ t0 = ToLinearF[cr = wp[0]];
+ t1 = ToLinearF[cg = wp[1]];
+ t2 = ToLinearF[cb = wp[2]];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ n -= 3;
+ while (n > 0) {
+ wp += 3;
+ op += 3;
+ n -= 3;
+ t0 = ToLinearF[(cr += wp[0]) & mask];
+ t1 = ToLinearF[(cg += wp[1]) & mask];
+ t2 = ToLinearF[(cb += wp[2]) & mask];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ }
+ } else if (stride == 4) {
+ t0 = ToLinearF[cr = wp[0]];
+ t1 = ToLinearF[cg = wp[1]];
+ t2 = ToLinearF[cb = wp[2]];
+ t3 = ToLinearF[ca = wp[3]];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ n -= 4;
+ while (n > 0) {
+ wp += 4;
+ op += 4;
+ n -= 4;
+ t0 = ToLinearF[(cr += wp[0]) & mask];
+ t1 = ToLinearF[(cg += wp[1]) & mask];
+ t2 = ToLinearF[(cb += wp[2]) & mask];
+ t3 = ToLinearF[(ca += wp[3]) & mask];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ }
+ } else {
+ REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+static void
+horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op,
+ float *ToLinearF)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+ register float t0, t1, t2, t3;
+
+#define SCALE12 2048.0F
+#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ t0 = ToLinearF[cr = wp[0]] * SCALE12;
+ t1 = ToLinearF[cg = wp[1]] * SCALE12;
+ t2 = ToLinearF[cb = wp[2]] * SCALE12;
+ op[0] = CLAMP12(t0);
+ op[1] = CLAMP12(t1);
+ op[2] = CLAMP12(t2);
+ n -= 3;
+ while (n > 0) {
+ wp += 3;
+ op += 3;
+ n -= 3;
+ t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
+ t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
+ t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
+ op[0] = CLAMP12(t0);
+ op[1] = CLAMP12(t1);
+ op[2] = CLAMP12(t2);
+ }
+ } else if (stride == 4) {
+ t0 = ToLinearF[cr = wp[0]] * SCALE12;
+ t1 = ToLinearF[cg = wp[1]] * SCALE12;
+ t2 = ToLinearF[cb = wp[2]] * SCALE12;
+ t3 = ToLinearF[ca = wp[3]] * SCALE12;
+ op[0] = CLAMP12(t0);
+ op[1] = CLAMP12(t1);
+ op[2] = CLAMP12(t2);
+ op[3] = CLAMP12(t3);
+ n -= 4;
+ while (n > 0) {
+ wp += 4;
+ op += 4;
+ n -= 4;
+ t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
+ t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
+ t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
+ t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
+ op[0] = CLAMP12(t0);
+ op[1] = CLAMP12(t1);
+ op[2] = CLAMP12(t2);
+ op[3] = CLAMP12(t3);
+ }
+ } else {
+ REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
+ *op = CLAMP12(t0); wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
+ *op = CLAMP12(t0); wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+static void
+horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
+ uint16 *ToLinear16)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ op[0] = ToLinear16[cr = wp[0]];
+ op[1] = ToLinear16[cg = wp[1]];
+ op[2] = ToLinear16[cb = wp[2]];
+ n -= 3;
+ while (n > 0) {
+ wp += 3;
+ op += 3;
+ n -= 3;
+ op[0] = ToLinear16[(cr += wp[0]) & mask];
+ op[1] = ToLinear16[(cg += wp[1]) & mask];
+ op[2] = ToLinear16[(cb += wp[2]) & mask];
+ }
+ } else if (stride == 4) {
+ op[0] = ToLinear16[cr = wp[0]];
+ op[1] = ToLinear16[cg = wp[1]];
+ op[2] = ToLinear16[cb = wp[2]];
+ op[3] = ToLinear16[ca = wp[3]];
+ n -= 4;
+ while (n > 0) {
+ wp += 4;
+ op += 4;
+ n -= 4;
+ op[0] = ToLinear16[(cr += wp[0]) & mask];
+ op[1] = ToLinear16[(cg += wp[1]) & mask];
+ op[2] = ToLinear16[(cb += wp[2]) & mask];
+ op[3] = ToLinear16[(ca += wp[3]) & mask];
+ }
+ } else {
+ REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+/*
+ * Returns the log encoded 11-bit values with the horizontal
+ * differencing undone.
+ */
+static void
+horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2];
+ n -= 3;
+ while (n > 0) {
+ wp += 3;
+ op += 3;
+ n -= 3;
+ op[0] = (cr += wp[0]) & mask;
+ op[1] = (cg += wp[1]) & mask;
+ op[2] = (cb += wp[2]) & mask;
+ }
+ } else if (stride == 4) {
+ op[0] = cr = wp[0]; op[1] = cg = wp[1];
+ op[2] = cb = wp[2]; op[3] = ca = wp[3];
+ n -= 4;
+ while (n > 0) {
+ wp += 4;
+ op += 4;
+ n -= 4;
+ op[0] = (cr += wp[0]) & mask;
+ op[1] = (cg += wp[1]) & mask;
+ op[2] = (cb += wp[2]) & mask;
+ op[3] = (ca += wp[3]) & mask;
+ }
+ } else {
+ REPEAT(stride, *op = *wp&mask; wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; *op = *wp&mask; wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+static void
+horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op,
+ unsigned char *ToLinear8)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ op[0] = ToLinear8[cr = wp[0]];
+ op[1] = ToLinear8[cg = wp[1]];
+ op[2] = ToLinear8[cb = wp[2]];
+ n -= 3;
+ while (n > 0) {
+ n -= 3;
+ wp += 3;
+ op += 3;
+ op[0] = ToLinear8[(cr += wp[0]) & mask];
+ op[1] = ToLinear8[(cg += wp[1]) & mask];
+ op[2] = ToLinear8[(cb += wp[2]) & mask];
+ }
+ } else if (stride == 4) {
+ op[0] = ToLinear8[cr = wp[0]];
+ op[1] = ToLinear8[cg = wp[1]];
+ op[2] = ToLinear8[cb = wp[2]];
+ op[3] = ToLinear8[ca = wp[3]];
+ n -= 4;
+ while (n > 0) {
+ n -= 4;
+ wp += 4;
+ op += 4;
+ op[0] = ToLinear8[(cr += wp[0]) & mask];
+ op[1] = ToLinear8[(cg += wp[1]) & mask];
+ op[2] = ToLinear8[(cb += wp[2]) & mask];
+ op[3] = ToLinear8[(ca += wp[3]) & mask];
+ }
+ } else {
+ REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+
+static void
+horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
+ unsigned char *ToLinear8)
+{
+ register unsigned int cr, cg, cb, ca, mask;
+ register unsigned char t0, t1, t2, t3;
+
+ if (n >= stride) {
+ mask = CODE_MASK;
+ if (stride == 3) {
+ op[0] = 0;
+ t1 = ToLinear8[cb = wp[2]];
+ t2 = ToLinear8[cg = wp[1]];
+ t3 = ToLinear8[cr = wp[0]];
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ n -= 3;
+ while (n > 0) {
+ n -= 3;
+ wp += 3;
+ op += 4;
+ op[0] = 0;
+ t1 = ToLinear8[(cb += wp[2]) & mask];
+ t2 = ToLinear8[(cg += wp[1]) & mask];
+ t3 = ToLinear8[(cr += wp[0]) & mask];
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ }
+ } else if (stride == 4) {
+ t0 = ToLinear8[ca = wp[3]];
+ t1 = ToLinear8[cb = wp[2]];
+ t2 = ToLinear8[cg = wp[1]];
+ t3 = ToLinear8[cr = wp[0]];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ n -= 4;
+ while (n > 0) {
+ n -= 4;
+ wp += 4;
+ op += 4;
+ t0 = ToLinear8[(ca += wp[3]) & mask];
+ t1 = ToLinear8[(cb += wp[2]) & mask];
+ t2 = ToLinear8[(cg += wp[1]) & mask];
+ t3 = ToLinear8[(cr += wp[0]) & mask];
+ op[0] = t0;
+ op[1] = t1;
+ op[2] = t2;
+ op[3] = t3;
+ }
+ } else {
+ REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride,
+ wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
+ n -= stride;
+ }
+ }
+ }
+}
+
+/*
+ * State block for each open TIFF
+ * file using PixarLog compression/decompression.
+ */
+typedef struct {
+ TIFFPredictorState predict;
+ z_stream stream;
+ uint16 *tbuf;
+ uint16 stride;
+ int state;
+ int user_datafmt;
+ int quality;
+#define PLSTATE_INIT 1
+
+ TIFFVSetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+
+ float *ToLinearF;
+ uint16 *ToLinear16;
+ unsigned char *ToLinear8;
+ uint16 *FromLT2;
+ uint16 *From14; /* Really for 16-bit data, but we shift down 2 */
+ uint16 *From8;
+
+} PixarLogState;
+
+static int
+PixarLogMakeTables(PixarLogState *sp)
+{
+
+/*
+ * We make several tables here to convert between various external
+ * representations (float, 16-bit, and 8-bit) and the internal
+ * 11-bit companded representation. The 11-bit representation has two
+ * distinct regions. A linear bottom end up through .018316 in steps
+ * of about .000073, and a region of constant ratio up to about 25.
+ * These floating point numbers are stored in the main table ToLinearF.
+ * All other tables are derived from this one. The tables (and the
+ * ratios) are continuous at the internal seam.
+ */
+
+ int nlin, lt2size;
+ int i, j;
+ double b, c, linstep, v;
+ float *ToLinearF;
+ uint16 *ToLinear16;
+ unsigned char *ToLinear8;
+ uint16 *FromLT2;
+ uint16 *From14; /* Really for 16-bit data, but we shift down 2 */
+ uint16 *From8;
+
+ c = log(RATIO);
+ nlin = (int)(1./c); /* nlin must be an integer */
+ c = 1./nlin;
+ b = exp(-c*ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */
+ linstep = b*c*exp(1.);
+
+ LogK1 = (float)(1./c); /* if (v >= 2) token = k1*log(v*k2) */
+ LogK2 = (float)(1./b);
+ lt2size = (int)(2./linstep) + 1;
+ FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16));
+ From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16));
+ From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16));
+ ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
+ ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16));
+ ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
+ if (FromLT2 == NULL || From14 == NULL || From8 == NULL ||
+ ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
+ if (FromLT2) _TIFFfree(FromLT2);
+ if (From14) _TIFFfree(From14);
+ if (From8) _TIFFfree(From8);
+ if (ToLinearF) _TIFFfree(ToLinearF);
+ if (ToLinear16) _TIFFfree(ToLinear16);
+ if (ToLinear8) _TIFFfree(ToLinear8);
+ sp->FromLT2 = NULL;
+ sp->From14 = NULL;
+ sp->From8 = NULL;
+ sp->ToLinearF = NULL;
+ sp->ToLinear16 = NULL;
+ sp->ToLinear8 = NULL;
+ return 0;
+ }
+
+ j = 0;
+
+ for (i = 0; i < nlin; i++) {
+ v = i * linstep;
+ ToLinearF[j++] = (float)v;
+ }
+
+ for (i = nlin; i < TSIZE; i++)
+ ToLinearF[j++] = (float)(b*exp(c*i));
+
+ ToLinearF[2048] = ToLinearF[2047];
+
+ for (i = 0; i < TSIZEP1; i++) {
+ v = ToLinearF[i]*65535.0 + 0.5;
+ ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v;
+ v = ToLinearF[i]*255.0 + 0.5;
+ ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v;
+ }
+
+ j = 0;
+ for (i = 0; i < lt2size; i++) {
+ if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
+ j++;
+ FromLT2[i] = j;
+ }
+
+ /*
+ * Since we lose info anyway on 16-bit data, we set up a 14-bit
+ * table and shift 16-bit values down two bits on input.
+ * saves a little table space.
+ */
+ j = 0;
+ for (i = 0; i < 16384; i++) {
+ while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
+ j++;
+ From14[i] = j;
+ }
+
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
+ j++;
+ From8[i] = j;
+ }
+
+ Fltsize = (float)(lt2size/2);
+
+ sp->ToLinearF = ToLinearF;
+ sp->ToLinear16 = ToLinear16;
+ sp->ToLinear8 = ToLinear8;
+ sp->FromLT2 = FromLT2;
+ sp->From14 = From14;
+ sp->From8 = From8;
+
+ return 1;
+}
+
+#define DecoderState(tif) ((PixarLogState*) (tif)->tif_data)
+#define EncoderState(tif) ((PixarLogState*) (tif)->tif_data)
+
+static int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+
+#define PIXARLOGDATAFMT_UNKNOWN -1
+
+static int
+PixarLogGuessDataFmt(TIFFDirectory *td)
+{
+ int guess = PIXARLOGDATAFMT_UNKNOWN;
+ int format = td->td_sampleformat;
+
+ /* If the user didn't tell us his datafmt,
+ * take our best guess from the bitspersample.
+ */
+ switch (td->td_bitspersample) {
+ case 32:
+ if (format == SAMPLEFORMAT_IEEEFP)
+ guess = PIXARLOGDATAFMT_FLOAT;
+ break;
+ case 16:
+ if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+ guess = PIXARLOGDATAFMT_16BIT;
+ break;
+ case 12:
+ if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
+ guess = PIXARLOGDATAFMT_12BITPICIO;
+ break;
+ case 11:
+ if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+ guess = PIXARLOGDATAFMT_11BITLOG;
+ break;
+ case 8:
+ if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
+ guess = PIXARLOGDATAFMT_8BIT;
+ break;
+ }
+
+ return guess;
+}
+
+static uint32
+multiply(size_t m1, size_t m2)
+{
+ uint32 bytes = m1 * m2;
+
+ if (m1 && bytes / m1 != m2)
+ bytes = 0;
+
+ return bytes;
+}
+
+static int
+PixarLogSetupDecode(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ PixarLogState* sp = DecoderState(tif);
+ tsize_t tbuf_size;
+ static const char module[] = "PixarLogSetupDecode";
+
+ assert(sp != NULL);
+
+ /* Make sure no byte swapping happens on the data
+ * after decompression. */
+ tif->tif_postdecode = _TIFFNoPostDecode;
+
+ /* for some reason, we can't do this in TIFFInitPixarLog */
+
+ sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+ td->td_samplesperpixel : 1);
+ tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
+ td->td_rowsperstrip), sizeof(uint16));
+ if (tbuf_size == 0)
+ return (0);
+ sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
+ if (sp->tbuf == NULL)
+ return (0);
+ if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
+ sp->user_datafmt = PixarLogGuessDataFmt(td);
+ if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "PixarLog compression can't handle bits depth/data format combination (depth: %d)",
+ td->td_bitspersample);
+ return (0);
+ }
+
+ if (inflateInit(&sp->stream) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
+ return (0);
+ } else {
+ sp->state |= PLSTATE_INIT;
+ return (1);
+ }
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+PixarLogPreDecode(TIFF* tif, tsample_t s)
+{
+ PixarLogState* sp = DecoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ sp->stream.next_in = tif->tif_rawdata;
+ sp->stream.avail_in = tif->tif_rawcc;
+ return (inflateReset(&sp->stream) == Z_OK);
+}
+
+static int
+PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ PixarLogState* sp = DecoderState(tif);
+ static const char module[] = "PixarLogDecode";
+ int i, nsamples, llen;
+ uint16 *up;
+
+ switch (sp->user_datafmt) {
+ case PIXARLOGDATAFMT_FLOAT:
+ nsamples = occ / sizeof(float); /* XXX float == 32 bits */
+ break;
+ case PIXARLOGDATAFMT_16BIT:
+ case PIXARLOGDATAFMT_12BITPICIO:
+ case PIXARLOGDATAFMT_11BITLOG:
+ nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */
+ break;
+ case PIXARLOGDATAFMT_8BIT:
+ case PIXARLOGDATAFMT_8BITABGR:
+ nsamples = occ;
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%d bit input not supported in PixarLog",
+ td->td_bitspersample);
+ return 0;
+ }
+
+ llen = sp->stride * td->td_imagewidth;
+
+ (void) s;
+ assert(sp != NULL);
+ sp->stream.next_out = (unsigned char *) sp->tbuf;
+ sp->stream.avail_out = nsamples * sizeof(uint16);
+ do {
+ int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+ if (state == Z_STREAM_END) {
+ break; /* XXX */
+ }
+ if (state == Z_DATA_ERROR) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Decoding error at scanline %d, %s",
+ tif->tif_name, tif->tif_row, sp->stream.msg);
+ if (inflateSync(&sp->stream) != Z_OK)
+ return (0);
+ continue;
+ }
+ if (state != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ } while (sp->stream.avail_out > 0);
+
+ /* hopefully, we got all the bytes we needed */
+ if (sp->stream.avail_out != 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Not enough data at scanline %d (short %d bytes)",
+ tif->tif_name, tif->tif_row, sp->stream.avail_out);
+ return (0);
+ }
+
+ up = sp->tbuf;
+ /* Swap bytes in the data if from a different endian machine. */
+ if (tif->tif_flags & TIFF_SWAB)
+ TIFFSwabArrayOfShort(up, nsamples);
+
+ /*
+ * if llen is not an exact multiple of nsamples, the decode operation
+ * may overflow the output buffer, so truncate it enough to prevent
+ * that but still salvage as much data as possible.
+ */
+ if (nsamples % llen) {
+ TIFFWarningExt(tif->tif_clientdata, module,
+ "%s: stride %d is not a multiple of sample count, "
+ "%d, data truncated.", tif->tif_name, llen, nsamples);
+ nsamples -= nsamples % llen;
+ }
+
+ for (i = 0; i < nsamples; i += llen, up += llen) {
+ switch (sp->user_datafmt) {
+ case PIXARLOGDATAFMT_FLOAT:
+ horizontalAccumulateF(up, llen, sp->stride,
+ (float *)op, sp->ToLinearF);
+ op += llen * sizeof(float);
+ break;
+ case PIXARLOGDATAFMT_16BIT:
+ horizontalAccumulate16(up, llen, sp->stride,
+ (uint16 *)op, sp->ToLinear16);
+ op += llen * sizeof(uint16);
+ break;
+ case PIXARLOGDATAFMT_12BITPICIO:
+ horizontalAccumulate12(up, llen, sp->stride,
+ (int16 *)op, sp->ToLinearF);
+ op += llen * sizeof(int16);
+ break;
+ case PIXARLOGDATAFMT_11BITLOG:
+ horizontalAccumulate11(up, llen, sp->stride,
+ (uint16 *)op);
+ op += llen * sizeof(uint16);
+ break;
+ case PIXARLOGDATAFMT_8BIT:
+ horizontalAccumulate8(up, llen, sp->stride,
+ (unsigned char *)op, sp->ToLinear8);
+ op += llen * sizeof(unsigned char);
+ break;
+ case PIXARLOGDATAFMT_8BITABGR:
+ horizontalAccumulate8abgr(up, llen, sp->stride,
+ (unsigned char *)op, sp->ToLinear8);
+ op += llen * sizeof(unsigned char);
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "PixarLogDecode: unsupported bits/sample: %d",
+ td->td_bitspersample);
+ return (0);
+ }
+ }
+
+ return (1);
+}
+
+static int
+PixarLogSetupEncode(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ PixarLogState* sp = EncoderState(tif);
+ tsize_t tbuf_size;
+ static const char module[] = "PixarLogSetupEncode";
+
+ assert(sp != NULL);
+
+ /* for some reason, we can't do this in TIFFInitPixarLog */
+
+ sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+ td->td_samplesperpixel : 1);
+ tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
+ td->td_rowsperstrip), sizeof(uint16));
+ if (tbuf_size == 0)
+ return (0);
+ sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
+ if (sp->tbuf == NULL)
+ return (0);
+ if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
+ sp->user_datafmt = PixarLogGuessDataFmt(td);
+ if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
+ TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample);
+ return (0);
+ }
+
+ if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
+ return (0);
+ } else {
+ sp->state |= PLSTATE_INIT;
+ return (1);
+ }
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+PixarLogPreEncode(TIFF* tif, tsample_t s)
+{
+ PixarLogState *sp = EncoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ return (deflateReset(&sp->stream) == Z_OK);
+}
+
+static void
+horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
+{
+
+ int32 r1, g1, b1, a1, r2, g2, b2, a2, mask;
+ float fltsize = Fltsize;
+
+#define CLAMP(v) ( (v<(float)0.) ? 0 \
+ : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \
+ : (v>(float)24.2) ? 2047 \
+ : LogK1*log(v*LogK2) + 0.5 )
+
+ mask = CODE_MASK;
+ if (n >= stride) {
+ if (stride == 3) {
+ r2 = wp[0] = (uint16) CLAMP(ip[0]);
+ g2 = wp[1] = (uint16) CLAMP(ip[1]);
+ b2 = wp[2] = (uint16) CLAMP(ip[2]);
+ n -= 3;
+ while (n > 0) {
+ n -= 3;
+ wp += 3;
+ ip += 3;
+ r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+ g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+ b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+ }
+ } else if (stride == 4) {
+ r2 = wp[0] = (uint16) CLAMP(ip[0]);
+ g2 = wp[1] = (uint16) CLAMP(ip[1]);
+ b2 = wp[2] = (uint16) CLAMP(ip[2]);
+ a2 = wp[3] = (uint16) CLAMP(ip[3]);
+ n -= 4;
+ while (n > 0) {
+ n -= 4;
+ wp += 4;
+ ip += 4;
+ r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+ g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+ b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+ a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+ }
+ } else {
+ ip += n - 1; /* point to last one */
+ wp += n - 1; /* point to last one */
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
+ wp[stride] -= wp[0];
+ wp[stride] &= mask;
+ wp--; ip--)
+ n -= stride;
+ }
+ REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
+ }
+ }
+}
+
+static void
+horizontalDifference16(unsigned short *ip, int n, int stride,
+ unsigned short *wp, uint16 *From14)
+{
+ register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
+
+/* assumption is unsigned pixel values */
+#undef CLAMP
+#define CLAMP(v) From14[(v) >> 2]
+
+ mask = CODE_MASK;
+ if (n >= stride) {
+ if (stride == 3) {
+ r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
+ b2 = wp[2] = CLAMP(ip[2]);
+ n -= 3;
+ while (n > 0) {
+ n -= 3;
+ wp += 3;
+ ip += 3;
+ r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+ g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+ b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+ }
+ } else if (stride == 4) {
+ r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
+ b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]);
+ n -= 4;
+ while (n > 0) {
+ n -= 4;
+ wp += 4;
+ ip += 4;
+ r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
+ g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
+ b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
+ a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
+ }
+ } else {
+ ip += n - 1; /* point to last one */
+ wp += n - 1; /* point to last one */
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride, wp[0] = CLAMP(ip[0]);
+ wp[stride] -= wp[0];
+ wp[stride] &= mask;
+ wp--; ip--)
+ n -= stride;
+ }
+ REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
+ }
+ }
+}
+
+
+static void
+horizontalDifference8(unsigned char *ip, int n, int stride,
+ unsigned short *wp, uint16 *From8)
+{
+ register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
+
+#undef CLAMP
+#define CLAMP(v) (From8[(v)])
+
+ mask = CODE_MASK;
+ if (n >= stride) {
+ if (stride == 3) {
+ r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
+ b2 = wp[2] = CLAMP(ip[2]);
+ n -= 3;
+ while (n > 0) {
+ n -= 3;
+ r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
+ g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
+ b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
+ wp += 3;
+ ip += 3;
+ }
+ } else if (stride == 4) {
+ r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
+ b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]);
+ n -= 4;
+ while (n > 0) {
+ n -= 4;
+ r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
+ g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
+ b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
+ a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
+ wp += 4;
+ ip += 4;
+ }
+ } else {
+ wp += n + stride - 1; /* point to last one */
+ ip += n + stride - 1; /* point to last one */
+ n -= stride;
+ while (n > 0) {
+ REPEAT(stride, wp[0] = CLAMP(ip[0]);
+ wp[stride] -= wp[0];
+ wp[stride] &= mask;
+ wp--; ip--)
+ n -= stride;
+ }
+ REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
+ }
+ }
+}
+
+/*
+ * Encode a chunk of pixels.
+ */
+static int
+PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ PixarLogState *sp = EncoderState(tif);
+ static const char module[] = "PixarLogEncode";
+ int i, n, llen;
+ unsigned short * up;
+
+ (void) s;
+
+ switch (sp->user_datafmt) {
+ case PIXARLOGDATAFMT_FLOAT:
+ n = cc / sizeof(float); /* XXX float == 32 bits */
+ break;
+ case PIXARLOGDATAFMT_16BIT:
+ case PIXARLOGDATAFMT_12BITPICIO:
+ case PIXARLOGDATAFMT_11BITLOG:
+ n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */
+ break;
+ case PIXARLOGDATAFMT_8BIT:
+ case PIXARLOGDATAFMT_8BITABGR:
+ n = cc;
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%d bit input not supported in PixarLog",
+ td->td_bitspersample);
+ return 0;
+ }
+
+ llen = sp->stride * td->td_imagewidth;
+
+ for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
+ switch (sp->user_datafmt) {
+ case PIXARLOGDATAFMT_FLOAT:
+ horizontalDifferenceF((float *)bp, llen,
+ sp->stride, up, sp->FromLT2);
+ bp += llen * sizeof(float);
+ break;
+ case PIXARLOGDATAFMT_16BIT:
+ horizontalDifference16((uint16 *)bp, llen,
+ sp->stride, up, sp->From14);
+ bp += llen * sizeof(uint16);
+ break;
+ case PIXARLOGDATAFMT_8BIT:
+ horizontalDifference8((unsigned char *)bp, llen,
+ sp->stride, up, sp->From8);
+ bp += llen * sizeof(unsigned char);
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%d bit input not supported in PixarLog",
+ td->td_bitspersample);
+ return 0;
+ }
+ }
+
+ sp->stream.next_in = (unsigned char *) sp->tbuf;
+ sp->stream.avail_in = n * sizeof(uint16);
+
+ do {
+ if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ if (sp->stream.avail_out == 0) {
+ tif->tif_rawcc = tif->tif_rawdatasize;
+ TIFFFlushData1(tif);
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ }
+ } while (sp->stream.avail_in > 0);
+ return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+
+static int
+PixarLogPostEncode(TIFF* tif)
+{
+ PixarLogState *sp = EncoderState(tif);
+ static const char module[] = "PixarLogPostEncode";
+ int state;
+
+ sp->stream.avail_in = 0;
+
+ do {
+ state = deflate(&sp->stream, Z_FINISH);
+ switch (state) {
+ case Z_STREAM_END:
+ case Z_OK:
+ if (sp->stream.avail_out != (uint32)tif->tif_rawdatasize) {
+ tif->tif_rawcc =
+ tif->tif_rawdatasize - sp->stream.avail_out;
+ TIFFFlushData1(tif);
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ }
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ } while (state != Z_STREAM_END);
+ return (1);
+}
+
+static void
+PixarLogClose(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ /* In a really sneaky maneuver, on close, we covertly modify both
+ * bitspersample and sampleformat in the directory to indicate
+ * 8-bit linear. This way, the decode "just works" even for
+ * readers that don't know about PixarLog, or how to set
+ * the PIXARLOGDATFMT pseudo-tag.
+ */
+ td->td_bitspersample = 8;
+ td->td_sampleformat = SAMPLEFORMAT_UINT;
+}
+
+static void
+PixarLogCleanup(TIFF* tif)
+{
+ PixarLogState* sp = (PixarLogState*) tif->tif_data;
+
+ assert(sp != 0);
+
+ (void)TIFFPredictorCleanup(tif);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ if (sp->FromLT2) _TIFFfree(sp->FromLT2);
+ if (sp->From14) _TIFFfree(sp->From14);
+ if (sp->From8) _TIFFfree(sp->From8);
+ if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
+ if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
+ if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
+ if (sp->state&PLSTATE_INIT) {
+ if (tif->tif_mode == O_RDONLY)
+ inflateEnd(&sp->stream);
+ else
+ deflateEnd(&sp->stream);
+ }
+ if (sp->tbuf)
+ _TIFFfree(sp->tbuf);
+ _TIFFfree(sp);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static int
+PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ PixarLogState *sp = (PixarLogState *)tif->tif_data;
+ int result;
+ static const char module[] = "PixarLogVSetField";
+
+ switch (tag) {
+ case TIFFTAG_PIXARLOGQUALITY:
+ sp->quality = va_arg(ap, int);
+ if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
+ if (deflateParams(&sp->stream,
+ sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ }
+ return (1);
+ case TIFFTAG_PIXARLOGDATAFMT:
+ sp->user_datafmt = va_arg(ap, int);
+ /* Tweak the TIFF header so that the rest of libtiff knows what
+ * size of data will be passed between app and library, and
+ * assume that the app knows what it is doing and is not
+ * confused by these header manipulations...
+ */
+ switch (sp->user_datafmt) {
+ case PIXARLOGDATAFMT_8BIT:
+ case PIXARLOGDATAFMT_8BITABGR:
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+ break;
+ case PIXARLOGDATAFMT_11BITLOG:
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+ break;
+ case PIXARLOGDATAFMT_12BITPICIO:
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
+ break;
+ case PIXARLOGDATAFMT_16BIT:
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
+ break;
+ case PIXARLOGDATAFMT_FLOAT:
+ TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
+ TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
+ break;
+ }
+ /*
+ * Must recalculate sizes should bits/sample change.
+ */
+ tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+ tif->tif_scanlinesize = TIFFScanlineSize(tif);
+ result = 1; /* NB: pseudo tag */
+ break;
+ default:
+ result = (*sp->vsetparent)(tif, tag, ap);
+ }
+ return (result);
+}
+
+static int
+PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ PixarLogState *sp = (PixarLogState *)tif->tif_data;
+
+ switch (tag) {
+ case TIFFTAG_PIXARLOGQUALITY:
+ *va_arg(ap, int*) = sp->quality;
+ break;
+ case TIFFTAG_PIXARLOGDATAFMT:
+ *va_arg(ap, int*) = sp->user_datafmt;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return (1);
+}
+
+static const TIFFFieldInfo pixarlogFieldInfo[] = {
+ {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""},
+ {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""}
+};
+
+int
+TIFFInitPixarLog(TIFF* tif, int scheme)
+{
+ static const char module[] = "TIFFInitPixarLog";
+
+ PixarLogState* sp;
+
+ assert(scheme == COMPRESSION_PIXARLOG);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, pixarlogFieldInfo,
+ TIFFArrayCount(pixarlogFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging PixarLog codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ sp = (PixarLogState*) tif->tif_data;
+ _TIFFmemset(sp, 0, sizeof (*sp));
+ sp->stream.data_type = Z_BINARY;
+ sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = PixarLogSetupDecode;
+ tif->tif_predecode = PixarLogPreDecode;
+ tif->tif_decoderow = PixarLogDecode;
+ tif->tif_decodestrip = PixarLogDecode;
+ tif->tif_decodetile = PixarLogDecode;
+ tif->tif_setupencode = PixarLogSetupEncode;
+ tif->tif_preencode = PixarLogPreEncode;
+ tif->tif_postencode = PixarLogPostEncode;
+ tif->tif_encoderow = PixarLogEncode;
+ tif->tif_encodestrip = PixarLogEncode;
+ tif->tif_encodetile = PixarLogEncode;
+ tif->tif_close = PixarLogClose;
+ tif->tif_cleanup = PixarLogCleanup;
+
+ /* Override SetField so we can handle our private pseudo-tag */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */
+
+ /* Default values for codec-specific fields */
+ sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
+ sp->state = 0;
+
+ /* we don't wish to use the predictor,
+ * the default is none, which predictor value 1
+ */
+ (void) TIFFPredictorInit(tif);
+
+ /*
+ * build the companding tables
+ */
+ PixarLogMakeTables(sp);
+
+ return (1);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "No space for PixarLog state block");
+ return (0);
+}
+#endif /* PIXARLOG_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_predict.c b/Source/LibTIFF/tif_predict.c
new file mode 100644
index 0000000..6f13f55
--- /dev/null
+++ b/Source/LibTIFF/tif_predict.c
@@ -0,0 +1,729 @@
+/* $Id: tif_predict.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Predictor Tag Support (used by multiple codecs).
+ */
+#include "tiffiop.h"
+#include "tif_predict.h"
+
+#define PredictorState(tif) ((TIFFPredictorState*) (tif)->tif_data)
+
+static void horAcc8(TIFF*, tidata_t, tsize_t);
+static void horAcc16(TIFF*, tidata_t, tsize_t);
+static void horAcc32(TIFF*, tidata_t, tsize_t);
+static void swabHorAcc16(TIFF*, tidata_t, tsize_t);
+static void swabHorAcc32(TIFF*, tidata_t, tsize_t);
+static void horDiff8(TIFF*, tidata_t, tsize_t);
+static void horDiff16(TIFF*, tidata_t, tsize_t);
+static void horDiff32(TIFF*, tidata_t, tsize_t);
+static void fpAcc(TIFF*, tidata_t, tsize_t);
+static void fpDiff(TIFF*, tidata_t, tsize_t);
+static int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
+static int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
+static int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
+static int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
+
+static int
+PredictorSetup(TIFF* tif)
+{
+ static const char module[] = "PredictorSetup";
+
+ TIFFPredictorState* sp = PredictorState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ switch (sp->predictor) /* no differencing */
+ {
+ case PREDICTOR_NONE:
+ return 1;
+ case PREDICTOR_HORIZONTAL:
+ if (td->td_bitspersample != 8
+ && td->td_bitspersample != 16
+ && td->td_bitspersample != 32) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
+ td->td_bitspersample);
+ return 0;
+ }
+ break;
+ case PREDICTOR_FLOATINGPOINT:
+ if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Floating point \"Predictor\" not supported with %d data format",
+ td->td_sampleformat);
+ return 0;
+ }
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "\"Predictor\" value %d not supported",
+ sp->predictor);
+ return 0;
+ }
+ sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
+ td->td_samplesperpixel : 1);
+ /*
+ * Calculate the scanline/tile-width size in bytes.
+ */
+ if (isTiled(tif))
+ sp->rowsize = TIFFTileRowSize(tif);
+ else
+ sp->rowsize = TIFFScanlineSize(tif);
+
+ return 1;
+}
+
+static int
+PredictorSetupDecode(TIFF* tif)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
+ return 0;
+
+ if (sp->predictor == 2) {
+ switch (td->td_bitspersample) {
+ case 8: sp->decodepfunc = horAcc8; break;
+ case 16: sp->decodepfunc = horAcc16; break;
+ case 32: sp->decodepfunc = horAcc32; break;
+ }
+ /*
+ * Override default decoding method with one that does the
+ * predictor stuff.
+ */
+ if( tif->tif_decoderow != PredictorDecodeRow )
+ {
+ sp->decoderow = tif->tif_decoderow;
+ tif->tif_decoderow = PredictorDecodeRow;
+ sp->decodestrip = tif->tif_decodestrip;
+ tif->tif_decodestrip = PredictorDecodeTile;
+ sp->decodetile = tif->tif_decodetile;
+ tif->tif_decodetile = PredictorDecodeTile;
+ }
+ /*
+ * If the data is horizontally differenced 16-bit data that
+ * requires byte-swapping, then it must be byte swapped before
+ * the accumulation step. We do this with a special-purpose
+ * routine and override the normal post decoding logic that
+ * the library setup when the directory was read.
+ */
+ if (tif->tif_flags & TIFF_SWAB) {
+ if (sp->decodepfunc == horAcc16) {
+ sp->decodepfunc = swabHorAcc16;
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ } else if (sp->decodepfunc == horAcc32) {
+ sp->decodepfunc = swabHorAcc32;
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ }
+ }
+ }
+
+ else if (sp->predictor == 3) {
+ sp->decodepfunc = fpAcc;
+ /*
+ * Override default decoding method with one that does the
+ * predictor stuff.
+ */
+ if( tif->tif_decoderow != PredictorDecodeRow )
+ {
+ sp->decoderow = tif->tif_decoderow;
+ tif->tif_decoderow = PredictorDecodeRow;
+ sp->decodestrip = tif->tif_decodestrip;
+ tif->tif_decodestrip = PredictorDecodeTile;
+ sp->decodetile = tif->tif_decodetile;
+ tif->tif_decodetile = PredictorDecodeTile;
+ }
+ /*
+ * The data should not be swapped outside of the floating
+ * point predictor, the accumulation routine should return
+ * byres in the native order.
+ */
+ if (tif->tif_flags & TIFF_SWAB) {
+ tif->tif_postdecode = _TIFFNoPostDecode;
+ }
+ /*
+ * Allocate buffer to keep the decoded bytes before
+ * rearranging in the ight order
+ */
+ }
+
+ return 1;
+}
+
+static int
+PredictorSetupEncode(TIFF* tif)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ TIFFDirectory* td = &tif->tif_dir;
+
+ if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
+ return 0;
+
+ if (sp->predictor == 2) {
+ switch (td->td_bitspersample) {
+ case 8: sp->encodepfunc = horDiff8; break;
+ case 16: sp->encodepfunc = horDiff16; break;
+ case 32: sp->encodepfunc = horDiff32; break;
+ }
+ /*
+ * Override default encoding method with one that does the
+ * predictor stuff.
+ */
+ if( tif->tif_encoderow != PredictorEncodeRow )
+ {
+ sp->encoderow = tif->tif_encoderow;
+ tif->tif_encoderow = PredictorEncodeRow;
+ sp->encodestrip = tif->tif_encodestrip;
+ tif->tif_encodestrip = PredictorEncodeTile;
+ sp->encodetile = tif->tif_encodetile;
+ tif->tif_encodetile = PredictorEncodeTile;
+ }
+ }
+
+ else if (sp->predictor == 3) {
+ sp->encodepfunc = fpDiff;
+ /*
+ * Override default encoding method with one that does the
+ * predictor stuff.
+ */
+ if( tif->tif_encoderow != PredictorEncodeRow )
+ {
+ sp->encoderow = tif->tif_encoderow;
+ tif->tif_encoderow = PredictorEncodeRow;
+ sp->encodestrip = tif->tif_encodestrip;
+ tif->tif_encodestrip = PredictorEncodeTile;
+ sp->encodetile = tif->tif_encodetile;
+ tif->tif_encodetile = PredictorEncodeTile;
+ }
+ }
+
+ return 1;
+}
+
+#define REPEAT4(n, op) \
+ switch (n) { \
+ default: { int i; for (i = n-4; i > 0; i--) { op; } } \
+ case 4: op; \
+ case 3: op; \
+ case 2: op; \
+ case 1: op; \
+ case 0: ; \
+ }
+
+static void
+horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+
+ char* cp = (char*) cp0;
+ if (cc > stride) {
+ cc -= stride;
+ /*
+ * Pipeline the most common cases.
+ */
+ if (stride == 3) {
+ unsigned int cr = cp[0];
+ unsigned int cg = cp[1];
+ unsigned int cb = cp[2];
+ do {
+ cc -= 3, cp += 3;
+ cp[0] = (char) (cr += cp[0]);
+ cp[1] = (char) (cg += cp[1]);
+ cp[2] = (char) (cb += cp[2]);
+ } while ((int32) cc > 0);
+ } else if (stride == 4) {
+ unsigned int cr = cp[0];
+ unsigned int cg = cp[1];
+ unsigned int cb = cp[2];
+ unsigned int ca = cp[3];
+ do {
+ cc -= 4, cp += 4;
+ cp[0] = (char) (cr += cp[0]);
+ cp[1] = (char) (cg += cp[1]);
+ cp[2] = (char) (cb += cp[2]);
+ cp[3] = (char) (ca += cp[3]);
+ } while ((int32) cc > 0);
+ } else {
+ do {
+ REPEAT4(stride, cp[stride] =
+ (char) (cp[stride] + *cp); cp++)
+ cc -= stride;
+ } while ((int32) cc > 0);
+ }
+ }
+}
+
+static void
+swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint16* wp = (uint16*) cp0;
+ tsize_t wc = cc / 2;
+
+ if (wc > stride) {
+ TIFFSwabArrayOfShort(wp, wc);
+ wc -= stride;
+ do {
+ REPEAT4(stride, wp[stride] += wp[0]; wp++)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+static void
+horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint16* wp = (uint16*) cp0;
+ tsize_t wc = cc / 2;
+
+ if (wc > stride) {
+ wc -= stride;
+ do {
+ REPEAT4(stride, wp[stride] += wp[0]; wp++)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+static void
+swabHorAcc32(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint32* wp = (uint32*) cp0;
+ tsize_t wc = cc / 4;
+
+ if (wc > stride) {
+ TIFFSwabArrayOfLong(wp, wc);
+ wc -= stride;
+ do {
+ REPEAT4(stride, wp[stride] += wp[0]; wp++)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+static void
+horAcc32(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint32* wp = (uint32*) cp0;
+ tsize_t wc = cc / 4;
+
+ if (wc > stride) {
+ wc -= stride;
+ do {
+ REPEAT4(stride, wp[stride] += wp[0]; wp++)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+/*
+ * Floating point predictor accumulation routine.
+ */
+static void
+fpAcc(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint32 bps = tif->tif_dir.td_bitspersample / 8;
+ tsize_t wc = cc / bps;
+ tsize_t count = cc;
+ uint8 *cp = (uint8 *) cp0;
+ uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
+
+ if (!tmp)
+ return;
+
+ while (count > stride) {
+ REPEAT4(stride, cp[stride] += cp[0]; cp++)
+ count -= stride;
+ }
+
+ _TIFFmemcpy(tmp, cp0, cc);
+ cp = (uint8 *) cp0;
+ for (count = 0; count < wc; count++) {
+ uint32 byte;
+ for (byte = 0; byte < bps; byte++) {
+#if WORDS_BIGENDIAN
+ cp[bps * count + byte] = tmp[byte * wc + count];
+#else
+ cp[bps * count + byte] =
+ tmp[(bps - byte - 1) * wc + count];
+#endif
+ }
+ }
+ _TIFFfree(tmp);
+}
+
+/*
+ * Decode a scanline and apply the predictor routine.
+ */
+static int
+PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+ TIFFPredictorState *sp = PredictorState(tif);
+
+ assert(sp != NULL);
+ assert(sp->decoderow != NULL);
+ assert(sp->decodepfunc != NULL);
+
+ if ((*sp->decoderow)(tif, op0, occ0, s)) {
+ (*sp->decodepfunc)(tif, op0, occ0);
+ return 1;
+ } else
+ return 0;
+}
+
+/*
+ * Decode a tile/strip and apply the predictor routine.
+ * Note that horizontal differencing must be done on a
+ * row-by-row basis. The width of a "row" has already
+ * been calculated at pre-decode time according to the
+ * strip/tile dimensions.
+ */
+static int
+PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
+{
+ TIFFPredictorState *sp = PredictorState(tif);
+
+ assert(sp != NULL);
+ assert(sp->decodetile != NULL);
+
+ if ((*sp->decodetile)(tif, op0, occ0, s)) {
+ tsize_t rowsize = sp->rowsize;
+ assert(rowsize > 0);
+ assert(sp->decodepfunc != NULL);
+ while ((long)occ0 > 0) {
+ (*sp->decodepfunc)(tif, op0, (tsize_t) rowsize);
+ occ0 -= rowsize;
+ op0 += rowsize;
+ }
+ return 1;
+ } else
+ return 0;
+}
+
+static void
+horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ tsize_t stride = sp->stride;
+ char* cp = (char*) cp0;
+
+ if (cc > stride) {
+ cc -= stride;
+ /*
+ * Pipeline the most common cases.
+ */
+ if (stride == 3) {
+ int r1, g1, b1;
+ int r2 = cp[0];
+ int g2 = cp[1];
+ int b2 = cp[2];
+ do {
+ r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
+ g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
+ b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
+ cp += 3;
+ } while ((int32)(cc -= 3) > 0);
+ } else if (stride == 4) {
+ int r1, g1, b1, a1;
+ int r2 = cp[0];
+ int g2 = cp[1];
+ int b2 = cp[2];
+ int a2 = cp[3];
+ do {
+ r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
+ g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
+ b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
+ a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
+ cp += 4;
+ } while ((int32)(cc -= 4) > 0);
+ } else {
+ cp += cc - 1;
+ do {
+ REPEAT4(stride, cp[stride] -= cp[0]; cp--)
+ } while ((int32)(cc -= stride) > 0);
+ }
+ }
+}
+
+static void
+horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ tsize_t stride = sp->stride;
+ int16 *wp = (int16*) cp0;
+ tsize_t wc = cc/2;
+
+ if (wc > stride) {
+ wc -= stride;
+ wp += wc - 1;
+ do {
+ REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+static void
+horDiff32(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+ tsize_t stride = sp->stride;
+ int32 *wp = (int32*) cp0;
+ tsize_t wc = cc/4;
+
+ if (wc > stride) {
+ wc -= stride;
+ wp += wc - 1;
+ do {
+ REPEAT4(stride, wp[stride] -= wp[0]; wp--)
+ wc -= stride;
+ } while ((int32) wc > 0);
+ }
+}
+
+/*
+ * Floating point predictor differencing routine.
+ */
+static void
+fpDiff(TIFF* tif, tidata_t cp0, tsize_t cc)
+{
+ tsize_t stride = PredictorState(tif)->stride;
+ uint32 bps = tif->tif_dir.td_bitspersample / 8;
+ tsize_t wc = cc / bps;
+ tsize_t count;
+ uint8 *cp = (uint8 *) cp0;
+ uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
+
+ if (!tmp)
+ return;
+
+ _TIFFmemcpy(tmp, cp0, cc);
+ for (count = 0; count < wc; count++) {
+ uint32 byte;
+ for (byte = 0; byte < bps; byte++) {
+#if WORDS_BIGENDIAN
+ cp[byte * wc + count] = tmp[bps * count + byte];
+#else
+ cp[(bps - byte - 1) * wc + count] =
+ tmp[bps * count + byte];
+#endif
+ }
+ }
+ _TIFFfree(tmp);
+
+ cp = (uint8 *) cp0;
+ cp += cc - stride - 1;
+ for (count = cc; count > stride; count -= stride)
+ REPEAT4(stride, cp[stride] -= cp[0]; cp--)
+}
+
+static int
+PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ TIFFPredictorState *sp = PredictorState(tif);
+
+ assert(sp != NULL);
+ assert(sp->encodepfunc != NULL);
+ assert(sp->encoderow != NULL);
+
+ /* XXX horizontal differencing alters user's data XXX */
+ (*sp->encodepfunc)(tif, bp, cc);
+ return (*sp->encoderow)(tif, bp, cc, s);
+}
+
+static int
+PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
+{
+ static const char module[] = "PredictorEncodeTile";
+ TIFFPredictorState *sp = PredictorState(tif);
+ uint8 *working_copy;
+ tsize_t cc = cc0, rowsize;
+ unsigned char* bp;
+ int result_code;
+
+ assert(sp != NULL);
+ assert(sp->encodepfunc != NULL);
+ assert(sp->encodetile != NULL);
+
+ /*
+ * Do predictor manipulation in a working buffer to avoid altering
+ * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965
+ */
+ working_copy = (uint8*) _TIFFmalloc(cc0);
+ if( working_copy == NULL )
+ {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Out of memory allocating %d byte temp buffer.",
+ cc0 );
+ return 0;
+ }
+ memcpy( working_copy, bp0, cc0 );
+ bp = working_copy;
+
+ rowsize = sp->rowsize;
+ assert(rowsize > 0);
+ assert((cc0%rowsize)==0);
+ while (cc > 0) {
+ (*sp->encodepfunc)(tif, bp, rowsize);
+ cc -= rowsize;
+ bp += rowsize;
+ }
+ result_code = (*sp->encodetile)(tif, working_copy, cc0, s);
+
+ _TIFFfree( working_copy );
+
+ return result_code;
+}
+
+#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */
+
+static const TIFFFieldInfo predictFieldInfo[] = {
+ { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, FIELD_PREDICTOR,
+ FALSE, FALSE, "Predictor" },
+};
+
+static int
+PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ TIFFPredictorState *sp = PredictorState(tif);
+
+ assert(sp != NULL);
+ assert(sp->vsetparent != NULL);
+
+ switch (tag) {
+ case TIFFTAG_PREDICTOR:
+ sp->predictor = (uint16) va_arg(ap, int);
+ TIFFSetFieldBit(tif, FIELD_PREDICTOR);
+ break;
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+ tif->tif_flags |= TIFF_DIRTYDIRECT;
+ return 1;
+}
+
+static int
+PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ TIFFPredictorState *sp = PredictorState(tif);
+
+ assert(sp != NULL);
+ assert(sp->vgetparent != NULL);
+
+ switch (tag) {
+ case TIFFTAG_PREDICTOR:
+ *va_arg(ap, uint16*) = sp->predictor;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return 1;
+}
+
+static void
+PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+
+ (void) flags;
+ if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
+ fprintf(fd, " Predictor: ");
+ switch (sp->predictor) {
+ case 1: fprintf(fd, "none "); break;
+ case 2: fprintf(fd, "horizontal differencing "); break;
+ case 3: fprintf(fd, "floating point predictor "); break;
+ }
+ fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
+ }
+ if (sp->printdir)
+ (*sp->printdir)(tif, fd, flags);
+}
+
+int
+TIFFPredictorInit(TIFF* tif)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+
+ assert(sp != 0);
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, predictFieldInfo,
+ TIFFArrayCount(predictFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit",
+ "Merging Predictor codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield =
+ PredictorVGetField;/* hook for predictor tag */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield =
+ PredictorVSetField;/* hook for predictor tag */
+ sp->printdir = tif->tif_tagmethods.printdir;
+ tif->tif_tagmethods.printdir =
+ PredictorPrintDir; /* hook for predictor tag */
+
+ sp->setupdecode = tif->tif_setupdecode;
+ tif->tif_setupdecode = PredictorSetupDecode;
+ sp->setupencode = tif->tif_setupencode;
+ tif->tif_setupencode = PredictorSetupEncode;
+
+ sp->predictor = 1; /* default value */
+ sp->encodepfunc = NULL; /* no predictor routine */
+ sp->decodepfunc = NULL; /* no predictor routine */
+ return 1;
+}
+
+int
+TIFFPredictorCleanup(TIFF* tif)
+{
+ TIFFPredictorState* sp = PredictorState(tif);
+
+ assert(sp != 0);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+ tif->tif_tagmethods.printdir = sp->printdir;
+ tif->tif_setupdecode = sp->setupdecode;
+ tif->tif_setupencode = sp->setupencode;
+
+ return 1;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_predict.h b/Source/LibTIFF/tif_predict.h
new file mode 100644
index 0000000..a4cbf82
--- /dev/null
+++ b/Source/LibTIFF/tif_predict.h
@@ -0,0 +1,70 @@
+/* $Id: tif_predict.h,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1995-1997 Sam Leffler
+ * Copyright (c) 1995-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFPREDICT_
+#define _TIFFPREDICT_
+/*
+ * ``Library-private'' Support for the Predictor Tag
+ */
+
+/*
+ * Codecs that want to support the Predictor tag must place
+ * this structure first in their private state block so that
+ * the predictor code can cast tif_data to find its state.
+ */
+typedef struct {
+ int predictor; /* predictor tag value */
+ int stride; /* sample stride over data */
+ tsize_t rowsize; /* tile/strip row size */
+
+ TIFFCodeMethod encoderow; /* parent codec encode/decode row */
+ TIFFCodeMethod encodestrip; /* parent codec encode/decode strip */
+ TIFFCodeMethod encodetile; /* parent codec encode/decode tile */
+ TIFFPostMethod encodepfunc; /* horizontal differencer */
+
+ TIFFCodeMethod decoderow; /* parent codec encode/decode row */
+ TIFFCodeMethod decodestrip; /* parent codec encode/decode strip */
+ TIFFCodeMethod decodetile; /* parent codec encode/decode tile */
+ TIFFPostMethod decodepfunc; /* horizontal accumulator */
+
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+ TIFFPrintMethod printdir; /* super-class method */
+ TIFFBoolMethod setupdecode; /* super-class method */
+ TIFFBoolMethod setupencode; /* super-class method */
+} TIFFPredictorState;
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern int TIFFPredictorInit(TIFF*);
+extern int TIFFPredictorCleanup(TIFF*);
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFPREDICT_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_print.c b/Source/LibTIFF/tif_print.c
new file mode 100644
index 0000000..2bc0bb7
--- /dev/null
+++ b/Source/LibTIFF/tif_print.c
@@ -0,0 +1,639 @@
+/* $Id: tif_print.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Directory Printing Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+#include <ctype.h>
+
+static const char *photoNames[] = {
+ "min-is-white", /* PHOTOMETRIC_MINISWHITE */
+ "min-is-black", /* PHOTOMETRIC_MINISBLACK */
+ "RGB color", /* PHOTOMETRIC_RGB */
+ "palette color (RGB from colormap)", /* PHOTOMETRIC_PALETTE */
+ "transparency mask", /* PHOTOMETRIC_MASK */
+ "separated", /* PHOTOMETRIC_SEPARATED */
+ "YCbCr", /* PHOTOMETRIC_YCBCR */
+ "7 (0x7)",
+ "CIE L*a*b*", /* PHOTOMETRIC_CIELAB */
+};
+#define NPHOTONAMES (sizeof (photoNames) / sizeof (photoNames[0]))
+
+static const char *orientNames[] = {
+ "0 (0x0)",
+ "row 0 top, col 0 lhs", /* ORIENTATION_TOPLEFT */
+ "row 0 top, col 0 rhs", /* ORIENTATION_TOPRIGHT */
+ "row 0 bottom, col 0 rhs", /* ORIENTATION_BOTRIGHT */
+ "row 0 bottom, col 0 lhs", /* ORIENTATION_BOTLEFT */
+ "row 0 lhs, col 0 top", /* ORIENTATION_LEFTTOP */
+ "row 0 rhs, col 0 top", /* ORIENTATION_RIGHTTOP */
+ "row 0 rhs, col 0 bottom", /* ORIENTATION_RIGHTBOT */
+ "row 0 lhs, col 0 bottom", /* ORIENTATION_LEFTBOT */
+};
+#define NORIENTNAMES (sizeof (orientNames) / sizeof (orientNames[0]))
+
+static void
+_TIFFPrintField(FILE* fd, const TIFFFieldInfo *fip,
+ uint32 value_count, void *raw_data)
+{
+ uint32 j;
+
+ fprintf(fd, " %s: ", fip->field_name);
+
+ for(j = 0; j < value_count; j++) {
+ if(fip->field_type == TIFF_BYTE)
+ fprintf(fd, "%u", ((uint8 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_UNDEFINED)
+ fprintf(fd, "0x%x",
+ (unsigned int) ((unsigned char *) raw_data)[j]);
+ else if(fip->field_type == TIFF_SBYTE)
+ fprintf(fd, "%d", ((int8 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_SHORT)
+ fprintf(fd, "%u", ((uint16 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_SSHORT)
+ fprintf(fd, "%d", ((int16 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_LONG)
+ fprintf(fd, "%lu",
+ (unsigned long)((uint32 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_SLONG)
+ fprintf(fd, "%ld", (long)((int32 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_RATIONAL
+ || fip->field_type == TIFF_SRATIONAL
+ || fip->field_type == TIFF_FLOAT)
+ fprintf(fd, "%f", ((float *) raw_data)[j]);
+ else if(fip->field_type == TIFF_IFD)
+ fprintf(fd, "0x%ulx", ((uint32 *) raw_data)[j]);
+ else if(fip->field_type == TIFF_ASCII) {
+ fprintf(fd, "%s", (char *) raw_data);
+ break;
+ }
+ else if(fip->field_type == TIFF_DOUBLE)
+ fprintf(fd, "%f", ((double *) raw_data)[j]);
+ else if(fip->field_type == TIFF_FLOAT)
+ fprintf(fd, "%f", ((float *)raw_data)[j]);
+ else {
+ fprintf(fd, "<unsupported data type in TIFFPrint>");
+ break;
+ }
+
+ if(j < value_count - 1)
+ fprintf(fd, ",");
+ }
+
+ fprintf(fd, "\n");
+}
+
+static int
+_TIFFPrettyPrintField(TIFF* tif, FILE* fd, ttag_t tag,
+ uint32 value_count, void *raw_data)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ switch (tag)
+ {
+ case TIFFTAG_INKSET:
+ fprintf(fd, " Ink Set: ");
+ switch (*((uint16*)raw_data)) {
+ case INKSET_CMYK:
+ fprintf(fd, "CMYK\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ *((uint16*)raw_data),
+ *((uint16*)raw_data));
+ break;
+ }
+ return 1;
+ case TIFFTAG_DOTRANGE:
+ fprintf(fd, " Dot Range: %u-%u\n",
+ ((uint16*)raw_data)[0], ((uint16*)raw_data)[1]);
+ return 1;
+ case TIFFTAG_WHITEPOINT:
+ fprintf(fd, " White Point: %g-%g\n",
+ ((float *)raw_data)[0], ((float *)raw_data)[1]); return 1;
+ case TIFFTAG_REFERENCEBLACKWHITE:
+ {
+ uint16 i;
+
+ fprintf(fd, " Reference Black/White:\n");
+ for (i = 0; i < td->td_samplesperpixel; i++)
+ fprintf(fd, " %2d: %5g %5g\n", i,
+ ((float *)raw_data)[2*i+0],
+ ((float *)raw_data)[2*i+1]);
+ return 1;
+ }
+ case TIFFTAG_XMLPACKET:
+ {
+ uint32 i;
+
+ fprintf(fd, " XMLPacket (XMP Metadata):\n" );
+ for(i = 0; i < value_count; i++)
+ fputc(((char *)raw_data)[i], fd);
+ fprintf( fd, "\n" );
+ return 1;
+ }
+ case TIFFTAG_RICHTIFFIPTC:
+ /*
+ * XXX: for some weird reason RichTIFFIPTC tag
+ * defined as array of LONG values.
+ */
+ fprintf(fd,
+ " RichTIFFIPTC Data: <present>, %lu bytes\n",
+ (unsigned long) value_count * 4);
+ return 1;
+ case TIFFTAG_PHOTOSHOP:
+ fprintf(fd, " Photoshop Data: <present>, %lu bytes\n",
+ (unsigned long) value_count);
+ return 1;
+ case TIFFTAG_ICCPROFILE:
+ fprintf(fd, " ICC Profile: <present>, %lu bytes\n",
+ (unsigned long) value_count);
+ return 1;
+ case TIFFTAG_STONITS:
+ fprintf(fd,
+ " Sample to Nits conversion factor: %.4e\n",
+ *((double*)raw_data));
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Print the contents of the current directory
+ * to the specified stdio file stream.
+ */
+void
+TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ char *sep;
+ uint16 i;
+ long l, n;
+
+ fprintf(fd, "TIFF Directory at offset 0x%lx (%lu)\n",
+ (unsigned long)tif->tif_diroff, (unsigned long)tif->tif_diroff);
+ if (TIFFFieldSet(tif,FIELD_SUBFILETYPE)) {
+ fprintf(fd, " Subfile Type:");
+ sep = " ";
+ if (td->td_subfiletype & FILETYPE_REDUCEDIMAGE) {
+ fprintf(fd, "%sreduced-resolution image", sep);
+ sep = "/";
+ }
+ if (td->td_subfiletype & FILETYPE_PAGE) {
+ fprintf(fd, "%smulti-page document", sep);
+ sep = "/";
+ }
+ if (td->td_subfiletype & FILETYPE_MASK)
+ fprintf(fd, "%stransparency mask", sep);
+ fprintf(fd, " (%lu = 0x%lx)\n",
+ (long) td->td_subfiletype, (long) td->td_subfiletype);
+ }
+ if (TIFFFieldSet(tif,FIELD_IMAGEDIMENSIONS)) {
+ fprintf(fd, " Image Width: %lu Image Length: %lu",
+ (unsigned long) td->td_imagewidth, (unsigned long) td->td_imagelength);
+ if (TIFFFieldSet(tif,FIELD_IMAGEDEPTH))
+ fprintf(fd, " Image Depth: %lu",
+ (unsigned long) td->td_imagedepth);
+ fprintf(fd, "\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_TILEDIMENSIONS)) {
+ fprintf(fd, " Tile Width: %lu Tile Length: %lu",
+ (unsigned long) td->td_tilewidth, (unsigned long) td->td_tilelength);
+ if (TIFFFieldSet(tif,FIELD_TILEDEPTH))
+ fprintf(fd, " Tile Depth: %lu",
+ (unsigned long) td->td_tiledepth);
+ fprintf(fd, "\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_RESOLUTION)) {
+ fprintf(fd, " Resolution: %g, %g",
+ td->td_xresolution, td->td_yresolution);
+ if (TIFFFieldSet(tif,FIELD_RESOLUTIONUNIT)) {
+ switch (td->td_resolutionunit) {
+ case RESUNIT_NONE:
+ fprintf(fd, " (unitless)");
+ break;
+ case RESUNIT_INCH:
+ fprintf(fd, " pixels/inch");
+ break;
+ case RESUNIT_CENTIMETER:
+ fprintf(fd, " pixels/cm");
+ break;
+ default:
+ fprintf(fd, " (unit %u = 0x%x)",
+ td->td_resolutionunit,
+ td->td_resolutionunit);
+ break;
+ }
+ }
+ fprintf(fd, "\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_POSITION))
+ fprintf(fd, " Position: %g, %g\n",
+ td->td_xposition, td->td_yposition);
+ if (TIFFFieldSet(tif,FIELD_BITSPERSAMPLE))
+ fprintf(fd, " Bits/Sample: %u\n", td->td_bitspersample);
+ if (TIFFFieldSet(tif,FIELD_SAMPLEFORMAT)) {
+ fprintf(fd, " Sample Format: ");
+ switch (td->td_sampleformat) {
+ case SAMPLEFORMAT_VOID:
+ fprintf(fd, "void\n");
+ break;
+ case SAMPLEFORMAT_INT:
+ fprintf(fd, "signed integer\n");
+ break;
+ case SAMPLEFORMAT_UINT:
+ fprintf(fd, "unsigned integer\n");
+ break;
+ case SAMPLEFORMAT_IEEEFP:
+ fprintf(fd, "IEEE floating point\n");
+ break;
+ case SAMPLEFORMAT_COMPLEXINT:
+ fprintf(fd, "complex signed integer\n");
+ break;
+ case SAMPLEFORMAT_COMPLEXIEEEFP:
+ fprintf(fd, "complex IEEE floating point\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_sampleformat, td->td_sampleformat);
+ break;
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_COMPRESSION)) {
+ const TIFFCodec* c = TIFFFindCODEC(td->td_compression);
+ fprintf(fd, " Compression Scheme: ");
+ if (c)
+ fprintf(fd, "%s\n", c->name);
+ else
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_compression, td->td_compression);
+ }
+ if (TIFFFieldSet(tif,FIELD_PHOTOMETRIC)) {
+ fprintf(fd, " Photometric Interpretation: ");
+ if (td->td_photometric < NPHOTONAMES)
+ fprintf(fd, "%s\n", photoNames[td->td_photometric]);
+ else {
+ switch (td->td_photometric) {
+ case PHOTOMETRIC_LOGL:
+ fprintf(fd, "CIE Log2(L)\n");
+ break;
+ case PHOTOMETRIC_LOGLUV:
+ fprintf(fd, "CIE Log2(L) (u',v')\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_photometric, td->td_photometric);
+ break;
+ }
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_EXTRASAMPLES) && td->td_extrasamples) {
+ fprintf(fd, " Extra Samples: %u<", td->td_extrasamples);
+ sep = "";
+ for (i = 0; i < td->td_extrasamples; i++) {
+ switch (td->td_sampleinfo[i]) {
+ case EXTRASAMPLE_UNSPECIFIED:
+ fprintf(fd, "%sunspecified", sep);
+ break;
+ case EXTRASAMPLE_ASSOCALPHA:
+ fprintf(fd, "%sassoc-alpha", sep);
+ break;
+ case EXTRASAMPLE_UNASSALPHA:
+ fprintf(fd, "%sunassoc-alpha", sep);
+ break;
+ default:
+ fprintf(fd, "%s%u (0x%x)", sep,
+ td->td_sampleinfo[i], td->td_sampleinfo[i]);
+ break;
+ }
+ sep = ", ";
+ }
+ fprintf(fd, ">\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_INKNAMES)) {
+ char* cp;
+ fprintf(fd, " Ink Names: ");
+ i = td->td_samplesperpixel;
+ sep = "";
+ for (cp = td->td_inknames; i > 0; cp = strchr(cp,'\0')+1, i--) {
+ fputs(sep, fd);
+ _TIFFprintAscii(fd, cp);
+ sep = ", ";
+ }
+ fputs("\n", fd);
+ }
+ if (TIFFFieldSet(tif,FIELD_THRESHHOLDING)) {
+ fprintf(fd, " Thresholding: ");
+ switch (td->td_threshholding) {
+ case THRESHHOLD_BILEVEL:
+ fprintf(fd, "bilevel art scan\n");
+ break;
+ case THRESHHOLD_HALFTONE:
+ fprintf(fd, "halftone or dithered scan\n");
+ break;
+ case THRESHHOLD_ERRORDIFFUSE:
+ fprintf(fd, "error diffused\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_threshholding, td->td_threshholding);
+ break;
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_FILLORDER)) {
+ fprintf(fd, " FillOrder: ");
+ switch (td->td_fillorder) {
+ case FILLORDER_MSB2LSB:
+ fprintf(fd, "msb-to-lsb\n");
+ break;
+ case FILLORDER_LSB2MSB:
+ fprintf(fd, "lsb-to-msb\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_fillorder, td->td_fillorder);
+ break;
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_YCBCRSUBSAMPLING))
+ {
+ /*
+ * For hacky reasons (see tif_jpeg.c - JPEGFixupTestSubsampling),
+ * we need to fetch this rather than trust what is in our
+ * structures.
+ */
+ uint16 subsampling[2];
+
+ TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING,
+ subsampling + 0, subsampling + 1 );
+ fprintf(fd, " YCbCr Subsampling: %u, %u\n",
+ subsampling[0], subsampling[1] );
+ }
+ if (TIFFFieldSet(tif,FIELD_YCBCRPOSITIONING)) {
+ fprintf(fd, " YCbCr Positioning: ");
+ switch (td->td_ycbcrpositioning) {
+ case YCBCRPOSITION_CENTERED:
+ fprintf(fd, "centered\n");
+ break;
+ case YCBCRPOSITION_COSITED:
+ fprintf(fd, "cosited\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_ycbcrpositioning, td->td_ycbcrpositioning);
+ break;
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_HALFTONEHINTS))
+ fprintf(fd, " Halftone Hints: light %u dark %u\n",
+ td->td_halftonehints[0], td->td_halftonehints[1]);
+ if (TIFFFieldSet(tif,FIELD_ORIENTATION)) {
+ fprintf(fd, " Orientation: ");
+ if (td->td_orientation < NORIENTNAMES)
+ fprintf(fd, "%s\n", orientNames[td->td_orientation]);
+ else
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_orientation, td->td_orientation);
+ }
+ if (TIFFFieldSet(tif,FIELD_SAMPLESPERPIXEL))
+ fprintf(fd, " Samples/Pixel: %u\n", td->td_samplesperpixel);
+ if (TIFFFieldSet(tif,FIELD_ROWSPERSTRIP)) {
+ fprintf(fd, " Rows/Strip: ");
+ if (td->td_rowsperstrip == (uint32) -1)
+ fprintf(fd, "(infinite)\n");
+ else
+ fprintf(fd, "%lu\n", (unsigned long) td->td_rowsperstrip);
+ }
+ if (TIFFFieldSet(tif,FIELD_MINSAMPLEVALUE))
+ fprintf(fd, " Min Sample Value: %u\n", td->td_minsamplevalue);
+ if (TIFFFieldSet(tif,FIELD_MAXSAMPLEVALUE))
+ fprintf(fd, " Max Sample Value: %u\n", td->td_maxsamplevalue);
+ if (TIFFFieldSet(tif,FIELD_SMINSAMPLEVALUE))
+ fprintf(fd, " SMin Sample Value: %g\n",
+ td->td_sminsamplevalue);
+ if (TIFFFieldSet(tif,FIELD_SMAXSAMPLEVALUE))
+ fprintf(fd, " SMax Sample Value: %g\n",
+ td->td_smaxsamplevalue);
+ if (TIFFFieldSet(tif,FIELD_PLANARCONFIG)) {
+ fprintf(fd, " Planar Configuration: ");
+ switch (td->td_planarconfig) {
+ case PLANARCONFIG_CONTIG:
+ fprintf(fd, "single image plane\n");
+ break;
+ case PLANARCONFIG_SEPARATE:
+ fprintf(fd, "separate image planes\n");
+ break;
+ default:
+ fprintf(fd, "%u (0x%x)\n",
+ td->td_planarconfig, td->td_planarconfig);
+ break;
+ }
+ }
+ if (TIFFFieldSet(tif,FIELD_PAGENUMBER))
+ fprintf(fd, " Page Number: %u-%u\n",
+ td->td_pagenumber[0], td->td_pagenumber[1]);
+ if (TIFFFieldSet(tif,FIELD_COLORMAP)) {
+ fprintf(fd, " Color Map: ");
+ if (flags & TIFFPRINT_COLORMAP) {
+ fprintf(fd, "\n");
+ n = 1L<<td->td_bitspersample;
+ for (l = 0; l < n; l++)
+ fprintf(fd, " %5lu: %5u %5u %5u\n",
+ l,
+ td->td_colormap[0][l],
+ td->td_colormap[1][l],
+ td->td_colormap[2][l]);
+ } else
+ fprintf(fd, "(present)\n");
+ }
+ if (TIFFFieldSet(tif,FIELD_TRANSFERFUNCTION)) {
+ fprintf(fd, " Transfer Function: ");
+ if (flags & TIFFPRINT_CURVES) {
+ fprintf(fd, "\n");
+ n = 1L<<td->td_bitspersample;
+ for (l = 0; l < n; l++) {
+ fprintf(fd, " %2lu: %5u",
+ l, td->td_transferfunction[0][l]);
+ for (i = 1; i < td->td_samplesperpixel; i++)
+ fprintf(fd, " %5u",
+ td->td_transferfunction[i][l]);
+ fputc('\n', fd);
+ }
+ } else
+ fprintf(fd, "(present)\n");
+ }
+ if (TIFFFieldSet(tif, FIELD_SUBIFD) && (td->td_subifd)) {
+ fprintf(fd, " SubIFD Offsets:");
+ for (i = 0; i < td->td_nsubifd; i++)
+ fprintf(fd, " %5lu", (long) td->td_subifd[i]);
+ fputc('\n', fd);
+ }
+
+ /*
+ ** Custom tag support.
+ */
+ {
+ int i;
+ short count;
+
+ count = (short) TIFFGetTagListCount(tif);
+ for(i = 0; i < count; i++) {
+ ttag_t tag = TIFFGetTagListEntry(tif, i);
+ const TIFFFieldInfo *fip;
+ uint32 value_count;
+ int mem_alloc = 0;
+ void *raw_data;
+
+ fip = TIFFFieldWithTag(tif, tag);
+ if(fip == NULL)
+ continue;
+
+ if(fip->field_passcount) {
+ if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1)
+ continue;
+ } else {
+ if (fip->field_readcount == TIFF_VARIABLE
+ || fip->field_readcount == TIFF_VARIABLE2)
+ value_count = 1;
+ else if (fip->field_readcount == TIFF_SPP)
+ value_count = td->td_samplesperpixel;
+ else
+ value_count = fip->field_readcount;
+ if ((fip->field_type == TIFF_ASCII
+ || fip->field_readcount == TIFF_VARIABLE
+ || fip->field_readcount == TIFF_VARIABLE2
+ || fip->field_readcount == TIFF_SPP
+ || value_count > 1)
+ && fip->field_tag != TIFFTAG_PAGENUMBER
+ && fip->field_tag != TIFFTAG_HALFTONEHINTS
+ && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
+ && fip->field_tag != TIFFTAG_DOTRANGE) {
+ if(TIFFGetField(tif, tag, &raw_data) != 1)
+ continue;
+ } else if (fip->field_tag != TIFFTAG_PAGENUMBER
+ && fip->field_tag != TIFFTAG_HALFTONEHINTS
+ && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
+ && fip->field_tag != TIFFTAG_DOTRANGE) {
+ raw_data = _TIFFmalloc(
+ _TIFFDataSize(fip->field_type)
+ * value_count);
+ mem_alloc = 1;
+ if(TIFFGetField(tif, tag, raw_data) != 1) {
+ _TIFFfree(raw_data);
+ continue;
+ }
+ } else {
+ /*
+ * XXX: Should be fixed and removed, see the
+ * notes related to TIFFTAG_PAGENUMBER,
+ * TIFFTAG_HALFTONEHINTS,
+ * TIFFTAG_YCBCRSUBSAMPLING and
+ * TIFFTAG_DOTRANGE tags in tif_dir.c. */
+ char *tmp;
+ raw_data = _TIFFmalloc(
+ _TIFFDataSize(fip->field_type)
+ * value_count);
+ tmp = raw_data;
+ mem_alloc = 1;
+ if(TIFFGetField(tif, tag, tmp,
+ tmp + _TIFFDataSize(fip->field_type)) != 1) {
+ _TIFFfree(raw_data);
+ continue;
+ }
+ }
+ }
+
+ /*
+ * Catch the tags which needs to be specially handled and
+ * pretty print them. If tag not handled in
+ * _TIFFPrettyPrintField() fall down and print it as any other
+ * tag.
+ */
+ if (_TIFFPrettyPrintField(tif, fd, tag, value_count, raw_data)) {
+ if(mem_alloc)
+ _TIFFfree(raw_data);
+ continue;
+ }
+ else
+ _TIFFPrintField(fd, fip, value_count, raw_data);
+
+ if(mem_alloc)
+ _TIFFfree(raw_data);
+ }
+ }
+
+ if (tif->tif_tagmethods.printdir)
+ (*tif->tif_tagmethods.printdir)(tif, fd, flags);
+ if ((flags & TIFFPRINT_STRIPS) &&
+ TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
+ tstrip_t s;
+
+ fprintf(fd, " %lu %s:\n",
+ (long) td->td_nstrips,
+ isTiled(tif) ? "Tiles" : "Strips");
+ for (s = 0; s < td->td_nstrips; s++)
+ fprintf(fd, " %3lu: [%8lu, %8lu]\n",
+ (unsigned long) s,
+ (unsigned long) td->td_stripoffset[s],
+ (unsigned long) td->td_stripbytecount[s]);
+ }
+}
+
+void
+_TIFFprintAscii(FILE* fd, const char* cp)
+{
+ for (; *cp != '\0'; cp++) {
+ const char* tp;
+
+ if (isprint((int)*cp)) {
+ fputc(*cp, fd);
+ continue;
+ }
+ for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
+ if (*tp++ == *cp)
+ break;
+ if (*tp)
+ fprintf(fd, "\\%c", *tp);
+ else
+ fprintf(fd, "\\%03o", *cp & 0xff);
+ }
+}
+
+void
+_TIFFprintAsciiTag(FILE* fd, const char* name, const char* value)
+{
+ fprintf(fd, " %s: \"", name);
+ _TIFFprintAscii(fd, value);
+ fprintf(fd, "\"\n");
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_read.c b/Source/LibTIFF/tif_read.c
new file mode 100644
index 0000000..922f0b3
--- /dev/null
+++ b/Source/LibTIFF/tif_read.c
@@ -0,0 +1,741 @@
+/* $Id: tif_read.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ * Scanline-oriented Read Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+ int TIFFFillStrip(TIFF*, tstrip_t);
+ int TIFFFillTile(TIFF*, ttile_t);
+static int TIFFStartStrip(TIFF*, tstrip_t);
+static int TIFFStartTile(TIFF*, ttile_t);
+static int TIFFCheckRead(TIFF*, int);
+
+#define NOSTRIP ((tstrip_t) -1) /* undefined state */
+#define NOTILE ((ttile_t) -1) /* undefined state */
+
+/*
+ * Seek to a random row+sample in a file.
+ */
+static int
+TIFFSeek(TIFF* tif, uint32 row, tsample_t sample)
+{
+ register TIFFDirectory *td = &tif->tif_dir;
+ tstrip_t strip;
+
+ if (row >= td->td_imagelength) { /* out of range */
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Row out of range, max %lu",
+ (unsigned long) row,
+ (unsigned long) td->td_imagelength);
+ return (0);
+ }
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ if (sample >= td->td_samplesperpixel) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Sample out of range, max %lu",
+ (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
+ return (0);
+ }
+ strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
+ } else
+ strip = row / td->td_rowsperstrip;
+ if (strip != tif->tif_curstrip) { /* different strip, refill */
+ if (!TIFFFillStrip(tif, strip))
+ return (0);
+ } else if (row < tif->tif_row) {
+ /*
+ * Moving backwards within the same strip: backup
+ * to the start and then decode forward (below).
+ *
+ * NB: If you're planning on lots of random access within a
+ * strip, it's better to just read and decode the entire
+ * strip, and then access the decoded data in a random fashion.
+ */
+ if (!TIFFStartStrip(tif, strip))
+ return (0);
+ }
+ if (row != tif->tif_row) {
+ /*
+ * Seek forward to the desired row.
+ */
+ if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+ return (0);
+ tif->tif_row = row;
+ }
+ return (1);
+}
+
+int
+TIFFReadScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
+{
+ int e;
+
+ if (!TIFFCheckRead(tif, 0))
+ return (-1);
+ if( (e = TIFFSeek(tif, row, sample)) != 0) {
+ /*
+ * Decompress desired row into user buffer.
+ */
+ e = (*tif->tif_decoderow)
+ (tif, (tidata_t) buf, tif->tif_scanlinesize, sample);
+
+ /* we are now poised at the beginning of the next row */
+ tif->tif_row = row + 1;
+
+ if (e)
+ (*tif->tif_postdecode)(tif, (tidata_t) buf,
+ tif->tif_scanlinesize);
+ }
+ return (e > 0 ? 1 : -1);
+}
+
+/*
+ * Read a strip of data and decompress the specified
+ * amount into the user-supplied buffer.
+ */
+tsize_t
+TIFFReadEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ uint32 nrows;
+ tsize_t stripsize;
+ tstrip_t sep_strip, strips_per_sep;
+
+ if (!TIFFCheckRead(tif, 0))
+ return (-1);
+ if (strip >= td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%ld: Strip out of range, max %ld",
+ (long) strip, (long) td->td_nstrips);
+ return (-1);
+ }
+ /*
+ * Calculate the strip size according to the number of
+ * rows in the strip (check for truncated last strip on any
+ * of the separations).
+ */
+ if( td->td_rowsperstrip >= td->td_imagelength )
+ strips_per_sep = 1;
+ else
+ strips_per_sep = (td->td_imagelength+td->td_rowsperstrip-1)
+ / td->td_rowsperstrip;
+
+ sep_strip = strip % strips_per_sep;
+
+ if (sep_strip != strips_per_sep-1 ||
+ (nrows = td->td_imagelength % td->td_rowsperstrip) == 0)
+ nrows = td->td_rowsperstrip;
+
+ stripsize = TIFFVStripSize(tif, nrows);
+ if (size == (tsize_t) -1)
+ size = stripsize;
+ else if (size > stripsize)
+ size = stripsize;
+ if (TIFFFillStrip(tif, strip)
+ && (*tif->tif_decodestrip)(tif, (tidata_t) buf, size,
+ (tsample_t)(strip / td->td_stripsperimage)) > 0 ) {
+ (*tif->tif_postdecode)(tif, (tidata_t) buf, size);
+ return (size);
+ } else
+ return ((tsize_t) -1);
+}
+
+static tsize_t
+TIFFReadRawStrip1(TIFF* tif,
+ tstrip_t strip, tdata_t buf, tsize_t size, const char* module)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ assert((tif->tif_flags&TIFF_NOREADRAW)==0);
+ if (!isMapped(tif)) {
+ tsize_t cc;
+
+ if (!SeekOK(tif, td->td_stripoffset[strip])) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Seek error at scanline %lu, strip %lu",
+ tif->tif_name,
+ (unsigned long) tif->tif_row, (unsigned long) strip);
+ return (-1);
+ }
+ cc = TIFFReadFile(tif, buf, size);
+ if (cc != size) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Read error at scanline %lu; got %lu bytes, expected %lu",
+ tif->tif_name,
+ (unsigned long) tif->tif_row,
+ (unsigned long) cc,
+ (unsigned long) size);
+ return (-1);
+ }
+ } else {
+ if (td->td_stripoffset[strip] + size > tif->tif_size) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu",
+ tif->tif_name,
+ (unsigned long) tif->tif_row,
+ (unsigned long) strip,
+ (unsigned long) tif->tif_size - td->td_stripoffset[strip],
+ (unsigned long) size);
+ return (-1);
+ }
+ _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip],
+ size);
+ }
+ return (size);
+}
+
+/*
+ * Read a strip of data from the file.
+ */
+tsize_t
+TIFFReadRawStrip(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size)
+{
+ static const char module[] = "TIFFReadRawStrip";
+ TIFFDirectory *td = &tif->tif_dir;
+ /*
+ * FIXME: butecount should have tsize_t type, but for now libtiff
+ * defines tsize_t as a signed 32-bit integer and we are losing
+ * ability to read arrays larger than 2^31 bytes. So we are using
+ * uint32 instead of tsize_t here.
+ */
+ uint32 bytecount;
+
+ if (!TIFFCheckRead(tif, 0))
+ return ((tsize_t) -1);
+ if (strip >= td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Strip out of range, max %lu",
+ (unsigned long) strip,
+ (unsigned long) td->td_nstrips);
+ return ((tsize_t) -1);
+ }
+ if (tif->tif_flags&TIFF_NOREADRAW)
+ {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Compression scheme does not support access to raw uncompressed data");
+ return ((tsize_t) -1);
+ }
+ bytecount = td->td_stripbytecount[strip];
+ if (bytecount <= 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Invalid strip byte count, strip %lu",
+ (unsigned long) bytecount, (unsigned long) strip);
+ return ((tsize_t) -1);
+ }
+ if (size != (tsize_t)-1 && (uint32)size < bytecount)
+ bytecount = size;
+ return (TIFFReadRawStrip1(tif, strip, buf, bytecount, module));
+}
+
+/*
+ * Read the specified strip and setup for decoding. The data buffer is
+ * expanded, as necessary, to hold the strip's data.
+ */
+int
+TIFFFillStrip(TIFF* tif, tstrip_t strip)
+{
+ static const char module[] = "TIFFFillStrip";
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if ((tif->tif_flags&TIFF_NOREADRAW)==0)
+ {
+ /*
+ * FIXME: butecount should have tsize_t type, but for now
+ * libtiff defines tsize_t as a signed 32-bit integer and we
+ * are losing ability to read arrays larger than 2^31 bytes.
+ * So we are using uint32 instead of tsize_t here.
+ */
+ uint32 bytecount = td->td_stripbytecount[strip];
+ if (bytecount <= 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Invalid strip byte count %lu, strip %lu",
+ tif->tif_name, (unsigned long) bytecount,
+ (unsigned long) strip);
+ return (0);
+ }
+ if (isMapped(tif) &&
+ (isFillOrder(tif, td->td_fillorder)
+ || (tif->tif_flags & TIFF_NOBITREV))) {
+ /*
+ * The image is mapped into memory and we either don't
+ * need to flip bits or the compression routine is
+ * going to handle this operation itself. In this
+ * case, avoid copying the raw data and instead just
+ * reference the data from the memory mapped file
+ * image. This assumes that the decompression
+ * routines do not modify the contents of the raw data
+ * buffer (if they try to, the application will get a
+ * fault since the file is mapped read-only).
+ */
+ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ /*
+ * We must check for overflow, potentially causing
+ * an OOB read. Instead of simple
+ *
+ * td->td_stripoffset[strip]+bytecount > tif->tif_size
+ *
+ * comparison (which can overflow) we do the following
+ * two comparisons:
+ */
+ if (bytecount > tif->tif_size ||
+ td->td_stripoffset[strip] > tif->tif_size - bytecount) {
+ /*
+ * This error message might seem strange, but
+ * it's what would happen if a read were done
+ * instead.
+ */
+ TIFFErrorExt(tif->tif_clientdata, module,
+
+ "%s: Read error on strip %lu; "
+ "got %lu bytes, expected %lu",
+ tif->tif_name, (unsigned long) strip,
+ (unsigned long) tif->tif_size - td->td_stripoffset[strip],
+ (unsigned long) bytecount);
+ tif->tif_curstrip = NOSTRIP;
+ return (0);
+ }
+ tif->tif_rawdatasize = bytecount;
+ tif->tif_rawdata = tif->tif_base + td->td_stripoffset[strip];
+ } else {
+ /*
+ * Expand raw data buffer, if needed, to hold data
+ * strip coming from file (perhaps should set upper
+ * bound on the size of a buffer we'll use?).
+ */
+ if (bytecount > (uint32)tif->tif_rawdatasize) {
+ tif->tif_curstrip = NOSTRIP;
+ if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
+ TIFFErrorExt(tif->tif_clientdata,
+ module,
+ "%s: Data buffer too small to hold strip %lu",
+ tif->tif_name,
+ (unsigned long) strip);
+ return (0);
+ }
+ if (!TIFFReadBufferSetup(tif, 0,
+ TIFFroundup(bytecount, 1024)))
+ return (0);
+ }
+ if ((uint32)TIFFReadRawStrip1(tif, strip,
+ (unsigned char *)tif->tif_rawdata,
+ bytecount, module) != bytecount)
+ return (0);
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ TIFFReverseBits(tif->tif_rawdata, bytecount);
+ }
+ }
+ return (TIFFStartStrip(tif, strip));
+}
+
+/*
+ * Tile-oriented Read Support
+ * Contributed by Nancy Cam (Silicon Graphics).
+ */
+
+/*
+ * Read and decompress a tile of data. The
+ * tile is selected by the (x,y,z,s) coordinates.
+ */
+tsize_t
+TIFFReadTile(TIFF* tif,
+ tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+ if (!TIFFCheckRead(tif, 1) || !TIFFCheckTile(tif, x, y, z, s))
+ return (-1);
+ return (TIFFReadEncodedTile(tif,
+ TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
+}
+
+/*
+ * Read a tile of data and decompress the specified
+ * amount into the user-supplied buffer.
+ */
+tsize_t
+TIFFReadEncodedTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t tilesize = tif->tif_tilesize;
+
+ if (!TIFFCheckRead(tif, 1))
+ return (-1);
+ if (tile >= td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%ld: Tile out of range, max %ld",
+ (long) tile, (unsigned long) td->td_nstrips);
+ return (-1);
+ }
+ if (size == (tsize_t) -1)
+ size = tilesize;
+ else if (size > tilesize)
+ size = tilesize;
+ if (TIFFFillTile(tif, tile) && (*tif->tif_decodetile)(tif,
+ (tidata_t) buf, size, (tsample_t)(tile/td->td_stripsperimage))) {
+ (*tif->tif_postdecode)(tif, (tidata_t) buf, size);
+ return (size);
+ } else
+ return (-1);
+}
+
+static tsize_t
+TIFFReadRawTile1(TIFF* tif,
+ ttile_t tile, tdata_t buf, tsize_t size, const char* module)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ assert((tif->tif_flags&TIFF_NOREADRAW)==0);
+ if (!isMapped(tif)) {
+ tsize_t cc;
+
+ if (!SeekOK(tif, td->td_stripoffset[tile])) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Seek error at row %ld, col %ld, tile %ld",
+ tif->tif_name,
+ (long) tif->tif_row,
+ (long) tif->tif_col,
+ (long) tile);
+ return ((tsize_t) -1);
+ }
+ cc = TIFFReadFile(tif, buf, size);
+ if (cc != size) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu",
+ tif->tif_name,
+ (long) tif->tif_row,
+ (long) tif->tif_col,
+ (unsigned long) cc,
+ (unsigned long) size);
+ return ((tsize_t) -1);
+ }
+ } else {
+ if (td->td_stripoffset[tile] + size > tif->tif_size) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu",
+ tif->tif_name,
+ (long) tif->tif_row,
+ (long) tif->tif_col,
+ (long) tile,
+ (unsigned long) tif->tif_size - td->td_stripoffset[tile],
+ (unsigned long) size);
+ return ((tsize_t) -1);
+ }
+ _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size);
+ }
+ return (size);
+}
+
+/*
+ * Read a tile of data from the file.
+ */
+tsize_t
+TIFFReadRawTile(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size)
+{
+ static const char module[] = "TIFFReadRawTile";
+ TIFFDirectory *td = &tif->tif_dir;
+ /*
+ * FIXME: butecount should have tsize_t type, but for now libtiff
+ * defines tsize_t as a signed 32-bit integer and we are losing
+ * ability to read arrays larger than 2^31 bytes. So we are using
+ * uint32 instead of tsize_t here.
+ */
+ uint32 bytecount;
+
+ if (!TIFFCheckRead(tif, 1))
+ return ((tsize_t) -1);
+ if (tile >= td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Tile out of range, max %lu",
+ (unsigned long) tile, (unsigned long) td->td_nstrips);
+ return ((tsize_t) -1);
+ }
+ if (tif->tif_flags&TIFF_NOREADRAW)
+ {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Compression scheme does not support access to raw uncompressed data");
+ return ((tsize_t) -1);
+ }
+ bytecount = td->td_stripbytecount[tile];
+ if (size != (tsize_t) -1 && (uint32)size < bytecount)
+ bytecount = size;
+ return (TIFFReadRawTile1(tif, tile, buf, bytecount, module));
+}
+
+/*
+ * Read the specified tile and setup for decoding. The data buffer is
+ * expanded, as necessary, to hold the tile's data.
+ */
+int
+TIFFFillTile(TIFF* tif, ttile_t tile)
+{
+ static const char module[] = "TIFFFillTile";
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if ((tif->tif_flags&TIFF_NOREADRAW)==0)
+ {
+ /*
+ * FIXME: butecount should have tsize_t type, but for now
+ * libtiff defines tsize_t as a signed 32-bit integer and we
+ * are losing ability to read arrays larger than 2^31 bytes.
+ * So we are using uint32 instead of tsize_t here.
+ */
+ uint32 bytecount = td->td_stripbytecount[tile];
+ if (bytecount <= 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Invalid tile byte count, tile %lu",
+ (unsigned long) bytecount, (unsigned long) tile);
+ return (0);
+ }
+ if (isMapped(tif) &&
+ (isFillOrder(tif, td->td_fillorder)
+ || (tif->tif_flags & TIFF_NOBITREV))) {
+ /*
+ * The image is mapped into memory and we either don't
+ * need to flip bits or the compression routine is
+ * going to handle this operation itself. In this
+ * case, avoid copying the raw data and instead just
+ * reference the data from the memory mapped file
+ * image. This assumes that the decompression
+ * routines do not modify the contents of the raw data
+ * buffer (if they try to, the application will get a
+ * fault since the file is mapped read-only).
+ */
+ if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata)
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ /*
+ * We must check for overflow, potentially causing
+ * an OOB read. Instead of simple
+ *
+ * td->td_stripoffset[tile]+bytecount > tif->tif_size
+ *
+ * comparison (which can overflow) we do the following
+ * two comparisons:
+ */
+ if (bytecount > tif->tif_size ||
+ td->td_stripoffset[tile] > tif->tif_size - bytecount) {
+ tif->tif_curtile = NOTILE;
+ return (0);
+ }
+ tif->tif_rawdatasize = bytecount;
+ tif->tif_rawdata =
+ tif->tif_base + td->td_stripoffset[tile];
+ } else {
+ /*
+ * Expand raw data buffer, if needed, to hold data
+ * tile coming from file (perhaps should set upper
+ * bound on the size of a buffer we'll use?).
+ */
+ if (bytecount > (uint32)tif->tif_rawdatasize) {
+ tif->tif_curtile = NOTILE;
+ if ((tif->tif_flags & TIFF_MYBUFFER) == 0) {
+ TIFFErrorExt(tif->tif_clientdata,
+ module,
+ "%s: Data buffer too small to hold tile %ld",
+ tif->tif_name,
+ (long) tile);
+ return (0);
+ }
+ if (!TIFFReadBufferSetup(tif, 0,
+ TIFFroundup(bytecount, 1024)))
+ return (0);
+ }
+ if ((uint32)TIFFReadRawTile1(tif, tile,
+ (unsigned char *)tif->tif_rawdata,
+ bytecount, module) != bytecount)
+ return (0);
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ TIFFReverseBits(tif->tif_rawdata, bytecount);
+ }
+ }
+ return (TIFFStartTile(tif, tile));
+}
+
+/*
+ * Setup the raw data buffer in preparation for
+ * reading a strip of raw data. If the buffer
+ * is specified as zero, then a buffer of appropriate
+ * size is allocated by the library. Otherwise,
+ * the client must guarantee that the buffer is
+ * large enough to hold any individual strip of
+ * raw data.
+ */
+int
+TIFFReadBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
+{
+ static const char module[] = "TIFFReadBufferSetup";
+
+ assert((tif->tif_flags&TIFF_NOREADRAW)==0);
+ if (tif->tif_rawdata) {
+ if (tif->tif_flags & TIFF_MYBUFFER)
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_rawdata = NULL;
+ }
+ if (bp) {
+ tif->tif_rawdatasize = size;
+ tif->tif_rawdata = (tidata_t) bp;
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ } else {
+ tif->tif_rawdatasize = TIFFroundup(size, 1024);
+ tif->tif_rawdata = (tidata_t) _TIFFmalloc(tif->tif_rawdatasize);
+ tif->tif_flags |= TIFF_MYBUFFER;
+ }
+ if (tif->tif_rawdata == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: No space for data buffer at scanline %ld",
+ tif->tif_name, (long) tif->tif_row);
+ tif->tif_rawdatasize = 0;
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Set state to appear as if a
+ * strip has just been read in.
+ */
+static int
+TIFFStartStrip(TIFF* tif, tstrip_t strip)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+ if (!(*tif->tif_setupdecode)(tif))
+ return (0);
+ tif->tif_flags |= TIFF_CODERSETUP;
+ }
+ tif->tif_curstrip = strip;
+ tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+ if (tif->tif_flags&TIFF_NOREADRAW)
+ {
+ tif->tif_rawcp = NULL;
+ tif->tif_rawcc = 0;
+ }
+ else
+ {
+ tif->tif_rawcp = tif->tif_rawdata;
+ tif->tif_rawcc = td->td_stripbytecount[strip];
+ }
+ return ((*tif->tif_predecode)(tif,
+ (tsample_t)(strip / td->td_stripsperimage)));
+}
+
+/*
+ * Set state to appear as if a
+ * tile has just been read in.
+ */
+static int
+TIFFStartTile(TIFF* tif, ttile_t tile)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+ if (!(*tif->tif_setupdecode)(tif))
+ return (0);
+ tif->tif_flags |= TIFF_CODERSETUP;
+ }
+ tif->tif_curtile = tile;
+ tif->tif_row =
+ (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth)) *
+ td->td_tilelength;
+ tif->tif_col =
+ (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength)) *
+ td->td_tilewidth;
+ if (tif->tif_flags&TIFF_NOREADRAW)
+ {
+ tif->tif_rawcp = NULL;
+ tif->tif_rawcc = 0;
+ }
+ else
+ {
+ tif->tif_rawcp = tif->tif_rawdata;
+ tif->tif_rawcc = td->td_stripbytecount[tile];
+ }
+ return ((*tif->tif_predecode)(tif,
+ (tsample_t)(tile/td->td_stripsperimage)));
+}
+
+static int
+TIFFCheckRead(TIFF* tif, int tiles)
+{
+ if (tif->tif_mode == O_WRONLY) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading");
+ return (0);
+ }
+ if (tiles ^ isTiled(tif)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
+ "Can not read tiles from a stripped image" :
+ "Can not read scanlines from a tiled image");
+ return (0);
+ }
+ return (1);
+}
+
+void
+_TIFFNoPostDecode(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ (void) tif; (void) buf; (void) cc;
+}
+
+void
+_TIFFSwab16BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ (void) tif;
+ assert((cc & 1) == 0);
+ TIFFSwabArrayOfShort((uint16*) buf, cc/2);
+}
+
+void
+_TIFFSwab24BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ (void) tif;
+ assert((cc % 3) == 0);
+ TIFFSwabArrayOfTriples((uint8*) buf, cc/3);
+}
+
+void
+_TIFFSwab32BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ (void) tif;
+ assert((cc & 3) == 0);
+ TIFFSwabArrayOfLong((uint32*) buf, cc/4);
+}
+
+void
+_TIFFSwab64BitData(TIFF* tif, tidata_t buf, tsize_t cc)
+{
+ (void) tif;
+ assert((cc & 7) == 0);
+ TIFFSwabArrayOfDouble((double*) buf, cc/8);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_stream.cxx b/Source/LibTIFF/tif_stream.cxx
new file mode 100644
index 0000000..eb4d996
--- /dev/null
+++ b/Source/LibTIFF/tif_stream.cxx
@@ -0,0 +1,295 @@
+/* $Id: tif_stream.cxx,v 1.22 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1996 Sam Leffler
+ * Copyright (c) 1991-1996 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library UNIX-specific Routines.
+ */
+#include "tiffiop.h"
+#include <iostream>
+
+#ifndef __VMS
+using namespace std;
+#endif
+
+class tiffis_data
+{
+ public:
+
+ istream *myIS;
+ long myStreamStartPos;
+};
+
+class tiffos_data
+{
+ public:
+
+ ostream *myOS;
+ long myStreamStartPos;
+};
+
+static tsize_t
+_tiffosReadProc(thandle_t, tdata_t, tsize_t)
+{
+ return 0;
+}
+
+static tsize_t
+_tiffisReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ tiffis_data *data = (tiffis_data *)fd;
+
+ data->myIS->read((char *)buf, (int)size);
+
+ return data->myIS->gcount();
+}
+
+static tsize_t
+_tiffosWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ tiffos_data *data = (tiffos_data *)fd;
+ ostream *os = data->myOS;
+ int pos = os->tellp();
+
+ os->write((const char *)buf, size);
+
+ return ((int)os->tellp()) - pos;
+}
+
+static tsize_t
+_tiffisWriteProc(thandle_t, tdata_t, tsize_t)
+{
+ return 0;
+}
+
+static toff_t
+_tiffosSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ tiffos_data *data = (tiffos_data *)fd;
+ ostream *os = data->myOS;
+
+ // if the stream has already failed, don't do anything
+ if( os->fail() )
+ return os->tellp();
+
+ switch(whence) {
+ case SEEK_SET:
+ os->seekp(data->myStreamStartPos + off, ios::beg);
+ break;
+ case SEEK_CUR:
+ os->seekp(off, ios::cur);
+ break;
+ case SEEK_END:
+ os->seekp(off, ios::end);
+ break;
+ }
+
+ // Attempt to workaround problems with seeking past the end of the
+ // stream. ofstream doesn't have a problem with this but
+ // ostrstream/ostringstream does. In that situation, add intermediate
+ // '\0' characters.
+ if( os->fail() ) {
+#ifdef __VMS
+ int old_state;
+#else
+ ios::iostate old_state;
+#endif
+ toff_t origin=0;
+
+ old_state = os->rdstate();
+ // reset the fail bit or else tellp() won't work below
+ os->clear(os->rdstate() & ~ios::failbit);
+ switch( whence ) {
+ case SEEK_SET:
+ origin = data->myStreamStartPos;
+ break;
+ case SEEK_CUR:
+ origin = os->tellp();
+ break;
+ case SEEK_END:
+ os->seekp(0, ios::end);
+ origin = os->tellp();
+ break;
+ }
+ // restore original stream state
+ os->clear(old_state);
+
+ // only do something if desired seek position is valid
+ if( origin + off > data->myStreamStartPos ) {
+ toff_t num_fill;
+
+ // clear the fail bit
+ os->clear(os->rdstate() & ~ios::failbit);
+
+ // extend the stream to the expected size
+ os->seekp(0, ios::end);
+ num_fill = origin + off - (toff_t)os->tellp();
+ for( toff_t i = 0; i < num_fill; i++ )
+ os->put('\0');
+
+ // retry the seek
+ os->seekp(origin + off, ios::beg);
+ }
+ }
+
+ return os->tellp();
+}
+
+static toff_t
+_tiffisSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ tiffis_data *data = (tiffis_data *)fd;
+
+ switch(whence) {
+ case SEEK_SET:
+ data->myIS->seekg(data->myStreamStartPos + off, ios::beg);
+ break;
+ case SEEK_CUR:
+ data->myIS->seekg(off, ios::cur);
+ break;
+ case SEEK_END:
+ data->myIS->seekg(off, ios::end);
+ break;
+ }
+
+ return ((long)data->myIS->tellg()) - data->myStreamStartPos;
+}
+
+static toff_t
+_tiffosSizeProc(thandle_t fd)
+{
+ tiffos_data *data = (tiffos_data *)fd;
+ ostream *os = data->myOS;
+ toff_t pos = os->tellp();
+ toff_t len;
+
+ os->seekp(0, ios::end);
+ len = os->tellp();
+ os->seekp(pos);
+
+ return len;
+}
+
+static toff_t
+_tiffisSizeProc(thandle_t fd)
+{
+ tiffis_data *data = (tiffis_data *)fd;
+ int pos = data->myIS->tellg();
+ int len;
+
+ data->myIS->seekg(0, ios::end);
+ len = data->myIS->tellg();
+ data->myIS->seekg(pos);
+
+ return len;
+}
+
+static int
+_tiffosCloseProc(thandle_t fd)
+{
+ // Our stream was not allocated by us, so it shouldn't be closed by us.
+ delete (tiffos_data *)fd;
+ return 0;
+}
+
+static int
+_tiffisCloseProc(thandle_t fd)
+{
+ // Our stream was not allocated by us, so it shouldn't be closed by us.
+ delete (tiffis_data *)fd;
+ return 0;
+}
+
+static int
+_tiffDummyMapProc(thandle_t , tdata_t* , toff_t* )
+{
+ return (0);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t , tdata_t , toff_t )
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+static TIFF*
+_tiffStreamOpen(const char* name, const char* mode, void *fd)
+{
+ TIFF* tif;
+
+ if( strchr(mode, 'w') ) {
+ tiffos_data *data = new tiffos_data;
+ data->myOS = (ostream *)fd;
+ data->myStreamStartPos = data->myOS->tellp();
+
+ // Open for writing.
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) data,
+ _tiffosReadProc, _tiffosWriteProc,
+ _tiffosSeekProc, _tiffosCloseProc,
+ _tiffosSizeProc,
+ _tiffDummyMapProc, _tiffDummyUnmapProc);
+ } else {
+ tiffis_data *data = new tiffis_data;
+ data->myIS = (istream *)fd;
+ data->myStreamStartPos = data->myIS->tellg();
+ // Open for reading.
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) data,
+ _tiffisReadProc, _tiffisWriteProc,
+ _tiffisSeekProc, _tiffisCloseProc,
+ _tiffisSizeProc,
+ _tiffDummyMapProc, _tiffDummyUnmapProc);
+ }
+
+ return (tif);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, ostream *os)
+{
+ // If os is either a ostrstream or ostringstream, and has no data
+ // written to it yet, then tellp() will return -1 which will break us.
+ // We workaround this by writing out a dummy character and
+ // then seek back to the beginning.
+ if( !os->fail() && (int)os->tellp() < 0 ) {
+ *os << '\0';
+ os->seekp(0);
+ }
+
+ // NB: We don't support mapped files with streams so add 'm'
+ return _tiffStreamOpen(name, "wm", os);
+}
+
+TIFF*
+TIFFStreamOpen(const char* name, istream *is)
+{
+ // NB: We don't support mapped files with streams so add 'm'
+ return _tiffStreamOpen(name, "rm", is);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_strip.c b/Source/LibTIFF/tif_strip.c
new file mode 100644
index 0000000..752cace
--- /dev/null
+++ b/Source/LibTIFF/tif_strip.c
@@ -0,0 +1,363 @@
+/* $Id: tif_strip.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Strip-organized Image Support Routines.
+ */
+#include "tiffiop.h"
+
+static uint32
+summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where)
+{
+ /*
+ * XXX: We are using casting to uint32 here, bacause sizeof(size_t)
+ * may be larger than sizeof(uint32) on 64-bit architectures.
+ */
+ uint32 bytes = summand1 + summand2;
+
+ if (bytes - summand1 != summand2) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
+ bytes = 0;
+ }
+
+ return (bytes);
+}
+
+static uint32
+multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where)
+{
+ uint32 bytes = nmemb * elem_size;
+
+ if (elem_size && bytes / elem_size != nmemb) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
+ bytes = 0;
+ }
+
+ return (bytes);
+}
+
+/*
+ * Compute which strip a (row,sample) value is in.
+ */
+tstrip_t
+TIFFComputeStrip(TIFF* tif, uint32 row, tsample_t sample)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tstrip_t strip;
+
+ strip = row / td->td_rowsperstrip;
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ if (sample >= td->td_samplesperpixel) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Sample out of range, max %lu",
+ (unsigned long) sample, (unsigned long) td->td_samplesperpixel);
+ return ((tstrip_t) 0);
+ }
+ strip += sample*td->td_stripsperimage;
+ }
+ return (strip);
+}
+
+/*
+ * Compute how many strips are in an image.
+ */
+tstrip_t
+TIFFNumberOfStrips(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tstrip_t nstrips;
+
+ nstrips = (td->td_rowsperstrip == (uint32) -1 ? 1 :
+ TIFFhowmany(td->td_imagelength, td->td_rowsperstrip));
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ nstrips = multiply(tif, nstrips, td->td_samplesperpixel,
+ "TIFFNumberOfStrips");
+ return (nstrips);
+}
+
+/*
+ * Compute the # bytes in a variable height, row-aligned strip.
+ */
+tsize_t
+TIFFVStripSize(TIFF* tif, uint32 nrows)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if (nrows == (uint32) -1)
+ nrows = td->td_imagelength;
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+ td->td_photometric == PHOTOMETRIC_YCBCR &&
+ !isUpSampled(tif)) {
+ /*
+ * Packed YCbCr data contain one Cb+Cr for every
+ * HorizontalSampling*VerticalSampling Y values.
+ * Must also roundup width and height when calculating
+ * since images that are not a multiple of the
+ * horizontal/vertical subsampling area include
+ * YCbCr data for the extended image.
+ */
+ uint16 ycbcrsubsampling[2];
+ tsize_t w, scanline, samplingarea;
+
+ TIFFGetField( tif, TIFFTAG_YCBCRSUBSAMPLING,
+ ycbcrsubsampling + 0,
+ ycbcrsubsampling + 1 );
+
+ samplingarea = ycbcrsubsampling[0]*ycbcrsubsampling[1];
+ if (samplingarea == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Invalid YCbCr subsampling");
+ return 0;
+ }
+
+ w = TIFFroundup(td->td_imagewidth, ycbcrsubsampling[0]);
+ scanline = TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
+ "TIFFVStripSize"));
+ nrows = TIFFroundup(nrows, ycbcrsubsampling[1]);
+ /* NB: don't need TIFFhowmany here 'cuz everything is rounded */
+ scanline = multiply(tif, nrows, scanline, "TIFFVStripSize");
+ return ((tsize_t)
+ summarize(tif, scanline,
+ multiply(tif, 2, scanline / samplingarea,
+ "TIFFVStripSize"), "TIFFVStripSize"));
+ } else
+ return ((tsize_t) multiply(tif, nrows, TIFFScanlineSize(tif),
+ "TIFFVStripSize"));
+}
+
+
+/*
+ * Compute the # bytes in a raw strip.
+ */
+tsize_t
+TIFFRawStripSize(TIFF* tif, tstrip_t strip)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ tsize_t bytecount = td->td_stripbytecount[strip];
+
+ if (bytecount <= 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Invalid strip byte count, strip %lu",
+ (unsigned long) bytecount, (unsigned long) strip);
+ bytecount = (tsize_t) -1;
+ }
+
+ return bytecount;
+}
+
+/*
+ * Compute the # bytes in a (row-aligned) strip.
+ *
+ * Note that if RowsPerStrip is larger than the
+ * recorded ImageLength, then the strip size is
+ * truncated to reflect the actual space required
+ * to hold the strip.
+ */
+tsize_t
+TIFFStripSize(TIFF* tif)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+ uint32 rps = td->td_rowsperstrip;
+ if (rps > td->td_imagelength)
+ rps = td->td_imagelength;
+ return (TIFFVStripSize(tif, rps));
+}
+
+/*
+ * Compute a default strip size based on the image
+ * characteristics and a requested value. If the
+ * request is <1 then we choose a strip size according
+ * to certain heuristics.
+ */
+uint32
+TIFFDefaultStripSize(TIFF* tif, uint32 request)
+{
+ return (*tif->tif_defstripsize)(tif, request);
+}
+
+uint32
+_TIFFDefaultStripSize(TIFF* tif, uint32 s)
+{
+ if ((int32) s < 1) {
+ /*
+ * If RowsPerStrip is unspecified, try to break the
+ * image up into strips that are approximately
+ * STRIP_SIZE_DEFAULT bytes long.
+ */
+ tsize_t scanline = TIFFScanlineSize(tif);
+ s = (uint32)STRIP_SIZE_DEFAULT / (scanline == 0 ? 1 : scanline);
+ if (s == 0) /* very wide images */
+ s = 1;
+ }
+ return (s);
+}
+
+/*
+ * Return the number of bytes to read/write in a call to
+ * one of the scanline-oriented i/o routines. Note that
+ * this number may be 1/samples-per-pixel if data is
+ * stored as separate planes.
+ */
+tsize_t
+TIFFScanlineSize(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t scanline;
+
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ if (td->td_photometric == PHOTOMETRIC_YCBCR
+ && !isUpSampled(tif)) {
+ uint16 ycbcrsubsampling[2];
+
+ TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING,
+ ycbcrsubsampling + 0,
+ ycbcrsubsampling + 1);
+
+ if (ycbcrsubsampling[0] == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Invalid YCbCr subsampling");
+ return 0;
+ }
+
+ scanline = TIFFroundup(td->td_imagewidth,
+ ycbcrsubsampling[0]);
+ scanline = TIFFhowmany8(multiply(tif, scanline,
+ td->td_bitspersample,
+ "TIFFScanlineSize"));
+ return ((tsize_t)
+ summarize(tif, scanline,
+ multiply(tif, 2,
+ scanline / ycbcrsubsampling[0],
+ "TIFFVStripSize"),
+ "TIFFVStripSize"));
+ } else {
+ scanline = multiply(tif, td->td_imagewidth,
+ td->td_samplesperpixel,
+ "TIFFScanlineSize");
+ }
+ } else
+ scanline = td->td_imagewidth;
+ return ((tsize_t) TIFFhowmany8(multiply(tif, scanline,
+ td->td_bitspersample,
+ "TIFFScanlineSize")));
+}
+
+/*
+ * Some stuff depends on this older version of TIFFScanlineSize
+ * TODO: resolve this
+ */
+tsize_t
+TIFFOldScanlineSize(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t scanline;
+
+ scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
+ "TIFFScanlineSize");
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG)
+ scanline = multiply (tif, scanline, td->td_samplesperpixel,
+ "TIFFScanlineSize");
+ return ((tsize_t) TIFFhowmany8(scanline));
+}
+
+/*
+ * Return the number of bytes to read/write in a call to
+ * one of the scanline-oriented i/o routines. Note that
+ * this number may be 1/samples-per-pixel if data is
+ * stored as separate planes.
+ * The ScanlineSize in case of YCbCrSubsampling is defined as the
+ * strip size divided by the strip height, i.e. the size of a pack of vertical
+ * subsampling lines divided by vertical subsampling. It should thus make
+ * sense when multiplied by a multiple of vertical subsampling.
+ * Some stuff depends on this newer version of TIFFScanlineSize
+ * TODO: resolve this
+ */
+tsize_t
+TIFFNewScanlineSize(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t scanline;
+
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ if (td->td_photometric == PHOTOMETRIC_YCBCR
+ && !isUpSampled(tif)) {
+ uint16 ycbcrsubsampling[2];
+
+ TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING,
+ ycbcrsubsampling + 0,
+ ycbcrsubsampling + 1);
+
+ if (ycbcrsubsampling[0]*ycbcrsubsampling[1] == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Invalid YCbCr subsampling");
+ return 0;
+ }
+
+ return((tsize_t) ((((td->td_imagewidth+ycbcrsubsampling[0]-1)
+ /ycbcrsubsampling[0])
+ *(ycbcrsubsampling[0]*ycbcrsubsampling[1]+2)
+ *td->td_bitspersample+7)
+ /8)/ycbcrsubsampling[1]);
+
+ } else {
+ scanline = multiply(tif, td->td_imagewidth,
+ td->td_samplesperpixel,
+ "TIFFScanlineSize");
+ }
+ } else
+ scanline = td->td_imagewidth;
+ return ((tsize_t) TIFFhowmany8(multiply(tif, scanline,
+ td->td_bitspersample,
+ "TIFFScanlineSize")));
+}
+
+/*
+ * Return the number of bytes required to store a complete
+ * decoded and packed raster scanline (as opposed to the
+ * I/O size returned by TIFFScanlineSize which may be less
+ * if data is store as separate planes).
+ */
+tsize_t
+TIFFRasterScanlineSize(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t scanline;
+
+ scanline = multiply (tif, td->td_bitspersample, td->td_imagewidth,
+ "TIFFRasterScanlineSize");
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG) {
+ scanline = multiply (tif, scanline, td->td_samplesperpixel,
+ "TIFFRasterScanlineSize");
+ return ((tsize_t) TIFFhowmany8(scanline));
+ } else
+ return ((tsize_t) multiply (tif, TIFFhowmany8(scanline),
+ td->td_samplesperpixel,
+ "TIFFRasterScanlineSize"));
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_swab.c b/Source/LibTIFF/tif_swab.c
new file mode 100644
index 0000000..9062c33
--- /dev/null
+++ b/Source/LibTIFF/tif_swab.c
@@ -0,0 +1,235 @@
+/* $Id: tif_swab.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Bit & Byte Swapping Support.
+ *
+ * XXX We assume short = 16-bits and long = 32-bits XXX
+ */
+#include "tiffiop.h"
+
+#ifndef TIFFSwabShort
+void
+TIFFSwabShort(uint16* wp)
+{
+ register unsigned char* cp = (unsigned char*) wp;
+ unsigned char t;
+
+ t = cp[1]; cp[1] = cp[0]; cp[0] = t;
+}
+#endif
+
+#ifndef TIFFSwabLong
+void
+TIFFSwabLong(uint32* lp)
+{
+ register unsigned char* cp = (unsigned char*) lp;
+ unsigned char t;
+
+ t = cp[3]; cp[3] = cp[0]; cp[0] = t;
+ t = cp[2]; cp[2] = cp[1]; cp[1] = t;
+}
+#endif
+
+#ifndef TIFFSwabArrayOfShort
+void
+TIFFSwabArrayOfShort(uint16* wp, register unsigned long n)
+{
+ register unsigned char* cp;
+ register unsigned char t;
+
+ /* XXX unroll loop some */
+ while (n-- > 0) {
+ cp = (unsigned char*) wp;
+ t = cp[1]; cp[1] = cp[0]; cp[0] = t;
+ wp++;
+ }
+}
+#endif
+
+#ifndef TIFFSwabArrayOfTriples
+void
+TIFFSwabArrayOfTriples(uint8* tp, unsigned long n)
+{
+ unsigned char* cp;
+ unsigned char t;
+
+ /* XXX unroll loop some */
+ while (n-- > 0) {
+ cp = (unsigned char*) tp;
+ t = cp[2]; cp[2] = cp[0]; cp[0] = t;
+ tp += 3;
+ }
+}
+#endif
+
+#ifndef TIFFSwabArrayOfLong
+void
+TIFFSwabArrayOfLong(register uint32* lp, register unsigned long n)
+{
+ register unsigned char *cp;
+ register unsigned char t;
+
+ /* XXX unroll loop some */
+ while (n-- > 0) {
+ cp = (unsigned char *)lp;
+ t = cp[3]; cp[3] = cp[0]; cp[0] = t;
+ t = cp[2]; cp[2] = cp[1]; cp[1] = t;
+ lp++;
+ }
+}
+#endif
+
+#ifndef TIFFSwabDouble
+void
+TIFFSwabDouble(double *dp)
+{
+ register uint32* lp = (uint32*) dp;
+ uint32 t;
+
+ TIFFSwabArrayOfLong(lp, 2);
+ t = lp[0]; lp[0] = lp[1]; lp[1] = t;
+}
+#endif
+
+#ifndef TIFFSwabArrayOfDouble
+void
+TIFFSwabArrayOfDouble(double* dp, register unsigned long n)
+{
+ register uint32* lp = (uint32*) dp;
+ register uint32 t;
+
+ TIFFSwabArrayOfLong(lp, n + n);
+ while (n-- > 0) {
+ t = lp[0]; lp[0] = lp[1]; lp[1] = t;
+ lp += 2;
+ }
+}
+#endif
+
+/*
+ * Bit reversal tables. TIFFBitRevTable[<byte>] gives
+ * the bit reversed value of <byte>. Used in various
+ * places in the library when the FillOrder requires
+ * bit reversal of byte values (e.g. CCITT Fax 3
+ * encoding/decoding). TIFFNoBitRevTable is provided
+ * for algorithms that want an equivalent table that
+ * do not reverse bit values.
+ */
+static const unsigned char TIFFBitRevTable[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+static const unsigned char TIFFNoBitRevTable[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+};
+
+const unsigned char*
+TIFFGetBitRevTable(int reversed)
+{
+ return (reversed ? TIFFBitRevTable : TIFFNoBitRevTable);
+}
+
+void
+TIFFReverseBits(register unsigned char* cp, register unsigned long n)
+{
+ for (; n > 8; n -= 8) {
+ cp[0] = TIFFBitRevTable[cp[0]];
+ cp[1] = TIFFBitRevTable[cp[1]];
+ cp[2] = TIFFBitRevTable[cp[2]];
+ cp[3] = TIFFBitRevTable[cp[3]];
+ cp[4] = TIFFBitRevTable[cp[4]];
+ cp[5] = TIFFBitRevTable[cp[5]];
+ cp[6] = TIFFBitRevTable[cp[6]];
+ cp[7] = TIFFBitRevTable[cp[7]];
+ cp += 8;
+ }
+ while (n-- > 0)
+ *cp = TIFFBitRevTable[*cp], cp++;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_thunder.c b/Source/LibTIFF/tif_thunder.c
new file mode 100644
index 0000000..3c8a2ed
--- /dev/null
+++ b/Source/LibTIFF/tif_thunder.c
@@ -0,0 +1,158 @@
+/* $Id: tif_thunder.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef THUNDER_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * ThunderScan 4-bit Compression Algorithm Support
+ */
+
+/*
+ * ThunderScan uses an encoding scheme designed for
+ * 4-bit pixel values. Data is encoded in bytes, with
+ * each byte split into a 2-bit code word and a 6-bit
+ * data value. The encoding gives raw data, runs of
+ * pixels, or pixel values encoded as a delta from the
+ * previous pixel value. For the latter, either 2-bit
+ * or 3-bit delta values are used, with the deltas packed
+ * into a single byte.
+ */
+#define THUNDER_DATA 0x3f /* mask for 6-bit data */
+#define THUNDER_CODE 0xc0 /* mask for 2-bit code word */
+/* code values */
+#define THUNDER_RUN 0x00 /* run of pixels w/ encoded count */
+#define THUNDER_2BITDELTAS 0x40 /* 3 pixels w/ encoded 2-bit deltas */
+#define DELTA2_SKIP 2 /* skip code for 2-bit deltas */
+#define THUNDER_3BITDELTAS 0x80 /* 2 pixels w/ encoded 3-bit deltas */
+#define DELTA3_SKIP 4 /* skip code for 3-bit deltas */
+#define THUNDER_RAW 0xc0 /* raw data encoded */
+
+static const int twobitdeltas[4] = { 0, 1, 0, -1 };
+static const int threebitdeltas[8] = { 0, 1, 2, 3, 0, -3, -2, -1 };
+
+#define SETPIXEL(op, v) { \
+ lastpixel = (v) & 0xf; \
+ if (npixels++ & 1) \
+ *op++ |= lastpixel; \
+ else \
+ op[0] = (tidataval_t) (lastpixel << 4); \
+}
+
+static int
+ThunderDecode(TIFF* tif, tidata_t op, tsize_t maxpixels)
+{
+ register unsigned char *bp;
+ register tsize_t cc;
+ unsigned int lastpixel;
+ tsize_t npixels;
+
+ bp = (unsigned char *)tif->tif_rawcp;
+ cc = tif->tif_rawcc;
+ lastpixel = 0;
+ npixels = 0;
+ while (cc > 0 && npixels < maxpixels) {
+ int n, delta;
+
+ n = *bp++, cc--;
+ switch (n & THUNDER_CODE) {
+ case THUNDER_RUN: /* pixel run */
+ /*
+ * Replicate the last pixel n times,
+ * where n is the lower-order 6 bits.
+ */
+ if (npixels & 1) {
+ op[0] |= lastpixel;
+ lastpixel = *op++; npixels++; n--;
+ } else
+ lastpixel |= lastpixel << 4;
+ npixels += n;
+ if (npixels < maxpixels) {
+ for (; n > 0; n -= 2)
+ *op++ = (tidataval_t) lastpixel;
+ }
+ if (n == -1)
+ *--op &= 0xf0;
+ lastpixel &= 0xf;
+ break;
+ case THUNDER_2BITDELTAS: /* 2-bit deltas */
+ if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP)
+ SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+ if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP)
+ SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+ if ((delta = (n & 3)) != DELTA2_SKIP)
+ SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+ break;
+ case THUNDER_3BITDELTAS: /* 3-bit deltas */
+ if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP)
+ SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+ if ((delta = (n & 7)) != DELTA3_SKIP)
+ SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+ break;
+ case THUNDER_RAW: /* raw data */
+ SETPIXEL(op, n);
+ break;
+ }
+ }
+ tif->tif_rawcp = (tidata_t) bp;
+ tif->tif_rawcc = cc;
+ if (npixels != maxpixels) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "ThunderDecode: %s data at scanline %ld (%lu != %lu)",
+ npixels < maxpixels ? "Not enough" : "Too much",
+ (long) tif->tif_row, (long) npixels, (long) maxpixels);
+ return (0);
+ }
+ return (1);
+}
+
+static int
+ThunderDecodeRow(TIFF* tif, tidata_t buf, tsize_t occ, tsample_t s)
+{
+ tidata_t row = buf;
+
+ (void) s;
+ while ((long)occ > 0) {
+ if (!ThunderDecode(tif, row, tif->tif_dir.td_imagewidth))
+ return (0);
+ occ -= tif->tif_scanlinesize;
+ row += tif->tif_scanlinesize;
+ }
+ return (1);
+}
+
+int
+TIFFInitThunderScan(TIFF* tif, int scheme)
+{
+ (void) scheme;
+ tif->tif_decoderow = ThunderDecodeRow;
+ tif->tif_decodestrip = ThunderDecodeRow;
+ return (1);
+}
+#endif /* THUNDER_SUPPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_tile.c b/Source/LibTIFF/tif_tile.c
new file mode 100644
index 0000000..adf0a39
--- /dev/null
+++ b/Source/LibTIFF/tif_tile.c
@@ -0,0 +1,273 @@
+/* $Id: tif_tile.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Tiled Image Support Routines.
+ */
+#include "tiffiop.h"
+
+static uint32
+summarize(TIFF* tif, size_t summand1, size_t summand2, const char* where)
+{
+ /*
+ * XXX: We are using casting to uint32 here, because sizeof(size_t)
+ * may be larger than sizeof(uint32) on 64-bit architectures.
+ */
+ uint32 bytes = summand1 + summand2;
+
+ if (bytes - summand1 != summand2) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
+ bytes = 0;
+ }
+
+ return (bytes);
+}
+
+static uint32
+multiply(TIFF* tif, size_t nmemb, size_t elem_size, const char* where)
+{
+ uint32 bytes = nmemb * elem_size;
+
+ if (elem_size && bytes / elem_size != nmemb) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Integer overflow in %s", where);
+ bytes = 0;
+ }
+
+ return (bytes);
+}
+
+/*
+ * Compute which tile an (x,y,z,s) value is in.
+ */
+ttile_t
+TIFFComputeTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ uint32 dx = td->td_tilewidth;
+ uint32 dy = td->td_tilelength;
+ uint32 dz = td->td_tiledepth;
+ ttile_t tile = 1;
+
+ if (td->td_imagedepth == 1)
+ z = 0;
+ if (dx == (uint32) -1)
+ dx = td->td_imagewidth;
+ if (dy == (uint32) -1)
+ dy = td->td_imagelength;
+ if (dz == (uint32) -1)
+ dz = td->td_imagedepth;
+ if (dx != 0 && dy != 0 && dz != 0) {
+ uint32 xpt = TIFFhowmany(td->td_imagewidth, dx);
+ uint32 ypt = TIFFhowmany(td->td_imagelength, dy);
+ uint32 zpt = TIFFhowmany(td->td_imagedepth, dz);
+
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ tile = (xpt*ypt*zpt)*s +
+ (xpt*ypt)*(z/dz) +
+ xpt*(y/dy) +
+ x/dx;
+ else
+ tile = (xpt*ypt)*(z/dz) + xpt*(y/dy) + x/dx;
+ }
+ return (tile);
+}
+
+/*
+ * Check an (x,y,z,s) coordinate
+ * against the image bounds.
+ */
+int
+TIFFCheckTile(TIFF* tif, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if (x >= td->td_imagewidth) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Col out of range, max %lu",
+ (unsigned long) x,
+ (unsigned long) (td->td_imagewidth - 1));
+ return (0);
+ }
+ if (y >= td->td_imagelength) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Row out of range, max %lu",
+ (unsigned long) y,
+ (unsigned long) (td->td_imagelength - 1));
+ return (0);
+ }
+ if (z >= td->td_imagedepth) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Depth out of range, max %lu",
+ (unsigned long) z,
+ (unsigned long) (td->td_imagedepth - 1));
+ return (0);
+ }
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE &&
+ s >= td->td_samplesperpixel) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%lu: Sample out of range, max %lu",
+ (unsigned long) s,
+ (unsigned long) (td->td_samplesperpixel - 1));
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Compute how many tiles are in an image.
+ */
+ttile_t
+TIFFNumberOfTiles(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ uint32 dx = td->td_tilewidth;
+ uint32 dy = td->td_tilelength;
+ uint32 dz = td->td_tiledepth;
+ ttile_t ntiles;
+
+ if (dx == (uint32) -1)
+ dx = td->td_imagewidth;
+ if (dy == (uint32) -1)
+ dy = td->td_imagelength;
+ if (dz == (uint32) -1)
+ dz = td->td_imagedepth;
+ ntiles = (dx == 0 || dy == 0 || dz == 0) ? 0 :
+ multiply(tif, multiply(tif, TIFFhowmany(td->td_imagewidth, dx),
+ TIFFhowmany(td->td_imagelength, dy),
+ "TIFFNumberOfTiles"),
+ TIFFhowmany(td->td_imagedepth, dz), "TIFFNumberOfTiles");
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ ntiles = multiply(tif, ntiles, td->td_samplesperpixel,
+ "TIFFNumberOfTiles");
+ return (ntiles);
+}
+
+/*
+ * Compute the # bytes in each row of a tile.
+ */
+tsize_t
+TIFFTileRowSize(TIFF* tif)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t rowsize;
+
+ if (td->td_tilelength == 0 || td->td_tilewidth == 0)
+ return ((tsize_t) 0);
+ rowsize = multiply(tif, td->td_bitspersample, td->td_tilewidth,
+ "TIFFTileRowSize");
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG)
+ rowsize = multiply(tif, rowsize, td->td_samplesperpixel,
+ "TIFFTileRowSize");
+ return ((tsize_t) TIFFhowmany8(rowsize));
+}
+
+/*
+ * Compute the # bytes in a variable length, row-aligned tile.
+ */
+tsize_t
+TIFFVTileSize(TIFF* tif, uint32 nrows)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ tsize_t tilesize;
+
+ if (td->td_tilelength == 0 || td->td_tilewidth == 0 ||
+ td->td_tiledepth == 0)
+ return ((tsize_t) 0);
+ if (td->td_planarconfig == PLANARCONFIG_CONTIG &&
+ td->td_photometric == PHOTOMETRIC_YCBCR &&
+ !isUpSampled(tif)) {
+ /*
+ * Packed YCbCr data contain one Cb+Cr for every
+ * HorizontalSampling*VerticalSampling Y values.
+ * Must also roundup width and height when calculating
+ * since images that are not a multiple of the
+ * horizontal/vertical subsampling area include
+ * YCbCr data for the extended image.
+ */
+ tsize_t w =
+ TIFFroundup(td->td_tilewidth, td->td_ycbcrsubsampling[0]);
+ tsize_t rowsize =
+ TIFFhowmany8(multiply(tif, w, td->td_bitspersample,
+ "TIFFVTileSize"));
+ tsize_t samplingarea =
+ td->td_ycbcrsubsampling[0]*td->td_ycbcrsubsampling[1];
+ if (samplingarea == 0) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Invalid YCbCr subsampling");
+ return 0;
+ }
+ nrows = TIFFroundup(nrows, td->td_ycbcrsubsampling[1]);
+ /* NB: don't need TIFFhowmany here 'cuz everything is rounded */
+ tilesize = multiply(tif, nrows, rowsize, "TIFFVTileSize");
+ tilesize = summarize(tif, tilesize,
+ multiply(tif, 2, tilesize / samplingarea,
+ "TIFFVTileSize"),
+ "TIFFVTileSize");
+ } else
+ tilesize = multiply(tif, nrows, TIFFTileRowSize(tif),
+ "TIFFVTileSize");
+ return ((tsize_t)
+ multiply(tif, tilesize, td->td_tiledepth, "TIFFVTileSize"));
+}
+
+/*
+ * Compute the # bytes in a row-aligned tile.
+ */
+tsize_t
+TIFFTileSize(TIFF* tif)
+{
+ return (TIFFVTileSize(tif, tif->tif_dir.td_tilelength));
+}
+
+/*
+ * Compute a default tile size based on the image
+ * characteristics and a requested value. If a
+ * request is <1 then we choose a size according
+ * to certain heuristics.
+ */
+void
+TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+ (*tif->tif_deftilesize)(tif, tw, th);
+}
+
+void
+_TIFFDefaultTileSize(TIFF* tif, uint32* tw, uint32* th)
+{
+ (void) tif;
+ if (*(int32*) tw < 1)
+ *tw = 256;
+ if (*(int32*) th < 1)
+ *th = 256;
+ /* roundup to a multiple of 16 per the spec */
+ if (*tw & 0xf)
+ *tw = TIFFroundup(*tw, 16);
+ if (*th & 0xf)
+ *th = TIFFroundup(*th, 16);
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_unix.c b/Source/LibTIFF/tif_unix.c
new file mode 100644
index 0000000..e123b5e
--- /dev/null
+++ b/Source/LibTIFF/tif_unix.c
@@ -0,0 +1,293 @@
+/* $Id: tif_unix.c,v 1.25 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library UNIX-specific Routines. These are should also work with the
+ * Windows Common RunTime Library.
+ */
+#include "tif_config.h"
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_IO_H
+# include <io.h>
+#endif
+
+#include "tiffiop.h"
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((tsize_t) read((int) fd, buf, (size_t) size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return ((tsize_t) write((int) fd, buf, (size_t) size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (close((int) fd));
+}
+
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+#ifdef _AM29K
+ long fsize;
+ return ((fsize = lseek((int) fd, 0, SEEK_END)) < 0 ? 0 : fsize);
+#else
+ struct stat sb;
+ return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+#endif
+}
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ toff_t size = _tiffSizeProc(fd);
+ if (size != (toff_t) -1) {
+ *pbase = (tdata_t)
+ mmap(0, size, PROT_READ, MAP_SHARED, (int) fd, 0);
+ if (*pbase != (tdata_t) -1) {
+ *psize = size;
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ (void) fd;
+ (void) munmap(base, (off_t) size);
+}
+#else /* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ (void) fd; (void) pbase; (void) psize;
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ (void) fd; (void) base; (void) size;
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc,
+ _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+ _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+ TIFF* tif;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+
+/* for cygwin and mingw */
+#ifdef O_BINARY
+ m |= O_BINARY;
+#endif
+
+#ifdef _AM29K
+ fd = open(name, m);
+#else
+ fd = open(name, m, 0666);
+#endif
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ tif = TIFFFdOpen((int)fd, name, mode);
+ if(!tif)
+ close(fd);
+ return tif;
+}
+
+#ifdef __WIN32__
+#include <windows.h>
+/*
+ * Open a TIFF file with a Unicode filename, for read/writing.
+ */
+TIFF*
+TIFFOpenW(const wchar_t* name, const char* mode)
+{
+ static const char module[] = "TIFFOpenW";
+ int m, fd;
+ int mbsize;
+ char *mbname;
+ TIFF* tif;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+
+/* for cygwin and mingw */
+#ifdef O_BINARY
+ m |= O_BINARY;
+#endif
+
+ fd = _wopen(name, m, 0666);
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ mbname = NULL;
+ mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
+ if (mbsize > 0) {
+ mbname = _TIFFmalloc(mbsize);
+ if (!mbname) {
+ TIFFErrorExt(0, module,
+ "Can't allocate space for filename conversion buffer");
+ return ((TIFF*)0);
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
+ NULL, NULL);
+ }
+
+ tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "<unknown>",
+ mode);
+
+ _TIFFfree(mbname);
+
+ if(!tif)
+ close(fd);
+ return tif;
+}
+#endif
+
+void*
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+void*
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+static void
+unixWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFwarningHandler = unixWarningHandler;
+
+static void
+unixErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+TIFFErrorHandler _TIFFerrorHandler = unixErrorHandler;
diff --git a/Source/LibTIFF/tif_version.c b/Source/LibTIFF/tif_version.c
new file mode 100644
index 0000000..0d7f4e3
--- /dev/null
+++ b/Source/LibTIFF/tif_version.c
@@ -0,0 +1,33 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_version.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+/*
+ * Copyright (c) 1992-1997 Sam Leffler
+ * Copyright (c) 1992-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+#include "tiffiop.h"
+
+static const char TIFFVersion[] = TIFFLIB_VERSION_STR;
+
+const char*
+TIFFGetVersion(void)
+{
+ return (TIFFVersion);
+}
diff --git a/Source/LibTIFF/tif_vms.c b/Source/LibTIFF/tif_vms.c
new file mode 100644
index 0000000..cdbd32c
--- /dev/null
+++ b/Source/LibTIFF/tif_vms.c
@@ -0,0 +1,588 @@
+/* $Id: tif_vms.c,v 1.12 2009/07/14 21:10:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library VMS-specific Routines.
+ */
+
+#include <stdlib.h>
+#include <unixio.h>
+#include "tiffiop.h"
+#if !HAVE_IEEEFP
+#include <math.h>
+#endif
+
+#ifdef VAXC
+#define NOSHARE noshare
+#else
+#define NOSHARE
+#endif
+
+#ifdef __alpha
+/* Dummy entry point for backwards compatibility */
+void TIFFModeCCITTFax3(void){}
+#endif
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (read((int) fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (write((int) fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return ((toff_t) lseek((int) fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (close((int) fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ struct stat sb;
+ return (toff_t) (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+#ifdef HAVE_MMAP
+#include <starlet.h>
+#include <fab.h>
+#include <secdef.h>
+
+/*
+ * Table for storing information on current open sections.
+ * (Should really be a linked list)
+ */
+#define MAX_MAPPED 100
+static int no_mapped = 0;
+static struct {
+ char *base;
+ char *top;
+ unsigned short channel;
+} map_table[MAX_MAPPED];
+
+/*
+ * This routine maps a file into a private section. Note that this
+ * method of accessing a file is by far the fastest under VMS.
+ * The routine may fail (i.e. return 0) for several reasons, for
+ * example:
+ * - There is no more room for storing the info on sections.
+ * - The process is out of open file quota, channels, ...
+ * - fd does not describe an opened file.
+ * - The file is already opened for write access by this process
+ * or another process
+ * - There is no free "hole" in virtual memory that fits the
+ * size of the file
+ */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ char name[256];
+ struct FAB fab;
+ unsigned short channel;
+ char *inadr[2], *retadr[2];
+ unsigned long status;
+ long size;
+
+ if (no_mapped >= MAX_MAPPED)
+ return(0);
+ /*
+ * We cannot use a file descriptor, we
+ * must open the file once more.
+ */
+ if (getname((int)fd, name, 1) == NULL)
+ return(0);
+ /* prepare the FAB for a user file open */
+ fab = cc$rms_fab;
+ fab.fab$l_fop |= FAB$V_UFO;
+ fab.fab$b_fac = FAB$M_GET;
+ fab.fab$b_shr = FAB$M_SHRGET;
+ fab.fab$l_fna = name;
+ fab.fab$b_fns = strlen(name);
+ status = sys$open(&fab); /* open file & get channel number */
+ if ((status&1) == 0)
+ return(0);
+ channel = (unsigned short)fab.fab$l_stv;
+ inadr[0] = inadr[1] = (char *)0; /* just an address in P0 space */
+ /*
+ * Map the blocks of the file up to
+ * the EOF block into virtual memory.
+ */
+ size = _tiffSizeProc(fd);
+ status = sys$crmpsc(inadr, retadr, 0, SEC$M_EXPREG, 0,0,0, channel,
+ TIFFhowmany(size,512), 0,0,0);
+ if ((status&1) == 0){
+ sys$dassgn(channel);
+ return(0);
+ }
+ *pbase = (tdata_t) retadr[0]; /* starting virtual address */
+ /*
+ * Use the size of the file up to the
+ * EOF mark for UNIX compatibility.
+ */
+ *psize = (toff_t) size;
+ /* Record the section in the table */
+ map_table[no_mapped].base = retadr[0];
+ map_table[no_mapped].top = retadr[1];
+ map_table[no_mapped].channel = channel;
+ no_mapped++;
+
+ return(1);
+}
+
+/*
+ * This routine unmaps a section from the virtual address space of
+ * the process, but only if the base was the one returned from a
+ * call to TIFFMapFileContents.
+ */
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ char *inadr[2];
+ int i, j;
+
+ /* Find the section in the table */
+ for (i = 0;i < no_mapped; i++) {
+ if (map_table[i].base == (char *) base) {
+ /* Unmap the section */
+ inadr[0] = (char *) base;
+ inadr[1] = map_table[i].top;
+ sys$deltva(inadr, 0, 0);
+ sys$dassgn(map_table[i].channel);
+ /* Remove this section from the list */
+ for (j = i+1; j < no_mapped; j++)
+ map_table[j-1] = map_table[j];
+ no_mapped--;
+ return;
+ }
+ }
+}
+#else /* !HAVE_MMAP */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+#endif /* !HAVE_MMAP */
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+ if (m&O_TRUNC){
+ /*
+ * There is a bug in open in VAXC. If you use
+ * open w/ m=O_RDWR|O_CREAT|O_TRUNC the
+ * wrong thing happens. On the other hand
+ * creat does the right thing.
+ */
+ fd = creat((char *) /* bug in stdio.h */ name, 0666,
+ "alq = 128", "deq = 64", "mbc = 32",
+ "fop = tef");
+ } else if (m&O_RDWR) {
+ fd = open(name, m, 0666,
+ "deq = 64", "mbc = 32", "fop = tef", "ctx = stm");
+ } else
+ fd = open(name, m, 0666, "mbc = 32", "ctx = stm");
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF*)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (malloc((size_t) s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ free(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (realloc(p, (size_t) s));
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ memset(p, v, (size_t) c);
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ return (memcmp(p1, p2, (size_t) c));
+}
+
+/*
+ * On the VAX, we need to make those global, writable pointers
+ * non-shareable, otherwise they would be made shareable by default.
+ * On the AXP, this brain damage has been corrected.
+ *
+ * I (Karsten Spang, krs@kampsax.dk) have dug around in the GCC
+ * manual and the GAS code and have come up with the following
+ * construct, but I don't have GCC on my VAX, so it is untested.
+ * Please tell me if it does not work.
+ */
+
+static void
+vmsWarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFwarningHandler = vmsWarningHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFwarningHandler")
+#endif
+;
+
+static void
+vmsErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+}
+
+NOSHARE TIFFErrorHandler _TIFFerrorHandler = vmsErrorHandler
+#if defined(VAX) && defined(__GNUC__)
+asm("_$$PsectAttributes_NOSHR$$_TIFFerrorHandler")
+#endif
+;
+
+
+#if !HAVE_IEEEFP
+/* IEEE floting point handling */
+
+typedef struct ieeedouble {
+ unsigned long mant2; /* fix NDR: full 8-byte swap */
+ unsigned long mant : 20,
+ exp : 11,
+ sign : 1;
+} ieeedouble;
+typedef struct ieeefloat {
+ unsigned long mant : 23,
+ exp : 8,
+ sign : 1;
+} ieeefloat;
+
+/*
+ * NB: These are D_FLOAT's, not G_FLOAT's. A G_FLOAT is
+ * simply a reverse-IEEE float/double.
+ */
+
+typedef struct {
+ unsigned long mant1 : 7,
+ exp : 8,
+ sign : 1,
+ mant2 : 16,
+ mant3 : 16,
+ mant4 : 16;
+} nativedouble;
+typedef struct {
+ unsigned long mant1 : 7,
+ exp : 8,
+ sign : 1,
+ mant2 : 16;
+} nativefloat;
+
+typedef union {
+ ieeedouble ieee;
+ nativedouble native;
+ char b[8];
+ uint32 l[2];
+ double d;
+} double_t;
+
+typedef union {
+ ieeefloat ieee;
+ nativefloat native;
+ char b[4];
+ uint32 l;
+ float f;
+} float_t;
+
+#if defined(VAXC) || defined(DECC)
+#pragma inline(ieeetod,dtoieee)
+#endif
+
+/*
+ * Convert an IEEE double precision number to native double precision.
+ * The source is contained in two longwords, the second holding the sign,
+ * exponent and the higher order bits of the mantissa, and the first
+ * holding the rest of the mantissa as follows:
+ * (Note: It is assumed that the number has been eight-byte swapped to
+ * LSB first.)
+ *
+ * First longword:
+ * 32 least significant bits of mantissa
+ * Second longword:
+ * 0-19: 20 most significant bits of mantissa
+ * 20-30: exponent
+ * 31: sign
+ * The exponent is stored as excess 1023.
+ * The most significant bit of the mantissa is implied 1, and not stored.
+ * If the exponent and mantissa are zero, the number is zero.
+ * If the exponent is 0 (i.e. -1023) and the mantissa is non-zero, it is an
+ * unnormalized number with the most significant bit NOT implied.
+ * If the exponent is 2047, the number is invalid, in case the mantissa is zero,
+ * this means overflow (+/- depending of the sign bit), otherwise
+ * it simply means invalid number.
+ *
+ * If the number is too large for the machine or was specified as overflow,
+ * +/-HUGE_VAL is returned.
+ */
+INLINE static void
+ieeetod(double *dp)
+{
+ double_t source;
+ long sign,exp,mant;
+ double dmant;
+
+ source.ieee = ((double_t*)dp)->ieee;
+ sign = source.ieee.sign;
+ exp = source.ieee.exp;
+ mant = source.ieee.mant;
+
+ if (exp == 2047) {
+ if (mant) /* Not a Number (NAN) */
+ *dp = HUGE_VAL;
+ else /* +/- infinity */
+ *dp = (sign ? -HUGE_VAL : HUGE_VAL);
+ return;
+ }
+ if (!exp) {
+ if (!(mant || source.ieee.mant2)) { /* zero */
+ *dp=0;
+ return;
+ } else { /* Unnormalized number */
+ /* NB: not -1023, the 1 bit is not implied */
+ exp= -1022;
+ }
+ } else {
+ mant |= 1<<20;
+ exp -= 1023;
+ }
+ dmant = (((double) mant) +
+ ((double) source.ieee.mant2) / (((double) (1<<16)) *
+ ((double) (1<<16)))) / (double) (1<<20);
+ dmant = ldexp(dmant, exp);
+ if (sign)
+ dmant= -dmant;
+ *dp = dmant;
+}
+
+INLINE static void
+dtoieee(double *dp)
+{
+ double_t num;
+ double x;
+ int exp;
+
+ num.d = *dp;
+ if (!num.d) { /* Zero is just binary all zeros */
+ num.l[0] = num.l[1] = 0;
+ return;
+ }
+
+ if (num.d < 0) { /* Sign is encoded separately */
+ num.d = -num.d;
+ num.ieee.sign = 1;
+ } else {
+ num.ieee.sign = 0;
+ }
+
+ /* Now separate the absolute value into mantissa and exponent */
+ x = frexp(num.d, &exp);
+
+ /*
+ * Handle cases where the value is outside the
+ * range for IEEE floating point numbers.
+ * (Overflow cannot happen on a VAX, but underflow
+ * can happen for G float.)
+ */
+ if (exp < -1022) { /* Unnormalized number */
+ x = ldexp(x, -1023-exp);
+ exp = 0;
+ } else if (exp > 1023) { /* +/- infinity */
+ x = 0;
+ exp = 2047;
+ } else { /* Get rid of most significant bit */
+ x *= 2;
+ x -= 1;
+ exp += 1022; /* fix NDR: 1.0 -> x=0.5, exp=1 -> ieee.exp = 1023 */
+ }
+ num.ieee.exp = exp;
+
+ x *= (double) (1<<20);
+ num.ieee.mant = (long) x;
+ x -= (double) num.ieee.mant;
+ num.ieee.mant2 = (long) (x*((double) (1<<16)*(double) (1<<16)));
+
+ if (!(num.ieee.mant || num.ieee.exp || num.ieee.mant2)) {
+ /* Avoid negative zero */
+ num.ieee.sign = 0;
+ }
+ ((double_t*)dp)->ieee = num.ieee;
+}
+
+/*
+ * Beware, these do not handle over/under-flow
+ * during conversion from ieee to native format.
+ */
+#define NATIVE2IEEEFLOAT(fp) { \
+ float_t t; \
+ if (t.ieee.exp = (fp)->native.exp) \
+ t.ieee.exp += -129 + 127; \
+ t.ieee.sign = (fp)->native.sign; \
+ t.ieee.mant = ((fp)->native.mant1<<16)|(fp)->native.mant2; \
+ *(fp) = t; \
+}
+#define IEEEFLOAT2NATIVE(fp) { \
+ float_t t; int v = (fp)->ieee.exp; \
+ if (v) v += -127 + 129; /* alter bias of exponent */\
+ t.native.exp = v; /* implicit truncation of exponent */\
+ t.native.sign = (fp)->ieee.sign; \
+ v = (fp)->ieee.mant; \
+ t.native.mant1 = v >> 16; \
+ t.native.mant2 = v;\
+ *(fp) = t; \
+}
+
+#define IEEEDOUBLE2NATIVE(dp) ieeetod(dp)
+
+#define NATIVE2IEEEDOUBLE(dp) dtoieee(dp)
+
+
+/*
+ * These unions are used during floating point
+ * conversions. The above macros define the
+ * conversion operations.
+ */
+void
+TIFFCvtIEEEFloatToNative(TIFF* tif, u_int n, float* f)
+{
+ float_t* fp = (float_t*) f;
+
+ while (n-- > 0) {
+ IEEEFLOAT2NATIVE(fp);
+ fp++;
+ }
+}
+
+void
+TIFFCvtNativeToIEEEFloat(TIFF* tif, u_int n, float* f)
+{
+ float_t* fp = (float_t*) f;
+
+ while (n-- > 0) {
+ NATIVE2IEEEFLOAT(fp);
+ fp++;
+ }
+}
+void
+TIFFCvtIEEEDoubleToNative(TIFF* tif, u_int n, double* f)
+{
+ double_t* fp = (double_t*) f;
+
+ while (n-- > 0) {
+ IEEEDOUBLE2NATIVE(fp);
+ fp++;
+ }
+}
+
+void
+TIFFCvtNativeToIEEEDouble(TIFF* tif, u_int n, double* f)
+{
+ double_t* fp = (double_t*) f;
+
+ while (n-- > 0) {
+ NATIVE2IEEEDOUBLE(fp);
+ fp++;
+ }
+}
+#endif
diff --git a/Source/LibTIFF/tif_warning.c b/Source/LibTIFF/tif_warning.c
new file mode 100644
index 0000000..7e2fd96
--- /dev/null
+++ b/Source/LibTIFF/tif_warning.c
@@ -0,0 +1,74 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_warning.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ */
+#include "tiffiop.h"
+
+TIFFErrorHandlerExt _TIFFwarningHandlerExt = NULL;
+
+TIFFErrorHandler
+TIFFSetWarningHandler(TIFFErrorHandler handler)
+{
+ TIFFErrorHandler prev = _TIFFwarningHandler;
+ _TIFFwarningHandler = handler;
+ return (prev);
+}
+
+TIFFErrorHandlerExt
+TIFFSetWarningHandlerExt(TIFFErrorHandlerExt handler)
+{
+ TIFFErrorHandlerExt prev = _TIFFwarningHandlerExt;
+ _TIFFwarningHandlerExt = handler;
+ return (prev);
+}
+
+void
+TIFFWarning(const char* module, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (_TIFFwarningHandler)
+ (*_TIFFwarningHandler)(module, fmt, ap);
+ if (_TIFFwarningHandlerExt)
+ (*_TIFFwarningHandlerExt)(0, module, fmt, ap);
+ va_end(ap);
+}
+
+void
+TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (_TIFFwarningHandler)
+ (*_TIFFwarningHandler)(module, fmt, ap);
+ if (_TIFFwarningHandlerExt)
+ (*_TIFFwarningHandlerExt)(fd, module, fmt, ap);
+ va_end(ap);
+}
+
+
diff --git a/Source/LibTIFF/tif_win3.c b/Source/LibTIFF/tif_win3.c
new file mode 100644
index 0000000..d526dff
--- /dev/null
+++ b/Source/LibTIFF/tif_win3.c
@@ -0,0 +1,225 @@
+/* $Header: /cvsroot/freeimage/FreeImage/Source/LibTIFF/tif_win3.c,v 1.25 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Windows 3.x-specific Routines.
+ */
+#include "tiffiop.h"
+#if defined(__WATCOMC__) || defined(__BORLANDC__) || defined(_MSC_VER)
+#include <io.h> /* for open, close, etc. function prototypes */
+#endif
+
+#include <windows.h>
+#include <windowsx.h>
+#include <memory.h>
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (_hread(fd, buf, size));
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ return (_hwrite(fd, buf, size));
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ return (_llseek(fd, (off_t) off, whence));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (_lclose(fd));
+}
+
+#include <sys/stat.h>
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ struct stat sb;
+ return (fstat((int) fd, &sb) < 0 ? 0 : sb.st_size);
+}
+
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ return (0);
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ */
+TIFF*
+TIFFFdOpen(int fd, const char* name, const char* mode)
+{
+ TIFF* tif;
+
+ tif = TIFFClientOpen(name, mode,
+ (thandle_t) fd,
+ _tiffReadProc, _tiffWriteProc, _tiffSeekProc, _tiffCloseProc,
+ _tiffSizeProc, _tiffMapProc, _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
+}
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ int m, fd;
+ OFSTRUCT of;
+ int mm = 0;
+
+ m = _TIFFgetMode(mode, module);
+ if (m == -1)
+ return ((TIFF*)0);
+ if (m & O_CREAT) {
+ if ((m & O_TRUNC) || OpenFile(name, &of, OF_EXIST) != HFILE_ERROR)
+ mm |= OF_CREATE;
+ }
+ if (m & O_WRONLY)
+ mm |= OF_WRITE;
+ if (m & O_RDWR)
+ mm |= OF_READWRITE;
+ fd = OpenFile(name, &of, mm);
+ if (fd < 0) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF*)0);
+ }
+ return (TIFFFdOpen(fd, name, mode));
+}
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return (tdata_t) GlobalAllocPtr(GHND, (DWORD) s);
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ GlobalFreePtr(p);
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ return (tdata_t) GlobalReAllocPtr(p, (DWORD) s, GHND);
+}
+
+void
+_TIFFmemset(tdata_t p, int v, tsize_t c)
+{
+ char* pp = (char*) p;
+
+ while (c > 0) {
+ tsize_t chunk = 0x10000 - ((uint32) pp & 0xffff);/* What's left in segment */
+ if (chunk > 0xff00) /* No more than 0xff00 */
+ chunk = 0xff00;
+ if (chunk > c) /* No more than needed */
+ chunk = c;
+ memset(pp, v, chunk);
+ pp = (char*) (chunk + (char huge*) pp);
+ c -= chunk;
+ }
+}
+
+void
+_TIFFmemcpy(tdata_t d, const tdata_t s, tsize_t c)
+{
+ if (c > 0xFFFF)
+ hmemcpy((void _huge*) d, (void _huge*) s, c);
+ else
+ (void) memcpy(d, s, (size_t) c);
+}
+
+int
+_TIFFmemcmp(const tdata_t d, const tdata_t s, tsize_t c)
+{
+ char* dd = (char*) d;
+ char* ss = (char*) s;
+ tsize_t chunks, chunkd, chunk;
+ int result;
+
+ while (c > 0) {
+ chunks = 0x10000 - ((uint32) ss & 0xffff); /* What's left in segment */
+ chunkd = 0x10000 - ((uint32) dd & 0xffff); /* What's left in segment */
+ chunk = c; /* Get the largest of */
+ if (chunk > chunks) /* c, chunks, chunkd, */
+ chunk = chunks; /* 0xff00 */
+ if (chunk > chunkd)
+ chunk = chunkd;
+ if (chunk > 0xff00)
+ chunk = 0xff00;
+ result = memcmp(dd, ss, chunk);
+ if (result != 0)
+ return (result);
+ dd = (char*) (chunk + (char huge*) dd);
+ ss = (char*) (chunk + (char huge*) ss);
+ c -= chunk;
+ }
+ return (0);
+}
+
+static void
+win3WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ char e[512] = { '\0' };
+ if (module != NULL)
+ strcat(strcpy(e, module), ":");
+ vsprintf(e+strlen(e), fmt, ap);
+ strcat(e, ".");
+ MessageBox(GetActiveWindow(), e, "LibTIFF Warning",
+ MB_OK|MB_ICONEXCLAMATION);
+}
+TIFFErrorHandler _TIFFwarningHandler = win3WarningHandler;
+
+static void
+win3ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ char e[512] = { '\0' };
+ if (module != NULL)
+ strcat(strcpy(e, module), ":");
+ vsprintf(e+strlen(e), fmt, ap);
+ strcat(e, ".");
+ MessageBox(GetActiveWindow(), e, "LibTIFF Error", MB_OK|MB_ICONSTOP);
+}
+TIFFErrorHandler _TIFFerrorHandler = win3ErrorHandler;
diff --git a/Source/LibTIFF/tif_win32.c b/Source/LibTIFF/tif_win32.c
new file mode 100644
index 0000000..177220d
--- /dev/null
+++ b/Source/LibTIFF/tif_win32.c
@@ -0,0 +1,401 @@
+/* $Id: tif_win32.c,v 1.25 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library Win32-specific Routines. Adapted from tif_unix.c 4/5/95 by
+ * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
+ */
+#include "tiffiop.h"
+
+#include <windows.h>
+
+static tsize_t
+_tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ DWORD dwSizeRead;
+ if (!ReadFile(fd, buf, size, &dwSizeRead, NULL))
+ return(0);
+ return ((tsize_t) dwSizeRead);
+}
+
+static tsize_t
+_tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
+{
+ DWORD dwSizeWritten;
+ if (!WriteFile(fd, buf, size, &dwSizeWritten, NULL))
+ return(0);
+ return ((tsize_t) dwSizeWritten);
+}
+
+static toff_t
+_tiffSeekProc(thandle_t fd, toff_t off, int whence)
+{
+ ULARGE_INTEGER li;
+ DWORD dwMoveMethod;
+
+ li.QuadPart = off;
+
+ switch(whence)
+ {
+ case SEEK_SET:
+ dwMoveMethod = FILE_BEGIN;
+ break;
+ case SEEK_CUR:
+ dwMoveMethod = FILE_CURRENT;
+ break;
+ case SEEK_END:
+ dwMoveMethod = FILE_END;
+ break;
+ default:
+ dwMoveMethod = FILE_BEGIN;
+ break;
+ }
+ return ((toff_t)SetFilePointer(fd, (LONG) li.LowPart,
+ (PLONG)&li.HighPart, dwMoveMethod));
+}
+
+static int
+_tiffCloseProc(thandle_t fd)
+{
+ return (CloseHandle(fd) ? 0 : -1);
+}
+
+static toff_t
+_tiffSizeProc(thandle_t fd)
+{
+ return ((toff_t)GetFileSize(fd, NULL));
+}
+
+static int
+_tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ (void) fd;
+ (void) pbase;
+ (void) psize;
+ return (0);
+}
+
+/*
+ * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>:
+ *
+ * Windows uses both a handle and a pointer for file mapping,
+ * but according to the SDK documentation and Richter's book
+ * "Advanced Windows Programming" it is safe to free the handle
+ * after obtaining the file mapping pointer
+ *
+ * This removes a nasty OS dependency and cures a problem
+ * with Visual C++ 5.0
+ */
+static int
+_tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
+{
+ toff_t size;
+ HANDLE hMapFile;
+
+ if ((size = _tiffSizeProc(fd)) == 0xFFFFFFFF)
+ return (0);
+ hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL);
+ if (hMapFile == NULL)
+ return (0);
+ *pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(hMapFile);
+ if (*pbase == NULL)
+ return (0);
+ *psize = size;
+ return(1);
+}
+
+static void
+_tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ (void) fd;
+ (void) base;
+ (void) size;
+}
+
+static void
+_tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
+{
+ UnmapViewOfFile(base);
+}
+
+/*
+ * Open a TIFF file descriptor for read/writing.
+ * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
+ * string, which forces the file to be opened unmapped.
+ */
+TIFF*
+TIFFFdOpen(int ifd, const char* name, const char* mode)
+{
+ TIFF* tif;
+ BOOL fSuppressMap = (mode[1] == 'u' || (mode[1]!=0 && mode[2] == 'u'));
+
+ tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
+ _tiffReadProc, _tiffWriteProc,
+ _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
+ fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
+ fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
+ if (tif)
+ tif->tif_fd = ifd;
+ return (tif);
+}
+
+#ifndef _WIN32_WCE
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ thandle_t fd;
+ int m;
+ DWORD dwMode;
+ TIFF* tif;
+
+ m = _TIFFgetMode(mode, module);
+
+ switch(m)
+ {
+ case O_RDONLY:
+ dwMode = OPEN_EXISTING;
+ break;
+ case O_RDWR:
+ dwMode = OPEN_ALWAYS;
+ break;
+ case O_RDWR|O_CREAT:
+ dwMode = OPEN_ALWAYS;
+ break;
+ case O_RDWR|O_TRUNC:
+ dwMode = CREATE_ALWAYS;
+ break;
+ case O_RDWR|O_CREAT|O_TRUNC:
+ dwMode = CREATE_ALWAYS;
+ break;
+ default:
+ return ((TIFF*)0);
+ }
+ fd = (thandle_t)CreateFileA(name,
+ (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
+ (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ tif = TIFFFdOpen((int)fd, name, mode);
+ if(!tif)
+ CloseHandle(fd);
+ return tif;
+}
+
+/*
+ * Open a TIFF file with a Unicode filename, for read/writing.
+ */
+TIFF*
+TIFFOpenW(const wchar_t* name, const char* mode)
+{
+ static const char module[] = "TIFFOpenW";
+ thandle_t fd;
+ int m;
+ DWORD dwMode;
+ int mbsize;
+ char *mbname;
+ TIFF *tif;
+
+ m = _TIFFgetMode(mode, module);
+
+ switch(m) {
+ case O_RDONLY: dwMode = OPEN_EXISTING; break;
+ case O_RDWR: dwMode = OPEN_ALWAYS; break;
+ case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break;
+ case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break;
+ case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break;
+ default: return ((TIFF*)0);
+ }
+
+ fd = (thandle_t)CreateFileW(name,
+ (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
+ FILE_SHARE_READ, NULL, dwMode,
+ (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+ TIFFErrorExt(0, module, "%S: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ mbname = NULL;
+ mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
+ if (mbsize > 0) {
+ mbname = (char *)_TIFFmalloc(mbsize);
+ if (!mbname) {
+ TIFFErrorExt(0, module,
+ "Can't allocate space for filename conversion buffer");
+ return ((TIFF*)0);
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
+ NULL, NULL);
+ }
+
+ tif = TIFFFdOpen((int)fd,
+ (mbname != NULL) ? mbname : "<unknown>", mode);
+ if(!tif)
+ CloseHandle(fd);
+
+ _TIFFfree(mbname);
+
+ return tif;
+}
+
+#endif /* ndef _WIN32_WCE */
+
+
+tdata_t
+_TIFFmalloc(tsize_t s)
+{
+ return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
+}
+
+void
+_TIFFfree(tdata_t p)
+{
+ GlobalFree(p);
+ return;
+}
+
+tdata_t
+_TIFFrealloc(tdata_t p, tsize_t s)
+{
+ void* pvTmp;
+ tsize_t old;
+
+ if(p == NULL)
+ return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
+
+ old = GlobalSize(p);
+
+ if (old>=s) {
+ if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
+ CopyMemory(pvTmp, p, s);
+ GlobalFree(p);
+ }
+ } else {
+ if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
+ CopyMemory(pvTmp, p, old);
+ GlobalFree(p);
+ }
+ }
+ return ((tdata_t)pvTmp);
+}
+
+void
+_TIFFmemset(void* p, int v, tsize_t c)
+{
+ FillMemory(p, c, (BYTE)v);
+}
+
+void
+_TIFFmemcpy(void* d, const tdata_t s, tsize_t c)
+{
+ CopyMemory(d, s, c);
+}
+
+int
+_TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
+{
+ register const BYTE *pb1 = (const BYTE *) p1;
+ register const BYTE *pb2 = (const BYTE *) p2;
+ register DWORD dwTmp = c;
+ register int iTmp;
+ for (iTmp = 0; dwTmp-- && !iTmp; iTmp = (int)*pb1++ - (int)*pb2++)
+ ;
+ return (iTmp);
+}
+
+#ifndef _WIN32_WCE
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifndef TIF_PLATFORM_CONSOLE
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Warning";
+ LPCTSTR szDefaultModule = "LIBTIFF";
+ LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
+ strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
+ return;
+ sprintf(szTitle, szTitleText, szTmpModule);
+ szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
+ vsprintf(szTmp, fmt, ap);
+ MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ fprintf(stderr, "Warning, ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+}
+TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
+
+static void
+Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+#ifndef TIF_PLATFORM_CONSOLE
+ LPTSTR szTitle;
+ LPTSTR szTmp;
+ LPCTSTR szTitleText = "%s Error";
+ LPCTSTR szDefaultModule = "LIBTIFF";
+ LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
+ if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
+ strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
+ return;
+ sprintf(szTitle, szTitleText, szTmpModule);
+ szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
+ vsprintf(szTmp, fmt, ap);
+ MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
+ LocalFree(szTitle);
+ return;
+#else
+ if (module != NULL)
+ fprintf(stderr, "%s: ", module);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, ".\n");
+#endif
+}
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
+#endif /* ndef _WIN32_WCE */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_wince.c b/Source/LibTIFF/tif_wince.c
new file mode 100644
index 0000000..8825f8b
--- /dev/null
+++ b/Source/LibTIFF/tif_wince.c
@@ -0,0 +1,281 @@
+/* $Id: tif_wince.c,v 1.9 2009/07/14 21:10:27 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * Windows CE-specific routines for TIFF Library.
+ * Adapted from tif_win32.c 01/10/2006 by Mateusz Loskot (mateusz@loskot.net)
+ */
+
+#ifndef _WIN32_WCE
+# error "Only Windows CE target is supported!"
+#endif
+
+#include "tiffiop.h"
+#include <windows.h>
+
+/* Turn off console support on Windows CE. */
+#undef TIF_PLATFORM_CONSOLE
+
+
+/*
+ * Open a TIFF file for read/writing.
+ */
+TIFF*
+TIFFOpen(const char* name, const char* mode)
+{
+ static const char module[] = "TIFFOpen";
+ thandle_t fd;
+ int m;
+ DWORD dwMode;
+ TIFF* tif;
+ size_t nLen;
+ size_t nWideLen;
+ wchar_t* wchName;
+
+ m = _TIFFgetMode(mode, module);
+
+ switch(m)
+ {
+ case O_RDONLY:
+ dwMode = OPEN_EXISTING;
+ break;
+ case O_RDWR:
+ dwMode = OPEN_ALWAYS;
+ break;
+ case O_RDWR|O_CREAT:
+ dwMode = OPEN_ALWAYS;
+ break;
+ case O_RDWR|O_TRUNC:
+ dwMode = CREATE_ALWAYS;
+ break;
+ case O_RDWR|O_CREAT|O_TRUNC:
+ dwMode = CREATE_ALWAYS;
+ break;
+ default:
+ return ((TIFF*)0);
+ }
+
+ /* On Windows CE, CreateFile is mapped to CreateFileW,
+ * but file path is passed as char-based string,
+ * so the path has to be converted to wchar_t.
+ */
+
+ nWideLen = 0;
+ wchName = NULL;
+ nLen = strlen(name) + 1;
+
+ nWideLen = MultiByteToWideChar(CP_ACP, 0, name, nLen, NULL, 0);
+ wchName = (wchar_t*)malloc(sizeof(wchar_t) * nWideLen);
+ if (NULL == wchName)
+ {
+ TIFFErrorExt(0, module, "Memory allocation error!");
+ return ((TIFF *)0);
+ }
+ memset(wchName, 0, sizeof(wchar_t) * nWideLen);
+ MultiByteToWideChar(CP_ACP, 0, name, nLen, wchName, nWideLen);
+
+ fd = (thandle_t)CreateFile(wchName,
+ (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
+ (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ free(wchName);
+
+ if (fd == INVALID_HANDLE_VALUE) {
+ TIFFErrorExt(0, module, "%s: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ /* TODO - mloskot: change to TIFFdOpenW and pass wchar path */
+
+ tif = TIFFFdOpen((int)fd, name, mode);
+ if(!tif)
+ CloseHandle(fd);
+ return tif;
+}
+
+/*
+ * Open a TIFF file with a Unicode filename, for read/writing.
+ */
+TIFF*
+TIFFOpenW(const wchar_t* name, const char* mode)
+{
+ static const char module[] = "TIFFOpenW";
+ thandle_t fd;
+ int m;
+ DWORD dwMode;
+ int mbsize;
+ char *mbname;
+ TIFF *tif;
+
+ m = _TIFFgetMode(mode, module);
+
+ switch(m) {
+ case O_RDONLY: dwMode = OPEN_EXISTING; break;
+ case O_RDWR: dwMode = OPEN_ALWAYS; break;
+ case O_RDWR|O_CREAT: dwMode = OPEN_ALWAYS; break;
+ case O_RDWR|O_TRUNC: dwMode = CREATE_ALWAYS; break;
+ case O_RDWR|O_CREAT|O_TRUNC: dwMode = CREATE_ALWAYS; break;
+ default: return ((TIFF*)0);
+ }
+
+ /* On Windows CE, CreateFile is mapped to CreateFileW,
+ * so no conversion of wchar_t to char is required.
+ */
+
+ fd = (thandle_t)CreateFile(name,
+ (m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
+ FILE_SHARE_READ, NULL, dwMode,
+ (m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (fd == INVALID_HANDLE_VALUE) {
+ TIFFErrorExt(0, module, "%S: Cannot open", name);
+ return ((TIFF *)0);
+ }
+
+ mbname = NULL;
+ mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
+ if (mbsize > 0) {
+ mbname = (char *)_TIFFmalloc(mbsize);
+ if (!mbname) {
+ TIFFErrorExt(0, module,
+ "Can't allocate space for filename conversion buffer");
+ return ((TIFF*)0);
+ }
+
+ WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
+ NULL, NULL);
+ }
+
+ tif = TIFFFdOpen((int)fd,
+ (mbname != NULL) ? mbname : "<unknown>", mode);
+ if(!tif)
+ CloseHandle(fd);
+
+ _TIFFfree(mbname);
+
+ return tif;
+}
+
+static void
+Win32WarningHandler(const char* module, const char* fmt, va_list ap)
+{
+ /* On Windows CE, MessageBox is mapped to wide-char based MessageBoxW. */
+
+ size_t nWideLen = 0;
+ LPTSTR szWideTitle = NULL;
+ LPTSTR szWideMsg = NULL;
+
+ LPSTR szTitle;
+ LPSTR szTmp;
+ LPCSTR szTitleText = "%s Warning";
+ LPCSTR szDefaultModule = "LIBTIFF";
+ LPCSTR szTmpModule;
+
+ szTmpModule = (module == NULL) ? szDefaultModule : module;
+ if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED,
+ (strlen(szTmpModule) + strlen(szTitleText)
+ + strlen(fmt) + 128) * sizeof(char))) == NULL)
+ return;
+
+ sprintf(szTitle, szTitleText, szTmpModule);
+ szTmp = szTitle + (strlen(szTitle) + 2) * sizeof(char);
+ vsprintf(szTmp, fmt, ap);
+
+ /* Convert error message to Unicode. */
+
+ nWideLen = MultiByteToWideChar(CP_ACP, 0, szTitle, -1, NULL, 0);
+ szWideTitle = (wchar_t*)malloc(sizeof(wchar_t) * nWideLen);
+ MultiByteToWideChar(CP_ACP, 0, szTitle, -1, szWideTitle, nWideLen);
+
+ nWideLen = MultiByteToWideChar(CP_ACP, 0, szTmp, -1, NULL, 0);
+ szWideMsg = (wchar_t*)malloc(sizeof(wchar_t) * nWideLen);
+ MultiByteToWideChar(CP_ACP, 0, szTmp, -1, szWideMsg, nWideLen);
+
+ /* Display message */
+
+ MessageBox(GetFocus(), szWideMsg, szWideTitle, MB_OK | MB_ICONEXCLAMATION);
+
+ /* Free resources */
+
+ LocalFree(szTitle);
+ free(szWideMsg);
+ free(szWideTitle);
+}
+
+TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
+
+static void
+Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
+{
+ /* On Windows CE, MessageBox is mapped to wide-char based MessageBoxW. */
+
+ size_t nWideLen = 0;
+ LPTSTR szWideTitle = NULL;
+ LPTSTR szWideMsg = NULL;
+
+ LPSTR szTitle;
+ LPSTR szTmp;
+ LPCSTR szTitleText = "%s Error";
+ LPCSTR szDefaultModule = "LIBTIFF";
+ LPCSTR szTmpModule;
+
+ szTmpModule = (module == NULL) ? szDefaultModule : module;
+ if ((szTitle = (LPSTR)LocalAlloc(LMEM_FIXED,
+ (strlen(szTmpModule) + strlen(szTitleText)
+ + strlen(fmt) + 128) * sizeof(char))) == NULL)
+ return;
+
+ sprintf(szTitle, szTitleText, szTmpModule);
+ szTmp = szTitle + (strlen(szTitle) + 2) * sizeof(char);
+ vsprintf(szTmp, fmt, ap);
+
+ /* Convert error message to Unicode. */
+
+ nWideLen = MultiByteToWideChar(CP_ACP, 0, szTitle, -1, NULL, 0);
+ szWideTitle = (wchar_t*)malloc(sizeof(wchar_t) * nWideLen);
+ MultiByteToWideChar(CP_ACP, 0, szTitle, -1, szWideTitle, nWideLen);
+
+ nWideLen = MultiByteToWideChar(CP_ACP, 0, szTmp, -1, NULL, 0);
+ szWideMsg = (wchar_t*)malloc(sizeof(wchar_t) * nWideLen);
+ MultiByteToWideChar(CP_ACP, 0, szTmp, -1, szWideMsg, nWideLen);
+
+ /* Display message */
+
+ MessageBox(GetFocus(), szWideMsg, szWideTitle, MB_OK | MB_ICONEXCLAMATION);
+
+ /* Free resources */
+
+ LocalFree(szTitle);
+ free(szWideMsg);
+ free(szWideTitle);
+}
+
+TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
+
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_write.c b/Source/LibTIFF/tif_write.c
new file mode 100644
index 0000000..dec076d
--- /dev/null
+++ b/Source/LibTIFF/tif_write.c
@@ -0,0 +1,711 @@
+/* $Id: tif_write.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library.
+ *
+ * Scanline-oriented Write Support
+ */
+#include "tiffiop.h"
+#include <stdio.h>
+
+#define STRIPINCR 20 /* expansion factor on strip array */
+
+#define WRITECHECKSTRIPS(tif, module) \
+ (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),0,module))
+#define WRITECHECKTILES(tif, module) \
+ (((tif)->tif_flags&TIFF_BEENWRITING) || TIFFWriteCheck((tif),1,module))
+#define BUFFERCHECK(tif) \
+ ((((tif)->tif_flags & TIFF_BUFFERSETUP) && tif->tif_rawdata) || \
+ TIFFWriteBufferSetup((tif), NULL, (tsize_t) -1))
+
+static int TIFFGrowStrips(TIFF*, int, const char*);
+static int TIFFAppendToStrip(TIFF*, tstrip_t, tidata_t, tsize_t);
+
+int
+TIFFWriteScanline(TIFF* tif, tdata_t buf, uint32 row, tsample_t sample)
+{
+ static const char module[] = "TIFFWriteScanline";
+ register TIFFDirectory *td;
+ int status, imagegrew = 0;
+ tstrip_t strip;
+
+ if (!WRITECHECKSTRIPS(tif, module))
+ return (-1);
+ /*
+ * Handle delayed allocation of data buffer. This
+ * permits it to be sized more intelligently (using
+ * directory information).
+ */
+ if (!BUFFERCHECK(tif))
+ return (-1);
+ td = &tif->tif_dir;
+ /*
+ * Extend image length if needed
+ * (but only for PlanarConfig=1).
+ */
+ if (row >= td->td_imagelength) { /* extend image */
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Can not change \"ImageLength\" when using separate planes");
+ return (-1);
+ }
+ td->td_imagelength = row+1;
+ imagegrew = 1;
+ }
+ /*
+ * Calculate strip and check for crossings.
+ */
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ if (sample >= td->td_samplesperpixel) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "%d: Sample out of range, max %d",
+ sample, td->td_samplesperpixel);
+ return (-1);
+ }
+ strip = sample*td->td_stripsperimage + row/td->td_rowsperstrip;
+ } else
+ strip = row / td->td_rowsperstrip;
+ /*
+ * Check strip array to make sure there's space. We don't support
+ * dynamically growing files that have data organized in separate
+ * bitplanes because it's too painful. In that case we require that
+ * the imagelength be set properly before the first write (so that the
+ * strips array will be fully allocated above).
+ */
+ if (strip >= td->td_nstrips && !TIFFGrowStrips(tif, 1, module))
+ return (-1);
+ if (strip != tif->tif_curstrip) {
+ /*
+ * Changing strips -- flush any data present.
+ */
+ if (!TIFFFlushData(tif))
+ return (-1);
+ tif->tif_curstrip = strip;
+ /*
+ * Watch out for a growing image. The value of strips/image
+ * will initially be 1 (since it can't be deduced until the
+ * imagelength is known).
+ */
+ if (strip >= td->td_stripsperimage && imagegrew)
+ td->td_stripsperimage =
+ TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
+ tif->tif_row =
+ (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+ if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+ if (!(*tif->tif_setupencode)(tif))
+ return (-1);
+ tif->tif_flags |= TIFF_CODERSETUP;
+ }
+
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+
+ if( td->td_stripbytecount[strip] > 0 )
+ {
+ /* if we are writing over existing tiles, zero length */
+ td->td_stripbytecount[strip] = 0;
+
+ /* this forces TIFFAppendToStrip() to do a seek */
+ tif->tif_curoff = 0;
+ }
+
+ if (!(*tif->tif_preencode)(tif, sample))
+ return (-1);
+ tif->tif_flags |= TIFF_POSTENCODE;
+ }
+ /*
+ * Ensure the write is either sequential or at the
+ * beginning of a strip (or that we can randomly
+ * access the data -- i.e. no encoding).
+ */
+ if (row != tif->tif_row) {
+ if (row < tif->tif_row) {
+ /*
+ * Moving backwards within the same strip:
+ * backup to the start and then decode
+ * forward (below).
+ */
+ tif->tif_row = (strip % td->td_stripsperimage) *
+ td->td_rowsperstrip;
+ tif->tif_rawcp = tif->tif_rawdata;
+ }
+ /*
+ * Seek forward to the desired row.
+ */
+ if (!(*tif->tif_seek)(tif, row - tif->tif_row))
+ return (-1);
+ tif->tif_row = row;
+ }
+
+ /* swab if needed - note that source buffer will be altered */
+ tif->tif_postdecode( tif, (tidata_t) buf, tif->tif_scanlinesize );
+
+ status = (*tif->tif_encoderow)(tif, (tidata_t) buf,
+ tif->tif_scanlinesize, sample);
+
+ /* we are now poised at the beginning of the next row */
+ tif->tif_row = row + 1;
+ return (status);
+}
+
+/*
+ * Encode the supplied data and write it to the
+ * specified strip.
+ *
+ * NB: Image length must be setup before writing.
+ */
+tsize_t
+TIFFWriteEncodedStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
+{
+ static const char module[] = "TIFFWriteEncodedStrip";
+ TIFFDirectory *td = &tif->tif_dir;
+ tsample_t sample;
+
+ if (!WRITECHECKSTRIPS(tif, module))
+ return ((tsize_t) -1);
+ /*
+ * Check strip array to make sure there's space.
+ * We don't support dynamically growing files that
+ * have data organized in separate bitplanes because
+ * it's too painful. In that case we require that
+ * the imagelength be set properly before the first
+ * write (so that the strips array will be fully
+ * allocated above).
+ */
+ if (strip >= td->td_nstrips) {
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Can not grow image by strips when using separate planes");
+ return ((tsize_t) -1);
+ }
+ if (!TIFFGrowStrips(tif, 1, module))
+ return ((tsize_t) -1);
+ td->td_stripsperimage =
+ TIFFhowmany(td->td_imagelength, td->td_rowsperstrip);
+ }
+ /*
+ * Handle delayed allocation of data buffer. This
+ * permits it to be sized according to the directory
+ * info.
+ */
+ if (!BUFFERCHECK(tif))
+ return ((tsize_t) -1);
+ tif->tif_curstrip = strip;
+ tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+ if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+ if (!(*tif->tif_setupencode)(tif))
+ return ((tsize_t) -1);
+ tif->tif_flags |= TIFF_CODERSETUP;
+ }
+
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+
+ if( td->td_stripbytecount[strip] > 0 )
+ {
+ /* Force TIFFAppendToStrip() to consider placing data at end
+ of file. */
+ tif->tif_curoff = 0;
+ }
+
+ tif->tif_flags &= ~TIFF_POSTENCODE;
+ sample = (tsample_t)(strip / td->td_stripsperimage);
+ if (!(*tif->tif_preencode)(tif, sample))
+ return ((tsize_t) -1);
+
+ /* swab if needed - note that source buffer will be altered */
+ tif->tif_postdecode( tif, (tidata_t) data, cc );
+
+ if (!(*tif->tif_encodestrip)(tif, (tidata_t) data, cc, sample))
+ return ((tsize_t) 0);
+ if (!(*tif->tif_postencode)(tif))
+ return ((tsize_t) -1);
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ TIFFReverseBits(tif->tif_rawdata, tif->tif_rawcc);
+ if (tif->tif_rawcc > 0 &&
+ !TIFFAppendToStrip(tif, strip, tif->tif_rawdata, tif->tif_rawcc))
+ return ((tsize_t) -1);
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+ return (cc);
+}
+
+/*
+ * Write the supplied data to the specified strip.
+ *
+ * NB: Image length must be setup before writing.
+ */
+tsize_t
+TIFFWriteRawStrip(TIFF* tif, tstrip_t strip, tdata_t data, tsize_t cc)
+{
+ static const char module[] = "TIFFWriteRawStrip";
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if (!WRITECHECKSTRIPS(tif, module))
+ return ((tsize_t) -1);
+ /*
+ * Check strip array to make sure there's space.
+ * We don't support dynamically growing files that
+ * have data organized in separate bitplanes because
+ * it's too painful. In that case we require that
+ * the imagelength be set properly before the first
+ * write (so that the strips array will be fully
+ * allocated above).
+ */
+ if (strip >= td->td_nstrips) {
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+ "Can not grow image by strips when using separate planes");
+ return ((tsize_t) -1);
+ }
+ /*
+ * Watch out for a growing image. The value of
+ * strips/image will initially be 1 (since it
+ * can't be deduced until the imagelength is known).
+ */
+ if (strip >= td->td_stripsperimage)
+ td->td_stripsperimage =
+ TIFFhowmany(td->td_imagelength,td->td_rowsperstrip);
+ if (!TIFFGrowStrips(tif, 1, module))
+ return ((tsize_t) -1);
+ }
+ tif->tif_curstrip = strip;
+ tif->tif_row = (strip % td->td_stripsperimage) * td->td_rowsperstrip;
+ return (TIFFAppendToStrip(tif, strip, (tidata_t) data, cc) ?
+ cc : (tsize_t) -1);
+}
+
+/*
+ * Write and compress a tile of data. The
+ * tile is selected by the (x,y,z,s) coordinates.
+ */
+tsize_t
+TIFFWriteTile(TIFF* tif,
+ tdata_t buf, uint32 x, uint32 y, uint32 z, tsample_t s)
+{
+ if (!TIFFCheckTile(tif, x, y, z, s))
+ return (-1);
+ /*
+ * NB: A tile size of -1 is used instead of tif_tilesize knowing
+ * that TIFFWriteEncodedTile will clamp this to the tile size.
+ * This is done because the tile size may not be defined until
+ * after the output buffer is setup in TIFFWriteBufferSetup.
+ */
+ return (TIFFWriteEncodedTile(tif,
+ TIFFComputeTile(tif, x, y, z, s), buf, (tsize_t) -1));
+}
+
+/*
+ * Encode the supplied data and write it to the
+ * specified tile. There must be space for the
+ * data. The function clamps individual writes
+ * to a tile to the tile size, but does not (and
+ * can not) check that multiple writes to the same
+ * tile do not write more than tile size data.
+ *
+ * NB: Image length must be setup before writing; this
+ * interface does not support automatically growing
+ * the image on each write (as TIFFWriteScanline does).
+ */
+tsize_t
+TIFFWriteEncodedTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
+{
+ static const char module[] = "TIFFWriteEncodedTile";
+ TIFFDirectory *td;
+ tsample_t sample;
+
+ if (!WRITECHECKTILES(tif, module))
+ return ((tsize_t) -1);
+ td = &tif->tif_dir;
+ if (tile >= td->td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
+ tif->tif_name, (unsigned long) tile, (unsigned long) td->td_nstrips);
+ return ((tsize_t) -1);
+ }
+ /*
+ * Handle delayed allocation of data buffer. This
+ * permits it to be sized more intelligently (using
+ * directory information).
+ */
+ if (!BUFFERCHECK(tif))
+ return ((tsize_t) -1);
+ tif->tif_curtile = tile;
+
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+
+ if( td->td_stripbytecount[tile] > 0 )
+ {
+ /* Force TIFFAppendToStrip() to consider placing data at end
+ of file. */
+ tif->tif_curoff = 0;
+ }
+
+ /*
+ * Compute tiles per row & per column to compute
+ * current row and column
+ */
+ tif->tif_row = (tile % TIFFhowmany(td->td_imagelength, td->td_tilelength))
+ * td->td_tilelength;
+ tif->tif_col = (tile % TIFFhowmany(td->td_imagewidth, td->td_tilewidth))
+ * td->td_tilewidth;
+
+ if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
+ if (!(*tif->tif_setupencode)(tif))
+ return ((tsize_t) -1);
+ tif->tif_flags |= TIFF_CODERSETUP;
+ }
+ tif->tif_flags &= ~TIFF_POSTENCODE;
+ sample = (tsample_t)(tile/td->td_stripsperimage);
+ if (!(*tif->tif_preencode)(tif, sample))
+ return ((tsize_t) -1);
+ /*
+ * Clamp write amount to the tile size. This is mostly
+ * done so that callers can pass in some large number
+ * (e.g. -1) and have the tile size used instead.
+ */
+ if ( cc < 1 || cc > tif->tif_tilesize)
+ cc = tif->tif_tilesize;
+
+ /* swab if needed - note that source buffer will be altered */
+ tif->tif_postdecode( tif, (tidata_t) data, cc );
+
+ if (!(*tif->tif_encodetile)(tif, (tidata_t) data, cc, sample))
+ return ((tsize_t) 0);
+ if (!(*tif->tif_postencode)(tif))
+ return ((tsize_t) -1);
+ if (!isFillOrder(tif, td->td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ TIFFReverseBits((unsigned char *)tif->tif_rawdata, tif->tif_rawcc);
+ if (tif->tif_rawcc > 0 && !TIFFAppendToStrip(tif, tile,
+ tif->tif_rawdata, tif->tif_rawcc))
+ return ((tsize_t) -1);
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+ return (cc);
+}
+
+/*
+ * Write the supplied data to the specified strip.
+ * There must be space for the data; we don't check
+ * if strips overlap!
+ *
+ * NB: Image length must be setup before writing; this
+ * interface does not support automatically growing
+ * the image on each write (as TIFFWriteScanline does).
+ */
+tsize_t
+TIFFWriteRawTile(TIFF* tif, ttile_t tile, tdata_t data, tsize_t cc)
+{
+ static const char module[] = "TIFFWriteRawTile";
+
+ if (!WRITECHECKTILES(tif, module))
+ return ((tsize_t) -1);
+ if (tile >= tif->tif_dir.td_nstrips) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Tile %lu out of range, max %lu",
+ tif->tif_name, (unsigned long) tile,
+ (unsigned long) tif->tif_dir.td_nstrips);
+ return ((tsize_t) -1);
+ }
+ return (TIFFAppendToStrip(tif, tile, (tidata_t) data, cc) ?
+ cc : (tsize_t) -1);
+}
+
+#define isUnspecified(tif, f) \
+ (TIFFFieldSet(tif,f) && (tif)->tif_dir.td_imagelength == 0)
+
+int
+TIFFSetupStrips(TIFF* tif)
+{
+ TIFFDirectory* td = &tif->tif_dir;
+
+ if (isTiled(tif))
+ td->td_stripsperimage =
+ isUnspecified(tif, FIELD_TILEDIMENSIONS) ?
+ td->td_samplesperpixel : TIFFNumberOfTiles(tif);
+ else
+ td->td_stripsperimage =
+ isUnspecified(tif, FIELD_ROWSPERSTRIP) ?
+ td->td_samplesperpixel : TIFFNumberOfStrips(tif);
+ td->td_nstrips = td->td_stripsperimage;
+ if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
+ td->td_stripsperimage /= td->td_samplesperpixel;
+ td->td_stripoffset = (uint32 *)
+ _TIFFmalloc(td->td_nstrips * sizeof (uint32));
+ td->td_stripbytecount = (uint32 *)
+ _TIFFmalloc(td->td_nstrips * sizeof (uint32));
+ if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
+ return (0);
+ /*
+ * Place data at the end-of-file
+ * (by setting offsets to zero).
+ */
+ _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint32));
+ _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint32));
+ TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
+ TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
+ return (1);
+}
+#undef isUnspecified
+
+/*
+ * Verify file is writable and that the directory
+ * information is setup properly. In doing the latter
+ * we also "freeze" the state of the directory so
+ * that important information is not changed.
+ */
+int
+TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
+{
+ if (tif->tif_mode == O_RDONLY) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: File not open for writing",
+ tif->tif_name);
+ return (0);
+ }
+ if (tiles ^ isTiled(tif)) {
+ TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
+ "Can not write tiles to a stripped image" :
+ "Can not write scanlines to a tiled image");
+ return (0);
+ }
+
+ /*
+ * On the first write verify all the required information
+ * has been setup and initialize any data structures that
+ * had to wait until directory information was set.
+ * Note that a lot of our work is assumed to remain valid
+ * because we disallow any of the important parameters
+ * from changing after we start writing (i.e. once
+ * TIFF_BEENWRITING is set, TIFFSetField will only allow
+ * the image's length to be changed).
+ */
+ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Must set \"ImageWidth\" before writing data",
+ tif->tif_name);
+ return (0);
+ }
+ if (tif->tif_dir.td_samplesperpixel == 1) {
+ /*
+ * Planarconfiguration is irrelevant in case of single band
+ * images and need not be included. We will set it anyway,
+ * because this field is used in other parts of library even
+ * in the single band case.
+ */
+ if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG))
+ tif->tif_dir.td_planarconfig = PLANARCONFIG_CONTIG;
+ } else {
+ if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Must set \"PlanarConfiguration\" before writing data",
+ tif->tif_name);
+ return (0);
+ }
+ }
+ if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
+ tif->tif_dir.td_nstrips = 0;
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for %s arrays",
+ tif->tif_name, isTiled(tif) ? "tile" : "strip");
+ return (0);
+ }
+ tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
+ tif->tif_scanlinesize = TIFFScanlineSize(tif);
+ tif->tif_flags |= TIFF_BEENWRITING;
+ return (1);
+}
+
+/*
+ * Setup the raw data buffer used for encoding.
+ */
+int
+TIFFWriteBufferSetup(TIFF* tif, tdata_t bp, tsize_t size)
+{
+ static const char module[] = "TIFFWriteBufferSetup";
+
+ if (tif->tif_rawdata) {
+ if (tif->tif_flags & TIFF_MYBUFFER) {
+ _TIFFfree(tif->tif_rawdata);
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ }
+ tif->tif_rawdata = NULL;
+ }
+ if (size == (tsize_t) -1) {
+ size = (isTiled(tif) ?
+ tif->tif_tilesize : TIFFStripSize(tif));
+ /*
+ * Make raw data buffer at least 8K
+ */
+ if (size < 8*1024)
+ size = 8*1024;
+ bp = NULL; /* NB: force malloc */
+ }
+ if (bp == NULL) {
+ bp = _TIFFmalloc(size);
+ if (bp == NULL) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for output buffer",
+ tif->tif_name);
+ return (0);
+ }
+ tif->tif_flags |= TIFF_MYBUFFER;
+ } else
+ tif->tif_flags &= ~TIFF_MYBUFFER;
+ tif->tif_rawdata = (tidata_t) bp;
+ tif->tif_rawdatasize = size;
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+ tif->tif_flags |= TIFF_BUFFERSETUP;
+ return (1);
+}
+
+/*
+ * Grow the strip data structures by delta strips.
+ */
+static int
+TIFFGrowStrips(TIFF* tif, int delta, const char* module)
+{
+ TIFFDirectory *td = &tif->tif_dir;
+ uint32 *new_stripoffset, *new_stripbytecount;
+
+ assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
+ new_stripoffset = (uint32*)_TIFFrealloc(td->td_stripoffset,
+ (td->td_nstrips + delta) * sizeof (uint32));
+ new_stripbytecount = (uint32*)_TIFFrealloc(td->td_stripbytecount,
+ (td->td_nstrips + delta) * sizeof (uint32));
+ if (new_stripoffset == NULL || new_stripbytecount == NULL) {
+ if (new_stripoffset)
+ _TIFFfree(new_stripoffset);
+ if (new_stripbytecount)
+ _TIFFfree(new_stripbytecount);
+ td->td_nstrips = 0;
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: No space to expand strip arrays",
+ tif->tif_name);
+ return (0);
+ }
+ td->td_stripoffset = new_stripoffset;
+ td->td_stripbytecount = new_stripbytecount;
+ _TIFFmemset(td->td_stripoffset + td->td_nstrips,
+ 0, delta*sizeof (uint32));
+ _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
+ 0, delta*sizeof (uint32));
+ td->td_nstrips += delta;
+ return (1);
+}
+
+/*
+ * Append the data to the specified strip.
+ */
+static int
+TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc)
+{
+ static const char module[] = "TIFFAppendToStrip";
+ TIFFDirectory *td = &tif->tif_dir;
+
+ if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
+ assert(td->td_nstrips > 0);
+
+ if( td->td_stripbytecount[strip] != 0
+ && td->td_stripoffset[strip] != 0
+ && td->td_stripbytecount[strip] >= cc )
+ {
+ /*
+ * There is already tile data on disk, and the new tile
+ * data we have to will fit in the same space. The only
+ * aspect of this that is risky is that there could be
+ * more data to append to this strip before we are done
+ * depending on how we are getting called.
+ */
+ if (!SeekOK(tif, td->td_stripoffset[strip])) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Seek error at scanline %lu",
+ (unsigned long)tif->tif_row);
+ return (0);
+ }
+ }
+ else
+ {
+ /*
+ * Seek to end of file, and set that as our location to
+ * write this strip.
+ */
+ td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
+ }
+
+ tif->tif_curoff = td->td_stripoffset[strip];
+
+ /*
+ * We are starting a fresh strip/tile, so set the size to zero.
+ */
+ td->td_stripbytecount[strip] = 0;
+ }
+
+ if (!WriteOK(tif, data, cc)) {
+ TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu",
+ (unsigned long) tif->tif_row);
+ return (0);
+ }
+ tif->tif_curoff = tif->tif_curoff+cc;
+ td->td_stripbytecount[strip] += cc;
+ return (1);
+}
+
+/*
+ * Internal version of TIFFFlushData that can be
+ * called by ``encodestrip routines'' w/o concern
+ * for infinite recursion.
+ */
+int
+TIFFFlushData1(TIFF* tif)
+{
+ if (tif->tif_rawcc > 0) {
+ if (!isFillOrder(tif, tif->tif_dir.td_fillorder) &&
+ (tif->tif_flags & TIFF_NOBITREV) == 0)
+ TIFFReverseBits((unsigned char *)tif->tif_rawdata,
+ tif->tif_rawcc);
+ if (!TIFFAppendToStrip(tif,
+ isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip,
+ tif->tif_rawdata, tif->tif_rawcc))
+ return (0);
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+ }
+ return (1);
+}
+
+/*
+ * Set the current write offset. This should only be
+ * used to set the offset to a known previous location
+ * (very carefully), or to 0 so that the next write gets
+ * appended to the end of the file.
+ */
+void
+TIFFSetWriteOffset(TIFF* tif, toff_t off)
+{
+ tif->tif_curoff = off;
+}
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tif_zip.c b/Source/LibTIFF/tif_zip.c
new file mode 100644
index 0000000..7b23085
--- /dev/null
+++ b/Source/LibTIFF/tif_zip.c
@@ -0,0 +1,412 @@
+/* $Id: tif_zip.c,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1995-1997 Sam Leffler
+ * Copyright (c) 1995-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "tiffiop.h"
+#ifdef ZIP_SUPPORT
+/*
+ * TIFF Library.
+ *
+ * ZIP (aka Deflate) Compression Support
+ *
+ * This file is simply an interface to the zlib library written by
+ * Jean-loup Gailly and Mark Adler. You must use version 1.0 or later
+ * of the library: this code assumes the 1.0 API and also depends on
+ * the ability to write the zlib header multiple times (one per strip)
+ * which was not possible with versions prior to 0.95. Note also that
+ * older versions of this codec avoided this bug by supressing the header
+ * entirely. This means that files written with the old library cannot
+ * be read; they should be converted to a different compression scheme
+ * and then reconverted.
+ *
+ * The data format used by the zlib library is described in the files
+ * zlib-3.1.doc, deflate-1.1.doc and gzip-4.1.doc, available in the
+ * directory ftp://ftp.uu.net/pub/archiving/zip/doc. The library was
+ * last found at ftp://ftp.uu.net/pub/archiving/zip/zlib/zlib-0.99.tar.gz.
+ */
+#include "tif_predict.h"
+#include <zlib.h>
+
+#include <stdio.h>
+
+/*
+ * Sigh, ZLIB_VERSION is defined as a string so there's no
+ * way to do a proper check here. Instead we guess based
+ * on the presence of #defines that were added between the
+ * 0.95 and 1.0 distributions.
+ */
+#if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED)
+#error "Antiquated ZLIB software; you must use version 1.0 or later"
+#endif
+
+/*
+ * State block for each open TIFF
+ * file using ZIP compression/decompression.
+ */
+typedef struct {
+ TIFFPredictorState predict;
+ z_stream stream;
+ int zipquality; /* compression level */
+ int state; /* state flags */
+#define ZSTATE_INIT_DECODE 0x01
+#define ZSTATE_INIT_ENCODE 0x02
+
+ TIFFVGetMethod vgetparent; /* super-class method */
+ TIFFVSetMethod vsetparent; /* super-class method */
+} ZIPState;
+
+#define ZState(tif) ((ZIPState*) (tif)->tif_data)
+#define DecoderState(tif) ZState(tif)
+#define EncoderState(tif) ZState(tif)
+
+static int ZIPEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+static int ZIPDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+
+static int
+ZIPSetupDecode(TIFF* tif)
+{
+ ZIPState* sp = DecoderState(tif);
+ static const char module[] = "ZIPSetupDecode";
+
+ assert(sp != NULL);
+
+ /* if we were last encoding, terminate this mode */
+ if (sp->state & ZSTATE_INIT_ENCODE) {
+ deflateEnd(&sp->stream);
+ sp->state = 0;
+ }
+
+ if (inflateInit(&sp->stream) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
+ return (0);
+ } else {
+ sp->state |= ZSTATE_INIT_DECODE;
+ return (1);
+ }
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+ZIPPreDecode(TIFF* tif, tsample_t s)
+{
+ ZIPState* sp = DecoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+
+ if( (sp->state & ZSTATE_INIT_DECODE) == 0 )
+ tif->tif_setupdecode( tif );
+
+ sp->stream.next_in = tif->tif_rawdata;
+ sp->stream.avail_in = tif->tif_rawcc;
+ return (inflateReset(&sp->stream) == Z_OK);
+}
+
+static int
+ZIPDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
+{
+ ZIPState* sp = DecoderState(tif);
+ static const char module[] = "ZIPDecode";
+
+ (void) s;
+ assert(sp != NULL);
+ assert(sp->state == ZSTATE_INIT_DECODE);
+
+ sp->stream.next_out = op;
+ sp->stream.avail_out = occ;
+ do {
+ int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+ if (state == Z_STREAM_END)
+ break;
+ if (state == Z_DATA_ERROR) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Decoding error at scanline %d, %s",
+ tif->tif_name, tif->tif_row, sp->stream.msg);
+ if (inflateSync(&sp->stream) != Z_OK)
+ return (0);
+ continue;
+ }
+ if (state != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ } while (sp->stream.avail_out > 0);
+ if (sp->stream.avail_out != 0) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "%s: Not enough data at scanline %d (short %d bytes)",
+ tif->tif_name, tif->tif_row, sp->stream.avail_out);
+ return (0);
+ }
+ return (1);
+}
+
+static int
+ZIPSetupEncode(TIFF* tif)
+{
+ ZIPState* sp = EncoderState(tif);
+ static const char module[] = "ZIPSetupEncode";
+
+ assert(sp != NULL);
+ if (sp->state & ZSTATE_INIT_DECODE) {
+ inflateEnd(&sp->stream);
+ sp->state = 0;
+ }
+
+ if (deflateInit(&sp->stream, sp->zipquality) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
+ return (0);
+ } else {
+ sp->state |= ZSTATE_INIT_ENCODE;
+ return (1);
+ }
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+ZIPPreEncode(TIFF* tif, tsample_t s)
+{
+ ZIPState *sp = EncoderState(tif);
+
+ (void) s;
+ assert(sp != NULL);
+ if( sp->state != ZSTATE_INIT_ENCODE )
+ tif->tif_setupencode( tif );
+
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ return (deflateReset(&sp->stream) == Z_OK);
+}
+
+/*
+ * Encode a chunk of pixels.
+ */
+static int
+ZIPEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
+{
+ ZIPState *sp = EncoderState(tif);
+ static const char module[] = "ZIPEncode";
+
+ assert(sp != NULL);
+ assert(sp->state == ZSTATE_INIT_ENCODE);
+
+ (void) s;
+ sp->stream.next_in = bp;
+ sp->stream.avail_in = cc;
+ do {
+ if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ if (sp->stream.avail_out == 0) {
+ tif->tif_rawcc = tif->tif_rawdatasize;
+ TIFFFlushData1(tif);
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ }
+ } while (sp->stream.avail_in > 0);
+ return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+ZIPPostEncode(TIFF* tif)
+{
+ ZIPState *sp = EncoderState(tif);
+ static const char module[] = "ZIPPostEncode";
+ int state;
+
+ sp->stream.avail_in = 0;
+ do {
+ state = deflate(&sp->stream, Z_FINISH);
+ switch (state) {
+ case Z_STREAM_END:
+ case Z_OK:
+ if ((int)sp->stream.avail_out != (int)tif->tif_rawdatasize)
+ {
+ tif->tif_rawcc =
+ tif->tif_rawdatasize - sp->stream.avail_out;
+ TIFFFlushData1(tif);
+ sp->stream.next_out = tif->tif_rawdata;
+ sp->stream.avail_out = tif->tif_rawdatasize;
+ }
+ break;
+ default:
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ } while (state != Z_STREAM_END);
+ return (1);
+}
+
+static void
+ZIPCleanup(TIFF* tif)
+{
+ ZIPState* sp = ZState(tif);
+
+ assert(sp != 0);
+
+ (void)TIFFPredictorCleanup(tif);
+
+ tif->tif_tagmethods.vgetfield = sp->vgetparent;
+ tif->tif_tagmethods.vsetfield = sp->vsetparent;
+
+ if (sp->state & ZSTATE_INIT_ENCODE) {
+ deflateEnd(&sp->stream);
+ sp->state = 0;
+ } else if( sp->state & ZSTATE_INIT_DECODE) {
+ inflateEnd(&sp->stream);
+ sp->state = 0;
+ }
+ _TIFFfree(sp);
+ tif->tif_data = NULL;
+
+ _TIFFSetDefaultCompressionState(tif);
+}
+
+static int
+ZIPVSetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ ZIPState* sp = ZState(tif);
+ static const char module[] = "ZIPVSetField";
+
+ switch (tag) {
+ case TIFFTAG_ZIPQUALITY:
+ sp->zipquality = va_arg(ap, int);
+ if ( sp->state&ZSTATE_INIT_ENCODE ) {
+ if (deflateParams(&sp->stream,
+ sp->zipquality, Z_DEFAULT_STRATEGY) != Z_OK) {
+ TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
+ tif->tif_name, sp->stream.msg);
+ return (0);
+ }
+ }
+ return (1);
+ default:
+ return (*sp->vsetparent)(tif, tag, ap);
+ }
+ /*NOTREACHED*/
+}
+
+static int
+ZIPVGetField(TIFF* tif, ttag_t tag, va_list ap)
+{
+ ZIPState* sp = ZState(tif);
+
+ switch (tag) {
+ case TIFFTAG_ZIPQUALITY:
+ *va_arg(ap, int*) = sp->zipquality;
+ break;
+ default:
+ return (*sp->vgetparent)(tif, tag, ap);
+ }
+ return (1);
+}
+
+static const TIFFFieldInfo zipFieldInfo[] = {
+ { TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, FIELD_PSEUDO,
+ TRUE, FALSE, "" },
+};
+
+int
+TIFFInitZIP(TIFF* tif, int scheme)
+{
+ static const char module[] = "TIFFInitZIP";
+ ZIPState* sp;
+
+ assert( (scheme == COMPRESSION_DEFLATE)
+ || (scheme == COMPRESSION_ADOBE_DEFLATE));
+
+ /*
+ * Merge codec-specific tag information.
+ */
+ if (!_TIFFMergeFieldInfo(tif, zipFieldInfo,
+ TIFFArrayCount(zipFieldInfo))) {
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "Merging Deflate codec-specific tags failed");
+ return 0;
+ }
+
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (ZIPState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ sp = ZState(tif);
+ sp->stream.zalloc = NULL;
+ sp->stream.zfree = NULL;
+ sp->stream.opaque = NULL;
+ sp->stream.data_type = Z_BINARY;
+
+ /*
+ * Override parent get/set field methods.
+ */
+ sp->vgetparent = tif->tif_tagmethods.vgetfield;
+ tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */
+ sp->vsetparent = tif->tif_tagmethods.vsetfield;
+ tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */
+
+ /* Default values for codec-specific fields */
+ sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
+ sp->state = 0;
+
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = ZIPSetupDecode;
+ tif->tif_predecode = ZIPPreDecode;
+ tif->tif_decoderow = ZIPDecode;
+ tif->tif_decodestrip = ZIPDecode;
+ tif->tif_decodetile = ZIPDecode;
+ tif->tif_setupencode = ZIPSetupEncode;
+ tif->tif_preencode = ZIPPreEncode;
+ tif->tif_postencode = ZIPPostEncode;
+ tif->tif_encoderow = ZIPEncode;
+ tif->tif_encodestrip = ZIPEncode;
+ tif->tif_encodetile = ZIPEncode;
+ tif->tif_cleanup = ZIPCleanup;
+ /*
+ * Setup predictor setup.
+ */
+ (void) TIFFPredictorInit(tif);
+ return (1);
+bad:
+ TIFFErrorExt(tif->tif_clientdata, module,
+ "No space for ZIP state block");
+ return (0);
+}
+#endif /* ZIP_SUPORT */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tiff.h b/Source/LibTIFF/tiff.h
new file mode 100644
index 0000000..cb5b69d
--- /dev/null
+++ b/Source/LibTIFF/tiff.h
@@ -0,0 +1,647 @@
+/* $Id: tiff.h,v 1.28 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFF_
+#define _TIFF_
+
+#include "tif_config.h"
+
+/*
+ * Tag Image File Format (TIFF)
+ *
+ * Based on Rev 6.0 from:
+ * Developer's Desk
+ * Aldus Corporation
+ * 411 First Ave. South
+ * Suite 200
+ * Seattle, WA 98104
+ * 206-622-5500
+ *
+ * (http://partners.adobe.com/asn/developer/PDFS/TN/TIFF6.pdf)
+ *
+ * For Big TIFF design notes see the following link
+ * http://www.remotesensing.org/libtiff/bigtiffdesign.html
+ */
+#define TIFF_VERSION 42
+#define TIFF_BIGTIFF_VERSION 43
+
+#define TIFF_BIGENDIAN 0x4d4d
+#define TIFF_LITTLEENDIAN 0x4949
+#define MDI_LITTLEENDIAN 0x5045
+#define MDI_BIGENDIAN 0x4550
+/*
+ * Intrinsic data types required by the file format:
+ *
+ * 8-bit quantities int8/uint8
+ * 16-bit quantities int16/uint16
+ * 32-bit quantities int32/uint32
+ * strings unsigned char*
+ */
+
+#ifndef HAVE_INT8
+typedef signed char int8; /* NB: non-ANSI compilers may not grok */
+#endif
+typedef unsigned char uint8;
+#ifndef HAVE_INT16
+typedef short int16;
+#endif
+typedef unsigned short uint16; /* sizeof (uint16) must == 2 */
+#if SIZEOF_INT == 4
+#ifndef HAVE_INT32
+typedef int int32;
+#endif
+typedef unsigned int uint32; /* sizeof (uint32) must == 4 */
+#elif SIZEOF_LONG == 4
+#ifndef HAVE_INT32
+typedef long int32;
+#endif
+typedef unsigned long uint32; /* sizeof (uint32) must == 4 */
+#endif
+
+/* For TIFFReassignTagToIgnore */
+enum TIFFIgnoreSense /* IGNORE tag table */
+{
+ TIS_STORE,
+ TIS_EXTRACT,
+ TIS_EMPTY
+};
+
+/*
+ * TIFF header.
+ */
+typedef struct {
+ uint16 tiff_magic; /* magic number (defines byte order) */
+#define TIFF_MAGIC_SIZE 2
+ uint16 tiff_version; /* TIFF version number */
+#define TIFF_VERSION_SIZE 2
+ uint32 tiff_diroff; /* byte offset to first directory */
+#define TIFF_DIROFFSET_SIZE 4
+} TIFFHeader;
+
+
+/*
+ * TIFF Image File Directories are comprised of a table of field
+ * descriptors of the form shown below. The table is sorted in
+ * ascending order by tag. The values associated with each entry are
+ * disjoint and may appear anywhere in the file (so long as they are
+ * placed on a word boundary).
+ *
+ * If the value is 4 bytes or less, then it is placed in the offset
+ * field to save space. If the value is less than 4 bytes, it is
+ * left-justified in the offset field.
+ */
+typedef struct {
+ uint16 tdir_tag; /* see below */
+ uint16 tdir_type; /* data type; see below */
+ uint32 tdir_count; /* number of items; length in spec */
+ uint32 tdir_offset; /* byte offset to field data */
+} TIFFDirEntry;
+
+/*
+ * NB: In the comments below,
+ * - items marked with a + are obsoleted by revision 5.0,
+ * - items marked with a ! are introduced in revision 6.0.
+ * - items marked with a % are introduced post revision 6.0.
+ * - items marked with a $ are obsoleted by revision 6.0.
+ * - items marked with a & are introduced by Adobe DNG specification.
+ */
+
+/*
+ * Tag data type information.
+ *
+ * Note: RATIONALs are the ratio of two 32-bit integer values.
+ */
+typedef enum {
+ TIFF_NOTYPE = 0, /* placeholder */
+ TIFF_BYTE = 1, /* 8-bit unsigned integer */
+ TIFF_ASCII = 2, /* 8-bit bytes w/ last byte null */
+ TIFF_SHORT = 3, /* 16-bit unsigned integer */
+ TIFF_LONG = 4, /* 32-bit unsigned integer */
+ TIFF_RATIONAL = 5, /* 64-bit unsigned fraction */
+ TIFF_SBYTE = 6, /* !8-bit signed integer */
+ TIFF_UNDEFINED = 7, /* !8-bit untyped data */
+ TIFF_SSHORT = 8, /* !16-bit signed integer */
+ TIFF_SLONG = 9, /* !32-bit signed integer */
+ TIFF_SRATIONAL = 10, /* !64-bit signed fraction */
+ TIFF_FLOAT = 11, /* !32-bit IEEE floating point */
+ TIFF_DOUBLE = 12, /* !64-bit IEEE floating point */
+ TIFF_IFD = 13 /* %32-bit unsigned integer (offset) */
+} TIFFDataType;
+
+/*
+ * TIFF Tag Definitions.
+ */
+#define TIFFTAG_SUBFILETYPE 254 /* subfile data descriptor */
+#define FILETYPE_REDUCEDIMAGE 0x1 /* reduced resolution version */
+#define FILETYPE_PAGE 0x2 /* one page of many */
+#define FILETYPE_MASK 0x4 /* transparency mask */
+#define TIFFTAG_OSUBFILETYPE 255 /* +kind of data in subfile */
+#define OFILETYPE_IMAGE 1 /* full resolution image data */
+#define OFILETYPE_REDUCEDIMAGE 2 /* reduced size image data */
+#define OFILETYPE_PAGE 3 /* one page of many */
+#define TIFFTAG_IMAGEWIDTH 256 /* image width in pixels */
+#define TIFFTAG_IMAGELENGTH 257 /* image height in pixels */
+#define TIFFTAG_BITSPERSAMPLE 258 /* bits per channel (sample) */
+#define TIFFTAG_COMPRESSION 259 /* data compression technique */
+#define COMPRESSION_NONE 1 /* dump mode */
+#define COMPRESSION_CCITTRLE 2 /* CCITT modified Huffman RLE */
+#define COMPRESSION_CCITTFAX3 3 /* CCITT Group 3 fax encoding */
+#define COMPRESSION_CCITT_T4 3 /* CCITT T.4 (TIFF 6 name) */
+#define COMPRESSION_CCITTFAX4 4 /* CCITT Group 4 fax encoding */
+#define COMPRESSION_CCITT_T6 4 /* CCITT T.6 (TIFF 6 name) */
+#define COMPRESSION_LZW 5 /* Lempel-Ziv & Welch */
+#define COMPRESSION_OJPEG 6 /* !6.0 JPEG */
+#define COMPRESSION_JPEG 7 /* %JPEG DCT compression */
+#define COMPRESSION_NEXT 32766 /* NeXT 2-bit RLE */
+#define COMPRESSION_CCITTRLEW 32771 /* #1 w/ word alignment */
+#define COMPRESSION_PACKBITS 32773 /* Macintosh RLE */
+#define COMPRESSION_THUNDERSCAN 32809 /* ThunderScan RLE */
+/* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+#define COMPRESSION_IT8CTPAD 32895 /* IT8 CT w/padding */
+#define COMPRESSION_IT8LW 32896 /* IT8 Linework RLE */
+#define COMPRESSION_IT8MP 32897 /* IT8 Monochrome picture */
+#define COMPRESSION_IT8BL 32898 /* IT8 Binary line art */
+/* compression codes 32908-32911 are reserved for Pixar */
+#define COMPRESSION_PIXARFILM 32908 /* Pixar companded 10bit LZW */
+#define COMPRESSION_PIXARLOG 32909 /* Pixar companded 11bit ZIP */
+#define COMPRESSION_DEFLATE 32946 /* Deflate compression */
+#define COMPRESSION_ADOBE_DEFLATE 8 /* Deflate compression,
+ as recognized by Adobe */
+/* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
+#define COMPRESSION_DCS 32947 /* Kodak DCS encoding */
+#define COMPRESSION_JBIG 34661 /* ISO JBIG */
+#define COMPRESSION_SGILOG 34676 /* SGI Log Luminance RLE */
+#define COMPRESSION_SGILOG24 34677 /* SGI Log 24-bit packed */
+#define COMPRESSION_JP2000 34712 /* Leadtools JPEG2000 */
+#define TIFFTAG_PHOTOMETRIC 262 /* photometric interpretation */
+#define PHOTOMETRIC_MINISWHITE 0 /* min value is white */
+#define PHOTOMETRIC_MINISBLACK 1 /* min value is black */
+#define PHOTOMETRIC_RGB 2 /* RGB color model */
+#define PHOTOMETRIC_PALETTE 3 /* color map indexed */
+#define PHOTOMETRIC_MASK 4 /* $holdout mask */
+#define PHOTOMETRIC_SEPARATED 5 /* !color separations */
+#define PHOTOMETRIC_YCBCR 6 /* !CCIR 601 */
+#define PHOTOMETRIC_CIELAB 8 /* !1976 CIE L*a*b* */
+#define PHOTOMETRIC_ICCLAB 9 /* ICC L*a*b* [Adobe TIFF Technote 4] */
+#define PHOTOMETRIC_ITULAB 10 /* ITU L*a*b* */
+#define PHOTOMETRIC_LOGL 32844 /* CIE Log2(L) */
+#define PHOTOMETRIC_LOGLUV 32845 /* CIE Log2(L) (u',v') */
+#define TIFFTAG_THRESHHOLDING 263 /* +thresholding used on data */
+#define THRESHHOLD_BILEVEL 1 /* b&w art scan */
+#define THRESHHOLD_HALFTONE 2 /* or dithered scan */
+#define THRESHHOLD_ERRORDIFFUSE 3 /* usually floyd-steinberg */
+#define TIFFTAG_CELLWIDTH 264 /* +dithering matrix width */
+#define TIFFTAG_CELLLENGTH 265 /* +dithering matrix height */
+#define TIFFTAG_FILLORDER 266 /* data order within a byte */
+#define FILLORDER_MSB2LSB 1 /* most significant -> least */
+#define FILLORDER_LSB2MSB 2 /* least significant -> most */
+#define TIFFTAG_DOCUMENTNAME 269 /* name of doc. image is from */
+#define TIFFTAG_IMAGEDESCRIPTION 270 /* info about image */
+#define TIFFTAG_MAKE 271 /* scanner manufacturer name */
+#define TIFFTAG_MODEL 272 /* scanner model name/number */
+#define TIFFTAG_STRIPOFFSETS 273 /* offsets to data strips */
+#define TIFFTAG_ORIENTATION 274 /* +image orientation */
+#define ORIENTATION_TOPLEFT 1 /* row 0 top, col 0 lhs */
+#define ORIENTATION_TOPRIGHT 2 /* row 0 top, col 0 rhs */
+#define ORIENTATION_BOTRIGHT 3 /* row 0 bottom, col 0 rhs */
+#define ORIENTATION_BOTLEFT 4 /* row 0 bottom, col 0 lhs */
+#define ORIENTATION_LEFTTOP 5 /* row 0 lhs, col 0 top */
+#define ORIENTATION_RIGHTTOP 6 /* row 0 rhs, col 0 top */
+#define ORIENTATION_RIGHTBOT 7 /* row 0 rhs, col 0 bottom */
+#define ORIENTATION_LEFTBOT 8 /* row 0 lhs, col 0 bottom */
+#define TIFFTAG_SAMPLESPERPIXEL 277 /* samples per pixel */
+#define TIFFTAG_ROWSPERSTRIP 278 /* rows per strip of data */
+#define TIFFTAG_STRIPBYTECOUNTS 279 /* bytes counts for strips */
+#define TIFFTAG_MINSAMPLEVALUE 280 /* +minimum sample value */
+#define TIFFTAG_MAXSAMPLEVALUE 281 /* +maximum sample value */
+#define TIFFTAG_XRESOLUTION 282 /* pixels/resolution in x */
+#define TIFFTAG_YRESOLUTION 283 /* pixels/resolution in y */
+#define TIFFTAG_PLANARCONFIG 284 /* storage organization */
+#define PLANARCONFIG_CONTIG 1 /* single image plane */
+#define PLANARCONFIG_SEPARATE 2 /* separate planes of data */
+#define TIFFTAG_PAGENAME 285 /* page name image is from */
+#define TIFFTAG_XPOSITION 286 /* x page offset of image lhs */
+#define TIFFTAG_YPOSITION 287 /* y page offset of image lhs */
+#define TIFFTAG_FREEOFFSETS 288 /* +byte offset to free block */
+#define TIFFTAG_FREEBYTECOUNTS 289 /* +sizes of free blocks */
+#define TIFFTAG_GRAYRESPONSEUNIT 290 /* $gray scale curve accuracy */
+#define GRAYRESPONSEUNIT_10S 1 /* tenths of a unit */
+#define GRAYRESPONSEUNIT_100S 2 /* hundredths of a unit */
+#define GRAYRESPONSEUNIT_1000S 3 /* thousandths of a unit */
+#define GRAYRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
+#define GRAYRESPONSEUNIT_100000S 5 /* hundred-thousandths */
+#define TIFFTAG_GRAYRESPONSECURVE 291 /* $gray scale response curve */
+#define TIFFTAG_GROUP3OPTIONS 292 /* 32 flag bits */
+#define TIFFTAG_T4OPTIONS 292 /* TIFF 6.0 proper name alias */
+#define GROUP3OPT_2DENCODING 0x1 /* 2-dimensional coding */
+#define GROUP3OPT_UNCOMPRESSED 0x2 /* data not compressed */
+#define GROUP3OPT_FILLBITS 0x4 /* fill to byte boundary */
+#define TIFFTAG_GROUP4OPTIONS 293 /* 32 flag bits */
+#define TIFFTAG_T6OPTIONS 293 /* TIFF 6.0 proper name */
+#define GROUP4OPT_UNCOMPRESSED 0x2 /* data not compressed */
+#define TIFFTAG_RESOLUTIONUNIT 296 /* units of resolutions */
+#define RESUNIT_NONE 1 /* no meaningful units */
+#define RESUNIT_INCH 2 /* english */
+#define RESUNIT_CENTIMETER 3 /* metric */
+#define TIFFTAG_PAGENUMBER 297 /* page numbers of multi-page */
+#define TIFFTAG_COLORRESPONSEUNIT 300 /* $color curve accuracy */
+#define COLORRESPONSEUNIT_10S 1 /* tenths of a unit */
+#define COLORRESPONSEUNIT_100S 2 /* hundredths of a unit */
+#define COLORRESPONSEUNIT_1000S 3 /* thousandths of a unit */
+#define COLORRESPONSEUNIT_10000S 4 /* ten-thousandths of a unit */
+#define COLORRESPONSEUNIT_100000S 5 /* hundred-thousandths */
+#define TIFFTAG_TRANSFERFUNCTION 301 /* !colorimetry info */
+#define TIFFTAG_SOFTWARE 305 /* name & release */
+#define TIFFTAG_DATETIME 306 /* creation date and time */
+#define TIFFTAG_ARTIST 315 /* creator of image */
+#define TIFFTAG_HOSTCOMPUTER 316 /* machine where created */
+#define TIFFTAG_PREDICTOR 317 /* prediction scheme w/ LZW */
+#define PREDICTOR_NONE 1 /* no prediction scheme used */
+#define PREDICTOR_HORIZONTAL 2 /* horizontal differencing */
+#define PREDICTOR_FLOATINGPOINT 3 /* floating point predictor */
+#define TIFFTAG_WHITEPOINT 318 /* image white point */
+#define TIFFTAG_PRIMARYCHROMATICITIES 319 /* !primary chromaticities */
+#define TIFFTAG_COLORMAP 320 /* RGB map for pallette image */
+#define TIFFTAG_HALFTONEHINTS 321 /* !highlight+shadow info */
+#define TIFFTAG_TILEWIDTH 322 /* !tile width in pixels */
+#define TIFFTAG_TILELENGTH 323 /* !tile height in pixels */
+#define TIFFTAG_TILEOFFSETS 324 /* !offsets to data tiles */
+#define TIFFTAG_TILEBYTECOUNTS 325 /* !byte counts for tiles */
+#define TIFFTAG_BADFAXLINES 326 /* lines w/ wrong pixel count */
+#define TIFFTAG_CLEANFAXDATA 327 /* regenerated line info */
+#define CLEANFAXDATA_CLEAN 0 /* no errors detected */
+#define CLEANFAXDATA_REGENERATED 1 /* receiver regenerated lines */
+#define CLEANFAXDATA_UNCLEAN 2 /* uncorrected errors exist */
+#define TIFFTAG_CONSECUTIVEBADFAXLINES 328 /* max consecutive bad lines */
+#define TIFFTAG_SUBIFD 330 /* subimage descriptors */
+#define TIFFTAG_INKSET 332 /* !inks in separated image */
+#define INKSET_CMYK 1 /* !cyan-magenta-yellow-black color */
+#define INKSET_MULTIINK 2 /* !multi-ink or hi-fi color */
+#define TIFFTAG_INKNAMES 333 /* !ascii names of inks */
+#define TIFFTAG_NUMBEROFINKS 334 /* !number of inks */
+#define TIFFTAG_DOTRANGE 336 /* !0% and 100% dot codes */
+#define TIFFTAG_TARGETPRINTER 337 /* !separation target */
+#define TIFFTAG_EXTRASAMPLES 338 /* !info about extra samples */
+#define EXTRASAMPLE_UNSPECIFIED 0 /* !unspecified data */
+#define EXTRASAMPLE_ASSOCALPHA 1 /* !associated alpha data */
+#define EXTRASAMPLE_UNASSALPHA 2 /* !unassociated alpha data */
+#define TIFFTAG_SAMPLEFORMAT 339 /* !data sample format */
+#define SAMPLEFORMAT_UINT 1 /* !unsigned integer data */
+#define SAMPLEFORMAT_INT 2 /* !signed integer data */
+#define SAMPLEFORMAT_IEEEFP 3 /* !IEEE floating point data */
+#define SAMPLEFORMAT_VOID 4 /* !untyped data */
+#define SAMPLEFORMAT_COMPLEXINT 5 /* !complex signed int */
+#define SAMPLEFORMAT_COMPLEXIEEEFP 6 /* !complex ieee floating */
+#define TIFFTAG_SMINSAMPLEVALUE 340 /* !variable MinSampleValue */
+#define TIFFTAG_SMAXSAMPLEVALUE 341 /* !variable MaxSampleValue */
+#define TIFFTAG_CLIPPATH 343 /* %ClipPath
+ [Adobe TIFF technote 2] */
+#define TIFFTAG_XCLIPPATHUNITS 344 /* %XClipPathUnits
+ [Adobe TIFF technote 2] */
+#define TIFFTAG_YCLIPPATHUNITS 345 /* %YClipPathUnits
+ [Adobe TIFF technote 2] */
+#define TIFFTAG_INDEXED 346 /* %Indexed
+ [Adobe TIFF Technote 3] */
+#define TIFFTAG_JPEGTABLES 347 /* %JPEG table stream */
+#define TIFFTAG_OPIPROXY 351 /* %OPI Proxy [Adobe TIFF technote] */
+/*
+ * Tags 512-521 are obsoleted by Technical Note #2 which specifies a
+ * revised JPEG-in-TIFF scheme.
+ */
+#define TIFFTAG_JPEGPROC 512 /* !JPEG processing algorithm */
+#define JPEGPROC_BASELINE 1 /* !baseline sequential */
+#define JPEGPROC_LOSSLESS 14 /* !Huffman coded lossless */
+#define TIFFTAG_JPEGIFOFFSET 513 /* !pointer to SOI marker */
+#define TIFFTAG_JPEGIFBYTECOUNT 514 /* !JFIF stream length */
+#define TIFFTAG_JPEGRESTARTINTERVAL 515 /* !restart interval length */
+#define TIFFTAG_JPEGLOSSLESSPREDICTORS 517 /* !lossless proc predictor */
+#define TIFFTAG_JPEGPOINTTRANSFORM 518 /* !lossless point transform */
+#define TIFFTAG_JPEGQTABLES 519 /* !Q matrice offsets */
+#define TIFFTAG_JPEGDCTABLES 520 /* !DCT table offsets */
+#define TIFFTAG_JPEGACTABLES 521 /* !AC coefficient offsets */
+#define TIFFTAG_YCBCRCOEFFICIENTS 529 /* !RGB -> YCbCr transform */
+#define TIFFTAG_YCBCRSUBSAMPLING 530 /* !YCbCr subsampling factors */
+#define TIFFTAG_YCBCRPOSITIONING 531 /* !subsample positioning */
+#define YCBCRPOSITION_CENTERED 1 /* !as in PostScript Level 2 */
+#define YCBCRPOSITION_COSITED 2 /* !as in CCIR 601-1 */
+#define TIFFTAG_REFERENCEBLACKWHITE 532 /* !colorimetry info */
+#define TIFFTAG_XMLPACKET 700 /* %XML packet
+ [Adobe XMP Specification,
+ January 2004 */
+#define TIFFTAG_OPIIMAGEID 32781 /* %OPI ImageID
+ [Adobe TIFF technote] */
+/* tags 32952-32956 are private tags registered to Island Graphics */
+#define TIFFTAG_REFPTS 32953 /* image reference points */
+#define TIFFTAG_REGIONTACKPOINT 32954 /* region-xform tack point */
+#define TIFFTAG_REGIONWARPCORNERS 32955 /* warp quadrilateral */
+#define TIFFTAG_REGIONAFFINE 32956 /* affine transformation mat */
+/* tags 32995-32999 are private tags registered to SGI */
+#define TIFFTAG_MATTEING 32995 /* $use ExtraSamples */
+#define TIFFTAG_DATATYPE 32996 /* $use SampleFormat */
+#define TIFFTAG_IMAGEDEPTH 32997 /* z depth of image */
+#define TIFFTAG_TILEDEPTH 32998 /* z depth/data tile */
+/* tags 33300-33309 are private tags registered to Pixar */
+/*
+ * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH
+ * are set when an image has been cropped out of a larger image.
+ * They reflect the size of the original uncropped image.
+ * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used
+ * to determine the position of the smaller image in the larger one.
+ */
+#define TIFFTAG_PIXAR_IMAGEFULLWIDTH 33300 /* full image size in x */
+#define TIFFTAG_PIXAR_IMAGEFULLLENGTH 33301 /* full image size in y */
+ /* Tags 33302-33306 are used to identify special image modes and data
+ * used by Pixar's texture formats.
+ */
+#define TIFFTAG_PIXAR_TEXTUREFORMAT 33302 /* texture map format */
+#define TIFFTAG_PIXAR_WRAPMODES 33303 /* s & t wrap modes */
+#define TIFFTAG_PIXAR_FOVCOT 33304 /* cotan(fov) for env. maps */
+#define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305
+#define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306
+/* tag 33405 is a private tag registered to Eastman Kodak */
+#define TIFFTAG_WRITERSERIALNUMBER 33405 /* device serial number */
+/* tag 33432 is listed in the 6.0 spec w/ unknown ownership */
+#define TIFFTAG_COPYRIGHT 33432 /* copyright string */
+/* IPTC TAG from RichTIFF specifications */
+#define TIFFTAG_RICHTIFFIPTC 33723
+/* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+#define TIFFTAG_IT8SITE 34016 /* site name */
+#define TIFFTAG_IT8COLORSEQUENCE 34017 /* color seq. [RGB,CMYK,etc] */
+#define TIFFTAG_IT8HEADER 34018 /* DDES Header */
+#define TIFFTAG_IT8RASTERPADDING 34019 /* raster scanline padding */
+#define TIFFTAG_IT8BITSPERRUNLENGTH 34020 /* # of bits in short run */
+#define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021/* # of bits in long run */
+#define TIFFTAG_IT8COLORTABLE 34022 /* LW colortable */
+#define TIFFTAG_IT8IMAGECOLORINDICATOR 34023 /* BP/BL image color switch */
+#define TIFFTAG_IT8BKGCOLORINDICATOR 34024 /* BP/BL bg color switch */
+#define TIFFTAG_IT8IMAGECOLORVALUE 34025 /* BP/BL image color value */
+#define TIFFTAG_IT8BKGCOLORVALUE 34026 /* BP/BL bg color value */
+#define TIFFTAG_IT8PIXELINTENSITYRANGE 34027 /* MP pixel intensity value */
+#define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028 /* HC transparency switch */
+#define TIFFTAG_IT8COLORCHARACTERIZATION 34029 /* color character. table */
+#define TIFFTAG_IT8HCUSAGE 34030 /* HC usage indicator */
+#define TIFFTAG_IT8TRAPINDICATOR 34031 /* Trapping indicator
+ (untrapped=0, trapped=1) */
+#define TIFFTAG_IT8CMYKEQUIVALENT 34032 /* CMYK color equivalents */
+/* tags 34232-34236 are private tags registered to Texas Instruments */
+#define TIFFTAG_FRAMECOUNT 34232 /* Sequence Frame Count */
+/* tag 34377 is private tag registered to Adobe for PhotoShop */
+#define TIFFTAG_PHOTOSHOP 34377
+/* tags 34665, 34853 and 40965 are documented in EXIF specification */
+#define TIFFTAG_EXIFIFD 34665 /* Pointer to EXIF private directory */
+/* tag 34750 is a private tag registered to Adobe? */
+#define TIFFTAG_ICCPROFILE 34675 /* ICC profile data */
+/* tag 34750 is a private tag registered to Pixel Magic */
+#define TIFFTAG_JBIGOPTIONS 34750 /* JBIG options */
+#define TIFFTAG_GPSIFD 34853 /* Pointer to GPS private directory */
+/* tags 34908-34914 are private tags registered to SGI */
+#define TIFFTAG_FAXRECVPARAMS 34908 /* encoded Class 2 ses. parms */
+#define TIFFTAG_FAXSUBADDRESS 34909 /* received SubAddr string */
+#define TIFFTAG_FAXRECVTIME 34910 /* receive time (secs) */
+#define TIFFTAG_FAXDCS 34911 /* encoded fax ses. params, Table 2/T.30 */
+/* tags 37439-37443 are registered to SGI <gregl@sgi.com> */
+#define TIFFTAG_STONITS 37439 /* Sample value to Nits */
+/* tag 34929 is a private tag registered to FedEx */
+#define TIFFTAG_FEDEX_EDR 34929 /* unknown use */
+#define TIFFTAG_INTEROPERABILITYIFD 40965 /* Pointer to Interoperability private directory */
+/* Adobe Digital Negative (DNG) format tags */
+#define TIFFTAG_DNGVERSION 50706 /* &DNG version number */
+#define TIFFTAG_DNGBACKWARDVERSION 50707 /* &DNG compatibility version */
+#define TIFFTAG_UNIQUECAMERAMODEL 50708 /* &name for the camera model */
+#define TIFFTAG_LOCALIZEDCAMERAMODEL 50709 /* &localized camera model
+ name */
+#define TIFFTAG_CFAPLANECOLOR 50710 /* &CFAPattern->LinearRaw space
+ mapping */
+#define TIFFTAG_CFALAYOUT 50711 /* &spatial layout of the CFA */
+#define TIFFTAG_LINEARIZATIONTABLE 50712 /* &lookup table description */
+#define TIFFTAG_BLACKLEVELREPEATDIM 50713 /* &repeat pattern size for
+ the BlackLevel tag */
+#define TIFFTAG_BLACKLEVEL 50714 /* &zero light encoding level */
+#define TIFFTAG_BLACKLEVELDELTAH 50715 /* &zero light encoding level
+ differences (columns) */
+#define TIFFTAG_BLACKLEVELDELTAV 50716 /* &zero light encoding level
+ differences (rows) */
+#define TIFFTAG_WHITELEVEL 50717 /* &fully saturated encoding
+ level */
+#define TIFFTAG_DEFAULTSCALE 50718 /* &default scale factors */
+#define TIFFTAG_DEFAULTCROPORIGIN 50719 /* &origin of the final image
+ area */
+#define TIFFTAG_DEFAULTCROPSIZE 50720 /* &size of the final image
+ area */
+#define TIFFTAG_COLORMATRIX1 50721 /* &XYZ->reference color space
+ transformation matrix 1 */
+#define TIFFTAG_COLORMATRIX2 50722 /* &XYZ->reference color space
+ transformation matrix 2 */
+#define TIFFTAG_CAMERACALIBRATION1 50723 /* &calibration matrix 1 */
+#define TIFFTAG_CAMERACALIBRATION2 50724 /* &calibration matrix 2 */
+#define TIFFTAG_REDUCTIONMATRIX1 50725 /* &dimensionality reduction
+ matrix 1 */
+#define TIFFTAG_REDUCTIONMATRIX2 50726 /* &dimensionality reduction
+ matrix 2 */
+#define TIFFTAG_ANALOGBALANCE 50727 /* &gain applied the stored raw
+ values*/
+#define TIFFTAG_ASSHOTNEUTRAL 50728 /* &selected white balance in
+ linear reference space */
+#define TIFFTAG_ASSHOTWHITEXY 50729 /* &selected white balance in
+ x-y chromaticity
+ coordinates */
+#define TIFFTAG_BASELINEEXPOSURE 50730 /* &how much to move the zero
+ point */
+#define TIFFTAG_BASELINENOISE 50731 /* &relative noise level */
+#define TIFFTAG_BASELINESHARPNESS 50732 /* &relative amount of
+ sharpening */
+#define TIFFTAG_BAYERGREENSPLIT 50733 /* &how closely the values of
+ the green pixels in the
+ blue/green rows track the
+ values of the green pixels
+ in the red/green rows */
+#define TIFFTAG_LINEARRESPONSELIMIT 50734 /* &non-linear encoding range */
+#define TIFFTAG_CAMERASERIALNUMBER 50735 /* &camera's serial number */
+#define TIFFTAG_LENSINFO 50736 /* info about the lens */
+#define TIFFTAG_CHROMABLURRADIUS 50737 /* &chroma blur radius */
+#define TIFFTAG_ANTIALIASSTRENGTH 50738 /* &relative strength of the
+ camera's anti-alias filter */
+#define TIFFTAG_SHADOWSCALE 50739 /* &used by Adobe Camera Raw */
+#define TIFFTAG_DNGPRIVATEDATA 50740 /* &manufacturer's private data */
+#define TIFFTAG_MAKERNOTESAFETY 50741 /* &whether the EXIF MakerNote
+ tag is safe to preserve
+ along with the rest of the
+ EXIF data */
+#define TIFFTAG_CALIBRATIONILLUMINANT1 50778 /* &illuminant 1 */
+#define TIFFTAG_CALIBRATIONILLUMINANT2 50779 /* &illuminant 2 */
+#define TIFFTAG_BESTQUALITYSCALE 50780 /* &best quality multiplier */
+#define TIFFTAG_RAWDATAUNIQUEID 50781 /* &unique identifier for
+ the raw image data */
+#define TIFFTAG_ORIGINALRAWFILENAME 50827 /* &file name of the original
+ raw file */
+#define TIFFTAG_ORIGINALRAWFILEDATA 50828 /* &contents of the original
+ raw file */
+#define TIFFTAG_ACTIVEAREA 50829 /* &active (non-masked) pixels
+ of the sensor */
+#define TIFFTAG_MASKEDAREAS 50830 /* &list of coordinates
+ of fully masked pixels */
+#define TIFFTAG_ASSHOTICCPROFILE 50831 /* &these two tags used to */
+#define TIFFTAG_ASSHOTPREPROFILEMATRIX 50832 /* map cameras's color space
+ into ICC profile space */
+#define TIFFTAG_CURRENTICCPROFILE 50833 /* & */
+#define TIFFTAG_CURRENTPREPROFILEMATRIX 50834 /* & */
+/* tag 65535 is an undefined tag used by Eastman Kodak */
+#define TIFFTAG_DCSHUESHIFTVALUES 65535 /* hue shift correction data */
+
+/*
+ * The following are ``pseudo tags'' that can be used to control
+ * codec-specific functionality. These tags are not written to file.
+ * Note that these values start at 0xffff+1 so that they'll never
+ * collide with Aldus-assigned tags.
+ *
+ * If you want your private pseudo tags ``registered'' (i.e. added to
+ * this file), please post a bug report via the tracking system at
+ * http://www.remotesensing.org/libtiff/bugs.html with the appropriate
+ * C definitions to add.
+ */
+#define TIFFTAG_FAXMODE 65536 /* Group 3/4 format control */
+#define FAXMODE_CLASSIC 0x0000 /* default, include RTC */
+#define FAXMODE_NORTC 0x0001 /* no RTC at end of data */
+#define FAXMODE_NOEOL 0x0002 /* no EOL code at end of row */
+#define FAXMODE_BYTEALIGN 0x0004 /* byte align row */
+#define FAXMODE_WORDALIGN 0x0008 /* word align row */
+#define FAXMODE_CLASSF FAXMODE_NORTC /* TIFF Class F */
+#define TIFFTAG_JPEGQUALITY 65537 /* Compression quality level */
+/* Note: quality level is on the IJG 0-100 scale. Default value is 75 */
+#define TIFFTAG_JPEGCOLORMODE 65538 /* Auto RGB<=>YCbCr convert? */
+#define JPEGCOLORMODE_RAW 0x0000 /* no conversion (default) */
+#define JPEGCOLORMODE_RGB 0x0001 /* do auto conversion */
+#define TIFFTAG_JPEGTABLESMODE 65539 /* What to put in JPEGTables */
+#define JPEGTABLESMODE_QUANT 0x0001 /* include quantization tbls */
+#define JPEGTABLESMODE_HUFF 0x0002 /* include Huffman tbls */
+/* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */
+#define TIFFTAG_FAXFILLFUNC 65540 /* G3/G4 fill function */
+#define TIFFTAG_PIXARLOGDATAFMT 65549 /* PixarLogCodec I/O data sz */
+#define PIXARLOGDATAFMT_8BIT 0 /* regular u_char samples */
+#define PIXARLOGDATAFMT_8BITABGR 1 /* ABGR-order u_chars */
+#define PIXARLOGDATAFMT_11BITLOG 2 /* 11-bit log-encoded (raw) */
+#define PIXARLOGDATAFMT_12BITPICIO 3 /* as per PICIO (1.0==2048) */
+#define PIXARLOGDATAFMT_16BIT 4 /* signed short samples */
+#define PIXARLOGDATAFMT_FLOAT 5 /* IEEE float samples */
+/* 65550-65556 are allocated to Oceana Matrix <dev@oceana.com> */
+#define TIFFTAG_DCSIMAGERTYPE 65550 /* imager model & filter */
+#define DCSIMAGERMODEL_M3 0 /* M3 chip (1280 x 1024) */
+#define DCSIMAGERMODEL_M5 1 /* M5 chip (1536 x 1024) */
+#define DCSIMAGERMODEL_M6 2 /* M6 chip (3072 x 2048) */
+#define DCSIMAGERFILTER_IR 0 /* infrared filter */
+#define DCSIMAGERFILTER_MONO 1 /* monochrome filter */
+#define DCSIMAGERFILTER_CFA 2 /* color filter array */
+#define DCSIMAGERFILTER_OTHER 3 /* other filter */
+#define TIFFTAG_DCSINTERPMODE 65551 /* interpolation mode */
+#define DCSINTERPMODE_NORMAL 0x0 /* whole image, default */
+#define DCSINTERPMODE_PREVIEW 0x1 /* preview of image (384x256) */
+#define TIFFTAG_DCSBALANCEARRAY 65552 /* color balance values */
+#define TIFFTAG_DCSCORRECTMATRIX 65553 /* color correction values */
+#define TIFFTAG_DCSGAMMA 65554 /* gamma value */
+#define TIFFTAG_DCSTOESHOULDERPTS 65555 /* toe & shoulder points */
+#define TIFFTAG_DCSCALIBRATIONFD 65556 /* calibration file desc */
+/* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */
+#define TIFFTAG_ZIPQUALITY 65557 /* compression quality level */
+#define TIFFTAG_PIXARLOGQUALITY 65558 /* PixarLog uses same scale */
+/* 65559 is allocated to Oceana Matrix <dev@oceana.com> */
+#define TIFFTAG_DCSCLIPRECTANGLE 65559 /* area of image to acquire */
+#define TIFFTAG_SGILOGDATAFMT 65560 /* SGILog user data format */
+#define SGILOGDATAFMT_FLOAT 0 /* IEEE float samples */
+#define SGILOGDATAFMT_16BIT 1 /* 16-bit samples */
+#define SGILOGDATAFMT_RAW 2 /* uninterpreted data */
+#define SGILOGDATAFMT_8BIT 3 /* 8-bit RGB monitor values */
+#define TIFFTAG_SGILOGENCODE 65561 /* SGILog data encoding control*/
+#define SGILOGENCODE_NODITHER 0 /* do not dither encoded values*/
+#define SGILOGENCODE_RANDITHER 1 /* randomly dither encd values */
+
+/*
+ * EXIF tags
+ */
+#define EXIFTAG_EXPOSURETIME 33434 /* Exposure time */
+#define EXIFTAG_FNUMBER 33437 /* F number */
+#define EXIFTAG_EXPOSUREPROGRAM 34850 /* Exposure program */
+#define EXIFTAG_SPECTRALSENSITIVITY 34852 /* Spectral sensitivity */
+#define EXIFTAG_ISOSPEEDRATINGS 34855 /* ISO speed rating */
+#define EXIFTAG_OECF 34856 /* Optoelectric conversion
+ factor */
+#define EXIFTAG_EXIFVERSION 36864 /* Exif version */
+#define EXIFTAG_DATETIMEORIGINAL 36867 /* Date and time of original
+ data generation */
+#define EXIFTAG_DATETIMEDIGITIZED 36868 /* Date and time of digital
+ data generation */
+#define EXIFTAG_COMPONENTSCONFIGURATION 37121 /* Meaning of each component */
+#define EXIFTAG_COMPRESSEDBITSPERPIXEL 37122 /* Image compression mode */
+#define EXIFTAG_SHUTTERSPEEDVALUE 37377 /* Shutter speed */
+#define EXIFTAG_APERTUREVALUE 37378 /* Aperture */
+#define EXIFTAG_BRIGHTNESSVALUE 37379 /* Brightness */
+#define EXIFTAG_EXPOSUREBIASVALUE 37380 /* Exposure bias */
+#define EXIFTAG_MAXAPERTUREVALUE 37381 /* Maximum lens aperture */
+#define EXIFTAG_SUBJECTDISTANCE 37382 /* Subject distance */
+#define EXIFTAG_METERINGMODE 37383 /* Metering mode */
+#define EXIFTAG_LIGHTSOURCE 37384 /* Light source */
+#define EXIFTAG_FLASH 37385 /* Flash */
+#define EXIFTAG_FOCALLENGTH 37386 /* Lens focal length */
+#define EXIFTAG_SUBJECTAREA 37396 /* Subject area */
+#define EXIFTAG_MAKERNOTE 37500 /* Manufacturer notes */
+#define EXIFTAG_USERCOMMENT 37510 /* User comments */
+#define EXIFTAG_SUBSECTIME 37520 /* DateTime subseconds */
+#define EXIFTAG_SUBSECTIMEORIGINAL 37521 /* DateTimeOriginal subseconds */
+#define EXIFTAG_SUBSECTIMEDIGITIZED 37522 /* DateTimeDigitized subseconds */
+#define EXIFTAG_FLASHPIXVERSION 40960 /* Supported Flashpix version */
+#define EXIFTAG_COLORSPACE 40961 /* Color space information */
+#define EXIFTAG_PIXELXDIMENSION 40962 /* Valid image width */
+#define EXIFTAG_PIXELYDIMENSION 40963 /* Valid image height */
+#define EXIFTAG_RELATEDSOUNDFILE 40964 /* Related audio file */
+#define EXIFTAG_FLASHENERGY 41483 /* Flash energy */
+#define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484 /* Spatial frequency response */
+#define EXIFTAG_FOCALPLANEXRESOLUTION 41486 /* Focal plane X resolution */
+#define EXIFTAG_FOCALPLANEYRESOLUTION 41487 /* Focal plane Y resolution */
+#define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488 /* Focal plane resolution unit */
+#define EXIFTAG_SUBJECTLOCATION 41492 /* Subject location */
+#define EXIFTAG_EXPOSUREINDEX 41493 /* Exposure index */
+#define EXIFTAG_SENSINGMETHOD 41495 /* Sensing method */
+#define EXIFTAG_FILESOURCE 41728 /* File source */
+#define EXIFTAG_SCENETYPE 41729 /* Scene type */
+#define EXIFTAG_CFAPATTERN 41730 /* CFA pattern */
+#define EXIFTAG_CUSTOMRENDERED 41985 /* Custom image processing */
+#define EXIFTAG_EXPOSUREMODE 41986 /* Exposure mode */
+#define EXIFTAG_WHITEBALANCE 41987 /* White balance */
+#define EXIFTAG_DIGITALZOOMRATIO 41988 /* Digital zoom ratio */
+#define EXIFTAG_FOCALLENGTHIN35MMFILM 41989 /* Focal length in 35 mm film */
+#define EXIFTAG_SCENECAPTURETYPE 41990 /* Scene capture type */
+#define EXIFTAG_GAINCONTROL 41991 /* Gain control */
+#define EXIFTAG_CONTRAST 41992 /* Contrast */
+#define EXIFTAG_SATURATION 41993 /* Saturation */
+#define EXIFTAG_SHARPNESS 41994 /* Sharpness */
+#define EXIFTAG_DEVICESETTINGDESCRIPTION 41995 /* Device settings description */
+#define EXIFTAG_SUBJECTDISTANCERANGE 41996 /* Subject distance range */
+#define EXIFTAG_GAINCONTROL 41991 /* Gain control */
+#define EXIFTAG_GAINCONTROL 41991 /* Gain control */
+#define EXIFTAG_IMAGEUNIQUEID 42016 /* Unique image ID */
+
+#endif /* _TIFF_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tiffconf.h-vms b/Source/LibTIFF/tiffconf.h-vms
new file mode 100644
index 0000000..de717ec
--- /dev/null
+++ b/Source/LibTIFF/tiffconf.h-vms
@@ -0,0 +1,99 @@
+/*
+ Configuration defines for installed libtiff.
+ This file maintained for backward compatibility. Do not use definitions
+ from this file in your programs.
+*/
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define to 1 if the system has the type `int16'. */
+//#define HAVE_INT16
+
+/* Define to 1 if the system has the type `int32'. */
+//#define HAVE_INT32
+
+/* Define to 1 if the system has the type `int8'. */
+//#define HAVE_INT8
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Compatibility stuff. */
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+#define HAVE_GETOPT 1
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
+#define HOST_BIGENDIAN 0
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#define JPEG_SUPPORT
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+ fails with unpatched IJG JPEG library) */
+/* #undef OJPEG_SUPPORT */
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+/* #undef PIXARLOG_SUPPORT */
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#define THUNDER_SUPPORT 1
+
+/* Support Deflate compression */
+/* #undef ZIP_SUPPORT */
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
+#define SUBIFD_SUPPORT 1
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#define CHECK_JPEG_YCBCR_SUBSAMPLING 1
+
+/*
+ * Feature support definitions.
+ * XXX: These macros are obsoleted. Don't use them in your apps!
+ * Macros stays here for backward compatibility and should be always defined.
+ */
+#define COLORIMETRY_SUPPORT
+#define YCBCR_SUPPORT
+#define CMYK_SUPPORT
+#define ICC_SUPPORT
+#define PHOTOSHOP_SUPPORT
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
diff --git a/Source/LibTIFF/tiffconf.h.in b/Source/LibTIFF/tiffconf.h.in
new file mode 100644
index 0000000..1a52b37
--- /dev/null
+++ b/Source/LibTIFF/tiffconf.h.in
@@ -0,0 +1,103 @@
+/*
+ Configuration defines for installed libtiff.
+ This file maintained for backward compatibility. Do not use definitions
+ from this file in your programs.
+*/
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define to 1 if the system has the type `int16'. */
+#undef HAVE_INT16
+
+/* Define to 1 if the system has the type `int32'. */
+#undef HAVE_INT32
+
+/* Define to 1 if the system has the type `int8'. */
+#undef HAVE_INT8
+
+/* The size of a `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of a `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* Compatibility stuff. */
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#undef HAVE_IEEEFP
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#undef HOST_FILLORDER
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
+#undef HOST_BIGENDIAN
+
+/* Support CCITT Group 3 & 4 algorithms */
+#undef CCITT_SUPPORT
+
+/* Support JPEG compression (requires IJG JPEG library) */
+#undef JPEG_SUPPORT
+
+/* Support JBIG compression (requires JBIG-KIT library) */
+#undef JBIG_SUPPORT
+
+/* Support LogLuv high dynamic range encoding */
+#undef LOGLUV_SUPPORT
+
+/* Support LZW algorithm */
+#undef LZW_SUPPORT
+
+/* Support NeXT 2-bit RLE algorithm */
+#undef NEXT_SUPPORT
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+ fails with unpatched IJG JPEG library) */
+#undef OJPEG_SUPPORT
+
+/* Support Macintosh PackBits algorithm */
+#undef PACKBITS_SUPPORT
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+#undef PIXARLOG_SUPPORT
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#undef THUNDER_SUPPORT
+
+/* Support Deflate compression */
+#undef ZIP_SUPPORT
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of ~8Kb to reduce memory usage) */
+#undef STRIPCHOP_DEFAULT
+
+/* Enable SubIFD tag (330) support */
+#undef SUBIFD_SUPPORT
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#undef DEFAULT_EXTRASAMPLE_AS_ALPHA
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#undef CHECK_JPEG_YCBCR_SUBSAMPLING
+
+/* Support MS MDI magic number files as TIFF */
+#undef MDI_SUPPORT
+
+/*
+ * Feature support definitions.
+ * XXX: These macros are obsoleted. Don't use them in your apps!
+ * Macros stays here for backward compatibility and should be always defined.
+ */
+#define COLORIMETRY_SUPPORT
+#define YCBCR_SUPPORT
+#define CMYK_SUPPORT
+#define ICC_SUPPORT
+#define PHOTOSHOP_SUPPORT
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
diff --git a/Source/LibTIFF/tiffconf.vc.h b/Source/LibTIFF/tiffconf.vc.h
new file mode 100644
index 0000000..9a0b152
--- /dev/null
+++ b/Source/LibTIFF/tiffconf.vc.h
@@ -0,0 +1,109 @@
+/*
+ Configuration defines for installed libtiff.
+ This file maintained for backward compatibility. Do not use definitions
+ from this file in your programs.
+*/
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define to 1 if the system has the type `int16'. */
+/* #undef HAVE_INT16 */
+
+/* Define to 1 if the system has the type `int32'. */
+/* #undef HAVE_INT32 */
+
+/* Define to 1 if the system has the type `int8'. */
+/* #undef HAVE_INT8 */
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Signed 64-bit type formatter */
+#define TIFF_INT64_FORMAT "%I64d"
+
+/* Signed 64-bit type */
+#define TIFF_INT64_T signed __int64
+
+/* Unsigned 64-bit type formatter */
+#define TIFF_UINT64_FORMAT "%I64u"
+
+/* Unsigned 64-bit type */
+#define TIFF_UINT64_T unsigned __int64
+
+/* Compatibility stuff. */
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
+#define HOST_BIGENDIAN 0
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Support JPEG compression (requires IJG JPEG library) */
+/* #undef JPEG_SUPPORT */
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+ fails with unpatched IJG JPEG library) */
+/* #undef OJPEG_SUPPORT */
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+/* #undef PIXARLOG_SUPPORT */
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#define THUNDER_SUPPORT 1
+
+/* Support Deflate compression */
+/* #undef ZIP_SUPPORT */
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
+#define SUBIFD_SUPPORT 1
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#define CHECK_JPEG_YCBCR_SUBSAMPLING 1
+
+/*
+ * Feature support definitions.
+ * XXX: These macros are obsoleted. Don't use them in your apps!
+ * Macros stays here for backward compatibility and should be always defined.
+ */
+#define COLORIMETRY_SUPPORT
+#define YCBCR_SUPPORT
+#define CMYK_SUPPORT
+#define ICC_SUPPORT
+#define PHOTOSHOP_SUPPORT
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
diff --git a/Source/LibTIFF/tiffconf.wince.h b/Source/LibTIFF/tiffconf.wince.h
new file mode 100644
index 0000000..8d31cd2
--- /dev/null
+++ b/Source/LibTIFF/tiffconf.wince.h
@@ -0,0 +1,129 @@
+/* $Id: tiffconf.wince.h,v 1.11 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Windows CE platform tiffconf.wince.h
+ * Created by Mateusz Loskot (mateusz@loskot.net)
+ *
+ * NOTE: Requires WCELIBCEX library with wceex_* functions,
+ * It's an extension to C library on Windows CE platform.
+ * For example, HAVE_STDIO_H definition indicates there are
+ * following files available:
+ * stdio.h - from Windows CE / Windows Mobile SDK
+ * wce_stdio.h - from WCELIBCEX library
+ */
+
+
+/*
+ Configuration defines for installed libtiff.
+ This file maintained for backward compatibility. Do not use definitions
+ from this file in your programs.
+*/
+
+#ifndef _WIN32_WCE
+# error This version of tif_config.h header is dedicated for Windows CE platform!
+#endif
+
+
+#ifndef _TIFFCONF_
+#define _TIFFCONF_
+
+/* Define to 1 if the system has the type `int16'. */
+/* #undef HAVE_INT16 */
+
+/* Define to 1 if the system has the type `int32'. */
+/* #undef HAVE_INT32 */
+
+/* Define to 1 if the system has the type `int8'. */
+/* #undef HAVE_INT8 */
+
+/* The size of a `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of a `long', as computed by sizeof. */
+#define SIZEOF_LONG 4
+
+/* Signed 64-bit type formatter */
+#define TIFF_INT64_FORMAT "%I64d"
+
+/* Signed 64-bit type */
+#define TIFF_INT64_T signed __int64
+
+/* Unsigned 64-bit type formatter */
+#define TIFF_UINT64_FORMAT "%I64u"
+
+/* Unsigned 64-bit type */
+#define TIFF_UINT64_T unsigned __int64
+
+/* Compatibility stuff. */
+
+/* Define as 0 or 1 according to the floating point format suported by the
+ machine */
+#define HAVE_IEEEFP 1
+
+/* Set the native cpu bit order (FILLORDER_LSB2MSB or FILLORDER_MSB2LSB) */
+#define HOST_FILLORDER FILLORDER_LSB2MSB
+
+/* Native cpu byte order: 1 if big-endian (Motorola) or 0 if little-endian
+ (Intel) */
+#define HOST_BIGENDIAN 0
+
+/* Support CCITT Group 3 & 4 algorithms */
+#define CCITT_SUPPORT 1
+
+/* Support JPEG compression (requires IJG JPEG library) */
+/* #undef JPEG_SUPPORT */
+
+/* Support LogLuv high dynamic range encoding */
+#define LOGLUV_SUPPORT 1
+
+/* Support LZW algorithm */
+#define LZW_SUPPORT 1
+
+/* Support NeXT 2-bit RLE algorithm */
+#define NEXT_SUPPORT 1
+
+/* Support Old JPEG compresson (read contrib/ojpeg/README first! Compilation
+ fails with unpatched IJG JPEG library) */
+/* #undef OJPEG_SUPPORT */
+
+/* Support Macintosh PackBits algorithm */
+#define PACKBITS_SUPPORT 1
+
+/* Support Pixar log-format algorithm (requires Zlib) */
+/* #undef PIXARLOG_SUPPORT */
+
+/* Support ThunderScan 4-bit RLE algorithm */
+#define THUNDER_SUPPORT 1
+
+/* Support Deflate compression */
+/* #undef ZIP_SUPPORT */
+
+/* Support strip chopping (whether or not to convert single-strip uncompressed
+ images to mutiple strips of ~8Kb to reduce memory usage) */
+#define STRIPCHOP_DEFAULT TIFF_STRIPCHOP
+
+/* Enable SubIFD tag (330) support */
+#define SUBIFD_SUPPORT 1
+
+/* Treat extra sample as alpha (default enabled). The RGBA interface will
+ treat a fourth sample with no EXTRASAMPLE_ value as being ASSOCALPHA. Many
+ packages produce RGBA files but don't mark the alpha properly. */
+#define DEFAULT_EXTRASAMPLE_AS_ALPHA 1
+
+/* Pick up YCbCr subsampling info from the JPEG data stream to support files
+ lacking the tag (default enabled). */
+#define CHECK_JPEG_YCBCR_SUBSAMPLING 1
+
+/*
+ * Feature support definitions.
+ * XXX: These macros are obsoleted. Don't use them in your apps!
+ * Macros stays here for backward compatibility and should be always defined.
+ */
+#define COLORIMETRY_SUPPORT
+#define YCBCR_SUPPORT
+#define CMYK_SUPPORT
+#define ICC_SUPPORT
+#define PHOTOSHOP_SUPPORT
+#define IPTC_SUPPORT
+
+#endif /* _TIFFCONF_ */
diff --git a/Source/LibTIFF/tiffio.h b/Source/LibTIFF/tiffio.h
new file mode 100644
index 0000000..0388b1b
--- /dev/null
+++ b/Source/LibTIFF/tiffio.h
@@ -0,0 +1,519 @@
+/* $Id: tiffio.h,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIO_
+#define _TIFFIO_
+
+/*
+ * TIFF I/O Library Definitions.
+ */
+#include "tiff.h"
+#include "tiffvers.h"
+
+/*
+ * TIFF is defined as an incomplete type to hide the
+ * library's internal data structures from clients.
+ */
+typedef struct tiff TIFF;
+
+/*
+ * The following typedefs define the intrinsic size of
+ * data types used in the *exported* interfaces. These
+ * definitions depend on the proper definition of types
+ * in tiff.h. Note also that the varargs interface used
+ * to pass tag types and values uses the types defined in
+ * tiff.h directly.
+ *
+ * NB: ttag_t is unsigned int and not unsigned short because
+ * ANSI C requires that the type before the ellipsis be a
+ * promoted type (i.e. one of int, unsigned int, pointer,
+ * or double) and because we defined pseudo-tags that are
+ * outside the range of legal Aldus-assigned tags.
+ * NB: tsize_t is int32 and not uint32 because some functions
+ * return -1.
+ * NB: toff_t is not off_t for many reasons; TIFFs max out at
+ * 32-bit file offsets being the most important, and to ensure
+ * that it is unsigned, rather than signed.
+ */
+typedef uint32 ttag_t; /* directory tag */
+typedef uint16 tdir_t; /* directory index */
+typedef uint16 tsample_t; /* sample number */
+typedef uint32 tstrile_t; /* strip or tile number */
+typedef tstrile_t tstrip_t; /* strip number */
+typedef tstrile_t ttile_t; /* tile number */
+typedef int32 tsize_t; /* i/o size in bytes */
+typedef void* tdata_t; /* image data ref */
+typedef uint32 toff_t; /* file offset */
+
+#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32))
+#define __WIN32__
+#endif
+
+/*
+ * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c
+ * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c).
+ *
+ * By default tif_unix.c is assumed.
+ */
+
+#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows)
+# if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && !defined(USE_WIN32_FILEIO)
+# define AVOID_WIN32_FILEIO
+# endif
+#endif
+
+#if defined(USE_WIN32_FILEIO)
+# define VC_EXTRALEAN
+# include <windows.h>
+# ifdef __WIN32__
+DECLARE_HANDLE(thandle_t); /* Win32 file handle */
+# else
+typedef HFILE thandle_t; /* client data handle */
+# endif /* __WIN32__ */
+#else
+typedef void* thandle_t; /* client data handle */
+#endif /* USE_WIN32_FILEIO */
+
+/*
+ * Flags to pass to TIFFPrintDirectory to control
+ * printing of data structures that are potentially
+ * very large. Bit-or these flags to enable printing
+ * multiple items.
+ */
+#define TIFFPRINT_NONE 0x0 /* no extra info */
+#define TIFFPRINT_STRIPS 0x1 /* strips/tiles info */
+#define TIFFPRINT_CURVES 0x2 /* color/gray response curves */
+#define TIFFPRINT_COLORMAP 0x4 /* colormap */
+#define TIFFPRINT_JPEGQTABLES 0x100 /* JPEG Q matrices */
+#define TIFFPRINT_JPEGACTABLES 0x200 /* JPEG AC tables */
+#define TIFFPRINT_JPEGDCTABLES 0x200 /* JPEG DC tables */
+
+/*
+ * Colour conversion stuff
+ */
+
+/* reference white */
+#define D65_X0 (95.0470F)
+#define D65_Y0 (100.0F)
+#define D65_Z0 (108.8827F)
+
+#define D50_X0 (96.4250F)
+#define D50_Y0 (100.0F)
+#define D50_Z0 (82.4680F)
+
+/* Structure for holding information about a display device. */
+
+typedef unsigned char TIFFRGBValue; /* 8-bit samples */
+
+typedef struct {
+ float d_mat[3][3]; /* XYZ -> luminance matrix */
+ float d_YCR; /* Light o/p for reference white */
+ float d_YCG;
+ float d_YCB;
+ uint32 d_Vrwr; /* Pixel values for ref. white */
+ uint32 d_Vrwg;
+ uint32 d_Vrwb;
+ float d_Y0R; /* Residual light for black pixel */
+ float d_Y0G;
+ float d_Y0B;
+ float d_gammaR; /* Gamma values for the three guns */
+ float d_gammaG;
+ float d_gammaB;
+} TIFFDisplay;
+
+typedef struct { /* YCbCr->RGB support */
+ TIFFRGBValue* clamptab; /* range clamping table */
+ int* Cr_r_tab;
+ int* Cb_b_tab;
+ int32* Cr_g_tab;
+ int32* Cb_g_tab;
+ int32* Y_tab;
+} TIFFYCbCrToRGB;
+
+typedef struct { /* CIE Lab 1976->RGB support */
+ int range; /* Size of conversion table */
+#define CIELABTORGB_TABLE_RANGE 1500
+ float rstep, gstep, bstep;
+ float X0, Y0, Z0; /* Reference white point */
+ TIFFDisplay display;
+ float Yr2r[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yr to r */
+ float Yg2g[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yg to g */
+ float Yb2b[CIELABTORGB_TABLE_RANGE + 1]; /* Conversion of Yb to b */
+} TIFFCIELabToRGB;
+
+/*
+ * RGBA-style image support.
+ */
+typedef struct _TIFFRGBAImage TIFFRGBAImage;
+/*
+ * The image reading and conversion routines invoke
+ * ``put routines'' to copy/image/whatever tiles of
+ * raw image data. A default set of routines are
+ * provided to convert/copy raw image data to 8-bit
+ * packed ABGR format rasters. Applications can supply
+ * alternate routines that unpack the data into a
+ * different format or, for example, unpack the data
+ * and draw the unpacked raster on the display.
+ */
+typedef void (*tileContigRoutine)
+ (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32,
+ unsigned char*);
+typedef void (*tileSeparateRoutine)
+ (TIFFRGBAImage*, uint32*, uint32, uint32, uint32, uint32, int32, int32,
+ unsigned char*, unsigned char*, unsigned char*, unsigned char*);
+/*
+ * RGBA-reader state.
+ */
+struct _TIFFRGBAImage {
+ TIFF* tif; /* image handle */
+ int stoponerr; /* stop on read error */
+ int isContig; /* data is packed/separate */
+ int alpha; /* type of alpha data present */
+ uint32 width; /* image width */
+ uint32 height; /* image height */
+ uint16 bitspersample; /* image bits/sample */
+ uint16 samplesperpixel; /* image samples/pixel */
+ uint16 orientation; /* image orientation */
+ uint16 req_orientation; /* requested orientation */
+ uint16 photometric; /* image photometric interp */
+ uint16* redcmap; /* colormap pallete */
+ uint16* greencmap;
+ uint16* bluecmap;
+ /* get image data routine */
+ int (*get)(TIFFRGBAImage*, uint32*, uint32, uint32);
+ /* put decoded strip/tile */
+ union {
+ void (*any)(TIFFRGBAImage*);
+ tileContigRoutine contig;
+ tileSeparateRoutine separate;
+ } put;
+ TIFFRGBValue* Map; /* sample mapping array */
+ uint32** BWmap; /* black&white map */
+ uint32** PALmap; /* palette image map */
+ TIFFYCbCrToRGB* ycbcr; /* YCbCr conversion state */
+ TIFFCIELabToRGB* cielab; /* CIE L*a*b conversion state */
+
+ int row_offset;
+ int col_offset;
+};
+
+/*
+ * Macros for extracting components from the
+ * packed ABGR form returned by TIFFReadRGBAImage.
+ */
+#define TIFFGetR(abgr) ((abgr) & 0xff)
+#define TIFFGetG(abgr) (((abgr) >> 8) & 0xff)
+#define TIFFGetB(abgr) (((abgr) >> 16) & 0xff)
+#define TIFFGetA(abgr) (((abgr) >> 24) & 0xff)
+
+/*
+ * A CODEC is a software package that implements decoding,
+ * encoding, or decoding+encoding of a compression algorithm.
+ * The library provides a collection of builtin codecs.
+ * More codecs may be registered through calls to the library
+ * and/or the builtin implementations may be overridden.
+ */
+typedef int (*TIFFInitMethod)(TIFF*, int);
+typedef struct {
+ char* name;
+ uint16 scheme;
+ TIFFInitMethod init;
+} TIFFCodec;
+
+#include <stdio.h>
+#include <stdarg.h>
+
+/* share internal LogLuv conversion routines? */
+#ifndef LOGLUV_PUBLIC
+#define LOGLUV_PUBLIC 1
+#endif
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+# define __attribute__(x) /*nothing*/
+#endif
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern "C" {
+#endif
+typedef void (*TIFFErrorHandler)(const char*, const char*, va_list);
+typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list);
+typedef tsize_t (*TIFFReadWriteProc)(thandle_t, tdata_t, tsize_t);
+typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int);
+typedef int (*TIFFCloseProc)(thandle_t);
+typedef toff_t (*TIFFSizeProc)(thandle_t);
+typedef int (*TIFFMapFileProc)(thandle_t, tdata_t*, toff_t*);
+typedef void (*TIFFUnmapFileProc)(thandle_t, tdata_t, toff_t);
+typedef void (*TIFFExtendProc)(TIFF*);
+
+extern const char* TIFFGetVersion(void);
+
+extern const TIFFCodec* TIFFFindCODEC(uint16);
+extern TIFFCodec* TIFFRegisterCODEC(uint16, const char*, TIFFInitMethod);
+extern void TIFFUnRegisterCODEC(TIFFCodec*);
+extern int TIFFIsCODECConfigured(uint16);
+extern TIFFCodec* TIFFGetConfiguredCODECs(void);
+
+/*
+ * Auxiliary functions.
+ */
+
+extern tdata_t _TIFFmalloc(tsize_t);
+extern tdata_t _TIFFrealloc(tdata_t, tsize_t);
+extern void _TIFFmemset(tdata_t, int, tsize_t);
+extern void _TIFFmemcpy(tdata_t, const tdata_t, tsize_t);
+extern int _TIFFmemcmp(const tdata_t, const tdata_t, tsize_t);
+extern void _TIFFfree(tdata_t);
+
+/*
+** Stuff, related to tag handling and creating custom tags.
+*/
+extern int TIFFGetTagListCount( TIFF * );
+extern ttag_t TIFFGetTagListEntry( TIFF *, int tag_index );
+
+#define TIFF_ANY TIFF_NOTYPE /* for field descriptor searching */
+#define TIFF_VARIABLE -1 /* marker for variable length tags */
+#define TIFF_SPP -2 /* marker for SamplesPerPixel tags */
+#define TIFF_VARIABLE2 -3 /* marker for uint32 var-length tags */
+
+#define FIELD_CUSTOM 65
+
+typedef struct {
+ ttag_t field_tag; /* field's tag */
+ short field_readcount; /* read count/TIFF_VARIABLE/TIFF_SPP */
+ short field_writecount; /* write count/TIFF_VARIABLE */
+ TIFFDataType field_type; /* type of associated data */
+ unsigned short field_bit; /* bit in fieldsset bit vector */
+ unsigned char field_oktochange; /* if true, can change while writing */
+ unsigned char field_passcount; /* if true, pass dir count on set */
+ char *field_name; /* ASCII name */
+} TIFFFieldInfo;
+
+typedef struct _TIFFTagValue {
+ const TIFFFieldInfo *info;
+ int count;
+ void *value;
+} TIFFTagValue;
+
+extern void TIFFMergeFieldInfo(TIFF*, const TIFFFieldInfo[], int);
+extern const TIFFFieldInfo* TIFFFindFieldInfo(TIFF*, ttag_t, TIFFDataType);
+extern const TIFFFieldInfo* TIFFFindFieldInfoByName(TIFF* , const char *,
+ TIFFDataType);
+extern const TIFFFieldInfo* TIFFFieldWithTag(TIFF*, ttag_t);
+extern const TIFFFieldInfo* TIFFFieldWithName(TIFF*, const char *);
+
+typedef int (*TIFFVSetMethod)(TIFF*, ttag_t, va_list);
+typedef int (*TIFFVGetMethod)(TIFF*, ttag_t, va_list);
+typedef void (*TIFFPrintMethod)(TIFF*, FILE*, long);
+
+typedef struct {
+ TIFFVSetMethod vsetfield; /* tag set routine */
+ TIFFVGetMethod vgetfield; /* tag get routine */
+ TIFFPrintMethod printdir; /* directory print routine */
+} TIFFTagMethods;
+
+extern TIFFTagMethods *TIFFAccessTagMethods( TIFF * );
+extern void *TIFFGetClientInfo( TIFF *, const char * );
+extern void TIFFSetClientInfo( TIFF *, void *, const char * );
+
+extern void TIFFCleanup(TIFF*);
+extern void TIFFClose(TIFF*);
+extern int TIFFFlush(TIFF*);
+extern int TIFFFlushData(TIFF*);
+extern int TIFFGetField(TIFF*, ttag_t, ...);
+extern int TIFFVGetField(TIFF*, ttag_t, va_list);
+extern int TIFFGetFieldDefaulted(TIFF*, ttag_t, ...);
+extern int TIFFVGetFieldDefaulted(TIFF*, ttag_t, va_list);
+extern int TIFFReadDirectory(TIFF*);
+extern int TIFFReadCustomDirectory(TIFF*, toff_t, const TIFFFieldInfo[],
+ size_t);
+extern int TIFFReadEXIFDirectory(TIFF*, toff_t);
+extern tsize_t TIFFScanlineSize(TIFF*);
+extern tsize_t TIFFOldScanlineSize(TIFF*);
+extern tsize_t TIFFNewScanlineSize(TIFF*);
+extern tsize_t TIFFRasterScanlineSize(TIFF*);
+extern tsize_t TIFFStripSize(TIFF*);
+extern tsize_t TIFFRawStripSize(TIFF*, tstrip_t);
+extern tsize_t TIFFVStripSize(TIFF*, uint32);
+extern tsize_t TIFFTileRowSize(TIFF*);
+extern tsize_t TIFFTileSize(TIFF*);
+extern tsize_t TIFFVTileSize(TIFF*, uint32);
+extern uint32 TIFFDefaultStripSize(TIFF*, uint32);
+extern void TIFFDefaultTileSize(TIFF*, uint32*, uint32*);
+extern int TIFFFileno(TIFF*);
+extern int TIFFSetFileno(TIFF*, int);
+extern thandle_t TIFFClientdata(TIFF*);
+extern thandle_t TIFFSetClientdata(TIFF*, thandle_t);
+extern int TIFFGetMode(TIFF*);
+extern int TIFFSetMode(TIFF*, int);
+extern int TIFFIsTiled(TIFF*);
+extern int TIFFIsByteSwapped(TIFF*);
+extern int TIFFIsUpSampled(TIFF*);
+extern int TIFFIsMSB2LSB(TIFF*);
+extern int TIFFIsBigEndian(TIFF*);
+extern TIFFReadWriteProc TIFFGetReadProc(TIFF*);
+extern TIFFReadWriteProc TIFFGetWriteProc(TIFF*);
+extern TIFFSeekProc TIFFGetSeekProc(TIFF*);
+extern TIFFCloseProc TIFFGetCloseProc(TIFF*);
+extern TIFFSizeProc TIFFGetSizeProc(TIFF*);
+extern TIFFMapFileProc TIFFGetMapFileProc(TIFF*);
+extern TIFFUnmapFileProc TIFFGetUnmapFileProc(TIFF*);
+extern uint32 TIFFCurrentRow(TIFF*);
+extern tdir_t TIFFCurrentDirectory(TIFF*);
+extern tdir_t TIFFNumberOfDirectories(TIFF*);
+extern uint32 TIFFCurrentDirOffset(TIFF*);
+extern tstrip_t TIFFCurrentStrip(TIFF*);
+extern ttile_t TIFFCurrentTile(TIFF*);
+extern int TIFFReadBufferSetup(TIFF*, tdata_t, tsize_t);
+extern int TIFFWriteBufferSetup(TIFF*, tdata_t, tsize_t);
+extern int TIFFSetupStrips(TIFF *);
+extern int TIFFWriteCheck(TIFF*, int, const char *);
+extern void TIFFFreeDirectory(TIFF*);
+extern int TIFFCreateDirectory(TIFF*);
+extern int TIFFLastDirectory(TIFF*);
+extern int TIFFSetDirectory(TIFF*, tdir_t);
+extern int TIFFSetSubDirectory(TIFF*, uint32);
+extern int TIFFUnlinkDirectory(TIFF*, tdir_t);
+extern int TIFFSetField(TIFF*, ttag_t, ...);
+extern int TIFFVSetField(TIFF*, ttag_t, va_list);
+extern int TIFFWriteDirectory(TIFF *);
+extern int TIFFCheckpointDirectory(TIFF *);
+extern int TIFFRewriteDirectory(TIFF *);
+extern int TIFFReassignTagToIgnore(enum TIFFIgnoreSense, int);
+
+#if defined(c_plusplus) || defined(__cplusplus)
+extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0);
+extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t = 0);
+extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t = 0);
+extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int = 0);
+extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*,
+ int = ORIENTATION_BOTLEFT, int = 0);
+#else
+extern void TIFFPrintDirectory(TIFF*, FILE*, long);
+extern int TIFFReadScanline(TIFF*, tdata_t, uint32, tsample_t);
+extern int TIFFWriteScanline(TIFF*, tdata_t, uint32, tsample_t);
+extern int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int);
+extern int TIFFReadRGBAImageOriented(TIFF*, uint32, uint32, uint32*, int, int);
+#endif
+
+extern int TIFFReadRGBAStrip(TIFF*, tstrip_t, uint32 * );
+extern int TIFFReadRGBATile(TIFF*, uint32, uint32, uint32 * );
+extern int TIFFRGBAImageOK(TIFF*, char [1024]);
+extern int TIFFRGBAImageBegin(TIFFRGBAImage*, TIFF*, int, char [1024]);
+extern int TIFFRGBAImageGet(TIFFRGBAImage*, uint32*, uint32, uint32);
+extern void TIFFRGBAImageEnd(TIFFRGBAImage*);
+extern TIFF* TIFFOpen(const char*, const char*);
+# ifdef __WIN32__
+extern TIFF* TIFFOpenW(const wchar_t*, const char*);
+# endif /* __WIN32__ */
+extern TIFF* TIFFFdOpen(int, const char*, const char*);
+extern TIFF* TIFFClientOpen(const char*, const char*,
+ thandle_t,
+ TIFFReadWriteProc, TIFFReadWriteProc,
+ TIFFSeekProc, TIFFCloseProc,
+ TIFFSizeProc,
+ TIFFMapFileProc, TIFFUnmapFileProc);
+extern const char* TIFFFileName(TIFF*);
+extern const char* TIFFSetFileName(TIFF*, const char *);
+extern void TIFFError(const char*, const char*, ...) __attribute__((format (printf,2,3)));
+extern void TIFFErrorExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4)));
+extern void TIFFWarning(const char*, const char*, ...) __attribute__((format (printf,2,3)));
+extern void TIFFWarningExt(thandle_t, const char*, const char*, ...) __attribute__((format (printf,3,4)));
+extern TIFFErrorHandler TIFFSetErrorHandler(TIFFErrorHandler);
+extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt);
+extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler);
+extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt);
+extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc);
+extern ttile_t TIFFComputeTile(TIFF*, uint32, uint32, uint32, tsample_t);
+extern int TIFFCheckTile(TIFF*, uint32, uint32, uint32, tsample_t);
+extern ttile_t TIFFNumberOfTiles(TIFF*);
+extern tsize_t TIFFReadTile(TIFF*,
+ tdata_t, uint32, uint32, uint32, tsample_t);
+extern tsize_t TIFFWriteTile(TIFF*,
+ tdata_t, uint32, uint32, uint32, tsample_t);
+extern tstrip_t TIFFComputeStrip(TIFF*, uint32, tsample_t);
+extern tstrip_t TIFFNumberOfStrips(TIFF*);
+extern tsize_t TIFFReadEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern tsize_t TIFFReadRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern tsize_t TIFFReadEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern tsize_t TIFFReadRawTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern tsize_t TIFFWriteEncodedStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern tsize_t TIFFWriteRawStrip(TIFF*, tstrip_t, tdata_t, tsize_t);
+extern tsize_t TIFFWriteEncodedTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern tsize_t TIFFWriteRawTile(TIFF*, ttile_t, tdata_t, tsize_t);
+extern int TIFFDataWidth(TIFFDataType); /* table of tag datatype widths */
+extern void TIFFSetWriteOffset(TIFF*, toff_t);
+extern void TIFFSwabShort(uint16*);
+extern void TIFFSwabLong(uint32*);
+extern void TIFFSwabDouble(double*);
+extern void TIFFSwabArrayOfShort(uint16*, unsigned long);
+extern void TIFFSwabArrayOfTriples(uint8*, unsigned long);
+extern void TIFFSwabArrayOfLong(uint32*, unsigned long);
+extern void TIFFSwabArrayOfDouble(double*, unsigned long);
+extern void TIFFReverseBits(unsigned char *, unsigned long);
+extern const unsigned char* TIFFGetBitRevTable(int);
+
+#ifdef LOGLUV_PUBLIC
+#define U_NEU 0.210526316
+#define V_NEU 0.473684211
+#define UVSCALE 410.
+extern double LogL16toY(int);
+extern double LogL10toY(int);
+extern void XYZtoRGB24(float*, uint8*);
+extern int uv_decode(double*, double*, int);
+extern void LogLuv24toXYZ(uint32, float*);
+extern void LogLuv32toXYZ(uint32, float*);
+#if defined(c_plusplus) || defined(__cplusplus)
+extern int LogL16fromY(double, int = SGILOGENCODE_NODITHER);
+extern int LogL10fromY(double, int = SGILOGENCODE_NODITHER);
+extern int uv_encode(double, double, int = SGILOGENCODE_NODITHER);
+extern uint32 LogLuv24fromXYZ(float*, int = SGILOGENCODE_NODITHER);
+extern uint32 LogLuv32fromXYZ(float*, int = SGILOGENCODE_NODITHER);
+#else
+extern int LogL16fromY(double, int);
+extern int LogL10fromY(double, int);
+extern int uv_encode(double, double, int);
+extern uint32 LogLuv24fromXYZ(float*, int);
+extern uint32 LogLuv32fromXYZ(float*, int);
+#endif
+#endif /* LOGLUV_PUBLIC */
+
+extern int TIFFCIELabToRGBInit(TIFFCIELabToRGB*, TIFFDisplay *, float*);
+extern void TIFFCIELabToXYZ(TIFFCIELabToRGB *, uint32, int32, int32,
+ float *, float *, float *);
+extern void TIFFXYZToRGB(TIFFCIELabToRGB *, float, float, float,
+ uint32 *, uint32 *, uint32 *);
+
+extern int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB*, float*, float*);
+extern void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *, uint32, int32, int32,
+ uint32 *, uint32 *, uint32 *);
+
+#if defined(c_plusplus) || defined(__cplusplus)
+}
+#endif
+
+#endif /* _TIFFIO_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tiffio.hxx b/Source/LibTIFF/tiffio.hxx
new file mode 100644
index 0000000..885a612
--- /dev/null
+++ b/Source/LibTIFF/tiffio.hxx
@@ -0,0 +1,42 @@
+/* $Id: tiffio.hxx,v 1.22 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIO_HXX_
+#define _TIFFIO_HXX_
+
+/*
+ * TIFF I/O library definitions which provide C++ streams API.
+ */
+
+#include <iostream>
+#include "tiff.h"
+
+extern TIFF* TIFFStreamOpen(const char*, std::ostream *);
+extern TIFF* TIFFStreamOpen(const char*, std::istream *);
+
+#endif /* _TIFFIO_HXX_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tiffiop.h b/Source/LibTIFF/tiffiop.h
new file mode 100644
index 0000000..9333c14
--- /dev/null
+++ b/Source/LibTIFF/tiffiop.h
@@ -0,0 +1,338 @@
+/* $Id: tiffiop.h,v 1.27 2009/09/06 13:11:29 drolon Exp $ */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _TIFFIOP_
+#define _TIFFIOP_
+/*
+ * ``Library-private'' definitions.
+ */
+
+#include "tif_config.h"
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+# include <assert.h>
+#else
+# define assert(x)
+#endif
+
+#ifdef HAVE_SEARCH_H
+# include <search.h>
+#else
+extern void *lfind(const void *, const void *, size_t *, size_t,
+ int (*)(const void *, const void *));
+#endif
+
+/*
+ Libtiff itself does not require a 64-bit type, but bundled TIFF
+ utilities may use it.
+*/
+#define TIFF_INT64_T signed long long
+#define TIFF_UINT64_T unsigned long long
+
+#include "tiffio.h"
+#include "tif_dir.h"
+
+#ifndef STRIP_SIZE_DEFAULT
+# define STRIP_SIZE_DEFAULT 8192
+#endif
+
+#define streq(a,b) (strcmp(a,b) == 0)
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+typedef struct client_info {
+ struct client_info *next;
+ void *data;
+ char *name;
+} TIFFClientInfoLink;
+
+/*
+ * Typedefs for ``method pointers'' used internally.
+ */
+typedef unsigned char tidataval_t; /* internal image data value type */
+typedef tidataval_t* tidata_t; /* reference to internal image data */
+
+typedef void (*TIFFVoidMethod)(TIFF*);
+typedef int (*TIFFBoolMethod)(TIFF*);
+typedef int (*TIFFPreMethod)(TIFF*, tsample_t);
+typedef int (*TIFFCodeMethod)(TIFF*, tidata_t, tsize_t, tsample_t);
+typedef int (*TIFFSeekMethod)(TIFF*, uint32);
+typedef void (*TIFFPostMethod)(TIFF*, tidata_t, tsize_t);
+typedef uint32 (*TIFFStripMethod)(TIFF*, uint32);
+typedef void (*TIFFTileMethod)(TIFF*, uint32*, uint32*);
+
+struct tiff {
+ char* tif_name; /* name of open file */
+ int tif_fd; /* open file descriptor */
+ int tif_mode; /* open mode (O_*) */
+ uint32 tif_flags;
+#define TIFF_FILLORDER 0x00003 /* natural bit fill order for machine */
+#define TIFF_DIRTYHEADER 0x00004 /* header must be written on close */
+#define TIFF_DIRTYDIRECT 0x00008 /* current directory must be written */
+#define TIFF_BUFFERSETUP 0x00010 /* data buffers setup */
+#define TIFF_CODERSETUP 0x00020 /* encoder/decoder setup done */
+#define TIFF_BEENWRITING 0x00040 /* written 1+ scanlines to file */
+#define TIFF_SWAB 0x00080 /* byte swap file information */
+#define TIFF_NOBITREV 0x00100 /* inhibit bit reversal logic */
+#define TIFF_MYBUFFER 0x00200 /* my raw data buffer; free on close */
+#define TIFF_ISTILED 0x00400 /* file is tile, not strip- based */
+#define TIFF_MAPPED 0x00800 /* file is mapped into memory */
+#define TIFF_POSTENCODE 0x01000 /* need call to postencode routine */
+#define TIFF_INSUBIFD 0x02000 /* currently writing a subifd */
+#define TIFF_UPSAMPLED 0x04000 /* library is doing data up-sampling */
+#define TIFF_STRIPCHOP 0x08000 /* enable strip chopping support */
+#define TIFF_HEADERONLY 0x10000 /* read header only, do not process */
+ /* the first directory */
+#define TIFF_NOREADRAW 0x20000 /* skip reading of raw uncompressed */
+ /* image data */
+#define TIFF_INCUSTOMIFD 0x40000 /* currently writing a custom IFD */
+ toff_t tif_diroff; /* file offset of current directory */
+ toff_t tif_nextdiroff; /* file offset of following directory */
+ toff_t* tif_dirlist; /* list of offsets to already seen */
+ /* directories to prevent IFD looping */
+ tsize_t tif_dirlistsize;/* number of entires in offset list */
+ uint16 tif_dirnumber; /* number of already seen directories */
+ TIFFDirectory tif_dir; /* internal rep of current directory */
+ TIFFDirectory tif_customdir; /* custom IFDs are separated from
+ the main ones */
+ TIFFHeader tif_header; /* file's header block */
+ const int* tif_typeshift; /* data type shift counts */
+ const long* tif_typemask; /* data type masks */
+ uint32 tif_row; /* current scanline */
+ tdir_t tif_curdir; /* current directory (index) */
+ tstrip_t tif_curstrip; /* current strip for read/write */
+ toff_t tif_curoff; /* current offset for read/write */
+ toff_t tif_dataoff; /* current offset for writing dir */
+/* SubIFD support */
+ uint16 tif_nsubifd; /* remaining subifds to write */
+ toff_t tif_subifdoff; /* offset for patching SubIFD link */
+/* tiling support */
+ uint32 tif_col; /* current column (offset by row too) */
+ ttile_t tif_curtile; /* current tile for read/write */
+ tsize_t tif_tilesize; /* # of bytes in a tile */
+/* compression scheme hooks */
+ int tif_decodestatus;
+ TIFFBoolMethod tif_setupdecode;/* called once before predecode */
+ TIFFPreMethod tif_predecode; /* pre- row/strip/tile decoding */
+ TIFFBoolMethod tif_setupencode;/* called once before preencode */
+ int tif_encodestatus;
+ TIFFPreMethod tif_preencode; /* pre- row/strip/tile encoding */
+ TIFFBoolMethod tif_postencode; /* post- row/strip/tile encoding */
+ TIFFCodeMethod tif_decoderow; /* scanline decoding routine */
+ TIFFCodeMethod tif_encoderow; /* scanline encoding routine */
+ TIFFCodeMethod tif_decodestrip;/* strip decoding routine */
+ TIFFCodeMethod tif_encodestrip;/* strip encoding routine */
+ TIFFCodeMethod tif_decodetile; /* tile decoding routine */
+ TIFFCodeMethod tif_encodetile; /* tile encoding routine */
+ TIFFVoidMethod tif_close; /* cleanup-on-close routine */
+ TIFFSeekMethod tif_seek; /* position within a strip routine */
+ TIFFVoidMethod tif_cleanup; /* cleanup state routine */
+ TIFFStripMethod tif_defstripsize;/* calculate/constrain strip size */
+ TIFFTileMethod tif_deftilesize;/* calculate/constrain tile size */
+ tidata_t tif_data; /* compression scheme private data */
+/* input/output buffering */
+ tsize_t tif_scanlinesize;/* # of bytes in a scanline */
+ tsize_t tif_scanlineskew;/* scanline skew for reading strips */
+ tidata_t tif_rawdata; /* raw data buffer */
+ tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */
+ tidata_t tif_rawcp; /* current spot in raw buffer */
+ tsize_t tif_rawcc; /* bytes unread from raw buffer */
+/* memory-mapped file support */
+ tidata_t tif_base; /* base of mapped file */
+ toff_t tif_size; /* size of mapped file region (bytes)
+ FIXME: it should be tsize_t */
+ TIFFMapFileProc tif_mapproc; /* map file method */
+ TIFFUnmapFileProc tif_unmapproc;/* unmap file method */
+/* input/output callback methods */
+ thandle_t tif_clientdata; /* callback parameter */
+ TIFFReadWriteProc tif_readproc; /* read method */
+ TIFFReadWriteProc tif_writeproc;/* write method */
+ TIFFSeekProc tif_seekproc; /* lseek method */
+ TIFFCloseProc tif_closeproc; /* close method */
+ TIFFSizeProc tif_sizeproc; /* filesize method */
+/* post-decoding support */
+ TIFFPostMethod tif_postdecode; /* post decoding routine */
+/* tag support */
+ TIFFFieldInfo** tif_fieldinfo; /* sorted table of registered tags */
+ size_t tif_nfields; /* # entries in registered tag table */
+ const TIFFFieldInfo *tif_foundfield;/* cached pointer to already found tag */
+ TIFFTagMethods tif_tagmethods; /* tag get/set/print routines */
+ TIFFClientInfoLink *tif_clientinfo; /* extra client information. */
+};
+
+#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
+
+#define isTiled(tif) (((tif)->tif_flags & TIFF_ISTILED) != 0)
+#define isMapped(tif) (((tif)->tif_flags & TIFF_MAPPED) != 0)
+#define isFillOrder(tif, o) (((tif)->tif_flags & (o)) != 0)
+#define isUpSampled(tif) (((tif)->tif_flags & TIFF_UPSAMPLED) != 0)
+#define TIFFReadFile(tif, buf, size) \
+ ((*(tif)->tif_readproc)((tif)->tif_clientdata,buf,size))
+#define TIFFWriteFile(tif, buf, size) \
+ ((*(tif)->tif_writeproc)((tif)->tif_clientdata,buf,size))
+#define TIFFSeekFile(tif, off, whence) \
+ ((*(tif)->tif_seekproc)((tif)->tif_clientdata,(toff_t)(off),whence))
+#define TIFFCloseFile(tif) \
+ ((*(tif)->tif_closeproc)((tif)->tif_clientdata))
+#define TIFFGetFileSize(tif) \
+ ((*(tif)->tif_sizeproc)((tif)->tif_clientdata))
+#define TIFFMapFileContents(tif, paddr, psize) \
+ ((*(tif)->tif_mapproc)((tif)->tif_clientdata,paddr,psize))
+#define TIFFUnmapFileContents(tif, addr, size) \
+ ((*(tif)->tif_unmapproc)((tif)->tif_clientdata,addr,size))
+
+/*
+ * Default Read/Seek/Write definitions.
+ */
+#ifndef ReadOK
+#define ReadOK(tif, buf, size) \
+ (TIFFReadFile(tif, (tdata_t) buf, (tsize_t)(size)) == (tsize_t)(size))
+#endif
+#ifndef SeekOK
+#define SeekOK(tif, off) \
+ (TIFFSeekFile(tif, (toff_t) off, SEEK_SET) == (toff_t) off)
+#endif
+#ifndef WriteOK
+#define WriteOK(tif, buf, size) \
+ (TIFFWriteFile(tif, (tdata_t) buf, (tsize_t) size) == (tsize_t) size)
+#endif
+
+/* NB: the uint32 casts are to silence certain ANSI-C compilers */
+#define TIFFhowmany(x, y) ((((uint32)(x))+(((uint32)(y))-1))/((uint32)(y)))
+#define TIFFhowmany8(x) (((x)&0x07)?((uint32)(x)>>3)+1:(uint32)(x)>>3)
+#define TIFFroundup(x, y) (TIFFhowmany(x,y)*(y))
+
+#define TIFFmax(A,B) ((A)>(B)?(A):(B))
+#define TIFFmin(A,B) ((A)<(B)?(A):(B))
+
+#define TIFFArrayCount(a) (sizeof (a) / sizeof ((a)[0]))
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+extern int _TIFFgetMode(const char*, const char*);
+extern int _TIFFNoRowEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern int _TIFFNoStripEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern int _TIFFNoTileEncode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern int _TIFFNoRowDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern int _TIFFNoStripDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern int _TIFFNoTileDecode(TIFF*, tidata_t, tsize_t, tsample_t);
+extern void _TIFFNoPostDecode(TIFF*, tidata_t, tsize_t);
+extern int _TIFFNoPreCode (TIFF*, tsample_t);
+extern int _TIFFNoSeek(TIFF*, uint32);
+extern void _TIFFSwab16BitData(TIFF*, tidata_t, tsize_t);
+extern void _TIFFSwab24BitData(TIFF*, tidata_t, tsize_t);
+extern void _TIFFSwab32BitData(TIFF*, tidata_t, tsize_t);
+extern void _TIFFSwab64BitData(TIFF*, tidata_t, tsize_t);
+extern int TIFFFlushData1(TIFF*);
+extern int TIFFDefaultDirectory(TIFF*);
+extern void _TIFFSetDefaultCompressionState(TIFF*);
+extern int TIFFSetCompressionScheme(TIFF*, int);
+extern int TIFFSetDefaultCompressionState(TIFF*);
+extern uint32 _TIFFDefaultStripSize(TIFF*, uint32);
+extern void _TIFFDefaultTileSize(TIFF*, uint32*, uint32*);
+extern int _TIFFDataSize(TIFFDataType);
+
+extern void _TIFFsetByteArray(void**, void*, uint32);
+extern void _TIFFsetString(char**, char*);
+extern void _TIFFsetShortArray(uint16**, uint16*, uint32);
+extern void _TIFFsetLongArray(uint32**, uint32*, uint32);
+extern void _TIFFsetFloatArray(float**, float*, uint32);
+extern void _TIFFsetDoubleArray(double**, double*, uint32);
+
+extern void _TIFFprintAscii(FILE*, const char*);
+extern void _TIFFprintAsciiTag(FILE*, const char*, const char*);
+
+extern TIFFErrorHandler _TIFFwarningHandler;
+extern TIFFErrorHandler _TIFFerrorHandler;
+extern TIFFErrorHandlerExt _TIFFwarningHandlerExt;
+extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
+
+extern tdata_t _TIFFCheckMalloc(TIFF*, size_t, size_t, const char*);
+extern tdata_t _TIFFCheckRealloc(TIFF*, tdata_t, size_t, size_t, const char*);
+
+extern int TIFFInitDumpMode(TIFF*, int);
+#ifdef PACKBITS_SUPPORT
+extern int TIFFInitPackBits(TIFF*, int);
+#endif
+#ifdef CCITT_SUPPORT
+extern int TIFFInitCCITTRLE(TIFF*, int), TIFFInitCCITTRLEW(TIFF*, int);
+extern int TIFFInitCCITTFax3(TIFF*, int), TIFFInitCCITTFax4(TIFF*, int);
+#endif
+#ifdef THUNDER_SUPPORT
+extern int TIFFInitThunderScan(TIFF*, int);
+#endif
+#ifdef NEXT_SUPPORT
+extern int TIFFInitNeXT(TIFF*, int);
+#endif
+#ifdef LZW_SUPPORT
+extern int TIFFInitLZW(TIFF*, int);
+#endif
+#ifdef OJPEG_SUPPORT
+extern int TIFFInitOJPEG(TIFF*, int);
+#endif
+#ifdef JPEG_SUPPORT
+extern int TIFFInitJPEG(TIFF*, int);
+#endif
+#ifdef JBIG_SUPPORT
+extern int TIFFInitJBIG(TIFF*, int);
+#endif
+#ifdef ZIP_SUPPORT
+extern int TIFFInitZIP(TIFF*, int);
+#endif
+#ifdef PIXARLOG_SUPPORT
+extern int TIFFInitPixarLog(TIFF*, int);
+#endif
+#ifdef LOGLUV_SUPPORT
+extern int TIFFInitSGILog(TIFF*, int);
+#endif
+#ifdef VMS
+extern const TIFFCodec _TIFFBuiltinCODECS[];
+#else
+extern TIFFCodec _TIFFBuiltinCODECS[];
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* _TIFFIOP_ */
+
+/* vim: set ts=8 sts=8 sw=8 noet: */
diff --git a/Source/LibTIFF/tiffvers.h b/Source/LibTIFF/tiffvers.h
new file mode 100644
index 0000000..c4693f4
--- /dev/null
+++ b/Source/LibTIFF/tiffvers.h
@@ -0,0 +1,9 @@
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 3.9.1\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+/*
+ * This define can be used in code that requires
+ * compilation-related definitions specific to a
+ * version or versions of the library. Runtime
+ * version checking should be done based on the
+ * string returned by TIFFGetVersion.
+ */
+#define TIFFLIB_VERSION 20090828
diff --git a/Source/LibTIFF/tiffvers.h.in b/Source/LibTIFF/tiffvers.h.in
new file mode 100644
index 0000000..48ec0eb
--- /dev/null
+++ b/Source/LibTIFF/tiffvers.h.in
@@ -0,0 +1,9 @@
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version LIBTIFF_VERSION\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+/*
+ * This define can be used in code that requires
+ * compilation-related definitions specific to a
+ * version or versions of the library. Runtime
+ * version checking should be done based on the
+ * string returned by TIFFGetVersion.
+ */
+#define TIFFLIB_VERSION LIBTIFF_RELEASE_DATE
diff --git a/Source/LibTIFF/uvcode.h b/Source/LibTIFF/uvcode.h
new file mode 100644
index 0000000..5b2d7d7
--- /dev/null
+++ b/Source/LibTIFF/uvcode.h
@@ -0,0 +1,173 @@
+/* Version 1.0 generated April 7, 1997 by Greg Ward Larson, SGI */
+#define UV_SQSIZ (float)0.003500
+#define UV_NDIVS 16289
+#define UV_VSTART (float)0.016940
+#define UV_NVS 163
+static struct {
+ float ustart;
+ short nus, ncum;
+} uv_row[UV_NVS] = {
+ { (float)0.247663, 4, 0 },
+ { (float)0.243779, 6, 4 },
+ { (float)0.241684, 7, 10 },
+ { (float)0.237874, 9, 17 },
+ { (float)0.235906, 10, 26 },
+ { (float)0.232153, 12, 36 },
+ { (float)0.228352, 14, 48 },
+ { (float)0.226259, 15, 62 },
+ { (float)0.222371, 17, 77 },
+ { (float)0.220410, 18, 94 },
+ { (float)0.214710, 21, 112 },
+ { (float)0.212714, 22, 133 },
+ { (float)0.210721, 23, 155 },
+ { (float)0.204976, 26, 178 },
+ { (float)0.202986, 27, 204 },
+ { (float)0.199245, 29, 231 },
+ { (float)0.195525, 31, 260 },
+ { (float)0.193560, 32, 291 },
+ { (float)0.189878, 34, 323 },
+ { (float)0.186216, 36, 357 },
+ { (float)0.186216, 36, 393 },
+ { (float)0.182592, 38, 429 },
+ { (float)0.179003, 40, 467 },
+ { (float)0.175466, 42, 507 },
+ { (float)0.172001, 44, 549 },
+ { (float)0.172001, 44, 593 },
+ { (float)0.168612, 46, 637 },
+ { (float)0.168612, 46, 683 },
+ { (float)0.163575, 49, 729 },
+ { (float)0.158642, 52, 778 },
+ { (float)0.158642, 52, 830 },
+ { (float)0.158642, 52, 882 },
+ { (float)0.153815, 55, 934 },
+ { (float)0.153815, 55, 989 },
+ { (float)0.149097, 58, 1044 },
+ { (float)0.149097, 58, 1102 },
+ { (float)0.142746, 62, 1160 },
+ { (float)0.142746, 62, 1222 },
+ { (float)0.142746, 62, 1284 },
+ { (float)0.138270, 65, 1346 },
+ { (float)0.138270, 65, 1411 },
+ { (float)0.138270, 65, 1476 },
+ { (float)0.132166, 69, 1541 },
+ { (float)0.132166, 69, 1610 },
+ { (float)0.126204, 73, 1679 },
+ { (float)0.126204, 73, 1752 },
+ { (float)0.126204, 73, 1825 },
+ { (float)0.120381, 77, 1898 },
+ { (float)0.120381, 77, 1975 },
+ { (float)0.120381, 77, 2052 },
+ { (float)0.120381, 77, 2129 },
+ { (float)0.112962, 82, 2206 },
+ { (float)0.112962, 82, 2288 },
+ { (float)0.112962, 82, 2370 },
+ { (float)0.107450, 86, 2452 },
+ { (float)0.107450, 86, 2538 },
+ { (float)0.107450, 86, 2624 },
+ { (float)0.107450, 86, 2710 },
+ { (float)0.100343, 91, 2796 },
+ { (float)0.100343, 91, 2887 },
+ { (float)0.100343, 91, 2978 },
+ { (float)0.095126, 95, 3069 },
+ { (float)0.095126, 95, 3164 },
+ { (float)0.095126, 95, 3259 },
+ { (float)0.095126, 95, 3354 },
+ { (float)0.088276, 100, 3449 },
+ { (float)0.088276, 100, 3549 },
+ { (float)0.088276, 100, 3649 },
+ { (float)0.088276, 100, 3749 },
+ { (float)0.081523, 105, 3849 },
+ { (float)0.081523, 105, 3954 },
+ { (float)0.081523, 105, 4059 },
+ { (float)0.081523, 105, 4164 },
+ { (float)0.074861, 110, 4269 },
+ { (float)0.074861, 110, 4379 },
+ { (float)0.074861, 110, 4489 },
+ { (float)0.074861, 110, 4599 },
+ { (float)0.068290, 115, 4709 },
+ { (float)0.068290, 115, 4824 },
+ { (float)0.068290, 115, 4939 },
+ { (float)0.068290, 115, 5054 },
+ { (float)0.063573, 119, 5169 },
+ { (float)0.063573, 119, 5288 },
+ { (float)0.063573, 119, 5407 },
+ { (float)0.063573, 119, 5526 },
+ { (float)0.057219, 124, 5645 },
+ { (float)0.057219, 124, 5769 },
+ { (float)0.057219, 124, 5893 },
+ { (float)0.057219, 124, 6017 },
+ { (float)0.050985, 129, 6141 },
+ { (float)0.050985, 129, 6270 },
+ { (float)0.050985, 129, 6399 },
+ { (float)0.050985, 129, 6528 },
+ { (float)0.050985, 129, 6657 },
+ { (float)0.044859, 134, 6786 },
+ { (float)0.044859, 134, 6920 },
+ { (float)0.044859, 134, 7054 },
+ { (float)0.044859, 134, 7188 },
+ { (float)0.040571, 138, 7322 },
+ { (float)0.040571, 138, 7460 },
+ { (float)0.040571, 138, 7598 },
+ { (float)0.040571, 138, 7736 },
+ { (float)0.036339, 142, 7874 },
+ { (float)0.036339, 142, 8016 },
+ { (float)0.036339, 142, 8158 },
+ { (float)0.036339, 142, 8300 },
+ { (float)0.032139, 146, 8442 },
+ { (float)0.032139, 146, 8588 },
+ { (float)0.032139, 146, 8734 },
+ { (float)0.032139, 146, 8880 },
+ { (float)0.027947, 150, 9026 },
+ { (float)0.027947, 150, 9176 },
+ { (float)0.027947, 150, 9326 },
+ { (float)0.023739, 154, 9476 },
+ { (float)0.023739, 154, 9630 },
+ { (float)0.023739, 154, 9784 },
+ { (float)0.023739, 154, 9938 },
+ { (float)0.019504, 158, 10092 },
+ { (float)0.019504, 158, 10250 },
+ { (float)0.019504, 158, 10408 },
+ { (float)0.016976, 161, 10566 },
+ { (float)0.016976, 161, 10727 },
+ { (float)0.016976, 161, 10888 },
+ { (float)0.016976, 161, 11049 },
+ { (float)0.012639, 165, 11210 },
+ { (float)0.012639, 165, 11375 },
+ { (float)0.012639, 165, 11540 },
+ { (float)0.009991, 168, 11705 },
+ { (float)0.009991, 168, 11873 },
+ { (float)0.009991, 168, 12041 },
+ { (float)0.009016, 170, 12209 },
+ { (float)0.009016, 170, 12379 },
+ { (float)0.009016, 170, 12549 },
+ { (float)0.006217, 173, 12719 },
+ { (float)0.006217, 173, 12892 },
+ { (float)0.005097, 175, 13065 },
+ { (float)0.005097, 175, 13240 },
+ { (float)0.005097, 175, 13415 },
+ { (float)0.003909, 177, 13590 },
+ { (float)0.003909, 177, 13767 },
+ { (float)0.002340, 177, 13944 },
+ { (float)0.002389, 170, 14121 },
+ { (float)0.001068, 164, 14291 },
+ { (float)0.001653, 157, 14455 },
+ { (float)0.000717, 150, 14612 },
+ { (float)0.001614, 143, 14762 },
+ { (float)0.000270, 136, 14905 },
+ { (float)0.000484, 129, 15041 },
+ { (float)0.001103, 123, 15170 },
+ { (float)0.001242, 115, 15293 },
+ { (float)0.001188, 109, 15408 },
+ { (float)0.001011, 103, 15517 },
+ { (float)0.000709, 97, 15620 },
+ { (float)0.000301, 89, 15717 },
+ { (float)0.002416, 82, 15806 },
+ { (float)0.003251, 76, 15888 },
+ { (float)0.003246, 69, 15964 },
+ { (float)0.004141, 62, 16033 },
+ { (float)0.005963, 55, 16095 },
+ { (float)0.008839, 47, 16150 },
+ { (float)0.010490, 40, 16197 },
+ { (float)0.016994, 31, 16237 },
+ { (float)0.023659, 21, 16268 },
+};
diff --git a/Source/Metadata/Exif.cpp b/Source/Metadata/Exif.cpp
new file mode 100644
index 0000000..a4a30ec
--- /dev/null
+++ b/Source/Metadata/Exif.cpp
@@ -0,0 +1,698 @@
+// ==========================================================
+// Metadata functions implementation
+// Exif metadata model
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// Based on the following implementations:
+// - metadata-extractor : http://www.drewnoakes.com/code/exif/
+// - jhead : http://www.sentex.net/~mwandel/jhead/
+// - ImageMagick : http://www.imagemagick.org/
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// ==========================================================
+// Exif JPEG routines
+// ==========================================================
+
+#define EXIF_NUM_FORMATS 12
+
+#define TAG_EXIF_OFFSET 0x8769 // Exif IFD Pointer
+#define TAG_GPS_OFFSET 0x8825 // GPS Info IFD Pointer
+#define TAG_INTEROP_OFFSET 0xA005 // Interoperability IFD Pointer
+#define TAG_THUMBNAIL_OFFSET 0x0201 // Thumbnail Pointer
+#define TAG_MAKER_NOTE 0x927C // Maker note
+
+// CANON cameras have some funny bespoke fields that need further processing...
+#define TAG_CANON_CAMERA_STATE_1 0x0001
+#define TAG_CANON_CAMERA_STATE_2 0x0002
+#define TAG_CANON_CAMERA_STATE_4 0x0004
+
+
+// =====================================================================
+// Reimplementation of strnicmp (it is not supported on some systems)
+// =====================================================================
+
+static int
+FreeImage_strnicmp(const char *s1, const char *s2, size_t len) {
+ unsigned char c1, c2;
+
+ if(!s1 || !s2) return -1;
+
+ c1 = 0; c2 = 0;
+ if(len) {
+ do {
+ c1 = *s1; c2 = *s2;
+ s1++; s2++;
+ if (!c1)
+ break;
+ if (!c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = (BYTE)tolower(c1);
+ c2 = (BYTE)tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
+ }
+ return (int)c1 - (int)c2;
+}
+
+
+// ----------------------------------------------------------
+// Little Endian / Big Endian io routines
+// ----------------------------------------------------------
+
+static short
+ReadInt16(BOOL msb_order, void *buffer) {
+ short value;
+
+ if(msb_order) {
+ value = (short)((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
+ return value;
+ }
+ value = (short)((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
+ return value;
+}
+
+static long
+ReadInt32(BOOL msb_order, void *buffer) {
+ long value;
+
+ if(msb_order) {
+ value = (long)((((BYTE*) buffer)[0] << 24) | (((BYTE*) buffer)[1] << 16) | (((BYTE*) buffer)[2] << 8) | (((BYTE*) buffer)[3]));
+ return value;
+ }
+ value = (long)((((BYTE*) buffer)[3] << 24) | (((BYTE*) buffer)[2] << 16) | (((BYTE*) buffer)[1] << 8 ) | (((BYTE*) buffer)[0]));
+ return value;
+}
+
+static unsigned short
+ReadUint16(BOOL msb_order, void *buffer) {
+ unsigned short value;
+
+ if(msb_order) {
+ value = (unsigned short) ((((BYTE*) buffer)[0] << 8) | ((BYTE*) buffer)[1]);
+ return value;
+ }
+ value = (unsigned short) ((((BYTE*) buffer)[1] << 8) | ((BYTE*) buffer)[0]);
+ return value;
+}
+
+static unsigned long
+ReadUint32(BOOL msb_order, void *buffer) {
+ return ((unsigned long) ReadInt32(msb_order, buffer) & 0xFFFFFFFF);
+}
+
+// ----------------------------------------------------------
+// Exif JPEG markers routines
+// ----------------------------------------------------------
+
+/**
+Process a IFD offset
+Returns the offset and the metadata model for this tag
+*/
+static void
+processIFDOffset(FITAG *tag, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
+ // get the IFD offset
+ *subdirOffset = (DWORD) ReadUint32(msb_order, pval);
+
+ // select a tag info table
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_EXIF_OFFSET:
+ *md_model = TagLib::EXIF_EXIF;
+ break;
+ case TAG_GPS_OFFSET:
+ *md_model = TagLib::EXIF_GPS;
+ break;
+ case TAG_INTEROP_OFFSET:
+ *md_model = TagLib::EXIF_INTEROP;
+ break;
+ }
+
+}
+
+/**
+Process a maker note IFD offset
+Returns the offset and the metadata model for this tag
+*/
+static void
+processMakerNote(FIBITMAP *dib, char *pval, BOOL msb_order, DWORD *subdirOffset, TagLib::MDMODEL *md_model) {
+ FITAG *tagMake = NULL;
+
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+
+ // Determine the camera model and makernote format
+ // WARNING: note that Maker may be NULL sometimes so check its value before using it
+ // (NULL pointer checking is done by FreeImage_strnicmp)
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake);
+ const char *Maker = (char*)FreeImage_GetTagValue(tagMake);
+
+ if((strncmp("OLYMP\x00\x01", pval, 7) == 0) || (strncmp("OLYMP\x00\x02", pval, 7) == 0) || (strncmp("EPSON", pval, 5) == 0) || (strncmp("AGFA", pval, 4) == 0)) {
+ // Olympus Type 1 Makernote
+ // Epson and Agfa use Olympus maker note standard,
+ // see: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
+ *md_model = TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1;
+ *subdirOffset = 8;
+ }
+ else if(strncmp("OLYMPUS\x00\x49\x49\x03\x00", pval, 12) == 0) {
+ // Olympus Type 2 Makernote
+ // !!! NOT YET SUPPORTED !!!
+ *subdirOffset = 0;
+ *md_model = TagLib::UNKNOWN;
+ }
+ else if(strncmp("Nikon", pval, 5) == 0) {
+ /* There are two scenarios here:
+ * Type 1:
+ * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
+ * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
+ * Type 3:
+ * :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
+ * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
+ */
+ if (pval[6] == 1) {
+ // Nikon type 1 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE1;
+ *subdirOffset = 8;
+ } else if (pval[6] == 2) {
+ // Nikon type 3 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE3;
+ *subdirOffset = 18;
+ } else {
+ // Unsupported makernote data ignored
+ *md_model = TagLib::UNKNOWN;
+ }
+ } else if(Maker && (FreeImage_strnicmp("NIKON", Maker, 5) == 0)) {
+ // Nikon type 2 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_NIKONTYPE2;
+ *subdirOffset = 0;
+ } else if(Maker && (FreeImage_strnicmp("Canon", Maker, 5) == 0)) {
+ // Canon Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CANON;
+ *subdirOffset = 0;
+ } else if(Maker && (FreeImage_strnicmp("Casio", Maker, 5) == 0)) {
+ // Casio Makernote
+ if(strncmp("QVC\x00\x00\x00", pval, 6) == 0) {
+ // Casio Type 2 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE2;
+ *subdirOffset = 6;
+ } else {
+ // Casio Type 1 Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_CASIOTYPE1;
+ *subdirOffset = 0;
+ }
+ } else if ((strncmp("FUJIFILM", pval, 8) == 0) || (Maker && (FreeImage_strnicmp("Fujifilm", Maker, 8) == 0))) {
+ // Fujifile Makernote
+ // Fujifilm's Makernote always use Intel order altough the Exif section maybe in Intel order or in Motorola order.
+ // If msb_order == TRUE, the Makernote won't be read:
+ // the value of ifdStart will be 0x0c000000 instead of 0x0000000c and the MakerNote section will be discarded later
+ // in jpeg_read_exif_dir because the IFD is too high
+ *md_model = TagLib::EXIF_MAKERNOTE_FUJIFILM;
+ DWORD ifdStart = (DWORD) ReadUint32(msb_order, pval + 8);
+ *subdirOffset = ifdStart;
+ }
+ else if(memcmp("KYOCERA \x00\x00\x00", pval, 22) == 0) {
+ *md_model = TagLib::EXIF_MAKERNOTE_KYOCERA;
+ *subdirOffset = 22;
+ }
+ else if(Maker && (FreeImage_strnicmp("Minolta", Maker, 7) == 0)) {
+ // Minolta maker note
+ *md_model = TagLib::EXIF_MAKERNOTE_MINOLTA;
+ *subdirOffset = 0;
+ }
+ else if(memcmp("Panasonic\x00\x00\x00", pval, 12) == 0) {
+ // Panasonic maker note
+ *md_model = TagLib::EXIF_MAKERNOTE_PANASONIC;
+ *subdirOffset = 12;
+ }
+ else if(Maker && ((FreeImage_strnicmp("Pentax", Maker, 6) == 0) || (FreeImage_strnicmp("Asahi", Maker, 5) == 0))) {
+ // Pentax maker note
+ if(strncmp("AOC\x00", pval, 4) == 0) {
+ // Type 2 Pentax Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_PENTAX;
+ *subdirOffset = 6;
+ } else {
+ // Type 1 Pentax Makernote
+ *md_model = TagLib::EXIF_MAKERNOTE_ASAHI;
+ *subdirOffset = 0;
+ }
+ }
+ else if((strncmp("SONY CAM", pval, 8) == 0) || (strncmp("SONY DSC", pval, 8) == 0)) {
+ *md_model = TagLib::EXIF_MAKERNOTE_SONY;
+ *subdirOffset = 12;
+ }
+}
+
+/**
+Process a Canon maker note tag.
+A single Canon tag may contain many other tags within.
+*/
+static void
+processCanonMakerNoteTag(FIBITMAP *dib, FITAG *tag) {
+ char defaultKey[16];
+ DWORD startIndex = 0;
+ TagLib& s = TagLib::instance();
+
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ if((tag_id == TAG_CANON_CAMERA_STATE_1) || (tag_id == TAG_CANON_CAMERA_STATE_2) || (tag_id == TAG_CANON_CAMERA_STATE_4)) {
+ // this single tag has multiple values within
+
+ int subTagTypeBase = 0;
+
+ switch(tag_id) {
+ case TAG_CANON_CAMERA_STATE_1:
+ subTagTypeBase = 0xC100;
+ startIndex = 1;
+ break;
+ case TAG_CANON_CAMERA_STATE_2:
+ subTagTypeBase = 0xC200;
+ startIndex = 0;
+ break;
+ case TAG_CANON_CAMERA_STATE_4:
+ subTagTypeBase = 0xC400;
+ startIndex = 2;
+ break;
+ }
+
+ WORD *pvalue = (WORD*)FreeImage_GetTagValue(tag);
+
+ // we intentionally skip the first array member
+ for (DWORD i = startIndex; i < FreeImage_GetTagCount(tag); i++) {
+ // create a tag
+ FITAG *canonTag = FreeImage_CreateTag();
+ if(!canonTag) return;
+
+ tag_id = (WORD)(subTagTypeBase + i);
+
+ FreeImage_SetTagID(canonTag, tag_id);
+ FreeImage_SetTagType(canonTag, FIDT_SHORT);
+ FreeImage_SetTagCount(canonTag, 1);
+ FreeImage_SetTagLength(canonTag, 2);
+ FreeImage_SetTagValue(canonTag, &pvalue[i]);
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
+ FreeImage_SetTagKey(canonTag, key);
+ const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
+ FreeImage_SetTagDescription(canonTag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, canonTag);
+ }
+
+ // delete the tag
+ FreeImage_DeleteTag(canonTag);
+ }
+ }
+ else {
+ // process as a normal tag
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(TagLib::EXIF_MAKERNOTE_CANON, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = s.getTagDescription(TagLib::EXIF_MAKERNOTE_CANON, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_EXIF_MAKERNOTE, dib, key, tag);
+ }
+ }
+}
+
+/**
+Process a standard Exif tag
+*/
+static void
+processExifTag(FIBITMAP *dib, FITAG *tag, char *pval, BOOL msb_order, TagLib::MDMODEL md_model) {
+ char defaultKey[16];
+ int n;
+ DWORD i;
+
+ // allocate a buffer to store the tag value
+ BYTE *exif_value = (BYTE*)malloc(FreeImage_GetTagLength(tag) * sizeof(BYTE));
+ memset(exif_value, 0, FreeImage_GetTagLength(tag) * sizeof(BYTE));
+
+ // get the tag value
+ switch(FreeImage_GetTagType(tag)) {
+
+ case FIDT_SHORT:
+ {
+ WORD *value = (WORD*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadUint16(msb_order, pval + i * sizeof(WORD));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SSHORT:
+ {
+ short *value = (short*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadInt16(msb_order, pval + i * sizeof(short));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_LONG:
+ {
+ DWORD *value = (DWORD*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadUint32(msb_order, pval + i * sizeof(DWORD));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SLONG:
+ {
+ LONG *value = (LONG*)&exif_value[0];
+ for(i = 0; i < FreeImage_GetTagCount(tag); i++) {
+ value[i] = ReadInt32(msb_order, pval + i * sizeof(LONG));
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_RATIONAL:
+ {
+ n = sizeof(DWORD);
+
+ DWORD *value = (DWORD*)&exif_value[0];
+ for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
+ // read a sequence of (numerator, denominator)
+ value[i] = ReadUint32(msb_order, n*i + (char*)pval);
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_SRATIONAL:
+ {
+ n = sizeof(LONG);
+
+ LONG *value = (LONG*)&exif_value[0];
+ for(i = 0; i < 2 * FreeImage_GetTagCount(tag); i++) {
+ // read a sequence of (numerator, denominator)
+ value[i] = ReadInt32(msb_order, n*i + (char*)pval);
+ }
+ FreeImage_SetTagValue(tag, value);
+ break;
+ }
+ case FIDT_BYTE:
+ case FIDT_ASCII:
+ case FIDT_SBYTE:
+ case FIDT_UNDEFINED:
+ case FIDT_FLOAT:
+ case FIDT_DOUBLE:
+ default:
+ FreeImage_SetTagValue(tag, pval);
+ break;
+ }
+
+ if(md_model == TagLib::EXIF_MAKERNOTE_CANON) {
+ // A single Canon tag can have multiple values within
+ processCanonMakerNoteTag(dib, tag);
+ }
+ else {
+ TagLib& s = TagLib::instance();
+
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ // get the tag key and description
+ const char *key = s.getTagFieldName(md_model, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = s.getTagDescription(md_model, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(s.getFreeImageModel(md_model), dib, key, tag);
+ }
+ }
+
+
+ // free the temporary buffer
+ free(exif_value);
+
+}
+
+/**
+ Process Exif directory
+
+ @param dib Input FIBITMAP
+ @param tiffp Pointer to the TIFF header
+ @param offset 0th IFD offset
+ @param length Length of the datafile
+ @param msb_order Endianess order of the datafile
+ @return
+*/
+static BOOL
+jpeg_read_exif_dir(FIBITMAP *dib, const BYTE *tiffp, unsigned long offset, unsigned int length, BOOL msb_order) {
+ WORD de, nde;
+
+ std::stack<WORD> destack; // directory entries stack
+ std::stack<BYTE*> ifdstack; // IFD stack
+ std::stack<TagLib::MDMODEL> modelstack; // metadata model stack
+
+ // Keep a list of already visited IFD to avoid stack overflows
+ // when recursive/cyclic directory structures exist.
+ // This kind of recursive Exif file was encountered with Kodak images coming from
+ // KODAK PROFESSIONAL DCS Photo Desk JPEG Export v3.2 W
+ std::map<DWORD, int> visitedIFD;
+
+ #define DIR_ENTRY_ADDR(_start, _entry) (_start + 2 + (12 * _entry))
+
+ // set the metadata model to Exif
+
+ TagLib::MDMODEL md_model = TagLib::EXIF_MAIN;
+
+ // set the pointer to the first IFD and follow it were it leads.
+
+ BYTE *ifdp = (BYTE*)tiffp + offset;
+
+ de = 0;
+
+ do {
+ // if there is anything on the stack then pop it off
+ if(!destack.empty()) {
+ ifdp = ifdstack.top(); ifdstack.pop();
+ de = destack.top(); destack.pop();
+ md_model = modelstack.top(); modelstack.pop();
+ }
+
+ // remember that we've visited this directory so that we don't visit it again later
+ DWORD visited = (DWORD)( (((size_t)ifdp & 0xFFFF) << 16) | (size_t)de );
+ if(visitedIFD.find(visited) != visitedIFD.end()) {
+ continue;
+ } else {
+ visitedIFD[visited] = 1; // processed
+ }
+
+ // determine how many entries there are in the current IFD
+ nde = ReadUint16(msb_order, ifdp);
+
+ for(; de < nde; de++) {
+ char *pde = NULL; // pointer to the directory entry
+ char *pval = NULL; // pointer to the tag value
+
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(!tag) return FALSE;
+
+ // point to the directory entry
+ pde = (char*) DIR_ENTRY_ADDR(ifdp, de);
+
+ // get the tag ID
+ FreeImage_SetTagID(tag, ReadUint16(msb_order, pde));
+ // get the tag format
+ WORD tag_type = (WORD)ReadUint16(msb_order, pde + 2);
+ if((tag_type - 1) >= EXIF_NUM_FORMATS) {
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // break out of the for loop
+ break;
+ }
+ FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)tag_type);
+
+ // get number of components
+ FreeImage_SetTagCount(tag, ReadUint32(msb_order, pde + 4));
+ // get the size of the tag value in bytes
+ FreeImage_SetTagLength(tag, FreeImage_GetTagCount(tag) * FreeImage_TagDataWidth((WORD)FreeImage_GetTagType(tag)));
+
+ if(FreeImage_GetTagLength(tag) <= 4) {
+ // 4 bytes or less and value is in the dir entry itself
+ pval = pde + 8;
+ } else {
+ // if its bigger than 4 bytes, the directory entry contains an offset
+ // first check if offset exceeds buffer, at this stage FreeImage_GetTagLength may return invalid data
+ DWORD offset_value = ReadUint32(msb_order, pde + 8);
+ if(offset_value > length) {
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // jump to next entry
+ continue;
+ }
+ // now check if offset + tag length exceeds buffer
+ if(offset_value > length - FreeImage_GetTagLength(tag)) {
+ // a problem occured : delete the tag (not free'd after)
+ FreeImage_DeleteTag(tag);
+ // jump to next entry
+ continue;
+ }
+ pval = (char*)(tiffp + offset_value);
+ }
+
+ // check for a IFD offset
+ BOOL isIFDOffset = FALSE;
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_EXIF_OFFSET:
+ case TAG_GPS_OFFSET:
+ case TAG_INTEROP_OFFSET:
+ case TAG_MAKER_NOTE:
+ isIFDOffset = TRUE;
+ break;
+ }
+ if(isIFDOffset) {
+ DWORD sub_offset = 0;
+ TagLib::MDMODEL next_mdmodel = md_model;
+ BYTE *next_ifd = ifdp;
+
+ // get offset and metadata model
+ if (FreeImage_GetTagID(tag) == TAG_MAKER_NOTE) {
+ processMakerNote(dib, pval, msb_order, &sub_offset, &next_mdmodel);
+ next_ifd = (BYTE*)pval + sub_offset;
+ } else {
+ processIFDOffset(tag, pval, msb_order, &sub_offset, &next_mdmodel);
+ next_ifd = (BYTE*)tiffp + sub_offset;
+ }
+
+ if((sub_offset < (DWORD) length) && (next_mdmodel != TagLib::UNKNOWN)) {
+ // push our current directory state onto the stack
+ ifdstack.push(ifdp);
+ // bump to the next entry
+ de++;
+ destack.push(de);
+
+ // push our current metadata model
+ modelstack.push(md_model);
+
+ // push new state onto of stack to cause a jump
+ ifdstack.push(next_ifd);
+ destack.push(0);
+
+ // select a new metadata model
+ modelstack.push(next_mdmodel);
+
+ // delete the tag as it won't be stored nor deleted in the for() loop
+ FreeImage_DeleteTag(tag);
+
+ break; // break out of the for loop
+ }
+ else {
+ // unsupported camera model, canon maker tag or or something unknown
+ // process as a standard tag
+ processExifTag(dib, tag, pval, msb_order, md_model);
+ }
+
+ } else {
+ // process as a standard tag
+ processExifTag(dib, tag, pval, msb_order, md_model);
+ }
+
+ // delete the tag
+ FreeImage_DeleteTag(tag);
+
+ } // for(nde)
+
+ // additional thumbnail data is skipped
+
+ } while (!destack.empty());
+
+
+ return TRUE;
+}
+
+/**
+ Read JPEG_APP1 marker (Exif profile)
+ @param dib Input FIBITMAP
+ @param dataptr Pointer to the APP1 marker
+ @param datalen APP1 marker length
+ @return Returns TRUE if successful, FALSE otherwise
+*/
+BOOL
+jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ // marker identifying string for Exif = "Exif\0\0"
+ BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
+ BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Intel order
+ BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Motorola order
+
+ unsigned int length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ // verify the identifying string
+
+ if(memcmp(exif_signature, profile, sizeof(exif_signature)) == 0) {
+ // Exif profile
+
+ profile += sizeof(exif_signature);
+ length -= sizeof(exif_signature);
+
+ // check the endianess order
+
+ BOOL bMotorolaOrder = TRUE;
+
+ if(memcmp(profile, lsb_first, sizeof(lsb_first)) == 0) {
+ // Exif section in Intel order
+ bMotorolaOrder = FALSE;
+ } else {
+ if(memcmp(profile, msb_first, sizeof(msb_first)) == 0) {
+ // Exif section in Motorola order
+ bMotorolaOrder = TRUE;
+ } else {
+ // Invalid Exif alignment marker
+ return FALSE;
+ }
+ }
+
+ // this is the offset to the first IFD
+ unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4);
+
+ if (first_offset < 8 || first_offset > 16) {
+ // This is usually set to 8
+ // but PENTAX Optio 230 has it set differently, and uses it as offset.
+ FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value");
+ return FALSE;
+ }
+
+ // process Exif directories
+ return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder);
+ }
+
+ return FALSE;
+}
+
+
diff --git a/Source/Metadata/FIRational.cpp b/Source/Metadata/FIRational.cpp
new file mode 100644
index 0000000..ad26443
--- /dev/null
+++ b/Source/Metadata/FIRational.cpp
@@ -0,0 +1,176 @@
+// ==========================================================
+// Helper class for rational numbers
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FIRational.h"
+
+/// Initialize and normalize a rational number
+void FIRational::initialize(long n, long d) {
+ if(d) {
+ _numerator = n;
+ _denominator = d;
+ // normalize rational
+ normalize();
+ } else {
+ _numerator = 0;
+ _denominator = 0;
+ }
+}
+
+/// Default constructor
+FIRational::FIRational() {
+ _numerator = 0;
+ _denominator = 0;
+}
+
+/// Constructor with longs
+FIRational::FIRational(long n, long d) {
+ initialize(n, d);
+}
+
+/// Constructor with FITAG
+FIRational::FIRational(const FITAG *tag) {
+ switch(FreeImage_GetTagType((FITAG*)tag)) {
+ case FIDT_RATIONAL: // 64-bit unsigned fraction
+ {
+ DWORD *pvalue = (DWORD*)FreeImage_GetTagValue((FITAG*)tag);
+ initialize((long)pvalue[0], (long)pvalue[1]);
+ break;
+ }
+
+ case FIDT_SRATIONAL: // 64-bit signed fraction
+ {
+ LONG *pvalue = (LONG*)FreeImage_GetTagValue((FITAG*)tag);
+ initialize((long)pvalue[0], (long)pvalue[1]);
+ break;
+ }
+ }
+}
+
+FIRational::FIRational(float value) {
+ if (value == (float)((long)value)) {
+ _numerator = (long)value;
+ _denominator = 1L;
+ } else {
+ int k, count;
+ long n[4];
+
+ float x = fabs(value);
+ int sign = (value > 0) ? 1 : -1;
+
+ // make a continued-fraction expansion of x
+ count = -1;
+ for(k = 0; k < 4; k++) {
+ n[k] = (long)floor(x);
+ count++;
+ x -= (float)n[k];
+ if(x == 0) break;
+ x = 1 / x;
+ }
+ // compute the rational
+ _numerator = 1;
+ _denominator = n[count];
+
+ for(int i = count - 1; i >= 0; i--) {
+ if(n[i] == 0) break;
+ long _num = (n[i] * _numerator + _denominator);
+ long _den = _numerator;
+ _numerator = _num;
+ _denominator = _den;
+ }
+ _numerator *= sign;
+ }
+}
+
+/// Copy constructor
+FIRational::FIRational (const FIRational& r) {
+ initialize(r._numerator, r._denominator);
+}
+
+/// Destructor
+FIRational::~FIRational() {
+}
+
+/// Assignement operator
+FIRational& FIRational::operator=(FIRational& r) {
+ if(this != &r) {
+ initialize(r._numerator, r._denominator);
+ }
+ return *this;
+}
+
+/// Get the numerator
+long FIRational::getNumerator() {
+ return _numerator;
+}
+
+/// Get the denominator
+long FIRational::getDenominator() {
+ return _denominator;
+}
+
+/// Calculate GCD
+long FIRational::gcd(long a, long b) {
+ long temp;
+ while (b) { // While non-zero value
+ temp = b; // Save current value
+ b = a % b; // Assign remainder of division
+ a = temp; // Copy old value
+ }
+ return a; // Return GCD of numbers
+}
+
+/// Normalize numerator / denominator
+void FIRational::normalize() {
+ if (_numerator != 1 && _denominator != 1) { // Is there something to do?
+ // Calculate GCD
+ long common = gcd(_numerator, _denominator);
+ if (common != 1) { // If GCD is not one
+ _numerator /= common; // Calculate new numerator
+ _denominator /= common; // Calculate new denominator
+ }
+ }
+ if(_denominator < 0) { // If sign is in denominator
+ _numerator *= -1; // Multiply num and den by -1
+ _denominator *= -1; // To keep sign in numerator
+ }
+}
+
+/// Checks if this rational number is an Integer, either positive or negative
+BOOL FIRational::isInteger() {
+ if(_denominator == 1 || (_denominator != 0 && (_numerator % _denominator == 0)) || (_denominator == 0 && _numerator == 0))
+ return TRUE;
+ return FALSE;
+}
+
+/// Convert as "numerator/denominator"
+std::string FIRational::toString() {
+ std::ostringstream s;
+ if(isInteger()) {
+ s << intValue();
+ } else {
+ s << _numerator << "/" << _denominator;
+ }
+ return s.str();
+}
+
+
diff --git a/Source/Metadata/FIRational.h b/Source/Metadata/FIRational.h
new file mode 100644
index 0000000..fc51dba
--- /dev/null
+++ b/Source/Metadata/FIRational.h
@@ -0,0 +1,107 @@
+// ==========================================================
+// Helper class for rational numbers
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FIRATIONAL_H
+#define FIRATIONAL_H
+
+/**
+Helper class to deal with rational numbers
+*/
+class FIRational {
+private:
+ /// numerator
+ long _numerator;
+ /// denominator
+ long _denominator;
+
+public:
+ /// Default constructor
+ FIRational();
+
+ /// Constructor with longs
+ FIRational(long n, long d = 1);
+
+ /// Constructor with FITAG
+ FIRational(const FITAG *tag);
+
+ /// Constructor with a float
+ FIRational(float value);
+
+ /// Copy constructor
+ FIRational (const FIRational& r);
+
+ /// Destructor
+ ~FIRational();
+
+ /// Assignement operator
+ FIRational& operator=(FIRational& r);
+
+ /// Get the numerator
+ long getNumerator();
+
+ /// Get the denominator
+ long getDenominator();
+
+ /// Converts rational value by truncating towards zero
+ long truncate() {
+ // Return truncated rational
+ return _denominator ? (long) (_numerator / _denominator) : 0;
+ }
+
+ /**@name Implicit conversions */
+ //@{
+ short shortValue() {
+ return (short)truncate();
+ }
+ int intValue() {
+ return (int)truncate();
+ }
+ long longValue() {
+ return (long)truncate();
+ }
+ float floatValue() {
+ return _denominator ? ((float)_numerator)/((float)_denominator) : 0;
+ }
+ double doubleValue() {
+ return _denominator ? ((double)_numerator)/((double)_denominator) : 0;
+ }
+ //@}
+
+ /// Checks if this rational number is an integer, either positive or negative
+ BOOL isInteger();
+
+ /// Convert as "numerator/denominator"
+ std::string toString();
+
+private:
+ /// Initialize and normalize a rational number
+ void initialize(long n, long d);
+
+ /// Calculate GCD
+ long gcd(long a, long b);
+
+ /// Normalize numerator / denominator
+ void normalize();
+
+};
+
+#endif // FIRATIONAL_H
+
diff --git a/Source/Metadata/FreeImageTag.cpp b/Source/Metadata/FreeImageTag.cpp
new file mode 100644
index 0000000..af8f23d
--- /dev/null
+++ b/Source/Metadata/FreeImageTag.cpp
@@ -0,0 +1,284 @@
+// ==========================================================
+// Tag manipulation functions
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// --------------------------------------------------------------------------
+// FITAG header definition
+// --------------------------------------------------------------------------
+
+FI_STRUCT (FITAGHEADER) {
+ char *key; // tag field name
+ char *description; // tag description
+ WORD id; // tag ID
+ WORD type; // tag data type (see FREE_IMAGE_MDTYPE)
+ DWORD count; // number of components (in 'tag data types' units)
+ DWORD length; // value length in bytes
+ void *value; // tag value
+};
+
+// --------------------------------------------------------------------------
+// FITAG creation / destruction
+// --------------------------------------------------------------------------
+
+FITAG * DLL_CALLCONV
+FreeImage_CreateTag() {
+ FITAG *tag = (FITAG *)malloc(sizeof(FITAG));
+
+ if (tag != NULL) {
+ unsigned tag_size = sizeof(FITAGHEADER);
+ tag->data = (BYTE *)malloc(tag_size * sizeof(BYTE));
+ if (tag->data != NULL) {
+ memset(tag->data, 0, tag_size);
+ return tag;
+ }
+ free(tag);
+ }
+
+ return NULL;
+}
+
+void DLL_CALLCONV
+FreeImage_DeleteTag(FITAG *tag) {
+ if (NULL != tag) {
+ if (NULL != tag->data) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ // delete tag members
+ free(tag_header->key);
+ free(tag_header->description);
+ free(tag_header->value);
+ // delete the tag
+ free(tag->data);
+ }
+ // and the wrapper
+ free(tag);
+ }
+}
+
+FITAG * DLL_CALLCONV
+FreeImage_CloneTag(FITAG *tag) {
+ if(!tag) return NULL;
+
+ // allocate a new tag
+ FITAG *clone = FreeImage_CreateTag();
+ if(!clone) return NULL;
+
+ // copy the tag
+ FITAGHEADER *src_tag = (FITAGHEADER *)tag->data;
+ FITAGHEADER *dst_tag = (FITAGHEADER *)clone->data;
+
+ // tag ID
+ dst_tag->id = src_tag->id;
+ // tag key
+ if(src_tag->key) {
+ dst_tag->key = (char*)malloc((strlen(src_tag->key) + 1) * sizeof(char));
+ strcpy(dst_tag->key, src_tag->key);
+ }
+ // tag description
+ if(src_tag->description) {
+ dst_tag->description = (char*)malloc((strlen(src_tag->description) + 1) * sizeof(char));
+ strcpy(dst_tag->description, src_tag->description);
+ }
+ // tag data type
+ dst_tag->type = src_tag->type;
+ // tag count
+ dst_tag->count = src_tag->count;
+ // tag length
+ dst_tag->length = src_tag->length;
+ // tag value
+ switch(dst_tag->type) {
+ case FIDT_ASCII:
+ dst_tag->value = (char*)malloc((strlen((char*)src_tag->value) + 1) * sizeof(char));
+ strcpy((char*)dst_tag->value, (char*)src_tag->value);
+ break;
+ default:
+ if(src_tag->value) {
+ size_t len = (src_tag->length > 64*1024) ? 64*1024 : src_tag->length; // limit size in case of corrupted tags
+ dst_tag->value = (BYTE*)malloc(len * sizeof(BYTE));
+ memcpy(dst_tag->value, src_tag->value, len);
+ }
+ break;
+ }
+
+ return clone;
+}
+
+// --------------------------------------------------------------------------
+// FITAG getters / setters
+// --------------------------------------------------------------------------
+
+const char * DLL_CALLCONV
+FreeImage_GetTagKey(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->key : 0;
+}
+
+const char * DLL_CALLCONV
+FreeImage_GetTagDescription(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->description : 0;
+}
+
+WORD DLL_CALLCONV
+FreeImage_GetTagID(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->id : 0;
+}
+
+FREE_IMAGE_MDTYPE DLL_CALLCONV
+FreeImage_GetTagType(FITAG *tag) {
+ return tag ? (FREE_IMAGE_MDTYPE)(((FITAGHEADER *)tag->data)->type) : FIDT_NOTYPE;
+}
+
+DWORD DLL_CALLCONV
+FreeImage_GetTagCount(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->count : 0;
+}
+
+DWORD DLL_CALLCONV
+FreeImage_GetTagLength(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->length : 0;
+}
+
+const void *DLL_CALLCONV
+FreeImage_GetTagValue(FITAG *tag) {
+ return tag ? ((FITAGHEADER *)tag->data)->value : 0;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagKey(FITAG *tag, const char *key) {
+ if(tag && key) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ if(tag_header->key) free(tag_header->key);
+ tag_header->key = (char*)malloc(strlen(key) + 1);
+ strcpy(tag_header->key, key);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagDescription(FITAG *tag, const char *description) {
+ if(tag && description) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ if(tag_header->description) free(tag_header->description);
+ tag_header->description = (char*)malloc(strlen(description) + 1);
+ strcpy(tag_header->description, description);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagID(FITAG *tag, WORD id) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->id = id;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagType(FITAG *tag, FREE_IMAGE_MDTYPE type) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->type = (WORD)type;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagCount(FITAG *tag, DWORD count) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->count = count;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagLength(FITAG *tag, DWORD length) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ tag_header->length = length;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL DLL_CALLCONV
+FreeImage_SetTagValue(FITAG *tag, const void *value) {
+ if(tag) {
+ FITAGHEADER *tag_header = (FITAGHEADER *)tag->data;
+ // first, check the tag
+ if(tag_header->count * FreeImage_TagDataWidth(tag_header->type) != tag_header->length) {
+ // invalid data count ?
+ return FALSE;
+ }
+
+ if(tag_header->value) free(tag_header->value);
+
+ switch(tag_header->type) {
+ case FIDT_ASCII:
+ {
+ size_t len = (tag_header->length > (64*1024)) ? (64*1024) : tag_header->length; // limit tag size. Useful in case of corruption
+ tag_header->value = (char*)malloc((len + 1) * sizeof(char));
+ strncpy((char*)tag_header->value, (char*)value, len);
+ ((char*)tag_header->value)[len] = '\0';
+ tag_header->count = tag_header->length = strlen((char*)tag_header->value);
+ }
+ break;
+
+ default:
+ if(tag_header->length > (64*1024)) { // limit tag size. Useful in case of corruption
+ tag_header->length = 0;
+ tag_header->value = strdup("");
+ return FALSE;
+ }
+ tag_header->value = malloc(tag_header->length * sizeof(BYTE));
+ memcpy(tag_header->value, value, tag_header->length);
+ break;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// --------------------------------------------------------------------------
+// FITAG internal helper functions
+// --------------------------------------------------------------------------
+
+int
+FreeImage_TagDataWidth(WORD type) {
+ static int format_bytes[] = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8, 4, 4 };
+
+ return (type < 15) ? format_bytes[type] : 0;
+}
+
+
+
diff --git a/Source/Metadata/FreeImageTag.h b/Source/Metadata/FreeImageTag.h
new file mode 100644
index 0000000..803dc1c
--- /dev/null
+++ b/Source/Metadata/FreeImageTag.h
@@ -0,0 +1,435 @@
+// ==========================================================
+// Tag manipulation functions
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FREEIMAGETAG_H
+#define FREEIMAGETAG_H
+
+// ==========================================================
+// Exif JPEG tags
+// ==========================================================
+
+// ----------------------------------------------------------
+// TIFF Rev. 6.0 Attribute Information Used in Exif
+// ----------------------------------------------------------
+
+// Tags relating to image data structure
+
+#define TAG_IMAGE_WIDTH 0x0100
+#define TAG_IMAGE_HEIGHT 0x0101
+#define TAG_BITS_PER_SAMPLE 0x0102
+#define TAG_COMPRESSION 0x0103
+#define TAG_PHOTOMETRIC_INTERPRETATION 0x0106
+#define TAG_ORIENTATION 0x0112
+#define TAG_SAMPLES_PER_PIXEL 0x0115
+#define TAG_PLANAR_CONFIGURATION 0x011C
+#define TAG_YCBCR_SUBSAMPLING 0x0212
+#define TAG_YCBCR_POSITIONING 0x0213
+#define TAG_X_RESOLUTION 0x011A
+#define TAG_Y_RESOLUTION 0x011B
+#define TAG_RESOLUTION_UNIT 0x0128
+
+// Tags relating to recording offset
+
+#define TAG_STRIP_OFFSETS 0x0111
+#define TAG_ROWS_PER_STRIP 0x0116
+#define TAG_STRIP_BYTE_COUNTS 0x0117
+#define TAG_JPEG_INTERCHANGE_FORMAT 0x0201
+#define TAG_JPEG_INTERCHANGE_FORMAT_LENGTH 0x0202
+
+// Tags relating to image data characteristics
+
+#define TAG_TRANSFER_FUNCTION 0x012D
+#define TAG_WHITE_POINT 0x013E
+#define TAG_PRIMARY_CHROMATICITIES 0x013F
+#define TAG_YCBCR_COEFFICIENTS 0x0211
+#define TAG_REFERENCE_BLACK_WHITE 0x0214
+
+// Other tags
+
+#define TAG_DATETIME 0x0132
+#define TAG_IMAGE_DESCRIPTION 0x010E
+#define TAG_MAKE 0x010F
+#define TAG_MODEL 0x0110
+#define TAG_SOFTWARE 0x0131
+#define TAG_ARTIST 0x013B
+#define TAG_COPYRIGHT 0x8298
+
+// ----------------------------------------------------------
+// Exif IFD Attribute Information
+// ----------------------------------------------------------
+
+// Tags relating to version
+
+#define TAG_EXIF_VERSION 0x9000
+#define TAG_FLASHPIX_VERSION 0xA000
+
+// Tag relating to image data characteristics
+
+#define TAG_COLOR_SPACE 0xA001
+
+// Tags relating to image configuration
+
+#define TAG_COMPONENTS_CONFIGURATION 0x9101
+#define TAG_COMPRESSED_BITS_PER_PIXEL 0x9102
+#define TAG_PIXEL_X_DIMENSION 0xA002
+#define TAG_PIXEL_Y_DIMENSION 0xA003
+
+// Tags relating to user information
+
+#define TAG_MARKER_NOTE 0x927C
+#define TAG_USER_COMMENT 0x9286
+
+// Tag relating to related file information
+
+#define TAG_RELATED_SOUND_FILE 0xA004
+
+// Tags relating to date and time
+
+#define TAG_DATETIME_ORIGINAL 0x9003
+#define TAG_DATETIME_DIGITIZED 0x9004
+#define TAG_SUBSECOND_TIME 0x9290
+#define TAG_SUBSECOND_TIME_ORIGINAL 0x9291
+#define TAG_SUBSECOND_TIME_DIGITIZED 0x9292
+
+// Tags relating to picture-taking conditions
+
+#define TAG_EXPOSURE_TIME 0x829A
+#define TAG_FNUMBER 0x829D
+#define TAG_EXPOSURE_PROGRAM 0x8822
+#define TAG_SPECTRAL_SENSITIVITY 0x8824
+#define TAG_ISO_SPEED_RATINGS 0x8827
+#define TAG_OECF 0x8828
+#define TAG_SHUTTER_SPEED_VALUE 0x9201
+#define TAG_APERTURE_VALUE 0x9202
+#define TAG_BRIGHTNESS_VALUE 0x9203
+#define TAG_EXPOSURE_BIAS_VALUE 0x9204
+#define TAG_MAX_APERTURE_VALUE 0x9205
+#define TAG_SUBJECT_DISTANCE 0x9206
+#define TAG_METERING_MODE 0x9207
+#define TAG_LIGHT_SOURCE 0x9208
+#define TAG_FLASH 0x9209
+#define TAG_FOCAL_LENGTH 0x920A
+#define TAG_SUBJECT_AREA 0x9214
+#define TAG_FLASH_ENERGY 0xA20B
+#define TAG_SPATIAL_FREQ_RESPONSE 0xA20C
+#define TAG_FOCAL_PLANE_X_RES 0xA20E
+#define TAG_FOCAL_PLANE_Y_RES 0xA20F
+#define TAG_FOCAL_PLANE_UNIT 0xA210
+#define TAG_SUBJECT_LOCATION 0xA214
+#define TAG_EXPOSURE_INDEX 0xA215
+#define TAG_SENSING_METHOD 0xA217
+#define TAG_FILE_SOURCE 0xA300
+#define TAG_SCENE_TYPE 0xA301
+#define TAG_CFA_PATTERN 0xA302
+#define TAG_CUSTOM_RENDERED 0xA401
+#define TAG_EXPOSURE_MODE 0xA402
+#define TAG_WHITE_BALANCE 0xA403
+#define TAG_DIGITAL_ZOOM_RATIO 0xA404
+#define TAG_FOCAL_LENGTH_IN_35MM_FILM 0xA405
+#define TAG_SCENE_CAPTURE_TYPE 0xA406
+#define TAG_GAIN_CONTROL 0xA407
+#define TAG_CONTRAST 0xA408
+#define TAG_SATURATION 0xA409
+#define TAG_SHARPNESS 0xA40A
+#define TAG_DEVICE_SETTING_DESCRIPTION 0xA40B
+#define TAG_SUBJECT_DISTANCE_RANGE 0xA40C
+
+// Other tags
+
+#define TAG_IMAGE_UNIQUE_ID 0xA420
+
+// ----------------------------------------------------------
+// GPS Attribute Information
+// ----------------------------------------------------------
+
+#define TAG_GPS_VERSION_ID 0x0000
+#define TAG_GPS_LATITUDE_REF 0x0001
+#define TAG_GPS_LATITUDE 0x0002
+#define TAG_GPS_LONGITUDE_REF 0x0003
+#define TAG_GPS_LONGITUDE 0x0004
+#define TAG_GPS_ALTITUDE_REF 0x0005
+#define TAG_GPS_ALTITUDE 0x0006
+#define TAG_GPS_TIME_STAMP 0x0007
+#define TAG_GPS_SATELLITES 0x0008
+#define TAG_GPS_STATUS 0x0009
+#define TAG_GPS_MEASURE_MODE 0x000A
+#define TAG_GPS_DOP 0x000B
+#define TAG_GPS_SPEED_REF 0x000C
+#define TAG_GPS_SPEED 0x000D
+#define TAG_GPS_TRACK_REF 0x000E
+#define TAG_GPS_TRACK 0x000F
+#define TAG_GPS_IMG_DIRECTION_REF 0x0010
+#define TAG_GPS_IMG_DIRECTION 0x0011
+#define TAG_GPS_MAP_DATUM 0x0012
+#define TAG_GPS_DEST_LATITUDE_REF 0x0013
+#define TAG_GPS_DEST_LATITUDE 0x0014
+#define TAG_GPS_DEST_LONGITUDE_REF 0x0015
+#define TAG_GPS_DEST_LONGITUDE 0x0016
+#define TAG_GPS_DEST_BEARING_REF 0x0017
+#define TAG_GPS_DEST_BEARING 0x0018
+#define TAG_GPS_DEST_DISTANCE_REF 0x0019
+#define TAG_GPS_DEST_DISTANCE 0x001A
+#define TAG_GPS_PROCESSING_METHOD 0x001B
+#define TAG_GPS_AREA_INFORMATION 0x001C
+#define TAG_GPS_DATE_STAMP 0x001D
+#define TAG_GPS_DIFFERENTIAL 0x001E
+
+// ==========================================================
+// IPTC/NAA tags
+// ==========================================================
+
+#define TAG_RECORD_VERSION 0x0200
+#define TAG_CAPTION 0x0278
+#define TAG_WRITER 0x027A
+#define TAG_HEADLINE 0x0269
+#define TAG_SPECIAL_INSTRUCTIONS 0x0228
+#define TAG_BY_LINE 0x0250
+#define TAG_BY_LINE_TITLE 0x0255
+#define TAG_CREDIT 0x026E
+#define TAG_SOURCE 0x0273
+#define TAG_OBJECT_NAME 0x0205
+#define TAG_DATE_CREATED 0x0237
+#define TAG_CITY 0x025A
+#define TAG_PROVINCE_OR_STATE 0x025F
+#define TAG_COUNTRY_OR_PRIMARY_LOCATION 0x0265
+#define TAG_ORIGINAL_TRANSMISSION_REFERENCE 0x0267
+#define TAG_CATEGORY 0x020F
+#define TAG_SUPPLEMENTAL_CATEGORIES 0x0214
+#define TAG_URGENCY 0x020A
+#define TAG_KEYWORDS 0x0219
+#define TAG_COPYRIGHT_NOTICE 0x0274
+#define TAG_RELEASE_DATE 0x021E
+#define TAG_RELEASE_TIME 0x0223
+#define TAG_TIME_CREATED 0x023C
+#define TAG_ORIGINATING_PROGRAM 0x0241
+
+// ==========================================================
+// GeoTIFF tags
+// ==========================================================
+
+// tags 33550 is a private tag registered to SoftDesk, Inc
+#define TIFFTAG_GEOPIXELSCALE 33550
+// tags 33920-33921 are private tags registered to Intergraph, Inc
+#define TIFFTAG_INTERGRAPH_MATRIX 33920
+#define TIFFTAG_GEOTIEPOINTS 33922
+// tags 34263-34264 are private tags registered to NASA-JPL Carto Group
+#define TIFFTAG_JPL_CARTO_IFD 34263
+#define TIFFTAG_GEOTRANSMATRIX 34264 /* New Matrix Tag replaces 33920 */
+// tags 34735-3438 are private tags registered to SPOT Image, Inc
+#define TIFFTAG_GEOKEYDIRECTORY 34735
+#define TIFFTAG_GEODOUBLEPARAMS 34736
+#define TIFFTAG_GEOASCIIPARAMS 34737
+
+// ==========================================================
+// FreeImage Animation tags
+// ==========================================================
+
+#define ANIMTAG_LOGICALWIDTH 0x0001
+#define ANIMTAG_LOGICALHEIGHT 0x0002
+#define ANIMTAG_GLOBALPALETTE 0x0003
+#define ANIMTAG_LOOP 0x0004
+#define ANIMTAG_FRAMELEFT 0x1001
+#define ANIMTAG_FRAMETOP 0x1002
+#define ANIMTAG_NOLOCALPALETTE 0x1003
+#define ANIMTAG_INTERLACED 0x1004
+#define ANIMTAG_FRAMETIME 0x1005
+#define ANIMTAG_DISPOSALMETHOD 0x1006
+
+// --------------------------------------------------------------------------
+// Helper functions to deal with the FITAG structure
+// --------------------------------------------------------------------------
+
+/**
+Describes the tag format descriptor
+@param type Tag data type
+@return Returns the width of a single element, in bytes
+@see FREE_IMAGE_MDTYPE
+*/
+int FreeImage_TagDataWidth(WORD type);
+
+// --------------------------------------------------------------------------
+
+/**
+ Structure to hold a tag information
+*/
+typedef struct tagTagInfo {
+ WORD tag; // Tag ID (required)
+ char *fieldname; // Field name (required)
+ char *description; // Field description (may be NULL)
+} TagInfo;
+
+
+/**
+ Class to hold tag information (based on Meyers’ Singleton).<br>
+
+ Sample usage :<br>
+ <code>
+ TagLib& s = TagLib::instance();
+ TagInfo *tag_info = s.getTagInfo(EXIF_MAIN, 0x0100);
+ </code>
+
+*/
+
+class TagLib {
+public:
+
+ /**
+ internal tag info tables registered in TagLib
+ */
+ enum MDMODEL {
+ UNKNOWN,
+ EXIF_MAIN,
+ EXIF_EXIF,
+ EXIF_GPS,
+ EXIF_INTEROP,
+ EXIF_MAKERNOTE_CANON,
+ EXIF_MAKERNOTE_CASIOTYPE1,
+ EXIF_MAKERNOTE_CASIOTYPE2,
+ EXIF_MAKERNOTE_FUJIFILM,
+ EXIF_MAKERNOTE_KYOCERA,
+ EXIF_MAKERNOTE_MINOLTA,
+ EXIF_MAKERNOTE_NIKONTYPE1,
+ EXIF_MAKERNOTE_NIKONTYPE2,
+ EXIF_MAKERNOTE_NIKONTYPE3,
+ EXIF_MAKERNOTE_OLYMPUSTYPE1,
+ EXIF_MAKERNOTE_PANASONIC,
+ EXIF_MAKERNOTE_ASAHI,
+ EXIF_MAKERNOTE_PENTAX,
+ EXIF_MAKERNOTE_SONY,
+ IPTC,
+ GEOTIFF,
+ ANIMATION
+ };
+
+private:
+
+ typedef std::map<WORD, TagInfo*> TAGINFO;
+ typedef std::map<int, TAGINFO*> TABLEMAP;
+
+ /// store hash tables for all known tag info tables
+ TABLEMAP _table_map;
+
+private:
+ /**
+ Constructor (private)<br>
+ This is where the tag info tables are initialized.
+ @see addMetadataModel
+ */
+ TagLib();
+
+ /// Assignement operator (disabled)
+ void operator=(TagLib&);
+
+ /// Copy constructor (disabled)
+ TagLib(const TagLib&);
+
+ /**
+ Used in the constructor to initialize the tag tables
+ @param md_model Internal metadata model
+ @param tag_table Tag info table
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL addMetadataModel(MDMODEL md_model, TagInfo *tag_table);
+
+public:
+ /// Destructor
+ ~TagLib();
+
+ /**
+ @return Returns a reference to the TagLib instance
+ */
+ static TagLib& instance();
+
+ /**
+ Given a tag ID, returns its TagInfo descriptor
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @return Returns the TagInfo descriptor if successful, returns NULL otherwise
+ */
+ const TagInfo* getTagInfo(MDMODEL md_model, WORD tagID);
+
+ /**
+ Given a tag ID, returns its tag field name.
+ When the tag is unknown and defaultKey is not NULL, a string such as "Tag 0x1234" is returned.
+ This string is contained in the provided defaultKey buffer (assumed to be an array of at least 16 chars).
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @param defaultKey Assumed to be an array of 16 chars. If not NULL, build a key for unknown tags
+ @return Returns the tag field name if successful, returns an 'unknown tag' string contained in defaultKey otherwise
+ */
+ const char* getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey);
+
+ /**
+ Given a tag ID, returns its description.
+ When the tag has no description, a NULL value is returned.
+ @param md_model Internal metadata model
+ @param tagID tag ID
+ @return Returns the tag description if successful, returns NULL otherwise
+ */
+ const char* getTagDescription(MDMODEL md_model, WORD tagID);
+
+ /**
+ Given a tag field name, returns its tag ID.
+ When the tag doesn't exists, a value '-1' is returned.
+ @param md_model Internal metadata model
+ @param key tag field name
+ @return Returns the tag ID if successful, returns -1 otherwise
+ */
+ int getTagID(MDMODEL md_model, const char *key);
+
+ /**
+ Perform a conversion between internal metadata models and FreeImage public metadata models
+ @param md_model Internal metadata model
+ */
+ FREE_IMAGE_MDMODEL getFreeImageModel(MDMODEL model);
+
+};
+
+// --------------------------------------------------------------------------
+// Constant strings
+// --------------------------------------------------------------------------
+
+/// Name of the XMP field
+static char *g_TagLib_XMPFieldName = "XMLPacket";
+
+// --------------------------------------------------------------------------
+// Metadata routines
+// --------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+// JPEG Exif profile
+BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
+
+// JPEG / TIFF IPTC profile
+BOOL read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen);
+BOOL write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size);
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif // FREEIMAGETAG_H
+
+
diff --git a/Source/Metadata/IPTC.cpp b/Source/Metadata/IPTC.cpp
new file mode 100644
index 0000000..b47140a
--- /dev/null
+++ b/Source/Metadata/IPTC.cpp
@@ -0,0 +1,321 @@
+// ==========================================================
+// Metadata functions implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+// ----------------------------------------------------------
+// IPTC JPEG / TIFF markers routines
+// ----------------------------------------------------------
+
+static const char* IPTC_DELIMITER = ";"; // keywords/supplemental category delimiter
+/**
+ Read and decode IPTC binary data
+*/
+BOOL
+read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
+ char defaultKey[16];
+ size_t length = datalen;
+ BYTE *profile = (BYTE*)dataptr;
+
+ std::string Keywords;
+ std::string SupplementalCategory;
+
+ WORD tag_id;
+
+ // create a tag
+
+ FITAG *tag = FreeImage_CreateTag();
+
+ TagLib& tag_lib = TagLib::instance();
+
+ // find start of the BIM portion of the binary data
+ size_t offset = 0;
+ while(offset < length - 1) {
+ if((profile[offset] == 0x1C) && (profile[offset+1] == 0x02))
+ break;
+ offset++;
+ }
+
+ // for each tag
+ while (offset < length) {
+
+ // identifies start of a tag
+ if (profile[offset] != 0x1c) {
+ break;
+ }
+ // we need at least five bytes left to read a tag
+ if ((offset + 5) >= length) {
+ break;
+ }
+
+ offset++;
+
+ int directoryType = profile[offset++];
+ int tagType = profile[offset++];;
+ int tagByteCount = ((profile[offset] & 0xFF) << 8) | (profile[offset + 1] & 0xFF);
+ offset += 2;
+
+ if ((offset + tagByteCount) > length) {
+ // data for tag extends beyond end of iptc segment
+ break;
+ }
+
+ // process the tag
+
+ tag_id = (WORD)(tagType | (directoryType << 8));
+
+ FreeImage_SetTagID(tag, tag_id);
+ FreeImage_SetTagLength(tag, tagByteCount);
+
+ // allocate a buffer to store the tag value
+ BYTE *iptc_value = (BYTE*)malloc((tagByteCount + 1) * sizeof(BYTE));
+ memset(iptc_value, 0, (tagByteCount + 1) * sizeof(BYTE));
+
+ // get the tag value
+
+ switch (tag_id) {
+ case TAG_RECORD_VERSION:
+ {
+ // short
+ FreeImage_SetTagType(tag, FIDT_SSHORT);
+ FreeImage_SetTagCount(tag, 1);
+ short *pvalue = (short*)&iptc_value[0];
+ *pvalue = (short)((profile[offset] << 8) | profile[offset + 1]);
+ FreeImage_SetTagValue(tag, pvalue);
+ break;
+ }
+
+ case TAG_RELEASE_DATE:
+ case TAG_DATE_CREATED:
+ // Date object
+ case TAG_RELEASE_TIME:
+ case TAG_TIME_CREATED:
+ // time
+ default:
+ {
+ // string
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagCount(tag, tagByteCount);
+ for(int i = 0; i < tagByteCount; i++) {
+ iptc_value[i] = profile[offset + i];
+ }
+ iptc_value[tagByteCount] = '\0';
+ FreeImage_SetTagValue(tag, (char*)&iptc_value[0]);
+ break;
+ }
+ }
+
+ if(tag_id == TAG_SUPPLEMENTAL_CATEGORIES) {
+ // concatenate the categories
+ if(SupplementalCategory.length() == 0) {
+ SupplementalCategory.append((char*)iptc_value);
+ } else {
+ SupplementalCategory.append(IPTC_DELIMITER);
+ SupplementalCategory.append((char*)iptc_value);
+ }
+ }
+ else if(tag_id == TAG_KEYWORDS) {
+ // concatenate the keywords
+ if(Keywords.length() == 0) {
+ Keywords.append((char*)iptc_value);
+ } else {
+ Keywords.append(IPTC_DELIMITER);
+ Keywords.append((char*)iptc_value);
+ }
+ }
+ else {
+ // get the tag key and description
+ const char *key = tag_lib.getTagFieldName(TagLib::IPTC, tag_id, defaultKey);
+ FreeImage_SetTagKey(tag, key);
+ const char *description = tag_lib.getTagDescription(TagLib::IPTC, tag_id);
+ FreeImage_SetTagDescription(tag, description);
+
+ // store the tag
+ if(key) {
+ FreeImage_SetMetadata(FIMD_IPTC, dib, key, tag);
+ }
+ }
+
+ free(iptc_value);
+
+ // next tag
+ offset += tagByteCount;
+
+ }
+
+ // store the 'keywords' tag
+ if(Keywords.length()) {
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagID(tag, TAG_KEYWORDS);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_KEYWORDS, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_KEYWORDS));
+ FreeImage_SetTagLength(tag, (DWORD)Keywords.length());
+ FreeImage_SetTagCount(tag, (DWORD)Keywords.length());
+ FreeImage_SetTagValue(tag, (char*)Keywords.c_str());
+ FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
+ }
+
+ // store the 'supplemental category' tag
+ if(SupplementalCategory.length()) {
+ FreeImage_SetTagType(tag, FIDT_ASCII);
+ FreeImage_SetTagID(tag, TAG_SUPPLEMENTAL_CATEGORIES);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::IPTC, TAG_SUPPLEMENTAL_CATEGORIES));
+ FreeImage_SetTagLength(tag, (DWORD)SupplementalCategory.length());
+ FreeImage_SetTagCount(tag, (DWORD)SupplementalCategory.length());
+ FreeImage_SetTagValue(tag, (char*)SupplementalCategory.c_str());
+ FreeImage_SetMetadata(FIMD_IPTC, dib, FreeImage_GetTagKey(tag), tag);
+ }
+
+ // delete the tag
+
+ FreeImage_DeleteTag(tag);
+
+ return TRUE;
+}
+
+// --------------------------------------------------------------------------
+
+static BYTE*
+append_iptc_tag(BYTE *profile, unsigned *profile_size, WORD id, DWORD length, const void *value) {
+ BYTE *buffer = NULL;
+
+ // calculate the new buffer size
+ size_t buffer_size = (5 + *profile_size + length) * sizeof(BYTE);
+ buffer = (BYTE*)malloc(buffer_size);
+ if(!buffer)
+ return NULL;
+
+ // add the header
+ buffer[0] = 0x1C;
+ buffer[1] = 0x02;
+ // add the tag type
+ buffer[2] = (BYTE)(id & 0x00FF);
+ // add the tag length
+ buffer[3] = (BYTE)(length >> 8);
+ buffer[4] = (BYTE)(length & 0xFF);
+ // add the tag value
+ memcpy(buffer + 5, (BYTE*)value, length);
+ // append the previous profile
+ if(NULL == profile) {
+ *profile_size = (5 + length);
+ }
+ else {
+ memcpy(buffer + 5 + length, profile, *profile_size);
+ *profile_size += (5 + length);
+ free(profile);
+ }
+
+ return buffer;
+}
+
+/**
+Encode IPTC metadata into a binary buffer.
+The buffer is allocated by the function and must be freed by the caller.
+*/
+BOOL
+write_iptc_profile(FIBITMAP *dib, BYTE **profile, unsigned *profile_size) {
+ FITAG *tag = NULL;
+ FIMETADATA *mdhandle = NULL;
+
+ BYTE *buffer = NULL;
+ unsigned buffer_size = 0;
+
+ // parse all IPTC tags and rebuild a IPTC profile
+ mdhandle = FreeImage_FindFirstMetadata(FIMD_IPTC, dib, &tag);
+
+ if(mdhandle) {
+ do {
+ WORD tag_id = FreeImage_GetTagID(tag);
+
+ // append the tag to the profile
+
+ switch(tag_id) {
+ case TAG_RECORD_VERSION:
+ // ignore (already handled)
+ break;
+
+ case TAG_SUPPLEMENTAL_CATEGORIES:
+ case TAG_KEYWORDS:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ std::string value = (const char*)FreeImage_GetTagValue(tag);
+
+ // split the tag value
+ std::vector<std::string> output;
+ std::string delimiter = IPTC_DELIMITER;
+
+ size_t offset = 0;
+ size_t delimiterIndex = 0;
+
+ delimiterIndex = value.find(delimiter, offset);
+ while (delimiterIndex != std::string::npos) {
+ output.push_back(value.substr(offset, delimiterIndex - offset));
+ offset += delimiterIndex - offset + delimiter.length();
+ delimiterIndex = value.find(delimiter, offset);
+ }
+ output.push_back(value.substr(offset));
+
+ // add as many tags as there are comma separated strings
+ for(int i = 0; i < (int)output.size(); i++) {
+ std::string& tag_value = output[i];
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, (DWORD)tag_value.length(), tag_value.c_str());
+ }
+
+ }
+ break;
+
+ case TAG_URGENCY:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ DWORD length = 1; // keep the first octet only
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
+ }
+ break;
+
+ default:
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ DWORD length = FreeImage_GetTagLength(tag);
+ buffer = append_iptc_tag(buffer, &buffer_size, tag_id, length, FreeImage_GetTagValue(tag));
+ }
+ break;
+ }
+
+ } while(FreeImage_FindNextMetadata(mdhandle, &tag));
+
+ FreeImage_FindCloseMetadata(mdhandle);
+
+ // add the DirectoryVersion tag
+ const short version = 0x0200;
+ buffer = append_iptc_tag(buffer, &buffer_size, TAG_RECORD_VERSION, sizeof(version), &version);
+
+ *profile = buffer;
+ *profile_size = buffer_size;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
diff --git a/Source/Metadata/TagConversion.cpp b/Source/Metadata/TagConversion.cpp
new file mode 100644
index 0000000..ba08b51
--- /dev/null
+++ b/Source/Metadata/TagConversion.cpp
@@ -0,0 +1,968 @@
+// ==========================================================
+// Tag to string conversion functions
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+#include "FIRational.h"
+
+#define MAX_TEXT_EXTENT 512
+
+/**
+Convert a tag to a C string
+*/
+static const char*
+ConvertAnyTag(FITAG *tag) {
+ char format[MAX_TEXT_EXTENT];
+ static std::string buffer;
+ DWORD i;
+
+ if(!tag)
+ return NULL;
+
+ buffer.erase();
+
+ // convert the tag value to a string buffer
+
+ FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
+ DWORD tag_count = FreeImage_GetTagCount(tag);
+
+ switch(tag_type) {
+ case FIDT_BYTE: // N x 8-bit unsigned integer
+ {
+ BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld", (long) pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %ld", (long) pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_SHORT: // N x 16-bit unsigned integer
+ {
+ unsigned short *pvalue = (unsigned short *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%hu", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %hu", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_LONG: // N x 32-bit unsigned integer
+ {
+ unsigned long *pvalue = (unsigned long *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%lu", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %lu", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_RATIONAL: // N x 64-bit unsigned fraction
+ {
+ DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_SBYTE: // N x 8-bit signed integer
+ {
+ char *pvalue = (char*)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld", (long) pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %ld", (long) pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_SSHORT: // N x 16-bit signed integer
+ {
+ short *pvalue = (short *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%hd", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %hd", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_SLONG: // N x 32-bit signed integer
+ {
+ long *pvalue = (long *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %ld", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_SRATIONAL:// N x 64-bit signed fraction
+ {
+ LONG *pvalue = (LONG*)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%ld/%ld", pvalue[0], pvalue[1]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %ld/%ld", pvalue[2*i], pvalue[2*i+1]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_FLOAT: // N x 32-bit IEEE floating point
+ {
+ float *pvalue = (float *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%f", (double) pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, "%f", (double) pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_DOUBLE: // N x 64-bit IEEE floating point
+ {
+ double *pvalue = (double *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%f", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, "%f", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_IFD: // N x 32-bit unsigned integer (offset)
+ {
+ unsigned long *pvalue = (unsigned long *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "%X", pvalue[0]);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " %X", pvalue[i]);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_PALETTE: // N x 32-bit RGBQUAD
+ {
+ RGBQUAD *pvalue = (RGBQUAD *)FreeImage_GetTagValue(tag);
+
+ sprintf(format, "(%d,%d,%d,%d)", pvalue[0].rgbRed, pvalue[0].rgbGreen, pvalue[0].rgbBlue, pvalue[0].rgbReserved);
+ buffer += format;
+ for(i = 1; i < tag_count; i++) {
+ sprintf(format, " (%d,%d,%d,%d)", pvalue[i].rgbRed, pvalue[i].rgbGreen, pvalue[i].rgbBlue, pvalue[i].rgbReserved);
+ buffer += format;
+ }
+ break;
+ }
+ case FIDT_ASCII: // 8-bit bytes w/ last byte null
+ case FIDT_UNDEFINED:// 8-bit untyped data
+ default:
+ {
+ int max_size = MIN((int)FreeImage_GetTagLength(tag), (int)MAX_TEXT_EXTENT);
+ if(max_size == MAX_TEXT_EXTENT)
+ max_size--;
+ memcpy(format, (char*)FreeImage_GetTagValue(tag), max_size);
+ format[max_size] = '\0';
+ buffer += format;
+ break;
+ }
+ }
+
+ return buffer.c_str();
+}
+
+/**
+Convert a Exif tag to a C string
+*/
+static const char*
+ConvertExifTag(FITAG *tag) {
+ char format[MAX_TEXT_EXTENT];
+ static std::string buffer;
+
+ if(!tag)
+ return NULL;
+
+ buffer.erase();
+
+ // convert the tag value to a string buffer
+
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_ORIENTATION:
+ {
+ unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (orientation) {
+ case 1:
+ return "top, left side";
+ case 2:
+ return "top, right side";
+ case 3:
+ return "bottom, right side";
+ case 4:
+ return "bottom, left side";
+ case 5:
+ return "left side, top";
+ case 6:
+ return "right side, top";
+ case 7:
+ return "right side, bottom";
+ case 8:
+ return "left side, bottom";
+ default:
+ break;
+ }
+ }
+ break;
+
+ case TAG_REFERENCE_BLACK_WHITE:
+ {
+ DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
+ if(FreeImage_GetTagLength(tag) == 48) {
+ // reference black point value and reference white point value (ReferenceBlackWhite)
+ int blackR = 0, whiteR = 0, blackG = 0, whiteG = 0, blackB = 0, whiteB = 0;
+ if(pvalue[1])
+ blackR = (int)(pvalue[0] / pvalue[1]);
+ if(pvalue[3])
+ whiteR = (int)(pvalue[2] / pvalue[3]);
+ if(pvalue[5])
+ blackG = (int)(pvalue[4] / pvalue[5]);
+ if(pvalue[7])
+ whiteG = (int)(pvalue[6] / pvalue[7]);
+ if(pvalue[9])
+ blackB = (int)(pvalue[8] / pvalue[9]);
+ if(pvalue[11])
+ whiteB = (int)(pvalue[10] / pvalue[11]);
+
+ sprintf(format, "[%d,%d,%d] [%d,%d,%d]", blackR, blackG, blackB, whiteR, whiteG, whiteB);
+ buffer += format;
+ return buffer.c_str();
+ }
+
+ }
+ break;
+
+ case TAG_COLOR_SPACE:
+ {
+ unsigned short colorSpace = *((unsigned short *)FreeImage_GetTagValue(tag));
+ if (colorSpace == 1) {
+ return "sRGB";
+ } else if (colorSpace == 65535) {
+ return "Undefined";
+ } else {
+ return "Unknown";
+ }
+ }
+ break;
+
+ case TAG_COMPONENTS_CONFIGURATION:
+ {
+ char *componentStrings[7] = {"", "Y", "Cb", "Cr", "R", "G", "B"};
+ BYTE *pvalue = (BYTE*)FreeImage_GetTagValue(tag);
+ for(DWORD i = 0; i < MIN((DWORD)4, FreeImage_GetTagCount(tag)); i++) {
+ int j = pvalue[i];
+ if(j > 0 && j < 7)
+ buffer += componentStrings[j];
+ }
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_COMPRESSED_BITS_PER_PIXEL:
+ {
+ FIRational r(tag);
+ buffer = r.toString();
+ if(buffer == "1")
+ buffer += " bit/pixel";
+ else
+ buffer += " bits/pixel";
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_X_RESOLUTION:
+ case TAG_Y_RESOLUTION:
+ case TAG_FOCAL_PLANE_X_RES:
+ case TAG_FOCAL_PLANE_Y_RES:
+ case TAG_BRIGHTNESS_VALUE:
+ case TAG_EXPOSURE_BIAS_VALUE:
+ {
+ FIRational r(tag);
+ buffer = r.toString();
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_RESOLUTION_UNIT:
+ case TAG_FOCAL_PLANE_UNIT:
+ {
+ unsigned short resolutionUnit = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (resolutionUnit) {
+ case 1:
+ return "(No unit)";
+ case 2:
+ return "inches";
+ case 3:
+ return "cm";
+ default:
+ break;
+ }
+ }
+ break;
+
+ case TAG_YCBCR_POSITIONING:
+ {
+ unsigned short yCbCrPosition = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (yCbCrPosition) {
+ case 1:
+ return "Center of pixel array";
+ case 2:
+ return "Datum point";
+ default:
+ break;
+ }
+ }
+ break;
+
+ case TAG_EXPOSURE_TIME:
+ {
+ FIRational r(tag);
+ buffer = r.toString();
+ buffer += " sec";
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_SHUTTER_SPEED_VALUE:
+ {
+ FIRational r(tag);
+ long apexValue = r.longValue();
+ long apexPower = 1 << apexValue;
+ sprintf(format, "1/%d sec", (int)apexPower);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_APERTURE_VALUE:
+ case TAG_MAX_APERTURE_VALUE:
+ {
+ FIRational r(tag);
+ double apertureApex = r.doubleValue();
+ double rootTwo = sqrt((double)2);
+ double fStop = pow(rootTwo, apertureApex);
+ sprintf(format, "F%.1f", fStop);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_FNUMBER:
+ {
+ FIRational r(tag);
+ double fnumber = r.doubleValue();
+ sprintf(format, "F%.1f", fnumber);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_FOCAL_LENGTH:
+ {
+ FIRational r(tag);
+ double focalLength = r.doubleValue();
+ sprintf(format, "%.1f mm", focalLength);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_FOCAL_LENGTH_IN_35MM_FILM:
+ {
+ unsigned short focalLength = *((unsigned short *)FreeImage_GetTagValue(tag));
+ sprintf(format, "%hu mm", focalLength);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_FLASH:
+ {
+ unsigned short flash = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch(flash) {
+ case 0x0000:
+ return "Flash did not fire";
+ case 0x0001:
+ return "Flash fired";
+ case 0x0005:
+ return "Strobe return light not detected";
+ case 0x0007:
+ return "Strobe return light detected";
+ case 0x0009:
+ return "Flash fired, compulsory flash mode";
+ case 0x000D:
+ return "Flash fired, compulsory flash mode, return light not detected";
+ case 0x000F:
+ return "Flash fired, compulsory flash mode, return light detected";
+ case 0x0010:
+ return "Flash did not fire, compulsory flash mode";
+ case 0x0018:
+ return "Flash did not fire, auto mode";
+ case 0x0019:
+ return "Flash fired, auto mode";
+ case 0x001D:
+ return "Flash fired, auto mode, return light not detected";
+ case 0x001F:
+ return "Flash fired, auto mode, return light detected";
+ case 0x0020:
+ return "No flash function";
+ case 0x0041:
+ return "Flash fired, red-eye reduction mode";
+ case 0x0045:
+ return "Flash fired, red-eye reduction mode, return light not detected";
+ case 0x0047:
+ return "Flash fired, red-eye reduction mode, return light detected";
+ case 0x0049:
+ return "Flash fired, compulsory flash mode, red-eye reduction mode";
+ case 0x004D:
+ return "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
+ case 0x004F:
+ return "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
+ case 0x0059:
+ return "Flash fired, auto mode, red-eye reduction mode";
+ case 0x005D:
+ return "Flash fired, auto mode, return light not detected, red-eye reduction mode";
+ case 0x005F:
+ return "Flash fired, auto mode, return light detected, red-eye reduction mode";
+ default:
+ sprintf(format, "Unknown (%d)", flash);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SCENE_TYPE:
+ {
+ BYTE sceneType = *((BYTE*)FreeImage_GetTagValue(tag));
+ if (sceneType == 1) {
+ return "Directly photographed image";
+ } else {
+ sprintf(format, "Unknown (%d)", sceneType);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SUBJECT_DISTANCE:
+ {
+ FIRational r(tag);
+ if(r.getNumerator() == 0xFFFFFFFF) {
+ return "Infinity";
+ } else if(r.getNumerator() == 0) {
+ return "Distance unknown";
+ } else {
+ double distance = r.doubleValue();
+ sprintf(format, "%.3f meters", distance);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_METERING_MODE:
+ {
+ unsigned short meteringMode = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (meteringMode) {
+ case 0:
+ return "Unknown";
+ case 1:
+ return "Average";
+ case 2:
+ return "Center weighted average";
+ case 3:
+ return "Spot";
+ case 4:
+ return "Multi-spot";
+ case 5:
+ return "Multi-segment";
+ case 6:
+ return "Partial";
+ case 255:
+ return "(Other)";
+ default:
+ return "";
+ }
+ }
+ break;
+
+ case TAG_LIGHT_SOURCE:
+ {
+ unsigned short lightSource = *((unsigned short *)FreeImage_GetTagValue(tag));
+ switch (lightSource) {
+ case 0:
+ return "Unknown";
+ case 1:
+ return "Daylight";
+ case 2:
+ return "Fluorescent";
+ case 3:
+ return "Tungsten (incandescent light)";
+ case 4:
+ return "Flash";
+ case 9:
+ return "Fine weather";
+ case 10:
+ return "Cloudy weather";
+ case 11:
+ return "Shade";
+ case 12:
+ return "Daylight fluorescent (D 5700 - 7100K)";
+ case 13:
+ return "Day white fluorescent (N 4600 - 5400K)";
+ case 14:
+ return "Cool white fluorescent (W 3900 - 4500K)";
+ case 15:
+ return "White fluorescent (WW 3200 - 3700K)";
+ case 17:
+ return "Standard light A";
+ case 18:
+ return "Standard light B";
+ case 19:
+ return "Standard light C";
+ case 20:
+ return "D55";
+ case 21:
+ return "D65";
+ case 22:
+ return "D75";
+ case 23:
+ return "D50";
+ case 24:
+ return "ISO studio tungsten";
+ case 255:
+ return "(Other)";
+ default:
+ return "";
+ }
+ }
+ break;
+
+ case TAG_SENSING_METHOD:
+ {
+ unsigned short sensingMethod = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (sensingMethod) {
+ case 1:
+ return "(Not defined)";
+ case 2:
+ return "One-chip color area sensor";
+ case 3:
+ return "Two-chip color area sensor";
+ case 4:
+ return "Three-chip color area sensor";
+ case 5:
+ return "Color sequential area sensor";
+ case 7:
+ return "Trilinear sensor";
+ case 8:
+ return "Color sequential linear sensor";
+ default:
+ return "";
+ }
+ }
+ break;
+
+ case TAG_FILE_SOURCE:
+ {
+ BYTE fileSource = *((BYTE*)FreeImage_GetTagValue(tag));
+ if (fileSource == 3) {
+ return "Digital Still Camera (DSC)";
+ } else {
+ sprintf(format, "Unknown (%d)", fileSource);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_EXPOSURE_PROGRAM:
+ {
+ unsigned short exposureProgram = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (exposureProgram) {
+ case 1:
+ return "Manual control";
+ case 2:
+ return "Program normal";
+ case 3:
+ return "Aperture priority";
+ case 4:
+ return "Shutter priority";
+ case 5:
+ return "Program creative (slow program)";
+ case 6:
+ return "Program action (high-speed program)";
+ case 7:
+ return "Portrait mode";
+ case 8:
+ return "Landscape mode";
+ default:
+ sprintf(format, "Unknown program (%d)", exposureProgram);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_CUSTOM_RENDERED:
+ {
+ unsigned short customRendered = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (customRendered) {
+ case 0:
+ return "Normal process";
+ case 1:
+ return "Custom process";
+ default:
+ sprintf(format, "Unknown rendering (%d)", customRendered);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_EXPOSURE_MODE:
+ {
+ unsigned short exposureMode = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (exposureMode) {
+ case 0:
+ return "Auto exposure";
+ case 1:
+ return "Manual exposure";
+ case 2:
+ return "Auto bracket";
+ default:
+ sprintf(format, "Unknown mode (%d)", exposureMode);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_WHITE_BALANCE:
+ {
+ unsigned short whiteBalance = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (whiteBalance) {
+ case 0:
+ return "Auto white balance";
+ case 1:
+ return "Manual white balance";
+ default:
+ sprintf(format, "Unknown (%d)", whiteBalance);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SCENE_CAPTURE_TYPE:
+ {
+ unsigned short sceneType = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (sceneType) {
+ case 0:
+ return "Standard";
+ case 1:
+ return "Landscape";
+ case 2:
+ return "Portrait";
+ case 3:
+ return "Night scene";
+ default:
+ sprintf(format, "Unknown (%d)", sceneType);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_GAIN_CONTROL:
+ {
+ unsigned short gainControl = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (gainControl) {
+ case 0:
+ return "None";
+ case 1:
+ return "Low gain up";
+ case 2:
+ return "High gain up";
+ case 3:
+ return "Low gain down";
+ case 4:
+ return "High gain down";
+ default:
+ sprintf(format, "Unknown (%d)", gainControl);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_CONTRAST:
+ {
+ unsigned short contrast = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (contrast) {
+ case 0:
+ return "Normal";
+ case 1:
+ return "Soft";
+ case 2:
+ return "Hard";
+ default:
+ sprintf(format, "Unknown (%d)", contrast);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SATURATION:
+ {
+ unsigned short saturation = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (saturation) {
+ case 0:
+ return "Normal";
+ case 1:
+ return "Low saturation";
+ case 2:
+ return "High saturation";
+ default:
+ sprintf(format, "Unknown (%d)", saturation);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SHARPNESS:
+ {
+ unsigned short sharpness = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (sharpness) {
+ case 0:
+ return "Normal";
+ case 1:
+ return "Soft";
+ case 2:
+ return "Hard";
+ default:
+ sprintf(format, "Unknown (%d)", sharpness);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_SUBJECT_DISTANCE_RANGE:
+ {
+ unsigned short distanceRange = *((unsigned short *)FreeImage_GetTagValue(tag));
+
+ switch (distanceRange) {
+ case 0:
+ return "unknown";
+ case 1:
+ return "Macro";
+ case 2:
+ return "Close view";
+ case 3:
+ return "Distant view";
+ default:
+ sprintf(format, "Unknown (%d)", distanceRange);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_ISO_SPEED_RATINGS:
+ {
+ unsigned short isoEquiv = *((unsigned short *)FreeImage_GetTagValue(tag));
+ if (isoEquiv < 50) {
+ isoEquiv *= 200;
+ }
+ sprintf(format, "%d", isoEquiv);
+ buffer += format;
+ return buffer.c_str();
+ }
+ break;
+
+ case TAG_USER_COMMENT:
+ {
+ // first 8 bytes are used to define an ID code
+ // we assume this is an ASCII string
+ const BYTE *userComment = (BYTE*)FreeImage_GetTagValue(tag);
+ for(DWORD i = 8; i < FreeImage_GetTagLength(tag); i++) {
+ buffer += userComment[i];
+ }
+ buffer += '\0';
+ return buffer.c_str();
+ }
+ break;
+
+ }
+
+ return ConvertAnyTag(tag);
+}
+
+/**
+Convert a Exif GPS tag to a C string
+*/
+static const char*
+ConvertExifGPSTag(FITAG *tag) {
+ char format[MAX_TEXT_EXTENT];
+ static std::string buffer;
+
+ if(!tag)
+ return NULL;
+
+ buffer.erase();
+
+ // convert the tag value to a string buffer
+
+ switch(FreeImage_GetTagID(tag)) {
+ case TAG_GPS_LATITUDE:
+ case TAG_GPS_LONGITUDE:
+ case TAG_GPS_TIME_STAMP:
+ {
+ DWORD *pvalue = (DWORD*)FreeImage_GetTagValue(tag);
+ if(FreeImage_GetTagLength(tag) == 24) {
+ // dd:mm:ss or hh:mm:ss
+ int dd = 0, mm = 0;
+ double ss = 0;
+
+ // convert to seconds
+ if(pvalue[1])
+ ss += ((double)pvalue[0] / (double)pvalue[1]) * 3600;
+ if(pvalue[3])
+ ss += ((double)pvalue[2] / (double)pvalue[3]) * 60;
+ if(pvalue[5])
+ ss += ((double)pvalue[4] / (double)pvalue[5]);
+
+ // convert to dd:mm:ss.ss
+ dd = (int)(ss / 3600);
+ mm = (int)(ss / 60) - dd * 60;
+ ss = ss - dd * 3600 - mm * 60;
+
+ sprintf(format, "%d:%d:%.2f", dd, mm, ss);
+ buffer += format;
+ return buffer.c_str();
+ }
+ }
+ break;
+
+ case TAG_GPS_VERSION_ID:
+ case TAG_GPS_LATITUDE_REF:
+ case TAG_GPS_LONGITUDE_REF:
+ case TAG_GPS_ALTITUDE_REF:
+ case TAG_GPS_ALTITUDE:
+ case TAG_GPS_SATELLITES:
+ case TAG_GPS_STATUS:
+ case TAG_GPS_MEASURE_MODE:
+ case TAG_GPS_DOP:
+ case TAG_GPS_SPEED_REF:
+ case TAG_GPS_SPEED:
+ case TAG_GPS_TRACK_REF:
+ case TAG_GPS_TRACK:
+ case TAG_GPS_IMG_DIRECTION_REF:
+ case TAG_GPS_IMG_DIRECTION:
+ case TAG_GPS_MAP_DATUM:
+ case TAG_GPS_DEST_LATITUDE_REF:
+ case TAG_GPS_DEST_LATITUDE:
+ case TAG_GPS_DEST_LONGITUDE_REF:
+ case TAG_GPS_DEST_LONGITUDE:
+ case TAG_GPS_DEST_BEARING_REF:
+ case TAG_GPS_DEST_BEARING:
+ case TAG_GPS_DEST_DISTANCE_REF:
+ case TAG_GPS_DEST_DISTANCE:
+ case TAG_GPS_PROCESSING_METHOD:
+ case TAG_GPS_AREA_INFORMATION:
+ case TAG_GPS_DATE_STAMP:
+ case TAG_GPS_DIFFERENTIAL:
+ break;
+ }
+
+ return ConvertAnyTag(tag);
+}
+
+// ==========================================================
+// Tag to string conversion function
+//
+
+const char* DLL_CALLCONV
+FreeImage_TagToString(FREE_IMAGE_MDMODEL model, FITAG *tag, char *Make) {
+ switch(model) {
+ case FIMD_EXIF_MAIN:
+ case FIMD_EXIF_EXIF:
+ return ConvertExifTag(tag);
+
+ case FIMD_EXIF_GPS:
+ return ConvertExifGPSTag(tag);
+
+ case FIMD_EXIF_MAKERNOTE:
+ // We should use the Make string to select an appropriate conversion function
+ // TO DO ...
+ break;
+
+ case FIMD_EXIF_INTEROP:
+ default:
+ break;
+ }
+
+ return ConvertAnyTag(tag);
+}
+
diff --git a/Source/Metadata/TagLib.cpp b/Source/Metadata/TagLib.cpp
new file mode 100644
index 0000000..2a00f46
--- /dev/null
+++ b/Source/Metadata/TagLib.cpp
@@ -0,0 +1,1096 @@
+// ==========================================================
+// Tag library
+//
+// Design and implementation by
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// Implementation notes :
+// ----------------------
+// The tag info tables declared in this file should probably
+// be loaded from an XML file.
+// This would allow internationalization features and also
+// more extensibility.
+// Maybe in a future release ?
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+
+/**
+ HOW-TO : add a new TagIngo table
+ --------------------------------------------------------------------------
+ 1) add a table identifier in the TagLib class definition (see enum MDMODEL)
+ 2) declare the tag table as static and use a 0/NULL value as last entry
+ 3) initialize the table in TagLib::TagLib
+ 4) provide a conversion in TagLib::getFreeImageModel
+*/
+
+// --------------------------------------------------------------------------
+// EXIF standard tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_exif_tag_table[] =
+ {
+ { 0x0100, (char *) "ImageWidth", (char *) "Image width"},
+ { 0x0101, (char *) "ImageLength", (char *) "Image height"},
+ { 0x0102, (char *) "BitsPerSample", (char *) "Number of bits per component"},
+ { 0x0103, (char *) "Compression", (char *) "Compression scheme"},
+ { 0x0106, (char *) "PhotometricInterpretation", (char *) "Pixel composition"},
+ { 0x010A, (char *) "FillOrder", (char*) NULL},
+ { 0x010D, (char *) "DocumentName", (char *) NULL},
+ { 0x010E, (char *) "ImageDescription", (char *) "Image title"},
+ { 0x010F, (char *) "Make", (char *) "Image input equipment manufacturer"},
+ { 0x0110, (char *) "Model", (char *) "Image input equipment model"},
+ { 0x0111, (char *) "StripOffsets", (char *) "Image data location"},
+ { 0x0112, (char *) "Orientation", (char *) "Orientation of image"},
+ { 0x0115, (char *) "SamplesPerPixel", (char *) "Number of components"},
+ { 0x0116, (char *) "RowsPerStrip", (char *) "Number of rows per strip"},
+ { 0x0117, (char *) "StripByteCounts", (char *) "Bytes per compressed strip"},
+ { 0x011A, (char *) "XResolution", (char *) "Image resolution in width direction"},
+ { 0x011B, (char *) "YResolution", (char *) "Image resolution in height direction"},
+ { 0x011C, (char *) "PlanarConfiguration", (char *) "Image data arrangement"},
+ { 0x0128, (char *) "ResolutionUnit", (char *) "Unit of X and Y resolution"},
+ { 0x012D, (char *) "TransferFunction", (char *) "Transfer function"},
+ { 0x0131, (char *) "Software", (char *) "Software used"},
+ { 0x0132, (char *) "DateTime", (char *) "File change date and time"},
+ { 0x013B, (char *) "Artist", (char *) "Person who created the image"},
+ { 0x013E, (char *) "WhitePoint", (char *) "White point chromaticity"},
+ { 0x013F, (char *) "PrimaryChromaticities", (char *) "Chromaticities of primaries"},
+ { 0x0156, (char *) "TransferRange", (char *) NULL},
+ { 0x0200, (char *) "JPEGProc", (char *) NULL},
+ { 0x0201, (char *) "JPEGInterchangeFormat", (char *) "Offset to JPEG SOI"},
+ { 0x0202, (char *) "JPEGInterchangeFormatLength", (char *) "Bytes of JPEG data"},
+ { 0x0211, (char *) "YCbCrCoefficients", (char *) "Color space transformation matrix coefficients"},
+ { 0x0212, (char *) "YCbCrSubSampling", (char *) "Subsampling ratio of Y to C"},
+ { 0x0213, (char *) "YCbCrPositioning", (char *) "Y and C positioning"},
+ { 0x0214, (char *) "ReferenceBlackWhite", (char *) "Pair of black and white reference values"},
+ { 0x828D, (char *) "CFARepeatPatternDim", (char *) NULL},
+ { 0x828E, (char *) "CFAPattern", (char *) NULL},
+ { 0x828F, (char *) "BatteryLevel", (char *) NULL},
+ { 0x8298, (char *) "Copyright", (char *) "Copyright holder"},
+ { 0x829A, (char *) "ExposureTime", (char *) "Exposure time"},
+ { 0x829D, (char *) "FNumber", (char *) "F number"},
+ { 0x83BB, (char *) "IPTC/NAA", (char *) NULL},
+ { 0x8773, (char *) "InterColorProfile", (char *) NULL},
+ { 0x8822, (char *) "ExposureProgram", (char *) "Exposure program"},
+ { 0x8824, (char *) "SpectralSensitivity", (char *) "Spectral sensitivity"},
+ { 0x8825, (char *) "GPSInfo", (char *) NULL},
+ { 0x8827, (char *) "ISOSpeedRatings", (char *) "ISO speed rating"},
+ { 0x8828, (char *) "OECF", (char *) "Optoelectric conversion factor"},
+ { 0x9000, (char *) "ExifVersion", (char *) "Exif version"},
+ { 0x9003, (char *) "DateTimeOriginal", (char *) "Date and time of original data generation"},
+ { 0x9004, (char *) "DateTimeDigitized", (char *) "Date and time of digital data generation"},
+ { 0x9101, (char *) "ComponentsConfiguration", (char *) "Meaning of each component"},
+ { 0x9102, (char *) "CompressedBitsPerPixel", (char *) "Image compression mode"},
+ { 0x9201, (char *) "ShutterSpeedValue", (char *) "Shutter speed"},
+ { 0x9202, (char *) "ApertureValue", (char *) "Aperture"},
+ { 0x9203, (char *) "BrightnessValue", (char *) "Brightness"},
+ { 0x9204, (char *) "ExposureBiasValue", (char *) "Exposure bias"},
+ { 0x9205, (char *) "MaxApertureValue", (char *) "Maximum lens aperture"},
+ { 0x9206, (char *) "SubjectDistance", (char *) "Subject distance"},
+ { 0x9207, (char *) "MeteringMode", (char *) "Metering mode"},
+ { 0x9208, (char *) "LightSource", (char *) "Light source"},
+ { 0x9209, (char *) "Flash", (char *) "Flash"},
+ { 0x920A, (char *) "FocalLength", (char *) "Lens focal length"},
+ { 0x9214, (char *) "SubjectArea", (char *) "Subject area"},
+ { 0x927C, (char *) "MakerNote", (char *) "Manufacturer notes"},
+ { 0x9286, (char *) "UserComment", (char *) "User comments"},
+ { 0x9290, (char *) "SubSecTime", (char *) "DateTime subseconds"},
+ { 0x9291, (char *) "SubSecTimeOriginal", (char *) "DateTimeOriginal subseconds"},
+ { 0x9292, (char *) "SubSecTimeDigitized", (char *) "DateTimeDigitized subseconds"},
+ { 0xA000, (char *) "FlashPixVersion", (char *) "Supported Flashpix version"},
+ { 0xA001, (char *) "ColorSpace", (char *) "Color space information"},
+ { 0xA002, (char *) "PixelXDimension", (char *) "Valid image width"},
+ { 0xA003, (char *) "PixelYDimension", (char *) "Valid image height"},
+ { 0xA004, (char *) "RelatedSoundFile", (char *) "Related audio file"},
+ { 0xA005, (char *) "InteroperabilityOffset", (char *) NULL},
+ { 0xA20B, (char *) "FlashEnergy", (char *) "Flash energy"},
+ { 0xA20C, (char *) "SpatialFrequencyResponse", (char *) "Spatial frequency response"},
+ { 0xA20E, (char *) "FocalPlaneXResolution", (char *) "Focal plane X resolution"},
+ { 0xA20F, (char *) "FocalPlaneYResolution", (char *) "Focal plane Y resolution"},
+ { 0xA210, (char *) "FocalPlaneResolutionUnit", (char *) "Focal plane resolution unit"},
+ { 0xA214, (char *) "SubjectLocation", (char *) "Subject location"},
+ { 0xA215, (char *) "ExposureIndex", (char *) "Exposure index"},
+ { 0xA217, (char *) "SensingMethod", (char *) "Sensing method"},
+ { 0xA300, (char *) "FileSrc", (char *) "File source"},
+ { 0xA301, (char *) "SceneType", (char *) "Scene type"},
+ { 0xA302, (char *) "CFAPattern", (char *) "CFA pattern"},
+ { 0xA401, (char *) "CustomRendered", (char *) "Custom image processing"},
+ { 0xA402, (char *) "ExposureMode", (char *) "Exposure mode"},
+ { 0xA403, (char *) "WhiteBalance", (char *) "White balance"},
+ { 0xA404, (char *) "DigitalZoomRatio", (char *) "Digital zoom ratio"},
+ { 0xA405, (char *) "FocalLengthIn35mmFilm", (char *) "Focal length in 35 mm film"},
+ { 0xA406, (char *) "SceneCaptureType", (char *) "Scene capture type"},
+ { 0xA407, (char *) "GainControl", (char *) "Gain control"},
+ { 0xA408, (char *) "Contrast", (char *) "Contrast"},
+ { 0xA409, (char *) "Saturation", (char *) "Saturation"},
+ { 0xA40A, (char *) "Sharpness", (char *) "Sharpness"},
+ { 0xA40B, (char *) "DeviceSettingDescription", (char *) "Device settings description"},
+ { 0xA40C, (char *) "SubjectDistanceRange", (char *) "Subject distance range"},
+ { 0xA420, (char *) "ImageUniqueID", (char *) "Unique image ID"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF GPS tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_gps_tag_table[] =
+ {
+ { 0x0000, (char *) "GPSVersionID", (char *) "GPS tag version"},
+ { 0x0001, (char *) "GPSLatitudeRef", (char *) "North or South Latitude"},
+ { 0x0002, (char *) "GPSLatitude", (char *) "Latitude"},
+ { 0x0003, (char *) "GPSLongitudeRef", (char *) "East or West Longitude"},
+ { 0x0004, (char *) "GPSLongitude", (char *) "Longitude"},
+ { 0x0005, (char *) "GPSAltitudeRef", (char *) "Altitude reference"},
+ { 0x0006, (char *) "GPSAltitude", (char *) "Altitude"},
+ { 0x0007, (char *) "GPSTimeStamp", (char *) "GPS time (atomic clock)"},
+ { 0x0008, (char *) "GPSSatellites", (char *) "GPS satellites used for measurement"},
+ { 0x0009, (char *) "GPSStatus", (char *) "GPS receiver status"},
+ { 0x000A, (char *) "GPSMeasureMode", (char *) "GPS measurement mode"},
+ { 0x000B, (char *) "GPSDOP", (char *) "Measurement precision"},
+ { 0x000C, (char *) "GPSSpeedRef", (char *) "Speed unit"},
+ { 0x000D, (char *) "GPSSpeed", (char *) "Speed of GPS receiver"},
+ { 0x000E, (char *) "GPSTrackRef", (char *) "Reference for direction of movement"},
+ { 0x000F, (char *) "GPSTrack", (char *) "Direction of movement"},
+ { 0x0010, (char *) "GPSImgDirectionRef", (char *) "Reference for direction of image"},
+ { 0x0011, (char *) "GPSImgDirection", (char *) "Direction of image"},
+ { 0x0012, (char *) "GPSMapDatum", (char *) "Geodetic survey data used"},
+ { 0x0013, (char *) "GPSDestLatitudeRef", (char *) "Reference for latitude of destination"},
+ { 0x0014, (char *) "GPSDestLatitude", (char *) "Latitude of destination"},
+ { 0x0015, (char *) "GPSDestLongitudeRef", (char *) "Reference for longitude of destination"},
+ { 0x0016, (char *) "GPSDestLongitude", (char *) "Longitude of destination"},
+ { 0x0017, (char *) "GPSDestBearingRef", (char *) "Reference for bearing of destination"},
+ { 0x0018, (char *) "GPSDestBearing", (char *) "Bearing of destination"},
+ { 0x0019, (char *) "GPSDestDistanceRef", (char *) "Reference for distance to destination"},
+ { 0x001A, (char *) "GPSDestDistance", (char *) "Distance to destination"},
+ { 0x001B, (char *) "GPSProcessingMethod", (char *) "Name of GPS processing method"},
+ { 0x001C, (char *) "GPSAreaInformation", (char *) "Name of GPS area"},
+ { 0x001D, (char *) "GPSDateStamp", (char *) "GPS date"},
+ { 0x001E, (char *) "GPSDifferential", (char *) "GPS differential correction"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF interoperability tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ exif_interop_tag_table[] =
+ {
+ { 0x0001, (char *) "InteroperabilityIndex", (char *) "Interoperability Identification"},
+ { 0x0002, (char *) "InteroperabilityVersion", (char *) "Interoperability version"},
+ { 0x1000, (char *) "RelatedImageFileFormat", (char *) "File format of image file"},
+ { 0x1001, (char *) "RelatedImageWidth", (char *) "Image width"},
+ { 0x1002, (char *) "RelatedImageLength", (char *) "Image height"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// EXIF maker note tags definition
+// --------------------------------------------------------------------------
+
+/**
+Canon maker note
+*/
+static TagInfo
+ exif_canon_tag_table[] =
+ {
+ { 0x0001, (char *) "CanonCameraSettings", (char *) "Canon CameraSettings Tags"},
+ { 0x0002, (char *) "CanonFocalLength", (char *) "Canon FocalLength Tags"},
+ { 0x0003, (char *) "CanonFlashInfo?", (char *) NULL},
+ { 0x0004, (char *) "CanonShotInfo", (char *) "Canon ShotInfo Tags"},
+ { 0x0005, (char *) "CanonPanorama", (char *) "Canon Panorama Tags"},
+ { 0x0006, (char *) "CanonImageType", (char *) NULL},
+ { 0x0007, (char *) "CanonFirmwareVersion", (char *) NULL},
+ { 0x0008, (char *) "FileNumber", (char *) NULL},
+ { 0x0009, (char *) "OwnerName", (char *) NULL},
+ { 0x000A, (char *) "ColorInfoD30", (char *) "Canon ColorInfoD30 Tags"},
+ { 0x000C, (char *) "SerialNumber", (char *) NULL},
+ { 0x000D, (char *) "CanonCameraInfo", (char *) "Canon CameraInfo Tags"},
+ { 0x000E, (char *) "CanonFileLength", (char *) NULL},
+ { 0x000F, (char *) "CanonCustomFunctions", (char *) "Custom Functions"},
+ { 0x0010, (char *) "CanonModelID", (char *) NULL},
+ { 0x0012, (char *) "CanonPictureInfo", (char *) "Canon PictureInfo Tags"},
+ { 0x0015, (char *) "SerialNumberFormat", (char *) NULL},
+
+ // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
+
+ // Fields under tag 0x0001 (we add 0xC100 to make unique tag id)
+ { 0xC101, (char *) "CameraSettings:MacroMode", (char *) NULL},
+ { 0xC102, (char *) "CameraSettings:SelfTimerDelay", (char *) NULL},
+ { 0xC103, (char *) "CameraSettings:Quality", (char *) NULL},
+ { 0xC104, (char *) "CameraSettings:CanonFlashMode", (char *) NULL},
+ { 0xC105, (char *) "CameraSettings:ContinuousDrive", (char *) NULL},
+ { 0xC107, (char *) "CameraSettings:FocusMode", (char *) NULL},
+ { 0xC10A, (char *) "CameraSettings:CanonImageSize", (char *) NULL},
+ { 0xC10B, (char *) "CameraSettings:EasyMode", (char *) NULL},
+ { 0xC10C, (char *) "CameraSettings:DigitalZoom", (char *) NULL},
+ { 0xC10D, (char *) "CameraSettings:Contrast", (char *) NULL},
+ { 0xC10E, (char *) "CameraSettings:Saturation", (char *) NULL},
+ { 0xC10F, (char *) "CameraSettings:Sharpness", (char *) NULL},
+ { 0xC110, (char *) "CameraSettings:CameraISO", (char *) NULL},
+ { 0xC111, (char *) "CameraSettings:MeteringMode", (char *) NULL},
+ { 0xC112, (char *) "CameraSettings:FocusRange", (char *) NULL},
+ { 0xC113, (char *) "CameraSettings:AFPoint", (char *) NULL},
+ { 0xC114, (char *) "CameraSettings:CanonExposureMode", (char *) NULL},
+ { 0xC116, (char *) "CameraSettings:LensType", (char *) NULL},
+ { 0xC117, (char *) "CameraSettings:LongFocal", (char *) NULL},
+ { 0xC118, (char *) "CameraSettings:ShortFocal", (char *) NULL},
+ { 0xC119, (char *) "CameraSettings:FocalUnits", (char *) "Focal Units per mm"},
+ { 0xC11A, (char *) "CameraSettings:MaxAperture", (char *) NULL},
+ { 0xC11B, (char *) "CameraSettings:MinAperture", (char *) NULL},
+ { 0xC11C, (char *) "CameraSettings:FlashActivity", (char *) NULL},
+ { 0xC11D, (char *) "CameraSettings:FlashBits", (char *) NULL},
+ { 0xC120, (char *) "CameraSettings:FocusContinuous", (char *) NULL},
+ { 0xC121, (char *) "CameraSettings:AESetting", (char *) NULL},
+ { 0xC122, (char *) "CameraSettings:ImageStabilization", (char *) NULL},
+ { 0xC123, (char *) "CameraSettings:DisplayAperture", (char *) NULL},
+ { 0xC124, (char *) "CameraSettings:ZoomSourceWidth", (char *) NULL},
+ { 0xC125, (char *) "CameraSettings:ZoomTargetWidth", (char *) NULL},
+ { 0xC128, (char *) "CameraSettings:PhotoEffect", (char *) NULL},
+ { 0xC12A, (char *) "CameraSettings:ColorTone", (char *) NULL},
+
+ // Fields under tag 0x0002 (we add 0xC200 to make unique tag id)
+ { 0xC200, (char *) "FocalLength:FocalType", (char *) NULL},
+ { 0xC201, (char *) "FocalLength:FocalLength", (char *) NULL},
+ { 0xC202, (char *) "FocalLength:FocalPlaneXSize", (char *) NULL},
+ { 0xC203, (char *) "FocalLength:FocalPlaneYSize", (char *) NULL},
+
+ // Fields under tag 0x0004 (we add 0xC400 to make unique tag id)
+ { 0xC402, (char *) "ShotInfo:ISO", (char *) NULL},
+ { 0xC404, (char *) "ShotInfo:TargetAperture", (char *) NULL},
+ { 0xC405, (char *) "ShotInfo:TargetExposureTime", (char *) NULL},
+ { 0xC406, (char *) "ShotInfo:ExposureCompensation", (char *) NULL},
+ { 0xC407, (char *) "ShotInfo:WhiteBalance", (char *) NULL},
+ { 0xC408, (char *) "ShotInfo:SlowShutter", (char *) NULL},
+ { 0xC409, (char *) "ShotInfo:SequenceNumber", (char *) NULL},
+ { 0xC40D, (char *) "ShotInfo:FlashGuideNumber", (char *) NULL},
+ { 0xC40E, (char *) "ShotInfo:AFPointUsed", (char *) NULL},
+ { 0xC40F, (char *) "ShotInfo:FlashExposureComp", (char *) NULL},
+ { 0xC410, (char *) "ShotInfo:AutoExposureBracketing", (char *) NULL},
+ { 0xC411, (char *) "ShotInfo:AEBBracketValue", (char *) NULL},
+ { 0xC413, (char *) "ShotInfo:FocusDistanceUpper", (char *) NULL},
+ { 0xC414, (char *) "ShotInfo:FocusDistanceLower", (char *) NULL},
+ { 0xC415, (char *) "ShotInfo:FNumber", (char *) NULL},
+ { 0xC416, (char *) "ShotInfo:ExposureTime", (char *) NULL},
+ { 0xC418, (char *) "ShotInfo:BulbDuration", (char *) NULL},
+ { 0xC41B, (char *) "ShotInfo:AutoRotate", (char *) NULL},
+ { 0xC41D, (char *) "ShotInfo:SelfTimer2", (char *) NULL},
+
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Casio maker note
+*/
+static TagInfo
+ exif_casio_type1_tag_table[] =
+ {
+ { 0x0001, (char *) "RecordingMode", (char *) NULL},
+ { 0x0002, (char *) "Quality", (char *) NULL},
+ { 0x0003, (char *) "FocusMode", (char *) NULL},
+ { 0x0004, (char *) "FlashMode", (char *) NULL},
+ { 0x0005, (char *) "FlashIntensity", (char *) NULL},
+ { 0x0006, (char *) "ObjectDistance", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x000A, (char *) "DigitalZoom", (char *) NULL},
+ { 0x000B, (char *) "Sharpness", (char *) NULL},
+ { 0x000C, (char *) "Contrast", (char *) NULL},
+ { 0x000D, (char *) "Saturation", (char *) NULL},
+ { 0x0014, (char *) "CCDSensitivity", (char *) NULL},
+ { 0x0016, (char *) "Enhancement", (char *) NULL},
+ { 0x0017, (char *) "Filter", (char *) NULL},
+ { 0x0018, (char *) "AFPoint", (char *) NULL},
+ { 0x0019, (char *) "FlashIntensity", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+static TagInfo
+ exif_casio_type2_tag_table[] =
+ {
+ { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
+ { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0008, (char *) "QualityMode", (char *) NULL},
+ { 0x0009, (char *) "CasioImageSize", (char *) NULL},
+ { 0x000D, (char *) "FocusMode", (char *) NULL},
+ { 0x0014, (char *) "ISO", (char *) NULL},
+ { 0x0019, (char *) "WhiteBalance", (char *) NULL},
+ { 0x001D, (char *) "FocalLength", (char *) NULL},
+ { 0x001F, (char *) "Saturation", (char *) NULL},
+ { 0x0020, (char *) "Contrast", (char *) NULL},
+ { 0x0021, (char *) "Sharpness", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x2000, (char *) "PreviewImage", (char *) NULL},
+ { 0x2011, (char *) "WhiteBalanceBias", (char *) NULL},
+ { 0x2012, (char *) "WhiteBalance", (char *) NULL},
+ { 0x2022, (char *) "ObjectDistance", (char *) NULL},
+ { 0x2034, (char *) "FlashDistance", (char *) NULL},
+ { 0x3000, (char *) "RecordMode", (char *) NULL},
+ { 0x3001, (char *) "SelfTimer", (char *) NULL},
+ { 0x3002, (char *) "Quality", (char *) NULL},
+ { 0x3003, (char *) "FocusMode", (char *) NULL},
+ { 0x3006, (char *) "TimeZone", (char *) NULL},
+ { 0x3007, (char *) "BestShotMode", (char *) NULL},
+ { 0x3008, (char *) "AutoISO", (char *) NULL},
+ { 0x3011, (char *) "Sharpness", (char *) NULL},
+ { 0x3012, (char *) "Contrast", (char *) NULL},
+ { 0x3013, (char *) "Saturation", (char *) NULL},
+ { 0x3014, (char *) "CCDISOSensitivity", (char *) NULL},
+ { 0x3015, (char *) "ColorMode", (char *) NULL},
+ { 0x3016, (char *) "Enhancement", (char *) NULL},
+ { 0x3017, (char *) "Filter", (char *) NULL},
+ { 0x301C, (char *) "SequenceNumber", (char *) NULL},
+ { 0x301D, (char *) "BracketSequence", (char *) NULL},
+ { 0x3020, (char *) "ImageStabilization", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+FujiFilm maker note
+*/
+static TagInfo
+ exif_fujifilm_tag_table[] =
+ {
+ { 0x0000, (char *) "MakernoteVersion", (char *) NULL},
+ { 0x0010, (char *) "InternalSerialNumber", (char *) NULL},
+ { 0x1000, (char *) "Quality", (char *) NULL},
+ { 0x1001, (char *) "Sharpness", (char *) NULL},
+ { 0x1002, (char *) "WhiteBalance", (char *) NULL},
+ { 0x1003, (char *) "Color", (char *) NULL},
+ { 0x1004, (char *) "Tone", (char *) NULL},
+ { 0x1010, (char *) "FlashMode", (char *) NULL},
+ { 0x1011, (char *) "FlashStrength", (char *) NULL},
+ { 0x1020, (char *) "Macro", (char *) NULL},
+ { 0x1021, (char *) "FocusMode", (char *) NULL},
+ { 0x1023, (char *) "FocusPixel", (char *) NULL},
+ { 0x1030, (char *) "SlowSynchro", (char *) NULL},
+ { 0x1031, (char *) "PictureMode", (char *) NULL},
+ { 0x1100, (char *) "AutoBracketting", (char *) NULL},
+ { 0x1101, (char *) "SequenceNumber", (char *) NULL},
+ { 0x1210, (char *) "ColorMode", (char *) NULL},
+ { 0x1300, (char *) "BlurWarning", (char *) NULL},
+ { 0x1301, (char *) "FocusWarning", (char *) NULL},
+ { 0x1302, (char *) "ExposureWarning", (char *) NULL},
+ { 0x1400, (char *) "DynamicRange", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Kyocera maker note
+*/
+static TagInfo
+ exif_kyocera_tag_table[] =
+ {
+ { 0x0001, (char *) "ThumbnailImage", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) "Print Image Matching Info"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Olympus Type 1 / Epson / Agfa maker note
+*/
+static TagInfo
+ exif_olympus_type1__tag_table[] =
+ {
+ { 0x0000, (char *) "MakerNoteVersion", (char *) NULL},
+ { 0x0001, (char *) "MinoltaCameraSettingsOld", (char *) NULL},
+ { 0x0003, (char *) "MinoltaCameraSettings", (char *) NULL},
+ { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
+ { 0x0081, (char *) "PreviewImageData", (char *) NULL},
+ { 0x0088, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0089, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0100, (char *) "ThumbnailImage", (char *) NULL},
+ { 0x0101, (char *) "ColorMode", (char *) NULL},
+ { 0x0200, (char *) "SpecialMode", (char *) NULL},
+ { 0x0201, (char *) "Quality", (char *) NULL},
+ { 0x0202, (char *) "Macro", (char *) NULL},
+ { 0x0203, (char *) "BWMode", (char *) NULL},
+ { 0x0204, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0205, (char *) "FocalPlaneDiagonal", (char *) NULL},
+ { 0x0206, (char *) "LensDistortionParams", (char *) NULL},
+ { 0x0207, (char *) "CameraType", (char *) NULL},
+ { 0x0208, (char *) "TextInfo", (char *) "Olympus TextInfo Tags"},
+ { 0x0209, (char *) "CameraID", (char *) NULL},
+ { 0x0300, (char *) "PreCaptureFrames", (char *) NULL},
+ { 0x0302, (char *) "OneTouchWB", (char *) NULL},
+ { 0x0404, (char *) "SerialNumber", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) "PrintIM Tags"},
+ { 0x0F00, (char *) "DataDump", (char *) NULL},
+ { 0x0F01, (char *) "DataDump2", (char *) NULL},
+ { 0x1000, (char *) "ShutterSpeedValue", (char *) NULL},
+ { 0x1001, (char *) "ISOValue", (char *) NULL},
+ { 0x1002, (char *) "ApertureValue", (char *) NULL},
+ { 0x1003, (char *) "BrightnessValue", (char *) NULL},
+ { 0x1004, (char *) "FlashMode", (char *) NULL},
+ { 0x1005, (char *) "FlashDevice", (char *) NULL},
+ { 0x1006, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x1007, (char *) "SensorTemperature", (char *) NULL},
+ { 0x1008, (char *) "LensTemperature", (char *) NULL},
+ { 0x100B, (char *) "FocusMode", (char *) NULL},
+ { 0x100C, (char *) "ManualFocusDistance", (char *) NULL},
+ { 0x100D, (char *) "ZoomStepCount", (char *) NULL},
+ { 0x100E, (char *) "FocusStepCount", (char *) NULL},
+ { 0x100F, (char *) "Sharpness", (char *) NULL},
+ { 0x1010, (char *) "FlashChargeLevel", (char *) NULL},
+ { 0x1011, (char *) "ColorMatrix", (char *) NULL},
+ { 0x1012, (char *) "BlackLevel", (char *) NULL},
+ { 0x1015, (char *) "WBMode", (char *) NULL},
+ { 0x1017, (char *) "RedBalance", (char *) NULL},
+ { 0x1018, (char *) "BlueBalance", (char *) NULL},
+ { 0x101A, (char *) "SerialNumber", (char *) NULL},
+ { 0x1023, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x1026, (char *) "ExternalFlashBounce", (char *) NULL},
+ { 0x1027, (char *) "ExternalFlashZoom", (char *) NULL},
+ { 0x1028, (char *) "ExternalFlashMode", (char *) NULL},
+ { 0x1029, (char *) "Contrast", (char *) NULL},
+ { 0x102A, (char *) "SharpnessFactor", (char *) NULL},
+ { 0x102B, (char *) "ColorControl", (char *) NULL},
+ { 0x102C, (char *) "ValidBits", (char *) NULL},
+ { 0x102D, (char *) "CoringFilter", (char *) NULL},
+ { 0x102E, (char *) "OlympusImageWidth", (char *) NULL},
+ { 0x102F, (char *) "OlympusImageHeight", (char *) NULL},
+ { 0x1034, (char *) "CompressionRatio", (char *) NULL},
+ { 0x1035, (char *) "PreviewImageValid", (char *) NULL},
+ { 0x1036, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x1037, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x1039, (char *) "CCDScanMode", (char *) NULL},
+ { 0x103A, (char *) "NoiseReduction", (char *) NULL},
+ { 0x103B, (char *) "InfinityLensStep", (char *) NULL},
+ { 0x103C, (char *) "NearLensStep", (char *) NULL},
+ { 0x2010, (char *) "Equipment", (char *) "Olympus Equipment Tags"},
+ { 0x2020, (char *) "CameraSettings", (char *) "Olympus CameraSettings Tags"},
+ { 0x2030, (char *) "RawDevelopment", (char *) "Olympus RawDevelopment Tags"},
+ { 0x2040, (char *) "ImageProcessing", (char *) "Olympus ImageProcessing Tags"},
+ { 0x2050, (char *) "FocusInfo", (char *) "Olympus FocusInfo Tags"},
+ { 0x3000, (char *) "RawInfo", (char *) "Olympus RawInfo Tags"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Minolta maker note
+*/
+static TagInfo
+ exif_minolta_tag_table[] =
+ {
+ { 0x0000, (char *) "Version", (char *) NULL},
+ { 0x0040, (char *) "CompressedImageSize", (char *) NULL},
+ { 0x0081, (char *) "JPEGThumbnailImage", (char *) NULL},
+ { 0x0088, (char *) "JPEGThumbnailOffset", (char *) NULL},
+ { 0x0089, (char *) "JPEGThumbnailLength", (char *) NULL},
+ { 0x0101, (char *) "ColorMode", (char *) NULL},
+ { 0x0102, (char *) "ImageQuality", (char *) NULL},
+ { 0x0103, (char *) "ImageQuality2", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+There are 3 formats of Nikon's MakerNote. MakerNote of E700/E800/E900/E900S/E910/E950
+starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from
+offset 0x08. This is the same as Olympus except start string.
+*/
+
+/**
+TYPE 1 is for E-Series cameras prior to (not including) E990
+*/
+static TagInfo
+ exif_nikon_type1_tag_table[] =
+ {
+ { 0x0002, (char *) "FamilyID", (char *) NULL},
+ { 0x0003, (char *) "Quality", (char *) NULL},
+ { 0x0004, (char *) "ColorMode", (char *) NULL},
+ { 0x0005, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0006, (char *) "CCDSensitivity", (char *) NULL},
+ { 0x0007, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0008, (char *) "Focus", (char *) NULL},
+ { 0x000A, (char *) "DigitalZoom", (char *) NULL},
+ { 0x000B, (char *) "FisheyeConverter", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+static TagInfo
+ exif_nikon_type2_tag_table[] =
+ {
+ { 0x0001, (char *) "FirmwareVersion", (char *) NULL},
+ { 0x0002, (char *) "ISOSetting", (char *) NULL},
+ { 0x0003, (char *) "ColorMode", (char *) NULL},
+ { 0x0004, (char *) "Quality", (char *) NULL},
+ { 0x0005, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0006, (char *) "ImageSharpening", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x0008, (char *) "FlashSetting", (char *) NULL},
+ { 0x0009, (char *) "AutoFlashMode", (char *) NULL},
+ { 0x000B, (char *) "WhiteBias", (char *) NULL},
+ { 0x000F, (char *) "ISOSelection", (char *) NULL},
+ { 0x0010, (char *) "DataDump", (char *) NULL},
+ { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0082, (char *) "LensAdapter", (char *) NULL},
+ { 0x0085, (char *) "FocusDistance", (char *) NULL},
+ { 0x0086, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0088, (char *) "AFFocusPosition", (char *) NULL},
+ { 0x0089, (char *) "ShootingMode", (char *) NULL},
+ { 0x008D, (char *) "ColorMode", (char *) NULL},
+ { 0x008F, (char *) "SceneMode", (char *) NULL},
+ { 0x0092, (char *) "HueAdjustment", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+The type-3 directory is for D-Series cameras such as the D1 and D100.
+see http://www.timelesswanderings.net/equipment/D100/NEF.html
+*/
+static TagInfo
+ exif_nikon_type3_tag_table[] =
+ {
+ { 0x0001, (char *) "FirmwareVersion", (char *) NULL},
+ { 0x0002, (char *) "ISO", (char *) NULL},
+ { 0x0003, (char *) "ColorMode", (char *) NULL},
+ { 0x0004, (char *) "Quality", (char *) NULL},
+ { 0x0005, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0006, (char *) "Sharpening", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x0008, (char *) "FlashSetting", (char *) NULL},
+ { 0x0009, (char *) "FlashMode", (char *) NULL},
+ { 0x000B, (char *) "WhiteBalanceFineTune", (char *) NULL},
+ { 0x000C, (char *) "WhiteBalanceRBCoefficients", (char *) NULL},
+ { 0x000D, (char *) "ProgramShift", (char *) NULL},
+ { 0x000E, (char *) "ExposureDifference", (char *) NULL},
+ { 0x000F, (char *) "ISOSelection", (char *) NULL},
+ { 0x0011, (char *) "ThumbnailIFDOffset", (char *) NULL},
+ { 0x0012, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x0013, (char *) "ISOSetting", (char *) NULL},
+ { 0x0016, (char *) "ImageBoundary", (char *) NULL},
+ { 0x0018, (char *) "FlashExposureBracketValue", (char *) NULL},
+ { 0x0019, (char *) "ExposureBracketValue", (char *) NULL},
+ { 0x001A, (char *) "ImageProcessing", (char *) NULL},
+ { 0x001B, (char *) "CropHiSpeed", (char *) NULL},
+ { 0x001D, (char *) "SerialNumber", (char *) NULL},
+ { 0x001E, (char *) "ColorSpace", (char *) NULL},
+ { 0x0080, (char *) "ImageAdjustment", (char *) NULL},
+ { 0x0081, (char *) "ToneCompensation", (char *) NULL},
+ { 0x0082, (char *) "AuxiliaryLens", (char *) NULL},
+ { 0x0083, (char *) "LensType", (char *) NULL},
+ { 0x0084, (char *) "Lens", (char *) NULL},
+ { 0x0085, (char *) "ManualFocusDistance", (char *) NULL},
+ { 0x0086, (char *) "DigitalZoom", (char *) NULL},
+ { 0x0087, (char *) "FlashMode", (char *) NULL},
+ { 0x0088, (char *) "AFInfo", (char *) NULL},
+ { 0x0089, (char *) "ShootingMode", (char *) NULL},
+ { 0x008A, (char *) "AutoBracketRelease", (char *) NULL},
+ { 0x008B, (char *) "LensFStops", (char *) NULL},
+ { 0x008C, (char *) "NEFCurve1", (char *) NULL},
+ { 0x008D, (char *) "ColorHue", (char *) NULL},
+ { 0x008F, (char *) "SceneMode", (char *) NULL},
+ { 0x0090, (char *) "LightSource", (char *) NULL},
+ { 0x0092, (char *) "HueAdjustment", (char *) NULL},
+ { 0x0094, (char *) "Saturation", (char *) NULL},
+ { 0x0095, (char *) "NoiseReduction", (char *) NULL},
+ { 0x0096, (char *) "NEFCurve2", (char *) NULL},
+ { 0x0099, (char *) "RawImageCenter", (char *) NULL},
+ { 0x009A, (char *) "SensorPixelSize", (char *) NULL},
+ { 0x009C, (char *) "SceneAssist", (char *) NULL},
+ { 0x009E, (char *) "RetouchHistory", (char *) NULL},
+ { 0x00A0, (char *) "SerialNumber2", (char *) NULL},
+ { 0x00A2, (char *) "ImageDataSize", (char *) NULL},
+ { 0x00A5, (char *) "ImageCount", (char *) NULL},
+ { 0x00A6, (char *) "DeletedImageCount", (char *) NULL},
+ { 0x00A7, (char *) "ShutterCount", (char *) NULL},
+ { 0x00A9, (char *) "ImageOptimization", (char *) NULL},
+ { 0x00AA, (char *) "Saturation2", (char *) NULL},
+ { 0x00AB, (char *) "VariProgram", (char *) NULL},
+ { 0x00AC, (char *) "ImageStabilization", (char *) NULL},
+ { 0x00AD, (char *) "AFResponse", (char *) NULL},
+ { 0x00B1, (char *) "HighISONoiseReduction", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0E01, (char *) "NikonCaptureData", (char *) NULL},
+ { 0x0E09, (char *) "NikonCaptureVersion", (char *) NULL},
+ { 0x0E0E, (char *) "NikonCaptureOffsets", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Panasonic maker note
+*/
+static TagInfo
+ exif_panasonic_tag_table[] =
+ {
+ { 0x0001, (char *) "ImageQuality", (char *) NULL},
+ { 0x0002, (char *) "FirmwareVersion", (char *) NULL},
+ { 0x0003, (char *) "WhiteBalance", (char *) NULL},
+ { 0x0007, (char *) "FocusMode", (char *) NULL},
+ { 0x000F, (char *) "SpotMode", (char *) NULL},
+ { 0x001A, (char *) "ImageStabilizer", (char *) NULL},
+ { 0x001C, (char *) "MacroMode", (char *) NULL},
+ { 0x001F, (char *) "ShootingMode", (char *) NULL},
+ { 0x0020, (char *) "Audio", (char *) NULL},
+ { 0x0021, (char *) "DataDump", (char *) NULL},
+ { 0x0023, (char *) "WhiteBalanceBias", (char *) NULL},
+ { 0x0024, (char *) "FlashBias", (char *) NULL},
+ { 0x0025, (char *) "InternalSerialNumber", (char *) NULL},
+ { 0x0028, (char *) "ColorEffect", (char *) NULL},
+ { 0x002A, (char *) "BurstMode", (char *) NULL},
+ { 0x002B, (char *) "SequenceNumber", (char *) NULL},
+ { 0x002C, (char *) "Contrast", (char *) NULL},
+ { 0x002D, (char *) "NoiseReduction", (char *) NULL},
+ { 0x002E, (char *) "SelfTimer", (char *) NULL},
+ { 0x0030, (char *) "Rotation", (char *) NULL},
+ { 0x0032, (char *) "ColorMode", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Pentax (Asahi) maker note
+*/
+static TagInfo
+ exif_asahi_tag_table[] =
+ {
+ { 0x0001, (char *) "Capture Mode", (char *) NULL},
+ { 0x0002, (char *) "Quality Level", (char *) NULL},
+ { 0x0003, (char *) "Focus Mode", (char *) NULL},
+ { 0x0004, (char *) "Flash Mode", (char *) NULL},
+ { 0x0007, (char *) "White Balance", (char *) NULL},
+ { 0x000A, (char *) "Digital Zoom", (char *) NULL},
+ { 0x000B, (char *) "Sharpness", (char *) NULL},
+ { 0x000C, (char *) "Contrast", (char *) NULL},
+ { 0x000D, (char *) "Saturation", (char *) NULL},
+ { 0x0014, (char *) "ISO Speed", (char *) NULL},
+ { 0x0017, (char *) "Color", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x1000, (char *) "Time Zone", (char *) NULL},
+ { 0x1001, (char *) "Daylight Savings", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+static TagInfo
+ exif_pentax_tag_table[] =
+ {
+ { 0x0000, (char *) "PentaxVersion", (char *) NULL},
+ { 0x0001, (char *) "PentaxMode", (char *) NULL},
+ { 0x0002, (char *) "PreviewImageSize", (char *) NULL},
+ { 0x0003, (char *) "PreviewImageLength", (char *) NULL},
+ { 0x0004, (char *) "PreviewImageStart", (char *) NULL},
+ { 0x0005, (char *) "PentaxModelID", (char *) NULL},
+ { 0x0006, (char *) "Date", (char *) NULL},
+ { 0x0007, (char *) "Time", (char *) NULL},
+ { 0x0008, (char *) "Quality", (char *) NULL},
+ { 0x0009, (char *) "PentaxImageSize", (char *) NULL},
+ { 0x000B, (char *) "PictureMode", (char *) NULL},
+ { 0x000C, (char *) "FlashMode", (char *) NULL},
+ { 0x000D, (char *) "FocusMode", (char *) NULL},
+ { 0x000E, (char *) "AFPointSelected", (char *) NULL},
+ { 0x000F, (char *) "AFPointsInFocus", (char *) NULL},
+ { 0x0010, (char *) "FocusPosition", (char *) NULL},
+ { 0x0012, (char *) "ExposureTime", (char *) NULL},
+ { 0x0013, (char *) "FNumber", (char *) NULL},
+ { 0x0014, (char *) "ISO", (char *) NULL},
+ { 0x0016, (char *) "ExposureCompensation", (char *) NULL},
+ { 0x0017, (char *) "MeteringMode", (char *) NULL},
+ { 0x0018, (char *) "AutoBracketing", (char *) NULL},
+ { 0x0019, (char *) "WhiteBalance", (char *) NULL},
+ { 0x001A, (char *) "WhiteBalanceMode", (char *) NULL},
+ { 0x001B, (char *) "BlueBalance", (char *) NULL},
+ { 0x001C, (char *) "RedBalance", (char *) NULL},
+ { 0x001D, (char *) "FocalLength", (char *) NULL},
+ { 0x001E, (char *) "DigitalZoom", (char *) NULL},
+ { 0x001F, (char *) "Saturation", (char *) NULL},
+ { 0x0020, (char *) "Contrast", (char *) NULL},
+ { 0x0021, (char *) "Sharpness", (char *) NULL},
+ { 0x0022, (char *) "WorldTimeLocation", (char *) NULL},
+ { 0x0023, (char *) "HometownCity", (char *) NULL},
+ { 0x0024, (char *) "DestinationCity", (char *) NULL},
+ { 0x0025, (char *) "HometownDST", (char *) NULL},
+ { 0x0026, (char *) "DestinationDST", (char *) NULL},
+ { 0x0027, (char *) "DSPFirmwareVersion", (char *) NULL},
+ { 0x0028, (char *) "CPUFirmwareVersion", (char *) NULL},
+ { 0x0029, (char *) "FrameNumber", (char *) NULL},
+ { 0x002D, (char *) "EffectiveLV", (char *) NULL},
+ { 0x0032, (char *) "ImageProcessing", (char *) NULL},
+ { 0x0033, (char *) "PictureMode", (char *) NULL},
+ { 0x0034, (char *) "DriveMode", (char *) NULL},
+ { 0x0037, (char *) "ColorSpace", (char *) NULL},
+ { 0x0039, (char *) "RawImageSize", (char *) NULL},
+ { 0x003E, (char *) "PreviewImageBorders", (char *) NULL},
+ { 0x003F, (char *) "LensType", (char *) NULL},
+ { 0x0040, (char *) "SensitivityAdjust", (char *) NULL},
+ { 0x0041, (char *) "ImageProcessingCount", (char *) NULL},
+ { 0x0047, (char *) "CameraTemperature", (char *) NULL},
+ { 0x0048, (char *) "AELock", (char *) NULL},
+ { 0x0049, (char *) "NoiseReduction", (char *) NULL},
+ { 0x004D, (char *) "FlashExposureComp", (char *) NULL},
+ { 0x004F, (char *) "ImageTone", (char *) NULL},
+ { 0x0050, (char *) "ColorTemperature", (char *) NULL},
+ { 0x005C, (char *) "ShakeReductionInfo", (char *) NULL},
+ { 0x005D, (char *) "ShutterCount", (char *) NULL},
+ { 0x0069, (char *) "DynamicRangeExpansion", (char *) NULL},
+ { 0x0071, (char *) "HighISONoiseReduction", (char *) NULL},
+ { 0x0072, (char *) "AFAdjustment", (char *) NULL},
+ { 0x0200, (char *) "BlackPoint", (char *) NULL},
+ { 0x0201, (char *) "WhitePoint", (char *) NULL},
+ { 0x0203, (char *) "ColorMatrixA", (char *) NULL},
+ { 0x0204, (char *) "ColorMatrixB", (char *) NULL},
+ { 0x0205, (char *) "CameraSettings", (char *) NULL},
+ { 0x0206, (char *) "AEInfo", (char *) NULL},
+ { 0x0207, (char *) "LensInfo", (char *) NULL},
+ { 0x0208, (char *) "FlashInfo", (char *) NULL},
+ { 0x0209, (char *) "AEMeteringSegments", (char *) NULL},
+ { 0x020A, (char *) "FlashMeteringSegments", (char *) NULL},
+ { 0x020B, (char *) "SlaveFlashMeteringSegments", (char *) NULL},
+ { 0x020D, (char *) "WB_RGGBLevelsDaylight", (char *) NULL},
+ { 0x020E, (char *) "WB_RGGBLevelsShade", (char *) NULL},
+ { 0x020F, (char *) "WB_RGGBLevelsCloudy", (char *) NULL},
+ { 0x0210, (char *) "WB_RGGBLevelsTungsten", (char *) NULL},
+ { 0x0211, (char *) "WB_RGGBLevelsFluorescentD", (char *) NULL},
+ { 0x0212, (char *) "WB_RGGBLevelsFluorescentN", (char *) NULL},
+ { 0x0213, (char *) "WB_RGGBLevelsFluorescentW", (char *) NULL},
+ { 0x0214, (char *) "WB_RGGBLevelsFlash", (char *) NULL},
+ { 0x0215, (char *) "CameraInfo", (char *) NULL},
+ { 0x0216, (char *) "BatteryInfo", (char *) NULL},
+ { 0x021B, (char *) "SaturationInfo", (char *) NULL},
+ { 0x021F, (char *) "AFInfo", (char *) NULL},
+ { 0x0222, (char *) "ColorInfo", (char *) NULL},
+ { 0x0224, (char *) "EVStepInfo", (char *) NULL},
+ { 0x03FE, (char *) "DataDump", (char *) NULL},
+ { 0x0402, (char *) "ToneCurve", (char *) NULL},
+ { 0x0403, (char *) "ToneCurves", (char *) NULL},
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x1000, (char *) "HometownCityCode", (char *) NULL},
+ { 0x1001, (char *) "DestinationCityCode", (char *) NULL},
+ { 0x2000, (char *) "PreviewImageData", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+/**
+Sony maker note
+*/
+static TagInfo
+ exif_sony_tag_table[] =
+ {
+ { 0x0E00, (char *) "PrintIM", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// IPTC tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ iptc_tag_table[] =
+ {
+ // IPTC-NAA IIM version 4
+ { 0x0200 + 0, (char *) "ApplicationRecordVersion", (char *) "Application Record Version"},
+ { 0x0200 + 3, (char *) "ObjectTypeReference", (char *) "Object Type Reference"},
+ { 0x0200 + 4, (char *) "ObjectAttributeReference", (char *) "Object Attribute Reference"},
+ { 0x0200 + 5, (char *) "ObjectName", (char *) "Title"},
+ { 0x0200 + 7, (char *) "EditStatus", (char *) "Edit Status"},
+ { 0x0200 + 8, (char *) "EditorialUpdate", (char *) "Editorial Update"},
+ { 0x0200 + 10, (char *) "Urgency", (char *) "Urgency"},
+ { 0x0200 + 12, (char *) "SubjectReference", (char *) "Subject Reference"},
+ { 0x0200 + 15, (char *) "Category", (char *) "Category"},
+ { 0x0200 + 20, (char *) "SupplementalCategories", (char *) "Supplemental Categories"},
+ { 0x0200 + 22, (char *) "FixtureIdentifier", (char *) "Fixture Identifier"},
+ { 0x0200 + 25, (char *) "Keywords", (char *) "Keywords"},
+ { 0x0200 + 26, (char *) "ContentLocationCode", (char *) "Content Location Code"},
+ { 0x0200 + 27, (char *) "ContentLocationName", (char *) "Content Location Name"},
+ { 0x0200 + 30, (char *) "ReleaseDate", (char *) "Release Date"},
+ { 0x0200 + 35, (char *) "ReleaseTime", (char *) "Release Time"},
+ { 0x0200 + 37, (char *) "ExpirationDate", (char *) "Expiration Date"},
+ { 0x0200 + 38, (char *) "ExpirationTime", (char *) "Expiration Time"},
+ { 0x0200 + 40, (char *) "SpecialInstructions", (char *) "Instructions"},
+ { 0x0200 + 42, (char *) "ActionAdvised", (char *) "Action Advised"},
+ { 0x0200 + 45, (char *) "ReferenceService", (char *) "Reference Service"},
+ { 0x0200 + 47, (char *) "ReferenceDate", (char *) "Reference Date"},
+ { 0x0200 + 50, (char *) "ReferenceNumber", (char *) "Reference Number"},
+ { 0x0200 + 55, (char *) "DateCreated", (char *) "Date Created"},
+ { 0x0200 + 60, (char *) "TimeCreated", (char *) "Time Created"},
+ { 0x0200 + 62, (char *) "DigitalCreationDate", (char *) "Digital Creation Date"},
+ { 0x0200 + 63, (char *) "DigitalCreationTime", (char *) "Digital Creation Time"},
+ { 0x0200 + 65, (char *) "OriginatingProgram", (char *) "Originating Program"},
+ { 0x0200 + 70, (char *) "ProgramVersion", (char *) "Program Version"},
+ { 0x0200 + 75, (char *) "ObjectCycle", (char *) "Object Cycle"},
+ { 0x0200 + 80, (char *) "By-line", (char *) "Author"},
+ { 0x0200 + 85, (char *) "By-lineTitle", (char *) "Author's Position"},
+ { 0x0200 + 90, (char *) "City", (char *) "City"},
+ { 0x0200 + 92, (char *) "SubLocation", (char *) "Sub-Location"},
+ { 0x0200 + 95, (char *) "Province-State", (char *) "State/Province"},
+ { 0x0200 + 100, (char *) "Country-PrimaryLocationCode", (char *) "Country Code"},
+ { 0x0200 + 101, (char *) "Country-PrimaryLocationName", (char *) "Country Name"},
+ { 0x0200 + 103, (char *) "OriginalTransmissionReference", (char *) "Transmission Reference"},
+ { 0x0200 + 105, (char *) "Headline", (char *) "Headline"},
+ { 0x0200 + 110, (char *) "Credit", (char *) "Credit"},
+ { 0x0200 + 115, (char *) "Source", (char *) "Source"},
+ { 0x0200 + 116, (char *) "CopyrightNotice", (char *) "Copyright Notice"},
+ { 0x0200 + 118, (char *) "Contact", (char *) "Contact"},
+ { 0x0200 + 120, (char *) "Caption-Abstract", (char *) "Caption"},
+ { 0x0200 + 122, (char *) "Writer-Editor", (char *) "Caption Writer"},
+ { 0x0200 + 125, (char *) "RasterizedCaption", (char *) "Rasterized Caption"},
+ { 0x0200 + 130, (char *) "ImageType", (char *) "Image Type"},
+ { 0x0200 + 131, (char *) "ImageOrientation", (char *) "Image Orientation"},
+ { 0x0200 + 135, (char *) "LanguageIdentifier", (char *) "Language Identifier"},
+ { 0x0200 + 150, (char *) "AudioType", (char *) "Audio Type"},
+ { 0x0200 + 151, (char *) "AudioSamplingRate", (char *) "Audio Sampling Rate"},
+ { 0x0200 + 152, (char *) "AudioSamplingResolution", (char *) "Audio Sampling Resolution"},
+ { 0x0200 + 153, (char *) "AudioDuration", (char *) "Audio Duration"},
+ { 0x0200 + 154, (char *) "AudioOutcue", (char *) "Audio Outcue"},
+ // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
+ { 0x0200 + 184, (char *) "JobID", (char *) "Job ID"},
+ { 0x0200 + 185, (char *) "MasterDocumentID", (char *) "Master Document ID"},
+ { 0x0200 + 186, (char *) "ShortDocumentID", (char *) "Short Document ID"},
+ { 0x0200 + 187, (char *) "UniqueDocumentID", (char *) "Unique Document ID"},
+ { 0x0200 + 188, (char *) "OwnerID", (char *) "Owner ID"},
+ // IPTC-NAA IIM version 4
+ { 0x0200 + 200, (char *) "ObjectPreviewFileFormat", (char *) "Object Preview File Format"},
+ { 0x0200 + 201, (char *) "ObjectPreviewFileVersion", (char *) "Object Preview File Version"},
+ { 0x0200 + 202, (char *) "ObjectPreviewData", (char *) "Audio Outcue"},
+ // Metadata seen in other softwares (see also http://owl.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html#ApplicationRecord)
+ { 0x0200 + 221, (char *) "Prefs", (char *) "PhotoMechanic preferences"},
+ { 0x0200 + 225, (char *) "ClassifyState", (char *) "Classify State"},
+ { 0x0200 + 228, (char *) "SimilarityIndex", (char *) "Similarity Index"},
+ { 0x0200 + 230, (char *) "DocumentNotes", (char *) "Document Notes"},
+ { 0x0200 + 231, (char *) "DocumentHistory", (char *) "Document History"},
+ { 0x0200 + 232, (char *) "ExifCameraInfo", (char *) "Exif Camera Info"},
+
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// GeoTIFF tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ geotiff_tag_table[] =
+ {
+ { 0x830E, (char *) "GeoPixelScale", (char *) NULL},
+ { 0x8480, (char *) "Intergraph TransformationMatrix", (char *) NULL},
+ { 0x8482, (char *) "GeoTiePoints", (char *) NULL},
+ { 0x85D7, (char *) "JPL Carto IFD offset", (char *) NULL},
+ { 0x85D8, (char *) "GeoTransformationMatrix", (char *) NULL},
+ { 0x87AF, (char *) "GeoKeyDirectory", (char *) NULL},
+ { 0x87B0, (char *) "GeoDoubleParams", (char *) NULL},
+ { 0x87B1, (char *) "GeoASCIIParams", (char *) NULL},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// Animation tags definition
+// --------------------------------------------------------------------------
+
+static TagInfo
+ animation_tag_table[] =
+ {
+ { 0x0001, (char *) "LogicalWidth", (char *) "Logical width"},
+ { 0x0002, (char *) "LogicalHeight", (char *) "Logical height"},
+ { 0x0003, (char *) "GlobalPalette", (char *) "Global Palette"},
+ { 0x0004, (char *) "Loop", (char *) "loop"},
+ { 0x1001, (char *) "FrameLeft", (char *) "Frame left"},
+ { 0x1002, (char *) "FrameTop", (char *) "Frame top"},
+ { 0x1003, (char *) "NoLocalPalette", (char *) "No Local Palette"},
+ { 0x1004, (char *) "Interlaced", (char *) "Interlaced"},
+ { 0x1005, (char *) "FrameTime", (char *) "Frame display time"},
+ { 0x1006, (char *) "DisposalMethod", (char *) "Frame disposal method"},
+ { 0x0000, (char *) NULL, (char *) NULL}
+ };
+
+// --------------------------------------------------------------------------
+// TagLib class definition
+// --------------------------------------------------------------------------
+
+
+/**
+This is where the tag info tables are initialized
+*/
+TagLib::TagLib() {
+ // initialize all known metadata models
+ // ====================================
+
+ // Exif
+ addMetadataModel(TagLib::EXIF_MAIN, exif_exif_tag_table);
+ addMetadataModel(TagLib::EXIF_EXIF, exif_exif_tag_table);
+ addMetadataModel(TagLib::EXIF_GPS, exif_gps_tag_table);
+ addMetadataModel(TagLib::EXIF_INTEROP, exif_interop_tag_table);
+
+ // Exif maker note
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CANON, exif_canon_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE1, exif_casio_type1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_CASIOTYPE2, exif_casio_type2_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_FUJIFILM, exif_fujifilm_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_KYOCERA, exif_kyocera_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_MINOLTA, exif_minolta_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE1, exif_nikon_type1_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE2, exif_nikon_type2_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_NIKONTYPE3, exif_nikon_type3_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_OLYMPUSTYPE1, exif_olympus_type1__tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_PANASONIC, exif_panasonic_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_ASAHI, exif_asahi_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_PENTAX, exif_pentax_tag_table);
+ addMetadataModel(TagLib::EXIF_MAKERNOTE_SONY, exif_sony_tag_table);
+
+ // IPTC/NAA
+ addMetadataModel(TagLib::IPTC, iptc_tag_table);
+
+ // GeoTIFF
+ addMetadataModel(TagLib::GEOTIFF, geotiff_tag_table);
+
+ // Animation
+ addMetadataModel(TagLib::ANIMATION, animation_tag_table);
+}
+
+BOOL TagLib::addMetadataModel(MDMODEL md_model, TagInfo *tag_table) {
+ // check that the model doesn't already exist
+ TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
+
+ if((info_map == NULL) && (tag_table != NULL)) {
+ // add the tag description table
+ TAGINFO *info_map = new TAGINFO();
+ for(int i = 0; ; i++) {
+ if((tag_table[i].tag == 0) && (tag_table[i].fieldname == NULL))
+ break;
+ (*info_map)[tag_table[i].tag] = &tag_table[i];
+ }
+
+ // add the metadata model
+ _table_map[md_model] = info_map;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+TagLib::~TagLib() {
+ // delete metadata models
+ for(TABLEMAP::iterator i = _table_map.begin(); i != _table_map.end(); i++) {
+ TAGINFO *info_map = (*i).second;
+ delete info_map;
+ }
+}
+
+
+TagLib&
+TagLib::instance() {
+ static TagLib s;
+ return s;
+}
+
+const TagInfo*
+TagLib::getTagInfo(MDMODEL md_model, WORD tagID) {
+ TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
+
+ if(info_map != NULL) {
+ return (*info_map)[tagID];
+ }
+
+ return NULL;
+}
+
+const char*
+TagLib::getTagFieldName(MDMODEL md_model, WORD tagID, char *defaultKey) {
+
+ const TagInfo *info = getTagInfo(md_model, tagID);
+ if(NULL == info) {
+ if(defaultKey != NULL) {
+ sprintf(defaultKey, "Tag 0x%04X", tagID);
+ return &defaultKey[0];
+ } else {
+ return NULL;
+ }
+ }
+
+ return info->fieldname;
+}
+
+const char*
+TagLib::getTagDescription(MDMODEL md_model, WORD tagID) {
+
+ const TagInfo *info = getTagInfo(md_model, tagID);
+ if(info) {
+ return info->description;
+ }
+
+ return NULL;
+}
+
+int TagLib::getTagID(MDMODEL md_model, const char *key) {
+ TAGINFO *info_map = (TAGINFO*)_table_map[md_model];
+ if(info_map != NULL) {
+ for(TAGINFO::iterator i = info_map->begin(); i != info_map->end(); i++) {
+ const TagInfo *info = (*i).second;
+ if(info && (strcmp(info->fieldname, key) == 0)) {
+ return (int)info->tag;
+ }
+ }
+ }
+
+ return -1;
+}
+
+FREE_IMAGE_MDMODEL
+TagLib::getFreeImageModel(MDMODEL model) {
+ switch(model) {
+ case EXIF_MAIN:
+ return FIMD_EXIF_MAIN;
+
+ case EXIF_EXIF:
+ return FIMD_EXIF_EXIF;
+
+ case EXIF_GPS:
+ return FIMD_EXIF_GPS;
+
+ case EXIF_INTEROP:
+ return FIMD_EXIF_INTEROP;
+
+ case EXIF_MAKERNOTE_CANON:
+ case EXIF_MAKERNOTE_CASIOTYPE1:
+ case EXIF_MAKERNOTE_CASIOTYPE2:
+ case EXIF_MAKERNOTE_FUJIFILM:
+ case EXIF_MAKERNOTE_KYOCERA:
+ case EXIF_MAKERNOTE_MINOLTA:
+ case EXIF_MAKERNOTE_NIKONTYPE1:
+ case EXIF_MAKERNOTE_NIKONTYPE2:
+ case EXIF_MAKERNOTE_NIKONTYPE3:
+ case EXIF_MAKERNOTE_OLYMPUSTYPE1:
+ case EXIF_MAKERNOTE_PANASONIC:
+ case EXIF_MAKERNOTE_ASAHI:
+ case EXIF_MAKERNOTE_PENTAX:
+ case EXIF_MAKERNOTE_SONY:
+ return FIMD_EXIF_MAKERNOTE;
+
+ case IPTC:
+ return FIMD_IPTC;
+
+ case GEOTIFF:
+ return FIMD_GEOTIFF;
+
+ case ANIMATION:
+ return FIMD_ANIMATION;
+ }
+
+ return FIMD_NODATA;
+}
+
diff --git a/Source/Metadata/XTIFF.cpp b/Source/Metadata/XTIFF.cpp
new file mode 100644
index 0000000..27b79e3
--- /dev/null
+++ b/Source/Metadata/XTIFF.cpp
@@ -0,0 +1,404 @@
+// ==========================================================
+// Metadata functions implementation
+// Extended TIFF Directory GEO Tag Support
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+// - Thorsten Radde (support@IdealSoftware.com)
+//
+// Based on the LibTIFF xtiffio sample and on LibGeoTIFF
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#include "../LibTIFF/tiffiop.h"
+
+#include "FreeImage.h"
+#include "Utilities.h"
+#include "FreeImageTag.h"
+#include "FIRational.h"
+
+// ----------------------------------------------------------
+// Extended TIFF Directory GEO Tag Support
+// ----------------------------------------------------------
+
+/**
+ Tiff info structure.
+ Entry format:
+ { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM, OkToChange, PassDirCountOnSet, AsciiName }
+
+ For ReadCount, WriteCount, -1 = unknown.
+*/
+static const TIFFFieldInfo xtiffFieldInfo[] = {
+ { TIFFTAG_GEOPIXELSCALE, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoPixelScale" },
+ { TIFFTAG_INTERGRAPH_MATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "Intergraph TransformationMatrix" },
+ { TIFFTAG_GEOTRANSMATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoTransformationMatrix" },
+ { TIFFTAG_GEOTIEPOINTS, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoTiePoints" },
+ { TIFFTAG_GEOKEYDIRECTORY,-1,-1, TIFF_SHORT, FIELD_CUSTOM, TRUE, TRUE, "GeoKeyDirectory" },
+ { TIFFTAG_GEODOUBLEPARAMS, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoDoubleParams" },
+ { TIFFTAG_GEOASCIIPARAMS, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, "GeoASCIIParams" },
+ { TIFFTAG_JPL_CARTO_IFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, TRUE, TRUE, "JPL Carto IFD offset" } /** Don't use this! **/
+};
+
+static void
+_XTIFFLocalDefaultDirectory(TIFF *tif) {
+ int tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
+ // Install the extended Tag field info
+ TIFFMergeFieldInfo(tif, xtiffFieldInfo, tag_size);
+}
+
+static TIFFExtendProc _ParentExtender;
+
+/**
+This is the callback procedure, and is
+called by the DefaultDirectory method
+every time a new TIFF directory is opened.
+*/
+static void
+_XTIFFDefaultDirectory(TIFF *tif) {
+ // set up our own defaults
+ _XTIFFLocalDefaultDirectory(tif);
+
+ /*
+ Since an XTIFF client module may have overridden
+ the default directory method, we call it now to
+ allow it to set up the rest of its own methods.
+ */
+ if (_ParentExtender)
+ (*_ParentExtender)(tif);
+}
+
+/**
+XTIFF Initializer -- sets up the callback procedure for the TIFF module
+*/
+void
+XTIFFInitialize(void) {
+ static int first_time = 1;
+
+ if (! first_time) return; /* Been there. Done that. */
+ first_time = 0;
+
+ // Grab the inherited method and install
+ _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
+}
+
+// ----------------------------------------------------------
+// GeoTIFF tag reading / writing
+// ----------------------------------------------------------
+
+void
+tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
+ char defaultKey[16];
+
+ size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
+
+ TagLib& tag_lib = TagLib::instance();
+
+ for(unsigned i = 0; i < tag_size; i++) {
+
+ const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
+
+ if(fieldInfo->field_type == TIFF_ASCII) {
+ char *params = NULL;
+
+ if(TIFFGetField(tif, fieldInfo->field_tag, &params)) {
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(!tag) return;
+
+ WORD tag_id = (WORD)fieldInfo->field_tag;
+
+ FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)fieldInfo->field_type);
+ FreeImage_SetTagID(tag, tag_id);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
+ FreeImage_SetTagLength(tag, (DWORD)strlen(params) + 1);
+ FreeImage_SetTagCount(tag, FreeImage_GetTagLength(tag));
+ FreeImage_SetTagValue(tag, params);
+ FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
+
+ // delete the tag
+ FreeImage_DeleteTag(tag);
+ }
+ } else {
+ short tag_count = 0;
+ void* data = NULL;
+
+ if(TIFFGetField(tif, fieldInfo->field_tag, &tag_count, &data)) {
+ // create a tag
+ FITAG *tag = FreeImage_CreateTag();
+ if(!tag) return;
+
+ WORD tag_id = (WORD)fieldInfo->field_tag;
+ FREE_IMAGE_MDTYPE tag_type = (FREE_IMAGE_MDTYPE)fieldInfo->field_type;
+
+ FreeImage_SetTagType(tag, tag_type);
+ FreeImage_SetTagID(tag, tag_id);
+ FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
+ FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
+ FreeImage_SetTagLength(tag, FreeImage_TagDataWidth((WORD)tag_type) * tag_count);
+ FreeImage_SetTagCount(tag, tag_count);
+ FreeImage_SetTagValue(tag, data);
+ FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
+
+ // delete the tag
+ FreeImage_DeleteTag(tag);
+ }
+ }
+ } // for(tag_size)
+}
+
+void
+tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
+ char defaultKey[16];
+
+ if(FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib) == 0) {
+ return;
+ }
+
+ size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
+
+ TagLib& tag_lib = TagLib::instance();
+
+ for(unsigned i = 0; i < tag_size; i++) {
+ const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
+
+ FITAG *tag = NULL;
+ const char *key = tag_lib.getTagFieldName(TagLib::GEOTIFF, (WORD)fieldInfo->field_tag, defaultKey);
+
+ if(FreeImage_GetMetadata(FIMD_GEOTIFF, dib, key, &tag)) {
+ if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
+ TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagValue(tag));
+ } else {
+ TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------
+// EXIF tag reading
+// ----------------------------------------------------------
+
+BOOL tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
+ int i;
+ short count;
+
+ TagLib& tagLib = TagLib::instance();
+
+ TIFFDirectory *td = &tif->tif_dir;
+
+ count = (short) TIFFGetTagListCount(tif);
+ for(i = 0; i < count; i++) {
+ ttag_t tag = TIFFGetTagListEntry(tif, i);
+ const TIFFFieldInfo *fip;
+ uint32 value_count;
+ int mem_alloc = 0;
+ void *raw_data;
+
+ if(tag == TIFFTAG_EXIFIFD) continue;
+
+ // get the tag key - use NULL to avoid reading GeoTIFF tags
+ const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL);
+ if(key == NULL) continue;
+
+ fip = TIFFFieldWithTag(tif, tag);
+ if(fip == NULL) continue;
+
+ if(fip->field_passcount) {
+ if (fip->field_readcount != TIFF_VARIABLE2) {
+ // assume TIFF_VARIABLE
+ uint16 value_count16;
+ if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) continue;
+ value_count = value_count16;
+ } else {
+ if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) continue;
+ }
+ } else {
+ if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) {
+ value_count = 1;
+ } else if (fip->field_readcount == TIFF_SPP) {
+ value_count = td->td_samplesperpixel;
+ } else {
+ value_count = fip->field_readcount;
+ }
+ if (fip->field_type == TIFF_ASCII
+ || fip->field_readcount == TIFF_VARIABLE
+ || fip->field_readcount == TIFF_VARIABLE2
+ || fip->field_readcount == TIFF_SPP
+ || value_count > 1) {
+ if(TIFFGetField(tif, tag, &raw_data) != 1) continue;
+ } else {
+ raw_data = _TIFFmalloc(_TIFFDataSize(fip->field_type) * value_count);
+ mem_alloc = 1;
+ if(TIFFGetField(tif, tag, raw_data) != 1) {
+ _TIFFfree(raw_data);
+ continue;
+ }
+ }
+ }
+
+ // create a tag
+ FITAG *fitag = FreeImage_CreateTag();
+ if(!fitag) {
+ if(mem_alloc)
+ _TIFFfree(raw_data);
+ return FALSE;
+ }
+
+ FreeImage_SetTagID(fitag, (WORD)tag);
+ FreeImage_SetTagKey(fitag, key);
+
+ switch(fip->field_type) {
+ case TIFF_BYTE:
+ FreeImage_SetTagType(fitag, FIDT_BYTE);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_UNDEFINED:
+ FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_SBYTE:
+ FreeImage_SetTagType(fitag, FIDT_SBYTE);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_SHORT:
+ FreeImage_SetTagType(fitag, FIDT_SHORT);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_SSHORT:
+ FreeImage_SetTagType(fitag, FIDT_SSHORT);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_LONG:
+ FreeImage_SetTagType(fitag, FIDT_LONG);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_IFD:
+ FreeImage_SetTagType(fitag, FIDT_IFD);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_SLONG:
+ FreeImage_SetTagType(fitag, FIDT_SLONG);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_RATIONAL:
+ {
+ // LibTIFF converts rational to floats : reconvert floats to rationals
+ DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
+ for(uint32 i = 0; i < value_count; i++) {
+ float *fv = (float*)raw_data;
+ FIRational rational(fv[i]);
+ rvalue[2*i] = rational.getNumerator();
+ rvalue[2*i+1] = rational.getDenominator();
+ }
+ FreeImage_SetTagType(fitag, FIDT_RATIONAL);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, rvalue);
+ free(rvalue);
+ }
+ break;
+
+ case TIFF_SRATIONAL:
+ {
+ // LibTIFF converts rational to floats : reconvert floats to rationals
+ LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
+ for(uint32 i = 0; i < value_count; i++) {
+ float *fv = (float*)raw_data;
+ FIRational rational(fv[i]);
+ rvalue[2*i] = rational.getNumerator();
+ rvalue[2*i+1] = rational.getDenominator();
+ }
+ FreeImage_SetTagType(fitag, FIDT_RATIONAL);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, rvalue);
+ free(rvalue);
+ }
+ break;
+
+ case TIFF_FLOAT:
+ FreeImage_SetTagType(fitag, FIDT_FLOAT);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ case TIFF_DOUBLE:
+ FreeImage_SetTagType(fitag, FIDT_DOUBLE);
+ FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
+ FreeImage_SetTagCount(fitag, value_count);
+ FreeImage_SetTagValue(fitag, raw_data);
+ break;
+
+ default:
+ {
+ size_t length = strlen((char*)raw_data) + 1;
+ FreeImage_SetTagType(fitag, FIDT_ASCII);
+ FreeImage_SetTagLength(fitag, (DWORD)length);
+ FreeImage_SetTagCount(fitag, (DWORD)length);
+ FreeImage_SetTagValue(fitag, raw_data);
+ }
+ break;
+ }
+
+ const char *description = tagLib.getTagDescription(md_model, (WORD)tag);
+ if(description) {
+ FreeImage_SetTagDescription(fitag, description);
+ }
+ // store the tag
+ FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);
+
+ // destroy the tag
+ FreeImage_DeleteTag(fitag);
+
+ if(mem_alloc)
+ _TIFFfree(raw_data);
+ }
+
+ return TRUE;
+
+}
+
+
diff --git a/Source/OpenEXR/Copyrights/AUTHORS b/Source/OpenEXR/Copyrights/AUTHORS
new file mode 100644
index 0000000..2926b13
--- /dev/null
+++ b/Source/OpenEXR/Copyrights/AUTHORS
@@ -0,0 +1,41 @@
+Developers:
+-----------
+
+Florian Kainz <kainz@ilm.com>
+Rod Bogart <rgb@ilm.com>
+Drew Hess <dhess@ilm.com>
+Paul Schneider <paultschneider@mac.com>
+Bill Anderson <wja@ilm.com>
+Wojciech Jarosz <wjarosz@ucsd.edu>
+Andrew Kunz <akunz@ilm.com>
+
+Contributors:
+-------------
+
+Simon Green <SGreen@nvidia.com>
+Rito Trevino <etrevino@ilm.com>
+Josh Pines
+Christian Rouet
+Rodrigo Damazio <rdamazio@lsi.usp.br>
+Greg Ward <gward@lmi.net>
+Joseph Goldstone <joseph@lp.com>
+Loren Carpenter, Pixar Animation Studios
+
+Win32 build system:
+-------------------
+
+Nick Porcino <NPorcino@lucasarts.com>
+Kimball Thurston
+
+Win32 port contributors:
+------------------------
+
+Dustin Graves <dgraves@computer.org>
+Jukka Liimatta <jukka.liimatta@twilight3d.com>
+Baumann Konstantin <Konstantin.Baumann@hpi.uni-potsdam.de>
+Daniel Koch <daniel@eyeonline.com>
+E. Scott Larsen <larsene@cs.unc.edu>
+stephan mantler <step@acm.org>
+Andreas Kahler <AKahler@nxn-software.com>
+Frank Jargstorff <fjargstorff@nvidia.com>
+Lutz Latta
diff --git a/Source/OpenEXR/Copyrights/COPYING b/Source/OpenEXR/Copyrights/COPYING
new file mode 100644
index 0000000..6372750
--- /dev/null
+++ b/Source/OpenEXR/Copyrights/COPYING
@@ -0,0 +1,34 @@
+Copyright (c) 2006, Industrial Light & Magic, a division of Lucasfilm
+Entertainment Company Ltd. Portions contributed and copyright held by
+others as indicated. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with
+ the distribution.
+
+ * Neither the name of Industrial Light & Magic nor the names of
+ any other contributors to this software may be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Source/OpenEXR/Copyrights/ChangeLog b/Source/OpenEXR/Copyrights/ChangeLog
new file mode 100644
index 0000000..f2fea08
--- /dev/null
+++ b/Source/OpenEXR/Copyrights/ChangeLog
@@ -0,0 +1,581 @@
+Version 1.6.1:
+ * Removed Windows .suo files from distribution.
+ (Eric Wimmer)
+ * Bug fix: crashes, memory leaks and file descriptor leaks
+ when reading damaged image files (some reported by Apple,
+ others found by running IlmImfFuzzTest).
+ (Florian Kainz)
+ * Added new IlmImfFuzzTest program to test how resilient the
+ IlmImf library is with respect broken input files: the program
+ first damages OpenEXR files by partially overwriting them with
+ random data; then it tries to read the damaged files. If all
+ goes well, the program doesn't crash.
+ (Florian Kainz)
+
+Version 1.6.0:
+ * Bumped DSO version number to 6.0
+ (Florian Kainz)
+ * Added new standard attributes related to color rendering with
+ CTL (Color Transformation Language): renderingTransform,
+ lookModTransform and adoptedNeutral.
+ (Florian Kainz)
+ * Bug fix: for pixels with luminance near HALF_MIN, conversion
+ from RGB to luminance/chroma produces NaNs and infinities
+ (Florian Kainz)
+ * Bug fix: excessive desaturation of small details with certain
+ colors after repeatedly loading and saving luminance/chroma
+ encoded images with B44 compression.
+ (Florian Kainz)
+ * Added B44A compression, a minor variation of B44: in most cases,
+ the compression ratio is 2.28:1, the same as with B44, but in
+ uniform image areas where all pixels have the same value, the
+ compression ratio increases to 10.66:1. Uniform areas occur, for
+ example, in an image's alpha channel, which typically contains
+ large patches that are solid black or white, or in computer-
+ generated images with a black background.
+ (Florian Kainz)
+ * Added flag to configure.ac to enable or disable use of large
+ auto arrays in the IlmImf library. Default is "enable" for
+ Linux, "disable" for everything else.
+ (Darby Johnston, Florian Kainz)
+ * corrected version number on dso's (libtool) - now 5.0
+ * Separated ILMBASE_LDFLAGS and ILMBASE_LIBS so that test programs
+ can link with static libraries properly
+ * eliminated some warning messages during install
+ (Andrew Kunz)
+
+Version 1.5.0:
+ * reorganized packaging of OpenEXR libraries to facilitate
+ integration with CTL. Now this library depends on the library
+ IlmBase. Some functionality has been moved into OpenEXR_Viewers,
+ which depends on two other libraries, CTL and OpenEXR_CTL.
+ Note: previously there were separate releases of
+ OpenEXR-related plugins for Renderman, Shake and Photoshop.
+ OpenEXR is supported natively by Rendermand and Photoshop, so
+ these plugins will not be supported for this or future
+ versions of OpenEXR.
+ (Andrew Kunz)
+ * New build scripts for Linux/Unix
+ (Andrew Kunz)
+ * New Windows project files and build scripts
+ (Kimball Thurston)
+ * float-to-half conversion now preserves the sign of float zeroes
+ and of floats that are so small that they become half zeroes.
+ (Florian Kainz)
+ * Bug fix: Imath::Frustum<T>::planes() returns incorrect planes
+ if the frustum is orthogonal.
+ (Philip Hubbard)
+ * added new framesPerSecond optional standard attribute
+ (Florian Kainz)
+ * Imath cleanup:
+ - Rewrote function Imath::Quat<T>::setRotation() to make it
+ numerically more accurate, added confidence tests
+ - Rewrote function Imath::Quat<T>::slerp() using Don Hatch's
+ method, which is numerically more accurate, added confidence
+ tests.
+ - Rewrote functions Imath::closestPoints(), Imath::intersect(),
+ added confidence tests.
+ - Removed broken function Imath::nearestPointOnTriangle().
+ - Rewrote Imath::drand48(), Imath::lrand48(), etc. to make
+ them functionally identical with the Unix/Linux versions
+ of drand48(), lrand48() and friends.
+ - Replaced redundant definitions of Int64 in Imath and IlmImf
+ with a single definition in ImathInt64.h.
+ (Florian Kainz)
+ * exrdisplay: if the file's and the display's RGB chromaticities
+ differ, the pixels RGB values are transformed from the file's
+ to the display's RGB space.
+ (Florian Kainz)
+ * Added new lossy B44 compression method. HALF channels are
+ compressed with a fixed ratio of 2.28:1. UINT and FLOAT
+ channels are stored verbatim, without compression.
+ (Florian Kainz)
+
+Version 1.4.0a:
+ * Fixed the ReleaseDLL targets for Visual Studio 2003.
+ (Barnaby Robson)
+
+Version 1.4.0:
+ * Production release.
+ * Bug Fix: calling setFrameBuffer() for every scan line
+ while reading a tiled file through the scan line API
+ returns bad pixel data. (Paul Schneider, Florian Kainz)
+
+Version 1.3.1:
+ * Fixed the ReleaseDLL targets for Visual Studio 2005.
+ (Nick Porcino, Drew Hess)
+ * Fixes/enhancements for createDLL.
+ (Nick Porcino)
+
+Version 1.3.0:
+ * Removed openexr.spec file, it's out of date and broken to
+ boot.
+ (Drew Hess)
+ * Support for Visual Studio 2005.
+ (Drew Hess, Nick Porcino)
+ * When compiling against OpenEXR headers on Windows, you
+ no longer need to define any HAVE_* or PLATFORM_*
+ macros in your projects. If you are using any OpenEXR
+ DLLs, however, you must define OPENEXR_DLL in your
+ project's preprocessor directives.
+ (Drew Hess)
+ * Many fixes to the Windows VC7 build system.
+ (Drew Hess, Nick Porcino)
+ * Support for building universal binaries on OS X 10.4.
+ (Drew Hess, Paul Schneider)
+ * Minor configure.ac fix to accomodate OS X's automake.
+ (Drew Hess)
+ * Removed CPU-specific optimizations from configure.ac,
+ autoconf's guess at the CPU type isn't very useful,
+ anyway. Closes #13429.
+ (Drew Hess)
+ * Fixed quoting for tests in configure.ac. Closes #13428.
+ (Drew Hess)
+ * Use host specification instead of target in configure.ac.
+ Closes #13427.
+ (Drew Hess)
+ * Fix use of AC_ARG_ENABLE in configure.ac. Closes
+ #13426.
+ (Drew Hess)
+ * Removed workaround for OS X istream::read bug.
+ (Drew Hess)
+ * Added pthread support to OpenEXR pkg-config file.
+ (Drew Hess)
+ * Added -no-undefined to LDFLAGS and required libs to LIBADD
+ for library projects with other library dependencies, per
+ Rex Dieter's patch.
+ (Drew Hess)
+ * HAVE_* macros are now defined in the OpenEXRConfig.h header
+ file instead of via compiler flags. There are a handful of
+ public headers which rely on the value of these macros,
+ and projects including these headers have previously needed
+ to define the same macros and values as used by OpenEXR's
+ 'configure', which is bad form. Now 'configure' writes these
+ values to the OpenEXRConfig.h header file, which is included
+ by any OpenEXR source files that need these macros. This
+ method of specifying HAVE_* macros guarantees that projects
+ will get the proper settings without needing to add compile-
+ time flags to accomodate OpenEXR. Note that this isn't
+ implemented properly for Windows yet.
+ (Drew Hess)
+ * Platform cleanups:
+ - No more support for IRIX or OSF1.
+ - No more explicit support for SunOS, because we have no way to
+ verify that it's working. I suspect that newish versions of
+ SunOS will just work out of the box, but let me know if not.
+ - No more PLATFORM_* macros (vestiges of the ILM internal build
+ system). PLATFORM_DARWIN_PPC is replaced by HAVE_DARWIN.
+ PLATFORM_REDHAT_IA32 (which was only used in IlmImfTest) is
+ replaced by HAVE_LINUX_PROCFS.
+ - OS X 10.4, which is the minimum version we're going to support
+ with this version, appears to have support for nrand48 and friends,
+ so no need to use the Imath-supplied version of them anymore.
+ (Drew Hess)
+ * No more PLATFORM_WINDOWS or PLATFORM_WIN32, replace with
+ proper standard Windows macros. (Drew Hess)
+ * Remove support for gcc 2.95, no longer supported. (Drew Hess)
+ * Eliminate HAVE_IOS_BASE macro, OpenEXR now requires support for
+ ios_base. (Drew Hess)
+ * Eliminate HAVE_STL_LIMITS macro, OpenEXR now requires the ISO C++
+ <limits> header. (Drew Hess)
+ * Use double quote-style include dirctives for OpenEXR
+ includes. (Drew Hess)
+ * Added a document that gives an overview of the on-disk
+ layout of OpenEXR files (Florian Kainz)
+ * Added sections on layers and on memory-mapped file input
+ to the documentation. (Florian Kainz)
+ * Bug fix: reading an incomplete file causes a deadlock while
+ waiting on a semaphore. (Florian Kainz)
+ * Updated documentation (ReadingAndWritingImageFiles.sxw) and
+ sample code (IlmImfExamples):
+ Added a section about multi-threading, updated section on
+ thread-safety, changed documentation and sample code to use
+ readTiles()/writeTiles() instead of readTile()/writeTile()
+ where possible, mentioned that environment maps contain
+ redundant pixels, updated section on testing if a file is
+ an OpenEXR file.
+ (Florian Kainz)
+ * Multi-threading bug fixes (exceptions could be thrown
+ multiple times, some operations were not thread safe),
+ updated some comments, added comments, more multithreaded
+ testing.
+ (Florian Kainz)
+ * Added multi-threading support: multiple threads
+ cooperate to read or write a single OpenEXR file.
+ (Wojciech Jarosz)
+ * Added operator== and operator!= to Imath::Frustum.
+ (Andre Mazzone)
+ * Bug fix: Reading a PIZ-compressed file with an invalid
+ Huffman code table caused crashes by indexing off the
+ end of an array.
+ (Florian Kainz)
+
+Version 1.2.2:
+ * Updated README to remove option for building with Visual C++ 6.0.
+ (Drew Hess)
+ * Some older versions of gcc don't support a full iomanip
+ implemenation; check for this during configuration.
+ (Drew Hess)
+ * Install PDF versions of documentation, remove old/out-of-date
+ HTML documentation. (Florian Kainz)
+ * Removed vc/vc6 directory; Visual C++ 6.0 is no longer
+ supported. (Drew Hess)
+ * Updated README.win32 with details of new build system.
+ (Florian Kainz, Drew Hess)
+ * New build system for Windows / Visual C++ 7 builds both
+ static libraries and DLLs.
+ (Nick Porcino)
+ * Removed Imath::TMatrix<T> and related classes, which are not
+ used anywhere in OpenEXR.
+ (Florian Kainz)
+ * Added minimal support for "image layers" to class Imf::ChannelList
+ (Florian Kainz)
+ * Added new isComplete() method to InputFile, TiledInputFile
+ etc., that checks if a file is complete or if any pixels
+ are missing (for example, because writing the file was
+ aborted prematurely).
+ (Florian Kainz)
+ * Exposed staticInitialize() function in ImfHeader.h in order
+ to allow thread-safe library initialization in multithreaded
+ programs.
+ (Florian Kainz)
+ * Added a new "time code" attribute
+ (Florian Kainz)
+ * exrmaketiled: when a MIPMAP_LEVELS or RIPMAP_LEVELS image
+ is produced, low-pass filtering takes samples outside the
+ image's data window. This requires extrapolating the image.
+ The user can now specify how the image is extrapolated
+ horizontally and vertically (image is surrounded by black /
+ outermost row of pixels repeats / entire image repeats /
+ entire image repeats, every other copy is a mirror image).
+ exrdisplay: added option to swap the top and botton half,
+ and the left and right half of an image, so that the image's
+ four corners end up in the center. This is useful for checking
+ the seams of wrap-around texture map images.
+ IlmImf library: Added new "wrapmodes" standard attribute
+ to indicate the extrapolation mode for MIPMAP_LEVELS and
+ RIPMAP_LEVELS images.
+ (Florian Kainz)
+ * Added a new "key code" attribute to identify motion picture
+ film frames.
+ (Florian Kainz)
+ * Removed #include <Iex.h> from ImfAttribute.h, ImfHeader.h
+ and ImfXdr.h so that including header files such as
+ ImfInputFile.h no longer defines ASSERT and THROW macros,
+ which may conflict with similar macros defined by
+ application programs.
+ (Florian Kainz)
+ * Converted HTML documentation to OpenOffice format to
+ make maintaining the documents easier:
+ api.html -> ReadingAndWritingImageFiles.sxw
+ details.html -> TechnicalIntroduction.sxw
+ (Florian Kainz)
+
+Version 1.2.1:
+ * exrenvmap and exrmaketiled use slightly less memory
+ (Florian Kainz)
+ * Added functions to IlmImf for quickly testing if a file
+ is an OpenEXR file, and whether the file is scan-line
+ based or tiled. (Florian Kainz)
+ * Added preview image examples to IlmImfExamples. Added
+ description of preview images and environment maps to
+ docs/api.html (Florian Kainz)
+ * Bug fix: PXR24 compression did not work properly for channels
+ with ySampling != 1.
+ (Florian Kainz)
+ * Made template <class T> become template <class S, class T> for
+ the transform(ObjectS, ObjectT) methods. This was done to allow
+ for differing templated objects to be passed in e.g. say a
+ Box<Vec3<S>> and a Matrix44<T>, where S=float and T=double.
+ (Jeff Yost, Arkell Rasiah)
+ * New method Matrix44::setTheMatrix(). Used for assigning a
+ M44f to a M44d. (Jeff Yost, Arkell Rasiah)
+ * Added convenience Color typedefs for half versions of Color3
+ and Color4. Note the Makefile.am for both Imath and ImathTest
+ have been updated with -I and/or -L pathing to Half.
+ (Max Chen, Arkell Rasiah)
+ * Methods equalWithAbsError() and equalWithRelError() are now
+ declared as const. (Colette Mullenhoff, Arkell Rasiah)
+ * Fixes for gcc34. Mainly typename/template/using/this syntax
+ correctness changes. (Nick Ramussen, Arkell Rasiah)
+ * Added Custom low-level file I/O examples to IlmImfExamples
+ and to the docs/api.html document. (Florian Kainz)
+ * Eliminated most warnings messages when OpenEXR is compiled
+ with Visual C++. The OpenEXR code uses lots of (intentional
+ and unintended) implicit type conversions. By default, Visual
+ C++ warns about almost all of them. Most implicit conversions
+ have been removed from the .h files, so that including them
+ should not generate warnings even at warning level 3. Most
+ .cpp files are now compiled with warning level 1.
+ (Florian Kainz)
+
+Version 1.2.0:
+ * Production-ready release.
+ * Disable long double warnings on OS X. (Drew Hess)
+ * Add new source files to VC7 IlmImfDll target. (Drew Hess)
+ * Iex: change the way that APPEND_EXC and REPLACE_EXC modify
+ their what() string to work around an issue with Visual C++
+ 7.1. (Florian Kainz, Nick Porcino)
+ * Bumped OpenEXR version to 1.2 and .so versions to 2.0.0 in
+ preparation for the release. (Drew Hess)
+ * Imath: fixed ImathTMatrix.h to work with gcc 3.4. (Drew Hess)
+ * Another quoting fix in openexr.m4. (Drew Hess)
+ * Quoting fix in acinclude.m4 for automake 1.8. (Brad Hards)
+ * Imath: put inline at beginning of declaration in ImathMatrix.h
+ to fix a warning. (Ken McGaugh)
+ * Imath: made Vec equalWith*Error () methods const.
+ * Cleaned up compile-time Win32 support. (Florian Kainz)
+ * Bug fix: Reading a particular broken PIZ-compressed file
+ caused crashes by indexing off the end of an array.
+ (Florian Kainz)
+
+Version 1.1.1:
+ * Half: operator= and variants now return by reference rather
+ than by value. This brings half into conformance with
+ built-in types. (Drew Hess)
+ * Half: remove copy constructor, let compiler supply its
+ own. This improves performance up to 25% on some
+ expressions using half. (Drew Hess)
+ * configure: don't try to be fancy with CXXFLAGS, just use
+ what the user supplies or let configure choose a sensible
+ default if CXXFLAGS is not defined.
+ * IlmImf: fixed a bug in reading scanline files on big-endian
+ architectures. (Drew Hess)
+ * exrmaketiled: Added an option to select compression type.
+ (Florian Kainz)
+ * exrenvmap: Added an option to select compression type.
+ (Florian Kainz)
+ * exrdisplay: Added some new command-line options. (Florian Kainz)
+ * IlmImf: Added Pixar's new "slightly lossy" image compression
+ method. The new method, named PXR24, preserves HALF and
+ UINT data without loss, but FLOAT pixels are converted to
+ a 24-bit representation. PXR24 appears to compress
+ FLOAT depth buffers very well without losing much accuracy.
+ (Loren Carpenter, Florian Kainz)
+ * Changed top-level LICENSE file to allow for other copyright
+ holders for individual files.
+ * IlmImf: TILED FILE FORMAT CHANGE. TiledOutputFile was
+ incorrectly interleaving channels and scanlines before
+ passing pixel data to a compressor. The lossless compressors
+ still work, but lossy compressors do not. Fix the bug by
+ interleaving channels and scanlines in tiled files in the
+ same way as ScanLineOutputFile does. Programs compiled with
+ the new version of IlmImf cannot read tiled images produced
+ with version 1.1.0. (Florian Kainz)
+ * IlmImf: ImfXdr.h fix for 64-bit architectures. (Florian Kainz)
+ * IlmImf: OpenEXR now supports YCA (luminance/chroma/alpha)
+ images with subsampled chroma channels. When an image
+ is written with the RGBA convenience interface, selecting
+ WRITE_YCA instead of WRITE_RGBA causes the library to
+ convert the pixels to YCA format. If WRITE_Y is selected,
+ only luminance is stored in the file (for black and white
+ images). When an image file is read with the RGBA convenience
+ interface, YCA data are automatically converted back to RGBA.
+ (Florian Kainz)
+ * IlmImf: speed up reading tiled files as scan lines.
+ (Florian Kainz)
+ * Half: Fixed subtle bug in Half where signaling float NaNs
+ were being converted to inf in half. (Florian Kainz)
+ * gcc 3.3 compiler warning cleanups. (various)
+ * Imath: ImathEuler.h fixes for gcc 3.4. (Garrick Meeker)
+
+Version 1.1.0:
+ * Added new targets to Visual C++ .NET 2003 project
+ for exrmaketiled, exrenvmap, exrmakepreview, and exrstdattr.
+ (Drew Hess)
+ * A few assorted Win32 fixes for Imath. (Drew Hess)
+ * GNU autoconf builds now produce versioned libraries.
+ This release is 1:0:0. (Drew Hess)
+ * Fixes for Visual C++ .NET 2003. (Paul Schneider)
+ * Updated Visual C++ zlib project file to zlib 1.2.1.
+ (Drew Hess)
+ * exrdisplay: Fixed fragment shader version. (Drew Hess)
+ * *Test: Fixed some compiler issues. (Drew Hess)
+ * Imath: Handle "restrict" keyword properly. (Drew Hess)
+ * IlmImfExamples: Updated to latest versions of example
+ source code, includes tiling and multi-res images.
+ (Florian Kainz)
+ * exrmakepreview: A new utility to create preview images.
+ (Florian Kainz)
+ * exrenvmap: A new utility to create OpenEXR environment
+ maps. (Florian Kainz)
+ * exrstdattr: A new utility to modify standard
+ attributes. (Florian Kainz)
+ * Updated exrheader to print level rounding mode and
+ preview image size. (Florian Kainz)
+ * Updated exrmaketiled to use level rounding mode.
+ (Florian Kainz)
+ * IlmImf: Changed the orientation of lat-long envmaps to
+ match typical panoramic camera setups. (Florian Kainz)
+ * IlmImf: Fixed a bug where partially-completed files with
+ DECREASING_Y could not be read. (Florian Kainz)
+ * IlmImf: Added support for selectable rounding mode (up/down)
+ when generating multiresolution files. (Florian Kainz)
+ * exrdisplay: Support for tiled images, mip/ripmaps, preview
+ images, and display windows. (Florian Kainz, Drew Hess)
+ * exrmaketiled: A new utility which generates tiled
+ versions of OpenEXR images. (Florian Kainz)
+ * IlmImf: Changed Imf::VERSION to Imf::EXR_VERSION to
+ work around problems with autoconf VERSION macro
+ conflict. (Drew Hess)
+ * exrheader: Support for tiles, mipmaps, environment
+ maps. (Florian Kainz)
+ * IlmImf: Environment map support. (Florian Kainz)
+ * IlmImf: Abstracted stream I/O support. (Florian Kainz)
+ * IlmImf: Support for tiled and mip/ripmapped files;
+ requires new file format. (Wojciech Jarosz, Florian Kainz)
+ * Imath: TMatrix*, generic 2D matricies and algorithms.
+ (Francesco Callari)
+ * Imath: major quaternions cleanup. (Cary Phillips)
+ * Imath: added GLBegin, GLPushAttrib, GLPushMatrix objects
+ for automatic cleanup on exceptions. (Cary Phillips)
+ * Imath: removed implicit scalar->vector promotions and vector
+ comparisons. (Nick Rasmussen)
+
+Version 1.0.7:
+ * Fixed a typo in one of the IlmImfTest tests. (Paul Schneider)
+ * Fixed a bug in exrdisplay that causes the image to display
+ as all black if there's a NaN or infinity in an OpenEXR
+ image. (Florian Kainz)
+ * Updated exrheader per recent changes to IlmImf library.
+ (Florian Kainz)
+ * Changed an errant float to a T in ImathFrame.h nextFrame().
+ (Cary Phillips)
+ * Support for new "optional standard" attributes
+ (chromaticities, luminance, comments, etc.).
+ (Florian Kainz, Greg Ward, Joseph Goldstone)
+ * Fixed a buffer overrun in ImfOpaqueAttribute. (Paul Schneider)
+ * Added new function, isImfMagic (). (Florian Kainz)
+
+Version 1.0.6:
+ * Added README.win32 to disted files.
+ * Fixed OpenEXR.pc.in pkg-config file, OpenEXR now works
+ with pkg-config.
+ * Random fixes to readme files for new release.
+ * Fixed openexr.m4, now looks in /usr by default.
+ * Added Visual Studio .NET 2003 "solution."
+ * Fixes for Visual Studio .NET 2003 w/ Microsoft C++ compiler.
+ (Various)
+ * Random Imath fixes and enhancements. Note that
+ extractSHRT now takes an additional optional
+ argument, see ImathMatrixAlgo.h for details. (Various)
+ * Added Wojciech Jarosz to AUTHORS file.
+ * Added test cases for uncompressed case, preview images,
+ frame buffer type conversion. (Wojciech Jarosz,
+ Florian Kainz)
+ * Fix a bug in IlmImf where uncompressed data doesn't get
+ read/written correctly. (Wojciech Jarosz)
+ * Added support for preview images and preview image
+ attributes (thumbnail images) in IlmImf. (Florian Kainz)
+ * Added support for automatic frame buffer type conversion
+ in IlmImf. (Florian Kainz)
+ * Cleaned up some compile-time checks.
+ * Added HalfTest unit tests.
+ * [exrdisplay] Download half framebuffer to texture memory
+ instead of converting to float first. Requires latest
+ Nvidia drivers.
+
+Version 1.0.5:
+ * Fixed IlmImf.dll to use static runtime libs (Andreas).
+ * Added exrheader project to Visual Studio 6.0 workspace.
+ * Added some example code showing how to use the IlmImf library.
+ (Florian)
+ * Use DLL runtime libs for Win32 libraries rather than static
+ runtime libs.
+ * Add an exrdisplay_fragshader project to the Visual Studio 6.0
+ workspace to enable fragment shaders in Win32.
+ * Add an IlmImfDll project to the Visual Studio 6.0 workspace.
+ * In Win32, export the ImfCRgbaFile C interface via a DLL so
+ that Visual C++ 6.0 users can link against an Intel-compiled
+ IlmImf. (Andreas Kahler)
+ * Use auto_ptr in ImfAutoArray on Win32, it doesn't like large
+ automatic stacks.
+ * Performance improvements in PIZ decoding, between
+ 20 and 60% speedup on Athlon and Pentium 4 systems.
+ (Florian)
+ * Updated the README with various information, made
+ some cosmetic changes for readability.
+ * Added fragment shader support to exrdisplay.
+ * Bumped the version to 1.0.5 in prep for release.
+ * Updated README and README.OSX to talk about CodeWarrior
+ project files.
+ * Incorporated Rodrigo Damazio's patch for an openexr.m4
+ macro file and an openexr.spec file for building RPMs.
+ * Small change in ImfAttribute.h to make IlmImf compile with gcc 2.95.
+ * Updated ImfDoubleAttribute.h for Codewarrior on MacOS.
+ * Added exrheader utility.
+ * Update to AUTHORS file.
+ * Added a README.win32 file.
+ * Added project files for Visual Studio 6.0.
+ * Initial Win32 port. Requires Visual Studio 6.0 and Intel C++
+ compiler version 7.0.
+ * Added new intersectT method in ImathSphere.h
+ * Fixed some bugs in ImathQuat.h
+ * Proper use of fltk-config to get platform-specific FLTK
+ compile- and link-time flags.
+ * exrdisplay uses Imath::Math<T>::pow instead of powf now.
+ powf is not availble on all platforms.
+ * Roll OS X "hack" into the source until Apple fixes their
+ istream implementation.
+
+Version 1.0.4:
+ * OpenEXR is now covered by a modified BSD license. See LICENSE
+ for the new terms.
+
+Version 1.0.3:
+
+ * OpenEXR is now in sf.net CVS.
+ * Imf::Xdr namespace cleanups.
+ * Some IlmImfTest cleanups for OS X.
+ * Use .cpp extension in exrdisplay sources.
+ * Iex cleanups.
+ * Make IlmImf compile with Metrowerks Codewarrior.
+ * Change large automatic stacks in ImfHuf.C to auto_ptrs allocated
+ off the heap. MacOS X default stack size isn't large enough.
+ * std::ios fix for MacOS X in ImfInputFile.C.
+ * Added new FP predecessor/successor functions to Imath, added
+ tests to ImathTest
+ * Fixed a bug in Imath::extractSHRT for 3x3 matricies when
+ exactly one of the original scaling factors is negative, updated
+ ImathTest to check this case.
+ * Install include files when 'make install' is run.
+ * exrdisplay requires fltk 1.1+ now in an effort to support
+ a MacOS X display program (fltk 1.1 runs on OS X), though this
+ is untested.
+ * renamed configure.in to configure.ac
+ * Removed some tests from IexTest that are no longer used.
+ * Removed ImfHalfXdr.h, it's not used anymore.
+ * Revamped the autoconf system, added some compile-time
+ optimizations, a pkgconfig target, and some maintainer-specific
+ stuff.
+
+Version 1.0.2:
+
+ * More OS X fixes in Imath, IlmImf and IlmImfTest.
+ * Imath updates.
+ * Fixed a rotation bug in Imath
+
+Version 1.0.1:
+
+ * Used autoconf 2.53 and automake 1.6 to generate build environment.
+ * Makefile.am cleanups.
+ * OS X fixes.
+ * removed images directory (now distributed separately).
+
+Version 1.0:
+
+ * first official release.
+ * added some high-level documentation, removed the old OpenEXR.html
+ documentation.
+ * fixed a few nagging build problems.
+ * bumped IMV_VERSION_NUMBER to 2
+
+Version 0.9:
+
+ * added exrdisplay viewer application.
+ * cleanup _data in Imf::InputFile and Imf::OutputFile constructors.
+ * removed old ILM copyright notices.
+
+Version 0.8:
+
+ * Initial release.
diff --git a/Source/OpenEXR/Copyrights/LICENSE b/Source/OpenEXR/Copyrights/LICENSE
new file mode 100644
index 0000000..7681f42
--- /dev/null
+++ b/Source/OpenEXR/Copyrights/LICENSE
@@ -0,0 +1,34 @@
+Copyright (c) 2006, Industrial Light & Magic, a division of Lucasfilm
+Entertainment Company Ltd. Portions contributed and copyright held by
+others as indicated. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above
+ copyright notice, this list of conditions and the following
+ disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided with
+ the distribution.
+
+ * Neither the name of Industrial Light & Magic nor the names of
+ any other contributors to this software may be used to endorse or
+ promote products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Source/OpenEXR/Half/Makefile.am b/Source/OpenEXR/Half/Makefile.am
new file mode 100644
index 0000000..c591f55
--- /dev/null
+++ b/Source/OpenEXR/Half/Makefile.am
@@ -0,0 +1,32 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = -I$(top_srcdir)/config
+
+lib_LTLIBRARIES = libHalf.la
+
+libHalf_la_SOURCES = half.cpp half.h halfFunction.h halfLimits.h
+
+libHalf_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+
+libHalfincludedir = $(includedir)/OpenEXR
+
+libHalfinclude_HEADERS = half.h halfFunction.h halfLimits.h
+
+# these are used to build eLut.h and toFloat.h dynamically
+EXTRA_DIST = eLut.cpp toFloat.cpp
+
+CLEANFILES = eLut eLut.h toFloat toFloat.h
+
+eLut_SOURCES = eLut.cpp
+
+toFloat_SOURCES = toFloat.cpp
+
+eLut.h: eLut
+ ./eLut > eLut.h
+
+toFloat.h: toFloat
+ ./toFloat > toFloat.h
+
+BUILT_SOURCES = eLut.h toFloat.h
+
+noinst_PROGRAMS = eLut toFloat
diff --git a/Source/OpenEXR/Half/Makefile.in b/Source/OpenEXR/Half/Makefile.in
new file mode 100644
index 0000000..d9c6c1c
--- /dev/null
+++ b/Source/OpenEXR/Half/Makefile.in
@@ -0,0 +1,541 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+SOURCES = $(libHalf_la_SOURCES) $(eLut_SOURCES) $(toFloat_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = eLut$(EXEEXT) toFloat$(EXEEXT)
+subdir = Half
+DIST_COMMON = $(libHalfinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/IlmBaseConfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libHalfincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libHalf_la_LIBADD =
+am_libHalf_la_OBJECTS = half.lo
+libHalf_la_OBJECTS = $(am_libHalf_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_eLut_OBJECTS = eLut.$(OBJEXT)
+eLut_OBJECTS = $(am_eLut_OBJECTS)
+eLut_LDADD = $(LDADD)
+am_toFloat_OBJECTS = toFloat.$(OBJEXT)
+toFloat_OBJECTS = $(am_toFloat_OBJECTS)
+toFloat_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libHalf_la_SOURCES) $(eLut_SOURCES) $(toFloat_SOURCES)
+DIST_SOURCES = $(libHalf_la_SOURCES) $(eLut_SOURCES) \
+ $(toFloat_SOURCES)
+libHalfincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libHalfinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CXXFLAGS = @AM_CXXFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+ILMBASE_VERSION = @ILMBASE_VERSION@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION = @LIBTOOL_VERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+acx_pthread_config = @acx_pthread_config@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+INCLUDES = -I$(top_srcdir)/config
+lib_LTLIBRARIES = libHalf.la
+libHalf_la_SOURCES = half.cpp half.h halfFunction.h halfLimits.h
+libHalf_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libHalfincludedir = $(includedir)/OpenEXR
+libHalfinclude_HEADERS = half.h halfFunction.h halfLimits.h
+
+# these are used to build eLut.h and toFloat.h dynamically
+EXTRA_DIST = eLut.cpp toFloat.cpp
+CLEANFILES = eLut eLut.h toFloat toFloat.h
+eLut_SOURCES = eLut.cpp
+toFloat_SOURCES = toFloat.cpp
+BUILT_SOURCES = eLut.h toFloat.h
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Half/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Half/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libHalf.la: $(libHalf_la_OBJECTS) $(libHalf_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libHalf_la_LDFLAGS) $(libHalf_la_OBJECTS) $(libHalf_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+eLut$(EXEEXT): $(eLut_OBJECTS) $(eLut_DEPENDENCIES)
+ @rm -f eLut$(EXEEXT)
+ $(CXXLINK) $(eLut_LDFLAGS) $(eLut_OBJECTS) $(eLut_LDADD) $(LIBS)
+toFloat$(EXEEXT): $(toFloat_OBJECTS) $(toFloat_DEPENDENCIES)
+ @rm -f toFloat$(EXEEXT)
+ $(CXXLINK) $(toFloat_LDFLAGS) $(toFloat_OBJECTS) $(toFloat_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eLut.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/half.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/toFloat.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libHalfincludeHEADERS: $(libHalfinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libHalfincludedir)" || $(mkdir_p) "$(DESTDIR)$(libHalfincludedir)"
+ @list='$(libHalfinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libHalfincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libHalfincludedir)/$$f'"; \
+ $(libHalfincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libHalfincludedir)/$$f"; \
+ done
+
+uninstall-libHalfincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libHalfinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libHalfincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libHalfincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libHalfincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libHalfincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libHalfincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-libHalfincludeHEADERS \
+ install-libLTLIBRARIES install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am \
+ uninstall-libHalfincludeHEADERS uninstall-libLTLIBRARIES
+
+
+eLut.h: eLut
+ ./eLut > eLut.h
+
+toFloat.h: toFloat
+ ./toFloat > toFloat.h
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/OpenEXR/Half/eLut.cpp b/Source/OpenEXR/Half/eLut.cpp
new file mode 100644
index 0000000..ce64b50
--- /dev/null
+++ b/Source/OpenEXR/Half/eLut.cpp
@@ -0,0 +1,114 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+//-----------------------------------------------------
+// Compute a lookup table for float-to-half conversion.
+//
+// When indexed with the combined sign and exponent of
+// a float, the table either returns the combined sign
+// and exponent of the corresponding half, or zero if
+// the corresponding half may not be normalized (zero,
+// denormalized, overflow).
+//-----------------------------------------------------
+
+void
+initELut (unsigned short eLut[])
+{
+ for (int i = 0; i < 0x100; i++)
+ {
+ int e = (i & 0x0ff) - (127 - 15);
+
+ if (e <= 0 || e >= 30)
+ {
+ //
+ // Special case
+ //
+
+ eLut[i] = 0;
+ eLut[i | 0x100] = 0;
+ }
+ else
+ {
+ //
+ // Common case - normalized half, no exponent overflow possible
+ //
+
+ eLut[i] = (e << 10);
+ eLut[i | 0x100] = ((e << 10) | 0x8000);
+ }
+ }
+}
+
+
+//------------------------------------------------------------
+// Main - prints the sign-and-exponent conversion lookup table
+//------------------------------------------------------------
+
+int
+main ()
+{
+ const int tableSize = 1 << 9;
+ unsigned short eLut[tableSize];
+ initELut (eLut);
+
+ cout << "//\n"
+ "// This is an automatically generated file.\n"
+ "// Do not edit.\n"
+ "//\n\n";
+
+ cout << "{\n ";
+
+ for (int i = 0; i < tableSize; i++)
+ {
+ cout << setw (5) << eLut[i] << ", ";
+
+ if (i % 8 == 7)
+ {
+ cout << "\n";
+
+ if (i < tableSize - 1)
+ cout << " ";
+ }
+ }
+
+ cout << "};\n";
+ return 0;
+}
diff --git a/Source/OpenEXR/Half/eLut.h b/Source/OpenEXR/Half/eLut.h
new file mode 100644
index 0000000..f028cdb
--- /dev/null
+++ b/Source/OpenEXR/Half/eLut.h
@@ -0,0 +1,71 @@
+//
+// This is an automatically generated file.
+// Do not edit.
+//
+
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1024, 2048, 3072, 4096, 5120, 6144, 7168,
+ 8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360,
+ 16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552,
+ 24576, 25600, 26624, 27648, 28672, 29696, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 33792, 34816, 35840, 36864, 37888, 38912, 39936,
+ 40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128,
+ 49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320,
+ 57344, 58368, 59392, 60416, 61440, 62464, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
diff --git a/Source/OpenEXR/Half/half.cpp b/Source/OpenEXR/Half/half.cpp
new file mode 100644
index 0000000..02549d5
--- /dev/null
+++ b/Source/OpenEXR/Half/half.cpp
@@ -0,0 +1,317 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+// Primary authors:
+// Florian Kainz <kainz@ilm.com>
+// Rod Bogart <rgb@ilm.com>
+
+
+//---------------------------------------------------------------------------
+//
+// class half --
+// implementation of non-inline members
+//
+//---------------------------------------------------------------------------
+
+#include <assert.h>
+#include "half.h"
+
+using namespace std;
+
+//-------------------------------------------------------------
+// Lookup tables for half-to-float and float-to-half conversion
+//-------------------------------------------------------------
+
+#if defined (OPENEXR_DLL)
+__declspec(dllexport) half::uif _toFloat[1 << 16] =
+ #include "toFloat.h"
+__declspec(dllexport) unsigned short _eLut[1 << 9] =
+ #include "eLut.h"
+#else
+const half::uif half::_toFloat[1 << 16] =
+ #include "toFloat.h"
+const unsigned short half::_eLut[1 << 9] =
+ #include "eLut.h"
+#endif
+
+//-----------------------------------------------
+// Overflow handler for float-to-half conversion;
+// generates a hardware floating-point overflow,
+// which may be trapped by the operating system.
+//-----------------------------------------------
+
+float
+half::overflow ()
+{
+ volatile float f = 1e10;
+
+ for (int i = 0; i < 10; i++)
+ f *= f; // this will overflow before
+ // the for­loop terminates
+ return f;
+}
+
+
+//-----------------------------------------------------
+// Float-to-half conversion -- general case, including
+// zeroes, denormalized numbers and exponent overflows.
+//-----------------------------------------------------
+
+short
+half::convert (int i)
+{
+ //
+ // Our floating point number, f, is represented by the bit
+ // pattern in integer i. Disassemble that bit pattern into
+ // the sign, s, the exponent, e, and the significand, m.
+ // Shift s into the position where it will go in in the
+ // resulting half number.
+ // Adjust e, accounting for the different exponent bias
+ // of float and half (127 versus 15).
+ //
+
+ register int s = (i >> 16) & 0x00008000;
+ register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
+ register int m = i & 0x007fffff;
+
+ //
+ // Now reassemble s, e and m into a half:
+ //
+
+ if (e <= 0)
+ {
+ if (e < -10)
+ {
+ //
+ // E is less than -10. The absolute value of f is
+ // less than HALF_MIN (f may be a small normalized
+ // float, a denormalized float or a zero).
+ //
+ // We convert f to a half zero with the same sign as f.
+ //
+
+ return s;
+ }
+
+ //
+ // E is between -10 and 0. F is a normalized float
+ // whose magnitude is less than HALF_NRM_MIN.
+ //
+ // We convert f to a denormalized half.
+ //
+
+ //
+ // Add an explicit leading 1 to the significand.
+ //
+
+ m = m | 0x00800000;
+
+ //
+ // Round to m to the nearest (10+e)-bit value (with e between
+ // -10 and 0); in case of a tie, round to the nearest even value.
+ //
+ // Rounding may cause the significand to overflow and make
+ // our number normalized. Because of the way a half's bits
+ // are laid out, we don't have to treat this case separately;
+ // the code below will handle it correctly.
+ //
+
+ int t = 14 - e;
+ int a = (1 << (t - 1)) - 1;
+ int b = (m >> t) & 1;
+
+ m = (m + a + b) >> t;
+
+ //
+ // Assemble the half from s, e (zero) and m.
+ //
+
+ return s | m;
+ }
+ else if (e == 0xff - (127 - 15))
+ {
+ if (m == 0)
+ {
+ //
+ // F is an infinity; convert f to a half
+ // infinity with the same sign as f.
+ //
+
+ return s | 0x7c00;
+ }
+ else
+ {
+ //
+ // F is a NAN; we produce a half NAN that preserves
+ // the sign bit and the 10 leftmost bits of the
+ // significand of f, with one exception: If the 10
+ // leftmost bits are all zero, the NAN would turn
+ // into an infinity, so we have to set at least one
+ // bit in the significand.
+ //
+
+ m >>= 13;
+ return s | 0x7c00 | m | (m == 0);
+ }
+ }
+ else
+ {
+ //
+ // E is greater than zero. F is a normalized float.
+ // We try to convert f to a normalized half.
+ //
+
+ //
+ // Round to m to the nearest 10-bit value. In case of
+ // a tie, round to the nearest even value.
+ //
+
+ m = m + 0x00000fff + ((m >> 13) & 1);
+
+ if (m & 0x00800000)
+ {
+ m = 0; // overflow in significand,
+ e += 1; // adjust exponent
+ }
+
+ //
+ // Handle exponent overflow
+ //
+
+ if (e > 30)
+ {
+ overflow (); // Cause a hardware floating point overflow;
+ return s | 0x7c00; // if this returns, the half becomes an
+ } // infinity with the same sign as f.
+
+ //
+ // Assemble the half from s, e and m.
+ //
+
+ return s | (e << 10) | (m >> 13);
+ }
+}
+
+
+//---------------------
+// Stream I/O operators
+//---------------------
+
+ostream &
+operator << (ostream &os, half h)
+{
+ os << float (h);
+ return os;
+}
+
+
+istream &
+operator >> (istream &is, half &h)
+{
+ float f;
+ is >> f;
+ h = half (f);
+ return is;
+}
+
+
+//---------------------------------------
+// Functions to print the bit-layout of
+// floats and halfs, mostly for debugging
+//---------------------------------------
+
+void
+printBits (ostream &os, half h)
+{
+ unsigned short b = h.bits();
+
+ for (int i = 15; i >= 0; i--)
+ {
+ os << (((b >> i) & 1)? '1': '0');
+
+ if (i == 15 || i == 10)
+ os << ' ';
+ }
+}
+
+
+void
+printBits (ostream &os, float f)
+{
+ half::uif x;
+ x.f = f;
+
+ for (int i = 31; i >= 0; i--)
+ {
+ os << (((x.i >> i) & 1)? '1': '0');
+
+ if (i == 31 || i == 23)
+ os << ' ';
+ }
+}
+
+
+void
+printBits (char c[19], half h)
+{
+ unsigned short b = h.bits();
+
+ for (int i = 15, j = 0; i >= 0; i--, j++)
+ {
+ c[j] = (((b >> i) & 1)? '1': '0');
+
+ if (i == 15 || i == 10)
+ c[++j] = ' ';
+ }
+
+ c[18] = 0;
+}
+
+
+void
+printBits (char c[35], float f)
+{
+ half::uif x;
+ x.f = f;
+
+ for (int i = 31, j = 0; i >= 0; i--, j++)
+ {
+ c[j] = (((x.i >> i) & 1)? '1': '0');
+
+ if (i == 31 || i == 23)
+ c[++j] = ' ';
+ }
+
+ c[34] = 0;
+}
diff --git a/Source/OpenEXR/Half/half.h b/Source/OpenEXR/Half/half.h
new file mode 100644
index 0000000..bfb0116
--- /dev/null
+++ b/Source/OpenEXR/Half/half.h
@@ -0,0 +1,776 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+// Primary authors:
+// Florian Kainz <kainz@ilm.com>
+// Rod Bogart <rgb@ilm.com>
+
+//---------------------------------------------------------------------------
+//
+// half -- a 16-bit floating point number class:
+//
+// Type half can represent positive and negative numbers whose
+// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative
+// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented
+// with an absolute error of 6.0e-8. All integers from -2048 to
+// +2048 can be represented exactly.
+//
+// Type half behaves (almost) like the built-in C++ floating point
+// types. In arithmetic expressions, half, float and double can be
+// mixed freely. Here are a few examples:
+//
+// half a (3.5);
+// float b (a + sqrt (a));
+// a += b;
+// b += a;
+// b = a + 7;
+//
+// Conversions from half to float are lossless; all half numbers
+// are exactly representable as floats.
+//
+// Conversions from float to half may not preserve the float's
+// value exactly. If a float is not representable as a half, the
+// float value is rounded to the nearest representable half. If
+// a float value is exactly in the middle between the two closest
+// representable half values, then the float value is rounded to
+// the half with the greater magnitude.
+//
+// Overflows during float-to-half conversions cause arithmetic
+// exceptions. An overflow occurs when the float value to be
+// converted is too large to be represented as a half, or if the
+// float value is an infinity or a NAN.
+//
+// The implementation of type half makes the following assumptions
+// about the implementation of the built-in C++ types:
+//
+// float is an IEEE 754 single-precision number
+// sizeof (float) == 4
+// sizeof (unsigned int) == sizeof (float)
+// alignof (unsigned int) == alignof (float)
+// sizeof (unsigned short) == 2
+//
+//---------------------------------------------------------------------------
+
+#ifndef _HALF_H_
+#define _HALF_H_
+
+#include <iostream>
+
+class half
+{
+ public:
+
+ //-------------
+ // Constructors
+ //-------------
+
+ half (); // no initialization
+ half (float f);
+
+
+ //--------------------
+ // Conversion to float
+ //--------------------
+
+ operator float () const;
+
+
+ //------------
+ // Unary minus
+ //------------
+
+ half operator - () const;
+
+
+ //-----------
+ // Assignment
+ //-----------
+
+ half & operator = (half h);
+ half & operator = (float f);
+
+ half & operator += (half h);
+ half & operator += (float f);
+
+ half & operator -= (half h);
+ half & operator -= (float f);
+
+ half & operator *= (half h);
+ half & operator *= (float f);
+
+ half & operator /= (half h);
+ half & operator /= (float f);
+
+
+ //---------------------------------------------------------
+ // Round to n-bit precision (n should be between 0 and 10).
+ // After rounding, the significand's 10-n least significant
+ // bits will be zero.
+ //---------------------------------------------------------
+
+ half round (unsigned int n) const;
+
+
+ //--------------------------------------------------------------------
+ // Classification:
+ //
+ // h.isFinite() returns true if h is a normalized number,
+ // a denormalized number or zero
+ //
+ // h.isNormalized() returns true if h is a normalized number
+ //
+ // h.isDenormalized() returns true if h is a denormalized number
+ //
+ // h.isZero() returns true if h is zero
+ //
+ // h.isNan() returns true if h is a NAN
+ //
+ // h.isInfinity() returns true if h is a positive
+ // or a negative infinity
+ //
+ // h.isNegative() returns true if the sign bit of h
+ // is set (negative)
+ //--------------------------------------------------------------------
+
+ bool isFinite () const;
+ bool isNormalized () const;
+ bool isDenormalized () const;
+ bool isZero () const;
+ bool isNan () const;
+ bool isInfinity () const;
+ bool isNegative () const;
+
+
+ //--------------------------------------------
+ // Special values
+ //
+ // posInf() returns +infinity
+ //
+ // negInf() returns -infinity
+ //
+ // qNan() returns a NAN with the bit
+ // pattern 0111111111111111
+ //
+ // sNan() returns a NAN with the bit
+ // pattern 0111110111111111
+ //--------------------------------------------
+
+ static half posInf ();
+ static half negInf ();
+ static half qNan ();
+ static half sNan ();
+
+
+ //--------------------------------------
+ // Access to the internal representation
+ //--------------------------------------
+
+ unsigned short bits () const;
+ void setBits (unsigned short bits);
+
+
+ public:
+
+ union uif
+ {
+ unsigned int i;
+ float f;
+ };
+
+ private:
+
+ static short convert (int i);
+ static float overflow ();
+
+ unsigned short _h;
+
+ //---------------------------------------------------
+ // Windows dynamic libraries don't like static
+ // member variables.
+ //---------------------------------------------------
+#ifndef OPENEXR_DLL
+ static const uif _toFloat[1 << 16];
+ static const unsigned short _eLut[1 << 9];
+#endif
+};
+
+#if defined(OPENEXR_DLL)
+ //--------------------------------------
+ // Lookup tables defined for Windows DLL
+ //--------------------------------------
+ #if defined(HALF_EXPORTS)
+ extern __declspec(dllexport) half::uif _toFloat[1 << 16];
+ extern __declspec(dllexport) unsigned short _eLut[1 << 9];
+ #else
+ extern __declspec(dllimport) half::uif _toFloat[1 << 16];
+ extern __declspec(dllimport) unsigned short _eLut[1 << 9];
+ #endif
+#endif
+
+
+//-----------
+// Stream I/O
+//-----------
+
+std::ostream & operator << (std::ostream &os, half h);
+std::istream & operator >> (std::istream &is, half &h);
+
+
+//----------
+// Debugging
+//----------
+
+void printBits (std::ostream &os, half h);
+void printBits (std::ostream &os, float f);
+void printBits (char c[19], half h);
+void printBits (char c[35], float f);
+
+
+//-------------------------------------------------------------------------
+// Limits
+//
+// Visual C++ will complain if HALF_MIN, HALF_NRM_MIN etc. are not float
+// constants, but at least one other compiler (gcc 2.96) produces incorrect
+// results if they are.
+//-------------------------------------------------------------------------
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+
+ #define HALF_MIN 5.96046448e-08f // Smallest positive half
+
+ #define HALF_NRM_MIN 6.10351562e-05f // Smallest positive normalized half
+
+ #define HALF_MAX 65504.0f // Largest positive half
+
+ #define HALF_EPSILON 0.00097656f // Smallest positive e for which
+ // half (1.0 + e) != half (1.0)
+#else
+
+ #define HALF_MIN 5.96046448e-08 // Smallest positive half
+
+ #define HALF_NRM_MIN 6.10351562e-05 // Smallest positive normalized half
+
+ #define HALF_MAX 65504.0 // Largest positive half
+
+ #define HALF_EPSILON 0.00097656 // Smallest positive e for which
+ // half (1.0 + e) != half (1.0)
+#endif
+
+
+#define HALF_MANT_DIG 11 // Number of digits in mantissa
+ // (significand + hidden leading 1)
+
+#define HALF_DIG 2 // Number of base 10 digits that
+ // can be represented without change
+
+#define HALF_RADIX 2 // Base of the exponent
+
+#define HALF_MIN_EXP -13 // Minimum negative integer such that
+ // HALF_RADIX raised to the power of
+ // one less than that integer is a
+ // normalized half
+
+#define HALF_MAX_EXP 16 // Maximum positive integer such that
+ // HALF_RADIX raised to the power of
+ // one less than that integer is a
+ // normalized half
+
+#define HALF_MIN_10_EXP -4 // Minimum positive integer such
+ // that 10 raised to that power is
+ // a normalized half
+
+#define HALF_MAX_10_EXP 4 // Maximum positive integer such
+ // that 10 raised to that power is
+ // a normalized half
+
+
+//---------------------------------------------------------------------------
+//
+// Implementation --
+//
+// Representation of a float:
+//
+// We assume that a float, f, is an IEEE 754 single-precision
+// floating point number, whose bits are arranged as follows:
+//
+// 31 (msb)
+// |
+// | 30 23
+// | | |
+// | | | 22 0 (lsb)
+// | | | | |
+// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
+//
+// s e m
+//
+// S is the sign-bit, e is the exponent and m is the significand.
+//
+// If e is between 1 and 254, f is a normalized number:
+//
+// s e-127
+// f = (-1) * 2 * 1.m
+//
+// If e is 0, and m is not zero, f is a denormalized number:
+//
+// s -126
+// f = (-1) * 2 * 0.m
+//
+// If e and m are both zero, f is zero:
+//
+// f = 0.0
+//
+// If e is 255, f is an "infinity" or "not a number" (NAN),
+// depending on whether m is zero or not.
+//
+// Examples:
+//
+// 0 00000000 00000000000000000000000 = 0.0
+// 0 01111110 00000000000000000000000 = 0.5
+// 0 01111111 00000000000000000000000 = 1.0
+// 0 10000000 00000000000000000000000 = 2.0
+// 0 10000000 10000000000000000000000 = 3.0
+// 1 10000101 11110000010000000000000 = -124.0625
+// 0 11111111 00000000000000000000000 = +infinity
+// 1 11111111 00000000000000000000000 = -infinity
+// 0 11111111 10000000000000000000000 = NAN
+// 1 11111111 11111111111111111111111 = NAN
+//
+// Representation of a half:
+//
+// Here is the bit-layout for a half number, h:
+//
+// 15 (msb)
+// |
+// | 14 10
+// | | |
+// | | | 9 0 (lsb)
+// | | | | |
+// X XXXXX XXXXXXXXXX
+//
+// s e m
+//
+// S is the sign-bit, e is the exponent and m is the significand.
+//
+// If e is between 1 and 30, h is a normalized number:
+//
+// s e-15
+// h = (-1) * 2 * 1.m
+//
+// If e is 0, and m is not zero, h is a denormalized number:
+//
+// S -14
+// h = (-1) * 2 * 0.m
+//
+// If e and m are both zero, h is zero:
+//
+// h = 0.0
+//
+// If e is 31, h is an "infinity" or "not a number" (NAN),
+// depending on whether m is zero or not.
+//
+// Examples:
+//
+// 0 00000 0000000000 = 0.0
+// 0 01110 0000000000 = 0.5
+// 0 01111 0000000000 = 1.0
+// 0 10000 0000000000 = 2.0
+// 0 10000 1000000000 = 3.0
+// 1 10101 1111000001 = -124.0625
+// 0 11111 0000000000 = +infinity
+// 1 11111 0000000000 = -infinity
+// 0 11111 1000000000 = NAN
+// 1 11111 1111111111 = NAN
+//
+// Conversion:
+//
+// Converting from a float to a half requires some non-trivial bit
+// manipulations. In some cases, this makes conversion relatively
+// slow, but the most common case is accelerated via table lookups.
+//
+// Converting back from a half to a float is easier because we don't
+// have to do any rounding. In addition, there are only 65536
+// different half numbers; we can convert each of those numbers once
+// and store the results in a table. Later, all conversions can be
+// done using only simple table lookups.
+//
+//---------------------------------------------------------------------------
+
+
+//--------------------
+// Simple constructors
+//--------------------
+
+inline
+half::half ()
+{
+ // no initialization
+}
+
+
+//----------------------------
+// Half-from-float constructor
+//----------------------------
+
+inline
+half::half (float f)
+{
+ uif x;
+
+ x.f = f;
+
+ if (f == 0)
+ {
+ //
+ // Common special case - zero.
+ // Preserve the zero's sign bit.
+ //
+
+ _h = (x.i >> 16);
+ }
+ else
+ {
+ //
+ // We extract the combined sign and exponent, e, from our
+ // floating-point number, f. Then we convert e to the sign
+ // and exponent of the half number via a table lookup.
+ //
+ // For the most common case, where a normalized half is produced,
+ // the table lookup returns a non-zero value; in this case, all
+ // we have to do is round f's significand to 10 bits and combine
+ // the result with e.
+ //
+ // For all other cases (overflow, zeroes, denormalized numbers
+ // resulting from underflow, infinities and NANs), the table
+ // lookup returns zero, and we call a longer, non-inline function
+ // to do the float-to-half conversion.
+ //
+
+ register int e = (x.i >> 23) & 0x000001ff;
+
+ e = _eLut[e];
+
+ if (e)
+ {
+ //
+ // Simple case - round the significand, m, to 10
+ // bits and combine it with the sign and exponent.
+ //
+
+ register int m = x.i & 0x007fffff;
+ _h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);
+ }
+ else
+ {
+ //
+ // Difficult case - call a function.
+ //
+
+ _h = convert (x.i);
+ }
+ }
+}
+
+
+//------------------------------------------
+// Half-to-float conversion via table lookup
+//------------------------------------------
+
+inline
+half::operator float () const
+{
+ return _toFloat[_h].f;
+}
+
+
+//-------------------------
+// Round to n-bit precision
+//-------------------------
+
+inline half
+half::round (unsigned int n) const
+{
+ //
+ // Parameter check.
+ //
+
+ if (n >= 10)
+ return *this;
+
+ //
+ // Disassemble h into the sign, s,
+ // and the combined exponent and significand, e.
+ //
+
+ unsigned short s = _h & 0x8000;
+ unsigned short e = _h & 0x7fff;
+
+ //
+ // Round the exponent and significand to the nearest value
+ // where ones occur only in the (10-n) most significant bits.
+ // Note that the exponent adjusts automatically if rounding
+ // up causes the significand to overflow.
+ //
+
+ e >>= 9 - n;
+ e += e & 1;
+ e <<= 9 - n;
+
+ //
+ // Check for exponent overflow.
+ //
+
+ if (e >= 0x7c00)
+ {
+ //
+ // Overflow occurred -- truncate instead of rounding.
+ //
+
+ e = _h;
+ e >>= 10 - n;
+ e <<= 10 - n;
+ }
+
+ //
+ // Put the original sign bit back.
+ //
+
+ half h;
+ h._h = s | e;
+
+ return h;
+}
+
+
+//-----------------------
+// Other inline functions
+//-----------------------
+
+inline half
+half::operator - () const
+{
+ half h;
+ h._h = _h ^ 0x8000;
+ return h;
+}
+
+
+inline half &
+half::operator = (half h)
+{
+ _h = h._h;
+ return *this;
+}
+
+
+inline half &
+half::operator = (float f)
+{
+ *this = half (f);
+ return *this;
+}
+
+
+inline half &
+half::operator += (half h)
+{
+ *this = half (float (*this) + float (h));
+ return *this;
+}
+
+
+inline half &
+half::operator += (float f)
+{
+ *this = half (float (*this) + f);
+ return *this;
+}
+
+
+inline half &
+half::operator -= (half h)
+{
+ *this = half (float (*this) - float (h));
+ return *this;
+}
+
+
+inline half &
+half::operator -= (float f)
+{
+ *this = half (float (*this) - f);
+ return *this;
+}
+
+
+inline half &
+half::operator *= (half h)
+{
+ *this = half (float (*this) * float (h));
+ return *this;
+}
+
+
+inline half &
+half::operator *= (float f)
+{
+ *this = half (float (*this) * f);
+ return *this;
+}
+
+
+inline half &
+half::operator /= (half h)
+{
+ *this = half (float (*this) / float (h));
+ return *this;
+}
+
+
+inline half &
+half::operator /= (float f)
+{
+ *this = half (float (*this) / f);
+ return *this;
+}
+
+
+inline bool
+half::isFinite () const
+{
+ unsigned short e = (_h >> 10) & 0x001f;
+ return e < 31;
+}
+
+
+inline bool
+half::isNormalized () const
+{
+ unsigned short e = (_h >> 10) & 0x001f;
+ return e > 0 && e < 31;
+}
+
+
+inline bool
+half::isDenormalized () const
+{
+ unsigned short e = (_h >> 10) & 0x001f;
+ unsigned short m = _h & 0x3ff;
+ return e == 0 && m != 0;
+}
+
+
+inline bool
+half::isZero () const
+{
+ return (_h & 0x7fff) == 0;
+}
+
+
+inline bool
+half::isNan () const
+{
+ unsigned short e = (_h >> 10) & 0x001f;
+ unsigned short m = _h & 0x3ff;
+ return e == 31 && m != 0;
+}
+
+
+inline bool
+half::isInfinity () const
+{
+ unsigned short e = (_h >> 10) & 0x001f;
+ unsigned short m = _h & 0x3ff;
+ return e == 31 && m == 0;
+}
+
+
+inline bool
+half::isNegative () const
+{
+ return (_h & 0x8000) != 0;
+}
+
+
+inline half
+half::posInf ()
+{
+ half h;
+ h._h = 0x7c00;
+ return h;
+}
+
+
+inline half
+half::negInf ()
+{
+ half h;
+ h._h = 0xfc00;
+ return h;
+}
+
+
+inline half
+half::qNan ()
+{
+ half h;
+ h._h = 0x7fff;
+ return h;
+}
+
+
+inline half
+half::sNan ()
+{
+ half h;
+ h._h = 0x7dff;
+ return h;
+}
+
+
+inline unsigned short
+half::bits () const
+{
+ return _h;
+}
+
+
+inline void
+half::setBits (unsigned short bits)
+{
+ _h = bits;
+}
+
+#undef HALF_EXPORT_CONST
+
+#endif
diff --git a/Source/OpenEXR/Half/halfFunction.h b/Source/OpenEXR/Half/halfFunction.h
new file mode 100644
index 0000000..1983880
--- /dev/null
+++ b/Source/OpenEXR/Half/halfFunction.h
@@ -0,0 +1,159 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+// Primary authors:
+// Florian Kainz <kainz@ilm.com>
+// Rod Bogart <rgb@ilm.com>
+
+
+//---------------------------------------------------------------------------
+//
+// halfFunction<T> -- a class for fast evaluation
+// of half --> T functions
+//
+// The constructor for a halfFunction object,
+//
+// halfFunction (function,
+// domainMin, domainMax,
+// defaultValue,
+// posInfValue, negInfValue,
+// nanValue);
+//
+// evaluates the function for all finite half values in the interval
+// [domainMin, domainMax], and stores the results in a lookup table.
+// For finite half values that are not in [domainMin, domainMax], the
+// constructor stores defaultValue in the table. For positive infinity,
+// negative infinity and NANs, posInfValue, negInfValue and nanValue
+// are stored in the table.
+//
+// The tabulated function can then be evaluated quickly for arbitrary
+// half values by calling the the halfFunction object's operator()
+// method.
+//
+// Example:
+//
+// #include <math.h>
+// #include <halfFunction.h>
+//
+// halfFunction<half> hsin (sin);
+//
+// halfFunction<half> hsqrt (sqrt, // function
+// 0, HALF_MAX, // domain
+// half::qNan(), // sqrt(x) for x < 0
+// half::posInf(), // sqrt(+inf)
+// half::qNan(), // sqrt(-inf)
+// half::qNan()); // sqrt(nan)
+//
+// half x = hsin (1);
+// half y = hsqrt (3.5);
+//
+//---------------------------------------------------------------------------
+
+#ifndef _HALF_FUNCTION_H_
+#define _HALF_FUNCTION_H_
+
+#include <float.h>
+#include "half.h"
+
+
+template <class T>
+class halfFunction
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ template <class Function>
+ halfFunction (Function f,
+ half domainMin = -HALF_MAX,
+ half domainMax = HALF_MAX,
+ T defaultValue = 0,
+ T posInfValue = 0,
+ T negInfValue = 0,
+ T nanValue = 0);
+
+ //-----------
+ // Evaluation
+ //-----------
+
+ T operator () (half x) const;
+
+ private:
+
+ T _lut[1 << 16];
+};
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+template <class Function>
+halfFunction<T>::halfFunction (Function f,
+ half domainMin,
+ half domainMax,
+ T defaultValue,
+ T posInfValue,
+ T negInfValue,
+ T nanValue)
+{
+ for (int i = 0; i < (1 << 16); i++)
+ {
+ half x;
+ x.setBits (i);
+
+ if (x.isNan())
+ _lut[i] = nanValue;
+ else if (x.isInfinity())
+ _lut[i] = x.isNegative()? negInfValue: posInfValue;
+ else if (x < domainMin || x > domainMax)
+ _lut[i] = defaultValue;
+ else
+ _lut[i] = f (x);
+ }
+}
+
+
+template <class T>
+inline T
+halfFunction<T>::operator () (half x) const
+{
+ return _lut[x.bits()];
+}
+
+
+#endif
diff --git a/Source/OpenEXR/Half/halfLimits.h b/Source/OpenEXR/Half/halfLimits.h
new file mode 100644
index 0000000..404f589
--- /dev/null
+++ b/Source/OpenEXR/Half/halfLimits.h
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+// Primary authors:
+// Florian Kainz <kainz@ilm.com>
+// Rod Bogart <rgb@ilm.com>
+
+
+#ifndef INCLUDED_HALF_LIMITS_H
+#define INCLUDED_HALF_LIMITS_H
+
+
+//------------------------------------------------------------------------
+//
+// C++ standard library-style numeric_limits for class half
+//
+//------------------------------------------------------------------------
+
+#include <limits>
+#include "half.h"
+
+namespace std {
+
+template <>
+class numeric_limits <half>
+{
+ public:
+
+ static const bool is_specialized = true;
+
+ static half min () throw () {return HALF_NRM_MIN;}
+ static half max () throw () {return HALF_MAX;}
+
+ static const int digits = HALF_MANT_DIG;
+ static const int digits10 = HALF_DIG;
+ static const bool is_signed = true;
+ static const bool is_integer = false;
+ static const bool is_exact = false;
+ static const int radix = HALF_RADIX;
+ static half epsilon () throw () {return HALF_EPSILON;}
+ static half round_error () throw () {return HALF_EPSILON / 2;}
+
+ static const int min_exponent = HALF_MIN_EXP;
+ static const int min_exponent10 = HALF_MIN_10_EXP;
+ static const int max_exponent = HALF_MAX_EXP;
+ static const int max_exponent10 = HALF_MAX_10_EXP;
+
+ static const bool has_infinity = true;
+ static const bool has_quiet_NaN = true;
+ static const bool has_signaling_NaN = true;
+ static const float_denorm_style has_denorm = denorm_present;
+ static const bool has_denorm_loss = false;
+ static half infinity () throw () {return half::posInf();}
+ static half quiet_NaN () throw () {return half::qNan();}
+ static half signaling_NaN () throw () {return half::sNan();}
+ static half denorm_min () throw () {return HALF_MIN;}
+
+ static const bool is_iec559 = false;
+ static const bool is_bounded = false;
+ static const bool is_modulo = false;
+
+ static const bool traps = true;
+ static const bool tinyness_before = false;
+ static const float_round_style round_style = round_to_nearest;
+};
+
+
+} // namespace std
+
+#endif
diff --git a/Source/OpenEXR/Half/toFloat.cpp b/Source/OpenEXR/Half/toFloat.cpp
new file mode 100644
index 0000000..001bc51
--- /dev/null
+++ b/Source/OpenEXR/Half/toFloat.cpp
@@ -0,0 +1,164 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+//---------------------------------------------------------------------------
+//
+// toFloat
+//
+// A program to generate the lookup table for half-to-float
+// conversion needed by class half.
+// The program loops over all 65536 possible half numbers,
+// converts each of them to a float, and prints the result.
+//
+//---------------------------------------------------------------------------
+
+
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+//---------------------------------------------------
+// Interpret an unsigned short bit pattern as a half,
+// and convert that half to the corresponding float's
+// bit pattern.
+//---------------------------------------------------
+
+unsigned int
+halfToFloat (unsigned short y)
+{
+
+ int s = (y >> 15) & 0x00000001;
+ int e = (y >> 10) & 0x0000001f;
+ int m = y & 0x000003ff;
+
+ if (e == 0)
+ {
+ if (m == 0)
+ {
+ //
+ // Plus or minus zero
+ //
+
+ return s << 31;
+ }
+ else
+ {
+ //
+ // Denormalized number -- renormalize it
+ //
+
+ while (!(m & 0x00000400))
+ {
+ m <<= 1;
+ e -= 1;
+ }
+
+ e += 1;
+ m &= ~0x00000400;
+ }
+ }
+ else if (e == 31)
+ {
+ if (m == 0)
+ {
+ //
+ // Positive or negative infinity
+ //
+
+ return (s << 31) | 0x7f800000;
+ }
+ else
+ {
+ //
+ // Nan -- preserve sign and significand bits
+ //
+
+ return (s << 31) | 0x7f800000 | (m << 13);
+ }
+ }
+
+ //
+ // Normalized number
+ //
+
+ e = e + (127 - 15);
+ m = m << 13;
+
+ //
+ // Assemble s, e and m.
+ //
+
+ return (s << 31) | (e << 23) | m;
+}
+
+
+//---------------------------------------------
+// Main - prints the half-to-float lookup table
+//---------------------------------------------
+
+int
+main ()
+{
+ cout.precision (9);
+ cout.setf (ios_base::hex, ios_base::basefield);
+
+ cout << "//\n"
+ "// This is an automatically generated file.\n"
+ "// Do not edit.\n"
+ "//\n\n";
+
+ cout << "{\n ";
+
+ const int iMax = (1 << 16);
+
+ for (int i = 0; i < iMax; i++)
+ {
+ cout << "{0x" << setfill ('0') << setw (8) << halfToFloat (i) << "}, ";
+
+ if (i % 4 == 3)
+ {
+ cout << "\n";
+
+ if (i < iMax - 1)
+ cout << " ";
+ }
+ }
+
+ cout << "};\n";
+ return 0;
+}
diff --git a/Source/OpenEXR/Half/toFloat.h b/Source/OpenEXR/Half/toFloat.h
new file mode 100644
index 0000000..37c9556
--- /dev/null
+++ b/Source/OpenEXR/Half/toFloat.h
@@ -0,0 +1,16391 @@
+//
+// This is an automatically generated file.
+// Do not edit.
+//
+
+{
+ {0x00000000}, {0x33800000}, {0x34000000}, {0x34400000},
+ {0x34800000}, {0x34a00000}, {0x34c00000}, {0x34e00000},
+ {0x35000000}, {0x35100000}, {0x35200000}, {0x35300000},
+ {0x35400000}, {0x35500000}, {0x35600000}, {0x35700000},
+ {0x35800000}, {0x35880000}, {0x35900000}, {0x35980000},
+ {0x35a00000}, {0x35a80000}, {0x35b00000}, {0x35b80000},
+ {0x35c00000}, {0x35c80000}, {0x35d00000}, {0x35d80000},
+ {0x35e00000}, {0x35e80000}, {0x35f00000}, {0x35f80000},
+ {0x36000000}, {0x36040000}, {0x36080000}, {0x360c0000},
+ {0x36100000}, {0x36140000}, {0x36180000}, {0x361c0000},
+ {0x36200000}, {0x36240000}, {0x36280000}, {0x362c0000},
+ {0x36300000}, {0x36340000}, {0x36380000}, {0x363c0000},
+ {0x36400000}, {0x36440000}, {0x36480000}, {0x364c0000},
+ {0x36500000}, {0x36540000}, {0x36580000}, {0x365c0000},
+ {0x36600000}, {0x36640000}, {0x36680000}, {0x366c0000},
+ {0x36700000}, {0x36740000}, {0x36780000}, {0x367c0000},
+ {0x36800000}, {0x36820000}, {0x36840000}, {0x36860000},
+ {0x36880000}, {0x368a0000}, {0x368c0000}, {0x368e0000},
+ {0x36900000}, {0x36920000}, {0x36940000}, {0x36960000},
+ {0x36980000}, {0x369a0000}, {0x369c0000}, {0x369e0000},
+ {0x36a00000}, {0x36a20000}, {0x36a40000}, {0x36a60000},
+ {0x36a80000}, {0x36aa0000}, {0x36ac0000}, {0x36ae0000},
+ {0x36b00000}, {0x36b20000}, {0x36b40000}, {0x36b60000},
+ {0x36b80000}, {0x36ba0000}, {0x36bc0000}, {0x36be0000},
+ {0x36c00000}, {0x36c20000}, {0x36c40000}, {0x36c60000},
+ {0x36c80000}, {0x36ca0000}, {0x36cc0000}, {0x36ce0000},
+ {0x36d00000}, {0x36d20000}, {0x36d40000}, {0x36d60000},
+ {0x36d80000}, {0x36da0000}, {0x36dc0000}, {0x36de0000},
+ {0x36e00000}, {0x36e20000}, {0x36e40000}, {0x36e60000},
+ {0x36e80000}, {0x36ea0000}, {0x36ec0000}, {0x36ee0000},
+ {0x36f00000}, {0x36f20000}, {0x36f40000}, {0x36f60000},
+ {0x36f80000}, {0x36fa0000}, {0x36fc0000}, {0x36fe0000},
+ {0x37000000}, {0x37010000}, {0x37020000}, {0x37030000},
+ {0x37040000}, {0x37050000}, {0x37060000}, {0x37070000},
+ {0x37080000}, {0x37090000}, {0x370a0000}, {0x370b0000},
+ {0x370c0000}, {0x370d0000}, {0x370e0000}, {0x370f0000},
+ {0x37100000}, {0x37110000}, {0x37120000}, {0x37130000},
+ {0x37140000}, {0x37150000}, {0x37160000}, {0x37170000},
+ {0x37180000}, {0x37190000}, {0x371a0000}, {0x371b0000},
+ {0x371c0000}, {0x371d0000}, {0x371e0000}, {0x371f0000},
+ {0x37200000}, {0x37210000}, {0x37220000}, {0x37230000},
+ {0x37240000}, {0x37250000}, {0x37260000}, {0x37270000},
+ {0x37280000}, {0x37290000}, {0x372a0000}, {0x372b0000},
+ {0x372c0000}, {0x372d0000}, {0x372e0000}, {0x372f0000},
+ {0x37300000}, {0x37310000}, {0x37320000}, {0x37330000},
+ {0x37340000}, {0x37350000}, {0x37360000}, {0x37370000},
+ {0x37380000}, {0x37390000}, {0x373a0000}, {0x373b0000},
+ {0x373c0000}, {0x373d0000}, {0x373e0000}, {0x373f0000},
+ {0x37400000}, {0x37410000}, {0x37420000}, {0x37430000},
+ {0x37440000}, {0x37450000}, {0x37460000}, {0x37470000},
+ {0x37480000}, {0x37490000}, {0x374a0000}, {0x374b0000},
+ {0x374c0000}, {0x374d0000}, {0x374e0000}, {0x374f0000},
+ {0x37500000}, {0x37510000}, {0x37520000}, {0x37530000},
+ {0x37540000}, {0x37550000}, {0x37560000}, {0x37570000},
+ {0x37580000}, {0x37590000}, {0x375a0000}, {0x375b0000},
+ {0x375c0000}, {0x375d0000}, {0x375e0000}, {0x375f0000},
+ {0x37600000}, {0x37610000}, {0x37620000}, {0x37630000},
+ {0x37640000}, {0x37650000}, {0x37660000}, {0x37670000},
+ {0x37680000}, {0x37690000}, {0x376a0000}, {0x376b0000},
+ {0x376c0000}, {0x376d0000}, {0x376e0000}, {0x376f0000},
+ {0x37700000}, {0x37710000}, {0x37720000}, {0x37730000},
+ {0x37740000}, {0x37750000}, {0x37760000}, {0x37770000},
+ {0x37780000}, {0x37790000}, {0x377a0000}, {0x377b0000},
+ {0x377c0000}, {0x377d0000}, {0x377e0000}, {0x377f0000},
+ {0x37800000}, {0x37808000}, {0x37810000}, {0x37818000},
+ {0x37820000}, {0x37828000}, {0x37830000}, {0x37838000},
+ {0x37840000}, {0x37848000}, {0x37850000}, {0x37858000},
+ {0x37860000}, {0x37868000}, {0x37870000}, {0x37878000},
+ {0x37880000}, {0x37888000}, {0x37890000}, {0x37898000},
+ {0x378a0000}, {0x378a8000}, {0x378b0000}, {0x378b8000},
+ {0x378c0000}, {0x378c8000}, {0x378d0000}, {0x378d8000},
+ {0x378e0000}, {0x378e8000}, {0x378f0000}, {0x378f8000},
+ {0x37900000}, {0x37908000}, {0x37910000}, {0x37918000},
+ {0x37920000}, {0x37928000}, {0x37930000}, {0x37938000},
+ {0x37940000}, {0x37948000}, {0x37950000}, {0x37958000},
+ {0x37960000}, {0x37968000}, {0x37970000}, {0x37978000},
+ {0x37980000}, {0x37988000}, {0x37990000}, {0x37998000},
+ {0x379a0000}, {0x379a8000}, {0x379b0000}, {0x379b8000},
+ {0x379c0000}, {0x379c8000}, {0x379d0000}, {0x379d8000},
+ {0x379e0000}, {0x379e8000}, {0x379f0000}, {0x379f8000},
+ {0x37a00000}, {0x37a08000}, {0x37a10000}, {0x37a18000},
+ {0x37a20000}, {0x37a28000}, {0x37a30000}, {0x37a38000},
+ {0x37a40000}, {0x37a48000}, {0x37a50000}, {0x37a58000},
+ {0x37a60000}, {0x37a68000}, {0x37a70000}, {0x37a78000},
+ {0x37a80000}, {0x37a88000}, {0x37a90000}, {0x37a98000},
+ {0x37aa0000}, {0x37aa8000}, {0x37ab0000}, {0x37ab8000},
+ {0x37ac0000}, {0x37ac8000}, {0x37ad0000}, {0x37ad8000},
+ {0x37ae0000}, {0x37ae8000}, {0x37af0000}, {0x37af8000},
+ {0x37b00000}, {0x37b08000}, {0x37b10000}, {0x37b18000},
+ {0x37b20000}, {0x37b28000}, {0x37b30000}, {0x37b38000},
+ {0x37b40000}, {0x37b48000}, {0x37b50000}, {0x37b58000},
+ {0x37b60000}, {0x37b68000}, {0x37b70000}, {0x37b78000},
+ {0x37b80000}, {0x37b88000}, {0x37b90000}, {0x37b98000},
+ {0x37ba0000}, {0x37ba8000}, {0x37bb0000}, {0x37bb8000},
+ {0x37bc0000}, {0x37bc8000}, {0x37bd0000}, {0x37bd8000},
+ {0x37be0000}, {0x37be8000}, {0x37bf0000}, {0x37bf8000},
+ {0x37c00000}, {0x37c08000}, {0x37c10000}, {0x37c18000},
+ {0x37c20000}, {0x37c28000}, {0x37c30000}, {0x37c38000},
+ {0x37c40000}, {0x37c48000}, {0x37c50000}, {0x37c58000},
+ {0x37c60000}, {0x37c68000}, {0x37c70000}, {0x37c78000},
+ {0x37c80000}, {0x37c88000}, {0x37c90000}, {0x37c98000},
+ {0x37ca0000}, {0x37ca8000}, {0x37cb0000}, {0x37cb8000},
+ {0x37cc0000}, {0x37cc8000}, {0x37cd0000}, {0x37cd8000},
+ {0x37ce0000}, {0x37ce8000}, {0x37cf0000}, {0x37cf8000},
+ {0x37d00000}, {0x37d08000}, {0x37d10000}, {0x37d18000},
+ {0x37d20000}, {0x37d28000}, {0x37d30000}, {0x37d38000},
+ {0x37d40000}, {0x37d48000}, {0x37d50000}, {0x37d58000},
+ {0x37d60000}, {0x37d68000}, {0x37d70000}, {0x37d78000},
+ {0x37d80000}, {0x37d88000}, {0x37d90000}, {0x37d98000},
+ {0x37da0000}, {0x37da8000}, {0x37db0000}, {0x37db8000},
+ {0x37dc0000}, {0x37dc8000}, {0x37dd0000}, {0x37dd8000},
+ {0x37de0000}, {0x37de8000}, {0x37df0000}, {0x37df8000},
+ {0x37e00000}, {0x37e08000}, {0x37e10000}, {0x37e18000},
+ {0x37e20000}, {0x37e28000}, {0x37e30000}, {0x37e38000},
+ {0x37e40000}, {0x37e48000}, {0x37e50000}, {0x37e58000},
+ {0x37e60000}, {0x37e68000}, {0x37e70000}, {0x37e78000},
+ {0x37e80000}, {0x37e88000}, {0x37e90000}, {0x37e98000},
+ {0x37ea0000}, {0x37ea8000}, {0x37eb0000}, {0x37eb8000},
+ {0x37ec0000}, {0x37ec8000}, {0x37ed0000}, {0x37ed8000},
+ {0x37ee0000}, {0x37ee8000}, {0x37ef0000}, {0x37ef8000},
+ {0x37f00000}, {0x37f08000}, {0x37f10000}, {0x37f18000},
+ {0x37f20000}, {0x37f28000}, {0x37f30000}, {0x37f38000},
+ {0x37f40000}, {0x37f48000}, {0x37f50000}, {0x37f58000},
+ {0x37f60000}, {0x37f68000}, {0x37f70000}, {0x37f78000},
+ {0x37f80000}, {0x37f88000}, {0x37f90000}, {0x37f98000},
+ {0x37fa0000}, {0x37fa8000}, {0x37fb0000}, {0x37fb8000},
+ {0x37fc0000}, {0x37fc8000}, {0x37fd0000}, {0x37fd8000},
+ {0x37fe0000}, {0x37fe8000}, {0x37ff0000}, {0x37ff8000},
+ {0x38000000}, {0x38004000}, {0x38008000}, {0x3800c000},
+ {0x38010000}, {0x38014000}, {0x38018000}, {0x3801c000},
+ {0x38020000}, {0x38024000}, {0x38028000}, {0x3802c000},
+ {0x38030000}, {0x38034000}, {0x38038000}, {0x3803c000},
+ {0x38040000}, {0x38044000}, {0x38048000}, {0x3804c000},
+ {0x38050000}, {0x38054000}, {0x38058000}, {0x3805c000},
+ {0x38060000}, {0x38064000}, {0x38068000}, {0x3806c000},
+ {0x38070000}, {0x38074000}, {0x38078000}, {0x3807c000},
+ {0x38080000}, {0x38084000}, {0x38088000}, {0x3808c000},
+ {0x38090000}, {0x38094000}, {0x38098000}, {0x3809c000},
+ {0x380a0000}, {0x380a4000}, {0x380a8000}, {0x380ac000},
+ {0x380b0000}, {0x380b4000}, {0x380b8000}, {0x380bc000},
+ {0x380c0000}, {0x380c4000}, {0x380c8000}, {0x380cc000},
+ {0x380d0000}, {0x380d4000}, {0x380d8000}, {0x380dc000},
+ {0x380e0000}, {0x380e4000}, {0x380e8000}, {0x380ec000},
+ {0x380f0000}, {0x380f4000}, {0x380f8000}, {0x380fc000},
+ {0x38100000}, {0x38104000}, {0x38108000}, {0x3810c000},
+ {0x38110000}, {0x38114000}, {0x38118000}, {0x3811c000},
+ {0x38120000}, {0x38124000}, {0x38128000}, {0x3812c000},
+ {0x38130000}, {0x38134000}, {0x38138000}, {0x3813c000},
+ {0x38140000}, {0x38144000}, {0x38148000}, {0x3814c000},
+ {0x38150000}, {0x38154000}, {0x38158000}, {0x3815c000},
+ {0x38160000}, {0x38164000}, {0x38168000}, {0x3816c000},
+ {0x38170000}, {0x38174000}, {0x38178000}, {0x3817c000},
+ {0x38180000}, {0x38184000}, {0x38188000}, {0x3818c000},
+ {0x38190000}, {0x38194000}, {0x38198000}, {0x3819c000},
+ {0x381a0000}, {0x381a4000}, {0x381a8000}, {0x381ac000},
+ {0x381b0000}, {0x381b4000}, {0x381b8000}, {0x381bc000},
+ {0x381c0000}, {0x381c4000}, {0x381c8000}, {0x381cc000},
+ {0x381d0000}, {0x381d4000}, {0x381d8000}, {0x381dc000},
+ {0x381e0000}, {0x381e4000}, {0x381e8000}, {0x381ec000},
+ {0x381f0000}, {0x381f4000}, {0x381f8000}, {0x381fc000},
+ {0x38200000}, {0x38204000}, {0x38208000}, {0x3820c000},
+ {0x38210000}, {0x38214000}, {0x38218000}, {0x3821c000},
+ {0x38220000}, {0x38224000}, {0x38228000}, {0x3822c000},
+ {0x38230000}, {0x38234000}, {0x38238000}, {0x3823c000},
+ {0x38240000}, {0x38244000}, {0x38248000}, {0x3824c000},
+ {0x38250000}, {0x38254000}, {0x38258000}, {0x3825c000},
+ {0x38260000}, {0x38264000}, {0x38268000}, {0x3826c000},
+ {0x38270000}, {0x38274000}, {0x38278000}, {0x3827c000},
+ {0x38280000}, {0x38284000}, {0x38288000}, {0x3828c000},
+ {0x38290000}, {0x38294000}, {0x38298000}, {0x3829c000},
+ {0x382a0000}, {0x382a4000}, {0x382a8000}, {0x382ac000},
+ {0x382b0000}, {0x382b4000}, {0x382b8000}, {0x382bc000},
+ {0x382c0000}, {0x382c4000}, {0x382c8000}, {0x382cc000},
+ {0x382d0000}, {0x382d4000}, {0x382d8000}, {0x382dc000},
+ {0x382e0000}, {0x382e4000}, {0x382e8000}, {0x382ec000},
+ {0x382f0000}, {0x382f4000}, {0x382f8000}, {0x382fc000},
+ {0x38300000}, {0x38304000}, {0x38308000}, {0x3830c000},
+ {0x38310000}, {0x38314000}, {0x38318000}, {0x3831c000},
+ {0x38320000}, {0x38324000}, {0x38328000}, {0x3832c000},
+ {0x38330000}, {0x38334000}, {0x38338000}, {0x3833c000},
+ {0x38340000}, {0x38344000}, {0x38348000}, {0x3834c000},
+ {0x38350000}, {0x38354000}, {0x38358000}, {0x3835c000},
+ {0x38360000}, {0x38364000}, {0x38368000}, {0x3836c000},
+ {0x38370000}, {0x38374000}, {0x38378000}, {0x3837c000},
+ {0x38380000}, {0x38384000}, {0x38388000}, {0x3838c000},
+ {0x38390000}, {0x38394000}, {0x38398000}, {0x3839c000},
+ {0x383a0000}, {0x383a4000}, {0x383a8000}, {0x383ac000},
+ {0x383b0000}, {0x383b4000}, {0x383b8000}, {0x383bc000},
+ {0x383c0000}, {0x383c4000}, {0x383c8000}, {0x383cc000},
+ {0x383d0000}, {0x383d4000}, {0x383d8000}, {0x383dc000},
+ {0x383e0000}, {0x383e4000}, {0x383e8000}, {0x383ec000},
+ {0x383f0000}, {0x383f4000}, {0x383f8000}, {0x383fc000},
+ {0x38400000}, {0x38404000}, {0x38408000}, {0x3840c000},
+ {0x38410000}, {0x38414000}, {0x38418000}, {0x3841c000},
+ {0x38420000}, {0x38424000}, {0x38428000}, {0x3842c000},
+ {0x38430000}, {0x38434000}, {0x38438000}, {0x3843c000},
+ {0x38440000}, {0x38444000}, {0x38448000}, {0x3844c000},
+ {0x38450000}, {0x38454000}, {0x38458000}, {0x3845c000},
+ {0x38460000}, {0x38464000}, {0x38468000}, {0x3846c000},
+ {0x38470000}, {0x38474000}, {0x38478000}, {0x3847c000},
+ {0x38480000}, {0x38484000}, {0x38488000}, {0x3848c000},
+ {0x38490000}, {0x38494000}, {0x38498000}, {0x3849c000},
+ {0x384a0000}, {0x384a4000}, {0x384a8000}, {0x384ac000},
+ {0x384b0000}, {0x384b4000}, {0x384b8000}, {0x384bc000},
+ {0x384c0000}, {0x384c4000}, {0x384c8000}, {0x384cc000},
+ {0x384d0000}, {0x384d4000}, {0x384d8000}, {0x384dc000},
+ {0x384e0000}, {0x384e4000}, {0x384e8000}, {0x384ec000},
+ {0x384f0000}, {0x384f4000}, {0x384f8000}, {0x384fc000},
+ {0x38500000}, {0x38504000}, {0x38508000}, {0x3850c000},
+ {0x38510000}, {0x38514000}, {0x38518000}, {0x3851c000},
+ {0x38520000}, {0x38524000}, {0x38528000}, {0x3852c000},
+ {0x38530000}, {0x38534000}, {0x38538000}, {0x3853c000},
+ {0x38540000}, {0x38544000}, {0x38548000}, {0x3854c000},
+ {0x38550000}, {0x38554000}, {0x38558000}, {0x3855c000},
+ {0x38560000}, {0x38564000}, {0x38568000}, {0x3856c000},
+ {0x38570000}, {0x38574000}, {0x38578000}, {0x3857c000},
+ {0x38580000}, {0x38584000}, {0x38588000}, {0x3858c000},
+ {0x38590000}, {0x38594000}, {0x38598000}, {0x3859c000},
+ {0x385a0000}, {0x385a4000}, {0x385a8000}, {0x385ac000},
+ {0x385b0000}, {0x385b4000}, {0x385b8000}, {0x385bc000},
+ {0x385c0000}, {0x385c4000}, {0x385c8000}, {0x385cc000},
+ {0x385d0000}, {0x385d4000}, {0x385d8000}, {0x385dc000},
+ {0x385e0000}, {0x385e4000}, {0x385e8000}, {0x385ec000},
+ {0x385f0000}, {0x385f4000}, {0x385f8000}, {0x385fc000},
+ {0x38600000}, {0x38604000}, {0x38608000}, {0x3860c000},
+ {0x38610000}, {0x38614000}, {0x38618000}, {0x3861c000},
+ {0x38620000}, {0x38624000}, {0x38628000}, {0x3862c000},
+ {0x38630000}, {0x38634000}, {0x38638000}, {0x3863c000},
+ {0x38640000}, {0x38644000}, {0x38648000}, {0x3864c000},
+ {0x38650000}, {0x38654000}, {0x38658000}, {0x3865c000},
+ {0x38660000}, {0x38664000}, {0x38668000}, {0x3866c000},
+ {0x38670000}, {0x38674000}, {0x38678000}, {0x3867c000},
+ {0x38680000}, {0x38684000}, {0x38688000}, {0x3868c000},
+ {0x38690000}, {0x38694000}, {0x38698000}, {0x3869c000},
+ {0x386a0000}, {0x386a4000}, {0x386a8000}, {0x386ac000},
+ {0x386b0000}, {0x386b4000}, {0x386b8000}, {0x386bc000},
+ {0x386c0000}, {0x386c4000}, {0x386c8000}, {0x386cc000},
+ {0x386d0000}, {0x386d4000}, {0x386d8000}, {0x386dc000},
+ {0x386e0000}, {0x386e4000}, {0x386e8000}, {0x386ec000},
+ {0x386f0000}, {0x386f4000}, {0x386f8000}, {0x386fc000},
+ {0x38700000}, {0x38704000}, {0x38708000}, {0x3870c000},
+ {0x38710000}, {0x38714000}, {0x38718000}, {0x3871c000},
+ {0x38720000}, {0x38724000}, {0x38728000}, {0x3872c000},
+ {0x38730000}, {0x38734000}, {0x38738000}, {0x3873c000},
+ {0x38740000}, {0x38744000}, {0x38748000}, {0x3874c000},
+ {0x38750000}, {0x38754000}, {0x38758000}, {0x3875c000},
+ {0x38760000}, {0x38764000}, {0x38768000}, {0x3876c000},
+ {0x38770000}, {0x38774000}, {0x38778000}, {0x3877c000},
+ {0x38780000}, {0x38784000}, {0x38788000}, {0x3878c000},
+ {0x38790000}, {0x38794000}, {0x38798000}, {0x3879c000},
+ {0x387a0000}, {0x387a4000}, {0x387a8000}, {0x387ac000},
+ {0x387b0000}, {0x387b4000}, {0x387b8000}, {0x387bc000},
+ {0x387c0000}, {0x387c4000}, {0x387c8000}, {0x387cc000},
+ {0x387d0000}, {0x387d4000}, {0x387d8000}, {0x387dc000},
+ {0x387e0000}, {0x387e4000}, {0x387e8000}, {0x387ec000},
+ {0x387f0000}, {0x387f4000}, {0x387f8000}, {0x387fc000},
+ {0x38800000}, {0x38802000}, {0x38804000}, {0x38806000},
+ {0x38808000}, {0x3880a000}, {0x3880c000}, {0x3880e000},
+ {0x38810000}, {0x38812000}, {0x38814000}, {0x38816000},
+ {0x38818000}, {0x3881a000}, {0x3881c000}, {0x3881e000},
+ {0x38820000}, {0x38822000}, {0x38824000}, {0x38826000},
+ {0x38828000}, {0x3882a000}, {0x3882c000}, {0x3882e000},
+ {0x38830000}, {0x38832000}, {0x38834000}, {0x38836000},
+ {0x38838000}, {0x3883a000}, {0x3883c000}, {0x3883e000},
+ {0x38840000}, {0x38842000}, {0x38844000}, {0x38846000},
+ {0x38848000}, {0x3884a000}, {0x3884c000}, {0x3884e000},
+ {0x38850000}, {0x38852000}, {0x38854000}, {0x38856000},
+ {0x38858000}, {0x3885a000}, {0x3885c000}, {0x3885e000},
+ {0x38860000}, {0x38862000}, {0x38864000}, {0x38866000},
+ {0x38868000}, {0x3886a000}, {0x3886c000}, {0x3886e000},
+ {0x38870000}, {0x38872000}, {0x38874000}, {0x38876000},
+ {0x38878000}, {0x3887a000}, {0x3887c000}, {0x3887e000},
+ {0x38880000}, {0x38882000}, {0x38884000}, {0x38886000},
+ {0x38888000}, {0x3888a000}, {0x3888c000}, {0x3888e000},
+ {0x38890000}, {0x38892000}, {0x38894000}, {0x38896000},
+ {0x38898000}, {0x3889a000}, {0x3889c000}, {0x3889e000},
+ {0x388a0000}, {0x388a2000}, {0x388a4000}, {0x388a6000},
+ {0x388a8000}, {0x388aa000}, {0x388ac000}, {0x388ae000},
+ {0x388b0000}, {0x388b2000}, {0x388b4000}, {0x388b6000},
+ {0x388b8000}, {0x388ba000}, {0x388bc000}, {0x388be000},
+ {0x388c0000}, {0x388c2000}, {0x388c4000}, {0x388c6000},
+ {0x388c8000}, {0x388ca000}, {0x388cc000}, {0x388ce000},
+ {0x388d0000}, {0x388d2000}, {0x388d4000}, {0x388d6000},
+ {0x388d8000}, {0x388da000}, {0x388dc000}, {0x388de000},
+ {0x388e0000}, {0x388e2000}, {0x388e4000}, {0x388e6000},
+ {0x388e8000}, {0x388ea000}, {0x388ec000}, {0x388ee000},
+ {0x388f0000}, {0x388f2000}, {0x388f4000}, {0x388f6000},
+ {0x388f8000}, {0x388fa000}, {0x388fc000}, {0x388fe000},
+ {0x38900000}, {0x38902000}, {0x38904000}, {0x38906000},
+ {0x38908000}, {0x3890a000}, {0x3890c000}, {0x3890e000},
+ {0x38910000}, {0x38912000}, {0x38914000}, {0x38916000},
+ {0x38918000}, {0x3891a000}, {0x3891c000}, {0x3891e000},
+ {0x38920000}, {0x38922000}, {0x38924000}, {0x38926000},
+ {0x38928000}, {0x3892a000}, {0x3892c000}, {0x3892e000},
+ {0x38930000}, {0x38932000}, {0x38934000}, {0x38936000},
+ {0x38938000}, {0x3893a000}, {0x3893c000}, {0x3893e000},
+ {0x38940000}, {0x38942000}, {0x38944000}, {0x38946000},
+ {0x38948000}, {0x3894a000}, {0x3894c000}, {0x3894e000},
+ {0x38950000}, {0x38952000}, {0x38954000}, {0x38956000},
+ {0x38958000}, {0x3895a000}, {0x3895c000}, {0x3895e000},
+ {0x38960000}, {0x38962000}, {0x38964000}, {0x38966000},
+ {0x38968000}, {0x3896a000}, {0x3896c000}, {0x3896e000},
+ {0x38970000}, {0x38972000}, {0x38974000}, {0x38976000},
+ {0x38978000}, {0x3897a000}, {0x3897c000}, {0x3897e000},
+ {0x38980000}, {0x38982000}, {0x38984000}, {0x38986000},
+ {0x38988000}, {0x3898a000}, {0x3898c000}, {0x3898e000},
+ {0x38990000}, {0x38992000}, {0x38994000}, {0x38996000},
+ {0x38998000}, {0x3899a000}, {0x3899c000}, {0x3899e000},
+ {0x389a0000}, {0x389a2000}, {0x389a4000}, {0x389a6000},
+ {0x389a8000}, {0x389aa000}, {0x389ac000}, {0x389ae000},
+ {0x389b0000}, {0x389b2000}, {0x389b4000}, {0x389b6000},
+ {0x389b8000}, {0x389ba000}, {0x389bc000}, {0x389be000},
+ {0x389c0000}, {0x389c2000}, {0x389c4000}, {0x389c6000},
+ {0x389c8000}, {0x389ca000}, {0x389cc000}, {0x389ce000},
+ {0x389d0000}, {0x389d2000}, {0x389d4000}, {0x389d6000},
+ {0x389d8000}, {0x389da000}, {0x389dc000}, {0x389de000},
+ {0x389e0000}, {0x389e2000}, {0x389e4000}, {0x389e6000},
+ {0x389e8000}, {0x389ea000}, {0x389ec000}, {0x389ee000},
+ {0x389f0000}, {0x389f2000}, {0x389f4000}, {0x389f6000},
+ {0x389f8000}, {0x389fa000}, {0x389fc000}, {0x389fe000},
+ {0x38a00000}, {0x38a02000}, {0x38a04000}, {0x38a06000},
+ {0x38a08000}, {0x38a0a000}, {0x38a0c000}, {0x38a0e000},
+ {0x38a10000}, {0x38a12000}, {0x38a14000}, {0x38a16000},
+ {0x38a18000}, {0x38a1a000}, {0x38a1c000}, {0x38a1e000},
+ {0x38a20000}, {0x38a22000}, {0x38a24000}, {0x38a26000},
+ {0x38a28000}, {0x38a2a000}, {0x38a2c000}, {0x38a2e000},
+ {0x38a30000}, {0x38a32000}, {0x38a34000}, {0x38a36000},
+ {0x38a38000}, {0x38a3a000}, {0x38a3c000}, {0x38a3e000},
+ {0x38a40000}, {0x38a42000}, {0x38a44000}, {0x38a46000},
+ {0x38a48000}, {0x38a4a000}, {0x38a4c000}, {0x38a4e000},
+ {0x38a50000}, {0x38a52000}, {0x38a54000}, {0x38a56000},
+ {0x38a58000}, {0x38a5a000}, {0x38a5c000}, {0x38a5e000},
+ {0x38a60000}, {0x38a62000}, {0x38a64000}, {0x38a66000},
+ {0x38a68000}, {0x38a6a000}, {0x38a6c000}, {0x38a6e000},
+ {0x38a70000}, {0x38a72000}, {0x38a74000}, {0x38a76000},
+ {0x38a78000}, {0x38a7a000}, {0x38a7c000}, {0x38a7e000},
+ {0x38a80000}, {0x38a82000}, {0x38a84000}, {0x38a86000},
+ {0x38a88000}, {0x38a8a000}, {0x38a8c000}, {0x38a8e000},
+ {0x38a90000}, {0x38a92000}, {0x38a94000}, {0x38a96000},
+ {0x38a98000}, {0x38a9a000}, {0x38a9c000}, {0x38a9e000},
+ {0x38aa0000}, {0x38aa2000}, {0x38aa4000}, {0x38aa6000},
+ {0x38aa8000}, {0x38aaa000}, {0x38aac000}, {0x38aae000},
+ {0x38ab0000}, {0x38ab2000}, {0x38ab4000}, {0x38ab6000},
+ {0x38ab8000}, {0x38aba000}, {0x38abc000}, {0x38abe000},
+ {0x38ac0000}, {0x38ac2000}, {0x38ac4000}, {0x38ac6000},
+ {0x38ac8000}, {0x38aca000}, {0x38acc000}, {0x38ace000},
+ {0x38ad0000}, {0x38ad2000}, {0x38ad4000}, {0x38ad6000},
+ {0x38ad8000}, {0x38ada000}, {0x38adc000}, {0x38ade000},
+ {0x38ae0000}, {0x38ae2000}, {0x38ae4000}, {0x38ae6000},
+ {0x38ae8000}, {0x38aea000}, {0x38aec000}, {0x38aee000},
+ {0x38af0000}, {0x38af2000}, {0x38af4000}, {0x38af6000},
+ {0x38af8000}, {0x38afa000}, {0x38afc000}, {0x38afe000},
+ {0x38b00000}, {0x38b02000}, {0x38b04000}, {0x38b06000},
+ {0x38b08000}, {0x38b0a000}, {0x38b0c000}, {0x38b0e000},
+ {0x38b10000}, {0x38b12000}, {0x38b14000}, {0x38b16000},
+ {0x38b18000}, {0x38b1a000}, {0x38b1c000}, {0x38b1e000},
+ {0x38b20000}, {0x38b22000}, {0x38b24000}, {0x38b26000},
+ {0x38b28000}, {0x38b2a000}, {0x38b2c000}, {0x38b2e000},
+ {0x38b30000}, {0x38b32000}, {0x38b34000}, {0x38b36000},
+ {0x38b38000}, {0x38b3a000}, {0x38b3c000}, {0x38b3e000},
+ {0x38b40000}, {0x38b42000}, {0x38b44000}, {0x38b46000},
+ {0x38b48000}, {0x38b4a000}, {0x38b4c000}, {0x38b4e000},
+ {0x38b50000}, {0x38b52000}, {0x38b54000}, {0x38b56000},
+ {0x38b58000}, {0x38b5a000}, {0x38b5c000}, {0x38b5e000},
+ {0x38b60000}, {0x38b62000}, {0x38b64000}, {0x38b66000},
+ {0x38b68000}, {0x38b6a000}, {0x38b6c000}, {0x38b6e000},
+ {0x38b70000}, {0x38b72000}, {0x38b74000}, {0x38b76000},
+ {0x38b78000}, {0x38b7a000}, {0x38b7c000}, {0x38b7e000},
+ {0x38b80000}, {0x38b82000}, {0x38b84000}, {0x38b86000},
+ {0x38b88000}, {0x38b8a000}, {0x38b8c000}, {0x38b8e000},
+ {0x38b90000}, {0x38b92000}, {0x38b94000}, {0x38b96000},
+ {0x38b98000}, {0x38b9a000}, {0x38b9c000}, {0x38b9e000},
+ {0x38ba0000}, {0x38ba2000}, {0x38ba4000}, {0x38ba6000},
+ {0x38ba8000}, {0x38baa000}, {0x38bac000}, {0x38bae000},
+ {0x38bb0000}, {0x38bb2000}, {0x38bb4000}, {0x38bb6000},
+ {0x38bb8000}, {0x38bba000}, {0x38bbc000}, {0x38bbe000},
+ {0x38bc0000}, {0x38bc2000}, {0x38bc4000}, {0x38bc6000},
+ {0x38bc8000}, {0x38bca000}, {0x38bcc000}, {0x38bce000},
+ {0x38bd0000}, {0x38bd2000}, {0x38bd4000}, {0x38bd6000},
+ {0x38bd8000}, {0x38bda000}, {0x38bdc000}, {0x38bde000},
+ {0x38be0000}, {0x38be2000}, {0x38be4000}, {0x38be6000},
+ {0x38be8000}, {0x38bea000}, {0x38bec000}, {0x38bee000},
+ {0x38bf0000}, {0x38bf2000}, {0x38bf4000}, {0x38bf6000},
+ {0x38bf8000}, {0x38bfa000}, {0x38bfc000}, {0x38bfe000},
+ {0x38c00000}, {0x38c02000}, {0x38c04000}, {0x38c06000},
+ {0x38c08000}, {0x38c0a000}, {0x38c0c000}, {0x38c0e000},
+ {0x38c10000}, {0x38c12000}, {0x38c14000}, {0x38c16000},
+ {0x38c18000}, {0x38c1a000}, {0x38c1c000}, {0x38c1e000},
+ {0x38c20000}, {0x38c22000}, {0x38c24000}, {0x38c26000},
+ {0x38c28000}, {0x38c2a000}, {0x38c2c000}, {0x38c2e000},
+ {0x38c30000}, {0x38c32000}, {0x38c34000}, {0x38c36000},
+ {0x38c38000}, {0x38c3a000}, {0x38c3c000}, {0x38c3e000},
+ {0x38c40000}, {0x38c42000}, {0x38c44000}, {0x38c46000},
+ {0x38c48000}, {0x38c4a000}, {0x38c4c000}, {0x38c4e000},
+ {0x38c50000}, {0x38c52000}, {0x38c54000}, {0x38c56000},
+ {0x38c58000}, {0x38c5a000}, {0x38c5c000}, {0x38c5e000},
+ {0x38c60000}, {0x38c62000}, {0x38c64000}, {0x38c66000},
+ {0x38c68000}, {0x38c6a000}, {0x38c6c000}, {0x38c6e000},
+ {0x38c70000}, {0x38c72000}, {0x38c74000}, {0x38c76000},
+ {0x38c78000}, {0x38c7a000}, {0x38c7c000}, {0x38c7e000},
+ {0x38c80000}, {0x38c82000}, {0x38c84000}, {0x38c86000},
+ {0x38c88000}, {0x38c8a000}, {0x38c8c000}, {0x38c8e000},
+ {0x38c90000}, {0x38c92000}, {0x38c94000}, {0x38c96000},
+ {0x38c98000}, {0x38c9a000}, {0x38c9c000}, {0x38c9e000},
+ {0x38ca0000}, {0x38ca2000}, {0x38ca4000}, {0x38ca6000},
+ {0x38ca8000}, {0x38caa000}, {0x38cac000}, {0x38cae000},
+ {0x38cb0000}, {0x38cb2000}, {0x38cb4000}, {0x38cb6000},
+ {0x38cb8000}, {0x38cba000}, {0x38cbc000}, {0x38cbe000},
+ {0x38cc0000}, {0x38cc2000}, {0x38cc4000}, {0x38cc6000},
+ {0x38cc8000}, {0x38cca000}, {0x38ccc000}, {0x38cce000},
+ {0x38cd0000}, {0x38cd2000}, {0x38cd4000}, {0x38cd6000},
+ {0x38cd8000}, {0x38cda000}, {0x38cdc000}, {0x38cde000},
+ {0x38ce0000}, {0x38ce2000}, {0x38ce4000}, {0x38ce6000},
+ {0x38ce8000}, {0x38cea000}, {0x38cec000}, {0x38cee000},
+ {0x38cf0000}, {0x38cf2000}, {0x38cf4000}, {0x38cf6000},
+ {0x38cf8000}, {0x38cfa000}, {0x38cfc000}, {0x38cfe000},
+ {0x38d00000}, {0x38d02000}, {0x38d04000}, {0x38d06000},
+ {0x38d08000}, {0x38d0a000}, {0x38d0c000}, {0x38d0e000},
+ {0x38d10000}, {0x38d12000}, {0x38d14000}, {0x38d16000},
+ {0x38d18000}, {0x38d1a000}, {0x38d1c000}, {0x38d1e000},
+ {0x38d20000}, {0x38d22000}, {0x38d24000}, {0x38d26000},
+ {0x38d28000}, {0x38d2a000}, {0x38d2c000}, {0x38d2e000},
+ {0x38d30000}, {0x38d32000}, {0x38d34000}, {0x38d36000},
+ {0x38d38000}, {0x38d3a000}, {0x38d3c000}, {0x38d3e000},
+ {0x38d40000}, {0x38d42000}, {0x38d44000}, {0x38d46000},
+ {0x38d48000}, {0x38d4a000}, {0x38d4c000}, {0x38d4e000},
+ {0x38d50000}, {0x38d52000}, {0x38d54000}, {0x38d56000},
+ {0x38d58000}, {0x38d5a000}, {0x38d5c000}, {0x38d5e000},
+ {0x38d60000}, {0x38d62000}, {0x38d64000}, {0x38d66000},
+ {0x38d68000}, {0x38d6a000}, {0x38d6c000}, {0x38d6e000},
+ {0x38d70000}, {0x38d72000}, {0x38d74000}, {0x38d76000},
+ {0x38d78000}, {0x38d7a000}, {0x38d7c000}, {0x38d7e000},
+ {0x38d80000}, {0x38d82000}, {0x38d84000}, {0x38d86000},
+ {0x38d88000}, {0x38d8a000}, {0x38d8c000}, {0x38d8e000},
+ {0x38d90000}, {0x38d92000}, {0x38d94000}, {0x38d96000},
+ {0x38d98000}, {0x38d9a000}, {0x38d9c000}, {0x38d9e000},
+ {0x38da0000}, {0x38da2000}, {0x38da4000}, {0x38da6000},
+ {0x38da8000}, {0x38daa000}, {0x38dac000}, {0x38dae000},
+ {0x38db0000}, {0x38db2000}, {0x38db4000}, {0x38db6000},
+ {0x38db8000}, {0x38dba000}, {0x38dbc000}, {0x38dbe000},
+ {0x38dc0000}, {0x38dc2000}, {0x38dc4000}, {0x38dc6000},
+ {0x38dc8000}, {0x38dca000}, {0x38dcc000}, {0x38dce000},
+ {0x38dd0000}, {0x38dd2000}, {0x38dd4000}, {0x38dd6000},
+ {0x38dd8000}, {0x38dda000}, {0x38ddc000}, {0x38dde000},
+ {0x38de0000}, {0x38de2000}, {0x38de4000}, {0x38de6000},
+ {0x38de8000}, {0x38dea000}, {0x38dec000}, {0x38dee000},
+ {0x38df0000}, {0x38df2000}, {0x38df4000}, {0x38df6000},
+ {0x38df8000}, {0x38dfa000}, {0x38dfc000}, {0x38dfe000},
+ {0x38e00000}, {0x38e02000}, {0x38e04000}, {0x38e06000},
+ {0x38e08000}, {0x38e0a000}, {0x38e0c000}, {0x38e0e000},
+ {0x38e10000}, {0x38e12000}, {0x38e14000}, {0x38e16000},
+ {0x38e18000}, {0x38e1a000}, {0x38e1c000}, {0x38e1e000},
+ {0x38e20000}, {0x38e22000}, {0x38e24000}, {0x38e26000},
+ {0x38e28000}, {0x38e2a000}, {0x38e2c000}, {0x38e2e000},
+ {0x38e30000}, {0x38e32000}, {0x38e34000}, {0x38e36000},
+ {0x38e38000}, {0x38e3a000}, {0x38e3c000}, {0x38e3e000},
+ {0x38e40000}, {0x38e42000}, {0x38e44000}, {0x38e46000},
+ {0x38e48000}, {0x38e4a000}, {0x38e4c000}, {0x38e4e000},
+ {0x38e50000}, {0x38e52000}, {0x38e54000}, {0x38e56000},
+ {0x38e58000}, {0x38e5a000}, {0x38e5c000}, {0x38e5e000},
+ {0x38e60000}, {0x38e62000}, {0x38e64000}, {0x38e66000},
+ {0x38e68000}, {0x38e6a000}, {0x38e6c000}, {0x38e6e000},
+ {0x38e70000}, {0x38e72000}, {0x38e74000}, {0x38e76000},
+ {0x38e78000}, {0x38e7a000}, {0x38e7c000}, {0x38e7e000},
+ {0x38e80000}, {0x38e82000}, {0x38e84000}, {0x38e86000},
+ {0x38e88000}, {0x38e8a000}, {0x38e8c000}, {0x38e8e000},
+ {0x38e90000}, {0x38e92000}, {0x38e94000}, {0x38e96000},
+ {0x38e98000}, {0x38e9a000}, {0x38e9c000}, {0x38e9e000},
+ {0x38ea0000}, {0x38ea2000}, {0x38ea4000}, {0x38ea6000},
+ {0x38ea8000}, {0x38eaa000}, {0x38eac000}, {0x38eae000},
+ {0x38eb0000}, {0x38eb2000}, {0x38eb4000}, {0x38eb6000},
+ {0x38eb8000}, {0x38eba000}, {0x38ebc000}, {0x38ebe000},
+ {0x38ec0000}, {0x38ec2000}, {0x38ec4000}, {0x38ec6000},
+ {0x38ec8000}, {0x38eca000}, {0x38ecc000}, {0x38ece000},
+ {0x38ed0000}, {0x38ed2000}, {0x38ed4000}, {0x38ed6000},
+ {0x38ed8000}, {0x38eda000}, {0x38edc000}, {0x38ede000},
+ {0x38ee0000}, {0x38ee2000}, {0x38ee4000}, {0x38ee6000},
+ {0x38ee8000}, {0x38eea000}, {0x38eec000}, {0x38eee000},
+ {0x38ef0000}, {0x38ef2000}, {0x38ef4000}, {0x38ef6000},
+ {0x38ef8000}, {0x38efa000}, {0x38efc000}, {0x38efe000},
+ {0x38f00000}, {0x38f02000}, {0x38f04000}, {0x38f06000},
+ {0x38f08000}, {0x38f0a000}, {0x38f0c000}, {0x38f0e000},
+ {0x38f10000}, {0x38f12000}, {0x38f14000}, {0x38f16000},
+ {0x38f18000}, {0x38f1a000}, {0x38f1c000}, {0x38f1e000},
+ {0x38f20000}, {0x38f22000}, {0x38f24000}, {0x38f26000},
+ {0x38f28000}, {0x38f2a000}, {0x38f2c000}, {0x38f2e000},
+ {0x38f30000}, {0x38f32000}, {0x38f34000}, {0x38f36000},
+ {0x38f38000}, {0x38f3a000}, {0x38f3c000}, {0x38f3e000},
+ {0x38f40000}, {0x38f42000}, {0x38f44000}, {0x38f46000},
+ {0x38f48000}, {0x38f4a000}, {0x38f4c000}, {0x38f4e000},
+ {0x38f50000}, {0x38f52000}, {0x38f54000}, {0x38f56000},
+ {0x38f58000}, {0x38f5a000}, {0x38f5c000}, {0x38f5e000},
+ {0x38f60000}, {0x38f62000}, {0x38f64000}, {0x38f66000},
+ {0x38f68000}, {0x38f6a000}, {0x38f6c000}, {0x38f6e000},
+ {0x38f70000}, {0x38f72000}, {0x38f74000}, {0x38f76000},
+ {0x38f78000}, {0x38f7a000}, {0x38f7c000}, {0x38f7e000},
+ {0x38f80000}, {0x38f82000}, {0x38f84000}, {0x38f86000},
+ {0x38f88000}, {0x38f8a000}, {0x38f8c000}, {0x38f8e000},
+ {0x38f90000}, {0x38f92000}, {0x38f94000}, {0x38f96000},
+ {0x38f98000}, {0x38f9a000}, {0x38f9c000}, {0x38f9e000},
+ {0x38fa0000}, {0x38fa2000}, {0x38fa4000}, {0x38fa6000},
+ {0x38fa8000}, {0x38faa000}, {0x38fac000}, {0x38fae000},
+ {0x38fb0000}, {0x38fb2000}, {0x38fb4000}, {0x38fb6000},
+ {0x38fb8000}, {0x38fba000}, {0x38fbc000}, {0x38fbe000},
+ {0x38fc0000}, {0x38fc2000}, {0x38fc4000}, {0x38fc6000},
+ {0x38fc8000}, {0x38fca000}, {0x38fcc000}, {0x38fce000},
+ {0x38fd0000}, {0x38fd2000}, {0x38fd4000}, {0x38fd6000},
+ {0x38fd8000}, {0x38fda000}, {0x38fdc000}, {0x38fde000},
+ {0x38fe0000}, {0x38fe2000}, {0x38fe4000}, {0x38fe6000},
+ {0x38fe8000}, {0x38fea000}, {0x38fec000}, {0x38fee000},
+ {0x38ff0000}, {0x38ff2000}, {0x38ff4000}, {0x38ff6000},
+ {0x38ff8000}, {0x38ffa000}, {0x38ffc000}, {0x38ffe000},
+ {0x39000000}, {0x39002000}, {0x39004000}, {0x39006000},
+ {0x39008000}, {0x3900a000}, {0x3900c000}, {0x3900e000},
+ {0x39010000}, {0x39012000}, {0x39014000}, {0x39016000},
+ {0x39018000}, {0x3901a000}, {0x3901c000}, {0x3901e000},
+ {0x39020000}, {0x39022000}, {0x39024000}, {0x39026000},
+ {0x39028000}, {0x3902a000}, {0x3902c000}, {0x3902e000},
+ {0x39030000}, {0x39032000}, {0x39034000}, {0x39036000},
+ {0x39038000}, {0x3903a000}, {0x3903c000}, {0x3903e000},
+ {0x39040000}, {0x39042000}, {0x39044000}, {0x39046000},
+ {0x39048000}, {0x3904a000}, {0x3904c000}, {0x3904e000},
+ {0x39050000}, {0x39052000}, {0x39054000}, {0x39056000},
+ {0x39058000}, {0x3905a000}, {0x3905c000}, {0x3905e000},
+ {0x39060000}, {0x39062000}, {0x39064000}, {0x39066000},
+ {0x39068000}, {0x3906a000}, {0x3906c000}, {0x3906e000},
+ {0x39070000}, {0x39072000}, {0x39074000}, {0x39076000},
+ {0x39078000}, {0x3907a000}, {0x3907c000}, {0x3907e000},
+ {0x39080000}, {0x39082000}, {0x39084000}, {0x39086000},
+ {0x39088000}, {0x3908a000}, {0x3908c000}, {0x3908e000},
+ {0x39090000}, {0x39092000}, {0x39094000}, {0x39096000},
+ {0x39098000}, {0x3909a000}, {0x3909c000}, {0x3909e000},
+ {0x390a0000}, {0x390a2000}, {0x390a4000}, {0x390a6000},
+ {0x390a8000}, {0x390aa000}, {0x390ac000}, {0x390ae000},
+ {0x390b0000}, {0x390b2000}, {0x390b4000}, {0x390b6000},
+ {0x390b8000}, {0x390ba000}, {0x390bc000}, {0x390be000},
+ {0x390c0000}, {0x390c2000}, {0x390c4000}, {0x390c6000},
+ {0x390c8000}, {0x390ca000}, {0x390cc000}, {0x390ce000},
+ {0x390d0000}, {0x390d2000}, {0x390d4000}, {0x390d6000},
+ {0x390d8000}, {0x390da000}, {0x390dc000}, {0x390de000},
+ {0x390e0000}, {0x390e2000}, {0x390e4000}, {0x390e6000},
+ {0x390e8000}, {0x390ea000}, {0x390ec000}, {0x390ee000},
+ {0x390f0000}, {0x390f2000}, {0x390f4000}, {0x390f6000},
+ {0x390f8000}, {0x390fa000}, {0x390fc000}, {0x390fe000},
+ {0x39100000}, {0x39102000}, {0x39104000}, {0x39106000},
+ {0x39108000}, {0x3910a000}, {0x3910c000}, {0x3910e000},
+ {0x39110000}, {0x39112000}, {0x39114000}, {0x39116000},
+ {0x39118000}, {0x3911a000}, {0x3911c000}, {0x3911e000},
+ {0x39120000}, {0x39122000}, {0x39124000}, {0x39126000},
+ {0x39128000}, {0x3912a000}, {0x3912c000}, {0x3912e000},
+ {0x39130000}, {0x39132000}, {0x39134000}, {0x39136000},
+ {0x39138000}, {0x3913a000}, {0x3913c000}, {0x3913e000},
+ {0x39140000}, {0x39142000}, {0x39144000}, {0x39146000},
+ {0x39148000}, {0x3914a000}, {0x3914c000}, {0x3914e000},
+ {0x39150000}, {0x39152000}, {0x39154000}, {0x39156000},
+ {0x39158000}, {0x3915a000}, {0x3915c000}, {0x3915e000},
+ {0x39160000}, {0x39162000}, {0x39164000}, {0x39166000},
+ {0x39168000}, {0x3916a000}, {0x3916c000}, {0x3916e000},
+ {0x39170000}, {0x39172000}, {0x39174000}, {0x39176000},
+ {0x39178000}, {0x3917a000}, {0x3917c000}, {0x3917e000},
+ {0x39180000}, {0x39182000}, {0x39184000}, {0x39186000},
+ {0x39188000}, {0x3918a000}, {0x3918c000}, {0x3918e000},
+ {0x39190000}, {0x39192000}, {0x39194000}, {0x39196000},
+ {0x39198000}, {0x3919a000}, {0x3919c000}, {0x3919e000},
+ {0x391a0000}, {0x391a2000}, {0x391a4000}, {0x391a6000},
+ {0x391a8000}, {0x391aa000}, {0x391ac000}, {0x391ae000},
+ {0x391b0000}, {0x391b2000}, {0x391b4000}, {0x391b6000},
+ {0x391b8000}, {0x391ba000}, {0x391bc000}, {0x391be000},
+ {0x391c0000}, {0x391c2000}, {0x391c4000}, {0x391c6000},
+ {0x391c8000}, {0x391ca000}, {0x391cc000}, {0x391ce000},
+ {0x391d0000}, {0x391d2000}, {0x391d4000}, {0x391d6000},
+ {0x391d8000}, {0x391da000}, {0x391dc000}, {0x391de000},
+ {0x391e0000}, {0x391e2000}, {0x391e4000}, {0x391e6000},
+ {0x391e8000}, {0x391ea000}, {0x391ec000}, {0x391ee000},
+ {0x391f0000}, {0x391f2000}, {0x391f4000}, {0x391f6000},
+ {0x391f8000}, {0x391fa000}, {0x391fc000}, {0x391fe000},
+ {0x39200000}, {0x39202000}, {0x39204000}, {0x39206000},
+ {0x39208000}, {0x3920a000}, {0x3920c000}, {0x3920e000},
+ {0x39210000}, {0x39212000}, {0x39214000}, {0x39216000},
+ {0x39218000}, {0x3921a000}, {0x3921c000}, {0x3921e000},
+ {0x39220000}, {0x39222000}, {0x39224000}, {0x39226000},
+ {0x39228000}, {0x3922a000}, {0x3922c000}, {0x3922e000},
+ {0x39230000}, {0x39232000}, {0x39234000}, {0x39236000},
+ {0x39238000}, {0x3923a000}, {0x3923c000}, {0x3923e000},
+ {0x39240000}, {0x39242000}, {0x39244000}, {0x39246000},
+ {0x39248000}, {0x3924a000}, {0x3924c000}, {0x3924e000},
+ {0x39250000}, {0x39252000}, {0x39254000}, {0x39256000},
+ {0x39258000}, {0x3925a000}, {0x3925c000}, {0x3925e000},
+ {0x39260000}, {0x39262000}, {0x39264000}, {0x39266000},
+ {0x39268000}, {0x3926a000}, {0x3926c000}, {0x3926e000},
+ {0x39270000}, {0x39272000}, {0x39274000}, {0x39276000},
+ {0x39278000}, {0x3927a000}, {0x3927c000}, {0x3927e000},
+ {0x39280000}, {0x39282000}, {0x39284000}, {0x39286000},
+ {0x39288000}, {0x3928a000}, {0x3928c000}, {0x3928e000},
+ {0x39290000}, {0x39292000}, {0x39294000}, {0x39296000},
+ {0x39298000}, {0x3929a000}, {0x3929c000}, {0x3929e000},
+ {0x392a0000}, {0x392a2000}, {0x392a4000}, {0x392a6000},
+ {0x392a8000}, {0x392aa000}, {0x392ac000}, {0x392ae000},
+ {0x392b0000}, {0x392b2000}, {0x392b4000}, {0x392b6000},
+ {0x392b8000}, {0x392ba000}, {0x392bc000}, {0x392be000},
+ {0x392c0000}, {0x392c2000}, {0x392c4000}, {0x392c6000},
+ {0x392c8000}, {0x392ca000}, {0x392cc000}, {0x392ce000},
+ {0x392d0000}, {0x392d2000}, {0x392d4000}, {0x392d6000},
+ {0x392d8000}, {0x392da000}, {0x392dc000}, {0x392de000},
+ {0x392e0000}, {0x392e2000}, {0x392e4000}, {0x392e6000},
+ {0x392e8000}, {0x392ea000}, {0x392ec000}, {0x392ee000},
+ {0x392f0000}, {0x392f2000}, {0x392f4000}, {0x392f6000},
+ {0x392f8000}, {0x392fa000}, {0x392fc000}, {0x392fe000},
+ {0x39300000}, {0x39302000}, {0x39304000}, {0x39306000},
+ {0x39308000}, {0x3930a000}, {0x3930c000}, {0x3930e000},
+ {0x39310000}, {0x39312000}, {0x39314000}, {0x39316000},
+ {0x39318000}, {0x3931a000}, {0x3931c000}, {0x3931e000},
+ {0x39320000}, {0x39322000}, {0x39324000}, {0x39326000},
+ {0x39328000}, {0x3932a000}, {0x3932c000}, {0x3932e000},
+ {0x39330000}, {0x39332000}, {0x39334000}, {0x39336000},
+ {0x39338000}, {0x3933a000}, {0x3933c000}, {0x3933e000},
+ {0x39340000}, {0x39342000}, {0x39344000}, {0x39346000},
+ {0x39348000}, {0x3934a000}, {0x3934c000}, {0x3934e000},
+ {0x39350000}, {0x39352000}, {0x39354000}, {0x39356000},
+ {0x39358000}, {0x3935a000}, {0x3935c000}, {0x3935e000},
+ {0x39360000}, {0x39362000}, {0x39364000}, {0x39366000},
+ {0x39368000}, {0x3936a000}, {0x3936c000}, {0x3936e000},
+ {0x39370000}, {0x39372000}, {0x39374000}, {0x39376000},
+ {0x39378000}, {0x3937a000}, {0x3937c000}, {0x3937e000},
+ {0x39380000}, {0x39382000}, {0x39384000}, {0x39386000},
+ {0x39388000}, {0x3938a000}, {0x3938c000}, {0x3938e000},
+ {0x39390000}, {0x39392000}, {0x39394000}, {0x39396000},
+ {0x39398000}, {0x3939a000}, {0x3939c000}, {0x3939e000},
+ {0x393a0000}, {0x393a2000}, {0x393a4000}, {0x393a6000},
+ {0x393a8000}, {0x393aa000}, {0x393ac000}, {0x393ae000},
+ {0x393b0000}, {0x393b2000}, {0x393b4000}, {0x393b6000},
+ {0x393b8000}, {0x393ba000}, {0x393bc000}, {0x393be000},
+ {0x393c0000}, {0x393c2000}, {0x393c4000}, {0x393c6000},
+ {0x393c8000}, {0x393ca000}, {0x393cc000}, {0x393ce000},
+ {0x393d0000}, {0x393d2000}, {0x393d4000}, {0x393d6000},
+ {0x393d8000}, {0x393da000}, {0x393dc000}, {0x393de000},
+ {0x393e0000}, {0x393e2000}, {0x393e4000}, {0x393e6000},
+ {0x393e8000}, {0x393ea000}, {0x393ec000}, {0x393ee000},
+ {0x393f0000}, {0x393f2000}, {0x393f4000}, {0x393f6000},
+ {0x393f8000}, {0x393fa000}, {0x393fc000}, {0x393fe000},
+ {0x39400000}, {0x39402000}, {0x39404000}, {0x39406000},
+ {0x39408000}, {0x3940a000}, {0x3940c000}, {0x3940e000},
+ {0x39410000}, {0x39412000}, {0x39414000}, {0x39416000},
+ {0x39418000}, {0x3941a000}, {0x3941c000}, {0x3941e000},
+ {0x39420000}, {0x39422000}, {0x39424000}, {0x39426000},
+ {0x39428000}, {0x3942a000}, {0x3942c000}, {0x3942e000},
+ {0x39430000}, {0x39432000}, {0x39434000}, {0x39436000},
+ {0x39438000}, {0x3943a000}, {0x3943c000}, {0x3943e000},
+ {0x39440000}, {0x39442000}, {0x39444000}, {0x39446000},
+ {0x39448000}, {0x3944a000}, {0x3944c000}, {0x3944e000},
+ {0x39450000}, {0x39452000}, {0x39454000}, {0x39456000},
+ {0x39458000}, {0x3945a000}, {0x3945c000}, {0x3945e000},
+ {0x39460000}, {0x39462000}, {0x39464000}, {0x39466000},
+ {0x39468000}, {0x3946a000}, {0x3946c000}, {0x3946e000},
+ {0x39470000}, {0x39472000}, {0x39474000}, {0x39476000},
+ {0x39478000}, {0x3947a000}, {0x3947c000}, {0x3947e000},
+ {0x39480000}, {0x39482000}, {0x39484000}, {0x39486000},
+ {0x39488000}, {0x3948a000}, {0x3948c000}, {0x3948e000},
+ {0x39490000}, {0x39492000}, {0x39494000}, {0x39496000},
+ {0x39498000}, {0x3949a000}, {0x3949c000}, {0x3949e000},
+ {0x394a0000}, {0x394a2000}, {0x394a4000}, {0x394a6000},
+ {0x394a8000}, {0x394aa000}, {0x394ac000}, {0x394ae000},
+ {0x394b0000}, {0x394b2000}, {0x394b4000}, {0x394b6000},
+ {0x394b8000}, {0x394ba000}, {0x394bc000}, {0x394be000},
+ {0x394c0000}, {0x394c2000}, {0x394c4000}, {0x394c6000},
+ {0x394c8000}, {0x394ca000}, {0x394cc000}, {0x394ce000},
+ {0x394d0000}, {0x394d2000}, {0x394d4000}, {0x394d6000},
+ {0x394d8000}, {0x394da000}, {0x394dc000}, {0x394de000},
+ {0x394e0000}, {0x394e2000}, {0x394e4000}, {0x394e6000},
+ {0x394e8000}, {0x394ea000}, {0x394ec000}, {0x394ee000},
+ {0x394f0000}, {0x394f2000}, {0x394f4000}, {0x394f6000},
+ {0x394f8000}, {0x394fa000}, {0x394fc000}, {0x394fe000},
+ {0x39500000}, {0x39502000}, {0x39504000}, {0x39506000},
+ {0x39508000}, {0x3950a000}, {0x3950c000}, {0x3950e000},
+ {0x39510000}, {0x39512000}, {0x39514000}, {0x39516000},
+ {0x39518000}, {0x3951a000}, {0x3951c000}, {0x3951e000},
+ {0x39520000}, {0x39522000}, {0x39524000}, {0x39526000},
+ {0x39528000}, {0x3952a000}, {0x3952c000}, {0x3952e000},
+ {0x39530000}, {0x39532000}, {0x39534000}, {0x39536000},
+ {0x39538000}, {0x3953a000}, {0x3953c000}, {0x3953e000},
+ {0x39540000}, {0x39542000}, {0x39544000}, {0x39546000},
+ {0x39548000}, {0x3954a000}, {0x3954c000}, {0x3954e000},
+ {0x39550000}, {0x39552000}, {0x39554000}, {0x39556000},
+ {0x39558000}, {0x3955a000}, {0x3955c000}, {0x3955e000},
+ {0x39560000}, {0x39562000}, {0x39564000}, {0x39566000},
+ {0x39568000}, {0x3956a000}, {0x3956c000}, {0x3956e000},
+ {0x39570000}, {0x39572000}, {0x39574000}, {0x39576000},
+ {0x39578000}, {0x3957a000}, {0x3957c000}, {0x3957e000},
+ {0x39580000}, {0x39582000}, {0x39584000}, {0x39586000},
+ {0x39588000}, {0x3958a000}, {0x3958c000}, {0x3958e000},
+ {0x39590000}, {0x39592000}, {0x39594000}, {0x39596000},
+ {0x39598000}, {0x3959a000}, {0x3959c000}, {0x3959e000},
+ {0x395a0000}, {0x395a2000}, {0x395a4000}, {0x395a6000},
+ {0x395a8000}, {0x395aa000}, {0x395ac000}, {0x395ae000},
+ {0x395b0000}, {0x395b2000}, {0x395b4000}, {0x395b6000},
+ {0x395b8000}, {0x395ba000}, {0x395bc000}, {0x395be000},
+ {0x395c0000}, {0x395c2000}, {0x395c4000}, {0x395c6000},
+ {0x395c8000}, {0x395ca000}, {0x395cc000}, {0x395ce000},
+ {0x395d0000}, {0x395d2000}, {0x395d4000}, {0x395d6000},
+ {0x395d8000}, {0x395da000}, {0x395dc000}, {0x395de000},
+ {0x395e0000}, {0x395e2000}, {0x395e4000}, {0x395e6000},
+ {0x395e8000}, {0x395ea000}, {0x395ec000}, {0x395ee000},
+ {0x395f0000}, {0x395f2000}, {0x395f4000}, {0x395f6000},
+ {0x395f8000}, {0x395fa000}, {0x395fc000}, {0x395fe000},
+ {0x39600000}, {0x39602000}, {0x39604000}, {0x39606000},
+ {0x39608000}, {0x3960a000}, {0x3960c000}, {0x3960e000},
+ {0x39610000}, {0x39612000}, {0x39614000}, {0x39616000},
+ {0x39618000}, {0x3961a000}, {0x3961c000}, {0x3961e000},
+ {0x39620000}, {0x39622000}, {0x39624000}, {0x39626000},
+ {0x39628000}, {0x3962a000}, {0x3962c000}, {0x3962e000},
+ {0x39630000}, {0x39632000}, {0x39634000}, {0x39636000},
+ {0x39638000}, {0x3963a000}, {0x3963c000}, {0x3963e000},
+ {0x39640000}, {0x39642000}, {0x39644000}, {0x39646000},
+ {0x39648000}, {0x3964a000}, {0x3964c000}, {0x3964e000},
+ {0x39650000}, {0x39652000}, {0x39654000}, {0x39656000},
+ {0x39658000}, {0x3965a000}, {0x3965c000}, {0x3965e000},
+ {0x39660000}, {0x39662000}, {0x39664000}, {0x39666000},
+ {0x39668000}, {0x3966a000}, {0x3966c000}, {0x3966e000},
+ {0x39670000}, {0x39672000}, {0x39674000}, {0x39676000},
+ {0x39678000}, {0x3967a000}, {0x3967c000}, {0x3967e000},
+ {0x39680000}, {0x39682000}, {0x39684000}, {0x39686000},
+ {0x39688000}, {0x3968a000}, {0x3968c000}, {0x3968e000},
+ {0x39690000}, {0x39692000}, {0x39694000}, {0x39696000},
+ {0x39698000}, {0x3969a000}, {0x3969c000}, {0x3969e000},
+ {0x396a0000}, {0x396a2000}, {0x396a4000}, {0x396a6000},
+ {0x396a8000}, {0x396aa000}, {0x396ac000}, {0x396ae000},
+ {0x396b0000}, {0x396b2000}, {0x396b4000}, {0x396b6000},
+ {0x396b8000}, {0x396ba000}, {0x396bc000}, {0x396be000},
+ {0x396c0000}, {0x396c2000}, {0x396c4000}, {0x396c6000},
+ {0x396c8000}, {0x396ca000}, {0x396cc000}, {0x396ce000},
+ {0x396d0000}, {0x396d2000}, {0x396d4000}, {0x396d6000},
+ {0x396d8000}, {0x396da000}, {0x396dc000}, {0x396de000},
+ {0x396e0000}, {0x396e2000}, {0x396e4000}, {0x396e6000},
+ {0x396e8000}, {0x396ea000}, {0x396ec000}, {0x396ee000},
+ {0x396f0000}, {0x396f2000}, {0x396f4000}, {0x396f6000},
+ {0x396f8000}, {0x396fa000}, {0x396fc000}, {0x396fe000},
+ {0x39700000}, {0x39702000}, {0x39704000}, {0x39706000},
+ {0x39708000}, {0x3970a000}, {0x3970c000}, {0x3970e000},
+ {0x39710000}, {0x39712000}, {0x39714000}, {0x39716000},
+ {0x39718000}, {0x3971a000}, {0x3971c000}, {0x3971e000},
+ {0x39720000}, {0x39722000}, {0x39724000}, {0x39726000},
+ {0x39728000}, {0x3972a000}, {0x3972c000}, {0x3972e000},
+ {0x39730000}, {0x39732000}, {0x39734000}, {0x39736000},
+ {0x39738000}, {0x3973a000}, {0x3973c000}, {0x3973e000},
+ {0x39740000}, {0x39742000}, {0x39744000}, {0x39746000},
+ {0x39748000}, {0x3974a000}, {0x3974c000}, {0x3974e000},
+ {0x39750000}, {0x39752000}, {0x39754000}, {0x39756000},
+ {0x39758000}, {0x3975a000}, {0x3975c000}, {0x3975e000},
+ {0x39760000}, {0x39762000}, {0x39764000}, {0x39766000},
+ {0x39768000}, {0x3976a000}, {0x3976c000}, {0x3976e000},
+ {0x39770000}, {0x39772000}, {0x39774000}, {0x39776000},
+ {0x39778000}, {0x3977a000}, {0x3977c000}, {0x3977e000},
+ {0x39780000}, {0x39782000}, {0x39784000}, {0x39786000},
+ {0x39788000}, {0x3978a000}, {0x3978c000}, {0x3978e000},
+ {0x39790000}, {0x39792000}, {0x39794000}, {0x39796000},
+ {0x39798000}, {0x3979a000}, {0x3979c000}, {0x3979e000},
+ {0x397a0000}, {0x397a2000}, {0x397a4000}, {0x397a6000},
+ {0x397a8000}, {0x397aa000}, {0x397ac000}, {0x397ae000},
+ {0x397b0000}, {0x397b2000}, {0x397b4000}, {0x397b6000},
+ {0x397b8000}, {0x397ba000}, {0x397bc000}, {0x397be000},
+ {0x397c0000}, {0x397c2000}, {0x397c4000}, {0x397c6000},
+ {0x397c8000}, {0x397ca000}, {0x397cc000}, {0x397ce000},
+ {0x397d0000}, {0x397d2000}, {0x397d4000}, {0x397d6000},
+ {0x397d8000}, {0x397da000}, {0x397dc000}, {0x397de000},
+ {0x397e0000}, {0x397e2000}, {0x397e4000}, {0x397e6000},
+ {0x397e8000}, {0x397ea000}, {0x397ec000}, {0x397ee000},
+ {0x397f0000}, {0x397f2000}, {0x397f4000}, {0x397f6000},
+ {0x397f8000}, {0x397fa000}, {0x397fc000}, {0x397fe000},
+ {0x39800000}, {0x39802000}, {0x39804000}, {0x39806000},
+ {0x39808000}, {0x3980a000}, {0x3980c000}, {0x3980e000},
+ {0x39810000}, {0x39812000}, {0x39814000}, {0x39816000},
+ {0x39818000}, {0x3981a000}, {0x3981c000}, {0x3981e000},
+ {0x39820000}, {0x39822000}, {0x39824000}, {0x39826000},
+ {0x39828000}, {0x3982a000}, {0x3982c000}, {0x3982e000},
+ {0x39830000}, {0x39832000}, {0x39834000}, {0x39836000},
+ {0x39838000}, {0x3983a000}, {0x3983c000}, {0x3983e000},
+ {0x39840000}, {0x39842000}, {0x39844000}, {0x39846000},
+ {0x39848000}, {0x3984a000}, {0x3984c000}, {0x3984e000},
+ {0x39850000}, {0x39852000}, {0x39854000}, {0x39856000},
+ {0x39858000}, {0x3985a000}, {0x3985c000}, {0x3985e000},
+ {0x39860000}, {0x39862000}, {0x39864000}, {0x39866000},
+ {0x39868000}, {0x3986a000}, {0x3986c000}, {0x3986e000},
+ {0x39870000}, {0x39872000}, {0x39874000}, {0x39876000},
+ {0x39878000}, {0x3987a000}, {0x3987c000}, {0x3987e000},
+ {0x39880000}, {0x39882000}, {0x39884000}, {0x39886000},
+ {0x39888000}, {0x3988a000}, {0x3988c000}, {0x3988e000},
+ {0x39890000}, {0x39892000}, {0x39894000}, {0x39896000},
+ {0x39898000}, {0x3989a000}, {0x3989c000}, {0x3989e000},
+ {0x398a0000}, {0x398a2000}, {0x398a4000}, {0x398a6000},
+ {0x398a8000}, {0x398aa000}, {0x398ac000}, {0x398ae000},
+ {0x398b0000}, {0x398b2000}, {0x398b4000}, {0x398b6000},
+ {0x398b8000}, {0x398ba000}, {0x398bc000}, {0x398be000},
+ {0x398c0000}, {0x398c2000}, {0x398c4000}, {0x398c6000},
+ {0x398c8000}, {0x398ca000}, {0x398cc000}, {0x398ce000},
+ {0x398d0000}, {0x398d2000}, {0x398d4000}, {0x398d6000},
+ {0x398d8000}, {0x398da000}, {0x398dc000}, {0x398de000},
+ {0x398e0000}, {0x398e2000}, {0x398e4000}, {0x398e6000},
+ {0x398e8000}, {0x398ea000}, {0x398ec000}, {0x398ee000},
+ {0x398f0000}, {0x398f2000}, {0x398f4000}, {0x398f6000},
+ {0x398f8000}, {0x398fa000}, {0x398fc000}, {0x398fe000},
+ {0x39900000}, {0x39902000}, {0x39904000}, {0x39906000},
+ {0x39908000}, {0x3990a000}, {0x3990c000}, {0x3990e000},
+ {0x39910000}, {0x39912000}, {0x39914000}, {0x39916000},
+ {0x39918000}, {0x3991a000}, {0x3991c000}, {0x3991e000},
+ {0x39920000}, {0x39922000}, {0x39924000}, {0x39926000},
+ {0x39928000}, {0x3992a000}, {0x3992c000}, {0x3992e000},
+ {0x39930000}, {0x39932000}, {0x39934000}, {0x39936000},
+ {0x39938000}, {0x3993a000}, {0x3993c000}, {0x3993e000},
+ {0x39940000}, {0x39942000}, {0x39944000}, {0x39946000},
+ {0x39948000}, {0x3994a000}, {0x3994c000}, {0x3994e000},
+ {0x39950000}, {0x39952000}, {0x39954000}, {0x39956000},
+ {0x39958000}, {0x3995a000}, {0x3995c000}, {0x3995e000},
+ {0x39960000}, {0x39962000}, {0x39964000}, {0x39966000},
+ {0x39968000}, {0x3996a000}, {0x3996c000}, {0x3996e000},
+ {0x39970000}, {0x39972000}, {0x39974000}, {0x39976000},
+ {0x39978000}, {0x3997a000}, {0x3997c000}, {0x3997e000},
+ {0x39980000}, {0x39982000}, {0x39984000}, {0x39986000},
+ {0x39988000}, {0x3998a000}, {0x3998c000}, {0x3998e000},
+ {0x39990000}, {0x39992000}, {0x39994000}, {0x39996000},
+ {0x39998000}, {0x3999a000}, {0x3999c000}, {0x3999e000},
+ {0x399a0000}, {0x399a2000}, {0x399a4000}, {0x399a6000},
+ {0x399a8000}, {0x399aa000}, {0x399ac000}, {0x399ae000},
+ {0x399b0000}, {0x399b2000}, {0x399b4000}, {0x399b6000},
+ {0x399b8000}, {0x399ba000}, {0x399bc000}, {0x399be000},
+ {0x399c0000}, {0x399c2000}, {0x399c4000}, {0x399c6000},
+ {0x399c8000}, {0x399ca000}, {0x399cc000}, {0x399ce000},
+ {0x399d0000}, {0x399d2000}, {0x399d4000}, {0x399d6000},
+ {0x399d8000}, {0x399da000}, {0x399dc000}, {0x399de000},
+ {0x399e0000}, {0x399e2000}, {0x399e4000}, {0x399e6000},
+ {0x399e8000}, {0x399ea000}, {0x399ec000}, {0x399ee000},
+ {0x399f0000}, {0x399f2000}, {0x399f4000}, {0x399f6000},
+ {0x399f8000}, {0x399fa000}, {0x399fc000}, {0x399fe000},
+ {0x39a00000}, {0x39a02000}, {0x39a04000}, {0x39a06000},
+ {0x39a08000}, {0x39a0a000}, {0x39a0c000}, {0x39a0e000},
+ {0x39a10000}, {0x39a12000}, {0x39a14000}, {0x39a16000},
+ {0x39a18000}, {0x39a1a000}, {0x39a1c000}, {0x39a1e000},
+ {0x39a20000}, {0x39a22000}, {0x39a24000}, {0x39a26000},
+ {0x39a28000}, {0x39a2a000}, {0x39a2c000}, {0x39a2e000},
+ {0x39a30000}, {0x39a32000}, {0x39a34000}, {0x39a36000},
+ {0x39a38000}, {0x39a3a000}, {0x39a3c000}, {0x39a3e000},
+ {0x39a40000}, {0x39a42000}, {0x39a44000}, {0x39a46000},
+ {0x39a48000}, {0x39a4a000}, {0x39a4c000}, {0x39a4e000},
+ {0x39a50000}, {0x39a52000}, {0x39a54000}, {0x39a56000},
+ {0x39a58000}, {0x39a5a000}, {0x39a5c000}, {0x39a5e000},
+ {0x39a60000}, {0x39a62000}, {0x39a64000}, {0x39a66000},
+ {0x39a68000}, {0x39a6a000}, {0x39a6c000}, {0x39a6e000},
+ {0x39a70000}, {0x39a72000}, {0x39a74000}, {0x39a76000},
+ {0x39a78000}, {0x39a7a000}, {0x39a7c000}, {0x39a7e000},
+ {0x39a80000}, {0x39a82000}, {0x39a84000}, {0x39a86000},
+ {0x39a88000}, {0x39a8a000}, {0x39a8c000}, {0x39a8e000},
+ {0x39a90000}, {0x39a92000}, {0x39a94000}, {0x39a96000},
+ {0x39a98000}, {0x39a9a000}, {0x39a9c000}, {0x39a9e000},
+ {0x39aa0000}, {0x39aa2000}, {0x39aa4000}, {0x39aa6000},
+ {0x39aa8000}, {0x39aaa000}, {0x39aac000}, {0x39aae000},
+ {0x39ab0000}, {0x39ab2000}, {0x39ab4000}, {0x39ab6000},
+ {0x39ab8000}, {0x39aba000}, {0x39abc000}, {0x39abe000},
+ {0x39ac0000}, {0x39ac2000}, {0x39ac4000}, {0x39ac6000},
+ {0x39ac8000}, {0x39aca000}, {0x39acc000}, {0x39ace000},
+ {0x39ad0000}, {0x39ad2000}, {0x39ad4000}, {0x39ad6000},
+ {0x39ad8000}, {0x39ada000}, {0x39adc000}, {0x39ade000},
+ {0x39ae0000}, {0x39ae2000}, {0x39ae4000}, {0x39ae6000},
+ {0x39ae8000}, {0x39aea000}, {0x39aec000}, {0x39aee000},
+ {0x39af0000}, {0x39af2000}, {0x39af4000}, {0x39af6000},
+ {0x39af8000}, {0x39afa000}, {0x39afc000}, {0x39afe000},
+ {0x39b00000}, {0x39b02000}, {0x39b04000}, {0x39b06000},
+ {0x39b08000}, {0x39b0a000}, {0x39b0c000}, {0x39b0e000},
+ {0x39b10000}, {0x39b12000}, {0x39b14000}, {0x39b16000},
+ {0x39b18000}, {0x39b1a000}, {0x39b1c000}, {0x39b1e000},
+ {0x39b20000}, {0x39b22000}, {0x39b24000}, {0x39b26000},
+ {0x39b28000}, {0x39b2a000}, {0x39b2c000}, {0x39b2e000},
+ {0x39b30000}, {0x39b32000}, {0x39b34000}, {0x39b36000},
+ {0x39b38000}, {0x39b3a000}, {0x39b3c000}, {0x39b3e000},
+ {0x39b40000}, {0x39b42000}, {0x39b44000}, {0x39b46000},
+ {0x39b48000}, {0x39b4a000}, {0x39b4c000}, {0x39b4e000},
+ {0x39b50000}, {0x39b52000}, {0x39b54000}, {0x39b56000},
+ {0x39b58000}, {0x39b5a000}, {0x39b5c000}, {0x39b5e000},
+ {0x39b60000}, {0x39b62000}, {0x39b64000}, {0x39b66000},
+ {0x39b68000}, {0x39b6a000}, {0x39b6c000}, {0x39b6e000},
+ {0x39b70000}, {0x39b72000}, {0x39b74000}, {0x39b76000},
+ {0x39b78000}, {0x39b7a000}, {0x39b7c000}, {0x39b7e000},
+ {0x39b80000}, {0x39b82000}, {0x39b84000}, {0x39b86000},
+ {0x39b88000}, {0x39b8a000}, {0x39b8c000}, {0x39b8e000},
+ {0x39b90000}, {0x39b92000}, {0x39b94000}, {0x39b96000},
+ {0x39b98000}, {0x39b9a000}, {0x39b9c000}, {0x39b9e000},
+ {0x39ba0000}, {0x39ba2000}, {0x39ba4000}, {0x39ba6000},
+ {0x39ba8000}, {0x39baa000}, {0x39bac000}, {0x39bae000},
+ {0x39bb0000}, {0x39bb2000}, {0x39bb4000}, {0x39bb6000},
+ {0x39bb8000}, {0x39bba000}, {0x39bbc000}, {0x39bbe000},
+ {0x39bc0000}, {0x39bc2000}, {0x39bc4000}, {0x39bc6000},
+ {0x39bc8000}, {0x39bca000}, {0x39bcc000}, {0x39bce000},
+ {0x39bd0000}, {0x39bd2000}, {0x39bd4000}, {0x39bd6000},
+ {0x39bd8000}, {0x39bda000}, {0x39bdc000}, {0x39bde000},
+ {0x39be0000}, {0x39be2000}, {0x39be4000}, {0x39be6000},
+ {0x39be8000}, {0x39bea000}, {0x39bec000}, {0x39bee000},
+ {0x39bf0000}, {0x39bf2000}, {0x39bf4000}, {0x39bf6000},
+ {0x39bf8000}, {0x39bfa000}, {0x39bfc000}, {0x39bfe000},
+ {0x39c00000}, {0x39c02000}, {0x39c04000}, {0x39c06000},
+ {0x39c08000}, {0x39c0a000}, {0x39c0c000}, {0x39c0e000},
+ {0x39c10000}, {0x39c12000}, {0x39c14000}, {0x39c16000},
+ {0x39c18000}, {0x39c1a000}, {0x39c1c000}, {0x39c1e000},
+ {0x39c20000}, {0x39c22000}, {0x39c24000}, {0x39c26000},
+ {0x39c28000}, {0x39c2a000}, {0x39c2c000}, {0x39c2e000},
+ {0x39c30000}, {0x39c32000}, {0x39c34000}, {0x39c36000},
+ {0x39c38000}, {0x39c3a000}, {0x39c3c000}, {0x39c3e000},
+ {0x39c40000}, {0x39c42000}, {0x39c44000}, {0x39c46000},
+ {0x39c48000}, {0x39c4a000}, {0x39c4c000}, {0x39c4e000},
+ {0x39c50000}, {0x39c52000}, {0x39c54000}, {0x39c56000},
+ {0x39c58000}, {0x39c5a000}, {0x39c5c000}, {0x39c5e000},
+ {0x39c60000}, {0x39c62000}, {0x39c64000}, {0x39c66000},
+ {0x39c68000}, {0x39c6a000}, {0x39c6c000}, {0x39c6e000},
+ {0x39c70000}, {0x39c72000}, {0x39c74000}, {0x39c76000},
+ {0x39c78000}, {0x39c7a000}, {0x39c7c000}, {0x39c7e000},
+ {0x39c80000}, {0x39c82000}, {0x39c84000}, {0x39c86000},
+ {0x39c88000}, {0x39c8a000}, {0x39c8c000}, {0x39c8e000},
+ {0x39c90000}, {0x39c92000}, {0x39c94000}, {0x39c96000},
+ {0x39c98000}, {0x39c9a000}, {0x39c9c000}, {0x39c9e000},
+ {0x39ca0000}, {0x39ca2000}, {0x39ca4000}, {0x39ca6000},
+ {0x39ca8000}, {0x39caa000}, {0x39cac000}, {0x39cae000},
+ {0x39cb0000}, {0x39cb2000}, {0x39cb4000}, {0x39cb6000},
+ {0x39cb8000}, {0x39cba000}, {0x39cbc000}, {0x39cbe000},
+ {0x39cc0000}, {0x39cc2000}, {0x39cc4000}, {0x39cc6000},
+ {0x39cc8000}, {0x39cca000}, {0x39ccc000}, {0x39cce000},
+ {0x39cd0000}, {0x39cd2000}, {0x39cd4000}, {0x39cd6000},
+ {0x39cd8000}, {0x39cda000}, {0x39cdc000}, {0x39cde000},
+ {0x39ce0000}, {0x39ce2000}, {0x39ce4000}, {0x39ce6000},
+ {0x39ce8000}, {0x39cea000}, {0x39cec000}, {0x39cee000},
+ {0x39cf0000}, {0x39cf2000}, {0x39cf4000}, {0x39cf6000},
+ {0x39cf8000}, {0x39cfa000}, {0x39cfc000}, {0x39cfe000},
+ {0x39d00000}, {0x39d02000}, {0x39d04000}, {0x39d06000},
+ {0x39d08000}, {0x39d0a000}, {0x39d0c000}, {0x39d0e000},
+ {0x39d10000}, {0x39d12000}, {0x39d14000}, {0x39d16000},
+ {0x39d18000}, {0x39d1a000}, {0x39d1c000}, {0x39d1e000},
+ {0x39d20000}, {0x39d22000}, {0x39d24000}, {0x39d26000},
+ {0x39d28000}, {0x39d2a000}, {0x39d2c000}, {0x39d2e000},
+ {0x39d30000}, {0x39d32000}, {0x39d34000}, {0x39d36000},
+ {0x39d38000}, {0x39d3a000}, {0x39d3c000}, {0x39d3e000},
+ {0x39d40000}, {0x39d42000}, {0x39d44000}, {0x39d46000},
+ {0x39d48000}, {0x39d4a000}, {0x39d4c000}, {0x39d4e000},
+ {0x39d50000}, {0x39d52000}, {0x39d54000}, {0x39d56000},
+ {0x39d58000}, {0x39d5a000}, {0x39d5c000}, {0x39d5e000},
+ {0x39d60000}, {0x39d62000}, {0x39d64000}, {0x39d66000},
+ {0x39d68000}, {0x39d6a000}, {0x39d6c000}, {0x39d6e000},
+ {0x39d70000}, {0x39d72000}, {0x39d74000}, {0x39d76000},
+ {0x39d78000}, {0x39d7a000}, {0x39d7c000}, {0x39d7e000},
+ {0x39d80000}, {0x39d82000}, {0x39d84000}, {0x39d86000},
+ {0x39d88000}, {0x39d8a000}, {0x39d8c000}, {0x39d8e000},
+ {0x39d90000}, {0x39d92000}, {0x39d94000}, {0x39d96000},
+ {0x39d98000}, {0x39d9a000}, {0x39d9c000}, {0x39d9e000},
+ {0x39da0000}, {0x39da2000}, {0x39da4000}, {0x39da6000},
+ {0x39da8000}, {0x39daa000}, {0x39dac000}, {0x39dae000},
+ {0x39db0000}, {0x39db2000}, {0x39db4000}, {0x39db6000},
+ {0x39db8000}, {0x39dba000}, {0x39dbc000}, {0x39dbe000},
+ {0x39dc0000}, {0x39dc2000}, {0x39dc4000}, {0x39dc6000},
+ {0x39dc8000}, {0x39dca000}, {0x39dcc000}, {0x39dce000},
+ {0x39dd0000}, {0x39dd2000}, {0x39dd4000}, {0x39dd6000},
+ {0x39dd8000}, {0x39dda000}, {0x39ddc000}, {0x39dde000},
+ {0x39de0000}, {0x39de2000}, {0x39de4000}, {0x39de6000},
+ {0x39de8000}, {0x39dea000}, {0x39dec000}, {0x39dee000},
+ {0x39df0000}, {0x39df2000}, {0x39df4000}, {0x39df6000},
+ {0x39df8000}, {0x39dfa000}, {0x39dfc000}, {0x39dfe000},
+ {0x39e00000}, {0x39e02000}, {0x39e04000}, {0x39e06000},
+ {0x39e08000}, {0x39e0a000}, {0x39e0c000}, {0x39e0e000},
+ {0x39e10000}, {0x39e12000}, {0x39e14000}, {0x39e16000},
+ {0x39e18000}, {0x39e1a000}, {0x39e1c000}, {0x39e1e000},
+ {0x39e20000}, {0x39e22000}, {0x39e24000}, {0x39e26000},
+ {0x39e28000}, {0x39e2a000}, {0x39e2c000}, {0x39e2e000},
+ {0x39e30000}, {0x39e32000}, {0x39e34000}, {0x39e36000},
+ {0x39e38000}, {0x39e3a000}, {0x39e3c000}, {0x39e3e000},
+ {0x39e40000}, {0x39e42000}, {0x39e44000}, {0x39e46000},
+ {0x39e48000}, {0x39e4a000}, {0x39e4c000}, {0x39e4e000},
+ {0x39e50000}, {0x39e52000}, {0x39e54000}, {0x39e56000},
+ {0x39e58000}, {0x39e5a000}, {0x39e5c000}, {0x39e5e000},
+ {0x39e60000}, {0x39e62000}, {0x39e64000}, {0x39e66000},
+ {0x39e68000}, {0x39e6a000}, {0x39e6c000}, {0x39e6e000},
+ {0x39e70000}, {0x39e72000}, {0x39e74000}, {0x39e76000},
+ {0x39e78000}, {0x39e7a000}, {0x39e7c000}, {0x39e7e000},
+ {0x39e80000}, {0x39e82000}, {0x39e84000}, {0x39e86000},
+ {0x39e88000}, {0x39e8a000}, {0x39e8c000}, {0x39e8e000},
+ {0x39e90000}, {0x39e92000}, {0x39e94000}, {0x39e96000},
+ {0x39e98000}, {0x39e9a000}, {0x39e9c000}, {0x39e9e000},
+ {0x39ea0000}, {0x39ea2000}, {0x39ea4000}, {0x39ea6000},
+ {0x39ea8000}, {0x39eaa000}, {0x39eac000}, {0x39eae000},
+ {0x39eb0000}, {0x39eb2000}, {0x39eb4000}, {0x39eb6000},
+ {0x39eb8000}, {0x39eba000}, {0x39ebc000}, {0x39ebe000},
+ {0x39ec0000}, {0x39ec2000}, {0x39ec4000}, {0x39ec6000},
+ {0x39ec8000}, {0x39eca000}, {0x39ecc000}, {0x39ece000},
+ {0x39ed0000}, {0x39ed2000}, {0x39ed4000}, {0x39ed6000},
+ {0x39ed8000}, {0x39eda000}, {0x39edc000}, {0x39ede000},
+ {0x39ee0000}, {0x39ee2000}, {0x39ee4000}, {0x39ee6000},
+ {0x39ee8000}, {0x39eea000}, {0x39eec000}, {0x39eee000},
+ {0x39ef0000}, {0x39ef2000}, {0x39ef4000}, {0x39ef6000},
+ {0x39ef8000}, {0x39efa000}, {0x39efc000}, {0x39efe000},
+ {0x39f00000}, {0x39f02000}, {0x39f04000}, {0x39f06000},
+ {0x39f08000}, {0x39f0a000}, {0x39f0c000}, {0x39f0e000},
+ {0x39f10000}, {0x39f12000}, {0x39f14000}, {0x39f16000},
+ {0x39f18000}, {0x39f1a000}, {0x39f1c000}, {0x39f1e000},
+ {0x39f20000}, {0x39f22000}, {0x39f24000}, {0x39f26000},
+ {0x39f28000}, {0x39f2a000}, {0x39f2c000}, {0x39f2e000},
+ {0x39f30000}, {0x39f32000}, {0x39f34000}, {0x39f36000},
+ {0x39f38000}, {0x39f3a000}, {0x39f3c000}, {0x39f3e000},
+ {0x39f40000}, {0x39f42000}, {0x39f44000}, {0x39f46000},
+ {0x39f48000}, {0x39f4a000}, {0x39f4c000}, {0x39f4e000},
+ {0x39f50000}, {0x39f52000}, {0x39f54000}, {0x39f56000},
+ {0x39f58000}, {0x39f5a000}, {0x39f5c000}, {0x39f5e000},
+ {0x39f60000}, {0x39f62000}, {0x39f64000}, {0x39f66000},
+ {0x39f68000}, {0x39f6a000}, {0x39f6c000}, {0x39f6e000},
+ {0x39f70000}, {0x39f72000}, {0x39f74000}, {0x39f76000},
+ {0x39f78000}, {0x39f7a000}, {0x39f7c000}, {0x39f7e000},
+ {0x39f80000}, {0x39f82000}, {0x39f84000}, {0x39f86000},
+ {0x39f88000}, {0x39f8a000}, {0x39f8c000}, {0x39f8e000},
+ {0x39f90000}, {0x39f92000}, {0x39f94000}, {0x39f96000},
+ {0x39f98000}, {0x39f9a000}, {0x39f9c000}, {0x39f9e000},
+ {0x39fa0000}, {0x39fa2000}, {0x39fa4000}, {0x39fa6000},
+ {0x39fa8000}, {0x39faa000}, {0x39fac000}, {0x39fae000},
+ {0x39fb0000}, {0x39fb2000}, {0x39fb4000}, {0x39fb6000},
+ {0x39fb8000}, {0x39fba000}, {0x39fbc000}, {0x39fbe000},
+ {0x39fc0000}, {0x39fc2000}, {0x39fc4000}, {0x39fc6000},
+ {0x39fc8000}, {0x39fca000}, {0x39fcc000}, {0x39fce000},
+ {0x39fd0000}, {0x39fd2000}, {0x39fd4000}, {0x39fd6000},
+ {0x39fd8000}, {0x39fda000}, {0x39fdc000}, {0x39fde000},
+ {0x39fe0000}, {0x39fe2000}, {0x39fe4000}, {0x39fe6000},
+ {0x39fe8000}, {0x39fea000}, {0x39fec000}, {0x39fee000},
+ {0x39ff0000}, {0x39ff2000}, {0x39ff4000}, {0x39ff6000},
+ {0x39ff8000}, {0x39ffa000}, {0x39ffc000}, {0x39ffe000},
+ {0x3a000000}, {0x3a002000}, {0x3a004000}, {0x3a006000},
+ {0x3a008000}, {0x3a00a000}, {0x3a00c000}, {0x3a00e000},
+ {0x3a010000}, {0x3a012000}, {0x3a014000}, {0x3a016000},
+ {0x3a018000}, {0x3a01a000}, {0x3a01c000}, {0x3a01e000},
+ {0x3a020000}, {0x3a022000}, {0x3a024000}, {0x3a026000},
+ {0x3a028000}, {0x3a02a000}, {0x3a02c000}, {0x3a02e000},
+ {0x3a030000}, {0x3a032000}, {0x3a034000}, {0x3a036000},
+ {0x3a038000}, {0x3a03a000}, {0x3a03c000}, {0x3a03e000},
+ {0x3a040000}, {0x3a042000}, {0x3a044000}, {0x3a046000},
+ {0x3a048000}, {0x3a04a000}, {0x3a04c000}, {0x3a04e000},
+ {0x3a050000}, {0x3a052000}, {0x3a054000}, {0x3a056000},
+ {0x3a058000}, {0x3a05a000}, {0x3a05c000}, {0x3a05e000},
+ {0x3a060000}, {0x3a062000}, {0x3a064000}, {0x3a066000},
+ {0x3a068000}, {0x3a06a000}, {0x3a06c000}, {0x3a06e000},
+ {0x3a070000}, {0x3a072000}, {0x3a074000}, {0x3a076000},
+ {0x3a078000}, {0x3a07a000}, {0x3a07c000}, {0x3a07e000},
+ {0x3a080000}, {0x3a082000}, {0x3a084000}, {0x3a086000},
+ {0x3a088000}, {0x3a08a000}, {0x3a08c000}, {0x3a08e000},
+ {0x3a090000}, {0x3a092000}, {0x3a094000}, {0x3a096000},
+ {0x3a098000}, {0x3a09a000}, {0x3a09c000}, {0x3a09e000},
+ {0x3a0a0000}, {0x3a0a2000}, {0x3a0a4000}, {0x3a0a6000},
+ {0x3a0a8000}, {0x3a0aa000}, {0x3a0ac000}, {0x3a0ae000},
+ {0x3a0b0000}, {0x3a0b2000}, {0x3a0b4000}, {0x3a0b6000},
+ {0x3a0b8000}, {0x3a0ba000}, {0x3a0bc000}, {0x3a0be000},
+ {0x3a0c0000}, {0x3a0c2000}, {0x3a0c4000}, {0x3a0c6000},
+ {0x3a0c8000}, {0x3a0ca000}, {0x3a0cc000}, {0x3a0ce000},
+ {0x3a0d0000}, {0x3a0d2000}, {0x3a0d4000}, {0x3a0d6000},
+ {0x3a0d8000}, {0x3a0da000}, {0x3a0dc000}, {0x3a0de000},
+ {0x3a0e0000}, {0x3a0e2000}, {0x3a0e4000}, {0x3a0e6000},
+ {0x3a0e8000}, {0x3a0ea000}, {0x3a0ec000}, {0x3a0ee000},
+ {0x3a0f0000}, {0x3a0f2000}, {0x3a0f4000}, {0x3a0f6000},
+ {0x3a0f8000}, {0x3a0fa000}, {0x3a0fc000}, {0x3a0fe000},
+ {0x3a100000}, {0x3a102000}, {0x3a104000}, {0x3a106000},
+ {0x3a108000}, {0x3a10a000}, {0x3a10c000}, {0x3a10e000},
+ {0x3a110000}, {0x3a112000}, {0x3a114000}, {0x3a116000},
+ {0x3a118000}, {0x3a11a000}, {0x3a11c000}, {0x3a11e000},
+ {0x3a120000}, {0x3a122000}, {0x3a124000}, {0x3a126000},
+ {0x3a128000}, {0x3a12a000}, {0x3a12c000}, {0x3a12e000},
+ {0x3a130000}, {0x3a132000}, {0x3a134000}, {0x3a136000},
+ {0x3a138000}, {0x3a13a000}, {0x3a13c000}, {0x3a13e000},
+ {0x3a140000}, {0x3a142000}, {0x3a144000}, {0x3a146000},
+ {0x3a148000}, {0x3a14a000}, {0x3a14c000}, {0x3a14e000},
+ {0x3a150000}, {0x3a152000}, {0x3a154000}, {0x3a156000},
+ {0x3a158000}, {0x3a15a000}, {0x3a15c000}, {0x3a15e000},
+ {0x3a160000}, {0x3a162000}, {0x3a164000}, {0x3a166000},
+ {0x3a168000}, {0x3a16a000}, {0x3a16c000}, {0x3a16e000},
+ {0x3a170000}, {0x3a172000}, {0x3a174000}, {0x3a176000},
+ {0x3a178000}, {0x3a17a000}, {0x3a17c000}, {0x3a17e000},
+ {0x3a180000}, {0x3a182000}, {0x3a184000}, {0x3a186000},
+ {0x3a188000}, {0x3a18a000}, {0x3a18c000}, {0x3a18e000},
+ {0x3a190000}, {0x3a192000}, {0x3a194000}, {0x3a196000},
+ {0x3a198000}, {0x3a19a000}, {0x3a19c000}, {0x3a19e000},
+ {0x3a1a0000}, {0x3a1a2000}, {0x3a1a4000}, {0x3a1a6000},
+ {0x3a1a8000}, {0x3a1aa000}, {0x3a1ac000}, {0x3a1ae000},
+ {0x3a1b0000}, {0x3a1b2000}, {0x3a1b4000}, {0x3a1b6000},
+ {0x3a1b8000}, {0x3a1ba000}, {0x3a1bc000}, {0x3a1be000},
+ {0x3a1c0000}, {0x3a1c2000}, {0x3a1c4000}, {0x3a1c6000},
+ {0x3a1c8000}, {0x3a1ca000}, {0x3a1cc000}, {0x3a1ce000},
+ {0x3a1d0000}, {0x3a1d2000}, {0x3a1d4000}, {0x3a1d6000},
+ {0x3a1d8000}, {0x3a1da000}, {0x3a1dc000}, {0x3a1de000},
+ {0x3a1e0000}, {0x3a1e2000}, {0x3a1e4000}, {0x3a1e6000},
+ {0x3a1e8000}, {0x3a1ea000}, {0x3a1ec000}, {0x3a1ee000},
+ {0x3a1f0000}, {0x3a1f2000}, {0x3a1f4000}, {0x3a1f6000},
+ {0x3a1f8000}, {0x3a1fa000}, {0x3a1fc000}, {0x3a1fe000},
+ {0x3a200000}, {0x3a202000}, {0x3a204000}, {0x3a206000},
+ {0x3a208000}, {0x3a20a000}, {0x3a20c000}, {0x3a20e000},
+ {0x3a210000}, {0x3a212000}, {0x3a214000}, {0x3a216000},
+ {0x3a218000}, {0x3a21a000}, {0x3a21c000}, {0x3a21e000},
+ {0x3a220000}, {0x3a222000}, {0x3a224000}, {0x3a226000},
+ {0x3a228000}, {0x3a22a000}, {0x3a22c000}, {0x3a22e000},
+ {0x3a230000}, {0x3a232000}, {0x3a234000}, {0x3a236000},
+ {0x3a238000}, {0x3a23a000}, {0x3a23c000}, {0x3a23e000},
+ {0x3a240000}, {0x3a242000}, {0x3a244000}, {0x3a246000},
+ {0x3a248000}, {0x3a24a000}, {0x3a24c000}, {0x3a24e000},
+ {0x3a250000}, {0x3a252000}, {0x3a254000}, {0x3a256000},
+ {0x3a258000}, {0x3a25a000}, {0x3a25c000}, {0x3a25e000},
+ {0x3a260000}, {0x3a262000}, {0x3a264000}, {0x3a266000},
+ {0x3a268000}, {0x3a26a000}, {0x3a26c000}, {0x3a26e000},
+ {0x3a270000}, {0x3a272000}, {0x3a274000}, {0x3a276000},
+ {0x3a278000}, {0x3a27a000}, {0x3a27c000}, {0x3a27e000},
+ {0x3a280000}, {0x3a282000}, {0x3a284000}, {0x3a286000},
+ {0x3a288000}, {0x3a28a000}, {0x3a28c000}, {0x3a28e000},
+ {0x3a290000}, {0x3a292000}, {0x3a294000}, {0x3a296000},
+ {0x3a298000}, {0x3a29a000}, {0x3a29c000}, {0x3a29e000},
+ {0x3a2a0000}, {0x3a2a2000}, {0x3a2a4000}, {0x3a2a6000},
+ {0x3a2a8000}, {0x3a2aa000}, {0x3a2ac000}, {0x3a2ae000},
+ {0x3a2b0000}, {0x3a2b2000}, {0x3a2b4000}, {0x3a2b6000},
+ {0x3a2b8000}, {0x3a2ba000}, {0x3a2bc000}, {0x3a2be000},
+ {0x3a2c0000}, {0x3a2c2000}, {0x3a2c4000}, {0x3a2c6000},
+ {0x3a2c8000}, {0x3a2ca000}, {0x3a2cc000}, {0x3a2ce000},
+ {0x3a2d0000}, {0x3a2d2000}, {0x3a2d4000}, {0x3a2d6000},
+ {0x3a2d8000}, {0x3a2da000}, {0x3a2dc000}, {0x3a2de000},
+ {0x3a2e0000}, {0x3a2e2000}, {0x3a2e4000}, {0x3a2e6000},
+ {0x3a2e8000}, {0x3a2ea000}, {0x3a2ec000}, {0x3a2ee000},
+ {0x3a2f0000}, {0x3a2f2000}, {0x3a2f4000}, {0x3a2f6000},
+ {0x3a2f8000}, {0x3a2fa000}, {0x3a2fc000}, {0x3a2fe000},
+ {0x3a300000}, {0x3a302000}, {0x3a304000}, {0x3a306000},
+ {0x3a308000}, {0x3a30a000}, {0x3a30c000}, {0x3a30e000},
+ {0x3a310000}, {0x3a312000}, {0x3a314000}, {0x3a316000},
+ {0x3a318000}, {0x3a31a000}, {0x3a31c000}, {0x3a31e000},
+ {0x3a320000}, {0x3a322000}, {0x3a324000}, {0x3a326000},
+ {0x3a328000}, {0x3a32a000}, {0x3a32c000}, {0x3a32e000},
+ {0x3a330000}, {0x3a332000}, {0x3a334000}, {0x3a336000},
+ {0x3a338000}, {0x3a33a000}, {0x3a33c000}, {0x3a33e000},
+ {0x3a340000}, {0x3a342000}, {0x3a344000}, {0x3a346000},
+ {0x3a348000}, {0x3a34a000}, {0x3a34c000}, {0x3a34e000},
+ {0x3a350000}, {0x3a352000}, {0x3a354000}, {0x3a356000},
+ {0x3a358000}, {0x3a35a000}, {0x3a35c000}, {0x3a35e000},
+ {0x3a360000}, {0x3a362000}, {0x3a364000}, {0x3a366000},
+ {0x3a368000}, {0x3a36a000}, {0x3a36c000}, {0x3a36e000},
+ {0x3a370000}, {0x3a372000}, {0x3a374000}, {0x3a376000},
+ {0x3a378000}, {0x3a37a000}, {0x3a37c000}, {0x3a37e000},
+ {0x3a380000}, {0x3a382000}, {0x3a384000}, {0x3a386000},
+ {0x3a388000}, {0x3a38a000}, {0x3a38c000}, {0x3a38e000},
+ {0x3a390000}, {0x3a392000}, {0x3a394000}, {0x3a396000},
+ {0x3a398000}, {0x3a39a000}, {0x3a39c000}, {0x3a39e000},
+ {0x3a3a0000}, {0x3a3a2000}, {0x3a3a4000}, {0x3a3a6000},
+ {0x3a3a8000}, {0x3a3aa000}, {0x3a3ac000}, {0x3a3ae000},
+ {0x3a3b0000}, {0x3a3b2000}, {0x3a3b4000}, {0x3a3b6000},
+ {0x3a3b8000}, {0x3a3ba000}, {0x3a3bc000}, {0x3a3be000},
+ {0x3a3c0000}, {0x3a3c2000}, {0x3a3c4000}, {0x3a3c6000},
+ {0x3a3c8000}, {0x3a3ca000}, {0x3a3cc000}, {0x3a3ce000},
+ {0x3a3d0000}, {0x3a3d2000}, {0x3a3d4000}, {0x3a3d6000},
+ {0x3a3d8000}, {0x3a3da000}, {0x3a3dc000}, {0x3a3de000},
+ {0x3a3e0000}, {0x3a3e2000}, {0x3a3e4000}, {0x3a3e6000},
+ {0x3a3e8000}, {0x3a3ea000}, {0x3a3ec000}, {0x3a3ee000},
+ {0x3a3f0000}, {0x3a3f2000}, {0x3a3f4000}, {0x3a3f6000},
+ {0x3a3f8000}, {0x3a3fa000}, {0x3a3fc000}, {0x3a3fe000},
+ {0x3a400000}, {0x3a402000}, {0x3a404000}, {0x3a406000},
+ {0x3a408000}, {0x3a40a000}, {0x3a40c000}, {0x3a40e000},
+ {0x3a410000}, {0x3a412000}, {0x3a414000}, {0x3a416000},
+ {0x3a418000}, {0x3a41a000}, {0x3a41c000}, {0x3a41e000},
+ {0x3a420000}, {0x3a422000}, {0x3a424000}, {0x3a426000},
+ {0x3a428000}, {0x3a42a000}, {0x3a42c000}, {0x3a42e000},
+ {0x3a430000}, {0x3a432000}, {0x3a434000}, {0x3a436000},
+ {0x3a438000}, {0x3a43a000}, {0x3a43c000}, {0x3a43e000},
+ {0x3a440000}, {0x3a442000}, {0x3a444000}, {0x3a446000},
+ {0x3a448000}, {0x3a44a000}, {0x3a44c000}, {0x3a44e000},
+ {0x3a450000}, {0x3a452000}, {0x3a454000}, {0x3a456000},
+ {0x3a458000}, {0x3a45a000}, {0x3a45c000}, {0x3a45e000},
+ {0x3a460000}, {0x3a462000}, {0x3a464000}, {0x3a466000},
+ {0x3a468000}, {0x3a46a000}, {0x3a46c000}, {0x3a46e000},
+ {0x3a470000}, {0x3a472000}, {0x3a474000}, {0x3a476000},
+ {0x3a478000}, {0x3a47a000}, {0x3a47c000}, {0x3a47e000},
+ {0x3a480000}, {0x3a482000}, {0x3a484000}, {0x3a486000},
+ {0x3a488000}, {0x3a48a000}, {0x3a48c000}, {0x3a48e000},
+ {0x3a490000}, {0x3a492000}, {0x3a494000}, {0x3a496000},
+ {0x3a498000}, {0x3a49a000}, {0x3a49c000}, {0x3a49e000},
+ {0x3a4a0000}, {0x3a4a2000}, {0x3a4a4000}, {0x3a4a6000},
+ {0x3a4a8000}, {0x3a4aa000}, {0x3a4ac000}, {0x3a4ae000},
+ {0x3a4b0000}, {0x3a4b2000}, {0x3a4b4000}, {0x3a4b6000},
+ {0x3a4b8000}, {0x3a4ba000}, {0x3a4bc000}, {0x3a4be000},
+ {0x3a4c0000}, {0x3a4c2000}, {0x3a4c4000}, {0x3a4c6000},
+ {0x3a4c8000}, {0x3a4ca000}, {0x3a4cc000}, {0x3a4ce000},
+ {0x3a4d0000}, {0x3a4d2000}, {0x3a4d4000}, {0x3a4d6000},
+ {0x3a4d8000}, {0x3a4da000}, {0x3a4dc000}, {0x3a4de000},
+ {0x3a4e0000}, {0x3a4e2000}, {0x3a4e4000}, {0x3a4e6000},
+ {0x3a4e8000}, {0x3a4ea000}, {0x3a4ec000}, {0x3a4ee000},
+ {0x3a4f0000}, {0x3a4f2000}, {0x3a4f4000}, {0x3a4f6000},
+ {0x3a4f8000}, {0x3a4fa000}, {0x3a4fc000}, {0x3a4fe000},
+ {0x3a500000}, {0x3a502000}, {0x3a504000}, {0x3a506000},
+ {0x3a508000}, {0x3a50a000}, {0x3a50c000}, {0x3a50e000},
+ {0x3a510000}, {0x3a512000}, {0x3a514000}, {0x3a516000},
+ {0x3a518000}, {0x3a51a000}, {0x3a51c000}, {0x3a51e000},
+ {0x3a520000}, {0x3a522000}, {0x3a524000}, {0x3a526000},
+ {0x3a528000}, {0x3a52a000}, {0x3a52c000}, {0x3a52e000},
+ {0x3a530000}, {0x3a532000}, {0x3a534000}, {0x3a536000},
+ {0x3a538000}, {0x3a53a000}, {0x3a53c000}, {0x3a53e000},
+ {0x3a540000}, {0x3a542000}, {0x3a544000}, {0x3a546000},
+ {0x3a548000}, {0x3a54a000}, {0x3a54c000}, {0x3a54e000},
+ {0x3a550000}, {0x3a552000}, {0x3a554000}, {0x3a556000},
+ {0x3a558000}, {0x3a55a000}, {0x3a55c000}, {0x3a55e000},
+ {0x3a560000}, {0x3a562000}, {0x3a564000}, {0x3a566000},
+ {0x3a568000}, {0x3a56a000}, {0x3a56c000}, {0x3a56e000},
+ {0x3a570000}, {0x3a572000}, {0x3a574000}, {0x3a576000},
+ {0x3a578000}, {0x3a57a000}, {0x3a57c000}, {0x3a57e000},
+ {0x3a580000}, {0x3a582000}, {0x3a584000}, {0x3a586000},
+ {0x3a588000}, {0x3a58a000}, {0x3a58c000}, {0x3a58e000},
+ {0x3a590000}, {0x3a592000}, {0x3a594000}, {0x3a596000},
+ {0x3a598000}, {0x3a59a000}, {0x3a59c000}, {0x3a59e000},
+ {0x3a5a0000}, {0x3a5a2000}, {0x3a5a4000}, {0x3a5a6000},
+ {0x3a5a8000}, {0x3a5aa000}, {0x3a5ac000}, {0x3a5ae000},
+ {0x3a5b0000}, {0x3a5b2000}, {0x3a5b4000}, {0x3a5b6000},
+ {0x3a5b8000}, {0x3a5ba000}, {0x3a5bc000}, {0x3a5be000},
+ {0x3a5c0000}, {0x3a5c2000}, {0x3a5c4000}, {0x3a5c6000},
+ {0x3a5c8000}, {0x3a5ca000}, {0x3a5cc000}, {0x3a5ce000},
+ {0x3a5d0000}, {0x3a5d2000}, {0x3a5d4000}, {0x3a5d6000},
+ {0x3a5d8000}, {0x3a5da000}, {0x3a5dc000}, {0x3a5de000},
+ {0x3a5e0000}, {0x3a5e2000}, {0x3a5e4000}, {0x3a5e6000},
+ {0x3a5e8000}, {0x3a5ea000}, {0x3a5ec000}, {0x3a5ee000},
+ {0x3a5f0000}, {0x3a5f2000}, {0x3a5f4000}, {0x3a5f6000},
+ {0x3a5f8000}, {0x3a5fa000}, {0x3a5fc000}, {0x3a5fe000},
+ {0x3a600000}, {0x3a602000}, {0x3a604000}, {0x3a606000},
+ {0x3a608000}, {0x3a60a000}, {0x3a60c000}, {0x3a60e000},
+ {0x3a610000}, {0x3a612000}, {0x3a614000}, {0x3a616000},
+ {0x3a618000}, {0x3a61a000}, {0x3a61c000}, {0x3a61e000},
+ {0x3a620000}, {0x3a622000}, {0x3a624000}, {0x3a626000},
+ {0x3a628000}, {0x3a62a000}, {0x3a62c000}, {0x3a62e000},
+ {0x3a630000}, {0x3a632000}, {0x3a634000}, {0x3a636000},
+ {0x3a638000}, {0x3a63a000}, {0x3a63c000}, {0x3a63e000},
+ {0x3a640000}, {0x3a642000}, {0x3a644000}, {0x3a646000},
+ {0x3a648000}, {0x3a64a000}, {0x3a64c000}, {0x3a64e000},
+ {0x3a650000}, {0x3a652000}, {0x3a654000}, {0x3a656000},
+ {0x3a658000}, {0x3a65a000}, {0x3a65c000}, {0x3a65e000},
+ {0x3a660000}, {0x3a662000}, {0x3a664000}, {0x3a666000},
+ {0x3a668000}, {0x3a66a000}, {0x3a66c000}, {0x3a66e000},
+ {0x3a670000}, {0x3a672000}, {0x3a674000}, {0x3a676000},
+ {0x3a678000}, {0x3a67a000}, {0x3a67c000}, {0x3a67e000},
+ {0x3a680000}, {0x3a682000}, {0x3a684000}, {0x3a686000},
+ {0x3a688000}, {0x3a68a000}, {0x3a68c000}, {0x3a68e000},
+ {0x3a690000}, {0x3a692000}, {0x3a694000}, {0x3a696000},
+ {0x3a698000}, {0x3a69a000}, {0x3a69c000}, {0x3a69e000},
+ {0x3a6a0000}, {0x3a6a2000}, {0x3a6a4000}, {0x3a6a6000},
+ {0x3a6a8000}, {0x3a6aa000}, {0x3a6ac000}, {0x3a6ae000},
+ {0x3a6b0000}, {0x3a6b2000}, {0x3a6b4000}, {0x3a6b6000},
+ {0x3a6b8000}, {0x3a6ba000}, {0x3a6bc000}, {0x3a6be000},
+ {0x3a6c0000}, {0x3a6c2000}, {0x3a6c4000}, {0x3a6c6000},
+ {0x3a6c8000}, {0x3a6ca000}, {0x3a6cc000}, {0x3a6ce000},
+ {0x3a6d0000}, {0x3a6d2000}, {0x3a6d4000}, {0x3a6d6000},
+ {0x3a6d8000}, {0x3a6da000}, {0x3a6dc000}, {0x3a6de000},
+ {0x3a6e0000}, {0x3a6e2000}, {0x3a6e4000}, {0x3a6e6000},
+ {0x3a6e8000}, {0x3a6ea000}, {0x3a6ec000}, {0x3a6ee000},
+ {0x3a6f0000}, {0x3a6f2000}, {0x3a6f4000}, {0x3a6f6000},
+ {0x3a6f8000}, {0x3a6fa000}, {0x3a6fc000}, {0x3a6fe000},
+ {0x3a700000}, {0x3a702000}, {0x3a704000}, {0x3a706000},
+ {0x3a708000}, {0x3a70a000}, {0x3a70c000}, {0x3a70e000},
+ {0x3a710000}, {0x3a712000}, {0x3a714000}, {0x3a716000},
+ {0x3a718000}, {0x3a71a000}, {0x3a71c000}, {0x3a71e000},
+ {0x3a720000}, {0x3a722000}, {0x3a724000}, {0x3a726000},
+ {0x3a728000}, {0x3a72a000}, {0x3a72c000}, {0x3a72e000},
+ {0x3a730000}, {0x3a732000}, {0x3a734000}, {0x3a736000},
+ {0x3a738000}, {0x3a73a000}, {0x3a73c000}, {0x3a73e000},
+ {0x3a740000}, {0x3a742000}, {0x3a744000}, {0x3a746000},
+ {0x3a748000}, {0x3a74a000}, {0x3a74c000}, {0x3a74e000},
+ {0x3a750000}, {0x3a752000}, {0x3a754000}, {0x3a756000},
+ {0x3a758000}, {0x3a75a000}, {0x3a75c000}, {0x3a75e000},
+ {0x3a760000}, {0x3a762000}, {0x3a764000}, {0x3a766000},
+ {0x3a768000}, {0x3a76a000}, {0x3a76c000}, {0x3a76e000},
+ {0x3a770000}, {0x3a772000}, {0x3a774000}, {0x3a776000},
+ {0x3a778000}, {0x3a77a000}, {0x3a77c000}, {0x3a77e000},
+ {0x3a780000}, {0x3a782000}, {0x3a784000}, {0x3a786000},
+ {0x3a788000}, {0x3a78a000}, {0x3a78c000}, {0x3a78e000},
+ {0x3a790000}, {0x3a792000}, {0x3a794000}, {0x3a796000},
+ {0x3a798000}, {0x3a79a000}, {0x3a79c000}, {0x3a79e000},
+ {0x3a7a0000}, {0x3a7a2000}, {0x3a7a4000}, {0x3a7a6000},
+ {0x3a7a8000}, {0x3a7aa000}, {0x3a7ac000}, {0x3a7ae000},
+ {0x3a7b0000}, {0x3a7b2000}, {0x3a7b4000}, {0x3a7b6000},
+ {0x3a7b8000}, {0x3a7ba000}, {0x3a7bc000}, {0x3a7be000},
+ {0x3a7c0000}, {0x3a7c2000}, {0x3a7c4000}, {0x3a7c6000},
+ {0x3a7c8000}, {0x3a7ca000}, {0x3a7cc000}, {0x3a7ce000},
+ {0x3a7d0000}, {0x3a7d2000}, {0x3a7d4000}, {0x3a7d6000},
+ {0x3a7d8000}, {0x3a7da000}, {0x3a7dc000}, {0x3a7de000},
+ {0x3a7e0000}, {0x3a7e2000}, {0x3a7e4000}, {0x3a7e6000},
+ {0x3a7e8000}, {0x3a7ea000}, {0x3a7ec000}, {0x3a7ee000},
+ {0x3a7f0000}, {0x3a7f2000}, {0x3a7f4000}, {0x3a7f6000},
+ {0x3a7f8000}, {0x3a7fa000}, {0x3a7fc000}, {0x3a7fe000},
+ {0x3a800000}, {0x3a802000}, {0x3a804000}, {0x3a806000},
+ {0x3a808000}, {0x3a80a000}, {0x3a80c000}, {0x3a80e000},
+ {0x3a810000}, {0x3a812000}, {0x3a814000}, {0x3a816000},
+ {0x3a818000}, {0x3a81a000}, {0x3a81c000}, {0x3a81e000},
+ {0x3a820000}, {0x3a822000}, {0x3a824000}, {0x3a826000},
+ {0x3a828000}, {0x3a82a000}, {0x3a82c000}, {0x3a82e000},
+ {0x3a830000}, {0x3a832000}, {0x3a834000}, {0x3a836000},
+ {0x3a838000}, {0x3a83a000}, {0x3a83c000}, {0x3a83e000},
+ {0x3a840000}, {0x3a842000}, {0x3a844000}, {0x3a846000},
+ {0x3a848000}, {0x3a84a000}, {0x3a84c000}, {0x3a84e000},
+ {0x3a850000}, {0x3a852000}, {0x3a854000}, {0x3a856000},
+ {0x3a858000}, {0x3a85a000}, {0x3a85c000}, {0x3a85e000},
+ {0x3a860000}, {0x3a862000}, {0x3a864000}, {0x3a866000},
+ {0x3a868000}, {0x3a86a000}, {0x3a86c000}, {0x3a86e000},
+ {0x3a870000}, {0x3a872000}, {0x3a874000}, {0x3a876000},
+ {0x3a878000}, {0x3a87a000}, {0x3a87c000}, {0x3a87e000},
+ {0x3a880000}, {0x3a882000}, {0x3a884000}, {0x3a886000},
+ {0x3a888000}, {0x3a88a000}, {0x3a88c000}, {0x3a88e000},
+ {0x3a890000}, {0x3a892000}, {0x3a894000}, {0x3a896000},
+ {0x3a898000}, {0x3a89a000}, {0x3a89c000}, {0x3a89e000},
+ {0x3a8a0000}, {0x3a8a2000}, {0x3a8a4000}, {0x3a8a6000},
+ {0x3a8a8000}, {0x3a8aa000}, {0x3a8ac000}, {0x3a8ae000},
+ {0x3a8b0000}, {0x3a8b2000}, {0x3a8b4000}, {0x3a8b6000},
+ {0x3a8b8000}, {0x3a8ba000}, {0x3a8bc000}, {0x3a8be000},
+ {0x3a8c0000}, {0x3a8c2000}, {0x3a8c4000}, {0x3a8c6000},
+ {0x3a8c8000}, {0x3a8ca000}, {0x3a8cc000}, {0x3a8ce000},
+ {0x3a8d0000}, {0x3a8d2000}, {0x3a8d4000}, {0x3a8d6000},
+ {0x3a8d8000}, {0x3a8da000}, {0x3a8dc000}, {0x3a8de000},
+ {0x3a8e0000}, {0x3a8e2000}, {0x3a8e4000}, {0x3a8e6000},
+ {0x3a8e8000}, {0x3a8ea000}, {0x3a8ec000}, {0x3a8ee000},
+ {0x3a8f0000}, {0x3a8f2000}, {0x3a8f4000}, {0x3a8f6000},
+ {0x3a8f8000}, {0x3a8fa000}, {0x3a8fc000}, {0x3a8fe000},
+ {0x3a900000}, {0x3a902000}, {0x3a904000}, {0x3a906000},
+ {0x3a908000}, {0x3a90a000}, {0x3a90c000}, {0x3a90e000},
+ {0x3a910000}, {0x3a912000}, {0x3a914000}, {0x3a916000},
+ {0x3a918000}, {0x3a91a000}, {0x3a91c000}, {0x3a91e000},
+ {0x3a920000}, {0x3a922000}, {0x3a924000}, {0x3a926000},
+ {0x3a928000}, {0x3a92a000}, {0x3a92c000}, {0x3a92e000},
+ {0x3a930000}, {0x3a932000}, {0x3a934000}, {0x3a936000},
+ {0x3a938000}, {0x3a93a000}, {0x3a93c000}, {0x3a93e000},
+ {0x3a940000}, {0x3a942000}, {0x3a944000}, {0x3a946000},
+ {0x3a948000}, {0x3a94a000}, {0x3a94c000}, {0x3a94e000},
+ {0x3a950000}, {0x3a952000}, {0x3a954000}, {0x3a956000},
+ {0x3a958000}, {0x3a95a000}, {0x3a95c000}, {0x3a95e000},
+ {0x3a960000}, {0x3a962000}, {0x3a964000}, {0x3a966000},
+ {0x3a968000}, {0x3a96a000}, {0x3a96c000}, {0x3a96e000},
+ {0x3a970000}, {0x3a972000}, {0x3a974000}, {0x3a976000},
+ {0x3a978000}, {0x3a97a000}, {0x3a97c000}, {0x3a97e000},
+ {0x3a980000}, {0x3a982000}, {0x3a984000}, {0x3a986000},
+ {0x3a988000}, {0x3a98a000}, {0x3a98c000}, {0x3a98e000},
+ {0x3a990000}, {0x3a992000}, {0x3a994000}, {0x3a996000},
+ {0x3a998000}, {0x3a99a000}, {0x3a99c000}, {0x3a99e000},
+ {0x3a9a0000}, {0x3a9a2000}, {0x3a9a4000}, {0x3a9a6000},
+ {0x3a9a8000}, {0x3a9aa000}, {0x3a9ac000}, {0x3a9ae000},
+ {0x3a9b0000}, {0x3a9b2000}, {0x3a9b4000}, {0x3a9b6000},
+ {0x3a9b8000}, {0x3a9ba000}, {0x3a9bc000}, {0x3a9be000},
+ {0x3a9c0000}, {0x3a9c2000}, {0x3a9c4000}, {0x3a9c6000},
+ {0x3a9c8000}, {0x3a9ca000}, {0x3a9cc000}, {0x3a9ce000},
+ {0x3a9d0000}, {0x3a9d2000}, {0x3a9d4000}, {0x3a9d6000},
+ {0x3a9d8000}, {0x3a9da000}, {0x3a9dc000}, {0x3a9de000},
+ {0x3a9e0000}, {0x3a9e2000}, {0x3a9e4000}, {0x3a9e6000},
+ {0x3a9e8000}, {0x3a9ea000}, {0x3a9ec000}, {0x3a9ee000},
+ {0x3a9f0000}, {0x3a9f2000}, {0x3a9f4000}, {0x3a9f6000},
+ {0x3a9f8000}, {0x3a9fa000}, {0x3a9fc000}, {0x3a9fe000},
+ {0x3aa00000}, {0x3aa02000}, {0x3aa04000}, {0x3aa06000},
+ {0x3aa08000}, {0x3aa0a000}, {0x3aa0c000}, {0x3aa0e000},
+ {0x3aa10000}, {0x3aa12000}, {0x3aa14000}, {0x3aa16000},
+ {0x3aa18000}, {0x3aa1a000}, {0x3aa1c000}, {0x3aa1e000},
+ {0x3aa20000}, {0x3aa22000}, {0x3aa24000}, {0x3aa26000},
+ {0x3aa28000}, {0x3aa2a000}, {0x3aa2c000}, {0x3aa2e000},
+ {0x3aa30000}, {0x3aa32000}, {0x3aa34000}, {0x3aa36000},
+ {0x3aa38000}, {0x3aa3a000}, {0x3aa3c000}, {0x3aa3e000},
+ {0x3aa40000}, {0x3aa42000}, {0x3aa44000}, {0x3aa46000},
+ {0x3aa48000}, {0x3aa4a000}, {0x3aa4c000}, {0x3aa4e000},
+ {0x3aa50000}, {0x3aa52000}, {0x3aa54000}, {0x3aa56000},
+ {0x3aa58000}, {0x3aa5a000}, {0x3aa5c000}, {0x3aa5e000},
+ {0x3aa60000}, {0x3aa62000}, {0x3aa64000}, {0x3aa66000},
+ {0x3aa68000}, {0x3aa6a000}, {0x3aa6c000}, {0x3aa6e000},
+ {0x3aa70000}, {0x3aa72000}, {0x3aa74000}, {0x3aa76000},
+ {0x3aa78000}, {0x3aa7a000}, {0x3aa7c000}, {0x3aa7e000},
+ {0x3aa80000}, {0x3aa82000}, {0x3aa84000}, {0x3aa86000},
+ {0x3aa88000}, {0x3aa8a000}, {0x3aa8c000}, {0x3aa8e000},
+ {0x3aa90000}, {0x3aa92000}, {0x3aa94000}, {0x3aa96000},
+ {0x3aa98000}, {0x3aa9a000}, {0x3aa9c000}, {0x3aa9e000},
+ {0x3aaa0000}, {0x3aaa2000}, {0x3aaa4000}, {0x3aaa6000},
+ {0x3aaa8000}, {0x3aaaa000}, {0x3aaac000}, {0x3aaae000},
+ {0x3aab0000}, {0x3aab2000}, {0x3aab4000}, {0x3aab6000},
+ {0x3aab8000}, {0x3aaba000}, {0x3aabc000}, {0x3aabe000},
+ {0x3aac0000}, {0x3aac2000}, {0x3aac4000}, {0x3aac6000},
+ {0x3aac8000}, {0x3aaca000}, {0x3aacc000}, {0x3aace000},
+ {0x3aad0000}, {0x3aad2000}, {0x3aad4000}, {0x3aad6000},
+ {0x3aad8000}, {0x3aada000}, {0x3aadc000}, {0x3aade000},
+ {0x3aae0000}, {0x3aae2000}, {0x3aae4000}, {0x3aae6000},
+ {0x3aae8000}, {0x3aaea000}, {0x3aaec000}, {0x3aaee000},
+ {0x3aaf0000}, {0x3aaf2000}, {0x3aaf4000}, {0x3aaf6000},
+ {0x3aaf8000}, {0x3aafa000}, {0x3aafc000}, {0x3aafe000},
+ {0x3ab00000}, {0x3ab02000}, {0x3ab04000}, {0x3ab06000},
+ {0x3ab08000}, {0x3ab0a000}, {0x3ab0c000}, {0x3ab0e000},
+ {0x3ab10000}, {0x3ab12000}, {0x3ab14000}, {0x3ab16000},
+ {0x3ab18000}, {0x3ab1a000}, {0x3ab1c000}, {0x3ab1e000},
+ {0x3ab20000}, {0x3ab22000}, {0x3ab24000}, {0x3ab26000},
+ {0x3ab28000}, {0x3ab2a000}, {0x3ab2c000}, {0x3ab2e000},
+ {0x3ab30000}, {0x3ab32000}, {0x3ab34000}, {0x3ab36000},
+ {0x3ab38000}, {0x3ab3a000}, {0x3ab3c000}, {0x3ab3e000},
+ {0x3ab40000}, {0x3ab42000}, {0x3ab44000}, {0x3ab46000},
+ {0x3ab48000}, {0x3ab4a000}, {0x3ab4c000}, {0x3ab4e000},
+ {0x3ab50000}, {0x3ab52000}, {0x3ab54000}, {0x3ab56000},
+ {0x3ab58000}, {0x3ab5a000}, {0x3ab5c000}, {0x3ab5e000},
+ {0x3ab60000}, {0x3ab62000}, {0x3ab64000}, {0x3ab66000},
+ {0x3ab68000}, {0x3ab6a000}, {0x3ab6c000}, {0x3ab6e000},
+ {0x3ab70000}, {0x3ab72000}, {0x3ab74000}, {0x3ab76000},
+ {0x3ab78000}, {0x3ab7a000}, {0x3ab7c000}, {0x3ab7e000},
+ {0x3ab80000}, {0x3ab82000}, {0x3ab84000}, {0x3ab86000},
+ {0x3ab88000}, {0x3ab8a000}, {0x3ab8c000}, {0x3ab8e000},
+ {0x3ab90000}, {0x3ab92000}, {0x3ab94000}, {0x3ab96000},
+ {0x3ab98000}, {0x3ab9a000}, {0x3ab9c000}, {0x3ab9e000},
+ {0x3aba0000}, {0x3aba2000}, {0x3aba4000}, {0x3aba6000},
+ {0x3aba8000}, {0x3abaa000}, {0x3abac000}, {0x3abae000},
+ {0x3abb0000}, {0x3abb2000}, {0x3abb4000}, {0x3abb6000},
+ {0x3abb8000}, {0x3abba000}, {0x3abbc000}, {0x3abbe000},
+ {0x3abc0000}, {0x3abc2000}, {0x3abc4000}, {0x3abc6000},
+ {0x3abc8000}, {0x3abca000}, {0x3abcc000}, {0x3abce000},
+ {0x3abd0000}, {0x3abd2000}, {0x3abd4000}, {0x3abd6000},
+ {0x3abd8000}, {0x3abda000}, {0x3abdc000}, {0x3abde000},
+ {0x3abe0000}, {0x3abe2000}, {0x3abe4000}, {0x3abe6000},
+ {0x3abe8000}, {0x3abea000}, {0x3abec000}, {0x3abee000},
+ {0x3abf0000}, {0x3abf2000}, {0x3abf4000}, {0x3abf6000},
+ {0x3abf8000}, {0x3abfa000}, {0x3abfc000}, {0x3abfe000},
+ {0x3ac00000}, {0x3ac02000}, {0x3ac04000}, {0x3ac06000},
+ {0x3ac08000}, {0x3ac0a000}, {0x3ac0c000}, {0x3ac0e000},
+ {0x3ac10000}, {0x3ac12000}, {0x3ac14000}, {0x3ac16000},
+ {0x3ac18000}, {0x3ac1a000}, {0x3ac1c000}, {0x3ac1e000},
+ {0x3ac20000}, {0x3ac22000}, {0x3ac24000}, {0x3ac26000},
+ {0x3ac28000}, {0x3ac2a000}, {0x3ac2c000}, {0x3ac2e000},
+ {0x3ac30000}, {0x3ac32000}, {0x3ac34000}, {0x3ac36000},
+ {0x3ac38000}, {0x3ac3a000}, {0x3ac3c000}, {0x3ac3e000},
+ {0x3ac40000}, {0x3ac42000}, {0x3ac44000}, {0x3ac46000},
+ {0x3ac48000}, {0x3ac4a000}, {0x3ac4c000}, {0x3ac4e000},
+ {0x3ac50000}, {0x3ac52000}, {0x3ac54000}, {0x3ac56000},
+ {0x3ac58000}, {0x3ac5a000}, {0x3ac5c000}, {0x3ac5e000},
+ {0x3ac60000}, {0x3ac62000}, {0x3ac64000}, {0x3ac66000},
+ {0x3ac68000}, {0x3ac6a000}, {0x3ac6c000}, {0x3ac6e000},
+ {0x3ac70000}, {0x3ac72000}, {0x3ac74000}, {0x3ac76000},
+ {0x3ac78000}, {0x3ac7a000}, {0x3ac7c000}, {0x3ac7e000},
+ {0x3ac80000}, {0x3ac82000}, {0x3ac84000}, {0x3ac86000},
+ {0x3ac88000}, {0x3ac8a000}, {0x3ac8c000}, {0x3ac8e000},
+ {0x3ac90000}, {0x3ac92000}, {0x3ac94000}, {0x3ac96000},
+ {0x3ac98000}, {0x3ac9a000}, {0x3ac9c000}, {0x3ac9e000},
+ {0x3aca0000}, {0x3aca2000}, {0x3aca4000}, {0x3aca6000},
+ {0x3aca8000}, {0x3acaa000}, {0x3acac000}, {0x3acae000},
+ {0x3acb0000}, {0x3acb2000}, {0x3acb4000}, {0x3acb6000},
+ {0x3acb8000}, {0x3acba000}, {0x3acbc000}, {0x3acbe000},
+ {0x3acc0000}, {0x3acc2000}, {0x3acc4000}, {0x3acc6000},
+ {0x3acc8000}, {0x3acca000}, {0x3accc000}, {0x3acce000},
+ {0x3acd0000}, {0x3acd2000}, {0x3acd4000}, {0x3acd6000},
+ {0x3acd8000}, {0x3acda000}, {0x3acdc000}, {0x3acde000},
+ {0x3ace0000}, {0x3ace2000}, {0x3ace4000}, {0x3ace6000},
+ {0x3ace8000}, {0x3acea000}, {0x3acec000}, {0x3acee000},
+ {0x3acf0000}, {0x3acf2000}, {0x3acf4000}, {0x3acf6000},
+ {0x3acf8000}, {0x3acfa000}, {0x3acfc000}, {0x3acfe000},
+ {0x3ad00000}, {0x3ad02000}, {0x3ad04000}, {0x3ad06000},
+ {0x3ad08000}, {0x3ad0a000}, {0x3ad0c000}, {0x3ad0e000},
+ {0x3ad10000}, {0x3ad12000}, {0x3ad14000}, {0x3ad16000},
+ {0x3ad18000}, {0x3ad1a000}, {0x3ad1c000}, {0x3ad1e000},
+ {0x3ad20000}, {0x3ad22000}, {0x3ad24000}, {0x3ad26000},
+ {0x3ad28000}, {0x3ad2a000}, {0x3ad2c000}, {0x3ad2e000},
+ {0x3ad30000}, {0x3ad32000}, {0x3ad34000}, {0x3ad36000},
+ {0x3ad38000}, {0x3ad3a000}, {0x3ad3c000}, {0x3ad3e000},
+ {0x3ad40000}, {0x3ad42000}, {0x3ad44000}, {0x3ad46000},
+ {0x3ad48000}, {0x3ad4a000}, {0x3ad4c000}, {0x3ad4e000},
+ {0x3ad50000}, {0x3ad52000}, {0x3ad54000}, {0x3ad56000},
+ {0x3ad58000}, {0x3ad5a000}, {0x3ad5c000}, {0x3ad5e000},
+ {0x3ad60000}, {0x3ad62000}, {0x3ad64000}, {0x3ad66000},
+ {0x3ad68000}, {0x3ad6a000}, {0x3ad6c000}, {0x3ad6e000},
+ {0x3ad70000}, {0x3ad72000}, {0x3ad74000}, {0x3ad76000},
+ {0x3ad78000}, {0x3ad7a000}, {0x3ad7c000}, {0x3ad7e000},
+ {0x3ad80000}, {0x3ad82000}, {0x3ad84000}, {0x3ad86000},
+ {0x3ad88000}, {0x3ad8a000}, {0x3ad8c000}, {0x3ad8e000},
+ {0x3ad90000}, {0x3ad92000}, {0x3ad94000}, {0x3ad96000},
+ {0x3ad98000}, {0x3ad9a000}, {0x3ad9c000}, {0x3ad9e000},
+ {0x3ada0000}, {0x3ada2000}, {0x3ada4000}, {0x3ada6000},
+ {0x3ada8000}, {0x3adaa000}, {0x3adac000}, {0x3adae000},
+ {0x3adb0000}, {0x3adb2000}, {0x3adb4000}, {0x3adb6000},
+ {0x3adb8000}, {0x3adba000}, {0x3adbc000}, {0x3adbe000},
+ {0x3adc0000}, {0x3adc2000}, {0x3adc4000}, {0x3adc6000},
+ {0x3adc8000}, {0x3adca000}, {0x3adcc000}, {0x3adce000},
+ {0x3add0000}, {0x3add2000}, {0x3add4000}, {0x3add6000},
+ {0x3add8000}, {0x3adda000}, {0x3addc000}, {0x3adde000},
+ {0x3ade0000}, {0x3ade2000}, {0x3ade4000}, {0x3ade6000},
+ {0x3ade8000}, {0x3adea000}, {0x3adec000}, {0x3adee000},
+ {0x3adf0000}, {0x3adf2000}, {0x3adf4000}, {0x3adf6000},
+ {0x3adf8000}, {0x3adfa000}, {0x3adfc000}, {0x3adfe000},
+ {0x3ae00000}, {0x3ae02000}, {0x3ae04000}, {0x3ae06000},
+ {0x3ae08000}, {0x3ae0a000}, {0x3ae0c000}, {0x3ae0e000},
+ {0x3ae10000}, {0x3ae12000}, {0x3ae14000}, {0x3ae16000},
+ {0x3ae18000}, {0x3ae1a000}, {0x3ae1c000}, {0x3ae1e000},
+ {0x3ae20000}, {0x3ae22000}, {0x3ae24000}, {0x3ae26000},
+ {0x3ae28000}, {0x3ae2a000}, {0x3ae2c000}, {0x3ae2e000},
+ {0x3ae30000}, {0x3ae32000}, {0x3ae34000}, {0x3ae36000},
+ {0x3ae38000}, {0x3ae3a000}, {0x3ae3c000}, {0x3ae3e000},
+ {0x3ae40000}, {0x3ae42000}, {0x3ae44000}, {0x3ae46000},
+ {0x3ae48000}, {0x3ae4a000}, {0x3ae4c000}, {0x3ae4e000},
+ {0x3ae50000}, {0x3ae52000}, {0x3ae54000}, {0x3ae56000},
+ {0x3ae58000}, {0x3ae5a000}, {0x3ae5c000}, {0x3ae5e000},
+ {0x3ae60000}, {0x3ae62000}, {0x3ae64000}, {0x3ae66000},
+ {0x3ae68000}, {0x3ae6a000}, {0x3ae6c000}, {0x3ae6e000},
+ {0x3ae70000}, {0x3ae72000}, {0x3ae74000}, {0x3ae76000},
+ {0x3ae78000}, {0x3ae7a000}, {0x3ae7c000}, {0x3ae7e000},
+ {0x3ae80000}, {0x3ae82000}, {0x3ae84000}, {0x3ae86000},
+ {0x3ae88000}, {0x3ae8a000}, {0x3ae8c000}, {0x3ae8e000},
+ {0x3ae90000}, {0x3ae92000}, {0x3ae94000}, {0x3ae96000},
+ {0x3ae98000}, {0x3ae9a000}, {0x3ae9c000}, {0x3ae9e000},
+ {0x3aea0000}, {0x3aea2000}, {0x3aea4000}, {0x3aea6000},
+ {0x3aea8000}, {0x3aeaa000}, {0x3aeac000}, {0x3aeae000},
+ {0x3aeb0000}, {0x3aeb2000}, {0x3aeb4000}, {0x3aeb6000},
+ {0x3aeb8000}, {0x3aeba000}, {0x3aebc000}, {0x3aebe000},
+ {0x3aec0000}, {0x3aec2000}, {0x3aec4000}, {0x3aec6000},
+ {0x3aec8000}, {0x3aeca000}, {0x3aecc000}, {0x3aece000},
+ {0x3aed0000}, {0x3aed2000}, {0x3aed4000}, {0x3aed6000},
+ {0x3aed8000}, {0x3aeda000}, {0x3aedc000}, {0x3aede000},
+ {0x3aee0000}, {0x3aee2000}, {0x3aee4000}, {0x3aee6000},
+ {0x3aee8000}, {0x3aeea000}, {0x3aeec000}, {0x3aeee000},
+ {0x3aef0000}, {0x3aef2000}, {0x3aef4000}, {0x3aef6000},
+ {0x3aef8000}, {0x3aefa000}, {0x3aefc000}, {0x3aefe000},
+ {0x3af00000}, {0x3af02000}, {0x3af04000}, {0x3af06000},
+ {0x3af08000}, {0x3af0a000}, {0x3af0c000}, {0x3af0e000},
+ {0x3af10000}, {0x3af12000}, {0x3af14000}, {0x3af16000},
+ {0x3af18000}, {0x3af1a000}, {0x3af1c000}, {0x3af1e000},
+ {0x3af20000}, {0x3af22000}, {0x3af24000}, {0x3af26000},
+ {0x3af28000}, {0x3af2a000}, {0x3af2c000}, {0x3af2e000},
+ {0x3af30000}, {0x3af32000}, {0x3af34000}, {0x3af36000},
+ {0x3af38000}, {0x3af3a000}, {0x3af3c000}, {0x3af3e000},
+ {0x3af40000}, {0x3af42000}, {0x3af44000}, {0x3af46000},
+ {0x3af48000}, {0x3af4a000}, {0x3af4c000}, {0x3af4e000},
+ {0x3af50000}, {0x3af52000}, {0x3af54000}, {0x3af56000},
+ {0x3af58000}, {0x3af5a000}, {0x3af5c000}, {0x3af5e000},
+ {0x3af60000}, {0x3af62000}, {0x3af64000}, {0x3af66000},
+ {0x3af68000}, {0x3af6a000}, {0x3af6c000}, {0x3af6e000},
+ {0x3af70000}, {0x3af72000}, {0x3af74000}, {0x3af76000},
+ {0x3af78000}, {0x3af7a000}, {0x3af7c000}, {0x3af7e000},
+ {0x3af80000}, {0x3af82000}, {0x3af84000}, {0x3af86000},
+ {0x3af88000}, {0x3af8a000}, {0x3af8c000}, {0x3af8e000},
+ {0x3af90000}, {0x3af92000}, {0x3af94000}, {0x3af96000},
+ {0x3af98000}, {0x3af9a000}, {0x3af9c000}, {0x3af9e000},
+ {0x3afa0000}, {0x3afa2000}, {0x3afa4000}, {0x3afa6000},
+ {0x3afa8000}, {0x3afaa000}, {0x3afac000}, {0x3afae000},
+ {0x3afb0000}, {0x3afb2000}, {0x3afb4000}, {0x3afb6000},
+ {0x3afb8000}, {0x3afba000}, {0x3afbc000}, {0x3afbe000},
+ {0x3afc0000}, {0x3afc2000}, {0x3afc4000}, {0x3afc6000},
+ {0x3afc8000}, {0x3afca000}, {0x3afcc000}, {0x3afce000},
+ {0x3afd0000}, {0x3afd2000}, {0x3afd4000}, {0x3afd6000},
+ {0x3afd8000}, {0x3afda000}, {0x3afdc000}, {0x3afde000},
+ {0x3afe0000}, {0x3afe2000}, {0x3afe4000}, {0x3afe6000},
+ {0x3afe8000}, {0x3afea000}, {0x3afec000}, {0x3afee000},
+ {0x3aff0000}, {0x3aff2000}, {0x3aff4000}, {0x3aff6000},
+ {0x3aff8000}, {0x3affa000}, {0x3affc000}, {0x3affe000},
+ {0x3b000000}, {0x3b002000}, {0x3b004000}, {0x3b006000},
+ {0x3b008000}, {0x3b00a000}, {0x3b00c000}, {0x3b00e000},
+ {0x3b010000}, {0x3b012000}, {0x3b014000}, {0x3b016000},
+ {0x3b018000}, {0x3b01a000}, {0x3b01c000}, {0x3b01e000},
+ {0x3b020000}, {0x3b022000}, {0x3b024000}, {0x3b026000},
+ {0x3b028000}, {0x3b02a000}, {0x3b02c000}, {0x3b02e000},
+ {0x3b030000}, {0x3b032000}, {0x3b034000}, {0x3b036000},
+ {0x3b038000}, {0x3b03a000}, {0x3b03c000}, {0x3b03e000},
+ {0x3b040000}, {0x3b042000}, {0x3b044000}, {0x3b046000},
+ {0x3b048000}, {0x3b04a000}, {0x3b04c000}, {0x3b04e000},
+ {0x3b050000}, {0x3b052000}, {0x3b054000}, {0x3b056000},
+ {0x3b058000}, {0x3b05a000}, {0x3b05c000}, {0x3b05e000},
+ {0x3b060000}, {0x3b062000}, {0x3b064000}, {0x3b066000},
+ {0x3b068000}, {0x3b06a000}, {0x3b06c000}, {0x3b06e000},
+ {0x3b070000}, {0x3b072000}, {0x3b074000}, {0x3b076000},
+ {0x3b078000}, {0x3b07a000}, {0x3b07c000}, {0x3b07e000},
+ {0x3b080000}, {0x3b082000}, {0x3b084000}, {0x3b086000},
+ {0x3b088000}, {0x3b08a000}, {0x3b08c000}, {0x3b08e000},
+ {0x3b090000}, {0x3b092000}, {0x3b094000}, {0x3b096000},
+ {0x3b098000}, {0x3b09a000}, {0x3b09c000}, {0x3b09e000},
+ {0x3b0a0000}, {0x3b0a2000}, {0x3b0a4000}, {0x3b0a6000},
+ {0x3b0a8000}, {0x3b0aa000}, {0x3b0ac000}, {0x3b0ae000},
+ {0x3b0b0000}, {0x3b0b2000}, {0x3b0b4000}, {0x3b0b6000},
+ {0x3b0b8000}, {0x3b0ba000}, {0x3b0bc000}, {0x3b0be000},
+ {0x3b0c0000}, {0x3b0c2000}, {0x3b0c4000}, {0x3b0c6000},
+ {0x3b0c8000}, {0x3b0ca000}, {0x3b0cc000}, {0x3b0ce000},
+ {0x3b0d0000}, {0x3b0d2000}, {0x3b0d4000}, {0x3b0d6000},
+ {0x3b0d8000}, {0x3b0da000}, {0x3b0dc000}, {0x3b0de000},
+ {0x3b0e0000}, {0x3b0e2000}, {0x3b0e4000}, {0x3b0e6000},
+ {0x3b0e8000}, {0x3b0ea000}, {0x3b0ec000}, {0x3b0ee000},
+ {0x3b0f0000}, {0x3b0f2000}, {0x3b0f4000}, {0x3b0f6000},
+ {0x3b0f8000}, {0x3b0fa000}, {0x3b0fc000}, {0x3b0fe000},
+ {0x3b100000}, {0x3b102000}, {0x3b104000}, {0x3b106000},
+ {0x3b108000}, {0x3b10a000}, {0x3b10c000}, {0x3b10e000},
+ {0x3b110000}, {0x3b112000}, {0x3b114000}, {0x3b116000},
+ {0x3b118000}, {0x3b11a000}, {0x3b11c000}, {0x3b11e000},
+ {0x3b120000}, {0x3b122000}, {0x3b124000}, {0x3b126000},
+ {0x3b128000}, {0x3b12a000}, {0x3b12c000}, {0x3b12e000},
+ {0x3b130000}, {0x3b132000}, {0x3b134000}, {0x3b136000},
+ {0x3b138000}, {0x3b13a000}, {0x3b13c000}, {0x3b13e000},
+ {0x3b140000}, {0x3b142000}, {0x3b144000}, {0x3b146000},
+ {0x3b148000}, {0x3b14a000}, {0x3b14c000}, {0x3b14e000},
+ {0x3b150000}, {0x3b152000}, {0x3b154000}, {0x3b156000},
+ {0x3b158000}, {0x3b15a000}, {0x3b15c000}, {0x3b15e000},
+ {0x3b160000}, {0x3b162000}, {0x3b164000}, {0x3b166000},
+ {0x3b168000}, {0x3b16a000}, {0x3b16c000}, {0x3b16e000},
+ {0x3b170000}, {0x3b172000}, {0x3b174000}, {0x3b176000},
+ {0x3b178000}, {0x3b17a000}, {0x3b17c000}, {0x3b17e000},
+ {0x3b180000}, {0x3b182000}, {0x3b184000}, {0x3b186000},
+ {0x3b188000}, {0x3b18a000}, {0x3b18c000}, {0x3b18e000},
+ {0x3b190000}, {0x3b192000}, {0x3b194000}, {0x3b196000},
+ {0x3b198000}, {0x3b19a000}, {0x3b19c000}, {0x3b19e000},
+ {0x3b1a0000}, {0x3b1a2000}, {0x3b1a4000}, {0x3b1a6000},
+ {0x3b1a8000}, {0x3b1aa000}, {0x3b1ac000}, {0x3b1ae000},
+ {0x3b1b0000}, {0x3b1b2000}, {0x3b1b4000}, {0x3b1b6000},
+ {0x3b1b8000}, {0x3b1ba000}, {0x3b1bc000}, {0x3b1be000},
+ {0x3b1c0000}, {0x3b1c2000}, {0x3b1c4000}, {0x3b1c6000},
+ {0x3b1c8000}, {0x3b1ca000}, {0x3b1cc000}, {0x3b1ce000},
+ {0x3b1d0000}, {0x3b1d2000}, {0x3b1d4000}, {0x3b1d6000},
+ {0x3b1d8000}, {0x3b1da000}, {0x3b1dc000}, {0x3b1de000},
+ {0x3b1e0000}, {0x3b1e2000}, {0x3b1e4000}, {0x3b1e6000},
+ {0x3b1e8000}, {0x3b1ea000}, {0x3b1ec000}, {0x3b1ee000},
+ {0x3b1f0000}, {0x3b1f2000}, {0x3b1f4000}, {0x3b1f6000},
+ {0x3b1f8000}, {0x3b1fa000}, {0x3b1fc000}, {0x3b1fe000},
+ {0x3b200000}, {0x3b202000}, {0x3b204000}, {0x3b206000},
+ {0x3b208000}, {0x3b20a000}, {0x3b20c000}, {0x3b20e000},
+ {0x3b210000}, {0x3b212000}, {0x3b214000}, {0x3b216000},
+ {0x3b218000}, {0x3b21a000}, {0x3b21c000}, {0x3b21e000},
+ {0x3b220000}, {0x3b222000}, {0x3b224000}, {0x3b226000},
+ {0x3b228000}, {0x3b22a000}, {0x3b22c000}, {0x3b22e000},
+ {0x3b230000}, {0x3b232000}, {0x3b234000}, {0x3b236000},
+ {0x3b238000}, {0x3b23a000}, {0x3b23c000}, {0x3b23e000},
+ {0x3b240000}, {0x3b242000}, {0x3b244000}, {0x3b246000},
+ {0x3b248000}, {0x3b24a000}, {0x3b24c000}, {0x3b24e000},
+ {0x3b250000}, {0x3b252000}, {0x3b254000}, {0x3b256000},
+ {0x3b258000}, {0x3b25a000}, {0x3b25c000}, {0x3b25e000},
+ {0x3b260000}, {0x3b262000}, {0x3b264000}, {0x3b266000},
+ {0x3b268000}, {0x3b26a000}, {0x3b26c000}, {0x3b26e000},
+ {0x3b270000}, {0x3b272000}, {0x3b274000}, {0x3b276000},
+ {0x3b278000}, {0x3b27a000}, {0x3b27c000}, {0x3b27e000},
+ {0x3b280000}, {0x3b282000}, {0x3b284000}, {0x3b286000},
+ {0x3b288000}, {0x3b28a000}, {0x3b28c000}, {0x3b28e000},
+ {0x3b290000}, {0x3b292000}, {0x3b294000}, {0x3b296000},
+ {0x3b298000}, {0x3b29a000}, {0x3b29c000}, {0x3b29e000},
+ {0x3b2a0000}, {0x3b2a2000}, {0x3b2a4000}, {0x3b2a6000},
+ {0x3b2a8000}, {0x3b2aa000}, {0x3b2ac000}, {0x3b2ae000},
+ {0x3b2b0000}, {0x3b2b2000}, {0x3b2b4000}, {0x3b2b6000},
+ {0x3b2b8000}, {0x3b2ba000}, {0x3b2bc000}, {0x3b2be000},
+ {0x3b2c0000}, {0x3b2c2000}, {0x3b2c4000}, {0x3b2c6000},
+ {0x3b2c8000}, {0x3b2ca000}, {0x3b2cc000}, {0x3b2ce000},
+ {0x3b2d0000}, {0x3b2d2000}, {0x3b2d4000}, {0x3b2d6000},
+ {0x3b2d8000}, {0x3b2da000}, {0x3b2dc000}, {0x3b2de000},
+ {0x3b2e0000}, {0x3b2e2000}, {0x3b2e4000}, {0x3b2e6000},
+ {0x3b2e8000}, {0x3b2ea000}, {0x3b2ec000}, {0x3b2ee000},
+ {0x3b2f0000}, {0x3b2f2000}, {0x3b2f4000}, {0x3b2f6000},
+ {0x3b2f8000}, {0x3b2fa000}, {0x3b2fc000}, {0x3b2fe000},
+ {0x3b300000}, {0x3b302000}, {0x3b304000}, {0x3b306000},
+ {0x3b308000}, {0x3b30a000}, {0x3b30c000}, {0x3b30e000},
+ {0x3b310000}, {0x3b312000}, {0x3b314000}, {0x3b316000},
+ {0x3b318000}, {0x3b31a000}, {0x3b31c000}, {0x3b31e000},
+ {0x3b320000}, {0x3b322000}, {0x3b324000}, {0x3b326000},
+ {0x3b328000}, {0x3b32a000}, {0x3b32c000}, {0x3b32e000},
+ {0x3b330000}, {0x3b332000}, {0x3b334000}, {0x3b336000},
+ {0x3b338000}, {0x3b33a000}, {0x3b33c000}, {0x3b33e000},
+ {0x3b340000}, {0x3b342000}, {0x3b344000}, {0x3b346000},
+ {0x3b348000}, {0x3b34a000}, {0x3b34c000}, {0x3b34e000},
+ {0x3b350000}, {0x3b352000}, {0x3b354000}, {0x3b356000},
+ {0x3b358000}, {0x3b35a000}, {0x3b35c000}, {0x3b35e000},
+ {0x3b360000}, {0x3b362000}, {0x3b364000}, {0x3b366000},
+ {0x3b368000}, {0x3b36a000}, {0x3b36c000}, {0x3b36e000},
+ {0x3b370000}, {0x3b372000}, {0x3b374000}, {0x3b376000},
+ {0x3b378000}, {0x3b37a000}, {0x3b37c000}, {0x3b37e000},
+ {0x3b380000}, {0x3b382000}, {0x3b384000}, {0x3b386000},
+ {0x3b388000}, {0x3b38a000}, {0x3b38c000}, {0x3b38e000},
+ {0x3b390000}, {0x3b392000}, {0x3b394000}, {0x3b396000},
+ {0x3b398000}, {0x3b39a000}, {0x3b39c000}, {0x3b39e000},
+ {0x3b3a0000}, {0x3b3a2000}, {0x3b3a4000}, {0x3b3a6000},
+ {0x3b3a8000}, {0x3b3aa000}, {0x3b3ac000}, {0x3b3ae000},
+ {0x3b3b0000}, {0x3b3b2000}, {0x3b3b4000}, {0x3b3b6000},
+ {0x3b3b8000}, {0x3b3ba000}, {0x3b3bc000}, {0x3b3be000},
+ {0x3b3c0000}, {0x3b3c2000}, {0x3b3c4000}, {0x3b3c6000},
+ {0x3b3c8000}, {0x3b3ca000}, {0x3b3cc000}, {0x3b3ce000},
+ {0x3b3d0000}, {0x3b3d2000}, {0x3b3d4000}, {0x3b3d6000},
+ {0x3b3d8000}, {0x3b3da000}, {0x3b3dc000}, {0x3b3de000},
+ {0x3b3e0000}, {0x3b3e2000}, {0x3b3e4000}, {0x3b3e6000},
+ {0x3b3e8000}, {0x3b3ea000}, {0x3b3ec000}, {0x3b3ee000},
+ {0x3b3f0000}, {0x3b3f2000}, {0x3b3f4000}, {0x3b3f6000},
+ {0x3b3f8000}, {0x3b3fa000}, {0x3b3fc000}, {0x3b3fe000},
+ {0x3b400000}, {0x3b402000}, {0x3b404000}, {0x3b406000},
+ {0x3b408000}, {0x3b40a000}, {0x3b40c000}, {0x3b40e000},
+ {0x3b410000}, {0x3b412000}, {0x3b414000}, {0x3b416000},
+ {0x3b418000}, {0x3b41a000}, {0x3b41c000}, {0x3b41e000},
+ {0x3b420000}, {0x3b422000}, {0x3b424000}, {0x3b426000},
+ {0x3b428000}, {0x3b42a000}, {0x3b42c000}, {0x3b42e000},
+ {0x3b430000}, {0x3b432000}, {0x3b434000}, {0x3b436000},
+ {0x3b438000}, {0x3b43a000}, {0x3b43c000}, {0x3b43e000},
+ {0x3b440000}, {0x3b442000}, {0x3b444000}, {0x3b446000},
+ {0x3b448000}, {0x3b44a000}, {0x3b44c000}, {0x3b44e000},
+ {0x3b450000}, {0x3b452000}, {0x3b454000}, {0x3b456000},
+ {0x3b458000}, {0x3b45a000}, {0x3b45c000}, {0x3b45e000},
+ {0x3b460000}, {0x3b462000}, {0x3b464000}, {0x3b466000},
+ {0x3b468000}, {0x3b46a000}, {0x3b46c000}, {0x3b46e000},
+ {0x3b470000}, {0x3b472000}, {0x3b474000}, {0x3b476000},
+ {0x3b478000}, {0x3b47a000}, {0x3b47c000}, {0x3b47e000},
+ {0x3b480000}, {0x3b482000}, {0x3b484000}, {0x3b486000},
+ {0x3b488000}, {0x3b48a000}, {0x3b48c000}, {0x3b48e000},
+ {0x3b490000}, {0x3b492000}, {0x3b494000}, {0x3b496000},
+ {0x3b498000}, {0x3b49a000}, {0x3b49c000}, {0x3b49e000},
+ {0x3b4a0000}, {0x3b4a2000}, {0x3b4a4000}, {0x3b4a6000},
+ {0x3b4a8000}, {0x3b4aa000}, {0x3b4ac000}, {0x3b4ae000},
+ {0x3b4b0000}, {0x3b4b2000}, {0x3b4b4000}, {0x3b4b6000},
+ {0x3b4b8000}, {0x3b4ba000}, {0x3b4bc000}, {0x3b4be000},
+ {0x3b4c0000}, {0x3b4c2000}, {0x3b4c4000}, {0x3b4c6000},
+ {0x3b4c8000}, {0x3b4ca000}, {0x3b4cc000}, {0x3b4ce000},
+ {0x3b4d0000}, {0x3b4d2000}, {0x3b4d4000}, {0x3b4d6000},
+ {0x3b4d8000}, {0x3b4da000}, {0x3b4dc000}, {0x3b4de000},
+ {0x3b4e0000}, {0x3b4e2000}, {0x3b4e4000}, {0x3b4e6000},
+ {0x3b4e8000}, {0x3b4ea000}, {0x3b4ec000}, {0x3b4ee000},
+ {0x3b4f0000}, {0x3b4f2000}, {0x3b4f4000}, {0x3b4f6000},
+ {0x3b4f8000}, {0x3b4fa000}, {0x3b4fc000}, {0x3b4fe000},
+ {0x3b500000}, {0x3b502000}, {0x3b504000}, {0x3b506000},
+ {0x3b508000}, {0x3b50a000}, {0x3b50c000}, {0x3b50e000},
+ {0x3b510000}, {0x3b512000}, {0x3b514000}, {0x3b516000},
+ {0x3b518000}, {0x3b51a000}, {0x3b51c000}, {0x3b51e000},
+ {0x3b520000}, {0x3b522000}, {0x3b524000}, {0x3b526000},
+ {0x3b528000}, {0x3b52a000}, {0x3b52c000}, {0x3b52e000},
+ {0x3b530000}, {0x3b532000}, {0x3b534000}, {0x3b536000},
+ {0x3b538000}, {0x3b53a000}, {0x3b53c000}, {0x3b53e000},
+ {0x3b540000}, {0x3b542000}, {0x3b544000}, {0x3b546000},
+ {0x3b548000}, {0x3b54a000}, {0x3b54c000}, {0x3b54e000},
+ {0x3b550000}, {0x3b552000}, {0x3b554000}, {0x3b556000},
+ {0x3b558000}, {0x3b55a000}, {0x3b55c000}, {0x3b55e000},
+ {0x3b560000}, {0x3b562000}, {0x3b564000}, {0x3b566000},
+ {0x3b568000}, {0x3b56a000}, {0x3b56c000}, {0x3b56e000},
+ {0x3b570000}, {0x3b572000}, {0x3b574000}, {0x3b576000},
+ {0x3b578000}, {0x3b57a000}, {0x3b57c000}, {0x3b57e000},
+ {0x3b580000}, {0x3b582000}, {0x3b584000}, {0x3b586000},
+ {0x3b588000}, {0x3b58a000}, {0x3b58c000}, {0x3b58e000},
+ {0x3b590000}, {0x3b592000}, {0x3b594000}, {0x3b596000},
+ {0x3b598000}, {0x3b59a000}, {0x3b59c000}, {0x3b59e000},
+ {0x3b5a0000}, {0x3b5a2000}, {0x3b5a4000}, {0x3b5a6000},
+ {0x3b5a8000}, {0x3b5aa000}, {0x3b5ac000}, {0x3b5ae000},
+ {0x3b5b0000}, {0x3b5b2000}, {0x3b5b4000}, {0x3b5b6000},
+ {0x3b5b8000}, {0x3b5ba000}, {0x3b5bc000}, {0x3b5be000},
+ {0x3b5c0000}, {0x3b5c2000}, {0x3b5c4000}, {0x3b5c6000},
+ {0x3b5c8000}, {0x3b5ca000}, {0x3b5cc000}, {0x3b5ce000},
+ {0x3b5d0000}, {0x3b5d2000}, {0x3b5d4000}, {0x3b5d6000},
+ {0x3b5d8000}, {0x3b5da000}, {0x3b5dc000}, {0x3b5de000},
+ {0x3b5e0000}, {0x3b5e2000}, {0x3b5e4000}, {0x3b5e6000},
+ {0x3b5e8000}, {0x3b5ea000}, {0x3b5ec000}, {0x3b5ee000},
+ {0x3b5f0000}, {0x3b5f2000}, {0x3b5f4000}, {0x3b5f6000},
+ {0x3b5f8000}, {0x3b5fa000}, {0x3b5fc000}, {0x3b5fe000},
+ {0x3b600000}, {0x3b602000}, {0x3b604000}, {0x3b606000},
+ {0x3b608000}, {0x3b60a000}, {0x3b60c000}, {0x3b60e000},
+ {0x3b610000}, {0x3b612000}, {0x3b614000}, {0x3b616000},
+ {0x3b618000}, {0x3b61a000}, {0x3b61c000}, {0x3b61e000},
+ {0x3b620000}, {0x3b622000}, {0x3b624000}, {0x3b626000},
+ {0x3b628000}, {0x3b62a000}, {0x3b62c000}, {0x3b62e000},
+ {0x3b630000}, {0x3b632000}, {0x3b634000}, {0x3b636000},
+ {0x3b638000}, {0x3b63a000}, {0x3b63c000}, {0x3b63e000},
+ {0x3b640000}, {0x3b642000}, {0x3b644000}, {0x3b646000},
+ {0x3b648000}, {0x3b64a000}, {0x3b64c000}, {0x3b64e000},
+ {0x3b650000}, {0x3b652000}, {0x3b654000}, {0x3b656000},
+ {0x3b658000}, {0x3b65a000}, {0x3b65c000}, {0x3b65e000},
+ {0x3b660000}, {0x3b662000}, {0x3b664000}, {0x3b666000},
+ {0x3b668000}, {0x3b66a000}, {0x3b66c000}, {0x3b66e000},
+ {0x3b670000}, {0x3b672000}, {0x3b674000}, {0x3b676000},
+ {0x3b678000}, {0x3b67a000}, {0x3b67c000}, {0x3b67e000},
+ {0x3b680000}, {0x3b682000}, {0x3b684000}, {0x3b686000},
+ {0x3b688000}, {0x3b68a000}, {0x3b68c000}, {0x3b68e000},
+ {0x3b690000}, {0x3b692000}, {0x3b694000}, {0x3b696000},
+ {0x3b698000}, {0x3b69a000}, {0x3b69c000}, {0x3b69e000},
+ {0x3b6a0000}, {0x3b6a2000}, {0x3b6a4000}, {0x3b6a6000},
+ {0x3b6a8000}, {0x3b6aa000}, {0x3b6ac000}, {0x3b6ae000},
+ {0x3b6b0000}, {0x3b6b2000}, {0x3b6b4000}, {0x3b6b6000},
+ {0x3b6b8000}, {0x3b6ba000}, {0x3b6bc000}, {0x3b6be000},
+ {0x3b6c0000}, {0x3b6c2000}, {0x3b6c4000}, {0x3b6c6000},
+ {0x3b6c8000}, {0x3b6ca000}, {0x3b6cc000}, {0x3b6ce000},
+ {0x3b6d0000}, {0x3b6d2000}, {0x3b6d4000}, {0x3b6d6000},
+ {0x3b6d8000}, {0x3b6da000}, {0x3b6dc000}, {0x3b6de000},
+ {0x3b6e0000}, {0x3b6e2000}, {0x3b6e4000}, {0x3b6e6000},
+ {0x3b6e8000}, {0x3b6ea000}, {0x3b6ec000}, {0x3b6ee000},
+ {0x3b6f0000}, {0x3b6f2000}, {0x3b6f4000}, {0x3b6f6000},
+ {0x3b6f8000}, {0x3b6fa000}, {0x3b6fc000}, {0x3b6fe000},
+ {0x3b700000}, {0x3b702000}, {0x3b704000}, {0x3b706000},
+ {0x3b708000}, {0x3b70a000}, {0x3b70c000}, {0x3b70e000},
+ {0x3b710000}, {0x3b712000}, {0x3b714000}, {0x3b716000},
+ {0x3b718000}, {0x3b71a000}, {0x3b71c000}, {0x3b71e000},
+ {0x3b720000}, {0x3b722000}, {0x3b724000}, {0x3b726000},
+ {0x3b728000}, {0x3b72a000}, {0x3b72c000}, {0x3b72e000},
+ {0x3b730000}, {0x3b732000}, {0x3b734000}, {0x3b736000},
+ {0x3b738000}, {0x3b73a000}, {0x3b73c000}, {0x3b73e000},
+ {0x3b740000}, {0x3b742000}, {0x3b744000}, {0x3b746000},
+ {0x3b748000}, {0x3b74a000}, {0x3b74c000}, {0x3b74e000},
+ {0x3b750000}, {0x3b752000}, {0x3b754000}, {0x3b756000},
+ {0x3b758000}, {0x3b75a000}, {0x3b75c000}, {0x3b75e000},
+ {0x3b760000}, {0x3b762000}, {0x3b764000}, {0x3b766000},
+ {0x3b768000}, {0x3b76a000}, {0x3b76c000}, {0x3b76e000},
+ {0x3b770000}, {0x3b772000}, {0x3b774000}, {0x3b776000},
+ {0x3b778000}, {0x3b77a000}, {0x3b77c000}, {0x3b77e000},
+ {0x3b780000}, {0x3b782000}, {0x3b784000}, {0x3b786000},
+ {0x3b788000}, {0x3b78a000}, {0x3b78c000}, {0x3b78e000},
+ {0x3b790000}, {0x3b792000}, {0x3b794000}, {0x3b796000},
+ {0x3b798000}, {0x3b79a000}, {0x3b79c000}, {0x3b79e000},
+ {0x3b7a0000}, {0x3b7a2000}, {0x3b7a4000}, {0x3b7a6000},
+ {0x3b7a8000}, {0x3b7aa000}, {0x3b7ac000}, {0x3b7ae000},
+ {0x3b7b0000}, {0x3b7b2000}, {0x3b7b4000}, {0x3b7b6000},
+ {0x3b7b8000}, {0x3b7ba000}, {0x3b7bc000}, {0x3b7be000},
+ {0x3b7c0000}, {0x3b7c2000}, {0x3b7c4000}, {0x3b7c6000},
+ {0x3b7c8000}, {0x3b7ca000}, {0x3b7cc000}, {0x3b7ce000},
+ {0x3b7d0000}, {0x3b7d2000}, {0x3b7d4000}, {0x3b7d6000},
+ {0x3b7d8000}, {0x3b7da000}, {0x3b7dc000}, {0x3b7de000},
+ {0x3b7e0000}, {0x3b7e2000}, {0x3b7e4000}, {0x3b7e6000},
+ {0x3b7e8000}, {0x3b7ea000}, {0x3b7ec000}, {0x3b7ee000},
+ {0x3b7f0000}, {0x3b7f2000}, {0x3b7f4000}, {0x3b7f6000},
+ {0x3b7f8000}, {0x3b7fa000}, {0x3b7fc000}, {0x3b7fe000},
+ {0x3b800000}, {0x3b802000}, {0x3b804000}, {0x3b806000},
+ {0x3b808000}, {0x3b80a000}, {0x3b80c000}, {0x3b80e000},
+ {0x3b810000}, {0x3b812000}, {0x3b814000}, {0x3b816000},
+ {0x3b818000}, {0x3b81a000}, {0x3b81c000}, {0x3b81e000},
+ {0x3b820000}, {0x3b822000}, {0x3b824000}, {0x3b826000},
+ {0x3b828000}, {0x3b82a000}, {0x3b82c000}, {0x3b82e000},
+ {0x3b830000}, {0x3b832000}, {0x3b834000}, {0x3b836000},
+ {0x3b838000}, {0x3b83a000}, {0x3b83c000}, {0x3b83e000},
+ {0x3b840000}, {0x3b842000}, {0x3b844000}, {0x3b846000},
+ {0x3b848000}, {0x3b84a000}, {0x3b84c000}, {0x3b84e000},
+ {0x3b850000}, {0x3b852000}, {0x3b854000}, {0x3b856000},
+ {0x3b858000}, {0x3b85a000}, {0x3b85c000}, {0x3b85e000},
+ {0x3b860000}, {0x3b862000}, {0x3b864000}, {0x3b866000},
+ {0x3b868000}, {0x3b86a000}, {0x3b86c000}, {0x3b86e000},
+ {0x3b870000}, {0x3b872000}, {0x3b874000}, {0x3b876000},
+ {0x3b878000}, {0x3b87a000}, {0x3b87c000}, {0x3b87e000},
+ {0x3b880000}, {0x3b882000}, {0x3b884000}, {0x3b886000},
+ {0x3b888000}, {0x3b88a000}, {0x3b88c000}, {0x3b88e000},
+ {0x3b890000}, {0x3b892000}, {0x3b894000}, {0x3b896000},
+ {0x3b898000}, {0x3b89a000}, {0x3b89c000}, {0x3b89e000},
+ {0x3b8a0000}, {0x3b8a2000}, {0x3b8a4000}, {0x3b8a6000},
+ {0x3b8a8000}, {0x3b8aa000}, {0x3b8ac000}, {0x3b8ae000},
+ {0x3b8b0000}, {0x3b8b2000}, {0x3b8b4000}, {0x3b8b6000},
+ {0x3b8b8000}, {0x3b8ba000}, {0x3b8bc000}, {0x3b8be000},
+ {0x3b8c0000}, {0x3b8c2000}, {0x3b8c4000}, {0x3b8c6000},
+ {0x3b8c8000}, {0x3b8ca000}, {0x3b8cc000}, {0x3b8ce000},
+ {0x3b8d0000}, {0x3b8d2000}, {0x3b8d4000}, {0x3b8d6000},
+ {0x3b8d8000}, {0x3b8da000}, {0x3b8dc000}, {0x3b8de000},
+ {0x3b8e0000}, {0x3b8e2000}, {0x3b8e4000}, {0x3b8e6000},
+ {0x3b8e8000}, {0x3b8ea000}, {0x3b8ec000}, {0x3b8ee000},
+ {0x3b8f0000}, {0x3b8f2000}, {0x3b8f4000}, {0x3b8f6000},
+ {0x3b8f8000}, {0x3b8fa000}, {0x3b8fc000}, {0x3b8fe000},
+ {0x3b900000}, {0x3b902000}, {0x3b904000}, {0x3b906000},
+ {0x3b908000}, {0x3b90a000}, {0x3b90c000}, {0x3b90e000},
+ {0x3b910000}, {0x3b912000}, {0x3b914000}, {0x3b916000},
+ {0x3b918000}, {0x3b91a000}, {0x3b91c000}, {0x3b91e000},
+ {0x3b920000}, {0x3b922000}, {0x3b924000}, {0x3b926000},
+ {0x3b928000}, {0x3b92a000}, {0x3b92c000}, {0x3b92e000},
+ {0x3b930000}, {0x3b932000}, {0x3b934000}, {0x3b936000},
+ {0x3b938000}, {0x3b93a000}, {0x3b93c000}, {0x3b93e000},
+ {0x3b940000}, {0x3b942000}, {0x3b944000}, {0x3b946000},
+ {0x3b948000}, {0x3b94a000}, {0x3b94c000}, {0x3b94e000},
+ {0x3b950000}, {0x3b952000}, {0x3b954000}, {0x3b956000},
+ {0x3b958000}, {0x3b95a000}, {0x3b95c000}, {0x3b95e000},
+ {0x3b960000}, {0x3b962000}, {0x3b964000}, {0x3b966000},
+ {0x3b968000}, {0x3b96a000}, {0x3b96c000}, {0x3b96e000},
+ {0x3b970000}, {0x3b972000}, {0x3b974000}, {0x3b976000},
+ {0x3b978000}, {0x3b97a000}, {0x3b97c000}, {0x3b97e000},
+ {0x3b980000}, {0x3b982000}, {0x3b984000}, {0x3b986000},
+ {0x3b988000}, {0x3b98a000}, {0x3b98c000}, {0x3b98e000},
+ {0x3b990000}, {0x3b992000}, {0x3b994000}, {0x3b996000},
+ {0x3b998000}, {0x3b99a000}, {0x3b99c000}, {0x3b99e000},
+ {0x3b9a0000}, {0x3b9a2000}, {0x3b9a4000}, {0x3b9a6000},
+ {0x3b9a8000}, {0x3b9aa000}, {0x3b9ac000}, {0x3b9ae000},
+ {0x3b9b0000}, {0x3b9b2000}, {0x3b9b4000}, {0x3b9b6000},
+ {0x3b9b8000}, {0x3b9ba000}, {0x3b9bc000}, {0x3b9be000},
+ {0x3b9c0000}, {0x3b9c2000}, {0x3b9c4000}, {0x3b9c6000},
+ {0x3b9c8000}, {0x3b9ca000}, {0x3b9cc000}, {0x3b9ce000},
+ {0x3b9d0000}, {0x3b9d2000}, {0x3b9d4000}, {0x3b9d6000},
+ {0x3b9d8000}, {0x3b9da000}, {0x3b9dc000}, {0x3b9de000},
+ {0x3b9e0000}, {0x3b9e2000}, {0x3b9e4000}, {0x3b9e6000},
+ {0x3b9e8000}, {0x3b9ea000}, {0x3b9ec000}, {0x3b9ee000},
+ {0x3b9f0000}, {0x3b9f2000}, {0x3b9f4000}, {0x3b9f6000},
+ {0x3b9f8000}, {0x3b9fa000}, {0x3b9fc000}, {0x3b9fe000},
+ {0x3ba00000}, {0x3ba02000}, {0x3ba04000}, {0x3ba06000},
+ {0x3ba08000}, {0x3ba0a000}, {0x3ba0c000}, {0x3ba0e000},
+ {0x3ba10000}, {0x3ba12000}, {0x3ba14000}, {0x3ba16000},
+ {0x3ba18000}, {0x3ba1a000}, {0x3ba1c000}, {0x3ba1e000},
+ {0x3ba20000}, {0x3ba22000}, {0x3ba24000}, {0x3ba26000},
+ {0x3ba28000}, {0x3ba2a000}, {0x3ba2c000}, {0x3ba2e000},
+ {0x3ba30000}, {0x3ba32000}, {0x3ba34000}, {0x3ba36000},
+ {0x3ba38000}, {0x3ba3a000}, {0x3ba3c000}, {0x3ba3e000},
+ {0x3ba40000}, {0x3ba42000}, {0x3ba44000}, {0x3ba46000},
+ {0x3ba48000}, {0x3ba4a000}, {0x3ba4c000}, {0x3ba4e000},
+ {0x3ba50000}, {0x3ba52000}, {0x3ba54000}, {0x3ba56000},
+ {0x3ba58000}, {0x3ba5a000}, {0x3ba5c000}, {0x3ba5e000},
+ {0x3ba60000}, {0x3ba62000}, {0x3ba64000}, {0x3ba66000},
+ {0x3ba68000}, {0x3ba6a000}, {0x3ba6c000}, {0x3ba6e000},
+ {0x3ba70000}, {0x3ba72000}, {0x3ba74000}, {0x3ba76000},
+ {0x3ba78000}, {0x3ba7a000}, {0x3ba7c000}, {0x3ba7e000},
+ {0x3ba80000}, {0x3ba82000}, {0x3ba84000}, {0x3ba86000},
+ {0x3ba88000}, {0x3ba8a000}, {0x3ba8c000}, {0x3ba8e000},
+ {0x3ba90000}, {0x3ba92000}, {0x3ba94000}, {0x3ba96000},
+ {0x3ba98000}, {0x3ba9a000}, {0x3ba9c000}, {0x3ba9e000},
+ {0x3baa0000}, {0x3baa2000}, {0x3baa4000}, {0x3baa6000},
+ {0x3baa8000}, {0x3baaa000}, {0x3baac000}, {0x3baae000},
+ {0x3bab0000}, {0x3bab2000}, {0x3bab4000}, {0x3bab6000},
+ {0x3bab8000}, {0x3baba000}, {0x3babc000}, {0x3babe000},
+ {0x3bac0000}, {0x3bac2000}, {0x3bac4000}, {0x3bac6000},
+ {0x3bac8000}, {0x3baca000}, {0x3bacc000}, {0x3bace000},
+ {0x3bad0000}, {0x3bad2000}, {0x3bad4000}, {0x3bad6000},
+ {0x3bad8000}, {0x3bada000}, {0x3badc000}, {0x3bade000},
+ {0x3bae0000}, {0x3bae2000}, {0x3bae4000}, {0x3bae6000},
+ {0x3bae8000}, {0x3baea000}, {0x3baec000}, {0x3baee000},
+ {0x3baf0000}, {0x3baf2000}, {0x3baf4000}, {0x3baf6000},
+ {0x3baf8000}, {0x3bafa000}, {0x3bafc000}, {0x3bafe000},
+ {0x3bb00000}, {0x3bb02000}, {0x3bb04000}, {0x3bb06000},
+ {0x3bb08000}, {0x3bb0a000}, {0x3bb0c000}, {0x3bb0e000},
+ {0x3bb10000}, {0x3bb12000}, {0x3bb14000}, {0x3bb16000},
+ {0x3bb18000}, {0x3bb1a000}, {0x3bb1c000}, {0x3bb1e000},
+ {0x3bb20000}, {0x3bb22000}, {0x3bb24000}, {0x3bb26000},
+ {0x3bb28000}, {0x3bb2a000}, {0x3bb2c000}, {0x3bb2e000},
+ {0x3bb30000}, {0x3bb32000}, {0x3bb34000}, {0x3bb36000},
+ {0x3bb38000}, {0x3bb3a000}, {0x3bb3c000}, {0x3bb3e000},
+ {0x3bb40000}, {0x3bb42000}, {0x3bb44000}, {0x3bb46000},
+ {0x3bb48000}, {0x3bb4a000}, {0x3bb4c000}, {0x3bb4e000},
+ {0x3bb50000}, {0x3bb52000}, {0x3bb54000}, {0x3bb56000},
+ {0x3bb58000}, {0x3bb5a000}, {0x3bb5c000}, {0x3bb5e000},
+ {0x3bb60000}, {0x3bb62000}, {0x3bb64000}, {0x3bb66000},
+ {0x3bb68000}, {0x3bb6a000}, {0x3bb6c000}, {0x3bb6e000},
+ {0x3bb70000}, {0x3bb72000}, {0x3bb74000}, {0x3bb76000},
+ {0x3bb78000}, {0x3bb7a000}, {0x3bb7c000}, {0x3bb7e000},
+ {0x3bb80000}, {0x3bb82000}, {0x3bb84000}, {0x3bb86000},
+ {0x3bb88000}, {0x3bb8a000}, {0x3bb8c000}, {0x3bb8e000},
+ {0x3bb90000}, {0x3bb92000}, {0x3bb94000}, {0x3bb96000},
+ {0x3bb98000}, {0x3bb9a000}, {0x3bb9c000}, {0x3bb9e000},
+ {0x3bba0000}, {0x3bba2000}, {0x3bba4000}, {0x3bba6000},
+ {0x3bba8000}, {0x3bbaa000}, {0x3bbac000}, {0x3bbae000},
+ {0x3bbb0000}, {0x3bbb2000}, {0x3bbb4000}, {0x3bbb6000},
+ {0x3bbb8000}, {0x3bbba000}, {0x3bbbc000}, {0x3bbbe000},
+ {0x3bbc0000}, {0x3bbc2000}, {0x3bbc4000}, {0x3bbc6000},
+ {0x3bbc8000}, {0x3bbca000}, {0x3bbcc000}, {0x3bbce000},
+ {0x3bbd0000}, {0x3bbd2000}, {0x3bbd4000}, {0x3bbd6000},
+ {0x3bbd8000}, {0x3bbda000}, {0x3bbdc000}, {0x3bbde000},
+ {0x3bbe0000}, {0x3bbe2000}, {0x3bbe4000}, {0x3bbe6000},
+ {0x3bbe8000}, {0x3bbea000}, {0x3bbec000}, {0x3bbee000},
+ {0x3bbf0000}, {0x3bbf2000}, {0x3bbf4000}, {0x3bbf6000},
+ {0x3bbf8000}, {0x3bbfa000}, {0x3bbfc000}, {0x3bbfe000},
+ {0x3bc00000}, {0x3bc02000}, {0x3bc04000}, {0x3bc06000},
+ {0x3bc08000}, {0x3bc0a000}, {0x3bc0c000}, {0x3bc0e000},
+ {0x3bc10000}, {0x3bc12000}, {0x3bc14000}, {0x3bc16000},
+ {0x3bc18000}, {0x3bc1a000}, {0x3bc1c000}, {0x3bc1e000},
+ {0x3bc20000}, {0x3bc22000}, {0x3bc24000}, {0x3bc26000},
+ {0x3bc28000}, {0x3bc2a000}, {0x3bc2c000}, {0x3bc2e000},
+ {0x3bc30000}, {0x3bc32000}, {0x3bc34000}, {0x3bc36000},
+ {0x3bc38000}, {0x3bc3a000}, {0x3bc3c000}, {0x3bc3e000},
+ {0x3bc40000}, {0x3bc42000}, {0x3bc44000}, {0x3bc46000},
+ {0x3bc48000}, {0x3bc4a000}, {0x3bc4c000}, {0x3bc4e000},
+ {0x3bc50000}, {0x3bc52000}, {0x3bc54000}, {0x3bc56000},
+ {0x3bc58000}, {0x3bc5a000}, {0x3bc5c000}, {0x3bc5e000},
+ {0x3bc60000}, {0x3bc62000}, {0x3bc64000}, {0x3bc66000},
+ {0x3bc68000}, {0x3bc6a000}, {0x3bc6c000}, {0x3bc6e000},
+ {0x3bc70000}, {0x3bc72000}, {0x3bc74000}, {0x3bc76000},
+ {0x3bc78000}, {0x3bc7a000}, {0x3bc7c000}, {0x3bc7e000},
+ {0x3bc80000}, {0x3bc82000}, {0x3bc84000}, {0x3bc86000},
+ {0x3bc88000}, {0x3bc8a000}, {0x3bc8c000}, {0x3bc8e000},
+ {0x3bc90000}, {0x3bc92000}, {0x3bc94000}, {0x3bc96000},
+ {0x3bc98000}, {0x3bc9a000}, {0x3bc9c000}, {0x3bc9e000},
+ {0x3bca0000}, {0x3bca2000}, {0x3bca4000}, {0x3bca6000},
+ {0x3bca8000}, {0x3bcaa000}, {0x3bcac000}, {0x3bcae000},
+ {0x3bcb0000}, {0x3bcb2000}, {0x3bcb4000}, {0x3bcb6000},
+ {0x3bcb8000}, {0x3bcba000}, {0x3bcbc000}, {0x3bcbe000},
+ {0x3bcc0000}, {0x3bcc2000}, {0x3bcc4000}, {0x3bcc6000},
+ {0x3bcc8000}, {0x3bcca000}, {0x3bccc000}, {0x3bcce000},
+ {0x3bcd0000}, {0x3bcd2000}, {0x3bcd4000}, {0x3bcd6000},
+ {0x3bcd8000}, {0x3bcda000}, {0x3bcdc000}, {0x3bcde000},
+ {0x3bce0000}, {0x3bce2000}, {0x3bce4000}, {0x3bce6000},
+ {0x3bce8000}, {0x3bcea000}, {0x3bcec000}, {0x3bcee000},
+ {0x3bcf0000}, {0x3bcf2000}, {0x3bcf4000}, {0x3bcf6000},
+ {0x3bcf8000}, {0x3bcfa000}, {0x3bcfc000}, {0x3bcfe000},
+ {0x3bd00000}, {0x3bd02000}, {0x3bd04000}, {0x3bd06000},
+ {0x3bd08000}, {0x3bd0a000}, {0x3bd0c000}, {0x3bd0e000},
+ {0x3bd10000}, {0x3bd12000}, {0x3bd14000}, {0x3bd16000},
+ {0x3bd18000}, {0x3bd1a000}, {0x3bd1c000}, {0x3bd1e000},
+ {0x3bd20000}, {0x3bd22000}, {0x3bd24000}, {0x3bd26000},
+ {0x3bd28000}, {0x3bd2a000}, {0x3bd2c000}, {0x3bd2e000},
+ {0x3bd30000}, {0x3bd32000}, {0x3bd34000}, {0x3bd36000},
+ {0x3bd38000}, {0x3bd3a000}, {0x3bd3c000}, {0x3bd3e000},
+ {0x3bd40000}, {0x3bd42000}, {0x3bd44000}, {0x3bd46000},
+ {0x3bd48000}, {0x3bd4a000}, {0x3bd4c000}, {0x3bd4e000},
+ {0x3bd50000}, {0x3bd52000}, {0x3bd54000}, {0x3bd56000},
+ {0x3bd58000}, {0x3bd5a000}, {0x3bd5c000}, {0x3bd5e000},
+ {0x3bd60000}, {0x3bd62000}, {0x3bd64000}, {0x3bd66000},
+ {0x3bd68000}, {0x3bd6a000}, {0x3bd6c000}, {0x3bd6e000},
+ {0x3bd70000}, {0x3bd72000}, {0x3bd74000}, {0x3bd76000},
+ {0x3bd78000}, {0x3bd7a000}, {0x3bd7c000}, {0x3bd7e000},
+ {0x3bd80000}, {0x3bd82000}, {0x3bd84000}, {0x3bd86000},
+ {0x3bd88000}, {0x3bd8a000}, {0x3bd8c000}, {0x3bd8e000},
+ {0x3bd90000}, {0x3bd92000}, {0x3bd94000}, {0x3bd96000},
+ {0x3bd98000}, {0x3bd9a000}, {0x3bd9c000}, {0x3bd9e000},
+ {0x3bda0000}, {0x3bda2000}, {0x3bda4000}, {0x3bda6000},
+ {0x3bda8000}, {0x3bdaa000}, {0x3bdac000}, {0x3bdae000},
+ {0x3bdb0000}, {0x3bdb2000}, {0x3bdb4000}, {0x3bdb6000},
+ {0x3bdb8000}, {0x3bdba000}, {0x3bdbc000}, {0x3bdbe000},
+ {0x3bdc0000}, {0x3bdc2000}, {0x3bdc4000}, {0x3bdc6000},
+ {0x3bdc8000}, {0x3bdca000}, {0x3bdcc000}, {0x3bdce000},
+ {0x3bdd0000}, {0x3bdd2000}, {0x3bdd4000}, {0x3bdd6000},
+ {0x3bdd8000}, {0x3bdda000}, {0x3bddc000}, {0x3bdde000},
+ {0x3bde0000}, {0x3bde2000}, {0x3bde4000}, {0x3bde6000},
+ {0x3bde8000}, {0x3bdea000}, {0x3bdec000}, {0x3bdee000},
+ {0x3bdf0000}, {0x3bdf2000}, {0x3bdf4000}, {0x3bdf6000},
+ {0x3bdf8000}, {0x3bdfa000}, {0x3bdfc000}, {0x3bdfe000},
+ {0x3be00000}, {0x3be02000}, {0x3be04000}, {0x3be06000},
+ {0x3be08000}, {0x3be0a000}, {0x3be0c000}, {0x3be0e000},
+ {0x3be10000}, {0x3be12000}, {0x3be14000}, {0x3be16000},
+ {0x3be18000}, {0x3be1a000}, {0x3be1c000}, {0x3be1e000},
+ {0x3be20000}, {0x3be22000}, {0x3be24000}, {0x3be26000},
+ {0x3be28000}, {0x3be2a000}, {0x3be2c000}, {0x3be2e000},
+ {0x3be30000}, {0x3be32000}, {0x3be34000}, {0x3be36000},
+ {0x3be38000}, {0x3be3a000}, {0x3be3c000}, {0x3be3e000},
+ {0x3be40000}, {0x3be42000}, {0x3be44000}, {0x3be46000},
+ {0x3be48000}, {0x3be4a000}, {0x3be4c000}, {0x3be4e000},
+ {0x3be50000}, {0x3be52000}, {0x3be54000}, {0x3be56000},
+ {0x3be58000}, {0x3be5a000}, {0x3be5c000}, {0x3be5e000},
+ {0x3be60000}, {0x3be62000}, {0x3be64000}, {0x3be66000},
+ {0x3be68000}, {0x3be6a000}, {0x3be6c000}, {0x3be6e000},
+ {0x3be70000}, {0x3be72000}, {0x3be74000}, {0x3be76000},
+ {0x3be78000}, {0x3be7a000}, {0x3be7c000}, {0x3be7e000},
+ {0x3be80000}, {0x3be82000}, {0x3be84000}, {0x3be86000},
+ {0x3be88000}, {0x3be8a000}, {0x3be8c000}, {0x3be8e000},
+ {0x3be90000}, {0x3be92000}, {0x3be94000}, {0x3be96000},
+ {0x3be98000}, {0x3be9a000}, {0x3be9c000}, {0x3be9e000},
+ {0x3bea0000}, {0x3bea2000}, {0x3bea4000}, {0x3bea6000},
+ {0x3bea8000}, {0x3beaa000}, {0x3beac000}, {0x3beae000},
+ {0x3beb0000}, {0x3beb2000}, {0x3beb4000}, {0x3beb6000},
+ {0x3beb8000}, {0x3beba000}, {0x3bebc000}, {0x3bebe000},
+ {0x3bec0000}, {0x3bec2000}, {0x3bec4000}, {0x3bec6000},
+ {0x3bec8000}, {0x3beca000}, {0x3becc000}, {0x3bece000},
+ {0x3bed0000}, {0x3bed2000}, {0x3bed4000}, {0x3bed6000},
+ {0x3bed8000}, {0x3beda000}, {0x3bedc000}, {0x3bede000},
+ {0x3bee0000}, {0x3bee2000}, {0x3bee4000}, {0x3bee6000},
+ {0x3bee8000}, {0x3beea000}, {0x3beec000}, {0x3beee000},
+ {0x3bef0000}, {0x3bef2000}, {0x3bef4000}, {0x3bef6000},
+ {0x3bef8000}, {0x3befa000}, {0x3befc000}, {0x3befe000},
+ {0x3bf00000}, {0x3bf02000}, {0x3bf04000}, {0x3bf06000},
+ {0x3bf08000}, {0x3bf0a000}, {0x3bf0c000}, {0x3bf0e000},
+ {0x3bf10000}, {0x3bf12000}, {0x3bf14000}, {0x3bf16000},
+ {0x3bf18000}, {0x3bf1a000}, {0x3bf1c000}, {0x3bf1e000},
+ {0x3bf20000}, {0x3bf22000}, {0x3bf24000}, {0x3bf26000},
+ {0x3bf28000}, {0x3bf2a000}, {0x3bf2c000}, {0x3bf2e000},
+ {0x3bf30000}, {0x3bf32000}, {0x3bf34000}, {0x3bf36000},
+ {0x3bf38000}, {0x3bf3a000}, {0x3bf3c000}, {0x3bf3e000},
+ {0x3bf40000}, {0x3bf42000}, {0x3bf44000}, {0x3bf46000},
+ {0x3bf48000}, {0x3bf4a000}, {0x3bf4c000}, {0x3bf4e000},
+ {0x3bf50000}, {0x3bf52000}, {0x3bf54000}, {0x3bf56000},
+ {0x3bf58000}, {0x3bf5a000}, {0x3bf5c000}, {0x3bf5e000},
+ {0x3bf60000}, {0x3bf62000}, {0x3bf64000}, {0x3bf66000},
+ {0x3bf68000}, {0x3bf6a000}, {0x3bf6c000}, {0x3bf6e000},
+ {0x3bf70000}, {0x3bf72000}, {0x3bf74000}, {0x3bf76000},
+ {0x3bf78000}, {0x3bf7a000}, {0x3bf7c000}, {0x3bf7e000},
+ {0x3bf80000}, {0x3bf82000}, {0x3bf84000}, {0x3bf86000},
+ {0x3bf88000}, {0x3bf8a000}, {0x3bf8c000}, {0x3bf8e000},
+ {0x3bf90000}, {0x3bf92000}, {0x3bf94000}, {0x3bf96000},
+ {0x3bf98000}, {0x3bf9a000}, {0x3bf9c000}, {0x3bf9e000},
+ {0x3bfa0000}, {0x3bfa2000}, {0x3bfa4000}, {0x3bfa6000},
+ {0x3bfa8000}, {0x3bfaa000}, {0x3bfac000}, {0x3bfae000},
+ {0x3bfb0000}, {0x3bfb2000}, {0x3bfb4000}, {0x3bfb6000},
+ {0x3bfb8000}, {0x3bfba000}, {0x3bfbc000}, {0x3bfbe000},
+ {0x3bfc0000}, {0x3bfc2000}, {0x3bfc4000}, {0x3bfc6000},
+ {0x3bfc8000}, {0x3bfca000}, {0x3bfcc000}, {0x3bfce000},
+ {0x3bfd0000}, {0x3bfd2000}, {0x3bfd4000}, {0x3bfd6000},
+ {0x3bfd8000}, {0x3bfda000}, {0x3bfdc000}, {0x3bfde000},
+ {0x3bfe0000}, {0x3bfe2000}, {0x3bfe4000}, {0x3bfe6000},
+ {0x3bfe8000}, {0x3bfea000}, {0x3bfec000}, {0x3bfee000},
+ {0x3bff0000}, {0x3bff2000}, {0x3bff4000}, {0x3bff6000},
+ {0x3bff8000}, {0x3bffa000}, {0x3bffc000}, {0x3bffe000},
+ {0x3c000000}, {0x3c002000}, {0x3c004000}, {0x3c006000},
+ {0x3c008000}, {0x3c00a000}, {0x3c00c000}, {0x3c00e000},
+ {0x3c010000}, {0x3c012000}, {0x3c014000}, {0x3c016000},
+ {0x3c018000}, {0x3c01a000}, {0x3c01c000}, {0x3c01e000},
+ {0x3c020000}, {0x3c022000}, {0x3c024000}, {0x3c026000},
+ {0x3c028000}, {0x3c02a000}, {0x3c02c000}, {0x3c02e000},
+ {0x3c030000}, {0x3c032000}, {0x3c034000}, {0x3c036000},
+ {0x3c038000}, {0x3c03a000}, {0x3c03c000}, {0x3c03e000},
+ {0x3c040000}, {0x3c042000}, {0x3c044000}, {0x3c046000},
+ {0x3c048000}, {0x3c04a000}, {0x3c04c000}, {0x3c04e000},
+ {0x3c050000}, {0x3c052000}, {0x3c054000}, {0x3c056000},
+ {0x3c058000}, {0x3c05a000}, {0x3c05c000}, {0x3c05e000},
+ {0x3c060000}, {0x3c062000}, {0x3c064000}, {0x3c066000},
+ {0x3c068000}, {0x3c06a000}, {0x3c06c000}, {0x3c06e000},
+ {0x3c070000}, {0x3c072000}, {0x3c074000}, {0x3c076000},
+ {0x3c078000}, {0x3c07a000}, {0x3c07c000}, {0x3c07e000},
+ {0x3c080000}, {0x3c082000}, {0x3c084000}, {0x3c086000},
+ {0x3c088000}, {0x3c08a000}, {0x3c08c000}, {0x3c08e000},
+ {0x3c090000}, {0x3c092000}, {0x3c094000}, {0x3c096000},
+ {0x3c098000}, {0x3c09a000}, {0x3c09c000}, {0x3c09e000},
+ {0x3c0a0000}, {0x3c0a2000}, {0x3c0a4000}, {0x3c0a6000},
+ {0x3c0a8000}, {0x3c0aa000}, {0x3c0ac000}, {0x3c0ae000},
+ {0x3c0b0000}, {0x3c0b2000}, {0x3c0b4000}, {0x3c0b6000},
+ {0x3c0b8000}, {0x3c0ba000}, {0x3c0bc000}, {0x3c0be000},
+ {0x3c0c0000}, {0x3c0c2000}, {0x3c0c4000}, {0x3c0c6000},
+ {0x3c0c8000}, {0x3c0ca000}, {0x3c0cc000}, {0x3c0ce000},
+ {0x3c0d0000}, {0x3c0d2000}, {0x3c0d4000}, {0x3c0d6000},
+ {0x3c0d8000}, {0x3c0da000}, {0x3c0dc000}, {0x3c0de000},
+ {0x3c0e0000}, {0x3c0e2000}, {0x3c0e4000}, {0x3c0e6000},
+ {0x3c0e8000}, {0x3c0ea000}, {0x3c0ec000}, {0x3c0ee000},
+ {0x3c0f0000}, {0x3c0f2000}, {0x3c0f4000}, {0x3c0f6000},
+ {0x3c0f8000}, {0x3c0fa000}, {0x3c0fc000}, {0x3c0fe000},
+ {0x3c100000}, {0x3c102000}, {0x3c104000}, {0x3c106000},
+ {0x3c108000}, {0x3c10a000}, {0x3c10c000}, {0x3c10e000},
+ {0x3c110000}, {0x3c112000}, {0x3c114000}, {0x3c116000},
+ {0x3c118000}, {0x3c11a000}, {0x3c11c000}, {0x3c11e000},
+ {0x3c120000}, {0x3c122000}, {0x3c124000}, {0x3c126000},
+ {0x3c128000}, {0x3c12a000}, {0x3c12c000}, {0x3c12e000},
+ {0x3c130000}, {0x3c132000}, {0x3c134000}, {0x3c136000},
+ {0x3c138000}, {0x3c13a000}, {0x3c13c000}, {0x3c13e000},
+ {0x3c140000}, {0x3c142000}, {0x3c144000}, {0x3c146000},
+ {0x3c148000}, {0x3c14a000}, {0x3c14c000}, {0x3c14e000},
+ {0x3c150000}, {0x3c152000}, {0x3c154000}, {0x3c156000},
+ {0x3c158000}, {0x3c15a000}, {0x3c15c000}, {0x3c15e000},
+ {0x3c160000}, {0x3c162000}, {0x3c164000}, {0x3c166000},
+ {0x3c168000}, {0x3c16a000}, {0x3c16c000}, {0x3c16e000},
+ {0x3c170000}, {0x3c172000}, {0x3c174000}, {0x3c176000},
+ {0x3c178000}, {0x3c17a000}, {0x3c17c000}, {0x3c17e000},
+ {0x3c180000}, {0x3c182000}, {0x3c184000}, {0x3c186000},
+ {0x3c188000}, {0x3c18a000}, {0x3c18c000}, {0x3c18e000},
+ {0x3c190000}, {0x3c192000}, {0x3c194000}, {0x3c196000},
+ {0x3c198000}, {0x3c19a000}, {0x3c19c000}, {0x3c19e000},
+ {0x3c1a0000}, {0x3c1a2000}, {0x3c1a4000}, {0x3c1a6000},
+ {0x3c1a8000}, {0x3c1aa000}, {0x3c1ac000}, {0x3c1ae000},
+ {0x3c1b0000}, {0x3c1b2000}, {0x3c1b4000}, {0x3c1b6000},
+ {0x3c1b8000}, {0x3c1ba000}, {0x3c1bc000}, {0x3c1be000},
+ {0x3c1c0000}, {0x3c1c2000}, {0x3c1c4000}, {0x3c1c6000},
+ {0x3c1c8000}, {0x3c1ca000}, {0x3c1cc000}, {0x3c1ce000},
+ {0x3c1d0000}, {0x3c1d2000}, {0x3c1d4000}, {0x3c1d6000},
+ {0x3c1d8000}, {0x3c1da000}, {0x3c1dc000}, {0x3c1de000},
+ {0x3c1e0000}, {0x3c1e2000}, {0x3c1e4000}, {0x3c1e6000},
+ {0x3c1e8000}, {0x3c1ea000}, {0x3c1ec000}, {0x3c1ee000},
+ {0x3c1f0000}, {0x3c1f2000}, {0x3c1f4000}, {0x3c1f6000},
+ {0x3c1f8000}, {0x3c1fa000}, {0x3c1fc000}, {0x3c1fe000},
+ {0x3c200000}, {0x3c202000}, {0x3c204000}, {0x3c206000},
+ {0x3c208000}, {0x3c20a000}, {0x3c20c000}, {0x3c20e000},
+ {0x3c210000}, {0x3c212000}, {0x3c214000}, {0x3c216000},
+ {0x3c218000}, {0x3c21a000}, {0x3c21c000}, {0x3c21e000},
+ {0x3c220000}, {0x3c222000}, {0x3c224000}, {0x3c226000},
+ {0x3c228000}, {0x3c22a000}, {0x3c22c000}, {0x3c22e000},
+ {0x3c230000}, {0x3c232000}, {0x3c234000}, {0x3c236000},
+ {0x3c238000}, {0x3c23a000}, {0x3c23c000}, {0x3c23e000},
+ {0x3c240000}, {0x3c242000}, {0x3c244000}, {0x3c246000},
+ {0x3c248000}, {0x3c24a000}, {0x3c24c000}, {0x3c24e000},
+ {0x3c250000}, {0x3c252000}, {0x3c254000}, {0x3c256000},
+ {0x3c258000}, {0x3c25a000}, {0x3c25c000}, {0x3c25e000},
+ {0x3c260000}, {0x3c262000}, {0x3c264000}, {0x3c266000},
+ {0x3c268000}, {0x3c26a000}, {0x3c26c000}, {0x3c26e000},
+ {0x3c270000}, {0x3c272000}, {0x3c274000}, {0x3c276000},
+ {0x3c278000}, {0x3c27a000}, {0x3c27c000}, {0x3c27e000},
+ {0x3c280000}, {0x3c282000}, {0x3c284000}, {0x3c286000},
+ {0x3c288000}, {0x3c28a000}, {0x3c28c000}, {0x3c28e000},
+ {0x3c290000}, {0x3c292000}, {0x3c294000}, {0x3c296000},
+ {0x3c298000}, {0x3c29a000}, {0x3c29c000}, {0x3c29e000},
+ {0x3c2a0000}, {0x3c2a2000}, {0x3c2a4000}, {0x3c2a6000},
+ {0x3c2a8000}, {0x3c2aa000}, {0x3c2ac000}, {0x3c2ae000},
+ {0x3c2b0000}, {0x3c2b2000}, {0x3c2b4000}, {0x3c2b6000},
+ {0x3c2b8000}, {0x3c2ba000}, {0x3c2bc000}, {0x3c2be000},
+ {0x3c2c0000}, {0x3c2c2000}, {0x3c2c4000}, {0x3c2c6000},
+ {0x3c2c8000}, {0x3c2ca000}, {0x3c2cc000}, {0x3c2ce000},
+ {0x3c2d0000}, {0x3c2d2000}, {0x3c2d4000}, {0x3c2d6000},
+ {0x3c2d8000}, {0x3c2da000}, {0x3c2dc000}, {0x3c2de000},
+ {0x3c2e0000}, {0x3c2e2000}, {0x3c2e4000}, {0x3c2e6000},
+ {0x3c2e8000}, {0x3c2ea000}, {0x3c2ec000}, {0x3c2ee000},
+ {0x3c2f0000}, {0x3c2f2000}, {0x3c2f4000}, {0x3c2f6000},
+ {0x3c2f8000}, {0x3c2fa000}, {0x3c2fc000}, {0x3c2fe000},
+ {0x3c300000}, {0x3c302000}, {0x3c304000}, {0x3c306000},
+ {0x3c308000}, {0x3c30a000}, {0x3c30c000}, {0x3c30e000},
+ {0x3c310000}, {0x3c312000}, {0x3c314000}, {0x3c316000},
+ {0x3c318000}, {0x3c31a000}, {0x3c31c000}, {0x3c31e000},
+ {0x3c320000}, {0x3c322000}, {0x3c324000}, {0x3c326000},
+ {0x3c328000}, {0x3c32a000}, {0x3c32c000}, {0x3c32e000},
+ {0x3c330000}, {0x3c332000}, {0x3c334000}, {0x3c336000},
+ {0x3c338000}, {0x3c33a000}, {0x3c33c000}, {0x3c33e000},
+ {0x3c340000}, {0x3c342000}, {0x3c344000}, {0x3c346000},
+ {0x3c348000}, {0x3c34a000}, {0x3c34c000}, {0x3c34e000},
+ {0x3c350000}, {0x3c352000}, {0x3c354000}, {0x3c356000},
+ {0x3c358000}, {0x3c35a000}, {0x3c35c000}, {0x3c35e000},
+ {0x3c360000}, {0x3c362000}, {0x3c364000}, {0x3c366000},
+ {0x3c368000}, {0x3c36a000}, {0x3c36c000}, {0x3c36e000},
+ {0x3c370000}, {0x3c372000}, {0x3c374000}, {0x3c376000},
+ {0x3c378000}, {0x3c37a000}, {0x3c37c000}, {0x3c37e000},
+ {0x3c380000}, {0x3c382000}, {0x3c384000}, {0x3c386000},
+ {0x3c388000}, {0x3c38a000}, {0x3c38c000}, {0x3c38e000},
+ {0x3c390000}, {0x3c392000}, {0x3c394000}, {0x3c396000},
+ {0x3c398000}, {0x3c39a000}, {0x3c39c000}, {0x3c39e000},
+ {0x3c3a0000}, {0x3c3a2000}, {0x3c3a4000}, {0x3c3a6000},
+ {0x3c3a8000}, {0x3c3aa000}, {0x3c3ac000}, {0x3c3ae000},
+ {0x3c3b0000}, {0x3c3b2000}, {0x3c3b4000}, {0x3c3b6000},
+ {0x3c3b8000}, {0x3c3ba000}, {0x3c3bc000}, {0x3c3be000},
+ {0x3c3c0000}, {0x3c3c2000}, {0x3c3c4000}, {0x3c3c6000},
+ {0x3c3c8000}, {0x3c3ca000}, {0x3c3cc000}, {0x3c3ce000},
+ {0x3c3d0000}, {0x3c3d2000}, {0x3c3d4000}, {0x3c3d6000},
+ {0x3c3d8000}, {0x3c3da000}, {0x3c3dc000}, {0x3c3de000},
+ {0x3c3e0000}, {0x3c3e2000}, {0x3c3e4000}, {0x3c3e6000},
+ {0x3c3e8000}, {0x3c3ea000}, {0x3c3ec000}, {0x3c3ee000},
+ {0x3c3f0000}, {0x3c3f2000}, {0x3c3f4000}, {0x3c3f6000},
+ {0x3c3f8000}, {0x3c3fa000}, {0x3c3fc000}, {0x3c3fe000},
+ {0x3c400000}, {0x3c402000}, {0x3c404000}, {0x3c406000},
+ {0x3c408000}, {0x3c40a000}, {0x3c40c000}, {0x3c40e000},
+ {0x3c410000}, {0x3c412000}, {0x3c414000}, {0x3c416000},
+ {0x3c418000}, {0x3c41a000}, {0x3c41c000}, {0x3c41e000},
+ {0x3c420000}, {0x3c422000}, {0x3c424000}, {0x3c426000},
+ {0x3c428000}, {0x3c42a000}, {0x3c42c000}, {0x3c42e000},
+ {0x3c430000}, {0x3c432000}, {0x3c434000}, {0x3c436000},
+ {0x3c438000}, {0x3c43a000}, {0x3c43c000}, {0x3c43e000},
+ {0x3c440000}, {0x3c442000}, {0x3c444000}, {0x3c446000},
+ {0x3c448000}, {0x3c44a000}, {0x3c44c000}, {0x3c44e000},
+ {0x3c450000}, {0x3c452000}, {0x3c454000}, {0x3c456000},
+ {0x3c458000}, {0x3c45a000}, {0x3c45c000}, {0x3c45e000},
+ {0x3c460000}, {0x3c462000}, {0x3c464000}, {0x3c466000},
+ {0x3c468000}, {0x3c46a000}, {0x3c46c000}, {0x3c46e000},
+ {0x3c470000}, {0x3c472000}, {0x3c474000}, {0x3c476000},
+ {0x3c478000}, {0x3c47a000}, {0x3c47c000}, {0x3c47e000},
+ {0x3c480000}, {0x3c482000}, {0x3c484000}, {0x3c486000},
+ {0x3c488000}, {0x3c48a000}, {0x3c48c000}, {0x3c48e000},
+ {0x3c490000}, {0x3c492000}, {0x3c494000}, {0x3c496000},
+ {0x3c498000}, {0x3c49a000}, {0x3c49c000}, {0x3c49e000},
+ {0x3c4a0000}, {0x3c4a2000}, {0x3c4a4000}, {0x3c4a6000},
+ {0x3c4a8000}, {0x3c4aa000}, {0x3c4ac000}, {0x3c4ae000},
+ {0x3c4b0000}, {0x3c4b2000}, {0x3c4b4000}, {0x3c4b6000},
+ {0x3c4b8000}, {0x3c4ba000}, {0x3c4bc000}, {0x3c4be000},
+ {0x3c4c0000}, {0x3c4c2000}, {0x3c4c4000}, {0x3c4c6000},
+ {0x3c4c8000}, {0x3c4ca000}, {0x3c4cc000}, {0x3c4ce000},
+ {0x3c4d0000}, {0x3c4d2000}, {0x3c4d4000}, {0x3c4d6000},
+ {0x3c4d8000}, {0x3c4da000}, {0x3c4dc000}, {0x3c4de000},
+ {0x3c4e0000}, {0x3c4e2000}, {0x3c4e4000}, {0x3c4e6000},
+ {0x3c4e8000}, {0x3c4ea000}, {0x3c4ec000}, {0x3c4ee000},
+ {0x3c4f0000}, {0x3c4f2000}, {0x3c4f4000}, {0x3c4f6000},
+ {0x3c4f8000}, {0x3c4fa000}, {0x3c4fc000}, {0x3c4fe000},
+ {0x3c500000}, {0x3c502000}, {0x3c504000}, {0x3c506000},
+ {0x3c508000}, {0x3c50a000}, {0x3c50c000}, {0x3c50e000},
+ {0x3c510000}, {0x3c512000}, {0x3c514000}, {0x3c516000},
+ {0x3c518000}, {0x3c51a000}, {0x3c51c000}, {0x3c51e000},
+ {0x3c520000}, {0x3c522000}, {0x3c524000}, {0x3c526000},
+ {0x3c528000}, {0x3c52a000}, {0x3c52c000}, {0x3c52e000},
+ {0x3c530000}, {0x3c532000}, {0x3c534000}, {0x3c536000},
+ {0x3c538000}, {0x3c53a000}, {0x3c53c000}, {0x3c53e000},
+ {0x3c540000}, {0x3c542000}, {0x3c544000}, {0x3c546000},
+ {0x3c548000}, {0x3c54a000}, {0x3c54c000}, {0x3c54e000},
+ {0x3c550000}, {0x3c552000}, {0x3c554000}, {0x3c556000},
+ {0x3c558000}, {0x3c55a000}, {0x3c55c000}, {0x3c55e000},
+ {0x3c560000}, {0x3c562000}, {0x3c564000}, {0x3c566000},
+ {0x3c568000}, {0x3c56a000}, {0x3c56c000}, {0x3c56e000},
+ {0x3c570000}, {0x3c572000}, {0x3c574000}, {0x3c576000},
+ {0x3c578000}, {0x3c57a000}, {0x3c57c000}, {0x3c57e000},
+ {0x3c580000}, {0x3c582000}, {0x3c584000}, {0x3c586000},
+ {0x3c588000}, {0x3c58a000}, {0x3c58c000}, {0x3c58e000},
+ {0x3c590000}, {0x3c592000}, {0x3c594000}, {0x3c596000},
+ {0x3c598000}, {0x3c59a000}, {0x3c59c000}, {0x3c59e000},
+ {0x3c5a0000}, {0x3c5a2000}, {0x3c5a4000}, {0x3c5a6000},
+ {0x3c5a8000}, {0x3c5aa000}, {0x3c5ac000}, {0x3c5ae000},
+ {0x3c5b0000}, {0x3c5b2000}, {0x3c5b4000}, {0x3c5b6000},
+ {0x3c5b8000}, {0x3c5ba000}, {0x3c5bc000}, {0x3c5be000},
+ {0x3c5c0000}, {0x3c5c2000}, {0x3c5c4000}, {0x3c5c6000},
+ {0x3c5c8000}, {0x3c5ca000}, {0x3c5cc000}, {0x3c5ce000},
+ {0x3c5d0000}, {0x3c5d2000}, {0x3c5d4000}, {0x3c5d6000},
+ {0x3c5d8000}, {0x3c5da000}, {0x3c5dc000}, {0x3c5de000},
+ {0x3c5e0000}, {0x3c5e2000}, {0x3c5e4000}, {0x3c5e6000},
+ {0x3c5e8000}, {0x3c5ea000}, {0x3c5ec000}, {0x3c5ee000},
+ {0x3c5f0000}, {0x3c5f2000}, {0x3c5f4000}, {0x3c5f6000},
+ {0x3c5f8000}, {0x3c5fa000}, {0x3c5fc000}, {0x3c5fe000},
+ {0x3c600000}, {0x3c602000}, {0x3c604000}, {0x3c606000},
+ {0x3c608000}, {0x3c60a000}, {0x3c60c000}, {0x3c60e000},
+ {0x3c610000}, {0x3c612000}, {0x3c614000}, {0x3c616000},
+ {0x3c618000}, {0x3c61a000}, {0x3c61c000}, {0x3c61e000},
+ {0x3c620000}, {0x3c622000}, {0x3c624000}, {0x3c626000},
+ {0x3c628000}, {0x3c62a000}, {0x3c62c000}, {0x3c62e000},
+ {0x3c630000}, {0x3c632000}, {0x3c634000}, {0x3c636000},
+ {0x3c638000}, {0x3c63a000}, {0x3c63c000}, {0x3c63e000},
+ {0x3c640000}, {0x3c642000}, {0x3c644000}, {0x3c646000},
+ {0x3c648000}, {0x3c64a000}, {0x3c64c000}, {0x3c64e000},
+ {0x3c650000}, {0x3c652000}, {0x3c654000}, {0x3c656000},
+ {0x3c658000}, {0x3c65a000}, {0x3c65c000}, {0x3c65e000},
+ {0x3c660000}, {0x3c662000}, {0x3c664000}, {0x3c666000},
+ {0x3c668000}, {0x3c66a000}, {0x3c66c000}, {0x3c66e000},
+ {0x3c670000}, {0x3c672000}, {0x3c674000}, {0x3c676000},
+ {0x3c678000}, {0x3c67a000}, {0x3c67c000}, {0x3c67e000},
+ {0x3c680000}, {0x3c682000}, {0x3c684000}, {0x3c686000},
+ {0x3c688000}, {0x3c68a000}, {0x3c68c000}, {0x3c68e000},
+ {0x3c690000}, {0x3c692000}, {0x3c694000}, {0x3c696000},
+ {0x3c698000}, {0x3c69a000}, {0x3c69c000}, {0x3c69e000},
+ {0x3c6a0000}, {0x3c6a2000}, {0x3c6a4000}, {0x3c6a6000},
+ {0x3c6a8000}, {0x3c6aa000}, {0x3c6ac000}, {0x3c6ae000},
+ {0x3c6b0000}, {0x3c6b2000}, {0x3c6b4000}, {0x3c6b6000},
+ {0x3c6b8000}, {0x3c6ba000}, {0x3c6bc000}, {0x3c6be000},
+ {0x3c6c0000}, {0x3c6c2000}, {0x3c6c4000}, {0x3c6c6000},
+ {0x3c6c8000}, {0x3c6ca000}, {0x3c6cc000}, {0x3c6ce000},
+ {0x3c6d0000}, {0x3c6d2000}, {0x3c6d4000}, {0x3c6d6000},
+ {0x3c6d8000}, {0x3c6da000}, {0x3c6dc000}, {0x3c6de000},
+ {0x3c6e0000}, {0x3c6e2000}, {0x3c6e4000}, {0x3c6e6000},
+ {0x3c6e8000}, {0x3c6ea000}, {0x3c6ec000}, {0x3c6ee000},
+ {0x3c6f0000}, {0x3c6f2000}, {0x3c6f4000}, {0x3c6f6000},
+ {0x3c6f8000}, {0x3c6fa000}, {0x3c6fc000}, {0x3c6fe000},
+ {0x3c700000}, {0x3c702000}, {0x3c704000}, {0x3c706000},
+ {0x3c708000}, {0x3c70a000}, {0x3c70c000}, {0x3c70e000},
+ {0x3c710000}, {0x3c712000}, {0x3c714000}, {0x3c716000},
+ {0x3c718000}, {0x3c71a000}, {0x3c71c000}, {0x3c71e000},
+ {0x3c720000}, {0x3c722000}, {0x3c724000}, {0x3c726000},
+ {0x3c728000}, {0x3c72a000}, {0x3c72c000}, {0x3c72e000},
+ {0x3c730000}, {0x3c732000}, {0x3c734000}, {0x3c736000},
+ {0x3c738000}, {0x3c73a000}, {0x3c73c000}, {0x3c73e000},
+ {0x3c740000}, {0x3c742000}, {0x3c744000}, {0x3c746000},
+ {0x3c748000}, {0x3c74a000}, {0x3c74c000}, {0x3c74e000},
+ {0x3c750000}, {0x3c752000}, {0x3c754000}, {0x3c756000},
+ {0x3c758000}, {0x3c75a000}, {0x3c75c000}, {0x3c75e000},
+ {0x3c760000}, {0x3c762000}, {0x3c764000}, {0x3c766000},
+ {0x3c768000}, {0x3c76a000}, {0x3c76c000}, {0x3c76e000},
+ {0x3c770000}, {0x3c772000}, {0x3c774000}, {0x3c776000},
+ {0x3c778000}, {0x3c77a000}, {0x3c77c000}, {0x3c77e000},
+ {0x3c780000}, {0x3c782000}, {0x3c784000}, {0x3c786000},
+ {0x3c788000}, {0x3c78a000}, {0x3c78c000}, {0x3c78e000},
+ {0x3c790000}, {0x3c792000}, {0x3c794000}, {0x3c796000},
+ {0x3c798000}, {0x3c79a000}, {0x3c79c000}, {0x3c79e000},
+ {0x3c7a0000}, {0x3c7a2000}, {0x3c7a4000}, {0x3c7a6000},
+ {0x3c7a8000}, {0x3c7aa000}, {0x3c7ac000}, {0x3c7ae000},
+ {0x3c7b0000}, {0x3c7b2000}, {0x3c7b4000}, {0x3c7b6000},
+ {0x3c7b8000}, {0x3c7ba000}, {0x3c7bc000}, {0x3c7be000},
+ {0x3c7c0000}, {0x3c7c2000}, {0x3c7c4000}, {0x3c7c6000},
+ {0x3c7c8000}, {0x3c7ca000}, {0x3c7cc000}, {0x3c7ce000},
+ {0x3c7d0000}, {0x3c7d2000}, {0x3c7d4000}, {0x3c7d6000},
+ {0x3c7d8000}, {0x3c7da000}, {0x3c7dc000}, {0x3c7de000},
+ {0x3c7e0000}, {0x3c7e2000}, {0x3c7e4000}, {0x3c7e6000},
+ {0x3c7e8000}, {0x3c7ea000}, {0x3c7ec000}, {0x3c7ee000},
+ {0x3c7f0000}, {0x3c7f2000}, {0x3c7f4000}, {0x3c7f6000},
+ {0x3c7f8000}, {0x3c7fa000}, {0x3c7fc000}, {0x3c7fe000},
+ {0x3c800000}, {0x3c802000}, {0x3c804000}, {0x3c806000},
+ {0x3c808000}, {0x3c80a000}, {0x3c80c000}, {0x3c80e000},
+ {0x3c810000}, {0x3c812000}, {0x3c814000}, {0x3c816000},
+ {0x3c818000}, {0x3c81a000}, {0x3c81c000}, {0x3c81e000},
+ {0x3c820000}, {0x3c822000}, {0x3c824000}, {0x3c826000},
+ {0x3c828000}, {0x3c82a000}, {0x3c82c000}, {0x3c82e000},
+ {0x3c830000}, {0x3c832000}, {0x3c834000}, {0x3c836000},
+ {0x3c838000}, {0x3c83a000}, {0x3c83c000}, {0x3c83e000},
+ {0x3c840000}, {0x3c842000}, {0x3c844000}, {0x3c846000},
+ {0x3c848000}, {0x3c84a000}, {0x3c84c000}, {0x3c84e000},
+ {0x3c850000}, {0x3c852000}, {0x3c854000}, {0x3c856000},
+ {0x3c858000}, {0x3c85a000}, {0x3c85c000}, {0x3c85e000},
+ {0x3c860000}, {0x3c862000}, {0x3c864000}, {0x3c866000},
+ {0x3c868000}, {0x3c86a000}, {0x3c86c000}, {0x3c86e000},
+ {0x3c870000}, {0x3c872000}, {0x3c874000}, {0x3c876000},
+ {0x3c878000}, {0x3c87a000}, {0x3c87c000}, {0x3c87e000},
+ {0x3c880000}, {0x3c882000}, {0x3c884000}, {0x3c886000},
+ {0x3c888000}, {0x3c88a000}, {0x3c88c000}, {0x3c88e000},
+ {0x3c890000}, {0x3c892000}, {0x3c894000}, {0x3c896000},
+ {0x3c898000}, {0x3c89a000}, {0x3c89c000}, {0x3c89e000},
+ {0x3c8a0000}, {0x3c8a2000}, {0x3c8a4000}, {0x3c8a6000},
+ {0x3c8a8000}, {0x3c8aa000}, {0x3c8ac000}, {0x3c8ae000},
+ {0x3c8b0000}, {0x3c8b2000}, {0x3c8b4000}, {0x3c8b6000},
+ {0x3c8b8000}, {0x3c8ba000}, {0x3c8bc000}, {0x3c8be000},
+ {0x3c8c0000}, {0x3c8c2000}, {0x3c8c4000}, {0x3c8c6000},
+ {0x3c8c8000}, {0x3c8ca000}, {0x3c8cc000}, {0x3c8ce000},
+ {0x3c8d0000}, {0x3c8d2000}, {0x3c8d4000}, {0x3c8d6000},
+ {0x3c8d8000}, {0x3c8da000}, {0x3c8dc000}, {0x3c8de000},
+ {0x3c8e0000}, {0x3c8e2000}, {0x3c8e4000}, {0x3c8e6000},
+ {0x3c8e8000}, {0x3c8ea000}, {0x3c8ec000}, {0x3c8ee000},
+ {0x3c8f0000}, {0x3c8f2000}, {0x3c8f4000}, {0x3c8f6000},
+ {0x3c8f8000}, {0x3c8fa000}, {0x3c8fc000}, {0x3c8fe000},
+ {0x3c900000}, {0x3c902000}, {0x3c904000}, {0x3c906000},
+ {0x3c908000}, {0x3c90a000}, {0x3c90c000}, {0x3c90e000},
+ {0x3c910000}, {0x3c912000}, {0x3c914000}, {0x3c916000},
+ {0x3c918000}, {0x3c91a000}, {0x3c91c000}, {0x3c91e000},
+ {0x3c920000}, {0x3c922000}, {0x3c924000}, {0x3c926000},
+ {0x3c928000}, {0x3c92a000}, {0x3c92c000}, {0x3c92e000},
+ {0x3c930000}, {0x3c932000}, {0x3c934000}, {0x3c936000},
+ {0x3c938000}, {0x3c93a000}, {0x3c93c000}, {0x3c93e000},
+ {0x3c940000}, {0x3c942000}, {0x3c944000}, {0x3c946000},
+ {0x3c948000}, {0x3c94a000}, {0x3c94c000}, {0x3c94e000},
+ {0x3c950000}, {0x3c952000}, {0x3c954000}, {0x3c956000},
+ {0x3c958000}, {0x3c95a000}, {0x3c95c000}, {0x3c95e000},
+ {0x3c960000}, {0x3c962000}, {0x3c964000}, {0x3c966000},
+ {0x3c968000}, {0x3c96a000}, {0x3c96c000}, {0x3c96e000},
+ {0x3c970000}, {0x3c972000}, {0x3c974000}, {0x3c976000},
+ {0x3c978000}, {0x3c97a000}, {0x3c97c000}, {0x3c97e000},
+ {0x3c980000}, {0x3c982000}, {0x3c984000}, {0x3c986000},
+ {0x3c988000}, {0x3c98a000}, {0x3c98c000}, {0x3c98e000},
+ {0x3c990000}, {0x3c992000}, {0x3c994000}, {0x3c996000},
+ {0x3c998000}, {0x3c99a000}, {0x3c99c000}, {0x3c99e000},
+ {0x3c9a0000}, {0x3c9a2000}, {0x3c9a4000}, {0x3c9a6000},
+ {0x3c9a8000}, {0x3c9aa000}, {0x3c9ac000}, {0x3c9ae000},
+ {0x3c9b0000}, {0x3c9b2000}, {0x3c9b4000}, {0x3c9b6000},
+ {0x3c9b8000}, {0x3c9ba000}, {0x3c9bc000}, {0x3c9be000},
+ {0x3c9c0000}, {0x3c9c2000}, {0x3c9c4000}, {0x3c9c6000},
+ {0x3c9c8000}, {0x3c9ca000}, {0x3c9cc000}, {0x3c9ce000},
+ {0x3c9d0000}, {0x3c9d2000}, {0x3c9d4000}, {0x3c9d6000},
+ {0x3c9d8000}, {0x3c9da000}, {0x3c9dc000}, {0x3c9de000},
+ {0x3c9e0000}, {0x3c9e2000}, {0x3c9e4000}, {0x3c9e6000},
+ {0x3c9e8000}, {0x3c9ea000}, {0x3c9ec000}, {0x3c9ee000},
+ {0x3c9f0000}, {0x3c9f2000}, {0x3c9f4000}, {0x3c9f6000},
+ {0x3c9f8000}, {0x3c9fa000}, {0x3c9fc000}, {0x3c9fe000},
+ {0x3ca00000}, {0x3ca02000}, {0x3ca04000}, {0x3ca06000},
+ {0x3ca08000}, {0x3ca0a000}, {0x3ca0c000}, {0x3ca0e000},
+ {0x3ca10000}, {0x3ca12000}, {0x3ca14000}, {0x3ca16000},
+ {0x3ca18000}, {0x3ca1a000}, {0x3ca1c000}, {0x3ca1e000},
+ {0x3ca20000}, {0x3ca22000}, {0x3ca24000}, {0x3ca26000},
+ {0x3ca28000}, {0x3ca2a000}, {0x3ca2c000}, {0x3ca2e000},
+ {0x3ca30000}, {0x3ca32000}, {0x3ca34000}, {0x3ca36000},
+ {0x3ca38000}, {0x3ca3a000}, {0x3ca3c000}, {0x3ca3e000},
+ {0x3ca40000}, {0x3ca42000}, {0x3ca44000}, {0x3ca46000},
+ {0x3ca48000}, {0x3ca4a000}, {0x3ca4c000}, {0x3ca4e000},
+ {0x3ca50000}, {0x3ca52000}, {0x3ca54000}, {0x3ca56000},
+ {0x3ca58000}, {0x3ca5a000}, {0x3ca5c000}, {0x3ca5e000},
+ {0x3ca60000}, {0x3ca62000}, {0x3ca64000}, {0x3ca66000},
+ {0x3ca68000}, {0x3ca6a000}, {0x3ca6c000}, {0x3ca6e000},
+ {0x3ca70000}, {0x3ca72000}, {0x3ca74000}, {0x3ca76000},
+ {0x3ca78000}, {0x3ca7a000}, {0x3ca7c000}, {0x3ca7e000},
+ {0x3ca80000}, {0x3ca82000}, {0x3ca84000}, {0x3ca86000},
+ {0x3ca88000}, {0x3ca8a000}, {0x3ca8c000}, {0x3ca8e000},
+ {0x3ca90000}, {0x3ca92000}, {0x3ca94000}, {0x3ca96000},
+ {0x3ca98000}, {0x3ca9a000}, {0x3ca9c000}, {0x3ca9e000},
+ {0x3caa0000}, {0x3caa2000}, {0x3caa4000}, {0x3caa6000},
+ {0x3caa8000}, {0x3caaa000}, {0x3caac000}, {0x3caae000},
+ {0x3cab0000}, {0x3cab2000}, {0x3cab4000}, {0x3cab6000},
+ {0x3cab8000}, {0x3caba000}, {0x3cabc000}, {0x3cabe000},
+ {0x3cac0000}, {0x3cac2000}, {0x3cac4000}, {0x3cac6000},
+ {0x3cac8000}, {0x3caca000}, {0x3cacc000}, {0x3cace000},
+ {0x3cad0000}, {0x3cad2000}, {0x3cad4000}, {0x3cad6000},
+ {0x3cad8000}, {0x3cada000}, {0x3cadc000}, {0x3cade000},
+ {0x3cae0000}, {0x3cae2000}, {0x3cae4000}, {0x3cae6000},
+ {0x3cae8000}, {0x3caea000}, {0x3caec000}, {0x3caee000},
+ {0x3caf0000}, {0x3caf2000}, {0x3caf4000}, {0x3caf6000},
+ {0x3caf8000}, {0x3cafa000}, {0x3cafc000}, {0x3cafe000},
+ {0x3cb00000}, {0x3cb02000}, {0x3cb04000}, {0x3cb06000},
+ {0x3cb08000}, {0x3cb0a000}, {0x3cb0c000}, {0x3cb0e000},
+ {0x3cb10000}, {0x3cb12000}, {0x3cb14000}, {0x3cb16000},
+ {0x3cb18000}, {0x3cb1a000}, {0x3cb1c000}, {0x3cb1e000},
+ {0x3cb20000}, {0x3cb22000}, {0x3cb24000}, {0x3cb26000},
+ {0x3cb28000}, {0x3cb2a000}, {0x3cb2c000}, {0x3cb2e000},
+ {0x3cb30000}, {0x3cb32000}, {0x3cb34000}, {0x3cb36000},
+ {0x3cb38000}, {0x3cb3a000}, {0x3cb3c000}, {0x3cb3e000},
+ {0x3cb40000}, {0x3cb42000}, {0x3cb44000}, {0x3cb46000},
+ {0x3cb48000}, {0x3cb4a000}, {0x3cb4c000}, {0x3cb4e000},
+ {0x3cb50000}, {0x3cb52000}, {0x3cb54000}, {0x3cb56000},
+ {0x3cb58000}, {0x3cb5a000}, {0x3cb5c000}, {0x3cb5e000},
+ {0x3cb60000}, {0x3cb62000}, {0x3cb64000}, {0x3cb66000},
+ {0x3cb68000}, {0x3cb6a000}, {0x3cb6c000}, {0x3cb6e000},
+ {0x3cb70000}, {0x3cb72000}, {0x3cb74000}, {0x3cb76000},
+ {0x3cb78000}, {0x3cb7a000}, {0x3cb7c000}, {0x3cb7e000},
+ {0x3cb80000}, {0x3cb82000}, {0x3cb84000}, {0x3cb86000},
+ {0x3cb88000}, {0x3cb8a000}, {0x3cb8c000}, {0x3cb8e000},
+ {0x3cb90000}, {0x3cb92000}, {0x3cb94000}, {0x3cb96000},
+ {0x3cb98000}, {0x3cb9a000}, {0x3cb9c000}, {0x3cb9e000},
+ {0x3cba0000}, {0x3cba2000}, {0x3cba4000}, {0x3cba6000},
+ {0x3cba8000}, {0x3cbaa000}, {0x3cbac000}, {0x3cbae000},
+ {0x3cbb0000}, {0x3cbb2000}, {0x3cbb4000}, {0x3cbb6000},
+ {0x3cbb8000}, {0x3cbba000}, {0x3cbbc000}, {0x3cbbe000},
+ {0x3cbc0000}, {0x3cbc2000}, {0x3cbc4000}, {0x3cbc6000},
+ {0x3cbc8000}, {0x3cbca000}, {0x3cbcc000}, {0x3cbce000},
+ {0x3cbd0000}, {0x3cbd2000}, {0x3cbd4000}, {0x3cbd6000},
+ {0x3cbd8000}, {0x3cbda000}, {0x3cbdc000}, {0x3cbde000},
+ {0x3cbe0000}, {0x3cbe2000}, {0x3cbe4000}, {0x3cbe6000},
+ {0x3cbe8000}, {0x3cbea000}, {0x3cbec000}, {0x3cbee000},
+ {0x3cbf0000}, {0x3cbf2000}, {0x3cbf4000}, {0x3cbf6000},
+ {0x3cbf8000}, {0x3cbfa000}, {0x3cbfc000}, {0x3cbfe000},
+ {0x3cc00000}, {0x3cc02000}, {0x3cc04000}, {0x3cc06000},
+ {0x3cc08000}, {0x3cc0a000}, {0x3cc0c000}, {0x3cc0e000},
+ {0x3cc10000}, {0x3cc12000}, {0x3cc14000}, {0x3cc16000},
+ {0x3cc18000}, {0x3cc1a000}, {0x3cc1c000}, {0x3cc1e000},
+ {0x3cc20000}, {0x3cc22000}, {0x3cc24000}, {0x3cc26000},
+ {0x3cc28000}, {0x3cc2a000}, {0x3cc2c000}, {0x3cc2e000},
+ {0x3cc30000}, {0x3cc32000}, {0x3cc34000}, {0x3cc36000},
+ {0x3cc38000}, {0x3cc3a000}, {0x3cc3c000}, {0x3cc3e000},
+ {0x3cc40000}, {0x3cc42000}, {0x3cc44000}, {0x3cc46000},
+ {0x3cc48000}, {0x3cc4a000}, {0x3cc4c000}, {0x3cc4e000},
+ {0x3cc50000}, {0x3cc52000}, {0x3cc54000}, {0x3cc56000},
+ {0x3cc58000}, {0x3cc5a000}, {0x3cc5c000}, {0x3cc5e000},
+ {0x3cc60000}, {0x3cc62000}, {0x3cc64000}, {0x3cc66000},
+ {0x3cc68000}, {0x3cc6a000}, {0x3cc6c000}, {0x3cc6e000},
+ {0x3cc70000}, {0x3cc72000}, {0x3cc74000}, {0x3cc76000},
+ {0x3cc78000}, {0x3cc7a000}, {0x3cc7c000}, {0x3cc7e000},
+ {0x3cc80000}, {0x3cc82000}, {0x3cc84000}, {0x3cc86000},
+ {0x3cc88000}, {0x3cc8a000}, {0x3cc8c000}, {0x3cc8e000},
+ {0x3cc90000}, {0x3cc92000}, {0x3cc94000}, {0x3cc96000},
+ {0x3cc98000}, {0x3cc9a000}, {0x3cc9c000}, {0x3cc9e000},
+ {0x3cca0000}, {0x3cca2000}, {0x3cca4000}, {0x3cca6000},
+ {0x3cca8000}, {0x3ccaa000}, {0x3ccac000}, {0x3ccae000},
+ {0x3ccb0000}, {0x3ccb2000}, {0x3ccb4000}, {0x3ccb6000},
+ {0x3ccb8000}, {0x3ccba000}, {0x3ccbc000}, {0x3ccbe000},
+ {0x3ccc0000}, {0x3ccc2000}, {0x3ccc4000}, {0x3ccc6000},
+ {0x3ccc8000}, {0x3ccca000}, {0x3cccc000}, {0x3ccce000},
+ {0x3ccd0000}, {0x3ccd2000}, {0x3ccd4000}, {0x3ccd6000},
+ {0x3ccd8000}, {0x3ccda000}, {0x3ccdc000}, {0x3ccde000},
+ {0x3cce0000}, {0x3cce2000}, {0x3cce4000}, {0x3cce6000},
+ {0x3cce8000}, {0x3ccea000}, {0x3ccec000}, {0x3ccee000},
+ {0x3ccf0000}, {0x3ccf2000}, {0x3ccf4000}, {0x3ccf6000},
+ {0x3ccf8000}, {0x3ccfa000}, {0x3ccfc000}, {0x3ccfe000},
+ {0x3cd00000}, {0x3cd02000}, {0x3cd04000}, {0x3cd06000},
+ {0x3cd08000}, {0x3cd0a000}, {0x3cd0c000}, {0x3cd0e000},
+ {0x3cd10000}, {0x3cd12000}, {0x3cd14000}, {0x3cd16000},
+ {0x3cd18000}, {0x3cd1a000}, {0x3cd1c000}, {0x3cd1e000},
+ {0x3cd20000}, {0x3cd22000}, {0x3cd24000}, {0x3cd26000},
+ {0x3cd28000}, {0x3cd2a000}, {0x3cd2c000}, {0x3cd2e000},
+ {0x3cd30000}, {0x3cd32000}, {0x3cd34000}, {0x3cd36000},
+ {0x3cd38000}, {0x3cd3a000}, {0x3cd3c000}, {0x3cd3e000},
+ {0x3cd40000}, {0x3cd42000}, {0x3cd44000}, {0x3cd46000},
+ {0x3cd48000}, {0x3cd4a000}, {0x3cd4c000}, {0x3cd4e000},
+ {0x3cd50000}, {0x3cd52000}, {0x3cd54000}, {0x3cd56000},
+ {0x3cd58000}, {0x3cd5a000}, {0x3cd5c000}, {0x3cd5e000},
+ {0x3cd60000}, {0x3cd62000}, {0x3cd64000}, {0x3cd66000},
+ {0x3cd68000}, {0x3cd6a000}, {0x3cd6c000}, {0x3cd6e000},
+ {0x3cd70000}, {0x3cd72000}, {0x3cd74000}, {0x3cd76000},
+ {0x3cd78000}, {0x3cd7a000}, {0x3cd7c000}, {0x3cd7e000},
+ {0x3cd80000}, {0x3cd82000}, {0x3cd84000}, {0x3cd86000},
+ {0x3cd88000}, {0x3cd8a000}, {0x3cd8c000}, {0x3cd8e000},
+ {0x3cd90000}, {0x3cd92000}, {0x3cd94000}, {0x3cd96000},
+ {0x3cd98000}, {0x3cd9a000}, {0x3cd9c000}, {0x3cd9e000},
+ {0x3cda0000}, {0x3cda2000}, {0x3cda4000}, {0x3cda6000},
+ {0x3cda8000}, {0x3cdaa000}, {0x3cdac000}, {0x3cdae000},
+ {0x3cdb0000}, {0x3cdb2000}, {0x3cdb4000}, {0x3cdb6000},
+ {0x3cdb8000}, {0x3cdba000}, {0x3cdbc000}, {0x3cdbe000},
+ {0x3cdc0000}, {0x3cdc2000}, {0x3cdc4000}, {0x3cdc6000},
+ {0x3cdc8000}, {0x3cdca000}, {0x3cdcc000}, {0x3cdce000},
+ {0x3cdd0000}, {0x3cdd2000}, {0x3cdd4000}, {0x3cdd6000},
+ {0x3cdd8000}, {0x3cdda000}, {0x3cddc000}, {0x3cdde000},
+ {0x3cde0000}, {0x3cde2000}, {0x3cde4000}, {0x3cde6000},
+ {0x3cde8000}, {0x3cdea000}, {0x3cdec000}, {0x3cdee000},
+ {0x3cdf0000}, {0x3cdf2000}, {0x3cdf4000}, {0x3cdf6000},
+ {0x3cdf8000}, {0x3cdfa000}, {0x3cdfc000}, {0x3cdfe000},
+ {0x3ce00000}, {0x3ce02000}, {0x3ce04000}, {0x3ce06000},
+ {0x3ce08000}, {0x3ce0a000}, {0x3ce0c000}, {0x3ce0e000},
+ {0x3ce10000}, {0x3ce12000}, {0x3ce14000}, {0x3ce16000},
+ {0x3ce18000}, {0x3ce1a000}, {0x3ce1c000}, {0x3ce1e000},
+ {0x3ce20000}, {0x3ce22000}, {0x3ce24000}, {0x3ce26000},
+ {0x3ce28000}, {0x3ce2a000}, {0x3ce2c000}, {0x3ce2e000},
+ {0x3ce30000}, {0x3ce32000}, {0x3ce34000}, {0x3ce36000},
+ {0x3ce38000}, {0x3ce3a000}, {0x3ce3c000}, {0x3ce3e000},
+ {0x3ce40000}, {0x3ce42000}, {0x3ce44000}, {0x3ce46000},
+ {0x3ce48000}, {0x3ce4a000}, {0x3ce4c000}, {0x3ce4e000},
+ {0x3ce50000}, {0x3ce52000}, {0x3ce54000}, {0x3ce56000},
+ {0x3ce58000}, {0x3ce5a000}, {0x3ce5c000}, {0x3ce5e000},
+ {0x3ce60000}, {0x3ce62000}, {0x3ce64000}, {0x3ce66000},
+ {0x3ce68000}, {0x3ce6a000}, {0x3ce6c000}, {0x3ce6e000},
+ {0x3ce70000}, {0x3ce72000}, {0x3ce74000}, {0x3ce76000},
+ {0x3ce78000}, {0x3ce7a000}, {0x3ce7c000}, {0x3ce7e000},
+ {0x3ce80000}, {0x3ce82000}, {0x3ce84000}, {0x3ce86000},
+ {0x3ce88000}, {0x3ce8a000}, {0x3ce8c000}, {0x3ce8e000},
+ {0x3ce90000}, {0x3ce92000}, {0x3ce94000}, {0x3ce96000},
+ {0x3ce98000}, {0x3ce9a000}, {0x3ce9c000}, {0x3ce9e000},
+ {0x3cea0000}, {0x3cea2000}, {0x3cea4000}, {0x3cea6000},
+ {0x3cea8000}, {0x3ceaa000}, {0x3ceac000}, {0x3ceae000},
+ {0x3ceb0000}, {0x3ceb2000}, {0x3ceb4000}, {0x3ceb6000},
+ {0x3ceb8000}, {0x3ceba000}, {0x3cebc000}, {0x3cebe000},
+ {0x3cec0000}, {0x3cec2000}, {0x3cec4000}, {0x3cec6000},
+ {0x3cec8000}, {0x3ceca000}, {0x3cecc000}, {0x3cece000},
+ {0x3ced0000}, {0x3ced2000}, {0x3ced4000}, {0x3ced6000},
+ {0x3ced8000}, {0x3ceda000}, {0x3cedc000}, {0x3cede000},
+ {0x3cee0000}, {0x3cee2000}, {0x3cee4000}, {0x3cee6000},
+ {0x3cee8000}, {0x3ceea000}, {0x3ceec000}, {0x3ceee000},
+ {0x3cef0000}, {0x3cef2000}, {0x3cef4000}, {0x3cef6000},
+ {0x3cef8000}, {0x3cefa000}, {0x3cefc000}, {0x3cefe000},
+ {0x3cf00000}, {0x3cf02000}, {0x3cf04000}, {0x3cf06000},
+ {0x3cf08000}, {0x3cf0a000}, {0x3cf0c000}, {0x3cf0e000},
+ {0x3cf10000}, {0x3cf12000}, {0x3cf14000}, {0x3cf16000},
+ {0x3cf18000}, {0x3cf1a000}, {0x3cf1c000}, {0x3cf1e000},
+ {0x3cf20000}, {0x3cf22000}, {0x3cf24000}, {0x3cf26000},
+ {0x3cf28000}, {0x3cf2a000}, {0x3cf2c000}, {0x3cf2e000},
+ {0x3cf30000}, {0x3cf32000}, {0x3cf34000}, {0x3cf36000},
+ {0x3cf38000}, {0x3cf3a000}, {0x3cf3c000}, {0x3cf3e000},
+ {0x3cf40000}, {0x3cf42000}, {0x3cf44000}, {0x3cf46000},
+ {0x3cf48000}, {0x3cf4a000}, {0x3cf4c000}, {0x3cf4e000},
+ {0x3cf50000}, {0x3cf52000}, {0x3cf54000}, {0x3cf56000},
+ {0x3cf58000}, {0x3cf5a000}, {0x3cf5c000}, {0x3cf5e000},
+ {0x3cf60000}, {0x3cf62000}, {0x3cf64000}, {0x3cf66000},
+ {0x3cf68000}, {0x3cf6a000}, {0x3cf6c000}, {0x3cf6e000},
+ {0x3cf70000}, {0x3cf72000}, {0x3cf74000}, {0x3cf76000},
+ {0x3cf78000}, {0x3cf7a000}, {0x3cf7c000}, {0x3cf7e000},
+ {0x3cf80000}, {0x3cf82000}, {0x3cf84000}, {0x3cf86000},
+ {0x3cf88000}, {0x3cf8a000}, {0x3cf8c000}, {0x3cf8e000},
+ {0x3cf90000}, {0x3cf92000}, {0x3cf94000}, {0x3cf96000},
+ {0x3cf98000}, {0x3cf9a000}, {0x3cf9c000}, {0x3cf9e000},
+ {0x3cfa0000}, {0x3cfa2000}, {0x3cfa4000}, {0x3cfa6000},
+ {0x3cfa8000}, {0x3cfaa000}, {0x3cfac000}, {0x3cfae000},
+ {0x3cfb0000}, {0x3cfb2000}, {0x3cfb4000}, {0x3cfb6000},
+ {0x3cfb8000}, {0x3cfba000}, {0x3cfbc000}, {0x3cfbe000},
+ {0x3cfc0000}, {0x3cfc2000}, {0x3cfc4000}, {0x3cfc6000},
+ {0x3cfc8000}, {0x3cfca000}, {0x3cfcc000}, {0x3cfce000},
+ {0x3cfd0000}, {0x3cfd2000}, {0x3cfd4000}, {0x3cfd6000},
+ {0x3cfd8000}, {0x3cfda000}, {0x3cfdc000}, {0x3cfde000},
+ {0x3cfe0000}, {0x3cfe2000}, {0x3cfe4000}, {0x3cfe6000},
+ {0x3cfe8000}, {0x3cfea000}, {0x3cfec000}, {0x3cfee000},
+ {0x3cff0000}, {0x3cff2000}, {0x3cff4000}, {0x3cff6000},
+ {0x3cff8000}, {0x3cffa000}, {0x3cffc000}, {0x3cffe000},
+ {0x3d000000}, {0x3d002000}, {0x3d004000}, {0x3d006000},
+ {0x3d008000}, {0x3d00a000}, {0x3d00c000}, {0x3d00e000},
+ {0x3d010000}, {0x3d012000}, {0x3d014000}, {0x3d016000},
+ {0x3d018000}, {0x3d01a000}, {0x3d01c000}, {0x3d01e000},
+ {0x3d020000}, {0x3d022000}, {0x3d024000}, {0x3d026000},
+ {0x3d028000}, {0x3d02a000}, {0x3d02c000}, {0x3d02e000},
+ {0x3d030000}, {0x3d032000}, {0x3d034000}, {0x3d036000},
+ {0x3d038000}, {0x3d03a000}, {0x3d03c000}, {0x3d03e000},
+ {0x3d040000}, {0x3d042000}, {0x3d044000}, {0x3d046000},
+ {0x3d048000}, {0x3d04a000}, {0x3d04c000}, {0x3d04e000},
+ {0x3d050000}, {0x3d052000}, {0x3d054000}, {0x3d056000},
+ {0x3d058000}, {0x3d05a000}, {0x3d05c000}, {0x3d05e000},
+ {0x3d060000}, {0x3d062000}, {0x3d064000}, {0x3d066000},
+ {0x3d068000}, {0x3d06a000}, {0x3d06c000}, {0x3d06e000},
+ {0x3d070000}, {0x3d072000}, {0x3d074000}, {0x3d076000},
+ {0x3d078000}, {0x3d07a000}, {0x3d07c000}, {0x3d07e000},
+ {0x3d080000}, {0x3d082000}, {0x3d084000}, {0x3d086000},
+ {0x3d088000}, {0x3d08a000}, {0x3d08c000}, {0x3d08e000},
+ {0x3d090000}, {0x3d092000}, {0x3d094000}, {0x3d096000},
+ {0x3d098000}, {0x3d09a000}, {0x3d09c000}, {0x3d09e000},
+ {0x3d0a0000}, {0x3d0a2000}, {0x3d0a4000}, {0x3d0a6000},
+ {0x3d0a8000}, {0x3d0aa000}, {0x3d0ac000}, {0x3d0ae000},
+ {0x3d0b0000}, {0x3d0b2000}, {0x3d0b4000}, {0x3d0b6000},
+ {0x3d0b8000}, {0x3d0ba000}, {0x3d0bc000}, {0x3d0be000},
+ {0x3d0c0000}, {0x3d0c2000}, {0x3d0c4000}, {0x3d0c6000},
+ {0x3d0c8000}, {0x3d0ca000}, {0x3d0cc000}, {0x3d0ce000},
+ {0x3d0d0000}, {0x3d0d2000}, {0x3d0d4000}, {0x3d0d6000},
+ {0x3d0d8000}, {0x3d0da000}, {0x3d0dc000}, {0x3d0de000},
+ {0x3d0e0000}, {0x3d0e2000}, {0x3d0e4000}, {0x3d0e6000},
+ {0x3d0e8000}, {0x3d0ea000}, {0x3d0ec000}, {0x3d0ee000},
+ {0x3d0f0000}, {0x3d0f2000}, {0x3d0f4000}, {0x3d0f6000},
+ {0x3d0f8000}, {0x3d0fa000}, {0x3d0fc000}, {0x3d0fe000},
+ {0x3d100000}, {0x3d102000}, {0x3d104000}, {0x3d106000},
+ {0x3d108000}, {0x3d10a000}, {0x3d10c000}, {0x3d10e000},
+ {0x3d110000}, {0x3d112000}, {0x3d114000}, {0x3d116000},
+ {0x3d118000}, {0x3d11a000}, {0x3d11c000}, {0x3d11e000},
+ {0x3d120000}, {0x3d122000}, {0x3d124000}, {0x3d126000},
+ {0x3d128000}, {0x3d12a000}, {0x3d12c000}, {0x3d12e000},
+ {0x3d130000}, {0x3d132000}, {0x3d134000}, {0x3d136000},
+ {0x3d138000}, {0x3d13a000}, {0x3d13c000}, {0x3d13e000},
+ {0x3d140000}, {0x3d142000}, {0x3d144000}, {0x3d146000},
+ {0x3d148000}, {0x3d14a000}, {0x3d14c000}, {0x3d14e000},
+ {0x3d150000}, {0x3d152000}, {0x3d154000}, {0x3d156000},
+ {0x3d158000}, {0x3d15a000}, {0x3d15c000}, {0x3d15e000},
+ {0x3d160000}, {0x3d162000}, {0x3d164000}, {0x3d166000},
+ {0x3d168000}, {0x3d16a000}, {0x3d16c000}, {0x3d16e000},
+ {0x3d170000}, {0x3d172000}, {0x3d174000}, {0x3d176000},
+ {0x3d178000}, {0x3d17a000}, {0x3d17c000}, {0x3d17e000},
+ {0x3d180000}, {0x3d182000}, {0x3d184000}, {0x3d186000},
+ {0x3d188000}, {0x3d18a000}, {0x3d18c000}, {0x3d18e000},
+ {0x3d190000}, {0x3d192000}, {0x3d194000}, {0x3d196000},
+ {0x3d198000}, {0x3d19a000}, {0x3d19c000}, {0x3d19e000},
+ {0x3d1a0000}, {0x3d1a2000}, {0x3d1a4000}, {0x3d1a6000},
+ {0x3d1a8000}, {0x3d1aa000}, {0x3d1ac000}, {0x3d1ae000},
+ {0x3d1b0000}, {0x3d1b2000}, {0x3d1b4000}, {0x3d1b6000},
+ {0x3d1b8000}, {0x3d1ba000}, {0x3d1bc000}, {0x3d1be000},
+ {0x3d1c0000}, {0x3d1c2000}, {0x3d1c4000}, {0x3d1c6000},
+ {0x3d1c8000}, {0x3d1ca000}, {0x3d1cc000}, {0x3d1ce000},
+ {0x3d1d0000}, {0x3d1d2000}, {0x3d1d4000}, {0x3d1d6000},
+ {0x3d1d8000}, {0x3d1da000}, {0x3d1dc000}, {0x3d1de000},
+ {0x3d1e0000}, {0x3d1e2000}, {0x3d1e4000}, {0x3d1e6000},
+ {0x3d1e8000}, {0x3d1ea000}, {0x3d1ec000}, {0x3d1ee000},
+ {0x3d1f0000}, {0x3d1f2000}, {0x3d1f4000}, {0x3d1f6000},
+ {0x3d1f8000}, {0x3d1fa000}, {0x3d1fc000}, {0x3d1fe000},
+ {0x3d200000}, {0x3d202000}, {0x3d204000}, {0x3d206000},
+ {0x3d208000}, {0x3d20a000}, {0x3d20c000}, {0x3d20e000},
+ {0x3d210000}, {0x3d212000}, {0x3d214000}, {0x3d216000},
+ {0x3d218000}, {0x3d21a000}, {0x3d21c000}, {0x3d21e000},
+ {0x3d220000}, {0x3d222000}, {0x3d224000}, {0x3d226000},
+ {0x3d228000}, {0x3d22a000}, {0x3d22c000}, {0x3d22e000},
+ {0x3d230000}, {0x3d232000}, {0x3d234000}, {0x3d236000},
+ {0x3d238000}, {0x3d23a000}, {0x3d23c000}, {0x3d23e000},
+ {0x3d240000}, {0x3d242000}, {0x3d244000}, {0x3d246000},
+ {0x3d248000}, {0x3d24a000}, {0x3d24c000}, {0x3d24e000},
+ {0x3d250000}, {0x3d252000}, {0x3d254000}, {0x3d256000},
+ {0x3d258000}, {0x3d25a000}, {0x3d25c000}, {0x3d25e000},
+ {0x3d260000}, {0x3d262000}, {0x3d264000}, {0x3d266000},
+ {0x3d268000}, {0x3d26a000}, {0x3d26c000}, {0x3d26e000},
+ {0x3d270000}, {0x3d272000}, {0x3d274000}, {0x3d276000},
+ {0x3d278000}, {0x3d27a000}, {0x3d27c000}, {0x3d27e000},
+ {0x3d280000}, {0x3d282000}, {0x3d284000}, {0x3d286000},
+ {0x3d288000}, {0x3d28a000}, {0x3d28c000}, {0x3d28e000},
+ {0x3d290000}, {0x3d292000}, {0x3d294000}, {0x3d296000},
+ {0x3d298000}, {0x3d29a000}, {0x3d29c000}, {0x3d29e000},
+ {0x3d2a0000}, {0x3d2a2000}, {0x3d2a4000}, {0x3d2a6000},
+ {0x3d2a8000}, {0x3d2aa000}, {0x3d2ac000}, {0x3d2ae000},
+ {0x3d2b0000}, {0x3d2b2000}, {0x3d2b4000}, {0x3d2b6000},
+ {0x3d2b8000}, {0x3d2ba000}, {0x3d2bc000}, {0x3d2be000},
+ {0x3d2c0000}, {0x3d2c2000}, {0x3d2c4000}, {0x3d2c6000},
+ {0x3d2c8000}, {0x3d2ca000}, {0x3d2cc000}, {0x3d2ce000},
+ {0x3d2d0000}, {0x3d2d2000}, {0x3d2d4000}, {0x3d2d6000},
+ {0x3d2d8000}, {0x3d2da000}, {0x3d2dc000}, {0x3d2de000},
+ {0x3d2e0000}, {0x3d2e2000}, {0x3d2e4000}, {0x3d2e6000},
+ {0x3d2e8000}, {0x3d2ea000}, {0x3d2ec000}, {0x3d2ee000},
+ {0x3d2f0000}, {0x3d2f2000}, {0x3d2f4000}, {0x3d2f6000},
+ {0x3d2f8000}, {0x3d2fa000}, {0x3d2fc000}, {0x3d2fe000},
+ {0x3d300000}, {0x3d302000}, {0x3d304000}, {0x3d306000},
+ {0x3d308000}, {0x3d30a000}, {0x3d30c000}, {0x3d30e000},
+ {0x3d310000}, {0x3d312000}, {0x3d314000}, {0x3d316000},
+ {0x3d318000}, {0x3d31a000}, {0x3d31c000}, {0x3d31e000},
+ {0x3d320000}, {0x3d322000}, {0x3d324000}, {0x3d326000},
+ {0x3d328000}, {0x3d32a000}, {0x3d32c000}, {0x3d32e000},
+ {0x3d330000}, {0x3d332000}, {0x3d334000}, {0x3d336000},
+ {0x3d338000}, {0x3d33a000}, {0x3d33c000}, {0x3d33e000},
+ {0x3d340000}, {0x3d342000}, {0x3d344000}, {0x3d346000},
+ {0x3d348000}, {0x3d34a000}, {0x3d34c000}, {0x3d34e000},
+ {0x3d350000}, {0x3d352000}, {0x3d354000}, {0x3d356000},
+ {0x3d358000}, {0x3d35a000}, {0x3d35c000}, {0x3d35e000},
+ {0x3d360000}, {0x3d362000}, {0x3d364000}, {0x3d366000},
+ {0x3d368000}, {0x3d36a000}, {0x3d36c000}, {0x3d36e000},
+ {0x3d370000}, {0x3d372000}, {0x3d374000}, {0x3d376000},
+ {0x3d378000}, {0x3d37a000}, {0x3d37c000}, {0x3d37e000},
+ {0x3d380000}, {0x3d382000}, {0x3d384000}, {0x3d386000},
+ {0x3d388000}, {0x3d38a000}, {0x3d38c000}, {0x3d38e000},
+ {0x3d390000}, {0x3d392000}, {0x3d394000}, {0x3d396000},
+ {0x3d398000}, {0x3d39a000}, {0x3d39c000}, {0x3d39e000},
+ {0x3d3a0000}, {0x3d3a2000}, {0x3d3a4000}, {0x3d3a6000},
+ {0x3d3a8000}, {0x3d3aa000}, {0x3d3ac000}, {0x3d3ae000},
+ {0x3d3b0000}, {0x3d3b2000}, {0x3d3b4000}, {0x3d3b6000},
+ {0x3d3b8000}, {0x3d3ba000}, {0x3d3bc000}, {0x3d3be000},
+ {0x3d3c0000}, {0x3d3c2000}, {0x3d3c4000}, {0x3d3c6000},
+ {0x3d3c8000}, {0x3d3ca000}, {0x3d3cc000}, {0x3d3ce000},
+ {0x3d3d0000}, {0x3d3d2000}, {0x3d3d4000}, {0x3d3d6000},
+ {0x3d3d8000}, {0x3d3da000}, {0x3d3dc000}, {0x3d3de000},
+ {0x3d3e0000}, {0x3d3e2000}, {0x3d3e4000}, {0x3d3e6000},
+ {0x3d3e8000}, {0x3d3ea000}, {0x3d3ec000}, {0x3d3ee000},
+ {0x3d3f0000}, {0x3d3f2000}, {0x3d3f4000}, {0x3d3f6000},
+ {0x3d3f8000}, {0x3d3fa000}, {0x3d3fc000}, {0x3d3fe000},
+ {0x3d400000}, {0x3d402000}, {0x3d404000}, {0x3d406000},
+ {0x3d408000}, {0x3d40a000}, {0x3d40c000}, {0x3d40e000},
+ {0x3d410000}, {0x3d412000}, {0x3d414000}, {0x3d416000},
+ {0x3d418000}, {0x3d41a000}, {0x3d41c000}, {0x3d41e000},
+ {0x3d420000}, {0x3d422000}, {0x3d424000}, {0x3d426000},
+ {0x3d428000}, {0x3d42a000}, {0x3d42c000}, {0x3d42e000},
+ {0x3d430000}, {0x3d432000}, {0x3d434000}, {0x3d436000},
+ {0x3d438000}, {0x3d43a000}, {0x3d43c000}, {0x3d43e000},
+ {0x3d440000}, {0x3d442000}, {0x3d444000}, {0x3d446000},
+ {0x3d448000}, {0x3d44a000}, {0x3d44c000}, {0x3d44e000},
+ {0x3d450000}, {0x3d452000}, {0x3d454000}, {0x3d456000},
+ {0x3d458000}, {0x3d45a000}, {0x3d45c000}, {0x3d45e000},
+ {0x3d460000}, {0x3d462000}, {0x3d464000}, {0x3d466000},
+ {0x3d468000}, {0x3d46a000}, {0x3d46c000}, {0x3d46e000},
+ {0x3d470000}, {0x3d472000}, {0x3d474000}, {0x3d476000},
+ {0x3d478000}, {0x3d47a000}, {0x3d47c000}, {0x3d47e000},
+ {0x3d480000}, {0x3d482000}, {0x3d484000}, {0x3d486000},
+ {0x3d488000}, {0x3d48a000}, {0x3d48c000}, {0x3d48e000},
+ {0x3d490000}, {0x3d492000}, {0x3d494000}, {0x3d496000},
+ {0x3d498000}, {0x3d49a000}, {0x3d49c000}, {0x3d49e000},
+ {0x3d4a0000}, {0x3d4a2000}, {0x3d4a4000}, {0x3d4a6000},
+ {0x3d4a8000}, {0x3d4aa000}, {0x3d4ac000}, {0x3d4ae000},
+ {0x3d4b0000}, {0x3d4b2000}, {0x3d4b4000}, {0x3d4b6000},
+ {0x3d4b8000}, {0x3d4ba000}, {0x3d4bc000}, {0x3d4be000},
+ {0x3d4c0000}, {0x3d4c2000}, {0x3d4c4000}, {0x3d4c6000},
+ {0x3d4c8000}, {0x3d4ca000}, {0x3d4cc000}, {0x3d4ce000},
+ {0x3d4d0000}, {0x3d4d2000}, {0x3d4d4000}, {0x3d4d6000},
+ {0x3d4d8000}, {0x3d4da000}, {0x3d4dc000}, {0x3d4de000},
+ {0x3d4e0000}, {0x3d4e2000}, {0x3d4e4000}, {0x3d4e6000},
+ {0x3d4e8000}, {0x3d4ea000}, {0x3d4ec000}, {0x3d4ee000},
+ {0x3d4f0000}, {0x3d4f2000}, {0x3d4f4000}, {0x3d4f6000},
+ {0x3d4f8000}, {0x3d4fa000}, {0x3d4fc000}, {0x3d4fe000},
+ {0x3d500000}, {0x3d502000}, {0x3d504000}, {0x3d506000},
+ {0x3d508000}, {0x3d50a000}, {0x3d50c000}, {0x3d50e000},
+ {0x3d510000}, {0x3d512000}, {0x3d514000}, {0x3d516000},
+ {0x3d518000}, {0x3d51a000}, {0x3d51c000}, {0x3d51e000},
+ {0x3d520000}, {0x3d522000}, {0x3d524000}, {0x3d526000},
+ {0x3d528000}, {0x3d52a000}, {0x3d52c000}, {0x3d52e000},
+ {0x3d530000}, {0x3d532000}, {0x3d534000}, {0x3d536000},
+ {0x3d538000}, {0x3d53a000}, {0x3d53c000}, {0x3d53e000},
+ {0x3d540000}, {0x3d542000}, {0x3d544000}, {0x3d546000},
+ {0x3d548000}, {0x3d54a000}, {0x3d54c000}, {0x3d54e000},
+ {0x3d550000}, {0x3d552000}, {0x3d554000}, {0x3d556000},
+ {0x3d558000}, {0x3d55a000}, {0x3d55c000}, {0x3d55e000},
+ {0x3d560000}, {0x3d562000}, {0x3d564000}, {0x3d566000},
+ {0x3d568000}, {0x3d56a000}, {0x3d56c000}, {0x3d56e000},
+ {0x3d570000}, {0x3d572000}, {0x3d574000}, {0x3d576000},
+ {0x3d578000}, {0x3d57a000}, {0x3d57c000}, {0x3d57e000},
+ {0x3d580000}, {0x3d582000}, {0x3d584000}, {0x3d586000},
+ {0x3d588000}, {0x3d58a000}, {0x3d58c000}, {0x3d58e000},
+ {0x3d590000}, {0x3d592000}, {0x3d594000}, {0x3d596000},
+ {0x3d598000}, {0x3d59a000}, {0x3d59c000}, {0x3d59e000},
+ {0x3d5a0000}, {0x3d5a2000}, {0x3d5a4000}, {0x3d5a6000},
+ {0x3d5a8000}, {0x3d5aa000}, {0x3d5ac000}, {0x3d5ae000},
+ {0x3d5b0000}, {0x3d5b2000}, {0x3d5b4000}, {0x3d5b6000},
+ {0x3d5b8000}, {0x3d5ba000}, {0x3d5bc000}, {0x3d5be000},
+ {0x3d5c0000}, {0x3d5c2000}, {0x3d5c4000}, {0x3d5c6000},
+ {0x3d5c8000}, {0x3d5ca000}, {0x3d5cc000}, {0x3d5ce000},
+ {0x3d5d0000}, {0x3d5d2000}, {0x3d5d4000}, {0x3d5d6000},
+ {0x3d5d8000}, {0x3d5da000}, {0x3d5dc000}, {0x3d5de000},
+ {0x3d5e0000}, {0x3d5e2000}, {0x3d5e4000}, {0x3d5e6000},
+ {0x3d5e8000}, {0x3d5ea000}, {0x3d5ec000}, {0x3d5ee000},
+ {0x3d5f0000}, {0x3d5f2000}, {0x3d5f4000}, {0x3d5f6000},
+ {0x3d5f8000}, {0x3d5fa000}, {0x3d5fc000}, {0x3d5fe000},
+ {0x3d600000}, {0x3d602000}, {0x3d604000}, {0x3d606000},
+ {0x3d608000}, {0x3d60a000}, {0x3d60c000}, {0x3d60e000},
+ {0x3d610000}, {0x3d612000}, {0x3d614000}, {0x3d616000},
+ {0x3d618000}, {0x3d61a000}, {0x3d61c000}, {0x3d61e000},
+ {0x3d620000}, {0x3d622000}, {0x3d624000}, {0x3d626000},
+ {0x3d628000}, {0x3d62a000}, {0x3d62c000}, {0x3d62e000},
+ {0x3d630000}, {0x3d632000}, {0x3d634000}, {0x3d636000},
+ {0x3d638000}, {0x3d63a000}, {0x3d63c000}, {0x3d63e000},
+ {0x3d640000}, {0x3d642000}, {0x3d644000}, {0x3d646000},
+ {0x3d648000}, {0x3d64a000}, {0x3d64c000}, {0x3d64e000},
+ {0x3d650000}, {0x3d652000}, {0x3d654000}, {0x3d656000},
+ {0x3d658000}, {0x3d65a000}, {0x3d65c000}, {0x3d65e000},
+ {0x3d660000}, {0x3d662000}, {0x3d664000}, {0x3d666000},
+ {0x3d668000}, {0x3d66a000}, {0x3d66c000}, {0x3d66e000},
+ {0x3d670000}, {0x3d672000}, {0x3d674000}, {0x3d676000},
+ {0x3d678000}, {0x3d67a000}, {0x3d67c000}, {0x3d67e000},
+ {0x3d680000}, {0x3d682000}, {0x3d684000}, {0x3d686000},
+ {0x3d688000}, {0x3d68a000}, {0x3d68c000}, {0x3d68e000},
+ {0x3d690000}, {0x3d692000}, {0x3d694000}, {0x3d696000},
+ {0x3d698000}, {0x3d69a000}, {0x3d69c000}, {0x3d69e000},
+ {0x3d6a0000}, {0x3d6a2000}, {0x3d6a4000}, {0x3d6a6000},
+ {0x3d6a8000}, {0x3d6aa000}, {0x3d6ac000}, {0x3d6ae000},
+ {0x3d6b0000}, {0x3d6b2000}, {0x3d6b4000}, {0x3d6b6000},
+ {0x3d6b8000}, {0x3d6ba000}, {0x3d6bc000}, {0x3d6be000},
+ {0x3d6c0000}, {0x3d6c2000}, {0x3d6c4000}, {0x3d6c6000},
+ {0x3d6c8000}, {0x3d6ca000}, {0x3d6cc000}, {0x3d6ce000},
+ {0x3d6d0000}, {0x3d6d2000}, {0x3d6d4000}, {0x3d6d6000},
+ {0x3d6d8000}, {0x3d6da000}, {0x3d6dc000}, {0x3d6de000},
+ {0x3d6e0000}, {0x3d6e2000}, {0x3d6e4000}, {0x3d6e6000},
+ {0x3d6e8000}, {0x3d6ea000}, {0x3d6ec000}, {0x3d6ee000},
+ {0x3d6f0000}, {0x3d6f2000}, {0x3d6f4000}, {0x3d6f6000},
+ {0x3d6f8000}, {0x3d6fa000}, {0x3d6fc000}, {0x3d6fe000},
+ {0x3d700000}, {0x3d702000}, {0x3d704000}, {0x3d706000},
+ {0x3d708000}, {0x3d70a000}, {0x3d70c000}, {0x3d70e000},
+ {0x3d710000}, {0x3d712000}, {0x3d714000}, {0x3d716000},
+ {0x3d718000}, {0x3d71a000}, {0x3d71c000}, {0x3d71e000},
+ {0x3d720000}, {0x3d722000}, {0x3d724000}, {0x3d726000},
+ {0x3d728000}, {0x3d72a000}, {0x3d72c000}, {0x3d72e000},
+ {0x3d730000}, {0x3d732000}, {0x3d734000}, {0x3d736000},
+ {0x3d738000}, {0x3d73a000}, {0x3d73c000}, {0x3d73e000},
+ {0x3d740000}, {0x3d742000}, {0x3d744000}, {0x3d746000},
+ {0x3d748000}, {0x3d74a000}, {0x3d74c000}, {0x3d74e000},
+ {0x3d750000}, {0x3d752000}, {0x3d754000}, {0x3d756000},
+ {0x3d758000}, {0x3d75a000}, {0x3d75c000}, {0x3d75e000},
+ {0x3d760000}, {0x3d762000}, {0x3d764000}, {0x3d766000},
+ {0x3d768000}, {0x3d76a000}, {0x3d76c000}, {0x3d76e000},
+ {0x3d770000}, {0x3d772000}, {0x3d774000}, {0x3d776000},
+ {0x3d778000}, {0x3d77a000}, {0x3d77c000}, {0x3d77e000},
+ {0x3d780000}, {0x3d782000}, {0x3d784000}, {0x3d786000},
+ {0x3d788000}, {0x3d78a000}, {0x3d78c000}, {0x3d78e000},
+ {0x3d790000}, {0x3d792000}, {0x3d794000}, {0x3d796000},
+ {0x3d798000}, {0x3d79a000}, {0x3d79c000}, {0x3d79e000},
+ {0x3d7a0000}, {0x3d7a2000}, {0x3d7a4000}, {0x3d7a6000},
+ {0x3d7a8000}, {0x3d7aa000}, {0x3d7ac000}, {0x3d7ae000},
+ {0x3d7b0000}, {0x3d7b2000}, {0x3d7b4000}, {0x3d7b6000},
+ {0x3d7b8000}, {0x3d7ba000}, {0x3d7bc000}, {0x3d7be000},
+ {0x3d7c0000}, {0x3d7c2000}, {0x3d7c4000}, {0x3d7c6000},
+ {0x3d7c8000}, {0x3d7ca000}, {0x3d7cc000}, {0x3d7ce000},
+ {0x3d7d0000}, {0x3d7d2000}, {0x3d7d4000}, {0x3d7d6000},
+ {0x3d7d8000}, {0x3d7da000}, {0x3d7dc000}, {0x3d7de000},
+ {0x3d7e0000}, {0x3d7e2000}, {0x3d7e4000}, {0x3d7e6000},
+ {0x3d7e8000}, {0x3d7ea000}, {0x3d7ec000}, {0x3d7ee000},
+ {0x3d7f0000}, {0x3d7f2000}, {0x3d7f4000}, {0x3d7f6000},
+ {0x3d7f8000}, {0x3d7fa000}, {0x3d7fc000}, {0x3d7fe000},
+ {0x3d800000}, {0x3d802000}, {0x3d804000}, {0x3d806000},
+ {0x3d808000}, {0x3d80a000}, {0x3d80c000}, {0x3d80e000},
+ {0x3d810000}, {0x3d812000}, {0x3d814000}, {0x3d816000},
+ {0x3d818000}, {0x3d81a000}, {0x3d81c000}, {0x3d81e000},
+ {0x3d820000}, {0x3d822000}, {0x3d824000}, {0x3d826000},
+ {0x3d828000}, {0x3d82a000}, {0x3d82c000}, {0x3d82e000},
+ {0x3d830000}, {0x3d832000}, {0x3d834000}, {0x3d836000},
+ {0x3d838000}, {0x3d83a000}, {0x3d83c000}, {0x3d83e000},
+ {0x3d840000}, {0x3d842000}, {0x3d844000}, {0x3d846000},
+ {0x3d848000}, {0x3d84a000}, {0x3d84c000}, {0x3d84e000},
+ {0x3d850000}, {0x3d852000}, {0x3d854000}, {0x3d856000},
+ {0x3d858000}, {0x3d85a000}, {0x3d85c000}, {0x3d85e000},
+ {0x3d860000}, {0x3d862000}, {0x3d864000}, {0x3d866000},
+ {0x3d868000}, {0x3d86a000}, {0x3d86c000}, {0x3d86e000},
+ {0x3d870000}, {0x3d872000}, {0x3d874000}, {0x3d876000},
+ {0x3d878000}, {0x3d87a000}, {0x3d87c000}, {0x3d87e000},
+ {0x3d880000}, {0x3d882000}, {0x3d884000}, {0x3d886000},
+ {0x3d888000}, {0x3d88a000}, {0x3d88c000}, {0x3d88e000},
+ {0x3d890000}, {0x3d892000}, {0x3d894000}, {0x3d896000},
+ {0x3d898000}, {0x3d89a000}, {0x3d89c000}, {0x3d89e000},
+ {0x3d8a0000}, {0x3d8a2000}, {0x3d8a4000}, {0x3d8a6000},
+ {0x3d8a8000}, {0x3d8aa000}, {0x3d8ac000}, {0x3d8ae000},
+ {0x3d8b0000}, {0x3d8b2000}, {0x3d8b4000}, {0x3d8b6000},
+ {0x3d8b8000}, {0x3d8ba000}, {0x3d8bc000}, {0x3d8be000},
+ {0x3d8c0000}, {0x3d8c2000}, {0x3d8c4000}, {0x3d8c6000},
+ {0x3d8c8000}, {0x3d8ca000}, {0x3d8cc000}, {0x3d8ce000},
+ {0x3d8d0000}, {0x3d8d2000}, {0x3d8d4000}, {0x3d8d6000},
+ {0x3d8d8000}, {0x3d8da000}, {0x3d8dc000}, {0x3d8de000},
+ {0x3d8e0000}, {0x3d8e2000}, {0x3d8e4000}, {0x3d8e6000},
+ {0x3d8e8000}, {0x3d8ea000}, {0x3d8ec000}, {0x3d8ee000},
+ {0x3d8f0000}, {0x3d8f2000}, {0x3d8f4000}, {0x3d8f6000},
+ {0x3d8f8000}, {0x3d8fa000}, {0x3d8fc000}, {0x3d8fe000},
+ {0x3d900000}, {0x3d902000}, {0x3d904000}, {0x3d906000},
+ {0x3d908000}, {0x3d90a000}, {0x3d90c000}, {0x3d90e000},
+ {0x3d910000}, {0x3d912000}, {0x3d914000}, {0x3d916000},
+ {0x3d918000}, {0x3d91a000}, {0x3d91c000}, {0x3d91e000},
+ {0x3d920000}, {0x3d922000}, {0x3d924000}, {0x3d926000},
+ {0x3d928000}, {0x3d92a000}, {0x3d92c000}, {0x3d92e000},
+ {0x3d930000}, {0x3d932000}, {0x3d934000}, {0x3d936000},
+ {0x3d938000}, {0x3d93a000}, {0x3d93c000}, {0x3d93e000},
+ {0x3d940000}, {0x3d942000}, {0x3d944000}, {0x3d946000},
+ {0x3d948000}, {0x3d94a000}, {0x3d94c000}, {0x3d94e000},
+ {0x3d950000}, {0x3d952000}, {0x3d954000}, {0x3d956000},
+ {0x3d958000}, {0x3d95a000}, {0x3d95c000}, {0x3d95e000},
+ {0x3d960000}, {0x3d962000}, {0x3d964000}, {0x3d966000},
+ {0x3d968000}, {0x3d96a000}, {0x3d96c000}, {0x3d96e000},
+ {0x3d970000}, {0x3d972000}, {0x3d974000}, {0x3d976000},
+ {0x3d978000}, {0x3d97a000}, {0x3d97c000}, {0x3d97e000},
+ {0x3d980000}, {0x3d982000}, {0x3d984000}, {0x3d986000},
+ {0x3d988000}, {0x3d98a000}, {0x3d98c000}, {0x3d98e000},
+ {0x3d990000}, {0x3d992000}, {0x3d994000}, {0x3d996000},
+ {0x3d998000}, {0x3d99a000}, {0x3d99c000}, {0x3d99e000},
+ {0x3d9a0000}, {0x3d9a2000}, {0x3d9a4000}, {0x3d9a6000},
+ {0x3d9a8000}, {0x3d9aa000}, {0x3d9ac000}, {0x3d9ae000},
+ {0x3d9b0000}, {0x3d9b2000}, {0x3d9b4000}, {0x3d9b6000},
+ {0x3d9b8000}, {0x3d9ba000}, {0x3d9bc000}, {0x3d9be000},
+ {0x3d9c0000}, {0x3d9c2000}, {0x3d9c4000}, {0x3d9c6000},
+ {0x3d9c8000}, {0x3d9ca000}, {0x3d9cc000}, {0x3d9ce000},
+ {0x3d9d0000}, {0x3d9d2000}, {0x3d9d4000}, {0x3d9d6000},
+ {0x3d9d8000}, {0x3d9da000}, {0x3d9dc000}, {0x3d9de000},
+ {0x3d9e0000}, {0x3d9e2000}, {0x3d9e4000}, {0x3d9e6000},
+ {0x3d9e8000}, {0x3d9ea000}, {0x3d9ec000}, {0x3d9ee000},
+ {0x3d9f0000}, {0x3d9f2000}, {0x3d9f4000}, {0x3d9f6000},
+ {0x3d9f8000}, {0x3d9fa000}, {0x3d9fc000}, {0x3d9fe000},
+ {0x3da00000}, {0x3da02000}, {0x3da04000}, {0x3da06000},
+ {0x3da08000}, {0x3da0a000}, {0x3da0c000}, {0x3da0e000},
+ {0x3da10000}, {0x3da12000}, {0x3da14000}, {0x3da16000},
+ {0x3da18000}, {0x3da1a000}, {0x3da1c000}, {0x3da1e000},
+ {0x3da20000}, {0x3da22000}, {0x3da24000}, {0x3da26000},
+ {0x3da28000}, {0x3da2a000}, {0x3da2c000}, {0x3da2e000},
+ {0x3da30000}, {0x3da32000}, {0x3da34000}, {0x3da36000},
+ {0x3da38000}, {0x3da3a000}, {0x3da3c000}, {0x3da3e000},
+ {0x3da40000}, {0x3da42000}, {0x3da44000}, {0x3da46000},
+ {0x3da48000}, {0x3da4a000}, {0x3da4c000}, {0x3da4e000},
+ {0x3da50000}, {0x3da52000}, {0x3da54000}, {0x3da56000},
+ {0x3da58000}, {0x3da5a000}, {0x3da5c000}, {0x3da5e000},
+ {0x3da60000}, {0x3da62000}, {0x3da64000}, {0x3da66000},
+ {0x3da68000}, {0x3da6a000}, {0x3da6c000}, {0x3da6e000},
+ {0x3da70000}, {0x3da72000}, {0x3da74000}, {0x3da76000},
+ {0x3da78000}, {0x3da7a000}, {0x3da7c000}, {0x3da7e000},
+ {0x3da80000}, {0x3da82000}, {0x3da84000}, {0x3da86000},
+ {0x3da88000}, {0x3da8a000}, {0x3da8c000}, {0x3da8e000},
+ {0x3da90000}, {0x3da92000}, {0x3da94000}, {0x3da96000},
+ {0x3da98000}, {0x3da9a000}, {0x3da9c000}, {0x3da9e000},
+ {0x3daa0000}, {0x3daa2000}, {0x3daa4000}, {0x3daa6000},
+ {0x3daa8000}, {0x3daaa000}, {0x3daac000}, {0x3daae000},
+ {0x3dab0000}, {0x3dab2000}, {0x3dab4000}, {0x3dab6000},
+ {0x3dab8000}, {0x3daba000}, {0x3dabc000}, {0x3dabe000},
+ {0x3dac0000}, {0x3dac2000}, {0x3dac4000}, {0x3dac6000},
+ {0x3dac8000}, {0x3daca000}, {0x3dacc000}, {0x3dace000},
+ {0x3dad0000}, {0x3dad2000}, {0x3dad4000}, {0x3dad6000},
+ {0x3dad8000}, {0x3dada000}, {0x3dadc000}, {0x3dade000},
+ {0x3dae0000}, {0x3dae2000}, {0x3dae4000}, {0x3dae6000},
+ {0x3dae8000}, {0x3daea000}, {0x3daec000}, {0x3daee000},
+ {0x3daf0000}, {0x3daf2000}, {0x3daf4000}, {0x3daf6000},
+ {0x3daf8000}, {0x3dafa000}, {0x3dafc000}, {0x3dafe000},
+ {0x3db00000}, {0x3db02000}, {0x3db04000}, {0x3db06000},
+ {0x3db08000}, {0x3db0a000}, {0x3db0c000}, {0x3db0e000},
+ {0x3db10000}, {0x3db12000}, {0x3db14000}, {0x3db16000},
+ {0x3db18000}, {0x3db1a000}, {0x3db1c000}, {0x3db1e000},
+ {0x3db20000}, {0x3db22000}, {0x3db24000}, {0x3db26000},
+ {0x3db28000}, {0x3db2a000}, {0x3db2c000}, {0x3db2e000},
+ {0x3db30000}, {0x3db32000}, {0x3db34000}, {0x3db36000},
+ {0x3db38000}, {0x3db3a000}, {0x3db3c000}, {0x3db3e000},
+ {0x3db40000}, {0x3db42000}, {0x3db44000}, {0x3db46000},
+ {0x3db48000}, {0x3db4a000}, {0x3db4c000}, {0x3db4e000},
+ {0x3db50000}, {0x3db52000}, {0x3db54000}, {0x3db56000},
+ {0x3db58000}, {0x3db5a000}, {0x3db5c000}, {0x3db5e000},
+ {0x3db60000}, {0x3db62000}, {0x3db64000}, {0x3db66000},
+ {0x3db68000}, {0x3db6a000}, {0x3db6c000}, {0x3db6e000},
+ {0x3db70000}, {0x3db72000}, {0x3db74000}, {0x3db76000},
+ {0x3db78000}, {0x3db7a000}, {0x3db7c000}, {0x3db7e000},
+ {0x3db80000}, {0x3db82000}, {0x3db84000}, {0x3db86000},
+ {0x3db88000}, {0x3db8a000}, {0x3db8c000}, {0x3db8e000},
+ {0x3db90000}, {0x3db92000}, {0x3db94000}, {0x3db96000},
+ {0x3db98000}, {0x3db9a000}, {0x3db9c000}, {0x3db9e000},
+ {0x3dba0000}, {0x3dba2000}, {0x3dba4000}, {0x3dba6000},
+ {0x3dba8000}, {0x3dbaa000}, {0x3dbac000}, {0x3dbae000},
+ {0x3dbb0000}, {0x3dbb2000}, {0x3dbb4000}, {0x3dbb6000},
+ {0x3dbb8000}, {0x3dbba000}, {0x3dbbc000}, {0x3dbbe000},
+ {0x3dbc0000}, {0x3dbc2000}, {0x3dbc4000}, {0x3dbc6000},
+ {0x3dbc8000}, {0x3dbca000}, {0x3dbcc000}, {0x3dbce000},
+ {0x3dbd0000}, {0x3dbd2000}, {0x3dbd4000}, {0x3dbd6000},
+ {0x3dbd8000}, {0x3dbda000}, {0x3dbdc000}, {0x3dbde000},
+ {0x3dbe0000}, {0x3dbe2000}, {0x3dbe4000}, {0x3dbe6000},
+ {0x3dbe8000}, {0x3dbea000}, {0x3dbec000}, {0x3dbee000},
+ {0x3dbf0000}, {0x3dbf2000}, {0x3dbf4000}, {0x3dbf6000},
+ {0x3dbf8000}, {0x3dbfa000}, {0x3dbfc000}, {0x3dbfe000},
+ {0x3dc00000}, {0x3dc02000}, {0x3dc04000}, {0x3dc06000},
+ {0x3dc08000}, {0x3dc0a000}, {0x3dc0c000}, {0x3dc0e000},
+ {0x3dc10000}, {0x3dc12000}, {0x3dc14000}, {0x3dc16000},
+ {0x3dc18000}, {0x3dc1a000}, {0x3dc1c000}, {0x3dc1e000},
+ {0x3dc20000}, {0x3dc22000}, {0x3dc24000}, {0x3dc26000},
+ {0x3dc28000}, {0x3dc2a000}, {0x3dc2c000}, {0x3dc2e000},
+ {0x3dc30000}, {0x3dc32000}, {0x3dc34000}, {0x3dc36000},
+ {0x3dc38000}, {0x3dc3a000}, {0x3dc3c000}, {0x3dc3e000},
+ {0x3dc40000}, {0x3dc42000}, {0x3dc44000}, {0x3dc46000},
+ {0x3dc48000}, {0x3dc4a000}, {0x3dc4c000}, {0x3dc4e000},
+ {0x3dc50000}, {0x3dc52000}, {0x3dc54000}, {0x3dc56000},
+ {0x3dc58000}, {0x3dc5a000}, {0x3dc5c000}, {0x3dc5e000},
+ {0x3dc60000}, {0x3dc62000}, {0x3dc64000}, {0x3dc66000},
+ {0x3dc68000}, {0x3dc6a000}, {0x3dc6c000}, {0x3dc6e000},
+ {0x3dc70000}, {0x3dc72000}, {0x3dc74000}, {0x3dc76000},
+ {0x3dc78000}, {0x3dc7a000}, {0x3dc7c000}, {0x3dc7e000},
+ {0x3dc80000}, {0x3dc82000}, {0x3dc84000}, {0x3dc86000},
+ {0x3dc88000}, {0x3dc8a000}, {0x3dc8c000}, {0x3dc8e000},
+ {0x3dc90000}, {0x3dc92000}, {0x3dc94000}, {0x3dc96000},
+ {0x3dc98000}, {0x3dc9a000}, {0x3dc9c000}, {0x3dc9e000},
+ {0x3dca0000}, {0x3dca2000}, {0x3dca4000}, {0x3dca6000},
+ {0x3dca8000}, {0x3dcaa000}, {0x3dcac000}, {0x3dcae000},
+ {0x3dcb0000}, {0x3dcb2000}, {0x3dcb4000}, {0x3dcb6000},
+ {0x3dcb8000}, {0x3dcba000}, {0x3dcbc000}, {0x3dcbe000},
+ {0x3dcc0000}, {0x3dcc2000}, {0x3dcc4000}, {0x3dcc6000},
+ {0x3dcc8000}, {0x3dcca000}, {0x3dccc000}, {0x3dcce000},
+ {0x3dcd0000}, {0x3dcd2000}, {0x3dcd4000}, {0x3dcd6000},
+ {0x3dcd8000}, {0x3dcda000}, {0x3dcdc000}, {0x3dcde000},
+ {0x3dce0000}, {0x3dce2000}, {0x3dce4000}, {0x3dce6000},
+ {0x3dce8000}, {0x3dcea000}, {0x3dcec000}, {0x3dcee000},
+ {0x3dcf0000}, {0x3dcf2000}, {0x3dcf4000}, {0x3dcf6000},
+ {0x3dcf8000}, {0x3dcfa000}, {0x3dcfc000}, {0x3dcfe000},
+ {0x3dd00000}, {0x3dd02000}, {0x3dd04000}, {0x3dd06000},
+ {0x3dd08000}, {0x3dd0a000}, {0x3dd0c000}, {0x3dd0e000},
+ {0x3dd10000}, {0x3dd12000}, {0x3dd14000}, {0x3dd16000},
+ {0x3dd18000}, {0x3dd1a000}, {0x3dd1c000}, {0x3dd1e000},
+ {0x3dd20000}, {0x3dd22000}, {0x3dd24000}, {0x3dd26000},
+ {0x3dd28000}, {0x3dd2a000}, {0x3dd2c000}, {0x3dd2e000},
+ {0x3dd30000}, {0x3dd32000}, {0x3dd34000}, {0x3dd36000},
+ {0x3dd38000}, {0x3dd3a000}, {0x3dd3c000}, {0x3dd3e000},
+ {0x3dd40000}, {0x3dd42000}, {0x3dd44000}, {0x3dd46000},
+ {0x3dd48000}, {0x3dd4a000}, {0x3dd4c000}, {0x3dd4e000},
+ {0x3dd50000}, {0x3dd52000}, {0x3dd54000}, {0x3dd56000},
+ {0x3dd58000}, {0x3dd5a000}, {0x3dd5c000}, {0x3dd5e000},
+ {0x3dd60000}, {0x3dd62000}, {0x3dd64000}, {0x3dd66000},
+ {0x3dd68000}, {0x3dd6a000}, {0x3dd6c000}, {0x3dd6e000},
+ {0x3dd70000}, {0x3dd72000}, {0x3dd74000}, {0x3dd76000},
+ {0x3dd78000}, {0x3dd7a000}, {0x3dd7c000}, {0x3dd7e000},
+ {0x3dd80000}, {0x3dd82000}, {0x3dd84000}, {0x3dd86000},
+ {0x3dd88000}, {0x3dd8a000}, {0x3dd8c000}, {0x3dd8e000},
+ {0x3dd90000}, {0x3dd92000}, {0x3dd94000}, {0x3dd96000},
+ {0x3dd98000}, {0x3dd9a000}, {0x3dd9c000}, {0x3dd9e000},
+ {0x3dda0000}, {0x3dda2000}, {0x3dda4000}, {0x3dda6000},
+ {0x3dda8000}, {0x3ddaa000}, {0x3ddac000}, {0x3ddae000},
+ {0x3ddb0000}, {0x3ddb2000}, {0x3ddb4000}, {0x3ddb6000},
+ {0x3ddb8000}, {0x3ddba000}, {0x3ddbc000}, {0x3ddbe000},
+ {0x3ddc0000}, {0x3ddc2000}, {0x3ddc4000}, {0x3ddc6000},
+ {0x3ddc8000}, {0x3ddca000}, {0x3ddcc000}, {0x3ddce000},
+ {0x3ddd0000}, {0x3ddd2000}, {0x3ddd4000}, {0x3ddd6000},
+ {0x3ddd8000}, {0x3ddda000}, {0x3dddc000}, {0x3ddde000},
+ {0x3dde0000}, {0x3dde2000}, {0x3dde4000}, {0x3dde6000},
+ {0x3dde8000}, {0x3ddea000}, {0x3ddec000}, {0x3ddee000},
+ {0x3ddf0000}, {0x3ddf2000}, {0x3ddf4000}, {0x3ddf6000},
+ {0x3ddf8000}, {0x3ddfa000}, {0x3ddfc000}, {0x3ddfe000},
+ {0x3de00000}, {0x3de02000}, {0x3de04000}, {0x3de06000},
+ {0x3de08000}, {0x3de0a000}, {0x3de0c000}, {0x3de0e000},
+ {0x3de10000}, {0x3de12000}, {0x3de14000}, {0x3de16000},
+ {0x3de18000}, {0x3de1a000}, {0x3de1c000}, {0x3de1e000},
+ {0x3de20000}, {0x3de22000}, {0x3de24000}, {0x3de26000},
+ {0x3de28000}, {0x3de2a000}, {0x3de2c000}, {0x3de2e000},
+ {0x3de30000}, {0x3de32000}, {0x3de34000}, {0x3de36000},
+ {0x3de38000}, {0x3de3a000}, {0x3de3c000}, {0x3de3e000},
+ {0x3de40000}, {0x3de42000}, {0x3de44000}, {0x3de46000},
+ {0x3de48000}, {0x3de4a000}, {0x3de4c000}, {0x3de4e000},
+ {0x3de50000}, {0x3de52000}, {0x3de54000}, {0x3de56000},
+ {0x3de58000}, {0x3de5a000}, {0x3de5c000}, {0x3de5e000},
+ {0x3de60000}, {0x3de62000}, {0x3de64000}, {0x3de66000},
+ {0x3de68000}, {0x3de6a000}, {0x3de6c000}, {0x3de6e000},
+ {0x3de70000}, {0x3de72000}, {0x3de74000}, {0x3de76000},
+ {0x3de78000}, {0x3de7a000}, {0x3de7c000}, {0x3de7e000},
+ {0x3de80000}, {0x3de82000}, {0x3de84000}, {0x3de86000},
+ {0x3de88000}, {0x3de8a000}, {0x3de8c000}, {0x3de8e000},
+ {0x3de90000}, {0x3de92000}, {0x3de94000}, {0x3de96000},
+ {0x3de98000}, {0x3de9a000}, {0x3de9c000}, {0x3de9e000},
+ {0x3dea0000}, {0x3dea2000}, {0x3dea4000}, {0x3dea6000},
+ {0x3dea8000}, {0x3deaa000}, {0x3deac000}, {0x3deae000},
+ {0x3deb0000}, {0x3deb2000}, {0x3deb4000}, {0x3deb6000},
+ {0x3deb8000}, {0x3deba000}, {0x3debc000}, {0x3debe000},
+ {0x3dec0000}, {0x3dec2000}, {0x3dec4000}, {0x3dec6000},
+ {0x3dec8000}, {0x3deca000}, {0x3decc000}, {0x3dece000},
+ {0x3ded0000}, {0x3ded2000}, {0x3ded4000}, {0x3ded6000},
+ {0x3ded8000}, {0x3deda000}, {0x3dedc000}, {0x3dede000},
+ {0x3dee0000}, {0x3dee2000}, {0x3dee4000}, {0x3dee6000},
+ {0x3dee8000}, {0x3deea000}, {0x3deec000}, {0x3deee000},
+ {0x3def0000}, {0x3def2000}, {0x3def4000}, {0x3def6000},
+ {0x3def8000}, {0x3defa000}, {0x3defc000}, {0x3defe000},
+ {0x3df00000}, {0x3df02000}, {0x3df04000}, {0x3df06000},
+ {0x3df08000}, {0x3df0a000}, {0x3df0c000}, {0x3df0e000},
+ {0x3df10000}, {0x3df12000}, {0x3df14000}, {0x3df16000},
+ {0x3df18000}, {0x3df1a000}, {0x3df1c000}, {0x3df1e000},
+ {0x3df20000}, {0x3df22000}, {0x3df24000}, {0x3df26000},
+ {0x3df28000}, {0x3df2a000}, {0x3df2c000}, {0x3df2e000},
+ {0x3df30000}, {0x3df32000}, {0x3df34000}, {0x3df36000},
+ {0x3df38000}, {0x3df3a000}, {0x3df3c000}, {0x3df3e000},
+ {0x3df40000}, {0x3df42000}, {0x3df44000}, {0x3df46000},
+ {0x3df48000}, {0x3df4a000}, {0x3df4c000}, {0x3df4e000},
+ {0x3df50000}, {0x3df52000}, {0x3df54000}, {0x3df56000},
+ {0x3df58000}, {0x3df5a000}, {0x3df5c000}, {0x3df5e000},
+ {0x3df60000}, {0x3df62000}, {0x3df64000}, {0x3df66000},
+ {0x3df68000}, {0x3df6a000}, {0x3df6c000}, {0x3df6e000},
+ {0x3df70000}, {0x3df72000}, {0x3df74000}, {0x3df76000},
+ {0x3df78000}, {0x3df7a000}, {0x3df7c000}, {0x3df7e000},
+ {0x3df80000}, {0x3df82000}, {0x3df84000}, {0x3df86000},
+ {0x3df88000}, {0x3df8a000}, {0x3df8c000}, {0x3df8e000},
+ {0x3df90000}, {0x3df92000}, {0x3df94000}, {0x3df96000},
+ {0x3df98000}, {0x3df9a000}, {0x3df9c000}, {0x3df9e000},
+ {0x3dfa0000}, {0x3dfa2000}, {0x3dfa4000}, {0x3dfa6000},
+ {0x3dfa8000}, {0x3dfaa000}, {0x3dfac000}, {0x3dfae000},
+ {0x3dfb0000}, {0x3dfb2000}, {0x3dfb4000}, {0x3dfb6000},
+ {0x3dfb8000}, {0x3dfba000}, {0x3dfbc000}, {0x3dfbe000},
+ {0x3dfc0000}, {0x3dfc2000}, {0x3dfc4000}, {0x3dfc6000},
+ {0x3dfc8000}, {0x3dfca000}, {0x3dfcc000}, {0x3dfce000},
+ {0x3dfd0000}, {0x3dfd2000}, {0x3dfd4000}, {0x3dfd6000},
+ {0x3dfd8000}, {0x3dfda000}, {0x3dfdc000}, {0x3dfde000},
+ {0x3dfe0000}, {0x3dfe2000}, {0x3dfe4000}, {0x3dfe6000},
+ {0x3dfe8000}, {0x3dfea000}, {0x3dfec000}, {0x3dfee000},
+ {0x3dff0000}, {0x3dff2000}, {0x3dff4000}, {0x3dff6000},
+ {0x3dff8000}, {0x3dffa000}, {0x3dffc000}, {0x3dffe000},
+ {0x3e000000}, {0x3e002000}, {0x3e004000}, {0x3e006000},
+ {0x3e008000}, {0x3e00a000}, {0x3e00c000}, {0x3e00e000},
+ {0x3e010000}, {0x3e012000}, {0x3e014000}, {0x3e016000},
+ {0x3e018000}, {0x3e01a000}, {0x3e01c000}, {0x3e01e000},
+ {0x3e020000}, {0x3e022000}, {0x3e024000}, {0x3e026000},
+ {0x3e028000}, {0x3e02a000}, {0x3e02c000}, {0x3e02e000},
+ {0x3e030000}, {0x3e032000}, {0x3e034000}, {0x3e036000},
+ {0x3e038000}, {0x3e03a000}, {0x3e03c000}, {0x3e03e000},
+ {0x3e040000}, {0x3e042000}, {0x3e044000}, {0x3e046000},
+ {0x3e048000}, {0x3e04a000}, {0x3e04c000}, {0x3e04e000},
+ {0x3e050000}, {0x3e052000}, {0x3e054000}, {0x3e056000},
+ {0x3e058000}, {0x3e05a000}, {0x3e05c000}, {0x3e05e000},
+ {0x3e060000}, {0x3e062000}, {0x3e064000}, {0x3e066000},
+ {0x3e068000}, {0x3e06a000}, {0x3e06c000}, {0x3e06e000},
+ {0x3e070000}, {0x3e072000}, {0x3e074000}, {0x3e076000},
+ {0x3e078000}, {0x3e07a000}, {0x3e07c000}, {0x3e07e000},
+ {0x3e080000}, {0x3e082000}, {0x3e084000}, {0x3e086000},
+ {0x3e088000}, {0x3e08a000}, {0x3e08c000}, {0x3e08e000},
+ {0x3e090000}, {0x3e092000}, {0x3e094000}, {0x3e096000},
+ {0x3e098000}, {0x3e09a000}, {0x3e09c000}, {0x3e09e000},
+ {0x3e0a0000}, {0x3e0a2000}, {0x3e0a4000}, {0x3e0a6000},
+ {0x3e0a8000}, {0x3e0aa000}, {0x3e0ac000}, {0x3e0ae000},
+ {0x3e0b0000}, {0x3e0b2000}, {0x3e0b4000}, {0x3e0b6000},
+ {0x3e0b8000}, {0x3e0ba000}, {0x3e0bc000}, {0x3e0be000},
+ {0x3e0c0000}, {0x3e0c2000}, {0x3e0c4000}, {0x3e0c6000},
+ {0x3e0c8000}, {0x3e0ca000}, {0x3e0cc000}, {0x3e0ce000},
+ {0x3e0d0000}, {0x3e0d2000}, {0x3e0d4000}, {0x3e0d6000},
+ {0x3e0d8000}, {0x3e0da000}, {0x3e0dc000}, {0x3e0de000},
+ {0x3e0e0000}, {0x3e0e2000}, {0x3e0e4000}, {0x3e0e6000},
+ {0x3e0e8000}, {0x3e0ea000}, {0x3e0ec000}, {0x3e0ee000},
+ {0x3e0f0000}, {0x3e0f2000}, {0x3e0f4000}, {0x3e0f6000},
+ {0x3e0f8000}, {0x3e0fa000}, {0x3e0fc000}, {0x3e0fe000},
+ {0x3e100000}, {0x3e102000}, {0x3e104000}, {0x3e106000},
+ {0x3e108000}, {0x3e10a000}, {0x3e10c000}, {0x3e10e000},
+ {0x3e110000}, {0x3e112000}, {0x3e114000}, {0x3e116000},
+ {0x3e118000}, {0x3e11a000}, {0x3e11c000}, {0x3e11e000},
+ {0x3e120000}, {0x3e122000}, {0x3e124000}, {0x3e126000},
+ {0x3e128000}, {0x3e12a000}, {0x3e12c000}, {0x3e12e000},
+ {0x3e130000}, {0x3e132000}, {0x3e134000}, {0x3e136000},
+ {0x3e138000}, {0x3e13a000}, {0x3e13c000}, {0x3e13e000},
+ {0x3e140000}, {0x3e142000}, {0x3e144000}, {0x3e146000},
+ {0x3e148000}, {0x3e14a000}, {0x3e14c000}, {0x3e14e000},
+ {0x3e150000}, {0x3e152000}, {0x3e154000}, {0x3e156000},
+ {0x3e158000}, {0x3e15a000}, {0x3e15c000}, {0x3e15e000},
+ {0x3e160000}, {0x3e162000}, {0x3e164000}, {0x3e166000},
+ {0x3e168000}, {0x3e16a000}, {0x3e16c000}, {0x3e16e000},
+ {0x3e170000}, {0x3e172000}, {0x3e174000}, {0x3e176000},
+ {0x3e178000}, {0x3e17a000}, {0x3e17c000}, {0x3e17e000},
+ {0x3e180000}, {0x3e182000}, {0x3e184000}, {0x3e186000},
+ {0x3e188000}, {0x3e18a000}, {0x3e18c000}, {0x3e18e000},
+ {0x3e190000}, {0x3e192000}, {0x3e194000}, {0x3e196000},
+ {0x3e198000}, {0x3e19a000}, {0x3e19c000}, {0x3e19e000},
+ {0x3e1a0000}, {0x3e1a2000}, {0x3e1a4000}, {0x3e1a6000},
+ {0x3e1a8000}, {0x3e1aa000}, {0x3e1ac000}, {0x3e1ae000},
+ {0x3e1b0000}, {0x3e1b2000}, {0x3e1b4000}, {0x3e1b6000},
+ {0x3e1b8000}, {0x3e1ba000}, {0x3e1bc000}, {0x3e1be000},
+ {0x3e1c0000}, {0x3e1c2000}, {0x3e1c4000}, {0x3e1c6000},
+ {0x3e1c8000}, {0x3e1ca000}, {0x3e1cc000}, {0x3e1ce000},
+ {0x3e1d0000}, {0x3e1d2000}, {0x3e1d4000}, {0x3e1d6000},
+ {0x3e1d8000}, {0x3e1da000}, {0x3e1dc000}, {0x3e1de000},
+ {0x3e1e0000}, {0x3e1e2000}, {0x3e1e4000}, {0x3e1e6000},
+ {0x3e1e8000}, {0x3e1ea000}, {0x3e1ec000}, {0x3e1ee000},
+ {0x3e1f0000}, {0x3e1f2000}, {0x3e1f4000}, {0x3e1f6000},
+ {0x3e1f8000}, {0x3e1fa000}, {0x3e1fc000}, {0x3e1fe000},
+ {0x3e200000}, {0x3e202000}, {0x3e204000}, {0x3e206000},
+ {0x3e208000}, {0x3e20a000}, {0x3e20c000}, {0x3e20e000},
+ {0x3e210000}, {0x3e212000}, {0x3e214000}, {0x3e216000},
+ {0x3e218000}, {0x3e21a000}, {0x3e21c000}, {0x3e21e000},
+ {0x3e220000}, {0x3e222000}, {0x3e224000}, {0x3e226000},
+ {0x3e228000}, {0x3e22a000}, {0x3e22c000}, {0x3e22e000},
+ {0x3e230000}, {0x3e232000}, {0x3e234000}, {0x3e236000},
+ {0x3e238000}, {0x3e23a000}, {0x3e23c000}, {0x3e23e000},
+ {0x3e240000}, {0x3e242000}, {0x3e244000}, {0x3e246000},
+ {0x3e248000}, {0x3e24a000}, {0x3e24c000}, {0x3e24e000},
+ {0x3e250000}, {0x3e252000}, {0x3e254000}, {0x3e256000},
+ {0x3e258000}, {0x3e25a000}, {0x3e25c000}, {0x3e25e000},
+ {0x3e260000}, {0x3e262000}, {0x3e264000}, {0x3e266000},
+ {0x3e268000}, {0x3e26a000}, {0x3e26c000}, {0x3e26e000},
+ {0x3e270000}, {0x3e272000}, {0x3e274000}, {0x3e276000},
+ {0x3e278000}, {0x3e27a000}, {0x3e27c000}, {0x3e27e000},
+ {0x3e280000}, {0x3e282000}, {0x3e284000}, {0x3e286000},
+ {0x3e288000}, {0x3e28a000}, {0x3e28c000}, {0x3e28e000},
+ {0x3e290000}, {0x3e292000}, {0x3e294000}, {0x3e296000},
+ {0x3e298000}, {0x3e29a000}, {0x3e29c000}, {0x3e29e000},
+ {0x3e2a0000}, {0x3e2a2000}, {0x3e2a4000}, {0x3e2a6000},
+ {0x3e2a8000}, {0x3e2aa000}, {0x3e2ac000}, {0x3e2ae000},
+ {0x3e2b0000}, {0x3e2b2000}, {0x3e2b4000}, {0x3e2b6000},
+ {0x3e2b8000}, {0x3e2ba000}, {0x3e2bc000}, {0x3e2be000},
+ {0x3e2c0000}, {0x3e2c2000}, {0x3e2c4000}, {0x3e2c6000},
+ {0x3e2c8000}, {0x3e2ca000}, {0x3e2cc000}, {0x3e2ce000},
+ {0x3e2d0000}, {0x3e2d2000}, {0x3e2d4000}, {0x3e2d6000},
+ {0x3e2d8000}, {0x3e2da000}, {0x3e2dc000}, {0x3e2de000},
+ {0x3e2e0000}, {0x3e2e2000}, {0x3e2e4000}, {0x3e2e6000},
+ {0x3e2e8000}, {0x3e2ea000}, {0x3e2ec000}, {0x3e2ee000},
+ {0x3e2f0000}, {0x3e2f2000}, {0x3e2f4000}, {0x3e2f6000},
+ {0x3e2f8000}, {0x3e2fa000}, {0x3e2fc000}, {0x3e2fe000},
+ {0x3e300000}, {0x3e302000}, {0x3e304000}, {0x3e306000},
+ {0x3e308000}, {0x3e30a000}, {0x3e30c000}, {0x3e30e000},
+ {0x3e310000}, {0x3e312000}, {0x3e314000}, {0x3e316000},
+ {0x3e318000}, {0x3e31a000}, {0x3e31c000}, {0x3e31e000},
+ {0x3e320000}, {0x3e322000}, {0x3e324000}, {0x3e326000},
+ {0x3e328000}, {0x3e32a000}, {0x3e32c000}, {0x3e32e000},
+ {0x3e330000}, {0x3e332000}, {0x3e334000}, {0x3e336000},
+ {0x3e338000}, {0x3e33a000}, {0x3e33c000}, {0x3e33e000},
+ {0x3e340000}, {0x3e342000}, {0x3e344000}, {0x3e346000},
+ {0x3e348000}, {0x3e34a000}, {0x3e34c000}, {0x3e34e000},
+ {0x3e350000}, {0x3e352000}, {0x3e354000}, {0x3e356000},
+ {0x3e358000}, {0x3e35a000}, {0x3e35c000}, {0x3e35e000},
+ {0x3e360000}, {0x3e362000}, {0x3e364000}, {0x3e366000},
+ {0x3e368000}, {0x3e36a000}, {0x3e36c000}, {0x3e36e000},
+ {0x3e370000}, {0x3e372000}, {0x3e374000}, {0x3e376000},
+ {0x3e378000}, {0x3e37a000}, {0x3e37c000}, {0x3e37e000},
+ {0x3e380000}, {0x3e382000}, {0x3e384000}, {0x3e386000},
+ {0x3e388000}, {0x3e38a000}, {0x3e38c000}, {0x3e38e000},
+ {0x3e390000}, {0x3e392000}, {0x3e394000}, {0x3e396000},
+ {0x3e398000}, {0x3e39a000}, {0x3e39c000}, {0x3e39e000},
+ {0x3e3a0000}, {0x3e3a2000}, {0x3e3a4000}, {0x3e3a6000},
+ {0x3e3a8000}, {0x3e3aa000}, {0x3e3ac000}, {0x3e3ae000},
+ {0x3e3b0000}, {0x3e3b2000}, {0x3e3b4000}, {0x3e3b6000},
+ {0x3e3b8000}, {0x3e3ba000}, {0x3e3bc000}, {0x3e3be000},
+ {0x3e3c0000}, {0x3e3c2000}, {0x3e3c4000}, {0x3e3c6000},
+ {0x3e3c8000}, {0x3e3ca000}, {0x3e3cc000}, {0x3e3ce000},
+ {0x3e3d0000}, {0x3e3d2000}, {0x3e3d4000}, {0x3e3d6000},
+ {0x3e3d8000}, {0x3e3da000}, {0x3e3dc000}, {0x3e3de000},
+ {0x3e3e0000}, {0x3e3e2000}, {0x3e3e4000}, {0x3e3e6000},
+ {0x3e3e8000}, {0x3e3ea000}, {0x3e3ec000}, {0x3e3ee000},
+ {0x3e3f0000}, {0x3e3f2000}, {0x3e3f4000}, {0x3e3f6000},
+ {0x3e3f8000}, {0x3e3fa000}, {0x3e3fc000}, {0x3e3fe000},
+ {0x3e400000}, {0x3e402000}, {0x3e404000}, {0x3e406000},
+ {0x3e408000}, {0x3e40a000}, {0x3e40c000}, {0x3e40e000},
+ {0x3e410000}, {0x3e412000}, {0x3e414000}, {0x3e416000},
+ {0x3e418000}, {0x3e41a000}, {0x3e41c000}, {0x3e41e000},
+ {0x3e420000}, {0x3e422000}, {0x3e424000}, {0x3e426000},
+ {0x3e428000}, {0x3e42a000}, {0x3e42c000}, {0x3e42e000},
+ {0x3e430000}, {0x3e432000}, {0x3e434000}, {0x3e436000},
+ {0x3e438000}, {0x3e43a000}, {0x3e43c000}, {0x3e43e000},
+ {0x3e440000}, {0x3e442000}, {0x3e444000}, {0x3e446000},
+ {0x3e448000}, {0x3e44a000}, {0x3e44c000}, {0x3e44e000},
+ {0x3e450000}, {0x3e452000}, {0x3e454000}, {0x3e456000},
+ {0x3e458000}, {0x3e45a000}, {0x3e45c000}, {0x3e45e000},
+ {0x3e460000}, {0x3e462000}, {0x3e464000}, {0x3e466000},
+ {0x3e468000}, {0x3e46a000}, {0x3e46c000}, {0x3e46e000},
+ {0x3e470000}, {0x3e472000}, {0x3e474000}, {0x3e476000},
+ {0x3e478000}, {0x3e47a000}, {0x3e47c000}, {0x3e47e000},
+ {0x3e480000}, {0x3e482000}, {0x3e484000}, {0x3e486000},
+ {0x3e488000}, {0x3e48a000}, {0x3e48c000}, {0x3e48e000},
+ {0x3e490000}, {0x3e492000}, {0x3e494000}, {0x3e496000},
+ {0x3e498000}, {0x3e49a000}, {0x3e49c000}, {0x3e49e000},
+ {0x3e4a0000}, {0x3e4a2000}, {0x3e4a4000}, {0x3e4a6000},
+ {0x3e4a8000}, {0x3e4aa000}, {0x3e4ac000}, {0x3e4ae000},
+ {0x3e4b0000}, {0x3e4b2000}, {0x3e4b4000}, {0x3e4b6000},
+ {0x3e4b8000}, {0x3e4ba000}, {0x3e4bc000}, {0x3e4be000},
+ {0x3e4c0000}, {0x3e4c2000}, {0x3e4c4000}, {0x3e4c6000},
+ {0x3e4c8000}, {0x3e4ca000}, {0x3e4cc000}, {0x3e4ce000},
+ {0x3e4d0000}, {0x3e4d2000}, {0x3e4d4000}, {0x3e4d6000},
+ {0x3e4d8000}, {0x3e4da000}, {0x3e4dc000}, {0x3e4de000},
+ {0x3e4e0000}, {0x3e4e2000}, {0x3e4e4000}, {0x3e4e6000},
+ {0x3e4e8000}, {0x3e4ea000}, {0x3e4ec000}, {0x3e4ee000},
+ {0x3e4f0000}, {0x3e4f2000}, {0x3e4f4000}, {0x3e4f6000},
+ {0x3e4f8000}, {0x3e4fa000}, {0x3e4fc000}, {0x3e4fe000},
+ {0x3e500000}, {0x3e502000}, {0x3e504000}, {0x3e506000},
+ {0x3e508000}, {0x3e50a000}, {0x3e50c000}, {0x3e50e000},
+ {0x3e510000}, {0x3e512000}, {0x3e514000}, {0x3e516000},
+ {0x3e518000}, {0x3e51a000}, {0x3e51c000}, {0x3e51e000},
+ {0x3e520000}, {0x3e522000}, {0x3e524000}, {0x3e526000},
+ {0x3e528000}, {0x3e52a000}, {0x3e52c000}, {0x3e52e000},
+ {0x3e530000}, {0x3e532000}, {0x3e534000}, {0x3e536000},
+ {0x3e538000}, {0x3e53a000}, {0x3e53c000}, {0x3e53e000},
+ {0x3e540000}, {0x3e542000}, {0x3e544000}, {0x3e546000},
+ {0x3e548000}, {0x3e54a000}, {0x3e54c000}, {0x3e54e000},
+ {0x3e550000}, {0x3e552000}, {0x3e554000}, {0x3e556000},
+ {0x3e558000}, {0x3e55a000}, {0x3e55c000}, {0x3e55e000},
+ {0x3e560000}, {0x3e562000}, {0x3e564000}, {0x3e566000},
+ {0x3e568000}, {0x3e56a000}, {0x3e56c000}, {0x3e56e000},
+ {0x3e570000}, {0x3e572000}, {0x3e574000}, {0x3e576000},
+ {0x3e578000}, {0x3e57a000}, {0x3e57c000}, {0x3e57e000},
+ {0x3e580000}, {0x3e582000}, {0x3e584000}, {0x3e586000},
+ {0x3e588000}, {0x3e58a000}, {0x3e58c000}, {0x3e58e000},
+ {0x3e590000}, {0x3e592000}, {0x3e594000}, {0x3e596000},
+ {0x3e598000}, {0x3e59a000}, {0x3e59c000}, {0x3e59e000},
+ {0x3e5a0000}, {0x3e5a2000}, {0x3e5a4000}, {0x3e5a6000},
+ {0x3e5a8000}, {0x3e5aa000}, {0x3e5ac000}, {0x3e5ae000},
+ {0x3e5b0000}, {0x3e5b2000}, {0x3e5b4000}, {0x3e5b6000},
+ {0x3e5b8000}, {0x3e5ba000}, {0x3e5bc000}, {0x3e5be000},
+ {0x3e5c0000}, {0x3e5c2000}, {0x3e5c4000}, {0x3e5c6000},
+ {0x3e5c8000}, {0x3e5ca000}, {0x3e5cc000}, {0x3e5ce000},
+ {0x3e5d0000}, {0x3e5d2000}, {0x3e5d4000}, {0x3e5d6000},
+ {0x3e5d8000}, {0x3e5da000}, {0x3e5dc000}, {0x3e5de000},
+ {0x3e5e0000}, {0x3e5e2000}, {0x3e5e4000}, {0x3e5e6000},
+ {0x3e5e8000}, {0x3e5ea000}, {0x3e5ec000}, {0x3e5ee000},
+ {0x3e5f0000}, {0x3e5f2000}, {0x3e5f4000}, {0x3e5f6000},
+ {0x3e5f8000}, {0x3e5fa000}, {0x3e5fc000}, {0x3e5fe000},
+ {0x3e600000}, {0x3e602000}, {0x3e604000}, {0x3e606000},
+ {0x3e608000}, {0x3e60a000}, {0x3e60c000}, {0x3e60e000},
+ {0x3e610000}, {0x3e612000}, {0x3e614000}, {0x3e616000},
+ {0x3e618000}, {0x3e61a000}, {0x3e61c000}, {0x3e61e000},
+ {0x3e620000}, {0x3e622000}, {0x3e624000}, {0x3e626000},
+ {0x3e628000}, {0x3e62a000}, {0x3e62c000}, {0x3e62e000},
+ {0x3e630000}, {0x3e632000}, {0x3e634000}, {0x3e636000},
+ {0x3e638000}, {0x3e63a000}, {0x3e63c000}, {0x3e63e000},
+ {0x3e640000}, {0x3e642000}, {0x3e644000}, {0x3e646000},
+ {0x3e648000}, {0x3e64a000}, {0x3e64c000}, {0x3e64e000},
+ {0x3e650000}, {0x3e652000}, {0x3e654000}, {0x3e656000},
+ {0x3e658000}, {0x3e65a000}, {0x3e65c000}, {0x3e65e000},
+ {0x3e660000}, {0x3e662000}, {0x3e664000}, {0x3e666000},
+ {0x3e668000}, {0x3e66a000}, {0x3e66c000}, {0x3e66e000},
+ {0x3e670000}, {0x3e672000}, {0x3e674000}, {0x3e676000},
+ {0x3e678000}, {0x3e67a000}, {0x3e67c000}, {0x3e67e000},
+ {0x3e680000}, {0x3e682000}, {0x3e684000}, {0x3e686000},
+ {0x3e688000}, {0x3e68a000}, {0x3e68c000}, {0x3e68e000},
+ {0x3e690000}, {0x3e692000}, {0x3e694000}, {0x3e696000},
+ {0x3e698000}, {0x3e69a000}, {0x3e69c000}, {0x3e69e000},
+ {0x3e6a0000}, {0x3e6a2000}, {0x3e6a4000}, {0x3e6a6000},
+ {0x3e6a8000}, {0x3e6aa000}, {0x3e6ac000}, {0x3e6ae000},
+ {0x3e6b0000}, {0x3e6b2000}, {0x3e6b4000}, {0x3e6b6000},
+ {0x3e6b8000}, {0x3e6ba000}, {0x3e6bc000}, {0x3e6be000},
+ {0x3e6c0000}, {0x3e6c2000}, {0x3e6c4000}, {0x3e6c6000},
+ {0x3e6c8000}, {0x3e6ca000}, {0x3e6cc000}, {0x3e6ce000},
+ {0x3e6d0000}, {0x3e6d2000}, {0x3e6d4000}, {0x3e6d6000},
+ {0x3e6d8000}, {0x3e6da000}, {0x3e6dc000}, {0x3e6de000},
+ {0x3e6e0000}, {0x3e6e2000}, {0x3e6e4000}, {0x3e6e6000},
+ {0x3e6e8000}, {0x3e6ea000}, {0x3e6ec000}, {0x3e6ee000},
+ {0x3e6f0000}, {0x3e6f2000}, {0x3e6f4000}, {0x3e6f6000},
+ {0x3e6f8000}, {0x3e6fa000}, {0x3e6fc000}, {0x3e6fe000},
+ {0x3e700000}, {0x3e702000}, {0x3e704000}, {0x3e706000},
+ {0x3e708000}, {0x3e70a000}, {0x3e70c000}, {0x3e70e000},
+ {0x3e710000}, {0x3e712000}, {0x3e714000}, {0x3e716000},
+ {0x3e718000}, {0x3e71a000}, {0x3e71c000}, {0x3e71e000},
+ {0x3e720000}, {0x3e722000}, {0x3e724000}, {0x3e726000},
+ {0x3e728000}, {0x3e72a000}, {0x3e72c000}, {0x3e72e000},
+ {0x3e730000}, {0x3e732000}, {0x3e734000}, {0x3e736000},
+ {0x3e738000}, {0x3e73a000}, {0x3e73c000}, {0x3e73e000},
+ {0x3e740000}, {0x3e742000}, {0x3e744000}, {0x3e746000},
+ {0x3e748000}, {0x3e74a000}, {0x3e74c000}, {0x3e74e000},
+ {0x3e750000}, {0x3e752000}, {0x3e754000}, {0x3e756000},
+ {0x3e758000}, {0x3e75a000}, {0x3e75c000}, {0x3e75e000},
+ {0x3e760000}, {0x3e762000}, {0x3e764000}, {0x3e766000},
+ {0x3e768000}, {0x3e76a000}, {0x3e76c000}, {0x3e76e000},
+ {0x3e770000}, {0x3e772000}, {0x3e774000}, {0x3e776000},
+ {0x3e778000}, {0x3e77a000}, {0x3e77c000}, {0x3e77e000},
+ {0x3e780000}, {0x3e782000}, {0x3e784000}, {0x3e786000},
+ {0x3e788000}, {0x3e78a000}, {0x3e78c000}, {0x3e78e000},
+ {0x3e790000}, {0x3e792000}, {0x3e794000}, {0x3e796000},
+ {0x3e798000}, {0x3e79a000}, {0x3e79c000}, {0x3e79e000},
+ {0x3e7a0000}, {0x3e7a2000}, {0x3e7a4000}, {0x3e7a6000},
+ {0x3e7a8000}, {0x3e7aa000}, {0x3e7ac000}, {0x3e7ae000},
+ {0x3e7b0000}, {0x3e7b2000}, {0x3e7b4000}, {0x3e7b6000},
+ {0x3e7b8000}, {0x3e7ba000}, {0x3e7bc000}, {0x3e7be000},
+ {0x3e7c0000}, {0x3e7c2000}, {0x3e7c4000}, {0x3e7c6000},
+ {0x3e7c8000}, {0x3e7ca000}, {0x3e7cc000}, {0x3e7ce000},
+ {0x3e7d0000}, {0x3e7d2000}, {0x3e7d4000}, {0x3e7d6000},
+ {0x3e7d8000}, {0x3e7da000}, {0x3e7dc000}, {0x3e7de000},
+ {0x3e7e0000}, {0x3e7e2000}, {0x3e7e4000}, {0x3e7e6000},
+ {0x3e7e8000}, {0x3e7ea000}, {0x3e7ec000}, {0x3e7ee000},
+ {0x3e7f0000}, {0x3e7f2000}, {0x3e7f4000}, {0x3e7f6000},
+ {0x3e7f8000}, {0x3e7fa000}, {0x3e7fc000}, {0x3e7fe000},
+ {0x3e800000}, {0x3e802000}, {0x3e804000}, {0x3e806000},
+ {0x3e808000}, {0x3e80a000}, {0x3e80c000}, {0x3e80e000},
+ {0x3e810000}, {0x3e812000}, {0x3e814000}, {0x3e816000},
+ {0x3e818000}, {0x3e81a000}, {0x3e81c000}, {0x3e81e000},
+ {0x3e820000}, {0x3e822000}, {0x3e824000}, {0x3e826000},
+ {0x3e828000}, {0x3e82a000}, {0x3e82c000}, {0x3e82e000},
+ {0x3e830000}, {0x3e832000}, {0x3e834000}, {0x3e836000},
+ {0x3e838000}, {0x3e83a000}, {0x3e83c000}, {0x3e83e000},
+ {0x3e840000}, {0x3e842000}, {0x3e844000}, {0x3e846000},
+ {0x3e848000}, {0x3e84a000}, {0x3e84c000}, {0x3e84e000},
+ {0x3e850000}, {0x3e852000}, {0x3e854000}, {0x3e856000},
+ {0x3e858000}, {0x3e85a000}, {0x3e85c000}, {0x3e85e000},
+ {0x3e860000}, {0x3e862000}, {0x3e864000}, {0x3e866000},
+ {0x3e868000}, {0x3e86a000}, {0x3e86c000}, {0x3e86e000},
+ {0x3e870000}, {0x3e872000}, {0x3e874000}, {0x3e876000},
+ {0x3e878000}, {0x3e87a000}, {0x3e87c000}, {0x3e87e000},
+ {0x3e880000}, {0x3e882000}, {0x3e884000}, {0x3e886000},
+ {0x3e888000}, {0x3e88a000}, {0x3e88c000}, {0x3e88e000},
+ {0x3e890000}, {0x3e892000}, {0x3e894000}, {0x3e896000},
+ {0x3e898000}, {0x3e89a000}, {0x3e89c000}, {0x3e89e000},
+ {0x3e8a0000}, {0x3e8a2000}, {0x3e8a4000}, {0x3e8a6000},
+ {0x3e8a8000}, {0x3e8aa000}, {0x3e8ac000}, {0x3e8ae000},
+ {0x3e8b0000}, {0x3e8b2000}, {0x3e8b4000}, {0x3e8b6000},
+ {0x3e8b8000}, {0x3e8ba000}, {0x3e8bc000}, {0x3e8be000},
+ {0x3e8c0000}, {0x3e8c2000}, {0x3e8c4000}, {0x3e8c6000},
+ {0x3e8c8000}, {0x3e8ca000}, {0x3e8cc000}, {0x3e8ce000},
+ {0x3e8d0000}, {0x3e8d2000}, {0x3e8d4000}, {0x3e8d6000},
+ {0x3e8d8000}, {0x3e8da000}, {0x3e8dc000}, {0x3e8de000},
+ {0x3e8e0000}, {0x3e8e2000}, {0x3e8e4000}, {0x3e8e6000},
+ {0x3e8e8000}, {0x3e8ea000}, {0x3e8ec000}, {0x3e8ee000},
+ {0x3e8f0000}, {0x3e8f2000}, {0x3e8f4000}, {0x3e8f6000},
+ {0x3e8f8000}, {0x3e8fa000}, {0x3e8fc000}, {0x3e8fe000},
+ {0x3e900000}, {0x3e902000}, {0x3e904000}, {0x3e906000},
+ {0x3e908000}, {0x3e90a000}, {0x3e90c000}, {0x3e90e000},
+ {0x3e910000}, {0x3e912000}, {0x3e914000}, {0x3e916000},
+ {0x3e918000}, {0x3e91a000}, {0x3e91c000}, {0x3e91e000},
+ {0x3e920000}, {0x3e922000}, {0x3e924000}, {0x3e926000},
+ {0x3e928000}, {0x3e92a000}, {0x3e92c000}, {0x3e92e000},
+ {0x3e930000}, {0x3e932000}, {0x3e934000}, {0x3e936000},
+ {0x3e938000}, {0x3e93a000}, {0x3e93c000}, {0x3e93e000},
+ {0x3e940000}, {0x3e942000}, {0x3e944000}, {0x3e946000},
+ {0x3e948000}, {0x3e94a000}, {0x3e94c000}, {0x3e94e000},
+ {0x3e950000}, {0x3e952000}, {0x3e954000}, {0x3e956000},
+ {0x3e958000}, {0x3e95a000}, {0x3e95c000}, {0x3e95e000},
+ {0x3e960000}, {0x3e962000}, {0x3e964000}, {0x3e966000},
+ {0x3e968000}, {0x3e96a000}, {0x3e96c000}, {0x3e96e000},
+ {0x3e970000}, {0x3e972000}, {0x3e974000}, {0x3e976000},
+ {0x3e978000}, {0x3e97a000}, {0x3e97c000}, {0x3e97e000},
+ {0x3e980000}, {0x3e982000}, {0x3e984000}, {0x3e986000},
+ {0x3e988000}, {0x3e98a000}, {0x3e98c000}, {0x3e98e000},
+ {0x3e990000}, {0x3e992000}, {0x3e994000}, {0x3e996000},
+ {0x3e998000}, {0x3e99a000}, {0x3e99c000}, {0x3e99e000},
+ {0x3e9a0000}, {0x3e9a2000}, {0x3e9a4000}, {0x3e9a6000},
+ {0x3e9a8000}, {0x3e9aa000}, {0x3e9ac000}, {0x3e9ae000},
+ {0x3e9b0000}, {0x3e9b2000}, {0x3e9b4000}, {0x3e9b6000},
+ {0x3e9b8000}, {0x3e9ba000}, {0x3e9bc000}, {0x3e9be000},
+ {0x3e9c0000}, {0x3e9c2000}, {0x3e9c4000}, {0x3e9c6000},
+ {0x3e9c8000}, {0x3e9ca000}, {0x3e9cc000}, {0x3e9ce000},
+ {0x3e9d0000}, {0x3e9d2000}, {0x3e9d4000}, {0x3e9d6000},
+ {0x3e9d8000}, {0x3e9da000}, {0x3e9dc000}, {0x3e9de000},
+ {0x3e9e0000}, {0x3e9e2000}, {0x3e9e4000}, {0x3e9e6000},
+ {0x3e9e8000}, {0x3e9ea000}, {0x3e9ec000}, {0x3e9ee000},
+ {0x3e9f0000}, {0x3e9f2000}, {0x3e9f4000}, {0x3e9f6000},
+ {0x3e9f8000}, {0x3e9fa000}, {0x3e9fc000}, {0x3e9fe000},
+ {0x3ea00000}, {0x3ea02000}, {0x3ea04000}, {0x3ea06000},
+ {0x3ea08000}, {0x3ea0a000}, {0x3ea0c000}, {0x3ea0e000},
+ {0x3ea10000}, {0x3ea12000}, {0x3ea14000}, {0x3ea16000},
+ {0x3ea18000}, {0x3ea1a000}, {0x3ea1c000}, {0x3ea1e000},
+ {0x3ea20000}, {0x3ea22000}, {0x3ea24000}, {0x3ea26000},
+ {0x3ea28000}, {0x3ea2a000}, {0x3ea2c000}, {0x3ea2e000},
+ {0x3ea30000}, {0x3ea32000}, {0x3ea34000}, {0x3ea36000},
+ {0x3ea38000}, {0x3ea3a000}, {0x3ea3c000}, {0x3ea3e000},
+ {0x3ea40000}, {0x3ea42000}, {0x3ea44000}, {0x3ea46000},
+ {0x3ea48000}, {0x3ea4a000}, {0x3ea4c000}, {0x3ea4e000},
+ {0x3ea50000}, {0x3ea52000}, {0x3ea54000}, {0x3ea56000},
+ {0x3ea58000}, {0x3ea5a000}, {0x3ea5c000}, {0x3ea5e000},
+ {0x3ea60000}, {0x3ea62000}, {0x3ea64000}, {0x3ea66000},
+ {0x3ea68000}, {0x3ea6a000}, {0x3ea6c000}, {0x3ea6e000},
+ {0x3ea70000}, {0x3ea72000}, {0x3ea74000}, {0x3ea76000},
+ {0x3ea78000}, {0x3ea7a000}, {0x3ea7c000}, {0x3ea7e000},
+ {0x3ea80000}, {0x3ea82000}, {0x3ea84000}, {0x3ea86000},
+ {0x3ea88000}, {0x3ea8a000}, {0x3ea8c000}, {0x3ea8e000},
+ {0x3ea90000}, {0x3ea92000}, {0x3ea94000}, {0x3ea96000},
+ {0x3ea98000}, {0x3ea9a000}, {0x3ea9c000}, {0x3ea9e000},
+ {0x3eaa0000}, {0x3eaa2000}, {0x3eaa4000}, {0x3eaa6000},
+ {0x3eaa8000}, {0x3eaaa000}, {0x3eaac000}, {0x3eaae000},
+ {0x3eab0000}, {0x3eab2000}, {0x3eab4000}, {0x3eab6000},
+ {0x3eab8000}, {0x3eaba000}, {0x3eabc000}, {0x3eabe000},
+ {0x3eac0000}, {0x3eac2000}, {0x3eac4000}, {0x3eac6000},
+ {0x3eac8000}, {0x3eaca000}, {0x3eacc000}, {0x3eace000},
+ {0x3ead0000}, {0x3ead2000}, {0x3ead4000}, {0x3ead6000},
+ {0x3ead8000}, {0x3eada000}, {0x3eadc000}, {0x3eade000},
+ {0x3eae0000}, {0x3eae2000}, {0x3eae4000}, {0x3eae6000},
+ {0x3eae8000}, {0x3eaea000}, {0x3eaec000}, {0x3eaee000},
+ {0x3eaf0000}, {0x3eaf2000}, {0x3eaf4000}, {0x3eaf6000},
+ {0x3eaf8000}, {0x3eafa000}, {0x3eafc000}, {0x3eafe000},
+ {0x3eb00000}, {0x3eb02000}, {0x3eb04000}, {0x3eb06000},
+ {0x3eb08000}, {0x3eb0a000}, {0x3eb0c000}, {0x3eb0e000},
+ {0x3eb10000}, {0x3eb12000}, {0x3eb14000}, {0x3eb16000},
+ {0x3eb18000}, {0x3eb1a000}, {0x3eb1c000}, {0x3eb1e000},
+ {0x3eb20000}, {0x3eb22000}, {0x3eb24000}, {0x3eb26000},
+ {0x3eb28000}, {0x3eb2a000}, {0x3eb2c000}, {0x3eb2e000},
+ {0x3eb30000}, {0x3eb32000}, {0x3eb34000}, {0x3eb36000},
+ {0x3eb38000}, {0x3eb3a000}, {0x3eb3c000}, {0x3eb3e000},
+ {0x3eb40000}, {0x3eb42000}, {0x3eb44000}, {0x3eb46000},
+ {0x3eb48000}, {0x3eb4a000}, {0x3eb4c000}, {0x3eb4e000},
+ {0x3eb50000}, {0x3eb52000}, {0x3eb54000}, {0x3eb56000},
+ {0x3eb58000}, {0x3eb5a000}, {0x3eb5c000}, {0x3eb5e000},
+ {0x3eb60000}, {0x3eb62000}, {0x3eb64000}, {0x3eb66000},
+ {0x3eb68000}, {0x3eb6a000}, {0x3eb6c000}, {0x3eb6e000},
+ {0x3eb70000}, {0x3eb72000}, {0x3eb74000}, {0x3eb76000},
+ {0x3eb78000}, {0x3eb7a000}, {0x3eb7c000}, {0x3eb7e000},
+ {0x3eb80000}, {0x3eb82000}, {0x3eb84000}, {0x3eb86000},
+ {0x3eb88000}, {0x3eb8a000}, {0x3eb8c000}, {0x3eb8e000},
+ {0x3eb90000}, {0x3eb92000}, {0x3eb94000}, {0x3eb96000},
+ {0x3eb98000}, {0x3eb9a000}, {0x3eb9c000}, {0x3eb9e000},
+ {0x3eba0000}, {0x3eba2000}, {0x3eba4000}, {0x3eba6000},
+ {0x3eba8000}, {0x3ebaa000}, {0x3ebac000}, {0x3ebae000},
+ {0x3ebb0000}, {0x3ebb2000}, {0x3ebb4000}, {0x3ebb6000},
+ {0x3ebb8000}, {0x3ebba000}, {0x3ebbc000}, {0x3ebbe000},
+ {0x3ebc0000}, {0x3ebc2000}, {0x3ebc4000}, {0x3ebc6000},
+ {0x3ebc8000}, {0x3ebca000}, {0x3ebcc000}, {0x3ebce000},
+ {0x3ebd0000}, {0x3ebd2000}, {0x3ebd4000}, {0x3ebd6000},
+ {0x3ebd8000}, {0x3ebda000}, {0x3ebdc000}, {0x3ebde000},
+ {0x3ebe0000}, {0x3ebe2000}, {0x3ebe4000}, {0x3ebe6000},
+ {0x3ebe8000}, {0x3ebea000}, {0x3ebec000}, {0x3ebee000},
+ {0x3ebf0000}, {0x3ebf2000}, {0x3ebf4000}, {0x3ebf6000},
+ {0x3ebf8000}, {0x3ebfa000}, {0x3ebfc000}, {0x3ebfe000},
+ {0x3ec00000}, {0x3ec02000}, {0x3ec04000}, {0x3ec06000},
+ {0x3ec08000}, {0x3ec0a000}, {0x3ec0c000}, {0x3ec0e000},
+ {0x3ec10000}, {0x3ec12000}, {0x3ec14000}, {0x3ec16000},
+ {0x3ec18000}, {0x3ec1a000}, {0x3ec1c000}, {0x3ec1e000},
+ {0x3ec20000}, {0x3ec22000}, {0x3ec24000}, {0x3ec26000},
+ {0x3ec28000}, {0x3ec2a000}, {0x3ec2c000}, {0x3ec2e000},
+ {0x3ec30000}, {0x3ec32000}, {0x3ec34000}, {0x3ec36000},
+ {0x3ec38000}, {0x3ec3a000}, {0x3ec3c000}, {0x3ec3e000},
+ {0x3ec40000}, {0x3ec42000}, {0x3ec44000}, {0x3ec46000},
+ {0x3ec48000}, {0x3ec4a000}, {0x3ec4c000}, {0x3ec4e000},
+ {0x3ec50000}, {0x3ec52000}, {0x3ec54000}, {0x3ec56000},
+ {0x3ec58000}, {0x3ec5a000}, {0x3ec5c000}, {0x3ec5e000},
+ {0x3ec60000}, {0x3ec62000}, {0x3ec64000}, {0x3ec66000},
+ {0x3ec68000}, {0x3ec6a000}, {0x3ec6c000}, {0x3ec6e000},
+ {0x3ec70000}, {0x3ec72000}, {0x3ec74000}, {0x3ec76000},
+ {0x3ec78000}, {0x3ec7a000}, {0x3ec7c000}, {0x3ec7e000},
+ {0x3ec80000}, {0x3ec82000}, {0x3ec84000}, {0x3ec86000},
+ {0x3ec88000}, {0x3ec8a000}, {0x3ec8c000}, {0x3ec8e000},
+ {0x3ec90000}, {0x3ec92000}, {0x3ec94000}, {0x3ec96000},
+ {0x3ec98000}, {0x3ec9a000}, {0x3ec9c000}, {0x3ec9e000},
+ {0x3eca0000}, {0x3eca2000}, {0x3eca4000}, {0x3eca6000},
+ {0x3eca8000}, {0x3ecaa000}, {0x3ecac000}, {0x3ecae000},
+ {0x3ecb0000}, {0x3ecb2000}, {0x3ecb4000}, {0x3ecb6000},
+ {0x3ecb8000}, {0x3ecba000}, {0x3ecbc000}, {0x3ecbe000},
+ {0x3ecc0000}, {0x3ecc2000}, {0x3ecc4000}, {0x3ecc6000},
+ {0x3ecc8000}, {0x3ecca000}, {0x3eccc000}, {0x3ecce000},
+ {0x3ecd0000}, {0x3ecd2000}, {0x3ecd4000}, {0x3ecd6000},
+ {0x3ecd8000}, {0x3ecda000}, {0x3ecdc000}, {0x3ecde000},
+ {0x3ece0000}, {0x3ece2000}, {0x3ece4000}, {0x3ece6000},
+ {0x3ece8000}, {0x3ecea000}, {0x3ecec000}, {0x3ecee000},
+ {0x3ecf0000}, {0x3ecf2000}, {0x3ecf4000}, {0x3ecf6000},
+ {0x3ecf8000}, {0x3ecfa000}, {0x3ecfc000}, {0x3ecfe000},
+ {0x3ed00000}, {0x3ed02000}, {0x3ed04000}, {0x3ed06000},
+ {0x3ed08000}, {0x3ed0a000}, {0x3ed0c000}, {0x3ed0e000},
+ {0x3ed10000}, {0x3ed12000}, {0x3ed14000}, {0x3ed16000},
+ {0x3ed18000}, {0x3ed1a000}, {0x3ed1c000}, {0x3ed1e000},
+ {0x3ed20000}, {0x3ed22000}, {0x3ed24000}, {0x3ed26000},
+ {0x3ed28000}, {0x3ed2a000}, {0x3ed2c000}, {0x3ed2e000},
+ {0x3ed30000}, {0x3ed32000}, {0x3ed34000}, {0x3ed36000},
+ {0x3ed38000}, {0x3ed3a000}, {0x3ed3c000}, {0x3ed3e000},
+ {0x3ed40000}, {0x3ed42000}, {0x3ed44000}, {0x3ed46000},
+ {0x3ed48000}, {0x3ed4a000}, {0x3ed4c000}, {0x3ed4e000},
+ {0x3ed50000}, {0x3ed52000}, {0x3ed54000}, {0x3ed56000},
+ {0x3ed58000}, {0x3ed5a000}, {0x3ed5c000}, {0x3ed5e000},
+ {0x3ed60000}, {0x3ed62000}, {0x3ed64000}, {0x3ed66000},
+ {0x3ed68000}, {0x3ed6a000}, {0x3ed6c000}, {0x3ed6e000},
+ {0x3ed70000}, {0x3ed72000}, {0x3ed74000}, {0x3ed76000},
+ {0x3ed78000}, {0x3ed7a000}, {0x3ed7c000}, {0x3ed7e000},
+ {0x3ed80000}, {0x3ed82000}, {0x3ed84000}, {0x3ed86000},
+ {0x3ed88000}, {0x3ed8a000}, {0x3ed8c000}, {0x3ed8e000},
+ {0x3ed90000}, {0x3ed92000}, {0x3ed94000}, {0x3ed96000},
+ {0x3ed98000}, {0x3ed9a000}, {0x3ed9c000}, {0x3ed9e000},
+ {0x3eda0000}, {0x3eda2000}, {0x3eda4000}, {0x3eda6000},
+ {0x3eda8000}, {0x3edaa000}, {0x3edac000}, {0x3edae000},
+ {0x3edb0000}, {0x3edb2000}, {0x3edb4000}, {0x3edb6000},
+ {0x3edb8000}, {0x3edba000}, {0x3edbc000}, {0x3edbe000},
+ {0x3edc0000}, {0x3edc2000}, {0x3edc4000}, {0x3edc6000},
+ {0x3edc8000}, {0x3edca000}, {0x3edcc000}, {0x3edce000},
+ {0x3edd0000}, {0x3edd2000}, {0x3edd4000}, {0x3edd6000},
+ {0x3edd8000}, {0x3edda000}, {0x3eddc000}, {0x3edde000},
+ {0x3ede0000}, {0x3ede2000}, {0x3ede4000}, {0x3ede6000},
+ {0x3ede8000}, {0x3edea000}, {0x3edec000}, {0x3edee000},
+ {0x3edf0000}, {0x3edf2000}, {0x3edf4000}, {0x3edf6000},
+ {0x3edf8000}, {0x3edfa000}, {0x3edfc000}, {0x3edfe000},
+ {0x3ee00000}, {0x3ee02000}, {0x3ee04000}, {0x3ee06000},
+ {0x3ee08000}, {0x3ee0a000}, {0x3ee0c000}, {0x3ee0e000},
+ {0x3ee10000}, {0x3ee12000}, {0x3ee14000}, {0x3ee16000},
+ {0x3ee18000}, {0x3ee1a000}, {0x3ee1c000}, {0x3ee1e000},
+ {0x3ee20000}, {0x3ee22000}, {0x3ee24000}, {0x3ee26000},
+ {0x3ee28000}, {0x3ee2a000}, {0x3ee2c000}, {0x3ee2e000},
+ {0x3ee30000}, {0x3ee32000}, {0x3ee34000}, {0x3ee36000},
+ {0x3ee38000}, {0x3ee3a000}, {0x3ee3c000}, {0x3ee3e000},
+ {0x3ee40000}, {0x3ee42000}, {0x3ee44000}, {0x3ee46000},
+ {0x3ee48000}, {0x3ee4a000}, {0x3ee4c000}, {0x3ee4e000},
+ {0x3ee50000}, {0x3ee52000}, {0x3ee54000}, {0x3ee56000},
+ {0x3ee58000}, {0x3ee5a000}, {0x3ee5c000}, {0x3ee5e000},
+ {0x3ee60000}, {0x3ee62000}, {0x3ee64000}, {0x3ee66000},
+ {0x3ee68000}, {0x3ee6a000}, {0x3ee6c000}, {0x3ee6e000},
+ {0x3ee70000}, {0x3ee72000}, {0x3ee74000}, {0x3ee76000},
+ {0x3ee78000}, {0x3ee7a000}, {0x3ee7c000}, {0x3ee7e000},
+ {0x3ee80000}, {0x3ee82000}, {0x3ee84000}, {0x3ee86000},
+ {0x3ee88000}, {0x3ee8a000}, {0x3ee8c000}, {0x3ee8e000},
+ {0x3ee90000}, {0x3ee92000}, {0x3ee94000}, {0x3ee96000},
+ {0x3ee98000}, {0x3ee9a000}, {0x3ee9c000}, {0x3ee9e000},
+ {0x3eea0000}, {0x3eea2000}, {0x3eea4000}, {0x3eea6000},
+ {0x3eea8000}, {0x3eeaa000}, {0x3eeac000}, {0x3eeae000},
+ {0x3eeb0000}, {0x3eeb2000}, {0x3eeb4000}, {0x3eeb6000},
+ {0x3eeb8000}, {0x3eeba000}, {0x3eebc000}, {0x3eebe000},
+ {0x3eec0000}, {0x3eec2000}, {0x3eec4000}, {0x3eec6000},
+ {0x3eec8000}, {0x3eeca000}, {0x3eecc000}, {0x3eece000},
+ {0x3eed0000}, {0x3eed2000}, {0x3eed4000}, {0x3eed6000},
+ {0x3eed8000}, {0x3eeda000}, {0x3eedc000}, {0x3eede000},
+ {0x3eee0000}, {0x3eee2000}, {0x3eee4000}, {0x3eee6000},
+ {0x3eee8000}, {0x3eeea000}, {0x3eeec000}, {0x3eeee000},
+ {0x3eef0000}, {0x3eef2000}, {0x3eef4000}, {0x3eef6000},
+ {0x3eef8000}, {0x3eefa000}, {0x3eefc000}, {0x3eefe000},
+ {0x3ef00000}, {0x3ef02000}, {0x3ef04000}, {0x3ef06000},
+ {0x3ef08000}, {0x3ef0a000}, {0x3ef0c000}, {0x3ef0e000},
+ {0x3ef10000}, {0x3ef12000}, {0x3ef14000}, {0x3ef16000},
+ {0x3ef18000}, {0x3ef1a000}, {0x3ef1c000}, {0x3ef1e000},
+ {0x3ef20000}, {0x3ef22000}, {0x3ef24000}, {0x3ef26000},
+ {0x3ef28000}, {0x3ef2a000}, {0x3ef2c000}, {0x3ef2e000},
+ {0x3ef30000}, {0x3ef32000}, {0x3ef34000}, {0x3ef36000},
+ {0x3ef38000}, {0x3ef3a000}, {0x3ef3c000}, {0x3ef3e000},
+ {0x3ef40000}, {0x3ef42000}, {0x3ef44000}, {0x3ef46000},
+ {0x3ef48000}, {0x3ef4a000}, {0x3ef4c000}, {0x3ef4e000},
+ {0x3ef50000}, {0x3ef52000}, {0x3ef54000}, {0x3ef56000},
+ {0x3ef58000}, {0x3ef5a000}, {0x3ef5c000}, {0x3ef5e000},
+ {0x3ef60000}, {0x3ef62000}, {0x3ef64000}, {0x3ef66000},
+ {0x3ef68000}, {0x3ef6a000}, {0x3ef6c000}, {0x3ef6e000},
+ {0x3ef70000}, {0x3ef72000}, {0x3ef74000}, {0x3ef76000},
+ {0x3ef78000}, {0x3ef7a000}, {0x3ef7c000}, {0x3ef7e000},
+ {0x3ef80000}, {0x3ef82000}, {0x3ef84000}, {0x3ef86000},
+ {0x3ef88000}, {0x3ef8a000}, {0x3ef8c000}, {0x3ef8e000},
+ {0x3ef90000}, {0x3ef92000}, {0x3ef94000}, {0x3ef96000},
+ {0x3ef98000}, {0x3ef9a000}, {0x3ef9c000}, {0x3ef9e000},
+ {0x3efa0000}, {0x3efa2000}, {0x3efa4000}, {0x3efa6000},
+ {0x3efa8000}, {0x3efaa000}, {0x3efac000}, {0x3efae000},
+ {0x3efb0000}, {0x3efb2000}, {0x3efb4000}, {0x3efb6000},
+ {0x3efb8000}, {0x3efba000}, {0x3efbc000}, {0x3efbe000},
+ {0x3efc0000}, {0x3efc2000}, {0x3efc4000}, {0x3efc6000},
+ {0x3efc8000}, {0x3efca000}, {0x3efcc000}, {0x3efce000},
+ {0x3efd0000}, {0x3efd2000}, {0x3efd4000}, {0x3efd6000},
+ {0x3efd8000}, {0x3efda000}, {0x3efdc000}, {0x3efde000},
+ {0x3efe0000}, {0x3efe2000}, {0x3efe4000}, {0x3efe6000},
+ {0x3efe8000}, {0x3efea000}, {0x3efec000}, {0x3efee000},
+ {0x3eff0000}, {0x3eff2000}, {0x3eff4000}, {0x3eff6000},
+ {0x3eff8000}, {0x3effa000}, {0x3effc000}, {0x3effe000},
+ {0x3f000000}, {0x3f002000}, {0x3f004000}, {0x3f006000},
+ {0x3f008000}, {0x3f00a000}, {0x3f00c000}, {0x3f00e000},
+ {0x3f010000}, {0x3f012000}, {0x3f014000}, {0x3f016000},
+ {0x3f018000}, {0x3f01a000}, {0x3f01c000}, {0x3f01e000},
+ {0x3f020000}, {0x3f022000}, {0x3f024000}, {0x3f026000},
+ {0x3f028000}, {0x3f02a000}, {0x3f02c000}, {0x3f02e000},
+ {0x3f030000}, {0x3f032000}, {0x3f034000}, {0x3f036000},
+ {0x3f038000}, {0x3f03a000}, {0x3f03c000}, {0x3f03e000},
+ {0x3f040000}, {0x3f042000}, {0x3f044000}, {0x3f046000},
+ {0x3f048000}, {0x3f04a000}, {0x3f04c000}, {0x3f04e000},
+ {0x3f050000}, {0x3f052000}, {0x3f054000}, {0x3f056000},
+ {0x3f058000}, {0x3f05a000}, {0x3f05c000}, {0x3f05e000},
+ {0x3f060000}, {0x3f062000}, {0x3f064000}, {0x3f066000},
+ {0x3f068000}, {0x3f06a000}, {0x3f06c000}, {0x3f06e000},
+ {0x3f070000}, {0x3f072000}, {0x3f074000}, {0x3f076000},
+ {0x3f078000}, {0x3f07a000}, {0x3f07c000}, {0x3f07e000},
+ {0x3f080000}, {0x3f082000}, {0x3f084000}, {0x3f086000},
+ {0x3f088000}, {0x3f08a000}, {0x3f08c000}, {0x3f08e000},
+ {0x3f090000}, {0x3f092000}, {0x3f094000}, {0x3f096000},
+ {0x3f098000}, {0x3f09a000}, {0x3f09c000}, {0x3f09e000},
+ {0x3f0a0000}, {0x3f0a2000}, {0x3f0a4000}, {0x3f0a6000},
+ {0x3f0a8000}, {0x3f0aa000}, {0x3f0ac000}, {0x3f0ae000},
+ {0x3f0b0000}, {0x3f0b2000}, {0x3f0b4000}, {0x3f0b6000},
+ {0x3f0b8000}, {0x3f0ba000}, {0x3f0bc000}, {0x3f0be000},
+ {0x3f0c0000}, {0x3f0c2000}, {0x3f0c4000}, {0x3f0c6000},
+ {0x3f0c8000}, {0x3f0ca000}, {0x3f0cc000}, {0x3f0ce000},
+ {0x3f0d0000}, {0x3f0d2000}, {0x3f0d4000}, {0x3f0d6000},
+ {0x3f0d8000}, {0x3f0da000}, {0x3f0dc000}, {0x3f0de000},
+ {0x3f0e0000}, {0x3f0e2000}, {0x3f0e4000}, {0x3f0e6000},
+ {0x3f0e8000}, {0x3f0ea000}, {0x3f0ec000}, {0x3f0ee000},
+ {0x3f0f0000}, {0x3f0f2000}, {0x3f0f4000}, {0x3f0f6000},
+ {0x3f0f8000}, {0x3f0fa000}, {0x3f0fc000}, {0x3f0fe000},
+ {0x3f100000}, {0x3f102000}, {0x3f104000}, {0x3f106000},
+ {0x3f108000}, {0x3f10a000}, {0x3f10c000}, {0x3f10e000},
+ {0x3f110000}, {0x3f112000}, {0x3f114000}, {0x3f116000},
+ {0x3f118000}, {0x3f11a000}, {0x3f11c000}, {0x3f11e000},
+ {0x3f120000}, {0x3f122000}, {0x3f124000}, {0x3f126000},
+ {0x3f128000}, {0x3f12a000}, {0x3f12c000}, {0x3f12e000},
+ {0x3f130000}, {0x3f132000}, {0x3f134000}, {0x3f136000},
+ {0x3f138000}, {0x3f13a000}, {0x3f13c000}, {0x3f13e000},
+ {0x3f140000}, {0x3f142000}, {0x3f144000}, {0x3f146000},
+ {0x3f148000}, {0x3f14a000}, {0x3f14c000}, {0x3f14e000},
+ {0x3f150000}, {0x3f152000}, {0x3f154000}, {0x3f156000},
+ {0x3f158000}, {0x3f15a000}, {0x3f15c000}, {0x3f15e000},
+ {0x3f160000}, {0x3f162000}, {0x3f164000}, {0x3f166000},
+ {0x3f168000}, {0x3f16a000}, {0x3f16c000}, {0x3f16e000},
+ {0x3f170000}, {0x3f172000}, {0x3f174000}, {0x3f176000},
+ {0x3f178000}, {0x3f17a000}, {0x3f17c000}, {0x3f17e000},
+ {0x3f180000}, {0x3f182000}, {0x3f184000}, {0x3f186000},
+ {0x3f188000}, {0x3f18a000}, {0x3f18c000}, {0x3f18e000},
+ {0x3f190000}, {0x3f192000}, {0x3f194000}, {0x3f196000},
+ {0x3f198000}, {0x3f19a000}, {0x3f19c000}, {0x3f19e000},
+ {0x3f1a0000}, {0x3f1a2000}, {0x3f1a4000}, {0x3f1a6000},
+ {0x3f1a8000}, {0x3f1aa000}, {0x3f1ac000}, {0x3f1ae000},
+ {0x3f1b0000}, {0x3f1b2000}, {0x3f1b4000}, {0x3f1b6000},
+ {0x3f1b8000}, {0x3f1ba000}, {0x3f1bc000}, {0x3f1be000},
+ {0x3f1c0000}, {0x3f1c2000}, {0x3f1c4000}, {0x3f1c6000},
+ {0x3f1c8000}, {0x3f1ca000}, {0x3f1cc000}, {0x3f1ce000},
+ {0x3f1d0000}, {0x3f1d2000}, {0x3f1d4000}, {0x3f1d6000},
+ {0x3f1d8000}, {0x3f1da000}, {0x3f1dc000}, {0x3f1de000},
+ {0x3f1e0000}, {0x3f1e2000}, {0x3f1e4000}, {0x3f1e6000},
+ {0x3f1e8000}, {0x3f1ea000}, {0x3f1ec000}, {0x3f1ee000},
+ {0x3f1f0000}, {0x3f1f2000}, {0x3f1f4000}, {0x3f1f6000},
+ {0x3f1f8000}, {0x3f1fa000}, {0x3f1fc000}, {0x3f1fe000},
+ {0x3f200000}, {0x3f202000}, {0x3f204000}, {0x3f206000},
+ {0x3f208000}, {0x3f20a000}, {0x3f20c000}, {0x3f20e000},
+ {0x3f210000}, {0x3f212000}, {0x3f214000}, {0x3f216000},
+ {0x3f218000}, {0x3f21a000}, {0x3f21c000}, {0x3f21e000},
+ {0x3f220000}, {0x3f222000}, {0x3f224000}, {0x3f226000},
+ {0x3f228000}, {0x3f22a000}, {0x3f22c000}, {0x3f22e000},
+ {0x3f230000}, {0x3f232000}, {0x3f234000}, {0x3f236000},
+ {0x3f238000}, {0x3f23a000}, {0x3f23c000}, {0x3f23e000},
+ {0x3f240000}, {0x3f242000}, {0x3f244000}, {0x3f246000},
+ {0x3f248000}, {0x3f24a000}, {0x3f24c000}, {0x3f24e000},
+ {0x3f250000}, {0x3f252000}, {0x3f254000}, {0x3f256000},
+ {0x3f258000}, {0x3f25a000}, {0x3f25c000}, {0x3f25e000},
+ {0x3f260000}, {0x3f262000}, {0x3f264000}, {0x3f266000},
+ {0x3f268000}, {0x3f26a000}, {0x3f26c000}, {0x3f26e000},
+ {0x3f270000}, {0x3f272000}, {0x3f274000}, {0x3f276000},
+ {0x3f278000}, {0x3f27a000}, {0x3f27c000}, {0x3f27e000},
+ {0x3f280000}, {0x3f282000}, {0x3f284000}, {0x3f286000},
+ {0x3f288000}, {0x3f28a000}, {0x3f28c000}, {0x3f28e000},
+ {0x3f290000}, {0x3f292000}, {0x3f294000}, {0x3f296000},
+ {0x3f298000}, {0x3f29a000}, {0x3f29c000}, {0x3f29e000},
+ {0x3f2a0000}, {0x3f2a2000}, {0x3f2a4000}, {0x3f2a6000},
+ {0x3f2a8000}, {0x3f2aa000}, {0x3f2ac000}, {0x3f2ae000},
+ {0x3f2b0000}, {0x3f2b2000}, {0x3f2b4000}, {0x3f2b6000},
+ {0x3f2b8000}, {0x3f2ba000}, {0x3f2bc000}, {0x3f2be000},
+ {0x3f2c0000}, {0x3f2c2000}, {0x3f2c4000}, {0x3f2c6000},
+ {0x3f2c8000}, {0x3f2ca000}, {0x3f2cc000}, {0x3f2ce000},
+ {0x3f2d0000}, {0x3f2d2000}, {0x3f2d4000}, {0x3f2d6000},
+ {0x3f2d8000}, {0x3f2da000}, {0x3f2dc000}, {0x3f2de000},
+ {0x3f2e0000}, {0x3f2e2000}, {0x3f2e4000}, {0x3f2e6000},
+ {0x3f2e8000}, {0x3f2ea000}, {0x3f2ec000}, {0x3f2ee000},
+ {0x3f2f0000}, {0x3f2f2000}, {0x3f2f4000}, {0x3f2f6000},
+ {0x3f2f8000}, {0x3f2fa000}, {0x3f2fc000}, {0x3f2fe000},
+ {0x3f300000}, {0x3f302000}, {0x3f304000}, {0x3f306000},
+ {0x3f308000}, {0x3f30a000}, {0x3f30c000}, {0x3f30e000},
+ {0x3f310000}, {0x3f312000}, {0x3f314000}, {0x3f316000},
+ {0x3f318000}, {0x3f31a000}, {0x3f31c000}, {0x3f31e000},
+ {0x3f320000}, {0x3f322000}, {0x3f324000}, {0x3f326000},
+ {0x3f328000}, {0x3f32a000}, {0x3f32c000}, {0x3f32e000},
+ {0x3f330000}, {0x3f332000}, {0x3f334000}, {0x3f336000},
+ {0x3f338000}, {0x3f33a000}, {0x3f33c000}, {0x3f33e000},
+ {0x3f340000}, {0x3f342000}, {0x3f344000}, {0x3f346000},
+ {0x3f348000}, {0x3f34a000}, {0x3f34c000}, {0x3f34e000},
+ {0x3f350000}, {0x3f352000}, {0x3f354000}, {0x3f356000},
+ {0x3f358000}, {0x3f35a000}, {0x3f35c000}, {0x3f35e000},
+ {0x3f360000}, {0x3f362000}, {0x3f364000}, {0x3f366000},
+ {0x3f368000}, {0x3f36a000}, {0x3f36c000}, {0x3f36e000},
+ {0x3f370000}, {0x3f372000}, {0x3f374000}, {0x3f376000},
+ {0x3f378000}, {0x3f37a000}, {0x3f37c000}, {0x3f37e000},
+ {0x3f380000}, {0x3f382000}, {0x3f384000}, {0x3f386000},
+ {0x3f388000}, {0x3f38a000}, {0x3f38c000}, {0x3f38e000},
+ {0x3f390000}, {0x3f392000}, {0x3f394000}, {0x3f396000},
+ {0x3f398000}, {0x3f39a000}, {0x3f39c000}, {0x3f39e000},
+ {0x3f3a0000}, {0x3f3a2000}, {0x3f3a4000}, {0x3f3a6000},
+ {0x3f3a8000}, {0x3f3aa000}, {0x3f3ac000}, {0x3f3ae000},
+ {0x3f3b0000}, {0x3f3b2000}, {0x3f3b4000}, {0x3f3b6000},
+ {0x3f3b8000}, {0x3f3ba000}, {0x3f3bc000}, {0x3f3be000},
+ {0x3f3c0000}, {0x3f3c2000}, {0x3f3c4000}, {0x3f3c6000},
+ {0x3f3c8000}, {0x3f3ca000}, {0x3f3cc000}, {0x3f3ce000},
+ {0x3f3d0000}, {0x3f3d2000}, {0x3f3d4000}, {0x3f3d6000},
+ {0x3f3d8000}, {0x3f3da000}, {0x3f3dc000}, {0x3f3de000},
+ {0x3f3e0000}, {0x3f3e2000}, {0x3f3e4000}, {0x3f3e6000},
+ {0x3f3e8000}, {0x3f3ea000}, {0x3f3ec000}, {0x3f3ee000},
+ {0x3f3f0000}, {0x3f3f2000}, {0x3f3f4000}, {0x3f3f6000},
+ {0x3f3f8000}, {0x3f3fa000}, {0x3f3fc000}, {0x3f3fe000},
+ {0x3f400000}, {0x3f402000}, {0x3f404000}, {0x3f406000},
+ {0x3f408000}, {0x3f40a000}, {0x3f40c000}, {0x3f40e000},
+ {0x3f410000}, {0x3f412000}, {0x3f414000}, {0x3f416000},
+ {0x3f418000}, {0x3f41a000}, {0x3f41c000}, {0x3f41e000},
+ {0x3f420000}, {0x3f422000}, {0x3f424000}, {0x3f426000},
+ {0x3f428000}, {0x3f42a000}, {0x3f42c000}, {0x3f42e000},
+ {0x3f430000}, {0x3f432000}, {0x3f434000}, {0x3f436000},
+ {0x3f438000}, {0x3f43a000}, {0x3f43c000}, {0x3f43e000},
+ {0x3f440000}, {0x3f442000}, {0x3f444000}, {0x3f446000},
+ {0x3f448000}, {0x3f44a000}, {0x3f44c000}, {0x3f44e000},
+ {0x3f450000}, {0x3f452000}, {0x3f454000}, {0x3f456000},
+ {0x3f458000}, {0x3f45a000}, {0x3f45c000}, {0x3f45e000},
+ {0x3f460000}, {0x3f462000}, {0x3f464000}, {0x3f466000},
+ {0x3f468000}, {0x3f46a000}, {0x3f46c000}, {0x3f46e000},
+ {0x3f470000}, {0x3f472000}, {0x3f474000}, {0x3f476000},
+ {0x3f478000}, {0x3f47a000}, {0x3f47c000}, {0x3f47e000},
+ {0x3f480000}, {0x3f482000}, {0x3f484000}, {0x3f486000},
+ {0x3f488000}, {0x3f48a000}, {0x3f48c000}, {0x3f48e000},
+ {0x3f490000}, {0x3f492000}, {0x3f494000}, {0x3f496000},
+ {0x3f498000}, {0x3f49a000}, {0x3f49c000}, {0x3f49e000},
+ {0x3f4a0000}, {0x3f4a2000}, {0x3f4a4000}, {0x3f4a6000},
+ {0x3f4a8000}, {0x3f4aa000}, {0x3f4ac000}, {0x3f4ae000},
+ {0x3f4b0000}, {0x3f4b2000}, {0x3f4b4000}, {0x3f4b6000},
+ {0x3f4b8000}, {0x3f4ba000}, {0x3f4bc000}, {0x3f4be000},
+ {0x3f4c0000}, {0x3f4c2000}, {0x3f4c4000}, {0x3f4c6000},
+ {0x3f4c8000}, {0x3f4ca000}, {0x3f4cc000}, {0x3f4ce000},
+ {0x3f4d0000}, {0x3f4d2000}, {0x3f4d4000}, {0x3f4d6000},
+ {0x3f4d8000}, {0x3f4da000}, {0x3f4dc000}, {0x3f4de000},
+ {0x3f4e0000}, {0x3f4e2000}, {0x3f4e4000}, {0x3f4e6000},
+ {0x3f4e8000}, {0x3f4ea000}, {0x3f4ec000}, {0x3f4ee000},
+ {0x3f4f0000}, {0x3f4f2000}, {0x3f4f4000}, {0x3f4f6000},
+ {0x3f4f8000}, {0x3f4fa000}, {0x3f4fc000}, {0x3f4fe000},
+ {0x3f500000}, {0x3f502000}, {0x3f504000}, {0x3f506000},
+ {0x3f508000}, {0x3f50a000}, {0x3f50c000}, {0x3f50e000},
+ {0x3f510000}, {0x3f512000}, {0x3f514000}, {0x3f516000},
+ {0x3f518000}, {0x3f51a000}, {0x3f51c000}, {0x3f51e000},
+ {0x3f520000}, {0x3f522000}, {0x3f524000}, {0x3f526000},
+ {0x3f528000}, {0x3f52a000}, {0x3f52c000}, {0x3f52e000},
+ {0x3f530000}, {0x3f532000}, {0x3f534000}, {0x3f536000},
+ {0x3f538000}, {0x3f53a000}, {0x3f53c000}, {0x3f53e000},
+ {0x3f540000}, {0x3f542000}, {0x3f544000}, {0x3f546000},
+ {0x3f548000}, {0x3f54a000}, {0x3f54c000}, {0x3f54e000},
+ {0x3f550000}, {0x3f552000}, {0x3f554000}, {0x3f556000},
+ {0x3f558000}, {0x3f55a000}, {0x3f55c000}, {0x3f55e000},
+ {0x3f560000}, {0x3f562000}, {0x3f564000}, {0x3f566000},
+ {0x3f568000}, {0x3f56a000}, {0x3f56c000}, {0x3f56e000},
+ {0x3f570000}, {0x3f572000}, {0x3f574000}, {0x3f576000},
+ {0x3f578000}, {0x3f57a000}, {0x3f57c000}, {0x3f57e000},
+ {0x3f580000}, {0x3f582000}, {0x3f584000}, {0x3f586000},
+ {0x3f588000}, {0x3f58a000}, {0x3f58c000}, {0x3f58e000},
+ {0x3f590000}, {0x3f592000}, {0x3f594000}, {0x3f596000},
+ {0x3f598000}, {0x3f59a000}, {0x3f59c000}, {0x3f59e000},
+ {0x3f5a0000}, {0x3f5a2000}, {0x3f5a4000}, {0x3f5a6000},
+ {0x3f5a8000}, {0x3f5aa000}, {0x3f5ac000}, {0x3f5ae000},
+ {0x3f5b0000}, {0x3f5b2000}, {0x3f5b4000}, {0x3f5b6000},
+ {0x3f5b8000}, {0x3f5ba000}, {0x3f5bc000}, {0x3f5be000},
+ {0x3f5c0000}, {0x3f5c2000}, {0x3f5c4000}, {0x3f5c6000},
+ {0x3f5c8000}, {0x3f5ca000}, {0x3f5cc000}, {0x3f5ce000},
+ {0x3f5d0000}, {0x3f5d2000}, {0x3f5d4000}, {0x3f5d6000},
+ {0x3f5d8000}, {0x3f5da000}, {0x3f5dc000}, {0x3f5de000},
+ {0x3f5e0000}, {0x3f5e2000}, {0x3f5e4000}, {0x3f5e6000},
+ {0x3f5e8000}, {0x3f5ea000}, {0x3f5ec000}, {0x3f5ee000},
+ {0x3f5f0000}, {0x3f5f2000}, {0x3f5f4000}, {0x3f5f6000},
+ {0x3f5f8000}, {0x3f5fa000}, {0x3f5fc000}, {0x3f5fe000},
+ {0x3f600000}, {0x3f602000}, {0x3f604000}, {0x3f606000},
+ {0x3f608000}, {0x3f60a000}, {0x3f60c000}, {0x3f60e000},
+ {0x3f610000}, {0x3f612000}, {0x3f614000}, {0x3f616000},
+ {0x3f618000}, {0x3f61a000}, {0x3f61c000}, {0x3f61e000},
+ {0x3f620000}, {0x3f622000}, {0x3f624000}, {0x3f626000},
+ {0x3f628000}, {0x3f62a000}, {0x3f62c000}, {0x3f62e000},
+ {0x3f630000}, {0x3f632000}, {0x3f634000}, {0x3f636000},
+ {0x3f638000}, {0x3f63a000}, {0x3f63c000}, {0x3f63e000},
+ {0x3f640000}, {0x3f642000}, {0x3f644000}, {0x3f646000},
+ {0x3f648000}, {0x3f64a000}, {0x3f64c000}, {0x3f64e000},
+ {0x3f650000}, {0x3f652000}, {0x3f654000}, {0x3f656000},
+ {0x3f658000}, {0x3f65a000}, {0x3f65c000}, {0x3f65e000},
+ {0x3f660000}, {0x3f662000}, {0x3f664000}, {0x3f666000},
+ {0x3f668000}, {0x3f66a000}, {0x3f66c000}, {0x3f66e000},
+ {0x3f670000}, {0x3f672000}, {0x3f674000}, {0x3f676000},
+ {0x3f678000}, {0x3f67a000}, {0x3f67c000}, {0x3f67e000},
+ {0x3f680000}, {0x3f682000}, {0x3f684000}, {0x3f686000},
+ {0x3f688000}, {0x3f68a000}, {0x3f68c000}, {0x3f68e000},
+ {0x3f690000}, {0x3f692000}, {0x3f694000}, {0x3f696000},
+ {0x3f698000}, {0x3f69a000}, {0x3f69c000}, {0x3f69e000},
+ {0x3f6a0000}, {0x3f6a2000}, {0x3f6a4000}, {0x3f6a6000},
+ {0x3f6a8000}, {0x3f6aa000}, {0x3f6ac000}, {0x3f6ae000},
+ {0x3f6b0000}, {0x3f6b2000}, {0x3f6b4000}, {0x3f6b6000},
+ {0x3f6b8000}, {0x3f6ba000}, {0x3f6bc000}, {0x3f6be000},
+ {0x3f6c0000}, {0x3f6c2000}, {0x3f6c4000}, {0x3f6c6000},
+ {0x3f6c8000}, {0x3f6ca000}, {0x3f6cc000}, {0x3f6ce000},
+ {0x3f6d0000}, {0x3f6d2000}, {0x3f6d4000}, {0x3f6d6000},
+ {0x3f6d8000}, {0x3f6da000}, {0x3f6dc000}, {0x3f6de000},
+ {0x3f6e0000}, {0x3f6e2000}, {0x3f6e4000}, {0x3f6e6000},
+ {0x3f6e8000}, {0x3f6ea000}, {0x3f6ec000}, {0x3f6ee000},
+ {0x3f6f0000}, {0x3f6f2000}, {0x3f6f4000}, {0x3f6f6000},
+ {0x3f6f8000}, {0x3f6fa000}, {0x3f6fc000}, {0x3f6fe000},
+ {0x3f700000}, {0x3f702000}, {0x3f704000}, {0x3f706000},
+ {0x3f708000}, {0x3f70a000}, {0x3f70c000}, {0x3f70e000},
+ {0x3f710000}, {0x3f712000}, {0x3f714000}, {0x3f716000},
+ {0x3f718000}, {0x3f71a000}, {0x3f71c000}, {0x3f71e000},
+ {0x3f720000}, {0x3f722000}, {0x3f724000}, {0x3f726000},
+ {0x3f728000}, {0x3f72a000}, {0x3f72c000}, {0x3f72e000},
+ {0x3f730000}, {0x3f732000}, {0x3f734000}, {0x3f736000},
+ {0x3f738000}, {0x3f73a000}, {0x3f73c000}, {0x3f73e000},
+ {0x3f740000}, {0x3f742000}, {0x3f744000}, {0x3f746000},
+ {0x3f748000}, {0x3f74a000}, {0x3f74c000}, {0x3f74e000},
+ {0x3f750000}, {0x3f752000}, {0x3f754000}, {0x3f756000},
+ {0x3f758000}, {0x3f75a000}, {0x3f75c000}, {0x3f75e000},
+ {0x3f760000}, {0x3f762000}, {0x3f764000}, {0x3f766000},
+ {0x3f768000}, {0x3f76a000}, {0x3f76c000}, {0x3f76e000},
+ {0x3f770000}, {0x3f772000}, {0x3f774000}, {0x3f776000},
+ {0x3f778000}, {0x3f77a000}, {0x3f77c000}, {0x3f77e000},
+ {0x3f780000}, {0x3f782000}, {0x3f784000}, {0x3f786000},
+ {0x3f788000}, {0x3f78a000}, {0x3f78c000}, {0x3f78e000},
+ {0x3f790000}, {0x3f792000}, {0x3f794000}, {0x3f796000},
+ {0x3f798000}, {0x3f79a000}, {0x3f79c000}, {0x3f79e000},
+ {0x3f7a0000}, {0x3f7a2000}, {0x3f7a4000}, {0x3f7a6000},
+ {0x3f7a8000}, {0x3f7aa000}, {0x3f7ac000}, {0x3f7ae000},
+ {0x3f7b0000}, {0x3f7b2000}, {0x3f7b4000}, {0x3f7b6000},
+ {0x3f7b8000}, {0x3f7ba000}, {0x3f7bc000}, {0x3f7be000},
+ {0x3f7c0000}, {0x3f7c2000}, {0x3f7c4000}, {0x3f7c6000},
+ {0x3f7c8000}, {0x3f7ca000}, {0x3f7cc000}, {0x3f7ce000},
+ {0x3f7d0000}, {0x3f7d2000}, {0x3f7d4000}, {0x3f7d6000},
+ {0x3f7d8000}, {0x3f7da000}, {0x3f7dc000}, {0x3f7de000},
+ {0x3f7e0000}, {0x3f7e2000}, {0x3f7e4000}, {0x3f7e6000},
+ {0x3f7e8000}, {0x3f7ea000}, {0x3f7ec000}, {0x3f7ee000},
+ {0x3f7f0000}, {0x3f7f2000}, {0x3f7f4000}, {0x3f7f6000},
+ {0x3f7f8000}, {0x3f7fa000}, {0x3f7fc000}, {0x3f7fe000},
+ {0x3f800000}, {0x3f802000}, {0x3f804000}, {0x3f806000},
+ {0x3f808000}, {0x3f80a000}, {0x3f80c000}, {0x3f80e000},
+ {0x3f810000}, {0x3f812000}, {0x3f814000}, {0x3f816000},
+ {0x3f818000}, {0x3f81a000}, {0x3f81c000}, {0x3f81e000},
+ {0x3f820000}, {0x3f822000}, {0x3f824000}, {0x3f826000},
+ {0x3f828000}, {0x3f82a000}, {0x3f82c000}, {0x3f82e000},
+ {0x3f830000}, {0x3f832000}, {0x3f834000}, {0x3f836000},
+ {0x3f838000}, {0x3f83a000}, {0x3f83c000}, {0x3f83e000},
+ {0x3f840000}, {0x3f842000}, {0x3f844000}, {0x3f846000},
+ {0x3f848000}, {0x3f84a000}, {0x3f84c000}, {0x3f84e000},
+ {0x3f850000}, {0x3f852000}, {0x3f854000}, {0x3f856000},
+ {0x3f858000}, {0x3f85a000}, {0x3f85c000}, {0x3f85e000},
+ {0x3f860000}, {0x3f862000}, {0x3f864000}, {0x3f866000},
+ {0x3f868000}, {0x3f86a000}, {0x3f86c000}, {0x3f86e000},
+ {0x3f870000}, {0x3f872000}, {0x3f874000}, {0x3f876000},
+ {0x3f878000}, {0x3f87a000}, {0x3f87c000}, {0x3f87e000},
+ {0x3f880000}, {0x3f882000}, {0x3f884000}, {0x3f886000},
+ {0x3f888000}, {0x3f88a000}, {0x3f88c000}, {0x3f88e000},
+ {0x3f890000}, {0x3f892000}, {0x3f894000}, {0x3f896000},
+ {0x3f898000}, {0x3f89a000}, {0x3f89c000}, {0x3f89e000},
+ {0x3f8a0000}, {0x3f8a2000}, {0x3f8a4000}, {0x3f8a6000},
+ {0x3f8a8000}, {0x3f8aa000}, {0x3f8ac000}, {0x3f8ae000},
+ {0x3f8b0000}, {0x3f8b2000}, {0x3f8b4000}, {0x3f8b6000},
+ {0x3f8b8000}, {0x3f8ba000}, {0x3f8bc000}, {0x3f8be000},
+ {0x3f8c0000}, {0x3f8c2000}, {0x3f8c4000}, {0x3f8c6000},
+ {0x3f8c8000}, {0x3f8ca000}, {0x3f8cc000}, {0x3f8ce000},
+ {0x3f8d0000}, {0x3f8d2000}, {0x3f8d4000}, {0x3f8d6000},
+ {0x3f8d8000}, {0x3f8da000}, {0x3f8dc000}, {0x3f8de000},
+ {0x3f8e0000}, {0x3f8e2000}, {0x3f8e4000}, {0x3f8e6000},
+ {0x3f8e8000}, {0x3f8ea000}, {0x3f8ec000}, {0x3f8ee000},
+ {0x3f8f0000}, {0x3f8f2000}, {0x3f8f4000}, {0x3f8f6000},
+ {0x3f8f8000}, {0x3f8fa000}, {0x3f8fc000}, {0x3f8fe000},
+ {0x3f900000}, {0x3f902000}, {0x3f904000}, {0x3f906000},
+ {0x3f908000}, {0x3f90a000}, {0x3f90c000}, {0x3f90e000},
+ {0x3f910000}, {0x3f912000}, {0x3f914000}, {0x3f916000},
+ {0x3f918000}, {0x3f91a000}, {0x3f91c000}, {0x3f91e000},
+ {0x3f920000}, {0x3f922000}, {0x3f924000}, {0x3f926000},
+ {0x3f928000}, {0x3f92a000}, {0x3f92c000}, {0x3f92e000},
+ {0x3f930000}, {0x3f932000}, {0x3f934000}, {0x3f936000},
+ {0x3f938000}, {0x3f93a000}, {0x3f93c000}, {0x3f93e000},
+ {0x3f940000}, {0x3f942000}, {0x3f944000}, {0x3f946000},
+ {0x3f948000}, {0x3f94a000}, {0x3f94c000}, {0x3f94e000},
+ {0x3f950000}, {0x3f952000}, {0x3f954000}, {0x3f956000},
+ {0x3f958000}, {0x3f95a000}, {0x3f95c000}, {0x3f95e000},
+ {0x3f960000}, {0x3f962000}, {0x3f964000}, {0x3f966000},
+ {0x3f968000}, {0x3f96a000}, {0x3f96c000}, {0x3f96e000},
+ {0x3f970000}, {0x3f972000}, {0x3f974000}, {0x3f976000},
+ {0x3f978000}, {0x3f97a000}, {0x3f97c000}, {0x3f97e000},
+ {0x3f980000}, {0x3f982000}, {0x3f984000}, {0x3f986000},
+ {0x3f988000}, {0x3f98a000}, {0x3f98c000}, {0x3f98e000},
+ {0x3f990000}, {0x3f992000}, {0x3f994000}, {0x3f996000},
+ {0x3f998000}, {0x3f99a000}, {0x3f99c000}, {0x3f99e000},
+ {0x3f9a0000}, {0x3f9a2000}, {0x3f9a4000}, {0x3f9a6000},
+ {0x3f9a8000}, {0x3f9aa000}, {0x3f9ac000}, {0x3f9ae000},
+ {0x3f9b0000}, {0x3f9b2000}, {0x3f9b4000}, {0x3f9b6000},
+ {0x3f9b8000}, {0x3f9ba000}, {0x3f9bc000}, {0x3f9be000},
+ {0x3f9c0000}, {0x3f9c2000}, {0x3f9c4000}, {0x3f9c6000},
+ {0x3f9c8000}, {0x3f9ca000}, {0x3f9cc000}, {0x3f9ce000},
+ {0x3f9d0000}, {0x3f9d2000}, {0x3f9d4000}, {0x3f9d6000},
+ {0x3f9d8000}, {0x3f9da000}, {0x3f9dc000}, {0x3f9de000},
+ {0x3f9e0000}, {0x3f9e2000}, {0x3f9e4000}, {0x3f9e6000},
+ {0x3f9e8000}, {0x3f9ea000}, {0x3f9ec000}, {0x3f9ee000},
+ {0x3f9f0000}, {0x3f9f2000}, {0x3f9f4000}, {0x3f9f6000},
+ {0x3f9f8000}, {0x3f9fa000}, {0x3f9fc000}, {0x3f9fe000},
+ {0x3fa00000}, {0x3fa02000}, {0x3fa04000}, {0x3fa06000},
+ {0x3fa08000}, {0x3fa0a000}, {0x3fa0c000}, {0x3fa0e000},
+ {0x3fa10000}, {0x3fa12000}, {0x3fa14000}, {0x3fa16000},
+ {0x3fa18000}, {0x3fa1a000}, {0x3fa1c000}, {0x3fa1e000},
+ {0x3fa20000}, {0x3fa22000}, {0x3fa24000}, {0x3fa26000},
+ {0x3fa28000}, {0x3fa2a000}, {0x3fa2c000}, {0x3fa2e000},
+ {0x3fa30000}, {0x3fa32000}, {0x3fa34000}, {0x3fa36000},
+ {0x3fa38000}, {0x3fa3a000}, {0x3fa3c000}, {0x3fa3e000},
+ {0x3fa40000}, {0x3fa42000}, {0x3fa44000}, {0x3fa46000},
+ {0x3fa48000}, {0x3fa4a000}, {0x3fa4c000}, {0x3fa4e000},
+ {0x3fa50000}, {0x3fa52000}, {0x3fa54000}, {0x3fa56000},
+ {0x3fa58000}, {0x3fa5a000}, {0x3fa5c000}, {0x3fa5e000},
+ {0x3fa60000}, {0x3fa62000}, {0x3fa64000}, {0x3fa66000},
+ {0x3fa68000}, {0x3fa6a000}, {0x3fa6c000}, {0x3fa6e000},
+ {0x3fa70000}, {0x3fa72000}, {0x3fa74000}, {0x3fa76000},
+ {0x3fa78000}, {0x3fa7a000}, {0x3fa7c000}, {0x3fa7e000},
+ {0x3fa80000}, {0x3fa82000}, {0x3fa84000}, {0x3fa86000},
+ {0x3fa88000}, {0x3fa8a000}, {0x3fa8c000}, {0x3fa8e000},
+ {0x3fa90000}, {0x3fa92000}, {0x3fa94000}, {0x3fa96000},
+ {0x3fa98000}, {0x3fa9a000}, {0x3fa9c000}, {0x3fa9e000},
+ {0x3faa0000}, {0x3faa2000}, {0x3faa4000}, {0x3faa6000},
+ {0x3faa8000}, {0x3faaa000}, {0x3faac000}, {0x3faae000},
+ {0x3fab0000}, {0x3fab2000}, {0x3fab4000}, {0x3fab6000},
+ {0x3fab8000}, {0x3faba000}, {0x3fabc000}, {0x3fabe000},
+ {0x3fac0000}, {0x3fac2000}, {0x3fac4000}, {0x3fac6000},
+ {0x3fac8000}, {0x3faca000}, {0x3facc000}, {0x3face000},
+ {0x3fad0000}, {0x3fad2000}, {0x3fad4000}, {0x3fad6000},
+ {0x3fad8000}, {0x3fada000}, {0x3fadc000}, {0x3fade000},
+ {0x3fae0000}, {0x3fae2000}, {0x3fae4000}, {0x3fae6000},
+ {0x3fae8000}, {0x3faea000}, {0x3faec000}, {0x3faee000},
+ {0x3faf0000}, {0x3faf2000}, {0x3faf4000}, {0x3faf6000},
+ {0x3faf8000}, {0x3fafa000}, {0x3fafc000}, {0x3fafe000},
+ {0x3fb00000}, {0x3fb02000}, {0x3fb04000}, {0x3fb06000},
+ {0x3fb08000}, {0x3fb0a000}, {0x3fb0c000}, {0x3fb0e000},
+ {0x3fb10000}, {0x3fb12000}, {0x3fb14000}, {0x3fb16000},
+ {0x3fb18000}, {0x3fb1a000}, {0x3fb1c000}, {0x3fb1e000},
+ {0x3fb20000}, {0x3fb22000}, {0x3fb24000}, {0x3fb26000},
+ {0x3fb28000}, {0x3fb2a000}, {0x3fb2c000}, {0x3fb2e000},
+ {0x3fb30000}, {0x3fb32000}, {0x3fb34000}, {0x3fb36000},
+ {0x3fb38000}, {0x3fb3a000}, {0x3fb3c000}, {0x3fb3e000},
+ {0x3fb40000}, {0x3fb42000}, {0x3fb44000}, {0x3fb46000},
+ {0x3fb48000}, {0x3fb4a000}, {0x3fb4c000}, {0x3fb4e000},
+ {0x3fb50000}, {0x3fb52000}, {0x3fb54000}, {0x3fb56000},
+ {0x3fb58000}, {0x3fb5a000}, {0x3fb5c000}, {0x3fb5e000},
+ {0x3fb60000}, {0x3fb62000}, {0x3fb64000}, {0x3fb66000},
+ {0x3fb68000}, {0x3fb6a000}, {0x3fb6c000}, {0x3fb6e000},
+ {0x3fb70000}, {0x3fb72000}, {0x3fb74000}, {0x3fb76000},
+ {0x3fb78000}, {0x3fb7a000}, {0x3fb7c000}, {0x3fb7e000},
+ {0x3fb80000}, {0x3fb82000}, {0x3fb84000}, {0x3fb86000},
+ {0x3fb88000}, {0x3fb8a000}, {0x3fb8c000}, {0x3fb8e000},
+ {0x3fb90000}, {0x3fb92000}, {0x3fb94000}, {0x3fb96000},
+ {0x3fb98000}, {0x3fb9a000}, {0x3fb9c000}, {0x3fb9e000},
+ {0x3fba0000}, {0x3fba2000}, {0x3fba4000}, {0x3fba6000},
+ {0x3fba8000}, {0x3fbaa000}, {0x3fbac000}, {0x3fbae000},
+ {0x3fbb0000}, {0x3fbb2000}, {0x3fbb4000}, {0x3fbb6000},
+ {0x3fbb8000}, {0x3fbba000}, {0x3fbbc000}, {0x3fbbe000},
+ {0x3fbc0000}, {0x3fbc2000}, {0x3fbc4000}, {0x3fbc6000},
+ {0x3fbc8000}, {0x3fbca000}, {0x3fbcc000}, {0x3fbce000},
+ {0x3fbd0000}, {0x3fbd2000}, {0x3fbd4000}, {0x3fbd6000},
+ {0x3fbd8000}, {0x3fbda000}, {0x3fbdc000}, {0x3fbde000},
+ {0x3fbe0000}, {0x3fbe2000}, {0x3fbe4000}, {0x3fbe6000},
+ {0x3fbe8000}, {0x3fbea000}, {0x3fbec000}, {0x3fbee000},
+ {0x3fbf0000}, {0x3fbf2000}, {0x3fbf4000}, {0x3fbf6000},
+ {0x3fbf8000}, {0x3fbfa000}, {0x3fbfc000}, {0x3fbfe000},
+ {0x3fc00000}, {0x3fc02000}, {0x3fc04000}, {0x3fc06000},
+ {0x3fc08000}, {0x3fc0a000}, {0x3fc0c000}, {0x3fc0e000},
+ {0x3fc10000}, {0x3fc12000}, {0x3fc14000}, {0x3fc16000},
+ {0x3fc18000}, {0x3fc1a000}, {0x3fc1c000}, {0x3fc1e000},
+ {0x3fc20000}, {0x3fc22000}, {0x3fc24000}, {0x3fc26000},
+ {0x3fc28000}, {0x3fc2a000}, {0x3fc2c000}, {0x3fc2e000},
+ {0x3fc30000}, {0x3fc32000}, {0x3fc34000}, {0x3fc36000},
+ {0x3fc38000}, {0x3fc3a000}, {0x3fc3c000}, {0x3fc3e000},
+ {0x3fc40000}, {0x3fc42000}, {0x3fc44000}, {0x3fc46000},
+ {0x3fc48000}, {0x3fc4a000}, {0x3fc4c000}, {0x3fc4e000},
+ {0x3fc50000}, {0x3fc52000}, {0x3fc54000}, {0x3fc56000},
+ {0x3fc58000}, {0x3fc5a000}, {0x3fc5c000}, {0x3fc5e000},
+ {0x3fc60000}, {0x3fc62000}, {0x3fc64000}, {0x3fc66000},
+ {0x3fc68000}, {0x3fc6a000}, {0x3fc6c000}, {0x3fc6e000},
+ {0x3fc70000}, {0x3fc72000}, {0x3fc74000}, {0x3fc76000},
+ {0x3fc78000}, {0x3fc7a000}, {0x3fc7c000}, {0x3fc7e000},
+ {0x3fc80000}, {0x3fc82000}, {0x3fc84000}, {0x3fc86000},
+ {0x3fc88000}, {0x3fc8a000}, {0x3fc8c000}, {0x3fc8e000},
+ {0x3fc90000}, {0x3fc92000}, {0x3fc94000}, {0x3fc96000},
+ {0x3fc98000}, {0x3fc9a000}, {0x3fc9c000}, {0x3fc9e000},
+ {0x3fca0000}, {0x3fca2000}, {0x3fca4000}, {0x3fca6000},
+ {0x3fca8000}, {0x3fcaa000}, {0x3fcac000}, {0x3fcae000},
+ {0x3fcb0000}, {0x3fcb2000}, {0x3fcb4000}, {0x3fcb6000},
+ {0x3fcb8000}, {0x3fcba000}, {0x3fcbc000}, {0x3fcbe000},
+ {0x3fcc0000}, {0x3fcc2000}, {0x3fcc4000}, {0x3fcc6000},
+ {0x3fcc8000}, {0x3fcca000}, {0x3fccc000}, {0x3fcce000},
+ {0x3fcd0000}, {0x3fcd2000}, {0x3fcd4000}, {0x3fcd6000},
+ {0x3fcd8000}, {0x3fcda000}, {0x3fcdc000}, {0x3fcde000},
+ {0x3fce0000}, {0x3fce2000}, {0x3fce4000}, {0x3fce6000},
+ {0x3fce8000}, {0x3fcea000}, {0x3fcec000}, {0x3fcee000},
+ {0x3fcf0000}, {0x3fcf2000}, {0x3fcf4000}, {0x3fcf6000},
+ {0x3fcf8000}, {0x3fcfa000}, {0x3fcfc000}, {0x3fcfe000},
+ {0x3fd00000}, {0x3fd02000}, {0x3fd04000}, {0x3fd06000},
+ {0x3fd08000}, {0x3fd0a000}, {0x3fd0c000}, {0x3fd0e000},
+ {0x3fd10000}, {0x3fd12000}, {0x3fd14000}, {0x3fd16000},
+ {0x3fd18000}, {0x3fd1a000}, {0x3fd1c000}, {0x3fd1e000},
+ {0x3fd20000}, {0x3fd22000}, {0x3fd24000}, {0x3fd26000},
+ {0x3fd28000}, {0x3fd2a000}, {0x3fd2c000}, {0x3fd2e000},
+ {0x3fd30000}, {0x3fd32000}, {0x3fd34000}, {0x3fd36000},
+ {0x3fd38000}, {0x3fd3a000}, {0x3fd3c000}, {0x3fd3e000},
+ {0x3fd40000}, {0x3fd42000}, {0x3fd44000}, {0x3fd46000},
+ {0x3fd48000}, {0x3fd4a000}, {0x3fd4c000}, {0x3fd4e000},
+ {0x3fd50000}, {0x3fd52000}, {0x3fd54000}, {0x3fd56000},
+ {0x3fd58000}, {0x3fd5a000}, {0x3fd5c000}, {0x3fd5e000},
+ {0x3fd60000}, {0x3fd62000}, {0x3fd64000}, {0x3fd66000},
+ {0x3fd68000}, {0x3fd6a000}, {0x3fd6c000}, {0x3fd6e000},
+ {0x3fd70000}, {0x3fd72000}, {0x3fd74000}, {0x3fd76000},
+ {0x3fd78000}, {0x3fd7a000}, {0x3fd7c000}, {0x3fd7e000},
+ {0x3fd80000}, {0x3fd82000}, {0x3fd84000}, {0x3fd86000},
+ {0x3fd88000}, {0x3fd8a000}, {0x3fd8c000}, {0x3fd8e000},
+ {0x3fd90000}, {0x3fd92000}, {0x3fd94000}, {0x3fd96000},
+ {0x3fd98000}, {0x3fd9a000}, {0x3fd9c000}, {0x3fd9e000},
+ {0x3fda0000}, {0x3fda2000}, {0x3fda4000}, {0x3fda6000},
+ {0x3fda8000}, {0x3fdaa000}, {0x3fdac000}, {0x3fdae000},
+ {0x3fdb0000}, {0x3fdb2000}, {0x3fdb4000}, {0x3fdb6000},
+ {0x3fdb8000}, {0x3fdba000}, {0x3fdbc000}, {0x3fdbe000},
+ {0x3fdc0000}, {0x3fdc2000}, {0x3fdc4000}, {0x3fdc6000},
+ {0x3fdc8000}, {0x3fdca000}, {0x3fdcc000}, {0x3fdce000},
+ {0x3fdd0000}, {0x3fdd2000}, {0x3fdd4000}, {0x3fdd6000},
+ {0x3fdd8000}, {0x3fdda000}, {0x3fddc000}, {0x3fdde000},
+ {0x3fde0000}, {0x3fde2000}, {0x3fde4000}, {0x3fde6000},
+ {0x3fde8000}, {0x3fdea000}, {0x3fdec000}, {0x3fdee000},
+ {0x3fdf0000}, {0x3fdf2000}, {0x3fdf4000}, {0x3fdf6000},
+ {0x3fdf8000}, {0x3fdfa000}, {0x3fdfc000}, {0x3fdfe000},
+ {0x3fe00000}, {0x3fe02000}, {0x3fe04000}, {0x3fe06000},
+ {0x3fe08000}, {0x3fe0a000}, {0x3fe0c000}, {0x3fe0e000},
+ {0x3fe10000}, {0x3fe12000}, {0x3fe14000}, {0x3fe16000},
+ {0x3fe18000}, {0x3fe1a000}, {0x3fe1c000}, {0x3fe1e000},
+ {0x3fe20000}, {0x3fe22000}, {0x3fe24000}, {0x3fe26000},
+ {0x3fe28000}, {0x3fe2a000}, {0x3fe2c000}, {0x3fe2e000},
+ {0x3fe30000}, {0x3fe32000}, {0x3fe34000}, {0x3fe36000},
+ {0x3fe38000}, {0x3fe3a000}, {0x3fe3c000}, {0x3fe3e000},
+ {0x3fe40000}, {0x3fe42000}, {0x3fe44000}, {0x3fe46000},
+ {0x3fe48000}, {0x3fe4a000}, {0x3fe4c000}, {0x3fe4e000},
+ {0x3fe50000}, {0x3fe52000}, {0x3fe54000}, {0x3fe56000},
+ {0x3fe58000}, {0x3fe5a000}, {0x3fe5c000}, {0x3fe5e000},
+ {0x3fe60000}, {0x3fe62000}, {0x3fe64000}, {0x3fe66000},
+ {0x3fe68000}, {0x3fe6a000}, {0x3fe6c000}, {0x3fe6e000},
+ {0x3fe70000}, {0x3fe72000}, {0x3fe74000}, {0x3fe76000},
+ {0x3fe78000}, {0x3fe7a000}, {0x3fe7c000}, {0x3fe7e000},
+ {0x3fe80000}, {0x3fe82000}, {0x3fe84000}, {0x3fe86000},
+ {0x3fe88000}, {0x3fe8a000}, {0x3fe8c000}, {0x3fe8e000},
+ {0x3fe90000}, {0x3fe92000}, {0x3fe94000}, {0x3fe96000},
+ {0x3fe98000}, {0x3fe9a000}, {0x3fe9c000}, {0x3fe9e000},
+ {0x3fea0000}, {0x3fea2000}, {0x3fea4000}, {0x3fea6000},
+ {0x3fea8000}, {0x3feaa000}, {0x3feac000}, {0x3feae000},
+ {0x3feb0000}, {0x3feb2000}, {0x3feb4000}, {0x3feb6000},
+ {0x3feb8000}, {0x3feba000}, {0x3febc000}, {0x3febe000},
+ {0x3fec0000}, {0x3fec2000}, {0x3fec4000}, {0x3fec6000},
+ {0x3fec8000}, {0x3feca000}, {0x3fecc000}, {0x3fece000},
+ {0x3fed0000}, {0x3fed2000}, {0x3fed4000}, {0x3fed6000},
+ {0x3fed8000}, {0x3feda000}, {0x3fedc000}, {0x3fede000},
+ {0x3fee0000}, {0x3fee2000}, {0x3fee4000}, {0x3fee6000},
+ {0x3fee8000}, {0x3feea000}, {0x3feec000}, {0x3feee000},
+ {0x3fef0000}, {0x3fef2000}, {0x3fef4000}, {0x3fef6000},
+ {0x3fef8000}, {0x3fefa000}, {0x3fefc000}, {0x3fefe000},
+ {0x3ff00000}, {0x3ff02000}, {0x3ff04000}, {0x3ff06000},
+ {0x3ff08000}, {0x3ff0a000}, {0x3ff0c000}, {0x3ff0e000},
+ {0x3ff10000}, {0x3ff12000}, {0x3ff14000}, {0x3ff16000},
+ {0x3ff18000}, {0x3ff1a000}, {0x3ff1c000}, {0x3ff1e000},
+ {0x3ff20000}, {0x3ff22000}, {0x3ff24000}, {0x3ff26000},
+ {0x3ff28000}, {0x3ff2a000}, {0x3ff2c000}, {0x3ff2e000},
+ {0x3ff30000}, {0x3ff32000}, {0x3ff34000}, {0x3ff36000},
+ {0x3ff38000}, {0x3ff3a000}, {0x3ff3c000}, {0x3ff3e000},
+ {0x3ff40000}, {0x3ff42000}, {0x3ff44000}, {0x3ff46000},
+ {0x3ff48000}, {0x3ff4a000}, {0x3ff4c000}, {0x3ff4e000},
+ {0x3ff50000}, {0x3ff52000}, {0x3ff54000}, {0x3ff56000},
+ {0x3ff58000}, {0x3ff5a000}, {0x3ff5c000}, {0x3ff5e000},
+ {0x3ff60000}, {0x3ff62000}, {0x3ff64000}, {0x3ff66000},
+ {0x3ff68000}, {0x3ff6a000}, {0x3ff6c000}, {0x3ff6e000},
+ {0x3ff70000}, {0x3ff72000}, {0x3ff74000}, {0x3ff76000},
+ {0x3ff78000}, {0x3ff7a000}, {0x3ff7c000}, {0x3ff7e000},
+ {0x3ff80000}, {0x3ff82000}, {0x3ff84000}, {0x3ff86000},
+ {0x3ff88000}, {0x3ff8a000}, {0x3ff8c000}, {0x3ff8e000},
+ {0x3ff90000}, {0x3ff92000}, {0x3ff94000}, {0x3ff96000},
+ {0x3ff98000}, {0x3ff9a000}, {0x3ff9c000}, {0x3ff9e000},
+ {0x3ffa0000}, {0x3ffa2000}, {0x3ffa4000}, {0x3ffa6000},
+ {0x3ffa8000}, {0x3ffaa000}, {0x3ffac000}, {0x3ffae000},
+ {0x3ffb0000}, {0x3ffb2000}, {0x3ffb4000}, {0x3ffb6000},
+ {0x3ffb8000}, {0x3ffba000}, {0x3ffbc000}, {0x3ffbe000},
+ {0x3ffc0000}, {0x3ffc2000}, {0x3ffc4000}, {0x3ffc6000},
+ {0x3ffc8000}, {0x3ffca000}, {0x3ffcc000}, {0x3ffce000},
+ {0x3ffd0000}, {0x3ffd2000}, {0x3ffd4000}, {0x3ffd6000},
+ {0x3ffd8000}, {0x3ffda000}, {0x3ffdc000}, {0x3ffde000},
+ {0x3ffe0000}, {0x3ffe2000}, {0x3ffe4000}, {0x3ffe6000},
+ {0x3ffe8000}, {0x3ffea000}, {0x3ffec000}, {0x3ffee000},
+ {0x3fff0000}, {0x3fff2000}, {0x3fff4000}, {0x3fff6000},
+ {0x3fff8000}, {0x3fffa000}, {0x3fffc000}, {0x3fffe000},
+ {0x40000000}, {0x40002000}, {0x40004000}, {0x40006000},
+ {0x40008000}, {0x4000a000}, {0x4000c000}, {0x4000e000},
+ {0x40010000}, {0x40012000}, {0x40014000}, {0x40016000},
+ {0x40018000}, {0x4001a000}, {0x4001c000}, {0x4001e000},
+ {0x40020000}, {0x40022000}, {0x40024000}, {0x40026000},
+ {0x40028000}, {0x4002a000}, {0x4002c000}, {0x4002e000},
+ {0x40030000}, {0x40032000}, {0x40034000}, {0x40036000},
+ {0x40038000}, {0x4003a000}, {0x4003c000}, {0x4003e000},
+ {0x40040000}, {0x40042000}, {0x40044000}, {0x40046000},
+ {0x40048000}, {0x4004a000}, {0x4004c000}, {0x4004e000},
+ {0x40050000}, {0x40052000}, {0x40054000}, {0x40056000},
+ {0x40058000}, {0x4005a000}, {0x4005c000}, {0x4005e000},
+ {0x40060000}, {0x40062000}, {0x40064000}, {0x40066000},
+ {0x40068000}, {0x4006a000}, {0x4006c000}, {0x4006e000},
+ {0x40070000}, {0x40072000}, {0x40074000}, {0x40076000},
+ {0x40078000}, {0x4007a000}, {0x4007c000}, {0x4007e000},
+ {0x40080000}, {0x40082000}, {0x40084000}, {0x40086000},
+ {0x40088000}, {0x4008a000}, {0x4008c000}, {0x4008e000},
+ {0x40090000}, {0x40092000}, {0x40094000}, {0x40096000},
+ {0x40098000}, {0x4009a000}, {0x4009c000}, {0x4009e000},
+ {0x400a0000}, {0x400a2000}, {0x400a4000}, {0x400a6000},
+ {0x400a8000}, {0x400aa000}, {0x400ac000}, {0x400ae000},
+ {0x400b0000}, {0x400b2000}, {0x400b4000}, {0x400b6000},
+ {0x400b8000}, {0x400ba000}, {0x400bc000}, {0x400be000},
+ {0x400c0000}, {0x400c2000}, {0x400c4000}, {0x400c6000},
+ {0x400c8000}, {0x400ca000}, {0x400cc000}, {0x400ce000},
+ {0x400d0000}, {0x400d2000}, {0x400d4000}, {0x400d6000},
+ {0x400d8000}, {0x400da000}, {0x400dc000}, {0x400de000},
+ {0x400e0000}, {0x400e2000}, {0x400e4000}, {0x400e6000},
+ {0x400e8000}, {0x400ea000}, {0x400ec000}, {0x400ee000},
+ {0x400f0000}, {0x400f2000}, {0x400f4000}, {0x400f6000},
+ {0x400f8000}, {0x400fa000}, {0x400fc000}, {0x400fe000},
+ {0x40100000}, {0x40102000}, {0x40104000}, {0x40106000},
+ {0x40108000}, {0x4010a000}, {0x4010c000}, {0x4010e000},
+ {0x40110000}, {0x40112000}, {0x40114000}, {0x40116000},
+ {0x40118000}, {0x4011a000}, {0x4011c000}, {0x4011e000},
+ {0x40120000}, {0x40122000}, {0x40124000}, {0x40126000},
+ {0x40128000}, {0x4012a000}, {0x4012c000}, {0x4012e000},
+ {0x40130000}, {0x40132000}, {0x40134000}, {0x40136000},
+ {0x40138000}, {0x4013a000}, {0x4013c000}, {0x4013e000},
+ {0x40140000}, {0x40142000}, {0x40144000}, {0x40146000},
+ {0x40148000}, {0x4014a000}, {0x4014c000}, {0x4014e000},
+ {0x40150000}, {0x40152000}, {0x40154000}, {0x40156000},
+ {0x40158000}, {0x4015a000}, {0x4015c000}, {0x4015e000},
+ {0x40160000}, {0x40162000}, {0x40164000}, {0x40166000},
+ {0x40168000}, {0x4016a000}, {0x4016c000}, {0x4016e000},
+ {0x40170000}, {0x40172000}, {0x40174000}, {0x40176000},
+ {0x40178000}, {0x4017a000}, {0x4017c000}, {0x4017e000},
+ {0x40180000}, {0x40182000}, {0x40184000}, {0x40186000},
+ {0x40188000}, {0x4018a000}, {0x4018c000}, {0x4018e000},
+ {0x40190000}, {0x40192000}, {0x40194000}, {0x40196000},
+ {0x40198000}, {0x4019a000}, {0x4019c000}, {0x4019e000},
+ {0x401a0000}, {0x401a2000}, {0x401a4000}, {0x401a6000},
+ {0x401a8000}, {0x401aa000}, {0x401ac000}, {0x401ae000},
+ {0x401b0000}, {0x401b2000}, {0x401b4000}, {0x401b6000},
+ {0x401b8000}, {0x401ba000}, {0x401bc000}, {0x401be000},
+ {0x401c0000}, {0x401c2000}, {0x401c4000}, {0x401c6000},
+ {0x401c8000}, {0x401ca000}, {0x401cc000}, {0x401ce000},
+ {0x401d0000}, {0x401d2000}, {0x401d4000}, {0x401d6000},
+ {0x401d8000}, {0x401da000}, {0x401dc000}, {0x401de000},
+ {0x401e0000}, {0x401e2000}, {0x401e4000}, {0x401e6000},
+ {0x401e8000}, {0x401ea000}, {0x401ec000}, {0x401ee000},
+ {0x401f0000}, {0x401f2000}, {0x401f4000}, {0x401f6000},
+ {0x401f8000}, {0x401fa000}, {0x401fc000}, {0x401fe000},
+ {0x40200000}, {0x40202000}, {0x40204000}, {0x40206000},
+ {0x40208000}, {0x4020a000}, {0x4020c000}, {0x4020e000},
+ {0x40210000}, {0x40212000}, {0x40214000}, {0x40216000},
+ {0x40218000}, {0x4021a000}, {0x4021c000}, {0x4021e000},
+ {0x40220000}, {0x40222000}, {0x40224000}, {0x40226000},
+ {0x40228000}, {0x4022a000}, {0x4022c000}, {0x4022e000},
+ {0x40230000}, {0x40232000}, {0x40234000}, {0x40236000},
+ {0x40238000}, {0x4023a000}, {0x4023c000}, {0x4023e000},
+ {0x40240000}, {0x40242000}, {0x40244000}, {0x40246000},
+ {0x40248000}, {0x4024a000}, {0x4024c000}, {0x4024e000},
+ {0x40250000}, {0x40252000}, {0x40254000}, {0x40256000},
+ {0x40258000}, {0x4025a000}, {0x4025c000}, {0x4025e000},
+ {0x40260000}, {0x40262000}, {0x40264000}, {0x40266000},
+ {0x40268000}, {0x4026a000}, {0x4026c000}, {0x4026e000},
+ {0x40270000}, {0x40272000}, {0x40274000}, {0x40276000},
+ {0x40278000}, {0x4027a000}, {0x4027c000}, {0x4027e000},
+ {0x40280000}, {0x40282000}, {0x40284000}, {0x40286000},
+ {0x40288000}, {0x4028a000}, {0x4028c000}, {0x4028e000},
+ {0x40290000}, {0x40292000}, {0x40294000}, {0x40296000},
+ {0x40298000}, {0x4029a000}, {0x4029c000}, {0x4029e000},
+ {0x402a0000}, {0x402a2000}, {0x402a4000}, {0x402a6000},
+ {0x402a8000}, {0x402aa000}, {0x402ac000}, {0x402ae000},
+ {0x402b0000}, {0x402b2000}, {0x402b4000}, {0x402b6000},
+ {0x402b8000}, {0x402ba000}, {0x402bc000}, {0x402be000},
+ {0x402c0000}, {0x402c2000}, {0x402c4000}, {0x402c6000},
+ {0x402c8000}, {0x402ca000}, {0x402cc000}, {0x402ce000},
+ {0x402d0000}, {0x402d2000}, {0x402d4000}, {0x402d6000},
+ {0x402d8000}, {0x402da000}, {0x402dc000}, {0x402de000},
+ {0x402e0000}, {0x402e2000}, {0x402e4000}, {0x402e6000},
+ {0x402e8000}, {0x402ea000}, {0x402ec000}, {0x402ee000},
+ {0x402f0000}, {0x402f2000}, {0x402f4000}, {0x402f6000},
+ {0x402f8000}, {0x402fa000}, {0x402fc000}, {0x402fe000},
+ {0x40300000}, {0x40302000}, {0x40304000}, {0x40306000},
+ {0x40308000}, {0x4030a000}, {0x4030c000}, {0x4030e000},
+ {0x40310000}, {0x40312000}, {0x40314000}, {0x40316000},
+ {0x40318000}, {0x4031a000}, {0x4031c000}, {0x4031e000},
+ {0x40320000}, {0x40322000}, {0x40324000}, {0x40326000},
+ {0x40328000}, {0x4032a000}, {0x4032c000}, {0x4032e000},
+ {0x40330000}, {0x40332000}, {0x40334000}, {0x40336000},
+ {0x40338000}, {0x4033a000}, {0x4033c000}, {0x4033e000},
+ {0x40340000}, {0x40342000}, {0x40344000}, {0x40346000},
+ {0x40348000}, {0x4034a000}, {0x4034c000}, {0x4034e000},
+ {0x40350000}, {0x40352000}, {0x40354000}, {0x40356000},
+ {0x40358000}, {0x4035a000}, {0x4035c000}, {0x4035e000},
+ {0x40360000}, {0x40362000}, {0x40364000}, {0x40366000},
+ {0x40368000}, {0x4036a000}, {0x4036c000}, {0x4036e000},
+ {0x40370000}, {0x40372000}, {0x40374000}, {0x40376000},
+ {0x40378000}, {0x4037a000}, {0x4037c000}, {0x4037e000},
+ {0x40380000}, {0x40382000}, {0x40384000}, {0x40386000},
+ {0x40388000}, {0x4038a000}, {0x4038c000}, {0x4038e000},
+ {0x40390000}, {0x40392000}, {0x40394000}, {0x40396000},
+ {0x40398000}, {0x4039a000}, {0x4039c000}, {0x4039e000},
+ {0x403a0000}, {0x403a2000}, {0x403a4000}, {0x403a6000},
+ {0x403a8000}, {0x403aa000}, {0x403ac000}, {0x403ae000},
+ {0x403b0000}, {0x403b2000}, {0x403b4000}, {0x403b6000},
+ {0x403b8000}, {0x403ba000}, {0x403bc000}, {0x403be000},
+ {0x403c0000}, {0x403c2000}, {0x403c4000}, {0x403c6000},
+ {0x403c8000}, {0x403ca000}, {0x403cc000}, {0x403ce000},
+ {0x403d0000}, {0x403d2000}, {0x403d4000}, {0x403d6000},
+ {0x403d8000}, {0x403da000}, {0x403dc000}, {0x403de000},
+ {0x403e0000}, {0x403e2000}, {0x403e4000}, {0x403e6000},
+ {0x403e8000}, {0x403ea000}, {0x403ec000}, {0x403ee000},
+ {0x403f0000}, {0x403f2000}, {0x403f4000}, {0x403f6000},
+ {0x403f8000}, {0x403fa000}, {0x403fc000}, {0x403fe000},
+ {0x40400000}, {0x40402000}, {0x40404000}, {0x40406000},
+ {0x40408000}, {0x4040a000}, {0x4040c000}, {0x4040e000},
+ {0x40410000}, {0x40412000}, {0x40414000}, {0x40416000},
+ {0x40418000}, {0x4041a000}, {0x4041c000}, {0x4041e000},
+ {0x40420000}, {0x40422000}, {0x40424000}, {0x40426000},
+ {0x40428000}, {0x4042a000}, {0x4042c000}, {0x4042e000},
+ {0x40430000}, {0x40432000}, {0x40434000}, {0x40436000},
+ {0x40438000}, {0x4043a000}, {0x4043c000}, {0x4043e000},
+ {0x40440000}, {0x40442000}, {0x40444000}, {0x40446000},
+ {0x40448000}, {0x4044a000}, {0x4044c000}, {0x4044e000},
+ {0x40450000}, {0x40452000}, {0x40454000}, {0x40456000},
+ {0x40458000}, {0x4045a000}, {0x4045c000}, {0x4045e000},
+ {0x40460000}, {0x40462000}, {0x40464000}, {0x40466000},
+ {0x40468000}, {0x4046a000}, {0x4046c000}, {0x4046e000},
+ {0x40470000}, {0x40472000}, {0x40474000}, {0x40476000},
+ {0x40478000}, {0x4047a000}, {0x4047c000}, {0x4047e000},
+ {0x40480000}, {0x40482000}, {0x40484000}, {0x40486000},
+ {0x40488000}, {0x4048a000}, {0x4048c000}, {0x4048e000},
+ {0x40490000}, {0x40492000}, {0x40494000}, {0x40496000},
+ {0x40498000}, {0x4049a000}, {0x4049c000}, {0x4049e000},
+ {0x404a0000}, {0x404a2000}, {0x404a4000}, {0x404a6000},
+ {0x404a8000}, {0x404aa000}, {0x404ac000}, {0x404ae000},
+ {0x404b0000}, {0x404b2000}, {0x404b4000}, {0x404b6000},
+ {0x404b8000}, {0x404ba000}, {0x404bc000}, {0x404be000},
+ {0x404c0000}, {0x404c2000}, {0x404c4000}, {0x404c6000},
+ {0x404c8000}, {0x404ca000}, {0x404cc000}, {0x404ce000},
+ {0x404d0000}, {0x404d2000}, {0x404d4000}, {0x404d6000},
+ {0x404d8000}, {0x404da000}, {0x404dc000}, {0x404de000},
+ {0x404e0000}, {0x404e2000}, {0x404e4000}, {0x404e6000},
+ {0x404e8000}, {0x404ea000}, {0x404ec000}, {0x404ee000},
+ {0x404f0000}, {0x404f2000}, {0x404f4000}, {0x404f6000},
+ {0x404f8000}, {0x404fa000}, {0x404fc000}, {0x404fe000},
+ {0x40500000}, {0x40502000}, {0x40504000}, {0x40506000},
+ {0x40508000}, {0x4050a000}, {0x4050c000}, {0x4050e000},
+ {0x40510000}, {0x40512000}, {0x40514000}, {0x40516000},
+ {0x40518000}, {0x4051a000}, {0x4051c000}, {0x4051e000},
+ {0x40520000}, {0x40522000}, {0x40524000}, {0x40526000},
+ {0x40528000}, {0x4052a000}, {0x4052c000}, {0x4052e000},
+ {0x40530000}, {0x40532000}, {0x40534000}, {0x40536000},
+ {0x40538000}, {0x4053a000}, {0x4053c000}, {0x4053e000},
+ {0x40540000}, {0x40542000}, {0x40544000}, {0x40546000},
+ {0x40548000}, {0x4054a000}, {0x4054c000}, {0x4054e000},
+ {0x40550000}, {0x40552000}, {0x40554000}, {0x40556000},
+ {0x40558000}, {0x4055a000}, {0x4055c000}, {0x4055e000},
+ {0x40560000}, {0x40562000}, {0x40564000}, {0x40566000},
+ {0x40568000}, {0x4056a000}, {0x4056c000}, {0x4056e000},
+ {0x40570000}, {0x40572000}, {0x40574000}, {0x40576000},
+ {0x40578000}, {0x4057a000}, {0x4057c000}, {0x4057e000},
+ {0x40580000}, {0x40582000}, {0x40584000}, {0x40586000},
+ {0x40588000}, {0x4058a000}, {0x4058c000}, {0x4058e000},
+ {0x40590000}, {0x40592000}, {0x40594000}, {0x40596000},
+ {0x40598000}, {0x4059a000}, {0x4059c000}, {0x4059e000},
+ {0x405a0000}, {0x405a2000}, {0x405a4000}, {0x405a6000},
+ {0x405a8000}, {0x405aa000}, {0x405ac000}, {0x405ae000},
+ {0x405b0000}, {0x405b2000}, {0x405b4000}, {0x405b6000},
+ {0x405b8000}, {0x405ba000}, {0x405bc000}, {0x405be000},
+ {0x405c0000}, {0x405c2000}, {0x405c4000}, {0x405c6000},
+ {0x405c8000}, {0x405ca000}, {0x405cc000}, {0x405ce000},
+ {0x405d0000}, {0x405d2000}, {0x405d4000}, {0x405d6000},
+ {0x405d8000}, {0x405da000}, {0x405dc000}, {0x405de000},
+ {0x405e0000}, {0x405e2000}, {0x405e4000}, {0x405e6000},
+ {0x405e8000}, {0x405ea000}, {0x405ec000}, {0x405ee000},
+ {0x405f0000}, {0x405f2000}, {0x405f4000}, {0x405f6000},
+ {0x405f8000}, {0x405fa000}, {0x405fc000}, {0x405fe000},
+ {0x40600000}, {0x40602000}, {0x40604000}, {0x40606000},
+ {0x40608000}, {0x4060a000}, {0x4060c000}, {0x4060e000},
+ {0x40610000}, {0x40612000}, {0x40614000}, {0x40616000},
+ {0x40618000}, {0x4061a000}, {0x4061c000}, {0x4061e000},
+ {0x40620000}, {0x40622000}, {0x40624000}, {0x40626000},
+ {0x40628000}, {0x4062a000}, {0x4062c000}, {0x4062e000},
+ {0x40630000}, {0x40632000}, {0x40634000}, {0x40636000},
+ {0x40638000}, {0x4063a000}, {0x4063c000}, {0x4063e000},
+ {0x40640000}, {0x40642000}, {0x40644000}, {0x40646000},
+ {0x40648000}, {0x4064a000}, {0x4064c000}, {0x4064e000},
+ {0x40650000}, {0x40652000}, {0x40654000}, {0x40656000},
+ {0x40658000}, {0x4065a000}, {0x4065c000}, {0x4065e000},
+ {0x40660000}, {0x40662000}, {0x40664000}, {0x40666000},
+ {0x40668000}, {0x4066a000}, {0x4066c000}, {0x4066e000},
+ {0x40670000}, {0x40672000}, {0x40674000}, {0x40676000},
+ {0x40678000}, {0x4067a000}, {0x4067c000}, {0x4067e000},
+ {0x40680000}, {0x40682000}, {0x40684000}, {0x40686000},
+ {0x40688000}, {0x4068a000}, {0x4068c000}, {0x4068e000},
+ {0x40690000}, {0x40692000}, {0x40694000}, {0x40696000},
+ {0x40698000}, {0x4069a000}, {0x4069c000}, {0x4069e000},
+ {0x406a0000}, {0x406a2000}, {0x406a4000}, {0x406a6000},
+ {0x406a8000}, {0x406aa000}, {0x406ac000}, {0x406ae000},
+ {0x406b0000}, {0x406b2000}, {0x406b4000}, {0x406b6000},
+ {0x406b8000}, {0x406ba000}, {0x406bc000}, {0x406be000},
+ {0x406c0000}, {0x406c2000}, {0x406c4000}, {0x406c6000},
+ {0x406c8000}, {0x406ca000}, {0x406cc000}, {0x406ce000},
+ {0x406d0000}, {0x406d2000}, {0x406d4000}, {0x406d6000},
+ {0x406d8000}, {0x406da000}, {0x406dc000}, {0x406de000},
+ {0x406e0000}, {0x406e2000}, {0x406e4000}, {0x406e6000},
+ {0x406e8000}, {0x406ea000}, {0x406ec000}, {0x406ee000},
+ {0x406f0000}, {0x406f2000}, {0x406f4000}, {0x406f6000},
+ {0x406f8000}, {0x406fa000}, {0x406fc000}, {0x406fe000},
+ {0x40700000}, {0x40702000}, {0x40704000}, {0x40706000},
+ {0x40708000}, {0x4070a000}, {0x4070c000}, {0x4070e000},
+ {0x40710000}, {0x40712000}, {0x40714000}, {0x40716000},
+ {0x40718000}, {0x4071a000}, {0x4071c000}, {0x4071e000},
+ {0x40720000}, {0x40722000}, {0x40724000}, {0x40726000},
+ {0x40728000}, {0x4072a000}, {0x4072c000}, {0x4072e000},
+ {0x40730000}, {0x40732000}, {0x40734000}, {0x40736000},
+ {0x40738000}, {0x4073a000}, {0x4073c000}, {0x4073e000},
+ {0x40740000}, {0x40742000}, {0x40744000}, {0x40746000},
+ {0x40748000}, {0x4074a000}, {0x4074c000}, {0x4074e000},
+ {0x40750000}, {0x40752000}, {0x40754000}, {0x40756000},
+ {0x40758000}, {0x4075a000}, {0x4075c000}, {0x4075e000},
+ {0x40760000}, {0x40762000}, {0x40764000}, {0x40766000},
+ {0x40768000}, {0x4076a000}, {0x4076c000}, {0x4076e000},
+ {0x40770000}, {0x40772000}, {0x40774000}, {0x40776000},
+ {0x40778000}, {0x4077a000}, {0x4077c000}, {0x4077e000},
+ {0x40780000}, {0x40782000}, {0x40784000}, {0x40786000},
+ {0x40788000}, {0x4078a000}, {0x4078c000}, {0x4078e000},
+ {0x40790000}, {0x40792000}, {0x40794000}, {0x40796000},
+ {0x40798000}, {0x4079a000}, {0x4079c000}, {0x4079e000},
+ {0x407a0000}, {0x407a2000}, {0x407a4000}, {0x407a6000},
+ {0x407a8000}, {0x407aa000}, {0x407ac000}, {0x407ae000},
+ {0x407b0000}, {0x407b2000}, {0x407b4000}, {0x407b6000},
+ {0x407b8000}, {0x407ba000}, {0x407bc000}, {0x407be000},
+ {0x407c0000}, {0x407c2000}, {0x407c4000}, {0x407c6000},
+ {0x407c8000}, {0x407ca000}, {0x407cc000}, {0x407ce000},
+ {0x407d0000}, {0x407d2000}, {0x407d4000}, {0x407d6000},
+ {0x407d8000}, {0x407da000}, {0x407dc000}, {0x407de000},
+ {0x407e0000}, {0x407e2000}, {0x407e4000}, {0x407e6000},
+ {0x407e8000}, {0x407ea000}, {0x407ec000}, {0x407ee000},
+ {0x407f0000}, {0x407f2000}, {0x407f4000}, {0x407f6000},
+ {0x407f8000}, {0x407fa000}, {0x407fc000}, {0x407fe000},
+ {0x40800000}, {0x40802000}, {0x40804000}, {0x40806000},
+ {0x40808000}, {0x4080a000}, {0x4080c000}, {0x4080e000},
+ {0x40810000}, {0x40812000}, {0x40814000}, {0x40816000},
+ {0x40818000}, {0x4081a000}, {0x4081c000}, {0x4081e000},
+ {0x40820000}, {0x40822000}, {0x40824000}, {0x40826000},
+ {0x40828000}, {0x4082a000}, {0x4082c000}, {0x4082e000},
+ {0x40830000}, {0x40832000}, {0x40834000}, {0x40836000},
+ {0x40838000}, {0x4083a000}, {0x4083c000}, {0x4083e000},
+ {0x40840000}, {0x40842000}, {0x40844000}, {0x40846000},
+ {0x40848000}, {0x4084a000}, {0x4084c000}, {0x4084e000},
+ {0x40850000}, {0x40852000}, {0x40854000}, {0x40856000},
+ {0x40858000}, {0x4085a000}, {0x4085c000}, {0x4085e000},
+ {0x40860000}, {0x40862000}, {0x40864000}, {0x40866000},
+ {0x40868000}, {0x4086a000}, {0x4086c000}, {0x4086e000},
+ {0x40870000}, {0x40872000}, {0x40874000}, {0x40876000},
+ {0x40878000}, {0x4087a000}, {0x4087c000}, {0x4087e000},
+ {0x40880000}, {0x40882000}, {0x40884000}, {0x40886000},
+ {0x40888000}, {0x4088a000}, {0x4088c000}, {0x4088e000},
+ {0x40890000}, {0x40892000}, {0x40894000}, {0x40896000},
+ {0x40898000}, {0x4089a000}, {0x4089c000}, {0x4089e000},
+ {0x408a0000}, {0x408a2000}, {0x408a4000}, {0x408a6000},
+ {0x408a8000}, {0x408aa000}, {0x408ac000}, {0x408ae000},
+ {0x408b0000}, {0x408b2000}, {0x408b4000}, {0x408b6000},
+ {0x408b8000}, {0x408ba000}, {0x408bc000}, {0x408be000},
+ {0x408c0000}, {0x408c2000}, {0x408c4000}, {0x408c6000},
+ {0x408c8000}, {0x408ca000}, {0x408cc000}, {0x408ce000},
+ {0x408d0000}, {0x408d2000}, {0x408d4000}, {0x408d6000},
+ {0x408d8000}, {0x408da000}, {0x408dc000}, {0x408de000},
+ {0x408e0000}, {0x408e2000}, {0x408e4000}, {0x408e6000},
+ {0x408e8000}, {0x408ea000}, {0x408ec000}, {0x408ee000},
+ {0x408f0000}, {0x408f2000}, {0x408f4000}, {0x408f6000},
+ {0x408f8000}, {0x408fa000}, {0x408fc000}, {0x408fe000},
+ {0x40900000}, {0x40902000}, {0x40904000}, {0x40906000},
+ {0x40908000}, {0x4090a000}, {0x4090c000}, {0x4090e000},
+ {0x40910000}, {0x40912000}, {0x40914000}, {0x40916000},
+ {0x40918000}, {0x4091a000}, {0x4091c000}, {0x4091e000},
+ {0x40920000}, {0x40922000}, {0x40924000}, {0x40926000},
+ {0x40928000}, {0x4092a000}, {0x4092c000}, {0x4092e000},
+ {0x40930000}, {0x40932000}, {0x40934000}, {0x40936000},
+ {0x40938000}, {0x4093a000}, {0x4093c000}, {0x4093e000},
+ {0x40940000}, {0x40942000}, {0x40944000}, {0x40946000},
+ {0x40948000}, {0x4094a000}, {0x4094c000}, {0x4094e000},
+ {0x40950000}, {0x40952000}, {0x40954000}, {0x40956000},
+ {0x40958000}, {0x4095a000}, {0x4095c000}, {0x4095e000},
+ {0x40960000}, {0x40962000}, {0x40964000}, {0x40966000},
+ {0x40968000}, {0x4096a000}, {0x4096c000}, {0x4096e000},
+ {0x40970000}, {0x40972000}, {0x40974000}, {0x40976000},
+ {0x40978000}, {0x4097a000}, {0x4097c000}, {0x4097e000},
+ {0x40980000}, {0x40982000}, {0x40984000}, {0x40986000},
+ {0x40988000}, {0x4098a000}, {0x4098c000}, {0x4098e000},
+ {0x40990000}, {0x40992000}, {0x40994000}, {0x40996000},
+ {0x40998000}, {0x4099a000}, {0x4099c000}, {0x4099e000},
+ {0x409a0000}, {0x409a2000}, {0x409a4000}, {0x409a6000},
+ {0x409a8000}, {0x409aa000}, {0x409ac000}, {0x409ae000},
+ {0x409b0000}, {0x409b2000}, {0x409b4000}, {0x409b6000},
+ {0x409b8000}, {0x409ba000}, {0x409bc000}, {0x409be000},
+ {0x409c0000}, {0x409c2000}, {0x409c4000}, {0x409c6000},
+ {0x409c8000}, {0x409ca000}, {0x409cc000}, {0x409ce000},
+ {0x409d0000}, {0x409d2000}, {0x409d4000}, {0x409d6000},
+ {0x409d8000}, {0x409da000}, {0x409dc000}, {0x409de000},
+ {0x409e0000}, {0x409e2000}, {0x409e4000}, {0x409e6000},
+ {0x409e8000}, {0x409ea000}, {0x409ec000}, {0x409ee000},
+ {0x409f0000}, {0x409f2000}, {0x409f4000}, {0x409f6000},
+ {0x409f8000}, {0x409fa000}, {0x409fc000}, {0x409fe000},
+ {0x40a00000}, {0x40a02000}, {0x40a04000}, {0x40a06000},
+ {0x40a08000}, {0x40a0a000}, {0x40a0c000}, {0x40a0e000},
+ {0x40a10000}, {0x40a12000}, {0x40a14000}, {0x40a16000},
+ {0x40a18000}, {0x40a1a000}, {0x40a1c000}, {0x40a1e000},
+ {0x40a20000}, {0x40a22000}, {0x40a24000}, {0x40a26000},
+ {0x40a28000}, {0x40a2a000}, {0x40a2c000}, {0x40a2e000},
+ {0x40a30000}, {0x40a32000}, {0x40a34000}, {0x40a36000},
+ {0x40a38000}, {0x40a3a000}, {0x40a3c000}, {0x40a3e000},
+ {0x40a40000}, {0x40a42000}, {0x40a44000}, {0x40a46000},
+ {0x40a48000}, {0x40a4a000}, {0x40a4c000}, {0x40a4e000},
+ {0x40a50000}, {0x40a52000}, {0x40a54000}, {0x40a56000},
+ {0x40a58000}, {0x40a5a000}, {0x40a5c000}, {0x40a5e000},
+ {0x40a60000}, {0x40a62000}, {0x40a64000}, {0x40a66000},
+ {0x40a68000}, {0x40a6a000}, {0x40a6c000}, {0x40a6e000},
+ {0x40a70000}, {0x40a72000}, {0x40a74000}, {0x40a76000},
+ {0x40a78000}, {0x40a7a000}, {0x40a7c000}, {0x40a7e000},
+ {0x40a80000}, {0x40a82000}, {0x40a84000}, {0x40a86000},
+ {0x40a88000}, {0x40a8a000}, {0x40a8c000}, {0x40a8e000},
+ {0x40a90000}, {0x40a92000}, {0x40a94000}, {0x40a96000},
+ {0x40a98000}, {0x40a9a000}, {0x40a9c000}, {0x40a9e000},
+ {0x40aa0000}, {0x40aa2000}, {0x40aa4000}, {0x40aa6000},
+ {0x40aa8000}, {0x40aaa000}, {0x40aac000}, {0x40aae000},
+ {0x40ab0000}, {0x40ab2000}, {0x40ab4000}, {0x40ab6000},
+ {0x40ab8000}, {0x40aba000}, {0x40abc000}, {0x40abe000},
+ {0x40ac0000}, {0x40ac2000}, {0x40ac4000}, {0x40ac6000},
+ {0x40ac8000}, {0x40aca000}, {0x40acc000}, {0x40ace000},
+ {0x40ad0000}, {0x40ad2000}, {0x40ad4000}, {0x40ad6000},
+ {0x40ad8000}, {0x40ada000}, {0x40adc000}, {0x40ade000},
+ {0x40ae0000}, {0x40ae2000}, {0x40ae4000}, {0x40ae6000},
+ {0x40ae8000}, {0x40aea000}, {0x40aec000}, {0x40aee000},
+ {0x40af0000}, {0x40af2000}, {0x40af4000}, {0x40af6000},
+ {0x40af8000}, {0x40afa000}, {0x40afc000}, {0x40afe000},
+ {0x40b00000}, {0x40b02000}, {0x40b04000}, {0x40b06000},
+ {0x40b08000}, {0x40b0a000}, {0x40b0c000}, {0x40b0e000},
+ {0x40b10000}, {0x40b12000}, {0x40b14000}, {0x40b16000},
+ {0x40b18000}, {0x40b1a000}, {0x40b1c000}, {0x40b1e000},
+ {0x40b20000}, {0x40b22000}, {0x40b24000}, {0x40b26000},
+ {0x40b28000}, {0x40b2a000}, {0x40b2c000}, {0x40b2e000},
+ {0x40b30000}, {0x40b32000}, {0x40b34000}, {0x40b36000},
+ {0x40b38000}, {0x40b3a000}, {0x40b3c000}, {0x40b3e000},
+ {0x40b40000}, {0x40b42000}, {0x40b44000}, {0x40b46000},
+ {0x40b48000}, {0x40b4a000}, {0x40b4c000}, {0x40b4e000},
+ {0x40b50000}, {0x40b52000}, {0x40b54000}, {0x40b56000},
+ {0x40b58000}, {0x40b5a000}, {0x40b5c000}, {0x40b5e000},
+ {0x40b60000}, {0x40b62000}, {0x40b64000}, {0x40b66000},
+ {0x40b68000}, {0x40b6a000}, {0x40b6c000}, {0x40b6e000},
+ {0x40b70000}, {0x40b72000}, {0x40b74000}, {0x40b76000},
+ {0x40b78000}, {0x40b7a000}, {0x40b7c000}, {0x40b7e000},
+ {0x40b80000}, {0x40b82000}, {0x40b84000}, {0x40b86000},
+ {0x40b88000}, {0x40b8a000}, {0x40b8c000}, {0x40b8e000},
+ {0x40b90000}, {0x40b92000}, {0x40b94000}, {0x40b96000},
+ {0x40b98000}, {0x40b9a000}, {0x40b9c000}, {0x40b9e000},
+ {0x40ba0000}, {0x40ba2000}, {0x40ba4000}, {0x40ba6000},
+ {0x40ba8000}, {0x40baa000}, {0x40bac000}, {0x40bae000},
+ {0x40bb0000}, {0x40bb2000}, {0x40bb4000}, {0x40bb6000},
+ {0x40bb8000}, {0x40bba000}, {0x40bbc000}, {0x40bbe000},
+ {0x40bc0000}, {0x40bc2000}, {0x40bc4000}, {0x40bc6000},
+ {0x40bc8000}, {0x40bca000}, {0x40bcc000}, {0x40bce000},
+ {0x40bd0000}, {0x40bd2000}, {0x40bd4000}, {0x40bd6000},
+ {0x40bd8000}, {0x40bda000}, {0x40bdc000}, {0x40bde000},
+ {0x40be0000}, {0x40be2000}, {0x40be4000}, {0x40be6000},
+ {0x40be8000}, {0x40bea000}, {0x40bec000}, {0x40bee000},
+ {0x40bf0000}, {0x40bf2000}, {0x40bf4000}, {0x40bf6000},
+ {0x40bf8000}, {0x40bfa000}, {0x40bfc000}, {0x40bfe000},
+ {0x40c00000}, {0x40c02000}, {0x40c04000}, {0x40c06000},
+ {0x40c08000}, {0x40c0a000}, {0x40c0c000}, {0x40c0e000},
+ {0x40c10000}, {0x40c12000}, {0x40c14000}, {0x40c16000},
+ {0x40c18000}, {0x40c1a000}, {0x40c1c000}, {0x40c1e000},
+ {0x40c20000}, {0x40c22000}, {0x40c24000}, {0x40c26000},
+ {0x40c28000}, {0x40c2a000}, {0x40c2c000}, {0x40c2e000},
+ {0x40c30000}, {0x40c32000}, {0x40c34000}, {0x40c36000},
+ {0x40c38000}, {0x40c3a000}, {0x40c3c000}, {0x40c3e000},
+ {0x40c40000}, {0x40c42000}, {0x40c44000}, {0x40c46000},
+ {0x40c48000}, {0x40c4a000}, {0x40c4c000}, {0x40c4e000},
+ {0x40c50000}, {0x40c52000}, {0x40c54000}, {0x40c56000},
+ {0x40c58000}, {0x40c5a000}, {0x40c5c000}, {0x40c5e000},
+ {0x40c60000}, {0x40c62000}, {0x40c64000}, {0x40c66000},
+ {0x40c68000}, {0x40c6a000}, {0x40c6c000}, {0x40c6e000},
+ {0x40c70000}, {0x40c72000}, {0x40c74000}, {0x40c76000},
+ {0x40c78000}, {0x40c7a000}, {0x40c7c000}, {0x40c7e000},
+ {0x40c80000}, {0x40c82000}, {0x40c84000}, {0x40c86000},
+ {0x40c88000}, {0x40c8a000}, {0x40c8c000}, {0x40c8e000},
+ {0x40c90000}, {0x40c92000}, {0x40c94000}, {0x40c96000},
+ {0x40c98000}, {0x40c9a000}, {0x40c9c000}, {0x40c9e000},
+ {0x40ca0000}, {0x40ca2000}, {0x40ca4000}, {0x40ca6000},
+ {0x40ca8000}, {0x40caa000}, {0x40cac000}, {0x40cae000},
+ {0x40cb0000}, {0x40cb2000}, {0x40cb4000}, {0x40cb6000},
+ {0x40cb8000}, {0x40cba000}, {0x40cbc000}, {0x40cbe000},
+ {0x40cc0000}, {0x40cc2000}, {0x40cc4000}, {0x40cc6000},
+ {0x40cc8000}, {0x40cca000}, {0x40ccc000}, {0x40cce000},
+ {0x40cd0000}, {0x40cd2000}, {0x40cd4000}, {0x40cd6000},
+ {0x40cd8000}, {0x40cda000}, {0x40cdc000}, {0x40cde000},
+ {0x40ce0000}, {0x40ce2000}, {0x40ce4000}, {0x40ce6000},
+ {0x40ce8000}, {0x40cea000}, {0x40cec000}, {0x40cee000},
+ {0x40cf0000}, {0x40cf2000}, {0x40cf4000}, {0x40cf6000},
+ {0x40cf8000}, {0x40cfa000}, {0x40cfc000}, {0x40cfe000},
+ {0x40d00000}, {0x40d02000}, {0x40d04000}, {0x40d06000},
+ {0x40d08000}, {0x40d0a000}, {0x40d0c000}, {0x40d0e000},
+ {0x40d10000}, {0x40d12000}, {0x40d14000}, {0x40d16000},
+ {0x40d18000}, {0x40d1a000}, {0x40d1c000}, {0x40d1e000},
+ {0x40d20000}, {0x40d22000}, {0x40d24000}, {0x40d26000},
+ {0x40d28000}, {0x40d2a000}, {0x40d2c000}, {0x40d2e000},
+ {0x40d30000}, {0x40d32000}, {0x40d34000}, {0x40d36000},
+ {0x40d38000}, {0x40d3a000}, {0x40d3c000}, {0x40d3e000},
+ {0x40d40000}, {0x40d42000}, {0x40d44000}, {0x40d46000},
+ {0x40d48000}, {0x40d4a000}, {0x40d4c000}, {0x40d4e000},
+ {0x40d50000}, {0x40d52000}, {0x40d54000}, {0x40d56000},
+ {0x40d58000}, {0x40d5a000}, {0x40d5c000}, {0x40d5e000},
+ {0x40d60000}, {0x40d62000}, {0x40d64000}, {0x40d66000},
+ {0x40d68000}, {0x40d6a000}, {0x40d6c000}, {0x40d6e000},
+ {0x40d70000}, {0x40d72000}, {0x40d74000}, {0x40d76000},
+ {0x40d78000}, {0x40d7a000}, {0x40d7c000}, {0x40d7e000},
+ {0x40d80000}, {0x40d82000}, {0x40d84000}, {0x40d86000},
+ {0x40d88000}, {0x40d8a000}, {0x40d8c000}, {0x40d8e000},
+ {0x40d90000}, {0x40d92000}, {0x40d94000}, {0x40d96000},
+ {0x40d98000}, {0x40d9a000}, {0x40d9c000}, {0x40d9e000},
+ {0x40da0000}, {0x40da2000}, {0x40da4000}, {0x40da6000},
+ {0x40da8000}, {0x40daa000}, {0x40dac000}, {0x40dae000},
+ {0x40db0000}, {0x40db2000}, {0x40db4000}, {0x40db6000},
+ {0x40db8000}, {0x40dba000}, {0x40dbc000}, {0x40dbe000},
+ {0x40dc0000}, {0x40dc2000}, {0x40dc4000}, {0x40dc6000},
+ {0x40dc8000}, {0x40dca000}, {0x40dcc000}, {0x40dce000},
+ {0x40dd0000}, {0x40dd2000}, {0x40dd4000}, {0x40dd6000},
+ {0x40dd8000}, {0x40dda000}, {0x40ddc000}, {0x40dde000},
+ {0x40de0000}, {0x40de2000}, {0x40de4000}, {0x40de6000},
+ {0x40de8000}, {0x40dea000}, {0x40dec000}, {0x40dee000},
+ {0x40df0000}, {0x40df2000}, {0x40df4000}, {0x40df6000},
+ {0x40df8000}, {0x40dfa000}, {0x40dfc000}, {0x40dfe000},
+ {0x40e00000}, {0x40e02000}, {0x40e04000}, {0x40e06000},
+ {0x40e08000}, {0x40e0a000}, {0x40e0c000}, {0x40e0e000},
+ {0x40e10000}, {0x40e12000}, {0x40e14000}, {0x40e16000},
+ {0x40e18000}, {0x40e1a000}, {0x40e1c000}, {0x40e1e000},
+ {0x40e20000}, {0x40e22000}, {0x40e24000}, {0x40e26000},
+ {0x40e28000}, {0x40e2a000}, {0x40e2c000}, {0x40e2e000},
+ {0x40e30000}, {0x40e32000}, {0x40e34000}, {0x40e36000},
+ {0x40e38000}, {0x40e3a000}, {0x40e3c000}, {0x40e3e000},
+ {0x40e40000}, {0x40e42000}, {0x40e44000}, {0x40e46000},
+ {0x40e48000}, {0x40e4a000}, {0x40e4c000}, {0x40e4e000},
+ {0x40e50000}, {0x40e52000}, {0x40e54000}, {0x40e56000},
+ {0x40e58000}, {0x40e5a000}, {0x40e5c000}, {0x40e5e000},
+ {0x40e60000}, {0x40e62000}, {0x40e64000}, {0x40e66000},
+ {0x40e68000}, {0x40e6a000}, {0x40e6c000}, {0x40e6e000},
+ {0x40e70000}, {0x40e72000}, {0x40e74000}, {0x40e76000},
+ {0x40e78000}, {0x40e7a000}, {0x40e7c000}, {0x40e7e000},
+ {0x40e80000}, {0x40e82000}, {0x40e84000}, {0x40e86000},
+ {0x40e88000}, {0x40e8a000}, {0x40e8c000}, {0x40e8e000},
+ {0x40e90000}, {0x40e92000}, {0x40e94000}, {0x40e96000},
+ {0x40e98000}, {0x40e9a000}, {0x40e9c000}, {0x40e9e000},
+ {0x40ea0000}, {0x40ea2000}, {0x40ea4000}, {0x40ea6000},
+ {0x40ea8000}, {0x40eaa000}, {0x40eac000}, {0x40eae000},
+ {0x40eb0000}, {0x40eb2000}, {0x40eb4000}, {0x40eb6000},
+ {0x40eb8000}, {0x40eba000}, {0x40ebc000}, {0x40ebe000},
+ {0x40ec0000}, {0x40ec2000}, {0x40ec4000}, {0x40ec6000},
+ {0x40ec8000}, {0x40eca000}, {0x40ecc000}, {0x40ece000},
+ {0x40ed0000}, {0x40ed2000}, {0x40ed4000}, {0x40ed6000},
+ {0x40ed8000}, {0x40eda000}, {0x40edc000}, {0x40ede000},
+ {0x40ee0000}, {0x40ee2000}, {0x40ee4000}, {0x40ee6000},
+ {0x40ee8000}, {0x40eea000}, {0x40eec000}, {0x40eee000},
+ {0x40ef0000}, {0x40ef2000}, {0x40ef4000}, {0x40ef6000},
+ {0x40ef8000}, {0x40efa000}, {0x40efc000}, {0x40efe000},
+ {0x40f00000}, {0x40f02000}, {0x40f04000}, {0x40f06000},
+ {0x40f08000}, {0x40f0a000}, {0x40f0c000}, {0x40f0e000},
+ {0x40f10000}, {0x40f12000}, {0x40f14000}, {0x40f16000},
+ {0x40f18000}, {0x40f1a000}, {0x40f1c000}, {0x40f1e000},
+ {0x40f20000}, {0x40f22000}, {0x40f24000}, {0x40f26000},
+ {0x40f28000}, {0x40f2a000}, {0x40f2c000}, {0x40f2e000},
+ {0x40f30000}, {0x40f32000}, {0x40f34000}, {0x40f36000},
+ {0x40f38000}, {0x40f3a000}, {0x40f3c000}, {0x40f3e000},
+ {0x40f40000}, {0x40f42000}, {0x40f44000}, {0x40f46000},
+ {0x40f48000}, {0x40f4a000}, {0x40f4c000}, {0x40f4e000},
+ {0x40f50000}, {0x40f52000}, {0x40f54000}, {0x40f56000},
+ {0x40f58000}, {0x40f5a000}, {0x40f5c000}, {0x40f5e000},
+ {0x40f60000}, {0x40f62000}, {0x40f64000}, {0x40f66000},
+ {0x40f68000}, {0x40f6a000}, {0x40f6c000}, {0x40f6e000},
+ {0x40f70000}, {0x40f72000}, {0x40f74000}, {0x40f76000},
+ {0x40f78000}, {0x40f7a000}, {0x40f7c000}, {0x40f7e000},
+ {0x40f80000}, {0x40f82000}, {0x40f84000}, {0x40f86000},
+ {0x40f88000}, {0x40f8a000}, {0x40f8c000}, {0x40f8e000},
+ {0x40f90000}, {0x40f92000}, {0x40f94000}, {0x40f96000},
+ {0x40f98000}, {0x40f9a000}, {0x40f9c000}, {0x40f9e000},
+ {0x40fa0000}, {0x40fa2000}, {0x40fa4000}, {0x40fa6000},
+ {0x40fa8000}, {0x40faa000}, {0x40fac000}, {0x40fae000},
+ {0x40fb0000}, {0x40fb2000}, {0x40fb4000}, {0x40fb6000},
+ {0x40fb8000}, {0x40fba000}, {0x40fbc000}, {0x40fbe000},
+ {0x40fc0000}, {0x40fc2000}, {0x40fc4000}, {0x40fc6000},
+ {0x40fc8000}, {0x40fca000}, {0x40fcc000}, {0x40fce000},
+ {0x40fd0000}, {0x40fd2000}, {0x40fd4000}, {0x40fd6000},
+ {0x40fd8000}, {0x40fda000}, {0x40fdc000}, {0x40fde000},
+ {0x40fe0000}, {0x40fe2000}, {0x40fe4000}, {0x40fe6000},
+ {0x40fe8000}, {0x40fea000}, {0x40fec000}, {0x40fee000},
+ {0x40ff0000}, {0x40ff2000}, {0x40ff4000}, {0x40ff6000},
+ {0x40ff8000}, {0x40ffa000}, {0x40ffc000}, {0x40ffe000},
+ {0x41000000}, {0x41002000}, {0x41004000}, {0x41006000},
+ {0x41008000}, {0x4100a000}, {0x4100c000}, {0x4100e000},
+ {0x41010000}, {0x41012000}, {0x41014000}, {0x41016000},
+ {0x41018000}, {0x4101a000}, {0x4101c000}, {0x4101e000},
+ {0x41020000}, {0x41022000}, {0x41024000}, {0x41026000},
+ {0x41028000}, {0x4102a000}, {0x4102c000}, {0x4102e000},
+ {0x41030000}, {0x41032000}, {0x41034000}, {0x41036000},
+ {0x41038000}, {0x4103a000}, {0x4103c000}, {0x4103e000},
+ {0x41040000}, {0x41042000}, {0x41044000}, {0x41046000},
+ {0x41048000}, {0x4104a000}, {0x4104c000}, {0x4104e000},
+ {0x41050000}, {0x41052000}, {0x41054000}, {0x41056000},
+ {0x41058000}, {0x4105a000}, {0x4105c000}, {0x4105e000},
+ {0x41060000}, {0x41062000}, {0x41064000}, {0x41066000},
+ {0x41068000}, {0x4106a000}, {0x4106c000}, {0x4106e000},
+ {0x41070000}, {0x41072000}, {0x41074000}, {0x41076000},
+ {0x41078000}, {0x4107a000}, {0x4107c000}, {0x4107e000},
+ {0x41080000}, {0x41082000}, {0x41084000}, {0x41086000},
+ {0x41088000}, {0x4108a000}, {0x4108c000}, {0x4108e000},
+ {0x41090000}, {0x41092000}, {0x41094000}, {0x41096000},
+ {0x41098000}, {0x4109a000}, {0x4109c000}, {0x4109e000},
+ {0x410a0000}, {0x410a2000}, {0x410a4000}, {0x410a6000},
+ {0x410a8000}, {0x410aa000}, {0x410ac000}, {0x410ae000},
+ {0x410b0000}, {0x410b2000}, {0x410b4000}, {0x410b6000},
+ {0x410b8000}, {0x410ba000}, {0x410bc000}, {0x410be000},
+ {0x410c0000}, {0x410c2000}, {0x410c4000}, {0x410c6000},
+ {0x410c8000}, {0x410ca000}, {0x410cc000}, {0x410ce000},
+ {0x410d0000}, {0x410d2000}, {0x410d4000}, {0x410d6000},
+ {0x410d8000}, {0x410da000}, {0x410dc000}, {0x410de000},
+ {0x410e0000}, {0x410e2000}, {0x410e4000}, {0x410e6000},
+ {0x410e8000}, {0x410ea000}, {0x410ec000}, {0x410ee000},
+ {0x410f0000}, {0x410f2000}, {0x410f4000}, {0x410f6000},
+ {0x410f8000}, {0x410fa000}, {0x410fc000}, {0x410fe000},
+ {0x41100000}, {0x41102000}, {0x41104000}, {0x41106000},
+ {0x41108000}, {0x4110a000}, {0x4110c000}, {0x4110e000},
+ {0x41110000}, {0x41112000}, {0x41114000}, {0x41116000},
+ {0x41118000}, {0x4111a000}, {0x4111c000}, {0x4111e000},
+ {0x41120000}, {0x41122000}, {0x41124000}, {0x41126000},
+ {0x41128000}, {0x4112a000}, {0x4112c000}, {0x4112e000},
+ {0x41130000}, {0x41132000}, {0x41134000}, {0x41136000},
+ {0x41138000}, {0x4113a000}, {0x4113c000}, {0x4113e000},
+ {0x41140000}, {0x41142000}, {0x41144000}, {0x41146000},
+ {0x41148000}, {0x4114a000}, {0x4114c000}, {0x4114e000},
+ {0x41150000}, {0x41152000}, {0x41154000}, {0x41156000},
+ {0x41158000}, {0x4115a000}, {0x4115c000}, {0x4115e000},
+ {0x41160000}, {0x41162000}, {0x41164000}, {0x41166000},
+ {0x41168000}, {0x4116a000}, {0x4116c000}, {0x4116e000},
+ {0x41170000}, {0x41172000}, {0x41174000}, {0x41176000},
+ {0x41178000}, {0x4117a000}, {0x4117c000}, {0x4117e000},
+ {0x41180000}, {0x41182000}, {0x41184000}, {0x41186000},
+ {0x41188000}, {0x4118a000}, {0x4118c000}, {0x4118e000},
+ {0x41190000}, {0x41192000}, {0x41194000}, {0x41196000},
+ {0x41198000}, {0x4119a000}, {0x4119c000}, {0x4119e000},
+ {0x411a0000}, {0x411a2000}, {0x411a4000}, {0x411a6000},
+ {0x411a8000}, {0x411aa000}, {0x411ac000}, {0x411ae000},
+ {0x411b0000}, {0x411b2000}, {0x411b4000}, {0x411b6000},
+ {0x411b8000}, {0x411ba000}, {0x411bc000}, {0x411be000},
+ {0x411c0000}, {0x411c2000}, {0x411c4000}, {0x411c6000},
+ {0x411c8000}, {0x411ca000}, {0x411cc000}, {0x411ce000},
+ {0x411d0000}, {0x411d2000}, {0x411d4000}, {0x411d6000},
+ {0x411d8000}, {0x411da000}, {0x411dc000}, {0x411de000},
+ {0x411e0000}, {0x411e2000}, {0x411e4000}, {0x411e6000},
+ {0x411e8000}, {0x411ea000}, {0x411ec000}, {0x411ee000},
+ {0x411f0000}, {0x411f2000}, {0x411f4000}, {0x411f6000},
+ {0x411f8000}, {0x411fa000}, {0x411fc000}, {0x411fe000},
+ {0x41200000}, {0x41202000}, {0x41204000}, {0x41206000},
+ {0x41208000}, {0x4120a000}, {0x4120c000}, {0x4120e000},
+ {0x41210000}, {0x41212000}, {0x41214000}, {0x41216000},
+ {0x41218000}, {0x4121a000}, {0x4121c000}, {0x4121e000},
+ {0x41220000}, {0x41222000}, {0x41224000}, {0x41226000},
+ {0x41228000}, {0x4122a000}, {0x4122c000}, {0x4122e000},
+ {0x41230000}, {0x41232000}, {0x41234000}, {0x41236000},
+ {0x41238000}, {0x4123a000}, {0x4123c000}, {0x4123e000},
+ {0x41240000}, {0x41242000}, {0x41244000}, {0x41246000},
+ {0x41248000}, {0x4124a000}, {0x4124c000}, {0x4124e000},
+ {0x41250000}, {0x41252000}, {0x41254000}, {0x41256000},
+ {0x41258000}, {0x4125a000}, {0x4125c000}, {0x4125e000},
+ {0x41260000}, {0x41262000}, {0x41264000}, {0x41266000},
+ {0x41268000}, {0x4126a000}, {0x4126c000}, {0x4126e000},
+ {0x41270000}, {0x41272000}, {0x41274000}, {0x41276000},
+ {0x41278000}, {0x4127a000}, {0x4127c000}, {0x4127e000},
+ {0x41280000}, {0x41282000}, {0x41284000}, {0x41286000},
+ {0x41288000}, {0x4128a000}, {0x4128c000}, {0x4128e000},
+ {0x41290000}, {0x41292000}, {0x41294000}, {0x41296000},
+ {0x41298000}, {0x4129a000}, {0x4129c000}, {0x4129e000},
+ {0x412a0000}, {0x412a2000}, {0x412a4000}, {0x412a6000},
+ {0x412a8000}, {0x412aa000}, {0x412ac000}, {0x412ae000},
+ {0x412b0000}, {0x412b2000}, {0x412b4000}, {0x412b6000},
+ {0x412b8000}, {0x412ba000}, {0x412bc000}, {0x412be000},
+ {0x412c0000}, {0x412c2000}, {0x412c4000}, {0x412c6000},
+ {0x412c8000}, {0x412ca000}, {0x412cc000}, {0x412ce000},
+ {0x412d0000}, {0x412d2000}, {0x412d4000}, {0x412d6000},
+ {0x412d8000}, {0x412da000}, {0x412dc000}, {0x412de000},
+ {0x412e0000}, {0x412e2000}, {0x412e4000}, {0x412e6000},
+ {0x412e8000}, {0x412ea000}, {0x412ec000}, {0x412ee000},
+ {0x412f0000}, {0x412f2000}, {0x412f4000}, {0x412f6000},
+ {0x412f8000}, {0x412fa000}, {0x412fc000}, {0x412fe000},
+ {0x41300000}, {0x41302000}, {0x41304000}, {0x41306000},
+ {0x41308000}, {0x4130a000}, {0x4130c000}, {0x4130e000},
+ {0x41310000}, {0x41312000}, {0x41314000}, {0x41316000},
+ {0x41318000}, {0x4131a000}, {0x4131c000}, {0x4131e000},
+ {0x41320000}, {0x41322000}, {0x41324000}, {0x41326000},
+ {0x41328000}, {0x4132a000}, {0x4132c000}, {0x4132e000},
+ {0x41330000}, {0x41332000}, {0x41334000}, {0x41336000},
+ {0x41338000}, {0x4133a000}, {0x4133c000}, {0x4133e000},
+ {0x41340000}, {0x41342000}, {0x41344000}, {0x41346000},
+ {0x41348000}, {0x4134a000}, {0x4134c000}, {0x4134e000},
+ {0x41350000}, {0x41352000}, {0x41354000}, {0x41356000},
+ {0x41358000}, {0x4135a000}, {0x4135c000}, {0x4135e000},
+ {0x41360000}, {0x41362000}, {0x41364000}, {0x41366000},
+ {0x41368000}, {0x4136a000}, {0x4136c000}, {0x4136e000},
+ {0x41370000}, {0x41372000}, {0x41374000}, {0x41376000},
+ {0x41378000}, {0x4137a000}, {0x4137c000}, {0x4137e000},
+ {0x41380000}, {0x41382000}, {0x41384000}, {0x41386000},
+ {0x41388000}, {0x4138a000}, {0x4138c000}, {0x4138e000},
+ {0x41390000}, {0x41392000}, {0x41394000}, {0x41396000},
+ {0x41398000}, {0x4139a000}, {0x4139c000}, {0x4139e000},
+ {0x413a0000}, {0x413a2000}, {0x413a4000}, {0x413a6000},
+ {0x413a8000}, {0x413aa000}, {0x413ac000}, {0x413ae000},
+ {0x413b0000}, {0x413b2000}, {0x413b4000}, {0x413b6000},
+ {0x413b8000}, {0x413ba000}, {0x413bc000}, {0x413be000},
+ {0x413c0000}, {0x413c2000}, {0x413c4000}, {0x413c6000},
+ {0x413c8000}, {0x413ca000}, {0x413cc000}, {0x413ce000},
+ {0x413d0000}, {0x413d2000}, {0x413d4000}, {0x413d6000},
+ {0x413d8000}, {0x413da000}, {0x413dc000}, {0x413de000},
+ {0x413e0000}, {0x413e2000}, {0x413e4000}, {0x413e6000},
+ {0x413e8000}, {0x413ea000}, {0x413ec000}, {0x413ee000},
+ {0x413f0000}, {0x413f2000}, {0x413f4000}, {0x413f6000},
+ {0x413f8000}, {0x413fa000}, {0x413fc000}, {0x413fe000},
+ {0x41400000}, {0x41402000}, {0x41404000}, {0x41406000},
+ {0x41408000}, {0x4140a000}, {0x4140c000}, {0x4140e000},
+ {0x41410000}, {0x41412000}, {0x41414000}, {0x41416000},
+ {0x41418000}, {0x4141a000}, {0x4141c000}, {0x4141e000},
+ {0x41420000}, {0x41422000}, {0x41424000}, {0x41426000},
+ {0x41428000}, {0x4142a000}, {0x4142c000}, {0x4142e000},
+ {0x41430000}, {0x41432000}, {0x41434000}, {0x41436000},
+ {0x41438000}, {0x4143a000}, {0x4143c000}, {0x4143e000},
+ {0x41440000}, {0x41442000}, {0x41444000}, {0x41446000},
+ {0x41448000}, {0x4144a000}, {0x4144c000}, {0x4144e000},
+ {0x41450000}, {0x41452000}, {0x41454000}, {0x41456000},
+ {0x41458000}, {0x4145a000}, {0x4145c000}, {0x4145e000},
+ {0x41460000}, {0x41462000}, {0x41464000}, {0x41466000},
+ {0x41468000}, {0x4146a000}, {0x4146c000}, {0x4146e000},
+ {0x41470000}, {0x41472000}, {0x41474000}, {0x41476000},
+ {0x41478000}, {0x4147a000}, {0x4147c000}, {0x4147e000},
+ {0x41480000}, {0x41482000}, {0x41484000}, {0x41486000},
+ {0x41488000}, {0x4148a000}, {0x4148c000}, {0x4148e000},
+ {0x41490000}, {0x41492000}, {0x41494000}, {0x41496000},
+ {0x41498000}, {0x4149a000}, {0x4149c000}, {0x4149e000},
+ {0x414a0000}, {0x414a2000}, {0x414a4000}, {0x414a6000},
+ {0x414a8000}, {0x414aa000}, {0x414ac000}, {0x414ae000},
+ {0x414b0000}, {0x414b2000}, {0x414b4000}, {0x414b6000},
+ {0x414b8000}, {0x414ba000}, {0x414bc000}, {0x414be000},
+ {0x414c0000}, {0x414c2000}, {0x414c4000}, {0x414c6000},
+ {0x414c8000}, {0x414ca000}, {0x414cc000}, {0x414ce000},
+ {0x414d0000}, {0x414d2000}, {0x414d4000}, {0x414d6000},
+ {0x414d8000}, {0x414da000}, {0x414dc000}, {0x414de000},
+ {0x414e0000}, {0x414e2000}, {0x414e4000}, {0x414e6000},
+ {0x414e8000}, {0x414ea000}, {0x414ec000}, {0x414ee000},
+ {0x414f0000}, {0x414f2000}, {0x414f4000}, {0x414f6000},
+ {0x414f8000}, {0x414fa000}, {0x414fc000}, {0x414fe000},
+ {0x41500000}, {0x41502000}, {0x41504000}, {0x41506000},
+ {0x41508000}, {0x4150a000}, {0x4150c000}, {0x4150e000},
+ {0x41510000}, {0x41512000}, {0x41514000}, {0x41516000},
+ {0x41518000}, {0x4151a000}, {0x4151c000}, {0x4151e000},
+ {0x41520000}, {0x41522000}, {0x41524000}, {0x41526000},
+ {0x41528000}, {0x4152a000}, {0x4152c000}, {0x4152e000},
+ {0x41530000}, {0x41532000}, {0x41534000}, {0x41536000},
+ {0x41538000}, {0x4153a000}, {0x4153c000}, {0x4153e000},
+ {0x41540000}, {0x41542000}, {0x41544000}, {0x41546000},
+ {0x41548000}, {0x4154a000}, {0x4154c000}, {0x4154e000},
+ {0x41550000}, {0x41552000}, {0x41554000}, {0x41556000},
+ {0x41558000}, {0x4155a000}, {0x4155c000}, {0x4155e000},
+ {0x41560000}, {0x41562000}, {0x41564000}, {0x41566000},
+ {0x41568000}, {0x4156a000}, {0x4156c000}, {0x4156e000},
+ {0x41570000}, {0x41572000}, {0x41574000}, {0x41576000},
+ {0x41578000}, {0x4157a000}, {0x4157c000}, {0x4157e000},
+ {0x41580000}, {0x41582000}, {0x41584000}, {0x41586000},
+ {0x41588000}, {0x4158a000}, {0x4158c000}, {0x4158e000},
+ {0x41590000}, {0x41592000}, {0x41594000}, {0x41596000},
+ {0x41598000}, {0x4159a000}, {0x4159c000}, {0x4159e000},
+ {0x415a0000}, {0x415a2000}, {0x415a4000}, {0x415a6000},
+ {0x415a8000}, {0x415aa000}, {0x415ac000}, {0x415ae000},
+ {0x415b0000}, {0x415b2000}, {0x415b4000}, {0x415b6000},
+ {0x415b8000}, {0x415ba000}, {0x415bc000}, {0x415be000},
+ {0x415c0000}, {0x415c2000}, {0x415c4000}, {0x415c6000},
+ {0x415c8000}, {0x415ca000}, {0x415cc000}, {0x415ce000},
+ {0x415d0000}, {0x415d2000}, {0x415d4000}, {0x415d6000},
+ {0x415d8000}, {0x415da000}, {0x415dc000}, {0x415de000},
+ {0x415e0000}, {0x415e2000}, {0x415e4000}, {0x415e6000},
+ {0x415e8000}, {0x415ea000}, {0x415ec000}, {0x415ee000},
+ {0x415f0000}, {0x415f2000}, {0x415f4000}, {0x415f6000},
+ {0x415f8000}, {0x415fa000}, {0x415fc000}, {0x415fe000},
+ {0x41600000}, {0x41602000}, {0x41604000}, {0x41606000},
+ {0x41608000}, {0x4160a000}, {0x4160c000}, {0x4160e000},
+ {0x41610000}, {0x41612000}, {0x41614000}, {0x41616000},
+ {0x41618000}, {0x4161a000}, {0x4161c000}, {0x4161e000},
+ {0x41620000}, {0x41622000}, {0x41624000}, {0x41626000},
+ {0x41628000}, {0x4162a000}, {0x4162c000}, {0x4162e000},
+ {0x41630000}, {0x41632000}, {0x41634000}, {0x41636000},
+ {0x41638000}, {0x4163a000}, {0x4163c000}, {0x4163e000},
+ {0x41640000}, {0x41642000}, {0x41644000}, {0x41646000},
+ {0x41648000}, {0x4164a000}, {0x4164c000}, {0x4164e000},
+ {0x41650000}, {0x41652000}, {0x41654000}, {0x41656000},
+ {0x41658000}, {0x4165a000}, {0x4165c000}, {0x4165e000},
+ {0x41660000}, {0x41662000}, {0x41664000}, {0x41666000},
+ {0x41668000}, {0x4166a000}, {0x4166c000}, {0x4166e000},
+ {0x41670000}, {0x41672000}, {0x41674000}, {0x41676000},
+ {0x41678000}, {0x4167a000}, {0x4167c000}, {0x4167e000},
+ {0x41680000}, {0x41682000}, {0x41684000}, {0x41686000},
+ {0x41688000}, {0x4168a000}, {0x4168c000}, {0x4168e000},
+ {0x41690000}, {0x41692000}, {0x41694000}, {0x41696000},
+ {0x41698000}, {0x4169a000}, {0x4169c000}, {0x4169e000},
+ {0x416a0000}, {0x416a2000}, {0x416a4000}, {0x416a6000},
+ {0x416a8000}, {0x416aa000}, {0x416ac000}, {0x416ae000},
+ {0x416b0000}, {0x416b2000}, {0x416b4000}, {0x416b6000},
+ {0x416b8000}, {0x416ba000}, {0x416bc000}, {0x416be000},
+ {0x416c0000}, {0x416c2000}, {0x416c4000}, {0x416c6000},
+ {0x416c8000}, {0x416ca000}, {0x416cc000}, {0x416ce000},
+ {0x416d0000}, {0x416d2000}, {0x416d4000}, {0x416d6000},
+ {0x416d8000}, {0x416da000}, {0x416dc000}, {0x416de000},
+ {0x416e0000}, {0x416e2000}, {0x416e4000}, {0x416e6000},
+ {0x416e8000}, {0x416ea000}, {0x416ec000}, {0x416ee000},
+ {0x416f0000}, {0x416f2000}, {0x416f4000}, {0x416f6000},
+ {0x416f8000}, {0x416fa000}, {0x416fc000}, {0x416fe000},
+ {0x41700000}, {0x41702000}, {0x41704000}, {0x41706000},
+ {0x41708000}, {0x4170a000}, {0x4170c000}, {0x4170e000},
+ {0x41710000}, {0x41712000}, {0x41714000}, {0x41716000},
+ {0x41718000}, {0x4171a000}, {0x4171c000}, {0x4171e000},
+ {0x41720000}, {0x41722000}, {0x41724000}, {0x41726000},
+ {0x41728000}, {0x4172a000}, {0x4172c000}, {0x4172e000},
+ {0x41730000}, {0x41732000}, {0x41734000}, {0x41736000},
+ {0x41738000}, {0x4173a000}, {0x4173c000}, {0x4173e000},
+ {0x41740000}, {0x41742000}, {0x41744000}, {0x41746000},
+ {0x41748000}, {0x4174a000}, {0x4174c000}, {0x4174e000},
+ {0x41750000}, {0x41752000}, {0x41754000}, {0x41756000},
+ {0x41758000}, {0x4175a000}, {0x4175c000}, {0x4175e000},
+ {0x41760000}, {0x41762000}, {0x41764000}, {0x41766000},
+ {0x41768000}, {0x4176a000}, {0x4176c000}, {0x4176e000},
+ {0x41770000}, {0x41772000}, {0x41774000}, {0x41776000},
+ {0x41778000}, {0x4177a000}, {0x4177c000}, {0x4177e000},
+ {0x41780000}, {0x41782000}, {0x41784000}, {0x41786000},
+ {0x41788000}, {0x4178a000}, {0x4178c000}, {0x4178e000},
+ {0x41790000}, {0x41792000}, {0x41794000}, {0x41796000},
+ {0x41798000}, {0x4179a000}, {0x4179c000}, {0x4179e000},
+ {0x417a0000}, {0x417a2000}, {0x417a4000}, {0x417a6000},
+ {0x417a8000}, {0x417aa000}, {0x417ac000}, {0x417ae000},
+ {0x417b0000}, {0x417b2000}, {0x417b4000}, {0x417b6000},
+ {0x417b8000}, {0x417ba000}, {0x417bc000}, {0x417be000},
+ {0x417c0000}, {0x417c2000}, {0x417c4000}, {0x417c6000},
+ {0x417c8000}, {0x417ca000}, {0x417cc000}, {0x417ce000},
+ {0x417d0000}, {0x417d2000}, {0x417d4000}, {0x417d6000},
+ {0x417d8000}, {0x417da000}, {0x417dc000}, {0x417de000},
+ {0x417e0000}, {0x417e2000}, {0x417e4000}, {0x417e6000},
+ {0x417e8000}, {0x417ea000}, {0x417ec000}, {0x417ee000},
+ {0x417f0000}, {0x417f2000}, {0x417f4000}, {0x417f6000},
+ {0x417f8000}, {0x417fa000}, {0x417fc000}, {0x417fe000},
+ {0x41800000}, {0x41802000}, {0x41804000}, {0x41806000},
+ {0x41808000}, {0x4180a000}, {0x4180c000}, {0x4180e000},
+ {0x41810000}, {0x41812000}, {0x41814000}, {0x41816000},
+ {0x41818000}, {0x4181a000}, {0x4181c000}, {0x4181e000},
+ {0x41820000}, {0x41822000}, {0x41824000}, {0x41826000},
+ {0x41828000}, {0x4182a000}, {0x4182c000}, {0x4182e000},
+ {0x41830000}, {0x41832000}, {0x41834000}, {0x41836000},
+ {0x41838000}, {0x4183a000}, {0x4183c000}, {0x4183e000},
+ {0x41840000}, {0x41842000}, {0x41844000}, {0x41846000},
+ {0x41848000}, {0x4184a000}, {0x4184c000}, {0x4184e000},
+ {0x41850000}, {0x41852000}, {0x41854000}, {0x41856000},
+ {0x41858000}, {0x4185a000}, {0x4185c000}, {0x4185e000},
+ {0x41860000}, {0x41862000}, {0x41864000}, {0x41866000},
+ {0x41868000}, {0x4186a000}, {0x4186c000}, {0x4186e000},
+ {0x41870000}, {0x41872000}, {0x41874000}, {0x41876000},
+ {0x41878000}, {0x4187a000}, {0x4187c000}, {0x4187e000},
+ {0x41880000}, {0x41882000}, {0x41884000}, {0x41886000},
+ {0x41888000}, {0x4188a000}, {0x4188c000}, {0x4188e000},
+ {0x41890000}, {0x41892000}, {0x41894000}, {0x41896000},
+ {0x41898000}, {0x4189a000}, {0x4189c000}, {0x4189e000},
+ {0x418a0000}, {0x418a2000}, {0x418a4000}, {0x418a6000},
+ {0x418a8000}, {0x418aa000}, {0x418ac000}, {0x418ae000},
+ {0x418b0000}, {0x418b2000}, {0x418b4000}, {0x418b6000},
+ {0x418b8000}, {0x418ba000}, {0x418bc000}, {0x418be000},
+ {0x418c0000}, {0x418c2000}, {0x418c4000}, {0x418c6000},
+ {0x418c8000}, {0x418ca000}, {0x418cc000}, {0x418ce000},
+ {0x418d0000}, {0x418d2000}, {0x418d4000}, {0x418d6000},
+ {0x418d8000}, {0x418da000}, {0x418dc000}, {0x418de000},
+ {0x418e0000}, {0x418e2000}, {0x418e4000}, {0x418e6000},
+ {0x418e8000}, {0x418ea000}, {0x418ec000}, {0x418ee000},
+ {0x418f0000}, {0x418f2000}, {0x418f4000}, {0x418f6000},
+ {0x418f8000}, {0x418fa000}, {0x418fc000}, {0x418fe000},
+ {0x41900000}, {0x41902000}, {0x41904000}, {0x41906000},
+ {0x41908000}, {0x4190a000}, {0x4190c000}, {0x4190e000},
+ {0x41910000}, {0x41912000}, {0x41914000}, {0x41916000},
+ {0x41918000}, {0x4191a000}, {0x4191c000}, {0x4191e000},
+ {0x41920000}, {0x41922000}, {0x41924000}, {0x41926000},
+ {0x41928000}, {0x4192a000}, {0x4192c000}, {0x4192e000},
+ {0x41930000}, {0x41932000}, {0x41934000}, {0x41936000},
+ {0x41938000}, {0x4193a000}, {0x4193c000}, {0x4193e000},
+ {0x41940000}, {0x41942000}, {0x41944000}, {0x41946000},
+ {0x41948000}, {0x4194a000}, {0x4194c000}, {0x4194e000},
+ {0x41950000}, {0x41952000}, {0x41954000}, {0x41956000},
+ {0x41958000}, {0x4195a000}, {0x4195c000}, {0x4195e000},
+ {0x41960000}, {0x41962000}, {0x41964000}, {0x41966000},
+ {0x41968000}, {0x4196a000}, {0x4196c000}, {0x4196e000},
+ {0x41970000}, {0x41972000}, {0x41974000}, {0x41976000},
+ {0x41978000}, {0x4197a000}, {0x4197c000}, {0x4197e000},
+ {0x41980000}, {0x41982000}, {0x41984000}, {0x41986000},
+ {0x41988000}, {0x4198a000}, {0x4198c000}, {0x4198e000},
+ {0x41990000}, {0x41992000}, {0x41994000}, {0x41996000},
+ {0x41998000}, {0x4199a000}, {0x4199c000}, {0x4199e000},
+ {0x419a0000}, {0x419a2000}, {0x419a4000}, {0x419a6000},
+ {0x419a8000}, {0x419aa000}, {0x419ac000}, {0x419ae000},
+ {0x419b0000}, {0x419b2000}, {0x419b4000}, {0x419b6000},
+ {0x419b8000}, {0x419ba000}, {0x419bc000}, {0x419be000},
+ {0x419c0000}, {0x419c2000}, {0x419c4000}, {0x419c6000},
+ {0x419c8000}, {0x419ca000}, {0x419cc000}, {0x419ce000},
+ {0x419d0000}, {0x419d2000}, {0x419d4000}, {0x419d6000},
+ {0x419d8000}, {0x419da000}, {0x419dc000}, {0x419de000},
+ {0x419e0000}, {0x419e2000}, {0x419e4000}, {0x419e6000},
+ {0x419e8000}, {0x419ea000}, {0x419ec000}, {0x419ee000},
+ {0x419f0000}, {0x419f2000}, {0x419f4000}, {0x419f6000},
+ {0x419f8000}, {0x419fa000}, {0x419fc000}, {0x419fe000},
+ {0x41a00000}, {0x41a02000}, {0x41a04000}, {0x41a06000},
+ {0x41a08000}, {0x41a0a000}, {0x41a0c000}, {0x41a0e000},
+ {0x41a10000}, {0x41a12000}, {0x41a14000}, {0x41a16000},
+ {0x41a18000}, {0x41a1a000}, {0x41a1c000}, {0x41a1e000},
+ {0x41a20000}, {0x41a22000}, {0x41a24000}, {0x41a26000},
+ {0x41a28000}, {0x41a2a000}, {0x41a2c000}, {0x41a2e000},
+ {0x41a30000}, {0x41a32000}, {0x41a34000}, {0x41a36000},
+ {0x41a38000}, {0x41a3a000}, {0x41a3c000}, {0x41a3e000},
+ {0x41a40000}, {0x41a42000}, {0x41a44000}, {0x41a46000},
+ {0x41a48000}, {0x41a4a000}, {0x41a4c000}, {0x41a4e000},
+ {0x41a50000}, {0x41a52000}, {0x41a54000}, {0x41a56000},
+ {0x41a58000}, {0x41a5a000}, {0x41a5c000}, {0x41a5e000},
+ {0x41a60000}, {0x41a62000}, {0x41a64000}, {0x41a66000},
+ {0x41a68000}, {0x41a6a000}, {0x41a6c000}, {0x41a6e000},
+ {0x41a70000}, {0x41a72000}, {0x41a74000}, {0x41a76000},
+ {0x41a78000}, {0x41a7a000}, {0x41a7c000}, {0x41a7e000},
+ {0x41a80000}, {0x41a82000}, {0x41a84000}, {0x41a86000},
+ {0x41a88000}, {0x41a8a000}, {0x41a8c000}, {0x41a8e000},
+ {0x41a90000}, {0x41a92000}, {0x41a94000}, {0x41a96000},
+ {0x41a98000}, {0x41a9a000}, {0x41a9c000}, {0x41a9e000},
+ {0x41aa0000}, {0x41aa2000}, {0x41aa4000}, {0x41aa6000},
+ {0x41aa8000}, {0x41aaa000}, {0x41aac000}, {0x41aae000},
+ {0x41ab0000}, {0x41ab2000}, {0x41ab4000}, {0x41ab6000},
+ {0x41ab8000}, {0x41aba000}, {0x41abc000}, {0x41abe000},
+ {0x41ac0000}, {0x41ac2000}, {0x41ac4000}, {0x41ac6000},
+ {0x41ac8000}, {0x41aca000}, {0x41acc000}, {0x41ace000},
+ {0x41ad0000}, {0x41ad2000}, {0x41ad4000}, {0x41ad6000},
+ {0x41ad8000}, {0x41ada000}, {0x41adc000}, {0x41ade000},
+ {0x41ae0000}, {0x41ae2000}, {0x41ae4000}, {0x41ae6000},
+ {0x41ae8000}, {0x41aea000}, {0x41aec000}, {0x41aee000},
+ {0x41af0000}, {0x41af2000}, {0x41af4000}, {0x41af6000},
+ {0x41af8000}, {0x41afa000}, {0x41afc000}, {0x41afe000},
+ {0x41b00000}, {0x41b02000}, {0x41b04000}, {0x41b06000},
+ {0x41b08000}, {0x41b0a000}, {0x41b0c000}, {0x41b0e000},
+ {0x41b10000}, {0x41b12000}, {0x41b14000}, {0x41b16000},
+ {0x41b18000}, {0x41b1a000}, {0x41b1c000}, {0x41b1e000},
+ {0x41b20000}, {0x41b22000}, {0x41b24000}, {0x41b26000},
+ {0x41b28000}, {0x41b2a000}, {0x41b2c000}, {0x41b2e000},
+ {0x41b30000}, {0x41b32000}, {0x41b34000}, {0x41b36000},
+ {0x41b38000}, {0x41b3a000}, {0x41b3c000}, {0x41b3e000},
+ {0x41b40000}, {0x41b42000}, {0x41b44000}, {0x41b46000},
+ {0x41b48000}, {0x41b4a000}, {0x41b4c000}, {0x41b4e000},
+ {0x41b50000}, {0x41b52000}, {0x41b54000}, {0x41b56000},
+ {0x41b58000}, {0x41b5a000}, {0x41b5c000}, {0x41b5e000},
+ {0x41b60000}, {0x41b62000}, {0x41b64000}, {0x41b66000},
+ {0x41b68000}, {0x41b6a000}, {0x41b6c000}, {0x41b6e000},
+ {0x41b70000}, {0x41b72000}, {0x41b74000}, {0x41b76000},
+ {0x41b78000}, {0x41b7a000}, {0x41b7c000}, {0x41b7e000},
+ {0x41b80000}, {0x41b82000}, {0x41b84000}, {0x41b86000},
+ {0x41b88000}, {0x41b8a000}, {0x41b8c000}, {0x41b8e000},
+ {0x41b90000}, {0x41b92000}, {0x41b94000}, {0x41b96000},
+ {0x41b98000}, {0x41b9a000}, {0x41b9c000}, {0x41b9e000},
+ {0x41ba0000}, {0x41ba2000}, {0x41ba4000}, {0x41ba6000},
+ {0x41ba8000}, {0x41baa000}, {0x41bac000}, {0x41bae000},
+ {0x41bb0000}, {0x41bb2000}, {0x41bb4000}, {0x41bb6000},
+ {0x41bb8000}, {0x41bba000}, {0x41bbc000}, {0x41bbe000},
+ {0x41bc0000}, {0x41bc2000}, {0x41bc4000}, {0x41bc6000},
+ {0x41bc8000}, {0x41bca000}, {0x41bcc000}, {0x41bce000},
+ {0x41bd0000}, {0x41bd2000}, {0x41bd4000}, {0x41bd6000},
+ {0x41bd8000}, {0x41bda000}, {0x41bdc000}, {0x41bde000},
+ {0x41be0000}, {0x41be2000}, {0x41be4000}, {0x41be6000},
+ {0x41be8000}, {0x41bea000}, {0x41bec000}, {0x41bee000},
+ {0x41bf0000}, {0x41bf2000}, {0x41bf4000}, {0x41bf6000},
+ {0x41bf8000}, {0x41bfa000}, {0x41bfc000}, {0x41bfe000},
+ {0x41c00000}, {0x41c02000}, {0x41c04000}, {0x41c06000},
+ {0x41c08000}, {0x41c0a000}, {0x41c0c000}, {0x41c0e000},
+ {0x41c10000}, {0x41c12000}, {0x41c14000}, {0x41c16000},
+ {0x41c18000}, {0x41c1a000}, {0x41c1c000}, {0x41c1e000},
+ {0x41c20000}, {0x41c22000}, {0x41c24000}, {0x41c26000},
+ {0x41c28000}, {0x41c2a000}, {0x41c2c000}, {0x41c2e000},
+ {0x41c30000}, {0x41c32000}, {0x41c34000}, {0x41c36000},
+ {0x41c38000}, {0x41c3a000}, {0x41c3c000}, {0x41c3e000},
+ {0x41c40000}, {0x41c42000}, {0x41c44000}, {0x41c46000},
+ {0x41c48000}, {0x41c4a000}, {0x41c4c000}, {0x41c4e000},
+ {0x41c50000}, {0x41c52000}, {0x41c54000}, {0x41c56000},
+ {0x41c58000}, {0x41c5a000}, {0x41c5c000}, {0x41c5e000},
+ {0x41c60000}, {0x41c62000}, {0x41c64000}, {0x41c66000},
+ {0x41c68000}, {0x41c6a000}, {0x41c6c000}, {0x41c6e000},
+ {0x41c70000}, {0x41c72000}, {0x41c74000}, {0x41c76000},
+ {0x41c78000}, {0x41c7a000}, {0x41c7c000}, {0x41c7e000},
+ {0x41c80000}, {0x41c82000}, {0x41c84000}, {0x41c86000},
+ {0x41c88000}, {0x41c8a000}, {0x41c8c000}, {0x41c8e000},
+ {0x41c90000}, {0x41c92000}, {0x41c94000}, {0x41c96000},
+ {0x41c98000}, {0x41c9a000}, {0x41c9c000}, {0x41c9e000},
+ {0x41ca0000}, {0x41ca2000}, {0x41ca4000}, {0x41ca6000},
+ {0x41ca8000}, {0x41caa000}, {0x41cac000}, {0x41cae000},
+ {0x41cb0000}, {0x41cb2000}, {0x41cb4000}, {0x41cb6000},
+ {0x41cb8000}, {0x41cba000}, {0x41cbc000}, {0x41cbe000},
+ {0x41cc0000}, {0x41cc2000}, {0x41cc4000}, {0x41cc6000},
+ {0x41cc8000}, {0x41cca000}, {0x41ccc000}, {0x41cce000},
+ {0x41cd0000}, {0x41cd2000}, {0x41cd4000}, {0x41cd6000},
+ {0x41cd8000}, {0x41cda000}, {0x41cdc000}, {0x41cde000},
+ {0x41ce0000}, {0x41ce2000}, {0x41ce4000}, {0x41ce6000},
+ {0x41ce8000}, {0x41cea000}, {0x41cec000}, {0x41cee000},
+ {0x41cf0000}, {0x41cf2000}, {0x41cf4000}, {0x41cf6000},
+ {0x41cf8000}, {0x41cfa000}, {0x41cfc000}, {0x41cfe000},
+ {0x41d00000}, {0x41d02000}, {0x41d04000}, {0x41d06000},
+ {0x41d08000}, {0x41d0a000}, {0x41d0c000}, {0x41d0e000},
+ {0x41d10000}, {0x41d12000}, {0x41d14000}, {0x41d16000},
+ {0x41d18000}, {0x41d1a000}, {0x41d1c000}, {0x41d1e000},
+ {0x41d20000}, {0x41d22000}, {0x41d24000}, {0x41d26000},
+ {0x41d28000}, {0x41d2a000}, {0x41d2c000}, {0x41d2e000},
+ {0x41d30000}, {0x41d32000}, {0x41d34000}, {0x41d36000},
+ {0x41d38000}, {0x41d3a000}, {0x41d3c000}, {0x41d3e000},
+ {0x41d40000}, {0x41d42000}, {0x41d44000}, {0x41d46000},
+ {0x41d48000}, {0x41d4a000}, {0x41d4c000}, {0x41d4e000},
+ {0x41d50000}, {0x41d52000}, {0x41d54000}, {0x41d56000},
+ {0x41d58000}, {0x41d5a000}, {0x41d5c000}, {0x41d5e000},
+ {0x41d60000}, {0x41d62000}, {0x41d64000}, {0x41d66000},
+ {0x41d68000}, {0x41d6a000}, {0x41d6c000}, {0x41d6e000},
+ {0x41d70000}, {0x41d72000}, {0x41d74000}, {0x41d76000},
+ {0x41d78000}, {0x41d7a000}, {0x41d7c000}, {0x41d7e000},
+ {0x41d80000}, {0x41d82000}, {0x41d84000}, {0x41d86000},
+ {0x41d88000}, {0x41d8a000}, {0x41d8c000}, {0x41d8e000},
+ {0x41d90000}, {0x41d92000}, {0x41d94000}, {0x41d96000},
+ {0x41d98000}, {0x41d9a000}, {0x41d9c000}, {0x41d9e000},
+ {0x41da0000}, {0x41da2000}, {0x41da4000}, {0x41da6000},
+ {0x41da8000}, {0x41daa000}, {0x41dac000}, {0x41dae000},
+ {0x41db0000}, {0x41db2000}, {0x41db4000}, {0x41db6000},
+ {0x41db8000}, {0x41dba000}, {0x41dbc000}, {0x41dbe000},
+ {0x41dc0000}, {0x41dc2000}, {0x41dc4000}, {0x41dc6000},
+ {0x41dc8000}, {0x41dca000}, {0x41dcc000}, {0x41dce000},
+ {0x41dd0000}, {0x41dd2000}, {0x41dd4000}, {0x41dd6000},
+ {0x41dd8000}, {0x41dda000}, {0x41ddc000}, {0x41dde000},
+ {0x41de0000}, {0x41de2000}, {0x41de4000}, {0x41de6000},
+ {0x41de8000}, {0x41dea000}, {0x41dec000}, {0x41dee000},
+ {0x41df0000}, {0x41df2000}, {0x41df4000}, {0x41df6000},
+ {0x41df8000}, {0x41dfa000}, {0x41dfc000}, {0x41dfe000},
+ {0x41e00000}, {0x41e02000}, {0x41e04000}, {0x41e06000},
+ {0x41e08000}, {0x41e0a000}, {0x41e0c000}, {0x41e0e000},
+ {0x41e10000}, {0x41e12000}, {0x41e14000}, {0x41e16000},
+ {0x41e18000}, {0x41e1a000}, {0x41e1c000}, {0x41e1e000},
+ {0x41e20000}, {0x41e22000}, {0x41e24000}, {0x41e26000},
+ {0x41e28000}, {0x41e2a000}, {0x41e2c000}, {0x41e2e000},
+ {0x41e30000}, {0x41e32000}, {0x41e34000}, {0x41e36000},
+ {0x41e38000}, {0x41e3a000}, {0x41e3c000}, {0x41e3e000},
+ {0x41e40000}, {0x41e42000}, {0x41e44000}, {0x41e46000},
+ {0x41e48000}, {0x41e4a000}, {0x41e4c000}, {0x41e4e000},
+ {0x41e50000}, {0x41e52000}, {0x41e54000}, {0x41e56000},
+ {0x41e58000}, {0x41e5a000}, {0x41e5c000}, {0x41e5e000},
+ {0x41e60000}, {0x41e62000}, {0x41e64000}, {0x41e66000},
+ {0x41e68000}, {0x41e6a000}, {0x41e6c000}, {0x41e6e000},
+ {0x41e70000}, {0x41e72000}, {0x41e74000}, {0x41e76000},
+ {0x41e78000}, {0x41e7a000}, {0x41e7c000}, {0x41e7e000},
+ {0x41e80000}, {0x41e82000}, {0x41e84000}, {0x41e86000},
+ {0x41e88000}, {0x41e8a000}, {0x41e8c000}, {0x41e8e000},
+ {0x41e90000}, {0x41e92000}, {0x41e94000}, {0x41e96000},
+ {0x41e98000}, {0x41e9a000}, {0x41e9c000}, {0x41e9e000},
+ {0x41ea0000}, {0x41ea2000}, {0x41ea4000}, {0x41ea6000},
+ {0x41ea8000}, {0x41eaa000}, {0x41eac000}, {0x41eae000},
+ {0x41eb0000}, {0x41eb2000}, {0x41eb4000}, {0x41eb6000},
+ {0x41eb8000}, {0x41eba000}, {0x41ebc000}, {0x41ebe000},
+ {0x41ec0000}, {0x41ec2000}, {0x41ec4000}, {0x41ec6000},
+ {0x41ec8000}, {0x41eca000}, {0x41ecc000}, {0x41ece000},
+ {0x41ed0000}, {0x41ed2000}, {0x41ed4000}, {0x41ed6000},
+ {0x41ed8000}, {0x41eda000}, {0x41edc000}, {0x41ede000},
+ {0x41ee0000}, {0x41ee2000}, {0x41ee4000}, {0x41ee6000},
+ {0x41ee8000}, {0x41eea000}, {0x41eec000}, {0x41eee000},
+ {0x41ef0000}, {0x41ef2000}, {0x41ef4000}, {0x41ef6000},
+ {0x41ef8000}, {0x41efa000}, {0x41efc000}, {0x41efe000},
+ {0x41f00000}, {0x41f02000}, {0x41f04000}, {0x41f06000},
+ {0x41f08000}, {0x41f0a000}, {0x41f0c000}, {0x41f0e000},
+ {0x41f10000}, {0x41f12000}, {0x41f14000}, {0x41f16000},
+ {0x41f18000}, {0x41f1a000}, {0x41f1c000}, {0x41f1e000},
+ {0x41f20000}, {0x41f22000}, {0x41f24000}, {0x41f26000},
+ {0x41f28000}, {0x41f2a000}, {0x41f2c000}, {0x41f2e000},
+ {0x41f30000}, {0x41f32000}, {0x41f34000}, {0x41f36000},
+ {0x41f38000}, {0x41f3a000}, {0x41f3c000}, {0x41f3e000},
+ {0x41f40000}, {0x41f42000}, {0x41f44000}, {0x41f46000},
+ {0x41f48000}, {0x41f4a000}, {0x41f4c000}, {0x41f4e000},
+ {0x41f50000}, {0x41f52000}, {0x41f54000}, {0x41f56000},
+ {0x41f58000}, {0x41f5a000}, {0x41f5c000}, {0x41f5e000},
+ {0x41f60000}, {0x41f62000}, {0x41f64000}, {0x41f66000},
+ {0x41f68000}, {0x41f6a000}, {0x41f6c000}, {0x41f6e000},
+ {0x41f70000}, {0x41f72000}, {0x41f74000}, {0x41f76000},
+ {0x41f78000}, {0x41f7a000}, {0x41f7c000}, {0x41f7e000},
+ {0x41f80000}, {0x41f82000}, {0x41f84000}, {0x41f86000},
+ {0x41f88000}, {0x41f8a000}, {0x41f8c000}, {0x41f8e000},
+ {0x41f90000}, {0x41f92000}, {0x41f94000}, {0x41f96000},
+ {0x41f98000}, {0x41f9a000}, {0x41f9c000}, {0x41f9e000},
+ {0x41fa0000}, {0x41fa2000}, {0x41fa4000}, {0x41fa6000},
+ {0x41fa8000}, {0x41faa000}, {0x41fac000}, {0x41fae000},
+ {0x41fb0000}, {0x41fb2000}, {0x41fb4000}, {0x41fb6000},
+ {0x41fb8000}, {0x41fba000}, {0x41fbc000}, {0x41fbe000},
+ {0x41fc0000}, {0x41fc2000}, {0x41fc4000}, {0x41fc6000},
+ {0x41fc8000}, {0x41fca000}, {0x41fcc000}, {0x41fce000},
+ {0x41fd0000}, {0x41fd2000}, {0x41fd4000}, {0x41fd6000},
+ {0x41fd8000}, {0x41fda000}, {0x41fdc000}, {0x41fde000},
+ {0x41fe0000}, {0x41fe2000}, {0x41fe4000}, {0x41fe6000},
+ {0x41fe8000}, {0x41fea000}, {0x41fec000}, {0x41fee000},
+ {0x41ff0000}, {0x41ff2000}, {0x41ff4000}, {0x41ff6000},
+ {0x41ff8000}, {0x41ffa000}, {0x41ffc000}, {0x41ffe000},
+ {0x42000000}, {0x42002000}, {0x42004000}, {0x42006000},
+ {0x42008000}, {0x4200a000}, {0x4200c000}, {0x4200e000},
+ {0x42010000}, {0x42012000}, {0x42014000}, {0x42016000},
+ {0x42018000}, {0x4201a000}, {0x4201c000}, {0x4201e000},
+ {0x42020000}, {0x42022000}, {0x42024000}, {0x42026000},
+ {0x42028000}, {0x4202a000}, {0x4202c000}, {0x4202e000},
+ {0x42030000}, {0x42032000}, {0x42034000}, {0x42036000},
+ {0x42038000}, {0x4203a000}, {0x4203c000}, {0x4203e000},
+ {0x42040000}, {0x42042000}, {0x42044000}, {0x42046000},
+ {0x42048000}, {0x4204a000}, {0x4204c000}, {0x4204e000},
+ {0x42050000}, {0x42052000}, {0x42054000}, {0x42056000},
+ {0x42058000}, {0x4205a000}, {0x4205c000}, {0x4205e000},
+ {0x42060000}, {0x42062000}, {0x42064000}, {0x42066000},
+ {0x42068000}, {0x4206a000}, {0x4206c000}, {0x4206e000},
+ {0x42070000}, {0x42072000}, {0x42074000}, {0x42076000},
+ {0x42078000}, {0x4207a000}, {0x4207c000}, {0x4207e000},
+ {0x42080000}, {0x42082000}, {0x42084000}, {0x42086000},
+ {0x42088000}, {0x4208a000}, {0x4208c000}, {0x4208e000},
+ {0x42090000}, {0x42092000}, {0x42094000}, {0x42096000},
+ {0x42098000}, {0x4209a000}, {0x4209c000}, {0x4209e000},
+ {0x420a0000}, {0x420a2000}, {0x420a4000}, {0x420a6000},
+ {0x420a8000}, {0x420aa000}, {0x420ac000}, {0x420ae000},
+ {0x420b0000}, {0x420b2000}, {0x420b4000}, {0x420b6000},
+ {0x420b8000}, {0x420ba000}, {0x420bc000}, {0x420be000},
+ {0x420c0000}, {0x420c2000}, {0x420c4000}, {0x420c6000},
+ {0x420c8000}, {0x420ca000}, {0x420cc000}, {0x420ce000},
+ {0x420d0000}, {0x420d2000}, {0x420d4000}, {0x420d6000},
+ {0x420d8000}, {0x420da000}, {0x420dc000}, {0x420de000},
+ {0x420e0000}, {0x420e2000}, {0x420e4000}, {0x420e6000},
+ {0x420e8000}, {0x420ea000}, {0x420ec000}, {0x420ee000},
+ {0x420f0000}, {0x420f2000}, {0x420f4000}, {0x420f6000},
+ {0x420f8000}, {0x420fa000}, {0x420fc000}, {0x420fe000},
+ {0x42100000}, {0x42102000}, {0x42104000}, {0x42106000},
+ {0x42108000}, {0x4210a000}, {0x4210c000}, {0x4210e000},
+ {0x42110000}, {0x42112000}, {0x42114000}, {0x42116000},
+ {0x42118000}, {0x4211a000}, {0x4211c000}, {0x4211e000},
+ {0x42120000}, {0x42122000}, {0x42124000}, {0x42126000},
+ {0x42128000}, {0x4212a000}, {0x4212c000}, {0x4212e000},
+ {0x42130000}, {0x42132000}, {0x42134000}, {0x42136000},
+ {0x42138000}, {0x4213a000}, {0x4213c000}, {0x4213e000},
+ {0x42140000}, {0x42142000}, {0x42144000}, {0x42146000},
+ {0x42148000}, {0x4214a000}, {0x4214c000}, {0x4214e000},
+ {0x42150000}, {0x42152000}, {0x42154000}, {0x42156000},
+ {0x42158000}, {0x4215a000}, {0x4215c000}, {0x4215e000},
+ {0x42160000}, {0x42162000}, {0x42164000}, {0x42166000},
+ {0x42168000}, {0x4216a000}, {0x4216c000}, {0x4216e000},
+ {0x42170000}, {0x42172000}, {0x42174000}, {0x42176000},
+ {0x42178000}, {0x4217a000}, {0x4217c000}, {0x4217e000},
+ {0x42180000}, {0x42182000}, {0x42184000}, {0x42186000},
+ {0x42188000}, {0x4218a000}, {0x4218c000}, {0x4218e000},
+ {0x42190000}, {0x42192000}, {0x42194000}, {0x42196000},
+ {0x42198000}, {0x4219a000}, {0x4219c000}, {0x4219e000},
+ {0x421a0000}, {0x421a2000}, {0x421a4000}, {0x421a6000},
+ {0x421a8000}, {0x421aa000}, {0x421ac000}, {0x421ae000},
+ {0x421b0000}, {0x421b2000}, {0x421b4000}, {0x421b6000},
+ {0x421b8000}, {0x421ba000}, {0x421bc000}, {0x421be000},
+ {0x421c0000}, {0x421c2000}, {0x421c4000}, {0x421c6000},
+ {0x421c8000}, {0x421ca000}, {0x421cc000}, {0x421ce000},
+ {0x421d0000}, {0x421d2000}, {0x421d4000}, {0x421d6000},
+ {0x421d8000}, {0x421da000}, {0x421dc000}, {0x421de000},
+ {0x421e0000}, {0x421e2000}, {0x421e4000}, {0x421e6000},
+ {0x421e8000}, {0x421ea000}, {0x421ec000}, {0x421ee000},
+ {0x421f0000}, {0x421f2000}, {0x421f4000}, {0x421f6000},
+ {0x421f8000}, {0x421fa000}, {0x421fc000}, {0x421fe000},
+ {0x42200000}, {0x42202000}, {0x42204000}, {0x42206000},
+ {0x42208000}, {0x4220a000}, {0x4220c000}, {0x4220e000},
+ {0x42210000}, {0x42212000}, {0x42214000}, {0x42216000},
+ {0x42218000}, {0x4221a000}, {0x4221c000}, {0x4221e000},
+ {0x42220000}, {0x42222000}, {0x42224000}, {0x42226000},
+ {0x42228000}, {0x4222a000}, {0x4222c000}, {0x4222e000},
+ {0x42230000}, {0x42232000}, {0x42234000}, {0x42236000},
+ {0x42238000}, {0x4223a000}, {0x4223c000}, {0x4223e000},
+ {0x42240000}, {0x42242000}, {0x42244000}, {0x42246000},
+ {0x42248000}, {0x4224a000}, {0x4224c000}, {0x4224e000},
+ {0x42250000}, {0x42252000}, {0x42254000}, {0x42256000},
+ {0x42258000}, {0x4225a000}, {0x4225c000}, {0x4225e000},
+ {0x42260000}, {0x42262000}, {0x42264000}, {0x42266000},
+ {0x42268000}, {0x4226a000}, {0x4226c000}, {0x4226e000},
+ {0x42270000}, {0x42272000}, {0x42274000}, {0x42276000},
+ {0x42278000}, {0x4227a000}, {0x4227c000}, {0x4227e000},
+ {0x42280000}, {0x42282000}, {0x42284000}, {0x42286000},
+ {0x42288000}, {0x4228a000}, {0x4228c000}, {0x4228e000},
+ {0x42290000}, {0x42292000}, {0x42294000}, {0x42296000},
+ {0x42298000}, {0x4229a000}, {0x4229c000}, {0x4229e000},
+ {0x422a0000}, {0x422a2000}, {0x422a4000}, {0x422a6000},
+ {0x422a8000}, {0x422aa000}, {0x422ac000}, {0x422ae000},
+ {0x422b0000}, {0x422b2000}, {0x422b4000}, {0x422b6000},
+ {0x422b8000}, {0x422ba000}, {0x422bc000}, {0x422be000},
+ {0x422c0000}, {0x422c2000}, {0x422c4000}, {0x422c6000},
+ {0x422c8000}, {0x422ca000}, {0x422cc000}, {0x422ce000},
+ {0x422d0000}, {0x422d2000}, {0x422d4000}, {0x422d6000},
+ {0x422d8000}, {0x422da000}, {0x422dc000}, {0x422de000},
+ {0x422e0000}, {0x422e2000}, {0x422e4000}, {0x422e6000},
+ {0x422e8000}, {0x422ea000}, {0x422ec000}, {0x422ee000},
+ {0x422f0000}, {0x422f2000}, {0x422f4000}, {0x422f6000},
+ {0x422f8000}, {0x422fa000}, {0x422fc000}, {0x422fe000},
+ {0x42300000}, {0x42302000}, {0x42304000}, {0x42306000},
+ {0x42308000}, {0x4230a000}, {0x4230c000}, {0x4230e000},
+ {0x42310000}, {0x42312000}, {0x42314000}, {0x42316000},
+ {0x42318000}, {0x4231a000}, {0x4231c000}, {0x4231e000},
+ {0x42320000}, {0x42322000}, {0x42324000}, {0x42326000},
+ {0x42328000}, {0x4232a000}, {0x4232c000}, {0x4232e000},
+ {0x42330000}, {0x42332000}, {0x42334000}, {0x42336000},
+ {0x42338000}, {0x4233a000}, {0x4233c000}, {0x4233e000},
+ {0x42340000}, {0x42342000}, {0x42344000}, {0x42346000},
+ {0x42348000}, {0x4234a000}, {0x4234c000}, {0x4234e000},
+ {0x42350000}, {0x42352000}, {0x42354000}, {0x42356000},
+ {0x42358000}, {0x4235a000}, {0x4235c000}, {0x4235e000},
+ {0x42360000}, {0x42362000}, {0x42364000}, {0x42366000},
+ {0x42368000}, {0x4236a000}, {0x4236c000}, {0x4236e000},
+ {0x42370000}, {0x42372000}, {0x42374000}, {0x42376000},
+ {0x42378000}, {0x4237a000}, {0x4237c000}, {0x4237e000},
+ {0x42380000}, {0x42382000}, {0x42384000}, {0x42386000},
+ {0x42388000}, {0x4238a000}, {0x4238c000}, {0x4238e000},
+ {0x42390000}, {0x42392000}, {0x42394000}, {0x42396000},
+ {0x42398000}, {0x4239a000}, {0x4239c000}, {0x4239e000},
+ {0x423a0000}, {0x423a2000}, {0x423a4000}, {0x423a6000},
+ {0x423a8000}, {0x423aa000}, {0x423ac000}, {0x423ae000},
+ {0x423b0000}, {0x423b2000}, {0x423b4000}, {0x423b6000},
+ {0x423b8000}, {0x423ba000}, {0x423bc000}, {0x423be000},
+ {0x423c0000}, {0x423c2000}, {0x423c4000}, {0x423c6000},
+ {0x423c8000}, {0x423ca000}, {0x423cc000}, {0x423ce000},
+ {0x423d0000}, {0x423d2000}, {0x423d4000}, {0x423d6000},
+ {0x423d8000}, {0x423da000}, {0x423dc000}, {0x423de000},
+ {0x423e0000}, {0x423e2000}, {0x423e4000}, {0x423e6000},
+ {0x423e8000}, {0x423ea000}, {0x423ec000}, {0x423ee000},
+ {0x423f0000}, {0x423f2000}, {0x423f4000}, {0x423f6000},
+ {0x423f8000}, {0x423fa000}, {0x423fc000}, {0x423fe000},
+ {0x42400000}, {0x42402000}, {0x42404000}, {0x42406000},
+ {0x42408000}, {0x4240a000}, {0x4240c000}, {0x4240e000},
+ {0x42410000}, {0x42412000}, {0x42414000}, {0x42416000},
+ {0x42418000}, {0x4241a000}, {0x4241c000}, {0x4241e000},
+ {0x42420000}, {0x42422000}, {0x42424000}, {0x42426000},
+ {0x42428000}, {0x4242a000}, {0x4242c000}, {0x4242e000},
+ {0x42430000}, {0x42432000}, {0x42434000}, {0x42436000},
+ {0x42438000}, {0x4243a000}, {0x4243c000}, {0x4243e000},
+ {0x42440000}, {0x42442000}, {0x42444000}, {0x42446000},
+ {0x42448000}, {0x4244a000}, {0x4244c000}, {0x4244e000},
+ {0x42450000}, {0x42452000}, {0x42454000}, {0x42456000},
+ {0x42458000}, {0x4245a000}, {0x4245c000}, {0x4245e000},
+ {0x42460000}, {0x42462000}, {0x42464000}, {0x42466000},
+ {0x42468000}, {0x4246a000}, {0x4246c000}, {0x4246e000},
+ {0x42470000}, {0x42472000}, {0x42474000}, {0x42476000},
+ {0x42478000}, {0x4247a000}, {0x4247c000}, {0x4247e000},
+ {0x42480000}, {0x42482000}, {0x42484000}, {0x42486000},
+ {0x42488000}, {0x4248a000}, {0x4248c000}, {0x4248e000},
+ {0x42490000}, {0x42492000}, {0x42494000}, {0x42496000},
+ {0x42498000}, {0x4249a000}, {0x4249c000}, {0x4249e000},
+ {0x424a0000}, {0x424a2000}, {0x424a4000}, {0x424a6000},
+ {0x424a8000}, {0x424aa000}, {0x424ac000}, {0x424ae000},
+ {0x424b0000}, {0x424b2000}, {0x424b4000}, {0x424b6000},
+ {0x424b8000}, {0x424ba000}, {0x424bc000}, {0x424be000},
+ {0x424c0000}, {0x424c2000}, {0x424c4000}, {0x424c6000},
+ {0x424c8000}, {0x424ca000}, {0x424cc000}, {0x424ce000},
+ {0x424d0000}, {0x424d2000}, {0x424d4000}, {0x424d6000},
+ {0x424d8000}, {0x424da000}, {0x424dc000}, {0x424de000},
+ {0x424e0000}, {0x424e2000}, {0x424e4000}, {0x424e6000},
+ {0x424e8000}, {0x424ea000}, {0x424ec000}, {0x424ee000},
+ {0x424f0000}, {0x424f2000}, {0x424f4000}, {0x424f6000},
+ {0x424f8000}, {0x424fa000}, {0x424fc000}, {0x424fe000},
+ {0x42500000}, {0x42502000}, {0x42504000}, {0x42506000},
+ {0x42508000}, {0x4250a000}, {0x4250c000}, {0x4250e000},
+ {0x42510000}, {0x42512000}, {0x42514000}, {0x42516000},
+ {0x42518000}, {0x4251a000}, {0x4251c000}, {0x4251e000},
+ {0x42520000}, {0x42522000}, {0x42524000}, {0x42526000},
+ {0x42528000}, {0x4252a000}, {0x4252c000}, {0x4252e000},
+ {0x42530000}, {0x42532000}, {0x42534000}, {0x42536000},
+ {0x42538000}, {0x4253a000}, {0x4253c000}, {0x4253e000},
+ {0x42540000}, {0x42542000}, {0x42544000}, {0x42546000},
+ {0x42548000}, {0x4254a000}, {0x4254c000}, {0x4254e000},
+ {0x42550000}, {0x42552000}, {0x42554000}, {0x42556000},
+ {0x42558000}, {0x4255a000}, {0x4255c000}, {0x4255e000},
+ {0x42560000}, {0x42562000}, {0x42564000}, {0x42566000},
+ {0x42568000}, {0x4256a000}, {0x4256c000}, {0x4256e000},
+ {0x42570000}, {0x42572000}, {0x42574000}, {0x42576000},
+ {0x42578000}, {0x4257a000}, {0x4257c000}, {0x4257e000},
+ {0x42580000}, {0x42582000}, {0x42584000}, {0x42586000},
+ {0x42588000}, {0x4258a000}, {0x4258c000}, {0x4258e000},
+ {0x42590000}, {0x42592000}, {0x42594000}, {0x42596000},
+ {0x42598000}, {0x4259a000}, {0x4259c000}, {0x4259e000},
+ {0x425a0000}, {0x425a2000}, {0x425a4000}, {0x425a6000},
+ {0x425a8000}, {0x425aa000}, {0x425ac000}, {0x425ae000},
+ {0x425b0000}, {0x425b2000}, {0x425b4000}, {0x425b6000},
+ {0x425b8000}, {0x425ba000}, {0x425bc000}, {0x425be000},
+ {0x425c0000}, {0x425c2000}, {0x425c4000}, {0x425c6000},
+ {0x425c8000}, {0x425ca000}, {0x425cc000}, {0x425ce000},
+ {0x425d0000}, {0x425d2000}, {0x425d4000}, {0x425d6000},
+ {0x425d8000}, {0x425da000}, {0x425dc000}, {0x425de000},
+ {0x425e0000}, {0x425e2000}, {0x425e4000}, {0x425e6000},
+ {0x425e8000}, {0x425ea000}, {0x425ec000}, {0x425ee000},
+ {0x425f0000}, {0x425f2000}, {0x425f4000}, {0x425f6000},
+ {0x425f8000}, {0x425fa000}, {0x425fc000}, {0x425fe000},
+ {0x42600000}, {0x42602000}, {0x42604000}, {0x42606000},
+ {0x42608000}, {0x4260a000}, {0x4260c000}, {0x4260e000},
+ {0x42610000}, {0x42612000}, {0x42614000}, {0x42616000},
+ {0x42618000}, {0x4261a000}, {0x4261c000}, {0x4261e000},
+ {0x42620000}, {0x42622000}, {0x42624000}, {0x42626000},
+ {0x42628000}, {0x4262a000}, {0x4262c000}, {0x4262e000},
+ {0x42630000}, {0x42632000}, {0x42634000}, {0x42636000},
+ {0x42638000}, {0x4263a000}, {0x4263c000}, {0x4263e000},
+ {0x42640000}, {0x42642000}, {0x42644000}, {0x42646000},
+ {0x42648000}, {0x4264a000}, {0x4264c000}, {0x4264e000},
+ {0x42650000}, {0x42652000}, {0x42654000}, {0x42656000},
+ {0x42658000}, {0x4265a000}, {0x4265c000}, {0x4265e000},
+ {0x42660000}, {0x42662000}, {0x42664000}, {0x42666000},
+ {0x42668000}, {0x4266a000}, {0x4266c000}, {0x4266e000},
+ {0x42670000}, {0x42672000}, {0x42674000}, {0x42676000},
+ {0x42678000}, {0x4267a000}, {0x4267c000}, {0x4267e000},
+ {0x42680000}, {0x42682000}, {0x42684000}, {0x42686000},
+ {0x42688000}, {0x4268a000}, {0x4268c000}, {0x4268e000},
+ {0x42690000}, {0x42692000}, {0x42694000}, {0x42696000},
+ {0x42698000}, {0x4269a000}, {0x4269c000}, {0x4269e000},
+ {0x426a0000}, {0x426a2000}, {0x426a4000}, {0x426a6000},
+ {0x426a8000}, {0x426aa000}, {0x426ac000}, {0x426ae000},
+ {0x426b0000}, {0x426b2000}, {0x426b4000}, {0x426b6000},
+ {0x426b8000}, {0x426ba000}, {0x426bc000}, {0x426be000},
+ {0x426c0000}, {0x426c2000}, {0x426c4000}, {0x426c6000},
+ {0x426c8000}, {0x426ca000}, {0x426cc000}, {0x426ce000},
+ {0x426d0000}, {0x426d2000}, {0x426d4000}, {0x426d6000},
+ {0x426d8000}, {0x426da000}, {0x426dc000}, {0x426de000},
+ {0x426e0000}, {0x426e2000}, {0x426e4000}, {0x426e6000},
+ {0x426e8000}, {0x426ea000}, {0x426ec000}, {0x426ee000},
+ {0x426f0000}, {0x426f2000}, {0x426f4000}, {0x426f6000},
+ {0x426f8000}, {0x426fa000}, {0x426fc000}, {0x426fe000},
+ {0x42700000}, {0x42702000}, {0x42704000}, {0x42706000},
+ {0x42708000}, {0x4270a000}, {0x4270c000}, {0x4270e000},
+ {0x42710000}, {0x42712000}, {0x42714000}, {0x42716000},
+ {0x42718000}, {0x4271a000}, {0x4271c000}, {0x4271e000},
+ {0x42720000}, {0x42722000}, {0x42724000}, {0x42726000},
+ {0x42728000}, {0x4272a000}, {0x4272c000}, {0x4272e000},
+ {0x42730000}, {0x42732000}, {0x42734000}, {0x42736000},
+ {0x42738000}, {0x4273a000}, {0x4273c000}, {0x4273e000},
+ {0x42740000}, {0x42742000}, {0x42744000}, {0x42746000},
+ {0x42748000}, {0x4274a000}, {0x4274c000}, {0x4274e000},
+ {0x42750000}, {0x42752000}, {0x42754000}, {0x42756000},
+ {0x42758000}, {0x4275a000}, {0x4275c000}, {0x4275e000},
+ {0x42760000}, {0x42762000}, {0x42764000}, {0x42766000},
+ {0x42768000}, {0x4276a000}, {0x4276c000}, {0x4276e000},
+ {0x42770000}, {0x42772000}, {0x42774000}, {0x42776000},
+ {0x42778000}, {0x4277a000}, {0x4277c000}, {0x4277e000},
+ {0x42780000}, {0x42782000}, {0x42784000}, {0x42786000},
+ {0x42788000}, {0x4278a000}, {0x4278c000}, {0x4278e000},
+ {0x42790000}, {0x42792000}, {0x42794000}, {0x42796000},
+ {0x42798000}, {0x4279a000}, {0x4279c000}, {0x4279e000},
+ {0x427a0000}, {0x427a2000}, {0x427a4000}, {0x427a6000},
+ {0x427a8000}, {0x427aa000}, {0x427ac000}, {0x427ae000},
+ {0x427b0000}, {0x427b2000}, {0x427b4000}, {0x427b6000},
+ {0x427b8000}, {0x427ba000}, {0x427bc000}, {0x427be000},
+ {0x427c0000}, {0x427c2000}, {0x427c4000}, {0x427c6000},
+ {0x427c8000}, {0x427ca000}, {0x427cc000}, {0x427ce000},
+ {0x427d0000}, {0x427d2000}, {0x427d4000}, {0x427d6000},
+ {0x427d8000}, {0x427da000}, {0x427dc000}, {0x427de000},
+ {0x427e0000}, {0x427e2000}, {0x427e4000}, {0x427e6000},
+ {0x427e8000}, {0x427ea000}, {0x427ec000}, {0x427ee000},
+ {0x427f0000}, {0x427f2000}, {0x427f4000}, {0x427f6000},
+ {0x427f8000}, {0x427fa000}, {0x427fc000}, {0x427fe000},
+ {0x42800000}, {0x42802000}, {0x42804000}, {0x42806000},
+ {0x42808000}, {0x4280a000}, {0x4280c000}, {0x4280e000},
+ {0x42810000}, {0x42812000}, {0x42814000}, {0x42816000},
+ {0x42818000}, {0x4281a000}, {0x4281c000}, {0x4281e000},
+ {0x42820000}, {0x42822000}, {0x42824000}, {0x42826000},
+ {0x42828000}, {0x4282a000}, {0x4282c000}, {0x4282e000},
+ {0x42830000}, {0x42832000}, {0x42834000}, {0x42836000},
+ {0x42838000}, {0x4283a000}, {0x4283c000}, {0x4283e000},
+ {0x42840000}, {0x42842000}, {0x42844000}, {0x42846000},
+ {0x42848000}, {0x4284a000}, {0x4284c000}, {0x4284e000},
+ {0x42850000}, {0x42852000}, {0x42854000}, {0x42856000},
+ {0x42858000}, {0x4285a000}, {0x4285c000}, {0x4285e000},
+ {0x42860000}, {0x42862000}, {0x42864000}, {0x42866000},
+ {0x42868000}, {0x4286a000}, {0x4286c000}, {0x4286e000},
+ {0x42870000}, {0x42872000}, {0x42874000}, {0x42876000},
+ {0x42878000}, {0x4287a000}, {0x4287c000}, {0x4287e000},
+ {0x42880000}, {0x42882000}, {0x42884000}, {0x42886000},
+ {0x42888000}, {0x4288a000}, {0x4288c000}, {0x4288e000},
+ {0x42890000}, {0x42892000}, {0x42894000}, {0x42896000},
+ {0x42898000}, {0x4289a000}, {0x4289c000}, {0x4289e000},
+ {0x428a0000}, {0x428a2000}, {0x428a4000}, {0x428a6000},
+ {0x428a8000}, {0x428aa000}, {0x428ac000}, {0x428ae000},
+ {0x428b0000}, {0x428b2000}, {0x428b4000}, {0x428b6000},
+ {0x428b8000}, {0x428ba000}, {0x428bc000}, {0x428be000},
+ {0x428c0000}, {0x428c2000}, {0x428c4000}, {0x428c6000},
+ {0x428c8000}, {0x428ca000}, {0x428cc000}, {0x428ce000},
+ {0x428d0000}, {0x428d2000}, {0x428d4000}, {0x428d6000},
+ {0x428d8000}, {0x428da000}, {0x428dc000}, {0x428de000},
+ {0x428e0000}, {0x428e2000}, {0x428e4000}, {0x428e6000},
+ {0x428e8000}, {0x428ea000}, {0x428ec000}, {0x428ee000},
+ {0x428f0000}, {0x428f2000}, {0x428f4000}, {0x428f6000},
+ {0x428f8000}, {0x428fa000}, {0x428fc000}, {0x428fe000},
+ {0x42900000}, {0x42902000}, {0x42904000}, {0x42906000},
+ {0x42908000}, {0x4290a000}, {0x4290c000}, {0x4290e000},
+ {0x42910000}, {0x42912000}, {0x42914000}, {0x42916000},
+ {0x42918000}, {0x4291a000}, {0x4291c000}, {0x4291e000},
+ {0x42920000}, {0x42922000}, {0x42924000}, {0x42926000},
+ {0x42928000}, {0x4292a000}, {0x4292c000}, {0x4292e000},
+ {0x42930000}, {0x42932000}, {0x42934000}, {0x42936000},
+ {0x42938000}, {0x4293a000}, {0x4293c000}, {0x4293e000},
+ {0x42940000}, {0x42942000}, {0x42944000}, {0x42946000},
+ {0x42948000}, {0x4294a000}, {0x4294c000}, {0x4294e000},
+ {0x42950000}, {0x42952000}, {0x42954000}, {0x42956000},
+ {0x42958000}, {0x4295a000}, {0x4295c000}, {0x4295e000},
+ {0x42960000}, {0x42962000}, {0x42964000}, {0x42966000},
+ {0x42968000}, {0x4296a000}, {0x4296c000}, {0x4296e000},
+ {0x42970000}, {0x42972000}, {0x42974000}, {0x42976000},
+ {0x42978000}, {0x4297a000}, {0x4297c000}, {0x4297e000},
+ {0x42980000}, {0x42982000}, {0x42984000}, {0x42986000},
+ {0x42988000}, {0x4298a000}, {0x4298c000}, {0x4298e000},
+ {0x42990000}, {0x42992000}, {0x42994000}, {0x42996000},
+ {0x42998000}, {0x4299a000}, {0x4299c000}, {0x4299e000},
+ {0x429a0000}, {0x429a2000}, {0x429a4000}, {0x429a6000},
+ {0x429a8000}, {0x429aa000}, {0x429ac000}, {0x429ae000},
+ {0x429b0000}, {0x429b2000}, {0x429b4000}, {0x429b6000},
+ {0x429b8000}, {0x429ba000}, {0x429bc000}, {0x429be000},
+ {0x429c0000}, {0x429c2000}, {0x429c4000}, {0x429c6000},
+ {0x429c8000}, {0x429ca000}, {0x429cc000}, {0x429ce000},
+ {0x429d0000}, {0x429d2000}, {0x429d4000}, {0x429d6000},
+ {0x429d8000}, {0x429da000}, {0x429dc000}, {0x429de000},
+ {0x429e0000}, {0x429e2000}, {0x429e4000}, {0x429e6000},
+ {0x429e8000}, {0x429ea000}, {0x429ec000}, {0x429ee000},
+ {0x429f0000}, {0x429f2000}, {0x429f4000}, {0x429f6000},
+ {0x429f8000}, {0x429fa000}, {0x429fc000}, {0x429fe000},
+ {0x42a00000}, {0x42a02000}, {0x42a04000}, {0x42a06000},
+ {0x42a08000}, {0x42a0a000}, {0x42a0c000}, {0x42a0e000},
+ {0x42a10000}, {0x42a12000}, {0x42a14000}, {0x42a16000},
+ {0x42a18000}, {0x42a1a000}, {0x42a1c000}, {0x42a1e000},
+ {0x42a20000}, {0x42a22000}, {0x42a24000}, {0x42a26000},
+ {0x42a28000}, {0x42a2a000}, {0x42a2c000}, {0x42a2e000},
+ {0x42a30000}, {0x42a32000}, {0x42a34000}, {0x42a36000},
+ {0x42a38000}, {0x42a3a000}, {0x42a3c000}, {0x42a3e000},
+ {0x42a40000}, {0x42a42000}, {0x42a44000}, {0x42a46000},
+ {0x42a48000}, {0x42a4a000}, {0x42a4c000}, {0x42a4e000},
+ {0x42a50000}, {0x42a52000}, {0x42a54000}, {0x42a56000},
+ {0x42a58000}, {0x42a5a000}, {0x42a5c000}, {0x42a5e000},
+ {0x42a60000}, {0x42a62000}, {0x42a64000}, {0x42a66000},
+ {0x42a68000}, {0x42a6a000}, {0x42a6c000}, {0x42a6e000},
+ {0x42a70000}, {0x42a72000}, {0x42a74000}, {0x42a76000},
+ {0x42a78000}, {0x42a7a000}, {0x42a7c000}, {0x42a7e000},
+ {0x42a80000}, {0x42a82000}, {0x42a84000}, {0x42a86000},
+ {0x42a88000}, {0x42a8a000}, {0x42a8c000}, {0x42a8e000},
+ {0x42a90000}, {0x42a92000}, {0x42a94000}, {0x42a96000},
+ {0x42a98000}, {0x42a9a000}, {0x42a9c000}, {0x42a9e000},
+ {0x42aa0000}, {0x42aa2000}, {0x42aa4000}, {0x42aa6000},
+ {0x42aa8000}, {0x42aaa000}, {0x42aac000}, {0x42aae000},
+ {0x42ab0000}, {0x42ab2000}, {0x42ab4000}, {0x42ab6000},
+ {0x42ab8000}, {0x42aba000}, {0x42abc000}, {0x42abe000},
+ {0x42ac0000}, {0x42ac2000}, {0x42ac4000}, {0x42ac6000},
+ {0x42ac8000}, {0x42aca000}, {0x42acc000}, {0x42ace000},
+ {0x42ad0000}, {0x42ad2000}, {0x42ad4000}, {0x42ad6000},
+ {0x42ad8000}, {0x42ada000}, {0x42adc000}, {0x42ade000},
+ {0x42ae0000}, {0x42ae2000}, {0x42ae4000}, {0x42ae6000},
+ {0x42ae8000}, {0x42aea000}, {0x42aec000}, {0x42aee000},
+ {0x42af0000}, {0x42af2000}, {0x42af4000}, {0x42af6000},
+ {0x42af8000}, {0x42afa000}, {0x42afc000}, {0x42afe000},
+ {0x42b00000}, {0x42b02000}, {0x42b04000}, {0x42b06000},
+ {0x42b08000}, {0x42b0a000}, {0x42b0c000}, {0x42b0e000},
+ {0x42b10000}, {0x42b12000}, {0x42b14000}, {0x42b16000},
+ {0x42b18000}, {0x42b1a000}, {0x42b1c000}, {0x42b1e000},
+ {0x42b20000}, {0x42b22000}, {0x42b24000}, {0x42b26000},
+ {0x42b28000}, {0x42b2a000}, {0x42b2c000}, {0x42b2e000},
+ {0x42b30000}, {0x42b32000}, {0x42b34000}, {0x42b36000},
+ {0x42b38000}, {0x42b3a000}, {0x42b3c000}, {0x42b3e000},
+ {0x42b40000}, {0x42b42000}, {0x42b44000}, {0x42b46000},
+ {0x42b48000}, {0x42b4a000}, {0x42b4c000}, {0x42b4e000},
+ {0x42b50000}, {0x42b52000}, {0x42b54000}, {0x42b56000},
+ {0x42b58000}, {0x42b5a000}, {0x42b5c000}, {0x42b5e000},
+ {0x42b60000}, {0x42b62000}, {0x42b64000}, {0x42b66000},
+ {0x42b68000}, {0x42b6a000}, {0x42b6c000}, {0x42b6e000},
+ {0x42b70000}, {0x42b72000}, {0x42b74000}, {0x42b76000},
+ {0x42b78000}, {0x42b7a000}, {0x42b7c000}, {0x42b7e000},
+ {0x42b80000}, {0x42b82000}, {0x42b84000}, {0x42b86000},
+ {0x42b88000}, {0x42b8a000}, {0x42b8c000}, {0x42b8e000},
+ {0x42b90000}, {0x42b92000}, {0x42b94000}, {0x42b96000},
+ {0x42b98000}, {0x42b9a000}, {0x42b9c000}, {0x42b9e000},
+ {0x42ba0000}, {0x42ba2000}, {0x42ba4000}, {0x42ba6000},
+ {0x42ba8000}, {0x42baa000}, {0x42bac000}, {0x42bae000},
+ {0x42bb0000}, {0x42bb2000}, {0x42bb4000}, {0x42bb6000},
+ {0x42bb8000}, {0x42bba000}, {0x42bbc000}, {0x42bbe000},
+ {0x42bc0000}, {0x42bc2000}, {0x42bc4000}, {0x42bc6000},
+ {0x42bc8000}, {0x42bca000}, {0x42bcc000}, {0x42bce000},
+ {0x42bd0000}, {0x42bd2000}, {0x42bd4000}, {0x42bd6000},
+ {0x42bd8000}, {0x42bda000}, {0x42bdc000}, {0x42bde000},
+ {0x42be0000}, {0x42be2000}, {0x42be4000}, {0x42be6000},
+ {0x42be8000}, {0x42bea000}, {0x42bec000}, {0x42bee000},
+ {0x42bf0000}, {0x42bf2000}, {0x42bf4000}, {0x42bf6000},
+ {0x42bf8000}, {0x42bfa000}, {0x42bfc000}, {0x42bfe000},
+ {0x42c00000}, {0x42c02000}, {0x42c04000}, {0x42c06000},
+ {0x42c08000}, {0x42c0a000}, {0x42c0c000}, {0x42c0e000},
+ {0x42c10000}, {0x42c12000}, {0x42c14000}, {0x42c16000},
+ {0x42c18000}, {0x42c1a000}, {0x42c1c000}, {0x42c1e000},
+ {0x42c20000}, {0x42c22000}, {0x42c24000}, {0x42c26000},
+ {0x42c28000}, {0x42c2a000}, {0x42c2c000}, {0x42c2e000},
+ {0x42c30000}, {0x42c32000}, {0x42c34000}, {0x42c36000},
+ {0x42c38000}, {0x42c3a000}, {0x42c3c000}, {0x42c3e000},
+ {0x42c40000}, {0x42c42000}, {0x42c44000}, {0x42c46000},
+ {0x42c48000}, {0x42c4a000}, {0x42c4c000}, {0x42c4e000},
+ {0x42c50000}, {0x42c52000}, {0x42c54000}, {0x42c56000},
+ {0x42c58000}, {0x42c5a000}, {0x42c5c000}, {0x42c5e000},
+ {0x42c60000}, {0x42c62000}, {0x42c64000}, {0x42c66000},
+ {0x42c68000}, {0x42c6a000}, {0x42c6c000}, {0x42c6e000},
+ {0x42c70000}, {0x42c72000}, {0x42c74000}, {0x42c76000},
+ {0x42c78000}, {0x42c7a000}, {0x42c7c000}, {0x42c7e000},
+ {0x42c80000}, {0x42c82000}, {0x42c84000}, {0x42c86000},
+ {0x42c88000}, {0x42c8a000}, {0x42c8c000}, {0x42c8e000},
+ {0x42c90000}, {0x42c92000}, {0x42c94000}, {0x42c96000},
+ {0x42c98000}, {0x42c9a000}, {0x42c9c000}, {0x42c9e000},
+ {0x42ca0000}, {0x42ca2000}, {0x42ca4000}, {0x42ca6000},
+ {0x42ca8000}, {0x42caa000}, {0x42cac000}, {0x42cae000},
+ {0x42cb0000}, {0x42cb2000}, {0x42cb4000}, {0x42cb6000},
+ {0x42cb8000}, {0x42cba000}, {0x42cbc000}, {0x42cbe000},
+ {0x42cc0000}, {0x42cc2000}, {0x42cc4000}, {0x42cc6000},
+ {0x42cc8000}, {0x42cca000}, {0x42ccc000}, {0x42cce000},
+ {0x42cd0000}, {0x42cd2000}, {0x42cd4000}, {0x42cd6000},
+ {0x42cd8000}, {0x42cda000}, {0x42cdc000}, {0x42cde000},
+ {0x42ce0000}, {0x42ce2000}, {0x42ce4000}, {0x42ce6000},
+ {0x42ce8000}, {0x42cea000}, {0x42cec000}, {0x42cee000},
+ {0x42cf0000}, {0x42cf2000}, {0x42cf4000}, {0x42cf6000},
+ {0x42cf8000}, {0x42cfa000}, {0x42cfc000}, {0x42cfe000},
+ {0x42d00000}, {0x42d02000}, {0x42d04000}, {0x42d06000},
+ {0x42d08000}, {0x42d0a000}, {0x42d0c000}, {0x42d0e000},
+ {0x42d10000}, {0x42d12000}, {0x42d14000}, {0x42d16000},
+ {0x42d18000}, {0x42d1a000}, {0x42d1c000}, {0x42d1e000},
+ {0x42d20000}, {0x42d22000}, {0x42d24000}, {0x42d26000},
+ {0x42d28000}, {0x42d2a000}, {0x42d2c000}, {0x42d2e000},
+ {0x42d30000}, {0x42d32000}, {0x42d34000}, {0x42d36000},
+ {0x42d38000}, {0x42d3a000}, {0x42d3c000}, {0x42d3e000},
+ {0x42d40000}, {0x42d42000}, {0x42d44000}, {0x42d46000},
+ {0x42d48000}, {0x42d4a000}, {0x42d4c000}, {0x42d4e000},
+ {0x42d50000}, {0x42d52000}, {0x42d54000}, {0x42d56000},
+ {0x42d58000}, {0x42d5a000}, {0x42d5c000}, {0x42d5e000},
+ {0x42d60000}, {0x42d62000}, {0x42d64000}, {0x42d66000},
+ {0x42d68000}, {0x42d6a000}, {0x42d6c000}, {0x42d6e000},
+ {0x42d70000}, {0x42d72000}, {0x42d74000}, {0x42d76000},
+ {0x42d78000}, {0x42d7a000}, {0x42d7c000}, {0x42d7e000},
+ {0x42d80000}, {0x42d82000}, {0x42d84000}, {0x42d86000},
+ {0x42d88000}, {0x42d8a000}, {0x42d8c000}, {0x42d8e000},
+ {0x42d90000}, {0x42d92000}, {0x42d94000}, {0x42d96000},
+ {0x42d98000}, {0x42d9a000}, {0x42d9c000}, {0x42d9e000},
+ {0x42da0000}, {0x42da2000}, {0x42da4000}, {0x42da6000},
+ {0x42da8000}, {0x42daa000}, {0x42dac000}, {0x42dae000},
+ {0x42db0000}, {0x42db2000}, {0x42db4000}, {0x42db6000},
+ {0x42db8000}, {0x42dba000}, {0x42dbc000}, {0x42dbe000},
+ {0x42dc0000}, {0x42dc2000}, {0x42dc4000}, {0x42dc6000},
+ {0x42dc8000}, {0x42dca000}, {0x42dcc000}, {0x42dce000},
+ {0x42dd0000}, {0x42dd2000}, {0x42dd4000}, {0x42dd6000},
+ {0x42dd8000}, {0x42dda000}, {0x42ddc000}, {0x42dde000},
+ {0x42de0000}, {0x42de2000}, {0x42de4000}, {0x42de6000},
+ {0x42de8000}, {0x42dea000}, {0x42dec000}, {0x42dee000},
+ {0x42df0000}, {0x42df2000}, {0x42df4000}, {0x42df6000},
+ {0x42df8000}, {0x42dfa000}, {0x42dfc000}, {0x42dfe000},
+ {0x42e00000}, {0x42e02000}, {0x42e04000}, {0x42e06000},
+ {0x42e08000}, {0x42e0a000}, {0x42e0c000}, {0x42e0e000},
+ {0x42e10000}, {0x42e12000}, {0x42e14000}, {0x42e16000},
+ {0x42e18000}, {0x42e1a000}, {0x42e1c000}, {0x42e1e000},
+ {0x42e20000}, {0x42e22000}, {0x42e24000}, {0x42e26000},
+ {0x42e28000}, {0x42e2a000}, {0x42e2c000}, {0x42e2e000},
+ {0x42e30000}, {0x42e32000}, {0x42e34000}, {0x42e36000},
+ {0x42e38000}, {0x42e3a000}, {0x42e3c000}, {0x42e3e000},
+ {0x42e40000}, {0x42e42000}, {0x42e44000}, {0x42e46000},
+ {0x42e48000}, {0x42e4a000}, {0x42e4c000}, {0x42e4e000},
+ {0x42e50000}, {0x42e52000}, {0x42e54000}, {0x42e56000},
+ {0x42e58000}, {0x42e5a000}, {0x42e5c000}, {0x42e5e000},
+ {0x42e60000}, {0x42e62000}, {0x42e64000}, {0x42e66000},
+ {0x42e68000}, {0x42e6a000}, {0x42e6c000}, {0x42e6e000},
+ {0x42e70000}, {0x42e72000}, {0x42e74000}, {0x42e76000},
+ {0x42e78000}, {0x42e7a000}, {0x42e7c000}, {0x42e7e000},
+ {0x42e80000}, {0x42e82000}, {0x42e84000}, {0x42e86000},
+ {0x42e88000}, {0x42e8a000}, {0x42e8c000}, {0x42e8e000},
+ {0x42e90000}, {0x42e92000}, {0x42e94000}, {0x42e96000},
+ {0x42e98000}, {0x42e9a000}, {0x42e9c000}, {0x42e9e000},
+ {0x42ea0000}, {0x42ea2000}, {0x42ea4000}, {0x42ea6000},
+ {0x42ea8000}, {0x42eaa000}, {0x42eac000}, {0x42eae000},
+ {0x42eb0000}, {0x42eb2000}, {0x42eb4000}, {0x42eb6000},
+ {0x42eb8000}, {0x42eba000}, {0x42ebc000}, {0x42ebe000},
+ {0x42ec0000}, {0x42ec2000}, {0x42ec4000}, {0x42ec6000},
+ {0x42ec8000}, {0x42eca000}, {0x42ecc000}, {0x42ece000},
+ {0x42ed0000}, {0x42ed2000}, {0x42ed4000}, {0x42ed6000},
+ {0x42ed8000}, {0x42eda000}, {0x42edc000}, {0x42ede000},
+ {0x42ee0000}, {0x42ee2000}, {0x42ee4000}, {0x42ee6000},
+ {0x42ee8000}, {0x42eea000}, {0x42eec000}, {0x42eee000},
+ {0x42ef0000}, {0x42ef2000}, {0x42ef4000}, {0x42ef6000},
+ {0x42ef8000}, {0x42efa000}, {0x42efc000}, {0x42efe000},
+ {0x42f00000}, {0x42f02000}, {0x42f04000}, {0x42f06000},
+ {0x42f08000}, {0x42f0a000}, {0x42f0c000}, {0x42f0e000},
+ {0x42f10000}, {0x42f12000}, {0x42f14000}, {0x42f16000},
+ {0x42f18000}, {0x42f1a000}, {0x42f1c000}, {0x42f1e000},
+ {0x42f20000}, {0x42f22000}, {0x42f24000}, {0x42f26000},
+ {0x42f28000}, {0x42f2a000}, {0x42f2c000}, {0x42f2e000},
+ {0x42f30000}, {0x42f32000}, {0x42f34000}, {0x42f36000},
+ {0x42f38000}, {0x42f3a000}, {0x42f3c000}, {0x42f3e000},
+ {0x42f40000}, {0x42f42000}, {0x42f44000}, {0x42f46000},
+ {0x42f48000}, {0x42f4a000}, {0x42f4c000}, {0x42f4e000},
+ {0x42f50000}, {0x42f52000}, {0x42f54000}, {0x42f56000},
+ {0x42f58000}, {0x42f5a000}, {0x42f5c000}, {0x42f5e000},
+ {0x42f60000}, {0x42f62000}, {0x42f64000}, {0x42f66000},
+ {0x42f68000}, {0x42f6a000}, {0x42f6c000}, {0x42f6e000},
+ {0x42f70000}, {0x42f72000}, {0x42f74000}, {0x42f76000},
+ {0x42f78000}, {0x42f7a000}, {0x42f7c000}, {0x42f7e000},
+ {0x42f80000}, {0x42f82000}, {0x42f84000}, {0x42f86000},
+ {0x42f88000}, {0x42f8a000}, {0x42f8c000}, {0x42f8e000},
+ {0x42f90000}, {0x42f92000}, {0x42f94000}, {0x42f96000},
+ {0x42f98000}, {0x42f9a000}, {0x42f9c000}, {0x42f9e000},
+ {0x42fa0000}, {0x42fa2000}, {0x42fa4000}, {0x42fa6000},
+ {0x42fa8000}, {0x42faa000}, {0x42fac000}, {0x42fae000},
+ {0x42fb0000}, {0x42fb2000}, {0x42fb4000}, {0x42fb6000},
+ {0x42fb8000}, {0x42fba000}, {0x42fbc000}, {0x42fbe000},
+ {0x42fc0000}, {0x42fc2000}, {0x42fc4000}, {0x42fc6000},
+ {0x42fc8000}, {0x42fca000}, {0x42fcc000}, {0x42fce000},
+ {0x42fd0000}, {0x42fd2000}, {0x42fd4000}, {0x42fd6000},
+ {0x42fd8000}, {0x42fda000}, {0x42fdc000}, {0x42fde000},
+ {0x42fe0000}, {0x42fe2000}, {0x42fe4000}, {0x42fe6000},
+ {0x42fe8000}, {0x42fea000}, {0x42fec000}, {0x42fee000},
+ {0x42ff0000}, {0x42ff2000}, {0x42ff4000}, {0x42ff6000},
+ {0x42ff8000}, {0x42ffa000}, {0x42ffc000}, {0x42ffe000},
+ {0x43000000}, {0x43002000}, {0x43004000}, {0x43006000},
+ {0x43008000}, {0x4300a000}, {0x4300c000}, {0x4300e000},
+ {0x43010000}, {0x43012000}, {0x43014000}, {0x43016000},
+ {0x43018000}, {0x4301a000}, {0x4301c000}, {0x4301e000},
+ {0x43020000}, {0x43022000}, {0x43024000}, {0x43026000},
+ {0x43028000}, {0x4302a000}, {0x4302c000}, {0x4302e000},
+ {0x43030000}, {0x43032000}, {0x43034000}, {0x43036000},
+ {0x43038000}, {0x4303a000}, {0x4303c000}, {0x4303e000},
+ {0x43040000}, {0x43042000}, {0x43044000}, {0x43046000},
+ {0x43048000}, {0x4304a000}, {0x4304c000}, {0x4304e000},
+ {0x43050000}, {0x43052000}, {0x43054000}, {0x43056000},
+ {0x43058000}, {0x4305a000}, {0x4305c000}, {0x4305e000},
+ {0x43060000}, {0x43062000}, {0x43064000}, {0x43066000},
+ {0x43068000}, {0x4306a000}, {0x4306c000}, {0x4306e000},
+ {0x43070000}, {0x43072000}, {0x43074000}, {0x43076000},
+ {0x43078000}, {0x4307a000}, {0x4307c000}, {0x4307e000},
+ {0x43080000}, {0x43082000}, {0x43084000}, {0x43086000},
+ {0x43088000}, {0x4308a000}, {0x4308c000}, {0x4308e000},
+ {0x43090000}, {0x43092000}, {0x43094000}, {0x43096000},
+ {0x43098000}, {0x4309a000}, {0x4309c000}, {0x4309e000},
+ {0x430a0000}, {0x430a2000}, {0x430a4000}, {0x430a6000},
+ {0x430a8000}, {0x430aa000}, {0x430ac000}, {0x430ae000},
+ {0x430b0000}, {0x430b2000}, {0x430b4000}, {0x430b6000},
+ {0x430b8000}, {0x430ba000}, {0x430bc000}, {0x430be000},
+ {0x430c0000}, {0x430c2000}, {0x430c4000}, {0x430c6000},
+ {0x430c8000}, {0x430ca000}, {0x430cc000}, {0x430ce000},
+ {0x430d0000}, {0x430d2000}, {0x430d4000}, {0x430d6000},
+ {0x430d8000}, {0x430da000}, {0x430dc000}, {0x430de000},
+ {0x430e0000}, {0x430e2000}, {0x430e4000}, {0x430e6000},
+ {0x430e8000}, {0x430ea000}, {0x430ec000}, {0x430ee000},
+ {0x430f0000}, {0x430f2000}, {0x430f4000}, {0x430f6000},
+ {0x430f8000}, {0x430fa000}, {0x430fc000}, {0x430fe000},
+ {0x43100000}, {0x43102000}, {0x43104000}, {0x43106000},
+ {0x43108000}, {0x4310a000}, {0x4310c000}, {0x4310e000},
+ {0x43110000}, {0x43112000}, {0x43114000}, {0x43116000},
+ {0x43118000}, {0x4311a000}, {0x4311c000}, {0x4311e000},
+ {0x43120000}, {0x43122000}, {0x43124000}, {0x43126000},
+ {0x43128000}, {0x4312a000}, {0x4312c000}, {0x4312e000},
+ {0x43130000}, {0x43132000}, {0x43134000}, {0x43136000},
+ {0x43138000}, {0x4313a000}, {0x4313c000}, {0x4313e000},
+ {0x43140000}, {0x43142000}, {0x43144000}, {0x43146000},
+ {0x43148000}, {0x4314a000}, {0x4314c000}, {0x4314e000},
+ {0x43150000}, {0x43152000}, {0x43154000}, {0x43156000},
+ {0x43158000}, {0x4315a000}, {0x4315c000}, {0x4315e000},
+ {0x43160000}, {0x43162000}, {0x43164000}, {0x43166000},
+ {0x43168000}, {0x4316a000}, {0x4316c000}, {0x4316e000},
+ {0x43170000}, {0x43172000}, {0x43174000}, {0x43176000},
+ {0x43178000}, {0x4317a000}, {0x4317c000}, {0x4317e000},
+ {0x43180000}, {0x43182000}, {0x43184000}, {0x43186000},
+ {0x43188000}, {0x4318a000}, {0x4318c000}, {0x4318e000},
+ {0x43190000}, {0x43192000}, {0x43194000}, {0x43196000},
+ {0x43198000}, {0x4319a000}, {0x4319c000}, {0x4319e000},
+ {0x431a0000}, {0x431a2000}, {0x431a4000}, {0x431a6000},
+ {0x431a8000}, {0x431aa000}, {0x431ac000}, {0x431ae000},
+ {0x431b0000}, {0x431b2000}, {0x431b4000}, {0x431b6000},
+ {0x431b8000}, {0x431ba000}, {0x431bc000}, {0x431be000},
+ {0x431c0000}, {0x431c2000}, {0x431c4000}, {0x431c6000},
+ {0x431c8000}, {0x431ca000}, {0x431cc000}, {0x431ce000},
+ {0x431d0000}, {0x431d2000}, {0x431d4000}, {0x431d6000},
+ {0x431d8000}, {0x431da000}, {0x431dc000}, {0x431de000},
+ {0x431e0000}, {0x431e2000}, {0x431e4000}, {0x431e6000},
+ {0x431e8000}, {0x431ea000}, {0x431ec000}, {0x431ee000},
+ {0x431f0000}, {0x431f2000}, {0x431f4000}, {0x431f6000},
+ {0x431f8000}, {0x431fa000}, {0x431fc000}, {0x431fe000},
+ {0x43200000}, {0x43202000}, {0x43204000}, {0x43206000},
+ {0x43208000}, {0x4320a000}, {0x4320c000}, {0x4320e000},
+ {0x43210000}, {0x43212000}, {0x43214000}, {0x43216000},
+ {0x43218000}, {0x4321a000}, {0x4321c000}, {0x4321e000},
+ {0x43220000}, {0x43222000}, {0x43224000}, {0x43226000},
+ {0x43228000}, {0x4322a000}, {0x4322c000}, {0x4322e000},
+ {0x43230000}, {0x43232000}, {0x43234000}, {0x43236000},
+ {0x43238000}, {0x4323a000}, {0x4323c000}, {0x4323e000},
+ {0x43240000}, {0x43242000}, {0x43244000}, {0x43246000},
+ {0x43248000}, {0x4324a000}, {0x4324c000}, {0x4324e000},
+ {0x43250000}, {0x43252000}, {0x43254000}, {0x43256000},
+ {0x43258000}, {0x4325a000}, {0x4325c000}, {0x4325e000},
+ {0x43260000}, {0x43262000}, {0x43264000}, {0x43266000},
+ {0x43268000}, {0x4326a000}, {0x4326c000}, {0x4326e000},
+ {0x43270000}, {0x43272000}, {0x43274000}, {0x43276000},
+ {0x43278000}, {0x4327a000}, {0x4327c000}, {0x4327e000},
+ {0x43280000}, {0x43282000}, {0x43284000}, {0x43286000},
+ {0x43288000}, {0x4328a000}, {0x4328c000}, {0x4328e000},
+ {0x43290000}, {0x43292000}, {0x43294000}, {0x43296000},
+ {0x43298000}, {0x4329a000}, {0x4329c000}, {0x4329e000},
+ {0x432a0000}, {0x432a2000}, {0x432a4000}, {0x432a6000},
+ {0x432a8000}, {0x432aa000}, {0x432ac000}, {0x432ae000},
+ {0x432b0000}, {0x432b2000}, {0x432b4000}, {0x432b6000},
+ {0x432b8000}, {0x432ba000}, {0x432bc000}, {0x432be000},
+ {0x432c0000}, {0x432c2000}, {0x432c4000}, {0x432c6000},
+ {0x432c8000}, {0x432ca000}, {0x432cc000}, {0x432ce000},
+ {0x432d0000}, {0x432d2000}, {0x432d4000}, {0x432d6000},
+ {0x432d8000}, {0x432da000}, {0x432dc000}, {0x432de000},
+ {0x432e0000}, {0x432e2000}, {0x432e4000}, {0x432e6000},
+ {0x432e8000}, {0x432ea000}, {0x432ec000}, {0x432ee000},
+ {0x432f0000}, {0x432f2000}, {0x432f4000}, {0x432f6000},
+ {0x432f8000}, {0x432fa000}, {0x432fc000}, {0x432fe000},
+ {0x43300000}, {0x43302000}, {0x43304000}, {0x43306000},
+ {0x43308000}, {0x4330a000}, {0x4330c000}, {0x4330e000},
+ {0x43310000}, {0x43312000}, {0x43314000}, {0x43316000},
+ {0x43318000}, {0x4331a000}, {0x4331c000}, {0x4331e000},
+ {0x43320000}, {0x43322000}, {0x43324000}, {0x43326000},
+ {0x43328000}, {0x4332a000}, {0x4332c000}, {0x4332e000},
+ {0x43330000}, {0x43332000}, {0x43334000}, {0x43336000},
+ {0x43338000}, {0x4333a000}, {0x4333c000}, {0x4333e000},
+ {0x43340000}, {0x43342000}, {0x43344000}, {0x43346000},
+ {0x43348000}, {0x4334a000}, {0x4334c000}, {0x4334e000},
+ {0x43350000}, {0x43352000}, {0x43354000}, {0x43356000},
+ {0x43358000}, {0x4335a000}, {0x4335c000}, {0x4335e000},
+ {0x43360000}, {0x43362000}, {0x43364000}, {0x43366000},
+ {0x43368000}, {0x4336a000}, {0x4336c000}, {0x4336e000},
+ {0x43370000}, {0x43372000}, {0x43374000}, {0x43376000},
+ {0x43378000}, {0x4337a000}, {0x4337c000}, {0x4337e000},
+ {0x43380000}, {0x43382000}, {0x43384000}, {0x43386000},
+ {0x43388000}, {0x4338a000}, {0x4338c000}, {0x4338e000},
+ {0x43390000}, {0x43392000}, {0x43394000}, {0x43396000},
+ {0x43398000}, {0x4339a000}, {0x4339c000}, {0x4339e000},
+ {0x433a0000}, {0x433a2000}, {0x433a4000}, {0x433a6000},
+ {0x433a8000}, {0x433aa000}, {0x433ac000}, {0x433ae000},
+ {0x433b0000}, {0x433b2000}, {0x433b4000}, {0x433b6000},
+ {0x433b8000}, {0x433ba000}, {0x433bc000}, {0x433be000},
+ {0x433c0000}, {0x433c2000}, {0x433c4000}, {0x433c6000},
+ {0x433c8000}, {0x433ca000}, {0x433cc000}, {0x433ce000},
+ {0x433d0000}, {0x433d2000}, {0x433d4000}, {0x433d6000},
+ {0x433d8000}, {0x433da000}, {0x433dc000}, {0x433de000},
+ {0x433e0000}, {0x433e2000}, {0x433e4000}, {0x433e6000},
+ {0x433e8000}, {0x433ea000}, {0x433ec000}, {0x433ee000},
+ {0x433f0000}, {0x433f2000}, {0x433f4000}, {0x433f6000},
+ {0x433f8000}, {0x433fa000}, {0x433fc000}, {0x433fe000},
+ {0x43400000}, {0x43402000}, {0x43404000}, {0x43406000},
+ {0x43408000}, {0x4340a000}, {0x4340c000}, {0x4340e000},
+ {0x43410000}, {0x43412000}, {0x43414000}, {0x43416000},
+ {0x43418000}, {0x4341a000}, {0x4341c000}, {0x4341e000},
+ {0x43420000}, {0x43422000}, {0x43424000}, {0x43426000},
+ {0x43428000}, {0x4342a000}, {0x4342c000}, {0x4342e000},
+ {0x43430000}, {0x43432000}, {0x43434000}, {0x43436000},
+ {0x43438000}, {0x4343a000}, {0x4343c000}, {0x4343e000},
+ {0x43440000}, {0x43442000}, {0x43444000}, {0x43446000},
+ {0x43448000}, {0x4344a000}, {0x4344c000}, {0x4344e000},
+ {0x43450000}, {0x43452000}, {0x43454000}, {0x43456000},
+ {0x43458000}, {0x4345a000}, {0x4345c000}, {0x4345e000},
+ {0x43460000}, {0x43462000}, {0x43464000}, {0x43466000},
+ {0x43468000}, {0x4346a000}, {0x4346c000}, {0x4346e000},
+ {0x43470000}, {0x43472000}, {0x43474000}, {0x43476000},
+ {0x43478000}, {0x4347a000}, {0x4347c000}, {0x4347e000},
+ {0x43480000}, {0x43482000}, {0x43484000}, {0x43486000},
+ {0x43488000}, {0x4348a000}, {0x4348c000}, {0x4348e000},
+ {0x43490000}, {0x43492000}, {0x43494000}, {0x43496000},
+ {0x43498000}, {0x4349a000}, {0x4349c000}, {0x4349e000},
+ {0x434a0000}, {0x434a2000}, {0x434a4000}, {0x434a6000},
+ {0x434a8000}, {0x434aa000}, {0x434ac000}, {0x434ae000},
+ {0x434b0000}, {0x434b2000}, {0x434b4000}, {0x434b6000},
+ {0x434b8000}, {0x434ba000}, {0x434bc000}, {0x434be000},
+ {0x434c0000}, {0x434c2000}, {0x434c4000}, {0x434c6000},
+ {0x434c8000}, {0x434ca000}, {0x434cc000}, {0x434ce000},
+ {0x434d0000}, {0x434d2000}, {0x434d4000}, {0x434d6000},
+ {0x434d8000}, {0x434da000}, {0x434dc000}, {0x434de000},
+ {0x434e0000}, {0x434e2000}, {0x434e4000}, {0x434e6000},
+ {0x434e8000}, {0x434ea000}, {0x434ec000}, {0x434ee000},
+ {0x434f0000}, {0x434f2000}, {0x434f4000}, {0x434f6000},
+ {0x434f8000}, {0x434fa000}, {0x434fc000}, {0x434fe000},
+ {0x43500000}, {0x43502000}, {0x43504000}, {0x43506000},
+ {0x43508000}, {0x4350a000}, {0x4350c000}, {0x4350e000},
+ {0x43510000}, {0x43512000}, {0x43514000}, {0x43516000},
+ {0x43518000}, {0x4351a000}, {0x4351c000}, {0x4351e000},
+ {0x43520000}, {0x43522000}, {0x43524000}, {0x43526000},
+ {0x43528000}, {0x4352a000}, {0x4352c000}, {0x4352e000},
+ {0x43530000}, {0x43532000}, {0x43534000}, {0x43536000},
+ {0x43538000}, {0x4353a000}, {0x4353c000}, {0x4353e000},
+ {0x43540000}, {0x43542000}, {0x43544000}, {0x43546000},
+ {0x43548000}, {0x4354a000}, {0x4354c000}, {0x4354e000},
+ {0x43550000}, {0x43552000}, {0x43554000}, {0x43556000},
+ {0x43558000}, {0x4355a000}, {0x4355c000}, {0x4355e000},
+ {0x43560000}, {0x43562000}, {0x43564000}, {0x43566000},
+ {0x43568000}, {0x4356a000}, {0x4356c000}, {0x4356e000},
+ {0x43570000}, {0x43572000}, {0x43574000}, {0x43576000},
+ {0x43578000}, {0x4357a000}, {0x4357c000}, {0x4357e000},
+ {0x43580000}, {0x43582000}, {0x43584000}, {0x43586000},
+ {0x43588000}, {0x4358a000}, {0x4358c000}, {0x4358e000},
+ {0x43590000}, {0x43592000}, {0x43594000}, {0x43596000},
+ {0x43598000}, {0x4359a000}, {0x4359c000}, {0x4359e000},
+ {0x435a0000}, {0x435a2000}, {0x435a4000}, {0x435a6000},
+ {0x435a8000}, {0x435aa000}, {0x435ac000}, {0x435ae000},
+ {0x435b0000}, {0x435b2000}, {0x435b4000}, {0x435b6000},
+ {0x435b8000}, {0x435ba000}, {0x435bc000}, {0x435be000},
+ {0x435c0000}, {0x435c2000}, {0x435c4000}, {0x435c6000},
+ {0x435c8000}, {0x435ca000}, {0x435cc000}, {0x435ce000},
+ {0x435d0000}, {0x435d2000}, {0x435d4000}, {0x435d6000},
+ {0x435d8000}, {0x435da000}, {0x435dc000}, {0x435de000},
+ {0x435e0000}, {0x435e2000}, {0x435e4000}, {0x435e6000},
+ {0x435e8000}, {0x435ea000}, {0x435ec000}, {0x435ee000},
+ {0x435f0000}, {0x435f2000}, {0x435f4000}, {0x435f6000},
+ {0x435f8000}, {0x435fa000}, {0x435fc000}, {0x435fe000},
+ {0x43600000}, {0x43602000}, {0x43604000}, {0x43606000},
+ {0x43608000}, {0x4360a000}, {0x4360c000}, {0x4360e000},
+ {0x43610000}, {0x43612000}, {0x43614000}, {0x43616000},
+ {0x43618000}, {0x4361a000}, {0x4361c000}, {0x4361e000},
+ {0x43620000}, {0x43622000}, {0x43624000}, {0x43626000},
+ {0x43628000}, {0x4362a000}, {0x4362c000}, {0x4362e000},
+ {0x43630000}, {0x43632000}, {0x43634000}, {0x43636000},
+ {0x43638000}, {0x4363a000}, {0x4363c000}, {0x4363e000},
+ {0x43640000}, {0x43642000}, {0x43644000}, {0x43646000},
+ {0x43648000}, {0x4364a000}, {0x4364c000}, {0x4364e000},
+ {0x43650000}, {0x43652000}, {0x43654000}, {0x43656000},
+ {0x43658000}, {0x4365a000}, {0x4365c000}, {0x4365e000},
+ {0x43660000}, {0x43662000}, {0x43664000}, {0x43666000},
+ {0x43668000}, {0x4366a000}, {0x4366c000}, {0x4366e000},
+ {0x43670000}, {0x43672000}, {0x43674000}, {0x43676000},
+ {0x43678000}, {0x4367a000}, {0x4367c000}, {0x4367e000},
+ {0x43680000}, {0x43682000}, {0x43684000}, {0x43686000},
+ {0x43688000}, {0x4368a000}, {0x4368c000}, {0x4368e000},
+ {0x43690000}, {0x43692000}, {0x43694000}, {0x43696000},
+ {0x43698000}, {0x4369a000}, {0x4369c000}, {0x4369e000},
+ {0x436a0000}, {0x436a2000}, {0x436a4000}, {0x436a6000},
+ {0x436a8000}, {0x436aa000}, {0x436ac000}, {0x436ae000},
+ {0x436b0000}, {0x436b2000}, {0x436b4000}, {0x436b6000},
+ {0x436b8000}, {0x436ba000}, {0x436bc000}, {0x436be000},
+ {0x436c0000}, {0x436c2000}, {0x436c4000}, {0x436c6000},
+ {0x436c8000}, {0x436ca000}, {0x436cc000}, {0x436ce000},
+ {0x436d0000}, {0x436d2000}, {0x436d4000}, {0x436d6000},
+ {0x436d8000}, {0x436da000}, {0x436dc000}, {0x436de000},
+ {0x436e0000}, {0x436e2000}, {0x436e4000}, {0x436e6000},
+ {0x436e8000}, {0x436ea000}, {0x436ec000}, {0x436ee000},
+ {0x436f0000}, {0x436f2000}, {0x436f4000}, {0x436f6000},
+ {0x436f8000}, {0x436fa000}, {0x436fc000}, {0x436fe000},
+ {0x43700000}, {0x43702000}, {0x43704000}, {0x43706000},
+ {0x43708000}, {0x4370a000}, {0x4370c000}, {0x4370e000},
+ {0x43710000}, {0x43712000}, {0x43714000}, {0x43716000},
+ {0x43718000}, {0x4371a000}, {0x4371c000}, {0x4371e000},
+ {0x43720000}, {0x43722000}, {0x43724000}, {0x43726000},
+ {0x43728000}, {0x4372a000}, {0x4372c000}, {0x4372e000},
+ {0x43730000}, {0x43732000}, {0x43734000}, {0x43736000},
+ {0x43738000}, {0x4373a000}, {0x4373c000}, {0x4373e000},
+ {0x43740000}, {0x43742000}, {0x43744000}, {0x43746000},
+ {0x43748000}, {0x4374a000}, {0x4374c000}, {0x4374e000},
+ {0x43750000}, {0x43752000}, {0x43754000}, {0x43756000},
+ {0x43758000}, {0x4375a000}, {0x4375c000}, {0x4375e000},
+ {0x43760000}, {0x43762000}, {0x43764000}, {0x43766000},
+ {0x43768000}, {0x4376a000}, {0x4376c000}, {0x4376e000},
+ {0x43770000}, {0x43772000}, {0x43774000}, {0x43776000},
+ {0x43778000}, {0x4377a000}, {0x4377c000}, {0x4377e000},
+ {0x43780000}, {0x43782000}, {0x43784000}, {0x43786000},
+ {0x43788000}, {0x4378a000}, {0x4378c000}, {0x4378e000},
+ {0x43790000}, {0x43792000}, {0x43794000}, {0x43796000},
+ {0x43798000}, {0x4379a000}, {0x4379c000}, {0x4379e000},
+ {0x437a0000}, {0x437a2000}, {0x437a4000}, {0x437a6000},
+ {0x437a8000}, {0x437aa000}, {0x437ac000}, {0x437ae000},
+ {0x437b0000}, {0x437b2000}, {0x437b4000}, {0x437b6000},
+ {0x437b8000}, {0x437ba000}, {0x437bc000}, {0x437be000},
+ {0x437c0000}, {0x437c2000}, {0x437c4000}, {0x437c6000},
+ {0x437c8000}, {0x437ca000}, {0x437cc000}, {0x437ce000},
+ {0x437d0000}, {0x437d2000}, {0x437d4000}, {0x437d6000},
+ {0x437d8000}, {0x437da000}, {0x437dc000}, {0x437de000},
+ {0x437e0000}, {0x437e2000}, {0x437e4000}, {0x437e6000},
+ {0x437e8000}, {0x437ea000}, {0x437ec000}, {0x437ee000},
+ {0x437f0000}, {0x437f2000}, {0x437f4000}, {0x437f6000},
+ {0x437f8000}, {0x437fa000}, {0x437fc000}, {0x437fe000},
+ {0x43800000}, {0x43802000}, {0x43804000}, {0x43806000},
+ {0x43808000}, {0x4380a000}, {0x4380c000}, {0x4380e000},
+ {0x43810000}, {0x43812000}, {0x43814000}, {0x43816000},
+ {0x43818000}, {0x4381a000}, {0x4381c000}, {0x4381e000},
+ {0x43820000}, {0x43822000}, {0x43824000}, {0x43826000},
+ {0x43828000}, {0x4382a000}, {0x4382c000}, {0x4382e000},
+ {0x43830000}, {0x43832000}, {0x43834000}, {0x43836000},
+ {0x43838000}, {0x4383a000}, {0x4383c000}, {0x4383e000},
+ {0x43840000}, {0x43842000}, {0x43844000}, {0x43846000},
+ {0x43848000}, {0x4384a000}, {0x4384c000}, {0x4384e000},
+ {0x43850000}, {0x43852000}, {0x43854000}, {0x43856000},
+ {0x43858000}, {0x4385a000}, {0x4385c000}, {0x4385e000},
+ {0x43860000}, {0x43862000}, {0x43864000}, {0x43866000},
+ {0x43868000}, {0x4386a000}, {0x4386c000}, {0x4386e000},
+ {0x43870000}, {0x43872000}, {0x43874000}, {0x43876000},
+ {0x43878000}, {0x4387a000}, {0x4387c000}, {0x4387e000},
+ {0x43880000}, {0x43882000}, {0x43884000}, {0x43886000},
+ {0x43888000}, {0x4388a000}, {0x4388c000}, {0x4388e000},
+ {0x43890000}, {0x43892000}, {0x43894000}, {0x43896000},
+ {0x43898000}, {0x4389a000}, {0x4389c000}, {0x4389e000},
+ {0x438a0000}, {0x438a2000}, {0x438a4000}, {0x438a6000},
+ {0x438a8000}, {0x438aa000}, {0x438ac000}, {0x438ae000},
+ {0x438b0000}, {0x438b2000}, {0x438b4000}, {0x438b6000},
+ {0x438b8000}, {0x438ba000}, {0x438bc000}, {0x438be000},
+ {0x438c0000}, {0x438c2000}, {0x438c4000}, {0x438c6000},
+ {0x438c8000}, {0x438ca000}, {0x438cc000}, {0x438ce000},
+ {0x438d0000}, {0x438d2000}, {0x438d4000}, {0x438d6000},
+ {0x438d8000}, {0x438da000}, {0x438dc000}, {0x438de000},
+ {0x438e0000}, {0x438e2000}, {0x438e4000}, {0x438e6000},
+ {0x438e8000}, {0x438ea000}, {0x438ec000}, {0x438ee000},
+ {0x438f0000}, {0x438f2000}, {0x438f4000}, {0x438f6000},
+ {0x438f8000}, {0x438fa000}, {0x438fc000}, {0x438fe000},
+ {0x43900000}, {0x43902000}, {0x43904000}, {0x43906000},
+ {0x43908000}, {0x4390a000}, {0x4390c000}, {0x4390e000},
+ {0x43910000}, {0x43912000}, {0x43914000}, {0x43916000},
+ {0x43918000}, {0x4391a000}, {0x4391c000}, {0x4391e000},
+ {0x43920000}, {0x43922000}, {0x43924000}, {0x43926000},
+ {0x43928000}, {0x4392a000}, {0x4392c000}, {0x4392e000},
+ {0x43930000}, {0x43932000}, {0x43934000}, {0x43936000},
+ {0x43938000}, {0x4393a000}, {0x4393c000}, {0x4393e000},
+ {0x43940000}, {0x43942000}, {0x43944000}, {0x43946000},
+ {0x43948000}, {0x4394a000}, {0x4394c000}, {0x4394e000},
+ {0x43950000}, {0x43952000}, {0x43954000}, {0x43956000},
+ {0x43958000}, {0x4395a000}, {0x4395c000}, {0x4395e000},
+ {0x43960000}, {0x43962000}, {0x43964000}, {0x43966000},
+ {0x43968000}, {0x4396a000}, {0x4396c000}, {0x4396e000},
+ {0x43970000}, {0x43972000}, {0x43974000}, {0x43976000},
+ {0x43978000}, {0x4397a000}, {0x4397c000}, {0x4397e000},
+ {0x43980000}, {0x43982000}, {0x43984000}, {0x43986000},
+ {0x43988000}, {0x4398a000}, {0x4398c000}, {0x4398e000},
+ {0x43990000}, {0x43992000}, {0x43994000}, {0x43996000},
+ {0x43998000}, {0x4399a000}, {0x4399c000}, {0x4399e000},
+ {0x439a0000}, {0x439a2000}, {0x439a4000}, {0x439a6000},
+ {0x439a8000}, {0x439aa000}, {0x439ac000}, {0x439ae000},
+ {0x439b0000}, {0x439b2000}, {0x439b4000}, {0x439b6000},
+ {0x439b8000}, {0x439ba000}, {0x439bc000}, {0x439be000},
+ {0x439c0000}, {0x439c2000}, {0x439c4000}, {0x439c6000},
+ {0x439c8000}, {0x439ca000}, {0x439cc000}, {0x439ce000},
+ {0x439d0000}, {0x439d2000}, {0x439d4000}, {0x439d6000},
+ {0x439d8000}, {0x439da000}, {0x439dc000}, {0x439de000},
+ {0x439e0000}, {0x439e2000}, {0x439e4000}, {0x439e6000},
+ {0x439e8000}, {0x439ea000}, {0x439ec000}, {0x439ee000},
+ {0x439f0000}, {0x439f2000}, {0x439f4000}, {0x439f6000},
+ {0x439f8000}, {0x439fa000}, {0x439fc000}, {0x439fe000},
+ {0x43a00000}, {0x43a02000}, {0x43a04000}, {0x43a06000},
+ {0x43a08000}, {0x43a0a000}, {0x43a0c000}, {0x43a0e000},
+ {0x43a10000}, {0x43a12000}, {0x43a14000}, {0x43a16000},
+ {0x43a18000}, {0x43a1a000}, {0x43a1c000}, {0x43a1e000},
+ {0x43a20000}, {0x43a22000}, {0x43a24000}, {0x43a26000},
+ {0x43a28000}, {0x43a2a000}, {0x43a2c000}, {0x43a2e000},
+ {0x43a30000}, {0x43a32000}, {0x43a34000}, {0x43a36000},
+ {0x43a38000}, {0x43a3a000}, {0x43a3c000}, {0x43a3e000},
+ {0x43a40000}, {0x43a42000}, {0x43a44000}, {0x43a46000},
+ {0x43a48000}, {0x43a4a000}, {0x43a4c000}, {0x43a4e000},
+ {0x43a50000}, {0x43a52000}, {0x43a54000}, {0x43a56000},
+ {0x43a58000}, {0x43a5a000}, {0x43a5c000}, {0x43a5e000},
+ {0x43a60000}, {0x43a62000}, {0x43a64000}, {0x43a66000},
+ {0x43a68000}, {0x43a6a000}, {0x43a6c000}, {0x43a6e000},
+ {0x43a70000}, {0x43a72000}, {0x43a74000}, {0x43a76000},
+ {0x43a78000}, {0x43a7a000}, {0x43a7c000}, {0x43a7e000},
+ {0x43a80000}, {0x43a82000}, {0x43a84000}, {0x43a86000},
+ {0x43a88000}, {0x43a8a000}, {0x43a8c000}, {0x43a8e000},
+ {0x43a90000}, {0x43a92000}, {0x43a94000}, {0x43a96000},
+ {0x43a98000}, {0x43a9a000}, {0x43a9c000}, {0x43a9e000},
+ {0x43aa0000}, {0x43aa2000}, {0x43aa4000}, {0x43aa6000},
+ {0x43aa8000}, {0x43aaa000}, {0x43aac000}, {0x43aae000},
+ {0x43ab0000}, {0x43ab2000}, {0x43ab4000}, {0x43ab6000},
+ {0x43ab8000}, {0x43aba000}, {0x43abc000}, {0x43abe000},
+ {0x43ac0000}, {0x43ac2000}, {0x43ac4000}, {0x43ac6000},
+ {0x43ac8000}, {0x43aca000}, {0x43acc000}, {0x43ace000},
+ {0x43ad0000}, {0x43ad2000}, {0x43ad4000}, {0x43ad6000},
+ {0x43ad8000}, {0x43ada000}, {0x43adc000}, {0x43ade000},
+ {0x43ae0000}, {0x43ae2000}, {0x43ae4000}, {0x43ae6000},
+ {0x43ae8000}, {0x43aea000}, {0x43aec000}, {0x43aee000},
+ {0x43af0000}, {0x43af2000}, {0x43af4000}, {0x43af6000},
+ {0x43af8000}, {0x43afa000}, {0x43afc000}, {0x43afe000},
+ {0x43b00000}, {0x43b02000}, {0x43b04000}, {0x43b06000},
+ {0x43b08000}, {0x43b0a000}, {0x43b0c000}, {0x43b0e000},
+ {0x43b10000}, {0x43b12000}, {0x43b14000}, {0x43b16000},
+ {0x43b18000}, {0x43b1a000}, {0x43b1c000}, {0x43b1e000},
+ {0x43b20000}, {0x43b22000}, {0x43b24000}, {0x43b26000},
+ {0x43b28000}, {0x43b2a000}, {0x43b2c000}, {0x43b2e000},
+ {0x43b30000}, {0x43b32000}, {0x43b34000}, {0x43b36000},
+ {0x43b38000}, {0x43b3a000}, {0x43b3c000}, {0x43b3e000},
+ {0x43b40000}, {0x43b42000}, {0x43b44000}, {0x43b46000},
+ {0x43b48000}, {0x43b4a000}, {0x43b4c000}, {0x43b4e000},
+ {0x43b50000}, {0x43b52000}, {0x43b54000}, {0x43b56000},
+ {0x43b58000}, {0x43b5a000}, {0x43b5c000}, {0x43b5e000},
+ {0x43b60000}, {0x43b62000}, {0x43b64000}, {0x43b66000},
+ {0x43b68000}, {0x43b6a000}, {0x43b6c000}, {0x43b6e000},
+ {0x43b70000}, {0x43b72000}, {0x43b74000}, {0x43b76000},
+ {0x43b78000}, {0x43b7a000}, {0x43b7c000}, {0x43b7e000},
+ {0x43b80000}, {0x43b82000}, {0x43b84000}, {0x43b86000},
+ {0x43b88000}, {0x43b8a000}, {0x43b8c000}, {0x43b8e000},
+ {0x43b90000}, {0x43b92000}, {0x43b94000}, {0x43b96000},
+ {0x43b98000}, {0x43b9a000}, {0x43b9c000}, {0x43b9e000},
+ {0x43ba0000}, {0x43ba2000}, {0x43ba4000}, {0x43ba6000},
+ {0x43ba8000}, {0x43baa000}, {0x43bac000}, {0x43bae000},
+ {0x43bb0000}, {0x43bb2000}, {0x43bb4000}, {0x43bb6000},
+ {0x43bb8000}, {0x43bba000}, {0x43bbc000}, {0x43bbe000},
+ {0x43bc0000}, {0x43bc2000}, {0x43bc4000}, {0x43bc6000},
+ {0x43bc8000}, {0x43bca000}, {0x43bcc000}, {0x43bce000},
+ {0x43bd0000}, {0x43bd2000}, {0x43bd4000}, {0x43bd6000},
+ {0x43bd8000}, {0x43bda000}, {0x43bdc000}, {0x43bde000},
+ {0x43be0000}, {0x43be2000}, {0x43be4000}, {0x43be6000},
+ {0x43be8000}, {0x43bea000}, {0x43bec000}, {0x43bee000},
+ {0x43bf0000}, {0x43bf2000}, {0x43bf4000}, {0x43bf6000},
+ {0x43bf8000}, {0x43bfa000}, {0x43bfc000}, {0x43bfe000},
+ {0x43c00000}, {0x43c02000}, {0x43c04000}, {0x43c06000},
+ {0x43c08000}, {0x43c0a000}, {0x43c0c000}, {0x43c0e000},
+ {0x43c10000}, {0x43c12000}, {0x43c14000}, {0x43c16000},
+ {0x43c18000}, {0x43c1a000}, {0x43c1c000}, {0x43c1e000},
+ {0x43c20000}, {0x43c22000}, {0x43c24000}, {0x43c26000},
+ {0x43c28000}, {0x43c2a000}, {0x43c2c000}, {0x43c2e000},
+ {0x43c30000}, {0x43c32000}, {0x43c34000}, {0x43c36000},
+ {0x43c38000}, {0x43c3a000}, {0x43c3c000}, {0x43c3e000},
+ {0x43c40000}, {0x43c42000}, {0x43c44000}, {0x43c46000},
+ {0x43c48000}, {0x43c4a000}, {0x43c4c000}, {0x43c4e000},
+ {0x43c50000}, {0x43c52000}, {0x43c54000}, {0x43c56000},
+ {0x43c58000}, {0x43c5a000}, {0x43c5c000}, {0x43c5e000},
+ {0x43c60000}, {0x43c62000}, {0x43c64000}, {0x43c66000},
+ {0x43c68000}, {0x43c6a000}, {0x43c6c000}, {0x43c6e000},
+ {0x43c70000}, {0x43c72000}, {0x43c74000}, {0x43c76000},
+ {0x43c78000}, {0x43c7a000}, {0x43c7c000}, {0x43c7e000},
+ {0x43c80000}, {0x43c82000}, {0x43c84000}, {0x43c86000},
+ {0x43c88000}, {0x43c8a000}, {0x43c8c000}, {0x43c8e000},
+ {0x43c90000}, {0x43c92000}, {0x43c94000}, {0x43c96000},
+ {0x43c98000}, {0x43c9a000}, {0x43c9c000}, {0x43c9e000},
+ {0x43ca0000}, {0x43ca2000}, {0x43ca4000}, {0x43ca6000},
+ {0x43ca8000}, {0x43caa000}, {0x43cac000}, {0x43cae000},
+ {0x43cb0000}, {0x43cb2000}, {0x43cb4000}, {0x43cb6000},
+ {0x43cb8000}, {0x43cba000}, {0x43cbc000}, {0x43cbe000},
+ {0x43cc0000}, {0x43cc2000}, {0x43cc4000}, {0x43cc6000},
+ {0x43cc8000}, {0x43cca000}, {0x43ccc000}, {0x43cce000},
+ {0x43cd0000}, {0x43cd2000}, {0x43cd4000}, {0x43cd6000},
+ {0x43cd8000}, {0x43cda000}, {0x43cdc000}, {0x43cde000},
+ {0x43ce0000}, {0x43ce2000}, {0x43ce4000}, {0x43ce6000},
+ {0x43ce8000}, {0x43cea000}, {0x43cec000}, {0x43cee000},
+ {0x43cf0000}, {0x43cf2000}, {0x43cf4000}, {0x43cf6000},
+ {0x43cf8000}, {0x43cfa000}, {0x43cfc000}, {0x43cfe000},
+ {0x43d00000}, {0x43d02000}, {0x43d04000}, {0x43d06000},
+ {0x43d08000}, {0x43d0a000}, {0x43d0c000}, {0x43d0e000},
+ {0x43d10000}, {0x43d12000}, {0x43d14000}, {0x43d16000},
+ {0x43d18000}, {0x43d1a000}, {0x43d1c000}, {0x43d1e000},
+ {0x43d20000}, {0x43d22000}, {0x43d24000}, {0x43d26000},
+ {0x43d28000}, {0x43d2a000}, {0x43d2c000}, {0x43d2e000},
+ {0x43d30000}, {0x43d32000}, {0x43d34000}, {0x43d36000},
+ {0x43d38000}, {0x43d3a000}, {0x43d3c000}, {0x43d3e000},
+ {0x43d40000}, {0x43d42000}, {0x43d44000}, {0x43d46000},
+ {0x43d48000}, {0x43d4a000}, {0x43d4c000}, {0x43d4e000},
+ {0x43d50000}, {0x43d52000}, {0x43d54000}, {0x43d56000},
+ {0x43d58000}, {0x43d5a000}, {0x43d5c000}, {0x43d5e000},
+ {0x43d60000}, {0x43d62000}, {0x43d64000}, {0x43d66000},
+ {0x43d68000}, {0x43d6a000}, {0x43d6c000}, {0x43d6e000},
+ {0x43d70000}, {0x43d72000}, {0x43d74000}, {0x43d76000},
+ {0x43d78000}, {0x43d7a000}, {0x43d7c000}, {0x43d7e000},
+ {0x43d80000}, {0x43d82000}, {0x43d84000}, {0x43d86000},
+ {0x43d88000}, {0x43d8a000}, {0x43d8c000}, {0x43d8e000},
+ {0x43d90000}, {0x43d92000}, {0x43d94000}, {0x43d96000},
+ {0x43d98000}, {0x43d9a000}, {0x43d9c000}, {0x43d9e000},
+ {0x43da0000}, {0x43da2000}, {0x43da4000}, {0x43da6000},
+ {0x43da8000}, {0x43daa000}, {0x43dac000}, {0x43dae000},
+ {0x43db0000}, {0x43db2000}, {0x43db4000}, {0x43db6000},
+ {0x43db8000}, {0x43dba000}, {0x43dbc000}, {0x43dbe000},
+ {0x43dc0000}, {0x43dc2000}, {0x43dc4000}, {0x43dc6000},
+ {0x43dc8000}, {0x43dca000}, {0x43dcc000}, {0x43dce000},
+ {0x43dd0000}, {0x43dd2000}, {0x43dd4000}, {0x43dd6000},
+ {0x43dd8000}, {0x43dda000}, {0x43ddc000}, {0x43dde000},
+ {0x43de0000}, {0x43de2000}, {0x43de4000}, {0x43de6000},
+ {0x43de8000}, {0x43dea000}, {0x43dec000}, {0x43dee000},
+ {0x43df0000}, {0x43df2000}, {0x43df4000}, {0x43df6000},
+ {0x43df8000}, {0x43dfa000}, {0x43dfc000}, {0x43dfe000},
+ {0x43e00000}, {0x43e02000}, {0x43e04000}, {0x43e06000},
+ {0x43e08000}, {0x43e0a000}, {0x43e0c000}, {0x43e0e000},
+ {0x43e10000}, {0x43e12000}, {0x43e14000}, {0x43e16000},
+ {0x43e18000}, {0x43e1a000}, {0x43e1c000}, {0x43e1e000},
+ {0x43e20000}, {0x43e22000}, {0x43e24000}, {0x43e26000},
+ {0x43e28000}, {0x43e2a000}, {0x43e2c000}, {0x43e2e000},
+ {0x43e30000}, {0x43e32000}, {0x43e34000}, {0x43e36000},
+ {0x43e38000}, {0x43e3a000}, {0x43e3c000}, {0x43e3e000},
+ {0x43e40000}, {0x43e42000}, {0x43e44000}, {0x43e46000},
+ {0x43e48000}, {0x43e4a000}, {0x43e4c000}, {0x43e4e000},
+ {0x43e50000}, {0x43e52000}, {0x43e54000}, {0x43e56000},
+ {0x43e58000}, {0x43e5a000}, {0x43e5c000}, {0x43e5e000},
+ {0x43e60000}, {0x43e62000}, {0x43e64000}, {0x43e66000},
+ {0x43e68000}, {0x43e6a000}, {0x43e6c000}, {0x43e6e000},
+ {0x43e70000}, {0x43e72000}, {0x43e74000}, {0x43e76000},
+ {0x43e78000}, {0x43e7a000}, {0x43e7c000}, {0x43e7e000},
+ {0x43e80000}, {0x43e82000}, {0x43e84000}, {0x43e86000},
+ {0x43e88000}, {0x43e8a000}, {0x43e8c000}, {0x43e8e000},
+ {0x43e90000}, {0x43e92000}, {0x43e94000}, {0x43e96000},
+ {0x43e98000}, {0x43e9a000}, {0x43e9c000}, {0x43e9e000},
+ {0x43ea0000}, {0x43ea2000}, {0x43ea4000}, {0x43ea6000},
+ {0x43ea8000}, {0x43eaa000}, {0x43eac000}, {0x43eae000},
+ {0x43eb0000}, {0x43eb2000}, {0x43eb4000}, {0x43eb6000},
+ {0x43eb8000}, {0x43eba000}, {0x43ebc000}, {0x43ebe000},
+ {0x43ec0000}, {0x43ec2000}, {0x43ec4000}, {0x43ec6000},
+ {0x43ec8000}, {0x43eca000}, {0x43ecc000}, {0x43ece000},
+ {0x43ed0000}, {0x43ed2000}, {0x43ed4000}, {0x43ed6000},
+ {0x43ed8000}, {0x43eda000}, {0x43edc000}, {0x43ede000},
+ {0x43ee0000}, {0x43ee2000}, {0x43ee4000}, {0x43ee6000},
+ {0x43ee8000}, {0x43eea000}, {0x43eec000}, {0x43eee000},
+ {0x43ef0000}, {0x43ef2000}, {0x43ef4000}, {0x43ef6000},
+ {0x43ef8000}, {0x43efa000}, {0x43efc000}, {0x43efe000},
+ {0x43f00000}, {0x43f02000}, {0x43f04000}, {0x43f06000},
+ {0x43f08000}, {0x43f0a000}, {0x43f0c000}, {0x43f0e000},
+ {0x43f10000}, {0x43f12000}, {0x43f14000}, {0x43f16000},
+ {0x43f18000}, {0x43f1a000}, {0x43f1c000}, {0x43f1e000},
+ {0x43f20000}, {0x43f22000}, {0x43f24000}, {0x43f26000},
+ {0x43f28000}, {0x43f2a000}, {0x43f2c000}, {0x43f2e000},
+ {0x43f30000}, {0x43f32000}, {0x43f34000}, {0x43f36000},
+ {0x43f38000}, {0x43f3a000}, {0x43f3c000}, {0x43f3e000},
+ {0x43f40000}, {0x43f42000}, {0x43f44000}, {0x43f46000},
+ {0x43f48000}, {0x43f4a000}, {0x43f4c000}, {0x43f4e000},
+ {0x43f50000}, {0x43f52000}, {0x43f54000}, {0x43f56000},
+ {0x43f58000}, {0x43f5a000}, {0x43f5c000}, {0x43f5e000},
+ {0x43f60000}, {0x43f62000}, {0x43f64000}, {0x43f66000},
+ {0x43f68000}, {0x43f6a000}, {0x43f6c000}, {0x43f6e000},
+ {0x43f70000}, {0x43f72000}, {0x43f74000}, {0x43f76000},
+ {0x43f78000}, {0x43f7a000}, {0x43f7c000}, {0x43f7e000},
+ {0x43f80000}, {0x43f82000}, {0x43f84000}, {0x43f86000},
+ {0x43f88000}, {0x43f8a000}, {0x43f8c000}, {0x43f8e000},
+ {0x43f90000}, {0x43f92000}, {0x43f94000}, {0x43f96000},
+ {0x43f98000}, {0x43f9a000}, {0x43f9c000}, {0x43f9e000},
+ {0x43fa0000}, {0x43fa2000}, {0x43fa4000}, {0x43fa6000},
+ {0x43fa8000}, {0x43faa000}, {0x43fac000}, {0x43fae000},
+ {0x43fb0000}, {0x43fb2000}, {0x43fb4000}, {0x43fb6000},
+ {0x43fb8000}, {0x43fba000}, {0x43fbc000}, {0x43fbe000},
+ {0x43fc0000}, {0x43fc2000}, {0x43fc4000}, {0x43fc6000},
+ {0x43fc8000}, {0x43fca000}, {0x43fcc000}, {0x43fce000},
+ {0x43fd0000}, {0x43fd2000}, {0x43fd4000}, {0x43fd6000},
+ {0x43fd8000}, {0x43fda000}, {0x43fdc000}, {0x43fde000},
+ {0x43fe0000}, {0x43fe2000}, {0x43fe4000}, {0x43fe6000},
+ {0x43fe8000}, {0x43fea000}, {0x43fec000}, {0x43fee000},
+ {0x43ff0000}, {0x43ff2000}, {0x43ff4000}, {0x43ff6000},
+ {0x43ff8000}, {0x43ffa000}, {0x43ffc000}, {0x43ffe000},
+ {0x44000000}, {0x44002000}, {0x44004000}, {0x44006000},
+ {0x44008000}, {0x4400a000}, {0x4400c000}, {0x4400e000},
+ {0x44010000}, {0x44012000}, {0x44014000}, {0x44016000},
+ {0x44018000}, {0x4401a000}, {0x4401c000}, {0x4401e000},
+ {0x44020000}, {0x44022000}, {0x44024000}, {0x44026000},
+ {0x44028000}, {0x4402a000}, {0x4402c000}, {0x4402e000},
+ {0x44030000}, {0x44032000}, {0x44034000}, {0x44036000},
+ {0x44038000}, {0x4403a000}, {0x4403c000}, {0x4403e000},
+ {0x44040000}, {0x44042000}, {0x44044000}, {0x44046000},
+ {0x44048000}, {0x4404a000}, {0x4404c000}, {0x4404e000},
+ {0x44050000}, {0x44052000}, {0x44054000}, {0x44056000},
+ {0x44058000}, {0x4405a000}, {0x4405c000}, {0x4405e000},
+ {0x44060000}, {0x44062000}, {0x44064000}, {0x44066000},
+ {0x44068000}, {0x4406a000}, {0x4406c000}, {0x4406e000},
+ {0x44070000}, {0x44072000}, {0x44074000}, {0x44076000},
+ {0x44078000}, {0x4407a000}, {0x4407c000}, {0x4407e000},
+ {0x44080000}, {0x44082000}, {0x44084000}, {0x44086000},
+ {0x44088000}, {0x4408a000}, {0x4408c000}, {0x4408e000},
+ {0x44090000}, {0x44092000}, {0x44094000}, {0x44096000},
+ {0x44098000}, {0x4409a000}, {0x4409c000}, {0x4409e000},
+ {0x440a0000}, {0x440a2000}, {0x440a4000}, {0x440a6000},
+ {0x440a8000}, {0x440aa000}, {0x440ac000}, {0x440ae000},
+ {0x440b0000}, {0x440b2000}, {0x440b4000}, {0x440b6000},
+ {0x440b8000}, {0x440ba000}, {0x440bc000}, {0x440be000},
+ {0x440c0000}, {0x440c2000}, {0x440c4000}, {0x440c6000},
+ {0x440c8000}, {0x440ca000}, {0x440cc000}, {0x440ce000},
+ {0x440d0000}, {0x440d2000}, {0x440d4000}, {0x440d6000},
+ {0x440d8000}, {0x440da000}, {0x440dc000}, {0x440de000},
+ {0x440e0000}, {0x440e2000}, {0x440e4000}, {0x440e6000},
+ {0x440e8000}, {0x440ea000}, {0x440ec000}, {0x440ee000},
+ {0x440f0000}, {0x440f2000}, {0x440f4000}, {0x440f6000},
+ {0x440f8000}, {0x440fa000}, {0x440fc000}, {0x440fe000},
+ {0x44100000}, {0x44102000}, {0x44104000}, {0x44106000},
+ {0x44108000}, {0x4410a000}, {0x4410c000}, {0x4410e000},
+ {0x44110000}, {0x44112000}, {0x44114000}, {0x44116000},
+ {0x44118000}, {0x4411a000}, {0x4411c000}, {0x4411e000},
+ {0x44120000}, {0x44122000}, {0x44124000}, {0x44126000},
+ {0x44128000}, {0x4412a000}, {0x4412c000}, {0x4412e000},
+ {0x44130000}, {0x44132000}, {0x44134000}, {0x44136000},
+ {0x44138000}, {0x4413a000}, {0x4413c000}, {0x4413e000},
+ {0x44140000}, {0x44142000}, {0x44144000}, {0x44146000},
+ {0x44148000}, {0x4414a000}, {0x4414c000}, {0x4414e000},
+ {0x44150000}, {0x44152000}, {0x44154000}, {0x44156000},
+ {0x44158000}, {0x4415a000}, {0x4415c000}, {0x4415e000},
+ {0x44160000}, {0x44162000}, {0x44164000}, {0x44166000},
+ {0x44168000}, {0x4416a000}, {0x4416c000}, {0x4416e000},
+ {0x44170000}, {0x44172000}, {0x44174000}, {0x44176000},
+ {0x44178000}, {0x4417a000}, {0x4417c000}, {0x4417e000},
+ {0x44180000}, {0x44182000}, {0x44184000}, {0x44186000},
+ {0x44188000}, {0x4418a000}, {0x4418c000}, {0x4418e000},
+ {0x44190000}, {0x44192000}, {0x44194000}, {0x44196000},
+ {0x44198000}, {0x4419a000}, {0x4419c000}, {0x4419e000},
+ {0x441a0000}, {0x441a2000}, {0x441a4000}, {0x441a6000},
+ {0x441a8000}, {0x441aa000}, {0x441ac000}, {0x441ae000},
+ {0x441b0000}, {0x441b2000}, {0x441b4000}, {0x441b6000},
+ {0x441b8000}, {0x441ba000}, {0x441bc000}, {0x441be000},
+ {0x441c0000}, {0x441c2000}, {0x441c4000}, {0x441c6000},
+ {0x441c8000}, {0x441ca000}, {0x441cc000}, {0x441ce000},
+ {0x441d0000}, {0x441d2000}, {0x441d4000}, {0x441d6000},
+ {0x441d8000}, {0x441da000}, {0x441dc000}, {0x441de000},
+ {0x441e0000}, {0x441e2000}, {0x441e4000}, {0x441e6000},
+ {0x441e8000}, {0x441ea000}, {0x441ec000}, {0x441ee000},
+ {0x441f0000}, {0x441f2000}, {0x441f4000}, {0x441f6000},
+ {0x441f8000}, {0x441fa000}, {0x441fc000}, {0x441fe000},
+ {0x44200000}, {0x44202000}, {0x44204000}, {0x44206000},
+ {0x44208000}, {0x4420a000}, {0x4420c000}, {0x4420e000},
+ {0x44210000}, {0x44212000}, {0x44214000}, {0x44216000},
+ {0x44218000}, {0x4421a000}, {0x4421c000}, {0x4421e000},
+ {0x44220000}, {0x44222000}, {0x44224000}, {0x44226000},
+ {0x44228000}, {0x4422a000}, {0x4422c000}, {0x4422e000},
+ {0x44230000}, {0x44232000}, {0x44234000}, {0x44236000},
+ {0x44238000}, {0x4423a000}, {0x4423c000}, {0x4423e000},
+ {0x44240000}, {0x44242000}, {0x44244000}, {0x44246000},
+ {0x44248000}, {0x4424a000}, {0x4424c000}, {0x4424e000},
+ {0x44250000}, {0x44252000}, {0x44254000}, {0x44256000},
+ {0x44258000}, {0x4425a000}, {0x4425c000}, {0x4425e000},
+ {0x44260000}, {0x44262000}, {0x44264000}, {0x44266000},
+ {0x44268000}, {0x4426a000}, {0x4426c000}, {0x4426e000},
+ {0x44270000}, {0x44272000}, {0x44274000}, {0x44276000},
+ {0x44278000}, {0x4427a000}, {0x4427c000}, {0x4427e000},
+ {0x44280000}, {0x44282000}, {0x44284000}, {0x44286000},
+ {0x44288000}, {0x4428a000}, {0x4428c000}, {0x4428e000},
+ {0x44290000}, {0x44292000}, {0x44294000}, {0x44296000},
+ {0x44298000}, {0x4429a000}, {0x4429c000}, {0x4429e000},
+ {0x442a0000}, {0x442a2000}, {0x442a4000}, {0x442a6000},
+ {0x442a8000}, {0x442aa000}, {0x442ac000}, {0x442ae000},
+ {0x442b0000}, {0x442b2000}, {0x442b4000}, {0x442b6000},
+ {0x442b8000}, {0x442ba000}, {0x442bc000}, {0x442be000},
+ {0x442c0000}, {0x442c2000}, {0x442c4000}, {0x442c6000},
+ {0x442c8000}, {0x442ca000}, {0x442cc000}, {0x442ce000},
+ {0x442d0000}, {0x442d2000}, {0x442d4000}, {0x442d6000},
+ {0x442d8000}, {0x442da000}, {0x442dc000}, {0x442de000},
+ {0x442e0000}, {0x442e2000}, {0x442e4000}, {0x442e6000},
+ {0x442e8000}, {0x442ea000}, {0x442ec000}, {0x442ee000},
+ {0x442f0000}, {0x442f2000}, {0x442f4000}, {0x442f6000},
+ {0x442f8000}, {0x442fa000}, {0x442fc000}, {0x442fe000},
+ {0x44300000}, {0x44302000}, {0x44304000}, {0x44306000},
+ {0x44308000}, {0x4430a000}, {0x4430c000}, {0x4430e000},
+ {0x44310000}, {0x44312000}, {0x44314000}, {0x44316000},
+ {0x44318000}, {0x4431a000}, {0x4431c000}, {0x4431e000},
+ {0x44320000}, {0x44322000}, {0x44324000}, {0x44326000},
+ {0x44328000}, {0x4432a000}, {0x4432c000}, {0x4432e000},
+ {0x44330000}, {0x44332000}, {0x44334000}, {0x44336000},
+ {0x44338000}, {0x4433a000}, {0x4433c000}, {0x4433e000},
+ {0x44340000}, {0x44342000}, {0x44344000}, {0x44346000},
+ {0x44348000}, {0x4434a000}, {0x4434c000}, {0x4434e000},
+ {0x44350000}, {0x44352000}, {0x44354000}, {0x44356000},
+ {0x44358000}, {0x4435a000}, {0x4435c000}, {0x4435e000},
+ {0x44360000}, {0x44362000}, {0x44364000}, {0x44366000},
+ {0x44368000}, {0x4436a000}, {0x4436c000}, {0x4436e000},
+ {0x44370000}, {0x44372000}, {0x44374000}, {0x44376000},
+ {0x44378000}, {0x4437a000}, {0x4437c000}, {0x4437e000},
+ {0x44380000}, {0x44382000}, {0x44384000}, {0x44386000},
+ {0x44388000}, {0x4438a000}, {0x4438c000}, {0x4438e000},
+ {0x44390000}, {0x44392000}, {0x44394000}, {0x44396000},
+ {0x44398000}, {0x4439a000}, {0x4439c000}, {0x4439e000},
+ {0x443a0000}, {0x443a2000}, {0x443a4000}, {0x443a6000},
+ {0x443a8000}, {0x443aa000}, {0x443ac000}, {0x443ae000},
+ {0x443b0000}, {0x443b2000}, {0x443b4000}, {0x443b6000},
+ {0x443b8000}, {0x443ba000}, {0x443bc000}, {0x443be000},
+ {0x443c0000}, {0x443c2000}, {0x443c4000}, {0x443c6000},
+ {0x443c8000}, {0x443ca000}, {0x443cc000}, {0x443ce000},
+ {0x443d0000}, {0x443d2000}, {0x443d4000}, {0x443d6000},
+ {0x443d8000}, {0x443da000}, {0x443dc000}, {0x443de000},
+ {0x443e0000}, {0x443e2000}, {0x443e4000}, {0x443e6000},
+ {0x443e8000}, {0x443ea000}, {0x443ec000}, {0x443ee000},
+ {0x443f0000}, {0x443f2000}, {0x443f4000}, {0x443f6000},
+ {0x443f8000}, {0x443fa000}, {0x443fc000}, {0x443fe000},
+ {0x44400000}, {0x44402000}, {0x44404000}, {0x44406000},
+ {0x44408000}, {0x4440a000}, {0x4440c000}, {0x4440e000},
+ {0x44410000}, {0x44412000}, {0x44414000}, {0x44416000},
+ {0x44418000}, {0x4441a000}, {0x4441c000}, {0x4441e000},
+ {0x44420000}, {0x44422000}, {0x44424000}, {0x44426000},
+ {0x44428000}, {0x4442a000}, {0x4442c000}, {0x4442e000},
+ {0x44430000}, {0x44432000}, {0x44434000}, {0x44436000},
+ {0x44438000}, {0x4443a000}, {0x4443c000}, {0x4443e000},
+ {0x44440000}, {0x44442000}, {0x44444000}, {0x44446000},
+ {0x44448000}, {0x4444a000}, {0x4444c000}, {0x4444e000},
+ {0x44450000}, {0x44452000}, {0x44454000}, {0x44456000},
+ {0x44458000}, {0x4445a000}, {0x4445c000}, {0x4445e000},
+ {0x44460000}, {0x44462000}, {0x44464000}, {0x44466000},
+ {0x44468000}, {0x4446a000}, {0x4446c000}, {0x4446e000},
+ {0x44470000}, {0x44472000}, {0x44474000}, {0x44476000},
+ {0x44478000}, {0x4447a000}, {0x4447c000}, {0x4447e000},
+ {0x44480000}, {0x44482000}, {0x44484000}, {0x44486000},
+ {0x44488000}, {0x4448a000}, {0x4448c000}, {0x4448e000},
+ {0x44490000}, {0x44492000}, {0x44494000}, {0x44496000},
+ {0x44498000}, {0x4449a000}, {0x4449c000}, {0x4449e000},
+ {0x444a0000}, {0x444a2000}, {0x444a4000}, {0x444a6000},
+ {0x444a8000}, {0x444aa000}, {0x444ac000}, {0x444ae000},
+ {0x444b0000}, {0x444b2000}, {0x444b4000}, {0x444b6000},
+ {0x444b8000}, {0x444ba000}, {0x444bc000}, {0x444be000},
+ {0x444c0000}, {0x444c2000}, {0x444c4000}, {0x444c6000},
+ {0x444c8000}, {0x444ca000}, {0x444cc000}, {0x444ce000},
+ {0x444d0000}, {0x444d2000}, {0x444d4000}, {0x444d6000},
+ {0x444d8000}, {0x444da000}, {0x444dc000}, {0x444de000},
+ {0x444e0000}, {0x444e2000}, {0x444e4000}, {0x444e6000},
+ {0x444e8000}, {0x444ea000}, {0x444ec000}, {0x444ee000},
+ {0x444f0000}, {0x444f2000}, {0x444f4000}, {0x444f6000},
+ {0x444f8000}, {0x444fa000}, {0x444fc000}, {0x444fe000},
+ {0x44500000}, {0x44502000}, {0x44504000}, {0x44506000},
+ {0x44508000}, {0x4450a000}, {0x4450c000}, {0x4450e000},
+ {0x44510000}, {0x44512000}, {0x44514000}, {0x44516000},
+ {0x44518000}, {0x4451a000}, {0x4451c000}, {0x4451e000},
+ {0x44520000}, {0x44522000}, {0x44524000}, {0x44526000},
+ {0x44528000}, {0x4452a000}, {0x4452c000}, {0x4452e000},
+ {0x44530000}, {0x44532000}, {0x44534000}, {0x44536000},
+ {0x44538000}, {0x4453a000}, {0x4453c000}, {0x4453e000},
+ {0x44540000}, {0x44542000}, {0x44544000}, {0x44546000},
+ {0x44548000}, {0x4454a000}, {0x4454c000}, {0x4454e000},
+ {0x44550000}, {0x44552000}, {0x44554000}, {0x44556000},
+ {0x44558000}, {0x4455a000}, {0x4455c000}, {0x4455e000},
+ {0x44560000}, {0x44562000}, {0x44564000}, {0x44566000},
+ {0x44568000}, {0x4456a000}, {0x4456c000}, {0x4456e000},
+ {0x44570000}, {0x44572000}, {0x44574000}, {0x44576000},
+ {0x44578000}, {0x4457a000}, {0x4457c000}, {0x4457e000},
+ {0x44580000}, {0x44582000}, {0x44584000}, {0x44586000},
+ {0x44588000}, {0x4458a000}, {0x4458c000}, {0x4458e000},
+ {0x44590000}, {0x44592000}, {0x44594000}, {0x44596000},
+ {0x44598000}, {0x4459a000}, {0x4459c000}, {0x4459e000},
+ {0x445a0000}, {0x445a2000}, {0x445a4000}, {0x445a6000},
+ {0x445a8000}, {0x445aa000}, {0x445ac000}, {0x445ae000},
+ {0x445b0000}, {0x445b2000}, {0x445b4000}, {0x445b6000},
+ {0x445b8000}, {0x445ba000}, {0x445bc000}, {0x445be000},
+ {0x445c0000}, {0x445c2000}, {0x445c4000}, {0x445c6000},
+ {0x445c8000}, {0x445ca000}, {0x445cc000}, {0x445ce000},
+ {0x445d0000}, {0x445d2000}, {0x445d4000}, {0x445d6000},
+ {0x445d8000}, {0x445da000}, {0x445dc000}, {0x445de000},
+ {0x445e0000}, {0x445e2000}, {0x445e4000}, {0x445e6000},
+ {0x445e8000}, {0x445ea000}, {0x445ec000}, {0x445ee000},
+ {0x445f0000}, {0x445f2000}, {0x445f4000}, {0x445f6000},
+ {0x445f8000}, {0x445fa000}, {0x445fc000}, {0x445fe000},
+ {0x44600000}, {0x44602000}, {0x44604000}, {0x44606000},
+ {0x44608000}, {0x4460a000}, {0x4460c000}, {0x4460e000},
+ {0x44610000}, {0x44612000}, {0x44614000}, {0x44616000},
+ {0x44618000}, {0x4461a000}, {0x4461c000}, {0x4461e000},
+ {0x44620000}, {0x44622000}, {0x44624000}, {0x44626000},
+ {0x44628000}, {0x4462a000}, {0x4462c000}, {0x4462e000},
+ {0x44630000}, {0x44632000}, {0x44634000}, {0x44636000},
+ {0x44638000}, {0x4463a000}, {0x4463c000}, {0x4463e000},
+ {0x44640000}, {0x44642000}, {0x44644000}, {0x44646000},
+ {0x44648000}, {0x4464a000}, {0x4464c000}, {0x4464e000},
+ {0x44650000}, {0x44652000}, {0x44654000}, {0x44656000},
+ {0x44658000}, {0x4465a000}, {0x4465c000}, {0x4465e000},
+ {0x44660000}, {0x44662000}, {0x44664000}, {0x44666000},
+ {0x44668000}, {0x4466a000}, {0x4466c000}, {0x4466e000},
+ {0x44670000}, {0x44672000}, {0x44674000}, {0x44676000},
+ {0x44678000}, {0x4467a000}, {0x4467c000}, {0x4467e000},
+ {0x44680000}, {0x44682000}, {0x44684000}, {0x44686000},
+ {0x44688000}, {0x4468a000}, {0x4468c000}, {0x4468e000},
+ {0x44690000}, {0x44692000}, {0x44694000}, {0x44696000},
+ {0x44698000}, {0x4469a000}, {0x4469c000}, {0x4469e000},
+ {0x446a0000}, {0x446a2000}, {0x446a4000}, {0x446a6000},
+ {0x446a8000}, {0x446aa000}, {0x446ac000}, {0x446ae000},
+ {0x446b0000}, {0x446b2000}, {0x446b4000}, {0x446b6000},
+ {0x446b8000}, {0x446ba000}, {0x446bc000}, {0x446be000},
+ {0x446c0000}, {0x446c2000}, {0x446c4000}, {0x446c6000},
+ {0x446c8000}, {0x446ca000}, {0x446cc000}, {0x446ce000},
+ {0x446d0000}, {0x446d2000}, {0x446d4000}, {0x446d6000},
+ {0x446d8000}, {0x446da000}, {0x446dc000}, {0x446de000},
+ {0x446e0000}, {0x446e2000}, {0x446e4000}, {0x446e6000},
+ {0x446e8000}, {0x446ea000}, {0x446ec000}, {0x446ee000},
+ {0x446f0000}, {0x446f2000}, {0x446f4000}, {0x446f6000},
+ {0x446f8000}, {0x446fa000}, {0x446fc000}, {0x446fe000},
+ {0x44700000}, {0x44702000}, {0x44704000}, {0x44706000},
+ {0x44708000}, {0x4470a000}, {0x4470c000}, {0x4470e000},
+ {0x44710000}, {0x44712000}, {0x44714000}, {0x44716000},
+ {0x44718000}, {0x4471a000}, {0x4471c000}, {0x4471e000},
+ {0x44720000}, {0x44722000}, {0x44724000}, {0x44726000},
+ {0x44728000}, {0x4472a000}, {0x4472c000}, {0x4472e000},
+ {0x44730000}, {0x44732000}, {0x44734000}, {0x44736000},
+ {0x44738000}, {0x4473a000}, {0x4473c000}, {0x4473e000},
+ {0x44740000}, {0x44742000}, {0x44744000}, {0x44746000},
+ {0x44748000}, {0x4474a000}, {0x4474c000}, {0x4474e000},
+ {0x44750000}, {0x44752000}, {0x44754000}, {0x44756000},
+ {0x44758000}, {0x4475a000}, {0x4475c000}, {0x4475e000},
+ {0x44760000}, {0x44762000}, {0x44764000}, {0x44766000},
+ {0x44768000}, {0x4476a000}, {0x4476c000}, {0x4476e000},
+ {0x44770000}, {0x44772000}, {0x44774000}, {0x44776000},
+ {0x44778000}, {0x4477a000}, {0x4477c000}, {0x4477e000},
+ {0x44780000}, {0x44782000}, {0x44784000}, {0x44786000},
+ {0x44788000}, {0x4478a000}, {0x4478c000}, {0x4478e000},
+ {0x44790000}, {0x44792000}, {0x44794000}, {0x44796000},
+ {0x44798000}, {0x4479a000}, {0x4479c000}, {0x4479e000},
+ {0x447a0000}, {0x447a2000}, {0x447a4000}, {0x447a6000},
+ {0x447a8000}, {0x447aa000}, {0x447ac000}, {0x447ae000},
+ {0x447b0000}, {0x447b2000}, {0x447b4000}, {0x447b6000},
+ {0x447b8000}, {0x447ba000}, {0x447bc000}, {0x447be000},
+ {0x447c0000}, {0x447c2000}, {0x447c4000}, {0x447c6000},
+ {0x447c8000}, {0x447ca000}, {0x447cc000}, {0x447ce000},
+ {0x447d0000}, {0x447d2000}, {0x447d4000}, {0x447d6000},
+ {0x447d8000}, {0x447da000}, {0x447dc000}, {0x447de000},
+ {0x447e0000}, {0x447e2000}, {0x447e4000}, {0x447e6000},
+ {0x447e8000}, {0x447ea000}, {0x447ec000}, {0x447ee000},
+ {0x447f0000}, {0x447f2000}, {0x447f4000}, {0x447f6000},
+ {0x447f8000}, {0x447fa000}, {0x447fc000}, {0x447fe000},
+ {0x44800000}, {0x44802000}, {0x44804000}, {0x44806000},
+ {0x44808000}, {0x4480a000}, {0x4480c000}, {0x4480e000},
+ {0x44810000}, {0x44812000}, {0x44814000}, {0x44816000},
+ {0x44818000}, {0x4481a000}, {0x4481c000}, {0x4481e000},
+ {0x44820000}, {0x44822000}, {0x44824000}, {0x44826000},
+ {0x44828000}, {0x4482a000}, {0x4482c000}, {0x4482e000},
+ {0x44830000}, {0x44832000}, {0x44834000}, {0x44836000},
+ {0x44838000}, {0x4483a000}, {0x4483c000}, {0x4483e000},
+ {0x44840000}, {0x44842000}, {0x44844000}, {0x44846000},
+ {0x44848000}, {0x4484a000}, {0x4484c000}, {0x4484e000},
+ {0x44850000}, {0x44852000}, {0x44854000}, {0x44856000},
+ {0x44858000}, {0x4485a000}, {0x4485c000}, {0x4485e000},
+ {0x44860000}, {0x44862000}, {0x44864000}, {0x44866000},
+ {0x44868000}, {0x4486a000}, {0x4486c000}, {0x4486e000},
+ {0x44870000}, {0x44872000}, {0x44874000}, {0x44876000},
+ {0x44878000}, {0x4487a000}, {0x4487c000}, {0x4487e000},
+ {0x44880000}, {0x44882000}, {0x44884000}, {0x44886000},
+ {0x44888000}, {0x4488a000}, {0x4488c000}, {0x4488e000},
+ {0x44890000}, {0x44892000}, {0x44894000}, {0x44896000},
+ {0x44898000}, {0x4489a000}, {0x4489c000}, {0x4489e000},
+ {0x448a0000}, {0x448a2000}, {0x448a4000}, {0x448a6000},
+ {0x448a8000}, {0x448aa000}, {0x448ac000}, {0x448ae000},
+ {0x448b0000}, {0x448b2000}, {0x448b4000}, {0x448b6000},
+ {0x448b8000}, {0x448ba000}, {0x448bc000}, {0x448be000},
+ {0x448c0000}, {0x448c2000}, {0x448c4000}, {0x448c6000},
+ {0x448c8000}, {0x448ca000}, {0x448cc000}, {0x448ce000},
+ {0x448d0000}, {0x448d2000}, {0x448d4000}, {0x448d6000},
+ {0x448d8000}, {0x448da000}, {0x448dc000}, {0x448de000},
+ {0x448e0000}, {0x448e2000}, {0x448e4000}, {0x448e6000},
+ {0x448e8000}, {0x448ea000}, {0x448ec000}, {0x448ee000},
+ {0x448f0000}, {0x448f2000}, {0x448f4000}, {0x448f6000},
+ {0x448f8000}, {0x448fa000}, {0x448fc000}, {0x448fe000},
+ {0x44900000}, {0x44902000}, {0x44904000}, {0x44906000},
+ {0x44908000}, {0x4490a000}, {0x4490c000}, {0x4490e000},
+ {0x44910000}, {0x44912000}, {0x44914000}, {0x44916000},
+ {0x44918000}, {0x4491a000}, {0x4491c000}, {0x4491e000},
+ {0x44920000}, {0x44922000}, {0x44924000}, {0x44926000},
+ {0x44928000}, {0x4492a000}, {0x4492c000}, {0x4492e000},
+ {0x44930000}, {0x44932000}, {0x44934000}, {0x44936000},
+ {0x44938000}, {0x4493a000}, {0x4493c000}, {0x4493e000},
+ {0x44940000}, {0x44942000}, {0x44944000}, {0x44946000},
+ {0x44948000}, {0x4494a000}, {0x4494c000}, {0x4494e000},
+ {0x44950000}, {0x44952000}, {0x44954000}, {0x44956000},
+ {0x44958000}, {0x4495a000}, {0x4495c000}, {0x4495e000},
+ {0x44960000}, {0x44962000}, {0x44964000}, {0x44966000},
+ {0x44968000}, {0x4496a000}, {0x4496c000}, {0x4496e000},
+ {0x44970000}, {0x44972000}, {0x44974000}, {0x44976000},
+ {0x44978000}, {0x4497a000}, {0x4497c000}, {0x4497e000},
+ {0x44980000}, {0x44982000}, {0x44984000}, {0x44986000},
+ {0x44988000}, {0x4498a000}, {0x4498c000}, {0x4498e000},
+ {0x44990000}, {0x44992000}, {0x44994000}, {0x44996000},
+ {0x44998000}, {0x4499a000}, {0x4499c000}, {0x4499e000},
+ {0x449a0000}, {0x449a2000}, {0x449a4000}, {0x449a6000},
+ {0x449a8000}, {0x449aa000}, {0x449ac000}, {0x449ae000},
+ {0x449b0000}, {0x449b2000}, {0x449b4000}, {0x449b6000},
+ {0x449b8000}, {0x449ba000}, {0x449bc000}, {0x449be000},
+ {0x449c0000}, {0x449c2000}, {0x449c4000}, {0x449c6000},
+ {0x449c8000}, {0x449ca000}, {0x449cc000}, {0x449ce000},
+ {0x449d0000}, {0x449d2000}, {0x449d4000}, {0x449d6000},
+ {0x449d8000}, {0x449da000}, {0x449dc000}, {0x449de000},
+ {0x449e0000}, {0x449e2000}, {0x449e4000}, {0x449e6000},
+ {0x449e8000}, {0x449ea000}, {0x449ec000}, {0x449ee000},
+ {0x449f0000}, {0x449f2000}, {0x449f4000}, {0x449f6000},
+ {0x449f8000}, {0x449fa000}, {0x449fc000}, {0x449fe000},
+ {0x44a00000}, {0x44a02000}, {0x44a04000}, {0x44a06000},
+ {0x44a08000}, {0x44a0a000}, {0x44a0c000}, {0x44a0e000},
+ {0x44a10000}, {0x44a12000}, {0x44a14000}, {0x44a16000},
+ {0x44a18000}, {0x44a1a000}, {0x44a1c000}, {0x44a1e000},
+ {0x44a20000}, {0x44a22000}, {0x44a24000}, {0x44a26000},
+ {0x44a28000}, {0x44a2a000}, {0x44a2c000}, {0x44a2e000},
+ {0x44a30000}, {0x44a32000}, {0x44a34000}, {0x44a36000},
+ {0x44a38000}, {0x44a3a000}, {0x44a3c000}, {0x44a3e000},
+ {0x44a40000}, {0x44a42000}, {0x44a44000}, {0x44a46000},
+ {0x44a48000}, {0x44a4a000}, {0x44a4c000}, {0x44a4e000},
+ {0x44a50000}, {0x44a52000}, {0x44a54000}, {0x44a56000},
+ {0x44a58000}, {0x44a5a000}, {0x44a5c000}, {0x44a5e000},
+ {0x44a60000}, {0x44a62000}, {0x44a64000}, {0x44a66000},
+ {0x44a68000}, {0x44a6a000}, {0x44a6c000}, {0x44a6e000},
+ {0x44a70000}, {0x44a72000}, {0x44a74000}, {0x44a76000},
+ {0x44a78000}, {0x44a7a000}, {0x44a7c000}, {0x44a7e000},
+ {0x44a80000}, {0x44a82000}, {0x44a84000}, {0x44a86000},
+ {0x44a88000}, {0x44a8a000}, {0x44a8c000}, {0x44a8e000},
+ {0x44a90000}, {0x44a92000}, {0x44a94000}, {0x44a96000},
+ {0x44a98000}, {0x44a9a000}, {0x44a9c000}, {0x44a9e000},
+ {0x44aa0000}, {0x44aa2000}, {0x44aa4000}, {0x44aa6000},
+ {0x44aa8000}, {0x44aaa000}, {0x44aac000}, {0x44aae000},
+ {0x44ab0000}, {0x44ab2000}, {0x44ab4000}, {0x44ab6000},
+ {0x44ab8000}, {0x44aba000}, {0x44abc000}, {0x44abe000},
+ {0x44ac0000}, {0x44ac2000}, {0x44ac4000}, {0x44ac6000},
+ {0x44ac8000}, {0x44aca000}, {0x44acc000}, {0x44ace000},
+ {0x44ad0000}, {0x44ad2000}, {0x44ad4000}, {0x44ad6000},
+ {0x44ad8000}, {0x44ada000}, {0x44adc000}, {0x44ade000},
+ {0x44ae0000}, {0x44ae2000}, {0x44ae4000}, {0x44ae6000},
+ {0x44ae8000}, {0x44aea000}, {0x44aec000}, {0x44aee000},
+ {0x44af0000}, {0x44af2000}, {0x44af4000}, {0x44af6000},
+ {0x44af8000}, {0x44afa000}, {0x44afc000}, {0x44afe000},
+ {0x44b00000}, {0x44b02000}, {0x44b04000}, {0x44b06000},
+ {0x44b08000}, {0x44b0a000}, {0x44b0c000}, {0x44b0e000},
+ {0x44b10000}, {0x44b12000}, {0x44b14000}, {0x44b16000},
+ {0x44b18000}, {0x44b1a000}, {0x44b1c000}, {0x44b1e000},
+ {0x44b20000}, {0x44b22000}, {0x44b24000}, {0x44b26000},
+ {0x44b28000}, {0x44b2a000}, {0x44b2c000}, {0x44b2e000},
+ {0x44b30000}, {0x44b32000}, {0x44b34000}, {0x44b36000},
+ {0x44b38000}, {0x44b3a000}, {0x44b3c000}, {0x44b3e000},
+ {0x44b40000}, {0x44b42000}, {0x44b44000}, {0x44b46000},
+ {0x44b48000}, {0x44b4a000}, {0x44b4c000}, {0x44b4e000},
+ {0x44b50000}, {0x44b52000}, {0x44b54000}, {0x44b56000},
+ {0x44b58000}, {0x44b5a000}, {0x44b5c000}, {0x44b5e000},
+ {0x44b60000}, {0x44b62000}, {0x44b64000}, {0x44b66000},
+ {0x44b68000}, {0x44b6a000}, {0x44b6c000}, {0x44b6e000},
+ {0x44b70000}, {0x44b72000}, {0x44b74000}, {0x44b76000},
+ {0x44b78000}, {0x44b7a000}, {0x44b7c000}, {0x44b7e000},
+ {0x44b80000}, {0x44b82000}, {0x44b84000}, {0x44b86000},
+ {0x44b88000}, {0x44b8a000}, {0x44b8c000}, {0x44b8e000},
+ {0x44b90000}, {0x44b92000}, {0x44b94000}, {0x44b96000},
+ {0x44b98000}, {0x44b9a000}, {0x44b9c000}, {0x44b9e000},
+ {0x44ba0000}, {0x44ba2000}, {0x44ba4000}, {0x44ba6000},
+ {0x44ba8000}, {0x44baa000}, {0x44bac000}, {0x44bae000},
+ {0x44bb0000}, {0x44bb2000}, {0x44bb4000}, {0x44bb6000},
+ {0x44bb8000}, {0x44bba000}, {0x44bbc000}, {0x44bbe000},
+ {0x44bc0000}, {0x44bc2000}, {0x44bc4000}, {0x44bc6000},
+ {0x44bc8000}, {0x44bca000}, {0x44bcc000}, {0x44bce000},
+ {0x44bd0000}, {0x44bd2000}, {0x44bd4000}, {0x44bd6000},
+ {0x44bd8000}, {0x44bda000}, {0x44bdc000}, {0x44bde000},
+ {0x44be0000}, {0x44be2000}, {0x44be4000}, {0x44be6000},
+ {0x44be8000}, {0x44bea000}, {0x44bec000}, {0x44bee000},
+ {0x44bf0000}, {0x44bf2000}, {0x44bf4000}, {0x44bf6000},
+ {0x44bf8000}, {0x44bfa000}, {0x44bfc000}, {0x44bfe000},
+ {0x44c00000}, {0x44c02000}, {0x44c04000}, {0x44c06000},
+ {0x44c08000}, {0x44c0a000}, {0x44c0c000}, {0x44c0e000},
+ {0x44c10000}, {0x44c12000}, {0x44c14000}, {0x44c16000},
+ {0x44c18000}, {0x44c1a000}, {0x44c1c000}, {0x44c1e000},
+ {0x44c20000}, {0x44c22000}, {0x44c24000}, {0x44c26000},
+ {0x44c28000}, {0x44c2a000}, {0x44c2c000}, {0x44c2e000},
+ {0x44c30000}, {0x44c32000}, {0x44c34000}, {0x44c36000},
+ {0x44c38000}, {0x44c3a000}, {0x44c3c000}, {0x44c3e000},
+ {0x44c40000}, {0x44c42000}, {0x44c44000}, {0x44c46000},
+ {0x44c48000}, {0x44c4a000}, {0x44c4c000}, {0x44c4e000},
+ {0x44c50000}, {0x44c52000}, {0x44c54000}, {0x44c56000},
+ {0x44c58000}, {0x44c5a000}, {0x44c5c000}, {0x44c5e000},
+ {0x44c60000}, {0x44c62000}, {0x44c64000}, {0x44c66000},
+ {0x44c68000}, {0x44c6a000}, {0x44c6c000}, {0x44c6e000},
+ {0x44c70000}, {0x44c72000}, {0x44c74000}, {0x44c76000},
+ {0x44c78000}, {0x44c7a000}, {0x44c7c000}, {0x44c7e000},
+ {0x44c80000}, {0x44c82000}, {0x44c84000}, {0x44c86000},
+ {0x44c88000}, {0x44c8a000}, {0x44c8c000}, {0x44c8e000},
+ {0x44c90000}, {0x44c92000}, {0x44c94000}, {0x44c96000},
+ {0x44c98000}, {0x44c9a000}, {0x44c9c000}, {0x44c9e000},
+ {0x44ca0000}, {0x44ca2000}, {0x44ca4000}, {0x44ca6000},
+ {0x44ca8000}, {0x44caa000}, {0x44cac000}, {0x44cae000},
+ {0x44cb0000}, {0x44cb2000}, {0x44cb4000}, {0x44cb6000},
+ {0x44cb8000}, {0x44cba000}, {0x44cbc000}, {0x44cbe000},
+ {0x44cc0000}, {0x44cc2000}, {0x44cc4000}, {0x44cc6000},
+ {0x44cc8000}, {0x44cca000}, {0x44ccc000}, {0x44cce000},
+ {0x44cd0000}, {0x44cd2000}, {0x44cd4000}, {0x44cd6000},
+ {0x44cd8000}, {0x44cda000}, {0x44cdc000}, {0x44cde000},
+ {0x44ce0000}, {0x44ce2000}, {0x44ce4000}, {0x44ce6000},
+ {0x44ce8000}, {0x44cea000}, {0x44cec000}, {0x44cee000},
+ {0x44cf0000}, {0x44cf2000}, {0x44cf4000}, {0x44cf6000},
+ {0x44cf8000}, {0x44cfa000}, {0x44cfc000}, {0x44cfe000},
+ {0x44d00000}, {0x44d02000}, {0x44d04000}, {0x44d06000},
+ {0x44d08000}, {0x44d0a000}, {0x44d0c000}, {0x44d0e000},
+ {0x44d10000}, {0x44d12000}, {0x44d14000}, {0x44d16000},
+ {0x44d18000}, {0x44d1a000}, {0x44d1c000}, {0x44d1e000},
+ {0x44d20000}, {0x44d22000}, {0x44d24000}, {0x44d26000},
+ {0x44d28000}, {0x44d2a000}, {0x44d2c000}, {0x44d2e000},
+ {0x44d30000}, {0x44d32000}, {0x44d34000}, {0x44d36000},
+ {0x44d38000}, {0x44d3a000}, {0x44d3c000}, {0x44d3e000},
+ {0x44d40000}, {0x44d42000}, {0x44d44000}, {0x44d46000},
+ {0x44d48000}, {0x44d4a000}, {0x44d4c000}, {0x44d4e000},
+ {0x44d50000}, {0x44d52000}, {0x44d54000}, {0x44d56000},
+ {0x44d58000}, {0x44d5a000}, {0x44d5c000}, {0x44d5e000},
+ {0x44d60000}, {0x44d62000}, {0x44d64000}, {0x44d66000},
+ {0x44d68000}, {0x44d6a000}, {0x44d6c000}, {0x44d6e000},
+ {0x44d70000}, {0x44d72000}, {0x44d74000}, {0x44d76000},
+ {0x44d78000}, {0x44d7a000}, {0x44d7c000}, {0x44d7e000},
+ {0x44d80000}, {0x44d82000}, {0x44d84000}, {0x44d86000},
+ {0x44d88000}, {0x44d8a000}, {0x44d8c000}, {0x44d8e000},
+ {0x44d90000}, {0x44d92000}, {0x44d94000}, {0x44d96000},
+ {0x44d98000}, {0x44d9a000}, {0x44d9c000}, {0x44d9e000},
+ {0x44da0000}, {0x44da2000}, {0x44da4000}, {0x44da6000},
+ {0x44da8000}, {0x44daa000}, {0x44dac000}, {0x44dae000},
+ {0x44db0000}, {0x44db2000}, {0x44db4000}, {0x44db6000},
+ {0x44db8000}, {0x44dba000}, {0x44dbc000}, {0x44dbe000},
+ {0x44dc0000}, {0x44dc2000}, {0x44dc4000}, {0x44dc6000},
+ {0x44dc8000}, {0x44dca000}, {0x44dcc000}, {0x44dce000},
+ {0x44dd0000}, {0x44dd2000}, {0x44dd4000}, {0x44dd6000},
+ {0x44dd8000}, {0x44dda000}, {0x44ddc000}, {0x44dde000},
+ {0x44de0000}, {0x44de2000}, {0x44de4000}, {0x44de6000},
+ {0x44de8000}, {0x44dea000}, {0x44dec000}, {0x44dee000},
+ {0x44df0000}, {0x44df2000}, {0x44df4000}, {0x44df6000},
+ {0x44df8000}, {0x44dfa000}, {0x44dfc000}, {0x44dfe000},
+ {0x44e00000}, {0x44e02000}, {0x44e04000}, {0x44e06000},
+ {0x44e08000}, {0x44e0a000}, {0x44e0c000}, {0x44e0e000},
+ {0x44e10000}, {0x44e12000}, {0x44e14000}, {0x44e16000},
+ {0x44e18000}, {0x44e1a000}, {0x44e1c000}, {0x44e1e000},
+ {0x44e20000}, {0x44e22000}, {0x44e24000}, {0x44e26000},
+ {0x44e28000}, {0x44e2a000}, {0x44e2c000}, {0x44e2e000},
+ {0x44e30000}, {0x44e32000}, {0x44e34000}, {0x44e36000},
+ {0x44e38000}, {0x44e3a000}, {0x44e3c000}, {0x44e3e000},
+ {0x44e40000}, {0x44e42000}, {0x44e44000}, {0x44e46000},
+ {0x44e48000}, {0x44e4a000}, {0x44e4c000}, {0x44e4e000},
+ {0x44e50000}, {0x44e52000}, {0x44e54000}, {0x44e56000},
+ {0x44e58000}, {0x44e5a000}, {0x44e5c000}, {0x44e5e000},
+ {0x44e60000}, {0x44e62000}, {0x44e64000}, {0x44e66000},
+ {0x44e68000}, {0x44e6a000}, {0x44e6c000}, {0x44e6e000},
+ {0x44e70000}, {0x44e72000}, {0x44e74000}, {0x44e76000},
+ {0x44e78000}, {0x44e7a000}, {0x44e7c000}, {0x44e7e000},
+ {0x44e80000}, {0x44e82000}, {0x44e84000}, {0x44e86000},
+ {0x44e88000}, {0x44e8a000}, {0x44e8c000}, {0x44e8e000},
+ {0x44e90000}, {0x44e92000}, {0x44e94000}, {0x44e96000},
+ {0x44e98000}, {0x44e9a000}, {0x44e9c000}, {0x44e9e000},
+ {0x44ea0000}, {0x44ea2000}, {0x44ea4000}, {0x44ea6000},
+ {0x44ea8000}, {0x44eaa000}, {0x44eac000}, {0x44eae000},
+ {0x44eb0000}, {0x44eb2000}, {0x44eb4000}, {0x44eb6000},
+ {0x44eb8000}, {0x44eba000}, {0x44ebc000}, {0x44ebe000},
+ {0x44ec0000}, {0x44ec2000}, {0x44ec4000}, {0x44ec6000},
+ {0x44ec8000}, {0x44eca000}, {0x44ecc000}, {0x44ece000},
+ {0x44ed0000}, {0x44ed2000}, {0x44ed4000}, {0x44ed6000},
+ {0x44ed8000}, {0x44eda000}, {0x44edc000}, {0x44ede000},
+ {0x44ee0000}, {0x44ee2000}, {0x44ee4000}, {0x44ee6000},
+ {0x44ee8000}, {0x44eea000}, {0x44eec000}, {0x44eee000},
+ {0x44ef0000}, {0x44ef2000}, {0x44ef4000}, {0x44ef6000},
+ {0x44ef8000}, {0x44efa000}, {0x44efc000}, {0x44efe000},
+ {0x44f00000}, {0x44f02000}, {0x44f04000}, {0x44f06000},
+ {0x44f08000}, {0x44f0a000}, {0x44f0c000}, {0x44f0e000},
+ {0x44f10000}, {0x44f12000}, {0x44f14000}, {0x44f16000},
+ {0x44f18000}, {0x44f1a000}, {0x44f1c000}, {0x44f1e000},
+ {0x44f20000}, {0x44f22000}, {0x44f24000}, {0x44f26000},
+ {0x44f28000}, {0x44f2a000}, {0x44f2c000}, {0x44f2e000},
+ {0x44f30000}, {0x44f32000}, {0x44f34000}, {0x44f36000},
+ {0x44f38000}, {0x44f3a000}, {0x44f3c000}, {0x44f3e000},
+ {0x44f40000}, {0x44f42000}, {0x44f44000}, {0x44f46000},
+ {0x44f48000}, {0x44f4a000}, {0x44f4c000}, {0x44f4e000},
+ {0x44f50000}, {0x44f52000}, {0x44f54000}, {0x44f56000},
+ {0x44f58000}, {0x44f5a000}, {0x44f5c000}, {0x44f5e000},
+ {0x44f60000}, {0x44f62000}, {0x44f64000}, {0x44f66000},
+ {0x44f68000}, {0x44f6a000}, {0x44f6c000}, {0x44f6e000},
+ {0x44f70000}, {0x44f72000}, {0x44f74000}, {0x44f76000},
+ {0x44f78000}, {0x44f7a000}, {0x44f7c000}, {0x44f7e000},
+ {0x44f80000}, {0x44f82000}, {0x44f84000}, {0x44f86000},
+ {0x44f88000}, {0x44f8a000}, {0x44f8c000}, {0x44f8e000},
+ {0x44f90000}, {0x44f92000}, {0x44f94000}, {0x44f96000},
+ {0x44f98000}, {0x44f9a000}, {0x44f9c000}, {0x44f9e000},
+ {0x44fa0000}, {0x44fa2000}, {0x44fa4000}, {0x44fa6000},
+ {0x44fa8000}, {0x44faa000}, {0x44fac000}, {0x44fae000},
+ {0x44fb0000}, {0x44fb2000}, {0x44fb4000}, {0x44fb6000},
+ {0x44fb8000}, {0x44fba000}, {0x44fbc000}, {0x44fbe000},
+ {0x44fc0000}, {0x44fc2000}, {0x44fc4000}, {0x44fc6000},
+ {0x44fc8000}, {0x44fca000}, {0x44fcc000}, {0x44fce000},
+ {0x44fd0000}, {0x44fd2000}, {0x44fd4000}, {0x44fd6000},
+ {0x44fd8000}, {0x44fda000}, {0x44fdc000}, {0x44fde000},
+ {0x44fe0000}, {0x44fe2000}, {0x44fe4000}, {0x44fe6000},
+ {0x44fe8000}, {0x44fea000}, {0x44fec000}, {0x44fee000},
+ {0x44ff0000}, {0x44ff2000}, {0x44ff4000}, {0x44ff6000},
+ {0x44ff8000}, {0x44ffa000}, {0x44ffc000}, {0x44ffe000},
+ {0x45000000}, {0x45002000}, {0x45004000}, {0x45006000},
+ {0x45008000}, {0x4500a000}, {0x4500c000}, {0x4500e000},
+ {0x45010000}, {0x45012000}, {0x45014000}, {0x45016000},
+ {0x45018000}, {0x4501a000}, {0x4501c000}, {0x4501e000},
+ {0x45020000}, {0x45022000}, {0x45024000}, {0x45026000},
+ {0x45028000}, {0x4502a000}, {0x4502c000}, {0x4502e000},
+ {0x45030000}, {0x45032000}, {0x45034000}, {0x45036000},
+ {0x45038000}, {0x4503a000}, {0x4503c000}, {0x4503e000},
+ {0x45040000}, {0x45042000}, {0x45044000}, {0x45046000},
+ {0x45048000}, {0x4504a000}, {0x4504c000}, {0x4504e000},
+ {0x45050000}, {0x45052000}, {0x45054000}, {0x45056000},
+ {0x45058000}, {0x4505a000}, {0x4505c000}, {0x4505e000},
+ {0x45060000}, {0x45062000}, {0x45064000}, {0x45066000},
+ {0x45068000}, {0x4506a000}, {0x4506c000}, {0x4506e000},
+ {0x45070000}, {0x45072000}, {0x45074000}, {0x45076000},
+ {0x45078000}, {0x4507a000}, {0x4507c000}, {0x4507e000},
+ {0x45080000}, {0x45082000}, {0x45084000}, {0x45086000},
+ {0x45088000}, {0x4508a000}, {0x4508c000}, {0x4508e000},
+ {0x45090000}, {0x45092000}, {0x45094000}, {0x45096000},
+ {0x45098000}, {0x4509a000}, {0x4509c000}, {0x4509e000},
+ {0x450a0000}, {0x450a2000}, {0x450a4000}, {0x450a6000},
+ {0x450a8000}, {0x450aa000}, {0x450ac000}, {0x450ae000},
+ {0x450b0000}, {0x450b2000}, {0x450b4000}, {0x450b6000},
+ {0x450b8000}, {0x450ba000}, {0x450bc000}, {0x450be000},
+ {0x450c0000}, {0x450c2000}, {0x450c4000}, {0x450c6000},
+ {0x450c8000}, {0x450ca000}, {0x450cc000}, {0x450ce000},
+ {0x450d0000}, {0x450d2000}, {0x450d4000}, {0x450d6000},
+ {0x450d8000}, {0x450da000}, {0x450dc000}, {0x450de000},
+ {0x450e0000}, {0x450e2000}, {0x450e4000}, {0x450e6000},
+ {0x450e8000}, {0x450ea000}, {0x450ec000}, {0x450ee000},
+ {0x450f0000}, {0x450f2000}, {0x450f4000}, {0x450f6000},
+ {0x450f8000}, {0x450fa000}, {0x450fc000}, {0x450fe000},
+ {0x45100000}, {0x45102000}, {0x45104000}, {0x45106000},
+ {0x45108000}, {0x4510a000}, {0x4510c000}, {0x4510e000},
+ {0x45110000}, {0x45112000}, {0x45114000}, {0x45116000},
+ {0x45118000}, {0x4511a000}, {0x4511c000}, {0x4511e000},
+ {0x45120000}, {0x45122000}, {0x45124000}, {0x45126000},
+ {0x45128000}, {0x4512a000}, {0x4512c000}, {0x4512e000},
+ {0x45130000}, {0x45132000}, {0x45134000}, {0x45136000},
+ {0x45138000}, {0x4513a000}, {0x4513c000}, {0x4513e000},
+ {0x45140000}, {0x45142000}, {0x45144000}, {0x45146000},
+ {0x45148000}, {0x4514a000}, {0x4514c000}, {0x4514e000},
+ {0x45150000}, {0x45152000}, {0x45154000}, {0x45156000},
+ {0x45158000}, {0x4515a000}, {0x4515c000}, {0x4515e000},
+ {0x45160000}, {0x45162000}, {0x45164000}, {0x45166000},
+ {0x45168000}, {0x4516a000}, {0x4516c000}, {0x4516e000},
+ {0x45170000}, {0x45172000}, {0x45174000}, {0x45176000},
+ {0x45178000}, {0x4517a000}, {0x4517c000}, {0x4517e000},
+ {0x45180000}, {0x45182000}, {0x45184000}, {0x45186000},
+ {0x45188000}, {0x4518a000}, {0x4518c000}, {0x4518e000},
+ {0x45190000}, {0x45192000}, {0x45194000}, {0x45196000},
+ {0x45198000}, {0x4519a000}, {0x4519c000}, {0x4519e000},
+ {0x451a0000}, {0x451a2000}, {0x451a4000}, {0x451a6000},
+ {0x451a8000}, {0x451aa000}, {0x451ac000}, {0x451ae000},
+ {0x451b0000}, {0x451b2000}, {0x451b4000}, {0x451b6000},
+ {0x451b8000}, {0x451ba000}, {0x451bc000}, {0x451be000},
+ {0x451c0000}, {0x451c2000}, {0x451c4000}, {0x451c6000},
+ {0x451c8000}, {0x451ca000}, {0x451cc000}, {0x451ce000},
+ {0x451d0000}, {0x451d2000}, {0x451d4000}, {0x451d6000},
+ {0x451d8000}, {0x451da000}, {0x451dc000}, {0x451de000},
+ {0x451e0000}, {0x451e2000}, {0x451e4000}, {0x451e6000},
+ {0x451e8000}, {0x451ea000}, {0x451ec000}, {0x451ee000},
+ {0x451f0000}, {0x451f2000}, {0x451f4000}, {0x451f6000},
+ {0x451f8000}, {0x451fa000}, {0x451fc000}, {0x451fe000},
+ {0x45200000}, {0x45202000}, {0x45204000}, {0x45206000},
+ {0x45208000}, {0x4520a000}, {0x4520c000}, {0x4520e000},
+ {0x45210000}, {0x45212000}, {0x45214000}, {0x45216000},
+ {0x45218000}, {0x4521a000}, {0x4521c000}, {0x4521e000},
+ {0x45220000}, {0x45222000}, {0x45224000}, {0x45226000},
+ {0x45228000}, {0x4522a000}, {0x4522c000}, {0x4522e000},
+ {0x45230000}, {0x45232000}, {0x45234000}, {0x45236000},
+ {0x45238000}, {0x4523a000}, {0x4523c000}, {0x4523e000},
+ {0x45240000}, {0x45242000}, {0x45244000}, {0x45246000},
+ {0x45248000}, {0x4524a000}, {0x4524c000}, {0x4524e000},
+ {0x45250000}, {0x45252000}, {0x45254000}, {0x45256000},
+ {0x45258000}, {0x4525a000}, {0x4525c000}, {0x4525e000},
+ {0x45260000}, {0x45262000}, {0x45264000}, {0x45266000},
+ {0x45268000}, {0x4526a000}, {0x4526c000}, {0x4526e000},
+ {0x45270000}, {0x45272000}, {0x45274000}, {0x45276000},
+ {0x45278000}, {0x4527a000}, {0x4527c000}, {0x4527e000},
+ {0x45280000}, {0x45282000}, {0x45284000}, {0x45286000},
+ {0x45288000}, {0x4528a000}, {0x4528c000}, {0x4528e000},
+ {0x45290000}, {0x45292000}, {0x45294000}, {0x45296000},
+ {0x45298000}, {0x4529a000}, {0x4529c000}, {0x4529e000},
+ {0x452a0000}, {0x452a2000}, {0x452a4000}, {0x452a6000},
+ {0x452a8000}, {0x452aa000}, {0x452ac000}, {0x452ae000},
+ {0x452b0000}, {0x452b2000}, {0x452b4000}, {0x452b6000},
+ {0x452b8000}, {0x452ba000}, {0x452bc000}, {0x452be000},
+ {0x452c0000}, {0x452c2000}, {0x452c4000}, {0x452c6000},
+ {0x452c8000}, {0x452ca000}, {0x452cc000}, {0x452ce000},
+ {0x452d0000}, {0x452d2000}, {0x452d4000}, {0x452d6000},
+ {0x452d8000}, {0x452da000}, {0x452dc000}, {0x452de000},
+ {0x452e0000}, {0x452e2000}, {0x452e4000}, {0x452e6000},
+ {0x452e8000}, {0x452ea000}, {0x452ec000}, {0x452ee000},
+ {0x452f0000}, {0x452f2000}, {0x452f4000}, {0x452f6000},
+ {0x452f8000}, {0x452fa000}, {0x452fc000}, {0x452fe000},
+ {0x45300000}, {0x45302000}, {0x45304000}, {0x45306000},
+ {0x45308000}, {0x4530a000}, {0x4530c000}, {0x4530e000},
+ {0x45310000}, {0x45312000}, {0x45314000}, {0x45316000},
+ {0x45318000}, {0x4531a000}, {0x4531c000}, {0x4531e000},
+ {0x45320000}, {0x45322000}, {0x45324000}, {0x45326000},
+ {0x45328000}, {0x4532a000}, {0x4532c000}, {0x4532e000},
+ {0x45330000}, {0x45332000}, {0x45334000}, {0x45336000},
+ {0x45338000}, {0x4533a000}, {0x4533c000}, {0x4533e000},
+ {0x45340000}, {0x45342000}, {0x45344000}, {0x45346000},
+ {0x45348000}, {0x4534a000}, {0x4534c000}, {0x4534e000},
+ {0x45350000}, {0x45352000}, {0x45354000}, {0x45356000},
+ {0x45358000}, {0x4535a000}, {0x4535c000}, {0x4535e000},
+ {0x45360000}, {0x45362000}, {0x45364000}, {0x45366000},
+ {0x45368000}, {0x4536a000}, {0x4536c000}, {0x4536e000},
+ {0x45370000}, {0x45372000}, {0x45374000}, {0x45376000},
+ {0x45378000}, {0x4537a000}, {0x4537c000}, {0x4537e000},
+ {0x45380000}, {0x45382000}, {0x45384000}, {0x45386000},
+ {0x45388000}, {0x4538a000}, {0x4538c000}, {0x4538e000},
+ {0x45390000}, {0x45392000}, {0x45394000}, {0x45396000},
+ {0x45398000}, {0x4539a000}, {0x4539c000}, {0x4539e000},
+ {0x453a0000}, {0x453a2000}, {0x453a4000}, {0x453a6000},
+ {0x453a8000}, {0x453aa000}, {0x453ac000}, {0x453ae000},
+ {0x453b0000}, {0x453b2000}, {0x453b4000}, {0x453b6000},
+ {0x453b8000}, {0x453ba000}, {0x453bc000}, {0x453be000},
+ {0x453c0000}, {0x453c2000}, {0x453c4000}, {0x453c6000},
+ {0x453c8000}, {0x453ca000}, {0x453cc000}, {0x453ce000},
+ {0x453d0000}, {0x453d2000}, {0x453d4000}, {0x453d6000},
+ {0x453d8000}, {0x453da000}, {0x453dc000}, {0x453de000},
+ {0x453e0000}, {0x453e2000}, {0x453e4000}, {0x453e6000},
+ {0x453e8000}, {0x453ea000}, {0x453ec000}, {0x453ee000},
+ {0x453f0000}, {0x453f2000}, {0x453f4000}, {0x453f6000},
+ {0x453f8000}, {0x453fa000}, {0x453fc000}, {0x453fe000},
+ {0x45400000}, {0x45402000}, {0x45404000}, {0x45406000},
+ {0x45408000}, {0x4540a000}, {0x4540c000}, {0x4540e000},
+ {0x45410000}, {0x45412000}, {0x45414000}, {0x45416000},
+ {0x45418000}, {0x4541a000}, {0x4541c000}, {0x4541e000},
+ {0x45420000}, {0x45422000}, {0x45424000}, {0x45426000},
+ {0x45428000}, {0x4542a000}, {0x4542c000}, {0x4542e000},
+ {0x45430000}, {0x45432000}, {0x45434000}, {0x45436000},
+ {0x45438000}, {0x4543a000}, {0x4543c000}, {0x4543e000},
+ {0x45440000}, {0x45442000}, {0x45444000}, {0x45446000},
+ {0x45448000}, {0x4544a000}, {0x4544c000}, {0x4544e000},
+ {0x45450000}, {0x45452000}, {0x45454000}, {0x45456000},
+ {0x45458000}, {0x4545a000}, {0x4545c000}, {0x4545e000},
+ {0x45460000}, {0x45462000}, {0x45464000}, {0x45466000},
+ {0x45468000}, {0x4546a000}, {0x4546c000}, {0x4546e000},
+ {0x45470000}, {0x45472000}, {0x45474000}, {0x45476000},
+ {0x45478000}, {0x4547a000}, {0x4547c000}, {0x4547e000},
+ {0x45480000}, {0x45482000}, {0x45484000}, {0x45486000},
+ {0x45488000}, {0x4548a000}, {0x4548c000}, {0x4548e000},
+ {0x45490000}, {0x45492000}, {0x45494000}, {0x45496000},
+ {0x45498000}, {0x4549a000}, {0x4549c000}, {0x4549e000},
+ {0x454a0000}, {0x454a2000}, {0x454a4000}, {0x454a6000},
+ {0x454a8000}, {0x454aa000}, {0x454ac000}, {0x454ae000},
+ {0x454b0000}, {0x454b2000}, {0x454b4000}, {0x454b6000},
+ {0x454b8000}, {0x454ba000}, {0x454bc000}, {0x454be000},
+ {0x454c0000}, {0x454c2000}, {0x454c4000}, {0x454c6000},
+ {0x454c8000}, {0x454ca000}, {0x454cc000}, {0x454ce000},
+ {0x454d0000}, {0x454d2000}, {0x454d4000}, {0x454d6000},
+ {0x454d8000}, {0x454da000}, {0x454dc000}, {0x454de000},
+ {0x454e0000}, {0x454e2000}, {0x454e4000}, {0x454e6000},
+ {0x454e8000}, {0x454ea000}, {0x454ec000}, {0x454ee000},
+ {0x454f0000}, {0x454f2000}, {0x454f4000}, {0x454f6000},
+ {0x454f8000}, {0x454fa000}, {0x454fc000}, {0x454fe000},
+ {0x45500000}, {0x45502000}, {0x45504000}, {0x45506000},
+ {0x45508000}, {0x4550a000}, {0x4550c000}, {0x4550e000},
+ {0x45510000}, {0x45512000}, {0x45514000}, {0x45516000},
+ {0x45518000}, {0x4551a000}, {0x4551c000}, {0x4551e000},
+ {0x45520000}, {0x45522000}, {0x45524000}, {0x45526000},
+ {0x45528000}, {0x4552a000}, {0x4552c000}, {0x4552e000},
+ {0x45530000}, {0x45532000}, {0x45534000}, {0x45536000},
+ {0x45538000}, {0x4553a000}, {0x4553c000}, {0x4553e000},
+ {0x45540000}, {0x45542000}, {0x45544000}, {0x45546000},
+ {0x45548000}, {0x4554a000}, {0x4554c000}, {0x4554e000},
+ {0x45550000}, {0x45552000}, {0x45554000}, {0x45556000},
+ {0x45558000}, {0x4555a000}, {0x4555c000}, {0x4555e000},
+ {0x45560000}, {0x45562000}, {0x45564000}, {0x45566000},
+ {0x45568000}, {0x4556a000}, {0x4556c000}, {0x4556e000},
+ {0x45570000}, {0x45572000}, {0x45574000}, {0x45576000},
+ {0x45578000}, {0x4557a000}, {0x4557c000}, {0x4557e000},
+ {0x45580000}, {0x45582000}, {0x45584000}, {0x45586000},
+ {0x45588000}, {0x4558a000}, {0x4558c000}, {0x4558e000},
+ {0x45590000}, {0x45592000}, {0x45594000}, {0x45596000},
+ {0x45598000}, {0x4559a000}, {0x4559c000}, {0x4559e000},
+ {0x455a0000}, {0x455a2000}, {0x455a4000}, {0x455a6000},
+ {0x455a8000}, {0x455aa000}, {0x455ac000}, {0x455ae000},
+ {0x455b0000}, {0x455b2000}, {0x455b4000}, {0x455b6000},
+ {0x455b8000}, {0x455ba000}, {0x455bc000}, {0x455be000},
+ {0x455c0000}, {0x455c2000}, {0x455c4000}, {0x455c6000},
+ {0x455c8000}, {0x455ca000}, {0x455cc000}, {0x455ce000},
+ {0x455d0000}, {0x455d2000}, {0x455d4000}, {0x455d6000},
+ {0x455d8000}, {0x455da000}, {0x455dc000}, {0x455de000},
+ {0x455e0000}, {0x455e2000}, {0x455e4000}, {0x455e6000},
+ {0x455e8000}, {0x455ea000}, {0x455ec000}, {0x455ee000},
+ {0x455f0000}, {0x455f2000}, {0x455f4000}, {0x455f6000},
+ {0x455f8000}, {0x455fa000}, {0x455fc000}, {0x455fe000},
+ {0x45600000}, {0x45602000}, {0x45604000}, {0x45606000},
+ {0x45608000}, {0x4560a000}, {0x4560c000}, {0x4560e000},
+ {0x45610000}, {0x45612000}, {0x45614000}, {0x45616000},
+ {0x45618000}, {0x4561a000}, {0x4561c000}, {0x4561e000},
+ {0x45620000}, {0x45622000}, {0x45624000}, {0x45626000},
+ {0x45628000}, {0x4562a000}, {0x4562c000}, {0x4562e000},
+ {0x45630000}, {0x45632000}, {0x45634000}, {0x45636000},
+ {0x45638000}, {0x4563a000}, {0x4563c000}, {0x4563e000},
+ {0x45640000}, {0x45642000}, {0x45644000}, {0x45646000},
+ {0x45648000}, {0x4564a000}, {0x4564c000}, {0x4564e000},
+ {0x45650000}, {0x45652000}, {0x45654000}, {0x45656000},
+ {0x45658000}, {0x4565a000}, {0x4565c000}, {0x4565e000},
+ {0x45660000}, {0x45662000}, {0x45664000}, {0x45666000},
+ {0x45668000}, {0x4566a000}, {0x4566c000}, {0x4566e000},
+ {0x45670000}, {0x45672000}, {0x45674000}, {0x45676000},
+ {0x45678000}, {0x4567a000}, {0x4567c000}, {0x4567e000},
+ {0x45680000}, {0x45682000}, {0x45684000}, {0x45686000},
+ {0x45688000}, {0x4568a000}, {0x4568c000}, {0x4568e000},
+ {0x45690000}, {0x45692000}, {0x45694000}, {0x45696000},
+ {0x45698000}, {0x4569a000}, {0x4569c000}, {0x4569e000},
+ {0x456a0000}, {0x456a2000}, {0x456a4000}, {0x456a6000},
+ {0x456a8000}, {0x456aa000}, {0x456ac000}, {0x456ae000},
+ {0x456b0000}, {0x456b2000}, {0x456b4000}, {0x456b6000},
+ {0x456b8000}, {0x456ba000}, {0x456bc000}, {0x456be000},
+ {0x456c0000}, {0x456c2000}, {0x456c4000}, {0x456c6000},
+ {0x456c8000}, {0x456ca000}, {0x456cc000}, {0x456ce000},
+ {0x456d0000}, {0x456d2000}, {0x456d4000}, {0x456d6000},
+ {0x456d8000}, {0x456da000}, {0x456dc000}, {0x456de000},
+ {0x456e0000}, {0x456e2000}, {0x456e4000}, {0x456e6000},
+ {0x456e8000}, {0x456ea000}, {0x456ec000}, {0x456ee000},
+ {0x456f0000}, {0x456f2000}, {0x456f4000}, {0x456f6000},
+ {0x456f8000}, {0x456fa000}, {0x456fc000}, {0x456fe000},
+ {0x45700000}, {0x45702000}, {0x45704000}, {0x45706000},
+ {0x45708000}, {0x4570a000}, {0x4570c000}, {0x4570e000},
+ {0x45710000}, {0x45712000}, {0x45714000}, {0x45716000},
+ {0x45718000}, {0x4571a000}, {0x4571c000}, {0x4571e000},
+ {0x45720000}, {0x45722000}, {0x45724000}, {0x45726000},
+ {0x45728000}, {0x4572a000}, {0x4572c000}, {0x4572e000},
+ {0x45730000}, {0x45732000}, {0x45734000}, {0x45736000},
+ {0x45738000}, {0x4573a000}, {0x4573c000}, {0x4573e000},
+ {0x45740000}, {0x45742000}, {0x45744000}, {0x45746000},
+ {0x45748000}, {0x4574a000}, {0x4574c000}, {0x4574e000},
+ {0x45750000}, {0x45752000}, {0x45754000}, {0x45756000},
+ {0x45758000}, {0x4575a000}, {0x4575c000}, {0x4575e000},
+ {0x45760000}, {0x45762000}, {0x45764000}, {0x45766000},
+ {0x45768000}, {0x4576a000}, {0x4576c000}, {0x4576e000},
+ {0x45770000}, {0x45772000}, {0x45774000}, {0x45776000},
+ {0x45778000}, {0x4577a000}, {0x4577c000}, {0x4577e000},
+ {0x45780000}, {0x45782000}, {0x45784000}, {0x45786000},
+ {0x45788000}, {0x4578a000}, {0x4578c000}, {0x4578e000},
+ {0x45790000}, {0x45792000}, {0x45794000}, {0x45796000},
+ {0x45798000}, {0x4579a000}, {0x4579c000}, {0x4579e000},
+ {0x457a0000}, {0x457a2000}, {0x457a4000}, {0x457a6000},
+ {0x457a8000}, {0x457aa000}, {0x457ac000}, {0x457ae000},
+ {0x457b0000}, {0x457b2000}, {0x457b4000}, {0x457b6000},
+ {0x457b8000}, {0x457ba000}, {0x457bc000}, {0x457be000},
+ {0x457c0000}, {0x457c2000}, {0x457c4000}, {0x457c6000},
+ {0x457c8000}, {0x457ca000}, {0x457cc000}, {0x457ce000},
+ {0x457d0000}, {0x457d2000}, {0x457d4000}, {0x457d6000},
+ {0x457d8000}, {0x457da000}, {0x457dc000}, {0x457de000},
+ {0x457e0000}, {0x457e2000}, {0x457e4000}, {0x457e6000},
+ {0x457e8000}, {0x457ea000}, {0x457ec000}, {0x457ee000},
+ {0x457f0000}, {0x457f2000}, {0x457f4000}, {0x457f6000},
+ {0x457f8000}, {0x457fa000}, {0x457fc000}, {0x457fe000},
+ {0x45800000}, {0x45802000}, {0x45804000}, {0x45806000},
+ {0x45808000}, {0x4580a000}, {0x4580c000}, {0x4580e000},
+ {0x45810000}, {0x45812000}, {0x45814000}, {0x45816000},
+ {0x45818000}, {0x4581a000}, {0x4581c000}, {0x4581e000},
+ {0x45820000}, {0x45822000}, {0x45824000}, {0x45826000},
+ {0x45828000}, {0x4582a000}, {0x4582c000}, {0x4582e000},
+ {0x45830000}, {0x45832000}, {0x45834000}, {0x45836000},
+ {0x45838000}, {0x4583a000}, {0x4583c000}, {0x4583e000},
+ {0x45840000}, {0x45842000}, {0x45844000}, {0x45846000},
+ {0x45848000}, {0x4584a000}, {0x4584c000}, {0x4584e000},
+ {0x45850000}, {0x45852000}, {0x45854000}, {0x45856000},
+ {0x45858000}, {0x4585a000}, {0x4585c000}, {0x4585e000},
+ {0x45860000}, {0x45862000}, {0x45864000}, {0x45866000},
+ {0x45868000}, {0x4586a000}, {0x4586c000}, {0x4586e000},
+ {0x45870000}, {0x45872000}, {0x45874000}, {0x45876000},
+ {0x45878000}, {0x4587a000}, {0x4587c000}, {0x4587e000},
+ {0x45880000}, {0x45882000}, {0x45884000}, {0x45886000},
+ {0x45888000}, {0x4588a000}, {0x4588c000}, {0x4588e000},
+ {0x45890000}, {0x45892000}, {0x45894000}, {0x45896000},
+ {0x45898000}, {0x4589a000}, {0x4589c000}, {0x4589e000},
+ {0x458a0000}, {0x458a2000}, {0x458a4000}, {0x458a6000},
+ {0x458a8000}, {0x458aa000}, {0x458ac000}, {0x458ae000},
+ {0x458b0000}, {0x458b2000}, {0x458b4000}, {0x458b6000},
+ {0x458b8000}, {0x458ba000}, {0x458bc000}, {0x458be000},
+ {0x458c0000}, {0x458c2000}, {0x458c4000}, {0x458c6000},
+ {0x458c8000}, {0x458ca000}, {0x458cc000}, {0x458ce000},
+ {0x458d0000}, {0x458d2000}, {0x458d4000}, {0x458d6000},
+ {0x458d8000}, {0x458da000}, {0x458dc000}, {0x458de000},
+ {0x458e0000}, {0x458e2000}, {0x458e4000}, {0x458e6000},
+ {0x458e8000}, {0x458ea000}, {0x458ec000}, {0x458ee000},
+ {0x458f0000}, {0x458f2000}, {0x458f4000}, {0x458f6000},
+ {0x458f8000}, {0x458fa000}, {0x458fc000}, {0x458fe000},
+ {0x45900000}, {0x45902000}, {0x45904000}, {0x45906000},
+ {0x45908000}, {0x4590a000}, {0x4590c000}, {0x4590e000},
+ {0x45910000}, {0x45912000}, {0x45914000}, {0x45916000},
+ {0x45918000}, {0x4591a000}, {0x4591c000}, {0x4591e000},
+ {0x45920000}, {0x45922000}, {0x45924000}, {0x45926000},
+ {0x45928000}, {0x4592a000}, {0x4592c000}, {0x4592e000},
+ {0x45930000}, {0x45932000}, {0x45934000}, {0x45936000},
+ {0x45938000}, {0x4593a000}, {0x4593c000}, {0x4593e000},
+ {0x45940000}, {0x45942000}, {0x45944000}, {0x45946000},
+ {0x45948000}, {0x4594a000}, {0x4594c000}, {0x4594e000},
+ {0x45950000}, {0x45952000}, {0x45954000}, {0x45956000},
+ {0x45958000}, {0x4595a000}, {0x4595c000}, {0x4595e000},
+ {0x45960000}, {0x45962000}, {0x45964000}, {0x45966000},
+ {0x45968000}, {0x4596a000}, {0x4596c000}, {0x4596e000},
+ {0x45970000}, {0x45972000}, {0x45974000}, {0x45976000},
+ {0x45978000}, {0x4597a000}, {0x4597c000}, {0x4597e000},
+ {0x45980000}, {0x45982000}, {0x45984000}, {0x45986000},
+ {0x45988000}, {0x4598a000}, {0x4598c000}, {0x4598e000},
+ {0x45990000}, {0x45992000}, {0x45994000}, {0x45996000},
+ {0x45998000}, {0x4599a000}, {0x4599c000}, {0x4599e000},
+ {0x459a0000}, {0x459a2000}, {0x459a4000}, {0x459a6000},
+ {0x459a8000}, {0x459aa000}, {0x459ac000}, {0x459ae000},
+ {0x459b0000}, {0x459b2000}, {0x459b4000}, {0x459b6000},
+ {0x459b8000}, {0x459ba000}, {0x459bc000}, {0x459be000},
+ {0x459c0000}, {0x459c2000}, {0x459c4000}, {0x459c6000},
+ {0x459c8000}, {0x459ca000}, {0x459cc000}, {0x459ce000},
+ {0x459d0000}, {0x459d2000}, {0x459d4000}, {0x459d6000},
+ {0x459d8000}, {0x459da000}, {0x459dc000}, {0x459de000},
+ {0x459e0000}, {0x459e2000}, {0x459e4000}, {0x459e6000},
+ {0x459e8000}, {0x459ea000}, {0x459ec000}, {0x459ee000},
+ {0x459f0000}, {0x459f2000}, {0x459f4000}, {0x459f6000},
+ {0x459f8000}, {0x459fa000}, {0x459fc000}, {0x459fe000},
+ {0x45a00000}, {0x45a02000}, {0x45a04000}, {0x45a06000},
+ {0x45a08000}, {0x45a0a000}, {0x45a0c000}, {0x45a0e000},
+ {0x45a10000}, {0x45a12000}, {0x45a14000}, {0x45a16000},
+ {0x45a18000}, {0x45a1a000}, {0x45a1c000}, {0x45a1e000},
+ {0x45a20000}, {0x45a22000}, {0x45a24000}, {0x45a26000},
+ {0x45a28000}, {0x45a2a000}, {0x45a2c000}, {0x45a2e000},
+ {0x45a30000}, {0x45a32000}, {0x45a34000}, {0x45a36000},
+ {0x45a38000}, {0x45a3a000}, {0x45a3c000}, {0x45a3e000},
+ {0x45a40000}, {0x45a42000}, {0x45a44000}, {0x45a46000},
+ {0x45a48000}, {0x45a4a000}, {0x45a4c000}, {0x45a4e000},
+ {0x45a50000}, {0x45a52000}, {0x45a54000}, {0x45a56000},
+ {0x45a58000}, {0x45a5a000}, {0x45a5c000}, {0x45a5e000},
+ {0x45a60000}, {0x45a62000}, {0x45a64000}, {0x45a66000},
+ {0x45a68000}, {0x45a6a000}, {0x45a6c000}, {0x45a6e000},
+ {0x45a70000}, {0x45a72000}, {0x45a74000}, {0x45a76000},
+ {0x45a78000}, {0x45a7a000}, {0x45a7c000}, {0x45a7e000},
+ {0x45a80000}, {0x45a82000}, {0x45a84000}, {0x45a86000},
+ {0x45a88000}, {0x45a8a000}, {0x45a8c000}, {0x45a8e000},
+ {0x45a90000}, {0x45a92000}, {0x45a94000}, {0x45a96000},
+ {0x45a98000}, {0x45a9a000}, {0x45a9c000}, {0x45a9e000},
+ {0x45aa0000}, {0x45aa2000}, {0x45aa4000}, {0x45aa6000},
+ {0x45aa8000}, {0x45aaa000}, {0x45aac000}, {0x45aae000},
+ {0x45ab0000}, {0x45ab2000}, {0x45ab4000}, {0x45ab6000},
+ {0x45ab8000}, {0x45aba000}, {0x45abc000}, {0x45abe000},
+ {0x45ac0000}, {0x45ac2000}, {0x45ac4000}, {0x45ac6000},
+ {0x45ac8000}, {0x45aca000}, {0x45acc000}, {0x45ace000},
+ {0x45ad0000}, {0x45ad2000}, {0x45ad4000}, {0x45ad6000},
+ {0x45ad8000}, {0x45ada000}, {0x45adc000}, {0x45ade000},
+ {0x45ae0000}, {0x45ae2000}, {0x45ae4000}, {0x45ae6000},
+ {0x45ae8000}, {0x45aea000}, {0x45aec000}, {0x45aee000},
+ {0x45af0000}, {0x45af2000}, {0x45af4000}, {0x45af6000},
+ {0x45af8000}, {0x45afa000}, {0x45afc000}, {0x45afe000},
+ {0x45b00000}, {0x45b02000}, {0x45b04000}, {0x45b06000},
+ {0x45b08000}, {0x45b0a000}, {0x45b0c000}, {0x45b0e000},
+ {0x45b10000}, {0x45b12000}, {0x45b14000}, {0x45b16000},
+ {0x45b18000}, {0x45b1a000}, {0x45b1c000}, {0x45b1e000},
+ {0x45b20000}, {0x45b22000}, {0x45b24000}, {0x45b26000},
+ {0x45b28000}, {0x45b2a000}, {0x45b2c000}, {0x45b2e000},
+ {0x45b30000}, {0x45b32000}, {0x45b34000}, {0x45b36000},
+ {0x45b38000}, {0x45b3a000}, {0x45b3c000}, {0x45b3e000},
+ {0x45b40000}, {0x45b42000}, {0x45b44000}, {0x45b46000},
+ {0x45b48000}, {0x45b4a000}, {0x45b4c000}, {0x45b4e000},
+ {0x45b50000}, {0x45b52000}, {0x45b54000}, {0x45b56000},
+ {0x45b58000}, {0x45b5a000}, {0x45b5c000}, {0x45b5e000},
+ {0x45b60000}, {0x45b62000}, {0x45b64000}, {0x45b66000},
+ {0x45b68000}, {0x45b6a000}, {0x45b6c000}, {0x45b6e000},
+ {0x45b70000}, {0x45b72000}, {0x45b74000}, {0x45b76000},
+ {0x45b78000}, {0x45b7a000}, {0x45b7c000}, {0x45b7e000},
+ {0x45b80000}, {0x45b82000}, {0x45b84000}, {0x45b86000},
+ {0x45b88000}, {0x45b8a000}, {0x45b8c000}, {0x45b8e000},
+ {0x45b90000}, {0x45b92000}, {0x45b94000}, {0x45b96000},
+ {0x45b98000}, {0x45b9a000}, {0x45b9c000}, {0x45b9e000},
+ {0x45ba0000}, {0x45ba2000}, {0x45ba4000}, {0x45ba6000},
+ {0x45ba8000}, {0x45baa000}, {0x45bac000}, {0x45bae000},
+ {0x45bb0000}, {0x45bb2000}, {0x45bb4000}, {0x45bb6000},
+ {0x45bb8000}, {0x45bba000}, {0x45bbc000}, {0x45bbe000},
+ {0x45bc0000}, {0x45bc2000}, {0x45bc4000}, {0x45bc6000},
+ {0x45bc8000}, {0x45bca000}, {0x45bcc000}, {0x45bce000},
+ {0x45bd0000}, {0x45bd2000}, {0x45bd4000}, {0x45bd6000},
+ {0x45bd8000}, {0x45bda000}, {0x45bdc000}, {0x45bde000},
+ {0x45be0000}, {0x45be2000}, {0x45be4000}, {0x45be6000},
+ {0x45be8000}, {0x45bea000}, {0x45bec000}, {0x45bee000},
+ {0x45bf0000}, {0x45bf2000}, {0x45bf4000}, {0x45bf6000},
+ {0x45bf8000}, {0x45bfa000}, {0x45bfc000}, {0x45bfe000},
+ {0x45c00000}, {0x45c02000}, {0x45c04000}, {0x45c06000},
+ {0x45c08000}, {0x45c0a000}, {0x45c0c000}, {0x45c0e000},
+ {0x45c10000}, {0x45c12000}, {0x45c14000}, {0x45c16000},
+ {0x45c18000}, {0x45c1a000}, {0x45c1c000}, {0x45c1e000},
+ {0x45c20000}, {0x45c22000}, {0x45c24000}, {0x45c26000},
+ {0x45c28000}, {0x45c2a000}, {0x45c2c000}, {0x45c2e000},
+ {0x45c30000}, {0x45c32000}, {0x45c34000}, {0x45c36000},
+ {0x45c38000}, {0x45c3a000}, {0x45c3c000}, {0x45c3e000},
+ {0x45c40000}, {0x45c42000}, {0x45c44000}, {0x45c46000},
+ {0x45c48000}, {0x45c4a000}, {0x45c4c000}, {0x45c4e000},
+ {0x45c50000}, {0x45c52000}, {0x45c54000}, {0x45c56000},
+ {0x45c58000}, {0x45c5a000}, {0x45c5c000}, {0x45c5e000},
+ {0x45c60000}, {0x45c62000}, {0x45c64000}, {0x45c66000},
+ {0x45c68000}, {0x45c6a000}, {0x45c6c000}, {0x45c6e000},
+ {0x45c70000}, {0x45c72000}, {0x45c74000}, {0x45c76000},
+ {0x45c78000}, {0x45c7a000}, {0x45c7c000}, {0x45c7e000},
+ {0x45c80000}, {0x45c82000}, {0x45c84000}, {0x45c86000},
+ {0x45c88000}, {0x45c8a000}, {0x45c8c000}, {0x45c8e000},
+ {0x45c90000}, {0x45c92000}, {0x45c94000}, {0x45c96000},
+ {0x45c98000}, {0x45c9a000}, {0x45c9c000}, {0x45c9e000},
+ {0x45ca0000}, {0x45ca2000}, {0x45ca4000}, {0x45ca6000},
+ {0x45ca8000}, {0x45caa000}, {0x45cac000}, {0x45cae000},
+ {0x45cb0000}, {0x45cb2000}, {0x45cb4000}, {0x45cb6000},
+ {0x45cb8000}, {0x45cba000}, {0x45cbc000}, {0x45cbe000},
+ {0x45cc0000}, {0x45cc2000}, {0x45cc4000}, {0x45cc6000},
+ {0x45cc8000}, {0x45cca000}, {0x45ccc000}, {0x45cce000},
+ {0x45cd0000}, {0x45cd2000}, {0x45cd4000}, {0x45cd6000},
+ {0x45cd8000}, {0x45cda000}, {0x45cdc000}, {0x45cde000},
+ {0x45ce0000}, {0x45ce2000}, {0x45ce4000}, {0x45ce6000},
+ {0x45ce8000}, {0x45cea000}, {0x45cec000}, {0x45cee000},
+ {0x45cf0000}, {0x45cf2000}, {0x45cf4000}, {0x45cf6000},
+ {0x45cf8000}, {0x45cfa000}, {0x45cfc000}, {0x45cfe000},
+ {0x45d00000}, {0x45d02000}, {0x45d04000}, {0x45d06000},
+ {0x45d08000}, {0x45d0a000}, {0x45d0c000}, {0x45d0e000},
+ {0x45d10000}, {0x45d12000}, {0x45d14000}, {0x45d16000},
+ {0x45d18000}, {0x45d1a000}, {0x45d1c000}, {0x45d1e000},
+ {0x45d20000}, {0x45d22000}, {0x45d24000}, {0x45d26000},
+ {0x45d28000}, {0x45d2a000}, {0x45d2c000}, {0x45d2e000},
+ {0x45d30000}, {0x45d32000}, {0x45d34000}, {0x45d36000},
+ {0x45d38000}, {0x45d3a000}, {0x45d3c000}, {0x45d3e000},
+ {0x45d40000}, {0x45d42000}, {0x45d44000}, {0x45d46000},
+ {0x45d48000}, {0x45d4a000}, {0x45d4c000}, {0x45d4e000},
+ {0x45d50000}, {0x45d52000}, {0x45d54000}, {0x45d56000},
+ {0x45d58000}, {0x45d5a000}, {0x45d5c000}, {0x45d5e000},
+ {0x45d60000}, {0x45d62000}, {0x45d64000}, {0x45d66000},
+ {0x45d68000}, {0x45d6a000}, {0x45d6c000}, {0x45d6e000},
+ {0x45d70000}, {0x45d72000}, {0x45d74000}, {0x45d76000},
+ {0x45d78000}, {0x45d7a000}, {0x45d7c000}, {0x45d7e000},
+ {0x45d80000}, {0x45d82000}, {0x45d84000}, {0x45d86000},
+ {0x45d88000}, {0x45d8a000}, {0x45d8c000}, {0x45d8e000},
+ {0x45d90000}, {0x45d92000}, {0x45d94000}, {0x45d96000},
+ {0x45d98000}, {0x45d9a000}, {0x45d9c000}, {0x45d9e000},
+ {0x45da0000}, {0x45da2000}, {0x45da4000}, {0x45da6000},
+ {0x45da8000}, {0x45daa000}, {0x45dac000}, {0x45dae000},
+ {0x45db0000}, {0x45db2000}, {0x45db4000}, {0x45db6000},
+ {0x45db8000}, {0x45dba000}, {0x45dbc000}, {0x45dbe000},
+ {0x45dc0000}, {0x45dc2000}, {0x45dc4000}, {0x45dc6000},
+ {0x45dc8000}, {0x45dca000}, {0x45dcc000}, {0x45dce000},
+ {0x45dd0000}, {0x45dd2000}, {0x45dd4000}, {0x45dd6000},
+ {0x45dd8000}, {0x45dda000}, {0x45ddc000}, {0x45dde000},
+ {0x45de0000}, {0x45de2000}, {0x45de4000}, {0x45de6000},
+ {0x45de8000}, {0x45dea000}, {0x45dec000}, {0x45dee000},
+ {0x45df0000}, {0x45df2000}, {0x45df4000}, {0x45df6000},
+ {0x45df8000}, {0x45dfa000}, {0x45dfc000}, {0x45dfe000},
+ {0x45e00000}, {0x45e02000}, {0x45e04000}, {0x45e06000},
+ {0x45e08000}, {0x45e0a000}, {0x45e0c000}, {0x45e0e000},
+ {0x45e10000}, {0x45e12000}, {0x45e14000}, {0x45e16000},
+ {0x45e18000}, {0x45e1a000}, {0x45e1c000}, {0x45e1e000},
+ {0x45e20000}, {0x45e22000}, {0x45e24000}, {0x45e26000},
+ {0x45e28000}, {0x45e2a000}, {0x45e2c000}, {0x45e2e000},
+ {0x45e30000}, {0x45e32000}, {0x45e34000}, {0x45e36000},
+ {0x45e38000}, {0x45e3a000}, {0x45e3c000}, {0x45e3e000},
+ {0x45e40000}, {0x45e42000}, {0x45e44000}, {0x45e46000},
+ {0x45e48000}, {0x45e4a000}, {0x45e4c000}, {0x45e4e000},
+ {0x45e50000}, {0x45e52000}, {0x45e54000}, {0x45e56000},
+ {0x45e58000}, {0x45e5a000}, {0x45e5c000}, {0x45e5e000},
+ {0x45e60000}, {0x45e62000}, {0x45e64000}, {0x45e66000},
+ {0x45e68000}, {0x45e6a000}, {0x45e6c000}, {0x45e6e000},
+ {0x45e70000}, {0x45e72000}, {0x45e74000}, {0x45e76000},
+ {0x45e78000}, {0x45e7a000}, {0x45e7c000}, {0x45e7e000},
+ {0x45e80000}, {0x45e82000}, {0x45e84000}, {0x45e86000},
+ {0x45e88000}, {0x45e8a000}, {0x45e8c000}, {0x45e8e000},
+ {0x45e90000}, {0x45e92000}, {0x45e94000}, {0x45e96000},
+ {0x45e98000}, {0x45e9a000}, {0x45e9c000}, {0x45e9e000},
+ {0x45ea0000}, {0x45ea2000}, {0x45ea4000}, {0x45ea6000},
+ {0x45ea8000}, {0x45eaa000}, {0x45eac000}, {0x45eae000},
+ {0x45eb0000}, {0x45eb2000}, {0x45eb4000}, {0x45eb6000},
+ {0x45eb8000}, {0x45eba000}, {0x45ebc000}, {0x45ebe000},
+ {0x45ec0000}, {0x45ec2000}, {0x45ec4000}, {0x45ec6000},
+ {0x45ec8000}, {0x45eca000}, {0x45ecc000}, {0x45ece000},
+ {0x45ed0000}, {0x45ed2000}, {0x45ed4000}, {0x45ed6000},
+ {0x45ed8000}, {0x45eda000}, {0x45edc000}, {0x45ede000},
+ {0x45ee0000}, {0x45ee2000}, {0x45ee4000}, {0x45ee6000},
+ {0x45ee8000}, {0x45eea000}, {0x45eec000}, {0x45eee000},
+ {0x45ef0000}, {0x45ef2000}, {0x45ef4000}, {0x45ef6000},
+ {0x45ef8000}, {0x45efa000}, {0x45efc000}, {0x45efe000},
+ {0x45f00000}, {0x45f02000}, {0x45f04000}, {0x45f06000},
+ {0x45f08000}, {0x45f0a000}, {0x45f0c000}, {0x45f0e000},
+ {0x45f10000}, {0x45f12000}, {0x45f14000}, {0x45f16000},
+ {0x45f18000}, {0x45f1a000}, {0x45f1c000}, {0x45f1e000},
+ {0x45f20000}, {0x45f22000}, {0x45f24000}, {0x45f26000},
+ {0x45f28000}, {0x45f2a000}, {0x45f2c000}, {0x45f2e000},
+ {0x45f30000}, {0x45f32000}, {0x45f34000}, {0x45f36000},
+ {0x45f38000}, {0x45f3a000}, {0x45f3c000}, {0x45f3e000},
+ {0x45f40000}, {0x45f42000}, {0x45f44000}, {0x45f46000},
+ {0x45f48000}, {0x45f4a000}, {0x45f4c000}, {0x45f4e000},
+ {0x45f50000}, {0x45f52000}, {0x45f54000}, {0x45f56000},
+ {0x45f58000}, {0x45f5a000}, {0x45f5c000}, {0x45f5e000},
+ {0x45f60000}, {0x45f62000}, {0x45f64000}, {0x45f66000},
+ {0x45f68000}, {0x45f6a000}, {0x45f6c000}, {0x45f6e000},
+ {0x45f70000}, {0x45f72000}, {0x45f74000}, {0x45f76000},
+ {0x45f78000}, {0x45f7a000}, {0x45f7c000}, {0x45f7e000},
+ {0x45f80000}, {0x45f82000}, {0x45f84000}, {0x45f86000},
+ {0x45f88000}, {0x45f8a000}, {0x45f8c000}, {0x45f8e000},
+ {0x45f90000}, {0x45f92000}, {0x45f94000}, {0x45f96000},
+ {0x45f98000}, {0x45f9a000}, {0x45f9c000}, {0x45f9e000},
+ {0x45fa0000}, {0x45fa2000}, {0x45fa4000}, {0x45fa6000},
+ {0x45fa8000}, {0x45faa000}, {0x45fac000}, {0x45fae000},
+ {0x45fb0000}, {0x45fb2000}, {0x45fb4000}, {0x45fb6000},
+ {0x45fb8000}, {0x45fba000}, {0x45fbc000}, {0x45fbe000},
+ {0x45fc0000}, {0x45fc2000}, {0x45fc4000}, {0x45fc6000},
+ {0x45fc8000}, {0x45fca000}, {0x45fcc000}, {0x45fce000},
+ {0x45fd0000}, {0x45fd2000}, {0x45fd4000}, {0x45fd6000},
+ {0x45fd8000}, {0x45fda000}, {0x45fdc000}, {0x45fde000},
+ {0x45fe0000}, {0x45fe2000}, {0x45fe4000}, {0x45fe6000},
+ {0x45fe8000}, {0x45fea000}, {0x45fec000}, {0x45fee000},
+ {0x45ff0000}, {0x45ff2000}, {0x45ff4000}, {0x45ff6000},
+ {0x45ff8000}, {0x45ffa000}, {0x45ffc000}, {0x45ffe000},
+ {0x46000000}, {0x46002000}, {0x46004000}, {0x46006000},
+ {0x46008000}, {0x4600a000}, {0x4600c000}, {0x4600e000},
+ {0x46010000}, {0x46012000}, {0x46014000}, {0x46016000},
+ {0x46018000}, {0x4601a000}, {0x4601c000}, {0x4601e000},
+ {0x46020000}, {0x46022000}, {0x46024000}, {0x46026000},
+ {0x46028000}, {0x4602a000}, {0x4602c000}, {0x4602e000},
+ {0x46030000}, {0x46032000}, {0x46034000}, {0x46036000},
+ {0x46038000}, {0x4603a000}, {0x4603c000}, {0x4603e000},
+ {0x46040000}, {0x46042000}, {0x46044000}, {0x46046000},
+ {0x46048000}, {0x4604a000}, {0x4604c000}, {0x4604e000},
+ {0x46050000}, {0x46052000}, {0x46054000}, {0x46056000},
+ {0x46058000}, {0x4605a000}, {0x4605c000}, {0x4605e000},
+ {0x46060000}, {0x46062000}, {0x46064000}, {0x46066000},
+ {0x46068000}, {0x4606a000}, {0x4606c000}, {0x4606e000},
+ {0x46070000}, {0x46072000}, {0x46074000}, {0x46076000},
+ {0x46078000}, {0x4607a000}, {0x4607c000}, {0x4607e000},
+ {0x46080000}, {0x46082000}, {0x46084000}, {0x46086000},
+ {0x46088000}, {0x4608a000}, {0x4608c000}, {0x4608e000},
+ {0x46090000}, {0x46092000}, {0x46094000}, {0x46096000},
+ {0x46098000}, {0x4609a000}, {0x4609c000}, {0x4609e000},
+ {0x460a0000}, {0x460a2000}, {0x460a4000}, {0x460a6000},
+ {0x460a8000}, {0x460aa000}, {0x460ac000}, {0x460ae000},
+ {0x460b0000}, {0x460b2000}, {0x460b4000}, {0x460b6000},
+ {0x460b8000}, {0x460ba000}, {0x460bc000}, {0x460be000},
+ {0x460c0000}, {0x460c2000}, {0x460c4000}, {0x460c6000},
+ {0x460c8000}, {0x460ca000}, {0x460cc000}, {0x460ce000},
+ {0x460d0000}, {0x460d2000}, {0x460d4000}, {0x460d6000},
+ {0x460d8000}, {0x460da000}, {0x460dc000}, {0x460de000},
+ {0x460e0000}, {0x460e2000}, {0x460e4000}, {0x460e6000},
+ {0x460e8000}, {0x460ea000}, {0x460ec000}, {0x460ee000},
+ {0x460f0000}, {0x460f2000}, {0x460f4000}, {0x460f6000},
+ {0x460f8000}, {0x460fa000}, {0x460fc000}, {0x460fe000},
+ {0x46100000}, {0x46102000}, {0x46104000}, {0x46106000},
+ {0x46108000}, {0x4610a000}, {0x4610c000}, {0x4610e000},
+ {0x46110000}, {0x46112000}, {0x46114000}, {0x46116000},
+ {0x46118000}, {0x4611a000}, {0x4611c000}, {0x4611e000},
+ {0x46120000}, {0x46122000}, {0x46124000}, {0x46126000},
+ {0x46128000}, {0x4612a000}, {0x4612c000}, {0x4612e000},
+ {0x46130000}, {0x46132000}, {0x46134000}, {0x46136000},
+ {0x46138000}, {0x4613a000}, {0x4613c000}, {0x4613e000},
+ {0x46140000}, {0x46142000}, {0x46144000}, {0x46146000},
+ {0x46148000}, {0x4614a000}, {0x4614c000}, {0x4614e000},
+ {0x46150000}, {0x46152000}, {0x46154000}, {0x46156000},
+ {0x46158000}, {0x4615a000}, {0x4615c000}, {0x4615e000},
+ {0x46160000}, {0x46162000}, {0x46164000}, {0x46166000},
+ {0x46168000}, {0x4616a000}, {0x4616c000}, {0x4616e000},
+ {0x46170000}, {0x46172000}, {0x46174000}, {0x46176000},
+ {0x46178000}, {0x4617a000}, {0x4617c000}, {0x4617e000},
+ {0x46180000}, {0x46182000}, {0x46184000}, {0x46186000},
+ {0x46188000}, {0x4618a000}, {0x4618c000}, {0x4618e000},
+ {0x46190000}, {0x46192000}, {0x46194000}, {0x46196000},
+ {0x46198000}, {0x4619a000}, {0x4619c000}, {0x4619e000},
+ {0x461a0000}, {0x461a2000}, {0x461a4000}, {0x461a6000},
+ {0x461a8000}, {0x461aa000}, {0x461ac000}, {0x461ae000},
+ {0x461b0000}, {0x461b2000}, {0x461b4000}, {0x461b6000},
+ {0x461b8000}, {0x461ba000}, {0x461bc000}, {0x461be000},
+ {0x461c0000}, {0x461c2000}, {0x461c4000}, {0x461c6000},
+ {0x461c8000}, {0x461ca000}, {0x461cc000}, {0x461ce000},
+ {0x461d0000}, {0x461d2000}, {0x461d4000}, {0x461d6000},
+ {0x461d8000}, {0x461da000}, {0x461dc000}, {0x461de000},
+ {0x461e0000}, {0x461e2000}, {0x461e4000}, {0x461e6000},
+ {0x461e8000}, {0x461ea000}, {0x461ec000}, {0x461ee000},
+ {0x461f0000}, {0x461f2000}, {0x461f4000}, {0x461f6000},
+ {0x461f8000}, {0x461fa000}, {0x461fc000}, {0x461fe000},
+ {0x46200000}, {0x46202000}, {0x46204000}, {0x46206000},
+ {0x46208000}, {0x4620a000}, {0x4620c000}, {0x4620e000},
+ {0x46210000}, {0x46212000}, {0x46214000}, {0x46216000},
+ {0x46218000}, {0x4621a000}, {0x4621c000}, {0x4621e000},
+ {0x46220000}, {0x46222000}, {0x46224000}, {0x46226000},
+ {0x46228000}, {0x4622a000}, {0x4622c000}, {0x4622e000},
+ {0x46230000}, {0x46232000}, {0x46234000}, {0x46236000},
+ {0x46238000}, {0x4623a000}, {0x4623c000}, {0x4623e000},
+ {0x46240000}, {0x46242000}, {0x46244000}, {0x46246000},
+ {0x46248000}, {0x4624a000}, {0x4624c000}, {0x4624e000},
+ {0x46250000}, {0x46252000}, {0x46254000}, {0x46256000},
+ {0x46258000}, {0x4625a000}, {0x4625c000}, {0x4625e000},
+ {0x46260000}, {0x46262000}, {0x46264000}, {0x46266000},
+ {0x46268000}, {0x4626a000}, {0x4626c000}, {0x4626e000},
+ {0x46270000}, {0x46272000}, {0x46274000}, {0x46276000},
+ {0x46278000}, {0x4627a000}, {0x4627c000}, {0x4627e000},
+ {0x46280000}, {0x46282000}, {0x46284000}, {0x46286000},
+ {0x46288000}, {0x4628a000}, {0x4628c000}, {0x4628e000},
+ {0x46290000}, {0x46292000}, {0x46294000}, {0x46296000},
+ {0x46298000}, {0x4629a000}, {0x4629c000}, {0x4629e000},
+ {0x462a0000}, {0x462a2000}, {0x462a4000}, {0x462a6000},
+ {0x462a8000}, {0x462aa000}, {0x462ac000}, {0x462ae000},
+ {0x462b0000}, {0x462b2000}, {0x462b4000}, {0x462b6000},
+ {0x462b8000}, {0x462ba000}, {0x462bc000}, {0x462be000},
+ {0x462c0000}, {0x462c2000}, {0x462c4000}, {0x462c6000},
+ {0x462c8000}, {0x462ca000}, {0x462cc000}, {0x462ce000},
+ {0x462d0000}, {0x462d2000}, {0x462d4000}, {0x462d6000},
+ {0x462d8000}, {0x462da000}, {0x462dc000}, {0x462de000},
+ {0x462e0000}, {0x462e2000}, {0x462e4000}, {0x462e6000},
+ {0x462e8000}, {0x462ea000}, {0x462ec000}, {0x462ee000},
+ {0x462f0000}, {0x462f2000}, {0x462f4000}, {0x462f6000},
+ {0x462f8000}, {0x462fa000}, {0x462fc000}, {0x462fe000},
+ {0x46300000}, {0x46302000}, {0x46304000}, {0x46306000},
+ {0x46308000}, {0x4630a000}, {0x4630c000}, {0x4630e000},
+ {0x46310000}, {0x46312000}, {0x46314000}, {0x46316000},
+ {0x46318000}, {0x4631a000}, {0x4631c000}, {0x4631e000},
+ {0x46320000}, {0x46322000}, {0x46324000}, {0x46326000},
+ {0x46328000}, {0x4632a000}, {0x4632c000}, {0x4632e000},
+ {0x46330000}, {0x46332000}, {0x46334000}, {0x46336000},
+ {0x46338000}, {0x4633a000}, {0x4633c000}, {0x4633e000},
+ {0x46340000}, {0x46342000}, {0x46344000}, {0x46346000},
+ {0x46348000}, {0x4634a000}, {0x4634c000}, {0x4634e000},
+ {0x46350000}, {0x46352000}, {0x46354000}, {0x46356000},
+ {0x46358000}, {0x4635a000}, {0x4635c000}, {0x4635e000},
+ {0x46360000}, {0x46362000}, {0x46364000}, {0x46366000},
+ {0x46368000}, {0x4636a000}, {0x4636c000}, {0x4636e000},
+ {0x46370000}, {0x46372000}, {0x46374000}, {0x46376000},
+ {0x46378000}, {0x4637a000}, {0x4637c000}, {0x4637e000},
+ {0x46380000}, {0x46382000}, {0x46384000}, {0x46386000},
+ {0x46388000}, {0x4638a000}, {0x4638c000}, {0x4638e000},
+ {0x46390000}, {0x46392000}, {0x46394000}, {0x46396000},
+ {0x46398000}, {0x4639a000}, {0x4639c000}, {0x4639e000},
+ {0x463a0000}, {0x463a2000}, {0x463a4000}, {0x463a6000},
+ {0x463a8000}, {0x463aa000}, {0x463ac000}, {0x463ae000},
+ {0x463b0000}, {0x463b2000}, {0x463b4000}, {0x463b6000},
+ {0x463b8000}, {0x463ba000}, {0x463bc000}, {0x463be000},
+ {0x463c0000}, {0x463c2000}, {0x463c4000}, {0x463c6000},
+ {0x463c8000}, {0x463ca000}, {0x463cc000}, {0x463ce000},
+ {0x463d0000}, {0x463d2000}, {0x463d4000}, {0x463d6000},
+ {0x463d8000}, {0x463da000}, {0x463dc000}, {0x463de000},
+ {0x463e0000}, {0x463e2000}, {0x463e4000}, {0x463e6000},
+ {0x463e8000}, {0x463ea000}, {0x463ec000}, {0x463ee000},
+ {0x463f0000}, {0x463f2000}, {0x463f4000}, {0x463f6000},
+ {0x463f8000}, {0x463fa000}, {0x463fc000}, {0x463fe000},
+ {0x46400000}, {0x46402000}, {0x46404000}, {0x46406000},
+ {0x46408000}, {0x4640a000}, {0x4640c000}, {0x4640e000},
+ {0x46410000}, {0x46412000}, {0x46414000}, {0x46416000},
+ {0x46418000}, {0x4641a000}, {0x4641c000}, {0x4641e000},
+ {0x46420000}, {0x46422000}, {0x46424000}, {0x46426000},
+ {0x46428000}, {0x4642a000}, {0x4642c000}, {0x4642e000},
+ {0x46430000}, {0x46432000}, {0x46434000}, {0x46436000},
+ {0x46438000}, {0x4643a000}, {0x4643c000}, {0x4643e000},
+ {0x46440000}, {0x46442000}, {0x46444000}, {0x46446000},
+ {0x46448000}, {0x4644a000}, {0x4644c000}, {0x4644e000},
+ {0x46450000}, {0x46452000}, {0x46454000}, {0x46456000},
+ {0x46458000}, {0x4645a000}, {0x4645c000}, {0x4645e000},
+ {0x46460000}, {0x46462000}, {0x46464000}, {0x46466000},
+ {0x46468000}, {0x4646a000}, {0x4646c000}, {0x4646e000},
+ {0x46470000}, {0x46472000}, {0x46474000}, {0x46476000},
+ {0x46478000}, {0x4647a000}, {0x4647c000}, {0x4647e000},
+ {0x46480000}, {0x46482000}, {0x46484000}, {0x46486000},
+ {0x46488000}, {0x4648a000}, {0x4648c000}, {0x4648e000},
+ {0x46490000}, {0x46492000}, {0x46494000}, {0x46496000},
+ {0x46498000}, {0x4649a000}, {0x4649c000}, {0x4649e000},
+ {0x464a0000}, {0x464a2000}, {0x464a4000}, {0x464a6000},
+ {0x464a8000}, {0x464aa000}, {0x464ac000}, {0x464ae000},
+ {0x464b0000}, {0x464b2000}, {0x464b4000}, {0x464b6000},
+ {0x464b8000}, {0x464ba000}, {0x464bc000}, {0x464be000},
+ {0x464c0000}, {0x464c2000}, {0x464c4000}, {0x464c6000},
+ {0x464c8000}, {0x464ca000}, {0x464cc000}, {0x464ce000},
+ {0x464d0000}, {0x464d2000}, {0x464d4000}, {0x464d6000},
+ {0x464d8000}, {0x464da000}, {0x464dc000}, {0x464de000},
+ {0x464e0000}, {0x464e2000}, {0x464e4000}, {0x464e6000},
+ {0x464e8000}, {0x464ea000}, {0x464ec000}, {0x464ee000},
+ {0x464f0000}, {0x464f2000}, {0x464f4000}, {0x464f6000},
+ {0x464f8000}, {0x464fa000}, {0x464fc000}, {0x464fe000},
+ {0x46500000}, {0x46502000}, {0x46504000}, {0x46506000},
+ {0x46508000}, {0x4650a000}, {0x4650c000}, {0x4650e000},
+ {0x46510000}, {0x46512000}, {0x46514000}, {0x46516000},
+ {0x46518000}, {0x4651a000}, {0x4651c000}, {0x4651e000},
+ {0x46520000}, {0x46522000}, {0x46524000}, {0x46526000},
+ {0x46528000}, {0x4652a000}, {0x4652c000}, {0x4652e000},
+ {0x46530000}, {0x46532000}, {0x46534000}, {0x46536000},
+ {0x46538000}, {0x4653a000}, {0x4653c000}, {0x4653e000},
+ {0x46540000}, {0x46542000}, {0x46544000}, {0x46546000},
+ {0x46548000}, {0x4654a000}, {0x4654c000}, {0x4654e000},
+ {0x46550000}, {0x46552000}, {0x46554000}, {0x46556000},
+ {0x46558000}, {0x4655a000}, {0x4655c000}, {0x4655e000},
+ {0x46560000}, {0x46562000}, {0x46564000}, {0x46566000},
+ {0x46568000}, {0x4656a000}, {0x4656c000}, {0x4656e000},
+ {0x46570000}, {0x46572000}, {0x46574000}, {0x46576000},
+ {0x46578000}, {0x4657a000}, {0x4657c000}, {0x4657e000},
+ {0x46580000}, {0x46582000}, {0x46584000}, {0x46586000},
+ {0x46588000}, {0x4658a000}, {0x4658c000}, {0x4658e000},
+ {0x46590000}, {0x46592000}, {0x46594000}, {0x46596000},
+ {0x46598000}, {0x4659a000}, {0x4659c000}, {0x4659e000},
+ {0x465a0000}, {0x465a2000}, {0x465a4000}, {0x465a6000},
+ {0x465a8000}, {0x465aa000}, {0x465ac000}, {0x465ae000},
+ {0x465b0000}, {0x465b2000}, {0x465b4000}, {0x465b6000},
+ {0x465b8000}, {0x465ba000}, {0x465bc000}, {0x465be000},
+ {0x465c0000}, {0x465c2000}, {0x465c4000}, {0x465c6000},
+ {0x465c8000}, {0x465ca000}, {0x465cc000}, {0x465ce000},
+ {0x465d0000}, {0x465d2000}, {0x465d4000}, {0x465d6000},
+ {0x465d8000}, {0x465da000}, {0x465dc000}, {0x465de000},
+ {0x465e0000}, {0x465e2000}, {0x465e4000}, {0x465e6000},
+ {0x465e8000}, {0x465ea000}, {0x465ec000}, {0x465ee000},
+ {0x465f0000}, {0x465f2000}, {0x465f4000}, {0x465f6000},
+ {0x465f8000}, {0x465fa000}, {0x465fc000}, {0x465fe000},
+ {0x46600000}, {0x46602000}, {0x46604000}, {0x46606000},
+ {0x46608000}, {0x4660a000}, {0x4660c000}, {0x4660e000},
+ {0x46610000}, {0x46612000}, {0x46614000}, {0x46616000},
+ {0x46618000}, {0x4661a000}, {0x4661c000}, {0x4661e000},
+ {0x46620000}, {0x46622000}, {0x46624000}, {0x46626000},
+ {0x46628000}, {0x4662a000}, {0x4662c000}, {0x4662e000},
+ {0x46630000}, {0x46632000}, {0x46634000}, {0x46636000},
+ {0x46638000}, {0x4663a000}, {0x4663c000}, {0x4663e000},
+ {0x46640000}, {0x46642000}, {0x46644000}, {0x46646000},
+ {0x46648000}, {0x4664a000}, {0x4664c000}, {0x4664e000},
+ {0x46650000}, {0x46652000}, {0x46654000}, {0x46656000},
+ {0x46658000}, {0x4665a000}, {0x4665c000}, {0x4665e000},
+ {0x46660000}, {0x46662000}, {0x46664000}, {0x46666000},
+ {0x46668000}, {0x4666a000}, {0x4666c000}, {0x4666e000},
+ {0x46670000}, {0x46672000}, {0x46674000}, {0x46676000},
+ {0x46678000}, {0x4667a000}, {0x4667c000}, {0x4667e000},
+ {0x46680000}, {0x46682000}, {0x46684000}, {0x46686000},
+ {0x46688000}, {0x4668a000}, {0x4668c000}, {0x4668e000},
+ {0x46690000}, {0x46692000}, {0x46694000}, {0x46696000},
+ {0x46698000}, {0x4669a000}, {0x4669c000}, {0x4669e000},
+ {0x466a0000}, {0x466a2000}, {0x466a4000}, {0x466a6000},
+ {0x466a8000}, {0x466aa000}, {0x466ac000}, {0x466ae000},
+ {0x466b0000}, {0x466b2000}, {0x466b4000}, {0x466b6000},
+ {0x466b8000}, {0x466ba000}, {0x466bc000}, {0x466be000},
+ {0x466c0000}, {0x466c2000}, {0x466c4000}, {0x466c6000},
+ {0x466c8000}, {0x466ca000}, {0x466cc000}, {0x466ce000},
+ {0x466d0000}, {0x466d2000}, {0x466d4000}, {0x466d6000},
+ {0x466d8000}, {0x466da000}, {0x466dc000}, {0x466de000},
+ {0x466e0000}, {0x466e2000}, {0x466e4000}, {0x466e6000},
+ {0x466e8000}, {0x466ea000}, {0x466ec000}, {0x466ee000},
+ {0x466f0000}, {0x466f2000}, {0x466f4000}, {0x466f6000},
+ {0x466f8000}, {0x466fa000}, {0x466fc000}, {0x466fe000},
+ {0x46700000}, {0x46702000}, {0x46704000}, {0x46706000},
+ {0x46708000}, {0x4670a000}, {0x4670c000}, {0x4670e000},
+ {0x46710000}, {0x46712000}, {0x46714000}, {0x46716000},
+ {0x46718000}, {0x4671a000}, {0x4671c000}, {0x4671e000},
+ {0x46720000}, {0x46722000}, {0x46724000}, {0x46726000},
+ {0x46728000}, {0x4672a000}, {0x4672c000}, {0x4672e000},
+ {0x46730000}, {0x46732000}, {0x46734000}, {0x46736000},
+ {0x46738000}, {0x4673a000}, {0x4673c000}, {0x4673e000},
+ {0x46740000}, {0x46742000}, {0x46744000}, {0x46746000},
+ {0x46748000}, {0x4674a000}, {0x4674c000}, {0x4674e000},
+ {0x46750000}, {0x46752000}, {0x46754000}, {0x46756000},
+ {0x46758000}, {0x4675a000}, {0x4675c000}, {0x4675e000},
+ {0x46760000}, {0x46762000}, {0x46764000}, {0x46766000},
+ {0x46768000}, {0x4676a000}, {0x4676c000}, {0x4676e000},
+ {0x46770000}, {0x46772000}, {0x46774000}, {0x46776000},
+ {0x46778000}, {0x4677a000}, {0x4677c000}, {0x4677e000},
+ {0x46780000}, {0x46782000}, {0x46784000}, {0x46786000},
+ {0x46788000}, {0x4678a000}, {0x4678c000}, {0x4678e000},
+ {0x46790000}, {0x46792000}, {0x46794000}, {0x46796000},
+ {0x46798000}, {0x4679a000}, {0x4679c000}, {0x4679e000},
+ {0x467a0000}, {0x467a2000}, {0x467a4000}, {0x467a6000},
+ {0x467a8000}, {0x467aa000}, {0x467ac000}, {0x467ae000},
+ {0x467b0000}, {0x467b2000}, {0x467b4000}, {0x467b6000},
+ {0x467b8000}, {0x467ba000}, {0x467bc000}, {0x467be000},
+ {0x467c0000}, {0x467c2000}, {0x467c4000}, {0x467c6000},
+ {0x467c8000}, {0x467ca000}, {0x467cc000}, {0x467ce000},
+ {0x467d0000}, {0x467d2000}, {0x467d4000}, {0x467d6000},
+ {0x467d8000}, {0x467da000}, {0x467dc000}, {0x467de000},
+ {0x467e0000}, {0x467e2000}, {0x467e4000}, {0x467e6000},
+ {0x467e8000}, {0x467ea000}, {0x467ec000}, {0x467ee000},
+ {0x467f0000}, {0x467f2000}, {0x467f4000}, {0x467f6000},
+ {0x467f8000}, {0x467fa000}, {0x467fc000}, {0x467fe000},
+ {0x46800000}, {0x46802000}, {0x46804000}, {0x46806000},
+ {0x46808000}, {0x4680a000}, {0x4680c000}, {0x4680e000},
+ {0x46810000}, {0x46812000}, {0x46814000}, {0x46816000},
+ {0x46818000}, {0x4681a000}, {0x4681c000}, {0x4681e000},
+ {0x46820000}, {0x46822000}, {0x46824000}, {0x46826000},
+ {0x46828000}, {0x4682a000}, {0x4682c000}, {0x4682e000},
+ {0x46830000}, {0x46832000}, {0x46834000}, {0x46836000},
+ {0x46838000}, {0x4683a000}, {0x4683c000}, {0x4683e000},
+ {0x46840000}, {0x46842000}, {0x46844000}, {0x46846000},
+ {0x46848000}, {0x4684a000}, {0x4684c000}, {0x4684e000},
+ {0x46850000}, {0x46852000}, {0x46854000}, {0x46856000},
+ {0x46858000}, {0x4685a000}, {0x4685c000}, {0x4685e000},
+ {0x46860000}, {0x46862000}, {0x46864000}, {0x46866000},
+ {0x46868000}, {0x4686a000}, {0x4686c000}, {0x4686e000},
+ {0x46870000}, {0x46872000}, {0x46874000}, {0x46876000},
+ {0x46878000}, {0x4687a000}, {0x4687c000}, {0x4687e000},
+ {0x46880000}, {0x46882000}, {0x46884000}, {0x46886000},
+ {0x46888000}, {0x4688a000}, {0x4688c000}, {0x4688e000},
+ {0x46890000}, {0x46892000}, {0x46894000}, {0x46896000},
+ {0x46898000}, {0x4689a000}, {0x4689c000}, {0x4689e000},
+ {0x468a0000}, {0x468a2000}, {0x468a4000}, {0x468a6000},
+ {0x468a8000}, {0x468aa000}, {0x468ac000}, {0x468ae000},
+ {0x468b0000}, {0x468b2000}, {0x468b4000}, {0x468b6000},
+ {0x468b8000}, {0x468ba000}, {0x468bc000}, {0x468be000},
+ {0x468c0000}, {0x468c2000}, {0x468c4000}, {0x468c6000},
+ {0x468c8000}, {0x468ca000}, {0x468cc000}, {0x468ce000},
+ {0x468d0000}, {0x468d2000}, {0x468d4000}, {0x468d6000},
+ {0x468d8000}, {0x468da000}, {0x468dc000}, {0x468de000},
+ {0x468e0000}, {0x468e2000}, {0x468e4000}, {0x468e6000},
+ {0x468e8000}, {0x468ea000}, {0x468ec000}, {0x468ee000},
+ {0x468f0000}, {0x468f2000}, {0x468f4000}, {0x468f6000},
+ {0x468f8000}, {0x468fa000}, {0x468fc000}, {0x468fe000},
+ {0x46900000}, {0x46902000}, {0x46904000}, {0x46906000},
+ {0x46908000}, {0x4690a000}, {0x4690c000}, {0x4690e000},
+ {0x46910000}, {0x46912000}, {0x46914000}, {0x46916000},
+ {0x46918000}, {0x4691a000}, {0x4691c000}, {0x4691e000},
+ {0x46920000}, {0x46922000}, {0x46924000}, {0x46926000},
+ {0x46928000}, {0x4692a000}, {0x4692c000}, {0x4692e000},
+ {0x46930000}, {0x46932000}, {0x46934000}, {0x46936000},
+ {0x46938000}, {0x4693a000}, {0x4693c000}, {0x4693e000},
+ {0x46940000}, {0x46942000}, {0x46944000}, {0x46946000},
+ {0x46948000}, {0x4694a000}, {0x4694c000}, {0x4694e000},
+ {0x46950000}, {0x46952000}, {0x46954000}, {0x46956000},
+ {0x46958000}, {0x4695a000}, {0x4695c000}, {0x4695e000},
+ {0x46960000}, {0x46962000}, {0x46964000}, {0x46966000},
+ {0x46968000}, {0x4696a000}, {0x4696c000}, {0x4696e000},
+ {0x46970000}, {0x46972000}, {0x46974000}, {0x46976000},
+ {0x46978000}, {0x4697a000}, {0x4697c000}, {0x4697e000},
+ {0x46980000}, {0x46982000}, {0x46984000}, {0x46986000},
+ {0x46988000}, {0x4698a000}, {0x4698c000}, {0x4698e000},
+ {0x46990000}, {0x46992000}, {0x46994000}, {0x46996000},
+ {0x46998000}, {0x4699a000}, {0x4699c000}, {0x4699e000},
+ {0x469a0000}, {0x469a2000}, {0x469a4000}, {0x469a6000},
+ {0x469a8000}, {0x469aa000}, {0x469ac000}, {0x469ae000},
+ {0x469b0000}, {0x469b2000}, {0x469b4000}, {0x469b6000},
+ {0x469b8000}, {0x469ba000}, {0x469bc000}, {0x469be000},
+ {0x469c0000}, {0x469c2000}, {0x469c4000}, {0x469c6000},
+ {0x469c8000}, {0x469ca000}, {0x469cc000}, {0x469ce000},
+ {0x469d0000}, {0x469d2000}, {0x469d4000}, {0x469d6000},
+ {0x469d8000}, {0x469da000}, {0x469dc000}, {0x469de000},
+ {0x469e0000}, {0x469e2000}, {0x469e4000}, {0x469e6000},
+ {0x469e8000}, {0x469ea000}, {0x469ec000}, {0x469ee000},
+ {0x469f0000}, {0x469f2000}, {0x469f4000}, {0x469f6000},
+ {0x469f8000}, {0x469fa000}, {0x469fc000}, {0x469fe000},
+ {0x46a00000}, {0x46a02000}, {0x46a04000}, {0x46a06000},
+ {0x46a08000}, {0x46a0a000}, {0x46a0c000}, {0x46a0e000},
+ {0x46a10000}, {0x46a12000}, {0x46a14000}, {0x46a16000},
+ {0x46a18000}, {0x46a1a000}, {0x46a1c000}, {0x46a1e000},
+ {0x46a20000}, {0x46a22000}, {0x46a24000}, {0x46a26000},
+ {0x46a28000}, {0x46a2a000}, {0x46a2c000}, {0x46a2e000},
+ {0x46a30000}, {0x46a32000}, {0x46a34000}, {0x46a36000},
+ {0x46a38000}, {0x46a3a000}, {0x46a3c000}, {0x46a3e000},
+ {0x46a40000}, {0x46a42000}, {0x46a44000}, {0x46a46000},
+ {0x46a48000}, {0x46a4a000}, {0x46a4c000}, {0x46a4e000},
+ {0x46a50000}, {0x46a52000}, {0x46a54000}, {0x46a56000},
+ {0x46a58000}, {0x46a5a000}, {0x46a5c000}, {0x46a5e000},
+ {0x46a60000}, {0x46a62000}, {0x46a64000}, {0x46a66000},
+ {0x46a68000}, {0x46a6a000}, {0x46a6c000}, {0x46a6e000},
+ {0x46a70000}, {0x46a72000}, {0x46a74000}, {0x46a76000},
+ {0x46a78000}, {0x46a7a000}, {0x46a7c000}, {0x46a7e000},
+ {0x46a80000}, {0x46a82000}, {0x46a84000}, {0x46a86000},
+ {0x46a88000}, {0x46a8a000}, {0x46a8c000}, {0x46a8e000},
+ {0x46a90000}, {0x46a92000}, {0x46a94000}, {0x46a96000},
+ {0x46a98000}, {0x46a9a000}, {0x46a9c000}, {0x46a9e000},
+ {0x46aa0000}, {0x46aa2000}, {0x46aa4000}, {0x46aa6000},
+ {0x46aa8000}, {0x46aaa000}, {0x46aac000}, {0x46aae000},
+ {0x46ab0000}, {0x46ab2000}, {0x46ab4000}, {0x46ab6000},
+ {0x46ab8000}, {0x46aba000}, {0x46abc000}, {0x46abe000},
+ {0x46ac0000}, {0x46ac2000}, {0x46ac4000}, {0x46ac6000},
+ {0x46ac8000}, {0x46aca000}, {0x46acc000}, {0x46ace000},
+ {0x46ad0000}, {0x46ad2000}, {0x46ad4000}, {0x46ad6000},
+ {0x46ad8000}, {0x46ada000}, {0x46adc000}, {0x46ade000},
+ {0x46ae0000}, {0x46ae2000}, {0x46ae4000}, {0x46ae6000},
+ {0x46ae8000}, {0x46aea000}, {0x46aec000}, {0x46aee000},
+ {0x46af0000}, {0x46af2000}, {0x46af4000}, {0x46af6000},
+ {0x46af8000}, {0x46afa000}, {0x46afc000}, {0x46afe000},
+ {0x46b00000}, {0x46b02000}, {0x46b04000}, {0x46b06000},
+ {0x46b08000}, {0x46b0a000}, {0x46b0c000}, {0x46b0e000},
+ {0x46b10000}, {0x46b12000}, {0x46b14000}, {0x46b16000},
+ {0x46b18000}, {0x46b1a000}, {0x46b1c000}, {0x46b1e000},
+ {0x46b20000}, {0x46b22000}, {0x46b24000}, {0x46b26000},
+ {0x46b28000}, {0x46b2a000}, {0x46b2c000}, {0x46b2e000},
+ {0x46b30000}, {0x46b32000}, {0x46b34000}, {0x46b36000},
+ {0x46b38000}, {0x46b3a000}, {0x46b3c000}, {0x46b3e000},
+ {0x46b40000}, {0x46b42000}, {0x46b44000}, {0x46b46000},
+ {0x46b48000}, {0x46b4a000}, {0x46b4c000}, {0x46b4e000},
+ {0x46b50000}, {0x46b52000}, {0x46b54000}, {0x46b56000},
+ {0x46b58000}, {0x46b5a000}, {0x46b5c000}, {0x46b5e000},
+ {0x46b60000}, {0x46b62000}, {0x46b64000}, {0x46b66000},
+ {0x46b68000}, {0x46b6a000}, {0x46b6c000}, {0x46b6e000},
+ {0x46b70000}, {0x46b72000}, {0x46b74000}, {0x46b76000},
+ {0x46b78000}, {0x46b7a000}, {0x46b7c000}, {0x46b7e000},
+ {0x46b80000}, {0x46b82000}, {0x46b84000}, {0x46b86000},
+ {0x46b88000}, {0x46b8a000}, {0x46b8c000}, {0x46b8e000},
+ {0x46b90000}, {0x46b92000}, {0x46b94000}, {0x46b96000},
+ {0x46b98000}, {0x46b9a000}, {0x46b9c000}, {0x46b9e000},
+ {0x46ba0000}, {0x46ba2000}, {0x46ba4000}, {0x46ba6000},
+ {0x46ba8000}, {0x46baa000}, {0x46bac000}, {0x46bae000},
+ {0x46bb0000}, {0x46bb2000}, {0x46bb4000}, {0x46bb6000},
+ {0x46bb8000}, {0x46bba000}, {0x46bbc000}, {0x46bbe000},
+ {0x46bc0000}, {0x46bc2000}, {0x46bc4000}, {0x46bc6000},
+ {0x46bc8000}, {0x46bca000}, {0x46bcc000}, {0x46bce000},
+ {0x46bd0000}, {0x46bd2000}, {0x46bd4000}, {0x46bd6000},
+ {0x46bd8000}, {0x46bda000}, {0x46bdc000}, {0x46bde000},
+ {0x46be0000}, {0x46be2000}, {0x46be4000}, {0x46be6000},
+ {0x46be8000}, {0x46bea000}, {0x46bec000}, {0x46bee000},
+ {0x46bf0000}, {0x46bf2000}, {0x46bf4000}, {0x46bf6000},
+ {0x46bf8000}, {0x46bfa000}, {0x46bfc000}, {0x46bfe000},
+ {0x46c00000}, {0x46c02000}, {0x46c04000}, {0x46c06000},
+ {0x46c08000}, {0x46c0a000}, {0x46c0c000}, {0x46c0e000},
+ {0x46c10000}, {0x46c12000}, {0x46c14000}, {0x46c16000},
+ {0x46c18000}, {0x46c1a000}, {0x46c1c000}, {0x46c1e000},
+ {0x46c20000}, {0x46c22000}, {0x46c24000}, {0x46c26000},
+ {0x46c28000}, {0x46c2a000}, {0x46c2c000}, {0x46c2e000},
+ {0x46c30000}, {0x46c32000}, {0x46c34000}, {0x46c36000},
+ {0x46c38000}, {0x46c3a000}, {0x46c3c000}, {0x46c3e000},
+ {0x46c40000}, {0x46c42000}, {0x46c44000}, {0x46c46000},
+ {0x46c48000}, {0x46c4a000}, {0x46c4c000}, {0x46c4e000},
+ {0x46c50000}, {0x46c52000}, {0x46c54000}, {0x46c56000},
+ {0x46c58000}, {0x46c5a000}, {0x46c5c000}, {0x46c5e000},
+ {0x46c60000}, {0x46c62000}, {0x46c64000}, {0x46c66000},
+ {0x46c68000}, {0x46c6a000}, {0x46c6c000}, {0x46c6e000},
+ {0x46c70000}, {0x46c72000}, {0x46c74000}, {0x46c76000},
+ {0x46c78000}, {0x46c7a000}, {0x46c7c000}, {0x46c7e000},
+ {0x46c80000}, {0x46c82000}, {0x46c84000}, {0x46c86000},
+ {0x46c88000}, {0x46c8a000}, {0x46c8c000}, {0x46c8e000},
+ {0x46c90000}, {0x46c92000}, {0x46c94000}, {0x46c96000},
+ {0x46c98000}, {0x46c9a000}, {0x46c9c000}, {0x46c9e000},
+ {0x46ca0000}, {0x46ca2000}, {0x46ca4000}, {0x46ca6000},
+ {0x46ca8000}, {0x46caa000}, {0x46cac000}, {0x46cae000},
+ {0x46cb0000}, {0x46cb2000}, {0x46cb4000}, {0x46cb6000},
+ {0x46cb8000}, {0x46cba000}, {0x46cbc000}, {0x46cbe000},
+ {0x46cc0000}, {0x46cc2000}, {0x46cc4000}, {0x46cc6000},
+ {0x46cc8000}, {0x46cca000}, {0x46ccc000}, {0x46cce000},
+ {0x46cd0000}, {0x46cd2000}, {0x46cd4000}, {0x46cd6000},
+ {0x46cd8000}, {0x46cda000}, {0x46cdc000}, {0x46cde000},
+ {0x46ce0000}, {0x46ce2000}, {0x46ce4000}, {0x46ce6000},
+ {0x46ce8000}, {0x46cea000}, {0x46cec000}, {0x46cee000},
+ {0x46cf0000}, {0x46cf2000}, {0x46cf4000}, {0x46cf6000},
+ {0x46cf8000}, {0x46cfa000}, {0x46cfc000}, {0x46cfe000},
+ {0x46d00000}, {0x46d02000}, {0x46d04000}, {0x46d06000},
+ {0x46d08000}, {0x46d0a000}, {0x46d0c000}, {0x46d0e000},
+ {0x46d10000}, {0x46d12000}, {0x46d14000}, {0x46d16000},
+ {0x46d18000}, {0x46d1a000}, {0x46d1c000}, {0x46d1e000},
+ {0x46d20000}, {0x46d22000}, {0x46d24000}, {0x46d26000},
+ {0x46d28000}, {0x46d2a000}, {0x46d2c000}, {0x46d2e000},
+ {0x46d30000}, {0x46d32000}, {0x46d34000}, {0x46d36000},
+ {0x46d38000}, {0x46d3a000}, {0x46d3c000}, {0x46d3e000},
+ {0x46d40000}, {0x46d42000}, {0x46d44000}, {0x46d46000},
+ {0x46d48000}, {0x46d4a000}, {0x46d4c000}, {0x46d4e000},
+ {0x46d50000}, {0x46d52000}, {0x46d54000}, {0x46d56000},
+ {0x46d58000}, {0x46d5a000}, {0x46d5c000}, {0x46d5e000},
+ {0x46d60000}, {0x46d62000}, {0x46d64000}, {0x46d66000},
+ {0x46d68000}, {0x46d6a000}, {0x46d6c000}, {0x46d6e000},
+ {0x46d70000}, {0x46d72000}, {0x46d74000}, {0x46d76000},
+ {0x46d78000}, {0x46d7a000}, {0x46d7c000}, {0x46d7e000},
+ {0x46d80000}, {0x46d82000}, {0x46d84000}, {0x46d86000},
+ {0x46d88000}, {0x46d8a000}, {0x46d8c000}, {0x46d8e000},
+ {0x46d90000}, {0x46d92000}, {0x46d94000}, {0x46d96000},
+ {0x46d98000}, {0x46d9a000}, {0x46d9c000}, {0x46d9e000},
+ {0x46da0000}, {0x46da2000}, {0x46da4000}, {0x46da6000},
+ {0x46da8000}, {0x46daa000}, {0x46dac000}, {0x46dae000},
+ {0x46db0000}, {0x46db2000}, {0x46db4000}, {0x46db6000},
+ {0x46db8000}, {0x46dba000}, {0x46dbc000}, {0x46dbe000},
+ {0x46dc0000}, {0x46dc2000}, {0x46dc4000}, {0x46dc6000},
+ {0x46dc8000}, {0x46dca000}, {0x46dcc000}, {0x46dce000},
+ {0x46dd0000}, {0x46dd2000}, {0x46dd4000}, {0x46dd6000},
+ {0x46dd8000}, {0x46dda000}, {0x46ddc000}, {0x46dde000},
+ {0x46de0000}, {0x46de2000}, {0x46de4000}, {0x46de6000},
+ {0x46de8000}, {0x46dea000}, {0x46dec000}, {0x46dee000},
+ {0x46df0000}, {0x46df2000}, {0x46df4000}, {0x46df6000},
+ {0x46df8000}, {0x46dfa000}, {0x46dfc000}, {0x46dfe000},
+ {0x46e00000}, {0x46e02000}, {0x46e04000}, {0x46e06000},
+ {0x46e08000}, {0x46e0a000}, {0x46e0c000}, {0x46e0e000},
+ {0x46e10000}, {0x46e12000}, {0x46e14000}, {0x46e16000},
+ {0x46e18000}, {0x46e1a000}, {0x46e1c000}, {0x46e1e000},
+ {0x46e20000}, {0x46e22000}, {0x46e24000}, {0x46e26000},
+ {0x46e28000}, {0x46e2a000}, {0x46e2c000}, {0x46e2e000},
+ {0x46e30000}, {0x46e32000}, {0x46e34000}, {0x46e36000},
+ {0x46e38000}, {0x46e3a000}, {0x46e3c000}, {0x46e3e000},
+ {0x46e40000}, {0x46e42000}, {0x46e44000}, {0x46e46000},
+ {0x46e48000}, {0x46e4a000}, {0x46e4c000}, {0x46e4e000},
+ {0x46e50000}, {0x46e52000}, {0x46e54000}, {0x46e56000},
+ {0x46e58000}, {0x46e5a000}, {0x46e5c000}, {0x46e5e000},
+ {0x46e60000}, {0x46e62000}, {0x46e64000}, {0x46e66000},
+ {0x46e68000}, {0x46e6a000}, {0x46e6c000}, {0x46e6e000},
+ {0x46e70000}, {0x46e72000}, {0x46e74000}, {0x46e76000},
+ {0x46e78000}, {0x46e7a000}, {0x46e7c000}, {0x46e7e000},
+ {0x46e80000}, {0x46e82000}, {0x46e84000}, {0x46e86000},
+ {0x46e88000}, {0x46e8a000}, {0x46e8c000}, {0x46e8e000},
+ {0x46e90000}, {0x46e92000}, {0x46e94000}, {0x46e96000},
+ {0x46e98000}, {0x46e9a000}, {0x46e9c000}, {0x46e9e000},
+ {0x46ea0000}, {0x46ea2000}, {0x46ea4000}, {0x46ea6000},
+ {0x46ea8000}, {0x46eaa000}, {0x46eac000}, {0x46eae000},
+ {0x46eb0000}, {0x46eb2000}, {0x46eb4000}, {0x46eb6000},
+ {0x46eb8000}, {0x46eba000}, {0x46ebc000}, {0x46ebe000},
+ {0x46ec0000}, {0x46ec2000}, {0x46ec4000}, {0x46ec6000},
+ {0x46ec8000}, {0x46eca000}, {0x46ecc000}, {0x46ece000},
+ {0x46ed0000}, {0x46ed2000}, {0x46ed4000}, {0x46ed6000},
+ {0x46ed8000}, {0x46eda000}, {0x46edc000}, {0x46ede000},
+ {0x46ee0000}, {0x46ee2000}, {0x46ee4000}, {0x46ee6000},
+ {0x46ee8000}, {0x46eea000}, {0x46eec000}, {0x46eee000},
+ {0x46ef0000}, {0x46ef2000}, {0x46ef4000}, {0x46ef6000},
+ {0x46ef8000}, {0x46efa000}, {0x46efc000}, {0x46efe000},
+ {0x46f00000}, {0x46f02000}, {0x46f04000}, {0x46f06000},
+ {0x46f08000}, {0x46f0a000}, {0x46f0c000}, {0x46f0e000},
+ {0x46f10000}, {0x46f12000}, {0x46f14000}, {0x46f16000},
+ {0x46f18000}, {0x46f1a000}, {0x46f1c000}, {0x46f1e000},
+ {0x46f20000}, {0x46f22000}, {0x46f24000}, {0x46f26000},
+ {0x46f28000}, {0x46f2a000}, {0x46f2c000}, {0x46f2e000},
+ {0x46f30000}, {0x46f32000}, {0x46f34000}, {0x46f36000},
+ {0x46f38000}, {0x46f3a000}, {0x46f3c000}, {0x46f3e000},
+ {0x46f40000}, {0x46f42000}, {0x46f44000}, {0x46f46000},
+ {0x46f48000}, {0x46f4a000}, {0x46f4c000}, {0x46f4e000},
+ {0x46f50000}, {0x46f52000}, {0x46f54000}, {0x46f56000},
+ {0x46f58000}, {0x46f5a000}, {0x46f5c000}, {0x46f5e000},
+ {0x46f60000}, {0x46f62000}, {0x46f64000}, {0x46f66000},
+ {0x46f68000}, {0x46f6a000}, {0x46f6c000}, {0x46f6e000},
+ {0x46f70000}, {0x46f72000}, {0x46f74000}, {0x46f76000},
+ {0x46f78000}, {0x46f7a000}, {0x46f7c000}, {0x46f7e000},
+ {0x46f80000}, {0x46f82000}, {0x46f84000}, {0x46f86000},
+ {0x46f88000}, {0x46f8a000}, {0x46f8c000}, {0x46f8e000},
+ {0x46f90000}, {0x46f92000}, {0x46f94000}, {0x46f96000},
+ {0x46f98000}, {0x46f9a000}, {0x46f9c000}, {0x46f9e000},
+ {0x46fa0000}, {0x46fa2000}, {0x46fa4000}, {0x46fa6000},
+ {0x46fa8000}, {0x46faa000}, {0x46fac000}, {0x46fae000},
+ {0x46fb0000}, {0x46fb2000}, {0x46fb4000}, {0x46fb6000},
+ {0x46fb8000}, {0x46fba000}, {0x46fbc000}, {0x46fbe000},
+ {0x46fc0000}, {0x46fc2000}, {0x46fc4000}, {0x46fc6000},
+ {0x46fc8000}, {0x46fca000}, {0x46fcc000}, {0x46fce000},
+ {0x46fd0000}, {0x46fd2000}, {0x46fd4000}, {0x46fd6000},
+ {0x46fd8000}, {0x46fda000}, {0x46fdc000}, {0x46fde000},
+ {0x46fe0000}, {0x46fe2000}, {0x46fe4000}, {0x46fe6000},
+ {0x46fe8000}, {0x46fea000}, {0x46fec000}, {0x46fee000},
+ {0x46ff0000}, {0x46ff2000}, {0x46ff4000}, {0x46ff6000},
+ {0x46ff8000}, {0x46ffa000}, {0x46ffc000}, {0x46ffe000},
+ {0x47000000}, {0x47002000}, {0x47004000}, {0x47006000},
+ {0x47008000}, {0x4700a000}, {0x4700c000}, {0x4700e000},
+ {0x47010000}, {0x47012000}, {0x47014000}, {0x47016000},
+ {0x47018000}, {0x4701a000}, {0x4701c000}, {0x4701e000},
+ {0x47020000}, {0x47022000}, {0x47024000}, {0x47026000},
+ {0x47028000}, {0x4702a000}, {0x4702c000}, {0x4702e000},
+ {0x47030000}, {0x47032000}, {0x47034000}, {0x47036000},
+ {0x47038000}, {0x4703a000}, {0x4703c000}, {0x4703e000},
+ {0x47040000}, {0x47042000}, {0x47044000}, {0x47046000},
+ {0x47048000}, {0x4704a000}, {0x4704c000}, {0x4704e000},
+ {0x47050000}, {0x47052000}, {0x47054000}, {0x47056000},
+ {0x47058000}, {0x4705a000}, {0x4705c000}, {0x4705e000},
+ {0x47060000}, {0x47062000}, {0x47064000}, {0x47066000},
+ {0x47068000}, {0x4706a000}, {0x4706c000}, {0x4706e000},
+ {0x47070000}, {0x47072000}, {0x47074000}, {0x47076000},
+ {0x47078000}, {0x4707a000}, {0x4707c000}, {0x4707e000},
+ {0x47080000}, {0x47082000}, {0x47084000}, {0x47086000},
+ {0x47088000}, {0x4708a000}, {0x4708c000}, {0x4708e000},
+ {0x47090000}, {0x47092000}, {0x47094000}, {0x47096000},
+ {0x47098000}, {0x4709a000}, {0x4709c000}, {0x4709e000},
+ {0x470a0000}, {0x470a2000}, {0x470a4000}, {0x470a6000},
+ {0x470a8000}, {0x470aa000}, {0x470ac000}, {0x470ae000},
+ {0x470b0000}, {0x470b2000}, {0x470b4000}, {0x470b6000},
+ {0x470b8000}, {0x470ba000}, {0x470bc000}, {0x470be000},
+ {0x470c0000}, {0x470c2000}, {0x470c4000}, {0x470c6000},
+ {0x470c8000}, {0x470ca000}, {0x470cc000}, {0x470ce000},
+ {0x470d0000}, {0x470d2000}, {0x470d4000}, {0x470d6000},
+ {0x470d8000}, {0x470da000}, {0x470dc000}, {0x470de000},
+ {0x470e0000}, {0x470e2000}, {0x470e4000}, {0x470e6000},
+ {0x470e8000}, {0x470ea000}, {0x470ec000}, {0x470ee000},
+ {0x470f0000}, {0x470f2000}, {0x470f4000}, {0x470f6000},
+ {0x470f8000}, {0x470fa000}, {0x470fc000}, {0x470fe000},
+ {0x47100000}, {0x47102000}, {0x47104000}, {0x47106000},
+ {0x47108000}, {0x4710a000}, {0x4710c000}, {0x4710e000},
+ {0x47110000}, {0x47112000}, {0x47114000}, {0x47116000},
+ {0x47118000}, {0x4711a000}, {0x4711c000}, {0x4711e000},
+ {0x47120000}, {0x47122000}, {0x47124000}, {0x47126000},
+ {0x47128000}, {0x4712a000}, {0x4712c000}, {0x4712e000},
+ {0x47130000}, {0x47132000}, {0x47134000}, {0x47136000},
+ {0x47138000}, {0x4713a000}, {0x4713c000}, {0x4713e000},
+ {0x47140000}, {0x47142000}, {0x47144000}, {0x47146000},
+ {0x47148000}, {0x4714a000}, {0x4714c000}, {0x4714e000},
+ {0x47150000}, {0x47152000}, {0x47154000}, {0x47156000},
+ {0x47158000}, {0x4715a000}, {0x4715c000}, {0x4715e000},
+ {0x47160000}, {0x47162000}, {0x47164000}, {0x47166000},
+ {0x47168000}, {0x4716a000}, {0x4716c000}, {0x4716e000},
+ {0x47170000}, {0x47172000}, {0x47174000}, {0x47176000},
+ {0x47178000}, {0x4717a000}, {0x4717c000}, {0x4717e000},
+ {0x47180000}, {0x47182000}, {0x47184000}, {0x47186000},
+ {0x47188000}, {0x4718a000}, {0x4718c000}, {0x4718e000},
+ {0x47190000}, {0x47192000}, {0x47194000}, {0x47196000},
+ {0x47198000}, {0x4719a000}, {0x4719c000}, {0x4719e000},
+ {0x471a0000}, {0x471a2000}, {0x471a4000}, {0x471a6000},
+ {0x471a8000}, {0x471aa000}, {0x471ac000}, {0x471ae000},
+ {0x471b0000}, {0x471b2000}, {0x471b4000}, {0x471b6000},
+ {0x471b8000}, {0x471ba000}, {0x471bc000}, {0x471be000},
+ {0x471c0000}, {0x471c2000}, {0x471c4000}, {0x471c6000},
+ {0x471c8000}, {0x471ca000}, {0x471cc000}, {0x471ce000},
+ {0x471d0000}, {0x471d2000}, {0x471d4000}, {0x471d6000},
+ {0x471d8000}, {0x471da000}, {0x471dc000}, {0x471de000},
+ {0x471e0000}, {0x471e2000}, {0x471e4000}, {0x471e6000},
+ {0x471e8000}, {0x471ea000}, {0x471ec000}, {0x471ee000},
+ {0x471f0000}, {0x471f2000}, {0x471f4000}, {0x471f6000},
+ {0x471f8000}, {0x471fa000}, {0x471fc000}, {0x471fe000},
+ {0x47200000}, {0x47202000}, {0x47204000}, {0x47206000},
+ {0x47208000}, {0x4720a000}, {0x4720c000}, {0x4720e000},
+ {0x47210000}, {0x47212000}, {0x47214000}, {0x47216000},
+ {0x47218000}, {0x4721a000}, {0x4721c000}, {0x4721e000},
+ {0x47220000}, {0x47222000}, {0x47224000}, {0x47226000},
+ {0x47228000}, {0x4722a000}, {0x4722c000}, {0x4722e000},
+ {0x47230000}, {0x47232000}, {0x47234000}, {0x47236000},
+ {0x47238000}, {0x4723a000}, {0x4723c000}, {0x4723e000},
+ {0x47240000}, {0x47242000}, {0x47244000}, {0x47246000},
+ {0x47248000}, {0x4724a000}, {0x4724c000}, {0x4724e000},
+ {0x47250000}, {0x47252000}, {0x47254000}, {0x47256000},
+ {0x47258000}, {0x4725a000}, {0x4725c000}, {0x4725e000},
+ {0x47260000}, {0x47262000}, {0x47264000}, {0x47266000},
+ {0x47268000}, {0x4726a000}, {0x4726c000}, {0x4726e000},
+ {0x47270000}, {0x47272000}, {0x47274000}, {0x47276000},
+ {0x47278000}, {0x4727a000}, {0x4727c000}, {0x4727e000},
+ {0x47280000}, {0x47282000}, {0x47284000}, {0x47286000},
+ {0x47288000}, {0x4728a000}, {0x4728c000}, {0x4728e000},
+ {0x47290000}, {0x47292000}, {0x47294000}, {0x47296000},
+ {0x47298000}, {0x4729a000}, {0x4729c000}, {0x4729e000},
+ {0x472a0000}, {0x472a2000}, {0x472a4000}, {0x472a6000},
+ {0x472a8000}, {0x472aa000}, {0x472ac000}, {0x472ae000},
+ {0x472b0000}, {0x472b2000}, {0x472b4000}, {0x472b6000},
+ {0x472b8000}, {0x472ba000}, {0x472bc000}, {0x472be000},
+ {0x472c0000}, {0x472c2000}, {0x472c4000}, {0x472c6000},
+ {0x472c8000}, {0x472ca000}, {0x472cc000}, {0x472ce000},
+ {0x472d0000}, {0x472d2000}, {0x472d4000}, {0x472d6000},
+ {0x472d8000}, {0x472da000}, {0x472dc000}, {0x472de000},
+ {0x472e0000}, {0x472e2000}, {0x472e4000}, {0x472e6000},
+ {0x472e8000}, {0x472ea000}, {0x472ec000}, {0x472ee000},
+ {0x472f0000}, {0x472f2000}, {0x472f4000}, {0x472f6000},
+ {0x472f8000}, {0x472fa000}, {0x472fc000}, {0x472fe000},
+ {0x47300000}, {0x47302000}, {0x47304000}, {0x47306000},
+ {0x47308000}, {0x4730a000}, {0x4730c000}, {0x4730e000},
+ {0x47310000}, {0x47312000}, {0x47314000}, {0x47316000},
+ {0x47318000}, {0x4731a000}, {0x4731c000}, {0x4731e000},
+ {0x47320000}, {0x47322000}, {0x47324000}, {0x47326000},
+ {0x47328000}, {0x4732a000}, {0x4732c000}, {0x4732e000},
+ {0x47330000}, {0x47332000}, {0x47334000}, {0x47336000},
+ {0x47338000}, {0x4733a000}, {0x4733c000}, {0x4733e000},
+ {0x47340000}, {0x47342000}, {0x47344000}, {0x47346000},
+ {0x47348000}, {0x4734a000}, {0x4734c000}, {0x4734e000},
+ {0x47350000}, {0x47352000}, {0x47354000}, {0x47356000},
+ {0x47358000}, {0x4735a000}, {0x4735c000}, {0x4735e000},
+ {0x47360000}, {0x47362000}, {0x47364000}, {0x47366000},
+ {0x47368000}, {0x4736a000}, {0x4736c000}, {0x4736e000},
+ {0x47370000}, {0x47372000}, {0x47374000}, {0x47376000},
+ {0x47378000}, {0x4737a000}, {0x4737c000}, {0x4737e000},
+ {0x47380000}, {0x47382000}, {0x47384000}, {0x47386000},
+ {0x47388000}, {0x4738a000}, {0x4738c000}, {0x4738e000},
+ {0x47390000}, {0x47392000}, {0x47394000}, {0x47396000},
+ {0x47398000}, {0x4739a000}, {0x4739c000}, {0x4739e000},
+ {0x473a0000}, {0x473a2000}, {0x473a4000}, {0x473a6000},
+ {0x473a8000}, {0x473aa000}, {0x473ac000}, {0x473ae000},
+ {0x473b0000}, {0x473b2000}, {0x473b4000}, {0x473b6000},
+ {0x473b8000}, {0x473ba000}, {0x473bc000}, {0x473be000},
+ {0x473c0000}, {0x473c2000}, {0x473c4000}, {0x473c6000},
+ {0x473c8000}, {0x473ca000}, {0x473cc000}, {0x473ce000},
+ {0x473d0000}, {0x473d2000}, {0x473d4000}, {0x473d6000},
+ {0x473d8000}, {0x473da000}, {0x473dc000}, {0x473de000},
+ {0x473e0000}, {0x473e2000}, {0x473e4000}, {0x473e6000},
+ {0x473e8000}, {0x473ea000}, {0x473ec000}, {0x473ee000},
+ {0x473f0000}, {0x473f2000}, {0x473f4000}, {0x473f6000},
+ {0x473f8000}, {0x473fa000}, {0x473fc000}, {0x473fe000},
+ {0x47400000}, {0x47402000}, {0x47404000}, {0x47406000},
+ {0x47408000}, {0x4740a000}, {0x4740c000}, {0x4740e000},
+ {0x47410000}, {0x47412000}, {0x47414000}, {0x47416000},
+ {0x47418000}, {0x4741a000}, {0x4741c000}, {0x4741e000},
+ {0x47420000}, {0x47422000}, {0x47424000}, {0x47426000},
+ {0x47428000}, {0x4742a000}, {0x4742c000}, {0x4742e000},
+ {0x47430000}, {0x47432000}, {0x47434000}, {0x47436000},
+ {0x47438000}, {0x4743a000}, {0x4743c000}, {0x4743e000},
+ {0x47440000}, {0x47442000}, {0x47444000}, {0x47446000},
+ {0x47448000}, {0x4744a000}, {0x4744c000}, {0x4744e000},
+ {0x47450000}, {0x47452000}, {0x47454000}, {0x47456000},
+ {0x47458000}, {0x4745a000}, {0x4745c000}, {0x4745e000},
+ {0x47460000}, {0x47462000}, {0x47464000}, {0x47466000},
+ {0x47468000}, {0x4746a000}, {0x4746c000}, {0x4746e000},
+ {0x47470000}, {0x47472000}, {0x47474000}, {0x47476000},
+ {0x47478000}, {0x4747a000}, {0x4747c000}, {0x4747e000},
+ {0x47480000}, {0x47482000}, {0x47484000}, {0x47486000},
+ {0x47488000}, {0x4748a000}, {0x4748c000}, {0x4748e000},
+ {0x47490000}, {0x47492000}, {0x47494000}, {0x47496000},
+ {0x47498000}, {0x4749a000}, {0x4749c000}, {0x4749e000},
+ {0x474a0000}, {0x474a2000}, {0x474a4000}, {0x474a6000},
+ {0x474a8000}, {0x474aa000}, {0x474ac000}, {0x474ae000},
+ {0x474b0000}, {0x474b2000}, {0x474b4000}, {0x474b6000},
+ {0x474b8000}, {0x474ba000}, {0x474bc000}, {0x474be000},
+ {0x474c0000}, {0x474c2000}, {0x474c4000}, {0x474c6000},
+ {0x474c8000}, {0x474ca000}, {0x474cc000}, {0x474ce000},
+ {0x474d0000}, {0x474d2000}, {0x474d4000}, {0x474d6000},
+ {0x474d8000}, {0x474da000}, {0x474dc000}, {0x474de000},
+ {0x474e0000}, {0x474e2000}, {0x474e4000}, {0x474e6000},
+ {0x474e8000}, {0x474ea000}, {0x474ec000}, {0x474ee000},
+ {0x474f0000}, {0x474f2000}, {0x474f4000}, {0x474f6000},
+ {0x474f8000}, {0x474fa000}, {0x474fc000}, {0x474fe000},
+ {0x47500000}, {0x47502000}, {0x47504000}, {0x47506000},
+ {0x47508000}, {0x4750a000}, {0x4750c000}, {0x4750e000},
+ {0x47510000}, {0x47512000}, {0x47514000}, {0x47516000},
+ {0x47518000}, {0x4751a000}, {0x4751c000}, {0x4751e000},
+ {0x47520000}, {0x47522000}, {0x47524000}, {0x47526000},
+ {0x47528000}, {0x4752a000}, {0x4752c000}, {0x4752e000},
+ {0x47530000}, {0x47532000}, {0x47534000}, {0x47536000},
+ {0x47538000}, {0x4753a000}, {0x4753c000}, {0x4753e000},
+ {0x47540000}, {0x47542000}, {0x47544000}, {0x47546000},
+ {0x47548000}, {0x4754a000}, {0x4754c000}, {0x4754e000},
+ {0x47550000}, {0x47552000}, {0x47554000}, {0x47556000},
+ {0x47558000}, {0x4755a000}, {0x4755c000}, {0x4755e000},
+ {0x47560000}, {0x47562000}, {0x47564000}, {0x47566000},
+ {0x47568000}, {0x4756a000}, {0x4756c000}, {0x4756e000},
+ {0x47570000}, {0x47572000}, {0x47574000}, {0x47576000},
+ {0x47578000}, {0x4757a000}, {0x4757c000}, {0x4757e000},
+ {0x47580000}, {0x47582000}, {0x47584000}, {0x47586000},
+ {0x47588000}, {0x4758a000}, {0x4758c000}, {0x4758e000},
+ {0x47590000}, {0x47592000}, {0x47594000}, {0x47596000},
+ {0x47598000}, {0x4759a000}, {0x4759c000}, {0x4759e000},
+ {0x475a0000}, {0x475a2000}, {0x475a4000}, {0x475a6000},
+ {0x475a8000}, {0x475aa000}, {0x475ac000}, {0x475ae000},
+ {0x475b0000}, {0x475b2000}, {0x475b4000}, {0x475b6000},
+ {0x475b8000}, {0x475ba000}, {0x475bc000}, {0x475be000},
+ {0x475c0000}, {0x475c2000}, {0x475c4000}, {0x475c6000},
+ {0x475c8000}, {0x475ca000}, {0x475cc000}, {0x475ce000},
+ {0x475d0000}, {0x475d2000}, {0x475d4000}, {0x475d6000},
+ {0x475d8000}, {0x475da000}, {0x475dc000}, {0x475de000},
+ {0x475e0000}, {0x475e2000}, {0x475e4000}, {0x475e6000},
+ {0x475e8000}, {0x475ea000}, {0x475ec000}, {0x475ee000},
+ {0x475f0000}, {0x475f2000}, {0x475f4000}, {0x475f6000},
+ {0x475f8000}, {0x475fa000}, {0x475fc000}, {0x475fe000},
+ {0x47600000}, {0x47602000}, {0x47604000}, {0x47606000},
+ {0x47608000}, {0x4760a000}, {0x4760c000}, {0x4760e000},
+ {0x47610000}, {0x47612000}, {0x47614000}, {0x47616000},
+ {0x47618000}, {0x4761a000}, {0x4761c000}, {0x4761e000},
+ {0x47620000}, {0x47622000}, {0x47624000}, {0x47626000},
+ {0x47628000}, {0x4762a000}, {0x4762c000}, {0x4762e000},
+ {0x47630000}, {0x47632000}, {0x47634000}, {0x47636000},
+ {0x47638000}, {0x4763a000}, {0x4763c000}, {0x4763e000},
+ {0x47640000}, {0x47642000}, {0x47644000}, {0x47646000},
+ {0x47648000}, {0x4764a000}, {0x4764c000}, {0x4764e000},
+ {0x47650000}, {0x47652000}, {0x47654000}, {0x47656000},
+ {0x47658000}, {0x4765a000}, {0x4765c000}, {0x4765e000},
+ {0x47660000}, {0x47662000}, {0x47664000}, {0x47666000},
+ {0x47668000}, {0x4766a000}, {0x4766c000}, {0x4766e000},
+ {0x47670000}, {0x47672000}, {0x47674000}, {0x47676000},
+ {0x47678000}, {0x4767a000}, {0x4767c000}, {0x4767e000},
+ {0x47680000}, {0x47682000}, {0x47684000}, {0x47686000},
+ {0x47688000}, {0x4768a000}, {0x4768c000}, {0x4768e000},
+ {0x47690000}, {0x47692000}, {0x47694000}, {0x47696000},
+ {0x47698000}, {0x4769a000}, {0x4769c000}, {0x4769e000},
+ {0x476a0000}, {0x476a2000}, {0x476a4000}, {0x476a6000},
+ {0x476a8000}, {0x476aa000}, {0x476ac000}, {0x476ae000},
+ {0x476b0000}, {0x476b2000}, {0x476b4000}, {0x476b6000},
+ {0x476b8000}, {0x476ba000}, {0x476bc000}, {0x476be000},
+ {0x476c0000}, {0x476c2000}, {0x476c4000}, {0x476c6000},
+ {0x476c8000}, {0x476ca000}, {0x476cc000}, {0x476ce000},
+ {0x476d0000}, {0x476d2000}, {0x476d4000}, {0x476d6000},
+ {0x476d8000}, {0x476da000}, {0x476dc000}, {0x476de000},
+ {0x476e0000}, {0x476e2000}, {0x476e4000}, {0x476e6000},
+ {0x476e8000}, {0x476ea000}, {0x476ec000}, {0x476ee000},
+ {0x476f0000}, {0x476f2000}, {0x476f4000}, {0x476f6000},
+ {0x476f8000}, {0x476fa000}, {0x476fc000}, {0x476fe000},
+ {0x47700000}, {0x47702000}, {0x47704000}, {0x47706000},
+ {0x47708000}, {0x4770a000}, {0x4770c000}, {0x4770e000},
+ {0x47710000}, {0x47712000}, {0x47714000}, {0x47716000},
+ {0x47718000}, {0x4771a000}, {0x4771c000}, {0x4771e000},
+ {0x47720000}, {0x47722000}, {0x47724000}, {0x47726000},
+ {0x47728000}, {0x4772a000}, {0x4772c000}, {0x4772e000},
+ {0x47730000}, {0x47732000}, {0x47734000}, {0x47736000},
+ {0x47738000}, {0x4773a000}, {0x4773c000}, {0x4773e000},
+ {0x47740000}, {0x47742000}, {0x47744000}, {0x47746000},
+ {0x47748000}, {0x4774a000}, {0x4774c000}, {0x4774e000},
+ {0x47750000}, {0x47752000}, {0x47754000}, {0x47756000},
+ {0x47758000}, {0x4775a000}, {0x4775c000}, {0x4775e000},
+ {0x47760000}, {0x47762000}, {0x47764000}, {0x47766000},
+ {0x47768000}, {0x4776a000}, {0x4776c000}, {0x4776e000},
+ {0x47770000}, {0x47772000}, {0x47774000}, {0x47776000},
+ {0x47778000}, {0x4777a000}, {0x4777c000}, {0x4777e000},
+ {0x47780000}, {0x47782000}, {0x47784000}, {0x47786000},
+ {0x47788000}, {0x4778a000}, {0x4778c000}, {0x4778e000},
+ {0x47790000}, {0x47792000}, {0x47794000}, {0x47796000},
+ {0x47798000}, {0x4779a000}, {0x4779c000}, {0x4779e000},
+ {0x477a0000}, {0x477a2000}, {0x477a4000}, {0x477a6000},
+ {0x477a8000}, {0x477aa000}, {0x477ac000}, {0x477ae000},
+ {0x477b0000}, {0x477b2000}, {0x477b4000}, {0x477b6000},
+ {0x477b8000}, {0x477ba000}, {0x477bc000}, {0x477be000},
+ {0x477c0000}, {0x477c2000}, {0x477c4000}, {0x477c6000},
+ {0x477c8000}, {0x477ca000}, {0x477cc000}, {0x477ce000},
+ {0x477d0000}, {0x477d2000}, {0x477d4000}, {0x477d6000},
+ {0x477d8000}, {0x477da000}, {0x477dc000}, {0x477de000},
+ {0x477e0000}, {0x477e2000}, {0x477e4000}, {0x477e6000},
+ {0x477e8000}, {0x477ea000}, {0x477ec000}, {0x477ee000},
+ {0x477f0000}, {0x477f2000}, {0x477f4000}, {0x477f6000},
+ {0x477f8000}, {0x477fa000}, {0x477fc000}, {0x477fe000},
+ {0x7f800000}, {0x7f802000}, {0x7f804000}, {0x7f806000},
+ {0x7f808000}, {0x7f80a000}, {0x7f80c000}, {0x7f80e000},
+ {0x7f810000}, {0x7f812000}, {0x7f814000}, {0x7f816000},
+ {0x7f818000}, {0x7f81a000}, {0x7f81c000}, {0x7f81e000},
+ {0x7f820000}, {0x7f822000}, {0x7f824000}, {0x7f826000},
+ {0x7f828000}, {0x7f82a000}, {0x7f82c000}, {0x7f82e000},
+ {0x7f830000}, {0x7f832000}, {0x7f834000}, {0x7f836000},
+ {0x7f838000}, {0x7f83a000}, {0x7f83c000}, {0x7f83e000},
+ {0x7f840000}, {0x7f842000}, {0x7f844000}, {0x7f846000},
+ {0x7f848000}, {0x7f84a000}, {0x7f84c000}, {0x7f84e000},
+ {0x7f850000}, {0x7f852000}, {0x7f854000}, {0x7f856000},
+ {0x7f858000}, {0x7f85a000}, {0x7f85c000}, {0x7f85e000},
+ {0x7f860000}, {0x7f862000}, {0x7f864000}, {0x7f866000},
+ {0x7f868000}, {0x7f86a000}, {0x7f86c000}, {0x7f86e000},
+ {0x7f870000}, {0x7f872000}, {0x7f874000}, {0x7f876000},
+ {0x7f878000}, {0x7f87a000}, {0x7f87c000}, {0x7f87e000},
+ {0x7f880000}, {0x7f882000}, {0x7f884000}, {0x7f886000},
+ {0x7f888000}, {0x7f88a000}, {0x7f88c000}, {0x7f88e000},
+ {0x7f890000}, {0x7f892000}, {0x7f894000}, {0x7f896000},
+ {0x7f898000}, {0x7f89a000}, {0x7f89c000}, {0x7f89e000},
+ {0x7f8a0000}, {0x7f8a2000}, {0x7f8a4000}, {0x7f8a6000},
+ {0x7f8a8000}, {0x7f8aa000}, {0x7f8ac000}, {0x7f8ae000},
+ {0x7f8b0000}, {0x7f8b2000}, {0x7f8b4000}, {0x7f8b6000},
+ {0x7f8b8000}, {0x7f8ba000}, {0x7f8bc000}, {0x7f8be000},
+ {0x7f8c0000}, {0x7f8c2000}, {0x7f8c4000}, {0x7f8c6000},
+ {0x7f8c8000}, {0x7f8ca000}, {0x7f8cc000}, {0x7f8ce000},
+ {0x7f8d0000}, {0x7f8d2000}, {0x7f8d4000}, {0x7f8d6000},
+ {0x7f8d8000}, {0x7f8da000}, {0x7f8dc000}, {0x7f8de000},
+ {0x7f8e0000}, {0x7f8e2000}, {0x7f8e4000}, {0x7f8e6000},
+ {0x7f8e8000}, {0x7f8ea000}, {0x7f8ec000}, {0x7f8ee000},
+ {0x7f8f0000}, {0x7f8f2000}, {0x7f8f4000}, {0x7f8f6000},
+ {0x7f8f8000}, {0x7f8fa000}, {0x7f8fc000}, {0x7f8fe000},
+ {0x7f900000}, {0x7f902000}, {0x7f904000}, {0x7f906000},
+ {0x7f908000}, {0x7f90a000}, {0x7f90c000}, {0x7f90e000},
+ {0x7f910000}, {0x7f912000}, {0x7f914000}, {0x7f916000},
+ {0x7f918000}, {0x7f91a000}, {0x7f91c000}, {0x7f91e000},
+ {0x7f920000}, {0x7f922000}, {0x7f924000}, {0x7f926000},
+ {0x7f928000}, {0x7f92a000}, {0x7f92c000}, {0x7f92e000},
+ {0x7f930000}, {0x7f932000}, {0x7f934000}, {0x7f936000},
+ {0x7f938000}, {0x7f93a000}, {0x7f93c000}, {0x7f93e000},
+ {0x7f940000}, {0x7f942000}, {0x7f944000}, {0x7f946000},
+ {0x7f948000}, {0x7f94a000}, {0x7f94c000}, {0x7f94e000},
+ {0x7f950000}, {0x7f952000}, {0x7f954000}, {0x7f956000},
+ {0x7f958000}, {0x7f95a000}, {0x7f95c000}, {0x7f95e000},
+ {0x7f960000}, {0x7f962000}, {0x7f964000}, {0x7f966000},
+ {0x7f968000}, {0x7f96a000}, {0x7f96c000}, {0x7f96e000},
+ {0x7f970000}, {0x7f972000}, {0x7f974000}, {0x7f976000},
+ {0x7f978000}, {0x7f97a000}, {0x7f97c000}, {0x7f97e000},
+ {0x7f980000}, {0x7f982000}, {0x7f984000}, {0x7f986000},
+ {0x7f988000}, {0x7f98a000}, {0x7f98c000}, {0x7f98e000},
+ {0x7f990000}, {0x7f992000}, {0x7f994000}, {0x7f996000},
+ {0x7f998000}, {0x7f99a000}, {0x7f99c000}, {0x7f99e000},
+ {0x7f9a0000}, {0x7f9a2000}, {0x7f9a4000}, {0x7f9a6000},
+ {0x7f9a8000}, {0x7f9aa000}, {0x7f9ac000}, {0x7f9ae000},
+ {0x7f9b0000}, {0x7f9b2000}, {0x7f9b4000}, {0x7f9b6000},
+ {0x7f9b8000}, {0x7f9ba000}, {0x7f9bc000}, {0x7f9be000},
+ {0x7f9c0000}, {0x7f9c2000}, {0x7f9c4000}, {0x7f9c6000},
+ {0x7f9c8000}, {0x7f9ca000}, {0x7f9cc000}, {0x7f9ce000},
+ {0x7f9d0000}, {0x7f9d2000}, {0x7f9d4000}, {0x7f9d6000},
+ {0x7f9d8000}, {0x7f9da000}, {0x7f9dc000}, {0x7f9de000},
+ {0x7f9e0000}, {0x7f9e2000}, {0x7f9e4000}, {0x7f9e6000},
+ {0x7f9e8000}, {0x7f9ea000}, {0x7f9ec000}, {0x7f9ee000},
+ {0x7f9f0000}, {0x7f9f2000}, {0x7f9f4000}, {0x7f9f6000},
+ {0x7f9f8000}, {0x7f9fa000}, {0x7f9fc000}, {0x7f9fe000},
+ {0x7fa00000}, {0x7fa02000}, {0x7fa04000}, {0x7fa06000},
+ {0x7fa08000}, {0x7fa0a000}, {0x7fa0c000}, {0x7fa0e000},
+ {0x7fa10000}, {0x7fa12000}, {0x7fa14000}, {0x7fa16000},
+ {0x7fa18000}, {0x7fa1a000}, {0x7fa1c000}, {0x7fa1e000},
+ {0x7fa20000}, {0x7fa22000}, {0x7fa24000}, {0x7fa26000},
+ {0x7fa28000}, {0x7fa2a000}, {0x7fa2c000}, {0x7fa2e000},
+ {0x7fa30000}, {0x7fa32000}, {0x7fa34000}, {0x7fa36000},
+ {0x7fa38000}, {0x7fa3a000}, {0x7fa3c000}, {0x7fa3e000},
+ {0x7fa40000}, {0x7fa42000}, {0x7fa44000}, {0x7fa46000},
+ {0x7fa48000}, {0x7fa4a000}, {0x7fa4c000}, {0x7fa4e000},
+ {0x7fa50000}, {0x7fa52000}, {0x7fa54000}, {0x7fa56000},
+ {0x7fa58000}, {0x7fa5a000}, {0x7fa5c000}, {0x7fa5e000},
+ {0x7fa60000}, {0x7fa62000}, {0x7fa64000}, {0x7fa66000},
+ {0x7fa68000}, {0x7fa6a000}, {0x7fa6c000}, {0x7fa6e000},
+ {0x7fa70000}, {0x7fa72000}, {0x7fa74000}, {0x7fa76000},
+ {0x7fa78000}, {0x7fa7a000}, {0x7fa7c000}, {0x7fa7e000},
+ {0x7fa80000}, {0x7fa82000}, {0x7fa84000}, {0x7fa86000},
+ {0x7fa88000}, {0x7fa8a000}, {0x7fa8c000}, {0x7fa8e000},
+ {0x7fa90000}, {0x7fa92000}, {0x7fa94000}, {0x7fa96000},
+ {0x7fa98000}, {0x7fa9a000}, {0x7fa9c000}, {0x7fa9e000},
+ {0x7faa0000}, {0x7faa2000}, {0x7faa4000}, {0x7faa6000},
+ {0x7faa8000}, {0x7faaa000}, {0x7faac000}, {0x7faae000},
+ {0x7fab0000}, {0x7fab2000}, {0x7fab4000}, {0x7fab6000},
+ {0x7fab8000}, {0x7faba000}, {0x7fabc000}, {0x7fabe000},
+ {0x7fac0000}, {0x7fac2000}, {0x7fac4000}, {0x7fac6000},
+ {0x7fac8000}, {0x7faca000}, {0x7facc000}, {0x7face000},
+ {0x7fad0000}, {0x7fad2000}, {0x7fad4000}, {0x7fad6000},
+ {0x7fad8000}, {0x7fada000}, {0x7fadc000}, {0x7fade000},
+ {0x7fae0000}, {0x7fae2000}, {0x7fae4000}, {0x7fae6000},
+ {0x7fae8000}, {0x7faea000}, {0x7faec000}, {0x7faee000},
+ {0x7faf0000}, {0x7faf2000}, {0x7faf4000}, {0x7faf6000},
+ {0x7faf8000}, {0x7fafa000}, {0x7fafc000}, {0x7fafe000},
+ {0x7fb00000}, {0x7fb02000}, {0x7fb04000}, {0x7fb06000},
+ {0x7fb08000}, {0x7fb0a000}, {0x7fb0c000}, {0x7fb0e000},
+ {0x7fb10000}, {0x7fb12000}, {0x7fb14000}, {0x7fb16000},
+ {0x7fb18000}, {0x7fb1a000}, {0x7fb1c000}, {0x7fb1e000},
+ {0x7fb20000}, {0x7fb22000}, {0x7fb24000}, {0x7fb26000},
+ {0x7fb28000}, {0x7fb2a000}, {0x7fb2c000}, {0x7fb2e000},
+ {0x7fb30000}, {0x7fb32000}, {0x7fb34000}, {0x7fb36000},
+ {0x7fb38000}, {0x7fb3a000}, {0x7fb3c000}, {0x7fb3e000},
+ {0x7fb40000}, {0x7fb42000}, {0x7fb44000}, {0x7fb46000},
+ {0x7fb48000}, {0x7fb4a000}, {0x7fb4c000}, {0x7fb4e000},
+ {0x7fb50000}, {0x7fb52000}, {0x7fb54000}, {0x7fb56000},
+ {0x7fb58000}, {0x7fb5a000}, {0x7fb5c000}, {0x7fb5e000},
+ {0x7fb60000}, {0x7fb62000}, {0x7fb64000}, {0x7fb66000},
+ {0x7fb68000}, {0x7fb6a000}, {0x7fb6c000}, {0x7fb6e000},
+ {0x7fb70000}, {0x7fb72000}, {0x7fb74000}, {0x7fb76000},
+ {0x7fb78000}, {0x7fb7a000}, {0x7fb7c000}, {0x7fb7e000},
+ {0x7fb80000}, {0x7fb82000}, {0x7fb84000}, {0x7fb86000},
+ {0x7fb88000}, {0x7fb8a000}, {0x7fb8c000}, {0x7fb8e000},
+ {0x7fb90000}, {0x7fb92000}, {0x7fb94000}, {0x7fb96000},
+ {0x7fb98000}, {0x7fb9a000}, {0x7fb9c000}, {0x7fb9e000},
+ {0x7fba0000}, {0x7fba2000}, {0x7fba4000}, {0x7fba6000},
+ {0x7fba8000}, {0x7fbaa000}, {0x7fbac000}, {0x7fbae000},
+ {0x7fbb0000}, {0x7fbb2000}, {0x7fbb4000}, {0x7fbb6000},
+ {0x7fbb8000}, {0x7fbba000}, {0x7fbbc000}, {0x7fbbe000},
+ {0x7fbc0000}, {0x7fbc2000}, {0x7fbc4000}, {0x7fbc6000},
+ {0x7fbc8000}, {0x7fbca000}, {0x7fbcc000}, {0x7fbce000},
+ {0x7fbd0000}, {0x7fbd2000}, {0x7fbd4000}, {0x7fbd6000},
+ {0x7fbd8000}, {0x7fbda000}, {0x7fbdc000}, {0x7fbde000},
+ {0x7fbe0000}, {0x7fbe2000}, {0x7fbe4000}, {0x7fbe6000},
+ {0x7fbe8000}, {0x7fbea000}, {0x7fbec000}, {0x7fbee000},
+ {0x7fbf0000}, {0x7fbf2000}, {0x7fbf4000}, {0x7fbf6000},
+ {0x7fbf8000}, {0x7fbfa000}, {0x7fbfc000}, {0x7fbfe000},
+ {0x7fc00000}, {0x7fc02000}, {0x7fc04000}, {0x7fc06000},
+ {0x7fc08000}, {0x7fc0a000}, {0x7fc0c000}, {0x7fc0e000},
+ {0x7fc10000}, {0x7fc12000}, {0x7fc14000}, {0x7fc16000},
+ {0x7fc18000}, {0x7fc1a000}, {0x7fc1c000}, {0x7fc1e000},
+ {0x7fc20000}, {0x7fc22000}, {0x7fc24000}, {0x7fc26000},
+ {0x7fc28000}, {0x7fc2a000}, {0x7fc2c000}, {0x7fc2e000},
+ {0x7fc30000}, {0x7fc32000}, {0x7fc34000}, {0x7fc36000},
+ {0x7fc38000}, {0x7fc3a000}, {0x7fc3c000}, {0x7fc3e000},
+ {0x7fc40000}, {0x7fc42000}, {0x7fc44000}, {0x7fc46000},
+ {0x7fc48000}, {0x7fc4a000}, {0x7fc4c000}, {0x7fc4e000},
+ {0x7fc50000}, {0x7fc52000}, {0x7fc54000}, {0x7fc56000},
+ {0x7fc58000}, {0x7fc5a000}, {0x7fc5c000}, {0x7fc5e000},
+ {0x7fc60000}, {0x7fc62000}, {0x7fc64000}, {0x7fc66000},
+ {0x7fc68000}, {0x7fc6a000}, {0x7fc6c000}, {0x7fc6e000},
+ {0x7fc70000}, {0x7fc72000}, {0x7fc74000}, {0x7fc76000},
+ {0x7fc78000}, {0x7fc7a000}, {0x7fc7c000}, {0x7fc7e000},
+ {0x7fc80000}, {0x7fc82000}, {0x7fc84000}, {0x7fc86000},
+ {0x7fc88000}, {0x7fc8a000}, {0x7fc8c000}, {0x7fc8e000},
+ {0x7fc90000}, {0x7fc92000}, {0x7fc94000}, {0x7fc96000},
+ {0x7fc98000}, {0x7fc9a000}, {0x7fc9c000}, {0x7fc9e000},
+ {0x7fca0000}, {0x7fca2000}, {0x7fca4000}, {0x7fca6000},
+ {0x7fca8000}, {0x7fcaa000}, {0x7fcac000}, {0x7fcae000},
+ {0x7fcb0000}, {0x7fcb2000}, {0x7fcb4000}, {0x7fcb6000},
+ {0x7fcb8000}, {0x7fcba000}, {0x7fcbc000}, {0x7fcbe000},
+ {0x7fcc0000}, {0x7fcc2000}, {0x7fcc4000}, {0x7fcc6000},
+ {0x7fcc8000}, {0x7fcca000}, {0x7fccc000}, {0x7fcce000},
+ {0x7fcd0000}, {0x7fcd2000}, {0x7fcd4000}, {0x7fcd6000},
+ {0x7fcd8000}, {0x7fcda000}, {0x7fcdc000}, {0x7fcde000},
+ {0x7fce0000}, {0x7fce2000}, {0x7fce4000}, {0x7fce6000},
+ {0x7fce8000}, {0x7fcea000}, {0x7fcec000}, {0x7fcee000},
+ {0x7fcf0000}, {0x7fcf2000}, {0x7fcf4000}, {0x7fcf6000},
+ {0x7fcf8000}, {0x7fcfa000}, {0x7fcfc000}, {0x7fcfe000},
+ {0x7fd00000}, {0x7fd02000}, {0x7fd04000}, {0x7fd06000},
+ {0x7fd08000}, {0x7fd0a000}, {0x7fd0c000}, {0x7fd0e000},
+ {0x7fd10000}, {0x7fd12000}, {0x7fd14000}, {0x7fd16000},
+ {0x7fd18000}, {0x7fd1a000}, {0x7fd1c000}, {0x7fd1e000},
+ {0x7fd20000}, {0x7fd22000}, {0x7fd24000}, {0x7fd26000},
+ {0x7fd28000}, {0x7fd2a000}, {0x7fd2c000}, {0x7fd2e000},
+ {0x7fd30000}, {0x7fd32000}, {0x7fd34000}, {0x7fd36000},
+ {0x7fd38000}, {0x7fd3a000}, {0x7fd3c000}, {0x7fd3e000},
+ {0x7fd40000}, {0x7fd42000}, {0x7fd44000}, {0x7fd46000},
+ {0x7fd48000}, {0x7fd4a000}, {0x7fd4c000}, {0x7fd4e000},
+ {0x7fd50000}, {0x7fd52000}, {0x7fd54000}, {0x7fd56000},
+ {0x7fd58000}, {0x7fd5a000}, {0x7fd5c000}, {0x7fd5e000},
+ {0x7fd60000}, {0x7fd62000}, {0x7fd64000}, {0x7fd66000},
+ {0x7fd68000}, {0x7fd6a000}, {0x7fd6c000}, {0x7fd6e000},
+ {0x7fd70000}, {0x7fd72000}, {0x7fd74000}, {0x7fd76000},
+ {0x7fd78000}, {0x7fd7a000}, {0x7fd7c000}, {0x7fd7e000},
+ {0x7fd80000}, {0x7fd82000}, {0x7fd84000}, {0x7fd86000},
+ {0x7fd88000}, {0x7fd8a000}, {0x7fd8c000}, {0x7fd8e000},
+ {0x7fd90000}, {0x7fd92000}, {0x7fd94000}, {0x7fd96000},
+ {0x7fd98000}, {0x7fd9a000}, {0x7fd9c000}, {0x7fd9e000},
+ {0x7fda0000}, {0x7fda2000}, {0x7fda4000}, {0x7fda6000},
+ {0x7fda8000}, {0x7fdaa000}, {0x7fdac000}, {0x7fdae000},
+ {0x7fdb0000}, {0x7fdb2000}, {0x7fdb4000}, {0x7fdb6000},
+ {0x7fdb8000}, {0x7fdba000}, {0x7fdbc000}, {0x7fdbe000},
+ {0x7fdc0000}, {0x7fdc2000}, {0x7fdc4000}, {0x7fdc6000},
+ {0x7fdc8000}, {0x7fdca000}, {0x7fdcc000}, {0x7fdce000},
+ {0x7fdd0000}, {0x7fdd2000}, {0x7fdd4000}, {0x7fdd6000},
+ {0x7fdd8000}, {0x7fdda000}, {0x7fddc000}, {0x7fdde000},
+ {0x7fde0000}, {0x7fde2000}, {0x7fde4000}, {0x7fde6000},
+ {0x7fde8000}, {0x7fdea000}, {0x7fdec000}, {0x7fdee000},
+ {0x7fdf0000}, {0x7fdf2000}, {0x7fdf4000}, {0x7fdf6000},
+ {0x7fdf8000}, {0x7fdfa000}, {0x7fdfc000}, {0x7fdfe000},
+ {0x7fe00000}, {0x7fe02000}, {0x7fe04000}, {0x7fe06000},
+ {0x7fe08000}, {0x7fe0a000}, {0x7fe0c000}, {0x7fe0e000},
+ {0x7fe10000}, {0x7fe12000}, {0x7fe14000}, {0x7fe16000},
+ {0x7fe18000}, {0x7fe1a000}, {0x7fe1c000}, {0x7fe1e000},
+ {0x7fe20000}, {0x7fe22000}, {0x7fe24000}, {0x7fe26000},
+ {0x7fe28000}, {0x7fe2a000}, {0x7fe2c000}, {0x7fe2e000},
+ {0x7fe30000}, {0x7fe32000}, {0x7fe34000}, {0x7fe36000},
+ {0x7fe38000}, {0x7fe3a000}, {0x7fe3c000}, {0x7fe3e000},
+ {0x7fe40000}, {0x7fe42000}, {0x7fe44000}, {0x7fe46000},
+ {0x7fe48000}, {0x7fe4a000}, {0x7fe4c000}, {0x7fe4e000},
+ {0x7fe50000}, {0x7fe52000}, {0x7fe54000}, {0x7fe56000},
+ {0x7fe58000}, {0x7fe5a000}, {0x7fe5c000}, {0x7fe5e000},
+ {0x7fe60000}, {0x7fe62000}, {0x7fe64000}, {0x7fe66000},
+ {0x7fe68000}, {0x7fe6a000}, {0x7fe6c000}, {0x7fe6e000},
+ {0x7fe70000}, {0x7fe72000}, {0x7fe74000}, {0x7fe76000},
+ {0x7fe78000}, {0x7fe7a000}, {0x7fe7c000}, {0x7fe7e000},
+ {0x7fe80000}, {0x7fe82000}, {0x7fe84000}, {0x7fe86000},
+ {0x7fe88000}, {0x7fe8a000}, {0x7fe8c000}, {0x7fe8e000},
+ {0x7fe90000}, {0x7fe92000}, {0x7fe94000}, {0x7fe96000},
+ {0x7fe98000}, {0x7fe9a000}, {0x7fe9c000}, {0x7fe9e000},
+ {0x7fea0000}, {0x7fea2000}, {0x7fea4000}, {0x7fea6000},
+ {0x7fea8000}, {0x7feaa000}, {0x7feac000}, {0x7feae000},
+ {0x7feb0000}, {0x7feb2000}, {0x7feb4000}, {0x7feb6000},
+ {0x7feb8000}, {0x7feba000}, {0x7febc000}, {0x7febe000},
+ {0x7fec0000}, {0x7fec2000}, {0x7fec4000}, {0x7fec6000},
+ {0x7fec8000}, {0x7feca000}, {0x7fecc000}, {0x7fece000},
+ {0x7fed0000}, {0x7fed2000}, {0x7fed4000}, {0x7fed6000},
+ {0x7fed8000}, {0x7feda000}, {0x7fedc000}, {0x7fede000},
+ {0x7fee0000}, {0x7fee2000}, {0x7fee4000}, {0x7fee6000},
+ {0x7fee8000}, {0x7feea000}, {0x7feec000}, {0x7feee000},
+ {0x7fef0000}, {0x7fef2000}, {0x7fef4000}, {0x7fef6000},
+ {0x7fef8000}, {0x7fefa000}, {0x7fefc000}, {0x7fefe000},
+ {0x7ff00000}, {0x7ff02000}, {0x7ff04000}, {0x7ff06000},
+ {0x7ff08000}, {0x7ff0a000}, {0x7ff0c000}, {0x7ff0e000},
+ {0x7ff10000}, {0x7ff12000}, {0x7ff14000}, {0x7ff16000},
+ {0x7ff18000}, {0x7ff1a000}, {0x7ff1c000}, {0x7ff1e000},
+ {0x7ff20000}, {0x7ff22000}, {0x7ff24000}, {0x7ff26000},
+ {0x7ff28000}, {0x7ff2a000}, {0x7ff2c000}, {0x7ff2e000},
+ {0x7ff30000}, {0x7ff32000}, {0x7ff34000}, {0x7ff36000},
+ {0x7ff38000}, {0x7ff3a000}, {0x7ff3c000}, {0x7ff3e000},
+ {0x7ff40000}, {0x7ff42000}, {0x7ff44000}, {0x7ff46000},
+ {0x7ff48000}, {0x7ff4a000}, {0x7ff4c000}, {0x7ff4e000},
+ {0x7ff50000}, {0x7ff52000}, {0x7ff54000}, {0x7ff56000},
+ {0x7ff58000}, {0x7ff5a000}, {0x7ff5c000}, {0x7ff5e000},
+ {0x7ff60000}, {0x7ff62000}, {0x7ff64000}, {0x7ff66000},
+ {0x7ff68000}, {0x7ff6a000}, {0x7ff6c000}, {0x7ff6e000},
+ {0x7ff70000}, {0x7ff72000}, {0x7ff74000}, {0x7ff76000},
+ {0x7ff78000}, {0x7ff7a000}, {0x7ff7c000}, {0x7ff7e000},
+ {0x7ff80000}, {0x7ff82000}, {0x7ff84000}, {0x7ff86000},
+ {0x7ff88000}, {0x7ff8a000}, {0x7ff8c000}, {0x7ff8e000},
+ {0x7ff90000}, {0x7ff92000}, {0x7ff94000}, {0x7ff96000},
+ {0x7ff98000}, {0x7ff9a000}, {0x7ff9c000}, {0x7ff9e000},
+ {0x7ffa0000}, {0x7ffa2000}, {0x7ffa4000}, {0x7ffa6000},
+ {0x7ffa8000}, {0x7ffaa000}, {0x7ffac000}, {0x7ffae000},
+ {0x7ffb0000}, {0x7ffb2000}, {0x7ffb4000}, {0x7ffb6000},
+ {0x7ffb8000}, {0x7ffba000}, {0x7ffbc000}, {0x7ffbe000},
+ {0x7ffc0000}, {0x7ffc2000}, {0x7ffc4000}, {0x7ffc6000},
+ {0x7ffc8000}, {0x7ffca000}, {0x7ffcc000}, {0x7ffce000},
+ {0x7ffd0000}, {0x7ffd2000}, {0x7ffd4000}, {0x7ffd6000},
+ {0x7ffd8000}, {0x7ffda000}, {0x7ffdc000}, {0x7ffde000},
+ {0x7ffe0000}, {0x7ffe2000}, {0x7ffe4000}, {0x7ffe6000},
+ {0x7ffe8000}, {0x7ffea000}, {0x7ffec000}, {0x7ffee000},
+ {0x7fff0000}, {0x7fff2000}, {0x7fff4000}, {0x7fff6000},
+ {0x7fff8000}, {0x7fffa000}, {0x7fffc000}, {0x7fffe000},
+ {0x80000000}, {0xb3800000}, {0xb4000000}, {0xb4400000},
+ {0xb4800000}, {0xb4a00000}, {0xb4c00000}, {0xb4e00000},
+ {0xb5000000}, {0xb5100000}, {0xb5200000}, {0xb5300000},
+ {0xb5400000}, {0xb5500000}, {0xb5600000}, {0xb5700000},
+ {0xb5800000}, {0xb5880000}, {0xb5900000}, {0xb5980000},
+ {0xb5a00000}, {0xb5a80000}, {0xb5b00000}, {0xb5b80000},
+ {0xb5c00000}, {0xb5c80000}, {0xb5d00000}, {0xb5d80000},
+ {0xb5e00000}, {0xb5e80000}, {0xb5f00000}, {0xb5f80000},
+ {0xb6000000}, {0xb6040000}, {0xb6080000}, {0xb60c0000},
+ {0xb6100000}, {0xb6140000}, {0xb6180000}, {0xb61c0000},
+ {0xb6200000}, {0xb6240000}, {0xb6280000}, {0xb62c0000},
+ {0xb6300000}, {0xb6340000}, {0xb6380000}, {0xb63c0000},
+ {0xb6400000}, {0xb6440000}, {0xb6480000}, {0xb64c0000},
+ {0xb6500000}, {0xb6540000}, {0xb6580000}, {0xb65c0000},
+ {0xb6600000}, {0xb6640000}, {0xb6680000}, {0xb66c0000},
+ {0xb6700000}, {0xb6740000}, {0xb6780000}, {0xb67c0000},
+ {0xb6800000}, {0xb6820000}, {0xb6840000}, {0xb6860000},
+ {0xb6880000}, {0xb68a0000}, {0xb68c0000}, {0xb68e0000},
+ {0xb6900000}, {0xb6920000}, {0xb6940000}, {0xb6960000},
+ {0xb6980000}, {0xb69a0000}, {0xb69c0000}, {0xb69e0000},
+ {0xb6a00000}, {0xb6a20000}, {0xb6a40000}, {0xb6a60000},
+ {0xb6a80000}, {0xb6aa0000}, {0xb6ac0000}, {0xb6ae0000},
+ {0xb6b00000}, {0xb6b20000}, {0xb6b40000}, {0xb6b60000},
+ {0xb6b80000}, {0xb6ba0000}, {0xb6bc0000}, {0xb6be0000},
+ {0xb6c00000}, {0xb6c20000}, {0xb6c40000}, {0xb6c60000},
+ {0xb6c80000}, {0xb6ca0000}, {0xb6cc0000}, {0xb6ce0000},
+ {0xb6d00000}, {0xb6d20000}, {0xb6d40000}, {0xb6d60000},
+ {0xb6d80000}, {0xb6da0000}, {0xb6dc0000}, {0xb6de0000},
+ {0xb6e00000}, {0xb6e20000}, {0xb6e40000}, {0xb6e60000},
+ {0xb6e80000}, {0xb6ea0000}, {0xb6ec0000}, {0xb6ee0000},
+ {0xb6f00000}, {0xb6f20000}, {0xb6f40000}, {0xb6f60000},
+ {0xb6f80000}, {0xb6fa0000}, {0xb6fc0000}, {0xb6fe0000},
+ {0xb7000000}, {0xb7010000}, {0xb7020000}, {0xb7030000},
+ {0xb7040000}, {0xb7050000}, {0xb7060000}, {0xb7070000},
+ {0xb7080000}, {0xb7090000}, {0xb70a0000}, {0xb70b0000},
+ {0xb70c0000}, {0xb70d0000}, {0xb70e0000}, {0xb70f0000},
+ {0xb7100000}, {0xb7110000}, {0xb7120000}, {0xb7130000},
+ {0xb7140000}, {0xb7150000}, {0xb7160000}, {0xb7170000},
+ {0xb7180000}, {0xb7190000}, {0xb71a0000}, {0xb71b0000},
+ {0xb71c0000}, {0xb71d0000}, {0xb71e0000}, {0xb71f0000},
+ {0xb7200000}, {0xb7210000}, {0xb7220000}, {0xb7230000},
+ {0xb7240000}, {0xb7250000}, {0xb7260000}, {0xb7270000},
+ {0xb7280000}, {0xb7290000}, {0xb72a0000}, {0xb72b0000},
+ {0xb72c0000}, {0xb72d0000}, {0xb72e0000}, {0xb72f0000},
+ {0xb7300000}, {0xb7310000}, {0xb7320000}, {0xb7330000},
+ {0xb7340000}, {0xb7350000}, {0xb7360000}, {0xb7370000},
+ {0xb7380000}, {0xb7390000}, {0xb73a0000}, {0xb73b0000},
+ {0xb73c0000}, {0xb73d0000}, {0xb73e0000}, {0xb73f0000},
+ {0xb7400000}, {0xb7410000}, {0xb7420000}, {0xb7430000},
+ {0xb7440000}, {0xb7450000}, {0xb7460000}, {0xb7470000},
+ {0xb7480000}, {0xb7490000}, {0xb74a0000}, {0xb74b0000},
+ {0xb74c0000}, {0xb74d0000}, {0xb74e0000}, {0xb74f0000},
+ {0xb7500000}, {0xb7510000}, {0xb7520000}, {0xb7530000},
+ {0xb7540000}, {0xb7550000}, {0xb7560000}, {0xb7570000},
+ {0xb7580000}, {0xb7590000}, {0xb75a0000}, {0xb75b0000},
+ {0xb75c0000}, {0xb75d0000}, {0xb75e0000}, {0xb75f0000},
+ {0xb7600000}, {0xb7610000}, {0xb7620000}, {0xb7630000},
+ {0xb7640000}, {0xb7650000}, {0xb7660000}, {0xb7670000},
+ {0xb7680000}, {0xb7690000}, {0xb76a0000}, {0xb76b0000},
+ {0xb76c0000}, {0xb76d0000}, {0xb76e0000}, {0xb76f0000},
+ {0xb7700000}, {0xb7710000}, {0xb7720000}, {0xb7730000},
+ {0xb7740000}, {0xb7750000}, {0xb7760000}, {0xb7770000},
+ {0xb7780000}, {0xb7790000}, {0xb77a0000}, {0xb77b0000},
+ {0xb77c0000}, {0xb77d0000}, {0xb77e0000}, {0xb77f0000},
+ {0xb7800000}, {0xb7808000}, {0xb7810000}, {0xb7818000},
+ {0xb7820000}, {0xb7828000}, {0xb7830000}, {0xb7838000},
+ {0xb7840000}, {0xb7848000}, {0xb7850000}, {0xb7858000},
+ {0xb7860000}, {0xb7868000}, {0xb7870000}, {0xb7878000},
+ {0xb7880000}, {0xb7888000}, {0xb7890000}, {0xb7898000},
+ {0xb78a0000}, {0xb78a8000}, {0xb78b0000}, {0xb78b8000},
+ {0xb78c0000}, {0xb78c8000}, {0xb78d0000}, {0xb78d8000},
+ {0xb78e0000}, {0xb78e8000}, {0xb78f0000}, {0xb78f8000},
+ {0xb7900000}, {0xb7908000}, {0xb7910000}, {0xb7918000},
+ {0xb7920000}, {0xb7928000}, {0xb7930000}, {0xb7938000},
+ {0xb7940000}, {0xb7948000}, {0xb7950000}, {0xb7958000},
+ {0xb7960000}, {0xb7968000}, {0xb7970000}, {0xb7978000},
+ {0xb7980000}, {0xb7988000}, {0xb7990000}, {0xb7998000},
+ {0xb79a0000}, {0xb79a8000}, {0xb79b0000}, {0xb79b8000},
+ {0xb79c0000}, {0xb79c8000}, {0xb79d0000}, {0xb79d8000},
+ {0xb79e0000}, {0xb79e8000}, {0xb79f0000}, {0xb79f8000},
+ {0xb7a00000}, {0xb7a08000}, {0xb7a10000}, {0xb7a18000},
+ {0xb7a20000}, {0xb7a28000}, {0xb7a30000}, {0xb7a38000},
+ {0xb7a40000}, {0xb7a48000}, {0xb7a50000}, {0xb7a58000},
+ {0xb7a60000}, {0xb7a68000}, {0xb7a70000}, {0xb7a78000},
+ {0xb7a80000}, {0xb7a88000}, {0xb7a90000}, {0xb7a98000},
+ {0xb7aa0000}, {0xb7aa8000}, {0xb7ab0000}, {0xb7ab8000},
+ {0xb7ac0000}, {0xb7ac8000}, {0xb7ad0000}, {0xb7ad8000},
+ {0xb7ae0000}, {0xb7ae8000}, {0xb7af0000}, {0xb7af8000},
+ {0xb7b00000}, {0xb7b08000}, {0xb7b10000}, {0xb7b18000},
+ {0xb7b20000}, {0xb7b28000}, {0xb7b30000}, {0xb7b38000},
+ {0xb7b40000}, {0xb7b48000}, {0xb7b50000}, {0xb7b58000},
+ {0xb7b60000}, {0xb7b68000}, {0xb7b70000}, {0xb7b78000},
+ {0xb7b80000}, {0xb7b88000}, {0xb7b90000}, {0xb7b98000},
+ {0xb7ba0000}, {0xb7ba8000}, {0xb7bb0000}, {0xb7bb8000},
+ {0xb7bc0000}, {0xb7bc8000}, {0xb7bd0000}, {0xb7bd8000},
+ {0xb7be0000}, {0xb7be8000}, {0xb7bf0000}, {0xb7bf8000},
+ {0xb7c00000}, {0xb7c08000}, {0xb7c10000}, {0xb7c18000},
+ {0xb7c20000}, {0xb7c28000}, {0xb7c30000}, {0xb7c38000},
+ {0xb7c40000}, {0xb7c48000}, {0xb7c50000}, {0xb7c58000},
+ {0xb7c60000}, {0xb7c68000}, {0xb7c70000}, {0xb7c78000},
+ {0xb7c80000}, {0xb7c88000}, {0xb7c90000}, {0xb7c98000},
+ {0xb7ca0000}, {0xb7ca8000}, {0xb7cb0000}, {0xb7cb8000},
+ {0xb7cc0000}, {0xb7cc8000}, {0xb7cd0000}, {0xb7cd8000},
+ {0xb7ce0000}, {0xb7ce8000}, {0xb7cf0000}, {0xb7cf8000},
+ {0xb7d00000}, {0xb7d08000}, {0xb7d10000}, {0xb7d18000},
+ {0xb7d20000}, {0xb7d28000}, {0xb7d30000}, {0xb7d38000},
+ {0xb7d40000}, {0xb7d48000}, {0xb7d50000}, {0xb7d58000},
+ {0xb7d60000}, {0xb7d68000}, {0xb7d70000}, {0xb7d78000},
+ {0xb7d80000}, {0xb7d88000}, {0xb7d90000}, {0xb7d98000},
+ {0xb7da0000}, {0xb7da8000}, {0xb7db0000}, {0xb7db8000},
+ {0xb7dc0000}, {0xb7dc8000}, {0xb7dd0000}, {0xb7dd8000},
+ {0xb7de0000}, {0xb7de8000}, {0xb7df0000}, {0xb7df8000},
+ {0xb7e00000}, {0xb7e08000}, {0xb7e10000}, {0xb7e18000},
+ {0xb7e20000}, {0xb7e28000}, {0xb7e30000}, {0xb7e38000},
+ {0xb7e40000}, {0xb7e48000}, {0xb7e50000}, {0xb7e58000},
+ {0xb7e60000}, {0xb7e68000}, {0xb7e70000}, {0xb7e78000},
+ {0xb7e80000}, {0xb7e88000}, {0xb7e90000}, {0xb7e98000},
+ {0xb7ea0000}, {0xb7ea8000}, {0xb7eb0000}, {0xb7eb8000},
+ {0xb7ec0000}, {0xb7ec8000}, {0xb7ed0000}, {0xb7ed8000},
+ {0xb7ee0000}, {0xb7ee8000}, {0xb7ef0000}, {0xb7ef8000},
+ {0xb7f00000}, {0xb7f08000}, {0xb7f10000}, {0xb7f18000},
+ {0xb7f20000}, {0xb7f28000}, {0xb7f30000}, {0xb7f38000},
+ {0xb7f40000}, {0xb7f48000}, {0xb7f50000}, {0xb7f58000},
+ {0xb7f60000}, {0xb7f68000}, {0xb7f70000}, {0xb7f78000},
+ {0xb7f80000}, {0xb7f88000}, {0xb7f90000}, {0xb7f98000},
+ {0xb7fa0000}, {0xb7fa8000}, {0xb7fb0000}, {0xb7fb8000},
+ {0xb7fc0000}, {0xb7fc8000}, {0xb7fd0000}, {0xb7fd8000},
+ {0xb7fe0000}, {0xb7fe8000}, {0xb7ff0000}, {0xb7ff8000},
+ {0xb8000000}, {0xb8004000}, {0xb8008000}, {0xb800c000},
+ {0xb8010000}, {0xb8014000}, {0xb8018000}, {0xb801c000},
+ {0xb8020000}, {0xb8024000}, {0xb8028000}, {0xb802c000},
+ {0xb8030000}, {0xb8034000}, {0xb8038000}, {0xb803c000},
+ {0xb8040000}, {0xb8044000}, {0xb8048000}, {0xb804c000},
+ {0xb8050000}, {0xb8054000}, {0xb8058000}, {0xb805c000},
+ {0xb8060000}, {0xb8064000}, {0xb8068000}, {0xb806c000},
+ {0xb8070000}, {0xb8074000}, {0xb8078000}, {0xb807c000},
+ {0xb8080000}, {0xb8084000}, {0xb8088000}, {0xb808c000},
+ {0xb8090000}, {0xb8094000}, {0xb8098000}, {0xb809c000},
+ {0xb80a0000}, {0xb80a4000}, {0xb80a8000}, {0xb80ac000},
+ {0xb80b0000}, {0xb80b4000}, {0xb80b8000}, {0xb80bc000},
+ {0xb80c0000}, {0xb80c4000}, {0xb80c8000}, {0xb80cc000},
+ {0xb80d0000}, {0xb80d4000}, {0xb80d8000}, {0xb80dc000},
+ {0xb80e0000}, {0xb80e4000}, {0xb80e8000}, {0xb80ec000},
+ {0xb80f0000}, {0xb80f4000}, {0xb80f8000}, {0xb80fc000},
+ {0xb8100000}, {0xb8104000}, {0xb8108000}, {0xb810c000},
+ {0xb8110000}, {0xb8114000}, {0xb8118000}, {0xb811c000},
+ {0xb8120000}, {0xb8124000}, {0xb8128000}, {0xb812c000},
+ {0xb8130000}, {0xb8134000}, {0xb8138000}, {0xb813c000},
+ {0xb8140000}, {0xb8144000}, {0xb8148000}, {0xb814c000},
+ {0xb8150000}, {0xb8154000}, {0xb8158000}, {0xb815c000},
+ {0xb8160000}, {0xb8164000}, {0xb8168000}, {0xb816c000},
+ {0xb8170000}, {0xb8174000}, {0xb8178000}, {0xb817c000},
+ {0xb8180000}, {0xb8184000}, {0xb8188000}, {0xb818c000},
+ {0xb8190000}, {0xb8194000}, {0xb8198000}, {0xb819c000},
+ {0xb81a0000}, {0xb81a4000}, {0xb81a8000}, {0xb81ac000},
+ {0xb81b0000}, {0xb81b4000}, {0xb81b8000}, {0xb81bc000},
+ {0xb81c0000}, {0xb81c4000}, {0xb81c8000}, {0xb81cc000},
+ {0xb81d0000}, {0xb81d4000}, {0xb81d8000}, {0xb81dc000},
+ {0xb81e0000}, {0xb81e4000}, {0xb81e8000}, {0xb81ec000},
+ {0xb81f0000}, {0xb81f4000}, {0xb81f8000}, {0xb81fc000},
+ {0xb8200000}, {0xb8204000}, {0xb8208000}, {0xb820c000},
+ {0xb8210000}, {0xb8214000}, {0xb8218000}, {0xb821c000},
+ {0xb8220000}, {0xb8224000}, {0xb8228000}, {0xb822c000},
+ {0xb8230000}, {0xb8234000}, {0xb8238000}, {0xb823c000},
+ {0xb8240000}, {0xb8244000}, {0xb8248000}, {0xb824c000},
+ {0xb8250000}, {0xb8254000}, {0xb8258000}, {0xb825c000},
+ {0xb8260000}, {0xb8264000}, {0xb8268000}, {0xb826c000},
+ {0xb8270000}, {0xb8274000}, {0xb8278000}, {0xb827c000},
+ {0xb8280000}, {0xb8284000}, {0xb8288000}, {0xb828c000},
+ {0xb8290000}, {0xb8294000}, {0xb8298000}, {0xb829c000},
+ {0xb82a0000}, {0xb82a4000}, {0xb82a8000}, {0xb82ac000},
+ {0xb82b0000}, {0xb82b4000}, {0xb82b8000}, {0xb82bc000},
+ {0xb82c0000}, {0xb82c4000}, {0xb82c8000}, {0xb82cc000},
+ {0xb82d0000}, {0xb82d4000}, {0xb82d8000}, {0xb82dc000},
+ {0xb82e0000}, {0xb82e4000}, {0xb82e8000}, {0xb82ec000},
+ {0xb82f0000}, {0xb82f4000}, {0xb82f8000}, {0xb82fc000},
+ {0xb8300000}, {0xb8304000}, {0xb8308000}, {0xb830c000},
+ {0xb8310000}, {0xb8314000}, {0xb8318000}, {0xb831c000},
+ {0xb8320000}, {0xb8324000}, {0xb8328000}, {0xb832c000},
+ {0xb8330000}, {0xb8334000}, {0xb8338000}, {0xb833c000},
+ {0xb8340000}, {0xb8344000}, {0xb8348000}, {0xb834c000},
+ {0xb8350000}, {0xb8354000}, {0xb8358000}, {0xb835c000},
+ {0xb8360000}, {0xb8364000}, {0xb8368000}, {0xb836c000},
+ {0xb8370000}, {0xb8374000}, {0xb8378000}, {0xb837c000},
+ {0xb8380000}, {0xb8384000}, {0xb8388000}, {0xb838c000},
+ {0xb8390000}, {0xb8394000}, {0xb8398000}, {0xb839c000},
+ {0xb83a0000}, {0xb83a4000}, {0xb83a8000}, {0xb83ac000},
+ {0xb83b0000}, {0xb83b4000}, {0xb83b8000}, {0xb83bc000},
+ {0xb83c0000}, {0xb83c4000}, {0xb83c8000}, {0xb83cc000},
+ {0xb83d0000}, {0xb83d4000}, {0xb83d8000}, {0xb83dc000},
+ {0xb83e0000}, {0xb83e4000}, {0xb83e8000}, {0xb83ec000},
+ {0xb83f0000}, {0xb83f4000}, {0xb83f8000}, {0xb83fc000},
+ {0xb8400000}, {0xb8404000}, {0xb8408000}, {0xb840c000},
+ {0xb8410000}, {0xb8414000}, {0xb8418000}, {0xb841c000},
+ {0xb8420000}, {0xb8424000}, {0xb8428000}, {0xb842c000},
+ {0xb8430000}, {0xb8434000}, {0xb8438000}, {0xb843c000},
+ {0xb8440000}, {0xb8444000}, {0xb8448000}, {0xb844c000},
+ {0xb8450000}, {0xb8454000}, {0xb8458000}, {0xb845c000},
+ {0xb8460000}, {0xb8464000}, {0xb8468000}, {0xb846c000},
+ {0xb8470000}, {0xb8474000}, {0xb8478000}, {0xb847c000},
+ {0xb8480000}, {0xb8484000}, {0xb8488000}, {0xb848c000},
+ {0xb8490000}, {0xb8494000}, {0xb8498000}, {0xb849c000},
+ {0xb84a0000}, {0xb84a4000}, {0xb84a8000}, {0xb84ac000},
+ {0xb84b0000}, {0xb84b4000}, {0xb84b8000}, {0xb84bc000},
+ {0xb84c0000}, {0xb84c4000}, {0xb84c8000}, {0xb84cc000},
+ {0xb84d0000}, {0xb84d4000}, {0xb84d8000}, {0xb84dc000},
+ {0xb84e0000}, {0xb84e4000}, {0xb84e8000}, {0xb84ec000},
+ {0xb84f0000}, {0xb84f4000}, {0xb84f8000}, {0xb84fc000},
+ {0xb8500000}, {0xb8504000}, {0xb8508000}, {0xb850c000},
+ {0xb8510000}, {0xb8514000}, {0xb8518000}, {0xb851c000},
+ {0xb8520000}, {0xb8524000}, {0xb8528000}, {0xb852c000},
+ {0xb8530000}, {0xb8534000}, {0xb8538000}, {0xb853c000},
+ {0xb8540000}, {0xb8544000}, {0xb8548000}, {0xb854c000},
+ {0xb8550000}, {0xb8554000}, {0xb8558000}, {0xb855c000},
+ {0xb8560000}, {0xb8564000}, {0xb8568000}, {0xb856c000},
+ {0xb8570000}, {0xb8574000}, {0xb8578000}, {0xb857c000},
+ {0xb8580000}, {0xb8584000}, {0xb8588000}, {0xb858c000},
+ {0xb8590000}, {0xb8594000}, {0xb8598000}, {0xb859c000},
+ {0xb85a0000}, {0xb85a4000}, {0xb85a8000}, {0xb85ac000},
+ {0xb85b0000}, {0xb85b4000}, {0xb85b8000}, {0xb85bc000},
+ {0xb85c0000}, {0xb85c4000}, {0xb85c8000}, {0xb85cc000},
+ {0xb85d0000}, {0xb85d4000}, {0xb85d8000}, {0xb85dc000},
+ {0xb85e0000}, {0xb85e4000}, {0xb85e8000}, {0xb85ec000},
+ {0xb85f0000}, {0xb85f4000}, {0xb85f8000}, {0xb85fc000},
+ {0xb8600000}, {0xb8604000}, {0xb8608000}, {0xb860c000},
+ {0xb8610000}, {0xb8614000}, {0xb8618000}, {0xb861c000},
+ {0xb8620000}, {0xb8624000}, {0xb8628000}, {0xb862c000},
+ {0xb8630000}, {0xb8634000}, {0xb8638000}, {0xb863c000},
+ {0xb8640000}, {0xb8644000}, {0xb8648000}, {0xb864c000},
+ {0xb8650000}, {0xb8654000}, {0xb8658000}, {0xb865c000},
+ {0xb8660000}, {0xb8664000}, {0xb8668000}, {0xb866c000},
+ {0xb8670000}, {0xb8674000}, {0xb8678000}, {0xb867c000},
+ {0xb8680000}, {0xb8684000}, {0xb8688000}, {0xb868c000},
+ {0xb8690000}, {0xb8694000}, {0xb8698000}, {0xb869c000},
+ {0xb86a0000}, {0xb86a4000}, {0xb86a8000}, {0xb86ac000},
+ {0xb86b0000}, {0xb86b4000}, {0xb86b8000}, {0xb86bc000},
+ {0xb86c0000}, {0xb86c4000}, {0xb86c8000}, {0xb86cc000},
+ {0xb86d0000}, {0xb86d4000}, {0xb86d8000}, {0xb86dc000},
+ {0xb86e0000}, {0xb86e4000}, {0xb86e8000}, {0xb86ec000},
+ {0xb86f0000}, {0xb86f4000}, {0xb86f8000}, {0xb86fc000},
+ {0xb8700000}, {0xb8704000}, {0xb8708000}, {0xb870c000},
+ {0xb8710000}, {0xb8714000}, {0xb8718000}, {0xb871c000},
+ {0xb8720000}, {0xb8724000}, {0xb8728000}, {0xb872c000},
+ {0xb8730000}, {0xb8734000}, {0xb8738000}, {0xb873c000},
+ {0xb8740000}, {0xb8744000}, {0xb8748000}, {0xb874c000},
+ {0xb8750000}, {0xb8754000}, {0xb8758000}, {0xb875c000},
+ {0xb8760000}, {0xb8764000}, {0xb8768000}, {0xb876c000},
+ {0xb8770000}, {0xb8774000}, {0xb8778000}, {0xb877c000},
+ {0xb8780000}, {0xb8784000}, {0xb8788000}, {0xb878c000},
+ {0xb8790000}, {0xb8794000}, {0xb8798000}, {0xb879c000},
+ {0xb87a0000}, {0xb87a4000}, {0xb87a8000}, {0xb87ac000},
+ {0xb87b0000}, {0xb87b4000}, {0xb87b8000}, {0xb87bc000},
+ {0xb87c0000}, {0xb87c4000}, {0xb87c8000}, {0xb87cc000},
+ {0xb87d0000}, {0xb87d4000}, {0xb87d8000}, {0xb87dc000},
+ {0xb87e0000}, {0xb87e4000}, {0xb87e8000}, {0xb87ec000},
+ {0xb87f0000}, {0xb87f4000}, {0xb87f8000}, {0xb87fc000},
+ {0xb8800000}, {0xb8802000}, {0xb8804000}, {0xb8806000},
+ {0xb8808000}, {0xb880a000}, {0xb880c000}, {0xb880e000},
+ {0xb8810000}, {0xb8812000}, {0xb8814000}, {0xb8816000},
+ {0xb8818000}, {0xb881a000}, {0xb881c000}, {0xb881e000},
+ {0xb8820000}, {0xb8822000}, {0xb8824000}, {0xb8826000},
+ {0xb8828000}, {0xb882a000}, {0xb882c000}, {0xb882e000},
+ {0xb8830000}, {0xb8832000}, {0xb8834000}, {0xb8836000},
+ {0xb8838000}, {0xb883a000}, {0xb883c000}, {0xb883e000},
+ {0xb8840000}, {0xb8842000}, {0xb8844000}, {0xb8846000},
+ {0xb8848000}, {0xb884a000}, {0xb884c000}, {0xb884e000},
+ {0xb8850000}, {0xb8852000}, {0xb8854000}, {0xb8856000},
+ {0xb8858000}, {0xb885a000}, {0xb885c000}, {0xb885e000},
+ {0xb8860000}, {0xb8862000}, {0xb8864000}, {0xb8866000},
+ {0xb8868000}, {0xb886a000}, {0xb886c000}, {0xb886e000},
+ {0xb8870000}, {0xb8872000}, {0xb8874000}, {0xb8876000},
+ {0xb8878000}, {0xb887a000}, {0xb887c000}, {0xb887e000},
+ {0xb8880000}, {0xb8882000}, {0xb8884000}, {0xb8886000},
+ {0xb8888000}, {0xb888a000}, {0xb888c000}, {0xb888e000},
+ {0xb8890000}, {0xb8892000}, {0xb8894000}, {0xb8896000},
+ {0xb8898000}, {0xb889a000}, {0xb889c000}, {0xb889e000},
+ {0xb88a0000}, {0xb88a2000}, {0xb88a4000}, {0xb88a6000},
+ {0xb88a8000}, {0xb88aa000}, {0xb88ac000}, {0xb88ae000},
+ {0xb88b0000}, {0xb88b2000}, {0xb88b4000}, {0xb88b6000},
+ {0xb88b8000}, {0xb88ba000}, {0xb88bc000}, {0xb88be000},
+ {0xb88c0000}, {0xb88c2000}, {0xb88c4000}, {0xb88c6000},
+ {0xb88c8000}, {0xb88ca000}, {0xb88cc000}, {0xb88ce000},
+ {0xb88d0000}, {0xb88d2000}, {0xb88d4000}, {0xb88d6000},
+ {0xb88d8000}, {0xb88da000}, {0xb88dc000}, {0xb88de000},
+ {0xb88e0000}, {0xb88e2000}, {0xb88e4000}, {0xb88e6000},
+ {0xb88e8000}, {0xb88ea000}, {0xb88ec000}, {0xb88ee000},
+ {0xb88f0000}, {0xb88f2000}, {0xb88f4000}, {0xb88f6000},
+ {0xb88f8000}, {0xb88fa000}, {0xb88fc000}, {0xb88fe000},
+ {0xb8900000}, {0xb8902000}, {0xb8904000}, {0xb8906000},
+ {0xb8908000}, {0xb890a000}, {0xb890c000}, {0xb890e000},
+ {0xb8910000}, {0xb8912000}, {0xb8914000}, {0xb8916000},
+ {0xb8918000}, {0xb891a000}, {0xb891c000}, {0xb891e000},
+ {0xb8920000}, {0xb8922000}, {0xb8924000}, {0xb8926000},
+ {0xb8928000}, {0xb892a000}, {0xb892c000}, {0xb892e000},
+ {0xb8930000}, {0xb8932000}, {0xb8934000}, {0xb8936000},
+ {0xb8938000}, {0xb893a000}, {0xb893c000}, {0xb893e000},
+ {0xb8940000}, {0xb8942000}, {0xb8944000}, {0xb8946000},
+ {0xb8948000}, {0xb894a000}, {0xb894c000}, {0xb894e000},
+ {0xb8950000}, {0xb8952000}, {0xb8954000}, {0xb8956000},
+ {0xb8958000}, {0xb895a000}, {0xb895c000}, {0xb895e000},
+ {0xb8960000}, {0xb8962000}, {0xb8964000}, {0xb8966000},
+ {0xb8968000}, {0xb896a000}, {0xb896c000}, {0xb896e000},
+ {0xb8970000}, {0xb8972000}, {0xb8974000}, {0xb8976000},
+ {0xb8978000}, {0xb897a000}, {0xb897c000}, {0xb897e000},
+ {0xb8980000}, {0xb8982000}, {0xb8984000}, {0xb8986000},
+ {0xb8988000}, {0xb898a000}, {0xb898c000}, {0xb898e000},
+ {0xb8990000}, {0xb8992000}, {0xb8994000}, {0xb8996000},
+ {0xb8998000}, {0xb899a000}, {0xb899c000}, {0xb899e000},
+ {0xb89a0000}, {0xb89a2000}, {0xb89a4000}, {0xb89a6000},
+ {0xb89a8000}, {0xb89aa000}, {0xb89ac000}, {0xb89ae000},
+ {0xb89b0000}, {0xb89b2000}, {0xb89b4000}, {0xb89b6000},
+ {0xb89b8000}, {0xb89ba000}, {0xb89bc000}, {0xb89be000},
+ {0xb89c0000}, {0xb89c2000}, {0xb89c4000}, {0xb89c6000},
+ {0xb89c8000}, {0xb89ca000}, {0xb89cc000}, {0xb89ce000},
+ {0xb89d0000}, {0xb89d2000}, {0xb89d4000}, {0xb89d6000},
+ {0xb89d8000}, {0xb89da000}, {0xb89dc000}, {0xb89de000},
+ {0xb89e0000}, {0xb89e2000}, {0xb89e4000}, {0xb89e6000},
+ {0xb89e8000}, {0xb89ea000}, {0xb89ec000}, {0xb89ee000},
+ {0xb89f0000}, {0xb89f2000}, {0xb89f4000}, {0xb89f6000},
+ {0xb89f8000}, {0xb89fa000}, {0xb89fc000}, {0xb89fe000},
+ {0xb8a00000}, {0xb8a02000}, {0xb8a04000}, {0xb8a06000},
+ {0xb8a08000}, {0xb8a0a000}, {0xb8a0c000}, {0xb8a0e000},
+ {0xb8a10000}, {0xb8a12000}, {0xb8a14000}, {0xb8a16000},
+ {0xb8a18000}, {0xb8a1a000}, {0xb8a1c000}, {0xb8a1e000},
+ {0xb8a20000}, {0xb8a22000}, {0xb8a24000}, {0xb8a26000},
+ {0xb8a28000}, {0xb8a2a000}, {0xb8a2c000}, {0xb8a2e000},
+ {0xb8a30000}, {0xb8a32000}, {0xb8a34000}, {0xb8a36000},
+ {0xb8a38000}, {0xb8a3a000}, {0xb8a3c000}, {0xb8a3e000},
+ {0xb8a40000}, {0xb8a42000}, {0xb8a44000}, {0xb8a46000},
+ {0xb8a48000}, {0xb8a4a000}, {0xb8a4c000}, {0xb8a4e000},
+ {0xb8a50000}, {0xb8a52000}, {0xb8a54000}, {0xb8a56000},
+ {0xb8a58000}, {0xb8a5a000}, {0xb8a5c000}, {0xb8a5e000},
+ {0xb8a60000}, {0xb8a62000}, {0xb8a64000}, {0xb8a66000},
+ {0xb8a68000}, {0xb8a6a000}, {0xb8a6c000}, {0xb8a6e000},
+ {0xb8a70000}, {0xb8a72000}, {0xb8a74000}, {0xb8a76000},
+ {0xb8a78000}, {0xb8a7a000}, {0xb8a7c000}, {0xb8a7e000},
+ {0xb8a80000}, {0xb8a82000}, {0xb8a84000}, {0xb8a86000},
+ {0xb8a88000}, {0xb8a8a000}, {0xb8a8c000}, {0xb8a8e000},
+ {0xb8a90000}, {0xb8a92000}, {0xb8a94000}, {0xb8a96000},
+ {0xb8a98000}, {0xb8a9a000}, {0xb8a9c000}, {0xb8a9e000},
+ {0xb8aa0000}, {0xb8aa2000}, {0xb8aa4000}, {0xb8aa6000},
+ {0xb8aa8000}, {0xb8aaa000}, {0xb8aac000}, {0xb8aae000},
+ {0xb8ab0000}, {0xb8ab2000}, {0xb8ab4000}, {0xb8ab6000},
+ {0xb8ab8000}, {0xb8aba000}, {0xb8abc000}, {0xb8abe000},
+ {0xb8ac0000}, {0xb8ac2000}, {0xb8ac4000}, {0xb8ac6000},
+ {0xb8ac8000}, {0xb8aca000}, {0xb8acc000}, {0xb8ace000},
+ {0xb8ad0000}, {0xb8ad2000}, {0xb8ad4000}, {0xb8ad6000},
+ {0xb8ad8000}, {0xb8ada000}, {0xb8adc000}, {0xb8ade000},
+ {0xb8ae0000}, {0xb8ae2000}, {0xb8ae4000}, {0xb8ae6000},
+ {0xb8ae8000}, {0xb8aea000}, {0xb8aec000}, {0xb8aee000},
+ {0xb8af0000}, {0xb8af2000}, {0xb8af4000}, {0xb8af6000},
+ {0xb8af8000}, {0xb8afa000}, {0xb8afc000}, {0xb8afe000},
+ {0xb8b00000}, {0xb8b02000}, {0xb8b04000}, {0xb8b06000},
+ {0xb8b08000}, {0xb8b0a000}, {0xb8b0c000}, {0xb8b0e000},
+ {0xb8b10000}, {0xb8b12000}, {0xb8b14000}, {0xb8b16000},
+ {0xb8b18000}, {0xb8b1a000}, {0xb8b1c000}, {0xb8b1e000},
+ {0xb8b20000}, {0xb8b22000}, {0xb8b24000}, {0xb8b26000},
+ {0xb8b28000}, {0xb8b2a000}, {0xb8b2c000}, {0xb8b2e000},
+ {0xb8b30000}, {0xb8b32000}, {0xb8b34000}, {0xb8b36000},
+ {0xb8b38000}, {0xb8b3a000}, {0xb8b3c000}, {0xb8b3e000},
+ {0xb8b40000}, {0xb8b42000}, {0xb8b44000}, {0xb8b46000},
+ {0xb8b48000}, {0xb8b4a000}, {0xb8b4c000}, {0xb8b4e000},
+ {0xb8b50000}, {0xb8b52000}, {0xb8b54000}, {0xb8b56000},
+ {0xb8b58000}, {0xb8b5a000}, {0xb8b5c000}, {0xb8b5e000},
+ {0xb8b60000}, {0xb8b62000}, {0xb8b64000}, {0xb8b66000},
+ {0xb8b68000}, {0xb8b6a000}, {0xb8b6c000}, {0xb8b6e000},
+ {0xb8b70000}, {0xb8b72000}, {0xb8b74000}, {0xb8b76000},
+ {0xb8b78000}, {0xb8b7a000}, {0xb8b7c000}, {0xb8b7e000},
+ {0xb8b80000}, {0xb8b82000}, {0xb8b84000}, {0xb8b86000},
+ {0xb8b88000}, {0xb8b8a000}, {0xb8b8c000}, {0xb8b8e000},
+ {0xb8b90000}, {0xb8b92000}, {0xb8b94000}, {0xb8b96000},
+ {0xb8b98000}, {0xb8b9a000}, {0xb8b9c000}, {0xb8b9e000},
+ {0xb8ba0000}, {0xb8ba2000}, {0xb8ba4000}, {0xb8ba6000},
+ {0xb8ba8000}, {0xb8baa000}, {0xb8bac000}, {0xb8bae000},
+ {0xb8bb0000}, {0xb8bb2000}, {0xb8bb4000}, {0xb8bb6000},
+ {0xb8bb8000}, {0xb8bba000}, {0xb8bbc000}, {0xb8bbe000},
+ {0xb8bc0000}, {0xb8bc2000}, {0xb8bc4000}, {0xb8bc6000},
+ {0xb8bc8000}, {0xb8bca000}, {0xb8bcc000}, {0xb8bce000},
+ {0xb8bd0000}, {0xb8bd2000}, {0xb8bd4000}, {0xb8bd6000},
+ {0xb8bd8000}, {0xb8bda000}, {0xb8bdc000}, {0xb8bde000},
+ {0xb8be0000}, {0xb8be2000}, {0xb8be4000}, {0xb8be6000},
+ {0xb8be8000}, {0xb8bea000}, {0xb8bec000}, {0xb8bee000},
+ {0xb8bf0000}, {0xb8bf2000}, {0xb8bf4000}, {0xb8bf6000},
+ {0xb8bf8000}, {0xb8bfa000}, {0xb8bfc000}, {0xb8bfe000},
+ {0xb8c00000}, {0xb8c02000}, {0xb8c04000}, {0xb8c06000},
+ {0xb8c08000}, {0xb8c0a000}, {0xb8c0c000}, {0xb8c0e000},
+ {0xb8c10000}, {0xb8c12000}, {0xb8c14000}, {0xb8c16000},
+ {0xb8c18000}, {0xb8c1a000}, {0xb8c1c000}, {0xb8c1e000},
+ {0xb8c20000}, {0xb8c22000}, {0xb8c24000}, {0xb8c26000},
+ {0xb8c28000}, {0xb8c2a000}, {0xb8c2c000}, {0xb8c2e000},
+ {0xb8c30000}, {0xb8c32000}, {0xb8c34000}, {0xb8c36000},
+ {0xb8c38000}, {0xb8c3a000}, {0xb8c3c000}, {0xb8c3e000},
+ {0xb8c40000}, {0xb8c42000}, {0xb8c44000}, {0xb8c46000},
+ {0xb8c48000}, {0xb8c4a000}, {0xb8c4c000}, {0xb8c4e000},
+ {0xb8c50000}, {0xb8c52000}, {0xb8c54000}, {0xb8c56000},
+ {0xb8c58000}, {0xb8c5a000}, {0xb8c5c000}, {0xb8c5e000},
+ {0xb8c60000}, {0xb8c62000}, {0xb8c64000}, {0xb8c66000},
+ {0xb8c68000}, {0xb8c6a000}, {0xb8c6c000}, {0xb8c6e000},
+ {0xb8c70000}, {0xb8c72000}, {0xb8c74000}, {0xb8c76000},
+ {0xb8c78000}, {0xb8c7a000}, {0xb8c7c000}, {0xb8c7e000},
+ {0xb8c80000}, {0xb8c82000}, {0xb8c84000}, {0xb8c86000},
+ {0xb8c88000}, {0xb8c8a000}, {0xb8c8c000}, {0xb8c8e000},
+ {0xb8c90000}, {0xb8c92000}, {0xb8c94000}, {0xb8c96000},
+ {0xb8c98000}, {0xb8c9a000}, {0xb8c9c000}, {0xb8c9e000},
+ {0xb8ca0000}, {0xb8ca2000}, {0xb8ca4000}, {0xb8ca6000},
+ {0xb8ca8000}, {0xb8caa000}, {0xb8cac000}, {0xb8cae000},
+ {0xb8cb0000}, {0xb8cb2000}, {0xb8cb4000}, {0xb8cb6000},
+ {0xb8cb8000}, {0xb8cba000}, {0xb8cbc000}, {0xb8cbe000},
+ {0xb8cc0000}, {0xb8cc2000}, {0xb8cc4000}, {0xb8cc6000},
+ {0xb8cc8000}, {0xb8cca000}, {0xb8ccc000}, {0xb8cce000},
+ {0xb8cd0000}, {0xb8cd2000}, {0xb8cd4000}, {0xb8cd6000},
+ {0xb8cd8000}, {0xb8cda000}, {0xb8cdc000}, {0xb8cde000},
+ {0xb8ce0000}, {0xb8ce2000}, {0xb8ce4000}, {0xb8ce6000},
+ {0xb8ce8000}, {0xb8cea000}, {0xb8cec000}, {0xb8cee000},
+ {0xb8cf0000}, {0xb8cf2000}, {0xb8cf4000}, {0xb8cf6000},
+ {0xb8cf8000}, {0xb8cfa000}, {0xb8cfc000}, {0xb8cfe000},
+ {0xb8d00000}, {0xb8d02000}, {0xb8d04000}, {0xb8d06000},
+ {0xb8d08000}, {0xb8d0a000}, {0xb8d0c000}, {0xb8d0e000},
+ {0xb8d10000}, {0xb8d12000}, {0xb8d14000}, {0xb8d16000},
+ {0xb8d18000}, {0xb8d1a000}, {0xb8d1c000}, {0xb8d1e000},
+ {0xb8d20000}, {0xb8d22000}, {0xb8d24000}, {0xb8d26000},
+ {0xb8d28000}, {0xb8d2a000}, {0xb8d2c000}, {0xb8d2e000},
+ {0xb8d30000}, {0xb8d32000}, {0xb8d34000}, {0xb8d36000},
+ {0xb8d38000}, {0xb8d3a000}, {0xb8d3c000}, {0xb8d3e000},
+ {0xb8d40000}, {0xb8d42000}, {0xb8d44000}, {0xb8d46000},
+ {0xb8d48000}, {0xb8d4a000}, {0xb8d4c000}, {0xb8d4e000},
+ {0xb8d50000}, {0xb8d52000}, {0xb8d54000}, {0xb8d56000},
+ {0xb8d58000}, {0xb8d5a000}, {0xb8d5c000}, {0xb8d5e000},
+ {0xb8d60000}, {0xb8d62000}, {0xb8d64000}, {0xb8d66000},
+ {0xb8d68000}, {0xb8d6a000}, {0xb8d6c000}, {0xb8d6e000},
+ {0xb8d70000}, {0xb8d72000}, {0xb8d74000}, {0xb8d76000},
+ {0xb8d78000}, {0xb8d7a000}, {0xb8d7c000}, {0xb8d7e000},
+ {0xb8d80000}, {0xb8d82000}, {0xb8d84000}, {0xb8d86000},
+ {0xb8d88000}, {0xb8d8a000}, {0xb8d8c000}, {0xb8d8e000},
+ {0xb8d90000}, {0xb8d92000}, {0xb8d94000}, {0xb8d96000},
+ {0xb8d98000}, {0xb8d9a000}, {0xb8d9c000}, {0xb8d9e000},
+ {0xb8da0000}, {0xb8da2000}, {0xb8da4000}, {0xb8da6000},
+ {0xb8da8000}, {0xb8daa000}, {0xb8dac000}, {0xb8dae000},
+ {0xb8db0000}, {0xb8db2000}, {0xb8db4000}, {0xb8db6000},
+ {0xb8db8000}, {0xb8dba000}, {0xb8dbc000}, {0xb8dbe000},
+ {0xb8dc0000}, {0xb8dc2000}, {0xb8dc4000}, {0xb8dc6000},
+ {0xb8dc8000}, {0xb8dca000}, {0xb8dcc000}, {0xb8dce000},
+ {0xb8dd0000}, {0xb8dd2000}, {0xb8dd4000}, {0xb8dd6000},
+ {0xb8dd8000}, {0xb8dda000}, {0xb8ddc000}, {0xb8dde000},
+ {0xb8de0000}, {0xb8de2000}, {0xb8de4000}, {0xb8de6000},
+ {0xb8de8000}, {0xb8dea000}, {0xb8dec000}, {0xb8dee000},
+ {0xb8df0000}, {0xb8df2000}, {0xb8df4000}, {0xb8df6000},
+ {0xb8df8000}, {0xb8dfa000}, {0xb8dfc000}, {0xb8dfe000},
+ {0xb8e00000}, {0xb8e02000}, {0xb8e04000}, {0xb8e06000},
+ {0xb8e08000}, {0xb8e0a000}, {0xb8e0c000}, {0xb8e0e000},
+ {0xb8e10000}, {0xb8e12000}, {0xb8e14000}, {0xb8e16000},
+ {0xb8e18000}, {0xb8e1a000}, {0xb8e1c000}, {0xb8e1e000},
+ {0xb8e20000}, {0xb8e22000}, {0xb8e24000}, {0xb8e26000},
+ {0xb8e28000}, {0xb8e2a000}, {0xb8e2c000}, {0xb8e2e000},
+ {0xb8e30000}, {0xb8e32000}, {0xb8e34000}, {0xb8e36000},
+ {0xb8e38000}, {0xb8e3a000}, {0xb8e3c000}, {0xb8e3e000},
+ {0xb8e40000}, {0xb8e42000}, {0xb8e44000}, {0xb8e46000},
+ {0xb8e48000}, {0xb8e4a000}, {0xb8e4c000}, {0xb8e4e000},
+ {0xb8e50000}, {0xb8e52000}, {0xb8e54000}, {0xb8e56000},
+ {0xb8e58000}, {0xb8e5a000}, {0xb8e5c000}, {0xb8e5e000},
+ {0xb8e60000}, {0xb8e62000}, {0xb8e64000}, {0xb8e66000},
+ {0xb8e68000}, {0xb8e6a000}, {0xb8e6c000}, {0xb8e6e000},
+ {0xb8e70000}, {0xb8e72000}, {0xb8e74000}, {0xb8e76000},
+ {0xb8e78000}, {0xb8e7a000}, {0xb8e7c000}, {0xb8e7e000},
+ {0xb8e80000}, {0xb8e82000}, {0xb8e84000}, {0xb8e86000},
+ {0xb8e88000}, {0xb8e8a000}, {0xb8e8c000}, {0xb8e8e000},
+ {0xb8e90000}, {0xb8e92000}, {0xb8e94000}, {0xb8e96000},
+ {0xb8e98000}, {0xb8e9a000}, {0xb8e9c000}, {0xb8e9e000},
+ {0xb8ea0000}, {0xb8ea2000}, {0xb8ea4000}, {0xb8ea6000},
+ {0xb8ea8000}, {0xb8eaa000}, {0xb8eac000}, {0xb8eae000},
+ {0xb8eb0000}, {0xb8eb2000}, {0xb8eb4000}, {0xb8eb6000},
+ {0xb8eb8000}, {0xb8eba000}, {0xb8ebc000}, {0xb8ebe000},
+ {0xb8ec0000}, {0xb8ec2000}, {0xb8ec4000}, {0xb8ec6000},
+ {0xb8ec8000}, {0xb8eca000}, {0xb8ecc000}, {0xb8ece000},
+ {0xb8ed0000}, {0xb8ed2000}, {0xb8ed4000}, {0xb8ed6000},
+ {0xb8ed8000}, {0xb8eda000}, {0xb8edc000}, {0xb8ede000},
+ {0xb8ee0000}, {0xb8ee2000}, {0xb8ee4000}, {0xb8ee6000},
+ {0xb8ee8000}, {0xb8eea000}, {0xb8eec000}, {0xb8eee000},
+ {0xb8ef0000}, {0xb8ef2000}, {0xb8ef4000}, {0xb8ef6000},
+ {0xb8ef8000}, {0xb8efa000}, {0xb8efc000}, {0xb8efe000},
+ {0xb8f00000}, {0xb8f02000}, {0xb8f04000}, {0xb8f06000},
+ {0xb8f08000}, {0xb8f0a000}, {0xb8f0c000}, {0xb8f0e000},
+ {0xb8f10000}, {0xb8f12000}, {0xb8f14000}, {0xb8f16000},
+ {0xb8f18000}, {0xb8f1a000}, {0xb8f1c000}, {0xb8f1e000},
+ {0xb8f20000}, {0xb8f22000}, {0xb8f24000}, {0xb8f26000},
+ {0xb8f28000}, {0xb8f2a000}, {0xb8f2c000}, {0xb8f2e000},
+ {0xb8f30000}, {0xb8f32000}, {0xb8f34000}, {0xb8f36000},
+ {0xb8f38000}, {0xb8f3a000}, {0xb8f3c000}, {0xb8f3e000},
+ {0xb8f40000}, {0xb8f42000}, {0xb8f44000}, {0xb8f46000},
+ {0xb8f48000}, {0xb8f4a000}, {0xb8f4c000}, {0xb8f4e000},
+ {0xb8f50000}, {0xb8f52000}, {0xb8f54000}, {0xb8f56000},
+ {0xb8f58000}, {0xb8f5a000}, {0xb8f5c000}, {0xb8f5e000},
+ {0xb8f60000}, {0xb8f62000}, {0xb8f64000}, {0xb8f66000},
+ {0xb8f68000}, {0xb8f6a000}, {0xb8f6c000}, {0xb8f6e000},
+ {0xb8f70000}, {0xb8f72000}, {0xb8f74000}, {0xb8f76000},
+ {0xb8f78000}, {0xb8f7a000}, {0xb8f7c000}, {0xb8f7e000},
+ {0xb8f80000}, {0xb8f82000}, {0xb8f84000}, {0xb8f86000},
+ {0xb8f88000}, {0xb8f8a000}, {0xb8f8c000}, {0xb8f8e000},
+ {0xb8f90000}, {0xb8f92000}, {0xb8f94000}, {0xb8f96000},
+ {0xb8f98000}, {0xb8f9a000}, {0xb8f9c000}, {0xb8f9e000},
+ {0xb8fa0000}, {0xb8fa2000}, {0xb8fa4000}, {0xb8fa6000},
+ {0xb8fa8000}, {0xb8faa000}, {0xb8fac000}, {0xb8fae000},
+ {0xb8fb0000}, {0xb8fb2000}, {0xb8fb4000}, {0xb8fb6000},
+ {0xb8fb8000}, {0xb8fba000}, {0xb8fbc000}, {0xb8fbe000},
+ {0xb8fc0000}, {0xb8fc2000}, {0xb8fc4000}, {0xb8fc6000},
+ {0xb8fc8000}, {0xb8fca000}, {0xb8fcc000}, {0xb8fce000},
+ {0xb8fd0000}, {0xb8fd2000}, {0xb8fd4000}, {0xb8fd6000},
+ {0xb8fd8000}, {0xb8fda000}, {0xb8fdc000}, {0xb8fde000},
+ {0xb8fe0000}, {0xb8fe2000}, {0xb8fe4000}, {0xb8fe6000},
+ {0xb8fe8000}, {0xb8fea000}, {0xb8fec000}, {0xb8fee000},
+ {0xb8ff0000}, {0xb8ff2000}, {0xb8ff4000}, {0xb8ff6000},
+ {0xb8ff8000}, {0xb8ffa000}, {0xb8ffc000}, {0xb8ffe000},
+ {0xb9000000}, {0xb9002000}, {0xb9004000}, {0xb9006000},
+ {0xb9008000}, {0xb900a000}, {0xb900c000}, {0xb900e000},
+ {0xb9010000}, {0xb9012000}, {0xb9014000}, {0xb9016000},
+ {0xb9018000}, {0xb901a000}, {0xb901c000}, {0xb901e000},
+ {0xb9020000}, {0xb9022000}, {0xb9024000}, {0xb9026000},
+ {0xb9028000}, {0xb902a000}, {0xb902c000}, {0xb902e000},
+ {0xb9030000}, {0xb9032000}, {0xb9034000}, {0xb9036000},
+ {0xb9038000}, {0xb903a000}, {0xb903c000}, {0xb903e000},
+ {0xb9040000}, {0xb9042000}, {0xb9044000}, {0xb9046000},
+ {0xb9048000}, {0xb904a000}, {0xb904c000}, {0xb904e000},
+ {0xb9050000}, {0xb9052000}, {0xb9054000}, {0xb9056000},
+ {0xb9058000}, {0xb905a000}, {0xb905c000}, {0xb905e000},
+ {0xb9060000}, {0xb9062000}, {0xb9064000}, {0xb9066000},
+ {0xb9068000}, {0xb906a000}, {0xb906c000}, {0xb906e000},
+ {0xb9070000}, {0xb9072000}, {0xb9074000}, {0xb9076000},
+ {0xb9078000}, {0xb907a000}, {0xb907c000}, {0xb907e000},
+ {0xb9080000}, {0xb9082000}, {0xb9084000}, {0xb9086000},
+ {0xb9088000}, {0xb908a000}, {0xb908c000}, {0xb908e000},
+ {0xb9090000}, {0xb9092000}, {0xb9094000}, {0xb9096000},
+ {0xb9098000}, {0xb909a000}, {0xb909c000}, {0xb909e000},
+ {0xb90a0000}, {0xb90a2000}, {0xb90a4000}, {0xb90a6000},
+ {0xb90a8000}, {0xb90aa000}, {0xb90ac000}, {0xb90ae000},
+ {0xb90b0000}, {0xb90b2000}, {0xb90b4000}, {0xb90b6000},
+ {0xb90b8000}, {0xb90ba000}, {0xb90bc000}, {0xb90be000},
+ {0xb90c0000}, {0xb90c2000}, {0xb90c4000}, {0xb90c6000},
+ {0xb90c8000}, {0xb90ca000}, {0xb90cc000}, {0xb90ce000},
+ {0xb90d0000}, {0xb90d2000}, {0xb90d4000}, {0xb90d6000},
+ {0xb90d8000}, {0xb90da000}, {0xb90dc000}, {0xb90de000},
+ {0xb90e0000}, {0xb90e2000}, {0xb90e4000}, {0xb90e6000},
+ {0xb90e8000}, {0xb90ea000}, {0xb90ec000}, {0xb90ee000},
+ {0xb90f0000}, {0xb90f2000}, {0xb90f4000}, {0xb90f6000},
+ {0xb90f8000}, {0xb90fa000}, {0xb90fc000}, {0xb90fe000},
+ {0xb9100000}, {0xb9102000}, {0xb9104000}, {0xb9106000},
+ {0xb9108000}, {0xb910a000}, {0xb910c000}, {0xb910e000},
+ {0xb9110000}, {0xb9112000}, {0xb9114000}, {0xb9116000},
+ {0xb9118000}, {0xb911a000}, {0xb911c000}, {0xb911e000},
+ {0xb9120000}, {0xb9122000}, {0xb9124000}, {0xb9126000},
+ {0xb9128000}, {0xb912a000}, {0xb912c000}, {0xb912e000},
+ {0xb9130000}, {0xb9132000}, {0xb9134000}, {0xb9136000},
+ {0xb9138000}, {0xb913a000}, {0xb913c000}, {0xb913e000},
+ {0xb9140000}, {0xb9142000}, {0xb9144000}, {0xb9146000},
+ {0xb9148000}, {0xb914a000}, {0xb914c000}, {0xb914e000},
+ {0xb9150000}, {0xb9152000}, {0xb9154000}, {0xb9156000},
+ {0xb9158000}, {0xb915a000}, {0xb915c000}, {0xb915e000},
+ {0xb9160000}, {0xb9162000}, {0xb9164000}, {0xb9166000},
+ {0xb9168000}, {0xb916a000}, {0xb916c000}, {0xb916e000},
+ {0xb9170000}, {0xb9172000}, {0xb9174000}, {0xb9176000},
+ {0xb9178000}, {0xb917a000}, {0xb917c000}, {0xb917e000},
+ {0xb9180000}, {0xb9182000}, {0xb9184000}, {0xb9186000},
+ {0xb9188000}, {0xb918a000}, {0xb918c000}, {0xb918e000},
+ {0xb9190000}, {0xb9192000}, {0xb9194000}, {0xb9196000},
+ {0xb9198000}, {0xb919a000}, {0xb919c000}, {0xb919e000},
+ {0xb91a0000}, {0xb91a2000}, {0xb91a4000}, {0xb91a6000},
+ {0xb91a8000}, {0xb91aa000}, {0xb91ac000}, {0xb91ae000},
+ {0xb91b0000}, {0xb91b2000}, {0xb91b4000}, {0xb91b6000},
+ {0xb91b8000}, {0xb91ba000}, {0xb91bc000}, {0xb91be000},
+ {0xb91c0000}, {0xb91c2000}, {0xb91c4000}, {0xb91c6000},
+ {0xb91c8000}, {0xb91ca000}, {0xb91cc000}, {0xb91ce000},
+ {0xb91d0000}, {0xb91d2000}, {0xb91d4000}, {0xb91d6000},
+ {0xb91d8000}, {0xb91da000}, {0xb91dc000}, {0xb91de000},
+ {0xb91e0000}, {0xb91e2000}, {0xb91e4000}, {0xb91e6000},
+ {0xb91e8000}, {0xb91ea000}, {0xb91ec000}, {0xb91ee000},
+ {0xb91f0000}, {0xb91f2000}, {0xb91f4000}, {0xb91f6000},
+ {0xb91f8000}, {0xb91fa000}, {0xb91fc000}, {0xb91fe000},
+ {0xb9200000}, {0xb9202000}, {0xb9204000}, {0xb9206000},
+ {0xb9208000}, {0xb920a000}, {0xb920c000}, {0xb920e000},
+ {0xb9210000}, {0xb9212000}, {0xb9214000}, {0xb9216000},
+ {0xb9218000}, {0xb921a000}, {0xb921c000}, {0xb921e000},
+ {0xb9220000}, {0xb9222000}, {0xb9224000}, {0xb9226000},
+ {0xb9228000}, {0xb922a000}, {0xb922c000}, {0xb922e000},
+ {0xb9230000}, {0xb9232000}, {0xb9234000}, {0xb9236000},
+ {0xb9238000}, {0xb923a000}, {0xb923c000}, {0xb923e000},
+ {0xb9240000}, {0xb9242000}, {0xb9244000}, {0xb9246000},
+ {0xb9248000}, {0xb924a000}, {0xb924c000}, {0xb924e000},
+ {0xb9250000}, {0xb9252000}, {0xb9254000}, {0xb9256000},
+ {0xb9258000}, {0xb925a000}, {0xb925c000}, {0xb925e000},
+ {0xb9260000}, {0xb9262000}, {0xb9264000}, {0xb9266000},
+ {0xb9268000}, {0xb926a000}, {0xb926c000}, {0xb926e000},
+ {0xb9270000}, {0xb9272000}, {0xb9274000}, {0xb9276000},
+ {0xb9278000}, {0xb927a000}, {0xb927c000}, {0xb927e000},
+ {0xb9280000}, {0xb9282000}, {0xb9284000}, {0xb9286000},
+ {0xb9288000}, {0xb928a000}, {0xb928c000}, {0xb928e000},
+ {0xb9290000}, {0xb9292000}, {0xb9294000}, {0xb9296000},
+ {0xb9298000}, {0xb929a000}, {0xb929c000}, {0xb929e000},
+ {0xb92a0000}, {0xb92a2000}, {0xb92a4000}, {0xb92a6000},
+ {0xb92a8000}, {0xb92aa000}, {0xb92ac000}, {0xb92ae000},
+ {0xb92b0000}, {0xb92b2000}, {0xb92b4000}, {0xb92b6000},
+ {0xb92b8000}, {0xb92ba000}, {0xb92bc000}, {0xb92be000},
+ {0xb92c0000}, {0xb92c2000}, {0xb92c4000}, {0xb92c6000},
+ {0xb92c8000}, {0xb92ca000}, {0xb92cc000}, {0xb92ce000},
+ {0xb92d0000}, {0xb92d2000}, {0xb92d4000}, {0xb92d6000},
+ {0xb92d8000}, {0xb92da000}, {0xb92dc000}, {0xb92de000},
+ {0xb92e0000}, {0xb92e2000}, {0xb92e4000}, {0xb92e6000},
+ {0xb92e8000}, {0xb92ea000}, {0xb92ec000}, {0xb92ee000},
+ {0xb92f0000}, {0xb92f2000}, {0xb92f4000}, {0xb92f6000},
+ {0xb92f8000}, {0xb92fa000}, {0xb92fc000}, {0xb92fe000},
+ {0xb9300000}, {0xb9302000}, {0xb9304000}, {0xb9306000},
+ {0xb9308000}, {0xb930a000}, {0xb930c000}, {0xb930e000},
+ {0xb9310000}, {0xb9312000}, {0xb9314000}, {0xb9316000},
+ {0xb9318000}, {0xb931a000}, {0xb931c000}, {0xb931e000},
+ {0xb9320000}, {0xb9322000}, {0xb9324000}, {0xb9326000},
+ {0xb9328000}, {0xb932a000}, {0xb932c000}, {0xb932e000},
+ {0xb9330000}, {0xb9332000}, {0xb9334000}, {0xb9336000},
+ {0xb9338000}, {0xb933a000}, {0xb933c000}, {0xb933e000},
+ {0xb9340000}, {0xb9342000}, {0xb9344000}, {0xb9346000},
+ {0xb9348000}, {0xb934a000}, {0xb934c000}, {0xb934e000},
+ {0xb9350000}, {0xb9352000}, {0xb9354000}, {0xb9356000},
+ {0xb9358000}, {0xb935a000}, {0xb935c000}, {0xb935e000},
+ {0xb9360000}, {0xb9362000}, {0xb9364000}, {0xb9366000},
+ {0xb9368000}, {0xb936a000}, {0xb936c000}, {0xb936e000},
+ {0xb9370000}, {0xb9372000}, {0xb9374000}, {0xb9376000},
+ {0xb9378000}, {0xb937a000}, {0xb937c000}, {0xb937e000},
+ {0xb9380000}, {0xb9382000}, {0xb9384000}, {0xb9386000},
+ {0xb9388000}, {0xb938a000}, {0xb938c000}, {0xb938e000},
+ {0xb9390000}, {0xb9392000}, {0xb9394000}, {0xb9396000},
+ {0xb9398000}, {0xb939a000}, {0xb939c000}, {0xb939e000},
+ {0xb93a0000}, {0xb93a2000}, {0xb93a4000}, {0xb93a6000},
+ {0xb93a8000}, {0xb93aa000}, {0xb93ac000}, {0xb93ae000},
+ {0xb93b0000}, {0xb93b2000}, {0xb93b4000}, {0xb93b6000},
+ {0xb93b8000}, {0xb93ba000}, {0xb93bc000}, {0xb93be000},
+ {0xb93c0000}, {0xb93c2000}, {0xb93c4000}, {0xb93c6000},
+ {0xb93c8000}, {0xb93ca000}, {0xb93cc000}, {0xb93ce000},
+ {0xb93d0000}, {0xb93d2000}, {0xb93d4000}, {0xb93d6000},
+ {0xb93d8000}, {0xb93da000}, {0xb93dc000}, {0xb93de000},
+ {0xb93e0000}, {0xb93e2000}, {0xb93e4000}, {0xb93e6000},
+ {0xb93e8000}, {0xb93ea000}, {0xb93ec000}, {0xb93ee000},
+ {0xb93f0000}, {0xb93f2000}, {0xb93f4000}, {0xb93f6000},
+ {0xb93f8000}, {0xb93fa000}, {0xb93fc000}, {0xb93fe000},
+ {0xb9400000}, {0xb9402000}, {0xb9404000}, {0xb9406000},
+ {0xb9408000}, {0xb940a000}, {0xb940c000}, {0xb940e000},
+ {0xb9410000}, {0xb9412000}, {0xb9414000}, {0xb9416000},
+ {0xb9418000}, {0xb941a000}, {0xb941c000}, {0xb941e000},
+ {0xb9420000}, {0xb9422000}, {0xb9424000}, {0xb9426000},
+ {0xb9428000}, {0xb942a000}, {0xb942c000}, {0xb942e000},
+ {0xb9430000}, {0xb9432000}, {0xb9434000}, {0xb9436000},
+ {0xb9438000}, {0xb943a000}, {0xb943c000}, {0xb943e000},
+ {0xb9440000}, {0xb9442000}, {0xb9444000}, {0xb9446000},
+ {0xb9448000}, {0xb944a000}, {0xb944c000}, {0xb944e000},
+ {0xb9450000}, {0xb9452000}, {0xb9454000}, {0xb9456000},
+ {0xb9458000}, {0xb945a000}, {0xb945c000}, {0xb945e000},
+ {0xb9460000}, {0xb9462000}, {0xb9464000}, {0xb9466000},
+ {0xb9468000}, {0xb946a000}, {0xb946c000}, {0xb946e000},
+ {0xb9470000}, {0xb9472000}, {0xb9474000}, {0xb9476000},
+ {0xb9478000}, {0xb947a000}, {0xb947c000}, {0xb947e000},
+ {0xb9480000}, {0xb9482000}, {0xb9484000}, {0xb9486000},
+ {0xb9488000}, {0xb948a000}, {0xb948c000}, {0xb948e000},
+ {0xb9490000}, {0xb9492000}, {0xb9494000}, {0xb9496000},
+ {0xb9498000}, {0xb949a000}, {0xb949c000}, {0xb949e000},
+ {0xb94a0000}, {0xb94a2000}, {0xb94a4000}, {0xb94a6000},
+ {0xb94a8000}, {0xb94aa000}, {0xb94ac000}, {0xb94ae000},
+ {0xb94b0000}, {0xb94b2000}, {0xb94b4000}, {0xb94b6000},
+ {0xb94b8000}, {0xb94ba000}, {0xb94bc000}, {0xb94be000},
+ {0xb94c0000}, {0xb94c2000}, {0xb94c4000}, {0xb94c6000},
+ {0xb94c8000}, {0xb94ca000}, {0xb94cc000}, {0xb94ce000},
+ {0xb94d0000}, {0xb94d2000}, {0xb94d4000}, {0xb94d6000},
+ {0xb94d8000}, {0xb94da000}, {0xb94dc000}, {0xb94de000},
+ {0xb94e0000}, {0xb94e2000}, {0xb94e4000}, {0xb94e6000},
+ {0xb94e8000}, {0xb94ea000}, {0xb94ec000}, {0xb94ee000},
+ {0xb94f0000}, {0xb94f2000}, {0xb94f4000}, {0xb94f6000},
+ {0xb94f8000}, {0xb94fa000}, {0xb94fc000}, {0xb94fe000},
+ {0xb9500000}, {0xb9502000}, {0xb9504000}, {0xb9506000},
+ {0xb9508000}, {0xb950a000}, {0xb950c000}, {0xb950e000},
+ {0xb9510000}, {0xb9512000}, {0xb9514000}, {0xb9516000},
+ {0xb9518000}, {0xb951a000}, {0xb951c000}, {0xb951e000},
+ {0xb9520000}, {0xb9522000}, {0xb9524000}, {0xb9526000},
+ {0xb9528000}, {0xb952a000}, {0xb952c000}, {0xb952e000},
+ {0xb9530000}, {0xb9532000}, {0xb9534000}, {0xb9536000},
+ {0xb9538000}, {0xb953a000}, {0xb953c000}, {0xb953e000},
+ {0xb9540000}, {0xb9542000}, {0xb9544000}, {0xb9546000},
+ {0xb9548000}, {0xb954a000}, {0xb954c000}, {0xb954e000},
+ {0xb9550000}, {0xb9552000}, {0xb9554000}, {0xb9556000},
+ {0xb9558000}, {0xb955a000}, {0xb955c000}, {0xb955e000},
+ {0xb9560000}, {0xb9562000}, {0xb9564000}, {0xb9566000},
+ {0xb9568000}, {0xb956a000}, {0xb956c000}, {0xb956e000},
+ {0xb9570000}, {0xb9572000}, {0xb9574000}, {0xb9576000},
+ {0xb9578000}, {0xb957a000}, {0xb957c000}, {0xb957e000},
+ {0xb9580000}, {0xb9582000}, {0xb9584000}, {0xb9586000},
+ {0xb9588000}, {0xb958a000}, {0xb958c000}, {0xb958e000},
+ {0xb9590000}, {0xb9592000}, {0xb9594000}, {0xb9596000},
+ {0xb9598000}, {0xb959a000}, {0xb959c000}, {0xb959e000},
+ {0xb95a0000}, {0xb95a2000}, {0xb95a4000}, {0xb95a6000},
+ {0xb95a8000}, {0xb95aa000}, {0xb95ac000}, {0xb95ae000},
+ {0xb95b0000}, {0xb95b2000}, {0xb95b4000}, {0xb95b6000},
+ {0xb95b8000}, {0xb95ba000}, {0xb95bc000}, {0xb95be000},
+ {0xb95c0000}, {0xb95c2000}, {0xb95c4000}, {0xb95c6000},
+ {0xb95c8000}, {0xb95ca000}, {0xb95cc000}, {0xb95ce000},
+ {0xb95d0000}, {0xb95d2000}, {0xb95d4000}, {0xb95d6000},
+ {0xb95d8000}, {0xb95da000}, {0xb95dc000}, {0xb95de000},
+ {0xb95e0000}, {0xb95e2000}, {0xb95e4000}, {0xb95e6000},
+ {0xb95e8000}, {0xb95ea000}, {0xb95ec000}, {0xb95ee000},
+ {0xb95f0000}, {0xb95f2000}, {0xb95f4000}, {0xb95f6000},
+ {0xb95f8000}, {0xb95fa000}, {0xb95fc000}, {0xb95fe000},
+ {0xb9600000}, {0xb9602000}, {0xb9604000}, {0xb9606000},
+ {0xb9608000}, {0xb960a000}, {0xb960c000}, {0xb960e000},
+ {0xb9610000}, {0xb9612000}, {0xb9614000}, {0xb9616000},
+ {0xb9618000}, {0xb961a000}, {0xb961c000}, {0xb961e000},
+ {0xb9620000}, {0xb9622000}, {0xb9624000}, {0xb9626000},
+ {0xb9628000}, {0xb962a000}, {0xb962c000}, {0xb962e000},
+ {0xb9630000}, {0xb9632000}, {0xb9634000}, {0xb9636000},
+ {0xb9638000}, {0xb963a000}, {0xb963c000}, {0xb963e000},
+ {0xb9640000}, {0xb9642000}, {0xb9644000}, {0xb9646000},
+ {0xb9648000}, {0xb964a000}, {0xb964c000}, {0xb964e000},
+ {0xb9650000}, {0xb9652000}, {0xb9654000}, {0xb9656000},
+ {0xb9658000}, {0xb965a000}, {0xb965c000}, {0xb965e000},
+ {0xb9660000}, {0xb9662000}, {0xb9664000}, {0xb9666000},
+ {0xb9668000}, {0xb966a000}, {0xb966c000}, {0xb966e000},
+ {0xb9670000}, {0xb9672000}, {0xb9674000}, {0xb9676000},
+ {0xb9678000}, {0xb967a000}, {0xb967c000}, {0xb967e000},
+ {0xb9680000}, {0xb9682000}, {0xb9684000}, {0xb9686000},
+ {0xb9688000}, {0xb968a000}, {0xb968c000}, {0xb968e000},
+ {0xb9690000}, {0xb9692000}, {0xb9694000}, {0xb9696000},
+ {0xb9698000}, {0xb969a000}, {0xb969c000}, {0xb969e000},
+ {0xb96a0000}, {0xb96a2000}, {0xb96a4000}, {0xb96a6000},
+ {0xb96a8000}, {0xb96aa000}, {0xb96ac000}, {0xb96ae000},
+ {0xb96b0000}, {0xb96b2000}, {0xb96b4000}, {0xb96b6000},
+ {0xb96b8000}, {0xb96ba000}, {0xb96bc000}, {0xb96be000},
+ {0xb96c0000}, {0xb96c2000}, {0xb96c4000}, {0xb96c6000},
+ {0xb96c8000}, {0xb96ca000}, {0xb96cc000}, {0xb96ce000},
+ {0xb96d0000}, {0xb96d2000}, {0xb96d4000}, {0xb96d6000},
+ {0xb96d8000}, {0xb96da000}, {0xb96dc000}, {0xb96de000},
+ {0xb96e0000}, {0xb96e2000}, {0xb96e4000}, {0xb96e6000},
+ {0xb96e8000}, {0xb96ea000}, {0xb96ec000}, {0xb96ee000},
+ {0xb96f0000}, {0xb96f2000}, {0xb96f4000}, {0xb96f6000},
+ {0xb96f8000}, {0xb96fa000}, {0xb96fc000}, {0xb96fe000},
+ {0xb9700000}, {0xb9702000}, {0xb9704000}, {0xb9706000},
+ {0xb9708000}, {0xb970a000}, {0xb970c000}, {0xb970e000},
+ {0xb9710000}, {0xb9712000}, {0xb9714000}, {0xb9716000},
+ {0xb9718000}, {0xb971a000}, {0xb971c000}, {0xb971e000},
+ {0xb9720000}, {0xb9722000}, {0xb9724000}, {0xb9726000},
+ {0xb9728000}, {0xb972a000}, {0xb972c000}, {0xb972e000},
+ {0xb9730000}, {0xb9732000}, {0xb9734000}, {0xb9736000},
+ {0xb9738000}, {0xb973a000}, {0xb973c000}, {0xb973e000},
+ {0xb9740000}, {0xb9742000}, {0xb9744000}, {0xb9746000},
+ {0xb9748000}, {0xb974a000}, {0xb974c000}, {0xb974e000},
+ {0xb9750000}, {0xb9752000}, {0xb9754000}, {0xb9756000},
+ {0xb9758000}, {0xb975a000}, {0xb975c000}, {0xb975e000},
+ {0xb9760000}, {0xb9762000}, {0xb9764000}, {0xb9766000},
+ {0xb9768000}, {0xb976a000}, {0xb976c000}, {0xb976e000},
+ {0xb9770000}, {0xb9772000}, {0xb9774000}, {0xb9776000},
+ {0xb9778000}, {0xb977a000}, {0xb977c000}, {0xb977e000},
+ {0xb9780000}, {0xb9782000}, {0xb9784000}, {0xb9786000},
+ {0xb9788000}, {0xb978a000}, {0xb978c000}, {0xb978e000},
+ {0xb9790000}, {0xb9792000}, {0xb9794000}, {0xb9796000},
+ {0xb9798000}, {0xb979a000}, {0xb979c000}, {0xb979e000},
+ {0xb97a0000}, {0xb97a2000}, {0xb97a4000}, {0xb97a6000},
+ {0xb97a8000}, {0xb97aa000}, {0xb97ac000}, {0xb97ae000},
+ {0xb97b0000}, {0xb97b2000}, {0xb97b4000}, {0xb97b6000},
+ {0xb97b8000}, {0xb97ba000}, {0xb97bc000}, {0xb97be000},
+ {0xb97c0000}, {0xb97c2000}, {0xb97c4000}, {0xb97c6000},
+ {0xb97c8000}, {0xb97ca000}, {0xb97cc000}, {0xb97ce000},
+ {0xb97d0000}, {0xb97d2000}, {0xb97d4000}, {0xb97d6000},
+ {0xb97d8000}, {0xb97da000}, {0xb97dc000}, {0xb97de000},
+ {0xb97e0000}, {0xb97e2000}, {0xb97e4000}, {0xb97e6000},
+ {0xb97e8000}, {0xb97ea000}, {0xb97ec000}, {0xb97ee000},
+ {0xb97f0000}, {0xb97f2000}, {0xb97f4000}, {0xb97f6000},
+ {0xb97f8000}, {0xb97fa000}, {0xb97fc000}, {0xb97fe000},
+ {0xb9800000}, {0xb9802000}, {0xb9804000}, {0xb9806000},
+ {0xb9808000}, {0xb980a000}, {0xb980c000}, {0xb980e000},
+ {0xb9810000}, {0xb9812000}, {0xb9814000}, {0xb9816000},
+ {0xb9818000}, {0xb981a000}, {0xb981c000}, {0xb981e000},
+ {0xb9820000}, {0xb9822000}, {0xb9824000}, {0xb9826000},
+ {0xb9828000}, {0xb982a000}, {0xb982c000}, {0xb982e000},
+ {0xb9830000}, {0xb9832000}, {0xb9834000}, {0xb9836000},
+ {0xb9838000}, {0xb983a000}, {0xb983c000}, {0xb983e000},
+ {0xb9840000}, {0xb9842000}, {0xb9844000}, {0xb9846000},
+ {0xb9848000}, {0xb984a000}, {0xb984c000}, {0xb984e000},
+ {0xb9850000}, {0xb9852000}, {0xb9854000}, {0xb9856000},
+ {0xb9858000}, {0xb985a000}, {0xb985c000}, {0xb985e000},
+ {0xb9860000}, {0xb9862000}, {0xb9864000}, {0xb9866000},
+ {0xb9868000}, {0xb986a000}, {0xb986c000}, {0xb986e000},
+ {0xb9870000}, {0xb9872000}, {0xb9874000}, {0xb9876000},
+ {0xb9878000}, {0xb987a000}, {0xb987c000}, {0xb987e000},
+ {0xb9880000}, {0xb9882000}, {0xb9884000}, {0xb9886000},
+ {0xb9888000}, {0xb988a000}, {0xb988c000}, {0xb988e000},
+ {0xb9890000}, {0xb9892000}, {0xb9894000}, {0xb9896000},
+ {0xb9898000}, {0xb989a000}, {0xb989c000}, {0xb989e000},
+ {0xb98a0000}, {0xb98a2000}, {0xb98a4000}, {0xb98a6000},
+ {0xb98a8000}, {0xb98aa000}, {0xb98ac000}, {0xb98ae000},
+ {0xb98b0000}, {0xb98b2000}, {0xb98b4000}, {0xb98b6000},
+ {0xb98b8000}, {0xb98ba000}, {0xb98bc000}, {0xb98be000},
+ {0xb98c0000}, {0xb98c2000}, {0xb98c4000}, {0xb98c6000},
+ {0xb98c8000}, {0xb98ca000}, {0xb98cc000}, {0xb98ce000},
+ {0xb98d0000}, {0xb98d2000}, {0xb98d4000}, {0xb98d6000},
+ {0xb98d8000}, {0xb98da000}, {0xb98dc000}, {0xb98de000},
+ {0xb98e0000}, {0xb98e2000}, {0xb98e4000}, {0xb98e6000},
+ {0xb98e8000}, {0xb98ea000}, {0xb98ec000}, {0xb98ee000},
+ {0xb98f0000}, {0xb98f2000}, {0xb98f4000}, {0xb98f6000},
+ {0xb98f8000}, {0xb98fa000}, {0xb98fc000}, {0xb98fe000},
+ {0xb9900000}, {0xb9902000}, {0xb9904000}, {0xb9906000},
+ {0xb9908000}, {0xb990a000}, {0xb990c000}, {0xb990e000},
+ {0xb9910000}, {0xb9912000}, {0xb9914000}, {0xb9916000},
+ {0xb9918000}, {0xb991a000}, {0xb991c000}, {0xb991e000},
+ {0xb9920000}, {0xb9922000}, {0xb9924000}, {0xb9926000},
+ {0xb9928000}, {0xb992a000}, {0xb992c000}, {0xb992e000},
+ {0xb9930000}, {0xb9932000}, {0xb9934000}, {0xb9936000},
+ {0xb9938000}, {0xb993a000}, {0xb993c000}, {0xb993e000},
+ {0xb9940000}, {0xb9942000}, {0xb9944000}, {0xb9946000},
+ {0xb9948000}, {0xb994a000}, {0xb994c000}, {0xb994e000},
+ {0xb9950000}, {0xb9952000}, {0xb9954000}, {0xb9956000},
+ {0xb9958000}, {0xb995a000}, {0xb995c000}, {0xb995e000},
+ {0xb9960000}, {0xb9962000}, {0xb9964000}, {0xb9966000},
+ {0xb9968000}, {0xb996a000}, {0xb996c000}, {0xb996e000},
+ {0xb9970000}, {0xb9972000}, {0xb9974000}, {0xb9976000},
+ {0xb9978000}, {0xb997a000}, {0xb997c000}, {0xb997e000},
+ {0xb9980000}, {0xb9982000}, {0xb9984000}, {0xb9986000},
+ {0xb9988000}, {0xb998a000}, {0xb998c000}, {0xb998e000},
+ {0xb9990000}, {0xb9992000}, {0xb9994000}, {0xb9996000},
+ {0xb9998000}, {0xb999a000}, {0xb999c000}, {0xb999e000},
+ {0xb99a0000}, {0xb99a2000}, {0xb99a4000}, {0xb99a6000},
+ {0xb99a8000}, {0xb99aa000}, {0xb99ac000}, {0xb99ae000},
+ {0xb99b0000}, {0xb99b2000}, {0xb99b4000}, {0xb99b6000},
+ {0xb99b8000}, {0xb99ba000}, {0xb99bc000}, {0xb99be000},
+ {0xb99c0000}, {0xb99c2000}, {0xb99c4000}, {0xb99c6000},
+ {0xb99c8000}, {0xb99ca000}, {0xb99cc000}, {0xb99ce000},
+ {0xb99d0000}, {0xb99d2000}, {0xb99d4000}, {0xb99d6000},
+ {0xb99d8000}, {0xb99da000}, {0xb99dc000}, {0xb99de000},
+ {0xb99e0000}, {0xb99e2000}, {0xb99e4000}, {0xb99e6000},
+ {0xb99e8000}, {0xb99ea000}, {0xb99ec000}, {0xb99ee000},
+ {0xb99f0000}, {0xb99f2000}, {0xb99f4000}, {0xb99f6000},
+ {0xb99f8000}, {0xb99fa000}, {0xb99fc000}, {0xb99fe000},
+ {0xb9a00000}, {0xb9a02000}, {0xb9a04000}, {0xb9a06000},
+ {0xb9a08000}, {0xb9a0a000}, {0xb9a0c000}, {0xb9a0e000},
+ {0xb9a10000}, {0xb9a12000}, {0xb9a14000}, {0xb9a16000},
+ {0xb9a18000}, {0xb9a1a000}, {0xb9a1c000}, {0xb9a1e000},
+ {0xb9a20000}, {0xb9a22000}, {0xb9a24000}, {0xb9a26000},
+ {0xb9a28000}, {0xb9a2a000}, {0xb9a2c000}, {0xb9a2e000},
+ {0xb9a30000}, {0xb9a32000}, {0xb9a34000}, {0xb9a36000},
+ {0xb9a38000}, {0xb9a3a000}, {0xb9a3c000}, {0xb9a3e000},
+ {0xb9a40000}, {0xb9a42000}, {0xb9a44000}, {0xb9a46000},
+ {0xb9a48000}, {0xb9a4a000}, {0xb9a4c000}, {0xb9a4e000},
+ {0xb9a50000}, {0xb9a52000}, {0xb9a54000}, {0xb9a56000},
+ {0xb9a58000}, {0xb9a5a000}, {0xb9a5c000}, {0xb9a5e000},
+ {0xb9a60000}, {0xb9a62000}, {0xb9a64000}, {0xb9a66000},
+ {0xb9a68000}, {0xb9a6a000}, {0xb9a6c000}, {0xb9a6e000},
+ {0xb9a70000}, {0xb9a72000}, {0xb9a74000}, {0xb9a76000},
+ {0xb9a78000}, {0xb9a7a000}, {0xb9a7c000}, {0xb9a7e000},
+ {0xb9a80000}, {0xb9a82000}, {0xb9a84000}, {0xb9a86000},
+ {0xb9a88000}, {0xb9a8a000}, {0xb9a8c000}, {0xb9a8e000},
+ {0xb9a90000}, {0xb9a92000}, {0xb9a94000}, {0xb9a96000},
+ {0xb9a98000}, {0xb9a9a000}, {0xb9a9c000}, {0xb9a9e000},
+ {0xb9aa0000}, {0xb9aa2000}, {0xb9aa4000}, {0xb9aa6000},
+ {0xb9aa8000}, {0xb9aaa000}, {0xb9aac000}, {0xb9aae000},
+ {0xb9ab0000}, {0xb9ab2000}, {0xb9ab4000}, {0xb9ab6000},
+ {0xb9ab8000}, {0xb9aba000}, {0xb9abc000}, {0xb9abe000},
+ {0xb9ac0000}, {0xb9ac2000}, {0xb9ac4000}, {0xb9ac6000},
+ {0xb9ac8000}, {0xb9aca000}, {0xb9acc000}, {0xb9ace000},
+ {0xb9ad0000}, {0xb9ad2000}, {0xb9ad4000}, {0xb9ad6000},
+ {0xb9ad8000}, {0xb9ada000}, {0xb9adc000}, {0xb9ade000},
+ {0xb9ae0000}, {0xb9ae2000}, {0xb9ae4000}, {0xb9ae6000},
+ {0xb9ae8000}, {0xb9aea000}, {0xb9aec000}, {0xb9aee000},
+ {0xb9af0000}, {0xb9af2000}, {0xb9af4000}, {0xb9af6000},
+ {0xb9af8000}, {0xb9afa000}, {0xb9afc000}, {0xb9afe000},
+ {0xb9b00000}, {0xb9b02000}, {0xb9b04000}, {0xb9b06000},
+ {0xb9b08000}, {0xb9b0a000}, {0xb9b0c000}, {0xb9b0e000},
+ {0xb9b10000}, {0xb9b12000}, {0xb9b14000}, {0xb9b16000},
+ {0xb9b18000}, {0xb9b1a000}, {0xb9b1c000}, {0xb9b1e000},
+ {0xb9b20000}, {0xb9b22000}, {0xb9b24000}, {0xb9b26000},
+ {0xb9b28000}, {0xb9b2a000}, {0xb9b2c000}, {0xb9b2e000},
+ {0xb9b30000}, {0xb9b32000}, {0xb9b34000}, {0xb9b36000},
+ {0xb9b38000}, {0xb9b3a000}, {0xb9b3c000}, {0xb9b3e000},
+ {0xb9b40000}, {0xb9b42000}, {0xb9b44000}, {0xb9b46000},
+ {0xb9b48000}, {0xb9b4a000}, {0xb9b4c000}, {0xb9b4e000},
+ {0xb9b50000}, {0xb9b52000}, {0xb9b54000}, {0xb9b56000},
+ {0xb9b58000}, {0xb9b5a000}, {0xb9b5c000}, {0xb9b5e000},
+ {0xb9b60000}, {0xb9b62000}, {0xb9b64000}, {0xb9b66000},
+ {0xb9b68000}, {0xb9b6a000}, {0xb9b6c000}, {0xb9b6e000},
+ {0xb9b70000}, {0xb9b72000}, {0xb9b74000}, {0xb9b76000},
+ {0xb9b78000}, {0xb9b7a000}, {0xb9b7c000}, {0xb9b7e000},
+ {0xb9b80000}, {0xb9b82000}, {0xb9b84000}, {0xb9b86000},
+ {0xb9b88000}, {0xb9b8a000}, {0xb9b8c000}, {0xb9b8e000},
+ {0xb9b90000}, {0xb9b92000}, {0xb9b94000}, {0xb9b96000},
+ {0xb9b98000}, {0xb9b9a000}, {0xb9b9c000}, {0xb9b9e000},
+ {0xb9ba0000}, {0xb9ba2000}, {0xb9ba4000}, {0xb9ba6000},
+ {0xb9ba8000}, {0xb9baa000}, {0xb9bac000}, {0xb9bae000},
+ {0xb9bb0000}, {0xb9bb2000}, {0xb9bb4000}, {0xb9bb6000},
+ {0xb9bb8000}, {0xb9bba000}, {0xb9bbc000}, {0xb9bbe000},
+ {0xb9bc0000}, {0xb9bc2000}, {0xb9bc4000}, {0xb9bc6000},
+ {0xb9bc8000}, {0xb9bca000}, {0xb9bcc000}, {0xb9bce000},
+ {0xb9bd0000}, {0xb9bd2000}, {0xb9bd4000}, {0xb9bd6000},
+ {0xb9bd8000}, {0xb9bda000}, {0xb9bdc000}, {0xb9bde000},
+ {0xb9be0000}, {0xb9be2000}, {0xb9be4000}, {0xb9be6000},
+ {0xb9be8000}, {0xb9bea000}, {0xb9bec000}, {0xb9bee000},
+ {0xb9bf0000}, {0xb9bf2000}, {0xb9bf4000}, {0xb9bf6000},
+ {0xb9bf8000}, {0xb9bfa000}, {0xb9bfc000}, {0xb9bfe000},
+ {0xb9c00000}, {0xb9c02000}, {0xb9c04000}, {0xb9c06000},
+ {0xb9c08000}, {0xb9c0a000}, {0xb9c0c000}, {0xb9c0e000},
+ {0xb9c10000}, {0xb9c12000}, {0xb9c14000}, {0xb9c16000},
+ {0xb9c18000}, {0xb9c1a000}, {0xb9c1c000}, {0xb9c1e000},
+ {0xb9c20000}, {0xb9c22000}, {0xb9c24000}, {0xb9c26000},
+ {0xb9c28000}, {0xb9c2a000}, {0xb9c2c000}, {0xb9c2e000},
+ {0xb9c30000}, {0xb9c32000}, {0xb9c34000}, {0xb9c36000},
+ {0xb9c38000}, {0xb9c3a000}, {0xb9c3c000}, {0xb9c3e000},
+ {0xb9c40000}, {0xb9c42000}, {0xb9c44000}, {0xb9c46000},
+ {0xb9c48000}, {0xb9c4a000}, {0xb9c4c000}, {0xb9c4e000},
+ {0xb9c50000}, {0xb9c52000}, {0xb9c54000}, {0xb9c56000},
+ {0xb9c58000}, {0xb9c5a000}, {0xb9c5c000}, {0xb9c5e000},
+ {0xb9c60000}, {0xb9c62000}, {0xb9c64000}, {0xb9c66000},
+ {0xb9c68000}, {0xb9c6a000}, {0xb9c6c000}, {0xb9c6e000},
+ {0xb9c70000}, {0xb9c72000}, {0xb9c74000}, {0xb9c76000},
+ {0xb9c78000}, {0xb9c7a000}, {0xb9c7c000}, {0xb9c7e000},
+ {0xb9c80000}, {0xb9c82000}, {0xb9c84000}, {0xb9c86000},
+ {0xb9c88000}, {0xb9c8a000}, {0xb9c8c000}, {0xb9c8e000},
+ {0xb9c90000}, {0xb9c92000}, {0xb9c94000}, {0xb9c96000},
+ {0xb9c98000}, {0xb9c9a000}, {0xb9c9c000}, {0xb9c9e000},
+ {0xb9ca0000}, {0xb9ca2000}, {0xb9ca4000}, {0xb9ca6000},
+ {0xb9ca8000}, {0xb9caa000}, {0xb9cac000}, {0xb9cae000},
+ {0xb9cb0000}, {0xb9cb2000}, {0xb9cb4000}, {0xb9cb6000},
+ {0xb9cb8000}, {0xb9cba000}, {0xb9cbc000}, {0xb9cbe000},
+ {0xb9cc0000}, {0xb9cc2000}, {0xb9cc4000}, {0xb9cc6000},
+ {0xb9cc8000}, {0xb9cca000}, {0xb9ccc000}, {0xb9cce000},
+ {0xb9cd0000}, {0xb9cd2000}, {0xb9cd4000}, {0xb9cd6000},
+ {0xb9cd8000}, {0xb9cda000}, {0xb9cdc000}, {0xb9cde000},
+ {0xb9ce0000}, {0xb9ce2000}, {0xb9ce4000}, {0xb9ce6000},
+ {0xb9ce8000}, {0xb9cea000}, {0xb9cec000}, {0xb9cee000},
+ {0xb9cf0000}, {0xb9cf2000}, {0xb9cf4000}, {0xb9cf6000},
+ {0xb9cf8000}, {0xb9cfa000}, {0xb9cfc000}, {0xb9cfe000},
+ {0xb9d00000}, {0xb9d02000}, {0xb9d04000}, {0xb9d06000},
+ {0xb9d08000}, {0xb9d0a000}, {0xb9d0c000}, {0xb9d0e000},
+ {0xb9d10000}, {0xb9d12000}, {0xb9d14000}, {0xb9d16000},
+ {0xb9d18000}, {0xb9d1a000}, {0xb9d1c000}, {0xb9d1e000},
+ {0xb9d20000}, {0xb9d22000}, {0xb9d24000}, {0xb9d26000},
+ {0xb9d28000}, {0xb9d2a000}, {0xb9d2c000}, {0xb9d2e000},
+ {0xb9d30000}, {0xb9d32000}, {0xb9d34000}, {0xb9d36000},
+ {0xb9d38000}, {0xb9d3a000}, {0xb9d3c000}, {0xb9d3e000},
+ {0xb9d40000}, {0xb9d42000}, {0xb9d44000}, {0xb9d46000},
+ {0xb9d48000}, {0xb9d4a000}, {0xb9d4c000}, {0xb9d4e000},
+ {0xb9d50000}, {0xb9d52000}, {0xb9d54000}, {0xb9d56000},
+ {0xb9d58000}, {0xb9d5a000}, {0xb9d5c000}, {0xb9d5e000},
+ {0xb9d60000}, {0xb9d62000}, {0xb9d64000}, {0xb9d66000},
+ {0xb9d68000}, {0xb9d6a000}, {0xb9d6c000}, {0xb9d6e000},
+ {0xb9d70000}, {0xb9d72000}, {0xb9d74000}, {0xb9d76000},
+ {0xb9d78000}, {0xb9d7a000}, {0xb9d7c000}, {0xb9d7e000},
+ {0xb9d80000}, {0xb9d82000}, {0xb9d84000}, {0xb9d86000},
+ {0xb9d88000}, {0xb9d8a000}, {0xb9d8c000}, {0xb9d8e000},
+ {0xb9d90000}, {0xb9d92000}, {0xb9d94000}, {0xb9d96000},
+ {0xb9d98000}, {0xb9d9a000}, {0xb9d9c000}, {0xb9d9e000},
+ {0xb9da0000}, {0xb9da2000}, {0xb9da4000}, {0xb9da6000},
+ {0xb9da8000}, {0xb9daa000}, {0xb9dac000}, {0xb9dae000},
+ {0xb9db0000}, {0xb9db2000}, {0xb9db4000}, {0xb9db6000},
+ {0xb9db8000}, {0xb9dba000}, {0xb9dbc000}, {0xb9dbe000},
+ {0xb9dc0000}, {0xb9dc2000}, {0xb9dc4000}, {0xb9dc6000},
+ {0xb9dc8000}, {0xb9dca000}, {0xb9dcc000}, {0xb9dce000},
+ {0xb9dd0000}, {0xb9dd2000}, {0xb9dd4000}, {0xb9dd6000},
+ {0xb9dd8000}, {0xb9dda000}, {0xb9ddc000}, {0xb9dde000},
+ {0xb9de0000}, {0xb9de2000}, {0xb9de4000}, {0xb9de6000},
+ {0xb9de8000}, {0xb9dea000}, {0xb9dec000}, {0xb9dee000},
+ {0xb9df0000}, {0xb9df2000}, {0xb9df4000}, {0xb9df6000},
+ {0xb9df8000}, {0xb9dfa000}, {0xb9dfc000}, {0xb9dfe000},
+ {0xb9e00000}, {0xb9e02000}, {0xb9e04000}, {0xb9e06000},
+ {0xb9e08000}, {0xb9e0a000}, {0xb9e0c000}, {0xb9e0e000},
+ {0xb9e10000}, {0xb9e12000}, {0xb9e14000}, {0xb9e16000},
+ {0xb9e18000}, {0xb9e1a000}, {0xb9e1c000}, {0xb9e1e000},
+ {0xb9e20000}, {0xb9e22000}, {0xb9e24000}, {0xb9e26000},
+ {0xb9e28000}, {0xb9e2a000}, {0xb9e2c000}, {0xb9e2e000},
+ {0xb9e30000}, {0xb9e32000}, {0xb9e34000}, {0xb9e36000},
+ {0xb9e38000}, {0xb9e3a000}, {0xb9e3c000}, {0xb9e3e000},
+ {0xb9e40000}, {0xb9e42000}, {0xb9e44000}, {0xb9e46000},
+ {0xb9e48000}, {0xb9e4a000}, {0xb9e4c000}, {0xb9e4e000},
+ {0xb9e50000}, {0xb9e52000}, {0xb9e54000}, {0xb9e56000},
+ {0xb9e58000}, {0xb9e5a000}, {0xb9e5c000}, {0xb9e5e000},
+ {0xb9e60000}, {0xb9e62000}, {0xb9e64000}, {0xb9e66000},
+ {0xb9e68000}, {0xb9e6a000}, {0xb9e6c000}, {0xb9e6e000},
+ {0xb9e70000}, {0xb9e72000}, {0xb9e74000}, {0xb9e76000},
+ {0xb9e78000}, {0xb9e7a000}, {0xb9e7c000}, {0xb9e7e000},
+ {0xb9e80000}, {0xb9e82000}, {0xb9e84000}, {0xb9e86000},
+ {0xb9e88000}, {0xb9e8a000}, {0xb9e8c000}, {0xb9e8e000},
+ {0xb9e90000}, {0xb9e92000}, {0xb9e94000}, {0xb9e96000},
+ {0xb9e98000}, {0xb9e9a000}, {0xb9e9c000}, {0xb9e9e000},
+ {0xb9ea0000}, {0xb9ea2000}, {0xb9ea4000}, {0xb9ea6000},
+ {0xb9ea8000}, {0xb9eaa000}, {0xb9eac000}, {0xb9eae000},
+ {0xb9eb0000}, {0xb9eb2000}, {0xb9eb4000}, {0xb9eb6000},
+ {0xb9eb8000}, {0xb9eba000}, {0xb9ebc000}, {0xb9ebe000},
+ {0xb9ec0000}, {0xb9ec2000}, {0xb9ec4000}, {0xb9ec6000},
+ {0xb9ec8000}, {0xb9eca000}, {0xb9ecc000}, {0xb9ece000},
+ {0xb9ed0000}, {0xb9ed2000}, {0xb9ed4000}, {0xb9ed6000},
+ {0xb9ed8000}, {0xb9eda000}, {0xb9edc000}, {0xb9ede000},
+ {0xb9ee0000}, {0xb9ee2000}, {0xb9ee4000}, {0xb9ee6000},
+ {0xb9ee8000}, {0xb9eea000}, {0xb9eec000}, {0xb9eee000},
+ {0xb9ef0000}, {0xb9ef2000}, {0xb9ef4000}, {0xb9ef6000},
+ {0xb9ef8000}, {0xb9efa000}, {0xb9efc000}, {0xb9efe000},
+ {0xb9f00000}, {0xb9f02000}, {0xb9f04000}, {0xb9f06000},
+ {0xb9f08000}, {0xb9f0a000}, {0xb9f0c000}, {0xb9f0e000},
+ {0xb9f10000}, {0xb9f12000}, {0xb9f14000}, {0xb9f16000},
+ {0xb9f18000}, {0xb9f1a000}, {0xb9f1c000}, {0xb9f1e000},
+ {0xb9f20000}, {0xb9f22000}, {0xb9f24000}, {0xb9f26000},
+ {0xb9f28000}, {0xb9f2a000}, {0xb9f2c000}, {0xb9f2e000},
+ {0xb9f30000}, {0xb9f32000}, {0xb9f34000}, {0xb9f36000},
+ {0xb9f38000}, {0xb9f3a000}, {0xb9f3c000}, {0xb9f3e000},
+ {0xb9f40000}, {0xb9f42000}, {0xb9f44000}, {0xb9f46000},
+ {0xb9f48000}, {0xb9f4a000}, {0xb9f4c000}, {0xb9f4e000},
+ {0xb9f50000}, {0xb9f52000}, {0xb9f54000}, {0xb9f56000},
+ {0xb9f58000}, {0xb9f5a000}, {0xb9f5c000}, {0xb9f5e000},
+ {0xb9f60000}, {0xb9f62000}, {0xb9f64000}, {0xb9f66000},
+ {0xb9f68000}, {0xb9f6a000}, {0xb9f6c000}, {0xb9f6e000},
+ {0xb9f70000}, {0xb9f72000}, {0xb9f74000}, {0xb9f76000},
+ {0xb9f78000}, {0xb9f7a000}, {0xb9f7c000}, {0xb9f7e000},
+ {0xb9f80000}, {0xb9f82000}, {0xb9f84000}, {0xb9f86000},
+ {0xb9f88000}, {0xb9f8a000}, {0xb9f8c000}, {0xb9f8e000},
+ {0xb9f90000}, {0xb9f92000}, {0xb9f94000}, {0xb9f96000},
+ {0xb9f98000}, {0xb9f9a000}, {0xb9f9c000}, {0xb9f9e000},
+ {0xb9fa0000}, {0xb9fa2000}, {0xb9fa4000}, {0xb9fa6000},
+ {0xb9fa8000}, {0xb9faa000}, {0xb9fac000}, {0xb9fae000},
+ {0xb9fb0000}, {0xb9fb2000}, {0xb9fb4000}, {0xb9fb6000},
+ {0xb9fb8000}, {0xb9fba000}, {0xb9fbc000}, {0xb9fbe000},
+ {0xb9fc0000}, {0xb9fc2000}, {0xb9fc4000}, {0xb9fc6000},
+ {0xb9fc8000}, {0xb9fca000}, {0xb9fcc000}, {0xb9fce000},
+ {0xb9fd0000}, {0xb9fd2000}, {0xb9fd4000}, {0xb9fd6000},
+ {0xb9fd8000}, {0xb9fda000}, {0xb9fdc000}, {0xb9fde000},
+ {0xb9fe0000}, {0xb9fe2000}, {0xb9fe4000}, {0xb9fe6000},
+ {0xb9fe8000}, {0xb9fea000}, {0xb9fec000}, {0xb9fee000},
+ {0xb9ff0000}, {0xb9ff2000}, {0xb9ff4000}, {0xb9ff6000},
+ {0xb9ff8000}, {0xb9ffa000}, {0xb9ffc000}, {0xb9ffe000},
+ {0xba000000}, {0xba002000}, {0xba004000}, {0xba006000},
+ {0xba008000}, {0xba00a000}, {0xba00c000}, {0xba00e000},
+ {0xba010000}, {0xba012000}, {0xba014000}, {0xba016000},
+ {0xba018000}, {0xba01a000}, {0xba01c000}, {0xba01e000},
+ {0xba020000}, {0xba022000}, {0xba024000}, {0xba026000},
+ {0xba028000}, {0xba02a000}, {0xba02c000}, {0xba02e000},
+ {0xba030000}, {0xba032000}, {0xba034000}, {0xba036000},
+ {0xba038000}, {0xba03a000}, {0xba03c000}, {0xba03e000},
+ {0xba040000}, {0xba042000}, {0xba044000}, {0xba046000},
+ {0xba048000}, {0xba04a000}, {0xba04c000}, {0xba04e000},
+ {0xba050000}, {0xba052000}, {0xba054000}, {0xba056000},
+ {0xba058000}, {0xba05a000}, {0xba05c000}, {0xba05e000},
+ {0xba060000}, {0xba062000}, {0xba064000}, {0xba066000},
+ {0xba068000}, {0xba06a000}, {0xba06c000}, {0xba06e000},
+ {0xba070000}, {0xba072000}, {0xba074000}, {0xba076000},
+ {0xba078000}, {0xba07a000}, {0xba07c000}, {0xba07e000},
+ {0xba080000}, {0xba082000}, {0xba084000}, {0xba086000},
+ {0xba088000}, {0xba08a000}, {0xba08c000}, {0xba08e000},
+ {0xba090000}, {0xba092000}, {0xba094000}, {0xba096000},
+ {0xba098000}, {0xba09a000}, {0xba09c000}, {0xba09e000},
+ {0xba0a0000}, {0xba0a2000}, {0xba0a4000}, {0xba0a6000},
+ {0xba0a8000}, {0xba0aa000}, {0xba0ac000}, {0xba0ae000},
+ {0xba0b0000}, {0xba0b2000}, {0xba0b4000}, {0xba0b6000},
+ {0xba0b8000}, {0xba0ba000}, {0xba0bc000}, {0xba0be000},
+ {0xba0c0000}, {0xba0c2000}, {0xba0c4000}, {0xba0c6000},
+ {0xba0c8000}, {0xba0ca000}, {0xba0cc000}, {0xba0ce000},
+ {0xba0d0000}, {0xba0d2000}, {0xba0d4000}, {0xba0d6000},
+ {0xba0d8000}, {0xba0da000}, {0xba0dc000}, {0xba0de000},
+ {0xba0e0000}, {0xba0e2000}, {0xba0e4000}, {0xba0e6000},
+ {0xba0e8000}, {0xba0ea000}, {0xba0ec000}, {0xba0ee000},
+ {0xba0f0000}, {0xba0f2000}, {0xba0f4000}, {0xba0f6000},
+ {0xba0f8000}, {0xba0fa000}, {0xba0fc000}, {0xba0fe000},
+ {0xba100000}, {0xba102000}, {0xba104000}, {0xba106000},
+ {0xba108000}, {0xba10a000}, {0xba10c000}, {0xba10e000},
+ {0xba110000}, {0xba112000}, {0xba114000}, {0xba116000},
+ {0xba118000}, {0xba11a000}, {0xba11c000}, {0xba11e000},
+ {0xba120000}, {0xba122000}, {0xba124000}, {0xba126000},
+ {0xba128000}, {0xba12a000}, {0xba12c000}, {0xba12e000},
+ {0xba130000}, {0xba132000}, {0xba134000}, {0xba136000},
+ {0xba138000}, {0xba13a000}, {0xba13c000}, {0xba13e000},
+ {0xba140000}, {0xba142000}, {0xba144000}, {0xba146000},
+ {0xba148000}, {0xba14a000}, {0xba14c000}, {0xba14e000},
+ {0xba150000}, {0xba152000}, {0xba154000}, {0xba156000},
+ {0xba158000}, {0xba15a000}, {0xba15c000}, {0xba15e000},
+ {0xba160000}, {0xba162000}, {0xba164000}, {0xba166000},
+ {0xba168000}, {0xba16a000}, {0xba16c000}, {0xba16e000},
+ {0xba170000}, {0xba172000}, {0xba174000}, {0xba176000},
+ {0xba178000}, {0xba17a000}, {0xba17c000}, {0xba17e000},
+ {0xba180000}, {0xba182000}, {0xba184000}, {0xba186000},
+ {0xba188000}, {0xba18a000}, {0xba18c000}, {0xba18e000},
+ {0xba190000}, {0xba192000}, {0xba194000}, {0xba196000},
+ {0xba198000}, {0xba19a000}, {0xba19c000}, {0xba19e000},
+ {0xba1a0000}, {0xba1a2000}, {0xba1a4000}, {0xba1a6000},
+ {0xba1a8000}, {0xba1aa000}, {0xba1ac000}, {0xba1ae000},
+ {0xba1b0000}, {0xba1b2000}, {0xba1b4000}, {0xba1b6000},
+ {0xba1b8000}, {0xba1ba000}, {0xba1bc000}, {0xba1be000},
+ {0xba1c0000}, {0xba1c2000}, {0xba1c4000}, {0xba1c6000},
+ {0xba1c8000}, {0xba1ca000}, {0xba1cc000}, {0xba1ce000},
+ {0xba1d0000}, {0xba1d2000}, {0xba1d4000}, {0xba1d6000},
+ {0xba1d8000}, {0xba1da000}, {0xba1dc000}, {0xba1de000},
+ {0xba1e0000}, {0xba1e2000}, {0xba1e4000}, {0xba1e6000},
+ {0xba1e8000}, {0xba1ea000}, {0xba1ec000}, {0xba1ee000},
+ {0xba1f0000}, {0xba1f2000}, {0xba1f4000}, {0xba1f6000},
+ {0xba1f8000}, {0xba1fa000}, {0xba1fc000}, {0xba1fe000},
+ {0xba200000}, {0xba202000}, {0xba204000}, {0xba206000},
+ {0xba208000}, {0xba20a000}, {0xba20c000}, {0xba20e000},
+ {0xba210000}, {0xba212000}, {0xba214000}, {0xba216000},
+ {0xba218000}, {0xba21a000}, {0xba21c000}, {0xba21e000},
+ {0xba220000}, {0xba222000}, {0xba224000}, {0xba226000},
+ {0xba228000}, {0xba22a000}, {0xba22c000}, {0xba22e000},
+ {0xba230000}, {0xba232000}, {0xba234000}, {0xba236000},
+ {0xba238000}, {0xba23a000}, {0xba23c000}, {0xba23e000},
+ {0xba240000}, {0xba242000}, {0xba244000}, {0xba246000},
+ {0xba248000}, {0xba24a000}, {0xba24c000}, {0xba24e000},
+ {0xba250000}, {0xba252000}, {0xba254000}, {0xba256000},
+ {0xba258000}, {0xba25a000}, {0xba25c000}, {0xba25e000},
+ {0xba260000}, {0xba262000}, {0xba264000}, {0xba266000},
+ {0xba268000}, {0xba26a000}, {0xba26c000}, {0xba26e000},
+ {0xba270000}, {0xba272000}, {0xba274000}, {0xba276000},
+ {0xba278000}, {0xba27a000}, {0xba27c000}, {0xba27e000},
+ {0xba280000}, {0xba282000}, {0xba284000}, {0xba286000},
+ {0xba288000}, {0xba28a000}, {0xba28c000}, {0xba28e000},
+ {0xba290000}, {0xba292000}, {0xba294000}, {0xba296000},
+ {0xba298000}, {0xba29a000}, {0xba29c000}, {0xba29e000},
+ {0xba2a0000}, {0xba2a2000}, {0xba2a4000}, {0xba2a6000},
+ {0xba2a8000}, {0xba2aa000}, {0xba2ac000}, {0xba2ae000},
+ {0xba2b0000}, {0xba2b2000}, {0xba2b4000}, {0xba2b6000},
+ {0xba2b8000}, {0xba2ba000}, {0xba2bc000}, {0xba2be000},
+ {0xba2c0000}, {0xba2c2000}, {0xba2c4000}, {0xba2c6000},
+ {0xba2c8000}, {0xba2ca000}, {0xba2cc000}, {0xba2ce000},
+ {0xba2d0000}, {0xba2d2000}, {0xba2d4000}, {0xba2d6000},
+ {0xba2d8000}, {0xba2da000}, {0xba2dc000}, {0xba2de000},
+ {0xba2e0000}, {0xba2e2000}, {0xba2e4000}, {0xba2e6000},
+ {0xba2e8000}, {0xba2ea000}, {0xba2ec000}, {0xba2ee000},
+ {0xba2f0000}, {0xba2f2000}, {0xba2f4000}, {0xba2f6000},
+ {0xba2f8000}, {0xba2fa000}, {0xba2fc000}, {0xba2fe000},
+ {0xba300000}, {0xba302000}, {0xba304000}, {0xba306000},
+ {0xba308000}, {0xba30a000}, {0xba30c000}, {0xba30e000},
+ {0xba310000}, {0xba312000}, {0xba314000}, {0xba316000},
+ {0xba318000}, {0xba31a000}, {0xba31c000}, {0xba31e000},
+ {0xba320000}, {0xba322000}, {0xba324000}, {0xba326000},
+ {0xba328000}, {0xba32a000}, {0xba32c000}, {0xba32e000},
+ {0xba330000}, {0xba332000}, {0xba334000}, {0xba336000},
+ {0xba338000}, {0xba33a000}, {0xba33c000}, {0xba33e000},
+ {0xba340000}, {0xba342000}, {0xba344000}, {0xba346000},
+ {0xba348000}, {0xba34a000}, {0xba34c000}, {0xba34e000},
+ {0xba350000}, {0xba352000}, {0xba354000}, {0xba356000},
+ {0xba358000}, {0xba35a000}, {0xba35c000}, {0xba35e000},
+ {0xba360000}, {0xba362000}, {0xba364000}, {0xba366000},
+ {0xba368000}, {0xba36a000}, {0xba36c000}, {0xba36e000},
+ {0xba370000}, {0xba372000}, {0xba374000}, {0xba376000},
+ {0xba378000}, {0xba37a000}, {0xba37c000}, {0xba37e000},
+ {0xba380000}, {0xba382000}, {0xba384000}, {0xba386000},
+ {0xba388000}, {0xba38a000}, {0xba38c000}, {0xba38e000},
+ {0xba390000}, {0xba392000}, {0xba394000}, {0xba396000},
+ {0xba398000}, {0xba39a000}, {0xba39c000}, {0xba39e000},
+ {0xba3a0000}, {0xba3a2000}, {0xba3a4000}, {0xba3a6000},
+ {0xba3a8000}, {0xba3aa000}, {0xba3ac000}, {0xba3ae000},
+ {0xba3b0000}, {0xba3b2000}, {0xba3b4000}, {0xba3b6000},
+ {0xba3b8000}, {0xba3ba000}, {0xba3bc000}, {0xba3be000},
+ {0xba3c0000}, {0xba3c2000}, {0xba3c4000}, {0xba3c6000},
+ {0xba3c8000}, {0xba3ca000}, {0xba3cc000}, {0xba3ce000},
+ {0xba3d0000}, {0xba3d2000}, {0xba3d4000}, {0xba3d6000},
+ {0xba3d8000}, {0xba3da000}, {0xba3dc000}, {0xba3de000},
+ {0xba3e0000}, {0xba3e2000}, {0xba3e4000}, {0xba3e6000},
+ {0xba3e8000}, {0xba3ea000}, {0xba3ec000}, {0xba3ee000},
+ {0xba3f0000}, {0xba3f2000}, {0xba3f4000}, {0xba3f6000},
+ {0xba3f8000}, {0xba3fa000}, {0xba3fc000}, {0xba3fe000},
+ {0xba400000}, {0xba402000}, {0xba404000}, {0xba406000},
+ {0xba408000}, {0xba40a000}, {0xba40c000}, {0xba40e000},
+ {0xba410000}, {0xba412000}, {0xba414000}, {0xba416000},
+ {0xba418000}, {0xba41a000}, {0xba41c000}, {0xba41e000},
+ {0xba420000}, {0xba422000}, {0xba424000}, {0xba426000},
+ {0xba428000}, {0xba42a000}, {0xba42c000}, {0xba42e000},
+ {0xba430000}, {0xba432000}, {0xba434000}, {0xba436000},
+ {0xba438000}, {0xba43a000}, {0xba43c000}, {0xba43e000},
+ {0xba440000}, {0xba442000}, {0xba444000}, {0xba446000},
+ {0xba448000}, {0xba44a000}, {0xba44c000}, {0xba44e000},
+ {0xba450000}, {0xba452000}, {0xba454000}, {0xba456000},
+ {0xba458000}, {0xba45a000}, {0xba45c000}, {0xba45e000},
+ {0xba460000}, {0xba462000}, {0xba464000}, {0xba466000},
+ {0xba468000}, {0xba46a000}, {0xba46c000}, {0xba46e000},
+ {0xba470000}, {0xba472000}, {0xba474000}, {0xba476000},
+ {0xba478000}, {0xba47a000}, {0xba47c000}, {0xba47e000},
+ {0xba480000}, {0xba482000}, {0xba484000}, {0xba486000},
+ {0xba488000}, {0xba48a000}, {0xba48c000}, {0xba48e000},
+ {0xba490000}, {0xba492000}, {0xba494000}, {0xba496000},
+ {0xba498000}, {0xba49a000}, {0xba49c000}, {0xba49e000},
+ {0xba4a0000}, {0xba4a2000}, {0xba4a4000}, {0xba4a6000},
+ {0xba4a8000}, {0xba4aa000}, {0xba4ac000}, {0xba4ae000},
+ {0xba4b0000}, {0xba4b2000}, {0xba4b4000}, {0xba4b6000},
+ {0xba4b8000}, {0xba4ba000}, {0xba4bc000}, {0xba4be000},
+ {0xba4c0000}, {0xba4c2000}, {0xba4c4000}, {0xba4c6000},
+ {0xba4c8000}, {0xba4ca000}, {0xba4cc000}, {0xba4ce000},
+ {0xba4d0000}, {0xba4d2000}, {0xba4d4000}, {0xba4d6000},
+ {0xba4d8000}, {0xba4da000}, {0xba4dc000}, {0xba4de000},
+ {0xba4e0000}, {0xba4e2000}, {0xba4e4000}, {0xba4e6000},
+ {0xba4e8000}, {0xba4ea000}, {0xba4ec000}, {0xba4ee000},
+ {0xba4f0000}, {0xba4f2000}, {0xba4f4000}, {0xba4f6000},
+ {0xba4f8000}, {0xba4fa000}, {0xba4fc000}, {0xba4fe000},
+ {0xba500000}, {0xba502000}, {0xba504000}, {0xba506000},
+ {0xba508000}, {0xba50a000}, {0xba50c000}, {0xba50e000},
+ {0xba510000}, {0xba512000}, {0xba514000}, {0xba516000},
+ {0xba518000}, {0xba51a000}, {0xba51c000}, {0xba51e000},
+ {0xba520000}, {0xba522000}, {0xba524000}, {0xba526000},
+ {0xba528000}, {0xba52a000}, {0xba52c000}, {0xba52e000},
+ {0xba530000}, {0xba532000}, {0xba534000}, {0xba536000},
+ {0xba538000}, {0xba53a000}, {0xba53c000}, {0xba53e000},
+ {0xba540000}, {0xba542000}, {0xba544000}, {0xba546000},
+ {0xba548000}, {0xba54a000}, {0xba54c000}, {0xba54e000},
+ {0xba550000}, {0xba552000}, {0xba554000}, {0xba556000},
+ {0xba558000}, {0xba55a000}, {0xba55c000}, {0xba55e000},
+ {0xba560000}, {0xba562000}, {0xba564000}, {0xba566000},
+ {0xba568000}, {0xba56a000}, {0xba56c000}, {0xba56e000},
+ {0xba570000}, {0xba572000}, {0xba574000}, {0xba576000},
+ {0xba578000}, {0xba57a000}, {0xba57c000}, {0xba57e000},
+ {0xba580000}, {0xba582000}, {0xba584000}, {0xba586000},
+ {0xba588000}, {0xba58a000}, {0xba58c000}, {0xba58e000},
+ {0xba590000}, {0xba592000}, {0xba594000}, {0xba596000},
+ {0xba598000}, {0xba59a000}, {0xba59c000}, {0xba59e000},
+ {0xba5a0000}, {0xba5a2000}, {0xba5a4000}, {0xba5a6000},
+ {0xba5a8000}, {0xba5aa000}, {0xba5ac000}, {0xba5ae000},
+ {0xba5b0000}, {0xba5b2000}, {0xba5b4000}, {0xba5b6000},
+ {0xba5b8000}, {0xba5ba000}, {0xba5bc000}, {0xba5be000},
+ {0xba5c0000}, {0xba5c2000}, {0xba5c4000}, {0xba5c6000},
+ {0xba5c8000}, {0xba5ca000}, {0xba5cc000}, {0xba5ce000},
+ {0xba5d0000}, {0xba5d2000}, {0xba5d4000}, {0xba5d6000},
+ {0xba5d8000}, {0xba5da000}, {0xba5dc000}, {0xba5de000},
+ {0xba5e0000}, {0xba5e2000}, {0xba5e4000}, {0xba5e6000},
+ {0xba5e8000}, {0xba5ea000}, {0xba5ec000}, {0xba5ee000},
+ {0xba5f0000}, {0xba5f2000}, {0xba5f4000}, {0xba5f6000},
+ {0xba5f8000}, {0xba5fa000}, {0xba5fc000}, {0xba5fe000},
+ {0xba600000}, {0xba602000}, {0xba604000}, {0xba606000},
+ {0xba608000}, {0xba60a000}, {0xba60c000}, {0xba60e000},
+ {0xba610000}, {0xba612000}, {0xba614000}, {0xba616000},
+ {0xba618000}, {0xba61a000}, {0xba61c000}, {0xba61e000},
+ {0xba620000}, {0xba622000}, {0xba624000}, {0xba626000},
+ {0xba628000}, {0xba62a000}, {0xba62c000}, {0xba62e000},
+ {0xba630000}, {0xba632000}, {0xba634000}, {0xba636000},
+ {0xba638000}, {0xba63a000}, {0xba63c000}, {0xba63e000},
+ {0xba640000}, {0xba642000}, {0xba644000}, {0xba646000},
+ {0xba648000}, {0xba64a000}, {0xba64c000}, {0xba64e000},
+ {0xba650000}, {0xba652000}, {0xba654000}, {0xba656000},
+ {0xba658000}, {0xba65a000}, {0xba65c000}, {0xba65e000},
+ {0xba660000}, {0xba662000}, {0xba664000}, {0xba666000},
+ {0xba668000}, {0xba66a000}, {0xba66c000}, {0xba66e000},
+ {0xba670000}, {0xba672000}, {0xba674000}, {0xba676000},
+ {0xba678000}, {0xba67a000}, {0xba67c000}, {0xba67e000},
+ {0xba680000}, {0xba682000}, {0xba684000}, {0xba686000},
+ {0xba688000}, {0xba68a000}, {0xba68c000}, {0xba68e000},
+ {0xba690000}, {0xba692000}, {0xba694000}, {0xba696000},
+ {0xba698000}, {0xba69a000}, {0xba69c000}, {0xba69e000},
+ {0xba6a0000}, {0xba6a2000}, {0xba6a4000}, {0xba6a6000},
+ {0xba6a8000}, {0xba6aa000}, {0xba6ac000}, {0xba6ae000},
+ {0xba6b0000}, {0xba6b2000}, {0xba6b4000}, {0xba6b6000},
+ {0xba6b8000}, {0xba6ba000}, {0xba6bc000}, {0xba6be000},
+ {0xba6c0000}, {0xba6c2000}, {0xba6c4000}, {0xba6c6000},
+ {0xba6c8000}, {0xba6ca000}, {0xba6cc000}, {0xba6ce000},
+ {0xba6d0000}, {0xba6d2000}, {0xba6d4000}, {0xba6d6000},
+ {0xba6d8000}, {0xba6da000}, {0xba6dc000}, {0xba6de000},
+ {0xba6e0000}, {0xba6e2000}, {0xba6e4000}, {0xba6e6000},
+ {0xba6e8000}, {0xba6ea000}, {0xba6ec000}, {0xba6ee000},
+ {0xba6f0000}, {0xba6f2000}, {0xba6f4000}, {0xba6f6000},
+ {0xba6f8000}, {0xba6fa000}, {0xba6fc000}, {0xba6fe000},
+ {0xba700000}, {0xba702000}, {0xba704000}, {0xba706000},
+ {0xba708000}, {0xba70a000}, {0xba70c000}, {0xba70e000},
+ {0xba710000}, {0xba712000}, {0xba714000}, {0xba716000},
+ {0xba718000}, {0xba71a000}, {0xba71c000}, {0xba71e000},
+ {0xba720000}, {0xba722000}, {0xba724000}, {0xba726000},
+ {0xba728000}, {0xba72a000}, {0xba72c000}, {0xba72e000},
+ {0xba730000}, {0xba732000}, {0xba734000}, {0xba736000},
+ {0xba738000}, {0xba73a000}, {0xba73c000}, {0xba73e000},
+ {0xba740000}, {0xba742000}, {0xba744000}, {0xba746000},
+ {0xba748000}, {0xba74a000}, {0xba74c000}, {0xba74e000},
+ {0xba750000}, {0xba752000}, {0xba754000}, {0xba756000},
+ {0xba758000}, {0xba75a000}, {0xba75c000}, {0xba75e000},
+ {0xba760000}, {0xba762000}, {0xba764000}, {0xba766000},
+ {0xba768000}, {0xba76a000}, {0xba76c000}, {0xba76e000},
+ {0xba770000}, {0xba772000}, {0xba774000}, {0xba776000},
+ {0xba778000}, {0xba77a000}, {0xba77c000}, {0xba77e000},
+ {0xba780000}, {0xba782000}, {0xba784000}, {0xba786000},
+ {0xba788000}, {0xba78a000}, {0xba78c000}, {0xba78e000},
+ {0xba790000}, {0xba792000}, {0xba794000}, {0xba796000},
+ {0xba798000}, {0xba79a000}, {0xba79c000}, {0xba79e000},
+ {0xba7a0000}, {0xba7a2000}, {0xba7a4000}, {0xba7a6000},
+ {0xba7a8000}, {0xba7aa000}, {0xba7ac000}, {0xba7ae000},
+ {0xba7b0000}, {0xba7b2000}, {0xba7b4000}, {0xba7b6000},
+ {0xba7b8000}, {0xba7ba000}, {0xba7bc000}, {0xba7be000},
+ {0xba7c0000}, {0xba7c2000}, {0xba7c4000}, {0xba7c6000},
+ {0xba7c8000}, {0xba7ca000}, {0xba7cc000}, {0xba7ce000},
+ {0xba7d0000}, {0xba7d2000}, {0xba7d4000}, {0xba7d6000},
+ {0xba7d8000}, {0xba7da000}, {0xba7dc000}, {0xba7de000},
+ {0xba7e0000}, {0xba7e2000}, {0xba7e4000}, {0xba7e6000},
+ {0xba7e8000}, {0xba7ea000}, {0xba7ec000}, {0xba7ee000},
+ {0xba7f0000}, {0xba7f2000}, {0xba7f4000}, {0xba7f6000},
+ {0xba7f8000}, {0xba7fa000}, {0xba7fc000}, {0xba7fe000},
+ {0xba800000}, {0xba802000}, {0xba804000}, {0xba806000},
+ {0xba808000}, {0xba80a000}, {0xba80c000}, {0xba80e000},
+ {0xba810000}, {0xba812000}, {0xba814000}, {0xba816000},
+ {0xba818000}, {0xba81a000}, {0xba81c000}, {0xba81e000},
+ {0xba820000}, {0xba822000}, {0xba824000}, {0xba826000},
+ {0xba828000}, {0xba82a000}, {0xba82c000}, {0xba82e000},
+ {0xba830000}, {0xba832000}, {0xba834000}, {0xba836000},
+ {0xba838000}, {0xba83a000}, {0xba83c000}, {0xba83e000},
+ {0xba840000}, {0xba842000}, {0xba844000}, {0xba846000},
+ {0xba848000}, {0xba84a000}, {0xba84c000}, {0xba84e000},
+ {0xba850000}, {0xba852000}, {0xba854000}, {0xba856000},
+ {0xba858000}, {0xba85a000}, {0xba85c000}, {0xba85e000},
+ {0xba860000}, {0xba862000}, {0xba864000}, {0xba866000},
+ {0xba868000}, {0xba86a000}, {0xba86c000}, {0xba86e000},
+ {0xba870000}, {0xba872000}, {0xba874000}, {0xba876000},
+ {0xba878000}, {0xba87a000}, {0xba87c000}, {0xba87e000},
+ {0xba880000}, {0xba882000}, {0xba884000}, {0xba886000},
+ {0xba888000}, {0xba88a000}, {0xba88c000}, {0xba88e000},
+ {0xba890000}, {0xba892000}, {0xba894000}, {0xba896000},
+ {0xba898000}, {0xba89a000}, {0xba89c000}, {0xba89e000},
+ {0xba8a0000}, {0xba8a2000}, {0xba8a4000}, {0xba8a6000},
+ {0xba8a8000}, {0xba8aa000}, {0xba8ac000}, {0xba8ae000},
+ {0xba8b0000}, {0xba8b2000}, {0xba8b4000}, {0xba8b6000},
+ {0xba8b8000}, {0xba8ba000}, {0xba8bc000}, {0xba8be000},
+ {0xba8c0000}, {0xba8c2000}, {0xba8c4000}, {0xba8c6000},
+ {0xba8c8000}, {0xba8ca000}, {0xba8cc000}, {0xba8ce000},
+ {0xba8d0000}, {0xba8d2000}, {0xba8d4000}, {0xba8d6000},
+ {0xba8d8000}, {0xba8da000}, {0xba8dc000}, {0xba8de000},
+ {0xba8e0000}, {0xba8e2000}, {0xba8e4000}, {0xba8e6000},
+ {0xba8e8000}, {0xba8ea000}, {0xba8ec000}, {0xba8ee000},
+ {0xba8f0000}, {0xba8f2000}, {0xba8f4000}, {0xba8f6000},
+ {0xba8f8000}, {0xba8fa000}, {0xba8fc000}, {0xba8fe000},
+ {0xba900000}, {0xba902000}, {0xba904000}, {0xba906000},
+ {0xba908000}, {0xba90a000}, {0xba90c000}, {0xba90e000},
+ {0xba910000}, {0xba912000}, {0xba914000}, {0xba916000},
+ {0xba918000}, {0xba91a000}, {0xba91c000}, {0xba91e000},
+ {0xba920000}, {0xba922000}, {0xba924000}, {0xba926000},
+ {0xba928000}, {0xba92a000}, {0xba92c000}, {0xba92e000},
+ {0xba930000}, {0xba932000}, {0xba934000}, {0xba936000},
+ {0xba938000}, {0xba93a000}, {0xba93c000}, {0xba93e000},
+ {0xba940000}, {0xba942000}, {0xba944000}, {0xba946000},
+ {0xba948000}, {0xba94a000}, {0xba94c000}, {0xba94e000},
+ {0xba950000}, {0xba952000}, {0xba954000}, {0xba956000},
+ {0xba958000}, {0xba95a000}, {0xba95c000}, {0xba95e000},
+ {0xba960000}, {0xba962000}, {0xba964000}, {0xba966000},
+ {0xba968000}, {0xba96a000}, {0xba96c000}, {0xba96e000},
+ {0xba970000}, {0xba972000}, {0xba974000}, {0xba976000},
+ {0xba978000}, {0xba97a000}, {0xba97c000}, {0xba97e000},
+ {0xba980000}, {0xba982000}, {0xba984000}, {0xba986000},
+ {0xba988000}, {0xba98a000}, {0xba98c000}, {0xba98e000},
+ {0xba990000}, {0xba992000}, {0xba994000}, {0xba996000},
+ {0xba998000}, {0xba99a000}, {0xba99c000}, {0xba99e000},
+ {0xba9a0000}, {0xba9a2000}, {0xba9a4000}, {0xba9a6000},
+ {0xba9a8000}, {0xba9aa000}, {0xba9ac000}, {0xba9ae000},
+ {0xba9b0000}, {0xba9b2000}, {0xba9b4000}, {0xba9b6000},
+ {0xba9b8000}, {0xba9ba000}, {0xba9bc000}, {0xba9be000},
+ {0xba9c0000}, {0xba9c2000}, {0xba9c4000}, {0xba9c6000},
+ {0xba9c8000}, {0xba9ca000}, {0xba9cc000}, {0xba9ce000},
+ {0xba9d0000}, {0xba9d2000}, {0xba9d4000}, {0xba9d6000},
+ {0xba9d8000}, {0xba9da000}, {0xba9dc000}, {0xba9de000},
+ {0xba9e0000}, {0xba9e2000}, {0xba9e4000}, {0xba9e6000},
+ {0xba9e8000}, {0xba9ea000}, {0xba9ec000}, {0xba9ee000},
+ {0xba9f0000}, {0xba9f2000}, {0xba9f4000}, {0xba9f6000},
+ {0xba9f8000}, {0xba9fa000}, {0xba9fc000}, {0xba9fe000},
+ {0xbaa00000}, {0xbaa02000}, {0xbaa04000}, {0xbaa06000},
+ {0xbaa08000}, {0xbaa0a000}, {0xbaa0c000}, {0xbaa0e000},
+ {0xbaa10000}, {0xbaa12000}, {0xbaa14000}, {0xbaa16000},
+ {0xbaa18000}, {0xbaa1a000}, {0xbaa1c000}, {0xbaa1e000},
+ {0xbaa20000}, {0xbaa22000}, {0xbaa24000}, {0xbaa26000},
+ {0xbaa28000}, {0xbaa2a000}, {0xbaa2c000}, {0xbaa2e000},
+ {0xbaa30000}, {0xbaa32000}, {0xbaa34000}, {0xbaa36000},
+ {0xbaa38000}, {0xbaa3a000}, {0xbaa3c000}, {0xbaa3e000},
+ {0xbaa40000}, {0xbaa42000}, {0xbaa44000}, {0xbaa46000},
+ {0xbaa48000}, {0xbaa4a000}, {0xbaa4c000}, {0xbaa4e000},
+ {0xbaa50000}, {0xbaa52000}, {0xbaa54000}, {0xbaa56000},
+ {0xbaa58000}, {0xbaa5a000}, {0xbaa5c000}, {0xbaa5e000},
+ {0xbaa60000}, {0xbaa62000}, {0xbaa64000}, {0xbaa66000},
+ {0xbaa68000}, {0xbaa6a000}, {0xbaa6c000}, {0xbaa6e000},
+ {0xbaa70000}, {0xbaa72000}, {0xbaa74000}, {0xbaa76000},
+ {0xbaa78000}, {0xbaa7a000}, {0xbaa7c000}, {0xbaa7e000},
+ {0xbaa80000}, {0xbaa82000}, {0xbaa84000}, {0xbaa86000},
+ {0xbaa88000}, {0xbaa8a000}, {0xbaa8c000}, {0xbaa8e000},
+ {0xbaa90000}, {0xbaa92000}, {0xbaa94000}, {0xbaa96000},
+ {0xbaa98000}, {0xbaa9a000}, {0xbaa9c000}, {0xbaa9e000},
+ {0xbaaa0000}, {0xbaaa2000}, {0xbaaa4000}, {0xbaaa6000},
+ {0xbaaa8000}, {0xbaaaa000}, {0xbaaac000}, {0xbaaae000},
+ {0xbaab0000}, {0xbaab2000}, {0xbaab4000}, {0xbaab6000},
+ {0xbaab8000}, {0xbaaba000}, {0xbaabc000}, {0xbaabe000},
+ {0xbaac0000}, {0xbaac2000}, {0xbaac4000}, {0xbaac6000},
+ {0xbaac8000}, {0xbaaca000}, {0xbaacc000}, {0xbaace000},
+ {0xbaad0000}, {0xbaad2000}, {0xbaad4000}, {0xbaad6000},
+ {0xbaad8000}, {0xbaada000}, {0xbaadc000}, {0xbaade000},
+ {0xbaae0000}, {0xbaae2000}, {0xbaae4000}, {0xbaae6000},
+ {0xbaae8000}, {0xbaaea000}, {0xbaaec000}, {0xbaaee000},
+ {0xbaaf0000}, {0xbaaf2000}, {0xbaaf4000}, {0xbaaf6000},
+ {0xbaaf8000}, {0xbaafa000}, {0xbaafc000}, {0xbaafe000},
+ {0xbab00000}, {0xbab02000}, {0xbab04000}, {0xbab06000},
+ {0xbab08000}, {0xbab0a000}, {0xbab0c000}, {0xbab0e000},
+ {0xbab10000}, {0xbab12000}, {0xbab14000}, {0xbab16000},
+ {0xbab18000}, {0xbab1a000}, {0xbab1c000}, {0xbab1e000},
+ {0xbab20000}, {0xbab22000}, {0xbab24000}, {0xbab26000},
+ {0xbab28000}, {0xbab2a000}, {0xbab2c000}, {0xbab2e000},
+ {0xbab30000}, {0xbab32000}, {0xbab34000}, {0xbab36000},
+ {0xbab38000}, {0xbab3a000}, {0xbab3c000}, {0xbab3e000},
+ {0xbab40000}, {0xbab42000}, {0xbab44000}, {0xbab46000},
+ {0xbab48000}, {0xbab4a000}, {0xbab4c000}, {0xbab4e000},
+ {0xbab50000}, {0xbab52000}, {0xbab54000}, {0xbab56000},
+ {0xbab58000}, {0xbab5a000}, {0xbab5c000}, {0xbab5e000},
+ {0xbab60000}, {0xbab62000}, {0xbab64000}, {0xbab66000},
+ {0xbab68000}, {0xbab6a000}, {0xbab6c000}, {0xbab6e000},
+ {0xbab70000}, {0xbab72000}, {0xbab74000}, {0xbab76000},
+ {0xbab78000}, {0xbab7a000}, {0xbab7c000}, {0xbab7e000},
+ {0xbab80000}, {0xbab82000}, {0xbab84000}, {0xbab86000},
+ {0xbab88000}, {0xbab8a000}, {0xbab8c000}, {0xbab8e000},
+ {0xbab90000}, {0xbab92000}, {0xbab94000}, {0xbab96000},
+ {0xbab98000}, {0xbab9a000}, {0xbab9c000}, {0xbab9e000},
+ {0xbaba0000}, {0xbaba2000}, {0xbaba4000}, {0xbaba6000},
+ {0xbaba8000}, {0xbabaa000}, {0xbabac000}, {0xbabae000},
+ {0xbabb0000}, {0xbabb2000}, {0xbabb4000}, {0xbabb6000},
+ {0xbabb8000}, {0xbabba000}, {0xbabbc000}, {0xbabbe000},
+ {0xbabc0000}, {0xbabc2000}, {0xbabc4000}, {0xbabc6000},
+ {0xbabc8000}, {0xbabca000}, {0xbabcc000}, {0xbabce000},
+ {0xbabd0000}, {0xbabd2000}, {0xbabd4000}, {0xbabd6000},
+ {0xbabd8000}, {0xbabda000}, {0xbabdc000}, {0xbabde000},
+ {0xbabe0000}, {0xbabe2000}, {0xbabe4000}, {0xbabe6000},
+ {0xbabe8000}, {0xbabea000}, {0xbabec000}, {0xbabee000},
+ {0xbabf0000}, {0xbabf2000}, {0xbabf4000}, {0xbabf6000},
+ {0xbabf8000}, {0xbabfa000}, {0xbabfc000}, {0xbabfe000},
+ {0xbac00000}, {0xbac02000}, {0xbac04000}, {0xbac06000},
+ {0xbac08000}, {0xbac0a000}, {0xbac0c000}, {0xbac0e000},
+ {0xbac10000}, {0xbac12000}, {0xbac14000}, {0xbac16000},
+ {0xbac18000}, {0xbac1a000}, {0xbac1c000}, {0xbac1e000},
+ {0xbac20000}, {0xbac22000}, {0xbac24000}, {0xbac26000},
+ {0xbac28000}, {0xbac2a000}, {0xbac2c000}, {0xbac2e000},
+ {0xbac30000}, {0xbac32000}, {0xbac34000}, {0xbac36000},
+ {0xbac38000}, {0xbac3a000}, {0xbac3c000}, {0xbac3e000},
+ {0xbac40000}, {0xbac42000}, {0xbac44000}, {0xbac46000},
+ {0xbac48000}, {0xbac4a000}, {0xbac4c000}, {0xbac4e000},
+ {0xbac50000}, {0xbac52000}, {0xbac54000}, {0xbac56000},
+ {0xbac58000}, {0xbac5a000}, {0xbac5c000}, {0xbac5e000},
+ {0xbac60000}, {0xbac62000}, {0xbac64000}, {0xbac66000},
+ {0xbac68000}, {0xbac6a000}, {0xbac6c000}, {0xbac6e000},
+ {0xbac70000}, {0xbac72000}, {0xbac74000}, {0xbac76000},
+ {0xbac78000}, {0xbac7a000}, {0xbac7c000}, {0xbac7e000},
+ {0xbac80000}, {0xbac82000}, {0xbac84000}, {0xbac86000},
+ {0xbac88000}, {0xbac8a000}, {0xbac8c000}, {0xbac8e000},
+ {0xbac90000}, {0xbac92000}, {0xbac94000}, {0xbac96000},
+ {0xbac98000}, {0xbac9a000}, {0xbac9c000}, {0xbac9e000},
+ {0xbaca0000}, {0xbaca2000}, {0xbaca4000}, {0xbaca6000},
+ {0xbaca8000}, {0xbacaa000}, {0xbacac000}, {0xbacae000},
+ {0xbacb0000}, {0xbacb2000}, {0xbacb4000}, {0xbacb6000},
+ {0xbacb8000}, {0xbacba000}, {0xbacbc000}, {0xbacbe000},
+ {0xbacc0000}, {0xbacc2000}, {0xbacc4000}, {0xbacc6000},
+ {0xbacc8000}, {0xbacca000}, {0xbaccc000}, {0xbacce000},
+ {0xbacd0000}, {0xbacd2000}, {0xbacd4000}, {0xbacd6000},
+ {0xbacd8000}, {0xbacda000}, {0xbacdc000}, {0xbacde000},
+ {0xbace0000}, {0xbace2000}, {0xbace4000}, {0xbace6000},
+ {0xbace8000}, {0xbacea000}, {0xbacec000}, {0xbacee000},
+ {0xbacf0000}, {0xbacf2000}, {0xbacf4000}, {0xbacf6000},
+ {0xbacf8000}, {0xbacfa000}, {0xbacfc000}, {0xbacfe000},
+ {0xbad00000}, {0xbad02000}, {0xbad04000}, {0xbad06000},
+ {0xbad08000}, {0xbad0a000}, {0xbad0c000}, {0xbad0e000},
+ {0xbad10000}, {0xbad12000}, {0xbad14000}, {0xbad16000},
+ {0xbad18000}, {0xbad1a000}, {0xbad1c000}, {0xbad1e000},
+ {0xbad20000}, {0xbad22000}, {0xbad24000}, {0xbad26000},
+ {0xbad28000}, {0xbad2a000}, {0xbad2c000}, {0xbad2e000},
+ {0xbad30000}, {0xbad32000}, {0xbad34000}, {0xbad36000},
+ {0xbad38000}, {0xbad3a000}, {0xbad3c000}, {0xbad3e000},
+ {0xbad40000}, {0xbad42000}, {0xbad44000}, {0xbad46000},
+ {0xbad48000}, {0xbad4a000}, {0xbad4c000}, {0xbad4e000},
+ {0xbad50000}, {0xbad52000}, {0xbad54000}, {0xbad56000},
+ {0xbad58000}, {0xbad5a000}, {0xbad5c000}, {0xbad5e000},
+ {0xbad60000}, {0xbad62000}, {0xbad64000}, {0xbad66000},
+ {0xbad68000}, {0xbad6a000}, {0xbad6c000}, {0xbad6e000},
+ {0xbad70000}, {0xbad72000}, {0xbad74000}, {0xbad76000},
+ {0xbad78000}, {0xbad7a000}, {0xbad7c000}, {0xbad7e000},
+ {0xbad80000}, {0xbad82000}, {0xbad84000}, {0xbad86000},
+ {0xbad88000}, {0xbad8a000}, {0xbad8c000}, {0xbad8e000},
+ {0xbad90000}, {0xbad92000}, {0xbad94000}, {0xbad96000},
+ {0xbad98000}, {0xbad9a000}, {0xbad9c000}, {0xbad9e000},
+ {0xbada0000}, {0xbada2000}, {0xbada4000}, {0xbada6000},
+ {0xbada8000}, {0xbadaa000}, {0xbadac000}, {0xbadae000},
+ {0xbadb0000}, {0xbadb2000}, {0xbadb4000}, {0xbadb6000},
+ {0xbadb8000}, {0xbadba000}, {0xbadbc000}, {0xbadbe000},
+ {0xbadc0000}, {0xbadc2000}, {0xbadc4000}, {0xbadc6000},
+ {0xbadc8000}, {0xbadca000}, {0xbadcc000}, {0xbadce000},
+ {0xbadd0000}, {0xbadd2000}, {0xbadd4000}, {0xbadd6000},
+ {0xbadd8000}, {0xbadda000}, {0xbaddc000}, {0xbadde000},
+ {0xbade0000}, {0xbade2000}, {0xbade4000}, {0xbade6000},
+ {0xbade8000}, {0xbadea000}, {0xbadec000}, {0xbadee000},
+ {0xbadf0000}, {0xbadf2000}, {0xbadf4000}, {0xbadf6000},
+ {0xbadf8000}, {0xbadfa000}, {0xbadfc000}, {0xbadfe000},
+ {0xbae00000}, {0xbae02000}, {0xbae04000}, {0xbae06000},
+ {0xbae08000}, {0xbae0a000}, {0xbae0c000}, {0xbae0e000},
+ {0xbae10000}, {0xbae12000}, {0xbae14000}, {0xbae16000},
+ {0xbae18000}, {0xbae1a000}, {0xbae1c000}, {0xbae1e000},
+ {0xbae20000}, {0xbae22000}, {0xbae24000}, {0xbae26000},
+ {0xbae28000}, {0xbae2a000}, {0xbae2c000}, {0xbae2e000},
+ {0xbae30000}, {0xbae32000}, {0xbae34000}, {0xbae36000},
+ {0xbae38000}, {0xbae3a000}, {0xbae3c000}, {0xbae3e000},
+ {0xbae40000}, {0xbae42000}, {0xbae44000}, {0xbae46000},
+ {0xbae48000}, {0xbae4a000}, {0xbae4c000}, {0xbae4e000},
+ {0xbae50000}, {0xbae52000}, {0xbae54000}, {0xbae56000},
+ {0xbae58000}, {0xbae5a000}, {0xbae5c000}, {0xbae5e000},
+ {0xbae60000}, {0xbae62000}, {0xbae64000}, {0xbae66000},
+ {0xbae68000}, {0xbae6a000}, {0xbae6c000}, {0xbae6e000},
+ {0xbae70000}, {0xbae72000}, {0xbae74000}, {0xbae76000},
+ {0xbae78000}, {0xbae7a000}, {0xbae7c000}, {0xbae7e000},
+ {0xbae80000}, {0xbae82000}, {0xbae84000}, {0xbae86000},
+ {0xbae88000}, {0xbae8a000}, {0xbae8c000}, {0xbae8e000},
+ {0xbae90000}, {0xbae92000}, {0xbae94000}, {0xbae96000},
+ {0xbae98000}, {0xbae9a000}, {0xbae9c000}, {0xbae9e000},
+ {0xbaea0000}, {0xbaea2000}, {0xbaea4000}, {0xbaea6000},
+ {0xbaea8000}, {0xbaeaa000}, {0xbaeac000}, {0xbaeae000},
+ {0xbaeb0000}, {0xbaeb2000}, {0xbaeb4000}, {0xbaeb6000},
+ {0xbaeb8000}, {0xbaeba000}, {0xbaebc000}, {0xbaebe000},
+ {0xbaec0000}, {0xbaec2000}, {0xbaec4000}, {0xbaec6000},
+ {0xbaec8000}, {0xbaeca000}, {0xbaecc000}, {0xbaece000},
+ {0xbaed0000}, {0xbaed2000}, {0xbaed4000}, {0xbaed6000},
+ {0xbaed8000}, {0xbaeda000}, {0xbaedc000}, {0xbaede000},
+ {0xbaee0000}, {0xbaee2000}, {0xbaee4000}, {0xbaee6000},
+ {0xbaee8000}, {0xbaeea000}, {0xbaeec000}, {0xbaeee000},
+ {0xbaef0000}, {0xbaef2000}, {0xbaef4000}, {0xbaef6000},
+ {0xbaef8000}, {0xbaefa000}, {0xbaefc000}, {0xbaefe000},
+ {0xbaf00000}, {0xbaf02000}, {0xbaf04000}, {0xbaf06000},
+ {0xbaf08000}, {0xbaf0a000}, {0xbaf0c000}, {0xbaf0e000},
+ {0xbaf10000}, {0xbaf12000}, {0xbaf14000}, {0xbaf16000},
+ {0xbaf18000}, {0xbaf1a000}, {0xbaf1c000}, {0xbaf1e000},
+ {0xbaf20000}, {0xbaf22000}, {0xbaf24000}, {0xbaf26000},
+ {0xbaf28000}, {0xbaf2a000}, {0xbaf2c000}, {0xbaf2e000},
+ {0xbaf30000}, {0xbaf32000}, {0xbaf34000}, {0xbaf36000},
+ {0xbaf38000}, {0xbaf3a000}, {0xbaf3c000}, {0xbaf3e000},
+ {0xbaf40000}, {0xbaf42000}, {0xbaf44000}, {0xbaf46000},
+ {0xbaf48000}, {0xbaf4a000}, {0xbaf4c000}, {0xbaf4e000},
+ {0xbaf50000}, {0xbaf52000}, {0xbaf54000}, {0xbaf56000},
+ {0xbaf58000}, {0xbaf5a000}, {0xbaf5c000}, {0xbaf5e000},
+ {0xbaf60000}, {0xbaf62000}, {0xbaf64000}, {0xbaf66000},
+ {0xbaf68000}, {0xbaf6a000}, {0xbaf6c000}, {0xbaf6e000},
+ {0xbaf70000}, {0xbaf72000}, {0xbaf74000}, {0xbaf76000},
+ {0xbaf78000}, {0xbaf7a000}, {0xbaf7c000}, {0xbaf7e000},
+ {0xbaf80000}, {0xbaf82000}, {0xbaf84000}, {0xbaf86000},
+ {0xbaf88000}, {0xbaf8a000}, {0xbaf8c000}, {0xbaf8e000},
+ {0xbaf90000}, {0xbaf92000}, {0xbaf94000}, {0xbaf96000},
+ {0xbaf98000}, {0xbaf9a000}, {0xbaf9c000}, {0xbaf9e000},
+ {0xbafa0000}, {0xbafa2000}, {0xbafa4000}, {0xbafa6000},
+ {0xbafa8000}, {0xbafaa000}, {0xbafac000}, {0xbafae000},
+ {0xbafb0000}, {0xbafb2000}, {0xbafb4000}, {0xbafb6000},
+ {0xbafb8000}, {0xbafba000}, {0xbafbc000}, {0xbafbe000},
+ {0xbafc0000}, {0xbafc2000}, {0xbafc4000}, {0xbafc6000},
+ {0xbafc8000}, {0xbafca000}, {0xbafcc000}, {0xbafce000},
+ {0xbafd0000}, {0xbafd2000}, {0xbafd4000}, {0xbafd6000},
+ {0xbafd8000}, {0xbafda000}, {0xbafdc000}, {0xbafde000},
+ {0xbafe0000}, {0xbafe2000}, {0xbafe4000}, {0xbafe6000},
+ {0xbafe8000}, {0xbafea000}, {0xbafec000}, {0xbafee000},
+ {0xbaff0000}, {0xbaff2000}, {0xbaff4000}, {0xbaff6000},
+ {0xbaff8000}, {0xbaffa000}, {0xbaffc000}, {0xbaffe000},
+ {0xbb000000}, {0xbb002000}, {0xbb004000}, {0xbb006000},
+ {0xbb008000}, {0xbb00a000}, {0xbb00c000}, {0xbb00e000},
+ {0xbb010000}, {0xbb012000}, {0xbb014000}, {0xbb016000},
+ {0xbb018000}, {0xbb01a000}, {0xbb01c000}, {0xbb01e000},
+ {0xbb020000}, {0xbb022000}, {0xbb024000}, {0xbb026000},
+ {0xbb028000}, {0xbb02a000}, {0xbb02c000}, {0xbb02e000},
+ {0xbb030000}, {0xbb032000}, {0xbb034000}, {0xbb036000},
+ {0xbb038000}, {0xbb03a000}, {0xbb03c000}, {0xbb03e000},
+ {0xbb040000}, {0xbb042000}, {0xbb044000}, {0xbb046000},
+ {0xbb048000}, {0xbb04a000}, {0xbb04c000}, {0xbb04e000},
+ {0xbb050000}, {0xbb052000}, {0xbb054000}, {0xbb056000},
+ {0xbb058000}, {0xbb05a000}, {0xbb05c000}, {0xbb05e000},
+ {0xbb060000}, {0xbb062000}, {0xbb064000}, {0xbb066000},
+ {0xbb068000}, {0xbb06a000}, {0xbb06c000}, {0xbb06e000},
+ {0xbb070000}, {0xbb072000}, {0xbb074000}, {0xbb076000},
+ {0xbb078000}, {0xbb07a000}, {0xbb07c000}, {0xbb07e000},
+ {0xbb080000}, {0xbb082000}, {0xbb084000}, {0xbb086000},
+ {0xbb088000}, {0xbb08a000}, {0xbb08c000}, {0xbb08e000},
+ {0xbb090000}, {0xbb092000}, {0xbb094000}, {0xbb096000},
+ {0xbb098000}, {0xbb09a000}, {0xbb09c000}, {0xbb09e000},
+ {0xbb0a0000}, {0xbb0a2000}, {0xbb0a4000}, {0xbb0a6000},
+ {0xbb0a8000}, {0xbb0aa000}, {0xbb0ac000}, {0xbb0ae000},
+ {0xbb0b0000}, {0xbb0b2000}, {0xbb0b4000}, {0xbb0b6000},
+ {0xbb0b8000}, {0xbb0ba000}, {0xbb0bc000}, {0xbb0be000},
+ {0xbb0c0000}, {0xbb0c2000}, {0xbb0c4000}, {0xbb0c6000},
+ {0xbb0c8000}, {0xbb0ca000}, {0xbb0cc000}, {0xbb0ce000},
+ {0xbb0d0000}, {0xbb0d2000}, {0xbb0d4000}, {0xbb0d6000},
+ {0xbb0d8000}, {0xbb0da000}, {0xbb0dc000}, {0xbb0de000},
+ {0xbb0e0000}, {0xbb0e2000}, {0xbb0e4000}, {0xbb0e6000},
+ {0xbb0e8000}, {0xbb0ea000}, {0xbb0ec000}, {0xbb0ee000},
+ {0xbb0f0000}, {0xbb0f2000}, {0xbb0f4000}, {0xbb0f6000},
+ {0xbb0f8000}, {0xbb0fa000}, {0xbb0fc000}, {0xbb0fe000},
+ {0xbb100000}, {0xbb102000}, {0xbb104000}, {0xbb106000},
+ {0xbb108000}, {0xbb10a000}, {0xbb10c000}, {0xbb10e000},
+ {0xbb110000}, {0xbb112000}, {0xbb114000}, {0xbb116000},
+ {0xbb118000}, {0xbb11a000}, {0xbb11c000}, {0xbb11e000},
+ {0xbb120000}, {0xbb122000}, {0xbb124000}, {0xbb126000},
+ {0xbb128000}, {0xbb12a000}, {0xbb12c000}, {0xbb12e000},
+ {0xbb130000}, {0xbb132000}, {0xbb134000}, {0xbb136000},
+ {0xbb138000}, {0xbb13a000}, {0xbb13c000}, {0xbb13e000},
+ {0xbb140000}, {0xbb142000}, {0xbb144000}, {0xbb146000},
+ {0xbb148000}, {0xbb14a000}, {0xbb14c000}, {0xbb14e000},
+ {0xbb150000}, {0xbb152000}, {0xbb154000}, {0xbb156000},
+ {0xbb158000}, {0xbb15a000}, {0xbb15c000}, {0xbb15e000},
+ {0xbb160000}, {0xbb162000}, {0xbb164000}, {0xbb166000},
+ {0xbb168000}, {0xbb16a000}, {0xbb16c000}, {0xbb16e000},
+ {0xbb170000}, {0xbb172000}, {0xbb174000}, {0xbb176000},
+ {0xbb178000}, {0xbb17a000}, {0xbb17c000}, {0xbb17e000},
+ {0xbb180000}, {0xbb182000}, {0xbb184000}, {0xbb186000},
+ {0xbb188000}, {0xbb18a000}, {0xbb18c000}, {0xbb18e000},
+ {0xbb190000}, {0xbb192000}, {0xbb194000}, {0xbb196000},
+ {0xbb198000}, {0xbb19a000}, {0xbb19c000}, {0xbb19e000},
+ {0xbb1a0000}, {0xbb1a2000}, {0xbb1a4000}, {0xbb1a6000},
+ {0xbb1a8000}, {0xbb1aa000}, {0xbb1ac000}, {0xbb1ae000},
+ {0xbb1b0000}, {0xbb1b2000}, {0xbb1b4000}, {0xbb1b6000},
+ {0xbb1b8000}, {0xbb1ba000}, {0xbb1bc000}, {0xbb1be000},
+ {0xbb1c0000}, {0xbb1c2000}, {0xbb1c4000}, {0xbb1c6000},
+ {0xbb1c8000}, {0xbb1ca000}, {0xbb1cc000}, {0xbb1ce000},
+ {0xbb1d0000}, {0xbb1d2000}, {0xbb1d4000}, {0xbb1d6000},
+ {0xbb1d8000}, {0xbb1da000}, {0xbb1dc000}, {0xbb1de000},
+ {0xbb1e0000}, {0xbb1e2000}, {0xbb1e4000}, {0xbb1e6000},
+ {0xbb1e8000}, {0xbb1ea000}, {0xbb1ec000}, {0xbb1ee000},
+ {0xbb1f0000}, {0xbb1f2000}, {0xbb1f4000}, {0xbb1f6000},
+ {0xbb1f8000}, {0xbb1fa000}, {0xbb1fc000}, {0xbb1fe000},
+ {0xbb200000}, {0xbb202000}, {0xbb204000}, {0xbb206000},
+ {0xbb208000}, {0xbb20a000}, {0xbb20c000}, {0xbb20e000},
+ {0xbb210000}, {0xbb212000}, {0xbb214000}, {0xbb216000},
+ {0xbb218000}, {0xbb21a000}, {0xbb21c000}, {0xbb21e000},
+ {0xbb220000}, {0xbb222000}, {0xbb224000}, {0xbb226000},
+ {0xbb228000}, {0xbb22a000}, {0xbb22c000}, {0xbb22e000},
+ {0xbb230000}, {0xbb232000}, {0xbb234000}, {0xbb236000},
+ {0xbb238000}, {0xbb23a000}, {0xbb23c000}, {0xbb23e000},
+ {0xbb240000}, {0xbb242000}, {0xbb244000}, {0xbb246000},
+ {0xbb248000}, {0xbb24a000}, {0xbb24c000}, {0xbb24e000},
+ {0xbb250000}, {0xbb252000}, {0xbb254000}, {0xbb256000},
+ {0xbb258000}, {0xbb25a000}, {0xbb25c000}, {0xbb25e000},
+ {0xbb260000}, {0xbb262000}, {0xbb264000}, {0xbb266000},
+ {0xbb268000}, {0xbb26a000}, {0xbb26c000}, {0xbb26e000},
+ {0xbb270000}, {0xbb272000}, {0xbb274000}, {0xbb276000},
+ {0xbb278000}, {0xbb27a000}, {0xbb27c000}, {0xbb27e000},
+ {0xbb280000}, {0xbb282000}, {0xbb284000}, {0xbb286000},
+ {0xbb288000}, {0xbb28a000}, {0xbb28c000}, {0xbb28e000},
+ {0xbb290000}, {0xbb292000}, {0xbb294000}, {0xbb296000},
+ {0xbb298000}, {0xbb29a000}, {0xbb29c000}, {0xbb29e000},
+ {0xbb2a0000}, {0xbb2a2000}, {0xbb2a4000}, {0xbb2a6000},
+ {0xbb2a8000}, {0xbb2aa000}, {0xbb2ac000}, {0xbb2ae000},
+ {0xbb2b0000}, {0xbb2b2000}, {0xbb2b4000}, {0xbb2b6000},
+ {0xbb2b8000}, {0xbb2ba000}, {0xbb2bc000}, {0xbb2be000},
+ {0xbb2c0000}, {0xbb2c2000}, {0xbb2c4000}, {0xbb2c6000},
+ {0xbb2c8000}, {0xbb2ca000}, {0xbb2cc000}, {0xbb2ce000},
+ {0xbb2d0000}, {0xbb2d2000}, {0xbb2d4000}, {0xbb2d6000},
+ {0xbb2d8000}, {0xbb2da000}, {0xbb2dc000}, {0xbb2de000},
+ {0xbb2e0000}, {0xbb2e2000}, {0xbb2e4000}, {0xbb2e6000},
+ {0xbb2e8000}, {0xbb2ea000}, {0xbb2ec000}, {0xbb2ee000},
+ {0xbb2f0000}, {0xbb2f2000}, {0xbb2f4000}, {0xbb2f6000},
+ {0xbb2f8000}, {0xbb2fa000}, {0xbb2fc000}, {0xbb2fe000},
+ {0xbb300000}, {0xbb302000}, {0xbb304000}, {0xbb306000},
+ {0xbb308000}, {0xbb30a000}, {0xbb30c000}, {0xbb30e000},
+ {0xbb310000}, {0xbb312000}, {0xbb314000}, {0xbb316000},
+ {0xbb318000}, {0xbb31a000}, {0xbb31c000}, {0xbb31e000},
+ {0xbb320000}, {0xbb322000}, {0xbb324000}, {0xbb326000},
+ {0xbb328000}, {0xbb32a000}, {0xbb32c000}, {0xbb32e000},
+ {0xbb330000}, {0xbb332000}, {0xbb334000}, {0xbb336000},
+ {0xbb338000}, {0xbb33a000}, {0xbb33c000}, {0xbb33e000},
+ {0xbb340000}, {0xbb342000}, {0xbb344000}, {0xbb346000},
+ {0xbb348000}, {0xbb34a000}, {0xbb34c000}, {0xbb34e000},
+ {0xbb350000}, {0xbb352000}, {0xbb354000}, {0xbb356000},
+ {0xbb358000}, {0xbb35a000}, {0xbb35c000}, {0xbb35e000},
+ {0xbb360000}, {0xbb362000}, {0xbb364000}, {0xbb366000},
+ {0xbb368000}, {0xbb36a000}, {0xbb36c000}, {0xbb36e000},
+ {0xbb370000}, {0xbb372000}, {0xbb374000}, {0xbb376000},
+ {0xbb378000}, {0xbb37a000}, {0xbb37c000}, {0xbb37e000},
+ {0xbb380000}, {0xbb382000}, {0xbb384000}, {0xbb386000},
+ {0xbb388000}, {0xbb38a000}, {0xbb38c000}, {0xbb38e000},
+ {0xbb390000}, {0xbb392000}, {0xbb394000}, {0xbb396000},
+ {0xbb398000}, {0xbb39a000}, {0xbb39c000}, {0xbb39e000},
+ {0xbb3a0000}, {0xbb3a2000}, {0xbb3a4000}, {0xbb3a6000},
+ {0xbb3a8000}, {0xbb3aa000}, {0xbb3ac000}, {0xbb3ae000},
+ {0xbb3b0000}, {0xbb3b2000}, {0xbb3b4000}, {0xbb3b6000},
+ {0xbb3b8000}, {0xbb3ba000}, {0xbb3bc000}, {0xbb3be000},
+ {0xbb3c0000}, {0xbb3c2000}, {0xbb3c4000}, {0xbb3c6000},
+ {0xbb3c8000}, {0xbb3ca000}, {0xbb3cc000}, {0xbb3ce000},
+ {0xbb3d0000}, {0xbb3d2000}, {0xbb3d4000}, {0xbb3d6000},
+ {0xbb3d8000}, {0xbb3da000}, {0xbb3dc000}, {0xbb3de000},
+ {0xbb3e0000}, {0xbb3e2000}, {0xbb3e4000}, {0xbb3e6000},
+ {0xbb3e8000}, {0xbb3ea000}, {0xbb3ec000}, {0xbb3ee000},
+ {0xbb3f0000}, {0xbb3f2000}, {0xbb3f4000}, {0xbb3f6000},
+ {0xbb3f8000}, {0xbb3fa000}, {0xbb3fc000}, {0xbb3fe000},
+ {0xbb400000}, {0xbb402000}, {0xbb404000}, {0xbb406000},
+ {0xbb408000}, {0xbb40a000}, {0xbb40c000}, {0xbb40e000},
+ {0xbb410000}, {0xbb412000}, {0xbb414000}, {0xbb416000},
+ {0xbb418000}, {0xbb41a000}, {0xbb41c000}, {0xbb41e000},
+ {0xbb420000}, {0xbb422000}, {0xbb424000}, {0xbb426000},
+ {0xbb428000}, {0xbb42a000}, {0xbb42c000}, {0xbb42e000},
+ {0xbb430000}, {0xbb432000}, {0xbb434000}, {0xbb436000},
+ {0xbb438000}, {0xbb43a000}, {0xbb43c000}, {0xbb43e000},
+ {0xbb440000}, {0xbb442000}, {0xbb444000}, {0xbb446000},
+ {0xbb448000}, {0xbb44a000}, {0xbb44c000}, {0xbb44e000},
+ {0xbb450000}, {0xbb452000}, {0xbb454000}, {0xbb456000},
+ {0xbb458000}, {0xbb45a000}, {0xbb45c000}, {0xbb45e000},
+ {0xbb460000}, {0xbb462000}, {0xbb464000}, {0xbb466000},
+ {0xbb468000}, {0xbb46a000}, {0xbb46c000}, {0xbb46e000},
+ {0xbb470000}, {0xbb472000}, {0xbb474000}, {0xbb476000},
+ {0xbb478000}, {0xbb47a000}, {0xbb47c000}, {0xbb47e000},
+ {0xbb480000}, {0xbb482000}, {0xbb484000}, {0xbb486000},
+ {0xbb488000}, {0xbb48a000}, {0xbb48c000}, {0xbb48e000},
+ {0xbb490000}, {0xbb492000}, {0xbb494000}, {0xbb496000},
+ {0xbb498000}, {0xbb49a000}, {0xbb49c000}, {0xbb49e000},
+ {0xbb4a0000}, {0xbb4a2000}, {0xbb4a4000}, {0xbb4a6000},
+ {0xbb4a8000}, {0xbb4aa000}, {0xbb4ac000}, {0xbb4ae000},
+ {0xbb4b0000}, {0xbb4b2000}, {0xbb4b4000}, {0xbb4b6000},
+ {0xbb4b8000}, {0xbb4ba000}, {0xbb4bc000}, {0xbb4be000},
+ {0xbb4c0000}, {0xbb4c2000}, {0xbb4c4000}, {0xbb4c6000},
+ {0xbb4c8000}, {0xbb4ca000}, {0xbb4cc000}, {0xbb4ce000},
+ {0xbb4d0000}, {0xbb4d2000}, {0xbb4d4000}, {0xbb4d6000},
+ {0xbb4d8000}, {0xbb4da000}, {0xbb4dc000}, {0xbb4de000},
+ {0xbb4e0000}, {0xbb4e2000}, {0xbb4e4000}, {0xbb4e6000},
+ {0xbb4e8000}, {0xbb4ea000}, {0xbb4ec000}, {0xbb4ee000},
+ {0xbb4f0000}, {0xbb4f2000}, {0xbb4f4000}, {0xbb4f6000},
+ {0xbb4f8000}, {0xbb4fa000}, {0xbb4fc000}, {0xbb4fe000},
+ {0xbb500000}, {0xbb502000}, {0xbb504000}, {0xbb506000},
+ {0xbb508000}, {0xbb50a000}, {0xbb50c000}, {0xbb50e000},
+ {0xbb510000}, {0xbb512000}, {0xbb514000}, {0xbb516000},
+ {0xbb518000}, {0xbb51a000}, {0xbb51c000}, {0xbb51e000},
+ {0xbb520000}, {0xbb522000}, {0xbb524000}, {0xbb526000},
+ {0xbb528000}, {0xbb52a000}, {0xbb52c000}, {0xbb52e000},
+ {0xbb530000}, {0xbb532000}, {0xbb534000}, {0xbb536000},
+ {0xbb538000}, {0xbb53a000}, {0xbb53c000}, {0xbb53e000},
+ {0xbb540000}, {0xbb542000}, {0xbb544000}, {0xbb546000},
+ {0xbb548000}, {0xbb54a000}, {0xbb54c000}, {0xbb54e000},
+ {0xbb550000}, {0xbb552000}, {0xbb554000}, {0xbb556000},
+ {0xbb558000}, {0xbb55a000}, {0xbb55c000}, {0xbb55e000},
+ {0xbb560000}, {0xbb562000}, {0xbb564000}, {0xbb566000},
+ {0xbb568000}, {0xbb56a000}, {0xbb56c000}, {0xbb56e000},
+ {0xbb570000}, {0xbb572000}, {0xbb574000}, {0xbb576000},
+ {0xbb578000}, {0xbb57a000}, {0xbb57c000}, {0xbb57e000},
+ {0xbb580000}, {0xbb582000}, {0xbb584000}, {0xbb586000},
+ {0xbb588000}, {0xbb58a000}, {0xbb58c000}, {0xbb58e000},
+ {0xbb590000}, {0xbb592000}, {0xbb594000}, {0xbb596000},
+ {0xbb598000}, {0xbb59a000}, {0xbb59c000}, {0xbb59e000},
+ {0xbb5a0000}, {0xbb5a2000}, {0xbb5a4000}, {0xbb5a6000},
+ {0xbb5a8000}, {0xbb5aa000}, {0xbb5ac000}, {0xbb5ae000},
+ {0xbb5b0000}, {0xbb5b2000}, {0xbb5b4000}, {0xbb5b6000},
+ {0xbb5b8000}, {0xbb5ba000}, {0xbb5bc000}, {0xbb5be000},
+ {0xbb5c0000}, {0xbb5c2000}, {0xbb5c4000}, {0xbb5c6000},
+ {0xbb5c8000}, {0xbb5ca000}, {0xbb5cc000}, {0xbb5ce000},
+ {0xbb5d0000}, {0xbb5d2000}, {0xbb5d4000}, {0xbb5d6000},
+ {0xbb5d8000}, {0xbb5da000}, {0xbb5dc000}, {0xbb5de000},
+ {0xbb5e0000}, {0xbb5e2000}, {0xbb5e4000}, {0xbb5e6000},
+ {0xbb5e8000}, {0xbb5ea000}, {0xbb5ec000}, {0xbb5ee000},
+ {0xbb5f0000}, {0xbb5f2000}, {0xbb5f4000}, {0xbb5f6000},
+ {0xbb5f8000}, {0xbb5fa000}, {0xbb5fc000}, {0xbb5fe000},
+ {0xbb600000}, {0xbb602000}, {0xbb604000}, {0xbb606000},
+ {0xbb608000}, {0xbb60a000}, {0xbb60c000}, {0xbb60e000},
+ {0xbb610000}, {0xbb612000}, {0xbb614000}, {0xbb616000},
+ {0xbb618000}, {0xbb61a000}, {0xbb61c000}, {0xbb61e000},
+ {0xbb620000}, {0xbb622000}, {0xbb624000}, {0xbb626000},
+ {0xbb628000}, {0xbb62a000}, {0xbb62c000}, {0xbb62e000},
+ {0xbb630000}, {0xbb632000}, {0xbb634000}, {0xbb636000},
+ {0xbb638000}, {0xbb63a000}, {0xbb63c000}, {0xbb63e000},
+ {0xbb640000}, {0xbb642000}, {0xbb644000}, {0xbb646000},
+ {0xbb648000}, {0xbb64a000}, {0xbb64c000}, {0xbb64e000},
+ {0xbb650000}, {0xbb652000}, {0xbb654000}, {0xbb656000},
+ {0xbb658000}, {0xbb65a000}, {0xbb65c000}, {0xbb65e000},
+ {0xbb660000}, {0xbb662000}, {0xbb664000}, {0xbb666000},
+ {0xbb668000}, {0xbb66a000}, {0xbb66c000}, {0xbb66e000},
+ {0xbb670000}, {0xbb672000}, {0xbb674000}, {0xbb676000},
+ {0xbb678000}, {0xbb67a000}, {0xbb67c000}, {0xbb67e000},
+ {0xbb680000}, {0xbb682000}, {0xbb684000}, {0xbb686000},
+ {0xbb688000}, {0xbb68a000}, {0xbb68c000}, {0xbb68e000},
+ {0xbb690000}, {0xbb692000}, {0xbb694000}, {0xbb696000},
+ {0xbb698000}, {0xbb69a000}, {0xbb69c000}, {0xbb69e000},
+ {0xbb6a0000}, {0xbb6a2000}, {0xbb6a4000}, {0xbb6a6000},
+ {0xbb6a8000}, {0xbb6aa000}, {0xbb6ac000}, {0xbb6ae000},
+ {0xbb6b0000}, {0xbb6b2000}, {0xbb6b4000}, {0xbb6b6000},
+ {0xbb6b8000}, {0xbb6ba000}, {0xbb6bc000}, {0xbb6be000},
+ {0xbb6c0000}, {0xbb6c2000}, {0xbb6c4000}, {0xbb6c6000},
+ {0xbb6c8000}, {0xbb6ca000}, {0xbb6cc000}, {0xbb6ce000},
+ {0xbb6d0000}, {0xbb6d2000}, {0xbb6d4000}, {0xbb6d6000},
+ {0xbb6d8000}, {0xbb6da000}, {0xbb6dc000}, {0xbb6de000},
+ {0xbb6e0000}, {0xbb6e2000}, {0xbb6e4000}, {0xbb6e6000},
+ {0xbb6e8000}, {0xbb6ea000}, {0xbb6ec000}, {0xbb6ee000},
+ {0xbb6f0000}, {0xbb6f2000}, {0xbb6f4000}, {0xbb6f6000},
+ {0xbb6f8000}, {0xbb6fa000}, {0xbb6fc000}, {0xbb6fe000},
+ {0xbb700000}, {0xbb702000}, {0xbb704000}, {0xbb706000},
+ {0xbb708000}, {0xbb70a000}, {0xbb70c000}, {0xbb70e000},
+ {0xbb710000}, {0xbb712000}, {0xbb714000}, {0xbb716000},
+ {0xbb718000}, {0xbb71a000}, {0xbb71c000}, {0xbb71e000},
+ {0xbb720000}, {0xbb722000}, {0xbb724000}, {0xbb726000},
+ {0xbb728000}, {0xbb72a000}, {0xbb72c000}, {0xbb72e000},
+ {0xbb730000}, {0xbb732000}, {0xbb734000}, {0xbb736000},
+ {0xbb738000}, {0xbb73a000}, {0xbb73c000}, {0xbb73e000},
+ {0xbb740000}, {0xbb742000}, {0xbb744000}, {0xbb746000},
+ {0xbb748000}, {0xbb74a000}, {0xbb74c000}, {0xbb74e000},
+ {0xbb750000}, {0xbb752000}, {0xbb754000}, {0xbb756000},
+ {0xbb758000}, {0xbb75a000}, {0xbb75c000}, {0xbb75e000},
+ {0xbb760000}, {0xbb762000}, {0xbb764000}, {0xbb766000},
+ {0xbb768000}, {0xbb76a000}, {0xbb76c000}, {0xbb76e000},
+ {0xbb770000}, {0xbb772000}, {0xbb774000}, {0xbb776000},
+ {0xbb778000}, {0xbb77a000}, {0xbb77c000}, {0xbb77e000},
+ {0xbb780000}, {0xbb782000}, {0xbb784000}, {0xbb786000},
+ {0xbb788000}, {0xbb78a000}, {0xbb78c000}, {0xbb78e000},
+ {0xbb790000}, {0xbb792000}, {0xbb794000}, {0xbb796000},
+ {0xbb798000}, {0xbb79a000}, {0xbb79c000}, {0xbb79e000},
+ {0xbb7a0000}, {0xbb7a2000}, {0xbb7a4000}, {0xbb7a6000},
+ {0xbb7a8000}, {0xbb7aa000}, {0xbb7ac000}, {0xbb7ae000},
+ {0xbb7b0000}, {0xbb7b2000}, {0xbb7b4000}, {0xbb7b6000},
+ {0xbb7b8000}, {0xbb7ba000}, {0xbb7bc000}, {0xbb7be000},
+ {0xbb7c0000}, {0xbb7c2000}, {0xbb7c4000}, {0xbb7c6000},
+ {0xbb7c8000}, {0xbb7ca000}, {0xbb7cc000}, {0xbb7ce000},
+ {0xbb7d0000}, {0xbb7d2000}, {0xbb7d4000}, {0xbb7d6000},
+ {0xbb7d8000}, {0xbb7da000}, {0xbb7dc000}, {0xbb7de000},
+ {0xbb7e0000}, {0xbb7e2000}, {0xbb7e4000}, {0xbb7e6000},
+ {0xbb7e8000}, {0xbb7ea000}, {0xbb7ec000}, {0xbb7ee000},
+ {0xbb7f0000}, {0xbb7f2000}, {0xbb7f4000}, {0xbb7f6000},
+ {0xbb7f8000}, {0xbb7fa000}, {0xbb7fc000}, {0xbb7fe000},
+ {0xbb800000}, {0xbb802000}, {0xbb804000}, {0xbb806000},
+ {0xbb808000}, {0xbb80a000}, {0xbb80c000}, {0xbb80e000},
+ {0xbb810000}, {0xbb812000}, {0xbb814000}, {0xbb816000},
+ {0xbb818000}, {0xbb81a000}, {0xbb81c000}, {0xbb81e000},
+ {0xbb820000}, {0xbb822000}, {0xbb824000}, {0xbb826000},
+ {0xbb828000}, {0xbb82a000}, {0xbb82c000}, {0xbb82e000},
+ {0xbb830000}, {0xbb832000}, {0xbb834000}, {0xbb836000},
+ {0xbb838000}, {0xbb83a000}, {0xbb83c000}, {0xbb83e000},
+ {0xbb840000}, {0xbb842000}, {0xbb844000}, {0xbb846000},
+ {0xbb848000}, {0xbb84a000}, {0xbb84c000}, {0xbb84e000},
+ {0xbb850000}, {0xbb852000}, {0xbb854000}, {0xbb856000},
+ {0xbb858000}, {0xbb85a000}, {0xbb85c000}, {0xbb85e000},
+ {0xbb860000}, {0xbb862000}, {0xbb864000}, {0xbb866000},
+ {0xbb868000}, {0xbb86a000}, {0xbb86c000}, {0xbb86e000},
+ {0xbb870000}, {0xbb872000}, {0xbb874000}, {0xbb876000},
+ {0xbb878000}, {0xbb87a000}, {0xbb87c000}, {0xbb87e000},
+ {0xbb880000}, {0xbb882000}, {0xbb884000}, {0xbb886000},
+ {0xbb888000}, {0xbb88a000}, {0xbb88c000}, {0xbb88e000},
+ {0xbb890000}, {0xbb892000}, {0xbb894000}, {0xbb896000},
+ {0xbb898000}, {0xbb89a000}, {0xbb89c000}, {0xbb89e000},
+ {0xbb8a0000}, {0xbb8a2000}, {0xbb8a4000}, {0xbb8a6000},
+ {0xbb8a8000}, {0xbb8aa000}, {0xbb8ac000}, {0xbb8ae000},
+ {0xbb8b0000}, {0xbb8b2000}, {0xbb8b4000}, {0xbb8b6000},
+ {0xbb8b8000}, {0xbb8ba000}, {0xbb8bc000}, {0xbb8be000},
+ {0xbb8c0000}, {0xbb8c2000}, {0xbb8c4000}, {0xbb8c6000},
+ {0xbb8c8000}, {0xbb8ca000}, {0xbb8cc000}, {0xbb8ce000},
+ {0xbb8d0000}, {0xbb8d2000}, {0xbb8d4000}, {0xbb8d6000},
+ {0xbb8d8000}, {0xbb8da000}, {0xbb8dc000}, {0xbb8de000},
+ {0xbb8e0000}, {0xbb8e2000}, {0xbb8e4000}, {0xbb8e6000},
+ {0xbb8e8000}, {0xbb8ea000}, {0xbb8ec000}, {0xbb8ee000},
+ {0xbb8f0000}, {0xbb8f2000}, {0xbb8f4000}, {0xbb8f6000},
+ {0xbb8f8000}, {0xbb8fa000}, {0xbb8fc000}, {0xbb8fe000},
+ {0xbb900000}, {0xbb902000}, {0xbb904000}, {0xbb906000},
+ {0xbb908000}, {0xbb90a000}, {0xbb90c000}, {0xbb90e000},
+ {0xbb910000}, {0xbb912000}, {0xbb914000}, {0xbb916000},
+ {0xbb918000}, {0xbb91a000}, {0xbb91c000}, {0xbb91e000},
+ {0xbb920000}, {0xbb922000}, {0xbb924000}, {0xbb926000},
+ {0xbb928000}, {0xbb92a000}, {0xbb92c000}, {0xbb92e000},
+ {0xbb930000}, {0xbb932000}, {0xbb934000}, {0xbb936000},
+ {0xbb938000}, {0xbb93a000}, {0xbb93c000}, {0xbb93e000},
+ {0xbb940000}, {0xbb942000}, {0xbb944000}, {0xbb946000},
+ {0xbb948000}, {0xbb94a000}, {0xbb94c000}, {0xbb94e000},
+ {0xbb950000}, {0xbb952000}, {0xbb954000}, {0xbb956000},
+ {0xbb958000}, {0xbb95a000}, {0xbb95c000}, {0xbb95e000},
+ {0xbb960000}, {0xbb962000}, {0xbb964000}, {0xbb966000},
+ {0xbb968000}, {0xbb96a000}, {0xbb96c000}, {0xbb96e000},
+ {0xbb970000}, {0xbb972000}, {0xbb974000}, {0xbb976000},
+ {0xbb978000}, {0xbb97a000}, {0xbb97c000}, {0xbb97e000},
+ {0xbb980000}, {0xbb982000}, {0xbb984000}, {0xbb986000},
+ {0xbb988000}, {0xbb98a000}, {0xbb98c000}, {0xbb98e000},
+ {0xbb990000}, {0xbb992000}, {0xbb994000}, {0xbb996000},
+ {0xbb998000}, {0xbb99a000}, {0xbb99c000}, {0xbb99e000},
+ {0xbb9a0000}, {0xbb9a2000}, {0xbb9a4000}, {0xbb9a6000},
+ {0xbb9a8000}, {0xbb9aa000}, {0xbb9ac000}, {0xbb9ae000},
+ {0xbb9b0000}, {0xbb9b2000}, {0xbb9b4000}, {0xbb9b6000},
+ {0xbb9b8000}, {0xbb9ba000}, {0xbb9bc000}, {0xbb9be000},
+ {0xbb9c0000}, {0xbb9c2000}, {0xbb9c4000}, {0xbb9c6000},
+ {0xbb9c8000}, {0xbb9ca000}, {0xbb9cc000}, {0xbb9ce000},
+ {0xbb9d0000}, {0xbb9d2000}, {0xbb9d4000}, {0xbb9d6000},
+ {0xbb9d8000}, {0xbb9da000}, {0xbb9dc000}, {0xbb9de000},
+ {0xbb9e0000}, {0xbb9e2000}, {0xbb9e4000}, {0xbb9e6000},
+ {0xbb9e8000}, {0xbb9ea000}, {0xbb9ec000}, {0xbb9ee000},
+ {0xbb9f0000}, {0xbb9f2000}, {0xbb9f4000}, {0xbb9f6000},
+ {0xbb9f8000}, {0xbb9fa000}, {0xbb9fc000}, {0xbb9fe000},
+ {0xbba00000}, {0xbba02000}, {0xbba04000}, {0xbba06000},
+ {0xbba08000}, {0xbba0a000}, {0xbba0c000}, {0xbba0e000},
+ {0xbba10000}, {0xbba12000}, {0xbba14000}, {0xbba16000},
+ {0xbba18000}, {0xbba1a000}, {0xbba1c000}, {0xbba1e000},
+ {0xbba20000}, {0xbba22000}, {0xbba24000}, {0xbba26000},
+ {0xbba28000}, {0xbba2a000}, {0xbba2c000}, {0xbba2e000},
+ {0xbba30000}, {0xbba32000}, {0xbba34000}, {0xbba36000},
+ {0xbba38000}, {0xbba3a000}, {0xbba3c000}, {0xbba3e000},
+ {0xbba40000}, {0xbba42000}, {0xbba44000}, {0xbba46000},
+ {0xbba48000}, {0xbba4a000}, {0xbba4c000}, {0xbba4e000},
+ {0xbba50000}, {0xbba52000}, {0xbba54000}, {0xbba56000},
+ {0xbba58000}, {0xbba5a000}, {0xbba5c000}, {0xbba5e000},
+ {0xbba60000}, {0xbba62000}, {0xbba64000}, {0xbba66000},
+ {0xbba68000}, {0xbba6a000}, {0xbba6c000}, {0xbba6e000},
+ {0xbba70000}, {0xbba72000}, {0xbba74000}, {0xbba76000},
+ {0xbba78000}, {0xbba7a000}, {0xbba7c000}, {0xbba7e000},
+ {0xbba80000}, {0xbba82000}, {0xbba84000}, {0xbba86000},
+ {0xbba88000}, {0xbba8a000}, {0xbba8c000}, {0xbba8e000},
+ {0xbba90000}, {0xbba92000}, {0xbba94000}, {0xbba96000},
+ {0xbba98000}, {0xbba9a000}, {0xbba9c000}, {0xbba9e000},
+ {0xbbaa0000}, {0xbbaa2000}, {0xbbaa4000}, {0xbbaa6000},
+ {0xbbaa8000}, {0xbbaaa000}, {0xbbaac000}, {0xbbaae000},
+ {0xbbab0000}, {0xbbab2000}, {0xbbab4000}, {0xbbab6000},
+ {0xbbab8000}, {0xbbaba000}, {0xbbabc000}, {0xbbabe000},
+ {0xbbac0000}, {0xbbac2000}, {0xbbac4000}, {0xbbac6000},
+ {0xbbac8000}, {0xbbaca000}, {0xbbacc000}, {0xbbace000},
+ {0xbbad0000}, {0xbbad2000}, {0xbbad4000}, {0xbbad6000},
+ {0xbbad8000}, {0xbbada000}, {0xbbadc000}, {0xbbade000},
+ {0xbbae0000}, {0xbbae2000}, {0xbbae4000}, {0xbbae6000},
+ {0xbbae8000}, {0xbbaea000}, {0xbbaec000}, {0xbbaee000},
+ {0xbbaf0000}, {0xbbaf2000}, {0xbbaf4000}, {0xbbaf6000},
+ {0xbbaf8000}, {0xbbafa000}, {0xbbafc000}, {0xbbafe000},
+ {0xbbb00000}, {0xbbb02000}, {0xbbb04000}, {0xbbb06000},
+ {0xbbb08000}, {0xbbb0a000}, {0xbbb0c000}, {0xbbb0e000},
+ {0xbbb10000}, {0xbbb12000}, {0xbbb14000}, {0xbbb16000},
+ {0xbbb18000}, {0xbbb1a000}, {0xbbb1c000}, {0xbbb1e000},
+ {0xbbb20000}, {0xbbb22000}, {0xbbb24000}, {0xbbb26000},
+ {0xbbb28000}, {0xbbb2a000}, {0xbbb2c000}, {0xbbb2e000},
+ {0xbbb30000}, {0xbbb32000}, {0xbbb34000}, {0xbbb36000},
+ {0xbbb38000}, {0xbbb3a000}, {0xbbb3c000}, {0xbbb3e000},
+ {0xbbb40000}, {0xbbb42000}, {0xbbb44000}, {0xbbb46000},
+ {0xbbb48000}, {0xbbb4a000}, {0xbbb4c000}, {0xbbb4e000},
+ {0xbbb50000}, {0xbbb52000}, {0xbbb54000}, {0xbbb56000},
+ {0xbbb58000}, {0xbbb5a000}, {0xbbb5c000}, {0xbbb5e000},
+ {0xbbb60000}, {0xbbb62000}, {0xbbb64000}, {0xbbb66000},
+ {0xbbb68000}, {0xbbb6a000}, {0xbbb6c000}, {0xbbb6e000},
+ {0xbbb70000}, {0xbbb72000}, {0xbbb74000}, {0xbbb76000},
+ {0xbbb78000}, {0xbbb7a000}, {0xbbb7c000}, {0xbbb7e000},
+ {0xbbb80000}, {0xbbb82000}, {0xbbb84000}, {0xbbb86000},
+ {0xbbb88000}, {0xbbb8a000}, {0xbbb8c000}, {0xbbb8e000},
+ {0xbbb90000}, {0xbbb92000}, {0xbbb94000}, {0xbbb96000},
+ {0xbbb98000}, {0xbbb9a000}, {0xbbb9c000}, {0xbbb9e000},
+ {0xbbba0000}, {0xbbba2000}, {0xbbba4000}, {0xbbba6000},
+ {0xbbba8000}, {0xbbbaa000}, {0xbbbac000}, {0xbbbae000},
+ {0xbbbb0000}, {0xbbbb2000}, {0xbbbb4000}, {0xbbbb6000},
+ {0xbbbb8000}, {0xbbbba000}, {0xbbbbc000}, {0xbbbbe000},
+ {0xbbbc0000}, {0xbbbc2000}, {0xbbbc4000}, {0xbbbc6000},
+ {0xbbbc8000}, {0xbbbca000}, {0xbbbcc000}, {0xbbbce000},
+ {0xbbbd0000}, {0xbbbd2000}, {0xbbbd4000}, {0xbbbd6000},
+ {0xbbbd8000}, {0xbbbda000}, {0xbbbdc000}, {0xbbbde000},
+ {0xbbbe0000}, {0xbbbe2000}, {0xbbbe4000}, {0xbbbe6000},
+ {0xbbbe8000}, {0xbbbea000}, {0xbbbec000}, {0xbbbee000},
+ {0xbbbf0000}, {0xbbbf2000}, {0xbbbf4000}, {0xbbbf6000},
+ {0xbbbf8000}, {0xbbbfa000}, {0xbbbfc000}, {0xbbbfe000},
+ {0xbbc00000}, {0xbbc02000}, {0xbbc04000}, {0xbbc06000},
+ {0xbbc08000}, {0xbbc0a000}, {0xbbc0c000}, {0xbbc0e000},
+ {0xbbc10000}, {0xbbc12000}, {0xbbc14000}, {0xbbc16000},
+ {0xbbc18000}, {0xbbc1a000}, {0xbbc1c000}, {0xbbc1e000},
+ {0xbbc20000}, {0xbbc22000}, {0xbbc24000}, {0xbbc26000},
+ {0xbbc28000}, {0xbbc2a000}, {0xbbc2c000}, {0xbbc2e000},
+ {0xbbc30000}, {0xbbc32000}, {0xbbc34000}, {0xbbc36000},
+ {0xbbc38000}, {0xbbc3a000}, {0xbbc3c000}, {0xbbc3e000},
+ {0xbbc40000}, {0xbbc42000}, {0xbbc44000}, {0xbbc46000},
+ {0xbbc48000}, {0xbbc4a000}, {0xbbc4c000}, {0xbbc4e000},
+ {0xbbc50000}, {0xbbc52000}, {0xbbc54000}, {0xbbc56000},
+ {0xbbc58000}, {0xbbc5a000}, {0xbbc5c000}, {0xbbc5e000},
+ {0xbbc60000}, {0xbbc62000}, {0xbbc64000}, {0xbbc66000},
+ {0xbbc68000}, {0xbbc6a000}, {0xbbc6c000}, {0xbbc6e000},
+ {0xbbc70000}, {0xbbc72000}, {0xbbc74000}, {0xbbc76000},
+ {0xbbc78000}, {0xbbc7a000}, {0xbbc7c000}, {0xbbc7e000},
+ {0xbbc80000}, {0xbbc82000}, {0xbbc84000}, {0xbbc86000},
+ {0xbbc88000}, {0xbbc8a000}, {0xbbc8c000}, {0xbbc8e000},
+ {0xbbc90000}, {0xbbc92000}, {0xbbc94000}, {0xbbc96000},
+ {0xbbc98000}, {0xbbc9a000}, {0xbbc9c000}, {0xbbc9e000},
+ {0xbbca0000}, {0xbbca2000}, {0xbbca4000}, {0xbbca6000},
+ {0xbbca8000}, {0xbbcaa000}, {0xbbcac000}, {0xbbcae000},
+ {0xbbcb0000}, {0xbbcb2000}, {0xbbcb4000}, {0xbbcb6000},
+ {0xbbcb8000}, {0xbbcba000}, {0xbbcbc000}, {0xbbcbe000},
+ {0xbbcc0000}, {0xbbcc2000}, {0xbbcc4000}, {0xbbcc6000},
+ {0xbbcc8000}, {0xbbcca000}, {0xbbccc000}, {0xbbcce000},
+ {0xbbcd0000}, {0xbbcd2000}, {0xbbcd4000}, {0xbbcd6000},
+ {0xbbcd8000}, {0xbbcda000}, {0xbbcdc000}, {0xbbcde000},
+ {0xbbce0000}, {0xbbce2000}, {0xbbce4000}, {0xbbce6000},
+ {0xbbce8000}, {0xbbcea000}, {0xbbcec000}, {0xbbcee000},
+ {0xbbcf0000}, {0xbbcf2000}, {0xbbcf4000}, {0xbbcf6000},
+ {0xbbcf8000}, {0xbbcfa000}, {0xbbcfc000}, {0xbbcfe000},
+ {0xbbd00000}, {0xbbd02000}, {0xbbd04000}, {0xbbd06000},
+ {0xbbd08000}, {0xbbd0a000}, {0xbbd0c000}, {0xbbd0e000},
+ {0xbbd10000}, {0xbbd12000}, {0xbbd14000}, {0xbbd16000},
+ {0xbbd18000}, {0xbbd1a000}, {0xbbd1c000}, {0xbbd1e000},
+ {0xbbd20000}, {0xbbd22000}, {0xbbd24000}, {0xbbd26000},
+ {0xbbd28000}, {0xbbd2a000}, {0xbbd2c000}, {0xbbd2e000},
+ {0xbbd30000}, {0xbbd32000}, {0xbbd34000}, {0xbbd36000},
+ {0xbbd38000}, {0xbbd3a000}, {0xbbd3c000}, {0xbbd3e000},
+ {0xbbd40000}, {0xbbd42000}, {0xbbd44000}, {0xbbd46000},
+ {0xbbd48000}, {0xbbd4a000}, {0xbbd4c000}, {0xbbd4e000},
+ {0xbbd50000}, {0xbbd52000}, {0xbbd54000}, {0xbbd56000},
+ {0xbbd58000}, {0xbbd5a000}, {0xbbd5c000}, {0xbbd5e000},
+ {0xbbd60000}, {0xbbd62000}, {0xbbd64000}, {0xbbd66000},
+ {0xbbd68000}, {0xbbd6a000}, {0xbbd6c000}, {0xbbd6e000},
+ {0xbbd70000}, {0xbbd72000}, {0xbbd74000}, {0xbbd76000},
+ {0xbbd78000}, {0xbbd7a000}, {0xbbd7c000}, {0xbbd7e000},
+ {0xbbd80000}, {0xbbd82000}, {0xbbd84000}, {0xbbd86000},
+ {0xbbd88000}, {0xbbd8a000}, {0xbbd8c000}, {0xbbd8e000},
+ {0xbbd90000}, {0xbbd92000}, {0xbbd94000}, {0xbbd96000},
+ {0xbbd98000}, {0xbbd9a000}, {0xbbd9c000}, {0xbbd9e000},
+ {0xbbda0000}, {0xbbda2000}, {0xbbda4000}, {0xbbda6000},
+ {0xbbda8000}, {0xbbdaa000}, {0xbbdac000}, {0xbbdae000},
+ {0xbbdb0000}, {0xbbdb2000}, {0xbbdb4000}, {0xbbdb6000},
+ {0xbbdb8000}, {0xbbdba000}, {0xbbdbc000}, {0xbbdbe000},
+ {0xbbdc0000}, {0xbbdc2000}, {0xbbdc4000}, {0xbbdc6000},
+ {0xbbdc8000}, {0xbbdca000}, {0xbbdcc000}, {0xbbdce000},
+ {0xbbdd0000}, {0xbbdd2000}, {0xbbdd4000}, {0xbbdd6000},
+ {0xbbdd8000}, {0xbbdda000}, {0xbbddc000}, {0xbbdde000},
+ {0xbbde0000}, {0xbbde2000}, {0xbbde4000}, {0xbbde6000},
+ {0xbbde8000}, {0xbbdea000}, {0xbbdec000}, {0xbbdee000},
+ {0xbbdf0000}, {0xbbdf2000}, {0xbbdf4000}, {0xbbdf6000},
+ {0xbbdf8000}, {0xbbdfa000}, {0xbbdfc000}, {0xbbdfe000},
+ {0xbbe00000}, {0xbbe02000}, {0xbbe04000}, {0xbbe06000},
+ {0xbbe08000}, {0xbbe0a000}, {0xbbe0c000}, {0xbbe0e000},
+ {0xbbe10000}, {0xbbe12000}, {0xbbe14000}, {0xbbe16000},
+ {0xbbe18000}, {0xbbe1a000}, {0xbbe1c000}, {0xbbe1e000},
+ {0xbbe20000}, {0xbbe22000}, {0xbbe24000}, {0xbbe26000},
+ {0xbbe28000}, {0xbbe2a000}, {0xbbe2c000}, {0xbbe2e000},
+ {0xbbe30000}, {0xbbe32000}, {0xbbe34000}, {0xbbe36000},
+ {0xbbe38000}, {0xbbe3a000}, {0xbbe3c000}, {0xbbe3e000},
+ {0xbbe40000}, {0xbbe42000}, {0xbbe44000}, {0xbbe46000},
+ {0xbbe48000}, {0xbbe4a000}, {0xbbe4c000}, {0xbbe4e000},
+ {0xbbe50000}, {0xbbe52000}, {0xbbe54000}, {0xbbe56000},
+ {0xbbe58000}, {0xbbe5a000}, {0xbbe5c000}, {0xbbe5e000},
+ {0xbbe60000}, {0xbbe62000}, {0xbbe64000}, {0xbbe66000},
+ {0xbbe68000}, {0xbbe6a000}, {0xbbe6c000}, {0xbbe6e000},
+ {0xbbe70000}, {0xbbe72000}, {0xbbe74000}, {0xbbe76000},
+ {0xbbe78000}, {0xbbe7a000}, {0xbbe7c000}, {0xbbe7e000},
+ {0xbbe80000}, {0xbbe82000}, {0xbbe84000}, {0xbbe86000},
+ {0xbbe88000}, {0xbbe8a000}, {0xbbe8c000}, {0xbbe8e000},
+ {0xbbe90000}, {0xbbe92000}, {0xbbe94000}, {0xbbe96000},
+ {0xbbe98000}, {0xbbe9a000}, {0xbbe9c000}, {0xbbe9e000},
+ {0xbbea0000}, {0xbbea2000}, {0xbbea4000}, {0xbbea6000},
+ {0xbbea8000}, {0xbbeaa000}, {0xbbeac000}, {0xbbeae000},
+ {0xbbeb0000}, {0xbbeb2000}, {0xbbeb4000}, {0xbbeb6000},
+ {0xbbeb8000}, {0xbbeba000}, {0xbbebc000}, {0xbbebe000},
+ {0xbbec0000}, {0xbbec2000}, {0xbbec4000}, {0xbbec6000},
+ {0xbbec8000}, {0xbbeca000}, {0xbbecc000}, {0xbbece000},
+ {0xbbed0000}, {0xbbed2000}, {0xbbed4000}, {0xbbed6000},
+ {0xbbed8000}, {0xbbeda000}, {0xbbedc000}, {0xbbede000},
+ {0xbbee0000}, {0xbbee2000}, {0xbbee4000}, {0xbbee6000},
+ {0xbbee8000}, {0xbbeea000}, {0xbbeec000}, {0xbbeee000},
+ {0xbbef0000}, {0xbbef2000}, {0xbbef4000}, {0xbbef6000},
+ {0xbbef8000}, {0xbbefa000}, {0xbbefc000}, {0xbbefe000},
+ {0xbbf00000}, {0xbbf02000}, {0xbbf04000}, {0xbbf06000},
+ {0xbbf08000}, {0xbbf0a000}, {0xbbf0c000}, {0xbbf0e000},
+ {0xbbf10000}, {0xbbf12000}, {0xbbf14000}, {0xbbf16000},
+ {0xbbf18000}, {0xbbf1a000}, {0xbbf1c000}, {0xbbf1e000},
+ {0xbbf20000}, {0xbbf22000}, {0xbbf24000}, {0xbbf26000},
+ {0xbbf28000}, {0xbbf2a000}, {0xbbf2c000}, {0xbbf2e000},
+ {0xbbf30000}, {0xbbf32000}, {0xbbf34000}, {0xbbf36000},
+ {0xbbf38000}, {0xbbf3a000}, {0xbbf3c000}, {0xbbf3e000},
+ {0xbbf40000}, {0xbbf42000}, {0xbbf44000}, {0xbbf46000},
+ {0xbbf48000}, {0xbbf4a000}, {0xbbf4c000}, {0xbbf4e000},
+ {0xbbf50000}, {0xbbf52000}, {0xbbf54000}, {0xbbf56000},
+ {0xbbf58000}, {0xbbf5a000}, {0xbbf5c000}, {0xbbf5e000},
+ {0xbbf60000}, {0xbbf62000}, {0xbbf64000}, {0xbbf66000},
+ {0xbbf68000}, {0xbbf6a000}, {0xbbf6c000}, {0xbbf6e000},
+ {0xbbf70000}, {0xbbf72000}, {0xbbf74000}, {0xbbf76000},
+ {0xbbf78000}, {0xbbf7a000}, {0xbbf7c000}, {0xbbf7e000},
+ {0xbbf80000}, {0xbbf82000}, {0xbbf84000}, {0xbbf86000},
+ {0xbbf88000}, {0xbbf8a000}, {0xbbf8c000}, {0xbbf8e000},
+ {0xbbf90000}, {0xbbf92000}, {0xbbf94000}, {0xbbf96000},
+ {0xbbf98000}, {0xbbf9a000}, {0xbbf9c000}, {0xbbf9e000},
+ {0xbbfa0000}, {0xbbfa2000}, {0xbbfa4000}, {0xbbfa6000},
+ {0xbbfa8000}, {0xbbfaa000}, {0xbbfac000}, {0xbbfae000},
+ {0xbbfb0000}, {0xbbfb2000}, {0xbbfb4000}, {0xbbfb6000},
+ {0xbbfb8000}, {0xbbfba000}, {0xbbfbc000}, {0xbbfbe000},
+ {0xbbfc0000}, {0xbbfc2000}, {0xbbfc4000}, {0xbbfc6000},
+ {0xbbfc8000}, {0xbbfca000}, {0xbbfcc000}, {0xbbfce000},
+ {0xbbfd0000}, {0xbbfd2000}, {0xbbfd4000}, {0xbbfd6000},
+ {0xbbfd8000}, {0xbbfda000}, {0xbbfdc000}, {0xbbfde000},
+ {0xbbfe0000}, {0xbbfe2000}, {0xbbfe4000}, {0xbbfe6000},
+ {0xbbfe8000}, {0xbbfea000}, {0xbbfec000}, {0xbbfee000},
+ {0xbbff0000}, {0xbbff2000}, {0xbbff4000}, {0xbbff6000},
+ {0xbbff8000}, {0xbbffa000}, {0xbbffc000}, {0xbbffe000},
+ {0xbc000000}, {0xbc002000}, {0xbc004000}, {0xbc006000},
+ {0xbc008000}, {0xbc00a000}, {0xbc00c000}, {0xbc00e000},
+ {0xbc010000}, {0xbc012000}, {0xbc014000}, {0xbc016000},
+ {0xbc018000}, {0xbc01a000}, {0xbc01c000}, {0xbc01e000},
+ {0xbc020000}, {0xbc022000}, {0xbc024000}, {0xbc026000},
+ {0xbc028000}, {0xbc02a000}, {0xbc02c000}, {0xbc02e000},
+ {0xbc030000}, {0xbc032000}, {0xbc034000}, {0xbc036000},
+ {0xbc038000}, {0xbc03a000}, {0xbc03c000}, {0xbc03e000},
+ {0xbc040000}, {0xbc042000}, {0xbc044000}, {0xbc046000},
+ {0xbc048000}, {0xbc04a000}, {0xbc04c000}, {0xbc04e000},
+ {0xbc050000}, {0xbc052000}, {0xbc054000}, {0xbc056000},
+ {0xbc058000}, {0xbc05a000}, {0xbc05c000}, {0xbc05e000},
+ {0xbc060000}, {0xbc062000}, {0xbc064000}, {0xbc066000},
+ {0xbc068000}, {0xbc06a000}, {0xbc06c000}, {0xbc06e000},
+ {0xbc070000}, {0xbc072000}, {0xbc074000}, {0xbc076000},
+ {0xbc078000}, {0xbc07a000}, {0xbc07c000}, {0xbc07e000},
+ {0xbc080000}, {0xbc082000}, {0xbc084000}, {0xbc086000},
+ {0xbc088000}, {0xbc08a000}, {0xbc08c000}, {0xbc08e000},
+ {0xbc090000}, {0xbc092000}, {0xbc094000}, {0xbc096000},
+ {0xbc098000}, {0xbc09a000}, {0xbc09c000}, {0xbc09e000},
+ {0xbc0a0000}, {0xbc0a2000}, {0xbc0a4000}, {0xbc0a6000},
+ {0xbc0a8000}, {0xbc0aa000}, {0xbc0ac000}, {0xbc0ae000},
+ {0xbc0b0000}, {0xbc0b2000}, {0xbc0b4000}, {0xbc0b6000},
+ {0xbc0b8000}, {0xbc0ba000}, {0xbc0bc000}, {0xbc0be000},
+ {0xbc0c0000}, {0xbc0c2000}, {0xbc0c4000}, {0xbc0c6000},
+ {0xbc0c8000}, {0xbc0ca000}, {0xbc0cc000}, {0xbc0ce000},
+ {0xbc0d0000}, {0xbc0d2000}, {0xbc0d4000}, {0xbc0d6000},
+ {0xbc0d8000}, {0xbc0da000}, {0xbc0dc000}, {0xbc0de000},
+ {0xbc0e0000}, {0xbc0e2000}, {0xbc0e4000}, {0xbc0e6000},
+ {0xbc0e8000}, {0xbc0ea000}, {0xbc0ec000}, {0xbc0ee000},
+ {0xbc0f0000}, {0xbc0f2000}, {0xbc0f4000}, {0xbc0f6000},
+ {0xbc0f8000}, {0xbc0fa000}, {0xbc0fc000}, {0xbc0fe000},
+ {0xbc100000}, {0xbc102000}, {0xbc104000}, {0xbc106000},
+ {0xbc108000}, {0xbc10a000}, {0xbc10c000}, {0xbc10e000},
+ {0xbc110000}, {0xbc112000}, {0xbc114000}, {0xbc116000},
+ {0xbc118000}, {0xbc11a000}, {0xbc11c000}, {0xbc11e000},
+ {0xbc120000}, {0xbc122000}, {0xbc124000}, {0xbc126000},
+ {0xbc128000}, {0xbc12a000}, {0xbc12c000}, {0xbc12e000},
+ {0xbc130000}, {0xbc132000}, {0xbc134000}, {0xbc136000},
+ {0xbc138000}, {0xbc13a000}, {0xbc13c000}, {0xbc13e000},
+ {0xbc140000}, {0xbc142000}, {0xbc144000}, {0xbc146000},
+ {0xbc148000}, {0xbc14a000}, {0xbc14c000}, {0xbc14e000},
+ {0xbc150000}, {0xbc152000}, {0xbc154000}, {0xbc156000},
+ {0xbc158000}, {0xbc15a000}, {0xbc15c000}, {0xbc15e000},
+ {0xbc160000}, {0xbc162000}, {0xbc164000}, {0xbc166000},
+ {0xbc168000}, {0xbc16a000}, {0xbc16c000}, {0xbc16e000},
+ {0xbc170000}, {0xbc172000}, {0xbc174000}, {0xbc176000},
+ {0xbc178000}, {0xbc17a000}, {0xbc17c000}, {0xbc17e000},
+ {0xbc180000}, {0xbc182000}, {0xbc184000}, {0xbc186000},
+ {0xbc188000}, {0xbc18a000}, {0xbc18c000}, {0xbc18e000},
+ {0xbc190000}, {0xbc192000}, {0xbc194000}, {0xbc196000},
+ {0xbc198000}, {0xbc19a000}, {0xbc19c000}, {0xbc19e000},
+ {0xbc1a0000}, {0xbc1a2000}, {0xbc1a4000}, {0xbc1a6000},
+ {0xbc1a8000}, {0xbc1aa000}, {0xbc1ac000}, {0xbc1ae000},
+ {0xbc1b0000}, {0xbc1b2000}, {0xbc1b4000}, {0xbc1b6000},
+ {0xbc1b8000}, {0xbc1ba000}, {0xbc1bc000}, {0xbc1be000},
+ {0xbc1c0000}, {0xbc1c2000}, {0xbc1c4000}, {0xbc1c6000},
+ {0xbc1c8000}, {0xbc1ca000}, {0xbc1cc000}, {0xbc1ce000},
+ {0xbc1d0000}, {0xbc1d2000}, {0xbc1d4000}, {0xbc1d6000},
+ {0xbc1d8000}, {0xbc1da000}, {0xbc1dc000}, {0xbc1de000},
+ {0xbc1e0000}, {0xbc1e2000}, {0xbc1e4000}, {0xbc1e6000},
+ {0xbc1e8000}, {0xbc1ea000}, {0xbc1ec000}, {0xbc1ee000},
+ {0xbc1f0000}, {0xbc1f2000}, {0xbc1f4000}, {0xbc1f6000},
+ {0xbc1f8000}, {0xbc1fa000}, {0xbc1fc000}, {0xbc1fe000},
+ {0xbc200000}, {0xbc202000}, {0xbc204000}, {0xbc206000},
+ {0xbc208000}, {0xbc20a000}, {0xbc20c000}, {0xbc20e000},
+ {0xbc210000}, {0xbc212000}, {0xbc214000}, {0xbc216000},
+ {0xbc218000}, {0xbc21a000}, {0xbc21c000}, {0xbc21e000},
+ {0xbc220000}, {0xbc222000}, {0xbc224000}, {0xbc226000},
+ {0xbc228000}, {0xbc22a000}, {0xbc22c000}, {0xbc22e000},
+ {0xbc230000}, {0xbc232000}, {0xbc234000}, {0xbc236000},
+ {0xbc238000}, {0xbc23a000}, {0xbc23c000}, {0xbc23e000},
+ {0xbc240000}, {0xbc242000}, {0xbc244000}, {0xbc246000},
+ {0xbc248000}, {0xbc24a000}, {0xbc24c000}, {0xbc24e000},
+ {0xbc250000}, {0xbc252000}, {0xbc254000}, {0xbc256000},
+ {0xbc258000}, {0xbc25a000}, {0xbc25c000}, {0xbc25e000},
+ {0xbc260000}, {0xbc262000}, {0xbc264000}, {0xbc266000},
+ {0xbc268000}, {0xbc26a000}, {0xbc26c000}, {0xbc26e000},
+ {0xbc270000}, {0xbc272000}, {0xbc274000}, {0xbc276000},
+ {0xbc278000}, {0xbc27a000}, {0xbc27c000}, {0xbc27e000},
+ {0xbc280000}, {0xbc282000}, {0xbc284000}, {0xbc286000},
+ {0xbc288000}, {0xbc28a000}, {0xbc28c000}, {0xbc28e000},
+ {0xbc290000}, {0xbc292000}, {0xbc294000}, {0xbc296000},
+ {0xbc298000}, {0xbc29a000}, {0xbc29c000}, {0xbc29e000},
+ {0xbc2a0000}, {0xbc2a2000}, {0xbc2a4000}, {0xbc2a6000},
+ {0xbc2a8000}, {0xbc2aa000}, {0xbc2ac000}, {0xbc2ae000},
+ {0xbc2b0000}, {0xbc2b2000}, {0xbc2b4000}, {0xbc2b6000},
+ {0xbc2b8000}, {0xbc2ba000}, {0xbc2bc000}, {0xbc2be000},
+ {0xbc2c0000}, {0xbc2c2000}, {0xbc2c4000}, {0xbc2c6000},
+ {0xbc2c8000}, {0xbc2ca000}, {0xbc2cc000}, {0xbc2ce000},
+ {0xbc2d0000}, {0xbc2d2000}, {0xbc2d4000}, {0xbc2d6000},
+ {0xbc2d8000}, {0xbc2da000}, {0xbc2dc000}, {0xbc2de000},
+ {0xbc2e0000}, {0xbc2e2000}, {0xbc2e4000}, {0xbc2e6000},
+ {0xbc2e8000}, {0xbc2ea000}, {0xbc2ec000}, {0xbc2ee000},
+ {0xbc2f0000}, {0xbc2f2000}, {0xbc2f4000}, {0xbc2f6000},
+ {0xbc2f8000}, {0xbc2fa000}, {0xbc2fc000}, {0xbc2fe000},
+ {0xbc300000}, {0xbc302000}, {0xbc304000}, {0xbc306000},
+ {0xbc308000}, {0xbc30a000}, {0xbc30c000}, {0xbc30e000},
+ {0xbc310000}, {0xbc312000}, {0xbc314000}, {0xbc316000},
+ {0xbc318000}, {0xbc31a000}, {0xbc31c000}, {0xbc31e000},
+ {0xbc320000}, {0xbc322000}, {0xbc324000}, {0xbc326000},
+ {0xbc328000}, {0xbc32a000}, {0xbc32c000}, {0xbc32e000},
+ {0xbc330000}, {0xbc332000}, {0xbc334000}, {0xbc336000},
+ {0xbc338000}, {0xbc33a000}, {0xbc33c000}, {0xbc33e000},
+ {0xbc340000}, {0xbc342000}, {0xbc344000}, {0xbc346000},
+ {0xbc348000}, {0xbc34a000}, {0xbc34c000}, {0xbc34e000},
+ {0xbc350000}, {0xbc352000}, {0xbc354000}, {0xbc356000},
+ {0xbc358000}, {0xbc35a000}, {0xbc35c000}, {0xbc35e000},
+ {0xbc360000}, {0xbc362000}, {0xbc364000}, {0xbc366000},
+ {0xbc368000}, {0xbc36a000}, {0xbc36c000}, {0xbc36e000},
+ {0xbc370000}, {0xbc372000}, {0xbc374000}, {0xbc376000},
+ {0xbc378000}, {0xbc37a000}, {0xbc37c000}, {0xbc37e000},
+ {0xbc380000}, {0xbc382000}, {0xbc384000}, {0xbc386000},
+ {0xbc388000}, {0xbc38a000}, {0xbc38c000}, {0xbc38e000},
+ {0xbc390000}, {0xbc392000}, {0xbc394000}, {0xbc396000},
+ {0xbc398000}, {0xbc39a000}, {0xbc39c000}, {0xbc39e000},
+ {0xbc3a0000}, {0xbc3a2000}, {0xbc3a4000}, {0xbc3a6000},
+ {0xbc3a8000}, {0xbc3aa000}, {0xbc3ac000}, {0xbc3ae000},
+ {0xbc3b0000}, {0xbc3b2000}, {0xbc3b4000}, {0xbc3b6000},
+ {0xbc3b8000}, {0xbc3ba000}, {0xbc3bc000}, {0xbc3be000},
+ {0xbc3c0000}, {0xbc3c2000}, {0xbc3c4000}, {0xbc3c6000},
+ {0xbc3c8000}, {0xbc3ca000}, {0xbc3cc000}, {0xbc3ce000},
+ {0xbc3d0000}, {0xbc3d2000}, {0xbc3d4000}, {0xbc3d6000},
+ {0xbc3d8000}, {0xbc3da000}, {0xbc3dc000}, {0xbc3de000},
+ {0xbc3e0000}, {0xbc3e2000}, {0xbc3e4000}, {0xbc3e6000},
+ {0xbc3e8000}, {0xbc3ea000}, {0xbc3ec000}, {0xbc3ee000},
+ {0xbc3f0000}, {0xbc3f2000}, {0xbc3f4000}, {0xbc3f6000},
+ {0xbc3f8000}, {0xbc3fa000}, {0xbc3fc000}, {0xbc3fe000},
+ {0xbc400000}, {0xbc402000}, {0xbc404000}, {0xbc406000},
+ {0xbc408000}, {0xbc40a000}, {0xbc40c000}, {0xbc40e000},
+ {0xbc410000}, {0xbc412000}, {0xbc414000}, {0xbc416000},
+ {0xbc418000}, {0xbc41a000}, {0xbc41c000}, {0xbc41e000},
+ {0xbc420000}, {0xbc422000}, {0xbc424000}, {0xbc426000},
+ {0xbc428000}, {0xbc42a000}, {0xbc42c000}, {0xbc42e000},
+ {0xbc430000}, {0xbc432000}, {0xbc434000}, {0xbc436000},
+ {0xbc438000}, {0xbc43a000}, {0xbc43c000}, {0xbc43e000},
+ {0xbc440000}, {0xbc442000}, {0xbc444000}, {0xbc446000},
+ {0xbc448000}, {0xbc44a000}, {0xbc44c000}, {0xbc44e000},
+ {0xbc450000}, {0xbc452000}, {0xbc454000}, {0xbc456000},
+ {0xbc458000}, {0xbc45a000}, {0xbc45c000}, {0xbc45e000},
+ {0xbc460000}, {0xbc462000}, {0xbc464000}, {0xbc466000},
+ {0xbc468000}, {0xbc46a000}, {0xbc46c000}, {0xbc46e000},
+ {0xbc470000}, {0xbc472000}, {0xbc474000}, {0xbc476000},
+ {0xbc478000}, {0xbc47a000}, {0xbc47c000}, {0xbc47e000},
+ {0xbc480000}, {0xbc482000}, {0xbc484000}, {0xbc486000},
+ {0xbc488000}, {0xbc48a000}, {0xbc48c000}, {0xbc48e000},
+ {0xbc490000}, {0xbc492000}, {0xbc494000}, {0xbc496000},
+ {0xbc498000}, {0xbc49a000}, {0xbc49c000}, {0xbc49e000},
+ {0xbc4a0000}, {0xbc4a2000}, {0xbc4a4000}, {0xbc4a6000},
+ {0xbc4a8000}, {0xbc4aa000}, {0xbc4ac000}, {0xbc4ae000},
+ {0xbc4b0000}, {0xbc4b2000}, {0xbc4b4000}, {0xbc4b6000},
+ {0xbc4b8000}, {0xbc4ba000}, {0xbc4bc000}, {0xbc4be000},
+ {0xbc4c0000}, {0xbc4c2000}, {0xbc4c4000}, {0xbc4c6000},
+ {0xbc4c8000}, {0xbc4ca000}, {0xbc4cc000}, {0xbc4ce000},
+ {0xbc4d0000}, {0xbc4d2000}, {0xbc4d4000}, {0xbc4d6000},
+ {0xbc4d8000}, {0xbc4da000}, {0xbc4dc000}, {0xbc4de000},
+ {0xbc4e0000}, {0xbc4e2000}, {0xbc4e4000}, {0xbc4e6000},
+ {0xbc4e8000}, {0xbc4ea000}, {0xbc4ec000}, {0xbc4ee000},
+ {0xbc4f0000}, {0xbc4f2000}, {0xbc4f4000}, {0xbc4f6000},
+ {0xbc4f8000}, {0xbc4fa000}, {0xbc4fc000}, {0xbc4fe000},
+ {0xbc500000}, {0xbc502000}, {0xbc504000}, {0xbc506000},
+ {0xbc508000}, {0xbc50a000}, {0xbc50c000}, {0xbc50e000},
+ {0xbc510000}, {0xbc512000}, {0xbc514000}, {0xbc516000},
+ {0xbc518000}, {0xbc51a000}, {0xbc51c000}, {0xbc51e000},
+ {0xbc520000}, {0xbc522000}, {0xbc524000}, {0xbc526000},
+ {0xbc528000}, {0xbc52a000}, {0xbc52c000}, {0xbc52e000},
+ {0xbc530000}, {0xbc532000}, {0xbc534000}, {0xbc536000},
+ {0xbc538000}, {0xbc53a000}, {0xbc53c000}, {0xbc53e000},
+ {0xbc540000}, {0xbc542000}, {0xbc544000}, {0xbc546000},
+ {0xbc548000}, {0xbc54a000}, {0xbc54c000}, {0xbc54e000},
+ {0xbc550000}, {0xbc552000}, {0xbc554000}, {0xbc556000},
+ {0xbc558000}, {0xbc55a000}, {0xbc55c000}, {0xbc55e000},
+ {0xbc560000}, {0xbc562000}, {0xbc564000}, {0xbc566000},
+ {0xbc568000}, {0xbc56a000}, {0xbc56c000}, {0xbc56e000},
+ {0xbc570000}, {0xbc572000}, {0xbc574000}, {0xbc576000},
+ {0xbc578000}, {0xbc57a000}, {0xbc57c000}, {0xbc57e000},
+ {0xbc580000}, {0xbc582000}, {0xbc584000}, {0xbc586000},
+ {0xbc588000}, {0xbc58a000}, {0xbc58c000}, {0xbc58e000},
+ {0xbc590000}, {0xbc592000}, {0xbc594000}, {0xbc596000},
+ {0xbc598000}, {0xbc59a000}, {0xbc59c000}, {0xbc59e000},
+ {0xbc5a0000}, {0xbc5a2000}, {0xbc5a4000}, {0xbc5a6000},
+ {0xbc5a8000}, {0xbc5aa000}, {0xbc5ac000}, {0xbc5ae000},
+ {0xbc5b0000}, {0xbc5b2000}, {0xbc5b4000}, {0xbc5b6000},
+ {0xbc5b8000}, {0xbc5ba000}, {0xbc5bc000}, {0xbc5be000},
+ {0xbc5c0000}, {0xbc5c2000}, {0xbc5c4000}, {0xbc5c6000},
+ {0xbc5c8000}, {0xbc5ca000}, {0xbc5cc000}, {0xbc5ce000},
+ {0xbc5d0000}, {0xbc5d2000}, {0xbc5d4000}, {0xbc5d6000},
+ {0xbc5d8000}, {0xbc5da000}, {0xbc5dc000}, {0xbc5de000},
+ {0xbc5e0000}, {0xbc5e2000}, {0xbc5e4000}, {0xbc5e6000},
+ {0xbc5e8000}, {0xbc5ea000}, {0xbc5ec000}, {0xbc5ee000},
+ {0xbc5f0000}, {0xbc5f2000}, {0xbc5f4000}, {0xbc5f6000},
+ {0xbc5f8000}, {0xbc5fa000}, {0xbc5fc000}, {0xbc5fe000},
+ {0xbc600000}, {0xbc602000}, {0xbc604000}, {0xbc606000},
+ {0xbc608000}, {0xbc60a000}, {0xbc60c000}, {0xbc60e000},
+ {0xbc610000}, {0xbc612000}, {0xbc614000}, {0xbc616000},
+ {0xbc618000}, {0xbc61a000}, {0xbc61c000}, {0xbc61e000},
+ {0xbc620000}, {0xbc622000}, {0xbc624000}, {0xbc626000},
+ {0xbc628000}, {0xbc62a000}, {0xbc62c000}, {0xbc62e000},
+ {0xbc630000}, {0xbc632000}, {0xbc634000}, {0xbc636000},
+ {0xbc638000}, {0xbc63a000}, {0xbc63c000}, {0xbc63e000},
+ {0xbc640000}, {0xbc642000}, {0xbc644000}, {0xbc646000},
+ {0xbc648000}, {0xbc64a000}, {0xbc64c000}, {0xbc64e000},
+ {0xbc650000}, {0xbc652000}, {0xbc654000}, {0xbc656000},
+ {0xbc658000}, {0xbc65a000}, {0xbc65c000}, {0xbc65e000},
+ {0xbc660000}, {0xbc662000}, {0xbc664000}, {0xbc666000},
+ {0xbc668000}, {0xbc66a000}, {0xbc66c000}, {0xbc66e000},
+ {0xbc670000}, {0xbc672000}, {0xbc674000}, {0xbc676000},
+ {0xbc678000}, {0xbc67a000}, {0xbc67c000}, {0xbc67e000},
+ {0xbc680000}, {0xbc682000}, {0xbc684000}, {0xbc686000},
+ {0xbc688000}, {0xbc68a000}, {0xbc68c000}, {0xbc68e000},
+ {0xbc690000}, {0xbc692000}, {0xbc694000}, {0xbc696000},
+ {0xbc698000}, {0xbc69a000}, {0xbc69c000}, {0xbc69e000},
+ {0xbc6a0000}, {0xbc6a2000}, {0xbc6a4000}, {0xbc6a6000},
+ {0xbc6a8000}, {0xbc6aa000}, {0xbc6ac000}, {0xbc6ae000},
+ {0xbc6b0000}, {0xbc6b2000}, {0xbc6b4000}, {0xbc6b6000},
+ {0xbc6b8000}, {0xbc6ba000}, {0xbc6bc000}, {0xbc6be000},
+ {0xbc6c0000}, {0xbc6c2000}, {0xbc6c4000}, {0xbc6c6000},
+ {0xbc6c8000}, {0xbc6ca000}, {0xbc6cc000}, {0xbc6ce000},
+ {0xbc6d0000}, {0xbc6d2000}, {0xbc6d4000}, {0xbc6d6000},
+ {0xbc6d8000}, {0xbc6da000}, {0xbc6dc000}, {0xbc6de000},
+ {0xbc6e0000}, {0xbc6e2000}, {0xbc6e4000}, {0xbc6e6000},
+ {0xbc6e8000}, {0xbc6ea000}, {0xbc6ec000}, {0xbc6ee000},
+ {0xbc6f0000}, {0xbc6f2000}, {0xbc6f4000}, {0xbc6f6000},
+ {0xbc6f8000}, {0xbc6fa000}, {0xbc6fc000}, {0xbc6fe000},
+ {0xbc700000}, {0xbc702000}, {0xbc704000}, {0xbc706000},
+ {0xbc708000}, {0xbc70a000}, {0xbc70c000}, {0xbc70e000},
+ {0xbc710000}, {0xbc712000}, {0xbc714000}, {0xbc716000},
+ {0xbc718000}, {0xbc71a000}, {0xbc71c000}, {0xbc71e000},
+ {0xbc720000}, {0xbc722000}, {0xbc724000}, {0xbc726000},
+ {0xbc728000}, {0xbc72a000}, {0xbc72c000}, {0xbc72e000},
+ {0xbc730000}, {0xbc732000}, {0xbc734000}, {0xbc736000},
+ {0xbc738000}, {0xbc73a000}, {0xbc73c000}, {0xbc73e000},
+ {0xbc740000}, {0xbc742000}, {0xbc744000}, {0xbc746000},
+ {0xbc748000}, {0xbc74a000}, {0xbc74c000}, {0xbc74e000},
+ {0xbc750000}, {0xbc752000}, {0xbc754000}, {0xbc756000},
+ {0xbc758000}, {0xbc75a000}, {0xbc75c000}, {0xbc75e000},
+ {0xbc760000}, {0xbc762000}, {0xbc764000}, {0xbc766000},
+ {0xbc768000}, {0xbc76a000}, {0xbc76c000}, {0xbc76e000},
+ {0xbc770000}, {0xbc772000}, {0xbc774000}, {0xbc776000},
+ {0xbc778000}, {0xbc77a000}, {0xbc77c000}, {0xbc77e000},
+ {0xbc780000}, {0xbc782000}, {0xbc784000}, {0xbc786000},
+ {0xbc788000}, {0xbc78a000}, {0xbc78c000}, {0xbc78e000},
+ {0xbc790000}, {0xbc792000}, {0xbc794000}, {0xbc796000},
+ {0xbc798000}, {0xbc79a000}, {0xbc79c000}, {0xbc79e000},
+ {0xbc7a0000}, {0xbc7a2000}, {0xbc7a4000}, {0xbc7a6000},
+ {0xbc7a8000}, {0xbc7aa000}, {0xbc7ac000}, {0xbc7ae000},
+ {0xbc7b0000}, {0xbc7b2000}, {0xbc7b4000}, {0xbc7b6000},
+ {0xbc7b8000}, {0xbc7ba000}, {0xbc7bc000}, {0xbc7be000},
+ {0xbc7c0000}, {0xbc7c2000}, {0xbc7c4000}, {0xbc7c6000},
+ {0xbc7c8000}, {0xbc7ca000}, {0xbc7cc000}, {0xbc7ce000},
+ {0xbc7d0000}, {0xbc7d2000}, {0xbc7d4000}, {0xbc7d6000},
+ {0xbc7d8000}, {0xbc7da000}, {0xbc7dc000}, {0xbc7de000},
+ {0xbc7e0000}, {0xbc7e2000}, {0xbc7e4000}, {0xbc7e6000},
+ {0xbc7e8000}, {0xbc7ea000}, {0xbc7ec000}, {0xbc7ee000},
+ {0xbc7f0000}, {0xbc7f2000}, {0xbc7f4000}, {0xbc7f6000},
+ {0xbc7f8000}, {0xbc7fa000}, {0xbc7fc000}, {0xbc7fe000},
+ {0xbc800000}, {0xbc802000}, {0xbc804000}, {0xbc806000},
+ {0xbc808000}, {0xbc80a000}, {0xbc80c000}, {0xbc80e000},
+ {0xbc810000}, {0xbc812000}, {0xbc814000}, {0xbc816000},
+ {0xbc818000}, {0xbc81a000}, {0xbc81c000}, {0xbc81e000},
+ {0xbc820000}, {0xbc822000}, {0xbc824000}, {0xbc826000},
+ {0xbc828000}, {0xbc82a000}, {0xbc82c000}, {0xbc82e000},
+ {0xbc830000}, {0xbc832000}, {0xbc834000}, {0xbc836000},
+ {0xbc838000}, {0xbc83a000}, {0xbc83c000}, {0xbc83e000},
+ {0xbc840000}, {0xbc842000}, {0xbc844000}, {0xbc846000},
+ {0xbc848000}, {0xbc84a000}, {0xbc84c000}, {0xbc84e000},
+ {0xbc850000}, {0xbc852000}, {0xbc854000}, {0xbc856000},
+ {0xbc858000}, {0xbc85a000}, {0xbc85c000}, {0xbc85e000},
+ {0xbc860000}, {0xbc862000}, {0xbc864000}, {0xbc866000},
+ {0xbc868000}, {0xbc86a000}, {0xbc86c000}, {0xbc86e000},
+ {0xbc870000}, {0xbc872000}, {0xbc874000}, {0xbc876000},
+ {0xbc878000}, {0xbc87a000}, {0xbc87c000}, {0xbc87e000},
+ {0xbc880000}, {0xbc882000}, {0xbc884000}, {0xbc886000},
+ {0xbc888000}, {0xbc88a000}, {0xbc88c000}, {0xbc88e000},
+ {0xbc890000}, {0xbc892000}, {0xbc894000}, {0xbc896000},
+ {0xbc898000}, {0xbc89a000}, {0xbc89c000}, {0xbc89e000},
+ {0xbc8a0000}, {0xbc8a2000}, {0xbc8a4000}, {0xbc8a6000},
+ {0xbc8a8000}, {0xbc8aa000}, {0xbc8ac000}, {0xbc8ae000},
+ {0xbc8b0000}, {0xbc8b2000}, {0xbc8b4000}, {0xbc8b6000},
+ {0xbc8b8000}, {0xbc8ba000}, {0xbc8bc000}, {0xbc8be000},
+ {0xbc8c0000}, {0xbc8c2000}, {0xbc8c4000}, {0xbc8c6000},
+ {0xbc8c8000}, {0xbc8ca000}, {0xbc8cc000}, {0xbc8ce000},
+ {0xbc8d0000}, {0xbc8d2000}, {0xbc8d4000}, {0xbc8d6000},
+ {0xbc8d8000}, {0xbc8da000}, {0xbc8dc000}, {0xbc8de000},
+ {0xbc8e0000}, {0xbc8e2000}, {0xbc8e4000}, {0xbc8e6000},
+ {0xbc8e8000}, {0xbc8ea000}, {0xbc8ec000}, {0xbc8ee000},
+ {0xbc8f0000}, {0xbc8f2000}, {0xbc8f4000}, {0xbc8f6000},
+ {0xbc8f8000}, {0xbc8fa000}, {0xbc8fc000}, {0xbc8fe000},
+ {0xbc900000}, {0xbc902000}, {0xbc904000}, {0xbc906000},
+ {0xbc908000}, {0xbc90a000}, {0xbc90c000}, {0xbc90e000},
+ {0xbc910000}, {0xbc912000}, {0xbc914000}, {0xbc916000},
+ {0xbc918000}, {0xbc91a000}, {0xbc91c000}, {0xbc91e000},
+ {0xbc920000}, {0xbc922000}, {0xbc924000}, {0xbc926000},
+ {0xbc928000}, {0xbc92a000}, {0xbc92c000}, {0xbc92e000},
+ {0xbc930000}, {0xbc932000}, {0xbc934000}, {0xbc936000},
+ {0xbc938000}, {0xbc93a000}, {0xbc93c000}, {0xbc93e000},
+ {0xbc940000}, {0xbc942000}, {0xbc944000}, {0xbc946000},
+ {0xbc948000}, {0xbc94a000}, {0xbc94c000}, {0xbc94e000},
+ {0xbc950000}, {0xbc952000}, {0xbc954000}, {0xbc956000},
+ {0xbc958000}, {0xbc95a000}, {0xbc95c000}, {0xbc95e000},
+ {0xbc960000}, {0xbc962000}, {0xbc964000}, {0xbc966000},
+ {0xbc968000}, {0xbc96a000}, {0xbc96c000}, {0xbc96e000},
+ {0xbc970000}, {0xbc972000}, {0xbc974000}, {0xbc976000},
+ {0xbc978000}, {0xbc97a000}, {0xbc97c000}, {0xbc97e000},
+ {0xbc980000}, {0xbc982000}, {0xbc984000}, {0xbc986000},
+ {0xbc988000}, {0xbc98a000}, {0xbc98c000}, {0xbc98e000},
+ {0xbc990000}, {0xbc992000}, {0xbc994000}, {0xbc996000},
+ {0xbc998000}, {0xbc99a000}, {0xbc99c000}, {0xbc99e000},
+ {0xbc9a0000}, {0xbc9a2000}, {0xbc9a4000}, {0xbc9a6000},
+ {0xbc9a8000}, {0xbc9aa000}, {0xbc9ac000}, {0xbc9ae000},
+ {0xbc9b0000}, {0xbc9b2000}, {0xbc9b4000}, {0xbc9b6000},
+ {0xbc9b8000}, {0xbc9ba000}, {0xbc9bc000}, {0xbc9be000},
+ {0xbc9c0000}, {0xbc9c2000}, {0xbc9c4000}, {0xbc9c6000},
+ {0xbc9c8000}, {0xbc9ca000}, {0xbc9cc000}, {0xbc9ce000},
+ {0xbc9d0000}, {0xbc9d2000}, {0xbc9d4000}, {0xbc9d6000},
+ {0xbc9d8000}, {0xbc9da000}, {0xbc9dc000}, {0xbc9de000},
+ {0xbc9e0000}, {0xbc9e2000}, {0xbc9e4000}, {0xbc9e6000},
+ {0xbc9e8000}, {0xbc9ea000}, {0xbc9ec000}, {0xbc9ee000},
+ {0xbc9f0000}, {0xbc9f2000}, {0xbc9f4000}, {0xbc9f6000},
+ {0xbc9f8000}, {0xbc9fa000}, {0xbc9fc000}, {0xbc9fe000},
+ {0xbca00000}, {0xbca02000}, {0xbca04000}, {0xbca06000},
+ {0xbca08000}, {0xbca0a000}, {0xbca0c000}, {0xbca0e000},
+ {0xbca10000}, {0xbca12000}, {0xbca14000}, {0xbca16000},
+ {0xbca18000}, {0xbca1a000}, {0xbca1c000}, {0xbca1e000},
+ {0xbca20000}, {0xbca22000}, {0xbca24000}, {0xbca26000},
+ {0xbca28000}, {0xbca2a000}, {0xbca2c000}, {0xbca2e000},
+ {0xbca30000}, {0xbca32000}, {0xbca34000}, {0xbca36000},
+ {0xbca38000}, {0xbca3a000}, {0xbca3c000}, {0xbca3e000},
+ {0xbca40000}, {0xbca42000}, {0xbca44000}, {0xbca46000},
+ {0xbca48000}, {0xbca4a000}, {0xbca4c000}, {0xbca4e000},
+ {0xbca50000}, {0xbca52000}, {0xbca54000}, {0xbca56000},
+ {0xbca58000}, {0xbca5a000}, {0xbca5c000}, {0xbca5e000},
+ {0xbca60000}, {0xbca62000}, {0xbca64000}, {0xbca66000},
+ {0xbca68000}, {0xbca6a000}, {0xbca6c000}, {0xbca6e000},
+ {0xbca70000}, {0xbca72000}, {0xbca74000}, {0xbca76000},
+ {0xbca78000}, {0xbca7a000}, {0xbca7c000}, {0xbca7e000},
+ {0xbca80000}, {0xbca82000}, {0xbca84000}, {0xbca86000},
+ {0xbca88000}, {0xbca8a000}, {0xbca8c000}, {0xbca8e000},
+ {0xbca90000}, {0xbca92000}, {0xbca94000}, {0xbca96000},
+ {0xbca98000}, {0xbca9a000}, {0xbca9c000}, {0xbca9e000},
+ {0xbcaa0000}, {0xbcaa2000}, {0xbcaa4000}, {0xbcaa6000},
+ {0xbcaa8000}, {0xbcaaa000}, {0xbcaac000}, {0xbcaae000},
+ {0xbcab0000}, {0xbcab2000}, {0xbcab4000}, {0xbcab6000},
+ {0xbcab8000}, {0xbcaba000}, {0xbcabc000}, {0xbcabe000},
+ {0xbcac0000}, {0xbcac2000}, {0xbcac4000}, {0xbcac6000},
+ {0xbcac8000}, {0xbcaca000}, {0xbcacc000}, {0xbcace000},
+ {0xbcad0000}, {0xbcad2000}, {0xbcad4000}, {0xbcad6000},
+ {0xbcad8000}, {0xbcada000}, {0xbcadc000}, {0xbcade000},
+ {0xbcae0000}, {0xbcae2000}, {0xbcae4000}, {0xbcae6000},
+ {0xbcae8000}, {0xbcaea000}, {0xbcaec000}, {0xbcaee000},
+ {0xbcaf0000}, {0xbcaf2000}, {0xbcaf4000}, {0xbcaf6000},
+ {0xbcaf8000}, {0xbcafa000}, {0xbcafc000}, {0xbcafe000},
+ {0xbcb00000}, {0xbcb02000}, {0xbcb04000}, {0xbcb06000},
+ {0xbcb08000}, {0xbcb0a000}, {0xbcb0c000}, {0xbcb0e000},
+ {0xbcb10000}, {0xbcb12000}, {0xbcb14000}, {0xbcb16000},
+ {0xbcb18000}, {0xbcb1a000}, {0xbcb1c000}, {0xbcb1e000},
+ {0xbcb20000}, {0xbcb22000}, {0xbcb24000}, {0xbcb26000},
+ {0xbcb28000}, {0xbcb2a000}, {0xbcb2c000}, {0xbcb2e000},
+ {0xbcb30000}, {0xbcb32000}, {0xbcb34000}, {0xbcb36000},
+ {0xbcb38000}, {0xbcb3a000}, {0xbcb3c000}, {0xbcb3e000},
+ {0xbcb40000}, {0xbcb42000}, {0xbcb44000}, {0xbcb46000},
+ {0xbcb48000}, {0xbcb4a000}, {0xbcb4c000}, {0xbcb4e000},
+ {0xbcb50000}, {0xbcb52000}, {0xbcb54000}, {0xbcb56000},
+ {0xbcb58000}, {0xbcb5a000}, {0xbcb5c000}, {0xbcb5e000},
+ {0xbcb60000}, {0xbcb62000}, {0xbcb64000}, {0xbcb66000},
+ {0xbcb68000}, {0xbcb6a000}, {0xbcb6c000}, {0xbcb6e000},
+ {0xbcb70000}, {0xbcb72000}, {0xbcb74000}, {0xbcb76000},
+ {0xbcb78000}, {0xbcb7a000}, {0xbcb7c000}, {0xbcb7e000},
+ {0xbcb80000}, {0xbcb82000}, {0xbcb84000}, {0xbcb86000},
+ {0xbcb88000}, {0xbcb8a000}, {0xbcb8c000}, {0xbcb8e000},
+ {0xbcb90000}, {0xbcb92000}, {0xbcb94000}, {0xbcb96000},
+ {0xbcb98000}, {0xbcb9a000}, {0xbcb9c000}, {0xbcb9e000},
+ {0xbcba0000}, {0xbcba2000}, {0xbcba4000}, {0xbcba6000},
+ {0xbcba8000}, {0xbcbaa000}, {0xbcbac000}, {0xbcbae000},
+ {0xbcbb0000}, {0xbcbb2000}, {0xbcbb4000}, {0xbcbb6000},
+ {0xbcbb8000}, {0xbcbba000}, {0xbcbbc000}, {0xbcbbe000},
+ {0xbcbc0000}, {0xbcbc2000}, {0xbcbc4000}, {0xbcbc6000},
+ {0xbcbc8000}, {0xbcbca000}, {0xbcbcc000}, {0xbcbce000},
+ {0xbcbd0000}, {0xbcbd2000}, {0xbcbd4000}, {0xbcbd6000},
+ {0xbcbd8000}, {0xbcbda000}, {0xbcbdc000}, {0xbcbde000},
+ {0xbcbe0000}, {0xbcbe2000}, {0xbcbe4000}, {0xbcbe6000},
+ {0xbcbe8000}, {0xbcbea000}, {0xbcbec000}, {0xbcbee000},
+ {0xbcbf0000}, {0xbcbf2000}, {0xbcbf4000}, {0xbcbf6000},
+ {0xbcbf8000}, {0xbcbfa000}, {0xbcbfc000}, {0xbcbfe000},
+ {0xbcc00000}, {0xbcc02000}, {0xbcc04000}, {0xbcc06000},
+ {0xbcc08000}, {0xbcc0a000}, {0xbcc0c000}, {0xbcc0e000},
+ {0xbcc10000}, {0xbcc12000}, {0xbcc14000}, {0xbcc16000},
+ {0xbcc18000}, {0xbcc1a000}, {0xbcc1c000}, {0xbcc1e000},
+ {0xbcc20000}, {0xbcc22000}, {0xbcc24000}, {0xbcc26000},
+ {0xbcc28000}, {0xbcc2a000}, {0xbcc2c000}, {0xbcc2e000},
+ {0xbcc30000}, {0xbcc32000}, {0xbcc34000}, {0xbcc36000},
+ {0xbcc38000}, {0xbcc3a000}, {0xbcc3c000}, {0xbcc3e000},
+ {0xbcc40000}, {0xbcc42000}, {0xbcc44000}, {0xbcc46000},
+ {0xbcc48000}, {0xbcc4a000}, {0xbcc4c000}, {0xbcc4e000},
+ {0xbcc50000}, {0xbcc52000}, {0xbcc54000}, {0xbcc56000},
+ {0xbcc58000}, {0xbcc5a000}, {0xbcc5c000}, {0xbcc5e000},
+ {0xbcc60000}, {0xbcc62000}, {0xbcc64000}, {0xbcc66000},
+ {0xbcc68000}, {0xbcc6a000}, {0xbcc6c000}, {0xbcc6e000},
+ {0xbcc70000}, {0xbcc72000}, {0xbcc74000}, {0xbcc76000},
+ {0xbcc78000}, {0xbcc7a000}, {0xbcc7c000}, {0xbcc7e000},
+ {0xbcc80000}, {0xbcc82000}, {0xbcc84000}, {0xbcc86000},
+ {0xbcc88000}, {0xbcc8a000}, {0xbcc8c000}, {0xbcc8e000},
+ {0xbcc90000}, {0xbcc92000}, {0xbcc94000}, {0xbcc96000},
+ {0xbcc98000}, {0xbcc9a000}, {0xbcc9c000}, {0xbcc9e000},
+ {0xbcca0000}, {0xbcca2000}, {0xbcca4000}, {0xbcca6000},
+ {0xbcca8000}, {0xbccaa000}, {0xbccac000}, {0xbccae000},
+ {0xbccb0000}, {0xbccb2000}, {0xbccb4000}, {0xbccb6000},
+ {0xbccb8000}, {0xbccba000}, {0xbccbc000}, {0xbccbe000},
+ {0xbccc0000}, {0xbccc2000}, {0xbccc4000}, {0xbccc6000},
+ {0xbccc8000}, {0xbccca000}, {0xbcccc000}, {0xbccce000},
+ {0xbccd0000}, {0xbccd2000}, {0xbccd4000}, {0xbccd6000},
+ {0xbccd8000}, {0xbccda000}, {0xbccdc000}, {0xbccde000},
+ {0xbcce0000}, {0xbcce2000}, {0xbcce4000}, {0xbcce6000},
+ {0xbcce8000}, {0xbccea000}, {0xbccec000}, {0xbccee000},
+ {0xbccf0000}, {0xbccf2000}, {0xbccf4000}, {0xbccf6000},
+ {0xbccf8000}, {0xbccfa000}, {0xbccfc000}, {0xbccfe000},
+ {0xbcd00000}, {0xbcd02000}, {0xbcd04000}, {0xbcd06000},
+ {0xbcd08000}, {0xbcd0a000}, {0xbcd0c000}, {0xbcd0e000},
+ {0xbcd10000}, {0xbcd12000}, {0xbcd14000}, {0xbcd16000},
+ {0xbcd18000}, {0xbcd1a000}, {0xbcd1c000}, {0xbcd1e000},
+ {0xbcd20000}, {0xbcd22000}, {0xbcd24000}, {0xbcd26000},
+ {0xbcd28000}, {0xbcd2a000}, {0xbcd2c000}, {0xbcd2e000},
+ {0xbcd30000}, {0xbcd32000}, {0xbcd34000}, {0xbcd36000},
+ {0xbcd38000}, {0xbcd3a000}, {0xbcd3c000}, {0xbcd3e000},
+ {0xbcd40000}, {0xbcd42000}, {0xbcd44000}, {0xbcd46000},
+ {0xbcd48000}, {0xbcd4a000}, {0xbcd4c000}, {0xbcd4e000},
+ {0xbcd50000}, {0xbcd52000}, {0xbcd54000}, {0xbcd56000},
+ {0xbcd58000}, {0xbcd5a000}, {0xbcd5c000}, {0xbcd5e000},
+ {0xbcd60000}, {0xbcd62000}, {0xbcd64000}, {0xbcd66000},
+ {0xbcd68000}, {0xbcd6a000}, {0xbcd6c000}, {0xbcd6e000},
+ {0xbcd70000}, {0xbcd72000}, {0xbcd74000}, {0xbcd76000},
+ {0xbcd78000}, {0xbcd7a000}, {0xbcd7c000}, {0xbcd7e000},
+ {0xbcd80000}, {0xbcd82000}, {0xbcd84000}, {0xbcd86000},
+ {0xbcd88000}, {0xbcd8a000}, {0xbcd8c000}, {0xbcd8e000},
+ {0xbcd90000}, {0xbcd92000}, {0xbcd94000}, {0xbcd96000},
+ {0xbcd98000}, {0xbcd9a000}, {0xbcd9c000}, {0xbcd9e000},
+ {0xbcda0000}, {0xbcda2000}, {0xbcda4000}, {0xbcda6000},
+ {0xbcda8000}, {0xbcdaa000}, {0xbcdac000}, {0xbcdae000},
+ {0xbcdb0000}, {0xbcdb2000}, {0xbcdb4000}, {0xbcdb6000},
+ {0xbcdb8000}, {0xbcdba000}, {0xbcdbc000}, {0xbcdbe000},
+ {0xbcdc0000}, {0xbcdc2000}, {0xbcdc4000}, {0xbcdc6000},
+ {0xbcdc8000}, {0xbcdca000}, {0xbcdcc000}, {0xbcdce000},
+ {0xbcdd0000}, {0xbcdd2000}, {0xbcdd4000}, {0xbcdd6000},
+ {0xbcdd8000}, {0xbcdda000}, {0xbcddc000}, {0xbcdde000},
+ {0xbcde0000}, {0xbcde2000}, {0xbcde4000}, {0xbcde6000},
+ {0xbcde8000}, {0xbcdea000}, {0xbcdec000}, {0xbcdee000},
+ {0xbcdf0000}, {0xbcdf2000}, {0xbcdf4000}, {0xbcdf6000},
+ {0xbcdf8000}, {0xbcdfa000}, {0xbcdfc000}, {0xbcdfe000},
+ {0xbce00000}, {0xbce02000}, {0xbce04000}, {0xbce06000},
+ {0xbce08000}, {0xbce0a000}, {0xbce0c000}, {0xbce0e000},
+ {0xbce10000}, {0xbce12000}, {0xbce14000}, {0xbce16000},
+ {0xbce18000}, {0xbce1a000}, {0xbce1c000}, {0xbce1e000},
+ {0xbce20000}, {0xbce22000}, {0xbce24000}, {0xbce26000},
+ {0xbce28000}, {0xbce2a000}, {0xbce2c000}, {0xbce2e000},
+ {0xbce30000}, {0xbce32000}, {0xbce34000}, {0xbce36000},
+ {0xbce38000}, {0xbce3a000}, {0xbce3c000}, {0xbce3e000},
+ {0xbce40000}, {0xbce42000}, {0xbce44000}, {0xbce46000},
+ {0xbce48000}, {0xbce4a000}, {0xbce4c000}, {0xbce4e000},
+ {0xbce50000}, {0xbce52000}, {0xbce54000}, {0xbce56000},
+ {0xbce58000}, {0xbce5a000}, {0xbce5c000}, {0xbce5e000},
+ {0xbce60000}, {0xbce62000}, {0xbce64000}, {0xbce66000},
+ {0xbce68000}, {0xbce6a000}, {0xbce6c000}, {0xbce6e000},
+ {0xbce70000}, {0xbce72000}, {0xbce74000}, {0xbce76000},
+ {0xbce78000}, {0xbce7a000}, {0xbce7c000}, {0xbce7e000},
+ {0xbce80000}, {0xbce82000}, {0xbce84000}, {0xbce86000},
+ {0xbce88000}, {0xbce8a000}, {0xbce8c000}, {0xbce8e000},
+ {0xbce90000}, {0xbce92000}, {0xbce94000}, {0xbce96000},
+ {0xbce98000}, {0xbce9a000}, {0xbce9c000}, {0xbce9e000},
+ {0xbcea0000}, {0xbcea2000}, {0xbcea4000}, {0xbcea6000},
+ {0xbcea8000}, {0xbceaa000}, {0xbceac000}, {0xbceae000},
+ {0xbceb0000}, {0xbceb2000}, {0xbceb4000}, {0xbceb6000},
+ {0xbceb8000}, {0xbceba000}, {0xbcebc000}, {0xbcebe000},
+ {0xbcec0000}, {0xbcec2000}, {0xbcec4000}, {0xbcec6000},
+ {0xbcec8000}, {0xbceca000}, {0xbcecc000}, {0xbcece000},
+ {0xbced0000}, {0xbced2000}, {0xbced4000}, {0xbced6000},
+ {0xbced8000}, {0xbceda000}, {0xbcedc000}, {0xbcede000},
+ {0xbcee0000}, {0xbcee2000}, {0xbcee4000}, {0xbcee6000},
+ {0xbcee8000}, {0xbceea000}, {0xbceec000}, {0xbceee000},
+ {0xbcef0000}, {0xbcef2000}, {0xbcef4000}, {0xbcef6000},
+ {0xbcef8000}, {0xbcefa000}, {0xbcefc000}, {0xbcefe000},
+ {0xbcf00000}, {0xbcf02000}, {0xbcf04000}, {0xbcf06000},
+ {0xbcf08000}, {0xbcf0a000}, {0xbcf0c000}, {0xbcf0e000},
+ {0xbcf10000}, {0xbcf12000}, {0xbcf14000}, {0xbcf16000},
+ {0xbcf18000}, {0xbcf1a000}, {0xbcf1c000}, {0xbcf1e000},
+ {0xbcf20000}, {0xbcf22000}, {0xbcf24000}, {0xbcf26000},
+ {0xbcf28000}, {0xbcf2a000}, {0xbcf2c000}, {0xbcf2e000},
+ {0xbcf30000}, {0xbcf32000}, {0xbcf34000}, {0xbcf36000},
+ {0xbcf38000}, {0xbcf3a000}, {0xbcf3c000}, {0xbcf3e000},
+ {0xbcf40000}, {0xbcf42000}, {0xbcf44000}, {0xbcf46000},
+ {0xbcf48000}, {0xbcf4a000}, {0xbcf4c000}, {0xbcf4e000},
+ {0xbcf50000}, {0xbcf52000}, {0xbcf54000}, {0xbcf56000},
+ {0xbcf58000}, {0xbcf5a000}, {0xbcf5c000}, {0xbcf5e000},
+ {0xbcf60000}, {0xbcf62000}, {0xbcf64000}, {0xbcf66000},
+ {0xbcf68000}, {0xbcf6a000}, {0xbcf6c000}, {0xbcf6e000},
+ {0xbcf70000}, {0xbcf72000}, {0xbcf74000}, {0xbcf76000},
+ {0xbcf78000}, {0xbcf7a000}, {0xbcf7c000}, {0xbcf7e000},
+ {0xbcf80000}, {0xbcf82000}, {0xbcf84000}, {0xbcf86000},
+ {0xbcf88000}, {0xbcf8a000}, {0xbcf8c000}, {0xbcf8e000},
+ {0xbcf90000}, {0xbcf92000}, {0xbcf94000}, {0xbcf96000},
+ {0xbcf98000}, {0xbcf9a000}, {0xbcf9c000}, {0xbcf9e000},
+ {0xbcfa0000}, {0xbcfa2000}, {0xbcfa4000}, {0xbcfa6000},
+ {0xbcfa8000}, {0xbcfaa000}, {0xbcfac000}, {0xbcfae000},
+ {0xbcfb0000}, {0xbcfb2000}, {0xbcfb4000}, {0xbcfb6000},
+ {0xbcfb8000}, {0xbcfba000}, {0xbcfbc000}, {0xbcfbe000},
+ {0xbcfc0000}, {0xbcfc2000}, {0xbcfc4000}, {0xbcfc6000},
+ {0xbcfc8000}, {0xbcfca000}, {0xbcfcc000}, {0xbcfce000},
+ {0xbcfd0000}, {0xbcfd2000}, {0xbcfd4000}, {0xbcfd6000},
+ {0xbcfd8000}, {0xbcfda000}, {0xbcfdc000}, {0xbcfde000},
+ {0xbcfe0000}, {0xbcfe2000}, {0xbcfe4000}, {0xbcfe6000},
+ {0xbcfe8000}, {0xbcfea000}, {0xbcfec000}, {0xbcfee000},
+ {0xbcff0000}, {0xbcff2000}, {0xbcff4000}, {0xbcff6000},
+ {0xbcff8000}, {0xbcffa000}, {0xbcffc000}, {0xbcffe000},
+ {0xbd000000}, {0xbd002000}, {0xbd004000}, {0xbd006000},
+ {0xbd008000}, {0xbd00a000}, {0xbd00c000}, {0xbd00e000},
+ {0xbd010000}, {0xbd012000}, {0xbd014000}, {0xbd016000},
+ {0xbd018000}, {0xbd01a000}, {0xbd01c000}, {0xbd01e000},
+ {0xbd020000}, {0xbd022000}, {0xbd024000}, {0xbd026000},
+ {0xbd028000}, {0xbd02a000}, {0xbd02c000}, {0xbd02e000},
+ {0xbd030000}, {0xbd032000}, {0xbd034000}, {0xbd036000},
+ {0xbd038000}, {0xbd03a000}, {0xbd03c000}, {0xbd03e000},
+ {0xbd040000}, {0xbd042000}, {0xbd044000}, {0xbd046000},
+ {0xbd048000}, {0xbd04a000}, {0xbd04c000}, {0xbd04e000},
+ {0xbd050000}, {0xbd052000}, {0xbd054000}, {0xbd056000},
+ {0xbd058000}, {0xbd05a000}, {0xbd05c000}, {0xbd05e000},
+ {0xbd060000}, {0xbd062000}, {0xbd064000}, {0xbd066000},
+ {0xbd068000}, {0xbd06a000}, {0xbd06c000}, {0xbd06e000},
+ {0xbd070000}, {0xbd072000}, {0xbd074000}, {0xbd076000},
+ {0xbd078000}, {0xbd07a000}, {0xbd07c000}, {0xbd07e000},
+ {0xbd080000}, {0xbd082000}, {0xbd084000}, {0xbd086000},
+ {0xbd088000}, {0xbd08a000}, {0xbd08c000}, {0xbd08e000},
+ {0xbd090000}, {0xbd092000}, {0xbd094000}, {0xbd096000},
+ {0xbd098000}, {0xbd09a000}, {0xbd09c000}, {0xbd09e000},
+ {0xbd0a0000}, {0xbd0a2000}, {0xbd0a4000}, {0xbd0a6000},
+ {0xbd0a8000}, {0xbd0aa000}, {0xbd0ac000}, {0xbd0ae000},
+ {0xbd0b0000}, {0xbd0b2000}, {0xbd0b4000}, {0xbd0b6000},
+ {0xbd0b8000}, {0xbd0ba000}, {0xbd0bc000}, {0xbd0be000},
+ {0xbd0c0000}, {0xbd0c2000}, {0xbd0c4000}, {0xbd0c6000},
+ {0xbd0c8000}, {0xbd0ca000}, {0xbd0cc000}, {0xbd0ce000},
+ {0xbd0d0000}, {0xbd0d2000}, {0xbd0d4000}, {0xbd0d6000},
+ {0xbd0d8000}, {0xbd0da000}, {0xbd0dc000}, {0xbd0de000},
+ {0xbd0e0000}, {0xbd0e2000}, {0xbd0e4000}, {0xbd0e6000},
+ {0xbd0e8000}, {0xbd0ea000}, {0xbd0ec000}, {0xbd0ee000},
+ {0xbd0f0000}, {0xbd0f2000}, {0xbd0f4000}, {0xbd0f6000},
+ {0xbd0f8000}, {0xbd0fa000}, {0xbd0fc000}, {0xbd0fe000},
+ {0xbd100000}, {0xbd102000}, {0xbd104000}, {0xbd106000},
+ {0xbd108000}, {0xbd10a000}, {0xbd10c000}, {0xbd10e000},
+ {0xbd110000}, {0xbd112000}, {0xbd114000}, {0xbd116000},
+ {0xbd118000}, {0xbd11a000}, {0xbd11c000}, {0xbd11e000},
+ {0xbd120000}, {0xbd122000}, {0xbd124000}, {0xbd126000},
+ {0xbd128000}, {0xbd12a000}, {0xbd12c000}, {0xbd12e000},
+ {0xbd130000}, {0xbd132000}, {0xbd134000}, {0xbd136000},
+ {0xbd138000}, {0xbd13a000}, {0xbd13c000}, {0xbd13e000},
+ {0xbd140000}, {0xbd142000}, {0xbd144000}, {0xbd146000},
+ {0xbd148000}, {0xbd14a000}, {0xbd14c000}, {0xbd14e000},
+ {0xbd150000}, {0xbd152000}, {0xbd154000}, {0xbd156000},
+ {0xbd158000}, {0xbd15a000}, {0xbd15c000}, {0xbd15e000},
+ {0xbd160000}, {0xbd162000}, {0xbd164000}, {0xbd166000},
+ {0xbd168000}, {0xbd16a000}, {0xbd16c000}, {0xbd16e000},
+ {0xbd170000}, {0xbd172000}, {0xbd174000}, {0xbd176000},
+ {0xbd178000}, {0xbd17a000}, {0xbd17c000}, {0xbd17e000},
+ {0xbd180000}, {0xbd182000}, {0xbd184000}, {0xbd186000},
+ {0xbd188000}, {0xbd18a000}, {0xbd18c000}, {0xbd18e000},
+ {0xbd190000}, {0xbd192000}, {0xbd194000}, {0xbd196000},
+ {0xbd198000}, {0xbd19a000}, {0xbd19c000}, {0xbd19e000},
+ {0xbd1a0000}, {0xbd1a2000}, {0xbd1a4000}, {0xbd1a6000},
+ {0xbd1a8000}, {0xbd1aa000}, {0xbd1ac000}, {0xbd1ae000},
+ {0xbd1b0000}, {0xbd1b2000}, {0xbd1b4000}, {0xbd1b6000},
+ {0xbd1b8000}, {0xbd1ba000}, {0xbd1bc000}, {0xbd1be000},
+ {0xbd1c0000}, {0xbd1c2000}, {0xbd1c4000}, {0xbd1c6000},
+ {0xbd1c8000}, {0xbd1ca000}, {0xbd1cc000}, {0xbd1ce000},
+ {0xbd1d0000}, {0xbd1d2000}, {0xbd1d4000}, {0xbd1d6000},
+ {0xbd1d8000}, {0xbd1da000}, {0xbd1dc000}, {0xbd1de000},
+ {0xbd1e0000}, {0xbd1e2000}, {0xbd1e4000}, {0xbd1e6000},
+ {0xbd1e8000}, {0xbd1ea000}, {0xbd1ec000}, {0xbd1ee000},
+ {0xbd1f0000}, {0xbd1f2000}, {0xbd1f4000}, {0xbd1f6000},
+ {0xbd1f8000}, {0xbd1fa000}, {0xbd1fc000}, {0xbd1fe000},
+ {0xbd200000}, {0xbd202000}, {0xbd204000}, {0xbd206000},
+ {0xbd208000}, {0xbd20a000}, {0xbd20c000}, {0xbd20e000},
+ {0xbd210000}, {0xbd212000}, {0xbd214000}, {0xbd216000},
+ {0xbd218000}, {0xbd21a000}, {0xbd21c000}, {0xbd21e000},
+ {0xbd220000}, {0xbd222000}, {0xbd224000}, {0xbd226000},
+ {0xbd228000}, {0xbd22a000}, {0xbd22c000}, {0xbd22e000},
+ {0xbd230000}, {0xbd232000}, {0xbd234000}, {0xbd236000},
+ {0xbd238000}, {0xbd23a000}, {0xbd23c000}, {0xbd23e000},
+ {0xbd240000}, {0xbd242000}, {0xbd244000}, {0xbd246000},
+ {0xbd248000}, {0xbd24a000}, {0xbd24c000}, {0xbd24e000},
+ {0xbd250000}, {0xbd252000}, {0xbd254000}, {0xbd256000},
+ {0xbd258000}, {0xbd25a000}, {0xbd25c000}, {0xbd25e000},
+ {0xbd260000}, {0xbd262000}, {0xbd264000}, {0xbd266000},
+ {0xbd268000}, {0xbd26a000}, {0xbd26c000}, {0xbd26e000},
+ {0xbd270000}, {0xbd272000}, {0xbd274000}, {0xbd276000},
+ {0xbd278000}, {0xbd27a000}, {0xbd27c000}, {0xbd27e000},
+ {0xbd280000}, {0xbd282000}, {0xbd284000}, {0xbd286000},
+ {0xbd288000}, {0xbd28a000}, {0xbd28c000}, {0xbd28e000},
+ {0xbd290000}, {0xbd292000}, {0xbd294000}, {0xbd296000},
+ {0xbd298000}, {0xbd29a000}, {0xbd29c000}, {0xbd29e000},
+ {0xbd2a0000}, {0xbd2a2000}, {0xbd2a4000}, {0xbd2a6000},
+ {0xbd2a8000}, {0xbd2aa000}, {0xbd2ac000}, {0xbd2ae000},
+ {0xbd2b0000}, {0xbd2b2000}, {0xbd2b4000}, {0xbd2b6000},
+ {0xbd2b8000}, {0xbd2ba000}, {0xbd2bc000}, {0xbd2be000},
+ {0xbd2c0000}, {0xbd2c2000}, {0xbd2c4000}, {0xbd2c6000},
+ {0xbd2c8000}, {0xbd2ca000}, {0xbd2cc000}, {0xbd2ce000},
+ {0xbd2d0000}, {0xbd2d2000}, {0xbd2d4000}, {0xbd2d6000},
+ {0xbd2d8000}, {0xbd2da000}, {0xbd2dc000}, {0xbd2de000},
+ {0xbd2e0000}, {0xbd2e2000}, {0xbd2e4000}, {0xbd2e6000},
+ {0xbd2e8000}, {0xbd2ea000}, {0xbd2ec000}, {0xbd2ee000},
+ {0xbd2f0000}, {0xbd2f2000}, {0xbd2f4000}, {0xbd2f6000},
+ {0xbd2f8000}, {0xbd2fa000}, {0xbd2fc000}, {0xbd2fe000},
+ {0xbd300000}, {0xbd302000}, {0xbd304000}, {0xbd306000},
+ {0xbd308000}, {0xbd30a000}, {0xbd30c000}, {0xbd30e000},
+ {0xbd310000}, {0xbd312000}, {0xbd314000}, {0xbd316000},
+ {0xbd318000}, {0xbd31a000}, {0xbd31c000}, {0xbd31e000},
+ {0xbd320000}, {0xbd322000}, {0xbd324000}, {0xbd326000},
+ {0xbd328000}, {0xbd32a000}, {0xbd32c000}, {0xbd32e000},
+ {0xbd330000}, {0xbd332000}, {0xbd334000}, {0xbd336000},
+ {0xbd338000}, {0xbd33a000}, {0xbd33c000}, {0xbd33e000},
+ {0xbd340000}, {0xbd342000}, {0xbd344000}, {0xbd346000},
+ {0xbd348000}, {0xbd34a000}, {0xbd34c000}, {0xbd34e000},
+ {0xbd350000}, {0xbd352000}, {0xbd354000}, {0xbd356000},
+ {0xbd358000}, {0xbd35a000}, {0xbd35c000}, {0xbd35e000},
+ {0xbd360000}, {0xbd362000}, {0xbd364000}, {0xbd366000},
+ {0xbd368000}, {0xbd36a000}, {0xbd36c000}, {0xbd36e000},
+ {0xbd370000}, {0xbd372000}, {0xbd374000}, {0xbd376000},
+ {0xbd378000}, {0xbd37a000}, {0xbd37c000}, {0xbd37e000},
+ {0xbd380000}, {0xbd382000}, {0xbd384000}, {0xbd386000},
+ {0xbd388000}, {0xbd38a000}, {0xbd38c000}, {0xbd38e000},
+ {0xbd390000}, {0xbd392000}, {0xbd394000}, {0xbd396000},
+ {0xbd398000}, {0xbd39a000}, {0xbd39c000}, {0xbd39e000},
+ {0xbd3a0000}, {0xbd3a2000}, {0xbd3a4000}, {0xbd3a6000},
+ {0xbd3a8000}, {0xbd3aa000}, {0xbd3ac000}, {0xbd3ae000},
+ {0xbd3b0000}, {0xbd3b2000}, {0xbd3b4000}, {0xbd3b6000},
+ {0xbd3b8000}, {0xbd3ba000}, {0xbd3bc000}, {0xbd3be000},
+ {0xbd3c0000}, {0xbd3c2000}, {0xbd3c4000}, {0xbd3c6000},
+ {0xbd3c8000}, {0xbd3ca000}, {0xbd3cc000}, {0xbd3ce000},
+ {0xbd3d0000}, {0xbd3d2000}, {0xbd3d4000}, {0xbd3d6000},
+ {0xbd3d8000}, {0xbd3da000}, {0xbd3dc000}, {0xbd3de000},
+ {0xbd3e0000}, {0xbd3e2000}, {0xbd3e4000}, {0xbd3e6000},
+ {0xbd3e8000}, {0xbd3ea000}, {0xbd3ec000}, {0xbd3ee000},
+ {0xbd3f0000}, {0xbd3f2000}, {0xbd3f4000}, {0xbd3f6000},
+ {0xbd3f8000}, {0xbd3fa000}, {0xbd3fc000}, {0xbd3fe000},
+ {0xbd400000}, {0xbd402000}, {0xbd404000}, {0xbd406000},
+ {0xbd408000}, {0xbd40a000}, {0xbd40c000}, {0xbd40e000},
+ {0xbd410000}, {0xbd412000}, {0xbd414000}, {0xbd416000},
+ {0xbd418000}, {0xbd41a000}, {0xbd41c000}, {0xbd41e000},
+ {0xbd420000}, {0xbd422000}, {0xbd424000}, {0xbd426000},
+ {0xbd428000}, {0xbd42a000}, {0xbd42c000}, {0xbd42e000},
+ {0xbd430000}, {0xbd432000}, {0xbd434000}, {0xbd436000},
+ {0xbd438000}, {0xbd43a000}, {0xbd43c000}, {0xbd43e000},
+ {0xbd440000}, {0xbd442000}, {0xbd444000}, {0xbd446000},
+ {0xbd448000}, {0xbd44a000}, {0xbd44c000}, {0xbd44e000},
+ {0xbd450000}, {0xbd452000}, {0xbd454000}, {0xbd456000},
+ {0xbd458000}, {0xbd45a000}, {0xbd45c000}, {0xbd45e000},
+ {0xbd460000}, {0xbd462000}, {0xbd464000}, {0xbd466000},
+ {0xbd468000}, {0xbd46a000}, {0xbd46c000}, {0xbd46e000},
+ {0xbd470000}, {0xbd472000}, {0xbd474000}, {0xbd476000},
+ {0xbd478000}, {0xbd47a000}, {0xbd47c000}, {0xbd47e000},
+ {0xbd480000}, {0xbd482000}, {0xbd484000}, {0xbd486000},
+ {0xbd488000}, {0xbd48a000}, {0xbd48c000}, {0xbd48e000},
+ {0xbd490000}, {0xbd492000}, {0xbd494000}, {0xbd496000},
+ {0xbd498000}, {0xbd49a000}, {0xbd49c000}, {0xbd49e000},
+ {0xbd4a0000}, {0xbd4a2000}, {0xbd4a4000}, {0xbd4a6000},
+ {0xbd4a8000}, {0xbd4aa000}, {0xbd4ac000}, {0xbd4ae000},
+ {0xbd4b0000}, {0xbd4b2000}, {0xbd4b4000}, {0xbd4b6000},
+ {0xbd4b8000}, {0xbd4ba000}, {0xbd4bc000}, {0xbd4be000},
+ {0xbd4c0000}, {0xbd4c2000}, {0xbd4c4000}, {0xbd4c6000},
+ {0xbd4c8000}, {0xbd4ca000}, {0xbd4cc000}, {0xbd4ce000},
+ {0xbd4d0000}, {0xbd4d2000}, {0xbd4d4000}, {0xbd4d6000},
+ {0xbd4d8000}, {0xbd4da000}, {0xbd4dc000}, {0xbd4de000},
+ {0xbd4e0000}, {0xbd4e2000}, {0xbd4e4000}, {0xbd4e6000},
+ {0xbd4e8000}, {0xbd4ea000}, {0xbd4ec000}, {0xbd4ee000},
+ {0xbd4f0000}, {0xbd4f2000}, {0xbd4f4000}, {0xbd4f6000},
+ {0xbd4f8000}, {0xbd4fa000}, {0xbd4fc000}, {0xbd4fe000},
+ {0xbd500000}, {0xbd502000}, {0xbd504000}, {0xbd506000},
+ {0xbd508000}, {0xbd50a000}, {0xbd50c000}, {0xbd50e000},
+ {0xbd510000}, {0xbd512000}, {0xbd514000}, {0xbd516000},
+ {0xbd518000}, {0xbd51a000}, {0xbd51c000}, {0xbd51e000},
+ {0xbd520000}, {0xbd522000}, {0xbd524000}, {0xbd526000},
+ {0xbd528000}, {0xbd52a000}, {0xbd52c000}, {0xbd52e000},
+ {0xbd530000}, {0xbd532000}, {0xbd534000}, {0xbd536000},
+ {0xbd538000}, {0xbd53a000}, {0xbd53c000}, {0xbd53e000},
+ {0xbd540000}, {0xbd542000}, {0xbd544000}, {0xbd546000},
+ {0xbd548000}, {0xbd54a000}, {0xbd54c000}, {0xbd54e000},
+ {0xbd550000}, {0xbd552000}, {0xbd554000}, {0xbd556000},
+ {0xbd558000}, {0xbd55a000}, {0xbd55c000}, {0xbd55e000},
+ {0xbd560000}, {0xbd562000}, {0xbd564000}, {0xbd566000},
+ {0xbd568000}, {0xbd56a000}, {0xbd56c000}, {0xbd56e000},
+ {0xbd570000}, {0xbd572000}, {0xbd574000}, {0xbd576000},
+ {0xbd578000}, {0xbd57a000}, {0xbd57c000}, {0xbd57e000},
+ {0xbd580000}, {0xbd582000}, {0xbd584000}, {0xbd586000},
+ {0xbd588000}, {0xbd58a000}, {0xbd58c000}, {0xbd58e000},
+ {0xbd590000}, {0xbd592000}, {0xbd594000}, {0xbd596000},
+ {0xbd598000}, {0xbd59a000}, {0xbd59c000}, {0xbd59e000},
+ {0xbd5a0000}, {0xbd5a2000}, {0xbd5a4000}, {0xbd5a6000},
+ {0xbd5a8000}, {0xbd5aa000}, {0xbd5ac000}, {0xbd5ae000},
+ {0xbd5b0000}, {0xbd5b2000}, {0xbd5b4000}, {0xbd5b6000},
+ {0xbd5b8000}, {0xbd5ba000}, {0xbd5bc000}, {0xbd5be000},
+ {0xbd5c0000}, {0xbd5c2000}, {0xbd5c4000}, {0xbd5c6000},
+ {0xbd5c8000}, {0xbd5ca000}, {0xbd5cc000}, {0xbd5ce000},
+ {0xbd5d0000}, {0xbd5d2000}, {0xbd5d4000}, {0xbd5d6000},
+ {0xbd5d8000}, {0xbd5da000}, {0xbd5dc000}, {0xbd5de000},
+ {0xbd5e0000}, {0xbd5e2000}, {0xbd5e4000}, {0xbd5e6000},
+ {0xbd5e8000}, {0xbd5ea000}, {0xbd5ec000}, {0xbd5ee000},
+ {0xbd5f0000}, {0xbd5f2000}, {0xbd5f4000}, {0xbd5f6000},
+ {0xbd5f8000}, {0xbd5fa000}, {0xbd5fc000}, {0xbd5fe000},
+ {0xbd600000}, {0xbd602000}, {0xbd604000}, {0xbd606000},
+ {0xbd608000}, {0xbd60a000}, {0xbd60c000}, {0xbd60e000},
+ {0xbd610000}, {0xbd612000}, {0xbd614000}, {0xbd616000},
+ {0xbd618000}, {0xbd61a000}, {0xbd61c000}, {0xbd61e000},
+ {0xbd620000}, {0xbd622000}, {0xbd624000}, {0xbd626000},
+ {0xbd628000}, {0xbd62a000}, {0xbd62c000}, {0xbd62e000},
+ {0xbd630000}, {0xbd632000}, {0xbd634000}, {0xbd636000},
+ {0xbd638000}, {0xbd63a000}, {0xbd63c000}, {0xbd63e000},
+ {0xbd640000}, {0xbd642000}, {0xbd644000}, {0xbd646000},
+ {0xbd648000}, {0xbd64a000}, {0xbd64c000}, {0xbd64e000},
+ {0xbd650000}, {0xbd652000}, {0xbd654000}, {0xbd656000},
+ {0xbd658000}, {0xbd65a000}, {0xbd65c000}, {0xbd65e000},
+ {0xbd660000}, {0xbd662000}, {0xbd664000}, {0xbd666000},
+ {0xbd668000}, {0xbd66a000}, {0xbd66c000}, {0xbd66e000},
+ {0xbd670000}, {0xbd672000}, {0xbd674000}, {0xbd676000},
+ {0xbd678000}, {0xbd67a000}, {0xbd67c000}, {0xbd67e000},
+ {0xbd680000}, {0xbd682000}, {0xbd684000}, {0xbd686000},
+ {0xbd688000}, {0xbd68a000}, {0xbd68c000}, {0xbd68e000},
+ {0xbd690000}, {0xbd692000}, {0xbd694000}, {0xbd696000},
+ {0xbd698000}, {0xbd69a000}, {0xbd69c000}, {0xbd69e000},
+ {0xbd6a0000}, {0xbd6a2000}, {0xbd6a4000}, {0xbd6a6000},
+ {0xbd6a8000}, {0xbd6aa000}, {0xbd6ac000}, {0xbd6ae000},
+ {0xbd6b0000}, {0xbd6b2000}, {0xbd6b4000}, {0xbd6b6000},
+ {0xbd6b8000}, {0xbd6ba000}, {0xbd6bc000}, {0xbd6be000},
+ {0xbd6c0000}, {0xbd6c2000}, {0xbd6c4000}, {0xbd6c6000},
+ {0xbd6c8000}, {0xbd6ca000}, {0xbd6cc000}, {0xbd6ce000},
+ {0xbd6d0000}, {0xbd6d2000}, {0xbd6d4000}, {0xbd6d6000},
+ {0xbd6d8000}, {0xbd6da000}, {0xbd6dc000}, {0xbd6de000},
+ {0xbd6e0000}, {0xbd6e2000}, {0xbd6e4000}, {0xbd6e6000},
+ {0xbd6e8000}, {0xbd6ea000}, {0xbd6ec000}, {0xbd6ee000},
+ {0xbd6f0000}, {0xbd6f2000}, {0xbd6f4000}, {0xbd6f6000},
+ {0xbd6f8000}, {0xbd6fa000}, {0xbd6fc000}, {0xbd6fe000},
+ {0xbd700000}, {0xbd702000}, {0xbd704000}, {0xbd706000},
+ {0xbd708000}, {0xbd70a000}, {0xbd70c000}, {0xbd70e000},
+ {0xbd710000}, {0xbd712000}, {0xbd714000}, {0xbd716000},
+ {0xbd718000}, {0xbd71a000}, {0xbd71c000}, {0xbd71e000},
+ {0xbd720000}, {0xbd722000}, {0xbd724000}, {0xbd726000},
+ {0xbd728000}, {0xbd72a000}, {0xbd72c000}, {0xbd72e000},
+ {0xbd730000}, {0xbd732000}, {0xbd734000}, {0xbd736000},
+ {0xbd738000}, {0xbd73a000}, {0xbd73c000}, {0xbd73e000},
+ {0xbd740000}, {0xbd742000}, {0xbd744000}, {0xbd746000},
+ {0xbd748000}, {0xbd74a000}, {0xbd74c000}, {0xbd74e000},
+ {0xbd750000}, {0xbd752000}, {0xbd754000}, {0xbd756000},
+ {0xbd758000}, {0xbd75a000}, {0xbd75c000}, {0xbd75e000},
+ {0xbd760000}, {0xbd762000}, {0xbd764000}, {0xbd766000},
+ {0xbd768000}, {0xbd76a000}, {0xbd76c000}, {0xbd76e000},
+ {0xbd770000}, {0xbd772000}, {0xbd774000}, {0xbd776000},
+ {0xbd778000}, {0xbd77a000}, {0xbd77c000}, {0xbd77e000},
+ {0xbd780000}, {0xbd782000}, {0xbd784000}, {0xbd786000},
+ {0xbd788000}, {0xbd78a000}, {0xbd78c000}, {0xbd78e000},
+ {0xbd790000}, {0xbd792000}, {0xbd794000}, {0xbd796000},
+ {0xbd798000}, {0xbd79a000}, {0xbd79c000}, {0xbd79e000},
+ {0xbd7a0000}, {0xbd7a2000}, {0xbd7a4000}, {0xbd7a6000},
+ {0xbd7a8000}, {0xbd7aa000}, {0xbd7ac000}, {0xbd7ae000},
+ {0xbd7b0000}, {0xbd7b2000}, {0xbd7b4000}, {0xbd7b6000},
+ {0xbd7b8000}, {0xbd7ba000}, {0xbd7bc000}, {0xbd7be000},
+ {0xbd7c0000}, {0xbd7c2000}, {0xbd7c4000}, {0xbd7c6000},
+ {0xbd7c8000}, {0xbd7ca000}, {0xbd7cc000}, {0xbd7ce000},
+ {0xbd7d0000}, {0xbd7d2000}, {0xbd7d4000}, {0xbd7d6000},
+ {0xbd7d8000}, {0xbd7da000}, {0xbd7dc000}, {0xbd7de000},
+ {0xbd7e0000}, {0xbd7e2000}, {0xbd7e4000}, {0xbd7e6000},
+ {0xbd7e8000}, {0xbd7ea000}, {0xbd7ec000}, {0xbd7ee000},
+ {0xbd7f0000}, {0xbd7f2000}, {0xbd7f4000}, {0xbd7f6000},
+ {0xbd7f8000}, {0xbd7fa000}, {0xbd7fc000}, {0xbd7fe000},
+ {0xbd800000}, {0xbd802000}, {0xbd804000}, {0xbd806000},
+ {0xbd808000}, {0xbd80a000}, {0xbd80c000}, {0xbd80e000},
+ {0xbd810000}, {0xbd812000}, {0xbd814000}, {0xbd816000},
+ {0xbd818000}, {0xbd81a000}, {0xbd81c000}, {0xbd81e000},
+ {0xbd820000}, {0xbd822000}, {0xbd824000}, {0xbd826000},
+ {0xbd828000}, {0xbd82a000}, {0xbd82c000}, {0xbd82e000},
+ {0xbd830000}, {0xbd832000}, {0xbd834000}, {0xbd836000},
+ {0xbd838000}, {0xbd83a000}, {0xbd83c000}, {0xbd83e000},
+ {0xbd840000}, {0xbd842000}, {0xbd844000}, {0xbd846000},
+ {0xbd848000}, {0xbd84a000}, {0xbd84c000}, {0xbd84e000},
+ {0xbd850000}, {0xbd852000}, {0xbd854000}, {0xbd856000},
+ {0xbd858000}, {0xbd85a000}, {0xbd85c000}, {0xbd85e000},
+ {0xbd860000}, {0xbd862000}, {0xbd864000}, {0xbd866000},
+ {0xbd868000}, {0xbd86a000}, {0xbd86c000}, {0xbd86e000},
+ {0xbd870000}, {0xbd872000}, {0xbd874000}, {0xbd876000},
+ {0xbd878000}, {0xbd87a000}, {0xbd87c000}, {0xbd87e000},
+ {0xbd880000}, {0xbd882000}, {0xbd884000}, {0xbd886000},
+ {0xbd888000}, {0xbd88a000}, {0xbd88c000}, {0xbd88e000},
+ {0xbd890000}, {0xbd892000}, {0xbd894000}, {0xbd896000},
+ {0xbd898000}, {0xbd89a000}, {0xbd89c000}, {0xbd89e000},
+ {0xbd8a0000}, {0xbd8a2000}, {0xbd8a4000}, {0xbd8a6000},
+ {0xbd8a8000}, {0xbd8aa000}, {0xbd8ac000}, {0xbd8ae000},
+ {0xbd8b0000}, {0xbd8b2000}, {0xbd8b4000}, {0xbd8b6000},
+ {0xbd8b8000}, {0xbd8ba000}, {0xbd8bc000}, {0xbd8be000},
+ {0xbd8c0000}, {0xbd8c2000}, {0xbd8c4000}, {0xbd8c6000},
+ {0xbd8c8000}, {0xbd8ca000}, {0xbd8cc000}, {0xbd8ce000},
+ {0xbd8d0000}, {0xbd8d2000}, {0xbd8d4000}, {0xbd8d6000},
+ {0xbd8d8000}, {0xbd8da000}, {0xbd8dc000}, {0xbd8de000},
+ {0xbd8e0000}, {0xbd8e2000}, {0xbd8e4000}, {0xbd8e6000},
+ {0xbd8e8000}, {0xbd8ea000}, {0xbd8ec000}, {0xbd8ee000},
+ {0xbd8f0000}, {0xbd8f2000}, {0xbd8f4000}, {0xbd8f6000},
+ {0xbd8f8000}, {0xbd8fa000}, {0xbd8fc000}, {0xbd8fe000},
+ {0xbd900000}, {0xbd902000}, {0xbd904000}, {0xbd906000},
+ {0xbd908000}, {0xbd90a000}, {0xbd90c000}, {0xbd90e000},
+ {0xbd910000}, {0xbd912000}, {0xbd914000}, {0xbd916000},
+ {0xbd918000}, {0xbd91a000}, {0xbd91c000}, {0xbd91e000},
+ {0xbd920000}, {0xbd922000}, {0xbd924000}, {0xbd926000},
+ {0xbd928000}, {0xbd92a000}, {0xbd92c000}, {0xbd92e000},
+ {0xbd930000}, {0xbd932000}, {0xbd934000}, {0xbd936000},
+ {0xbd938000}, {0xbd93a000}, {0xbd93c000}, {0xbd93e000},
+ {0xbd940000}, {0xbd942000}, {0xbd944000}, {0xbd946000},
+ {0xbd948000}, {0xbd94a000}, {0xbd94c000}, {0xbd94e000},
+ {0xbd950000}, {0xbd952000}, {0xbd954000}, {0xbd956000},
+ {0xbd958000}, {0xbd95a000}, {0xbd95c000}, {0xbd95e000},
+ {0xbd960000}, {0xbd962000}, {0xbd964000}, {0xbd966000},
+ {0xbd968000}, {0xbd96a000}, {0xbd96c000}, {0xbd96e000},
+ {0xbd970000}, {0xbd972000}, {0xbd974000}, {0xbd976000},
+ {0xbd978000}, {0xbd97a000}, {0xbd97c000}, {0xbd97e000},
+ {0xbd980000}, {0xbd982000}, {0xbd984000}, {0xbd986000},
+ {0xbd988000}, {0xbd98a000}, {0xbd98c000}, {0xbd98e000},
+ {0xbd990000}, {0xbd992000}, {0xbd994000}, {0xbd996000},
+ {0xbd998000}, {0xbd99a000}, {0xbd99c000}, {0xbd99e000},
+ {0xbd9a0000}, {0xbd9a2000}, {0xbd9a4000}, {0xbd9a6000},
+ {0xbd9a8000}, {0xbd9aa000}, {0xbd9ac000}, {0xbd9ae000},
+ {0xbd9b0000}, {0xbd9b2000}, {0xbd9b4000}, {0xbd9b6000},
+ {0xbd9b8000}, {0xbd9ba000}, {0xbd9bc000}, {0xbd9be000},
+ {0xbd9c0000}, {0xbd9c2000}, {0xbd9c4000}, {0xbd9c6000},
+ {0xbd9c8000}, {0xbd9ca000}, {0xbd9cc000}, {0xbd9ce000},
+ {0xbd9d0000}, {0xbd9d2000}, {0xbd9d4000}, {0xbd9d6000},
+ {0xbd9d8000}, {0xbd9da000}, {0xbd9dc000}, {0xbd9de000},
+ {0xbd9e0000}, {0xbd9e2000}, {0xbd9e4000}, {0xbd9e6000},
+ {0xbd9e8000}, {0xbd9ea000}, {0xbd9ec000}, {0xbd9ee000},
+ {0xbd9f0000}, {0xbd9f2000}, {0xbd9f4000}, {0xbd9f6000},
+ {0xbd9f8000}, {0xbd9fa000}, {0xbd9fc000}, {0xbd9fe000},
+ {0xbda00000}, {0xbda02000}, {0xbda04000}, {0xbda06000},
+ {0xbda08000}, {0xbda0a000}, {0xbda0c000}, {0xbda0e000},
+ {0xbda10000}, {0xbda12000}, {0xbda14000}, {0xbda16000},
+ {0xbda18000}, {0xbda1a000}, {0xbda1c000}, {0xbda1e000},
+ {0xbda20000}, {0xbda22000}, {0xbda24000}, {0xbda26000},
+ {0xbda28000}, {0xbda2a000}, {0xbda2c000}, {0xbda2e000},
+ {0xbda30000}, {0xbda32000}, {0xbda34000}, {0xbda36000},
+ {0xbda38000}, {0xbda3a000}, {0xbda3c000}, {0xbda3e000},
+ {0xbda40000}, {0xbda42000}, {0xbda44000}, {0xbda46000},
+ {0xbda48000}, {0xbda4a000}, {0xbda4c000}, {0xbda4e000},
+ {0xbda50000}, {0xbda52000}, {0xbda54000}, {0xbda56000},
+ {0xbda58000}, {0xbda5a000}, {0xbda5c000}, {0xbda5e000},
+ {0xbda60000}, {0xbda62000}, {0xbda64000}, {0xbda66000},
+ {0xbda68000}, {0xbda6a000}, {0xbda6c000}, {0xbda6e000},
+ {0xbda70000}, {0xbda72000}, {0xbda74000}, {0xbda76000},
+ {0xbda78000}, {0xbda7a000}, {0xbda7c000}, {0xbda7e000},
+ {0xbda80000}, {0xbda82000}, {0xbda84000}, {0xbda86000},
+ {0xbda88000}, {0xbda8a000}, {0xbda8c000}, {0xbda8e000},
+ {0xbda90000}, {0xbda92000}, {0xbda94000}, {0xbda96000},
+ {0xbda98000}, {0xbda9a000}, {0xbda9c000}, {0xbda9e000},
+ {0xbdaa0000}, {0xbdaa2000}, {0xbdaa4000}, {0xbdaa6000},
+ {0xbdaa8000}, {0xbdaaa000}, {0xbdaac000}, {0xbdaae000},
+ {0xbdab0000}, {0xbdab2000}, {0xbdab4000}, {0xbdab6000},
+ {0xbdab8000}, {0xbdaba000}, {0xbdabc000}, {0xbdabe000},
+ {0xbdac0000}, {0xbdac2000}, {0xbdac4000}, {0xbdac6000},
+ {0xbdac8000}, {0xbdaca000}, {0xbdacc000}, {0xbdace000},
+ {0xbdad0000}, {0xbdad2000}, {0xbdad4000}, {0xbdad6000},
+ {0xbdad8000}, {0xbdada000}, {0xbdadc000}, {0xbdade000},
+ {0xbdae0000}, {0xbdae2000}, {0xbdae4000}, {0xbdae6000},
+ {0xbdae8000}, {0xbdaea000}, {0xbdaec000}, {0xbdaee000},
+ {0xbdaf0000}, {0xbdaf2000}, {0xbdaf4000}, {0xbdaf6000},
+ {0xbdaf8000}, {0xbdafa000}, {0xbdafc000}, {0xbdafe000},
+ {0xbdb00000}, {0xbdb02000}, {0xbdb04000}, {0xbdb06000},
+ {0xbdb08000}, {0xbdb0a000}, {0xbdb0c000}, {0xbdb0e000},
+ {0xbdb10000}, {0xbdb12000}, {0xbdb14000}, {0xbdb16000},
+ {0xbdb18000}, {0xbdb1a000}, {0xbdb1c000}, {0xbdb1e000},
+ {0xbdb20000}, {0xbdb22000}, {0xbdb24000}, {0xbdb26000},
+ {0xbdb28000}, {0xbdb2a000}, {0xbdb2c000}, {0xbdb2e000},
+ {0xbdb30000}, {0xbdb32000}, {0xbdb34000}, {0xbdb36000},
+ {0xbdb38000}, {0xbdb3a000}, {0xbdb3c000}, {0xbdb3e000},
+ {0xbdb40000}, {0xbdb42000}, {0xbdb44000}, {0xbdb46000},
+ {0xbdb48000}, {0xbdb4a000}, {0xbdb4c000}, {0xbdb4e000},
+ {0xbdb50000}, {0xbdb52000}, {0xbdb54000}, {0xbdb56000},
+ {0xbdb58000}, {0xbdb5a000}, {0xbdb5c000}, {0xbdb5e000},
+ {0xbdb60000}, {0xbdb62000}, {0xbdb64000}, {0xbdb66000},
+ {0xbdb68000}, {0xbdb6a000}, {0xbdb6c000}, {0xbdb6e000},
+ {0xbdb70000}, {0xbdb72000}, {0xbdb74000}, {0xbdb76000},
+ {0xbdb78000}, {0xbdb7a000}, {0xbdb7c000}, {0xbdb7e000},
+ {0xbdb80000}, {0xbdb82000}, {0xbdb84000}, {0xbdb86000},
+ {0xbdb88000}, {0xbdb8a000}, {0xbdb8c000}, {0xbdb8e000},
+ {0xbdb90000}, {0xbdb92000}, {0xbdb94000}, {0xbdb96000},
+ {0xbdb98000}, {0xbdb9a000}, {0xbdb9c000}, {0xbdb9e000},
+ {0xbdba0000}, {0xbdba2000}, {0xbdba4000}, {0xbdba6000},
+ {0xbdba8000}, {0xbdbaa000}, {0xbdbac000}, {0xbdbae000},
+ {0xbdbb0000}, {0xbdbb2000}, {0xbdbb4000}, {0xbdbb6000},
+ {0xbdbb8000}, {0xbdbba000}, {0xbdbbc000}, {0xbdbbe000},
+ {0xbdbc0000}, {0xbdbc2000}, {0xbdbc4000}, {0xbdbc6000},
+ {0xbdbc8000}, {0xbdbca000}, {0xbdbcc000}, {0xbdbce000},
+ {0xbdbd0000}, {0xbdbd2000}, {0xbdbd4000}, {0xbdbd6000},
+ {0xbdbd8000}, {0xbdbda000}, {0xbdbdc000}, {0xbdbde000},
+ {0xbdbe0000}, {0xbdbe2000}, {0xbdbe4000}, {0xbdbe6000},
+ {0xbdbe8000}, {0xbdbea000}, {0xbdbec000}, {0xbdbee000},
+ {0xbdbf0000}, {0xbdbf2000}, {0xbdbf4000}, {0xbdbf6000},
+ {0xbdbf8000}, {0xbdbfa000}, {0xbdbfc000}, {0xbdbfe000},
+ {0xbdc00000}, {0xbdc02000}, {0xbdc04000}, {0xbdc06000},
+ {0xbdc08000}, {0xbdc0a000}, {0xbdc0c000}, {0xbdc0e000},
+ {0xbdc10000}, {0xbdc12000}, {0xbdc14000}, {0xbdc16000},
+ {0xbdc18000}, {0xbdc1a000}, {0xbdc1c000}, {0xbdc1e000},
+ {0xbdc20000}, {0xbdc22000}, {0xbdc24000}, {0xbdc26000},
+ {0xbdc28000}, {0xbdc2a000}, {0xbdc2c000}, {0xbdc2e000},
+ {0xbdc30000}, {0xbdc32000}, {0xbdc34000}, {0xbdc36000},
+ {0xbdc38000}, {0xbdc3a000}, {0xbdc3c000}, {0xbdc3e000},
+ {0xbdc40000}, {0xbdc42000}, {0xbdc44000}, {0xbdc46000},
+ {0xbdc48000}, {0xbdc4a000}, {0xbdc4c000}, {0xbdc4e000},
+ {0xbdc50000}, {0xbdc52000}, {0xbdc54000}, {0xbdc56000},
+ {0xbdc58000}, {0xbdc5a000}, {0xbdc5c000}, {0xbdc5e000},
+ {0xbdc60000}, {0xbdc62000}, {0xbdc64000}, {0xbdc66000},
+ {0xbdc68000}, {0xbdc6a000}, {0xbdc6c000}, {0xbdc6e000},
+ {0xbdc70000}, {0xbdc72000}, {0xbdc74000}, {0xbdc76000},
+ {0xbdc78000}, {0xbdc7a000}, {0xbdc7c000}, {0xbdc7e000},
+ {0xbdc80000}, {0xbdc82000}, {0xbdc84000}, {0xbdc86000},
+ {0xbdc88000}, {0xbdc8a000}, {0xbdc8c000}, {0xbdc8e000},
+ {0xbdc90000}, {0xbdc92000}, {0xbdc94000}, {0xbdc96000},
+ {0xbdc98000}, {0xbdc9a000}, {0xbdc9c000}, {0xbdc9e000},
+ {0xbdca0000}, {0xbdca2000}, {0xbdca4000}, {0xbdca6000},
+ {0xbdca8000}, {0xbdcaa000}, {0xbdcac000}, {0xbdcae000},
+ {0xbdcb0000}, {0xbdcb2000}, {0xbdcb4000}, {0xbdcb6000},
+ {0xbdcb8000}, {0xbdcba000}, {0xbdcbc000}, {0xbdcbe000},
+ {0xbdcc0000}, {0xbdcc2000}, {0xbdcc4000}, {0xbdcc6000},
+ {0xbdcc8000}, {0xbdcca000}, {0xbdccc000}, {0xbdcce000},
+ {0xbdcd0000}, {0xbdcd2000}, {0xbdcd4000}, {0xbdcd6000},
+ {0xbdcd8000}, {0xbdcda000}, {0xbdcdc000}, {0xbdcde000},
+ {0xbdce0000}, {0xbdce2000}, {0xbdce4000}, {0xbdce6000},
+ {0xbdce8000}, {0xbdcea000}, {0xbdcec000}, {0xbdcee000},
+ {0xbdcf0000}, {0xbdcf2000}, {0xbdcf4000}, {0xbdcf6000},
+ {0xbdcf8000}, {0xbdcfa000}, {0xbdcfc000}, {0xbdcfe000},
+ {0xbdd00000}, {0xbdd02000}, {0xbdd04000}, {0xbdd06000},
+ {0xbdd08000}, {0xbdd0a000}, {0xbdd0c000}, {0xbdd0e000},
+ {0xbdd10000}, {0xbdd12000}, {0xbdd14000}, {0xbdd16000},
+ {0xbdd18000}, {0xbdd1a000}, {0xbdd1c000}, {0xbdd1e000},
+ {0xbdd20000}, {0xbdd22000}, {0xbdd24000}, {0xbdd26000},
+ {0xbdd28000}, {0xbdd2a000}, {0xbdd2c000}, {0xbdd2e000},
+ {0xbdd30000}, {0xbdd32000}, {0xbdd34000}, {0xbdd36000},
+ {0xbdd38000}, {0xbdd3a000}, {0xbdd3c000}, {0xbdd3e000},
+ {0xbdd40000}, {0xbdd42000}, {0xbdd44000}, {0xbdd46000},
+ {0xbdd48000}, {0xbdd4a000}, {0xbdd4c000}, {0xbdd4e000},
+ {0xbdd50000}, {0xbdd52000}, {0xbdd54000}, {0xbdd56000},
+ {0xbdd58000}, {0xbdd5a000}, {0xbdd5c000}, {0xbdd5e000},
+ {0xbdd60000}, {0xbdd62000}, {0xbdd64000}, {0xbdd66000},
+ {0xbdd68000}, {0xbdd6a000}, {0xbdd6c000}, {0xbdd6e000},
+ {0xbdd70000}, {0xbdd72000}, {0xbdd74000}, {0xbdd76000},
+ {0xbdd78000}, {0xbdd7a000}, {0xbdd7c000}, {0xbdd7e000},
+ {0xbdd80000}, {0xbdd82000}, {0xbdd84000}, {0xbdd86000},
+ {0xbdd88000}, {0xbdd8a000}, {0xbdd8c000}, {0xbdd8e000},
+ {0xbdd90000}, {0xbdd92000}, {0xbdd94000}, {0xbdd96000},
+ {0xbdd98000}, {0xbdd9a000}, {0xbdd9c000}, {0xbdd9e000},
+ {0xbdda0000}, {0xbdda2000}, {0xbdda4000}, {0xbdda6000},
+ {0xbdda8000}, {0xbddaa000}, {0xbddac000}, {0xbddae000},
+ {0xbddb0000}, {0xbddb2000}, {0xbddb4000}, {0xbddb6000},
+ {0xbddb8000}, {0xbddba000}, {0xbddbc000}, {0xbddbe000},
+ {0xbddc0000}, {0xbddc2000}, {0xbddc4000}, {0xbddc6000},
+ {0xbddc8000}, {0xbddca000}, {0xbddcc000}, {0xbddce000},
+ {0xbddd0000}, {0xbddd2000}, {0xbddd4000}, {0xbddd6000},
+ {0xbddd8000}, {0xbddda000}, {0xbdddc000}, {0xbddde000},
+ {0xbdde0000}, {0xbdde2000}, {0xbdde4000}, {0xbdde6000},
+ {0xbdde8000}, {0xbddea000}, {0xbddec000}, {0xbddee000},
+ {0xbddf0000}, {0xbddf2000}, {0xbddf4000}, {0xbddf6000},
+ {0xbddf8000}, {0xbddfa000}, {0xbddfc000}, {0xbddfe000},
+ {0xbde00000}, {0xbde02000}, {0xbde04000}, {0xbde06000},
+ {0xbde08000}, {0xbde0a000}, {0xbde0c000}, {0xbde0e000},
+ {0xbde10000}, {0xbde12000}, {0xbde14000}, {0xbde16000},
+ {0xbde18000}, {0xbde1a000}, {0xbde1c000}, {0xbde1e000},
+ {0xbde20000}, {0xbde22000}, {0xbde24000}, {0xbde26000},
+ {0xbde28000}, {0xbde2a000}, {0xbde2c000}, {0xbde2e000},
+ {0xbde30000}, {0xbde32000}, {0xbde34000}, {0xbde36000},
+ {0xbde38000}, {0xbde3a000}, {0xbde3c000}, {0xbde3e000},
+ {0xbde40000}, {0xbde42000}, {0xbde44000}, {0xbde46000},
+ {0xbde48000}, {0xbde4a000}, {0xbde4c000}, {0xbde4e000},
+ {0xbde50000}, {0xbde52000}, {0xbde54000}, {0xbde56000},
+ {0xbde58000}, {0xbde5a000}, {0xbde5c000}, {0xbde5e000},
+ {0xbde60000}, {0xbde62000}, {0xbde64000}, {0xbde66000},
+ {0xbde68000}, {0xbde6a000}, {0xbde6c000}, {0xbde6e000},
+ {0xbde70000}, {0xbde72000}, {0xbde74000}, {0xbde76000},
+ {0xbde78000}, {0xbde7a000}, {0xbde7c000}, {0xbde7e000},
+ {0xbde80000}, {0xbde82000}, {0xbde84000}, {0xbde86000},
+ {0xbde88000}, {0xbde8a000}, {0xbde8c000}, {0xbde8e000},
+ {0xbde90000}, {0xbde92000}, {0xbde94000}, {0xbde96000},
+ {0xbde98000}, {0xbde9a000}, {0xbde9c000}, {0xbde9e000},
+ {0xbdea0000}, {0xbdea2000}, {0xbdea4000}, {0xbdea6000},
+ {0xbdea8000}, {0xbdeaa000}, {0xbdeac000}, {0xbdeae000},
+ {0xbdeb0000}, {0xbdeb2000}, {0xbdeb4000}, {0xbdeb6000},
+ {0xbdeb8000}, {0xbdeba000}, {0xbdebc000}, {0xbdebe000},
+ {0xbdec0000}, {0xbdec2000}, {0xbdec4000}, {0xbdec6000},
+ {0xbdec8000}, {0xbdeca000}, {0xbdecc000}, {0xbdece000},
+ {0xbded0000}, {0xbded2000}, {0xbded4000}, {0xbded6000},
+ {0xbded8000}, {0xbdeda000}, {0xbdedc000}, {0xbdede000},
+ {0xbdee0000}, {0xbdee2000}, {0xbdee4000}, {0xbdee6000},
+ {0xbdee8000}, {0xbdeea000}, {0xbdeec000}, {0xbdeee000},
+ {0xbdef0000}, {0xbdef2000}, {0xbdef4000}, {0xbdef6000},
+ {0xbdef8000}, {0xbdefa000}, {0xbdefc000}, {0xbdefe000},
+ {0xbdf00000}, {0xbdf02000}, {0xbdf04000}, {0xbdf06000},
+ {0xbdf08000}, {0xbdf0a000}, {0xbdf0c000}, {0xbdf0e000},
+ {0xbdf10000}, {0xbdf12000}, {0xbdf14000}, {0xbdf16000},
+ {0xbdf18000}, {0xbdf1a000}, {0xbdf1c000}, {0xbdf1e000},
+ {0xbdf20000}, {0xbdf22000}, {0xbdf24000}, {0xbdf26000},
+ {0xbdf28000}, {0xbdf2a000}, {0xbdf2c000}, {0xbdf2e000},
+ {0xbdf30000}, {0xbdf32000}, {0xbdf34000}, {0xbdf36000},
+ {0xbdf38000}, {0xbdf3a000}, {0xbdf3c000}, {0xbdf3e000},
+ {0xbdf40000}, {0xbdf42000}, {0xbdf44000}, {0xbdf46000},
+ {0xbdf48000}, {0xbdf4a000}, {0xbdf4c000}, {0xbdf4e000},
+ {0xbdf50000}, {0xbdf52000}, {0xbdf54000}, {0xbdf56000},
+ {0xbdf58000}, {0xbdf5a000}, {0xbdf5c000}, {0xbdf5e000},
+ {0xbdf60000}, {0xbdf62000}, {0xbdf64000}, {0xbdf66000},
+ {0xbdf68000}, {0xbdf6a000}, {0xbdf6c000}, {0xbdf6e000},
+ {0xbdf70000}, {0xbdf72000}, {0xbdf74000}, {0xbdf76000},
+ {0xbdf78000}, {0xbdf7a000}, {0xbdf7c000}, {0xbdf7e000},
+ {0xbdf80000}, {0xbdf82000}, {0xbdf84000}, {0xbdf86000},
+ {0xbdf88000}, {0xbdf8a000}, {0xbdf8c000}, {0xbdf8e000},
+ {0xbdf90000}, {0xbdf92000}, {0xbdf94000}, {0xbdf96000},
+ {0xbdf98000}, {0xbdf9a000}, {0xbdf9c000}, {0xbdf9e000},
+ {0xbdfa0000}, {0xbdfa2000}, {0xbdfa4000}, {0xbdfa6000},
+ {0xbdfa8000}, {0xbdfaa000}, {0xbdfac000}, {0xbdfae000},
+ {0xbdfb0000}, {0xbdfb2000}, {0xbdfb4000}, {0xbdfb6000},
+ {0xbdfb8000}, {0xbdfba000}, {0xbdfbc000}, {0xbdfbe000},
+ {0xbdfc0000}, {0xbdfc2000}, {0xbdfc4000}, {0xbdfc6000},
+ {0xbdfc8000}, {0xbdfca000}, {0xbdfcc000}, {0xbdfce000},
+ {0xbdfd0000}, {0xbdfd2000}, {0xbdfd4000}, {0xbdfd6000},
+ {0xbdfd8000}, {0xbdfda000}, {0xbdfdc000}, {0xbdfde000},
+ {0xbdfe0000}, {0xbdfe2000}, {0xbdfe4000}, {0xbdfe6000},
+ {0xbdfe8000}, {0xbdfea000}, {0xbdfec000}, {0xbdfee000},
+ {0xbdff0000}, {0xbdff2000}, {0xbdff4000}, {0xbdff6000},
+ {0xbdff8000}, {0xbdffa000}, {0xbdffc000}, {0xbdffe000},
+ {0xbe000000}, {0xbe002000}, {0xbe004000}, {0xbe006000},
+ {0xbe008000}, {0xbe00a000}, {0xbe00c000}, {0xbe00e000},
+ {0xbe010000}, {0xbe012000}, {0xbe014000}, {0xbe016000},
+ {0xbe018000}, {0xbe01a000}, {0xbe01c000}, {0xbe01e000},
+ {0xbe020000}, {0xbe022000}, {0xbe024000}, {0xbe026000},
+ {0xbe028000}, {0xbe02a000}, {0xbe02c000}, {0xbe02e000},
+ {0xbe030000}, {0xbe032000}, {0xbe034000}, {0xbe036000},
+ {0xbe038000}, {0xbe03a000}, {0xbe03c000}, {0xbe03e000},
+ {0xbe040000}, {0xbe042000}, {0xbe044000}, {0xbe046000},
+ {0xbe048000}, {0xbe04a000}, {0xbe04c000}, {0xbe04e000},
+ {0xbe050000}, {0xbe052000}, {0xbe054000}, {0xbe056000},
+ {0xbe058000}, {0xbe05a000}, {0xbe05c000}, {0xbe05e000},
+ {0xbe060000}, {0xbe062000}, {0xbe064000}, {0xbe066000},
+ {0xbe068000}, {0xbe06a000}, {0xbe06c000}, {0xbe06e000},
+ {0xbe070000}, {0xbe072000}, {0xbe074000}, {0xbe076000},
+ {0xbe078000}, {0xbe07a000}, {0xbe07c000}, {0xbe07e000},
+ {0xbe080000}, {0xbe082000}, {0xbe084000}, {0xbe086000},
+ {0xbe088000}, {0xbe08a000}, {0xbe08c000}, {0xbe08e000},
+ {0xbe090000}, {0xbe092000}, {0xbe094000}, {0xbe096000},
+ {0xbe098000}, {0xbe09a000}, {0xbe09c000}, {0xbe09e000},
+ {0xbe0a0000}, {0xbe0a2000}, {0xbe0a4000}, {0xbe0a6000},
+ {0xbe0a8000}, {0xbe0aa000}, {0xbe0ac000}, {0xbe0ae000},
+ {0xbe0b0000}, {0xbe0b2000}, {0xbe0b4000}, {0xbe0b6000},
+ {0xbe0b8000}, {0xbe0ba000}, {0xbe0bc000}, {0xbe0be000},
+ {0xbe0c0000}, {0xbe0c2000}, {0xbe0c4000}, {0xbe0c6000},
+ {0xbe0c8000}, {0xbe0ca000}, {0xbe0cc000}, {0xbe0ce000},
+ {0xbe0d0000}, {0xbe0d2000}, {0xbe0d4000}, {0xbe0d6000},
+ {0xbe0d8000}, {0xbe0da000}, {0xbe0dc000}, {0xbe0de000},
+ {0xbe0e0000}, {0xbe0e2000}, {0xbe0e4000}, {0xbe0e6000},
+ {0xbe0e8000}, {0xbe0ea000}, {0xbe0ec000}, {0xbe0ee000},
+ {0xbe0f0000}, {0xbe0f2000}, {0xbe0f4000}, {0xbe0f6000},
+ {0xbe0f8000}, {0xbe0fa000}, {0xbe0fc000}, {0xbe0fe000},
+ {0xbe100000}, {0xbe102000}, {0xbe104000}, {0xbe106000},
+ {0xbe108000}, {0xbe10a000}, {0xbe10c000}, {0xbe10e000},
+ {0xbe110000}, {0xbe112000}, {0xbe114000}, {0xbe116000},
+ {0xbe118000}, {0xbe11a000}, {0xbe11c000}, {0xbe11e000},
+ {0xbe120000}, {0xbe122000}, {0xbe124000}, {0xbe126000},
+ {0xbe128000}, {0xbe12a000}, {0xbe12c000}, {0xbe12e000},
+ {0xbe130000}, {0xbe132000}, {0xbe134000}, {0xbe136000},
+ {0xbe138000}, {0xbe13a000}, {0xbe13c000}, {0xbe13e000},
+ {0xbe140000}, {0xbe142000}, {0xbe144000}, {0xbe146000},
+ {0xbe148000}, {0xbe14a000}, {0xbe14c000}, {0xbe14e000},
+ {0xbe150000}, {0xbe152000}, {0xbe154000}, {0xbe156000},
+ {0xbe158000}, {0xbe15a000}, {0xbe15c000}, {0xbe15e000},
+ {0xbe160000}, {0xbe162000}, {0xbe164000}, {0xbe166000},
+ {0xbe168000}, {0xbe16a000}, {0xbe16c000}, {0xbe16e000},
+ {0xbe170000}, {0xbe172000}, {0xbe174000}, {0xbe176000},
+ {0xbe178000}, {0xbe17a000}, {0xbe17c000}, {0xbe17e000},
+ {0xbe180000}, {0xbe182000}, {0xbe184000}, {0xbe186000},
+ {0xbe188000}, {0xbe18a000}, {0xbe18c000}, {0xbe18e000},
+ {0xbe190000}, {0xbe192000}, {0xbe194000}, {0xbe196000},
+ {0xbe198000}, {0xbe19a000}, {0xbe19c000}, {0xbe19e000},
+ {0xbe1a0000}, {0xbe1a2000}, {0xbe1a4000}, {0xbe1a6000},
+ {0xbe1a8000}, {0xbe1aa000}, {0xbe1ac000}, {0xbe1ae000},
+ {0xbe1b0000}, {0xbe1b2000}, {0xbe1b4000}, {0xbe1b6000},
+ {0xbe1b8000}, {0xbe1ba000}, {0xbe1bc000}, {0xbe1be000},
+ {0xbe1c0000}, {0xbe1c2000}, {0xbe1c4000}, {0xbe1c6000},
+ {0xbe1c8000}, {0xbe1ca000}, {0xbe1cc000}, {0xbe1ce000},
+ {0xbe1d0000}, {0xbe1d2000}, {0xbe1d4000}, {0xbe1d6000},
+ {0xbe1d8000}, {0xbe1da000}, {0xbe1dc000}, {0xbe1de000},
+ {0xbe1e0000}, {0xbe1e2000}, {0xbe1e4000}, {0xbe1e6000},
+ {0xbe1e8000}, {0xbe1ea000}, {0xbe1ec000}, {0xbe1ee000},
+ {0xbe1f0000}, {0xbe1f2000}, {0xbe1f4000}, {0xbe1f6000},
+ {0xbe1f8000}, {0xbe1fa000}, {0xbe1fc000}, {0xbe1fe000},
+ {0xbe200000}, {0xbe202000}, {0xbe204000}, {0xbe206000},
+ {0xbe208000}, {0xbe20a000}, {0xbe20c000}, {0xbe20e000},
+ {0xbe210000}, {0xbe212000}, {0xbe214000}, {0xbe216000},
+ {0xbe218000}, {0xbe21a000}, {0xbe21c000}, {0xbe21e000},
+ {0xbe220000}, {0xbe222000}, {0xbe224000}, {0xbe226000},
+ {0xbe228000}, {0xbe22a000}, {0xbe22c000}, {0xbe22e000},
+ {0xbe230000}, {0xbe232000}, {0xbe234000}, {0xbe236000},
+ {0xbe238000}, {0xbe23a000}, {0xbe23c000}, {0xbe23e000},
+ {0xbe240000}, {0xbe242000}, {0xbe244000}, {0xbe246000},
+ {0xbe248000}, {0xbe24a000}, {0xbe24c000}, {0xbe24e000},
+ {0xbe250000}, {0xbe252000}, {0xbe254000}, {0xbe256000},
+ {0xbe258000}, {0xbe25a000}, {0xbe25c000}, {0xbe25e000},
+ {0xbe260000}, {0xbe262000}, {0xbe264000}, {0xbe266000},
+ {0xbe268000}, {0xbe26a000}, {0xbe26c000}, {0xbe26e000},
+ {0xbe270000}, {0xbe272000}, {0xbe274000}, {0xbe276000},
+ {0xbe278000}, {0xbe27a000}, {0xbe27c000}, {0xbe27e000},
+ {0xbe280000}, {0xbe282000}, {0xbe284000}, {0xbe286000},
+ {0xbe288000}, {0xbe28a000}, {0xbe28c000}, {0xbe28e000},
+ {0xbe290000}, {0xbe292000}, {0xbe294000}, {0xbe296000},
+ {0xbe298000}, {0xbe29a000}, {0xbe29c000}, {0xbe29e000},
+ {0xbe2a0000}, {0xbe2a2000}, {0xbe2a4000}, {0xbe2a6000},
+ {0xbe2a8000}, {0xbe2aa000}, {0xbe2ac000}, {0xbe2ae000},
+ {0xbe2b0000}, {0xbe2b2000}, {0xbe2b4000}, {0xbe2b6000},
+ {0xbe2b8000}, {0xbe2ba000}, {0xbe2bc000}, {0xbe2be000},
+ {0xbe2c0000}, {0xbe2c2000}, {0xbe2c4000}, {0xbe2c6000},
+ {0xbe2c8000}, {0xbe2ca000}, {0xbe2cc000}, {0xbe2ce000},
+ {0xbe2d0000}, {0xbe2d2000}, {0xbe2d4000}, {0xbe2d6000},
+ {0xbe2d8000}, {0xbe2da000}, {0xbe2dc000}, {0xbe2de000},
+ {0xbe2e0000}, {0xbe2e2000}, {0xbe2e4000}, {0xbe2e6000},
+ {0xbe2e8000}, {0xbe2ea000}, {0xbe2ec000}, {0xbe2ee000},
+ {0xbe2f0000}, {0xbe2f2000}, {0xbe2f4000}, {0xbe2f6000},
+ {0xbe2f8000}, {0xbe2fa000}, {0xbe2fc000}, {0xbe2fe000},
+ {0xbe300000}, {0xbe302000}, {0xbe304000}, {0xbe306000},
+ {0xbe308000}, {0xbe30a000}, {0xbe30c000}, {0xbe30e000},
+ {0xbe310000}, {0xbe312000}, {0xbe314000}, {0xbe316000},
+ {0xbe318000}, {0xbe31a000}, {0xbe31c000}, {0xbe31e000},
+ {0xbe320000}, {0xbe322000}, {0xbe324000}, {0xbe326000},
+ {0xbe328000}, {0xbe32a000}, {0xbe32c000}, {0xbe32e000},
+ {0xbe330000}, {0xbe332000}, {0xbe334000}, {0xbe336000},
+ {0xbe338000}, {0xbe33a000}, {0xbe33c000}, {0xbe33e000},
+ {0xbe340000}, {0xbe342000}, {0xbe344000}, {0xbe346000},
+ {0xbe348000}, {0xbe34a000}, {0xbe34c000}, {0xbe34e000},
+ {0xbe350000}, {0xbe352000}, {0xbe354000}, {0xbe356000},
+ {0xbe358000}, {0xbe35a000}, {0xbe35c000}, {0xbe35e000},
+ {0xbe360000}, {0xbe362000}, {0xbe364000}, {0xbe366000},
+ {0xbe368000}, {0xbe36a000}, {0xbe36c000}, {0xbe36e000},
+ {0xbe370000}, {0xbe372000}, {0xbe374000}, {0xbe376000},
+ {0xbe378000}, {0xbe37a000}, {0xbe37c000}, {0xbe37e000},
+ {0xbe380000}, {0xbe382000}, {0xbe384000}, {0xbe386000},
+ {0xbe388000}, {0xbe38a000}, {0xbe38c000}, {0xbe38e000},
+ {0xbe390000}, {0xbe392000}, {0xbe394000}, {0xbe396000},
+ {0xbe398000}, {0xbe39a000}, {0xbe39c000}, {0xbe39e000},
+ {0xbe3a0000}, {0xbe3a2000}, {0xbe3a4000}, {0xbe3a6000},
+ {0xbe3a8000}, {0xbe3aa000}, {0xbe3ac000}, {0xbe3ae000},
+ {0xbe3b0000}, {0xbe3b2000}, {0xbe3b4000}, {0xbe3b6000},
+ {0xbe3b8000}, {0xbe3ba000}, {0xbe3bc000}, {0xbe3be000},
+ {0xbe3c0000}, {0xbe3c2000}, {0xbe3c4000}, {0xbe3c6000},
+ {0xbe3c8000}, {0xbe3ca000}, {0xbe3cc000}, {0xbe3ce000},
+ {0xbe3d0000}, {0xbe3d2000}, {0xbe3d4000}, {0xbe3d6000},
+ {0xbe3d8000}, {0xbe3da000}, {0xbe3dc000}, {0xbe3de000},
+ {0xbe3e0000}, {0xbe3e2000}, {0xbe3e4000}, {0xbe3e6000},
+ {0xbe3e8000}, {0xbe3ea000}, {0xbe3ec000}, {0xbe3ee000},
+ {0xbe3f0000}, {0xbe3f2000}, {0xbe3f4000}, {0xbe3f6000},
+ {0xbe3f8000}, {0xbe3fa000}, {0xbe3fc000}, {0xbe3fe000},
+ {0xbe400000}, {0xbe402000}, {0xbe404000}, {0xbe406000},
+ {0xbe408000}, {0xbe40a000}, {0xbe40c000}, {0xbe40e000},
+ {0xbe410000}, {0xbe412000}, {0xbe414000}, {0xbe416000},
+ {0xbe418000}, {0xbe41a000}, {0xbe41c000}, {0xbe41e000},
+ {0xbe420000}, {0xbe422000}, {0xbe424000}, {0xbe426000},
+ {0xbe428000}, {0xbe42a000}, {0xbe42c000}, {0xbe42e000},
+ {0xbe430000}, {0xbe432000}, {0xbe434000}, {0xbe436000},
+ {0xbe438000}, {0xbe43a000}, {0xbe43c000}, {0xbe43e000},
+ {0xbe440000}, {0xbe442000}, {0xbe444000}, {0xbe446000},
+ {0xbe448000}, {0xbe44a000}, {0xbe44c000}, {0xbe44e000},
+ {0xbe450000}, {0xbe452000}, {0xbe454000}, {0xbe456000},
+ {0xbe458000}, {0xbe45a000}, {0xbe45c000}, {0xbe45e000},
+ {0xbe460000}, {0xbe462000}, {0xbe464000}, {0xbe466000},
+ {0xbe468000}, {0xbe46a000}, {0xbe46c000}, {0xbe46e000},
+ {0xbe470000}, {0xbe472000}, {0xbe474000}, {0xbe476000},
+ {0xbe478000}, {0xbe47a000}, {0xbe47c000}, {0xbe47e000},
+ {0xbe480000}, {0xbe482000}, {0xbe484000}, {0xbe486000},
+ {0xbe488000}, {0xbe48a000}, {0xbe48c000}, {0xbe48e000},
+ {0xbe490000}, {0xbe492000}, {0xbe494000}, {0xbe496000},
+ {0xbe498000}, {0xbe49a000}, {0xbe49c000}, {0xbe49e000},
+ {0xbe4a0000}, {0xbe4a2000}, {0xbe4a4000}, {0xbe4a6000},
+ {0xbe4a8000}, {0xbe4aa000}, {0xbe4ac000}, {0xbe4ae000},
+ {0xbe4b0000}, {0xbe4b2000}, {0xbe4b4000}, {0xbe4b6000},
+ {0xbe4b8000}, {0xbe4ba000}, {0xbe4bc000}, {0xbe4be000},
+ {0xbe4c0000}, {0xbe4c2000}, {0xbe4c4000}, {0xbe4c6000},
+ {0xbe4c8000}, {0xbe4ca000}, {0xbe4cc000}, {0xbe4ce000},
+ {0xbe4d0000}, {0xbe4d2000}, {0xbe4d4000}, {0xbe4d6000},
+ {0xbe4d8000}, {0xbe4da000}, {0xbe4dc000}, {0xbe4de000},
+ {0xbe4e0000}, {0xbe4e2000}, {0xbe4e4000}, {0xbe4e6000},
+ {0xbe4e8000}, {0xbe4ea000}, {0xbe4ec000}, {0xbe4ee000},
+ {0xbe4f0000}, {0xbe4f2000}, {0xbe4f4000}, {0xbe4f6000},
+ {0xbe4f8000}, {0xbe4fa000}, {0xbe4fc000}, {0xbe4fe000},
+ {0xbe500000}, {0xbe502000}, {0xbe504000}, {0xbe506000},
+ {0xbe508000}, {0xbe50a000}, {0xbe50c000}, {0xbe50e000},
+ {0xbe510000}, {0xbe512000}, {0xbe514000}, {0xbe516000},
+ {0xbe518000}, {0xbe51a000}, {0xbe51c000}, {0xbe51e000},
+ {0xbe520000}, {0xbe522000}, {0xbe524000}, {0xbe526000},
+ {0xbe528000}, {0xbe52a000}, {0xbe52c000}, {0xbe52e000},
+ {0xbe530000}, {0xbe532000}, {0xbe534000}, {0xbe536000},
+ {0xbe538000}, {0xbe53a000}, {0xbe53c000}, {0xbe53e000},
+ {0xbe540000}, {0xbe542000}, {0xbe544000}, {0xbe546000},
+ {0xbe548000}, {0xbe54a000}, {0xbe54c000}, {0xbe54e000},
+ {0xbe550000}, {0xbe552000}, {0xbe554000}, {0xbe556000},
+ {0xbe558000}, {0xbe55a000}, {0xbe55c000}, {0xbe55e000},
+ {0xbe560000}, {0xbe562000}, {0xbe564000}, {0xbe566000},
+ {0xbe568000}, {0xbe56a000}, {0xbe56c000}, {0xbe56e000},
+ {0xbe570000}, {0xbe572000}, {0xbe574000}, {0xbe576000},
+ {0xbe578000}, {0xbe57a000}, {0xbe57c000}, {0xbe57e000},
+ {0xbe580000}, {0xbe582000}, {0xbe584000}, {0xbe586000},
+ {0xbe588000}, {0xbe58a000}, {0xbe58c000}, {0xbe58e000},
+ {0xbe590000}, {0xbe592000}, {0xbe594000}, {0xbe596000},
+ {0xbe598000}, {0xbe59a000}, {0xbe59c000}, {0xbe59e000},
+ {0xbe5a0000}, {0xbe5a2000}, {0xbe5a4000}, {0xbe5a6000},
+ {0xbe5a8000}, {0xbe5aa000}, {0xbe5ac000}, {0xbe5ae000},
+ {0xbe5b0000}, {0xbe5b2000}, {0xbe5b4000}, {0xbe5b6000},
+ {0xbe5b8000}, {0xbe5ba000}, {0xbe5bc000}, {0xbe5be000},
+ {0xbe5c0000}, {0xbe5c2000}, {0xbe5c4000}, {0xbe5c6000},
+ {0xbe5c8000}, {0xbe5ca000}, {0xbe5cc000}, {0xbe5ce000},
+ {0xbe5d0000}, {0xbe5d2000}, {0xbe5d4000}, {0xbe5d6000},
+ {0xbe5d8000}, {0xbe5da000}, {0xbe5dc000}, {0xbe5de000},
+ {0xbe5e0000}, {0xbe5e2000}, {0xbe5e4000}, {0xbe5e6000},
+ {0xbe5e8000}, {0xbe5ea000}, {0xbe5ec000}, {0xbe5ee000},
+ {0xbe5f0000}, {0xbe5f2000}, {0xbe5f4000}, {0xbe5f6000},
+ {0xbe5f8000}, {0xbe5fa000}, {0xbe5fc000}, {0xbe5fe000},
+ {0xbe600000}, {0xbe602000}, {0xbe604000}, {0xbe606000},
+ {0xbe608000}, {0xbe60a000}, {0xbe60c000}, {0xbe60e000},
+ {0xbe610000}, {0xbe612000}, {0xbe614000}, {0xbe616000},
+ {0xbe618000}, {0xbe61a000}, {0xbe61c000}, {0xbe61e000},
+ {0xbe620000}, {0xbe622000}, {0xbe624000}, {0xbe626000},
+ {0xbe628000}, {0xbe62a000}, {0xbe62c000}, {0xbe62e000},
+ {0xbe630000}, {0xbe632000}, {0xbe634000}, {0xbe636000},
+ {0xbe638000}, {0xbe63a000}, {0xbe63c000}, {0xbe63e000},
+ {0xbe640000}, {0xbe642000}, {0xbe644000}, {0xbe646000},
+ {0xbe648000}, {0xbe64a000}, {0xbe64c000}, {0xbe64e000},
+ {0xbe650000}, {0xbe652000}, {0xbe654000}, {0xbe656000},
+ {0xbe658000}, {0xbe65a000}, {0xbe65c000}, {0xbe65e000},
+ {0xbe660000}, {0xbe662000}, {0xbe664000}, {0xbe666000},
+ {0xbe668000}, {0xbe66a000}, {0xbe66c000}, {0xbe66e000},
+ {0xbe670000}, {0xbe672000}, {0xbe674000}, {0xbe676000},
+ {0xbe678000}, {0xbe67a000}, {0xbe67c000}, {0xbe67e000},
+ {0xbe680000}, {0xbe682000}, {0xbe684000}, {0xbe686000},
+ {0xbe688000}, {0xbe68a000}, {0xbe68c000}, {0xbe68e000},
+ {0xbe690000}, {0xbe692000}, {0xbe694000}, {0xbe696000},
+ {0xbe698000}, {0xbe69a000}, {0xbe69c000}, {0xbe69e000},
+ {0xbe6a0000}, {0xbe6a2000}, {0xbe6a4000}, {0xbe6a6000},
+ {0xbe6a8000}, {0xbe6aa000}, {0xbe6ac000}, {0xbe6ae000},
+ {0xbe6b0000}, {0xbe6b2000}, {0xbe6b4000}, {0xbe6b6000},
+ {0xbe6b8000}, {0xbe6ba000}, {0xbe6bc000}, {0xbe6be000},
+ {0xbe6c0000}, {0xbe6c2000}, {0xbe6c4000}, {0xbe6c6000},
+ {0xbe6c8000}, {0xbe6ca000}, {0xbe6cc000}, {0xbe6ce000},
+ {0xbe6d0000}, {0xbe6d2000}, {0xbe6d4000}, {0xbe6d6000},
+ {0xbe6d8000}, {0xbe6da000}, {0xbe6dc000}, {0xbe6de000},
+ {0xbe6e0000}, {0xbe6e2000}, {0xbe6e4000}, {0xbe6e6000},
+ {0xbe6e8000}, {0xbe6ea000}, {0xbe6ec000}, {0xbe6ee000},
+ {0xbe6f0000}, {0xbe6f2000}, {0xbe6f4000}, {0xbe6f6000},
+ {0xbe6f8000}, {0xbe6fa000}, {0xbe6fc000}, {0xbe6fe000},
+ {0xbe700000}, {0xbe702000}, {0xbe704000}, {0xbe706000},
+ {0xbe708000}, {0xbe70a000}, {0xbe70c000}, {0xbe70e000},
+ {0xbe710000}, {0xbe712000}, {0xbe714000}, {0xbe716000},
+ {0xbe718000}, {0xbe71a000}, {0xbe71c000}, {0xbe71e000},
+ {0xbe720000}, {0xbe722000}, {0xbe724000}, {0xbe726000},
+ {0xbe728000}, {0xbe72a000}, {0xbe72c000}, {0xbe72e000},
+ {0xbe730000}, {0xbe732000}, {0xbe734000}, {0xbe736000},
+ {0xbe738000}, {0xbe73a000}, {0xbe73c000}, {0xbe73e000},
+ {0xbe740000}, {0xbe742000}, {0xbe744000}, {0xbe746000},
+ {0xbe748000}, {0xbe74a000}, {0xbe74c000}, {0xbe74e000},
+ {0xbe750000}, {0xbe752000}, {0xbe754000}, {0xbe756000},
+ {0xbe758000}, {0xbe75a000}, {0xbe75c000}, {0xbe75e000},
+ {0xbe760000}, {0xbe762000}, {0xbe764000}, {0xbe766000},
+ {0xbe768000}, {0xbe76a000}, {0xbe76c000}, {0xbe76e000},
+ {0xbe770000}, {0xbe772000}, {0xbe774000}, {0xbe776000},
+ {0xbe778000}, {0xbe77a000}, {0xbe77c000}, {0xbe77e000},
+ {0xbe780000}, {0xbe782000}, {0xbe784000}, {0xbe786000},
+ {0xbe788000}, {0xbe78a000}, {0xbe78c000}, {0xbe78e000},
+ {0xbe790000}, {0xbe792000}, {0xbe794000}, {0xbe796000},
+ {0xbe798000}, {0xbe79a000}, {0xbe79c000}, {0xbe79e000},
+ {0xbe7a0000}, {0xbe7a2000}, {0xbe7a4000}, {0xbe7a6000},
+ {0xbe7a8000}, {0xbe7aa000}, {0xbe7ac000}, {0xbe7ae000},
+ {0xbe7b0000}, {0xbe7b2000}, {0xbe7b4000}, {0xbe7b6000},
+ {0xbe7b8000}, {0xbe7ba000}, {0xbe7bc000}, {0xbe7be000},
+ {0xbe7c0000}, {0xbe7c2000}, {0xbe7c4000}, {0xbe7c6000},
+ {0xbe7c8000}, {0xbe7ca000}, {0xbe7cc000}, {0xbe7ce000},
+ {0xbe7d0000}, {0xbe7d2000}, {0xbe7d4000}, {0xbe7d6000},
+ {0xbe7d8000}, {0xbe7da000}, {0xbe7dc000}, {0xbe7de000},
+ {0xbe7e0000}, {0xbe7e2000}, {0xbe7e4000}, {0xbe7e6000},
+ {0xbe7e8000}, {0xbe7ea000}, {0xbe7ec000}, {0xbe7ee000},
+ {0xbe7f0000}, {0xbe7f2000}, {0xbe7f4000}, {0xbe7f6000},
+ {0xbe7f8000}, {0xbe7fa000}, {0xbe7fc000}, {0xbe7fe000},
+ {0xbe800000}, {0xbe802000}, {0xbe804000}, {0xbe806000},
+ {0xbe808000}, {0xbe80a000}, {0xbe80c000}, {0xbe80e000},
+ {0xbe810000}, {0xbe812000}, {0xbe814000}, {0xbe816000},
+ {0xbe818000}, {0xbe81a000}, {0xbe81c000}, {0xbe81e000},
+ {0xbe820000}, {0xbe822000}, {0xbe824000}, {0xbe826000},
+ {0xbe828000}, {0xbe82a000}, {0xbe82c000}, {0xbe82e000},
+ {0xbe830000}, {0xbe832000}, {0xbe834000}, {0xbe836000},
+ {0xbe838000}, {0xbe83a000}, {0xbe83c000}, {0xbe83e000},
+ {0xbe840000}, {0xbe842000}, {0xbe844000}, {0xbe846000},
+ {0xbe848000}, {0xbe84a000}, {0xbe84c000}, {0xbe84e000},
+ {0xbe850000}, {0xbe852000}, {0xbe854000}, {0xbe856000},
+ {0xbe858000}, {0xbe85a000}, {0xbe85c000}, {0xbe85e000},
+ {0xbe860000}, {0xbe862000}, {0xbe864000}, {0xbe866000},
+ {0xbe868000}, {0xbe86a000}, {0xbe86c000}, {0xbe86e000},
+ {0xbe870000}, {0xbe872000}, {0xbe874000}, {0xbe876000},
+ {0xbe878000}, {0xbe87a000}, {0xbe87c000}, {0xbe87e000},
+ {0xbe880000}, {0xbe882000}, {0xbe884000}, {0xbe886000},
+ {0xbe888000}, {0xbe88a000}, {0xbe88c000}, {0xbe88e000},
+ {0xbe890000}, {0xbe892000}, {0xbe894000}, {0xbe896000},
+ {0xbe898000}, {0xbe89a000}, {0xbe89c000}, {0xbe89e000},
+ {0xbe8a0000}, {0xbe8a2000}, {0xbe8a4000}, {0xbe8a6000},
+ {0xbe8a8000}, {0xbe8aa000}, {0xbe8ac000}, {0xbe8ae000},
+ {0xbe8b0000}, {0xbe8b2000}, {0xbe8b4000}, {0xbe8b6000},
+ {0xbe8b8000}, {0xbe8ba000}, {0xbe8bc000}, {0xbe8be000},
+ {0xbe8c0000}, {0xbe8c2000}, {0xbe8c4000}, {0xbe8c6000},
+ {0xbe8c8000}, {0xbe8ca000}, {0xbe8cc000}, {0xbe8ce000},
+ {0xbe8d0000}, {0xbe8d2000}, {0xbe8d4000}, {0xbe8d6000},
+ {0xbe8d8000}, {0xbe8da000}, {0xbe8dc000}, {0xbe8de000},
+ {0xbe8e0000}, {0xbe8e2000}, {0xbe8e4000}, {0xbe8e6000},
+ {0xbe8e8000}, {0xbe8ea000}, {0xbe8ec000}, {0xbe8ee000},
+ {0xbe8f0000}, {0xbe8f2000}, {0xbe8f4000}, {0xbe8f6000},
+ {0xbe8f8000}, {0xbe8fa000}, {0xbe8fc000}, {0xbe8fe000},
+ {0xbe900000}, {0xbe902000}, {0xbe904000}, {0xbe906000},
+ {0xbe908000}, {0xbe90a000}, {0xbe90c000}, {0xbe90e000},
+ {0xbe910000}, {0xbe912000}, {0xbe914000}, {0xbe916000},
+ {0xbe918000}, {0xbe91a000}, {0xbe91c000}, {0xbe91e000},
+ {0xbe920000}, {0xbe922000}, {0xbe924000}, {0xbe926000},
+ {0xbe928000}, {0xbe92a000}, {0xbe92c000}, {0xbe92e000},
+ {0xbe930000}, {0xbe932000}, {0xbe934000}, {0xbe936000},
+ {0xbe938000}, {0xbe93a000}, {0xbe93c000}, {0xbe93e000},
+ {0xbe940000}, {0xbe942000}, {0xbe944000}, {0xbe946000},
+ {0xbe948000}, {0xbe94a000}, {0xbe94c000}, {0xbe94e000},
+ {0xbe950000}, {0xbe952000}, {0xbe954000}, {0xbe956000},
+ {0xbe958000}, {0xbe95a000}, {0xbe95c000}, {0xbe95e000},
+ {0xbe960000}, {0xbe962000}, {0xbe964000}, {0xbe966000},
+ {0xbe968000}, {0xbe96a000}, {0xbe96c000}, {0xbe96e000},
+ {0xbe970000}, {0xbe972000}, {0xbe974000}, {0xbe976000},
+ {0xbe978000}, {0xbe97a000}, {0xbe97c000}, {0xbe97e000},
+ {0xbe980000}, {0xbe982000}, {0xbe984000}, {0xbe986000},
+ {0xbe988000}, {0xbe98a000}, {0xbe98c000}, {0xbe98e000},
+ {0xbe990000}, {0xbe992000}, {0xbe994000}, {0xbe996000},
+ {0xbe998000}, {0xbe99a000}, {0xbe99c000}, {0xbe99e000},
+ {0xbe9a0000}, {0xbe9a2000}, {0xbe9a4000}, {0xbe9a6000},
+ {0xbe9a8000}, {0xbe9aa000}, {0xbe9ac000}, {0xbe9ae000},
+ {0xbe9b0000}, {0xbe9b2000}, {0xbe9b4000}, {0xbe9b6000},
+ {0xbe9b8000}, {0xbe9ba000}, {0xbe9bc000}, {0xbe9be000},
+ {0xbe9c0000}, {0xbe9c2000}, {0xbe9c4000}, {0xbe9c6000},
+ {0xbe9c8000}, {0xbe9ca000}, {0xbe9cc000}, {0xbe9ce000},
+ {0xbe9d0000}, {0xbe9d2000}, {0xbe9d4000}, {0xbe9d6000},
+ {0xbe9d8000}, {0xbe9da000}, {0xbe9dc000}, {0xbe9de000},
+ {0xbe9e0000}, {0xbe9e2000}, {0xbe9e4000}, {0xbe9e6000},
+ {0xbe9e8000}, {0xbe9ea000}, {0xbe9ec000}, {0xbe9ee000},
+ {0xbe9f0000}, {0xbe9f2000}, {0xbe9f4000}, {0xbe9f6000},
+ {0xbe9f8000}, {0xbe9fa000}, {0xbe9fc000}, {0xbe9fe000},
+ {0xbea00000}, {0xbea02000}, {0xbea04000}, {0xbea06000},
+ {0xbea08000}, {0xbea0a000}, {0xbea0c000}, {0xbea0e000},
+ {0xbea10000}, {0xbea12000}, {0xbea14000}, {0xbea16000},
+ {0xbea18000}, {0xbea1a000}, {0xbea1c000}, {0xbea1e000},
+ {0xbea20000}, {0xbea22000}, {0xbea24000}, {0xbea26000},
+ {0xbea28000}, {0xbea2a000}, {0xbea2c000}, {0xbea2e000},
+ {0xbea30000}, {0xbea32000}, {0xbea34000}, {0xbea36000},
+ {0xbea38000}, {0xbea3a000}, {0xbea3c000}, {0xbea3e000},
+ {0xbea40000}, {0xbea42000}, {0xbea44000}, {0xbea46000},
+ {0xbea48000}, {0xbea4a000}, {0xbea4c000}, {0xbea4e000},
+ {0xbea50000}, {0xbea52000}, {0xbea54000}, {0xbea56000},
+ {0xbea58000}, {0xbea5a000}, {0xbea5c000}, {0xbea5e000},
+ {0xbea60000}, {0xbea62000}, {0xbea64000}, {0xbea66000},
+ {0xbea68000}, {0xbea6a000}, {0xbea6c000}, {0xbea6e000},
+ {0xbea70000}, {0xbea72000}, {0xbea74000}, {0xbea76000},
+ {0xbea78000}, {0xbea7a000}, {0xbea7c000}, {0xbea7e000},
+ {0xbea80000}, {0xbea82000}, {0xbea84000}, {0xbea86000},
+ {0xbea88000}, {0xbea8a000}, {0xbea8c000}, {0xbea8e000},
+ {0xbea90000}, {0xbea92000}, {0xbea94000}, {0xbea96000},
+ {0xbea98000}, {0xbea9a000}, {0xbea9c000}, {0xbea9e000},
+ {0xbeaa0000}, {0xbeaa2000}, {0xbeaa4000}, {0xbeaa6000},
+ {0xbeaa8000}, {0xbeaaa000}, {0xbeaac000}, {0xbeaae000},
+ {0xbeab0000}, {0xbeab2000}, {0xbeab4000}, {0xbeab6000},
+ {0xbeab8000}, {0xbeaba000}, {0xbeabc000}, {0xbeabe000},
+ {0xbeac0000}, {0xbeac2000}, {0xbeac4000}, {0xbeac6000},
+ {0xbeac8000}, {0xbeaca000}, {0xbeacc000}, {0xbeace000},
+ {0xbead0000}, {0xbead2000}, {0xbead4000}, {0xbead6000},
+ {0xbead8000}, {0xbeada000}, {0xbeadc000}, {0xbeade000},
+ {0xbeae0000}, {0xbeae2000}, {0xbeae4000}, {0xbeae6000},
+ {0xbeae8000}, {0xbeaea000}, {0xbeaec000}, {0xbeaee000},
+ {0xbeaf0000}, {0xbeaf2000}, {0xbeaf4000}, {0xbeaf6000},
+ {0xbeaf8000}, {0xbeafa000}, {0xbeafc000}, {0xbeafe000},
+ {0xbeb00000}, {0xbeb02000}, {0xbeb04000}, {0xbeb06000},
+ {0xbeb08000}, {0xbeb0a000}, {0xbeb0c000}, {0xbeb0e000},
+ {0xbeb10000}, {0xbeb12000}, {0xbeb14000}, {0xbeb16000},
+ {0xbeb18000}, {0xbeb1a000}, {0xbeb1c000}, {0xbeb1e000},
+ {0xbeb20000}, {0xbeb22000}, {0xbeb24000}, {0xbeb26000},
+ {0xbeb28000}, {0xbeb2a000}, {0xbeb2c000}, {0xbeb2e000},
+ {0xbeb30000}, {0xbeb32000}, {0xbeb34000}, {0xbeb36000},
+ {0xbeb38000}, {0xbeb3a000}, {0xbeb3c000}, {0xbeb3e000},
+ {0xbeb40000}, {0xbeb42000}, {0xbeb44000}, {0xbeb46000},
+ {0xbeb48000}, {0xbeb4a000}, {0xbeb4c000}, {0xbeb4e000},
+ {0xbeb50000}, {0xbeb52000}, {0xbeb54000}, {0xbeb56000},
+ {0xbeb58000}, {0xbeb5a000}, {0xbeb5c000}, {0xbeb5e000},
+ {0xbeb60000}, {0xbeb62000}, {0xbeb64000}, {0xbeb66000},
+ {0xbeb68000}, {0xbeb6a000}, {0xbeb6c000}, {0xbeb6e000},
+ {0xbeb70000}, {0xbeb72000}, {0xbeb74000}, {0xbeb76000},
+ {0xbeb78000}, {0xbeb7a000}, {0xbeb7c000}, {0xbeb7e000},
+ {0xbeb80000}, {0xbeb82000}, {0xbeb84000}, {0xbeb86000},
+ {0xbeb88000}, {0xbeb8a000}, {0xbeb8c000}, {0xbeb8e000},
+ {0xbeb90000}, {0xbeb92000}, {0xbeb94000}, {0xbeb96000},
+ {0xbeb98000}, {0xbeb9a000}, {0xbeb9c000}, {0xbeb9e000},
+ {0xbeba0000}, {0xbeba2000}, {0xbeba4000}, {0xbeba6000},
+ {0xbeba8000}, {0xbebaa000}, {0xbebac000}, {0xbebae000},
+ {0xbebb0000}, {0xbebb2000}, {0xbebb4000}, {0xbebb6000},
+ {0xbebb8000}, {0xbebba000}, {0xbebbc000}, {0xbebbe000},
+ {0xbebc0000}, {0xbebc2000}, {0xbebc4000}, {0xbebc6000},
+ {0xbebc8000}, {0xbebca000}, {0xbebcc000}, {0xbebce000},
+ {0xbebd0000}, {0xbebd2000}, {0xbebd4000}, {0xbebd6000},
+ {0xbebd8000}, {0xbebda000}, {0xbebdc000}, {0xbebde000},
+ {0xbebe0000}, {0xbebe2000}, {0xbebe4000}, {0xbebe6000},
+ {0xbebe8000}, {0xbebea000}, {0xbebec000}, {0xbebee000},
+ {0xbebf0000}, {0xbebf2000}, {0xbebf4000}, {0xbebf6000},
+ {0xbebf8000}, {0xbebfa000}, {0xbebfc000}, {0xbebfe000},
+ {0xbec00000}, {0xbec02000}, {0xbec04000}, {0xbec06000},
+ {0xbec08000}, {0xbec0a000}, {0xbec0c000}, {0xbec0e000},
+ {0xbec10000}, {0xbec12000}, {0xbec14000}, {0xbec16000},
+ {0xbec18000}, {0xbec1a000}, {0xbec1c000}, {0xbec1e000},
+ {0xbec20000}, {0xbec22000}, {0xbec24000}, {0xbec26000},
+ {0xbec28000}, {0xbec2a000}, {0xbec2c000}, {0xbec2e000},
+ {0xbec30000}, {0xbec32000}, {0xbec34000}, {0xbec36000},
+ {0xbec38000}, {0xbec3a000}, {0xbec3c000}, {0xbec3e000},
+ {0xbec40000}, {0xbec42000}, {0xbec44000}, {0xbec46000},
+ {0xbec48000}, {0xbec4a000}, {0xbec4c000}, {0xbec4e000},
+ {0xbec50000}, {0xbec52000}, {0xbec54000}, {0xbec56000},
+ {0xbec58000}, {0xbec5a000}, {0xbec5c000}, {0xbec5e000},
+ {0xbec60000}, {0xbec62000}, {0xbec64000}, {0xbec66000},
+ {0xbec68000}, {0xbec6a000}, {0xbec6c000}, {0xbec6e000},
+ {0xbec70000}, {0xbec72000}, {0xbec74000}, {0xbec76000},
+ {0xbec78000}, {0xbec7a000}, {0xbec7c000}, {0xbec7e000},
+ {0xbec80000}, {0xbec82000}, {0xbec84000}, {0xbec86000},
+ {0xbec88000}, {0xbec8a000}, {0xbec8c000}, {0xbec8e000},
+ {0xbec90000}, {0xbec92000}, {0xbec94000}, {0xbec96000},
+ {0xbec98000}, {0xbec9a000}, {0xbec9c000}, {0xbec9e000},
+ {0xbeca0000}, {0xbeca2000}, {0xbeca4000}, {0xbeca6000},
+ {0xbeca8000}, {0xbecaa000}, {0xbecac000}, {0xbecae000},
+ {0xbecb0000}, {0xbecb2000}, {0xbecb4000}, {0xbecb6000},
+ {0xbecb8000}, {0xbecba000}, {0xbecbc000}, {0xbecbe000},
+ {0xbecc0000}, {0xbecc2000}, {0xbecc4000}, {0xbecc6000},
+ {0xbecc8000}, {0xbecca000}, {0xbeccc000}, {0xbecce000},
+ {0xbecd0000}, {0xbecd2000}, {0xbecd4000}, {0xbecd6000},
+ {0xbecd8000}, {0xbecda000}, {0xbecdc000}, {0xbecde000},
+ {0xbece0000}, {0xbece2000}, {0xbece4000}, {0xbece6000},
+ {0xbece8000}, {0xbecea000}, {0xbecec000}, {0xbecee000},
+ {0xbecf0000}, {0xbecf2000}, {0xbecf4000}, {0xbecf6000},
+ {0xbecf8000}, {0xbecfa000}, {0xbecfc000}, {0xbecfe000},
+ {0xbed00000}, {0xbed02000}, {0xbed04000}, {0xbed06000},
+ {0xbed08000}, {0xbed0a000}, {0xbed0c000}, {0xbed0e000},
+ {0xbed10000}, {0xbed12000}, {0xbed14000}, {0xbed16000},
+ {0xbed18000}, {0xbed1a000}, {0xbed1c000}, {0xbed1e000},
+ {0xbed20000}, {0xbed22000}, {0xbed24000}, {0xbed26000},
+ {0xbed28000}, {0xbed2a000}, {0xbed2c000}, {0xbed2e000},
+ {0xbed30000}, {0xbed32000}, {0xbed34000}, {0xbed36000},
+ {0xbed38000}, {0xbed3a000}, {0xbed3c000}, {0xbed3e000},
+ {0xbed40000}, {0xbed42000}, {0xbed44000}, {0xbed46000},
+ {0xbed48000}, {0xbed4a000}, {0xbed4c000}, {0xbed4e000},
+ {0xbed50000}, {0xbed52000}, {0xbed54000}, {0xbed56000},
+ {0xbed58000}, {0xbed5a000}, {0xbed5c000}, {0xbed5e000},
+ {0xbed60000}, {0xbed62000}, {0xbed64000}, {0xbed66000},
+ {0xbed68000}, {0xbed6a000}, {0xbed6c000}, {0xbed6e000},
+ {0xbed70000}, {0xbed72000}, {0xbed74000}, {0xbed76000},
+ {0xbed78000}, {0xbed7a000}, {0xbed7c000}, {0xbed7e000},
+ {0xbed80000}, {0xbed82000}, {0xbed84000}, {0xbed86000},
+ {0xbed88000}, {0xbed8a000}, {0xbed8c000}, {0xbed8e000},
+ {0xbed90000}, {0xbed92000}, {0xbed94000}, {0xbed96000},
+ {0xbed98000}, {0xbed9a000}, {0xbed9c000}, {0xbed9e000},
+ {0xbeda0000}, {0xbeda2000}, {0xbeda4000}, {0xbeda6000},
+ {0xbeda8000}, {0xbedaa000}, {0xbedac000}, {0xbedae000},
+ {0xbedb0000}, {0xbedb2000}, {0xbedb4000}, {0xbedb6000},
+ {0xbedb8000}, {0xbedba000}, {0xbedbc000}, {0xbedbe000},
+ {0xbedc0000}, {0xbedc2000}, {0xbedc4000}, {0xbedc6000},
+ {0xbedc8000}, {0xbedca000}, {0xbedcc000}, {0xbedce000},
+ {0xbedd0000}, {0xbedd2000}, {0xbedd4000}, {0xbedd6000},
+ {0xbedd8000}, {0xbedda000}, {0xbeddc000}, {0xbedde000},
+ {0xbede0000}, {0xbede2000}, {0xbede4000}, {0xbede6000},
+ {0xbede8000}, {0xbedea000}, {0xbedec000}, {0xbedee000},
+ {0xbedf0000}, {0xbedf2000}, {0xbedf4000}, {0xbedf6000},
+ {0xbedf8000}, {0xbedfa000}, {0xbedfc000}, {0xbedfe000},
+ {0xbee00000}, {0xbee02000}, {0xbee04000}, {0xbee06000},
+ {0xbee08000}, {0xbee0a000}, {0xbee0c000}, {0xbee0e000},
+ {0xbee10000}, {0xbee12000}, {0xbee14000}, {0xbee16000},
+ {0xbee18000}, {0xbee1a000}, {0xbee1c000}, {0xbee1e000},
+ {0xbee20000}, {0xbee22000}, {0xbee24000}, {0xbee26000},
+ {0xbee28000}, {0xbee2a000}, {0xbee2c000}, {0xbee2e000},
+ {0xbee30000}, {0xbee32000}, {0xbee34000}, {0xbee36000},
+ {0xbee38000}, {0xbee3a000}, {0xbee3c000}, {0xbee3e000},
+ {0xbee40000}, {0xbee42000}, {0xbee44000}, {0xbee46000},
+ {0xbee48000}, {0xbee4a000}, {0xbee4c000}, {0xbee4e000},
+ {0xbee50000}, {0xbee52000}, {0xbee54000}, {0xbee56000},
+ {0xbee58000}, {0xbee5a000}, {0xbee5c000}, {0xbee5e000},
+ {0xbee60000}, {0xbee62000}, {0xbee64000}, {0xbee66000},
+ {0xbee68000}, {0xbee6a000}, {0xbee6c000}, {0xbee6e000},
+ {0xbee70000}, {0xbee72000}, {0xbee74000}, {0xbee76000},
+ {0xbee78000}, {0xbee7a000}, {0xbee7c000}, {0xbee7e000},
+ {0xbee80000}, {0xbee82000}, {0xbee84000}, {0xbee86000},
+ {0xbee88000}, {0xbee8a000}, {0xbee8c000}, {0xbee8e000},
+ {0xbee90000}, {0xbee92000}, {0xbee94000}, {0xbee96000},
+ {0xbee98000}, {0xbee9a000}, {0xbee9c000}, {0xbee9e000},
+ {0xbeea0000}, {0xbeea2000}, {0xbeea4000}, {0xbeea6000},
+ {0xbeea8000}, {0xbeeaa000}, {0xbeeac000}, {0xbeeae000},
+ {0xbeeb0000}, {0xbeeb2000}, {0xbeeb4000}, {0xbeeb6000},
+ {0xbeeb8000}, {0xbeeba000}, {0xbeebc000}, {0xbeebe000},
+ {0xbeec0000}, {0xbeec2000}, {0xbeec4000}, {0xbeec6000},
+ {0xbeec8000}, {0xbeeca000}, {0xbeecc000}, {0xbeece000},
+ {0xbeed0000}, {0xbeed2000}, {0xbeed4000}, {0xbeed6000},
+ {0xbeed8000}, {0xbeeda000}, {0xbeedc000}, {0xbeede000},
+ {0xbeee0000}, {0xbeee2000}, {0xbeee4000}, {0xbeee6000},
+ {0xbeee8000}, {0xbeeea000}, {0xbeeec000}, {0xbeeee000},
+ {0xbeef0000}, {0xbeef2000}, {0xbeef4000}, {0xbeef6000},
+ {0xbeef8000}, {0xbeefa000}, {0xbeefc000}, {0xbeefe000},
+ {0xbef00000}, {0xbef02000}, {0xbef04000}, {0xbef06000},
+ {0xbef08000}, {0xbef0a000}, {0xbef0c000}, {0xbef0e000},
+ {0xbef10000}, {0xbef12000}, {0xbef14000}, {0xbef16000},
+ {0xbef18000}, {0xbef1a000}, {0xbef1c000}, {0xbef1e000},
+ {0xbef20000}, {0xbef22000}, {0xbef24000}, {0xbef26000},
+ {0xbef28000}, {0xbef2a000}, {0xbef2c000}, {0xbef2e000},
+ {0xbef30000}, {0xbef32000}, {0xbef34000}, {0xbef36000},
+ {0xbef38000}, {0xbef3a000}, {0xbef3c000}, {0xbef3e000},
+ {0xbef40000}, {0xbef42000}, {0xbef44000}, {0xbef46000},
+ {0xbef48000}, {0xbef4a000}, {0xbef4c000}, {0xbef4e000},
+ {0xbef50000}, {0xbef52000}, {0xbef54000}, {0xbef56000},
+ {0xbef58000}, {0xbef5a000}, {0xbef5c000}, {0xbef5e000},
+ {0xbef60000}, {0xbef62000}, {0xbef64000}, {0xbef66000},
+ {0xbef68000}, {0xbef6a000}, {0xbef6c000}, {0xbef6e000},
+ {0xbef70000}, {0xbef72000}, {0xbef74000}, {0xbef76000},
+ {0xbef78000}, {0xbef7a000}, {0xbef7c000}, {0xbef7e000},
+ {0xbef80000}, {0xbef82000}, {0xbef84000}, {0xbef86000},
+ {0xbef88000}, {0xbef8a000}, {0xbef8c000}, {0xbef8e000},
+ {0xbef90000}, {0xbef92000}, {0xbef94000}, {0xbef96000},
+ {0xbef98000}, {0xbef9a000}, {0xbef9c000}, {0xbef9e000},
+ {0xbefa0000}, {0xbefa2000}, {0xbefa4000}, {0xbefa6000},
+ {0xbefa8000}, {0xbefaa000}, {0xbefac000}, {0xbefae000},
+ {0xbefb0000}, {0xbefb2000}, {0xbefb4000}, {0xbefb6000},
+ {0xbefb8000}, {0xbefba000}, {0xbefbc000}, {0xbefbe000},
+ {0xbefc0000}, {0xbefc2000}, {0xbefc4000}, {0xbefc6000},
+ {0xbefc8000}, {0xbefca000}, {0xbefcc000}, {0xbefce000},
+ {0xbefd0000}, {0xbefd2000}, {0xbefd4000}, {0xbefd6000},
+ {0xbefd8000}, {0xbefda000}, {0xbefdc000}, {0xbefde000},
+ {0xbefe0000}, {0xbefe2000}, {0xbefe4000}, {0xbefe6000},
+ {0xbefe8000}, {0xbefea000}, {0xbefec000}, {0xbefee000},
+ {0xbeff0000}, {0xbeff2000}, {0xbeff4000}, {0xbeff6000},
+ {0xbeff8000}, {0xbeffa000}, {0xbeffc000}, {0xbeffe000},
+ {0xbf000000}, {0xbf002000}, {0xbf004000}, {0xbf006000},
+ {0xbf008000}, {0xbf00a000}, {0xbf00c000}, {0xbf00e000},
+ {0xbf010000}, {0xbf012000}, {0xbf014000}, {0xbf016000},
+ {0xbf018000}, {0xbf01a000}, {0xbf01c000}, {0xbf01e000},
+ {0xbf020000}, {0xbf022000}, {0xbf024000}, {0xbf026000},
+ {0xbf028000}, {0xbf02a000}, {0xbf02c000}, {0xbf02e000},
+ {0xbf030000}, {0xbf032000}, {0xbf034000}, {0xbf036000},
+ {0xbf038000}, {0xbf03a000}, {0xbf03c000}, {0xbf03e000},
+ {0xbf040000}, {0xbf042000}, {0xbf044000}, {0xbf046000},
+ {0xbf048000}, {0xbf04a000}, {0xbf04c000}, {0xbf04e000},
+ {0xbf050000}, {0xbf052000}, {0xbf054000}, {0xbf056000},
+ {0xbf058000}, {0xbf05a000}, {0xbf05c000}, {0xbf05e000},
+ {0xbf060000}, {0xbf062000}, {0xbf064000}, {0xbf066000},
+ {0xbf068000}, {0xbf06a000}, {0xbf06c000}, {0xbf06e000},
+ {0xbf070000}, {0xbf072000}, {0xbf074000}, {0xbf076000},
+ {0xbf078000}, {0xbf07a000}, {0xbf07c000}, {0xbf07e000},
+ {0xbf080000}, {0xbf082000}, {0xbf084000}, {0xbf086000},
+ {0xbf088000}, {0xbf08a000}, {0xbf08c000}, {0xbf08e000},
+ {0xbf090000}, {0xbf092000}, {0xbf094000}, {0xbf096000},
+ {0xbf098000}, {0xbf09a000}, {0xbf09c000}, {0xbf09e000},
+ {0xbf0a0000}, {0xbf0a2000}, {0xbf0a4000}, {0xbf0a6000},
+ {0xbf0a8000}, {0xbf0aa000}, {0xbf0ac000}, {0xbf0ae000},
+ {0xbf0b0000}, {0xbf0b2000}, {0xbf0b4000}, {0xbf0b6000},
+ {0xbf0b8000}, {0xbf0ba000}, {0xbf0bc000}, {0xbf0be000},
+ {0xbf0c0000}, {0xbf0c2000}, {0xbf0c4000}, {0xbf0c6000},
+ {0xbf0c8000}, {0xbf0ca000}, {0xbf0cc000}, {0xbf0ce000},
+ {0xbf0d0000}, {0xbf0d2000}, {0xbf0d4000}, {0xbf0d6000},
+ {0xbf0d8000}, {0xbf0da000}, {0xbf0dc000}, {0xbf0de000},
+ {0xbf0e0000}, {0xbf0e2000}, {0xbf0e4000}, {0xbf0e6000},
+ {0xbf0e8000}, {0xbf0ea000}, {0xbf0ec000}, {0xbf0ee000},
+ {0xbf0f0000}, {0xbf0f2000}, {0xbf0f4000}, {0xbf0f6000},
+ {0xbf0f8000}, {0xbf0fa000}, {0xbf0fc000}, {0xbf0fe000},
+ {0xbf100000}, {0xbf102000}, {0xbf104000}, {0xbf106000},
+ {0xbf108000}, {0xbf10a000}, {0xbf10c000}, {0xbf10e000},
+ {0xbf110000}, {0xbf112000}, {0xbf114000}, {0xbf116000},
+ {0xbf118000}, {0xbf11a000}, {0xbf11c000}, {0xbf11e000},
+ {0xbf120000}, {0xbf122000}, {0xbf124000}, {0xbf126000},
+ {0xbf128000}, {0xbf12a000}, {0xbf12c000}, {0xbf12e000},
+ {0xbf130000}, {0xbf132000}, {0xbf134000}, {0xbf136000},
+ {0xbf138000}, {0xbf13a000}, {0xbf13c000}, {0xbf13e000},
+ {0xbf140000}, {0xbf142000}, {0xbf144000}, {0xbf146000},
+ {0xbf148000}, {0xbf14a000}, {0xbf14c000}, {0xbf14e000},
+ {0xbf150000}, {0xbf152000}, {0xbf154000}, {0xbf156000},
+ {0xbf158000}, {0xbf15a000}, {0xbf15c000}, {0xbf15e000},
+ {0xbf160000}, {0xbf162000}, {0xbf164000}, {0xbf166000},
+ {0xbf168000}, {0xbf16a000}, {0xbf16c000}, {0xbf16e000},
+ {0xbf170000}, {0xbf172000}, {0xbf174000}, {0xbf176000},
+ {0xbf178000}, {0xbf17a000}, {0xbf17c000}, {0xbf17e000},
+ {0xbf180000}, {0xbf182000}, {0xbf184000}, {0xbf186000},
+ {0xbf188000}, {0xbf18a000}, {0xbf18c000}, {0xbf18e000},
+ {0xbf190000}, {0xbf192000}, {0xbf194000}, {0xbf196000},
+ {0xbf198000}, {0xbf19a000}, {0xbf19c000}, {0xbf19e000},
+ {0xbf1a0000}, {0xbf1a2000}, {0xbf1a4000}, {0xbf1a6000},
+ {0xbf1a8000}, {0xbf1aa000}, {0xbf1ac000}, {0xbf1ae000},
+ {0xbf1b0000}, {0xbf1b2000}, {0xbf1b4000}, {0xbf1b6000},
+ {0xbf1b8000}, {0xbf1ba000}, {0xbf1bc000}, {0xbf1be000},
+ {0xbf1c0000}, {0xbf1c2000}, {0xbf1c4000}, {0xbf1c6000},
+ {0xbf1c8000}, {0xbf1ca000}, {0xbf1cc000}, {0xbf1ce000},
+ {0xbf1d0000}, {0xbf1d2000}, {0xbf1d4000}, {0xbf1d6000},
+ {0xbf1d8000}, {0xbf1da000}, {0xbf1dc000}, {0xbf1de000},
+ {0xbf1e0000}, {0xbf1e2000}, {0xbf1e4000}, {0xbf1e6000},
+ {0xbf1e8000}, {0xbf1ea000}, {0xbf1ec000}, {0xbf1ee000},
+ {0xbf1f0000}, {0xbf1f2000}, {0xbf1f4000}, {0xbf1f6000},
+ {0xbf1f8000}, {0xbf1fa000}, {0xbf1fc000}, {0xbf1fe000},
+ {0xbf200000}, {0xbf202000}, {0xbf204000}, {0xbf206000},
+ {0xbf208000}, {0xbf20a000}, {0xbf20c000}, {0xbf20e000},
+ {0xbf210000}, {0xbf212000}, {0xbf214000}, {0xbf216000},
+ {0xbf218000}, {0xbf21a000}, {0xbf21c000}, {0xbf21e000},
+ {0xbf220000}, {0xbf222000}, {0xbf224000}, {0xbf226000},
+ {0xbf228000}, {0xbf22a000}, {0xbf22c000}, {0xbf22e000},
+ {0xbf230000}, {0xbf232000}, {0xbf234000}, {0xbf236000},
+ {0xbf238000}, {0xbf23a000}, {0xbf23c000}, {0xbf23e000},
+ {0xbf240000}, {0xbf242000}, {0xbf244000}, {0xbf246000},
+ {0xbf248000}, {0xbf24a000}, {0xbf24c000}, {0xbf24e000},
+ {0xbf250000}, {0xbf252000}, {0xbf254000}, {0xbf256000},
+ {0xbf258000}, {0xbf25a000}, {0xbf25c000}, {0xbf25e000},
+ {0xbf260000}, {0xbf262000}, {0xbf264000}, {0xbf266000},
+ {0xbf268000}, {0xbf26a000}, {0xbf26c000}, {0xbf26e000},
+ {0xbf270000}, {0xbf272000}, {0xbf274000}, {0xbf276000},
+ {0xbf278000}, {0xbf27a000}, {0xbf27c000}, {0xbf27e000},
+ {0xbf280000}, {0xbf282000}, {0xbf284000}, {0xbf286000},
+ {0xbf288000}, {0xbf28a000}, {0xbf28c000}, {0xbf28e000},
+ {0xbf290000}, {0xbf292000}, {0xbf294000}, {0xbf296000},
+ {0xbf298000}, {0xbf29a000}, {0xbf29c000}, {0xbf29e000},
+ {0xbf2a0000}, {0xbf2a2000}, {0xbf2a4000}, {0xbf2a6000},
+ {0xbf2a8000}, {0xbf2aa000}, {0xbf2ac000}, {0xbf2ae000},
+ {0xbf2b0000}, {0xbf2b2000}, {0xbf2b4000}, {0xbf2b6000},
+ {0xbf2b8000}, {0xbf2ba000}, {0xbf2bc000}, {0xbf2be000},
+ {0xbf2c0000}, {0xbf2c2000}, {0xbf2c4000}, {0xbf2c6000},
+ {0xbf2c8000}, {0xbf2ca000}, {0xbf2cc000}, {0xbf2ce000},
+ {0xbf2d0000}, {0xbf2d2000}, {0xbf2d4000}, {0xbf2d6000},
+ {0xbf2d8000}, {0xbf2da000}, {0xbf2dc000}, {0xbf2de000},
+ {0xbf2e0000}, {0xbf2e2000}, {0xbf2e4000}, {0xbf2e6000},
+ {0xbf2e8000}, {0xbf2ea000}, {0xbf2ec000}, {0xbf2ee000},
+ {0xbf2f0000}, {0xbf2f2000}, {0xbf2f4000}, {0xbf2f6000},
+ {0xbf2f8000}, {0xbf2fa000}, {0xbf2fc000}, {0xbf2fe000},
+ {0xbf300000}, {0xbf302000}, {0xbf304000}, {0xbf306000},
+ {0xbf308000}, {0xbf30a000}, {0xbf30c000}, {0xbf30e000},
+ {0xbf310000}, {0xbf312000}, {0xbf314000}, {0xbf316000},
+ {0xbf318000}, {0xbf31a000}, {0xbf31c000}, {0xbf31e000},
+ {0xbf320000}, {0xbf322000}, {0xbf324000}, {0xbf326000},
+ {0xbf328000}, {0xbf32a000}, {0xbf32c000}, {0xbf32e000},
+ {0xbf330000}, {0xbf332000}, {0xbf334000}, {0xbf336000},
+ {0xbf338000}, {0xbf33a000}, {0xbf33c000}, {0xbf33e000},
+ {0xbf340000}, {0xbf342000}, {0xbf344000}, {0xbf346000},
+ {0xbf348000}, {0xbf34a000}, {0xbf34c000}, {0xbf34e000},
+ {0xbf350000}, {0xbf352000}, {0xbf354000}, {0xbf356000},
+ {0xbf358000}, {0xbf35a000}, {0xbf35c000}, {0xbf35e000},
+ {0xbf360000}, {0xbf362000}, {0xbf364000}, {0xbf366000},
+ {0xbf368000}, {0xbf36a000}, {0xbf36c000}, {0xbf36e000},
+ {0xbf370000}, {0xbf372000}, {0xbf374000}, {0xbf376000},
+ {0xbf378000}, {0xbf37a000}, {0xbf37c000}, {0xbf37e000},
+ {0xbf380000}, {0xbf382000}, {0xbf384000}, {0xbf386000},
+ {0xbf388000}, {0xbf38a000}, {0xbf38c000}, {0xbf38e000},
+ {0xbf390000}, {0xbf392000}, {0xbf394000}, {0xbf396000},
+ {0xbf398000}, {0xbf39a000}, {0xbf39c000}, {0xbf39e000},
+ {0xbf3a0000}, {0xbf3a2000}, {0xbf3a4000}, {0xbf3a6000},
+ {0xbf3a8000}, {0xbf3aa000}, {0xbf3ac000}, {0xbf3ae000},
+ {0xbf3b0000}, {0xbf3b2000}, {0xbf3b4000}, {0xbf3b6000},
+ {0xbf3b8000}, {0xbf3ba000}, {0xbf3bc000}, {0xbf3be000},
+ {0xbf3c0000}, {0xbf3c2000}, {0xbf3c4000}, {0xbf3c6000},
+ {0xbf3c8000}, {0xbf3ca000}, {0xbf3cc000}, {0xbf3ce000},
+ {0xbf3d0000}, {0xbf3d2000}, {0xbf3d4000}, {0xbf3d6000},
+ {0xbf3d8000}, {0xbf3da000}, {0xbf3dc000}, {0xbf3de000},
+ {0xbf3e0000}, {0xbf3e2000}, {0xbf3e4000}, {0xbf3e6000},
+ {0xbf3e8000}, {0xbf3ea000}, {0xbf3ec000}, {0xbf3ee000},
+ {0xbf3f0000}, {0xbf3f2000}, {0xbf3f4000}, {0xbf3f6000},
+ {0xbf3f8000}, {0xbf3fa000}, {0xbf3fc000}, {0xbf3fe000},
+ {0xbf400000}, {0xbf402000}, {0xbf404000}, {0xbf406000},
+ {0xbf408000}, {0xbf40a000}, {0xbf40c000}, {0xbf40e000},
+ {0xbf410000}, {0xbf412000}, {0xbf414000}, {0xbf416000},
+ {0xbf418000}, {0xbf41a000}, {0xbf41c000}, {0xbf41e000},
+ {0xbf420000}, {0xbf422000}, {0xbf424000}, {0xbf426000},
+ {0xbf428000}, {0xbf42a000}, {0xbf42c000}, {0xbf42e000},
+ {0xbf430000}, {0xbf432000}, {0xbf434000}, {0xbf436000},
+ {0xbf438000}, {0xbf43a000}, {0xbf43c000}, {0xbf43e000},
+ {0xbf440000}, {0xbf442000}, {0xbf444000}, {0xbf446000},
+ {0xbf448000}, {0xbf44a000}, {0xbf44c000}, {0xbf44e000},
+ {0xbf450000}, {0xbf452000}, {0xbf454000}, {0xbf456000},
+ {0xbf458000}, {0xbf45a000}, {0xbf45c000}, {0xbf45e000},
+ {0xbf460000}, {0xbf462000}, {0xbf464000}, {0xbf466000},
+ {0xbf468000}, {0xbf46a000}, {0xbf46c000}, {0xbf46e000},
+ {0xbf470000}, {0xbf472000}, {0xbf474000}, {0xbf476000},
+ {0xbf478000}, {0xbf47a000}, {0xbf47c000}, {0xbf47e000},
+ {0xbf480000}, {0xbf482000}, {0xbf484000}, {0xbf486000},
+ {0xbf488000}, {0xbf48a000}, {0xbf48c000}, {0xbf48e000},
+ {0xbf490000}, {0xbf492000}, {0xbf494000}, {0xbf496000},
+ {0xbf498000}, {0xbf49a000}, {0xbf49c000}, {0xbf49e000},
+ {0xbf4a0000}, {0xbf4a2000}, {0xbf4a4000}, {0xbf4a6000},
+ {0xbf4a8000}, {0xbf4aa000}, {0xbf4ac000}, {0xbf4ae000},
+ {0xbf4b0000}, {0xbf4b2000}, {0xbf4b4000}, {0xbf4b6000},
+ {0xbf4b8000}, {0xbf4ba000}, {0xbf4bc000}, {0xbf4be000},
+ {0xbf4c0000}, {0xbf4c2000}, {0xbf4c4000}, {0xbf4c6000},
+ {0xbf4c8000}, {0xbf4ca000}, {0xbf4cc000}, {0xbf4ce000},
+ {0xbf4d0000}, {0xbf4d2000}, {0xbf4d4000}, {0xbf4d6000},
+ {0xbf4d8000}, {0xbf4da000}, {0xbf4dc000}, {0xbf4de000},
+ {0xbf4e0000}, {0xbf4e2000}, {0xbf4e4000}, {0xbf4e6000},
+ {0xbf4e8000}, {0xbf4ea000}, {0xbf4ec000}, {0xbf4ee000},
+ {0xbf4f0000}, {0xbf4f2000}, {0xbf4f4000}, {0xbf4f6000},
+ {0xbf4f8000}, {0xbf4fa000}, {0xbf4fc000}, {0xbf4fe000},
+ {0xbf500000}, {0xbf502000}, {0xbf504000}, {0xbf506000},
+ {0xbf508000}, {0xbf50a000}, {0xbf50c000}, {0xbf50e000},
+ {0xbf510000}, {0xbf512000}, {0xbf514000}, {0xbf516000},
+ {0xbf518000}, {0xbf51a000}, {0xbf51c000}, {0xbf51e000},
+ {0xbf520000}, {0xbf522000}, {0xbf524000}, {0xbf526000},
+ {0xbf528000}, {0xbf52a000}, {0xbf52c000}, {0xbf52e000},
+ {0xbf530000}, {0xbf532000}, {0xbf534000}, {0xbf536000},
+ {0xbf538000}, {0xbf53a000}, {0xbf53c000}, {0xbf53e000},
+ {0xbf540000}, {0xbf542000}, {0xbf544000}, {0xbf546000},
+ {0xbf548000}, {0xbf54a000}, {0xbf54c000}, {0xbf54e000},
+ {0xbf550000}, {0xbf552000}, {0xbf554000}, {0xbf556000},
+ {0xbf558000}, {0xbf55a000}, {0xbf55c000}, {0xbf55e000},
+ {0xbf560000}, {0xbf562000}, {0xbf564000}, {0xbf566000},
+ {0xbf568000}, {0xbf56a000}, {0xbf56c000}, {0xbf56e000},
+ {0xbf570000}, {0xbf572000}, {0xbf574000}, {0xbf576000},
+ {0xbf578000}, {0xbf57a000}, {0xbf57c000}, {0xbf57e000},
+ {0xbf580000}, {0xbf582000}, {0xbf584000}, {0xbf586000},
+ {0xbf588000}, {0xbf58a000}, {0xbf58c000}, {0xbf58e000},
+ {0xbf590000}, {0xbf592000}, {0xbf594000}, {0xbf596000},
+ {0xbf598000}, {0xbf59a000}, {0xbf59c000}, {0xbf59e000},
+ {0xbf5a0000}, {0xbf5a2000}, {0xbf5a4000}, {0xbf5a6000},
+ {0xbf5a8000}, {0xbf5aa000}, {0xbf5ac000}, {0xbf5ae000},
+ {0xbf5b0000}, {0xbf5b2000}, {0xbf5b4000}, {0xbf5b6000},
+ {0xbf5b8000}, {0xbf5ba000}, {0xbf5bc000}, {0xbf5be000},
+ {0xbf5c0000}, {0xbf5c2000}, {0xbf5c4000}, {0xbf5c6000},
+ {0xbf5c8000}, {0xbf5ca000}, {0xbf5cc000}, {0xbf5ce000},
+ {0xbf5d0000}, {0xbf5d2000}, {0xbf5d4000}, {0xbf5d6000},
+ {0xbf5d8000}, {0xbf5da000}, {0xbf5dc000}, {0xbf5de000},
+ {0xbf5e0000}, {0xbf5e2000}, {0xbf5e4000}, {0xbf5e6000},
+ {0xbf5e8000}, {0xbf5ea000}, {0xbf5ec000}, {0xbf5ee000},
+ {0xbf5f0000}, {0xbf5f2000}, {0xbf5f4000}, {0xbf5f6000},
+ {0xbf5f8000}, {0xbf5fa000}, {0xbf5fc000}, {0xbf5fe000},
+ {0xbf600000}, {0xbf602000}, {0xbf604000}, {0xbf606000},
+ {0xbf608000}, {0xbf60a000}, {0xbf60c000}, {0xbf60e000},
+ {0xbf610000}, {0xbf612000}, {0xbf614000}, {0xbf616000},
+ {0xbf618000}, {0xbf61a000}, {0xbf61c000}, {0xbf61e000},
+ {0xbf620000}, {0xbf622000}, {0xbf624000}, {0xbf626000},
+ {0xbf628000}, {0xbf62a000}, {0xbf62c000}, {0xbf62e000},
+ {0xbf630000}, {0xbf632000}, {0xbf634000}, {0xbf636000},
+ {0xbf638000}, {0xbf63a000}, {0xbf63c000}, {0xbf63e000},
+ {0xbf640000}, {0xbf642000}, {0xbf644000}, {0xbf646000},
+ {0xbf648000}, {0xbf64a000}, {0xbf64c000}, {0xbf64e000},
+ {0xbf650000}, {0xbf652000}, {0xbf654000}, {0xbf656000},
+ {0xbf658000}, {0xbf65a000}, {0xbf65c000}, {0xbf65e000},
+ {0xbf660000}, {0xbf662000}, {0xbf664000}, {0xbf666000},
+ {0xbf668000}, {0xbf66a000}, {0xbf66c000}, {0xbf66e000},
+ {0xbf670000}, {0xbf672000}, {0xbf674000}, {0xbf676000},
+ {0xbf678000}, {0xbf67a000}, {0xbf67c000}, {0xbf67e000},
+ {0xbf680000}, {0xbf682000}, {0xbf684000}, {0xbf686000},
+ {0xbf688000}, {0xbf68a000}, {0xbf68c000}, {0xbf68e000},
+ {0xbf690000}, {0xbf692000}, {0xbf694000}, {0xbf696000},
+ {0xbf698000}, {0xbf69a000}, {0xbf69c000}, {0xbf69e000},
+ {0xbf6a0000}, {0xbf6a2000}, {0xbf6a4000}, {0xbf6a6000},
+ {0xbf6a8000}, {0xbf6aa000}, {0xbf6ac000}, {0xbf6ae000},
+ {0xbf6b0000}, {0xbf6b2000}, {0xbf6b4000}, {0xbf6b6000},
+ {0xbf6b8000}, {0xbf6ba000}, {0xbf6bc000}, {0xbf6be000},
+ {0xbf6c0000}, {0xbf6c2000}, {0xbf6c4000}, {0xbf6c6000},
+ {0xbf6c8000}, {0xbf6ca000}, {0xbf6cc000}, {0xbf6ce000},
+ {0xbf6d0000}, {0xbf6d2000}, {0xbf6d4000}, {0xbf6d6000},
+ {0xbf6d8000}, {0xbf6da000}, {0xbf6dc000}, {0xbf6de000},
+ {0xbf6e0000}, {0xbf6e2000}, {0xbf6e4000}, {0xbf6e6000},
+ {0xbf6e8000}, {0xbf6ea000}, {0xbf6ec000}, {0xbf6ee000},
+ {0xbf6f0000}, {0xbf6f2000}, {0xbf6f4000}, {0xbf6f6000},
+ {0xbf6f8000}, {0xbf6fa000}, {0xbf6fc000}, {0xbf6fe000},
+ {0xbf700000}, {0xbf702000}, {0xbf704000}, {0xbf706000},
+ {0xbf708000}, {0xbf70a000}, {0xbf70c000}, {0xbf70e000},
+ {0xbf710000}, {0xbf712000}, {0xbf714000}, {0xbf716000},
+ {0xbf718000}, {0xbf71a000}, {0xbf71c000}, {0xbf71e000},
+ {0xbf720000}, {0xbf722000}, {0xbf724000}, {0xbf726000},
+ {0xbf728000}, {0xbf72a000}, {0xbf72c000}, {0xbf72e000},
+ {0xbf730000}, {0xbf732000}, {0xbf734000}, {0xbf736000},
+ {0xbf738000}, {0xbf73a000}, {0xbf73c000}, {0xbf73e000},
+ {0xbf740000}, {0xbf742000}, {0xbf744000}, {0xbf746000},
+ {0xbf748000}, {0xbf74a000}, {0xbf74c000}, {0xbf74e000},
+ {0xbf750000}, {0xbf752000}, {0xbf754000}, {0xbf756000},
+ {0xbf758000}, {0xbf75a000}, {0xbf75c000}, {0xbf75e000},
+ {0xbf760000}, {0xbf762000}, {0xbf764000}, {0xbf766000},
+ {0xbf768000}, {0xbf76a000}, {0xbf76c000}, {0xbf76e000},
+ {0xbf770000}, {0xbf772000}, {0xbf774000}, {0xbf776000},
+ {0xbf778000}, {0xbf77a000}, {0xbf77c000}, {0xbf77e000},
+ {0xbf780000}, {0xbf782000}, {0xbf784000}, {0xbf786000},
+ {0xbf788000}, {0xbf78a000}, {0xbf78c000}, {0xbf78e000},
+ {0xbf790000}, {0xbf792000}, {0xbf794000}, {0xbf796000},
+ {0xbf798000}, {0xbf79a000}, {0xbf79c000}, {0xbf79e000},
+ {0xbf7a0000}, {0xbf7a2000}, {0xbf7a4000}, {0xbf7a6000},
+ {0xbf7a8000}, {0xbf7aa000}, {0xbf7ac000}, {0xbf7ae000},
+ {0xbf7b0000}, {0xbf7b2000}, {0xbf7b4000}, {0xbf7b6000},
+ {0xbf7b8000}, {0xbf7ba000}, {0xbf7bc000}, {0xbf7be000},
+ {0xbf7c0000}, {0xbf7c2000}, {0xbf7c4000}, {0xbf7c6000},
+ {0xbf7c8000}, {0xbf7ca000}, {0xbf7cc000}, {0xbf7ce000},
+ {0xbf7d0000}, {0xbf7d2000}, {0xbf7d4000}, {0xbf7d6000},
+ {0xbf7d8000}, {0xbf7da000}, {0xbf7dc000}, {0xbf7de000},
+ {0xbf7e0000}, {0xbf7e2000}, {0xbf7e4000}, {0xbf7e6000},
+ {0xbf7e8000}, {0xbf7ea000}, {0xbf7ec000}, {0xbf7ee000},
+ {0xbf7f0000}, {0xbf7f2000}, {0xbf7f4000}, {0xbf7f6000},
+ {0xbf7f8000}, {0xbf7fa000}, {0xbf7fc000}, {0xbf7fe000},
+ {0xbf800000}, {0xbf802000}, {0xbf804000}, {0xbf806000},
+ {0xbf808000}, {0xbf80a000}, {0xbf80c000}, {0xbf80e000},
+ {0xbf810000}, {0xbf812000}, {0xbf814000}, {0xbf816000},
+ {0xbf818000}, {0xbf81a000}, {0xbf81c000}, {0xbf81e000},
+ {0xbf820000}, {0xbf822000}, {0xbf824000}, {0xbf826000},
+ {0xbf828000}, {0xbf82a000}, {0xbf82c000}, {0xbf82e000},
+ {0xbf830000}, {0xbf832000}, {0xbf834000}, {0xbf836000},
+ {0xbf838000}, {0xbf83a000}, {0xbf83c000}, {0xbf83e000},
+ {0xbf840000}, {0xbf842000}, {0xbf844000}, {0xbf846000},
+ {0xbf848000}, {0xbf84a000}, {0xbf84c000}, {0xbf84e000},
+ {0xbf850000}, {0xbf852000}, {0xbf854000}, {0xbf856000},
+ {0xbf858000}, {0xbf85a000}, {0xbf85c000}, {0xbf85e000},
+ {0xbf860000}, {0xbf862000}, {0xbf864000}, {0xbf866000},
+ {0xbf868000}, {0xbf86a000}, {0xbf86c000}, {0xbf86e000},
+ {0xbf870000}, {0xbf872000}, {0xbf874000}, {0xbf876000},
+ {0xbf878000}, {0xbf87a000}, {0xbf87c000}, {0xbf87e000},
+ {0xbf880000}, {0xbf882000}, {0xbf884000}, {0xbf886000},
+ {0xbf888000}, {0xbf88a000}, {0xbf88c000}, {0xbf88e000},
+ {0xbf890000}, {0xbf892000}, {0xbf894000}, {0xbf896000},
+ {0xbf898000}, {0xbf89a000}, {0xbf89c000}, {0xbf89e000},
+ {0xbf8a0000}, {0xbf8a2000}, {0xbf8a4000}, {0xbf8a6000},
+ {0xbf8a8000}, {0xbf8aa000}, {0xbf8ac000}, {0xbf8ae000},
+ {0xbf8b0000}, {0xbf8b2000}, {0xbf8b4000}, {0xbf8b6000},
+ {0xbf8b8000}, {0xbf8ba000}, {0xbf8bc000}, {0xbf8be000},
+ {0xbf8c0000}, {0xbf8c2000}, {0xbf8c4000}, {0xbf8c6000},
+ {0xbf8c8000}, {0xbf8ca000}, {0xbf8cc000}, {0xbf8ce000},
+ {0xbf8d0000}, {0xbf8d2000}, {0xbf8d4000}, {0xbf8d6000},
+ {0xbf8d8000}, {0xbf8da000}, {0xbf8dc000}, {0xbf8de000},
+ {0xbf8e0000}, {0xbf8e2000}, {0xbf8e4000}, {0xbf8e6000},
+ {0xbf8e8000}, {0xbf8ea000}, {0xbf8ec000}, {0xbf8ee000},
+ {0xbf8f0000}, {0xbf8f2000}, {0xbf8f4000}, {0xbf8f6000},
+ {0xbf8f8000}, {0xbf8fa000}, {0xbf8fc000}, {0xbf8fe000},
+ {0xbf900000}, {0xbf902000}, {0xbf904000}, {0xbf906000},
+ {0xbf908000}, {0xbf90a000}, {0xbf90c000}, {0xbf90e000},
+ {0xbf910000}, {0xbf912000}, {0xbf914000}, {0xbf916000},
+ {0xbf918000}, {0xbf91a000}, {0xbf91c000}, {0xbf91e000},
+ {0xbf920000}, {0xbf922000}, {0xbf924000}, {0xbf926000},
+ {0xbf928000}, {0xbf92a000}, {0xbf92c000}, {0xbf92e000},
+ {0xbf930000}, {0xbf932000}, {0xbf934000}, {0xbf936000},
+ {0xbf938000}, {0xbf93a000}, {0xbf93c000}, {0xbf93e000},
+ {0xbf940000}, {0xbf942000}, {0xbf944000}, {0xbf946000},
+ {0xbf948000}, {0xbf94a000}, {0xbf94c000}, {0xbf94e000},
+ {0xbf950000}, {0xbf952000}, {0xbf954000}, {0xbf956000},
+ {0xbf958000}, {0xbf95a000}, {0xbf95c000}, {0xbf95e000},
+ {0xbf960000}, {0xbf962000}, {0xbf964000}, {0xbf966000},
+ {0xbf968000}, {0xbf96a000}, {0xbf96c000}, {0xbf96e000},
+ {0xbf970000}, {0xbf972000}, {0xbf974000}, {0xbf976000},
+ {0xbf978000}, {0xbf97a000}, {0xbf97c000}, {0xbf97e000},
+ {0xbf980000}, {0xbf982000}, {0xbf984000}, {0xbf986000},
+ {0xbf988000}, {0xbf98a000}, {0xbf98c000}, {0xbf98e000},
+ {0xbf990000}, {0xbf992000}, {0xbf994000}, {0xbf996000},
+ {0xbf998000}, {0xbf99a000}, {0xbf99c000}, {0xbf99e000},
+ {0xbf9a0000}, {0xbf9a2000}, {0xbf9a4000}, {0xbf9a6000},
+ {0xbf9a8000}, {0xbf9aa000}, {0xbf9ac000}, {0xbf9ae000},
+ {0xbf9b0000}, {0xbf9b2000}, {0xbf9b4000}, {0xbf9b6000},
+ {0xbf9b8000}, {0xbf9ba000}, {0xbf9bc000}, {0xbf9be000},
+ {0xbf9c0000}, {0xbf9c2000}, {0xbf9c4000}, {0xbf9c6000},
+ {0xbf9c8000}, {0xbf9ca000}, {0xbf9cc000}, {0xbf9ce000},
+ {0xbf9d0000}, {0xbf9d2000}, {0xbf9d4000}, {0xbf9d6000},
+ {0xbf9d8000}, {0xbf9da000}, {0xbf9dc000}, {0xbf9de000},
+ {0xbf9e0000}, {0xbf9e2000}, {0xbf9e4000}, {0xbf9e6000},
+ {0xbf9e8000}, {0xbf9ea000}, {0xbf9ec000}, {0xbf9ee000},
+ {0xbf9f0000}, {0xbf9f2000}, {0xbf9f4000}, {0xbf9f6000},
+ {0xbf9f8000}, {0xbf9fa000}, {0xbf9fc000}, {0xbf9fe000},
+ {0xbfa00000}, {0xbfa02000}, {0xbfa04000}, {0xbfa06000},
+ {0xbfa08000}, {0xbfa0a000}, {0xbfa0c000}, {0xbfa0e000},
+ {0xbfa10000}, {0xbfa12000}, {0xbfa14000}, {0xbfa16000},
+ {0xbfa18000}, {0xbfa1a000}, {0xbfa1c000}, {0xbfa1e000},
+ {0xbfa20000}, {0xbfa22000}, {0xbfa24000}, {0xbfa26000},
+ {0xbfa28000}, {0xbfa2a000}, {0xbfa2c000}, {0xbfa2e000},
+ {0xbfa30000}, {0xbfa32000}, {0xbfa34000}, {0xbfa36000},
+ {0xbfa38000}, {0xbfa3a000}, {0xbfa3c000}, {0xbfa3e000},
+ {0xbfa40000}, {0xbfa42000}, {0xbfa44000}, {0xbfa46000},
+ {0xbfa48000}, {0xbfa4a000}, {0xbfa4c000}, {0xbfa4e000},
+ {0xbfa50000}, {0xbfa52000}, {0xbfa54000}, {0xbfa56000},
+ {0xbfa58000}, {0xbfa5a000}, {0xbfa5c000}, {0xbfa5e000},
+ {0xbfa60000}, {0xbfa62000}, {0xbfa64000}, {0xbfa66000},
+ {0xbfa68000}, {0xbfa6a000}, {0xbfa6c000}, {0xbfa6e000},
+ {0xbfa70000}, {0xbfa72000}, {0xbfa74000}, {0xbfa76000},
+ {0xbfa78000}, {0xbfa7a000}, {0xbfa7c000}, {0xbfa7e000},
+ {0xbfa80000}, {0xbfa82000}, {0xbfa84000}, {0xbfa86000},
+ {0xbfa88000}, {0xbfa8a000}, {0xbfa8c000}, {0xbfa8e000},
+ {0xbfa90000}, {0xbfa92000}, {0xbfa94000}, {0xbfa96000},
+ {0xbfa98000}, {0xbfa9a000}, {0xbfa9c000}, {0xbfa9e000},
+ {0xbfaa0000}, {0xbfaa2000}, {0xbfaa4000}, {0xbfaa6000},
+ {0xbfaa8000}, {0xbfaaa000}, {0xbfaac000}, {0xbfaae000},
+ {0xbfab0000}, {0xbfab2000}, {0xbfab4000}, {0xbfab6000},
+ {0xbfab8000}, {0xbfaba000}, {0xbfabc000}, {0xbfabe000},
+ {0xbfac0000}, {0xbfac2000}, {0xbfac4000}, {0xbfac6000},
+ {0xbfac8000}, {0xbfaca000}, {0xbfacc000}, {0xbface000},
+ {0xbfad0000}, {0xbfad2000}, {0xbfad4000}, {0xbfad6000},
+ {0xbfad8000}, {0xbfada000}, {0xbfadc000}, {0xbfade000},
+ {0xbfae0000}, {0xbfae2000}, {0xbfae4000}, {0xbfae6000},
+ {0xbfae8000}, {0xbfaea000}, {0xbfaec000}, {0xbfaee000},
+ {0xbfaf0000}, {0xbfaf2000}, {0xbfaf4000}, {0xbfaf6000},
+ {0xbfaf8000}, {0xbfafa000}, {0xbfafc000}, {0xbfafe000},
+ {0xbfb00000}, {0xbfb02000}, {0xbfb04000}, {0xbfb06000},
+ {0xbfb08000}, {0xbfb0a000}, {0xbfb0c000}, {0xbfb0e000},
+ {0xbfb10000}, {0xbfb12000}, {0xbfb14000}, {0xbfb16000},
+ {0xbfb18000}, {0xbfb1a000}, {0xbfb1c000}, {0xbfb1e000},
+ {0xbfb20000}, {0xbfb22000}, {0xbfb24000}, {0xbfb26000},
+ {0xbfb28000}, {0xbfb2a000}, {0xbfb2c000}, {0xbfb2e000},
+ {0xbfb30000}, {0xbfb32000}, {0xbfb34000}, {0xbfb36000},
+ {0xbfb38000}, {0xbfb3a000}, {0xbfb3c000}, {0xbfb3e000},
+ {0xbfb40000}, {0xbfb42000}, {0xbfb44000}, {0xbfb46000},
+ {0xbfb48000}, {0xbfb4a000}, {0xbfb4c000}, {0xbfb4e000},
+ {0xbfb50000}, {0xbfb52000}, {0xbfb54000}, {0xbfb56000},
+ {0xbfb58000}, {0xbfb5a000}, {0xbfb5c000}, {0xbfb5e000},
+ {0xbfb60000}, {0xbfb62000}, {0xbfb64000}, {0xbfb66000},
+ {0xbfb68000}, {0xbfb6a000}, {0xbfb6c000}, {0xbfb6e000},
+ {0xbfb70000}, {0xbfb72000}, {0xbfb74000}, {0xbfb76000},
+ {0xbfb78000}, {0xbfb7a000}, {0xbfb7c000}, {0xbfb7e000},
+ {0xbfb80000}, {0xbfb82000}, {0xbfb84000}, {0xbfb86000},
+ {0xbfb88000}, {0xbfb8a000}, {0xbfb8c000}, {0xbfb8e000},
+ {0xbfb90000}, {0xbfb92000}, {0xbfb94000}, {0xbfb96000},
+ {0xbfb98000}, {0xbfb9a000}, {0xbfb9c000}, {0xbfb9e000},
+ {0xbfba0000}, {0xbfba2000}, {0xbfba4000}, {0xbfba6000},
+ {0xbfba8000}, {0xbfbaa000}, {0xbfbac000}, {0xbfbae000},
+ {0xbfbb0000}, {0xbfbb2000}, {0xbfbb4000}, {0xbfbb6000},
+ {0xbfbb8000}, {0xbfbba000}, {0xbfbbc000}, {0xbfbbe000},
+ {0xbfbc0000}, {0xbfbc2000}, {0xbfbc4000}, {0xbfbc6000},
+ {0xbfbc8000}, {0xbfbca000}, {0xbfbcc000}, {0xbfbce000},
+ {0xbfbd0000}, {0xbfbd2000}, {0xbfbd4000}, {0xbfbd6000},
+ {0xbfbd8000}, {0xbfbda000}, {0xbfbdc000}, {0xbfbde000},
+ {0xbfbe0000}, {0xbfbe2000}, {0xbfbe4000}, {0xbfbe6000},
+ {0xbfbe8000}, {0xbfbea000}, {0xbfbec000}, {0xbfbee000},
+ {0xbfbf0000}, {0xbfbf2000}, {0xbfbf4000}, {0xbfbf6000},
+ {0xbfbf8000}, {0xbfbfa000}, {0xbfbfc000}, {0xbfbfe000},
+ {0xbfc00000}, {0xbfc02000}, {0xbfc04000}, {0xbfc06000},
+ {0xbfc08000}, {0xbfc0a000}, {0xbfc0c000}, {0xbfc0e000},
+ {0xbfc10000}, {0xbfc12000}, {0xbfc14000}, {0xbfc16000},
+ {0xbfc18000}, {0xbfc1a000}, {0xbfc1c000}, {0xbfc1e000},
+ {0xbfc20000}, {0xbfc22000}, {0xbfc24000}, {0xbfc26000},
+ {0xbfc28000}, {0xbfc2a000}, {0xbfc2c000}, {0xbfc2e000},
+ {0xbfc30000}, {0xbfc32000}, {0xbfc34000}, {0xbfc36000},
+ {0xbfc38000}, {0xbfc3a000}, {0xbfc3c000}, {0xbfc3e000},
+ {0xbfc40000}, {0xbfc42000}, {0xbfc44000}, {0xbfc46000},
+ {0xbfc48000}, {0xbfc4a000}, {0xbfc4c000}, {0xbfc4e000},
+ {0xbfc50000}, {0xbfc52000}, {0xbfc54000}, {0xbfc56000},
+ {0xbfc58000}, {0xbfc5a000}, {0xbfc5c000}, {0xbfc5e000},
+ {0xbfc60000}, {0xbfc62000}, {0xbfc64000}, {0xbfc66000},
+ {0xbfc68000}, {0xbfc6a000}, {0xbfc6c000}, {0xbfc6e000},
+ {0xbfc70000}, {0xbfc72000}, {0xbfc74000}, {0xbfc76000},
+ {0xbfc78000}, {0xbfc7a000}, {0xbfc7c000}, {0xbfc7e000},
+ {0xbfc80000}, {0xbfc82000}, {0xbfc84000}, {0xbfc86000},
+ {0xbfc88000}, {0xbfc8a000}, {0xbfc8c000}, {0xbfc8e000},
+ {0xbfc90000}, {0xbfc92000}, {0xbfc94000}, {0xbfc96000},
+ {0xbfc98000}, {0xbfc9a000}, {0xbfc9c000}, {0xbfc9e000},
+ {0xbfca0000}, {0xbfca2000}, {0xbfca4000}, {0xbfca6000},
+ {0xbfca8000}, {0xbfcaa000}, {0xbfcac000}, {0xbfcae000},
+ {0xbfcb0000}, {0xbfcb2000}, {0xbfcb4000}, {0xbfcb6000},
+ {0xbfcb8000}, {0xbfcba000}, {0xbfcbc000}, {0xbfcbe000},
+ {0xbfcc0000}, {0xbfcc2000}, {0xbfcc4000}, {0xbfcc6000},
+ {0xbfcc8000}, {0xbfcca000}, {0xbfccc000}, {0xbfcce000},
+ {0xbfcd0000}, {0xbfcd2000}, {0xbfcd4000}, {0xbfcd6000},
+ {0xbfcd8000}, {0xbfcda000}, {0xbfcdc000}, {0xbfcde000},
+ {0xbfce0000}, {0xbfce2000}, {0xbfce4000}, {0xbfce6000},
+ {0xbfce8000}, {0xbfcea000}, {0xbfcec000}, {0xbfcee000},
+ {0xbfcf0000}, {0xbfcf2000}, {0xbfcf4000}, {0xbfcf6000},
+ {0xbfcf8000}, {0xbfcfa000}, {0xbfcfc000}, {0xbfcfe000},
+ {0xbfd00000}, {0xbfd02000}, {0xbfd04000}, {0xbfd06000},
+ {0xbfd08000}, {0xbfd0a000}, {0xbfd0c000}, {0xbfd0e000},
+ {0xbfd10000}, {0xbfd12000}, {0xbfd14000}, {0xbfd16000},
+ {0xbfd18000}, {0xbfd1a000}, {0xbfd1c000}, {0xbfd1e000},
+ {0xbfd20000}, {0xbfd22000}, {0xbfd24000}, {0xbfd26000},
+ {0xbfd28000}, {0xbfd2a000}, {0xbfd2c000}, {0xbfd2e000},
+ {0xbfd30000}, {0xbfd32000}, {0xbfd34000}, {0xbfd36000},
+ {0xbfd38000}, {0xbfd3a000}, {0xbfd3c000}, {0xbfd3e000},
+ {0xbfd40000}, {0xbfd42000}, {0xbfd44000}, {0xbfd46000},
+ {0xbfd48000}, {0xbfd4a000}, {0xbfd4c000}, {0xbfd4e000},
+ {0xbfd50000}, {0xbfd52000}, {0xbfd54000}, {0xbfd56000},
+ {0xbfd58000}, {0xbfd5a000}, {0xbfd5c000}, {0xbfd5e000},
+ {0xbfd60000}, {0xbfd62000}, {0xbfd64000}, {0xbfd66000},
+ {0xbfd68000}, {0xbfd6a000}, {0xbfd6c000}, {0xbfd6e000},
+ {0xbfd70000}, {0xbfd72000}, {0xbfd74000}, {0xbfd76000},
+ {0xbfd78000}, {0xbfd7a000}, {0xbfd7c000}, {0xbfd7e000},
+ {0xbfd80000}, {0xbfd82000}, {0xbfd84000}, {0xbfd86000},
+ {0xbfd88000}, {0xbfd8a000}, {0xbfd8c000}, {0xbfd8e000},
+ {0xbfd90000}, {0xbfd92000}, {0xbfd94000}, {0xbfd96000},
+ {0xbfd98000}, {0xbfd9a000}, {0xbfd9c000}, {0xbfd9e000},
+ {0xbfda0000}, {0xbfda2000}, {0xbfda4000}, {0xbfda6000},
+ {0xbfda8000}, {0xbfdaa000}, {0xbfdac000}, {0xbfdae000},
+ {0xbfdb0000}, {0xbfdb2000}, {0xbfdb4000}, {0xbfdb6000},
+ {0xbfdb8000}, {0xbfdba000}, {0xbfdbc000}, {0xbfdbe000},
+ {0xbfdc0000}, {0xbfdc2000}, {0xbfdc4000}, {0xbfdc6000},
+ {0xbfdc8000}, {0xbfdca000}, {0xbfdcc000}, {0xbfdce000},
+ {0xbfdd0000}, {0xbfdd2000}, {0xbfdd4000}, {0xbfdd6000},
+ {0xbfdd8000}, {0xbfdda000}, {0xbfddc000}, {0xbfdde000},
+ {0xbfde0000}, {0xbfde2000}, {0xbfde4000}, {0xbfde6000},
+ {0xbfde8000}, {0xbfdea000}, {0xbfdec000}, {0xbfdee000},
+ {0xbfdf0000}, {0xbfdf2000}, {0xbfdf4000}, {0xbfdf6000},
+ {0xbfdf8000}, {0xbfdfa000}, {0xbfdfc000}, {0xbfdfe000},
+ {0xbfe00000}, {0xbfe02000}, {0xbfe04000}, {0xbfe06000},
+ {0xbfe08000}, {0xbfe0a000}, {0xbfe0c000}, {0xbfe0e000},
+ {0xbfe10000}, {0xbfe12000}, {0xbfe14000}, {0xbfe16000},
+ {0xbfe18000}, {0xbfe1a000}, {0xbfe1c000}, {0xbfe1e000},
+ {0xbfe20000}, {0xbfe22000}, {0xbfe24000}, {0xbfe26000},
+ {0xbfe28000}, {0xbfe2a000}, {0xbfe2c000}, {0xbfe2e000},
+ {0xbfe30000}, {0xbfe32000}, {0xbfe34000}, {0xbfe36000},
+ {0xbfe38000}, {0xbfe3a000}, {0xbfe3c000}, {0xbfe3e000},
+ {0xbfe40000}, {0xbfe42000}, {0xbfe44000}, {0xbfe46000},
+ {0xbfe48000}, {0xbfe4a000}, {0xbfe4c000}, {0xbfe4e000},
+ {0xbfe50000}, {0xbfe52000}, {0xbfe54000}, {0xbfe56000},
+ {0xbfe58000}, {0xbfe5a000}, {0xbfe5c000}, {0xbfe5e000},
+ {0xbfe60000}, {0xbfe62000}, {0xbfe64000}, {0xbfe66000},
+ {0xbfe68000}, {0xbfe6a000}, {0xbfe6c000}, {0xbfe6e000},
+ {0xbfe70000}, {0xbfe72000}, {0xbfe74000}, {0xbfe76000},
+ {0xbfe78000}, {0xbfe7a000}, {0xbfe7c000}, {0xbfe7e000},
+ {0xbfe80000}, {0xbfe82000}, {0xbfe84000}, {0xbfe86000},
+ {0xbfe88000}, {0xbfe8a000}, {0xbfe8c000}, {0xbfe8e000},
+ {0xbfe90000}, {0xbfe92000}, {0xbfe94000}, {0xbfe96000},
+ {0xbfe98000}, {0xbfe9a000}, {0xbfe9c000}, {0xbfe9e000},
+ {0xbfea0000}, {0xbfea2000}, {0xbfea4000}, {0xbfea6000},
+ {0xbfea8000}, {0xbfeaa000}, {0xbfeac000}, {0xbfeae000},
+ {0xbfeb0000}, {0xbfeb2000}, {0xbfeb4000}, {0xbfeb6000},
+ {0xbfeb8000}, {0xbfeba000}, {0xbfebc000}, {0xbfebe000},
+ {0xbfec0000}, {0xbfec2000}, {0xbfec4000}, {0xbfec6000},
+ {0xbfec8000}, {0xbfeca000}, {0xbfecc000}, {0xbfece000},
+ {0xbfed0000}, {0xbfed2000}, {0xbfed4000}, {0xbfed6000},
+ {0xbfed8000}, {0xbfeda000}, {0xbfedc000}, {0xbfede000},
+ {0xbfee0000}, {0xbfee2000}, {0xbfee4000}, {0xbfee6000},
+ {0xbfee8000}, {0xbfeea000}, {0xbfeec000}, {0xbfeee000},
+ {0xbfef0000}, {0xbfef2000}, {0xbfef4000}, {0xbfef6000},
+ {0xbfef8000}, {0xbfefa000}, {0xbfefc000}, {0xbfefe000},
+ {0xbff00000}, {0xbff02000}, {0xbff04000}, {0xbff06000},
+ {0xbff08000}, {0xbff0a000}, {0xbff0c000}, {0xbff0e000},
+ {0xbff10000}, {0xbff12000}, {0xbff14000}, {0xbff16000},
+ {0xbff18000}, {0xbff1a000}, {0xbff1c000}, {0xbff1e000},
+ {0xbff20000}, {0xbff22000}, {0xbff24000}, {0xbff26000},
+ {0xbff28000}, {0xbff2a000}, {0xbff2c000}, {0xbff2e000},
+ {0xbff30000}, {0xbff32000}, {0xbff34000}, {0xbff36000},
+ {0xbff38000}, {0xbff3a000}, {0xbff3c000}, {0xbff3e000},
+ {0xbff40000}, {0xbff42000}, {0xbff44000}, {0xbff46000},
+ {0xbff48000}, {0xbff4a000}, {0xbff4c000}, {0xbff4e000},
+ {0xbff50000}, {0xbff52000}, {0xbff54000}, {0xbff56000},
+ {0xbff58000}, {0xbff5a000}, {0xbff5c000}, {0xbff5e000},
+ {0xbff60000}, {0xbff62000}, {0xbff64000}, {0xbff66000},
+ {0xbff68000}, {0xbff6a000}, {0xbff6c000}, {0xbff6e000},
+ {0xbff70000}, {0xbff72000}, {0xbff74000}, {0xbff76000},
+ {0xbff78000}, {0xbff7a000}, {0xbff7c000}, {0xbff7e000},
+ {0xbff80000}, {0xbff82000}, {0xbff84000}, {0xbff86000},
+ {0xbff88000}, {0xbff8a000}, {0xbff8c000}, {0xbff8e000},
+ {0xbff90000}, {0xbff92000}, {0xbff94000}, {0xbff96000},
+ {0xbff98000}, {0xbff9a000}, {0xbff9c000}, {0xbff9e000},
+ {0xbffa0000}, {0xbffa2000}, {0xbffa4000}, {0xbffa6000},
+ {0xbffa8000}, {0xbffaa000}, {0xbffac000}, {0xbffae000},
+ {0xbffb0000}, {0xbffb2000}, {0xbffb4000}, {0xbffb6000},
+ {0xbffb8000}, {0xbffba000}, {0xbffbc000}, {0xbffbe000},
+ {0xbffc0000}, {0xbffc2000}, {0xbffc4000}, {0xbffc6000},
+ {0xbffc8000}, {0xbffca000}, {0xbffcc000}, {0xbffce000},
+ {0xbffd0000}, {0xbffd2000}, {0xbffd4000}, {0xbffd6000},
+ {0xbffd8000}, {0xbffda000}, {0xbffdc000}, {0xbffde000},
+ {0xbffe0000}, {0xbffe2000}, {0xbffe4000}, {0xbffe6000},
+ {0xbffe8000}, {0xbffea000}, {0xbffec000}, {0xbffee000},
+ {0xbfff0000}, {0xbfff2000}, {0xbfff4000}, {0xbfff6000},
+ {0xbfff8000}, {0xbfffa000}, {0xbfffc000}, {0xbfffe000},
+ {0xc0000000}, {0xc0002000}, {0xc0004000}, {0xc0006000},
+ {0xc0008000}, {0xc000a000}, {0xc000c000}, {0xc000e000},
+ {0xc0010000}, {0xc0012000}, {0xc0014000}, {0xc0016000},
+ {0xc0018000}, {0xc001a000}, {0xc001c000}, {0xc001e000},
+ {0xc0020000}, {0xc0022000}, {0xc0024000}, {0xc0026000},
+ {0xc0028000}, {0xc002a000}, {0xc002c000}, {0xc002e000},
+ {0xc0030000}, {0xc0032000}, {0xc0034000}, {0xc0036000},
+ {0xc0038000}, {0xc003a000}, {0xc003c000}, {0xc003e000},
+ {0xc0040000}, {0xc0042000}, {0xc0044000}, {0xc0046000},
+ {0xc0048000}, {0xc004a000}, {0xc004c000}, {0xc004e000},
+ {0xc0050000}, {0xc0052000}, {0xc0054000}, {0xc0056000},
+ {0xc0058000}, {0xc005a000}, {0xc005c000}, {0xc005e000},
+ {0xc0060000}, {0xc0062000}, {0xc0064000}, {0xc0066000},
+ {0xc0068000}, {0xc006a000}, {0xc006c000}, {0xc006e000},
+ {0xc0070000}, {0xc0072000}, {0xc0074000}, {0xc0076000},
+ {0xc0078000}, {0xc007a000}, {0xc007c000}, {0xc007e000},
+ {0xc0080000}, {0xc0082000}, {0xc0084000}, {0xc0086000},
+ {0xc0088000}, {0xc008a000}, {0xc008c000}, {0xc008e000},
+ {0xc0090000}, {0xc0092000}, {0xc0094000}, {0xc0096000},
+ {0xc0098000}, {0xc009a000}, {0xc009c000}, {0xc009e000},
+ {0xc00a0000}, {0xc00a2000}, {0xc00a4000}, {0xc00a6000},
+ {0xc00a8000}, {0xc00aa000}, {0xc00ac000}, {0xc00ae000},
+ {0xc00b0000}, {0xc00b2000}, {0xc00b4000}, {0xc00b6000},
+ {0xc00b8000}, {0xc00ba000}, {0xc00bc000}, {0xc00be000},
+ {0xc00c0000}, {0xc00c2000}, {0xc00c4000}, {0xc00c6000},
+ {0xc00c8000}, {0xc00ca000}, {0xc00cc000}, {0xc00ce000},
+ {0xc00d0000}, {0xc00d2000}, {0xc00d4000}, {0xc00d6000},
+ {0xc00d8000}, {0xc00da000}, {0xc00dc000}, {0xc00de000},
+ {0xc00e0000}, {0xc00e2000}, {0xc00e4000}, {0xc00e6000},
+ {0xc00e8000}, {0xc00ea000}, {0xc00ec000}, {0xc00ee000},
+ {0xc00f0000}, {0xc00f2000}, {0xc00f4000}, {0xc00f6000},
+ {0xc00f8000}, {0xc00fa000}, {0xc00fc000}, {0xc00fe000},
+ {0xc0100000}, {0xc0102000}, {0xc0104000}, {0xc0106000},
+ {0xc0108000}, {0xc010a000}, {0xc010c000}, {0xc010e000},
+ {0xc0110000}, {0xc0112000}, {0xc0114000}, {0xc0116000},
+ {0xc0118000}, {0xc011a000}, {0xc011c000}, {0xc011e000},
+ {0xc0120000}, {0xc0122000}, {0xc0124000}, {0xc0126000},
+ {0xc0128000}, {0xc012a000}, {0xc012c000}, {0xc012e000},
+ {0xc0130000}, {0xc0132000}, {0xc0134000}, {0xc0136000},
+ {0xc0138000}, {0xc013a000}, {0xc013c000}, {0xc013e000},
+ {0xc0140000}, {0xc0142000}, {0xc0144000}, {0xc0146000},
+ {0xc0148000}, {0xc014a000}, {0xc014c000}, {0xc014e000},
+ {0xc0150000}, {0xc0152000}, {0xc0154000}, {0xc0156000},
+ {0xc0158000}, {0xc015a000}, {0xc015c000}, {0xc015e000},
+ {0xc0160000}, {0xc0162000}, {0xc0164000}, {0xc0166000},
+ {0xc0168000}, {0xc016a000}, {0xc016c000}, {0xc016e000},
+ {0xc0170000}, {0xc0172000}, {0xc0174000}, {0xc0176000},
+ {0xc0178000}, {0xc017a000}, {0xc017c000}, {0xc017e000},
+ {0xc0180000}, {0xc0182000}, {0xc0184000}, {0xc0186000},
+ {0xc0188000}, {0xc018a000}, {0xc018c000}, {0xc018e000},
+ {0xc0190000}, {0xc0192000}, {0xc0194000}, {0xc0196000},
+ {0xc0198000}, {0xc019a000}, {0xc019c000}, {0xc019e000},
+ {0xc01a0000}, {0xc01a2000}, {0xc01a4000}, {0xc01a6000},
+ {0xc01a8000}, {0xc01aa000}, {0xc01ac000}, {0xc01ae000},
+ {0xc01b0000}, {0xc01b2000}, {0xc01b4000}, {0xc01b6000},
+ {0xc01b8000}, {0xc01ba000}, {0xc01bc000}, {0xc01be000},
+ {0xc01c0000}, {0xc01c2000}, {0xc01c4000}, {0xc01c6000},
+ {0xc01c8000}, {0xc01ca000}, {0xc01cc000}, {0xc01ce000},
+ {0xc01d0000}, {0xc01d2000}, {0xc01d4000}, {0xc01d6000},
+ {0xc01d8000}, {0xc01da000}, {0xc01dc000}, {0xc01de000},
+ {0xc01e0000}, {0xc01e2000}, {0xc01e4000}, {0xc01e6000},
+ {0xc01e8000}, {0xc01ea000}, {0xc01ec000}, {0xc01ee000},
+ {0xc01f0000}, {0xc01f2000}, {0xc01f4000}, {0xc01f6000},
+ {0xc01f8000}, {0xc01fa000}, {0xc01fc000}, {0xc01fe000},
+ {0xc0200000}, {0xc0202000}, {0xc0204000}, {0xc0206000},
+ {0xc0208000}, {0xc020a000}, {0xc020c000}, {0xc020e000},
+ {0xc0210000}, {0xc0212000}, {0xc0214000}, {0xc0216000},
+ {0xc0218000}, {0xc021a000}, {0xc021c000}, {0xc021e000},
+ {0xc0220000}, {0xc0222000}, {0xc0224000}, {0xc0226000},
+ {0xc0228000}, {0xc022a000}, {0xc022c000}, {0xc022e000},
+ {0xc0230000}, {0xc0232000}, {0xc0234000}, {0xc0236000},
+ {0xc0238000}, {0xc023a000}, {0xc023c000}, {0xc023e000},
+ {0xc0240000}, {0xc0242000}, {0xc0244000}, {0xc0246000},
+ {0xc0248000}, {0xc024a000}, {0xc024c000}, {0xc024e000},
+ {0xc0250000}, {0xc0252000}, {0xc0254000}, {0xc0256000},
+ {0xc0258000}, {0xc025a000}, {0xc025c000}, {0xc025e000},
+ {0xc0260000}, {0xc0262000}, {0xc0264000}, {0xc0266000},
+ {0xc0268000}, {0xc026a000}, {0xc026c000}, {0xc026e000},
+ {0xc0270000}, {0xc0272000}, {0xc0274000}, {0xc0276000},
+ {0xc0278000}, {0xc027a000}, {0xc027c000}, {0xc027e000},
+ {0xc0280000}, {0xc0282000}, {0xc0284000}, {0xc0286000},
+ {0xc0288000}, {0xc028a000}, {0xc028c000}, {0xc028e000},
+ {0xc0290000}, {0xc0292000}, {0xc0294000}, {0xc0296000},
+ {0xc0298000}, {0xc029a000}, {0xc029c000}, {0xc029e000},
+ {0xc02a0000}, {0xc02a2000}, {0xc02a4000}, {0xc02a6000},
+ {0xc02a8000}, {0xc02aa000}, {0xc02ac000}, {0xc02ae000},
+ {0xc02b0000}, {0xc02b2000}, {0xc02b4000}, {0xc02b6000},
+ {0xc02b8000}, {0xc02ba000}, {0xc02bc000}, {0xc02be000},
+ {0xc02c0000}, {0xc02c2000}, {0xc02c4000}, {0xc02c6000},
+ {0xc02c8000}, {0xc02ca000}, {0xc02cc000}, {0xc02ce000},
+ {0xc02d0000}, {0xc02d2000}, {0xc02d4000}, {0xc02d6000},
+ {0xc02d8000}, {0xc02da000}, {0xc02dc000}, {0xc02de000},
+ {0xc02e0000}, {0xc02e2000}, {0xc02e4000}, {0xc02e6000},
+ {0xc02e8000}, {0xc02ea000}, {0xc02ec000}, {0xc02ee000},
+ {0xc02f0000}, {0xc02f2000}, {0xc02f4000}, {0xc02f6000},
+ {0xc02f8000}, {0xc02fa000}, {0xc02fc000}, {0xc02fe000},
+ {0xc0300000}, {0xc0302000}, {0xc0304000}, {0xc0306000},
+ {0xc0308000}, {0xc030a000}, {0xc030c000}, {0xc030e000},
+ {0xc0310000}, {0xc0312000}, {0xc0314000}, {0xc0316000},
+ {0xc0318000}, {0xc031a000}, {0xc031c000}, {0xc031e000},
+ {0xc0320000}, {0xc0322000}, {0xc0324000}, {0xc0326000},
+ {0xc0328000}, {0xc032a000}, {0xc032c000}, {0xc032e000},
+ {0xc0330000}, {0xc0332000}, {0xc0334000}, {0xc0336000},
+ {0xc0338000}, {0xc033a000}, {0xc033c000}, {0xc033e000},
+ {0xc0340000}, {0xc0342000}, {0xc0344000}, {0xc0346000},
+ {0xc0348000}, {0xc034a000}, {0xc034c000}, {0xc034e000},
+ {0xc0350000}, {0xc0352000}, {0xc0354000}, {0xc0356000},
+ {0xc0358000}, {0xc035a000}, {0xc035c000}, {0xc035e000},
+ {0xc0360000}, {0xc0362000}, {0xc0364000}, {0xc0366000},
+ {0xc0368000}, {0xc036a000}, {0xc036c000}, {0xc036e000},
+ {0xc0370000}, {0xc0372000}, {0xc0374000}, {0xc0376000},
+ {0xc0378000}, {0xc037a000}, {0xc037c000}, {0xc037e000},
+ {0xc0380000}, {0xc0382000}, {0xc0384000}, {0xc0386000},
+ {0xc0388000}, {0xc038a000}, {0xc038c000}, {0xc038e000},
+ {0xc0390000}, {0xc0392000}, {0xc0394000}, {0xc0396000},
+ {0xc0398000}, {0xc039a000}, {0xc039c000}, {0xc039e000},
+ {0xc03a0000}, {0xc03a2000}, {0xc03a4000}, {0xc03a6000},
+ {0xc03a8000}, {0xc03aa000}, {0xc03ac000}, {0xc03ae000},
+ {0xc03b0000}, {0xc03b2000}, {0xc03b4000}, {0xc03b6000},
+ {0xc03b8000}, {0xc03ba000}, {0xc03bc000}, {0xc03be000},
+ {0xc03c0000}, {0xc03c2000}, {0xc03c4000}, {0xc03c6000},
+ {0xc03c8000}, {0xc03ca000}, {0xc03cc000}, {0xc03ce000},
+ {0xc03d0000}, {0xc03d2000}, {0xc03d4000}, {0xc03d6000},
+ {0xc03d8000}, {0xc03da000}, {0xc03dc000}, {0xc03de000},
+ {0xc03e0000}, {0xc03e2000}, {0xc03e4000}, {0xc03e6000},
+ {0xc03e8000}, {0xc03ea000}, {0xc03ec000}, {0xc03ee000},
+ {0xc03f0000}, {0xc03f2000}, {0xc03f4000}, {0xc03f6000},
+ {0xc03f8000}, {0xc03fa000}, {0xc03fc000}, {0xc03fe000},
+ {0xc0400000}, {0xc0402000}, {0xc0404000}, {0xc0406000},
+ {0xc0408000}, {0xc040a000}, {0xc040c000}, {0xc040e000},
+ {0xc0410000}, {0xc0412000}, {0xc0414000}, {0xc0416000},
+ {0xc0418000}, {0xc041a000}, {0xc041c000}, {0xc041e000},
+ {0xc0420000}, {0xc0422000}, {0xc0424000}, {0xc0426000},
+ {0xc0428000}, {0xc042a000}, {0xc042c000}, {0xc042e000},
+ {0xc0430000}, {0xc0432000}, {0xc0434000}, {0xc0436000},
+ {0xc0438000}, {0xc043a000}, {0xc043c000}, {0xc043e000},
+ {0xc0440000}, {0xc0442000}, {0xc0444000}, {0xc0446000},
+ {0xc0448000}, {0xc044a000}, {0xc044c000}, {0xc044e000},
+ {0xc0450000}, {0xc0452000}, {0xc0454000}, {0xc0456000},
+ {0xc0458000}, {0xc045a000}, {0xc045c000}, {0xc045e000},
+ {0xc0460000}, {0xc0462000}, {0xc0464000}, {0xc0466000},
+ {0xc0468000}, {0xc046a000}, {0xc046c000}, {0xc046e000},
+ {0xc0470000}, {0xc0472000}, {0xc0474000}, {0xc0476000},
+ {0xc0478000}, {0xc047a000}, {0xc047c000}, {0xc047e000},
+ {0xc0480000}, {0xc0482000}, {0xc0484000}, {0xc0486000},
+ {0xc0488000}, {0xc048a000}, {0xc048c000}, {0xc048e000},
+ {0xc0490000}, {0xc0492000}, {0xc0494000}, {0xc0496000},
+ {0xc0498000}, {0xc049a000}, {0xc049c000}, {0xc049e000},
+ {0xc04a0000}, {0xc04a2000}, {0xc04a4000}, {0xc04a6000},
+ {0xc04a8000}, {0xc04aa000}, {0xc04ac000}, {0xc04ae000},
+ {0xc04b0000}, {0xc04b2000}, {0xc04b4000}, {0xc04b6000},
+ {0xc04b8000}, {0xc04ba000}, {0xc04bc000}, {0xc04be000},
+ {0xc04c0000}, {0xc04c2000}, {0xc04c4000}, {0xc04c6000},
+ {0xc04c8000}, {0xc04ca000}, {0xc04cc000}, {0xc04ce000},
+ {0xc04d0000}, {0xc04d2000}, {0xc04d4000}, {0xc04d6000},
+ {0xc04d8000}, {0xc04da000}, {0xc04dc000}, {0xc04de000},
+ {0xc04e0000}, {0xc04e2000}, {0xc04e4000}, {0xc04e6000},
+ {0xc04e8000}, {0xc04ea000}, {0xc04ec000}, {0xc04ee000},
+ {0xc04f0000}, {0xc04f2000}, {0xc04f4000}, {0xc04f6000},
+ {0xc04f8000}, {0xc04fa000}, {0xc04fc000}, {0xc04fe000},
+ {0xc0500000}, {0xc0502000}, {0xc0504000}, {0xc0506000},
+ {0xc0508000}, {0xc050a000}, {0xc050c000}, {0xc050e000},
+ {0xc0510000}, {0xc0512000}, {0xc0514000}, {0xc0516000},
+ {0xc0518000}, {0xc051a000}, {0xc051c000}, {0xc051e000},
+ {0xc0520000}, {0xc0522000}, {0xc0524000}, {0xc0526000},
+ {0xc0528000}, {0xc052a000}, {0xc052c000}, {0xc052e000},
+ {0xc0530000}, {0xc0532000}, {0xc0534000}, {0xc0536000},
+ {0xc0538000}, {0xc053a000}, {0xc053c000}, {0xc053e000},
+ {0xc0540000}, {0xc0542000}, {0xc0544000}, {0xc0546000},
+ {0xc0548000}, {0xc054a000}, {0xc054c000}, {0xc054e000},
+ {0xc0550000}, {0xc0552000}, {0xc0554000}, {0xc0556000},
+ {0xc0558000}, {0xc055a000}, {0xc055c000}, {0xc055e000},
+ {0xc0560000}, {0xc0562000}, {0xc0564000}, {0xc0566000},
+ {0xc0568000}, {0xc056a000}, {0xc056c000}, {0xc056e000},
+ {0xc0570000}, {0xc0572000}, {0xc0574000}, {0xc0576000},
+ {0xc0578000}, {0xc057a000}, {0xc057c000}, {0xc057e000},
+ {0xc0580000}, {0xc0582000}, {0xc0584000}, {0xc0586000},
+ {0xc0588000}, {0xc058a000}, {0xc058c000}, {0xc058e000},
+ {0xc0590000}, {0xc0592000}, {0xc0594000}, {0xc0596000},
+ {0xc0598000}, {0xc059a000}, {0xc059c000}, {0xc059e000},
+ {0xc05a0000}, {0xc05a2000}, {0xc05a4000}, {0xc05a6000},
+ {0xc05a8000}, {0xc05aa000}, {0xc05ac000}, {0xc05ae000},
+ {0xc05b0000}, {0xc05b2000}, {0xc05b4000}, {0xc05b6000},
+ {0xc05b8000}, {0xc05ba000}, {0xc05bc000}, {0xc05be000},
+ {0xc05c0000}, {0xc05c2000}, {0xc05c4000}, {0xc05c6000},
+ {0xc05c8000}, {0xc05ca000}, {0xc05cc000}, {0xc05ce000},
+ {0xc05d0000}, {0xc05d2000}, {0xc05d4000}, {0xc05d6000},
+ {0xc05d8000}, {0xc05da000}, {0xc05dc000}, {0xc05de000},
+ {0xc05e0000}, {0xc05e2000}, {0xc05e4000}, {0xc05e6000},
+ {0xc05e8000}, {0xc05ea000}, {0xc05ec000}, {0xc05ee000},
+ {0xc05f0000}, {0xc05f2000}, {0xc05f4000}, {0xc05f6000},
+ {0xc05f8000}, {0xc05fa000}, {0xc05fc000}, {0xc05fe000},
+ {0xc0600000}, {0xc0602000}, {0xc0604000}, {0xc0606000},
+ {0xc0608000}, {0xc060a000}, {0xc060c000}, {0xc060e000},
+ {0xc0610000}, {0xc0612000}, {0xc0614000}, {0xc0616000},
+ {0xc0618000}, {0xc061a000}, {0xc061c000}, {0xc061e000},
+ {0xc0620000}, {0xc0622000}, {0xc0624000}, {0xc0626000},
+ {0xc0628000}, {0xc062a000}, {0xc062c000}, {0xc062e000},
+ {0xc0630000}, {0xc0632000}, {0xc0634000}, {0xc0636000},
+ {0xc0638000}, {0xc063a000}, {0xc063c000}, {0xc063e000},
+ {0xc0640000}, {0xc0642000}, {0xc0644000}, {0xc0646000},
+ {0xc0648000}, {0xc064a000}, {0xc064c000}, {0xc064e000},
+ {0xc0650000}, {0xc0652000}, {0xc0654000}, {0xc0656000},
+ {0xc0658000}, {0xc065a000}, {0xc065c000}, {0xc065e000},
+ {0xc0660000}, {0xc0662000}, {0xc0664000}, {0xc0666000},
+ {0xc0668000}, {0xc066a000}, {0xc066c000}, {0xc066e000},
+ {0xc0670000}, {0xc0672000}, {0xc0674000}, {0xc0676000},
+ {0xc0678000}, {0xc067a000}, {0xc067c000}, {0xc067e000},
+ {0xc0680000}, {0xc0682000}, {0xc0684000}, {0xc0686000},
+ {0xc0688000}, {0xc068a000}, {0xc068c000}, {0xc068e000},
+ {0xc0690000}, {0xc0692000}, {0xc0694000}, {0xc0696000},
+ {0xc0698000}, {0xc069a000}, {0xc069c000}, {0xc069e000},
+ {0xc06a0000}, {0xc06a2000}, {0xc06a4000}, {0xc06a6000},
+ {0xc06a8000}, {0xc06aa000}, {0xc06ac000}, {0xc06ae000},
+ {0xc06b0000}, {0xc06b2000}, {0xc06b4000}, {0xc06b6000},
+ {0xc06b8000}, {0xc06ba000}, {0xc06bc000}, {0xc06be000},
+ {0xc06c0000}, {0xc06c2000}, {0xc06c4000}, {0xc06c6000},
+ {0xc06c8000}, {0xc06ca000}, {0xc06cc000}, {0xc06ce000},
+ {0xc06d0000}, {0xc06d2000}, {0xc06d4000}, {0xc06d6000},
+ {0xc06d8000}, {0xc06da000}, {0xc06dc000}, {0xc06de000},
+ {0xc06e0000}, {0xc06e2000}, {0xc06e4000}, {0xc06e6000},
+ {0xc06e8000}, {0xc06ea000}, {0xc06ec000}, {0xc06ee000},
+ {0xc06f0000}, {0xc06f2000}, {0xc06f4000}, {0xc06f6000},
+ {0xc06f8000}, {0xc06fa000}, {0xc06fc000}, {0xc06fe000},
+ {0xc0700000}, {0xc0702000}, {0xc0704000}, {0xc0706000},
+ {0xc0708000}, {0xc070a000}, {0xc070c000}, {0xc070e000},
+ {0xc0710000}, {0xc0712000}, {0xc0714000}, {0xc0716000},
+ {0xc0718000}, {0xc071a000}, {0xc071c000}, {0xc071e000},
+ {0xc0720000}, {0xc0722000}, {0xc0724000}, {0xc0726000},
+ {0xc0728000}, {0xc072a000}, {0xc072c000}, {0xc072e000},
+ {0xc0730000}, {0xc0732000}, {0xc0734000}, {0xc0736000},
+ {0xc0738000}, {0xc073a000}, {0xc073c000}, {0xc073e000},
+ {0xc0740000}, {0xc0742000}, {0xc0744000}, {0xc0746000},
+ {0xc0748000}, {0xc074a000}, {0xc074c000}, {0xc074e000},
+ {0xc0750000}, {0xc0752000}, {0xc0754000}, {0xc0756000},
+ {0xc0758000}, {0xc075a000}, {0xc075c000}, {0xc075e000},
+ {0xc0760000}, {0xc0762000}, {0xc0764000}, {0xc0766000},
+ {0xc0768000}, {0xc076a000}, {0xc076c000}, {0xc076e000},
+ {0xc0770000}, {0xc0772000}, {0xc0774000}, {0xc0776000},
+ {0xc0778000}, {0xc077a000}, {0xc077c000}, {0xc077e000},
+ {0xc0780000}, {0xc0782000}, {0xc0784000}, {0xc0786000},
+ {0xc0788000}, {0xc078a000}, {0xc078c000}, {0xc078e000},
+ {0xc0790000}, {0xc0792000}, {0xc0794000}, {0xc0796000},
+ {0xc0798000}, {0xc079a000}, {0xc079c000}, {0xc079e000},
+ {0xc07a0000}, {0xc07a2000}, {0xc07a4000}, {0xc07a6000},
+ {0xc07a8000}, {0xc07aa000}, {0xc07ac000}, {0xc07ae000},
+ {0xc07b0000}, {0xc07b2000}, {0xc07b4000}, {0xc07b6000},
+ {0xc07b8000}, {0xc07ba000}, {0xc07bc000}, {0xc07be000},
+ {0xc07c0000}, {0xc07c2000}, {0xc07c4000}, {0xc07c6000},
+ {0xc07c8000}, {0xc07ca000}, {0xc07cc000}, {0xc07ce000},
+ {0xc07d0000}, {0xc07d2000}, {0xc07d4000}, {0xc07d6000},
+ {0xc07d8000}, {0xc07da000}, {0xc07dc000}, {0xc07de000},
+ {0xc07e0000}, {0xc07e2000}, {0xc07e4000}, {0xc07e6000},
+ {0xc07e8000}, {0xc07ea000}, {0xc07ec000}, {0xc07ee000},
+ {0xc07f0000}, {0xc07f2000}, {0xc07f4000}, {0xc07f6000},
+ {0xc07f8000}, {0xc07fa000}, {0xc07fc000}, {0xc07fe000},
+ {0xc0800000}, {0xc0802000}, {0xc0804000}, {0xc0806000},
+ {0xc0808000}, {0xc080a000}, {0xc080c000}, {0xc080e000},
+ {0xc0810000}, {0xc0812000}, {0xc0814000}, {0xc0816000},
+ {0xc0818000}, {0xc081a000}, {0xc081c000}, {0xc081e000},
+ {0xc0820000}, {0xc0822000}, {0xc0824000}, {0xc0826000},
+ {0xc0828000}, {0xc082a000}, {0xc082c000}, {0xc082e000},
+ {0xc0830000}, {0xc0832000}, {0xc0834000}, {0xc0836000},
+ {0xc0838000}, {0xc083a000}, {0xc083c000}, {0xc083e000},
+ {0xc0840000}, {0xc0842000}, {0xc0844000}, {0xc0846000},
+ {0xc0848000}, {0xc084a000}, {0xc084c000}, {0xc084e000},
+ {0xc0850000}, {0xc0852000}, {0xc0854000}, {0xc0856000},
+ {0xc0858000}, {0xc085a000}, {0xc085c000}, {0xc085e000},
+ {0xc0860000}, {0xc0862000}, {0xc0864000}, {0xc0866000},
+ {0xc0868000}, {0xc086a000}, {0xc086c000}, {0xc086e000},
+ {0xc0870000}, {0xc0872000}, {0xc0874000}, {0xc0876000},
+ {0xc0878000}, {0xc087a000}, {0xc087c000}, {0xc087e000},
+ {0xc0880000}, {0xc0882000}, {0xc0884000}, {0xc0886000},
+ {0xc0888000}, {0xc088a000}, {0xc088c000}, {0xc088e000},
+ {0xc0890000}, {0xc0892000}, {0xc0894000}, {0xc0896000},
+ {0xc0898000}, {0xc089a000}, {0xc089c000}, {0xc089e000},
+ {0xc08a0000}, {0xc08a2000}, {0xc08a4000}, {0xc08a6000},
+ {0xc08a8000}, {0xc08aa000}, {0xc08ac000}, {0xc08ae000},
+ {0xc08b0000}, {0xc08b2000}, {0xc08b4000}, {0xc08b6000},
+ {0xc08b8000}, {0xc08ba000}, {0xc08bc000}, {0xc08be000},
+ {0xc08c0000}, {0xc08c2000}, {0xc08c4000}, {0xc08c6000},
+ {0xc08c8000}, {0xc08ca000}, {0xc08cc000}, {0xc08ce000},
+ {0xc08d0000}, {0xc08d2000}, {0xc08d4000}, {0xc08d6000},
+ {0xc08d8000}, {0xc08da000}, {0xc08dc000}, {0xc08de000},
+ {0xc08e0000}, {0xc08e2000}, {0xc08e4000}, {0xc08e6000},
+ {0xc08e8000}, {0xc08ea000}, {0xc08ec000}, {0xc08ee000},
+ {0xc08f0000}, {0xc08f2000}, {0xc08f4000}, {0xc08f6000},
+ {0xc08f8000}, {0xc08fa000}, {0xc08fc000}, {0xc08fe000},
+ {0xc0900000}, {0xc0902000}, {0xc0904000}, {0xc0906000},
+ {0xc0908000}, {0xc090a000}, {0xc090c000}, {0xc090e000},
+ {0xc0910000}, {0xc0912000}, {0xc0914000}, {0xc0916000},
+ {0xc0918000}, {0xc091a000}, {0xc091c000}, {0xc091e000},
+ {0xc0920000}, {0xc0922000}, {0xc0924000}, {0xc0926000},
+ {0xc0928000}, {0xc092a000}, {0xc092c000}, {0xc092e000},
+ {0xc0930000}, {0xc0932000}, {0xc0934000}, {0xc0936000},
+ {0xc0938000}, {0xc093a000}, {0xc093c000}, {0xc093e000},
+ {0xc0940000}, {0xc0942000}, {0xc0944000}, {0xc0946000},
+ {0xc0948000}, {0xc094a000}, {0xc094c000}, {0xc094e000},
+ {0xc0950000}, {0xc0952000}, {0xc0954000}, {0xc0956000},
+ {0xc0958000}, {0xc095a000}, {0xc095c000}, {0xc095e000},
+ {0xc0960000}, {0xc0962000}, {0xc0964000}, {0xc0966000},
+ {0xc0968000}, {0xc096a000}, {0xc096c000}, {0xc096e000},
+ {0xc0970000}, {0xc0972000}, {0xc0974000}, {0xc0976000},
+ {0xc0978000}, {0xc097a000}, {0xc097c000}, {0xc097e000},
+ {0xc0980000}, {0xc0982000}, {0xc0984000}, {0xc0986000},
+ {0xc0988000}, {0xc098a000}, {0xc098c000}, {0xc098e000},
+ {0xc0990000}, {0xc0992000}, {0xc0994000}, {0xc0996000},
+ {0xc0998000}, {0xc099a000}, {0xc099c000}, {0xc099e000},
+ {0xc09a0000}, {0xc09a2000}, {0xc09a4000}, {0xc09a6000},
+ {0xc09a8000}, {0xc09aa000}, {0xc09ac000}, {0xc09ae000},
+ {0xc09b0000}, {0xc09b2000}, {0xc09b4000}, {0xc09b6000},
+ {0xc09b8000}, {0xc09ba000}, {0xc09bc000}, {0xc09be000},
+ {0xc09c0000}, {0xc09c2000}, {0xc09c4000}, {0xc09c6000},
+ {0xc09c8000}, {0xc09ca000}, {0xc09cc000}, {0xc09ce000},
+ {0xc09d0000}, {0xc09d2000}, {0xc09d4000}, {0xc09d6000},
+ {0xc09d8000}, {0xc09da000}, {0xc09dc000}, {0xc09de000},
+ {0xc09e0000}, {0xc09e2000}, {0xc09e4000}, {0xc09e6000},
+ {0xc09e8000}, {0xc09ea000}, {0xc09ec000}, {0xc09ee000},
+ {0xc09f0000}, {0xc09f2000}, {0xc09f4000}, {0xc09f6000},
+ {0xc09f8000}, {0xc09fa000}, {0xc09fc000}, {0xc09fe000},
+ {0xc0a00000}, {0xc0a02000}, {0xc0a04000}, {0xc0a06000},
+ {0xc0a08000}, {0xc0a0a000}, {0xc0a0c000}, {0xc0a0e000},
+ {0xc0a10000}, {0xc0a12000}, {0xc0a14000}, {0xc0a16000},
+ {0xc0a18000}, {0xc0a1a000}, {0xc0a1c000}, {0xc0a1e000},
+ {0xc0a20000}, {0xc0a22000}, {0xc0a24000}, {0xc0a26000},
+ {0xc0a28000}, {0xc0a2a000}, {0xc0a2c000}, {0xc0a2e000},
+ {0xc0a30000}, {0xc0a32000}, {0xc0a34000}, {0xc0a36000},
+ {0xc0a38000}, {0xc0a3a000}, {0xc0a3c000}, {0xc0a3e000},
+ {0xc0a40000}, {0xc0a42000}, {0xc0a44000}, {0xc0a46000},
+ {0xc0a48000}, {0xc0a4a000}, {0xc0a4c000}, {0xc0a4e000},
+ {0xc0a50000}, {0xc0a52000}, {0xc0a54000}, {0xc0a56000},
+ {0xc0a58000}, {0xc0a5a000}, {0xc0a5c000}, {0xc0a5e000},
+ {0xc0a60000}, {0xc0a62000}, {0xc0a64000}, {0xc0a66000},
+ {0xc0a68000}, {0xc0a6a000}, {0xc0a6c000}, {0xc0a6e000},
+ {0xc0a70000}, {0xc0a72000}, {0xc0a74000}, {0xc0a76000},
+ {0xc0a78000}, {0xc0a7a000}, {0xc0a7c000}, {0xc0a7e000},
+ {0xc0a80000}, {0xc0a82000}, {0xc0a84000}, {0xc0a86000},
+ {0xc0a88000}, {0xc0a8a000}, {0xc0a8c000}, {0xc0a8e000},
+ {0xc0a90000}, {0xc0a92000}, {0xc0a94000}, {0xc0a96000},
+ {0xc0a98000}, {0xc0a9a000}, {0xc0a9c000}, {0xc0a9e000},
+ {0xc0aa0000}, {0xc0aa2000}, {0xc0aa4000}, {0xc0aa6000},
+ {0xc0aa8000}, {0xc0aaa000}, {0xc0aac000}, {0xc0aae000},
+ {0xc0ab0000}, {0xc0ab2000}, {0xc0ab4000}, {0xc0ab6000},
+ {0xc0ab8000}, {0xc0aba000}, {0xc0abc000}, {0xc0abe000},
+ {0xc0ac0000}, {0xc0ac2000}, {0xc0ac4000}, {0xc0ac6000},
+ {0xc0ac8000}, {0xc0aca000}, {0xc0acc000}, {0xc0ace000},
+ {0xc0ad0000}, {0xc0ad2000}, {0xc0ad4000}, {0xc0ad6000},
+ {0xc0ad8000}, {0xc0ada000}, {0xc0adc000}, {0xc0ade000},
+ {0xc0ae0000}, {0xc0ae2000}, {0xc0ae4000}, {0xc0ae6000},
+ {0xc0ae8000}, {0xc0aea000}, {0xc0aec000}, {0xc0aee000},
+ {0xc0af0000}, {0xc0af2000}, {0xc0af4000}, {0xc0af6000},
+ {0xc0af8000}, {0xc0afa000}, {0xc0afc000}, {0xc0afe000},
+ {0xc0b00000}, {0xc0b02000}, {0xc0b04000}, {0xc0b06000},
+ {0xc0b08000}, {0xc0b0a000}, {0xc0b0c000}, {0xc0b0e000},
+ {0xc0b10000}, {0xc0b12000}, {0xc0b14000}, {0xc0b16000},
+ {0xc0b18000}, {0xc0b1a000}, {0xc0b1c000}, {0xc0b1e000},
+ {0xc0b20000}, {0xc0b22000}, {0xc0b24000}, {0xc0b26000},
+ {0xc0b28000}, {0xc0b2a000}, {0xc0b2c000}, {0xc0b2e000},
+ {0xc0b30000}, {0xc0b32000}, {0xc0b34000}, {0xc0b36000},
+ {0xc0b38000}, {0xc0b3a000}, {0xc0b3c000}, {0xc0b3e000},
+ {0xc0b40000}, {0xc0b42000}, {0xc0b44000}, {0xc0b46000},
+ {0xc0b48000}, {0xc0b4a000}, {0xc0b4c000}, {0xc0b4e000},
+ {0xc0b50000}, {0xc0b52000}, {0xc0b54000}, {0xc0b56000},
+ {0xc0b58000}, {0xc0b5a000}, {0xc0b5c000}, {0xc0b5e000},
+ {0xc0b60000}, {0xc0b62000}, {0xc0b64000}, {0xc0b66000},
+ {0xc0b68000}, {0xc0b6a000}, {0xc0b6c000}, {0xc0b6e000},
+ {0xc0b70000}, {0xc0b72000}, {0xc0b74000}, {0xc0b76000},
+ {0xc0b78000}, {0xc0b7a000}, {0xc0b7c000}, {0xc0b7e000},
+ {0xc0b80000}, {0xc0b82000}, {0xc0b84000}, {0xc0b86000},
+ {0xc0b88000}, {0xc0b8a000}, {0xc0b8c000}, {0xc0b8e000},
+ {0xc0b90000}, {0xc0b92000}, {0xc0b94000}, {0xc0b96000},
+ {0xc0b98000}, {0xc0b9a000}, {0xc0b9c000}, {0xc0b9e000},
+ {0xc0ba0000}, {0xc0ba2000}, {0xc0ba4000}, {0xc0ba6000},
+ {0xc0ba8000}, {0xc0baa000}, {0xc0bac000}, {0xc0bae000},
+ {0xc0bb0000}, {0xc0bb2000}, {0xc0bb4000}, {0xc0bb6000},
+ {0xc0bb8000}, {0xc0bba000}, {0xc0bbc000}, {0xc0bbe000},
+ {0xc0bc0000}, {0xc0bc2000}, {0xc0bc4000}, {0xc0bc6000},
+ {0xc0bc8000}, {0xc0bca000}, {0xc0bcc000}, {0xc0bce000},
+ {0xc0bd0000}, {0xc0bd2000}, {0xc0bd4000}, {0xc0bd6000},
+ {0xc0bd8000}, {0xc0bda000}, {0xc0bdc000}, {0xc0bde000},
+ {0xc0be0000}, {0xc0be2000}, {0xc0be4000}, {0xc0be6000},
+ {0xc0be8000}, {0xc0bea000}, {0xc0bec000}, {0xc0bee000},
+ {0xc0bf0000}, {0xc0bf2000}, {0xc0bf4000}, {0xc0bf6000},
+ {0xc0bf8000}, {0xc0bfa000}, {0xc0bfc000}, {0xc0bfe000},
+ {0xc0c00000}, {0xc0c02000}, {0xc0c04000}, {0xc0c06000},
+ {0xc0c08000}, {0xc0c0a000}, {0xc0c0c000}, {0xc0c0e000},
+ {0xc0c10000}, {0xc0c12000}, {0xc0c14000}, {0xc0c16000},
+ {0xc0c18000}, {0xc0c1a000}, {0xc0c1c000}, {0xc0c1e000},
+ {0xc0c20000}, {0xc0c22000}, {0xc0c24000}, {0xc0c26000},
+ {0xc0c28000}, {0xc0c2a000}, {0xc0c2c000}, {0xc0c2e000},
+ {0xc0c30000}, {0xc0c32000}, {0xc0c34000}, {0xc0c36000},
+ {0xc0c38000}, {0xc0c3a000}, {0xc0c3c000}, {0xc0c3e000},
+ {0xc0c40000}, {0xc0c42000}, {0xc0c44000}, {0xc0c46000},
+ {0xc0c48000}, {0xc0c4a000}, {0xc0c4c000}, {0xc0c4e000},
+ {0xc0c50000}, {0xc0c52000}, {0xc0c54000}, {0xc0c56000},
+ {0xc0c58000}, {0xc0c5a000}, {0xc0c5c000}, {0xc0c5e000},
+ {0xc0c60000}, {0xc0c62000}, {0xc0c64000}, {0xc0c66000},
+ {0xc0c68000}, {0xc0c6a000}, {0xc0c6c000}, {0xc0c6e000},
+ {0xc0c70000}, {0xc0c72000}, {0xc0c74000}, {0xc0c76000},
+ {0xc0c78000}, {0xc0c7a000}, {0xc0c7c000}, {0xc0c7e000},
+ {0xc0c80000}, {0xc0c82000}, {0xc0c84000}, {0xc0c86000},
+ {0xc0c88000}, {0xc0c8a000}, {0xc0c8c000}, {0xc0c8e000},
+ {0xc0c90000}, {0xc0c92000}, {0xc0c94000}, {0xc0c96000},
+ {0xc0c98000}, {0xc0c9a000}, {0xc0c9c000}, {0xc0c9e000},
+ {0xc0ca0000}, {0xc0ca2000}, {0xc0ca4000}, {0xc0ca6000},
+ {0xc0ca8000}, {0xc0caa000}, {0xc0cac000}, {0xc0cae000},
+ {0xc0cb0000}, {0xc0cb2000}, {0xc0cb4000}, {0xc0cb6000},
+ {0xc0cb8000}, {0xc0cba000}, {0xc0cbc000}, {0xc0cbe000},
+ {0xc0cc0000}, {0xc0cc2000}, {0xc0cc4000}, {0xc0cc6000},
+ {0xc0cc8000}, {0xc0cca000}, {0xc0ccc000}, {0xc0cce000},
+ {0xc0cd0000}, {0xc0cd2000}, {0xc0cd4000}, {0xc0cd6000},
+ {0xc0cd8000}, {0xc0cda000}, {0xc0cdc000}, {0xc0cde000},
+ {0xc0ce0000}, {0xc0ce2000}, {0xc0ce4000}, {0xc0ce6000},
+ {0xc0ce8000}, {0xc0cea000}, {0xc0cec000}, {0xc0cee000},
+ {0xc0cf0000}, {0xc0cf2000}, {0xc0cf4000}, {0xc0cf6000},
+ {0xc0cf8000}, {0xc0cfa000}, {0xc0cfc000}, {0xc0cfe000},
+ {0xc0d00000}, {0xc0d02000}, {0xc0d04000}, {0xc0d06000},
+ {0xc0d08000}, {0xc0d0a000}, {0xc0d0c000}, {0xc0d0e000},
+ {0xc0d10000}, {0xc0d12000}, {0xc0d14000}, {0xc0d16000},
+ {0xc0d18000}, {0xc0d1a000}, {0xc0d1c000}, {0xc0d1e000},
+ {0xc0d20000}, {0xc0d22000}, {0xc0d24000}, {0xc0d26000},
+ {0xc0d28000}, {0xc0d2a000}, {0xc0d2c000}, {0xc0d2e000},
+ {0xc0d30000}, {0xc0d32000}, {0xc0d34000}, {0xc0d36000},
+ {0xc0d38000}, {0xc0d3a000}, {0xc0d3c000}, {0xc0d3e000},
+ {0xc0d40000}, {0xc0d42000}, {0xc0d44000}, {0xc0d46000},
+ {0xc0d48000}, {0xc0d4a000}, {0xc0d4c000}, {0xc0d4e000},
+ {0xc0d50000}, {0xc0d52000}, {0xc0d54000}, {0xc0d56000},
+ {0xc0d58000}, {0xc0d5a000}, {0xc0d5c000}, {0xc0d5e000},
+ {0xc0d60000}, {0xc0d62000}, {0xc0d64000}, {0xc0d66000},
+ {0xc0d68000}, {0xc0d6a000}, {0xc0d6c000}, {0xc0d6e000},
+ {0xc0d70000}, {0xc0d72000}, {0xc0d74000}, {0xc0d76000},
+ {0xc0d78000}, {0xc0d7a000}, {0xc0d7c000}, {0xc0d7e000},
+ {0xc0d80000}, {0xc0d82000}, {0xc0d84000}, {0xc0d86000},
+ {0xc0d88000}, {0xc0d8a000}, {0xc0d8c000}, {0xc0d8e000},
+ {0xc0d90000}, {0xc0d92000}, {0xc0d94000}, {0xc0d96000},
+ {0xc0d98000}, {0xc0d9a000}, {0xc0d9c000}, {0xc0d9e000},
+ {0xc0da0000}, {0xc0da2000}, {0xc0da4000}, {0xc0da6000},
+ {0xc0da8000}, {0xc0daa000}, {0xc0dac000}, {0xc0dae000},
+ {0xc0db0000}, {0xc0db2000}, {0xc0db4000}, {0xc0db6000},
+ {0xc0db8000}, {0xc0dba000}, {0xc0dbc000}, {0xc0dbe000},
+ {0xc0dc0000}, {0xc0dc2000}, {0xc0dc4000}, {0xc0dc6000},
+ {0xc0dc8000}, {0xc0dca000}, {0xc0dcc000}, {0xc0dce000},
+ {0xc0dd0000}, {0xc0dd2000}, {0xc0dd4000}, {0xc0dd6000},
+ {0xc0dd8000}, {0xc0dda000}, {0xc0ddc000}, {0xc0dde000},
+ {0xc0de0000}, {0xc0de2000}, {0xc0de4000}, {0xc0de6000},
+ {0xc0de8000}, {0xc0dea000}, {0xc0dec000}, {0xc0dee000},
+ {0xc0df0000}, {0xc0df2000}, {0xc0df4000}, {0xc0df6000},
+ {0xc0df8000}, {0xc0dfa000}, {0xc0dfc000}, {0xc0dfe000},
+ {0xc0e00000}, {0xc0e02000}, {0xc0e04000}, {0xc0e06000},
+ {0xc0e08000}, {0xc0e0a000}, {0xc0e0c000}, {0xc0e0e000},
+ {0xc0e10000}, {0xc0e12000}, {0xc0e14000}, {0xc0e16000},
+ {0xc0e18000}, {0xc0e1a000}, {0xc0e1c000}, {0xc0e1e000},
+ {0xc0e20000}, {0xc0e22000}, {0xc0e24000}, {0xc0e26000},
+ {0xc0e28000}, {0xc0e2a000}, {0xc0e2c000}, {0xc0e2e000},
+ {0xc0e30000}, {0xc0e32000}, {0xc0e34000}, {0xc0e36000},
+ {0xc0e38000}, {0xc0e3a000}, {0xc0e3c000}, {0xc0e3e000},
+ {0xc0e40000}, {0xc0e42000}, {0xc0e44000}, {0xc0e46000},
+ {0xc0e48000}, {0xc0e4a000}, {0xc0e4c000}, {0xc0e4e000},
+ {0xc0e50000}, {0xc0e52000}, {0xc0e54000}, {0xc0e56000},
+ {0xc0e58000}, {0xc0e5a000}, {0xc0e5c000}, {0xc0e5e000},
+ {0xc0e60000}, {0xc0e62000}, {0xc0e64000}, {0xc0e66000},
+ {0xc0e68000}, {0xc0e6a000}, {0xc0e6c000}, {0xc0e6e000},
+ {0xc0e70000}, {0xc0e72000}, {0xc0e74000}, {0xc0e76000},
+ {0xc0e78000}, {0xc0e7a000}, {0xc0e7c000}, {0xc0e7e000},
+ {0xc0e80000}, {0xc0e82000}, {0xc0e84000}, {0xc0e86000},
+ {0xc0e88000}, {0xc0e8a000}, {0xc0e8c000}, {0xc0e8e000},
+ {0xc0e90000}, {0xc0e92000}, {0xc0e94000}, {0xc0e96000},
+ {0xc0e98000}, {0xc0e9a000}, {0xc0e9c000}, {0xc0e9e000},
+ {0xc0ea0000}, {0xc0ea2000}, {0xc0ea4000}, {0xc0ea6000},
+ {0xc0ea8000}, {0xc0eaa000}, {0xc0eac000}, {0xc0eae000},
+ {0xc0eb0000}, {0xc0eb2000}, {0xc0eb4000}, {0xc0eb6000},
+ {0xc0eb8000}, {0xc0eba000}, {0xc0ebc000}, {0xc0ebe000},
+ {0xc0ec0000}, {0xc0ec2000}, {0xc0ec4000}, {0xc0ec6000},
+ {0xc0ec8000}, {0xc0eca000}, {0xc0ecc000}, {0xc0ece000},
+ {0xc0ed0000}, {0xc0ed2000}, {0xc0ed4000}, {0xc0ed6000},
+ {0xc0ed8000}, {0xc0eda000}, {0xc0edc000}, {0xc0ede000},
+ {0xc0ee0000}, {0xc0ee2000}, {0xc0ee4000}, {0xc0ee6000},
+ {0xc0ee8000}, {0xc0eea000}, {0xc0eec000}, {0xc0eee000},
+ {0xc0ef0000}, {0xc0ef2000}, {0xc0ef4000}, {0xc0ef6000},
+ {0xc0ef8000}, {0xc0efa000}, {0xc0efc000}, {0xc0efe000},
+ {0xc0f00000}, {0xc0f02000}, {0xc0f04000}, {0xc0f06000},
+ {0xc0f08000}, {0xc0f0a000}, {0xc0f0c000}, {0xc0f0e000},
+ {0xc0f10000}, {0xc0f12000}, {0xc0f14000}, {0xc0f16000},
+ {0xc0f18000}, {0xc0f1a000}, {0xc0f1c000}, {0xc0f1e000},
+ {0xc0f20000}, {0xc0f22000}, {0xc0f24000}, {0xc0f26000},
+ {0xc0f28000}, {0xc0f2a000}, {0xc0f2c000}, {0xc0f2e000},
+ {0xc0f30000}, {0xc0f32000}, {0xc0f34000}, {0xc0f36000},
+ {0xc0f38000}, {0xc0f3a000}, {0xc0f3c000}, {0xc0f3e000},
+ {0xc0f40000}, {0xc0f42000}, {0xc0f44000}, {0xc0f46000},
+ {0xc0f48000}, {0xc0f4a000}, {0xc0f4c000}, {0xc0f4e000},
+ {0xc0f50000}, {0xc0f52000}, {0xc0f54000}, {0xc0f56000},
+ {0xc0f58000}, {0xc0f5a000}, {0xc0f5c000}, {0xc0f5e000},
+ {0xc0f60000}, {0xc0f62000}, {0xc0f64000}, {0xc0f66000},
+ {0xc0f68000}, {0xc0f6a000}, {0xc0f6c000}, {0xc0f6e000},
+ {0xc0f70000}, {0xc0f72000}, {0xc0f74000}, {0xc0f76000},
+ {0xc0f78000}, {0xc0f7a000}, {0xc0f7c000}, {0xc0f7e000},
+ {0xc0f80000}, {0xc0f82000}, {0xc0f84000}, {0xc0f86000},
+ {0xc0f88000}, {0xc0f8a000}, {0xc0f8c000}, {0xc0f8e000},
+ {0xc0f90000}, {0xc0f92000}, {0xc0f94000}, {0xc0f96000},
+ {0xc0f98000}, {0xc0f9a000}, {0xc0f9c000}, {0xc0f9e000},
+ {0xc0fa0000}, {0xc0fa2000}, {0xc0fa4000}, {0xc0fa6000},
+ {0xc0fa8000}, {0xc0faa000}, {0xc0fac000}, {0xc0fae000},
+ {0xc0fb0000}, {0xc0fb2000}, {0xc0fb4000}, {0xc0fb6000},
+ {0xc0fb8000}, {0xc0fba000}, {0xc0fbc000}, {0xc0fbe000},
+ {0xc0fc0000}, {0xc0fc2000}, {0xc0fc4000}, {0xc0fc6000},
+ {0xc0fc8000}, {0xc0fca000}, {0xc0fcc000}, {0xc0fce000},
+ {0xc0fd0000}, {0xc0fd2000}, {0xc0fd4000}, {0xc0fd6000},
+ {0xc0fd8000}, {0xc0fda000}, {0xc0fdc000}, {0xc0fde000},
+ {0xc0fe0000}, {0xc0fe2000}, {0xc0fe4000}, {0xc0fe6000},
+ {0xc0fe8000}, {0xc0fea000}, {0xc0fec000}, {0xc0fee000},
+ {0xc0ff0000}, {0xc0ff2000}, {0xc0ff4000}, {0xc0ff6000},
+ {0xc0ff8000}, {0xc0ffa000}, {0xc0ffc000}, {0xc0ffe000},
+ {0xc1000000}, {0xc1002000}, {0xc1004000}, {0xc1006000},
+ {0xc1008000}, {0xc100a000}, {0xc100c000}, {0xc100e000},
+ {0xc1010000}, {0xc1012000}, {0xc1014000}, {0xc1016000},
+ {0xc1018000}, {0xc101a000}, {0xc101c000}, {0xc101e000},
+ {0xc1020000}, {0xc1022000}, {0xc1024000}, {0xc1026000},
+ {0xc1028000}, {0xc102a000}, {0xc102c000}, {0xc102e000},
+ {0xc1030000}, {0xc1032000}, {0xc1034000}, {0xc1036000},
+ {0xc1038000}, {0xc103a000}, {0xc103c000}, {0xc103e000},
+ {0xc1040000}, {0xc1042000}, {0xc1044000}, {0xc1046000},
+ {0xc1048000}, {0xc104a000}, {0xc104c000}, {0xc104e000},
+ {0xc1050000}, {0xc1052000}, {0xc1054000}, {0xc1056000},
+ {0xc1058000}, {0xc105a000}, {0xc105c000}, {0xc105e000},
+ {0xc1060000}, {0xc1062000}, {0xc1064000}, {0xc1066000},
+ {0xc1068000}, {0xc106a000}, {0xc106c000}, {0xc106e000},
+ {0xc1070000}, {0xc1072000}, {0xc1074000}, {0xc1076000},
+ {0xc1078000}, {0xc107a000}, {0xc107c000}, {0xc107e000},
+ {0xc1080000}, {0xc1082000}, {0xc1084000}, {0xc1086000},
+ {0xc1088000}, {0xc108a000}, {0xc108c000}, {0xc108e000},
+ {0xc1090000}, {0xc1092000}, {0xc1094000}, {0xc1096000},
+ {0xc1098000}, {0xc109a000}, {0xc109c000}, {0xc109e000},
+ {0xc10a0000}, {0xc10a2000}, {0xc10a4000}, {0xc10a6000},
+ {0xc10a8000}, {0xc10aa000}, {0xc10ac000}, {0xc10ae000},
+ {0xc10b0000}, {0xc10b2000}, {0xc10b4000}, {0xc10b6000},
+ {0xc10b8000}, {0xc10ba000}, {0xc10bc000}, {0xc10be000},
+ {0xc10c0000}, {0xc10c2000}, {0xc10c4000}, {0xc10c6000},
+ {0xc10c8000}, {0xc10ca000}, {0xc10cc000}, {0xc10ce000},
+ {0xc10d0000}, {0xc10d2000}, {0xc10d4000}, {0xc10d6000},
+ {0xc10d8000}, {0xc10da000}, {0xc10dc000}, {0xc10de000},
+ {0xc10e0000}, {0xc10e2000}, {0xc10e4000}, {0xc10e6000},
+ {0xc10e8000}, {0xc10ea000}, {0xc10ec000}, {0xc10ee000},
+ {0xc10f0000}, {0xc10f2000}, {0xc10f4000}, {0xc10f6000},
+ {0xc10f8000}, {0xc10fa000}, {0xc10fc000}, {0xc10fe000},
+ {0xc1100000}, {0xc1102000}, {0xc1104000}, {0xc1106000},
+ {0xc1108000}, {0xc110a000}, {0xc110c000}, {0xc110e000},
+ {0xc1110000}, {0xc1112000}, {0xc1114000}, {0xc1116000},
+ {0xc1118000}, {0xc111a000}, {0xc111c000}, {0xc111e000},
+ {0xc1120000}, {0xc1122000}, {0xc1124000}, {0xc1126000},
+ {0xc1128000}, {0xc112a000}, {0xc112c000}, {0xc112e000},
+ {0xc1130000}, {0xc1132000}, {0xc1134000}, {0xc1136000},
+ {0xc1138000}, {0xc113a000}, {0xc113c000}, {0xc113e000},
+ {0xc1140000}, {0xc1142000}, {0xc1144000}, {0xc1146000},
+ {0xc1148000}, {0xc114a000}, {0xc114c000}, {0xc114e000},
+ {0xc1150000}, {0xc1152000}, {0xc1154000}, {0xc1156000},
+ {0xc1158000}, {0xc115a000}, {0xc115c000}, {0xc115e000},
+ {0xc1160000}, {0xc1162000}, {0xc1164000}, {0xc1166000},
+ {0xc1168000}, {0xc116a000}, {0xc116c000}, {0xc116e000},
+ {0xc1170000}, {0xc1172000}, {0xc1174000}, {0xc1176000},
+ {0xc1178000}, {0xc117a000}, {0xc117c000}, {0xc117e000},
+ {0xc1180000}, {0xc1182000}, {0xc1184000}, {0xc1186000},
+ {0xc1188000}, {0xc118a000}, {0xc118c000}, {0xc118e000},
+ {0xc1190000}, {0xc1192000}, {0xc1194000}, {0xc1196000},
+ {0xc1198000}, {0xc119a000}, {0xc119c000}, {0xc119e000},
+ {0xc11a0000}, {0xc11a2000}, {0xc11a4000}, {0xc11a6000},
+ {0xc11a8000}, {0xc11aa000}, {0xc11ac000}, {0xc11ae000},
+ {0xc11b0000}, {0xc11b2000}, {0xc11b4000}, {0xc11b6000},
+ {0xc11b8000}, {0xc11ba000}, {0xc11bc000}, {0xc11be000},
+ {0xc11c0000}, {0xc11c2000}, {0xc11c4000}, {0xc11c6000},
+ {0xc11c8000}, {0xc11ca000}, {0xc11cc000}, {0xc11ce000},
+ {0xc11d0000}, {0xc11d2000}, {0xc11d4000}, {0xc11d6000},
+ {0xc11d8000}, {0xc11da000}, {0xc11dc000}, {0xc11de000},
+ {0xc11e0000}, {0xc11e2000}, {0xc11e4000}, {0xc11e6000},
+ {0xc11e8000}, {0xc11ea000}, {0xc11ec000}, {0xc11ee000},
+ {0xc11f0000}, {0xc11f2000}, {0xc11f4000}, {0xc11f6000},
+ {0xc11f8000}, {0xc11fa000}, {0xc11fc000}, {0xc11fe000},
+ {0xc1200000}, {0xc1202000}, {0xc1204000}, {0xc1206000},
+ {0xc1208000}, {0xc120a000}, {0xc120c000}, {0xc120e000},
+ {0xc1210000}, {0xc1212000}, {0xc1214000}, {0xc1216000},
+ {0xc1218000}, {0xc121a000}, {0xc121c000}, {0xc121e000},
+ {0xc1220000}, {0xc1222000}, {0xc1224000}, {0xc1226000},
+ {0xc1228000}, {0xc122a000}, {0xc122c000}, {0xc122e000},
+ {0xc1230000}, {0xc1232000}, {0xc1234000}, {0xc1236000},
+ {0xc1238000}, {0xc123a000}, {0xc123c000}, {0xc123e000},
+ {0xc1240000}, {0xc1242000}, {0xc1244000}, {0xc1246000},
+ {0xc1248000}, {0xc124a000}, {0xc124c000}, {0xc124e000},
+ {0xc1250000}, {0xc1252000}, {0xc1254000}, {0xc1256000},
+ {0xc1258000}, {0xc125a000}, {0xc125c000}, {0xc125e000},
+ {0xc1260000}, {0xc1262000}, {0xc1264000}, {0xc1266000},
+ {0xc1268000}, {0xc126a000}, {0xc126c000}, {0xc126e000},
+ {0xc1270000}, {0xc1272000}, {0xc1274000}, {0xc1276000},
+ {0xc1278000}, {0xc127a000}, {0xc127c000}, {0xc127e000},
+ {0xc1280000}, {0xc1282000}, {0xc1284000}, {0xc1286000},
+ {0xc1288000}, {0xc128a000}, {0xc128c000}, {0xc128e000},
+ {0xc1290000}, {0xc1292000}, {0xc1294000}, {0xc1296000},
+ {0xc1298000}, {0xc129a000}, {0xc129c000}, {0xc129e000},
+ {0xc12a0000}, {0xc12a2000}, {0xc12a4000}, {0xc12a6000},
+ {0xc12a8000}, {0xc12aa000}, {0xc12ac000}, {0xc12ae000},
+ {0xc12b0000}, {0xc12b2000}, {0xc12b4000}, {0xc12b6000},
+ {0xc12b8000}, {0xc12ba000}, {0xc12bc000}, {0xc12be000},
+ {0xc12c0000}, {0xc12c2000}, {0xc12c4000}, {0xc12c6000},
+ {0xc12c8000}, {0xc12ca000}, {0xc12cc000}, {0xc12ce000},
+ {0xc12d0000}, {0xc12d2000}, {0xc12d4000}, {0xc12d6000},
+ {0xc12d8000}, {0xc12da000}, {0xc12dc000}, {0xc12de000},
+ {0xc12e0000}, {0xc12e2000}, {0xc12e4000}, {0xc12e6000},
+ {0xc12e8000}, {0xc12ea000}, {0xc12ec000}, {0xc12ee000},
+ {0xc12f0000}, {0xc12f2000}, {0xc12f4000}, {0xc12f6000},
+ {0xc12f8000}, {0xc12fa000}, {0xc12fc000}, {0xc12fe000},
+ {0xc1300000}, {0xc1302000}, {0xc1304000}, {0xc1306000},
+ {0xc1308000}, {0xc130a000}, {0xc130c000}, {0xc130e000},
+ {0xc1310000}, {0xc1312000}, {0xc1314000}, {0xc1316000},
+ {0xc1318000}, {0xc131a000}, {0xc131c000}, {0xc131e000},
+ {0xc1320000}, {0xc1322000}, {0xc1324000}, {0xc1326000},
+ {0xc1328000}, {0xc132a000}, {0xc132c000}, {0xc132e000},
+ {0xc1330000}, {0xc1332000}, {0xc1334000}, {0xc1336000},
+ {0xc1338000}, {0xc133a000}, {0xc133c000}, {0xc133e000},
+ {0xc1340000}, {0xc1342000}, {0xc1344000}, {0xc1346000},
+ {0xc1348000}, {0xc134a000}, {0xc134c000}, {0xc134e000},
+ {0xc1350000}, {0xc1352000}, {0xc1354000}, {0xc1356000},
+ {0xc1358000}, {0xc135a000}, {0xc135c000}, {0xc135e000},
+ {0xc1360000}, {0xc1362000}, {0xc1364000}, {0xc1366000},
+ {0xc1368000}, {0xc136a000}, {0xc136c000}, {0xc136e000},
+ {0xc1370000}, {0xc1372000}, {0xc1374000}, {0xc1376000},
+ {0xc1378000}, {0xc137a000}, {0xc137c000}, {0xc137e000},
+ {0xc1380000}, {0xc1382000}, {0xc1384000}, {0xc1386000},
+ {0xc1388000}, {0xc138a000}, {0xc138c000}, {0xc138e000},
+ {0xc1390000}, {0xc1392000}, {0xc1394000}, {0xc1396000},
+ {0xc1398000}, {0xc139a000}, {0xc139c000}, {0xc139e000},
+ {0xc13a0000}, {0xc13a2000}, {0xc13a4000}, {0xc13a6000},
+ {0xc13a8000}, {0xc13aa000}, {0xc13ac000}, {0xc13ae000},
+ {0xc13b0000}, {0xc13b2000}, {0xc13b4000}, {0xc13b6000},
+ {0xc13b8000}, {0xc13ba000}, {0xc13bc000}, {0xc13be000},
+ {0xc13c0000}, {0xc13c2000}, {0xc13c4000}, {0xc13c6000},
+ {0xc13c8000}, {0xc13ca000}, {0xc13cc000}, {0xc13ce000},
+ {0xc13d0000}, {0xc13d2000}, {0xc13d4000}, {0xc13d6000},
+ {0xc13d8000}, {0xc13da000}, {0xc13dc000}, {0xc13de000},
+ {0xc13e0000}, {0xc13e2000}, {0xc13e4000}, {0xc13e6000},
+ {0xc13e8000}, {0xc13ea000}, {0xc13ec000}, {0xc13ee000},
+ {0xc13f0000}, {0xc13f2000}, {0xc13f4000}, {0xc13f6000},
+ {0xc13f8000}, {0xc13fa000}, {0xc13fc000}, {0xc13fe000},
+ {0xc1400000}, {0xc1402000}, {0xc1404000}, {0xc1406000},
+ {0xc1408000}, {0xc140a000}, {0xc140c000}, {0xc140e000},
+ {0xc1410000}, {0xc1412000}, {0xc1414000}, {0xc1416000},
+ {0xc1418000}, {0xc141a000}, {0xc141c000}, {0xc141e000},
+ {0xc1420000}, {0xc1422000}, {0xc1424000}, {0xc1426000},
+ {0xc1428000}, {0xc142a000}, {0xc142c000}, {0xc142e000},
+ {0xc1430000}, {0xc1432000}, {0xc1434000}, {0xc1436000},
+ {0xc1438000}, {0xc143a000}, {0xc143c000}, {0xc143e000},
+ {0xc1440000}, {0xc1442000}, {0xc1444000}, {0xc1446000},
+ {0xc1448000}, {0xc144a000}, {0xc144c000}, {0xc144e000},
+ {0xc1450000}, {0xc1452000}, {0xc1454000}, {0xc1456000},
+ {0xc1458000}, {0xc145a000}, {0xc145c000}, {0xc145e000},
+ {0xc1460000}, {0xc1462000}, {0xc1464000}, {0xc1466000},
+ {0xc1468000}, {0xc146a000}, {0xc146c000}, {0xc146e000},
+ {0xc1470000}, {0xc1472000}, {0xc1474000}, {0xc1476000},
+ {0xc1478000}, {0xc147a000}, {0xc147c000}, {0xc147e000},
+ {0xc1480000}, {0xc1482000}, {0xc1484000}, {0xc1486000},
+ {0xc1488000}, {0xc148a000}, {0xc148c000}, {0xc148e000},
+ {0xc1490000}, {0xc1492000}, {0xc1494000}, {0xc1496000},
+ {0xc1498000}, {0xc149a000}, {0xc149c000}, {0xc149e000},
+ {0xc14a0000}, {0xc14a2000}, {0xc14a4000}, {0xc14a6000},
+ {0xc14a8000}, {0xc14aa000}, {0xc14ac000}, {0xc14ae000},
+ {0xc14b0000}, {0xc14b2000}, {0xc14b4000}, {0xc14b6000},
+ {0xc14b8000}, {0xc14ba000}, {0xc14bc000}, {0xc14be000},
+ {0xc14c0000}, {0xc14c2000}, {0xc14c4000}, {0xc14c6000},
+ {0xc14c8000}, {0xc14ca000}, {0xc14cc000}, {0xc14ce000},
+ {0xc14d0000}, {0xc14d2000}, {0xc14d4000}, {0xc14d6000},
+ {0xc14d8000}, {0xc14da000}, {0xc14dc000}, {0xc14de000},
+ {0xc14e0000}, {0xc14e2000}, {0xc14e4000}, {0xc14e6000},
+ {0xc14e8000}, {0xc14ea000}, {0xc14ec000}, {0xc14ee000},
+ {0xc14f0000}, {0xc14f2000}, {0xc14f4000}, {0xc14f6000},
+ {0xc14f8000}, {0xc14fa000}, {0xc14fc000}, {0xc14fe000},
+ {0xc1500000}, {0xc1502000}, {0xc1504000}, {0xc1506000},
+ {0xc1508000}, {0xc150a000}, {0xc150c000}, {0xc150e000},
+ {0xc1510000}, {0xc1512000}, {0xc1514000}, {0xc1516000},
+ {0xc1518000}, {0xc151a000}, {0xc151c000}, {0xc151e000},
+ {0xc1520000}, {0xc1522000}, {0xc1524000}, {0xc1526000},
+ {0xc1528000}, {0xc152a000}, {0xc152c000}, {0xc152e000},
+ {0xc1530000}, {0xc1532000}, {0xc1534000}, {0xc1536000},
+ {0xc1538000}, {0xc153a000}, {0xc153c000}, {0xc153e000},
+ {0xc1540000}, {0xc1542000}, {0xc1544000}, {0xc1546000},
+ {0xc1548000}, {0xc154a000}, {0xc154c000}, {0xc154e000},
+ {0xc1550000}, {0xc1552000}, {0xc1554000}, {0xc1556000},
+ {0xc1558000}, {0xc155a000}, {0xc155c000}, {0xc155e000},
+ {0xc1560000}, {0xc1562000}, {0xc1564000}, {0xc1566000},
+ {0xc1568000}, {0xc156a000}, {0xc156c000}, {0xc156e000},
+ {0xc1570000}, {0xc1572000}, {0xc1574000}, {0xc1576000},
+ {0xc1578000}, {0xc157a000}, {0xc157c000}, {0xc157e000},
+ {0xc1580000}, {0xc1582000}, {0xc1584000}, {0xc1586000},
+ {0xc1588000}, {0xc158a000}, {0xc158c000}, {0xc158e000},
+ {0xc1590000}, {0xc1592000}, {0xc1594000}, {0xc1596000},
+ {0xc1598000}, {0xc159a000}, {0xc159c000}, {0xc159e000},
+ {0xc15a0000}, {0xc15a2000}, {0xc15a4000}, {0xc15a6000},
+ {0xc15a8000}, {0xc15aa000}, {0xc15ac000}, {0xc15ae000},
+ {0xc15b0000}, {0xc15b2000}, {0xc15b4000}, {0xc15b6000},
+ {0xc15b8000}, {0xc15ba000}, {0xc15bc000}, {0xc15be000},
+ {0xc15c0000}, {0xc15c2000}, {0xc15c4000}, {0xc15c6000},
+ {0xc15c8000}, {0xc15ca000}, {0xc15cc000}, {0xc15ce000},
+ {0xc15d0000}, {0xc15d2000}, {0xc15d4000}, {0xc15d6000},
+ {0xc15d8000}, {0xc15da000}, {0xc15dc000}, {0xc15de000},
+ {0xc15e0000}, {0xc15e2000}, {0xc15e4000}, {0xc15e6000},
+ {0xc15e8000}, {0xc15ea000}, {0xc15ec000}, {0xc15ee000},
+ {0xc15f0000}, {0xc15f2000}, {0xc15f4000}, {0xc15f6000},
+ {0xc15f8000}, {0xc15fa000}, {0xc15fc000}, {0xc15fe000},
+ {0xc1600000}, {0xc1602000}, {0xc1604000}, {0xc1606000},
+ {0xc1608000}, {0xc160a000}, {0xc160c000}, {0xc160e000},
+ {0xc1610000}, {0xc1612000}, {0xc1614000}, {0xc1616000},
+ {0xc1618000}, {0xc161a000}, {0xc161c000}, {0xc161e000},
+ {0xc1620000}, {0xc1622000}, {0xc1624000}, {0xc1626000},
+ {0xc1628000}, {0xc162a000}, {0xc162c000}, {0xc162e000},
+ {0xc1630000}, {0xc1632000}, {0xc1634000}, {0xc1636000},
+ {0xc1638000}, {0xc163a000}, {0xc163c000}, {0xc163e000},
+ {0xc1640000}, {0xc1642000}, {0xc1644000}, {0xc1646000},
+ {0xc1648000}, {0xc164a000}, {0xc164c000}, {0xc164e000},
+ {0xc1650000}, {0xc1652000}, {0xc1654000}, {0xc1656000},
+ {0xc1658000}, {0xc165a000}, {0xc165c000}, {0xc165e000},
+ {0xc1660000}, {0xc1662000}, {0xc1664000}, {0xc1666000},
+ {0xc1668000}, {0xc166a000}, {0xc166c000}, {0xc166e000},
+ {0xc1670000}, {0xc1672000}, {0xc1674000}, {0xc1676000},
+ {0xc1678000}, {0xc167a000}, {0xc167c000}, {0xc167e000},
+ {0xc1680000}, {0xc1682000}, {0xc1684000}, {0xc1686000},
+ {0xc1688000}, {0xc168a000}, {0xc168c000}, {0xc168e000},
+ {0xc1690000}, {0xc1692000}, {0xc1694000}, {0xc1696000},
+ {0xc1698000}, {0xc169a000}, {0xc169c000}, {0xc169e000},
+ {0xc16a0000}, {0xc16a2000}, {0xc16a4000}, {0xc16a6000},
+ {0xc16a8000}, {0xc16aa000}, {0xc16ac000}, {0xc16ae000},
+ {0xc16b0000}, {0xc16b2000}, {0xc16b4000}, {0xc16b6000},
+ {0xc16b8000}, {0xc16ba000}, {0xc16bc000}, {0xc16be000},
+ {0xc16c0000}, {0xc16c2000}, {0xc16c4000}, {0xc16c6000},
+ {0xc16c8000}, {0xc16ca000}, {0xc16cc000}, {0xc16ce000},
+ {0xc16d0000}, {0xc16d2000}, {0xc16d4000}, {0xc16d6000},
+ {0xc16d8000}, {0xc16da000}, {0xc16dc000}, {0xc16de000},
+ {0xc16e0000}, {0xc16e2000}, {0xc16e4000}, {0xc16e6000},
+ {0xc16e8000}, {0xc16ea000}, {0xc16ec000}, {0xc16ee000},
+ {0xc16f0000}, {0xc16f2000}, {0xc16f4000}, {0xc16f6000},
+ {0xc16f8000}, {0xc16fa000}, {0xc16fc000}, {0xc16fe000},
+ {0xc1700000}, {0xc1702000}, {0xc1704000}, {0xc1706000},
+ {0xc1708000}, {0xc170a000}, {0xc170c000}, {0xc170e000},
+ {0xc1710000}, {0xc1712000}, {0xc1714000}, {0xc1716000},
+ {0xc1718000}, {0xc171a000}, {0xc171c000}, {0xc171e000},
+ {0xc1720000}, {0xc1722000}, {0xc1724000}, {0xc1726000},
+ {0xc1728000}, {0xc172a000}, {0xc172c000}, {0xc172e000},
+ {0xc1730000}, {0xc1732000}, {0xc1734000}, {0xc1736000},
+ {0xc1738000}, {0xc173a000}, {0xc173c000}, {0xc173e000},
+ {0xc1740000}, {0xc1742000}, {0xc1744000}, {0xc1746000},
+ {0xc1748000}, {0xc174a000}, {0xc174c000}, {0xc174e000},
+ {0xc1750000}, {0xc1752000}, {0xc1754000}, {0xc1756000},
+ {0xc1758000}, {0xc175a000}, {0xc175c000}, {0xc175e000},
+ {0xc1760000}, {0xc1762000}, {0xc1764000}, {0xc1766000},
+ {0xc1768000}, {0xc176a000}, {0xc176c000}, {0xc176e000},
+ {0xc1770000}, {0xc1772000}, {0xc1774000}, {0xc1776000},
+ {0xc1778000}, {0xc177a000}, {0xc177c000}, {0xc177e000},
+ {0xc1780000}, {0xc1782000}, {0xc1784000}, {0xc1786000},
+ {0xc1788000}, {0xc178a000}, {0xc178c000}, {0xc178e000},
+ {0xc1790000}, {0xc1792000}, {0xc1794000}, {0xc1796000},
+ {0xc1798000}, {0xc179a000}, {0xc179c000}, {0xc179e000},
+ {0xc17a0000}, {0xc17a2000}, {0xc17a4000}, {0xc17a6000},
+ {0xc17a8000}, {0xc17aa000}, {0xc17ac000}, {0xc17ae000},
+ {0xc17b0000}, {0xc17b2000}, {0xc17b4000}, {0xc17b6000},
+ {0xc17b8000}, {0xc17ba000}, {0xc17bc000}, {0xc17be000},
+ {0xc17c0000}, {0xc17c2000}, {0xc17c4000}, {0xc17c6000},
+ {0xc17c8000}, {0xc17ca000}, {0xc17cc000}, {0xc17ce000},
+ {0xc17d0000}, {0xc17d2000}, {0xc17d4000}, {0xc17d6000},
+ {0xc17d8000}, {0xc17da000}, {0xc17dc000}, {0xc17de000},
+ {0xc17e0000}, {0xc17e2000}, {0xc17e4000}, {0xc17e6000},
+ {0xc17e8000}, {0xc17ea000}, {0xc17ec000}, {0xc17ee000},
+ {0xc17f0000}, {0xc17f2000}, {0xc17f4000}, {0xc17f6000},
+ {0xc17f8000}, {0xc17fa000}, {0xc17fc000}, {0xc17fe000},
+ {0xc1800000}, {0xc1802000}, {0xc1804000}, {0xc1806000},
+ {0xc1808000}, {0xc180a000}, {0xc180c000}, {0xc180e000},
+ {0xc1810000}, {0xc1812000}, {0xc1814000}, {0xc1816000},
+ {0xc1818000}, {0xc181a000}, {0xc181c000}, {0xc181e000},
+ {0xc1820000}, {0xc1822000}, {0xc1824000}, {0xc1826000},
+ {0xc1828000}, {0xc182a000}, {0xc182c000}, {0xc182e000},
+ {0xc1830000}, {0xc1832000}, {0xc1834000}, {0xc1836000},
+ {0xc1838000}, {0xc183a000}, {0xc183c000}, {0xc183e000},
+ {0xc1840000}, {0xc1842000}, {0xc1844000}, {0xc1846000},
+ {0xc1848000}, {0xc184a000}, {0xc184c000}, {0xc184e000},
+ {0xc1850000}, {0xc1852000}, {0xc1854000}, {0xc1856000},
+ {0xc1858000}, {0xc185a000}, {0xc185c000}, {0xc185e000},
+ {0xc1860000}, {0xc1862000}, {0xc1864000}, {0xc1866000},
+ {0xc1868000}, {0xc186a000}, {0xc186c000}, {0xc186e000},
+ {0xc1870000}, {0xc1872000}, {0xc1874000}, {0xc1876000},
+ {0xc1878000}, {0xc187a000}, {0xc187c000}, {0xc187e000},
+ {0xc1880000}, {0xc1882000}, {0xc1884000}, {0xc1886000},
+ {0xc1888000}, {0xc188a000}, {0xc188c000}, {0xc188e000},
+ {0xc1890000}, {0xc1892000}, {0xc1894000}, {0xc1896000},
+ {0xc1898000}, {0xc189a000}, {0xc189c000}, {0xc189e000},
+ {0xc18a0000}, {0xc18a2000}, {0xc18a4000}, {0xc18a6000},
+ {0xc18a8000}, {0xc18aa000}, {0xc18ac000}, {0xc18ae000},
+ {0xc18b0000}, {0xc18b2000}, {0xc18b4000}, {0xc18b6000},
+ {0xc18b8000}, {0xc18ba000}, {0xc18bc000}, {0xc18be000},
+ {0xc18c0000}, {0xc18c2000}, {0xc18c4000}, {0xc18c6000},
+ {0xc18c8000}, {0xc18ca000}, {0xc18cc000}, {0xc18ce000},
+ {0xc18d0000}, {0xc18d2000}, {0xc18d4000}, {0xc18d6000},
+ {0xc18d8000}, {0xc18da000}, {0xc18dc000}, {0xc18de000},
+ {0xc18e0000}, {0xc18e2000}, {0xc18e4000}, {0xc18e6000},
+ {0xc18e8000}, {0xc18ea000}, {0xc18ec000}, {0xc18ee000},
+ {0xc18f0000}, {0xc18f2000}, {0xc18f4000}, {0xc18f6000},
+ {0xc18f8000}, {0xc18fa000}, {0xc18fc000}, {0xc18fe000},
+ {0xc1900000}, {0xc1902000}, {0xc1904000}, {0xc1906000},
+ {0xc1908000}, {0xc190a000}, {0xc190c000}, {0xc190e000},
+ {0xc1910000}, {0xc1912000}, {0xc1914000}, {0xc1916000},
+ {0xc1918000}, {0xc191a000}, {0xc191c000}, {0xc191e000},
+ {0xc1920000}, {0xc1922000}, {0xc1924000}, {0xc1926000},
+ {0xc1928000}, {0xc192a000}, {0xc192c000}, {0xc192e000},
+ {0xc1930000}, {0xc1932000}, {0xc1934000}, {0xc1936000},
+ {0xc1938000}, {0xc193a000}, {0xc193c000}, {0xc193e000},
+ {0xc1940000}, {0xc1942000}, {0xc1944000}, {0xc1946000},
+ {0xc1948000}, {0xc194a000}, {0xc194c000}, {0xc194e000},
+ {0xc1950000}, {0xc1952000}, {0xc1954000}, {0xc1956000},
+ {0xc1958000}, {0xc195a000}, {0xc195c000}, {0xc195e000},
+ {0xc1960000}, {0xc1962000}, {0xc1964000}, {0xc1966000},
+ {0xc1968000}, {0xc196a000}, {0xc196c000}, {0xc196e000},
+ {0xc1970000}, {0xc1972000}, {0xc1974000}, {0xc1976000},
+ {0xc1978000}, {0xc197a000}, {0xc197c000}, {0xc197e000},
+ {0xc1980000}, {0xc1982000}, {0xc1984000}, {0xc1986000},
+ {0xc1988000}, {0xc198a000}, {0xc198c000}, {0xc198e000},
+ {0xc1990000}, {0xc1992000}, {0xc1994000}, {0xc1996000},
+ {0xc1998000}, {0xc199a000}, {0xc199c000}, {0xc199e000},
+ {0xc19a0000}, {0xc19a2000}, {0xc19a4000}, {0xc19a6000},
+ {0xc19a8000}, {0xc19aa000}, {0xc19ac000}, {0xc19ae000},
+ {0xc19b0000}, {0xc19b2000}, {0xc19b4000}, {0xc19b6000},
+ {0xc19b8000}, {0xc19ba000}, {0xc19bc000}, {0xc19be000},
+ {0xc19c0000}, {0xc19c2000}, {0xc19c4000}, {0xc19c6000},
+ {0xc19c8000}, {0xc19ca000}, {0xc19cc000}, {0xc19ce000},
+ {0xc19d0000}, {0xc19d2000}, {0xc19d4000}, {0xc19d6000},
+ {0xc19d8000}, {0xc19da000}, {0xc19dc000}, {0xc19de000},
+ {0xc19e0000}, {0xc19e2000}, {0xc19e4000}, {0xc19e6000},
+ {0xc19e8000}, {0xc19ea000}, {0xc19ec000}, {0xc19ee000},
+ {0xc19f0000}, {0xc19f2000}, {0xc19f4000}, {0xc19f6000},
+ {0xc19f8000}, {0xc19fa000}, {0xc19fc000}, {0xc19fe000},
+ {0xc1a00000}, {0xc1a02000}, {0xc1a04000}, {0xc1a06000},
+ {0xc1a08000}, {0xc1a0a000}, {0xc1a0c000}, {0xc1a0e000},
+ {0xc1a10000}, {0xc1a12000}, {0xc1a14000}, {0xc1a16000},
+ {0xc1a18000}, {0xc1a1a000}, {0xc1a1c000}, {0xc1a1e000},
+ {0xc1a20000}, {0xc1a22000}, {0xc1a24000}, {0xc1a26000},
+ {0xc1a28000}, {0xc1a2a000}, {0xc1a2c000}, {0xc1a2e000},
+ {0xc1a30000}, {0xc1a32000}, {0xc1a34000}, {0xc1a36000},
+ {0xc1a38000}, {0xc1a3a000}, {0xc1a3c000}, {0xc1a3e000},
+ {0xc1a40000}, {0xc1a42000}, {0xc1a44000}, {0xc1a46000},
+ {0xc1a48000}, {0xc1a4a000}, {0xc1a4c000}, {0xc1a4e000},
+ {0xc1a50000}, {0xc1a52000}, {0xc1a54000}, {0xc1a56000},
+ {0xc1a58000}, {0xc1a5a000}, {0xc1a5c000}, {0xc1a5e000},
+ {0xc1a60000}, {0xc1a62000}, {0xc1a64000}, {0xc1a66000},
+ {0xc1a68000}, {0xc1a6a000}, {0xc1a6c000}, {0xc1a6e000},
+ {0xc1a70000}, {0xc1a72000}, {0xc1a74000}, {0xc1a76000},
+ {0xc1a78000}, {0xc1a7a000}, {0xc1a7c000}, {0xc1a7e000},
+ {0xc1a80000}, {0xc1a82000}, {0xc1a84000}, {0xc1a86000},
+ {0xc1a88000}, {0xc1a8a000}, {0xc1a8c000}, {0xc1a8e000},
+ {0xc1a90000}, {0xc1a92000}, {0xc1a94000}, {0xc1a96000},
+ {0xc1a98000}, {0xc1a9a000}, {0xc1a9c000}, {0xc1a9e000},
+ {0xc1aa0000}, {0xc1aa2000}, {0xc1aa4000}, {0xc1aa6000},
+ {0xc1aa8000}, {0xc1aaa000}, {0xc1aac000}, {0xc1aae000},
+ {0xc1ab0000}, {0xc1ab2000}, {0xc1ab4000}, {0xc1ab6000},
+ {0xc1ab8000}, {0xc1aba000}, {0xc1abc000}, {0xc1abe000},
+ {0xc1ac0000}, {0xc1ac2000}, {0xc1ac4000}, {0xc1ac6000},
+ {0xc1ac8000}, {0xc1aca000}, {0xc1acc000}, {0xc1ace000},
+ {0xc1ad0000}, {0xc1ad2000}, {0xc1ad4000}, {0xc1ad6000},
+ {0xc1ad8000}, {0xc1ada000}, {0xc1adc000}, {0xc1ade000},
+ {0xc1ae0000}, {0xc1ae2000}, {0xc1ae4000}, {0xc1ae6000},
+ {0xc1ae8000}, {0xc1aea000}, {0xc1aec000}, {0xc1aee000},
+ {0xc1af0000}, {0xc1af2000}, {0xc1af4000}, {0xc1af6000},
+ {0xc1af8000}, {0xc1afa000}, {0xc1afc000}, {0xc1afe000},
+ {0xc1b00000}, {0xc1b02000}, {0xc1b04000}, {0xc1b06000},
+ {0xc1b08000}, {0xc1b0a000}, {0xc1b0c000}, {0xc1b0e000},
+ {0xc1b10000}, {0xc1b12000}, {0xc1b14000}, {0xc1b16000},
+ {0xc1b18000}, {0xc1b1a000}, {0xc1b1c000}, {0xc1b1e000},
+ {0xc1b20000}, {0xc1b22000}, {0xc1b24000}, {0xc1b26000},
+ {0xc1b28000}, {0xc1b2a000}, {0xc1b2c000}, {0xc1b2e000},
+ {0xc1b30000}, {0xc1b32000}, {0xc1b34000}, {0xc1b36000},
+ {0xc1b38000}, {0xc1b3a000}, {0xc1b3c000}, {0xc1b3e000},
+ {0xc1b40000}, {0xc1b42000}, {0xc1b44000}, {0xc1b46000},
+ {0xc1b48000}, {0xc1b4a000}, {0xc1b4c000}, {0xc1b4e000},
+ {0xc1b50000}, {0xc1b52000}, {0xc1b54000}, {0xc1b56000},
+ {0xc1b58000}, {0xc1b5a000}, {0xc1b5c000}, {0xc1b5e000},
+ {0xc1b60000}, {0xc1b62000}, {0xc1b64000}, {0xc1b66000},
+ {0xc1b68000}, {0xc1b6a000}, {0xc1b6c000}, {0xc1b6e000},
+ {0xc1b70000}, {0xc1b72000}, {0xc1b74000}, {0xc1b76000},
+ {0xc1b78000}, {0xc1b7a000}, {0xc1b7c000}, {0xc1b7e000},
+ {0xc1b80000}, {0xc1b82000}, {0xc1b84000}, {0xc1b86000},
+ {0xc1b88000}, {0xc1b8a000}, {0xc1b8c000}, {0xc1b8e000},
+ {0xc1b90000}, {0xc1b92000}, {0xc1b94000}, {0xc1b96000},
+ {0xc1b98000}, {0xc1b9a000}, {0xc1b9c000}, {0xc1b9e000},
+ {0xc1ba0000}, {0xc1ba2000}, {0xc1ba4000}, {0xc1ba6000},
+ {0xc1ba8000}, {0xc1baa000}, {0xc1bac000}, {0xc1bae000},
+ {0xc1bb0000}, {0xc1bb2000}, {0xc1bb4000}, {0xc1bb6000},
+ {0xc1bb8000}, {0xc1bba000}, {0xc1bbc000}, {0xc1bbe000},
+ {0xc1bc0000}, {0xc1bc2000}, {0xc1bc4000}, {0xc1bc6000},
+ {0xc1bc8000}, {0xc1bca000}, {0xc1bcc000}, {0xc1bce000},
+ {0xc1bd0000}, {0xc1bd2000}, {0xc1bd4000}, {0xc1bd6000},
+ {0xc1bd8000}, {0xc1bda000}, {0xc1bdc000}, {0xc1bde000},
+ {0xc1be0000}, {0xc1be2000}, {0xc1be4000}, {0xc1be6000},
+ {0xc1be8000}, {0xc1bea000}, {0xc1bec000}, {0xc1bee000},
+ {0xc1bf0000}, {0xc1bf2000}, {0xc1bf4000}, {0xc1bf6000},
+ {0xc1bf8000}, {0xc1bfa000}, {0xc1bfc000}, {0xc1bfe000},
+ {0xc1c00000}, {0xc1c02000}, {0xc1c04000}, {0xc1c06000},
+ {0xc1c08000}, {0xc1c0a000}, {0xc1c0c000}, {0xc1c0e000},
+ {0xc1c10000}, {0xc1c12000}, {0xc1c14000}, {0xc1c16000},
+ {0xc1c18000}, {0xc1c1a000}, {0xc1c1c000}, {0xc1c1e000},
+ {0xc1c20000}, {0xc1c22000}, {0xc1c24000}, {0xc1c26000},
+ {0xc1c28000}, {0xc1c2a000}, {0xc1c2c000}, {0xc1c2e000},
+ {0xc1c30000}, {0xc1c32000}, {0xc1c34000}, {0xc1c36000},
+ {0xc1c38000}, {0xc1c3a000}, {0xc1c3c000}, {0xc1c3e000},
+ {0xc1c40000}, {0xc1c42000}, {0xc1c44000}, {0xc1c46000},
+ {0xc1c48000}, {0xc1c4a000}, {0xc1c4c000}, {0xc1c4e000},
+ {0xc1c50000}, {0xc1c52000}, {0xc1c54000}, {0xc1c56000},
+ {0xc1c58000}, {0xc1c5a000}, {0xc1c5c000}, {0xc1c5e000},
+ {0xc1c60000}, {0xc1c62000}, {0xc1c64000}, {0xc1c66000},
+ {0xc1c68000}, {0xc1c6a000}, {0xc1c6c000}, {0xc1c6e000},
+ {0xc1c70000}, {0xc1c72000}, {0xc1c74000}, {0xc1c76000},
+ {0xc1c78000}, {0xc1c7a000}, {0xc1c7c000}, {0xc1c7e000},
+ {0xc1c80000}, {0xc1c82000}, {0xc1c84000}, {0xc1c86000},
+ {0xc1c88000}, {0xc1c8a000}, {0xc1c8c000}, {0xc1c8e000},
+ {0xc1c90000}, {0xc1c92000}, {0xc1c94000}, {0xc1c96000},
+ {0xc1c98000}, {0xc1c9a000}, {0xc1c9c000}, {0xc1c9e000},
+ {0xc1ca0000}, {0xc1ca2000}, {0xc1ca4000}, {0xc1ca6000},
+ {0xc1ca8000}, {0xc1caa000}, {0xc1cac000}, {0xc1cae000},
+ {0xc1cb0000}, {0xc1cb2000}, {0xc1cb4000}, {0xc1cb6000},
+ {0xc1cb8000}, {0xc1cba000}, {0xc1cbc000}, {0xc1cbe000},
+ {0xc1cc0000}, {0xc1cc2000}, {0xc1cc4000}, {0xc1cc6000},
+ {0xc1cc8000}, {0xc1cca000}, {0xc1ccc000}, {0xc1cce000},
+ {0xc1cd0000}, {0xc1cd2000}, {0xc1cd4000}, {0xc1cd6000},
+ {0xc1cd8000}, {0xc1cda000}, {0xc1cdc000}, {0xc1cde000},
+ {0xc1ce0000}, {0xc1ce2000}, {0xc1ce4000}, {0xc1ce6000},
+ {0xc1ce8000}, {0xc1cea000}, {0xc1cec000}, {0xc1cee000},
+ {0xc1cf0000}, {0xc1cf2000}, {0xc1cf4000}, {0xc1cf6000},
+ {0xc1cf8000}, {0xc1cfa000}, {0xc1cfc000}, {0xc1cfe000},
+ {0xc1d00000}, {0xc1d02000}, {0xc1d04000}, {0xc1d06000},
+ {0xc1d08000}, {0xc1d0a000}, {0xc1d0c000}, {0xc1d0e000},
+ {0xc1d10000}, {0xc1d12000}, {0xc1d14000}, {0xc1d16000},
+ {0xc1d18000}, {0xc1d1a000}, {0xc1d1c000}, {0xc1d1e000},
+ {0xc1d20000}, {0xc1d22000}, {0xc1d24000}, {0xc1d26000},
+ {0xc1d28000}, {0xc1d2a000}, {0xc1d2c000}, {0xc1d2e000},
+ {0xc1d30000}, {0xc1d32000}, {0xc1d34000}, {0xc1d36000},
+ {0xc1d38000}, {0xc1d3a000}, {0xc1d3c000}, {0xc1d3e000},
+ {0xc1d40000}, {0xc1d42000}, {0xc1d44000}, {0xc1d46000},
+ {0xc1d48000}, {0xc1d4a000}, {0xc1d4c000}, {0xc1d4e000},
+ {0xc1d50000}, {0xc1d52000}, {0xc1d54000}, {0xc1d56000},
+ {0xc1d58000}, {0xc1d5a000}, {0xc1d5c000}, {0xc1d5e000},
+ {0xc1d60000}, {0xc1d62000}, {0xc1d64000}, {0xc1d66000},
+ {0xc1d68000}, {0xc1d6a000}, {0xc1d6c000}, {0xc1d6e000},
+ {0xc1d70000}, {0xc1d72000}, {0xc1d74000}, {0xc1d76000},
+ {0xc1d78000}, {0xc1d7a000}, {0xc1d7c000}, {0xc1d7e000},
+ {0xc1d80000}, {0xc1d82000}, {0xc1d84000}, {0xc1d86000},
+ {0xc1d88000}, {0xc1d8a000}, {0xc1d8c000}, {0xc1d8e000},
+ {0xc1d90000}, {0xc1d92000}, {0xc1d94000}, {0xc1d96000},
+ {0xc1d98000}, {0xc1d9a000}, {0xc1d9c000}, {0xc1d9e000},
+ {0xc1da0000}, {0xc1da2000}, {0xc1da4000}, {0xc1da6000},
+ {0xc1da8000}, {0xc1daa000}, {0xc1dac000}, {0xc1dae000},
+ {0xc1db0000}, {0xc1db2000}, {0xc1db4000}, {0xc1db6000},
+ {0xc1db8000}, {0xc1dba000}, {0xc1dbc000}, {0xc1dbe000},
+ {0xc1dc0000}, {0xc1dc2000}, {0xc1dc4000}, {0xc1dc6000},
+ {0xc1dc8000}, {0xc1dca000}, {0xc1dcc000}, {0xc1dce000},
+ {0xc1dd0000}, {0xc1dd2000}, {0xc1dd4000}, {0xc1dd6000},
+ {0xc1dd8000}, {0xc1dda000}, {0xc1ddc000}, {0xc1dde000},
+ {0xc1de0000}, {0xc1de2000}, {0xc1de4000}, {0xc1de6000},
+ {0xc1de8000}, {0xc1dea000}, {0xc1dec000}, {0xc1dee000},
+ {0xc1df0000}, {0xc1df2000}, {0xc1df4000}, {0xc1df6000},
+ {0xc1df8000}, {0xc1dfa000}, {0xc1dfc000}, {0xc1dfe000},
+ {0xc1e00000}, {0xc1e02000}, {0xc1e04000}, {0xc1e06000},
+ {0xc1e08000}, {0xc1e0a000}, {0xc1e0c000}, {0xc1e0e000},
+ {0xc1e10000}, {0xc1e12000}, {0xc1e14000}, {0xc1e16000},
+ {0xc1e18000}, {0xc1e1a000}, {0xc1e1c000}, {0xc1e1e000},
+ {0xc1e20000}, {0xc1e22000}, {0xc1e24000}, {0xc1e26000},
+ {0xc1e28000}, {0xc1e2a000}, {0xc1e2c000}, {0xc1e2e000},
+ {0xc1e30000}, {0xc1e32000}, {0xc1e34000}, {0xc1e36000},
+ {0xc1e38000}, {0xc1e3a000}, {0xc1e3c000}, {0xc1e3e000},
+ {0xc1e40000}, {0xc1e42000}, {0xc1e44000}, {0xc1e46000},
+ {0xc1e48000}, {0xc1e4a000}, {0xc1e4c000}, {0xc1e4e000},
+ {0xc1e50000}, {0xc1e52000}, {0xc1e54000}, {0xc1e56000},
+ {0xc1e58000}, {0xc1e5a000}, {0xc1e5c000}, {0xc1e5e000},
+ {0xc1e60000}, {0xc1e62000}, {0xc1e64000}, {0xc1e66000},
+ {0xc1e68000}, {0xc1e6a000}, {0xc1e6c000}, {0xc1e6e000},
+ {0xc1e70000}, {0xc1e72000}, {0xc1e74000}, {0xc1e76000},
+ {0xc1e78000}, {0xc1e7a000}, {0xc1e7c000}, {0xc1e7e000},
+ {0xc1e80000}, {0xc1e82000}, {0xc1e84000}, {0xc1e86000},
+ {0xc1e88000}, {0xc1e8a000}, {0xc1e8c000}, {0xc1e8e000},
+ {0xc1e90000}, {0xc1e92000}, {0xc1e94000}, {0xc1e96000},
+ {0xc1e98000}, {0xc1e9a000}, {0xc1e9c000}, {0xc1e9e000},
+ {0xc1ea0000}, {0xc1ea2000}, {0xc1ea4000}, {0xc1ea6000},
+ {0xc1ea8000}, {0xc1eaa000}, {0xc1eac000}, {0xc1eae000},
+ {0xc1eb0000}, {0xc1eb2000}, {0xc1eb4000}, {0xc1eb6000},
+ {0xc1eb8000}, {0xc1eba000}, {0xc1ebc000}, {0xc1ebe000},
+ {0xc1ec0000}, {0xc1ec2000}, {0xc1ec4000}, {0xc1ec6000},
+ {0xc1ec8000}, {0xc1eca000}, {0xc1ecc000}, {0xc1ece000},
+ {0xc1ed0000}, {0xc1ed2000}, {0xc1ed4000}, {0xc1ed6000},
+ {0xc1ed8000}, {0xc1eda000}, {0xc1edc000}, {0xc1ede000},
+ {0xc1ee0000}, {0xc1ee2000}, {0xc1ee4000}, {0xc1ee6000},
+ {0xc1ee8000}, {0xc1eea000}, {0xc1eec000}, {0xc1eee000},
+ {0xc1ef0000}, {0xc1ef2000}, {0xc1ef4000}, {0xc1ef6000},
+ {0xc1ef8000}, {0xc1efa000}, {0xc1efc000}, {0xc1efe000},
+ {0xc1f00000}, {0xc1f02000}, {0xc1f04000}, {0xc1f06000},
+ {0xc1f08000}, {0xc1f0a000}, {0xc1f0c000}, {0xc1f0e000},
+ {0xc1f10000}, {0xc1f12000}, {0xc1f14000}, {0xc1f16000},
+ {0xc1f18000}, {0xc1f1a000}, {0xc1f1c000}, {0xc1f1e000},
+ {0xc1f20000}, {0xc1f22000}, {0xc1f24000}, {0xc1f26000},
+ {0xc1f28000}, {0xc1f2a000}, {0xc1f2c000}, {0xc1f2e000},
+ {0xc1f30000}, {0xc1f32000}, {0xc1f34000}, {0xc1f36000},
+ {0xc1f38000}, {0xc1f3a000}, {0xc1f3c000}, {0xc1f3e000},
+ {0xc1f40000}, {0xc1f42000}, {0xc1f44000}, {0xc1f46000},
+ {0xc1f48000}, {0xc1f4a000}, {0xc1f4c000}, {0xc1f4e000},
+ {0xc1f50000}, {0xc1f52000}, {0xc1f54000}, {0xc1f56000},
+ {0xc1f58000}, {0xc1f5a000}, {0xc1f5c000}, {0xc1f5e000},
+ {0xc1f60000}, {0xc1f62000}, {0xc1f64000}, {0xc1f66000},
+ {0xc1f68000}, {0xc1f6a000}, {0xc1f6c000}, {0xc1f6e000},
+ {0xc1f70000}, {0xc1f72000}, {0xc1f74000}, {0xc1f76000},
+ {0xc1f78000}, {0xc1f7a000}, {0xc1f7c000}, {0xc1f7e000},
+ {0xc1f80000}, {0xc1f82000}, {0xc1f84000}, {0xc1f86000},
+ {0xc1f88000}, {0xc1f8a000}, {0xc1f8c000}, {0xc1f8e000},
+ {0xc1f90000}, {0xc1f92000}, {0xc1f94000}, {0xc1f96000},
+ {0xc1f98000}, {0xc1f9a000}, {0xc1f9c000}, {0xc1f9e000},
+ {0xc1fa0000}, {0xc1fa2000}, {0xc1fa4000}, {0xc1fa6000},
+ {0xc1fa8000}, {0xc1faa000}, {0xc1fac000}, {0xc1fae000},
+ {0xc1fb0000}, {0xc1fb2000}, {0xc1fb4000}, {0xc1fb6000},
+ {0xc1fb8000}, {0xc1fba000}, {0xc1fbc000}, {0xc1fbe000},
+ {0xc1fc0000}, {0xc1fc2000}, {0xc1fc4000}, {0xc1fc6000},
+ {0xc1fc8000}, {0xc1fca000}, {0xc1fcc000}, {0xc1fce000},
+ {0xc1fd0000}, {0xc1fd2000}, {0xc1fd4000}, {0xc1fd6000},
+ {0xc1fd8000}, {0xc1fda000}, {0xc1fdc000}, {0xc1fde000},
+ {0xc1fe0000}, {0xc1fe2000}, {0xc1fe4000}, {0xc1fe6000},
+ {0xc1fe8000}, {0xc1fea000}, {0xc1fec000}, {0xc1fee000},
+ {0xc1ff0000}, {0xc1ff2000}, {0xc1ff4000}, {0xc1ff6000},
+ {0xc1ff8000}, {0xc1ffa000}, {0xc1ffc000}, {0xc1ffe000},
+ {0xc2000000}, {0xc2002000}, {0xc2004000}, {0xc2006000},
+ {0xc2008000}, {0xc200a000}, {0xc200c000}, {0xc200e000},
+ {0xc2010000}, {0xc2012000}, {0xc2014000}, {0xc2016000},
+ {0xc2018000}, {0xc201a000}, {0xc201c000}, {0xc201e000},
+ {0xc2020000}, {0xc2022000}, {0xc2024000}, {0xc2026000},
+ {0xc2028000}, {0xc202a000}, {0xc202c000}, {0xc202e000},
+ {0xc2030000}, {0xc2032000}, {0xc2034000}, {0xc2036000},
+ {0xc2038000}, {0xc203a000}, {0xc203c000}, {0xc203e000},
+ {0xc2040000}, {0xc2042000}, {0xc2044000}, {0xc2046000},
+ {0xc2048000}, {0xc204a000}, {0xc204c000}, {0xc204e000},
+ {0xc2050000}, {0xc2052000}, {0xc2054000}, {0xc2056000},
+ {0xc2058000}, {0xc205a000}, {0xc205c000}, {0xc205e000},
+ {0xc2060000}, {0xc2062000}, {0xc2064000}, {0xc2066000},
+ {0xc2068000}, {0xc206a000}, {0xc206c000}, {0xc206e000},
+ {0xc2070000}, {0xc2072000}, {0xc2074000}, {0xc2076000},
+ {0xc2078000}, {0xc207a000}, {0xc207c000}, {0xc207e000},
+ {0xc2080000}, {0xc2082000}, {0xc2084000}, {0xc2086000},
+ {0xc2088000}, {0xc208a000}, {0xc208c000}, {0xc208e000},
+ {0xc2090000}, {0xc2092000}, {0xc2094000}, {0xc2096000},
+ {0xc2098000}, {0xc209a000}, {0xc209c000}, {0xc209e000},
+ {0xc20a0000}, {0xc20a2000}, {0xc20a4000}, {0xc20a6000},
+ {0xc20a8000}, {0xc20aa000}, {0xc20ac000}, {0xc20ae000},
+ {0xc20b0000}, {0xc20b2000}, {0xc20b4000}, {0xc20b6000},
+ {0xc20b8000}, {0xc20ba000}, {0xc20bc000}, {0xc20be000},
+ {0xc20c0000}, {0xc20c2000}, {0xc20c4000}, {0xc20c6000},
+ {0xc20c8000}, {0xc20ca000}, {0xc20cc000}, {0xc20ce000},
+ {0xc20d0000}, {0xc20d2000}, {0xc20d4000}, {0xc20d6000},
+ {0xc20d8000}, {0xc20da000}, {0xc20dc000}, {0xc20de000},
+ {0xc20e0000}, {0xc20e2000}, {0xc20e4000}, {0xc20e6000},
+ {0xc20e8000}, {0xc20ea000}, {0xc20ec000}, {0xc20ee000},
+ {0xc20f0000}, {0xc20f2000}, {0xc20f4000}, {0xc20f6000},
+ {0xc20f8000}, {0xc20fa000}, {0xc20fc000}, {0xc20fe000},
+ {0xc2100000}, {0xc2102000}, {0xc2104000}, {0xc2106000},
+ {0xc2108000}, {0xc210a000}, {0xc210c000}, {0xc210e000},
+ {0xc2110000}, {0xc2112000}, {0xc2114000}, {0xc2116000},
+ {0xc2118000}, {0xc211a000}, {0xc211c000}, {0xc211e000},
+ {0xc2120000}, {0xc2122000}, {0xc2124000}, {0xc2126000},
+ {0xc2128000}, {0xc212a000}, {0xc212c000}, {0xc212e000},
+ {0xc2130000}, {0xc2132000}, {0xc2134000}, {0xc2136000},
+ {0xc2138000}, {0xc213a000}, {0xc213c000}, {0xc213e000},
+ {0xc2140000}, {0xc2142000}, {0xc2144000}, {0xc2146000},
+ {0xc2148000}, {0xc214a000}, {0xc214c000}, {0xc214e000},
+ {0xc2150000}, {0xc2152000}, {0xc2154000}, {0xc2156000},
+ {0xc2158000}, {0xc215a000}, {0xc215c000}, {0xc215e000},
+ {0xc2160000}, {0xc2162000}, {0xc2164000}, {0xc2166000},
+ {0xc2168000}, {0xc216a000}, {0xc216c000}, {0xc216e000},
+ {0xc2170000}, {0xc2172000}, {0xc2174000}, {0xc2176000},
+ {0xc2178000}, {0xc217a000}, {0xc217c000}, {0xc217e000},
+ {0xc2180000}, {0xc2182000}, {0xc2184000}, {0xc2186000},
+ {0xc2188000}, {0xc218a000}, {0xc218c000}, {0xc218e000},
+ {0xc2190000}, {0xc2192000}, {0xc2194000}, {0xc2196000},
+ {0xc2198000}, {0xc219a000}, {0xc219c000}, {0xc219e000},
+ {0xc21a0000}, {0xc21a2000}, {0xc21a4000}, {0xc21a6000},
+ {0xc21a8000}, {0xc21aa000}, {0xc21ac000}, {0xc21ae000},
+ {0xc21b0000}, {0xc21b2000}, {0xc21b4000}, {0xc21b6000},
+ {0xc21b8000}, {0xc21ba000}, {0xc21bc000}, {0xc21be000},
+ {0xc21c0000}, {0xc21c2000}, {0xc21c4000}, {0xc21c6000},
+ {0xc21c8000}, {0xc21ca000}, {0xc21cc000}, {0xc21ce000},
+ {0xc21d0000}, {0xc21d2000}, {0xc21d4000}, {0xc21d6000},
+ {0xc21d8000}, {0xc21da000}, {0xc21dc000}, {0xc21de000},
+ {0xc21e0000}, {0xc21e2000}, {0xc21e4000}, {0xc21e6000},
+ {0xc21e8000}, {0xc21ea000}, {0xc21ec000}, {0xc21ee000},
+ {0xc21f0000}, {0xc21f2000}, {0xc21f4000}, {0xc21f6000},
+ {0xc21f8000}, {0xc21fa000}, {0xc21fc000}, {0xc21fe000},
+ {0xc2200000}, {0xc2202000}, {0xc2204000}, {0xc2206000},
+ {0xc2208000}, {0xc220a000}, {0xc220c000}, {0xc220e000},
+ {0xc2210000}, {0xc2212000}, {0xc2214000}, {0xc2216000},
+ {0xc2218000}, {0xc221a000}, {0xc221c000}, {0xc221e000},
+ {0xc2220000}, {0xc2222000}, {0xc2224000}, {0xc2226000},
+ {0xc2228000}, {0xc222a000}, {0xc222c000}, {0xc222e000},
+ {0xc2230000}, {0xc2232000}, {0xc2234000}, {0xc2236000},
+ {0xc2238000}, {0xc223a000}, {0xc223c000}, {0xc223e000},
+ {0xc2240000}, {0xc2242000}, {0xc2244000}, {0xc2246000},
+ {0xc2248000}, {0xc224a000}, {0xc224c000}, {0xc224e000},
+ {0xc2250000}, {0xc2252000}, {0xc2254000}, {0xc2256000},
+ {0xc2258000}, {0xc225a000}, {0xc225c000}, {0xc225e000},
+ {0xc2260000}, {0xc2262000}, {0xc2264000}, {0xc2266000},
+ {0xc2268000}, {0xc226a000}, {0xc226c000}, {0xc226e000},
+ {0xc2270000}, {0xc2272000}, {0xc2274000}, {0xc2276000},
+ {0xc2278000}, {0xc227a000}, {0xc227c000}, {0xc227e000},
+ {0xc2280000}, {0xc2282000}, {0xc2284000}, {0xc2286000},
+ {0xc2288000}, {0xc228a000}, {0xc228c000}, {0xc228e000},
+ {0xc2290000}, {0xc2292000}, {0xc2294000}, {0xc2296000},
+ {0xc2298000}, {0xc229a000}, {0xc229c000}, {0xc229e000},
+ {0xc22a0000}, {0xc22a2000}, {0xc22a4000}, {0xc22a6000},
+ {0xc22a8000}, {0xc22aa000}, {0xc22ac000}, {0xc22ae000},
+ {0xc22b0000}, {0xc22b2000}, {0xc22b4000}, {0xc22b6000},
+ {0xc22b8000}, {0xc22ba000}, {0xc22bc000}, {0xc22be000},
+ {0xc22c0000}, {0xc22c2000}, {0xc22c4000}, {0xc22c6000},
+ {0xc22c8000}, {0xc22ca000}, {0xc22cc000}, {0xc22ce000},
+ {0xc22d0000}, {0xc22d2000}, {0xc22d4000}, {0xc22d6000},
+ {0xc22d8000}, {0xc22da000}, {0xc22dc000}, {0xc22de000},
+ {0xc22e0000}, {0xc22e2000}, {0xc22e4000}, {0xc22e6000},
+ {0xc22e8000}, {0xc22ea000}, {0xc22ec000}, {0xc22ee000},
+ {0xc22f0000}, {0xc22f2000}, {0xc22f4000}, {0xc22f6000},
+ {0xc22f8000}, {0xc22fa000}, {0xc22fc000}, {0xc22fe000},
+ {0xc2300000}, {0xc2302000}, {0xc2304000}, {0xc2306000},
+ {0xc2308000}, {0xc230a000}, {0xc230c000}, {0xc230e000},
+ {0xc2310000}, {0xc2312000}, {0xc2314000}, {0xc2316000},
+ {0xc2318000}, {0xc231a000}, {0xc231c000}, {0xc231e000},
+ {0xc2320000}, {0xc2322000}, {0xc2324000}, {0xc2326000},
+ {0xc2328000}, {0xc232a000}, {0xc232c000}, {0xc232e000},
+ {0xc2330000}, {0xc2332000}, {0xc2334000}, {0xc2336000},
+ {0xc2338000}, {0xc233a000}, {0xc233c000}, {0xc233e000},
+ {0xc2340000}, {0xc2342000}, {0xc2344000}, {0xc2346000},
+ {0xc2348000}, {0xc234a000}, {0xc234c000}, {0xc234e000},
+ {0xc2350000}, {0xc2352000}, {0xc2354000}, {0xc2356000},
+ {0xc2358000}, {0xc235a000}, {0xc235c000}, {0xc235e000},
+ {0xc2360000}, {0xc2362000}, {0xc2364000}, {0xc2366000},
+ {0xc2368000}, {0xc236a000}, {0xc236c000}, {0xc236e000},
+ {0xc2370000}, {0xc2372000}, {0xc2374000}, {0xc2376000},
+ {0xc2378000}, {0xc237a000}, {0xc237c000}, {0xc237e000},
+ {0xc2380000}, {0xc2382000}, {0xc2384000}, {0xc2386000},
+ {0xc2388000}, {0xc238a000}, {0xc238c000}, {0xc238e000},
+ {0xc2390000}, {0xc2392000}, {0xc2394000}, {0xc2396000},
+ {0xc2398000}, {0xc239a000}, {0xc239c000}, {0xc239e000},
+ {0xc23a0000}, {0xc23a2000}, {0xc23a4000}, {0xc23a6000},
+ {0xc23a8000}, {0xc23aa000}, {0xc23ac000}, {0xc23ae000},
+ {0xc23b0000}, {0xc23b2000}, {0xc23b4000}, {0xc23b6000},
+ {0xc23b8000}, {0xc23ba000}, {0xc23bc000}, {0xc23be000},
+ {0xc23c0000}, {0xc23c2000}, {0xc23c4000}, {0xc23c6000},
+ {0xc23c8000}, {0xc23ca000}, {0xc23cc000}, {0xc23ce000},
+ {0xc23d0000}, {0xc23d2000}, {0xc23d4000}, {0xc23d6000},
+ {0xc23d8000}, {0xc23da000}, {0xc23dc000}, {0xc23de000},
+ {0xc23e0000}, {0xc23e2000}, {0xc23e4000}, {0xc23e6000},
+ {0xc23e8000}, {0xc23ea000}, {0xc23ec000}, {0xc23ee000},
+ {0xc23f0000}, {0xc23f2000}, {0xc23f4000}, {0xc23f6000},
+ {0xc23f8000}, {0xc23fa000}, {0xc23fc000}, {0xc23fe000},
+ {0xc2400000}, {0xc2402000}, {0xc2404000}, {0xc2406000},
+ {0xc2408000}, {0xc240a000}, {0xc240c000}, {0xc240e000},
+ {0xc2410000}, {0xc2412000}, {0xc2414000}, {0xc2416000},
+ {0xc2418000}, {0xc241a000}, {0xc241c000}, {0xc241e000},
+ {0xc2420000}, {0xc2422000}, {0xc2424000}, {0xc2426000},
+ {0xc2428000}, {0xc242a000}, {0xc242c000}, {0xc242e000},
+ {0xc2430000}, {0xc2432000}, {0xc2434000}, {0xc2436000},
+ {0xc2438000}, {0xc243a000}, {0xc243c000}, {0xc243e000},
+ {0xc2440000}, {0xc2442000}, {0xc2444000}, {0xc2446000},
+ {0xc2448000}, {0xc244a000}, {0xc244c000}, {0xc244e000},
+ {0xc2450000}, {0xc2452000}, {0xc2454000}, {0xc2456000},
+ {0xc2458000}, {0xc245a000}, {0xc245c000}, {0xc245e000},
+ {0xc2460000}, {0xc2462000}, {0xc2464000}, {0xc2466000},
+ {0xc2468000}, {0xc246a000}, {0xc246c000}, {0xc246e000},
+ {0xc2470000}, {0xc2472000}, {0xc2474000}, {0xc2476000},
+ {0xc2478000}, {0xc247a000}, {0xc247c000}, {0xc247e000},
+ {0xc2480000}, {0xc2482000}, {0xc2484000}, {0xc2486000},
+ {0xc2488000}, {0xc248a000}, {0xc248c000}, {0xc248e000},
+ {0xc2490000}, {0xc2492000}, {0xc2494000}, {0xc2496000},
+ {0xc2498000}, {0xc249a000}, {0xc249c000}, {0xc249e000},
+ {0xc24a0000}, {0xc24a2000}, {0xc24a4000}, {0xc24a6000},
+ {0xc24a8000}, {0xc24aa000}, {0xc24ac000}, {0xc24ae000},
+ {0xc24b0000}, {0xc24b2000}, {0xc24b4000}, {0xc24b6000},
+ {0xc24b8000}, {0xc24ba000}, {0xc24bc000}, {0xc24be000},
+ {0xc24c0000}, {0xc24c2000}, {0xc24c4000}, {0xc24c6000},
+ {0xc24c8000}, {0xc24ca000}, {0xc24cc000}, {0xc24ce000},
+ {0xc24d0000}, {0xc24d2000}, {0xc24d4000}, {0xc24d6000},
+ {0xc24d8000}, {0xc24da000}, {0xc24dc000}, {0xc24de000},
+ {0xc24e0000}, {0xc24e2000}, {0xc24e4000}, {0xc24e6000},
+ {0xc24e8000}, {0xc24ea000}, {0xc24ec000}, {0xc24ee000},
+ {0xc24f0000}, {0xc24f2000}, {0xc24f4000}, {0xc24f6000},
+ {0xc24f8000}, {0xc24fa000}, {0xc24fc000}, {0xc24fe000},
+ {0xc2500000}, {0xc2502000}, {0xc2504000}, {0xc2506000},
+ {0xc2508000}, {0xc250a000}, {0xc250c000}, {0xc250e000},
+ {0xc2510000}, {0xc2512000}, {0xc2514000}, {0xc2516000},
+ {0xc2518000}, {0xc251a000}, {0xc251c000}, {0xc251e000},
+ {0xc2520000}, {0xc2522000}, {0xc2524000}, {0xc2526000},
+ {0xc2528000}, {0xc252a000}, {0xc252c000}, {0xc252e000},
+ {0xc2530000}, {0xc2532000}, {0xc2534000}, {0xc2536000},
+ {0xc2538000}, {0xc253a000}, {0xc253c000}, {0xc253e000},
+ {0xc2540000}, {0xc2542000}, {0xc2544000}, {0xc2546000},
+ {0xc2548000}, {0xc254a000}, {0xc254c000}, {0xc254e000},
+ {0xc2550000}, {0xc2552000}, {0xc2554000}, {0xc2556000},
+ {0xc2558000}, {0xc255a000}, {0xc255c000}, {0xc255e000},
+ {0xc2560000}, {0xc2562000}, {0xc2564000}, {0xc2566000},
+ {0xc2568000}, {0xc256a000}, {0xc256c000}, {0xc256e000},
+ {0xc2570000}, {0xc2572000}, {0xc2574000}, {0xc2576000},
+ {0xc2578000}, {0xc257a000}, {0xc257c000}, {0xc257e000},
+ {0xc2580000}, {0xc2582000}, {0xc2584000}, {0xc2586000},
+ {0xc2588000}, {0xc258a000}, {0xc258c000}, {0xc258e000},
+ {0xc2590000}, {0xc2592000}, {0xc2594000}, {0xc2596000},
+ {0xc2598000}, {0xc259a000}, {0xc259c000}, {0xc259e000},
+ {0xc25a0000}, {0xc25a2000}, {0xc25a4000}, {0xc25a6000},
+ {0xc25a8000}, {0xc25aa000}, {0xc25ac000}, {0xc25ae000},
+ {0xc25b0000}, {0xc25b2000}, {0xc25b4000}, {0xc25b6000},
+ {0xc25b8000}, {0xc25ba000}, {0xc25bc000}, {0xc25be000},
+ {0xc25c0000}, {0xc25c2000}, {0xc25c4000}, {0xc25c6000},
+ {0xc25c8000}, {0xc25ca000}, {0xc25cc000}, {0xc25ce000},
+ {0xc25d0000}, {0xc25d2000}, {0xc25d4000}, {0xc25d6000},
+ {0xc25d8000}, {0xc25da000}, {0xc25dc000}, {0xc25de000},
+ {0xc25e0000}, {0xc25e2000}, {0xc25e4000}, {0xc25e6000},
+ {0xc25e8000}, {0xc25ea000}, {0xc25ec000}, {0xc25ee000},
+ {0xc25f0000}, {0xc25f2000}, {0xc25f4000}, {0xc25f6000},
+ {0xc25f8000}, {0xc25fa000}, {0xc25fc000}, {0xc25fe000},
+ {0xc2600000}, {0xc2602000}, {0xc2604000}, {0xc2606000},
+ {0xc2608000}, {0xc260a000}, {0xc260c000}, {0xc260e000},
+ {0xc2610000}, {0xc2612000}, {0xc2614000}, {0xc2616000},
+ {0xc2618000}, {0xc261a000}, {0xc261c000}, {0xc261e000},
+ {0xc2620000}, {0xc2622000}, {0xc2624000}, {0xc2626000},
+ {0xc2628000}, {0xc262a000}, {0xc262c000}, {0xc262e000},
+ {0xc2630000}, {0xc2632000}, {0xc2634000}, {0xc2636000},
+ {0xc2638000}, {0xc263a000}, {0xc263c000}, {0xc263e000},
+ {0xc2640000}, {0xc2642000}, {0xc2644000}, {0xc2646000},
+ {0xc2648000}, {0xc264a000}, {0xc264c000}, {0xc264e000},
+ {0xc2650000}, {0xc2652000}, {0xc2654000}, {0xc2656000},
+ {0xc2658000}, {0xc265a000}, {0xc265c000}, {0xc265e000},
+ {0xc2660000}, {0xc2662000}, {0xc2664000}, {0xc2666000},
+ {0xc2668000}, {0xc266a000}, {0xc266c000}, {0xc266e000},
+ {0xc2670000}, {0xc2672000}, {0xc2674000}, {0xc2676000},
+ {0xc2678000}, {0xc267a000}, {0xc267c000}, {0xc267e000},
+ {0xc2680000}, {0xc2682000}, {0xc2684000}, {0xc2686000},
+ {0xc2688000}, {0xc268a000}, {0xc268c000}, {0xc268e000},
+ {0xc2690000}, {0xc2692000}, {0xc2694000}, {0xc2696000},
+ {0xc2698000}, {0xc269a000}, {0xc269c000}, {0xc269e000},
+ {0xc26a0000}, {0xc26a2000}, {0xc26a4000}, {0xc26a6000},
+ {0xc26a8000}, {0xc26aa000}, {0xc26ac000}, {0xc26ae000},
+ {0xc26b0000}, {0xc26b2000}, {0xc26b4000}, {0xc26b6000},
+ {0xc26b8000}, {0xc26ba000}, {0xc26bc000}, {0xc26be000},
+ {0xc26c0000}, {0xc26c2000}, {0xc26c4000}, {0xc26c6000},
+ {0xc26c8000}, {0xc26ca000}, {0xc26cc000}, {0xc26ce000},
+ {0xc26d0000}, {0xc26d2000}, {0xc26d4000}, {0xc26d6000},
+ {0xc26d8000}, {0xc26da000}, {0xc26dc000}, {0xc26de000},
+ {0xc26e0000}, {0xc26e2000}, {0xc26e4000}, {0xc26e6000},
+ {0xc26e8000}, {0xc26ea000}, {0xc26ec000}, {0xc26ee000},
+ {0xc26f0000}, {0xc26f2000}, {0xc26f4000}, {0xc26f6000},
+ {0xc26f8000}, {0xc26fa000}, {0xc26fc000}, {0xc26fe000},
+ {0xc2700000}, {0xc2702000}, {0xc2704000}, {0xc2706000},
+ {0xc2708000}, {0xc270a000}, {0xc270c000}, {0xc270e000},
+ {0xc2710000}, {0xc2712000}, {0xc2714000}, {0xc2716000},
+ {0xc2718000}, {0xc271a000}, {0xc271c000}, {0xc271e000},
+ {0xc2720000}, {0xc2722000}, {0xc2724000}, {0xc2726000},
+ {0xc2728000}, {0xc272a000}, {0xc272c000}, {0xc272e000},
+ {0xc2730000}, {0xc2732000}, {0xc2734000}, {0xc2736000},
+ {0xc2738000}, {0xc273a000}, {0xc273c000}, {0xc273e000},
+ {0xc2740000}, {0xc2742000}, {0xc2744000}, {0xc2746000},
+ {0xc2748000}, {0xc274a000}, {0xc274c000}, {0xc274e000},
+ {0xc2750000}, {0xc2752000}, {0xc2754000}, {0xc2756000},
+ {0xc2758000}, {0xc275a000}, {0xc275c000}, {0xc275e000},
+ {0xc2760000}, {0xc2762000}, {0xc2764000}, {0xc2766000},
+ {0xc2768000}, {0xc276a000}, {0xc276c000}, {0xc276e000},
+ {0xc2770000}, {0xc2772000}, {0xc2774000}, {0xc2776000},
+ {0xc2778000}, {0xc277a000}, {0xc277c000}, {0xc277e000},
+ {0xc2780000}, {0xc2782000}, {0xc2784000}, {0xc2786000},
+ {0xc2788000}, {0xc278a000}, {0xc278c000}, {0xc278e000},
+ {0xc2790000}, {0xc2792000}, {0xc2794000}, {0xc2796000},
+ {0xc2798000}, {0xc279a000}, {0xc279c000}, {0xc279e000},
+ {0xc27a0000}, {0xc27a2000}, {0xc27a4000}, {0xc27a6000},
+ {0xc27a8000}, {0xc27aa000}, {0xc27ac000}, {0xc27ae000},
+ {0xc27b0000}, {0xc27b2000}, {0xc27b4000}, {0xc27b6000},
+ {0xc27b8000}, {0xc27ba000}, {0xc27bc000}, {0xc27be000},
+ {0xc27c0000}, {0xc27c2000}, {0xc27c4000}, {0xc27c6000},
+ {0xc27c8000}, {0xc27ca000}, {0xc27cc000}, {0xc27ce000},
+ {0xc27d0000}, {0xc27d2000}, {0xc27d4000}, {0xc27d6000},
+ {0xc27d8000}, {0xc27da000}, {0xc27dc000}, {0xc27de000},
+ {0xc27e0000}, {0xc27e2000}, {0xc27e4000}, {0xc27e6000},
+ {0xc27e8000}, {0xc27ea000}, {0xc27ec000}, {0xc27ee000},
+ {0xc27f0000}, {0xc27f2000}, {0xc27f4000}, {0xc27f6000},
+ {0xc27f8000}, {0xc27fa000}, {0xc27fc000}, {0xc27fe000},
+ {0xc2800000}, {0xc2802000}, {0xc2804000}, {0xc2806000},
+ {0xc2808000}, {0xc280a000}, {0xc280c000}, {0xc280e000},
+ {0xc2810000}, {0xc2812000}, {0xc2814000}, {0xc2816000},
+ {0xc2818000}, {0xc281a000}, {0xc281c000}, {0xc281e000},
+ {0xc2820000}, {0xc2822000}, {0xc2824000}, {0xc2826000},
+ {0xc2828000}, {0xc282a000}, {0xc282c000}, {0xc282e000},
+ {0xc2830000}, {0xc2832000}, {0xc2834000}, {0xc2836000},
+ {0xc2838000}, {0xc283a000}, {0xc283c000}, {0xc283e000},
+ {0xc2840000}, {0xc2842000}, {0xc2844000}, {0xc2846000},
+ {0xc2848000}, {0xc284a000}, {0xc284c000}, {0xc284e000},
+ {0xc2850000}, {0xc2852000}, {0xc2854000}, {0xc2856000},
+ {0xc2858000}, {0xc285a000}, {0xc285c000}, {0xc285e000},
+ {0xc2860000}, {0xc2862000}, {0xc2864000}, {0xc2866000},
+ {0xc2868000}, {0xc286a000}, {0xc286c000}, {0xc286e000},
+ {0xc2870000}, {0xc2872000}, {0xc2874000}, {0xc2876000},
+ {0xc2878000}, {0xc287a000}, {0xc287c000}, {0xc287e000},
+ {0xc2880000}, {0xc2882000}, {0xc2884000}, {0xc2886000},
+ {0xc2888000}, {0xc288a000}, {0xc288c000}, {0xc288e000},
+ {0xc2890000}, {0xc2892000}, {0xc2894000}, {0xc2896000},
+ {0xc2898000}, {0xc289a000}, {0xc289c000}, {0xc289e000},
+ {0xc28a0000}, {0xc28a2000}, {0xc28a4000}, {0xc28a6000},
+ {0xc28a8000}, {0xc28aa000}, {0xc28ac000}, {0xc28ae000},
+ {0xc28b0000}, {0xc28b2000}, {0xc28b4000}, {0xc28b6000},
+ {0xc28b8000}, {0xc28ba000}, {0xc28bc000}, {0xc28be000},
+ {0xc28c0000}, {0xc28c2000}, {0xc28c4000}, {0xc28c6000},
+ {0xc28c8000}, {0xc28ca000}, {0xc28cc000}, {0xc28ce000},
+ {0xc28d0000}, {0xc28d2000}, {0xc28d4000}, {0xc28d6000},
+ {0xc28d8000}, {0xc28da000}, {0xc28dc000}, {0xc28de000},
+ {0xc28e0000}, {0xc28e2000}, {0xc28e4000}, {0xc28e6000},
+ {0xc28e8000}, {0xc28ea000}, {0xc28ec000}, {0xc28ee000},
+ {0xc28f0000}, {0xc28f2000}, {0xc28f4000}, {0xc28f6000},
+ {0xc28f8000}, {0xc28fa000}, {0xc28fc000}, {0xc28fe000},
+ {0xc2900000}, {0xc2902000}, {0xc2904000}, {0xc2906000},
+ {0xc2908000}, {0xc290a000}, {0xc290c000}, {0xc290e000},
+ {0xc2910000}, {0xc2912000}, {0xc2914000}, {0xc2916000},
+ {0xc2918000}, {0xc291a000}, {0xc291c000}, {0xc291e000},
+ {0xc2920000}, {0xc2922000}, {0xc2924000}, {0xc2926000},
+ {0xc2928000}, {0xc292a000}, {0xc292c000}, {0xc292e000},
+ {0xc2930000}, {0xc2932000}, {0xc2934000}, {0xc2936000},
+ {0xc2938000}, {0xc293a000}, {0xc293c000}, {0xc293e000},
+ {0xc2940000}, {0xc2942000}, {0xc2944000}, {0xc2946000},
+ {0xc2948000}, {0xc294a000}, {0xc294c000}, {0xc294e000},
+ {0xc2950000}, {0xc2952000}, {0xc2954000}, {0xc2956000},
+ {0xc2958000}, {0xc295a000}, {0xc295c000}, {0xc295e000},
+ {0xc2960000}, {0xc2962000}, {0xc2964000}, {0xc2966000},
+ {0xc2968000}, {0xc296a000}, {0xc296c000}, {0xc296e000},
+ {0xc2970000}, {0xc2972000}, {0xc2974000}, {0xc2976000},
+ {0xc2978000}, {0xc297a000}, {0xc297c000}, {0xc297e000},
+ {0xc2980000}, {0xc2982000}, {0xc2984000}, {0xc2986000},
+ {0xc2988000}, {0xc298a000}, {0xc298c000}, {0xc298e000},
+ {0xc2990000}, {0xc2992000}, {0xc2994000}, {0xc2996000},
+ {0xc2998000}, {0xc299a000}, {0xc299c000}, {0xc299e000},
+ {0xc29a0000}, {0xc29a2000}, {0xc29a4000}, {0xc29a6000},
+ {0xc29a8000}, {0xc29aa000}, {0xc29ac000}, {0xc29ae000},
+ {0xc29b0000}, {0xc29b2000}, {0xc29b4000}, {0xc29b6000},
+ {0xc29b8000}, {0xc29ba000}, {0xc29bc000}, {0xc29be000},
+ {0xc29c0000}, {0xc29c2000}, {0xc29c4000}, {0xc29c6000},
+ {0xc29c8000}, {0xc29ca000}, {0xc29cc000}, {0xc29ce000},
+ {0xc29d0000}, {0xc29d2000}, {0xc29d4000}, {0xc29d6000},
+ {0xc29d8000}, {0xc29da000}, {0xc29dc000}, {0xc29de000},
+ {0xc29e0000}, {0xc29e2000}, {0xc29e4000}, {0xc29e6000},
+ {0xc29e8000}, {0xc29ea000}, {0xc29ec000}, {0xc29ee000},
+ {0xc29f0000}, {0xc29f2000}, {0xc29f4000}, {0xc29f6000},
+ {0xc29f8000}, {0xc29fa000}, {0xc29fc000}, {0xc29fe000},
+ {0xc2a00000}, {0xc2a02000}, {0xc2a04000}, {0xc2a06000},
+ {0xc2a08000}, {0xc2a0a000}, {0xc2a0c000}, {0xc2a0e000},
+ {0xc2a10000}, {0xc2a12000}, {0xc2a14000}, {0xc2a16000},
+ {0xc2a18000}, {0xc2a1a000}, {0xc2a1c000}, {0xc2a1e000},
+ {0xc2a20000}, {0xc2a22000}, {0xc2a24000}, {0xc2a26000},
+ {0xc2a28000}, {0xc2a2a000}, {0xc2a2c000}, {0xc2a2e000},
+ {0xc2a30000}, {0xc2a32000}, {0xc2a34000}, {0xc2a36000},
+ {0xc2a38000}, {0xc2a3a000}, {0xc2a3c000}, {0xc2a3e000},
+ {0xc2a40000}, {0xc2a42000}, {0xc2a44000}, {0xc2a46000},
+ {0xc2a48000}, {0xc2a4a000}, {0xc2a4c000}, {0xc2a4e000},
+ {0xc2a50000}, {0xc2a52000}, {0xc2a54000}, {0xc2a56000},
+ {0xc2a58000}, {0xc2a5a000}, {0xc2a5c000}, {0xc2a5e000},
+ {0xc2a60000}, {0xc2a62000}, {0xc2a64000}, {0xc2a66000},
+ {0xc2a68000}, {0xc2a6a000}, {0xc2a6c000}, {0xc2a6e000},
+ {0xc2a70000}, {0xc2a72000}, {0xc2a74000}, {0xc2a76000},
+ {0xc2a78000}, {0xc2a7a000}, {0xc2a7c000}, {0xc2a7e000},
+ {0xc2a80000}, {0xc2a82000}, {0xc2a84000}, {0xc2a86000},
+ {0xc2a88000}, {0xc2a8a000}, {0xc2a8c000}, {0xc2a8e000},
+ {0xc2a90000}, {0xc2a92000}, {0xc2a94000}, {0xc2a96000},
+ {0xc2a98000}, {0xc2a9a000}, {0xc2a9c000}, {0xc2a9e000},
+ {0xc2aa0000}, {0xc2aa2000}, {0xc2aa4000}, {0xc2aa6000},
+ {0xc2aa8000}, {0xc2aaa000}, {0xc2aac000}, {0xc2aae000},
+ {0xc2ab0000}, {0xc2ab2000}, {0xc2ab4000}, {0xc2ab6000},
+ {0xc2ab8000}, {0xc2aba000}, {0xc2abc000}, {0xc2abe000},
+ {0xc2ac0000}, {0xc2ac2000}, {0xc2ac4000}, {0xc2ac6000},
+ {0xc2ac8000}, {0xc2aca000}, {0xc2acc000}, {0xc2ace000},
+ {0xc2ad0000}, {0xc2ad2000}, {0xc2ad4000}, {0xc2ad6000},
+ {0xc2ad8000}, {0xc2ada000}, {0xc2adc000}, {0xc2ade000},
+ {0xc2ae0000}, {0xc2ae2000}, {0xc2ae4000}, {0xc2ae6000},
+ {0xc2ae8000}, {0xc2aea000}, {0xc2aec000}, {0xc2aee000},
+ {0xc2af0000}, {0xc2af2000}, {0xc2af4000}, {0xc2af6000},
+ {0xc2af8000}, {0xc2afa000}, {0xc2afc000}, {0xc2afe000},
+ {0xc2b00000}, {0xc2b02000}, {0xc2b04000}, {0xc2b06000},
+ {0xc2b08000}, {0xc2b0a000}, {0xc2b0c000}, {0xc2b0e000},
+ {0xc2b10000}, {0xc2b12000}, {0xc2b14000}, {0xc2b16000},
+ {0xc2b18000}, {0xc2b1a000}, {0xc2b1c000}, {0xc2b1e000},
+ {0xc2b20000}, {0xc2b22000}, {0xc2b24000}, {0xc2b26000},
+ {0xc2b28000}, {0xc2b2a000}, {0xc2b2c000}, {0xc2b2e000},
+ {0xc2b30000}, {0xc2b32000}, {0xc2b34000}, {0xc2b36000},
+ {0xc2b38000}, {0xc2b3a000}, {0xc2b3c000}, {0xc2b3e000},
+ {0xc2b40000}, {0xc2b42000}, {0xc2b44000}, {0xc2b46000},
+ {0xc2b48000}, {0xc2b4a000}, {0xc2b4c000}, {0xc2b4e000},
+ {0xc2b50000}, {0xc2b52000}, {0xc2b54000}, {0xc2b56000},
+ {0xc2b58000}, {0xc2b5a000}, {0xc2b5c000}, {0xc2b5e000},
+ {0xc2b60000}, {0xc2b62000}, {0xc2b64000}, {0xc2b66000},
+ {0xc2b68000}, {0xc2b6a000}, {0xc2b6c000}, {0xc2b6e000},
+ {0xc2b70000}, {0xc2b72000}, {0xc2b74000}, {0xc2b76000},
+ {0xc2b78000}, {0xc2b7a000}, {0xc2b7c000}, {0xc2b7e000},
+ {0xc2b80000}, {0xc2b82000}, {0xc2b84000}, {0xc2b86000},
+ {0xc2b88000}, {0xc2b8a000}, {0xc2b8c000}, {0xc2b8e000},
+ {0xc2b90000}, {0xc2b92000}, {0xc2b94000}, {0xc2b96000},
+ {0xc2b98000}, {0xc2b9a000}, {0xc2b9c000}, {0xc2b9e000},
+ {0xc2ba0000}, {0xc2ba2000}, {0xc2ba4000}, {0xc2ba6000},
+ {0xc2ba8000}, {0xc2baa000}, {0xc2bac000}, {0xc2bae000},
+ {0xc2bb0000}, {0xc2bb2000}, {0xc2bb4000}, {0xc2bb6000},
+ {0xc2bb8000}, {0xc2bba000}, {0xc2bbc000}, {0xc2bbe000},
+ {0xc2bc0000}, {0xc2bc2000}, {0xc2bc4000}, {0xc2bc6000},
+ {0xc2bc8000}, {0xc2bca000}, {0xc2bcc000}, {0xc2bce000},
+ {0xc2bd0000}, {0xc2bd2000}, {0xc2bd4000}, {0xc2bd6000},
+ {0xc2bd8000}, {0xc2bda000}, {0xc2bdc000}, {0xc2bde000},
+ {0xc2be0000}, {0xc2be2000}, {0xc2be4000}, {0xc2be6000},
+ {0xc2be8000}, {0xc2bea000}, {0xc2bec000}, {0xc2bee000},
+ {0xc2bf0000}, {0xc2bf2000}, {0xc2bf4000}, {0xc2bf6000},
+ {0xc2bf8000}, {0xc2bfa000}, {0xc2bfc000}, {0xc2bfe000},
+ {0xc2c00000}, {0xc2c02000}, {0xc2c04000}, {0xc2c06000},
+ {0xc2c08000}, {0xc2c0a000}, {0xc2c0c000}, {0xc2c0e000},
+ {0xc2c10000}, {0xc2c12000}, {0xc2c14000}, {0xc2c16000},
+ {0xc2c18000}, {0xc2c1a000}, {0xc2c1c000}, {0xc2c1e000},
+ {0xc2c20000}, {0xc2c22000}, {0xc2c24000}, {0xc2c26000},
+ {0xc2c28000}, {0xc2c2a000}, {0xc2c2c000}, {0xc2c2e000},
+ {0xc2c30000}, {0xc2c32000}, {0xc2c34000}, {0xc2c36000},
+ {0xc2c38000}, {0xc2c3a000}, {0xc2c3c000}, {0xc2c3e000},
+ {0xc2c40000}, {0xc2c42000}, {0xc2c44000}, {0xc2c46000},
+ {0xc2c48000}, {0xc2c4a000}, {0xc2c4c000}, {0xc2c4e000},
+ {0xc2c50000}, {0xc2c52000}, {0xc2c54000}, {0xc2c56000},
+ {0xc2c58000}, {0xc2c5a000}, {0xc2c5c000}, {0xc2c5e000},
+ {0xc2c60000}, {0xc2c62000}, {0xc2c64000}, {0xc2c66000},
+ {0xc2c68000}, {0xc2c6a000}, {0xc2c6c000}, {0xc2c6e000},
+ {0xc2c70000}, {0xc2c72000}, {0xc2c74000}, {0xc2c76000},
+ {0xc2c78000}, {0xc2c7a000}, {0xc2c7c000}, {0xc2c7e000},
+ {0xc2c80000}, {0xc2c82000}, {0xc2c84000}, {0xc2c86000},
+ {0xc2c88000}, {0xc2c8a000}, {0xc2c8c000}, {0xc2c8e000},
+ {0xc2c90000}, {0xc2c92000}, {0xc2c94000}, {0xc2c96000},
+ {0xc2c98000}, {0xc2c9a000}, {0xc2c9c000}, {0xc2c9e000},
+ {0xc2ca0000}, {0xc2ca2000}, {0xc2ca4000}, {0xc2ca6000},
+ {0xc2ca8000}, {0xc2caa000}, {0xc2cac000}, {0xc2cae000},
+ {0xc2cb0000}, {0xc2cb2000}, {0xc2cb4000}, {0xc2cb6000},
+ {0xc2cb8000}, {0xc2cba000}, {0xc2cbc000}, {0xc2cbe000},
+ {0xc2cc0000}, {0xc2cc2000}, {0xc2cc4000}, {0xc2cc6000},
+ {0xc2cc8000}, {0xc2cca000}, {0xc2ccc000}, {0xc2cce000},
+ {0xc2cd0000}, {0xc2cd2000}, {0xc2cd4000}, {0xc2cd6000},
+ {0xc2cd8000}, {0xc2cda000}, {0xc2cdc000}, {0xc2cde000},
+ {0xc2ce0000}, {0xc2ce2000}, {0xc2ce4000}, {0xc2ce6000},
+ {0xc2ce8000}, {0xc2cea000}, {0xc2cec000}, {0xc2cee000},
+ {0xc2cf0000}, {0xc2cf2000}, {0xc2cf4000}, {0xc2cf6000},
+ {0xc2cf8000}, {0xc2cfa000}, {0xc2cfc000}, {0xc2cfe000},
+ {0xc2d00000}, {0xc2d02000}, {0xc2d04000}, {0xc2d06000},
+ {0xc2d08000}, {0xc2d0a000}, {0xc2d0c000}, {0xc2d0e000},
+ {0xc2d10000}, {0xc2d12000}, {0xc2d14000}, {0xc2d16000},
+ {0xc2d18000}, {0xc2d1a000}, {0xc2d1c000}, {0xc2d1e000},
+ {0xc2d20000}, {0xc2d22000}, {0xc2d24000}, {0xc2d26000},
+ {0xc2d28000}, {0xc2d2a000}, {0xc2d2c000}, {0xc2d2e000},
+ {0xc2d30000}, {0xc2d32000}, {0xc2d34000}, {0xc2d36000},
+ {0xc2d38000}, {0xc2d3a000}, {0xc2d3c000}, {0xc2d3e000},
+ {0xc2d40000}, {0xc2d42000}, {0xc2d44000}, {0xc2d46000},
+ {0xc2d48000}, {0xc2d4a000}, {0xc2d4c000}, {0xc2d4e000},
+ {0xc2d50000}, {0xc2d52000}, {0xc2d54000}, {0xc2d56000},
+ {0xc2d58000}, {0xc2d5a000}, {0xc2d5c000}, {0xc2d5e000},
+ {0xc2d60000}, {0xc2d62000}, {0xc2d64000}, {0xc2d66000},
+ {0xc2d68000}, {0xc2d6a000}, {0xc2d6c000}, {0xc2d6e000},
+ {0xc2d70000}, {0xc2d72000}, {0xc2d74000}, {0xc2d76000},
+ {0xc2d78000}, {0xc2d7a000}, {0xc2d7c000}, {0xc2d7e000},
+ {0xc2d80000}, {0xc2d82000}, {0xc2d84000}, {0xc2d86000},
+ {0xc2d88000}, {0xc2d8a000}, {0xc2d8c000}, {0xc2d8e000},
+ {0xc2d90000}, {0xc2d92000}, {0xc2d94000}, {0xc2d96000},
+ {0xc2d98000}, {0xc2d9a000}, {0xc2d9c000}, {0xc2d9e000},
+ {0xc2da0000}, {0xc2da2000}, {0xc2da4000}, {0xc2da6000},
+ {0xc2da8000}, {0xc2daa000}, {0xc2dac000}, {0xc2dae000},
+ {0xc2db0000}, {0xc2db2000}, {0xc2db4000}, {0xc2db6000},
+ {0xc2db8000}, {0xc2dba000}, {0xc2dbc000}, {0xc2dbe000},
+ {0xc2dc0000}, {0xc2dc2000}, {0xc2dc4000}, {0xc2dc6000},
+ {0xc2dc8000}, {0xc2dca000}, {0xc2dcc000}, {0xc2dce000},
+ {0xc2dd0000}, {0xc2dd2000}, {0xc2dd4000}, {0xc2dd6000},
+ {0xc2dd8000}, {0xc2dda000}, {0xc2ddc000}, {0xc2dde000},
+ {0xc2de0000}, {0xc2de2000}, {0xc2de4000}, {0xc2de6000},
+ {0xc2de8000}, {0xc2dea000}, {0xc2dec000}, {0xc2dee000},
+ {0xc2df0000}, {0xc2df2000}, {0xc2df4000}, {0xc2df6000},
+ {0xc2df8000}, {0xc2dfa000}, {0xc2dfc000}, {0xc2dfe000},
+ {0xc2e00000}, {0xc2e02000}, {0xc2e04000}, {0xc2e06000},
+ {0xc2e08000}, {0xc2e0a000}, {0xc2e0c000}, {0xc2e0e000},
+ {0xc2e10000}, {0xc2e12000}, {0xc2e14000}, {0xc2e16000},
+ {0xc2e18000}, {0xc2e1a000}, {0xc2e1c000}, {0xc2e1e000},
+ {0xc2e20000}, {0xc2e22000}, {0xc2e24000}, {0xc2e26000},
+ {0xc2e28000}, {0xc2e2a000}, {0xc2e2c000}, {0xc2e2e000},
+ {0xc2e30000}, {0xc2e32000}, {0xc2e34000}, {0xc2e36000},
+ {0xc2e38000}, {0xc2e3a000}, {0xc2e3c000}, {0xc2e3e000},
+ {0xc2e40000}, {0xc2e42000}, {0xc2e44000}, {0xc2e46000},
+ {0xc2e48000}, {0xc2e4a000}, {0xc2e4c000}, {0xc2e4e000},
+ {0xc2e50000}, {0xc2e52000}, {0xc2e54000}, {0xc2e56000},
+ {0xc2e58000}, {0xc2e5a000}, {0xc2e5c000}, {0xc2e5e000},
+ {0xc2e60000}, {0xc2e62000}, {0xc2e64000}, {0xc2e66000},
+ {0xc2e68000}, {0xc2e6a000}, {0xc2e6c000}, {0xc2e6e000},
+ {0xc2e70000}, {0xc2e72000}, {0xc2e74000}, {0xc2e76000},
+ {0xc2e78000}, {0xc2e7a000}, {0xc2e7c000}, {0xc2e7e000},
+ {0xc2e80000}, {0xc2e82000}, {0xc2e84000}, {0xc2e86000},
+ {0xc2e88000}, {0xc2e8a000}, {0xc2e8c000}, {0xc2e8e000},
+ {0xc2e90000}, {0xc2e92000}, {0xc2e94000}, {0xc2e96000},
+ {0xc2e98000}, {0xc2e9a000}, {0xc2e9c000}, {0xc2e9e000},
+ {0xc2ea0000}, {0xc2ea2000}, {0xc2ea4000}, {0xc2ea6000},
+ {0xc2ea8000}, {0xc2eaa000}, {0xc2eac000}, {0xc2eae000},
+ {0xc2eb0000}, {0xc2eb2000}, {0xc2eb4000}, {0xc2eb6000},
+ {0xc2eb8000}, {0xc2eba000}, {0xc2ebc000}, {0xc2ebe000},
+ {0xc2ec0000}, {0xc2ec2000}, {0xc2ec4000}, {0xc2ec6000},
+ {0xc2ec8000}, {0xc2eca000}, {0xc2ecc000}, {0xc2ece000},
+ {0xc2ed0000}, {0xc2ed2000}, {0xc2ed4000}, {0xc2ed6000},
+ {0xc2ed8000}, {0xc2eda000}, {0xc2edc000}, {0xc2ede000},
+ {0xc2ee0000}, {0xc2ee2000}, {0xc2ee4000}, {0xc2ee6000},
+ {0xc2ee8000}, {0xc2eea000}, {0xc2eec000}, {0xc2eee000},
+ {0xc2ef0000}, {0xc2ef2000}, {0xc2ef4000}, {0xc2ef6000},
+ {0xc2ef8000}, {0xc2efa000}, {0xc2efc000}, {0xc2efe000},
+ {0xc2f00000}, {0xc2f02000}, {0xc2f04000}, {0xc2f06000},
+ {0xc2f08000}, {0xc2f0a000}, {0xc2f0c000}, {0xc2f0e000},
+ {0xc2f10000}, {0xc2f12000}, {0xc2f14000}, {0xc2f16000},
+ {0xc2f18000}, {0xc2f1a000}, {0xc2f1c000}, {0xc2f1e000},
+ {0xc2f20000}, {0xc2f22000}, {0xc2f24000}, {0xc2f26000},
+ {0xc2f28000}, {0xc2f2a000}, {0xc2f2c000}, {0xc2f2e000},
+ {0xc2f30000}, {0xc2f32000}, {0xc2f34000}, {0xc2f36000},
+ {0xc2f38000}, {0xc2f3a000}, {0xc2f3c000}, {0xc2f3e000},
+ {0xc2f40000}, {0xc2f42000}, {0xc2f44000}, {0xc2f46000},
+ {0xc2f48000}, {0xc2f4a000}, {0xc2f4c000}, {0xc2f4e000},
+ {0xc2f50000}, {0xc2f52000}, {0xc2f54000}, {0xc2f56000},
+ {0xc2f58000}, {0xc2f5a000}, {0xc2f5c000}, {0xc2f5e000},
+ {0xc2f60000}, {0xc2f62000}, {0xc2f64000}, {0xc2f66000},
+ {0xc2f68000}, {0xc2f6a000}, {0xc2f6c000}, {0xc2f6e000},
+ {0xc2f70000}, {0xc2f72000}, {0xc2f74000}, {0xc2f76000},
+ {0xc2f78000}, {0xc2f7a000}, {0xc2f7c000}, {0xc2f7e000},
+ {0xc2f80000}, {0xc2f82000}, {0xc2f84000}, {0xc2f86000},
+ {0xc2f88000}, {0xc2f8a000}, {0xc2f8c000}, {0xc2f8e000},
+ {0xc2f90000}, {0xc2f92000}, {0xc2f94000}, {0xc2f96000},
+ {0xc2f98000}, {0xc2f9a000}, {0xc2f9c000}, {0xc2f9e000},
+ {0xc2fa0000}, {0xc2fa2000}, {0xc2fa4000}, {0xc2fa6000},
+ {0xc2fa8000}, {0xc2faa000}, {0xc2fac000}, {0xc2fae000},
+ {0xc2fb0000}, {0xc2fb2000}, {0xc2fb4000}, {0xc2fb6000},
+ {0xc2fb8000}, {0xc2fba000}, {0xc2fbc000}, {0xc2fbe000},
+ {0xc2fc0000}, {0xc2fc2000}, {0xc2fc4000}, {0xc2fc6000},
+ {0xc2fc8000}, {0xc2fca000}, {0xc2fcc000}, {0xc2fce000},
+ {0xc2fd0000}, {0xc2fd2000}, {0xc2fd4000}, {0xc2fd6000},
+ {0xc2fd8000}, {0xc2fda000}, {0xc2fdc000}, {0xc2fde000},
+ {0xc2fe0000}, {0xc2fe2000}, {0xc2fe4000}, {0xc2fe6000},
+ {0xc2fe8000}, {0xc2fea000}, {0xc2fec000}, {0xc2fee000},
+ {0xc2ff0000}, {0xc2ff2000}, {0xc2ff4000}, {0xc2ff6000},
+ {0xc2ff8000}, {0xc2ffa000}, {0xc2ffc000}, {0xc2ffe000},
+ {0xc3000000}, {0xc3002000}, {0xc3004000}, {0xc3006000},
+ {0xc3008000}, {0xc300a000}, {0xc300c000}, {0xc300e000},
+ {0xc3010000}, {0xc3012000}, {0xc3014000}, {0xc3016000},
+ {0xc3018000}, {0xc301a000}, {0xc301c000}, {0xc301e000},
+ {0xc3020000}, {0xc3022000}, {0xc3024000}, {0xc3026000},
+ {0xc3028000}, {0xc302a000}, {0xc302c000}, {0xc302e000},
+ {0xc3030000}, {0xc3032000}, {0xc3034000}, {0xc3036000},
+ {0xc3038000}, {0xc303a000}, {0xc303c000}, {0xc303e000},
+ {0xc3040000}, {0xc3042000}, {0xc3044000}, {0xc3046000},
+ {0xc3048000}, {0xc304a000}, {0xc304c000}, {0xc304e000},
+ {0xc3050000}, {0xc3052000}, {0xc3054000}, {0xc3056000},
+ {0xc3058000}, {0xc305a000}, {0xc305c000}, {0xc305e000},
+ {0xc3060000}, {0xc3062000}, {0xc3064000}, {0xc3066000},
+ {0xc3068000}, {0xc306a000}, {0xc306c000}, {0xc306e000},
+ {0xc3070000}, {0xc3072000}, {0xc3074000}, {0xc3076000},
+ {0xc3078000}, {0xc307a000}, {0xc307c000}, {0xc307e000},
+ {0xc3080000}, {0xc3082000}, {0xc3084000}, {0xc3086000},
+ {0xc3088000}, {0xc308a000}, {0xc308c000}, {0xc308e000},
+ {0xc3090000}, {0xc3092000}, {0xc3094000}, {0xc3096000},
+ {0xc3098000}, {0xc309a000}, {0xc309c000}, {0xc309e000},
+ {0xc30a0000}, {0xc30a2000}, {0xc30a4000}, {0xc30a6000},
+ {0xc30a8000}, {0xc30aa000}, {0xc30ac000}, {0xc30ae000},
+ {0xc30b0000}, {0xc30b2000}, {0xc30b4000}, {0xc30b6000},
+ {0xc30b8000}, {0xc30ba000}, {0xc30bc000}, {0xc30be000},
+ {0xc30c0000}, {0xc30c2000}, {0xc30c4000}, {0xc30c6000},
+ {0xc30c8000}, {0xc30ca000}, {0xc30cc000}, {0xc30ce000},
+ {0xc30d0000}, {0xc30d2000}, {0xc30d4000}, {0xc30d6000},
+ {0xc30d8000}, {0xc30da000}, {0xc30dc000}, {0xc30de000},
+ {0xc30e0000}, {0xc30e2000}, {0xc30e4000}, {0xc30e6000},
+ {0xc30e8000}, {0xc30ea000}, {0xc30ec000}, {0xc30ee000},
+ {0xc30f0000}, {0xc30f2000}, {0xc30f4000}, {0xc30f6000},
+ {0xc30f8000}, {0xc30fa000}, {0xc30fc000}, {0xc30fe000},
+ {0xc3100000}, {0xc3102000}, {0xc3104000}, {0xc3106000},
+ {0xc3108000}, {0xc310a000}, {0xc310c000}, {0xc310e000},
+ {0xc3110000}, {0xc3112000}, {0xc3114000}, {0xc3116000},
+ {0xc3118000}, {0xc311a000}, {0xc311c000}, {0xc311e000},
+ {0xc3120000}, {0xc3122000}, {0xc3124000}, {0xc3126000},
+ {0xc3128000}, {0xc312a000}, {0xc312c000}, {0xc312e000},
+ {0xc3130000}, {0xc3132000}, {0xc3134000}, {0xc3136000},
+ {0xc3138000}, {0xc313a000}, {0xc313c000}, {0xc313e000},
+ {0xc3140000}, {0xc3142000}, {0xc3144000}, {0xc3146000},
+ {0xc3148000}, {0xc314a000}, {0xc314c000}, {0xc314e000},
+ {0xc3150000}, {0xc3152000}, {0xc3154000}, {0xc3156000},
+ {0xc3158000}, {0xc315a000}, {0xc315c000}, {0xc315e000},
+ {0xc3160000}, {0xc3162000}, {0xc3164000}, {0xc3166000},
+ {0xc3168000}, {0xc316a000}, {0xc316c000}, {0xc316e000},
+ {0xc3170000}, {0xc3172000}, {0xc3174000}, {0xc3176000},
+ {0xc3178000}, {0xc317a000}, {0xc317c000}, {0xc317e000},
+ {0xc3180000}, {0xc3182000}, {0xc3184000}, {0xc3186000},
+ {0xc3188000}, {0xc318a000}, {0xc318c000}, {0xc318e000},
+ {0xc3190000}, {0xc3192000}, {0xc3194000}, {0xc3196000},
+ {0xc3198000}, {0xc319a000}, {0xc319c000}, {0xc319e000},
+ {0xc31a0000}, {0xc31a2000}, {0xc31a4000}, {0xc31a6000},
+ {0xc31a8000}, {0xc31aa000}, {0xc31ac000}, {0xc31ae000},
+ {0xc31b0000}, {0xc31b2000}, {0xc31b4000}, {0xc31b6000},
+ {0xc31b8000}, {0xc31ba000}, {0xc31bc000}, {0xc31be000},
+ {0xc31c0000}, {0xc31c2000}, {0xc31c4000}, {0xc31c6000},
+ {0xc31c8000}, {0xc31ca000}, {0xc31cc000}, {0xc31ce000},
+ {0xc31d0000}, {0xc31d2000}, {0xc31d4000}, {0xc31d6000},
+ {0xc31d8000}, {0xc31da000}, {0xc31dc000}, {0xc31de000},
+ {0xc31e0000}, {0xc31e2000}, {0xc31e4000}, {0xc31e6000},
+ {0xc31e8000}, {0xc31ea000}, {0xc31ec000}, {0xc31ee000},
+ {0xc31f0000}, {0xc31f2000}, {0xc31f4000}, {0xc31f6000},
+ {0xc31f8000}, {0xc31fa000}, {0xc31fc000}, {0xc31fe000},
+ {0xc3200000}, {0xc3202000}, {0xc3204000}, {0xc3206000},
+ {0xc3208000}, {0xc320a000}, {0xc320c000}, {0xc320e000},
+ {0xc3210000}, {0xc3212000}, {0xc3214000}, {0xc3216000},
+ {0xc3218000}, {0xc321a000}, {0xc321c000}, {0xc321e000},
+ {0xc3220000}, {0xc3222000}, {0xc3224000}, {0xc3226000},
+ {0xc3228000}, {0xc322a000}, {0xc322c000}, {0xc322e000},
+ {0xc3230000}, {0xc3232000}, {0xc3234000}, {0xc3236000},
+ {0xc3238000}, {0xc323a000}, {0xc323c000}, {0xc323e000},
+ {0xc3240000}, {0xc3242000}, {0xc3244000}, {0xc3246000},
+ {0xc3248000}, {0xc324a000}, {0xc324c000}, {0xc324e000},
+ {0xc3250000}, {0xc3252000}, {0xc3254000}, {0xc3256000},
+ {0xc3258000}, {0xc325a000}, {0xc325c000}, {0xc325e000},
+ {0xc3260000}, {0xc3262000}, {0xc3264000}, {0xc3266000},
+ {0xc3268000}, {0xc326a000}, {0xc326c000}, {0xc326e000},
+ {0xc3270000}, {0xc3272000}, {0xc3274000}, {0xc3276000},
+ {0xc3278000}, {0xc327a000}, {0xc327c000}, {0xc327e000},
+ {0xc3280000}, {0xc3282000}, {0xc3284000}, {0xc3286000},
+ {0xc3288000}, {0xc328a000}, {0xc328c000}, {0xc328e000},
+ {0xc3290000}, {0xc3292000}, {0xc3294000}, {0xc3296000},
+ {0xc3298000}, {0xc329a000}, {0xc329c000}, {0xc329e000},
+ {0xc32a0000}, {0xc32a2000}, {0xc32a4000}, {0xc32a6000},
+ {0xc32a8000}, {0xc32aa000}, {0xc32ac000}, {0xc32ae000},
+ {0xc32b0000}, {0xc32b2000}, {0xc32b4000}, {0xc32b6000},
+ {0xc32b8000}, {0xc32ba000}, {0xc32bc000}, {0xc32be000},
+ {0xc32c0000}, {0xc32c2000}, {0xc32c4000}, {0xc32c6000},
+ {0xc32c8000}, {0xc32ca000}, {0xc32cc000}, {0xc32ce000},
+ {0xc32d0000}, {0xc32d2000}, {0xc32d4000}, {0xc32d6000},
+ {0xc32d8000}, {0xc32da000}, {0xc32dc000}, {0xc32de000},
+ {0xc32e0000}, {0xc32e2000}, {0xc32e4000}, {0xc32e6000},
+ {0xc32e8000}, {0xc32ea000}, {0xc32ec000}, {0xc32ee000},
+ {0xc32f0000}, {0xc32f2000}, {0xc32f4000}, {0xc32f6000},
+ {0xc32f8000}, {0xc32fa000}, {0xc32fc000}, {0xc32fe000},
+ {0xc3300000}, {0xc3302000}, {0xc3304000}, {0xc3306000},
+ {0xc3308000}, {0xc330a000}, {0xc330c000}, {0xc330e000},
+ {0xc3310000}, {0xc3312000}, {0xc3314000}, {0xc3316000},
+ {0xc3318000}, {0xc331a000}, {0xc331c000}, {0xc331e000},
+ {0xc3320000}, {0xc3322000}, {0xc3324000}, {0xc3326000},
+ {0xc3328000}, {0xc332a000}, {0xc332c000}, {0xc332e000},
+ {0xc3330000}, {0xc3332000}, {0xc3334000}, {0xc3336000},
+ {0xc3338000}, {0xc333a000}, {0xc333c000}, {0xc333e000},
+ {0xc3340000}, {0xc3342000}, {0xc3344000}, {0xc3346000},
+ {0xc3348000}, {0xc334a000}, {0xc334c000}, {0xc334e000},
+ {0xc3350000}, {0xc3352000}, {0xc3354000}, {0xc3356000},
+ {0xc3358000}, {0xc335a000}, {0xc335c000}, {0xc335e000},
+ {0xc3360000}, {0xc3362000}, {0xc3364000}, {0xc3366000},
+ {0xc3368000}, {0xc336a000}, {0xc336c000}, {0xc336e000},
+ {0xc3370000}, {0xc3372000}, {0xc3374000}, {0xc3376000},
+ {0xc3378000}, {0xc337a000}, {0xc337c000}, {0xc337e000},
+ {0xc3380000}, {0xc3382000}, {0xc3384000}, {0xc3386000},
+ {0xc3388000}, {0xc338a000}, {0xc338c000}, {0xc338e000},
+ {0xc3390000}, {0xc3392000}, {0xc3394000}, {0xc3396000},
+ {0xc3398000}, {0xc339a000}, {0xc339c000}, {0xc339e000},
+ {0xc33a0000}, {0xc33a2000}, {0xc33a4000}, {0xc33a6000},
+ {0xc33a8000}, {0xc33aa000}, {0xc33ac000}, {0xc33ae000},
+ {0xc33b0000}, {0xc33b2000}, {0xc33b4000}, {0xc33b6000},
+ {0xc33b8000}, {0xc33ba000}, {0xc33bc000}, {0xc33be000},
+ {0xc33c0000}, {0xc33c2000}, {0xc33c4000}, {0xc33c6000},
+ {0xc33c8000}, {0xc33ca000}, {0xc33cc000}, {0xc33ce000},
+ {0xc33d0000}, {0xc33d2000}, {0xc33d4000}, {0xc33d6000},
+ {0xc33d8000}, {0xc33da000}, {0xc33dc000}, {0xc33de000},
+ {0xc33e0000}, {0xc33e2000}, {0xc33e4000}, {0xc33e6000},
+ {0xc33e8000}, {0xc33ea000}, {0xc33ec000}, {0xc33ee000},
+ {0xc33f0000}, {0xc33f2000}, {0xc33f4000}, {0xc33f6000},
+ {0xc33f8000}, {0xc33fa000}, {0xc33fc000}, {0xc33fe000},
+ {0xc3400000}, {0xc3402000}, {0xc3404000}, {0xc3406000},
+ {0xc3408000}, {0xc340a000}, {0xc340c000}, {0xc340e000},
+ {0xc3410000}, {0xc3412000}, {0xc3414000}, {0xc3416000},
+ {0xc3418000}, {0xc341a000}, {0xc341c000}, {0xc341e000},
+ {0xc3420000}, {0xc3422000}, {0xc3424000}, {0xc3426000},
+ {0xc3428000}, {0xc342a000}, {0xc342c000}, {0xc342e000},
+ {0xc3430000}, {0xc3432000}, {0xc3434000}, {0xc3436000},
+ {0xc3438000}, {0xc343a000}, {0xc343c000}, {0xc343e000},
+ {0xc3440000}, {0xc3442000}, {0xc3444000}, {0xc3446000},
+ {0xc3448000}, {0xc344a000}, {0xc344c000}, {0xc344e000},
+ {0xc3450000}, {0xc3452000}, {0xc3454000}, {0xc3456000},
+ {0xc3458000}, {0xc345a000}, {0xc345c000}, {0xc345e000},
+ {0xc3460000}, {0xc3462000}, {0xc3464000}, {0xc3466000},
+ {0xc3468000}, {0xc346a000}, {0xc346c000}, {0xc346e000},
+ {0xc3470000}, {0xc3472000}, {0xc3474000}, {0xc3476000},
+ {0xc3478000}, {0xc347a000}, {0xc347c000}, {0xc347e000},
+ {0xc3480000}, {0xc3482000}, {0xc3484000}, {0xc3486000},
+ {0xc3488000}, {0xc348a000}, {0xc348c000}, {0xc348e000},
+ {0xc3490000}, {0xc3492000}, {0xc3494000}, {0xc3496000},
+ {0xc3498000}, {0xc349a000}, {0xc349c000}, {0xc349e000},
+ {0xc34a0000}, {0xc34a2000}, {0xc34a4000}, {0xc34a6000},
+ {0xc34a8000}, {0xc34aa000}, {0xc34ac000}, {0xc34ae000},
+ {0xc34b0000}, {0xc34b2000}, {0xc34b4000}, {0xc34b6000},
+ {0xc34b8000}, {0xc34ba000}, {0xc34bc000}, {0xc34be000},
+ {0xc34c0000}, {0xc34c2000}, {0xc34c4000}, {0xc34c6000},
+ {0xc34c8000}, {0xc34ca000}, {0xc34cc000}, {0xc34ce000},
+ {0xc34d0000}, {0xc34d2000}, {0xc34d4000}, {0xc34d6000},
+ {0xc34d8000}, {0xc34da000}, {0xc34dc000}, {0xc34de000},
+ {0xc34e0000}, {0xc34e2000}, {0xc34e4000}, {0xc34e6000},
+ {0xc34e8000}, {0xc34ea000}, {0xc34ec000}, {0xc34ee000},
+ {0xc34f0000}, {0xc34f2000}, {0xc34f4000}, {0xc34f6000},
+ {0xc34f8000}, {0xc34fa000}, {0xc34fc000}, {0xc34fe000},
+ {0xc3500000}, {0xc3502000}, {0xc3504000}, {0xc3506000},
+ {0xc3508000}, {0xc350a000}, {0xc350c000}, {0xc350e000},
+ {0xc3510000}, {0xc3512000}, {0xc3514000}, {0xc3516000},
+ {0xc3518000}, {0xc351a000}, {0xc351c000}, {0xc351e000},
+ {0xc3520000}, {0xc3522000}, {0xc3524000}, {0xc3526000},
+ {0xc3528000}, {0xc352a000}, {0xc352c000}, {0xc352e000},
+ {0xc3530000}, {0xc3532000}, {0xc3534000}, {0xc3536000},
+ {0xc3538000}, {0xc353a000}, {0xc353c000}, {0xc353e000},
+ {0xc3540000}, {0xc3542000}, {0xc3544000}, {0xc3546000},
+ {0xc3548000}, {0xc354a000}, {0xc354c000}, {0xc354e000},
+ {0xc3550000}, {0xc3552000}, {0xc3554000}, {0xc3556000},
+ {0xc3558000}, {0xc355a000}, {0xc355c000}, {0xc355e000},
+ {0xc3560000}, {0xc3562000}, {0xc3564000}, {0xc3566000},
+ {0xc3568000}, {0xc356a000}, {0xc356c000}, {0xc356e000},
+ {0xc3570000}, {0xc3572000}, {0xc3574000}, {0xc3576000},
+ {0xc3578000}, {0xc357a000}, {0xc357c000}, {0xc357e000},
+ {0xc3580000}, {0xc3582000}, {0xc3584000}, {0xc3586000},
+ {0xc3588000}, {0xc358a000}, {0xc358c000}, {0xc358e000},
+ {0xc3590000}, {0xc3592000}, {0xc3594000}, {0xc3596000},
+ {0xc3598000}, {0xc359a000}, {0xc359c000}, {0xc359e000},
+ {0xc35a0000}, {0xc35a2000}, {0xc35a4000}, {0xc35a6000},
+ {0xc35a8000}, {0xc35aa000}, {0xc35ac000}, {0xc35ae000},
+ {0xc35b0000}, {0xc35b2000}, {0xc35b4000}, {0xc35b6000},
+ {0xc35b8000}, {0xc35ba000}, {0xc35bc000}, {0xc35be000},
+ {0xc35c0000}, {0xc35c2000}, {0xc35c4000}, {0xc35c6000},
+ {0xc35c8000}, {0xc35ca000}, {0xc35cc000}, {0xc35ce000},
+ {0xc35d0000}, {0xc35d2000}, {0xc35d4000}, {0xc35d6000},
+ {0xc35d8000}, {0xc35da000}, {0xc35dc000}, {0xc35de000},
+ {0xc35e0000}, {0xc35e2000}, {0xc35e4000}, {0xc35e6000},
+ {0xc35e8000}, {0xc35ea000}, {0xc35ec000}, {0xc35ee000},
+ {0xc35f0000}, {0xc35f2000}, {0xc35f4000}, {0xc35f6000},
+ {0xc35f8000}, {0xc35fa000}, {0xc35fc000}, {0xc35fe000},
+ {0xc3600000}, {0xc3602000}, {0xc3604000}, {0xc3606000},
+ {0xc3608000}, {0xc360a000}, {0xc360c000}, {0xc360e000},
+ {0xc3610000}, {0xc3612000}, {0xc3614000}, {0xc3616000},
+ {0xc3618000}, {0xc361a000}, {0xc361c000}, {0xc361e000},
+ {0xc3620000}, {0xc3622000}, {0xc3624000}, {0xc3626000},
+ {0xc3628000}, {0xc362a000}, {0xc362c000}, {0xc362e000},
+ {0xc3630000}, {0xc3632000}, {0xc3634000}, {0xc3636000},
+ {0xc3638000}, {0xc363a000}, {0xc363c000}, {0xc363e000},
+ {0xc3640000}, {0xc3642000}, {0xc3644000}, {0xc3646000},
+ {0xc3648000}, {0xc364a000}, {0xc364c000}, {0xc364e000},
+ {0xc3650000}, {0xc3652000}, {0xc3654000}, {0xc3656000},
+ {0xc3658000}, {0xc365a000}, {0xc365c000}, {0xc365e000},
+ {0xc3660000}, {0xc3662000}, {0xc3664000}, {0xc3666000},
+ {0xc3668000}, {0xc366a000}, {0xc366c000}, {0xc366e000},
+ {0xc3670000}, {0xc3672000}, {0xc3674000}, {0xc3676000},
+ {0xc3678000}, {0xc367a000}, {0xc367c000}, {0xc367e000},
+ {0xc3680000}, {0xc3682000}, {0xc3684000}, {0xc3686000},
+ {0xc3688000}, {0xc368a000}, {0xc368c000}, {0xc368e000},
+ {0xc3690000}, {0xc3692000}, {0xc3694000}, {0xc3696000},
+ {0xc3698000}, {0xc369a000}, {0xc369c000}, {0xc369e000},
+ {0xc36a0000}, {0xc36a2000}, {0xc36a4000}, {0xc36a6000},
+ {0xc36a8000}, {0xc36aa000}, {0xc36ac000}, {0xc36ae000},
+ {0xc36b0000}, {0xc36b2000}, {0xc36b4000}, {0xc36b6000},
+ {0xc36b8000}, {0xc36ba000}, {0xc36bc000}, {0xc36be000},
+ {0xc36c0000}, {0xc36c2000}, {0xc36c4000}, {0xc36c6000},
+ {0xc36c8000}, {0xc36ca000}, {0xc36cc000}, {0xc36ce000},
+ {0xc36d0000}, {0xc36d2000}, {0xc36d4000}, {0xc36d6000},
+ {0xc36d8000}, {0xc36da000}, {0xc36dc000}, {0xc36de000},
+ {0xc36e0000}, {0xc36e2000}, {0xc36e4000}, {0xc36e6000},
+ {0xc36e8000}, {0xc36ea000}, {0xc36ec000}, {0xc36ee000},
+ {0xc36f0000}, {0xc36f2000}, {0xc36f4000}, {0xc36f6000},
+ {0xc36f8000}, {0xc36fa000}, {0xc36fc000}, {0xc36fe000},
+ {0xc3700000}, {0xc3702000}, {0xc3704000}, {0xc3706000},
+ {0xc3708000}, {0xc370a000}, {0xc370c000}, {0xc370e000},
+ {0xc3710000}, {0xc3712000}, {0xc3714000}, {0xc3716000},
+ {0xc3718000}, {0xc371a000}, {0xc371c000}, {0xc371e000},
+ {0xc3720000}, {0xc3722000}, {0xc3724000}, {0xc3726000},
+ {0xc3728000}, {0xc372a000}, {0xc372c000}, {0xc372e000},
+ {0xc3730000}, {0xc3732000}, {0xc3734000}, {0xc3736000},
+ {0xc3738000}, {0xc373a000}, {0xc373c000}, {0xc373e000},
+ {0xc3740000}, {0xc3742000}, {0xc3744000}, {0xc3746000},
+ {0xc3748000}, {0xc374a000}, {0xc374c000}, {0xc374e000},
+ {0xc3750000}, {0xc3752000}, {0xc3754000}, {0xc3756000},
+ {0xc3758000}, {0xc375a000}, {0xc375c000}, {0xc375e000},
+ {0xc3760000}, {0xc3762000}, {0xc3764000}, {0xc3766000},
+ {0xc3768000}, {0xc376a000}, {0xc376c000}, {0xc376e000},
+ {0xc3770000}, {0xc3772000}, {0xc3774000}, {0xc3776000},
+ {0xc3778000}, {0xc377a000}, {0xc377c000}, {0xc377e000},
+ {0xc3780000}, {0xc3782000}, {0xc3784000}, {0xc3786000},
+ {0xc3788000}, {0xc378a000}, {0xc378c000}, {0xc378e000},
+ {0xc3790000}, {0xc3792000}, {0xc3794000}, {0xc3796000},
+ {0xc3798000}, {0xc379a000}, {0xc379c000}, {0xc379e000},
+ {0xc37a0000}, {0xc37a2000}, {0xc37a4000}, {0xc37a6000},
+ {0xc37a8000}, {0xc37aa000}, {0xc37ac000}, {0xc37ae000},
+ {0xc37b0000}, {0xc37b2000}, {0xc37b4000}, {0xc37b6000},
+ {0xc37b8000}, {0xc37ba000}, {0xc37bc000}, {0xc37be000},
+ {0xc37c0000}, {0xc37c2000}, {0xc37c4000}, {0xc37c6000},
+ {0xc37c8000}, {0xc37ca000}, {0xc37cc000}, {0xc37ce000},
+ {0xc37d0000}, {0xc37d2000}, {0xc37d4000}, {0xc37d6000},
+ {0xc37d8000}, {0xc37da000}, {0xc37dc000}, {0xc37de000},
+ {0xc37e0000}, {0xc37e2000}, {0xc37e4000}, {0xc37e6000},
+ {0xc37e8000}, {0xc37ea000}, {0xc37ec000}, {0xc37ee000},
+ {0xc37f0000}, {0xc37f2000}, {0xc37f4000}, {0xc37f6000},
+ {0xc37f8000}, {0xc37fa000}, {0xc37fc000}, {0xc37fe000},
+ {0xc3800000}, {0xc3802000}, {0xc3804000}, {0xc3806000},
+ {0xc3808000}, {0xc380a000}, {0xc380c000}, {0xc380e000},
+ {0xc3810000}, {0xc3812000}, {0xc3814000}, {0xc3816000},
+ {0xc3818000}, {0xc381a000}, {0xc381c000}, {0xc381e000},
+ {0xc3820000}, {0xc3822000}, {0xc3824000}, {0xc3826000},
+ {0xc3828000}, {0xc382a000}, {0xc382c000}, {0xc382e000},
+ {0xc3830000}, {0xc3832000}, {0xc3834000}, {0xc3836000},
+ {0xc3838000}, {0xc383a000}, {0xc383c000}, {0xc383e000},
+ {0xc3840000}, {0xc3842000}, {0xc3844000}, {0xc3846000},
+ {0xc3848000}, {0xc384a000}, {0xc384c000}, {0xc384e000},
+ {0xc3850000}, {0xc3852000}, {0xc3854000}, {0xc3856000},
+ {0xc3858000}, {0xc385a000}, {0xc385c000}, {0xc385e000},
+ {0xc3860000}, {0xc3862000}, {0xc3864000}, {0xc3866000},
+ {0xc3868000}, {0xc386a000}, {0xc386c000}, {0xc386e000},
+ {0xc3870000}, {0xc3872000}, {0xc3874000}, {0xc3876000},
+ {0xc3878000}, {0xc387a000}, {0xc387c000}, {0xc387e000},
+ {0xc3880000}, {0xc3882000}, {0xc3884000}, {0xc3886000},
+ {0xc3888000}, {0xc388a000}, {0xc388c000}, {0xc388e000},
+ {0xc3890000}, {0xc3892000}, {0xc3894000}, {0xc3896000},
+ {0xc3898000}, {0xc389a000}, {0xc389c000}, {0xc389e000},
+ {0xc38a0000}, {0xc38a2000}, {0xc38a4000}, {0xc38a6000},
+ {0xc38a8000}, {0xc38aa000}, {0xc38ac000}, {0xc38ae000},
+ {0xc38b0000}, {0xc38b2000}, {0xc38b4000}, {0xc38b6000},
+ {0xc38b8000}, {0xc38ba000}, {0xc38bc000}, {0xc38be000},
+ {0xc38c0000}, {0xc38c2000}, {0xc38c4000}, {0xc38c6000},
+ {0xc38c8000}, {0xc38ca000}, {0xc38cc000}, {0xc38ce000},
+ {0xc38d0000}, {0xc38d2000}, {0xc38d4000}, {0xc38d6000},
+ {0xc38d8000}, {0xc38da000}, {0xc38dc000}, {0xc38de000},
+ {0xc38e0000}, {0xc38e2000}, {0xc38e4000}, {0xc38e6000},
+ {0xc38e8000}, {0xc38ea000}, {0xc38ec000}, {0xc38ee000},
+ {0xc38f0000}, {0xc38f2000}, {0xc38f4000}, {0xc38f6000},
+ {0xc38f8000}, {0xc38fa000}, {0xc38fc000}, {0xc38fe000},
+ {0xc3900000}, {0xc3902000}, {0xc3904000}, {0xc3906000},
+ {0xc3908000}, {0xc390a000}, {0xc390c000}, {0xc390e000},
+ {0xc3910000}, {0xc3912000}, {0xc3914000}, {0xc3916000},
+ {0xc3918000}, {0xc391a000}, {0xc391c000}, {0xc391e000},
+ {0xc3920000}, {0xc3922000}, {0xc3924000}, {0xc3926000},
+ {0xc3928000}, {0xc392a000}, {0xc392c000}, {0xc392e000},
+ {0xc3930000}, {0xc3932000}, {0xc3934000}, {0xc3936000},
+ {0xc3938000}, {0xc393a000}, {0xc393c000}, {0xc393e000},
+ {0xc3940000}, {0xc3942000}, {0xc3944000}, {0xc3946000},
+ {0xc3948000}, {0xc394a000}, {0xc394c000}, {0xc394e000},
+ {0xc3950000}, {0xc3952000}, {0xc3954000}, {0xc3956000},
+ {0xc3958000}, {0xc395a000}, {0xc395c000}, {0xc395e000},
+ {0xc3960000}, {0xc3962000}, {0xc3964000}, {0xc3966000},
+ {0xc3968000}, {0xc396a000}, {0xc396c000}, {0xc396e000},
+ {0xc3970000}, {0xc3972000}, {0xc3974000}, {0xc3976000},
+ {0xc3978000}, {0xc397a000}, {0xc397c000}, {0xc397e000},
+ {0xc3980000}, {0xc3982000}, {0xc3984000}, {0xc3986000},
+ {0xc3988000}, {0xc398a000}, {0xc398c000}, {0xc398e000},
+ {0xc3990000}, {0xc3992000}, {0xc3994000}, {0xc3996000},
+ {0xc3998000}, {0xc399a000}, {0xc399c000}, {0xc399e000},
+ {0xc39a0000}, {0xc39a2000}, {0xc39a4000}, {0xc39a6000},
+ {0xc39a8000}, {0xc39aa000}, {0xc39ac000}, {0xc39ae000},
+ {0xc39b0000}, {0xc39b2000}, {0xc39b4000}, {0xc39b6000},
+ {0xc39b8000}, {0xc39ba000}, {0xc39bc000}, {0xc39be000},
+ {0xc39c0000}, {0xc39c2000}, {0xc39c4000}, {0xc39c6000},
+ {0xc39c8000}, {0xc39ca000}, {0xc39cc000}, {0xc39ce000},
+ {0xc39d0000}, {0xc39d2000}, {0xc39d4000}, {0xc39d6000},
+ {0xc39d8000}, {0xc39da000}, {0xc39dc000}, {0xc39de000},
+ {0xc39e0000}, {0xc39e2000}, {0xc39e4000}, {0xc39e6000},
+ {0xc39e8000}, {0xc39ea000}, {0xc39ec000}, {0xc39ee000},
+ {0xc39f0000}, {0xc39f2000}, {0xc39f4000}, {0xc39f6000},
+ {0xc39f8000}, {0xc39fa000}, {0xc39fc000}, {0xc39fe000},
+ {0xc3a00000}, {0xc3a02000}, {0xc3a04000}, {0xc3a06000},
+ {0xc3a08000}, {0xc3a0a000}, {0xc3a0c000}, {0xc3a0e000},
+ {0xc3a10000}, {0xc3a12000}, {0xc3a14000}, {0xc3a16000},
+ {0xc3a18000}, {0xc3a1a000}, {0xc3a1c000}, {0xc3a1e000},
+ {0xc3a20000}, {0xc3a22000}, {0xc3a24000}, {0xc3a26000},
+ {0xc3a28000}, {0xc3a2a000}, {0xc3a2c000}, {0xc3a2e000},
+ {0xc3a30000}, {0xc3a32000}, {0xc3a34000}, {0xc3a36000},
+ {0xc3a38000}, {0xc3a3a000}, {0xc3a3c000}, {0xc3a3e000},
+ {0xc3a40000}, {0xc3a42000}, {0xc3a44000}, {0xc3a46000},
+ {0xc3a48000}, {0xc3a4a000}, {0xc3a4c000}, {0xc3a4e000},
+ {0xc3a50000}, {0xc3a52000}, {0xc3a54000}, {0xc3a56000},
+ {0xc3a58000}, {0xc3a5a000}, {0xc3a5c000}, {0xc3a5e000},
+ {0xc3a60000}, {0xc3a62000}, {0xc3a64000}, {0xc3a66000},
+ {0xc3a68000}, {0xc3a6a000}, {0xc3a6c000}, {0xc3a6e000},
+ {0xc3a70000}, {0xc3a72000}, {0xc3a74000}, {0xc3a76000},
+ {0xc3a78000}, {0xc3a7a000}, {0xc3a7c000}, {0xc3a7e000},
+ {0xc3a80000}, {0xc3a82000}, {0xc3a84000}, {0xc3a86000},
+ {0xc3a88000}, {0xc3a8a000}, {0xc3a8c000}, {0xc3a8e000},
+ {0xc3a90000}, {0xc3a92000}, {0xc3a94000}, {0xc3a96000},
+ {0xc3a98000}, {0xc3a9a000}, {0xc3a9c000}, {0xc3a9e000},
+ {0xc3aa0000}, {0xc3aa2000}, {0xc3aa4000}, {0xc3aa6000},
+ {0xc3aa8000}, {0xc3aaa000}, {0xc3aac000}, {0xc3aae000},
+ {0xc3ab0000}, {0xc3ab2000}, {0xc3ab4000}, {0xc3ab6000},
+ {0xc3ab8000}, {0xc3aba000}, {0xc3abc000}, {0xc3abe000},
+ {0xc3ac0000}, {0xc3ac2000}, {0xc3ac4000}, {0xc3ac6000},
+ {0xc3ac8000}, {0xc3aca000}, {0xc3acc000}, {0xc3ace000},
+ {0xc3ad0000}, {0xc3ad2000}, {0xc3ad4000}, {0xc3ad6000},
+ {0xc3ad8000}, {0xc3ada000}, {0xc3adc000}, {0xc3ade000},
+ {0xc3ae0000}, {0xc3ae2000}, {0xc3ae4000}, {0xc3ae6000},
+ {0xc3ae8000}, {0xc3aea000}, {0xc3aec000}, {0xc3aee000},
+ {0xc3af0000}, {0xc3af2000}, {0xc3af4000}, {0xc3af6000},
+ {0xc3af8000}, {0xc3afa000}, {0xc3afc000}, {0xc3afe000},
+ {0xc3b00000}, {0xc3b02000}, {0xc3b04000}, {0xc3b06000},
+ {0xc3b08000}, {0xc3b0a000}, {0xc3b0c000}, {0xc3b0e000},
+ {0xc3b10000}, {0xc3b12000}, {0xc3b14000}, {0xc3b16000},
+ {0xc3b18000}, {0xc3b1a000}, {0xc3b1c000}, {0xc3b1e000},
+ {0xc3b20000}, {0xc3b22000}, {0xc3b24000}, {0xc3b26000},
+ {0xc3b28000}, {0xc3b2a000}, {0xc3b2c000}, {0xc3b2e000},
+ {0xc3b30000}, {0xc3b32000}, {0xc3b34000}, {0xc3b36000},
+ {0xc3b38000}, {0xc3b3a000}, {0xc3b3c000}, {0xc3b3e000},
+ {0xc3b40000}, {0xc3b42000}, {0xc3b44000}, {0xc3b46000},
+ {0xc3b48000}, {0xc3b4a000}, {0xc3b4c000}, {0xc3b4e000},
+ {0xc3b50000}, {0xc3b52000}, {0xc3b54000}, {0xc3b56000},
+ {0xc3b58000}, {0xc3b5a000}, {0xc3b5c000}, {0xc3b5e000},
+ {0xc3b60000}, {0xc3b62000}, {0xc3b64000}, {0xc3b66000},
+ {0xc3b68000}, {0xc3b6a000}, {0xc3b6c000}, {0xc3b6e000},
+ {0xc3b70000}, {0xc3b72000}, {0xc3b74000}, {0xc3b76000},
+ {0xc3b78000}, {0xc3b7a000}, {0xc3b7c000}, {0xc3b7e000},
+ {0xc3b80000}, {0xc3b82000}, {0xc3b84000}, {0xc3b86000},
+ {0xc3b88000}, {0xc3b8a000}, {0xc3b8c000}, {0xc3b8e000},
+ {0xc3b90000}, {0xc3b92000}, {0xc3b94000}, {0xc3b96000},
+ {0xc3b98000}, {0xc3b9a000}, {0xc3b9c000}, {0xc3b9e000},
+ {0xc3ba0000}, {0xc3ba2000}, {0xc3ba4000}, {0xc3ba6000},
+ {0xc3ba8000}, {0xc3baa000}, {0xc3bac000}, {0xc3bae000},
+ {0xc3bb0000}, {0xc3bb2000}, {0xc3bb4000}, {0xc3bb6000},
+ {0xc3bb8000}, {0xc3bba000}, {0xc3bbc000}, {0xc3bbe000},
+ {0xc3bc0000}, {0xc3bc2000}, {0xc3bc4000}, {0xc3bc6000},
+ {0xc3bc8000}, {0xc3bca000}, {0xc3bcc000}, {0xc3bce000},
+ {0xc3bd0000}, {0xc3bd2000}, {0xc3bd4000}, {0xc3bd6000},
+ {0xc3bd8000}, {0xc3bda000}, {0xc3bdc000}, {0xc3bde000},
+ {0xc3be0000}, {0xc3be2000}, {0xc3be4000}, {0xc3be6000},
+ {0xc3be8000}, {0xc3bea000}, {0xc3bec000}, {0xc3bee000},
+ {0xc3bf0000}, {0xc3bf2000}, {0xc3bf4000}, {0xc3bf6000},
+ {0xc3bf8000}, {0xc3bfa000}, {0xc3bfc000}, {0xc3bfe000},
+ {0xc3c00000}, {0xc3c02000}, {0xc3c04000}, {0xc3c06000},
+ {0xc3c08000}, {0xc3c0a000}, {0xc3c0c000}, {0xc3c0e000},
+ {0xc3c10000}, {0xc3c12000}, {0xc3c14000}, {0xc3c16000},
+ {0xc3c18000}, {0xc3c1a000}, {0xc3c1c000}, {0xc3c1e000},
+ {0xc3c20000}, {0xc3c22000}, {0xc3c24000}, {0xc3c26000},
+ {0xc3c28000}, {0xc3c2a000}, {0xc3c2c000}, {0xc3c2e000},
+ {0xc3c30000}, {0xc3c32000}, {0xc3c34000}, {0xc3c36000},
+ {0xc3c38000}, {0xc3c3a000}, {0xc3c3c000}, {0xc3c3e000},
+ {0xc3c40000}, {0xc3c42000}, {0xc3c44000}, {0xc3c46000},
+ {0xc3c48000}, {0xc3c4a000}, {0xc3c4c000}, {0xc3c4e000},
+ {0xc3c50000}, {0xc3c52000}, {0xc3c54000}, {0xc3c56000},
+ {0xc3c58000}, {0xc3c5a000}, {0xc3c5c000}, {0xc3c5e000},
+ {0xc3c60000}, {0xc3c62000}, {0xc3c64000}, {0xc3c66000},
+ {0xc3c68000}, {0xc3c6a000}, {0xc3c6c000}, {0xc3c6e000},
+ {0xc3c70000}, {0xc3c72000}, {0xc3c74000}, {0xc3c76000},
+ {0xc3c78000}, {0xc3c7a000}, {0xc3c7c000}, {0xc3c7e000},
+ {0xc3c80000}, {0xc3c82000}, {0xc3c84000}, {0xc3c86000},
+ {0xc3c88000}, {0xc3c8a000}, {0xc3c8c000}, {0xc3c8e000},
+ {0xc3c90000}, {0xc3c92000}, {0xc3c94000}, {0xc3c96000},
+ {0xc3c98000}, {0xc3c9a000}, {0xc3c9c000}, {0xc3c9e000},
+ {0xc3ca0000}, {0xc3ca2000}, {0xc3ca4000}, {0xc3ca6000},
+ {0xc3ca8000}, {0xc3caa000}, {0xc3cac000}, {0xc3cae000},
+ {0xc3cb0000}, {0xc3cb2000}, {0xc3cb4000}, {0xc3cb6000},
+ {0xc3cb8000}, {0xc3cba000}, {0xc3cbc000}, {0xc3cbe000},
+ {0xc3cc0000}, {0xc3cc2000}, {0xc3cc4000}, {0xc3cc6000},
+ {0xc3cc8000}, {0xc3cca000}, {0xc3ccc000}, {0xc3cce000},
+ {0xc3cd0000}, {0xc3cd2000}, {0xc3cd4000}, {0xc3cd6000},
+ {0xc3cd8000}, {0xc3cda000}, {0xc3cdc000}, {0xc3cde000},
+ {0xc3ce0000}, {0xc3ce2000}, {0xc3ce4000}, {0xc3ce6000},
+ {0xc3ce8000}, {0xc3cea000}, {0xc3cec000}, {0xc3cee000},
+ {0xc3cf0000}, {0xc3cf2000}, {0xc3cf4000}, {0xc3cf6000},
+ {0xc3cf8000}, {0xc3cfa000}, {0xc3cfc000}, {0xc3cfe000},
+ {0xc3d00000}, {0xc3d02000}, {0xc3d04000}, {0xc3d06000},
+ {0xc3d08000}, {0xc3d0a000}, {0xc3d0c000}, {0xc3d0e000},
+ {0xc3d10000}, {0xc3d12000}, {0xc3d14000}, {0xc3d16000},
+ {0xc3d18000}, {0xc3d1a000}, {0xc3d1c000}, {0xc3d1e000},
+ {0xc3d20000}, {0xc3d22000}, {0xc3d24000}, {0xc3d26000},
+ {0xc3d28000}, {0xc3d2a000}, {0xc3d2c000}, {0xc3d2e000},
+ {0xc3d30000}, {0xc3d32000}, {0xc3d34000}, {0xc3d36000},
+ {0xc3d38000}, {0xc3d3a000}, {0xc3d3c000}, {0xc3d3e000},
+ {0xc3d40000}, {0xc3d42000}, {0xc3d44000}, {0xc3d46000},
+ {0xc3d48000}, {0xc3d4a000}, {0xc3d4c000}, {0xc3d4e000},
+ {0xc3d50000}, {0xc3d52000}, {0xc3d54000}, {0xc3d56000},
+ {0xc3d58000}, {0xc3d5a000}, {0xc3d5c000}, {0xc3d5e000},
+ {0xc3d60000}, {0xc3d62000}, {0xc3d64000}, {0xc3d66000},
+ {0xc3d68000}, {0xc3d6a000}, {0xc3d6c000}, {0xc3d6e000},
+ {0xc3d70000}, {0xc3d72000}, {0xc3d74000}, {0xc3d76000},
+ {0xc3d78000}, {0xc3d7a000}, {0xc3d7c000}, {0xc3d7e000},
+ {0xc3d80000}, {0xc3d82000}, {0xc3d84000}, {0xc3d86000},
+ {0xc3d88000}, {0xc3d8a000}, {0xc3d8c000}, {0xc3d8e000},
+ {0xc3d90000}, {0xc3d92000}, {0xc3d94000}, {0xc3d96000},
+ {0xc3d98000}, {0xc3d9a000}, {0xc3d9c000}, {0xc3d9e000},
+ {0xc3da0000}, {0xc3da2000}, {0xc3da4000}, {0xc3da6000},
+ {0xc3da8000}, {0xc3daa000}, {0xc3dac000}, {0xc3dae000},
+ {0xc3db0000}, {0xc3db2000}, {0xc3db4000}, {0xc3db6000},
+ {0xc3db8000}, {0xc3dba000}, {0xc3dbc000}, {0xc3dbe000},
+ {0xc3dc0000}, {0xc3dc2000}, {0xc3dc4000}, {0xc3dc6000},
+ {0xc3dc8000}, {0xc3dca000}, {0xc3dcc000}, {0xc3dce000},
+ {0xc3dd0000}, {0xc3dd2000}, {0xc3dd4000}, {0xc3dd6000},
+ {0xc3dd8000}, {0xc3dda000}, {0xc3ddc000}, {0xc3dde000},
+ {0xc3de0000}, {0xc3de2000}, {0xc3de4000}, {0xc3de6000},
+ {0xc3de8000}, {0xc3dea000}, {0xc3dec000}, {0xc3dee000},
+ {0xc3df0000}, {0xc3df2000}, {0xc3df4000}, {0xc3df6000},
+ {0xc3df8000}, {0xc3dfa000}, {0xc3dfc000}, {0xc3dfe000},
+ {0xc3e00000}, {0xc3e02000}, {0xc3e04000}, {0xc3e06000},
+ {0xc3e08000}, {0xc3e0a000}, {0xc3e0c000}, {0xc3e0e000},
+ {0xc3e10000}, {0xc3e12000}, {0xc3e14000}, {0xc3e16000},
+ {0xc3e18000}, {0xc3e1a000}, {0xc3e1c000}, {0xc3e1e000},
+ {0xc3e20000}, {0xc3e22000}, {0xc3e24000}, {0xc3e26000},
+ {0xc3e28000}, {0xc3e2a000}, {0xc3e2c000}, {0xc3e2e000},
+ {0xc3e30000}, {0xc3e32000}, {0xc3e34000}, {0xc3e36000},
+ {0xc3e38000}, {0xc3e3a000}, {0xc3e3c000}, {0xc3e3e000},
+ {0xc3e40000}, {0xc3e42000}, {0xc3e44000}, {0xc3e46000},
+ {0xc3e48000}, {0xc3e4a000}, {0xc3e4c000}, {0xc3e4e000},
+ {0xc3e50000}, {0xc3e52000}, {0xc3e54000}, {0xc3e56000},
+ {0xc3e58000}, {0xc3e5a000}, {0xc3e5c000}, {0xc3e5e000},
+ {0xc3e60000}, {0xc3e62000}, {0xc3e64000}, {0xc3e66000},
+ {0xc3e68000}, {0xc3e6a000}, {0xc3e6c000}, {0xc3e6e000},
+ {0xc3e70000}, {0xc3e72000}, {0xc3e74000}, {0xc3e76000},
+ {0xc3e78000}, {0xc3e7a000}, {0xc3e7c000}, {0xc3e7e000},
+ {0xc3e80000}, {0xc3e82000}, {0xc3e84000}, {0xc3e86000},
+ {0xc3e88000}, {0xc3e8a000}, {0xc3e8c000}, {0xc3e8e000},
+ {0xc3e90000}, {0xc3e92000}, {0xc3e94000}, {0xc3e96000},
+ {0xc3e98000}, {0xc3e9a000}, {0xc3e9c000}, {0xc3e9e000},
+ {0xc3ea0000}, {0xc3ea2000}, {0xc3ea4000}, {0xc3ea6000},
+ {0xc3ea8000}, {0xc3eaa000}, {0xc3eac000}, {0xc3eae000},
+ {0xc3eb0000}, {0xc3eb2000}, {0xc3eb4000}, {0xc3eb6000},
+ {0xc3eb8000}, {0xc3eba000}, {0xc3ebc000}, {0xc3ebe000},
+ {0xc3ec0000}, {0xc3ec2000}, {0xc3ec4000}, {0xc3ec6000},
+ {0xc3ec8000}, {0xc3eca000}, {0xc3ecc000}, {0xc3ece000},
+ {0xc3ed0000}, {0xc3ed2000}, {0xc3ed4000}, {0xc3ed6000},
+ {0xc3ed8000}, {0xc3eda000}, {0xc3edc000}, {0xc3ede000},
+ {0xc3ee0000}, {0xc3ee2000}, {0xc3ee4000}, {0xc3ee6000},
+ {0xc3ee8000}, {0xc3eea000}, {0xc3eec000}, {0xc3eee000},
+ {0xc3ef0000}, {0xc3ef2000}, {0xc3ef4000}, {0xc3ef6000},
+ {0xc3ef8000}, {0xc3efa000}, {0xc3efc000}, {0xc3efe000},
+ {0xc3f00000}, {0xc3f02000}, {0xc3f04000}, {0xc3f06000},
+ {0xc3f08000}, {0xc3f0a000}, {0xc3f0c000}, {0xc3f0e000},
+ {0xc3f10000}, {0xc3f12000}, {0xc3f14000}, {0xc3f16000},
+ {0xc3f18000}, {0xc3f1a000}, {0xc3f1c000}, {0xc3f1e000},
+ {0xc3f20000}, {0xc3f22000}, {0xc3f24000}, {0xc3f26000},
+ {0xc3f28000}, {0xc3f2a000}, {0xc3f2c000}, {0xc3f2e000},
+ {0xc3f30000}, {0xc3f32000}, {0xc3f34000}, {0xc3f36000},
+ {0xc3f38000}, {0xc3f3a000}, {0xc3f3c000}, {0xc3f3e000},
+ {0xc3f40000}, {0xc3f42000}, {0xc3f44000}, {0xc3f46000},
+ {0xc3f48000}, {0xc3f4a000}, {0xc3f4c000}, {0xc3f4e000},
+ {0xc3f50000}, {0xc3f52000}, {0xc3f54000}, {0xc3f56000},
+ {0xc3f58000}, {0xc3f5a000}, {0xc3f5c000}, {0xc3f5e000},
+ {0xc3f60000}, {0xc3f62000}, {0xc3f64000}, {0xc3f66000},
+ {0xc3f68000}, {0xc3f6a000}, {0xc3f6c000}, {0xc3f6e000},
+ {0xc3f70000}, {0xc3f72000}, {0xc3f74000}, {0xc3f76000},
+ {0xc3f78000}, {0xc3f7a000}, {0xc3f7c000}, {0xc3f7e000},
+ {0xc3f80000}, {0xc3f82000}, {0xc3f84000}, {0xc3f86000},
+ {0xc3f88000}, {0xc3f8a000}, {0xc3f8c000}, {0xc3f8e000},
+ {0xc3f90000}, {0xc3f92000}, {0xc3f94000}, {0xc3f96000},
+ {0xc3f98000}, {0xc3f9a000}, {0xc3f9c000}, {0xc3f9e000},
+ {0xc3fa0000}, {0xc3fa2000}, {0xc3fa4000}, {0xc3fa6000},
+ {0xc3fa8000}, {0xc3faa000}, {0xc3fac000}, {0xc3fae000},
+ {0xc3fb0000}, {0xc3fb2000}, {0xc3fb4000}, {0xc3fb6000},
+ {0xc3fb8000}, {0xc3fba000}, {0xc3fbc000}, {0xc3fbe000},
+ {0xc3fc0000}, {0xc3fc2000}, {0xc3fc4000}, {0xc3fc6000},
+ {0xc3fc8000}, {0xc3fca000}, {0xc3fcc000}, {0xc3fce000},
+ {0xc3fd0000}, {0xc3fd2000}, {0xc3fd4000}, {0xc3fd6000},
+ {0xc3fd8000}, {0xc3fda000}, {0xc3fdc000}, {0xc3fde000},
+ {0xc3fe0000}, {0xc3fe2000}, {0xc3fe4000}, {0xc3fe6000},
+ {0xc3fe8000}, {0xc3fea000}, {0xc3fec000}, {0xc3fee000},
+ {0xc3ff0000}, {0xc3ff2000}, {0xc3ff4000}, {0xc3ff6000},
+ {0xc3ff8000}, {0xc3ffa000}, {0xc3ffc000}, {0xc3ffe000},
+ {0xc4000000}, {0xc4002000}, {0xc4004000}, {0xc4006000},
+ {0xc4008000}, {0xc400a000}, {0xc400c000}, {0xc400e000},
+ {0xc4010000}, {0xc4012000}, {0xc4014000}, {0xc4016000},
+ {0xc4018000}, {0xc401a000}, {0xc401c000}, {0xc401e000},
+ {0xc4020000}, {0xc4022000}, {0xc4024000}, {0xc4026000},
+ {0xc4028000}, {0xc402a000}, {0xc402c000}, {0xc402e000},
+ {0xc4030000}, {0xc4032000}, {0xc4034000}, {0xc4036000},
+ {0xc4038000}, {0xc403a000}, {0xc403c000}, {0xc403e000},
+ {0xc4040000}, {0xc4042000}, {0xc4044000}, {0xc4046000},
+ {0xc4048000}, {0xc404a000}, {0xc404c000}, {0xc404e000},
+ {0xc4050000}, {0xc4052000}, {0xc4054000}, {0xc4056000},
+ {0xc4058000}, {0xc405a000}, {0xc405c000}, {0xc405e000},
+ {0xc4060000}, {0xc4062000}, {0xc4064000}, {0xc4066000},
+ {0xc4068000}, {0xc406a000}, {0xc406c000}, {0xc406e000},
+ {0xc4070000}, {0xc4072000}, {0xc4074000}, {0xc4076000},
+ {0xc4078000}, {0xc407a000}, {0xc407c000}, {0xc407e000},
+ {0xc4080000}, {0xc4082000}, {0xc4084000}, {0xc4086000},
+ {0xc4088000}, {0xc408a000}, {0xc408c000}, {0xc408e000},
+ {0xc4090000}, {0xc4092000}, {0xc4094000}, {0xc4096000},
+ {0xc4098000}, {0xc409a000}, {0xc409c000}, {0xc409e000},
+ {0xc40a0000}, {0xc40a2000}, {0xc40a4000}, {0xc40a6000},
+ {0xc40a8000}, {0xc40aa000}, {0xc40ac000}, {0xc40ae000},
+ {0xc40b0000}, {0xc40b2000}, {0xc40b4000}, {0xc40b6000},
+ {0xc40b8000}, {0xc40ba000}, {0xc40bc000}, {0xc40be000},
+ {0xc40c0000}, {0xc40c2000}, {0xc40c4000}, {0xc40c6000},
+ {0xc40c8000}, {0xc40ca000}, {0xc40cc000}, {0xc40ce000},
+ {0xc40d0000}, {0xc40d2000}, {0xc40d4000}, {0xc40d6000},
+ {0xc40d8000}, {0xc40da000}, {0xc40dc000}, {0xc40de000},
+ {0xc40e0000}, {0xc40e2000}, {0xc40e4000}, {0xc40e6000},
+ {0xc40e8000}, {0xc40ea000}, {0xc40ec000}, {0xc40ee000},
+ {0xc40f0000}, {0xc40f2000}, {0xc40f4000}, {0xc40f6000},
+ {0xc40f8000}, {0xc40fa000}, {0xc40fc000}, {0xc40fe000},
+ {0xc4100000}, {0xc4102000}, {0xc4104000}, {0xc4106000},
+ {0xc4108000}, {0xc410a000}, {0xc410c000}, {0xc410e000},
+ {0xc4110000}, {0xc4112000}, {0xc4114000}, {0xc4116000},
+ {0xc4118000}, {0xc411a000}, {0xc411c000}, {0xc411e000},
+ {0xc4120000}, {0xc4122000}, {0xc4124000}, {0xc4126000},
+ {0xc4128000}, {0xc412a000}, {0xc412c000}, {0xc412e000},
+ {0xc4130000}, {0xc4132000}, {0xc4134000}, {0xc4136000},
+ {0xc4138000}, {0xc413a000}, {0xc413c000}, {0xc413e000},
+ {0xc4140000}, {0xc4142000}, {0xc4144000}, {0xc4146000},
+ {0xc4148000}, {0xc414a000}, {0xc414c000}, {0xc414e000},
+ {0xc4150000}, {0xc4152000}, {0xc4154000}, {0xc4156000},
+ {0xc4158000}, {0xc415a000}, {0xc415c000}, {0xc415e000},
+ {0xc4160000}, {0xc4162000}, {0xc4164000}, {0xc4166000},
+ {0xc4168000}, {0xc416a000}, {0xc416c000}, {0xc416e000},
+ {0xc4170000}, {0xc4172000}, {0xc4174000}, {0xc4176000},
+ {0xc4178000}, {0xc417a000}, {0xc417c000}, {0xc417e000},
+ {0xc4180000}, {0xc4182000}, {0xc4184000}, {0xc4186000},
+ {0xc4188000}, {0xc418a000}, {0xc418c000}, {0xc418e000},
+ {0xc4190000}, {0xc4192000}, {0xc4194000}, {0xc4196000},
+ {0xc4198000}, {0xc419a000}, {0xc419c000}, {0xc419e000},
+ {0xc41a0000}, {0xc41a2000}, {0xc41a4000}, {0xc41a6000},
+ {0xc41a8000}, {0xc41aa000}, {0xc41ac000}, {0xc41ae000},
+ {0xc41b0000}, {0xc41b2000}, {0xc41b4000}, {0xc41b6000},
+ {0xc41b8000}, {0xc41ba000}, {0xc41bc000}, {0xc41be000},
+ {0xc41c0000}, {0xc41c2000}, {0xc41c4000}, {0xc41c6000},
+ {0xc41c8000}, {0xc41ca000}, {0xc41cc000}, {0xc41ce000},
+ {0xc41d0000}, {0xc41d2000}, {0xc41d4000}, {0xc41d6000},
+ {0xc41d8000}, {0xc41da000}, {0xc41dc000}, {0xc41de000},
+ {0xc41e0000}, {0xc41e2000}, {0xc41e4000}, {0xc41e6000},
+ {0xc41e8000}, {0xc41ea000}, {0xc41ec000}, {0xc41ee000},
+ {0xc41f0000}, {0xc41f2000}, {0xc41f4000}, {0xc41f6000},
+ {0xc41f8000}, {0xc41fa000}, {0xc41fc000}, {0xc41fe000},
+ {0xc4200000}, {0xc4202000}, {0xc4204000}, {0xc4206000},
+ {0xc4208000}, {0xc420a000}, {0xc420c000}, {0xc420e000},
+ {0xc4210000}, {0xc4212000}, {0xc4214000}, {0xc4216000},
+ {0xc4218000}, {0xc421a000}, {0xc421c000}, {0xc421e000},
+ {0xc4220000}, {0xc4222000}, {0xc4224000}, {0xc4226000},
+ {0xc4228000}, {0xc422a000}, {0xc422c000}, {0xc422e000},
+ {0xc4230000}, {0xc4232000}, {0xc4234000}, {0xc4236000},
+ {0xc4238000}, {0xc423a000}, {0xc423c000}, {0xc423e000},
+ {0xc4240000}, {0xc4242000}, {0xc4244000}, {0xc4246000},
+ {0xc4248000}, {0xc424a000}, {0xc424c000}, {0xc424e000},
+ {0xc4250000}, {0xc4252000}, {0xc4254000}, {0xc4256000},
+ {0xc4258000}, {0xc425a000}, {0xc425c000}, {0xc425e000},
+ {0xc4260000}, {0xc4262000}, {0xc4264000}, {0xc4266000},
+ {0xc4268000}, {0xc426a000}, {0xc426c000}, {0xc426e000},
+ {0xc4270000}, {0xc4272000}, {0xc4274000}, {0xc4276000},
+ {0xc4278000}, {0xc427a000}, {0xc427c000}, {0xc427e000},
+ {0xc4280000}, {0xc4282000}, {0xc4284000}, {0xc4286000},
+ {0xc4288000}, {0xc428a000}, {0xc428c000}, {0xc428e000},
+ {0xc4290000}, {0xc4292000}, {0xc4294000}, {0xc4296000},
+ {0xc4298000}, {0xc429a000}, {0xc429c000}, {0xc429e000},
+ {0xc42a0000}, {0xc42a2000}, {0xc42a4000}, {0xc42a6000},
+ {0xc42a8000}, {0xc42aa000}, {0xc42ac000}, {0xc42ae000},
+ {0xc42b0000}, {0xc42b2000}, {0xc42b4000}, {0xc42b6000},
+ {0xc42b8000}, {0xc42ba000}, {0xc42bc000}, {0xc42be000},
+ {0xc42c0000}, {0xc42c2000}, {0xc42c4000}, {0xc42c6000},
+ {0xc42c8000}, {0xc42ca000}, {0xc42cc000}, {0xc42ce000},
+ {0xc42d0000}, {0xc42d2000}, {0xc42d4000}, {0xc42d6000},
+ {0xc42d8000}, {0xc42da000}, {0xc42dc000}, {0xc42de000},
+ {0xc42e0000}, {0xc42e2000}, {0xc42e4000}, {0xc42e6000},
+ {0xc42e8000}, {0xc42ea000}, {0xc42ec000}, {0xc42ee000},
+ {0xc42f0000}, {0xc42f2000}, {0xc42f4000}, {0xc42f6000},
+ {0xc42f8000}, {0xc42fa000}, {0xc42fc000}, {0xc42fe000},
+ {0xc4300000}, {0xc4302000}, {0xc4304000}, {0xc4306000},
+ {0xc4308000}, {0xc430a000}, {0xc430c000}, {0xc430e000},
+ {0xc4310000}, {0xc4312000}, {0xc4314000}, {0xc4316000},
+ {0xc4318000}, {0xc431a000}, {0xc431c000}, {0xc431e000},
+ {0xc4320000}, {0xc4322000}, {0xc4324000}, {0xc4326000},
+ {0xc4328000}, {0xc432a000}, {0xc432c000}, {0xc432e000},
+ {0xc4330000}, {0xc4332000}, {0xc4334000}, {0xc4336000},
+ {0xc4338000}, {0xc433a000}, {0xc433c000}, {0xc433e000},
+ {0xc4340000}, {0xc4342000}, {0xc4344000}, {0xc4346000},
+ {0xc4348000}, {0xc434a000}, {0xc434c000}, {0xc434e000},
+ {0xc4350000}, {0xc4352000}, {0xc4354000}, {0xc4356000},
+ {0xc4358000}, {0xc435a000}, {0xc435c000}, {0xc435e000},
+ {0xc4360000}, {0xc4362000}, {0xc4364000}, {0xc4366000},
+ {0xc4368000}, {0xc436a000}, {0xc436c000}, {0xc436e000},
+ {0xc4370000}, {0xc4372000}, {0xc4374000}, {0xc4376000},
+ {0xc4378000}, {0xc437a000}, {0xc437c000}, {0xc437e000},
+ {0xc4380000}, {0xc4382000}, {0xc4384000}, {0xc4386000},
+ {0xc4388000}, {0xc438a000}, {0xc438c000}, {0xc438e000},
+ {0xc4390000}, {0xc4392000}, {0xc4394000}, {0xc4396000},
+ {0xc4398000}, {0xc439a000}, {0xc439c000}, {0xc439e000},
+ {0xc43a0000}, {0xc43a2000}, {0xc43a4000}, {0xc43a6000},
+ {0xc43a8000}, {0xc43aa000}, {0xc43ac000}, {0xc43ae000},
+ {0xc43b0000}, {0xc43b2000}, {0xc43b4000}, {0xc43b6000},
+ {0xc43b8000}, {0xc43ba000}, {0xc43bc000}, {0xc43be000},
+ {0xc43c0000}, {0xc43c2000}, {0xc43c4000}, {0xc43c6000},
+ {0xc43c8000}, {0xc43ca000}, {0xc43cc000}, {0xc43ce000},
+ {0xc43d0000}, {0xc43d2000}, {0xc43d4000}, {0xc43d6000},
+ {0xc43d8000}, {0xc43da000}, {0xc43dc000}, {0xc43de000},
+ {0xc43e0000}, {0xc43e2000}, {0xc43e4000}, {0xc43e6000},
+ {0xc43e8000}, {0xc43ea000}, {0xc43ec000}, {0xc43ee000},
+ {0xc43f0000}, {0xc43f2000}, {0xc43f4000}, {0xc43f6000},
+ {0xc43f8000}, {0xc43fa000}, {0xc43fc000}, {0xc43fe000},
+ {0xc4400000}, {0xc4402000}, {0xc4404000}, {0xc4406000},
+ {0xc4408000}, {0xc440a000}, {0xc440c000}, {0xc440e000},
+ {0xc4410000}, {0xc4412000}, {0xc4414000}, {0xc4416000},
+ {0xc4418000}, {0xc441a000}, {0xc441c000}, {0xc441e000},
+ {0xc4420000}, {0xc4422000}, {0xc4424000}, {0xc4426000},
+ {0xc4428000}, {0xc442a000}, {0xc442c000}, {0xc442e000},
+ {0xc4430000}, {0xc4432000}, {0xc4434000}, {0xc4436000},
+ {0xc4438000}, {0xc443a000}, {0xc443c000}, {0xc443e000},
+ {0xc4440000}, {0xc4442000}, {0xc4444000}, {0xc4446000},
+ {0xc4448000}, {0xc444a000}, {0xc444c000}, {0xc444e000},
+ {0xc4450000}, {0xc4452000}, {0xc4454000}, {0xc4456000},
+ {0xc4458000}, {0xc445a000}, {0xc445c000}, {0xc445e000},
+ {0xc4460000}, {0xc4462000}, {0xc4464000}, {0xc4466000},
+ {0xc4468000}, {0xc446a000}, {0xc446c000}, {0xc446e000},
+ {0xc4470000}, {0xc4472000}, {0xc4474000}, {0xc4476000},
+ {0xc4478000}, {0xc447a000}, {0xc447c000}, {0xc447e000},
+ {0xc4480000}, {0xc4482000}, {0xc4484000}, {0xc4486000},
+ {0xc4488000}, {0xc448a000}, {0xc448c000}, {0xc448e000},
+ {0xc4490000}, {0xc4492000}, {0xc4494000}, {0xc4496000},
+ {0xc4498000}, {0xc449a000}, {0xc449c000}, {0xc449e000},
+ {0xc44a0000}, {0xc44a2000}, {0xc44a4000}, {0xc44a6000},
+ {0xc44a8000}, {0xc44aa000}, {0xc44ac000}, {0xc44ae000},
+ {0xc44b0000}, {0xc44b2000}, {0xc44b4000}, {0xc44b6000},
+ {0xc44b8000}, {0xc44ba000}, {0xc44bc000}, {0xc44be000},
+ {0xc44c0000}, {0xc44c2000}, {0xc44c4000}, {0xc44c6000},
+ {0xc44c8000}, {0xc44ca000}, {0xc44cc000}, {0xc44ce000},
+ {0xc44d0000}, {0xc44d2000}, {0xc44d4000}, {0xc44d6000},
+ {0xc44d8000}, {0xc44da000}, {0xc44dc000}, {0xc44de000},
+ {0xc44e0000}, {0xc44e2000}, {0xc44e4000}, {0xc44e6000},
+ {0xc44e8000}, {0xc44ea000}, {0xc44ec000}, {0xc44ee000},
+ {0xc44f0000}, {0xc44f2000}, {0xc44f4000}, {0xc44f6000},
+ {0xc44f8000}, {0xc44fa000}, {0xc44fc000}, {0xc44fe000},
+ {0xc4500000}, {0xc4502000}, {0xc4504000}, {0xc4506000},
+ {0xc4508000}, {0xc450a000}, {0xc450c000}, {0xc450e000},
+ {0xc4510000}, {0xc4512000}, {0xc4514000}, {0xc4516000},
+ {0xc4518000}, {0xc451a000}, {0xc451c000}, {0xc451e000},
+ {0xc4520000}, {0xc4522000}, {0xc4524000}, {0xc4526000},
+ {0xc4528000}, {0xc452a000}, {0xc452c000}, {0xc452e000},
+ {0xc4530000}, {0xc4532000}, {0xc4534000}, {0xc4536000},
+ {0xc4538000}, {0xc453a000}, {0xc453c000}, {0xc453e000},
+ {0xc4540000}, {0xc4542000}, {0xc4544000}, {0xc4546000},
+ {0xc4548000}, {0xc454a000}, {0xc454c000}, {0xc454e000},
+ {0xc4550000}, {0xc4552000}, {0xc4554000}, {0xc4556000},
+ {0xc4558000}, {0xc455a000}, {0xc455c000}, {0xc455e000},
+ {0xc4560000}, {0xc4562000}, {0xc4564000}, {0xc4566000},
+ {0xc4568000}, {0xc456a000}, {0xc456c000}, {0xc456e000},
+ {0xc4570000}, {0xc4572000}, {0xc4574000}, {0xc4576000},
+ {0xc4578000}, {0xc457a000}, {0xc457c000}, {0xc457e000},
+ {0xc4580000}, {0xc4582000}, {0xc4584000}, {0xc4586000},
+ {0xc4588000}, {0xc458a000}, {0xc458c000}, {0xc458e000},
+ {0xc4590000}, {0xc4592000}, {0xc4594000}, {0xc4596000},
+ {0xc4598000}, {0xc459a000}, {0xc459c000}, {0xc459e000},
+ {0xc45a0000}, {0xc45a2000}, {0xc45a4000}, {0xc45a6000},
+ {0xc45a8000}, {0xc45aa000}, {0xc45ac000}, {0xc45ae000},
+ {0xc45b0000}, {0xc45b2000}, {0xc45b4000}, {0xc45b6000},
+ {0xc45b8000}, {0xc45ba000}, {0xc45bc000}, {0xc45be000},
+ {0xc45c0000}, {0xc45c2000}, {0xc45c4000}, {0xc45c6000},
+ {0xc45c8000}, {0xc45ca000}, {0xc45cc000}, {0xc45ce000},
+ {0xc45d0000}, {0xc45d2000}, {0xc45d4000}, {0xc45d6000},
+ {0xc45d8000}, {0xc45da000}, {0xc45dc000}, {0xc45de000},
+ {0xc45e0000}, {0xc45e2000}, {0xc45e4000}, {0xc45e6000},
+ {0xc45e8000}, {0xc45ea000}, {0xc45ec000}, {0xc45ee000},
+ {0xc45f0000}, {0xc45f2000}, {0xc45f4000}, {0xc45f6000},
+ {0xc45f8000}, {0xc45fa000}, {0xc45fc000}, {0xc45fe000},
+ {0xc4600000}, {0xc4602000}, {0xc4604000}, {0xc4606000},
+ {0xc4608000}, {0xc460a000}, {0xc460c000}, {0xc460e000},
+ {0xc4610000}, {0xc4612000}, {0xc4614000}, {0xc4616000},
+ {0xc4618000}, {0xc461a000}, {0xc461c000}, {0xc461e000},
+ {0xc4620000}, {0xc4622000}, {0xc4624000}, {0xc4626000},
+ {0xc4628000}, {0xc462a000}, {0xc462c000}, {0xc462e000},
+ {0xc4630000}, {0xc4632000}, {0xc4634000}, {0xc4636000},
+ {0xc4638000}, {0xc463a000}, {0xc463c000}, {0xc463e000},
+ {0xc4640000}, {0xc4642000}, {0xc4644000}, {0xc4646000},
+ {0xc4648000}, {0xc464a000}, {0xc464c000}, {0xc464e000},
+ {0xc4650000}, {0xc4652000}, {0xc4654000}, {0xc4656000},
+ {0xc4658000}, {0xc465a000}, {0xc465c000}, {0xc465e000},
+ {0xc4660000}, {0xc4662000}, {0xc4664000}, {0xc4666000},
+ {0xc4668000}, {0xc466a000}, {0xc466c000}, {0xc466e000},
+ {0xc4670000}, {0xc4672000}, {0xc4674000}, {0xc4676000},
+ {0xc4678000}, {0xc467a000}, {0xc467c000}, {0xc467e000},
+ {0xc4680000}, {0xc4682000}, {0xc4684000}, {0xc4686000},
+ {0xc4688000}, {0xc468a000}, {0xc468c000}, {0xc468e000},
+ {0xc4690000}, {0xc4692000}, {0xc4694000}, {0xc4696000},
+ {0xc4698000}, {0xc469a000}, {0xc469c000}, {0xc469e000},
+ {0xc46a0000}, {0xc46a2000}, {0xc46a4000}, {0xc46a6000},
+ {0xc46a8000}, {0xc46aa000}, {0xc46ac000}, {0xc46ae000},
+ {0xc46b0000}, {0xc46b2000}, {0xc46b4000}, {0xc46b6000},
+ {0xc46b8000}, {0xc46ba000}, {0xc46bc000}, {0xc46be000},
+ {0xc46c0000}, {0xc46c2000}, {0xc46c4000}, {0xc46c6000},
+ {0xc46c8000}, {0xc46ca000}, {0xc46cc000}, {0xc46ce000},
+ {0xc46d0000}, {0xc46d2000}, {0xc46d4000}, {0xc46d6000},
+ {0xc46d8000}, {0xc46da000}, {0xc46dc000}, {0xc46de000},
+ {0xc46e0000}, {0xc46e2000}, {0xc46e4000}, {0xc46e6000},
+ {0xc46e8000}, {0xc46ea000}, {0xc46ec000}, {0xc46ee000},
+ {0xc46f0000}, {0xc46f2000}, {0xc46f4000}, {0xc46f6000},
+ {0xc46f8000}, {0xc46fa000}, {0xc46fc000}, {0xc46fe000},
+ {0xc4700000}, {0xc4702000}, {0xc4704000}, {0xc4706000},
+ {0xc4708000}, {0xc470a000}, {0xc470c000}, {0xc470e000},
+ {0xc4710000}, {0xc4712000}, {0xc4714000}, {0xc4716000},
+ {0xc4718000}, {0xc471a000}, {0xc471c000}, {0xc471e000},
+ {0xc4720000}, {0xc4722000}, {0xc4724000}, {0xc4726000},
+ {0xc4728000}, {0xc472a000}, {0xc472c000}, {0xc472e000},
+ {0xc4730000}, {0xc4732000}, {0xc4734000}, {0xc4736000},
+ {0xc4738000}, {0xc473a000}, {0xc473c000}, {0xc473e000},
+ {0xc4740000}, {0xc4742000}, {0xc4744000}, {0xc4746000},
+ {0xc4748000}, {0xc474a000}, {0xc474c000}, {0xc474e000},
+ {0xc4750000}, {0xc4752000}, {0xc4754000}, {0xc4756000},
+ {0xc4758000}, {0xc475a000}, {0xc475c000}, {0xc475e000},
+ {0xc4760000}, {0xc4762000}, {0xc4764000}, {0xc4766000},
+ {0xc4768000}, {0xc476a000}, {0xc476c000}, {0xc476e000},
+ {0xc4770000}, {0xc4772000}, {0xc4774000}, {0xc4776000},
+ {0xc4778000}, {0xc477a000}, {0xc477c000}, {0xc477e000},
+ {0xc4780000}, {0xc4782000}, {0xc4784000}, {0xc4786000},
+ {0xc4788000}, {0xc478a000}, {0xc478c000}, {0xc478e000},
+ {0xc4790000}, {0xc4792000}, {0xc4794000}, {0xc4796000},
+ {0xc4798000}, {0xc479a000}, {0xc479c000}, {0xc479e000},
+ {0xc47a0000}, {0xc47a2000}, {0xc47a4000}, {0xc47a6000},
+ {0xc47a8000}, {0xc47aa000}, {0xc47ac000}, {0xc47ae000},
+ {0xc47b0000}, {0xc47b2000}, {0xc47b4000}, {0xc47b6000},
+ {0xc47b8000}, {0xc47ba000}, {0xc47bc000}, {0xc47be000},
+ {0xc47c0000}, {0xc47c2000}, {0xc47c4000}, {0xc47c6000},
+ {0xc47c8000}, {0xc47ca000}, {0xc47cc000}, {0xc47ce000},
+ {0xc47d0000}, {0xc47d2000}, {0xc47d4000}, {0xc47d6000},
+ {0xc47d8000}, {0xc47da000}, {0xc47dc000}, {0xc47de000},
+ {0xc47e0000}, {0xc47e2000}, {0xc47e4000}, {0xc47e6000},
+ {0xc47e8000}, {0xc47ea000}, {0xc47ec000}, {0xc47ee000},
+ {0xc47f0000}, {0xc47f2000}, {0xc47f4000}, {0xc47f6000},
+ {0xc47f8000}, {0xc47fa000}, {0xc47fc000}, {0xc47fe000},
+ {0xc4800000}, {0xc4802000}, {0xc4804000}, {0xc4806000},
+ {0xc4808000}, {0xc480a000}, {0xc480c000}, {0xc480e000},
+ {0xc4810000}, {0xc4812000}, {0xc4814000}, {0xc4816000},
+ {0xc4818000}, {0xc481a000}, {0xc481c000}, {0xc481e000},
+ {0xc4820000}, {0xc4822000}, {0xc4824000}, {0xc4826000},
+ {0xc4828000}, {0xc482a000}, {0xc482c000}, {0xc482e000},
+ {0xc4830000}, {0xc4832000}, {0xc4834000}, {0xc4836000},
+ {0xc4838000}, {0xc483a000}, {0xc483c000}, {0xc483e000},
+ {0xc4840000}, {0xc4842000}, {0xc4844000}, {0xc4846000},
+ {0xc4848000}, {0xc484a000}, {0xc484c000}, {0xc484e000},
+ {0xc4850000}, {0xc4852000}, {0xc4854000}, {0xc4856000},
+ {0xc4858000}, {0xc485a000}, {0xc485c000}, {0xc485e000},
+ {0xc4860000}, {0xc4862000}, {0xc4864000}, {0xc4866000},
+ {0xc4868000}, {0xc486a000}, {0xc486c000}, {0xc486e000},
+ {0xc4870000}, {0xc4872000}, {0xc4874000}, {0xc4876000},
+ {0xc4878000}, {0xc487a000}, {0xc487c000}, {0xc487e000},
+ {0xc4880000}, {0xc4882000}, {0xc4884000}, {0xc4886000},
+ {0xc4888000}, {0xc488a000}, {0xc488c000}, {0xc488e000},
+ {0xc4890000}, {0xc4892000}, {0xc4894000}, {0xc4896000},
+ {0xc4898000}, {0xc489a000}, {0xc489c000}, {0xc489e000},
+ {0xc48a0000}, {0xc48a2000}, {0xc48a4000}, {0xc48a6000},
+ {0xc48a8000}, {0xc48aa000}, {0xc48ac000}, {0xc48ae000},
+ {0xc48b0000}, {0xc48b2000}, {0xc48b4000}, {0xc48b6000},
+ {0xc48b8000}, {0xc48ba000}, {0xc48bc000}, {0xc48be000},
+ {0xc48c0000}, {0xc48c2000}, {0xc48c4000}, {0xc48c6000},
+ {0xc48c8000}, {0xc48ca000}, {0xc48cc000}, {0xc48ce000},
+ {0xc48d0000}, {0xc48d2000}, {0xc48d4000}, {0xc48d6000},
+ {0xc48d8000}, {0xc48da000}, {0xc48dc000}, {0xc48de000},
+ {0xc48e0000}, {0xc48e2000}, {0xc48e4000}, {0xc48e6000},
+ {0xc48e8000}, {0xc48ea000}, {0xc48ec000}, {0xc48ee000},
+ {0xc48f0000}, {0xc48f2000}, {0xc48f4000}, {0xc48f6000},
+ {0xc48f8000}, {0xc48fa000}, {0xc48fc000}, {0xc48fe000},
+ {0xc4900000}, {0xc4902000}, {0xc4904000}, {0xc4906000},
+ {0xc4908000}, {0xc490a000}, {0xc490c000}, {0xc490e000},
+ {0xc4910000}, {0xc4912000}, {0xc4914000}, {0xc4916000},
+ {0xc4918000}, {0xc491a000}, {0xc491c000}, {0xc491e000},
+ {0xc4920000}, {0xc4922000}, {0xc4924000}, {0xc4926000},
+ {0xc4928000}, {0xc492a000}, {0xc492c000}, {0xc492e000},
+ {0xc4930000}, {0xc4932000}, {0xc4934000}, {0xc4936000},
+ {0xc4938000}, {0xc493a000}, {0xc493c000}, {0xc493e000},
+ {0xc4940000}, {0xc4942000}, {0xc4944000}, {0xc4946000},
+ {0xc4948000}, {0xc494a000}, {0xc494c000}, {0xc494e000},
+ {0xc4950000}, {0xc4952000}, {0xc4954000}, {0xc4956000},
+ {0xc4958000}, {0xc495a000}, {0xc495c000}, {0xc495e000},
+ {0xc4960000}, {0xc4962000}, {0xc4964000}, {0xc4966000},
+ {0xc4968000}, {0xc496a000}, {0xc496c000}, {0xc496e000},
+ {0xc4970000}, {0xc4972000}, {0xc4974000}, {0xc4976000},
+ {0xc4978000}, {0xc497a000}, {0xc497c000}, {0xc497e000},
+ {0xc4980000}, {0xc4982000}, {0xc4984000}, {0xc4986000},
+ {0xc4988000}, {0xc498a000}, {0xc498c000}, {0xc498e000},
+ {0xc4990000}, {0xc4992000}, {0xc4994000}, {0xc4996000},
+ {0xc4998000}, {0xc499a000}, {0xc499c000}, {0xc499e000},
+ {0xc49a0000}, {0xc49a2000}, {0xc49a4000}, {0xc49a6000},
+ {0xc49a8000}, {0xc49aa000}, {0xc49ac000}, {0xc49ae000},
+ {0xc49b0000}, {0xc49b2000}, {0xc49b4000}, {0xc49b6000},
+ {0xc49b8000}, {0xc49ba000}, {0xc49bc000}, {0xc49be000},
+ {0xc49c0000}, {0xc49c2000}, {0xc49c4000}, {0xc49c6000},
+ {0xc49c8000}, {0xc49ca000}, {0xc49cc000}, {0xc49ce000},
+ {0xc49d0000}, {0xc49d2000}, {0xc49d4000}, {0xc49d6000},
+ {0xc49d8000}, {0xc49da000}, {0xc49dc000}, {0xc49de000},
+ {0xc49e0000}, {0xc49e2000}, {0xc49e4000}, {0xc49e6000},
+ {0xc49e8000}, {0xc49ea000}, {0xc49ec000}, {0xc49ee000},
+ {0xc49f0000}, {0xc49f2000}, {0xc49f4000}, {0xc49f6000},
+ {0xc49f8000}, {0xc49fa000}, {0xc49fc000}, {0xc49fe000},
+ {0xc4a00000}, {0xc4a02000}, {0xc4a04000}, {0xc4a06000},
+ {0xc4a08000}, {0xc4a0a000}, {0xc4a0c000}, {0xc4a0e000},
+ {0xc4a10000}, {0xc4a12000}, {0xc4a14000}, {0xc4a16000},
+ {0xc4a18000}, {0xc4a1a000}, {0xc4a1c000}, {0xc4a1e000},
+ {0xc4a20000}, {0xc4a22000}, {0xc4a24000}, {0xc4a26000},
+ {0xc4a28000}, {0xc4a2a000}, {0xc4a2c000}, {0xc4a2e000},
+ {0xc4a30000}, {0xc4a32000}, {0xc4a34000}, {0xc4a36000},
+ {0xc4a38000}, {0xc4a3a000}, {0xc4a3c000}, {0xc4a3e000},
+ {0xc4a40000}, {0xc4a42000}, {0xc4a44000}, {0xc4a46000},
+ {0xc4a48000}, {0xc4a4a000}, {0xc4a4c000}, {0xc4a4e000},
+ {0xc4a50000}, {0xc4a52000}, {0xc4a54000}, {0xc4a56000},
+ {0xc4a58000}, {0xc4a5a000}, {0xc4a5c000}, {0xc4a5e000},
+ {0xc4a60000}, {0xc4a62000}, {0xc4a64000}, {0xc4a66000},
+ {0xc4a68000}, {0xc4a6a000}, {0xc4a6c000}, {0xc4a6e000},
+ {0xc4a70000}, {0xc4a72000}, {0xc4a74000}, {0xc4a76000},
+ {0xc4a78000}, {0xc4a7a000}, {0xc4a7c000}, {0xc4a7e000},
+ {0xc4a80000}, {0xc4a82000}, {0xc4a84000}, {0xc4a86000},
+ {0xc4a88000}, {0xc4a8a000}, {0xc4a8c000}, {0xc4a8e000},
+ {0xc4a90000}, {0xc4a92000}, {0xc4a94000}, {0xc4a96000},
+ {0xc4a98000}, {0xc4a9a000}, {0xc4a9c000}, {0xc4a9e000},
+ {0xc4aa0000}, {0xc4aa2000}, {0xc4aa4000}, {0xc4aa6000},
+ {0xc4aa8000}, {0xc4aaa000}, {0xc4aac000}, {0xc4aae000},
+ {0xc4ab0000}, {0xc4ab2000}, {0xc4ab4000}, {0xc4ab6000},
+ {0xc4ab8000}, {0xc4aba000}, {0xc4abc000}, {0xc4abe000},
+ {0xc4ac0000}, {0xc4ac2000}, {0xc4ac4000}, {0xc4ac6000},
+ {0xc4ac8000}, {0xc4aca000}, {0xc4acc000}, {0xc4ace000},
+ {0xc4ad0000}, {0xc4ad2000}, {0xc4ad4000}, {0xc4ad6000},
+ {0xc4ad8000}, {0xc4ada000}, {0xc4adc000}, {0xc4ade000},
+ {0xc4ae0000}, {0xc4ae2000}, {0xc4ae4000}, {0xc4ae6000},
+ {0xc4ae8000}, {0xc4aea000}, {0xc4aec000}, {0xc4aee000},
+ {0xc4af0000}, {0xc4af2000}, {0xc4af4000}, {0xc4af6000},
+ {0xc4af8000}, {0xc4afa000}, {0xc4afc000}, {0xc4afe000},
+ {0xc4b00000}, {0xc4b02000}, {0xc4b04000}, {0xc4b06000},
+ {0xc4b08000}, {0xc4b0a000}, {0xc4b0c000}, {0xc4b0e000},
+ {0xc4b10000}, {0xc4b12000}, {0xc4b14000}, {0xc4b16000},
+ {0xc4b18000}, {0xc4b1a000}, {0xc4b1c000}, {0xc4b1e000},
+ {0xc4b20000}, {0xc4b22000}, {0xc4b24000}, {0xc4b26000},
+ {0xc4b28000}, {0xc4b2a000}, {0xc4b2c000}, {0xc4b2e000},
+ {0xc4b30000}, {0xc4b32000}, {0xc4b34000}, {0xc4b36000},
+ {0xc4b38000}, {0xc4b3a000}, {0xc4b3c000}, {0xc4b3e000},
+ {0xc4b40000}, {0xc4b42000}, {0xc4b44000}, {0xc4b46000},
+ {0xc4b48000}, {0xc4b4a000}, {0xc4b4c000}, {0xc4b4e000},
+ {0xc4b50000}, {0xc4b52000}, {0xc4b54000}, {0xc4b56000},
+ {0xc4b58000}, {0xc4b5a000}, {0xc4b5c000}, {0xc4b5e000},
+ {0xc4b60000}, {0xc4b62000}, {0xc4b64000}, {0xc4b66000},
+ {0xc4b68000}, {0xc4b6a000}, {0xc4b6c000}, {0xc4b6e000},
+ {0xc4b70000}, {0xc4b72000}, {0xc4b74000}, {0xc4b76000},
+ {0xc4b78000}, {0xc4b7a000}, {0xc4b7c000}, {0xc4b7e000},
+ {0xc4b80000}, {0xc4b82000}, {0xc4b84000}, {0xc4b86000},
+ {0xc4b88000}, {0xc4b8a000}, {0xc4b8c000}, {0xc4b8e000},
+ {0xc4b90000}, {0xc4b92000}, {0xc4b94000}, {0xc4b96000},
+ {0xc4b98000}, {0xc4b9a000}, {0xc4b9c000}, {0xc4b9e000},
+ {0xc4ba0000}, {0xc4ba2000}, {0xc4ba4000}, {0xc4ba6000},
+ {0xc4ba8000}, {0xc4baa000}, {0xc4bac000}, {0xc4bae000},
+ {0xc4bb0000}, {0xc4bb2000}, {0xc4bb4000}, {0xc4bb6000},
+ {0xc4bb8000}, {0xc4bba000}, {0xc4bbc000}, {0xc4bbe000},
+ {0xc4bc0000}, {0xc4bc2000}, {0xc4bc4000}, {0xc4bc6000},
+ {0xc4bc8000}, {0xc4bca000}, {0xc4bcc000}, {0xc4bce000},
+ {0xc4bd0000}, {0xc4bd2000}, {0xc4bd4000}, {0xc4bd6000},
+ {0xc4bd8000}, {0xc4bda000}, {0xc4bdc000}, {0xc4bde000},
+ {0xc4be0000}, {0xc4be2000}, {0xc4be4000}, {0xc4be6000},
+ {0xc4be8000}, {0xc4bea000}, {0xc4bec000}, {0xc4bee000},
+ {0xc4bf0000}, {0xc4bf2000}, {0xc4bf4000}, {0xc4bf6000},
+ {0xc4bf8000}, {0xc4bfa000}, {0xc4bfc000}, {0xc4bfe000},
+ {0xc4c00000}, {0xc4c02000}, {0xc4c04000}, {0xc4c06000},
+ {0xc4c08000}, {0xc4c0a000}, {0xc4c0c000}, {0xc4c0e000},
+ {0xc4c10000}, {0xc4c12000}, {0xc4c14000}, {0xc4c16000},
+ {0xc4c18000}, {0xc4c1a000}, {0xc4c1c000}, {0xc4c1e000},
+ {0xc4c20000}, {0xc4c22000}, {0xc4c24000}, {0xc4c26000},
+ {0xc4c28000}, {0xc4c2a000}, {0xc4c2c000}, {0xc4c2e000},
+ {0xc4c30000}, {0xc4c32000}, {0xc4c34000}, {0xc4c36000},
+ {0xc4c38000}, {0xc4c3a000}, {0xc4c3c000}, {0xc4c3e000},
+ {0xc4c40000}, {0xc4c42000}, {0xc4c44000}, {0xc4c46000},
+ {0xc4c48000}, {0xc4c4a000}, {0xc4c4c000}, {0xc4c4e000},
+ {0xc4c50000}, {0xc4c52000}, {0xc4c54000}, {0xc4c56000},
+ {0xc4c58000}, {0xc4c5a000}, {0xc4c5c000}, {0xc4c5e000},
+ {0xc4c60000}, {0xc4c62000}, {0xc4c64000}, {0xc4c66000},
+ {0xc4c68000}, {0xc4c6a000}, {0xc4c6c000}, {0xc4c6e000},
+ {0xc4c70000}, {0xc4c72000}, {0xc4c74000}, {0xc4c76000},
+ {0xc4c78000}, {0xc4c7a000}, {0xc4c7c000}, {0xc4c7e000},
+ {0xc4c80000}, {0xc4c82000}, {0xc4c84000}, {0xc4c86000},
+ {0xc4c88000}, {0xc4c8a000}, {0xc4c8c000}, {0xc4c8e000},
+ {0xc4c90000}, {0xc4c92000}, {0xc4c94000}, {0xc4c96000},
+ {0xc4c98000}, {0xc4c9a000}, {0xc4c9c000}, {0xc4c9e000},
+ {0xc4ca0000}, {0xc4ca2000}, {0xc4ca4000}, {0xc4ca6000},
+ {0xc4ca8000}, {0xc4caa000}, {0xc4cac000}, {0xc4cae000},
+ {0xc4cb0000}, {0xc4cb2000}, {0xc4cb4000}, {0xc4cb6000},
+ {0xc4cb8000}, {0xc4cba000}, {0xc4cbc000}, {0xc4cbe000},
+ {0xc4cc0000}, {0xc4cc2000}, {0xc4cc4000}, {0xc4cc6000},
+ {0xc4cc8000}, {0xc4cca000}, {0xc4ccc000}, {0xc4cce000},
+ {0xc4cd0000}, {0xc4cd2000}, {0xc4cd4000}, {0xc4cd6000},
+ {0xc4cd8000}, {0xc4cda000}, {0xc4cdc000}, {0xc4cde000},
+ {0xc4ce0000}, {0xc4ce2000}, {0xc4ce4000}, {0xc4ce6000},
+ {0xc4ce8000}, {0xc4cea000}, {0xc4cec000}, {0xc4cee000},
+ {0xc4cf0000}, {0xc4cf2000}, {0xc4cf4000}, {0xc4cf6000},
+ {0xc4cf8000}, {0xc4cfa000}, {0xc4cfc000}, {0xc4cfe000},
+ {0xc4d00000}, {0xc4d02000}, {0xc4d04000}, {0xc4d06000},
+ {0xc4d08000}, {0xc4d0a000}, {0xc4d0c000}, {0xc4d0e000},
+ {0xc4d10000}, {0xc4d12000}, {0xc4d14000}, {0xc4d16000},
+ {0xc4d18000}, {0xc4d1a000}, {0xc4d1c000}, {0xc4d1e000},
+ {0xc4d20000}, {0xc4d22000}, {0xc4d24000}, {0xc4d26000},
+ {0xc4d28000}, {0xc4d2a000}, {0xc4d2c000}, {0xc4d2e000},
+ {0xc4d30000}, {0xc4d32000}, {0xc4d34000}, {0xc4d36000},
+ {0xc4d38000}, {0xc4d3a000}, {0xc4d3c000}, {0xc4d3e000},
+ {0xc4d40000}, {0xc4d42000}, {0xc4d44000}, {0xc4d46000},
+ {0xc4d48000}, {0xc4d4a000}, {0xc4d4c000}, {0xc4d4e000},
+ {0xc4d50000}, {0xc4d52000}, {0xc4d54000}, {0xc4d56000},
+ {0xc4d58000}, {0xc4d5a000}, {0xc4d5c000}, {0xc4d5e000},
+ {0xc4d60000}, {0xc4d62000}, {0xc4d64000}, {0xc4d66000},
+ {0xc4d68000}, {0xc4d6a000}, {0xc4d6c000}, {0xc4d6e000},
+ {0xc4d70000}, {0xc4d72000}, {0xc4d74000}, {0xc4d76000},
+ {0xc4d78000}, {0xc4d7a000}, {0xc4d7c000}, {0xc4d7e000},
+ {0xc4d80000}, {0xc4d82000}, {0xc4d84000}, {0xc4d86000},
+ {0xc4d88000}, {0xc4d8a000}, {0xc4d8c000}, {0xc4d8e000},
+ {0xc4d90000}, {0xc4d92000}, {0xc4d94000}, {0xc4d96000},
+ {0xc4d98000}, {0xc4d9a000}, {0xc4d9c000}, {0xc4d9e000},
+ {0xc4da0000}, {0xc4da2000}, {0xc4da4000}, {0xc4da6000},
+ {0xc4da8000}, {0xc4daa000}, {0xc4dac000}, {0xc4dae000},
+ {0xc4db0000}, {0xc4db2000}, {0xc4db4000}, {0xc4db6000},
+ {0xc4db8000}, {0xc4dba000}, {0xc4dbc000}, {0xc4dbe000},
+ {0xc4dc0000}, {0xc4dc2000}, {0xc4dc4000}, {0xc4dc6000},
+ {0xc4dc8000}, {0xc4dca000}, {0xc4dcc000}, {0xc4dce000},
+ {0xc4dd0000}, {0xc4dd2000}, {0xc4dd4000}, {0xc4dd6000},
+ {0xc4dd8000}, {0xc4dda000}, {0xc4ddc000}, {0xc4dde000},
+ {0xc4de0000}, {0xc4de2000}, {0xc4de4000}, {0xc4de6000},
+ {0xc4de8000}, {0xc4dea000}, {0xc4dec000}, {0xc4dee000},
+ {0xc4df0000}, {0xc4df2000}, {0xc4df4000}, {0xc4df6000},
+ {0xc4df8000}, {0xc4dfa000}, {0xc4dfc000}, {0xc4dfe000},
+ {0xc4e00000}, {0xc4e02000}, {0xc4e04000}, {0xc4e06000},
+ {0xc4e08000}, {0xc4e0a000}, {0xc4e0c000}, {0xc4e0e000},
+ {0xc4e10000}, {0xc4e12000}, {0xc4e14000}, {0xc4e16000},
+ {0xc4e18000}, {0xc4e1a000}, {0xc4e1c000}, {0xc4e1e000},
+ {0xc4e20000}, {0xc4e22000}, {0xc4e24000}, {0xc4e26000},
+ {0xc4e28000}, {0xc4e2a000}, {0xc4e2c000}, {0xc4e2e000},
+ {0xc4e30000}, {0xc4e32000}, {0xc4e34000}, {0xc4e36000},
+ {0xc4e38000}, {0xc4e3a000}, {0xc4e3c000}, {0xc4e3e000},
+ {0xc4e40000}, {0xc4e42000}, {0xc4e44000}, {0xc4e46000},
+ {0xc4e48000}, {0xc4e4a000}, {0xc4e4c000}, {0xc4e4e000},
+ {0xc4e50000}, {0xc4e52000}, {0xc4e54000}, {0xc4e56000},
+ {0xc4e58000}, {0xc4e5a000}, {0xc4e5c000}, {0xc4e5e000},
+ {0xc4e60000}, {0xc4e62000}, {0xc4e64000}, {0xc4e66000},
+ {0xc4e68000}, {0xc4e6a000}, {0xc4e6c000}, {0xc4e6e000},
+ {0xc4e70000}, {0xc4e72000}, {0xc4e74000}, {0xc4e76000},
+ {0xc4e78000}, {0xc4e7a000}, {0xc4e7c000}, {0xc4e7e000},
+ {0xc4e80000}, {0xc4e82000}, {0xc4e84000}, {0xc4e86000},
+ {0xc4e88000}, {0xc4e8a000}, {0xc4e8c000}, {0xc4e8e000},
+ {0xc4e90000}, {0xc4e92000}, {0xc4e94000}, {0xc4e96000},
+ {0xc4e98000}, {0xc4e9a000}, {0xc4e9c000}, {0xc4e9e000},
+ {0xc4ea0000}, {0xc4ea2000}, {0xc4ea4000}, {0xc4ea6000},
+ {0xc4ea8000}, {0xc4eaa000}, {0xc4eac000}, {0xc4eae000},
+ {0xc4eb0000}, {0xc4eb2000}, {0xc4eb4000}, {0xc4eb6000},
+ {0xc4eb8000}, {0xc4eba000}, {0xc4ebc000}, {0xc4ebe000},
+ {0xc4ec0000}, {0xc4ec2000}, {0xc4ec4000}, {0xc4ec6000},
+ {0xc4ec8000}, {0xc4eca000}, {0xc4ecc000}, {0xc4ece000},
+ {0xc4ed0000}, {0xc4ed2000}, {0xc4ed4000}, {0xc4ed6000},
+ {0xc4ed8000}, {0xc4eda000}, {0xc4edc000}, {0xc4ede000},
+ {0xc4ee0000}, {0xc4ee2000}, {0xc4ee4000}, {0xc4ee6000},
+ {0xc4ee8000}, {0xc4eea000}, {0xc4eec000}, {0xc4eee000},
+ {0xc4ef0000}, {0xc4ef2000}, {0xc4ef4000}, {0xc4ef6000},
+ {0xc4ef8000}, {0xc4efa000}, {0xc4efc000}, {0xc4efe000},
+ {0xc4f00000}, {0xc4f02000}, {0xc4f04000}, {0xc4f06000},
+ {0xc4f08000}, {0xc4f0a000}, {0xc4f0c000}, {0xc4f0e000},
+ {0xc4f10000}, {0xc4f12000}, {0xc4f14000}, {0xc4f16000},
+ {0xc4f18000}, {0xc4f1a000}, {0xc4f1c000}, {0xc4f1e000},
+ {0xc4f20000}, {0xc4f22000}, {0xc4f24000}, {0xc4f26000},
+ {0xc4f28000}, {0xc4f2a000}, {0xc4f2c000}, {0xc4f2e000},
+ {0xc4f30000}, {0xc4f32000}, {0xc4f34000}, {0xc4f36000},
+ {0xc4f38000}, {0xc4f3a000}, {0xc4f3c000}, {0xc4f3e000},
+ {0xc4f40000}, {0xc4f42000}, {0xc4f44000}, {0xc4f46000},
+ {0xc4f48000}, {0xc4f4a000}, {0xc4f4c000}, {0xc4f4e000},
+ {0xc4f50000}, {0xc4f52000}, {0xc4f54000}, {0xc4f56000},
+ {0xc4f58000}, {0xc4f5a000}, {0xc4f5c000}, {0xc4f5e000},
+ {0xc4f60000}, {0xc4f62000}, {0xc4f64000}, {0xc4f66000},
+ {0xc4f68000}, {0xc4f6a000}, {0xc4f6c000}, {0xc4f6e000},
+ {0xc4f70000}, {0xc4f72000}, {0xc4f74000}, {0xc4f76000},
+ {0xc4f78000}, {0xc4f7a000}, {0xc4f7c000}, {0xc4f7e000},
+ {0xc4f80000}, {0xc4f82000}, {0xc4f84000}, {0xc4f86000},
+ {0xc4f88000}, {0xc4f8a000}, {0xc4f8c000}, {0xc4f8e000},
+ {0xc4f90000}, {0xc4f92000}, {0xc4f94000}, {0xc4f96000},
+ {0xc4f98000}, {0xc4f9a000}, {0xc4f9c000}, {0xc4f9e000},
+ {0xc4fa0000}, {0xc4fa2000}, {0xc4fa4000}, {0xc4fa6000},
+ {0xc4fa8000}, {0xc4faa000}, {0xc4fac000}, {0xc4fae000},
+ {0xc4fb0000}, {0xc4fb2000}, {0xc4fb4000}, {0xc4fb6000},
+ {0xc4fb8000}, {0xc4fba000}, {0xc4fbc000}, {0xc4fbe000},
+ {0xc4fc0000}, {0xc4fc2000}, {0xc4fc4000}, {0xc4fc6000},
+ {0xc4fc8000}, {0xc4fca000}, {0xc4fcc000}, {0xc4fce000},
+ {0xc4fd0000}, {0xc4fd2000}, {0xc4fd4000}, {0xc4fd6000},
+ {0xc4fd8000}, {0xc4fda000}, {0xc4fdc000}, {0xc4fde000},
+ {0xc4fe0000}, {0xc4fe2000}, {0xc4fe4000}, {0xc4fe6000},
+ {0xc4fe8000}, {0xc4fea000}, {0xc4fec000}, {0xc4fee000},
+ {0xc4ff0000}, {0xc4ff2000}, {0xc4ff4000}, {0xc4ff6000},
+ {0xc4ff8000}, {0xc4ffa000}, {0xc4ffc000}, {0xc4ffe000},
+ {0xc5000000}, {0xc5002000}, {0xc5004000}, {0xc5006000},
+ {0xc5008000}, {0xc500a000}, {0xc500c000}, {0xc500e000},
+ {0xc5010000}, {0xc5012000}, {0xc5014000}, {0xc5016000},
+ {0xc5018000}, {0xc501a000}, {0xc501c000}, {0xc501e000},
+ {0xc5020000}, {0xc5022000}, {0xc5024000}, {0xc5026000},
+ {0xc5028000}, {0xc502a000}, {0xc502c000}, {0xc502e000},
+ {0xc5030000}, {0xc5032000}, {0xc5034000}, {0xc5036000},
+ {0xc5038000}, {0xc503a000}, {0xc503c000}, {0xc503e000},
+ {0xc5040000}, {0xc5042000}, {0xc5044000}, {0xc5046000},
+ {0xc5048000}, {0xc504a000}, {0xc504c000}, {0xc504e000},
+ {0xc5050000}, {0xc5052000}, {0xc5054000}, {0xc5056000},
+ {0xc5058000}, {0xc505a000}, {0xc505c000}, {0xc505e000},
+ {0xc5060000}, {0xc5062000}, {0xc5064000}, {0xc5066000},
+ {0xc5068000}, {0xc506a000}, {0xc506c000}, {0xc506e000},
+ {0xc5070000}, {0xc5072000}, {0xc5074000}, {0xc5076000},
+ {0xc5078000}, {0xc507a000}, {0xc507c000}, {0xc507e000},
+ {0xc5080000}, {0xc5082000}, {0xc5084000}, {0xc5086000},
+ {0xc5088000}, {0xc508a000}, {0xc508c000}, {0xc508e000},
+ {0xc5090000}, {0xc5092000}, {0xc5094000}, {0xc5096000},
+ {0xc5098000}, {0xc509a000}, {0xc509c000}, {0xc509e000},
+ {0xc50a0000}, {0xc50a2000}, {0xc50a4000}, {0xc50a6000},
+ {0xc50a8000}, {0xc50aa000}, {0xc50ac000}, {0xc50ae000},
+ {0xc50b0000}, {0xc50b2000}, {0xc50b4000}, {0xc50b6000},
+ {0xc50b8000}, {0xc50ba000}, {0xc50bc000}, {0xc50be000},
+ {0xc50c0000}, {0xc50c2000}, {0xc50c4000}, {0xc50c6000},
+ {0xc50c8000}, {0xc50ca000}, {0xc50cc000}, {0xc50ce000},
+ {0xc50d0000}, {0xc50d2000}, {0xc50d4000}, {0xc50d6000},
+ {0xc50d8000}, {0xc50da000}, {0xc50dc000}, {0xc50de000},
+ {0xc50e0000}, {0xc50e2000}, {0xc50e4000}, {0xc50e6000},
+ {0xc50e8000}, {0xc50ea000}, {0xc50ec000}, {0xc50ee000},
+ {0xc50f0000}, {0xc50f2000}, {0xc50f4000}, {0xc50f6000},
+ {0xc50f8000}, {0xc50fa000}, {0xc50fc000}, {0xc50fe000},
+ {0xc5100000}, {0xc5102000}, {0xc5104000}, {0xc5106000},
+ {0xc5108000}, {0xc510a000}, {0xc510c000}, {0xc510e000},
+ {0xc5110000}, {0xc5112000}, {0xc5114000}, {0xc5116000},
+ {0xc5118000}, {0xc511a000}, {0xc511c000}, {0xc511e000},
+ {0xc5120000}, {0xc5122000}, {0xc5124000}, {0xc5126000},
+ {0xc5128000}, {0xc512a000}, {0xc512c000}, {0xc512e000},
+ {0xc5130000}, {0xc5132000}, {0xc5134000}, {0xc5136000},
+ {0xc5138000}, {0xc513a000}, {0xc513c000}, {0xc513e000},
+ {0xc5140000}, {0xc5142000}, {0xc5144000}, {0xc5146000},
+ {0xc5148000}, {0xc514a000}, {0xc514c000}, {0xc514e000},
+ {0xc5150000}, {0xc5152000}, {0xc5154000}, {0xc5156000},
+ {0xc5158000}, {0xc515a000}, {0xc515c000}, {0xc515e000},
+ {0xc5160000}, {0xc5162000}, {0xc5164000}, {0xc5166000},
+ {0xc5168000}, {0xc516a000}, {0xc516c000}, {0xc516e000},
+ {0xc5170000}, {0xc5172000}, {0xc5174000}, {0xc5176000},
+ {0xc5178000}, {0xc517a000}, {0xc517c000}, {0xc517e000},
+ {0xc5180000}, {0xc5182000}, {0xc5184000}, {0xc5186000},
+ {0xc5188000}, {0xc518a000}, {0xc518c000}, {0xc518e000},
+ {0xc5190000}, {0xc5192000}, {0xc5194000}, {0xc5196000},
+ {0xc5198000}, {0xc519a000}, {0xc519c000}, {0xc519e000},
+ {0xc51a0000}, {0xc51a2000}, {0xc51a4000}, {0xc51a6000},
+ {0xc51a8000}, {0xc51aa000}, {0xc51ac000}, {0xc51ae000},
+ {0xc51b0000}, {0xc51b2000}, {0xc51b4000}, {0xc51b6000},
+ {0xc51b8000}, {0xc51ba000}, {0xc51bc000}, {0xc51be000},
+ {0xc51c0000}, {0xc51c2000}, {0xc51c4000}, {0xc51c6000},
+ {0xc51c8000}, {0xc51ca000}, {0xc51cc000}, {0xc51ce000},
+ {0xc51d0000}, {0xc51d2000}, {0xc51d4000}, {0xc51d6000},
+ {0xc51d8000}, {0xc51da000}, {0xc51dc000}, {0xc51de000},
+ {0xc51e0000}, {0xc51e2000}, {0xc51e4000}, {0xc51e6000},
+ {0xc51e8000}, {0xc51ea000}, {0xc51ec000}, {0xc51ee000},
+ {0xc51f0000}, {0xc51f2000}, {0xc51f4000}, {0xc51f6000},
+ {0xc51f8000}, {0xc51fa000}, {0xc51fc000}, {0xc51fe000},
+ {0xc5200000}, {0xc5202000}, {0xc5204000}, {0xc5206000},
+ {0xc5208000}, {0xc520a000}, {0xc520c000}, {0xc520e000},
+ {0xc5210000}, {0xc5212000}, {0xc5214000}, {0xc5216000},
+ {0xc5218000}, {0xc521a000}, {0xc521c000}, {0xc521e000},
+ {0xc5220000}, {0xc5222000}, {0xc5224000}, {0xc5226000},
+ {0xc5228000}, {0xc522a000}, {0xc522c000}, {0xc522e000},
+ {0xc5230000}, {0xc5232000}, {0xc5234000}, {0xc5236000},
+ {0xc5238000}, {0xc523a000}, {0xc523c000}, {0xc523e000},
+ {0xc5240000}, {0xc5242000}, {0xc5244000}, {0xc5246000},
+ {0xc5248000}, {0xc524a000}, {0xc524c000}, {0xc524e000},
+ {0xc5250000}, {0xc5252000}, {0xc5254000}, {0xc5256000},
+ {0xc5258000}, {0xc525a000}, {0xc525c000}, {0xc525e000},
+ {0xc5260000}, {0xc5262000}, {0xc5264000}, {0xc5266000},
+ {0xc5268000}, {0xc526a000}, {0xc526c000}, {0xc526e000},
+ {0xc5270000}, {0xc5272000}, {0xc5274000}, {0xc5276000},
+ {0xc5278000}, {0xc527a000}, {0xc527c000}, {0xc527e000},
+ {0xc5280000}, {0xc5282000}, {0xc5284000}, {0xc5286000},
+ {0xc5288000}, {0xc528a000}, {0xc528c000}, {0xc528e000},
+ {0xc5290000}, {0xc5292000}, {0xc5294000}, {0xc5296000},
+ {0xc5298000}, {0xc529a000}, {0xc529c000}, {0xc529e000},
+ {0xc52a0000}, {0xc52a2000}, {0xc52a4000}, {0xc52a6000},
+ {0xc52a8000}, {0xc52aa000}, {0xc52ac000}, {0xc52ae000},
+ {0xc52b0000}, {0xc52b2000}, {0xc52b4000}, {0xc52b6000},
+ {0xc52b8000}, {0xc52ba000}, {0xc52bc000}, {0xc52be000},
+ {0xc52c0000}, {0xc52c2000}, {0xc52c4000}, {0xc52c6000},
+ {0xc52c8000}, {0xc52ca000}, {0xc52cc000}, {0xc52ce000},
+ {0xc52d0000}, {0xc52d2000}, {0xc52d4000}, {0xc52d6000},
+ {0xc52d8000}, {0xc52da000}, {0xc52dc000}, {0xc52de000},
+ {0xc52e0000}, {0xc52e2000}, {0xc52e4000}, {0xc52e6000},
+ {0xc52e8000}, {0xc52ea000}, {0xc52ec000}, {0xc52ee000},
+ {0xc52f0000}, {0xc52f2000}, {0xc52f4000}, {0xc52f6000},
+ {0xc52f8000}, {0xc52fa000}, {0xc52fc000}, {0xc52fe000},
+ {0xc5300000}, {0xc5302000}, {0xc5304000}, {0xc5306000},
+ {0xc5308000}, {0xc530a000}, {0xc530c000}, {0xc530e000},
+ {0xc5310000}, {0xc5312000}, {0xc5314000}, {0xc5316000},
+ {0xc5318000}, {0xc531a000}, {0xc531c000}, {0xc531e000},
+ {0xc5320000}, {0xc5322000}, {0xc5324000}, {0xc5326000},
+ {0xc5328000}, {0xc532a000}, {0xc532c000}, {0xc532e000},
+ {0xc5330000}, {0xc5332000}, {0xc5334000}, {0xc5336000},
+ {0xc5338000}, {0xc533a000}, {0xc533c000}, {0xc533e000},
+ {0xc5340000}, {0xc5342000}, {0xc5344000}, {0xc5346000},
+ {0xc5348000}, {0xc534a000}, {0xc534c000}, {0xc534e000},
+ {0xc5350000}, {0xc5352000}, {0xc5354000}, {0xc5356000},
+ {0xc5358000}, {0xc535a000}, {0xc535c000}, {0xc535e000},
+ {0xc5360000}, {0xc5362000}, {0xc5364000}, {0xc5366000},
+ {0xc5368000}, {0xc536a000}, {0xc536c000}, {0xc536e000},
+ {0xc5370000}, {0xc5372000}, {0xc5374000}, {0xc5376000},
+ {0xc5378000}, {0xc537a000}, {0xc537c000}, {0xc537e000},
+ {0xc5380000}, {0xc5382000}, {0xc5384000}, {0xc5386000},
+ {0xc5388000}, {0xc538a000}, {0xc538c000}, {0xc538e000},
+ {0xc5390000}, {0xc5392000}, {0xc5394000}, {0xc5396000},
+ {0xc5398000}, {0xc539a000}, {0xc539c000}, {0xc539e000},
+ {0xc53a0000}, {0xc53a2000}, {0xc53a4000}, {0xc53a6000},
+ {0xc53a8000}, {0xc53aa000}, {0xc53ac000}, {0xc53ae000},
+ {0xc53b0000}, {0xc53b2000}, {0xc53b4000}, {0xc53b6000},
+ {0xc53b8000}, {0xc53ba000}, {0xc53bc000}, {0xc53be000},
+ {0xc53c0000}, {0xc53c2000}, {0xc53c4000}, {0xc53c6000},
+ {0xc53c8000}, {0xc53ca000}, {0xc53cc000}, {0xc53ce000},
+ {0xc53d0000}, {0xc53d2000}, {0xc53d4000}, {0xc53d6000},
+ {0xc53d8000}, {0xc53da000}, {0xc53dc000}, {0xc53de000},
+ {0xc53e0000}, {0xc53e2000}, {0xc53e4000}, {0xc53e6000},
+ {0xc53e8000}, {0xc53ea000}, {0xc53ec000}, {0xc53ee000},
+ {0xc53f0000}, {0xc53f2000}, {0xc53f4000}, {0xc53f6000},
+ {0xc53f8000}, {0xc53fa000}, {0xc53fc000}, {0xc53fe000},
+ {0xc5400000}, {0xc5402000}, {0xc5404000}, {0xc5406000},
+ {0xc5408000}, {0xc540a000}, {0xc540c000}, {0xc540e000},
+ {0xc5410000}, {0xc5412000}, {0xc5414000}, {0xc5416000},
+ {0xc5418000}, {0xc541a000}, {0xc541c000}, {0xc541e000},
+ {0xc5420000}, {0xc5422000}, {0xc5424000}, {0xc5426000},
+ {0xc5428000}, {0xc542a000}, {0xc542c000}, {0xc542e000},
+ {0xc5430000}, {0xc5432000}, {0xc5434000}, {0xc5436000},
+ {0xc5438000}, {0xc543a000}, {0xc543c000}, {0xc543e000},
+ {0xc5440000}, {0xc5442000}, {0xc5444000}, {0xc5446000},
+ {0xc5448000}, {0xc544a000}, {0xc544c000}, {0xc544e000},
+ {0xc5450000}, {0xc5452000}, {0xc5454000}, {0xc5456000},
+ {0xc5458000}, {0xc545a000}, {0xc545c000}, {0xc545e000},
+ {0xc5460000}, {0xc5462000}, {0xc5464000}, {0xc5466000},
+ {0xc5468000}, {0xc546a000}, {0xc546c000}, {0xc546e000},
+ {0xc5470000}, {0xc5472000}, {0xc5474000}, {0xc5476000},
+ {0xc5478000}, {0xc547a000}, {0xc547c000}, {0xc547e000},
+ {0xc5480000}, {0xc5482000}, {0xc5484000}, {0xc5486000},
+ {0xc5488000}, {0xc548a000}, {0xc548c000}, {0xc548e000},
+ {0xc5490000}, {0xc5492000}, {0xc5494000}, {0xc5496000},
+ {0xc5498000}, {0xc549a000}, {0xc549c000}, {0xc549e000},
+ {0xc54a0000}, {0xc54a2000}, {0xc54a4000}, {0xc54a6000},
+ {0xc54a8000}, {0xc54aa000}, {0xc54ac000}, {0xc54ae000},
+ {0xc54b0000}, {0xc54b2000}, {0xc54b4000}, {0xc54b6000},
+ {0xc54b8000}, {0xc54ba000}, {0xc54bc000}, {0xc54be000},
+ {0xc54c0000}, {0xc54c2000}, {0xc54c4000}, {0xc54c6000},
+ {0xc54c8000}, {0xc54ca000}, {0xc54cc000}, {0xc54ce000},
+ {0xc54d0000}, {0xc54d2000}, {0xc54d4000}, {0xc54d6000},
+ {0xc54d8000}, {0xc54da000}, {0xc54dc000}, {0xc54de000},
+ {0xc54e0000}, {0xc54e2000}, {0xc54e4000}, {0xc54e6000},
+ {0xc54e8000}, {0xc54ea000}, {0xc54ec000}, {0xc54ee000},
+ {0xc54f0000}, {0xc54f2000}, {0xc54f4000}, {0xc54f6000},
+ {0xc54f8000}, {0xc54fa000}, {0xc54fc000}, {0xc54fe000},
+ {0xc5500000}, {0xc5502000}, {0xc5504000}, {0xc5506000},
+ {0xc5508000}, {0xc550a000}, {0xc550c000}, {0xc550e000},
+ {0xc5510000}, {0xc5512000}, {0xc5514000}, {0xc5516000},
+ {0xc5518000}, {0xc551a000}, {0xc551c000}, {0xc551e000},
+ {0xc5520000}, {0xc5522000}, {0xc5524000}, {0xc5526000},
+ {0xc5528000}, {0xc552a000}, {0xc552c000}, {0xc552e000},
+ {0xc5530000}, {0xc5532000}, {0xc5534000}, {0xc5536000},
+ {0xc5538000}, {0xc553a000}, {0xc553c000}, {0xc553e000},
+ {0xc5540000}, {0xc5542000}, {0xc5544000}, {0xc5546000},
+ {0xc5548000}, {0xc554a000}, {0xc554c000}, {0xc554e000},
+ {0xc5550000}, {0xc5552000}, {0xc5554000}, {0xc5556000},
+ {0xc5558000}, {0xc555a000}, {0xc555c000}, {0xc555e000},
+ {0xc5560000}, {0xc5562000}, {0xc5564000}, {0xc5566000},
+ {0xc5568000}, {0xc556a000}, {0xc556c000}, {0xc556e000},
+ {0xc5570000}, {0xc5572000}, {0xc5574000}, {0xc5576000},
+ {0xc5578000}, {0xc557a000}, {0xc557c000}, {0xc557e000},
+ {0xc5580000}, {0xc5582000}, {0xc5584000}, {0xc5586000},
+ {0xc5588000}, {0xc558a000}, {0xc558c000}, {0xc558e000},
+ {0xc5590000}, {0xc5592000}, {0xc5594000}, {0xc5596000},
+ {0xc5598000}, {0xc559a000}, {0xc559c000}, {0xc559e000},
+ {0xc55a0000}, {0xc55a2000}, {0xc55a4000}, {0xc55a6000},
+ {0xc55a8000}, {0xc55aa000}, {0xc55ac000}, {0xc55ae000},
+ {0xc55b0000}, {0xc55b2000}, {0xc55b4000}, {0xc55b6000},
+ {0xc55b8000}, {0xc55ba000}, {0xc55bc000}, {0xc55be000},
+ {0xc55c0000}, {0xc55c2000}, {0xc55c4000}, {0xc55c6000},
+ {0xc55c8000}, {0xc55ca000}, {0xc55cc000}, {0xc55ce000},
+ {0xc55d0000}, {0xc55d2000}, {0xc55d4000}, {0xc55d6000},
+ {0xc55d8000}, {0xc55da000}, {0xc55dc000}, {0xc55de000},
+ {0xc55e0000}, {0xc55e2000}, {0xc55e4000}, {0xc55e6000},
+ {0xc55e8000}, {0xc55ea000}, {0xc55ec000}, {0xc55ee000},
+ {0xc55f0000}, {0xc55f2000}, {0xc55f4000}, {0xc55f6000},
+ {0xc55f8000}, {0xc55fa000}, {0xc55fc000}, {0xc55fe000},
+ {0xc5600000}, {0xc5602000}, {0xc5604000}, {0xc5606000},
+ {0xc5608000}, {0xc560a000}, {0xc560c000}, {0xc560e000},
+ {0xc5610000}, {0xc5612000}, {0xc5614000}, {0xc5616000},
+ {0xc5618000}, {0xc561a000}, {0xc561c000}, {0xc561e000},
+ {0xc5620000}, {0xc5622000}, {0xc5624000}, {0xc5626000},
+ {0xc5628000}, {0xc562a000}, {0xc562c000}, {0xc562e000},
+ {0xc5630000}, {0xc5632000}, {0xc5634000}, {0xc5636000},
+ {0xc5638000}, {0xc563a000}, {0xc563c000}, {0xc563e000},
+ {0xc5640000}, {0xc5642000}, {0xc5644000}, {0xc5646000},
+ {0xc5648000}, {0xc564a000}, {0xc564c000}, {0xc564e000},
+ {0xc5650000}, {0xc5652000}, {0xc5654000}, {0xc5656000},
+ {0xc5658000}, {0xc565a000}, {0xc565c000}, {0xc565e000},
+ {0xc5660000}, {0xc5662000}, {0xc5664000}, {0xc5666000},
+ {0xc5668000}, {0xc566a000}, {0xc566c000}, {0xc566e000},
+ {0xc5670000}, {0xc5672000}, {0xc5674000}, {0xc5676000},
+ {0xc5678000}, {0xc567a000}, {0xc567c000}, {0xc567e000},
+ {0xc5680000}, {0xc5682000}, {0xc5684000}, {0xc5686000},
+ {0xc5688000}, {0xc568a000}, {0xc568c000}, {0xc568e000},
+ {0xc5690000}, {0xc5692000}, {0xc5694000}, {0xc5696000},
+ {0xc5698000}, {0xc569a000}, {0xc569c000}, {0xc569e000},
+ {0xc56a0000}, {0xc56a2000}, {0xc56a4000}, {0xc56a6000},
+ {0xc56a8000}, {0xc56aa000}, {0xc56ac000}, {0xc56ae000},
+ {0xc56b0000}, {0xc56b2000}, {0xc56b4000}, {0xc56b6000},
+ {0xc56b8000}, {0xc56ba000}, {0xc56bc000}, {0xc56be000},
+ {0xc56c0000}, {0xc56c2000}, {0xc56c4000}, {0xc56c6000},
+ {0xc56c8000}, {0xc56ca000}, {0xc56cc000}, {0xc56ce000},
+ {0xc56d0000}, {0xc56d2000}, {0xc56d4000}, {0xc56d6000},
+ {0xc56d8000}, {0xc56da000}, {0xc56dc000}, {0xc56de000},
+ {0xc56e0000}, {0xc56e2000}, {0xc56e4000}, {0xc56e6000},
+ {0xc56e8000}, {0xc56ea000}, {0xc56ec000}, {0xc56ee000},
+ {0xc56f0000}, {0xc56f2000}, {0xc56f4000}, {0xc56f6000},
+ {0xc56f8000}, {0xc56fa000}, {0xc56fc000}, {0xc56fe000},
+ {0xc5700000}, {0xc5702000}, {0xc5704000}, {0xc5706000},
+ {0xc5708000}, {0xc570a000}, {0xc570c000}, {0xc570e000},
+ {0xc5710000}, {0xc5712000}, {0xc5714000}, {0xc5716000},
+ {0xc5718000}, {0xc571a000}, {0xc571c000}, {0xc571e000},
+ {0xc5720000}, {0xc5722000}, {0xc5724000}, {0xc5726000},
+ {0xc5728000}, {0xc572a000}, {0xc572c000}, {0xc572e000},
+ {0xc5730000}, {0xc5732000}, {0xc5734000}, {0xc5736000},
+ {0xc5738000}, {0xc573a000}, {0xc573c000}, {0xc573e000},
+ {0xc5740000}, {0xc5742000}, {0xc5744000}, {0xc5746000},
+ {0xc5748000}, {0xc574a000}, {0xc574c000}, {0xc574e000},
+ {0xc5750000}, {0xc5752000}, {0xc5754000}, {0xc5756000},
+ {0xc5758000}, {0xc575a000}, {0xc575c000}, {0xc575e000},
+ {0xc5760000}, {0xc5762000}, {0xc5764000}, {0xc5766000},
+ {0xc5768000}, {0xc576a000}, {0xc576c000}, {0xc576e000},
+ {0xc5770000}, {0xc5772000}, {0xc5774000}, {0xc5776000},
+ {0xc5778000}, {0xc577a000}, {0xc577c000}, {0xc577e000},
+ {0xc5780000}, {0xc5782000}, {0xc5784000}, {0xc5786000},
+ {0xc5788000}, {0xc578a000}, {0xc578c000}, {0xc578e000},
+ {0xc5790000}, {0xc5792000}, {0xc5794000}, {0xc5796000},
+ {0xc5798000}, {0xc579a000}, {0xc579c000}, {0xc579e000},
+ {0xc57a0000}, {0xc57a2000}, {0xc57a4000}, {0xc57a6000},
+ {0xc57a8000}, {0xc57aa000}, {0xc57ac000}, {0xc57ae000},
+ {0xc57b0000}, {0xc57b2000}, {0xc57b4000}, {0xc57b6000},
+ {0xc57b8000}, {0xc57ba000}, {0xc57bc000}, {0xc57be000},
+ {0xc57c0000}, {0xc57c2000}, {0xc57c4000}, {0xc57c6000},
+ {0xc57c8000}, {0xc57ca000}, {0xc57cc000}, {0xc57ce000},
+ {0xc57d0000}, {0xc57d2000}, {0xc57d4000}, {0xc57d6000},
+ {0xc57d8000}, {0xc57da000}, {0xc57dc000}, {0xc57de000},
+ {0xc57e0000}, {0xc57e2000}, {0xc57e4000}, {0xc57e6000},
+ {0xc57e8000}, {0xc57ea000}, {0xc57ec000}, {0xc57ee000},
+ {0xc57f0000}, {0xc57f2000}, {0xc57f4000}, {0xc57f6000},
+ {0xc57f8000}, {0xc57fa000}, {0xc57fc000}, {0xc57fe000},
+ {0xc5800000}, {0xc5802000}, {0xc5804000}, {0xc5806000},
+ {0xc5808000}, {0xc580a000}, {0xc580c000}, {0xc580e000},
+ {0xc5810000}, {0xc5812000}, {0xc5814000}, {0xc5816000},
+ {0xc5818000}, {0xc581a000}, {0xc581c000}, {0xc581e000},
+ {0xc5820000}, {0xc5822000}, {0xc5824000}, {0xc5826000},
+ {0xc5828000}, {0xc582a000}, {0xc582c000}, {0xc582e000},
+ {0xc5830000}, {0xc5832000}, {0xc5834000}, {0xc5836000},
+ {0xc5838000}, {0xc583a000}, {0xc583c000}, {0xc583e000},
+ {0xc5840000}, {0xc5842000}, {0xc5844000}, {0xc5846000},
+ {0xc5848000}, {0xc584a000}, {0xc584c000}, {0xc584e000},
+ {0xc5850000}, {0xc5852000}, {0xc5854000}, {0xc5856000},
+ {0xc5858000}, {0xc585a000}, {0xc585c000}, {0xc585e000},
+ {0xc5860000}, {0xc5862000}, {0xc5864000}, {0xc5866000},
+ {0xc5868000}, {0xc586a000}, {0xc586c000}, {0xc586e000},
+ {0xc5870000}, {0xc5872000}, {0xc5874000}, {0xc5876000},
+ {0xc5878000}, {0xc587a000}, {0xc587c000}, {0xc587e000},
+ {0xc5880000}, {0xc5882000}, {0xc5884000}, {0xc5886000},
+ {0xc5888000}, {0xc588a000}, {0xc588c000}, {0xc588e000},
+ {0xc5890000}, {0xc5892000}, {0xc5894000}, {0xc5896000},
+ {0xc5898000}, {0xc589a000}, {0xc589c000}, {0xc589e000},
+ {0xc58a0000}, {0xc58a2000}, {0xc58a4000}, {0xc58a6000},
+ {0xc58a8000}, {0xc58aa000}, {0xc58ac000}, {0xc58ae000},
+ {0xc58b0000}, {0xc58b2000}, {0xc58b4000}, {0xc58b6000},
+ {0xc58b8000}, {0xc58ba000}, {0xc58bc000}, {0xc58be000},
+ {0xc58c0000}, {0xc58c2000}, {0xc58c4000}, {0xc58c6000},
+ {0xc58c8000}, {0xc58ca000}, {0xc58cc000}, {0xc58ce000},
+ {0xc58d0000}, {0xc58d2000}, {0xc58d4000}, {0xc58d6000},
+ {0xc58d8000}, {0xc58da000}, {0xc58dc000}, {0xc58de000},
+ {0xc58e0000}, {0xc58e2000}, {0xc58e4000}, {0xc58e6000},
+ {0xc58e8000}, {0xc58ea000}, {0xc58ec000}, {0xc58ee000},
+ {0xc58f0000}, {0xc58f2000}, {0xc58f4000}, {0xc58f6000},
+ {0xc58f8000}, {0xc58fa000}, {0xc58fc000}, {0xc58fe000},
+ {0xc5900000}, {0xc5902000}, {0xc5904000}, {0xc5906000},
+ {0xc5908000}, {0xc590a000}, {0xc590c000}, {0xc590e000},
+ {0xc5910000}, {0xc5912000}, {0xc5914000}, {0xc5916000},
+ {0xc5918000}, {0xc591a000}, {0xc591c000}, {0xc591e000},
+ {0xc5920000}, {0xc5922000}, {0xc5924000}, {0xc5926000},
+ {0xc5928000}, {0xc592a000}, {0xc592c000}, {0xc592e000},
+ {0xc5930000}, {0xc5932000}, {0xc5934000}, {0xc5936000},
+ {0xc5938000}, {0xc593a000}, {0xc593c000}, {0xc593e000},
+ {0xc5940000}, {0xc5942000}, {0xc5944000}, {0xc5946000},
+ {0xc5948000}, {0xc594a000}, {0xc594c000}, {0xc594e000},
+ {0xc5950000}, {0xc5952000}, {0xc5954000}, {0xc5956000},
+ {0xc5958000}, {0xc595a000}, {0xc595c000}, {0xc595e000},
+ {0xc5960000}, {0xc5962000}, {0xc5964000}, {0xc5966000},
+ {0xc5968000}, {0xc596a000}, {0xc596c000}, {0xc596e000},
+ {0xc5970000}, {0xc5972000}, {0xc5974000}, {0xc5976000},
+ {0xc5978000}, {0xc597a000}, {0xc597c000}, {0xc597e000},
+ {0xc5980000}, {0xc5982000}, {0xc5984000}, {0xc5986000},
+ {0xc5988000}, {0xc598a000}, {0xc598c000}, {0xc598e000},
+ {0xc5990000}, {0xc5992000}, {0xc5994000}, {0xc5996000},
+ {0xc5998000}, {0xc599a000}, {0xc599c000}, {0xc599e000},
+ {0xc59a0000}, {0xc59a2000}, {0xc59a4000}, {0xc59a6000},
+ {0xc59a8000}, {0xc59aa000}, {0xc59ac000}, {0xc59ae000},
+ {0xc59b0000}, {0xc59b2000}, {0xc59b4000}, {0xc59b6000},
+ {0xc59b8000}, {0xc59ba000}, {0xc59bc000}, {0xc59be000},
+ {0xc59c0000}, {0xc59c2000}, {0xc59c4000}, {0xc59c6000},
+ {0xc59c8000}, {0xc59ca000}, {0xc59cc000}, {0xc59ce000},
+ {0xc59d0000}, {0xc59d2000}, {0xc59d4000}, {0xc59d6000},
+ {0xc59d8000}, {0xc59da000}, {0xc59dc000}, {0xc59de000},
+ {0xc59e0000}, {0xc59e2000}, {0xc59e4000}, {0xc59e6000},
+ {0xc59e8000}, {0xc59ea000}, {0xc59ec000}, {0xc59ee000},
+ {0xc59f0000}, {0xc59f2000}, {0xc59f4000}, {0xc59f6000},
+ {0xc59f8000}, {0xc59fa000}, {0xc59fc000}, {0xc59fe000},
+ {0xc5a00000}, {0xc5a02000}, {0xc5a04000}, {0xc5a06000},
+ {0xc5a08000}, {0xc5a0a000}, {0xc5a0c000}, {0xc5a0e000},
+ {0xc5a10000}, {0xc5a12000}, {0xc5a14000}, {0xc5a16000},
+ {0xc5a18000}, {0xc5a1a000}, {0xc5a1c000}, {0xc5a1e000},
+ {0xc5a20000}, {0xc5a22000}, {0xc5a24000}, {0xc5a26000},
+ {0xc5a28000}, {0xc5a2a000}, {0xc5a2c000}, {0xc5a2e000},
+ {0xc5a30000}, {0xc5a32000}, {0xc5a34000}, {0xc5a36000},
+ {0xc5a38000}, {0xc5a3a000}, {0xc5a3c000}, {0xc5a3e000},
+ {0xc5a40000}, {0xc5a42000}, {0xc5a44000}, {0xc5a46000},
+ {0xc5a48000}, {0xc5a4a000}, {0xc5a4c000}, {0xc5a4e000},
+ {0xc5a50000}, {0xc5a52000}, {0xc5a54000}, {0xc5a56000},
+ {0xc5a58000}, {0xc5a5a000}, {0xc5a5c000}, {0xc5a5e000},
+ {0xc5a60000}, {0xc5a62000}, {0xc5a64000}, {0xc5a66000},
+ {0xc5a68000}, {0xc5a6a000}, {0xc5a6c000}, {0xc5a6e000},
+ {0xc5a70000}, {0xc5a72000}, {0xc5a74000}, {0xc5a76000},
+ {0xc5a78000}, {0xc5a7a000}, {0xc5a7c000}, {0xc5a7e000},
+ {0xc5a80000}, {0xc5a82000}, {0xc5a84000}, {0xc5a86000},
+ {0xc5a88000}, {0xc5a8a000}, {0xc5a8c000}, {0xc5a8e000},
+ {0xc5a90000}, {0xc5a92000}, {0xc5a94000}, {0xc5a96000},
+ {0xc5a98000}, {0xc5a9a000}, {0xc5a9c000}, {0xc5a9e000},
+ {0xc5aa0000}, {0xc5aa2000}, {0xc5aa4000}, {0xc5aa6000},
+ {0xc5aa8000}, {0xc5aaa000}, {0xc5aac000}, {0xc5aae000},
+ {0xc5ab0000}, {0xc5ab2000}, {0xc5ab4000}, {0xc5ab6000},
+ {0xc5ab8000}, {0xc5aba000}, {0xc5abc000}, {0xc5abe000},
+ {0xc5ac0000}, {0xc5ac2000}, {0xc5ac4000}, {0xc5ac6000},
+ {0xc5ac8000}, {0xc5aca000}, {0xc5acc000}, {0xc5ace000},
+ {0xc5ad0000}, {0xc5ad2000}, {0xc5ad4000}, {0xc5ad6000},
+ {0xc5ad8000}, {0xc5ada000}, {0xc5adc000}, {0xc5ade000},
+ {0xc5ae0000}, {0xc5ae2000}, {0xc5ae4000}, {0xc5ae6000},
+ {0xc5ae8000}, {0xc5aea000}, {0xc5aec000}, {0xc5aee000},
+ {0xc5af0000}, {0xc5af2000}, {0xc5af4000}, {0xc5af6000},
+ {0xc5af8000}, {0xc5afa000}, {0xc5afc000}, {0xc5afe000},
+ {0xc5b00000}, {0xc5b02000}, {0xc5b04000}, {0xc5b06000},
+ {0xc5b08000}, {0xc5b0a000}, {0xc5b0c000}, {0xc5b0e000},
+ {0xc5b10000}, {0xc5b12000}, {0xc5b14000}, {0xc5b16000},
+ {0xc5b18000}, {0xc5b1a000}, {0xc5b1c000}, {0xc5b1e000},
+ {0xc5b20000}, {0xc5b22000}, {0xc5b24000}, {0xc5b26000},
+ {0xc5b28000}, {0xc5b2a000}, {0xc5b2c000}, {0xc5b2e000},
+ {0xc5b30000}, {0xc5b32000}, {0xc5b34000}, {0xc5b36000},
+ {0xc5b38000}, {0xc5b3a000}, {0xc5b3c000}, {0xc5b3e000},
+ {0xc5b40000}, {0xc5b42000}, {0xc5b44000}, {0xc5b46000},
+ {0xc5b48000}, {0xc5b4a000}, {0xc5b4c000}, {0xc5b4e000},
+ {0xc5b50000}, {0xc5b52000}, {0xc5b54000}, {0xc5b56000},
+ {0xc5b58000}, {0xc5b5a000}, {0xc5b5c000}, {0xc5b5e000},
+ {0xc5b60000}, {0xc5b62000}, {0xc5b64000}, {0xc5b66000},
+ {0xc5b68000}, {0xc5b6a000}, {0xc5b6c000}, {0xc5b6e000},
+ {0xc5b70000}, {0xc5b72000}, {0xc5b74000}, {0xc5b76000},
+ {0xc5b78000}, {0xc5b7a000}, {0xc5b7c000}, {0xc5b7e000},
+ {0xc5b80000}, {0xc5b82000}, {0xc5b84000}, {0xc5b86000},
+ {0xc5b88000}, {0xc5b8a000}, {0xc5b8c000}, {0xc5b8e000},
+ {0xc5b90000}, {0xc5b92000}, {0xc5b94000}, {0xc5b96000},
+ {0xc5b98000}, {0xc5b9a000}, {0xc5b9c000}, {0xc5b9e000},
+ {0xc5ba0000}, {0xc5ba2000}, {0xc5ba4000}, {0xc5ba6000},
+ {0xc5ba8000}, {0xc5baa000}, {0xc5bac000}, {0xc5bae000},
+ {0xc5bb0000}, {0xc5bb2000}, {0xc5bb4000}, {0xc5bb6000},
+ {0xc5bb8000}, {0xc5bba000}, {0xc5bbc000}, {0xc5bbe000},
+ {0xc5bc0000}, {0xc5bc2000}, {0xc5bc4000}, {0xc5bc6000},
+ {0xc5bc8000}, {0xc5bca000}, {0xc5bcc000}, {0xc5bce000},
+ {0xc5bd0000}, {0xc5bd2000}, {0xc5bd4000}, {0xc5bd6000},
+ {0xc5bd8000}, {0xc5bda000}, {0xc5bdc000}, {0xc5bde000},
+ {0xc5be0000}, {0xc5be2000}, {0xc5be4000}, {0xc5be6000},
+ {0xc5be8000}, {0xc5bea000}, {0xc5bec000}, {0xc5bee000},
+ {0xc5bf0000}, {0xc5bf2000}, {0xc5bf4000}, {0xc5bf6000},
+ {0xc5bf8000}, {0xc5bfa000}, {0xc5bfc000}, {0xc5bfe000},
+ {0xc5c00000}, {0xc5c02000}, {0xc5c04000}, {0xc5c06000},
+ {0xc5c08000}, {0xc5c0a000}, {0xc5c0c000}, {0xc5c0e000},
+ {0xc5c10000}, {0xc5c12000}, {0xc5c14000}, {0xc5c16000},
+ {0xc5c18000}, {0xc5c1a000}, {0xc5c1c000}, {0xc5c1e000},
+ {0xc5c20000}, {0xc5c22000}, {0xc5c24000}, {0xc5c26000},
+ {0xc5c28000}, {0xc5c2a000}, {0xc5c2c000}, {0xc5c2e000},
+ {0xc5c30000}, {0xc5c32000}, {0xc5c34000}, {0xc5c36000},
+ {0xc5c38000}, {0xc5c3a000}, {0xc5c3c000}, {0xc5c3e000},
+ {0xc5c40000}, {0xc5c42000}, {0xc5c44000}, {0xc5c46000},
+ {0xc5c48000}, {0xc5c4a000}, {0xc5c4c000}, {0xc5c4e000},
+ {0xc5c50000}, {0xc5c52000}, {0xc5c54000}, {0xc5c56000},
+ {0xc5c58000}, {0xc5c5a000}, {0xc5c5c000}, {0xc5c5e000},
+ {0xc5c60000}, {0xc5c62000}, {0xc5c64000}, {0xc5c66000},
+ {0xc5c68000}, {0xc5c6a000}, {0xc5c6c000}, {0xc5c6e000},
+ {0xc5c70000}, {0xc5c72000}, {0xc5c74000}, {0xc5c76000},
+ {0xc5c78000}, {0xc5c7a000}, {0xc5c7c000}, {0xc5c7e000},
+ {0xc5c80000}, {0xc5c82000}, {0xc5c84000}, {0xc5c86000},
+ {0xc5c88000}, {0xc5c8a000}, {0xc5c8c000}, {0xc5c8e000},
+ {0xc5c90000}, {0xc5c92000}, {0xc5c94000}, {0xc5c96000},
+ {0xc5c98000}, {0xc5c9a000}, {0xc5c9c000}, {0xc5c9e000},
+ {0xc5ca0000}, {0xc5ca2000}, {0xc5ca4000}, {0xc5ca6000},
+ {0xc5ca8000}, {0xc5caa000}, {0xc5cac000}, {0xc5cae000},
+ {0xc5cb0000}, {0xc5cb2000}, {0xc5cb4000}, {0xc5cb6000},
+ {0xc5cb8000}, {0xc5cba000}, {0xc5cbc000}, {0xc5cbe000},
+ {0xc5cc0000}, {0xc5cc2000}, {0xc5cc4000}, {0xc5cc6000},
+ {0xc5cc8000}, {0xc5cca000}, {0xc5ccc000}, {0xc5cce000},
+ {0xc5cd0000}, {0xc5cd2000}, {0xc5cd4000}, {0xc5cd6000},
+ {0xc5cd8000}, {0xc5cda000}, {0xc5cdc000}, {0xc5cde000},
+ {0xc5ce0000}, {0xc5ce2000}, {0xc5ce4000}, {0xc5ce6000},
+ {0xc5ce8000}, {0xc5cea000}, {0xc5cec000}, {0xc5cee000},
+ {0xc5cf0000}, {0xc5cf2000}, {0xc5cf4000}, {0xc5cf6000},
+ {0xc5cf8000}, {0xc5cfa000}, {0xc5cfc000}, {0xc5cfe000},
+ {0xc5d00000}, {0xc5d02000}, {0xc5d04000}, {0xc5d06000},
+ {0xc5d08000}, {0xc5d0a000}, {0xc5d0c000}, {0xc5d0e000},
+ {0xc5d10000}, {0xc5d12000}, {0xc5d14000}, {0xc5d16000},
+ {0xc5d18000}, {0xc5d1a000}, {0xc5d1c000}, {0xc5d1e000},
+ {0xc5d20000}, {0xc5d22000}, {0xc5d24000}, {0xc5d26000},
+ {0xc5d28000}, {0xc5d2a000}, {0xc5d2c000}, {0xc5d2e000},
+ {0xc5d30000}, {0xc5d32000}, {0xc5d34000}, {0xc5d36000},
+ {0xc5d38000}, {0xc5d3a000}, {0xc5d3c000}, {0xc5d3e000},
+ {0xc5d40000}, {0xc5d42000}, {0xc5d44000}, {0xc5d46000},
+ {0xc5d48000}, {0xc5d4a000}, {0xc5d4c000}, {0xc5d4e000},
+ {0xc5d50000}, {0xc5d52000}, {0xc5d54000}, {0xc5d56000},
+ {0xc5d58000}, {0xc5d5a000}, {0xc5d5c000}, {0xc5d5e000},
+ {0xc5d60000}, {0xc5d62000}, {0xc5d64000}, {0xc5d66000},
+ {0xc5d68000}, {0xc5d6a000}, {0xc5d6c000}, {0xc5d6e000},
+ {0xc5d70000}, {0xc5d72000}, {0xc5d74000}, {0xc5d76000},
+ {0xc5d78000}, {0xc5d7a000}, {0xc5d7c000}, {0xc5d7e000},
+ {0xc5d80000}, {0xc5d82000}, {0xc5d84000}, {0xc5d86000},
+ {0xc5d88000}, {0xc5d8a000}, {0xc5d8c000}, {0xc5d8e000},
+ {0xc5d90000}, {0xc5d92000}, {0xc5d94000}, {0xc5d96000},
+ {0xc5d98000}, {0xc5d9a000}, {0xc5d9c000}, {0xc5d9e000},
+ {0xc5da0000}, {0xc5da2000}, {0xc5da4000}, {0xc5da6000},
+ {0xc5da8000}, {0xc5daa000}, {0xc5dac000}, {0xc5dae000},
+ {0xc5db0000}, {0xc5db2000}, {0xc5db4000}, {0xc5db6000},
+ {0xc5db8000}, {0xc5dba000}, {0xc5dbc000}, {0xc5dbe000},
+ {0xc5dc0000}, {0xc5dc2000}, {0xc5dc4000}, {0xc5dc6000},
+ {0xc5dc8000}, {0xc5dca000}, {0xc5dcc000}, {0xc5dce000},
+ {0xc5dd0000}, {0xc5dd2000}, {0xc5dd4000}, {0xc5dd6000},
+ {0xc5dd8000}, {0xc5dda000}, {0xc5ddc000}, {0xc5dde000},
+ {0xc5de0000}, {0xc5de2000}, {0xc5de4000}, {0xc5de6000},
+ {0xc5de8000}, {0xc5dea000}, {0xc5dec000}, {0xc5dee000},
+ {0xc5df0000}, {0xc5df2000}, {0xc5df4000}, {0xc5df6000},
+ {0xc5df8000}, {0xc5dfa000}, {0xc5dfc000}, {0xc5dfe000},
+ {0xc5e00000}, {0xc5e02000}, {0xc5e04000}, {0xc5e06000},
+ {0xc5e08000}, {0xc5e0a000}, {0xc5e0c000}, {0xc5e0e000},
+ {0xc5e10000}, {0xc5e12000}, {0xc5e14000}, {0xc5e16000},
+ {0xc5e18000}, {0xc5e1a000}, {0xc5e1c000}, {0xc5e1e000},
+ {0xc5e20000}, {0xc5e22000}, {0xc5e24000}, {0xc5e26000},
+ {0xc5e28000}, {0xc5e2a000}, {0xc5e2c000}, {0xc5e2e000},
+ {0xc5e30000}, {0xc5e32000}, {0xc5e34000}, {0xc5e36000},
+ {0xc5e38000}, {0xc5e3a000}, {0xc5e3c000}, {0xc5e3e000},
+ {0xc5e40000}, {0xc5e42000}, {0xc5e44000}, {0xc5e46000},
+ {0xc5e48000}, {0xc5e4a000}, {0xc5e4c000}, {0xc5e4e000},
+ {0xc5e50000}, {0xc5e52000}, {0xc5e54000}, {0xc5e56000},
+ {0xc5e58000}, {0xc5e5a000}, {0xc5e5c000}, {0xc5e5e000},
+ {0xc5e60000}, {0xc5e62000}, {0xc5e64000}, {0xc5e66000},
+ {0xc5e68000}, {0xc5e6a000}, {0xc5e6c000}, {0xc5e6e000},
+ {0xc5e70000}, {0xc5e72000}, {0xc5e74000}, {0xc5e76000},
+ {0xc5e78000}, {0xc5e7a000}, {0xc5e7c000}, {0xc5e7e000},
+ {0xc5e80000}, {0xc5e82000}, {0xc5e84000}, {0xc5e86000},
+ {0xc5e88000}, {0xc5e8a000}, {0xc5e8c000}, {0xc5e8e000},
+ {0xc5e90000}, {0xc5e92000}, {0xc5e94000}, {0xc5e96000},
+ {0xc5e98000}, {0xc5e9a000}, {0xc5e9c000}, {0xc5e9e000},
+ {0xc5ea0000}, {0xc5ea2000}, {0xc5ea4000}, {0xc5ea6000},
+ {0xc5ea8000}, {0xc5eaa000}, {0xc5eac000}, {0xc5eae000},
+ {0xc5eb0000}, {0xc5eb2000}, {0xc5eb4000}, {0xc5eb6000},
+ {0xc5eb8000}, {0xc5eba000}, {0xc5ebc000}, {0xc5ebe000},
+ {0xc5ec0000}, {0xc5ec2000}, {0xc5ec4000}, {0xc5ec6000},
+ {0xc5ec8000}, {0xc5eca000}, {0xc5ecc000}, {0xc5ece000},
+ {0xc5ed0000}, {0xc5ed2000}, {0xc5ed4000}, {0xc5ed6000},
+ {0xc5ed8000}, {0xc5eda000}, {0xc5edc000}, {0xc5ede000},
+ {0xc5ee0000}, {0xc5ee2000}, {0xc5ee4000}, {0xc5ee6000},
+ {0xc5ee8000}, {0xc5eea000}, {0xc5eec000}, {0xc5eee000},
+ {0xc5ef0000}, {0xc5ef2000}, {0xc5ef4000}, {0xc5ef6000},
+ {0xc5ef8000}, {0xc5efa000}, {0xc5efc000}, {0xc5efe000},
+ {0xc5f00000}, {0xc5f02000}, {0xc5f04000}, {0xc5f06000},
+ {0xc5f08000}, {0xc5f0a000}, {0xc5f0c000}, {0xc5f0e000},
+ {0xc5f10000}, {0xc5f12000}, {0xc5f14000}, {0xc5f16000},
+ {0xc5f18000}, {0xc5f1a000}, {0xc5f1c000}, {0xc5f1e000},
+ {0xc5f20000}, {0xc5f22000}, {0xc5f24000}, {0xc5f26000},
+ {0xc5f28000}, {0xc5f2a000}, {0xc5f2c000}, {0xc5f2e000},
+ {0xc5f30000}, {0xc5f32000}, {0xc5f34000}, {0xc5f36000},
+ {0xc5f38000}, {0xc5f3a000}, {0xc5f3c000}, {0xc5f3e000},
+ {0xc5f40000}, {0xc5f42000}, {0xc5f44000}, {0xc5f46000},
+ {0xc5f48000}, {0xc5f4a000}, {0xc5f4c000}, {0xc5f4e000},
+ {0xc5f50000}, {0xc5f52000}, {0xc5f54000}, {0xc5f56000},
+ {0xc5f58000}, {0xc5f5a000}, {0xc5f5c000}, {0xc5f5e000},
+ {0xc5f60000}, {0xc5f62000}, {0xc5f64000}, {0xc5f66000},
+ {0xc5f68000}, {0xc5f6a000}, {0xc5f6c000}, {0xc5f6e000},
+ {0xc5f70000}, {0xc5f72000}, {0xc5f74000}, {0xc5f76000},
+ {0xc5f78000}, {0xc5f7a000}, {0xc5f7c000}, {0xc5f7e000},
+ {0xc5f80000}, {0xc5f82000}, {0xc5f84000}, {0xc5f86000},
+ {0xc5f88000}, {0xc5f8a000}, {0xc5f8c000}, {0xc5f8e000},
+ {0xc5f90000}, {0xc5f92000}, {0xc5f94000}, {0xc5f96000},
+ {0xc5f98000}, {0xc5f9a000}, {0xc5f9c000}, {0xc5f9e000},
+ {0xc5fa0000}, {0xc5fa2000}, {0xc5fa4000}, {0xc5fa6000},
+ {0xc5fa8000}, {0xc5faa000}, {0xc5fac000}, {0xc5fae000},
+ {0xc5fb0000}, {0xc5fb2000}, {0xc5fb4000}, {0xc5fb6000},
+ {0xc5fb8000}, {0xc5fba000}, {0xc5fbc000}, {0xc5fbe000},
+ {0xc5fc0000}, {0xc5fc2000}, {0xc5fc4000}, {0xc5fc6000},
+ {0xc5fc8000}, {0xc5fca000}, {0xc5fcc000}, {0xc5fce000},
+ {0xc5fd0000}, {0xc5fd2000}, {0xc5fd4000}, {0xc5fd6000},
+ {0xc5fd8000}, {0xc5fda000}, {0xc5fdc000}, {0xc5fde000},
+ {0xc5fe0000}, {0xc5fe2000}, {0xc5fe4000}, {0xc5fe6000},
+ {0xc5fe8000}, {0xc5fea000}, {0xc5fec000}, {0xc5fee000},
+ {0xc5ff0000}, {0xc5ff2000}, {0xc5ff4000}, {0xc5ff6000},
+ {0xc5ff8000}, {0xc5ffa000}, {0xc5ffc000}, {0xc5ffe000},
+ {0xc6000000}, {0xc6002000}, {0xc6004000}, {0xc6006000},
+ {0xc6008000}, {0xc600a000}, {0xc600c000}, {0xc600e000},
+ {0xc6010000}, {0xc6012000}, {0xc6014000}, {0xc6016000},
+ {0xc6018000}, {0xc601a000}, {0xc601c000}, {0xc601e000},
+ {0xc6020000}, {0xc6022000}, {0xc6024000}, {0xc6026000},
+ {0xc6028000}, {0xc602a000}, {0xc602c000}, {0xc602e000},
+ {0xc6030000}, {0xc6032000}, {0xc6034000}, {0xc6036000},
+ {0xc6038000}, {0xc603a000}, {0xc603c000}, {0xc603e000},
+ {0xc6040000}, {0xc6042000}, {0xc6044000}, {0xc6046000},
+ {0xc6048000}, {0xc604a000}, {0xc604c000}, {0xc604e000},
+ {0xc6050000}, {0xc6052000}, {0xc6054000}, {0xc6056000},
+ {0xc6058000}, {0xc605a000}, {0xc605c000}, {0xc605e000},
+ {0xc6060000}, {0xc6062000}, {0xc6064000}, {0xc6066000},
+ {0xc6068000}, {0xc606a000}, {0xc606c000}, {0xc606e000},
+ {0xc6070000}, {0xc6072000}, {0xc6074000}, {0xc6076000},
+ {0xc6078000}, {0xc607a000}, {0xc607c000}, {0xc607e000},
+ {0xc6080000}, {0xc6082000}, {0xc6084000}, {0xc6086000},
+ {0xc6088000}, {0xc608a000}, {0xc608c000}, {0xc608e000},
+ {0xc6090000}, {0xc6092000}, {0xc6094000}, {0xc6096000},
+ {0xc6098000}, {0xc609a000}, {0xc609c000}, {0xc609e000},
+ {0xc60a0000}, {0xc60a2000}, {0xc60a4000}, {0xc60a6000},
+ {0xc60a8000}, {0xc60aa000}, {0xc60ac000}, {0xc60ae000},
+ {0xc60b0000}, {0xc60b2000}, {0xc60b4000}, {0xc60b6000},
+ {0xc60b8000}, {0xc60ba000}, {0xc60bc000}, {0xc60be000},
+ {0xc60c0000}, {0xc60c2000}, {0xc60c4000}, {0xc60c6000},
+ {0xc60c8000}, {0xc60ca000}, {0xc60cc000}, {0xc60ce000},
+ {0xc60d0000}, {0xc60d2000}, {0xc60d4000}, {0xc60d6000},
+ {0xc60d8000}, {0xc60da000}, {0xc60dc000}, {0xc60de000},
+ {0xc60e0000}, {0xc60e2000}, {0xc60e4000}, {0xc60e6000},
+ {0xc60e8000}, {0xc60ea000}, {0xc60ec000}, {0xc60ee000},
+ {0xc60f0000}, {0xc60f2000}, {0xc60f4000}, {0xc60f6000},
+ {0xc60f8000}, {0xc60fa000}, {0xc60fc000}, {0xc60fe000},
+ {0xc6100000}, {0xc6102000}, {0xc6104000}, {0xc6106000},
+ {0xc6108000}, {0xc610a000}, {0xc610c000}, {0xc610e000},
+ {0xc6110000}, {0xc6112000}, {0xc6114000}, {0xc6116000},
+ {0xc6118000}, {0xc611a000}, {0xc611c000}, {0xc611e000},
+ {0xc6120000}, {0xc6122000}, {0xc6124000}, {0xc6126000},
+ {0xc6128000}, {0xc612a000}, {0xc612c000}, {0xc612e000},
+ {0xc6130000}, {0xc6132000}, {0xc6134000}, {0xc6136000},
+ {0xc6138000}, {0xc613a000}, {0xc613c000}, {0xc613e000},
+ {0xc6140000}, {0xc6142000}, {0xc6144000}, {0xc6146000},
+ {0xc6148000}, {0xc614a000}, {0xc614c000}, {0xc614e000},
+ {0xc6150000}, {0xc6152000}, {0xc6154000}, {0xc6156000},
+ {0xc6158000}, {0xc615a000}, {0xc615c000}, {0xc615e000},
+ {0xc6160000}, {0xc6162000}, {0xc6164000}, {0xc6166000},
+ {0xc6168000}, {0xc616a000}, {0xc616c000}, {0xc616e000},
+ {0xc6170000}, {0xc6172000}, {0xc6174000}, {0xc6176000},
+ {0xc6178000}, {0xc617a000}, {0xc617c000}, {0xc617e000},
+ {0xc6180000}, {0xc6182000}, {0xc6184000}, {0xc6186000},
+ {0xc6188000}, {0xc618a000}, {0xc618c000}, {0xc618e000},
+ {0xc6190000}, {0xc6192000}, {0xc6194000}, {0xc6196000},
+ {0xc6198000}, {0xc619a000}, {0xc619c000}, {0xc619e000},
+ {0xc61a0000}, {0xc61a2000}, {0xc61a4000}, {0xc61a6000},
+ {0xc61a8000}, {0xc61aa000}, {0xc61ac000}, {0xc61ae000},
+ {0xc61b0000}, {0xc61b2000}, {0xc61b4000}, {0xc61b6000},
+ {0xc61b8000}, {0xc61ba000}, {0xc61bc000}, {0xc61be000},
+ {0xc61c0000}, {0xc61c2000}, {0xc61c4000}, {0xc61c6000},
+ {0xc61c8000}, {0xc61ca000}, {0xc61cc000}, {0xc61ce000},
+ {0xc61d0000}, {0xc61d2000}, {0xc61d4000}, {0xc61d6000},
+ {0xc61d8000}, {0xc61da000}, {0xc61dc000}, {0xc61de000},
+ {0xc61e0000}, {0xc61e2000}, {0xc61e4000}, {0xc61e6000},
+ {0xc61e8000}, {0xc61ea000}, {0xc61ec000}, {0xc61ee000},
+ {0xc61f0000}, {0xc61f2000}, {0xc61f4000}, {0xc61f6000},
+ {0xc61f8000}, {0xc61fa000}, {0xc61fc000}, {0xc61fe000},
+ {0xc6200000}, {0xc6202000}, {0xc6204000}, {0xc6206000},
+ {0xc6208000}, {0xc620a000}, {0xc620c000}, {0xc620e000},
+ {0xc6210000}, {0xc6212000}, {0xc6214000}, {0xc6216000},
+ {0xc6218000}, {0xc621a000}, {0xc621c000}, {0xc621e000},
+ {0xc6220000}, {0xc6222000}, {0xc6224000}, {0xc6226000},
+ {0xc6228000}, {0xc622a000}, {0xc622c000}, {0xc622e000},
+ {0xc6230000}, {0xc6232000}, {0xc6234000}, {0xc6236000},
+ {0xc6238000}, {0xc623a000}, {0xc623c000}, {0xc623e000},
+ {0xc6240000}, {0xc6242000}, {0xc6244000}, {0xc6246000},
+ {0xc6248000}, {0xc624a000}, {0xc624c000}, {0xc624e000},
+ {0xc6250000}, {0xc6252000}, {0xc6254000}, {0xc6256000},
+ {0xc6258000}, {0xc625a000}, {0xc625c000}, {0xc625e000},
+ {0xc6260000}, {0xc6262000}, {0xc6264000}, {0xc6266000},
+ {0xc6268000}, {0xc626a000}, {0xc626c000}, {0xc626e000},
+ {0xc6270000}, {0xc6272000}, {0xc6274000}, {0xc6276000},
+ {0xc6278000}, {0xc627a000}, {0xc627c000}, {0xc627e000},
+ {0xc6280000}, {0xc6282000}, {0xc6284000}, {0xc6286000},
+ {0xc6288000}, {0xc628a000}, {0xc628c000}, {0xc628e000},
+ {0xc6290000}, {0xc6292000}, {0xc6294000}, {0xc6296000},
+ {0xc6298000}, {0xc629a000}, {0xc629c000}, {0xc629e000},
+ {0xc62a0000}, {0xc62a2000}, {0xc62a4000}, {0xc62a6000},
+ {0xc62a8000}, {0xc62aa000}, {0xc62ac000}, {0xc62ae000},
+ {0xc62b0000}, {0xc62b2000}, {0xc62b4000}, {0xc62b6000},
+ {0xc62b8000}, {0xc62ba000}, {0xc62bc000}, {0xc62be000},
+ {0xc62c0000}, {0xc62c2000}, {0xc62c4000}, {0xc62c6000},
+ {0xc62c8000}, {0xc62ca000}, {0xc62cc000}, {0xc62ce000},
+ {0xc62d0000}, {0xc62d2000}, {0xc62d4000}, {0xc62d6000},
+ {0xc62d8000}, {0xc62da000}, {0xc62dc000}, {0xc62de000},
+ {0xc62e0000}, {0xc62e2000}, {0xc62e4000}, {0xc62e6000},
+ {0xc62e8000}, {0xc62ea000}, {0xc62ec000}, {0xc62ee000},
+ {0xc62f0000}, {0xc62f2000}, {0xc62f4000}, {0xc62f6000},
+ {0xc62f8000}, {0xc62fa000}, {0xc62fc000}, {0xc62fe000},
+ {0xc6300000}, {0xc6302000}, {0xc6304000}, {0xc6306000},
+ {0xc6308000}, {0xc630a000}, {0xc630c000}, {0xc630e000},
+ {0xc6310000}, {0xc6312000}, {0xc6314000}, {0xc6316000},
+ {0xc6318000}, {0xc631a000}, {0xc631c000}, {0xc631e000},
+ {0xc6320000}, {0xc6322000}, {0xc6324000}, {0xc6326000},
+ {0xc6328000}, {0xc632a000}, {0xc632c000}, {0xc632e000},
+ {0xc6330000}, {0xc6332000}, {0xc6334000}, {0xc6336000},
+ {0xc6338000}, {0xc633a000}, {0xc633c000}, {0xc633e000},
+ {0xc6340000}, {0xc6342000}, {0xc6344000}, {0xc6346000},
+ {0xc6348000}, {0xc634a000}, {0xc634c000}, {0xc634e000},
+ {0xc6350000}, {0xc6352000}, {0xc6354000}, {0xc6356000},
+ {0xc6358000}, {0xc635a000}, {0xc635c000}, {0xc635e000},
+ {0xc6360000}, {0xc6362000}, {0xc6364000}, {0xc6366000},
+ {0xc6368000}, {0xc636a000}, {0xc636c000}, {0xc636e000},
+ {0xc6370000}, {0xc6372000}, {0xc6374000}, {0xc6376000},
+ {0xc6378000}, {0xc637a000}, {0xc637c000}, {0xc637e000},
+ {0xc6380000}, {0xc6382000}, {0xc6384000}, {0xc6386000},
+ {0xc6388000}, {0xc638a000}, {0xc638c000}, {0xc638e000},
+ {0xc6390000}, {0xc6392000}, {0xc6394000}, {0xc6396000},
+ {0xc6398000}, {0xc639a000}, {0xc639c000}, {0xc639e000},
+ {0xc63a0000}, {0xc63a2000}, {0xc63a4000}, {0xc63a6000},
+ {0xc63a8000}, {0xc63aa000}, {0xc63ac000}, {0xc63ae000},
+ {0xc63b0000}, {0xc63b2000}, {0xc63b4000}, {0xc63b6000},
+ {0xc63b8000}, {0xc63ba000}, {0xc63bc000}, {0xc63be000},
+ {0xc63c0000}, {0xc63c2000}, {0xc63c4000}, {0xc63c6000},
+ {0xc63c8000}, {0xc63ca000}, {0xc63cc000}, {0xc63ce000},
+ {0xc63d0000}, {0xc63d2000}, {0xc63d4000}, {0xc63d6000},
+ {0xc63d8000}, {0xc63da000}, {0xc63dc000}, {0xc63de000},
+ {0xc63e0000}, {0xc63e2000}, {0xc63e4000}, {0xc63e6000},
+ {0xc63e8000}, {0xc63ea000}, {0xc63ec000}, {0xc63ee000},
+ {0xc63f0000}, {0xc63f2000}, {0xc63f4000}, {0xc63f6000},
+ {0xc63f8000}, {0xc63fa000}, {0xc63fc000}, {0xc63fe000},
+ {0xc6400000}, {0xc6402000}, {0xc6404000}, {0xc6406000},
+ {0xc6408000}, {0xc640a000}, {0xc640c000}, {0xc640e000},
+ {0xc6410000}, {0xc6412000}, {0xc6414000}, {0xc6416000},
+ {0xc6418000}, {0xc641a000}, {0xc641c000}, {0xc641e000},
+ {0xc6420000}, {0xc6422000}, {0xc6424000}, {0xc6426000},
+ {0xc6428000}, {0xc642a000}, {0xc642c000}, {0xc642e000},
+ {0xc6430000}, {0xc6432000}, {0xc6434000}, {0xc6436000},
+ {0xc6438000}, {0xc643a000}, {0xc643c000}, {0xc643e000},
+ {0xc6440000}, {0xc6442000}, {0xc6444000}, {0xc6446000},
+ {0xc6448000}, {0xc644a000}, {0xc644c000}, {0xc644e000},
+ {0xc6450000}, {0xc6452000}, {0xc6454000}, {0xc6456000},
+ {0xc6458000}, {0xc645a000}, {0xc645c000}, {0xc645e000},
+ {0xc6460000}, {0xc6462000}, {0xc6464000}, {0xc6466000},
+ {0xc6468000}, {0xc646a000}, {0xc646c000}, {0xc646e000},
+ {0xc6470000}, {0xc6472000}, {0xc6474000}, {0xc6476000},
+ {0xc6478000}, {0xc647a000}, {0xc647c000}, {0xc647e000},
+ {0xc6480000}, {0xc6482000}, {0xc6484000}, {0xc6486000},
+ {0xc6488000}, {0xc648a000}, {0xc648c000}, {0xc648e000},
+ {0xc6490000}, {0xc6492000}, {0xc6494000}, {0xc6496000},
+ {0xc6498000}, {0xc649a000}, {0xc649c000}, {0xc649e000},
+ {0xc64a0000}, {0xc64a2000}, {0xc64a4000}, {0xc64a6000},
+ {0xc64a8000}, {0xc64aa000}, {0xc64ac000}, {0xc64ae000},
+ {0xc64b0000}, {0xc64b2000}, {0xc64b4000}, {0xc64b6000},
+ {0xc64b8000}, {0xc64ba000}, {0xc64bc000}, {0xc64be000},
+ {0xc64c0000}, {0xc64c2000}, {0xc64c4000}, {0xc64c6000},
+ {0xc64c8000}, {0xc64ca000}, {0xc64cc000}, {0xc64ce000},
+ {0xc64d0000}, {0xc64d2000}, {0xc64d4000}, {0xc64d6000},
+ {0xc64d8000}, {0xc64da000}, {0xc64dc000}, {0xc64de000},
+ {0xc64e0000}, {0xc64e2000}, {0xc64e4000}, {0xc64e6000},
+ {0xc64e8000}, {0xc64ea000}, {0xc64ec000}, {0xc64ee000},
+ {0xc64f0000}, {0xc64f2000}, {0xc64f4000}, {0xc64f6000},
+ {0xc64f8000}, {0xc64fa000}, {0xc64fc000}, {0xc64fe000},
+ {0xc6500000}, {0xc6502000}, {0xc6504000}, {0xc6506000},
+ {0xc6508000}, {0xc650a000}, {0xc650c000}, {0xc650e000},
+ {0xc6510000}, {0xc6512000}, {0xc6514000}, {0xc6516000},
+ {0xc6518000}, {0xc651a000}, {0xc651c000}, {0xc651e000},
+ {0xc6520000}, {0xc6522000}, {0xc6524000}, {0xc6526000},
+ {0xc6528000}, {0xc652a000}, {0xc652c000}, {0xc652e000},
+ {0xc6530000}, {0xc6532000}, {0xc6534000}, {0xc6536000},
+ {0xc6538000}, {0xc653a000}, {0xc653c000}, {0xc653e000},
+ {0xc6540000}, {0xc6542000}, {0xc6544000}, {0xc6546000},
+ {0xc6548000}, {0xc654a000}, {0xc654c000}, {0xc654e000},
+ {0xc6550000}, {0xc6552000}, {0xc6554000}, {0xc6556000},
+ {0xc6558000}, {0xc655a000}, {0xc655c000}, {0xc655e000},
+ {0xc6560000}, {0xc6562000}, {0xc6564000}, {0xc6566000},
+ {0xc6568000}, {0xc656a000}, {0xc656c000}, {0xc656e000},
+ {0xc6570000}, {0xc6572000}, {0xc6574000}, {0xc6576000},
+ {0xc6578000}, {0xc657a000}, {0xc657c000}, {0xc657e000},
+ {0xc6580000}, {0xc6582000}, {0xc6584000}, {0xc6586000},
+ {0xc6588000}, {0xc658a000}, {0xc658c000}, {0xc658e000},
+ {0xc6590000}, {0xc6592000}, {0xc6594000}, {0xc6596000},
+ {0xc6598000}, {0xc659a000}, {0xc659c000}, {0xc659e000},
+ {0xc65a0000}, {0xc65a2000}, {0xc65a4000}, {0xc65a6000},
+ {0xc65a8000}, {0xc65aa000}, {0xc65ac000}, {0xc65ae000},
+ {0xc65b0000}, {0xc65b2000}, {0xc65b4000}, {0xc65b6000},
+ {0xc65b8000}, {0xc65ba000}, {0xc65bc000}, {0xc65be000},
+ {0xc65c0000}, {0xc65c2000}, {0xc65c4000}, {0xc65c6000},
+ {0xc65c8000}, {0xc65ca000}, {0xc65cc000}, {0xc65ce000},
+ {0xc65d0000}, {0xc65d2000}, {0xc65d4000}, {0xc65d6000},
+ {0xc65d8000}, {0xc65da000}, {0xc65dc000}, {0xc65de000},
+ {0xc65e0000}, {0xc65e2000}, {0xc65e4000}, {0xc65e6000},
+ {0xc65e8000}, {0xc65ea000}, {0xc65ec000}, {0xc65ee000},
+ {0xc65f0000}, {0xc65f2000}, {0xc65f4000}, {0xc65f6000},
+ {0xc65f8000}, {0xc65fa000}, {0xc65fc000}, {0xc65fe000},
+ {0xc6600000}, {0xc6602000}, {0xc6604000}, {0xc6606000},
+ {0xc6608000}, {0xc660a000}, {0xc660c000}, {0xc660e000},
+ {0xc6610000}, {0xc6612000}, {0xc6614000}, {0xc6616000},
+ {0xc6618000}, {0xc661a000}, {0xc661c000}, {0xc661e000},
+ {0xc6620000}, {0xc6622000}, {0xc6624000}, {0xc6626000},
+ {0xc6628000}, {0xc662a000}, {0xc662c000}, {0xc662e000},
+ {0xc6630000}, {0xc6632000}, {0xc6634000}, {0xc6636000},
+ {0xc6638000}, {0xc663a000}, {0xc663c000}, {0xc663e000},
+ {0xc6640000}, {0xc6642000}, {0xc6644000}, {0xc6646000},
+ {0xc6648000}, {0xc664a000}, {0xc664c000}, {0xc664e000},
+ {0xc6650000}, {0xc6652000}, {0xc6654000}, {0xc6656000},
+ {0xc6658000}, {0xc665a000}, {0xc665c000}, {0xc665e000},
+ {0xc6660000}, {0xc6662000}, {0xc6664000}, {0xc6666000},
+ {0xc6668000}, {0xc666a000}, {0xc666c000}, {0xc666e000},
+ {0xc6670000}, {0xc6672000}, {0xc6674000}, {0xc6676000},
+ {0xc6678000}, {0xc667a000}, {0xc667c000}, {0xc667e000},
+ {0xc6680000}, {0xc6682000}, {0xc6684000}, {0xc6686000},
+ {0xc6688000}, {0xc668a000}, {0xc668c000}, {0xc668e000},
+ {0xc6690000}, {0xc6692000}, {0xc6694000}, {0xc6696000},
+ {0xc6698000}, {0xc669a000}, {0xc669c000}, {0xc669e000},
+ {0xc66a0000}, {0xc66a2000}, {0xc66a4000}, {0xc66a6000},
+ {0xc66a8000}, {0xc66aa000}, {0xc66ac000}, {0xc66ae000},
+ {0xc66b0000}, {0xc66b2000}, {0xc66b4000}, {0xc66b6000},
+ {0xc66b8000}, {0xc66ba000}, {0xc66bc000}, {0xc66be000},
+ {0xc66c0000}, {0xc66c2000}, {0xc66c4000}, {0xc66c6000},
+ {0xc66c8000}, {0xc66ca000}, {0xc66cc000}, {0xc66ce000},
+ {0xc66d0000}, {0xc66d2000}, {0xc66d4000}, {0xc66d6000},
+ {0xc66d8000}, {0xc66da000}, {0xc66dc000}, {0xc66de000},
+ {0xc66e0000}, {0xc66e2000}, {0xc66e4000}, {0xc66e6000},
+ {0xc66e8000}, {0xc66ea000}, {0xc66ec000}, {0xc66ee000},
+ {0xc66f0000}, {0xc66f2000}, {0xc66f4000}, {0xc66f6000},
+ {0xc66f8000}, {0xc66fa000}, {0xc66fc000}, {0xc66fe000},
+ {0xc6700000}, {0xc6702000}, {0xc6704000}, {0xc6706000},
+ {0xc6708000}, {0xc670a000}, {0xc670c000}, {0xc670e000},
+ {0xc6710000}, {0xc6712000}, {0xc6714000}, {0xc6716000},
+ {0xc6718000}, {0xc671a000}, {0xc671c000}, {0xc671e000},
+ {0xc6720000}, {0xc6722000}, {0xc6724000}, {0xc6726000},
+ {0xc6728000}, {0xc672a000}, {0xc672c000}, {0xc672e000},
+ {0xc6730000}, {0xc6732000}, {0xc6734000}, {0xc6736000},
+ {0xc6738000}, {0xc673a000}, {0xc673c000}, {0xc673e000},
+ {0xc6740000}, {0xc6742000}, {0xc6744000}, {0xc6746000},
+ {0xc6748000}, {0xc674a000}, {0xc674c000}, {0xc674e000},
+ {0xc6750000}, {0xc6752000}, {0xc6754000}, {0xc6756000},
+ {0xc6758000}, {0xc675a000}, {0xc675c000}, {0xc675e000},
+ {0xc6760000}, {0xc6762000}, {0xc6764000}, {0xc6766000},
+ {0xc6768000}, {0xc676a000}, {0xc676c000}, {0xc676e000},
+ {0xc6770000}, {0xc6772000}, {0xc6774000}, {0xc6776000},
+ {0xc6778000}, {0xc677a000}, {0xc677c000}, {0xc677e000},
+ {0xc6780000}, {0xc6782000}, {0xc6784000}, {0xc6786000},
+ {0xc6788000}, {0xc678a000}, {0xc678c000}, {0xc678e000},
+ {0xc6790000}, {0xc6792000}, {0xc6794000}, {0xc6796000},
+ {0xc6798000}, {0xc679a000}, {0xc679c000}, {0xc679e000},
+ {0xc67a0000}, {0xc67a2000}, {0xc67a4000}, {0xc67a6000},
+ {0xc67a8000}, {0xc67aa000}, {0xc67ac000}, {0xc67ae000},
+ {0xc67b0000}, {0xc67b2000}, {0xc67b4000}, {0xc67b6000},
+ {0xc67b8000}, {0xc67ba000}, {0xc67bc000}, {0xc67be000},
+ {0xc67c0000}, {0xc67c2000}, {0xc67c4000}, {0xc67c6000},
+ {0xc67c8000}, {0xc67ca000}, {0xc67cc000}, {0xc67ce000},
+ {0xc67d0000}, {0xc67d2000}, {0xc67d4000}, {0xc67d6000},
+ {0xc67d8000}, {0xc67da000}, {0xc67dc000}, {0xc67de000},
+ {0xc67e0000}, {0xc67e2000}, {0xc67e4000}, {0xc67e6000},
+ {0xc67e8000}, {0xc67ea000}, {0xc67ec000}, {0xc67ee000},
+ {0xc67f0000}, {0xc67f2000}, {0xc67f4000}, {0xc67f6000},
+ {0xc67f8000}, {0xc67fa000}, {0xc67fc000}, {0xc67fe000},
+ {0xc6800000}, {0xc6802000}, {0xc6804000}, {0xc6806000},
+ {0xc6808000}, {0xc680a000}, {0xc680c000}, {0xc680e000},
+ {0xc6810000}, {0xc6812000}, {0xc6814000}, {0xc6816000},
+ {0xc6818000}, {0xc681a000}, {0xc681c000}, {0xc681e000},
+ {0xc6820000}, {0xc6822000}, {0xc6824000}, {0xc6826000},
+ {0xc6828000}, {0xc682a000}, {0xc682c000}, {0xc682e000},
+ {0xc6830000}, {0xc6832000}, {0xc6834000}, {0xc6836000},
+ {0xc6838000}, {0xc683a000}, {0xc683c000}, {0xc683e000},
+ {0xc6840000}, {0xc6842000}, {0xc6844000}, {0xc6846000},
+ {0xc6848000}, {0xc684a000}, {0xc684c000}, {0xc684e000},
+ {0xc6850000}, {0xc6852000}, {0xc6854000}, {0xc6856000},
+ {0xc6858000}, {0xc685a000}, {0xc685c000}, {0xc685e000},
+ {0xc6860000}, {0xc6862000}, {0xc6864000}, {0xc6866000},
+ {0xc6868000}, {0xc686a000}, {0xc686c000}, {0xc686e000},
+ {0xc6870000}, {0xc6872000}, {0xc6874000}, {0xc6876000},
+ {0xc6878000}, {0xc687a000}, {0xc687c000}, {0xc687e000},
+ {0xc6880000}, {0xc6882000}, {0xc6884000}, {0xc6886000},
+ {0xc6888000}, {0xc688a000}, {0xc688c000}, {0xc688e000},
+ {0xc6890000}, {0xc6892000}, {0xc6894000}, {0xc6896000},
+ {0xc6898000}, {0xc689a000}, {0xc689c000}, {0xc689e000},
+ {0xc68a0000}, {0xc68a2000}, {0xc68a4000}, {0xc68a6000},
+ {0xc68a8000}, {0xc68aa000}, {0xc68ac000}, {0xc68ae000},
+ {0xc68b0000}, {0xc68b2000}, {0xc68b4000}, {0xc68b6000},
+ {0xc68b8000}, {0xc68ba000}, {0xc68bc000}, {0xc68be000},
+ {0xc68c0000}, {0xc68c2000}, {0xc68c4000}, {0xc68c6000},
+ {0xc68c8000}, {0xc68ca000}, {0xc68cc000}, {0xc68ce000},
+ {0xc68d0000}, {0xc68d2000}, {0xc68d4000}, {0xc68d6000},
+ {0xc68d8000}, {0xc68da000}, {0xc68dc000}, {0xc68de000},
+ {0xc68e0000}, {0xc68e2000}, {0xc68e4000}, {0xc68e6000},
+ {0xc68e8000}, {0xc68ea000}, {0xc68ec000}, {0xc68ee000},
+ {0xc68f0000}, {0xc68f2000}, {0xc68f4000}, {0xc68f6000},
+ {0xc68f8000}, {0xc68fa000}, {0xc68fc000}, {0xc68fe000},
+ {0xc6900000}, {0xc6902000}, {0xc6904000}, {0xc6906000},
+ {0xc6908000}, {0xc690a000}, {0xc690c000}, {0xc690e000},
+ {0xc6910000}, {0xc6912000}, {0xc6914000}, {0xc6916000},
+ {0xc6918000}, {0xc691a000}, {0xc691c000}, {0xc691e000},
+ {0xc6920000}, {0xc6922000}, {0xc6924000}, {0xc6926000},
+ {0xc6928000}, {0xc692a000}, {0xc692c000}, {0xc692e000},
+ {0xc6930000}, {0xc6932000}, {0xc6934000}, {0xc6936000},
+ {0xc6938000}, {0xc693a000}, {0xc693c000}, {0xc693e000},
+ {0xc6940000}, {0xc6942000}, {0xc6944000}, {0xc6946000},
+ {0xc6948000}, {0xc694a000}, {0xc694c000}, {0xc694e000},
+ {0xc6950000}, {0xc6952000}, {0xc6954000}, {0xc6956000},
+ {0xc6958000}, {0xc695a000}, {0xc695c000}, {0xc695e000},
+ {0xc6960000}, {0xc6962000}, {0xc6964000}, {0xc6966000},
+ {0xc6968000}, {0xc696a000}, {0xc696c000}, {0xc696e000},
+ {0xc6970000}, {0xc6972000}, {0xc6974000}, {0xc6976000},
+ {0xc6978000}, {0xc697a000}, {0xc697c000}, {0xc697e000},
+ {0xc6980000}, {0xc6982000}, {0xc6984000}, {0xc6986000},
+ {0xc6988000}, {0xc698a000}, {0xc698c000}, {0xc698e000},
+ {0xc6990000}, {0xc6992000}, {0xc6994000}, {0xc6996000},
+ {0xc6998000}, {0xc699a000}, {0xc699c000}, {0xc699e000},
+ {0xc69a0000}, {0xc69a2000}, {0xc69a4000}, {0xc69a6000},
+ {0xc69a8000}, {0xc69aa000}, {0xc69ac000}, {0xc69ae000},
+ {0xc69b0000}, {0xc69b2000}, {0xc69b4000}, {0xc69b6000},
+ {0xc69b8000}, {0xc69ba000}, {0xc69bc000}, {0xc69be000},
+ {0xc69c0000}, {0xc69c2000}, {0xc69c4000}, {0xc69c6000},
+ {0xc69c8000}, {0xc69ca000}, {0xc69cc000}, {0xc69ce000},
+ {0xc69d0000}, {0xc69d2000}, {0xc69d4000}, {0xc69d6000},
+ {0xc69d8000}, {0xc69da000}, {0xc69dc000}, {0xc69de000},
+ {0xc69e0000}, {0xc69e2000}, {0xc69e4000}, {0xc69e6000},
+ {0xc69e8000}, {0xc69ea000}, {0xc69ec000}, {0xc69ee000},
+ {0xc69f0000}, {0xc69f2000}, {0xc69f4000}, {0xc69f6000},
+ {0xc69f8000}, {0xc69fa000}, {0xc69fc000}, {0xc69fe000},
+ {0xc6a00000}, {0xc6a02000}, {0xc6a04000}, {0xc6a06000},
+ {0xc6a08000}, {0xc6a0a000}, {0xc6a0c000}, {0xc6a0e000},
+ {0xc6a10000}, {0xc6a12000}, {0xc6a14000}, {0xc6a16000},
+ {0xc6a18000}, {0xc6a1a000}, {0xc6a1c000}, {0xc6a1e000},
+ {0xc6a20000}, {0xc6a22000}, {0xc6a24000}, {0xc6a26000},
+ {0xc6a28000}, {0xc6a2a000}, {0xc6a2c000}, {0xc6a2e000},
+ {0xc6a30000}, {0xc6a32000}, {0xc6a34000}, {0xc6a36000},
+ {0xc6a38000}, {0xc6a3a000}, {0xc6a3c000}, {0xc6a3e000},
+ {0xc6a40000}, {0xc6a42000}, {0xc6a44000}, {0xc6a46000},
+ {0xc6a48000}, {0xc6a4a000}, {0xc6a4c000}, {0xc6a4e000},
+ {0xc6a50000}, {0xc6a52000}, {0xc6a54000}, {0xc6a56000},
+ {0xc6a58000}, {0xc6a5a000}, {0xc6a5c000}, {0xc6a5e000},
+ {0xc6a60000}, {0xc6a62000}, {0xc6a64000}, {0xc6a66000},
+ {0xc6a68000}, {0xc6a6a000}, {0xc6a6c000}, {0xc6a6e000},
+ {0xc6a70000}, {0xc6a72000}, {0xc6a74000}, {0xc6a76000},
+ {0xc6a78000}, {0xc6a7a000}, {0xc6a7c000}, {0xc6a7e000},
+ {0xc6a80000}, {0xc6a82000}, {0xc6a84000}, {0xc6a86000},
+ {0xc6a88000}, {0xc6a8a000}, {0xc6a8c000}, {0xc6a8e000},
+ {0xc6a90000}, {0xc6a92000}, {0xc6a94000}, {0xc6a96000},
+ {0xc6a98000}, {0xc6a9a000}, {0xc6a9c000}, {0xc6a9e000},
+ {0xc6aa0000}, {0xc6aa2000}, {0xc6aa4000}, {0xc6aa6000},
+ {0xc6aa8000}, {0xc6aaa000}, {0xc6aac000}, {0xc6aae000},
+ {0xc6ab0000}, {0xc6ab2000}, {0xc6ab4000}, {0xc6ab6000},
+ {0xc6ab8000}, {0xc6aba000}, {0xc6abc000}, {0xc6abe000},
+ {0xc6ac0000}, {0xc6ac2000}, {0xc6ac4000}, {0xc6ac6000},
+ {0xc6ac8000}, {0xc6aca000}, {0xc6acc000}, {0xc6ace000},
+ {0xc6ad0000}, {0xc6ad2000}, {0xc6ad4000}, {0xc6ad6000},
+ {0xc6ad8000}, {0xc6ada000}, {0xc6adc000}, {0xc6ade000},
+ {0xc6ae0000}, {0xc6ae2000}, {0xc6ae4000}, {0xc6ae6000},
+ {0xc6ae8000}, {0xc6aea000}, {0xc6aec000}, {0xc6aee000},
+ {0xc6af0000}, {0xc6af2000}, {0xc6af4000}, {0xc6af6000},
+ {0xc6af8000}, {0xc6afa000}, {0xc6afc000}, {0xc6afe000},
+ {0xc6b00000}, {0xc6b02000}, {0xc6b04000}, {0xc6b06000},
+ {0xc6b08000}, {0xc6b0a000}, {0xc6b0c000}, {0xc6b0e000},
+ {0xc6b10000}, {0xc6b12000}, {0xc6b14000}, {0xc6b16000},
+ {0xc6b18000}, {0xc6b1a000}, {0xc6b1c000}, {0xc6b1e000},
+ {0xc6b20000}, {0xc6b22000}, {0xc6b24000}, {0xc6b26000},
+ {0xc6b28000}, {0xc6b2a000}, {0xc6b2c000}, {0xc6b2e000},
+ {0xc6b30000}, {0xc6b32000}, {0xc6b34000}, {0xc6b36000},
+ {0xc6b38000}, {0xc6b3a000}, {0xc6b3c000}, {0xc6b3e000},
+ {0xc6b40000}, {0xc6b42000}, {0xc6b44000}, {0xc6b46000},
+ {0xc6b48000}, {0xc6b4a000}, {0xc6b4c000}, {0xc6b4e000},
+ {0xc6b50000}, {0xc6b52000}, {0xc6b54000}, {0xc6b56000},
+ {0xc6b58000}, {0xc6b5a000}, {0xc6b5c000}, {0xc6b5e000},
+ {0xc6b60000}, {0xc6b62000}, {0xc6b64000}, {0xc6b66000},
+ {0xc6b68000}, {0xc6b6a000}, {0xc6b6c000}, {0xc6b6e000},
+ {0xc6b70000}, {0xc6b72000}, {0xc6b74000}, {0xc6b76000},
+ {0xc6b78000}, {0xc6b7a000}, {0xc6b7c000}, {0xc6b7e000},
+ {0xc6b80000}, {0xc6b82000}, {0xc6b84000}, {0xc6b86000},
+ {0xc6b88000}, {0xc6b8a000}, {0xc6b8c000}, {0xc6b8e000},
+ {0xc6b90000}, {0xc6b92000}, {0xc6b94000}, {0xc6b96000},
+ {0xc6b98000}, {0xc6b9a000}, {0xc6b9c000}, {0xc6b9e000},
+ {0xc6ba0000}, {0xc6ba2000}, {0xc6ba4000}, {0xc6ba6000},
+ {0xc6ba8000}, {0xc6baa000}, {0xc6bac000}, {0xc6bae000},
+ {0xc6bb0000}, {0xc6bb2000}, {0xc6bb4000}, {0xc6bb6000},
+ {0xc6bb8000}, {0xc6bba000}, {0xc6bbc000}, {0xc6bbe000},
+ {0xc6bc0000}, {0xc6bc2000}, {0xc6bc4000}, {0xc6bc6000},
+ {0xc6bc8000}, {0xc6bca000}, {0xc6bcc000}, {0xc6bce000},
+ {0xc6bd0000}, {0xc6bd2000}, {0xc6bd4000}, {0xc6bd6000},
+ {0xc6bd8000}, {0xc6bda000}, {0xc6bdc000}, {0xc6bde000},
+ {0xc6be0000}, {0xc6be2000}, {0xc6be4000}, {0xc6be6000},
+ {0xc6be8000}, {0xc6bea000}, {0xc6bec000}, {0xc6bee000},
+ {0xc6bf0000}, {0xc6bf2000}, {0xc6bf4000}, {0xc6bf6000},
+ {0xc6bf8000}, {0xc6bfa000}, {0xc6bfc000}, {0xc6bfe000},
+ {0xc6c00000}, {0xc6c02000}, {0xc6c04000}, {0xc6c06000},
+ {0xc6c08000}, {0xc6c0a000}, {0xc6c0c000}, {0xc6c0e000},
+ {0xc6c10000}, {0xc6c12000}, {0xc6c14000}, {0xc6c16000},
+ {0xc6c18000}, {0xc6c1a000}, {0xc6c1c000}, {0xc6c1e000},
+ {0xc6c20000}, {0xc6c22000}, {0xc6c24000}, {0xc6c26000},
+ {0xc6c28000}, {0xc6c2a000}, {0xc6c2c000}, {0xc6c2e000},
+ {0xc6c30000}, {0xc6c32000}, {0xc6c34000}, {0xc6c36000},
+ {0xc6c38000}, {0xc6c3a000}, {0xc6c3c000}, {0xc6c3e000},
+ {0xc6c40000}, {0xc6c42000}, {0xc6c44000}, {0xc6c46000},
+ {0xc6c48000}, {0xc6c4a000}, {0xc6c4c000}, {0xc6c4e000},
+ {0xc6c50000}, {0xc6c52000}, {0xc6c54000}, {0xc6c56000},
+ {0xc6c58000}, {0xc6c5a000}, {0xc6c5c000}, {0xc6c5e000},
+ {0xc6c60000}, {0xc6c62000}, {0xc6c64000}, {0xc6c66000},
+ {0xc6c68000}, {0xc6c6a000}, {0xc6c6c000}, {0xc6c6e000},
+ {0xc6c70000}, {0xc6c72000}, {0xc6c74000}, {0xc6c76000},
+ {0xc6c78000}, {0xc6c7a000}, {0xc6c7c000}, {0xc6c7e000},
+ {0xc6c80000}, {0xc6c82000}, {0xc6c84000}, {0xc6c86000},
+ {0xc6c88000}, {0xc6c8a000}, {0xc6c8c000}, {0xc6c8e000},
+ {0xc6c90000}, {0xc6c92000}, {0xc6c94000}, {0xc6c96000},
+ {0xc6c98000}, {0xc6c9a000}, {0xc6c9c000}, {0xc6c9e000},
+ {0xc6ca0000}, {0xc6ca2000}, {0xc6ca4000}, {0xc6ca6000},
+ {0xc6ca8000}, {0xc6caa000}, {0xc6cac000}, {0xc6cae000},
+ {0xc6cb0000}, {0xc6cb2000}, {0xc6cb4000}, {0xc6cb6000},
+ {0xc6cb8000}, {0xc6cba000}, {0xc6cbc000}, {0xc6cbe000},
+ {0xc6cc0000}, {0xc6cc2000}, {0xc6cc4000}, {0xc6cc6000},
+ {0xc6cc8000}, {0xc6cca000}, {0xc6ccc000}, {0xc6cce000},
+ {0xc6cd0000}, {0xc6cd2000}, {0xc6cd4000}, {0xc6cd6000},
+ {0xc6cd8000}, {0xc6cda000}, {0xc6cdc000}, {0xc6cde000},
+ {0xc6ce0000}, {0xc6ce2000}, {0xc6ce4000}, {0xc6ce6000},
+ {0xc6ce8000}, {0xc6cea000}, {0xc6cec000}, {0xc6cee000},
+ {0xc6cf0000}, {0xc6cf2000}, {0xc6cf4000}, {0xc6cf6000},
+ {0xc6cf8000}, {0xc6cfa000}, {0xc6cfc000}, {0xc6cfe000},
+ {0xc6d00000}, {0xc6d02000}, {0xc6d04000}, {0xc6d06000},
+ {0xc6d08000}, {0xc6d0a000}, {0xc6d0c000}, {0xc6d0e000},
+ {0xc6d10000}, {0xc6d12000}, {0xc6d14000}, {0xc6d16000},
+ {0xc6d18000}, {0xc6d1a000}, {0xc6d1c000}, {0xc6d1e000},
+ {0xc6d20000}, {0xc6d22000}, {0xc6d24000}, {0xc6d26000},
+ {0xc6d28000}, {0xc6d2a000}, {0xc6d2c000}, {0xc6d2e000},
+ {0xc6d30000}, {0xc6d32000}, {0xc6d34000}, {0xc6d36000},
+ {0xc6d38000}, {0xc6d3a000}, {0xc6d3c000}, {0xc6d3e000},
+ {0xc6d40000}, {0xc6d42000}, {0xc6d44000}, {0xc6d46000},
+ {0xc6d48000}, {0xc6d4a000}, {0xc6d4c000}, {0xc6d4e000},
+ {0xc6d50000}, {0xc6d52000}, {0xc6d54000}, {0xc6d56000},
+ {0xc6d58000}, {0xc6d5a000}, {0xc6d5c000}, {0xc6d5e000},
+ {0xc6d60000}, {0xc6d62000}, {0xc6d64000}, {0xc6d66000},
+ {0xc6d68000}, {0xc6d6a000}, {0xc6d6c000}, {0xc6d6e000},
+ {0xc6d70000}, {0xc6d72000}, {0xc6d74000}, {0xc6d76000},
+ {0xc6d78000}, {0xc6d7a000}, {0xc6d7c000}, {0xc6d7e000},
+ {0xc6d80000}, {0xc6d82000}, {0xc6d84000}, {0xc6d86000},
+ {0xc6d88000}, {0xc6d8a000}, {0xc6d8c000}, {0xc6d8e000},
+ {0xc6d90000}, {0xc6d92000}, {0xc6d94000}, {0xc6d96000},
+ {0xc6d98000}, {0xc6d9a000}, {0xc6d9c000}, {0xc6d9e000},
+ {0xc6da0000}, {0xc6da2000}, {0xc6da4000}, {0xc6da6000},
+ {0xc6da8000}, {0xc6daa000}, {0xc6dac000}, {0xc6dae000},
+ {0xc6db0000}, {0xc6db2000}, {0xc6db4000}, {0xc6db6000},
+ {0xc6db8000}, {0xc6dba000}, {0xc6dbc000}, {0xc6dbe000},
+ {0xc6dc0000}, {0xc6dc2000}, {0xc6dc4000}, {0xc6dc6000},
+ {0xc6dc8000}, {0xc6dca000}, {0xc6dcc000}, {0xc6dce000},
+ {0xc6dd0000}, {0xc6dd2000}, {0xc6dd4000}, {0xc6dd6000},
+ {0xc6dd8000}, {0xc6dda000}, {0xc6ddc000}, {0xc6dde000},
+ {0xc6de0000}, {0xc6de2000}, {0xc6de4000}, {0xc6de6000},
+ {0xc6de8000}, {0xc6dea000}, {0xc6dec000}, {0xc6dee000},
+ {0xc6df0000}, {0xc6df2000}, {0xc6df4000}, {0xc6df6000},
+ {0xc6df8000}, {0xc6dfa000}, {0xc6dfc000}, {0xc6dfe000},
+ {0xc6e00000}, {0xc6e02000}, {0xc6e04000}, {0xc6e06000},
+ {0xc6e08000}, {0xc6e0a000}, {0xc6e0c000}, {0xc6e0e000},
+ {0xc6e10000}, {0xc6e12000}, {0xc6e14000}, {0xc6e16000},
+ {0xc6e18000}, {0xc6e1a000}, {0xc6e1c000}, {0xc6e1e000},
+ {0xc6e20000}, {0xc6e22000}, {0xc6e24000}, {0xc6e26000},
+ {0xc6e28000}, {0xc6e2a000}, {0xc6e2c000}, {0xc6e2e000},
+ {0xc6e30000}, {0xc6e32000}, {0xc6e34000}, {0xc6e36000},
+ {0xc6e38000}, {0xc6e3a000}, {0xc6e3c000}, {0xc6e3e000},
+ {0xc6e40000}, {0xc6e42000}, {0xc6e44000}, {0xc6e46000},
+ {0xc6e48000}, {0xc6e4a000}, {0xc6e4c000}, {0xc6e4e000},
+ {0xc6e50000}, {0xc6e52000}, {0xc6e54000}, {0xc6e56000},
+ {0xc6e58000}, {0xc6e5a000}, {0xc6e5c000}, {0xc6e5e000},
+ {0xc6e60000}, {0xc6e62000}, {0xc6e64000}, {0xc6e66000},
+ {0xc6e68000}, {0xc6e6a000}, {0xc6e6c000}, {0xc6e6e000},
+ {0xc6e70000}, {0xc6e72000}, {0xc6e74000}, {0xc6e76000},
+ {0xc6e78000}, {0xc6e7a000}, {0xc6e7c000}, {0xc6e7e000},
+ {0xc6e80000}, {0xc6e82000}, {0xc6e84000}, {0xc6e86000},
+ {0xc6e88000}, {0xc6e8a000}, {0xc6e8c000}, {0xc6e8e000},
+ {0xc6e90000}, {0xc6e92000}, {0xc6e94000}, {0xc6e96000},
+ {0xc6e98000}, {0xc6e9a000}, {0xc6e9c000}, {0xc6e9e000},
+ {0xc6ea0000}, {0xc6ea2000}, {0xc6ea4000}, {0xc6ea6000},
+ {0xc6ea8000}, {0xc6eaa000}, {0xc6eac000}, {0xc6eae000},
+ {0xc6eb0000}, {0xc6eb2000}, {0xc6eb4000}, {0xc6eb6000},
+ {0xc6eb8000}, {0xc6eba000}, {0xc6ebc000}, {0xc6ebe000},
+ {0xc6ec0000}, {0xc6ec2000}, {0xc6ec4000}, {0xc6ec6000},
+ {0xc6ec8000}, {0xc6eca000}, {0xc6ecc000}, {0xc6ece000},
+ {0xc6ed0000}, {0xc6ed2000}, {0xc6ed4000}, {0xc6ed6000},
+ {0xc6ed8000}, {0xc6eda000}, {0xc6edc000}, {0xc6ede000},
+ {0xc6ee0000}, {0xc6ee2000}, {0xc6ee4000}, {0xc6ee6000},
+ {0xc6ee8000}, {0xc6eea000}, {0xc6eec000}, {0xc6eee000},
+ {0xc6ef0000}, {0xc6ef2000}, {0xc6ef4000}, {0xc6ef6000},
+ {0xc6ef8000}, {0xc6efa000}, {0xc6efc000}, {0xc6efe000},
+ {0xc6f00000}, {0xc6f02000}, {0xc6f04000}, {0xc6f06000},
+ {0xc6f08000}, {0xc6f0a000}, {0xc6f0c000}, {0xc6f0e000},
+ {0xc6f10000}, {0xc6f12000}, {0xc6f14000}, {0xc6f16000},
+ {0xc6f18000}, {0xc6f1a000}, {0xc6f1c000}, {0xc6f1e000},
+ {0xc6f20000}, {0xc6f22000}, {0xc6f24000}, {0xc6f26000},
+ {0xc6f28000}, {0xc6f2a000}, {0xc6f2c000}, {0xc6f2e000},
+ {0xc6f30000}, {0xc6f32000}, {0xc6f34000}, {0xc6f36000},
+ {0xc6f38000}, {0xc6f3a000}, {0xc6f3c000}, {0xc6f3e000},
+ {0xc6f40000}, {0xc6f42000}, {0xc6f44000}, {0xc6f46000},
+ {0xc6f48000}, {0xc6f4a000}, {0xc6f4c000}, {0xc6f4e000},
+ {0xc6f50000}, {0xc6f52000}, {0xc6f54000}, {0xc6f56000},
+ {0xc6f58000}, {0xc6f5a000}, {0xc6f5c000}, {0xc6f5e000},
+ {0xc6f60000}, {0xc6f62000}, {0xc6f64000}, {0xc6f66000},
+ {0xc6f68000}, {0xc6f6a000}, {0xc6f6c000}, {0xc6f6e000},
+ {0xc6f70000}, {0xc6f72000}, {0xc6f74000}, {0xc6f76000},
+ {0xc6f78000}, {0xc6f7a000}, {0xc6f7c000}, {0xc6f7e000},
+ {0xc6f80000}, {0xc6f82000}, {0xc6f84000}, {0xc6f86000},
+ {0xc6f88000}, {0xc6f8a000}, {0xc6f8c000}, {0xc6f8e000},
+ {0xc6f90000}, {0xc6f92000}, {0xc6f94000}, {0xc6f96000},
+ {0xc6f98000}, {0xc6f9a000}, {0xc6f9c000}, {0xc6f9e000},
+ {0xc6fa0000}, {0xc6fa2000}, {0xc6fa4000}, {0xc6fa6000},
+ {0xc6fa8000}, {0xc6faa000}, {0xc6fac000}, {0xc6fae000},
+ {0xc6fb0000}, {0xc6fb2000}, {0xc6fb4000}, {0xc6fb6000},
+ {0xc6fb8000}, {0xc6fba000}, {0xc6fbc000}, {0xc6fbe000},
+ {0xc6fc0000}, {0xc6fc2000}, {0xc6fc4000}, {0xc6fc6000},
+ {0xc6fc8000}, {0xc6fca000}, {0xc6fcc000}, {0xc6fce000},
+ {0xc6fd0000}, {0xc6fd2000}, {0xc6fd4000}, {0xc6fd6000},
+ {0xc6fd8000}, {0xc6fda000}, {0xc6fdc000}, {0xc6fde000},
+ {0xc6fe0000}, {0xc6fe2000}, {0xc6fe4000}, {0xc6fe6000},
+ {0xc6fe8000}, {0xc6fea000}, {0xc6fec000}, {0xc6fee000},
+ {0xc6ff0000}, {0xc6ff2000}, {0xc6ff4000}, {0xc6ff6000},
+ {0xc6ff8000}, {0xc6ffa000}, {0xc6ffc000}, {0xc6ffe000},
+ {0xc7000000}, {0xc7002000}, {0xc7004000}, {0xc7006000},
+ {0xc7008000}, {0xc700a000}, {0xc700c000}, {0xc700e000},
+ {0xc7010000}, {0xc7012000}, {0xc7014000}, {0xc7016000},
+ {0xc7018000}, {0xc701a000}, {0xc701c000}, {0xc701e000},
+ {0xc7020000}, {0xc7022000}, {0xc7024000}, {0xc7026000},
+ {0xc7028000}, {0xc702a000}, {0xc702c000}, {0xc702e000},
+ {0xc7030000}, {0xc7032000}, {0xc7034000}, {0xc7036000},
+ {0xc7038000}, {0xc703a000}, {0xc703c000}, {0xc703e000},
+ {0xc7040000}, {0xc7042000}, {0xc7044000}, {0xc7046000},
+ {0xc7048000}, {0xc704a000}, {0xc704c000}, {0xc704e000},
+ {0xc7050000}, {0xc7052000}, {0xc7054000}, {0xc7056000},
+ {0xc7058000}, {0xc705a000}, {0xc705c000}, {0xc705e000},
+ {0xc7060000}, {0xc7062000}, {0xc7064000}, {0xc7066000},
+ {0xc7068000}, {0xc706a000}, {0xc706c000}, {0xc706e000},
+ {0xc7070000}, {0xc7072000}, {0xc7074000}, {0xc7076000},
+ {0xc7078000}, {0xc707a000}, {0xc707c000}, {0xc707e000},
+ {0xc7080000}, {0xc7082000}, {0xc7084000}, {0xc7086000},
+ {0xc7088000}, {0xc708a000}, {0xc708c000}, {0xc708e000},
+ {0xc7090000}, {0xc7092000}, {0xc7094000}, {0xc7096000},
+ {0xc7098000}, {0xc709a000}, {0xc709c000}, {0xc709e000},
+ {0xc70a0000}, {0xc70a2000}, {0xc70a4000}, {0xc70a6000},
+ {0xc70a8000}, {0xc70aa000}, {0xc70ac000}, {0xc70ae000},
+ {0xc70b0000}, {0xc70b2000}, {0xc70b4000}, {0xc70b6000},
+ {0xc70b8000}, {0xc70ba000}, {0xc70bc000}, {0xc70be000},
+ {0xc70c0000}, {0xc70c2000}, {0xc70c4000}, {0xc70c6000},
+ {0xc70c8000}, {0xc70ca000}, {0xc70cc000}, {0xc70ce000},
+ {0xc70d0000}, {0xc70d2000}, {0xc70d4000}, {0xc70d6000},
+ {0xc70d8000}, {0xc70da000}, {0xc70dc000}, {0xc70de000},
+ {0xc70e0000}, {0xc70e2000}, {0xc70e4000}, {0xc70e6000},
+ {0xc70e8000}, {0xc70ea000}, {0xc70ec000}, {0xc70ee000},
+ {0xc70f0000}, {0xc70f2000}, {0xc70f4000}, {0xc70f6000},
+ {0xc70f8000}, {0xc70fa000}, {0xc70fc000}, {0xc70fe000},
+ {0xc7100000}, {0xc7102000}, {0xc7104000}, {0xc7106000},
+ {0xc7108000}, {0xc710a000}, {0xc710c000}, {0xc710e000},
+ {0xc7110000}, {0xc7112000}, {0xc7114000}, {0xc7116000},
+ {0xc7118000}, {0xc711a000}, {0xc711c000}, {0xc711e000},
+ {0xc7120000}, {0xc7122000}, {0xc7124000}, {0xc7126000},
+ {0xc7128000}, {0xc712a000}, {0xc712c000}, {0xc712e000},
+ {0xc7130000}, {0xc7132000}, {0xc7134000}, {0xc7136000},
+ {0xc7138000}, {0xc713a000}, {0xc713c000}, {0xc713e000},
+ {0xc7140000}, {0xc7142000}, {0xc7144000}, {0xc7146000},
+ {0xc7148000}, {0xc714a000}, {0xc714c000}, {0xc714e000},
+ {0xc7150000}, {0xc7152000}, {0xc7154000}, {0xc7156000},
+ {0xc7158000}, {0xc715a000}, {0xc715c000}, {0xc715e000},
+ {0xc7160000}, {0xc7162000}, {0xc7164000}, {0xc7166000},
+ {0xc7168000}, {0xc716a000}, {0xc716c000}, {0xc716e000},
+ {0xc7170000}, {0xc7172000}, {0xc7174000}, {0xc7176000},
+ {0xc7178000}, {0xc717a000}, {0xc717c000}, {0xc717e000},
+ {0xc7180000}, {0xc7182000}, {0xc7184000}, {0xc7186000},
+ {0xc7188000}, {0xc718a000}, {0xc718c000}, {0xc718e000},
+ {0xc7190000}, {0xc7192000}, {0xc7194000}, {0xc7196000},
+ {0xc7198000}, {0xc719a000}, {0xc719c000}, {0xc719e000},
+ {0xc71a0000}, {0xc71a2000}, {0xc71a4000}, {0xc71a6000},
+ {0xc71a8000}, {0xc71aa000}, {0xc71ac000}, {0xc71ae000},
+ {0xc71b0000}, {0xc71b2000}, {0xc71b4000}, {0xc71b6000},
+ {0xc71b8000}, {0xc71ba000}, {0xc71bc000}, {0xc71be000},
+ {0xc71c0000}, {0xc71c2000}, {0xc71c4000}, {0xc71c6000},
+ {0xc71c8000}, {0xc71ca000}, {0xc71cc000}, {0xc71ce000},
+ {0xc71d0000}, {0xc71d2000}, {0xc71d4000}, {0xc71d6000},
+ {0xc71d8000}, {0xc71da000}, {0xc71dc000}, {0xc71de000},
+ {0xc71e0000}, {0xc71e2000}, {0xc71e4000}, {0xc71e6000},
+ {0xc71e8000}, {0xc71ea000}, {0xc71ec000}, {0xc71ee000},
+ {0xc71f0000}, {0xc71f2000}, {0xc71f4000}, {0xc71f6000},
+ {0xc71f8000}, {0xc71fa000}, {0xc71fc000}, {0xc71fe000},
+ {0xc7200000}, {0xc7202000}, {0xc7204000}, {0xc7206000},
+ {0xc7208000}, {0xc720a000}, {0xc720c000}, {0xc720e000},
+ {0xc7210000}, {0xc7212000}, {0xc7214000}, {0xc7216000},
+ {0xc7218000}, {0xc721a000}, {0xc721c000}, {0xc721e000},
+ {0xc7220000}, {0xc7222000}, {0xc7224000}, {0xc7226000},
+ {0xc7228000}, {0xc722a000}, {0xc722c000}, {0xc722e000},
+ {0xc7230000}, {0xc7232000}, {0xc7234000}, {0xc7236000},
+ {0xc7238000}, {0xc723a000}, {0xc723c000}, {0xc723e000},
+ {0xc7240000}, {0xc7242000}, {0xc7244000}, {0xc7246000},
+ {0xc7248000}, {0xc724a000}, {0xc724c000}, {0xc724e000},
+ {0xc7250000}, {0xc7252000}, {0xc7254000}, {0xc7256000},
+ {0xc7258000}, {0xc725a000}, {0xc725c000}, {0xc725e000},
+ {0xc7260000}, {0xc7262000}, {0xc7264000}, {0xc7266000},
+ {0xc7268000}, {0xc726a000}, {0xc726c000}, {0xc726e000},
+ {0xc7270000}, {0xc7272000}, {0xc7274000}, {0xc7276000},
+ {0xc7278000}, {0xc727a000}, {0xc727c000}, {0xc727e000},
+ {0xc7280000}, {0xc7282000}, {0xc7284000}, {0xc7286000},
+ {0xc7288000}, {0xc728a000}, {0xc728c000}, {0xc728e000},
+ {0xc7290000}, {0xc7292000}, {0xc7294000}, {0xc7296000},
+ {0xc7298000}, {0xc729a000}, {0xc729c000}, {0xc729e000},
+ {0xc72a0000}, {0xc72a2000}, {0xc72a4000}, {0xc72a6000},
+ {0xc72a8000}, {0xc72aa000}, {0xc72ac000}, {0xc72ae000},
+ {0xc72b0000}, {0xc72b2000}, {0xc72b4000}, {0xc72b6000},
+ {0xc72b8000}, {0xc72ba000}, {0xc72bc000}, {0xc72be000},
+ {0xc72c0000}, {0xc72c2000}, {0xc72c4000}, {0xc72c6000},
+ {0xc72c8000}, {0xc72ca000}, {0xc72cc000}, {0xc72ce000},
+ {0xc72d0000}, {0xc72d2000}, {0xc72d4000}, {0xc72d6000},
+ {0xc72d8000}, {0xc72da000}, {0xc72dc000}, {0xc72de000},
+ {0xc72e0000}, {0xc72e2000}, {0xc72e4000}, {0xc72e6000},
+ {0xc72e8000}, {0xc72ea000}, {0xc72ec000}, {0xc72ee000},
+ {0xc72f0000}, {0xc72f2000}, {0xc72f4000}, {0xc72f6000},
+ {0xc72f8000}, {0xc72fa000}, {0xc72fc000}, {0xc72fe000},
+ {0xc7300000}, {0xc7302000}, {0xc7304000}, {0xc7306000},
+ {0xc7308000}, {0xc730a000}, {0xc730c000}, {0xc730e000},
+ {0xc7310000}, {0xc7312000}, {0xc7314000}, {0xc7316000},
+ {0xc7318000}, {0xc731a000}, {0xc731c000}, {0xc731e000},
+ {0xc7320000}, {0xc7322000}, {0xc7324000}, {0xc7326000},
+ {0xc7328000}, {0xc732a000}, {0xc732c000}, {0xc732e000},
+ {0xc7330000}, {0xc7332000}, {0xc7334000}, {0xc7336000},
+ {0xc7338000}, {0xc733a000}, {0xc733c000}, {0xc733e000},
+ {0xc7340000}, {0xc7342000}, {0xc7344000}, {0xc7346000},
+ {0xc7348000}, {0xc734a000}, {0xc734c000}, {0xc734e000},
+ {0xc7350000}, {0xc7352000}, {0xc7354000}, {0xc7356000},
+ {0xc7358000}, {0xc735a000}, {0xc735c000}, {0xc735e000},
+ {0xc7360000}, {0xc7362000}, {0xc7364000}, {0xc7366000},
+ {0xc7368000}, {0xc736a000}, {0xc736c000}, {0xc736e000},
+ {0xc7370000}, {0xc7372000}, {0xc7374000}, {0xc7376000},
+ {0xc7378000}, {0xc737a000}, {0xc737c000}, {0xc737e000},
+ {0xc7380000}, {0xc7382000}, {0xc7384000}, {0xc7386000},
+ {0xc7388000}, {0xc738a000}, {0xc738c000}, {0xc738e000},
+ {0xc7390000}, {0xc7392000}, {0xc7394000}, {0xc7396000},
+ {0xc7398000}, {0xc739a000}, {0xc739c000}, {0xc739e000},
+ {0xc73a0000}, {0xc73a2000}, {0xc73a4000}, {0xc73a6000},
+ {0xc73a8000}, {0xc73aa000}, {0xc73ac000}, {0xc73ae000},
+ {0xc73b0000}, {0xc73b2000}, {0xc73b4000}, {0xc73b6000},
+ {0xc73b8000}, {0xc73ba000}, {0xc73bc000}, {0xc73be000},
+ {0xc73c0000}, {0xc73c2000}, {0xc73c4000}, {0xc73c6000},
+ {0xc73c8000}, {0xc73ca000}, {0xc73cc000}, {0xc73ce000},
+ {0xc73d0000}, {0xc73d2000}, {0xc73d4000}, {0xc73d6000},
+ {0xc73d8000}, {0xc73da000}, {0xc73dc000}, {0xc73de000},
+ {0xc73e0000}, {0xc73e2000}, {0xc73e4000}, {0xc73e6000},
+ {0xc73e8000}, {0xc73ea000}, {0xc73ec000}, {0xc73ee000},
+ {0xc73f0000}, {0xc73f2000}, {0xc73f4000}, {0xc73f6000},
+ {0xc73f8000}, {0xc73fa000}, {0xc73fc000}, {0xc73fe000},
+ {0xc7400000}, {0xc7402000}, {0xc7404000}, {0xc7406000},
+ {0xc7408000}, {0xc740a000}, {0xc740c000}, {0xc740e000},
+ {0xc7410000}, {0xc7412000}, {0xc7414000}, {0xc7416000},
+ {0xc7418000}, {0xc741a000}, {0xc741c000}, {0xc741e000},
+ {0xc7420000}, {0xc7422000}, {0xc7424000}, {0xc7426000},
+ {0xc7428000}, {0xc742a000}, {0xc742c000}, {0xc742e000},
+ {0xc7430000}, {0xc7432000}, {0xc7434000}, {0xc7436000},
+ {0xc7438000}, {0xc743a000}, {0xc743c000}, {0xc743e000},
+ {0xc7440000}, {0xc7442000}, {0xc7444000}, {0xc7446000},
+ {0xc7448000}, {0xc744a000}, {0xc744c000}, {0xc744e000},
+ {0xc7450000}, {0xc7452000}, {0xc7454000}, {0xc7456000},
+ {0xc7458000}, {0xc745a000}, {0xc745c000}, {0xc745e000},
+ {0xc7460000}, {0xc7462000}, {0xc7464000}, {0xc7466000},
+ {0xc7468000}, {0xc746a000}, {0xc746c000}, {0xc746e000},
+ {0xc7470000}, {0xc7472000}, {0xc7474000}, {0xc7476000},
+ {0xc7478000}, {0xc747a000}, {0xc747c000}, {0xc747e000},
+ {0xc7480000}, {0xc7482000}, {0xc7484000}, {0xc7486000},
+ {0xc7488000}, {0xc748a000}, {0xc748c000}, {0xc748e000},
+ {0xc7490000}, {0xc7492000}, {0xc7494000}, {0xc7496000},
+ {0xc7498000}, {0xc749a000}, {0xc749c000}, {0xc749e000},
+ {0xc74a0000}, {0xc74a2000}, {0xc74a4000}, {0xc74a6000},
+ {0xc74a8000}, {0xc74aa000}, {0xc74ac000}, {0xc74ae000},
+ {0xc74b0000}, {0xc74b2000}, {0xc74b4000}, {0xc74b6000},
+ {0xc74b8000}, {0xc74ba000}, {0xc74bc000}, {0xc74be000},
+ {0xc74c0000}, {0xc74c2000}, {0xc74c4000}, {0xc74c6000},
+ {0xc74c8000}, {0xc74ca000}, {0xc74cc000}, {0xc74ce000},
+ {0xc74d0000}, {0xc74d2000}, {0xc74d4000}, {0xc74d6000},
+ {0xc74d8000}, {0xc74da000}, {0xc74dc000}, {0xc74de000},
+ {0xc74e0000}, {0xc74e2000}, {0xc74e4000}, {0xc74e6000},
+ {0xc74e8000}, {0xc74ea000}, {0xc74ec000}, {0xc74ee000},
+ {0xc74f0000}, {0xc74f2000}, {0xc74f4000}, {0xc74f6000},
+ {0xc74f8000}, {0xc74fa000}, {0xc74fc000}, {0xc74fe000},
+ {0xc7500000}, {0xc7502000}, {0xc7504000}, {0xc7506000},
+ {0xc7508000}, {0xc750a000}, {0xc750c000}, {0xc750e000},
+ {0xc7510000}, {0xc7512000}, {0xc7514000}, {0xc7516000},
+ {0xc7518000}, {0xc751a000}, {0xc751c000}, {0xc751e000},
+ {0xc7520000}, {0xc7522000}, {0xc7524000}, {0xc7526000},
+ {0xc7528000}, {0xc752a000}, {0xc752c000}, {0xc752e000},
+ {0xc7530000}, {0xc7532000}, {0xc7534000}, {0xc7536000},
+ {0xc7538000}, {0xc753a000}, {0xc753c000}, {0xc753e000},
+ {0xc7540000}, {0xc7542000}, {0xc7544000}, {0xc7546000},
+ {0xc7548000}, {0xc754a000}, {0xc754c000}, {0xc754e000},
+ {0xc7550000}, {0xc7552000}, {0xc7554000}, {0xc7556000},
+ {0xc7558000}, {0xc755a000}, {0xc755c000}, {0xc755e000},
+ {0xc7560000}, {0xc7562000}, {0xc7564000}, {0xc7566000},
+ {0xc7568000}, {0xc756a000}, {0xc756c000}, {0xc756e000},
+ {0xc7570000}, {0xc7572000}, {0xc7574000}, {0xc7576000},
+ {0xc7578000}, {0xc757a000}, {0xc757c000}, {0xc757e000},
+ {0xc7580000}, {0xc7582000}, {0xc7584000}, {0xc7586000},
+ {0xc7588000}, {0xc758a000}, {0xc758c000}, {0xc758e000},
+ {0xc7590000}, {0xc7592000}, {0xc7594000}, {0xc7596000},
+ {0xc7598000}, {0xc759a000}, {0xc759c000}, {0xc759e000},
+ {0xc75a0000}, {0xc75a2000}, {0xc75a4000}, {0xc75a6000},
+ {0xc75a8000}, {0xc75aa000}, {0xc75ac000}, {0xc75ae000},
+ {0xc75b0000}, {0xc75b2000}, {0xc75b4000}, {0xc75b6000},
+ {0xc75b8000}, {0xc75ba000}, {0xc75bc000}, {0xc75be000},
+ {0xc75c0000}, {0xc75c2000}, {0xc75c4000}, {0xc75c6000},
+ {0xc75c8000}, {0xc75ca000}, {0xc75cc000}, {0xc75ce000},
+ {0xc75d0000}, {0xc75d2000}, {0xc75d4000}, {0xc75d6000},
+ {0xc75d8000}, {0xc75da000}, {0xc75dc000}, {0xc75de000},
+ {0xc75e0000}, {0xc75e2000}, {0xc75e4000}, {0xc75e6000},
+ {0xc75e8000}, {0xc75ea000}, {0xc75ec000}, {0xc75ee000},
+ {0xc75f0000}, {0xc75f2000}, {0xc75f4000}, {0xc75f6000},
+ {0xc75f8000}, {0xc75fa000}, {0xc75fc000}, {0xc75fe000},
+ {0xc7600000}, {0xc7602000}, {0xc7604000}, {0xc7606000},
+ {0xc7608000}, {0xc760a000}, {0xc760c000}, {0xc760e000},
+ {0xc7610000}, {0xc7612000}, {0xc7614000}, {0xc7616000},
+ {0xc7618000}, {0xc761a000}, {0xc761c000}, {0xc761e000},
+ {0xc7620000}, {0xc7622000}, {0xc7624000}, {0xc7626000},
+ {0xc7628000}, {0xc762a000}, {0xc762c000}, {0xc762e000},
+ {0xc7630000}, {0xc7632000}, {0xc7634000}, {0xc7636000},
+ {0xc7638000}, {0xc763a000}, {0xc763c000}, {0xc763e000},
+ {0xc7640000}, {0xc7642000}, {0xc7644000}, {0xc7646000},
+ {0xc7648000}, {0xc764a000}, {0xc764c000}, {0xc764e000},
+ {0xc7650000}, {0xc7652000}, {0xc7654000}, {0xc7656000},
+ {0xc7658000}, {0xc765a000}, {0xc765c000}, {0xc765e000},
+ {0xc7660000}, {0xc7662000}, {0xc7664000}, {0xc7666000},
+ {0xc7668000}, {0xc766a000}, {0xc766c000}, {0xc766e000},
+ {0xc7670000}, {0xc7672000}, {0xc7674000}, {0xc7676000},
+ {0xc7678000}, {0xc767a000}, {0xc767c000}, {0xc767e000},
+ {0xc7680000}, {0xc7682000}, {0xc7684000}, {0xc7686000},
+ {0xc7688000}, {0xc768a000}, {0xc768c000}, {0xc768e000},
+ {0xc7690000}, {0xc7692000}, {0xc7694000}, {0xc7696000},
+ {0xc7698000}, {0xc769a000}, {0xc769c000}, {0xc769e000},
+ {0xc76a0000}, {0xc76a2000}, {0xc76a4000}, {0xc76a6000},
+ {0xc76a8000}, {0xc76aa000}, {0xc76ac000}, {0xc76ae000},
+ {0xc76b0000}, {0xc76b2000}, {0xc76b4000}, {0xc76b6000},
+ {0xc76b8000}, {0xc76ba000}, {0xc76bc000}, {0xc76be000},
+ {0xc76c0000}, {0xc76c2000}, {0xc76c4000}, {0xc76c6000},
+ {0xc76c8000}, {0xc76ca000}, {0xc76cc000}, {0xc76ce000},
+ {0xc76d0000}, {0xc76d2000}, {0xc76d4000}, {0xc76d6000},
+ {0xc76d8000}, {0xc76da000}, {0xc76dc000}, {0xc76de000},
+ {0xc76e0000}, {0xc76e2000}, {0xc76e4000}, {0xc76e6000},
+ {0xc76e8000}, {0xc76ea000}, {0xc76ec000}, {0xc76ee000},
+ {0xc76f0000}, {0xc76f2000}, {0xc76f4000}, {0xc76f6000},
+ {0xc76f8000}, {0xc76fa000}, {0xc76fc000}, {0xc76fe000},
+ {0xc7700000}, {0xc7702000}, {0xc7704000}, {0xc7706000},
+ {0xc7708000}, {0xc770a000}, {0xc770c000}, {0xc770e000},
+ {0xc7710000}, {0xc7712000}, {0xc7714000}, {0xc7716000},
+ {0xc7718000}, {0xc771a000}, {0xc771c000}, {0xc771e000},
+ {0xc7720000}, {0xc7722000}, {0xc7724000}, {0xc7726000},
+ {0xc7728000}, {0xc772a000}, {0xc772c000}, {0xc772e000},
+ {0xc7730000}, {0xc7732000}, {0xc7734000}, {0xc7736000},
+ {0xc7738000}, {0xc773a000}, {0xc773c000}, {0xc773e000},
+ {0xc7740000}, {0xc7742000}, {0xc7744000}, {0xc7746000},
+ {0xc7748000}, {0xc774a000}, {0xc774c000}, {0xc774e000},
+ {0xc7750000}, {0xc7752000}, {0xc7754000}, {0xc7756000},
+ {0xc7758000}, {0xc775a000}, {0xc775c000}, {0xc775e000},
+ {0xc7760000}, {0xc7762000}, {0xc7764000}, {0xc7766000},
+ {0xc7768000}, {0xc776a000}, {0xc776c000}, {0xc776e000},
+ {0xc7770000}, {0xc7772000}, {0xc7774000}, {0xc7776000},
+ {0xc7778000}, {0xc777a000}, {0xc777c000}, {0xc777e000},
+ {0xc7780000}, {0xc7782000}, {0xc7784000}, {0xc7786000},
+ {0xc7788000}, {0xc778a000}, {0xc778c000}, {0xc778e000},
+ {0xc7790000}, {0xc7792000}, {0xc7794000}, {0xc7796000},
+ {0xc7798000}, {0xc779a000}, {0xc779c000}, {0xc779e000},
+ {0xc77a0000}, {0xc77a2000}, {0xc77a4000}, {0xc77a6000},
+ {0xc77a8000}, {0xc77aa000}, {0xc77ac000}, {0xc77ae000},
+ {0xc77b0000}, {0xc77b2000}, {0xc77b4000}, {0xc77b6000},
+ {0xc77b8000}, {0xc77ba000}, {0xc77bc000}, {0xc77be000},
+ {0xc77c0000}, {0xc77c2000}, {0xc77c4000}, {0xc77c6000},
+ {0xc77c8000}, {0xc77ca000}, {0xc77cc000}, {0xc77ce000},
+ {0xc77d0000}, {0xc77d2000}, {0xc77d4000}, {0xc77d6000},
+ {0xc77d8000}, {0xc77da000}, {0xc77dc000}, {0xc77de000},
+ {0xc77e0000}, {0xc77e2000}, {0xc77e4000}, {0xc77e6000},
+ {0xc77e8000}, {0xc77ea000}, {0xc77ec000}, {0xc77ee000},
+ {0xc77f0000}, {0xc77f2000}, {0xc77f4000}, {0xc77f6000},
+ {0xc77f8000}, {0xc77fa000}, {0xc77fc000}, {0xc77fe000},
+ {0xff800000}, {0xff802000}, {0xff804000}, {0xff806000},
+ {0xff808000}, {0xff80a000}, {0xff80c000}, {0xff80e000},
+ {0xff810000}, {0xff812000}, {0xff814000}, {0xff816000},
+ {0xff818000}, {0xff81a000}, {0xff81c000}, {0xff81e000},
+ {0xff820000}, {0xff822000}, {0xff824000}, {0xff826000},
+ {0xff828000}, {0xff82a000}, {0xff82c000}, {0xff82e000},
+ {0xff830000}, {0xff832000}, {0xff834000}, {0xff836000},
+ {0xff838000}, {0xff83a000}, {0xff83c000}, {0xff83e000},
+ {0xff840000}, {0xff842000}, {0xff844000}, {0xff846000},
+ {0xff848000}, {0xff84a000}, {0xff84c000}, {0xff84e000},
+ {0xff850000}, {0xff852000}, {0xff854000}, {0xff856000},
+ {0xff858000}, {0xff85a000}, {0xff85c000}, {0xff85e000},
+ {0xff860000}, {0xff862000}, {0xff864000}, {0xff866000},
+ {0xff868000}, {0xff86a000}, {0xff86c000}, {0xff86e000},
+ {0xff870000}, {0xff872000}, {0xff874000}, {0xff876000},
+ {0xff878000}, {0xff87a000}, {0xff87c000}, {0xff87e000},
+ {0xff880000}, {0xff882000}, {0xff884000}, {0xff886000},
+ {0xff888000}, {0xff88a000}, {0xff88c000}, {0xff88e000},
+ {0xff890000}, {0xff892000}, {0xff894000}, {0xff896000},
+ {0xff898000}, {0xff89a000}, {0xff89c000}, {0xff89e000},
+ {0xff8a0000}, {0xff8a2000}, {0xff8a4000}, {0xff8a6000},
+ {0xff8a8000}, {0xff8aa000}, {0xff8ac000}, {0xff8ae000},
+ {0xff8b0000}, {0xff8b2000}, {0xff8b4000}, {0xff8b6000},
+ {0xff8b8000}, {0xff8ba000}, {0xff8bc000}, {0xff8be000},
+ {0xff8c0000}, {0xff8c2000}, {0xff8c4000}, {0xff8c6000},
+ {0xff8c8000}, {0xff8ca000}, {0xff8cc000}, {0xff8ce000},
+ {0xff8d0000}, {0xff8d2000}, {0xff8d4000}, {0xff8d6000},
+ {0xff8d8000}, {0xff8da000}, {0xff8dc000}, {0xff8de000},
+ {0xff8e0000}, {0xff8e2000}, {0xff8e4000}, {0xff8e6000},
+ {0xff8e8000}, {0xff8ea000}, {0xff8ec000}, {0xff8ee000},
+ {0xff8f0000}, {0xff8f2000}, {0xff8f4000}, {0xff8f6000},
+ {0xff8f8000}, {0xff8fa000}, {0xff8fc000}, {0xff8fe000},
+ {0xff900000}, {0xff902000}, {0xff904000}, {0xff906000},
+ {0xff908000}, {0xff90a000}, {0xff90c000}, {0xff90e000},
+ {0xff910000}, {0xff912000}, {0xff914000}, {0xff916000},
+ {0xff918000}, {0xff91a000}, {0xff91c000}, {0xff91e000},
+ {0xff920000}, {0xff922000}, {0xff924000}, {0xff926000},
+ {0xff928000}, {0xff92a000}, {0xff92c000}, {0xff92e000},
+ {0xff930000}, {0xff932000}, {0xff934000}, {0xff936000},
+ {0xff938000}, {0xff93a000}, {0xff93c000}, {0xff93e000},
+ {0xff940000}, {0xff942000}, {0xff944000}, {0xff946000},
+ {0xff948000}, {0xff94a000}, {0xff94c000}, {0xff94e000},
+ {0xff950000}, {0xff952000}, {0xff954000}, {0xff956000},
+ {0xff958000}, {0xff95a000}, {0xff95c000}, {0xff95e000},
+ {0xff960000}, {0xff962000}, {0xff964000}, {0xff966000},
+ {0xff968000}, {0xff96a000}, {0xff96c000}, {0xff96e000},
+ {0xff970000}, {0xff972000}, {0xff974000}, {0xff976000},
+ {0xff978000}, {0xff97a000}, {0xff97c000}, {0xff97e000},
+ {0xff980000}, {0xff982000}, {0xff984000}, {0xff986000},
+ {0xff988000}, {0xff98a000}, {0xff98c000}, {0xff98e000},
+ {0xff990000}, {0xff992000}, {0xff994000}, {0xff996000},
+ {0xff998000}, {0xff99a000}, {0xff99c000}, {0xff99e000},
+ {0xff9a0000}, {0xff9a2000}, {0xff9a4000}, {0xff9a6000},
+ {0xff9a8000}, {0xff9aa000}, {0xff9ac000}, {0xff9ae000},
+ {0xff9b0000}, {0xff9b2000}, {0xff9b4000}, {0xff9b6000},
+ {0xff9b8000}, {0xff9ba000}, {0xff9bc000}, {0xff9be000},
+ {0xff9c0000}, {0xff9c2000}, {0xff9c4000}, {0xff9c6000},
+ {0xff9c8000}, {0xff9ca000}, {0xff9cc000}, {0xff9ce000},
+ {0xff9d0000}, {0xff9d2000}, {0xff9d4000}, {0xff9d6000},
+ {0xff9d8000}, {0xff9da000}, {0xff9dc000}, {0xff9de000},
+ {0xff9e0000}, {0xff9e2000}, {0xff9e4000}, {0xff9e6000},
+ {0xff9e8000}, {0xff9ea000}, {0xff9ec000}, {0xff9ee000},
+ {0xff9f0000}, {0xff9f2000}, {0xff9f4000}, {0xff9f6000},
+ {0xff9f8000}, {0xff9fa000}, {0xff9fc000}, {0xff9fe000},
+ {0xffa00000}, {0xffa02000}, {0xffa04000}, {0xffa06000},
+ {0xffa08000}, {0xffa0a000}, {0xffa0c000}, {0xffa0e000},
+ {0xffa10000}, {0xffa12000}, {0xffa14000}, {0xffa16000},
+ {0xffa18000}, {0xffa1a000}, {0xffa1c000}, {0xffa1e000},
+ {0xffa20000}, {0xffa22000}, {0xffa24000}, {0xffa26000},
+ {0xffa28000}, {0xffa2a000}, {0xffa2c000}, {0xffa2e000},
+ {0xffa30000}, {0xffa32000}, {0xffa34000}, {0xffa36000},
+ {0xffa38000}, {0xffa3a000}, {0xffa3c000}, {0xffa3e000},
+ {0xffa40000}, {0xffa42000}, {0xffa44000}, {0xffa46000},
+ {0xffa48000}, {0xffa4a000}, {0xffa4c000}, {0xffa4e000},
+ {0xffa50000}, {0xffa52000}, {0xffa54000}, {0xffa56000},
+ {0xffa58000}, {0xffa5a000}, {0xffa5c000}, {0xffa5e000},
+ {0xffa60000}, {0xffa62000}, {0xffa64000}, {0xffa66000},
+ {0xffa68000}, {0xffa6a000}, {0xffa6c000}, {0xffa6e000},
+ {0xffa70000}, {0xffa72000}, {0xffa74000}, {0xffa76000},
+ {0xffa78000}, {0xffa7a000}, {0xffa7c000}, {0xffa7e000},
+ {0xffa80000}, {0xffa82000}, {0xffa84000}, {0xffa86000},
+ {0xffa88000}, {0xffa8a000}, {0xffa8c000}, {0xffa8e000},
+ {0xffa90000}, {0xffa92000}, {0xffa94000}, {0xffa96000},
+ {0xffa98000}, {0xffa9a000}, {0xffa9c000}, {0xffa9e000},
+ {0xffaa0000}, {0xffaa2000}, {0xffaa4000}, {0xffaa6000},
+ {0xffaa8000}, {0xffaaa000}, {0xffaac000}, {0xffaae000},
+ {0xffab0000}, {0xffab2000}, {0xffab4000}, {0xffab6000},
+ {0xffab8000}, {0xffaba000}, {0xffabc000}, {0xffabe000},
+ {0xffac0000}, {0xffac2000}, {0xffac4000}, {0xffac6000},
+ {0xffac8000}, {0xffaca000}, {0xffacc000}, {0xfface000},
+ {0xffad0000}, {0xffad2000}, {0xffad4000}, {0xffad6000},
+ {0xffad8000}, {0xffada000}, {0xffadc000}, {0xffade000},
+ {0xffae0000}, {0xffae2000}, {0xffae4000}, {0xffae6000},
+ {0xffae8000}, {0xffaea000}, {0xffaec000}, {0xffaee000},
+ {0xffaf0000}, {0xffaf2000}, {0xffaf4000}, {0xffaf6000},
+ {0xffaf8000}, {0xffafa000}, {0xffafc000}, {0xffafe000},
+ {0xffb00000}, {0xffb02000}, {0xffb04000}, {0xffb06000},
+ {0xffb08000}, {0xffb0a000}, {0xffb0c000}, {0xffb0e000},
+ {0xffb10000}, {0xffb12000}, {0xffb14000}, {0xffb16000},
+ {0xffb18000}, {0xffb1a000}, {0xffb1c000}, {0xffb1e000},
+ {0xffb20000}, {0xffb22000}, {0xffb24000}, {0xffb26000},
+ {0xffb28000}, {0xffb2a000}, {0xffb2c000}, {0xffb2e000},
+ {0xffb30000}, {0xffb32000}, {0xffb34000}, {0xffb36000},
+ {0xffb38000}, {0xffb3a000}, {0xffb3c000}, {0xffb3e000},
+ {0xffb40000}, {0xffb42000}, {0xffb44000}, {0xffb46000},
+ {0xffb48000}, {0xffb4a000}, {0xffb4c000}, {0xffb4e000},
+ {0xffb50000}, {0xffb52000}, {0xffb54000}, {0xffb56000},
+ {0xffb58000}, {0xffb5a000}, {0xffb5c000}, {0xffb5e000},
+ {0xffb60000}, {0xffb62000}, {0xffb64000}, {0xffb66000},
+ {0xffb68000}, {0xffb6a000}, {0xffb6c000}, {0xffb6e000},
+ {0xffb70000}, {0xffb72000}, {0xffb74000}, {0xffb76000},
+ {0xffb78000}, {0xffb7a000}, {0xffb7c000}, {0xffb7e000},
+ {0xffb80000}, {0xffb82000}, {0xffb84000}, {0xffb86000},
+ {0xffb88000}, {0xffb8a000}, {0xffb8c000}, {0xffb8e000},
+ {0xffb90000}, {0xffb92000}, {0xffb94000}, {0xffb96000},
+ {0xffb98000}, {0xffb9a000}, {0xffb9c000}, {0xffb9e000},
+ {0xffba0000}, {0xffba2000}, {0xffba4000}, {0xffba6000},
+ {0xffba8000}, {0xffbaa000}, {0xffbac000}, {0xffbae000},
+ {0xffbb0000}, {0xffbb2000}, {0xffbb4000}, {0xffbb6000},
+ {0xffbb8000}, {0xffbba000}, {0xffbbc000}, {0xffbbe000},
+ {0xffbc0000}, {0xffbc2000}, {0xffbc4000}, {0xffbc6000},
+ {0xffbc8000}, {0xffbca000}, {0xffbcc000}, {0xffbce000},
+ {0xffbd0000}, {0xffbd2000}, {0xffbd4000}, {0xffbd6000},
+ {0xffbd8000}, {0xffbda000}, {0xffbdc000}, {0xffbde000},
+ {0xffbe0000}, {0xffbe2000}, {0xffbe4000}, {0xffbe6000},
+ {0xffbe8000}, {0xffbea000}, {0xffbec000}, {0xffbee000},
+ {0xffbf0000}, {0xffbf2000}, {0xffbf4000}, {0xffbf6000},
+ {0xffbf8000}, {0xffbfa000}, {0xffbfc000}, {0xffbfe000},
+ {0xffc00000}, {0xffc02000}, {0xffc04000}, {0xffc06000},
+ {0xffc08000}, {0xffc0a000}, {0xffc0c000}, {0xffc0e000},
+ {0xffc10000}, {0xffc12000}, {0xffc14000}, {0xffc16000},
+ {0xffc18000}, {0xffc1a000}, {0xffc1c000}, {0xffc1e000},
+ {0xffc20000}, {0xffc22000}, {0xffc24000}, {0xffc26000},
+ {0xffc28000}, {0xffc2a000}, {0xffc2c000}, {0xffc2e000},
+ {0xffc30000}, {0xffc32000}, {0xffc34000}, {0xffc36000},
+ {0xffc38000}, {0xffc3a000}, {0xffc3c000}, {0xffc3e000},
+ {0xffc40000}, {0xffc42000}, {0xffc44000}, {0xffc46000},
+ {0xffc48000}, {0xffc4a000}, {0xffc4c000}, {0xffc4e000},
+ {0xffc50000}, {0xffc52000}, {0xffc54000}, {0xffc56000},
+ {0xffc58000}, {0xffc5a000}, {0xffc5c000}, {0xffc5e000},
+ {0xffc60000}, {0xffc62000}, {0xffc64000}, {0xffc66000},
+ {0xffc68000}, {0xffc6a000}, {0xffc6c000}, {0xffc6e000},
+ {0xffc70000}, {0xffc72000}, {0xffc74000}, {0xffc76000},
+ {0xffc78000}, {0xffc7a000}, {0xffc7c000}, {0xffc7e000},
+ {0xffc80000}, {0xffc82000}, {0xffc84000}, {0xffc86000},
+ {0xffc88000}, {0xffc8a000}, {0xffc8c000}, {0xffc8e000},
+ {0xffc90000}, {0xffc92000}, {0xffc94000}, {0xffc96000},
+ {0xffc98000}, {0xffc9a000}, {0xffc9c000}, {0xffc9e000},
+ {0xffca0000}, {0xffca2000}, {0xffca4000}, {0xffca6000},
+ {0xffca8000}, {0xffcaa000}, {0xffcac000}, {0xffcae000},
+ {0xffcb0000}, {0xffcb2000}, {0xffcb4000}, {0xffcb6000},
+ {0xffcb8000}, {0xffcba000}, {0xffcbc000}, {0xffcbe000},
+ {0xffcc0000}, {0xffcc2000}, {0xffcc4000}, {0xffcc6000},
+ {0xffcc8000}, {0xffcca000}, {0xffccc000}, {0xffcce000},
+ {0xffcd0000}, {0xffcd2000}, {0xffcd4000}, {0xffcd6000},
+ {0xffcd8000}, {0xffcda000}, {0xffcdc000}, {0xffcde000},
+ {0xffce0000}, {0xffce2000}, {0xffce4000}, {0xffce6000},
+ {0xffce8000}, {0xffcea000}, {0xffcec000}, {0xffcee000},
+ {0xffcf0000}, {0xffcf2000}, {0xffcf4000}, {0xffcf6000},
+ {0xffcf8000}, {0xffcfa000}, {0xffcfc000}, {0xffcfe000},
+ {0xffd00000}, {0xffd02000}, {0xffd04000}, {0xffd06000},
+ {0xffd08000}, {0xffd0a000}, {0xffd0c000}, {0xffd0e000},
+ {0xffd10000}, {0xffd12000}, {0xffd14000}, {0xffd16000},
+ {0xffd18000}, {0xffd1a000}, {0xffd1c000}, {0xffd1e000},
+ {0xffd20000}, {0xffd22000}, {0xffd24000}, {0xffd26000},
+ {0xffd28000}, {0xffd2a000}, {0xffd2c000}, {0xffd2e000},
+ {0xffd30000}, {0xffd32000}, {0xffd34000}, {0xffd36000},
+ {0xffd38000}, {0xffd3a000}, {0xffd3c000}, {0xffd3e000},
+ {0xffd40000}, {0xffd42000}, {0xffd44000}, {0xffd46000},
+ {0xffd48000}, {0xffd4a000}, {0xffd4c000}, {0xffd4e000},
+ {0xffd50000}, {0xffd52000}, {0xffd54000}, {0xffd56000},
+ {0xffd58000}, {0xffd5a000}, {0xffd5c000}, {0xffd5e000},
+ {0xffd60000}, {0xffd62000}, {0xffd64000}, {0xffd66000},
+ {0xffd68000}, {0xffd6a000}, {0xffd6c000}, {0xffd6e000},
+ {0xffd70000}, {0xffd72000}, {0xffd74000}, {0xffd76000},
+ {0xffd78000}, {0xffd7a000}, {0xffd7c000}, {0xffd7e000},
+ {0xffd80000}, {0xffd82000}, {0xffd84000}, {0xffd86000},
+ {0xffd88000}, {0xffd8a000}, {0xffd8c000}, {0xffd8e000},
+ {0xffd90000}, {0xffd92000}, {0xffd94000}, {0xffd96000},
+ {0xffd98000}, {0xffd9a000}, {0xffd9c000}, {0xffd9e000},
+ {0xffda0000}, {0xffda2000}, {0xffda4000}, {0xffda6000},
+ {0xffda8000}, {0xffdaa000}, {0xffdac000}, {0xffdae000},
+ {0xffdb0000}, {0xffdb2000}, {0xffdb4000}, {0xffdb6000},
+ {0xffdb8000}, {0xffdba000}, {0xffdbc000}, {0xffdbe000},
+ {0xffdc0000}, {0xffdc2000}, {0xffdc4000}, {0xffdc6000},
+ {0xffdc8000}, {0xffdca000}, {0xffdcc000}, {0xffdce000},
+ {0xffdd0000}, {0xffdd2000}, {0xffdd4000}, {0xffdd6000},
+ {0xffdd8000}, {0xffdda000}, {0xffddc000}, {0xffdde000},
+ {0xffde0000}, {0xffde2000}, {0xffde4000}, {0xffde6000},
+ {0xffde8000}, {0xffdea000}, {0xffdec000}, {0xffdee000},
+ {0xffdf0000}, {0xffdf2000}, {0xffdf4000}, {0xffdf6000},
+ {0xffdf8000}, {0xffdfa000}, {0xffdfc000}, {0xffdfe000},
+ {0xffe00000}, {0xffe02000}, {0xffe04000}, {0xffe06000},
+ {0xffe08000}, {0xffe0a000}, {0xffe0c000}, {0xffe0e000},
+ {0xffe10000}, {0xffe12000}, {0xffe14000}, {0xffe16000},
+ {0xffe18000}, {0xffe1a000}, {0xffe1c000}, {0xffe1e000},
+ {0xffe20000}, {0xffe22000}, {0xffe24000}, {0xffe26000},
+ {0xffe28000}, {0xffe2a000}, {0xffe2c000}, {0xffe2e000},
+ {0xffe30000}, {0xffe32000}, {0xffe34000}, {0xffe36000},
+ {0xffe38000}, {0xffe3a000}, {0xffe3c000}, {0xffe3e000},
+ {0xffe40000}, {0xffe42000}, {0xffe44000}, {0xffe46000},
+ {0xffe48000}, {0xffe4a000}, {0xffe4c000}, {0xffe4e000},
+ {0xffe50000}, {0xffe52000}, {0xffe54000}, {0xffe56000},
+ {0xffe58000}, {0xffe5a000}, {0xffe5c000}, {0xffe5e000},
+ {0xffe60000}, {0xffe62000}, {0xffe64000}, {0xffe66000},
+ {0xffe68000}, {0xffe6a000}, {0xffe6c000}, {0xffe6e000},
+ {0xffe70000}, {0xffe72000}, {0xffe74000}, {0xffe76000},
+ {0xffe78000}, {0xffe7a000}, {0xffe7c000}, {0xffe7e000},
+ {0xffe80000}, {0xffe82000}, {0xffe84000}, {0xffe86000},
+ {0xffe88000}, {0xffe8a000}, {0xffe8c000}, {0xffe8e000},
+ {0xffe90000}, {0xffe92000}, {0xffe94000}, {0xffe96000},
+ {0xffe98000}, {0xffe9a000}, {0xffe9c000}, {0xffe9e000},
+ {0xffea0000}, {0xffea2000}, {0xffea4000}, {0xffea6000},
+ {0xffea8000}, {0xffeaa000}, {0xffeac000}, {0xffeae000},
+ {0xffeb0000}, {0xffeb2000}, {0xffeb4000}, {0xffeb6000},
+ {0xffeb8000}, {0xffeba000}, {0xffebc000}, {0xffebe000},
+ {0xffec0000}, {0xffec2000}, {0xffec4000}, {0xffec6000},
+ {0xffec8000}, {0xffeca000}, {0xffecc000}, {0xffece000},
+ {0xffed0000}, {0xffed2000}, {0xffed4000}, {0xffed6000},
+ {0xffed8000}, {0xffeda000}, {0xffedc000}, {0xffede000},
+ {0xffee0000}, {0xffee2000}, {0xffee4000}, {0xffee6000},
+ {0xffee8000}, {0xffeea000}, {0xffeec000}, {0xffeee000},
+ {0xffef0000}, {0xffef2000}, {0xffef4000}, {0xffef6000},
+ {0xffef8000}, {0xffefa000}, {0xffefc000}, {0xffefe000},
+ {0xfff00000}, {0xfff02000}, {0xfff04000}, {0xfff06000},
+ {0xfff08000}, {0xfff0a000}, {0xfff0c000}, {0xfff0e000},
+ {0xfff10000}, {0xfff12000}, {0xfff14000}, {0xfff16000},
+ {0xfff18000}, {0xfff1a000}, {0xfff1c000}, {0xfff1e000},
+ {0xfff20000}, {0xfff22000}, {0xfff24000}, {0xfff26000},
+ {0xfff28000}, {0xfff2a000}, {0xfff2c000}, {0xfff2e000},
+ {0xfff30000}, {0xfff32000}, {0xfff34000}, {0xfff36000},
+ {0xfff38000}, {0xfff3a000}, {0xfff3c000}, {0xfff3e000},
+ {0xfff40000}, {0xfff42000}, {0xfff44000}, {0xfff46000},
+ {0xfff48000}, {0xfff4a000}, {0xfff4c000}, {0xfff4e000},
+ {0xfff50000}, {0xfff52000}, {0xfff54000}, {0xfff56000},
+ {0xfff58000}, {0xfff5a000}, {0xfff5c000}, {0xfff5e000},
+ {0xfff60000}, {0xfff62000}, {0xfff64000}, {0xfff66000},
+ {0xfff68000}, {0xfff6a000}, {0xfff6c000}, {0xfff6e000},
+ {0xfff70000}, {0xfff72000}, {0xfff74000}, {0xfff76000},
+ {0xfff78000}, {0xfff7a000}, {0xfff7c000}, {0xfff7e000},
+ {0xfff80000}, {0xfff82000}, {0xfff84000}, {0xfff86000},
+ {0xfff88000}, {0xfff8a000}, {0xfff8c000}, {0xfff8e000},
+ {0xfff90000}, {0xfff92000}, {0xfff94000}, {0xfff96000},
+ {0xfff98000}, {0xfff9a000}, {0xfff9c000}, {0xfff9e000},
+ {0xfffa0000}, {0xfffa2000}, {0xfffa4000}, {0xfffa6000},
+ {0xfffa8000}, {0xfffaa000}, {0xfffac000}, {0xfffae000},
+ {0xfffb0000}, {0xfffb2000}, {0xfffb4000}, {0xfffb6000},
+ {0xfffb8000}, {0xfffba000}, {0xfffbc000}, {0xfffbe000},
+ {0xfffc0000}, {0xfffc2000}, {0xfffc4000}, {0xfffc6000},
+ {0xfffc8000}, {0xfffca000}, {0xfffcc000}, {0xfffce000},
+ {0xfffd0000}, {0xfffd2000}, {0xfffd4000}, {0xfffd6000},
+ {0xfffd8000}, {0xfffda000}, {0xfffdc000}, {0xfffde000},
+ {0xfffe0000}, {0xfffe2000}, {0xfffe4000}, {0xfffe6000},
+ {0xfffe8000}, {0xfffea000}, {0xfffec000}, {0xfffee000},
+ {0xffff0000}, {0xffff2000}, {0xffff4000}, {0xffff6000},
+ {0xffff8000}, {0xffffa000}, {0xffffc000}, {0xffffe000},
+};
diff --git a/Source/OpenEXR/Iex/Iex.h b/Source/OpenEXR/Iex/Iex.h
new file mode 100644
index 0000000..a0fd31d
--- /dev/null
+++ b/Source/OpenEXR/Iex/Iex.h
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEX_H
+#define INCLUDED_IEX_H
+
+
+//--------------------------------
+//
+// Exception handling
+//
+//--------------------------------
+
+
+#include "IexMacros.h"
+#include "IexBaseExc.h"
+#include "IexMathExc.h"
+#include "IexThrowErrnoExc.h"
+
+// Note that we do not include file IexErrnoExc.h here. That file
+// defines over 150 classes and significantly slows down compilation.
+// If you throw ErrnoExc exceptions using the throwErrnoExc() function,
+// you don't need IexErrnoExc.h. You have to include IexErrnoExc.h
+// only if you want to catch specific subclasses of ErrnoExc.
+
+
+#endif
diff --git a/Source/OpenEXR/Iex/IexBaseExc.cpp b/Source/OpenEXR/Iex/IexBaseExc.cpp
new file mode 100644
index 0000000..c85b0c2
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexBaseExc.cpp
@@ -0,0 +1,129 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//---------------------------------------------------------------------
+//
+// Constructors and destructors for our exception base class.
+//
+//---------------------------------------------------------------------
+
+#include "IexBaseExc.h"
+
+namespace Iex {
+namespace {
+
+
+StackTracer currentStackTracer = 0;
+
+
+} // namespace
+
+
+void
+setStackTracer (StackTracer stackTracer)
+{
+ currentStackTracer = stackTracer;
+}
+
+
+StackTracer
+stackTracer ()
+{
+ return currentStackTracer;
+}
+
+
+BaseExc::BaseExc (const char* s) throw () :
+ std::string (s? s: ""),
+ _stackTrace (currentStackTracer? currentStackTracer(): "")
+{
+ // empty
+}
+
+
+BaseExc::BaseExc (const std::string &s) throw () :
+ std::string (s),
+ _stackTrace (currentStackTracer? currentStackTracer(): "")
+{
+ // empty
+}
+
+
+BaseExc::BaseExc (std::stringstream &s) throw () :
+ std::string (s.str()),
+ _stackTrace (currentStackTracer? currentStackTracer(): "")
+{
+ // empty
+}
+
+
+BaseExc::BaseExc (const BaseExc &be) throw () :
+ std::string (be),
+ _stackTrace (be._stackTrace)
+{
+ // empty
+}
+
+
+BaseExc::~BaseExc () throw ()
+{
+ // empty
+}
+
+
+const char *
+BaseExc::what () const throw ()
+{
+ return c_str();
+}
+
+
+BaseExc &
+BaseExc::assign (std::stringstream &s)
+{
+ std::string::assign (s.str());
+ return *this;
+}
+
+BaseExc &
+BaseExc::append (std::stringstream &s)
+{
+ std::string::append (s.str());
+ return *this;
+}
+
+
+} // namespace Iex
diff --git a/Source/OpenEXR/Iex/IexBaseExc.h b/Source/OpenEXR/Iex/IexBaseExc.h
new file mode 100644
index 0000000..9d8ab24
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexBaseExc.h
@@ -0,0 +1,266 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEXBASEEXC_H
+#define INCLUDED_IEXBASEEXC_H
+
+
+//----------------------------------------------------------
+//
+// A general exception base class, and a few
+// useful exceptions derived from the base class.
+//
+//----------------------------------------------------------
+
+#include <string>
+#include <exception>
+#include <sstream>
+
+namespace Iex {
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// Tell MS VC++ to suppress exception specification warnings
+#pragma warning(disable:4290)
+#endif
+
+//-------------------------------
+// Our most basic exception class
+//-------------------------------
+
+class BaseExc: public std::string, public std::exception
+{
+ public:
+
+ //----------------------------
+ // Constructors and destructor
+ //----------------------------
+
+ BaseExc (const char *s = 0) throw(); // std::string (s)
+ BaseExc (const std::string &s) throw(); // std::string (s)
+ BaseExc (std::stringstream &s) throw(); // std::string (s.str())
+
+ BaseExc (const BaseExc &be) throw();
+ virtual ~BaseExc () throw ();
+
+ //--------------------------------------------
+ // what() method -- e.what() returns e.c_str()
+ //--------------------------------------------
+
+ virtual const char * what () const throw ();
+
+
+ //--------------------------------------------------
+ // Convenient methods to change the exception's text
+ //--------------------------------------------------
+
+ BaseExc & assign (std::stringstream &s); // assign (s.str())
+ BaseExc & operator = (std::stringstream &s);
+
+ BaseExc & append (std::stringstream &s); // append (s.str())
+ BaseExc & operator += (std::stringstream &s);
+
+
+ //--------------------------------------------------
+ // These methods from the base class get obscured by
+ // the definitions above.
+ //--------------------------------------------------
+
+ BaseExc & assign (const char *s);
+ BaseExc & operator = (const char *s);
+
+ BaseExc & append (const char *s);
+ BaseExc & operator += (const char *s);
+
+
+ //--------------------------------------------------
+ // Stack trace for the point at which the exception
+ // was thrown. The stack trace will be an empty
+ // string unless a working stack-tracing routine
+ // has been installed (see below, setStackTracer()).
+ //--------------------------------------------------
+
+ const std::string & stackTrace () const;
+
+ private:
+
+ std::string _stackTrace;
+};
+
+
+//-----------------------------------------------------
+// A macro to save typing when declararing an exception
+// class derived directly or indirectly from BaseExc:
+//-----------------------------------------------------
+
+#define DEFINE_EXC(name, base) \
+ class name: public base \
+ { \
+ public: \
+ name (const char* text=0) throw(): base (text) {} \
+ name (const std::string &text) throw(): base (text) {} \
+ name (std::stringstream &text) throw(): base (text) {} \
+ };
+
+
+//--------------------------------------------------------
+// Some exceptions which should be useful in most programs
+//--------------------------------------------------------
+
+DEFINE_EXC (ArgExc, BaseExc) // Invalid arguments to a function call
+
+DEFINE_EXC (LogicExc, BaseExc) // General error in a program's logic,
+ // for example, a function was called
+ // in a context where the call does
+ // not make sense.
+
+DEFINE_EXC (InputExc, BaseExc) // Invalid input data, e.g. from a file
+
+DEFINE_EXC (IoExc, BaseExc) // Input or output operation failed
+
+DEFINE_EXC (MathExc, BaseExc) // Arithmetic exception; more specific
+ // exceptions derived from this class
+ // are defined in ExcMath.h
+
+DEFINE_EXC (ErrnoExc, BaseExc) // Base class for exceptions corresponding
+ // to errno values (see errno.h); more
+ // specific exceptions derived from this
+ // class are defined in ExcErrno.h
+
+DEFINE_EXC (NoImplExc, BaseExc) // Missing method exception e.g. from a
+ // call to a method that is only partially
+ // or not at all implemented. A reminder
+ // to lazy software people to get back
+ // to work.
+
+DEFINE_EXC (NullExc, BaseExc) // A pointer is inappropriately null.
+
+DEFINE_EXC (TypeExc, BaseExc) // An object is an inappropriate type,
+ // i.e. a dynamnic_cast failed.
+
+
+//----------------------------------------------------------------------
+// Stack-tracing support:
+//
+// setStackTracer(st)
+//
+// installs a stack-tracing routine, st, which will be called from
+// class BaseExc's constructor every time an exception derived from
+// BaseExc is thrown. The stack-tracing routine should return a
+// string that contains a printable representation of the program's
+// current call stack. This string will be stored in the BaseExc
+// object; the string is accesible via the BaseExc::stackTrace()
+// method.
+//
+// setStackTracer(0)
+//
+// removes the current stack tracing routine. When an exception
+// derived from BaseExc is thrown, the stack trace string stored
+// in the BaseExc object will be empty.
+//
+// stackTracer()
+//
+// returns a pointer to the current stack-tracing routine, or 0
+// if there is no current stack stack-tracing routine.
+//
+//----------------------------------------------------------------------
+
+typedef std::string (* StackTracer) ();
+
+void setStackTracer (StackTracer stackTracer);
+StackTracer stackTracer ();
+
+
+//-----------------
+// Inline functions
+//-----------------
+
+inline BaseExc &
+BaseExc::operator = (std::stringstream &s)
+{
+ return assign (s);
+}
+
+
+inline BaseExc &
+BaseExc::operator += (std::stringstream &s)
+{
+ return append (s);
+}
+
+
+inline BaseExc &
+BaseExc::assign (const char *s)
+{
+ std::string::assign(s);
+ return *this;
+}
+
+
+inline BaseExc &
+BaseExc::operator = (const char *s)
+{
+ return assign(s);
+}
+
+
+inline BaseExc &
+BaseExc::append (const char *s)
+{
+ std::string::append(s);
+ return *this;
+}
+
+
+inline BaseExc &
+BaseExc::operator += (const char *s)
+{
+ return append(s);
+}
+
+
+inline const std::string &
+BaseExc::stackTrace () const
+{
+ return _stackTrace;
+}
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(default:4290)
+#endif
+
+} // namespace Iex
+
+#endif
diff --git a/Source/OpenEXR/Iex/IexErrnoExc.h b/Source/OpenEXR/Iex/IexErrnoExc.h
new file mode 100644
index 0000000..53cc28f
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexErrnoExc.h
@@ -0,0 +1,210 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEXERRNOEXC_H
+#define INCLUDED_IEXERRNOEXC_H
+
+//----------------------------------------------------------------
+//
+// Exceptions which correspond to "errno" error codes.
+//
+//----------------------------------------------------------------
+
+#include "IexBaseExc.h"
+
+namespace Iex {
+
+
+DEFINE_EXC (EpermExc, ErrnoExc)
+DEFINE_EXC (EnoentExc, ErrnoExc)
+DEFINE_EXC (EsrchExc, ErrnoExc)
+DEFINE_EXC (EintrExc, ErrnoExc)
+DEFINE_EXC (EioExc, ErrnoExc)
+DEFINE_EXC (EnxioExc, ErrnoExc)
+DEFINE_EXC (E2bigExc, ErrnoExc)
+DEFINE_EXC (EnoexecExc, ErrnoExc)
+DEFINE_EXC (EbadfExc, ErrnoExc)
+DEFINE_EXC (EchildExc, ErrnoExc)
+DEFINE_EXC (EagainExc, ErrnoExc)
+DEFINE_EXC (EnomemExc, ErrnoExc)
+DEFINE_EXC (EaccesExc, ErrnoExc)
+DEFINE_EXC (EfaultExc, ErrnoExc)
+DEFINE_EXC (EnotblkExc, ErrnoExc)
+DEFINE_EXC (EbusyExc, ErrnoExc)
+DEFINE_EXC (EexistExc, ErrnoExc)
+DEFINE_EXC (ExdevExc, ErrnoExc)
+DEFINE_EXC (EnodevExc, ErrnoExc)
+DEFINE_EXC (EnotdirExc, ErrnoExc)
+DEFINE_EXC (EisdirExc, ErrnoExc)
+DEFINE_EXC (EinvalExc, ErrnoExc)
+DEFINE_EXC (EnfileExc, ErrnoExc)
+DEFINE_EXC (EmfileExc, ErrnoExc)
+DEFINE_EXC (EnottyExc, ErrnoExc)
+DEFINE_EXC (EtxtbsyExc, ErrnoExc)
+DEFINE_EXC (EfbigExc, ErrnoExc)
+DEFINE_EXC (EnospcExc, ErrnoExc)
+DEFINE_EXC (EspipeExc, ErrnoExc)
+DEFINE_EXC (ErofsExc, ErrnoExc)
+DEFINE_EXC (EmlinkExc, ErrnoExc)
+DEFINE_EXC (EpipeExc, ErrnoExc)
+DEFINE_EXC (EdomExc, ErrnoExc)
+DEFINE_EXC (ErangeExc, ErrnoExc)
+DEFINE_EXC (EnomsgExc, ErrnoExc)
+DEFINE_EXC (EidrmExc, ErrnoExc)
+DEFINE_EXC (EchrngExc, ErrnoExc)
+DEFINE_EXC (El2nsyncExc, ErrnoExc)
+DEFINE_EXC (El3hltExc, ErrnoExc)
+DEFINE_EXC (El3rstExc, ErrnoExc)
+DEFINE_EXC (ElnrngExc, ErrnoExc)
+DEFINE_EXC (EunatchExc, ErrnoExc)
+DEFINE_EXC (EnocsiExc, ErrnoExc)
+DEFINE_EXC (El2hltExc, ErrnoExc)
+DEFINE_EXC (EdeadlkExc, ErrnoExc)
+DEFINE_EXC (EnolckExc, ErrnoExc)
+DEFINE_EXC (EbadeExc, ErrnoExc)
+DEFINE_EXC (EbadrExc, ErrnoExc)
+DEFINE_EXC (ExfullExc, ErrnoExc)
+DEFINE_EXC (EnoanoExc, ErrnoExc)
+DEFINE_EXC (EbadrqcExc, ErrnoExc)
+DEFINE_EXC (EbadsltExc, ErrnoExc)
+DEFINE_EXC (EdeadlockExc, ErrnoExc)
+DEFINE_EXC (EbfontExc, ErrnoExc)
+DEFINE_EXC (EnostrExc, ErrnoExc)
+DEFINE_EXC (EnodataExc, ErrnoExc)
+DEFINE_EXC (EtimeExc, ErrnoExc)
+DEFINE_EXC (EnosrExc, ErrnoExc)
+DEFINE_EXC (EnonetExc, ErrnoExc)
+DEFINE_EXC (EnopkgExc, ErrnoExc)
+DEFINE_EXC (EremoteExc, ErrnoExc)
+DEFINE_EXC (EnolinkExc, ErrnoExc)
+DEFINE_EXC (EadvExc, ErrnoExc)
+DEFINE_EXC (EsrmntExc, ErrnoExc)
+DEFINE_EXC (EcommExc, ErrnoExc)
+DEFINE_EXC (EprotoExc, ErrnoExc)
+DEFINE_EXC (EmultihopExc, ErrnoExc)
+DEFINE_EXC (EbadmsgExc, ErrnoExc)
+DEFINE_EXC (EnametoolongExc, ErrnoExc)
+DEFINE_EXC (EoverflowExc, ErrnoExc)
+DEFINE_EXC (EnotuniqExc, ErrnoExc)
+DEFINE_EXC (EbadfdExc, ErrnoExc)
+DEFINE_EXC (EremchgExc, ErrnoExc)
+DEFINE_EXC (ElibaccExc, ErrnoExc)
+DEFINE_EXC (ElibbadExc, ErrnoExc)
+DEFINE_EXC (ElibscnExc, ErrnoExc)
+DEFINE_EXC (ElibmaxExc, ErrnoExc)
+DEFINE_EXC (ElibexecExc, ErrnoExc)
+DEFINE_EXC (EilseqExc, ErrnoExc)
+DEFINE_EXC (EnosysExc, ErrnoExc)
+DEFINE_EXC (EloopExc, ErrnoExc)
+DEFINE_EXC (ErestartExc, ErrnoExc)
+DEFINE_EXC (EstrpipeExc, ErrnoExc)
+DEFINE_EXC (EnotemptyExc, ErrnoExc)
+DEFINE_EXC (EusersExc, ErrnoExc)
+DEFINE_EXC (EnotsockExc, ErrnoExc)
+DEFINE_EXC (EdestaddrreqExc, ErrnoExc)
+DEFINE_EXC (EmsgsizeExc, ErrnoExc)
+DEFINE_EXC (EprototypeExc, ErrnoExc)
+DEFINE_EXC (EnoprotooptExc, ErrnoExc)
+DEFINE_EXC (EprotonosupportExc, ErrnoExc)
+DEFINE_EXC (EsocktnosupportExc, ErrnoExc)
+DEFINE_EXC (EopnotsuppExc, ErrnoExc)
+DEFINE_EXC (EpfnosupportExc, ErrnoExc)
+DEFINE_EXC (EafnosupportExc, ErrnoExc)
+DEFINE_EXC (EaddrinuseExc, ErrnoExc)
+DEFINE_EXC (EaddrnotavailExc, ErrnoExc)
+DEFINE_EXC (EnetdownExc, ErrnoExc)
+DEFINE_EXC (EnetunreachExc, ErrnoExc)
+DEFINE_EXC (EnetresetExc, ErrnoExc)
+DEFINE_EXC (EconnabortedExc, ErrnoExc)
+DEFINE_EXC (EconnresetExc, ErrnoExc)
+DEFINE_EXC (EnobufsExc, ErrnoExc)
+DEFINE_EXC (EisconnExc, ErrnoExc)
+DEFINE_EXC (EnotconnExc, ErrnoExc)
+DEFINE_EXC (EshutdownExc, ErrnoExc)
+DEFINE_EXC (EtoomanyrefsExc, ErrnoExc)
+DEFINE_EXC (EtimedoutExc, ErrnoExc)
+DEFINE_EXC (EconnrefusedExc, ErrnoExc)
+DEFINE_EXC (EhostdownExc, ErrnoExc)
+DEFINE_EXC (EhostunreachExc, ErrnoExc)
+DEFINE_EXC (EalreadyExc, ErrnoExc)
+DEFINE_EXC (EinprogressExc, ErrnoExc)
+DEFINE_EXC (EstaleExc, ErrnoExc)
+DEFINE_EXC (EioresidExc, ErrnoExc)
+DEFINE_EXC (EucleanExc, ErrnoExc)
+DEFINE_EXC (EnotnamExc, ErrnoExc)
+DEFINE_EXC (EnavailExc, ErrnoExc)
+DEFINE_EXC (EisnamExc, ErrnoExc)
+DEFINE_EXC (EremoteioExc, ErrnoExc)
+DEFINE_EXC (EinitExc, ErrnoExc)
+DEFINE_EXC (EremdevExc, ErrnoExc)
+DEFINE_EXC (EcanceledExc, ErrnoExc)
+DEFINE_EXC (EnolimfileExc, ErrnoExc)
+DEFINE_EXC (EproclimExc, ErrnoExc)
+DEFINE_EXC (EdisjointExc, ErrnoExc)
+DEFINE_EXC (EnologinExc, ErrnoExc)
+DEFINE_EXC (EloginlimExc, ErrnoExc)
+DEFINE_EXC (EgrouploopExc, ErrnoExc)
+DEFINE_EXC (EnoattachExc, ErrnoExc)
+DEFINE_EXC (EnotsupExc, ErrnoExc)
+DEFINE_EXC (EnoattrExc, ErrnoExc)
+DEFINE_EXC (EdircorruptedExc, ErrnoExc)
+DEFINE_EXC (EdquotExc, ErrnoExc)
+DEFINE_EXC (EnfsremoteExc, ErrnoExc)
+DEFINE_EXC (EcontrollerExc, ErrnoExc)
+DEFINE_EXC (EnotcontrollerExc, ErrnoExc)
+DEFINE_EXC (EenqueuedExc, ErrnoExc)
+DEFINE_EXC (EnotenqueuedExc, ErrnoExc)
+DEFINE_EXC (EjoinedExc, ErrnoExc)
+DEFINE_EXC (EnotjoinedExc, ErrnoExc)
+DEFINE_EXC (EnoprocExc, ErrnoExc)
+DEFINE_EXC (EmustrunExc, ErrnoExc)
+DEFINE_EXC (EnotstoppedExc, ErrnoExc)
+DEFINE_EXC (EclockcpuExc, ErrnoExc)
+DEFINE_EXC (EinvalstateExc, ErrnoExc)
+DEFINE_EXC (EnoexistExc, ErrnoExc)
+DEFINE_EXC (EendofminorExc, ErrnoExc)
+DEFINE_EXC (EbufsizeExc, ErrnoExc)
+DEFINE_EXC (EemptyExc, ErrnoExc)
+DEFINE_EXC (EnointrgroupExc, ErrnoExc)
+DEFINE_EXC (EinvalmodeExc, ErrnoExc)
+DEFINE_EXC (EcantextentExc, ErrnoExc)
+DEFINE_EXC (EinvaltimeExc, ErrnoExc)
+DEFINE_EXC (EdestroyedExc, ErrnoExc)
+
+
+} // namespace Iex
+
+#endif
diff --git a/Source/OpenEXR/Iex/IexMacros.h b/Source/OpenEXR/Iex/IexMacros.h
new file mode 100644
index 0000000..4c715c3
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexMacros.h
@@ -0,0 +1,148 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEXMACROS_H
+#define INCLUDED_IEXMACROS_H
+
+//--------------------------------------------------------------------
+//
+// Macros which make throwing exceptions more convenient
+//
+//--------------------------------------------------------------------
+
+#include <sstream>
+
+
+//----------------------------------------------------------------------------
+// A macro to throw exceptions whose text is assembled using stringstreams.
+//
+// Example:
+//
+// THROW (InputExc, "Syntax error in line " << line ", " << file << ".");
+//
+//----------------------------------------------------------------------------
+
+#define THROW(type, text) \
+ do \
+ { \
+ std::stringstream s; \
+ s << text; \
+ throw type (s); \
+ } \
+ while (0)
+
+
+//----------------------------------------------------------------------------
+// Macros to add to or to replace the text of an exception.
+// The new text is assembled using stringstreams.
+//
+// Examples:
+//
+// Append to end of an exception's text:
+//
+// catch (BaseExc &e)
+// {
+// APPEND_EXC (e, " Directory " << name << " does not exist.");
+// throw;
+// }
+//
+// Replace an exception's text:
+//
+// catch (BaseExc &e)
+// {
+// REPLACE_EXC (e, "Directory " << name << " does not exist. " << e);
+// throw;
+// }
+//----------------------------------------------------------------------------
+
+#define APPEND_EXC(exc, text) \
+ do \
+ { \
+ std::stringstream s; \
+ s << text; \
+ exc.append (s); \
+ } \
+ while (0)
+
+#define REPLACE_EXC(exc, text) \
+ do \
+ { \
+ std::stringstream s; \
+ s << text; \
+ exc.assign (s); \
+ } \
+ while (0)
+
+
+//-------------------------------------------------------------
+// A macro to throw ErrnoExc exceptions whose text is assembled
+// using stringstreams:
+//
+// Example:
+//
+// THROW_ERRNO ("Cannot open file " << name << " (%T).");
+//
+//-------------------------------------------------------------
+
+#define THROW_ERRNO(text) \
+ do \
+ { \
+ std::stringstream s; \
+ s << text; \
+ ::Iex::throwErrnoExc (s.str()); \
+ } \
+ while (0)
+
+
+//-------------------------------------------------------------
+// A macro to throw exceptions if an assertion is false.
+//
+// Example:
+//
+// ASSERT (NullExc, ptr != NULL, "Null pointer" );
+//
+//-------------------------------------------------------------
+
+#define ASSERT(assertion, type, text) \
+ do \
+ { \
+ if( (assertion) == false ) \
+ THROW( type, text ); \
+ } \
+ while (0)
+
+
+#endif
diff --git a/Source/OpenEXR/Iex/IexMathExc.h b/Source/OpenEXR/Iex/IexMathExc.h
new file mode 100644
index 0000000..4ef90d3
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexMathExc.h
@@ -0,0 +1,58 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEXMATHEXC_H
+#define INCLUDED_IEXMATHEXC_H
+
+#include "IexBaseExc.h"
+
+namespace Iex {
+
+//---------------------------------------------------------
+// Exception classess which correspond to specific floating
+// point exceptions.
+//---------------------------------------------------------
+
+DEFINE_EXC (OverflowExc, MathExc) // Overflow
+DEFINE_EXC (UnderflowExc, MathExc) // Underflow
+DEFINE_EXC (DivzeroExc, MathExc) // Division by zero
+DEFINE_EXC (InexactExc, MathExc) // Inexact result
+DEFINE_EXC (InvalidFpOpExc, MathExc) // Invalid operation
+
+
+} // namespace Iex
+
+#endif
diff --git a/Source/OpenEXR/Iex/IexThrowErrnoExc.cpp b/Source/OpenEXR/Iex/IexThrowErrnoExc.cpp
new file mode 100644
index 0000000..fea5eac
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexThrowErrnoExc.cpp
@@ -0,0 +1,859 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//----------------------------------------------------------------
+//
+// Exceptions that correspond to "errno" error codes,
+// and a function to make throwing those exceptions easy.
+//
+//----------------------------------------------------------------
+
+#include "IexThrowErrnoExc.h"
+#include "IexErrnoExc.h"
+#include <string.h>
+#include <errno.h>
+
+namespace Iex {
+
+
+void throwErrnoExc (const std::string &text, int errnum)
+{
+ const char *entext = strerror (errnum);
+ std::string tmp (text);
+ int pos;
+
+ while (-1 != (pos = tmp.find ("%T")))
+ tmp.replace (pos, 2, entext, strlen (entext));
+
+ switch (errnum)
+ {
+ #if defined (EPERM)
+ case EPERM:
+ throw EpermExc (tmp);
+ #endif
+
+ #if defined (ENOENT)
+ case ENOENT:
+ throw EnoentExc (tmp);
+ #endif
+
+ #if defined (ESRCH)
+ case ESRCH:
+ throw EsrchExc (tmp);
+ #endif
+
+ #if defined (EINTR)
+ case EINTR:
+ throw EintrExc (tmp);
+ #endif
+
+ #if defined (EIO)
+ case EIO:
+ throw EioExc (tmp);
+ #endif
+
+ #if defined (ENXIO)
+ case ENXIO:
+ throw EnxioExc (tmp);
+ #endif
+
+ #if defined (E2BIG)
+ case E2BIG:
+ throw E2bigExc (tmp);
+ #endif
+
+ #if defined (ENOEXEC)
+ case ENOEXEC:
+ throw EnoexecExc (tmp);
+ #endif
+
+ #if defined (EBADF)
+ case EBADF:
+ throw EbadfExc (tmp);
+ #endif
+
+ #if defined (ECHILD)
+ case ECHILD:
+ throw EchildExc (tmp);
+ #endif
+
+ #if defined (EAGAIN)
+ case EAGAIN:
+ throw EagainExc (tmp);
+ #endif
+
+ #if defined (ENOMEM)
+ case ENOMEM:
+ throw EnomemExc (tmp);
+ #endif
+
+ #if defined (EACCES)
+ case EACCES:
+ throw EaccesExc (tmp);
+ #endif
+
+ #if defined (EFAULT)
+ case EFAULT:
+ throw EfaultExc (tmp);
+ #endif
+
+ #if defined (ENOTBLK)
+ case ENOTBLK:
+ throw EnotblkExc (tmp);
+ #endif
+
+ #if defined (EBUSY)
+ case EBUSY:
+ throw EbusyExc (tmp);
+ #endif
+
+ #if defined (EEXIST)
+ case EEXIST:
+ throw EexistExc (tmp);
+ #endif
+
+ #if defined (EXDEV)
+ case EXDEV:
+ throw ExdevExc (tmp);
+ #endif
+
+ #if defined (ENODEV)
+ case ENODEV:
+ throw EnodevExc (tmp);
+ #endif
+
+ #if defined (ENOTDIR)
+ case ENOTDIR:
+ throw EnotdirExc (tmp);
+ #endif
+
+ #if defined (EISDIR)
+ case EISDIR:
+ throw EisdirExc (tmp);
+ #endif
+
+ #if defined (EINVAL)
+ case EINVAL:
+ throw EinvalExc (tmp);
+ #endif
+
+ #if defined (ENFILE)
+ case ENFILE:
+ throw EnfileExc (tmp);
+ #endif
+
+ #if defined (EMFILE)
+ case EMFILE:
+ throw EmfileExc (tmp);
+ #endif
+
+ #if defined (ENOTTY)
+ case ENOTTY:
+ throw EnottyExc (tmp);
+ #endif
+
+ #if defined (ETXTBSY)
+ case ETXTBSY:
+ throw EtxtbsyExc (tmp);
+ #endif
+
+ #if defined (EFBIG)
+ case EFBIG:
+ throw EfbigExc (tmp);
+ #endif
+
+ #if defined (ENOSPC)
+ case ENOSPC:
+ throw EnospcExc (tmp);
+ #endif
+
+ #if defined (ESPIPE)
+ case ESPIPE:
+ throw EspipeExc (tmp);
+ #endif
+
+ #if defined (EROFS)
+ case EROFS:
+ throw ErofsExc (tmp);
+ #endif
+
+ #if defined (EMLINK)
+ case EMLINK:
+ throw EmlinkExc (tmp);
+ #endif
+
+ #if defined (EPIPE)
+ case EPIPE:
+ throw EpipeExc (tmp);
+ #endif
+
+ #if defined (EDOM)
+ case EDOM:
+ throw EdomExc (tmp);
+ #endif
+
+ #if defined (ERANGE)
+ case ERANGE:
+ throw ErangeExc (tmp);
+ #endif
+
+ #if defined (ENOMSG)
+ case ENOMSG:
+ throw EnomsgExc (tmp);
+ #endif
+
+ #if defined (EIDRM)
+ case EIDRM:
+ throw EidrmExc (tmp);
+ #endif
+
+ #if defined (ECHRNG)
+ case ECHRNG:
+ throw EchrngExc (tmp);
+ #endif
+
+ #if defined (EL2NSYNC)
+ case EL2NSYNC:
+ throw El2nsyncExc (tmp);
+ #endif
+
+ #if defined (EL3HLT)
+ case EL3HLT:
+ throw El3hltExc (tmp);
+ #endif
+
+ #if defined (EL3RST)
+ case EL3RST:
+ throw El3rstExc (tmp);
+ #endif
+
+ #if defined (ELNRNG)
+ case ELNRNG:
+ throw ElnrngExc (tmp);
+ #endif
+
+ #if defined (EUNATCH)
+ case EUNATCH:
+ throw EunatchExc (tmp);
+ #endif
+
+ #if defined (ENOSCI)
+ case ENOCSI:
+ throw EnocsiExc (tmp);
+ #endif
+
+ #if defined (EL2HLT)
+ case EL2HLT:
+ throw El2hltExc (tmp);
+ #endif
+
+ #if defined (EDEADLK)
+ case EDEADLK:
+ throw EdeadlkExc (tmp);
+ #endif
+
+ #if defined (ENOLCK)
+ case ENOLCK:
+ throw EnolckExc (tmp);
+ #endif
+
+ #if defined (EBADE)
+ case EBADE:
+ throw EbadeExc (tmp);
+ #endif
+
+ #if defined (EBADR)
+ case EBADR:
+ throw EbadrExc (tmp);
+ #endif
+
+ #if defined (EXFULL)
+ case EXFULL:
+ throw ExfullExc (tmp);
+ #endif
+
+ #if defined (ENOANO)
+ case ENOANO:
+ throw EnoanoExc (tmp);
+ #endif
+
+ #if defined (EBADRQC)
+ case EBADRQC:
+ throw EbadrqcExc (tmp);
+ #endif
+
+ #if defined (EBADSLT)
+ case EBADSLT:
+ throw EbadsltExc (tmp);
+ #endif
+
+ #if defined (EDEADLOCK) && defined (EDEADLK)
+ #if EDEADLOCK != EDEADLK
+ case EDEADLOCK:
+ throw EdeadlockExc (tmp);
+ #endif
+ #elif defined (EDEADLOCK)
+ case EDEADLOCK:
+ throw EdeadlockExc (tmp);
+ #endif
+
+ #if defined (EBFONT)
+ case EBFONT:
+ throw EbfontExc (tmp);
+ #endif
+
+ #if defined (ENOSTR)
+ case ENOSTR:
+ throw EnostrExc (tmp);
+ #endif
+
+ #if defined (ENODATA)
+ case ENODATA:
+ throw EnodataExc (tmp);
+ #endif
+
+ #if defined (ETIME)
+ case ETIME:
+ throw EtimeExc (tmp);
+ #endif
+
+ #if defined (ENOSR)
+ case ENOSR:
+ throw EnosrExc (tmp);
+ #endif
+
+ #if defined (ENONET)
+ case ENONET:
+ throw EnonetExc (tmp);
+ #endif
+
+ #if defined (ENOPKG)
+ case ENOPKG:
+ throw EnopkgExc (tmp);
+ #endif
+
+ #if defined (EREMOTE)
+ case EREMOTE:
+ throw EremoteExc (tmp);
+ #endif
+
+ #if defined (ENOLINK)
+ case ENOLINK:
+ throw EnolinkExc (tmp);
+ #endif
+
+ #if defined (EADV)
+ case EADV:
+ throw EadvExc (tmp);
+ #endif
+
+ #if defined (ESRMNT)
+ case ESRMNT:
+ throw EsrmntExc (tmp);
+ #endif
+
+ #if defined (ECOMM)
+ case ECOMM:
+ throw EcommExc (tmp);
+ #endif
+
+ #if defined (EPROTO)
+ case EPROTO:
+ throw EprotoExc (tmp);
+ #endif
+
+ #if defined (EMULTIHOP)
+ case EMULTIHOP:
+ throw EmultihopExc (tmp);
+ #endif
+
+ #if defined (EBADMSG)
+ case EBADMSG:
+ throw EbadmsgExc (tmp);
+ #endif
+
+ #if defined (ENAMETOOLONG)
+ case ENAMETOOLONG:
+ throw EnametoolongExc (tmp);
+ #endif
+
+ #if defined (EOVERFLOW)
+ case EOVERFLOW:
+ throw EoverflowExc (tmp);
+ #endif
+
+ #if defined (ENOTUNIQ)
+ case ENOTUNIQ:
+ throw EnotuniqExc (tmp);
+ #endif
+
+ #if defined (EBADFD)
+ case EBADFD:
+ throw EbadfdExc (tmp);
+ #endif
+
+ #if defined (EREMCHG)
+ case EREMCHG:
+ throw EremchgExc (tmp);
+ #endif
+
+ #if defined (ELIBACC)
+ case ELIBACC:
+ throw ElibaccExc (tmp);
+ #endif
+
+ #if defined (ELIBBAD)
+ case ELIBBAD:
+ throw ElibbadExc (tmp);
+ #endif
+
+ #if defined (ELIBSCN)
+ case ELIBSCN:
+ throw ElibscnExc (tmp);
+ #endif
+
+ #if defined (ELIBMAX)
+ case ELIBMAX:
+ throw ElibmaxExc (tmp);
+ #endif
+
+ #if defined (ELIBEXEC)
+ case ELIBEXEC:
+ throw ElibexecExc (tmp);
+ #endif
+
+ #if defined (EILSEQ)
+ case EILSEQ:
+ throw EilseqExc (tmp);
+ #endif
+
+ #if defined (ENOSYS)
+ case ENOSYS:
+ throw EnosysExc (tmp);
+ #endif
+
+ #if defined (ELOOP)
+ case ELOOP:
+ throw EloopExc (tmp);
+ #endif
+
+ #if defined (ERESTART)
+ case ERESTART:
+ throw ErestartExc (tmp);
+ #endif
+
+ #if defined (ESTRPIPE)
+ case ESTRPIPE:
+ throw EstrpipeExc (tmp);
+ #endif
+
+ #if defined (ENOTEMPTY)
+ case ENOTEMPTY:
+ throw EnotemptyExc (tmp);
+ #endif
+
+ #if defined (EUSERS)
+ case EUSERS:
+ throw EusersExc (tmp);
+ #endif
+
+ #if defined (ENOTSOCK)
+ case ENOTSOCK:
+ throw EnotsockExc (tmp);
+ #endif
+
+ #if defined (EDESTADDRREQ)
+ case EDESTADDRREQ:
+ throw EdestaddrreqExc (tmp);
+ #endif
+
+ #if defined (EMSGSIZE)
+ case EMSGSIZE:
+ throw EmsgsizeExc (tmp);
+ #endif
+
+ #if defined (EPROTOTYPE)
+ case EPROTOTYPE:
+ throw EprototypeExc (tmp);
+ #endif
+
+ #if defined (ENOPROTOOPT)
+ case ENOPROTOOPT:
+ throw EnoprotooptExc (tmp);
+ #endif
+
+ #if defined (EPROTONOSUPPORT)
+ case EPROTONOSUPPORT:
+ throw EprotonosupportExc (tmp);
+ #endif
+
+ #if defined (ESOCKTNOSUPPORT)
+ case ESOCKTNOSUPPORT:
+ throw EsocktnosupportExc (tmp);
+ #endif
+
+ #if defined (EOPNOTSUPP)
+ case EOPNOTSUPP:
+ throw EopnotsuppExc (tmp);
+ #endif
+
+ #if defined (EPFNOSUPPORT)
+ case EPFNOSUPPORT:
+ throw EpfnosupportExc (tmp);
+ #endif
+
+ #if defined (EAFNOSUPPORT)
+ case EAFNOSUPPORT:
+ throw EafnosupportExc (tmp);
+ #endif
+
+ #if defined (EADDRINUSE)
+ case EADDRINUSE:
+ throw EaddrinuseExc (tmp);
+ #endif
+
+ #if defined (EADDRNOTAVAIL)
+ case EADDRNOTAVAIL:
+ throw EaddrnotavailExc (tmp);
+ #endif
+
+ #if defined (ENETDOWN)
+ case ENETDOWN:
+ throw EnetdownExc (tmp);
+ #endif
+
+ #if defined (ENETUNREACH)
+ case ENETUNREACH:
+ throw EnetunreachExc (tmp);
+ #endif
+
+ #if defined (ENETRESET)
+ case ENETRESET:
+ throw EnetresetExc (tmp);
+ #endif
+
+ #if defined (ECONNABORTED)
+ case ECONNABORTED:
+ throw EconnabortedExc (tmp);
+ #endif
+
+ #if defined (ECONNRESET)
+ case ECONNRESET:
+ throw EconnresetExc (tmp);
+ #endif
+
+ #if defined (ENOBUFS)
+ case ENOBUFS:
+ throw EnobufsExc (tmp);
+ #endif
+
+ #if defined (EISCONN)
+ case EISCONN:
+ throw EisconnExc (tmp);
+ #endif
+
+ #if defined (ENOTCONN)
+ case ENOTCONN:
+ throw EnotconnExc (tmp);
+ #endif
+
+ #if defined (ESHUTDOWN)
+ case ESHUTDOWN:
+ throw EshutdownExc (tmp);
+ #endif
+
+ #if defined (ETOOMANYREFS)
+ case ETOOMANYREFS:
+ throw EtoomanyrefsExc (tmp);
+ #endif
+
+ #if defined (ETIMEDOUT)
+ case ETIMEDOUT:
+ throw EtimedoutExc (tmp);
+ #endif
+
+ #if defined (ECONNREFUSED)
+ case ECONNREFUSED:
+ throw EconnrefusedExc (tmp);
+ #endif
+
+ #if defined (EHOSTDOWN)
+ case EHOSTDOWN:
+ throw EhostdownExc (tmp);
+ #endif
+
+ #if defined (EHOSTUNREACH)
+ case EHOSTUNREACH:
+ throw EhostunreachExc (tmp);
+ #endif
+
+ #if defined (EALREADY)
+ case EALREADY:
+ throw EalreadyExc (tmp);
+ #endif
+
+ #if defined (EINPROGRESS)
+ case EINPROGRESS:
+ throw EinprogressExc (tmp);
+ #endif
+
+ #if defined (ESTALE)
+ case ESTALE:
+ throw EstaleExc (tmp);
+ #endif
+
+ #if defined (EIORESID)
+ case EIORESID:
+ throw EioresidExc (tmp);
+ #endif
+
+ #if defined (EUCLEAN)
+ case EUCLEAN:
+ throw EucleanExc (tmp);
+ #endif
+
+ #if defined (ENOTNAM)
+ case ENOTNAM:
+ throw EnotnamExc (tmp);
+ #endif
+
+ #if defined (ENAVAIL)
+ case ENAVAIL:
+ throw EnavailExc (tmp);
+ #endif
+
+ #if defined (EISNAM)
+ case EISNAM:
+ throw EisnamExc (tmp);
+ #endif
+
+ #if defined (EREMOTEIO)
+ case EREMOTEIO:
+ throw EremoteioExc (tmp);
+ #endif
+
+ #if defined (EINIT)
+ case EINIT:
+ throw EinitExc (tmp);
+ #endif
+
+ #if defined (EREMDEV)
+ case EREMDEV:
+ throw EremdevExc (tmp);
+ #endif
+
+ #if defined (ECANCELED)
+ case ECANCELED:
+ throw EcanceledExc (tmp);
+ #endif
+
+ #if defined (ENOLIMFILE)
+ case ENOLIMFILE:
+ throw EnolimfileExc (tmp);
+ #endif
+
+ #if defined (EPROCLIM)
+ case EPROCLIM:
+ throw EproclimExc (tmp);
+ #endif
+
+ #if defined (EDISJOINT)
+ case EDISJOINT:
+ throw EdisjointExc (tmp);
+ #endif
+
+ #if defined (ENOLOGIN)
+ case ENOLOGIN:
+ throw EnologinExc (tmp);
+ #endif
+
+ #if defined (ELOGINLIM)
+ case ELOGINLIM:
+ throw EloginlimExc (tmp);
+ #endif
+
+ #if defined (EGROUPLOOP)
+ case EGROUPLOOP:
+ throw EgrouploopExc (tmp);
+ #endif
+
+ #if defined (ENOATTACH)
+ case ENOATTACH:
+ throw EnoattachExc (tmp);
+ #endif
+
+ #if defined (ENOTSUP) && defined (EOPNOTSUPP)
+ #if ENOTSUP != EOPNOTSUPP
+ case ENOTSUP:
+ throw EnotsupExc (tmp);
+ #endif
+ #elif defined (ENOTSUP)
+ case ENOTSUP:
+ throw EnotsupExc (tmp);
+ #endif
+
+ #if defined (ENOATTR)
+ case ENOATTR:
+ throw EnoattrExc (tmp);
+ #endif
+
+ #if defined (EDIRCORRUPTED)
+ case EDIRCORRUPTED:
+ throw EdircorruptedExc (tmp);
+ #endif
+
+ #if defined (EDQUOT)
+ case EDQUOT:
+ throw EdquotExc (tmp);
+ #endif
+
+ #if defined (ENFSREMOTE)
+ case ENFSREMOTE:
+ throw EnfsremoteExc (tmp);
+ #endif
+
+ #if defined (ECONTROLLER)
+ case ECONTROLLER:
+ throw EcontrollerExc (tmp);
+ #endif
+
+ #if defined (ENOTCONTROLLER)
+ case ENOTCONTROLLER:
+ throw EnotcontrollerExc (tmp);
+ #endif
+
+ #if defined (EENQUEUED)
+ case EENQUEUED:
+ throw EenqueuedExc (tmp);
+ #endif
+
+ #if defined (ENOTENQUEUED)
+ case ENOTENQUEUED:
+ throw EnotenqueuedExc (tmp);
+ #endif
+
+ #if defined (EJOINED)
+ case EJOINED:
+ throw EjoinedExc (tmp);
+ #endif
+
+ #if defined (ENOTJOINED)
+ case ENOTJOINED:
+ throw EnotjoinedExc (tmp);
+ #endif
+
+ #if defined (ENOPROC)
+ case ENOPROC:
+ throw EnoprocExc (tmp);
+ #endif
+
+ #if defined (EMUSTRUN)
+ case EMUSTRUN:
+ throw EmustrunExc (tmp);
+ #endif
+
+ #if defined (ENOTSTOPPED)
+ case ENOTSTOPPED:
+ throw EnotstoppedExc (tmp);
+ #endif
+
+ #if defined (ECLOCKCPU)
+ case ECLOCKCPU:
+ throw EclockcpuExc (tmp);
+ #endif
+
+ #if defined (EINVALSTATE)
+ case EINVALSTATE:
+ throw EinvalstateExc (tmp);
+ #endif
+
+ #if defined (ENOEXIST)
+ case ENOEXIST:
+ throw EnoexistExc (tmp);
+ #endif
+
+ #if defined (EENDOFMINOR)
+ case EENDOFMINOR:
+ throw EendofminorExc (tmp);
+ #endif
+
+ #if defined (EBUFSIZE)
+ case EBUFSIZE:
+ throw EbufsizeExc (tmp);
+ #endif
+
+ #if defined (EEMPTY)
+ case EEMPTY:
+ throw EemptyExc (tmp);
+ #endif
+
+ #if defined (ENOINTRGROUP)
+ case ENOINTRGROUP:
+ throw EnointrgroupExc (tmp);
+ #endif
+
+ #if defined (EINVALMODE)
+ case EINVALMODE:
+ throw EinvalmodeExc (tmp);
+ #endif
+
+ #if defined (ECANTEXTENT)
+ case ECANTEXTENT:
+ throw EcantextentExc (tmp);
+ #endif
+
+ #if defined (EINVALTIME)
+ case EINVALTIME:
+ throw EinvaltimeExc (tmp);
+ #endif
+
+ #if defined (EDESTROYED)
+ case EDESTROYED:
+ throw EdestroyedExc (tmp);
+ #endif
+ }
+
+ throw ErrnoExc (tmp);
+}
+
+
+void throwErrnoExc (const std::string &text)
+{
+ throwErrnoExc (text, errno);
+}
+
+
+} // namespace Iex
diff --git a/Source/OpenEXR/Iex/IexThrowErrnoExc.h b/Source/OpenEXR/Iex/IexThrowErrnoExc.h
new file mode 100644
index 0000000..5b41dcc
--- /dev/null
+++ b/Source/OpenEXR/Iex/IexThrowErrnoExc.h
@@ -0,0 +1,96 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IEXTHROWERRNOEXC_H
+#define INCLUDED_IEXTHROWERRNOEXC_H
+
+//----------------------------------------------------------
+//
+// A function which throws ExcErrno exceptions
+//
+//----------------------------------------------------------
+
+#include "IexBaseExc.h"
+
+namespace Iex {
+
+
+//--------------------------------------------------------------------------
+//
+// Function throwErrnoExc() throws an exception which corresponds to
+// error code errnum. The exception text is initialized with a copy
+// of the string passed to throwErrnoExc(), where all occurrences of
+// "%T" have been replaced with the output of strerror(oserror()).
+//
+// Example:
+//
+// If opening file /tmp/output failed with an ENOENT error code,
+// calling
+//
+// throwErrnoExc ();
+//
+// or
+//
+// throwErrnoExc ("%T.");
+//
+// will throw an EnoentExc whose text reads
+//
+// No such file or directory.
+//
+// More detailed messages can be assembled using stringstreams:
+//
+// std::stringstream s;
+// s << "Cannot open file " << name << " (%T).";
+// throwErrnoExc (s);
+//
+// The resulting exception contains the following text:
+//
+// Cannot open file /tmp/output (No such file or directory).
+//
+// Alternatively, you may want to use the THROW_ERRNO macro defined
+// in IexMacros.h:
+//
+// THROW_ERRNO ("Cannot open file " << name << " (%T).")
+//
+//--------------------------------------------------------------------------
+
+void throwErrnoExc (const std::string &txt, int errnum);
+void throwErrnoExc (const std::string &txt = "%T." /*, int errnum = oserror() */);
+
+
+} // namespace Iex
+
+#endif
diff --git a/Source/OpenEXR/Iex/Makefile.am b/Source/OpenEXR/Iex/Makefile.am
new file mode 100644
index 0000000..9b6df1b
--- /dev/null
+++ b/Source/OpenEXR/Iex/Makefile.am
@@ -0,0 +1,16 @@
+## Process this file with automake to produce Makefile.in
+
+INCLUDES = -I$(top_srcdir)/config
+
+lib_LTLIBRARIES = libIex.la
+
+libIex_la_SOURCES = IexThrowErrnoExc.cpp IexBaseExc.cpp IexBaseExc.h \
+ IexErrnoExc.h Iex.h IexMacros.h IexMathExc.h \
+ IexThrowErrnoExc.h
+
+libIex_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+
+libIexincludedir = $(includedir)/OpenEXR
+
+libIexinclude_HEADERS = IexBaseExc.h IexMathExc.h IexThrowErrnoExc.h \
+ IexErrnoExc.h IexMacros.h Iex.h
diff --git a/Source/OpenEXR/Iex/Makefile.in b/Source/OpenEXR/Iex/Makefile.in
new file mode 100644
index 0000000..14f090c
--- /dev/null
+++ b/Source/OpenEXR/Iex/Makefile.in
@@ -0,0 +1,504 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+SOURCES = $(libIex_la_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = Iex
+DIST_COMMON = $(libIexinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/IlmBaseConfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libIexincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libIex_la_LIBADD =
+am_libIex_la_OBJECTS = IexThrowErrnoExc.lo IexBaseExc.lo
+libIex_la_OBJECTS = $(am_libIex_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libIex_la_SOURCES)
+DIST_SOURCES = $(libIex_la_SOURCES)
+libIexincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libIexinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CXXFLAGS = @AM_CXXFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+ILMBASE_VERSION = @ILMBASE_VERSION@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION = @LIBTOOL_VERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+acx_pthread_config = @acx_pthread_config@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+INCLUDES = -I$(top_srcdir)/config
+lib_LTLIBRARIES = libIex.la
+libIex_la_SOURCES = IexThrowErrnoExc.cpp IexBaseExc.cpp IexBaseExc.h \
+ IexErrnoExc.h Iex.h IexMacros.h IexMathExc.h \
+ IexThrowErrnoExc.h
+
+libIex_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libIexincludedir = $(includedir)/OpenEXR
+libIexinclude_HEADERS = IexBaseExc.h IexMathExc.h IexThrowErrnoExc.h \
+ IexErrnoExc.h IexMacros.h Iex.h
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Iex/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Iex/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libIex.la: $(libIex_la_OBJECTS) $(libIex_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libIex_la_LDFLAGS) $(libIex_la_OBJECTS) $(libIex_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IexBaseExc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IexThrowErrnoExc.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libIexincludeHEADERS: $(libIexinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libIexincludedir)" || $(mkdir_p) "$(DESTDIR)$(libIexincludedir)"
+ @list='$(libIexinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libIexincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libIexincludedir)/$$f'"; \
+ $(libIexincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libIexincludedir)/$$f"; \
+ done
+
+uninstall-libIexincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libIexinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libIexincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libIexincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libIexincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libIexincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libIexincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am \
+ install-libIexincludeHEADERS install-libLTLIBRARIES \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am uninstall-libIexincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/OpenEXR/IlmBaseConfig.h b/Source/OpenEXR/IlmBaseConfig.h
new file mode 100644
index 0000000..cc8bb9d
--- /dev/null
+++ b/Source/OpenEXR/IlmBaseConfig.h
@@ -0,0 +1,46 @@
+//
+// Define and set to 1 if the target system has POSIX thread support
+// and you want OpenEXR to use it for multithreaded file I/O.
+//
+
+#undef HAVE_PTHREAD // currently disabled in FreeImage
+
+//
+// Define and set to 1 if the target system supports POSIX semaphores
+// and you want OpenEXR to use them; otherwise, OpenEXR will use its
+// own semaphore implementation.
+//
+
+#undef HAVE_POSIX_SEMAPHORES
+
+//
+// Define and set to 1 if the target system is a Darwin-based system
+// (e.g., OS X).
+//
+
+#undef HAVE_DARWIN
+
+//
+// Define and set to 1 if the target system supports a proc filesystem
+// compatible with the Linux kernel's proc filesystem. Note that this
+// is only used by a program in the IlmImfTest test suite, it's not
+// used by any OpenEXR library or application code.
+//
+
+#undef HAVE_LINUX_PROCFS
+
+//
+// Define and set to 1 if the target system includes the NVIDIA Cg
+// runtime. The exrdisplay program will use a fragment shader to
+// accelerate the display of OpenEXR images.
+//
+
+#undef HAVE_FRAGMENT_SHADERS
+
+//
+// Define and set to 1 if the target system has a complete <iomanip>
+// implementation, specifically if it supports the std::right
+// formatter.
+//
+
+#undef HAVE_COMPLETE_IOMANIP
diff --git a/Source/OpenEXR/IlmImf/ImfArray.h b/Source/OpenEXR/IlmImf/ImfArray.h
new file mode 100644
index 0000000..18eb66f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfArray.h
@@ -0,0 +1,261 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_ARRAY_H
+#define INCLUDED_IMF_ARRAY_H
+
+//-------------------------------------------------------------------------
+//
+// class Array
+// class Array2D
+//
+// "Arrays of T" whose sizes are not known at compile time.
+// When an array goes out of scope, its elements are automatically
+// deleted.
+//
+// Usage example:
+//
+// struct C
+// {
+// C () {std::cout << "C::C (" << this << ")\n";};
+// virtual ~C () {std::cout << "C::~C (" << this << ")\n";};
+// };
+//
+// int
+// main ()
+// {
+// Array <C> a(3);
+//
+// C &b = a[1];
+// const C &c = a[1];
+// C *d = a + 2;
+// const C *e = a;
+//
+// return 0;
+// }
+//
+//-------------------------------------------------------------------------
+
+namespace Imf {
+
+
+template <class T>
+class Array
+{
+ public:
+
+ //-----------------------------
+ // Constructors and destructors
+ //-----------------------------
+
+ Array () {_data = 0;}
+ Array (long size) {_data = new T[size];}
+ ~Array () {delete [] _data;}
+
+
+ //-----------------------------
+ // Access to the array elements
+ //-----------------------------
+
+ operator T * () {return _data;}
+ operator const T * () const {return _data;}
+
+
+ //------------------------------------------------------
+ // Resize and clear the array (the contents of the array
+ // are not preserved across the resize operation).
+ //
+ // resizeEraseUnsafe() is more memory efficient than
+ // resizeErase() because it deletes the old memory block
+ // before allocating a new one, but if allocating the
+ // new block throws an exception, resizeEraseUnsafe()
+ // leaves the array in an unusable state.
+ //
+ //------------------------------------------------------
+
+ void resizeErase (long size);
+ void resizeEraseUnsafe (long size);
+
+
+ private:
+
+ Array (const Array &); // Copying and assignment
+ Array & operator = (const Array &); // are not implemented
+
+ T * _data;
+};
+
+
+template <class T>
+class Array2D
+{
+ public:
+
+ //-----------------------------
+ // Constructors and destructors
+ //-----------------------------
+
+ Array2D (); // empty array, 0 by 0 elements
+ Array2D (long sizeX, long sizeY); // sizeX by sizeY elements
+ ~Array2D ();
+
+
+ //-----------------------------
+ // Access to the array elements
+ //-----------------------------
+
+ T * operator [] (long x);
+ const T * operator [] (long x) const;
+
+
+ //------------------------------------------------------
+ // Resize and clear the array (the contents of the array
+ // are not preserved across the resize operation).
+ //
+ // resizeEraseUnsafe() is more memory efficient than
+ // resizeErase() because it deletes the old memory block
+ // before allocating a new one, but if allocating the
+ // new block throws an exception, resizeEraseUnsafe()
+ // leaves the array in an unusable state.
+ //
+ //------------------------------------------------------
+
+ void resizeErase (long sizeX, long sizeY);
+ void resizeEraseUnsafe (long sizeX, long sizeY);
+
+
+ private:
+
+ Array2D (const Array2D &); // Copying and assignment
+ Array2D & operator = (const Array2D &); // are not implemented
+
+ long _sizeY;
+ T * _data;
+};
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+inline void
+Array<T>::resizeErase (long size)
+{
+ T *tmp = new T[size];
+ delete [] _data;
+ _data = tmp;
+}
+
+
+template <class T>
+inline void
+Array<T>::resizeEraseUnsafe (long size)
+{
+ delete [] _data;
+ _data = 0;
+ _data = new T[size];
+}
+
+
+template <class T>
+inline
+Array2D<T>::Array2D ():
+ _sizeY (0), _data (0)
+{
+ // emtpy
+}
+
+
+template <class T>
+inline
+Array2D<T>::Array2D (long sizeX, long sizeY):
+ _sizeY (sizeY), _data (new T[sizeX * sizeY])
+{
+ // emtpy
+}
+
+
+template <class T>
+inline
+Array2D<T>::~Array2D ()
+{
+ delete [] _data;
+}
+
+
+template <class T>
+inline T *
+Array2D<T>::operator [] (long x)
+{
+ return _data + x * _sizeY;
+}
+
+
+template <class T>
+inline const T *
+Array2D<T>::operator [] (long x) const
+{
+ return _data + x * _sizeY;
+}
+
+
+template <class T>
+inline void
+Array2D<T>::resizeErase (long sizeX, long sizeY)
+{
+ T *tmp = new T[sizeX * sizeY];
+ delete [] _data;
+ _sizeY = sizeY;
+ _data = tmp;
+}
+
+
+template <class T>
+inline void
+Array2D<T>::resizeEraseUnsafe (long sizeX, long sizeY)
+{
+ delete [] _data;
+ _data = 0;
+ _sizeY = 0;
+ _data = new T[sizeX * sizeY];
+ _sizeY = sizeY;
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfAttribute.cpp b/Source/OpenEXR/IlmImf/ImfAttribute.cpp
new file mode 100644
index 0000000..feb5f83
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfAttribute.cpp
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Attribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <string.h>
+#include <map>
+
+
+namespace Imf {
+
+using IlmThread::Mutex;
+using IlmThread::Lock;
+
+
+Attribute::Attribute () {}
+
+
+Attribute::~Attribute () {}
+
+
+namespace {
+
+struct NameCompare: std::binary_function <const char *, const char *, bool>
+{
+ bool
+ operator () (const char *x, const char *y) const
+ {
+ return strcmp (x, y) < 0;
+ }
+};
+
+
+typedef Attribute* (*Constructor)();
+typedef std::map <const char *, Constructor, NameCompare> TypeMap;
+
+
+class LockedTypeMap: public TypeMap
+{
+ public:
+
+ Mutex mutex;
+};
+
+
+LockedTypeMap &
+typeMap ()
+{
+ static Mutex criticalSection;
+ Lock lock (criticalSection);
+
+ static LockedTypeMap* typeMap = 0;
+
+ if (typeMap == 0)
+ typeMap = new LockedTypeMap ();
+
+ return *typeMap;
+}
+
+
+} // namespace
+
+
+bool
+Attribute::knownType (const char typeName[])
+{
+ LockedTypeMap& tMap = typeMap();
+ Lock lock (tMap.mutex);
+
+ return tMap.find (typeName) != tMap.end();
+}
+
+
+void
+Attribute::registerAttributeType (const char typeName[],
+ Attribute *(*newAttribute)())
+{
+ LockedTypeMap& tMap = typeMap();
+ Lock lock (tMap.mutex);
+
+ if (tMap.find (typeName) != tMap.end())
+ THROW (Iex::ArgExc, "Cannot register image file attribute "
+ "type \"" << typeName << "\". "
+ "The type has already been registered.");
+
+ tMap.insert (TypeMap::value_type (typeName, newAttribute));
+}
+
+
+void
+Attribute::unRegisterAttributeType (const char typeName[])
+{
+ LockedTypeMap& tMap = typeMap();
+ Lock lock (tMap.mutex);
+
+ tMap.erase (typeName);
+}
+
+
+Attribute *
+Attribute::newAttribute (const char typeName[])
+{
+ LockedTypeMap& tMap = typeMap();
+ Lock lock (tMap.mutex);
+
+ TypeMap::const_iterator i = tMap.find (typeName);
+
+ if (i == tMap.end())
+ THROW (Iex::ArgExc, "Cannot create image file attribute of "
+ "unknown type \"" << typeName << "\".");
+
+ return (i->second)();
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfAttribute.h b/Source/OpenEXR/IlmImf/ImfAttribute.h
new file mode 100644
index 0000000..45d62ff
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfAttribute.h
@@ -0,0 +1,422 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_ATTRIBUTE_H
+#define INCLUDED_IMF_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class Attribute
+//
+//-----------------------------------------------------------------------------
+
+#include "IexBaseExc.h"
+#include <ImfIO.h>
+#include <ImfXdr.h>
+
+
+namespace Imf {
+
+
+class Attribute
+{
+ public:
+
+ //---------------------------
+ // Constructor and destructor
+ //---------------------------
+
+ Attribute ();
+ virtual ~Attribute ();
+
+
+ //-------------------------------
+ // Get this attribute's type name
+ //-------------------------------
+
+ virtual const char * typeName () const = 0;
+
+
+ //------------------------------
+ // Make a copy of this attribute
+ //------------------------------
+
+ virtual Attribute * copy () const = 0;
+
+
+ //----------------------------------------
+ // Type-specific attribute I/O and copying
+ //----------------------------------------
+
+ virtual void writeValueTo (OStream &os,
+ int version) const = 0;
+
+ virtual void readValueFrom (IStream &is,
+ int size,
+ int version) = 0;
+
+ virtual void copyValueFrom (const Attribute &other) = 0;
+
+
+ //------------------
+ // Attribute factory
+ //------------------
+
+ static Attribute * newAttribute (const char typeName[]);
+
+
+ //-----------------------------------------------------------
+ // Test if a given attribute type has already been registered
+ //-----------------------------------------------------------
+
+ static bool knownType (const char typeName[]);
+
+
+ protected:
+
+ //--------------------------------------------------
+ // Register an attribute type so that newAttribute()
+ // knows how to make objects of this type.
+ //--------------------------------------------------
+
+ static void registerAttributeType (const char typeName[],
+ Attribute *(*newAttribute)());
+
+ //------------------------------------------------------
+ // Un-register an attribute type so that newAttribute()
+ // no longer knows how to make objects of this type (for
+ // debugging only).
+ //------------------------------------------------------
+
+ static void unRegisterAttributeType (const char typeName[]);
+};
+
+
+//-------------------------------------------------
+// Class template for attributes of a specific type
+//-------------------------------------------------
+
+template <class T>
+class TypedAttribute: public Attribute
+{
+ public:
+
+ //----------------------------
+ // Constructors and destructor
+ //------------_---------------
+
+ TypedAttribute ();
+ TypedAttribute (const T &value);
+ TypedAttribute (const TypedAttribute<T> &other);
+ virtual ~TypedAttribute ();
+
+
+ //--------------------------------
+ // Access to the attribute's value
+ //--------------------------------
+
+ T & value ();
+ const T & value () const;
+
+
+ //--------------------------------
+ // Get this attribute's type name.
+ //--------------------------------
+
+ virtual const char * typeName () const;
+
+
+ //---------------------------------------------------------
+ // Static version of typeName()
+ // This function must be specialized for each value type T.
+ //---------------------------------------------------------
+
+ static const char * staticTypeName ();
+
+
+ //---------------------
+ // Make a new attribute
+ //---------------------
+
+ static Attribute * makeNewAttribute ();
+
+
+ //------------------------------
+ // Make a copy of this attribute
+ //------------------------------
+
+ virtual Attribute * copy () const;
+
+
+ //-----------------------------------------------------------------
+ // Type-specific attribute I/O and copying.
+ // Depending on type T, these functions may have to be specialized.
+ //-----------------------------------------------------------------
+
+ virtual void writeValueTo (OStream &os,
+ int version) const;
+
+ virtual void readValueFrom (IStream &is,
+ int size,
+ int version);
+
+ virtual void copyValueFrom (const Attribute &other);
+
+
+ //------------------------------------------------------------
+ // Dynamic casts that throw exceptions instead of returning 0.
+ //------------------------------------------------------------
+
+ static TypedAttribute * cast (Attribute *attribute);
+ static const TypedAttribute * cast (const Attribute *attribute);
+ static TypedAttribute & cast (Attribute &attribute);
+ static const TypedAttribute & cast (const Attribute &attribute);
+
+
+ //---------------------------------------------------------------
+ // Register this attribute type so that Attribute::newAttribute()
+ // knows how to make objects of this type.
+ //
+ // Note that this function is not thread-safe because it modifies
+ // a global variable in the IlmIlm library. A thread in a multi-
+ // threaded program may call registerAttributeType() only when no
+ // other thread is accessing any functions or classes in the
+ // IlmImf library.
+ //
+ //---------------------------------------------------------------
+
+ static void registerAttributeType ();
+
+
+ //-----------------------------------------------------
+ // Un-register this attribute type (for debugging only)
+ //-----------------------------------------------------
+
+ static void unRegisterAttributeType ();
+
+
+ private:
+
+ T _value;
+};
+
+
+//------------------------------------
+// Implementation of TypedAttribute<T>
+//------------------------------------
+
+template <class T>
+TypedAttribute<T>::TypedAttribute (): _value (T())
+{
+ // empty
+}
+
+
+template <class T>
+TypedAttribute<T>::TypedAttribute (const T &value): _value (value)
+{
+ // empty
+}
+
+
+template <class T>
+TypedAttribute<T>::TypedAttribute (const TypedAttribute<T> &other):
+ _value ()
+{
+ copyValueFrom (other);
+}
+
+
+template <class T>
+TypedAttribute<T>::~TypedAttribute ()
+{
+ // empty
+}
+
+
+template <class T>
+inline T &
+TypedAttribute<T>::value ()
+{
+ return _value;
+}
+
+
+template <class T>
+inline const T &
+TypedAttribute<T>::value () const
+{
+ return _value;
+}
+
+
+template <class T>
+const char *
+TypedAttribute<T>::typeName () const
+{
+ return staticTypeName();
+}
+
+
+template <class T>
+Attribute *
+TypedAttribute<T>::makeNewAttribute ()
+{
+ return new TypedAttribute<T>();
+}
+
+
+template <class T>
+Attribute *
+TypedAttribute<T>::copy () const
+{
+ Attribute * attribute = new TypedAttribute<T>();
+ attribute->copyValueFrom (*this);
+ return attribute;
+}
+
+
+template <class T>
+void
+TypedAttribute<T>::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value);
+}
+
+
+template <class T>
+void
+TypedAttribute<T>::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value);
+}
+
+
+template <class T>
+void
+TypedAttribute<T>::copyValueFrom (const Attribute &other)
+{
+ _value = cast(other)._value;
+}
+
+
+template <class T>
+TypedAttribute<T> *
+TypedAttribute<T>::cast (Attribute *attribute)
+{
+ TypedAttribute<T> *t =
+ dynamic_cast <TypedAttribute<T> *> (attribute);
+
+ if (t == 0)
+ throw Iex::TypeExc ("Unexpected attribute type.");
+
+ return t;
+}
+
+
+template <class T>
+const TypedAttribute<T> *
+TypedAttribute<T>::cast (const Attribute *attribute)
+{
+ const TypedAttribute<T> *t =
+ dynamic_cast <const TypedAttribute<T> *> (attribute);
+
+ if (t == 0)
+ throw Iex::TypeExc ("Unexpected attribute type.");
+
+ return t;
+}
+
+
+template <class T>
+inline TypedAttribute<T> &
+TypedAttribute<T>::cast (Attribute &attribute)
+{
+ return *cast (&attribute);
+}
+
+
+template <class T>
+inline const TypedAttribute<T> &
+TypedAttribute<T>::cast (const Attribute &attribute)
+{
+ return *cast (&attribute);
+}
+
+
+template <class T>
+inline void
+TypedAttribute<T>::registerAttributeType ()
+{
+ Attribute::registerAttributeType (staticTypeName(), makeNewAttribute);
+}
+
+
+template <class T>
+inline void
+TypedAttribute<T>::unRegisterAttributeType ()
+{
+ Attribute::unRegisterAttributeType (staticTypeName());
+}
+
+
+} // namespace Imf
+
+#if defined(OPENEXR_DLL) && defined(_MSC_VER)
+ // Tell MS VC++ to disable "non dll-interface class used as base
+ // for dll-interface class" and "no suitable definition provided
+ // for explicit template"
+ #pragma warning (disable : 4275 4661)
+
+ #if defined (ILMIMF_EXPORTS)
+ #define IMF_EXPIMP_TEMPLATE
+ #else
+ #define IMF_EXPIMP_TEMPLATE extern
+ #endif
+
+ IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute<float>;
+ IMF_EXPIMP_TEMPLATE template class Imf::TypedAttribute<double>;
+
+ #pragma warning(default : 4251)
+ #undef EXTERN_TEMPLATE
+#endif
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfAutoArray.h b/Source/OpenEXR/IlmImf/ImfAutoArray.h
new file mode 100644
index 0000000..e026824
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfAutoArray.h
@@ -0,0 +1,93 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_AUTO_ARRAY_H
+#define INCLUDED_IMF_AUTO_ARRAY_H
+
+//-----------------------------------------------------------------------------
+//
+// class AutoArray -- a workaround for systems with
+// insufficient stack space for large auto arrays.
+//
+//-----------------------------------------------------------------------------
+
+#include "OpenEXRConfig.h"
+
+namespace Imf {
+
+
+#if !defined (HAVE_LARGE_STACK)
+
+
+ template <class T, int size>
+ class AutoArray
+ {
+ public:
+
+ AutoArray (): _data (new T [size]) {}
+ ~AutoArray () {delete [] _data;}
+
+ operator T * () {return _data;}
+ operator const T * () const {return _data;}
+
+ private:
+
+ T *_data;
+ };
+
+
+#else
+
+
+ template <class T, int size>
+ class AutoArray
+ {
+ public:
+
+ operator T * () {return _data;}
+ operator const T * () const {return _data;}
+
+ private:
+
+ T _data[size];
+ };
+
+
+#endif
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfB44Compressor.cpp b/Source/OpenEXR/IlmImf/ImfB44Compressor.cpp
new file mode 100644
index 0000000..7771e6e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfB44Compressor.cpp
@@ -0,0 +1,1064 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class B44Compressor
+//
+// This compressor is lossy for HALF channels; the compression rate
+// is fixed at 32/14 (approximately 2.28). FLOAT and UINT channels
+// are not compressed; their data are preserved exactly.
+//
+// Each HALF channel is split into blocks of 4 by 4 pixels. An
+// uncompressed block occupies 32 bytes, which are re-interpreted
+// as sixteen 16-bit unsigned integers, t[0] ... t[15]. Compression
+// shrinks the block to 14 bytes. The compressed 14-byte block
+// contains
+//
+// - t[0]
+//
+// - a 6-bit shift value
+//
+// - 15 densely packed 6-bit values, r[0] ... r[14], which are
+// computed by subtracting adjacent pixel values and right-
+// shifting the differences according to the stored shift value.
+//
+// Differences between adjacent pixels are computed according
+// to the following diagram:
+//
+// 0 --------> 1 --------> 2 --------> 3
+// | 3 7 11
+// |
+// | 0
+// |
+// v
+// 4 --------> 5 --------> 6 --------> 7
+// | 4 8 12
+// |
+// | 1
+// |
+// v
+// 8 --------> 9 --------> 10 --------> 11
+// | 5 9 13
+// |
+// | 2
+// |
+// v
+// 12 --------> 13 --------> 14 --------> 15
+// 6 10 14
+//
+// Here
+//
+// 5 ---------> 6
+// 8
+//
+// means that r[8] is the difference between t[5] and t[6].
+//
+// - optionally, a 4-by-4 pixel block where all pixels have the
+// same value can be treated as a special case, where the
+// compressed block contains only 3 instead of 14 bytes:
+// t[0], followed by an "impossible" 6-bit shift value and
+// two padding bits.
+//
+// This compressor can handle positive and negative pixel values.
+// NaNs and infinities are replaced with zeroes before compression.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfB44Compressor.h>
+#include <ImfHeader.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImathFun.h>
+#include <ImathBox.h>
+#include <Iex.h>
+#include <ImfIO.h>
+#include <ImfXdr.h>
+#include <string.h>
+#include <assert.h>
+#include <algorithm>
+
+namespace Imf {
+
+using Imath::divp;
+using Imath::modp;
+using Imath::Box2i;
+using Imath::V2i;
+using std::min;
+
+namespace {
+
+//
+// Lookup tables for
+// y = exp (x / 8)
+// and
+// x = 8 * log (y)
+//
+
+#include "b44ExpLogTable.h"
+
+
+inline void
+convertFromLinear (unsigned short s[16])
+{
+ for (int i = 0; i < 16; ++i)
+ s[i] = expTable[s[i]];
+}
+
+
+inline void
+convertToLinear (unsigned short s[16])
+{
+ for (int i = 0; i < 16; ++i)
+ s[i] = logTable[s[i]];
+}
+
+
+inline int
+shiftAndRound (int x, int shift)
+{
+ //
+ // Compute
+ //
+ // y = x * pow (2, -shift),
+ //
+ // then round y to the nearest integer.
+ // In case of a tie, where y is exactly
+ // halfway between two integers, round
+ // to the even one.
+ //
+
+ x <<= 1;
+ int a = (1 << shift) - 1;
+ shift += 1;
+ int b = (x >> shift) & 1;
+ return (x + a + b) >> shift;
+}
+
+
+int
+pack (const unsigned short s[16],
+ unsigned char b[14],
+ bool optFlatFields,
+ bool exactMax)
+{
+ //
+ // Pack a block of 4 by 4 16-bit pixels (32 bytes) into
+ // either 14 or 3 bytes.
+ //
+
+ //
+ // Integers s[0] ... s[15] represent floating-point numbers
+ // in what is essentially a sign-magnitude format. Convert
+ // s[0] .. s[15] into a new set of integers, t[0] ... t[15],
+ // such that if t[i] is greater than t[j], the floating-point
+ // number that corresponds to s[i] is always greater than
+ // the floating-point number that corresponds to s[j].
+ //
+ // Also, replace any bit patterns that represent NaNs or
+ // infinities with bit patterns that represent floating-point
+ // zeroes.
+ //
+ // bit pattern floating-point bit pattern
+ // in s[i] value in t[i]
+ //
+ // 0x7fff NAN 0x8000
+ // 0x7ffe NAN 0x8000
+ // ... ...
+ // 0x7c01 NAN 0x8000
+ // 0x7c00 +infinity 0x8000
+ // 0x7bff +HALF_MAX 0xfbff
+ // 0x7bfe 0xfbfe
+ // 0x7bfd 0xfbfd
+ // ... ...
+ // 0x0002 +2 * HALF_MIN 0x8002
+ // 0x0001 +HALF_MIN 0x8001
+ // 0x0000 +0.0 0x8000
+ // 0x8000 -0.0 0x7fff
+ // 0x8001 -HALF_MIN 0x7ffe
+ // 0x8002 -2 * HALF_MIN 0x7ffd
+ // ... ...
+ // 0xfbfd 0x0f02
+ // 0xfbfe 0x0401
+ // 0xfbff -HALF_MAX 0x0400
+ // 0xfc00 -infinity 0x8000
+ // 0xfc01 NAN 0x8000
+ // ... ...
+ // 0xfffe NAN 0x8000
+ // 0xffff NAN 0x8000
+ //
+
+ unsigned short t[16];
+
+ for (int i = 0; i < 16; ++i)
+ {
+ if ((s[i] & 0x7c00) == 0x7c00)
+ t[i] = 0x8000;
+ else if (s[i] & 0x8000)
+ t[i] = ~s[i];
+ else
+ t[i] = s[i] | 0x8000;
+ }
+
+ //
+ // Find the maximum, tMax, of t[0] ... t[15].
+ //
+
+ unsigned short tMax = 0;
+
+ for (int i = 0; i < 16; ++i)
+ if (tMax < t[i])
+ tMax = t[i];
+
+ //
+ // Compute a set of running differences, r[0] ... r[14]:
+ // Find a shift value such that after rounding off the
+ // rightmost bits and shifting all differenes are between
+ // -32 and +31. Then bias the differences so that they
+ // end up between 0 and 63.
+ //
+
+ int shift = -1;
+ int d[16];
+ int r[15];
+ int rMin;
+ int rMax;
+
+ const int bias = 0x20;
+
+ do
+ {
+ shift += 1;
+
+ //
+ // Compute absolute differences, d[0] ... d[15],
+ // between tMax and t[0] ... t[15].
+ //
+ // Shift and round the absolute differences.
+ //
+
+ for (int i = 0; i < 16; ++i)
+ d[i] = shiftAndRound (tMax - t[i], shift);
+
+ //
+ // Convert d[0] .. d[15] into running differences
+ //
+
+ r[ 0] = d[ 0] - d[ 4] + bias;
+ r[ 1] = d[ 4] - d[ 8] + bias;
+ r[ 2] = d[ 8] - d[12] + bias;
+
+ r[ 3] = d[ 0] - d[ 1] + bias;
+ r[ 4] = d[ 4] - d[ 5] + bias;
+ r[ 5] = d[ 8] - d[ 9] + bias;
+ r[ 6] = d[12] - d[13] + bias;
+
+ r[ 7] = d[ 1] - d[ 2] + bias;
+ r[ 8] = d[ 5] - d[ 6] + bias;
+ r[ 9] = d[ 9] - d[10] + bias;
+ r[10] = d[13] - d[14] + bias;
+
+ r[11] = d[ 2] - d[ 3] + bias;
+ r[12] = d[ 6] - d[ 7] + bias;
+ r[13] = d[10] - d[11] + bias;
+ r[14] = d[14] - d[15] + bias;
+
+ rMin = r[0];
+ rMax = r[0];
+
+ for (int i = 1; i < 15; ++i)
+ {
+ if (rMin > r[i])
+ rMin = r[i];
+
+ if (rMax < r[i])
+ rMax = r[i];
+ }
+ }
+ while (rMin < 0 || rMax > 0x3f);
+
+ if (rMin == bias && rMax == bias && optFlatFields)
+ {
+ //
+ // Special case - all pixels have the same value.
+ // We encode this in 3 instead of 14 bytes by
+ // storing the value 0xfc in the third output byte,
+ // which cannot occur in the 14-byte encoding.
+ //
+
+ b[0] = (t[0] >> 8);
+ b[1] = t[0];
+ b[2] = 0xfc;
+
+ return 3;
+ }
+
+ if (exactMax)
+ {
+ //
+ // Adjust t[0] so that the pixel whose value is equal
+ // to tMax gets represented as accurately as possible.
+ //
+
+ t[0] = tMax - (d[0] << shift);
+ }
+
+ //
+ // Pack t[0], shift and r[0] ... r[14] into 14 bytes:
+ //
+
+ b[ 0] = (t[0] >> 8);
+ b[ 1] = t[0];
+
+ b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4));
+ b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2));
+ b[ 4] = (unsigned char) ((r[ 1] << 6) | r[ 2] );
+
+ b[ 5] = (unsigned char) ((r[ 3] << 2) | (r[ 4] >> 4));
+ b[ 6] = (unsigned char) ((r[ 4] << 4) | (r[ 5] >> 2));
+ b[ 7] = (unsigned char) ((r[ 5] << 6) | r[ 6] );
+
+ b[ 8] = (unsigned char) ((r[ 7] << 2) | (r[ 8] >> 4));
+ b[ 9] = (unsigned char) ((r[ 8] << 4) | (r[ 9] >> 2));
+ b[10] = (unsigned char) ((r[ 9] << 6) | r[10] );
+
+ b[11] = (unsigned char) ((r[11] << 2) | (r[12] >> 4));
+ b[12] = (unsigned char) ((r[12] << 4) | (r[13] >> 2));
+ b[13] = (unsigned char) ((r[13] << 6) | r[14] );
+
+ return 14;
+}
+
+
+inline
+void
+unpack14 (const unsigned char b[14], unsigned short s[16])
+{
+ //
+ // Unpack a 14-byte block into 4 by 4 16-bit pixels.
+ //
+
+ #if defined (DEBUG)
+ assert (b[2] != 0xfc);
+ #endif
+
+ s[ 0] = (b[0] << 8) | b[1];
+
+ unsigned short shift = (b[ 2] >> 2);
+ unsigned short bias = (0x20 << shift);
+
+ s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
+ s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
+ s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) - bias;
+
+ s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) - bias;
+ s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
+ s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
+ s[13] = s[12] + ((b[ 7] & 0x3f) << shift) - bias;
+
+ s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) - bias;
+ s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
+ s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
+ s[14] = s[13] + ((b[10] & 0x3f) << shift) - bias;
+
+ s[ 3] = s[ 2] + ((b[11] >> 2) << shift) - bias;
+ s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
+ s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
+ s[15] = s[14] + ((b[13] & 0x3f) << shift) - bias;
+
+ for (int i = 0; i < 16; ++i)
+ {
+ if (s[i] & 0x8000)
+ s[i] &= 0x7fff;
+ else
+ s[i] = ~s[i];
+ }
+}
+
+
+inline
+void
+unpack3 (const unsigned char b[3], unsigned short s[16])
+{
+ //
+ // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
+ //
+
+ #if defined (DEBUG)
+ assert (b[2] == 0xfc);
+ #endif
+
+ s[0] = (b[0] << 8) | b[1];
+
+ if (s[0] & 0x8000)
+ s[0] &= 0x7fff;
+ else
+ s[0] = ~s[0];
+
+ for (int i = 1; i < 16; ++i)
+ s[i] = s[0];
+}
+
+
+void
+notEnoughData ()
+{
+ throw Iex::InputExc ("Error decompressing data "
+ "(input data are shorter than expected).");
+}
+
+
+void
+tooMuchData ()
+{
+ throw Iex::InputExc ("Error decompressing data "
+ "(input data are longer than expected).");
+}
+
+} // namespace
+
+
+struct B44Compressor::ChannelData
+{
+ unsigned short * start;
+ unsigned short * end;
+ int nx;
+ int ny;
+ int ys;
+ PixelType type;
+ bool pLinear;
+ int size;
+};
+
+
+B44Compressor::B44Compressor
+ (const Header &hdr,
+ int maxScanLineSize,
+ int numScanLines,
+ bool optFlatFields)
+:
+ Compressor (hdr),
+ _maxScanLineSize (maxScanLineSize),
+ _optFlatFields (optFlatFields),
+ _format (XDR),
+ _numScanLines (numScanLines),
+ _tmpBuffer (0),
+ _outBuffer (0),
+ _numChans (0),
+ _channels (hdr.channels()),
+ _channelData (0)
+{
+ //
+ // Allocate buffers for compressed an uncompressed pixel data,
+ // allocate a set of ChannelData structs to help speed up the
+ // compress() and uncompress() functions, below, and determine
+ // if uncompressed pixel data should be in native or Xdr format.
+ //
+
+ _tmpBuffer = new unsigned short [maxScanLineSize * numScanLines];
+
+ const ChannelList &channels = header().channels();
+ int numHalfChans = 0;
+
+ for (ChannelList::ConstIterator c = channels.begin();
+ c != channels.end();
+ ++c)
+ {
+ assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);
+ ++_numChans;
+
+ if (c.channel().type == HALF)
+ ++numHalfChans;
+ }
+
+ //
+ // Compressed data may be larger than the input data
+ //
+
+ int padding = 12 * numHalfChans * (numScanLines + 3) / 4;
+
+ _outBuffer = new char [maxScanLineSize * numScanLines + padding];
+ _channelData = new ChannelData[_numChans];
+
+ int i = 0;
+
+ for (ChannelList::ConstIterator c = channels.begin();
+ c != channels.end();
+ ++c, ++i)
+ {
+ _channelData[i].ys = c.channel().ySampling;
+ _channelData[i].type = c.channel().type;
+ _channelData[i].pLinear = c.channel().pLinear;
+ _channelData[i].size =
+ pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
+ }
+
+ const Box2i &dataWindow = hdr.dataWindow();
+
+ _minX = dataWindow.min.x;
+ _maxX = dataWindow.max.x;
+ _maxY = dataWindow.max.y;
+
+ //
+ // We can support uncompressed data in the machine's native
+ // format only if all image channels are of type HALF.
+ //
+
+ assert (sizeof (unsigned short) == pixelTypeSize (HALF));
+
+ if (_numChans == numHalfChans)
+ _format = NATIVE;
+}
+
+
+B44Compressor::~B44Compressor ()
+{
+ delete [] _tmpBuffer;
+ delete [] _outBuffer;
+ delete [] _channelData;
+}
+
+
+int
+B44Compressor::numScanLines () const
+{
+ return _numScanLines;
+}
+
+
+Compressor::Format
+B44Compressor::format () const
+{
+ return _format;
+}
+
+
+int
+B44Compressor::compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return compress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + numScanLines() - 1)),
+ outPtr);
+}
+
+
+int
+B44Compressor::compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ return compress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+B44Compressor::uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return uncompress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + numScanLines() - 1)),
+ outPtr);
+}
+
+
+int
+B44Compressor::uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ return uncompress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+B44Compressor::compress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ //
+ // Compress a block of pixel data: First copy the input pixels
+ // from the input buffer into _tmpBuffer, rearranging them such
+ // that blocks of 4x4 pixels of a single channel can be accessed
+ // conveniently. Then compress each 4x4 block of HALF pixel data
+ // and append the result to the output buffer. Copy UINT and
+ // FLOAT data to the output buffer without compressing them.
+ //
+
+ outPtr = _outBuffer;
+
+ if (inSize == 0)
+ {
+ //
+ // Special case - empty input buffer.
+ //
+
+ return 0;
+ }
+
+ //
+ // For each channel, detemine how many pixels are stored
+ // in the input buffer, and where those pixels will be
+ // placed in _tmpBuffer.
+ //
+
+ int minX = range.min.x;
+ int maxX = min (range.max.x, _maxX);
+ int minY = range.min.y;
+ int maxY = min (range.max.y, _maxY);
+
+ unsigned short *tmpBufferEnd = _tmpBuffer;
+ int i = 0;
+
+ for (ChannelList::ConstIterator c = _channels.begin();
+ c != _channels.end();
+ ++c, ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ cd.start = tmpBufferEnd;
+ cd.end = cd.start;
+
+ cd.nx = numSamples (c.channel().xSampling, minX, maxX);
+ cd.ny = numSamples (c.channel().ySampling, minY, maxY);
+
+ tmpBufferEnd += cd.nx * cd.ny * cd.size;
+ }
+
+ if (_format == XDR)
+ {
+ //
+ // The data in the input buffer are in the machine-independent
+ // Xdr format. Copy the HALF channels into _tmpBuffer and
+ // convert them back into native format for compression.
+ // Copy UINT and FLOAT channels verbatim into _tmpBuffer.
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ if (cd.type == HALF)
+ {
+ for (int x = cd.nx; x > 0; --x)
+ {
+ Xdr::read <CharPtrIO> (inPtr, *cd.end);
+ ++cd.end;
+ }
+ }
+ else
+ {
+ int n = cd.nx * cd.size;
+ memcpy (cd.end, inPtr, n * sizeof (unsigned short));
+ inPtr += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+ }
+ else
+ {
+ //
+ // The input buffer contains only HALF channels, and they
+ // are in native, machine-dependent format. Copy the pixels
+ // into _tmpBuffer.
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ #if defined (DEBUG)
+ assert (cd.type == HALF);
+ #endif
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ int n = cd.nx * cd.size;
+ memcpy (cd.end, inPtr, n * sizeof (unsigned short));
+ inPtr += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+
+ //
+ // The pixels for each channel have been packed into a contiguous
+ // block in _tmpBuffer. HALF channels are in native format; UINT
+ // and FLOAT channels are in Xdr format.
+ //
+
+ #if defined (DEBUG)
+
+ for (int i = 1; i < _numChans; ++i)
+ assert (_channelData[i-1].end == _channelData[i].start);
+
+ assert (_channelData[_numChans-1].end == tmpBufferEnd);
+
+ #endif
+
+ //
+ // For each HALF channel, split the data in _tmpBuffer into 4x4
+ // pixel blocks. Compress each block and append the compressed
+ // data to the output buffer.
+ //
+ // UINT and FLOAT channels are copied from _tmpBuffer into the
+ // output buffer without further processing.
+ //
+
+ char *outEnd = _outBuffer;
+
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (cd.type != HALF)
+ {
+ //
+ // UINT or FLOAT channel.
+ //
+
+ int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
+ memcpy (outEnd, cd.start, n);
+ outEnd += n;
+
+ continue;
+ }
+
+ //
+ // HALF channel
+ //
+
+ for (int y = 0; y < cd.ny; y += 4)
+ {
+ //
+ // Copy the next 4x4 pixel block into array s.
+ // If the width, cd.nx, or the height, cd.ny, of
+ // the pixel data in _tmpBuffer is not divisible
+ // by 4, then pad the data by repeating the
+ // rightmost column and the bottom row.
+ //
+
+ unsigned short *row0 = cd.start + y * cd.nx;
+ unsigned short *row1 = row0 + cd.nx;
+ unsigned short *row2 = row1 + cd.nx;
+ unsigned short *row3 = row2 + cd.nx;
+
+ if (y + 3 >= cd.ny)
+ {
+ if (y + 1 >= cd.ny)
+ row1 = row0;
+
+ if (y + 2 >= cd.ny)
+ row2 = row1;
+
+ row3 = row2;
+ }
+
+ for (int x = 0; x < cd.nx; x += 4)
+ {
+ unsigned short s[16];
+
+ if (x + 3 >= cd.nx)
+ {
+ int n = cd.nx - x;
+
+ for (int i = 0; i < 4; ++i)
+ {
+ int j = min (i, n - 1);
+
+ s[i + 0] = row0[j];
+ s[i + 4] = row1[j];
+ s[i + 8] = row2[j];
+ s[i + 12] = row3[j];
+ }
+ }
+ else
+ {
+ memcpy (&s[ 0], row0, 4 * sizeof (unsigned short));
+ memcpy (&s[ 4], row1, 4 * sizeof (unsigned short));
+ memcpy (&s[ 8], row2, 4 * sizeof (unsigned short));
+ memcpy (&s[12], row3, 4 * sizeof (unsigned short));
+ }
+
+ row0 += 4;
+ row1 += 4;
+ row2 += 4;
+ row3 += 4;
+
+ //
+ // Compress the contents of array s and append the
+ // results to the output buffer.
+ //
+
+ if (cd.pLinear)
+ convertFromLinear (s);
+
+ outEnd += pack (s, (unsigned char *) outEnd,
+ _optFlatFields, !cd.pLinear);
+ }
+ }
+ }
+
+ return outEnd - _outBuffer;
+}
+
+
+int
+B44Compressor::uncompress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ //
+ // This function is the reverse of the compress() function,
+ // above. First all pixels are moved from the input buffer
+ // into _tmpBuffer. UINT and FLOAT channels are copied
+ // verbatim; HALF channels are uncompressed in blocks of
+ // 4x4 pixels. Then the pixels in _tmpBuffer are copied
+ // into the output buffer and rearranged such that the data
+ // for for each scan line form a contiguous block.
+ //
+
+ outPtr = _outBuffer;
+
+ if (inSize == 0)
+ {
+ return 0;
+ }
+
+ int minX = range.min.x;
+ int maxX = min (range.max.x, _maxX);
+ int minY = range.min.y;
+ int maxY = min (range.max.y, _maxY);
+
+ unsigned short *tmpBufferEnd = _tmpBuffer;
+ int i = 0;
+
+ for (ChannelList::ConstIterator c = _channels.begin();
+ c != _channels.end();
+ ++c, ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ cd.start = tmpBufferEnd;
+ cd.end = cd.start;
+
+ cd.nx = numSamples (c.channel().xSampling, minX, maxX);
+ cd.ny = numSamples (c.channel().ySampling, minY, maxY);
+
+ tmpBufferEnd += cd.nx * cd.ny * cd.size;
+ }
+
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (cd.type != HALF)
+ {
+ //
+ // UINT or FLOAT channel.
+ //
+
+ int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
+
+ if (inSize < n)
+ notEnoughData();
+
+ memcpy (cd.start, inPtr, n);
+ inPtr += n;
+ inSize -= n;
+
+ continue;
+ }
+
+ //
+ // HALF channel
+ //
+
+ for (int y = 0; y < cd.ny; y += 4)
+ {
+ unsigned short *row0 = cd.start + y * cd.nx;
+ unsigned short *row1 = row0 + cd.nx;
+ unsigned short *row2 = row1 + cd.nx;
+ unsigned short *row3 = row2 + cd.nx;
+
+ for (int x = 0; x < cd.nx; x += 4)
+ {
+ unsigned short s[16];
+
+ if (inSize < 3)
+ notEnoughData();
+
+ if (((const unsigned char *)inPtr)[2] == 0xfc)
+ {
+ unpack3 ((const unsigned char *)inPtr, s);
+ inPtr += 3;
+ inSize -= 3;
+ }
+ else
+ {
+ if (inSize < 14)
+ notEnoughData();
+
+ unpack14 ((const unsigned char *)inPtr, s);
+ inPtr += 14;
+ inSize -= 14;
+ }
+
+ if (cd.pLinear)
+ convertToLinear (s);
+
+ int n = (x + 3 < cd.nx)?
+ 4 * sizeof (unsigned short) :
+ (cd.nx - x) * sizeof (unsigned short);
+
+ if (y + 3 < cd.ny)
+ {
+ memcpy (row0, &s[ 0], n);
+ memcpy (row1, &s[ 4], n);
+ memcpy (row2, &s[ 8], n);
+ memcpy (row3, &s[12], n);
+ }
+ else
+ {
+ memcpy (row0, &s[ 0], n);
+
+ if (y + 1 < cd.ny)
+ memcpy (row1, &s[ 4], n);
+
+ if (y + 2 < cd.ny)
+ memcpy (row2, &s[ 8], n);
+ }
+
+ row0 += 4;
+ row1 += 4;
+ row2 += 4;
+ row3 += 4;
+ }
+ }
+ }
+
+ char *outEnd = _outBuffer;
+
+ if (_format == XDR)
+ {
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ if (cd.type == HALF)
+ {
+ for (int x = cd.nx; x > 0; --x)
+ {
+ Xdr::write <CharPtrIO> (outEnd, *cd.end);
+ ++cd.end;
+ }
+ }
+ else
+ {
+ int n = cd.nx * cd.size;
+ memcpy (outEnd, cd.end, n * sizeof (unsigned short));
+ outEnd += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ #if defined (DEBUG)
+ assert (cd.type == HALF);
+ #endif
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ int n = cd.nx * cd.size;
+ memcpy (outEnd, cd.end, n * sizeof (unsigned short));
+ outEnd += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+
+ #if defined (DEBUG)
+
+ for (int i = 1; i < _numChans; ++i)
+ assert (_channelData[i-1].end == _channelData[i].start);
+
+ assert (_channelData[_numChans-1].end == tmpBufferEnd);
+
+ #endif
+
+ if (inSize > 0)
+ tooMuchData();
+
+ outPtr = _outBuffer;
+ return outEnd - _outBuffer;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfB44Compressor.h b/Source/OpenEXR/IlmImf/ImfB44Compressor.h
new file mode 100644
index 0000000..b426927
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfB44Compressor.h
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_B44_COMPRESSOR_H
+#define INCLUDED_IMF_B44_COMPRESSOR_H
+
+//-----------------------------------------------------------------------------
+//
+// class B44Compressor -- lossy compression of 4x4 pixel blocks
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+class ChannelList;
+
+
+class B44Compressor: public Compressor
+{
+ public:
+
+ B44Compressor (const Header &hdr,
+ int maxScanLineSize,
+ int numScanLines,
+ bool optFlatFields);
+
+ virtual ~B44Compressor ();
+
+ virtual int numScanLines () const;
+
+ virtual Format format () const;
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+ private:
+
+ struct ChannelData;
+
+ int compress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int uncompress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int _maxScanLineSize;
+ bool _optFlatFields;
+ Format _format;
+ int _numScanLines;
+ unsigned short * _tmpBuffer;
+ char * _outBuffer;
+ int _numChans;
+ const ChannelList & _channels;
+ ChannelData * _channelData;
+ int _minX;
+ int _maxX;
+ int _maxY;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfBoxAttribute.cpp b/Source/OpenEXR/IlmImf/ImfBoxAttribute.cpp
new file mode 100644
index 0000000..d275d11
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfBoxAttribute.cpp
@@ -0,0 +1,110 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Box2iAttribute
+// class Box2fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfBoxAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+Box2iAttribute::staticTypeName ()
+{
+ return "box2i";
+}
+
+
+template <>
+void
+Box2iAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.min.x);
+ Xdr::write <StreamIO> (os, _value.min.y);
+ Xdr::write <StreamIO> (os, _value.max.x);
+ Xdr::write <StreamIO> (os, _value.max.y);
+}
+
+
+template <>
+void
+Box2iAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.min.x);
+ Xdr::read <StreamIO> (is, _value.min.y);
+ Xdr::read <StreamIO> (is, _value.max.x);
+ Xdr::read <StreamIO> (is, _value.max.y);
+}
+
+
+template <>
+const char *
+Box2fAttribute::staticTypeName ()
+{
+ return "box2f";
+}
+
+
+template <>
+void
+Box2fAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.min.x);
+ Xdr::write <StreamIO> (os, _value.min.y);
+ Xdr::write <StreamIO> (os, _value.max.x);
+ Xdr::write <StreamIO> (os, _value.max.y);
+}
+
+
+template <>
+void
+Box2fAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.min.x);
+ Xdr::read <StreamIO> (is, _value.min.y);
+ Xdr::read <StreamIO> (is, _value.max.x);
+ Xdr::read <StreamIO> (is, _value.max.y);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfBoxAttribute.h b/Source/OpenEXR/IlmImf/ImfBoxAttribute.h
new file mode 100644
index 0000000..fe35391
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfBoxAttribute.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_BOX_ATTRIBUTE_H
+#define INCLUDED_IMF_BOX_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class Box2iAttribute
+// class Box2fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include "ImathBox.h"
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Imath::Box2i> Box2iAttribute;
+template <> const char *Box2iAttribute::staticTypeName ();
+template <> void Box2iAttribute::writeValueTo (OStream &, int) const;
+template <> void Box2iAttribute::readValueFrom (IStream &, int, int);
+
+
+typedef TypedAttribute<Imath::Box2f> Box2fAttribute;
+template <> const char *Box2fAttribute::staticTypeName ();
+template <> void Box2fAttribute::writeValueTo (OStream &, int) const;
+template <> void Box2fAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfBoxAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfCRgbaFile.cpp b/Source/OpenEXR/IlmImf/ImfCRgbaFile.cpp
new file mode 100644
index 0000000..1fcf8c6
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCRgbaFile.cpp
@@ -0,0 +1,1434 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// C interface to C++ classes Imf::RgbaOutputFile and Imf::RgbaInputFile
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ImfCRgbaFile.h>
+#include <ImfRgbaFile.h>
+#include <ImfTiledRgbaFile.h>
+#include <ImfIntAttribute.h>
+#include <ImfFloatAttribute.h>
+#include <ImfDoubleAttribute.h>
+#include <ImfStringAttribute.h>
+#include <ImfBoxAttribute.h>
+#include <ImfVecAttribute.h>
+#include <ImfMatrixAttribute.h>
+#include <ImfChannelList.h>
+#include <ImfLut.h>
+#include "half.h"
+#include <string.h>
+
+using Imath::Box2i;
+using Imath::Box2f;
+using Imath::V2i;
+using Imath::V2f;
+using Imath::V3i;
+using Imath::V3f;
+using Imath::M33f;
+using Imath::M44f;
+
+
+namespace {
+
+
+const int MAX_ERR_LENGTH = 1024;
+char errorMessage[MAX_ERR_LENGTH];
+
+
+void
+setErrorMessage (const std::exception &e)
+{
+ strncpy (errorMessage, e.what(), MAX_ERR_LENGTH - 1);
+ errorMessage[MAX_ERR_LENGTH - 1] = 0;
+}
+
+
+inline Imf::Header *
+header (ImfHeader *hdr)
+{
+ return (Imf::Header *)(hdr);
+}
+
+
+inline const Imf::Header *
+header (const ImfHeader *hdr)
+{
+ return (const Imf::Header *)(hdr);
+}
+
+
+inline Imf::RgbaOutputFile *
+outfile (ImfOutputFile *out)
+{
+ return (Imf::RgbaOutputFile *) out;
+}
+
+
+inline const Imf::RgbaOutputFile *
+outfile (const ImfOutputFile *out)
+{
+ return (const Imf::RgbaOutputFile *) out;
+}
+
+
+inline Imf::TiledRgbaOutputFile *
+outfile (ImfTiledOutputFile *out)
+{
+ return (Imf::TiledRgbaOutputFile *) out;
+}
+
+
+inline const Imf::TiledRgbaOutputFile *
+outfile (const ImfTiledOutputFile *out)
+{
+ return (const Imf::TiledRgbaOutputFile *) out;
+}
+
+
+inline Imf::RgbaInputFile *
+infile (ImfInputFile *in)
+{
+ return (Imf::RgbaInputFile *) in;
+}
+
+
+inline const Imf::RgbaInputFile *
+infile (const ImfInputFile *in)
+{
+ return (const Imf::RgbaInputFile *) in;
+}
+
+
+inline Imf::TiledRgbaInputFile *
+infile (ImfTiledInputFile *in)
+{
+ return (Imf::TiledRgbaInputFile *) in;
+}
+
+
+inline const Imf::TiledRgbaInputFile *
+infile (const ImfTiledInputFile *in)
+{
+ return (const Imf::TiledRgbaInputFile *) in;
+}
+
+
+} // namespace
+
+
+void
+ImfFloatToHalf (float f, ImfHalf *h)
+{
+ *h = half(f).bits();
+}
+
+
+void
+ImfFloatToHalfArray (int n, const float f[/*n*/], ImfHalf h[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ h[i] = half(f[i]).bits();
+}
+
+
+float
+ImfHalfToFloat (ImfHalf h)
+{
+ return float (*((half *)&h));
+}
+
+
+void
+ImfHalfToFloatArray (int n, const ImfHalf h[/*n*/], float f[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ f[i] = float (*((half *)(h + i)));
+}
+
+
+ImfHeader *
+ImfNewHeader (void)
+{
+ try
+ {
+ return (ImfHeader *) new Imf::Header;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+void
+ImfDeleteHeader (ImfHeader *hdr)
+{
+ delete header (hdr);
+}
+
+
+ImfHeader *
+ImfCopyHeader (const ImfHeader *hdr)
+{
+ try
+ {
+ return (ImfHeader *) new Imf::Header (*header (hdr));
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+void
+ImfHeaderSetDisplayWindow (ImfHeader *hdr,
+ int xMin, int yMin,
+ int xMax, int yMax)
+{
+ header(hdr)->displayWindow() = Box2i (V2i (xMin, yMin), V2i (xMax, yMax));
+}
+
+
+void
+ImfHeaderDisplayWindow (const ImfHeader *hdr,
+ int *xMin, int *yMin,
+ int *xMax, int *yMax)
+{
+ const Box2i dw = header(hdr)->displayWindow();
+ *xMin = dw.min.x;
+ *yMin = dw.min.y;
+ *xMax = dw.max.x;
+ *yMax = dw.max.y;
+}
+
+
+void
+ImfHeaderSetDataWindow (ImfHeader *hdr,
+ int xMin, int yMin,
+ int xMax, int yMax)
+{
+ header(hdr)->dataWindow() = Box2i (V2i (xMin, yMin), V2i (xMax, yMax));
+}
+
+
+void
+ImfHeaderDataWindow (const ImfHeader *hdr,
+ int *xMin, int *yMin,
+ int *xMax, int *yMax)
+{
+ const Box2i dw = header(hdr)->dataWindow();
+ *xMin = dw.min.x;
+ *yMin = dw.min.y;
+ *xMax = dw.max.x;
+ *yMax = dw.max.y;
+}
+
+
+void
+ImfHeaderSetPixelAspectRatio (ImfHeader *hdr, float pixelAspectRatio)
+{
+ header(hdr)->pixelAspectRatio() = pixelAspectRatio;
+}
+
+
+float
+ImfHeaderPixelAspectRatio (const ImfHeader *hdr)
+{
+ return header(hdr)->pixelAspectRatio();
+}
+
+
+void
+ImfHeaderSetScreenWindowCenter (ImfHeader *hdr, float x, float y)
+{
+ header(hdr)->screenWindowCenter() = V2f (x, y);
+}
+
+
+void
+ImfHeaderScreenWindowCenter (const ImfHeader *hdr, float *x, float *y)
+{
+ const V2i &swc = header(hdr)->screenWindowCenter();
+ *x = swc.x;
+ *y = swc.y;
+}
+
+
+void
+ImfHeaderSetScreenWindowWidth (ImfHeader *hdr, float width)
+{
+ header(hdr)->screenWindowWidth() = width;
+}
+
+
+float
+ImfHeaderScreenWindowWidth (const ImfHeader *hdr)
+{
+ return header(hdr)->screenWindowWidth();
+}
+
+
+void
+ImfHeaderSetLineOrder (ImfHeader *hdr, int lineOrder)
+{
+ header(hdr)->lineOrder() = Imf::LineOrder (lineOrder);
+}
+
+
+int
+ImfHeaderLineOrder (const ImfHeader *hdr)
+{
+ return header(hdr)->lineOrder();
+}
+
+
+void
+ImfHeaderSetCompression (ImfHeader *hdr, int compression)
+{
+ header(hdr)->compression() = Imf::Compression (compression);
+}
+
+
+int
+ImfHeaderCompression (const ImfHeader *hdr)
+{
+ return header(hdr)->compression();
+}
+
+
+int
+ImfHeaderSetIntAttribute (ImfHeader *hdr, const char name[], int value)
+{
+ try
+ {
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::IntAttribute (value));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::IntAttribute>(name).value() =
+ value;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderIntAttribute (const ImfHeader *hdr, const char name[], int *value)
+{
+ try
+ {
+ *value = header(hdr)->typedAttribute<Imf::IntAttribute>(name).value();
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetFloatAttribute (ImfHeader *hdr, const char name[], float value)
+{
+ try
+ {
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::FloatAttribute (value));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::FloatAttribute>(name).value() =
+ value;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetDoubleAttribute (ImfHeader *hdr, const char name[], double value)
+{
+ try
+ {
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::DoubleAttribute (value));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::DoubleAttribute>(name).value() =
+ value;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderFloatAttribute (const ImfHeader *hdr, const char name[], float *value)
+{
+ try
+ {
+ *value = header(hdr)->typedAttribute<Imf::FloatAttribute>(name).value();
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderDoubleAttribute (const ImfHeader *hdr,
+ const char name[],
+ double *value)
+{
+ try
+ {
+ *value = header(hdr)->
+ typedAttribute<Imf::DoubleAttribute>(name).value();
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetStringAttribute (ImfHeader *hdr,
+ const char name[],
+ const char value[])
+{
+ try
+ {
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::StringAttribute (value));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::StringAttribute>(name).value() =
+ value;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderStringAttribute (const ImfHeader *hdr,
+ const char name[],
+ const char **value)
+{
+ try
+ {
+ *value = header(hdr)->
+ typedAttribute<Imf::StringAttribute>(name).value().c_str();
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetBox2iAttribute (ImfHeader *hdr,
+ const char name[],
+ int xMin, int yMin,
+ int xMax, int yMax)
+{
+ try
+ {
+ Box2i box (V2i (xMin, yMin), V2i (xMax, yMax));
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::Box2iAttribute (box));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::Box2iAttribute>(name).value() =
+ box;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderBox2iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *xMin, int *yMin,
+ int *xMax, int *yMax)
+{
+ try
+ {
+ const Box2i &box =
+ header(hdr)->typedAttribute<Imf::Box2iAttribute>(name).value();
+
+ *xMin = box.min.x;
+ *yMin = box.min.y;
+ *xMax = box.max.x;
+ *yMax = box.max.y;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetBox2fAttribute (ImfHeader *hdr,
+ const char name[],
+ float xMin, float yMin,
+ float xMax, float yMax)
+{
+ try
+ {
+ Box2f box (V2f (xMin, yMin), V2f (xMax, yMax));
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ {
+ header(hdr)->insert (name, Imf::Box2fAttribute (box));
+ }
+ else
+ {
+ header(hdr)->typedAttribute<Imf::Box2fAttribute>(name).value() =
+ box;
+ }
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderBox2fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *xMin, float *yMin,
+ float *xMax, float *yMax)
+{
+ try
+ {
+ const Box2f &box =
+ header(hdr)->typedAttribute<Imf::Box2fAttribute>(name).value();
+
+ *xMin = box.min.x;
+ *yMin = box.min.y;
+ *xMax = box.max.x;
+ *yMax = box.max.y;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetV2iAttribute (ImfHeader *hdr,
+ const char name[],
+ int x, int y)
+{
+ try
+ {
+ V2i v (x, y);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::V2iAttribute (v));
+ else
+ header(hdr)->typedAttribute<Imf::V2iAttribute>(name).value() = v;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderV2iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *x, int *y)
+{
+ try
+ {
+ const V2i &v =
+ header(hdr)->typedAttribute<Imf::V2iAttribute>(name).value();
+
+ *x = v.x;
+ *y = v.y;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetV2fAttribute (ImfHeader *hdr,
+ const char name[],
+ float x, float y)
+{
+ try
+ {
+ V2f v (x, y);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::V2fAttribute (v));
+ else
+ header(hdr)->typedAttribute<Imf::V2fAttribute>(name).value() = v;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderV2fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *x, float *y)
+{
+ try
+ {
+ const V2f &v =
+ header(hdr)->typedAttribute<Imf::V2fAttribute>(name).value();
+
+ *x = v.x;
+ *y = v.y;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetV3iAttribute (ImfHeader *hdr,
+ const char name[],
+ int x, int y, int z)
+{
+ try
+ {
+ V3i v (x, y, z);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::V3iAttribute (v));
+ else
+ header(hdr)->typedAttribute<Imf::V3iAttribute>(name).value() = v;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderV3iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *x, int *y, int *z)
+{
+ try
+ {
+ const V3i &v =
+ header(hdr)->typedAttribute<Imf::V3iAttribute>(name).value();
+
+ *x = v.x;
+ *y = v.y;
+ *z = v.z;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetV3fAttribute (ImfHeader *hdr,
+ const char name[],
+ float x, float y, float z)
+{
+ try
+ {
+ V3f v (x, y, z);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::V3fAttribute (v));
+ else
+ header(hdr)->typedAttribute<Imf::V3fAttribute>(name).value() = v;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderV3fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *x, float *y, float *z)
+{
+ try
+ {
+ const V3f &v =
+ header(hdr)->typedAttribute<Imf::V3fAttribute>(name).value();
+
+ *x = v.x;
+ *y = v.y;
+ *z = v.z;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetM33fAttribute (ImfHeader *hdr,
+ const char name[],
+ const float m[3][3])
+{
+ try
+ {
+ M33f m3 (m);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::M33fAttribute (m3));
+ else
+ header(hdr)->typedAttribute<Imf::M33fAttribute>(name).value() = m3;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderM33fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float m[3][3])
+{
+ try
+ {
+ const M33f &m3 =
+ header(hdr)->typedAttribute<Imf::M33fAttribute>(name).value();
+
+ m[0][0] = m3[0][0];
+ m[0][1] = m3[0][1];
+ m[0][2] = m3[0][2];
+
+ m[1][0] = m3[1][0];
+ m[1][1] = m3[1][1];
+ m[1][2] = m3[1][2];
+
+ m[2][0] = m3[2][0];
+ m[2][1] = m3[2][1];
+ m[2][2] = m3[2][2];
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderSetM44fAttribute (ImfHeader *hdr,
+ const char name[],
+ const float m[4][4])
+{
+ try
+ {
+ M44f m4 (m);
+
+ if (header(hdr)->find(name) == header(hdr)->end())
+ header(hdr)->insert (name, Imf::M44fAttribute (m4));
+ else
+ header(hdr)->typedAttribute<Imf::M44fAttribute>(name).value() = m4;
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfHeaderM44fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float m[4][4])
+{
+ try
+ {
+ const M44f &m4 =
+ header(hdr)->typedAttribute<Imf::M44fAttribute>(name).value();
+
+ m[0][0] = m4[0][0];
+ m[0][1] = m4[0][1];
+ m[0][2] = m4[0][2];
+ m[0][3] = m4[0][3];
+
+ m[1][0] = m4[1][0];
+ m[1][1] = m4[1][1];
+ m[1][2] = m4[1][2];
+ m[1][3] = m4[1][3];
+
+ m[2][0] = m4[2][0];
+ m[2][1] = m4[2][1];
+ m[2][2] = m4[2][2];
+ m[2][3] = m4[2][3];
+
+ m[3][0] = m4[3][0];
+ m[3][1] = m4[3][1];
+ m[3][2] = m4[3][2];
+ m[3][3] = m4[3][3];
+
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+ImfOutputFile *
+ImfOpenOutputFile (const char name[], const ImfHeader *hdr, int channels)
+{
+ try
+ {
+ return (ImfOutputFile *) new Imf::RgbaOutputFile
+ (name, *header(hdr), Imf::RgbaChannels (channels));
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfCloseOutputFile (ImfOutputFile *out)
+{
+ try
+ {
+ delete outfile (out);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfOutputSetFrameBuffer (ImfOutputFile *out,
+ const ImfRgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ try
+ {
+ outfile(out)->setFrameBuffer ((Imf::Rgba *)base, xStride, yStride);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfOutputWritePixels (ImfOutputFile *out, int numScanLines)
+{
+ try
+ {
+ outfile(out)->writePixels (numScanLines);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfOutputCurrentScanLine (const ImfOutputFile *out)
+{
+ return outfile(out)->currentScanLine();
+}
+
+
+const ImfHeader *
+ImfOutputHeader (const ImfOutputFile *out)
+{
+ return (const ImfHeader *) &outfile(out)->header();
+}
+
+
+int
+ImfOutputChannels (const ImfOutputFile *out)
+{
+ return outfile(out)->channels();
+}
+
+
+ImfTiledOutputFile *
+ImfOpenTiledOutputFile (const char name[],
+ const ImfHeader *hdr,
+ int channels,
+ int xSize, int ySize,
+ int mode, int rmode)
+{
+ try
+ {
+ return (ImfTiledOutputFile *) new Imf::TiledRgbaOutputFile
+ (name, *header(hdr),
+ Imf::RgbaChannels (channels),
+ xSize, ySize,
+ Imf::LevelMode (mode),
+ Imf::LevelRoundingMode (rmode));
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfCloseTiledOutputFile (ImfTiledOutputFile *out)
+{
+ try
+ {
+ delete outfile (out);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledOutputSetFrameBuffer (ImfTiledOutputFile *out,
+ const ImfRgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ try
+ {
+ outfile(out)->setFrameBuffer ((Imf::Rgba *)base, xStride, yStride);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledOutputWriteTile (ImfTiledOutputFile *out,
+ int dx, int dy,
+ int lx, int ly)
+{
+ try
+ {
+ outfile(out)->writeTile (dx, dy, lx, ly);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledOutputWriteTiles (ImfTiledOutputFile *out,
+ int dxMin, int dxMax,
+ int dyMin, int dyMax,
+ int lx, int ly)
+{
+ try
+ {
+ outfile(out)->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+const ImfHeader *
+ImfTiledOutputHeader (const ImfTiledOutputFile *out)
+{
+ return (const ImfHeader *) &outfile(out)->header();
+}
+
+
+int
+ImfTiledOutputChannels (const ImfTiledOutputFile *out)
+{
+ return outfile(out)->channels();
+}
+
+
+int
+ImfTiledOutputTileXSize (const ImfTiledOutputFile *out)
+{
+ return outfile(out)->tileXSize();
+}
+
+
+int
+ImfTiledOutputTileYSize (const ImfTiledOutputFile *out)
+{
+ return outfile(out)->tileYSize();
+}
+
+
+int
+ImfTiledOutputLevelMode (const ImfTiledOutputFile *out)
+{
+ return outfile(out)->levelMode();
+}
+
+
+int
+ImfTiledOutputLevelRoundingMode (const ImfTiledOutputFile *out)
+{
+ return outfile(out)->levelRoundingMode();
+}
+
+
+ImfInputFile *
+ImfOpenInputFile (const char name[])
+{
+ try
+ {
+ return (ImfInputFile *) new Imf::RgbaInputFile (name);
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfCloseInputFile (ImfInputFile *in)
+{
+ try
+ {
+ delete infile (in);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfInputSetFrameBuffer (ImfInputFile *in,
+ ImfRgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ try
+ {
+ infile(in)->setFrameBuffer ((Imf::Rgba *) base, xStride, yStride);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfInputReadPixels (ImfInputFile *in, int scanLine1, int scanLine2)
+{
+ try
+ {
+ infile(in)->readPixels (scanLine1, scanLine2);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+const ImfHeader *
+ImfInputHeader (const ImfInputFile *in)
+{
+ return (const ImfHeader *) &infile(in)->header();
+}
+
+
+int
+ImfInputChannels (const ImfInputFile *in)
+{
+ return infile(in)->channels();
+}
+
+
+const char *
+ImfInputFileName (const ImfInputFile *in)
+{
+ return infile(in)->fileName();
+}
+
+
+ImfTiledInputFile *
+ImfOpenTiledInputFile (const char name[])
+{
+ try
+ {
+ return (ImfTiledInputFile *) new Imf::TiledRgbaInputFile (name);
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfCloseTiledInputFile (ImfTiledInputFile *in)
+{
+ try
+ {
+ delete infile (in);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledInputSetFrameBuffer (ImfTiledInputFile *in,
+ ImfRgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ try
+ {
+ infile(in)->setFrameBuffer ((Imf::Rgba *) base, xStride, yStride);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledInputReadTile (ImfTiledInputFile *in,
+ int dx, int dy,
+ int lx, int ly)
+{
+ try
+ {
+ infile(in)->readTile (dx, dy, lx, ly);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+int
+ImfTiledInputReadTiles (ImfTiledInputFile *in,
+ int dxMin, int dxMax,
+ int dyMin, int dyMax,
+ int lx, int ly)
+{
+ try
+ {
+ infile(in)->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
+ return 1;
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+const ImfHeader *
+ImfTiledInputHeader (const ImfTiledInputFile *in)
+{
+ return (const ImfHeader *) &infile(in)->header();
+}
+
+
+int
+ImfTiledInputChannels (const ImfTiledInputFile *in)
+{
+ return infile(in)->channels();
+}
+
+
+const char *
+ImfTiledInputFileName (const ImfTiledInputFile *in)
+{
+ return infile(in)->fileName();
+}
+
+
+int
+ImfTiledInputTileXSize (const ImfTiledInputFile *in)
+{
+ return infile(in)->tileXSize();
+}
+
+
+int
+ImfTiledInputTileYSize (const ImfTiledInputFile *in)
+{
+ return infile(in)->tileYSize();
+}
+
+
+int
+ImfTiledInputLevelMode (const ImfTiledInputFile *in)
+{
+ return infile(in)->levelMode();
+}
+
+
+int
+ImfTiledInputLevelRoundingMode (const ImfTiledInputFile *in)
+{
+ return infile(in)->levelRoundingMode();
+}
+
+
+ImfLut *
+ImfNewRound12logLut (int channels)
+{
+ try
+ {
+ return (ImfLut *) new Imf::RgbaLut
+ (Imf::round12log, Imf::RgbaChannels (channels));
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+ImfLut *
+ImfNewRoundNBitLut (unsigned int n, int channels)
+{
+ try
+ {
+ return (ImfLut *) new Imf::RgbaLut
+ (Imf::roundNBit (n), Imf::RgbaChannels (channels));
+ }
+ catch (const std::exception &e)
+ {
+ setErrorMessage (e);
+ return 0;
+ }
+}
+
+
+void
+ImfDeleteLut (ImfLut *lut)
+{
+ delete (Imf::RgbaLut *) lut;
+}
+
+
+void
+ImfApplyLut (ImfLut *lut, ImfRgba *data, int nData, int stride)
+{
+ ((Imf::RgbaLut *)lut)->apply ((Imf::Rgba *)data, nData, stride);
+}
+
+
+const char *
+ImfErrorMessage ()
+{
+ return errorMessage;
+}
diff --git a/Source/OpenEXR/IlmImf/ImfCRgbaFile.h b/Source/OpenEXR/IlmImf/ImfCRgbaFile.h
new file mode 100644
index 0000000..e3dc1ce
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCRgbaFile.h
@@ -0,0 +1,467 @@
+/*
+
+Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+Digital Ltd. LLC
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+* Neither the name of Industrial Light & Magic nor the names of
+its contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#ifndef INCLUDED_IMF_C_RGBA_FILE_H
+#define INCLUDED_IMF_C_RGBA_FILE_H
+
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Interpreting unsigned shorts as 16-bit floating point numbers
+*/
+
+typedef unsigned short ImfHalf;
+
+void ImfFloatToHalf (float f,
+ ImfHalf *h);
+
+void ImfFloatToHalfArray (int n,
+ const float f[/*n*/],
+ ImfHalf h[/*n*/]);
+
+float ImfHalfToFloat (ImfHalf h);
+
+void ImfHalfToFloatArray (int n,
+ const ImfHalf h[/*n*/],
+ float f[/*n*/]);
+
+/*
+** RGBA pixel; memory layout must be the same as struct Imf::Rgba.
+*/
+
+struct ImfRgba
+{
+ ImfHalf r;
+ ImfHalf g;
+ ImfHalf b;
+ ImfHalf a;
+};
+
+typedef struct ImfRgba ImfRgba;
+
+/*
+** Magic number; this must be the same as Imf::MAGIC
+*/
+
+#define IMF_MAGIC 20000630
+
+/*
+** Version number; this must be the same as Imf::EXR_VERSION
+*/
+
+#define IMF_VERSION_NUMBER 2
+
+/*
+** Line order; values must the the same as in Imf::LineOrder.
+*/
+
+#define IMF_INCREASING_Y 0
+#define IMF_DECREASING_Y 1
+#define IMF_RAMDOM_Y 2
+
+
+/*
+** Compression types; values must be the same as in Imf::Compression.
+*/
+
+#define IMF_NO_COMPRESSION 0
+#define IMF_RLE_COMPRESSION 1
+#define IMF_ZIPS_COMPRESSION 2
+#define IMF_ZIP_COMPRESSION 3
+#define IMF_PIZ_COMPRESSION 4
+#define IMF_PXR24_COMPRESSION 5
+#define IMF_B44_COMPRESSION 6
+#define IMF_B44A_COMPRESSION 7
+
+
+/*
+** Channels; values must be the same as in Imf::RgbaChannels.
+*/
+
+#define IMF_WRITE_R 0x01
+#define IMF_WRITE_G 0x02
+#define IMF_WRITE_B 0x04
+#define IMF_WRITE_A 0x08
+#define IMF_WRITE_Y 0x10
+#define IMF_WRITE_C 0x20
+#define IMF_WRITE_RGB 0x07
+#define IMF_WRITE_RGBA 0x0f
+#define IMF_WRITE_YC 0x30
+#define IMF_WRITE_YA 0x18
+#define IMF_WRITE_YCA 0x38
+
+
+/*
+** Level modes; values must be the same as in Imf::LevelMode
+*/
+
+#define IMF_ONE_LEVEL 0
+#define IMF_MIPMAP_LEVELS 1
+#define IMF_RIPMAP_LEVELS 2
+
+
+/*
+** Level rounding modes; values must be the same as in Imf::LevelRoundingMode
+*/
+
+#define IMF_ROUND_DOWN 0
+#define IMF_ROUND_UP 1
+
+
+/*
+** RGBA file header
+*/
+
+struct ImfHeader;
+typedef struct ImfHeader ImfHeader;
+
+ImfHeader * ImfNewHeader (void);
+
+void ImfDeleteHeader (ImfHeader *hdr);
+
+ImfHeader * ImfCopyHeader (const ImfHeader *hdr);
+
+void ImfHeaderSetDisplayWindow (ImfHeader *hdr,
+ int xMin, int yMin,
+ int xMax, int yMax);
+
+void ImfHeaderDisplayWindow (const ImfHeader *hdr,
+ int *xMin, int *yMin,
+ int *xMax, int *yMax);
+
+void ImfHeaderSetDataWindow (ImfHeader *hdr,
+ int xMin, int yMin,
+ int xMax, int yMax);
+
+void ImfHeaderDataWindow (const ImfHeader *hdr,
+ int *xMin, int *yMin,
+ int *xMax, int *yMax);
+
+void ImfHeaderSetPixelAspectRatio (ImfHeader *hdr,
+ float pixelAspectRatio);
+
+float ImfHeaderPixelAspectRatio (const ImfHeader *hdr);
+
+void ImfHeaderSetScreenWindowCenter (ImfHeader *hdr,
+ float x, float y);
+
+void ImfHeaderScreenWindowCenter (const ImfHeader *hdr,
+ float *x, float *y);
+
+void ImfHeaderSetScreenWindowWidth (ImfHeader *hdr,
+ float width);
+
+float ImfHeaderScreenWindowWidth (const ImfHeader *hdr);
+
+void ImfHeaderSetLineOrder (ImfHeader *hdr,
+ int lineOrder);
+
+int ImfHeaderLineOrder (const ImfHeader *hdr);
+
+void ImfHeaderSetCompression (ImfHeader *hdr,
+ int compression);
+
+int ImfHeaderCompression (const ImfHeader *hdr);
+
+int ImfHeaderSetIntAttribute (ImfHeader *hdr,
+ const char name[],
+ int value);
+
+int ImfHeaderIntAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *value);
+
+int ImfHeaderSetFloatAttribute (ImfHeader *hdr,
+ const char name[],
+ float value);
+
+int ImfHeaderSetDoubleAttribute (ImfHeader *hdr,
+ const char name[],
+ double value);
+
+int ImfHeaderFloatAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *value);
+
+int ImfHeaderDoubleAttribute (const ImfHeader *hdr,
+ const char name[],
+ double *value);
+
+int ImfHeaderSetStringAttribute (ImfHeader *hdr,
+ const char name[],
+ const char value[]);
+
+int ImfHeaderStringAttribute (const ImfHeader *hdr,
+ const char name[],
+ const char **value);
+
+int ImfHeaderSetBox2iAttribute (ImfHeader *hdr,
+ const char name[],
+ int xMin, int yMin,
+ int xMax, int yMax);
+
+int ImfHeaderBox2iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *xMin, int *yMin,
+ int *xMax, int *yMax);
+
+int ImfHeaderSetBox2fAttribute (ImfHeader *hdr,
+ const char name[],
+ float xMin, float yMin,
+ float xMax, float yMax);
+
+int ImfHeaderBox2fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *xMin, float *yMin,
+ float *xMax, float *yMax);
+
+int ImfHeaderSetV2iAttribute (ImfHeader *hdr,
+ const char name[],
+ int x, int y);
+
+int ImfHeaderV2iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *x, int *y);
+
+int ImfHeaderSetV2fAttribute (ImfHeader *hdr,
+ const char name[],
+ float x, float y);
+
+int ImfHeaderV2fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *x, float *y);
+
+int ImfHeaderSetV3iAttribute (ImfHeader *hdr,
+ const char name[],
+ int x, int y, int z);
+
+int ImfHeaderV3iAttribute (const ImfHeader *hdr,
+ const char name[],
+ int *x, int *y, int *z);
+
+int ImfHeaderSetV3fAttribute (ImfHeader *hdr,
+ const char name[],
+ float x, float y, float z);
+
+int ImfHeaderV3fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float *x, float *y, float *z);
+
+int ImfHeaderSetM33fAttribute (ImfHeader *hdr,
+ const char name[],
+ const float m[3][3]);
+
+int ImfHeaderM33fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float m[3][3]);
+
+int ImfHeaderSetM44fAttribute (ImfHeader *hdr,
+ const char name[],
+ const float m[4][4]);
+
+int ImfHeaderM44fAttribute (const ImfHeader *hdr,
+ const char name[],
+ float m[4][4]);
+
+/*
+** RGBA output file
+*/
+
+struct ImfOutputFile;
+typedef struct ImfOutputFile ImfOutputFile;
+
+ImfOutputFile * ImfOpenOutputFile (const char name[],
+ const ImfHeader *hdr,
+ int channels);
+
+int ImfCloseOutputFile (ImfOutputFile *out);
+
+int ImfOutputSetFrameBuffer (ImfOutputFile *out,
+ const ImfRgba *base,
+ size_t xStride,
+ size_t yStride);
+
+int ImfOutputWritePixels (ImfOutputFile *out,
+ int numScanLines);
+
+int ImfOutputCurrentScanLine (const ImfOutputFile *out);
+
+const ImfHeader * ImfOutputHeader (const ImfOutputFile *out);
+
+int ImfOutputChannels (const ImfOutputFile *out);
+
+
+/*
+** Tiled RGBA output file
+*/
+
+struct ImfTiledOutputFile;
+typedef struct ImfTiledOutputFile ImfTiledOutputFile;
+
+ImfTiledOutputFile * ImfOpenTiledOutputFile (const char name[],
+ const ImfHeader *hdr,
+ int channels,
+ int xSize, int ySize,
+ int mode, int rmode);
+
+int ImfCloseTiledOutputFile (ImfTiledOutputFile *out);
+
+int ImfTiledOutputSetFrameBuffer (ImfTiledOutputFile *out,
+ const ImfRgba *base,
+ size_t xStride,
+ size_t yStride);
+
+int ImfTiledOutputWriteTile (ImfTiledOutputFile *out,
+ int dx, int dy,
+ int lx, int ly);
+
+int ImfTiledOutputWriteTiles (ImfTiledOutputFile *out,
+ int dxMin, int dxMax,
+ int dyMin, int dyMax,
+ int lx, int ly);
+
+const ImfHeader * ImfTiledOutputHeader (const ImfTiledOutputFile *out);
+
+int ImfTiledOutputChannels (const ImfTiledOutputFile *out);
+
+int ImfTiledOutputTileXSize (const ImfTiledOutputFile *out);
+
+int ImfTiledOutputTileYSize (const ImfTiledOutputFile *out);
+
+int ImfTiledOutputLevelMode (const ImfTiledOutputFile *out);
+int ImfTiledOutputLevelRoundingMode
+ (const ImfTiledOutputFile *out);
+
+
+/*
+** RGBA input file
+*/
+
+struct ImfInputFile;
+typedef struct ImfInputFile ImfInputFile;
+
+ImfInputFile * ImfOpenInputFile (const char name[]);
+
+int ImfCloseInputFile (ImfInputFile *in);
+
+int ImfInputSetFrameBuffer (ImfInputFile *in,
+ ImfRgba *base,
+ size_t xStride,
+ size_t yStride);
+
+int ImfInputReadPixels (ImfInputFile *in,
+ int scanLine1,
+ int scanLine2);
+
+const ImfHeader * ImfInputHeader (const ImfInputFile *in);
+
+int ImfInputChannels (const ImfInputFile *in);
+
+const char * ImfInputFileName (const ImfInputFile *in);
+
+
+/*
+** Tiled RGBA input file
+*/
+
+struct ImfTiledInputFile;
+typedef struct ImfTiledInputFile ImfTiledInputFile;
+
+ImfTiledInputFile * ImfOpenTiledInputFile (const char name[]);
+
+int ImfCloseTiledInputFile (ImfTiledInputFile *in);
+
+int ImfTiledInputSetFrameBuffer (ImfTiledInputFile *in,
+ ImfRgba *base,
+ size_t xStride,
+ size_t yStride);
+
+int ImfTiledInputReadTile (ImfTiledInputFile *in,
+ int dx, int dy,
+ int lx, int ly);
+
+int ImfTiledInputReadTiles (ImfTiledInputFile *in,
+ int dxMin, int dxMax,
+ int dyMin, int dyMax,
+ int lx, int ly);
+
+const ImfHeader * ImfTiledInputHeader (const ImfTiledInputFile *in);
+
+int ImfTiledInputChannels (const ImfTiledInputFile *in);
+
+const char * ImfTiledInputFileName (const ImfTiledInputFile *in);
+
+int ImfTiledInputTileXSize (const ImfTiledInputFile *in);
+
+int ImfTiledInputTileYSize (const ImfTiledInputFile *in);
+
+int ImfTiledInputLevelMode (const ImfTiledInputFile *in);
+
+int ImfTiledInputLevelRoundingMode
+ (const ImfTiledInputFile *in);
+
+/*
+** Lookup tables
+*/
+
+struct ImfLut;
+typedef struct ImfLut ImfLut;
+
+ImfLut * ImfNewRound12logLut (int channels);
+
+ImfLut * ImfNewRoundNBitLut (unsigned int n, int channels);
+
+void ImfDeleteLut (ImfLut *lut);
+
+void ImfApplyLut (ImfLut *lut,
+ ImfRgba *data,
+ int nData,
+ int stride);
+/*
+** Most recent error message
+*/
+
+const char * ImfErrorMessage (void);
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfChannelList.cpp b/Source/OpenEXR/IlmImf/ImfChannelList.cpp
new file mode 100644
index 0000000..832738b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChannelList.cpp
@@ -0,0 +1,254 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Channel
+// class ChannelList
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfChannelList.h>
+#include <Iex.h>
+
+
+using std::string;
+using std::set;
+
+namespace Imf {
+
+
+Channel::Channel (PixelType t, int xs, int ys, bool pl):
+ type (t),
+ xSampling (xs),
+ ySampling (ys),
+ pLinear (pl)
+{
+ // empty
+}
+
+
+bool
+Channel::operator == (const Channel &other) const
+{
+ return type == other.type &&
+ xSampling == other.xSampling &&
+ ySampling == other.ySampling &&
+ pLinear == other.pLinear;
+}
+
+
+void
+ChannelList::insert (const char name[], const Channel &channel)
+{
+ if (name[0] == 0)
+ THROW (Iex::ArgExc, "Image channel name cannot be an empty string.");
+
+ _map[name] = channel;
+}
+
+
+Channel &
+ChannelList::operator [] (const char name[])
+{
+ ChannelMap::iterator i = _map.find (name);
+
+ if (i == _map.end())
+ THROW (Iex::ArgExc, "Cannot find image channel \"" << name << "\".");
+
+ return i->second;
+}
+
+
+const Channel &
+ChannelList::operator [] (const char name[]) const
+{
+ ChannelMap::const_iterator i = _map.find (name);
+
+ if (i == _map.end())
+ THROW (Iex::ArgExc, "Cannot find image channel \"" << name << "\".");
+
+ return i->second;
+}
+
+
+Channel *
+ChannelList::findChannel (const char name[])
+{
+ ChannelMap::iterator i = _map.find (name);
+ return (i == _map.end())? 0: &i->second;
+}
+
+
+const Channel *
+ChannelList::findChannel (const char name[]) const
+{
+ ChannelMap::const_iterator i = _map.find (name);
+ return (i == _map.end())? 0: &i->second;
+}
+
+
+ChannelList::Iterator
+ChannelList::begin ()
+{
+ return _map.begin();
+}
+
+
+ChannelList::ConstIterator
+ChannelList::begin () const
+{
+ return _map.begin();
+}
+
+
+ChannelList::Iterator
+ChannelList::end ()
+{
+ return _map.end();
+}
+
+
+ChannelList::ConstIterator
+ChannelList::end () const
+{
+ return _map.end();
+}
+
+
+ChannelList::Iterator
+ChannelList::find (const char name[])
+{
+ return _map.find (name);
+}
+
+
+ChannelList::ConstIterator
+ChannelList::find (const char name[]) const
+{
+ return _map.find (name);
+}
+
+
+void
+ChannelList::layers (set <string> &layerNames) const
+{
+ layerNames.clear();
+
+ for (ConstIterator i = begin(); i != end(); ++i)
+ {
+ string layerName = i.name();
+ size_t pos = layerName.rfind ('.');
+
+ if (pos != string::npos && pos != 0 && pos + 1 < layerName.size())
+ {
+ layerName.erase (pos);
+ layerNames.insert (layerName);
+ }
+ }
+}
+
+
+void
+ChannelList::channelsInLayer (const string &layerName,
+ Iterator &first,
+ Iterator &last)
+{
+ channelsWithPrefix ((layerName + '.').c_str(), first, last);
+}
+
+
+void
+ChannelList::channelsInLayer (const string &layerName,
+ ConstIterator &first,
+ ConstIterator &last) const
+{
+ channelsWithPrefix ((layerName + '.').c_str(), first, last);
+}
+
+
+void
+ChannelList::channelsWithPrefix (const char prefix[],
+ Iterator &first,
+ Iterator &last)
+{
+ first = last = _map.lower_bound (prefix);
+ int n = strlen (prefix);
+
+ while (last != Iterator (_map.end()) &&
+ strncmp (last.name(), prefix, n) <= 0)
+ {
+ ++last;
+ }
+}
+
+
+void
+ChannelList::channelsWithPrefix (const char prefix[],
+ ConstIterator &first,
+ ConstIterator &last) const
+{
+ first = last = _map.lower_bound (prefix);
+ int n = strlen (prefix);
+
+ while (last != ConstIterator (_map.end()) &&
+ strncmp (last.name(), prefix, n) <= 0)
+ {
+ ++last;
+ }
+}
+
+
+bool
+ChannelList::operator == (const ChannelList &other) const
+{
+ ConstIterator i = begin();
+ ConstIterator j = other.begin();
+
+ while (i != end() && j != other.end())
+ {
+ if (!(i.channel() == j.channel()))
+ return false;
+
+ ++i;
+ ++j;
+ }
+
+ return i == end() && j == other.end();
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfChannelList.h b/Source/OpenEXR/IlmImf/ImfChannelList.h
new file mode 100644
index 0000000..e712b62
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChannelList.h
@@ -0,0 +1,411 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_CHANNEL_LIST_H
+#define INCLUDED_IMF_CHANNEL_LIST_H
+
+//-----------------------------------------------------------------------------
+//
+// class Channel
+// class ChannelList
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfName.h>
+#include <ImfPixelType.h>
+#include <map>
+#include <set>
+#include <string>
+
+
+namespace Imf {
+
+
+struct Channel
+{
+ //------------------------------
+ // Data type; see ImfPixelType.h
+ //------------------------------
+
+ PixelType type;
+
+
+ //--------------------------------------------
+ // Subsampling: pixel (x, y) is present in the
+ // channel only if
+ //
+ // x % xSampling == 0 && y % ySampling == 0
+ //
+ //--------------------------------------------
+
+ int xSampling;
+ int ySampling;
+
+
+ //--------------------------------------------------------------
+ // Hint to lossy compression methods that indicates whether
+ // human perception of the quantity represented by this channel
+ // is closer to linear or closer to logarithmic. Compression
+ // methods may optimize image quality by adjusting pixel data
+ // quantization acording to this hint.
+ // For example, perception of red, green, blue and luminance is
+ // approximately logarithmic; the difference between 0.1 and 0.2
+ // is perceived to be roughly the same as the difference between
+ // 1.0 and 2.0. Perception of chroma coordinates tends to be
+ // closer to linear than logarithmic; the difference between 0.1
+ // and 0.2 is perceived to be roughly the same as the difference
+ // between 1.0 and 1.1.
+ //--------------------------------------------------------------
+
+ bool pLinear;
+
+
+ //------------
+ // Constructor
+ //------------
+
+ Channel (PixelType type = HALF,
+ int xSampling = 1,
+ int ySampling = 1,
+ bool pLinear = false);
+
+
+ //------------
+ // Operator ==
+ //------------
+
+ bool operator == (const Channel &other) const;
+};
+
+
+class ChannelList
+{
+ public:
+
+ //--------------
+ // Add a channel
+ //--------------
+
+ void insert (const char name[],
+ const Channel &channel);
+
+ //------------------------------------------------------------------
+ // Access to existing channels:
+ //
+ // [n] Returns a reference to the channel with name n.
+ // If no channel with name n exists, an Iex::ArgExc
+ // is thrown.
+ //
+ // findChannel(n) Returns a pointer to the channel with name n,
+ // or 0 if no channel with name n exists.
+ //
+ //------------------------------------------------------------------
+
+ Channel & operator [] (const char name[]);
+ const Channel & operator [] (const char name[]) const;
+
+ Channel * findChannel (const char name[]);
+ const Channel * findChannel (const char name[]) const;
+
+
+ //-------------------------------------------
+ // Iterator-style access to existing channels
+ //-------------------------------------------
+
+ typedef std::map <Name, Channel> ChannelMap;
+
+ class Iterator;
+ class ConstIterator;
+
+ Iterator begin ();
+ ConstIterator begin () const;
+ Iterator end ();
+ ConstIterator end () const;
+ Iterator find (const char name[]);
+ ConstIterator find (const char name[]) const;
+
+
+ //-----------------------------------------------------------------
+ // Support for image layers:
+ //
+ // In an image file with many channels it is sometimes useful to
+ // group the channels into "layers", that is, into sets of channels
+ // that logically belong together. Grouping channels into layers
+ // is done using a naming convention: channel C in layer L is
+ // called "L.C".
+ //
+ // For example, a computer graphic image may contain separate
+ // R, G and B channels for light that originated at each of
+ // several different virtual light sources. The channels in
+ // this image might be called "light1.R", "light1.G", "light1.B",
+ // "light2.R", "light2.G", "light2.B", etc.
+ //
+ // Note that this naming convention allows layers to be nested;
+ // for example, "light1.specular.R" identifies the "R" channel
+ // in the "specular" sub-layer of layer "light1".
+ //
+ // Channel names that don't contain a "." or that contain a
+ // "." only at the beginning or at the end are not considered
+ // to be part of any layer.
+ //
+ // layers(lns) sorts the channels in this ChannelList
+ // into layers and stores the names of
+ // all layers, sorted alphabetically,
+ // into string set lns.
+ //
+ // channelsInLayer(ln,f,l) stores a pair of iterators in f and l
+ // such that the loop
+ //
+ // for (ConstIterator i = f; i != l; ++i)
+ // ...
+ //
+ // iterates over all channels in layer ln.
+ // channelsInLayer (ln, l, p) calls
+ // channelsWithPrefix (ln + ".", l, p).
+ //
+ //-----------------------------------------------------------------
+
+ void layers (std::set <std::string> &layerNames) const;
+
+ void channelsInLayer (const std::string &layerName,
+ Iterator &first,
+ Iterator &last);
+
+ void channelsInLayer (const std::string &layerName,
+ ConstIterator &first,
+ ConstIterator &last) const;
+
+
+ //-------------------------------------------------------------------
+ // Find all channels whose name begins with a given prefix:
+ //
+ // channelsWithPrefix(p,f,l) stores a pair of iterators in f and l
+ // such that the following loop iterates over all channels whose name
+ // begins with string p:
+ //
+ // for (ConstIterator i = f; i != l; ++i)
+ // ...
+ //
+ //-------------------------------------------------------------------
+
+ void channelsWithPrefix (const char prefix[],
+ Iterator &first,
+ Iterator &last);
+
+ void channelsWithPrefix (const char prefix[],
+ ConstIterator &first,
+ ConstIterator &last) const;
+
+ //------------
+ // Operator ==
+ //------------
+
+ bool operator == (const ChannelList &other) const;
+
+ private:
+
+ ChannelMap _map;
+};
+
+
+//----------
+// Iterators
+//----------
+
+class ChannelList::Iterator
+{
+ public:
+
+ Iterator ();
+ Iterator (const ChannelList::ChannelMap::iterator &i);
+
+ Iterator & operator ++ ();
+ Iterator operator ++ (int);
+
+ const char * name () const;
+ Channel & channel () const;
+
+ private:
+
+ friend class ChannelList::ConstIterator;
+
+ ChannelList::ChannelMap::iterator _i;
+};
+
+
+class ChannelList::ConstIterator
+{
+ public:
+
+ ConstIterator ();
+ ConstIterator (const ChannelList::ChannelMap::const_iterator &i);
+ ConstIterator (const ChannelList::Iterator &other);
+
+ ConstIterator & operator ++ ();
+ ConstIterator operator ++ (int);
+
+ const char * name () const;
+ const Channel & channel () const;
+
+ private:
+
+ friend bool operator == (const ConstIterator &, const ConstIterator &);
+ friend bool operator != (const ConstIterator &, const ConstIterator &);
+
+ ChannelList::ChannelMap::const_iterator _i;
+};
+
+
+//-----------------
+// Inline Functions
+//-----------------
+
+inline
+ChannelList::Iterator::Iterator (): _i()
+{
+ // empty
+}
+
+
+inline
+ChannelList::Iterator::Iterator (const ChannelList::ChannelMap::iterator &i):
+ _i (i)
+{
+ // empty
+}
+
+
+inline ChannelList::Iterator &
+ChannelList::Iterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline ChannelList::Iterator
+ChannelList::Iterator::operator ++ (int)
+{
+ Iterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+ChannelList::Iterator::name () const
+{
+ return *_i->first;
+}
+
+
+inline Channel &
+ChannelList::Iterator::channel () const
+{
+ return _i->second;
+}
+
+
+inline
+ChannelList::ConstIterator::ConstIterator (): _i()
+{
+ // empty
+}
+
+inline
+ChannelList::ConstIterator::ConstIterator
+ (const ChannelList::ChannelMap::const_iterator &i): _i (i)
+{
+ // empty
+}
+
+
+inline
+ChannelList::ConstIterator::ConstIterator (const ChannelList::Iterator &other):
+ _i (other._i)
+{
+ // empty
+}
+
+inline ChannelList::ConstIterator &
+ChannelList::ConstIterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline ChannelList::ConstIterator
+ChannelList::ConstIterator::operator ++ (int)
+{
+ ConstIterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+ChannelList::ConstIterator::name () const
+{
+ return *_i->first;
+}
+
+inline const Channel &
+ChannelList::ConstIterator::channel () const
+{
+ return _i->second;
+}
+
+
+inline bool
+operator == (const ChannelList::ConstIterator &x,
+ const ChannelList::ConstIterator &y)
+{
+ return x._i == y._i;
+}
+
+
+inline bool
+operator != (const ChannelList::ConstIterator &x,
+ const ChannelList::ConstIterator &y)
+{
+ return !(x == y);
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfChannelListAttribute.cpp b/Source/OpenEXR/IlmImf/ImfChannelListAttribute.cpp
new file mode 100644
index 0000000..b6d62f4
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChannelListAttribute.cpp
@@ -0,0 +1,127 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class ChannelListAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfChannelListAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+ChannelListAttribute::staticTypeName ()
+{
+ return "chlist";
+}
+
+
+template <>
+void
+ChannelListAttribute::writeValueTo (OStream &os, int version) const
+{
+ for (ChannelList::ConstIterator i = _value.begin();
+ i != _value.end();
+ ++i)
+ {
+ //
+ // Write name
+ //
+
+ Xdr::write <StreamIO> (os, i.name());
+
+ //
+ // Write Channel struct
+ //
+
+ Xdr::write <StreamIO> (os, int (i.channel().type));
+ Xdr::write <StreamIO> (os, i.channel().pLinear);
+ Xdr::pad <StreamIO> (os, 3);
+ Xdr::write <StreamIO> (os, i.channel().xSampling);
+ Xdr::write <StreamIO> (os, i.channel().ySampling);
+ }
+
+ //
+ // Write end of list marker
+ //
+
+ Xdr::write <StreamIO> (os, "");
+}
+
+
+template <>
+void
+ChannelListAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ while (true)
+ {
+ //
+ // Read name; zero length name means end of channel list
+ //
+
+ char name[Name::SIZE];
+ Xdr::read <StreamIO> (is, sizeof (name), name);
+
+ if (name[0] == 0)
+ break;
+
+ //
+ // Read Channel struct
+ //
+
+ int type;
+ bool pLinear;
+ int xSampling;
+ int ySampling;
+
+ Xdr::read <StreamIO> (is, type);
+ Xdr::read <StreamIO> (is, pLinear);
+ Xdr::skip <StreamIO> (is, 3);
+ Xdr::read <StreamIO> (is, xSampling);
+ Xdr::read <StreamIO> (is, ySampling);
+
+ _value.insert
+ (name, Channel (PixelType (type), xSampling, ySampling, pLinear));
+ }
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfChannelListAttribute.h b/Source/OpenEXR/IlmImf/ImfChannelListAttribute.h
new file mode 100644
index 0000000..050ecf9
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChannelListAttribute.h
@@ -0,0 +1,67 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_CHANNEL_LIST_ATTRIBUTE_H
+#define INCLUDED_IMF_CHANNEL_LIST_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class ChannelListAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfChannelList.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<ChannelList> ChannelListAttribute;
+template <> const char *ChannelListAttribute::staticTypeName ();
+template <> void ChannelListAttribute::writeValueTo (OStream &, int) const;
+template <> void ChannelListAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfChannelListAttribute.cpp>
+#endif
+
+#endif
+
diff --git a/Source/OpenEXR/IlmImf/ImfChromaticities.cpp b/Source/OpenEXR/IlmImf/ImfChromaticities.cpp
new file mode 100644
index 0000000..2db9d0e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChromaticities.cpp
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// CIE (x,y) chromaticities, and conversions between
+// RGB tiples and CIE XYZ tristimulus values.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfChromaticities.h>
+
+namespace Imf {
+
+
+Chromaticities::Chromaticities (const Imath::V2f &red,
+ const Imath::V2f &green,
+ const Imath::V2f &blue,
+ const Imath::V2f &white)
+:
+ red (red),
+ green (green),
+ blue (blue),
+ white (white)
+{
+ // empty
+}
+
+
+Imath::M44f
+RGBtoXYZ (const Chromaticities chroma, float Y)
+{
+ //
+ // For an explanation of how the color conversion matrix is derived,
+ // see Roy Hall, "Illumination and Color in Computer Generated Imagery",
+ // Springer-Verlag, 1989, chapter 3, "Perceptual Response"; and
+ // Charles A. Poynton, "A Technical Introduction to Digital Video",
+ // John Wiley & Sons, 1996, chapter 7, "Color science for video".
+ //
+
+ //
+ // X and Z values of RGB value (1, 1, 1), or "white"
+ //
+
+ float X = chroma.white.x * Y / chroma.white.y;
+ float Z = (1 - chroma.white.x - chroma.white.y) * Y / chroma.white.y;
+
+ //
+ // Scale factors for matrix rows
+ //
+
+ float d = chroma.red.x * (chroma.blue.y - chroma.green.y) +
+ chroma.blue.x * (chroma.green.y - chroma.red.y) +
+ chroma.green.x * (chroma.red.y - chroma.blue.y);
+
+ float Sr = (X * (chroma.blue.y - chroma.green.y) -
+ chroma.green.x * (Y * (chroma.blue.y - 1) +
+ chroma.blue.y * (X + Z)) +
+ chroma.blue.x * (Y * (chroma.green.y - 1) +
+ chroma.green.y * (X + Z))) / d;
+
+ float Sg = (X * (chroma.red.y - chroma.blue.y) +
+ chroma.red.x * (Y * (chroma.blue.y - 1) +
+ chroma.blue.y * (X + Z)) -
+ chroma.blue.x * (Y * (chroma.red.y - 1) +
+ chroma.red.y * (X + Z))) / d;
+
+ float Sb = (X * (chroma.green.y - chroma.red.y) -
+ chroma.red.x * (Y * (chroma.green.y - 1) +
+ chroma.green.y * (X + Z)) +
+ chroma.green.x * (Y * (chroma.red.y - 1) +
+ chroma.red.y * (X + Z))) / d;
+
+ //
+ // Assemble the matrix
+ //
+
+ Imath::M44f M;
+
+ M[0][0] = Sr * chroma.red.x;
+ M[0][1] = Sr * chroma.red.y;
+ M[0][2] = Sr * (1 - chroma.red.x - chroma.red.y);
+
+ M[1][0] = Sg * chroma.green.x;
+ M[1][1] = Sg * chroma.green.y;
+ M[1][2] = Sg * (1 - chroma.green.x - chroma.green.y);
+
+ M[2][0] = Sb * chroma.blue.x;
+ M[2][1] = Sb * chroma.blue.y;
+ M[2][2] = Sb * (1 - chroma.blue.x - chroma.blue.y);
+
+ return M;
+}
+
+
+Imath::M44f
+XYZtoRGB (const Chromaticities chroma, float Y)
+{
+ return RGBtoXYZ (chroma, Y).inverse();
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfChromaticities.h b/Source/OpenEXR/IlmImf/ImfChromaticities.h
new file mode 100644
index 0000000..28e8c51
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChromaticities.h
@@ -0,0 +1,120 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_CHROMATICITIES_H
+#define INCLUDED_IMF_CHROMATICITIES_H
+
+//-----------------------------------------------------------------------------
+//
+// CIE (x,y) chromaticities, and conversions between
+// RGB tiples and CIE XYZ tristimulus values.
+//
+//-----------------------------------------------------------------------------
+
+#include "ImathVec.h"
+#include "ImathMatrix.h"
+
+namespace Imf {
+
+
+struct Chromaticities
+{
+ //-----------------------------------------------
+ // The CIE x and y coordinates of the RGB triples
+ // (1,0,0), (0,1,0), (0,0,1) and (1,1,1).
+ //-----------------------------------------------
+
+ Imath::V2f red;
+ Imath::V2f green;
+ Imath::V2f blue;
+ Imath::V2f white;
+
+ //--------------------------------------------
+ // Default constructor produces chromaticities
+ // according to Rec. ITU-R BT.709-3
+ //--------------------------------------------
+
+ Chromaticities (const Imath::V2f &red = Imath::V2f (0.6400f, 0.3300f),
+ const Imath::V2f &green = Imath::V2f (0.3000f, 0.6000f),
+ const Imath::V2f &blue = Imath::V2f (0.1500f, 0.0600f),
+ const Imath::V2f &white = Imath::V2f (0.3127f, 0.3290f));
+};
+
+
+//
+// Conversions between RGB and CIE XYZ
+//
+// RGB to XYZ:
+//
+// Given a set of chromaticities, c, and the luminance, Y, of the RGB
+// triple (1,1,1), or "white", RGBtoXYZ(c,Y) computes a matrix, M, so
+// that multiplying an RGB value, v, with M produces an equivalent
+// XYZ value, w. (w == v * M)
+//
+// If we define that
+//
+// (Xr, Yr, Zr) == (1, 0, 0) * M
+// (Xg, Yg, Zg) == (0, 1, 0) * M
+// (Xb, Yb, Zb) == (0, 0, 1) * M
+// (Xw, Yw, Zw) == (1, 1, 1) * M,
+//
+// then the following statements are true:
+//
+// Xr / (Xr + Yr + Zr) == c.red.x
+// Yr / (Xr + Yr + Zr) == c.red.y
+//
+// Xg / (Xg + Yg + Zg) == c.red.x
+// Yg / (Xg + Yg + Zg) == c.red.y
+//
+// Xb / (Xb + Yb + Zb) == c.red.x
+// Yb / (Xb + Yb + Zb) == c.red.y
+//
+// Xw / (Xw + Yw + Zw) == c.red.x
+// Yw / (Xw + Yw + Zw) == c.red.y
+//
+// Yw == Y.
+//
+// XYZ to RGB:
+//
+// YYZtoRGB(c,Y) returns RGBtoXYZ(c,Y).inverse().
+//
+
+Imath::M44f RGBtoXYZ (const Chromaticities chroma, float Y);
+Imath::M44f XYZtoRGB (const Chromaticities chroma, float Y);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.cpp b/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.cpp
new file mode 100644
index 0000000..03f3a8d
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.cpp
@@ -0,0 +1,86 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class ChromaticitiesAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfChromaticitiesAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+ChromaticitiesAttribute::staticTypeName ()
+{
+ return "chromaticities";
+}
+
+
+template <>
+void
+ChromaticitiesAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.red.x);
+ Xdr::write <StreamIO> (os, _value.red.y);
+ Xdr::write <StreamIO> (os, _value.green.x);
+ Xdr::write <StreamIO> (os, _value.green.y);
+ Xdr::write <StreamIO> (os, _value.blue.x);
+ Xdr::write <StreamIO> (os, _value.blue.y);
+ Xdr::write <StreamIO> (os, _value.white.x);
+ Xdr::write <StreamIO> (os, _value.white.y);
+}
+
+
+template <>
+void
+ChromaticitiesAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.red.x);
+ Xdr::read <StreamIO> (is, _value.red.y);
+ Xdr::read <StreamIO> (is, _value.green.x);
+ Xdr::read <StreamIO> (is, _value.green.y);
+ Xdr::read <StreamIO> (is, _value.blue.x);
+ Xdr::read <StreamIO> (is, _value.blue.y);
+ Xdr::read <StreamIO> (is, _value.white.x);
+ Xdr::read <StreamIO> (is, _value.white.y);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.h b/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.h
new file mode 100644
index 0000000..08357fa
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfChromaticitiesAttribute.h
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_CHROMATICITIES_ATTRIBUTE_H
+#define INCLUDED_IMF_CHROMATICITIES_ATTRIBUTE_H
+
+
+//-----------------------------------------------------------------------------
+//
+// class ChromaticitiesAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfChromaticities.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Chromaticities> ChromaticitiesAttribute;
+
+template <>
+const char *ChromaticitiesAttribute::staticTypeName ();
+
+template <>
+void ChromaticitiesAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void ChromaticitiesAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfChromaticitiesAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfCompression.h b/Source/OpenEXR/IlmImf/ImfCompression.h
new file mode 100644
index 0000000..2115943
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCompression.h
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_COMPRESSION_H
+#define INCLUDED_IMF_COMPRESSION_H
+
+//-----------------------------------------------------------------------------
+//
+// enum Compression
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+enum Compression
+{
+ NO_COMPRESSION = 0, // no compression
+
+ RLE_COMPRESSION = 1, // run length encoding
+
+ ZIPS_COMPRESSION = 2, // zlib compression, one scan line at a time
+
+ ZIP_COMPRESSION = 3, // zlib compression, in blocks of 16 scan lines
+
+ PIZ_COMPRESSION = 4, // piz-based wavelet compression
+
+ PXR24_COMPRESSION = 5, // lossy 24-bit float compression
+
+ B44_COMPRESSION = 6, // lossy 4-by-4 pixel block compression,
+ // fixed compression rate
+
+ B44A_COMPRESSION = 7, // lossy 4-by-4 pixel block compression,
+ // flat fields are compressed more
+
+ NUM_COMPRESSION_METHODS // number of different compression methods
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfCompressionAttribute.cpp b/Source/OpenEXR/IlmImf/ImfCompressionAttribute.cpp
new file mode 100644
index 0000000..0c28d16
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCompressionAttribute.cpp
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class CompressionAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressionAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+CompressionAttribute::staticTypeName ()
+{
+ return "compression";
+}
+
+
+template <>
+void
+CompressionAttribute::writeValueTo (OStream &os, int version) const
+{
+ unsigned char tmp = _value;
+ Xdr::write <StreamIO> (os, tmp);
+}
+
+
+template <>
+void
+CompressionAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ unsigned char tmp;
+ Xdr::read <StreamIO> (is, tmp);
+ _value = Compression (tmp);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfCompressionAttribute.h b/Source/OpenEXR/IlmImf/ImfCompressionAttribute.h
new file mode 100644
index 0000000..268c26b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCompressionAttribute.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_COMPRESSION_ATTRIBUTE_H
+#define INCLUDED_IMF_COMPRESSION_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class CompressionAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfCompression.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Compression> CompressionAttribute;
+template <> const char *CompressionAttribute::staticTypeName ();
+template <> void CompressionAttribute::writeValueTo (OStream &, int) const;
+template <> void CompressionAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfCompressionAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfCompressor.cpp b/Source/OpenEXR/IlmImf/ImfCompressor.cpp
new file mode 100644
index 0000000..17dbab9
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCompressor.cpp
@@ -0,0 +1,191 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Compressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+#include <ImfRleCompressor.h>
+#include <ImfZipCompressor.h>
+#include <ImfPizCompressor.h>
+#include <ImfPxr24Compressor.h>
+#include <ImfB44Compressor.h>
+
+namespace Imf {
+
+using Imath::Box2i;
+
+
+Compressor::Compressor (const Header &hdr): _header (hdr) {}
+
+
+Compressor::~Compressor () {}
+
+
+Compressor::Format
+Compressor::format () const
+{
+ return XDR;
+}
+
+
+int
+Compressor::compressTile (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ return compress (inPtr, inSize, range.min.y, outPtr);
+}
+
+
+int
+Compressor::uncompressTile (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ return uncompress (inPtr, inSize, range.min.y, outPtr);
+}
+
+
+bool
+isValidCompression (Compression c)
+{
+ switch (c)
+ {
+ case NO_COMPRESSION:
+ case RLE_COMPRESSION:
+ case ZIPS_COMPRESSION:
+ case ZIP_COMPRESSION:
+ case PIZ_COMPRESSION:
+ case PXR24_COMPRESSION:
+ case B44_COMPRESSION:
+ case B44A_COMPRESSION:
+
+ return true;
+
+ default:
+
+ return false;
+ }
+}
+
+
+Compressor *
+newCompressor (Compression c, int maxScanLineSize, const Header &hdr)
+{
+ switch (c)
+ {
+ case RLE_COMPRESSION:
+
+ return new RleCompressor (hdr, maxScanLineSize);
+
+ case ZIPS_COMPRESSION:
+
+ return new ZipCompressor (hdr, maxScanLineSize, 1);
+
+ case ZIP_COMPRESSION:
+
+ return new ZipCompressor (hdr, maxScanLineSize, 16);
+
+ case PIZ_COMPRESSION:
+
+ return new PizCompressor (hdr, maxScanLineSize, 32);
+
+ case PXR24_COMPRESSION:
+
+ return new Pxr24Compressor (hdr, maxScanLineSize, 16);
+
+ case B44_COMPRESSION:
+
+ return new B44Compressor (hdr, maxScanLineSize, 32, false);
+
+ case B44A_COMPRESSION:
+
+ return new B44Compressor (hdr, maxScanLineSize, 32, true);
+
+ default:
+
+ return 0;
+ }
+}
+
+
+Compressor *
+newTileCompressor (Compression c,
+ int tileLineSize,
+ int numTileLines,
+ const Header &hdr)
+{
+ switch (c)
+ {
+ case RLE_COMPRESSION:
+
+ return new RleCompressor (hdr, tileLineSize * numTileLines);
+
+ case ZIPS_COMPRESSION:
+ case ZIP_COMPRESSION:
+
+ return new ZipCompressor (hdr, tileLineSize, numTileLines);
+
+ case PIZ_COMPRESSION:
+
+ return new PizCompressor (hdr, tileLineSize, numTileLines);
+
+ case PXR24_COMPRESSION:
+
+ return new Pxr24Compressor (hdr, tileLineSize, numTileLines);
+
+ case B44_COMPRESSION:
+
+ return new B44Compressor (hdr, tileLineSize, numTileLines, false);
+
+ case B44A_COMPRESSION:
+
+ return new B44Compressor (hdr, tileLineSize, numTileLines, true);
+
+ default:
+
+ return 0;
+ }
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfCompressor.h b/Source/OpenEXR/IlmImf/ImfCompressor.h
new file mode 100644
index 0000000..7439fd3
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfCompressor.h
@@ -0,0 +1,251 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_COMPRESSOR_H
+#define INCLUDED_IMF_COMPRESSOR_H
+
+//-----------------------------------------------------------------------------
+//
+// class Compressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompression.h>
+#include "ImathBox.h"
+
+namespace Imf {
+
+class Header;
+
+
+class Compressor
+{
+ public:
+
+ //---------------------------------------------
+ // Constructor -- hdr is the header of the file
+ // that will be compressed or uncompressed
+ //---------------------------------------------
+
+ Compressor (const Header &hdr);
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~Compressor ();
+
+
+ //----------------------------------------------
+ // Maximum number of scan lines processed by
+ // a single call to compress() and uncompress().
+ //----------------------------------------------
+
+ virtual int numScanLines () const = 0;
+
+
+ //--------------------------------------------
+ // Format of the pixel data read and written
+ // by the compress() and uncompress() methods.
+ // The default implementation of format()
+ // returns XDR.
+ //--------------------------------------------
+
+ enum Format
+ {
+ NATIVE, // the machine's native format
+ XDR // Xdr format
+ };
+
+ virtual Format format () const;
+
+
+ //----------------------------
+ // Access to the file's header
+ //----------------------------
+
+ const Header & header () const {return _header;}
+
+
+ //-------------------------------------------------------------------------
+ // Compress an array of bytes that represents the contents of up to
+ // numScanLines() scan lines:
+ //
+ // inPtr Input buffer (uncompressed data).
+ //
+ // inSize Number of bytes in the input buffer
+ //
+ // minY Minimum y coordinate of the scan lines to
+ // be compressed
+ //
+ // outPtr Pointer to output buffer
+ //
+ // return value Size of compressed data in output buffer
+ //
+ // Arrangement of uncompressed pixel data in the input buffer:
+ //
+ // Before calling
+ //
+ // compress (buf, size, minY, ...);
+ //
+ // the InputFile::writePixels() method gathers pixel data from the
+ // frame buffer, fb, and places them in buffer buf, like this:
+ //
+ // char *endOfBuf = buf;
+ //
+ // for (int y = minY;
+ // y <= min (minY + numScanLines() - 1, header().dataWindow().max.y);
+ // ++y)
+ // {
+ // for (ChannelList::ConstIterator c = header().channels().begin();
+ // c != header().channels().end();
+ // ++c)
+ // {
+ // if (modp (y, c.channel().ySampling) != 0)
+ // continue;
+ //
+ // for (int x = header().dataWindow().min.x;
+ // x <= header().dataWindow().max.x;
+ // ++x)
+ // {
+ // if (modp (x, c.channel().xSampling) != 0)
+ // continue;
+ //
+ // Xdr::write<CharPtrIO> (endOfBuf, fb.pixel (c, x, y));
+ // }
+ // }
+ // }
+ //
+ // int size = endOfBuf - buf;
+ //
+ //-------------------------------------------------------------------------
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr) = 0;
+
+ virtual int compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ //-------------------------------------------------------------------------
+ // Uncompress an array of bytes that has been compressed by compress():
+ //
+ // inPtr Input buffer (compressed data).
+ //
+ // inSize Number of bytes in the input buffer
+ //
+ // minY Minimum y coordinate of the scan lines to
+ // be uncompressed
+ //
+ // outPtr Pointer to output buffer
+ //
+ // return value Size of uncompressed data in output buffer
+ //
+ //-------------------------------------------------------------------------
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr) = 0;
+
+ virtual int uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ private:
+
+ const Header & _header;
+};
+
+
+//--------------------------------------
+// Test if c is a valid compression type
+//--------------------------------------
+
+bool isValidCompression (Compression c);
+
+
+//-----------------------------------------------------------------
+// Construct a Compressor for compression type c:
+//
+// maxScanLineSize Maximum number of bytes per uncompressed
+// scan line.
+//
+// header Header of the input or output file whose
+// pixels will be compressed or uncompressed.
+//
+// return value A pointer to a new Compressor object (it
+// is the caller's responsibility to delete
+// the object), or 0 (if c is NO_COMPRESSION).
+//
+//-----------------------------------------------------------------
+
+Compressor * newCompressor (Compression c,
+ int maxScanLineSize,
+ const Header &hdr);
+
+
+//-----------------------------------------------------------------
+// Construct a Compressor for compression type c for a tiled image:
+//
+// tileLineSize Maximum number of bytes per uncompressed
+// line in a tile.
+//
+// numTileLines Maximum number of lines in a tile.
+//
+// header Header of the input or output file whose
+// pixels will be compressed or uncompressed.
+//
+// return value A pointer to a new Compressor object (it
+// is the caller's responsibility to delete
+// the object), or 0 (if c is NO_COMPRESSION).
+//
+//-----------------------------------------------------------------
+
+Compressor * newTileCompressor (Compression c,
+ int tileLineSize,
+ int numTileLines,
+ const Header &hdr);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfConvert.cpp b/Source/OpenEXR/IlmImf/ImfConvert.cpp
new file mode 100644
index 0000000..0d6a4a1
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfConvert.cpp
@@ -0,0 +1,139 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Routines for converting between pixel data types,
+// with well-defined behavior for exceptional cases.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfConvert.h>
+#include <limits.h>
+
+namespace Imf {
+namespace {
+
+inline bool
+isNegative (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+ return (u.i & 0x80000000) != 0;
+}
+
+
+inline bool
+isNan (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+ return (u.i & 0x7fffffff) > 0x7f800000;
+}
+
+
+inline bool
+isInfinity (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+ return (u.i & 0x7fffffff) == 0x7f800000;
+}
+
+
+inline bool
+isFinite (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+ return (u.i & 0x7f800000) != 0x7f800000;
+}
+
+} // namespace
+
+
+unsigned int
+halfToUint (half h)
+{
+ if (h.isNegative() || h.isNan())
+ return 0;
+
+ if (h.isInfinity())
+ return UINT_MAX;
+
+ return (unsigned int) h;
+}
+
+
+unsigned int
+floatToUint (float f)
+{
+ if (isNegative (f) || isNan (f))
+ return 0;
+
+ if (isInfinity (f) || f > UINT_MAX)
+ return UINT_MAX;
+
+ return (unsigned int) f;
+}
+
+
+half
+uintToHalf (unsigned int ui)
+{
+ if (ui > HALF_MAX)
+ return half::posInf();
+
+ return half (ui);
+}
+
+
+half
+floatToHalf (float f)
+{
+ if (isFinite (f))
+ {
+ if (f > HALF_MAX)
+ return half::posInf();
+
+ if (f < -HALF_MAX)
+ return half::negInf();
+ }
+
+ return half (f);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfConvert.h b/Source/OpenEXR/IlmImf/ImfConvert.h
new file mode 100644
index 0000000..fc2c037
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfConvert.h
@@ -0,0 +1,104 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_CONVERT_H
+#define INCLUDED_IMF_CONVERT_H
+
+//-----------------------------------------------------------------------------
+//
+// Routines for converting between pixel data types,
+// with well-defined behavior for exceptional cases,
+// without depending on how hardware and operating
+// system handle integer overflows and floating-point
+// exceptions.
+//
+//-----------------------------------------------------------------------------
+
+#include "half.h"
+
+
+namespace Imf {
+
+//---------------------------------------------------------
+// Conversion from half or float to unsigned int:
+//
+// input result
+// ---------------------------------------------------
+//
+// finite, >= 0 input, cast to unsigned int
+// (rounds towards zero)
+//
+// finite, < 0 0
+//
+// NaN 0
+//
+// +infinity UINT_MAX
+//
+// -infinity 0
+//
+//---------------------------------------------------------
+
+unsigned int halfToUint (half h);
+unsigned int floatToUint (float f);
+
+
+//---------------------------------------------------------
+// Conversion from unsigned int or float to half:
+//
+// input result
+// ---------------------------------------------------
+//
+// finite, closest possible half
+// magnitude <= HALF_MAX
+//
+// finite, > HALF_MAX +infinity
+//
+// finite, < -HALF_MAX -infinity
+//
+// NaN NaN
+//
+// +infinity +infinity
+//
+// -infinity -infinity
+//
+//---------------------------------------------------------
+
+half uintToHalf (unsigned int ui);
+half floatToHalf (float f);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfDoubleAttribute.cpp b/Source/OpenEXR/IlmImf/ImfDoubleAttribute.cpp
new file mode 100644
index 0000000..1ed40c0
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfDoubleAttribute.cpp
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class DoubleAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfDoubleAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+DoubleAttribute::staticTypeName ()
+{
+ return "double";
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfDoubleAttribute.h b/Source/OpenEXR/IlmImf/ImfDoubleAttribute.h
new file mode 100644
index 0000000..bafd1ef
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfDoubleAttribute.h
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_DOUBLE_ATTRIBUTE_H
+#define INCLUDED_IMF_DOUBLE_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class DoubleAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<double> DoubleAttribute;
+template <> const char *DoubleAttribute::staticTypeName ();
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfDoubleAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfEnvmap.cpp b/Source/OpenEXR/IlmImf/ImfEnvmap.cpp
new file mode 100644
index 0000000..fdb04ac
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfEnvmap.cpp
@@ -0,0 +1,328 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Environment maps
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfEnvmap.h>
+#include "ImathFun.h"
+#include <algorithm>
+#include <math.h>
+
+using namespace std;
+using namespace Imath;
+
+namespace Imf {
+namespace LatLongMap {
+
+V2f
+latLong (const V3f &dir)
+{
+ float r = sqrt (dir.z * dir.z + dir.x * dir.x);
+
+ float latitude = (r < abs (dir.y))?
+ acos (r / dir.length()) * sign (dir.y):
+ asin (dir.y / dir.length());
+
+ float longitude = (dir.z == 0 && dir.x == 0)? 0: atan2 (dir.x, dir.z);
+
+ return V2f (latitude, longitude);
+}
+
+
+V2f
+latLong (const Box2i &dataWindow, const V2f &pixelPosition)
+{
+ float latitude, longitude;
+
+ if (dataWindow.max.y > dataWindow.min.y)
+ {
+ latitude = -M_PI *
+ ((pixelPosition.y - dataWindow.min.y) /
+ (dataWindow.max.y - dataWindow.min.y) - 0.5f);
+ }
+ else
+ {
+ latitude = 0;
+ }
+
+ if (dataWindow.max.x > dataWindow.min.x)
+ {
+ longitude = -2 * M_PI *
+ ((pixelPosition.x - dataWindow.min.x) /
+ (dataWindow.max.x - dataWindow.min.x) - 0.5f);
+ }
+ else
+ {
+ longitude = 0;
+ }
+
+ return V2f (latitude, longitude);
+}
+
+
+V2f
+pixelPosition (const Box2i &dataWindow, const V2f &latLong)
+{
+ float x = latLong.y / (-2 * M_PI) + 0.5f;
+ float y = latLong.x / -M_PI + 0.5f;
+
+ return V2f (x * (dataWindow.max.x - dataWindow.min.x) + dataWindow.min.x,
+ y * (dataWindow.max.y - dataWindow.min.y) + dataWindow.min.y);
+}
+
+
+V2f
+pixelPosition (const Box2i &dataWindow, const V3f &direction)
+{
+ return pixelPosition (dataWindow, latLong (direction));
+}
+
+
+V3f
+direction (const Box2i &dataWindow, const V2f &pixelPosition)
+{
+ V2f ll = latLong (dataWindow, pixelPosition);
+
+ return V3f (sin (ll.y) * cos (ll.x),
+ sin (ll.x),
+ cos (ll.y) * cos (ll.x));
+}
+
+} // namespace LatLongMap
+
+
+namespace CubeMap {
+
+int
+sizeOfFace (const Box2i &dataWindow)
+{
+ return min ((dataWindow.max.x - dataWindow.min.x + 1),
+ (dataWindow.max.y - dataWindow.min.y + 1) / 6);
+}
+
+
+Box2i
+dataWindowForFace (CubeMapFace face, const Box2i &dataWindow)
+{
+ int sof = sizeOfFace (dataWindow);
+ Box2i dwf;
+
+ dwf.min.x = 0;
+ dwf.min.y = int (face) * sof;
+
+ dwf.max.x = dwf.min.x + sof - 1;
+ dwf.max.y = dwf.min.y + sof - 1;
+
+ return dwf;
+}
+
+
+V2f
+pixelPosition (CubeMapFace face, const Box2i &dataWindow, V2f positionInFace)
+{
+ Box2i dwf = dataWindowForFace (face, dataWindow);
+ V2f pos (0, 0);
+
+ switch (face)
+ {
+ case CUBEFACE_POS_X:
+
+ pos.x = dwf.min.x + positionInFace.y;
+ pos.y = dwf.max.y - positionInFace.x;
+ break;
+
+ case CUBEFACE_NEG_X:
+
+ pos.x = dwf.max.x - positionInFace.y;
+ pos.y = dwf.max.y - positionInFace.x;
+ break;
+
+ case CUBEFACE_POS_Y:
+
+ pos.x = dwf.min.x + positionInFace.x;
+ pos.y = dwf.max.y - positionInFace.y;
+ break;
+
+ case CUBEFACE_NEG_Y:
+
+ pos.x = dwf.min.x + positionInFace.x;
+ pos.y = dwf.min.y + positionInFace.y;
+ break;
+
+ case CUBEFACE_POS_Z:
+
+ pos.x = dwf.max.x - positionInFace.x;
+ pos.y = dwf.max.y - positionInFace.y;
+ break;
+
+ case CUBEFACE_NEG_Z:
+
+ pos.x = dwf.min.x + positionInFace.x;
+ pos.y = dwf.max.y - positionInFace.y;
+ break;
+ }
+
+ return pos;
+}
+
+
+void
+faceAndPixelPosition (const V3f &direction,
+ const Box2i &dataWindow,
+ CubeMapFace &face,
+ V2f &pif)
+{
+ int sof = sizeOfFace (dataWindow);
+ float absx = abs (direction.x);
+ float absy = abs (direction.y);
+ float absz = abs (direction.z);
+
+ if (absx >= absy && absx >= absz)
+ {
+ if (absx == 0)
+ {
+ //
+ // Special case - direction is (0, 0, 0)
+ //
+
+ face = CUBEFACE_POS_X;
+ pif = V2f (0, 0);
+ return;
+ }
+
+ pif.x = (direction.y / absx + 1) / 2 * (sof - 1);
+ pif.y = (direction.z / absx + 1) / 2 * (sof - 1);
+
+ if (direction.x > 0)
+ face = CUBEFACE_POS_X;
+ else
+ face = CUBEFACE_NEG_X;
+ }
+ else if (absy >= absz)
+ {
+ pif.x = (direction.x / absy + 1) / 2 * (sof - 1);
+ pif.y = (direction.z / absy + 1) / 2 * (sof - 1);
+
+ if (direction.y > 0)
+ face = CUBEFACE_POS_Y;
+ else
+ face = CUBEFACE_NEG_Y;
+ }
+ else
+ {
+ pif.x = (direction.x / absz + 1) / 2 * (sof - 1);
+ pif.y = (direction.y / absz + 1) / 2 * (sof - 1);
+
+ if (direction.z > 0)
+ face = CUBEFACE_POS_Z;
+ else
+ face = CUBEFACE_NEG_Z;
+ }
+}
+
+
+V3f
+direction (CubeMapFace face, const Box2i &dataWindow, const V2f &positionInFace)
+{
+ int sof = sizeOfFace (dataWindow);
+
+ V2f pos;
+
+ if (sof > 1)
+ {
+ pos = V2f (positionInFace.x / (sof - 1) * 2 - 1,
+ positionInFace.y / (sof - 1) * 2 - 1);
+ }
+ else
+ {
+ pos = V2f (0, 0);
+ }
+
+ V3f dir (1, 0, 0);
+
+ switch (face)
+ {
+ case CUBEFACE_POS_X:
+
+ dir.x = 1;
+ dir.y = pos.x;
+ dir.z = pos.y;
+ break;
+
+ case CUBEFACE_NEG_X:
+
+ dir.x = -1;
+ dir.y = pos.x;
+ dir.z = pos.y;
+ break;
+
+ case CUBEFACE_POS_Y:
+
+ dir.x = pos.x;
+ dir.y = 1;
+ dir.z = pos.y;
+ break;
+
+ case CUBEFACE_NEG_Y:
+
+ dir.x = pos.x;
+ dir.y = -1;
+ dir.z = pos.y;
+ break;
+
+ case CUBEFACE_POS_Z:
+
+ dir.x = pos.x;
+ dir.y = pos.y;
+ dir.z = 1;
+ break;
+
+ case CUBEFACE_NEG_Z:
+
+ dir.x = pos.x;
+ dir.y = pos.y;
+ dir.z = -1;
+ break;
+ }
+
+ return dir;
+}
+
+} // namespace CubeMap
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfEnvmap.h b/Source/OpenEXR/IlmImf/ImfEnvmap.h
new file mode 100644
index 0000000..30c61e7
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfEnvmap.h
@@ -0,0 +1,322 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_ENVMAP_H
+#define INCLUDED_IMF_ENVMAP_H
+
+//-----------------------------------------------------------------------------
+//
+// Environment maps
+//
+// Environment maps define a mapping from 3D directions to 2D
+// pixel space locations. Environment maps are typically used
+// in 3D rendering, for effects such as quickly approximating
+// how shiny surfaces reflect their environment.
+//
+// Environment maps can be stored in scanline-based or in tiled
+// OpenEXR files. The fact that an image is an environment map
+// is indicated by the presence of an EnvmapAttribute whose name
+// is "envmap". (Convenience functions to access this attribute
+// are defined in header file ImfStandardAttributes.h.)
+// The attribute's value defines the mapping from 3D directions
+// to 2D pixel space locations.
+//
+// This header file defines the set of possible EnvmapAttribute
+// values.
+//
+// For each possible EnvmapAttribute value, this header file also
+// defines a set of convienience functions to convert between 3D
+// directions and 2D pixel locations.
+//
+// Most of the convenience functions defined below require a
+// dataWindow parameter. For scanline-based images, and for
+// tiled images with level mode ONE_LEVEL, the dataWindow
+// parameter should be set to the image's data window, as
+// defined in the image header. For tiled images with level
+// mode MIPMAP_LEVELS or RIPMAP_LEVELS, the data window of the
+// image level that is being accessed should be used instead.
+// (See the dataWindowForLevel() methods in ImfTiledInputFile.h
+// and ImfTiledOutputFile.h.)
+//
+//-----------------------------------------------------------------------------
+
+#include "ImathBox.h"
+
+namespace Imf {
+
+//--------------------------------
+// Supported environment map types
+//--------------------------------
+
+enum Envmap
+{
+ ENVMAP_LATLONG = 0, // Latitude-longitude environment map
+ ENVMAP_CUBE = 1, // Cube map
+
+ NUM_ENVMAPTYPES // Number of different environment map types
+};
+
+
+//-------------------------------------------------------------------------
+// Latitude-Longitude Map:
+//
+// The environment is projected onto the image using polar coordinates
+// (latitude and longitude). A pixel's x coordinate corresponds to
+// its longitude, and the y coordinate corresponds to its latitude.
+// Pixel (dataWindow.min.x, dataWindow.min.y) has latitude +pi/2 and
+// longitude +pi; pixel (dataWindow.max.x, dataWindow.max.y) has
+// latitude -pi/2 and longitude -pi.
+//
+// In 3D space, latitudes -pi/2 and +pi/2 correspond to the negative and
+// positive y direction. Latitude 0, longitude 0 points into positive
+// z direction; and latitude 0, longitude pi/2 points into positive x
+// direction.
+//
+// The size of the data window should be 2*N by N pixels (width by height),
+// where N can be any integer greater than 0.
+//-------------------------------------------------------------------------
+
+namespace LatLongMap
+{
+ //----------------------------------------------------
+ // Convert a 3D direction to a 2D vector whose x and y
+ // components represent the corresponding latitude
+ // and longitude.
+ //----------------------------------------------------
+
+ Imath::V2f latLong (const Imath::V3f &direction);
+
+
+ //--------------------------------------------------------
+ // Convert the position of a pixel to a 2D vector whose
+ // x and y components represent the corresponding latitude
+ // and longitude.
+ //--------------------------------------------------------
+
+ Imath::V2f latLong (const Imath::Box2i &dataWindow,
+ const Imath::V2f &pixelPosition);
+
+
+ //-------------------------------------------------------------
+ // Convert a 2D vector, whose x and y components represent
+ // longitude and latitude, into a corresponding pixel position.
+ //-------------------------------------------------------------
+
+ Imath::V2f pixelPosition (const Imath::Box2i &dataWindow,
+ const Imath::V2f &latLong);
+
+
+ //-----------------------------------------------------
+ // Convert a 3D direction vector into a corresponding
+ // pixel position. pixelPosition(dw,dir) is equivalent
+ // to pixelPosition(dw,latLong(dw,dir)).
+ //-----------------------------------------------------
+
+ Imath::V2f pixelPosition (const Imath::Box2i &dataWindow,
+ const Imath::V3f &direction);
+
+
+ //--------------------------------------------------------
+ // Convert the position of a pixel in a latitude-longitude
+ // map into a corresponding 3D direction.
+ //--------------------------------------------------------
+
+ Imath::V3f direction (const Imath::Box2i &dataWindow,
+ const Imath::V2f &pixelPosition);
+}
+
+
+//--------------------------------------------------------------
+// Cube Map:
+//
+// The environment is projected onto the six faces of an
+// axis-aligned cube. The cube's faces are then arranged
+// in a 2D image as shown below.
+//
+// 2-----------3
+// / /|
+// / / | Y
+// / / | |
+// 6-----------7 | |
+// | | | |
+// | | | |
+// | 0 | 1 *------- X
+// | | / /
+// | | / /
+// | |/ /
+// 4-----------5 Z
+//
+// dataWindow.min
+// /
+// /
+// +-----------+
+// |3 Y 7|
+// | | |
+// | | |
+// | ---+---Z | +X face
+// | | |
+// | | |
+// |1 5|
+// +-----------+
+// |6 Y 2|
+// | | |
+// | | |
+// | Z---+--- | -X face
+// | | |
+// | | |
+// |4 0|
+// +-----------+
+// |6 Z 7|
+// | | |
+// | | |
+// | ---+---X | +Y face
+// | | |
+// | | |
+// |2 3|
+// +-----------+
+// |0 1|
+// | | |
+// | | |
+// | ---+---X | -Y face
+// | | |
+// | | |
+// |4 Z 5|
+// +-----------+
+// |7 Y 6|
+// | | |
+// | | |
+// | X---+--- | +Z face
+// | | |
+// | | |
+// |5 4|
+// +-----------+
+// |2 Y 3|
+// | | |
+// | | |
+// | ---+---X | -Z face
+// | | |
+// | | |
+// |0 1|
+// +-----------+
+// /
+// /
+// dataWindow.max
+//
+// The size of the data window should be N by 6*N pixels
+// (width by height), where N can be any integer greater
+// than 0.
+//
+//--------------------------------------------------------------
+
+//------------------------------------
+// Names for the six faces of the cube
+//------------------------------------
+
+enum CubeMapFace
+{
+ CUBEFACE_POS_X, // +X face
+ CUBEFACE_NEG_X, // -X face
+ CUBEFACE_POS_Y, // +Y face
+ CUBEFACE_NEG_Y, // -Y face
+ CUBEFACE_POS_Z, // +Z face
+ CUBEFACE_NEG_Z // -Z face
+};
+
+namespace CubeMap
+{
+ //---------------------------------------------
+ // Width and height of a cube's face, in pixels
+ //---------------------------------------------
+
+ int sizeOfFace (const Imath::Box2i &dataWindow);
+
+
+ //------------------------------------------
+ // Compute the region in the environment map
+ // that is covered by the specified face.
+ //------------------------------------------
+
+ Imath::Box2i dataWindowForFace (CubeMapFace face,
+ const Imath::Box2i &dataWindow);
+
+
+ //----------------------------------------------------
+ // Convert the coordinates of a pixel within a face
+ // [in the range from (0,0) to (s-1,s-1), where
+ // s == sizeOfFace(dataWindow)] to pixel coordinates
+ // in the environment map.
+ //----------------------------------------------------
+
+ Imath::V2f pixelPosition (CubeMapFace face,
+ const Imath::Box2i &dataWindow,
+ Imath::V2f positionInFace);
+
+
+ //--------------------------------------------------------------
+ // Convert a 3D direction into a cube face, and a pixel position
+ // within that face.
+ //
+ // If you have a 3D direction, dir, the following code fragment
+ // finds the position, pos, of the corresponding pixel in an
+ // environment map with data window dw:
+ //
+ // CubeMapFace f;
+ // V2f pif, pos;
+ //
+ // faceAndPixelPosition (dir, dw, f, pif);
+ // pos = pixelPosition (f, dw, pif);
+ //
+ //--------------------------------------------------------------
+
+ void faceAndPixelPosition (const Imath::V3f &direction,
+ const Imath::Box2i &dataWindow,
+ CubeMapFace &face,
+ Imath::V2f &positionInFace);
+
+
+ // --------------------------------------------------------
+ // Given a cube face and a pixel position within that face,
+ // compute the corresponding 3D direction.
+ // --------------------------------------------------------
+
+ Imath::V3f direction (CubeMapFace face,
+ const Imath::Box2i &dataWindow,
+ const Imath::V2f &positionInFace);
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.cpp b/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.cpp
new file mode 100644
index 0000000..03a7928
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.cpp
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class EnvmapAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfEnvmapAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+EnvmapAttribute::staticTypeName ()
+{
+ return "envmap";
+}
+
+
+template <>
+void
+EnvmapAttribute::writeValueTo (OStream &os, int version) const
+{
+ unsigned char tmp = _value;
+ Xdr::write <StreamIO> (os, tmp);
+}
+
+
+template <>
+void
+EnvmapAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ unsigned char tmp;
+ Xdr::read <StreamIO> (is, tmp);
+ _value = Envmap (tmp);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.h b/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.h
new file mode 100644
index 0000000..716883f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfEnvmapAttribute.h
@@ -0,0 +1,65 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_IMF_ENVMAP_ATTRIBUTE_H
+#define INCLUDED_IMF_ENVMAP_ATTRIBUTE_H
+
+
+//-----------------------------------------------------------------------------
+//
+// class EnvmapAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfEnvmap.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Envmap> EnvmapAttribute;
+template <> const char *EnvmapAttribute::staticTypeName ();
+template <> void EnvmapAttribute::writeValueTo (OStream &, int) const;
+template <> void EnvmapAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfEnvmapAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfFloatAttribute.cpp b/Source/OpenEXR/IlmImf/ImfFloatAttribute.cpp
new file mode 100644
index 0000000..22366c3
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFloatAttribute.cpp
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class FloatAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfFloatAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+FloatAttribute::staticTypeName ()
+{
+ return "float";
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfFloatAttribute.h b/Source/OpenEXR/IlmImf/ImfFloatAttribute.h
new file mode 100644
index 0000000..60d6f23
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFloatAttribute.h
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_FLOAT_ATTRIBUTE_H
+#define INCLUDED_IMF_FLOAT_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class FloatAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<float> FloatAttribute;
+template <> const char *FloatAttribute::staticTypeName ();
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfFloatAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfFrameBuffer.cpp b/Source/OpenEXR/IlmImf/ImfFrameBuffer.cpp
new file mode 100644
index 0000000..d9c15f3
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFrameBuffer.cpp
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Slice
+// class FrameBuffer
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfFrameBuffer.h>
+#include "Iex.h"
+
+
+namespace Imf {
+
+
+Slice::Slice (PixelType t,
+ char *b,
+ size_t xst,
+ size_t yst,
+ int xsm,
+ int ysm,
+ double fv,
+ bool xtc,
+ bool ytc)
+:
+ type (t),
+ base (b),
+ xStride (xst),
+ yStride (yst),
+ xSampling (xsm),
+ ySampling (ysm),
+ fillValue (fv),
+ xTileCoords (xtc),
+ yTileCoords (ytc)
+{
+ // empty
+}
+
+
+void
+FrameBuffer::insert (const char name[], const Slice &slice)
+{
+ if (name[0] == 0)
+ {
+ THROW (Iex::ArgExc,
+ "Frame buffer slice name cannot be an empty string.");
+ }
+
+ _map[name] = slice;
+}
+
+
+Slice &
+FrameBuffer::operator [] (const char name[])
+{
+ SliceMap::iterator i = _map.find (name);
+
+ if (i == _map.end())
+ {
+ THROW (Iex::ArgExc,
+ "Cannot find frame buffer slice \"" << name << "\".");
+ }
+
+ return i->second;
+}
+
+
+const Slice &
+FrameBuffer::operator [] (const char name[]) const
+{
+ SliceMap::const_iterator i = _map.find (name);
+
+ if (i == _map.end())
+ {
+ THROW (Iex::ArgExc,
+ "Cannot find frame buffer slice \"" << name << "\".");
+ }
+
+ return i->second;
+}
+
+
+Slice *
+FrameBuffer::findSlice (const char name[])
+{
+ SliceMap::iterator i = _map.find (name);
+ return (i == _map.end())? 0: &i->second;
+}
+
+
+const Slice *
+FrameBuffer::findSlice (const char name[]) const
+{
+ SliceMap::const_iterator i = _map.find (name);
+ return (i == _map.end())? 0: &i->second;
+}
+
+
+FrameBuffer::Iterator
+FrameBuffer::begin ()
+{
+ return _map.begin();
+}
+
+
+FrameBuffer::ConstIterator
+FrameBuffer::begin () const
+{
+ return _map.begin();
+}
+
+
+FrameBuffer::Iterator
+FrameBuffer::end ()
+{
+ return _map.end();
+}
+
+
+FrameBuffer::ConstIterator
+FrameBuffer::end () const
+{
+ return _map.end();
+}
+
+
+FrameBuffer::Iterator
+FrameBuffer::find (const char name[])
+{
+ return _map.find (name);
+}
+
+
+FrameBuffer::ConstIterator
+FrameBuffer::find (const char name[]) const
+{
+ return _map.find (name);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfFrameBuffer.h b/Source/OpenEXR/IlmImf/ImfFrameBuffer.h
new file mode 100644
index 0000000..cd24016
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFrameBuffer.h
@@ -0,0 +1,368 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_FRAME_BUFFER_H
+#define INCLUDED_IMF_FRAME_BUFFER_H
+
+//-----------------------------------------------------------------------------
+//
+// class Slice
+// class FrameBuffer
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfName.h>
+#include <ImfPixelType.h>
+#include <map>
+
+
+namespace Imf {
+
+
+//-------------------------------------------------------
+// Description of a single slice of the frame buffer:
+//
+// Note -- terminology: as part of a file, a component of
+// an image (e.g. red, green, blue, depth etc.) is called
+// a "channel". As part of a frame buffer, an image
+// component is called a "slice".
+//-------------------------------------------------------
+
+struct Slice
+{
+ //------------------------------
+ // Data type; see ImfPixelType.h
+ //------------------------------
+
+ PixelType type;
+
+
+ //---------------------------------------------------------------------
+ // Memory layout: The address of pixel (x, y) is
+ //
+ // base + (xp / xSampling) * xStride + (yp / ySampling) * yStride
+ //
+ // where xp and yp are computed as follows:
+ //
+ // * If we are reading or writing a scanline-based file:
+ //
+ // xp = x
+ // yp = y
+ //
+ // * If we are reading a tile whose upper left coorner is at (xt, yt):
+ //
+ // if xTileCoords is true then xp = x - xt, else xp = x
+ // if yTileCoords is true then yp = y - yt, else yp = y
+ //
+ //---------------------------------------------------------------------
+
+ char * base;
+ size_t xStride;
+ size_t yStride;
+
+
+ //--------------------------------------------
+ // Subsampling: pixel (x, y) is present in the
+ // slice only if
+ //
+ // x % xSampling == 0 && y % ySampling == 0
+ //
+ //--------------------------------------------
+
+ int xSampling;
+ int ySampling;
+
+
+ //----------------------------------------------------------
+ // Default value, used to fill the slice when a file without
+ // a channel that corresponds to this slice is read.
+ //----------------------------------------------------------
+
+ double fillValue;
+
+
+ //-------------------------------------------------------
+ // For tiled files, the xTileCoords and yTileCoords flags
+ // determine whether pixel addressing is performed using
+ // absolute coordinates or coordinates relative to a
+ // tile's upper left corner. (See the comment on base,
+ // xStride and yStride, above.)
+ //
+ // For scanline-based files these flags have no effect;
+ // pixel addressing is always done using absolute
+ // coordinates.
+ //-------------------------------------------------------
+
+ bool xTileCoords;
+ bool yTileCoords;
+
+
+ //------------
+ // Constructor
+ //------------
+
+ Slice (PixelType type = HALF,
+ char * base = 0,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ int xSampling = 1,
+ int ySampling = 1,
+ double fillValue = 0.0,
+ bool xTileCoords = false,
+ bool yTileCoords = false);
+};
+
+
+class FrameBuffer
+{
+ public:
+
+ //------------
+ // Add a slice
+ //------------
+
+ void insert (const char name[],
+ const Slice &slice);
+
+ //----------------------------------------------------------------
+ // Access to existing slices:
+ //
+ // [n] Returns a reference to the slice with name n.
+ // If no slice with name n exists, an Iex::ArgExc
+ // is thrown.
+ //
+ // findSlice(n) Returns a pointer to the slice with name n,
+ // or 0 if no slice with name n exists.
+ //
+ //----------------------------------------------------------------
+
+ Slice & operator [] (const char name[]);
+ const Slice & operator [] (const char name[]) const;
+
+ Slice * findSlice (const char name[]);
+ const Slice * findSlice (const char name[]) const;
+
+
+ //-----------------------------------------
+ // Iterator-style access to existing slices
+ //-----------------------------------------
+
+ typedef std::map <Name, Slice> SliceMap;
+
+ class Iterator;
+ class ConstIterator;
+
+ Iterator begin ();
+ ConstIterator begin () const;
+ Iterator end ();
+ ConstIterator end () const;
+ Iterator find (const char name[]);
+ ConstIterator find (const char name[]) const;
+
+ private:
+
+ SliceMap _map;
+};
+
+
+//----------
+// Iterators
+//----------
+
+class FrameBuffer::Iterator
+{
+ public:
+
+ Iterator ();
+ Iterator (const FrameBuffer::SliceMap::iterator &i);
+
+ Iterator & operator ++ ();
+ Iterator operator ++ (int);
+
+ const char * name () const;
+ Slice & slice () const;
+
+ private:
+
+ friend class FrameBuffer::ConstIterator;
+
+ FrameBuffer::SliceMap::iterator _i;
+};
+
+
+class FrameBuffer::ConstIterator
+{
+ public:
+
+ ConstIterator ();
+ ConstIterator (const FrameBuffer::SliceMap::const_iterator &i);
+ ConstIterator (const FrameBuffer::Iterator &other);
+
+ ConstIterator & operator ++ ();
+ ConstIterator operator ++ (int);
+
+ const char * name () const;
+ const Slice & slice () const;
+
+ private:
+
+ friend bool operator == (const ConstIterator &, const ConstIterator &);
+ friend bool operator != (const ConstIterator &, const ConstIterator &);
+
+ FrameBuffer::SliceMap::const_iterator _i;
+};
+
+
+//-----------------
+// Inline Functions
+//-----------------
+
+inline
+FrameBuffer::Iterator::Iterator (): _i()
+{
+ // empty
+}
+
+
+inline
+FrameBuffer::Iterator::Iterator (const FrameBuffer::SliceMap::iterator &i):
+ _i (i)
+{
+ // empty
+}
+
+
+inline FrameBuffer::Iterator &
+FrameBuffer::Iterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline FrameBuffer::Iterator
+FrameBuffer::Iterator::operator ++ (int)
+{
+ Iterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+FrameBuffer::Iterator::name () const
+{
+ return *_i->first;
+}
+
+
+inline Slice &
+FrameBuffer::Iterator::slice () const
+{
+ return _i->second;
+}
+
+
+inline
+FrameBuffer::ConstIterator::ConstIterator (): _i()
+{
+ // empty
+}
+
+inline
+FrameBuffer::ConstIterator::ConstIterator
+ (const FrameBuffer::SliceMap::const_iterator &i): _i (i)
+{
+ // empty
+}
+
+
+inline
+FrameBuffer::ConstIterator::ConstIterator (const FrameBuffer::Iterator &other):
+ _i (other._i)
+{
+ // empty
+}
+
+inline FrameBuffer::ConstIterator &
+FrameBuffer::ConstIterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline FrameBuffer::ConstIterator
+FrameBuffer::ConstIterator::operator ++ (int)
+{
+ ConstIterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+FrameBuffer::ConstIterator::name () const
+{
+ return *_i->first;
+}
+
+inline const Slice &
+FrameBuffer::ConstIterator::slice () const
+{
+ return _i->second;
+}
+
+
+inline bool
+operator == (const FrameBuffer::ConstIterator &x,
+ const FrameBuffer::ConstIterator &y)
+{
+ return x._i == y._i;
+}
+
+
+inline bool
+operator != (const FrameBuffer::ConstIterator &x,
+ const FrameBuffer::ConstIterator &y)
+{
+ return !(x == y);
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfFramesPerSecond.cpp b/Source/OpenEXR/IlmImf/ImfFramesPerSecond.cpp
new file mode 100644
index 0000000..cc533a0
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFramesPerSecond.cpp
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Convenience functions related to the framesPerSecond attribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfFramesPerSecond.h>
+#include "ImathFun.h"
+
+using namespace Imath;
+
+namespace Imf {
+
+Rational
+guessExactFps (double fps)
+{
+ return guessExactFps (Rational (fps));
+}
+
+
+Rational
+guessExactFps (const Rational &fps)
+{
+ const double e = 0.002;
+
+ if (abs (double (fps) - double (fps_23_976())) < e)
+ return fps_23_976();
+
+ if (abs (double (fps) - double (fps_29_97())) < e)
+ return fps_29_97();
+
+ if (abs (double (fps) - double (fps_47_952())) < e)
+ return fps_47_952();
+
+ if (abs (double (fps) - double (fps_59_94())) < e)
+ return fps_59_94();
+
+ return fps;
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfFramesPerSecond.h b/Source/OpenEXR/IlmImf/ImfFramesPerSecond.h
new file mode 100644
index 0000000..cbef984
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfFramesPerSecond.h
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_FRAMES_PER_SECOND_H
+#define INCLUDED_IMF_FRAMES_PER_SECOND_H
+
+//-----------------------------------------------------------------------------
+//
+// Convenience functions related to the framesPerSecond attribute
+//
+// Functions that return the exact values for commonly used frame rates:
+//
+// name frames per second
+//
+// fps_23_976() 23.976023...
+// fps_24() 24.0 35mm film frames
+// fps_25() 25.0 PAL video frames
+// fps_29_97() 29.970029... NTSC video frames
+// fps_30() 30.0 60Hz HDTV frames
+// fps_47_952() 47.952047...
+// fps_48() 48.0
+// fps_50() 50.0 PAL video fields
+// fps_59_94() 59.940059... NTSC video fields
+// fps_60() 60.0 60Hz HDTV fields
+//
+// Functions that try to convert inexact frame rates into exact ones:
+//
+// Given a frame rate, fps, that is close to one of the pre-defined
+// frame rates fps_23_976(), fps_29_97(), fps_47_952() or fps_59_94(),
+// guessExactFps(fps) returns the corresponding pre-defined frame
+// rate. If fps is not close to one of the pre-defined frame rates,
+// then guessExactFps(fps) returns Rational(fps).
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRational.h>
+
+namespace Imf {
+
+inline Rational fps_23_976 () {return Rational (24000, 1001);}
+inline Rational fps_24 () {return Rational (24, 1);}
+inline Rational fps_25 () {return Rational (25, 1);}
+inline Rational fps_29_97 () {return Rational (30000, 1001);}
+inline Rational fps_30 () {return Rational (30, 1);}
+inline Rational fps_47_952 () {return Rational (48000, 1001);}
+inline Rational fps_48 () {return Rational (48, 1);}
+inline Rational fps_50 () {return Rational (50, 1);}
+inline Rational fps_59_94 () {return Rational (60000, 1001);}
+inline Rational fps_60 () {return Rational (60, 1);}
+
+Rational guessExactFps (double fps);
+Rational guessExactFps (const Rational &fps);
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfHeader.cpp b/Source/OpenEXR/IlmImf/ImfHeader.cpp
new file mode 100644
index 0000000..ad8d316
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfHeader.cpp
@@ -0,0 +1,1003 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class Header
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfStdIO.h>
+#include <ImfVersion.h>
+#include <ImfCompressor.h>
+#include <ImfMisc.h>
+#include <ImfBoxAttribute.h>
+#include <ImfChannelListAttribute.h>
+#include <ImfChromaticitiesAttribute.h>
+#include <ImfCompressionAttribute.h>
+#include <ImfDoubleAttribute.h>
+#include <ImfEnvmapAttribute.h>
+#include <ImfFloatAttribute.h>
+#include <ImfIntAttribute.h>
+#include <ImfKeyCodeAttribute.h>
+#include <ImfLineOrderAttribute.h>
+#include <ImfMatrixAttribute.h>
+#include <ImfOpaqueAttribute.h>
+#include <ImfPreviewImageAttribute.h>
+#include <ImfRationalAttribute.h>
+#include <ImfStringAttribute.h>
+#include <ImfTileDescriptionAttribute.h>
+#include <ImfTimeCodeAttribute.h>
+#include <ImfVecAttribute.h>
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <sstream>
+#include <stdlib.h>
+#include <time.h>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::V2i;
+using Imath::V2f;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+
+
+namespace {
+
+int maxImageWidth = 0;
+int maxImageHeight = 0;
+int maxTileWidth = 0;
+int maxTileHeight = 0;
+
+
+void
+initialize (Header &header,
+ const Box2i &displayWindow,
+ const Box2i &dataWindow,
+ float pixelAspectRatio,
+ const V2f &screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression)
+{
+ header.insert ("displayWindow", Box2iAttribute (displayWindow));
+ header.insert ("dataWindow", Box2iAttribute (dataWindow));
+ header.insert ("pixelAspectRatio", FloatAttribute (pixelAspectRatio));
+ header.insert ("screenWindowCenter", V2fAttribute (screenWindowCenter));
+ header.insert ("screenWindowWidth", FloatAttribute (screenWindowWidth));
+ header.insert ("lineOrder", LineOrderAttribute (lineOrder));
+ header.insert ("compression", CompressionAttribute (compression));
+ header.insert ("channels", ChannelListAttribute ());
+}
+
+} // namespace
+
+
+Header::Header (int width,
+ int height,
+ float pixelAspectRatio,
+ const V2f &screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression)
+:
+ _map()
+{
+ staticInitialize();
+
+ Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));
+
+ initialize (*this,
+ displayWindow,
+ displayWindow,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+}
+
+
+Header::Header (int width,
+ int height,
+ const Box2i &dataWindow,
+ float pixelAspectRatio,
+ const V2f &screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression)
+:
+ _map()
+{
+ staticInitialize();
+
+ Box2i displayWindow (V2i (0, 0), V2i (width - 1, height - 1));
+
+ initialize (*this,
+ displayWindow,
+ dataWindow,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+}
+
+
+Header::Header (const Box2i &displayWindow,
+ const Box2i &dataWindow,
+ float pixelAspectRatio,
+ const V2f &screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression)
+:
+ _map()
+{
+ staticInitialize();
+
+ initialize (*this,
+ displayWindow,
+ dataWindow,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+}
+
+
+Header::Header (const Header &other): _map()
+{
+ for (AttributeMap::const_iterator i = other._map.begin();
+ i != other._map.end();
+ ++i)
+ {
+ insert (*i->first, *i->second);
+ }
+}
+
+
+Header::~Header ()
+{
+ for (AttributeMap::iterator i = _map.begin();
+ i != _map.end();
+ ++i)
+ {
+ delete i->second;
+ }
+}
+
+
+Header &
+Header::operator = (const Header &other)
+{
+ if (this != &other)
+ {
+ for (AttributeMap::iterator i = _map.begin();
+ i != _map.end();
+ ++i)
+ {
+ delete i->second;
+ }
+
+ _map.erase (_map.begin(), _map.end());
+
+ for (AttributeMap::const_iterator i = other._map.begin();
+ i != other._map.end();
+ ++i)
+ {
+ insert (*i->first, *i->second);
+ }
+ }
+
+ return *this;
+}
+
+
+void
+Header::insert (const char name[], const Attribute &attribute)
+{
+ if (name[0] == 0)
+ THROW (Iex::ArgExc, "Image attribute name cannot be an empty string.");
+
+ AttributeMap::iterator i = _map.find (name);
+
+ if (i == _map.end())
+ {
+ Attribute *tmp = attribute.copy();
+
+ try
+ {
+ _map[name] = tmp;
+ }
+ catch (...)
+ {
+ delete tmp;
+ throw;
+ }
+ }
+ else
+ {
+ if (strcmp (i->second->typeName(), attribute.typeName()))
+ THROW (Iex::TypeExc, "Cannot assign a value of "
+ "type \"" << attribute.typeName() << "\" "
+ "to image attribute \"" << name << "\" of "
+ "type \"" << i->second->typeName() << "\".");
+
+ Attribute *tmp = attribute.copy();
+ delete i->second;
+ i->second = tmp;
+ }
+}
+
+
+Attribute &
+Header::operator [] (const char name[])
+{
+ AttributeMap::iterator i = _map.find (name);
+
+ if (i == _map.end())
+ THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\".");
+
+ return *i->second;
+}
+
+
+const Attribute &
+Header::operator [] (const char name[]) const
+{
+ AttributeMap::const_iterator i = _map.find (name);
+
+ if (i == _map.end())
+ THROW (Iex::ArgExc, "Cannot find image attribute \"" << name << "\".");
+
+ return *i->second;
+}
+
+
+Header::Iterator
+Header::begin ()
+{
+ return _map.begin();
+}
+
+
+Header::ConstIterator
+Header::begin () const
+{
+ return _map.begin();
+}
+
+
+Header::Iterator
+Header::end ()
+{
+ return _map.end();
+}
+
+
+Header::ConstIterator
+Header::end () const
+{
+ return _map.end();
+}
+
+
+Header::Iterator
+Header::find (const char name[])
+{
+ return _map.find (name);
+}
+
+
+Header::ConstIterator
+Header::find (const char name[]) const
+{
+ return _map.find (name);
+}
+
+
+Imath::Box2i &
+Header::displayWindow ()
+{
+ return static_cast <Box2iAttribute &>
+ ((*this)["displayWindow"]).value();
+}
+
+
+const Imath::Box2i &
+Header::displayWindow () const
+{
+ return static_cast <const Box2iAttribute &>
+ ((*this)["displayWindow"]).value();
+}
+
+Imath::Box2i &
+Header::dataWindow ()
+{
+ return static_cast <Box2iAttribute &>
+ ((*this)["dataWindow"]).value();
+}
+
+
+const Imath::Box2i &
+Header::dataWindow () const
+{
+ return static_cast <const Box2iAttribute &>
+ ((*this)["dataWindow"]).value();
+}
+
+
+float &
+Header::pixelAspectRatio ()
+{
+ return static_cast <FloatAttribute &>
+ ((*this)["pixelAspectRatio"]).value();
+}
+
+
+const float &
+Header::pixelAspectRatio () const
+{
+ return static_cast <const FloatAttribute &>
+ ((*this)["pixelAspectRatio"]).value();
+}
+
+
+Imath::V2f &
+Header::screenWindowCenter ()
+{
+ return static_cast <V2fAttribute &>
+ ((*this)["screenWindowCenter"]).value();
+}
+
+
+const Imath::V2f &
+Header::screenWindowCenter () const
+{
+ return static_cast <const V2fAttribute &>
+ ((*this)["screenWindowCenter"]).value();
+}
+
+
+float &
+Header::screenWindowWidth ()
+{
+ return static_cast <FloatAttribute &>
+ ((*this)["screenWindowWidth"]).value();
+}
+
+
+const float &
+Header::screenWindowWidth () const
+{
+ return static_cast <const FloatAttribute &>
+ ((*this)["screenWindowWidth"]).value();
+}
+
+
+ChannelList &
+Header::channels ()
+{
+ return static_cast <ChannelListAttribute &>
+ ((*this)["channels"]).value();
+}
+
+
+const ChannelList &
+Header::channels () const
+{
+ return static_cast <const ChannelListAttribute &>
+ ((*this)["channels"]).value();
+}
+
+
+LineOrder &
+Header::lineOrder ()
+{
+ return static_cast <LineOrderAttribute &>
+ ((*this)["lineOrder"]).value();
+}
+
+
+const LineOrder &
+Header::lineOrder () const
+{
+ return static_cast <const LineOrderAttribute &>
+ ((*this)["lineOrder"]).value();
+}
+
+
+Compression &
+Header::compression ()
+{
+ return static_cast <CompressionAttribute &>
+ ((*this)["compression"]).value();
+}
+
+
+const Compression &
+Header::compression () const
+{
+ return static_cast <const CompressionAttribute &>
+ ((*this)["compression"]).value();
+}
+
+
+void
+Header::setTileDescription(const TileDescription& td)
+{
+ insert ("tiles", TileDescriptionAttribute (td));
+}
+
+
+bool
+Header::hasTileDescription() const
+{
+ return findTypedAttribute <TileDescriptionAttribute> ("tiles") != 0;
+}
+
+
+TileDescription &
+Header::tileDescription ()
+{
+ return typedAttribute <TileDescriptionAttribute> ("tiles").value();
+}
+
+
+const TileDescription &
+Header::tileDescription () const
+{
+ return typedAttribute <TileDescriptionAttribute> ("tiles").value();
+}
+
+void
+Header::setPreviewImage (const PreviewImage &pi)
+{
+ insert ("preview", PreviewImageAttribute (pi));
+}
+
+
+PreviewImage &
+Header::previewImage ()
+{
+ return typedAttribute <PreviewImageAttribute> ("preview").value();
+}
+
+
+const PreviewImage &
+Header::previewImage () const
+{
+ return typedAttribute <PreviewImageAttribute> ("preview").value();
+}
+
+
+bool
+Header::hasPreviewImage () const
+{
+ return findTypedAttribute <PreviewImageAttribute> ("preview") != 0;
+}
+
+
+void
+Header::sanityCheck (bool isTiled) const
+{
+ //
+ // The display window and the data window must each
+ // contain at least one pixel. In addition, the
+ // coordinates of the window corners must be small
+ // enough to keep expressions like max-min+1 or
+ // max+min from overflowing.
+ //
+
+ const Box2i &displayWindow = this->displayWindow();
+
+ if (displayWindow.min.x > displayWindow.max.x ||
+ displayWindow.min.y > displayWindow.max.y ||
+ displayWindow.min.x <= -(INT_MAX / 2) ||
+ displayWindow.min.y <= -(INT_MAX / 2) ||
+ displayWindow.max.x >= (INT_MAX / 2) ||
+ displayWindow.max.y >= (INT_MAX / 2))
+ {
+ throw Iex::ArgExc ("Invalid display window in image header.");
+ }
+
+ const Box2i &dataWindow = this->dataWindow();
+
+ if (dataWindow.min.x > dataWindow.max.x ||
+ dataWindow.min.y > dataWindow.max.y ||
+ dataWindow.min.x <= -(INT_MAX / 2) ||
+ dataWindow.min.y <= -(INT_MAX / 2) ||
+ dataWindow.max.x >= (INT_MAX / 2) ||
+ dataWindow.max.y >= (INT_MAX / 2))
+ {
+ throw Iex::ArgExc ("Invalid data window in image header.");
+ }
+
+ if (maxImageWidth > 0 &&
+ maxImageWidth < dataWindow.max.x - dataWindow.min.x + 1)
+ {
+ THROW (Iex::ArgExc, "The width of the data window exceeds the "
+ "maximum width of " << maxImageWidth << "pixels.");
+ }
+
+ if (maxImageHeight > 0 &&
+ maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1)
+ {
+ THROW (Iex::ArgExc, "The width of the data window exceeds the "
+ "maximum width of " << maxImageHeight << "pixels.");
+ }
+
+ //
+ // The pixel aspect ratio must be greater than 0.
+ // In applications, numbers like the the display or
+ // data window dimensions are likely to be multiplied
+ // or divided by the pixel aspect ratio; to avoid
+ // arithmetic exceptions, we limit the pixel aspect
+ // ratio to a range that is smaller than theoretically
+ // possible (real aspect ratios are likely to be close
+ // to 1.0 anyway).
+ //
+
+ float pixelAspectRatio = this->pixelAspectRatio();
+
+ const float MIN_PIXEL_ASPECT_RATIO = 1e-6;
+ const float MAX_PIXEL_ASPECT_RATIO = 1e+6;
+
+ if (pixelAspectRatio < MIN_PIXEL_ASPECT_RATIO ||
+ pixelAspectRatio > MAX_PIXEL_ASPECT_RATIO)
+ {
+ throw Iex::ArgExc ("Invalid pixel aspect ratio in image header.");
+ }
+
+ //
+ // The screen window width must not be less than 0.
+ // The size of the screen window can vary over a wide
+ // range (fish-eye lens to astronomical telescope),
+ // so we can't limit the screen window width to a
+ // small range.
+ //
+
+ float screenWindowWidth = this->screenWindowWidth();
+
+ if (screenWindowWidth < 0)
+ throw Iex::ArgExc ("Invalid screen window width in image header.");
+
+ //
+ // If the file is tiled, verify that the tile description has resonable
+ // values and check to see if the lineOrder is one of the predefined 3.
+ // If the file is not tiled, then the lineOrder can only be INCREASING_Y
+ // or DECREASING_Y.
+ //
+
+ LineOrder lineOrder = this->lineOrder();
+
+ if (isTiled)
+ {
+ if (!hasTileDescription())
+ {
+ throw Iex::ArgExc ("Tiled image has no tile "
+ "description attribute.");
+ }
+
+ const TileDescription &tileDesc = tileDescription();
+
+ if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
+ throw Iex::ArgExc ("Invalid tile size in image header.");
+
+ if (maxTileWidth > 0 &&
+ maxTileWidth < tileDesc.xSize)
+ {
+ THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum "
+ "width of " << maxTileWidth << "pixels.");
+ }
+
+ if (maxTileHeight > 0 &&
+ maxTileHeight < tileDesc.ySize)
+ {
+ THROW (Iex::ArgExc, "The width of the tiles exceeds the maximum "
+ "width of " << maxTileHeight << "pixels.");
+ }
+
+ if (tileDesc.mode != ONE_LEVEL &&
+ tileDesc.mode != MIPMAP_LEVELS &&
+ tileDesc.mode != RIPMAP_LEVELS)
+ throw Iex::ArgExc ("Invalid level mode in image header.");
+
+ if (tileDesc.roundingMode != ROUND_UP &&
+ tileDesc.roundingMode != ROUND_DOWN)
+ throw Iex::ArgExc ("Invalid level rounding mode in image header.");
+
+ if (lineOrder != INCREASING_Y &&
+ lineOrder != DECREASING_Y &&
+ lineOrder != RANDOM_Y)
+ throw Iex::ArgExc ("Invalid line order in image header.");
+ }
+ else
+ {
+ if (lineOrder != INCREASING_Y &&
+ lineOrder != DECREASING_Y)
+ throw Iex::ArgExc ("Invalid line order in image header.");
+ }
+
+ //
+ // The compression method must be one of the predefined values.
+ //
+
+ if (!isValidCompression (this->compression()))
+ throw Iex::ArgExc ("Unknown compression type in image header.");
+
+ //
+ // Check the channel list:
+ //
+ // If the file is tiled then for each channel, the type must be one of the
+ // predefined values, and the x and y sampling must both be 1.
+ //
+ // If the file is not tiled then for each channel, the type must be one
+ // of the predefined values, the x and y coordinates of the data window's
+ // upper left corner must be divisible by the x and y subsampling factors,
+ // and the width and height of the data window must be divisible by the
+ // x and y subsampling factors.
+ //
+
+ const ChannelList &channels = this->channels();
+
+ if (isTiled)
+ {
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ if (i.channel().type != UINT &&
+ i.channel().type != HALF &&
+ i.channel().type != FLOAT)
+ {
+ THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
+ "image channel is invalid.");
+ }
+
+ if (i.channel().xSampling != 1)
+ {
+ THROW (Iex::ArgExc, "The x subsampling factor for the "
+ "\"" << i.name() << "\" channel "
+ "is not 1.");
+ }
+
+ if (i.channel().ySampling != 1)
+ {
+ THROW (Iex::ArgExc, "The y subsampling factor for the "
+ "\"" << i.name() << "\" channel "
+ "is not 1.");
+ }
+ }
+ }
+ else
+ {
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ if (i.channel().type != UINT &&
+ i.channel().type != HALF &&
+ i.channel().type != FLOAT)
+ {
+ THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" "
+ "image channel is invalid.");
+ }
+
+ if (i.channel().xSampling < 1)
+ {
+ THROW (Iex::ArgExc, "The x subsampling factor for the "
+ "\"" << i.name() << "\" channel "
+ "is invalid.");
+ }
+
+ if (i.channel().ySampling < 1)
+ {
+ THROW (Iex::ArgExc, "The y subsampling factor for the "
+ "\"" << i.name() << "\" channel "
+ "is invalid.");
+ }
+
+ if (dataWindow.min.x % i.channel().xSampling)
+ {
+ THROW (Iex::ArgExc, "The minimum x coordinate of the "
+ "image's data window is not a multiple "
+ "of the x subsampling factor of "
+ "the \"" << i.name() << "\" channel.");
+ }
+
+ if (dataWindow.min.y % i.channel().ySampling)
+ {
+ THROW (Iex::ArgExc, "The minimum y coordinate of the "
+ "image's data window is not a multiple "
+ "of the y subsampling factor of "
+ "the \"" << i.name() << "\" channel.");
+ }
+
+ if ((dataWindow.max.x - dataWindow.min.x + 1) %
+ i.channel().xSampling)
+ {
+ THROW (Iex::ArgExc, "Number of pixels per row in the "
+ "image's data window is not a multiple "
+ "of the x subsampling factor of "
+ "the \"" << i.name() << "\" channel.");
+ }
+
+ if ((dataWindow.max.y - dataWindow.min.y + 1) %
+ i.channel().ySampling)
+ {
+ THROW (Iex::ArgExc, "Number of pixels per column in the "
+ "image's data window is not a multiple "
+ "of the y subsampling factor of "
+ "the \"" << i.name() << "\" channel.");
+ }
+ }
+ }
+}
+
+
+void
+Header::setMaxImageSize (int maxWidth, int maxHeight)
+{
+ maxImageWidth = maxWidth;
+ maxImageHeight = maxHeight;
+}
+
+
+void
+Header::setMaxTileSize (int maxWidth, int maxHeight)
+{
+ maxTileWidth = maxWidth;
+ maxTileHeight = maxHeight;
+}
+
+
+Int64
+Header::writeTo (OStream &os, bool isTiled) const
+{
+ //
+ // Write a "magic number" to identify the file as an image file.
+ // Write the current file format version number.
+ //
+
+ Xdr::write <StreamIO> (os, MAGIC);
+
+ int version = isTiled ? makeTiled (EXR_VERSION) : EXR_VERSION;
+ Xdr::write <StreamIO> (os, version);
+
+ //
+ // Write all attributes. If we have a preview image attribute,
+ // keep track of its position in the file.
+ //
+
+ Int64 previewPosition = 0;
+
+ const Attribute *preview =
+ findTypedAttribute <PreviewImageAttribute> ("preview");
+
+ for (ConstIterator i = begin(); i != end(); ++i)
+ {
+ //
+ // Write the attribute's name and type.
+ //
+
+ Xdr::write <StreamIO> (os, i.name());
+ Xdr::write <StreamIO> (os, i.attribute().typeName());
+
+ //
+ // Write the size of the attribute value,
+ // and the value itself.
+ //
+
+ StdOSStream oss;
+ i.attribute().writeValueTo (oss, version);
+
+ std::string s = oss.str();
+ Xdr::write <StreamIO> (os, (int) s.length());
+
+ if (&i.attribute() == preview)
+ previewPosition = os.tellp();
+
+ os.write (s.data(), s.length());
+ }
+
+ //
+ // Write zero-length attribute name to mark the end of the header.
+ //
+
+ Xdr::write <StreamIO> (os, "");
+
+ return previewPosition;
+}
+
+
+void
+Header::readFrom (IStream &is, int &version)
+{
+ //
+ // Read the magic number and the file format version number.
+ // Then check if we can read the rest of this file.
+ //
+
+ int magic;
+
+ Xdr::read <StreamIO> (is, magic);
+ Xdr::read <StreamIO> (is, version);
+
+ if (magic != MAGIC)
+ {
+ throw Iex::InputExc ("File is not an image file.");
+ }
+
+ if (getVersion (version) != EXR_VERSION)
+ {
+ THROW (Iex::InputExc, "Cannot read "
+ "version " << getVersion (version) << " "
+ "image files. Current file format version "
+ "is " << EXR_VERSION << ".");
+ }
+
+ if (!supportsFlags (getFlags (version)))
+ {
+ THROW (Iex::InputExc, "The file format version number's flag field "
+ "contains unrecognized flags.");
+ }
+
+ //
+ // Read all attributes.
+ //
+
+ while (true)
+ {
+ //
+ // Read the name of the attribute.
+ // A zero-length attribute name indicates the end of the header.
+ //
+
+ char name[100];
+ Xdr::read <StreamIO> (is, sizeof (name), name);
+
+ if (name[0] == 0)
+ break;
+
+ //
+ // Read the attribute type and the size of the attribute value.
+ //
+
+ char typeName[100];
+ int size;
+
+ Xdr::read <StreamIO> (is, sizeof (typeName), typeName);
+ Xdr::read <StreamIO> (is, size);
+
+ AttributeMap::iterator i = _map.find (name);
+
+ if (i != _map.end())
+ {
+ //
+ // The attribute already exists (for example,
+ // because it is a predefined attribute).
+ // Read the attribute's new value from the file.
+ //
+
+ if (strncmp (i->second->typeName(), typeName, sizeof (typeName)))
+ THROW (Iex::InputExc, "Unexpected type for image attribute "
+ "\"" << name << "\".");
+
+ i->second->readValueFrom (is, size, version);
+ }
+ else
+ {
+ //
+ // The new attribute does not exist yet.
+ // If the attribute type is of a known type,
+ // read the attribute value. If the attribute
+ // is of an unknown type, read its value and
+ // store it as an OpaqueAttribute.
+ //
+
+ Attribute *attr;
+
+ if (Attribute::knownType (typeName))
+ attr = Attribute::newAttribute (typeName);
+ else
+ attr = new OpaqueAttribute (typeName);
+
+ try
+ {
+ attr->readValueFrom (is, size, version);
+ _map[name] = attr;
+ }
+ catch (...)
+ {
+ delete attr;
+ throw;
+ }
+ }
+ }
+}
+
+
+void
+staticInitialize ()
+{
+ static Mutex criticalSection;
+ Lock lock (criticalSection);
+
+ static bool initialized = false;
+
+ if (!initialized)
+ {
+ //
+ // One-time initialization -- register
+ // some predefined attribute types.
+ //
+
+ Box2fAttribute::registerAttributeType();
+ Box2iAttribute::registerAttributeType();
+ ChannelListAttribute::registerAttributeType();
+ CompressionAttribute::registerAttributeType();
+ ChromaticitiesAttribute::registerAttributeType();
+ DoubleAttribute::registerAttributeType();
+ EnvmapAttribute::registerAttributeType();
+ FloatAttribute::registerAttributeType();
+ IntAttribute::registerAttributeType();
+ KeyCodeAttribute::registerAttributeType();
+ LineOrderAttribute::registerAttributeType();
+ M33fAttribute::registerAttributeType();
+ M44fAttribute::registerAttributeType();
+ PreviewImageAttribute::registerAttributeType();
+ RationalAttribute::registerAttributeType();
+ StringAttribute::registerAttributeType();
+ TileDescriptionAttribute::registerAttributeType();
+ TimeCodeAttribute::registerAttributeType();
+ V2fAttribute::registerAttributeType();
+ V2iAttribute::registerAttributeType();
+ V3fAttribute::registerAttributeType();
+ V3iAttribute::registerAttributeType();
+
+ initialized = true;
+ }
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfHeader.h b/Source/OpenEXR/IlmImf/ImfHeader.h
new file mode 100644
index 0000000..5e2cd42
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfHeader.h
@@ -0,0 +1,577 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_HEADER_H
+#define INCLUDED_IMF_HEADER_H
+
+//-----------------------------------------------------------------------------
+//
+// class Header
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfLineOrder.h>
+#include <ImfCompression.h>
+#include <ImfName.h>
+#include <ImfTileDescription.h>
+#include <ImfInt64.h>
+#include "ImathVec.h"
+#include "ImathBox.h"
+#include "IexBaseExc.h"
+#include <map>
+#include <iosfwd>
+
+namespace Imf {
+
+
+class Attribute;
+class ChannelList;
+class IStream;
+class OStream;
+class PreviewImage;
+
+
+class Header
+{
+ public:
+
+ //----------------------------------------------------------------
+ // Default constructor -- the display window and the data window
+ // are both set to Box2i (V2i (0, 0), V2i (width-1, height-1).
+ //----------------------------------------------------------------
+
+ Header (int width = 64,
+ int height = 64,
+ float pixelAspectRatio = 1,
+ const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression = ZIP_COMPRESSION);
+
+
+ //--------------------------------------------------------------------
+ // Constructor -- the data window is specified explicitly; the display
+ // window is set to Box2i (V2i (0, 0), V2i (width-1, height-1).
+ //--------------------------------------------------------------------
+
+ Header (int width,
+ int height,
+ const Imath::Box2i &dataWindow,
+ float pixelAspectRatio = 1,
+ const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression = ZIP_COMPRESSION);
+
+
+ //----------------------------------------------------------
+ // Constructor -- the display window and the data window are
+ // both specified explicitly.
+ //----------------------------------------------------------
+
+ Header (const Imath::Box2i &displayWindow,
+ const Imath::Box2i &dataWindow,
+ float pixelAspectRatio = 1,
+ const Imath::V2f &screenWindowCenter = Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression = ZIP_COMPRESSION);
+
+
+ //-----------------
+ // Copy constructor
+ //-----------------
+
+ Header (const Header &other);
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ ~Header ();
+
+
+ //-----------
+ // Assignment
+ //-----------
+
+ Header & operator = (const Header &other);
+
+
+ //---------------------------------------------------------------
+ // Add an attribute:
+ //
+ // insert(n,attr) If no attribute with name n exists, a new
+ // attribute with name n, and the same type as
+ // attr, is added, and the value of attr is
+ // copied into the new attribute.
+ //
+ // If an attribute with name n exists, and its
+ // type is the same as attr, the value of attr
+ // is copied into this attribute.
+ //
+ // If an attribute with name n exists, and its
+ // type is different from attr, an Iex::TypeExc
+ // is thrown.
+ //
+ //---------------------------------------------------------------
+
+ void insert (const char name[],
+ const Attribute &attribute);
+
+ //------------------------------------------------------------------
+ // Access to existing attributes:
+ //
+ // [n] Returns a reference to the attribute
+ // with name n. If no attribute with
+ // name n exists, an Iex::ArgExc is thrown.
+ //
+ // typedAttribute<T>(n) Returns a reference to the attribute
+ // with name n and type T. If no attribute
+ // with name n exists, an Iex::ArgExc is
+ // thrown. If an attribute with name n
+ // exists, but its type is not T, an
+ // Iex::TypeExc is thrown.
+ //
+ // findTypedAttribute<T>(n) Returns a pointer to the attribute with
+ // name n and type T, or 0 if no attribute
+ // with name n and type T exists.
+ //
+ //------------------------------------------------------------------
+
+ Attribute & operator [] (const char name[]);
+ const Attribute & operator [] (const char name[]) const;
+
+ template <class T> T& typedAttribute (const char name[]);
+ template <class T> const T& typedAttribute (const char name[]) const;
+
+ template <class T> T* findTypedAttribute (const char name[]);
+ template <class T> const T* findTypedAttribute (const char name[]) const;
+
+
+ //---------------------------------------------
+ // Iterator-style access to existing attributes
+ //---------------------------------------------
+
+ typedef std::map <Name, Attribute *> AttributeMap;
+
+ class Iterator;
+ class ConstIterator;
+
+ Iterator begin ();
+ ConstIterator begin () const;
+ Iterator end ();
+ ConstIterator end () const;
+ Iterator find (const char name[]);
+ ConstIterator find (const char name[]) const;
+
+
+ //--------------------------------
+ // Access to predefined attributes
+ //--------------------------------
+
+ Imath::Box2i & displayWindow ();
+ const Imath::Box2i & displayWindow () const;
+
+ Imath::Box2i & dataWindow ();
+ const Imath::Box2i & dataWindow () const;
+
+ float & pixelAspectRatio ();
+ const float & pixelAspectRatio () const;
+
+ Imath::V2f & screenWindowCenter ();
+ const Imath::V2f & screenWindowCenter () const;
+
+ float & screenWindowWidth ();
+ const float & screenWindowWidth () const;
+
+ ChannelList & channels ();
+ const ChannelList & channels () const;
+
+ LineOrder & lineOrder ();
+ const LineOrder & lineOrder () const;
+
+ Compression & compression ();
+ const Compression & compression () const;
+
+
+ //----------------------------------------------------------------------
+ // Tile Description:
+ //
+ // The tile description is a TileDescriptionAttribute whose name
+ // is "tiles". The "tiles" attribute must be present in any tiled
+ // image file. When present, it describes various properties of the
+ // tiles that make up the file.
+ //
+ // Convenience functions:
+ //
+ // setTileDescription(td)
+ // calls insert ("tiles", TileDescriptionAttribute (td))
+ //
+ // tileDescription()
+ // returns typedAttribute<TileDescriptionAttribute>("tiles").value()
+ //
+ // hasTileDescription()
+ // return findTypedAttribute<TileDescriptionAttribute>("tiles") != 0
+ //
+ //----------------------------------------------------------------------
+
+ void setTileDescription (const TileDescription & td);
+
+ TileDescription & tileDescription ();
+ const TileDescription & tileDescription () const;
+
+ bool hasTileDescription() const;
+
+
+ //----------------------------------------------------------------------
+ // Preview image:
+ //
+ // The preview image is a PreviewImageAttribute whose name is "preview".
+ // This attribute is special -- while an image file is being written,
+ // the pixels of the preview image can be changed repeatedly by calling
+ // OutputFile::updatePreviewImage().
+ //
+ // Convenience functions:
+ //
+ // setPreviewImage(p)
+ // calls insert ("preview", PreviewImageAttribute (p))
+ //
+ // previewImage()
+ // returns typedAttribute<PreviewImageAttribute>("preview").value()
+ //
+ // hasPreviewImage()
+ // return findTypedAttribute<PreviewImageAttribute>("preview") != 0
+ //
+ //----------------------------------------------------------------------
+
+ void setPreviewImage (const PreviewImage &p);
+
+ PreviewImage & previewImage ();
+ const PreviewImage & previewImage () const;
+
+ bool hasPreviewImage () const;
+
+
+ //-------------------------------------------------------------
+ // Sanity check -- examines the header, and throws an exception
+ // if it finds something wrong (empty display window, negative
+ // pixel aspect ratio, unknown compression sceme etc.)
+ //
+ // set isTiled to true if you are checking a tiled/multi-res
+ // header
+ //-------------------------------------------------------------
+
+ void sanityCheck (bool isTiled = false) const;
+
+
+ //----------------------------------------------------------------
+ // Maximum image size and maximim tile size:
+ //
+ // sanityCheck() will throw an exception if the width or height of
+ // the data window exceeds the maximum image width or height, or
+ // if the size of a tile exceeds the maximum tile width or height.
+ //
+ // At program startup the maximum image and tile width and height
+ // are set to zero, meaning that width and height are unlimited.
+ //
+ // Limiting image and tile width and height limits how much memory
+ // will be allocated when a file is opened. This can help protect
+ // applications from running out of memory while trying to read
+ // a damaged image file.
+ //----------------------------------------------------------------
+
+ static void setMaxImageSize (int maxWidth, int maxHeight);
+ static void setMaxTileSize (int maxWidth, int maxHeight);
+
+
+ //------------------------------------------------------------------
+ // Input and output:
+ //
+ // If the header contains a preview image attribute, then writeTo()
+ // returns the position of that attribute in the output stream; this
+ // information is used by OutputFile::updatePreviewImage().
+ // If the header contains no preview image attribute, then writeTo()
+ // returns 0.
+ //------------------------------------------------------------------
+
+
+ Int64 writeTo (OStream &os,
+ bool isTiled = false) const;
+
+ void readFrom (IStream &is, int &version);
+
+ private:
+
+ AttributeMap _map;
+};
+
+
+//----------
+// Iterators
+//----------
+
+class Header::Iterator
+{
+ public:
+
+ Iterator ();
+ Iterator (const Header::AttributeMap::iterator &i);
+
+ Iterator & operator ++ ();
+ Iterator operator ++ (int);
+
+ const char * name () const;
+ Attribute & attribute () const;
+
+ private:
+
+ friend class Header::ConstIterator;
+
+ Header::AttributeMap::iterator _i;
+};
+
+
+class Header::ConstIterator
+{
+ public:
+
+ ConstIterator ();
+ ConstIterator (const Header::AttributeMap::const_iterator &i);
+ ConstIterator (const Header::Iterator &other);
+
+ ConstIterator & operator ++ ();
+ ConstIterator operator ++ (int);
+
+ const char * name () const;
+ const Attribute & attribute () const;
+
+ private:
+
+ friend bool operator == (const ConstIterator &, const ConstIterator &);
+ friend bool operator != (const ConstIterator &, const ConstIterator &);
+
+ Header::AttributeMap::const_iterator _i;
+};
+
+
+//------------------------------------------------------------------------
+// Library initialization:
+//
+// In a multithreaded program, staticInitialize() must be called once
+// during startup, before the program accesses any other functions or
+// classes in the IlmImf library. Calling staticInitialize() in this
+// way avoids races during initialization of the library's global
+// variables.
+//
+// Single-threaded programs are not required to call staticInitialize();
+// initialization of the library's global variables happens automatically.
+//
+//------------------------------------------------------------------------
+
+void staticInitialize ();
+
+
+//-----------------
+// Inline Functions
+//-----------------
+
+
+inline
+Header::Iterator::Iterator (): _i()
+{
+ // empty
+}
+
+
+inline
+Header::Iterator::Iterator (const Header::AttributeMap::iterator &i): _i (i)
+{
+ // empty
+}
+
+
+inline Header::Iterator &
+Header::Iterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline Header::Iterator
+Header::Iterator::operator ++ (int)
+{
+ Iterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+Header::Iterator::name () const
+{
+ return *_i->first;
+}
+
+
+inline Attribute &
+Header::Iterator::attribute () const
+{
+ return *_i->second;
+}
+
+
+inline
+Header::ConstIterator::ConstIterator (): _i()
+{
+ // empty
+}
+
+inline
+Header::ConstIterator::ConstIterator
+ (const Header::AttributeMap::const_iterator &i): _i (i)
+{
+ // empty
+}
+
+
+inline
+Header::ConstIterator::ConstIterator (const Header::Iterator &other):
+ _i (other._i)
+{
+ // empty
+}
+
+inline Header::ConstIterator &
+Header::ConstIterator::operator ++ ()
+{
+ ++_i;
+ return *this;
+}
+
+
+inline Header::ConstIterator
+Header::ConstIterator::operator ++ (int)
+{
+ ConstIterator tmp = *this;
+ ++_i;
+ return tmp;
+}
+
+
+inline const char *
+Header::ConstIterator::name () const
+{
+ return *_i->first;
+}
+
+
+inline const Attribute &
+Header::ConstIterator::attribute () const
+{
+ return *_i->second;
+}
+
+
+inline bool
+operator == (const Header::ConstIterator &x, const Header::ConstIterator &y)
+{
+ return x._i == y._i;
+}
+
+
+inline bool
+operator != (const Header::ConstIterator &x, const Header::ConstIterator &y)
+{
+ return !(x == y);
+}
+
+
+//---------------------
+// Template definitions
+//---------------------
+
+template <class T>
+T &
+Header::typedAttribute (const char name[])
+{
+ Attribute *attr = &(*this)[name];
+ T *tattr = dynamic_cast <T*> (attr);
+
+ if (tattr == 0)
+ throw Iex::TypeExc ("Unexpected attribute type.");
+
+ return *tattr;
+}
+
+
+template <class T>
+const T &
+Header::typedAttribute (const char name[]) const
+{
+ const Attribute *attr = &(*this)[name];
+ const T *tattr = dynamic_cast <const T*> (attr);
+
+ if (tattr == 0)
+ throw Iex::TypeExc ("Unexpected attribute type.");
+
+ return *tattr;
+}
+
+
+template <class T>
+T *
+Header::findTypedAttribute (const char name[])
+{
+ AttributeMap::iterator i = _map.find (name);
+ return (i == _map.end())? 0: dynamic_cast <T*> (i->second);
+}
+
+
+template <class T>
+const T *
+Header::findTypedAttribute (const char name[]) const
+{
+ AttributeMap::const_iterator i = _map.find (name);
+ return (i == _map.end())? 0: dynamic_cast <const T*> (i->second);
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfHuf.cpp b/Source/OpenEXR/IlmImf/ImfHuf.cpp
new file mode 100644
index 0000000..4aa60e3
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfHuf.cpp
@@ -0,0 +1,1072 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+//-----------------------------------------------------------------------------
+//
+// 16-bit Huffman compression and decompression.
+//
+// The source code in this file is derived from the 8-bit
+// Huffman compression and decompression routines written
+// by Christian Rouet for his PIZ image file format.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHuf.h>
+#include <ImfInt64.h>
+#include <ImfAutoArray.h>
+#include "Iex.h"
+#include <string.h>
+#include <assert.h>
+#include <algorithm>
+
+
+using namespace std;
+using namespace Iex;
+
+namespace Imf {
+namespace {
+
+
+const int HUF_ENCBITS = 16; // literal (value) bit length
+const int HUF_DECBITS = 14; // decoding bit size (>= 8)
+
+const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1; // encoding table size
+const int HUF_DECSIZE = 1 << HUF_DECBITS; // decoding table size
+const int HUF_DECMASK = HUF_DECSIZE - 1;
+
+
+struct HufDec
+{ // short code long code
+ //-------------------------------
+ int len:8; // code length 0
+ int lit:24; // lit p size
+ int * p; // 0 lits
+};
+
+
+void
+invalidNBits ()
+{
+ throw InputExc ("Error in header for Huffman-encoded data "
+ "(invalid number of bits).");
+}
+
+
+void
+tooMuchData ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(decoded data are longer than expected).");
+}
+
+
+void
+notEnoughData ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(decoded data are shorter than expected).");
+}
+
+
+void
+invalidCode ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(invalid code).");
+}
+
+
+void
+invalidTableSize ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(invalid code table size).");
+}
+
+
+void
+unexpectedEndOfTable ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(unexpected end of code table data).");
+}
+
+
+void
+tableTooLong ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(code table is longer than expected).");
+}
+
+
+void
+invalidTableEntry ()
+{
+ throw InputExc ("Error in Huffman-encoded data "
+ "(invalid code table entry).");
+}
+
+
+inline Int64
+hufLength (Int64 code)
+{
+ return code & 63;
+}
+
+
+inline Int64
+hufCode (Int64 code)
+{
+ return code >> 6;
+}
+
+
+inline void
+outputBits (int nBits, Int64 bits, Int64 &c, int &lc, char *&out)
+{
+ c <<= nBits;
+ lc += nBits;
+
+ c |= bits;
+
+ while (lc >= 8)
+ *out++ = (c >> (lc -= 8));
+}
+
+
+inline Int64
+getBits (int nBits, Int64 &c, int &lc, const char *&in)
+{
+ while (lc < nBits)
+ {
+ c = (c << 8) | *(unsigned char *)(in++);
+ lc += 8;
+ }
+
+ lc -= nBits;
+ return (c >> lc) & ((1 << nBits) - 1);
+}
+
+
+//
+// ENCODING TABLE BUILDING & (UN)PACKING
+//
+
+//
+// Build a "canonical" Huffman code table:
+// - for each (uncompressed) symbol, hcode contains the length
+// of the corresponding code (in the compressed data)
+// - canonical codes are computed and stored in hcode
+// - the rules for constructing canonical codes are as follows:
+// * shorter codes (if filled with zeroes to the right)
+// have a numerically higher value than longer codes
+// * for codes with the same length, numerical values
+// increase with numerical symbol values
+// - because the canonical code table can be constructed from
+// symbol lengths alone, the code table can be transmitted
+// without sending the actual code values
+// - see http://www.compressconsult.com/huffman/
+//
+
+void
+hufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE])
+{
+ Int64 n[59];
+
+ //
+ // For each i from 0 through 58, count the
+ // number of different codes of length i, and
+ // store the count in n[i].
+ //
+
+ for (int i = 0; i <= 58; ++i)
+ n[i] = 0;
+
+ for (int i = 0; i < HUF_ENCSIZE; ++i)
+ n[hcode[i]] += 1;
+
+ //
+ // For each i from 58 through 1, compute the
+ // numerically lowest code with length i, and
+ // store that code in n[i].
+ //
+
+ Int64 c = 0;
+
+ for (int i = 58; i > 0; --i)
+ {
+ Int64 nc = ((c + n[i]) >> 1);
+ n[i] = c;
+ c = nc;
+ }
+
+ //
+ // hcode[i] contains the length, l, of the
+ // code for symbol i. Assign the next available
+ // code of length l to the symbol and store both
+ // l and the code in hcode[i].
+ //
+
+ for (int i = 0; i < HUF_ENCSIZE; ++i)
+ {
+ int l = hcode[i];
+
+ if (l > 0)
+ hcode[i] = l | (n[l]++ << 6);
+ }
+}
+
+
+//
+// Compute Huffman codes (based on frq input) and store them in frq:
+// - code structure is : [63:lsb - 6:msb] | [5-0: bit length];
+// - max code length is 58 bits;
+// - codes outside the range [im-iM] have a null length (unused values);
+// - original frequencies are destroyed;
+// - encoding tables are used by hufEncode() and hufBuildDecTable();
+//
+
+
+struct FHeapCompare
+{
+ bool operator () (Int64 *a, Int64 *b) {return *a > *b;}
+};
+
+
+void
+hufBuildEncTable
+ (Int64* frq, // io: input frequencies [HUF_ENCSIZE], output table
+ int* im, // o: min frq index
+ int* iM) // o: max frq index
+{
+ //
+ // This function assumes that when it is called, array frq
+ // indicates the frequency of all possible symbols in the data
+ // that are to be Huffman-encoded. (frq[i] contains the number
+ // of occurrences of symbol i in the data.)
+ //
+ // The loop below does three things:
+ //
+ // 1) Finds the minimum and maximum indices that point
+ // to non-zero entries in frq:
+ //
+ // frq[im] != 0, and frq[i] == 0 for all i < im
+ // frq[iM] != 0, and frq[i] == 0 for all i > iM
+ //
+ // 2) Fills array fHeap with pointers to all non-zero
+ // entries in frq.
+ //
+ // 3) Initializes array hlink such that hlink[i] == i
+ // for all array entries.
+ //
+
+ AutoArray <int, HUF_ENCSIZE> hlink;
+ AutoArray <Int64 *, HUF_ENCSIZE> fHeap;
+
+ *im = 0;
+
+ while (!frq[*im])
+ (*im)++;
+
+ int nf = 0;
+
+ for (int i = *im; i < HUF_ENCSIZE; i++)
+ {
+ hlink[i] = i;
+
+ if (frq[i])
+ {
+ fHeap[nf] = &frq[i];
+ nf++;
+ *iM = i;
+ }
+ }
+
+ //
+ // Add a pseudo-symbol, with a frequency count of 1, to frq;
+ // adjust the fHeap and hlink array accordingly. Function
+ // hufEncode() uses the pseudo-symbol for run-length encoding.
+ //
+
+ (*iM)++;
+ frq[*iM] = 1;
+ fHeap[nf] = &frq[*iM];
+ nf++;
+
+ //
+ // Build an array, scode, such that scode[i] contains the number
+ // of bits assigned to symbol i. Conceptually this is done by
+ // constructing a tree whose leaves are the symbols with non-zero
+ // frequency:
+ //
+ // Make a heap that contains all symbols with a non-zero frequency,
+ // with the least frequent symbol on top.
+ //
+ // Repeat until only one symbol is left on the heap:
+ //
+ // Take the two least frequent symbols off the top of the heap.
+ // Create a new node that has first two nodes as children, and
+ // whose frequency is the sum of the frequencies of the first
+ // two nodes. Put the new node back into the heap.
+ //
+ // The last node left on the heap is the root of the tree. For each
+ // leaf node, the distance between the root and the leaf is the length
+ // of the code for the corresponding symbol.
+ //
+ // The loop below doesn't actually build the tree; instead we compute
+ // the distances of the leaves from the root on the fly. When a new
+ // node is added to the heap, then that node's descendants are linked
+ // into a single linear list that starts at the new node, and the code
+ // lengths of the descendants (that is, their distance from the root
+ // of the tree) are incremented by one.
+ //
+
+ make_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
+
+ AutoArray <Int64, HUF_ENCSIZE> scode;
+ memset (scode, 0, sizeof (Int64) * HUF_ENCSIZE);
+
+ while (nf > 1)
+ {
+ //
+ // Find the indices, mm and m, of the two smallest non-zero frq
+ // values in fHeap, add the smallest frq to the second-smallest
+ // frq, and remove the smallest frq value from fHeap.
+ //
+
+ int mm = fHeap[0] - frq;
+ pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
+ --nf;
+
+ int m = fHeap[0] - frq;
+ pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
+
+ frq[m ] += frq[mm];
+ push_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
+
+ //
+ // The entries in scode are linked into lists with the
+ // entries in hlink serving as "next" pointers and with
+ // the end of a list marked by hlink[j] == j.
+ //
+ // Traverse the lists that start at scode[m] and scode[mm].
+ // For each element visited, increment the length of the
+ // corresponding code by one bit. (If we visit scode[j]
+ // during the traversal, then the code for symbol j becomes
+ // one bit longer.)
+ //
+ // Merge the lists that start at scode[m] and scode[mm]
+ // into a single list that starts at scode[m].
+ //
+
+ //
+ // Add a bit to all codes in the first list.
+ //
+
+ for (int j = m; true; j = hlink[j])
+ {
+ scode[j]++;
+
+ assert (scode[j] <= 58);
+
+ if (hlink[j] == j)
+ {
+ //
+ // Merge the two lists.
+ //
+
+ hlink[j] = mm;
+ break;
+ }
+ }
+
+ //
+ // Add a bit to all codes in the second list
+ //
+
+ for (int j = mm; true; j = hlink[j])
+ {
+ scode[j]++;
+
+ assert (scode[j] <= 58);
+
+ if (hlink[j] == j)
+ break;
+ }
+ }
+
+ //
+ // Build a canonical Huffman code table, replacing the code
+ // lengths in scode with (code, code length) pairs. Copy the
+ // code table from scode into frq.
+ //
+
+ hufCanonicalCodeTable (scode);
+ memcpy (frq, scode, sizeof (Int64) * HUF_ENCSIZE);
+}
+
+
+//
+// Pack an encoding table:
+// - only code lengths, not actual codes, are stored
+// - runs of zeroes are compressed as follows:
+//
+// unpacked packed
+// --------------------------------
+// 1 zero 0 (6 bits)
+// 2 zeroes 59
+// 3 zeroes 60
+// 4 zeroes 61
+// 5 zeroes 62
+// n zeroes (6 or more) 63 n-6 (6 + 8 bits)
+//
+
+const int SHORT_ZEROCODE_RUN = 59;
+const int LONG_ZEROCODE_RUN = 63;
+const int SHORTEST_LONG_RUN = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
+const int LONGEST_LONG_RUN = 255 + SHORTEST_LONG_RUN;
+
+
+void
+hufPackEncTable
+ (const Int64* hcode, // i : encoding table [HUF_ENCSIZE]
+ int im, // i : min hcode index
+ int iM, // i : max hcode index
+ char** pcode) // o: ptr to packed table (updated)
+{
+ char *p = *pcode;
+ Int64 c = 0;
+ int lc = 0;
+
+ for (; im <= iM; im++)
+ {
+ int l = hufLength (hcode[im]);
+
+ if (l == 0)
+ {
+ int zerun = 1;
+
+ while ((im < iM) && (zerun < LONGEST_LONG_RUN))
+ {
+ if (hufLength (hcode[im+1]) > 0 )
+ break;
+ im++;
+ zerun++;
+ }
+
+ if (zerun >= 2)
+ {
+ if (zerun >= SHORTEST_LONG_RUN)
+ {
+ outputBits (6, LONG_ZEROCODE_RUN, c, lc, p);
+ outputBits (8, zerun - SHORTEST_LONG_RUN, c, lc, p);
+ }
+ else
+ {
+ outputBits (6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);
+ }
+ continue;
+ }
+ }
+
+ outputBits (6, l, c, lc, p);
+ }
+
+ if (lc > 0)
+ *p++ = (unsigned char) (c << (8 - lc));
+
+ *pcode = p;
+}
+
+
+//
+// Unpack an encoding table packed by hufPackEncTable():
+//
+
+void
+hufUnpackEncTable
+ (const char** pcode, // io: ptr to packed table (updated)
+ int ni, // i : input size (in bytes)
+ int im, // i : min hcode index
+ int iM, // i : max hcode index
+ Int64* hcode) // o: encoding table [HUF_ENCSIZE]
+{
+ memset (hcode, 0, sizeof (Int64) * HUF_ENCSIZE);
+
+ const char *p = *pcode;
+ Int64 c = 0;
+ int lc = 0;
+
+ for (; im <= iM; im++)
+ {
+ if (p - *pcode > ni)
+ unexpectedEndOfTable();
+
+ Int64 l = hcode[im] = getBits (6, c, lc, p); // code length
+
+ if (l == (Int64) LONG_ZEROCODE_RUN)
+ {
+ if (p - *pcode > ni)
+ unexpectedEndOfTable();
+
+ int zerun = getBits (8, c, lc, p) + SHORTEST_LONG_RUN;
+
+ if (im + zerun > iM + 1)
+ tableTooLong();
+
+ while (zerun--)
+ hcode[im++] = 0;
+
+ im--;
+ }
+ else if (l >= (Int64) SHORT_ZEROCODE_RUN)
+ {
+ int zerun = l - SHORT_ZEROCODE_RUN + 2;
+
+ if (im + zerun > iM + 1)
+ tableTooLong();
+
+ while (zerun--)
+ hcode[im++] = 0;
+
+ im--;
+ }
+ }
+
+ *pcode = (char *) p;
+
+ hufCanonicalCodeTable (hcode);
+}
+
+
+//
+// DECODING TABLE BUILDING
+//
+
+//
+// Build a decoding hash table based on the encoding table hcode:
+// - short codes (<= HUF_DECBITS) are resolved with a single table access;
+// - long code entry allocations are not optimized, because long codes are
+// unfrequent;
+// - decoding tables are used by hufDecode();
+//
+
+void
+hufBuildDecTable
+ (const Int64* hcode, // i : encoding table
+ int im, // i : min index in hcode
+ int iM, // i : max index in hcode
+ HufDec * hdecod) // o: (allocated by caller)
+ // decoding table [HUF_DECSIZE]
+{
+ //
+ // Init hashtable & loop on all codes
+ //
+
+ memset (hdecod, 0, sizeof (HufDec) * HUF_DECSIZE);
+
+ for (; im <= iM; im++)
+ {
+ Int64 c = hufCode (hcode[im]);
+ int l = hufLength (hcode[im]);
+
+ if (c >> l)
+ {
+ //
+ // Error: c is supposed to be an l-bit code,
+ // but c contains a value that is greater
+ // than the largest l-bit number.
+ //
+
+ invalidTableEntry();
+ }
+
+ if (l > HUF_DECBITS)
+ {
+ //
+ // Long code: add a secondary entry
+ //
+
+ HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));
+
+ if (pl->len)
+ {
+ //
+ // Error: a short code has already
+ // been stored in table entry *pl.
+ //
+
+ invalidTableEntry();
+ }
+
+ pl->lit++;
+
+ if (pl->p)
+ {
+ int *p = pl->p;
+ pl->p = new int [pl->lit];
+
+ for (int i = 0; i < pl->lit - 1; ++i)
+ pl->p[i] = p[i];
+
+ delete [] p;
+ }
+ else
+ {
+ pl->p = new int [1];
+ }
+
+ pl->p[pl->lit - 1]= im;
+ }
+ else if (l)
+ {
+ //
+ // Short code: init all primary entries
+ //
+
+ HufDec *pl = hdecod + (c << (HUF_DECBITS - l));
+
+ for (Int64 i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++)
+ {
+ if (pl->len || pl->p)
+ {
+ //
+ // Error: a short code or a long code has
+ // already been stored in table entry *pl.
+ //
+
+ invalidTableEntry();
+ }
+
+ pl->len = l;
+ pl->lit = im;
+ }
+ }
+ }
+}
+
+
+//
+// Free the long code entries of a decoding table built by hufBuildDecTable()
+//
+
+void
+hufFreeDecTable (HufDec *hdecod) // io: Decoding table
+{
+ for (int i = 0; i < HUF_DECSIZE; i++)
+ {
+ if (hdecod[i].p)
+ {
+ delete [] hdecod[i].p;
+ hdecod[i].p = 0;
+ }
+ }
+}
+
+
+//
+// ENCODING
+//
+
+inline void
+outputCode (Int64 code, Int64 &c, int &lc, char *&out)
+{
+ outputBits (hufLength (code), hufCode (code), c, lc, out);
+}
+
+
+inline void
+sendCode (Int64 sCode, int runCount, Int64 runCode,
+ Int64 &c, int &lc, char *&out)
+{
+ static const int RLMIN = 32; // min count to activate run-length coding
+
+ if (runCount > RLMIN)
+ {
+ outputCode (sCode, c, lc, out);
+ outputCode (runCode, c, lc, out);
+ outputBits (8, runCount, c, lc, out);
+ }
+ else
+ {
+ while (runCount-- >= 0)
+ outputCode (sCode, c, lc, out);
+ }
+}
+
+
+//
+// Encode (compress) ni values based on the Huffman encoding table hcode:
+//
+
+int
+hufEncode // return: output size (in bits)
+ (const Int64* hcode, // i : encoding table
+ const unsigned short* in, // i : uncompressed input buffer
+ const int ni, // i : input buffer size (in bytes)
+ int rlc, // i : rl code
+ char* out) // o: compressed output buffer
+{
+ char *outStart = out;
+ Int64 c = 0; // bits not yet written to out
+ int lc = 0; // number of valid bits in c (LSB)
+ int s = in[0];
+ int cs = 0;
+
+ //
+ // Loop on input values
+ //
+
+ for (int i = 1; i < ni; i++)
+ {
+ //
+ // Count same values or send code
+ //
+
+ if (s == in[i] && cs < 255)
+ {
+ cs++;
+ }
+ else
+ {
+ sendCode (hcode[s], cs, hcode[rlc], c, lc, out);
+ cs=0;
+ }
+
+ s = in[i];
+ }
+
+ //
+ // Send remaining code
+ //
+
+ sendCode (hcode[s], cs, hcode[rlc], c, lc, out);
+
+ if (lc)
+ *out = (c << (8 - lc)) & 0xff;
+
+ return (out - outStart) * 8 + lc;
+}
+
+
+//
+// DECODING
+//
+
+//
+// In order to force the compiler to inline them,
+// getChar() and getCode() are implemented as macros
+// instead of "inline" functions.
+//
+
+#define getChar(c, lc, in) \
+{ \
+ c = (c << 8) | *(unsigned char *)(in++); \
+ lc += 8; \
+}
+
+
+#define getCode(po, rlc, c, lc, in, out, oe) \
+{ \
+ if (po == rlc) \
+ { \
+ if (lc < 8) \
+ getChar(c, lc, in); \
+ \
+ lc -= 8; \
+ \
+ unsigned char cs = (c >> lc); \
+ \
+ if (out + cs > oe) \
+ tooMuchData(); \
+ \
+ unsigned short s = out[-1]; \
+ \
+ while (cs-- > 0) \
+ *out++ = s; \
+ } \
+ else if (out < oe) \
+ { \
+ *out++ = po; \
+ } \
+ else \
+ { \
+ tooMuchData(); \
+ } \
+}
+
+
+//
+// Decode (uncompress) ni bits based on encoding & decoding tables:
+//
+
+void
+hufDecode
+ (const Int64 * hcode, // i : encoding table
+ const HufDec * hdecod, // i : decoding table
+ const char* in, // i : compressed input buffer
+ int ni, // i : input size (in bits)
+ int rlc, // i : run-length code
+ int no, // i : expected output size (in bytes)
+ unsigned short* out) // o: uncompressed output buffer
+{
+ Int64 c = 0;
+ int lc = 0;
+ unsigned short * outb = out;
+ unsigned short * oe = out + no;
+ const char * ie = in + (ni + 7) / 8; // input byte size
+
+ //
+ // Loop on input bytes
+ //
+
+ while (in < ie)
+ {
+ getChar (c, lc, in);
+
+ //
+ // Access decoding table
+ //
+
+ while (lc >= HUF_DECBITS)
+ {
+ const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK];
+
+ if (pl.len)
+ {
+ //
+ // Get short code
+ //
+
+ lc -= pl.len;
+ getCode (pl.lit, rlc, c, lc, in, out, oe);
+ }
+ else
+ {
+ if (!pl.p)
+ invalidCode(); // wrong code
+
+ //
+ // Search long code
+ //
+
+ int j;
+
+ for (j = 0; j < pl.lit; j++)
+ {
+ int l = hufLength (hcode[pl.p[j]]);
+
+ while (lc < l && in < ie) // get more bits
+ getChar (c, lc, in);
+
+ if (lc >= l)
+ {
+ if (hufCode (hcode[pl.p[j]]) ==
+ ((c >> (lc - l)) & ((Int64(1) << l) - 1)))
+ {
+ //
+ // Found : get long code
+ //
+
+ lc -= l;
+ getCode (pl.p[j], rlc, c, lc, in, out, oe);
+ break;
+ }
+ }
+ }
+
+ if (j == pl.lit)
+ invalidCode(); // Not found
+ }
+ }
+ }
+
+ //
+ // Get remaining (short) codes
+ //
+
+ int i = (8 - ni) & 7;
+ c >>= i;
+ lc -= i;
+
+ while (lc > 0)
+ {
+ const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];
+
+ if (pl.len)
+ {
+ lc -= pl.len;
+ getCode (pl.lit, rlc, c, lc, in, out, oe);
+ }
+ else
+ {
+ invalidCode(); // wrong (long) code
+ }
+ }
+
+ if (out - outb != no)
+ notEnoughData ();
+}
+
+
+void
+countFrequencies (Int64 freq[HUF_ENCSIZE],
+ const unsigned short data[/*n*/],
+ int n)
+{
+ for (int i = 0; i < HUF_ENCSIZE; ++i)
+ freq[i] = 0;
+
+ for (int i = 0; i < n; ++i)
+ ++freq[data[i]];
+}
+
+
+void
+writeUInt (char buf[4], unsigned int i)
+{
+ unsigned char *b = (unsigned char *) buf;
+
+ b[0] = i;
+ b[1] = i >> 8;
+ b[2] = i >> 16;
+ b[3] = i >> 24;
+}
+
+
+unsigned int
+readUInt (const char buf[4])
+{
+ const unsigned char *b = (const unsigned char *) buf;
+
+ return ( b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ ((b[3] << 24) & 0xff000000);
+}
+
+} // namespace
+
+
+//
+// EXTERNAL INTERFACE
+//
+
+
+int
+hufCompress (const unsigned short raw[],
+ int nRaw,
+ char compressed[])
+{
+ if (nRaw == 0)
+ return 0;
+
+ AutoArray <Int64, HUF_ENCSIZE> freq;
+
+ countFrequencies (freq, raw, nRaw);
+
+ int im, iM;
+ hufBuildEncTable (freq, &im, &iM);
+
+ char *tableStart = compressed + 20;
+ char *tableEnd = tableStart;
+ hufPackEncTable (freq, im, iM, &tableEnd);
+ int tableLength = tableEnd - tableStart;
+
+ char *dataStart = tableEnd;
+ int nBits = hufEncode (freq, raw, nRaw, iM, dataStart);
+ int dataLength = (nBits + 7) / 8;
+
+ writeUInt (compressed, im);
+ writeUInt (compressed + 4, iM);
+ writeUInt (compressed + 8, tableLength);
+ writeUInt (compressed + 12, nBits);
+ writeUInt (compressed + 16, 0); // room for future extensions
+
+ return dataStart + dataLength - compressed;
+}
+
+
+void
+hufUncompress (const char compressed[],
+ int nCompressed,
+ unsigned short raw[],
+ int nRaw)
+{
+ if (nCompressed == 0)
+ {
+ if (nRaw != 0)
+ notEnoughData();
+
+ return;
+ }
+
+ int im = readUInt (compressed);
+ int iM = readUInt (compressed + 4);
+ // int tableLength = readUInt (compressed + 8);
+ int nBits = readUInt (compressed + 12);
+
+ if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE)
+ invalidTableSize();
+
+ const char *ptr = compressed + 20;
+
+ AutoArray <Int64, HUF_ENCSIZE> freq;
+ AutoArray <HufDec, HUF_DECSIZE> hdec;
+
+ hufUnpackEncTable (&ptr, nCompressed - (ptr - compressed), im, iM, freq);
+
+ try
+ {
+ if (nBits > 8 * (nCompressed - (ptr - compressed)))
+ invalidNBits();
+
+ hufBuildDecTable (freq, im, iM, hdec);
+ hufDecode (freq, hdec, ptr, nBits, iM, nRaw, raw);
+ }
+ catch (...)
+ {
+ hufFreeDecTable (hdec);
+ throw;
+ }
+
+ hufFreeDecTable (hdec);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfHuf.h b/Source/OpenEXR/IlmImf/ImfHuf.h
new file mode 100644
index 0000000..5134dfd
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfHuf.h
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_HUF_H
+#define INCLUDED_IMF_HUF_H
+
+
+//-----------------------------------------------------------------------------
+//
+// 16-bit Huffman compression and decompression:
+//
+// hufCompress (r, nr, c)
+//
+// Compresses the contents of array r (of length nr),
+// stores the compressed data in array c, and returns
+// the size of the compressed data (in bytes).
+//
+// To avoid buffer overflows, the size of array c should
+// be at least 2 * nr + 65536.
+//
+// hufUncompress (c, nc, r, nr)
+//
+// Uncompresses the data in array c (with length nc),
+// and stores the results in array r (with length nr).
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+int
+hufCompress (const unsigned short raw[/*nRaw*/],
+ int nRaw,
+ char compressed[/*2 * nRaw + 65536*/]);
+
+
+void
+hufUncompress (const char compressed[/*nCompressed*/],
+ int nCompressed,
+ unsigned short raw[/*nRaw*/],
+ int nRaw);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfIO.cpp b/Source/OpenEXR/IlmImf/ImfIO.cpp
new file mode 100644
index 0000000..711cdbb
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfIO.cpp
@@ -0,0 +1,109 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Low-level file input and output for OpenEXR.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfIO.h>
+#include "Iex.h"
+
+namespace Imf {
+
+
+IStream::IStream (const char fileName[]): _fileName (fileName)
+{
+ // empty
+}
+
+
+IStream::~IStream ()
+{
+ // empty
+}
+
+
+bool
+IStream::isMemoryMapped () const
+{
+ return false;
+}
+
+
+char *
+IStream::readMemoryMapped (int n)
+{
+ throw Iex::InputExc ("Attempt to perform a memory-mapped read "
+ "on a file that is not memory mapped.");
+ return 0;
+}
+
+
+void
+IStream::clear ()
+{
+ // empty
+}
+
+
+const char *
+IStream::fileName () const
+{
+ return _fileName.c_str();
+}
+
+
+OStream::OStream (const char fileName[]): _fileName (fileName)
+{
+ // empty
+}
+
+
+OStream::~OStream ()
+{
+ // empty
+}
+
+
+const char *
+OStream::fileName () const
+{
+ return _fileName.c_str();
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfIO.h b/Source/OpenEXR/IlmImf/ImfIO.h
new file mode 100644
index 0000000..44f51a3
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfIO.h
@@ -0,0 +1,252 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_IO_H
+#define INCLUDED_IMF_IO_H
+
+//-----------------------------------------------------------------------------
+//
+// Low-level file input and output for OpenEXR.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfInt64.h>
+#include <string>
+
+namespace Imf {
+
+//-----------------------------------------------------------
+// class IStream -- an abstract base class for input streams.
+//-----------------------------------------------------------
+
+class IStream
+{
+ public:
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~IStream ();
+
+
+ //-------------------------------------------------
+ // Does this input stream support memory-mapped IO?
+ //
+ // Memory-mapped streams can avoid an extra copy;
+ // memory-mapped read operations return a pointer
+ // to an internal buffer instead of copying data
+ // into a buffer supplied by the caller.
+ //-------------------------------------------------
+
+ virtual bool isMemoryMapped () const;
+
+
+ //------------------------------------------------------
+ // Read from the stream:
+ //
+ // read(c,n) reads n bytes from the stream, and stores
+ // them in array c. If the stream contains less than n
+ // bytes, or if an I/O error occurs, read(c,n) throws
+ // an exception. If read(c,n) reads the last byte from
+ // the file it returns false, otherwise it returns true.
+ //------------------------------------------------------
+
+ virtual bool read (char c[/*n*/], int n) = 0;
+
+
+ //---------------------------------------------------
+ // Read from a memory-mapped stream:
+ //
+ // readMemoryMapped(n) reads n bytes from the stream
+ // and returns a pointer to the first byte. The
+ // returned pointer remains valid until the stream
+ // is closed. If there are less than n byte left to
+ // read in the stream or if the stream is not memory-
+ // mapped, readMemoryMapped(n) throws an exception.
+ //---------------------------------------------------
+
+ virtual char * readMemoryMapped (int n);
+
+
+ //--------------------------------------------------------
+ // Get the current reading position, in bytes from the
+ // beginning of the file. If the next call to read() will
+ // read the first byte in the file, tellg() returns 0.
+ //--------------------------------------------------------
+
+ virtual Int64 tellg () = 0;
+
+
+ //-------------------------------------------
+ // Set the current reading position.
+ // After calling seekg(i), tellg() returns i.
+ //-------------------------------------------
+
+ virtual void seekg (Int64 pos) = 0;
+
+
+ //------------------------------------------------------
+ // Clear error conditions after an operation has failed.
+ //------------------------------------------------------
+
+ virtual void clear ();
+
+
+ //------------------------------------------------------
+ // Get the name of the file associated with this stream.
+ //------------------------------------------------------
+
+ const char * fileName () const;
+
+ protected:
+
+ IStream (const char fileName[]);
+
+ private:
+
+ IStream (const IStream &); // not implemented
+ IStream & operator = (const IStream &); // not implemented
+
+ std::string _fileName;
+};
+
+
+//-----------------------------------------------------------
+// class OStream -- an abstract base class for output streams
+//-----------------------------------------------------------
+
+class OStream
+{
+ public:
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~OStream ();
+
+
+ //----------------------------------------------------------
+ // Write to the stream:
+ //
+ // write(c,n) takes n bytes from array c, and stores them
+ // in the stream. If an I/O error occurs, write(c,n) throws
+ // an exception.
+ //----------------------------------------------------------
+
+ virtual void write (const char c[/*n*/], int n) = 0;
+
+
+ //---------------------------------------------------------
+ // Get the current writing position, in bytes from the
+ // beginning of the file. If the next call to write() will
+ // start writing at the beginning of the file, tellp()
+ // returns 0.
+ //---------------------------------------------------------
+
+ virtual Int64 tellp () = 0;
+
+
+ //-------------------------------------------
+ // Set the current writing position.
+ // After calling seekp(i), tellp() returns i.
+ //-------------------------------------------
+
+ virtual void seekp (Int64 pos) = 0;
+
+
+ //------------------------------------------------------
+ // Get the name of the file associated with this stream.
+ //------------------------------------------------------
+
+ const char * fileName () const;
+
+ protected:
+
+ OStream (const char fileName[]);
+
+ private:
+
+ OStream (const OStream &); // not implemented
+ OStream & operator = (const OStream &); // not implemented
+
+ std::string _fileName;
+};
+
+
+//-----------------------
+// Helper classes for Xdr
+//-----------------------
+
+struct StreamIO
+{
+ static void
+ writeChars (OStream &os, const char c[/*n*/], int n)
+ {
+ os.write (c, n);
+ }
+
+ static bool
+ readChars (IStream &is, char c[/*n*/], int n)
+ {
+ return is.read (c, n);
+ }
+};
+
+
+struct CharPtrIO
+{
+ static void
+ writeChars (char *&op, const char c[/*n*/], int n)
+ {
+ while (n--)
+ *op++ = *c++;
+ }
+
+ static bool
+ readChars (const char *&ip, char c[/*n*/], int n)
+ {
+ while (n--)
+ *c++ = *ip++;
+
+ return true;
+ }
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfInputFile.cpp b/Source/OpenEXR/IlmImf/ImfInputFile.cpp
new file mode 100644
index 0000000..cc6a41f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfInputFile.cpp
@@ -0,0 +1,648 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class InputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfInputFile.h>
+#include <ImfScanLineInputFile.h>
+#include <ImfTiledInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImfStdIO.h>
+#include <ImfVersion.h>
+#include "ImathFun.h"
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include "half.h"
+#include <fstream>
+#include <algorithm>
+
+
+namespace Imf {
+
+
+using Imath::Box2i;
+using Imath::divp;
+using Imath::modp;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+
+
+//
+// Struct InputFile::Data stores things that will be
+// needed between calls to readPixels
+//
+
+struct InputFile::Data: public Mutex
+{
+ Header header;
+ int version;
+ IStream * is;
+ bool deleteStream;
+
+ TiledInputFile * tFile;
+ ScanLineInputFile * sFile;
+
+ LineOrder lineOrder; // the file's lineorder
+ int minY; // data window's min y coord
+ int maxY; // data window's max x coord
+
+ FrameBuffer tFileBuffer;
+ FrameBuffer * cachedBuffer;
+
+ int cachedTileY;
+ int offset;
+
+ int numThreads;
+
+ Data (bool del, int numThreads);
+ ~Data ();
+
+ void deleteCachedBuffer();
+};
+
+
+InputFile::Data::Data (bool del, int numThreads):
+ is (0),
+ deleteStream (del),
+ tFile (0),
+ sFile (0),
+ cachedBuffer (0),
+ cachedTileY (-1),
+ numThreads (numThreads)
+{
+ // empty
+}
+
+
+InputFile::Data::~Data ()
+{
+ delete tFile;
+ delete sFile;
+
+ if (deleteStream)
+ delete is;
+
+ deleteCachedBuffer();
+}
+
+
+void
+InputFile::Data::deleteCachedBuffer()
+{
+ //
+ // Delete the cached frame buffer, and all memory
+ // allocated for the slices in the cached frameBuffer.
+ //
+
+ if (cachedBuffer)
+ {
+ for (FrameBuffer::Iterator k = cachedBuffer->begin();
+ k != cachedBuffer->end();
+ ++k)
+ {
+ Slice &s = k.slice();
+
+ switch (s.type)
+ {
+ case UINT:
+
+ delete [] (((unsigned int *)s.base) + offset);
+ break;
+
+ case HALF:
+
+ delete [] ((half *)s.base + offset);
+ break;
+
+ case FLOAT:
+
+ delete [] (((float *)s.base) + offset);
+ break;
+ }
+ }
+
+ //
+ // delete the cached frame buffer
+ //
+
+ delete cachedBuffer;
+ cachedBuffer = 0;
+ }
+}
+
+
+namespace {
+
+void
+bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
+{
+ //
+ // bufferedReadPixels reads each row of tiles that intersect the
+ // scan-line range (scanLine1 to scanLine2). The previous row of
+ // tiles is cached in order to prevent redundent tile reads when
+ // accessing scanlines sequentially.
+ //
+
+ int minY = std::min (scanLine1, scanLine2);
+ int maxY = std::max (scanLine1, scanLine2);
+
+ if (minY < ifd->minY || maxY > ifd->maxY)
+ {
+ throw Iex::ArgExc ("Tried to read scan line outside "
+ "the image file's data window.");
+ }
+
+ //
+ // The minimum and maximum y tile coordinates that intersect this
+ // scanline range
+ //
+
+ int minDy = (minY - ifd->minY) / ifd->tFile->tileYSize();
+ int maxDy = (maxY - ifd->minY) / ifd->tFile->tileYSize();
+
+ //
+ // Figure out which one is first in the file so we can read without seeking
+ //
+
+ int yStart, yEnd, yStep;
+
+ if (ifd->lineOrder == DECREASING_Y)
+ {
+ yStart = maxDy;
+ yEnd = minDy - 1;
+ yStep = -1;
+ }
+ else
+ {
+ yStart = minDy;
+ yEnd = maxDy + 1;
+ yStep = 1;
+ }
+
+ //
+ // the number of pixels in a row of tiles
+ //
+
+ Box2i levelRange = ifd->tFile->dataWindowForLevel(0);
+
+ //
+ // Read the tiles into our temporary framebuffer and copy them into
+ // the user's buffer
+ //
+
+ for (int j = yStart; j != yEnd; j += yStep)
+ {
+ Box2i tileRange = ifd->tFile->dataWindowForTile (0, j, 0);
+
+ int minYThisRow = std::max (minY, tileRange.min.y);
+ int maxYThisRow = std::min (maxY, tileRange.max.y);
+
+ if (j != ifd->cachedTileY)
+ {
+ //
+ // We don't have any valid buffered info, so we need to read in
+ // from the file.
+ //
+
+ ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
+ ifd->cachedTileY = j;
+ }
+
+ //
+ // Copy the data from our cached framebuffer into the user's
+ // framebuffer.
+ //
+
+ for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin();
+ k != ifd->cachedBuffer->end();
+ ++k)
+ {
+ Slice fromSlice = k.slice(); // slice to write from
+ Slice toSlice = ifd->tFileBuffer[k.name()]; // slice to write to
+
+ char *fromPtr, *toPtr;
+ int size = pixelTypeSize (toSlice.type);
+
+ int xStart = levelRange.min.x;
+ int yStart = minYThisRow;
+
+ while (modp (xStart, toSlice.xSampling) != 0)
+ ++xStart;
+
+ while (modp (yStart, toSlice.ySampling) != 0)
+ ++yStart;
+
+ for (int y = yStart;
+ y <= maxYThisRow;
+ y += toSlice.ySampling)
+ {
+ //
+ // Set the pointers to the start of the y scanline in
+ // this row of tiles
+ //
+
+ fromPtr = fromSlice.base +
+ (y - tileRange.min.y) * fromSlice.yStride +
+ xStart * fromSlice.xStride;
+
+ toPtr = toSlice.base +
+ divp (y, toSlice.ySampling) * toSlice.yStride +
+ divp (xStart, toSlice.xSampling) * toSlice.xStride;
+
+ //
+ // Copy all pixels for the scanline in this row of tiles
+ //
+
+ for (int x = xStart;
+ x <= levelRange.max.x;
+ x += toSlice.xSampling)
+ {
+ for (size_t i = 0; i < size; ++i)
+ toPtr[i] = fromPtr[i];
+
+ fromPtr += fromSlice.xStride * toSlice.xSampling;
+ toPtr += toSlice.xStride;
+ }
+ }
+ }
+ }
+}
+
+} // namespace
+
+
+
+InputFile::InputFile (const char fileName[], int numThreads):
+ _data (new Data (true, numThreads))
+{
+ try
+ {
+ _data->is = new StdIFStream (fileName);
+ initialize();
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot read image file "
+ "\"" << fileName << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+InputFile::InputFile (IStream &is, int numThreads):
+ _data (new Data (false, numThreads))
+{
+ try
+ {
+ _data->is = &is;
+ initialize();
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot read image file "
+ "\"" << is.fileName() << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+void
+InputFile::initialize ()
+{
+ _data->header.readFrom (*_data->is, _data->version);
+ _data->header.sanityCheck (isTiled (_data->version));
+
+ if (isTiled (_data->version))
+ {
+ _data->lineOrder = _data->header.lineOrder();
+
+ //
+ // Save the dataWindow information
+ //
+
+ const Box2i &dataWindow = _data->header.dataWindow();
+ _data->minY = dataWindow.min.y;
+ _data->maxY = dataWindow.max.y;
+
+ _data->tFile = new TiledInputFile (_data->header,
+ _data->is,
+ _data->version,
+ _data->numThreads);
+ }
+ else
+ {
+ _data->sFile = new ScanLineInputFile (_data->header,
+ _data->is,
+ _data->numThreads);
+ }
+}
+
+
+InputFile::~InputFile ()
+{
+ delete _data;
+}
+
+
+const char *
+InputFile::fileName () const
+{
+ return _data->is->fileName();
+}
+
+
+const Header &
+InputFile::header () const
+{
+ return _data->header;
+}
+
+
+int
+InputFile::version () const
+{
+ return _data->version;
+}
+
+
+void
+InputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
+{
+ if (isTiled (_data->version))
+ {
+ Lock lock (*_data);
+
+ //
+ // We must invalidate the cached buffer if the new frame
+ // buffer has a different set of channels than the old
+ // frame buffer, or if the type of a channel has changed.
+ //
+
+ const FrameBuffer &oldFrameBuffer = _data->tFileBuffer;
+
+ FrameBuffer::ConstIterator i = oldFrameBuffer.begin();
+ FrameBuffer::ConstIterator j = frameBuffer.begin();
+
+ while (i != oldFrameBuffer.end())
+ {
+ if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type)
+ break;
+
+ ++i;
+ ++j;
+ }
+
+ if (i != oldFrameBuffer.end() || j != frameBuffer.end())
+ {
+ //
+ // Invalidate the cached buffer.
+ //
+
+ _data->deleteCachedBuffer ();
+ _data->cachedTileY = -1;
+
+ //
+ // Create new a cached frame buffer. It can hold a single
+ // row of tiles. The cached buffer can be reused for each
+ // row of tiles because we set the yTileCoords parameter of
+ // each Slice to true.
+ //
+
+ const Box2i &dataWindow = _data->header.dataWindow();
+ _data->cachedBuffer = new FrameBuffer();
+ _data->offset = dataWindow.min.x;
+
+ int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) *
+ _data->tFile->tileYSize();
+
+ for (FrameBuffer::ConstIterator k = frameBuffer.begin();
+ k != frameBuffer.end();
+ ++k)
+ {
+ Slice s = k.slice();
+
+ switch (s.type)
+ {
+ case UINT:
+
+ _data->cachedBuffer->insert
+ (k.name(),
+ Slice (UINT,
+ (char *)(new unsigned int[tileRowSize] -
+ _data->offset),
+ sizeof (unsigned int),
+ sizeof (unsigned int) *
+ _data->tFile->levelWidth(0),
+ 1, 1,
+ s.fillValue,
+ false, true));
+ break;
+
+ case HALF:
+
+ _data->cachedBuffer->insert
+ (k.name(),
+ Slice (HALF,
+ (char *)(new half[tileRowSize] -
+ _data->offset),
+ sizeof (half),
+ sizeof (half) *
+ _data->tFile->levelWidth(0),
+ 1, 1,
+ s.fillValue,
+ false, true));
+ break;
+
+ case FLOAT:
+
+ _data->cachedBuffer->insert
+ (k.name(),
+ Slice (FLOAT,
+ (char *)(new float[tileRowSize] -
+ _data->offset),
+ sizeof(float),
+ sizeof(float) *
+ _data->tFile->levelWidth(0),
+ 1, 1,
+ s.fillValue,
+ false, true));
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+
+ _data->tFile->setFrameBuffer (*_data->cachedBuffer);
+ }
+
+ _data->tFileBuffer = frameBuffer;
+ }
+ else
+ {
+ _data->sFile->setFrameBuffer (frameBuffer);
+ }
+}
+
+
+const FrameBuffer &
+InputFile::frameBuffer () const
+{
+ if (isTiled (_data->version))
+ {
+ Lock lock (*_data);
+ return _data->tFileBuffer;
+ }
+ else
+ {
+ return _data->sFile->frameBuffer();
+ }
+}
+
+
+bool
+InputFile::isComplete () const
+{
+ if (isTiled (_data->version))
+ return _data->tFile->isComplete();
+ else
+ return _data->sFile->isComplete();
+}
+
+
+void
+InputFile::readPixels (int scanLine1, int scanLine2)
+{
+ if (isTiled (_data->version))
+ {
+ Lock lock (*_data);
+ bufferedReadPixels (_data, scanLine1, scanLine2);
+ }
+ else
+ {
+ _data->sFile->readPixels (scanLine1, scanLine2);
+ }
+}
+
+
+void
+InputFile::readPixels (int scanLine)
+{
+ readPixels (scanLine, scanLine);
+}
+
+
+void
+InputFile::rawPixelData (int firstScanLine,
+ const char *&pixelData,
+ int &pixelDataSize)
+{
+ try
+ {
+ if (isTiled (_data->version))
+ {
+ throw Iex::ArgExc ("Tried to read a raw scanline "
+ "from a tiled image.");
+ }
+
+ _data->sFile->rawPixelData (firstScanLine, pixelData, pixelDataSize);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading pixel data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+InputFile::rawTileData (int &dx, int &dy,
+ int &lx, int &ly,
+ const char *&pixelData,
+ int &pixelDataSize)
+{
+ try
+ {
+ if (!isTiled (_data->version))
+ {
+ throw Iex::ArgExc ("Tried to read a raw tile "
+ "from a scanline-based image.");
+ }
+
+ _data->tFile->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading tile data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+TiledInputFile*
+InputFile::tFile()
+{
+ if (!isTiled (_data->version))
+ {
+ throw Iex::ArgExc ("Cannot get a TiledInputFile pointer "
+ "from an InputFile that is not tiled.");
+ }
+
+ return _data->tFile;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfInputFile.h b/Source/OpenEXR/IlmImf/ImfInputFile.h
new file mode 100644
index 0000000..af9256b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfInputFile.h
@@ -0,0 +1,209 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_INPUT_FILE_H
+#define INCLUDED_IMF_INPUT_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// class InputFile -- a scanline-based interface that can be used
+// to read both scanline-based and tiled OpenEXR image files.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include <ImfTiledOutputFile.h>
+#include <string>
+#include <fstream>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+class TiledInputFile;
+class ScanLineInputFile;
+
+
+class InputFile
+{
+ public:
+
+ //-----------------------------------------------------------
+ // A constructor that opens the file with the specified name.
+ // Destroying the InputFile object will close the file.
+ //
+ // numThreads determines the number of threads that will be
+ // used to read the file (see ImfThreading.h).
+ //-----------------------------------------------------------
+
+ InputFile (const char fileName[], int numThreads = globalThreadCount());
+
+
+ //-------------------------------------------------------------
+ // A constructor that attaches the new InputFile object to a
+ // file that has already been opened. Destroying the InputFile
+ // object will not close the file.
+ //
+ // numThreads determines the number of threads that will be
+ // used to read the file (see ImfThreading.h).
+ //-------------------------------------------------------------
+
+ InputFile (IStream &is, int numThreads = globalThreadCount());
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~InputFile ();
+
+
+ //------------------------
+ // Access to the file name
+ //------------------------
+
+ const char * fileName () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+
+
+ //----------------------------------
+ // Access to the file format version
+ //----------------------------------
+
+ int version () const;
+
+
+ //-----------------------------------------------------------
+ // Set the current frame buffer -- copies the FrameBuffer
+ // object into the InputFile object.
+ //
+ // The current frame buffer is the destination for the pixel
+ // data read from the file. The current frame buffer must be
+ // set at least once before readPixels() is called.
+ // The current frame buffer can be changed after each call
+ // to readPixels().
+ //-----------------------------------------------------------
+
+ void setFrameBuffer (const FrameBuffer &frameBuffer);
+
+
+ //-----------------------------------
+ // Access to the current frame buffer
+ //-----------------------------------
+
+ const FrameBuffer & frameBuffer () const;
+
+
+ //---------------------------------------------------------------
+ // Check if the file is complete:
+ //
+ // isComplete() returns true if all pixels in the data window are
+ // present in the input file, or false if any pixels are missing.
+ // (Another program may still be busy writing the file, or file
+ // writing may have been aborted prematurely.)
+ //---------------------------------------------------------------
+
+ bool isComplete () const;
+
+
+ //---------------------------------------------------------------
+ // Read pixel data:
+ //
+ // readPixels(s1,s2) reads all scan lines with y coordinates
+ // in the interval [min (s1, s2), max (s1, s2)] from the file,
+ // and stores them in the current frame buffer.
+ //
+ // Both s1 and s2 must be within the interval
+ // [header().dataWindow().min.y, header().dataWindow().max.y]
+ //
+ // The scan lines can be read from the file in random order, and
+ // individual scan lines may be skipped or read multiple times.
+ // For maximum efficiency, the scan lines should be read in the
+ // order in which they were written to the file.
+ //
+ // readPixels(s) calls readPixels(s,s).
+ //
+ //---------------------------------------------------------------
+
+ void readPixels (int scanLine1, int scanLine2);
+ void readPixels (int scanLine);
+
+
+ //----------------------------------------------
+ // Read a block of raw pixel data from the file,
+ // without uncompressing it (this function is
+ // used to implement OutputFile::copyPixels()).
+ //----------------------------------------------
+
+ void rawPixelData (int firstScanLine,
+ const char *&pixelData,
+ int &pixelDataSize);
+
+ //--------------------------------------------------
+ // Read a tile of raw pixel data from the file,
+ // without uncompressing it (this function is
+ // used to implement TiledOutputFile::copyPixels()).
+ //--------------------------------------------------
+
+ void rawTileData (int &dx, int &dy,
+ int &lx, int &ly,
+ const char *&pixelData,
+ int &pixelDataSize);
+
+ struct Data;
+
+ private:
+
+ InputFile (const InputFile &); // not implemented
+ InputFile & operator = (const InputFile &); // not implemented
+
+ void initialize ();
+ TiledInputFile * tFile ();
+
+ friend void TiledOutputFile::copyPixels (InputFile &);
+
+ Data * _data;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfInt64.h b/Source/OpenEXR/IlmImf/ImfInt64.h
new file mode 100644
index 0000000..d8fdc81
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfInt64.h
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_IMF_INT64_H
+#define INCLUDED_IMF_INT64_H
+
+//----------------------------------------------------------------------------
+//
+// Int64 -- unsigned 64-bit integers, imported from namespace Imath
+//
+//----------------------------------------------------------------------------
+
+#include "ImathInt64.h"
+
+namespace Imf {
+
+using Imath::Int64;
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfIntAttribute.cpp b/Source/OpenEXR/IlmImf/ImfIntAttribute.cpp
new file mode 100644
index 0000000..f233b58
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfIntAttribute.cpp
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class IntAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfIntAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+IntAttribute::staticTypeName ()
+{
+ return "int";
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfIntAttribute.h b/Source/OpenEXR/IlmImf/ImfIntAttribute.h
new file mode 100644
index 0000000..c67e5b1
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfIntAttribute.h
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_INT_ATTRIBUTE_H
+#define INCLUDED_IMF_INT_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class IntAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<int> IntAttribute;
+template <> const char *IntAttribute::staticTypeName ();
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfIntAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfKeyCode.cpp b/Source/OpenEXR/IlmImf/ImfKeyCode.cpp
new file mode 100644
index 0000000..b199cf5
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfKeyCode.cpp
@@ -0,0 +1,216 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class KeyCode
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfKeyCode.h>
+#include "Iex.h"
+
+namespace Imf {
+
+
+KeyCode::KeyCode (int filmMfcCode,
+ int filmType,
+ int prefix,
+ int count,
+ int perfOffset,
+ int perfsPerFrame,
+ int perfsPerCount)
+{
+ setFilmMfcCode (filmMfcCode);
+ setFilmType (filmType);
+ setPrefix (prefix);
+ setCount (count);
+ setPerfOffset (perfOffset);
+ setPerfsPerFrame (perfsPerFrame);
+ setPerfsPerCount (perfsPerCount);
+}
+
+
+KeyCode::KeyCode (const KeyCode &other)
+{
+ _filmMfcCode = other._filmMfcCode;
+ _filmType = other._filmType;
+ _prefix = other._prefix;
+ _count = other._count;
+ _perfOffset = other._perfOffset;
+ _perfsPerFrame = other._perfsPerFrame;
+ _perfsPerCount = other._perfsPerCount;
+}
+
+
+KeyCode &
+KeyCode::operator = (const KeyCode &other)
+{
+ _filmMfcCode = other._filmMfcCode;
+ _filmType = other._filmType;
+ _prefix = other._prefix;
+ _count = other._count;
+ _perfOffset = other._perfOffset;
+ _perfsPerFrame = other._perfsPerFrame;
+ _perfsPerCount = other._perfsPerCount;
+
+ return *this;
+}
+
+
+int
+KeyCode::filmMfcCode () const
+{
+ return _filmMfcCode;
+}
+
+
+void
+KeyCode::setFilmMfcCode (int filmMfcCode)
+{
+ if (filmMfcCode < 0 || filmMfcCode > 99)
+ throw Iex::ArgExc ("Invalid key code film manufacturer code "
+ "(must be between 0 and 99).");
+
+ _filmMfcCode = filmMfcCode;
+}
+
+int
+KeyCode::filmType () const
+{
+ return _filmType;
+}
+
+
+void
+KeyCode::setFilmType (int filmType)
+{
+ if (filmType < 0 || filmType > 99)
+ throw Iex::ArgExc ("Invalid key code film type "
+ "(must be between 0 and 99).");
+
+ _filmType = filmType;
+}
+
+int
+KeyCode::prefix () const
+{
+ return _prefix;
+}
+
+
+void
+KeyCode::setPrefix (int prefix)
+{
+ if (prefix < 0 || prefix > 999999)
+ throw Iex::ArgExc ("Invalid key code prefix "
+ "(must be between 0 and 999999).");
+
+ _prefix = prefix;
+}
+
+
+int
+KeyCode::count () const
+{
+ return _count;
+}
+
+
+void
+KeyCode::setCount (int count)
+{
+ if (count < 0 || count > 9999)
+ throw Iex::ArgExc ("Invalid key code count "
+ "(must be between 0 and 9999).");
+
+ _count = count;
+}
+
+
+int
+KeyCode::perfOffset () const
+{
+ return _perfOffset;
+}
+
+
+void
+KeyCode::setPerfOffset (int perfOffset)
+{
+ if (perfOffset < 0 || perfOffset > 119)
+ throw Iex::ArgExc ("Invalid key code perforation offset "
+ "(must be between 0 and 119).");
+
+ _perfOffset = perfOffset;
+}
+
+
+int
+KeyCode::perfsPerFrame () const
+{
+ return _perfsPerFrame;
+}
+
+
+void
+KeyCode::setPerfsPerFrame (int perfsPerFrame)
+{
+ if (perfsPerFrame < 1 || perfsPerFrame > 15)
+ throw Iex::ArgExc ("Invalid key code number of perforations per frame "
+ "(must be between 1 and 15).");
+
+ _perfsPerFrame = perfsPerFrame;
+}
+
+
+int
+KeyCode::perfsPerCount () const
+{
+ return _perfsPerCount;
+}
+
+
+void
+KeyCode::setPerfsPerCount (int perfsPerCount)
+{
+ if (perfsPerCount < 20 || perfsPerCount > 120)
+ throw Iex::ArgExc ("Invalid key code number of perforations per count "
+ "(must be between 20 and 120).");
+
+ _perfsPerCount = perfsPerCount;
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfKeyCode.h b/Source/OpenEXR/IlmImf/ImfKeyCode.h
new file mode 100644
index 0000000..93dd915
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfKeyCode.h
@@ -0,0 +1,161 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_KEY_CODE_H
+#define INCLUDED_IMF_KEY_CODE_H
+
+//-----------------------------------------------------------------------------
+//
+// class KeyCode
+//
+// A KeyCode object uniquely identifies a motion picture film frame.
+// The following fields specifiy film manufacturer, film type, film
+// roll and the frame's position within the roll:
+//
+// filmMfcCode film manufacturer code
+// range: 0 - 99
+//
+// filmType film type code
+// range: 0 - 99
+//
+// prefix prefix to identify film roll
+// range: 0 - 999999
+//
+// count count, increments once every perfsPerCount
+// perforations (see below)
+// range: 0 - 9999
+//
+// perfOffset offset of frame, in perforations from
+// zero-frame reference mark
+// range: 0 - 119
+//
+// perfsPerFrame number of perforations per frame
+// range: 1 - 15
+//
+// typical values:
+//
+// 1 for 16mm film
+// 3, 4, or 8 for 35mm film
+// 5, 8 or 15 for 65mm film
+//
+// perfsPerCount number of perforations per count
+// range: 20 - 120
+//
+// typical values:
+//
+// 20 for 16mm film
+// 64 for 35mm film
+// 80 or 120 for 65mm film
+//
+// For more information about the interpretation of those fields see
+// the following standards and recommended practice publications:
+//
+// SMPTE 254 Motion-Picture Film (35-mm) - Manufacturer-Printed
+// Latent Image Identification Information
+//
+// SMPTE 268M File Format for Digital Moving-Picture Exchange (DPX)
+// (section 6.1)
+//
+// SMPTE 270 Motion-Picture Film (65-mm) - Manufacturer- Printed
+// Latent Image Identification Information
+//
+// SMPTE 271 Motion-Picture Film (16-mm) - Manufacturer- Printed
+// Latent Image Identification Information
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+class KeyCode
+{
+ public:
+
+ //-------------------------------------
+ // Constructors and assignment operator
+ //-------------------------------------
+
+ KeyCode (int filmMfcCode = 0,
+ int filmType = 0,
+ int prefix = 0,
+ int count = 0,
+ int perfOffset = 0,
+ int perfsPerFrame = 4,
+ int perfsPerCount = 64);
+
+ KeyCode (const KeyCode &other);
+ KeyCode & operator = (const KeyCode &other);
+
+
+ //----------------------------
+ // Access to individual fields
+ //----------------------------
+
+ int filmMfcCode () const;
+ void setFilmMfcCode (int filmMfcCode);
+
+ int filmType () const;
+ void setFilmType (int filmType);
+
+ int prefix () const;
+ void setPrefix (int prefix);
+
+ int count () const;
+ void setCount (int count);
+
+ int perfOffset () const;
+ void setPerfOffset (int perfOffset);
+
+ int perfsPerFrame () const;
+ void setPerfsPerFrame (int perfsPerFrame);
+
+ int perfsPerCount () const;
+ void setPerfsPerCount (int perfsPerCount);
+
+ private:
+
+ int _filmMfcCode;
+ int _filmType;
+ int _prefix;
+ int _count;
+ int _perfOffset;
+ int _perfsPerFrame;
+ int _perfsPerCount;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.cpp b/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.cpp
new file mode 100644
index 0000000..00156bd
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.cpp
@@ -0,0 +1,98 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class KeyCodeAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfKeyCodeAttribute.h>
+
+namespace Imf {
+
+
+template <>
+const char *
+KeyCodeAttribute::staticTypeName ()
+{
+ return "keycode";
+}
+
+
+template <>
+void
+KeyCodeAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.filmMfcCode());
+ Xdr::write <StreamIO> (os, _value.filmType());
+ Xdr::write <StreamIO> (os, _value.prefix());
+ Xdr::write <StreamIO> (os, _value.count());
+ Xdr::write <StreamIO> (os, _value.perfOffset());
+ Xdr::write <StreamIO> (os, _value.perfsPerFrame());
+ Xdr::write <StreamIO> (os, _value.perfsPerCount());
+}
+
+
+template <>
+void
+KeyCodeAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ int tmp;
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setFilmMfcCode (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setFilmType (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setPrefix (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setCount (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setPerfOffset (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setPerfsPerFrame (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setPerfsPerCount (tmp);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.h b/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.h
new file mode 100644
index 0000000..9ec8f84
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfKeyCodeAttribute.h
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_KEY_CODE_ATTRIBUTE_H
+#define INCLUDED_IMF_KEY_CODE_ATTRIBUTE_H
+
+
+//-----------------------------------------------------------------------------
+//
+// class KeyCodeAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfKeyCode.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<KeyCode> KeyCodeAttribute;
+
+template <>
+const char *KeyCodeAttribute::staticTypeName ();
+
+template <>
+void KeyCodeAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void KeyCodeAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfKeyCodeAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfLineOrder.h b/Source/OpenEXR/IlmImf/ImfLineOrder.h
new file mode 100644
index 0000000..2f91352
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfLineOrder.h
@@ -0,0 +1,64 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_LINE_ORDER_H
+#define INCLUDED_IMF_LINE_ORDER_H
+
+//-----------------------------------------------------------------------------
+//
+// enum LineOrder
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+enum LineOrder
+{
+ INCREASING_Y = 0, // first scan line has lowest y coordinate
+
+ DECREASING_Y = 1, // first scan line has highest y coordinate
+
+ RANDOM_Y = 2, // only for tiled files; tiles are written
+ // in random order
+
+ NUM_LINEORDERS // number of different line orders
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.cpp b/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.cpp
new file mode 100644
index 0000000..6b9c0f9
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.cpp
@@ -0,0 +1,77 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class LineOrderAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfLineOrderAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+LineOrderAttribute::staticTypeName ()
+{
+ return "lineOrder";
+}
+
+
+template <>
+void
+LineOrderAttribute::writeValueTo (OStream &os, int version) const
+{
+ unsigned char tmp = _value;
+ Xdr::write <StreamIO> (os, tmp);
+}
+
+
+template <>
+void
+LineOrderAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ unsigned char tmp;
+ Xdr::read <StreamIO> (is, tmp);
+ _value = LineOrder (tmp);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.h b/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.h
new file mode 100644
index 0000000..eb9301e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfLineOrderAttribute.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_LINE_ORDER_ATTRIBUTE_H
+#define INCLUDED_IMF_LINE_ORDER_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class LineOrderAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfLineOrder.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<LineOrder> LineOrderAttribute;
+template <> const char *LineOrderAttribute::staticTypeName ();
+template <> void LineOrderAttribute::writeValueTo (OStream &, int) const;
+template <> void LineOrderAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfLineOrderAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfLut.cpp b/Source/OpenEXR/IlmImf/ImfLut.cpp
new file mode 100644
index 0000000..284bd21
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfLut.cpp
@@ -0,0 +1,176 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Lookup tables for efficient application
+// of half --> half functions to pixel data,
+// and some commonly applied functions.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfLut.h>
+#include <math.h>
+#include <assert.h>
+
+namespace Imf {
+
+
+void
+HalfLut::apply (half *data, int nData, int stride) const
+{
+ while (nData)
+ {
+ *data = _lut (*data);
+ data += stride;
+ nData -= 1;
+ }
+}
+
+
+void
+HalfLut::apply (const Slice &data, const Imath::Box2i &dataWindow) const
+{
+ assert (data.type == HALF);
+ assert (dataWindow.min.x % data.xSampling == 0);
+ assert (dataWindow.min.y % data.ySampling == 0);
+ assert ((dataWindow.max.x - dataWindow.min.x + 1) % data.xSampling == 0);
+ assert ((dataWindow.max.y - dataWindow.min.y + 1) % data.ySampling == 0);
+
+ char *base = data.base + data.yStride *
+ (dataWindow.min.y / data.ySampling);
+
+ for (int y = dataWindow.min.y;
+ y <= dataWindow.max.y;
+ y += data.ySampling)
+ {
+ char *pixel = base + data.xStride *
+ (dataWindow.min.x / data.xSampling);
+
+ for (int x = dataWindow.min.x;
+ x <= dataWindow.max.x;
+ x += data.xSampling)
+ {
+ *(half *)pixel = _lut (*(half *)pixel);
+ pixel += data.xStride;
+ }
+
+ base += data.yStride;
+ }
+}
+
+
+void
+RgbaLut::apply (Rgba *data, int nData, int stride) const
+{
+ while (nData)
+ {
+ if (_chn & WRITE_R)
+ data->r = _lut (data->r);
+
+ if (_chn & WRITE_G)
+ data->g = _lut (data->g);
+
+ if (_chn & WRITE_B)
+ data->b = _lut (data->b);
+
+ if (_chn & WRITE_A)
+ data->a = _lut (data->a);
+
+ data += stride;
+ nData -= 1;
+ }
+}
+
+
+void
+RgbaLut::apply (Rgba *base,
+ int xStride, int yStride,
+ const Imath::Box2i &dataWindow) const
+{
+ base += dataWindow.min.y * yStride;
+
+ for (int y = dataWindow.min.y; y <= dataWindow.max.y; ++y)
+ {
+ Rgba *pixel = base + dataWindow.min.x * xStride;
+
+ for (int x = dataWindow.min.x; x <= dataWindow.max.x; ++x)
+ {
+ if (_chn & WRITE_R)
+ pixel->r = _lut (pixel->r);
+
+ if (_chn & WRITE_G)
+ pixel->g = _lut (pixel->g);
+
+ if (_chn & WRITE_B)
+ pixel->b = _lut (pixel->b);
+
+ if (_chn & WRITE_A)
+ pixel->a = _lut (pixel->a);
+
+ pixel += xStride;
+ }
+
+ base += yStride;
+ }
+}
+
+
+half
+round12log (half x)
+{
+ const float middleval = pow (2.0, -2.5);
+ int int12log;
+
+ if (x <= 0)
+ {
+ return 0;
+ }
+ else
+ {
+ int12log = int (2000.5 + 200.0 * log (x / middleval) / log (2.0));
+
+ if (int12log > 4095)
+ int12log = 4095;
+
+ if (int12log < 1)
+ int12log = 1;
+ }
+
+ return middleval * pow (2.0, (int12log - 2000.0) / 200.0);
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfLut.h b/Source/OpenEXR/IlmImf/ImfLut.h
new file mode 100644
index 0000000..ca702d2
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfLut.h
@@ -0,0 +1,185 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_LUT_H
+#define INCLUDED_IMF_LUT_H
+
+//-----------------------------------------------------------------------------
+//
+// Lookup tables for efficient application
+// of half --> half functions to pixel data,
+// and some commonly applied functions.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRgbaFile.h>
+#include <ImfFrameBuffer.h>
+#include "ImathBox.h"
+#include "halfFunction.h"
+
+namespace Imf {
+
+//
+// Lookup table for individual half channels.
+//
+
+class HalfLut
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ template <class Function>
+ HalfLut (Function f);
+
+
+ //----------------------------------------------------------------------
+ // Apply the table to data[0], data[stride] ... data[(nData-1) * stride]
+ //----------------------------------------------------------------------
+
+ void apply (half *data,
+ int nData,
+ int stride = 1) const;
+
+
+ //---------------------------------------------------------------
+ // Apply the table to a frame buffer slice (see ImfFrameBuffer.h)
+ //---------------------------------------------------------------
+
+ void apply (const Slice &data,
+ const Imath::Box2i &dataWindow) const;
+
+ private:
+
+ halfFunction <half> _lut;
+};
+
+
+//
+// Lookup table for combined RGBA data.
+//
+
+class RgbaLut
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ template <class Function>
+ RgbaLut (Function f, RgbaChannels chn = WRITE_RGB);
+
+
+ //----------------------------------------------------------------------
+ // Apply the table to data[0], data[stride] ... data[(nData-1) * stride]
+ //----------------------------------------------------------------------
+
+ void apply (Rgba *data,
+ int nData,
+ int stride = 1) const;
+
+
+ //-----------------------------------------------------------------------
+ // Apply the table to a frame buffer (see RgbaOutpuFile.setFrameBuffer())
+ //-----------------------------------------------------------------------
+
+ void apply (Rgba *base,
+ int xStride,
+ int yStride,
+ const Imath::Box2i &dataWindow) const;
+
+ private:
+
+ halfFunction <half> _lut;
+ RgbaChannels _chn;
+};
+
+
+//
+// 12bit log rounding reduces data to 20 stops with 200 steps per stop.
+// That makes 4000 numbers. An extra 96 just come along for the ride.
+// Zero explicitly remains zero. The first non-zero half will map to 1
+// in the 0-4095 12log space. A nice power of two number is placed at
+// the center [2000] and that number is near 0.18.
+//
+
+half round12log (half x);
+
+
+//
+// Round to n-bit precision (n should be between 0 and 10).
+// After rounding, the significand's 10-n least significant
+// bits will be zero.
+//
+
+struct roundNBit
+{
+ roundNBit (int n): n(n) {}
+ half operator () (half x) {return x.round(n);}
+ int n;
+};
+
+
+//
+// Template definitions
+//
+
+
+template <class Function>
+HalfLut::HalfLut (Function f):
+ _lut(f, -HALF_MAX, HALF_MAX, half (0),
+ half::posInf(), half::negInf(), half::qNan())
+{
+ // empty
+}
+
+
+template <class Function>
+RgbaLut::RgbaLut (Function f, RgbaChannels chn):
+ _lut(f, -HALF_MAX, HALF_MAX, half (0),
+ half::posInf(), half::negInf(), half::qNan()),
+ _chn(chn)
+{
+ // empty
+}
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfMatrixAttribute.cpp b/Source/OpenEXR/IlmImf/ImfMatrixAttribute.cpp
new file mode 100644
index 0000000..66f81f5
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfMatrixAttribute.cpp
@@ -0,0 +1,154 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class M33fAttribute
+// class M44fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfMatrixAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+M33fAttribute::staticTypeName ()
+{
+ return "m33f";
+}
+
+
+template <>
+void
+M33fAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value[0][0]);
+ Xdr::write <StreamIO> (os, _value[0][1]);
+ Xdr::write <StreamIO> (os, _value[0][2]);
+
+ Xdr::write <StreamIO> (os, _value[1][0]);
+ Xdr::write <StreamIO> (os, _value[1][1]);
+ Xdr::write <StreamIO> (os, _value[1][2]);
+
+ Xdr::write <StreamIO> (os, _value[2][0]);
+ Xdr::write <StreamIO> (os, _value[2][1]);
+ Xdr::write <StreamIO> (os, _value[2][2]);
+}
+
+
+template <>
+void
+M33fAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value[0][0]);
+ Xdr::read <StreamIO> (is, _value[0][1]);
+ Xdr::read <StreamIO> (is, _value[0][2]);
+
+ Xdr::read <StreamIO> (is, _value[1][0]);
+ Xdr::read <StreamIO> (is, _value[1][1]);
+ Xdr::read <StreamIO> (is, _value[1][2]);
+
+ Xdr::read <StreamIO> (is, _value[2][0]);
+ Xdr::read <StreamIO> (is, _value[2][1]);
+ Xdr::read <StreamIO> (is, _value[2][2]);
+}
+
+
+template <>
+const char *
+M44fAttribute::staticTypeName ()
+{
+ return "m44f";
+}
+
+
+template <>
+void
+M44fAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value[0][0]);
+ Xdr::write <StreamIO> (os, _value[0][1]);
+ Xdr::write <StreamIO> (os, _value[0][2]);
+ Xdr::write <StreamIO> (os, _value[0][3]);
+
+ Xdr::write <StreamIO> (os, _value[1][0]);
+ Xdr::write <StreamIO> (os, _value[1][1]);
+ Xdr::write <StreamIO> (os, _value[1][2]);
+ Xdr::write <StreamIO> (os, _value[1][3]);
+
+ Xdr::write <StreamIO> (os, _value[2][0]);
+ Xdr::write <StreamIO> (os, _value[2][1]);
+ Xdr::write <StreamIO> (os, _value[2][2]);
+ Xdr::write <StreamIO> (os, _value[2][3]);
+
+ Xdr::write <StreamIO> (os, _value[3][0]);
+ Xdr::write <StreamIO> (os, _value[3][1]);
+ Xdr::write <StreamIO> (os, _value[3][2]);
+ Xdr::write <StreamIO> (os, _value[3][3]);
+}
+
+
+template <>
+void
+M44fAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value[0][0]);
+ Xdr::read <StreamIO> (is, _value[0][1]);
+ Xdr::read <StreamIO> (is, _value[0][2]);
+ Xdr::read <StreamIO> (is, _value[0][3]);
+
+ Xdr::read <StreamIO> (is, _value[1][0]);
+ Xdr::read <StreamIO> (is, _value[1][1]);
+ Xdr::read <StreamIO> (is, _value[1][2]);
+ Xdr::read <StreamIO> (is, _value[1][3]);
+
+ Xdr::read <StreamIO> (is, _value[2][0]);
+ Xdr::read <StreamIO> (is, _value[2][1]);
+ Xdr::read <StreamIO> (is, _value[2][2]);
+ Xdr::read <StreamIO> (is, _value[2][3]);
+
+ Xdr::read <StreamIO> (is, _value[3][0]);
+ Xdr::read <StreamIO> (is, _value[3][1]);
+ Xdr::read <StreamIO> (is, _value[3][2]);
+ Xdr::read <StreamIO> (is, _value[3][3]);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfMatrixAttribute.h b/Source/OpenEXR/IlmImf/ImfMatrixAttribute.h
new file mode 100644
index 0000000..db0efc7
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfMatrixAttribute.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_MATRIX_ATTRIBUTE_H
+#define INCLUDED_IMF_MATRIX_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class M33fAttribute
+// class M44fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include "ImathMatrix.h"
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Imath::M33f> M33fAttribute;
+template <> const char *M33fAttribute::staticTypeName ();
+template <> void M33fAttribute::writeValueTo (OStream &, int) const;
+template <> void M33fAttribute::readValueFrom (IStream &, int, int);
+
+
+typedef TypedAttribute<Imath::M44f> M44fAttribute;
+template <> const char *M44fAttribute::staticTypeName ();
+template <> void M44fAttribute::writeValueTo (OStream &, int) const;
+template <> void M44fAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfMatrixAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfMisc.cpp b/Source/OpenEXR/IlmImf/ImfMisc.cpp
new file mode 100644
index 0000000..e13f390
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfMisc.cpp
@@ -0,0 +1,787 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Miscellaneous helper functions for OpenEXR image file I/O
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfMisc.h>
+#include <ImfHeader.h>
+#include <ImfCompressor.h>
+#include <ImfChannelList.h>
+#include <ImfXdr.h>
+#include <ImathFun.h>
+#include <Iex.h>
+#include <ImfStdIO.h>
+#include <ImfConvert.h>
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::divp;
+using Imath::modp;
+using std::vector;
+
+int
+pixelTypeSize (PixelType type)
+{
+ int size;
+
+ switch (type)
+ {
+ case UINT:
+
+ size = Xdr::size <unsigned int> ();
+ break;
+
+ case HALF:
+
+ size = Xdr::size <half> ();
+ break;
+
+ case FLOAT:
+
+ size = Xdr::size <float> ();
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel type.");
+ }
+
+ return size;
+}
+
+
+int
+numSamples (int s, int a, int b)
+{
+ int a1 = divp (a, s);
+ int b1 = divp (b, s);
+ return b1 - a1 + ((a1 * s < a)? 0: 1);
+}
+
+
+size_t
+bytesPerLineTable (const Header &header,
+ vector<size_t> &bytesPerLine)
+{
+ const Box2i &dataWindow = header.dataWindow();
+ const ChannelList &channels = header.channels();
+
+ bytesPerLine.resize (dataWindow.max.y - dataWindow.min.y + 1);
+
+ for (ChannelList::ConstIterator c = channels.begin();
+ c != channels.end();
+ ++c)
+ {
+ int nBytes = pixelTypeSize (c.channel().type) *
+ (dataWindow.max.x - dataWindow.min.x + 1) /
+ c.channel().xSampling;
+
+ for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
+ if (modp (y, c.channel().ySampling) == 0)
+ bytesPerLine[i] += nBytes;
+ }
+
+ size_t maxBytesPerLine = 0;
+
+ for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
+ if (maxBytesPerLine < bytesPerLine[i])
+ maxBytesPerLine = bytesPerLine[i];
+
+ return maxBytesPerLine;
+}
+
+
+void
+offsetInLineBufferTable (const vector<size_t> &bytesPerLine,
+ int linesInLineBuffer,
+ vector<size_t> &offsetInLineBuffer)
+{
+ offsetInLineBuffer.resize (bytesPerLine.size());
+
+ size_t offset = 0;
+
+ for (int i = 0; i < bytesPerLine.size(); ++i)
+ {
+ if (i % linesInLineBuffer == 0)
+ offset = 0;
+
+ offsetInLineBuffer[i] = offset;
+ offset += bytesPerLine[i];
+ }
+}
+
+
+int
+lineBufferMinY (int y, int minY, int linesInLineBuffer)
+{
+ return ((y - minY) / linesInLineBuffer) * linesInLineBuffer + minY;
+}
+
+
+int
+lineBufferMaxY (int y, int minY, int linesInLineBuffer)
+{
+ return lineBufferMinY (y, minY, linesInLineBuffer) + linesInLineBuffer - 1;
+}
+
+
+Compressor::Format
+defaultFormat (Compressor * compressor)
+{
+ return compressor? compressor->format(): Compressor::XDR;
+}
+
+
+int
+numLinesInBuffer (Compressor * compressor)
+{
+ return compressor? compressor->numScanLines(): 1;
+}
+
+
+void
+copyIntoFrameBuffer (const char *& readPtr,
+ char * writePtr,
+ char * endPtr,
+ size_t xStride,
+ bool fill,
+ double fillValue,
+ Compressor::Format format,
+ PixelType typeInFrameBuffer,
+ PixelType typeInFile)
+{
+ //
+ // Copy a horizontal row of pixels from an input
+ // file's line or tile buffer to a frame buffer.
+ //
+
+ if (fill)
+ {
+ //
+ // The file contains no data for this channel.
+ // Store a default value in the frame buffer.
+ //
+
+ switch (typeInFrameBuffer)
+ {
+ case UINT:
+
+ {
+ unsigned int fillVal = (unsigned int) (fillValue);
+
+ while (writePtr <= endPtr)
+ {
+ *(unsigned int *) writePtr = fillVal;
+ writePtr += xStride;
+ }
+ }
+ break;
+
+ case HALF:
+
+ {
+ half fillVal = half (fillValue);
+
+ while (writePtr <= endPtr)
+ {
+ *(half *) writePtr = fillVal;
+ writePtr += xStride;
+ }
+ }
+ break;
+
+ case FLOAT:
+
+ {
+ float fillVal = float (fillValue);
+
+ while (writePtr <= endPtr)
+ {
+ *(float *) writePtr = fillVal;
+ writePtr += xStride;
+ }
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+ else if (format == Compressor::XDR)
+ {
+ //
+ // The the line or tile buffer is in XDR format.
+ //
+ // Convert the pixels from the file's machine-
+ // independent representation, and store the
+ // results in the frame buffer.
+ //
+
+ switch (typeInFrameBuffer)
+ {
+ case UINT:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ Xdr::read <CharPtrIO> (readPtr, *(unsigned int *) writePtr);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ half h;
+ Xdr::read <CharPtrIO> (readPtr, h);
+ *(unsigned int *) writePtr = halfToUint (h);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ float f;
+ Xdr::read <CharPtrIO> (readPtr, f);
+ *(unsigned int *)writePtr = floatToUint (f);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ case HALF:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ unsigned int ui;
+ Xdr::read <CharPtrIO> (readPtr, ui);
+ *(half *) writePtr = uintToHalf (ui);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ Xdr::read <CharPtrIO> (readPtr, *(half *) writePtr);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ float f;
+ Xdr::read <CharPtrIO> (readPtr, f);
+ *(half *) writePtr = floatToHalf (f);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ case FLOAT:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ unsigned int ui;
+ Xdr::read <CharPtrIO> (readPtr, ui);
+ *(float *) writePtr = float (ui);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ half h;
+ Xdr::read <CharPtrIO> (readPtr, h);
+ *(float *) writePtr = float (h);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ Xdr::read <CharPtrIO> (readPtr, *(float *) writePtr);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+ else
+ {
+ //
+ // The the line or tile buffer is in NATIVE format.
+ // Copy the results into the frame buffer.
+ //
+
+ switch (typeInFrameBuffer)
+ {
+ case UINT:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ for (size_t i = 0; i < sizeof (unsigned int); ++i)
+ writePtr[i] = readPtr[i];
+
+ readPtr += sizeof (unsigned int);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ half h = *(half *) readPtr;
+ *(unsigned int *) writePtr = halfToUint (h);
+ readPtr += sizeof (half);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ float f;
+
+ for (size_t i = 0; i < sizeof (float); ++i)
+ ((char *)&f)[i] = readPtr[i];
+
+ *(unsigned int *)writePtr = floatToUint (f);
+ readPtr += sizeof (float);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ case HALF:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ unsigned int ui;
+
+ for (size_t i = 0; i < sizeof (unsigned int); ++i)
+ ((char *)&ui)[i] = readPtr[i];
+
+ *(half *) writePtr = uintToHalf (ui);
+ readPtr += sizeof (unsigned int);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ *(half *) writePtr = *(half *)readPtr;
+ readPtr += sizeof (half);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ float f;
+
+ for (size_t i = 0; i < sizeof (float); ++i)
+ ((char *)&f)[i] = readPtr[i];
+
+ *(half *) writePtr = floatToHalf (f);
+ readPtr += sizeof (float);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ case FLOAT:
+
+ switch (typeInFile)
+ {
+ case UINT:
+
+ while (writePtr <= endPtr)
+ {
+ unsigned int ui;
+
+ for (size_t i = 0; i < sizeof (unsigned int); ++i)
+ ((char *)&ui)[i] = readPtr[i];
+
+ *(float *) writePtr = float (ui);
+ readPtr += sizeof (unsigned int);
+ writePtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (writePtr <= endPtr)
+ {
+ half h = *(half *) readPtr;
+ *(float *) writePtr = float (h);
+ readPtr += sizeof (half);
+ writePtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (writePtr <= endPtr)
+ {
+ for (size_t i = 0; i < sizeof (float); ++i)
+ writePtr[i] = readPtr[i];
+
+ readPtr += sizeof (float);
+ writePtr += xStride;
+ }
+ break;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+}
+
+
+void
+skipChannel (const char *& readPtr,
+ PixelType typeInFile,
+ size_t xSize)
+{
+ switch (typeInFile)
+ {
+ case UINT:
+
+ Xdr::skip <CharPtrIO> (readPtr, Xdr::size <unsigned int> () * xSize);
+ break;
+
+ case HALF:
+
+ Xdr::skip <CharPtrIO> (readPtr, Xdr::size <half> () * xSize);
+ break;
+
+ case FLOAT:
+
+ Xdr::skip <CharPtrIO> (readPtr, Xdr::size <float> () * xSize);
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+}
+
+
+void
+convertInPlace (char *& writePtr,
+ const char *& readPtr,
+ PixelType type,
+ size_t numPixels)
+{
+ switch (type)
+ {
+ case UINT:
+
+ for (int j = 0; j < numPixels; ++j)
+ {
+ Xdr::write <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
+ readPtr += sizeof(unsigned int);
+ }
+ break;
+
+ case HALF:
+
+ for (int j = 0; j < numPixels; ++j)
+ {
+ Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
+ readPtr += sizeof(half);
+ }
+ break;
+
+ case FLOAT:
+
+ for (int j = 0; j < numPixels; ++j)
+ {
+ Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
+ readPtr += sizeof(float);
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+}
+
+
+void
+copyFromFrameBuffer (char *& writePtr,
+ const char *& readPtr,
+ const char * endPtr,
+ size_t xStride,
+ Compressor::Format format,
+ PixelType type)
+{
+ //
+ // Copy a horizontal row of pixels from a frame
+ // buffer to an output file's line or tile buffer.
+ //
+
+ if (format == Compressor::XDR)
+ {
+ //
+ // The the line or tile buffer is in XDR format.
+ //
+
+ switch (type)
+ {
+ case UINT:
+
+ while (readPtr <= endPtr)
+ {
+ Xdr::write <CharPtrIO> (writePtr,
+ *(const unsigned int *) readPtr);
+ readPtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (readPtr <= endPtr)
+ {
+ Xdr::write <CharPtrIO> (writePtr, *(const half *) readPtr);
+ readPtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (readPtr <= endPtr)
+ {
+ Xdr::write <CharPtrIO> (writePtr, *(const float *) readPtr);
+ readPtr += xStride;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+ else
+ {
+ //
+ // The the line or tile buffer is in NATIVE format.
+ //
+
+ switch (type)
+ {
+ case UINT:
+
+ while (readPtr <= endPtr)
+ {
+ for (size_t i = 0; i < sizeof (unsigned int); ++i)
+ *writePtr++ = readPtr[i];
+
+ readPtr += xStride;
+ }
+ break;
+
+ case HALF:
+
+ while (readPtr <= endPtr)
+ {
+ *(half *) writePtr = *(const half *) readPtr;
+ writePtr += sizeof (half);
+ readPtr += xStride;
+ }
+ break;
+
+ case FLOAT:
+
+ while (readPtr <= endPtr)
+ {
+ for (size_t i = 0; i < sizeof (float); ++i)
+ *writePtr++ = readPtr[i];
+
+ readPtr += xStride;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+}
+
+
+void
+fillChannelWithZeroes (char *& writePtr,
+ Compressor::Format format,
+ PixelType type,
+ size_t xSize)
+{
+ if (format == Compressor::XDR)
+ {
+ //
+ // Fill with data in XDR format.
+ //
+
+ switch (type)
+ {
+ case UINT:
+
+ for (int j = 0; j < xSize; ++j)
+ Xdr::write <CharPtrIO> (writePtr, (unsigned int) 0);
+
+ break;
+
+ case HALF:
+
+ for (int j = 0; j < xSize; ++j)
+ Xdr::write <CharPtrIO> (writePtr, (half) 0);
+
+ break;
+
+ case FLOAT:
+
+ for (int j = 0; j < xSize; ++j)
+ Xdr::write <CharPtrIO> (writePtr, (float) 0);
+
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+ else
+ {
+ //
+ // Fill with data in NATIVE format.
+ //
+
+ switch (type)
+ {
+ case UINT:
+
+ for (int j = 0; j < xSize; ++j)
+ {
+ static const unsigned int ui = 0;
+
+ for (size_t i = 0; i < sizeof (ui); ++i)
+ *writePtr++ = ((char *) &ui)[i];
+ }
+ break;
+
+ case HALF:
+
+ for (int j = 0; j < xSize; ++j)
+ {
+ *(half *) writePtr = half (0);
+ writePtr += sizeof (half);
+ }
+ break;
+
+ case FLOAT:
+
+ for (int j = 0; j < xSize; ++j)
+ {
+ static const float f = 0;
+
+ for (size_t i = 0; i < sizeof (f); ++i)
+ *writePtr++ = ((char *) &f)[i];
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown pixel data type.");
+ }
+ }
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfMisc.h b/Source/OpenEXR/IlmImf/ImfMisc.h
new file mode 100644
index 0000000..85718f4
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfMisc.h
@@ -0,0 +1,255 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_MISC_H
+#define INCLUDED_IMF_MISC_H
+
+//-----------------------------------------------------------------------------
+//
+// Miscellaneous helper functions for OpenEXR image file I/O
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfPixelType.h>
+#include <vector>
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+class Header;
+
+//
+// Return the size of a single value of the indicated type,
+// in the machine's native format.
+//
+
+int pixelTypeSize (PixelType type);
+
+
+//
+// Return the number of samples a channel with subsampling rate
+// s has in the interval [a, b]. For example, a channel with
+// subsampling rate 2 (and samples at 0, 2, 4, 6, 8, etc.) has
+// 2 samples in the interval [1, 5] and three samples in the
+// interval [2, 6].
+//
+
+int numSamples (int s, int a, int b);
+
+
+//
+// Build a table that lists, for each scanline in a file's
+// data window, how many bytes are required to store all
+// pixels in all channels in that scanline (assuming that
+// the pixel data are tightly packed).
+//
+
+size_t bytesPerLineTable (const Header &header,
+ std::vector<size_t> &bytesPerLine);
+
+//
+// For scanline-based files, pixels are read or written in
+// in multi-scanline blocks. Internally, class OutputFile
+// and class ScanLineInputFile store a block of scan lines
+// in a "line buffer". Function offsetInLineBufferTable()
+// builds a table that lists, for each scan line in a file's
+// data window, the location of the pixel data for the scanline
+// relative to the beginning of the line buffer.
+//
+
+void offsetInLineBufferTable (const std::vector<size_t> &bytesPerLine,
+ int linesInLineBuffer,
+ std::vector<size_t> &offsetInLineBuffer);
+
+//
+// For a scanline-based file, compute the range of scanlines
+// that occupy the same line buffer as a given scanline, y.
+// (minY is the minimum y coordinate of the file's data window.)
+//
+
+int lineBufferMinY (int y, int minY, int linesInLineBuffer);
+int lineBufferMaxY (int y, int minY, int linesInLineBuffer);
+
+
+//
+// Return a compressor's data format (Compressor::NATIVE or Compressor::XDR).
+// If compressor is 0, return Compressor::XDR.
+//
+
+Compressor::Format defaultFormat (Compressor *compressor);
+
+
+//
+// Return the number of scan lines a compressor wants to compress
+// or uncompress at once. If compressor is 0, return 1.
+//
+
+int numLinesInBuffer (Compressor *compressor);
+
+
+//
+// Copy a single channel of a horizontal row of pixels from an
+// input file's internal line buffer or tile buffer into a
+// frame buffer slice. If necessary, perform on-the-fly data
+// type conversion.
+//
+// readPtr initially points to the beginning of the
+// data in the line or tile buffer. readPtr
+// is advanced as the pixel data are copied;
+// when copyIntoFrameBuffer() returns,
+// readPtr points just past the end of the
+// copied data.
+//
+// writePtr, endPtr point to the lefmost and rightmost pixels
+// in the frame buffer slice
+//
+// xStride the xStride for the frame buffer slice
+//
+// format indicates if the line or tile buffer is
+// in NATIVE or XDR format.
+//
+// typeInFrameBuffer the pixel data type of the frame buffer slice
+//
+// typeInFile the pixel data type in the input file's channel
+//
+
+void copyIntoFrameBuffer (const char *&readPtr,
+ char *writePtr,
+ char *endPtr,
+ size_t xStride,
+ bool fill,
+ double fillValue,
+ Compressor::Format format,
+ PixelType typeInFrameBuffer,
+ PixelType typeInFile);
+
+//
+// Given a pointer into a an input file's line buffer or tile buffer,
+// skip over the data for xSize pixels of type typeInFile.
+// readPtr initially points to the beginning of the data to be skipped;
+// when skipChannel() returns, readPtr points just past the end of the
+// skipped data.
+//
+
+void skipChannel (const char *&readPtr,
+ PixelType typeInFile,
+ size_t xSize);
+
+//
+// Convert an array of pixel data from the machine's native
+// representation to XDR format.
+//
+// toPtr, fromPtr initially point to the beginning of the input
+// and output pixel data arrays; when convertInPlace()
+// returns, toPtr and fromPtr point just past the
+// end of the input and output arrays.
+// If the native representation of the data has the
+// same size as the XDR data, then the conversion
+// can take in place, without an intermediate
+// temporary buffer (toPtr and fromPtr can point
+// to the same location).
+//
+// type the pixel data type
+//
+// numPixels number of pixels in the input and output arrays
+//
+
+void convertInPlace (char *&toPtr,
+ const char *&fromPtr,
+ PixelType type,
+ size_t numPixels);
+
+//
+// Copy a single channel of a horizontal row of pixels from a
+// a frame buffer into an output file's internal line buffer or
+// tile buffer.
+//
+// writePtr initially points to the beginning of the
+// data in the line or tile buffer. writePtr
+// is advanced as the pixel data are copied;
+// when copyFromFrameBuffer() returns,
+// writePtr points just past the end of the
+// copied data.
+//
+// readPtr, endPtr point to the lefmost and rightmost pixels
+// in the frame buffer slice
+//
+// xStride the xStride for the frame buffer slice
+//
+// format indicates if the line or tile buffer is
+// in NATIVE or XDR format.
+//
+// type the pixel data type in the frame buffer
+// and in the output file's channel (function
+// copyFromFrameBuffer() doesn't do on-the-fly
+// data type conversion)
+//
+
+void copyFromFrameBuffer (char *&writePtr,
+ const char *&readPtr,
+ const char *endPtr,
+ size_t xStride,
+ Compressor::Format format,
+ PixelType type);
+
+//
+// Fill part of an output file's line buffer or tile buffer with
+// zeroes. This routine is called when an output file contains
+// a channel for which the frame buffer contains no corresponding
+// slice.
+//
+// writePtr initially points to the beginning of the
+// data in the line or tile buffer. When
+// fillChannelWithZeroes() returns, writePtr
+// points just past the end of the zeroed
+// data.
+//
+// format indicates if the line or tile buffer is
+// in NATIVE or XDR format.
+//
+// type the pixel data type in the line or frame buffer.
+//
+// xSize number of pixels to be filled with zeroes.
+//
+
+void fillChannelWithZeroes (char *&writePtr,
+ Compressor::Format format,
+ PixelType type,
+ size_t xSize);
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfName.h b/Source/OpenEXR/IlmImf/ImfName.h
new file mode 100644
index 0000000..afa8930
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfName.h
@@ -0,0 +1,146 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_NAME_H
+#define INCLUDED_IMF_NAME_H
+
+//-----------------------------------------------------------------------------
+//
+// class ImfName -- a zero-terminated string
+// with a fixed, small maximum length
+//
+//-----------------------------------------------------------------------------
+
+#include <string.h>
+
+namespace Imf {
+
+
+class Name
+{
+ public:
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Name ();
+ Name (const char text[]);
+
+
+ //--------------------
+ // Assignment operator
+ //--------------------
+
+ Name & operator = (const char text[]);
+
+
+ //---------------------
+ // Access to the string
+ //---------------------
+
+ const char * text () const {return _text;}
+ const char * operator * () const {return _text;}
+
+ //---------------
+ // Maximum length
+ //---------------
+
+ static const int SIZE = 32;
+ static const int MAX_LENGTH = SIZE - 1;
+
+ private:
+
+ char _text[SIZE];
+};
+
+
+bool operator == (const Name &x, const Name &y);
+bool operator != (const Name &x, const Name &y);
+bool operator < (const Name &x, const Name &y);
+
+
+//-----------------
+// Inline functions
+//-----------------
+
+inline Name &
+Name::operator = (const char text[])
+{
+ strncpy (_text, text, MAX_LENGTH);
+ return *this;
+}
+
+
+inline
+Name::Name ()
+{
+ _text[0] = 0;
+}
+
+
+inline
+Name::Name (const char text[])
+{
+ *this = text;
+ _text [MAX_LENGTH] = 0;
+}
+
+
+inline bool
+operator == (const Name &x, const Name &y)
+{
+ return strcmp (*x, *y) == 0;
+}
+
+
+inline bool
+operator != (const Name &x, const Name &y)
+{
+ return !(x == y);
+}
+
+
+inline bool
+operator < (const Name &x, const Name &y)
+{
+ return strcmp (*x, *y) < 0;
+}
+
+
+} // namespace IMF
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.cpp b/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.cpp
new file mode 100644
index 0000000..0abaa86
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.cpp
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class OpaqueAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfOpaqueAttribute.h>
+#include "Iex.h"
+#include <string.h>
+
+namespace Imf {
+
+
+OpaqueAttribute::OpaqueAttribute (const char typeName[]):
+ _typeName (strlen (typeName) + 1),
+ _dataSize (0)
+{
+ strcpy (_typeName, typeName);
+}
+
+
+OpaqueAttribute::OpaqueAttribute (const OpaqueAttribute &other):
+ _typeName (strlen (other._typeName) + 1),
+ _dataSize (other._dataSize),
+ _data (other._dataSize)
+{
+ strcpy (_typeName, other._typeName);
+ _data.resizeErase (other._dataSize);
+ memcpy ((char *) _data, (const char *) other._data, other._dataSize);
+}
+
+
+OpaqueAttribute::~OpaqueAttribute ()
+{
+ // empty
+}
+
+
+const char *
+OpaqueAttribute::typeName () const
+{
+ return _typeName;
+}
+
+
+Attribute *
+OpaqueAttribute::copy () const
+{
+ return new OpaqueAttribute (*this);
+}
+
+
+void
+OpaqueAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _data, _dataSize);
+}
+
+
+void
+OpaqueAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ _data.resizeErase (size);
+ _dataSize = size;
+ Xdr::read <StreamIO> (is, _data, size);
+}
+
+
+void
+OpaqueAttribute::copyValueFrom (const Attribute &other)
+{
+ const OpaqueAttribute *oa = dynamic_cast <const OpaqueAttribute *> (&other);
+
+ if (oa == 0 || strcmp (_typeName, oa->_typeName))
+ {
+ THROW (Iex::TypeExc, "Cannot copy the value of an "
+ "image file attribute of type "
+ "\"" << other.typeName() << "\" "
+ "to an attribute of type "
+ "\"" << _typeName << "\".");
+ }
+
+ _data.resizeErase (oa->_dataSize);
+ _dataSize = oa->_dataSize;
+ memcpy ((char *) _data, (const char *) oa->_data, oa->_dataSize);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.h b/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.h
new file mode 100644
index 0000000..864ae93
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfOpaqueAttribute.h
@@ -0,0 +1,114 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_OPAQUE_ATTRIBUTE_H
+#define INCLUDED_IMF_OPAQUE_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class OpaqueAttribute
+//
+// When an image file is read, OpqaqueAttribute objects are used
+// to hold the values of attributes whose types are not recognized
+// by the reading program. OpaqueAttribute objects can be read
+// from an image file, copied, and written back to to another image
+// file, but their values are inaccessible.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfArray.h>
+
+namespace Imf {
+
+
+class OpaqueAttribute: public Attribute
+{
+ public:
+
+ //----------------------------
+ // Constructors and destructor
+ //----------------------------
+
+ OpaqueAttribute (const char typeName[]);
+ OpaqueAttribute (const OpaqueAttribute &other);
+ virtual ~OpaqueAttribute ();
+
+
+ //-------------------------------
+ // Get this attribute's type name
+ //-------------------------------
+
+ virtual const char * typeName () const;
+
+
+ //------------------------------
+ // Make a copy of this attribute
+ //------------------------------
+
+ virtual Attribute * copy () const;
+
+
+ //----------------
+ // I/O and copying
+ //----------------
+
+ virtual void writeValueTo (OStream &os,
+ int version) const;
+
+ virtual void readValueFrom (IStream &is,
+ int size,
+ int version);
+
+ virtual void copyValueFrom (const Attribute &other);
+
+
+ private:
+
+ Array<char> _typeName;
+ long _dataSize;
+ Array<char> _data;
+};
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfOpaqueAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfOutputFile.cpp b/Source/OpenEXR/IlmImf/ImfOutputFile.cpp
new file mode 100644
index 0000000..31a339e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfOutputFile.cpp
@@ -0,0 +1,1287 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class OutputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfOutputFile.h>
+#include <ImfInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImfStdIO.h>
+#include <ImfCompressor.h>
+#include "ImathBox.h"
+#include "ImathFun.h"
+#include <ImfArray.h>
+#include <ImfXdr.h>
+#include <ImfPreviewImageAttribute.h>
+#include "IlmThreadPool.h"
+#include "IlmThreadSemaphore.h"
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <string>
+#include <vector>
+#include <fstream>
+#include <assert.h>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::divp;
+using Imath::modp;
+using std::string;
+using std::vector;
+using std::ofstream;
+using std::min;
+using std::max;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+using IlmThread::Semaphore;
+using IlmThread::Task;
+using IlmThread::TaskGroup;
+using IlmThread::ThreadPool;
+
+namespace {
+
+
+struct OutSliceInfo
+{
+ PixelType type;
+ const char * base;
+ size_t xStride;
+ size_t yStride;
+ int xSampling;
+ int ySampling;
+ bool zero;
+
+ OutSliceInfo (PixelType type = HALF,
+ const char *base = 0,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ int xSampling = 1,
+ int ySampling = 1,
+ bool zero = false);
+};
+
+
+OutSliceInfo::OutSliceInfo (PixelType t,
+ const char *b,
+ size_t xs, size_t ys,
+ int xsm, int ysm,
+ bool z)
+:
+ type (t),
+ base (b),
+ xStride (xs),
+ yStride (ys),
+ xSampling (xsm),
+ ySampling (ysm),
+ zero (z)
+{
+ // empty
+}
+
+
+struct LineBuffer
+{
+ Array<char> buffer;
+ const char * dataPtr;
+ int dataSize;
+ char * endOfLineBufferData;
+ int minY;
+ int maxY;
+ int scanLineMin;
+ int scanLineMax;
+ Compressor * compressor;
+ bool partiallyFull; // has incomplete data
+ bool hasException;
+ string exception;
+
+ LineBuffer (Compressor *comp);
+ ~LineBuffer ();
+
+ void wait () {_sem.wait();}
+ void post () {_sem.post();}
+
+ private:
+
+ Semaphore _sem;
+};
+
+
+LineBuffer::LineBuffer (Compressor *comp) :
+ dataPtr (0),
+ dataSize (0),
+ compressor (comp),
+ partiallyFull (false),
+ hasException (false),
+ exception (),
+ _sem (1)
+{
+ // empty
+}
+
+
+LineBuffer::~LineBuffer ()
+{
+ delete compressor;
+}
+
+} // namespace
+
+
+struct OutputFile::Data: public Mutex
+{
+ Header header; // the image header
+ int version; // file format version
+ Int64 previewPosition; // file position for preview
+ FrameBuffer frameBuffer; // framebuffer to write into
+ int currentScanLine; // next scanline to be written
+ int missingScanLines; // number of lines to write
+ LineOrder lineOrder; // the file's lineorder
+ int minX; // data window's min x coord
+ int maxX; // data window's max x coord
+ int minY; // data window's min y coord
+ int maxY; // data window's max x coord
+ vector<Int64> lineOffsets; // stores offsets in file for
+ // each scanline
+ vector<size_t> bytesPerLine; // combined size of a line over
+ // all channels
+ vector<size_t> offsetInLineBuffer; // offset for each scanline in
+ // its linebuffer
+ Compressor::Format format; // compressor's data format
+ vector<OutSliceInfo> slices; // info about channels in file
+ OStream * os; // file stream to write to
+ bool deleteStream;
+ Int64 lineOffsetsPosition; // file position for line
+ // offset table
+ Int64 currentPosition; // current file position
+
+ vector<LineBuffer*> lineBuffers; // each holds one line buffer
+ int linesInBuffer; // number of scanlines each
+ // buffer holds
+ size_t lineBufferSize; // size of the line buffer
+
+ Data (bool deleteStream, int numThreads);
+ ~Data ();
+
+
+ inline LineBuffer * getLineBuffer (int number); // hash function from line
+ // buffer indices into our
+ // vector of line buffers
+};
+
+
+OutputFile::Data::Data (bool deleteStream, int numThreads):
+ os (0),
+ deleteStream (deleteStream),
+ lineOffsetsPosition (0)
+{
+ //
+ // We need at least one lineBuffer, but if threading is used,
+ // to keep n threads busy we need 2*n lineBuffers.
+ //
+
+ lineBuffers.resize (max (1, 2 * numThreads));
+}
+
+
+OutputFile::Data::~Data ()
+{
+ if (deleteStream)
+ delete os;
+
+ for (size_t i = 0; i < lineBuffers.size(); i++)
+ delete lineBuffers[i];
+}
+
+
+LineBuffer*
+OutputFile::Data::getLineBuffer (int number)
+{
+ return lineBuffers[number % lineBuffers.size()];
+}
+
+
+namespace {
+
+
+Int64
+writeLineOffsets (OStream &os, const vector<Int64> &lineOffsets)
+{
+ Int64 pos = os.tellp();
+
+ if (pos == -1)
+ Iex::throwErrnoExc ("Cannot determine current file position (%T).");
+
+ for (unsigned int i = 0; i < lineOffsets.size(); i++)
+ Xdr::write <StreamIO> (os, lineOffsets[i]);
+
+ return pos;
+}
+
+
+void
+writePixelData (OutputFile::Data *ofd,
+ int lineBufferMinY,
+ const char pixelData[],
+ int pixelDataSize)
+{
+ //
+ // Store a block of pixel data in the output file, and try
+ // to keep track of the current writing position the file
+ // without calling tellp() (tellp() can be fairly expensive).
+ //
+
+ Int64 currentPosition = ofd->currentPosition;
+ ofd->currentPosition = 0;
+
+ if (currentPosition == 0)
+ currentPosition = ofd->os->tellp();
+
+ ofd->lineOffsets[(ofd->currentScanLine - ofd->minY) / ofd->linesInBuffer] =
+ currentPosition;
+
+ #ifdef DEBUG
+
+ assert (ofd->os->tellp() == currentPosition);
+
+ #endif
+
+ Xdr::write <StreamIO> (*ofd->os, lineBufferMinY);
+ Xdr::write <StreamIO> (*ofd->os, pixelDataSize);
+ ofd->os->write (pixelData, pixelDataSize);
+
+ ofd->currentPosition = currentPosition +
+ Xdr::size<int>() +
+ Xdr::size<int>() +
+ pixelDataSize;
+}
+
+
+inline void
+writePixelData (OutputFile::Data *ofd, const LineBuffer *lineBuffer)
+{
+ writePixelData (ofd,
+ lineBuffer->minY,
+ lineBuffer->dataPtr,
+ lineBuffer->dataSize);
+}
+
+
+void
+convertToXdr (OutputFile::Data *ofd,
+ Array<char> &lineBuffer,
+ int lineBufferMinY,
+ int lineBufferMaxY,
+ int inSize)
+{
+ //
+ // Convert the contents of a lineBuffer from the machine's native
+ // representation to Xdr format. This function is called by
+ // CompressLineBuffer::execute(), below, if the compressor wanted
+ // its input pixel data in the machine's native format, but then
+ // failed to compress the data (most compressors will expand rather
+ // than compress random input data).
+ //
+ // Note that this routine assumes that the machine's native
+ // representation of the pixel data has the same size as the
+ // Xdr representation. This makes it possible to convert the
+ // pixel data in place, without an intermediate temporary buffer.
+ //
+
+ int startY, endY; // The first and last scanlines in
+ // the file that are in the lineBuffer.
+ int step;
+
+ if (ofd->lineOrder == INCREASING_Y)
+ {
+ startY = max (lineBufferMinY, ofd->minY);
+ endY = min (lineBufferMaxY, ofd->maxY) + 1;
+ step = 1;
+ }
+ else
+ {
+ startY = min (lineBufferMaxY, ofd->maxY);
+ endY = max (lineBufferMinY, ofd->minY) - 1;
+ step = -1;
+ }
+
+ //
+ // Iterate over all scanlines in the lineBuffer to convert.
+ //
+
+ for (int y = startY; y != endY; y += step)
+ {
+ //
+ // Set these to point to the start of line y.
+ // We will write to writePtr from readPtr.
+ //
+
+ char *writePtr = lineBuffer + ofd->offsetInLineBuffer[y - ofd->minY];
+ const char *readPtr = writePtr;
+
+ //
+ // Iterate over all slices in the file.
+ //
+
+ for (unsigned int i = 0; i < ofd->slices.size(); ++i)
+ {
+ //
+ // Test if scan line y of this channel is
+ // contains any data (the scan line contains
+ // data only if y % ySampling == 0).
+ //
+
+ const OutSliceInfo &slice = ofd->slices[i];
+
+ if (modp (y, slice.ySampling) != 0)
+ continue;
+
+ //
+ // Find the number of sampled pixels, dMaxX-dMinX+1, for
+ // slice i in scan line y (i.e. pixels within the data window
+ // for which x % xSampling == 0).
+ //
+
+ int dMinX = divp (ofd->minX, slice.xSampling);
+ int dMaxX = divp (ofd->maxX, slice.xSampling);
+
+ //
+ // Convert the samples in place.
+ //
+
+ convertInPlace (writePtr, readPtr, slice.type, dMaxX - dMinX + 1);
+ }
+ }
+}
+
+
+//
+// A LineBufferTask encapsulates the task of copying a set of scanlines
+// from the user's frame buffer into a LineBuffer object, compressing
+// the data if necessary.
+//
+
+class LineBufferTask: public Task
+{
+ public:
+
+ LineBufferTask (TaskGroup *group,
+ OutputFile::Data *ofd,
+ int number,
+ int scanLineMin,
+ int scanLineMax);
+
+ virtual ~LineBufferTask ();
+
+ virtual void execute ();
+
+ private:
+
+ OutputFile::Data * _ofd;
+ LineBuffer * _lineBuffer;
+};
+
+
+LineBufferTask::LineBufferTask
+ (TaskGroup *group,
+ OutputFile::Data *ofd,
+ int number,
+ int scanLineMin,
+ int scanLineMax)
+:
+ Task (group),
+ _ofd (ofd),
+ _lineBuffer (_ofd->getLineBuffer(number))
+{
+ //
+ // Wait for the lineBuffer to become available
+ //
+
+ _lineBuffer->wait ();
+
+ //
+ // Initialize the lineBuffer data if necessary
+ //
+
+ if (!_lineBuffer->partiallyFull)
+ {
+ _lineBuffer->endOfLineBufferData = _lineBuffer->buffer;
+
+ _lineBuffer->minY = _ofd->minY + number * _ofd->linesInBuffer;
+
+ _lineBuffer->maxY = min (_lineBuffer->minY + _ofd->linesInBuffer - 1,
+ _ofd->maxY);
+
+ _lineBuffer->partiallyFull = true;
+ }
+
+ _lineBuffer->scanLineMin = max (_lineBuffer->minY, scanLineMin);
+ _lineBuffer->scanLineMax = min (_lineBuffer->maxY, scanLineMax);
+}
+
+
+LineBufferTask::~LineBufferTask ()
+{
+ //
+ // Signal that the line buffer is now free
+ //
+
+ _lineBuffer->post ();
+}
+
+
+void
+LineBufferTask::execute ()
+{
+ try
+ {
+ //
+ // First copy the pixel data from the
+ // frame buffer into the line buffer
+ //
+
+ int yStart, yStop, dy;
+
+ if (_ofd->lineOrder == INCREASING_Y)
+ {
+ yStart = _lineBuffer->scanLineMin;
+ yStop = _lineBuffer->scanLineMax + 1;
+ dy = 1;
+ }
+ else
+ {
+ yStart = _lineBuffer->scanLineMax;
+ yStop = _lineBuffer->scanLineMin - 1;
+ dy = -1;
+ }
+
+ int y;
+
+ for (y = yStart; y != yStop; y += dy)
+ {
+ //
+ // Gather one scan line's worth of pixel data and store
+ // them in _ofd->lineBuffer.
+ //
+
+ char *writePtr = _lineBuffer->buffer +
+ _ofd->offsetInLineBuffer[y - _ofd->minY];
+ //
+ // Iterate over all image channels.
+ //
+
+ for (unsigned int i = 0; i < _ofd->slices.size(); ++i)
+ {
+ //
+ // Test if scan line y of this channel contains any data
+ // (the scan line contains data only if y % ySampling == 0).
+ //
+
+ const OutSliceInfo &slice = _ofd->slices[i];
+
+ if (modp (y, slice.ySampling) != 0)
+ continue;
+
+ //
+ // Find the x coordinates of the leftmost and rightmost
+ // sampled pixels (i.e. pixels within the data window
+ // for which x % xSampling == 0).
+ //
+
+ int dMinX = divp (_ofd->minX, slice.xSampling);
+ int dMaxX = divp (_ofd->maxX, slice.xSampling);
+
+ //
+ // Fill the line buffer with with pixel data.
+ //
+
+ if (slice.zero)
+ {
+ //
+ // The frame buffer contains no data for this channel.
+ // Store zeroes in _lineBuffer->buffer.
+ //
+
+ fillChannelWithZeroes (writePtr, _ofd->format, slice.type,
+ dMaxX - dMinX + 1);
+ }
+ else
+ {
+ //
+ // If necessary, convert the pixel data to Xdr format.
+ // Then store the pixel data in _ofd->lineBuffer.
+ //
+
+ const char *linePtr = slice.base +
+ divp (y, slice.ySampling) *
+ slice.yStride;
+
+ const char *readPtr = linePtr + dMinX * slice.xStride;
+ const char *endPtr = linePtr + dMaxX * slice.xStride;
+
+ copyFromFrameBuffer (writePtr, readPtr, endPtr,
+ slice.xStride, _ofd->format,
+ slice.type);
+ }
+ }
+
+ if (_lineBuffer->endOfLineBufferData < writePtr)
+ _lineBuffer->endOfLineBufferData = writePtr;
+
+ #ifdef DEBUG
+
+ assert (writePtr - (_lineBuffer->buffer +
+ _ofd->offsetInLineBuffer[y - _ofd->minY]) ==
+ (int) _ofd->bytesPerLine[y - _ofd->minY]);
+
+ #endif
+
+ }
+
+ //
+ // If the next scanline isn't past the bounds of the lineBuffer
+ // then we are done, otherwise compress the linebuffer
+ //
+
+ if (y >= _lineBuffer->minY && y <= _lineBuffer->maxY)
+ return;
+
+ _lineBuffer->dataPtr = _lineBuffer->buffer;
+
+ _lineBuffer->dataSize = _lineBuffer->endOfLineBufferData -
+ _lineBuffer->buffer;
+
+ //
+ // Compress the data
+ //
+
+ Compressor *compressor = _lineBuffer->compressor;
+
+ if (compressor)
+ {
+ const char *compPtr;
+
+ int compSize = compressor->compress (_lineBuffer->dataPtr,
+ _lineBuffer->dataSize,
+ _lineBuffer->minY, compPtr);
+
+ if (compSize < _lineBuffer->dataSize)
+ {
+ _lineBuffer->dataSize = compSize;
+ _lineBuffer->dataPtr = compPtr;
+ }
+ else if (_ofd->format == Compressor::NATIVE)
+ {
+ //
+ // The data did not shrink during compression, but
+ // we cannot write to the file using the machine's
+ // native format, so we need to convert the lineBuffer
+ // to Xdr.
+ //
+
+ convertToXdr (_ofd, _lineBuffer->buffer, _lineBuffer->minY,
+ _lineBuffer->maxY, _lineBuffer->dataSize);
+ }
+ }
+
+ _lineBuffer->partiallyFull = false;
+ }
+ catch (std::exception &e)
+ {
+ if (!_lineBuffer->hasException)
+ {
+ _lineBuffer->exception = e.what ();
+ _lineBuffer->hasException = true;
+ }
+ }
+ catch (...)
+ {
+ if (!_lineBuffer->hasException)
+ {
+ _lineBuffer->exception = "unrecognized exception";
+ _lineBuffer->hasException = true;
+ }
+ }
+}
+
+} // namespace
+
+
+OutputFile::OutputFile
+ (const char fileName[],
+ const Header &header,
+ int numThreads)
+:
+ _data (new Data (true, numThreads))
+{
+ try
+ {
+ header.sanityCheck();
+ _data->os = new StdOFStream (fileName);
+ initialize (header);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << fileName << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+OutputFile::OutputFile
+ (OStream &os,
+ const Header &header,
+ int numThreads)
+:
+ _data (new Data (false, numThreads))
+{
+ try
+ {
+ header.sanityCheck();
+ _data->os = &os;
+ initialize (header);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << os.fileName() << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+void
+OutputFile::initialize (const Header &header)
+{
+ _data->header = header;
+
+ const Box2i &dataWindow = header.dataWindow();
+
+ _data->currentScanLine = (header.lineOrder() == INCREASING_Y)?
+ dataWindow.min.y: dataWindow.max.y;
+
+ _data->missingScanLines = dataWindow.max.y - dataWindow.min.y + 1;
+ _data->lineOrder = header.lineOrder();
+ _data->minX = dataWindow.min.x;
+ _data->maxX = dataWindow.max.x;
+ _data->minY = dataWindow.min.y;
+ _data->maxY = dataWindow.max.y;
+
+ size_t maxBytesPerLine = bytesPerLineTable (_data->header,
+ _data->bytesPerLine);
+
+ for (size_t i = 0; i < _data->lineBuffers.size(); ++i)
+ {
+ _data->lineBuffers[i] =
+ new LineBuffer (newCompressor (_data->header.compression(),
+ maxBytesPerLine,
+ _data->header));
+ }
+
+ LineBuffer *lineBuffer = _data->lineBuffers[0];
+ _data->format = defaultFormat (lineBuffer->compressor);
+ _data->linesInBuffer = numLinesInBuffer (lineBuffer->compressor);
+ _data->lineBufferSize = maxBytesPerLine * _data->linesInBuffer;
+
+ for (size_t i = 0; i < _data->lineBuffers.size(); i++)
+ _data->lineBuffers[i]->buffer.resizeErase(_data->lineBufferSize);
+
+ int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y +
+ _data->linesInBuffer) / _data->linesInBuffer;
+
+ _data->lineOffsets.resize (lineOffsetSize);
+
+ offsetInLineBufferTable (_data->bytesPerLine,
+ _data->linesInBuffer,
+ _data->offsetInLineBuffer);
+
+ _data->previewPosition =
+ _data->header.writeTo (*_data->os);
+
+ _data->lineOffsetsPosition =
+ writeLineOffsets (*_data->os, _data->lineOffsets);
+
+ _data->currentPosition = _data->os->tellp();
+}
+
+
+OutputFile::~OutputFile ()
+{
+ if (_data)
+ {
+ {
+ if (_data->lineOffsetsPosition > 0)
+ {
+ try
+ {
+ _data->os->seekp (_data->lineOffsetsPosition);
+ writeLineOffsets (*_data->os, _data->lineOffsets);
+ }
+ catch (...)
+ {
+ //
+ // We cannot safely throw any exceptions from here.
+ // This destructor may have been called because the
+ // stack is currently being unwound for another
+ // exception.
+ //
+ }
+ }
+ }
+
+ delete _data;
+ }
+}
+
+
+const char *
+OutputFile::fileName () const
+{
+ return _data->os->fileName();
+}
+
+
+const Header &
+OutputFile::header () const
+{
+ return _data->header;
+}
+
+
+void
+OutputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
+{
+ Lock lock (*_data);
+
+ //
+ // Check if the new frame buffer descriptor
+ // is compatible with the image file header.
+ //
+
+ const ChannelList &channels = _data->header.channels();
+
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ FrameBuffer::ConstIterator j = frameBuffer.find (i.name());
+
+ if (j == frameBuffer.end())
+ continue;
+
+ if (i.channel().type != j.slice().type)
+ {
+ THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" channel "
+ "of output file \"" << fileName() << "\" is "
+ "not compatible with the frame buffer's "
+ "pixel type.");
+ }
+
+ if (i.channel().xSampling != j.slice().xSampling ||
+ i.channel().ySampling != j.slice().ySampling)
+ {
+ THROW (Iex::ArgExc, "X and/or y subsampling factors "
+ "of \"" << i.name() << "\" channel "
+ "of output file \"" << fileName() << "\" are "
+ "not compatible with the frame buffer's "
+ "subsampling factors.");
+ }
+ }
+
+ //
+ // Initialize slice table for writePixels().
+ //
+
+ vector<OutSliceInfo> slices;
+
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ FrameBuffer::ConstIterator j = frameBuffer.find (i.name());
+
+ if (j == frameBuffer.end())
+ {
+ //
+ // Channel i is not present in the frame buffer.
+ // In the file, channel i will contain only zeroes.
+ //
+
+ slices.push_back (OutSliceInfo (i.channel().type,
+ 0, // base
+ 0, // xStride,
+ 0, // yStride,
+ i.channel().xSampling,
+ i.channel().ySampling,
+ true)); // zero
+ }
+ else
+ {
+ //
+ // Channel i is present in the frame buffer.
+ //
+
+ slices.push_back (OutSliceInfo (j.slice().type,
+ j.slice().base,
+ j.slice().xStride,
+ j.slice().yStride,
+ j.slice().xSampling,
+ j.slice().ySampling,
+ false)); // zero
+ }
+ }
+
+ //
+ // Store the new frame buffer.
+ //
+
+ _data->frameBuffer = frameBuffer;
+ _data->slices = slices;
+}
+
+
+const FrameBuffer &
+OutputFile::frameBuffer () const
+{
+ Lock lock (*_data);
+ return _data->frameBuffer;
+}
+
+
+void
+OutputFile::writePixels (int numScanLines)
+{
+ try
+ {
+ Lock lock (*_data);
+
+ if (_data->slices.size() == 0)
+ throw Iex::ArgExc ("No frame buffer specified "
+ "as pixel data source.");
+
+ //
+ // Maintain two iterators:
+ // nextWriteBuffer: next linebuffer to be written to the file
+ // nextCompressBuffer: next linebuffer to compress
+ //
+
+ int first = (_data->currentScanLine - _data->minY) /
+ _data->linesInBuffer;
+
+ int nextWriteBuffer = first;
+ int nextCompressBuffer;
+ int stop;
+ int step;
+ int scanLineMin;
+ int scanLineMax;
+
+ {
+ //
+ // Create a task group for all line buffer tasks. When the
+ // taskgroup goes out of scope, the destructor waits until
+ // all tasks are complete.
+ //
+
+ TaskGroup taskGroup;
+
+ //
+ // Determine the range of lineBuffers that intersect the scan
+ // line range. Then add the initial compression tasks to the
+ // thread pool. We always add in at least one task but the
+ // individual task might not do anything if numScanLines == 0.
+ //
+
+ if (_data->lineOrder == INCREASING_Y)
+ {
+ int last = (_data->currentScanLine + (numScanLines - 1) -
+ _data->minY) / _data->linesInBuffer;
+
+ scanLineMin = _data->currentScanLine;
+ scanLineMax = _data->currentScanLine + numScanLines - 1;
+
+ int numTasks = max (min ((int)_data->lineBuffers.size(),
+ last - first + 1),
+ 1);
+
+ for (int i = 0; i < numTasks; i++)
+ {
+ ThreadPool::addGlobalTask
+ (new LineBufferTask (&taskGroup, _data, first + i,
+ scanLineMin, scanLineMax));
+ }
+
+ nextCompressBuffer = first + numTasks;
+ stop = last + 1;
+ step = 1;
+ }
+ else
+ {
+ int last = (_data->currentScanLine - (numScanLines - 1) -
+ _data->minY) / _data->linesInBuffer;
+
+ scanLineMax = _data->currentScanLine;
+ scanLineMin = _data->currentScanLine - numScanLines + 1;
+
+ int numTasks = max (min ((int)_data->lineBuffers.size(),
+ first - last + 1),
+ 1);
+
+ for (int i = 0; i < numTasks; i++)
+ {
+ ThreadPool::addGlobalTask
+ (new LineBufferTask (&taskGroup, _data, first - i,
+ scanLineMin, scanLineMax));
+ }
+
+ nextCompressBuffer = first - numTasks;
+ stop = last - 1;
+ step = -1;
+ }
+
+ while (true)
+ {
+ if (_data->missingScanLines <= 0)
+ {
+ throw Iex::ArgExc ("Tried to write more scan lines "
+ "than specified by the data window.");
+ }
+
+ //
+ // Wait until the next line buffer is ready to be written
+ //
+
+ LineBuffer *writeBuffer =
+ _data->getLineBuffer (nextWriteBuffer);
+
+ writeBuffer->wait();
+
+ int numLines = writeBuffer->scanLineMax -
+ writeBuffer->scanLineMin + 1;
+
+ _data->missingScanLines -= numLines;
+
+ //
+ // If the line buffer is only partially full, then it is
+ // not complete and we cannot write it to disk yet.
+ //
+
+ if (writeBuffer->partiallyFull)
+ {
+ _data->currentScanLine = _data->currentScanLine +
+ step * numLines;
+ writeBuffer->post();
+
+ return;
+ }
+
+ //
+ // Write the line buffer
+ //
+
+ writePixelData (_data, writeBuffer);
+ nextWriteBuffer += step;
+
+ _data->currentScanLine = _data->currentScanLine +
+ step * numLines;
+
+ #ifdef DEBUG
+
+ assert (_data->currentScanLine ==
+ ((_data->lineOrder == INCREASING_Y) ?
+ writeBuffer->scanLineMax + 1:
+ writeBuffer->scanLineMin - 1));
+
+ #endif
+
+ //
+ // Release the lock on the line buffer
+ //
+
+ writeBuffer->post();
+
+ //
+ // If this was the last line buffer in the scanline range
+ //
+
+ if (nextWriteBuffer == stop)
+ break;
+
+ //
+ // If there are no more line buffers to compress,
+ // then only continue to write out remaining lineBuffers
+ //
+
+ if (nextCompressBuffer == stop)
+ continue;
+
+ //
+ // Add nextCompressBuffer as a compression task
+ //
+
+ ThreadPool::addGlobalTask
+ (new LineBufferTask (&taskGroup, _data, nextCompressBuffer,
+ scanLineMin, scanLineMax));
+
+ //
+ // Update the next line buffer we need to compress
+ //
+
+ nextCompressBuffer += step;
+ }
+
+ //
+ // Finish all tasks
+ //
+ }
+
+ //
+ // Exeption handling:
+ //
+ // LineBufferTask::execute() may have encountered exceptions, but
+ // those exceptions occurred in another thread, not in the thread
+ // that is executing this call to OutputFile::writePixels().
+ // LineBufferTask::execute() has caught all exceptions and stored
+ // the exceptions' what() strings in the line buffers.
+ // Now we check if any line buffer contains a stored exception; if
+ // this is the case then we re-throw the exception in this thread.
+ // (It is possible that multiple line buffers contain stored
+ // exceptions. We re-throw the first exception we find and
+ // ignore all others.)
+ //
+
+ const string *exception = 0;
+
+ for (int i = 0; i < _data->lineBuffers.size(); ++i)
+ {
+ LineBuffer *lineBuffer = _data->lineBuffers[i];
+
+ if (lineBuffer->hasException && !exception)
+ exception = &lineBuffer->exception;
+
+ lineBuffer->hasException = false;
+ }
+
+ if (exception)
+ throw Iex::IoExc (*exception);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Failed to write pixel data to image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+int
+OutputFile::currentScanLine () const
+{
+ Lock lock (*_data);
+ return _data->currentScanLine;
+}
+
+
+void
+OutputFile::copyPixels (InputFile &in)
+{
+ Lock lock (*_data);
+
+ //
+ // Check if this file's and and the InputFile's
+ // headers are compatible.
+ //
+
+ const Header &hdr = _data->header;
+ const Header &inHdr = in.header();
+
+ if (inHdr.find("tiles") != inHdr.end())
+ THROW (Iex::ArgExc, "Cannot copy pixels from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\". "
+ "The input file is tiled, but the output file is "
+ "not. Try using TiledOutputFile::copyPixels "
+ "instead.");
+
+ if (!(hdr.dataWindow() == inHdr.dataWindow()))
+ THROW (Iex::ArgExc, "Cannot copy pixels from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\". "
+ "The files have different data windows.");
+
+ if (!(hdr.lineOrder() == inHdr.lineOrder()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files have different line orders.");
+
+ if (!(hdr.compression() == inHdr.compression()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files use different compression methods.");
+
+ if (!(hdr.channels() == inHdr.channels()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files have different channel lists.");
+
+ //
+ // Verify that no pixel data have been written to this file yet.
+ //
+
+ const Box2i &dataWindow = hdr.dataWindow();
+
+ if (_data->missingScanLines != dataWindow.max.y - dataWindow.min.y + 1)
+ THROW (Iex::LogicExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "\"" << fileName() << "\" already contains "
+ "pixel data.");
+
+ //
+ // Copy the pixel data.
+ //
+
+ while (_data->missingScanLines > 0)
+ {
+ const char *pixelData;
+ int pixelDataSize;
+
+ in.rawPixelData (_data->currentScanLine, pixelData, pixelDataSize);
+
+ writePixelData (_data, lineBufferMinY (_data->currentScanLine,
+ _data->minY,
+ _data->linesInBuffer),
+ pixelData, pixelDataSize);
+
+ _data->currentScanLine += (_data->lineOrder == INCREASING_Y)?
+ _data->linesInBuffer: -_data->linesInBuffer;
+
+ _data->missingScanLines -= _data->linesInBuffer;
+ }
+}
+
+
+void
+OutputFile::updatePreviewImage (const PreviewRgba newPixels[])
+{
+ Lock lock (*_data);
+
+ if (_data->previewPosition <= 0)
+ THROW (Iex::LogicExc, "Cannot update preview image pixels. "
+ "File \"" << fileName() << "\" does not "
+ "contain a preview image.");
+
+ //
+ // Store the new pixels in the header's preview image attribute.
+ //
+
+ PreviewImageAttribute &pia =
+ _data->header.typedAttribute <PreviewImageAttribute> ("preview");
+
+ PreviewImage &pi = pia.value();
+ PreviewRgba *pixels = pi.pixels();
+ int numPixels = pi.width() * pi.height();
+
+ for (int i = 0; i < numPixels; ++i)
+ pixels[i] = newPixels[i];
+
+ //
+ // Save the current file position, jump to the position in
+ // the file where the preview image starts, store the new
+ // preview image, and jump back to the saved file position.
+ //
+
+ Int64 savedPosition = _data->os->tellp();
+
+ try
+ {
+ _data->os->seekp (_data->previewPosition);
+ pia.writeValueTo (*_data->os, _data->version);
+ _data->os->seekp (savedPosition);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Cannot update preview image pixels for "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+OutputFile::breakScanLine (int y, int offset, int length, char c)
+{
+ Lock lock (*_data);
+
+ Int64 position =
+ _data->lineOffsets[(y - _data->minY) / _data->linesInBuffer];
+
+ if (!position)
+ THROW (Iex::ArgExc, "Cannot overwrite scan line " << y << ". "
+ "The scan line has not yet been stored in "
+ "file \"" << fileName() << "\".");
+
+ _data->currentPosition = 0;
+ _data->os->seekp (position + offset);
+
+ for (int i = 0; i < length; ++i)
+ _data->os->write (&c, 1);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfOutputFile.h b/Source/OpenEXR/IlmImf/ImfOutputFile.h
new file mode 100644
index 0000000..bdc317a
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfOutputFile.h
@@ -0,0 +1,241 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_OUTPUT_FILE_H
+#define INCLUDED_IMF_OUTPUT_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// class OutputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+class InputFile;
+struct PreviewRgba;
+
+
+class OutputFile
+{
+ public:
+
+ //-----------------------------------------------------------
+ // Constructor -- opens the file and writes the file header.
+ // The file header is also copied into the OutputFile object,
+ // and can later be accessed via the header() method.
+ // Destroying this OutputFile object automatically closes
+ // the file.
+ //
+ // numThreads determines the number of threads that will be
+ // used to write the file (see ImfThreading.h).
+ //-----------------------------------------------------------
+
+ OutputFile (const char fileName[], const Header &header,
+ int numThreads = globalThreadCount());
+
+
+ //------------------------------------------------------------
+ // Constructor -- attaches the new OutputFile object to a file
+ // that has already been opened, and writes the file header.
+ // The file header is also copied into the OutputFile object,
+ // and can later be accessed via the header() method.
+ // Destroying this OutputFile object does not automatically
+ // close the file.
+ //
+ // numThreads determines the number of threads that will be
+ // used to write the file (see ImfThreading.h).
+ //------------------------------------------------------------
+
+ OutputFile (OStream &os, const Header &header,
+ int numThreads = globalThreadCount());
+
+
+ //-------------------------------------------------
+ // Destructor
+ //
+ // Destroying the OutputFile object before writing
+ // all scan lines within the data window results in
+ // an incomplete file.
+ //-------------------------------------------------
+
+ virtual ~OutputFile ();
+
+
+ //------------------------
+ // Access to the file name
+ //------------------------
+
+ const char * fileName () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+
+
+ //-------------------------------------------------------
+ // Set the current frame buffer -- copies the FrameBuffer
+ // object into the OutputFile object.
+ //
+ // The current frame buffer is the source of the pixel
+ // data written to the file. The current frame buffer
+ // must be set at least once before writePixels() is
+ // called. The current frame buffer can be changed
+ // after each call to writePixels.
+ //-------------------------------------------------------
+
+ void setFrameBuffer (const FrameBuffer &frameBuffer);
+
+
+ //-----------------------------------
+ // Access to the current frame buffer
+ //-----------------------------------
+
+ const FrameBuffer & frameBuffer () const;
+
+
+ //-------------------------------------------------------------------
+ // Write pixel data:
+ //
+ // writePixels(n) retrieves the next n scan lines worth of data from
+ // the current frame buffer, starting with the scan line indicated by
+ // currentScanLine(), and stores the data in the output file, and
+ // progressing in the direction indicated by header.lineOrder().
+ //
+ // To produce a complete and correct file, exactly m scan lines must
+ // be written, where m is equal to
+ // header().dataWindow().max.y - header().dataWindow().min.y + 1.
+ //-------------------------------------------------------------------
+
+ void writePixels (int numScanLines = 1);
+
+
+ //------------------------------------------------------------------
+ // Access to the current scan line:
+ //
+ // currentScanLine() returns the y coordinate of the first scan line
+ // that will be read from the current frame buffer during the next
+ // call to writePixels().
+ //
+ // If header.lineOrder() == INCREASING_Y:
+ //
+ // The current scan line before the first call to writePixels()
+ // is header().dataWindow().min.y. After writing each scan line,
+ // the current scan line is incremented by 1.
+ //
+ // If header.lineOrder() == DECREASING_Y:
+ //
+ // The current scan line before the first call to writePixels()
+ // is header().dataWindow().max.y. After writing each scan line,
+ // the current scan line is decremented by 1.
+ //
+ //------------------------------------------------------------------
+
+ int currentScanLine () const;
+
+
+ //--------------------------------------------------------------
+ // Shortcut to copy all pixels from an InputFile into this file,
+ // without uncompressing and then recompressing the pixel data.
+ // This file's header must be compatible with the InputFile's
+ // header: The two header's "dataWindow", "compression",
+ // "lineOrder" and "channels" attributes must be the same.
+ //--------------------------------------------------------------
+
+ void copyPixels (InputFile &in);
+
+
+ //--------------------------------------------------------------
+ // Updating the preview image:
+ //
+ // updatePreviewImage() supplies a new set of pixels for the
+ // preview image attribute in the file's header. If the header
+ // does not contain a preview image, updatePreviewImage() throws
+ // an Iex::LogicExc.
+ //
+ // Note: updatePreviewImage() is necessary because images are
+ // often stored in a file incrementally, a few scan lines at a
+ // time, while the image is being generated. Since the preview
+ // image is an attribute in the file's header, it gets stored in
+ // the file as soon as the file is opened, but we may not know
+ // what the preview image should look like until we have written
+ // the last scan line of the main image.
+ //
+ //--------------------------------------------------------------
+
+ void updatePreviewImage (const PreviewRgba newPixels[]);
+
+
+ //---------------------------------------------------------
+ // Break a scan line -- for testing and debugging only:
+ //
+ // breakScanLine(y,p,n,c) introduces an error into the
+ // output file by writing n copies of character c, starting
+ // p bytes from the beginning of the pixel data block that
+ // contains scan line y.
+ //
+ // Warning: Calling this function usually results in a
+ // broken image file. The file or parts of it may not
+ // be readable, or the file may contain bad data.
+ //
+ //---------------------------------------------------------
+
+ void breakScanLine (int y, int offset, int length, char c);
+
+
+ struct Data;
+
+ private:
+
+ OutputFile (const OutputFile &); // not implemented
+ OutputFile & operator = (const OutputFile &); // not implemented
+
+ void initialize (const Header &header);
+
+ Data * _data;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfPixelType.h b/Source/OpenEXR/IlmImf/ImfPixelType.h
new file mode 100644
index 0000000..8f504ef
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPixelType.h
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_PIXEL_TYPE_H
+#define INCLUDED_IMF_PIXEL_TYPE_H
+
+//-----------------------------------------------------------------------------
+//
+// enum PixelType
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+enum PixelType
+{
+ UINT = 0, // unsigned int (32 bit)
+ HALF = 1, // half (16 bit floating point)
+ FLOAT = 2, // float (32 bit floating point)
+
+ NUM_PIXELTYPES // number of different pixel types
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfPizCompressor.cpp b/Source/OpenEXR/IlmImf/ImfPizCompressor.cpp
new file mode 100644
index 0000000..7c84919
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPizCompressor.cpp
@@ -0,0 +1,656 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class PizCompressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfPizCompressor.h>
+#include <ImfHeader.h>
+#include <ImfChannelList.h>
+#include <ImfHuf.h>
+#include <ImfWav.h>
+#include <ImfMisc.h>
+#include <ImathFun.h>
+#include <ImathBox.h>
+#include <Iex.h>
+#include <ImfIO.h>
+#include <ImfXdr.h>
+#include <ImfAutoArray.h>
+#include <string.h>
+#include <assert.h>
+
+namespace Imf {
+
+using Imath::divp;
+using Imath::modp;
+using Imath::Box2i;
+using Imath::V2i;
+using Iex::InputExc;
+
+namespace {
+
+//
+// Functions to compress the range of values in the pixel data
+//
+
+const int USHORT_RANGE = (1 << 16);
+const int BITMAP_SIZE = (USHORT_RANGE >> 3);
+
+void
+bitmapFromData (const unsigned short data[/*nData*/],
+ int nData,
+ unsigned char bitmap[BITMAP_SIZE],
+ unsigned short &minNonZero,
+ unsigned short &maxNonZero)
+{
+ for (int i = 0; i < BITMAP_SIZE; ++i)
+ bitmap[i] = 0;
+
+ for (int i = 0; i < nData; ++i)
+ bitmap[data[i] >> 3] |= (1 << (data[i] & 7));
+
+ bitmap[0] &= ~1; // zero is not explicitly stored in
+ // the bitmap; we assume that the
+ // data always contain zeroes
+ minNonZero = BITMAP_SIZE - 1;
+ maxNonZero = 0;
+
+ for (int i = 0; i < BITMAP_SIZE; ++i)
+ {
+ if (bitmap[i])
+ {
+ if (minNonZero > i)
+ minNonZero = i;
+ if (maxNonZero < i)
+ maxNonZero = i;
+ }
+ }
+}
+
+
+unsigned short
+forwardLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE],
+ unsigned short lut[USHORT_RANGE])
+{
+ int k = 0;
+
+ for (int i = 0; i < USHORT_RANGE; ++i)
+ {
+ if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))))
+ lut[i] = k++;
+ else
+ lut[i] = 0;
+ }
+
+ return k - 1; // maximum value stored in lut[],
+} // i.e. number of ones in bitmap minus 1
+
+
+unsigned short
+reverseLutFromBitmap (const unsigned char bitmap[BITMAP_SIZE],
+ unsigned short lut[USHORT_RANGE])
+{
+ int k = 0;
+
+ for (int i = 0; i < USHORT_RANGE; ++i)
+ {
+ if ((i == 0) || (bitmap[i >> 3] & (1 << (i & 7))))
+ lut[k++] = i;
+ }
+
+ int n = k - 1;
+
+ while (k < USHORT_RANGE)
+ lut[k++] = 0;
+
+ return n; // maximum k where lut[k] is non-zero,
+} // i.e. number of ones in bitmap minus 1
+
+
+void
+applyLut (const unsigned short lut[USHORT_RANGE],
+ unsigned short data[/*nData*/],
+ int nData)
+{
+ for (int i = 0; i < nData; ++i)
+ data[i] = lut[data[i]];
+}
+
+
+} // namespace
+
+
+struct PizCompressor::ChannelData
+{
+ unsigned short * start;
+ unsigned short * end;
+ int nx;
+ int ny;
+ int ys;
+ int size;
+};
+
+
+PizCompressor::PizCompressor
+ (const Header &hdr,
+ int maxScanLineSize,
+ int numScanLines)
+:
+ Compressor (hdr),
+ _maxScanLineSize (maxScanLineSize),
+ _format (XDR),
+ _numScanLines (numScanLines),
+ _tmpBuffer (0),
+ _outBuffer (0),
+ _numChans (0),
+ _channels (hdr.channels()),
+ _channelData (0)
+{
+ _tmpBuffer = new unsigned short [maxScanLineSize * numScanLines / 2];
+ _outBuffer = new char [maxScanLineSize * numScanLines + 65536 + 8192];
+
+ const ChannelList &channels = header().channels();
+ bool onlyHalfChannels = true;
+
+ for (ChannelList::ConstIterator c = channels.begin();
+ c != channels.end();
+ ++c)
+ {
+ _numChans++;
+
+ assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);
+
+ if (c.channel().type != HALF)
+ onlyHalfChannels = false;
+ }
+
+ _channelData = new ChannelData[_numChans];
+
+ const Box2i &dataWindow = hdr.dataWindow();
+
+ _minX = dataWindow.min.x;
+ _maxX = dataWindow.max.x;
+ _maxY = dataWindow.max.y;
+
+ //
+ // We can support uncompressed data in the machine's native format
+ // if all image channels are of type HALF, and if the Xdr and the
+ // native represenations of a half have the same size.
+ //
+
+ if (onlyHalfChannels && (sizeof (half) == pixelTypeSize (HALF)))
+ _format = NATIVE;
+}
+
+
+PizCompressor::~PizCompressor ()
+{
+ delete [] _tmpBuffer;
+ delete [] _outBuffer;
+ delete [] _channelData;
+}
+
+
+int
+PizCompressor::numScanLines () const
+{
+ return _numScanLines;
+}
+
+
+Compressor::Format
+PizCompressor::format () const
+{
+ return _format;
+}
+
+
+int
+PizCompressor::compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return compress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + numScanLines() - 1)),
+ outPtr);
+}
+
+
+int
+PizCompressor::compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ return compress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+PizCompressor::uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return uncompress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + numScanLines() - 1)),
+ outPtr);
+}
+
+
+int
+PizCompressor::uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ return uncompress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+PizCompressor::compress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ //
+ // This is the compress function which is used by both the tiled and
+ // scanline compression routines.
+ //
+
+ //
+ // Special case ­- empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Rearrange the pixel data so that the wavelet
+ // and Huffman encoders can process them easily.
+ //
+ // The wavelet and Huffman encoders both handle only
+ // 16-bit data, so 32-bit data must be split into smaller
+ // pieces. We treat each 32-bit channel (UINT, FLOAT) as
+ // two interleaved 16-bit channels.
+ //
+
+ int minX = range.min.x;
+ int maxX = range.max.x;
+ int minY = range.min.y;
+ int maxY = range.max.y;
+
+ if (maxY > _maxY)
+ maxY = _maxY;
+
+ if (maxX > _maxX)
+ maxX = _maxX;
+
+ unsigned short *tmpBufferEnd = _tmpBuffer;
+ int i = 0;
+
+ for (ChannelList::ConstIterator c = _channels.begin();
+ c != _channels.end();
+ ++c, ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ cd.start = tmpBufferEnd;
+ cd.end = cd.start;
+
+ cd.nx = numSamples (c.channel().xSampling, minX, maxX);
+ cd.ny = numSamples (c.channel().ySampling, minY, maxY);
+ cd.ys = c.channel().ySampling;
+
+ cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
+
+ tmpBufferEnd += cd.nx * cd.ny * cd.size;
+ }
+
+ if (_format == XDR)
+ {
+ //
+ // Machine-independent (Xdr) data format
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ for (int x = cd.nx * cd.size; x > 0; --x)
+ {
+ Xdr::read <CharPtrIO> (inPtr, *cd.end);
+ ++cd.end;
+ }
+ }
+ }
+ }
+ else
+ {
+ //
+ // Native, machine-dependent data format
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ int n = cd.nx * cd.size;
+ memcpy (cd.end, inPtr, n * sizeof (unsigned short));
+ inPtr += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+
+ #if defined (DEBUG)
+
+ for (int i = 1; i < _numChans; ++i)
+ assert (_channelData[i-1].end == _channelData[i].start);
+
+ assert (_channelData[_numChans-1].end == tmpBufferEnd);
+
+ #endif
+
+ //
+ // Compress the range of the pixel data
+ //
+
+ AutoArray <unsigned char, BITMAP_SIZE> bitmap;
+ unsigned short minNonZero;
+ unsigned short maxNonZero;
+
+ bitmapFromData (_tmpBuffer,
+ tmpBufferEnd - _tmpBuffer,
+ bitmap,
+ minNonZero, maxNonZero);
+
+ AutoArray <unsigned short, USHORT_RANGE> lut;
+ unsigned short maxValue = forwardLutFromBitmap (bitmap, lut);
+ applyLut (lut, _tmpBuffer, tmpBufferEnd - _tmpBuffer);
+
+ //
+ // Store range compression info in _outBuffer
+ //
+
+ char *buf = _outBuffer;
+
+ Xdr::write <CharPtrIO> (buf, minNonZero);
+ Xdr::write <CharPtrIO> (buf, maxNonZero);
+
+ if (minNonZero <= maxNonZero)
+ {
+ Xdr::write <CharPtrIO> (buf, (char *) &bitmap[0] + minNonZero,
+ maxNonZero - minNonZero + 1);
+ }
+
+ //
+ // Apply wavelet encoding
+ //
+
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ for (int j = 0; j < cd.size; ++j)
+ {
+ wav2Encode (cd.start + j,
+ cd.nx, cd.size,
+ cd.ny, cd.nx * cd.size,
+ maxValue);
+ }
+ }
+
+ //
+ // Apply Huffman encoding; append the result to _outBuffer
+ //
+
+ char *lengthPtr = buf;
+ Xdr::write <CharPtrIO> (buf, int(0));
+
+ int length = hufCompress (_tmpBuffer, tmpBufferEnd - _tmpBuffer, buf);
+ Xdr::write <CharPtrIO> (lengthPtr, length);
+
+ outPtr = _outBuffer;
+ return buf - _outBuffer + length;
+}
+
+
+int
+PizCompressor::uncompress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr)
+{
+ //
+ // This is the cunompress function which is used by both the tiled and
+ // scanline decompression routines.
+ //
+
+ //
+ // Special case - empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Determine the layout of the compressed pixel data
+ //
+
+ int minX = range.min.x;
+ int maxX = range.max.x;
+ int minY = range.min.y;
+ int maxY = range.max.y;
+
+ if (maxY > _maxY)
+ maxY = _maxY;
+
+ if (maxX > _maxX)
+ maxX = _maxX;
+
+ unsigned short *tmpBufferEnd = _tmpBuffer;
+ int i = 0;
+
+ for (ChannelList::ConstIterator c = _channels.begin();
+ c != _channels.end();
+ ++c, ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ cd.start = tmpBufferEnd;
+ cd.end = cd.start;
+
+ cd.nx = numSamples (c.channel().xSampling, minX, maxX);
+ cd.ny = numSamples (c.channel().ySampling, minY, maxY);
+ cd.ys = c.channel().ySampling;
+
+ cd.size = pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
+
+ tmpBufferEnd += cd.nx * cd.ny * cd.size;
+ }
+
+ //
+ // Read range compression data
+ //
+
+ unsigned short minNonZero;
+ unsigned short maxNonZero;
+
+ AutoArray <unsigned char, BITMAP_SIZE> bitmap;
+ memset (bitmap, 0, sizeof (unsigned char) * BITMAP_SIZE);
+
+ Xdr::read <CharPtrIO> (inPtr, minNonZero);
+ Xdr::read <CharPtrIO> (inPtr, maxNonZero);
+
+ if (maxNonZero >= BITMAP_SIZE)
+ {
+ throw InputExc ("Error in header for PIZ-compressed data "
+ "(invalid bitmap size).");
+ }
+
+ if (minNonZero <= maxNonZero)
+ {
+ Xdr::read <CharPtrIO> (inPtr, (char *) &bitmap[0] + minNonZero,
+ maxNonZero - minNonZero + 1);
+ }
+
+ AutoArray <unsigned short, USHORT_RANGE> lut;
+ unsigned short maxValue = reverseLutFromBitmap (bitmap, lut);
+
+ //
+ // Huffman decoding
+ //
+
+ int length;
+ Xdr::read <CharPtrIO> (inPtr, length);
+
+ hufUncompress (inPtr, length, _tmpBuffer, tmpBufferEnd - _tmpBuffer);
+
+ //
+ // Wavelet decoding
+ //
+
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ for (int j = 0; j < cd.size; ++j)
+ {
+ wav2Decode (cd.start + j,
+ cd.nx, cd.size,
+ cd.ny, cd.nx * cd.size,
+ maxValue);
+ }
+ }
+
+ //
+ // Expand the pixel data to their original range
+ //
+
+ applyLut (lut, _tmpBuffer, tmpBufferEnd - _tmpBuffer);
+
+ //
+ // Rearrange the pixel data into the format expected by the caller.
+ //
+
+ char *outEnd = _outBuffer;
+
+ if (_format == XDR)
+ {
+ //
+ // Machine-independent (Xdr) data format
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ for (int x = cd.nx * cd.size; x > 0; --x)
+ {
+ Xdr::write <CharPtrIO> (outEnd, *cd.end);
+ ++cd.end;
+ }
+ }
+ }
+ }
+ else
+ {
+ //
+ // Native, machine-dependent data format
+ //
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (int i = 0; i < _numChans; ++i)
+ {
+ ChannelData &cd = _channelData[i];
+
+ if (modp (y, cd.ys) != 0)
+ continue;
+
+ int n = cd.nx * cd.size;
+ memcpy (outEnd, cd.end, n * sizeof (unsigned short));
+ outEnd += n * sizeof (unsigned short);
+ cd.end += n;
+ }
+ }
+ }
+
+ #if defined (DEBUG)
+
+ for (int i = 1; i < _numChans; ++i)
+ assert (_channelData[i-1].end == _channelData[i].start);
+
+ assert (_channelData[_numChans-1].end == tmpBufferEnd);
+
+ #endif
+
+ outPtr = _outBuffer;
+ return outEnd - _outBuffer;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfPizCompressor.h b/Source/OpenEXR/IlmImf/ImfPizCompressor.h
new file mode 100644
index 0000000..f9ac7f4
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPizCompressor.h
@@ -0,0 +1,112 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_PIZ_COMPRESSOR_H
+#define INCLUDED_IMF_PIZ_COMPRESSOR_H
+
+//-----------------------------------------------------------------------------
+//
+// class PizCompressor -- uses Wavelet and Huffman encoding.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+class ChannelList;
+
+
+class PizCompressor: public Compressor
+{
+ public:
+
+ PizCompressor (const Header &hdr, int maxScanLineSize, int numScanLines);
+ virtual ~PizCompressor ();
+
+ virtual int numScanLines () const;
+
+ virtual Format format () const;
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+ private:
+
+ struct ChannelData;
+
+ int compress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int uncompress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int _maxScanLineSize;
+ Format _format;
+ int _numScanLines;
+ unsigned short * _tmpBuffer;
+ char * _outBuffer;
+ int _numChans;
+ const ChannelList & _channels;
+ ChannelData * _channelData;
+ int _minX;
+ int _maxX;
+ int _maxY;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfPreviewImage.cpp b/Source/OpenEXR/IlmImf/ImfPreviewImage.cpp
new file mode 100644
index 0000000..dae5227
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPreviewImage.cpp
@@ -0,0 +1,101 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class PreviewImage
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfPreviewImage.h>
+#include "Iex.h"
+
+namespace Imf {
+
+
+PreviewImage::PreviewImage (unsigned int width,
+ unsigned int height,
+ const PreviewRgba pixels[])
+{
+ _width = width;
+ _height = height;
+ _pixels = new PreviewRgba [_width * _height];
+
+ if (pixels)
+ {
+ for (unsigned int i = 0; i < _width * _height; ++i)
+ _pixels[i] = pixels[i];
+ }
+ else
+ {
+ for (unsigned int i = 0; i < _width * _height; ++i)
+ _pixels[i] = PreviewRgba();
+ }
+}
+
+
+PreviewImage::PreviewImage (const PreviewImage &other):
+ _width (other._width),
+ _height (other._height),
+ _pixels (new PreviewRgba [other._width * other._height])
+{
+ for (unsigned int i = 0; i < _width * _height; ++i)
+ _pixels[i] = other._pixels[i];
+}
+
+
+PreviewImage::~PreviewImage ()
+{
+ delete [] _pixels;
+}
+
+
+PreviewImage &
+PreviewImage::operator = (const PreviewImage &other)
+{
+ delete [] _pixels;
+
+ _width = other._width;
+ _height = other._height;
+ _pixels = new PreviewRgba [other._width * other._height];
+
+ for (unsigned int i = 0; i < _width * _height; ++i)
+ _pixels[i] = other._pixels[i];
+
+ return *this;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfPreviewImage.h b/Source/OpenEXR/IlmImf/ImfPreviewImage.h
new file mode 100644
index 0000000..d016620
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPreviewImage.h
@@ -0,0 +1,131 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_PREVIEW_IMAGE_H
+#define INCLUDED_IMF_PREVIEW_IMAGE_H
+
+//-----------------------------------------------------------------------------
+//
+// class PreviewImage -- a usually small, low-dynamic range image,
+// that is intended to be stored in an image file's header.
+//
+// struct PreviewRgba -- holds the value of a PreviewImage pixel.
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+struct PreviewRgba
+{
+ unsigned char r; // Red, green and blue components of
+ unsigned char g; // the pixel's color; intensity is
+ unsigned char b; // proportional to pow (x/255, 2.2),
+ // where x is r, g, or b.
+
+ unsigned char a; // The pixel's alpha; 0 == transparent,
+ // 255 == opaque.
+
+ PreviewRgba (unsigned char r = 0,
+ unsigned char g = 0,
+ unsigned char b = 0,
+ unsigned char a = 255)
+ : r(r), g(g), b(b), a(a) {}
+};
+
+
+class PreviewImage
+{
+ public:
+
+ //--------------------------------------------------------------------
+ // Constructor:
+ //
+ // PreviewImage(w,h,p) constructs a preview image with w by h pixels
+ // whose initial values are specified in pixel array p. The x and y
+ // coordinates of the pixels in p go from 0 to w-1, and from 0 to h-1.
+ // The pixel with coordinates (x, y) is at address p + y*w + x.
+ // Pixel (0, 0) is in the upper left corner of the preview image.
+ // If p is zero, the pixels in the preview image are initialized with
+ // (r = 0, b = 0, g = 0, a = 255).
+ //
+ //--------------------------------------------------------------------
+
+ PreviewImage (unsigned int width = 0,
+ unsigned int height = 0,
+ const PreviewRgba pixels[] = 0);
+
+ //-----------------------------------------------------
+ // Copy constructor, destructor and assignment operator
+ //-----------------------------------------------------
+
+ PreviewImage (const PreviewImage &other);
+ ~PreviewImage ();
+
+ PreviewImage & operator = (const PreviewImage &other);
+
+
+ //-----------------------------------------------
+ // Access to width, height and to the pixel array
+ //-----------------------------------------------
+
+ unsigned int width () const {return _width;}
+ unsigned int height () const {return _height;}
+
+ PreviewRgba * pixels () {return _pixels;}
+ const PreviewRgba * pixels () const {return _pixels;}
+
+
+ //----------------------------
+ // Access to individual pixels
+ //----------------------------
+
+ PreviewRgba & pixel (unsigned int x, unsigned int y)
+ {return _pixels[y * _width + x];}
+
+ const PreviewRgba & pixel (unsigned int x, unsigned int y) const
+ {return _pixels[y * _width + x];}
+
+ private:
+
+ unsigned int _width;
+ unsigned int _height;
+ PreviewRgba * _pixels;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.cpp b/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.cpp
new file mode 100644
index 0000000..476c756
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.cpp
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class PreviewImageAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfPreviewImageAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+PreviewImageAttribute::staticTypeName ()
+{
+ return "preview";
+}
+
+
+template <>
+void
+PreviewImageAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.width());
+ Xdr::write <StreamIO> (os, _value.height());
+
+ int numPixels = _value.width() * _value.height();
+ const PreviewRgba *pixels = _value.pixels();
+
+ for (int i = 0; i < numPixels; ++i)
+ {
+ Xdr::write <StreamIO> (os, pixels[i].r);
+ Xdr::write <StreamIO> (os, pixels[i].g);
+ Xdr::write <StreamIO> (os, pixels[i].b);
+ Xdr::write <StreamIO> (os, pixels[i].a);
+ }
+}
+
+
+template <>
+void
+PreviewImageAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ int width, height;
+
+ Xdr::read <StreamIO> (is, width);
+ Xdr::read <StreamIO> (is, height);
+
+ PreviewImage p (width, height);
+
+ int numPixels = p.width() * p.height();
+ PreviewRgba *pixels = p.pixels();
+
+ for (int i = 0; i < numPixels; ++i)
+ {
+ Xdr::read <StreamIO> (is, pixels[i].r);
+ Xdr::read <StreamIO> (is, pixels[i].g);
+ Xdr::read <StreamIO> (is, pixels[i].b);
+ Xdr::read <StreamIO> (is, pixels[i].a);
+ }
+
+ _value = p;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.h b/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.h
new file mode 100644
index 0000000..f08b9b7
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPreviewImageAttribute.h
@@ -0,0 +1,71 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_PREVIEW_IMAGE_ATTRIBUTE_H
+#define INCLUDED_IMF_PREVIEW_IMAGE_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class PreviewImageAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfPreviewImage.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<PreviewImage> PreviewImageAttribute;
+
+template <>
+const char *PreviewImageAttribute::staticTypeName ();
+
+template <>
+void PreviewImageAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void PreviewImageAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfPreviewImageAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfPxr24Compressor.cpp b/Source/OpenEXR/IlmImf/ImfPxr24Compressor.cpp
new file mode 100644
index 0000000..a8edaad
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPxr24Compressor.cpp
@@ -0,0 +1,542 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Pixar Animation Studios
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Pixar Animation Studios nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Pxr24Compressor
+//
+// This compressor is based on source code that was contributed to
+// OpenEXR by Pixar Animation Studios. The compression method was
+// developed by Loren Carpenter.
+//
+// The compressor preprocesses the pixel data to reduce entropy,
+// and then calls zlib.
+//
+// Compression of HALF and UINT channels is lossless, but compressing
+// FLOAT channels is lossy: 32-bit floating-point numbers are converted
+// to 24 bits by rounding the significand to 15 bits.
+//
+// When the compressor is invoked, the caller has already arranged
+// the pixel data so that the values for each channel appear in a
+// contiguous block of memory. The compressor converts the pixel
+// values to unsigned integers: For UINT, this is a no-op. HALF
+// values are simply re-interpreted as 16-bit integers. FLOAT
+// values are converted to 24 bits, and the resulting bit patterns
+// are interpreted as integers. The compressor then replaces each
+// value with the difference between the value and its left neighbor.
+// This turns flat fields in the image into zeroes, and ramps into
+// strings of similar values. Next, each difference is split into
+// 2, 3 or 4 bytes, and the bytes are transposed so that all the
+// most significant bytes end up in a contiguous block, followed
+// by the second most significant bytes, and so on. The resulting
+// string of bytes is compressed with zlib.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfPxr24Compressor.h>
+#include <ImfHeader.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImathFun.h>
+#include <Iex.h>
+#include <half.h>
+#include <zlib.h>
+#include <assert.h>
+#include <algorithm>
+
+using namespace std;
+using namespace Imath;
+
+namespace Imf {
+namespace {
+
+//
+// Conversion from 32-bit to 24-bit floating-point numbers.
+// Conversion back to 32 bits is simply an 8-bit shift to the left.
+//
+
+inline unsigned int
+floatToFloat24 (float f)
+{
+ union
+ {
+ float f;
+ unsigned int i;
+ } u;
+
+ u.f = f;
+
+ //
+ // Disassemble the 32-bit floating point number, f,
+ // into sign, s, exponent, e, and significand, m.
+ //
+
+ unsigned int s = u.i & 0x80000000;
+ unsigned int e = u.i & 0x7f800000;
+ unsigned int m = u.i & 0x007fffff;
+ unsigned int i;
+
+ if (e == 0x7f800000)
+ {
+ if (m)
+ {
+ //
+ // F is a NAN; we preserve the sign bit and
+ // the 15 leftmost bits of the significand,
+ // with one exception: If the 15 leftmost
+ // bits are all zero, the NAN would turn
+ // into an infinity, so we have to set at
+ // least one bit in the significand.
+ //
+
+ m >>= 8;
+ i = (e >> 8) | m | (m == 0);
+ }
+ else
+ {
+ //
+ // F is an infinity.
+ //
+
+ i = e >> 8;
+ }
+ }
+ else
+ {
+ //
+ // F is finite, round the significand to 15 bits.
+ //
+
+ i = ((e | m) + (m & 0x00000080)) >> 8;
+
+ if (i >= 0x7f8000)
+ {
+ //
+ // F was close to FLT_MAX, and the significand was
+ // rounded up, resulting in an exponent overflow.
+ // Avoid the overflow by truncating the significand
+ // instead of rounding it.
+ //
+
+ i = (e | m) >> 8;
+ }
+ }
+
+ return (s >> 8) | i;
+}
+
+
+void
+notEnoughData ()
+{
+ throw Iex::InputExc ("Error decompressing data "
+ "(input data are shorter than expected).");
+}
+
+
+void
+tooMuchData ()
+{
+ throw Iex::InputExc ("Error decompressing data "
+ "(input data are longer than expected).");
+}
+
+} // namespace
+
+
+Pxr24Compressor::Pxr24Compressor (const Header &hdr,
+ int maxScanLineSize,
+ int numScanLines)
+:
+ Compressor (hdr),
+ _maxScanLineSize (maxScanLineSize),
+ _numScanLines (numScanLines),
+ _tmpBuffer (0),
+ _outBuffer (0),
+ _channels (hdr.channels())
+{
+ int maxInBytes = maxScanLineSize * numScanLines;
+
+ _tmpBuffer = new unsigned char [maxInBytes];
+ _outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];
+
+ const Box2i &dataWindow = hdr.dataWindow();
+
+ _minX = dataWindow.min.x;
+ _maxX = dataWindow.max.x;
+ _maxY = dataWindow.max.y;
+}
+
+
+Pxr24Compressor::~Pxr24Compressor ()
+{
+ delete [] _tmpBuffer;
+ delete [] _outBuffer;
+}
+
+
+int
+Pxr24Compressor::numScanLines () const
+{
+ return _numScanLines;
+}
+
+
+Compressor::Format
+Pxr24Compressor::format () const
+{
+ return NATIVE;
+}
+
+
+int
+Pxr24Compressor::compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return compress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + _numScanLines - 1)),
+ outPtr);
+}
+
+
+int
+Pxr24Compressor::compressTile (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ return compress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+Pxr24Compressor::uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ return uncompress (inPtr,
+ inSize,
+ Box2i (V2i (_minX, minY),
+ V2i (_maxX, minY + _numScanLines - 1)),
+ outPtr);
+}
+
+
+int
+Pxr24Compressor::uncompressTile (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ return uncompress (inPtr, inSize, range, outPtr);
+}
+
+
+int
+Pxr24Compressor::compress (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ int minX = range.min.x;
+ int maxX = min (range.max.x, _maxX);
+ int minY = range.min.y;
+ int maxY = min (range.max.y, _maxY);
+
+ unsigned char *tmpBufferEnd = _tmpBuffer;
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (ChannelList::ConstIterator i = _channels.begin();
+ i != _channels.end();
+ ++i)
+ {
+ const Channel &c = i.channel();
+
+ if (modp (y, c.ySampling) != 0)
+ continue;
+
+ int n = numSamples (c.xSampling, minX, maxX);
+
+ unsigned char *ptr[4];
+ unsigned int previousPixel = 0;
+
+ switch (c.type)
+ {
+ case UINT:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ ptr[2] = ptr[1] + n;
+ ptr[3] = ptr[2] + n;
+ tmpBufferEnd = ptr[3] + n;
+
+ for (int j = 0; j < n; ++j)
+ {
+ unsigned int pixel;
+ char *pPtr = (char *) &pixel;
+
+ for (int k = 0; k < sizeof (pixel); ++k)
+ *pPtr++ = *inPtr++;
+
+ unsigned int diff = pixel - previousPixel;
+ previousPixel = pixel;
+
+ *(ptr[0]++) = diff >> 24;
+ *(ptr[1]++) = diff >> 16;
+ *(ptr[2]++) = diff >> 8;
+ *(ptr[3]++) = diff;
+ }
+
+ break;
+
+ case HALF:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ tmpBufferEnd = ptr[1] + n;
+
+ for (int j = 0; j < n; ++j)
+ {
+ half pixel;
+
+ pixel = *(const half *) inPtr;
+ inPtr += sizeof (half);
+
+ unsigned int diff = pixel.bits() - previousPixel;
+ previousPixel = pixel.bits();
+
+ *(ptr[0]++) = diff >> 8;
+ *(ptr[1]++) = diff;
+ }
+
+ break;
+
+ case FLOAT:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ ptr[2] = ptr[1] + n;
+ tmpBufferEnd = ptr[2] + n;
+
+ for (int j = 0; j < n; ++j)
+ {
+ float pixel;
+ char *pPtr = (char *) &pixel;
+
+ for (int k = 0; k < sizeof (pixel); ++k)
+ *pPtr++ = *inPtr++;
+
+ unsigned int pixel24 = floatToFloat24 (pixel);
+ unsigned int diff = pixel24 - previousPixel;
+ previousPixel = pixel24;
+
+ *(ptr[0]++) = diff >> 16;
+ *(ptr[1]++) = diff >> 8;
+ *(ptr[2]++) = diff;
+ }
+
+ break;
+
+ default:
+
+ assert (false);
+ }
+ }
+ }
+
+ uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
+
+ if (Z_OK != ::compress ((Bytef *) _outBuffer,
+ &outSize,
+ (const Bytef *) _tmpBuffer,
+ tmpBufferEnd - _tmpBuffer))
+ {
+ throw Iex::BaseExc ("Data compression (zlib) failed.");
+ }
+
+ outPtr = _outBuffer;
+ return outSize;
+}
+
+
+int
+Pxr24Compressor::uncompress (const char *inPtr,
+ int inSize,
+ Box2i range,
+ const char *&outPtr)
+{
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ uLongf tmpSize = _maxScanLineSize * _numScanLines;
+
+ if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
+ &tmpSize,
+ (const Bytef *) inPtr,
+ inSize))
+ {
+ throw Iex::InputExc ("Data decompression (zlib) failed.");
+ }
+
+ int minX = range.min.x;
+ int maxX = min (range.max.x, _maxX);
+ int minY = range.min.y;
+ int maxY = min (range.max.y, _maxY);
+
+ const unsigned char *tmpBufferEnd = _tmpBuffer;
+ char *writePtr = _outBuffer;
+
+ for (int y = minY; y <= maxY; ++y)
+ {
+ for (ChannelList::ConstIterator i = _channels.begin();
+ i != _channels.end();
+ ++i)
+ {
+ const Channel &c = i.channel();
+
+ if (modp (y, c.ySampling) != 0)
+ continue;
+
+ int n = numSamples (c.xSampling, minX, maxX);
+
+ const unsigned char *ptr[4];
+ unsigned int pixel = 0;
+
+ switch (c.type)
+ {
+ case UINT:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ ptr[2] = ptr[1] + n;
+ ptr[3] = ptr[2] + n;
+ tmpBufferEnd = ptr[3] + n;
+
+ if (tmpBufferEnd - _tmpBuffer > tmpSize)
+ notEnoughData();
+
+ for (int j = 0; j < n; ++j)
+ {
+ unsigned int diff = (*(ptr[0]++) << 24) |
+ (*(ptr[1]++) << 16) |
+ (*(ptr[2]++) << 8) |
+ *(ptr[3]++);
+
+ pixel += diff;
+
+ char *pPtr = (char *) &pixel;
+
+ for (int k = 0; k < sizeof (pixel); ++k)
+ *writePtr++ = *pPtr++;
+ }
+
+ break;
+
+ case HALF:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ tmpBufferEnd = ptr[1] + n;
+
+ if (tmpBufferEnd - _tmpBuffer > tmpSize)
+ notEnoughData();
+
+ for (int j = 0; j < n; ++j)
+ {
+ unsigned int diff = (*(ptr[0]++) << 8) |
+ *(ptr[1]++);
+
+ pixel += diff;
+
+ half * hPtr = (half *) writePtr;
+ hPtr->setBits ((unsigned short) pixel);
+ writePtr += sizeof (half);
+ }
+
+ break;
+
+ case FLOAT:
+
+ ptr[0] = tmpBufferEnd;
+ ptr[1] = ptr[0] + n;
+ ptr[2] = ptr[1] + n;
+ tmpBufferEnd = ptr[2] + n;
+
+ if (tmpBufferEnd - _tmpBuffer > tmpSize)
+ notEnoughData();
+
+ for (int j = 0; j < n; ++j)
+ {
+ unsigned int diff = (*(ptr[0]++) << 24) |
+ (*(ptr[1]++) << 16) |
+ (*(ptr[2]++) << 8);
+ pixel += diff;
+
+ char *pPtr = (char *) &pixel;
+
+ for (int k = 0; k < sizeof (pixel); ++k)
+ *writePtr++ = *pPtr++;
+ }
+
+ break;
+
+ default:
+
+ assert (false);
+ }
+ }
+ }
+
+ if (tmpBufferEnd - _tmpBuffer < tmpSize)
+ tooMuchData();
+
+ outPtr = _outBuffer;
+ return writePtr - _outBuffer;
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfPxr24Compressor.h b/Source/OpenEXR/IlmImf/ImfPxr24Compressor.h
new file mode 100644
index 0000000..ff168ae
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfPxr24Compressor.h
@@ -0,0 +1,105 @@
+#ifndef INCLUDED_IMF_PXR24_COMPRESSOR_H
+#define INCLUDED_IMF_PXR24_COMPRESSOR_H
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Pixar Animation Studios
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Pixar Animation Studios nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+/////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Pxr24Compressor -- Loren Carpenter's 24-bit float compressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+class ChannelList;
+
+
+class Pxr24Compressor: public Compressor
+{
+ public:
+
+ Pxr24Compressor (const Header &hdr, int maxScanLineSize, int numScanLines);
+ virtual ~Pxr24Compressor ();
+
+ virtual int numScanLines () const;
+
+ virtual Format format () const;
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int compressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int uncompressTile (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+ private:
+
+ int compress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int uncompress (const char *inPtr,
+ int inSize,
+ Imath::Box2i range,
+ const char *&outPtr);
+
+ int _maxScanLineSize;
+ int _numScanLines;
+ unsigned char * _tmpBuffer;
+ char * _outBuffer;
+ const ChannelList & _channels;
+ int _minX;
+ int _maxX;
+ int _maxY;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRational.cpp b/Source/OpenEXR/IlmImf/ImfRational.cpp
new file mode 100644
index 0000000..ae6bc0a
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRational.cpp
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Rational numbers
+//
+// The double-to-Rational conversion code below
+// was contributed to OpenEXR by Greg Ward.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRational.h>
+#include <cmath>
+
+using namespace std;
+
+namespace Imf {
+namespace {
+
+double
+frac (double x, double e)
+{
+ return x - floor (x + e);
+}
+
+
+double
+square (double x)
+{
+ return x * x;
+}
+
+
+double
+denom (double x, double e)
+{
+ if (e > frac (x, e))
+ {
+ return 1;
+ }
+ else
+ {
+ double r = frac (1 / x, e);
+
+ if (e > r)
+ {
+ return floor (1 / x + e);
+ }
+ else
+ {
+ return denom (frac (1 / r, e), e / square (x * r)) +
+ floor (1 / x + e) * denom (frac (1 / x, e), e / square (x));
+ }
+ }
+}
+
+} // namespace
+
+
+Rational::Rational (double x)
+{
+ int sign;
+
+ if (x >= 0)
+ {
+ sign = 1; // positive
+ }
+ else if (x < 0)
+ {
+ sign = -1; // negative
+ x = -x;
+ }
+ else
+ {
+ n = 0; // NaN
+ d = 0;
+ return;
+ }
+
+ if (x >= (1U << 31) - 0.5)
+ {
+ n = sign; // infinity
+ d = 0;
+ return;
+ }
+
+ double e = (x < 1? 1: x) / (1U << 30);
+ d = (unsigned int) denom (x, e);
+ n = sign * (int) floor (x * d + 0.5);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfRational.h b/Source/OpenEXR/IlmImf/ImfRational.h
new file mode 100644
index 0000000..4bad7b8
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRational.h
@@ -0,0 +1,93 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_RATIONAL_H
+#define INCLUDED_IMF_RATIONAL_H
+
+//-----------------------------------------------------------------------------
+//
+// Rational numbers
+//
+// A rational number is represented as pair of integers, n and d.
+// The value of of the rational number is
+//
+// n/d for d > 0
+// positive infinity for n > 0, d == 0
+// negative infinity for n < 0, d == 0
+// not a number (NaN) for n == 0, d == 0
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+class Rational
+{
+ public:
+
+ int n; // numerator
+ unsigned int d; // denominator
+
+
+ //----------------------------------------
+ // Default constructor, sets value to zero
+ //----------------------------------------
+
+ Rational (): n (0), d (1) {}
+
+
+ //-------------------------------------
+ // Constructor, explicitly sets n and d
+ //-------------------------------------
+
+ Rational (int n, int d): n (n), d (d) {}
+
+
+ //----------------------------
+ // Constructor, approximates x
+ //----------------------------
+
+ explicit Rational (double x);
+
+
+ //---------------------------------
+ // Approximate conversion to double
+ //---------------------------------
+
+ operator double () const {return double (n) / double (d);}
+};
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRationalAttribute.cpp b/Source/OpenEXR/IlmImf/ImfRationalAttribute.cpp
new file mode 100644
index 0000000..757ca27
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRationalAttribute.cpp
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class RationalAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRationalAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+RationalAttribute::staticTypeName ()
+{
+ return "rational";
+}
+
+
+template <>
+void
+RationalAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.n);
+ Xdr::write <StreamIO> (os, _value.d);
+}
+
+
+template <>
+void
+RationalAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.n);
+ Xdr::read <StreamIO> (is, _value.d);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfRationalAttribute.h b/Source/OpenEXR/IlmImf/ImfRationalAttribute.h
new file mode 100644
index 0000000..862bbf4
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRationalAttribute.h
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_IMF_RATIONAL_ATTRIBUTE_H
+#define INCLUDED_IMF_RATIONAL_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class RationalAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfRational.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Rational> RationalAttribute;
+
+template <>
+const char *RationalAttribute::staticTypeName ();
+
+template <>
+void RationalAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void RationalAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfRationalAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRgba.h b/Source/OpenEXR/IlmImf/ImfRgba.h
new file mode 100644
index 0000000..e68cb4b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRgba.h
@@ -0,0 +1,104 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_RGBA_H
+#define INCLUDED_IMF_RGBA_H
+
+//-----------------------------------------------------------------------------
+//
+// class Rgba
+//
+//-----------------------------------------------------------------------------
+
+#include "half.h"
+
+namespace Imf {
+
+
+//
+// RGBA pixel
+//
+
+struct Rgba
+{
+ half r;
+ half g;
+ half b;
+ half a;
+
+ Rgba () {}
+ Rgba (half r, half g, half b, half a = 1.f): r (r), g (g), b (b), a (a) {}
+
+ Rgba & operator = (const Rgba &other)
+ {
+ r = other.r;
+ g = other.g;
+ b = other.b;
+ a = other.a;
+
+ return *this;
+ }
+};
+
+
+//
+// Channels in an RGBA file
+//
+
+enum RgbaChannels
+{
+ WRITE_R = 0x01, // Red
+ WRITE_G = 0x02, // Green
+ WRITE_B = 0x04, // Blue
+ WRITE_A = 0x08, // Alpha
+
+ WRITE_Y = 0x10, // Luminance, for black-and-white images,
+ // or in combination with chroma
+
+ WRITE_C = 0x20, // Chroma (two subsampled channels, RY and BY,
+ // supported only for scanline-based files)
+
+ WRITE_RGB = 0x07, // Red, green, blue
+ WRITE_RGBA = 0x0f, // Red, green, blue, alpha
+
+ WRITE_YC = 0x30, // Luminance, chroma
+ WRITE_YA = 0x18, // Luminance, alpha
+ WRITE_YCA = 0x38 // Luminance, chroma, alpha
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRgbaFile.cpp b/Source/OpenEXR/IlmImf/ImfRgbaFile.cpp
new file mode 100644
index 0000000..be31fb8
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRgbaFile.cpp
@@ -0,0 +1,1297 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class RgbaOutputFile
+// class RgbaInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRgbaFile.h>
+#include <ImfOutputFile.h>
+#include <ImfInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfRgbaYca.h>
+#include <ImfStandardAttributes.h>
+#include <ImathFun.h>
+#include <IlmThreadMutex.h>
+#include <Iex.h>
+#include <string.h>
+#include <algorithm>
+
+
+namespace Imf {
+
+using namespace std;
+using namespace Imath;
+using namespace RgbaYca;
+using namespace IlmThread;
+
+namespace {
+
+void
+insertChannels (Header &header, RgbaChannels rgbaChannels)
+{
+ ChannelList ch;
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ {
+ if (rgbaChannels & WRITE_Y)
+ {
+ ch.insert ("Y", Channel (HALF, 1, 1));
+ }
+
+ if (rgbaChannels & WRITE_C)
+ {
+ ch.insert ("RY", Channel (HALF, 2, 2, true));
+ ch.insert ("BY", Channel (HALF, 2, 2, true));
+ }
+ }
+ else
+ {
+ if (rgbaChannels & WRITE_R)
+ ch.insert ("R", Channel (HALF, 1, 1));
+
+ if (rgbaChannels & WRITE_G)
+ ch.insert ("G", Channel (HALF, 1, 1));
+
+ if (rgbaChannels & WRITE_B)
+ ch.insert ("B", Channel (HALF, 1, 1));
+ }
+
+ if (rgbaChannels & WRITE_A)
+ ch.insert ("A", Channel (HALF, 1, 1));
+
+ header.channels() = ch;
+}
+
+
+RgbaChannels
+rgbaChannels (const ChannelList &ch)
+{
+ int i = 0;
+
+ if (ch.findChannel ("R"))
+ i |= WRITE_R;
+
+ if (ch.findChannel ("G"))
+ i |= WRITE_G;
+
+ if (ch.findChannel ("B"))
+ i |= WRITE_B;
+
+ if (ch.findChannel ("A"))
+ i |= WRITE_A;
+
+ if (ch.findChannel ("Y"))
+ i |= WRITE_Y;
+
+ if (ch.findChannel ("RY") || ch.findChannel ("BY"))
+ i |= WRITE_C;
+
+ return RgbaChannels (i);
+}
+
+
+V3f
+ywFromHeader (const Header &header)
+{
+ Chromaticities cr;
+
+ if (hasChromaticities (header))
+ cr = chromaticities (header);
+
+ return computeYw (cr);
+}
+
+} // namespace
+
+
+class RgbaOutputFile::ToYca: public Mutex
+{
+ public:
+
+ ToYca (OutputFile &outputFile, RgbaChannels rgbaChannels);
+ ~ToYca ();
+
+ void setYCRounding (unsigned int roundY,
+ unsigned int roundC);
+
+ void setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ void writePixels (int numScanLines);
+ int currentScanLine () const;
+
+ private:
+
+ void padTmpBuf ();
+ void rotateBuffers ();
+ void duplicateLastBuffer ();
+ void duplicateSecondToLastBuffer ();
+ void decimateChromaVertAndWriteScanLine ();
+
+ OutputFile & _outputFile;
+ bool _writeY;
+ bool _writeC;
+ bool _writeA;
+ int _xMin;
+ int _width;
+ int _height;
+ int _linesConverted;
+ LineOrder _lineOrder;
+ int _currentScanLine;
+ V3f _yw;
+ Rgba * _buf[N];
+ Rgba * _tmpBuf;
+ const Rgba * _fbBase;
+ size_t _fbXStride;
+ size_t _fbYStride;
+ int _roundY;
+ int _roundC;
+};
+
+
+RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile,
+ RgbaChannels rgbaChannels)
+:
+ _outputFile (outputFile)
+{
+ _writeY = (rgbaChannels & WRITE_Y)? true: false;
+ _writeC = (rgbaChannels & WRITE_C)? true: false;
+ _writeA = (rgbaChannels & WRITE_A)? true: false;
+
+ const Box2i dw = _outputFile.header().dataWindow();
+
+ _xMin = dw.min.x;
+ _width = dw.max.x - dw.min.x + 1;
+ _height = dw.max.y - dw.min.y + 1;
+
+ _linesConverted = 0;
+ _lineOrder = _outputFile.header().lineOrder();
+
+ if (_lineOrder == INCREASING_Y)
+ _currentScanLine = dw.min.y;
+ else
+ _currentScanLine = dw.max.y;
+
+ _yw = ywFromHeader (_outputFile.header());
+
+ for (int i = 0; i < N; ++i)
+ _buf[i] = new Rgba[_width];
+
+ _tmpBuf = new Rgba[_width + N - 1];
+
+ _fbBase = 0;
+ _fbXStride = 0;
+ _fbYStride = 0;
+
+ _roundY = 7;
+ _roundC = 5;
+}
+
+
+RgbaOutputFile::ToYca::~ToYca ()
+{
+ for (int i = 0; i < N; ++i)
+ delete [] _buf[i];
+
+ delete [] _tmpBuf;
+}
+
+
+void
+RgbaOutputFile::ToYca::setYCRounding (unsigned int roundY,
+ unsigned int roundC)
+{
+ _roundY = roundY;
+ _roundC = roundC;
+}
+
+
+void
+RgbaOutputFile::ToYca::setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ if (_fbBase == 0)
+ {
+ FrameBuffer fb;
+
+ if (_writeY)
+ {
+ fb.insert ("Y",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[-_xMin].g, // base
+ sizeof (Rgba), // xStride
+ 0, // yStride
+ 1, // xSampling
+ 1)); // ySampling
+ }
+
+ if (_writeC)
+ {
+ fb.insert ("RY",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[-_xMin].r, // base
+ sizeof (Rgba) * 2, // xStride
+ 0, // yStride
+ 2, // xSampling
+ 2)); // ySampling
+
+ fb.insert ("BY",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[-_xMin].b, // base
+ sizeof (Rgba) * 2, // xStride
+ 0, // yStride
+ 2, // xSampling
+ 2)); // ySampling
+ }
+
+ if (_writeA)
+ {
+ fb.insert ("A",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[-_xMin].a, // base
+ sizeof (Rgba), // xStride
+ 0, // yStride
+ 1, // xSampling
+ 1)); // ySampling
+ }
+
+ _outputFile.setFrameBuffer (fb);
+ }
+
+ _fbBase = base;
+ _fbXStride = xStride;
+ _fbYStride = yStride;
+}
+
+
+void
+RgbaOutputFile::ToYca::writePixels (int numScanLines)
+{
+ if (_fbBase == 0)
+ {
+ THROW (Iex::ArgExc, "No frame buffer was specified as the "
+ "pixel data source for image file "
+ "\"" << _outputFile.fileName() << "\".");
+ }
+
+ if (_writeY && !_writeC)
+ {
+ //
+ // We are writing only luminance; filtering
+ // and subsampling are not necessary.
+ //
+
+ for (int i = 0; i < numScanLines; ++i)
+ {
+ //
+ // Copy the next scan line from the caller's
+ // frame buffer into _tmpBuf.
+ //
+
+ for (int j = 0; j < _width; ++j)
+ {
+ _tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine +
+ _fbXStride * (j + _xMin)];
+ }
+
+ //
+ // Convert the scan line from RGB to luminance/chroma,
+ // and store the result in the output file.
+ //
+
+ RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf);
+ _outputFile.writePixels (1);
+
+ ++_linesConverted;
+
+ if (_lineOrder == INCREASING_Y)
+ ++_currentScanLine;
+ else
+ --_currentScanLine;
+ }
+ }
+ else
+ {
+ //
+ // We are writing chroma; the pixels must be filtered and subsampled.
+ //
+
+ for (int i = 0; i < numScanLines; ++i)
+ {
+ //
+ // Copy the next scan line from the caller's
+ // frame buffer into _tmpBuf.
+ //
+
+ for (int j = 0; j < _width; ++j)
+ {
+ _tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine +
+ _fbXStride * (j + _xMin)];
+ }
+
+ //
+ // Convert the scan line from RGB to luminance/chroma.
+ //
+
+ RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2);
+
+ //
+ // Append N2 copies of the first and last pixel to the
+ // beginning and end of the scan line.
+ //
+
+ padTmpBuf ();
+
+ //
+ // Filter and subsample the scan line's chroma channels
+ // horizontally; store the result in _buf.
+ //
+
+ rotateBuffers();
+ decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]);
+
+ //
+ // If this is the first scan line in the image,
+ // store N2 more copies of the scan line in _buf.
+ //
+
+ if (_linesConverted == 0)
+ {
+ for (int j = 0; j < N2; ++j)
+ duplicateLastBuffer();
+ }
+
+ ++_linesConverted;
+
+ //
+ // If we have have converted at least N2 scan lines from
+ // RGBA to luminance/chroma, then we can start to filter
+ // and subsample vertically, and store pixels in the
+ // output file.
+ //
+
+ if (_linesConverted > N2)
+ decimateChromaVertAndWriteScanLine();
+
+ //
+ // If we have already converted the last scan line in
+ // the image to luminance/chroma, filter, subsample and
+ // store the remaining scan lines in _buf.
+ //
+
+ if (_linesConverted >= _height)
+ {
+ for (int j = 0; j < N2 - _height; ++j)
+ duplicateLastBuffer();
+
+ duplicateSecondToLastBuffer();
+ ++_linesConverted;
+ decimateChromaVertAndWriteScanLine();
+
+ for (int j = 1; j < min (_height, N2); ++j)
+ {
+ duplicateLastBuffer();
+ ++_linesConverted;
+ decimateChromaVertAndWriteScanLine();
+ }
+ }
+
+ if (_lineOrder == INCREASING_Y)
+ ++_currentScanLine;
+ else
+ --_currentScanLine;
+ }
+ }
+}
+
+
+int
+RgbaOutputFile::ToYca::currentScanLine () const
+{
+ return _currentScanLine;
+}
+
+
+void
+RgbaOutputFile::ToYca::padTmpBuf ()
+{
+ for (int i = 0; i < N2; ++i)
+ {
+ _tmpBuf[i] = _tmpBuf[N2];
+ _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
+ }
+}
+
+
+void
+RgbaOutputFile::ToYca::rotateBuffers ()
+{
+ Rgba *tmp = _buf[0];
+
+ for (int i = 0; i < N - 1; ++i)
+ _buf[i] = _buf[i + 1];
+
+ _buf[N - 1] = tmp;
+}
+
+
+void
+RgbaOutputFile::ToYca::duplicateLastBuffer ()
+{
+ rotateBuffers();
+ memcpy (_buf[N - 1], _buf[N - 2], _width * sizeof (Rgba));
+}
+
+
+void
+RgbaOutputFile::ToYca::duplicateSecondToLastBuffer ()
+{
+ rotateBuffers();
+ memcpy (_buf[N - 1], _buf[N - 3], _width * sizeof (Rgba));
+}
+
+
+void
+RgbaOutputFile::ToYca::decimateChromaVertAndWriteScanLine ()
+{
+ if (_linesConverted & 1)
+ memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba));
+ else
+ decimateChromaVert (_width, _buf, _tmpBuf);
+
+ if (_writeY && _writeC)
+ roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf);
+
+ _outputFile.writePixels (1);
+}
+
+
+RgbaOutputFile::RgbaOutputFile (const char name[],
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int numThreads):
+ _outputFile (0),
+ _toYca (0)
+{
+ Header hd (header);
+ insertChannels (hd, rgbaChannels);
+ _outputFile = new OutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _toYca = new ToYca (*_outputFile, rgbaChannels);
+}
+
+
+RgbaOutputFile::RgbaOutputFile (OStream &os,
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int numThreads):
+ _outputFile (0),
+ _toYca (0)
+{
+ Header hd (header);
+ insertChannels (hd, rgbaChannels);
+ _outputFile = new OutputFile (os, hd, numThreads);
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _toYca = new ToYca (*_outputFile, rgbaChannels);
+}
+
+
+RgbaOutputFile::RgbaOutputFile (const char name[],
+ const Imath::Box2i &displayWindow,
+ const Imath::Box2i &dataWindow,
+ RgbaChannels rgbaChannels,
+ float pixelAspectRatio,
+ const Imath::V2f screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression,
+ int numThreads):
+ _outputFile (0),
+ _toYca (0)
+{
+ Header hd (displayWindow,
+ dataWindow.isEmpty()? displayWindow: dataWindow,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+
+ insertChannels (hd, rgbaChannels);
+ _outputFile = new OutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _toYca = new ToYca (*_outputFile, rgbaChannels);
+}
+
+
+RgbaOutputFile::RgbaOutputFile (const char name[],
+ int width,
+ int height,
+ RgbaChannels rgbaChannels,
+ float pixelAspectRatio,
+ const Imath::V2f screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression,
+ int numThreads):
+ _outputFile (0),
+ _toYca (0)
+{
+ Header hd (width,
+ height,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+
+ insertChannels (hd, rgbaChannels);
+ _outputFile = new OutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _toYca = new ToYca (*_outputFile, rgbaChannels);
+}
+
+
+RgbaOutputFile::~RgbaOutputFile ()
+{
+ delete _toYca;
+ delete _outputFile;
+}
+
+
+void
+RgbaOutputFile::setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ if (_toYca)
+ {
+ Lock lock (*_toYca);
+ _toYca->setFrameBuffer (base, xStride, yStride);
+ }
+ else
+ {
+ size_t xs = xStride * sizeof (Rgba);
+ size_t ys = yStride * sizeof (Rgba);
+
+ FrameBuffer fb;
+
+ fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));
+ fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));
+ fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));
+ fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));
+
+ _outputFile->setFrameBuffer (fb);
+ }
+}
+
+
+void
+RgbaOutputFile::writePixels (int numScanLines)
+{
+ if (_toYca)
+ {
+ Lock lock (*_toYca);
+ _toYca->writePixels (numScanLines);
+ }
+ else
+ {
+ _outputFile->writePixels (numScanLines);
+ }
+}
+
+
+int
+RgbaOutputFile::currentScanLine () const
+{
+ if (_toYca)
+ {
+ Lock lock (*_toYca);
+ return _toYca->currentScanLine();
+ }
+ else
+ {
+ return _outputFile->currentScanLine();
+ }
+}
+
+
+const Header &
+RgbaOutputFile::header () const
+{
+ return _outputFile->header();
+}
+
+
+const FrameBuffer &
+RgbaOutputFile::frameBuffer () const
+{
+ return _outputFile->frameBuffer();
+}
+
+
+const Imath::Box2i &
+RgbaOutputFile::displayWindow () const
+{
+ return _outputFile->header().displayWindow();
+}
+
+
+const Imath::Box2i &
+RgbaOutputFile::dataWindow () const
+{
+ return _outputFile->header().dataWindow();
+}
+
+
+float
+RgbaOutputFile::pixelAspectRatio () const
+{
+ return _outputFile->header().pixelAspectRatio();
+}
+
+
+const Imath::V2f
+RgbaOutputFile::screenWindowCenter () const
+{
+ return _outputFile->header().screenWindowCenter();
+}
+
+
+float
+RgbaOutputFile::screenWindowWidth () const
+{
+ return _outputFile->header().screenWindowWidth();
+}
+
+
+LineOrder
+RgbaOutputFile::lineOrder () const
+{
+ return _outputFile->header().lineOrder();
+}
+
+
+Compression
+RgbaOutputFile::compression () const
+{
+ return _outputFile->header().compression();
+}
+
+
+RgbaChannels
+RgbaOutputFile::channels () const
+{
+ return rgbaChannels (_outputFile->header().channels());
+}
+
+
+void
+RgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
+{
+ _outputFile->updatePreviewImage (newPixels);
+}
+
+
+void
+RgbaOutputFile::setYCRounding (unsigned int roundY, unsigned int roundC)
+{
+ if (_toYca)
+ {
+ Lock lock (*_toYca);
+ _toYca->setYCRounding (roundY, roundC);
+ }
+}
+
+
+void
+RgbaOutputFile::breakScanLine (int y, int offset, int length, char c)
+{
+ _outputFile->breakScanLine (y, offset, length, c);
+}
+
+
+class RgbaInputFile::FromYca: public Mutex
+{
+ public:
+
+ FromYca (InputFile &inputFile, RgbaChannels rgbaChannels);
+ ~FromYca ();
+
+ void setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ void readPixels (int scanLine1, int scanLine2);
+
+ private:
+
+ void readPixels (int scanLine);
+ void rotateBuf1 (int d);
+ void rotateBuf2 (int d);
+ void readYCAScanLine (int y, Rgba buf[]);
+ void padTmpBuf ();
+
+ InputFile & _inputFile;
+ bool _readC;
+ int _xMin;
+ int _yMin;
+ int _yMax;
+ int _width;
+ int _height;
+ int _currentScanLine;
+ LineOrder _lineOrder;
+ V3f _yw;
+ Rgba * _buf1[N + 2];
+ Rgba * _buf2[3];
+ Rgba * _tmpBuf;
+ Rgba * _fbBase;
+ size_t _fbXStride;
+ size_t _fbYStride;
+};
+
+
+RgbaInputFile::FromYca::FromYca (InputFile &inputFile,
+ RgbaChannels rgbaChannels)
+:
+ _inputFile (inputFile)
+{
+ _readC = (rgbaChannels & WRITE_C)? true: false;
+
+ const Box2i dw = _inputFile.header().dataWindow();
+
+ _xMin = dw.min.x;
+ _yMin = dw.min.y;
+ _yMax = dw.max.y;
+ _width = dw.max.x - dw.min.x + 1;
+ _height = dw.max.y - dw.min.y + 1;
+ _currentScanLine = dw.min.y - N - 2;
+ _lineOrder = _inputFile.header().lineOrder();
+ _yw = ywFromHeader (_inputFile.header());
+
+ for (int i = 0; i < N + 2; ++i)
+ _buf1[i] = new Rgba[_width];
+
+ for (int i = 0; i < 3; ++i)
+ _buf2[i] = new Rgba[_width];
+
+ _tmpBuf = new Rgba[_width + N - 1];
+
+ _fbBase = 0;
+ _fbXStride = 0;
+ _fbYStride = 0;
+}
+
+
+RgbaInputFile::FromYca::~FromYca ()
+{
+ for (int i = 0; i < N + 2; ++i)
+ delete [] _buf1[i];
+
+ for (int i = 0; i < 3; ++i)
+ delete [] _buf2[i];
+
+ delete [] _tmpBuf;
+}
+
+
+void
+RgbaInputFile::FromYca::setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ if (_fbBase == 0)
+ {
+ FrameBuffer fb;
+
+ fb.insert ("Y",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[N2 - _xMin].g, // base
+ sizeof (Rgba), // xStride
+ 0, // yStride
+ 1, // xSampling
+ 1, // ySampling
+ 0.5)); // fillValue
+
+ if (_readC)
+ {
+ fb.insert ("RY",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[N2 - _xMin].r, // base
+ sizeof (Rgba) * 2, // xStride
+ 0, // yStride
+ 2, // xSampling
+ 2, // ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("BY",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[N2 - _xMin].b, // base
+ sizeof (Rgba) * 2, // xStride
+ 0, // yStride
+ 2, // xSampling
+ 2, // ySampling
+ 0.0)); // fillValue
+ }
+
+ fb.insert ("A",
+ Slice (HALF, // type
+ (char *) &_tmpBuf[N2 - _xMin].a, // base
+ sizeof (Rgba), // xStride
+ 0, // yStride
+ 1, // xSampling
+ 1, // ySampling
+ 1.0)); // fillValue
+
+ _inputFile.setFrameBuffer (fb);
+ }
+
+ _fbBase = base;
+ _fbXStride = xStride;
+ _fbYStride = yStride;
+}
+
+
+void
+RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2)
+{
+ int minY = min (scanLine1, scanLine2);
+ int maxY = max (scanLine1, scanLine2);
+
+ if (_lineOrder == INCREASING_Y)
+ {
+ for (int y = minY; y <= maxY; ++y)
+ readPixels (y);
+ }
+ else
+ {
+ for (int y = maxY; y >= minY; --y)
+ readPixels (y);
+ }
+}
+
+
+void
+RgbaInputFile::FromYca::readPixels (int scanLine)
+{
+ if (_fbBase == 0)
+ {
+ THROW (Iex::ArgExc, "No frame buffer was specified as the "
+ "pixel data destination for image file "
+ "\"" << _inputFile.fileName() << "\".");
+ }
+
+ //
+ // In order to convert one scan line to RGB format, we need that
+ // scan line plus N2+1 extra scan lines above and N2+1 scan lines
+ // below in luminance/chroma format.
+ //
+ // We allow random access to scan lines, but we buffer partially
+ // processed luminance/chroma data in order to make reading pixels
+ // in increasing y or decreasing y order reasonably efficient:
+ //
+ // _currentScanLine holds the y coordinate of the scan line
+ // that was most recently read.
+ //
+ // _buf1 contains scan lines _currentScanLine-N2-1
+ // through _currentScanLine+N2+1 in
+ // luminance/chroma format. Odd-numbered
+ // lines contain no chroma data. Even-numbered
+ // lines have valid chroma data for all pixels.
+ //
+ // _buf2 contains scan lines _currentScanLine-1
+ // through _currentScanLine+1, in RGB format.
+ // Super-saturated pixels (see ImfRgbaYca.h)
+ // have not yet been eliminated.
+ //
+ // If the scan line we are trying to read now is close enough to
+ // _currentScanLine, we don't have to recompute the contents of _buf1
+ // and _buf2 from scratch. We can rotate _buf1 and _buf2, and fill
+ // in the missing data.
+ //
+
+ int dy = scanLine - _currentScanLine;
+
+ if (abs (dy) < N + 2)
+ rotateBuf1 (dy);
+
+ if (abs (dy) < 3)
+ rotateBuf2 (dy);
+
+ if (dy < 0)
+ {
+ {
+ int n = min (-dy, N + 2);
+ int yMin = scanLine - N2 - 1;
+
+ for (int i = n - 1; i >= 0; --i)
+ readYCAScanLine (yMin + i, _buf1[i]);
+ }
+
+ {
+ int n = min (-dy, 3);
+
+ for (int i = 0; i < n; ++i)
+ {
+ if ((scanLine + i) & 1)
+ {
+ YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
+ }
+ else
+ {
+ reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
+ YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
+ }
+ }
+ }
+ }
+ else
+ {
+ {
+ int n = min (dy, N + 2);
+ int yMax = scanLine + N2 + 1;
+
+ for (int i = n - 1; i >= 0; --i)
+ readYCAScanLine (yMax - i, _buf1[N + 1 - i]);
+ }
+
+ {
+ int n = min (dy, 3);
+
+ for (int i = 2; i > 2 - n; --i)
+ {
+ if ((scanLine + i) & 1)
+ {
+ YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
+ }
+ else
+ {
+ reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
+ YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
+ }
+ }
+ }
+ }
+
+ fixSaturation (_yw, _width, _buf2, _tmpBuf);
+
+ for (int i = 0; i < _width; ++i)
+ _fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i];
+
+ _currentScanLine = scanLine;
+}
+
+
+void
+RgbaInputFile::FromYca::rotateBuf1 (int d)
+{
+ d = modp (d, N + 2);
+
+ Rgba *tmp[N + 2];
+
+ for (int i = 0; i < N + 2; ++i)
+ tmp[i] = _buf1[i];
+
+ for (int i = 0; i < N + 2; ++i)
+ _buf1[i] = tmp[(i + d) % (N + 2)];
+}
+
+
+void
+RgbaInputFile::FromYca::rotateBuf2 (int d)
+{
+ d = modp (d, 3);
+
+ Rgba *tmp[3];
+
+ for (int i = 0; i < 3; ++i)
+ tmp[i] = _buf2[i];
+
+ for (int i = 0; i < 3; ++i)
+ _buf2[i] = tmp[(i + d) % 3];
+}
+
+
+void
+RgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf)
+{
+ //
+ // Clamp y.
+ //
+
+ if (y < _yMin)
+ y = _yMin;
+ else if (y > _yMax)
+ y = _yMax - 1;
+
+ //
+ // Read scan line y into _tmpBuf.
+ //
+
+ _inputFile.readPixels (y);
+
+ //
+ // Reconstruct missing chroma samples and copy
+ // the scan line into buf.
+ //
+
+ if (!_readC)
+ {
+ for (int i = 0; i < _width; ++i)
+ {
+ _tmpBuf[i + N2].r = 0;
+ _tmpBuf[i + N2].b = 0;
+ }
+ }
+
+ if (y & 1)
+ {
+ memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba));
+ }
+ else
+ {
+ padTmpBuf();
+ reconstructChromaHoriz (_width, _tmpBuf, buf);
+ }
+}
+
+
+void
+RgbaInputFile::FromYca::padTmpBuf ()
+{
+ for (int i = 0; i < N2; ++i)
+ {
+ _tmpBuf[i] = _tmpBuf[N2];
+ _tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
+ }
+}
+
+
+RgbaInputFile::RgbaInputFile (const char name[], int numThreads):
+ _inputFile (new InputFile (name, numThreads)),
+ _fromYca (0)
+{
+ RgbaChannels rgbaChannels = channels();
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _fromYca = new FromYca (*_inputFile, rgbaChannels);
+}
+
+
+RgbaInputFile::RgbaInputFile (IStream &is, int numThreads):
+ _inputFile (new InputFile (is, numThreads)),
+ _fromYca (0)
+{
+ RgbaChannels rgbaChannels = channels();
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ _fromYca = new FromYca (*_inputFile, rgbaChannels);
+}
+
+
+RgbaInputFile::~RgbaInputFile ()
+{
+ delete _inputFile;
+ delete _fromYca;
+}
+
+
+void
+RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
+{
+ if (_fromYca)
+ {
+ Lock lock (*_fromYca);
+ _fromYca->setFrameBuffer (base, xStride, yStride);
+ }
+ else
+ {
+ size_t xs = xStride * sizeof (Rgba);
+ size_t ys = yStride * sizeof (Rgba);
+
+ FrameBuffer fb;
+
+ fb.insert ("R", Slice (HALF,
+ (char *) &base[0].r,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("G", Slice (HALF,
+ (char *) &base[0].g,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("B", Slice (HALF,
+ (char *) &base[0].b,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("A", Slice (HALF,
+ (char *) &base[0].a,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 1.0)); // fillValue
+
+ _inputFile->setFrameBuffer (fb);
+ }
+}
+
+
+void
+RgbaInputFile::readPixels (int scanLine1, int scanLine2)
+{
+ if (_fromYca)
+ {
+ Lock lock (*_fromYca);
+ _fromYca->readPixels (scanLine1, scanLine2);
+ }
+ else
+ {
+ _inputFile->readPixels (scanLine1, scanLine2);
+ }
+}
+
+
+void
+RgbaInputFile::readPixels (int scanLine)
+{
+ readPixels (scanLine, scanLine);
+}
+
+
+bool
+RgbaInputFile::isComplete () const
+{
+ return _inputFile->isComplete();
+}
+
+
+const Header &
+RgbaInputFile::header () const
+{
+ return _inputFile->header();
+}
+
+
+const char *
+RgbaInputFile::fileName () const
+{
+ return _inputFile->fileName();
+}
+
+
+const FrameBuffer &
+RgbaInputFile::frameBuffer () const
+{
+ return _inputFile->frameBuffer();
+}
+
+
+const Imath::Box2i &
+RgbaInputFile::displayWindow () const
+{
+ return _inputFile->header().displayWindow();
+}
+
+
+const Imath::Box2i &
+RgbaInputFile::dataWindow () const
+{
+ return _inputFile->header().dataWindow();
+}
+
+
+float
+RgbaInputFile::pixelAspectRatio () const
+{
+ return _inputFile->header().pixelAspectRatio();
+}
+
+
+const Imath::V2f
+RgbaInputFile::screenWindowCenter () const
+{
+ return _inputFile->header().screenWindowCenter();
+}
+
+
+float
+RgbaInputFile::screenWindowWidth () const
+{
+ return _inputFile->header().screenWindowWidth();
+}
+
+
+LineOrder
+RgbaInputFile::lineOrder () const
+{
+ return _inputFile->header().lineOrder();
+}
+
+
+Compression
+RgbaInputFile::compression () const
+{
+ return _inputFile->header().compression();
+}
+
+
+RgbaChannels
+RgbaInputFile::channels () const
+{
+ return rgbaChannels (_inputFile->header().channels());
+}
+
+
+int
+RgbaInputFile::version () const
+{
+ return _inputFile->version();
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfRgbaFile.h b/Source/OpenEXR/IlmImf/ImfRgbaFile.h
new file mode 100644
index 0000000..ff7b07b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRgbaFile.h
@@ -0,0 +1,315 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_RGBA_FILE_H
+#define INCLUDED_IMF_RGBA_FILE_H
+
+
+//-----------------------------------------------------------------------------
+//
+// Simplified RGBA image I/O
+//
+// class RgbaOutputFile
+// class RgbaInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include <ImfRgba.h>
+#include "ImathVec.h"
+#include "ImathBox.h"
+#include "half.h"
+#include <ImfThreading.h>
+
+namespace Imf {
+
+
+class OutputFile;
+class InputFile;
+struct PreviewRgba;
+
+//
+// RGBA output file.
+//
+
+class RgbaOutputFile
+{
+ public:
+
+ //---------------------------------------------------
+ // Constructor -- header is constructed by the caller
+ //---------------------------------------------------
+
+ RgbaOutputFile (const char name[],
+ const Header &header,
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ int numThreads = globalThreadCount());
+
+
+ //----------------------------------------------------
+ // Constructor -- header is constructed by the caller,
+ // file is opened by the caller, destructor will not
+ // automatically close the file.
+ //----------------------------------------------------
+
+ RgbaOutputFile (OStream &os,
+ const Header &header,
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ int numThreads = globalThreadCount());
+
+
+ //----------------------------------------------------------------
+ // Constructor -- header data are explicitly specified as function
+ // call arguments (empty dataWindow means "same as displayWindow")
+ //----------------------------------------------------------------
+
+ RgbaOutputFile (const char name[],
+ const Imath::Box2i &displayWindow,
+ const Imath::Box2i &dataWindow = Imath::Box2i(),
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ float pixelAspectRatio = 1,
+ const Imath::V2f screenWindowCenter = Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression compression = PIZ_COMPRESSION,
+ int numThreads = globalThreadCount());
+
+
+ //-----------------------------------------------
+ // Constructor -- like the previous one, but both
+ // the display window and the data window are
+ // Box2i (V2i (0, 0), V2i (width - 1, height -1))
+ //-----------------------------------------------
+
+ RgbaOutputFile (const char name[],
+ int width,
+ int height,
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ float pixelAspectRatio = 1,
+ const Imath::V2f screenWindowCenter = Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression compression = PIZ_COMPRESSION,
+ int numThreads = globalThreadCount());
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~RgbaOutputFile ();
+
+
+ //------------------------------------------------
+ // Define a frame buffer as the pixel data source:
+ // Pixel (x, y) is at address
+ //
+ // base + x * xStride + y * yStride
+ //
+ //------------------------------------------------
+
+ void setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+
+ //---------------------------------------------
+ // Write pixel data (see class Imf::OutputFile)
+ //---------------------------------------------
+
+ void writePixels (int numScanLines = 1);
+ int currentScanLine () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+ const FrameBuffer & frameBuffer () const;
+ const Imath::Box2i & displayWindow () const;
+ const Imath::Box2i & dataWindow () const;
+ float pixelAspectRatio () const;
+ const Imath::V2f screenWindowCenter () const;
+ float screenWindowWidth () const;
+ LineOrder lineOrder () const;
+ Compression compression () const;
+ RgbaChannels channels () const;
+
+
+ // --------------------------------------------------------------------
+ // Update the preview image (see Imf::OutputFile::updatePreviewImage())
+ // --------------------------------------------------------------------
+
+ void updatePreviewImage (const PreviewRgba[]);
+
+
+ //-----------------------------------------------------------------------
+ // Rounding control for luminance/chroma images:
+ //
+ // If the output file contains luminance and chroma channels (WRITE_YC
+ // or WRITE_YCA), then the the significands of the luminance and
+ // chroma values are rounded to roundY and roundC bits respectively (see
+ // function half::round()). Rounding improves compression with minimal
+ // image degradation, usually much less than the degradation caused by
+ // chroma subsampling. By default, roundY is 7, and roundC is 5.
+ //
+ // If the output file contains RGB channels or a luminance channel,
+ // without chroma, then no rounding is performed.
+ //-----------------------------------------------------------------------
+
+ void setYCRounding (unsigned int roundY,
+ unsigned int roundC);
+
+
+ //----------------------------------------------------
+ // Break a scan line -- for testing and debugging only
+ // (see Imf::OutputFile::updatePreviewImage()
+ //
+ // Warning: Calling this function usually results in a
+ // broken image file. The file or parts of it may not
+ // be readable, or the file may contain bad data.
+ //
+ //----------------------------------------------------
+
+ void breakScanLine (int y,
+ int offset,
+ int length,
+ char c);
+ private:
+
+ RgbaOutputFile (const RgbaOutputFile &); // not implemented
+ RgbaOutputFile & operator = (const RgbaOutputFile &); // not implemented
+
+ class ToYca;
+
+ OutputFile * _outputFile;
+ ToYca * _toYca;
+};
+
+
+//
+// RGBA input file
+//
+
+class RgbaInputFile
+{
+ public:
+
+ //-------------------------------------------------------
+ // Constructor -- opens the file with the specified name,
+ // destructor will automatically close the file.
+ //-------------------------------------------------------
+
+ RgbaInputFile (const char name[], int numThreads = globalThreadCount());
+
+
+ //-----------------------------------------------------------
+ // Constructor -- attaches the new RgbaInputFile object to a
+ // file that has already been opened by the caller.
+ // Destroying the RgbaInputFile object will not automatically
+ // close the file.
+ //-----------------------------------------------------------
+
+ RgbaInputFile (IStream &is, int numThreads = globalThreadCount());
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~RgbaInputFile ();
+
+ //-----------------------------------------------------
+ // Define a frame buffer as the pixel data destination:
+ // Pixel (x, y) is at address
+ //
+ // base + x * xStride + y * yStride
+ //
+ //-----------------------------------------------------
+
+ void setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+
+ //-------------------------------------------
+ // Read pixel data (see class Imf::InputFile)
+ //-------------------------------------------
+
+ void readPixels (int scanLine1, int scanLine2);
+ void readPixels (int scanLine);
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+ const FrameBuffer & frameBuffer () const;
+ const Imath::Box2i & displayWindow () const;
+ const Imath::Box2i & dataWindow () const;
+ float pixelAspectRatio () const;
+ const Imath::V2f screenWindowCenter () const;
+ float screenWindowWidth () const;
+ LineOrder lineOrder () const;
+ Compression compression () const;
+ RgbaChannels channels () const;
+ const char * fileName () const;
+ bool isComplete () const;
+
+ //----------------------------------
+ // Access to the file format version
+ //----------------------------------
+
+ int version () const;
+
+ private:
+
+ RgbaInputFile (const RgbaInputFile &); // not implemented
+ RgbaInputFile & operator = (const RgbaInputFile &); // not implemented
+
+ class FromYca;
+
+ InputFile * _inputFile;
+ FromYca * _fromYca;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRgbaYca.cpp b/Source/OpenEXR/IlmImf/ImfRgbaYca.cpp
new file mode 100644
index 0000000..850c734
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRgbaYca.cpp
@@ -0,0 +1,482 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
+// Entertainment Company Ltd. Portions contributed and copyright held by
+// others as indicated. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided with
+// the distribution.
+//
+// * Neither the name of Industrial Light & Magic nor the names of
+// any other contributors to this software may be used to endorse or
+// promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Conversion between RGBA and YCA data.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRgbaYca.h>
+#include <assert.h>
+#include <algorithm>
+
+using namespace Imath;
+using namespace std;
+
+namespace Imf {
+namespace RgbaYca {
+
+
+V3f
+computeYw (const Chromaticities &cr)
+{
+ M44f m = RGBtoXYZ (cr, 1);
+ return V3f (m[0][1], m[1][1], m[2][1]) / (m[0][1] + m[1][1] + m[2][1]);
+}
+
+
+void
+RGBAtoYCA (const V3f &yw,
+ int n,
+ bool aIsValid,
+ const Rgba rgbaIn[/*n*/],
+ Rgba ycaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ Rgba in = rgbaIn[i];
+ Rgba &out = ycaOut[i];
+
+ //
+ // Conversion to YCA and subsequent chroma subsampling
+ // work only if R, G and B are finite and non-negative.
+ //
+
+ if (!in.r.isFinite() || in.r < 0)
+ in.r = 0;
+
+ if (!in.g.isFinite() || in.g < 0)
+ in.g = 0;
+
+ if (!in.b.isFinite() || in.b < 0)
+ in.b = 0;
+
+ if (in.r == in.g && in.g == in.b)
+ {
+ //
+ // Special case -- R, G and B are equal. To avoid rounding
+ // errors, we explicitly set the output luminance channel
+ // to G, and the chroma channels to 0.
+ //
+ // The special cases here and in YCAtoRGBA() ensure that
+ // converting black-and white images from RGBA to YCA and
+ // back is lossless.
+ //
+
+ out.r = 0;
+ out.g = in.g;
+ out.b = 0;
+ }
+ else
+ {
+ out.g = in.r * yw.x + in.g * yw.y + in.b * yw.z;
+
+ float Y = out.g;
+
+ if (abs (in.r - Y) < HALF_MAX * Y)
+ out.r = (in.r - Y) / Y;
+ else
+ out.r = 0;
+
+ if (abs (in.b - Y) < HALF_MAX * Y)
+ out.b = (in.b - Y) / Y;
+ else
+ out.b = 0;
+ }
+
+ if (aIsValid)
+ out.a = in.a;
+ else
+ out.a = 1;
+ }
+}
+
+
+void
+decimateChromaHoriz (int n,
+ const Rgba ycaIn[/*n+N-1*/],
+ Rgba ycaOut[/*n*/])
+{
+ #ifdef DEBUG
+ assert (ycaIn != ycaOut);
+ #endif
+
+ int begin = N2;
+ int end = begin + n;
+
+ for (int i = begin, j = 0; i < end; ++i, ++j)
+ {
+ if ((j & 1) == 0)
+ {
+ ycaOut[j].r = ycaIn[i - 13].r * 0.001064 +
+ ycaIn[i - 11].r * -0.003771 +
+ ycaIn[i - 9].r * 0.009801 +
+ ycaIn[i - 7].r * -0.021586 +
+ ycaIn[i - 5].r * 0.043978 +
+ ycaIn[i - 3].r * -0.093067 +
+ ycaIn[i - 1].r * 0.313659 +
+ ycaIn[i ].r * 0.499846 +
+ ycaIn[i + 1].r * 0.313659 +
+ ycaIn[i + 3].r * -0.093067 +
+ ycaIn[i + 5].r * 0.043978 +
+ ycaIn[i + 7].r * -0.021586 +
+ ycaIn[i + 9].r * 0.009801 +
+ ycaIn[i + 11].r * -0.003771 +
+ ycaIn[i + 13].r * 0.001064;
+
+ ycaOut[j].b = ycaIn[i - 13].b * 0.001064 +
+ ycaIn[i - 11].b * -0.003771 +
+ ycaIn[i - 9].b * 0.009801 +
+ ycaIn[i - 7].b * -0.021586 +
+ ycaIn[i - 5].b * 0.043978 +
+ ycaIn[i - 3].b * -0.093067 +
+ ycaIn[i - 1].b * 0.313659 +
+ ycaIn[i ].b * 0.499846 +
+ ycaIn[i + 1].b * 0.313659 +
+ ycaIn[i + 3].b * -0.093067 +
+ ycaIn[i + 5].b * 0.043978 +
+ ycaIn[i + 7].b * -0.021586 +
+ ycaIn[i + 9].b * 0.009801 +
+ ycaIn[i + 11].b * -0.003771 +
+ ycaIn[i + 13].b * 0.001064;
+ }
+
+ ycaOut[j].g = ycaIn[i].g;
+ ycaOut[j].a = ycaIn[i].a;
+ }
+}
+
+
+void
+decimateChromaVert (int n,
+ const Rgba * const ycaIn[N],
+ Rgba ycaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ if ((i & 1) == 0)
+ {
+ ycaOut[i].r = ycaIn[ 0][i].r * 0.001064 +
+ ycaIn[ 2][i].r * -0.003771 +
+ ycaIn[ 4][i].r * 0.009801 +
+ ycaIn[ 6][i].r * -0.021586 +
+ ycaIn[ 8][i].r * 0.043978 +
+ ycaIn[10][i].r * -0.093067 +
+ ycaIn[12][i].r * 0.313659 +
+ ycaIn[13][i].r * 0.499846 +
+ ycaIn[14][i].r * 0.313659 +
+ ycaIn[16][i].r * -0.093067 +
+ ycaIn[18][i].r * 0.043978 +
+ ycaIn[20][i].r * -0.021586 +
+ ycaIn[22][i].r * 0.009801 +
+ ycaIn[24][i].r * -0.003771 +
+ ycaIn[26][i].r * 0.001064;
+
+ ycaOut[i].b = ycaIn[ 0][i].b * 0.001064 +
+ ycaIn[ 2][i].b * -0.003771 +
+ ycaIn[ 4][i].b * 0.009801 +
+ ycaIn[ 6][i].b * -0.021586 +
+ ycaIn[ 8][i].b * 0.043978 +
+ ycaIn[10][i].b * -0.093067 +
+ ycaIn[12][i].b * 0.313659 +
+ ycaIn[13][i].b * 0.499846 +
+ ycaIn[14][i].b * 0.313659 +
+ ycaIn[16][i].b * -0.093067 +
+ ycaIn[18][i].b * 0.043978 +
+ ycaIn[20][i].b * -0.021586 +
+ ycaIn[22][i].b * 0.009801 +
+ ycaIn[24][i].b * -0.003771 +
+ ycaIn[26][i].b * 0.001064;
+ }
+
+ ycaOut[i].g = ycaIn[13][i].g;
+ ycaOut[i].a = ycaIn[13][i].a;
+ }
+}
+
+
+void
+roundYCA (int n,
+ unsigned int roundY,
+ unsigned int roundC,
+ const Rgba ycaIn[/*n*/],
+ Rgba ycaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ ycaOut[i].g = ycaIn[i].g.round (roundY);
+ ycaOut[i].a = ycaIn[i].a;
+
+ if ((i & 1) == 0)
+ {
+ ycaOut[i].r = ycaIn[i].r.round (roundC);
+ ycaOut[i].b = ycaIn[i].b.round (roundC);
+ }
+ }
+}
+
+
+void
+reconstructChromaHoriz (int n,
+ const Rgba ycaIn[/*n+N-1*/],
+ Rgba ycaOut[/*n*/])
+{
+ #ifdef DEBUG
+ assert (ycaIn != ycaOut);
+ #endif
+
+ int begin = N2;
+ int end = begin + n;
+
+ for (int i = begin, j = 0; i < end; ++i, ++j)
+ {
+ if (j & 1)
+ {
+ ycaOut[j].r = ycaIn[i - 13].r * 0.002128 +
+ ycaIn[i - 11].r * -0.007540 +
+ ycaIn[i - 9].r * 0.019597 +
+ ycaIn[i - 7].r * -0.043159 +
+ ycaIn[i - 5].r * 0.087929 +
+ ycaIn[i - 3].r * -0.186077 +
+ ycaIn[i - 1].r * 0.627123 +
+ ycaIn[i + 1].r * 0.627123 +
+ ycaIn[i + 3].r * -0.186077 +
+ ycaIn[i + 5].r * 0.087929 +
+ ycaIn[i + 7].r * -0.043159 +
+ ycaIn[i + 9].r * 0.019597 +
+ ycaIn[i + 11].r * -0.007540 +
+ ycaIn[i + 13].r * 0.002128;
+
+ ycaOut[j].b = ycaIn[i - 13].b * 0.002128 +
+ ycaIn[i - 11].b * -0.007540 +
+ ycaIn[i - 9].b * 0.019597 +
+ ycaIn[i - 7].b * -0.043159 +
+ ycaIn[i - 5].b * 0.087929 +
+ ycaIn[i - 3].b * -0.186077 +
+ ycaIn[i - 1].b * 0.627123 +
+ ycaIn[i + 1].b * 0.627123 +
+ ycaIn[i + 3].b * -0.186077 +
+ ycaIn[i + 5].b * 0.087929 +
+ ycaIn[i + 7].b * -0.043159 +
+ ycaIn[i + 9].b * 0.019597 +
+ ycaIn[i + 11].b * -0.007540 +
+ ycaIn[i + 13].b * 0.002128;
+ }
+ else
+ {
+ ycaOut[j].r = ycaIn[i].r;
+ ycaOut[j].b = ycaIn[i].b;
+ }
+
+ ycaOut[j].g = ycaIn[i].g;
+ ycaOut[j].a = ycaIn[i].a;
+ }
+}
+
+
+void
+reconstructChromaVert (int n,
+ const Rgba * const ycaIn[N],
+ Rgba ycaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ ycaOut[i].r = ycaIn[ 0][i].r * 0.002128 +
+ ycaIn[ 2][i].r * -0.007540 +
+ ycaIn[ 4][i].r * 0.019597 +
+ ycaIn[ 6][i].r * -0.043159 +
+ ycaIn[ 8][i].r * 0.087929 +
+ ycaIn[10][i].r * -0.186077 +
+ ycaIn[12][i].r * 0.627123 +
+ ycaIn[14][i].r * 0.627123 +
+ ycaIn[16][i].r * -0.186077 +
+ ycaIn[18][i].r * 0.087929 +
+ ycaIn[20][i].r * -0.043159 +
+ ycaIn[22][i].r * 0.019597 +
+ ycaIn[24][i].r * -0.007540 +
+ ycaIn[26][i].r * 0.002128;
+
+ ycaOut[i].b = ycaIn[ 0][i].b * 0.002128 +
+ ycaIn[ 2][i].b * -0.007540 +
+ ycaIn[ 4][i].b * 0.019597 +
+ ycaIn[ 6][i].b * -0.043159 +
+ ycaIn[ 8][i].b * 0.087929 +
+ ycaIn[10][i].b * -0.186077 +
+ ycaIn[12][i].b * 0.627123 +
+ ycaIn[14][i].b * 0.627123 +
+ ycaIn[16][i].b * -0.186077 +
+ ycaIn[18][i].b * 0.087929 +
+ ycaIn[20][i].b * -0.043159 +
+ ycaIn[22][i].b * 0.019597 +
+ ycaIn[24][i].b * -0.007540 +
+ ycaIn[26][i].b * 0.002128;
+
+ ycaOut[i].g = ycaIn[13][i].g;
+ ycaOut[i].a = ycaIn[13][i].a;
+ }
+}
+
+
+void
+YCAtoRGBA (const Imath::V3f &yw,
+ int n,
+ const Rgba ycaIn[/*n*/],
+ Rgba rgbaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ const Rgba &in = ycaIn[i];
+ Rgba &out = rgbaOut[i];
+
+ if (in.r == 0 && in.b == 0)
+ {
+ //
+ // Special case -- both chroma channels are 0. To avoid
+ // rounding errors, we explicitly set the output R, G and B
+ // channels equal to the input luminance.
+ //
+ // The special cases here and in RGBAtoYCA() ensure that
+ // converting black-and white images from RGBA to YCA and
+ // back is lossless.
+ //
+
+ out.r = in.g;
+ out.g = in.g;
+ out.b = in.g;
+ out.a = in.a;
+ }
+ else
+ {
+ float Y = in.g;
+ float r = (in.r + 1) * Y;
+ float b = (in.b + 1) * Y;
+ float g = (Y - r * yw.x - b * yw.z) / yw.y;
+
+ out.r = r;
+ out.g = g;
+ out.b = b;
+ out.a = in.a;
+ }
+ }
+}
+
+
+namespace {
+
+inline float
+saturation (const Rgba &in)
+{
+ float rgbMax = max (in.r, max (in.g, in.b));
+ float rgbMin = min (in.r, min (in.g, in.b));
+
+ if (rgbMax > 0)
+ return 1 - rgbMin / rgbMax;
+ else
+ return 0;
+}
+
+
+void
+desaturate (const Rgba &in, float f, const V3f &yw, Rgba &out)
+{
+ float rgbMax = max (in.r, max (in.g, in.b));
+
+ out.r = max (float (rgbMax - (rgbMax - in.r) * f), 0.0f);
+ out.g = max (float (rgbMax - (rgbMax - in.g) * f), 0.0f);
+ out.b = max (float (rgbMax - (rgbMax - in.b) * f), 0.0f);
+ out.a = in.a;
+
+ float Yin = in.r * yw.x + in.g * yw.y + in.b * yw.z;
+ float Yout = out.r * yw.x + out.g * yw.y + out.b * yw.z;
+
+ if (Yout > 0)
+ {
+ out.r *= Yin / Yout;
+ out.g *= Yin / Yout;
+ out.b *= Yin / Yout;
+ }
+}
+
+} // namespace
+
+
+void
+fixSaturation (const Imath::V3f &yw,
+ int n,
+ const Rgba * const rgbaIn[3],
+ Rgba rgbaOut[/*n*/])
+{
+ for (int i = 0; i < n; ++i)
+ {
+ const int i0 = max (i - 1, 0);
+ const int i1 = min (i + 1, n - 1);
+
+ const Rgba &neighbor0 = rgbaIn[0][i0];
+ const Rgba &neighbor1 = rgbaIn[0][i1];
+ const Rgba &neighbor2 = rgbaIn[2][i0];
+ const Rgba &neighbor3 = rgbaIn[2][i1];
+
+ float sMean = min (1.0f, 0.25f * (saturation (neighbor0) +
+ saturation (neighbor1) +
+ saturation (neighbor2) +
+ saturation (neighbor3)));
+
+ const Rgba &in = rgbaIn[1][i];
+ Rgba &out = rgbaOut[i];
+
+ float s = saturation (in);
+
+ if (s > sMean)
+ {
+ float sMax = min (1.0f, 1 - (1 - sMean) * 0.25f);
+
+ if (s > sMax)
+ {
+ desaturate (in, sMax / s, yw, out);
+ continue;
+ }
+ }
+
+ out = in;
+ }
+}
+
+
+} // namespace RgbaYca
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfRgbaYca.h b/Source/OpenEXR/IlmImf/ImfRgbaYca.h
new file mode 100644
index 0000000..4a2743e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRgbaYca.h
@@ -0,0 +1,248 @@
+#ifndef INCLUDED_IMF_RGBA_YCA_H
+#define INCLUDED_IMF_RGBA_YCA_H
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucasfilm
+// Entertainment Company Ltd. Portions contributed and copyright held by
+// others as indicated. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above
+// copyright notice, this list of conditions and the following
+// disclaimer.
+//
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided with
+// the distribution.
+//
+// * Neither the name of Industrial Light & Magic nor the names of
+// any other contributors to this software may be used to endorse or
+// promote products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Conversion between RGBA (red, green, blue alpha)
+// and YCA (luminance, subsampled chroma, alpha) data:
+//
+// Luminance, Y, is computed as a weighted sum of R, G, and B:
+//
+// Y = yw.x * R + yw.y * G + yw.z * B
+//
+// Function computeYw() computes a set of RGB-to-Y weights, yw,
+// from a set of primary and white point chromaticities.
+//
+// Chroma, C, consists of two components, RY and BY:
+//
+// RY = (R - Y) / Y
+// BY = (B - Y) / Y
+//
+// For efficiency, the x and y subsampling rates for chroma are
+// hardwired to 2, and the chroma subsampling and reconstruction
+// filters are fixed 27-pixel wide windowed sinc functions.
+//
+// Starting with an image that has RGBA data for all pixels,
+//
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+// ...
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+// RGBA RGBA RGBA RGBA ... RGBA RGBA
+//
+// function RGBAtoYCA() converts the pixels to YCA format:
+//
+// YCA YCA YCA YCA ... YCA YCA
+// YCA YCA YCA YCA ... YCA YCA
+// YCA YCA YCA YCA ... YCA YCA
+// YCA YCA YCA YCA ... YCA YCA
+// ...
+// YCA YCA YCA YCA ... YCA YCA
+// YCA YCA YCA YCA ... YCA YCA
+//
+// Next, decimateChomaHoriz() eliminates the chroma values from
+// the odd-numbered pixels in every scan line:
+//
+// YCA YA YCA YA ... YCA YA
+// YCA YA YCA YA ... YCA YA
+// YCA YA YCA YA ... YCA YA
+// YCA YA YCA YA ... YCA YA
+// ...
+// YCA YA YCA YA ... YCA YA
+// YCA YA YCA YA ... YCA YA
+//
+// decimateChromaVert() eliminates all chroma values from the
+// odd-numbered scan lines:
+//
+// YCA YA YCA YA ... YCA YA
+// YA YA YA YA ... YA YA
+// YCA YA YCA YA ... YCA YA
+// YA YA YA YA ... YA YA
+// ...
+// YCA YA YCA YA ... YCA YA
+// YA YA YA YA ... YA YA
+//
+// Finally, roundYCA() reduces the precision of the luminance
+// and chroma values so that the pixel data shrink more when
+// they are saved in a compressed file.
+//
+// The output of roundYCA() can be converted back to a set
+// of RGBA pixel data that is visually very similar to the
+// original RGBA image, by calling reconstructChromaHoriz(),
+// reconstructChromaVert(), YCAtoRGBA(), and finally
+// fixSaturation().
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRgba.h>
+#include <ImfChromaticities.h>
+
+namespace Imf {
+namespace RgbaYca {
+
+
+//
+// Width of the chroma subsampling and reconstruction filters
+//
+
+static const int N = 27;
+static const int N2 = N / 2;
+
+
+//
+// Convert a set of primary chromaticities into a set of weighting
+// factors for computing a pixels's luminance, Y, from R, G and B
+//
+
+Imath::V3f computeYw (const Chromaticities &cr);
+
+
+//
+// Convert an array of n RGBA pixels, rgbaIn, to YCA (luminance/chroma/alpha):
+//
+// ycaOut[i].g = Y (rgbaIn[i]);
+// ycaOut[i].r = RY (rgbaIn[i]);
+// ycaOut[i].b = BY (rgbaIn[i]);
+// ycaOut[i].a = aIsValid? rgbaIn[i].a: 1
+//
+// yw is a set of RGB-to-Y weighting factors, as computed by computeYw().
+//
+
+void RGBAtoYCA (const Imath::V3f &yw,
+ int n,
+ bool aIsValid,
+ const Rgba rgbaIn[/*n*/],
+ Rgba ycaOut[/*n*/]);
+
+//
+// Perform horizontal low-pass filtering and subsampling of
+// the chroma channels of an array of n pixels. In order
+// to avoid indexing off the ends of the input array during
+// low-pass filtering, ycaIn must have N2 extra pixels at
+// both ends. Before calling decimateChromaHoriz(), the extra
+// pixels should be filled with copies of the first and last
+// "real" input pixel.
+//
+
+void decimateChromaHoriz (int n,
+ const Rgba ycaIn[/*n+N-1*/],
+ Rgba ycaOut[/*n*/]);
+
+//
+// Perform vertical chroma channel low-pass filtering and subsampling.
+// N scan lines of input pixels are combined into a single scan line
+// of output pixels.
+//
+
+void decimateChromaVert (int n,
+ const Rgba * const ycaIn[N],
+ Rgba ycaOut[/*n*/]);
+
+//
+// Round the luminance and chroma channels of an array of YCA
+// pixels that has already been filtered and subsampled.
+// The signifcands of the pixels' luminance and chroma values
+// are rounded to roundY and roundC bits respectively.
+//
+
+void roundYCA (int n,
+ unsigned int roundY,
+ unsigned int roundC,
+ const Rgba ycaIn[/*n*/],
+ Rgba ycaOut[/*n*/]);
+
+//
+// For a scan line that has valid chroma data only for every other pixel,
+// reconstruct the missing chroma values.
+//
+
+void reconstructChromaHoriz (int n,
+ const Rgba ycaIn[/*n+N-1*/],
+ Rgba ycaOut[/*n*/]);
+
+//
+// For a scan line that has only luminance and no valid chroma data,
+// reconstruct chroma from the surronding N scan lines.
+//
+
+void reconstructChromaVert (int n,
+ const Rgba * const ycaIn[N],
+ Rgba ycaOut[/*n*/]);
+
+//
+// Convert an array of n YCA (luminance/chroma/alpha) pixels to RGBA.
+// This function is the inverse of RGBAtoYCA().
+// yw is a set of RGB-to-Y weighting factors, as computed by computeYw().
+//
+
+void YCAtoRGBA (const Imath::V3f &yw,
+ int n,
+ const Rgba ycaIn[/*n*/],
+ Rgba rgbaOut[/*n*/]);
+
+//
+// Eliminate super-saturated pixels:
+//
+// Converting an image from RGBA to YCA, low-pass filtering chroma,
+// and converting the result back to RGBA can produce pixels with
+// super-saturated colors, where one or two of the RGB components
+// become zero or negative. (The low-pass and reconstruction filters
+// introduce some amount of ringing into the chroma components.
+// This can lead to negative RGB values near high-contrast edges.)
+//
+// The fixSaturation() function finds super-saturated pixels and
+// corrects them by desaturating their colors while maintaining
+// their luminance. fixSaturation() takes three adjacent input
+// scan lines, rgbaIn[0], rgbaIn[1], rgbaIn[2], adjusts the
+// saturation of rgbaIn[1], and stores the result in rgbaOut.
+//
+
+void fixSaturation (const Imath::V3f &yw,
+ int n,
+ const Rgba * const rgbaIn[3],
+ Rgba rgbaOut[/*n*/]);
+
+} // namespace RgbaYca
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfRleCompressor.cpp b/Source/OpenEXR/IlmImf/ImfRleCompressor.cpp
new file mode 100644
index 0000000..cd79609
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRleCompressor.cpp
@@ -0,0 +1,330 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class RleCompressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfRleCompressor.h>
+#include "Iex.h"
+
+namespace Imf {
+namespace {
+
+const int MIN_RUN_LENGTH = 3;
+const int MAX_RUN_LENGTH = 127;
+
+
+//
+// Compress an array of bytes, using run-length encoding,
+// and return the length of the compressed data.
+//
+
+int
+rleCompress (int inLength, const char in[], signed char out[])
+{
+ const char *inEnd = in + inLength;
+ const char *runStart = in;
+ const char *runEnd = in + 1;
+ signed char *outWrite = out;
+
+ while (runStart < inEnd)
+ {
+ while (runEnd < inEnd &&
+ *runStart == *runEnd &&
+ runEnd - runStart - 1 < MAX_RUN_LENGTH)
+ {
+ ++runEnd;
+ }
+
+ if (runEnd - runStart >= MIN_RUN_LENGTH)
+ {
+ //
+ // Compressable run
+ //
+
+ *outWrite++ = (runEnd - runStart) - 1;
+ *outWrite++ = *(signed char *) runStart;
+ runStart = runEnd;
+ }
+ else
+ {
+ //
+ // Uncompressable run
+ //
+
+ while (runEnd < inEnd &&
+ ((runEnd + 1 >= inEnd ||
+ *runEnd != *(runEnd + 1)) ||
+ (runEnd + 2 >= inEnd ||
+ *(runEnd + 1) != *(runEnd + 2))) &&
+ runEnd - runStart < MAX_RUN_LENGTH)
+ {
+ ++runEnd;
+ }
+
+ *outWrite++ = runStart - runEnd;
+
+ while (runStart < runEnd)
+ {
+ *outWrite++ = *(signed char *) (runStart++);
+ }
+ }
+
+ ++runEnd;
+ }
+
+ return outWrite - out;
+}
+
+
+//
+// Uncompress an array of bytes compressed with rleCompress().
+// Returns the length of the oncompressed data, or 0 if the
+// length of the uncompressed data would be more than maxLength.
+//
+
+int
+rleUncompress (int inLength, int maxLength, const signed char in[], char out[])
+{
+ char *outStart = out;
+
+ while (inLength > 0)
+ {
+ if (*in < 0)
+ {
+ int count = -((int)*in++);
+ inLength -= count + 1;
+
+ if (0 > (maxLength -= count))
+ return 0;
+
+ while (count-- > 0)
+ *out++ = *(char *) (in++);
+ }
+ else
+ {
+ int count = *in++;
+ inLength -= 2;
+
+ if (0 > (maxLength -= count + 1))
+ return 0;
+
+ while (count-- >= 0)
+ *out++ = *(char *) in;
+
+ in++;
+ }
+ }
+
+ return out - outStart;
+}
+
+} // namespace
+
+
+RleCompressor::RleCompressor (const Header &hdr, int maxScanLineSize):
+ Compressor (hdr),
+ _maxScanLineSize (maxScanLineSize),
+ _tmpBuffer (0),
+ _outBuffer (0)
+{
+ _tmpBuffer = new char [maxScanLineSize];
+ _outBuffer = new char [maxScanLineSize * 3 / 2];
+}
+
+
+RleCompressor::~RleCompressor ()
+{
+ delete [] _tmpBuffer;
+ delete [] _outBuffer;
+}
+
+
+int
+RleCompressor::numScanLines () const
+{
+ //
+ // This compressor compresses individual scan lines.
+ //
+
+ return 1;
+}
+
+
+int
+RleCompressor::compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ //
+ // Special case ­- empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Reorder the pixel data.
+ //
+
+ {
+ char *t1 = _tmpBuffer;
+ char *t2 = _tmpBuffer + (inSize + 1) / 2;
+ const char *stop = inPtr + inSize;
+
+ while (true)
+ {
+ if (inPtr < stop)
+ *(t1++) = *(inPtr++);
+ else
+ break;
+
+ if (inPtr < stop)
+ *(t2++) = *(inPtr++);
+ else
+ break;
+ }
+ }
+
+ //
+ // Predictor.
+ //
+
+ {
+ unsigned char *t = (unsigned char *) _tmpBuffer + 1;
+ unsigned char *stop = (unsigned char *) _tmpBuffer + inSize;
+ int p = t[-1];
+
+ while (t < stop)
+ {
+ int d = int (t[0]) - p + (128 + 256);
+ p = t[0];
+ t[0] = d;
+ ++t;
+ }
+ }
+
+ //
+ // Run-length encode the data.
+ //
+
+ outPtr = _outBuffer;
+ return rleCompress (inSize, _tmpBuffer, (signed char *) _outBuffer);
+}
+
+
+int
+RleCompressor::uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ //
+ // Special case ­- empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Decode the run-length encoded data
+ //
+
+ int outSize;
+
+ if (0 == (outSize = rleUncompress (inSize, _maxScanLineSize,
+ (const signed char *) inPtr,
+ _tmpBuffer)))
+ {
+ throw Iex::InputExc ("Data decoding (rle) failed.");
+ }
+
+ //
+ // Predictor.
+ //
+
+ {
+ unsigned char *t = (unsigned char *) _tmpBuffer + 1;
+ unsigned char *stop = (unsigned char *) _tmpBuffer + outSize;
+
+ while (t < stop)
+ {
+ int d = int (t[-1]) + int (t[0]) - 128;
+ t[0] = d;
+ ++t;
+ }
+ }
+
+ //
+ // Reorder the pixel data.
+ //
+
+ {
+ const char *t1 = _tmpBuffer;
+ const char *t2 = _tmpBuffer + (outSize + 1) / 2;
+ char *s = _outBuffer;
+ char *stop = s + outSize;
+
+ while (true)
+ {
+ if (s < stop)
+ *(s++) = *(t1++);
+ else
+ break;
+
+ if (s < stop)
+ *(s++) = *(t2++);
+ else
+ break;
+ }
+ }
+
+ outPtr = _outBuffer;
+ return outSize;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfRleCompressor.h b/Source/OpenEXR/IlmImf/ImfRleCompressor.h
new file mode 100644
index 0000000..455c640
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfRleCompressor.h
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_RLE_COMPRESSOR_H
+#define INCLUDED_IMF_RLE_COMPRESSOR_H
+
+//-----------------------------------------------------------------------------
+//
+// class RleCompressor -- performs run-length encoding
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+
+class RleCompressor: public Compressor
+{
+ public:
+
+ RleCompressor (const Header &hdr, int maxScanLineSize);
+ virtual ~RleCompressor ();
+
+ virtual int numScanLines () const;
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+ private:
+
+ int _maxScanLineSize;
+ char * _tmpBuffer;
+ char * _outBuffer;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfScanLineInputFile.cpp b/Source/OpenEXR/IlmImf/ImfScanLineInputFile.cpp
new file mode 100644
index 0000000..add23c2
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfScanLineInputFile.cpp
@@ -0,0 +1,1008 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class ScanLineInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfScanLineInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImfStdIO.h>
+#include <ImfCompressor.h>
+#include "ImathBox.h"
+#include "ImathFun.h"
+#include <ImfXdr.h>
+#include <ImfConvert.h>
+#include <ImfThreading.h>
+#include "IlmThreadPool.h"
+#include "IlmThreadSemaphore.h"
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <string>
+#include <vector>
+#include <assert.h>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::divp;
+using Imath::modp;
+using std::string;
+using std::vector;
+using std::ifstream;
+using std::min;
+using std::max;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+using IlmThread::Semaphore;
+using IlmThread::Task;
+using IlmThread::TaskGroup;
+using IlmThread::ThreadPool;
+
+namespace {
+
+struct InSliceInfo
+{
+ PixelType typeInFrameBuffer;
+ PixelType typeInFile;
+ char * base;
+ size_t xStride;
+ size_t yStride;
+ int xSampling;
+ int ySampling;
+ bool fill;
+ bool skip;
+ double fillValue;
+
+ InSliceInfo (PixelType typeInFrameBuffer = HALF,
+ PixelType typeInFile = HALF,
+ char *base = 0,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ int xSampling = 1,
+ int ySampling = 1,
+ bool fill = false,
+ bool skip = false,
+ double fillValue = 0.0);
+};
+
+
+InSliceInfo::InSliceInfo (PixelType tifb,
+ PixelType tifl,
+ char *b,
+ size_t xs, size_t ys,
+ int xsm, int ysm,
+ bool f, bool s,
+ double fv)
+:
+ typeInFrameBuffer (tifb),
+ typeInFile (tifl),
+ base (b),
+ xStride (xs),
+ yStride (ys),
+ xSampling (xsm),
+ ySampling (ysm),
+ fill (f),
+ skip (s),
+ fillValue (fv)
+{
+ // empty
+}
+
+
+struct LineBuffer
+{
+ const char * uncompressedData;
+ char * buffer;
+ int dataSize;
+ int minY;
+ int maxY;
+ Compressor * compressor;
+ Compressor::Format format;
+ int number;
+ bool hasException;
+ string exception;
+
+ LineBuffer (Compressor * const comp);
+ ~LineBuffer ();
+
+ inline void wait () {_sem.wait();}
+ inline void post () {_sem.post();}
+
+ private:
+
+ Semaphore _sem;
+};
+
+
+LineBuffer::LineBuffer (Compressor *comp):
+ uncompressedData (0),
+ buffer (0),
+ dataSize (0),
+ compressor (comp),
+ format (defaultFormat(compressor)),
+ number (-1),
+ hasException (false),
+ exception (),
+ _sem (1)
+{
+ // empty
+}
+
+
+LineBuffer::~LineBuffer ()
+{
+ delete compressor;
+}
+
+} // namespace
+
+
+struct ScanLineInputFile::Data: public Mutex
+{
+ Header header; // the image header
+ int version; // file's version
+ FrameBuffer frameBuffer; // framebuffer to write into
+ LineOrder lineOrder; // order of the scanlines in file
+ int minX; // data window's min x coord
+ int maxX; // data window's max x coord
+ int minY; // data window's min y coord
+ int maxY; // data window's max x coord
+ vector<Int64> lineOffsets; // stores offsets in file for
+ // each line
+ bool fileIsComplete; // True if no scanlines are missing
+ // in the file
+ int nextLineBufferMinY; // minimum y of the next linebuffer
+ vector<size_t> bytesPerLine; // combined size of a line over all
+ // channels
+ vector<size_t> offsetInLineBuffer; // offset for each scanline in its
+ // linebuffer
+ vector<InSliceInfo> slices; // info about channels in file
+ IStream * is; // file stream to read from
+
+ vector<LineBuffer*> lineBuffers; // each holds one line buffer
+ int linesInBuffer; // number of scanlines each buffer
+ // holds
+ size_t lineBufferSize; // size of the line buffer
+
+ Data (IStream *is, int numThreads);
+ ~Data ();
+
+ inline LineBuffer * getLineBuffer (int number); // hash function from line
+ // buffer indices into our
+ // vector of line buffers
+};
+
+
+ScanLineInputFile::Data::Data (IStream *is, int numThreads):
+ is (is)
+{
+ //
+ // We need at least one lineBuffer, but if threading is used,
+ // to keep n threads busy we need 2*n lineBuffers
+ //
+
+ lineBuffers.resize (max (1, 2 * numThreads));
+}
+
+
+ScanLineInputFile::Data::~Data ()
+{
+ for (size_t i = 0; i < lineBuffers.size(); i++)
+ delete lineBuffers[i];
+}
+
+
+inline LineBuffer *
+ScanLineInputFile::Data::getLineBuffer (int lineBufferNumber)
+{
+ return lineBuffers[lineBufferNumber % lineBuffers.size()];
+}
+
+
+namespace {
+
+
+void
+reconstructLineOffsets (IStream &is,
+ LineOrder lineOrder,
+ vector<Int64> &lineOffsets)
+{
+ Int64 position = is.tellg();
+
+ try
+ {
+ for (unsigned int i = 0; i < lineOffsets.size(); i++)
+ {
+ Int64 lineOffset = is.tellg();
+
+ int y;
+ Xdr::read <StreamIO> (is, y);
+
+ int dataSize;
+ Xdr::read <StreamIO> (is, dataSize);
+
+ Xdr::skip <StreamIO> (is, dataSize);
+
+ if (lineOrder == INCREASING_Y)
+ lineOffsets[i] = lineOffset;
+ else
+ lineOffsets[lineOffsets.size() - i - 1] = lineOffset;
+ }
+ }
+ catch (...)
+ {
+ //
+ // Suppress all exceptions. This functions is
+ // called only to reconstruct the line offset
+ // table for incomplete files, and exceptions
+ // are likely.
+ //
+ }
+
+ is.clear();
+ is.seekg (position);
+}
+
+
+void
+readLineOffsets (IStream &is,
+ LineOrder lineOrder,
+ vector<Int64> &lineOffsets,
+ bool &complete)
+{
+ for (unsigned int i = 0; i < lineOffsets.size(); i++)
+ {
+ Xdr::read <StreamIO> (is, lineOffsets[i]);
+ }
+
+ complete = true;
+
+ for (unsigned int i = 0; i < lineOffsets.size(); i++)
+ {
+ if (lineOffsets[i] <= 0)
+ {
+ //
+ // Invalid data in the line offset table mean that
+ // the file is probably incomplete (the table is
+ // the last thing written to the file). Either
+ // some process is still busy writing the file,
+ // or writing the file was aborted.
+ //
+ // We should still be able to read the existing
+ // parts of the file. In order to do this, we
+ // have to make a sequential scan over the scan
+ // line data to reconstruct the line offset table.
+ //
+
+ complete = false;
+ reconstructLineOffsets (is, lineOrder, lineOffsets);
+ break;
+ }
+ }
+}
+
+
+void
+readPixelData (ScanLineInputFile::Data *ifd,
+ int minY,
+ char *&buffer,
+ int &dataSize)
+{
+ //
+ // Read a single line buffer from the input file.
+ //
+ // If the input file is not memory-mapped, we copy the pixel data into
+ // into the array pointed to by buffer. If the file is memory-mapped,
+ // then we change where buffer points to instead of writing into the
+ // array (hence buffer needs to be a reference to a char *).
+ //
+
+ Int64 lineOffset =
+ ifd->lineOffsets[(minY - ifd->minY) / ifd->linesInBuffer];
+
+ if (lineOffset == 0)
+ THROW (Iex::InputExc, "Scan line " << minY << " is missing.");
+
+ //
+ // Seek to the start of the scan line in the file,
+ // if necessary.
+ //
+
+ if (ifd->nextLineBufferMinY != minY)
+ ifd->is->seekg (lineOffset);
+
+ //
+ // Read the data block's header.
+ //
+
+ int yInFile;
+
+ Xdr::read <StreamIO> (*ifd->is, yInFile);
+ Xdr::read <StreamIO> (*ifd->is, dataSize);
+
+ if (yInFile != minY)
+ throw Iex::InputExc ("Unexpected data block y coordinate.");
+
+ if (dataSize > (int) ifd->lineBufferSize)
+ throw Iex::InputExc ("Unexpected data block length.");
+
+ //
+ // Read the pixel data.
+ //
+
+ if (ifd->is->isMemoryMapped ())
+ buffer = ifd->is->readMemoryMapped (dataSize);
+ else
+ ifd->is->read (buffer, dataSize);
+
+ //
+ // Keep track of which scan line is the next one in
+ // the file, so that we can avoid redundant seekg()
+ // operations (seekg() can be fairly expensive).
+ //
+
+ if (ifd->lineOrder == INCREASING_Y)
+ ifd->nextLineBufferMinY = minY + ifd->linesInBuffer;
+ else
+ ifd->nextLineBufferMinY = minY - ifd->linesInBuffer;
+}
+
+
+//
+// A LineBufferTask encapsulates the task uncompressing a set of
+// scanlines (line buffer) and copying them into the frame buffer.
+//
+
+class LineBufferTask : public Task
+{
+ public:
+
+ LineBufferTask (TaskGroup *group,
+ ScanLineInputFile::Data *ifd,
+ LineBuffer *lineBuffer,
+ int scanLineMin,
+ int scanLineMax);
+
+ virtual ~LineBufferTask ();
+
+ virtual void execute ();
+
+ private:
+
+ ScanLineInputFile::Data * _ifd;
+ LineBuffer * _lineBuffer;
+ int _scanLineMin;
+ int _scanLineMax;
+};
+
+
+LineBufferTask::LineBufferTask
+ (TaskGroup *group,
+ ScanLineInputFile::Data *ifd,
+ LineBuffer *lineBuffer,
+ int scanLineMin,
+ int scanLineMax)
+:
+ Task (group),
+ _ifd (ifd),
+ _lineBuffer (lineBuffer),
+ _scanLineMin (scanLineMin),
+ _scanLineMax (scanLineMax)
+{
+ // empty
+}
+
+
+LineBufferTask::~LineBufferTask ()
+{
+ //
+ // Signal that the line buffer is now free
+ //
+
+ _lineBuffer->post ();
+}
+
+
+void
+LineBufferTask::execute ()
+{
+ try
+ {
+ //
+ // Uncompress the data, if necessary
+ //
+
+ if (_lineBuffer->uncompressedData == 0)
+ {
+ int uncompressedSize = 0;
+ int maxY = min (_lineBuffer->maxY, _ifd->maxY);
+
+ for (int i = _lineBuffer->minY - _ifd->minY;
+ i <= maxY - _ifd->minY;
+ ++i)
+ {
+ uncompressedSize += (int) _ifd->bytesPerLine[i];
+ }
+
+ if (_lineBuffer->compressor &&
+ _lineBuffer->dataSize < uncompressedSize)
+ {
+ _lineBuffer->format = _lineBuffer->compressor->format();
+
+ _lineBuffer->dataSize = _lineBuffer->compressor->uncompress
+ (_lineBuffer->buffer, _lineBuffer->dataSize,
+ _lineBuffer->minY, _lineBuffer->uncompressedData);
+ }
+ else
+ {
+ //
+ // If the line is uncompressed, it's in XDR format,
+ // regardless of the compressor's output format.
+ //
+
+ _lineBuffer->format = Compressor::XDR;
+ _lineBuffer->uncompressedData = _lineBuffer->buffer;
+ }
+ }
+
+ int yStart, yStop, dy;
+
+ if (_ifd->lineOrder == INCREASING_Y)
+ {
+ yStart = _scanLineMin;
+ yStop = _scanLineMax + 1;
+ dy = 1;
+ }
+ else
+ {
+ yStart = _scanLineMax;
+ yStop = _scanLineMin - 1;
+ dy = -1;
+ }
+
+ for (int y = yStart; y != yStop; y += dy)
+ {
+ //
+ // Convert one scan line's worth of pixel data back
+ // from the machine-independent representation, and
+ // store the result in the frame buffer.
+ //
+
+ const char *readPtr = _lineBuffer->uncompressedData +
+ _ifd->offsetInLineBuffer[y - _ifd->minY];
+
+ //
+ // Iterate over all image channels.
+ //
+
+ for (unsigned int i = 0; i < _ifd->slices.size(); ++i)
+ {
+ //
+ // Test if scan line y of this channel contains any data
+ // (the scan line contains data only if y % ySampling == 0).
+ //
+
+ const InSliceInfo &slice = _ifd->slices[i];
+
+ if (modp (y, slice.ySampling) != 0)
+ continue;
+
+ //
+ // Find the x coordinates of the leftmost and rightmost
+ // sampled pixels (i.e. pixels within the data window
+ // for which x % xSampling == 0).
+ //
+
+ int dMinX = divp (_ifd->minX, slice.xSampling);
+ int dMaxX = divp (_ifd->maxX, slice.xSampling);
+
+ //
+ // Fill the frame buffer with pixel data.
+ //
+
+ if (slice.skip)
+ {
+ //
+ // The file contains data for this channel, but
+ // the frame buffer contains no slice for this channel.
+ //
+
+ skipChannel (readPtr, slice.typeInFile, dMaxX - dMinX + 1);
+ }
+ else
+ {
+ //
+ // The frame buffer contains a slice for this channel.
+ //
+
+ char *linePtr = slice.base +
+ divp (y, slice.ySampling) *
+ slice.yStride;
+
+ char *writePtr = linePtr + dMinX * slice.xStride;
+ char *endPtr = linePtr + dMaxX * slice.xStride;
+
+ copyIntoFrameBuffer (readPtr, writePtr, endPtr,
+ slice.xStride, slice.fill,
+ slice.fillValue, _lineBuffer->format,
+ slice.typeInFrameBuffer,
+ slice.typeInFile);
+ }
+ }
+ }
+ }
+ catch (std::exception &e)
+ {
+ if (!_lineBuffer->hasException)
+ {
+ _lineBuffer->exception = e.what();
+ _lineBuffer->hasException = true;
+ }
+ }
+ catch (...)
+ {
+ if (!_lineBuffer->hasException)
+ {
+ _lineBuffer->exception = "unrecognized exception";
+ _lineBuffer->hasException = true;
+ }
+ }
+}
+
+
+LineBufferTask *
+newLineBufferTask
+ (TaskGroup *group,
+ ScanLineInputFile::Data *ifd,
+ int number,
+ int scanLineMin,
+ int scanLineMax)
+{
+ //
+ // Wait for a line buffer to become available, fill the line
+ // buffer with raw data from the file if necessary, and create
+ // a new LineBufferTask whose execute() method will uncompress
+ // the contents of the buffer and copy the pixels into the
+ // frame buffer.
+ //
+
+ LineBuffer *lineBuffer = ifd->getLineBuffer (number);
+
+ try
+ {
+ lineBuffer->wait ();
+
+ if (lineBuffer->number != number)
+ {
+ lineBuffer->minY = ifd->minY + number * ifd->linesInBuffer;
+ lineBuffer->maxY = lineBuffer->minY + ifd->linesInBuffer - 1;
+
+ lineBuffer->number = number;
+ lineBuffer->uncompressedData = 0;
+
+ readPixelData (ifd, lineBuffer->minY,
+ lineBuffer->buffer,
+ lineBuffer->dataSize);
+ }
+ }
+ catch (...)
+ {
+ //
+ // Reading from the file caused an exception.
+ // Signal that the line buffer is free, and
+ // re-throw the exception.
+ //
+
+ lineBuffer->number = -1;
+ lineBuffer->post();
+ throw;
+ }
+
+ scanLineMin = max (lineBuffer->minY, scanLineMin);
+ scanLineMax = min (lineBuffer->maxY, scanLineMax);
+
+ return new LineBufferTask (group, ifd, lineBuffer,
+ scanLineMin, scanLineMax);
+}
+
+} // namespace
+
+
+ScanLineInputFile::ScanLineInputFile
+ (const Header &header,
+ IStream *is,
+ int numThreads)
+:
+ _data (new Data (is, numThreads))
+{
+ try
+ {
+ _data->header = header;
+
+ _data->lineOrder = _data->header.lineOrder();
+
+ const Box2i &dataWindow = _data->header.dataWindow();
+
+ _data->minX = dataWindow.min.x;
+ _data->maxX = dataWindow.max.x;
+ _data->minY = dataWindow.min.y;
+ _data->maxY = dataWindow.max.y;
+
+ size_t maxBytesPerLine = bytesPerLineTable (_data->header,
+ _data->bytesPerLine);
+
+ for (size_t i = 0; i < _data->lineBuffers.size(); i++)
+ {
+ _data->lineBuffers[i] = new LineBuffer (newCompressor
+ (_data->header.compression(),
+ maxBytesPerLine,
+ _data->header));
+ }
+
+ _data->linesInBuffer =
+ numLinesInBuffer (_data->lineBuffers[0]->compressor);
+
+ _data->lineBufferSize = maxBytesPerLine * _data->linesInBuffer;
+
+ if (!_data->is->isMemoryMapped())
+ for (size_t i = 0; i < _data->lineBuffers.size(); i++)
+ _data->lineBuffers[i]->buffer = new char[_data->lineBufferSize];
+
+ _data->nextLineBufferMinY = _data->minY - 1;
+
+ offsetInLineBufferTable (_data->bytesPerLine,
+ _data->linesInBuffer,
+ _data->offsetInLineBuffer);
+
+ int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y +
+ _data->linesInBuffer) / _data->linesInBuffer;
+
+ _data->lineOffsets.resize (lineOffsetSize);
+
+ readLineOffsets (*_data->is,
+ _data->lineOrder,
+ _data->lineOffsets,
+ _data->fileIsComplete);
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+ScanLineInputFile::~ScanLineInputFile ()
+{
+ if (!_data->is->isMemoryMapped())
+ for (size_t i = 0; i < _data->lineBuffers.size(); i++)
+ delete [] _data->lineBuffers[i]->buffer;
+
+ delete _data;
+}
+
+
+const char *
+ScanLineInputFile::fileName () const
+{
+ return _data->is->fileName();
+}
+
+
+const Header &
+ScanLineInputFile::header () const
+{
+ return _data->header;
+}
+
+
+int
+ScanLineInputFile::version () const
+{
+ return _data->version;
+}
+
+
+void
+ScanLineInputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
+{
+ Lock lock (*_data);
+
+ //
+ // Check if the new frame buffer descriptor is
+ // compatible with the image file header.
+ //
+
+ const ChannelList &channels = _data->header.channels();
+
+ for (FrameBuffer::ConstIterator j = frameBuffer.begin();
+ j != frameBuffer.end();
+ ++j)
+ {
+ ChannelList::ConstIterator i = channels.find (j.name());
+
+ if (i == channels.end())
+ continue;
+
+ if (i.channel().xSampling != j.slice().xSampling ||
+ i.channel().ySampling != j.slice().ySampling)
+ THROW (Iex::ArgExc, "X and/or y subsampling factors "
+ "of \"" << i.name() << "\" channel "
+ "of input file \"" << fileName() << "\" are "
+ "not compatible with the frame buffer's "
+ "subsampling factors.");
+ }
+
+ //
+ // Initialize the slice table for readPixels().
+ //
+
+ vector<InSliceInfo> slices;
+ ChannelList::ConstIterator i = channels.begin();
+
+ for (FrameBuffer::ConstIterator j = frameBuffer.begin();
+ j != frameBuffer.end();
+ ++j)
+ {
+ while (i != channels.end() && strcmp (i.name(), j.name()) < 0)
+ {
+ //
+ // Channel i is present in the file but not
+ // in the frame buffer; data for channel i
+ // will be skipped during readPixels().
+ //
+
+ slices.push_back (InSliceInfo (i.channel().type,
+ i.channel().type,
+ 0, // base
+ 0, // xStride
+ 0, // yStride
+ i.channel().xSampling,
+ i.channel().ySampling,
+ false, // fill
+ true, // skip
+ 0.0)); // fillValue
+ ++i;
+ }
+
+ bool fill = false;
+
+ if (i == channels.end() || strcmp (i.name(), j.name()) > 0)
+ {
+ //
+ // Channel i is present in the frame buffer, but not in the file.
+ // In the frame buffer, slice j will be filled with a default value.
+ //
+
+ fill = true;
+ }
+
+ slices.push_back (InSliceInfo (j.slice().type,
+ fill? j.slice().type:
+ i.channel().type,
+ j.slice().base,
+ j.slice().xStride,
+ j.slice().yStride,
+ j.slice().xSampling,
+ j.slice().ySampling,
+ fill,
+ false, // skip
+ j.slice().fillValue));
+
+ if (i != channels.end() && !fill)
+ ++i;
+ }
+
+ //
+ // Store the new frame buffer.
+ //
+
+ _data->frameBuffer = frameBuffer;
+ _data->slices = slices;
+}
+
+
+const FrameBuffer &
+ScanLineInputFile::frameBuffer () const
+{
+ Lock lock (*_data);
+ return _data->frameBuffer;
+}
+
+
+bool
+ScanLineInputFile::isComplete () const
+{
+ return _data->fileIsComplete;
+}
+
+
+void
+ScanLineInputFile::readPixels (int scanLine1, int scanLine2)
+{
+ try
+ {
+ Lock lock (*_data);
+
+ if (_data->slices.size() == 0)
+ throw Iex::ArgExc ("No frame buffer specified "
+ "as pixel data destination.");
+
+ int scanLineMin = min (scanLine1, scanLine2);
+ int scanLineMax = max (scanLine1, scanLine2);
+
+ if (scanLineMin < _data->minY || scanLineMax > _data->maxY)
+ throw Iex::ArgExc ("Tried to read scan line outside "
+ "the image file's data window.");
+
+ //
+ // We impose a numbering scheme on the lineBuffers where the first
+ // scanline is contained in lineBuffer 1.
+ //
+ // Determine the first and last lineBuffer numbers in this scanline
+ // range. We always attempt to read the scanlines in the order that
+ // they are stored in the file.
+ //
+
+ int start, stop, dl;
+
+ if (_data->lineOrder == INCREASING_Y)
+ {
+ start = (scanLineMin - _data->minY) / _data->linesInBuffer;
+ stop = (scanLineMax - _data->minY) / _data->linesInBuffer + 1;
+ dl = 1;
+ }
+ else
+ {
+ start = (scanLineMax - _data->minY) / _data->linesInBuffer;
+ stop = (scanLineMin - _data->minY) / _data->linesInBuffer - 1;
+ dl = -1;
+ }
+
+ //
+ // Create a task group for all line buffer tasks. When the
+ // task group goes out of scope, the destructor waits until
+ // all tasks are complete.
+ //
+
+ {
+ TaskGroup taskGroup;
+
+ //
+ // Add the line buffer tasks.
+ //
+ // The tasks will execute in the order that they are created
+ // because we lock the line buffers during construction and the
+ // constructors are called by the main thread. Hence, in order
+ // for a successive task to execute the previous task which
+ // used that line buffer must have completed already.
+ //
+
+ for (int l = start; l != stop; l += dl)
+ {
+ ThreadPool::addGlobalTask (newLineBufferTask (&taskGroup,
+ _data, l,
+ scanLineMin,
+ scanLineMax));
+ }
+
+ //
+ // finish all tasks
+ //
+ }
+
+ //
+ // Exeption handling:
+ //
+ // LineBufferTask::execute() may have encountered exceptions, but
+ // those exceptions occurred in another thread, not in the thread
+ // that is executing this call to ScanLineInputFile::readPixels().
+ // LineBufferTask::execute() has caught all exceptions and stored
+ // the exceptions' what() strings in the line buffers.
+ // Now we check if any line buffer contains a stored exception; if
+ // this is the case then we re-throw the exception in this thread.
+ // (It is possible that multiple line buffers contain stored
+ // exceptions. We re-throw the first exception we find and
+ // ignore all others.)
+ //
+
+ const string *exception = 0;
+
+ for (int i = 0; i < _data->lineBuffers.size(); ++i)
+ {
+ LineBuffer *lineBuffer = _data->lineBuffers[i];
+
+ if (lineBuffer->hasException && !exception)
+ exception = &lineBuffer->exception;
+
+ lineBuffer->hasException = false;
+ }
+
+ if (exception)
+ throw Iex::IoExc (*exception);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading pixel data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+ScanLineInputFile::readPixels (int scanLine)
+{
+ readPixels (scanLine, scanLine);
+}
+
+
+void
+ScanLineInputFile::rawPixelData (int firstScanLine,
+ const char *&pixelData,
+ int &pixelDataSize)
+{
+ try
+ {
+ Lock lock (*_data);
+
+ if (firstScanLine < _data->minY || firstScanLine > _data->maxY)
+ {
+ throw Iex::ArgExc ("Tried to read scan line outside "
+ "the image file's data window.");
+ }
+
+ int minY = lineBufferMinY
+ (firstScanLine, _data->minY, _data->linesInBuffer);
+
+ readPixelData
+ (_data, minY, _data->lineBuffers[0]->buffer, pixelDataSize);
+
+ pixelData = _data->lineBuffers[0]->buffer;
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading pixel data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfScanLineInputFile.h b/Source/OpenEXR/IlmImf/ImfScanLineInputFile.h
new file mode 100644
index 0000000..02b36e2
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfScanLineInputFile.h
@@ -0,0 +1,172 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_SCAN_LINE_INPUT_FILE_H
+#define INCLUDED_IMF_SCAN_LINE_INPUT_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// class ScanLineInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+
+class ScanLineInputFile
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ ScanLineInputFile (const Header &header, IStream *is,
+ int numThreads = globalThreadCount());
+
+
+ //-----------------------------------------
+ // Destructor -- deallocates internal data
+ // structures, but does not close the file.
+ //-----------------------------------------
+
+ virtual ~ScanLineInputFile ();
+
+
+ //------------------------
+ // Access to the file name
+ //------------------------
+
+ const char * fileName () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+
+
+ //----------------------------------
+ // Access to the file format version
+ //----------------------------------
+
+ int version () const;
+
+
+ //-----------------------------------------------------------
+ // Set the current frame buffer -- copies the FrameBuffer
+ // object into the InputFile object.
+ //
+ // The current frame buffer is the destination for the pixel
+ // data read from the file. The current frame buffer must be
+ // set at least once before readPixels() is called.
+ // The current frame buffer can be changed after each call
+ // to readPixels().
+ //-----------------------------------------------------------
+
+ void setFrameBuffer (const FrameBuffer &frameBuffer);
+
+
+ //-----------------------------------
+ // Access to the current frame buffer
+ //-----------------------------------
+
+ const FrameBuffer & frameBuffer () const;
+
+
+ //---------------------------------------------------------------
+ // Check if the file is complete:
+ //
+ // isComplete() returns true if all pixels in the data window are
+ // present in the input file, or false if any pixels are missing.
+ // (Another program may still be busy writing the file, or file
+ // writing may have been aborted prematurely.)
+ //---------------------------------------------------------------
+
+ bool isComplete () const;
+
+
+ //---------------------------------------------------------------
+ // Read pixel data:
+ //
+ // readPixels(s1,s2) reads all scan lines with y coordinates
+ // in the interval [min (s1, s2), max (s1, s2)] from the file,
+ // and stores them in the current frame buffer.
+ //
+ // Both s1 and s2 must be within the interval
+ // [header().dataWindow().min.y, header.dataWindow().max.y]
+ //
+ // The scan lines can be read from the file in random order, and
+ // individual scan lines may be skipped or read multiple times.
+ // For maximum efficiency, the scan lines should be read in the
+ // order in which they were written to the file.
+ //
+ // readPixels(s) calls readPixels(s,s).
+ //
+ // If threading is enabled, readPixels (s1, s2) tries to perform
+ // decopmression of multiple scanlines in parallel.
+ //
+ //---------------------------------------------------------------
+
+ void readPixels (int scanLine1, int scanLine2);
+ void readPixels (int scanLine);
+
+
+ //----------------------------------------------
+ // Read a block of raw pixel data from the file,
+ // without uncompressing it (this function is
+ // used to implement OutputFile::copyPixels()).
+ //----------------------------------------------
+
+ void rawPixelData (int firstScanLine,
+ const char *&pixelData,
+ int &pixelDataSize);
+
+ struct Data;
+
+ private:
+
+ Data * _data;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfStandardAttributes.cpp b/Source/OpenEXR/IlmImf/ImfStandardAttributes.cpp
new file mode 100644
index 0000000..dcab918
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStandardAttributes.cpp
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2003, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Optional Standard Attributes
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfStandardAttributes.h>
+
+
+#define IMF_STRING(name) #name
+
+#define IMF_STD_ATTRIBUTE_IMP(name,suffix,type) \
+ \
+ void \
+ add##suffix (Header &header, const type &value) \
+ { \
+ header.insert (IMF_STRING (name), TypedAttribute<type> (value)); \
+ } \
+ \
+ bool \
+ has##suffix (const Header &header) \
+ { \
+ return header.findTypedAttribute <TypedAttribute <type> > \
+ (IMF_STRING (name)) != 0; \
+ } \
+ \
+ const TypedAttribute<type> & \
+ name##Attribute (const Header &header) \
+ { \
+ return header.typedAttribute <TypedAttribute <type> > \
+ (IMF_STRING (name)); \
+ } \
+ \
+ TypedAttribute<type> & \
+ name##Attribute (Header &header) \
+ { \
+ return header.typedAttribute <TypedAttribute <type> > \
+ (IMF_STRING (name)); \
+ } \
+ \
+ const type & \
+ name (const Header &header) \
+ { \
+ return name##Attribute(header).value(); \
+ } \
+ \
+ type & \
+ name (Header &header) \
+ { \
+ return name##Attribute(header).value(); \
+ }
+
+
+namespace Imf {
+
+
+IMF_STD_ATTRIBUTE_IMP (chromaticities, Chromaticities, Chromaticities)
+IMF_STD_ATTRIBUTE_IMP (whiteLuminance, WhiteLuminance, float)
+IMF_STD_ATTRIBUTE_IMP (adoptedNeutral, AdoptedNeutral, Imath::V2f)
+IMF_STD_ATTRIBUTE_IMP (renderingTransform, RenderingTransform, std::string)
+IMF_STD_ATTRIBUTE_IMP (lookModTransform, LookModTransform, std::string)
+IMF_STD_ATTRIBUTE_IMP (xDensity, XDensity, float)
+IMF_STD_ATTRIBUTE_IMP (owner, Owner, std::string)
+IMF_STD_ATTRIBUTE_IMP (comments, Comments, std::string)
+IMF_STD_ATTRIBUTE_IMP (capDate, CapDate, std::string)
+IMF_STD_ATTRIBUTE_IMP (utcOffset, UtcOffset, float)
+IMF_STD_ATTRIBUTE_IMP (longitude, Longitude, float)
+IMF_STD_ATTRIBUTE_IMP (latitude, Latitude, float)
+IMF_STD_ATTRIBUTE_IMP (altitude, Altitude, float)
+IMF_STD_ATTRIBUTE_IMP (focus, Focus, float)
+IMF_STD_ATTRIBUTE_IMP (expTime, ExpTime, float)
+IMF_STD_ATTRIBUTE_IMP (aperture, Aperture, float)
+IMF_STD_ATTRIBUTE_IMP (isoSpeed, IsoSpeed, float)
+IMF_STD_ATTRIBUTE_IMP (envmap, Envmap, Envmap)
+IMF_STD_ATTRIBUTE_IMP (keyCode, KeyCode, KeyCode)
+IMF_STD_ATTRIBUTE_IMP (timeCode, TimeCode, TimeCode)
+IMF_STD_ATTRIBUTE_IMP (wrapmodes, Wrapmodes, std::string)
+IMF_STD_ATTRIBUTE_IMP (framesPerSecond, FramesPerSecond, Rational)
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfStandardAttributes.h b/Source/OpenEXR/IlmImf/ImfStandardAttributes.h
new file mode 100644
index 0000000..f45a5a7
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStandardAttributes.h
@@ -0,0 +1,291 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_STANDARD_ATTRIBUTES_H
+#define INCLUDED_IMF_STANDARD_ATTRIBUTES_H
+
+//-----------------------------------------------------------------------------
+//
+// Optional Standard Attributes -- these attributes are "optional"
+// because not every image file header has them, but they define a
+// "standard" way to represent commonly used data in the file header.
+//
+// For each attribute, with name "foo", and type "T", the following
+// functions are automatically generated via macros:
+//
+// void addFoo (Header &header, const T &value);
+// bool hasFoo (const Header &header);
+// const TypedAttribute<T> & fooAttribute (const Header &header);
+// TypedAttribute<T> & fooAttribute (Header &header);
+// const T & foo (const Header &Header);
+// T & foo (Header &Header);
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFloatAttribute.h>
+#include <ImfStringAttribute.h>
+#include <ImfChromaticitiesAttribute.h>
+#include <ImfEnvmapAttribute.h>
+#include <ImfKeyCodeAttribute.h>
+#include <ImfTimeCodeAttribute.h>
+#include <ImfRationalAttribute.h>
+#include <ImfVecAttribute.h>
+
+
+#define IMF_STD_ATTRIBUTE_DEF(name,suffix,type) \
+ \
+ void add##suffix (Header &header, const type &v); \
+ bool has##suffix (const Header &header); \
+ const TypedAttribute<type> & name##Attribute (const Header &header); \
+ TypedAttribute<type> & name##Attribute (Header &header); \
+ const type & name (const Header &header); \
+ type & name (Header &header);
+
+
+namespace Imf {
+
+//
+// chromaticities -- for RGB images, specifies the CIE (x,y)
+// chromaticities of the primaries and the white point
+//
+
+IMF_STD_ATTRIBUTE_DEF (chromaticities, Chromaticities, Chromaticities)
+
+
+//
+// whiteLuminance -- for RGB images, defines the luminance, in Nits
+// (candelas per square meter) of the RGB value (1.0, 1.0, 1.0).
+//
+// If the chromaticities and the whiteLuminance of an RGB image are
+// known, then it is possible to convert the image's pixels from RGB
+// to CIE XYZ tristimulus values (see function RGBtoXYZ() in header
+// file ImfChromaticities.h).
+//
+//
+
+IMF_STD_ATTRIBUTE_DEF (whiteLuminance, WhiteLuminance, float)
+
+
+//
+// adoptedNeutral -- specifies the CIE (x,y) coordinates that should
+// be considered neutral during color rendering. Pixels in the image
+// file whose (x,y) coordinates match the adoptedNeutral value should
+// be mapped to neutral values on the display.
+//
+
+IMF_STD_ATTRIBUTE_DEF (adoptedNeutral, AdoptedNeutral, Imath::V2f)
+
+
+//
+// renderingTransform, lookModTransform -- specify the names of the
+// CTL functions that implements the intended color rendering and look
+// modification transforms for this image.
+//
+
+IMF_STD_ATTRIBUTE_DEF (renderingTransform, RenderingTransform, std::string)
+IMF_STD_ATTRIBUTE_DEF (lookModTransform, LookModTransform, std::string)
+
+
+//
+// xDensity -- horizontal output density, in pixels per inch.
+// The image's vertical output density is xDensity * pixelAspectRatio.
+//
+
+IMF_STD_ATTRIBUTE_DEF (xDensity, XDensity, float)
+
+
+//
+// owner -- name of the owner of the image
+//
+
+IMF_STD_ATTRIBUTE_DEF (owner, Owner, std::string)
+
+
+//
+// comments -- additional image information in human-readable
+// form, for example a verbal description of the image
+//
+
+IMF_STD_ATTRIBUTE_DEF (comments, Comments, std::string)
+
+
+//
+// capDate -- the date when the image was created or captured,
+// in local time, and formatted as
+//
+// YYYY:MM:DD hh:mm:ss
+//
+// where YYYY is the year (4 digits, e.g. 2003), MM is the month
+// (2 digits, 01, 02, ... 12), DD is the day of the month (2 digits,
+// 01, 02, ... 31), hh is the hour (2 digits, 00, 01, ... 23), mm
+// is the minute, and ss is the second (2 digits, 00, 01, ... 59).
+//
+//
+
+IMF_STD_ATTRIBUTE_DEF (capDate, CapDate, std::string)
+
+
+//
+// utcOffset -- offset of local time at capDate from
+// Universal Coordinated Time (UTC), in seconds:
+//
+// UTC == local time + utcOffset
+//
+
+IMF_STD_ATTRIBUTE_DEF (utcOffset, UtcOffset, float)
+
+
+//
+// longitude, latitude, altitude -- for images of real objects, the
+// location where the image was recorded. Longitude and latitude are
+// in degrees east of Greenwich and north of the equator. Altitude
+// is in meters above sea level. For example, Kathmandu, Nepal is
+// at longitude 85.317, latitude 27.717, altitude 1305.
+//
+
+IMF_STD_ATTRIBUTE_DEF (longitude, Longitude, float)
+IMF_STD_ATTRIBUTE_DEF (latitude, Latitude, float)
+IMF_STD_ATTRIBUTE_DEF (altitude, Altitude, float)
+
+
+//
+// focus -- the camera's focus distance, in meters
+//
+
+IMF_STD_ATTRIBUTE_DEF (focus, Focus, float)
+
+
+//
+// exposure -- exposure time, in seconds
+//
+
+IMF_STD_ATTRIBUTE_DEF (expTime, ExpTime, float)
+
+
+//
+// aperture -- the camera's lens aperture, in f-stops (focal length
+// of the lens divided by the diameter of the iris opening)
+//
+
+IMF_STD_ATTRIBUTE_DEF (aperture, Aperture, float)
+
+
+//
+// isoSpeed -- the ISO speed of the film or image sensor
+// that was used to record the image
+//
+
+IMF_STD_ATTRIBUTE_DEF (isoSpeed, IsoSpeed, float)
+
+
+//
+// envmap -- if this attribute is present, the image represents
+// an environment map. The attribute's value defines how 3D
+// directions are mapped to 2D pixel locations. For details
+// see header file ImfEnvmap.h
+//
+
+IMF_STD_ATTRIBUTE_DEF (envmap, Envmap, Envmap)
+
+
+//
+// keyCode -- for motion picture film frames. Identifies film
+// manufacturer, film type, film roll and frame position within
+// the roll.
+//
+
+IMF_STD_ATTRIBUTE_DEF (keyCode, KeyCode, KeyCode)
+
+
+//
+// timeCode -- time and control code
+//
+
+IMF_STD_ATTRIBUTE_DEF (timeCode, TimeCode, TimeCode)
+
+
+//
+// wrapmodes -- determines how texture map images are extrapolated.
+// If an OpenEXR file is used as a texture map for 3D rendering,
+// texture coordinates (0.0, 0.0) and (1.0, 1.0) correspond to
+// the upper left and lower right corners of the data window.
+// If the image is mapped onto a surface with texture coordinates
+// outside the zero-to-one range, then the image must be extrapolated.
+// This attribute tells the renderer how to do this extrapolation.
+// The attribute contains either a pair of comma-separated keywords,
+// to specify separate extrapolation modes for the horizontal and
+// vertical directions; or a single keyword, to specify extrapolation
+// in both directions (e.g. "clamp,periodic" or "clamp"). Extra white
+// space surrounding the keywords is allowed, but should be ignored
+// by the renderer ("clamp, black " is equivalent to "clamp,black").
+// The keywords listed below are predefined; some renderers may support
+// additional extrapolation modes:
+//
+// black pixels outside the zero-to-one range are black
+//
+// clamp texture coordinates less than 0.0 and greater
+// than 1.0 are clamped to 0.0 and 1.0 respectively
+//
+// periodic the texture image repeats periodically
+//
+// mirror the texture image repeats periodically, but
+// every other instance is mirrored
+//
+
+IMF_STD_ATTRIBUTE_DEF (wrapmodes, Wrapmodes, std::string)
+
+
+//
+// framesPerSecond -- defines the nominal playback frame rate for image
+// sequences, in frames per second. Every image in a sequence should
+// have a framesPerSecond attribute, and the attribute value should be
+// the same for all images in the sequence. If an image sequence has
+// no framesPerSecond attribute, playback software should assume that
+// the frame rate for the sequence is 24 frames per second.
+//
+// In order to allow exact representation of NTSC frame and field rates,
+// framesPerSecond is stored as a rational number. A rational number is
+// a pair of integers, n and d, that represents the value n/d.
+//
+// For the exact values of commonly used frame rates, please see header
+// file ImfFramesPerSecond.h.
+//
+
+IMF_STD_ATTRIBUTE_DEF (framesPerSecond, FramesPerSecond, Rational)
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfStdIO.cpp b/Source/OpenEXR/IlmImf/ImfStdIO.cpp
new file mode 100644
index 0000000..4af3859
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStdIO.cpp
@@ -0,0 +1,234 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Low-level file input and output for OpenEXR
+// based on C++ standard iostreams.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfStdIO.h>
+#include "Iex.h"
+#include <errno.h>
+
+using namespace std;
+
+namespace Imf {
+namespace {
+
+void
+clearError ()
+{
+ errno = 0;
+}
+
+
+bool
+checkError (istream &is)
+{
+ if (!is)
+ {
+ if (errno)
+ Iex::throwErrnoExc();
+ return false;
+ }
+
+ return true;
+}
+
+
+void
+checkError (ostream &os)
+{
+ if (!os)
+ {
+ if (errno)
+ Iex::throwErrnoExc();
+
+ throw Iex::ErrnoExc ("File output failed.");
+ }
+}
+
+} // namespace
+
+
+StdIFStream::StdIFStream (const char fileName[]):
+ IStream (fileName),
+ _is (new ifstream (fileName, ios_base::binary)),
+ _deleteStream (true)
+{
+ if (!*_is)
+ {
+ delete _is;
+ Iex::throwErrnoExc();
+ }
+}
+
+
+StdIFStream::StdIFStream (ifstream &is, const char fileName[]):
+ IStream (fileName),
+ _is (&is),
+ _deleteStream (false)
+{
+ // empty
+}
+
+
+StdIFStream::~StdIFStream ()
+{
+ if (_deleteStream)
+ delete _is;
+}
+
+
+bool
+StdIFStream::read (char c[/*n*/], int n)
+{
+ if (!*_is)
+ throw Iex::InputExc ("Unexpected end of file.");
+
+ clearError();
+ _is->read (c, n);
+ return checkError (*_is);
+}
+
+
+Int64
+StdIFStream::tellg ()
+{
+ return std::streamoff (_is->tellg());
+}
+
+
+void
+StdIFStream::seekg (Int64 pos)
+{
+ _is->seekg (pos);
+ checkError (*_is);
+}
+
+
+void
+StdIFStream::clear ()
+{
+ _is->clear();
+}
+
+
+StdOFStream::StdOFStream (const char fileName[]):
+ OStream (fileName),
+ _os (new ofstream (fileName, ios_base::binary)),
+ _deleteStream (true)
+{
+ if (!*_os)
+ {
+ delete _os;
+ Iex::throwErrnoExc();
+ }
+}
+
+
+StdOFStream::StdOFStream (ofstream &os, const char fileName[]):
+ OStream (fileName),
+ _os (&os),
+ _deleteStream (false)
+{
+ // empty
+}
+
+
+StdOFStream::~StdOFStream ()
+{
+ if (_deleteStream)
+ delete _os;
+}
+
+
+void
+StdOFStream::write (const char c[/*n*/], int n)
+{
+ clearError();
+ _os->write (c, n);
+ checkError (*_os);
+}
+
+
+Int64
+StdOFStream::tellp ()
+{
+ return std::streamoff (_os->tellp());
+}
+
+
+void
+StdOFStream::seekp (Int64 pos)
+{
+ _os->seekp (pos);
+ checkError (*_os);
+}
+
+
+StdOSStream::StdOSStream (): OStream ("(string)")
+{
+ // empty
+}
+
+
+void
+StdOSStream::write (const char c[/*n*/], int n)
+{
+ clearError();
+ _os.write (c, n);
+ checkError (_os);
+}
+
+
+Int64
+StdOSStream::tellp ()
+{
+ return std::streamoff (_os.tellp());
+}
+
+
+void
+StdOSStream::seekp (Int64 pos)
+{
+ _os.seekp (pos);
+ checkError (_os);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfStdIO.h b/Source/OpenEXR/IlmImf/ImfStdIO.h
new file mode 100644
index 0000000..0137b45
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStdIO.h
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_STD_IO_H
+#define INCLUDED_IMF_STD_IO_H
+
+//-----------------------------------------------------------------------------
+//
+// Low-level file input and output for OpenEXR
+// based on C++ standard iostreams.
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfIO.h>
+#include <fstream>
+#include <sstream>
+
+namespace Imf {
+
+//-------------------------------------------
+// class StdIFStream -- an implementation of
+// class IStream based on class std::ifstream
+//-------------------------------------------
+
+class StdIFStream: public IStream
+{
+ public:
+
+ //-------------------------------------------------------
+ // A constructor that opens the file with the given name.
+ // The destructor will close the file.
+ //-------------------------------------------------------
+
+ StdIFStream (const char fileName[]);
+
+
+ //---------------------------------------------------------
+ // A constructor that uses a std::ifstream that has already
+ // been opened by the caller. The StdIFStream's destructor
+ // will not close the std::ifstream.
+ //---------------------------------------------------------
+
+ StdIFStream (std::ifstream &is, const char fileName[]);
+
+
+ virtual ~StdIFStream ();
+
+ virtual bool read (char c[/*n*/], int n);
+ virtual Int64 tellg ();
+ virtual void seekg (Int64 pos);
+ virtual void clear ();
+
+ private:
+
+ std::ifstream * _is;
+ bool _deleteStream;
+};
+
+
+//-------------------------------------------
+// class StdOFStream -- an implementation of
+// class OStream based on class std::ofstream
+//-------------------------------------------
+
+class StdOFStream: public OStream
+{
+ public:
+
+ //-------------------------------------------------------
+ // A constructor that opens the file with the given name.
+ // The destructor will close the file.
+ //-------------------------------------------------------
+
+ StdOFStream (const char fileName[]);
+
+
+ //---------------------------------------------------------
+ // A constructor that uses a std::ofstream that has already
+ // been opened by the caller. The StdOFStream's destructor
+ // will not close the std::ofstream.
+ //---------------------------------------------------------
+
+ StdOFStream (std::ofstream &os, const char fileName[]);
+
+
+ virtual ~StdOFStream ();
+
+ virtual void write (const char c[/*n*/], int n);
+ virtual Int64 tellp ();
+ virtual void seekp (Int64 pos);
+
+ private:
+
+ std::ofstream * _os;
+ bool _deleteStream;
+};
+
+
+//------------------------------------------------
+// class StdOSStream -- an implementation of class
+// OStream, based on class std::ostringstream
+//------------------------------------------------
+
+class StdOSStream: public OStream
+{
+ public:
+
+ StdOSStream ();
+
+ virtual void write (const char c[/*n*/], int n);
+ virtual Int64 tellp ();
+ virtual void seekp (Int64 pos);
+
+ std::string str () const {return _os.str();}
+
+ private:
+
+ std::ostringstream _os;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfStringAttribute.cpp b/Source/OpenEXR/IlmImf/ImfStringAttribute.cpp
new file mode 100644
index 0000000..6f6ca94
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStringAttribute.cpp
@@ -0,0 +1,79 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class StringAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfStringAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+StringAttribute::staticTypeName ()
+{
+ return "string";
+}
+
+
+template <>
+void
+StringAttribute::writeValueTo (OStream &os, int version) const
+{
+ int size = _value.size();
+
+ for (int i = 0; i < size; i++)
+ Xdr::write <StreamIO> (os, _value[i]);
+}
+
+
+template <>
+void
+StringAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ _value.resize (size);
+
+ for (int i = 0; i < size; i++)
+ Xdr::read <StreamIO> (is, _value[i]);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfStringAttribute.h b/Source/OpenEXR/IlmImf/ImfStringAttribute.h
new file mode 100644
index 0000000..3ce76eb
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfStringAttribute.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_STRING_ATTRIBUTE_H
+#define INCLUDED_IMF_STRING_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class StringAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <string>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<std::string> StringAttribute;
+template <> const char *StringAttribute::staticTypeName ();
+template <> void StringAttribute::writeValueTo (OStream &, int) const;
+template <> void StringAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfStringAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTestFile.cpp b/Source/OpenEXR/IlmImf/ImfTestFile.cpp
new file mode 100644
index 0000000..1bf7872
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTestFile.cpp
@@ -0,0 +1,135 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Utility routines to test quickly if a given
+// file is an OpenEXR file, and whether the
+// file is scanline-based or tiled.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ImfTestFile.h>
+#include <ImfStdIO.h>
+#include <ImfXdr.h>
+#include <ImfVersion.h>
+
+namespace Imf {
+
+
+bool
+isOpenExrFile (const char fileName[], bool &tiled)
+{
+ try
+ {
+ StdIFStream is (fileName);
+
+ int magic, version;
+ Xdr::read <StreamIO> (is, magic);
+ Xdr::read <StreamIO> (is, version);
+
+ tiled = isTiled (version);
+ return magic == MAGIC;
+ }
+ catch (...)
+ {
+ tiled = false;
+ return false;
+ }
+}
+
+
+bool
+isOpenExrFile (const char fileName[])
+{
+ bool tiled;
+ return isOpenExrFile (fileName, tiled);
+}
+
+
+bool
+isTiledOpenExrFile (const char fileName[])
+{
+ bool exr, tiled;
+ exr = isOpenExrFile (fileName, tiled);
+ return exr && tiled;
+}
+
+
+bool
+isOpenExrFile (IStream &is, bool &tiled)
+{
+ try
+ {
+ Int64 pos = is.tellg();
+
+ if (pos != 0)
+ is.seekg (0);
+
+ int magic, version;
+ Xdr::read <StreamIO> (is, magic);
+ Xdr::read <StreamIO> (is, version);
+
+ is.seekg (pos);
+
+ tiled = isTiled (version);
+ return magic == MAGIC;
+ }
+ catch (...)
+ {
+ is.clear();
+ tiled = false;
+ return false;
+ }
+}
+
+
+bool
+isOpenExrFile (IStream &is)
+{
+ bool tiled;
+ return isOpenExrFile (is, tiled);
+}
+
+
+bool
+isTiledOpenExrFile (IStream &is)
+{
+ bool exr, tiled;
+ exr = isOpenExrFile (is, tiled);
+ return exr && tiled;
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTestFile.h b/Source/OpenEXR/IlmImf/ImfTestFile.h
new file mode 100644
index 0000000..d81c61a
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTestFile.h
@@ -0,0 +1,63 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TEST_FILE_H
+#define INCLUDED_IMF_TEST_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// Utility routines to test quickly if a given
+// file is an OpenEXR file, and whether the
+// file is scanline-based or tiled.
+//
+//-----------------------------------------------------------------------------
+
+
+namespace Imf {
+
+class IStream;
+
+
+bool isOpenExrFile (const char fileName[], bool &isTiled);
+bool isOpenExrFile (const char fileName[]);
+bool isTiledOpenExrFile (const char fileName[]);
+bool isOpenExrFile (IStream &is, bool &isTiled);
+bool isOpenExrFile (IStream &is);
+bool isTiledOpenExrFile (IStream &is);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfThreading.cpp b/Source/OpenEXR/IlmImf/ImfThreading.cpp
new file mode 100644
index 0000000..80f569c
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfThreading.cpp
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Threading support for the IlmImf library
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmThreadPool.h"
+
+namespace Imf {
+
+
+int
+globalThreadCount ()
+{
+ return IlmThread::ThreadPool::globalThreadPool().numThreads();
+}
+
+
+void
+setGlobalThreadCount (int count)
+{
+ IlmThread::ThreadPool::globalThreadPool().setNumThreads (count);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfThreading.h b/Source/OpenEXR/IlmImf/ImfThreading.h
new file mode 100644
index 0000000..50fe35e
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfThreading.h
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_IMF_THREADING_H
+#define INCLUDED_IMF_THREADING_H
+
+//-----------------------------------------------------------------------------
+//
+// Threading support for the IlmImf library
+//
+// The IlmImf library uses threads to perform reading and writing
+// of OpenEXR files in parallel. The thread that calls the library
+// always performs the actual file IO (this is usually the main
+// application thread) whereas a several worker threads perform
+// data compression and decompression. The number of worker
+// threads can be any non-negative value (a value of zero reverts
+// to single-threaded operation). As long as there is at least
+// one worker thread, file IO and compression can potentially be
+// done concurrently through pinelining. If there are two or more
+// worker threads, then pipelining as well as concurrent compression
+// of multiple blocks can be performed.
+//
+// Threading in the Imf library is controllable at two granularities:
+//
+// * The functions in this file query and control the total number
+// of worker threads, which will be created globally for the whole
+// library. Regardless of how many input or output files are
+// opened simultaneously, the library will use at most this number
+// of worker threads to perform all work. The default number of
+// global worker threads is zero (i.e. single-threaded operation;
+// everything happens in the thread that calls the library).
+//
+// * Furthermore, it is possible to set the number of threads that
+// each input or output file should keep busy. This number can
+// be explicitly set for each file. The default behavior is for
+// each file to try to occupy all worker threads in the library's
+// thread pool.
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+//-----------------------------------------------------------------------------
+// Return the number of Imf-global worker threads used for parallel
+// compression and decompression of OpenEXR files.
+//-----------------------------------------------------------------------------
+
+int globalThreadCount ();
+
+
+//-----------------------------------------------------------------------------
+// Change the number of Imf-global worker threads
+//-----------------------------------------------------------------------------
+
+void setGlobalThreadCount (int count);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTileDescription.h b/Source/OpenEXR/IlmImf/ImfTileDescription.h
new file mode 100644
index 0000000..0e59890
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTileDescription.h
@@ -0,0 +1,102 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILE_DESCRIPTION_H
+#define INCLUDED_IMF_TILE_DESCRIPTION_H
+
+//-----------------------------------------------------------------------------
+//
+// class TileDescription and enum LevelMode
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+enum LevelMode
+{
+ ONE_LEVEL = 0,
+ MIPMAP_LEVELS = 1,
+ RIPMAP_LEVELS = 2,
+
+ NUM_LEVELMODES // number of different level modes
+};
+
+
+enum LevelRoundingMode
+{
+ ROUND_DOWN = 0,
+ ROUND_UP = 1,
+
+ NUM_ROUNDINGMODES // number of different rounding modes
+};
+
+
+class TileDescription
+{
+ public:
+
+ unsigned int xSize; // size of a tile in the x dimension
+ unsigned int ySize; // size of a tile in the y dimension
+ LevelMode mode;
+ LevelRoundingMode roundingMode;
+
+ TileDescription (unsigned int xs = 32,
+ unsigned int ys = 32,
+ LevelMode m = ONE_LEVEL,
+ LevelRoundingMode r = ROUND_DOWN)
+ :
+ xSize (xs),
+ ySize (ys),
+ mode (m),
+ roundingMode (r)
+ {
+ // empty
+ }
+
+ bool
+ operator == (const TileDescription &other) const
+ {
+ return xSize == other.xSize &&
+ ySize == other.ySize &&
+ mode == other.mode &&
+ roundingMode == other.roundingMode;
+ }
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.cpp b/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.cpp
new file mode 100644
index 0000000..e15f10f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.cpp
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class TileDescriptionAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTileDescriptionAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+TileDescriptionAttribute::staticTypeName ()
+{
+ return "tiledesc";
+}
+
+
+template <>
+void
+TileDescriptionAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.xSize);
+ Xdr::write <StreamIO> (os, _value.ySize);
+
+ unsigned char tmp = _value.mode | (_value.roundingMode << 4);
+ Xdr::write <StreamIO> (os, tmp);
+}
+
+
+template <>
+void
+TileDescriptionAttribute::readValueFrom (IStream &is,
+ int size,
+ int version)
+{
+ Xdr::read <StreamIO> (is, _value.xSize);
+ Xdr::read <StreamIO> (is, _value.ySize);
+
+ unsigned char tmp;
+ Xdr::read <StreamIO> (is, tmp);
+ _value.mode = LevelMode (tmp & 0x0f);
+ _value.roundingMode = LevelRoundingMode ((tmp >> 4) & 0x0f);
+
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.h b/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.h
new file mode 100644
index 0000000..8a7125a
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTileDescriptionAttribute.h
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILE_DESCRIPTION_ATTRIBUTE_H
+#define INCLUDED_IMF_TILE_DESCRIPTION_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class TileDescriptionAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfTileDescription.h>
+
+namespace Imf {
+
+
+typedef TypedAttribute<TileDescription> TileDescriptionAttribute;
+
+template <>
+const char *
+TileDescriptionAttribute::staticTypeName ();
+
+template <>
+void
+TileDescriptionAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void
+TileDescriptionAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfTileDescriptionAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTileOffsets.cpp b/Source/OpenEXR/IlmImf/ImfTileOffsets.cpp
new file mode 100644
index 0000000..b1fa29c
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTileOffsets.cpp
@@ -0,0 +1,385 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class TileOffsets
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTileOffsets.h>
+#include <ImfXdr.h>
+#include <ImfIO.h>
+#include "Iex.h"
+
+namespace Imf {
+
+
+TileOffsets::TileOffsets (LevelMode mode,
+ int numXLevels, int numYLevels,
+ const int *numXTiles, const int *numYTiles)
+:
+ _mode (mode),
+ _numXLevels (numXLevels),
+ _numYLevels (numYLevels)
+{
+ switch (_mode)
+ {
+ case ONE_LEVEL:
+ case MIPMAP_LEVELS:
+
+ _offsets.resize (_numXLevels);
+
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ {
+ _offsets[l].resize (numYTiles[l]);
+
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ {
+ _offsets[l][dy].resize (numXTiles[l]);
+ }
+ }
+ break;
+
+ case RIPMAP_LEVELS:
+
+ _offsets.resize (_numXLevels * _numYLevels);
+
+ for (unsigned int ly = 0; ly < _numYLevels; ++ly)
+ {
+ for (unsigned int lx = 0; lx < _numXLevels; ++lx)
+ {
+ int l = ly * _numXLevels + lx;
+ _offsets[l].resize (numYTiles[ly]);
+
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ {
+ _offsets[l][dy].resize (numXTiles[lx]);
+ }
+ }
+ }
+ break;
+ }
+}
+
+
+bool
+TileOffsets::anyOffsetsAreInvalid () const
+{
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
+ if (_offsets[l][dy][dx] <= 0)
+ return true;
+
+ return false;
+}
+
+
+void
+TileOffsets::findTiles (IStream &is)
+{
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ {
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ {
+ for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
+ {
+ Int64 tileOffset = is.tellg();
+
+ int tileX;
+ Xdr::read <StreamIO> (is, tileX);
+
+ int tileY;
+ Xdr::read <StreamIO> (is, tileY);
+
+ int levelX;
+ Xdr::read <StreamIO> (is, levelX);
+
+ int levelY;
+ Xdr::read <StreamIO> (is, levelY);
+
+ int dataSize;
+ Xdr::read <StreamIO> (is, dataSize);
+
+ Xdr::skip <StreamIO> (is, dataSize);
+
+ if (!isValidTile(tileX, tileY, levelX, levelY))
+ return;
+
+ operator () (tileX, tileY, levelX, levelY) = tileOffset;
+ }
+ }
+ }
+}
+
+
+void
+TileOffsets::reconstructFromFile (IStream &is)
+{
+ //
+ // Try to reconstruct a missing tile offset table by sequentially
+ // scanning through the file, and recording the offsets in the file
+ // of the tiles we find.
+ //
+
+ Int64 position = is.tellg();
+
+ try
+ {
+ findTiles (is);
+ }
+ catch (...)
+ {
+ //
+ // Suppress all exceptions. This function is called only to
+ // reconstruct the tile offset table for incomplete files,
+ // and exceptions are likely.
+ //
+ }
+
+ is.clear();
+ is.seekg (position);
+}
+
+
+void
+TileOffsets::readFrom (IStream &is, bool &complete)
+{
+ //
+ // Read in the tile offsets from the file's tile offset table
+ //
+
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
+ Xdr::read <StreamIO> (is, _offsets[l][dy][dx]);
+
+ //
+ // Check if any tile offsets are invalid.
+ //
+ // Invalid offsets mean that the file is probably incomplete
+ // (the offset table is the last thing written to the file).
+ // Either some process is still busy writing the file, or
+ // writing the file was aborted.
+ //
+ // We should still be able to read the existing parts of the
+ // file. In order to do this, we have to make a sequential
+ // scan over the scan tile to reconstruct the tile offset
+ // table.
+ //
+
+ if (anyOffsetsAreInvalid())
+ {
+ complete = false;
+ reconstructFromFile (is);
+ }
+ else
+ {
+ complete = true;
+ }
+
+}
+
+
+Int64
+TileOffsets::writeTo (OStream &os) const
+{
+ //
+ // Write the tile offset table to the file, and
+ // return the position of the start of the table
+ // in the file.
+ //
+
+ Int64 pos = os.tellp();
+
+ if (pos == -1)
+ Iex::throwErrnoExc ("Cannot determine current file position (%T).");
+
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
+ Xdr::write <StreamIO> (os, _offsets[l][dy][dx]);
+
+ return pos;
+}
+
+
+bool
+TileOffsets::isEmpty () const
+{
+ for (unsigned int l = 0; l < _offsets.size(); ++l)
+ for (unsigned int dy = 0; dy < _offsets[l].size(); ++dy)
+ for (unsigned int dx = 0; dx < _offsets[l][dy].size(); ++dx)
+ if (_offsets[l][dy][dx] != 0)
+ return false;
+ return true;
+}
+
+
+bool
+TileOffsets::isValidTile (int dx, int dy, int lx, int ly) const
+{
+ switch (_mode)
+ {
+ case ONE_LEVEL:
+
+ if (lx == 0 &&
+ ly == 0 &&
+ _offsets.size() > 0 &&
+ _offsets[0].size() > dy &&
+ _offsets[0][dy].size() > dx)
+ {
+ return true;
+ }
+
+ break;
+
+ case MIPMAP_LEVELS:
+
+ if (lx < _numXLevels &&
+ ly < _numYLevels &&
+ _offsets.size() > lx &&
+ _offsets[lx].size() > dy &&
+ _offsets[lx][dy].size() > dx)
+ {
+ return true;
+ }
+
+ break;
+
+ case RIPMAP_LEVELS:
+
+ if (lx < _numXLevels &&
+ ly < _numYLevels &&
+ _offsets.size() > lx + ly * _numXLevels &&
+ _offsets[lx + ly * _numXLevels].size() > dy &&
+ _offsets[lx + ly * _numXLevels][dy].size() > dx)
+ {
+ return true;
+ }
+
+ break;
+
+ default:
+
+ return false;
+ }
+
+ return false;
+}
+
+
+Int64 &
+TileOffsets::operator () (int dx, int dy, int lx, int ly)
+{
+ //
+ // Looks up the value of the tile with tile coordinate (dx, dy)
+ // and level number (lx, ly) in the _offsets array, and returns
+ // the cooresponding offset.
+ //
+
+ switch (_mode)
+ {
+ case ONE_LEVEL:
+
+ return _offsets[0][dy][dx];
+ break;
+
+ case MIPMAP_LEVELS:
+
+ return _offsets[lx][dy][dx];
+ break;
+
+ case RIPMAP_LEVELS:
+
+ return _offsets[lx + ly * _numXLevels][dy][dx];
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown LevelMode format.");
+ }
+}
+
+
+Int64 &
+TileOffsets::operator () (int dx, int dy, int l)
+{
+ return operator () (dx, dy, l, l);
+}
+
+
+const Int64 &
+TileOffsets::operator () (int dx, int dy, int lx, int ly) const
+{
+ //
+ // Looks up the value of the tile with tile coordinate (dx, dy)
+ // and level number (lx, ly) in the _offsets array, and returns
+ // the cooresponding offset.
+ //
+
+ switch (_mode)
+ {
+ case ONE_LEVEL:
+
+ return _offsets[0][dy][dx];
+ break;
+
+ case MIPMAP_LEVELS:
+
+ return _offsets[lx][dy][dx];
+ break;
+
+ case RIPMAP_LEVELS:
+
+ return _offsets[lx + ly * _numXLevels][dy][dx];
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown LevelMode format.");
+ }
+}
+
+
+const Int64 &
+TileOffsets::operator () (int dx, int dy, int l) const
+{
+ return operator () (dx, dy, l, l);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTileOffsets.h b/Source/OpenEXR/IlmImf/ImfTileOffsets.h
new file mode 100644
index 0000000..7b2b4c2
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTileOffsets.h
@@ -0,0 +1,107 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILE_OFFSETS_H
+#define INCLUDED_IMF_TILE_OFFSETS_H
+
+//-----------------------------------------------------------------------------
+//
+// class TileOffsets
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTileDescription.h>
+#include <ImfInt64.h>
+#include <vector>
+
+namespace Imf {
+
+class IStream;
+class OStream;
+
+
+class TileOffsets
+{
+ public:
+
+ TileOffsets (LevelMode mode = ONE_LEVEL,
+ int numXLevels = 0,
+ int numYLevels = 0,
+ const int *numXTiles = 0,
+ const int *numYTiles = 0);
+
+ // --------
+ // File I/O
+ // --------
+
+ void readFrom (IStream &is, bool &complete);
+ Int64 writeTo (OStream &os) const;
+
+
+ //-----------------------------------------------------------
+ // Test if the tileOffsets array is empty (all entries are 0)
+ //-----------------------------------------------------------
+
+ bool isEmpty () const;
+
+
+ //-----------------------
+ // Access to the elements
+ //-----------------------
+
+ Int64 & operator () (int dx, int dy, int lx, int ly);
+ Int64 & operator () (int dx, int dy, int l);
+ const Int64 & operator () (int dx, int dy, int lx, int ly) const;
+ const Int64 & operator () (int dx, int dy, int l) const;
+
+ private:
+
+ void findTiles (IStream &is);
+ void reconstructFromFile (IStream &is);
+ bool readTile (IStream &is);
+ bool anyOffsetsAreInvalid () const;
+ bool isValidTile (int dx, int dy, int lx, int ly) const;
+
+ LevelMode _mode;
+ int _numXLevels;
+ int _numYLevels;
+
+ std::vector<std::vector<std::vector <Int64> > > _offsets;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTiledInputFile.cpp b/Source/OpenEXR/IlmImf/ImfTiledInputFile.cpp
new file mode 100644
index 0000000..a45c3ac
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledInputFile.cpp
@@ -0,0 +1,1302 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class TiledInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTiledInputFile.h>
+#include <ImfTileDescriptionAttribute.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImfTiledMisc.h>
+#include <ImfStdIO.h>
+#include <ImfCompressor.h>
+#include "ImathBox.h"
+#include <ImfXdr.h>
+#include <ImfConvert.h>
+#include <ImfVersion.h>
+#include <ImfTileOffsets.h>
+#include <ImfThreading.h>
+#include "IlmThreadPool.h"
+#include "IlmThreadSemaphore.h"
+#include "IlmThreadMutex.h"
+#include "ImathVec.h"
+#include "Iex.h"
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <assert.h>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::V2i;
+using std::string;
+using std::vector;
+using std::min;
+using std::max;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+using IlmThread::Semaphore;
+using IlmThread::Task;
+using IlmThread::TaskGroup;
+using IlmThread::ThreadPool;
+
+namespace {
+
+struct TInSliceInfo
+{
+ PixelType typeInFrameBuffer;
+ PixelType typeInFile;
+ char * base;
+ size_t xStride;
+ size_t yStride;
+ bool fill;
+ bool skip;
+ double fillValue;
+ int xTileCoords;
+ int yTileCoords;
+
+ TInSliceInfo (PixelType typeInFrameBuffer = HALF,
+ PixelType typeInFile = HALF,
+ char *base = 0,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ bool fill = false,
+ bool skip = false,
+ double fillValue = 0.0,
+ int xTileCoords = 0,
+ int yTileCoords = 0);
+};
+
+
+TInSliceInfo::TInSliceInfo (PixelType tifb,
+ PixelType tifl,
+ char *b,
+ size_t xs, size_t ys,
+ bool f, bool s,
+ double fv,
+ int xtc,
+ int ytc)
+:
+ typeInFrameBuffer (tifb),
+ typeInFile (tifl),
+ base (b),
+ xStride (xs),
+ yStride (ys),
+ fill (f),
+ skip (s),
+ fillValue (fv),
+ xTileCoords (xtc),
+ yTileCoords (ytc)
+{
+ // empty
+}
+
+
+struct TileBuffer
+{
+ const char * uncompressedData;
+ char * buffer;
+ int dataSize;
+ Compressor * compressor;
+ Compressor::Format format;
+ int dx;
+ int dy;
+ int lx;
+ int ly;
+ bool hasException;
+ string exception;
+
+ TileBuffer (Compressor * const comp);
+ ~TileBuffer ();
+
+ inline void wait () {_sem.wait();}
+ inline void post () {_sem.post();}
+
+ protected:
+
+ Semaphore _sem;
+};
+
+
+TileBuffer::TileBuffer (Compressor *comp):
+ uncompressedData (0),
+ dataSize (0),
+ compressor (comp),
+ format (defaultFormat (compressor)),
+ dx (-1),
+ dy (-1),
+ lx (-1),
+ ly (-1),
+ hasException (false),
+ exception (),
+ _sem (1)
+{
+ // empty
+}
+
+
+TileBuffer::~TileBuffer ()
+{
+ delete compressor;
+}
+
+} // namespace
+
+
+//
+// struct TiledInputFile::Data stores things that will be
+// needed between calls to readTile()
+//
+
+struct TiledInputFile::Data: public Mutex
+{
+ Header header; // the image header
+ TileDescription tileDesc; // describes the tile layout
+ int version; // file's version
+ FrameBuffer frameBuffer; // framebuffer to write into
+ LineOrder lineOrder; // the file's lineorder
+ int minX; // data window's min x coord
+ int maxX; // data window's max x coord
+ int minY; // data window's min y coord
+ int maxY; // data window's max x coord
+
+ int numXLevels; // number of x levels
+ int numYLevels; // number of y levels
+ int * numXTiles; // number of x tiles at a level
+ int * numYTiles; // number of y tiles at a level
+
+ TileOffsets tileOffsets; // stores offsets in file for
+ // each tile
+
+ bool fileIsComplete; // True if no tiles are missing
+ // in the file
+
+ Int64 currentPosition; // file offset for current tile,
+ // used to prevent unnecessary
+ // seeking
+
+ vector<TInSliceInfo> slices; // info about channels in file
+ IStream * is; // file stream to read from
+
+ bool deleteStream; // should we delete the stream
+ // ourselves? or does someone
+ // else do it?
+
+ size_t bytesPerPixel; // size of an uncompressed pixel
+
+ size_t maxBytesPerTileLine; // combined size of a line
+ // over all channels
+
+
+ vector<TileBuffer*> tileBuffers; // each holds a single tile
+ size_t tileBufferSize; // size of the tile buffers
+
+ Data (bool deleteStream, int numThreads);
+ ~Data ();
+
+ inline TileBuffer * getTileBuffer (int number);
+ // hash function from tile indices
+ // into our vector of tile buffers
+};
+
+
+TiledInputFile::Data::Data (bool del, int numThreads):
+ numXTiles (0),
+ numYTiles (0),
+ is (0),
+ deleteStream (del)
+{
+ //
+ // We need at least one tileBuffer, but if threading is used,
+ // to keep n threads busy we need 2*n tileBuffers
+ //
+
+ tileBuffers.resize (max (1, 2 * numThreads));
+}
+
+
+TiledInputFile::Data::~Data ()
+{
+ delete [] numXTiles;
+ delete [] numYTiles;
+
+ if (deleteStream)
+ delete is;
+
+ for (size_t i = 0; i < tileBuffers.size(); i++)
+ delete tileBuffers[i];
+}
+
+
+TileBuffer*
+TiledInputFile::Data::getTileBuffer (int number)
+{
+ return tileBuffers[number % tileBuffers.size()];
+}
+
+
+namespace {
+
+void
+readTileData (TiledInputFile::Data *ifd,
+ int dx, int dy,
+ int lx, int ly,
+ char *&buffer,
+ int &dataSize)
+{
+ //
+ // Read a single tile block from the file and into the array pointed
+ // to by buffer. If the file is memory-mapped, then we change where
+ // buffer points instead of writing into the array (hence buffer needs
+ // to be a reference to a char *).
+ //
+
+ //
+ // Look up the location for this tile in the Index and
+ // seek to that position if necessary
+ //
+
+ Int64 tileOffset = ifd->tileOffsets (dx, dy, lx, ly);
+
+ if (tileOffset == 0)
+ {
+ THROW (Iex::InputExc, "Tile (" << dx << ", " << dy << ", " <<
+ lx << ", " << ly << ") is missing.");
+ }
+
+ if (ifd->currentPosition != tileOffset)
+ ifd->is->seekg (tileOffset);
+
+ //
+ // Read the first few bytes of the tile (the header).
+ // Verify that the tile coordinates and the level number
+ // are correct.
+ //
+
+ int tileXCoord, tileYCoord, levelX, levelY;
+
+ Xdr::read <StreamIO> (*ifd->is, tileXCoord);
+ Xdr::read <StreamIO> (*ifd->is, tileYCoord);
+ Xdr::read <StreamIO> (*ifd->is, levelX);
+ Xdr::read <StreamIO> (*ifd->is, levelY);
+ Xdr::read <StreamIO> (*ifd->is, dataSize);
+
+ if (tileXCoord != dx)
+ throw Iex::InputExc ("Unexpected tile x coordinate.");
+
+ if (tileYCoord != dy)
+ throw Iex::InputExc ("Unexpected tile y coordinate.");
+
+ if (levelX != lx)
+ throw Iex::InputExc ("Unexpected tile x level number coordinate.");
+
+ if (levelY != ly)
+ throw Iex::InputExc ("Unexpected tile y level number coordinate.");
+
+ if (dataSize > (int) ifd->tileBufferSize)
+ throw Iex::InputExc ("Unexpected tile block length.");
+
+ //
+ // Read the pixel data.
+ //
+
+ if (ifd->is->isMemoryMapped ())
+ buffer = ifd->is->readMemoryMapped (dataSize);
+ else
+ ifd->is->read (buffer, dataSize);
+
+ //
+ // Keep track of which tile is the next one in
+ // the file, so that we can avoid redundant seekg()
+ // operations (seekg() can be fairly expensive).
+ //
+
+ ifd->currentPosition = tileOffset + 5 * Xdr::size<int>() + dataSize;
+}
+
+
+void
+readNextTileData (TiledInputFile::Data *ifd,
+ int &dx, int &dy,
+ int &lx, int &ly,
+ char * & buffer,
+ int &dataSize)
+{
+ //
+ // Read the next tile block from the file
+ //
+
+ //
+ // Read the first few bytes of the tile (the header).
+ //
+
+ Xdr::read <StreamIO> (*ifd->is, dx);
+ Xdr::read <StreamIO> (*ifd->is, dy);
+ Xdr::read <StreamIO> (*ifd->is, lx);
+ Xdr::read <StreamIO> (*ifd->is, ly);
+ Xdr::read <StreamIO> (*ifd->is, dataSize);
+
+ if (dataSize > (int) ifd->tileBufferSize)
+ throw Iex::InputExc ("Unexpected tile block length.");
+
+ //
+ // Read the pixel data.
+ //
+
+ ifd->is->read (buffer, dataSize);
+
+ //
+ // Keep track of which tile is the next one in
+ // the file, so that we can avoid redundant seekg()
+ // operations (seekg() can be fairly expensive).
+ //
+
+ ifd->currentPosition += 5 * Xdr::size<int>() + dataSize;
+}
+
+
+//
+// A TileBufferTask encapsulates the task of uncompressing
+// a single tile and copying it into the frame buffer.
+//
+
+class TileBufferTask : public Task
+{
+ public:
+
+ TileBufferTask (TaskGroup *group,
+ TiledInputFile::Data *ifd,
+ TileBuffer *tileBuffer);
+
+ virtual ~TileBufferTask ();
+
+ virtual void execute ();
+
+ private:
+
+ TiledInputFile::Data * _ifd;
+ TileBuffer * _tileBuffer;
+};
+
+
+TileBufferTask::TileBufferTask
+ (TaskGroup *group,
+ TiledInputFile::Data *ifd,
+ TileBuffer *tileBuffer)
+:
+ Task (group),
+ _ifd (ifd),
+ _tileBuffer (tileBuffer)
+{
+ // empty
+}
+
+
+TileBufferTask::~TileBufferTask ()
+{
+ //
+ // Signal that the tile buffer is now free
+ //
+
+ _tileBuffer->post ();
+}
+
+
+void
+TileBufferTask::execute ()
+{
+ try
+ {
+ //
+ // Calculate information about the tile
+ //
+
+ Box2i tileRange = Imf::dataWindowForTile (_ifd->tileDesc,
+ _ifd->minX, _ifd->maxX,
+ _ifd->minY, _ifd->maxY,
+ _tileBuffer->dx,
+ _tileBuffer->dy,
+ _tileBuffer->lx,
+ _tileBuffer->ly);
+
+ int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1;
+
+ int numPixelsInTile = numPixelsPerScanLine *
+ (tileRange.max.y - tileRange.min.y + 1);
+
+ int sizeOfTile = _ifd->bytesPerPixel * numPixelsInTile;
+
+
+ //
+ // Uncompress the data, if necessary
+ //
+
+ if (_tileBuffer->compressor && _tileBuffer->dataSize < sizeOfTile)
+ {
+ _tileBuffer->format = _tileBuffer->compressor->format();
+
+ _tileBuffer->dataSize = _tileBuffer->compressor->uncompressTile
+ (_tileBuffer->buffer, _tileBuffer->dataSize,
+ tileRange, _tileBuffer->uncompressedData);
+ }
+ else
+ {
+ //
+ // If the line is uncompressed, it's in XDR format,
+ // regardless of the compressor's output format.
+ //
+
+ _tileBuffer->format = Compressor::XDR;
+ _tileBuffer->uncompressedData = _tileBuffer->buffer;
+ }
+
+ //
+ // Convert the tile of pixel data back from the machine-independent
+ // representation, and store the result in the frame buffer.
+ //
+
+ const char *readPtr = _tileBuffer->uncompressedData;
+ // points to where we
+ // read from in the
+ // tile block
+
+ //
+ // Iterate over the scan lines in the tile.
+ //
+
+ for (int y = tileRange.min.y; y <= tileRange.max.y; ++y)
+ {
+ //
+ // Iterate over all image channels.
+ //
+
+ for (unsigned int i = 0; i < _ifd->slices.size(); ++i)
+ {
+ const TInSliceInfo &slice = _ifd->slices[i];
+
+ //
+ // These offsets are used to facilitate both
+ // absolute and tile-relative pixel coordinates.
+ //
+
+ int xOffset = slice.xTileCoords * tileRange.min.x;
+ int yOffset = slice.yTileCoords * tileRange.min.y;
+
+ //
+ // Fill the frame buffer with pixel data.
+ //
+
+ if (slice.skip)
+ {
+ //
+ // The file contains data for this channel, but
+ // the frame buffer contains no slice for this channel.
+ //
+
+ skipChannel (readPtr, slice.typeInFile,
+ numPixelsPerScanLine);
+ }
+ else
+ {
+ //
+ // The frame buffer contains a slice for this channel.
+ //
+
+ char *writePtr = slice.base +
+ (y - yOffset) * slice.yStride +
+ (tileRange.min.x - xOffset) *
+ slice.xStride;
+
+ char *endPtr = writePtr +
+ (numPixelsPerScanLine - 1) * slice.xStride;
+
+ copyIntoFrameBuffer (readPtr, writePtr, endPtr,
+ slice.xStride,
+ slice.fill, slice.fillValue,
+ _tileBuffer->format,
+ slice.typeInFrameBuffer,
+ slice.typeInFile);
+ }
+ }
+ }
+ }
+ catch (std::exception &e)
+ {
+ if (!_tileBuffer->hasException)
+ {
+ _tileBuffer->exception = e.what ();
+ _tileBuffer->hasException = true;
+ }
+ }
+ catch (...)
+ {
+ if (!_tileBuffer->hasException)
+ {
+ _tileBuffer->exception = "unrecognized exception";
+ _tileBuffer->hasException = true;
+ }
+ }
+}
+
+
+TileBufferTask *
+newTileBufferTask
+ (TaskGroup *group,
+ TiledInputFile::Data *ifd,
+ int number,
+ int dx, int dy,
+ int lx, int ly)
+{
+ //
+ // Wait for a tile buffer to become available,
+ // fill the buffer with raw data from the file,
+ // and create a new TileBufferTask whose execute()
+ // method will uncompress the tile and copy the
+ // tile's pixels into the frame buffer.
+ //
+
+ TileBuffer *tileBuffer = ifd->getTileBuffer (number);
+
+ try
+ {
+ tileBuffer->wait();
+
+ tileBuffer->dx = dx;
+ tileBuffer->dy = dy;
+ tileBuffer->lx = lx;
+ tileBuffer->ly = ly;
+
+ tileBuffer->uncompressedData = 0;
+
+ readTileData (ifd, dx, dy, lx, ly,
+ tileBuffer->buffer,
+ tileBuffer->dataSize);
+ }
+ catch (...)
+ {
+ //
+ // Reading from the file caused an exception.
+ // Signal that the tile buffer is free, and
+ // re-throw the exception.
+ //
+
+ tileBuffer->post();
+ throw;
+ }
+
+ return new TileBufferTask (group, ifd, tileBuffer);
+}
+
+
+} // namespace
+
+
+TiledInputFile::TiledInputFile (const char fileName[], int numThreads):
+ _data (new Data (true, numThreads))
+{
+ //
+ // This constructor is called when a user
+ // explicitly wants to read a tiled file.
+ //
+
+ try
+ {
+ _data->is = new StdIFStream (fileName);
+ _data->header.readFrom (*_data->is, _data->version);
+ initialize();
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << fileName << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+TiledInputFile::TiledInputFile (IStream &is, int numThreads):
+ _data (new Data (false, numThreads))
+{
+ //
+ // This constructor is called when a user
+ // explicitly wants to read a tiled file.
+ //
+
+ try
+ {
+ _data->is = &is;
+ _data->header.readFrom (*_data->is, _data->version);
+ initialize();
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << is.fileName() << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+TiledInputFile::TiledInputFile
+ (const Header &header,
+ IStream *is,
+ int version,
+ int numThreads)
+:
+ _data (new Data (false, numThreads))
+{
+ //
+ // This constructor called by class Imf::InputFile
+ // when a user wants to just read an image file, and
+ // doesn't care or know if the file is tiled.
+ //
+
+ _data->is = is;
+ _data->header = header;
+ _data->version = version;
+ initialize();
+}
+
+
+void
+TiledInputFile::initialize ()
+{
+ if (!isTiled (_data->version))
+ throw Iex::ArgExc ("Expected a tiled file but the file is not tiled.");
+
+ _data->header.sanityCheck (true);
+
+ _data->tileDesc = _data->header.tileDescription();
+ _data->lineOrder = _data->header.lineOrder();
+
+ //
+ // Save the dataWindow information
+ //
+
+ const Box2i &dataWindow = _data->header.dataWindow();
+ _data->minX = dataWindow.min.x;
+ _data->maxX = dataWindow.max.x;
+ _data->minY = dataWindow.min.y;
+ _data->maxY = dataWindow.max.y;
+
+ //
+ // Precompute level and tile information to speed up utility functions
+ //
+
+ precalculateTileInfo (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ _data->numXTiles, _data->numYTiles,
+ _data->numXLevels, _data->numYLevels);
+
+ _data->bytesPerPixel = calculateBytesPerPixel (_data->header);
+
+ _data->maxBytesPerTileLine = _data->bytesPerPixel * _data->tileDesc.xSize;
+
+ _data->tileBufferSize = _data->maxBytesPerTileLine * _data->tileDesc.ySize;
+
+ //
+ // Create all the TileBuffers and allocate their internal buffers
+ //
+
+ for (size_t i = 0; i < _data->tileBuffers.size(); i++)
+ {
+ _data->tileBuffers[i] = new TileBuffer (newTileCompressor
+ (_data->header.compression(),
+ _data->maxBytesPerTileLine,
+ _data->tileDesc.ySize,
+ _data->header));
+
+ if (!_data->is->isMemoryMapped ())
+ _data->tileBuffers[i]->buffer = new char [_data->tileBufferSize];
+ }
+
+ _data->tileOffsets = TileOffsets (_data->tileDesc.mode,
+ _data->numXLevels,
+ _data->numYLevels,
+ _data->numXTiles,
+ _data->numYTiles);
+
+ _data->tileOffsets.readFrom (*(_data->is), _data->fileIsComplete);
+
+ _data->currentPosition = _data->is->tellg();
+}
+
+
+TiledInputFile::~TiledInputFile ()
+{
+ if (!_data->is->isMemoryMapped())
+ for (size_t i = 0; i < _data->tileBuffers.size(); i++)
+ delete [] _data->tileBuffers[i]->buffer;
+
+ delete _data;
+}
+
+
+const char *
+TiledInputFile::fileName () const
+{
+ return _data->is->fileName();
+}
+
+
+const Header &
+TiledInputFile::header () const
+{
+ return _data->header;
+}
+
+
+int
+TiledInputFile::version () const
+{
+ return _data->version;
+}
+
+
+void
+TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
+{
+ Lock lock (*_data);
+
+ //
+ // Set the frame buffer
+ //
+
+ //
+ // Check if the new frame buffer descriptor is
+ // compatible with the image file header.
+ //
+
+ const ChannelList &channels = _data->header.channels();
+
+ for (FrameBuffer::ConstIterator j = frameBuffer.begin();
+ j != frameBuffer.end();
+ ++j)
+ {
+ ChannelList::ConstIterator i = channels.find (j.name());
+
+ if (i == channels.end())
+ continue;
+
+ if (i.channel().xSampling != j.slice().xSampling ||
+ i.channel().ySampling != j.slice().ySampling)
+ THROW (Iex::ArgExc, "X and/or y subsampling factors "
+ "of \"" << i.name() << "\" channel "
+ "of input file \"" << fileName() << "\" are "
+ "not compatible with the frame buffer's "
+ "subsampling factors.");
+ }
+
+ //
+ // Initialize the slice table for readPixels().
+ //
+
+ vector<TInSliceInfo> slices;
+ ChannelList::ConstIterator i = channels.begin();
+
+ for (FrameBuffer::ConstIterator j = frameBuffer.begin();
+ j != frameBuffer.end();
+ ++j)
+ {
+ while (i != channels.end() && strcmp (i.name(), j.name()) < 0)
+ {
+ //
+ // Channel i is present in the file but not
+ // in the frame buffer; data for channel i
+ // will be skipped during readPixels().
+ //
+
+ slices.push_back (TInSliceInfo (i.channel().type,
+ i.channel().type,
+ 0, // base
+ 0, // xStride
+ 0, // yStride
+ false, // fill
+ true, // skip
+ 0.0)); // fillValue
+ ++i;
+ }
+
+ bool fill = false;
+
+ if (i == channels.end() || strcmp (i.name(), j.name()) > 0)
+ {
+ //
+ // Channel i is present in the frame buffer, but not in the file.
+ // In the frame buffer, slice j will be filled with a default value.
+ //
+
+ fill = true;
+ }
+
+ slices.push_back (TInSliceInfo (j.slice().type,
+ fill? j.slice().type: i.channel().type,
+ j.slice().base,
+ j.slice().xStride,
+ j.slice().yStride,
+ fill,
+ false, // skip
+ j.slice().fillValue,
+ (j.slice().xTileCoords)? 1: 0,
+ (j.slice().yTileCoords)? 1: 0));
+
+ if (i != channels.end() && !fill)
+ ++i;
+ }
+
+ while (i != channels.end())
+ {
+ //
+ // Channel i is present in the file but not
+ // in the frame buffer; data for channel i
+ // will be skipped during readPixels().
+ //
+
+ slices.push_back (TInSliceInfo (i.channel().type,
+ i.channel().type,
+ 0, // base
+ 0, // xStride
+ 0, // yStride
+ false, // fill
+ true, // skip
+ 0.0)); // fillValue
+ ++i;
+ }
+
+ //
+ // Store the new frame buffer.
+ //
+
+ _data->frameBuffer = frameBuffer;
+ _data->slices = slices;
+}
+
+
+const FrameBuffer &
+TiledInputFile::frameBuffer () const
+{
+ Lock lock (*_data);
+ return _data->frameBuffer;
+}
+
+
+bool
+TiledInputFile::isComplete () const
+{
+ return _data->fileIsComplete;
+}
+
+
+void
+TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly)
+{
+ //
+ // Read a range of tiles from the file into the framebuffer
+ //
+
+ try
+ {
+ Lock lock (*_data);
+
+ if (_data->slices.size() == 0)
+ throw Iex::ArgExc ("No frame buffer specified "
+ "as pixel data destination.");
+
+ //
+ // Determine the first and last tile coordinates in both dimensions.
+ // We always attempt to read the range of tiles in the order that
+ // they are stored in the file.
+ //
+
+ if (dx1 > dx2)
+ std::swap (dx1, dx2);
+
+ if (dy1 > dy2)
+ std::swap (dy1, dy2);
+
+ int dyStart = dy1;
+ int dyStop = dy2 + 1;
+ int dY = 1;
+
+ if (_data->lineOrder == DECREASING_Y)
+ {
+ dyStart = dy2;
+ dyStop = dy1 - 1;
+ dY = -1;
+ }
+
+ //
+ // Create a task group for all tile buffer tasks. When the
+ // task group goes out of scope, the destructor waits until
+ // all tasks are complete.
+ //
+
+ {
+ TaskGroup taskGroup;
+ int tileNumber = 0;
+
+ for (int dy = dyStart; dy != dyStop; dy += dY)
+ {
+ for (int dx = dx1; dx <= dx2; dx++)
+ {
+ if (!isValidTile (dx, dy, lx, ly))
+ THROW (Iex::ArgExc,
+ "Tile (" << dx << ", " << dy << ", " <<
+ lx << "," << ly << ") is not a valid tile.");
+
+ ThreadPool::addGlobalTask (newTileBufferTask (&taskGroup,
+ _data,
+ tileNumber++,
+ dx, dy,
+ lx, ly));
+ }
+ }
+
+ //
+ // finish all tasks
+ //
+ }
+
+ //
+ // Exeption handling:
+ //
+ // TileBufferTask::execute() may have encountered exceptions, but
+ // those exceptions occurred in another thread, not in the thread
+ // that is executing this call to TiledInputFile::readTiles().
+ // TileBufferTask::execute() has caught all exceptions and stored
+ // the exceptions' what() strings in the tile buffers.
+ // Now we check if any tile buffer contains a stored exception; if
+ // this is the case then we re-throw the exception in this thread.
+ // (It is possible that multiple tile buffers contain stored
+ // exceptions. We re-throw the first exception we find and
+ // ignore all others.)
+ //
+
+ const string *exception = 0;
+
+ for (int i = 0; i < _data->tileBuffers.size(); ++i)
+ {
+ TileBuffer *tileBuffer = _data->tileBuffers[i];
+
+ if (tileBuffer->hasException && !exception)
+ exception = &tileBuffer->exception;
+
+ tileBuffer->hasException = false;
+ }
+
+ if (exception)
+ throw Iex::IoExc (*exception);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading pixel data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+TiledInputFile::readTiles (int dx1, int dx2, int dy1, int dy2, int l)
+{
+ readTiles (dx1, dx2, dy1, dy2, l, l);
+}
+
+
+void
+TiledInputFile::readTile (int dx, int dy, int lx, int ly)
+{
+ readTiles (dx, dx, dy, dy, lx, ly);
+}
+
+
+void
+TiledInputFile::readTile (int dx, int dy, int l)
+{
+ readTile (dx, dy, l, l);
+}
+
+
+void
+TiledInputFile::rawTileData (int &dx, int &dy,
+ int &lx, int &ly,
+ const char *&pixelData,
+ int &pixelDataSize)
+{
+ try
+ {
+ Lock lock (*_data);
+
+ if (!isValidTile (dx, dy, lx, ly))
+ throw Iex::ArgExc ("Tried to read a tile outside "
+ "the image file's data window.");
+
+ TileBuffer *tileBuffer = _data->getTileBuffer (0);
+
+ readNextTileData (_data, dx, dy, lx, ly,
+ tileBuffer->buffer,
+ pixelDataSize);
+
+ pixelData = tileBuffer->buffer;
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error reading pixel data from image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+unsigned int
+TiledInputFile::tileXSize () const
+{
+ return _data->tileDesc.xSize;
+}
+
+
+unsigned int
+TiledInputFile::tileYSize () const
+{
+ return _data->tileDesc.ySize;
+}
+
+
+LevelMode
+TiledInputFile::levelMode () const
+{
+ return _data->tileDesc.mode;
+}
+
+
+LevelRoundingMode
+TiledInputFile::levelRoundingMode () const
+{
+ return _data->tileDesc.roundingMode;
+}
+
+
+int
+TiledInputFile::numLevels () const
+{
+ if (levelMode() == RIPMAP_LEVELS)
+ THROW (Iex::LogicExc, "Error calling numLevels() on image "
+ "file \"" << fileName() << "\" "
+ "(numLevels() is not defined for files "
+ "with RIPMAP level mode).");
+
+ return _data->numXLevels;
+}
+
+
+int
+TiledInputFile::numXLevels () const
+{
+ return _data->numXLevels;
+}
+
+
+int
+TiledInputFile::numYLevels () const
+{
+ return _data->numYLevels;
+}
+
+
+bool
+TiledInputFile::isValidLevel (int lx, int ly) const
+{
+ if (lx < 0 || ly < 0)
+ return false;
+
+ if (levelMode() == MIPMAP_LEVELS && lx != ly)
+ return false;
+
+ if (lx >= numXLevels() || ly >= numYLevels())
+ return false;
+
+ return true;
+}
+
+
+int
+TiledInputFile::levelWidth (int lx) const
+{
+ try
+ {
+ return levelSize (_data->minX, _data->maxX, lx,
+ _data->tileDesc.roundingMode);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling levelWidth() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+int
+TiledInputFile::levelHeight (int ly) const
+{
+ try
+ {
+ return levelSize (_data->minY, _data->maxY, ly,
+ _data->tileDesc.roundingMode);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling levelHeight() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+int
+TiledInputFile::numXTiles (int lx) const
+{
+ if (lx < 0 || lx >= _data->numXLevels)
+ {
+ THROW (Iex::ArgExc, "Error calling numXTiles() on image "
+ "file \"" << _data->is->fileName() << "\" "
+ "(Argument is not in valid range).");
+
+ }
+
+ return _data->numXTiles[lx];
+}
+
+
+int
+TiledInputFile::numYTiles (int ly) const
+{
+ if (ly < 0 || ly >= _data->numYLevels)
+ {
+ THROW (Iex::ArgExc, "Error calling numYTiles() on image "
+ "file \"" << _data->is->fileName() << "\" "
+ "(Argument is not in valid range).");
+ }
+
+ return _data->numYTiles[ly];
+}
+
+
+Box2i
+TiledInputFile::dataWindowForLevel (int l) const
+{
+ return dataWindowForLevel (l, l);
+}
+
+
+Box2i
+TiledInputFile::dataWindowForLevel (int lx, int ly) const
+{
+ try
+ {
+ return Imf::dataWindowForLevel (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ lx, ly);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling dataWindowForLevel() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+Box2i
+TiledInputFile::dataWindowForTile (int dx, int dy, int l) const
+{
+ return dataWindowForTile (dx, dy, l, l);
+}
+
+
+Box2i
+TiledInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
+{
+ try
+ {
+ if (!isValidTile (dx, dy, lx, ly))
+ throw Iex::ArgExc ("Arguments not in valid range.");
+
+ return Imf::dataWindowForTile (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ dx, dy, lx, ly);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling dataWindowForTile() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+bool
+TiledInputFile::isValidTile (int dx, int dy, int lx, int ly) const
+{
+ return ((lx < _data->numXLevels && lx >= 0) &&
+ (ly < _data->numYLevels && ly >= 0) &&
+ (dx < _data->numXTiles[lx] && dx >= 0) &&
+ (dy < _data->numYTiles[ly] && dy >= 0));
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTiledInputFile.h b/Source/OpenEXR/IlmImf/ImfTiledInputFile.h
new file mode 100644
index 0000000..13eb84f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledInputFile.h
@@ -0,0 +1,381 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILED_INPUT_FILE_H
+#define INCLUDED_IMF_TILED_INPUT_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// class TiledInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include "ImathBox.h"
+#include <ImfTileDescription.h>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+
+class TiledInputFile
+{
+ public:
+
+ //--------------------------------------------------------------------
+ // A constructor that opens the file with the specified name, and
+ // reads the file header. The constructor throws an Iex::ArgExc
+ // exception if the file is not tiled.
+ // The numThreads parameter specifies how many worker threads this
+ // file will try to keep busy when decompressing individual tiles.
+ // Destroying TiledInputFile objects constructed with this constructor
+ // automatically closes the corresponding files.
+ //--------------------------------------------------------------------
+
+ TiledInputFile (const char fileName[],
+ int numThreads = globalThreadCount ());
+
+
+ // ----------------------------------------------------------
+ // A constructor that attaches the new TiledInputFile object
+ // to a file that has already been opened.
+ // Destroying TiledInputFile objects constructed with this
+ // constructor does not automatically close the corresponding
+ // files.
+ // ----------------------------------------------------------
+
+ TiledInputFile (IStream &is, int numThreads = globalThreadCount ());
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~TiledInputFile ();
+
+
+ //------------------------
+ // Access to the file name
+ //------------------------
+
+ const char * fileName () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+
+
+ //----------------------------------
+ // Access to the file format version
+ //----------------------------------
+
+ int version () const;
+
+
+ //-----------------------------------------------------------
+ // Set the current frame buffer -- copies the FrameBuffer
+ // object into the TiledInputFile object.
+ //
+ // The current frame buffer is the destination for the pixel
+ // data read from the file. The current frame buffer must be
+ // set at least once before readTile() is called.
+ // The current frame buffer can be changed after each call
+ // to readTile().
+ //-----------------------------------------------------------
+
+ void setFrameBuffer (const FrameBuffer &frameBuffer);
+
+
+ //-----------------------------------
+ // Access to the current frame buffer
+ //-----------------------------------
+
+ const FrameBuffer & frameBuffer () const;
+
+
+ //------------------------------------------------------------
+ // Check if the file is complete:
+ //
+ // isComplete() returns true if all pixels in the data window
+ // (in all levels) are present in the input file, or false if
+ // any pixels are missing. (Another program may still be busy
+ // writing the file, or file writing may have been aborted
+ // prematurely.)
+ //------------------------------------------------------------
+
+ bool isComplete () const;
+
+
+ //--------------------------------------------------
+ // Utility functions:
+ //--------------------------------------------------
+
+ //---------------------------------------------------------
+ // Multiresolution mode and tile size:
+ // The following functions return the xSize, ySize and mode
+ // fields of the file header's TileDescriptionAttribute.
+ //---------------------------------------------------------
+
+ unsigned int tileXSize () const;
+ unsigned int tileYSize () const;
+ LevelMode levelMode () const;
+ LevelRoundingMode levelRoundingMode () const;
+
+
+ //--------------------------------------------------------------------
+ // Number of levels:
+ //
+ // numXLevels() returns the file's number of levels in x direction.
+ //
+ // if levelMode() == ONE_LEVEL:
+ // return value is: 1
+ //
+ // if levelMode() == MIPMAP_LEVELS:
+ // return value is: rfunc (log (max (w, h)) / log (2)) + 1
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // return value is: rfunc (log (w) / log (2)) + 1
+ //
+ // where
+ // w is the width of the image's data window, max.x - min.x + 1,
+ // y is the height of the image's data window, max.y - min.y + 1,
+ // and rfunc(x) is either floor(x), or ceil(x), depending on
+ // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP.
+ //
+ // numYLevels() returns the file's number of levels in y direction.
+ //
+ // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
+ // return value is the same as for numXLevels()
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // return value is: rfunc (log (h) / log (2)) + 1
+ //
+ //
+ // numLevels() is a convenience function for use with
+ // MIPMAP_LEVELS files.
+ //
+ // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
+ // return value is the same as for numXLevels()
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // an Iex::LogicExc exception is thrown
+ //
+ // isValidLevel(lx, ly) returns true if the file contains
+ // a level with level number (lx, ly), false if not.
+ //
+ //--------------------------------------------------------------------
+
+ int numLevels () const;
+ int numXLevels () const;
+ int numYLevels () const;
+ bool isValidLevel (int lx, int ly) const;
+
+
+ //----------------------------------------------------------
+ // Dimensions of a level:
+ //
+ // levelWidth(lx) returns the width of a level with level
+ // number (lx, *), where * is any number.
+ //
+ // return value is:
+ // max (1, rfunc (w / pow (2, lx)))
+ //
+ //
+ // levelHeight(ly) returns the height of a level with level
+ // number (*, ly), where * is any number.
+ //
+ // return value is:
+ // max (1, rfunc (h / pow (2, ly)))
+ //
+ //----------------------------------------------------------
+
+ int levelWidth (int lx) const;
+ int levelHeight (int ly) const;
+
+
+ //--------------------------------------------------------------
+ // Number of tiles:
+ //
+ // numXTiles(lx) returns the number of tiles in x direction
+ // that cover a level with level number (lx, *), where * is
+ // any number.
+ //
+ // return value is:
+ // (levelWidth(lx) + tileXSize() - 1) / tileXSize()
+ //
+ //
+ // numYTiles(ly) returns the number of tiles in y direction
+ // that cover a level with level number (*, ly), where * is
+ // any number.
+ //
+ // return value is:
+ // (levelHeight(ly) + tileXSize() - 1) / tileXSize()
+ //
+ //--------------------------------------------------------------
+
+ int numXTiles (int lx = 0) const;
+ int numYTiles (int ly = 0) const;
+
+
+ //---------------------------------------------------------------
+ // Level pixel ranges:
+ //
+ // dataWindowForLevel(lx, ly) returns a 2-dimensional region of
+ // valid pixel coordinates for a level with level number (lx, ly)
+ //
+ // return value is a Box2i with min value:
+ // (dataWindow.min.x, dataWindow.min.y)
+ //
+ // and max value:
+ // (dataWindow.min.x + levelWidth(lx) - 1,
+ // dataWindow.min.y + levelHeight(ly) - 1)
+ //
+ // dataWindowForLevel(level) is a convenience function used
+ // for ONE_LEVEL and MIPMAP_LEVELS files. It returns
+ // dataWindowForLevel(level, level).
+ //
+ //---------------------------------------------------------------
+
+ Imath::Box2i dataWindowForLevel (int l = 0) const;
+ Imath::Box2i dataWindowForLevel (int lx, int ly) const;
+
+
+ //-------------------------------------------------------------------
+ // Tile pixel ranges:
+ //
+ // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional
+ // region of valid pixel coordinates for a tile with tile coordinates
+ // (dx,dy) and level number (lx, ly).
+ //
+ // return value is a Box2i with min value:
+ // (dataWindow.min.x + dx * tileXSize(),
+ // dataWindow.min.y + dy * tileYSize())
+ //
+ // and max value:
+ // (dataWindow.min.x + (dx + 1) * tileXSize() - 1,
+ // dataWindow.min.y + (dy + 1) * tileYSize() - 1)
+ //
+ // dataWindowForTile(dx, dy, level) is a convenience function
+ // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns
+ // dataWindowForTile(dx, dy, level, level).
+ //
+ //-------------------------------------------------------------------
+
+ Imath::Box2i dataWindowForTile (int dx, int dy, int l = 0) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int lx, int ly) const;
+
+ //------------------------------------------------------------
+ // Read pixel data:
+ //
+ // readTile(dx, dy, lx, ly) reads the tile with tile
+ // coordinates (dx, dy), and level number (lx, ly),
+ // and stores it in the current frame buffer.
+ //
+ // dx must lie in the interval [0, numXTiles(lx)-1]
+ // dy must lie in the interval [0, numYTiles(ly)-1]
+ //
+ // lx must lie in the interval [0, numXLevels()-1]
+ // ly must lie in the inverval [0, numYLevels()-1]
+ //
+ // readTile(dx, dy, level) is a convenience function used
+ // for ONE_LEVEL and MIPMAP_LEVELS files. It calls
+ // readTile(dx, dy, level, level).
+ //
+ // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow
+ // reading multiple tiles at once. If multi-threading is used
+ // the multiple tiles are read concurrently.
+ //
+ // Pixels that are outside the pixel coordinate range for the
+ // tile's level, are never accessed by readTile().
+ //
+ // Attempting to access a tile that is not present in the file
+ // throws an InputExc exception.
+ //
+ //------------------------------------------------------------
+
+ void readTile (int dx, int dy, int l = 0);
+ void readTile (int dx, int dy, int lx, int ly);
+
+ void readTiles (int dx1, int dx2, int dy1, int dy2,
+ int lx, int ly);
+
+ void readTiles (int dx1, int dx2, int dy1, int dy2,
+ int l = 0);
+
+
+ //--------------------------------------------------
+ // Read a tile of raw pixel data from the file,
+ // without uncompressing it (this function is
+ // used to implement TiledOutputFile::copyPixels()).
+ //--------------------------------------------------
+
+ void rawTileData (int &dx, int &dy,
+ int &lx, int &ly,
+ const char *&pixelData,
+ int &pixelDataSize);
+
+ struct Data;
+
+ private:
+
+ friend class InputFile;
+
+ TiledInputFile (const TiledInputFile &); // not implemented
+ TiledInputFile & operator = (const TiledInputFile &); // not implemented
+
+ TiledInputFile (const Header &header, IStream *is, int version,
+ int numThreads);
+
+ void initialize ();
+
+ bool isValidTile (int dx, int dy,
+ int lx, int ly) const;
+
+ size_t bytesPerLineForTile (int dx, int dy,
+ int lx, int ly) const;
+
+ Data * _data;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTiledMisc.cpp b/Source/OpenEXR/IlmImf/ImfTiledMisc.cpp
new file mode 100644
index 0000000..7c723bb
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledMisc.cpp
@@ -0,0 +1,301 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Miscellaneous stuff related to tiled files
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTiledMisc.h>
+#include "Iex.h"
+#include <ImfMisc.h>
+#include <ImfChannelList.h>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::V2i;
+
+
+int
+levelSize (int min, int max, int l, LevelRoundingMode rmode)
+{
+ if (l < 0)
+ throw Iex::ArgExc ("Argument not in valid range.");
+
+ int a = max - min + 1;
+ int b = (1 << l);
+ int size = a / b;
+
+ if (rmode == ROUND_UP && size * b < a)
+ size += 1;
+
+ return std::max (size, 1);
+}
+
+
+Box2i
+dataWindowForLevel (const TileDescription &tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int lx, int ly)
+{
+ V2i levelMin = V2i (minX, minY);
+
+ V2i levelMax = levelMin +
+ V2i (levelSize (minX, maxX, lx, tileDesc.roundingMode) - 1,
+ levelSize (minY, maxY, ly, tileDesc.roundingMode) - 1);
+
+ return Box2i(levelMin, levelMax);
+}
+
+
+Box2i
+dataWindowForTile (const TileDescription &tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int dx, int dy,
+ int lx, int ly)
+{
+ V2i tileMin = V2i (minX + dx * tileDesc.xSize,
+ minY + dy * tileDesc.ySize);
+
+ V2i tileMax = tileMin + V2i (tileDesc.xSize - 1, tileDesc.ySize - 1);
+
+ V2i levelMax = dataWindowForLevel
+ (tileDesc, minX, maxX, minY, maxY, lx, ly).max;
+
+ tileMax = V2i (std::min (tileMax[0], levelMax[0]),
+ std::min (tileMax[1], levelMax[1]));
+
+ return Box2i (tileMin, tileMax);
+}
+
+
+size_t
+calculateBytesPerPixel (const Header &header)
+{
+ const ChannelList &channels = header.channels();
+
+ size_t bytesPerPixel = 0;
+
+ for (ChannelList::ConstIterator c = channels.begin();
+ c != channels.end();
+ ++c)
+ {
+ bytesPerPixel += pixelTypeSize (c.channel().type);
+ }
+
+ return bytesPerPixel;
+}
+
+
+namespace {
+
+int
+floorLog2 (int x)
+{
+ //
+ // For x > 0, floorLog2(y) returns floor(log(x)/log(2)).
+ //
+
+ int y = 0;
+
+ while (x > 1)
+ {
+ y += 1;
+ x >>= 1;
+ }
+
+ return y;
+}
+
+
+int
+ceilLog2 (int x)
+{
+ //
+ // For x > 0, ceilLog2(y) returns ceil(log(x)/log(2)).
+ //
+
+ int y = 0;
+ int r = 0;
+
+ while (x > 1)
+ {
+ if (x & 1)
+ r = 1;
+
+ y += 1;
+ x >>= 1;
+ }
+
+ return y + r;
+}
+
+
+int
+roundLog2 (int x, LevelRoundingMode rmode)
+{
+ return (rmode == ROUND_DOWN)? floorLog2 (x): ceilLog2 (x);
+}
+
+
+int
+calculateNumXLevels (const TileDescription& tileDesc,
+ int minX, int maxX,
+ int minY, int maxY)
+{
+ int num = 0;
+
+ switch (tileDesc.mode)
+ {
+ case ONE_LEVEL:
+
+ num = 1;
+ break;
+
+ case MIPMAP_LEVELS:
+
+ {
+ int w = maxX - minX + 1;
+ int h = maxY - minY + 1;
+ num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
+ }
+ break;
+
+ case RIPMAP_LEVELS:
+
+ {
+ int w = maxX - minX + 1;
+ num = roundLog2 (w, tileDesc.roundingMode) + 1;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown LevelMode format.");
+ }
+
+ return num;
+}
+
+
+int
+calculateNumYLevels (const TileDescription& tileDesc,
+ int minX, int maxX,
+ int minY, int maxY)
+{
+ int num = 0;
+
+ switch (tileDesc.mode)
+ {
+ case ONE_LEVEL:
+
+ num = 1;
+ break;
+
+ case MIPMAP_LEVELS:
+
+ {
+ int w = maxX - minX + 1;
+ int h = maxY - minY + 1;
+ num = roundLog2 (std::max (w, h), tileDesc.roundingMode) + 1;
+ }
+ break;
+
+ case RIPMAP_LEVELS:
+
+ {
+ int h = maxY - minY + 1;
+ num = roundLog2 (h, tileDesc.roundingMode) + 1;
+ }
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown LevelMode format.");
+ }
+
+ return num;
+}
+
+
+void
+calculateNumTiles (int *numTiles,
+ int numLevels,
+ int min, int max,
+ int size,
+ LevelRoundingMode rmode)
+{
+ for (int i = 0; i < numLevels; i++)
+ {
+ numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size;
+ }
+}
+
+} // namespace
+
+
+void
+precalculateTileInfo (const TileDescription& tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int *&numXTiles, int *&numYTiles,
+ int &numXLevels, int &numYLevels)
+{
+ numXLevels = calculateNumXLevels(tileDesc, minX, maxX, minY, maxY);
+ numYLevels = calculateNumYLevels(tileDesc, minX, maxX, minY, maxY);
+
+ numXTiles = new int[numXLevels];
+ numYTiles = new int[numYLevels];
+
+ calculateNumTiles (numXTiles,
+ numXLevels,
+ minX, maxX,
+ tileDesc.xSize,
+ tileDesc.roundingMode);
+
+ calculateNumTiles (numYTiles,
+ numYLevels,
+ minY, maxY,
+ tileDesc.ySize,
+ tileDesc.roundingMode);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTiledMisc.h b/Source/OpenEXR/IlmImf/ImfTiledMisc.h
new file mode 100644
index 0000000..9342c6f
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledMisc.h
@@ -0,0 +1,75 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILED_MISC_H
+#define INCLUDED_IMF_TILED_MISC_H
+
+//-----------------------------------------------------------------------------
+//
+// Miscellaneous stuff related to tiled files
+//
+//-----------------------------------------------------------------------------
+
+#include "ImathBox.h"
+#include <ImfHeader.h>
+#include <stdio.h>
+
+namespace Imf {
+
+int levelSize (int min, int max, int l, LevelRoundingMode rmode);
+
+Imath::Box2i dataWindowForLevel (const TileDescription &tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int lx, int ly);
+
+Imath::Box2i dataWindowForTile (const TileDescription &tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int dx, int dy,
+ int lx, int ly);
+
+size_t calculateBytesPerPixel (const Header &header);
+
+void precalculateTileInfo (const TileDescription& tileDesc,
+ int minX, int maxX,
+ int minY, int maxY,
+ int *&numXTiles, int *&numYTiles,
+ int &numXLevels, int &numYLevels);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTiledOutputFile.cpp b/Source/OpenEXR/IlmImf/ImfTiledOutputFile.cpp
new file mode 100644
index 0000000..9a96ac9
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledOutputFile.cpp
@@ -0,0 +1,1692 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class TiledOutputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTiledOutputFile.h>
+#include <ImfTiledInputFile.h>
+#include <ImfInputFile.h>
+#include <ImfTileDescriptionAttribute.h>
+#include <ImfPreviewImageAttribute.h>
+#include <ImfChannelList.h>
+#include <ImfMisc.h>
+#include <ImfTiledMisc.h>
+#include <ImfStdIO.h>
+#include <ImfCompressor.h>
+#include "ImathBox.h"
+#include <ImfArray.h>
+#include <ImfXdr.h>
+#include <ImfVersion.h>
+#include <ImfTileOffsets.h>
+#include <ImfThreading.h>
+#include "IlmThreadPool.h"
+#include "IlmThreadSemaphore.h"
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <string>
+#include <vector>
+#include <fstream>
+#include <assert.h>
+#include <map>
+
+
+namespace Imf {
+
+using Imath::Box2i;
+using Imath::V2i;
+using std::string;
+using std::vector;
+using std::ofstream;
+using std::map;
+using std::min;
+using std::max;
+using std::swap;
+using IlmThread::Mutex;
+using IlmThread::Lock;
+using IlmThread::Semaphore;
+using IlmThread::Task;
+using IlmThread::TaskGroup;
+using IlmThread::ThreadPool;
+
+namespace {
+
+struct TOutSliceInfo
+{
+ PixelType type;
+ const char * base;
+ size_t xStride;
+ size_t yStride;
+ bool zero;
+ int xTileCoords;
+ int yTileCoords;
+
+ TOutSliceInfo (PixelType type = HALF,
+ const char *base = 0,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ bool zero = false,
+ int xTileCoords = 0,
+ int yTileCoords = 0);
+};
+
+
+TOutSliceInfo::TOutSliceInfo (PixelType t,
+ const char *b,
+ size_t xs, size_t ys,
+ bool z,
+ int xtc,
+ int ytc)
+:
+ type (t),
+ base (b),
+ xStride (xs),
+ yStride (ys),
+ zero (z),
+ xTileCoords (xtc),
+ yTileCoords (ytc)
+{
+ // empty
+}
+
+
+struct TileCoord
+{
+ int dx;
+ int dy;
+ int lx;
+ int ly;
+
+
+ TileCoord (int xTile = 0, int yTile = 0,
+ int xLevel = 0, int yLevel = 0)
+ :
+ dx (xTile), dy (yTile),
+ lx (xLevel), ly (yLevel)
+ {
+ // empty
+ }
+
+
+ bool
+ operator < (const TileCoord &other) const
+ {
+ return (ly < other.ly) ||
+ (ly == other.ly && lx < other.lx) ||
+ ((ly == other.ly && lx == other.lx) &&
+ ((dy < other.dy) || (dy == other.dy && dx < other.dx)));
+ }
+
+
+ bool
+ operator == (const TileCoord &other) const
+ {
+ return lx == other.lx &&
+ ly == other.ly &&
+ dx == other.dx &&
+ dy == other.dy;
+ }
+};
+
+
+struct BufferedTile
+{
+ char * pixelData;
+ int pixelDataSize;
+
+ BufferedTile (const char *data, int size):
+ pixelData (0),
+ pixelDataSize(size)
+ {
+ pixelData = new char[pixelDataSize];
+ memcpy (pixelData, data, pixelDataSize);
+ }
+
+ ~BufferedTile()
+ {
+ delete [] pixelData;
+ }
+};
+
+
+typedef map <TileCoord, BufferedTile *> TileMap;
+
+
+struct TileBuffer
+{
+ Array<char> buffer;
+ const char * dataPtr;
+ int dataSize;
+ Compressor * compressor;
+ TileCoord tileCoord;
+ bool hasException;
+ string exception;
+
+ TileBuffer (Compressor *comp);
+ ~TileBuffer ();
+
+ inline void wait () {_sem.wait();}
+ inline void post () {_sem.post();}
+
+ protected:
+
+ Semaphore _sem;
+};
+
+
+TileBuffer::TileBuffer (Compressor *comp):
+ dataPtr (0),
+ dataSize (0),
+ compressor (comp),
+ hasException (false),
+ exception (),
+ _sem (1)
+{
+ // empty
+}
+
+
+TileBuffer::~TileBuffer ()
+{
+ delete compressor;
+}
+
+
+} // namespace
+
+
+struct TiledOutputFile::Data: public Mutex
+{
+ Header header; // the image header
+ int version; // file format version
+ TileDescription tileDesc; // describes the tile layout
+ FrameBuffer frameBuffer; // framebuffer to write into
+ Int64 previewPosition;
+ LineOrder lineOrder; // the file's lineorder
+ int minX; // data window's min x coord
+ int maxX; // data window's max x coord
+ int minY; // data window's min y coord
+ int maxY; // data window's max x coord
+
+ int numXLevels; // number of x levels
+ int numYLevels; // number of y levels
+ int * numXTiles; // number of x tiles at a level
+ int * numYTiles; // number of y tiles at a level
+
+ TileOffsets tileOffsets; // stores offsets in file for
+ // each tile
+
+ Compressor::Format format; // compressor's data format
+ vector<TOutSliceInfo> slices; // info about channels in file
+ OStream * os; // file stream to write to
+ bool deleteStream;
+
+ size_t maxBytesPerTileLine; // combined size of a tile line
+ // over all channels
+
+
+ vector<TileBuffer*> tileBuffers;
+ size_t tileBufferSize; // size of a tile buffer
+
+ Int64 tileOffsetsPosition; // position of the tile index
+ Int64 currentPosition; // current position in the file
+
+ TileMap tileMap;
+ TileCoord nextTileToWrite;
+
+ Data (bool del, int numThreads);
+ ~Data ();
+
+ inline TileBuffer * getTileBuffer (int number);
+ // hash function from tile
+ // buffer coords into our
+ // vector of tile buffers
+
+ TileCoord nextTileCoord (const TileCoord &a);
+};
+
+
+TiledOutputFile::Data::Data (bool del, int numThreads):
+ numXTiles(0),
+ numYTiles(0),
+ os (0),
+ deleteStream (del),
+ tileOffsetsPosition (0)
+{
+ //
+ // We need at least one tileBuffer, but if threading is used,
+ // to keep n threads busy we need 2*n tileBuffers
+ //
+
+ tileBuffers.resize (max (1, 2 * numThreads));
+}
+
+
+TiledOutputFile::Data::~Data ()
+{
+ delete [] numXTiles;
+ delete [] numYTiles;
+
+ if (deleteStream)
+ delete os;
+
+ //
+ // Delete all the tile buffers, if any still happen to exist
+ //
+
+ for (TileMap::iterator i = tileMap.begin(); i != tileMap.end(); ++i)
+ delete i->second;
+
+ for (size_t i = 0; i < tileBuffers.size(); i++)
+ delete tileBuffers[i];
+}
+
+
+TileBuffer*
+TiledOutputFile::Data::getTileBuffer (int number)
+{
+ return tileBuffers[number % tileBuffers.size()];
+}
+
+
+TileCoord
+TiledOutputFile::Data::nextTileCoord (const TileCoord &a)
+{
+ TileCoord b = a;
+
+ if (lineOrder == INCREASING_Y)
+ {
+ b.dx++;
+
+ if (b.dx >= numXTiles[b.lx])
+ {
+ b.dx = 0;
+ b.dy++;
+
+ if (b.dy >= numYTiles[b.ly])
+ {
+ //
+ // the next tile is in the next level
+ //
+
+ b.dy = 0;
+
+ switch (tileDesc.mode)
+ {
+ case ONE_LEVEL:
+ case MIPMAP_LEVELS:
+
+ b.lx++;
+ b.ly++;
+ break;
+
+ case RIPMAP_LEVELS:
+
+ b.lx++;
+
+ if (b.lx >= numXLevels)
+ {
+ b.lx = 0;
+ b.ly++;
+
+ #ifdef DEBUG
+ assert (b.ly <= numYLevels);
+ #endif
+ }
+ break;
+ }
+ }
+ }
+ }
+ else if (lineOrder == DECREASING_Y)
+ {
+ b.dx++;
+
+ if (b.dx >= numXTiles[b.lx])
+ {
+ b.dx = 0;
+ b.dy--;
+
+ if (b.dy < 0)
+ {
+ //
+ // the next tile is in the next level
+ //
+
+ switch (tileDesc.mode)
+ {
+ case ONE_LEVEL:
+ case MIPMAP_LEVELS:
+
+ b.lx++;
+ b.ly++;
+ break;
+
+ case RIPMAP_LEVELS:
+
+ b.lx++;
+
+ if (b.lx >= numXLevels)
+ {
+ b.lx = 0;
+ b.ly++;
+
+ #ifdef DEBUG
+ assert (b.ly <= numYLevels);
+ #endif
+ }
+ break;
+ }
+
+ if (b.ly < numYLevels)
+ b.dy = numYTiles[b.ly] - 1;
+ }
+ }
+ }
+
+ return b;
+}
+
+
+namespace {
+
+void
+writeTileData (TiledOutputFile::Data *ofd,
+ int dx, int dy,
+ int lx, int ly,
+ const char pixelData[],
+ int pixelDataSize)
+{
+ //
+ // Store a block of pixel data in the output file, and try
+ // to keep track of the current writing position the file,
+ // without calling tellp() (tellp() can be fairly expensive).
+ //
+
+ Int64 currentPosition = ofd->currentPosition;
+ ofd->currentPosition = 0;
+
+ if (currentPosition == 0)
+ currentPosition = ofd->os->tellp();
+
+ ofd->tileOffsets (dx, dy, lx, ly) = currentPosition;
+
+ #ifdef DEBUG
+ assert (ofd->os->tellp() == currentPosition);
+ #endif
+
+ //
+ // Write the tile header.
+ //
+
+ Xdr::write <StreamIO> (*ofd->os, dx);
+ Xdr::write <StreamIO> (*ofd->os, dy);
+ Xdr::write <StreamIO> (*ofd->os, lx);
+ Xdr::write <StreamIO> (*ofd->os, ly);
+ Xdr::write <StreamIO> (*ofd->os, pixelDataSize);
+
+ ofd->os->write (pixelData, pixelDataSize);
+
+ //
+ // Keep current position in the file so that we can avoid
+ // redundant seekg() operations (seekg() can be fairly expensive).
+ //
+
+ ofd->currentPosition = currentPosition +
+ 5 * Xdr::size<int>() +
+ pixelDataSize;
+}
+
+
+
+void
+bufferedTileWrite (TiledOutputFile::Data *ofd,
+ int dx, int dy,
+ int lx, int ly,
+ const char pixelData[],
+ int pixelDataSize)
+{
+ //
+ // Check if a tile with coordinates (dx,dy,lx,ly) has already been written.
+ //
+
+ if (ofd->tileOffsets (dx, dy, lx, ly))
+ {
+ THROW (Iex::ArgExc,
+ "Attempt to write tile "
+ "(" << dx << ", " << dy << ", " << lx << "," << ly << ") "
+ "more than once.");
+ }
+
+ //
+ // If tiles can be written in random order, then don't buffer anything.
+ //
+
+ if (ofd->lineOrder == RANDOM_Y)
+ {
+ writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize);
+ return;
+ }
+
+ //
+ // If the tiles cannot be written in random order, then check if a
+ // tile with coordinates (dx,dy,lx,ly) has already been buffered.
+ //
+
+ TileCoord currentTile = TileCoord(dx, dy, lx, ly);
+
+ if (ofd->tileMap.find (currentTile) != ofd->tileMap.end())
+ {
+ THROW (Iex::ArgExc,
+ "Attempt to write tile "
+ "(" << dx << ", " << dy << ", " << lx << "," << ly << ") "
+ "more than once.");
+ }
+
+ //
+ // If all the tiles before this one have already been written to the file,
+ // then write this tile immediately and check if we have buffered tiles
+ // that can be written after this tile.
+ //
+ // Otherwise, buffer the tile so it can be written to file later.
+ //
+
+ if (ofd->nextTileToWrite == currentTile)
+ {
+ writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize);
+ ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite);
+
+ TileMap::iterator i = ofd->tileMap.find (ofd->nextTileToWrite);
+
+ //
+ // Step through the tiles and write all successive buffered tiles after
+ // the current one.
+ //
+
+ while(i != ofd->tileMap.end())
+ {
+ //
+ // Write the tile, and then delete the tile's buffered data
+ //
+
+ writeTileData (ofd,
+ i->first.dx, i->first.dy,
+ i->first.lx, i->first.ly,
+ i->second->pixelData,
+ i->second->pixelDataSize);
+
+ delete i->second;
+ ofd->tileMap.erase (i);
+
+ //
+ // Proceed to the next tile
+ //
+
+ ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite);
+ i = ofd->tileMap.find (ofd->nextTileToWrite);
+ }
+ }
+ else
+ {
+ //
+ // Create a new BufferedTile, copy the pixelData into it, and
+ // insert it into the tileMap.
+ //
+
+ ofd->tileMap[currentTile] =
+ new BufferedTile ((const char *)pixelData, pixelDataSize);
+ }
+}
+
+
+void
+convertToXdr (TiledOutputFile::Data *ofd,
+ Array<char>& tileBuffer,
+ int numScanLines,
+ int numPixelsPerScanLine)
+{
+ //
+ // Convert the contents of a TiledOutputFile's tileBuffer from the
+ // machine's native representation to Xdr format. This function is called
+ // by writeTile(), below, if the compressor wanted its input pixel data
+ // in the machine's native format, but then failed to compress the data
+ // (most compressors will expand rather than compress random input data).
+ //
+ // Note that this routine assumes that the machine's native representation
+ // of the pixel data has the same size as the Xdr representation. This
+ // makes it possible to convert the pixel data in place, without an
+ // intermediate temporary buffer.
+ //
+
+ //
+ // Set these to point to the start of the tile.
+ // We will write to toPtr, and read from fromPtr.
+ //
+
+ char *writePtr = tileBuffer;
+ const char *readPtr = writePtr;
+
+ //
+ // Iterate over all scan lines in the tile.
+ //
+
+ for (int y = 0; y < numScanLines; ++y)
+ {
+ //
+ // Iterate over all slices in the file.
+ //
+
+ for (unsigned int i = 0; i < ofd->slices.size(); ++i)
+ {
+ const TOutSliceInfo &slice = ofd->slices[i];
+
+ //
+ // Convert the samples in place.
+ //
+
+ convertInPlace (writePtr, readPtr, slice.type,
+ numPixelsPerScanLine);
+ }
+ }
+
+ #ifdef DEBUG
+
+ assert (writePtr == readPtr);
+
+ #endif
+}
+
+
+//
+// A TileBufferTask encapsulates the task of copying a tile from
+// the user's framebuffer into a LineBuffer and compressing the data
+// if necessary.
+//
+
+class TileBufferTask: public Task
+{
+ public:
+
+ TileBufferTask (TaskGroup *group,
+ TiledOutputFile::Data *ofd,
+ int number,
+ int dx, int dy,
+ int lx, int ly);
+
+ virtual ~TileBufferTask ();
+
+ virtual void execute ();
+
+ private:
+
+ TiledOutputFile::Data * _ofd;
+ TileBuffer * _tileBuffer;
+};
+
+
+TileBufferTask::TileBufferTask
+ (TaskGroup *group,
+ TiledOutputFile::Data *ofd,
+ int number,
+ int dx, int dy,
+ int lx, int ly)
+:
+ Task (group),
+ _ofd (ofd),
+ _tileBuffer (_ofd->getTileBuffer (number))
+{
+ //
+ // Wait for the tileBuffer to become available
+ //
+
+ _tileBuffer->wait ();
+ _tileBuffer->tileCoord = TileCoord (dx, dy, lx, ly);
+}
+
+
+TileBufferTask::~TileBufferTask ()
+{
+ //
+ // Signal that the tile buffer is now free
+ //
+
+ _tileBuffer->post ();
+}
+
+
+void
+TileBufferTask::execute ()
+{
+ try
+ {
+ //
+ // First copy the pixel data from the frame buffer
+ // into the tile buffer
+ //
+ // Convert one tile's worth of pixel data to
+ // a machine-independent representation, and store
+ // the result in _tileBuffer->buffer.
+ //
+
+ char *writePtr = _tileBuffer->buffer;
+
+ Box2i tileRange = Imf::dataWindowForTile (_ofd->tileDesc,
+ _ofd->minX, _ofd->maxX,
+ _ofd->minY, _ofd->maxY,
+ _tileBuffer->tileCoord.dx,
+ _tileBuffer->tileCoord.dy,
+ _tileBuffer->tileCoord.lx,
+ _tileBuffer->tileCoord.ly);
+
+ int numScanLines = tileRange.max.y - tileRange.min.y + 1;
+ int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1;
+
+ //
+ // Iterate over the scan lines in the tile.
+ //
+
+ for (int y = tileRange.min.y; y <= tileRange.max.y; ++y)
+ {
+ //
+ // Iterate over all image channels.
+ //
+
+ for (unsigned int i = 0; i < _ofd->slices.size(); ++i)
+ {
+ const TOutSliceInfo &slice = _ofd->slices[i];
+
+ //
+ // These offsets are used to facilitate both absolute
+ // and tile-relative pixel coordinates.
+ //
+
+ int xOffset = slice.xTileCoords * tileRange.min.x;
+ int yOffset = slice.yTileCoords * tileRange.min.y;
+
+ //
+ // Fill the tile buffer with pixel data.
+ //
+
+ if (slice.zero)
+ {
+ //
+ // The frame buffer contains no data for this channel.
+ // Store zeroes in _data->tileBuffer.
+ //
+
+ fillChannelWithZeroes (writePtr, _ofd->format, slice.type,
+ numPixelsPerScanLine);
+ }
+ else
+ {
+ //
+ // The frame buffer contains data for this channel.
+ //
+
+ const char *readPtr = slice.base +
+ (y - yOffset) * slice.yStride +
+ (tileRange.min.x - xOffset) *
+ slice.xStride;
+
+ const char *endPtr = readPtr +
+ (numPixelsPerScanLine - 1) *
+ slice.xStride;
+
+ copyFromFrameBuffer (writePtr, readPtr, endPtr,
+ slice.xStride, _ofd->format,
+ slice.type);
+ }
+ }
+ }
+
+ //
+ // Compress the contents of the tileBuffer,
+ // and store the compressed data in the output file.
+ //
+
+ _tileBuffer->dataSize = writePtr - _tileBuffer->buffer;
+ _tileBuffer->dataPtr = _tileBuffer->buffer;
+
+ if (_tileBuffer->compressor)
+ {
+ const char *compPtr;
+
+ int compSize = _tileBuffer->compressor->compressTile
+ (_tileBuffer->dataPtr,
+ _tileBuffer->dataSize,
+ tileRange, compPtr);
+
+ if (compSize < _tileBuffer->dataSize)
+ {
+ _tileBuffer->dataSize = compSize;
+ _tileBuffer->dataPtr = compPtr;
+ }
+ else if (_ofd->format == Compressor::NATIVE)
+ {
+ //
+ // The data did not shrink during compression, but
+ // we cannot write to the file using native format,
+ // so we need to convert the lineBuffer to Xdr.
+ //
+
+ convertToXdr (_ofd, _tileBuffer->buffer, numScanLines,
+ numPixelsPerScanLine);
+ }
+ }
+ }
+ catch (std::exception &e)
+ {
+ if (!_tileBuffer->hasException)
+ {
+ _tileBuffer->exception = e.what ();
+ _tileBuffer->hasException = true;
+ }
+ }
+ catch (...)
+ {
+ if (!_tileBuffer->hasException)
+ {
+ _tileBuffer->exception = "unrecognized exception";
+ _tileBuffer->hasException = true;
+ }
+ }
+}
+
+} // namespace
+
+
+TiledOutputFile::TiledOutputFile
+ (const char fileName[],
+ const Header &header,
+ int numThreads)
+:
+ _data (new Data (true, numThreads))
+{
+ try
+ {
+ header.sanityCheck (true);
+ _data->os = new StdOFStream (fileName);
+ initialize (header);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << fileName << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+TiledOutputFile::TiledOutputFile
+ (OStream &os,
+ const Header &header,
+ int numThreads)
+:
+ _data (new Data (false, numThreads))
+{
+ try
+ {
+ header.sanityCheck(true);
+ _data->os = &os;
+ initialize (header);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ delete _data;
+
+ REPLACE_EXC (e, "Cannot open image file "
+ "\"" << os.fileName() << "\". " << e);
+ throw;
+ }
+ catch (...)
+ {
+ delete _data;
+ throw;
+ }
+}
+
+
+void
+TiledOutputFile::initialize (const Header &header)
+{
+ _data->header = header;
+ _data->lineOrder = _data->header.lineOrder();
+
+ //
+ // Check that the file is indeed tiled
+ //
+
+ _data->tileDesc = _data->header.tileDescription();
+
+ //
+ // Save the dataWindow information
+ //
+
+ const Box2i &dataWindow = _data->header.dataWindow();
+ _data->minX = dataWindow.min.x;
+ _data->maxX = dataWindow.max.x;
+ _data->minY = dataWindow.min.y;
+ _data->maxY = dataWindow.max.y;
+
+ //
+ // Precompute level and tile information to speed up utility functions
+ //
+
+ precalculateTileInfo (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ _data->numXTiles, _data->numYTiles,
+ _data->numXLevels, _data->numYLevels);
+
+ //
+ // Determine the first tile coordinate that we will be writing
+ // if the file is not RANDOM_Y.
+ //
+
+ _data->nextTileToWrite = (_data->lineOrder == INCREASING_Y)?
+ TileCoord (0, 0, 0, 0):
+ TileCoord (0, _data->numYTiles[0] - 1, 0, 0);
+
+ _data->maxBytesPerTileLine =
+ calculateBytesPerPixel (_data->header) * _data->tileDesc.xSize;
+
+ _data->tileBufferSize = _data->maxBytesPerTileLine * _data->tileDesc.ySize;
+
+ //
+ // Create all the TileBuffers and allocate their internal buffers
+ //
+
+ for (size_t i = 0; i < _data->tileBuffers.size(); i++)
+ {
+ _data->tileBuffers[i] = new TileBuffer (newTileCompressor
+ (_data->header.compression(),
+ _data->maxBytesPerTileLine,
+ _data->tileDesc.ySize,
+ _data->header));
+
+ _data->tileBuffers[i]->buffer.resizeErase(_data->tileBufferSize);
+ }
+
+ _data->format = defaultFormat (_data->tileBuffers[0]->compressor);
+
+ _data->tileOffsets = TileOffsets (_data->tileDesc.mode,
+ _data->numXLevels,
+ _data->numYLevels,
+ _data->numXTiles,
+ _data->numYTiles);
+
+ _data->previewPosition = _data->header.writeTo (*_data->os, true);
+
+ _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_data->os);
+ _data->currentPosition = _data->os->tellp();
+}
+
+
+TiledOutputFile::~TiledOutputFile ()
+{
+ if (_data)
+ {
+ {
+ if (_data->tileOffsetsPosition > 0)
+ {
+ try
+ {
+ _data->os->seekp (_data->tileOffsetsPosition);
+ _data->tileOffsets.writeTo (*_data->os);
+ }
+ catch (...)
+ {
+ //
+ // We cannot safely throw any exceptions from here.
+ // This destructor may have been called because the
+ // stack is currently being unwound for another
+ // exception.
+ //
+ }
+ }
+ }
+
+ delete _data;
+ }
+}
+
+
+const char *
+TiledOutputFile::fileName () const
+{
+ return _data->os->fileName();
+}
+
+
+const Header &
+TiledOutputFile::header () const
+{
+ return _data->header;
+}
+
+
+void
+TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
+{
+ Lock lock (*_data);
+
+ //
+ // Check if the new frame buffer descriptor
+ // is compatible with the image file header.
+ //
+
+ const ChannelList &channels = _data->header.channels();
+
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ FrameBuffer::ConstIterator j = frameBuffer.find (i.name());
+
+ if (j == frameBuffer.end())
+ continue;
+
+ if (i.channel().type != j.slice().type)
+ THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" channel "
+ "of output file \"" << fileName() << "\" is "
+ "not compatible with the frame buffer's "
+ "pixel type.");
+
+ if (j.slice().xSampling != 1 || j.slice().ySampling != 1)
+ THROW (Iex::ArgExc, "All channels in a tiled file must have"
+ "sampling (1,1).");
+ }
+
+ //
+ // Initialize slice table for writePixels().
+ //
+
+ vector<TOutSliceInfo> slices;
+
+ for (ChannelList::ConstIterator i = channels.begin();
+ i != channels.end();
+ ++i)
+ {
+ FrameBuffer::ConstIterator j = frameBuffer.find (i.name());
+
+ if (j == frameBuffer.end())
+ {
+ //
+ // Channel i is not present in the frame buffer.
+ // In the file, channel i will contain only zeroes.
+ //
+
+ slices.push_back (TOutSliceInfo (i.channel().type,
+ 0, // base
+ 0, // xStride,
+ 0, // yStride,
+ true)); // zero
+ }
+ else
+ {
+ //
+ // Channel i is present in the frame buffer.
+ //
+
+ slices.push_back (TOutSliceInfo (j.slice().type,
+ j.slice().base,
+ j.slice().xStride,
+ j.slice().yStride,
+ false, // zero
+ (j.slice().xTileCoords)? 1: 0,
+ (j.slice().yTileCoords)? 1: 0));
+ }
+ }
+
+ //
+ // Store the new frame buffer.
+ //
+
+ _data->frameBuffer = frameBuffer;
+ _data->slices = slices;
+}
+
+
+const FrameBuffer &
+TiledOutputFile::frameBuffer () const
+{
+ Lock lock (*_data);
+ return _data->frameBuffer;
+}
+
+
+void
+TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2,
+ int lx, int ly)
+{
+ try
+ {
+ Lock lock (*_data);
+
+ if (_data->slices.size() == 0)
+ throw Iex::ArgExc ("No frame buffer specified "
+ "as pixel data source.");
+
+ if (!isValidTile (dx1, dy1, lx, ly) || !isValidTile (dx2, dy2, lx, ly))
+ throw Iex::ArgExc ("Tile coordinates are invalid.");
+
+ //
+ // Determine the first and last tile coordinates in both dimensions
+ // based on the file's lineOrder
+ //
+
+ if (dx1 > dx2)
+ swap (dx1, dx2);
+
+ if (dy1 > dy2)
+ swap (dy1, dy2);
+
+ int dyStart = dy1;
+ int dyStop = dy2 + 1;
+ int dY = 1;
+
+ if (_data->lineOrder == DECREASING_Y)
+ {
+ dyStart = dy2;
+ dyStop = dy1 - 1;
+ dY = -1;
+ }
+
+ int numTiles = (dx2 - dx1 + 1) * (dy2 - dy1 + 1);
+ int numTasks = min ((int)_data->tileBuffers.size(), numTiles);
+
+ //
+ // Create a task group for all tile buffer tasks. When the
+ // task group goes out of scope, the destructor waits until
+ // all tasks are complete.
+ //
+
+ {
+ TaskGroup taskGroup;
+
+ //
+ // Add in the initial compression tasks to the thread pool
+ //
+
+ int nextCompBuffer = 0;
+ int dxComp = dx1;
+ int dyComp = dyStart;
+
+ while (nextCompBuffer < numTasks)
+ {
+ ThreadPool::addGlobalTask (new TileBufferTask (&taskGroup,
+ _data,
+ nextCompBuffer++,
+ dxComp, dyComp,
+ lx, ly));
+ dxComp++;
+
+ if (dxComp > dx2)
+ {
+ dxComp = dx1;
+ dyComp += dY;
+ }
+ }
+
+ //
+ // Write the compressed buffers and add in more compression
+ // tasks until done
+ //
+
+ int nextWriteBuffer = 0;
+ int dxWrite = dx1;
+ int dyWrite = dyStart;
+
+ while (nextWriteBuffer < numTiles)
+ {
+ //
+ // Wait until the nextWriteBuffer is ready to be written
+ //
+
+ TileBuffer* writeBuffer =
+ _data->getTileBuffer (nextWriteBuffer);
+
+ writeBuffer->wait();
+
+ //
+ // Write the tilebuffer
+ //
+
+ bufferedTileWrite (_data, dxWrite, dyWrite, lx, ly,
+ writeBuffer->dataPtr,
+ writeBuffer->dataSize);
+
+ //
+ // Release the lock on nextWriteBuffer
+ //
+
+ writeBuffer->post();
+
+ //
+ // If there are no more tileBuffers to compress, then
+ // only continue to write out remaining tileBuffers,
+ // otherwise keep adding compression tasks.
+ //
+
+ if (nextCompBuffer < numTiles)
+ {
+ //
+ // add nextCompBuffer as a compression Task
+ //
+
+ ThreadPool::addGlobalTask
+ (new TileBufferTask (&taskGroup,
+ _data,
+ nextCompBuffer,
+ dxComp, dyComp,
+ lx, ly));
+ }
+
+ nextWriteBuffer++;
+ dxWrite++;
+
+ if (dxWrite > dx2)
+ {
+ dxWrite = dx1;
+ dyWrite += dY;
+ }
+
+ nextCompBuffer++;
+ dxComp++;
+
+ if (dxComp > dx2)
+ {
+ dxComp = dx1;
+ dyComp += dY;
+ }
+ }
+
+ //
+ // finish all tasks
+ //
+ }
+
+ //
+ // Exeption handling:
+ //
+ // TileBufferTask::execute() may have encountered exceptions, but
+ // those exceptions occurred in another thread, not in the thread
+ // that is executing this call to TiledOutputFile::writeTiles().
+ // TileBufferTask::execute() has caught all exceptions and stored
+ // the exceptions' what() strings in the tile buffers.
+ // Now we check if any tile buffer contains a stored exception; if
+ // this is the case then we re-throw the exception in this thread.
+ // (It is possible that multiple tile buffers contain stored
+ // exceptions. We re-throw the first exception we find and
+ // ignore all others.)
+ //
+
+ const string *exception = 0;
+
+ for (int i = 0; i < _data->tileBuffers.size(); ++i)
+ {
+ TileBuffer *tileBuffer = _data->tileBuffers[i];
+
+ if (tileBuffer->hasException && !exception)
+ exception = &tileBuffer->exception;
+
+ tileBuffer->hasException = false;
+ }
+
+ if (exception)
+ throw Iex::IoExc (*exception);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Failed to write pixel data to image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+TiledOutputFile::writeTiles (int dx1, int dxMax, int dyMin, int dyMax, int l)
+{
+ writeTiles (dx1, dxMax, dyMin, dyMax, l, l);
+}
+
+
+void
+TiledOutputFile::writeTile (int dx, int dy, int lx, int ly)
+{
+ writeTiles (dx, dx, dy, dy, lx, ly);
+}
+
+
+void
+TiledOutputFile::writeTile (int dx, int dy, int l)
+{
+ writeTile(dx, dy, l, l);
+}
+
+
+void
+TiledOutputFile::copyPixels (TiledInputFile &in)
+{
+ Lock lock (*_data);
+
+ //
+ // Check if this file's and and the InputFile's
+ // headers are compatible.
+ //
+
+ const Header &hdr = _data->header;
+ const Header &inHdr = in.header();
+
+ if (!hdr.hasTileDescription() || !inHdr.hasTileDescription())
+ THROW (Iex::ArgExc, "Cannot perform a quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\". The "
+ "output file is tiled, but the input file is not. "
+ "Try using OutputFile::copyPixels() instead.");
+
+ if (!(hdr.tileDescription() == inHdr.tileDescription()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files have different tile descriptions.");
+
+ if (!(hdr.dataWindow() == inHdr.dataWindow()))
+ THROW (Iex::ArgExc, "Cannot copy pixels from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\". The "
+ "files have different data windows.");
+
+ if (!(hdr.lineOrder() == inHdr.lineOrder()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files have different line orders.");
+
+ if (!(hdr.compression() == inHdr.compression()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" failed. "
+ "The files use different compression methods.");
+
+ if (!(hdr.channels() == inHdr.channels()))
+ THROW (Iex::ArgExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << fileName() << "\" "
+ "failed. The files have different channel "
+ "lists.");
+
+ //
+ // Verify that no pixel data have been written to this file yet.
+ //
+
+ if (!_data->tileOffsets.isEmpty())
+ THROW (Iex::LogicExc, "Quick pixel copy from image "
+ "file \"" << in.fileName() << "\" to image "
+ "file \"" << _data->os->fileName() << "\" "
+ "failed. \"" << fileName() << "\" "
+ "already contains pixel data.");
+
+ //
+ // Calculate the total number of tiles in the file
+ //
+
+ int numAllTiles = 0;
+
+ switch (levelMode ())
+ {
+ case ONE_LEVEL:
+ case MIPMAP_LEVELS:
+
+ for (size_t i_l = 0; i_l < numLevels (); ++i_l)
+ numAllTiles += numXTiles (i_l) * numYTiles (i_l);
+
+ break;
+
+ case RIPMAP_LEVELS:
+
+ for (size_t i_ly = 0; i_ly < numYLevels (); ++i_ly)
+ for (size_t i_lx = 0; i_lx < numXLevels (); ++i_lx)
+ numAllTiles += numXTiles (i_lx) * numYTiles (i_ly);
+
+ break;
+
+ default:
+
+ throw Iex::ArgExc ("Unknown LevelMode format.");
+ }
+
+ for (int i = 0; i < numAllTiles; ++i)
+ {
+ const char *pixelData;
+ int pixelDataSize;
+
+ int dx = _data->nextTileToWrite.dx;
+ int dy = _data->nextTileToWrite.dy;
+ int lx = _data->nextTileToWrite.lx;
+ int ly = _data->nextTileToWrite.ly;
+
+ in.rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
+ writeTileData (_data, dx, dy, lx, ly, pixelData, pixelDataSize);
+ }
+}
+
+
+void
+TiledOutputFile::copyPixels (InputFile &in)
+{
+ copyPixels (*in.tFile());
+}
+
+
+unsigned int
+TiledOutputFile::tileXSize () const
+{
+ return _data->tileDesc.xSize;
+}
+
+
+unsigned int
+TiledOutputFile::tileYSize () const
+{
+ return _data->tileDesc.ySize;
+}
+
+
+LevelMode
+TiledOutputFile::levelMode () const
+{
+ return _data->tileDesc.mode;
+}
+
+
+LevelRoundingMode
+TiledOutputFile::levelRoundingMode () const
+{
+ return _data->tileDesc.roundingMode;
+}
+
+
+int
+TiledOutputFile::numLevels () const
+{
+ if (levelMode() == RIPMAP_LEVELS)
+ THROW (Iex::LogicExc, "Error calling numLevels() on image "
+ "file \"" << fileName() << "\" "
+ "(numLevels() is not defined for RIPMAPs).");
+ return _data->numXLevels;
+}
+
+
+int
+TiledOutputFile::numXLevels () const
+{
+ return _data->numXLevels;
+}
+
+
+int
+TiledOutputFile::numYLevels () const
+{
+ return _data->numYLevels;
+}
+
+
+bool
+TiledOutputFile::isValidLevel (int lx, int ly) const
+{
+ if (lx < 0 || ly < 0)
+ return false;
+
+ if (levelMode() == MIPMAP_LEVELS && lx != ly)
+ return false;
+
+ if (lx >= numXLevels() || ly >= numYLevels())
+ return false;
+
+ return true;
+}
+
+
+int
+TiledOutputFile::levelWidth (int lx) const
+{
+ try
+ {
+ int retVal = levelSize (_data->minX, _data->maxX, lx,
+ _data->tileDesc.roundingMode);
+
+ return retVal;
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling levelWidth() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+int
+TiledOutputFile::levelHeight (int ly) const
+{
+ try
+ {
+ return levelSize (_data->minY, _data->maxY, ly,
+ _data->tileDesc.roundingMode);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling levelHeight() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+int
+TiledOutputFile::numXTiles (int lx) const
+{
+ if (lx < 0 || lx >= _data->numXLevels)
+ THROW (Iex::LogicExc, "Error calling numXTiles() on image "
+ "file \"" << _data->os->fileName() << "\" "
+ "(Argument is not in valid range).");
+
+ return _data->numXTiles[lx];
+}
+
+
+int
+TiledOutputFile::numYTiles (int ly) const
+{
+ if (ly < 0 || ly >= _data->numYLevels)
+ THROW (Iex::LogicExc, "Error calling numXTiles() on image "
+ "file \"" << _data->os->fileName() << "\" "
+ "(Argument is not in valid range).");
+
+ return _data->numYTiles[ly];
+}
+
+
+Box2i
+TiledOutputFile::dataWindowForLevel (int l) const
+{
+ return dataWindowForLevel (l, l);
+}
+
+
+Box2i
+TiledOutputFile::dataWindowForLevel (int lx, int ly) const
+{
+ try
+ {
+ return Imf::dataWindowForLevel (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ lx, ly);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling dataWindowForLevel() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+Box2i
+TiledOutputFile::dataWindowForTile (int dx, int dy, int l) const
+{
+ return dataWindowForTile (dx, dy, l, l);
+}
+
+
+Box2i
+TiledOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
+{
+ try
+ {
+ if (!isValidTile (dx, dy, lx, ly))
+ throw Iex::ArgExc ("Arguments not in valid range.");
+
+ return Imf::dataWindowForTile (_data->tileDesc,
+ _data->minX, _data->maxX,
+ _data->minY, _data->maxY,
+ dx, dy,
+ lx, ly);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Error calling dataWindowForTile() on image "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+bool
+TiledOutputFile::isValidTile (int dx, int dy, int lx, int ly) const
+{
+ return ((lx < _data->numXLevels && lx >= 0) &&
+ (ly < _data->numYLevels && ly >= 0) &&
+ (dx < _data->numXTiles[lx] && dx >= 0) &&
+ (dy < _data->numYTiles[ly] && dy >= 0));
+}
+
+
+void
+TiledOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
+{
+ Lock lock (*_data);
+
+ if (_data->previewPosition <= 0)
+ THROW (Iex::LogicExc, "Cannot update preview image pixels. "
+ "File \"" << fileName() << "\" does not "
+ "contain a preview image.");
+
+ //
+ // Store the new pixels in the header's preview image attribute.
+ //
+
+ PreviewImageAttribute &pia =
+ _data->header.typedAttribute <PreviewImageAttribute> ("preview");
+
+ PreviewImage &pi = pia.value();
+ PreviewRgba *pixels = pi.pixels();
+ int numPixels = pi.width() * pi.height();
+
+ for (int i = 0; i < numPixels; ++i)
+ pixels[i] = newPixels[i];
+
+ //
+ // Save the current file position, jump to the position in
+ // the file where the preview image starts, store the new
+ // preview image, and jump back to the saved file position.
+ //
+
+ Int64 savedPosition = _data->os->tellp();
+
+ try
+ {
+ _data->os->seekp (_data->previewPosition);
+ pia.writeValueTo (*_data->os, _data->version);
+ _data->os->seekp (savedPosition);
+ }
+ catch (Iex::BaseExc &e)
+ {
+ REPLACE_EXC (e, "Cannot update preview image pixels for "
+ "file \"" << fileName() << "\". " << e);
+ throw;
+ }
+}
+
+
+void
+TiledOutputFile::breakTile
+ (int dx, int dy,
+ int lx, int ly,
+ int offset,
+ int length,
+ char c)
+{
+ Lock lock (*_data);
+
+ Int64 position = _data->tileOffsets (dx, dy, lx, ly);
+
+ if (!position)
+ THROW (Iex::ArgExc,
+ "Cannot overwrite tile "
+ "(" << dx << ", " << dy << ", " << lx << "," << ly << "). "
+ "The tile has not yet been stored in "
+ "file \"" << fileName() << "\".");
+
+ _data->currentPosition = 0;
+ _data->os->seekp (position + offset);
+
+ for (int i = 0; i < length; ++i)
+ _data->os->write (&c, 1);
+}
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTiledOutputFile.h b/Source/OpenEXR/IlmImf/ImfTiledOutputFile.h
new file mode 100644
index 0000000..3b4f3ff
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledOutputFile.h
@@ -0,0 +1,475 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILED_OUTPUT_FILE_H
+#define INCLUDED_IMF_TILED_OUTPUT_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// class TiledOutputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include "ImathBox.h"
+#include <ImfTileDescription.h>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+class TiledInputFile;
+class InputFile;
+struct PreviewRgba;
+
+
+class TiledOutputFile
+{
+ public:
+
+ //-------------------------------------------------------------------
+ // A constructor that opens the file with the specified name, and
+ // writes the file header. The file header is also copied into the
+ // TiledOutputFile object, and can later be accessed via the header()
+ // method.
+ //
+ // Destroying TiledOutputFile constructed with this constructor
+ // automatically closes the corresponding files.
+ //
+ // The header must contain a TileDescriptionAttribute called "tiles".
+ //
+ // The x and y subsampling factors for all image channels must be 1;
+ // subsampling is not supported.
+ //
+ // Tiles can be written to the file in arbitrary order. The line
+ // order attribute can be used to cause the tiles to be sorted in
+ // the file. When the file is read later, reading the tiles in the
+ // same order as they are in the file tends to be significantly
+ // faster than reading the tiles in random order (see writeTile,
+ // below).
+ //-------------------------------------------------------------------
+
+ TiledOutputFile (const char fileName[],
+ const Header &header,
+ int numThreads = globalThreadCount ());
+
+
+ // ----------------------------------------------------------------
+ // A constructor that attaches the new TiledOutputFile object to
+ // a file that has already been opened. Destroying TiledOutputFile
+ // objects constructed with this constructor does not automatically
+ // close the corresponding files.
+ // ----------------------------------------------------------------
+
+ TiledOutputFile (OStream &os,
+ const Header &header,
+ int numThreads = globalThreadCount ());
+
+
+ //-----------------------------------------------------
+ // Destructor
+ //
+ // Destroying a TiledOutputFile object before all tiles
+ // have been written results in an incomplete file.
+ //-----------------------------------------------------
+
+ virtual ~TiledOutputFile ();
+
+
+ //------------------------
+ // Access to the file name
+ //------------------------
+
+ const char * fileName () const;
+
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+
+
+ //-------------------------------------------------------
+ // Set the current frame buffer -- copies the FrameBuffer
+ // object into the TiledOutputFile object.
+ //
+ // The current frame buffer is the source of the pixel
+ // data written to the file. The current frame buffer
+ // must be set at least once before writeTile() is
+ // called. The current frame buffer can be changed
+ // after each call to writeTile().
+ //-------------------------------------------------------
+
+ void setFrameBuffer (const FrameBuffer &frameBuffer);
+
+
+ //-----------------------------------
+ // Access to the current frame buffer
+ //-----------------------------------
+
+ const FrameBuffer & frameBuffer () const;
+
+
+ //-------------------
+ // Utility functions:
+ //-------------------
+
+ //---------------------------------------------------------
+ // Multiresolution mode and tile size:
+ // The following functions return the xSize, ySize and mode
+ // fields of the file header's TileDescriptionAttribute.
+ //---------------------------------------------------------
+
+ unsigned int tileXSize () const;
+ unsigned int tileYSize () const;
+ LevelMode levelMode () const;
+ LevelRoundingMode levelRoundingMode () const;
+
+
+ //--------------------------------------------------------------------
+ // Number of levels:
+ //
+ // numXLevels() returns the file's number of levels in x direction.
+ //
+ // if levelMode() == ONE_LEVEL:
+ // return value is: 1
+ //
+ // if levelMode() == MIPMAP_LEVELS:
+ // return value is: rfunc (log (max (w, h)) / log (2)) + 1
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // return value is: rfunc (log (w) / log (2)) + 1
+ //
+ // where
+ // w is the width of the image's data window, max.x - min.x + 1,
+ // y is the height of the image's data window, max.y - min.y + 1,
+ // and rfunc(x) is either floor(x), or ceil(x), depending on
+ // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP.
+ //
+ // numYLevels() returns the file's number of levels in y direction.
+ //
+ // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
+ // return value is the same as for numXLevels()
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // return value is: rfunc (log (h) / log (2)) + 1
+ //
+ //
+ // numLevels() is a convenience function for use with MIPMAP_LEVELS
+ // files.
+ //
+ // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS:
+ // return value is the same as for numXLevels()
+ //
+ // if levelMode() == RIPMAP_LEVELS:
+ // an Iex::LogicExc exception is thrown
+ //
+ // isValidLevel(lx, ly) returns true if the file contains
+ // a level with level number (lx, ly), false if not.
+ //
+ //--------------------------------------------------------------------
+
+ int numLevels () const;
+ int numXLevels () const;
+ int numYLevels () const;
+ bool isValidLevel (int lx, int ly) const;
+
+
+ //---------------------------------------------------------
+ // Dimensions of a level:
+ //
+ // levelWidth(lx) returns the width of a level with level
+ // number (lx, *), where * is any number.
+ //
+ // return value is:
+ // max (1, rfunc (w / pow (2, lx)))
+ //
+ //
+ // levelHeight(ly) returns the height of a level with level
+ // number (*, ly), where * is any number.
+ //
+ // return value is:
+ // max (1, rfunc (h / pow (2, ly)))
+ //
+ //---------------------------------------------------------
+
+ int levelWidth (int lx) const;
+ int levelHeight (int ly) const;
+
+
+ //----------------------------------------------------------
+ // Number of tiles:
+ //
+ // numXTiles(lx) returns the number of tiles in x direction
+ // that cover a level with level number (lx, *), where * is
+ // any number.
+ //
+ // return value is:
+ // (levelWidth(lx) + tileXSize() - 1) / tileXSize()
+ //
+ //
+ // numYTiles(ly) returns the number of tiles in y direction
+ // that cover a level with level number (*, ly), where * is
+ // any number.
+ //
+ // return value is:
+ // (levelHeight(ly) + tileXSize() - 1) / tileXSize()
+ //
+ //----------------------------------------------------------
+
+ int numXTiles (int lx = 0) const;
+ int numYTiles (int ly = 0) const;
+
+
+ //---------------------------------------------------------
+ // Level pixel ranges:
+ //
+ // dataWindowForLevel(lx, ly) returns a 2-dimensional
+ // region of valid pixel coordinates for a level with
+ // level number (lx, ly)
+ //
+ // return value is a Box2i with min value:
+ // (dataWindow.min.x, dataWindow.min.y)
+ //
+ // and max value:
+ // (dataWindow.min.x + levelWidth(lx) - 1,
+ // dataWindow.min.y + levelHeight(ly) - 1)
+ //
+ // dataWindowForLevel(level) is a convenience function used
+ // for ONE_LEVEL and MIPMAP_LEVELS files. It returns
+ // dataWindowForLevel(level, level).
+ //
+ //---------------------------------------------------------
+
+ Imath::Box2i dataWindowForLevel (int l = 0) const;
+ Imath::Box2i dataWindowForLevel (int lx, int ly) const;
+
+
+ //-------------------------------------------------------------------
+ // Tile pixel ranges:
+ //
+ // dataWindowForTile(dx, dy, lx, ly) returns a 2-dimensional
+ // region of valid pixel coordinates for a tile with tile coordinates
+ // (dx,dy) and level number (lx, ly).
+ //
+ // return value is a Box2i with min value:
+ // (dataWindow.min.x + dx * tileXSize(),
+ // dataWindow.min.y + dy * tileYSize())
+ //
+ // and max value:
+ // (dataWindow.min.x + (dx + 1) * tileXSize() - 1,
+ // dataWindow.min.y + (dy + 1) * tileYSize() - 1)
+ //
+ // dataWindowForTile(dx, dy, level) is a convenience function
+ // used for ONE_LEVEL and MIPMAP_LEVELS files. It returns
+ // dataWindowForTile(dx, dy, level, level).
+ //
+ //-------------------------------------------------------------------
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int l = 0) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int lx, int ly) const;
+
+ //------------------------------------------------------------------
+ // Write pixel data:
+ //
+ // writeTile(dx, dy, lx, ly) writes the tile with tile
+ // coordinates (dx, dy), and level number (lx, ly) to
+ // the file.
+ //
+ // dx must lie in the interval [0, numXTiles(lx) - 1]
+ // dy must lie in the interval [0, numYTiles(ly) - 1]
+ //
+ // lx must lie in the interval [0, numXLevels() - 1]
+ // ly must lie in the inverval [0, numYLevels() - 1]
+ //
+ // writeTile(dx, dy, level) is a convenience function
+ // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls
+ // writeTile(dx, dy, level, level).
+ //
+ // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow
+ // writing multiple tiles at once. If multi-threading is used
+ // multiple tiles are written concurrently. The tile coordinates,
+ // dx1, dx2 and dy1, dy2, specify inclusive ranges of tile
+ // coordinates. It is valid for dx1 < dx2 or dy1 < dy2; the
+ // tiles are always written in the order specified by the line
+ // order attribute. Hence, it is not possible to specify an
+ // "invalid" or empty tile range.
+ //
+ // Pixels that are outside the pixel coordinate range for the tile's
+ // level, are never accessed by writeTile().
+ //
+ // Each tile in the file must be written exactly once.
+ //
+ // The file's line order attribute determines the order of the tiles
+ // in the file:
+ //
+ // INCREASING_Y In the file, the tiles for each level are stored
+ // in a contiguous block. The levels are ordered
+ // like this:
+ //
+ // (0, 0) (1, 0) ... (nx-1, 0)
+ // (0, 1) (1, 1) ... (nx-1, 1)
+ // ...
+ // (0,ny-1) (1,ny-1) ... (nx-1,ny-1)
+ //
+ // where nx = numXLevels(), and ny = numYLevels().
+ // In an individual level, (lx, ly), the tiles
+ // are stored in the following order:
+ //
+ // (0, 0) (1, 0) ... (tx-1, 0)
+ // (0, 1) (1, 1) ... (tx-1, 1)
+ // ...
+ // (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
+ //
+ // where tx = numXTiles(lx),
+ // and ty = numYTiles(ly).
+ //
+ // DECREASING_Y As for INCREASING_Y, the tiles for each level
+ // are stored in a contiguous block. The levels
+ // are ordered the same way as for INCREASING_Y,
+ // but within an individual level, the tiles
+ // are stored in this order:
+ //
+ // (0,ty-1) (1,ty-1) ... (tx-1,ty-1)
+ // ...
+ // (0, 1) (1, 1) ... (tx-1, 1)
+ // (0, 0) (1, 0) ... (tx-1, 0)
+ //
+ //
+ // RANDOM_Y The order of the calls to writeTile() determines
+ // the order of the tiles in the file.
+ //
+ //------------------------------------------------------------------
+
+ void writeTile (int dx, int dy, int l = 0);
+ void writeTile (int dx, int dy, int lx, int ly);
+
+ void writeTiles (int dx1, int dx2, int dy1, int dy2,
+ int lx, int ly);
+
+ void writeTiles (int dx1, int dx2, int dy1, int dy2,
+ int l = 0);
+
+
+ //------------------------------------------------------------------
+ // Shortcut to copy all pixels from a TiledInputFile into this file,
+ // without uncompressing and then recompressing the pixel data.
+ // This file's header must be compatible with the TiledInputFile's
+ // header: The two header's "dataWindow", "compression",
+ // "lineOrder", "channels", and "tiles" attributes must be the same.
+ //------------------------------------------------------------------
+
+ void copyPixels (TiledInputFile &in);
+
+
+ //------------------------------------------------------------------
+ // Shortcut to copy all pixels from an InputFile into this file,
+ // without uncompressing and then recompressing the pixel data.
+ // This file's header must be compatible with the InputFile's
+ // header: The two header's "dataWindow", "compression",
+ // "lineOrder", "channels", and "tiles" attributes must be the same.
+ //
+ // To use this function, the InputFile must be tiled.
+ //------------------------------------------------------------------
+
+ void copyPixels (InputFile &in);
+
+
+ //--------------------------------------------------------------
+ // Updating the preview image:
+ //
+ // updatePreviewImage() supplies a new set of pixels for the
+ // preview image attribute in the file's header. If the header
+ // does not contain a preview image, updatePreviewImage() throws
+ // an Iex::LogicExc.
+ //
+ // Note: updatePreviewImage() is necessary because images are
+ // often stored in a file incrementally, a few tiles at a time,
+ // while the image is being generated. Since the preview image
+ // is an attribute in the file's header, it gets stored in the
+ // file as soon as the file is opened, but we may not know what
+ // the preview image should look like until we have written the
+ // last tile of the main image.
+ //
+ //--------------------------------------------------------------
+
+ void updatePreviewImage (const PreviewRgba newPixels[]);
+
+
+ //-------------------------------------------------------------
+ // Break a tile -- for testing and debugging only:
+ //
+ // breakTile(dx,dy,lx,ly,p,n,c) introduces an error into the
+ // output file by writing n copies of character c, starting
+ // p bytes from the beginning of the tile with tile coordinates
+ // (dx, dy) and level number (lx, ly).
+ //
+ // Warning: Calling this function usually results in a broken
+ // image file. The file or parts of it may not be readable,
+ // or the file may contain bad data.
+ //
+ //-------------------------------------------------------------
+
+ void breakTile (int dx, int dy,
+ int lx, int ly,
+ int offset,
+ int length,
+ char c);
+ struct Data;
+
+ private:
+
+ TiledOutputFile (const TiledOutputFile &); // not implemented
+ TiledOutputFile & operator = (const TiledOutputFile &); // not implemented
+
+ void initialize (const Header &header);
+
+ bool isValidTile (int dx, int dy,
+ int lx, int ly) const;
+
+ size_t bytesPerLineForTile (int dx, int dy,
+ int lx, int ly) const;
+
+ Data * _data;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.cpp b/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.cpp
new file mode 100644
index 0000000..9531c04
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.cpp
@@ -0,0 +1,1088 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class TiledRgbaOutputFile
+// class TiledRgbaInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTiledRgbaFile.h>
+#include <ImfRgbaFile.h>
+#include <ImfTiledOutputFile.h>
+#include <ImfTiledInputFile.h>
+#include <ImfChannelList.h>
+#include <ImfTileDescriptionAttribute.h>
+#include <ImfStandardAttributes.h>
+#include <ImfRgbaYca.h>
+#include <ImfArray.h>
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+
+
+namespace Imf {
+
+using namespace Imath;
+using namespace RgbaYca;
+using namespace IlmThread;
+
+namespace {
+
+void
+insertChannels (Header &header,
+ RgbaChannels rgbaChannels,
+ const char fileName[])
+{
+ ChannelList ch;
+
+ if (rgbaChannels & (WRITE_Y | WRITE_C))
+ {
+ if (rgbaChannels & WRITE_Y)
+ {
+ ch.insert ("Y", Channel (HALF, 1, 1));
+ }
+
+ if (rgbaChannels & WRITE_C)
+ {
+ THROW (Iex::ArgExc, "Cannot open file \"" << fileName << "\" "
+ "for writing. Tiled image files do not "
+ "support subsampled chroma channels.");
+ }
+ }
+ else
+ {
+ if (rgbaChannels & WRITE_R)
+ ch.insert ("R", Channel (HALF, 1, 1));
+
+ if (rgbaChannels & WRITE_G)
+ ch.insert ("G", Channel (HALF, 1, 1));
+
+ if (rgbaChannels & WRITE_B)
+ ch.insert ("B", Channel (HALF, 1, 1));
+ }
+
+ if (rgbaChannels & WRITE_A)
+ ch.insert ("A", Channel (HALF, 1, 1));
+
+ header.channels() = ch;
+}
+
+
+RgbaChannels
+rgbaChannels (const ChannelList &ch)
+{
+ int i = 0;
+
+ if (ch.findChannel ("R"))
+ i |= WRITE_R;
+
+ if (ch.findChannel ("G"))
+ i |= WRITE_G;
+
+ if (ch.findChannel ("B"))
+ i |= WRITE_B;
+
+ if (ch.findChannel ("A"))
+ i |= WRITE_A;
+
+ if (ch.findChannel ("Y"))
+ i |= WRITE_Y;
+
+ return RgbaChannels (i);
+}
+
+
+V3f
+ywFromHeader (const Header &header)
+{
+ Chromaticities cr;
+
+ if (hasChromaticities (header))
+ cr = chromaticities (header);
+
+ return computeYw (cr);
+}
+
+} // namespace
+
+
+class TiledRgbaOutputFile::ToYa: public Mutex
+{
+ public:
+
+ ToYa (TiledOutputFile &outputFile, RgbaChannels rgbaChannels);
+
+ void setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ void writeTile (int dx, int dy, int lx, int ly);
+
+ private:
+
+ TiledOutputFile & _outputFile;
+ bool _writeA;
+ unsigned int _tileXSize;
+ unsigned int _tileYSize;
+ V3f _yw;
+ Array2D <Rgba> _buf;
+ const Rgba * _fbBase;
+ size_t _fbXStride;
+ size_t _fbYStride;
+};
+
+
+TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile,
+ RgbaChannels rgbaChannels)
+:
+ _outputFile (outputFile)
+{
+ _writeA = (rgbaChannels & WRITE_A)? true: false;
+
+ const TileDescription &td = outputFile.header().tileDescription();
+
+ _tileXSize = td.xSize;
+ _tileYSize = td.ySize;
+ _yw = ywFromHeader (_outputFile.header());
+ _buf.resizeErase (_tileYSize, _tileXSize);
+ _fbBase = 0;
+ _fbXStride = 0;
+ _fbYStride = 0;
+}
+
+
+void
+TiledRgbaOutputFile::ToYa::setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ _fbBase = base;
+ _fbXStride = xStride;
+ _fbYStride = yStride;
+}
+
+
+void
+TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly)
+{
+ if (_fbBase == 0)
+ {
+ THROW (Iex::ArgExc, "No frame buffer was specified as the "
+ "pixel data source for image file "
+ "\"" << _outputFile.fileName() << "\".");
+ }
+
+ //
+ // Copy the tile's RGBA pixels into _buf and convert
+ // them to luminance/alpha format
+ //
+
+ Box2i dw = _outputFile.dataWindowForTile (dx, dy, lx, ly);
+ int width = dw.max.x - dw.min.x + 1;
+
+ for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
+ {
+ for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
+ _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride];
+
+ RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]);
+ }
+
+ //
+ // Store the contents of _buf in the output file
+ //
+
+ FrameBuffer fb;
+
+ fb.insert ("Y", Slice (HALF, // type
+ (char *) &_buf[-dw.min.y][-dw.min.x].g, // base
+ sizeof (Rgba), // xStride
+ sizeof (Rgba) * _tileXSize)); // yStride
+
+ fb.insert ("A", Slice (HALF, // type
+ (char *) &_buf[-dw.min.y][-dw.min.x].a, // base
+ sizeof (Rgba), // xStride
+ sizeof (Rgba) * _tileXSize)); // yStride
+
+ _outputFile.setFrameBuffer (fb);
+ _outputFile.writeTile (dx, dy, lx, ly);
+}
+
+
+TiledRgbaOutputFile::TiledRgbaOutputFile
+ (const char name[],
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode,
+ int numThreads)
+:
+ _outputFile (0),
+ _toYa (0)
+{
+ Header hd (header);
+ insertChannels (hd, rgbaChannels, name);
+ hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
+ _outputFile = new TiledOutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & WRITE_Y)
+ _toYa = new ToYa (*_outputFile, rgbaChannels);
+}
+
+
+
+TiledRgbaOutputFile::TiledRgbaOutputFile
+ (OStream &os,
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode,
+ int numThreads)
+:
+ _outputFile (0),
+ _toYa (0)
+{
+ Header hd (header);
+ insertChannels (hd, rgbaChannels, os.fileName());
+ hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
+ _outputFile = new TiledOutputFile (os, hd, numThreads);
+
+ if (rgbaChannels & WRITE_Y)
+ _toYa = new ToYa (*_outputFile, rgbaChannels);
+}
+
+
+
+TiledRgbaOutputFile::TiledRgbaOutputFile
+ (const char name[],
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode,
+ const Imath::Box2i &displayWindow,
+ const Imath::Box2i &dataWindow,
+ RgbaChannels rgbaChannels,
+ float pixelAspectRatio,
+ const Imath::V2f screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression,
+ int numThreads)
+:
+ _outputFile (0),
+ _toYa (0)
+{
+ Header hd (displayWindow,
+ dataWindow.isEmpty()? displayWindow: dataWindow,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+
+ insertChannels (hd, rgbaChannels, name);
+ hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
+ _outputFile = new TiledOutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & WRITE_Y)
+ _toYa = new ToYa (*_outputFile, rgbaChannels);
+}
+
+
+TiledRgbaOutputFile::TiledRgbaOutputFile
+ (const char name[],
+ int width,
+ int height,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode,
+ RgbaChannels rgbaChannels,
+ float pixelAspectRatio,
+ const Imath::V2f screenWindowCenter,
+ float screenWindowWidth,
+ LineOrder lineOrder,
+ Compression compression,
+ int numThreads)
+:
+ _outputFile (0),
+ _toYa (0)
+{
+ Header hd (width,
+ height,
+ pixelAspectRatio,
+ screenWindowCenter,
+ screenWindowWidth,
+ lineOrder,
+ compression);
+
+ insertChannels (hd, rgbaChannels, name);
+ hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
+ _outputFile = new TiledOutputFile (name, hd, numThreads);
+
+ if (rgbaChannels & WRITE_Y)
+ _toYa = new ToYa (*_outputFile, rgbaChannels);
+}
+
+
+TiledRgbaOutputFile::~TiledRgbaOutputFile ()
+{
+ delete _outputFile;
+ delete _toYa;
+}
+
+
+void
+TiledRgbaOutputFile::setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ if (_toYa)
+ {
+ Lock lock (*_toYa);
+ _toYa->setFrameBuffer (base, xStride, yStride);
+ }
+ else
+ {
+ size_t xs = xStride * sizeof (Rgba);
+ size_t ys = yStride * sizeof (Rgba);
+
+ FrameBuffer fb;
+
+ fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));
+ fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));
+ fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));
+ fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));
+
+ _outputFile->setFrameBuffer (fb);
+ }
+}
+
+
+const Header &
+TiledRgbaOutputFile::header () const
+{
+ return _outputFile->header();
+}
+
+
+const FrameBuffer &
+TiledRgbaOutputFile::frameBuffer () const
+{
+ return _outputFile->frameBuffer();
+}
+
+
+const Imath::Box2i &
+TiledRgbaOutputFile::displayWindow () const
+{
+ return _outputFile->header().displayWindow();
+}
+
+
+const Imath::Box2i &
+TiledRgbaOutputFile::dataWindow () const
+{
+ return _outputFile->header().dataWindow();
+}
+
+
+float
+TiledRgbaOutputFile::pixelAspectRatio () const
+{
+ return _outputFile->header().pixelAspectRatio();
+}
+
+
+const Imath::V2f
+TiledRgbaOutputFile::screenWindowCenter () const
+{
+ return _outputFile->header().screenWindowCenter();
+}
+
+
+float
+TiledRgbaOutputFile::screenWindowWidth () const
+{
+ return _outputFile->header().screenWindowWidth();
+}
+
+
+LineOrder
+TiledRgbaOutputFile::lineOrder () const
+{
+ return _outputFile->header().lineOrder();
+}
+
+
+Compression
+TiledRgbaOutputFile::compression () const
+{
+ return _outputFile->header().compression();
+}
+
+
+RgbaChannels
+TiledRgbaOutputFile::channels () const
+{
+ return rgbaChannels (_outputFile->header().channels());
+}
+
+
+unsigned int
+TiledRgbaOutputFile::tileXSize () const
+{
+ return _outputFile->tileXSize();
+}
+
+
+unsigned int
+TiledRgbaOutputFile::tileYSize () const
+{
+ return _outputFile->tileYSize();
+}
+
+
+LevelMode
+TiledRgbaOutputFile::levelMode () const
+{
+ return _outputFile->levelMode();
+}
+
+
+LevelRoundingMode
+TiledRgbaOutputFile::levelRoundingMode () const
+{
+ return _outputFile->levelRoundingMode();
+}
+
+
+int
+TiledRgbaOutputFile::numLevels () const
+{
+ return _outputFile->numLevels();
+}
+
+
+int
+TiledRgbaOutputFile::numXLevels () const
+{
+ return _outputFile->numXLevels();
+}
+
+
+int
+TiledRgbaOutputFile::numYLevels () const
+{
+ return _outputFile->numYLevels();
+}
+
+
+bool
+TiledRgbaOutputFile::isValidLevel (int lx, int ly) const
+{
+ return _outputFile->isValidLevel (lx, ly);
+}
+
+
+int
+TiledRgbaOutputFile::levelWidth (int lx) const
+{
+ return _outputFile->levelWidth (lx);
+}
+
+
+int
+TiledRgbaOutputFile::levelHeight (int ly) const
+{
+ return _outputFile->levelHeight (ly);
+}
+
+
+int
+TiledRgbaOutputFile::numXTiles (int lx) const
+{
+ return _outputFile->numXTiles (lx);
+}
+
+
+int
+TiledRgbaOutputFile::numYTiles (int ly) const
+{
+ return _outputFile->numYTiles (ly);
+}
+
+
+Imath::Box2i
+TiledRgbaOutputFile::dataWindowForLevel (int l) const
+{
+ return _outputFile->dataWindowForLevel (l);
+}
+
+
+Imath::Box2i
+TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const
+{
+ return _outputFile->dataWindowForLevel (lx, ly);
+}
+
+
+Imath::Box2i
+TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const
+{
+ return _outputFile->dataWindowForTile (dx, dy, l);
+}
+
+
+Imath::Box2i
+TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
+{
+ return _outputFile->dataWindowForTile (dx, dy, lx, ly);
+}
+
+
+void
+TiledRgbaOutputFile::writeTile (int dx, int dy, int l)
+{
+ if (_toYa)
+ {
+ Lock lock (*_toYa);
+ _toYa->writeTile (dx, dy, l, l);
+ }
+ else
+ {
+ _outputFile->writeTile (dx, dy, l);
+ }
+}
+
+
+void
+TiledRgbaOutputFile::writeTile (int dx, int dy, int lx, int ly)
+{
+ if (_toYa)
+ {
+ Lock lock (*_toYa);
+ _toYa->writeTile (dx, dy, lx, ly);
+ }
+ else
+ {
+ _outputFile->writeTile (dx, dy, lx, ly);
+ }
+}
+
+
+void
+TiledRgbaOutputFile::writeTiles
+ (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly)
+{
+ if (_toYa)
+ {
+ Lock lock (*_toYa);
+
+ for (int dy = dyMin; dy <= dyMax; dy++)
+ for (int dx = dxMin; dx <= dxMax; dx++)
+ _toYa->writeTile (dx, dy, lx, ly);
+ }
+ else
+ {
+ _outputFile->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
+ }
+}
+
+void
+TiledRgbaOutputFile::writeTiles
+ (int dxMin, int dxMax, int dyMin, int dyMax, int l)
+{
+ writeTiles (dxMin, dxMax, dyMin, dyMax, l, l);
+}
+
+
+class TiledRgbaInputFile::FromYa: public Mutex
+{
+ public:
+
+ FromYa (TiledInputFile &inputFile);
+
+ void setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ void readTile (int dx, int dy, int lx, int ly);
+
+ private:
+
+ TiledInputFile & _inputFile;
+ unsigned int _tileXSize;
+ unsigned int _tileYSize;
+ V3f _yw;
+ Array2D <Rgba> _buf;
+ Rgba * _fbBase;
+ size_t _fbXStride;
+ size_t _fbYStride;
+};
+
+
+TiledRgbaInputFile::FromYa::FromYa (TiledInputFile &inputFile)
+:
+ _inputFile (inputFile)
+{
+ const TileDescription &td = inputFile.header().tileDescription();
+
+ _tileXSize = td.xSize;
+ _tileYSize = td.ySize;
+ _yw = ywFromHeader (_inputFile.header());
+ _buf.resizeErase (_tileYSize, _tileXSize);
+ _fbBase = 0;
+ _fbXStride = 0;
+ _fbYStride = 0;
+}
+
+
+void
+TiledRgbaInputFile::FromYa::setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride)
+{
+ _fbBase = base;
+ _fbXStride = xStride;
+ _fbYStride = yStride;
+}
+
+
+void
+TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly)
+{
+ if (_fbBase == 0)
+ {
+ THROW (Iex::ArgExc, "No frame buffer was specified as the "
+ "pixel data destination for image file "
+ "\"" << _inputFile.fileName() << "\".");
+ }
+
+ //
+ // Read the tile requiested by the caller into _buf.
+ //
+
+ Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly);
+ FrameBuffer fb;
+
+ fb.insert ("Y", Slice (HALF, // type
+ (char *) &_buf[-dw.min.y][-dw.min.x].g, // base
+ sizeof (Rgba), // xStride
+ sizeof (Rgba) * _tileXSize)); // yStride
+
+ fb.insert ("A", Slice (HALF, // type
+ (char *) &_buf[-dw.min.y][-dw.min.x].a, // base
+ sizeof (Rgba), // xStride
+ sizeof (Rgba) * _tileXSize, // yStride
+ 1, 1, // sampling
+ 1.0)); // fillValue
+
+ _inputFile.setFrameBuffer (fb);
+ _inputFile.readTile (dx, dy, lx, ly);
+
+ //
+ // Convert the luminance/alpha pixels to RGBA
+ // and copy them into the caller's frame buffer.
+ //
+
+ int width = dw.max.x - dw.min.x + 1;
+
+ for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
+ {
+ for (int x1 = 0; x1 < width; ++x1)
+ {
+ _buf[y1][x1].r = 0;
+ _buf[y1][x1].b = 0;
+ }
+
+ YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]);
+
+ for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
+ {
+ _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1];
+ }
+ }
+}
+
+
+TiledRgbaInputFile::TiledRgbaInputFile (const char name[], int numThreads):
+ _inputFile (new TiledInputFile (name, numThreads)),
+ _fromYa (0)
+{
+ if (channels() & WRITE_Y)
+ _fromYa = new FromYa (*_inputFile);
+}
+
+
+TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, int numThreads):
+ _inputFile (new TiledInputFile (is, numThreads)),
+ _fromYa (0)
+{
+ if (channels() & WRITE_Y)
+ _fromYa = new FromYa (*_inputFile);
+}
+
+
+TiledRgbaInputFile::~TiledRgbaInputFile ()
+{
+ delete _inputFile;
+ delete _fromYa;
+}
+
+
+void
+TiledRgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
+{
+ if (_fromYa)
+ {
+ Lock lock (*_fromYa);
+ _fromYa->setFrameBuffer (base, xStride, yStride);
+ }
+ else
+ {
+ size_t xs = xStride * sizeof (Rgba);
+ size_t ys = yStride * sizeof (Rgba);
+
+ FrameBuffer fb;
+
+ fb.insert ("R", Slice (HALF,
+ (char *) &base[0].r,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("G", Slice (HALF,
+ (char *) &base[0].g,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("B", Slice (HALF,
+ (char *) &base[0].b,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 0.0)); // fillValue
+
+ fb.insert ("A", Slice (HALF,
+ (char *) &base[0].a,
+ xs, ys,
+ 1, 1, // xSampling, ySampling
+ 1.0)); // fillValue
+
+ _inputFile->setFrameBuffer (fb);
+ }
+}
+
+
+const Header &
+TiledRgbaInputFile::header () const
+{
+ return _inputFile->header();
+}
+
+
+const char *
+TiledRgbaInputFile::fileName () const
+{
+ return _inputFile->fileName();
+}
+
+
+const FrameBuffer &
+TiledRgbaInputFile::frameBuffer () const
+{
+ return _inputFile->frameBuffer();
+}
+
+
+const Imath::Box2i &
+TiledRgbaInputFile::displayWindow () const
+{
+ return _inputFile->header().displayWindow();
+}
+
+
+const Imath::Box2i &
+TiledRgbaInputFile::dataWindow () const
+{
+ return _inputFile->header().dataWindow();
+}
+
+
+float
+TiledRgbaInputFile::pixelAspectRatio () const
+{
+ return _inputFile->header().pixelAspectRatio();
+}
+
+
+const Imath::V2f
+TiledRgbaInputFile::screenWindowCenter () const
+{
+ return _inputFile->header().screenWindowCenter();
+}
+
+
+float
+TiledRgbaInputFile::screenWindowWidth () const
+{
+ return _inputFile->header().screenWindowWidth();
+}
+
+
+LineOrder
+TiledRgbaInputFile::lineOrder () const
+{
+ return _inputFile->header().lineOrder();
+}
+
+
+Compression
+TiledRgbaInputFile::compression () const
+{
+ return _inputFile->header().compression();
+}
+
+
+RgbaChannels
+TiledRgbaInputFile::channels () const
+{
+ return rgbaChannels (_inputFile->header().channels());
+}
+
+
+int
+TiledRgbaInputFile::version () const
+{
+ return _inputFile->version();
+}
+
+
+bool
+TiledRgbaInputFile::isComplete () const
+{
+ return _inputFile->isComplete();
+}
+
+
+unsigned int
+TiledRgbaInputFile::tileXSize () const
+{
+ return _inputFile->tileXSize();
+}
+
+
+unsigned int
+TiledRgbaInputFile::tileYSize () const
+{
+ return _inputFile->tileYSize();
+}
+
+
+LevelMode
+TiledRgbaInputFile::levelMode () const
+{
+ return _inputFile->levelMode();
+}
+
+
+LevelRoundingMode
+TiledRgbaInputFile::levelRoundingMode () const
+{
+ return _inputFile->levelRoundingMode();
+}
+
+
+int
+TiledRgbaInputFile::numLevels () const
+{
+ return _inputFile->numLevels();
+}
+
+
+int
+TiledRgbaInputFile::numXLevels () const
+{
+ return _inputFile->numXLevels();
+}
+
+
+int
+TiledRgbaInputFile::numYLevels () const
+{
+ return _inputFile->numYLevels();
+}
+
+
+bool
+TiledRgbaInputFile::isValidLevel (int lx, int ly) const
+{
+ return _inputFile->isValidLevel (lx, ly);
+}
+
+
+int
+TiledRgbaInputFile::levelWidth (int lx) const
+{
+ return _inputFile->levelWidth (lx);
+}
+
+
+int
+TiledRgbaInputFile::levelHeight (int ly) const
+{
+ return _inputFile->levelHeight (ly);
+}
+
+
+int
+TiledRgbaInputFile::numXTiles (int lx) const
+{
+ return _inputFile->numXTiles(lx);
+}
+
+
+int
+TiledRgbaInputFile::numYTiles (int ly) const
+{
+ return _inputFile->numYTiles(ly);
+}
+
+
+Imath::Box2i
+TiledRgbaInputFile::dataWindowForLevel (int l) const
+{
+ return _inputFile->dataWindowForLevel (l);
+}
+
+
+Imath::Box2i
+TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const
+{
+ return _inputFile->dataWindowForLevel (lx, ly);
+}
+
+
+Imath::Box2i
+TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const
+{
+ return _inputFile->dataWindowForTile (dx, dy, l);
+}
+
+
+Imath::Box2i
+TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
+{
+ return _inputFile->dataWindowForTile (dx, dy, lx, ly);
+}
+
+
+void
+TiledRgbaInputFile::readTile (int dx, int dy, int l)
+{
+ if (_fromYa)
+ {
+ Lock lock (*_fromYa);
+ _fromYa->readTile (dx, dy, l, l);
+ }
+ else
+ {
+ _inputFile->readTile (dx, dy, l);
+ }
+}
+
+
+void
+TiledRgbaInputFile::readTile (int dx, int dy, int lx, int ly)
+{
+ if (_fromYa)
+ {
+ Lock lock (*_fromYa);
+ _fromYa->readTile (dx, dy, lx, ly);
+ }
+ else
+ {
+ _inputFile->readTile (dx, dy, lx, ly);
+ }
+}
+
+
+void
+TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
+ int lx, int ly)
+{
+ if (_fromYa)
+ {
+ Lock lock (*_fromYa);
+
+ for (int dy = dyMin; dy <= dyMax; dy++)
+ for (int dx = dxMin; dx <= dxMax; dx++)
+ _fromYa->readTile (dx, dy, lx, ly);
+ }
+ else
+ {
+ _inputFile->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
+ }
+}
+
+void
+TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
+ int l)
+{
+ readTiles (dxMin, dxMax, dyMin, dyMax, l, l);
+}
+
+
+void
+TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
+{
+ _outputFile->updatePreviewImage (newPixels);
+}
+
+
+void
+TiledRgbaOutputFile::breakTile (int dx, int dy, int lx, int ly,
+ int offset, int length, char c)
+{
+ _outputFile->breakTile (dx, dy, lx, ly, offset, length, c);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.h b/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.h
new file mode 100644
index 0000000..4d7dd75
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTiledRgbaFile.h
@@ -0,0 +1,453 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TILED_RGBA_FILE_H
+#define INCLUDED_IMF_TILED_RGBA_FILE_H
+
+//-----------------------------------------------------------------------------
+//
+// Simplified RGBA image I/O for tiled files
+//
+// class TiledRgbaOutputFile
+// class TiledRgbaInputFile
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfHeader.h>
+#include <ImfFrameBuffer.h>
+#include "ImathVec.h"
+#include "ImathBox.h"
+#include "half.h"
+#include <ImfTileDescription.h>
+#include <ImfRgba.h>
+#include <ImfThreading.h>
+
+namespace Imf {
+
+class TiledOutputFile;
+class TiledInputFile;
+struct PreviewRgba;
+
+
+//
+// Tiled RGBA output file.
+//
+
+class TiledRgbaOutputFile
+{
+ public:
+
+ //---------------------------------------------------
+ // Constructor -- rgbaChannels, tileXSize, tileYSize,
+ // levelMode, and levelRoundingMode overwrite the
+ // channel list and tile description attribute in the
+ // header that is passed as an argument to the
+ // constructor.
+ //---------------------------------------------------
+
+ TiledRgbaOutputFile (const char name[],
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode = ROUND_DOWN,
+ int numThreads = globalThreadCount ());
+
+
+ //---------------------------------------------------
+ // Constructor -- like the previous one, but the new
+ // TiledRgbaOutputFile is attached to a file that has
+ // already been opened by the caller. Destroying
+ // TiledRgbaOutputFileObjects constructed with this
+ // constructor does not automatically close the
+ // corresponding files.
+ //---------------------------------------------------
+
+ TiledRgbaOutputFile (OStream &os,
+ const Header &header,
+ RgbaChannels rgbaChannels,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode = ROUND_DOWN,
+ int numThreads = globalThreadCount ());
+
+
+ //------------------------------------------------------
+ // Constructor -- header data are explicitly specified
+ // as function call arguments (an empty dataWindow means
+ // "same as displayWindow")
+ //------------------------------------------------------
+
+ TiledRgbaOutputFile (const char name[],
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode,
+ const Imath::Box2i &displayWindow,
+ const Imath::Box2i &dataWindow = Imath::Box2i(),
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ float pixelAspectRatio = 1,
+ const Imath::V2f screenWindowCenter =
+ Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression compression = ZIP_COMPRESSION,
+ int numThreads = globalThreadCount ());
+
+
+ //-----------------------------------------------
+ // Constructor -- like the previous one, but both
+ // the display window and the data window are
+ // Box2i (V2i (0, 0), V2i (width - 1, height -1))
+ //-----------------------------------------------
+
+ TiledRgbaOutputFile (const char name[],
+ int width,
+ int height,
+ int tileXSize,
+ int tileYSize,
+ LevelMode mode,
+ LevelRoundingMode rmode = ROUND_DOWN,
+ RgbaChannels rgbaChannels = WRITE_RGBA,
+ float pixelAspectRatio = 1,
+ const Imath::V2f screenWindowCenter =
+ Imath::V2f (0, 0),
+ float screenWindowWidth = 1,
+ LineOrder lineOrder = INCREASING_Y,
+ Compression compression = ZIP_COMPRESSION,
+ int numThreads = globalThreadCount ());
+
+
+ virtual ~TiledRgbaOutputFile ();
+
+
+ //------------------------------------------------
+ // Define a frame buffer as the pixel data source:
+ // Pixel (x, y) is at address
+ //
+ // base + x * xStride + y * yStride
+ //
+ //------------------------------------------------
+
+ void setFrameBuffer (const Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+ const FrameBuffer & frameBuffer () const;
+ const Imath::Box2i & displayWindow () const;
+ const Imath::Box2i & dataWindow () const;
+ float pixelAspectRatio () const;
+ const Imath::V2f screenWindowCenter () const;
+ float screenWindowWidth () const;
+ LineOrder lineOrder () const;
+ Compression compression () const;
+ RgbaChannels channels () const;
+
+
+ //----------------------------------------------------
+ // Utility functions (same as in Imf::TiledOutputFile)
+ //----------------------------------------------------
+
+ unsigned int tileXSize () const;
+ unsigned int tileYSize () const;
+ LevelMode levelMode () const;
+ LevelRoundingMode levelRoundingMode () const;
+
+ int numLevels () const;
+ int numXLevels () const;
+ int numYLevels () const;
+ bool isValidLevel (int lx, int ly) const;
+
+ int levelWidth (int lx) const;
+ int levelHeight (int ly) const;
+
+ int numXTiles (int lx = 0) const;
+ int numYTiles (int ly = 0) const;
+
+ Imath::Box2i dataWindowForLevel (int l = 0) const;
+ Imath::Box2i dataWindowForLevel (int lx, int ly) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int l = 0) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int lx, int ly) const;
+
+ //------------------------------------------------------------------
+ // Write pixel data:
+ //
+ // writeTile(dx, dy, lx, ly) writes the tile with tile
+ // coordinates (dx, dy), and level number (lx, ly) to
+ // the file.
+ //
+ // dx must lie in the interval [0, numXTiles(lx)-1]
+ // dy must lie in the interval [0, numYTiles(ly)-1]
+ //
+ // lx must lie in the interval [0, numXLevels()-1]
+ // ly must lie in the inverval [0, numYLevels()-1]
+ //
+ // writeTile(dx, dy, level) is a convenience function
+ // used for ONE_LEVEL and MIPMAP_LEVEL files. It calls
+ // writeTile(dx, dy, level, level).
+ //
+ // The two writeTiles(dx1, dx2, dy1, dy2, ...) functions allow
+ // writing multiple tiles at once. If multi-threading is used
+ // multiple tiles are written concurrently.
+ //
+ // Pixels that are outside the pixel coordinate range for the tile's
+ // level, are never accessed by writeTile().
+ //
+ // Each tile in the file must be written exactly once.
+ //
+ //------------------------------------------------------------------
+
+ void writeTile (int dx, int dy, int l = 0);
+ void writeTile (int dx, int dy, int lx, int ly);
+
+ void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax,
+ int lx, int ly);
+
+ void writeTiles (int dxMin, int dxMax, int dyMin, int dyMax,
+ int l = 0);
+
+
+ // -------------------------------------------------------------------------
+ // Update the preview image (see Imf::TiledOutputFile::updatePreviewImage())
+ // -------------------------------------------------------------------------
+
+ void updatePreviewImage (const PreviewRgba[]);
+
+
+ //------------------------------------------------
+ // Break a tile -- for testing and debugging only
+ // (see Imf::TiledOutputFile::breakTile())
+ //
+ // Warning: Calling this function usually results
+ // in a broken image file. The file or parts of
+ // it may not be readable, or the file may contain
+ // bad data.
+ //
+ //------------------------------------------------
+
+ void breakTile (int dx, int dy,
+ int lx, int ly,
+ int offset,
+ int length,
+ char c);
+ private:
+
+ //
+ // Copy constructor and assignment are not implemented
+ //
+
+ TiledRgbaOutputFile (const TiledRgbaOutputFile &);
+ TiledRgbaOutputFile & operator = (const TiledRgbaOutputFile &);
+
+ class ToYa;
+
+ TiledOutputFile * _outputFile;
+ ToYa * _toYa;
+};
+
+
+
+//
+// Tiled RGBA input file
+//
+
+class TiledRgbaInputFile
+{
+ public:
+
+ //--------------------------------------------------------
+ // Constructor -- opens the file with the specified name.
+ // Destroying TiledRgbaInputFile objects constructed with
+ // this constructor automatically closes the corresponding
+ // files.
+ //--------------------------------------------------------
+
+ TiledRgbaInputFile (const char name[],
+ int numThreads = globalThreadCount ());
+
+
+ //-------------------------------------------------------
+ // Constructor -- attaches the new TiledRgbaInputFile
+ // object to a file that has already been opened by the
+ // caller.
+ // Destroying TiledRgbaInputFile objects constructed with
+ // this constructor does not automatically close the
+ // corresponding files.
+ //-------------------------------------------------------
+
+ TiledRgbaInputFile (IStream &is, int numThreads = globalThreadCount ());
+
+
+ //-----------
+ // Destructor
+ //-----------
+
+ virtual ~TiledRgbaInputFile ();
+
+
+ //-----------------------------------------------------
+ // Define a frame buffer as the pixel data destination:
+ // Pixel (x, y) is at address
+ //
+ // base + x * xStride + y * yStride
+ //
+ //-----------------------------------------------------
+
+ void setFrameBuffer (Rgba *base,
+ size_t xStride,
+ size_t yStride);
+
+ //--------------------------
+ // Access to the file header
+ //--------------------------
+
+ const Header & header () const;
+ const FrameBuffer & frameBuffer () const;
+ const Imath::Box2i & displayWindow () const;
+ const Imath::Box2i & dataWindow () const;
+ float pixelAspectRatio () const;
+ const Imath::V2f screenWindowCenter () const;
+ float screenWindowWidth () const;
+ LineOrder lineOrder () const;
+ Compression compression () const;
+ RgbaChannels channels () const;
+ const char * fileName () const;
+ bool isComplete () const;
+
+ //----------------------------------
+ // Access to the file format version
+ //----------------------------------
+
+ int version () const;
+
+
+ //---------------------------------------------------
+ // Utility functions (same as in Imf::TiledInputFile)
+ //---------------------------------------------------
+
+ unsigned int tileXSize () const;
+ unsigned int tileYSize () const;
+ LevelMode levelMode () const;
+ LevelRoundingMode levelRoundingMode () const;
+
+ int numLevels () const;
+ int numXLevels () const;
+ int numYLevels () const;
+ bool isValidLevel (int lx, int ly) const;
+
+ int levelWidth (int lx) const;
+ int levelHeight (int ly) const;
+
+ int numXTiles (int lx = 0) const;
+ int numYTiles (int ly = 0) const;
+
+ Imath::Box2i dataWindowForLevel (int l = 0) const;
+ Imath::Box2i dataWindowForLevel (int lx, int ly) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int l = 0) const;
+
+ Imath::Box2i dataWindowForTile (int dx, int dy,
+ int lx, int ly) const;
+
+
+ //----------------------------------------------------------------
+ // Read pixel data:
+ //
+ // readTile(dx, dy, lx, ly) reads the tile with tile
+ // coordinates (dx, dy), and level number (lx, ly),
+ // and stores it in the current frame buffer.
+ //
+ // dx must lie in the interval [0, numXTiles(lx)-1]
+ // dy must lie in the interval [0, numYTiles(ly)-1]
+ //
+ // lx must lie in the interval [0, numXLevels()-1]
+ // ly must lie in the inverval [0, numYLevels()-1]
+ //
+ // readTile(dx, dy, level) is a convenience function used
+ // for ONE_LEVEL and MIPMAP_LEVELS files. It calls
+ // readTile(dx, dy, level, level).
+ //
+ // The two readTiles(dx1, dx2, dy1, dy2, ...) functions allow
+ // reading multiple tiles at once. If multi-threading is used
+ // multiple tiles are read concurrently.
+ //
+ // Pixels that are outside the pixel coordinate range for the
+ // tile's level, are never accessed by readTile().
+ //
+ // Attempting to access a tile that is not present in the file
+ // throws an InputExc exception.
+ //
+ //----------------------------------------------------------------
+
+ void readTile (int dx, int dy, int l = 0);
+ void readTile (int dx, int dy, int lx, int ly);
+
+ void readTiles (int dxMin, int dxMax,
+ int dyMin, int dyMax, int lx, int ly);
+
+ void readTiles (int dxMin, int dxMax,
+ int dyMin, int dyMax, int l = 0);
+
+ private:
+
+ //
+ // Copy constructor and assignment are not implemented
+ //
+
+ TiledRgbaInputFile (const TiledRgbaInputFile &);
+ TiledRgbaInputFile & operator = (const TiledRgbaInputFile &);
+
+ class FromYa;
+
+ TiledInputFile * _inputFile;
+ FromYa * _fromYa;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTimeCode.cpp b/Source/OpenEXR/IlmImf/ImfTimeCode.cpp
new file mode 100644
index 0000000..9b34cce
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTimeCode.cpp
@@ -0,0 +1,415 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class TimeCode
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTimeCode.h>
+#include "Iex.h"
+
+namespace Imf {
+
+
+TimeCode::TimeCode ()
+{
+ _time = 0;
+ _user = 0;
+}
+
+
+TimeCode::TimeCode
+ (int hours,
+ int minutes,
+ int seconds,
+ int frame,
+ bool dropFrame,
+ bool colorFrame,
+ bool fieldPhase,
+ bool bgf0,
+ bool bgf1,
+ bool bgf2,
+ int binaryGroup1,
+ int binaryGroup2,
+ int binaryGroup3,
+ int binaryGroup4,
+ int binaryGroup5,
+ int binaryGroup6,
+ int binaryGroup7,
+ int binaryGroup8)
+{
+ setHours (hours);
+ setMinutes (minutes);
+ setSeconds (seconds);
+ setFrame (frame);
+ setDropFrame (dropFrame);
+ setColorFrame (colorFrame);
+ setFieldPhase (fieldPhase);
+ setBgf0 (bgf0);
+ setBgf1 (bgf1);
+ setBgf2 (bgf2);
+ setBinaryGroup (1, binaryGroup1);
+ setBinaryGroup (2, binaryGroup2);
+ setBinaryGroup (3, binaryGroup3);
+ setBinaryGroup (4, binaryGroup4);
+ setBinaryGroup (5, binaryGroup5);
+ setBinaryGroup (6, binaryGroup6);
+ setBinaryGroup (7, binaryGroup7);
+ setBinaryGroup (8, binaryGroup8);
+}
+
+
+TimeCode::TimeCode
+ (unsigned int timeAndFlags,
+ unsigned int userData,
+ Packing packing)
+{
+ setTimeAndFlags (timeAndFlags, packing);
+ setUserData (userData);
+}
+
+
+TimeCode::TimeCode (const TimeCode &other)
+{
+ _time = other._time;
+ _user = other._user;
+}
+
+
+TimeCode &
+TimeCode::operator = (const TimeCode &other)
+{
+ _time = other._time;
+ _user = other._user;
+ return *this;
+}
+
+
+namespace {
+
+unsigned int
+bitField (unsigned int value, int minBit, int maxBit)
+{
+ int shift = minBit;
+ unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
+ return (value & mask) >> shift;
+}
+
+
+void
+setBitField (unsigned int &value, int minBit, int maxBit, unsigned int field)
+{
+ int shift = minBit;
+ unsigned int mask = (~(~0U << (maxBit - minBit + 1)) << minBit);
+ value = ((value & ~mask) | ((field << shift) & mask));
+}
+
+
+int
+bcdToBinary (unsigned int bcd)
+{
+ return int ((bcd & 0x0f) + 10 * ((bcd >> 4) & 0x0f));
+}
+
+
+unsigned int
+binaryToBcd (int binary)
+{
+ int units = binary % 10;
+ int tens = (binary / 10) % 10;
+ return (unsigned int) (units | (tens << 4));
+}
+
+
+} // namespace
+
+
+int
+TimeCode::hours () const
+{
+ return bcdToBinary (bitField (_time, 24, 29));
+}
+
+
+void
+TimeCode::setHours (int value)
+{
+ if (value < 0 || value > 23)
+ throw Iex::ArgExc ("Cannot set hours field in time code. "
+ "New value is out of range.");
+
+ setBitField (_time, 24, 29, binaryToBcd (value));
+}
+
+
+int
+TimeCode::minutes () const
+{
+ return bcdToBinary (bitField (_time, 16, 22));
+}
+
+
+void
+TimeCode::setMinutes (int value)
+{
+ if (value < 0 || value > 59)
+ throw Iex::ArgExc ("Cannot set minutes field in time code. "
+ "New value is out of range.");
+
+ setBitField (_time, 16, 22, binaryToBcd (value));
+}
+
+
+int
+TimeCode::seconds () const
+{
+ return bcdToBinary (bitField (_time, 8, 14));
+}
+
+
+void
+TimeCode::setSeconds (int value)
+{
+ if (value < 0 || value > 59)
+ throw Iex::ArgExc ("Cannot set seconds field in time code. "
+ "New value is out of range.");
+
+ setBitField (_time, 8, 14, binaryToBcd (value));
+}
+
+
+int
+TimeCode::frame () const
+{
+ return bcdToBinary (bitField (_time, 0, 5));
+}
+
+
+void
+TimeCode::setFrame (int value)
+{
+ if (value < 0 || value > 59)
+ throw Iex::ArgExc ("Cannot set frame field in time code. "
+ "New value is out of range.");
+
+ setBitField (_time, 0, 5, binaryToBcd (value));
+}
+
+
+bool
+TimeCode::dropFrame () const
+{
+ return bool (bitField (_time, 6, 6));
+}
+
+
+void
+TimeCode::setDropFrame (bool value)
+{
+ setBitField (_time, 6, 6, (unsigned int) !!value);
+}
+
+
+bool
+TimeCode::colorFrame () const
+{
+ return bool (bitField (_time, 7, 7));
+}
+
+
+void
+TimeCode::setColorFrame (bool value)
+{
+ setBitField (_time, 7, 7, (unsigned int) !!value);
+}
+
+
+bool
+TimeCode::fieldPhase () const
+{
+ return bool (bitField (_time, 15, 15));
+}
+
+
+void
+TimeCode::setFieldPhase (bool value)
+{
+ setBitField (_time, 15, 15, (unsigned int) !!value);
+}
+
+
+bool
+TimeCode::bgf0 () const
+{
+ return bool (bitField (_time, 23, 23));
+}
+
+
+void
+TimeCode::setBgf0 (bool value)
+{
+ setBitField (_time, 23, 23, (unsigned int) !!value);
+}
+
+
+bool
+TimeCode::bgf1 () const
+{
+ return bool (bitField (_time, 30, 30));
+}
+
+
+void
+TimeCode::setBgf1 (bool value)
+{
+ setBitField (_time, 30, 30, (unsigned int) !!value);
+}
+
+
+bool
+TimeCode::bgf2 () const
+{
+ return bool (bitField (_time, 31, 31));
+}
+
+
+void
+TimeCode::setBgf2 (bool value)
+{
+ setBitField (_time, 31, 31, (unsigned int) !!value);
+}
+
+
+int
+TimeCode::binaryGroup (int group) const
+{
+ if (group < 1 || group > 8)
+ throw Iex::ArgExc ("Cannot extract binary group from time code "
+ "user data. Group number is out of range.");
+
+ int minBit = 4 * (group - 1);
+ int maxBit = minBit + 3;
+ return int (bitField (_user, minBit, maxBit));
+}
+
+
+void
+TimeCode::setBinaryGroup (int group, int value)
+{
+ if (group < 1 || group > 8)
+ throw Iex::ArgExc ("Cannot extract binary group from time code "
+ "user data. Group number is out of range.");
+
+ int minBit = 4 * (group - 1);
+ int maxBit = minBit + 3;
+ setBitField (_user, minBit, maxBit, (unsigned int) value);
+}
+
+
+unsigned int
+TimeCode::timeAndFlags (Packing packing) const
+{
+ if (packing == TV50_PACKING)
+ {
+ unsigned int t = _time;
+
+ t &= ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
+
+ t |= ((unsigned int) bgf0() << 15);
+ t |= ((unsigned int) bgf2() << 23);
+ t |= ((unsigned int) bgf1() << 30);
+ t |= ((unsigned int) fieldPhase() << 31);
+
+ return t;
+ }
+ if (packing == FILM24_PACKING)
+ {
+ return _time & ~((1 << 6) | (1 << 7));
+ }
+ else // packing == TV60_PACKING
+ {
+ return _time;
+ }
+}
+
+
+void
+TimeCode::setTimeAndFlags (unsigned int value, Packing packing)
+{
+ if (packing == TV50_PACKING)
+ {
+ _time = value &
+ ~((1 << 6) | (1 << 15) | (1 << 23) | (1 << 30) | (1 << 31));
+
+ if (value & (1 << 15))
+ setBgf0 (true);
+
+ if (value & (1 << 23))
+ setBgf2 (true);
+
+ if (value & (1 << 30))
+ setBgf1 (true);
+
+ if (value & (1 << 31))
+ setFieldPhase (true);
+ }
+ else if (packing == FILM24_PACKING)
+ {
+ _time = value & ~((1 << 6) | (1 << 7));
+ }
+ else // packing == TV60_PACKING
+ {
+ _time = value;
+ }
+}
+
+
+unsigned int
+TimeCode::userData () const
+{
+ return _user;
+}
+
+
+void
+TimeCode::setUserData (unsigned int value)
+{
+ _user = value;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTimeCode.h b/Source/OpenEXR/IlmImf/ImfTimeCode.h
new file mode 100644
index 0000000..3030d49
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTimeCode.h
@@ -0,0 +1,226 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TIME_CODE_H
+#define INCLUDED_IMF_TIME_CODE_H
+
+//-----------------------------------------------------------------------------
+//
+// class TimeCode
+//
+// A TimeCode object stores time and control codes as described
+// in SMPTE standard 12M-1999. A TimeCode object contains the
+// following fields:
+//
+// Time Address:
+//
+// hours integer, range 0 - 23
+// minutes integer, range 0 - 59
+// seconds integer, range 0 - 59
+// frame integer, range 0 - 29
+//
+// Flags:
+//
+// drop frame flag boolean
+// color frame flag boolean
+// field/phase flag boolean
+// bgf0 boolean
+// bgf1 boolean
+// bgf2 boolean
+//
+// Binary groups for user-defined data and control codes:
+//
+// binary group 1 integer, range 0 - 15
+// binary group 2 integer, range 0 - 15
+// ...
+// binary group 8 integer, range 0 - 15
+//
+// Class TimeCode contains methods to convert between the fields
+// listed above and a more compact representation where the fields
+// are packed into two unsigned 32-bit integers. In the packed
+// integer representations, bit 0 is the least significant bit,
+// and bit 31 is the most significant bit of the integer value.
+//
+// The time address and flags fields can be packed in three
+// different ways:
+//
+// bits packing for packing for packing for
+// 24-frame 60-field 50-field
+// film television television
+//
+// 0 - 3 frame units frame units frame units
+// 4 - 5 frame tens frame tens frame tens
+// 6 unused, set to 0 drop frame flag unused, set to 0
+// 7 unused, set to 0 color frame flag color frame flag
+// 8 - 11 seconds units seconds units seconds units
+// 12 - 14 seconds tens seconds tens seconds tens
+// 15 phase flag field/phase flag bgf0
+// 16 - 19 minutes units minutes units minutes units
+// 20 - 22 minutes tens minutes tens minutes tens
+// 23 bgf0 bgf0 bgf2
+// 24 - 27 hours units hours units hours units
+// 28 - 29 hours tens hours tens hours tens
+// 30 bgf1 bgf1 bgf1
+// 31 bgf2 bgf2 field/phase flag
+//
+// User-defined data and control codes are packed as follows:
+//
+// bits field
+//
+// 0 - 3 binary group 1
+// 4 - 7 binary group 2
+// 8 - 11 binary group 3
+// 12 - 15 binary group 4
+// 16 - 19 binary group 5
+// 20 - 23 binary group 6
+// 24 - 27 binary group 7
+// 28 - 31 binary group 8
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+class TimeCode
+{
+ public:
+
+ //---------------------
+ // Bit packing variants
+ //---------------------
+
+ enum Packing
+ {
+ TV60_PACKING, // packing for 60-field television
+ TV50_PACKING, // packing for 50-field television
+ FILM24_PACKING // packing for 24-frame film
+ };
+
+
+ //-------------------------------------
+ // Constructors and assignment operator
+ //-------------------------------------
+
+ TimeCode (); // all fields set to 0 or false
+
+ TimeCode (int hours,
+ int minutes,
+ int seconds,
+ int frame,
+ bool dropFrame = false,
+ bool colorFrame = false,
+ bool fieldPhase = false,
+ bool bgf0 = false,
+ bool bgf1 = false,
+ bool bgf2 = false,
+ int binaryGroup1 = 0,
+ int binaryGroup2 = 0,
+ int binaryGroup3 = 0,
+ int binaryGroup4 = 0,
+ int binaryGroup5 = 0,
+ int binaryGroup6 = 0,
+ int binaryGroup7 = 0,
+ int binaryGroup8 = 0);
+
+ TimeCode (unsigned int timeAndFlags,
+ unsigned int userData = 0,
+ Packing packing = TV60_PACKING);
+
+ TimeCode (const TimeCode &other);
+
+ TimeCode & operator = (const TimeCode &other);
+
+
+ //----------------------------
+ // Access to individual fields
+ //----------------------------
+
+ int hours () const;
+ void setHours (int value);
+
+ int minutes () const;
+ void setMinutes (int value);
+
+ int seconds () const;
+ void setSeconds (int value);
+
+ int frame () const;
+ void setFrame (int value);
+
+ bool dropFrame () const;
+ void setDropFrame (bool value);
+
+ bool colorFrame () const;
+ void setColorFrame (bool value);
+
+ bool fieldPhase () const;
+ void setFieldPhase (bool value);
+
+ bool bgf0 () const;
+ void setBgf0 (bool value);
+
+ bool bgf1 () const;
+ void setBgf1 (bool value);
+
+ bool bgf2 () const;
+ void setBgf2 (bool value);
+
+ int binaryGroup (int group) const; // group must be between 1 and 8
+ void setBinaryGroup (int group, int value);
+
+
+ //---------------------------------
+ // Access to packed representations
+ //---------------------------------
+
+ unsigned int timeAndFlags (Packing packing = TV60_PACKING) const;
+
+ void setTimeAndFlags (unsigned int value,
+ Packing packing = TV60_PACKING);
+
+ unsigned int userData () const;
+
+ void setUserData (unsigned int value);
+
+ private:
+
+ unsigned int _time;
+ unsigned int _user;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.cpp b/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.cpp
new file mode 100644
index 0000000..2c2088b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.cpp
@@ -0,0 +1,78 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// class TimeCodeAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfTimeCodeAttribute.h>
+
+namespace Imf {
+
+
+template <>
+const char *
+TimeCodeAttribute::staticTypeName ()
+{
+ return "timecode";
+}
+
+
+template <>
+void
+TimeCodeAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.timeAndFlags());
+ Xdr::write <StreamIO> (os, _value.userData());
+}
+
+
+template <>
+void
+TimeCodeAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ unsigned int tmp;
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setTimeAndFlags (tmp);
+
+ Xdr::read <StreamIO> (is, tmp);
+ _value.setUserData (tmp);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.h b/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.h
new file mode 100644
index 0000000..3d548fa
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfTimeCodeAttribute.h
@@ -0,0 +1,72 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_TIME_CODE_ATTRIBUTE_H
+#define INCLUDED_IMF_TIME_CODE_ATTRIBUTE_H
+
+
+//-----------------------------------------------------------------------------
+//
+// class TimeCodeAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include <ImfTimeCode.h>
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<TimeCode> TimeCodeAttribute;
+
+template <>
+const char *TimeCodeAttribute::staticTypeName ();
+
+template <>
+void TimeCodeAttribute::writeValueTo (OStream &, int) const;
+
+template <>
+void TimeCodeAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfTimeCodeAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfVecAttribute.cpp b/Source/OpenEXR/IlmImf/ImfVecAttribute.cpp
new file mode 100644
index 0000000..0ac1815
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfVecAttribute.cpp
@@ -0,0 +1,160 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class V2iAttribute
+// class V2fAttribute
+// class V3iAttribute
+// class V3fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfVecAttribute.h>
+
+
+namespace Imf {
+
+
+template <>
+const char *
+V2iAttribute::staticTypeName ()
+{
+ return "v2i";
+}
+
+
+template <>
+void
+V2iAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.x);
+ Xdr::write <StreamIO> (os, _value.y);
+}
+
+
+template <>
+void
+V2iAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.x);
+ Xdr::read <StreamIO> (is, _value.y);
+}
+
+
+template <>
+const char *
+V2fAttribute::staticTypeName ()
+{
+ return "v2f";
+}
+
+
+template <>
+void
+V2fAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.x);
+ Xdr::write <StreamIO> (os, _value.y);
+}
+
+
+template <>
+void
+V2fAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.x);
+ Xdr::read <StreamIO> (is, _value.y);
+}
+
+
+template <>
+const char *
+V3iAttribute::staticTypeName ()
+{
+ return "v3i";
+}
+
+
+template <>
+void
+V3iAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.x);
+ Xdr::write <StreamIO> (os, _value.y);
+ Xdr::write <StreamIO> (os, _value.z);
+}
+
+
+template <>
+void
+V3iAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.x);
+ Xdr::read <StreamIO> (is, _value.y);
+ Xdr::read <StreamIO> (is, _value.z);
+}
+
+
+template <>
+const char *
+V3fAttribute::staticTypeName ()
+{
+ return "v3f";
+}
+
+
+template <>
+void
+V3fAttribute::writeValueTo (OStream &os, int version) const
+{
+ Xdr::write <StreamIO> (os, _value.x);
+ Xdr::write <StreamIO> (os, _value.y);
+ Xdr::write <StreamIO> (os, _value.z);
+}
+
+
+template <>
+void
+V3fAttribute::readValueFrom (IStream &is, int size, int version)
+{
+ Xdr::read <StreamIO> (is, _value.x);
+ Xdr::read <StreamIO> (is, _value.y);
+ Xdr::read <StreamIO> (is, _value.z);
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfVecAttribute.h b/Source/OpenEXR/IlmImf/ImfVecAttribute.h
new file mode 100644
index 0000000..ba13f86
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfVecAttribute.h
@@ -0,0 +1,87 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_VEC_ATTRIBUTE_H
+#define INCLUDED_IMF_VEC_ATTRIBUTE_H
+
+//-----------------------------------------------------------------------------
+//
+// class V2iAttribute
+// class V2fAttribute
+// class V3iAttribute
+// class V3fAttribute
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfAttribute.h>
+#include "ImathVec.h"
+
+
+namespace Imf {
+
+
+typedef TypedAttribute<Imath::V2i> V2iAttribute;
+template <> const char *V2iAttribute::staticTypeName ();
+template <> void V2iAttribute::writeValueTo (OStream &, int) const;
+template <> void V2iAttribute::readValueFrom (IStream &, int, int);
+
+
+typedef TypedAttribute<Imath::V2f> V2fAttribute;
+template <> const char *V2fAttribute::staticTypeName ();
+template <> void V2fAttribute::writeValueTo (OStream &, int) const;
+template <> void V2fAttribute::readValueFrom (IStream &, int, int);
+
+
+typedef TypedAttribute<Imath::V3i> V3iAttribute;
+template <> const char *V3iAttribute::staticTypeName ();
+template <> void V3iAttribute::writeValueTo (OStream &, int) const;
+template <> void V3iAttribute::readValueFrom (IStream &, int, int);
+
+
+typedef TypedAttribute<Imath::V3f> V3fAttribute;
+template <> const char *V3fAttribute::staticTypeName ();
+template <> void V3fAttribute::writeValueTo (OStream &, int) const;
+template <> void V3fAttribute::readValueFrom (IStream &, int, int);
+
+
+} // namespace Imf
+
+// Metrowerks compiler wants the .cpp file inlined, too
+#ifdef __MWERKS__
+#include <ImfVecAttribute.cpp>
+#endif
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfVersion.cpp b/Source/OpenEXR/IlmImf/ImfVersion.cpp
new file mode 100644
index 0000000..3814479
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfVersion.cpp
@@ -0,0 +1,59 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//-----------------------------------------------------------------------------
+//
+// Magic and version number.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ImfVersion.h>
+
+namespace Imf {
+
+
+bool
+isImfMagic (const char bytes[4])
+{
+ return bytes[0] == ((MAGIC >> 0) & 0x00ff) &&
+ bytes[1] == ((MAGIC >> 8) & 0x00ff) &&
+ bytes[2] == ((MAGIC >> 16) & 0x00ff) &&
+ bytes[3] == ((MAGIC >> 24) & 0x00ff);
+}
+
+
+} // namespace Imf
+
diff --git a/Source/OpenEXR/IlmImf/ImfVersion.h b/Source/OpenEXR/IlmImf/ImfVersion.h
new file mode 100644
index 0000000..76f0d84
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfVersion.h
@@ -0,0 +1,117 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_VERSION_H
+#define INCLUDED_IMF_VERSION_H
+
+//-----------------------------------------------------------------------------
+//
+// Magic and version number.
+//
+//-----------------------------------------------------------------------------
+
+
+namespace Imf {
+
+
+//
+// The MAGIC number is stored in the first four bytes of every
+// OpenEXR image file. This can be used to quickly test whether
+// a given file is an OpenEXR image file (see isImfMagic(), below).
+//
+
+const int MAGIC = 20000630;
+
+
+//
+// The second item in each OpenEXR image file, right after the
+// magic number, is a four-byte file version identifier. Depending
+// on a file's version identifier, a file reader can enable various
+// backwards-compatibility switches, or it can quickly reject files
+// that it cannot read.
+//
+// The version identifier is split into an 8-bit version number,
+// and a 24-bit flags field.
+//
+
+const int VERSION_NUMBER_FIELD = 0x000000ff;
+const int VERSION_FLAGS_FIELD = 0xffffff00;
+
+
+//
+// Value that goes into VERSION_NUMBER_FIELD.
+//
+
+const int EXR_VERSION = 2;
+
+
+//
+// Flags that can go into VERSION_FLAGS_FIELD.
+// Flags can only occupy the 1 bits in VERSION_FLAGS_FIELD.
+//
+
+const int TILED_FLAG = 0x00000200;
+
+
+//
+// Bitwise OR of all known flags.
+//
+
+const int ALL_FLAGS = TILED_FLAG;
+
+
+//
+// Utility functions
+//
+
+inline bool isTiled (int version) {return !!(version & TILED_FLAG);}
+inline int makeTiled (int version) {return version | TILED_FLAG;}
+inline int makeNotTiled (int version) {return version & ~TILED_FLAG;}
+inline int getVersion (int version) {return version & VERSION_NUMBER_FIELD;}
+inline int getFlags (int version) {return version & VERSION_FLAGS_FIELD;}
+inline bool supportsFlags (int flags) {return !(flags & ~ALL_FLAGS);}
+
+
+//
+// Given the first four bytes of a file, returns true if the
+// file is probably an OpenEXR image file, false if not.
+//
+
+bool isImfMagic (const char bytes[4]);
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfWav.cpp b/Source/OpenEXR/IlmImf/ImfWav.cpp
new file mode 100644
index 0000000..d4486d5
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfWav.cpp
@@ -0,0 +1,390 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// 16-bit Haar Wavelet encoding and decoding
+//
+// The source code in this file is derived from the encoding
+// and decoding routines written by Christian Rouet for his
+// PIZ image file format.
+//
+//-----------------------------------------------------------------------------
+
+
+#include <ImfWav.h>
+
+namespace Imf {
+namespace {
+
+
+//
+// Wavelet basis functions without modulo arithmetic; they produce
+// the best compression ratios when the wavelet-transformed data are
+// Huffman-encoded, but the wavelet transform works only for 14-bit
+// data (untransformed data values must be less than (1 << 14)).
+//
+
+inline void
+wenc14 (unsigned short a, unsigned short b,
+ unsigned short &l, unsigned short &h)
+{
+ short as = a;
+ short bs = b;
+
+ short ms = (as + bs) >> 1;
+ short ds = as - bs;
+
+ l = ms;
+ h = ds;
+}
+
+
+inline void
+wdec14 (unsigned short l, unsigned short h,
+ unsigned short &a, unsigned short &b)
+{
+ short ls = l;
+ short hs = h;
+
+ int hi = hs;
+ int ai = ls + (hi & 1) + (hi >> 1);
+
+ short as = ai;
+ short bs = ai - hi;
+
+ a = as;
+ b = bs;
+}
+
+
+//
+// Wavelet basis functions with modulo arithmetic; they work with full
+// 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't
+// compress the data quite as well.
+//
+
+const int NBITS = 16;
+const int A_OFFSET = 1 << (NBITS - 1);
+const int M_OFFSET = 1 << (NBITS - 1);
+const int MOD_MASK = (1 << NBITS) - 1;
+
+
+inline void
+wenc16 (unsigned short a, unsigned short b,
+ unsigned short &l, unsigned short &h)
+{
+ int ao = (a + A_OFFSET) & MOD_MASK;
+ int m = ((ao + b) >> 1);
+ int d = ao - b;
+
+ if (d < 0)
+ m = (m + M_OFFSET) & MOD_MASK;
+
+ d &= MOD_MASK;
+
+ l = m;
+ h = d;
+}
+
+
+inline void
+wdec16 (unsigned short l, unsigned short h,
+ unsigned short &a, unsigned short &b)
+{
+ int m = l;
+ int d = h;
+ int bb = (m - (d >> 1)) & MOD_MASK;
+ int aa = (d + bb - A_OFFSET) & MOD_MASK;
+ b = bb;
+ a = aa;
+}
+
+} // namespace
+
+
+//
+// 2D Wavelet encoding:
+//
+
+void
+wav2Encode
+ (unsigned short* in, // io: values are transformed in place
+ int nx, // i : x size
+ int ox, // i : x offset
+ int ny, // i : y size
+ int oy, // i : y offset
+ unsigned short mx) // i : maximum in[x][y] value
+{
+ bool w14 = (mx < (1 << 14));
+ int n = (nx > ny)? ny: nx;
+ int p = 1; // == 1 << level
+ int p2 = 2; // == 1 << (level+1)
+
+ //
+ // Hierachical loop on smaller dimension n
+ //
+
+ while (p2 <= n)
+ {
+ unsigned short *py = in;
+ unsigned short *ey = in + oy * (ny - p2);
+ int oy1 = oy * p;
+ int oy2 = oy * p2;
+ int ox1 = ox * p;
+ int ox2 = ox * p2;
+ unsigned short i00,i01,i10,i11;
+
+ //
+ // Y loop
+ //
+
+ for (; py <= ey; py += oy2)
+ {
+ unsigned short *px = py;
+ unsigned short *ex = py + ox * (nx - p2);
+
+ //
+ // X loop
+ //
+
+ for (; px <= ex; px += ox2)
+ {
+ unsigned short *p01 = px + ox1;
+ unsigned short *p10 = px + oy1;
+ unsigned short *p11 = p10 + ox1;
+
+ //
+ // 2D wavelet encoding
+ //
+
+ if (w14)
+ {
+ wenc14 (*px, *p01, i00, i01);
+ wenc14 (*p10, *p11, i10, i11);
+ wenc14 (i00, i10, *px, *p10);
+ wenc14 (i01, i11, *p01, *p11);
+ }
+ else
+ {
+ wenc16 (*px, *p01, i00, i01);
+ wenc16 (*p10, *p11, i10, i11);
+ wenc16 (i00, i10, *px, *p10);
+ wenc16 (i01, i11, *p01, *p11);
+ }
+ }
+
+ //
+ // Encode (1D) odd column (still in Y loop)
+ //
+
+ if (nx & p)
+ {
+ unsigned short *p10 = px + oy1;
+
+ if (w14)
+ wenc14 (*px, *p10, i00, *p10);
+ else
+ wenc16 (*px, *p10, i00, *p10);
+
+ *px= i00;
+ }
+ }
+
+ //
+ // Encode (1D) odd line (must loop in X)
+ //
+
+ if (ny & p)
+ {
+ unsigned short *px = py;
+ unsigned short *ex = py + ox * (nx - p2);
+
+ for (; px <= ex; px += ox2)
+ {
+ unsigned short *p01 = px + ox1;
+
+ if (w14)
+ wenc14 (*px, *p01, i00, *p01);
+ else
+ wenc16 (*px, *p01, i00, *p01);
+
+ *px= i00;
+ }
+ }
+
+ //
+ // Next level
+ //
+
+ p = p2;
+ p2 <<= 1;
+ }
+}
+
+
+//
+// 2D Wavelet decoding:
+//
+
+void
+wav2Decode
+ (unsigned short* in, // io: values are transformed in place
+ int nx, // i : x size
+ int ox, // i : x offset
+ int ny, // i : y size
+ int oy, // i : y offset
+ unsigned short mx) // i : maximum in[x][y] value
+{
+ bool w14 = (mx < (1 << 14));
+ int n = (nx > ny)? ny: nx;
+ int p = 1;
+ int p2;
+
+ //
+ // Search max level
+ //
+
+ while (p <= n)
+ p <<= 1;
+
+ p >>= 1;
+ p2 = p;
+ p >>= 1;
+
+ //
+ // Hierarchical loop on smaller dimension n
+ //
+
+ while (p >= 1)
+ {
+ unsigned short *py = in;
+ unsigned short *ey = in + oy * (ny - p2);
+ int oy1 = oy * p;
+ int oy2 = oy * p2;
+ int ox1 = ox * p;
+ int ox2 = ox * p2;
+ unsigned short i00,i01,i10,i11;
+
+ //
+ // Y loop
+ //
+
+ for (; py <= ey; py += oy2)
+ {
+ unsigned short *px = py;
+ unsigned short *ex = py + ox * (nx - p2);
+
+ //
+ // X loop
+ //
+
+ for (; px <= ex; px += ox2)
+ {
+ unsigned short *p01 = px + ox1;
+ unsigned short *p10 = px + oy1;
+ unsigned short *p11 = p10 + ox1;
+
+ //
+ // 2D wavelet decoding
+ //
+
+ if (w14)
+ {
+ wdec14 (*px, *p10, i00, i10);
+ wdec14 (*p01, *p11, i01, i11);
+ wdec14 (i00, i01, *px, *p01);
+ wdec14 (i10, i11, *p10, *p11);
+ }
+ else
+ {
+ wdec16 (*px, *p10, i00, i10);
+ wdec16 (*p01, *p11, i01, i11);
+ wdec16 (i00, i01, *px, *p01);
+ wdec16 (i10, i11, *p10, *p11);
+ }
+ }
+
+ //
+ // Decode (1D) odd column (still in Y loop)
+ //
+
+ if (nx & p)
+ {
+ unsigned short *p10 = px + oy1;
+
+ if (w14)
+ wdec14 (*px, *p10, i00, *p10);
+ else
+ wdec16 (*px, *p10, i00, *p10);
+
+ *px= i00;
+ }
+ }
+
+ //
+ // Decode (1D) odd line (must loop in X)
+ //
+
+ if (ny & p)
+ {
+ unsigned short *px = py;
+ unsigned short *ex = py + ox * (nx - p2);
+
+ for (; px <= ex; px += ox2)
+ {
+ unsigned short *p01 = px + ox1;
+
+ if (w14)
+ wdec14 (*px, *p01, i00, *p01);
+ else
+ wdec16 (*px, *p01, i00, *p01);
+
+ *px= i00;
+ }
+ }
+
+ //
+ // Next level
+ //
+
+ p2 = p;
+ p >>= 1;
+ }
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfWav.h b/Source/OpenEXR/IlmImf/ImfWav.h
new file mode 100644
index 0000000..815d2d5
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfWav.h
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_WAV_H
+#define INCLUDED_IMF_WAV_H
+
+//-----------------------------------------------------------------------------
+//
+// 16-bit Haar Wavelet encoding and decoding
+//
+//-----------------------------------------------------------------------------
+
+namespace Imf {
+
+
+void
+wav2Encode
+ (unsigned short *in, // io: values in[y][x] are transformed in place
+ int nx, // i : x size
+ int ox, // i : x offset
+ int ny, // i : y size
+ int oy, // i : y offset
+ unsigned short mx); // i : maximum in[x][y] value
+
+void
+wav2Decode
+ (unsigned short *in, // io: values in[y][x] are transformed in place
+ int nx, // i : x size
+ int ox, // i : x offset
+ int ny, // i : y size
+ int oy, // i : y offset
+ unsigned short mx); // i : maximum in[x][y] value
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfXdr.h b/Source/OpenEXR/IlmImf/ImfXdr.h
new file mode 100644
index 0000000..7992921
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfXdr.h
@@ -0,0 +1,916 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMF_XDR_H
+#define INCLUDED_IMF_XDR_H
+
+//----------------------------------------------------------------------------
+//
+// Xdr -- routines to convert data between the machine's native
+// format and a machine-independent external data representation:
+//
+// write<R> (T &o, S v); converts a value, v, of type S
+// into a machine-independent
+// representation and stores the
+// result in an output buffer, o.
+//
+// read<R> (T &i, S &v); reads the machine-independent
+// representation of a value of type
+// S from input buffer i, converts
+// the value into the machine's native
+// representation, and stores the result
+// in v.
+//
+// size<S>(); returns the size, in bytes, of the
+// machine-independent representation
+// of an object of type S.
+//
+// The write() and read() routines are templates; data can be written
+// to and read from any output or input buffer type T for which a helper
+// class, R, exits. Class R must define a method to store a char array
+// in a T, and a method to read a char array from a T:
+//
+// struct R
+// {
+// static void
+// writeChars (T &o, const char c[/*n*/], int n)
+// {
+// ... // Write c[0], c[1] ... c[n-1] to output buffer o.
+// }
+//
+// static void
+// readChars (T &i, char c[/*n*/], int n)
+// {
+// ... // Read n characters from input buffer i
+// // and copy them to c[0], c[1] ... c[n-1].
+// }
+// };
+//
+// Example - writing to and reading from iostreams:
+//
+// struct CharStreamIO
+// {
+// static void
+// writeChars (ostream &os, const char c[], int n)
+// {
+// os.write (c, n);
+// }
+//
+// static void
+// readChars (istream &is, char c[], int n)
+// {
+// is.read (c, n);
+// }
+// };
+//
+// ...
+//
+// Xdr::write<CharStreamIO> (os, 3);
+// Xdr::write<CharStreamIO> (os, 5.0);
+//
+//----------------------------------------------------------------------------
+
+#include <ImfInt64.h>
+#include "IexMathExc.h"
+#include "half.h"
+#include <limits.h>
+
+namespace Imf {
+namespace Xdr {
+
+
+//-------------------------------
+// Write data to an output stream
+//-------------------------------
+
+template <class S, class T>
+void
+write (T &out, bool v);
+
+template <class S, class T>
+void
+write (T &out, char v);
+
+template <class S, class T>
+void
+write (T &out, signed char v);
+
+template <class S, class T>
+void
+write (T &out, unsigned char v);
+
+template <class S, class T>
+void
+write (T &out, signed short v);
+
+template <class S, class T>
+void
+write (T &out, unsigned short v);
+
+template <class S, class T>
+void
+write (T &out, signed int v);
+
+template <class S, class T>
+void
+write (T &out, unsigned int v);
+
+template <class S, class T>
+void
+write (T &out, signed long v);
+
+template <class S, class T>
+void
+write (T &out, unsigned long v);
+
+#if ULONG_MAX != 18446744073709551615LU
+
+ template <class S, class T>
+ void
+ write (T &out, Int64 v);
+
+#endif
+
+template <class S, class T>
+void
+write (T &out, float v);
+
+template <class S, class T>
+void
+write (T &out, double v);
+
+template <class S, class T>
+void
+write (T &out, half v);
+
+template <class S, class T>
+void
+write (T &out, const char v[/*n*/], int n); // fixed-size char array
+
+template <class S, class T>
+void
+write (T &out, const char v[]); // zero-terminated string
+
+
+//-----------------------------------------
+// Append padding bytes to an output stream
+//-----------------------------------------
+
+template <class S, class T>
+void
+pad (T &out, int n); // write n padding bytes
+
+
+
+//-------------------------------
+// Read data from an input stream
+//-------------------------------
+
+template <class S, class T>
+void
+read (T &in, bool &v);
+
+template <class S, class T>
+void
+read (T &in, char &v);
+
+template <class S, class T>
+void
+read (T &in, signed char &v);
+
+template <class S, class T>
+void
+read (T &in, unsigned char &v);
+
+template <class S, class T>
+void
+read (T &in, signed short &v);
+
+template <class S, class T>
+void
+read (T &in, unsigned short &v);
+
+template <class S, class T>
+void
+read (T &in, signed int &v);
+
+template <class S, class T>
+void
+read (T &in, unsigned int &v);
+
+template <class S, class T>
+void
+read (T &in, signed long &v);
+
+template <class S, class T>
+void
+read (T &in, unsigned long &v);
+
+#if ULONG_MAX != 18446744073709551615LU
+
+ template <class S, class T>
+ void
+ read (T &in, Int64 &v);
+
+#endif
+
+template <class S, class T>
+void
+read (T &in, float &v);
+
+template <class S, class T>
+void
+read (T &in, double &v);
+
+template <class S, class T>
+void
+read (T &in, half &v);
+
+template <class S, class T>
+void
+read (T &in, char v[/*n*/], int n); // fixed-size char array
+
+template <class S, class T>
+void
+read (T &in, int n, char v[/*n*/]); // zero-terminated string
+
+
+//-------------------------------------------
+// Skip over padding bytes in an input stream
+//-------------------------------------------
+
+template <class S, class T>
+void
+skip (T &in, int n); // skip n padding bytes
+
+
+
+//--------------------------------------
+// Size of the machine-independent
+// representation of an object of type S
+//--------------------------------------
+
+template <class S>
+int
+size ();
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class S, class T>
+inline void
+writeSignedChars (T &out, const signed char c[], int n)
+{
+ S::writeChars (out, (const char *) c, n);
+}
+
+
+template <class S, class T>
+inline void
+writeUnsignedChars (T &out, const unsigned char c[], int n)
+{
+ S::writeChars (out, (const char *) c, n);
+}
+
+
+template <class S, class T>
+inline void
+readSignedChars (T &in, signed char c[], int n)
+{
+ S::readChars (in, (char *) c, n);
+}
+
+
+template <class S, class T>
+inline void
+readUnsignedChars (T &in, unsigned char c[], int n)
+{
+ S::readChars (in, (char *) c, n);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, bool v)
+{
+ char c = !!v;
+ S::writeChars (out, &c, 1);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, char v)
+{
+ S::writeChars (out, &v, 1);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, signed char v)
+{
+ writeSignedChars<S> (out, &v, 1);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, unsigned char v)
+{
+ writeUnsignedChars<S> (out, &v, 1);
+}
+
+
+template <class S, class T>
+void
+write (T &out, signed short v)
+{
+ signed char b[2];
+
+ b[0] = (signed char) (v);
+ b[1] = (signed char) (v >> 8);
+
+ writeSignedChars<S> (out, b, 2);
+}
+
+
+template <class S, class T>
+void
+write (T &out, unsigned short v)
+{
+ unsigned char b[2];
+
+ b[0] = (unsigned char) (v);
+ b[1] = (unsigned char) (v >> 8);
+
+ writeUnsignedChars<S> (out, b, 2);
+}
+
+
+template <class S, class T>
+void
+write (T &out, signed int v)
+{
+ signed char b[4];
+
+ b[0] = (signed char) (v);
+ b[1] = (signed char) (v >> 8);
+ b[2] = (signed char) (v >> 16);
+ b[3] = (signed char) (v >> 24);
+
+ writeSignedChars<S> (out, b, 4);
+}
+
+
+template <class S, class T>
+void
+write (T &out, unsigned int v)
+{
+ unsigned char b[4];
+
+ b[0] = (unsigned char) (v);
+ b[1] = (unsigned char) (v >> 8);
+ b[2] = (unsigned char) (v >> 16);
+ b[3] = (unsigned char) (v >> 24);
+
+ writeUnsignedChars<S> (out, b, 4);
+}
+
+
+template <class S, class T>
+void
+write (T &out, signed long v)
+{
+ signed char b[8];
+
+ b[0] = (signed char) (v);
+ b[1] = (signed char) (v >> 8);
+ b[2] = (signed char) (v >> 16);
+ b[3] = (signed char) (v >> 24);
+
+ #if LONG_MAX == 2147483647
+
+ if (v >= 0)
+ {
+ b[4] = 0;
+ b[5] = 0;
+ b[6] = 0;
+ b[7] = 0;
+ }
+ else
+ {
+ b[4] = ~0;
+ b[5] = ~0;
+ b[6] = ~0;
+ b[7] = ~0;
+ }
+
+ #elif LONG_MAX == 9223372036854775807L
+
+ b[4] = (signed char) (v >> 32);
+ b[5] = (signed char) (v >> 40);
+ b[6] = (signed char) (v >> 48);
+ b[7] = (signed char) (v >> 56);
+
+ #else
+
+ #error write<T> (T &out, signed long v) not implemented
+
+ #endif
+
+ writeSignedChars<S> (out, b, 8);
+}
+
+
+template <class S, class T>
+void
+write (T &out, unsigned long v)
+{
+ unsigned char b[8];
+
+ b[0] = (unsigned char) (v);
+ b[1] = (unsigned char) (v >> 8);
+ b[2] = (unsigned char) (v >> 16);
+ b[3] = (unsigned char) (v >> 24);
+
+ #if ULONG_MAX == 4294967295U
+
+ b[4] = 0;
+ b[5] = 0;
+ b[6] = 0;
+ b[7] = 0;
+
+ #elif ULONG_MAX == 18446744073709551615LU
+
+ b[4] = (unsigned char) (v >> 32);
+ b[5] = (unsigned char) (v >> 40);
+ b[6] = (unsigned char) (v >> 48);
+ b[7] = (unsigned char) (v >> 56);
+
+ #else
+
+ #error write<T> (T &out, unsigned long v) not implemented
+
+ #endif
+
+ writeUnsignedChars<S> (out, b, 8);
+}
+
+
+#if ULONG_MAX != 18446744073709551615LU
+
+ template <class S, class T>
+ void
+ write (T &out, Int64 v)
+ {
+ unsigned char b[8];
+
+ b[0] = (unsigned char) (v);
+ b[1] = (unsigned char) (v >> 8);
+ b[2] = (unsigned char) (v >> 16);
+ b[3] = (unsigned char) (v >> 24);
+ b[4] = (unsigned char) (v >> 32);
+ b[5] = (unsigned char) (v >> 40);
+ b[6] = (unsigned char) (v >> 48);
+ b[7] = (unsigned char) (v >> 56);
+
+ writeUnsignedChars<S> (out, b, 8);
+ }
+
+#endif
+
+
+template <class S, class T>
+void
+write (T &out, float v)
+{
+ union {unsigned int i; float f;} u;
+ u.f = v;
+
+ unsigned char b[4];
+
+ b[0] = (unsigned char) (u.i);
+ b[1] = (unsigned char) (u.i >> 8);
+ b[2] = (unsigned char) (u.i >> 16);
+ b[3] = (unsigned char) (u.i >> 24);
+
+ writeUnsignedChars<S> (out, b, 4);
+}
+
+
+template <class S, class T>
+void
+write (T &out, double v)
+{
+ union {Int64 i; double d;} u;
+ u.d = v;
+
+ unsigned char b[8];
+
+ b[0] = (unsigned char) (u.i);
+ b[1] = (unsigned char) (u.i >> 8);
+ b[2] = (unsigned char) (u.i >> 16);
+ b[3] = (unsigned char) (u.i >> 24);
+ b[4] = (unsigned char) (u.i >> 32);
+ b[5] = (unsigned char) (u.i >> 40);
+ b[6] = (unsigned char) (u.i >> 48);
+ b[7] = (unsigned char) (u.i >> 56);
+
+ writeUnsignedChars<S> (out, b, 8);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, half v)
+{
+ unsigned char b[2];
+
+ b[0] = (unsigned char) (v.bits());
+ b[1] = (unsigned char) (v.bits() >> 8);
+
+ writeUnsignedChars<S> (out, b, 2);
+}
+
+
+template <class S, class T>
+inline void
+write (T &out, const char v[], int n) // fixed-size char array
+{
+ S::writeChars (out, v, n);
+}
+
+
+template <class S, class T>
+void
+write (T &out, const char v[]) // zero-terminated string
+{
+ while (*v)
+ {
+ S::writeChars (out, v, 1);
+ ++v;
+ }
+
+ S::writeChars (out, v, 1);
+}
+
+
+template <class S, class T>
+void
+pad (T &out, int n) // add n padding bytes
+{
+ for (int i = 0; i < n; i++)
+ {
+ const char c = 0;
+ S::writeChars (out, &c, 1);
+ }
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, bool &v)
+{
+ char c;
+
+ S::readChars (in, &c, 1);
+ v = !!c;
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, char &v)
+{
+ S::readChars (in, &v, 1);
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, signed char &v)
+{
+ readSignedChars<S> (in, &v, 1);
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, unsigned char &v)
+{
+ readUnsignedChars<S> (in, &v, 1);
+}
+
+
+template <class S, class T>
+void
+read (T &in, signed short &v)
+{
+ signed char b[2];
+
+ readSignedChars<S> (in, b, 2);
+
+ v = (b[0] & 0x00ff) |
+ (b[1] << 8);
+}
+
+
+template <class S, class T>
+void
+read (T &in, unsigned short &v)
+{
+ unsigned char b[2];
+
+ readUnsignedChars<S> (in, b, 2);
+
+ v = (b[0] & 0x00ff) |
+ (b[1] << 8);
+}
+
+
+template <class S, class T>
+void
+read (T &in, signed int &v)
+{
+ signed char b[4];
+
+ readSignedChars<S> (in, b, 4);
+
+ v = (b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ (b[3] << 24);
+}
+
+
+template <class S, class T>
+void
+read (T &in, unsigned int &v)
+{
+ unsigned char b[4];
+
+ readUnsignedChars<S> (in, b, 4);
+
+ v = (b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ (b[3] << 24);
+}
+
+
+template <class S, class T>
+void
+read (T &in, signed long &v)
+{
+ signed char b[8];
+
+ readSignedChars<S> (in, b, 8);
+
+ #if LONG_MAX == 2147483647
+
+ v = (b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ (b[3] << 24);
+
+ if (( b[4] || b[5] || b[6] || b[7]) &&
+ (~b[4] || ~b[5] || ~b[6] || ~b[7]))
+ {
+ throw Iex::OverflowExc ("Long int overflow - read a large "
+ "64-bit integer in a 32-bit process.");
+ }
+
+ #elif LONG_MAX == 9223372036854775807L
+
+ v = ((long) b[0] & 0x00000000000000ff) |
+ (((long) b[1] << 8) & 0x000000000000ff00) |
+ (((long) b[2] << 16) & 0x0000000000ff0000) |
+ (((long) b[3] << 24) & 0x00000000ff000000) |
+ (((long) b[4] << 32) & 0x000000ff00000000) |
+ (((long) b[5] << 40) & 0x0000ff0000000000) |
+ (((long) b[6] << 48) & 0x00ff000000000000) |
+ ((long) b[7] << 56);
+
+ #else
+
+ #error read<T> (T &in, signed long &v) not implemented
+
+ #endif
+}
+
+
+template <class S, class T>
+void
+read (T &in, unsigned long &v)
+{
+ unsigned char b[8];
+
+ readUnsignedChars<S> (in, b, 8);
+
+ #if ULONG_MAX == 4294967295U
+
+ v = (b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ (b[3] << 24);
+
+ if (b[4] || b[5] || b[6] || b[7])
+ {
+ throw Iex::OverflowExc ("Long int overflow - read a large "
+ "64-bit integer in a 32-bit process.");
+ }
+
+ #elif ULONG_MAX == 18446744073709551615LU
+
+ v = ((unsigned long) b[0] & 0x00000000000000ff) |
+ (((unsigned long) b[1] << 8) & 0x000000000000ff00) |
+ (((unsigned long) b[2] << 16) & 0x0000000000ff0000) |
+ (((unsigned long) b[3] << 24) & 0x00000000ff000000) |
+ (((unsigned long) b[4] << 32) & 0x000000ff00000000) |
+ (((unsigned long) b[5] << 40) & 0x0000ff0000000000) |
+ (((unsigned long) b[6] << 48) & 0x00ff000000000000) |
+ ((unsigned long) b[7] << 56);
+
+ #else
+
+ #error read<T> (T &in, unsigned long &v) not implemented
+
+ #endif
+}
+
+
+#if ULONG_MAX != 18446744073709551615LU
+
+ template <class S, class T>
+ void
+ read (T &in, Int64 &v)
+ {
+ unsigned char b[8];
+
+ readUnsignedChars<S> (in, b, 8);
+
+ v = ((Int64) b[0] & 0x00000000000000ffLL) |
+ (((Int64) b[1] << 8) & 0x000000000000ff00LL) |
+ (((Int64) b[2] << 16) & 0x0000000000ff0000LL) |
+ (((Int64) b[3] << 24) & 0x00000000ff000000LL) |
+ (((Int64) b[4] << 32) & 0x000000ff00000000LL) |
+ (((Int64) b[5] << 40) & 0x0000ff0000000000LL) |
+ (((Int64) b[6] << 48) & 0x00ff000000000000LL) |
+ ((Int64) b[7] << 56);
+ }
+
+#endif
+
+
+template <class S, class T>
+void
+read (T &in, float &v)
+{
+ unsigned char b[4];
+
+ readUnsignedChars<S> (in, b, 4);
+
+ union {unsigned int i; float f;} u;
+
+ u.i = (b[0] & 0x000000ff) |
+ ((b[1] << 8) & 0x0000ff00) |
+ ((b[2] << 16) & 0x00ff0000) |
+ (b[3] << 24);
+
+ v = u.f;
+}
+
+
+template <class S, class T>
+void
+read (T &in, double &v)
+{
+ unsigned char b[8];
+
+ readUnsignedChars<S> (in, b, 8);
+
+ union {Int64 i; double d;} u;
+
+ u.i = ((Int64) b[0] & 0x00000000000000ffULL) |
+ (((Int64) b[1] << 8) & 0x000000000000ff00ULL) |
+ (((Int64) b[2] << 16) & 0x0000000000ff0000ULL) |
+ (((Int64) b[3] << 24) & 0x00000000ff000000ULL) |
+ (((Int64) b[4] << 32) & 0x000000ff00000000ULL) |
+ (((Int64) b[5] << 40) & 0x0000ff0000000000ULL) |
+ (((Int64) b[6] << 48) & 0x00ff000000000000ULL) |
+ ((Int64) b[7] << 56);
+
+ v = u.d;
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, half &v)
+{
+ unsigned char b[2];
+
+ readUnsignedChars<S> (in, b, 2);
+
+ v.setBits ((b[0] & 0x00ff) | (b[1] << 8));
+}
+
+
+template <class S, class T>
+inline void
+read (T &in, char v[], int n) // fixed-size char array
+{
+ S::readChars (in, v, n);
+}
+
+
+template <class S, class T>
+void
+read (T &in, int n, char v[]) // zero-terminated string
+{
+ while (n >= 0)
+ {
+ S::readChars (in, v, 1);
+
+ if (*v == 0)
+ break;
+
+ --n;
+ ++v;
+ }
+}
+
+
+template <class S, class T>
+void
+skip (T &in, int n) // skip n padding bytes
+{
+ char c[1024];
+
+ while (n >= (int) sizeof (c))
+ {
+ if (!S::readChars (in, c, sizeof (c)))
+ return;
+
+ n -= sizeof (c);
+ }
+
+ if (n >= 1)
+ S::readChars (in, c, n);
+}
+
+
+template <> inline int size <bool> () {return 1;}
+template <> inline int size <char> () {return 1;}
+template <> inline int size <signed char> () {return 1;}
+template <> inline int size <unsigned char> () {return 1;}
+template <> inline int size <signed short> () {return 2;}
+template <> inline int size <unsigned short> () {return 2;}
+template <> inline int size <signed int> () {return 4;}
+template <> inline int size <unsigned int> () {return 4;}
+template <> inline int size <signed long> () {return 8;}
+template <> inline int size <unsigned long> () {return 8;}
+template <> inline int size <float> () {return 4;}
+template <> inline int size <double> () {return 8;}
+template <> inline int size <half> () {return 2;}
+
+
+} // namespace Xdr
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/ImfZipCompressor.cpp b/Source/OpenEXR/IlmImf/ImfZipCompressor.cpp
new file mode 100644
index 0000000..0d98096
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfZipCompressor.cpp
@@ -0,0 +1,230 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//-----------------------------------------------------------------------------
+//
+// class ZipCompressor
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfZipCompressor.h>
+#include "Iex.h"
+#include <zlib.h>
+
+namespace Imf {
+
+
+ZipCompressor::ZipCompressor
+ (const Header &hdr,
+ int maxScanLineSize,
+ int numScanLines)
+:
+ Compressor (hdr),
+ _maxScanLineSize (maxScanLineSize),
+ _numScanLines (numScanLines),
+ _tmpBuffer (0),
+ _outBuffer (0)
+{
+ _tmpBuffer =
+ new char [maxScanLineSize * numScanLines];
+
+ _outBuffer =
+ new char [int (ceil (maxScanLineSize * numScanLines * 1.01)) + 100];
+}
+
+
+ZipCompressor::~ZipCompressor ()
+{
+ delete [] _tmpBuffer;
+ delete [] _outBuffer;
+}
+
+
+int
+ZipCompressor::numScanLines () const
+{
+ return _numScanLines;
+}
+
+
+int
+ZipCompressor::compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ //
+ // Special case ­- empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Reorder the pixel data.
+ //
+
+ {
+ char *t1 = _tmpBuffer;
+ char *t2 = _tmpBuffer + (inSize + 1) / 2;
+ const char *stop = inPtr + inSize;
+
+ while (true)
+ {
+ if (inPtr < stop)
+ *(t1++) = *(inPtr++);
+ else
+ break;
+
+ if (inPtr < stop)
+ *(t2++) = *(inPtr++);
+ else
+ break;
+ }
+ }
+
+ //
+ // Predictor.
+ //
+
+ {
+ unsigned char *t = (unsigned char *) _tmpBuffer + 1;
+ unsigned char *stop = (unsigned char *) _tmpBuffer + inSize;
+ int p = t[-1];
+
+ while (t < stop)
+ {
+ int d = int (t[0]) - p + (128 + 256);
+ p = t[0];
+ t[0] = d;
+ ++t;
+ }
+ }
+
+ //
+ // Compress the data using zlib
+ //
+
+ uLongf outSize = int(ceil(inSize * 1.01)) + 100;
+
+ if (Z_OK != ::compress ((Bytef *)_outBuffer, &outSize,
+ (const Bytef *) _tmpBuffer, inSize))
+ {
+ throw Iex::BaseExc ("Data compression (zlib) failed.");
+ }
+
+ outPtr = _outBuffer;
+ return outSize;
+}
+
+
+int
+ZipCompressor::uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr)
+{
+ //
+ // Special case ­- empty input buffer
+ //
+
+ if (inSize == 0)
+ {
+ outPtr = _outBuffer;
+ return 0;
+ }
+
+ //
+ // Decompress the data using zlib
+ //
+
+ uLongf outSize = _maxScanLineSize * _numScanLines;
+
+ if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer, &outSize,
+ (const Bytef *) inPtr, inSize))
+ {
+ throw Iex::InputExc ("Data decompression (zlib) failed.");
+ }
+
+ //
+ // Predictor.
+ //
+
+ {
+ unsigned char *t = (unsigned char *) _tmpBuffer + 1;
+ unsigned char *stop = (unsigned char *) _tmpBuffer + outSize;
+
+ while (t < stop)
+ {
+ int d = int (t[-1]) + int (t[0]) - 128;
+ t[0] = d;
+ ++t;
+ }
+ }
+
+ //
+ // Reorder the pixel data.
+ //
+
+ {
+ const char *t1 = _tmpBuffer;
+ const char *t2 = _tmpBuffer + (outSize + 1) / 2;
+ char *s = _outBuffer;
+ char *stop = s + outSize;
+
+ while (true)
+ {
+ if (s < stop)
+ *(s++) = *(t1++);
+ else
+ break;
+
+ if (s < stop)
+ *(s++) = *(t2++);
+ else
+ break;
+ }
+ }
+
+ outPtr = _outBuffer;
+ return outSize;
+}
+
+
+} // namespace Imf
diff --git a/Source/OpenEXR/IlmImf/ImfZipCompressor.h b/Source/OpenEXR/IlmImf/ImfZipCompressor.h
new file mode 100644
index 0000000..f4de96b
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/ImfZipCompressor.h
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMF_ZIP_COMPRESSOR_H
+#define INCLUDED_IMF_ZIP_COMPRESSOR_H
+
+//-----------------------------------------------------------------------------
+//
+// class ZipCompressor -- performs zlib-style compression
+//
+//-----------------------------------------------------------------------------
+
+#include <ImfCompressor.h>
+
+namespace Imf {
+
+
+class ZipCompressor: public Compressor
+{
+ public:
+
+ ZipCompressor (const Header &hdr, int maxScanLineSize, int numScanLines);
+ virtual ~ZipCompressor ();
+
+ virtual int numScanLines () const;
+
+ virtual int compress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+
+ virtual int uncompress (const char *inPtr,
+ int inSize,
+ int minY,
+ const char *&outPtr);
+ private:
+
+ int _maxScanLineSize;
+ int _numScanLines;
+ char * _tmpBuffer;
+ char * _outBuffer;
+};
+
+
+} // namespace Imf
+
+#endif
diff --git a/Source/OpenEXR/IlmImf/Makefile.am b/Source/OpenEXR/IlmImf/Makefile.am
new file mode 100644
index 0000000..5e2f742
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/Makefile.am
@@ -0,0 +1,121 @@
+## Process this file with automake to produce Makefile.in
+
+lib_LTLIBRARIES = libIlmImf.la
+
+libIlmImf_la_SOURCES = ImfAttribute.cpp ImfBoxAttribute.cpp ImfCRgbaFile.cpp \
+ ImfChannelList.cpp ImfChannelListAttribute.cpp \
+ ImfFloatAttribute.cpp ImfFrameBuffer.cpp \
+ ImfHeader.cpp ImfIO.cpp ImfInputFile.cpp \
+ ImfIntAttribute.cpp ImfLineOrderAttribute.cpp \
+ ImfMatrixAttribute.cpp ImfOpaqueAttribute.cpp \
+ ImfOutputFile.cpp ImfRgbaFile.cpp \
+ ImfStringAttribute.cpp ImfVecAttribute.cpp ImfHuf.cpp \
+ ImfThreading.cpp \
+ ImfWav.cpp ImfLut.cpp ImfCompressor.cpp \
+ ImfRleCompressor.cpp ImfZipCompressor.cpp \
+ ImfPizCompressor.cpp ImfB44Compressor.cpp ImfMisc.cpp \
+ ImfCompressionAttribute.cpp ImfDoubleAttribute.cpp \
+ ImfAttribute.h ImfBoxAttribute.h \
+ ImfCRgbaFile.h ImfChannelList.h \
+ ImfChannelListAttribute.h \
+ ImfCompressionAttribute.h \
+ ImfDoubleAttribute.h ImfFloatAttribute.h \
+ ImfFrameBuffer.h ImfHeader.h ImfIO.h \
+ ImfInputFile.h ImfIntAttribute.h \
+ ImfLineOrderAttribute.h ImfMatrixAttribute.h \
+ ImfOpaqueAttribute.h ImfOutputFile.h \
+ ImfRgbaFile.h ImfStringAttribute.h \
+ ImfVecAttribute.h ImfHuf.h ImfWav.h ImfLut.h \
+ ImfArray.h ImfCompression.h ImfLineOrder.h \
+ ImfName.h ImfPixelType.h ImfVersion.h ImfXdr.h \
+ ImfCompressor.h ImfRleCompressor.h ImfZipCompressor.h \
+ ImfPizCompressor.h ImfMisc.h ImfAutoArray.h \
+ ImfConvert.cpp ImfConvert.h ImfPreviewImage.cpp \
+ ImfPreviewImage.h ImfPreviewImageAttribute.cpp \
+ ImfPreviewImageAttribute.h ImfVersion.cpp \
+ ImfChromaticities.cpp ImfChromaticities.h \
+ ImfChromaticitiesAttribute.cpp \
+ ImfChromaticitiesAttribute.h \
+ ImfKeyCode.cpp ImfKeyCode.h \
+ ImfKeyCodeAttribute.cpp ImfKeyCodeAttribute.h \
+ ImfTimeCode.cpp ImfTimeCode.h \
+ ImfTimeCodeAttribute.cpp ImfTimeCodeAttribute.h \
+ ImfRational.cpp ImfRational.h \
+ ImfRationalAttribute.cpp ImfRationalAttribute.h \
+ ImfFramesPerSecond.cpp ImfFramesPerSecond.h \
+ ImfStandardAttributes.cpp ImfStandardAttributes.h \
+ ImfStdIO.cpp ImfStdIO.h ImfEnvmap.cpp ImfEnvmap.h \
+ ImfEnvmapAttribute.cpp ImfEnvmapAttribute.h \
+ ImfInt64.h ImfRgba.h ImfScanLineInputFile.cpp \
+ ImfScanLineInputFile.h ImfTiledInputFile.cpp \
+ ImfTiledMisc.cpp ImfTiledOutputFile.cpp \
+ ImfTiledRgbaFile.cpp ImfTileDescriptionAttribute.cpp \
+ ImfTileOffsets.cpp ImfTileDescription.h \
+ ImfTileDescriptionAttribute.h ImfTileOffsets.h \
+ ImfTiledInputFile.h ImfTiledMisc.h \
+ ImfTiledOutputFile.h ImfTiledRgbaFile.h \
+ ImfRgbaYca.cpp ImfRgbaYca.h \
+ ImfPxr24Compressor.cpp ImfPxr24Compressor.h \
+ ImfTestFile.cpp ImfTestFile.h ImfThreading.h
+
+libIlmImf_la_LDFLAGS = @ILMBASE_LDFLAGS@ -version-info @LIBTOOL_VERSION@ \
+ -no-undefined
+
+libIlmImf_la_LIBADD = -lz @ILMBASE_LIBS@
+
+libIlmImfincludedir = $(includedir)/OpenEXR
+
+libIlmImfinclude_HEADERS = ImfAttribute.h ImfBoxAttribute.h \
+ ImfCRgbaFile.h ImfChannelList.h \
+ ImfChannelListAttribute.h \
+ ImfCompressionAttribute.h \
+ ImfDoubleAttribute.h ImfFloatAttribute.h \
+ ImfFrameBuffer.h ImfHeader.h ImfIO.h \
+ ImfInputFile.h ImfIntAttribute.h \
+ ImfLineOrderAttribute.h ImfMatrixAttribute.h \
+ ImfOpaqueAttribute.h ImfOutputFile.h \
+ ImfRgbaFile.h ImfStringAttribute.h \
+ ImfVecAttribute.h ImfHuf.h ImfWav.h ImfLut.h \
+ ImfArray.h ImfCompression.h ImfLineOrder.h \
+ ImfName.h ImfPixelType.h ImfVersion.h ImfXdr.h \
+ ImfConvert.h ImfPreviewImage.h \
+ ImfPreviewImageAttribute.h ImfChromaticities.h \
+ ImfChromaticitiesAttribute.h \
+ ImfKeyCode.h ImfKeyCodeAttribute.h \
+ ImfTimeCode.h ImfTimeCodeAttribute.h \
+ ImfRational.h ImfRationalAttribute.h \
+ ImfFramesPerSecond.h \
+ ImfStandardAttributes.h \
+ ImfEnvmap.h \
+ ImfEnvmapAttribute.h \
+ ImfInt64.h ImfRgba.h \
+ ImfTileDescription.h \
+ ImfTileDescriptionAttribute.h \
+ ImfTiledInputFile.h \
+ ImfTiledOutputFile.h ImfTiledRgbaFile.h \
+ ImfRgbaYca.h \
+ ImfTestFile.h ImfThreading.h \
+ ImfB44Compressor.h
+
+noinst_HEADERS = ImfCompressor.h ImfRleCompressor.h ImfZipCompressor.h \
+ ImfPizCompressor.h ImfMisc.h ImfAutoArray.h ImfTiledMisc.h \
+ ImfTileOffsets.h ImfScanLineInputFile.h ImfPxr24Compressor.h
+
+EXTRA_DIST = $(noinst_HEADERS) b44ExpLogTable.cpp b44ExpLogTable.h
+
+
+INCLUDES = @ILMBASE_CXXFLAGS@ \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/config
+
+CLEANFILES = b44ExpLogTable b44ExpLogTable.h
+
+b44ExpLogTable_SOURCES = b44ExpLogTable.cpp
+b44ExpLogTable_LDADD = @ILMBASE_LDFLAGS@ @ILMBASE_LIBS@
+
+b44ExpLogTable.h: b44ExpLogTable
+ ./b44ExpLogTable > b44ExpLogTable.h
+
+BUILT_SOURCES = b44ExpLogTable.h
+
+noinst_PROGRAMS = b44ExpLogTable
diff --git a/Source/OpenEXR/IlmImf/Makefile.in b/Source/OpenEXR/IlmImf/Makefile.in
new file mode 100644
index 0000000..5b2a80c
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/Makefile.in
@@ -0,0 +1,708 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+SOURCES = $(libIlmImf_la_SOURCES) $(b44ExpLogTable_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+noinst_PROGRAMS = b44ExpLogTable$(EXEEXT)
+subdir = IlmImf
+DIST_COMMON = $(libIlmImfinclude_HEADERS) $(noinst_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compilelinkrun.m4 \
+ $(top_srcdir)/m4/path.pkgconfig.m4 $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/OpenEXRConfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libIlmImfincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libIlmImf_la_DEPENDENCIES =
+am_libIlmImf_la_OBJECTS = ImfAttribute.lo ImfBoxAttribute.lo \
+ ImfCRgbaFile.lo ImfChannelList.lo ImfChannelListAttribute.lo \
+ ImfFloatAttribute.lo ImfFrameBuffer.lo ImfHeader.lo ImfIO.lo \
+ ImfInputFile.lo ImfIntAttribute.lo ImfLineOrderAttribute.lo \
+ ImfMatrixAttribute.lo ImfOpaqueAttribute.lo ImfOutputFile.lo \
+ ImfRgbaFile.lo ImfStringAttribute.lo ImfVecAttribute.lo \
+ ImfHuf.lo ImfThreading.lo ImfWav.lo ImfLut.lo ImfCompressor.lo \
+ ImfRleCompressor.lo ImfZipCompressor.lo ImfPizCompressor.lo \
+ ImfB44Compressor.lo ImfMisc.lo ImfCompressionAttribute.lo \
+ ImfDoubleAttribute.lo ImfConvert.lo ImfPreviewImage.lo \
+ ImfPreviewImageAttribute.lo ImfVersion.lo ImfChromaticities.lo \
+ ImfChromaticitiesAttribute.lo ImfKeyCode.lo \
+ ImfKeyCodeAttribute.lo ImfTimeCode.lo ImfTimeCodeAttribute.lo \
+ ImfRational.lo ImfRationalAttribute.lo ImfFramesPerSecond.lo \
+ ImfStandardAttributes.lo ImfStdIO.lo ImfEnvmap.lo \
+ ImfEnvmapAttribute.lo ImfScanLineInputFile.lo \
+ ImfTiledInputFile.lo ImfTiledMisc.lo ImfTiledOutputFile.lo \
+ ImfTiledRgbaFile.lo ImfTileDescriptionAttribute.lo \
+ ImfTileOffsets.lo ImfRgbaYca.lo ImfPxr24Compressor.lo \
+ ImfTestFile.lo
+libIlmImf_la_OBJECTS = $(am_libIlmImf_la_OBJECTS)
+PROGRAMS = $(noinst_PROGRAMS)
+am_b44ExpLogTable_OBJECTS = b44ExpLogTable.$(OBJEXT)
+b44ExpLogTable_OBJECTS = $(am_b44ExpLogTable_OBJECTS)
+b44ExpLogTable_DEPENDENCIES =
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libIlmImf_la_SOURCES) $(b44ExpLogTable_SOURCES)
+DIST_SOURCES = $(libIlmImf_la_SOURCES) $(b44ExpLogTable_SOURCES)
+libIlmImfincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libIlmImfinclude_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CXXFLAGS = @AM_CXXFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_IMFEXAMPLES_FALSE = @BUILD_IMFEXAMPLES_FALSE@
+BUILD_IMFEXAMPLES_TRUE = @BUILD_IMFEXAMPLES_TRUE@
+BUILD_IMFFUZZTEST_FALSE = @BUILD_IMFFUZZTEST_FALSE@
+BUILD_IMFFUZZTEST_TRUE = @BUILD_IMFFUZZTEST_TRUE@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+ILMBASE_CXXFLAGS = @ILMBASE_CXXFLAGS@
+ILMBASE_LDFLAGS = @ILMBASE_LDFLAGS@
+ILMBASE_LIBS = @ILMBASE_LIBS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION = @LIBTOOL_VERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+OPENEXR_VERSION = @OPENEXR_VERSION@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+acx_pthread_config = @acx_pthread_config@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+lib_LTLIBRARIES = libIlmImf.la
+libIlmImf_la_SOURCES = ImfAttribute.cpp ImfBoxAttribute.cpp ImfCRgbaFile.cpp \
+ ImfChannelList.cpp ImfChannelListAttribute.cpp \
+ ImfFloatAttribute.cpp ImfFrameBuffer.cpp \
+ ImfHeader.cpp ImfIO.cpp ImfInputFile.cpp \
+ ImfIntAttribute.cpp ImfLineOrderAttribute.cpp \
+ ImfMatrixAttribute.cpp ImfOpaqueAttribute.cpp \
+ ImfOutputFile.cpp ImfRgbaFile.cpp \
+ ImfStringAttribute.cpp ImfVecAttribute.cpp ImfHuf.cpp \
+ ImfThreading.cpp \
+ ImfWav.cpp ImfLut.cpp ImfCompressor.cpp \
+ ImfRleCompressor.cpp ImfZipCompressor.cpp \
+ ImfPizCompressor.cpp ImfB44Compressor.cpp ImfMisc.cpp \
+ ImfCompressionAttribute.cpp ImfDoubleAttribute.cpp \
+ ImfAttribute.h ImfBoxAttribute.h \
+ ImfCRgbaFile.h ImfChannelList.h \
+ ImfChannelListAttribute.h \
+ ImfCompressionAttribute.h \
+ ImfDoubleAttribute.h ImfFloatAttribute.h \
+ ImfFrameBuffer.h ImfHeader.h ImfIO.h \
+ ImfInputFile.h ImfIntAttribute.h \
+ ImfLineOrderAttribute.h ImfMatrixAttribute.h \
+ ImfOpaqueAttribute.h ImfOutputFile.h \
+ ImfRgbaFile.h ImfStringAttribute.h \
+ ImfVecAttribute.h ImfHuf.h ImfWav.h ImfLut.h \
+ ImfArray.h ImfCompression.h ImfLineOrder.h \
+ ImfName.h ImfPixelType.h ImfVersion.h ImfXdr.h \
+ ImfCompressor.h ImfRleCompressor.h ImfZipCompressor.h \
+ ImfPizCompressor.h ImfMisc.h ImfAutoArray.h \
+ ImfConvert.cpp ImfConvert.h ImfPreviewImage.cpp \
+ ImfPreviewImage.h ImfPreviewImageAttribute.cpp \
+ ImfPreviewImageAttribute.h ImfVersion.cpp \
+ ImfChromaticities.cpp ImfChromaticities.h \
+ ImfChromaticitiesAttribute.cpp \
+ ImfChromaticitiesAttribute.h \
+ ImfKeyCode.cpp ImfKeyCode.h \
+ ImfKeyCodeAttribute.cpp ImfKeyCodeAttribute.h \
+ ImfTimeCode.cpp ImfTimeCode.h \
+ ImfTimeCodeAttribute.cpp ImfTimeCodeAttribute.h \
+ ImfRational.cpp ImfRational.h \
+ ImfRationalAttribute.cpp ImfRationalAttribute.h \
+ ImfFramesPerSecond.cpp ImfFramesPerSecond.h \
+ ImfStandardAttributes.cpp ImfStandardAttributes.h \
+ ImfStdIO.cpp ImfStdIO.h ImfEnvmap.cpp ImfEnvmap.h \
+ ImfEnvmapAttribute.cpp ImfEnvmapAttribute.h \
+ ImfInt64.h ImfRgba.h ImfScanLineInputFile.cpp \
+ ImfScanLineInputFile.h ImfTiledInputFile.cpp \
+ ImfTiledMisc.cpp ImfTiledOutputFile.cpp \
+ ImfTiledRgbaFile.cpp ImfTileDescriptionAttribute.cpp \
+ ImfTileOffsets.cpp ImfTileDescription.h \
+ ImfTileDescriptionAttribute.h ImfTileOffsets.h \
+ ImfTiledInputFile.h ImfTiledMisc.h \
+ ImfTiledOutputFile.h ImfTiledRgbaFile.h \
+ ImfRgbaYca.cpp ImfRgbaYca.h \
+ ImfPxr24Compressor.cpp ImfPxr24Compressor.h \
+ ImfTestFile.cpp ImfTestFile.h ImfThreading.h
+
+libIlmImf_la_LDFLAGS = @ILMBASE_LDFLAGS@ -version-info @LIBTOOL_VERSION@ \
+ -no-undefined
+
+libIlmImf_la_LIBADD = -lz @ILMBASE_LIBS@
+libIlmImfincludedir = $(includedir)/OpenEXR
+libIlmImfinclude_HEADERS = ImfAttribute.h ImfBoxAttribute.h \
+ ImfCRgbaFile.h ImfChannelList.h \
+ ImfChannelListAttribute.h \
+ ImfCompressionAttribute.h \
+ ImfDoubleAttribute.h ImfFloatAttribute.h \
+ ImfFrameBuffer.h ImfHeader.h ImfIO.h \
+ ImfInputFile.h ImfIntAttribute.h \
+ ImfLineOrderAttribute.h ImfMatrixAttribute.h \
+ ImfOpaqueAttribute.h ImfOutputFile.h \
+ ImfRgbaFile.h ImfStringAttribute.h \
+ ImfVecAttribute.h ImfHuf.h ImfWav.h ImfLut.h \
+ ImfArray.h ImfCompression.h ImfLineOrder.h \
+ ImfName.h ImfPixelType.h ImfVersion.h ImfXdr.h \
+ ImfConvert.h ImfPreviewImage.h \
+ ImfPreviewImageAttribute.h ImfChromaticities.h \
+ ImfChromaticitiesAttribute.h \
+ ImfKeyCode.h ImfKeyCodeAttribute.h \
+ ImfTimeCode.h ImfTimeCodeAttribute.h \
+ ImfRational.h ImfRationalAttribute.h \
+ ImfFramesPerSecond.h \
+ ImfStandardAttributes.h \
+ ImfEnvmap.h \
+ ImfEnvmapAttribute.h \
+ ImfInt64.h ImfRgba.h \
+ ImfTileDescription.h \
+ ImfTileDescriptionAttribute.h \
+ ImfTiledInputFile.h \
+ ImfTiledOutputFile.h ImfTiledRgbaFile.h \
+ ImfRgbaYca.h \
+ ImfTestFile.h ImfThreading.h \
+ ImfB44Compressor.h
+
+noinst_HEADERS = ImfCompressor.h ImfRleCompressor.h ImfZipCompressor.h \
+ ImfPizCompressor.h ImfMisc.h ImfAutoArray.h ImfTiledMisc.h \
+ ImfTileOffsets.h ImfScanLineInputFile.h ImfPxr24Compressor.h
+
+EXTRA_DIST = $(noinst_HEADERS) b44ExpLogTable.cpp b44ExpLogTable.h
+INCLUDES = @ILMBASE_CXXFLAGS@ \
+ -I$(top_builddir) \
+ -I$(top_srcdir)/config
+
+CLEANFILES = b44ExpLogTable b44ExpLogTable.h
+b44ExpLogTable_SOURCES = b44ExpLogTable.cpp
+b44ExpLogTable_LDADD = @ILMBASE_LDFLAGS@ @ILMBASE_LIBS@
+BUILT_SOURCES = b44ExpLogTable.h
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu IlmImf/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu IlmImf/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libIlmImf.la: $(libIlmImf_la_OBJECTS) $(libIlmImf_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libIlmImf_la_LDFLAGS) $(libIlmImf_la_OBJECTS) $(libIlmImf_la_LIBADD) $(LIBS)
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+b44ExpLogTable$(EXEEXT): $(b44ExpLogTable_OBJECTS) $(b44ExpLogTable_DEPENDENCIES)
+ @rm -f b44ExpLogTable$(EXEEXT)
+ $(CXXLINK) $(b44ExpLogTable_LDFLAGS) $(b44ExpLogTable_OBJECTS) $(b44ExpLogTable_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfB44Compressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfBoxAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfCRgbaFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfChannelList.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfChannelListAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfChromaticities.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfChromaticitiesAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfCompressionAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfCompressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfConvert.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfDoubleAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfEnvmap.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfEnvmapAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfFloatAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfFrameBuffer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfFramesPerSecond.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfHeader.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfHuf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfIO.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfInputFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfIntAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfKeyCode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfKeyCodeAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfLineOrderAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfLut.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfMatrixAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfMisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfOpaqueAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfOutputFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfPizCompressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfPreviewImage.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfPreviewImageAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfPxr24Compressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfRational.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfRationalAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfRgbaFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfRgbaYca.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfRleCompressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfScanLineInputFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfStandardAttributes.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfStdIO.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfStringAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTestFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfThreading.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTileDescriptionAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTileOffsets.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTiledInputFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTiledMisc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTiledOutputFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTiledRgbaFile.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTimeCode.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfTimeCodeAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfVecAttribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfVersion.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfWav.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImfZipCompressor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/b44ExpLogTable.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libIlmImfincludeHEADERS: $(libIlmImfinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libIlmImfincludedir)" || $(mkdir_p) "$(DESTDIR)$(libIlmImfincludedir)"
+ @list='$(libIlmImfinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libIlmImfincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libIlmImfincludedir)/$$f'"; \
+ $(libIlmImfincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libIlmImfincludedir)/$$f"; \
+ done
+
+uninstall-libIlmImfincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libIlmImfinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libIlmImfincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libIlmImfincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libIlmImfincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libIlmImfincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libIlmImfincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \
+ distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-libIlmImfincludeHEADERS \
+ install-libLTLIBRARIES install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am \
+ uninstall-libIlmImfincludeHEADERS uninstall-libLTLIBRARIES
+
+
+b44ExpLogTable.h: b44ExpLogTable
+ ./b44ExpLogTable > b44ExpLogTable.h
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/OpenEXR/IlmImf/b44ExpLogTable.cpp b/Source/OpenEXR/IlmImf/b44ExpLogTable.cpp
new file mode 100644
index 0000000..24e35fb
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/b44ExpLogTable.cpp
@@ -0,0 +1,136 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+//
+// b44ExpLogTable
+//
+// A program to generate lookup tables for
+//
+// y = exp (x / 8)
+//
+// and
+// x = 8 * log (x);
+//
+// where x and y are 16-bit floating-point numbers
+//
+// The tables are used by class B44Compressor.
+//
+//---------------------------------------------------------------------------
+
+#include <half.h>
+#include <math.h>
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+//---------------------------------------------
+// Main - prints the half-to-float lookup table
+//---------------------------------------------
+
+int
+main ()
+{
+#ifndef HAVE_IOS_BASE
+ cout.setf (ios::hex, ios::basefield);
+#else
+ cout.setf (ios_base::hex, ios_base::basefield);
+#endif
+
+ cout << "//\n"
+ "// This is an automatically generated file.\n"
+ "// Do not edit.\n"
+ "//\n\n";
+
+ const int iMax = (1 << 16);
+
+ cout << "const unsigned short expTable[] =\n"
+ "{\n"
+ " ";
+
+ for (int i = 0; i < iMax; i++)
+ {
+ half h;
+ h.setBits (i);
+
+ if (!h.isFinite())
+ h = 0;
+ else if (h >= 8 * log (HALF_MAX))
+ h = HALF_MAX;
+ else
+ h = exp (h / 8);
+
+ cout << "0x" << setfill ('0') << setw (4) << h.bits() << ", ";
+
+ if (i % 8 == 7)
+ {
+ cout << "\n";
+
+ if (i < iMax - 1)
+ cout << " ";
+ }
+ }
+
+ cout << "};\n\n";
+
+ cout << "const unsigned short logTable[] =\n"
+ "{\n"
+ " ";
+
+ for (int i = 0; i < iMax; i++)
+ {
+ half h;
+ h.setBits (i);
+
+ if (!h.isFinite() || h < 0)
+ h = 0;
+ else
+ h = 8 * log (h);
+
+ cout << "0x" << setfill ('0') << setw (4) << h.bits() << ", ";
+
+ if (i % 8 == 7)
+ {
+ cout << "\n";
+
+ if (i < iMax - 1)
+ cout << " ";
+ }
+ }
+
+ cout << "};\n";
+
+ return 0;
+}
diff --git a/Source/OpenEXR/IlmImf/b44ExpLogTable.h b/Source/OpenEXR/IlmImf/b44ExpLogTable.h
new file mode 100644
index 0000000..c13d16c
--- /dev/null
+++ b/Source/OpenEXR/IlmImf/b44ExpLogTable.h
@@ -0,0 +1,16396 @@
+//
+// This is an automatically generated file.
+// Do not edit.
+//
+
+const unsigned short expTable[] =
+{
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01,
+ 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c01, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02,
+ 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c02, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03,
+ 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c03, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04,
+ 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c04, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05,
+ 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c05, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06, 0x3c06,
+ 0x3c06, 0x3c06, 0x3c06, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07, 0x3c07,
+ 0x3c07, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c08,
+ 0x3c08, 0x3c08, 0x3c08, 0x3c08, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09, 0x3c09,
+ 0x3c09, 0x3c09, 0x3c09, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a, 0x3c0a,
+ 0x3c0a, 0x3c0a, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b, 0x3c0b,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c,
+ 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0c, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d,
+ 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0d, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0e,
+ 0x3c0e, 0x3c0e, 0x3c0e, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f, 0x3c0f,
+ 0x3c0f, 0x3c0f, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10, 0x3c10,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11,
+ 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c11, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12,
+ 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c12, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13,
+ 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c13, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c14,
+ 0x3c14, 0x3c14, 0x3c14, 0x3c14, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15, 0x3c15,
+ 0x3c15, 0x3c15, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16, 0x3c16,
+ 0x3c16, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17,
+ 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c17, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18,
+ 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c18, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19,
+ 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c19, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1a,
+ 0x3c1a, 0x3c1a, 0x3c1a, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b, 0x3c1b,
+ 0x3c1b, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c, 0x3c1c,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d,
+ 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1d, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e,
+ 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1e, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f, 0x3c1f,
+ 0x3c1f, 0x3c1f, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20, 0x3c20,
+ 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21,
+ 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21,
+ 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21,
+ 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c21, 0x3c22,
+ 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22,
+ 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22,
+ 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22,
+ 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c22, 0x3c23, 0x3c23,
+ 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23,
+ 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23,
+ 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23,
+ 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c23, 0x3c24, 0x3c24, 0x3c24,
+ 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24,
+ 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24,
+ 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c24,
+ 0x3c24, 0x3c24, 0x3c24, 0x3c24, 0x3c25, 0x3c25, 0x3c25, 0x3c25,
+ 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25,
+ 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25,
+ 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25, 0x3c25,
+ 0x3c25, 0x3c25, 0x3c25, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26,
+ 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26,
+ 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26,
+ 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26, 0x3c26,
+ 0x3c26, 0x3c26, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27,
+ 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27,
+ 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27,
+ 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27, 0x3c27,
+ 0x3c27, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28,
+ 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28,
+ 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28,
+ 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28, 0x3c28,
+ 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29,
+ 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29,
+ 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29,
+ 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c29, 0x3c2a, 0x3c2a,
+ 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a,
+ 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a,
+ 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a,
+ 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2a, 0x3c2b, 0x3c2b, 0x3c2b,
+ 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b,
+ 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b,
+ 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b,
+ 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2b, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c,
+ 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c,
+ 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c,
+ 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c, 0x3c2c,
+ 0x3c2c, 0x3c2c, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d,
+ 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d,
+ 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d,
+ 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d, 0x3c2d,
+ 0x3c2d, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e,
+ 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e,
+ 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e,
+ 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e, 0x3c2e,
+ 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f,
+ 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f,
+ 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f,
+ 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c2f, 0x3c30, 0x3c30,
+ 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30,
+ 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30,
+ 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30,
+ 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c30, 0x3c31, 0x3c31, 0x3c31,
+ 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31,
+ 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31,
+ 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31, 0x3c31,
+ 0x3c31, 0x3c31, 0x3c31, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32,
+ 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32,
+ 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32,
+ 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32, 0x3c32,
+ 0x3c32, 0x3c32, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33,
+ 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33,
+ 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33,
+ 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33, 0x3c33,
+ 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34,
+ 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34,
+ 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34,
+ 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c34, 0x3c35,
+ 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35,
+ 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35,
+ 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35,
+ 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c35, 0x3c36, 0x3c36, 0x3c36,
+ 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36,
+ 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36,
+ 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c36,
+ 0x3c36, 0x3c36, 0x3c36, 0x3c36, 0x3c37, 0x3c37, 0x3c37, 0x3c37,
+ 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37,
+ 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37,
+ 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37, 0x3c37,
+ 0x3c37, 0x3c37, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38,
+ 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38,
+ 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38,
+ 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38, 0x3c38,
+ 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39,
+ 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39,
+ 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39,
+ 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c39, 0x3c3a,
+ 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a,
+ 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a,
+ 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a,
+ 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3a, 0x3c3b, 0x3c3b, 0x3c3b,
+ 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b,
+ 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b,
+ 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3b,
+ 0x3c3b, 0x3c3b, 0x3c3b, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
+ 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
+ 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
+ 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c,
+ 0x3c3c, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d,
+ 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d,
+ 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d,
+ 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d, 0x3c3d,
+ 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e,
+ 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e,
+ 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e,
+ 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3e, 0x3c3f, 0x3c3f,
+ 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f,
+ 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f,
+ 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f,
+ 0x3c3f, 0x3c3f, 0x3c3f, 0x3c3f, 0x3c40, 0x3c40, 0x3c40, 0x3c40,
+ 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40,
+ 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40,
+ 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40, 0x3c40,
+ 0x3c40, 0x3c40, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41,
+ 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41,
+ 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41,
+ 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41, 0x3c41,
+ 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42,
+ 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42,
+ 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c42, 0x3c43,
+ 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43,
+ 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c43, 0x3c44, 0x3c44,
+ 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c44,
+ 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c44, 0x3c45, 0x3c45, 0x3c45,
+ 0x3c45, 0x3c45, 0x3c45, 0x3c45, 0x3c45, 0x3c45, 0x3c45, 0x3c45,
+ 0x3c45, 0x3c45, 0x3c45, 0x3c45, 0x3c46, 0x3c46, 0x3c46, 0x3c46,
+ 0x3c46, 0x3c46, 0x3c46, 0x3c46, 0x3c46, 0x3c46, 0x3c46, 0x3c46,
+ 0x3c46, 0x3c46, 0x3c46, 0x3c47, 0x3c47, 0x3c47, 0x3c47, 0x3c47,
+ 0x3c47, 0x3c47, 0x3c47, 0x3c47, 0x3c47, 0x3c47, 0x3c47, 0x3c47,
+ 0x3c47, 0x3c47, 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48,
+ 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48, 0x3c48,
+ 0x3c48, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49,
+ 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49, 0x3c49,
+ 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a,
+ 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4a, 0x3c4b,
+ 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b,
+ 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4b, 0x3c4c, 0x3c4c,
+ 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c,
+ 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4c, 0x3c4d, 0x3c4d, 0x3c4d,
+ 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d,
+ 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4d, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e,
+ 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4e,
+ 0x3c4e, 0x3c4e, 0x3c4e, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f,
+ 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f, 0x3c4f,
+ 0x3c4f, 0x3c4f, 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50,
+ 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50, 0x3c50,
+ 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51,
+ 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c51, 0x3c52,
+ 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52,
+ 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c52, 0x3c53, 0x3c53,
+ 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c53,
+ 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c53, 0x3c54, 0x3c54, 0x3c54,
+ 0x3c54, 0x3c54, 0x3c54, 0x3c54, 0x3c54, 0x3c54, 0x3c54, 0x3c54,
+ 0x3c54, 0x3c54, 0x3c54, 0x3c54, 0x3c55, 0x3c55, 0x3c55, 0x3c55,
+ 0x3c55, 0x3c55, 0x3c55, 0x3c55, 0x3c55, 0x3c55, 0x3c55, 0x3c55,
+ 0x3c55, 0x3c55, 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56,
+ 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56, 0x3c56,
+ 0x3c56, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57,
+ 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57, 0x3c57,
+ 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58,
+ 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c58, 0x3c59,
+ 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c59,
+ 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c59, 0x3c5a, 0x3c5a, 0x3c5a,
+ 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a,
+ 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5a, 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b,
+ 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5b,
+ 0x3c5b, 0x3c5b, 0x3c5b, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c,
+ 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c, 0x3c5c,
+ 0x3c5c, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d,
+ 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d, 0x3c5d,
+ 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e,
+ 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5e, 0x3c5f,
+ 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f,
+ 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c5f, 0x3c60, 0x3c60, 0x3c60,
+ 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c60,
+ 0x3c60, 0x3c60, 0x3c60, 0x3c60, 0x3c61, 0x3c61, 0x3c61, 0x3c61,
+ 0x3c61, 0x3c61, 0x3c61, 0x3c61, 0x3c61, 0x3c61, 0x3c61, 0x3c61,
+ 0x3c61, 0x3c61, 0x3c61, 0x3c62, 0x3c62, 0x3c62, 0x3c62, 0x3c62,
+ 0x3c62, 0x3c62, 0x3c62, 0x3c62, 0x3c62, 0x3c62, 0x3c62, 0x3c62,
+ 0x3c62, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63,
+ 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63, 0x3c63,
+ 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64,
+ 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c64, 0x3c65, 0x3c65,
+ 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c65,
+ 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c65, 0x3c66, 0x3c66, 0x3c66,
+ 0x3c66, 0x3c66, 0x3c66, 0x3c66, 0x3c66, 0x3c66, 0x3c66, 0x3c66,
+ 0x3c66, 0x3c66, 0x3c66, 0x3c66, 0x3c67, 0x3c67, 0x3c67, 0x3c67,
+ 0x3c67, 0x3c67, 0x3c67, 0x3c67, 0x3c67, 0x3c67, 0x3c67, 0x3c67,
+ 0x3c67, 0x3c67, 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68,
+ 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68, 0x3c68,
+ 0x3c68, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69,
+ 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c69, 0x3c6a,
+ 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a,
+ 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6a, 0x3c6b, 0x3c6b,
+ 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b,
+ 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6b, 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c,
+ 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6c,
+ 0x3c6c, 0x3c6c, 0x3c6c, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d,
+ 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d, 0x3c6d,
+ 0x3c6d, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e,
+ 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6e, 0x3c6f,
+ 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f,
+ 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c6f, 0x3c70, 0x3c70,
+ 0x3c70, 0x3c70, 0x3c70, 0x3c70, 0x3c70, 0x3c70, 0x3c70, 0x3c70,
+ 0x3c70, 0x3c70, 0x3c70, 0x3c70, 0x3c71, 0x3c71, 0x3c71, 0x3c71,
+ 0x3c71, 0x3c71, 0x3c71, 0x3c71, 0x3c71, 0x3c71, 0x3c71, 0x3c71,
+ 0x3c71, 0x3c71, 0x3c71, 0x3c72, 0x3c72, 0x3c72, 0x3c72, 0x3c72,
+ 0x3c72, 0x3c72, 0x3c72, 0x3c72, 0x3c72, 0x3c72, 0x3c72, 0x3c72,
+ 0x3c72, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73,
+ 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73, 0x3c73,
+ 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74,
+ 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c74, 0x3c75, 0x3c75,
+ 0x3c75, 0x3c75, 0x3c75, 0x3c75, 0x3c75, 0x3c75, 0x3c75, 0x3c75,
+ 0x3c75, 0x3c75, 0x3c75, 0x3c75, 0x3c76, 0x3c76, 0x3c76, 0x3c76,
+ 0x3c76, 0x3c76, 0x3c76, 0x3c76, 0x3c76, 0x3c76, 0x3c76, 0x3c76,
+ 0x3c76, 0x3c76, 0x3c76, 0x3c77, 0x3c77, 0x3c77, 0x3c77, 0x3c77,
+ 0x3c77, 0x3c77, 0x3c77, 0x3c77, 0x3c77, 0x3c77, 0x3c77, 0x3c77,
+ 0x3c77, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78,
+ 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c78, 0x3c79,
+ 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79,
+ 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c79, 0x3c7a, 0x3c7a,
+ 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a,
+ 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7a, 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b,
+ 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b, 0x3c7b,
+ 0x3c7b, 0x3c7b, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c,
+ 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c, 0x3c7c,
+ 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d,
+ 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7d, 0x3c7e,
+ 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e,
+ 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7e, 0x3c7f, 0x3c7f, 0x3c7f,
+ 0x3c7f, 0x3c7f, 0x3c7f, 0x3c7f, 0x3c7f, 0x3c7f, 0x3c7f, 0x3c7f,
+ 0x3c7f, 0x3c7f, 0x3c7f, 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c80,
+ 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c80, 0x3c80,
+ 0x3c80, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81,
+ 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81, 0x3c81,
+ 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82,
+ 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c82, 0x3c83, 0x3c83,
+ 0x3c83, 0x3c83, 0x3c83, 0x3c83, 0x3c83, 0x3c83, 0x3c83, 0x3c83,
+ 0x3c83, 0x3c83, 0x3c83, 0x3c83, 0x3c84, 0x3c84, 0x3c84, 0x3c84,
+ 0x3c84, 0x3c84, 0x3c84, 0x3c84, 0x3c84, 0x3c84, 0x3c84, 0x3c84,
+ 0x3c84, 0x3c84, 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85,
+ 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85, 0x3c85,
+ 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86,
+ 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c86, 0x3c87, 0x3c87,
+ 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c87,
+ 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c87, 0x3c88, 0x3c88, 0x3c88,
+ 0x3c88, 0x3c88, 0x3c88, 0x3c88, 0x3c88, 0x3c88, 0x3c88, 0x3c88,
+ 0x3c88, 0x3c88, 0x3c89, 0x3c89, 0x3c89, 0x3c89, 0x3c89, 0x3c89,
+ 0x3c89, 0x3c8a, 0x3c8a, 0x3c8a, 0x3c8a, 0x3c8a, 0x3c8a, 0x3c8a,
+ 0x3c8b, 0x3c8b, 0x3c8b, 0x3c8b, 0x3c8b, 0x3c8b, 0x3c8b, 0x3c8c,
+ 0x3c8c, 0x3c8c, 0x3c8c, 0x3c8c, 0x3c8c, 0x3c8c, 0x3c8d, 0x3c8d,
+ 0x3c8d, 0x3c8d, 0x3c8d, 0x3c8d, 0x3c8d, 0x3c8e, 0x3c8e, 0x3c8e,
+ 0x3c8e, 0x3c8e, 0x3c8e, 0x3c8e, 0x3c8f, 0x3c8f, 0x3c8f, 0x3c8f,
+ 0x3c8f, 0x3c8f, 0x3c8f, 0x3c90, 0x3c90, 0x3c90, 0x3c90, 0x3c90,
+ 0x3c90, 0x3c90, 0x3c91, 0x3c91, 0x3c91, 0x3c91, 0x3c91, 0x3c91,
+ 0x3c91, 0x3c92, 0x3c92, 0x3c92, 0x3c92, 0x3c92, 0x3c92, 0x3c92,
+ 0x3c93, 0x3c93, 0x3c93, 0x3c93, 0x3c93, 0x3c93, 0x3c93, 0x3c94,
+ 0x3c94, 0x3c94, 0x3c94, 0x3c94, 0x3c94, 0x3c94, 0x3c95, 0x3c95,
+ 0x3c95, 0x3c95, 0x3c95, 0x3c95, 0x3c95, 0x3c96, 0x3c96, 0x3c96,
+ 0x3c96, 0x3c96, 0x3c96, 0x3c96, 0x3c97, 0x3c97, 0x3c97, 0x3c97,
+ 0x3c97, 0x3c97, 0x3c97, 0x3c98, 0x3c98, 0x3c98, 0x3c98, 0x3c98,
+ 0x3c98, 0x3c98, 0x3c99, 0x3c99, 0x3c99, 0x3c99, 0x3c99, 0x3c99,
+ 0x3c99, 0x3c9a, 0x3c9a, 0x3c9a, 0x3c9a, 0x3c9a, 0x3c9a, 0x3c9a,
+ 0x3c9b, 0x3c9b, 0x3c9b, 0x3c9b, 0x3c9b, 0x3c9b, 0x3c9b, 0x3c9c,
+ 0x3c9c, 0x3c9c, 0x3c9c, 0x3c9c, 0x3c9c, 0x3c9c, 0x3c9d, 0x3c9d,
+ 0x3c9d, 0x3c9d, 0x3c9d, 0x3c9d, 0x3c9d, 0x3c9e, 0x3c9e, 0x3c9e,
+ 0x3c9e, 0x3c9e, 0x3c9e, 0x3c9f, 0x3c9f, 0x3c9f, 0x3c9f, 0x3c9f,
+ 0x3c9f, 0x3c9f, 0x3ca0, 0x3ca0, 0x3ca0, 0x3ca0, 0x3ca0, 0x3ca0,
+ 0x3ca0, 0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1, 0x3ca1,
+ 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca2, 0x3ca3,
+ 0x3ca3, 0x3ca3, 0x3ca3, 0x3ca3, 0x3ca3, 0x3ca3, 0x3ca4, 0x3ca4,
+ 0x3ca4, 0x3ca4, 0x3ca4, 0x3ca4, 0x3ca4, 0x3ca5, 0x3ca5, 0x3ca5,
+ 0x3ca5, 0x3ca5, 0x3ca5, 0x3ca5, 0x3ca6, 0x3ca6, 0x3ca6, 0x3ca6,
+ 0x3ca6, 0x3ca6, 0x3ca6, 0x3ca7, 0x3ca7, 0x3ca7, 0x3ca7, 0x3ca7,
+ 0x3ca7, 0x3ca7, 0x3ca8, 0x3ca8, 0x3ca8, 0x3ca8, 0x3ca8, 0x3ca8,
+ 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x3ca9, 0x3caa,
+ 0x3caa, 0x3caa, 0x3caa, 0x3caa, 0x3caa, 0x3caa, 0x3cab, 0x3cab,
+ 0x3cab, 0x3cab, 0x3cab, 0x3cab, 0x3cab, 0x3cac, 0x3cac, 0x3cac,
+ 0x3cac, 0x3cac, 0x3cac, 0x3cac, 0x3cad, 0x3cad, 0x3cad, 0x3cad,
+ 0x3cad, 0x3cad, 0x3cad, 0x3cae, 0x3cae, 0x3cae, 0x3cae, 0x3cae,
+ 0x3cae, 0x3cae, 0x3caf, 0x3caf, 0x3caf, 0x3caf, 0x3caf, 0x3caf,
+ 0x3cb0, 0x3cb0, 0x3cb0, 0x3cb0, 0x3cb0, 0x3cb0, 0x3cb0, 0x3cb1,
+ 0x3cb1, 0x3cb1, 0x3cb1, 0x3cb1, 0x3cb1, 0x3cb1, 0x3cb2, 0x3cb2,
+ 0x3cb2, 0x3cb2, 0x3cb2, 0x3cb2, 0x3cb2, 0x3cb3, 0x3cb3, 0x3cb3,
+ 0x3cb3, 0x3cb3, 0x3cb3, 0x3cb3, 0x3cb4, 0x3cb4, 0x3cb4, 0x3cb4,
+ 0x3cb4, 0x3cb4, 0x3cb5, 0x3cb5, 0x3cb5, 0x3cb5, 0x3cb5, 0x3cb5,
+ 0x3cb5, 0x3cb6, 0x3cb6, 0x3cb6, 0x3cb6, 0x3cb6, 0x3cb6, 0x3cb6,
+ 0x3cb7, 0x3cb7, 0x3cb7, 0x3cb7, 0x3cb7, 0x3cb7, 0x3cb7, 0x3cb8,
+ 0x3cb8, 0x3cb8, 0x3cb8, 0x3cb8, 0x3cb8, 0x3cb8, 0x3cb9, 0x3cb9,
+ 0x3cb9, 0x3cb9, 0x3cb9, 0x3cb9, 0x3cba, 0x3cba, 0x3cba, 0x3cba,
+ 0x3cba, 0x3cba, 0x3cba, 0x3cbb, 0x3cbb, 0x3cbb, 0x3cbb, 0x3cbb,
+ 0x3cbb, 0x3cbb, 0x3cbc, 0x3cbc, 0x3cbc, 0x3cbc, 0x3cbc, 0x3cbc,
+ 0x3cbc, 0x3cbd, 0x3cbd, 0x3cbd, 0x3cbd, 0x3cbd, 0x3cbd, 0x3cbe,
+ 0x3cbe, 0x3cbe, 0x3cbe, 0x3cbe, 0x3cbe, 0x3cbe, 0x3cbf, 0x3cbf,
+ 0x3cbf, 0x3cbf, 0x3cbf, 0x3cbf, 0x3cbf, 0x3cc0, 0x3cc0, 0x3cc0,
+ 0x3cc0, 0x3cc0, 0x3cc0, 0x3cc0, 0x3cc1, 0x3cc1, 0x3cc1, 0x3cc1,
+ 0x3cc1, 0x3cc1, 0x3cc2, 0x3cc2, 0x3cc2, 0x3cc2, 0x3cc2, 0x3cc2,
+ 0x3cc2, 0x3cc3, 0x3cc3, 0x3cc3, 0x3cc3, 0x3cc3, 0x3cc3, 0x3cc3,
+ 0x3cc4, 0x3cc4, 0x3cc4, 0x3cc4, 0x3cc4, 0x3cc4, 0x3cc4, 0x3cc5,
+ 0x3cc5, 0x3cc5, 0x3cc5, 0x3cc5, 0x3cc5, 0x3cc6, 0x3cc6, 0x3cc6,
+ 0x3cc6, 0x3cc6, 0x3cc6, 0x3cc6, 0x3cc7, 0x3cc7, 0x3cc7, 0x3cc7,
+ 0x3cc7, 0x3cc7, 0x3cc7, 0x3cc8, 0x3cc8, 0x3cc8, 0x3cc8, 0x3cc8,
+ 0x3cc8, 0x3cc9, 0x3cc9, 0x3cc9, 0x3cc9, 0x3cc9, 0x3cc9, 0x3cc9,
+ 0x3cca, 0x3cca, 0x3cca, 0x3cca, 0x3cca, 0x3cca, 0x3cca, 0x3ccb,
+ 0x3ccb, 0x3ccb, 0x3ccb, 0x3ccb, 0x3ccb, 0x3ccc, 0x3ccc, 0x3ccc,
+ 0x3ccc, 0x3ccc, 0x3ccc, 0x3ccc, 0x3ccd, 0x3ccd, 0x3ccd, 0x3ccd,
+ 0x3ccd, 0x3ccd, 0x3ccd, 0x3cce, 0x3cce, 0x3cce, 0x3cce, 0x3cce,
+ 0x3cce, 0x3ccf, 0x3ccf, 0x3ccf, 0x3ccf, 0x3ccf, 0x3ccf, 0x3ccf,
+ 0x3cd0, 0x3cd0, 0x3cd0, 0x3cd0, 0x3cd0, 0x3cd0, 0x3cd0, 0x3cd1,
+ 0x3cd1, 0x3cd1, 0x3cd1, 0x3cd1, 0x3cd1, 0x3cd2, 0x3cd2, 0x3cd2,
+ 0x3cd2, 0x3cd2, 0x3cd2, 0x3cd2, 0x3cd3, 0x3cd3, 0x3cd3, 0x3cd3,
+ 0x3cd3, 0x3cd3, 0x3cd3, 0x3cd4, 0x3cd4, 0x3cd4, 0x3cd4, 0x3cd4,
+ 0x3cd4, 0x3cd5, 0x3cd5, 0x3cd5, 0x3cd5, 0x3cd5, 0x3cd5, 0x3cd5,
+ 0x3cd6, 0x3cd6, 0x3cd6, 0x3cd6, 0x3cd6, 0x3cd6, 0x3cd7, 0x3cd7,
+ 0x3cd7, 0x3cd7, 0x3cd7, 0x3cd7, 0x3cd7, 0x3cd8, 0x3cd8, 0x3cd8,
+ 0x3cd8, 0x3cd8, 0x3cd8, 0x3cd8, 0x3cd9, 0x3cd9, 0x3cd9, 0x3cd9,
+ 0x3cd9, 0x3cd9, 0x3cda, 0x3cda, 0x3cda, 0x3cda, 0x3cda, 0x3cda,
+ 0x3cda, 0x3cdb, 0x3cdb, 0x3cdb, 0x3cdb, 0x3cdb, 0x3cdb, 0x3cdc,
+ 0x3cdc, 0x3cdc, 0x3cdc, 0x3cdc, 0x3cdc, 0x3cdc, 0x3cdd, 0x3cdd,
+ 0x3cdd, 0x3cdd, 0x3cdd, 0x3cdd, 0x3cdd, 0x3cde, 0x3cde, 0x3cde,
+ 0x3cde, 0x3cde, 0x3cde, 0x3cdf, 0x3cdf, 0x3cdf, 0x3cdf, 0x3cdf,
+ 0x3cdf, 0x3cdf, 0x3ce0, 0x3ce0, 0x3ce0, 0x3ce0, 0x3ce0, 0x3ce0,
+ 0x3ce1, 0x3ce1, 0x3ce1, 0x3ce1, 0x3ce1, 0x3ce1, 0x3ce1, 0x3ce2,
+ 0x3ce2, 0x3ce2, 0x3ce2, 0x3ce2, 0x3ce2, 0x3ce3, 0x3ce3, 0x3ce3,
+ 0x3ce3, 0x3ce3, 0x3ce3, 0x3ce3, 0x3ce4, 0x3ce4, 0x3ce4, 0x3ce4,
+ 0x3ce4, 0x3ce4, 0x3ce4, 0x3ce5, 0x3ce5, 0x3ce5, 0x3ce5, 0x3ce5,
+ 0x3ce5, 0x3ce6, 0x3ce6, 0x3ce6, 0x3ce6, 0x3ce6, 0x3ce6, 0x3ce6,
+ 0x3ce7, 0x3ce7, 0x3ce7, 0x3ce7, 0x3ce7, 0x3ce7, 0x3ce8, 0x3ce8,
+ 0x3ce8, 0x3ce8, 0x3ce8, 0x3ce8, 0x3ce8, 0x3ce9, 0x3ce9, 0x3ce9,
+ 0x3ce9, 0x3ce9, 0x3ce9, 0x3cea, 0x3cea, 0x3cea, 0x3cea, 0x3cea,
+ 0x3cea, 0x3cea, 0x3ceb, 0x3ceb, 0x3ceb, 0x3ceb, 0x3ceb, 0x3ceb,
+ 0x3cec, 0x3cec, 0x3cec, 0x3cec, 0x3cec, 0x3cec, 0x3cec, 0x3ced,
+ 0x3ced, 0x3ced, 0x3ced, 0x3ced, 0x3ced, 0x3cee, 0x3cee, 0x3cee,
+ 0x3cee, 0x3cee, 0x3cee, 0x3cee, 0x3cef, 0x3cef, 0x3cef, 0x3cef,
+ 0x3cef, 0x3cef, 0x3cf0, 0x3cf0, 0x3cf0, 0x3cf0, 0x3cf0, 0x3cf0,
+ 0x3cf0, 0x3cf1, 0x3cf1, 0x3cf1, 0x3cf1, 0x3cf1, 0x3cf1, 0x3cf2,
+ 0x3cf2, 0x3cf2, 0x3cf2, 0x3cf2, 0x3cf2, 0x3cf2, 0x3cf3, 0x3cf3,
+ 0x3cf3, 0x3cf3, 0x3cf3, 0x3cf3, 0x3cf4, 0x3cf4, 0x3cf4, 0x3cf4,
+ 0x3cf4, 0x3cf4, 0x3cf4, 0x3cf5, 0x3cf5, 0x3cf5, 0x3cf5, 0x3cf5,
+ 0x3cf5, 0x3cf6, 0x3cf6, 0x3cf6, 0x3cf6, 0x3cf6, 0x3cf6, 0x3cf7,
+ 0x3cf7, 0x3cf7, 0x3cf7, 0x3cf7, 0x3cf7, 0x3cf7, 0x3cf8, 0x3cf8,
+ 0x3cf8, 0x3cf8, 0x3cf8, 0x3cf8, 0x3cf9, 0x3cf9, 0x3cf9, 0x3cf9,
+ 0x3cf9, 0x3cf9, 0x3cf9, 0x3cfa, 0x3cfa, 0x3cfa, 0x3cfa, 0x3cfa,
+ 0x3cfa, 0x3cfb, 0x3cfb, 0x3cfb, 0x3cfb, 0x3cfb, 0x3cfb, 0x3cfb,
+ 0x3cfc, 0x3cfc, 0x3cfc, 0x3cfc, 0x3cfc, 0x3cfc, 0x3cfd, 0x3cfd,
+ 0x3cfd, 0x3cfd, 0x3cfd, 0x3cfd, 0x3cfe, 0x3cfe, 0x3cfe, 0x3cfe,
+ 0x3cfe, 0x3cfe, 0x3cfe, 0x3cff, 0x3cff, 0x3cff, 0x3cff, 0x3cff,
+ 0x3cff, 0x3d00, 0x3d00, 0x3d00, 0x3d00, 0x3d00, 0x3d00, 0x3d00,
+ 0x3d01, 0x3d01, 0x3d01, 0x3d01, 0x3d01, 0x3d01, 0x3d02, 0x3d02,
+ 0x3d02, 0x3d02, 0x3d02, 0x3d02, 0x3d03, 0x3d03, 0x3d03, 0x3d03,
+ 0x3d03, 0x3d03, 0x3d03, 0x3d04, 0x3d04, 0x3d04, 0x3d04, 0x3d04,
+ 0x3d04, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05, 0x3d05,
+ 0x3d06, 0x3d06, 0x3d06, 0x3d06, 0x3d06, 0x3d06, 0x3d07, 0x3d07,
+ 0x3d07, 0x3d07, 0x3d07, 0x3d07, 0x3d08, 0x3d08, 0x3d08, 0x3d08,
+ 0x3d08, 0x3d08, 0x3d08, 0x3d09, 0x3d09, 0x3d09, 0x3d09, 0x3d09,
+ 0x3d09, 0x3d0a, 0x3d0a, 0x3d0a, 0x3d0a, 0x3d0a, 0x3d0a, 0x3d0b,
+ 0x3d0b, 0x3d0b, 0x3d0b, 0x3d0b, 0x3d0b, 0x3d0b, 0x3d0c, 0x3d0c,
+ 0x3d0c, 0x3d0c, 0x3d0c, 0x3d0c, 0x3d0d, 0x3d0d, 0x3d0d, 0x3d0d,
+ 0x3d0d, 0x3d0d, 0x3d0e, 0x3d0e, 0x3d0e, 0x3d0e, 0x3d0e, 0x3d0e,
+ 0x3d0e, 0x3d0f, 0x3d0f, 0x3d0f, 0x3d0f, 0x3d0f, 0x3d0f, 0x3d10,
+ 0x3d10, 0x3d10, 0x3d10, 0x3d10, 0x3d10, 0x3d11, 0x3d11, 0x3d11,
+ 0x3d11, 0x3d11, 0x3d11, 0x3d11, 0x3d12, 0x3d12, 0x3d12, 0x3d12,
+ 0x3d12, 0x3d12, 0x3d13, 0x3d13, 0x3d13, 0x3d13, 0x3d13, 0x3d13,
+ 0x3d14, 0x3d14, 0x3d14, 0x3d14, 0x3d14, 0x3d14, 0x3d14, 0x3d15,
+ 0x3d15, 0x3d15, 0x3d15, 0x3d15, 0x3d15, 0x3d16, 0x3d16, 0x3d16,
+ 0x3d16, 0x3d16, 0x3d16, 0x3d17, 0x3d17, 0x3d17, 0x3d17, 0x3d17,
+ 0x3d17, 0x3d17, 0x3d18, 0x3d18, 0x3d18, 0x3d18, 0x3d18, 0x3d18,
+ 0x3d19, 0x3d19, 0x3d19, 0x3d19, 0x3d19, 0x3d19, 0x3d1a, 0x3d1a,
+ 0x3d1a, 0x3d1a, 0x3d1a, 0x3d1a, 0x3d1b, 0x3d1b, 0x3d1b, 0x3d1b,
+ 0x3d1b, 0x3d1b, 0x3d1b, 0x3d1c, 0x3d1c, 0x3d1c, 0x3d1c, 0x3d1c,
+ 0x3d1c, 0x3d1d, 0x3d1d, 0x3d1d, 0x3d1d, 0x3d1d, 0x3d1d, 0x3d1e,
+ 0x3d1e, 0x3d1e, 0x3d1e, 0x3d1e, 0x3d1e, 0x3d1f, 0x3d1f, 0x3d1f,
+ 0x3d1f, 0x3d1f, 0x3d1f, 0x3d1f, 0x3d20, 0x3d20, 0x3d20, 0x3d20,
+ 0x3d20, 0x3d20, 0x3d21, 0x3d21, 0x3d21, 0x3d21, 0x3d21, 0x3d21,
+ 0x3d22, 0x3d22, 0x3d22, 0x3d22, 0x3d22, 0x3d22, 0x3d23, 0x3d23,
+ 0x3d23, 0x3d23, 0x3d23, 0x3d24, 0x3d24, 0x3d24, 0x3d25, 0x3d25,
+ 0x3d25, 0x3d26, 0x3d26, 0x3d26, 0x3d27, 0x3d27, 0x3d27, 0x3d28,
+ 0x3d28, 0x3d28, 0x3d29, 0x3d29, 0x3d29, 0x3d2a, 0x3d2a, 0x3d2a,
+ 0x3d2b, 0x3d2b, 0x3d2b, 0x3d2c, 0x3d2c, 0x3d2c, 0x3d2d, 0x3d2d,
+ 0x3d2d, 0x3d2d, 0x3d2e, 0x3d2e, 0x3d2e, 0x3d2f, 0x3d2f, 0x3d2f,
+ 0x3d30, 0x3d30, 0x3d30, 0x3d31, 0x3d31, 0x3d31, 0x3d32, 0x3d32,
+ 0x3d32, 0x3d33, 0x3d33, 0x3d33, 0x3d34, 0x3d34, 0x3d34, 0x3d35,
+ 0x3d35, 0x3d35, 0x3d36, 0x3d36, 0x3d36, 0x3d37, 0x3d37, 0x3d37,
+ 0x3d38, 0x3d38, 0x3d38, 0x3d39, 0x3d39, 0x3d39, 0x3d3a, 0x3d3a,
+ 0x3d3a, 0x3d3a, 0x3d3b, 0x3d3b, 0x3d3b, 0x3d3c, 0x3d3c, 0x3d3c,
+ 0x3d3d, 0x3d3d, 0x3d3d, 0x3d3e, 0x3d3e, 0x3d3e, 0x3d3f, 0x3d3f,
+ 0x3d3f, 0x3d40, 0x3d40, 0x3d40, 0x3d41, 0x3d41, 0x3d41, 0x3d42,
+ 0x3d42, 0x3d42, 0x3d43, 0x3d43, 0x3d43, 0x3d44, 0x3d44, 0x3d44,
+ 0x3d45, 0x3d45, 0x3d45, 0x3d46, 0x3d46, 0x3d46, 0x3d47, 0x3d47,
+ 0x3d47, 0x3d48, 0x3d48, 0x3d48, 0x3d49, 0x3d49, 0x3d49, 0x3d4a,
+ 0x3d4a, 0x3d4a, 0x3d4b, 0x3d4b, 0x3d4b, 0x3d4c, 0x3d4c, 0x3d4c,
+ 0x3d4d, 0x3d4d, 0x3d4d, 0x3d4e, 0x3d4e, 0x3d4e, 0x3d4f, 0x3d4f,
+ 0x3d4f, 0x3d50, 0x3d50, 0x3d50, 0x3d51, 0x3d51, 0x3d51, 0x3d52,
+ 0x3d52, 0x3d52, 0x3d53, 0x3d53, 0x3d53, 0x3d54, 0x3d54, 0x3d54,
+ 0x3d55, 0x3d55, 0x3d55, 0x3d56, 0x3d56, 0x3d56, 0x3d57, 0x3d57,
+ 0x3d57, 0x3d58, 0x3d58, 0x3d58, 0x3d59, 0x3d59, 0x3d59, 0x3d5a,
+ 0x3d5a, 0x3d5a, 0x3d5b, 0x3d5b, 0x3d5b, 0x3d5c, 0x3d5c, 0x3d5c,
+ 0x3d5d, 0x3d5d, 0x3d5d, 0x3d5e, 0x3d5e, 0x3d5e, 0x3d5f, 0x3d5f,
+ 0x3d5f, 0x3d60, 0x3d60, 0x3d60, 0x3d61, 0x3d61, 0x3d61, 0x3d62,
+ 0x3d62, 0x3d62, 0x3d63, 0x3d63, 0x3d63, 0x3d64, 0x3d64, 0x3d64,
+ 0x3d65, 0x3d65, 0x3d65, 0x3d66, 0x3d66, 0x3d66, 0x3d67, 0x3d67,
+ 0x3d67, 0x3d68, 0x3d68, 0x3d68, 0x3d69, 0x3d69, 0x3d69, 0x3d6a,
+ 0x3d6a, 0x3d6a, 0x3d6b, 0x3d6b, 0x3d6b, 0x3d6c, 0x3d6c, 0x3d6c,
+ 0x3d6d, 0x3d6d, 0x3d6d, 0x3d6e, 0x3d6e, 0x3d6e, 0x3d6f, 0x3d6f,
+ 0x3d6f, 0x3d70, 0x3d70, 0x3d70, 0x3d71, 0x3d71, 0x3d72, 0x3d72,
+ 0x3d72, 0x3d73, 0x3d73, 0x3d73, 0x3d74, 0x3d74, 0x3d74, 0x3d75,
+ 0x3d75, 0x3d75, 0x3d76, 0x3d76, 0x3d76, 0x3d77, 0x3d77, 0x3d77,
+ 0x3d78, 0x3d78, 0x3d78, 0x3d79, 0x3d79, 0x3d79, 0x3d7a, 0x3d7a,
+ 0x3d7a, 0x3d7b, 0x3d7b, 0x3d7b, 0x3d7c, 0x3d7c, 0x3d7c, 0x3d7d,
+ 0x3d7d, 0x3d7d, 0x3d7e, 0x3d7e, 0x3d7e, 0x3d7f, 0x3d7f, 0x3d80,
+ 0x3d80, 0x3d80, 0x3d81, 0x3d81, 0x3d81, 0x3d82, 0x3d82, 0x3d82,
+ 0x3d83, 0x3d83, 0x3d83, 0x3d84, 0x3d84, 0x3d84, 0x3d85, 0x3d85,
+ 0x3d85, 0x3d86, 0x3d86, 0x3d86, 0x3d87, 0x3d87, 0x3d87, 0x3d88,
+ 0x3d88, 0x3d88, 0x3d89, 0x3d89, 0x3d8a, 0x3d8a, 0x3d8a, 0x3d8b,
+ 0x3d8b, 0x3d8b, 0x3d8c, 0x3d8c, 0x3d8c, 0x3d8d, 0x3d8d, 0x3d8d,
+ 0x3d8e, 0x3d8e, 0x3d8e, 0x3d8f, 0x3d8f, 0x3d8f, 0x3d90, 0x3d90,
+ 0x3d90, 0x3d91, 0x3d91, 0x3d92, 0x3d92, 0x3d92, 0x3d93, 0x3d93,
+ 0x3d93, 0x3d94, 0x3d94, 0x3d94, 0x3d95, 0x3d95, 0x3d95, 0x3d96,
+ 0x3d96, 0x3d96, 0x3d97, 0x3d97, 0x3d97, 0x3d98, 0x3d98, 0x3d98,
+ 0x3d99, 0x3d99, 0x3d9a, 0x3d9a, 0x3d9a, 0x3d9b, 0x3d9b, 0x3d9b,
+ 0x3d9c, 0x3d9c, 0x3d9c, 0x3d9d, 0x3d9d, 0x3d9d, 0x3d9e, 0x3d9e,
+ 0x3d9e, 0x3d9f, 0x3d9f, 0x3d9f, 0x3da0, 0x3da0, 0x3da1, 0x3da1,
+ 0x3da1, 0x3da2, 0x3da2, 0x3da2, 0x3da3, 0x3da3, 0x3da3, 0x3da4,
+ 0x3da4, 0x3da4, 0x3da5, 0x3da5, 0x3da5, 0x3da6, 0x3da6, 0x3da7,
+ 0x3da7, 0x3da7, 0x3da8, 0x3da8, 0x3da8, 0x3da9, 0x3da9, 0x3da9,
+ 0x3daa, 0x3daa, 0x3daa, 0x3dab, 0x3dab, 0x3dab, 0x3dac, 0x3dac,
+ 0x3dad, 0x3dad, 0x3dad, 0x3dae, 0x3dae, 0x3dae, 0x3daf, 0x3daf,
+ 0x3daf, 0x3db0, 0x3db0, 0x3db0, 0x3db1, 0x3db1, 0x3db2, 0x3db2,
+ 0x3db2, 0x3db3, 0x3db3, 0x3db3, 0x3db4, 0x3db4, 0x3db4, 0x3db5,
+ 0x3db5, 0x3db5, 0x3db6, 0x3db6, 0x3db7, 0x3db7, 0x3db7, 0x3db8,
+ 0x3db8, 0x3db8, 0x3db9, 0x3db9, 0x3db9, 0x3dba, 0x3dba, 0x3dba,
+ 0x3dbb, 0x3dbb, 0x3dbc, 0x3dbc, 0x3dbc, 0x3dbd, 0x3dbd, 0x3dbd,
+ 0x3dbe, 0x3dbe, 0x3dbe, 0x3dbf, 0x3dbf, 0x3dbf, 0x3dc0, 0x3dc0,
+ 0x3dc1, 0x3dc1, 0x3dc1, 0x3dc2, 0x3dc2, 0x3dc2, 0x3dc3, 0x3dc3,
+ 0x3dc3, 0x3dc4, 0x3dc4, 0x3dc5, 0x3dc5, 0x3dc5, 0x3dc6, 0x3dc6,
+ 0x3dc6, 0x3dc7, 0x3dc7, 0x3dc7, 0x3dc8, 0x3dc8, 0x3dc8, 0x3dc9,
+ 0x3dc9, 0x3dca, 0x3dca, 0x3dca, 0x3dcb, 0x3dcb, 0x3dcb, 0x3dcc,
+ 0x3dcc, 0x3dcc, 0x3dcd, 0x3dcd, 0x3dce, 0x3dce, 0x3dce, 0x3dcf,
+ 0x3dcf, 0x3dcf, 0x3dd0, 0x3dd0, 0x3dd0, 0x3dd1, 0x3dd1, 0x3dd2,
+ 0x3dd2, 0x3dd2, 0x3dd3, 0x3dd3, 0x3dd3, 0x3dd4, 0x3dd4, 0x3dd4,
+ 0x3dd5, 0x3dd5, 0x3dd6, 0x3dd6, 0x3dd6, 0x3dd7, 0x3dd7, 0x3dd7,
+ 0x3dd8, 0x3dd8, 0x3dd8, 0x3dd9, 0x3dd9, 0x3dda, 0x3dda, 0x3dda,
+ 0x3ddb, 0x3ddb, 0x3ddb, 0x3ddc, 0x3ddc, 0x3ddc, 0x3ddd, 0x3ddd,
+ 0x3dde, 0x3dde, 0x3dde, 0x3ddf, 0x3ddf, 0x3ddf, 0x3de0, 0x3de0,
+ 0x3de1, 0x3de1, 0x3de1, 0x3de2, 0x3de2, 0x3de2, 0x3de3, 0x3de3,
+ 0x3de3, 0x3de4, 0x3de4, 0x3de5, 0x3de5, 0x3de5, 0x3de6, 0x3de6,
+ 0x3de6, 0x3de7, 0x3de7, 0x3de8, 0x3de8, 0x3de8, 0x3de9, 0x3de9,
+ 0x3de9, 0x3dea, 0x3dea, 0x3dea, 0x3deb, 0x3deb, 0x3dec, 0x3dec,
+ 0x3dec, 0x3ded, 0x3ded, 0x3ded, 0x3dee, 0x3dee, 0x3def, 0x3def,
+ 0x3def, 0x3df0, 0x3df0, 0x3df0, 0x3df1, 0x3df1, 0x3df2, 0x3df2,
+ 0x3df2, 0x3df3, 0x3df3, 0x3df3, 0x3df4, 0x3df4, 0x3df4, 0x3df5,
+ 0x3df5, 0x3df6, 0x3df6, 0x3df6, 0x3df7, 0x3df7, 0x3df7, 0x3df8,
+ 0x3df8, 0x3df9, 0x3df9, 0x3df9, 0x3dfa, 0x3dfa, 0x3dfa, 0x3dfb,
+ 0x3dfb, 0x3dfc, 0x3dfc, 0x3dfc, 0x3dfd, 0x3dfd, 0x3dfd, 0x3dfe,
+ 0x3dfe, 0x3dff, 0x3dff, 0x3dff, 0x3e00, 0x3e00, 0x3e00, 0x3e01,
+ 0x3e01, 0x3e02, 0x3e02, 0x3e02, 0x3e03, 0x3e03, 0x3e03, 0x3e04,
+ 0x3e04, 0x3e05, 0x3e05, 0x3e05, 0x3e06, 0x3e06, 0x3e06, 0x3e07,
+ 0x3e07, 0x3e08, 0x3e08, 0x3e08, 0x3e09, 0x3e09, 0x3e09, 0x3e0a,
+ 0x3e0a, 0x3e0b, 0x3e0b, 0x3e0b, 0x3e0c, 0x3e0c, 0x3e0d, 0x3e0d,
+ 0x3e0d, 0x3e0e, 0x3e0e, 0x3e0e, 0x3e0f, 0x3e0f, 0x3e10, 0x3e10,
+ 0x3e10, 0x3e11, 0x3e11, 0x3e11, 0x3e12, 0x3e12, 0x3e13, 0x3e13,
+ 0x3e13, 0x3e14, 0x3e14, 0x3e14, 0x3e15, 0x3e15, 0x3e16, 0x3e16,
+ 0x3e16, 0x3e17, 0x3e17, 0x3e18, 0x3e18, 0x3e18, 0x3e19, 0x3e19,
+ 0x3e19, 0x3e1a, 0x3e1a, 0x3e1b, 0x3e1b, 0x3e1b, 0x3e1c, 0x3e1c,
+ 0x3e1c, 0x3e1d, 0x3e1d, 0x3e1e, 0x3e1e, 0x3e1e, 0x3e1f, 0x3e1f,
+ 0x3e20, 0x3e20, 0x3e20, 0x3e21, 0x3e21, 0x3e21, 0x3e22, 0x3e22,
+ 0x3e23, 0x3e23, 0x3e23, 0x3e24, 0x3e24, 0x3e25, 0x3e25, 0x3e25,
+ 0x3e26, 0x3e26, 0x3e26, 0x3e27, 0x3e27, 0x3e28, 0x3e28, 0x3e28,
+ 0x3e29, 0x3e29, 0x3e2a, 0x3e2a, 0x3e2a, 0x3e2b, 0x3e2b, 0x3e2b,
+ 0x3e2c, 0x3e2c, 0x3e2d, 0x3e2d, 0x3e2d, 0x3e2e, 0x3e2e, 0x3e2f,
+ 0x3e2f, 0x3e2f, 0x3e30, 0x3e30, 0x3e30, 0x3e31, 0x3e31, 0x3e32,
+ 0x3e32, 0x3e32, 0x3e33, 0x3e33, 0x3e34, 0x3e34, 0x3e34, 0x3e35,
+ 0x3e35, 0x3e35, 0x3e36, 0x3e36, 0x3e37, 0x3e37, 0x3e37, 0x3e38,
+ 0x3e38, 0x3e39, 0x3e39, 0x3e39, 0x3e3a, 0x3e3a, 0x3e3b, 0x3e3b,
+ 0x3e3b, 0x3e3c, 0x3e3c, 0x3e3c, 0x3e3d, 0x3e3d, 0x3e3e, 0x3e3e,
+ 0x3e3e, 0x3e3f, 0x3e3f, 0x3e40, 0x3e40, 0x3e40, 0x3e41, 0x3e41,
+ 0x3e42, 0x3e42, 0x3e42, 0x3e43, 0x3e43, 0x3e44, 0x3e44, 0x3e44,
+ 0x3e45, 0x3e45, 0x3e45, 0x3e46, 0x3e46, 0x3e47, 0x3e47, 0x3e47,
+ 0x3e48, 0x3e48, 0x3e49, 0x3e49, 0x3e49, 0x3e4a, 0x3e4a, 0x3e4b,
+ 0x3e4b, 0x3e4b, 0x3e4c, 0x3e4c, 0x3e4d, 0x3e4d, 0x3e4d, 0x3e4e,
+ 0x3e4e, 0x3e4f, 0x3e4f, 0x3e4f, 0x3e50, 0x3e50, 0x3e50, 0x3e51,
+ 0x3e51, 0x3e52, 0x3e52, 0x3e52, 0x3e53, 0x3e53, 0x3e54, 0x3e54,
+ 0x3e54, 0x3e55, 0x3e55, 0x3e56, 0x3e56, 0x3e56, 0x3e57, 0x3e57,
+ 0x3e58, 0x3e58, 0x3e58, 0x3e59, 0x3e59, 0x3e5a, 0x3e5a, 0x3e5a,
+ 0x3e5b, 0x3e5b, 0x3e5c, 0x3e5c, 0x3e5c, 0x3e5d, 0x3e5d, 0x3e5e,
+ 0x3e5e, 0x3e5e, 0x3e5f, 0x3e5f, 0x3e60, 0x3e60, 0x3e60, 0x3e61,
+ 0x3e61, 0x3e62, 0x3e62, 0x3e62, 0x3e63, 0x3e63, 0x3e64, 0x3e64,
+ 0x3e64, 0x3e65, 0x3e65, 0x3e66, 0x3e66, 0x3e66, 0x3e67, 0x3e67,
+ 0x3e68, 0x3e68, 0x3e68, 0x3e69, 0x3e69, 0x3e6a, 0x3e6a, 0x3e6a,
+ 0x3e6b, 0x3e6b, 0x3e6c, 0x3e6c, 0x3e6c, 0x3e6d, 0x3e6d, 0x3e6e,
+ 0x3e6e, 0x3e6e, 0x3e6f, 0x3e6f, 0x3e70, 0x3e70, 0x3e70, 0x3e71,
+ 0x3e71, 0x3e72, 0x3e72, 0x3e72, 0x3e73, 0x3e73, 0x3e74, 0x3e74,
+ 0x3e74, 0x3e75, 0x3e75, 0x3e76, 0x3e76, 0x3e76, 0x3e77, 0x3e77,
+ 0x3e78, 0x3e78, 0x3e78, 0x3e79, 0x3e79, 0x3e7a, 0x3e7a, 0x3e7a,
+ 0x3e7b, 0x3e7b, 0x3e7c, 0x3e7c, 0x3e7c, 0x3e7d, 0x3e7d, 0x3e7e,
+ 0x3e7e, 0x3e7f, 0x3e7f, 0x3e7f, 0x3e80, 0x3e80, 0x3e81, 0x3e81,
+ 0x3e81, 0x3e82, 0x3e82, 0x3e83, 0x3e83, 0x3e83, 0x3e84, 0x3e84,
+ 0x3e85, 0x3e85, 0x3e85, 0x3e86, 0x3e86, 0x3e87, 0x3e87, 0x3e87,
+ 0x3e88, 0x3e88, 0x3e89, 0x3e89, 0x3e8a, 0x3e8a, 0x3e8a, 0x3e8b,
+ 0x3e8b, 0x3e8c, 0x3e8c, 0x3e8c, 0x3e8d, 0x3e8d, 0x3e8e, 0x3e8e,
+ 0x3e8e, 0x3e8f, 0x3e8f, 0x3e90, 0x3e90, 0x3e90, 0x3e91, 0x3e91,
+ 0x3e92, 0x3e92, 0x3e93, 0x3e93, 0x3e93, 0x3e94, 0x3e94, 0x3e95,
+ 0x3e95, 0x3e95, 0x3e96, 0x3e96, 0x3e97, 0x3e97, 0x3e97, 0x3e98,
+ 0x3e98, 0x3e99, 0x3e9a, 0x3e9b, 0x3e9c, 0x3e9c, 0x3e9d, 0x3e9e,
+ 0x3e9f, 0x3ea0, 0x3ea1, 0x3ea1, 0x3ea2, 0x3ea3, 0x3ea4, 0x3ea5,
+ 0x3ea6, 0x3ea6, 0x3ea7, 0x3ea8, 0x3ea9, 0x3eaa, 0x3eab, 0x3eab,
+ 0x3eac, 0x3ead, 0x3eae, 0x3eaf, 0x3eb0, 0x3eb0, 0x3eb1, 0x3eb2,
+ 0x3eb3, 0x3eb4, 0x3eb5, 0x3eb5, 0x3eb6, 0x3eb7, 0x3eb8, 0x3eb9,
+ 0x3eba, 0x3eba, 0x3ebb, 0x3ebc, 0x3ebd, 0x3ebe, 0x3ebf, 0x3ebf,
+ 0x3ec0, 0x3ec1, 0x3ec2, 0x3ec3, 0x3ec4, 0x3ec5, 0x3ec5, 0x3ec6,
+ 0x3ec7, 0x3ec8, 0x3ec9, 0x3eca, 0x3eca, 0x3ecb, 0x3ecc, 0x3ecd,
+ 0x3ece, 0x3ecf, 0x3ed0, 0x3ed0, 0x3ed1, 0x3ed2, 0x3ed3, 0x3ed4,
+ 0x3ed5, 0x3ed6, 0x3ed6, 0x3ed7, 0x3ed8, 0x3ed9, 0x3eda, 0x3edb,
+ 0x3edc, 0x3edc, 0x3edd, 0x3ede, 0x3edf, 0x3ee0, 0x3ee1, 0x3ee2,
+ 0x3ee2, 0x3ee3, 0x3ee4, 0x3ee5, 0x3ee6, 0x3ee7, 0x3ee8, 0x3ee8,
+ 0x3ee9, 0x3eea, 0x3eeb, 0x3eec, 0x3eed, 0x3eee, 0x3eef, 0x3eef,
+ 0x3ef0, 0x3ef1, 0x3ef2, 0x3ef3, 0x3ef4, 0x3ef5, 0x3ef5, 0x3ef6,
+ 0x3ef7, 0x3ef8, 0x3ef9, 0x3efa, 0x3efb, 0x3efc, 0x3efc, 0x3efd,
+ 0x3efe, 0x3eff, 0x3f00, 0x3f01, 0x3f02, 0x3f03, 0x3f03, 0x3f04,
+ 0x3f05, 0x3f06, 0x3f07, 0x3f08, 0x3f09, 0x3f0a, 0x3f0a, 0x3f0b,
+ 0x3f0c, 0x3f0d, 0x3f0e, 0x3f0f, 0x3f10, 0x3f11, 0x3f12, 0x3f12,
+ 0x3f13, 0x3f14, 0x3f15, 0x3f16, 0x3f17, 0x3f18, 0x3f19, 0x3f19,
+ 0x3f1a, 0x3f1b, 0x3f1c, 0x3f1d, 0x3f1e, 0x3f1f, 0x3f20, 0x3f21,
+ 0x3f21, 0x3f22, 0x3f23, 0x3f24, 0x3f25, 0x3f26, 0x3f27, 0x3f28,
+ 0x3f29, 0x3f2a, 0x3f2a, 0x3f2b, 0x3f2c, 0x3f2d, 0x3f2e, 0x3f2f,
+ 0x3f30, 0x3f31, 0x3f32, 0x3f32, 0x3f33, 0x3f34, 0x3f35, 0x3f36,
+ 0x3f37, 0x3f38, 0x3f39, 0x3f3a, 0x3f3b, 0x3f3c, 0x3f3c, 0x3f3d,
+ 0x3f3e, 0x3f3f, 0x3f40, 0x3f41, 0x3f42, 0x3f43, 0x3f44, 0x3f45,
+ 0x3f45, 0x3f46, 0x3f47, 0x3f48, 0x3f49, 0x3f4a, 0x3f4b, 0x3f4c,
+ 0x3f4d, 0x3f4e, 0x3f4f, 0x3f50, 0x3f50, 0x3f51, 0x3f52, 0x3f53,
+ 0x3f54, 0x3f55, 0x3f56, 0x3f57, 0x3f58, 0x3f59, 0x3f5a, 0x3f5b,
+ 0x3f5b, 0x3f5c, 0x3f5d, 0x3f5e, 0x3f5f, 0x3f60, 0x3f61, 0x3f62,
+ 0x3f63, 0x3f64, 0x3f65, 0x3f66, 0x3f66, 0x3f67, 0x3f68, 0x3f69,
+ 0x3f6a, 0x3f6b, 0x3f6c, 0x3f6d, 0x3f6e, 0x3f6f, 0x3f70, 0x3f71,
+ 0x3f72, 0x3f73, 0x3f73, 0x3f74, 0x3f75, 0x3f76, 0x3f77, 0x3f78,
+ 0x3f79, 0x3f7a, 0x3f7b, 0x3f7c, 0x3f7d, 0x3f7e, 0x3f7f, 0x3f80,
+ 0x3f81, 0x3f82, 0x3f82, 0x3f83, 0x3f84, 0x3f85, 0x3f86, 0x3f87,
+ 0x3f88, 0x3f89, 0x3f8a, 0x3f8b, 0x3f8c, 0x3f8d, 0x3f8e, 0x3f8f,
+ 0x3f90, 0x3f91, 0x3f92, 0x3f92, 0x3f93, 0x3f94, 0x3f95, 0x3f96,
+ 0x3f97, 0x3f98, 0x3f99, 0x3f9a, 0x3f9b, 0x3f9c, 0x3f9d, 0x3f9e,
+ 0x3f9f, 0x3fa0, 0x3fa1, 0x3fa2, 0x3fa3, 0x3fa4, 0x3fa5, 0x3fa5,
+ 0x3fa6, 0x3fa7, 0x3fa8, 0x3fa9, 0x3faa, 0x3fab, 0x3fac, 0x3fad,
+ 0x3fae, 0x3faf, 0x3fb0, 0x3fb1, 0x3fb2, 0x3fb3, 0x3fb4, 0x3fb5,
+ 0x3fb6, 0x3fb7, 0x3fb8, 0x3fb9, 0x3fba, 0x3fbb, 0x3fbc, 0x3fbd,
+ 0x3fbe, 0x3fbf, 0x3fbf, 0x3fc0, 0x3fc1, 0x3fc2, 0x3fc3, 0x3fc4,
+ 0x3fc5, 0x3fc6, 0x3fc7, 0x3fc8, 0x3fc9, 0x3fca, 0x3fcb, 0x3fcc,
+ 0x3fcd, 0x3fce, 0x3fcf, 0x3fd0, 0x3fd1, 0x3fd2, 0x3fd3, 0x3fd4,
+ 0x3fd5, 0x3fd6, 0x3fd7, 0x3fd8, 0x3fd9, 0x3fda, 0x3fdb, 0x3fdc,
+ 0x3fdd, 0x3fde, 0x3fdf, 0x3fe0, 0x3fe1, 0x3fe2, 0x3fe3, 0x3fe4,
+ 0x3fe5, 0x3fe6, 0x3fe7, 0x3fe8, 0x3fe9, 0x3fea, 0x3feb, 0x3fec,
+ 0x3fed, 0x3fee, 0x3fef, 0x3ff0, 0x3ff0, 0x3ff1, 0x3ff2, 0x3ff3,
+ 0x3ff4, 0x3ff5, 0x3ff6, 0x3ff7, 0x3ff8, 0x3ff9, 0x3ffa, 0x3ffb,
+ 0x3ffc, 0x3ffd, 0x3ffe, 0x3fff, 0x4000, 0x4001, 0x4001, 0x4002,
+ 0x4002, 0x4003, 0x4003, 0x4004, 0x4004, 0x4005, 0x4005, 0x4006,
+ 0x4006, 0x4007, 0x4007, 0x4008, 0x4008, 0x4009, 0x4009, 0x400a,
+ 0x400a, 0x400b, 0x400b, 0x400c, 0x400c, 0x400d, 0x400d, 0x400e,
+ 0x400e, 0x400f, 0x400f, 0x4010, 0x4010, 0x4011, 0x4011, 0x4012,
+ 0x4012, 0x4013, 0x4013, 0x4014, 0x4014, 0x4015, 0x4015, 0x4016,
+ 0x4016, 0x4017, 0x4017, 0x4018, 0x4019, 0x4019, 0x401a, 0x401a,
+ 0x401b, 0x401b, 0x401c, 0x401c, 0x401d, 0x401d, 0x401e, 0x401e,
+ 0x401f, 0x401f, 0x4020, 0x4020, 0x4021, 0x4021, 0x4022, 0x4022,
+ 0x4023, 0x4023, 0x4024, 0x4024, 0x4025, 0x4025, 0x4026, 0x4026,
+ 0x4027, 0x4027, 0x4028, 0x4028, 0x4029, 0x402a, 0x402a, 0x402b,
+ 0x402b, 0x402c, 0x402c, 0x402d, 0x402d, 0x402e, 0x402e, 0x402f,
+ 0x402f, 0x4030, 0x4030, 0x4031, 0x4031, 0x4032, 0x4032, 0x4033,
+ 0x4033, 0x4034, 0x4035, 0x4035, 0x4036, 0x4036, 0x4037, 0x4037,
+ 0x4038, 0x4038, 0x4039, 0x4039, 0x403a, 0x403a, 0x403b, 0x403b,
+ 0x403c, 0x403c, 0x403d, 0x403d, 0x403e, 0x403f, 0x403f, 0x4040,
+ 0x4040, 0x4041, 0x4041, 0x4042, 0x4042, 0x4043, 0x4043, 0x4044,
+ 0x4044, 0x4045, 0x4045, 0x4046, 0x4047, 0x4047, 0x4048, 0x4048,
+ 0x4049, 0x4049, 0x404a, 0x404a, 0x404b, 0x404b, 0x404c, 0x404c,
+ 0x404d, 0x404e, 0x404e, 0x404f, 0x404f, 0x4050, 0x4050, 0x4051,
+ 0x4051, 0x4052, 0x4052, 0x4053, 0x4053, 0x4054, 0x4055, 0x4055,
+ 0x4056, 0x4056, 0x4057, 0x4057, 0x4058, 0x4058, 0x4059, 0x4059,
+ 0x405a, 0x405a, 0x405b, 0x405c, 0x405c, 0x405d, 0x405d, 0x405e,
+ 0x405e, 0x405f, 0x405f, 0x4060, 0x4060, 0x4061, 0x4062, 0x4062,
+ 0x4063, 0x4063, 0x4064, 0x4064, 0x4065, 0x4065, 0x4066, 0x4067,
+ 0x4067, 0x4068, 0x4068, 0x4069, 0x4069, 0x406a, 0x406a, 0x406b,
+ 0x406b, 0x406c, 0x406d, 0x406d, 0x406e, 0x406e, 0x406f, 0x406f,
+ 0x4070, 0x4070, 0x4071, 0x4072, 0x4072, 0x4073, 0x4073, 0x4074,
+ 0x4074, 0x4075, 0x4075, 0x4076, 0x4077, 0x4077, 0x4078, 0x4078,
+ 0x4079, 0x4079, 0x407a, 0x407b, 0x407b, 0x407c, 0x407c, 0x407d,
+ 0x407d, 0x407e, 0x407e, 0x407f, 0x4080, 0x4080, 0x4081, 0x4081,
+ 0x4082, 0x4082, 0x4083, 0x4084, 0x4084, 0x4085, 0x4085, 0x4086,
+ 0x4086, 0x4087, 0x4087, 0x4088, 0x4089, 0x4089, 0x408a, 0x408a,
+ 0x408b, 0x408b, 0x408c, 0x408d, 0x408d, 0x408e, 0x408e, 0x408f,
+ 0x408f, 0x4090, 0x4091, 0x4091, 0x4092, 0x4092, 0x4093, 0x4093,
+ 0x4094, 0x4095, 0x4095, 0x4096, 0x4096, 0x4097, 0x4097, 0x4098,
+ 0x4099, 0x4099, 0x409a, 0x409a, 0x409b, 0x409b, 0x409c, 0x409d,
+ 0x409d, 0x409e, 0x409e, 0x409f, 0x409f, 0x40a0, 0x40a1, 0x40a1,
+ 0x40a2, 0x40a2, 0x40a3, 0x40a4, 0x40a4, 0x40a5, 0x40a5, 0x40a6,
+ 0x40a6, 0x40a7, 0x40a8, 0x40a8, 0x40a9, 0x40a9, 0x40aa, 0x40ab,
+ 0x40ab, 0x40ac, 0x40ac, 0x40ad, 0x40ad, 0x40ae, 0x40af, 0x40af,
+ 0x40b0, 0x40b0, 0x40b1, 0x40b2, 0x40b2, 0x40b3, 0x40b3, 0x40b4,
+ 0x40b4, 0x40b5, 0x40b6, 0x40b6, 0x40b7, 0x40b7, 0x40b8, 0x40b9,
+ 0x40b9, 0x40ba, 0x40ba, 0x40bb, 0x40bc, 0x40bc, 0x40bd, 0x40bd,
+ 0x40be, 0x40bf, 0x40bf, 0x40c0, 0x40c0, 0x40c1, 0x40c1, 0x40c2,
+ 0x40c3, 0x40c3, 0x40c4, 0x40c4, 0x40c5, 0x40c6, 0x40c6, 0x40c7,
+ 0x40c7, 0x40c8, 0x40c9, 0x40c9, 0x40ca, 0x40ca, 0x40cb, 0x40cc,
+ 0x40cc, 0x40cd, 0x40cd, 0x40ce, 0x40cf, 0x40cf, 0x40d0, 0x40d0,
+ 0x40d1, 0x40d2, 0x40d2, 0x40d3, 0x40d3, 0x40d4, 0x40d5, 0x40d5,
+ 0x40d6, 0x40d6, 0x40d7, 0x40d8, 0x40d8, 0x40d9, 0x40d9, 0x40da,
+ 0x40db, 0x40db, 0x40dc, 0x40dd, 0x40dd, 0x40de, 0x40de, 0x40df,
+ 0x40e0, 0x40e0, 0x40e1, 0x40e1, 0x40e2, 0x40e3, 0x40e3, 0x40e4,
+ 0x40e4, 0x40e5, 0x40e6, 0x40e6, 0x40e7, 0x40e8, 0x40e8, 0x40e9,
+ 0x40e9, 0x40ea, 0x40eb, 0x40eb, 0x40ec, 0x40ec, 0x40ed, 0x40ee,
+ 0x40ee, 0x40ef, 0x40f0, 0x40f0, 0x40f1, 0x40f1, 0x40f2, 0x40f3,
+ 0x40f3, 0x40f4, 0x40f4, 0x40f5, 0x40f6, 0x40f6, 0x40f7, 0x40f8,
+ 0x40f8, 0x40f9, 0x40f9, 0x40fa, 0x40fb, 0x40fb, 0x40fc, 0x40fd,
+ 0x40fd, 0x40fe, 0x40fe, 0x40ff, 0x4100, 0x4100, 0x4101, 0x4102,
+ 0x4102, 0x4103, 0x4103, 0x4104, 0x4105, 0x4105, 0x4106, 0x4107,
+ 0x4107, 0x4108, 0x4108, 0x4109, 0x410a, 0x410a, 0x410b, 0x410c,
+ 0x410c, 0x410d, 0x410d, 0x410e, 0x410f, 0x410f, 0x4110, 0x4111,
+ 0x4111, 0x4112, 0x4113, 0x4113, 0x4114, 0x4114, 0x4115, 0x4116,
+ 0x4116, 0x4117, 0x4118, 0x4118, 0x4119, 0x411a, 0x411a, 0x411b,
+ 0x411b, 0x411c, 0x411d, 0x411d, 0x411e, 0x411f, 0x411f, 0x4120,
+ 0x4121, 0x4121, 0x4122, 0x4122, 0x4123, 0x4124, 0x4124, 0x4125,
+ 0x4126, 0x4126, 0x4127, 0x4128, 0x4128, 0x4129, 0x412a, 0x412a,
+ 0x412b, 0x412b, 0x412c, 0x412d, 0x412d, 0x412e, 0x412f, 0x412f,
+ 0x4130, 0x4131, 0x4131, 0x4132, 0x4133, 0x4133, 0x4134, 0x4135,
+ 0x4135, 0x4136, 0x4137, 0x4137, 0x4138, 0x4138, 0x4139, 0x413a,
+ 0x413a, 0x413b, 0x413c, 0x413c, 0x413d, 0x413e, 0x413e, 0x413f,
+ 0x4140, 0x4140, 0x4141, 0x4142, 0x4142, 0x4143, 0x4144, 0x4144,
+ 0x4145, 0x4146, 0x4146, 0x4147, 0x4148, 0x4148, 0x4149, 0x414a,
+ 0x414a, 0x414b, 0x414c, 0x414c, 0x414d, 0x414e, 0x414e, 0x414f,
+ 0x4150, 0x4150, 0x4151, 0x4152, 0x4152, 0x4153, 0x4154, 0x4154,
+ 0x4155, 0x4156, 0x4156, 0x4157, 0x4158, 0x4158, 0x4159, 0x415a,
+ 0x415a, 0x415b, 0x415c, 0x415c, 0x415d, 0x415e, 0x415e, 0x415f,
+ 0x4160, 0x4160, 0x4161, 0x4162, 0x4162, 0x4163, 0x4164, 0x4164,
+ 0x4165, 0x4166, 0x4166, 0x4167, 0x4168, 0x4168, 0x4169, 0x416a,
+ 0x416a, 0x416b, 0x416c, 0x416c, 0x416d, 0x416e, 0x416e, 0x416f,
+ 0x4170, 0x4171, 0x4172, 0x4174, 0x4175, 0x4177, 0x4178, 0x4179,
+ 0x417b, 0x417c, 0x417d, 0x417f, 0x4180, 0x4182, 0x4183, 0x4184,
+ 0x4186, 0x4187, 0x4188, 0x418a, 0x418b, 0x418d, 0x418e, 0x418f,
+ 0x4191, 0x4192, 0x4194, 0x4195, 0x4196, 0x4198, 0x4199, 0x419b,
+ 0x419c, 0x419d, 0x419f, 0x41a0, 0x41a2, 0x41a3, 0x41a4, 0x41a6,
+ 0x41a7, 0x41a9, 0x41aa, 0x41ab, 0x41ad, 0x41ae, 0x41b0, 0x41b1,
+ 0x41b3, 0x41b4, 0x41b5, 0x41b7, 0x41b8, 0x41ba, 0x41bb, 0x41bd,
+ 0x41be, 0x41bf, 0x41c1, 0x41c2, 0x41c4, 0x41c5, 0x41c7, 0x41c8,
+ 0x41ca, 0x41cb, 0x41cc, 0x41ce, 0x41cf, 0x41d1, 0x41d2, 0x41d4,
+ 0x41d5, 0x41d7, 0x41d8, 0x41da, 0x41db, 0x41dc, 0x41de, 0x41df,
+ 0x41e1, 0x41e2, 0x41e4, 0x41e5, 0x41e7, 0x41e8, 0x41ea, 0x41eb,
+ 0x41ed, 0x41ee, 0x41f0, 0x41f1, 0x41f3, 0x41f4, 0x41f6, 0x41f7,
+ 0x41f9, 0x41fa, 0x41fc, 0x41fd, 0x41ff, 0x4200, 0x4202, 0x4203,
+ 0x4205, 0x4206, 0x4208, 0x4209, 0x420b, 0x420c, 0x420e, 0x420f,
+ 0x4211, 0x4212, 0x4214, 0x4215, 0x4217, 0x4218, 0x421a, 0x421b,
+ 0x421d, 0x421e, 0x4220, 0x4221, 0x4223, 0x4224, 0x4226, 0x4228,
+ 0x4229, 0x422b, 0x422c, 0x422e, 0x422f, 0x4231, 0x4232, 0x4234,
+ 0x4235, 0x4237, 0x4239, 0x423a, 0x423c, 0x423d, 0x423f, 0x4240,
+ 0x4242, 0x4243, 0x4245, 0x4247, 0x4248, 0x424a, 0x424b, 0x424d,
+ 0x424e, 0x4250, 0x4252, 0x4253, 0x4255, 0x4256, 0x4258, 0x425a,
+ 0x425b, 0x425d, 0x425e, 0x4260, 0x4262, 0x4263, 0x4265, 0x4266,
+ 0x4268, 0x4269, 0x426b, 0x426d, 0x426e, 0x4270, 0x4272, 0x4273,
+ 0x4275, 0x4276, 0x4278, 0x427a, 0x427b, 0x427d, 0x427e, 0x4280,
+ 0x4282, 0x4283, 0x4285, 0x4287, 0x4288, 0x428a, 0x428c, 0x428d,
+ 0x428f, 0x4290, 0x4292, 0x4294, 0x4295, 0x4297, 0x4299, 0x429a,
+ 0x429c, 0x429e, 0x429f, 0x42a1, 0x42a3, 0x42a4, 0x42a6, 0x42a8,
+ 0x42a9, 0x42ab, 0x42ad, 0x42ae, 0x42b0, 0x42b2, 0x42b3, 0x42b5,
+ 0x42b7, 0x42b8, 0x42ba, 0x42bc, 0x42bd, 0x42bf, 0x42c1, 0x42c2,
+ 0x42c4, 0x42c6, 0x42c7, 0x42c9, 0x42cb, 0x42cd, 0x42ce, 0x42d0,
+ 0x42d2, 0x42d3, 0x42d5, 0x42d7, 0x42d8, 0x42da, 0x42dc, 0x42de,
+ 0x42df, 0x42e1, 0x42e3, 0x42e5, 0x42e6, 0x42e8, 0x42ea, 0x42eb,
+ 0x42ed, 0x42ef, 0x42f1, 0x42f2, 0x42f4, 0x42f6, 0x42f8, 0x42f9,
+ 0x42fb, 0x42fd, 0x42ff, 0x4300, 0x4302, 0x4304, 0x4306, 0x4307,
+ 0x4309, 0x430b, 0x430d, 0x430e, 0x4310, 0x4312, 0x4314, 0x4315,
+ 0x4317, 0x4319, 0x431b, 0x431d, 0x431e, 0x4320, 0x4322, 0x4324,
+ 0x4325, 0x4327, 0x4329, 0x432b, 0x432d, 0x432e, 0x4330, 0x4332,
+ 0x4334, 0x4336, 0x4337, 0x4339, 0x433b, 0x433d, 0x433f, 0x4340,
+ 0x4342, 0x4344, 0x4346, 0x4348, 0x434a, 0x434b, 0x434d, 0x434f,
+ 0x4351, 0x4353, 0x4354, 0x4356, 0x4358, 0x435a, 0x435c, 0x435e,
+ 0x4360, 0x4361, 0x4363, 0x4365, 0x4367, 0x4369, 0x436b, 0x436c,
+ 0x436e, 0x4370, 0x4372, 0x4374, 0x4376, 0x4378, 0x4379, 0x437b,
+ 0x437d, 0x437f, 0x4381, 0x4383, 0x4385, 0x4387, 0x4388, 0x438a,
+ 0x438c, 0x438e, 0x4390, 0x4392, 0x4394, 0x4396, 0x4398, 0x439a,
+ 0x439b, 0x439d, 0x439f, 0x43a1, 0x43a3, 0x43a5, 0x43a7, 0x43a9,
+ 0x43ab, 0x43ad, 0x43af, 0x43b0, 0x43b2, 0x43b4, 0x43b6, 0x43b8,
+ 0x43ba, 0x43bc, 0x43be, 0x43c0, 0x43c2, 0x43c4, 0x43c6, 0x43c8,
+ 0x43ca, 0x43cc, 0x43ce, 0x43cf, 0x43d1, 0x43d3, 0x43d5, 0x43d7,
+ 0x43d9, 0x43db, 0x43dd, 0x43df, 0x43e1, 0x43e3, 0x43e5, 0x43e7,
+ 0x43e9, 0x43eb, 0x43ed, 0x43ef, 0x43f1, 0x43f3, 0x43f5, 0x43f7,
+ 0x43f9, 0x43fb, 0x43fd, 0x43ff, 0x4400, 0x4401, 0x4402, 0x4403,
+ 0x4404, 0x4405, 0x4406, 0x4407, 0x4408, 0x4409, 0x440a, 0x440b,
+ 0x440d, 0x440e, 0x440f, 0x4410, 0x4411, 0x4412, 0x4413, 0x4414,
+ 0x4415, 0x4416, 0x4417, 0x4418, 0x4419, 0x441a, 0x441b, 0x441c,
+ 0x441d, 0x441e, 0x441f, 0x4420, 0x4421, 0x4422, 0x4423, 0x4424,
+ 0x4425, 0x4426, 0x4427, 0x4428, 0x4429, 0x442a, 0x442b, 0x442c,
+ 0x442d, 0x442e, 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, 0x4435,
+ 0x4436, 0x4437, 0x4438, 0x4439, 0x443a, 0x443b, 0x443c, 0x443d,
+ 0x443e, 0x443f, 0x4440, 0x4441, 0x4443, 0x4444, 0x4445, 0x4446,
+ 0x4447, 0x4448, 0x4449, 0x444a, 0x444b, 0x444c, 0x444d, 0x444e,
+ 0x444f, 0x4450, 0x4452, 0x4453, 0x4454, 0x4455, 0x4456, 0x4457,
+ 0x4458, 0x4459, 0x445a, 0x445b, 0x445c, 0x445d, 0x445f, 0x4460,
+ 0x4461, 0x4462, 0x4463, 0x4464, 0x4465, 0x4466, 0x4467, 0x4468,
+ 0x446a, 0x446b, 0x446c, 0x446d, 0x446e, 0x446f, 0x4470, 0x4471,
+ 0x4472, 0x4473, 0x4475, 0x4476, 0x4477, 0x4478, 0x4479, 0x447a,
+ 0x447b, 0x447c, 0x447e, 0x447f, 0x4480, 0x4481, 0x4482, 0x4483,
+ 0x4484, 0x4485, 0x4487, 0x4488, 0x4489, 0x448a, 0x448b, 0x448c,
+ 0x448d, 0x448f, 0x4490, 0x4491, 0x4492, 0x4493, 0x4494, 0x4495,
+ 0x4497, 0x4498, 0x4499, 0x449a, 0x449b, 0x449c, 0x449d, 0x449f,
+ 0x44a0, 0x44a1, 0x44a2, 0x44a3, 0x44a4, 0x44a6, 0x44a7, 0x44a8,
+ 0x44a9, 0x44aa, 0x44ab, 0x44ad, 0x44ae, 0x44af, 0x44b0, 0x44b1,
+ 0x44b2, 0x44b4, 0x44b5, 0x44b6, 0x44b7, 0x44b8, 0x44b9, 0x44bb,
+ 0x44bc, 0x44bd, 0x44be, 0x44bf, 0x44c1, 0x44c2, 0x44c3, 0x44c4,
+ 0x44c5, 0x44c7, 0x44c8, 0x44c9, 0x44ca, 0x44cb, 0x44cc, 0x44ce,
+ 0x44cf, 0x44d0, 0x44d1, 0x44d2, 0x44d4, 0x44d5, 0x44d6, 0x44d7,
+ 0x44d9, 0x44da, 0x44db, 0x44dc, 0x44dd, 0x44df, 0x44e0, 0x44e1,
+ 0x44e2, 0x44e3, 0x44e5, 0x44e6, 0x44e7, 0x44e8, 0x44ea, 0x44eb,
+ 0x44ec, 0x44ed, 0x44ef, 0x44f0, 0x44f1, 0x44f2, 0x44f3, 0x44f5,
+ 0x44f6, 0x44f7, 0x44f8, 0x44fa, 0x44fb, 0x44fc, 0x44fd, 0x44ff,
+ 0x4500, 0x4501, 0x4502, 0x4504, 0x4505, 0x4506, 0x4507, 0x4509,
+ 0x450a, 0x450b, 0x450c, 0x450e, 0x450f, 0x4510, 0x4512, 0x4513,
+ 0x4514, 0x4515, 0x4517, 0x4518, 0x4519, 0x451a, 0x451c, 0x451d,
+ 0x451e, 0x4520, 0x4521, 0x4522, 0x4523, 0x4525, 0x4526, 0x4527,
+ 0x4529, 0x452a, 0x452b, 0x452c, 0x452e, 0x452f, 0x4530, 0x4532,
+ 0x4533, 0x4534, 0x4536, 0x4537, 0x4538, 0x4539, 0x453b, 0x453c,
+ 0x453d, 0x453f, 0x4540, 0x4541, 0x4543, 0x4544, 0x4545, 0x4547,
+ 0x4548, 0x4549, 0x454b, 0x454c, 0x454d, 0x454e, 0x4550, 0x4551,
+ 0x4552, 0x4554, 0x4555, 0x4556, 0x4558, 0x4559, 0x455a, 0x455c,
+ 0x455d, 0x455e, 0x4560, 0x4561, 0x4563, 0x4564, 0x4565, 0x4567,
+ 0x4568, 0x4569, 0x456b, 0x456c, 0x456d, 0x456f, 0x4570, 0x4571,
+ 0x4573, 0x4574, 0x4576, 0x4577, 0x4578, 0x457a, 0x457b, 0x457c,
+ 0x457e, 0x457f, 0x4580, 0x4582, 0x4583, 0x4585, 0x4586, 0x4587,
+ 0x4589, 0x458a, 0x458c, 0x458d, 0x458e, 0x4590, 0x4591, 0x4592,
+ 0x4594, 0x4595, 0x4597, 0x4598, 0x4599, 0x459b, 0x459c, 0x459e,
+ 0x459f, 0x45a0, 0x45a2, 0x45a3, 0x45a5, 0x45a6, 0x45a8, 0x45a9,
+ 0x45aa, 0x45ac, 0x45ad, 0x45af, 0x45b0, 0x45b1, 0x45b3, 0x45b4,
+ 0x45b6, 0x45b7, 0x45b9, 0x45ba, 0x45bb, 0x45bd, 0x45be, 0x45c0,
+ 0x45c1, 0x45c3, 0x45c4, 0x45c6, 0x45c7, 0x45c8, 0x45ca, 0x45cb,
+ 0x45cd, 0x45ce, 0x45d0, 0x45d1, 0x45d3, 0x45d4, 0x45d5, 0x45d7,
+ 0x45d8, 0x45da, 0x45db, 0x45dd, 0x45de, 0x45e0, 0x45e1, 0x45e3,
+ 0x45e4, 0x45e6, 0x45e7, 0x45e9, 0x45ea, 0x45eb, 0x45ed, 0x45ee,
+ 0x45f0, 0x45f1, 0x45f3, 0x45f4, 0x45f6, 0x45f7, 0x45f9, 0x45fa,
+ 0x45fc, 0x45fd, 0x45ff, 0x4600, 0x4602, 0x4603, 0x4605, 0x4606,
+ 0x4608, 0x4609, 0x460b, 0x460c, 0x460e, 0x460f, 0x4611, 0x4612,
+ 0x4614, 0x4616, 0x4617, 0x4619, 0x461a, 0x461c, 0x461d, 0x461f,
+ 0x4620, 0x4622, 0x4623, 0x4625, 0x4626, 0x4628, 0x4629, 0x462b,
+ 0x462c, 0x462e, 0x4630, 0x4631, 0x4633, 0x4634, 0x4636, 0x4637,
+ 0x4639, 0x463a, 0x463c, 0x463e, 0x463f, 0x4641, 0x4642, 0x4644,
+ 0x4645, 0x4647, 0x4649, 0x464a, 0x464c, 0x464d, 0x464f, 0x4650,
+ 0x4652, 0x4654, 0x4655, 0x4657, 0x4658, 0x465a, 0x465b, 0x465d,
+ 0x465f, 0x4660, 0x4662, 0x4663, 0x4665, 0x4667, 0x4668, 0x466a,
+ 0x466b, 0x466d, 0x466f, 0x4670, 0x4672, 0x4673, 0x4675, 0x4677,
+ 0x4678, 0x467a, 0x467c, 0x467d, 0x467f, 0x4680, 0x4682, 0x4684,
+ 0x4685, 0x4687, 0x4689, 0x468a, 0x468c, 0x468e, 0x468f, 0x4691,
+ 0x4692, 0x4694, 0x4696, 0x4697, 0x4699, 0x469b, 0x469c, 0x469e,
+ 0x46a0, 0x46a1, 0x46a3, 0x46a5, 0x46a6, 0x46a8, 0x46aa, 0x46ab,
+ 0x46ad, 0x46af, 0x46b0, 0x46b2, 0x46b4, 0x46b5, 0x46b7, 0x46b9,
+ 0x46ba, 0x46bc, 0x46be, 0x46bf, 0x46c1, 0x46c3, 0x46c4, 0x46c6,
+ 0x46c8, 0x46ca, 0x46cb, 0x46cd, 0x46cf, 0x46d0, 0x46d2, 0x46d4,
+ 0x46d5, 0x46d7, 0x46d9, 0x46db, 0x46dc, 0x46de, 0x46e0, 0x46e1,
+ 0x46e3, 0x46e5, 0x46e7, 0x46e8, 0x46ea, 0x46ec, 0x46ee, 0x46ef,
+ 0x46f1, 0x46f3, 0x46f4, 0x46f6, 0x46f8, 0x46fa, 0x46fb, 0x46fd,
+ 0x46ff, 0x4701, 0x4702, 0x4704, 0x4706, 0x4708, 0x4709, 0x470b,
+ 0x470d, 0x470f, 0x4711, 0x4712, 0x4714, 0x4716, 0x4718, 0x4719,
+ 0x471b, 0x471d, 0x471f, 0x4720, 0x4722, 0x4724, 0x4726, 0x4728,
+ 0x4729, 0x472b, 0x472d, 0x472f, 0x4731, 0x4732, 0x4734, 0x4736,
+ 0x4738, 0x473a, 0x473b, 0x473d, 0x473f, 0x4741, 0x4743, 0x4744,
+ 0x4746, 0x4748, 0x474a, 0x474c, 0x474e, 0x474f, 0x4751, 0x4753,
+ 0x4755, 0x4757, 0x4759, 0x475a, 0x475c, 0x475e, 0x4760, 0x4762,
+ 0x4764, 0x4767, 0x476b, 0x476f, 0x4772, 0x4776, 0x477a, 0x477e,
+ 0x4781, 0x4785, 0x4789, 0x478d, 0x4790, 0x4794, 0x4798, 0x479c,
+ 0x47a0, 0x47a3, 0x47a7, 0x47ab, 0x47af, 0x47b3, 0x47b7, 0x47bb,
+ 0x47be, 0x47c2, 0x47c6, 0x47ca, 0x47ce, 0x47d2, 0x47d6, 0x47da,
+ 0x47de, 0x47e2, 0x47e5, 0x47e9, 0x47ed, 0x47f1, 0x47f5, 0x47f9,
+ 0x47fd, 0x4801, 0x4803, 0x4805, 0x4807, 0x4809, 0x480b, 0x480d,
+ 0x480f, 0x4811, 0x4813, 0x4815, 0x4817, 0x4819, 0x481b, 0x481d,
+ 0x481f, 0x4821, 0x4823, 0x4825, 0x4827, 0x4829, 0x482c, 0x482e,
+ 0x4830, 0x4832, 0x4834, 0x4836, 0x4838, 0x483a, 0x483c, 0x483e,
+ 0x4841, 0x4843, 0x4845, 0x4847, 0x4849, 0x484b, 0x484d, 0x4850,
+ 0x4852, 0x4854, 0x4856, 0x4858, 0x485a, 0x485d, 0x485f, 0x4861,
+ 0x4863, 0x4865, 0x4868, 0x486a, 0x486c, 0x486e, 0x4870, 0x4873,
+ 0x4875, 0x4877, 0x4879, 0x487c, 0x487e, 0x4880, 0x4882, 0x4885,
+ 0x4887, 0x4889, 0x488b, 0x488e, 0x4890, 0x4892, 0x4894, 0x4897,
+ 0x4899, 0x489b, 0x489e, 0x48a0, 0x48a2, 0x48a5, 0x48a7, 0x48a9,
+ 0x48ac, 0x48ae, 0x48b0, 0x48b3, 0x48b5, 0x48b7, 0x48ba, 0x48bc,
+ 0x48be, 0x48c1, 0x48c3, 0x48c6, 0x48c8, 0x48ca, 0x48cd, 0x48cf,
+ 0x48d2, 0x48d4, 0x48d6, 0x48d9, 0x48db, 0x48de, 0x48e0, 0x48e3,
+ 0x48e5, 0x48e7, 0x48ea, 0x48ec, 0x48ef, 0x48f1, 0x48f4, 0x48f6,
+ 0x48f9, 0x48fb, 0x48fe, 0x4900, 0x4903, 0x4905, 0x4908, 0x490a,
+ 0x490d, 0x490f, 0x4912, 0x4914, 0x4917, 0x4919, 0x491c, 0x491f,
+ 0x4921, 0x4924, 0x4926, 0x4929, 0x492b, 0x492e, 0x4931, 0x4933,
+ 0x4936, 0x4938, 0x493b, 0x493e, 0x4940, 0x4943, 0x4946, 0x4948,
+ 0x494b, 0x494d, 0x4950, 0x4953, 0x4955, 0x4958, 0x495b, 0x495d,
+ 0x4960, 0x4963, 0x4966, 0x4968, 0x496b, 0x496e, 0x4970, 0x4973,
+ 0x4976, 0x4979, 0x497b, 0x497e, 0x4981, 0x4984, 0x4986, 0x4989,
+ 0x498c, 0x498f, 0x4991, 0x4994, 0x4997, 0x499a, 0x499d, 0x499f,
+ 0x49a2, 0x49a5, 0x49a8, 0x49ab, 0x49ad, 0x49b0, 0x49b3, 0x49b6,
+ 0x49b9, 0x49bc, 0x49bf, 0x49c1, 0x49c4, 0x49c7, 0x49ca, 0x49cd,
+ 0x49d0, 0x49d3, 0x49d6, 0x49d9, 0x49dc, 0x49df, 0x49e1, 0x49e4,
+ 0x49e7, 0x49ea, 0x49ed, 0x49f0, 0x49f3, 0x49f6, 0x49f9, 0x49fc,
+ 0x49ff, 0x4a02, 0x4a05, 0x4a08, 0x4a0b, 0x4a0e, 0x4a11, 0x4a14,
+ 0x4a17, 0x4a1a, 0x4a1d, 0x4a21, 0x4a24, 0x4a27, 0x4a2a, 0x4a2d,
+ 0x4a30, 0x4a33, 0x4a36, 0x4a39, 0x4a3c, 0x4a3f, 0x4a43, 0x4a46,
+ 0x4a49, 0x4a4c, 0x4a4f, 0x4a52, 0x4a55, 0x4a59, 0x4a5c, 0x4a5f,
+ 0x4a62, 0x4a65, 0x4a69, 0x4a6c, 0x4a6f, 0x4a72, 0x4a75, 0x4a79,
+ 0x4a7c, 0x4a7f, 0x4a82, 0x4a86, 0x4a89, 0x4a8c, 0x4a8f, 0x4a93,
+ 0x4a96, 0x4a99, 0x4a9d, 0x4aa0, 0x4aa3, 0x4aa7, 0x4aaa, 0x4aad,
+ 0x4ab1, 0x4ab4, 0x4ab7, 0x4abb, 0x4abe, 0x4ac1, 0x4ac5, 0x4ac8,
+ 0x4acc, 0x4acf, 0x4ad2, 0x4ad6, 0x4ad9, 0x4add, 0x4ae0, 0x4ae4,
+ 0x4ae7, 0x4aea, 0x4aee, 0x4af1, 0x4af5, 0x4af8, 0x4afc, 0x4aff,
+ 0x4b03, 0x4b06, 0x4b0a, 0x4b0d, 0x4b11, 0x4b14, 0x4b18, 0x4b1c,
+ 0x4b1f, 0x4b23, 0x4b26, 0x4b2a, 0x4b2d, 0x4b31, 0x4b35, 0x4b38,
+ 0x4b3c, 0x4b3f, 0x4b43, 0x4b47, 0x4b4a, 0x4b4e, 0x4b52, 0x4b55,
+ 0x4b59, 0x4b5d, 0x4b60, 0x4b64, 0x4b68, 0x4b6b, 0x4b6f, 0x4b73,
+ 0x4b77, 0x4b7a, 0x4b7e, 0x4b82, 0x4b86, 0x4b89, 0x4b8d, 0x4b91,
+ 0x4b95, 0x4b98, 0x4b9c, 0x4ba0, 0x4ba4, 0x4ba8, 0x4bac, 0x4baf,
+ 0x4bb3, 0x4bb7, 0x4bbb, 0x4bbf, 0x4bc3, 0x4bc7, 0x4bca, 0x4bce,
+ 0x4bd2, 0x4bd6, 0x4bda, 0x4bde, 0x4be2, 0x4be6, 0x4bea, 0x4bee,
+ 0x4bf2, 0x4bf6, 0x4bfa, 0x4bfe, 0x4c01, 0x4c03, 0x4c05, 0x4c07,
+ 0x4c09, 0x4c0b, 0x4c0d, 0x4c0f, 0x4c11, 0x4c13, 0x4c15, 0x4c17,
+ 0x4c19, 0x4c1b, 0x4c1d, 0x4c1f, 0x4c21, 0x4c23, 0x4c26, 0x4c28,
+ 0x4c2a, 0x4c2c, 0x4c2e, 0x4c30, 0x4c32, 0x4c34, 0x4c36, 0x4c38,
+ 0x4c3a, 0x4c3d, 0x4c3f, 0x4c41, 0x4c43, 0x4c45, 0x4c47, 0x4c49,
+ 0x4c4c, 0x4c4e, 0x4c50, 0x4c52, 0x4c54, 0x4c56, 0x4c58, 0x4c5b,
+ 0x4c5d, 0x4c5f, 0x4c61, 0x4c63, 0x4c66, 0x4c68, 0x4c6a, 0x4c6c,
+ 0x4c6e, 0x4c71, 0x4c73, 0x4c75, 0x4c77, 0x4c7a, 0x4c7c, 0x4c7e,
+ 0x4c80, 0x4c83, 0x4c85, 0x4c87, 0x4c89, 0x4c8c, 0x4c8e, 0x4c90,
+ 0x4c92, 0x4c95, 0x4c97, 0x4c99, 0x4c9c, 0x4c9e, 0x4ca0, 0x4ca3,
+ 0x4ca5, 0x4ca7, 0x4caa, 0x4cac, 0x4cae, 0x4cb1, 0x4cb3, 0x4cb5,
+ 0x4cb8, 0x4cba, 0x4cbc, 0x4cbf, 0x4cc1, 0x4cc3, 0x4cc6, 0x4cc8,
+ 0x4ccb, 0x4ccd, 0x4ccf, 0x4cd2, 0x4cd4, 0x4cd7, 0x4cd9, 0x4cdb,
+ 0x4cde, 0x4ce0, 0x4ce3, 0x4ce5, 0x4ce8, 0x4cea, 0x4ced, 0x4cef,
+ 0x4cf2, 0x4cf4, 0x4cf6, 0x4cf9, 0x4cfb, 0x4cfe, 0x4d00, 0x4d03,
+ 0x4d05, 0x4d08, 0x4d0b, 0x4d0d, 0x4d10, 0x4d12, 0x4d15, 0x4d17,
+ 0x4d1a, 0x4d1c, 0x4d1f, 0x4d21, 0x4d24, 0x4d27, 0x4d29, 0x4d2c,
+ 0x4d2e, 0x4d31, 0x4d33, 0x4d36, 0x4d39, 0x4d3b, 0x4d3e, 0x4d41,
+ 0x4d43, 0x4d46, 0x4d48, 0x4d4b, 0x4d4e, 0x4d50, 0x4d53, 0x4d56,
+ 0x4d58, 0x4d5b, 0x4d5e, 0x4d60, 0x4d63, 0x4d66, 0x4d69, 0x4d6b,
+ 0x4d6e, 0x4d71, 0x4d73, 0x4d76, 0x4d79, 0x4d7c, 0x4d7e, 0x4d81,
+ 0x4d84, 0x4d87, 0x4d89, 0x4d8c, 0x4d8f, 0x4d92, 0x4d94, 0x4d97,
+ 0x4d9a, 0x4d9d, 0x4da0, 0x4da2, 0x4da5, 0x4da8, 0x4dab, 0x4dae,
+ 0x4db1, 0x4db3, 0x4db6, 0x4db9, 0x4dbc, 0x4dbf, 0x4dc2, 0x4dc5,
+ 0x4dc8, 0x4dca, 0x4dcd, 0x4dd0, 0x4dd3, 0x4dd6, 0x4dd9, 0x4ddc,
+ 0x4ddf, 0x4de2, 0x4de5, 0x4de8, 0x4deb, 0x4dee, 0x4df1, 0x4df4,
+ 0x4df7, 0x4dfa, 0x4dfd, 0x4e00, 0x4e03, 0x4e06, 0x4e09, 0x4e0c,
+ 0x4e0f, 0x4e12, 0x4e15, 0x4e18, 0x4e1b, 0x4e1e, 0x4e21, 0x4e24,
+ 0x4e27, 0x4e2a, 0x4e2d, 0x4e30, 0x4e33, 0x4e36, 0x4e3a, 0x4e3d,
+ 0x4e40, 0x4e43, 0x4e46, 0x4e49, 0x4e4c, 0x4e4f, 0x4e53, 0x4e56,
+ 0x4e59, 0x4e5c, 0x4e5f, 0x4e63, 0x4e66, 0x4e69, 0x4e6c, 0x4e6f,
+ 0x4e73, 0x4e76, 0x4e79, 0x4e7c, 0x4e80, 0x4e83, 0x4e86, 0x4e89,
+ 0x4e8d, 0x4e90, 0x4e93, 0x4e96, 0x4e9a, 0x4e9d, 0x4ea0, 0x4ea4,
+ 0x4ea7, 0x4eaa, 0x4eae, 0x4eb1, 0x4eb4, 0x4eb8, 0x4ebb, 0x4ebe,
+ 0x4ec2, 0x4ec5, 0x4ec9, 0x4ecc, 0x4ecf, 0x4ed3, 0x4ed6, 0x4eda,
+ 0x4edd, 0x4ee0, 0x4ee4, 0x4ee7, 0x4eeb, 0x4eee, 0x4ef2, 0x4ef5,
+ 0x4ef9, 0x4efc, 0x4f00, 0x4f03, 0x4f07, 0x4f0a, 0x4f0e, 0x4f11,
+ 0x4f15, 0x4f18, 0x4f1c, 0x4f1f, 0x4f23, 0x4f27, 0x4f2a, 0x4f2e,
+ 0x4f31, 0x4f35, 0x4f39, 0x4f3c, 0x4f40, 0x4f43, 0x4f47, 0x4f4b,
+ 0x4f4e, 0x4f52, 0x4f56, 0x4f59, 0x4f5d, 0x4f61, 0x4f64, 0x4f68,
+ 0x4f6c, 0x4f70, 0x4f73, 0x4f77, 0x4f7b, 0x4f7e, 0x4f82, 0x4f86,
+ 0x4f8a, 0x4f8d, 0x4f91, 0x4f95, 0x4f99, 0x4f9d, 0x4fa0, 0x4fa4,
+ 0x4fa8, 0x4fac, 0x4fb0, 0x4fb4, 0x4fb7, 0x4fbb, 0x4fbf, 0x4fc3,
+ 0x4fc7, 0x4fcb, 0x4fcf, 0x4fd3, 0x4fd7, 0x4fdb, 0x4fde, 0x4fe2,
+ 0x4fe6, 0x4fea, 0x4fee, 0x4ff2, 0x4ff6, 0x4ffa, 0x4ffe, 0x5001,
+ 0x5003, 0x5005, 0x5007, 0x5009, 0x500b, 0x500d, 0x500f, 0x5011,
+ 0x5013, 0x5015, 0x5017, 0x5019, 0x501b, 0x501e, 0x5020, 0x5022,
+ 0x5024, 0x5026, 0x5028, 0x502a, 0x502c, 0x502e, 0x5030, 0x5032,
+ 0x5034, 0x5036, 0x5039, 0x503b, 0x503d, 0x503f, 0x5041, 0x5043,
+ 0x5045, 0x5047, 0x504a, 0x504c, 0x504e, 0x5050, 0x5052, 0x5054,
+ 0x5057, 0x5059, 0x505b, 0x505d, 0x505f, 0x5061, 0x5064, 0x5066,
+ 0x5068, 0x506a, 0x506c, 0x506f, 0x5071, 0x5073, 0x5075, 0x5078,
+ 0x507a, 0x507c, 0x507e, 0x5081, 0x5083, 0x5085, 0x5087, 0x508a,
+ 0x508c, 0x508e, 0x5090, 0x5093, 0x5095, 0x5097, 0x509a, 0x509c,
+ 0x509e, 0x50a0, 0x50a3, 0x50a5, 0x50a7, 0x50aa, 0x50ac, 0x50ae,
+ 0x50b1, 0x50b3, 0x50b5, 0x50b8, 0x50ba, 0x50bd, 0x50bf, 0x50c1,
+ 0x50c4, 0x50c6, 0x50c8, 0x50cb, 0x50cd, 0x50d0, 0x50d2, 0x50d4,
+ 0x50d7, 0x50d9, 0x50dc, 0x50de, 0x50e1, 0x50e3, 0x50e6, 0x50e8,
+ 0x50ea, 0x50ed, 0x50ef, 0x50f2, 0x50f4, 0x50f7, 0x50f9, 0x50fc,
+ 0x50fe, 0x5101, 0x5103, 0x5106, 0x5108, 0x510b, 0x510d, 0x5110,
+ 0x5112, 0x5115, 0x5117, 0x511a, 0x511d, 0x511f, 0x5122, 0x5124,
+ 0x5127, 0x5129, 0x512c, 0x512f, 0x5131, 0x5134, 0x5136, 0x5139,
+ 0x513c, 0x513e, 0x5141, 0x5143, 0x5146, 0x5149, 0x514b, 0x514e,
+ 0x5151, 0x5153, 0x5156, 0x5159, 0x515b, 0x515e, 0x5161, 0x5163,
+ 0x5166, 0x5169, 0x516c, 0x516e, 0x5171, 0x5174, 0x5176, 0x5179,
+ 0x517c, 0x517f, 0x5181, 0x5184, 0x5187, 0x518a, 0x518c, 0x518f,
+ 0x5192, 0x5195, 0x5198, 0x519a, 0x519d, 0x51a0, 0x51a3, 0x51a6,
+ 0x51a8, 0x51ab, 0x51ae, 0x51b1, 0x51b4, 0x51b7, 0x51ba, 0x51bc,
+ 0x51bf, 0x51c2, 0x51c5, 0x51c8, 0x51cb, 0x51ce, 0x51d1, 0x51d3,
+ 0x51d6, 0x51d9, 0x51dc, 0x51df, 0x51e2, 0x51e5, 0x51e8, 0x51eb,
+ 0x51ee, 0x51f1, 0x51f4, 0x51f7, 0x51fa, 0x51fd, 0x5200, 0x5203,
+ 0x5206, 0x5209, 0x520c, 0x520f, 0x5212, 0x5215, 0x5218, 0x521b,
+ 0x521e, 0x5221, 0x5224, 0x5227, 0x522a, 0x522d, 0x5231, 0x5234,
+ 0x5237, 0x523a, 0x523d, 0x5240, 0x5243, 0x5246, 0x524a, 0x524d,
+ 0x5250, 0x5253, 0x5256, 0x5259, 0x525d, 0x5260, 0x5263, 0x5266,
+ 0x5269, 0x526c, 0x5270, 0x5273, 0x5276, 0x5279, 0x527d, 0x5280,
+ 0x5283, 0x5286, 0x528a, 0x528d, 0x5290, 0x5293, 0x5297, 0x529a,
+ 0x529d, 0x52a1, 0x52a4, 0x52a7, 0x52ab, 0x52ae, 0x52b1, 0x52b5,
+ 0x52b8, 0x52bb, 0x52bf, 0x52c2, 0x52c6, 0x52c9, 0x52cc, 0x52d0,
+ 0x52d3, 0x52da, 0x52e1, 0x52e8, 0x52ef, 0x52f6, 0x52fd, 0x5304,
+ 0x530b, 0x5312, 0x5319, 0x5320, 0x5327, 0x532e, 0x5335, 0x533d,
+ 0x5344, 0x534b, 0x5352, 0x535a, 0x5361, 0x5369, 0x5370, 0x5377,
+ 0x537f, 0x5386, 0x538e, 0x5395, 0x539d, 0x53a5, 0x53ac, 0x53b4,
+ 0x53bc, 0x53c4, 0x53cb, 0x53d3, 0x53db, 0x53e3, 0x53eb, 0x53f3,
+ 0x53fb, 0x5401, 0x5405, 0x5409, 0x540d, 0x5411, 0x5416, 0x541a,
+ 0x541e, 0x5422, 0x5426, 0x542a, 0x542e, 0x5433, 0x5437, 0x543b,
+ 0x543f, 0x5443, 0x5448, 0x544c, 0x5450, 0x5455, 0x5459, 0x545d,
+ 0x5462, 0x5466, 0x546a, 0x546f, 0x5473, 0x5478, 0x547c, 0x5481,
+ 0x5485, 0x548a, 0x548e, 0x5493, 0x5498, 0x549c, 0x54a1, 0x54a5,
+ 0x54aa, 0x54af, 0x54b3, 0x54b8, 0x54bd, 0x54c2, 0x54c6, 0x54cb,
+ 0x54d0, 0x54d5, 0x54da, 0x54de, 0x54e3, 0x54e8, 0x54ed, 0x54f2,
+ 0x54f7, 0x54fc, 0x5501, 0x5506, 0x550b, 0x5510, 0x5515, 0x551a,
+ 0x551f, 0x5525, 0x552a, 0x552f, 0x5534, 0x5539, 0x553e, 0x5544,
+ 0x5549, 0x554e, 0x5554, 0x5559, 0x555e, 0x5564, 0x5569, 0x556f,
+ 0x5574, 0x5579, 0x557f, 0x5584, 0x558a, 0x558f, 0x5595, 0x559b,
+ 0x55a0, 0x55a6, 0x55ac, 0x55b1, 0x55b7, 0x55bd, 0x55c2, 0x55c8,
+ 0x55ce, 0x55d4, 0x55da, 0x55e0, 0x55e5, 0x55eb, 0x55f1, 0x55f7,
+ 0x55fd, 0x5603, 0x5609, 0x560f, 0x5615, 0x561b, 0x5622, 0x5628,
+ 0x562e, 0x5634, 0x563a, 0x5640, 0x5647, 0x564d, 0x5653, 0x565a,
+ 0x5660, 0x5666, 0x566d, 0x5673, 0x567a, 0x5680, 0x5687, 0x568d,
+ 0x5694, 0x569a, 0x56a1, 0x56a8, 0x56ae, 0x56b5, 0x56bc, 0x56c3,
+ 0x56c9, 0x56d0, 0x56d7, 0x56de, 0x56e5, 0x56ec, 0x56f3, 0x56f9,
+ 0x5700, 0x5707, 0x570f, 0x5716, 0x571d, 0x5724, 0x572b, 0x5732,
+ 0x5739, 0x5741, 0x5748, 0x574f, 0x5756, 0x575e, 0x5765, 0x576d,
+ 0x5774, 0x577c, 0x5783, 0x578b, 0x5792, 0x579a, 0x57a1, 0x57a9,
+ 0x57b1, 0x57b8, 0x57c0, 0x57c8, 0x57d0, 0x57d7, 0x57df, 0x57e7,
+ 0x57ef, 0x57f7, 0x57ff, 0x5804, 0x5808, 0x580c, 0x5810, 0x5814,
+ 0x5818, 0x581c, 0x5820, 0x5824, 0x5828, 0x582c, 0x5831, 0x5835,
+ 0x5839, 0x583d, 0x5842, 0x5846, 0x584a, 0x584e, 0x5853, 0x5857,
+ 0x585b, 0x5860, 0x5864, 0x5869, 0x586d, 0x5871, 0x5876, 0x587a,
+ 0x587f, 0x5883, 0x5888, 0x588c, 0x5891, 0x5895, 0x589a, 0x589f,
+ 0x58a3, 0x58a8, 0x58ad, 0x58b1, 0x58b6, 0x58bb, 0x58bf, 0x58c4,
+ 0x58c9, 0x58ce, 0x58d3, 0x58d7, 0x58dc, 0x58e1, 0x58e6, 0x58eb,
+ 0x58f0, 0x58f5, 0x58fa, 0x58ff, 0x5904, 0x5909, 0x590e, 0x5913,
+ 0x5918, 0x591d, 0x5922, 0x5927, 0x592d, 0x5932, 0x5937, 0x593c,
+ 0x5941, 0x5947, 0x594c, 0x5951, 0x5957, 0x595c, 0x5961, 0x5967,
+ 0x596c, 0x5972, 0x5977, 0x597c, 0x5982, 0x5987, 0x598d, 0x5993,
+ 0x5998, 0x599e, 0x59a3, 0x59a9, 0x59af, 0x59b4, 0x59ba, 0x59c0,
+ 0x59c6, 0x59cb, 0x59d1, 0x59d7, 0x59dd, 0x59e3, 0x59e9, 0x59ef,
+ 0x59f5, 0x59fa, 0x5a00, 0x5a07, 0x5a0d, 0x5a13, 0x5a19, 0x5a1f,
+ 0x5a25, 0x5a2b, 0x5a31, 0x5a37, 0x5a3e, 0x5a44, 0x5a4a, 0x5a51,
+ 0x5a57, 0x5a5d, 0x5a64, 0x5a6a, 0x5a70, 0x5a77, 0x5a7d, 0x5a84,
+ 0x5a8a, 0x5a91, 0x5a98, 0x5a9e, 0x5aa5, 0x5aab, 0x5ab2, 0x5ab9,
+ 0x5ac0, 0x5ac6, 0x5acd, 0x5ad4, 0x5adb, 0x5ae2, 0x5ae8, 0x5aef,
+ 0x5af6, 0x5afd, 0x5b04, 0x5b0b, 0x5b12, 0x5b1a, 0x5b21, 0x5b28,
+ 0x5b2f, 0x5b36, 0x5b3d, 0x5b45, 0x5b4c, 0x5b53, 0x5b5b, 0x5b62,
+ 0x5b69, 0x5b71, 0x5b78, 0x5b80, 0x5b87, 0x5b8f, 0x5b96, 0x5b9e,
+ 0x5ba6, 0x5bad, 0x5bb5, 0x5bbd, 0x5bc4, 0x5bcc, 0x5bd4, 0x5bdc,
+ 0x5be4, 0x5bec, 0x5bf4, 0x5bfb, 0x5c02, 0x5c06, 0x5c0a, 0x5c0e,
+ 0x5c12, 0x5c16, 0x5c1a, 0x5c1e, 0x5c22, 0x5c26, 0x5c2b, 0x5c2f,
+ 0x5c33, 0x5c37, 0x5c3b, 0x5c40, 0x5c44, 0x5c48, 0x5c4c, 0x5c51,
+ 0x5c55, 0x5c59, 0x5c5e, 0x5c62, 0x5c67, 0x5c6b, 0x5c6f, 0x5c74,
+ 0x5c78, 0x5c7d, 0x5c81, 0x5c86, 0x5c8a, 0x5c8f, 0x5c93, 0x5c98,
+ 0x5c9d, 0x5ca1, 0x5ca6, 0x5cab, 0x5caf, 0x5cb4, 0x5cb9, 0x5cbd,
+ 0x5cc2, 0x5cc7, 0x5ccc, 0x5cd0, 0x5cd5, 0x5cda, 0x5cdf, 0x5ce4,
+ 0x5ce9, 0x5cee, 0x5cf3, 0x5cf8, 0x5cfd, 0x5d02, 0x5d07, 0x5d0c,
+ 0x5d11, 0x5d16, 0x5d1b, 0x5d20, 0x5d25, 0x5d2a, 0x5d2f, 0x5d35,
+ 0x5d3a, 0x5d3f, 0x5d44, 0x5d4a, 0x5d4f, 0x5d54, 0x5d5a, 0x5d5f,
+ 0x5d64, 0x5d6a, 0x5d6f, 0x5d75, 0x5d7a, 0x5d80, 0x5d85, 0x5d8b,
+ 0x5d90, 0x5d96, 0x5d9b, 0x5da1, 0x5da7, 0x5dac, 0x5db2, 0x5db8,
+ 0x5dbd, 0x5dc3, 0x5dc9, 0x5dcf, 0x5dd4, 0x5dda, 0x5de0, 0x5de6,
+ 0x5dec, 0x5df2, 0x5df8, 0x5dfe, 0x5e04, 0x5e0a, 0x5e10, 0x5e16,
+ 0x5e1c, 0x5e22, 0x5e28, 0x5e2f, 0x5e35, 0x5e3b, 0x5e41, 0x5e47,
+ 0x5e4e, 0x5e54, 0x5e5a, 0x5e61, 0x5e67, 0x5e6e, 0x5e74, 0x5e7a,
+ 0x5e81, 0x5e87, 0x5e8e, 0x5e95, 0x5e9b, 0x5ea2, 0x5ea8, 0x5eaf,
+ 0x5eb6, 0x5ebd, 0x5ec3, 0x5eca, 0x5ed1, 0x5ed8, 0x5edf, 0x5ee5,
+ 0x5eec, 0x5ef3, 0x5efa, 0x5f01, 0x5f08, 0x5f0f, 0x5f16, 0x5f1d,
+ 0x5f25, 0x5f2c, 0x5f33, 0x5f3a, 0x5f41, 0x5f49, 0x5f50, 0x5f57,
+ 0x5f5f, 0x5f66, 0x5f6d, 0x5f75, 0x5f7c, 0x5f84, 0x5f8b, 0x5f93,
+ 0x5f9b, 0x5fa2, 0x5faa, 0x5fb1, 0x5fb9, 0x5fc1, 0x5fc9, 0x5fd0,
+ 0x5fd8, 0x5fe0, 0x5fe8, 0x5ff0, 0x5ff8, 0x6000, 0x6004, 0x6008,
+ 0x600c, 0x6010, 0x6014, 0x6018, 0x601c, 0x6020, 0x6025, 0x6029,
+ 0x602d, 0x6031, 0x6035, 0x603a, 0x603e, 0x6042, 0x6046, 0x604b,
+ 0x604f, 0x6053, 0x6057, 0x605c, 0x6060, 0x6065, 0x6069, 0x606d,
+ 0x6072, 0x6076, 0x607b, 0x607f, 0x6084, 0x6088, 0x608d, 0x6091,
+ 0x6096, 0x609b, 0x609f, 0x60a4, 0x60a8, 0x60ad, 0x60b2, 0x60b7,
+ 0x60bb, 0x60c0, 0x60c5, 0x60ca, 0x60ce, 0x60d3, 0x60d8, 0x60dd,
+ 0x60e2, 0x60e7, 0x60eb, 0x60f0, 0x60f5, 0x60fa, 0x60ff, 0x6104,
+ 0x6109, 0x610e, 0x6113, 0x6119, 0x611e, 0x6123, 0x6128, 0x612d,
+ 0x6132, 0x6137, 0x613d, 0x6142, 0x6147, 0x614d, 0x6152, 0x6157,
+ 0x615d, 0x6162, 0x6167, 0x616d, 0x6172, 0x6178, 0x617d, 0x6183,
+ 0x6188, 0x618e, 0x6193, 0x6199, 0x619e, 0x61a4, 0x61aa, 0x61af,
+ 0x61b5, 0x61bb, 0x61c0, 0x61c6, 0x61cc, 0x61d2, 0x61d8, 0x61de,
+ 0x61e3, 0x61e9, 0x61ef, 0x61f5, 0x61fb, 0x6201, 0x6207, 0x620d,
+ 0x6213, 0x6219, 0x621f, 0x6226, 0x622c, 0x6232, 0x6238, 0x623e,
+ 0x6245, 0x624b, 0x6251, 0x6258, 0x625e, 0x6264, 0x626b, 0x6271,
+ 0x6278, 0x627e, 0x6285, 0x628b, 0x6292, 0x6298, 0x629f, 0x62a5,
+ 0x62ac, 0x62b3, 0x62ba, 0x62c0, 0x62c7, 0x62ce, 0x62d5, 0x62db,
+ 0x62e2, 0x62e9, 0x62f0, 0x62f7, 0x62fe, 0x6305, 0x630c, 0x6313,
+ 0x631a, 0x6321, 0x6329, 0x6330, 0x6337, 0x633e, 0x6345, 0x634d,
+ 0x6354, 0x635b, 0x6363, 0x636a, 0x6372, 0x6379, 0x6380, 0x6388,
+ 0x6390, 0x6397, 0x639f, 0x63a6, 0x63ae, 0x63b6, 0x63bd, 0x63c5,
+ 0x63cd, 0x63d5, 0x63dd, 0x63e5, 0x63ec, 0x63f4, 0x63fc, 0x6402,
+ 0x6406, 0x640a, 0x640e, 0x6412, 0x6416, 0x641b, 0x641f, 0x6423,
+ 0x6427, 0x642b, 0x642f, 0x6433, 0x6438, 0x643c, 0x6440, 0x6444,
+ 0x6449, 0x644d, 0x6451, 0x6456, 0x645a, 0x645e, 0x6463, 0x6467,
+ 0x646b, 0x6470, 0x6474, 0x6479, 0x647d, 0x6482, 0x6486, 0x648b,
+ 0x648f, 0x6494, 0x6499, 0x649d, 0x64a2, 0x64a6, 0x64ab, 0x64b0,
+ 0x64b4, 0x64b9, 0x64be, 0x64c3, 0x64c7, 0x64cc, 0x64d1, 0x64d6,
+ 0x64db, 0x64e0, 0x64e4, 0x64e9, 0x64ee, 0x64f3, 0x64f8, 0x64fd,
+ 0x6502, 0x6507, 0x650c, 0x6511, 0x6516, 0x651b, 0x6520, 0x6526,
+ 0x652b, 0x6530, 0x6535, 0x653a, 0x6540, 0x6545, 0x654a, 0x654f,
+ 0x6555, 0x655a, 0x655f, 0x6565, 0x656a, 0x6570, 0x6575, 0x657b,
+ 0x6580, 0x6586, 0x658b, 0x6591, 0x6596, 0x659c, 0x65a1, 0x65a7,
+ 0x65ad, 0x65b2, 0x65b8, 0x65be, 0x65c4, 0x65c9, 0x65cf, 0x65d5,
+ 0x65db, 0x65e1, 0x65e7, 0x65ed, 0x65f3, 0x65f8, 0x65fe, 0x6604,
+ 0x660b, 0x6611, 0x6617, 0x661d, 0x6623, 0x6629, 0x662f, 0x6635,
+ 0x663c, 0x6642, 0x6648, 0x664e, 0x6655, 0x665b, 0x6661, 0x6668,
+ 0x666e, 0x6675, 0x667b, 0x6682, 0x6688, 0x668f, 0x6695, 0x669c,
+ 0x66a2, 0x66a9, 0x66b0, 0x66b7, 0x66bd, 0x66c4, 0x66cb, 0x66d2,
+ 0x66d8, 0x66df, 0x66e6, 0x66ed, 0x66f4, 0x66fb, 0x6702, 0x6709,
+ 0x6710, 0x6717, 0x671e, 0x6725, 0x672d, 0x6734, 0x673b, 0x6742,
+ 0x6749, 0x6751, 0x6758, 0x675f, 0x6767, 0x676e, 0x6776, 0x677d,
+ 0x6785, 0x678c, 0x6794, 0x679b, 0x67a3, 0x67ab, 0x67b2, 0x67ba,
+ 0x67c2, 0x67ca, 0x67d1, 0x67d9, 0x67e1, 0x67e9, 0x67f1, 0x67f9,
+ 0x6800, 0x6804, 0x6808, 0x680c, 0x6811, 0x6815, 0x6819, 0x681d,
+ 0x6821, 0x6825, 0x6829, 0x682d, 0x6832, 0x6836, 0x683a, 0x683e,
+ 0x6842, 0x6847, 0x684b, 0x684f, 0x6854, 0x6858, 0x685c, 0x6861,
+ 0x6865, 0x6869, 0x686e, 0x6872, 0x6877, 0x687b, 0x6880, 0x6884,
+ 0x6889, 0x688d, 0x6892, 0x6896, 0x689b, 0x68a0, 0x68a4, 0x68a9,
+ 0x68ae, 0x68b2, 0x68b7, 0x68bc, 0x68c0, 0x68c5, 0x68ca, 0x68cf,
+ 0x68d4, 0x68d8, 0x68dd, 0x68e2, 0x68e7, 0x68ec, 0x68f1, 0x68f6,
+ 0x68fb, 0x6900, 0x6905, 0x690a, 0x690f, 0x6914, 0x6919, 0x691e,
+ 0x6923, 0x6928, 0x692e, 0x6933, 0x6938, 0x693d, 0x6943, 0x6948,
+ 0x694d, 0x6952, 0x6958, 0x695d, 0x6962, 0x6968, 0x696d, 0x6973,
+ 0x6978, 0x697e, 0x6983, 0x6989, 0x698e, 0x6994, 0x6999, 0x699f,
+ 0x69a5, 0x69aa, 0x69b0, 0x69b6, 0x69bb, 0x69c1, 0x69c7, 0x69cd,
+ 0x69d2, 0x69de, 0x69ea, 0x69f6, 0x6a02, 0x6a0e, 0x6a1a, 0x6a26,
+ 0x6a33, 0x6a3f, 0x6a4c, 0x6a58, 0x6a65, 0x6a72, 0x6a7f, 0x6a8c,
+ 0x6a99, 0x6aa6, 0x6ab4, 0x6ac1, 0x6acf, 0x6adc, 0x6aea, 0x6af8,
+ 0x6b06, 0x6b14, 0x6b22, 0x6b30, 0x6b3f, 0x6b4d, 0x6b5c, 0x6b6b,
+ 0x6b7a, 0x6b89, 0x6b98, 0x6ba7, 0x6bb7, 0x6bc6, 0x6bd6, 0x6be5,
+ 0x6bf5, 0x6c03, 0x6c0b, 0x6c13, 0x6c1b, 0x6c23, 0x6c2c, 0x6c34,
+ 0x6c3c, 0x6c45, 0x6c4d, 0x6c56, 0x6c5f, 0x6c68, 0x6c70, 0x6c79,
+ 0x6c82, 0x6c8b, 0x6c94, 0x6c9e, 0x6ca7, 0x6cb0, 0x6cba, 0x6cc3,
+ 0x6ccd, 0x6cd6, 0x6ce0, 0x6cea, 0x6cf4, 0x6cfe, 0x6d08, 0x6d12,
+ 0x6d1c, 0x6d26, 0x6d31, 0x6d3b, 0x6d45, 0x6d50, 0x6d5b, 0x6d65,
+ 0x6d70, 0x6d7b, 0x6d86, 0x6d91, 0x6d9c, 0x6da8, 0x6db3, 0x6dbf,
+ 0x6dca, 0x6dd6, 0x6de1, 0x6ded, 0x6df9, 0x6e05, 0x6e11, 0x6e1d,
+ 0x6e2a, 0x6e36, 0x6e43, 0x6e4f, 0x6e5c, 0x6e69, 0x6e75, 0x6e82,
+ 0x6e8f, 0x6e9d, 0x6eaa, 0x6eb7, 0x6ec5, 0x6ed2, 0x6ee0, 0x6eee,
+ 0x6efc, 0x6f0a, 0x6f18, 0x6f26, 0x6f34, 0x6f43, 0x6f52, 0x6f60,
+ 0x6f6f, 0x6f7e, 0x6f8d, 0x6f9c, 0x6fab, 0x6fbb, 0x6fca, 0x6fda,
+ 0x6fea, 0x6ffa, 0x7005, 0x700d, 0x7015, 0x701d, 0x7025, 0x702e,
+ 0x7036, 0x703f, 0x7047, 0x7050, 0x7058, 0x7061, 0x706a, 0x7073,
+ 0x707c, 0x7085, 0x708e, 0x7097, 0x70a0, 0x70a9, 0x70b3, 0x70bc,
+ 0x70c6, 0x70cf, 0x70d9, 0x70e3, 0x70ed, 0x70f6, 0x7100, 0x710a,
+ 0x7115, 0x711f, 0x7129, 0x7133, 0x713e, 0x7148, 0x7153, 0x715e,
+ 0x7168, 0x7173, 0x717e, 0x7189, 0x7194, 0x71a0, 0x71ab, 0x71b6,
+ 0x71c2, 0x71cd, 0x71d9, 0x71e5, 0x71f1, 0x71fc, 0x7208, 0x7215,
+ 0x7221, 0x722d, 0x7239, 0x7246, 0x7253, 0x725f, 0x726c, 0x7279,
+ 0x7286, 0x7293, 0x72a0, 0x72ae, 0x72bb, 0x72c8, 0x72d6, 0x72e4,
+ 0x72f2, 0x7300, 0x730e, 0x731c, 0x732a, 0x7338, 0x7347, 0x7356,
+ 0x7364, 0x7373, 0x7382, 0x7391, 0x73a0, 0x73b0, 0x73bf, 0x73cf,
+ 0x73de, 0x73ee, 0x73fe, 0x7407, 0x740f, 0x7417, 0x7420, 0x7428,
+ 0x7430, 0x7439, 0x7441, 0x744a, 0x7452, 0x745b, 0x7464, 0x746c,
+ 0x7475, 0x747e, 0x7487, 0x7490, 0x749a, 0x74a3, 0x74ac, 0x74b5,
+ 0x74bf, 0x74c8, 0x74d2, 0x74dc, 0x74e5, 0x74ef, 0x74f9, 0x7503,
+ 0x750d, 0x7517, 0x7522, 0x752c, 0x7536, 0x7541, 0x754b, 0x7556,
+ 0x7561, 0x756b, 0x7576, 0x7581, 0x758c, 0x7597, 0x75a3, 0x75ae,
+ 0x75b9, 0x75c5, 0x75d1, 0x75dc, 0x75e8, 0x75f4, 0x7600, 0x760c,
+ 0x7618, 0x7624, 0x7631, 0x763d, 0x7649, 0x7656, 0x7663, 0x7670,
+ 0x767d, 0x768a, 0x7697, 0x76a4, 0x76b1, 0x76bf, 0x76cc, 0x76da,
+ 0x76e8, 0x76f6, 0x7703, 0x7712, 0x7720, 0x772e, 0x773c, 0x774b,
+ 0x775a, 0x7768, 0x7777, 0x7786, 0x7795, 0x77a5, 0x77b4, 0x77c3,
+ 0x77d3, 0x77e3, 0x77f3, 0x7801, 0x7809, 0x7811, 0x781a, 0x7822,
+ 0x782a, 0x7832, 0x783b, 0x7843, 0x784c, 0x7855, 0x785d, 0x7866,
+ 0x786f, 0x7878, 0x7881, 0x788a, 0x7893, 0x789c, 0x78a5, 0x78af,
+ 0x78b8, 0x78c2, 0x78cb, 0x78d5, 0x78de, 0x78e8, 0x78f2, 0x78fc,
+ 0x7906, 0x7910, 0x791a, 0x7924, 0x792f, 0x7939, 0x7944, 0x794e,
+ 0x7959, 0x7964, 0x796e, 0x7979, 0x7984, 0x798f, 0x799b, 0x79a6,
+ 0x79b1, 0x79bd, 0x79c8, 0x79d4, 0x79df, 0x79eb, 0x79f7, 0x7a03,
+ 0x7a0f, 0x7a1b, 0x7a28, 0x7a34, 0x7a40, 0x7a4d, 0x7a5a, 0x7a66,
+ 0x7a73, 0x7a80, 0x7a8d, 0x7a9a, 0x7aa8, 0x7ab5, 0x7ac2, 0x7ad0,
+ 0x7ade, 0x7aeb, 0x7af9, 0x7b07, 0x7b16, 0x7b24, 0x7b32, 0x7b41,
+ 0x7b4f, 0x7b5e, 0x7b6d, 0x7b7b, 0x7b8a, 0x7b9a, 0x7ba9, 0x7bb8,
+ 0x7bc8, 0x7bd7, 0x7be7, 0x7bf7, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff, 0x7bff,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00,
+ 0x3c00, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff, 0x3bff,
+ 0x3bff, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe, 0x3bfe,
+ 0x3bfe, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd, 0x3bfd,
+ 0x3bfd, 0x3bfd, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc, 0x3bfc,
+ 0x3bfc, 0x3bfc, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb, 0x3bfb,
+ 0x3bfb, 0x3bfb, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa, 0x3bfa,
+ 0x3bfa, 0x3bfa, 0x3bfa, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9,
+ 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf9, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf8,
+ 0x3bf8, 0x3bf8, 0x3bf8, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf7,
+ 0x3bf7, 0x3bf7, 0x3bf7, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6,
+ 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf6, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5,
+ 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf5, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4,
+ 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf4, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3,
+ 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf3, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2,
+ 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf2, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1, 0x3bf1,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0,
+ 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bf0, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef,
+ 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bef, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee,
+ 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bee, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed,
+ 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bed, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec,
+ 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3bec, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb, 0x3beb,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea, 0x3bea,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9, 0x3be9,
+ 0x3be9, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8, 0x3be8,
+ 0x3be8, 0x3be8, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7, 0x3be7,
+ 0x3be7, 0x3be7, 0x3be7, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be6,
+ 0x3be6, 0x3be6, 0x3be6, 0x3be6, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be5,
+ 0x3be5, 0x3be5, 0x3be5, 0x3be5, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4,
+ 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be4, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3,
+ 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be3, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2,
+ 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be2, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1, 0x3be1,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0,
+ 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0, 0x3be0,
+ 0x3be0, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf,
+ 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf,
+ 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf,
+ 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf, 0x3bdf,
+ 0x3bdf, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde,
+ 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde,
+ 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde,
+ 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde, 0x3bde,
+ 0x3bde, 0x3bde, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd,
+ 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd,
+ 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd,
+ 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd, 0x3bdd,
+ 0x3bdd, 0x3bdd, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc,
+ 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc,
+ 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc,
+ 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdc,
+ 0x3bdc, 0x3bdc, 0x3bdc, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb,
+ 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb,
+ 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb,
+ 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb,
+ 0x3bdb, 0x3bdb, 0x3bdb, 0x3bdb, 0x3bda, 0x3bda, 0x3bda, 0x3bda,
+ 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda,
+ 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda,
+ 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bda,
+ 0x3bda, 0x3bda, 0x3bda, 0x3bda, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9,
+ 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9,
+ 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9,
+ 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9,
+ 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd9, 0x3bd8, 0x3bd8, 0x3bd8,
+ 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8,
+ 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8,
+ 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8,
+ 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd8, 0x3bd7, 0x3bd7, 0x3bd7,
+ 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7,
+ 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7,
+ 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7,
+ 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd7, 0x3bd6, 0x3bd6,
+ 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6,
+ 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6,
+ 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6,
+ 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd6, 0x3bd5,
+ 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5,
+ 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5,
+ 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5,
+ 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd5, 0x3bd4,
+ 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4,
+ 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4,
+ 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4,
+ 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4, 0x3bd4,
+ 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3,
+ 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3,
+ 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3,
+ 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3, 0x3bd3,
+ 0x3bd3, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2,
+ 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2,
+ 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2,
+ 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2, 0x3bd2,
+ 0x3bd2, 0x3bd2, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1,
+ 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1,
+ 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1,
+ 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1, 0x3bd1,
+ 0x3bd1, 0x3bd1, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0,
+ 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0,
+ 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0,
+ 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0, 0x3bd0,
+ 0x3bd0, 0x3bd0, 0x3bd0, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf,
+ 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf,
+ 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf,
+ 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf,
+ 0x3bcf, 0x3bcf, 0x3bcf, 0x3bcf, 0x3bce, 0x3bce, 0x3bce, 0x3bce,
+ 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce,
+ 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce,
+ 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce,
+ 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bce, 0x3bcd, 0x3bcd, 0x3bcd,
+ 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd,
+ 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd,
+ 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd,
+ 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcd, 0x3bcc, 0x3bcc,
+ 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc,
+ 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc,
+ 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc,
+ 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcc, 0x3bcb, 0x3bcb,
+ 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb,
+ 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb,
+ 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb,
+ 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bcb, 0x3bca,
+ 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca,
+ 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca,
+ 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca,
+ 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca, 0x3bca,
+ 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9,
+ 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9,
+ 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9,
+ 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9, 0x3bc9,
+ 0x3bc9, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8,
+ 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8,
+ 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8,
+ 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8,
+ 0x3bc8, 0x3bc8, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7,
+ 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7,
+ 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7,
+ 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc7,
+ 0x3bc7, 0x3bc7, 0x3bc7, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6,
+ 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6,
+ 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6,
+ 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6,
+ 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc6, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5,
+ 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5,
+ 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5,
+ 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5,
+ 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc5, 0x3bc4, 0x3bc4, 0x3bc4,
+ 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4,
+ 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4,
+ 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4,
+ 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc4, 0x3bc3, 0x3bc3,
+ 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3,
+ 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3,
+ 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3,
+ 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc3, 0x3bc2,
+ 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2,
+ 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2,
+ 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2,
+ 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2, 0x3bc2,
+ 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1,
+ 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1,
+ 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1, 0x3bc1,
+ 0x3bc1, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0,
+ 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0, 0x3bc0,
+ 0x3bc0, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf,
+ 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf, 0x3bbf,
+ 0x3bbf, 0x3bbf, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe,
+ 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe, 0x3bbe,
+ 0x3bbe, 0x3bbe, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd,
+ 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbd,
+ 0x3bbd, 0x3bbd, 0x3bbd, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc,
+ 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbc,
+ 0x3bbc, 0x3bbc, 0x3bbc, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb,
+ 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb,
+ 0x3bbb, 0x3bbb, 0x3bbb, 0x3bbb, 0x3bba, 0x3bba, 0x3bba, 0x3bba,
+ 0x3bba, 0x3bba, 0x3bba, 0x3bba, 0x3bba, 0x3bba, 0x3bba, 0x3bba,
+ 0x3bba, 0x3bba, 0x3bba, 0x3bba, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9,
+ 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9,
+ 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb9, 0x3bb8, 0x3bb8, 0x3bb8,
+ 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8,
+ 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb8, 0x3bb7, 0x3bb7,
+ 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7,
+ 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb7, 0x3bb6, 0x3bb6,
+ 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6,
+ 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb6, 0x3bb5,
+ 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5,
+ 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb5, 0x3bb4,
+ 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4,
+ 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4, 0x3bb4,
+ 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3,
+ 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3, 0x3bb3,
+ 0x3bb3, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2,
+ 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2, 0x3bb2,
+ 0x3bb2, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1,
+ 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1, 0x3bb1,
+ 0x3bb1, 0x3bb1, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0,
+ 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0, 0x3bb0,
+ 0x3bb0, 0x3bb0, 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf,
+ 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf, 0x3baf,
+ 0x3baf, 0x3baf, 0x3baf, 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bae,
+ 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bae,
+ 0x3bae, 0x3bae, 0x3bae, 0x3bae, 0x3bad, 0x3bad, 0x3bad, 0x3bad,
+ 0x3bad, 0x3bad, 0x3bad, 0x3bad, 0x3bad, 0x3bad, 0x3bad, 0x3bad,
+ 0x3bad, 0x3bad, 0x3bad, 0x3bad, 0x3bac, 0x3bac, 0x3bac, 0x3bac,
+ 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bac,
+ 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bac, 0x3bab, 0x3bab, 0x3bab,
+ 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab,
+ 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3bab, 0x3baa, 0x3baa,
+ 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa,
+ 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3baa, 0x3ba9,
+ 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9,
+ 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba9, 0x3ba8,
+ 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8,
+ 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8, 0x3ba8,
+ 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7,
+ 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7, 0x3ba7,
+ 0x3ba7, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6,
+ 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6, 0x3ba6,
+ 0x3ba6, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5,
+ 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5, 0x3ba5,
+ 0x3ba5, 0x3ba5, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4,
+ 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba4,
+ 0x3ba4, 0x3ba4, 0x3ba4, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3,
+ 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3,
+ 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba3, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2,
+ 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2,
+ 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1,
+ 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1,
+ 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba1, 0x3ba0, 0x3ba0, 0x3ba0,
+ 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0,
+ 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3ba0, 0x3b9f, 0x3b9f,
+ 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f,
+ 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9f, 0x3b9e,
+ 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e,
+ 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e, 0x3b9e,
+ 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d,
+ 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d, 0x3b9d,
+ 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c,
+ 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c, 0x3b9c,
+ 0x3b9c, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b,
+ 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b, 0x3b9b,
+ 0x3b9b, 0x3b9b, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a,
+ 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a, 0x3b9a,
+ 0x3b9a, 0x3b9a, 0x3b9a, 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b99,
+ 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b99,
+ 0x3b99, 0x3b99, 0x3b99, 0x3b99, 0x3b98, 0x3b98, 0x3b98, 0x3b98,
+ 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b98,
+ 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b98, 0x3b97, 0x3b97, 0x3b97,
+ 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97,
+ 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b97, 0x3b96, 0x3b96,
+ 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96,
+ 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b96, 0x3b95, 0x3b95,
+ 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95,
+ 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b95, 0x3b94,
+ 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94,
+ 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94, 0x3b94,
+ 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93,
+ 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93, 0x3b93,
+ 0x3b93, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92,
+ 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92, 0x3b92,
+ 0x3b92, 0x3b92, 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91,
+ 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91, 0x3b91,
+ 0x3b91, 0x3b91, 0x3b91, 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b90,
+ 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b90,
+ 0x3b90, 0x3b90, 0x3b90, 0x3b90, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f,
+ 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f,
+ 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8f, 0x3b8e, 0x3b8e, 0x3b8e,
+ 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e,
+ 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8e, 0x3b8d, 0x3b8d,
+ 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d,
+ 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8d, 0x3b8c,
+ 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c,
+ 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c, 0x3b8c,
+ 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b,
+ 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b, 0x3b8b,
+ 0x3b8b, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a,
+ 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a, 0x3b8a,
+ 0x3b8a, 0x3b8a, 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89,
+ 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89, 0x3b89,
+ 0x3b89, 0x3b89, 0x3b89, 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b88,
+ 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b88,
+ 0x3b88, 0x3b88, 0x3b88, 0x3b88, 0x3b87, 0x3b87, 0x3b87, 0x3b87,
+ 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b87,
+ 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b87, 0x3b86, 0x3b86, 0x3b86,
+ 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86,
+ 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b86, 0x3b85, 0x3b85,
+ 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85,
+ 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b85, 0x3b84,
+ 0x3b84, 0x3b84, 0x3b84, 0x3b84, 0x3b84, 0x3b84, 0x3b84, 0x3b84,
+ 0x3b84, 0x3b84, 0x3b84, 0x3b84, 0x3b83, 0x3b83, 0x3b83, 0x3b83,
+ 0x3b83, 0x3b83, 0x3b83, 0x3b83, 0x3b83, 0x3b82, 0x3b82, 0x3b82,
+ 0x3b82, 0x3b82, 0x3b82, 0x3b82, 0x3b82, 0x3b81, 0x3b81, 0x3b81,
+ 0x3b81, 0x3b81, 0x3b81, 0x3b81, 0x3b81, 0x3b81, 0x3b80, 0x3b80,
+ 0x3b80, 0x3b80, 0x3b80, 0x3b80, 0x3b80, 0x3b80, 0x3b7f, 0x3b7f,
+ 0x3b7f, 0x3b7f, 0x3b7f, 0x3b7f, 0x3b7f, 0x3b7f, 0x3b7f, 0x3b7e,
+ 0x3b7e, 0x3b7e, 0x3b7e, 0x3b7e, 0x3b7e, 0x3b7e, 0x3b7e, 0x3b7d,
+ 0x3b7d, 0x3b7d, 0x3b7d, 0x3b7d, 0x3b7d, 0x3b7d, 0x3b7d, 0x3b7d,
+ 0x3b7c, 0x3b7c, 0x3b7c, 0x3b7c, 0x3b7c, 0x3b7c, 0x3b7c, 0x3b7c,
+ 0x3b7b, 0x3b7b, 0x3b7b, 0x3b7b, 0x3b7b, 0x3b7b, 0x3b7b, 0x3b7b,
+ 0x3b7b, 0x3b7a, 0x3b7a, 0x3b7a, 0x3b7a, 0x3b7a, 0x3b7a, 0x3b7a,
+ 0x3b7a, 0x3b79, 0x3b79, 0x3b79, 0x3b79, 0x3b79, 0x3b79, 0x3b79,
+ 0x3b79, 0x3b79, 0x3b78, 0x3b78, 0x3b78, 0x3b78, 0x3b78, 0x3b78,
+ 0x3b78, 0x3b78, 0x3b78, 0x3b77, 0x3b77, 0x3b77, 0x3b77, 0x3b77,
+ 0x3b77, 0x3b77, 0x3b77, 0x3b76, 0x3b76, 0x3b76, 0x3b76, 0x3b76,
+ 0x3b76, 0x3b76, 0x3b76, 0x3b76, 0x3b75, 0x3b75, 0x3b75, 0x3b75,
+ 0x3b75, 0x3b75, 0x3b75, 0x3b75, 0x3b74, 0x3b74, 0x3b74, 0x3b74,
+ 0x3b74, 0x3b74, 0x3b74, 0x3b74, 0x3b74, 0x3b73, 0x3b73, 0x3b73,
+ 0x3b73, 0x3b73, 0x3b73, 0x3b73, 0x3b73, 0x3b73, 0x3b72, 0x3b72,
+ 0x3b72, 0x3b72, 0x3b72, 0x3b72, 0x3b72, 0x3b72, 0x3b71, 0x3b71,
+ 0x3b71, 0x3b71, 0x3b71, 0x3b71, 0x3b71, 0x3b71, 0x3b71, 0x3b70,
+ 0x3b70, 0x3b70, 0x3b70, 0x3b70, 0x3b70, 0x3b70, 0x3b70, 0x3b6f,
+ 0x3b6f, 0x3b6f, 0x3b6f, 0x3b6f, 0x3b6f, 0x3b6f, 0x3b6f, 0x3b6f,
+ 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e, 0x3b6e,
+ 0x3b6e, 0x3b6d, 0x3b6d, 0x3b6d, 0x3b6d, 0x3b6d, 0x3b6d, 0x3b6d,
+ 0x3b6d, 0x3b6c, 0x3b6c, 0x3b6c, 0x3b6c, 0x3b6c, 0x3b6c, 0x3b6c,
+ 0x3b6c, 0x3b6c, 0x3b6b, 0x3b6b, 0x3b6b, 0x3b6b, 0x3b6b, 0x3b6b,
+ 0x3b6b, 0x3b6b, 0x3b6a, 0x3b6a, 0x3b6a, 0x3b6a, 0x3b6a, 0x3b6a,
+ 0x3b6a, 0x3b6a, 0x3b6a, 0x3b69, 0x3b69, 0x3b69, 0x3b69, 0x3b69,
+ 0x3b69, 0x3b69, 0x3b69, 0x3b69, 0x3b68, 0x3b68, 0x3b68, 0x3b68,
+ 0x3b68, 0x3b68, 0x3b68, 0x3b68, 0x3b67, 0x3b67, 0x3b67, 0x3b67,
+ 0x3b67, 0x3b67, 0x3b67, 0x3b67, 0x3b67, 0x3b66, 0x3b66, 0x3b66,
+ 0x3b66, 0x3b66, 0x3b66, 0x3b66, 0x3b66, 0x3b66, 0x3b65, 0x3b65,
+ 0x3b65, 0x3b65, 0x3b65, 0x3b65, 0x3b65, 0x3b65, 0x3b64, 0x3b64,
+ 0x3b64, 0x3b64, 0x3b64, 0x3b64, 0x3b64, 0x3b64, 0x3b64, 0x3b63,
+ 0x3b63, 0x3b63, 0x3b63, 0x3b63, 0x3b63, 0x3b63, 0x3b63, 0x3b63,
+ 0x3b62, 0x3b62, 0x3b62, 0x3b62, 0x3b62, 0x3b62, 0x3b62, 0x3b62,
+ 0x3b61, 0x3b61, 0x3b61, 0x3b61, 0x3b61, 0x3b61, 0x3b61, 0x3b61,
+ 0x3b61, 0x3b60, 0x3b60, 0x3b60, 0x3b60, 0x3b60, 0x3b60, 0x3b60,
+ 0x3b60, 0x3b60, 0x3b5f, 0x3b5f, 0x3b5f, 0x3b5f, 0x3b5f, 0x3b5f,
+ 0x3b5f, 0x3b5f, 0x3b5e, 0x3b5e, 0x3b5e, 0x3b5e, 0x3b5e, 0x3b5e,
+ 0x3b5e, 0x3b5e, 0x3b5e, 0x3b5d, 0x3b5d, 0x3b5d, 0x3b5d, 0x3b5d,
+ 0x3b5d, 0x3b5d, 0x3b5d, 0x3b5d, 0x3b5c, 0x3b5c, 0x3b5c, 0x3b5c,
+ 0x3b5c, 0x3b5c, 0x3b5c, 0x3b5c, 0x3b5b, 0x3b5b, 0x3b5b, 0x3b5b,
+ 0x3b5b, 0x3b5b, 0x3b5b, 0x3b5b, 0x3b5b, 0x3b5a, 0x3b5a, 0x3b5a,
+ 0x3b5a, 0x3b5a, 0x3b5a, 0x3b5a, 0x3b5a, 0x3b5a, 0x3b59, 0x3b59,
+ 0x3b59, 0x3b59, 0x3b59, 0x3b59, 0x3b59, 0x3b59, 0x3b58, 0x3b58,
+ 0x3b58, 0x3b58, 0x3b58, 0x3b58, 0x3b58, 0x3b58, 0x3b58, 0x3b57,
+ 0x3b57, 0x3b57, 0x3b57, 0x3b57, 0x3b57, 0x3b57, 0x3b57, 0x3b57,
+ 0x3b56, 0x3b56, 0x3b56, 0x3b56, 0x3b56, 0x3b56, 0x3b56, 0x3b56,
+ 0x3b56, 0x3b55, 0x3b55, 0x3b55, 0x3b55, 0x3b55, 0x3b55, 0x3b55,
+ 0x3b55, 0x3b54, 0x3b54, 0x3b54, 0x3b54, 0x3b54, 0x3b54, 0x3b54,
+ 0x3b54, 0x3b54, 0x3b53, 0x3b53, 0x3b53, 0x3b53, 0x3b53, 0x3b53,
+ 0x3b53, 0x3b53, 0x3b53, 0x3b52, 0x3b52, 0x3b52, 0x3b52, 0x3b52,
+ 0x3b52, 0x3b52, 0x3b52, 0x3b52, 0x3b51, 0x3b51, 0x3b51, 0x3b51,
+ 0x3b51, 0x3b51, 0x3b51, 0x3b51, 0x3b50, 0x3b50, 0x3b50, 0x3b50,
+ 0x3b50, 0x3b50, 0x3b50, 0x3b50, 0x3b50, 0x3b4f, 0x3b4f, 0x3b4f,
+ 0x3b4f, 0x3b4f, 0x3b4f, 0x3b4f, 0x3b4f, 0x3b4f, 0x3b4e, 0x3b4e,
+ 0x3b4e, 0x3b4e, 0x3b4e, 0x3b4e, 0x3b4e, 0x3b4e, 0x3b4e, 0x3b4d,
+ 0x3b4d, 0x3b4d, 0x3b4d, 0x3b4d, 0x3b4d, 0x3b4d, 0x3b4d, 0x3b4c,
+ 0x3b4c, 0x3b4c, 0x3b4c, 0x3b4c, 0x3b4c, 0x3b4c, 0x3b4c, 0x3b4c,
+ 0x3b4b, 0x3b4b, 0x3b4b, 0x3b4b, 0x3b4b, 0x3b4b, 0x3b4b, 0x3b4b,
+ 0x3b4b, 0x3b4a, 0x3b4a, 0x3b4a, 0x3b4a, 0x3b4a, 0x3b4a, 0x3b4a,
+ 0x3b4a, 0x3b4a, 0x3b49, 0x3b49, 0x3b49, 0x3b49, 0x3b49, 0x3b49,
+ 0x3b49, 0x3b49, 0x3b48, 0x3b48, 0x3b48, 0x3b48, 0x3b48, 0x3b48,
+ 0x3b48, 0x3b48, 0x3b48, 0x3b47, 0x3b47, 0x3b47, 0x3b47, 0x3b47,
+ 0x3b47, 0x3b47, 0x3b47, 0x3b47, 0x3b46, 0x3b46, 0x3b46, 0x3b46,
+ 0x3b46, 0x3b46, 0x3b46, 0x3b46, 0x3b46, 0x3b45, 0x3b45, 0x3b45,
+ 0x3b45, 0x3b45, 0x3b45, 0x3b45, 0x3b45, 0x3b45, 0x3b44, 0x3b44,
+ 0x3b44, 0x3b44, 0x3b44, 0x3b44, 0x3b44, 0x3b44, 0x3b43, 0x3b43,
+ 0x3b43, 0x3b43, 0x3b43, 0x3b43, 0x3b43, 0x3b43, 0x3b43, 0x3b42,
+ 0x3b42, 0x3b42, 0x3b42, 0x3b42, 0x3b42, 0x3b42, 0x3b42, 0x3b42,
+ 0x3b41, 0x3b41, 0x3b41, 0x3b41, 0x3b41, 0x3b41, 0x3b41, 0x3b41,
+ 0x3b41, 0x3b40, 0x3b40, 0x3b40, 0x3b40, 0x3b40, 0x3b40, 0x3b40,
+ 0x3b40, 0x3b40, 0x3b3f, 0x3b3f, 0x3b3f, 0x3b3f, 0x3b3f, 0x3b3f,
+ 0x3b3f, 0x3b3f, 0x3b3f, 0x3b3e, 0x3b3e, 0x3b3e, 0x3b3e, 0x3b3e,
+ 0x3b3e, 0x3b3e, 0x3b3e, 0x3b3d, 0x3b3d, 0x3b3d, 0x3b3d, 0x3b3d,
+ 0x3b3d, 0x3b3d, 0x3b3d, 0x3b3d, 0x3b3c, 0x3b3c, 0x3b3c, 0x3b3c,
+ 0x3b3c, 0x3b3c, 0x3b3c, 0x3b3c, 0x3b3c, 0x3b3b, 0x3b3b, 0x3b3b,
+ 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3b, 0x3b3a, 0x3b3a,
+ 0x3b3a, 0x3b3a, 0x3b3a, 0x3b3a, 0x3b3a, 0x3b3a, 0x3b3a, 0x3b39,
+ 0x3b39, 0x3b39, 0x3b39, 0x3b39, 0x3b39, 0x3b39, 0x3b39, 0x3b39,
+ 0x3b38, 0x3b38, 0x3b38, 0x3b38, 0x3b38, 0x3b38, 0x3b38, 0x3b38,
+ 0x3b38, 0x3b37, 0x3b37, 0x3b37, 0x3b37, 0x3b37, 0x3b37, 0x3b37,
+ 0x3b37, 0x3b36, 0x3b36, 0x3b36, 0x3b36, 0x3b36, 0x3b36, 0x3b36,
+ 0x3b36, 0x3b36, 0x3b35, 0x3b35, 0x3b35, 0x3b35, 0x3b35, 0x3b35,
+ 0x3b35, 0x3b35, 0x3b35, 0x3b34, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
+ 0x3b34, 0x3b34, 0x3b34, 0x3b34, 0x3b33, 0x3b33, 0x3b33, 0x3b33,
+ 0x3b33, 0x3b33, 0x3b33, 0x3b33, 0x3b33, 0x3b32, 0x3b32, 0x3b32,
+ 0x3b32, 0x3b32, 0x3b32, 0x3b32, 0x3b32, 0x3b32, 0x3b31, 0x3b31,
+ 0x3b31, 0x3b31, 0x3b31, 0x3b31, 0x3b31, 0x3b31, 0x3b31, 0x3b30,
+ 0x3b30, 0x3b30, 0x3b30, 0x3b30, 0x3b30, 0x3b30, 0x3b30, 0x3b30,
+ 0x3b2f, 0x3b2f, 0x3b2f, 0x3b2f, 0x3b2f, 0x3b2f, 0x3b2f, 0x3b2f,
+ 0x3b2f, 0x3b2e, 0x3b2e, 0x3b2e, 0x3b2e, 0x3b2e, 0x3b2e, 0x3b2e,
+ 0x3b2e, 0x3b2d, 0x3b2d, 0x3b2d, 0x3b2d, 0x3b2d, 0x3b2d, 0x3b2d,
+ 0x3b2d, 0x3b2d, 0x3b2c, 0x3b2c, 0x3b2c, 0x3b2c, 0x3b2c, 0x3b2c,
+ 0x3b2c, 0x3b2c, 0x3b2c, 0x3b2b, 0x3b2b, 0x3b2b, 0x3b2b, 0x3b2b,
+ 0x3b2b, 0x3b2b, 0x3b2b, 0x3b2b, 0x3b2a, 0x3b2a, 0x3b2a, 0x3b2a,
+ 0x3b2a, 0x3b2a, 0x3b2a, 0x3b2a, 0x3b2a, 0x3b29, 0x3b29, 0x3b29,
+ 0x3b29, 0x3b29, 0x3b29, 0x3b29, 0x3b29, 0x3b29, 0x3b28, 0x3b28,
+ 0x3b28, 0x3b28, 0x3b28, 0x3b28, 0x3b28, 0x3b28, 0x3b28, 0x3b27,
+ 0x3b27, 0x3b27, 0x3b27, 0x3b27, 0x3b27, 0x3b27, 0x3b27, 0x3b27,
+ 0x3b26, 0x3b26, 0x3b26, 0x3b26, 0x3b26, 0x3b26, 0x3b26, 0x3b26,
+ 0x3b26, 0x3b25, 0x3b25, 0x3b25, 0x3b25, 0x3b25, 0x3b25, 0x3b25,
+ 0x3b25, 0x3b25, 0x3b24, 0x3b24, 0x3b24, 0x3b24, 0x3b24, 0x3b24,
+ 0x3b24, 0x3b24, 0x3b24, 0x3b23, 0x3b23, 0x3b23, 0x3b23, 0x3b23,
+ 0x3b23, 0x3b23, 0x3b23, 0x3b23, 0x3b22, 0x3b22, 0x3b22, 0x3b22,
+ 0x3b22, 0x3b22, 0x3b22, 0x3b22, 0x3b22, 0x3b21, 0x3b21, 0x3b21,
+ 0x3b21, 0x3b21, 0x3b21, 0x3b21, 0x3b21, 0x3b21, 0x3b20, 0x3b20,
+ 0x3b20, 0x3b20, 0x3b20, 0x3b20, 0x3b20, 0x3b20, 0x3b20, 0x3b1f,
+ 0x3b1f, 0x3b1f, 0x3b1f, 0x3b1f, 0x3b1f, 0x3b1f, 0x3b1f, 0x3b1f,
+ 0x3b1e, 0x3b1e, 0x3b1e, 0x3b1e, 0x3b1e, 0x3b1e, 0x3b1e, 0x3b1e,
+ 0x3b1e, 0x3b1d, 0x3b1d, 0x3b1d, 0x3b1d, 0x3b1d, 0x3b1d, 0x3b1d,
+ 0x3b1d, 0x3b1d, 0x3b1c, 0x3b1c, 0x3b1c, 0x3b1c, 0x3b1c, 0x3b1c,
+ 0x3b1c, 0x3b1c, 0x3b1c, 0x3b1b, 0x3b1b, 0x3b1b, 0x3b1b, 0x3b1b,
+ 0x3b1b, 0x3b1b, 0x3b1b, 0x3b1b, 0x3b1a, 0x3b1a, 0x3b1a, 0x3b1a,
+ 0x3b1a, 0x3b1a, 0x3b1a, 0x3b1a, 0x3b1a, 0x3b19, 0x3b19, 0x3b19,
+ 0x3b19, 0x3b19, 0x3b19, 0x3b19, 0x3b19, 0x3b19, 0x3b18, 0x3b18,
+ 0x3b18, 0x3b18, 0x3b18, 0x3b18, 0x3b18, 0x3b18, 0x3b18, 0x3b17,
+ 0x3b17, 0x3b17, 0x3b17, 0x3b17, 0x3b17, 0x3b17, 0x3b17, 0x3b17,
+ 0x3b16, 0x3b16, 0x3b16, 0x3b16, 0x3b16, 0x3b16, 0x3b16, 0x3b16,
+ 0x3b16, 0x3b15, 0x3b15, 0x3b15, 0x3b15, 0x3b15, 0x3b15, 0x3b15,
+ 0x3b15, 0x3b15, 0x3b14, 0x3b14, 0x3b14, 0x3b14, 0x3b14, 0x3b14,
+ 0x3b14, 0x3b14, 0x3b14, 0x3b13, 0x3b13, 0x3b13, 0x3b13, 0x3b13,
+ 0x3b13, 0x3b13, 0x3b13, 0x3b13, 0x3b12, 0x3b12, 0x3b12, 0x3b12,
+ 0x3b12, 0x3b12, 0x3b12, 0x3b12, 0x3b12, 0x3b11, 0x3b11, 0x3b11,
+ 0x3b11, 0x3b11, 0x3b11, 0x3b11, 0x3b11, 0x3b11, 0x3b10, 0x3b10,
+ 0x3b10, 0x3b10, 0x3b10, 0x3b10, 0x3b10, 0x3b10, 0x3b10, 0x3b0f,
+ 0x3b0f, 0x3b0f, 0x3b0f, 0x3b0f, 0x3b0e, 0x3b0e, 0x3b0e, 0x3b0e,
+ 0x3b0e, 0x3b0d, 0x3b0d, 0x3b0d, 0x3b0d, 0x3b0c, 0x3b0c, 0x3b0c,
+ 0x3b0c, 0x3b0c, 0x3b0b, 0x3b0b, 0x3b0b, 0x3b0b, 0x3b0b, 0x3b0a,
+ 0x3b0a, 0x3b0a, 0x3b0a, 0x3b09, 0x3b09, 0x3b09, 0x3b09, 0x3b09,
+ 0x3b08, 0x3b08, 0x3b08, 0x3b08, 0x3b07, 0x3b07, 0x3b07, 0x3b07,
+ 0x3b07, 0x3b06, 0x3b06, 0x3b06, 0x3b06, 0x3b05, 0x3b05, 0x3b05,
+ 0x3b05, 0x3b05, 0x3b04, 0x3b04, 0x3b04, 0x3b04, 0x3b03, 0x3b03,
+ 0x3b03, 0x3b03, 0x3b03, 0x3b02, 0x3b02, 0x3b02, 0x3b02, 0x3b02,
+ 0x3b01, 0x3b01, 0x3b01, 0x3b01, 0x3b00, 0x3b00, 0x3b00, 0x3b00,
+ 0x3b00, 0x3aff, 0x3aff, 0x3aff, 0x3aff, 0x3afe, 0x3afe, 0x3afe,
+ 0x3afe, 0x3afe, 0x3afd, 0x3afd, 0x3afd, 0x3afd, 0x3afc, 0x3afc,
+ 0x3afc, 0x3afc, 0x3afc, 0x3afb, 0x3afb, 0x3afb, 0x3afb, 0x3afb,
+ 0x3afa, 0x3afa, 0x3afa, 0x3afa, 0x3af9, 0x3af9, 0x3af9, 0x3af9,
+ 0x3af9, 0x3af8, 0x3af8, 0x3af8, 0x3af8, 0x3af7, 0x3af7, 0x3af7,
+ 0x3af7, 0x3af7, 0x3af6, 0x3af6, 0x3af6, 0x3af6, 0x3af6, 0x3af5,
+ 0x3af5, 0x3af5, 0x3af5, 0x3af4, 0x3af4, 0x3af4, 0x3af4, 0x3af4,
+ 0x3af3, 0x3af3, 0x3af3, 0x3af3, 0x3af2, 0x3af2, 0x3af2, 0x3af2,
+ 0x3af2, 0x3af1, 0x3af1, 0x3af1, 0x3af1, 0x3af1, 0x3af0, 0x3af0,
+ 0x3af0, 0x3af0, 0x3aef, 0x3aef, 0x3aef, 0x3aef, 0x3aef, 0x3aee,
+ 0x3aee, 0x3aee, 0x3aee, 0x3aed, 0x3aed, 0x3aed, 0x3aed, 0x3aed,
+ 0x3aec, 0x3aec, 0x3aec, 0x3aec, 0x3aec, 0x3aeb, 0x3aeb, 0x3aeb,
+ 0x3aeb, 0x3aea, 0x3aea, 0x3aea, 0x3aea, 0x3aea, 0x3ae9, 0x3ae9,
+ 0x3ae9, 0x3ae9, 0x3ae9, 0x3ae8, 0x3ae8, 0x3ae8, 0x3ae8, 0x3ae7,
+ 0x3ae7, 0x3ae7, 0x3ae7, 0x3ae7, 0x3ae6, 0x3ae6, 0x3ae6, 0x3ae6,
+ 0x3ae5, 0x3ae5, 0x3ae5, 0x3ae5, 0x3ae5, 0x3ae4, 0x3ae4, 0x3ae4,
+ 0x3ae4, 0x3ae4, 0x3ae3, 0x3ae3, 0x3ae3, 0x3ae3, 0x3ae2, 0x3ae2,
+ 0x3ae2, 0x3ae2, 0x3ae2, 0x3ae1, 0x3ae1, 0x3ae1, 0x3ae1, 0x3ae1,
+ 0x3ae0, 0x3ae0, 0x3ae0, 0x3ae0, 0x3adf, 0x3adf, 0x3adf, 0x3adf,
+ 0x3adf, 0x3ade, 0x3ade, 0x3ade, 0x3ade, 0x3ade, 0x3add, 0x3add,
+ 0x3add, 0x3add, 0x3adc, 0x3adc, 0x3adc, 0x3adc, 0x3adc, 0x3adb,
+ 0x3adb, 0x3adb, 0x3adb, 0x3adb, 0x3ada, 0x3ada, 0x3ada, 0x3ada,
+ 0x3ad9, 0x3ad9, 0x3ad9, 0x3ad9, 0x3ad9, 0x3ad8, 0x3ad8, 0x3ad8,
+ 0x3ad8, 0x3ad8, 0x3ad7, 0x3ad7, 0x3ad7, 0x3ad7, 0x3ad6, 0x3ad6,
+ 0x3ad6, 0x3ad6, 0x3ad6, 0x3ad5, 0x3ad5, 0x3ad5, 0x3ad5, 0x3ad5,
+ 0x3ad4, 0x3ad4, 0x3ad4, 0x3ad4, 0x3ad3, 0x3ad3, 0x3ad3, 0x3ad3,
+ 0x3ad3, 0x3ad2, 0x3ad2, 0x3ad2, 0x3ad2, 0x3ad2, 0x3ad1, 0x3ad1,
+ 0x3ad1, 0x3ad1, 0x3ad0, 0x3ad0, 0x3ad0, 0x3ad0, 0x3ad0, 0x3acf,
+ 0x3acf, 0x3acf, 0x3acf, 0x3acf, 0x3ace, 0x3ace, 0x3ace, 0x3ace,
+ 0x3ace, 0x3acd, 0x3acd, 0x3acd, 0x3acd, 0x3acc, 0x3acc, 0x3acc,
+ 0x3acc, 0x3acc, 0x3acb, 0x3acb, 0x3acb, 0x3acb, 0x3acb, 0x3aca,
+ 0x3aca, 0x3aca, 0x3aca, 0x3ac9, 0x3ac9, 0x3ac9, 0x3ac9, 0x3ac9,
+ 0x3ac8, 0x3ac8, 0x3ac8, 0x3ac8, 0x3ac8, 0x3ac7, 0x3ac7, 0x3ac7,
+ 0x3ac7, 0x3ac7, 0x3ac6, 0x3ac6, 0x3ac6, 0x3ac6, 0x3ac5, 0x3ac5,
+ 0x3ac5, 0x3ac5, 0x3ac5, 0x3ac4, 0x3ac4, 0x3ac4, 0x3ac4, 0x3ac4,
+ 0x3ac3, 0x3ac3, 0x3ac3, 0x3ac3, 0x3ac2, 0x3ac2, 0x3ac2, 0x3ac2,
+ 0x3ac2, 0x3ac1, 0x3ac1, 0x3ac1, 0x3ac1, 0x3ac1, 0x3ac0, 0x3ac0,
+ 0x3ac0, 0x3ac0, 0x3ac0, 0x3abf, 0x3abf, 0x3abf, 0x3abf, 0x3abe,
+ 0x3abe, 0x3abe, 0x3abe, 0x3abe, 0x3abd, 0x3abd, 0x3abd, 0x3abd,
+ 0x3abd, 0x3abc, 0x3abc, 0x3abc, 0x3abc, 0x3abc, 0x3abb, 0x3abb,
+ 0x3abb, 0x3abb, 0x3aba, 0x3aba, 0x3aba, 0x3aba, 0x3aba, 0x3ab9,
+ 0x3ab9, 0x3ab9, 0x3ab9, 0x3ab9, 0x3ab8, 0x3ab8, 0x3ab8, 0x3ab8,
+ 0x3ab8, 0x3ab7, 0x3ab7, 0x3ab7, 0x3ab7, 0x3ab6, 0x3ab6, 0x3ab6,
+ 0x3ab6, 0x3ab6, 0x3ab5, 0x3ab5, 0x3ab5, 0x3ab5, 0x3ab5, 0x3ab4,
+ 0x3ab4, 0x3ab4, 0x3ab4, 0x3ab4, 0x3ab3, 0x3ab3, 0x3ab3, 0x3ab3,
+ 0x3ab3, 0x3ab2, 0x3ab2, 0x3ab2, 0x3ab2, 0x3ab1, 0x3ab1, 0x3ab1,
+ 0x3ab1, 0x3ab1, 0x3ab0, 0x3ab0, 0x3ab0, 0x3ab0, 0x3ab0, 0x3aaf,
+ 0x3aaf, 0x3aaf, 0x3aaf, 0x3aaf, 0x3aae, 0x3aae, 0x3aae, 0x3aae,
+ 0x3aad, 0x3aad, 0x3aad, 0x3aad, 0x3aad, 0x3aac, 0x3aac, 0x3aac,
+ 0x3aac, 0x3aac, 0x3aab, 0x3aab, 0x3aab, 0x3aab, 0x3aab, 0x3aaa,
+ 0x3aaa, 0x3aaa, 0x3aaa, 0x3aaa, 0x3aa9, 0x3aa9, 0x3aa9, 0x3aa9,
+ 0x3aa8, 0x3aa8, 0x3aa8, 0x3aa8, 0x3aa8, 0x3aa7, 0x3aa7, 0x3aa7,
+ 0x3aa7, 0x3aa7, 0x3aa6, 0x3aa6, 0x3aa6, 0x3aa6, 0x3aa6, 0x3aa5,
+ 0x3aa5, 0x3aa5, 0x3aa5, 0x3aa5, 0x3aa4, 0x3aa4, 0x3aa4, 0x3aa4,
+ 0x3aa4, 0x3aa3, 0x3aa3, 0x3aa3, 0x3aa3, 0x3aa2, 0x3aa2, 0x3aa2,
+ 0x3aa2, 0x3aa2, 0x3aa1, 0x3aa1, 0x3aa1, 0x3aa1, 0x3aa1, 0x3aa0,
+ 0x3aa0, 0x3aa0, 0x3aa0, 0x3aa0, 0x3a9f, 0x3a9f, 0x3a9f, 0x3a9f,
+ 0x3a9f, 0x3a9e, 0x3a9e, 0x3a9e, 0x3a9e, 0x3a9e, 0x3a9d, 0x3a9d,
+ 0x3a9d, 0x3a9d, 0x3a9c, 0x3a9c, 0x3a9c, 0x3a9c, 0x3a9c, 0x3a9b,
+ 0x3a9b, 0x3a9b, 0x3a9b, 0x3a9b, 0x3a9a, 0x3a9a, 0x3a9a, 0x3a9a,
+ 0x3a9a, 0x3a99, 0x3a99, 0x3a99, 0x3a99, 0x3a99, 0x3a98, 0x3a98,
+ 0x3a98, 0x3a98, 0x3a98, 0x3a97, 0x3a97, 0x3a97, 0x3a97, 0x3a96,
+ 0x3a96, 0x3a96, 0x3a96, 0x3a96, 0x3a95, 0x3a95, 0x3a95, 0x3a95,
+ 0x3a95, 0x3a94, 0x3a94, 0x3a94, 0x3a94, 0x3a94, 0x3a93, 0x3a93,
+ 0x3a93, 0x3a93, 0x3a93, 0x3a92, 0x3a92, 0x3a92, 0x3a92, 0x3a92,
+ 0x3a91, 0x3a91, 0x3a91, 0x3a91, 0x3a91, 0x3a90, 0x3a90, 0x3a90,
+ 0x3a90, 0x3a90, 0x3a8f, 0x3a8f, 0x3a8f, 0x3a8f, 0x3a8e, 0x3a8e,
+ 0x3a8e, 0x3a8e, 0x3a8e, 0x3a8d, 0x3a8d, 0x3a8d, 0x3a8d, 0x3a8d,
+ 0x3a8c, 0x3a8c, 0x3a8c, 0x3a8c, 0x3a8c, 0x3a8b, 0x3a8b, 0x3a8b,
+ 0x3a8b, 0x3a8b, 0x3a8a, 0x3a8a, 0x3a8a, 0x3a8a, 0x3a8a, 0x3a89,
+ 0x3a89, 0x3a89, 0x3a89, 0x3a89, 0x3a88, 0x3a88, 0x3a88, 0x3a88,
+ 0x3a88, 0x3a87, 0x3a87, 0x3a87, 0x3a87, 0x3a87, 0x3a86, 0x3a86,
+ 0x3a86, 0x3a86, 0x3a85, 0x3a85, 0x3a85, 0x3a85, 0x3a85, 0x3a84,
+ 0x3a84, 0x3a84, 0x3a84, 0x3a84, 0x3a83, 0x3a83, 0x3a83, 0x3a83,
+ 0x3a83, 0x3a82, 0x3a82, 0x3a82, 0x3a82, 0x3a82, 0x3a81, 0x3a81,
+ 0x3a81, 0x3a81, 0x3a81, 0x3a80, 0x3a80, 0x3a80, 0x3a80, 0x3a80,
+ 0x3a7f, 0x3a7f, 0x3a7f, 0x3a7f, 0x3a7f, 0x3a7e, 0x3a7e, 0x3a7e,
+ 0x3a7e, 0x3a7e, 0x3a7d, 0x3a7d, 0x3a7d, 0x3a7d, 0x3a7d, 0x3a7c,
+ 0x3a7c, 0x3a7c, 0x3a7c, 0x3a7c, 0x3a7b, 0x3a7b, 0x3a7b, 0x3a7b,
+ 0x3a7b, 0x3a7a, 0x3a7a, 0x3a7a, 0x3a7a, 0x3a7a, 0x3a79, 0x3a79,
+ 0x3a79, 0x3a79, 0x3a78, 0x3a78, 0x3a78, 0x3a78, 0x3a78, 0x3a77,
+ 0x3a77, 0x3a77, 0x3a77, 0x3a77, 0x3a76, 0x3a76, 0x3a76, 0x3a76,
+ 0x3a76, 0x3a75, 0x3a75, 0x3a75, 0x3a75, 0x3a75, 0x3a74, 0x3a74,
+ 0x3a74, 0x3a74, 0x3a74, 0x3a73, 0x3a73, 0x3a73, 0x3a73, 0x3a73,
+ 0x3a72, 0x3a72, 0x3a72, 0x3a72, 0x3a72, 0x3a71, 0x3a71, 0x3a71,
+ 0x3a71, 0x3a71, 0x3a70, 0x3a70, 0x3a70, 0x3a70, 0x3a70, 0x3a6f,
+ 0x3a6f, 0x3a6f, 0x3a6f, 0x3a6f, 0x3a6e, 0x3a6e, 0x3a6e, 0x3a6e,
+ 0x3a6e, 0x3a6d, 0x3a6d, 0x3a6d, 0x3a6d, 0x3a6d, 0x3a6c, 0x3a6c,
+ 0x3a6c, 0x3a6c, 0x3a6c, 0x3a6b, 0x3a6b, 0x3a6b, 0x3a6b, 0x3a6b,
+ 0x3a6a, 0x3a6a, 0x3a6a, 0x3a6a, 0x3a6a, 0x3a69, 0x3a69, 0x3a69,
+ 0x3a69, 0x3a69, 0x3a68, 0x3a68, 0x3a68, 0x3a68, 0x3a68, 0x3a67,
+ 0x3a67, 0x3a67, 0x3a67, 0x3a67, 0x3a66, 0x3a66, 0x3a66, 0x3a66,
+ 0x3a66, 0x3a65, 0x3a65, 0x3a65, 0x3a65, 0x3a65, 0x3a64, 0x3a64,
+ 0x3a64, 0x3a64, 0x3a64, 0x3a63, 0x3a63, 0x3a63, 0x3a63, 0x3a63,
+ 0x3a62, 0x3a62, 0x3a62, 0x3a62, 0x3a62, 0x3a61, 0x3a61, 0x3a61,
+ 0x3a61, 0x3a61, 0x3a60, 0x3a60, 0x3a60, 0x3a60, 0x3a60, 0x3a5f,
+ 0x3a5f, 0x3a5f, 0x3a5f, 0x3a5f, 0x3a5e, 0x3a5e, 0x3a5e, 0x3a5e,
+ 0x3a5e, 0x3a5d, 0x3a5d, 0x3a5d, 0x3a5d, 0x3a5d, 0x3a5c, 0x3a5c,
+ 0x3a5c, 0x3a5c, 0x3a5c, 0x3a5b, 0x3a5b, 0x3a5b, 0x3a5b, 0x3a5b,
+ 0x3a5a, 0x3a5a, 0x3a5a, 0x3a5a, 0x3a5a, 0x3a59, 0x3a59, 0x3a59,
+ 0x3a59, 0x3a59, 0x3a58, 0x3a58, 0x3a58, 0x3a58, 0x3a58, 0x3a57,
+ 0x3a57, 0x3a57, 0x3a57, 0x3a57, 0x3a56, 0x3a56, 0x3a56, 0x3a56,
+ 0x3a56, 0x3a55, 0x3a55, 0x3a55, 0x3a55, 0x3a55, 0x3a54, 0x3a54,
+ 0x3a54, 0x3a54, 0x3a54, 0x3a54, 0x3a53, 0x3a53, 0x3a53, 0x3a53,
+ 0x3a53, 0x3a52, 0x3a52, 0x3a52, 0x3a52, 0x3a52, 0x3a51, 0x3a51,
+ 0x3a51, 0x3a51, 0x3a51, 0x3a50, 0x3a50, 0x3a50, 0x3a50, 0x3a50,
+ 0x3a4f, 0x3a4f, 0x3a4f, 0x3a4f, 0x3a4f, 0x3a4e, 0x3a4e, 0x3a4e,
+ 0x3a4e, 0x3a4e, 0x3a4d, 0x3a4d, 0x3a4d, 0x3a4d, 0x3a4d, 0x3a4c,
+ 0x3a4c, 0x3a4c, 0x3a4c, 0x3a4c, 0x3a4b, 0x3a4b, 0x3a4b, 0x3a4b,
+ 0x3a4b, 0x3a4a, 0x3a4a, 0x3a4a, 0x3a4a, 0x3a4a, 0x3a49, 0x3a49,
+ 0x3a49, 0x3a49, 0x3a49, 0x3a48, 0x3a48, 0x3a48, 0x3a48, 0x3a48,
+ 0x3a47, 0x3a47, 0x3a47, 0x3a47, 0x3a47, 0x3a47, 0x3a46, 0x3a46,
+ 0x3a46, 0x3a46, 0x3a46, 0x3a45, 0x3a45, 0x3a45, 0x3a45, 0x3a45,
+ 0x3a44, 0x3a44, 0x3a44, 0x3a44, 0x3a44, 0x3a43, 0x3a43, 0x3a43,
+ 0x3a43, 0x3a43, 0x3a42, 0x3a42, 0x3a42, 0x3a42, 0x3a42, 0x3a41,
+ 0x3a41, 0x3a41, 0x3a41, 0x3a41, 0x3a40, 0x3a40, 0x3a40, 0x3a40,
+ 0x3a40, 0x3a3f, 0x3a3f, 0x3a3f, 0x3a3f, 0x3a3f, 0x3a3e, 0x3a3e,
+ 0x3a3e, 0x3a3e, 0x3a3e, 0x3a3e, 0x3a3d, 0x3a3d, 0x3a3d, 0x3a3d,
+ 0x3a3d, 0x3a3c, 0x3a3c, 0x3a3c, 0x3a3c, 0x3a3c, 0x3a3b, 0x3a3b,
+ 0x3a3b, 0x3a3b, 0x3a3a, 0x3a3a, 0x3a39, 0x3a39, 0x3a39, 0x3a38,
+ 0x3a38, 0x3a37, 0x3a37, 0x3a37, 0x3a36, 0x3a36, 0x3a36, 0x3a35,
+ 0x3a35, 0x3a34, 0x3a34, 0x3a34, 0x3a33, 0x3a33, 0x3a32, 0x3a32,
+ 0x3a32, 0x3a31, 0x3a31, 0x3a31, 0x3a30, 0x3a30, 0x3a2f, 0x3a2f,
+ 0x3a2f, 0x3a2e, 0x3a2e, 0x3a2d, 0x3a2d, 0x3a2d, 0x3a2c, 0x3a2c,
+ 0x3a2b, 0x3a2b, 0x3a2b, 0x3a2a, 0x3a2a, 0x3a2a, 0x3a29, 0x3a29,
+ 0x3a28, 0x3a28, 0x3a28, 0x3a27, 0x3a27, 0x3a26, 0x3a26, 0x3a26,
+ 0x3a25, 0x3a25, 0x3a25, 0x3a24, 0x3a24, 0x3a23, 0x3a23, 0x3a23,
+ 0x3a22, 0x3a22, 0x3a21, 0x3a21, 0x3a21, 0x3a20, 0x3a20, 0x3a20,
+ 0x3a1f, 0x3a1f, 0x3a1e, 0x3a1e, 0x3a1e, 0x3a1d, 0x3a1d, 0x3a1d,
+ 0x3a1c, 0x3a1c, 0x3a1b, 0x3a1b, 0x3a1b, 0x3a1a, 0x3a1a, 0x3a19,
+ 0x3a19, 0x3a19, 0x3a18, 0x3a18, 0x3a18, 0x3a17, 0x3a17, 0x3a16,
+ 0x3a16, 0x3a16, 0x3a15, 0x3a15, 0x3a15, 0x3a14, 0x3a14, 0x3a13,
+ 0x3a13, 0x3a13, 0x3a12, 0x3a12, 0x3a11, 0x3a11, 0x3a11, 0x3a10,
+ 0x3a10, 0x3a10, 0x3a0f, 0x3a0f, 0x3a0e, 0x3a0e, 0x3a0e, 0x3a0d,
+ 0x3a0d, 0x3a0d, 0x3a0c, 0x3a0c, 0x3a0b, 0x3a0b, 0x3a0b, 0x3a0a,
+ 0x3a0a, 0x3a0a, 0x3a09, 0x3a09, 0x3a08, 0x3a08, 0x3a08, 0x3a07,
+ 0x3a07, 0x3a07, 0x3a06, 0x3a06, 0x3a05, 0x3a05, 0x3a05, 0x3a04,
+ 0x3a04, 0x3a04, 0x3a03, 0x3a03, 0x3a02, 0x3a02, 0x3a02, 0x3a01,
+ 0x3a01, 0x3a01, 0x3a00, 0x3a00, 0x39ff, 0x39ff, 0x39ff, 0x39fe,
+ 0x39fe, 0x39fe, 0x39fd, 0x39fd, 0x39fc, 0x39fc, 0x39fc, 0x39fb,
+ 0x39fb, 0x39fb, 0x39fa, 0x39fa, 0x39f9, 0x39f9, 0x39f9, 0x39f8,
+ 0x39f8, 0x39f8, 0x39f7, 0x39f7, 0x39f6, 0x39f6, 0x39f6, 0x39f5,
+ 0x39f5, 0x39f5, 0x39f4, 0x39f4, 0x39f3, 0x39f3, 0x39f3, 0x39f2,
+ 0x39f2, 0x39f2, 0x39f1, 0x39f1, 0x39f0, 0x39f0, 0x39f0, 0x39ef,
+ 0x39ef, 0x39ef, 0x39ee, 0x39ee, 0x39ed, 0x39ed, 0x39ed, 0x39ec,
+ 0x39ec, 0x39ec, 0x39eb, 0x39eb, 0x39eb, 0x39ea, 0x39ea, 0x39e9,
+ 0x39e9, 0x39e9, 0x39e8, 0x39e8, 0x39e8, 0x39e7, 0x39e7, 0x39e6,
+ 0x39e6, 0x39e6, 0x39e5, 0x39e5, 0x39e5, 0x39e4, 0x39e4, 0x39e4,
+ 0x39e3, 0x39e3, 0x39e2, 0x39e2, 0x39e2, 0x39e1, 0x39e1, 0x39e1,
+ 0x39e0, 0x39e0, 0x39df, 0x39df, 0x39df, 0x39de, 0x39de, 0x39de,
+ 0x39dd, 0x39dd, 0x39dd, 0x39dc, 0x39dc, 0x39db, 0x39db, 0x39db,
+ 0x39da, 0x39da, 0x39da, 0x39d9, 0x39d9, 0x39d9, 0x39d8, 0x39d8,
+ 0x39d7, 0x39d7, 0x39d7, 0x39d6, 0x39d6, 0x39d6, 0x39d5, 0x39d5,
+ 0x39d5, 0x39d4, 0x39d4, 0x39d3, 0x39d3, 0x39d3, 0x39d2, 0x39d2,
+ 0x39d2, 0x39d1, 0x39d1, 0x39d1, 0x39d0, 0x39d0, 0x39cf, 0x39cf,
+ 0x39cf, 0x39ce, 0x39ce, 0x39ce, 0x39cd, 0x39cd, 0x39cd, 0x39cc,
+ 0x39cc, 0x39cb, 0x39cb, 0x39cb, 0x39ca, 0x39ca, 0x39ca, 0x39c9,
+ 0x39c9, 0x39c9, 0x39c8, 0x39c8, 0x39c7, 0x39c7, 0x39c7, 0x39c6,
+ 0x39c6, 0x39c6, 0x39c5, 0x39c5, 0x39c5, 0x39c4, 0x39c4, 0x39c3,
+ 0x39c3, 0x39c3, 0x39c2, 0x39c2, 0x39c2, 0x39c1, 0x39c1, 0x39c1,
+ 0x39c0, 0x39c0, 0x39c0, 0x39bf, 0x39bf, 0x39be, 0x39be, 0x39be,
+ 0x39bd, 0x39bd, 0x39bd, 0x39bc, 0x39bc, 0x39bc, 0x39bb, 0x39bb,
+ 0x39bb, 0x39ba, 0x39ba, 0x39b9, 0x39b9, 0x39b9, 0x39b8, 0x39b8,
+ 0x39b8, 0x39b7, 0x39b7, 0x39b7, 0x39b6, 0x39b6, 0x39b5, 0x39b5,
+ 0x39b5, 0x39b4, 0x39b4, 0x39b4, 0x39b3, 0x39b3, 0x39b3, 0x39b2,
+ 0x39b2, 0x39b2, 0x39b1, 0x39b1, 0x39b1, 0x39b0, 0x39b0, 0x39af,
+ 0x39af, 0x39af, 0x39ae, 0x39ae, 0x39ae, 0x39ad, 0x39ad, 0x39ad,
+ 0x39ac, 0x39ac, 0x39ac, 0x39ab, 0x39ab, 0x39aa, 0x39aa, 0x39aa,
+ 0x39a9, 0x39a9, 0x39a9, 0x39a8, 0x39a8, 0x39a8, 0x39a7, 0x39a7,
+ 0x39a7, 0x39a6, 0x39a6, 0x39a6, 0x39a5, 0x39a5, 0x39a4, 0x39a4,
+ 0x39a4, 0x39a3, 0x39a3, 0x39a3, 0x39a2, 0x39a2, 0x39a2, 0x39a1,
+ 0x39a1, 0x39a1, 0x39a0, 0x39a0, 0x39a0, 0x399f, 0x399f, 0x399e,
+ 0x399e, 0x399e, 0x399d, 0x399d, 0x399d, 0x399c, 0x399c, 0x399c,
+ 0x399b, 0x399b, 0x399b, 0x399a, 0x399a, 0x399a, 0x3999, 0x3999,
+ 0x3999, 0x3998, 0x3998, 0x3997, 0x3997, 0x3997, 0x3996, 0x3996,
+ 0x3996, 0x3995, 0x3995, 0x3995, 0x3994, 0x3994, 0x3994, 0x3993,
+ 0x3993, 0x3993, 0x3992, 0x3992, 0x3992, 0x3991, 0x3991, 0x3991,
+ 0x3990, 0x3990, 0x398f, 0x398f, 0x398f, 0x398e, 0x398e, 0x398e,
+ 0x398d, 0x398d, 0x398d, 0x398c, 0x398c, 0x398c, 0x398b, 0x398b,
+ 0x398b, 0x398a, 0x398a, 0x398a, 0x3989, 0x3989, 0x3989, 0x3988,
+ 0x3988, 0x3987, 0x3987, 0x3987, 0x3986, 0x3986, 0x3986, 0x3985,
+ 0x3985, 0x3985, 0x3984, 0x3984, 0x3984, 0x3983, 0x3983, 0x3983,
+ 0x3982, 0x3982, 0x3982, 0x3981, 0x3981, 0x3981, 0x3980, 0x3980,
+ 0x3980, 0x397f, 0x397f, 0x397f, 0x397e, 0x397e, 0x397e, 0x397d,
+ 0x397d, 0x397c, 0x397c, 0x397c, 0x397b, 0x397b, 0x397b, 0x397a,
+ 0x397a, 0x397a, 0x3979, 0x3979, 0x3979, 0x3978, 0x3978, 0x3978,
+ 0x3977, 0x3977, 0x3977, 0x3976, 0x3976, 0x3976, 0x3975, 0x3975,
+ 0x3975, 0x3974, 0x3974, 0x3974, 0x3973, 0x3973, 0x3973, 0x3972,
+ 0x3972, 0x3972, 0x3971, 0x3971, 0x3971, 0x3970, 0x3970, 0x3970,
+ 0x396f, 0x396f, 0x396e, 0x396e, 0x396e, 0x396d, 0x396d, 0x396d,
+ 0x396c, 0x396c, 0x396c, 0x396b, 0x396b, 0x396b, 0x396a, 0x396a,
+ 0x396a, 0x3969, 0x3969, 0x3969, 0x3968, 0x3968, 0x3968, 0x3967,
+ 0x3967, 0x3967, 0x3966, 0x3966, 0x3966, 0x3965, 0x3965, 0x3965,
+ 0x3964, 0x3964, 0x3964, 0x3963, 0x3963, 0x3963, 0x3962, 0x3962,
+ 0x3962, 0x3961, 0x3961, 0x3961, 0x3960, 0x3960, 0x3960, 0x395f,
+ 0x395f, 0x395f, 0x395e, 0x395e, 0x395e, 0x395d, 0x395d, 0x395d,
+ 0x395c, 0x395c, 0x395c, 0x395b, 0x395b, 0x395b, 0x395a, 0x395a,
+ 0x395a, 0x3959, 0x3959, 0x3959, 0x3958, 0x3958, 0x3958, 0x3957,
+ 0x3957, 0x3957, 0x3956, 0x3956, 0x3956, 0x3955, 0x3955, 0x3955,
+ 0x3954, 0x3954, 0x3954, 0x3953, 0x3953, 0x3953, 0x3952, 0x3952,
+ 0x3952, 0x3951, 0x3951, 0x3951, 0x3950, 0x3950, 0x3950, 0x394f,
+ 0x394f, 0x394f, 0x394e, 0x394e, 0x394e, 0x394d, 0x394d, 0x394d,
+ 0x394c, 0x394c, 0x394c, 0x394b, 0x394b, 0x394b, 0x394a, 0x394a,
+ 0x394a, 0x3949, 0x3949, 0x3949, 0x3948, 0x3948, 0x3948, 0x3947,
+ 0x3947, 0x3947, 0x3946, 0x3946, 0x3946, 0x3945, 0x3945, 0x3945,
+ 0x3944, 0x3944, 0x3944, 0x3943, 0x3943, 0x3943, 0x3942, 0x3942,
+ 0x3942, 0x3941, 0x3941, 0x3941, 0x3940, 0x3940, 0x3940, 0x393f,
+ 0x393f, 0x393f, 0x393e, 0x393e, 0x393e, 0x393d, 0x393d, 0x393d,
+ 0x393c, 0x393c, 0x393c, 0x393c, 0x393b, 0x393b, 0x393b, 0x393a,
+ 0x393a, 0x393a, 0x3939, 0x3939, 0x3939, 0x3938, 0x3938, 0x3938,
+ 0x3937, 0x3937, 0x3937, 0x3936, 0x3936, 0x3936, 0x3935, 0x3935,
+ 0x3935, 0x3934, 0x3934, 0x3934, 0x3933, 0x3933, 0x3933, 0x3932,
+ 0x3932, 0x3932, 0x3931, 0x3931, 0x3931, 0x3930, 0x3930, 0x3930,
+ 0x392f, 0x392f, 0x392f, 0x392e, 0x392e, 0x392e, 0x392e, 0x392d,
+ 0x392d, 0x392d, 0x392c, 0x392c, 0x392c, 0x392b, 0x392b, 0x392b,
+ 0x392a, 0x392a, 0x392a, 0x3929, 0x3929, 0x3929, 0x3928, 0x3928,
+ 0x3928, 0x3927, 0x3927, 0x3927, 0x3926, 0x3926, 0x3926, 0x3925,
+ 0x3925, 0x3925, 0x3924, 0x3924, 0x3924, 0x3924, 0x3923, 0x3923,
+ 0x3923, 0x3922, 0x3922, 0x3922, 0x3921, 0x3921, 0x3921, 0x3920,
+ 0x3920, 0x3920, 0x391f, 0x391f, 0x391f, 0x391e, 0x391e, 0x391e,
+ 0x391d, 0x391d, 0x391d, 0x391c, 0x391c, 0x391c, 0x391c, 0x391b,
+ 0x391b, 0x391b, 0x391a, 0x391a, 0x391a, 0x3919, 0x3919, 0x3919,
+ 0x3918, 0x3918, 0x3918, 0x3917, 0x3917, 0x3917, 0x3916, 0x3916,
+ 0x3916, 0x3915, 0x3915, 0x3915, 0x3915, 0x3914, 0x3914, 0x3914,
+ 0x3913, 0x3913, 0x3913, 0x3912, 0x3912, 0x3912, 0x3911, 0x3911,
+ 0x3911, 0x3910, 0x3910, 0x3910, 0x390f, 0x390f, 0x390f, 0x390e,
+ 0x390e, 0x390e, 0x390e, 0x390d, 0x390d, 0x390d, 0x390c, 0x390c,
+ 0x390c, 0x390b, 0x390b, 0x390b, 0x390a, 0x390a, 0x390a, 0x3909,
+ 0x3909, 0x3909, 0x3909, 0x3908, 0x3908, 0x3908, 0x3907, 0x3907,
+ 0x3907, 0x3906, 0x3906, 0x3906, 0x3905, 0x3905, 0x3905, 0x3904,
+ 0x3904, 0x3904, 0x3903, 0x3903, 0x3903, 0x3903, 0x3902, 0x3902,
+ 0x3902, 0x3901, 0x3901, 0x3901, 0x3900, 0x3900, 0x3900, 0x38ff,
+ 0x38ff, 0x38ff, 0x38fe, 0x38fe, 0x38fe, 0x38fe, 0x38fd, 0x38fd,
+ 0x38fd, 0x38fc, 0x38fc, 0x38fc, 0x38fb, 0x38fb, 0x38fb, 0x38fa,
+ 0x38fa, 0x38fa, 0x38f9, 0x38f9, 0x38f9, 0x38f9, 0x38f8, 0x38f8,
+ 0x38f8, 0x38f7, 0x38f7, 0x38f7, 0x38f6, 0x38f6, 0x38f6, 0x38f5,
+ 0x38f5, 0x38f5, 0x38f5, 0x38f4, 0x38f4, 0x38f4, 0x38f3, 0x38f3,
+ 0x38f3, 0x38f2, 0x38f2, 0x38f2, 0x38f1, 0x38f1, 0x38f1, 0x38f1,
+ 0x38f0, 0x38f0, 0x38f0, 0x38ef, 0x38ef, 0x38ef, 0x38ee, 0x38ee,
+ 0x38ee, 0x38ed, 0x38ed, 0x38ed, 0x38ed, 0x38ec, 0x38ec, 0x38ec,
+ 0x38eb, 0x38eb, 0x38eb, 0x38ea, 0x38ea, 0x38ea, 0x38e9, 0x38e9,
+ 0x38e9, 0x38e9, 0x38e8, 0x38e8, 0x38e8, 0x38e7, 0x38e7, 0x38e7,
+ 0x38e6, 0x38e6, 0x38e6, 0x38e5, 0x38e5, 0x38e5, 0x38e5, 0x38e4,
+ 0x38e4, 0x38e4, 0x38e3, 0x38e3, 0x38e3, 0x38e2, 0x38e2, 0x38e2,
+ 0x38e1, 0x38e1, 0x38e1, 0x38e1, 0x38e0, 0x38e0, 0x38e0, 0x38df,
+ 0x38df, 0x38df, 0x38de, 0x38de, 0x38de, 0x38de, 0x38dd, 0x38dd,
+ 0x38dd, 0x38dc, 0x38dc, 0x38dc, 0x38db, 0x38db, 0x38db, 0x38da,
+ 0x38da, 0x38da, 0x38d9, 0x38d8, 0x38d8, 0x38d7, 0x38d7, 0x38d6,
+ 0x38d5, 0x38d5, 0x38d4, 0x38d4, 0x38d3, 0x38d2, 0x38d2, 0x38d1,
+ 0x38d1, 0x38d0, 0x38cf, 0x38cf, 0x38ce, 0x38ce, 0x38cd, 0x38cc,
+ 0x38cc, 0x38cb, 0x38cb, 0x38ca, 0x38c9, 0x38c9, 0x38c8, 0x38c8,
+ 0x38c7, 0x38c6, 0x38c6, 0x38c5, 0x38c5, 0x38c4, 0x38c3, 0x38c3,
+ 0x38c2, 0x38c2, 0x38c1, 0x38c0, 0x38c0, 0x38bf, 0x38bf, 0x38be,
+ 0x38bd, 0x38bd, 0x38bc, 0x38bc, 0x38bb, 0x38ba, 0x38ba, 0x38b9,
+ 0x38b9, 0x38b8, 0x38b7, 0x38b7, 0x38b6, 0x38b6, 0x38b5, 0x38b5,
+ 0x38b4, 0x38b3, 0x38b3, 0x38b2, 0x38b2, 0x38b1, 0x38b0, 0x38b0,
+ 0x38af, 0x38af, 0x38ae, 0x38ae, 0x38ad, 0x38ac, 0x38ac, 0x38ab,
+ 0x38ab, 0x38aa, 0x38a9, 0x38a9, 0x38a8, 0x38a8, 0x38a7, 0x38a7,
+ 0x38a6, 0x38a5, 0x38a5, 0x38a4, 0x38a4, 0x38a3, 0x38a2, 0x38a2,
+ 0x38a1, 0x38a1, 0x38a0, 0x38a0, 0x389f, 0x389e, 0x389e, 0x389d,
+ 0x389d, 0x389c, 0x389c, 0x389b, 0x389a, 0x389a, 0x3899, 0x3899,
+ 0x3898, 0x3897, 0x3897, 0x3896, 0x3896, 0x3895, 0x3895, 0x3894,
+ 0x3893, 0x3893, 0x3892, 0x3892, 0x3891, 0x3891, 0x3890, 0x388f,
+ 0x388f, 0x388e, 0x388e, 0x388d, 0x388d, 0x388c, 0x388c, 0x388b,
+ 0x388a, 0x388a, 0x3889, 0x3889, 0x3888, 0x3888, 0x3887, 0x3886,
+ 0x3886, 0x3885, 0x3885, 0x3884, 0x3884, 0x3883, 0x3882, 0x3882,
+ 0x3881, 0x3881, 0x3880, 0x3880, 0x387f, 0x387f, 0x387e, 0x387d,
+ 0x387d, 0x387c, 0x387c, 0x387b, 0x387b, 0x387a, 0x3879, 0x3879,
+ 0x3878, 0x3878, 0x3877, 0x3877, 0x3876, 0x3876, 0x3875, 0x3874,
+ 0x3874, 0x3873, 0x3873, 0x3872, 0x3872, 0x3871, 0x3871, 0x3870,
+ 0x386f, 0x386f, 0x386e, 0x386e, 0x386d, 0x386d, 0x386c, 0x386c,
+ 0x386b, 0x386a, 0x386a, 0x3869, 0x3869, 0x3868, 0x3868, 0x3867,
+ 0x3867, 0x3866, 0x3866, 0x3865, 0x3864, 0x3864, 0x3863, 0x3863,
+ 0x3862, 0x3862, 0x3861, 0x3861, 0x3860, 0x385f, 0x385f, 0x385e,
+ 0x385e, 0x385d, 0x385d, 0x385c, 0x385c, 0x385b, 0x385b, 0x385a,
+ 0x3859, 0x3859, 0x3858, 0x3858, 0x3857, 0x3857, 0x3856, 0x3856,
+ 0x3855, 0x3855, 0x3854, 0x3854, 0x3853, 0x3852, 0x3852, 0x3851,
+ 0x3851, 0x3850, 0x3850, 0x384f, 0x384f, 0x384e, 0x384e, 0x384d,
+ 0x384d, 0x384c, 0x384b, 0x384b, 0x384a, 0x384a, 0x3849, 0x3849,
+ 0x3848, 0x3848, 0x3847, 0x3847, 0x3846, 0x3846, 0x3845, 0x3844,
+ 0x3844, 0x3843, 0x3843, 0x3842, 0x3842, 0x3841, 0x3841, 0x3840,
+ 0x3840, 0x383f, 0x383f, 0x383e, 0x383e, 0x383d, 0x383d, 0x383c,
+ 0x383b, 0x383b, 0x383a, 0x383a, 0x3839, 0x3839, 0x3838, 0x3838,
+ 0x3837, 0x3837, 0x3836, 0x3836, 0x3835, 0x3835, 0x3834, 0x3834,
+ 0x3833, 0x3832, 0x3832, 0x3831, 0x3831, 0x3830, 0x3830, 0x382f,
+ 0x382f, 0x382e, 0x382e, 0x382d, 0x382d, 0x382c, 0x382c, 0x382b,
+ 0x382b, 0x382a, 0x382a, 0x3829, 0x3829, 0x3828, 0x3828, 0x3827,
+ 0x3826, 0x3826, 0x3825, 0x3825, 0x3824, 0x3824, 0x3823, 0x3823,
+ 0x3822, 0x3822, 0x3821, 0x3821, 0x3820, 0x3820, 0x381f, 0x381f,
+ 0x381e, 0x381e, 0x381d, 0x381d, 0x381c, 0x381c, 0x381b, 0x381b,
+ 0x381a, 0x381a, 0x3819, 0x3819, 0x3818, 0x3818, 0x3817, 0x3817,
+ 0x3816, 0x3816, 0x3815, 0x3814, 0x3814, 0x3813, 0x3813, 0x3812,
+ 0x3812, 0x3811, 0x3811, 0x3810, 0x3810, 0x380f, 0x380f, 0x380e,
+ 0x380e, 0x380d, 0x380d, 0x380c, 0x380c, 0x380b, 0x380b, 0x380a,
+ 0x380a, 0x3809, 0x3809, 0x3808, 0x3808, 0x3807, 0x3807, 0x3806,
+ 0x3806, 0x3805, 0x3805, 0x3804, 0x3804, 0x3803, 0x3803, 0x3802,
+ 0x3802, 0x3801, 0x3801, 0x3800, 0x3800, 0x37ff, 0x37fe, 0x37fd,
+ 0x37fc, 0x37fb, 0x37fa, 0x37f9, 0x37f8, 0x37f7, 0x37f6, 0x37f5,
+ 0x37f4, 0x37f3, 0x37f2, 0x37f1, 0x37f0, 0x37ef, 0x37ee, 0x37ed,
+ 0x37ec, 0x37eb, 0x37ea, 0x37e9, 0x37e8, 0x37e7, 0x37e6, 0x37e5,
+ 0x37e4, 0x37e3, 0x37e2, 0x37e1, 0x37e0, 0x37df, 0x37de, 0x37dd,
+ 0x37dc, 0x37db, 0x37da, 0x37d9, 0x37d8, 0x37d7, 0x37d6, 0x37d5,
+ 0x37d4, 0x37d3, 0x37d2, 0x37d1, 0x37d0, 0x37cf, 0x37ce, 0x37cd,
+ 0x37cc, 0x37cb, 0x37ca, 0x37c9, 0x37c8, 0x37c7, 0x37c6, 0x37c5,
+ 0x37c4, 0x37c3, 0x37c3, 0x37c2, 0x37c1, 0x37c0, 0x37bf, 0x37be,
+ 0x37bd, 0x37bc, 0x37bb, 0x37ba, 0x37b9, 0x37b8, 0x37b7, 0x37b6,
+ 0x37b5, 0x37b4, 0x37b3, 0x37b2, 0x37b1, 0x37b0, 0x37af, 0x37ae,
+ 0x37ad, 0x37ac, 0x37ab, 0x37aa, 0x37a9, 0x37a8, 0x37a8, 0x37a7,
+ 0x37a6, 0x37a5, 0x37a4, 0x37a3, 0x37a2, 0x37a1, 0x37a0, 0x379f,
+ 0x379e, 0x379d, 0x379c, 0x379b, 0x379a, 0x3799, 0x3798, 0x3797,
+ 0x3796, 0x3795, 0x3794, 0x3794, 0x3793, 0x3792, 0x3791, 0x3790,
+ 0x378f, 0x378e, 0x378d, 0x378c, 0x378b, 0x378a, 0x3789, 0x3788,
+ 0x3787, 0x3786, 0x3785, 0x3784, 0x3784, 0x3783, 0x3782, 0x3781,
+ 0x3780, 0x377f, 0x377e, 0x377d, 0x377c, 0x377b, 0x377a, 0x3779,
+ 0x3778, 0x3777, 0x3776, 0x3775, 0x3775, 0x3774, 0x3773, 0x3772,
+ 0x3771, 0x3770, 0x376f, 0x376e, 0x376d, 0x376c, 0x376b, 0x376a,
+ 0x3769, 0x3768, 0x3768, 0x3767, 0x3766, 0x3765, 0x3764, 0x3763,
+ 0x3762, 0x3761, 0x3760, 0x375f, 0x375e, 0x375d, 0x375c, 0x375c,
+ 0x375b, 0x375a, 0x3759, 0x3758, 0x3757, 0x3756, 0x3755, 0x3754,
+ 0x3753, 0x3752, 0x3751, 0x3751, 0x3750, 0x374f, 0x374e, 0x374d,
+ 0x374c, 0x374b, 0x374a, 0x3749, 0x3748, 0x3747, 0x3747, 0x3746,
+ 0x3745, 0x3744, 0x3743, 0x3742, 0x3741, 0x3740, 0x373f, 0x373e,
+ 0x373d, 0x373d, 0x373c, 0x373b, 0x373a, 0x3739, 0x3738, 0x3737,
+ 0x3736, 0x3735, 0x3734, 0x3734, 0x3733, 0x3732, 0x3731, 0x3730,
+ 0x372f, 0x372e, 0x372d, 0x372c, 0x372b, 0x372b, 0x372a, 0x3729,
+ 0x3728, 0x3727, 0x3726, 0x3725, 0x3724, 0x3723, 0x3722, 0x3722,
+ 0x3721, 0x3720, 0x371f, 0x371e, 0x371d, 0x371c, 0x371b, 0x371a,
+ 0x371a, 0x3719, 0x3718, 0x3717, 0x3716, 0x3715, 0x3714, 0x3713,
+ 0x3713, 0x3712, 0x3711, 0x3710, 0x370f, 0x370e, 0x370d, 0x370c,
+ 0x370b, 0x370b, 0x370a, 0x3709, 0x3708, 0x3707, 0x3706, 0x3705,
+ 0x3704, 0x3704, 0x3703, 0x3702, 0x3701, 0x3700, 0x36ff, 0x36fe,
+ 0x36fd, 0x36fd, 0x36fc, 0x36fb, 0x36fa, 0x36f9, 0x36f8, 0x36f7,
+ 0x36f6, 0x36f6, 0x36f5, 0x36f4, 0x36f3, 0x36f2, 0x36f1, 0x36f0,
+ 0x36ef, 0x36ef, 0x36ee, 0x36ed, 0x36ec, 0x36eb, 0x36ea, 0x36e9,
+ 0x36e9, 0x36e8, 0x36e7, 0x36e6, 0x36e5, 0x36e4, 0x36e3, 0x36e3,
+ 0x36e2, 0x36e1, 0x36e0, 0x36df, 0x36de, 0x36dd, 0x36dd, 0x36dc,
+ 0x36db, 0x36da, 0x36d9, 0x36d8, 0x36d7, 0x36d7, 0x36d6, 0x36d5,
+ 0x36d4, 0x36d3, 0x36d2, 0x36d1, 0x36d1, 0x36d0, 0x36cf, 0x36ce,
+ 0x36cd, 0x36cc, 0x36cb, 0x36cb, 0x36ca, 0x36c9, 0x36c8, 0x36c7,
+ 0x36c6, 0x36c6, 0x36c5, 0x36c4, 0x36c3, 0x36c2, 0x36c1, 0x36c0,
+ 0x36c0, 0x36bf, 0x36be, 0x36bd, 0x36bc, 0x36bb, 0x36bb, 0x36ba,
+ 0x36b9, 0x36b8, 0x36b7, 0x36b6, 0x36b6, 0x36b5, 0x36b4, 0x36b3,
+ 0x36b2, 0x36b1, 0x36b0, 0x36b0, 0x36af, 0x36ae, 0x36ad, 0x36ac,
+ 0x36ab, 0x36ab, 0x36aa, 0x36a9, 0x36a8, 0x36a7, 0x36a6, 0x36a6,
+ 0x36a5, 0x36a4, 0x36a3, 0x36a2, 0x36a1, 0x36a1, 0x36a0, 0x369f,
+ 0x369e, 0x369d, 0x369d, 0x369c, 0x369b, 0x369a, 0x3699, 0x3698,
+ 0x3698, 0x3697, 0x3696, 0x3695, 0x3694, 0x3693, 0x3693, 0x3692,
+ 0x3691, 0x3690, 0x368f, 0x368f, 0x368e, 0x368d, 0x368c, 0x368b,
+ 0x368a, 0x368a, 0x3689, 0x3688, 0x3687, 0x3686, 0x3686, 0x3685,
+ 0x3684, 0x3683, 0x3682, 0x3681, 0x3681, 0x3680, 0x367f, 0x367e,
+ 0x367d, 0x367d, 0x367c, 0x367b, 0x367a, 0x3679, 0x3679, 0x3678,
+ 0x3677, 0x3676, 0x3675, 0x3675, 0x3674, 0x3673, 0x3672, 0x3671,
+ 0x3670, 0x3670, 0x366f, 0x366e, 0x366d, 0x366c, 0x366c, 0x366b,
+ 0x366a, 0x3669, 0x3668, 0x3668, 0x3667, 0x3666, 0x3665, 0x3664,
+ 0x3664, 0x3663, 0x3662, 0x3661, 0x3660, 0x3660, 0x365f, 0x365e,
+ 0x365d, 0x365c, 0x365c, 0x365b, 0x365a, 0x3659, 0x3659, 0x3658,
+ 0x3657, 0x3656, 0x3655, 0x3655, 0x3654, 0x3653, 0x3652, 0x3651,
+ 0x3651, 0x3650, 0x364f, 0x364e, 0x364d, 0x364d, 0x364c, 0x364b,
+ 0x364a, 0x364a, 0x3649, 0x3648, 0x3647, 0x3646, 0x3646, 0x3645,
+ 0x3644, 0x3643, 0x3642, 0x3642, 0x3641, 0x3640, 0x363f, 0x363f,
+ 0x363e, 0x363d, 0x363c, 0x363b, 0x363b, 0x363a, 0x3639, 0x3638,
+ 0x3638, 0x3637, 0x3636, 0x3635, 0x3634, 0x3634, 0x3633, 0x3632,
+ 0x3631, 0x3631, 0x3630, 0x362f, 0x362e, 0x362d, 0x362d, 0x362c,
+ 0x362b, 0x362a, 0x362a, 0x3629, 0x3628, 0x3627, 0x3627, 0x3626,
+ 0x3625, 0x3624, 0x3623, 0x3623, 0x3622, 0x3621, 0x3620, 0x3620,
+ 0x361f, 0x361e, 0x361d, 0x361d, 0x361c, 0x361b, 0x361a, 0x361a,
+ 0x3619, 0x3618, 0x3617, 0x3616, 0x3616, 0x3615, 0x3614, 0x3613,
+ 0x3613, 0x3612, 0x3611, 0x3610, 0x3610, 0x360f, 0x360e, 0x360d,
+ 0x360d, 0x360c, 0x360b, 0x360a, 0x360a, 0x3609, 0x3608, 0x3607,
+ 0x3607, 0x3606, 0x3605, 0x3604, 0x3604, 0x3603, 0x3602, 0x3601,
+ 0x3601, 0x3600, 0x35ff, 0x35fe, 0x35fe, 0x35fd, 0x35fc, 0x35fb,
+ 0x35fb, 0x35fa, 0x35f9, 0x35f8, 0x35f8, 0x35f7, 0x35f6, 0x35f5,
+ 0x35f5, 0x35f4, 0x35f3, 0x35f2, 0x35f2, 0x35f1, 0x35f0, 0x35ef,
+ 0x35ef, 0x35ee, 0x35ed, 0x35ec, 0x35ec, 0x35eb, 0x35ea, 0x35e9,
+ 0x35e9, 0x35e8, 0x35e7, 0x35e7, 0x35e6, 0x35e5, 0x35e4, 0x35e4,
+ 0x35e3, 0x35e1, 0x35e0, 0x35de, 0x35dd, 0x35db, 0x35da, 0x35d9,
+ 0x35d7, 0x35d6, 0x35d4, 0x35d3, 0x35d1, 0x35d0, 0x35ce, 0x35cd,
+ 0x35cb, 0x35ca, 0x35c9, 0x35c7, 0x35c6, 0x35c4, 0x35c3, 0x35c1,
+ 0x35c0, 0x35be, 0x35bd, 0x35bc, 0x35ba, 0x35b9, 0x35b7, 0x35b6,
+ 0x35b4, 0x35b3, 0x35b2, 0x35b0, 0x35af, 0x35ad, 0x35ac, 0x35ab,
+ 0x35a9, 0x35a8, 0x35a6, 0x35a5, 0x35a3, 0x35a2, 0x35a1, 0x359f,
+ 0x359e, 0x359c, 0x359b, 0x359a, 0x3598, 0x3597, 0x3595, 0x3594,
+ 0x3593, 0x3591, 0x3590, 0x358e, 0x358d, 0x358c, 0x358a, 0x3589,
+ 0x3588, 0x3586, 0x3585, 0x3583, 0x3582, 0x3581, 0x357f, 0x357e,
+ 0x357d, 0x357b, 0x357a, 0x3578, 0x3577, 0x3576, 0x3574, 0x3573,
+ 0x3572, 0x3570, 0x356f, 0x356e, 0x356c, 0x356b, 0x3569, 0x3568,
+ 0x3567, 0x3565, 0x3564, 0x3563, 0x3561, 0x3560, 0x355f, 0x355d,
+ 0x355c, 0x355b, 0x3559, 0x3558, 0x3557, 0x3555, 0x3554, 0x3553,
+ 0x3551, 0x3550, 0x354f, 0x354d, 0x354c, 0x354b, 0x3549, 0x3548,
+ 0x3547, 0x3545, 0x3544, 0x3543, 0x3541, 0x3540, 0x353f, 0x353e,
+ 0x353c, 0x353b, 0x353a, 0x3538, 0x3537, 0x3536, 0x3534, 0x3533,
+ 0x3532, 0x3530, 0x352f, 0x352e, 0x352d, 0x352b, 0x352a, 0x3529,
+ 0x3527, 0x3526, 0x3525, 0x3524, 0x3522, 0x3521, 0x3520, 0x351e,
+ 0x351d, 0x351c, 0x351b, 0x3519, 0x3518, 0x3517, 0x3516, 0x3514,
+ 0x3513, 0x3512, 0x3510, 0x350f, 0x350e, 0x350d, 0x350b, 0x350a,
+ 0x3509, 0x3508, 0x3506, 0x3505, 0x3504, 0x3503, 0x3501, 0x3500,
+ 0x34ff, 0x34fe, 0x34fc, 0x34fb, 0x34fa, 0x34f9, 0x34f7, 0x34f6,
+ 0x34f5, 0x34f4, 0x34f2, 0x34f1, 0x34f0, 0x34ef, 0x34ed, 0x34ec,
+ 0x34eb, 0x34ea, 0x34e9, 0x34e7, 0x34e6, 0x34e5, 0x34e4, 0x34e2,
+ 0x34e1, 0x34e0, 0x34df, 0x34de, 0x34dc, 0x34db, 0x34da, 0x34d9,
+ 0x34d7, 0x34d6, 0x34d5, 0x34d4, 0x34d3, 0x34d1, 0x34d0, 0x34cf,
+ 0x34ce, 0x34cd, 0x34cb, 0x34ca, 0x34c9, 0x34c8, 0x34c7, 0x34c5,
+ 0x34c4, 0x34c3, 0x34c2, 0x34c1, 0x34c0, 0x34be, 0x34bd, 0x34bc,
+ 0x34bb, 0x34ba, 0x34b8, 0x34b7, 0x34b6, 0x34b5, 0x34b4, 0x34b3,
+ 0x34b1, 0x34b0, 0x34af, 0x34ae, 0x34ad, 0x34ac, 0x34aa, 0x34a9,
+ 0x34a8, 0x34a7, 0x34a6, 0x34a5, 0x34a3, 0x34a2, 0x34a1, 0x34a0,
+ 0x349f, 0x349e, 0x349c, 0x349b, 0x349a, 0x3499, 0x3498, 0x3497,
+ 0x3496, 0x3494, 0x3493, 0x3492, 0x3491, 0x3490, 0x348f, 0x348e,
+ 0x348c, 0x348b, 0x348a, 0x3489, 0x3488, 0x3487, 0x3486, 0x3484,
+ 0x3483, 0x3482, 0x3481, 0x3480, 0x347f, 0x347e, 0x347d, 0x347b,
+ 0x347a, 0x3479, 0x3478, 0x3477, 0x3476, 0x3475, 0x3474, 0x3473,
+ 0x3471, 0x3470, 0x346f, 0x346e, 0x346d, 0x346c, 0x346b, 0x346a,
+ 0x3469, 0x3467, 0x3466, 0x3465, 0x3464, 0x3463, 0x3462, 0x3461,
+ 0x3460, 0x345f, 0x345e, 0x345d, 0x345b, 0x345a, 0x3459, 0x3458,
+ 0x3457, 0x3456, 0x3455, 0x3454, 0x3453, 0x3452, 0x3451, 0x3450,
+ 0x344e, 0x344d, 0x344c, 0x344b, 0x344a, 0x3449, 0x3448, 0x3447,
+ 0x3446, 0x3445, 0x3444, 0x3443, 0x3442, 0x3441, 0x343f, 0x343e,
+ 0x343d, 0x343c, 0x343b, 0x343a, 0x3439, 0x3438, 0x3437, 0x3436,
+ 0x3435, 0x3434, 0x3433, 0x3432, 0x3431, 0x3430, 0x342f, 0x342e,
+ 0x342d, 0x342b, 0x342a, 0x3429, 0x3428, 0x3427, 0x3426, 0x3425,
+ 0x3424, 0x3423, 0x3422, 0x3421, 0x3420, 0x341f, 0x341e, 0x341d,
+ 0x341c, 0x341b, 0x341a, 0x3419, 0x3418, 0x3417, 0x3416, 0x3415,
+ 0x3414, 0x3413, 0x3412, 0x3411, 0x3410, 0x340f, 0x340e, 0x340d,
+ 0x340c, 0x340b, 0x340a, 0x3409, 0x3408, 0x3407, 0x3406, 0x3405,
+ 0x3404, 0x3403, 0x3402, 0x3401, 0x33ff, 0x33fd, 0x33fb, 0x33f9,
+ 0x33f7, 0x33f5, 0x33f3, 0x33f1, 0x33ef, 0x33ed, 0x33eb, 0x33e9,
+ 0x33e7, 0x33e5, 0x33e3, 0x33e1, 0x33df, 0x33dd, 0x33db, 0x33d9,
+ 0x33d8, 0x33d6, 0x33d4, 0x33d2, 0x33d0, 0x33ce, 0x33cc, 0x33ca,
+ 0x33c8, 0x33c6, 0x33c4, 0x33c2, 0x33c0, 0x33be, 0x33bc, 0x33ba,
+ 0x33b8, 0x33b6, 0x33b5, 0x33b3, 0x33b1, 0x33af, 0x33ad, 0x33ab,
+ 0x33a9, 0x33a7, 0x33a5, 0x33a3, 0x33a1, 0x339f, 0x339e, 0x339c,
+ 0x339a, 0x3398, 0x3396, 0x3394, 0x3392, 0x3390, 0x338e, 0x338d,
+ 0x338b, 0x3389, 0x3387, 0x3385, 0x3383, 0x3381, 0x337f, 0x337d,
+ 0x337c, 0x337a, 0x3378, 0x3376, 0x3374, 0x3372, 0x3370, 0x336f,
+ 0x336d, 0x336b, 0x3369, 0x3367, 0x3365, 0x3363, 0x3362, 0x3360,
+ 0x335e, 0x335c, 0x335a, 0x3358, 0x3357, 0x3355, 0x3353, 0x3351,
+ 0x334f, 0x334d, 0x334c, 0x334a, 0x3348, 0x3346, 0x3344, 0x3342,
+ 0x3341, 0x333f, 0x333d, 0x333b, 0x3339, 0x3338, 0x3336, 0x3334,
+ 0x3332, 0x3330, 0x332f, 0x332d, 0x332b, 0x3329, 0x3327, 0x3326,
+ 0x3324, 0x3322, 0x3320, 0x331f, 0x331d, 0x331b, 0x3319, 0x3317,
+ 0x3316, 0x3314, 0x3312, 0x3310, 0x330f, 0x330d, 0x330b, 0x3309,
+ 0x3308, 0x3306, 0x3304, 0x3302, 0x3301, 0x32ff, 0x32fd, 0x32fb,
+ 0x32fa, 0x32f8, 0x32f6, 0x32f4, 0x32f3, 0x32f1, 0x32ef, 0x32ed,
+ 0x32ec, 0x32ea, 0x32e8, 0x32e6, 0x32e5, 0x32e3, 0x32e1, 0x32e0,
+ 0x32de, 0x32dc, 0x32da, 0x32d9, 0x32d7, 0x32d5, 0x32d4, 0x32d2,
+ 0x32d0, 0x32ce, 0x32cd, 0x32cb, 0x32c9, 0x32c8, 0x32c6, 0x32c4,
+ 0x32c3, 0x32c1, 0x32bf, 0x32be, 0x32bc, 0x32ba, 0x32b8, 0x32b7,
+ 0x32b5, 0x32b3, 0x32b2, 0x32b0, 0x32ae, 0x32ad, 0x32ab, 0x32a9,
+ 0x32a8, 0x32a6, 0x32a4, 0x32a3, 0x32a1, 0x329f, 0x329e, 0x329c,
+ 0x329b, 0x3299, 0x3297, 0x3296, 0x3294, 0x3292, 0x3291, 0x328f,
+ 0x328d, 0x328c, 0x328a, 0x3288, 0x3287, 0x3285, 0x3284, 0x3282,
+ 0x3280, 0x327f, 0x327d, 0x327b, 0x327a, 0x3278, 0x3277, 0x3275,
+ 0x3273, 0x3272, 0x3270, 0x326f, 0x326d, 0x326b, 0x326a, 0x3268,
+ 0x3267, 0x3265, 0x3263, 0x3262, 0x3260, 0x325f, 0x325d, 0x325b,
+ 0x325a, 0x3258, 0x3257, 0x3255, 0x3253, 0x3252, 0x3250, 0x324f,
+ 0x324d, 0x324c, 0x324a, 0x3248, 0x3247, 0x3245, 0x3244, 0x3242,
+ 0x3241, 0x323f, 0x323d, 0x323c, 0x323a, 0x3239, 0x3237, 0x3236,
+ 0x3234, 0x3233, 0x3231, 0x322f, 0x322e, 0x322c, 0x322b, 0x3229,
+ 0x3228, 0x3226, 0x3225, 0x3223, 0x3222, 0x3220, 0x321f, 0x321d,
+ 0x321b, 0x321a, 0x3218, 0x3217, 0x3215, 0x3214, 0x3212, 0x3211,
+ 0x320f, 0x320e, 0x320c, 0x320b, 0x3209, 0x3208, 0x3206, 0x3205,
+ 0x3203, 0x3202, 0x3200, 0x31ff, 0x31fd, 0x31fc, 0x31fa, 0x31f9,
+ 0x31f7, 0x31f6, 0x31f4, 0x31f3, 0x31f1, 0x31f0, 0x31ee, 0x31ed,
+ 0x31eb, 0x31ea, 0x31e8, 0x31e7, 0x31e5, 0x31e4, 0x31e3, 0x31e1,
+ 0x31e0, 0x31de, 0x31dd, 0x31db, 0x31da, 0x31d8, 0x31d7, 0x31d5,
+ 0x31d4, 0x31d2, 0x31d1, 0x31d0, 0x31ce, 0x31cd, 0x31cb, 0x31ca,
+ 0x31c8, 0x31c7, 0x31c5, 0x31c4, 0x31c2, 0x31c1, 0x31c0, 0x31be,
+ 0x31bd, 0x31bb, 0x31ba, 0x31b8, 0x31b7, 0x31b6, 0x31b4, 0x31b3,
+ 0x31b1, 0x31b0, 0x31ae, 0x31ad, 0x31ac, 0x31aa, 0x31a9, 0x31a7,
+ 0x31a6, 0x31a5, 0x31a3, 0x31a2, 0x31a0, 0x319f, 0x319e, 0x319c,
+ 0x319b, 0x3199, 0x3198, 0x3197, 0x3195, 0x3194, 0x3192, 0x3191,
+ 0x3190, 0x318e, 0x318d, 0x318b, 0x318a, 0x3189, 0x3187, 0x3186,
+ 0x3184, 0x3183, 0x3182, 0x3180, 0x317f, 0x317e, 0x317c, 0x317b,
+ 0x3179, 0x3178, 0x3177, 0x3175, 0x3174, 0x3173, 0x3171, 0x3170,
+ 0x316f, 0x316d, 0x316c, 0x316b, 0x3169, 0x3168, 0x3166, 0x3165,
+ 0x3164, 0x3162, 0x3161, 0x3160, 0x315e, 0x315d, 0x315c, 0x315a,
+ 0x3159, 0x3158, 0x3156, 0x3155, 0x3154, 0x3152, 0x3151, 0x3150,
+ 0x314e, 0x314d, 0x314c, 0x314a, 0x3149, 0x3148, 0x3146, 0x3145,
+ 0x3144, 0x3142, 0x3141, 0x3140, 0x313f, 0x313d, 0x313c, 0x313b,
+ 0x3139, 0x3138, 0x3137, 0x3135, 0x3134, 0x3133, 0x3131, 0x3130,
+ 0x312f, 0x312e, 0x312c, 0x312b, 0x312a, 0x3128, 0x3127, 0x3126,
+ 0x3125, 0x3123, 0x3122, 0x3121, 0x311f, 0x311e, 0x311d, 0x311c,
+ 0x311a, 0x3119, 0x3118, 0x3117, 0x3115, 0x3114, 0x3113, 0x3111,
+ 0x3110, 0x310f, 0x310e, 0x310c, 0x310b, 0x310a, 0x3109, 0x3107,
+ 0x3106, 0x3105, 0x3104, 0x3102, 0x3101, 0x3100, 0x30ff, 0x30fd,
+ 0x30fc, 0x30fb, 0x30fa, 0x30f8, 0x30f7, 0x30f6, 0x30f5, 0x30f3,
+ 0x30f2, 0x30f1, 0x30f0, 0x30ee, 0x30ed, 0x30ec, 0x30eb, 0x30ea,
+ 0x30e8, 0x30e7, 0x30e6, 0x30e5, 0x30e3, 0x30e2, 0x30e1, 0x30e0,
+ 0x30df, 0x30dd, 0x30dc, 0x30db, 0x30da, 0x30d8, 0x30d7, 0x30d6,
+ 0x30d5, 0x30d4, 0x30d2, 0x30d1, 0x30d0, 0x30cf, 0x30ce, 0x30cc,
+ 0x30cb, 0x30ca, 0x30c9, 0x30c8, 0x30c6, 0x30c5, 0x30c4, 0x30c3,
+ 0x30c2, 0x30c0, 0x30bf, 0x30be, 0x30bd, 0x30bc, 0x30bb, 0x30b9,
+ 0x30b8, 0x30b7, 0x30b6, 0x30b5, 0x30b3, 0x30b2, 0x30b1, 0x30b0,
+ 0x30af, 0x30ae, 0x30ac, 0x30ab, 0x30aa, 0x30a9, 0x30a8, 0x30a7,
+ 0x30a5, 0x30a4, 0x30a3, 0x30a2, 0x30a1, 0x30a0, 0x309e, 0x309d,
+ 0x309c, 0x309b, 0x309a, 0x3099, 0x3098, 0x3096, 0x3095, 0x3094,
+ 0x3093, 0x3092, 0x3091, 0x3090, 0x308e, 0x308d, 0x308c, 0x308b,
+ 0x308a, 0x3089, 0x3088, 0x3086, 0x3085, 0x3084, 0x3083, 0x3082,
+ 0x3081, 0x3080, 0x307f, 0x307d, 0x307c, 0x307b, 0x307a, 0x3079,
+ 0x3078, 0x3077, 0x3076, 0x3075, 0x3073, 0x3072, 0x3071, 0x3070,
+ 0x306f, 0x306e, 0x306d, 0x306c, 0x306b, 0x3069, 0x3068, 0x3067,
+ 0x3066, 0x3065, 0x3064, 0x3063, 0x3062, 0x3061, 0x3060, 0x305e,
+ 0x305d, 0x305c, 0x305b, 0x305a, 0x3059, 0x3058, 0x3057, 0x3056,
+ 0x3055, 0x3053, 0x3050, 0x304e, 0x304c, 0x304a, 0x3048, 0x3046,
+ 0x3043, 0x3041, 0x303f, 0x303d, 0x303b, 0x3039, 0x3037, 0x3035,
+ 0x3033, 0x3030, 0x302e, 0x302c, 0x302a, 0x3028, 0x3026, 0x3024,
+ 0x3022, 0x3020, 0x301e, 0x301c, 0x301a, 0x3018, 0x3016, 0x3014,
+ 0x3011, 0x300f, 0x300d, 0x300b, 0x3009, 0x3007, 0x3005, 0x3003,
+ 0x3001, 0x2fff, 0x2ffb, 0x2ff7, 0x2ff3, 0x2fef, 0x2feb, 0x2fe7,
+ 0x2fe3, 0x2fdf, 0x2fdb, 0x2fd7, 0x2fd3, 0x2fcf, 0x2fcb, 0x2fc7,
+ 0x2fc4, 0x2fc0, 0x2fbc, 0x2fb8, 0x2fb4, 0x2fb0, 0x2fac, 0x2fa9,
+ 0x2fa5, 0x2fa1, 0x2f9d, 0x2f99, 0x2f96, 0x2f92, 0x2f8e, 0x2f8a,
+ 0x2f86, 0x2f83, 0x2f7f, 0x2f7b, 0x2f77, 0x2f74, 0x2f70, 0x2f6c,
+ 0x2f69, 0x2f65, 0x2f61, 0x2f5e, 0x2f5a, 0x2f56, 0x2f52, 0x2f4f,
+ 0x2f4b, 0x2f48, 0x2f44, 0x2f40, 0x2f3d, 0x2f39, 0x2f35, 0x2f32,
+ 0x2f2e, 0x2f2b, 0x2f27, 0x2f23, 0x2f20, 0x2f1c, 0x2f19, 0x2f15,
+ 0x2f12, 0x2f0e, 0x2f0b, 0x2f07, 0x2f04, 0x2f00, 0x2efd, 0x2ef9,
+ 0x2ef6, 0x2ef2, 0x2eef, 0x2eeb, 0x2ee8, 0x2ee4, 0x2ee1, 0x2edd,
+ 0x2eda, 0x2ed7, 0x2ed3, 0x2ed0, 0x2ecc, 0x2ec9, 0x2ec6, 0x2ec2,
+ 0x2ebf, 0x2ebb, 0x2eb8, 0x2eb5, 0x2eb1, 0x2eae, 0x2eab, 0x2ea7,
+ 0x2ea4, 0x2ea1, 0x2e9d, 0x2e9a, 0x2e97, 0x2e94, 0x2e90, 0x2e8d,
+ 0x2e8a, 0x2e86, 0x2e83, 0x2e80, 0x2e7d, 0x2e79, 0x2e76, 0x2e73,
+ 0x2e70, 0x2e6d, 0x2e69, 0x2e66, 0x2e63, 0x2e60, 0x2e5d, 0x2e59,
+ 0x2e56, 0x2e53, 0x2e50, 0x2e4d, 0x2e4a, 0x2e46, 0x2e43, 0x2e40,
+ 0x2e3d, 0x2e3a, 0x2e37, 0x2e34, 0x2e31, 0x2e2e, 0x2e2a, 0x2e27,
+ 0x2e24, 0x2e21, 0x2e1e, 0x2e1b, 0x2e18, 0x2e15, 0x2e12, 0x2e0f,
+ 0x2e0c, 0x2e09, 0x2e06, 0x2e03, 0x2e00, 0x2dfd, 0x2dfa, 0x2df7,
+ 0x2df4, 0x2df1, 0x2dee, 0x2deb, 0x2de8, 0x2de5, 0x2de2, 0x2ddf,
+ 0x2ddc, 0x2dd9, 0x2dd6, 0x2dd4, 0x2dd1, 0x2dce, 0x2dcb, 0x2dc8,
+ 0x2dc5, 0x2dc2, 0x2dbf, 0x2dbc, 0x2dba, 0x2db7, 0x2db4, 0x2db1,
+ 0x2dae, 0x2dab, 0x2da8, 0x2da6, 0x2da3, 0x2da0, 0x2d9d, 0x2d9a,
+ 0x2d98, 0x2d95, 0x2d92, 0x2d8f, 0x2d8c, 0x2d8a, 0x2d87, 0x2d84,
+ 0x2d81, 0x2d7f, 0x2d7c, 0x2d79, 0x2d76, 0x2d74, 0x2d71, 0x2d6e,
+ 0x2d6c, 0x2d69, 0x2d66, 0x2d63, 0x2d61, 0x2d5e, 0x2d5b, 0x2d59,
+ 0x2d56, 0x2d53, 0x2d51, 0x2d4e, 0x2d4b, 0x2d49, 0x2d46, 0x2d44,
+ 0x2d41, 0x2d3e, 0x2d3c, 0x2d39, 0x2d36, 0x2d34, 0x2d31, 0x2d2f,
+ 0x2d2c, 0x2d29, 0x2d27, 0x2d24, 0x2d22, 0x2d1f, 0x2d1d, 0x2d1a,
+ 0x2d18, 0x2d15, 0x2d12, 0x2d10, 0x2d0d, 0x2d0b, 0x2d08, 0x2d06,
+ 0x2d03, 0x2d01, 0x2cfe, 0x2cfc, 0x2cf9, 0x2cf7, 0x2cf4, 0x2cf2,
+ 0x2cef, 0x2ced, 0x2cea, 0x2ce8, 0x2ce6, 0x2ce3, 0x2ce1, 0x2cde,
+ 0x2cdc, 0x2cd9, 0x2cd7, 0x2cd5, 0x2cd2, 0x2cd0, 0x2ccd, 0x2ccb,
+ 0x2cc9, 0x2cc6, 0x2cc4, 0x2cc1, 0x2cbf, 0x2cbd, 0x2cba, 0x2cb8,
+ 0x2cb6, 0x2cb3, 0x2cb1, 0x2caf, 0x2cac, 0x2caa, 0x2ca7, 0x2ca5,
+ 0x2ca3, 0x2ca1, 0x2c9e, 0x2c9c, 0x2c9a, 0x2c97, 0x2c95, 0x2c93,
+ 0x2c90, 0x2c8e, 0x2c8c, 0x2c8a, 0x2c87, 0x2c85, 0x2c83, 0x2c81,
+ 0x2c7e, 0x2c7c, 0x2c7a, 0x2c78, 0x2c75, 0x2c73, 0x2c71, 0x2c6f,
+ 0x2c6d, 0x2c6a, 0x2c68, 0x2c66, 0x2c64, 0x2c61, 0x2c5f, 0x2c5d,
+ 0x2c5b, 0x2c59, 0x2c57, 0x2c54, 0x2c52, 0x2c50, 0x2c4e, 0x2c4c,
+ 0x2c4a, 0x2c48, 0x2c45, 0x2c43, 0x2c41, 0x2c3f, 0x2c3d, 0x2c3b,
+ 0x2c39, 0x2c37, 0x2c34, 0x2c32, 0x2c30, 0x2c2e, 0x2c2c, 0x2c2a,
+ 0x2c28, 0x2c26, 0x2c24, 0x2c22, 0x2c20, 0x2c1e, 0x2c1b, 0x2c19,
+ 0x2c17, 0x2c15, 0x2c13, 0x2c11, 0x2c0f, 0x2c0d, 0x2c0b, 0x2c09,
+ 0x2c07, 0x2c05, 0x2c03, 0x2c01, 0x2bfe, 0x2bfa, 0x2bf6, 0x2bf2,
+ 0x2bee, 0x2bea, 0x2be6, 0x2be2, 0x2bdf, 0x2bdb, 0x2bd7, 0x2bd3,
+ 0x2bcf, 0x2bcb, 0x2bc7, 0x2bc3, 0x2bbf, 0x2bbb, 0x2bb8, 0x2bb4,
+ 0x2bb0, 0x2bac, 0x2ba8, 0x2ba4, 0x2ba1, 0x2b9d, 0x2b99, 0x2b95,
+ 0x2b91, 0x2b8e, 0x2b8a, 0x2b86, 0x2b82, 0x2b7f, 0x2b7b, 0x2b77,
+ 0x2b73, 0x2b70, 0x2b6c, 0x2b68, 0x2b64, 0x2b61, 0x2b5d, 0x2b59,
+ 0x2b56, 0x2b52, 0x2b4e, 0x2b4b, 0x2b47, 0x2b44, 0x2b40, 0x2b3c,
+ 0x2b39, 0x2b35, 0x2b31, 0x2b2e, 0x2b2a, 0x2b27, 0x2b23, 0x2b20,
+ 0x2b1c, 0x2b18, 0x2b15, 0x2b11, 0x2b0e, 0x2b0a, 0x2b07, 0x2b03,
+ 0x2b00, 0x2afc, 0x2af9, 0x2af5, 0x2af2, 0x2aee, 0x2aeb, 0x2ae7,
+ 0x2ae4, 0x2ae1, 0x2add, 0x2ada, 0x2ad6, 0x2ad3, 0x2acf, 0x2acc,
+ 0x2ac9, 0x2ac5, 0x2ac2, 0x2abe, 0x2abb, 0x2ab8, 0x2ab4, 0x2ab1,
+ 0x2aae, 0x2aaa, 0x2aa7, 0x2aa4, 0x2aa0, 0x2a9d, 0x2a9a, 0x2a97,
+ 0x2a93, 0x2a90, 0x2a8d, 0x2a89, 0x2a86, 0x2a83, 0x2a80, 0x2a7c,
+ 0x2a79, 0x2a76, 0x2a73, 0x2a6f, 0x2a6c, 0x2a69, 0x2a66, 0x2a63,
+ 0x2a5f, 0x2a5c, 0x2a59, 0x2a56, 0x2a53, 0x2a50, 0x2a4c, 0x2a49,
+ 0x2a46, 0x2a43, 0x2a40, 0x2a3d, 0x2a3a, 0x2a37, 0x2a33, 0x2a30,
+ 0x2a2d, 0x2a2a, 0x2a27, 0x2a24, 0x2a21, 0x2a1e, 0x2a1b, 0x2a18,
+ 0x2a15, 0x2a12, 0x2a0f, 0x2a0c, 0x2a09, 0x2a06, 0x2a03, 0x2a00,
+ 0x29fd, 0x29fa, 0x29f7, 0x29f4, 0x29f1, 0x29ee, 0x29eb, 0x29e8,
+ 0x29e5, 0x29e2, 0x29df, 0x29dc, 0x29d9, 0x29d6, 0x29d3, 0x29d0,
+ 0x29cd, 0x29cb, 0x29c8, 0x29c5, 0x29c2, 0x29bf, 0x29bc, 0x29b9,
+ 0x29b6, 0x29b4, 0x29b1, 0x29ae, 0x29ab, 0x29a8, 0x29a5, 0x29a3,
+ 0x29a0, 0x299d, 0x299a, 0x2997, 0x2995, 0x2992, 0x298f, 0x298c,
+ 0x2989, 0x2987, 0x2984, 0x2981, 0x297e, 0x297c, 0x2979, 0x2976,
+ 0x2973, 0x2971, 0x296e, 0x296b, 0x2969, 0x2966, 0x2963, 0x2960,
+ 0x295e, 0x295b, 0x2958, 0x2956, 0x2953, 0x2950, 0x294e, 0x294b,
+ 0x2948, 0x2946, 0x2943, 0x2941, 0x293e, 0x293b, 0x2939, 0x2936,
+ 0x2934, 0x2931, 0x292e, 0x292c, 0x2929, 0x2927, 0x2924, 0x2921,
+ 0x291f, 0x291c, 0x291a, 0x2917, 0x2915, 0x2912, 0x2910, 0x290d,
+ 0x290b, 0x2908, 0x2906, 0x2903, 0x2901, 0x28fe, 0x28fc, 0x28f9,
+ 0x28f7, 0x28f4, 0x28f2, 0x28ef, 0x28ed, 0x28ea, 0x28e8, 0x28e5,
+ 0x28e3, 0x28e0, 0x28de, 0x28dc, 0x28d9, 0x28d7, 0x28d4, 0x28d2,
+ 0x28cf, 0x28cd, 0x28cb, 0x28c8, 0x28c6, 0x28c3, 0x28c1, 0x28bf,
+ 0x28bc, 0x28ba, 0x28b8, 0x28b5, 0x28b3, 0x28b1, 0x28ae, 0x28ac,
+ 0x28aa, 0x28a7, 0x28a5, 0x28a3, 0x28a0, 0x289e, 0x289c, 0x2899,
+ 0x2897, 0x2895, 0x2892, 0x2890, 0x288e, 0x288c, 0x2889, 0x2887,
+ 0x2885, 0x2883, 0x2880, 0x287e, 0x287c, 0x287a, 0x2877, 0x2875,
+ 0x2873, 0x2871, 0x286e, 0x286c, 0x286a, 0x2868, 0x2866, 0x2863,
+ 0x2861, 0x285f, 0x285d, 0x285b, 0x2859, 0x2856, 0x2854, 0x2852,
+ 0x2850, 0x284e, 0x284c, 0x2849, 0x2847, 0x2845, 0x2843, 0x2841,
+ 0x283f, 0x283d, 0x283b, 0x2838, 0x2836, 0x2834, 0x2832, 0x2830,
+ 0x282e, 0x282c, 0x282a, 0x2828, 0x2826, 0x2824, 0x2821, 0x281f,
+ 0x281d, 0x281b, 0x2819, 0x2817, 0x2815, 0x2813, 0x2811, 0x280f,
+ 0x280d, 0x280b, 0x2809, 0x2807, 0x2805, 0x2803, 0x2801, 0x27fe,
+ 0x27fa, 0x27f6, 0x27f2, 0x27ee, 0x27ea, 0x27e6, 0x27e2, 0x27de,
+ 0x27da, 0x27d6, 0x27d2, 0x27ce, 0x27cb, 0x27c7, 0x27c3, 0x27bf,
+ 0x27bb, 0x27b7, 0x27b3, 0x27af, 0x27ac, 0x27a8, 0x27a4, 0x27a0,
+ 0x279c, 0x2799, 0x2795, 0x2791, 0x278d, 0x2789, 0x2786, 0x2782,
+ 0x277e, 0x277a, 0x2777, 0x2773, 0x276f, 0x276b, 0x2768, 0x2764,
+ 0x2760, 0x275d, 0x2759, 0x2755, 0x2752, 0x274e, 0x274a, 0x2747,
+ 0x2743, 0x273f, 0x273c, 0x2738, 0x2735, 0x2731, 0x272d, 0x272a,
+ 0x2726, 0x2723, 0x271f, 0x271c, 0x2718, 0x2715, 0x2711, 0x270d,
+ 0x270a, 0x2706, 0x2703, 0x26ff, 0x26fc, 0x26f8, 0x26f5, 0x26f1,
+ 0x26ee, 0x26eb, 0x26e7, 0x26e4, 0x26e0, 0x26dd, 0x26d9, 0x26d6,
+ 0x26d2, 0x26cf, 0x26cc, 0x26c8, 0x26c5, 0x26c2, 0x26be, 0x26bb,
+ 0x26b7, 0x26b4, 0x26b1, 0x26ad, 0x26aa, 0x26a7, 0x26a3, 0x26a0,
+ 0x269d, 0x2699, 0x2696, 0x2693, 0x2690, 0x268c, 0x2689, 0x2686,
+ 0x2682, 0x267f, 0x267c, 0x2679, 0x2676, 0x2672, 0x266f, 0x266c,
+ 0x2669, 0x2665, 0x2662, 0x265f, 0x265c, 0x2659, 0x2656, 0x2652,
+ 0x264f, 0x264c, 0x2649, 0x2646, 0x2643, 0x2640, 0x263c, 0x2639,
+ 0x2636, 0x2633, 0x2630, 0x262d, 0x262a, 0x2627, 0x2624, 0x2621,
+ 0x261e, 0x261a, 0x2617, 0x2614, 0x2611, 0x260e, 0x260b, 0x2608,
+ 0x2605, 0x2602, 0x25ff, 0x25fc, 0x25f9, 0x25f6, 0x25f3, 0x25f0,
+ 0x25ed, 0x25ea, 0x25e7, 0x25e4, 0x25e2, 0x25df, 0x25dc, 0x25d9,
+ 0x25d6, 0x25d3, 0x25d0, 0x25cd, 0x25ca, 0x25c7, 0x25c4, 0x25c2,
+ 0x25bf, 0x25bc, 0x25b9, 0x25b6, 0x25b3, 0x25b0, 0x25ae, 0x25ab,
+ 0x25a8, 0x25a5, 0x25a2, 0x259f, 0x259d, 0x259a, 0x2597, 0x2594,
+ 0x2591, 0x258f, 0x258c, 0x2589, 0x2586, 0x2584, 0x2581, 0x257e,
+ 0x257b, 0x2579, 0x2576, 0x2573, 0x2570, 0x256e, 0x256b, 0x2568,
+ 0x2566, 0x2563, 0x2560, 0x255e, 0x255b, 0x2558, 0x2555, 0x2553,
+ 0x2550, 0x254e, 0x254b, 0x2548, 0x2546, 0x2543, 0x2540, 0x253e,
+ 0x253b, 0x2538, 0x2536, 0x2533, 0x2531, 0x252e, 0x252b, 0x2529,
+ 0x2526, 0x2524, 0x2521, 0x251f, 0x251c, 0x2519, 0x2517, 0x2514,
+ 0x2512, 0x250f, 0x250d, 0x250a, 0x2508, 0x2505, 0x2503, 0x2500,
+ 0x24fe, 0x24fb, 0x24f9, 0x24f6, 0x24f4, 0x24f1, 0x24ef, 0x24ec,
+ 0x24ea, 0x24e7, 0x24e5, 0x24e3, 0x24e0, 0x24de, 0x24db, 0x24d9,
+ 0x24d6, 0x24d4, 0x24d2, 0x24cf, 0x24cd, 0x24ca, 0x24c8, 0x24c6,
+ 0x24c3, 0x24c1, 0x24be, 0x24bc, 0x24ba, 0x24b7, 0x24b5, 0x24b3,
+ 0x24b0, 0x24ac, 0x24a7, 0x24a2, 0x249e, 0x2499, 0x2495, 0x2490,
+ 0x248b, 0x2487, 0x2482, 0x247e, 0x2479, 0x2475, 0x2470, 0x246c,
+ 0x2468, 0x2463, 0x245f, 0x245a, 0x2456, 0x2452, 0x244d, 0x2449,
+ 0x2445, 0x2441, 0x243c, 0x2438, 0x2434, 0x2430, 0x242c, 0x2427,
+ 0x2423, 0x241f, 0x241b, 0x2417, 0x2413, 0x240f, 0x240b, 0x2407,
+ 0x2403, 0x23fd, 0x23f5, 0x23ed, 0x23e6, 0x23de, 0x23d6, 0x23ce,
+ 0x23c6, 0x23be, 0x23b7, 0x23af, 0x23a7, 0x23a0, 0x2398, 0x2391,
+ 0x2389, 0x2381, 0x237a, 0x2373, 0x236b, 0x2364, 0x235c, 0x2355,
+ 0x234e, 0x2346, 0x233f, 0x2338, 0x2331, 0x2329, 0x2322, 0x231b,
+ 0x2314, 0x230d, 0x2306, 0x22ff, 0x22f8, 0x22f1, 0x22ea, 0x22e3,
+ 0x22dc, 0x22d6, 0x22cf, 0x22c8, 0x22c1, 0x22ba, 0x22b4, 0x22ad,
+ 0x22a6, 0x22a0, 0x2299, 0x2292, 0x228c, 0x2285, 0x227f, 0x2278,
+ 0x2272, 0x226c, 0x2265, 0x225f, 0x2258, 0x2252, 0x224c, 0x2245,
+ 0x223f, 0x2239, 0x2233, 0x222d, 0x2226, 0x2220, 0x221a, 0x2214,
+ 0x220e, 0x2208, 0x2202, 0x21fc, 0x21f6, 0x21f0, 0x21ea, 0x21e4,
+ 0x21de, 0x21d8, 0x21d3, 0x21cd, 0x21c7, 0x21c1, 0x21bb, 0x21b6,
+ 0x21b0, 0x21aa, 0x21a5, 0x219f, 0x219a, 0x2194, 0x218e, 0x2189,
+ 0x2183, 0x217e, 0x2178, 0x2173, 0x216d, 0x2168, 0x2163, 0x215d,
+ 0x2158, 0x2153, 0x214d, 0x2148, 0x2143, 0x213d, 0x2138, 0x2133,
+ 0x212e, 0x2129, 0x2123, 0x211e, 0x2119, 0x2114, 0x210f, 0x210a,
+ 0x2105, 0x2100, 0x20fb, 0x20f6, 0x20f1, 0x20ec, 0x20e7, 0x20e2,
+ 0x20dd, 0x20d9, 0x20d4, 0x20cf, 0x20ca, 0x20c5, 0x20c1, 0x20bc,
+ 0x20b7, 0x20b2, 0x20ae, 0x20a9, 0x20a4, 0x20a0, 0x209b, 0x2097,
+ 0x2092, 0x208d, 0x2089, 0x2084, 0x2080, 0x207b, 0x2077, 0x2072,
+ 0x206e, 0x206a, 0x2065, 0x2061, 0x205c, 0x2058, 0x2054, 0x204f,
+ 0x204b, 0x2047, 0x2043, 0x203e, 0x203a, 0x2036, 0x2032, 0x202d,
+ 0x2029, 0x2025, 0x2021, 0x201d, 0x2019, 0x2015, 0x2011, 0x200d,
+ 0x2009, 0x2004, 0x2000, 0x1ff9, 0x1ff1, 0x1fe9, 0x1fe1, 0x1fd9,
+ 0x1fd1, 0x1fca, 0x1fc2, 0x1fba, 0x1fb2, 0x1fab, 0x1fa3, 0x1f9c,
+ 0x1f94, 0x1f8c, 0x1f85, 0x1f7d, 0x1f76, 0x1f6e, 0x1f67, 0x1f60,
+ 0x1f58, 0x1f51, 0x1f4a, 0x1f42, 0x1f3b, 0x1f34, 0x1f2d, 0x1f26,
+ 0x1f1e, 0x1f17, 0x1f10, 0x1f09, 0x1f02, 0x1efb, 0x1ef4, 0x1eed,
+ 0x1ee6, 0x1edf, 0x1ed9, 0x1ed2, 0x1ecb, 0x1ec4, 0x1ebd, 0x1eb7,
+ 0x1eb0, 0x1ea9, 0x1ea3, 0x1e9c, 0x1e95, 0x1e8f, 0x1e88, 0x1e82,
+ 0x1e7b, 0x1e75, 0x1e6e, 0x1e68, 0x1e62, 0x1e5b, 0x1e55, 0x1e4f,
+ 0x1e48, 0x1e42, 0x1e3c, 0x1e36, 0x1e2f, 0x1e29, 0x1e23, 0x1e1d,
+ 0x1e17, 0x1e11, 0x1e0b, 0x1e05, 0x1dff, 0x1df9, 0x1df3, 0x1ded,
+ 0x1de7, 0x1de1, 0x1ddb, 0x1dd5, 0x1dcf, 0x1dca, 0x1dc4, 0x1dbe,
+ 0x1db8, 0x1db3, 0x1dad, 0x1da7, 0x1da2, 0x1d9c, 0x1d96, 0x1d91,
+ 0x1d8b, 0x1d86, 0x1d80, 0x1d7b, 0x1d75, 0x1d70, 0x1d6a, 0x1d65,
+ 0x1d60, 0x1d5a, 0x1d55, 0x1d50, 0x1d4a, 0x1d45, 0x1d40, 0x1d3b,
+ 0x1d35, 0x1d30, 0x1d2b, 0x1d26, 0x1d21, 0x1d1b, 0x1d16, 0x1d11,
+ 0x1d0c, 0x1d07, 0x1d02, 0x1cfd, 0x1cf8, 0x1cf3, 0x1cee, 0x1ce9,
+ 0x1ce5, 0x1ce0, 0x1cdb, 0x1cd6, 0x1cd1, 0x1ccc, 0x1cc7, 0x1cc3,
+ 0x1cbe, 0x1cb9, 0x1cb5, 0x1cb0, 0x1cab, 0x1ca6, 0x1ca2, 0x1c9d,
+ 0x1c99, 0x1c94, 0x1c8f, 0x1c8b, 0x1c86, 0x1c82, 0x1c7d, 0x1c79,
+ 0x1c74, 0x1c70, 0x1c6c, 0x1c67, 0x1c63, 0x1c5e, 0x1c5a, 0x1c56,
+ 0x1c51, 0x1c4d, 0x1c49, 0x1c44, 0x1c40, 0x1c3c, 0x1c38, 0x1c34,
+ 0x1c2f, 0x1c2b, 0x1c27, 0x1c23, 0x1c1f, 0x1c1b, 0x1c17, 0x1c12,
+ 0x1c0e, 0x1c0a, 0x1c06, 0x1c02, 0x1bfd, 0x1bf5, 0x1bed, 0x1be5,
+ 0x1bdd, 0x1bd5, 0x1bcd, 0x1bc5, 0x1bbe, 0x1bb6, 0x1bae, 0x1ba7,
+ 0x1b9f, 0x1b97, 0x1b90, 0x1b88, 0x1b81, 0x1b79, 0x1b72, 0x1b6a,
+ 0x1b63, 0x1b5c, 0x1b54, 0x1b4d, 0x1b46, 0x1b3e, 0x1b37, 0x1b30,
+ 0x1b29, 0x1b22, 0x1b1a, 0x1b13, 0x1b0c, 0x1b05, 0x1afe, 0x1af7,
+ 0x1af0, 0x1ae9, 0x1ae2, 0x1adc, 0x1ad5, 0x1ace, 0x1ac7, 0x1ac0,
+ 0x1aba, 0x1ab3, 0x1aac, 0x1aa6, 0x1a9f, 0x1a98, 0x1a92, 0x1a8b,
+ 0x1a85, 0x1a7e, 0x1a78, 0x1a71, 0x1a6b, 0x1a64, 0x1a5e, 0x1a58,
+ 0x1a51, 0x1a4b, 0x1a45, 0x1a3f, 0x1a38, 0x1a32, 0x1a2c, 0x1a26,
+ 0x1a20, 0x1a19, 0x1a13, 0x1a0d, 0x1a07, 0x1a01, 0x19fb, 0x19f5,
+ 0x19ef, 0x19e9, 0x19e4, 0x19de, 0x19d8, 0x19d2, 0x19cc, 0x19c6,
+ 0x19c1, 0x19bb, 0x19b5, 0x19af, 0x19aa, 0x19a4, 0x199f, 0x1999,
+ 0x1993, 0x198e, 0x1988, 0x1983, 0x197d, 0x1978, 0x1972, 0x196d,
+ 0x1967, 0x1962, 0x195d, 0x1957, 0x1952, 0x194d, 0x1947, 0x1942,
+ 0x193d, 0x1938, 0x1932, 0x192d, 0x1928, 0x1923, 0x191e, 0x1919,
+ 0x1914, 0x190f, 0x1909, 0x1904, 0x18ff, 0x18fa, 0x18f5, 0x18f1,
+ 0x18ec, 0x18e7, 0x18e2, 0x18dd, 0x18d8, 0x18d3, 0x18ce, 0x18ca,
+ 0x18c5, 0x18c0, 0x18bb, 0x18b7, 0x18b2, 0x18ad, 0x18a9, 0x18a4,
+ 0x189f, 0x189b, 0x1896, 0x1891, 0x188d, 0x1888, 0x1884, 0x187f,
+ 0x187b, 0x1876, 0x1872, 0x186e, 0x1869, 0x1865, 0x1860, 0x185c,
+ 0x1858, 0x1853, 0x184f, 0x184b, 0x1846, 0x1842, 0x183e, 0x183a,
+ 0x1835, 0x1831, 0x182d, 0x1829, 0x1825, 0x1821, 0x181c, 0x1818,
+ 0x1814, 0x1810, 0x180c, 0x1808, 0x1804, 0x1800, 0x17f8, 0x17f0,
+ 0x17e8, 0x17e0, 0x17d8, 0x17d1, 0x17c9, 0x17c1, 0x17b9, 0x17b2,
+ 0x17aa, 0x17a2, 0x179b, 0x1793, 0x178c, 0x1784, 0x177d, 0x1775,
+ 0x176e, 0x1766, 0x175f, 0x1757, 0x1750, 0x1749, 0x1742, 0x173a,
+ 0x1733, 0x172c, 0x1725, 0x171e, 0x1717, 0x170f, 0x1708, 0x1701,
+ 0x16fa, 0x16f3, 0x16ec, 0x16e6, 0x16df, 0x16d8, 0x16d1, 0x16ca,
+ 0x16c3, 0x16bd, 0x16b6, 0x16af, 0x16a9, 0x16a2, 0x169b, 0x1695,
+ 0x168e, 0x1688, 0x1681, 0x167b, 0x1674, 0x166e, 0x1667, 0x1661,
+ 0x165b, 0x1654, 0x164e, 0x1648, 0x1641, 0x163b, 0x1635, 0x162f,
+ 0x1628, 0x1622, 0x161c, 0x1616, 0x1610, 0x160a, 0x1604, 0x15fe,
+ 0x15f8, 0x15f2, 0x15ec, 0x15e6, 0x15e0, 0x15da, 0x15d5, 0x15cf,
+ 0x15c9, 0x15c3, 0x15bd, 0x15b8, 0x15b2, 0x15ac, 0x15a7, 0x15a1,
+ 0x159b, 0x1596, 0x1590, 0x158b, 0x1585, 0x1580, 0x157a, 0x1575,
+ 0x156f, 0x156a, 0x1564, 0x155f, 0x155a, 0x1554, 0x154f, 0x154a,
+ 0x1544, 0x153f, 0x153a, 0x1535, 0x1530, 0x152a, 0x1525, 0x1520,
+ 0x151b, 0x1516, 0x1511, 0x150c, 0x1507, 0x1502, 0x14fd, 0x14f8,
+ 0x14f3, 0x14ee, 0x14e9, 0x14e4, 0x14df, 0x14da, 0x14d5, 0x14d1,
+ 0x14cc, 0x14c7, 0x14c2, 0x14bd, 0x14b9, 0x14b4, 0x14af, 0x14ab,
+ 0x14a6, 0x14a1, 0x149d, 0x1498, 0x1494, 0x148f, 0x148a, 0x1486,
+ 0x1481, 0x147d, 0x1478, 0x1474, 0x146f, 0x146b, 0x1467, 0x1462,
+ 0x145e, 0x145a, 0x1455, 0x1451, 0x144d, 0x1448, 0x1444, 0x1440,
+ 0x143b, 0x1437, 0x1433, 0x142f, 0x142b, 0x1427, 0x1422, 0x141e,
+ 0x141a, 0x1416, 0x1412, 0x140e, 0x140a, 0x1406, 0x1402, 0x13fc,
+ 0x13f4, 0x13ec, 0x13e4, 0x13dc, 0x13d4, 0x13cc, 0x13c5, 0x13bd,
+ 0x13b5, 0x13ad, 0x13a6, 0x139e, 0x1396, 0x138f, 0x1387, 0x1380,
+ 0x1378, 0x1371, 0x1369, 0x1362, 0x135b, 0x1353, 0x134c, 0x1345,
+ 0x133e, 0x1336, 0x132f, 0x1328, 0x1321, 0x131a, 0x1313, 0x130c,
+ 0x1304, 0x12fd, 0x12f7, 0x12f0, 0x12e9, 0x12e2, 0x12db, 0x12d4,
+ 0x12cd, 0x12c6, 0x12c0, 0x12b9, 0x12b2, 0x12ac, 0x12a5, 0x129e,
+ 0x1298, 0x1291, 0x128b, 0x1284, 0x127d, 0x1277, 0x1271, 0x126a,
+ 0x1264, 0x125d, 0x1257, 0x1251, 0x124a, 0x1244, 0x123e, 0x1238,
+ 0x1231, 0x122b, 0x1225, 0x121f, 0x1219, 0x1213, 0x120d, 0x1207,
+ 0x1201, 0x11fb, 0x11f5, 0x11ef, 0x11e9, 0x11e3, 0x11dd, 0x11d7,
+ 0x11d1, 0x11cc, 0x11c6, 0x11c0, 0x11ba, 0x11b5, 0x11af, 0x11a9,
+ 0x11a4, 0x119e, 0x1198, 0x1193, 0x118d, 0x1188, 0x1182, 0x117d,
+ 0x1177, 0x1172, 0x116c, 0x1167, 0x1161, 0x115c, 0x1157, 0x1151,
+ 0x114c, 0x1147, 0x1142, 0x113c, 0x1137, 0x1132, 0x112d, 0x1127,
+ 0x1122, 0x111d, 0x1118, 0x1113, 0x110e, 0x1109, 0x1104, 0x10ff,
+ 0x10fa, 0x10f5, 0x10f0, 0x10eb, 0x10e6, 0x10e1, 0x10dc, 0x10d8,
+ 0x10d3, 0x10ce, 0x10c9, 0x10c4, 0x10c0, 0x10bb, 0x10b6, 0x10b1,
+ 0x10ad, 0x10a8, 0x10a3, 0x109f, 0x109a, 0x1096, 0x1091, 0x108c,
+ 0x1088, 0x1083, 0x107f, 0x107a, 0x1076, 0x1071, 0x106d, 0x1069,
+ 0x1064, 0x1060, 0x105b, 0x1057, 0x1053, 0x104e, 0x104a, 0x1046,
+ 0x1042, 0x103d, 0x1039, 0x1035, 0x1031, 0x102d, 0x1028, 0x1024,
+ 0x1020, 0x101c, 0x1018, 0x1014, 0x1010, 0x100c, 0x1008, 0x1004,
+ 0x0fff, 0x0ff7, 0x0fef, 0x0fe7, 0x0fdf, 0x0fd8, 0x0fd0, 0x0fc8,
+ 0x0fc0, 0x0fb8, 0x0fb1, 0x0fa9, 0x0fa1, 0x0f9a, 0x0f92, 0x0f8b,
+ 0x0f83, 0x0f7c, 0x0f74, 0x0f6d, 0x0f65, 0x0f5e, 0x0f57, 0x0f4f,
+ 0x0f48, 0x0f41, 0x0f3a, 0x0f32, 0x0f2b, 0x0f24, 0x0f1d, 0x0f16,
+ 0x0f0f, 0x0f08, 0x0f01, 0x0efa, 0x0ef3, 0x0eec, 0x0ee5, 0x0ede,
+ 0x0ed7, 0x0ed0, 0x0ec9, 0x0ec3, 0x0ebc, 0x0eb5, 0x0eaf, 0x0ea8,
+ 0x0ea1, 0x0e9b, 0x0e94, 0x0e8d, 0x0e87, 0x0e80, 0x0e7a, 0x0e73,
+ 0x0e6d, 0x0e67, 0x0e60, 0x0e5a, 0x0e53, 0x0e4d, 0x0e47, 0x0e41,
+ 0x0e3a, 0x0e34, 0x0e2e, 0x0e28, 0x0e22, 0x0e1c, 0x0e15, 0x0e0f,
+ 0x0e09, 0x0e03, 0x0dfd, 0x0df7, 0x0df1, 0x0deb, 0x0de6, 0x0de0,
+ 0x0dda, 0x0dd4, 0x0dce, 0x0dc8, 0x0dc3, 0x0dbd, 0x0db7, 0x0db1,
+ 0x0dac, 0x0da6, 0x0da0, 0x0d9b, 0x0d95, 0x0d90, 0x0d8a, 0x0d85,
+ 0x0d7f, 0x0d74, 0x0d69, 0x0d5e, 0x0d54, 0x0d49, 0x0d3f, 0x0d34,
+ 0x0d2a, 0x0d1f, 0x0d15, 0x0d0b, 0x0d01, 0x0cf7, 0x0ced, 0x0ce3,
+ 0x0cda, 0x0cd0, 0x0cc6, 0x0cbd, 0x0cb3, 0x0caa, 0x0ca1, 0x0c98,
+ 0x0c8e, 0x0c85, 0x0c7c, 0x0c73, 0x0c6b, 0x0c62, 0x0c59, 0x0c50,
+ 0x0c48, 0x0c3f, 0x0c37, 0x0c2e, 0x0c26, 0x0c1e, 0x0c16, 0x0c0d,
+ 0x0c05, 0x0bfb, 0x0beb, 0x0bdb, 0x0bcb, 0x0bbc, 0x0bad, 0x0b9d,
+ 0x0b8e, 0x0b7f, 0x0b70, 0x0b61, 0x0b53, 0x0b44, 0x0b36, 0x0b27,
+ 0x0b19, 0x0b0b, 0x0afd, 0x0aef, 0x0ae1, 0x0ad3, 0x0ac6, 0x0ab8,
+ 0x0aab, 0x0a9e, 0x0a90, 0x0a83, 0x0a76, 0x0a69, 0x0a5d, 0x0a50,
+ 0x0a43, 0x0a37, 0x0a2b, 0x0a1e, 0x0a12, 0x0a06, 0x09fa, 0x09ee,
+ 0x09e2, 0x09d7, 0x09cb, 0x09bf, 0x09b4, 0x09a9, 0x099d, 0x0992,
+ 0x0987, 0x097c, 0x0971, 0x0966, 0x095b, 0x0951, 0x0946, 0x093c,
+ 0x0931, 0x0927, 0x091d, 0x0912, 0x0908, 0x08fe, 0x08f4, 0x08eb,
+ 0x08e1, 0x08d7, 0x08cd, 0x08c4, 0x08ba, 0x08b1, 0x08a8, 0x089e,
+ 0x0895, 0x088c, 0x0883, 0x087a, 0x0871, 0x0868, 0x085f, 0x0857,
+ 0x084e, 0x0845, 0x083d, 0x0834, 0x082c, 0x0824, 0x081c, 0x0813,
+ 0x080b, 0x0803, 0x07f6, 0x07e7, 0x07d7, 0x07c7, 0x07b8, 0x07a8,
+ 0x0799, 0x078a, 0x077b, 0x076c, 0x075d, 0x074f, 0x0740, 0x0732,
+ 0x0723, 0x0715, 0x0707, 0x06f9, 0x06eb, 0x06dd, 0x06d0, 0x06c2,
+ 0x06b4, 0x06a7, 0x069a, 0x068d, 0x0680, 0x0673, 0x0666, 0x0659,
+ 0x064c, 0x0640, 0x0633, 0x0627, 0x061b, 0x060f, 0x0603, 0x05f7,
+ 0x05eb, 0x05df, 0x05d3, 0x05c8, 0x05bc, 0x05b1, 0x05a5, 0x059a,
+ 0x058f, 0x0584, 0x0579, 0x056e, 0x0563, 0x0558, 0x054e, 0x0543,
+ 0x0539, 0x052e, 0x0524, 0x051a, 0x0510, 0x0506, 0x04fc, 0x04f2,
+ 0x04e8, 0x04de, 0x04d4, 0x04cb, 0x04c1, 0x04b8, 0x04ae, 0x04a5,
+ 0x049c, 0x0493, 0x0489, 0x0480, 0x0477, 0x046f, 0x0466, 0x045d,
+ 0x0454, 0x044c, 0x0443, 0x043b, 0x0432, 0x042a, 0x0421, 0x0419,
+ 0x0411, 0x0409, 0x0401, 0x03f9, 0x03f1, 0x03e9, 0x03e1, 0x03da,
+ 0x03d2, 0x03ca, 0x03c3, 0x03bb, 0x03b4, 0x03ad, 0x03a5, 0x039e,
+ 0x0397, 0x0390, 0x0389, 0x0381, 0x037a, 0x0374, 0x036d, 0x0366,
+ 0x035f, 0x0358, 0x0352, 0x034b, 0x0345, 0x033e, 0x0338, 0x0331,
+ 0x032b, 0x0324, 0x031e, 0x0318, 0x0312, 0x030c, 0x0306, 0x0300,
+ 0x02fa, 0x02f4, 0x02ee, 0x02e8, 0x02e2, 0x02dd, 0x02d7, 0x02d1,
+ 0x02cc, 0x02c6, 0x02c0, 0x02bb, 0x02b6, 0x02b0, 0x02ab, 0x02a5,
+ 0x02a0, 0x029b, 0x0296, 0x0291, 0x028c, 0x0286, 0x0281, 0x027c,
+ 0x0277, 0x0273, 0x026e, 0x0269, 0x0264, 0x025f, 0x025b, 0x0256,
+ 0x0251, 0x024d, 0x0248, 0x0243, 0x023f, 0x023a, 0x0236, 0x0232,
+ 0x022d, 0x0229, 0x0225, 0x0220, 0x021c, 0x0218, 0x0214, 0x0210,
+ 0x020b, 0x0207, 0x0203, 0x01ff, 0x01fb, 0x01f7, 0x01f4, 0x01f0,
+ 0x01ec, 0x01e8, 0x01e4, 0x01e0, 0x01dd, 0x01d9, 0x01d5, 0x01d2,
+ 0x01ce, 0x01ca, 0x01c7, 0x01c3, 0x01c0, 0x01bc, 0x01b9, 0x01b5,
+ 0x01b2, 0x01af, 0x01ab, 0x01a8, 0x01a5, 0x01a1, 0x019e, 0x019b,
+ 0x0198, 0x0195, 0x0191, 0x018e, 0x018b, 0x0188, 0x0185, 0x0182,
+ 0x017f, 0x017c, 0x0179, 0x0176, 0x0173, 0x0170, 0x016d, 0x016b,
+ 0x0168, 0x0165, 0x0162, 0x015f, 0x015d, 0x015a, 0x0157, 0x0155,
+ 0x0152, 0x014f, 0x014d, 0x014a, 0x0148, 0x0145, 0x0143, 0x0140,
+ 0x013e, 0x013b, 0x0139, 0x0136, 0x0134, 0x0131, 0x012f, 0x012d,
+ 0x012a, 0x0128, 0x0126, 0x0123, 0x0121, 0x011f, 0x011d, 0x011a,
+ 0x0118, 0x0116, 0x0114, 0x0112, 0x0110, 0x010d, 0x010b, 0x0109,
+ 0x0107, 0x0105, 0x0103, 0x0101, 0x00ff, 0x00fd, 0x00fb, 0x00f9,
+ 0x00f7, 0x00f5, 0x00f3, 0x00f2, 0x00f0, 0x00ee, 0x00ec, 0x00ea,
+ 0x00e8, 0x00e6, 0x00e5, 0x00e3, 0x00e1, 0x00df, 0x00de, 0x00dc,
+ 0x00da, 0x00d9, 0x00d7, 0x00d5, 0x00d4, 0x00d2, 0x00d0, 0x00cf,
+ 0x00cd, 0x00cb, 0x00ca, 0x00c8, 0x00c7, 0x00c5, 0x00c4, 0x00c2,
+ 0x00c1, 0x00bf, 0x00be, 0x00bc, 0x00bb, 0x00b9, 0x00b8, 0x00b6,
+ 0x00b5, 0x00b4, 0x00b2, 0x00b1, 0x00af, 0x00ae, 0x00ad, 0x00ab,
+ 0x00aa, 0x00a9, 0x00a7, 0x00a6, 0x00a5, 0x00a3, 0x00a2, 0x00a1,
+ 0x00a0, 0x009e, 0x009d, 0x009c, 0x009b, 0x009a, 0x0098, 0x0097,
+ 0x0096, 0x0095, 0x0094, 0x0093, 0x0091, 0x0090, 0x008f, 0x008e,
+ 0x008d, 0x008c, 0x008b, 0x008a, 0x0089, 0x0087, 0x0086, 0x0085,
+ 0x0084, 0x0083, 0x0082, 0x0081, 0x0080, 0x007f, 0x007e, 0x007d,
+ 0x007c, 0x007b, 0x007a, 0x0079, 0x0079, 0x0078, 0x0077, 0x0076,
+ 0x0075, 0x0074, 0x0073, 0x0072, 0x0071, 0x0070, 0x006f, 0x006f,
+ 0x006e, 0x006d, 0x006c, 0x006b, 0x006a, 0x006a, 0x0069, 0x0068,
+ 0x0067, 0x0066, 0x0065, 0x0065, 0x0064, 0x0063, 0x0062, 0x0062,
+ 0x0061, 0x0060, 0x005f, 0x005f, 0x005e, 0x005d, 0x005c, 0x005c,
+ 0x005b, 0x005a, 0x005a, 0x0059, 0x0058, 0x0057, 0x0057, 0x0056,
+ 0x0055, 0x0055, 0x0054, 0x0053, 0x0053, 0x0052, 0x0052, 0x0051,
+ 0x0050, 0x0050, 0x004f, 0x004e, 0x004e, 0x004d, 0x004d, 0x004c,
+ 0x004b, 0x004b, 0x004a, 0x004a, 0x0049, 0x0049, 0x0048, 0x0047,
+ 0x0047, 0x0046, 0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043,
+ 0x0043, 0x0042, 0x0042, 0x0041, 0x0041, 0x0040, 0x0040, 0x003f,
+ 0x003f, 0x003e, 0x003e, 0x003d, 0x003d, 0x003c, 0x003c, 0x003b,
+ 0x003b, 0x003a, 0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038,
+ 0x0037, 0x0037, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034,
+ 0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0031, 0x0031,
+ 0x0031, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f, 0x002e, 0x002e,
+ 0x002e, 0x002d, 0x002d, 0x002d, 0x002c, 0x002c, 0x002c, 0x002b,
+ 0x002b, 0x002b, 0x002a, 0x002a, 0x002a, 0x0029, 0x0029, 0x0029,
+ 0x0028, 0x0028, 0x0028, 0x0027, 0x0027, 0x0027, 0x0027, 0x0026,
+ 0x0026, 0x0026, 0x0025, 0x0025, 0x0025, 0x0024, 0x0024, 0x0024,
+ 0x0024, 0x0023, 0x0023, 0x0023, 0x0023, 0x0022, 0x0022, 0x0022,
+ 0x0021, 0x0021, 0x0021, 0x0021, 0x0020, 0x0020, 0x0020, 0x0020,
+ 0x001f, 0x001f, 0x001f, 0x001f, 0x001e, 0x001e, 0x001e, 0x001e,
+ 0x001e, 0x001d, 0x001d, 0x001d, 0x001d, 0x001c, 0x001c, 0x001c,
+ 0x001c, 0x001c, 0x001b, 0x001b, 0x001b, 0x001b, 0x001a, 0x001a,
+ 0x001a, 0x001a, 0x001a, 0x0019, 0x0019, 0x0019, 0x0019, 0x0019,
+ 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0017, 0x0017,
+ 0x0017, 0x0017, 0x0017, 0x0016, 0x0016, 0x0016, 0x0016, 0x0016,
+ 0x0016, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0015, 0x0014,
+ 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0013, 0x0013,
+ 0x0013, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012, 0x0012,
+ 0x0012, 0x0012, 0x0012, 0x0011, 0x0011, 0x0011, 0x0011, 0x0011,
+ 0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
+ 0x0010, 0x0010, 0x0010, 0x000f, 0x000f, 0x000f, 0x000f, 0x000f,
+ 0x000f, 0x000f, 0x000f, 0x000f, 0x000e, 0x000e, 0x000e, 0x000e,
+ 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d,
+ 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000d, 0x000c,
+ 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c,
+ 0x000c, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000b,
+ 0x000b, 0x000b, 0x000b, 0x000b, 0x000b, 0x000a, 0x000a, 0x000a,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a,
+ 0x000a, 0x000a, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
+ 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+ 0x0007, 0x0007, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005,
+ 0x0005, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+const unsigned short logTable[] =
+{
+ 0xfc00, 0xd829, 0xd7f9, 0xd7c5, 0xd7a0, 0xd783, 0xd76c, 0xd758,
+ 0xd747, 0xd738, 0xd72b, 0xd71e, 0xd713, 0xd709, 0xd700, 0xd6f7,
+ 0xd6ee, 0xd6e7, 0xd6df, 0xd6d8, 0xd6d2, 0xd6cc, 0xd6c6, 0xd6c0,
+ 0xd6bb, 0xd6b5, 0xd6b0, 0xd6ab, 0xd6a7, 0xd6a2, 0xd69e, 0xd69a,
+ 0xd696, 0xd692, 0xd68e, 0xd68a, 0xd687, 0xd683, 0xd680, 0xd67c,
+ 0xd679, 0xd676, 0xd673, 0xd670, 0xd66d, 0xd66a, 0xd667, 0xd665,
+ 0xd662, 0xd65f, 0xd65d, 0xd65a, 0xd658, 0xd655, 0xd653, 0xd650,
+ 0xd64e, 0xd64c, 0xd64a, 0xd647, 0xd645, 0xd643, 0xd641, 0xd63f,
+ 0xd63d, 0xd63b, 0xd639, 0xd637, 0xd635, 0xd633, 0xd632, 0xd630,
+ 0xd62e, 0xd62c, 0xd62a, 0xd629, 0xd627, 0xd625, 0xd624, 0xd622,
+ 0xd620, 0xd61f, 0xd61d, 0xd61c, 0xd61a, 0xd619, 0xd617, 0xd616,
+ 0xd614, 0xd613, 0xd611, 0xd610, 0xd60f, 0xd60d, 0xd60c, 0xd60a,
+ 0xd609, 0xd608, 0xd606, 0xd605, 0xd604, 0xd603, 0xd601, 0xd600,
+ 0xd5ff, 0xd5fe, 0xd5fc, 0xd5fb, 0xd5fa, 0xd5f9, 0xd5f8, 0xd5f7,
+ 0xd5f5, 0xd5f4, 0xd5f3, 0xd5f2, 0xd5f1, 0xd5f0, 0xd5ef, 0xd5ee,
+ 0xd5ed, 0xd5eb, 0xd5ea, 0xd5e9, 0xd5e8, 0xd5e7, 0xd5e6, 0xd5e5,
+ 0xd5e4, 0xd5e3, 0xd5e2, 0xd5e1, 0xd5e0, 0xd5df, 0xd5de, 0xd5dd,
+ 0xd5dd, 0xd5dc, 0xd5db, 0xd5da, 0xd5d9, 0xd5d8, 0xd5d7, 0xd5d6,
+ 0xd5d5, 0xd5d4, 0xd5d3, 0xd5d3, 0xd5d2, 0xd5d1, 0xd5d0, 0xd5cf,
+ 0xd5ce, 0xd5cd, 0xd5cd, 0xd5cc, 0xd5cb, 0xd5ca, 0xd5c9, 0xd5c9,
+ 0xd5c8, 0xd5c7, 0xd5c6, 0xd5c5, 0xd5c5, 0xd5c4, 0xd5c3, 0xd5c2,
+ 0xd5c1, 0xd5c1, 0xd5c0, 0xd5bf, 0xd5be, 0xd5be, 0xd5bd, 0xd5bc,
+ 0xd5bc, 0xd5bb, 0xd5ba, 0xd5b9, 0xd5b9, 0xd5b8, 0xd5b7, 0xd5b7,
+ 0xd5b6, 0xd5b5, 0xd5b4, 0xd5b4, 0xd5b3, 0xd5b2, 0xd5b2, 0xd5b1,
+ 0xd5b0, 0xd5b0, 0xd5af, 0xd5ae, 0xd5ae, 0xd5ad, 0xd5ac, 0xd5ac,
+ 0xd5ab, 0xd5ab, 0xd5aa, 0xd5a9, 0xd5a9, 0xd5a8, 0xd5a7, 0xd5a7,
+ 0xd5a6, 0xd5a6, 0xd5a5, 0xd5a4, 0xd5a4, 0xd5a3, 0xd5a3, 0xd5a2,
+ 0xd5a1, 0xd5a1, 0xd5a0, 0xd5a0, 0xd59f, 0xd59e, 0xd59e, 0xd59d,
+ 0xd59d, 0xd59c, 0xd59c, 0xd59b, 0xd59a, 0xd59a, 0xd599, 0xd599,
+ 0xd598, 0xd598, 0xd597, 0xd597, 0xd596, 0xd595, 0xd595, 0xd594,
+ 0xd594, 0xd593, 0xd593, 0xd592, 0xd592, 0xd591, 0xd591, 0xd590,
+ 0xd590, 0xd58f, 0xd58f, 0xd58e, 0xd58e, 0xd58d, 0xd58d, 0xd58c,
+ 0xd58c, 0xd58b, 0xd58b, 0xd58a, 0xd58a, 0xd589, 0xd589, 0xd588,
+ 0xd588, 0xd587, 0xd587, 0xd586, 0xd586, 0xd585, 0xd585, 0xd584,
+ 0xd584, 0xd583, 0xd583, 0xd582, 0xd582, 0xd581, 0xd581, 0xd581,
+ 0xd580, 0xd580, 0xd57f, 0xd57f, 0xd57e, 0xd57e, 0xd57d, 0xd57d,
+ 0xd57c, 0xd57c, 0xd57c, 0xd57b, 0xd57b, 0xd57a, 0xd57a, 0xd579,
+ 0xd579, 0xd579, 0xd578, 0xd578, 0xd577, 0xd577, 0xd576, 0xd576,
+ 0xd576, 0xd575, 0xd575, 0xd574, 0xd574, 0xd573, 0xd573, 0xd573,
+ 0xd572, 0xd572, 0xd571, 0xd571, 0xd571, 0xd570, 0xd570, 0xd56f,
+ 0xd56f, 0xd56f, 0xd56e, 0xd56e, 0xd56d, 0xd56d, 0xd56d, 0xd56c,
+ 0xd56c, 0xd56b, 0xd56b, 0xd56b, 0xd56a, 0xd56a, 0xd56a, 0xd569,
+ 0xd569, 0xd568, 0xd568, 0xd568, 0xd567, 0xd567, 0xd566, 0xd566,
+ 0xd566, 0xd565, 0xd565, 0xd565, 0xd564, 0xd564, 0xd564, 0xd563,
+ 0xd563, 0xd562, 0xd562, 0xd562, 0xd561, 0xd561, 0xd561, 0xd560,
+ 0xd560, 0xd560, 0xd55f, 0xd55f, 0xd55f, 0xd55e, 0xd55e, 0xd55d,
+ 0xd55d, 0xd55d, 0xd55c, 0xd55c, 0xd55c, 0xd55b, 0xd55b, 0xd55b,
+ 0xd55a, 0xd55a, 0xd55a, 0xd559, 0xd559, 0xd559, 0xd558, 0xd558,
+ 0xd558, 0xd557, 0xd557, 0xd557, 0xd556, 0xd556, 0xd556, 0xd555,
+ 0xd555, 0xd555, 0xd554, 0xd554, 0xd554, 0xd553, 0xd553, 0xd553,
+ 0xd552, 0xd552, 0xd552, 0xd551, 0xd551, 0xd551, 0xd551, 0xd550,
+ 0xd550, 0xd550, 0xd54f, 0xd54f, 0xd54f, 0xd54e, 0xd54e, 0xd54e,
+ 0xd54d, 0xd54d, 0xd54d, 0xd54d, 0xd54c, 0xd54c, 0xd54c, 0xd54b,
+ 0xd54b, 0xd54b, 0xd54a, 0xd54a, 0xd54a, 0xd549, 0xd549, 0xd549,
+ 0xd549, 0xd548, 0xd548, 0xd548, 0xd547, 0xd547, 0xd547, 0xd547,
+ 0xd546, 0xd546, 0xd546, 0xd545, 0xd545, 0xd545, 0xd545, 0xd544,
+ 0xd544, 0xd544, 0xd543, 0xd543, 0xd543, 0xd543, 0xd542, 0xd542,
+ 0xd542, 0xd541, 0xd541, 0xd541, 0xd541, 0xd540, 0xd540, 0xd540,
+ 0xd53f, 0xd53f, 0xd53f, 0xd53f, 0xd53e, 0xd53e, 0xd53e, 0xd53e,
+ 0xd53d, 0xd53d, 0xd53d, 0xd53c, 0xd53c, 0xd53c, 0xd53c, 0xd53b,
+ 0xd53b, 0xd53b, 0xd53b, 0xd53a, 0xd53a, 0xd53a, 0xd53a, 0xd539,
+ 0xd539, 0xd539, 0xd538, 0xd538, 0xd538, 0xd538, 0xd537, 0xd537,
+ 0xd537, 0xd537, 0xd536, 0xd536, 0xd536, 0xd536, 0xd535, 0xd535,
+ 0xd535, 0xd535, 0xd534, 0xd534, 0xd534, 0xd534, 0xd533, 0xd533,
+ 0xd533, 0xd533, 0xd532, 0xd532, 0xd532, 0xd532, 0xd531, 0xd531,
+ 0xd531, 0xd531, 0xd530, 0xd530, 0xd530, 0xd530, 0xd52f, 0xd52f,
+ 0xd52f, 0xd52f, 0xd52e, 0xd52e, 0xd52e, 0xd52e, 0xd52d, 0xd52d,
+ 0xd52d, 0xd52d, 0xd52d, 0xd52c, 0xd52c, 0xd52c, 0xd52c, 0xd52b,
+ 0xd52b, 0xd52b, 0xd52b, 0xd52a, 0xd52a, 0xd52a, 0xd52a, 0xd529,
+ 0xd529, 0xd529, 0xd529, 0xd529, 0xd528, 0xd528, 0xd528, 0xd528,
+ 0xd527, 0xd527, 0xd527, 0xd527, 0xd526, 0xd526, 0xd526, 0xd526,
+ 0xd526, 0xd525, 0xd525, 0xd525, 0xd525, 0xd524, 0xd524, 0xd524,
+ 0xd524, 0xd524, 0xd523, 0xd523, 0xd523, 0xd523, 0xd522, 0xd522,
+ 0xd522, 0xd522, 0xd522, 0xd521, 0xd521, 0xd521, 0xd521, 0xd520,
+ 0xd520, 0xd520, 0xd520, 0xd520, 0xd51f, 0xd51f, 0xd51f, 0xd51f,
+ 0xd51f, 0xd51e, 0xd51e, 0xd51e, 0xd51e, 0xd51d, 0xd51d, 0xd51d,
+ 0xd51d, 0xd51d, 0xd51c, 0xd51c, 0xd51c, 0xd51c, 0xd51c, 0xd51b,
+ 0xd51b, 0xd51b, 0xd51b, 0xd51b, 0xd51a, 0xd51a, 0xd51a, 0xd51a,
+ 0xd51a, 0xd519, 0xd519, 0xd519, 0xd519, 0xd518, 0xd518, 0xd518,
+ 0xd518, 0xd518, 0xd517, 0xd517, 0xd517, 0xd517, 0xd517, 0xd516,
+ 0xd516, 0xd516, 0xd516, 0xd516, 0xd515, 0xd515, 0xd515, 0xd515,
+ 0xd515, 0xd514, 0xd514, 0xd514, 0xd514, 0xd514, 0xd514, 0xd513,
+ 0xd513, 0xd513, 0xd513, 0xd513, 0xd512, 0xd512, 0xd512, 0xd512,
+ 0xd512, 0xd511, 0xd511, 0xd511, 0xd511, 0xd511, 0xd510, 0xd510,
+ 0xd510, 0xd510, 0xd510, 0xd50f, 0xd50f, 0xd50f, 0xd50f, 0xd50f,
+ 0xd50f, 0xd50e, 0xd50e, 0xd50e, 0xd50e, 0xd50e, 0xd50d, 0xd50d,
+ 0xd50d, 0xd50d, 0xd50d, 0xd50c, 0xd50c, 0xd50c, 0xd50c, 0xd50c,
+ 0xd50c, 0xd50b, 0xd50b, 0xd50b, 0xd50b, 0xd50b, 0xd50a, 0xd50a,
+ 0xd50a, 0xd50a, 0xd50a, 0xd50a, 0xd509, 0xd509, 0xd509, 0xd509,
+ 0xd509, 0xd508, 0xd508, 0xd508, 0xd508, 0xd508, 0xd508, 0xd507,
+ 0xd507, 0xd507, 0xd507, 0xd507, 0xd506, 0xd506, 0xd506, 0xd506,
+ 0xd506, 0xd506, 0xd505, 0xd505, 0xd505, 0xd505, 0xd505, 0xd505,
+ 0xd504, 0xd504, 0xd504, 0xd504, 0xd504, 0xd504, 0xd503, 0xd503,
+ 0xd503, 0xd503, 0xd503, 0xd502, 0xd502, 0xd502, 0xd502, 0xd502,
+ 0xd502, 0xd501, 0xd501, 0xd501, 0xd501, 0xd501, 0xd501, 0xd500,
+ 0xd500, 0xd500, 0xd500, 0xd500, 0xd500, 0xd4ff, 0xd4ff, 0xd4ff,
+ 0xd4ff, 0xd4ff, 0xd4ff, 0xd4fe, 0xd4fe, 0xd4fe, 0xd4fe, 0xd4fe,
+ 0xd4fe, 0xd4fd, 0xd4fd, 0xd4fd, 0xd4fd, 0xd4fd, 0xd4fd, 0xd4fc,
+ 0xd4fc, 0xd4fc, 0xd4fc, 0xd4fc, 0xd4fc, 0xd4fb, 0xd4fb, 0xd4fb,
+ 0xd4fb, 0xd4fb, 0xd4fb, 0xd4fb, 0xd4fa, 0xd4fa, 0xd4fa, 0xd4fa,
+ 0xd4fa, 0xd4fa, 0xd4f9, 0xd4f9, 0xd4f9, 0xd4f9, 0xd4f9, 0xd4f9,
+ 0xd4f8, 0xd4f8, 0xd4f8, 0xd4f8, 0xd4f8, 0xd4f8, 0xd4f7, 0xd4f7,
+ 0xd4f7, 0xd4f7, 0xd4f7, 0xd4f7, 0xd4f7, 0xd4f6, 0xd4f6, 0xd4f6,
+ 0xd4f6, 0xd4f6, 0xd4f6, 0xd4f5, 0xd4f5, 0xd4f5, 0xd4f5, 0xd4f5,
+ 0xd4f5, 0xd4f5, 0xd4f4, 0xd4f4, 0xd4f4, 0xd4f4, 0xd4f4, 0xd4f4,
+ 0xd4f3, 0xd4f3, 0xd4f3, 0xd4f3, 0xd4f3, 0xd4f3, 0xd4f3, 0xd4f2,
+ 0xd4f2, 0xd4f2, 0xd4f2, 0xd4f2, 0xd4f2, 0xd4f2, 0xd4f1, 0xd4f1,
+ 0xd4f1, 0xd4f1, 0xd4f1, 0xd4f1, 0xd4f0, 0xd4f0, 0xd4f0, 0xd4f0,
+ 0xd4f0, 0xd4f0, 0xd4f0, 0xd4ef, 0xd4ef, 0xd4ef, 0xd4ef, 0xd4ef,
+ 0xd4ef, 0xd4ef, 0xd4ee, 0xd4ee, 0xd4ee, 0xd4ee, 0xd4ee, 0xd4ee,
+ 0xd4ee, 0xd4ed, 0xd4ed, 0xd4ed, 0xd4ed, 0xd4ed, 0xd4ed, 0xd4ed,
+ 0xd4ec, 0xd4ec, 0xd4ec, 0xd4ec, 0xd4ec, 0xd4ec, 0xd4eb, 0xd4eb,
+ 0xd4eb, 0xd4eb, 0xd4eb, 0xd4eb, 0xd4eb, 0xd4ea, 0xd4ea, 0xd4ea,
+ 0xd4ea, 0xd4ea, 0xd4ea, 0xd4ea, 0xd4ea, 0xd4e9, 0xd4e9, 0xd4e9,
+ 0xd4e9, 0xd4e9, 0xd4e9, 0xd4e9, 0xd4e8, 0xd4e8, 0xd4e8, 0xd4e8,
+ 0xd4e8, 0xd4e8, 0xd4e8, 0xd4e7, 0xd4e7, 0xd4e7, 0xd4e7, 0xd4e7,
+ 0xd4e7, 0xd4e7, 0xd4e6, 0xd4e6, 0xd4e6, 0xd4e6, 0xd4e6, 0xd4e6,
+ 0xd4e6, 0xd4e5, 0xd4e5, 0xd4e5, 0xd4e5, 0xd4e5, 0xd4e5, 0xd4e5,
+ 0xd4e5, 0xd4e4, 0xd4e4, 0xd4e4, 0xd4e4, 0xd4e4, 0xd4e4, 0xd4e4,
+ 0xd4e3, 0xd4e3, 0xd4e3, 0xd4e3, 0xd4e3, 0xd4e3, 0xd4e3, 0xd4e3,
+ 0xd4e2, 0xd4e2, 0xd4e2, 0xd4e2, 0xd4e2, 0xd4e2, 0xd4e2, 0xd4e1,
+ 0xd4e1, 0xd4e1, 0xd4e1, 0xd4e1, 0xd4e1, 0xd4e1, 0xd4e1, 0xd4e0,
+ 0xd4e0, 0xd4e0, 0xd4e0, 0xd4e0, 0xd4e0, 0xd4e0, 0xd4df, 0xd4df,
+ 0xd4df, 0xd4df, 0xd4df, 0xd4df, 0xd4df, 0xd4df, 0xd4de, 0xd4de,
+ 0xd4de, 0xd4de, 0xd4de, 0xd4de, 0xd4de, 0xd4de, 0xd4dd, 0xd4dd,
+ 0xd4dd, 0xd4dd, 0xd4dd, 0xd4dd, 0xd4dd, 0xd4dd, 0xd4dc, 0xd4dc,
+ 0xd4dc, 0xd4dc, 0xd4dc, 0xd4dc, 0xd4dc, 0xd4dc, 0xd4db, 0xd4db,
+ 0xd4db, 0xd4db, 0xd4db, 0xd4db, 0xd4db, 0xd4da, 0xd4da, 0xd4da,
+ 0xd4da, 0xd4da, 0xd4da, 0xd4da, 0xd4da, 0xd4d9, 0xd4d9, 0xd4d9,
+ 0xd4d9, 0xd4d9, 0xd4d9, 0xd4d9, 0xd4d9, 0xd4d9, 0xd4d8, 0xd4d8,
+ 0xd4d8, 0xd4d8, 0xd4d8, 0xd4d8, 0xd4d8, 0xd4d8, 0xd4d7, 0xd4d7,
+ 0xd4d7, 0xd4d7, 0xd4d7, 0xd4d7, 0xd4d7, 0xd4d7, 0xd4d6, 0xd4d6,
+ 0xd4d6, 0xd4d6, 0xd4d6, 0xd4d6, 0xd4d6, 0xd4d6, 0xd4d5, 0xd4d5,
+ 0xd4d5, 0xd4d5, 0xd4d5, 0xd4d5, 0xd4d5, 0xd4d5, 0xd4d4, 0xd4d4,
+ 0xd4d4, 0xd4d4, 0xd4d4, 0xd4d4, 0xd4d4, 0xd4d4, 0xd4d4, 0xd4d3,
+ 0xd4d3, 0xd4d3, 0xd4d3, 0xd4d3, 0xd4d3, 0xd4d3, 0xd4d3, 0xd4d2,
+ 0xd4d2, 0xd4d2, 0xd4d2, 0xd4d2, 0xd4d2, 0xd4d2, 0xd4d2, 0xd4d2,
+ 0xd4d1, 0xd4d1, 0xd4d1, 0xd4d1, 0xd4d1, 0xd4d1, 0xd4d1, 0xd4d1,
+ 0xd4d0, 0xd4d0, 0xd4d0, 0xd4d0, 0xd4d0, 0xd4d0, 0xd4d0, 0xd4d0,
+ 0xd4d0, 0xd4cf, 0xd4cf, 0xd4cf, 0xd4cf, 0xd4cf, 0xd4cf, 0xd4cf,
+ 0xd4cf, 0xd4cf, 0xd4ce, 0xd4ce, 0xd4ce, 0xd4ce, 0xd4ce, 0xd4ce,
+ 0xd4ce, 0xd4ce, 0xd4ce, 0xd4cd, 0xd4cd, 0xd4cd, 0xd4cd, 0xd4cd,
+ 0xd4cd, 0xd4cd, 0xd4cd, 0xd4cc, 0xd4cc, 0xd4cc, 0xd4cc, 0xd4cc,
+ 0xd4cc, 0xd4cc, 0xd4cc, 0xd4cc, 0xd4cb, 0xd4cb, 0xd4cb, 0xd4cb,
+ 0xd4cb, 0xd4cb, 0xd4cb, 0xd4cb, 0xd4cb, 0xd4ca, 0xd4ca, 0xd4ca,
+ 0xd4ca, 0xd4ca, 0xd4ca, 0xd4ca, 0xd4ca, 0xd4ca, 0xd4c9, 0xd4c9,
+ 0xd4c9, 0xd4c9, 0xd4c9, 0xd4c9, 0xd4c9, 0xd4c9, 0xd4c9, 0xd4c9,
+ 0xd4c8, 0xd4c8, 0xd4c8, 0xd4c8, 0xd4c8, 0xd4c8, 0xd4c8, 0xd4c8,
+ 0xd4c8, 0xd4c7, 0xd4c7, 0xd4c7, 0xd4c7, 0xd4c7, 0xd4c7, 0xd4c7,
+ 0xd4c7, 0xd4c7, 0xd4c6, 0xd4c6, 0xd4c6, 0xd4c6, 0xd4c6, 0xd4c6,
+ 0xd4c6, 0xd4c6, 0xd4c6, 0xd4c5, 0xd4c5, 0xd4c5, 0xd4c5, 0xd4c5,
+ 0xd4c5, 0xd4c5, 0xd4c5, 0xd4c5, 0xd4c5, 0xd4c4, 0xd4c4, 0xd4c4,
+ 0xd4c4, 0xd4c4, 0xd4c4, 0xd4c4, 0xd4c4, 0xd4c4, 0xd4c3, 0xd4c3,
+ 0xd4c3, 0xd4c3, 0xd4c3, 0xd4c3, 0xd4c3, 0xd4c3, 0xd4c3, 0xd4c3,
+ 0xd4c2, 0xd4c2, 0xd4c2, 0xd4c2, 0xd4c2, 0xd4c2, 0xd4c2, 0xd4c2,
+ 0xd4c2, 0xd4c2, 0xd4c1, 0xd4c1, 0xd4c1, 0xd4c1, 0xd4c1, 0xd4c1,
+ 0xd4c1, 0xd4c1, 0xd4c1, 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c0,
+ 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c0, 0xd4c0, 0xd4bf, 0xd4bf, 0xd4bf,
+ 0xd4bf, 0xd4bf, 0xd4bf, 0xd4bf, 0xd4bf, 0xd4bf, 0xd4bf, 0xd4be,
+ 0xd4be, 0xd4be, 0xd4be, 0xd4be, 0xd4be, 0xd4be, 0xd4be, 0xd4be,
+ 0xd4be, 0xd4bd, 0xd4bd, 0xd4bd, 0xd4bd, 0xd4bd, 0xd4bd, 0xd4bd,
+ 0xd4bd, 0xd4bd, 0xd4bd, 0xd4bc, 0xd4bc, 0xd4bc, 0xd4bc, 0xd4bc,
+ 0xd4bc, 0xd4bc, 0xd4bc, 0xd4bc, 0xd4bc, 0xd4bb, 0xd4bb, 0xd4bb,
+ 0xd4bb, 0xd4bb, 0xd4bb, 0xd4bb, 0xd4bb, 0xd4bb, 0xd4bb, 0xd4ba,
+ 0xd4ba, 0xd4ba, 0xd4ba, 0xd4ba, 0xd4ba, 0xd4ba, 0xd4ba, 0xd4ba,
+ 0xd4ba, 0xd4ba, 0xd4b9, 0xd4b9, 0xd4b9, 0xd4b9, 0xd4b9, 0xd4b9,
+ 0xd4b9, 0xd4b9, 0xd4b9, 0xd4b9, 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b8,
+ 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b8, 0xd4b7,
+ 0xd4b7, 0xd4b7, 0xd4b7, 0xd4b7, 0xd4b7, 0xd4b7, 0xd4b7, 0xd4b7,
+ 0xd4b7, 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b6,
+ 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b6, 0xd4b5, 0xd4b5, 0xd4b5, 0xd4b5,
+ 0xd4b5, 0xd4b5, 0xd4b5, 0xd4b5, 0xd4b5, 0xd4b5, 0xd4b4, 0xd4b4,
+ 0xd4b4, 0xd4b4, 0xd4b4, 0xd4b4, 0xd4b4, 0xd4b4, 0xd4b4, 0xd4b4,
+ 0xd4b4, 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b3,
+ 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b3, 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b2,
+ 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b2, 0xd4b1,
+ 0xd4b1, 0xd4b1, 0xd4b1, 0xd4b1, 0xd4b1, 0xd4b1, 0xd4b1, 0xd4b1,
+ 0xd4b1, 0xd4b1, 0xd4b0, 0xd4b0, 0xd4b0, 0xd4b0, 0xd4b0, 0xd4b0,
+ 0xd4b0, 0xd4b0, 0xd4b0, 0xd4b0, 0xd4b0, 0xd4af, 0xd4af, 0xd4af,
+ 0xd4af, 0xd4af, 0xd4af, 0xd4af, 0xd4af, 0xd4af, 0xd4af, 0xd4af,
+ 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae,
+ 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ae, 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ad,
+ 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ad, 0xd4ac,
+ 0xd4ac, 0xd4ac, 0xd4ac, 0xd4ac, 0xd4ac, 0xd4ac, 0xd4ac, 0xd4ac,
+ 0xd4ac, 0xd4ac, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab,
+ 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4ab, 0xd4aa, 0xd4aa,
+ 0xd4aa, 0xd4aa, 0xd4aa, 0xd4aa, 0xd4aa, 0xd4aa, 0xd4aa, 0xd4aa,
+ 0xd4aa, 0xd4aa, 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a9,
+ 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a9, 0xd4a8, 0xd4a8, 0xd4a8,
+ 0xd4a8, 0xd4a8, 0xd4a8, 0xd4a8, 0xd4a8, 0xd4a8, 0xd4a8, 0xd4a8,
+ 0xd4a8, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7,
+ 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a7, 0xd4a6, 0xd4a6, 0xd4a6,
+ 0xd4a6, 0xd4a6, 0xd4a6, 0xd4a6, 0xd4a6, 0xd4a6, 0xd4a6, 0xd4a6,
+ 0xd4a6, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5,
+ 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a5, 0xd4a4, 0xd4a4, 0xd4a4,
+ 0xd4a4, 0xd4a4, 0xd4a4, 0xd4a4, 0xd4a4, 0xd4a4, 0xd4a4, 0xd4a4,
+ 0xd4a4, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3,
+ 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a3, 0xd4a2, 0xd4a2,
+ 0xd4a2, 0xd4a2, 0xd4a2, 0xd4a2, 0xd4a2, 0xd4a2, 0xd4a2, 0xd4a2,
+ 0xd4a2, 0xd4a2, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1,
+ 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a1, 0xd4a0,
+ 0xd4a0, 0xd4a0, 0xd4a0, 0xd4a0, 0xd4a0, 0xd4a0, 0xd4a0, 0xd4a0,
+ 0xd4a0, 0xd4a0, 0xd4a0, 0xd49f, 0xd49f, 0xd49f, 0xd49f, 0xd49f,
+ 0xd49f, 0xd49f, 0xd49f, 0xd49f, 0xd49f, 0xd49f, 0xd49f, 0xd49f,
+ 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49e,
+ 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49e, 0xd49d, 0xd49d, 0xd49d,
+ 0xd49d, 0xd49d, 0xd49d, 0xd49d, 0xd49d, 0xd49d, 0xd49d, 0xd49d,
+ 0xd49d, 0xd49d, 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49c,
+ 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49c, 0xd49b,
+ 0xd49b, 0xd49b, 0xd49b, 0xd49b, 0xd49b, 0xd49b, 0xd49b, 0xd49b,
+ 0xd49b, 0xd49b, 0xd49b, 0xd49b, 0xd49a, 0xd49a, 0xd49a, 0xd49a,
+ 0xd49a, 0xd49a, 0xd49a, 0xd49a, 0xd49a, 0xd49a, 0xd49a, 0xd49a,
+ 0xd49a, 0xd499, 0xd499, 0xd499, 0xd499, 0xd499, 0xd499, 0xd499,
+ 0xd499, 0xd499, 0xd499, 0xd499, 0xd499, 0xd499, 0xd498, 0xd498,
+ 0xd498, 0xd498, 0xd498, 0xd498, 0xd498, 0xd498, 0xd498, 0xd498,
+ 0xd498, 0xd498, 0xd498, 0xd498, 0xd497, 0xd497, 0xd497, 0xd497,
+ 0xd497, 0xd497, 0xd497, 0xd497, 0xd497, 0xd497, 0xd497, 0xd497,
+ 0xd497, 0xd496, 0xd496, 0xd496, 0xd496, 0xd496, 0xd496, 0xd496,
+ 0xd496, 0xd496, 0xd496, 0xd496, 0xd496, 0xd496, 0xd496, 0xd495,
+ 0xd495, 0xd495, 0xd495, 0xd495, 0xd495, 0xd495, 0xd495, 0xd495,
+ 0xd495, 0xd495, 0xd495, 0xd495, 0xd495, 0xd494, 0xd494, 0xd494,
+ 0xd494, 0xd494, 0xd494, 0xd494, 0xd494, 0xd494, 0xd494, 0xd494,
+ 0xd494, 0xd494, 0xd493, 0xd493, 0xd493, 0xd493, 0xd493, 0xd493,
+ 0xd493, 0xd493, 0xd493, 0xd493, 0xd493, 0xd493, 0xd493, 0xd493,
+ 0xd492, 0xd492, 0xd492, 0xd492, 0xd492, 0xd492, 0xd492, 0xd492,
+ 0xd492, 0xd492, 0xd492, 0xd492, 0xd492, 0xd492, 0xd491, 0xd491,
+ 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, 0xd491,
+ 0xd491, 0xd491, 0xd491, 0xd491, 0xd491, 0xd490, 0xd490, 0xd490,
+ 0xd490, 0xd490, 0xd490, 0xd490, 0xd490, 0xd490, 0xd490, 0xd490,
+ 0xd490, 0xd490, 0xd490, 0xd48f, 0xd48f, 0xd48f, 0xd48f, 0xd48f,
+ 0xd48f, 0xd48f, 0xd48f, 0xd48f, 0xd48f, 0xd48f, 0xd48f, 0xd48f,
+ 0xd48f, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e,
+ 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e, 0xd48e,
+ 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d,
+ 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48d, 0xd48c, 0xd48c,
+ 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48c,
+ 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48c, 0xd48b, 0xd48b, 0xd48b,
+ 0xd48b, 0xd48b, 0xd48b, 0xd48b, 0xd48b, 0xd48b, 0xd48b, 0xd48b,
+ 0xd48b, 0xd48b, 0xd48b, 0xd48b, 0xd48a, 0xd48a, 0xd48a, 0xd48a,
+ 0xd48a, 0xd48a, 0xd48a, 0xd48a, 0xd48a, 0xd48a, 0xd48a, 0xd48a,
+ 0xd48a, 0xd48a, 0xd48a, 0xd489, 0xd489, 0xd489, 0xd489, 0xd489,
+ 0xd489, 0xd489, 0xd489, 0xd489, 0xd489, 0xd489, 0xd489, 0xd489,
+ 0xd489, 0xd489, 0xd488, 0xd488, 0xd488, 0xd488, 0xd488, 0xd488,
+ 0xd488, 0xd488, 0xd488, 0xd488, 0xd488, 0xd488, 0xd488, 0xd488,
+ 0xd488, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487,
+ 0xd487, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487, 0xd487,
+ 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486,
+ 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486, 0xd486,
+ 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd485,
+ 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd485, 0xd484,
+ 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd484,
+ 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd484, 0xd483,
+ 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd483,
+ 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd483, 0xd482,
+ 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd482,
+ 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd482, 0xd481,
+ 0xd481, 0xd481, 0xd481, 0xd481, 0xd481, 0xd481, 0xd481, 0xd481,
+ 0xd480, 0xd480, 0xd480, 0xd480, 0xd480, 0xd480, 0xd480, 0xd480,
+ 0xd47f, 0xd47f, 0xd47f, 0xd47f, 0xd47f, 0xd47f, 0xd47f, 0xd47f,
+ 0xd47e, 0xd47e, 0xd47e, 0xd47e, 0xd47e, 0xd47e, 0xd47e, 0xd47e,
+ 0xd47d, 0xd47d, 0xd47d, 0xd47d, 0xd47d, 0xd47d, 0xd47d, 0xd47d,
+ 0xd47c, 0xd47c, 0xd47c, 0xd47c, 0xd47c, 0xd47c, 0xd47c, 0xd47c,
+ 0xd47c, 0xd47b, 0xd47b, 0xd47b, 0xd47b, 0xd47b, 0xd47b, 0xd47b,
+ 0xd47b, 0xd47a, 0xd47a, 0xd47a, 0xd47a, 0xd47a, 0xd47a, 0xd47a,
+ 0xd47a, 0xd47a, 0xd479, 0xd479, 0xd479, 0xd479, 0xd479, 0xd479,
+ 0xd479, 0xd479, 0xd478, 0xd478, 0xd478, 0xd478, 0xd478, 0xd478,
+ 0xd478, 0xd478, 0xd478, 0xd477, 0xd477, 0xd477, 0xd477, 0xd477,
+ 0xd477, 0xd477, 0xd477, 0xd476, 0xd476, 0xd476, 0xd476, 0xd476,
+ 0xd476, 0xd476, 0xd476, 0xd476, 0xd475, 0xd475, 0xd475, 0xd475,
+ 0xd475, 0xd475, 0xd475, 0xd475, 0xd475, 0xd474, 0xd474, 0xd474,
+ 0xd474, 0xd474, 0xd474, 0xd474, 0xd474, 0xd474, 0xd473, 0xd473,
+ 0xd473, 0xd473, 0xd473, 0xd473, 0xd473, 0xd473, 0xd473, 0xd472,
+ 0xd472, 0xd472, 0xd472, 0xd472, 0xd472, 0xd472, 0xd472, 0xd472,
+ 0xd471, 0xd471, 0xd471, 0xd471, 0xd471, 0xd471, 0xd471, 0xd471,
+ 0xd471, 0xd470, 0xd470, 0xd470, 0xd470, 0xd470, 0xd470, 0xd470,
+ 0xd470, 0xd470, 0xd46f, 0xd46f, 0xd46f, 0xd46f, 0xd46f, 0xd46f,
+ 0xd46f, 0xd46f, 0xd46f, 0xd46e, 0xd46e, 0xd46e, 0xd46e, 0xd46e,
+ 0xd46e, 0xd46e, 0xd46e, 0xd46e, 0xd46e, 0xd46d, 0xd46d, 0xd46d,
+ 0xd46d, 0xd46d, 0xd46d, 0xd46d, 0xd46d, 0xd46d, 0xd46c, 0xd46c,
+ 0xd46c, 0xd46c, 0xd46c, 0xd46c, 0xd46c, 0xd46c, 0xd46c, 0xd46c,
+ 0xd46b, 0xd46b, 0xd46b, 0xd46b, 0xd46b, 0xd46b, 0xd46b, 0xd46b,
+ 0xd46b, 0xd46a, 0xd46a, 0xd46a, 0xd46a, 0xd46a, 0xd46a, 0xd46a,
+ 0xd46a, 0xd46a, 0xd46a, 0xd469, 0xd469, 0xd469, 0xd469, 0xd469,
+ 0xd469, 0xd469, 0xd469, 0xd469, 0xd468, 0xd468, 0xd468, 0xd468,
+ 0xd468, 0xd468, 0xd468, 0xd468, 0xd468, 0xd468, 0xd467, 0xd467,
+ 0xd467, 0xd467, 0xd467, 0xd467, 0xd467, 0xd467, 0xd467, 0xd467,
+ 0xd466, 0xd466, 0xd466, 0xd466, 0xd466, 0xd466, 0xd466, 0xd466,
+ 0xd466, 0xd466, 0xd465, 0xd465, 0xd465, 0xd465, 0xd465, 0xd465,
+ 0xd465, 0xd465, 0xd465, 0xd465, 0xd464, 0xd464, 0xd464, 0xd464,
+ 0xd464, 0xd464, 0xd464, 0xd464, 0xd464, 0xd464, 0xd463, 0xd463,
+ 0xd463, 0xd463, 0xd463, 0xd463, 0xd463, 0xd463, 0xd463, 0xd463,
+ 0xd462, 0xd462, 0xd462, 0xd462, 0xd462, 0xd462, 0xd462, 0xd462,
+ 0xd462, 0xd462, 0xd461, 0xd461, 0xd461, 0xd461, 0xd461, 0xd461,
+ 0xd461, 0xd461, 0xd461, 0xd461, 0xd461, 0xd460, 0xd460, 0xd460,
+ 0xd460, 0xd460, 0xd460, 0xd460, 0xd460, 0xd460, 0xd460, 0xd45f,
+ 0xd45f, 0xd45f, 0xd45f, 0xd45f, 0xd45f, 0xd45f, 0xd45f, 0xd45f,
+ 0xd45f, 0xd45e, 0xd45e, 0xd45e, 0xd45e, 0xd45e, 0xd45e, 0xd45e,
+ 0xd45e, 0xd45e, 0xd45e, 0xd45e, 0xd45d, 0xd45d, 0xd45d, 0xd45d,
+ 0xd45d, 0xd45d, 0xd45d, 0xd45d, 0xd45d, 0xd45d, 0xd45d, 0xd45c,
+ 0xd45c, 0xd45c, 0xd45c, 0xd45c, 0xd45c, 0xd45c, 0xd45c, 0xd45c,
+ 0xd45c, 0xd45b, 0xd45b, 0xd45b, 0xd45b, 0xd45b, 0xd45b, 0xd45b,
+ 0xd45b, 0xd45b, 0xd45b, 0xd45b, 0xd45a, 0xd45a, 0xd45a, 0xd45a,
+ 0xd45a, 0xd45a, 0xd45a, 0xd45a, 0xd45a, 0xd45a, 0xd45a, 0xd459,
+ 0xd459, 0xd459, 0xd459, 0xd459, 0xd459, 0xd459, 0xd459, 0xd459,
+ 0xd459, 0xd459, 0xd458, 0xd458, 0xd458, 0xd458, 0xd458, 0xd458,
+ 0xd458, 0xd458, 0xd458, 0xd458, 0xd458, 0xd457, 0xd457, 0xd457,
+ 0xd457, 0xd457, 0xd457, 0xd457, 0xd457, 0xd457, 0xd457, 0xd457,
+ 0xd456, 0xd456, 0xd456, 0xd456, 0xd456, 0xd456, 0xd456, 0xd456,
+ 0xd456, 0xd456, 0xd456, 0xd455, 0xd455, 0xd455, 0xd455, 0xd455,
+ 0xd455, 0xd455, 0xd455, 0xd455, 0xd455, 0xd455, 0xd455, 0xd454,
+ 0xd454, 0xd454, 0xd454, 0xd454, 0xd454, 0xd454, 0xd454, 0xd454,
+ 0xd454, 0xd454, 0xd453, 0xd453, 0xd453, 0xd453, 0xd453, 0xd453,
+ 0xd453, 0xd453, 0xd453, 0xd453, 0xd453, 0xd453, 0xd452, 0xd452,
+ 0xd452, 0xd452, 0xd452, 0xd452, 0xd452, 0xd452, 0xd452, 0xd452,
+ 0xd452, 0xd451, 0xd451, 0xd451, 0xd451, 0xd451, 0xd451, 0xd451,
+ 0xd451, 0xd451, 0xd451, 0xd451, 0xd451, 0xd450, 0xd450, 0xd450,
+ 0xd450, 0xd450, 0xd450, 0xd450, 0xd450, 0xd450, 0xd450, 0xd450,
+ 0xd450, 0xd44f, 0xd44f, 0xd44f, 0xd44f, 0xd44f, 0xd44f, 0xd44f,
+ 0xd44f, 0xd44f, 0xd44f, 0xd44f, 0xd44f, 0xd44e, 0xd44e, 0xd44e,
+ 0xd44e, 0xd44e, 0xd44e, 0xd44e, 0xd44e, 0xd44e, 0xd44e, 0xd44e,
+ 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44d,
+ 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44d, 0xd44c, 0xd44c, 0xd44c,
+ 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c, 0xd44c,
+ 0xd44c, 0xd44b, 0xd44b, 0xd44b, 0xd44b, 0xd44b, 0xd44b, 0xd44b,
+ 0xd44b, 0xd44b, 0xd44b, 0xd44b, 0xd44b, 0xd44a, 0xd44a, 0xd44a,
+ 0xd44a, 0xd44a, 0xd44a, 0xd44a, 0xd44a, 0xd44a, 0xd44a, 0xd44a,
+ 0xd44a, 0xd449, 0xd449, 0xd449, 0xd449, 0xd449, 0xd449, 0xd449,
+ 0xd449, 0xd449, 0xd449, 0xd449, 0xd449, 0xd449, 0xd448, 0xd448,
+ 0xd448, 0xd448, 0xd448, 0xd448, 0xd448, 0xd448, 0xd448, 0xd448,
+ 0xd448, 0xd448, 0xd447, 0xd447, 0xd447, 0xd447, 0xd447, 0xd447,
+ 0xd447, 0xd447, 0xd447, 0xd447, 0xd447, 0xd447, 0xd447, 0xd446,
+ 0xd446, 0xd446, 0xd446, 0xd446, 0xd446, 0xd446, 0xd446, 0xd446,
+ 0xd446, 0xd446, 0xd446, 0xd446, 0xd445, 0xd445, 0xd445, 0xd445,
+ 0xd445, 0xd445, 0xd445, 0xd445, 0xd445, 0xd445, 0xd445, 0xd445,
+ 0xd444, 0xd444, 0xd444, 0xd444, 0xd444, 0xd444, 0xd444, 0xd444,
+ 0xd444, 0xd444, 0xd444, 0xd444, 0xd444, 0xd443, 0xd443, 0xd443,
+ 0xd443, 0xd443, 0xd443, 0xd443, 0xd443, 0xd443, 0xd443, 0xd443,
+ 0xd443, 0xd443, 0xd442, 0xd442, 0xd442, 0xd442, 0xd442, 0xd442,
+ 0xd442, 0xd442, 0xd442, 0xd442, 0xd442, 0xd442, 0xd442, 0xd441,
+ 0xd441, 0xd441, 0xd441, 0xd441, 0xd441, 0xd441, 0xd441, 0xd441,
+ 0xd441, 0xd441, 0xd441, 0xd441, 0xd441, 0xd440, 0xd440, 0xd440,
+ 0xd440, 0xd440, 0xd440, 0xd440, 0xd440, 0xd440, 0xd440, 0xd440,
+ 0xd440, 0xd440, 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43f,
+ 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43f, 0xd43e,
+ 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43e,
+ 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43e, 0xd43d, 0xd43d, 0xd43d,
+ 0xd43d, 0xd43d, 0xd43d, 0xd43d, 0xd43d, 0xd43d, 0xd43d, 0xd43d,
+ 0xd43d, 0xd43d, 0xd43d, 0xd43c, 0xd43c, 0xd43c, 0xd43c, 0xd43c,
+ 0xd43c, 0xd43c, 0xd43c, 0xd43c, 0xd43c, 0xd43c, 0xd43c, 0xd43c,
+ 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b,
+ 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43b, 0xd43a, 0xd43a,
+ 0xd43a, 0xd43a, 0xd43a, 0xd43a, 0xd43a, 0xd43a, 0xd43a, 0xd43a,
+ 0xd43a, 0xd43a, 0xd43a, 0xd43a, 0xd439, 0xd439, 0xd439, 0xd439,
+ 0xd439, 0xd439, 0xd439, 0xd439, 0xd439, 0xd439, 0xd439, 0xd439,
+ 0xd439, 0xd439, 0xd438, 0xd438, 0xd438, 0xd438, 0xd438, 0xd438,
+ 0xd438, 0xd438, 0xd438, 0xd438, 0xd438, 0xd438, 0xd438, 0xd438,
+ 0xd438, 0xd437, 0xd437, 0xd437, 0xd437, 0xd437, 0xd437, 0xd437,
+ 0xd437, 0xd437, 0xd437, 0xd437, 0xd437, 0xd437, 0xd437, 0xd436,
+ 0xd436, 0xd436, 0xd436, 0xd436, 0xd436, 0xd436, 0xd436, 0xd436,
+ 0xd436, 0xd436, 0xd436, 0xd436, 0xd436, 0xd435, 0xd435, 0xd435,
+ 0xd435, 0xd435, 0xd435, 0xd435, 0xd435, 0xd435, 0xd435, 0xd435,
+ 0xd435, 0xd435, 0xd435, 0xd435, 0xd434, 0xd434, 0xd434, 0xd434,
+ 0xd434, 0xd434, 0xd434, 0xd434, 0xd434, 0xd434, 0xd434, 0xd434,
+ 0xd434, 0xd434, 0xd433, 0xd433, 0xd433, 0xd433, 0xd433, 0xd433,
+ 0xd433, 0xd433, 0xd433, 0xd433, 0xd433, 0xd433, 0xd433, 0xd433,
+ 0xd433, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432,
+ 0xd432, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432, 0xd432,
+ 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd431,
+ 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd431, 0xd430,
+ 0xd430, 0xd430, 0xd430, 0xd430, 0xd430, 0xd430, 0xd430, 0xd430,
+ 0xd430, 0xd430, 0xd430, 0xd430, 0xd430, 0xd430, 0xd42f, 0xd42f,
+ 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42f,
+ 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42f, 0xd42e, 0xd42e, 0xd42e,
+ 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42e,
+ 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42e, 0xd42d, 0xd42d, 0xd42d,
+ 0xd42d, 0xd42d, 0xd42d, 0xd42d, 0xd42d, 0xd42d, 0xd42d, 0xd42d,
+ 0xd42d, 0xd42d, 0xd42d, 0xd42d, 0xd42c, 0xd42c, 0xd42c, 0xd42c,
+ 0xd42c, 0xd42c, 0xd42c, 0xd42c, 0xd42c, 0xd42c, 0xd42c, 0xd42c,
+ 0xd42c, 0xd42c, 0xd42c, 0xd42c, 0xd42b, 0xd42b, 0xd42b, 0xd42b,
+ 0xd42b, 0xd42b, 0xd42b, 0xd42b, 0xd42b, 0xd42b, 0xd42b, 0xd42b,
+ 0xd42b, 0xd42b, 0xd42b, 0xd42a, 0xd42a, 0xd42a, 0xd42a, 0xd42a,
+ 0xd42a, 0xd42a, 0xd42a, 0xd42a, 0xd42a, 0xd42a, 0xd42a, 0xd42a,
+ 0xd42a, 0xd42a, 0xd42a, 0xd429, 0xd429, 0xd429, 0xd429, 0xd429,
+ 0xd429, 0xd429, 0xd429, 0xd429, 0xd429, 0xd429, 0xd429, 0xd429,
+ 0xd429, 0xd429, 0xd428, 0xd428, 0xd428, 0xd428, 0xd428, 0xd428,
+ 0xd428, 0xd428, 0xd427, 0xd427, 0xd427, 0xd427, 0xd427, 0xd427,
+ 0xd427, 0xd427, 0xd426, 0xd426, 0xd426, 0xd426, 0xd426, 0xd426,
+ 0xd426, 0xd426, 0xd425, 0xd425, 0xd425, 0xd425, 0xd425, 0xd425,
+ 0xd425, 0xd425, 0xd424, 0xd424, 0xd424, 0xd424, 0xd424, 0xd424,
+ 0xd424, 0xd424, 0xd424, 0xd423, 0xd423, 0xd423, 0xd423, 0xd423,
+ 0xd423, 0xd423, 0xd423, 0xd422, 0xd422, 0xd422, 0xd422, 0xd422,
+ 0xd422, 0xd422, 0xd422, 0xd422, 0xd421, 0xd421, 0xd421, 0xd421,
+ 0xd421, 0xd421, 0xd421, 0xd421, 0xd420, 0xd420, 0xd420, 0xd420,
+ 0xd420, 0xd420, 0xd420, 0xd420, 0xd420, 0xd41f, 0xd41f, 0xd41f,
+ 0xd41f, 0xd41f, 0xd41f, 0xd41f, 0xd41f, 0xd41e, 0xd41e, 0xd41e,
+ 0xd41e, 0xd41e, 0xd41e, 0xd41e, 0xd41e, 0xd41e, 0xd41d, 0xd41d,
+ 0xd41d, 0xd41d, 0xd41d, 0xd41d, 0xd41d, 0xd41d, 0xd41d, 0xd41c,
+ 0xd41c, 0xd41c, 0xd41c, 0xd41c, 0xd41c, 0xd41c, 0xd41c, 0xd41c,
+ 0xd41b, 0xd41b, 0xd41b, 0xd41b, 0xd41b, 0xd41b, 0xd41b, 0xd41b,
+ 0xd41a, 0xd41a, 0xd41a, 0xd41a, 0xd41a, 0xd41a, 0xd41a, 0xd41a,
+ 0xd41a, 0xd419, 0xd419, 0xd419, 0xd419, 0xd419, 0xd419, 0xd419,
+ 0xd419, 0xd419, 0xd418, 0xd418, 0xd418, 0xd418, 0xd418, 0xd418,
+ 0xd418, 0xd418, 0xd418, 0xd418, 0xd417, 0xd417, 0xd417, 0xd417,
+ 0xd417, 0xd417, 0xd417, 0xd417, 0xd417, 0xd416, 0xd416, 0xd416,
+ 0xd416, 0xd416, 0xd416, 0xd416, 0xd416, 0xd416, 0xd415, 0xd415,
+ 0xd415, 0xd415, 0xd415, 0xd415, 0xd415, 0xd415, 0xd415, 0xd414,
+ 0xd414, 0xd414, 0xd414, 0xd414, 0xd414, 0xd414, 0xd414, 0xd414,
+ 0xd414, 0xd413, 0xd413, 0xd413, 0xd413, 0xd413, 0xd413, 0xd413,
+ 0xd413, 0xd413, 0xd412, 0xd412, 0xd412, 0xd412, 0xd412, 0xd412,
+ 0xd412, 0xd412, 0xd412, 0xd412, 0xd411, 0xd411, 0xd411, 0xd411,
+ 0xd411, 0xd411, 0xd411, 0xd411, 0xd411, 0xd410, 0xd410, 0xd410,
+ 0xd410, 0xd410, 0xd410, 0xd410, 0xd410, 0xd410, 0xd410, 0xd40f,
+ 0xd40f, 0xd40f, 0xd40f, 0xd40f, 0xd40f, 0xd40f, 0xd40f, 0xd40f,
+ 0xd40f, 0xd40e, 0xd40e, 0xd40e, 0xd40e, 0xd40e, 0xd40e, 0xd40e,
+ 0xd40e, 0xd40e, 0xd40e, 0xd40d, 0xd40d, 0xd40d, 0xd40d, 0xd40d,
+ 0xd40d, 0xd40d, 0xd40d, 0xd40d, 0xd40d, 0xd40c, 0xd40c, 0xd40c,
+ 0xd40c, 0xd40c, 0xd40c, 0xd40c, 0xd40c, 0xd40c, 0xd40c, 0xd40b,
+ 0xd40b, 0xd40b, 0xd40b, 0xd40b, 0xd40b, 0xd40b, 0xd40b, 0xd40b,
+ 0xd40b, 0xd40a, 0xd40a, 0xd40a, 0xd40a, 0xd40a, 0xd40a, 0xd40a,
+ 0xd40a, 0xd40a, 0xd40a, 0xd409, 0xd409, 0xd409, 0xd409, 0xd409,
+ 0xd409, 0xd409, 0xd409, 0xd409, 0xd409, 0xd408, 0xd408, 0xd408,
+ 0xd408, 0xd408, 0xd408, 0xd408, 0xd408, 0xd408, 0xd408, 0xd407,
+ 0xd407, 0xd407, 0xd407, 0xd407, 0xd407, 0xd407, 0xd407, 0xd407,
+ 0xd407, 0xd407, 0xd406, 0xd406, 0xd406, 0xd406, 0xd406, 0xd406,
+ 0xd406, 0xd406, 0xd406, 0xd406, 0xd405, 0xd405, 0xd405, 0xd405,
+ 0xd405, 0xd405, 0xd405, 0xd405, 0xd405, 0xd405, 0xd405, 0xd404,
+ 0xd404, 0xd404, 0xd404, 0xd404, 0xd404, 0xd404, 0xd404, 0xd404,
+ 0xd404, 0xd404, 0xd403, 0xd403, 0xd403, 0xd403, 0xd403, 0xd403,
+ 0xd403, 0xd403, 0xd403, 0xd403, 0xd402, 0xd402, 0xd402, 0xd402,
+ 0xd402, 0xd402, 0xd402, 0xd402, 0xd402, 0xd402, 0xd402, 0xd401,
+ 0xd401, 0xd401, 0xd401, 0xd401, 0xd401, 0xd401, 0xd401, 0xd401,
+ 0xd401, 0xd401, 0xd400, 0xd400, 0xd400, 0xd400, 0xd400, 0xd400,
+ 0xd400, 0xd400, 0xd3ff, 0xd3ff, 0xd3ff, 0xd3ff, 0xd3ff, 0xd3ff,
+ 0xd3fe, 0xd3fe, 0xd3fe, 0xd3fe, 0xd3fe, 0xd3fd, 0xd3fd, 0xd3fd,
+ 0xd3fd, 0xd3fd, 0xd3fd, 0xd3fc, 0xd3fc, 0xd3fc, 0xd3fc, 0xd3fc,
+ 0xd3fb, 0xd3fb, 0xd3fb, 0xd3fb, 0xd3fb, 0xd3fb, 0xd3fa, 0xd3fa,
+ 0xd3fa, 0xd3fa, 0xd3fa, 0xd3fa, 0xd3f9, 0xd3f9, 0xd3f9, 0xd3f9,
+ 0xd3f9, 0xd3f8, 0xd3f8, 0xd3f8, 0xd3f8, 0xd3f8, 0xd3f8, 0xd3f7,
+ 0xd3f7, 0xd3f7, 0xd3f7, 0xd3f7, 0xd3f7, 0xd3f6, 0xd3f6, 0xd3f6,
+ 0xd3f6, 0xd3f6, 0xd3f5, 0xd3f5, 0xd3f5, 0xd3f5, 0xd3f5, 0xd3f5,
+ 0xd3f4, 0xd3f4, 0xd3f4, 0xd3f4, 0xd3f4, 0xd3f4, 0xd3f3, 0xd3f3,
+ 0xd3f3, 0xd3f3, 0xd3f3, 0xd3f3, 0xd3f2, 0xd3f2, 0xd3f2, 0xd3f2,
+ 0xd3f2, 0xd3f2, 0xd3f1, 0xd3f1, 0xd3f1, 0xd3f1, 0xd3f1, 0xd3f0,
+ 0xd3f0, 0xd3f0, 0xd3f0, 0xd3f0, 0xd3f0, 0xd3ef, 0xd3ef, 0xd3ef,
+ 0xd3ef, 0xd3ef, 0xd3ef, 0xd3ee, 0xd3ee, 0xd3ee, 0xd3ee, 0xd3ee,
+ 0xd3ee, 0xd3ed, 0xd3ed, 0xd3ed, 0xd3ed, 0xd3ed, 0xd3ed, 0xd3ec,
+ 0xd3ec, 0xd3ec, 0xd3ec, 0xd3ec, 0xd3ec, 0xd3eb, 0xd3eb, 0xd3eb,
+ 0xd3eb, 0xd3eb, 0xd3eb, 0xd3ea, 0xd3ea, 0xd3ea, 0xd3ea, 0xd3ea,
+ 0xd3ea, 0xd3e9, 0xd3e9, 0xd3e9, 0xd3e9, 0xd3e9, 0xd3e9, 0xd3e8,
+ 0xd3e8, 0xd3e8, 0xd3e8, 0xd3e8, 0xd3e8, 0xd3e7, 0xd3e7, 0xd3e7,
+ 0xd3e7, 0xd3e7, 0xd3e7, 0xd3e6, 0xd3e6, 0xd3e6, 0xd3e6, 0xd3e6,
+ 0xd3e6, 0xd3e5, 0xd3e5, 0xd3e5, 0xd3e5, 0xd3e5, 0xd3e5, 0xd3e4,
+ 0xd3e4, 0xd3e4, 0xd3e4, 0xd3e4, 0xd3e4, 0xd3e3, 0xd3e3, 0xd3e3,
+ 0xd3e3, 0xd3e3, 0xd3e3, 0xd3e2, 0xd3e2, 0xd3e2, 0xd3e2, 0xd3e2,
+ 0xd3e2, 0xd3e2, 0xd3e1, 0xd3e1, 0xd3e1, 0xd3e1, 0xd3e1, 0xd3e1,
+ 0xd3e0, 0xd3e0, 0xd3e0, 0xd3e0, 0xd3e0, 0xd3e0, 0xd3df, 0xd3df,
+ 0xd3df, 0xd3df, 0xd3df, 0xd3df, 0xd3de, 0xd3de, 0xd3de, 0xd3de,
+ 0xd3de, 0xd3de, 0xd3de, 0xd3dd, 0xd3dd, 0xd3dd, 0xd3dd, 0xd3dd,
+ 0xd3dd, 0xd3dc, 0xd3dc, 0xd3dc, 0xd3dc, 0xd3dc, 0xd3dc, 0xd3db,
+ 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3db, 0xd3da, 0xd3da,
+ 0xd3da, 0xd3da, 0xd3da, 0xd3da, 0xd3d9, 0xd3d9, 0xd3d9, 0xd3d9,
+ 0xd3d9, 0xd3d9, 0xd3d8, 0xd3d8, 0xd3d8, 0xd3d8, 0xd3d8, 0xd3d8,
+ 0xd3d8, 0xd3d7, 0xd3d7, 0xd3d7, 0xd3d7, 0xd3d7, 0xd3d7, 0xd3d6,
+ 0xd3d6, 0xd3d6, 0xd3d6, 0xd3d6, 0xd3d6, 0xd3d6, 0xd3d5, 0xd3d5,
+ 0xd3d5, 0xd3d5, 0xd3d5, 0xd3d5, 0xd3d4, 0xd3d4, 0xd3d4, 0xd3d4,
+ 0xd3d4, 0xd3d4, 0xd3d4, 0xd3d3, 0xd3d3, 0xd3d3, 0xd3d3, 0xd3d3,
+ 0xd3d3, 0xd3d2, 0xd3d2, 0xd3d2, 0xd3d2, 0xd3d2, 0xd3d2, 0xd3d2,
+ 0xd3d1, 0xd3d1, 0xd3d1, 0xd3d1, 0xd3d1, 0xd3d1, 0xd3d0, 0xd3d0,
+ 0xd3d0, 0xd3d0, 0xd3d0, 0xd3d0, 0xd3d0, 0xd3cf, 0xd3cf, 0xd3cf,
+ 0xd3cf, 0xd3cf, 0xd3cf, 0xd3cf, 0xd3ce, 0xd3ce, 0xd3ce, 0xd3ce,
+ 0xd3ce, 0xd3ce, 0xd3cd, 0xd3cd, 0xd3cd, 0xd3cd, 0xd3cd, 0xd3cd,
+ 0xd3cd, 0xd3cc, 0xd3cc, 0xd3cc, 0xd3cc, 0xd3cc, 0xd3cc, 0xd3cc,
+ 0xd3cb, 0xd3cb, 0xd3cb, 0xd3cb, 0xd3cb, 0xd3cb, 0xd3cb, 0xd3ca,
+ 0xd3ca, 0xd3ca, 0xd3ca, 0xd3ca, 0xd3ca, 0xd3c9, 0xd3c9, 0xd3c9,
+ 0xd3c9, 0xd3c9, 0xd3c9, 0xd3c9, 0xd3c8, 0xd3c8, 0xd3c8, 0xd3c8,
+ 0xd3c8, 0xd3c8, 0xd3c8, 0xd3c7, 0xd3c7, 0xd3c7, 0xd3c7, 0xd3c7,
+ 0xd3c7, 0xd3c7, 0xd3c6, 0xd3c6, 0xd3c6, 0xd3c6, 0xd3c6, 0xd3c6,
+ 0xd3c6, 0xd3c5, 0xd3c5, 0xd3c5, 0xd3c5, 0xd3c5, 0xd3c5, 0xd3c5,
+ 0xd3c4, 0xd3c4, 0xd3c4, 0xd3c4, 0xd3c4, 0xd3c4, 0xd3c4, 0xd3c3,
+ 0xd3c3, 0xd3c3, 0xd3c3, 0xd3c3, 0xd3c3, 0xd3c3, 0xd3c2, 0xd3c2,
+ 0xd3c2, 0xd3c2, 0xd3c2, 0xd3c2, 0xd3c2, 0xd3c1, 0xd3c1, 0xd3c1,
+ 0xd3c1, 0xd3c1, 0xd3c1, 0xd3c1, 0xd3c0, 0xd3c0, 0xd3c0, 0xd3c0,
+ 0xd3c0, 0xd3c0, 0xd3c0, 0xd3bf, 0xd3bf, 0xd3bf, 0xd3bf, 0xd3bf,
+ 0xd3bf, 0xd3bf, 0xd3be, 0xd3be, 0xd3be, 0xd3be, 0xd3be, 0xd3be,
+ 0xd3be, 0xd3bd, 0xd3bd, 0xd3bd, 0xd3bd, 0xd3bd, 0xd3bd, 0xd3bd,
+ 0xd3bc, 0xd3bc, 0xd3bc, 0xd3bc, 0xd3bc, 0xd3bc, 0xd3bc, 0xd3bb,
+ 0xd3bb, 0xd3bb, 0xd3bb, 0xd3bb, 0xd3bb, 0xd3bb, 0xd3ba, 0xd3ba,
+ 0xd3ba, 0xd3ba, 0xd3ba, 0xd3ba, 0xd3ba, 0xd3ba, 0xd3b9, 0xd3b9,
+ 0xd3b9, 0xd3b9, 0xd3b9, 0xd3b9, 0xd3b9, 0xd3b8, 0xd3b8, 0xd3b8,
+ 0xd3b8, 0xd3b8, 0xd3b8, 0xd3b8, 0xd3b7, 0xd3b7, 0xd3b7, 0xd3b7,
+ 0xd3b7, 0xd3b7, 0xd3b7, 0xd3b6, 0xd3b6, 0xd3b6, 0xd3b6, 0xd3b6,
+ 0xd3b6, 0xd3b6, 0xd3b6, 0xd3b5, 0xd3b5, 0xd3b5, 0xd3b5, 0xd3b5,
+ 0xd3b5, 0xd3b5, 0xd3b4, 0xd3b4, 0xd3b4, 0xd3b4, 0xd3b4, 0xd3b4,
+ 0xd3b4, 0xd3b4, 0xd3b3, 0xd3b3, 0xd3b3, 0xd3b3, 0xd3b3, 0xd3b3,
+ 0xd3b3, 0xd3b2, 0xd3b2, 0xd3b2, 0xd3b2, 0xd3b2, 0xd3b2, 0xd3b2,
+ 0xd3b1, 0xd3b1, 0xd3b1, 0xd3b1, 0xd3b1, 0xd3b1, 0xd3b1, 0xd3b1,
+ 0xd3b0, 0xd3b0, 0xd3b0, 0xd3b0, 0xd3b0, 0xd3b0, 0xd3b0, 0xd3af,
+ 0xd3af, 0xd3af, 0xd3af, 0xd3af, 0xd3af, 0xd3af, 0xd3af, 0xd3ae,
+ 0xd3ae, 0xd3ae, 0xd3ae, 0xd3ae, 0xd3ae, 0xd3ae, 0xd3ae, 0xd3ad,
+ 0xd3ad, 0xd3ad, 0xd3ad, 0xd3ad, 0xd3ad, 0xd3ad, 0xd3ac, 0xd3ac,
+ 0xd3ac, 0xd3ac, 0xd3ac, 0xd3ac, 0xd3ac, 0xd3ac, 0xd3ab, 0xd3ab,
+ 0xd3ab, 0xd3ab, 0xd3ab, 0xd3ab, 0xd3ab, 0xd3aa, 0xd3aa, 0xd3aa,
+ 0xd3aa, 0xd3aa, 0xd3aa, 0xd3aa, 0xd3aa, 0xd3a9, 0xd3a9, 0xd3a9,
+ 0xd3a9, 0xd3a9, 0xd3a9, 0xd3a9, 0xd3a9, 0xd3a8, 0xd3a8, 0xd3a8,
+ 0xd3a8, 0xd3a8, 0xd3a8, 0xd3a8, 0xd3a8, 0xd3a7, 0xd3a7, 0xd3a7,
+ 0xd3a7, 0xd3a7, 0xd3a7, 0xd3a7, 0xd3a6, 0xd3a6, 0xd3a6, 0xd3a6,
+ 0xd3a6, 0xd3a6, 0xd3a6, 0xd3a6, 0xd3a5, 0xd3a5, 0xd3a5, 0xd3a5,
+ 0xd3a5, 0xd3a5, 0xd3a5, 0xd3a5, 0xd3a4, 0xd3a4, 0xd3a4, 0xd3a4,
+ 0xd3a4, 0xd3a4, 0xd3a4, 0xd3a4, 0xd3a3, 0xd3a3, 0xd3a3, 0xd3a3,
+ 0xd3a3, 0xd3a3, 0xd3a3, 0xd3a3, 0xd3a2, 0xd3a2, 0xd3a2, 0xd3a2,
+ 0xd3a2, 0xd3a2, 0xd3a2, 0xd3a2, 0xd3a1, 0xd3a1, 0xd3a1, 0xd3a1,
+ 0xd3a1, 0xd3a1, 0xd3a1, 0xd3a1, 0xd3a0, 0xd3a0, 0xd3a0, 0xd3a0,
+ 0xd3a0, 0xd3a0, 0xd39f, 0xd39f, 0xd39f, 0xd39f, 0xd39e, 0xd39e,
+ 0xd39e, 0xd39e, 0xd39d, 0xd39d, 0xd39d, 0xd39d, 0xd39c, 0xd39c,
+ 0xd39c, 0xd39c, 0xd39b, 0xd39b, 0xd39b, 0xd39b, 0xd39a, 0xd39a,
+ 0xd39a, 0xd39a, 0xd399, 0xd399, 0xd399, 0xd399, 0xd399, 0xd398,
+ 0xd398, 0xd398, 0xd398, 0xd397, 0xd397, 0xd397, 0xd397, 0xd396,
+ 0xd396, 0xd396, 0xd396, 0xd395, 0xd395, 0xd395, 0xd395, 0xd394,
+ 0xd394, 0xd394, 0xd394, 0xd393, 0xd393, 0xd393, 0xd393, 0xd393,
+ 0xd392, 0xd392, 0xd392, 0xd392, 0xd391, 0xd391, 0xd391, 0xd391,
+ 0xd390, 0xd390, 0xd390, 0xd390, 0xd38f, 0xd38f, 0xd38f, 0xd38f,
+ 0xd38f, 0xd38e, 0xd38e, 0xd38e, 0xd38e, 0xd38d, 0xd38d, 0xd38d,
+ 0xd38d, 0xd38c, 0xd38c, 0xd38c, 0xd38c, 0xd38b, 0xd38b, 0xd38b,
+ 0xd38b, 0xd38b, 0xd38a, 0xd38a, 0xd38a, 0xd38a, 0xd389, 0xd389,
+ 0xd389, 0xd389, 0xd389, 0xd388, 0xd388, 0xd388, 0xd388, 0xd387,
+ 0xd387, 0xd387, 0xd387, 0xd386, 0xd386, 0xd386, 0xd386, 0xd386,
+ 0xd385, 0xd385, 0xd385, 0xd385, 0xd384, 0xd384, 0xd384, 0xd384,
+ 0xd384, 0xd383, 0xd383, 0xd383, 0xd383, 0xd382, 0xd382, 0xd382,
+ 0xd382, 0xd382, 0xd381, 0xd381, 0xd381, 0xd381, 0xd380, 0xd380,
+ 0xd380, 0xd380, 0xd380, 0xd37f, 0xd37f, 0xd37f, 0xd37f, 0xd37e,
+ 0xd37e, 0xd37e, 0xd37e, 0xd37e, 0xd37d, 0xd37d, 0xd37d, 0xd37d,
+ 0xd37c, 0xd37c, 0xd37c, 0xd37c, 0xd37c, 0xd37b, 0xd37b, 0xd37b,
+ 0xd37b, 0xd37b, 0xd37a, 0xd37a, 0xd37a, 0xd37a, 0xd379, 0xd379,
+ 0xd379, 0xd379, 0xd379, 0xd378, 0xd378, 0xd378, 0xd378, 0xd378,
+ 0xd377, 0xd377, 0xd377, 0xd377, 0xd376, 0xd376, 0xd376, 0xd376,
+ 0xd376, 0xd375, 0xd375, 0xd375, 0xd375, 0xd375, 0xd374, 0xd374,
+ 0xd374, 0xd374, 0xd373, 0xd373, 0xd373, 0xd373, 0xd373, 0xd372,
+ 0xd372, 0xd372, 0xd372, 0xd372, 0xd371, 0xd371, 0xd371, 0xd371,
+ 0xd371, 0xd370, 0xd370, 0xd370, 0xd370, 0xd370, 0xd36f, 0xd36f,
+ 0xd36f, 0xd36f, 0xd36e, 0xd36e, 0xd36e, 0xd36e, 0xd36e, 0xd36d,
+ 0xd36d, 0xd36d, 0xd36d, 0xd36d, 0xd36c, 0xd36c, 0xd36c, 0xd36c,
+ 0xd36c, 0xd36b, 0xd36b, 0xd36b, 0xd36b, 0xd36b, 0xd36a, 0xd36a,
+ 0xd36a, 0xd36a, 0xd36a, 0xd369, 0xd369, 0xd369, 0xd369, 0xd369,
+ 0xd368, 0xd368, 0xd368, 0xd368, 0xd368, 0xd367, 0xd367, 0xd367,
+ 0xd367, 0xd367, 0xd366, 0xd366, 0xd366, 0xd366, 0xd366, 0xd365,
+ 0xd365, 0xd365, 0xd365, 0xd365, 0xd364, 0xd364, 0xd364, 0xd364,
+ 0xd364, 0xd363, 0xd363, 0xd363, 0xd363, 0xd363, 0xd362, 0xd362,
+ 0xd362, 0xd362, 0xd362, 0xd361, 0xd361, 0xd361, 0xd361, 0xd361,
+ 0xd360, 0xd360, 0xd360, 0xd360, 0xd360, 0xd35f, 0xd35f, 0xd35f,
+ 0xd35f, 0xd35f, 0xd35f, 0xd35e, 0xd35e, 0xd35e, 0xd35e, 0xd35e,
+ 0xd35d, 0xd35d, 0xd35d, 0xd35d, 0xd35d, 0xd35c, 0xd35c, 0xd35c,
+ 0xd35c, 0xd35c, 0xd35b, 0xd35b, 0xd35b, 0xd35b, 0xd35b, 0xd35a,
+ 0xd35a, 0xd35a, 0xd35a, 0xd35a, 0xd35a, 0xd359, 0xd359, 0xd359,
+ 0xd359, 0xd359, 0xd358, 0xd358, 0xd358, 0xd358, 0xd358, 0xd357,
+ 0xd357, 0xd357, 0xd357, 0xd357, 0xd357, 0xd356, 0xd356, 0xd356,
+ 0xd356, 0xd356, 0xd355, 0xd355, 0xd355, 0xd355, 0xd355, 0xd354,
+ 0xd354, 0xd354, 0xd354, 0xd354, 0xd354, 0xd353, 0xd353, 0xd353,
+ 0xd353, 0xd353, 0xd352, 0xd352, 0xd352, 0xd352, 0xd352, 0xd351,
+ 0xd351, 0xd351, 0xd351, 0xd351, 0xd351, 0xd350, 0xd350, 0xd350,
+ 0xd350, 0xd350, 0xd34f, 0xd34f, 0xd34f, 0xd34f, 0xd34f, 0xd34f,
+ 0xd34e, 0xd34e, 0xd34e, 0xd34e, 0xd34e, 0xd34d, 0xd34d, 0xd34d,
+ 0xd34d, 0xd34d, 0xd34d, 0xd34c, 0xd34c, 0xd34c, 0xd34c, 0xd34c,
+ 0xd34b, 0xd34b, 0xd34b, 0xd34b, 0xd34b, 0xd34b, 0xd34a, 0xd34a,
+ 0xd34a, 0xd34a, 0xd34a, 0xd34a, 0xd349, 0xd349, 0xd349, 0xd349,
+ 0xd349, 0xd348, 0xd348, 0xd348, 0xd348, 0xd348, 0xd348, 0xd347,
+ 0xd347, 0xd347, 0xd347, 0xd347, 0xd347, 0xd346, 0xd346, 0xd346,
+ 0xd346, 0xd346, 0xd345, 0xd345, 0xd345, 0xd345, 0xd345, 0xd345,
+ 0xd344, 0xd344, 0xd344, 0xd344, 0xd344, 0xd344, 0xd343, 0xd343,
+ 0xd343, 0xd343, 0xd343, 0xd342, 0xd342, 0xd342, 0xd342, 0xd342,
+ 0xd342, 0xd341, 0xd341, 0xd341, 0xd341, 0xd341, 0xd341, 0xd340,
+ 0xd340, 0xd340, 0xd340, 0xd340, 0xd340, 0xd33f, 0xd33f, 0xd33f,
+ 0xd33f, 0xd33f, 0xd33f, 0xd33e, 0xd33e, 0xd33e, 0xd33e, 0xd33e,
+ 0xd33d, 0xd33d, 0xd33d, 0xd33d, 0xd33d, 0xd33d, 0xd33c, 0xd33c,
+ 0xd33c, 0xd33c, 0xd33c, 0xd33c, 0xd33b, 0xd33b, 0xd33b, 0xd33b,
+ 0xd33b, 0xd33b, 0xd33a, 0xd33a, 0xd33a, 0xd33a, 0xd33a, 0xd33a,
+ 0xd339, 0xd339, 0xd339, 0xd339, 0xd339, 0xd339, 0xd338, 0xd338,
+ 0xd338, 0xd338, 0xd338, 0xd338, 0xd337, 0xd337, 0xd337, 0xd337,
+ 0xd337, 0xd337, 0xd336, 0xd336, 0xd336, 0xd336, 0xd336, 0xd336,
+ 0xd335, 0xd335, 0xd335, 0xd335, 0xd335, 0xd335, 0xd334, 0xd334,
+ 0xd334, 0xd334, 0xd334, 0xd334, 0xd333, 0xd333, 0xd333, 0xd333,
+ 0xd333, 0xd333, 0xd332, 0xd332, 0xd332, 0xd332, 0xd332, 0xd332,
+ 0xd332, 0xd331, 0xd331, 0xd331, 0xd331, 0xd331, 0xd331, 0xd330,
+ 0xd330, 0xd330, 0xd330, 0xd330, 0xd330, 0xd32f, 0xd32f, 0xd32f,
+ 0xd32f, 0xd32f, 0xd32f, 0xd32e, 0xd32e, 0xd32e, 0xd32e, 0xd32e,
+ 0xd32e, 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd32d, 0xd32d,
+ 0xd32c, 0xd32c, 0xd32c, 0xd32c, 0xd32c, 0xd32c, 0xd32b, 0xd32b,
+ 0xd32b, 0xd32b, 0xd32b, 0xd32b, 0xd32a, 0xd32a, 0xd32a, 0xd32a,
+ 0xd32a, 0xd32a, 0xd32a, 0xd329, 0xd329, 0xd329, 0xd329, 0xd329,
+ 0xd329, 0xd328, 0xd328, 0xd328, 0xd328, 0xd328, 0xd328, 0xd327,
+ 0xd327, 0xd327, 0xd327, 0xd327, 0xd327, 0xd327, 0xd326, 0xd326,
+ 0xd326, 0xd326, 0xd326, 0xd326, 0xd325, 0xd325, 0xd325, 0xd325,
+ 0xd325, 0xd325, 0xd325, 0xd324, 0xd324, 0xd324, 0xd324, 0xd324,
+ 0xd324, 0xd323, 0xd323, 0xd323, 0xd323, 0xd323, 0xd323, 0xd323,
+ 0xd322, 0xd322, 0xd322, 0xd322, 0xd322, 0xd322, 0xd321, 0xd321,
+ 0xd321, 0xd321, 0xd321, 0xd321, 0xd321, 0xd320, 0xd320, 0xd320,
+ 0xd320, 0xd320, 0xd320, 0xd31f, 0xd31f, 0xd31f, 0xd31f, 0xd31f,
+ 0xd31f, 0xd31f, 0xd31e, 0xd31e, 0xd31e, 0xd31e, 0xd31e, 0xd31e,
+ 0xd31e, 0xd31d, 0xd31d, 0xd31d, 0xd31d, 0xd31d, 0xd31d, 0xd31c,
+ 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31c, 0xd31b, 0xd31b,
+ 0xd31b, 0xd31b, 0xd31b, 0xd31b, 0xd31b, 0xd31a, 0xd31a, 0xd31a,
+ 0xd31a, 0xd31a, 0xd31a, 0xd31a, 0xd319, 0xd319, 0xd319, 0xd319,
+ 0xd319, 0xd319, 0xd318, 0xd318, 0xd318, 0xd318, 0xd318, 0xd318,
+ 0xd318, 0xd317, 0xd317, 0xd317, 0xd317, 0xd317, 0xd317, 0xd317,
+ 0xd316, 0xd316, 0xd316, 0xd316, 0xd316, 0xd316, 0xd316, 0xd315,
+ 0xd315, 0xd315, 0xd315, 0xd315, 0xd315, 0xd315, 0xd314, 0xd314,
+ 0xd314, 0xd314, 0xd314, 0xd314, 0xd314, 0xd313, 0xd313, 0xd313,
+ 0xd313, 0xd313, 0xd313, 0xd313, 0xd312, 0xd312, 0xd312, 0xd312,
+ 0xd312, 0xd312, 0xd311, 0xd311, 0xd311, 0xd311, 0xd311, 0xd311,
+ 0xd311, 0xd310, 0xd310, 0xd310, 0xd310, 0xd310, 0xd310, 0xd310,
+ 0xd310, 0xd30f, 0xd30f, 0xd30f, 0xd30f, 0xd30f, 0xd30f, 0xd30f,
+ 0xd30e, 0xd30e, 0xd30e, 0xd30e, 0xd30e, 0xd30e, 0xd30e, 0xd30d,
+ 0xd30d, 0xd30d, 0xd30d, 0xd30d, 0xd30d, 0xd30d, 0xd30c, 0xd30c,
+ 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30c, 0xd30b, 0xd30b, 0xd30b,
+ 0xd30b, 0xd30b, 0xd30b, 0xd30b, 0xd30a, 0xd30a, 0xd30a, 0xd30a,
+ 0xd30a, 0xd30a, 0xd30a, 0xd309, 0xd309, 0xd309, 0xd309, 0xd309,
+ 0xd309, 0xd309, 0xd308, 0xd308, 0xd308, 0xd308, 0xd308, 0xd308,
+ 0xd308, 0xd308, 0xd307, 0xd307, 0xd307, 0xd307, 0xd307, 0xd307,
+ 0xd307, 0xd306, 0xd306, 0xd306, 0xd306, 0xd306, 0xd306, 0xd306,
+ 0xd305, 0xd305, 0xd305, 0xd305, 0xd305, 0xd305, 0xd305, 0xd305,
+ 0xd304, 0xd304, 0xd304, 0xd304, 0xd304, 0xd304, 0xd304, 0xd303,
+ 0xd303, 0xd303, 0xd303, 0xd303, 0xd303, 0xd303, 0xd302, 0xd302,
+ 0xd302, 0xd302, 0xd302, 0xd302, 0xd302, 0xd302, 0xd301, 0xd301,
+ 0xd301, 0xd301, 0xd301, 0xd301, 0xd301, 0xd300, 0xd300, 0xd300,
+ 0xd300, 0xd300, 0xd300, 0xd300, 0xd300, 0xd2ff, 0xd2ff, 0xd2ff,
+ 0xd2ff, 0xd2ff, 0xd2ff, 0xd2ff, 0xd2fe, 0xd2fe, 0xd2fe, 0xd2fe,
+ 0xd2fe, 0xd2fe, 0xd2fe, 0xd2fe, 0xd2fd, 0xd2fd, 0xd2fd, 0xd2fd,
+ 0xd2fd, 0xd2fd, 0xd2fd, 0xd2fc, 0xd2fc, 0xd2fc, 0xd2fc, 0xd2fc,
+ 0xd2fc, 0xd2fc, 0xd2fc, 0xd2fb, 0xd2fb, 0xd2fb, 0xd2fb, 0xd2fb,
+ 0xd2fb, 0xd2fb, 0xd2fa, 0xd2fa, 0xd2fa, 0xd2fa, 0xd2fa, 0xd2fa,
+ 0xd2fa, 0xd2fa, 0xd2f9, 0xd2f9, 0xd2f9, 0xd2f9, 0xd2f9, 0xd2f9,
+ 0xd2f9, 0xd2f9, 0xd2f8, 0xd2f8, 0xd2f8, 0xd2f8, 0xd2f8, 0xd2f8,
+ 0xd2f8, 0xd2f7, 0xd2f7, 0xd2f7, 0xd2f7, 0xd2f7, 0xd2f7, 0xd2f7,
+ 0xd2f7, 0xd2f6, 0xd2f6, 0xd2f6, 0xd2f6, 0xd2f6, 0xd2f6, 0xd2f6,
+ 0xd2f6, 0xd2f5, 0xd2f5, 0xd2f5, 0xd2f5, 0xd2f5, 0xd2f5, 0xd2f5,
+ 0xd2f5, 0xd2f4, 0xd2f4, 0xd2f4, 0xd2f4, 0xd2f4, 0xd2f4, 0xd2f4,
+ 0xd2f4, 0xd2f3, 0xd2f3, 0xd2f3, 0xd2f3, 0xd2f3, 0xd2f3, 0xd2f3,
+ 0xd2f2, 0xd2f2, 0xd2f2, 0xd2f2, 0xd2f2, 0xd2f2, 0xd2f2, 0xd2f2,
+ 0xd2f1, 0xd2f1, 0xd2f1, 0xd2f1, 0xd2f1, 0xd2f1, 0xd2f1, 0xd2f1,
+ 0xd2f0, 0xd2f0, 0xd2f0, 0xd2f0, 0xd2f0, 0xd2f0, 0xd2f0, 0xd2f0,
+ 0xd2ef, 0xd2ef, 0xd2ef, 0xd2ef, 0xd2ef, 0xd2ef, 0xd2ef, 0xd2ef,
+ 0xd2ee, 0xd2ee, 0xd2ee, 0xd2ee, 0xd2ed, 0xd2ed, 0xd2ed, 0xd2ed,
+ 0xd2ec, 0xd2ec, 0xd2ec, 0xd2ec, 0xd2eb, 0xd2eb, 0xd2eb, 0xd2eb,
+ 0xd2ea, 0xd2ea, 0xd2ea, 0xd2ea, 0xd2ea, 0xd2e9, 0xd2e9, 0xd2e9,
+ 0xd2e9, 0xd2e8, 0xd2e8, 0xd2e8, 0xd2e8, 0xd2e7, 0xd2e7, 0xd2e7,
+ 0xd2e7, 0xd2e6, 0xd2e6, 0xd2e6, 0xd2e6, 0xd2e5, 0xd2e5, 0xd2e5,
+ 0xd2e5, 0xd2e4, 0xd2e4, 0xd2e4, 0xd2e4, 0xd2e3, 0xd2e3, 0xd2e3,
+ 0xd2e3, 0xd2e2, 0xd2e2, 0xd2e2, 0xd2e2, 0xd2e2, 0xd2e1, 0xd2e1,
+ 0xd2e1, 0xd2e1, 0xd2e0, 0xd2e0, 0xd2e0, 0xd2e0, 0xd2df, 0xd2df,
+ 0xd2df, 0xd2df, 0xd2de, 0xd2de, 0xd2de, 0xd2de, 0xd2de, 0xd2dd,
+ 0xd2dd, 0xd2dd, 0xd2dd, 0xd2dc, 0xd2dc, 0xd2dc, 0xd2dc, 0xd2db,
+ 0xd2db, 0xd2db, 0xd2db, 0xd2db, 0xd2da, 0xd2da, 0xd2da, 0xd2da,
+ 0xd2d9, 0xd2d9, 0xd2d9, 0xd2d9, 0xd2d8, 0xd2d8, 0xd2d8, 0xd2d8,
+ 0xd2d8, 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d7, 0xd2d6, 0xd2d6, 0xd2d6,
+ 0xd2d6, 0xd2d5, 0xd2d5, 0xd2d5, 0xd2d5, 0xd2d5, 0xd2d4, 0xd2d4,
+ 0xd2d4, 0xd2d4, 0xd2d3, 0xd2d3, 0xd2d3, 0xd2d3, 0xd2d3, 0xd2d2,
+ 0xd2d2, 0xd2d2, 0xd2d2, 0xd2d1, 0xd2d1, 0xd2d1, 0xd2d1, 0xd2d1,
+ 0xd2d0, 0xd2d0, 0xd2d0, 0xd2d0, 0xd2cf, 0xd2cf, 0xd2cf, 0xd2cf,
+ 0xd2cf, 0xd2ce, 0xd2ce, 0xd2ce, 0xd2ce, 0xd2cd, 0xd2cd, 0xd2cd,
+ 0xd2cd, 0xd2cd, 0xd2cc, 0xd2cc, 0xd2cc, 0xd2cc, 0xd2cb, 0xd2cb,
+ 0xd2cb, 0xd2cb, 0xd2cb, 0xd2ca, 0xd2ca, 0xd2ca, 0xd2ca, 0xd2ca,
+ 0xd2c9, 0xd2c9, 0xd2c9, 0xd2c9, 0xd2c8, 0xd2c8, 0xd2c8, 0xd2c8,
+ 0xd2c8, 0xd2c7, 0xd2c7, 0xd2c7, 0xd2c7, 0xd2c6, 0xd2c6, 0xd2c6,
+ 0xd2c6, 0xd2c6, 0xd2c5, 0xd2c5, 0xd2c5, 0xd2c5, 0xd2c5, 0xd2c4,
+ 0xd2c4, 0xd2c4, 0xd2c4, 0xd2c4, 0xd2c3, 0xd2c3, 0xd2c3, 0xd2c3,
+ 0xd2c2, 0xd2c2, 0xd2c2, 0xd2c2, 0xd2c2, 0xd2c1, 0xd2c1, 0xd2c1,
+ 0xd2c1, 0xd2c1, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2c0, 0xd2bf,
+ 0xd2bf, 0xd2bf, 0xd2bf, 0xd2be, 0xd2be, 0xd2be, 0xd2be, 0xd2be,
+ 0xd2bd, 0xd2bd, 0xd2bd, 0xd2bd, 0xd2bd, 0xd2bc, 0xd2bc, 0xd2bc,
+ 0xd2bc, 0xd2bc, 0xd2bb, 0xd2bb, 0xd2bb, 0xd2bb, 0xd2bb, 0xd2ba,
+ 0xd2ba, 0xd2ba, 0xd2ba, 0xd2ba, 0xd2b9, 0xd2b9, 0xd2b9, 0xd2b9,
+ 0xd2b9, 0xd2b8, 0xd2b8, 0xd2b8, 0xd2b8, 0xd2b8, 0xd2b7, 0xd2b7,
+ 0xd2b7, 0xd2b7, 0xd2b7, 0xd2b6, 0xd2b6, 0xd2b6, 0xd2b6, 0xd2b6,
+ 0xd2b5, 0xd2b5, 0xd2b5, 0xd2b5, 0xd2b5, 0xd2b4, 0xd2b4, 0xd2b4,
+ 0xd2b4, 0xd2b4, 0xd2b3, 0xd2b3, 0xd2b3, 0xd2b3, 0xd2b3, 0xd2b2,
+ 0xd2b2, 0xd2b2, 0xd2b2, 0xd2b2, 0xd2b1, 0xd2b1, 0xd2b1, 0xd2b1,
+ 0xd2b1, 0xd2b0, 0xd2b0, 0xd2b0, 0xd2b0, 0xd2b0, 0xd2af, 0xd2af,
+ 0xd2af, 0xd2af, 0xd2af, 0xd2ae, 0xd2ae, 0xd2ae, 0xd2ae, 0xd2ae,
+ 0xd2ad, 0xd2ad, 0xd2ad, 0xd2ad, 0xd2ad, 0xd2ac, 0xd2ac, 0xd2ac,
+ 0xd2ac, 0xd2ac, 0xd2ac, 0xd2ab, 0xd2ab, 0xd2ab, 0xd2ab, 0xd2ab,
+ 0xd2aa, 0xd2aa, 0xd2aa, 0xd2aa, 0xd2aa, 0xd2a9, 0xd2a9, 0xd2a9,
+ 0xd2a9, 0xd2a9, 0xd2a8, 0xd2a8, 0xd2a8, 0xd2a8, 0xd2a8, 0xd2a8,
+ 0xd2a7, 0xd2a7, 0xd2a7, 0xd2a7, 0xd2a7, 0xd2a6, 0xd2a6, 0xd2a6,
+ 0xd2a6, 0xd2a6, 0xd2a5, 0xd2a5, 0xd2a5, 0xd2a5, 0xd2a5, 0xd2a4,
+ 0xd2a4, 0xd2a4, 0xd2a4, 0xd2a4, 0xd2a4, 0xd2a3, 0xd2a3, 0xd2a3,
+ 0xd2a3, 0xd2a3, 0xd2a2, 0xd2a2, 0xd2a2, 0xd2a2, 0xd2a2, 0xd2a2,
+ 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a1, 0xd2a0, 0xd2a0, 0xd2a0,
+ 0xd2a0, 0xd2a0, 0xd29f, 0xd29f, 0xd29f, 0xd29f, 0xd29f, 0xd29f,
+ 0xd29e, 0xd29e, 0xd29e, 0xd29e, 0xd29e, 0xd29d, 0xd29d, 0xd29d,
+ 0xd29d, 0xd29d, 0xd29d, 0xd29c, 0xd29c, 0xd29c, 0xd29c, 0xd29c,
+ 0xd29b, 0xd29b, 0xd29b, 0xd29b, 0xd29b, 0xd29b, 0xd29a, 0xd29a,
+ 0xd29a, 0xd29a, 0xd29a, 0xd29a, 0xd299, 0xd299, 0xd299, 0xd299,
+ 0xd299, 0xd298, 0xd298, 0xd298, 0xd298, 0xd298, 0xd298, 0xd297,
+ 0xd297, 0xd297, 0xd297, 0xd297, 0xd296, 0xd296, 0xd296, 0xd296,
+ 0xd296, 0xd296, 0xd295, 0xd295, 0xd295, 0xd295, 0xd295, 0xd295,
+ 0xd294, 0xd294, 0xd294, 0xd294, 0xd294, 0xd293, 0xd293, 0xd293,
+ 0xd293, 0xd293, 0xd293, 0xd292, 0xd292, 0xd292, 0xd292, 0xd292,
+ 0xd292, 0xd291, 0xd291, 0xd291, 0xd291, 0xd291, 0xd291, 0xd290,
+ 0xd290, 0xd290, 0xd290, 0xd290, 0xd28f, 0xd28f, 0xd28f, 0xd28f,
+ 0xd28f, 0xd28f, 0xd28e, 0xd28e, 0xd28e, 0xd28e, 0xd28e, 0xd28e,
+ 0xd28d, 0xd28d, 0xd28d, 0xd28d, 0xd28d, 0xd28d, 0xd28c, 0xd28c,
+ 0xd28c, 0xd28c, 0xd28c, 0xd28c, 0xd28b, 0xd28b, 0xd28b, 0xd28b,
+ 0xd28b, 0xd28b, 0xd28a, 0xd28a, 0xd28a, 0xd28a, 0xd28a, 0xd28a,
+ 0xd289, 0xd289, 0xd289, 0xd289, 0xd289, 0xd288, 0xd288, 0xd288,
+ 0xd288, 0xd288, 0xd288, 0xd287, 0xd287, 0xd287, 0xd287, 0xd287,
+ 0xd287, 0xd286, 0xd286, 0xd286, 0xd286, 0xd286, 0xd286, 0xd285,
+ 0xd285, 0xd285, 0xd285, 0xd285, 0xd285, 0xd285, 0xd284, 0xd284,
+ 0xd284, 0xd284, 0xd284, 0xd284, 0xd283, 0xd283, 0xd283, 0xd283,
+ 0xd283, 0xd283, 0xd282, 0xd282, 0xd282, 0xd282, 0xd282, 0xd282,
+ 0xd281, 0xd281, 0xd281, 0xd281, 0xd281, 0xd281, 0xd280, 0xd280,
+ 0xd280, 0xd280, 0xd280, 0xd280, 0xd27f, 0xd27f, 0xd27f, 0xd27f,
+ 0xd27f, 0xd27f, 0xd27e, 0xd27e, 0xd27e, 0xd27e, 0xd27e, 0xd27e,
+ 0xd27d, 0xd27d, 0xd27d, 0xd27d, 0xd27d, 0xd27d, 0xd27d, 0xd27c,
+ 0xd27c, 0xd27c, 0xd27c, 0xd27c, 0xd27c, 0xd27b, 0xd27b, 0xd27b,
+ 0xd27b, 0xd27b, 0xd27b, 0xd27a, 0xd27a, 0xd27a, 0xd27a, 0xd27a,
+ 0xd27a, 0xd27a, 0xd279, 0xd279, 0xd279, 0xd279, 0xd279, 0xd279,
+ 0xd278, 0xd278, 0xd278, 0xd278, 0xd278, 0xd278, 0xd277, 0xd277,
+ 0xd277, 0xd277, 0xd277, 0xd277, 0xd277, 0xd276, 0xd276, 0xd276,
+ 0xd276, 0xd276, 0xd276, 0xd275, 0xd275, 0xd275, 0xd275, 0xd275,
+ 0xd275, 0xd274, 0xd274, 0xd274, 0xd274, 0xd274, 0xd274, 0xd274,
+ 0xd273, 0xd273, 0xd273, 0xd273, 0xd273, 0xd273, 0xd272, 0xd272,
+ 0xd272, 0xd272, 0xd272, 0xd272, 0xd272, 0xd271, 0xd271, 0xd271,
+ 0xd271, 0xd271, 0xd271, 0xd270, 0xd270, 0xd270, 0xd270, 0xd270,
+ 0xd270, 0xd270, 0xd26f, 0xd26f, 0xd26f, 0xd26f, 0xd26f, 0xd26f,
+ 0xd26f, 0xd26e, 0xd26e, 0xd26e, 0xd26e, 0xd26e, 0xd26e, 0xd26d,
+ 0xd26d, 0xd26d, 0xd26d, 0xd26d, 0xd26d, 0xd26d, 0xd26c, 0xd26c,
+ 0xd26c, 0xd26c, 0xd26c, 0xd26c, 0xd26b, 0xd26b, 0xd26b, 0xd26b,
+ 0xd26b, 0xd26b, 0xd26b, 0xd26a, 0xd26a, 0xd26a, 0xd26a, 0xd26a,
+ 0xd26a, 0xd26a, 0xd269, 0xd269, 0xd269, 0xd269, 0xd269, 0xd269,
+ 0xd269, 0xd268, 0xd268, 0xd268, 0xd268, 0xd268, 0xd268, 0xd267,
+ 0xd267, 0xd267, 0xd267, 0xd267, 0xd267, 0xd267, 0xd266, 0xd266,
+ 0xd266, 0xd266, 0xd266, 0xd266, 0xd266, 0xd265, 0xd265, 0xd265,
+ 0xd265, 0xd265, 0xd265, 0xd265, 0xd264, 0xd264, 0xd264, 0xd264,
+ 0xd264, 0xd264, 0xd264, 0xd263, 0xd263, 0xd263, 0xd263, 0xd263,
+ 0xd263, 0xd263, 0xd262, 0xd262, 0xd262, 0xd262, 0xd262, 0xd262,
+ 0xd261, 0xd261, 0xd261, 0xd261, 0xd261, 0xd261, 0xd261, 0xd260,
+ 0xd260, 0xd260, 0xd260, 0xd260, 0xd260, 0xd260, 0xd25f, 0xd25f,
+ 0xd25f, 0xd25f, 0xd25f, 0xd25f, 0xd25f, 0xd25e, 0xd25e, 0xd25e,
+ 0xd25e, 0xd25e, 0xd25e, 0xd25e, 0xd25d, 0xd25d, 0xd25d, 0xd25d,
+ 0xd25d, 0xd25d, 0xd25d, 0xd25c, 0xd25c, 0xd25c, 0xd25c, 0xd25c,
+ 0xd25c, 0xd25c, 0xd25c, 0xd25b, 0xd25b, 0xd25b, 0xd25b, 0xd25b,
+ 0xd25b, 0xd25b, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a, 0xd25a,
+ 0xd25a, 0xd259, 0xd259, 0xd259, 0xd259, 0xd259, 0xd259, 0xd259,
+ 0xd258, 0xd258, 0xd258, 0xd258, 0xd258, 0xd258, 0xd258, 0xd257,
+ 0xd257, 0xd257, 0xd257, 0xd257, 0xd257, 0xd257, 0xd256, 0xd256,
+ 0xd256, 0xd256, 0xd256, 0xd256, 0xd256, 0xd256, 0xd255, 0xd255,
+ 0xd255, 0xd255, 0xd255, 0xd255, 0xd255, 0xd254, 0xd254, 0xd254,
+ 0xd254, 0xd254, 0xd254, 0xd254, 0xd253, 0xd253, 0xd253, 0xd253,
+ 0xd253, 0xd253, 0xd253, 0xd253, 0xd252, 0xd252, 0xd252, 0xd252,
+ 0xd252, 0xd252, 0xd252, 0xd251, 0xd251, 0xd251, 0xd251, 0xd251,
+ 0xd251, 0xd251, 0xd250, 0xd250, 0xd250, 0xd250, 0xd250, 0xd250,
+ 0xd250, 0xd250, 0xd24f, 0xd24f, 0xd24f, 0xd24f, 0xd24f, 0xd24f,
+ 0xd24f, 0xd24e, 0xd24e, 0xd24e, 0xd24e, 0xd24e, 0xd24e, 0xd24e,
+ 0xd24e, 0xd24d, 0xd24d, 0xd24d, 0xd24d, 0xd24d, 0xd24d, 0xd24d,
+ 0xd24c, 0xd24c, 0xd24c, 0xd24c, 0xd24c, 0xd24c, 0xd24c, 0xd24c,
+ 0xd24b, 0xd24b, 0xd24b, 0xd24b, 0xd24b, 0xd24b, 0xd24b, 0xd24a,
+ 0xd24a, 0xd24a, 0xd24a, 0xd24a, 0xd24a, 0xd24a, 0xd24a, 0xd249,
+ 0xd249, 0xd249, 0xd249, 0xd249, 0xd249, 0xd249, 0xd249, 0xd248,
+ 0xd248, 0xd248, 0xd248, 0xd248, 0xd248, 0xd248, 0xd247, 0xd247,
+ 0xd247, 0xd247, 0xd247, 0xd247, 0xd247, 0xd247, 0xd246, 0xd246,
+ 0xd246, 0xd246, 0xd246, 0xd246, 0xd246, 0xd246, 0xd245, 0xd245,
+ 0xd245, 0xd245, 0xd245, 0xd245, 0xd245, 0xd244, 0xd244, 0xd244,
+ 0xd244, 0xd244, 0xd244, 0xd244, 0xd244, 0xd243, 0xd243, 0xd243,
+ 0xd243, 0xd243, 0xd243, 0xd243, 0xd243, 0xd242, 0xd242, 0xd242,
+ 0xd242, 0xd242, 0xd242, 0xd242, 0xd242, 0xd241, 0xd241, 0xd241,
+ 0xd241, 0xd241, 0xd241, 0xd241, 0xd241, 0xd240, 0xd240, 0xd240,
+ 0xd240, 0xd240, 0xd240, 0xd240, 0xd240, 0xd23f, 0xd23f, 0xd23f,
+ 0xd23f, 0xd23f, 0xd23f, 0xd23f, 0xd23f, 0xd23e, 0xd23e, 0xd23e,
+ 0xd23e, 0xd23e, 0xd23e, 0xd23e, 0xd23e, 0xd23d, 0xd23d, 0xd23d,
+ 0xd23d, 0xd23d, 0xd23d, 0xd23c, 0xd23c, 0xd23c, 0xd23c, 0xd23b,
+ 0xd23b, 0xd23b, 0xd23b, 0xd23a, 0xd23a, 0xd23a, 0xd23a, 0xd239,
+ 0xd239, 0xd239, 0xd239, 0xd238, 0xd238, 0xd238, 0xd238, 0xd237,
+ 0xd237, 0xd237, 0xd237, 0xd236, 0xd236, 0xd236, 0xd236, 0xd235,
+ 0xd235, 0xd235, 0xd235, 0xd234, 0xd234, 0xd234, 0xd234, 0xd233,
+ 0xd233, 0xd233, 0xd233, 0xd232, 0xd232, 0xd232, 0xd232, 0xd232,
+ 0xd231, 0xd231, 0xd231, 0xd231, 0xd230, 0xd230, 0xd230, 0xd230,
+ 0xd22f, 0xd22f, 0xd22f, 0xd22f, 0xd22e, 0xd22e, 0xd22e, 0xd22e,
+ 0xd22d, 0xd22d, 0xd22d, 0xd22d, 0xd22d, 0xd22c, 0xd22c, 0xd22c,
+ 0xd22c, 0xd22b, 0xd22b, 0xd22b, 0xd22b, 0xd22a, 0xd22a, 0xd22a,
+ 0xd22a, 0xd22a, 0xd229, 0xd229, 0xd229, 0xd229, 0xd228, 0xd228,
+ 0xd228, 0xd228, 0xd227, 0xd227, 0xd227, 0xd227, 0xd227, 0xd226,
+ 0xd226, 0xd226, 0xd226, 0xd225, 0xd225, 0xd225, 0xd225, 0xd224,
+ 0xd224, 0xd224, 0xd224, 0xd224, 0xd223, 0xd223, 0xd223, 0xd223,
+ 0xd222, 0xd222, 0xd222, 0xd222, 0xd222, 0xd221, 0xd221, 0xd221,
+ 0xd221, 0xd220, 0xd220, 0xd220, 0xd220, 0xd220, 0xd21f, 0xd21f,
+ 0xd21f, 0xd21f, 0xd21e, 0xd21e, 0xd21e, 0xd21e, 0xd21e, 0xd21d,
+ 0xd21d, 0xd21d, 0xd21d, 0xd21c, 0xd21c, 0xd21c, 0xd21c, 0xd21c,
+ 0xd21b, 0xd21b, 0xd21b, 0xd21b, 0xd21a, 0xd21a, 0xd21a, 0xd21a,
+ 0xd21a, 0xd219, 0xd219, 0xd219, 0xd219, 0xd218, 0xd218, 0xd218,
+ 0xd218, 0xd218, 0xd217, 0xd217, 0xd217, 0xd217, 0xd217, 0xd216,
+ 0xd216, 0xd216, 0xd216, 0xd215, 0xd215, 0xd215, 0xd215, 0xd215,
+ 0xd214, 0xd214, 0xd214, 0xd214, 0xd214, 0xd213, 0xd213, 0xd213,
+ 0xd213, 0xd212, 0xd212, 0xd212, 0xd212, 0xd212, 0xd211, 0xd211,
+ 0xd211, 0xd211, 0xd211, 0xd210, 0xd210, 0xd210, 0xd210, 0xd210,
+ 0xd20f, 0xd20f, 0xd20f, 0xd20f, 0xd20f, 0xd20e, 0xd20e, 0xd20e,
+ 0xd20e, 0xd20d, 0xd20d, 0xd20d, 0xd20d, 0xd20d, 0xd20c, 0xd20c,
+ 0xd20c, 0xd20c, 0xd20c, 0xd20b, 0xd20b, 0xd20b, 0xd20b, 0xd20b,
+ 0xd20a, 0xd20a, 0xd20a, 0xd20a, 0xd20a, 0xd209, 0xd209, 0xd209,
+ 0xd209, 0xd209, 0xd208, 0xd208, 0xd208, 0xd208, 0xd208, 0xd207,
+ 0xd207, 0xd207, 0xd207, 0xd206, 0xd206, 0xd206, 0xd206, 0xd206,
+ 0xd205, 0xd205, 0xd205, 0xd205, 0xd205, 0xd204, 0xd204, 0xd204,
+ 0xd204, 0xd204, 0xd203, 0xd203, 0xd203, 0xd203, 0xd203, 0xd202,
+ 0xd202, 0xd202, 0xd202, 0xd202, 0xd201, 0xd201, 0xd201, 0xd201,
+ 0xd201, 0xd201, 0xd200, 0xd200, 0xd200, 0xd200, 0xd200, 0xd1ff,
+ 0xd1ff, 0xd1ff, 0xd1ff, 0xd1ff, 0xd1fe, 0xd1fe, 0xd1fe, 0xd1fe,
+ 0xd1fe, 0xd1fd, 0xd1fd, 0xd1fd, 0xd1fd, 0xd1fd, 0xd1fc, 0xd1fc,
+ 0xd1fc, 0xd1fc, 0xd1fc, 0xd1fb, 0xd1fb, 0xd1fb, 0xd1fb, 0xd1fb,
+ 0xd1fa, 0xd1fa, 0xd1fa, 0xd1fa, 0xd1fa, 0xd1f9, 0xd1f9, 0xd1f9,
+ 0xd1f9, 0xd1f9, 0xd1f9, 0xd1f8, 0xd1f8, 0xd1f8, 0xd1f8, 0xd1f8,
+ 0xd1f7, 0xd1f7, 0xd1f7, 0xd1f7, 0xd1f7, 0xd1f6, 0xd1f6, 0xd1f6,
+ 0xd1f6, 0xd1f6, 0xd1f5, 0xd1f5, 0xd1f5, 0xd1f5, 0xd1f5, 0xd1f5,
+ 0xd1f4, 0xd1f4, 0xd1f4, 0xd1f4, 0xd1f4, 0xd1f3, 0xd1f3, 0xd1f3,
+ 0xd1f3, 0xd1f3, 0xd1f2, 0xd1f2, 0xd1f2, 0xd1f2, 0xd1f2, 0xd1f2,
+ 0xd1f1, 0xd1f1, 0xd1f1, 0xd1f1, 0xd1f1, 0xd1f0, 0xd1f0, 0xd1f0,
+ 0xd1f0, 0xd1f0, 0xd1f0, 0xd1ef, 0xd1ef, 0xd1ef, 0xd1ef, 0xd1ef,
+ 0xd1ee, 0xd1ee, 0xd1ee, 0xd1ee, 0xd1ee, 0xd1ed, 0xd1ed, 0xd1ed,
+ 0xd1ed, 0xd1ed, 0xd1ed, 0xd1ec, 0xd1ec, 0xd1ec, 0xd1ec, 0xd1ec,
+ 0xd1eb, 0xd1eb, 0xd1eb, 0xd1eb, 0xd1eb, 0xd1eb, 0xd1ea, 0xd1ea,
+ 0xd1ea, 0xd1ea, 0xd1ea, 0xd1e9, 0xd1e9, 0xd1e9, 0xd1e9, 0xd1e9,
+ 0xd1e9, 0xd1e8, 0xd1e8, 0xd1e8, 0xd1e8, 0xd1e8, 0xd1e8, 0xd1e7,
+ 0xd1e7, 0xd1e7, 0xd1e7, 0xd1e7, 0xd1e6, 0xd1e6, 0xd1e6, 0xd1e6,
+ 0xd1e6, 0xd1e6, 0xd1e5, 0xd1e5, 0xd1e5, 0xd1e5, 0xd1e5, 0xd1e4,
+ 0xd1e4, 0xd1e4, 0xd1e4, 0xd1e4, 0xd1e4, 0xd1e3, 0xd1e3, 0xd1e3,
+ 0xd1e3, 0xd1e3, 0xd1e3, 0xd1e2, 0xd1e2, 0xd1e2, 0xd1e2, 0xd1e2,
+ 0xd1e2, 0xd1e1, 0xd1e1, 0xd1e1, 0xd1e1, 0xd1e1, 0xd1e0, 0xd1e0,
+ 0xd1e0, 0xd1e0, 0xd1e0, 0xd1e0, 0xd1df, 0xd1df, 0xd1df, 0xd1df,
+ 0xd1df, 0xd1df, 0xd1de, 0xd1de, 0xd1de, 0xd1de, 0xd1de, 0xd1de,
+ 0xd1dd, 0xd1dd, 0xd1dd, 0xd1dd, 0xd1dd, 0xd1dc, 0xd1dc, 0xd1dc,
+ 0xd1dc, 0xd1dc, 0xd1dc, 0xd1db, 0xd1db, 0xd1db, 0xd1db, 0xd1db,
+ 0xd1db, 0xd1da, 0xd1da, 0xd1da, 0xd1da, 0xd1da, 0xd1da, 0xd1d9,
+ 0xd1d9, 0xd1d9, 0xd1d9, 0xd1d9, 0xd1d9, 0xd1d8, 0xd1d8, 0xd1d8,
+ 0xd1d8, 0xd1d8, 0xd1d8, 0xd1d7, 0xd1d7, 0xd1d7, 0xd1d7, 0xd1d7,
+ 0xd1d7, 0xd1d6, 0xd1d6, 0xd1d6, 0xd1d6, 0xd1d6, 0xd1d6, 0xd1d5,
+ 0xd1d5, 0xd1d5, 0xd1d5, 0xd1d5, 0xd1d5, 0xd1d4, 0xd1d4, 0xd1d4,
+ 0xd1d4, 0xd1d4, 0xd1d4, 0xd1d3, 0xd1d3, 0xd1d3, 0xd1d3, 0xd1d3,
+ 0xd1d3, 0xd1d2, 0xd1d2, 0xd1d2, 0xd1d2, 0xd1d2, 0xd1d2, 0xd1d1,
+ 0xd1d1, 0xd1d1, 0xd1d1, 0xd1d1, 0xd1d1, 0xd1d0, 0xd1d0, 0xd1d0,
+ 0xd1d0, 0xd1d0, 0xd1d0, 0xd1cf, 0xd1cf, 0xd1cf, 0xd1cf, 0xd1cf,
+ 0xd1cf, 0xd1ce, 0xd1ce, 0xd1ce, 0xd1ce, 0xd1ce, 0xd1ce, 0xd1cd,
+ 0xd1cd, 0xd1cd, 0xd1cd, 0xd1cd, 0xd1cd, 0xd1cd, 0xd1cc, 0xd1cc,
+ 0xd1cc, 0xd1cc, 0xd1cc, 0xd1cc, 0xd1cb, 0xd1cb, 0xd1cb, 0xd1cb,
+ 0xd1cb, 0xd1cb, 0xd1ca, 0xd1ca, 0xd1ca, 0xd1ca, 0xd1ca, 0xd1ca,
+ 0xd1c9, 0xd1c9, 0xd1c9, 0xd1c9, 0xd1c9, 0xd1c9, 0xd1c9, 0xd1c8,
+ 0xd1c8, 0xd1c8, 0xd1c8, 0xd1c8, 0xd1c8, 0xd1c7, 0xd1c7, 0xd1c7,
+ 0xd1c7, 0xd1c7, 0xd1c7, 0xd1c6, 0xd1c6, 0xd1c6, 0xd1c6, 0xd1c6,
+ 0xd1c6, 0xd1c6, 0xd1c5, 0xd1c5, 0xd1c5, 0xd1c5, 0xd1c5, 0xd1c5,
+ 0xd1c4, 0xd1c4, 0xd1c4, 0xd1c4, 0xd1c4, 0xd1c4, 0xd1c4, 0xd1c3,
+ 0xd1c3, 0xd1c3, 0xd1c3, 0xd1c3, 0xd1c3, 0xd1c2, 0xd1c2, 0xd1c2,
+ 0xd1c2, 0xd1c2, 0xd1c2, 0xd1c1, 0xd1c1, 0xd1c1, 0xd1c1, 0xd1c1,
+ 0xd1c1, 0xd1c1, 0xd1c0, 0xd1c0, 0xd1c0, 0xd1c0, 0xd1c0, 0xd1c0,
+ 0xd1bf, 0xd1bf, 0xd1bf, 0xd1bf, 0xd1bf, 0xd1bf, 0xd1bf, 0xd1be,
+ 0xd1be, 0xd1be, 0xd1be, 0xd1be, 0xd1be, 0xd1be, 0xd1bd, 0xd1bd,
+ 0xd1bd, 0xd1bd, 0xd1bd, 0xd1bd, 0xd1bc, 0xd1bc, 0xd1bc, 0xd1bc,
+ 0xd1bc, 0xd1bc, 0xd1bc, 0xd1bb, 0xd1bb, 0xd1bb, 0xd1bb, 0xd1bb,
+ 0xd1bb, 0xd1ba, 0xd1ba, 0xd1ba, 0xd1ba, 0xd1ba, 0xd1ba, 0xd1ba,
+ 0xd1b9, 0xd1b9, 0xd1b9, 0xd1b9, 0xd1b9, 0xd1b9, 0xd1b9, 0xd1b8,
+ 0xd1b8, 0xd1b8, 0xd1b8, 0xd1b8, 0xd1b8, 0xd1b8, 0xd1b7, 0xd1b7,
+ 0xd1b7, 0xd1b7, 0xd1b7, 0xd1b7, 0xd1b6, 0xd1b6, 0xd1b6, 0xd1b6,
+ 0xd1b6, 0xd1b6, 0xd1b6, 0xd1b5, 0xd1b5, 0xd1b5, 0xd1b5, 0xd1b5,
+ 0xd1b5, 0xd1b5, 0xd1b4, 0xd1b4, 0xd1b4, 0xd1b4, 0xd1b4, 0xd1b4,
+ 0xd1b4, 0xd1b3, 0xd1b3, 0xd1b3, 0xd1b3, 0xd1b3, 0xd1b3, 0xd1b3,
+ 0xd1b2, 0xd1b2, 0xd1b2, 0xd1b2, 0xd1b2, 0xd1b2, 0xd1b1, 0xd1b1,
+ 0xd1b1, 0xd1b1, 0xd1b1, 0xd1b1, 0xd1b1, 0xd1b0, 0xd1b0, 0xd1b0,
+ 0xd1b0, 0xd1b0, 0xd1b0, 0xd1b0, 0xd1af, 0xd1af, 0xd1af, 0xd1af,
+ 0xd1af, 0xd1af, 0xd1af, 0xd1ae, 0xd1ae, 0xd1ae, 0xd1ae, 0xd1ae,
+ 0xd1ae, 0xd1ae, 0xd1ad, 0xd1ad, 0xd1ad, 0xd1ad, 0xd1ad, 0xd1ad,
+ 0xd1ad, 0xd1ac, 0xd1ac, 0xd1ac, 0xd1ac, 0xd1ac, 0xd1ac, 0xd1ac,
+ 0xd1ab, 0xd1ab, 0xd1ab, 0xd1ab, 0xd1ab, 0xd1ab, 0xd1ab, 0xd1aa,
+ 0xd1aa, 0xd1aa, 0xd1aa, 0xd1aa, 0xd1aa, 0xd1aa, 0xd1a9, 0xd1a9,
+ 0xd1a9, 0xd1a9, 0xd1a9, 0xd1a9, 0xd1a9, 0xd1a9, 0xd1a8, 0xd1a8,
+ 0xd1a8, 0xd1a8, 0xd1a8, 0xd1a8, 0xd1a8, 0xd1a7, 0xd1a7, 0xd1a7,
+ 0xd1a7, 0xd1a7, 0xd1a7, 0xd1a7, 0xd1a6, 0xd1a6, 0xd1a6, 0xd1a6,
+ 0xd1a6, 0xd1a6, 0xd1a6, 0xd1a5, 0xd1a5, 0xd1a5, 0xd1a5, 0xd1a5,
+ 0xd1a5, 0xd1a5, 0xd1a4, 0xd1a4, 0xd1a4, 0xd1a4, 0xd1a4, 0xd1a4,
+ 0xd1a4, 0xd1a4, 0xd1a3, 0xd1a3, 0xd1a3, 0xd1a3, 0xd1a3, 0xd1a3,
+ 0xd1a3, 0xd1a2, 0xd1a2, 0xd1a2, 0xd1a2, 0xd1a2, 0xd1a2, 0xd1a2,
+ 0xd1a1, 0xd1a1, 0xd1a1, 0xd1a1, 0xd1a1, 0xd1a1, 0xd1a1, 0xd1a1,
+ 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a0, 0xd1a0, 0xd19f,
+ 0xd19f, 0xd19f, 0xd19f, 0xd19f, 0xd19f, 0xd19f, 0xd19e, 0xd19e,
+ 0xd19e, 0xd19e, 0xd19e, 0xd19e, 0xd19e, 0xd19e, 0xd19d, 0xd19d,
+ 0xd19d, 0xd19d, 0xd19d, 0xd19d, 0xd19d, 0xd19c, 0xd19c, 0xd19c,
+ 0xd19c, 0xd19c, 0xd19c, 0xd19c, 0xd19c, 0xd19b, 0xd19b, 0xd19b,
+ 0xd19b, 0xd19b, 0xd19b, 0xd19b, 0xd19a, 0xd19a, 0xd19a, 0xd19a,
+ 0xd19a, 0xd19a, 0xd19a, 0xd19a, 0xd199, 0xd199, 0xd199, 0xd199,
+ 0xd199, 0xd199, 0xd199, 0xd199, 0xd198, 0xd198, 0xd198, 0xd198,
+ 0xd198, 0xd198, 0xd198, 0xd197, 0xd197, 0xd197, 0xd197, 0xd197,
+ 0xd197, 0xd197, 0xd197, 0xd196, 0xd196, 0xd196, 0xd196, 0xd196,
+ 0xd196, 0xd196, 0xd196, 0xd195, 0xd195, 0xd195, 0xd195, 0xd195,
+ 0xd195, 0xd195, 0xd194, 0xd194, 0xd194, 0xd194, 0xd194, 0xd194,
+ 0xd194, 0xd194, 0xd193, 0xd193, 0xd193, 0xd193, 0xd193, 0xd193,
+ 0xd193, 0xd193, 0xd192, 0xd192, 0xd192, 0xd192, 0xd192, 0xd192,
+ 0xd192, 0xd192, 0xd191, 0xd191, 0xd191, 0xd191, 0xd191, 0xd191,
+ 0xd191, 0xd190, 0xd190, 0xd190, 0xd190, 0xd190, 0xd190, 0xd190,
+ 0xd190, 0xd18f, 0xd18f, 0xd18f, 0xd18f, 0xd18f, 0xd18f, 0xd18f,
+ 0xd18f, 0xd18e, 0xd18e, 0xd18e, 0xd18e, 0xd18e, 0xd18e, 0xd18e,
+ 0xd18e, 0xd18d, 0xd18d, 0xd18d, 0xd18d, 0xd18d, 0xd18d, 0xd18d,
+ 0xd18d, 0xd18c, 0xd18c, 0xd18c, 0xd18c, 0xd18c, 0xd18c, 0xd18c,
+ 0xd18c, 0xd18b, 0xd18b, 0xd18b, 0xd18b, 0xd18a, 0xd18a, 0xd18a,
+ 0xd18a, 0xd189, 0xd189, 0xd189, 0xd189, 0xd188, 0xd188, 0xd188,
+ 0xd188, 0xd187, 0xd187, 0xd187, 0xd187, 0xd186, 0xd186, 0xd186,
+ 0xd186, 0xd185, 0xd185, 0xd185, 0xd185, 0xd184, 0xd184, 0xd184,
+ 0xd184, 0xd183, 0xd183, 0xd183, 0xd183, 0xd182, 0xd182, 0xd182,
+ 0xd182, 0xd182, 0xd181, 0xd181, 0xd181, 0xd181, 0xd180, 0xd180,
+ 0xd180, 0xd180, 0xd17f, 0xd17f, 0xd17f, 0xd17f, 0xd17e, 0xd17e,
+ 0xd17e, 0xd17e, 0xd17d, 0xd17d, 0xd17d, 0xd17d, 0xd17d, 0xd17c,
+ 0xd17c, 0xd17c, 0xd17c, 0xd17b, 0xd17b, 0xd17b, 0xd17b, 0xd17a,
+ 0xd17a, 0xd17a, 0xd17a, 0xd179, 0xd179, 0xd179, 0xd179, 0xd179,
+ 0xd178, 0xd178, 0xd178, 0xd178, 0xd177, 0xd177, 0xd177, 0xd177,
+ 0xd176, 0xd176, 0xd176, 0xd176, 0xd176, 0xd175, 0xd175, 0xd175,
+ 0xd175, 0xd174, 0xd174, 0xd174, 0xd174, 0xd173, 0xd173, 0xd173,
+ 0xd173, 0xd173, 0xd172, 0xd172, 0xd172, 0xd172, 0xd171, 0xd171,
+ 0xd171, 0xd171, 0xd171, 0xd170, 0xd170, 0xd170, 0xd170, 0xd16f,
+ 0xd16f, 0xd16f, 0xd16f, 0xd16f, 0xd16e, 0xd16e, 0xd16e, 0xd16e,
+ 0xd16d, 0xd16d, 0xd16d, 0xd16d, 0xd16d, 0xd16c, 0xd16c, 0xd16c,
+ 0xd16c, 0xd16b, 0xd16b, 0xd16b, 0xd16b, 0xd16b, 0xd16a, 0xd16a,
+ 0xd16a, 0xd16a, 0xd169, 0xd169, 0xd169, 0xd169, 0xd169, 0xd168,
+ 0xd168, 0xd168, 0xd168, 0xd167, 0xd167, 0xd167, 0xd167, 0xd167,
+ 0xd166, 0xd166, 0xd166, 0xd166, 0xd166, 0xd165, 0xd165, 0xd165,
+ 0xd165, 0xd164, 0xd164, 0xd164, 0xd164, 0xd164, 0xd163, 0xd163,
+ 0xd163, 0xd163, 0xd163, 0xd162, 0xd162, 0xd162, 0xd162, 0xd161,
+ 0xd161, 0xd161, 0xd161, 0xd161, 0xd160, 0xd160, 0xd160, 0xd160,
+ 0xd160, 0xd15f, 0xd15f, 0xd15f, 0xd15f, 0xd15f, 0xd15e, 0xd15e,
+ 0xd15e, 0xd15e, 0xd15d, 0xd15d, 0xd15d, 0xd15d, 0xd15d, 0xd15c,
+ 0xd15c, 0xd15c, 0xd15c, 0xd15c, 0xd15b, 0xd15b, 0xd15b, 0xd15b,
+ 0xd15b, 0xd15a, 0xd15a, 0xd15a, 0xd15a, 0xd15a, 0xd159, 0xd159,
+ 0xd159, 0xd159, 0xd159, 0xd158, 0xd158, 0xd158, 0xd158, 0xd157,
+ 0xd157, 0xd157, 0xd157, 0xd157, 0xd156, 0xd156, 0xd156, 0xd156,
+ 0xd156, 0xd155, 0xd155, 0xd155, 0xd155, 0xd155, 0xd154, 0xd154,
+ 0xd154, 0xd154, 0xd154, 0xd153, 0xd153, 0xd153, 0xd153, 0xd153,
+ 0xd152, 0xd152, 0xd152, 0xd152, 0xd152, 0xd151, 0xd151, 0xd151,
+ 0xd151, 0xd151, 0xd150, 0xd150, 0xd150, 0xd150, 0xd150, 0xd14f,
+ 0xd14f, 0xd14f, 0xd14f, 0xd14f, 0xd14e, 0xd14e, 0xd14e, 0xd14e,
+ 0xd14e, 0xd14d, 0xd14d, 0xd14d, 0xd14d, 0xd14d, 0xd14d, 0xd14c,
+ 0xd14c, 0xd14c, 0xd14c, 0xd14c, 0xd14b, 0xd14b, 0xd14b, 0xd14b,
+ 0xd14b, 0xd14a, 0xd14a, 0xd14a, 0xd14a, 0xd14a, 0xd149, 0xd149,
+ 0xd149, 0xd149, 0xd149, 0xd148, 0xd148, 0xd148, 0xd148, 0xd148,
+ 0xd147, 0xd147, 0xd147, 0xd147, 0xd147, 0xd147, 0xd146, 0xd146,
+ 0xd146, 0xd146, 0xd146, 0xd145, 0xd145, 0xd145, 0xd145, 0xd145,
+ 0xd144, 0xd144, 0xd144, 0xd144, 0xd144, 0xd143, 0xd143, 0xd143,
+ 0xd143, 0xd143, 0xd143, 0xd142, 0xd142, 0xd142, 0xd142, 0xd142,
+ 0xd141, 0xd141, 0xd141, 0xd141, 0xd141, 0xd140, 0xd140, 0xd140,
+ 0xd140, 0xd140, 0xd140, 0xd13f, 0xd13f, 0xd13f, 0xd13f, 0xd13f,
+ 0xd13e, 0xd13e, 0xd13e, 0xd13e, 0xd13e, 0xd13e, 0xd13d, 0xd13d,
+ 0xd13d, 0xd13d, 0xd13d, 0xd13c, 0xd13c, 0xd13c, 0xd13c, 0xd13c,
+ 0xd13c, 0xd13b, 0xd13b, 0xd13b, 0xd13b, 0xd13b, 0xd13a, 0xd13a,
+ 0xd13a, 0xd13a, 0xd13a, 0xd139, 0xd139, 0xd139, 0xd139, 0xd139,
+ 0xd139, 0xd138, 0xd138, 0xd138, 0xd138, 0xd138, 0xd138, 0xd137,
+ 0xd137, 0xd137, 0xd137, 0xd137, 0xd136, 0xd136, 0xd136, 0xd136,
+ 0xd136, 0xd136, 0xd135, 0xd135, 0xd135, 0xd135, 0xd135, 0xd134,
+ 0xd134, 0xd134, 0xd134, 0xd134, 0xd134, 0xd133, 0xd133, 0xd133,
+ 0xd133, 0xd133, 0xd133, 0xd132, 0xd132, 0xd132, 0xd132, 0xd132,
+ 0xd131, 0xd131, 0xd131, 0xd131, 0xd131, 0xd131, 0xd130, 0xd130,
+ 0xd130, 0xd130, 0xd130, 0xd130, 0xd12f, 0xd12f, 0xd12f, 0xd12f,
+ 0xd12f, 0xd12e, 0xd12e, 0xd12e, 0xd12e, 0xd12e, 0xd12e, 0xd12d,
+ 0xd12d, 0xd12d, 0xd12d, 0xd12d, 0xd12d, 0xd12c, 0xd12c, 0xd12c,
+ 0xd12c, 0xd12c, 0xd12c, 0xd12b, 0xd12b, 0xd12b, 0xd12b, 0xd12b,
+ 0xd12b, 0xd12a, 0xd12a, 0xd12a, 0xd12a, 0xd12a, 0xd129, 0xd129,
+ 0xd129, 0xd129, 0xd129, 0xd129, 0xd128, 0xd128, 0xd128, 0xd128,
+ 0xd128, 0xd128, 0xd127, 0xd127, 0xd127, 0xd127, 0xd127, 0xd127,
+ 0xd126, 0xd126, 0xd126, 0xd126, 0xd126, 0xd126, 0xd125, 0xd125,
+ 0xd125, 0xd125, 0xd125, 0xd125, 0xd124, 0xd124, 0xd124, 0xd124,
+ 0xd124, 0xd124, 0xd123, 0xd123, 0xd123, 0xd123, 0xd123, 0xd123,
+ 0xd122, 0xd122, 0xd122, 0xd122, 0xd122, 0xd122, 0xd121, 0xd121,
+ 0xd121, 0xd121, 0xd121, 0xd121, 0xd120, 0xd120, 0xd120, 0xd120,
+ 0xd120, 0xd120, 0xd11f, 0xd11f, 0xd11f, 0xd11f, 0xd11f, 0xd11f,
+ 0xd11e, 0xd11e, 0xd11e, 0xd11e, 0xd11e, 0xd11e, 0xd11e, 0xd11d,
+ 0xd11d, 0xd11d, 0xd11d, 0xd11d, 0xd11d, 0xd11c, 0xd11c, 0xd11c,
+ 0xd11c, 0xd11c, 0xd11c, 0xd11b, 0xd11b, 0xd11b, 0xd11b, 0xd11b,
+ 0xd11b, 0xd11a, 0xd11a, 0xd11a, 0xd11a, 0xd11a, 0xd11a, 0xd119,
+ 0xd119, 0xd119, 0xd119, 0xd119, 0xd119, 0xd119, 0xd118, 0xd118,
+ 0xd118, 0xd118, 0xd118, 0xd118, 0xd117, 0xd117, 0xd117, 0xd117,
+ 0xd117, 0xd117, 0xd116, 0xd116, 0xd116, 0xd116, 0xd116, 0xd116,
+ 0xd116, 0xd115, 0xd115, 0xd115, 0xd115, 0xd115, 0xd115, 0xd114,
+ 0xd114, 0xd114, 0xd114, 0xd114, 0xd114, 0xd113, 0xd113, 0xd113,
+ 0xd113, 0xd113, 0xd113, 0xd113, 0xd112, 0xd112, 0xd112, 0xd112,
+ 0xd112, 0xd112, 0xd111, 0xd111, 0xd111, 0xd111, 0xd111, 0xd111,
+ 0xd111, 0xd110, 0xd110, 0xd110, 0xd110, 0xd110, 0xd110, 0xd10f,
+ 0xd10f, 0xd10f, 0xd10f, 0xd10f, 0xd10f, 0xd10f, 0xd10e, 0xd10e,
+ 0xd10e, 0xd10e, 0xd10e, 0xd10e, 0xd10d, 0xd10d, 0xd10d, 0xd10d,
+ 0xd10d, 0xd10d, 0xd10d, 0xd10c, 0xd10c, 0xd10c, 0xd10c, 0xd10c,
+ 0xd10c, 0xd10b, 0xd10b, 0xd10b, 0xd10b, 0xd10b, 0xd10b, 0xd10b,
+ 0xd10a, 0xd10a, 0xd10a, 0xd10a, 0xd10a, 0xd10a, 0xd109, 0xd109,
+ 0xd109, 0xd109, 0xd109, 0xd109, 0xd109, 0xd108, 0xd108, 0xd108,
+ 0xd108, 0xd108, 0xd108, 0xd108, 0xd107, 0xd107, 0xd107, 0xd107,
+ 0xd107, 0xd107, 0xd107, 0xd106, 0xd106, 0xd106, 0xd106, 0xd106,
+ 0xd106, 0xd105, 0xd105, 0xd105, 0xd105, 0xd105, 0xd105, 0xd105,
+ 0xd104, 0xd104, 0xd104, 0xd104, 0xd104, 0xd104, 0xd104, 0xd103,
+ 0xd103, 0xd103, 0xd103, 0xd103, 0xd103, 0xd103, 0xd102, 0xd102,
+ 0xd102, 0xd102, 0xd102, 0xd102, 0xd101, 0xd101, 0xd101, 0xd101,
+ 0xd101, 0xd101, 0xd101, 0xd100, 0xd100, 0xd100, 0xd100, 0xd100,
+ 0xd100, 0xd100, 0xd0ff, 0xd0ff, 0xd0ff, 0xd0ff, 0xd0ff, 0xd0ff,
+ 0xd0ff, 0xd0fe, 0xd0fe, 0xd0fe, 0xd0fe, 0xd0fe, 0xd0fe, 0xd0fe,
+ 0xd0fd, 0xd0fd, 0xd0fd, 0xd0fd, 0xd0fd, 0xd0fd, 0xd0fd, 0xd0fc,
+ 0xd0fc, 0xd0fc, 0xd0fc, 0xd0fc, 0xd0fc, 0xd0fc, 0xd0fb, 0xd0fb,
+ 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fb, 0xd0fa, 0xd0fa, 0xd0fa,
+ 0xd0fa, 0xd0fa, 0xd0fa, 0xd0fa, 0xd0f9, 0xd0f9, 0xd0f9, 0xd0f9,
+ 0xd0f9, 0xd0f9, 0xd0f9, 0xd0f8, 0xd0f8, 0xd0f8, 0xd0f8, 0xd0f8,
+ 0xd0f8, 0xd0f8, 0xd0f7, 0xd0f7, 0xd0f7, 0xd0f7, 0xd0f7, 0xd0f7,
+ 0xd0f7, 0xd0f7, 0xd0f6, 0xd0f6, 0xd0f6, 0xd0f6, 0xd0f6, 0xd0f6,
+ 0xd0f6, 0xd0f5, 0xd0f5, 0xd0f5, 0xd0f5, 0xd0f5, 0xd0f5, 0xd0f5,
+ 0xd0f4, 0xd0f4, 0xd0f4, 0xd0f4, 0xd0f4, 0xd0f4, 0xd0f4, 0xd0f3,
+ 0xd0f3, 0xd0f3, 0xd0f3, 0xd0f3, 0xd0f3, 0xd0f3, 0xd0f2, 0xd0f2,
+ 0xd0f2, 0xd0f2, 0xd0f2, 0xd0f2, 0xd0f2, 0xd0f2, 0xd0f1, 0xd0f1,
+ 0xd0f1, 0xd0f1, 0xd0f1, 0xd0f1, 0xd0f1, 0xd0f0, 0xd0f0, 0xd0f0,
+ 0xd0f0, 0xd0f0, 0xd0f0, 0xd0f0, 0xd0ef, 0xd0ef, 0xd0ef, 0xd0ef,
+ 0xd0ef, 0xd0ef, 0xd0ef, 0xd0ef, 0xd0ee, 0xd0ee, 0xd0ee, 0xd0ee,
+ 0xd0ee, 0xd0ee, 0xd0ee, 0xd0ed, 0xd0ed, 0xd0ed, 0xd0ed, 0xd0ed,
+ 0xd0ed, 0xd0ed, 0xd0ed, 0xd0ec, 0xd0ec, 0xd0ec, 0xd0ec, 0xd0ec,
+ 0xd0ec, 0xd0ec, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb, 0xd0eb,
+ 0xd0eb, 0xd0eb, 0xd0ea, 0xd0ea, 0xd0ea, 0xd0ea, 0xd0ea, 0xd0ea,
+ 0xd0ea, 0xd0e9, 0xd0e9, 0xd0e9, 0xd0e9, 0xd0e9, 0xd0e9, 0xd0e9,
+ 0xd0e9, 0xd0e8, 0xd0e8, 0xd0e8, 0xd0e8, 0xd0e8, 0xd0e8, 0xd0e8,
+ 0xd0e7, 0xd0e7, 0xd0e7, 0xd0e7, 0xd0e7, 0xd0e7, 0xd0e7, 0xd0e7,
+ 0xd0e6, 0xd0e6, 0xd0e6, 0xd0e6, 0xd0e6, 0xd0e6, 0xd0e6, 0xd0e5,
+ 0xd0e5, 0xd0e5, 0xd0e5, 0xd0e5, 0xd0e5, 0xd0e5, 0xd0e5, 0xd0e4,
+ 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e4, 0xd0e3,
+ 0xd0e3, 0xd0e3, 0xd0e3, 0xd0e3, 0xd0e3, 0xd0e3, 0xd0e3, 0xd0e2,
+ 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e2, 0xd0e1, 0xd0e1,
+ 0xd0e1, 0xd0e1, 0xd0e1, 0xd0e1, 0xd0e1, 0xd0e1, 0xd0e0, 0xd0e0,
+ 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e0, 0xd0e0, 0xd0df, 0xd0df,
+ 0xd0df, 0xd0df, 0xd0df, 0xd0df, 0xd0df, 0xd0df, 0xd0de, 0xd0de,
+ 0xd0de, 0xd0de, 0xd0de, 0xd0de, 0xd0de, 0xd0de, 0xd0dd, 0xd0dd,
+ 0xd0dd, 0xd0dd, 0xd0dd, 0xd0dd, 0xd0dd, 0xd0dd, 0xd0dc, 0xd0dc,
+ 0xd0dc, 0xd0dc, 0xd0dc, 0xd0dc, 0xd0dc, 0xd0db, 0xd0db, 0xd0db,
+ 0xd0db, 0xd0db, 0xd0db, 0xd0db, 0xd0db, 0xd0da, 0xd0da, 0xd0da,
+ 0xd0da, 0xd0da, 0xd0da, 0xd0d9, 0xd0d9, 0xd0d9, 0xd0d9, 0xd0d8,
+ 0xd0d8, 0xd0d8, 0xd0d8, 0xd0d7, 0xd0d7, 0xd0d7, 0xd0d7, 0xd0d6,
+ 0xd0d6, 0xd0d6, 0xd0d6, 0xd0d5, 0xd0d5, 0xd0d5, 0xd0d5, 0xd0d4,
+ 0xd0d4, 0xd0d4, 0xd0d4, 0xd0d3, 0xd0d3, 0xd0d3, 0xd0d3, 0xd0d2,
+ 0xd0d2, 0xd0d2, 0xd0d2, 0xd0d2, 0xd0d1, 0xd0d1, 0xd0d1, 0xd0d1,
+ 0xd0d0, 0xd0d0, 0xd0d0, 0xd0d0, 0xd0cf, 0xd0cf, 0xd0cf, 0xd0cf,
+ 0xd0ce, 0xd0ce, 0xd0ce, 0xd0ce, 0xd0cd, 0xd0cd, 0xd0cd, 0xd0cd,
+ 0xd0cc, 0xd0cc, 0xd0cc, 0xd0cc, 0xd0cc, 0xd0cb, 0xd0cb, 0xd0cb,
+ 0xd0cb, 0xd0ca, 0xd0ca, 0xd0ca, 0xd0ca, 0xd0c9, 0xd0c9, 0xd0c9,
+ 0xd0c9, 0xd0c8, 0xd0c8, 0xd0c8, 0xd0c8, 0xd0c8, 0xd0c7, 0xd0c7,
+ 0xd0c7, 0xd0c7, 0xd0c6, 0xd0c6, 0xd0c6, 0xd0c6, 0xd0c5, 0xd0c5,
+ 0xd0c5, 0xd0c5, 0xd0c5, 0xd0c4, 0xd0c4, 0xd0c4, 0xd0c4, 0xd0c3,
+ 0xd0c3, 0xd0c3, 0xd0c3, 0xd0c2, 0xd0c2, 0xd0c2, 0xd0c2, 0xd0c2,
+ 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c1, 0xd0c0, 0xd0c0, 0xd0c0, 0xd0c0,
+ 0xd0c0, 0xd0bf, 0xd0bf, 0xd0bf, 0xd0bf, 0xd0be, 0xd0be, 0xd0be,
+ 0xd0be, 0xd0be, 0xd0bd, 0xd0bd, 0xd0bd, 0xd0bd, 0xd0bc, 0xd0bc,
+ 0xd0bc, 0xd0bc, 0xd0bc, 0xd0bb, 0xd0bb, 0xd0bb, 0xd0bb, 0xd0ba,
+ 0xd0ba, 0xd0ba, 0xd0ba, 0xd0ba, 0xd0b9, 0xd0b9, 0xd0b9, 0xd0b9,
+ 0xd0b8, 0xd0b8, 0xd0b8, 0xd0b8, 0xd0b8, 0xd0b7, 0xd0b7, 0xd0b7,
+ 0xd0b7, 0xd0b6, 0xd0b6, 0xd0b6, 0xd0b6, 0xd0b6, 0xd0b5, 0xd0b5,
+ 0xd0b5, 0xd0b5, 0xd0b5, 0xd0b4, 0xd0b4, 0xd0b4, 0xd0b4, 0xd0b3,
+ 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b3, 0xd0b2, 0xd0b2, 0xd0b2, 0xd0b2,
+ 0xd0b2, 0xd0b1, 0xd0b1, 0xd0b1, 0xd0b1, 0xd0b0, 0xd0b0, 0xd0b0,
+ 0xd0b0, 0xd0b0, 0xd0af, 0xd0af, 0xd0af, 0xd0af, 0xd0af, 0xd0ae,
+ 0xd0ae, 0xd0ae, 0xd0ae, 0xd0ad, 0xd0ad, 0xd0ad, 0xd0ad, 0xd0ad,
+ 0xd0ac, 0xd0ac, 0xd0ac, 0xd0ac, 0xd0ac, 0xd0ab, 0xd0ab, 0xd0ab,
+ 0xd0ab, 0xd0ab, 0xd0aa, 0xd0aa, 0xd0aa, 0xd0aa, 0xd0aa, 0xd0a9,
+ 0xd0a9, 0xd0a9, 0xd0a9, 0xd0a9, 0xd0a8, 0xd0a8, 0xd0a8, 0xd0a8,
+ 0xd0a7, 0xd0a7, 0xd0a7, 0xd0a7, 0xd0a7, 0xd0a6, 0xd0a6, 0xd0a6,
+ 0xd0a6, 0xd0a6, 0xd0a5, 0xd0a5, 0xd0a5, 0xd0a5, 0xd0a5, 0xd0a4,
+ 0xd0a4, 0xd0a4, 0xd0a4, 0xd0a4, 0xd0a3, 0xd0a3, 0xd0a3, 0xd0a3,
+ 0xd0a3, 0xd0a2, 0xd0a2, 0xd0a2, 0xd0a2, 0xd0a2, 0xd0a1, 0xd0a1,
+ 0xd0a1, 0xd0a1, 0xd0a1, 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a0, 0xd0a0,
+ 0xd09f, 0xd09f, 0xd09f, 0xd09f, 0xd09f, 0xd09e, 0xd09e, 0xd09e,
+ 0xd09e, 0xd09e, 0xd09d, 0xd09d, 0xd09d, 0xd09d, 0xd09d, 0xd09c,
+ 0xd09c, 0xd09c, 0xd09c, 0xd09c, 0xd09b, 0xd09b, 0xd09b, 0xd09b,
+ 0xd09b, 0xd09a, 0xd09a, 0xd09a, 0xd09a, 0xd09a, 0xd09a, 0xd099,
+ 0xd099, 0xd099, 0xd099, 0xd099, 0xd098, 0xd098, 0xd098, 0xd098,
+ 0xd098, 0xd097, 0xd097, 0xd097, 0xd097, 0xd097, 0xd096, 0xd096,
+ 0xd096, 0xd096, 0xd096, 0xd095, 0xd095, 0xd095, 0xd095, 0xd095,
+ 0xd095, 0xd094, 0xd094, 0xd094, 0xd094, 0xd094, 0xd093, 0xd093,
+ 0xd093, 0xd093, 0xd093, 0xd092, 0xd092, 0xd092, 0xd092, 0xd092,
+ 0xd091, 0xd091, 0xd091, 0xd091, 0xd091, 0xd091, 0xd090, 0xd090,
+ 0xd090, 0xd090, 0xd090, 0xd08f, 0xd08f, 0xd08f, 0xd08f, 0xd08f,
+ 0xd08e, 0xd08e, 0xd08e, 0xd08e, 0xd08e, 0xd08e, 0xd08d, 0xd08d,
+ 0xd08d, 0xd08d, 0xd08d, 0xd08c, 0xd08c, 0xd08c, 0xd08c, 0xd08c,
+ 0xd08c, 0xd08b, 0xd08b, 0xd08b, 0xd08b, 0xd08b, 0xd08a, 0xd08a,
+ 0xd08a, 0xd08a, 0xd08a, 0xd08a, 0xd089, 0xd089, 0xd089, 0xd089,
+ 0xd089, 0xd088, 0xd088, 0xd088, 0xd088, 0xd088, 0xd088, 0xd087,
+ 0xd087, 0xd087, 0xd087, 0xd087, 0xd086, 0xd086, 0xd086, 0xd086,
+ 0xd086, 0xd086, 0xd085, 0xd085, 0xd085, 0xd085, 0xd085, 0xd084,
+ 0xd084, 0xd084, 0xd084, 0xd084, 0xd084, 0xd083, 0xd083, 0xd083,
+ 0xd083, 0xd083, 0xd082, 0xd082, 0xd082, 0xd082, 0xd082, 0xd082,
+ 0xd081, 0xd081, 0xd081, 0xd081, 0xd081, 0xd081, 0xd080, 0xd080,
+ 0xd080, 0xd080, 0xd080, 0xd07f, 0xd07f, 0xd07f, 0xd07f, 0xd07f,
+ 0xd07f, 0xd07e, 0xd07e, 0xd07e, 0xd07e, 0xd07e, 0xd07e, 0xd07d,
+ 0xd07d, 0xd07d, 0xd07d, 0xd07d, 0xd07d, 0xd07c, 0xd07c, 0xd07c,
+ 0xd07c, 0xd07c, 0xd07b, 0xd07b, 0xd07b, 0xd07b, 0xd07b, 0xd07b,
+ 0xd07a, 0xd07a, 0xd07a, 0xd07a, 0xd07a, 0xd07a, 0xd079, 0xd079,
+ 0xd079, 0xd079, 0xd079, 0xd079, 0xd078, 0xd078, 0xd078, 0xd078,
+ 0xd078, 0xd078, 0xd077, 0xd077, 0xd077, 0xd077, 0xd077, 0xd077,
+ 0xd076, 0xd076, 0xd076, 0xd076, 0xd076, 0xd076, 0xd075, 0xd075,
+ 0xd075, 0xd075, 0xd075, 0xd074, 0xd074, 0xd074, 0xd074, 0xd074,
+ 0xd074, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd073, 0xd072,
+ 0xd072, 0xd072, 0xd072, 0xd072, 0xd072, 0xd071, 0xd071, 0xd071,
+ 0xd071, 0xd071, 0xd071, 0xd070, 0xd070, 0xd070, 0xd070, 0xd070,
+ 0xd070, 0xd070, 0xd06f, 0xd06f, 0xd06f, 0xd06f, 0xd06f, 0xd06f,
+ 0xd06e, 0xd06e, 0xd06e, 0xd06e, 0xd06e, 0xd06e, 0xd06d, 0xd06d,
+ 0xd06d, 0xd06d, 0xd06d, 0xd06d, 0xd06c, 0xd06c, 0xd06c, 0xd06c,
+ 0xd06c, 0xd06c, 0xd06b, 0xd06b, 0xd06b, 0xd06b, 0xd06b, 0xd06b,
+ 0xd06a, 0xd06a, 0xd06a, 0xd06a, 0xd06a, 0xd06a, 0xd069, 0xd069,
+ 0xd069, 0xd069, 0xd069, 0xd069, 0xd069, 0xd068, 0xd068, 0xd068,
+ 0xd068, 0xd068, 0xd068, 0xd067, 0xd067, 0xd067, 0xd067, 0xd067,
+ 0xd067, 0xd066, 0xd066, 0xd066, 0xd066, 0xd066, 0xd066, 0xd065,
+ 0xd065, 0xd065, 0xd065, 0xd065, 0xd065, 0xd065, 0xd064, 0xd064,
+ 0xd064, 0xd064, 0xd064, 0xd064, 0xd063, 0xd063, 0xd063, 0xd063,
+ 0xd063, 0xd063, 0xd062, 0xd062, 0xd062, 0xd062, 0xd062, 0xd062,
+ 0xd062, 0xd061, 0xd061, 0xd061, 0xd061, 0xd061, 0xd061, 0xd060,
+ 0xd060, 0xd060, 0xd060, 0xd060, 0xd060, 0xd060, 0xd05f, 0xd05f,
+ 0xd05f, 0xd05f, 0xd05f, 0xd05f, 0xd05e, 0xd05e, 0xd05e, 0xd05e,
+ 0xd05e, 0xd05e, 0xd05e, 0xd05d, 0xd05d, 0xd05d, 0xd05d, 0xd05d,
+ 0xd05d, 0xd05c, 0xd05c, 0xd05c, 0xd05c, 0xd05c, 0xd05c, 0xd05c,
+ 0xd05b, 0xd05b, 0xd05b, 0xd05b, 0xd05b, 0xd05b, 0xd05a, 0xd05a,
+ 0xd05a, 0xd05a, 0xd05a, 0xd05a, 0xd05a, 0xd059, 0xd059, 0xd059,
+ 0xd059, 0xd059, 0xd059, 0xd059, 0xd058, 0xd058, 0xd058, 0xd058,
+ 0xd058, 0xd058, 0xd057, 0xd057, 0xd057, 0xd057, 0xd057, 0xd057,
+ 0xd057, 0xd056, 0xd056, 0xd056, 0xd056, 0xd056, 0xd056, 0xd056,
+ 0xd055, 0xd055, 0xd055, 0xd055, 0xd055, 0xd055, 0xd054, 0xd054,
+ 0xd054, 0xd054, 0xd054, 0xd054, 0xd054, 0xd053, 0xd053, 0xd053,
+ 0xd053, 0xd053, 0xd053, 0xd053, 0xd052, 0xd052, 0xd052, 0xd052,
+ 0xd052, 0xd052, 0xd052, 0xd051, 0xd051, 0xd051, 0xd051, 0xd051,
+ 0xd051, 0xd050, 0xd050, 0xd050, 0xd050, 0xd050, 0xd050, 0xd050,
+ 0xd04f, 0xd04f, 0xd04f, 0xd04f, 0xd04f, 0xd04f, 0xd04f, 0xd04e,
+ 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0xd04e, 0xd04d, 0xd04d,
+ 0xd04d, 0xd04d, 0xd04d, 0xd04d, 0xd04d, 0xd04c, 0xd04c, 0xd04c,
+ 0xd04c, 0xd04c, 0xd04c, 0xd04c, 0xd04b, 0xd04b, 0xd04b, 0xd04b,
+ 0xd04b, 0xd04b, 0xd04b, 0xd04a, 0xd04a, 0xd04a, 0xd04a, 0xd04a,
+ 0xd04a, 0xd04a, 0xd049, 0xd049, 0xd049, 0xd049, 0xd049, 0xd049,
+ 0xd049, 0xd048, 0xd048, 0xd048, 0xd048, 0xd048, 0xd048, 0xd048,
+ 0xd047, 0xd047, 0xd047, 0xd047, 0xd047, 0xd047, 0xd047, 0xd046,
+ 0xd046, 0xd046, 0xd046, 0xd046, 0xd046, 0xd046, 0xd045, 0xd045,
+ 0xd045, 0xd045, 0xd045, 0xd045, 0xd045, 0xd045, 0xd044, 0xd044,
+ 0xd044, 0xd044, 0xd044, 0xd044, 0xd044, 0xd043, 0xd043, 0xd043,
+ 0xd043, 0xd043, 0xd043, 0xd043, 0xd042, 0xd042, 0xd042, 0xd042,
+ 0xd042, 0xd042, 0xd042, 0xd041, 0xd041, 0xd041, 0xd041, 0xd041,
+ 0xd041, 0xd041, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040, 0xd040,
+ 0xd040, 0xd040, 0xd03f, 0xd03f, 0xd03f, 0xd03f, 0xd03f, 0xd03f,
+ 0xd03f, 0xd03e, 0xd03e, 0xd03e, 0xd03e, 0xd03e, 0xd03e, 0xd03e,
+ 0xd03d, 0xd03d, 0xd03d, 0xd03d, 0xd03d, 0xd03d, 0xd03d, 0xd03d,
+ 0xd03c, 0xd03c, 0xd03c, 0xd03c, 0xd03c, 0xd03c, 0xd03c, 0xd03b,
+ 0xd03b, 0xd03b, 0xd03b, 0xd03b, 0xd03b, 0xd03b, 0xd03b, 0xd03a,
+ 0xd03a, 0xd03a, 0xd03a, 0xd03a, 0xd03a, 0xd03a, 0xd039, 0xd039,
+ 0xd039, 0xd039, 0xd039, 0xd039, 0xd039, 0xd039, 0xd038, 0xd038,
+ 0xd038, 0xd038, 0xd038, 0xd038, 0xd038, 0xd037, 0xd037, 0xd037,
+ 0xd037, 0xd037, 0xd037, 0xd037, 0xd037, 0xd036, 0xd036, 0xd036,
+ 0xd036, 0xd036, 0xd036, 0xd036, 0xd035, 0xd035, 0xd035, 0xd035,
+ 0xd035, 0xd035, 0xd035, 0xd035, 0xd034, 0xd034, 0xd034, 0xd034,
+ 0xd034, 0xd034, 0xd034, 0xd034, 0xd033, 0xd033, 0xd033, 0xd033,
+ 0xd033, 0xd033, 0xd033, 0xd032, 0xd032, 0xd032, 0xd032, 0xd032,
+ 0xd032, 0xd032, 0xd032, 0xd031, 0xd031, 0xd031, 0xd031, 0xd031,
+ 0xd031, 0xd031, 0xd031, 0xd030, 0xd030, 0xd030, 0xd030, 0xd030,
+ 0xd030, 0xd030, 0xd030, 0xd02f, 0xd02f, 0xd02f, 0xd02f, 0xd02f,
+ 0xd02f, 0xd02f, 0xd02e, 0xd02e, 0xd02e, 0xd02e, 0xd02e, 0xd02e,
+ 0xd02e, 0xd02e, 0xd02d, 0xd02d, 0xd02d, 0xd02d, 0xd02d, 0xd02d,
+ 0xd02d, 0xd02d, 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xd02c, 0xd02c,
+ 0xd02c, 0xd02c, 0xd02b, 0xd02b, 0xd02b, 0xd02b, 0xd02b, 0xd02b,
+ 0xd02b, 0xd02b, 0xd02a, 0xd02a, 0xd02a, 0xd02a, 0xd02a, 0xd02a,
+ 0xd02a, 0xd02a, 0xd029, 0xd029, 0xd029, 0xd029, 0xd029, 0xd029,
+ 0xd029, 0xd028, 0xd028, 0xd028, 0xd028, 0xd027, 0xd027, 0xd027,
+ 0xd027, 0xd026, 0xd026, 0xd026, 0xd026, 0xd025, 0xd025, 0xd025,
+ 0xd025, 0xd024, 0xd024, 0xd024, 0xd024, 0xd023, 0xd023, 0xd023,
+ 0xd023, 0xd022, 0xd022, 0xd022, 0xd022, 0xd022, 0xd021, 0xd021,
+ 0xd021, 0xd021, 0xd020, 0xd020, 0xd020, 0xd020, 0xd01f, 0xd01f,
+ 0xd01f, 0xd01f, 0xd01e, 0xd01e, 0xd01e, 0xd01e, 0xd01d, 0xd01d,
+ 0xd01d, 0xd01d, 0xd01c, 0xd01c, 0xd01c, 0xd01c, 0xd01c, 0xd01b,
+ 0xd01b, 0xd01b, 0xd01b, 0xd01a, 0xd01a, 0xd01a, 0xd01a, 0xd019,
+ 0xd019, 0xd019, 0xd019, 0xd018, 0xd018, 0xd018, 0xd018, 0xd018,
+ 0xd017, 0xd017, 0xd017, 0xd017, 0xd016, 0xd016, 0xd016, 0xd016,
+ 0xd015, 0xd015, 0xd015, 0xd015, 0xd014, 0xd014, 0xd014, 0xd014,
+ 0xd014, 0xd013, 0xd013, 0xd013, 0xd013, 0xd012, 0xd012, 0xd012,
+ 0xd012, 0xd012, 0xd011, 0xd011, 0xd011, 0xd011, 0xd010, 0xd010,
+ 0xd010, 0xd010, 0xd00f, 0xd00f, 0xd00f, 0xd00f, 0xd00f, 0xd00e,
+ 0xd00e, 0xd00e, 0xd00e, 0xd00d, 0xd00d, 0xd00d, 0xd00d, 0xd00d,
+ 0xd00c, 0xd00c, 0xd00c, 0xd00c, 0xd00b, 0xd00b, 0xd00b, 0xd00b,
+ 0xd00b, 0xd00a, 0xd00a, 0xd00a, 0xd00a, 0xd009, 0xd009, 0xd009,
+ 0xd009, 0xd009, 0xd008, 0xd008, 0xd008, 0xd008, 0xd007, 0xd007,
+ 0xd007, 0xd007, 0xd007, 0xd006, 0xd006, 0xd006, 0xd006, 0xd005,
+ 0xd005, 0xd005, 0xd005, 0xd005, 0xd004, 0xd004, 0xd004, 0xd004,
+ 0xd004, 0xd003, 0xd003, 0xd003, 0xd003, 0xd002, 0xd002, 0xd002,
+ 0xd002, 0xd002, 0xd001, 0xd001, 0xd001, 0xd001, 0xd000, 0xd000,
+ 0xd000, 0xd000, 0xcfff, 0xcfff, 0xcffe, 0xcffe, 0xcffe, 0xcffd,
+ 0xcffd, 0xcffc, 0xcffc, 0xcffb, 0xcffb, 0xcffb, 0xcffa, 0xcffa,
+ 0xcff9, 0xcff9, 0xcff9, 0xcff8, 0xcff8, 0xcff7, 0xcff7, 0xcff6,
+ 0xcff6, 0xcff6, 0xcff5, 0xcff5, 0xcff4, 0xcff4, 0xcff3, 0xcff3,
+ 0xcff3, 0xcff2, 0xcff2, 0xcff1, 0xcff1, 0xcff1, 0xcff0, 0xcff0,
+ 0xcfef, 0xcfef, 0xcfef, 0xcfee, 0xcfee, 0xcfed, 0xcfed, 0xcfec,
+ 0xcfec, 0xcfec, 0xcfeb, 0xcfeb, 0xcfea, 0xcfea, 0xcfea, 0xcfe9,
+ 0xcfe9, 0xcfe8, 0xcfe8, 0xcfe8, 0xcfe7, 0xcfe7, 0xcfe6, 0xcfe6,
+ 0xcfe6, 0xcfe5, 0xcfe5, 0xcfe4, 0xcfe4, 0xcfe4, 0xcfe3, 0xcfe3,
+ 0xcfe2, 0xcfe2, 0xcfe2, 0xcfe1, 0xcfe1, 0xcfe0, 0xcfe0, 0xcfdf,
+ 0xcfdf, 0xcfdf, 0xcfde, 0xcfde, 0xcfde, 0xcfdd, 0xcfdd, 0xcfdc,
+ 0xcfdc, 0xcfdc, 0xcfdb, 0xcfdb, 0xcfda, 0xcfda, 0xcfda, 0xcfd9,
+ 0xcfd9, 0xcfd8, 0xcfd8, 0xcfd8, 0xcfd7, 0xcfd7, 0xcfd6, 0xcfd6,
+ 0xcfd6, 0xcfd5, 0xcfd5, 0xcfd4, 0xcfd4, 0xcfd4, 0xcfd3, 0xcfd3,
+ 0xcfd2, 0xcfd2, 0xcfd2, 0xcfd1, 0xcfd1, 0xcfd1, 0xcfd0, 0xcfd0,
+ 0xcfcf, 0xcfcf, 0xcfcf, 0xcfce, 0xcfce, 0xcfcd, 0xcfcd, 0xcfcd,
+ 0xcfcc, 0xcfcc, 0xcfcb, 0xcfcb, 0xcfcb, 0xcfca, 0xcfca, 0xcfca,
+ 0xcfc9, 0xcfc9, 0xcfc8, 0xcfc8, 0xcfc8, 0xcfc7, 0xcfc7, 0xcfc6,
+ 0xcfc6, 0xcfc6, 0xcfc5, 0xcfc5, 0xcfc5, 0xcfc4, 0xcfc4, 0xcfc3,
+ 0xcfc3, 0xcfc3, 0xcfc2, 0xcfc2, 0xcfc2, 0xcfc1, 0xcfc1, 0xcfc0,
+ 0xcfc0, 0xcfc0, 0xcfbf, 0xcfbf, 0xcfbf, 0xcfbe, 0xcfbe, 0xcfbd,
+ 0xcfbd, 0xcfbd, 0xcfbc, 0xcfbc, 0xcfbc, 0xcfbb, 0xcfbb, 0xcfba,
+ 0xcfba, 0xcfba, 0xcfb9, 0xcfb9, 0xcfb9, 0xcfb8, 0xcfb8, 0xcfb7,
+ 0xcfb7, 0xcfb7, 0xcfb6, 0xcfb6, 0xcfb6, 0xcfb5, 0xcfb5, 0xcfb5,
+ 0xcfb4, 0xcfb4, 0xcfb3, 0xcfb3, 0xcfb3, 0xcfb2, 0xcfb2, 0xcfb2,
+ 0xcfb1, 0xcfb1, 0xcfb0, 0xcfb0, 0xcfb0, 0xcfaf, 0xcfaf, 0xcfaf,
+ 0xcfae, 0xcfae, 0xcfae, 0xcfad, 0xcfad, 0xcfac, 0xcfac, 0xcfac,
+ 0xcfab, 0xcfab, 0xcfab, 0xcfaa, 0xcfaa, 0xcfaa, 0xcfa9, 0xcfa9,
+ 0xcfa9, 0xcfa8, 0xcfa8, 0xcfa7, 0xcfa7, 0xcfa7, 0xcfa6, 0xcfa6,
+ 0xcfa6, 0xcfa5, 0xcfa5, 0xcfa5, 0xcfa4, 0xcfa4, 0xcfa4, 0xcfa3,
+ 0xcfa3, 0xcfa2, 0xcfa2, 0xcfa2, 0xcfa1, 0xcfa1, 0xcfa1, 0xcfa0,
+ 0xcfa0, 0xcfa0, 0xcf9f, 0xcf9f, 0xcf9f, 0xcf9e, 0xcf9e, 0xcf9d,
+ 0xcf9d, 0xcf9d, 0xcf9c, 0xcf9c, 0xcf9c, 0xcf9b, 0xcf9b, 0xcf9b,
+ 0xcf9a, 0xcf9a, 0xcf9a, 0xcf99, 0xcf99, 0xcf99, 0xcf98, 0xcf98,
+ 0xcf98, 0xcf97, 0xcf97, 0xcf96, 0xcf96, 0xcf96, 0xcf95, 0xcf95,
+ 0xcf95, 0xcf94, 0xcf94, 0xcf94, 0xcf93, 0xcf93, 0xcf93, 0xcf92,
+ 0xcf92, 0xcf92, 0xcf91, 0xcf91, 0xcf91, 0xcf90, 0xcf90, 0xcf90,
+ 0xcf8f, 0xcf8f, 0xcf8f, 0xcf8e, 0xcf8e, 0xcf8e, 0xcf8d, 0xcf8d,
+ 0xcf8d, 0xcf8c, 0xcf8c, 0xcf8c, 0xcf8b, 0xcf8b, 0xcf8a, 0xcf8a,
+ 0xcf8a, 0xcf89, 0xcf89, 0xcf89, 0xcf88, 0xcf88, 0xcf88, 0xcf87,
+ 0xcf87, 0xcf87, 0xcf86, 0xcf86, 0xcf86, 0xcf85, 0xcf85, 0xcf85,
+ 0xcf84, 0xcf84, 0xcf84, 0xcf83, 0xcf83, 0xcf83, 0xcf82, 0xcf82,
+ 0xcf82, 0xcf81, 0xcf81, 0xcf81, 0xcf80, 0xcf80, 0xcf80, 0xcf7f,
+ 0xcf7f, 0xcf7f, 0xcf7e, 0xcf7e, 0xcf7e, 0xcf7d, 0xcf7d, 0xcf7d,
+ 0xcf7c, 0xcf7c, 0xcf7c, 0xcf7b, 0xcf7b, 0xcf7b, 0xcf7a, 0xcf7a,
+ 0xcf7a, 0xcf79, 0xcf79, 0xcf79, 0xcf79, 0xcf78, 0xcf78, 0xcf78,
+ 0xcf77, 0xcf77, 0xcf77, 0xcf76, 0xcf76, 0xcf76, 0xcf75, 0xcf75,
+ 0xcf75, 0xcf74, 0xcf74, 0xcf74, 0xcf73, 0xcf73, 0xcf73, 0xcf72,
+ 0xcf72, 0xcf72, 0xcf71, 0xcf71, 0xcf71, 0xcf70, 0xcf70, 0xcf70,
+ 0xcf6f, 0xcf6f, 0xcf6f, 0xcf6e, 0xcf6e, 0xcf6e, 0xcf6d, 0xcf6d,
+ 0xcf6d, 0xcf6d, 0xcf6c, 0xcf6c, 0xcf6c, 0xcf6b, 0xcf6b, 0xcf6b,
+ 0xcf6a, 0xcf6a, 0xcf6a, 0xcf69, 0xcf69, 0xcf69, 0xcf68, 0xcf68,
+ 0xcf68, 0xcf67, 0xcf67, 0xcf67, 0xcf66, 0xcf66, 0xcf66, 0xcf66,
+ 0xcf65, 0xcf65, 0xcf65, 0xcf64, 0xcf64, 0xcf64, 0xcf63, 0xcf63,
+ 0xcf63, 0xcf62, 0xcf62, 0xcf62, 0xcf61, 0xcf61, 0xcf61, 0xcf61,
+ 0xcf60, 0xcf60, 0xcf60, 0xcf5f, 0xcf5f, 0xcf5f, 0xcf5e, 0xcf5e,
+ 0xcf5e, 0xcf5d, 0xcf5d, 0xcf5d, 0xcf5c, 0xcf5c, 0xcf5c, 0xcf5c,
+ 0xcf5b, 0xcf5b, 0xcf5b, 0xcf5a, 0xcf5a, 0xcf5a, 0xcf59, 0xcf59,
+ 0xcf59, 0xcf58, 0xcf58, 0xcf58, 0xcf58, 0xcf57, 0xcf57, 0xcf57,
+ 0xcf56, 0xcf56, 0xcf56, 0xcf55, 0xcf55, 0xcf55, 0xcf54, 0xcf54,
+ 0xcf54, 0xcf54, 0xcf53, 0xcf53, 0xcf53, 0xcf52, 0xcf52, 0xcf52,
+ 0xcf51, 0xcf51, 0xcf51, 0xcf51, 0xcf50, 0xcf50, 0xcf50, 0xcf4f,
+ 0xcf4f, 0xcf4f, 0xcf4e, 0xcf4e, 0xcf4e, 0xcf4e, 0xcf4d, 0xcf4d,
+ 0xcf4d, 0xcf4c, 0xcf4c, 0xcf4c, 0xcf4b, 0xcf4b, 0xcf4b, 0xcf4b,
+ 0xcf4a, 0xcf4a, 0xcf4a, 0xcf49, 0xcf49, 0xcf49, 0xcf48, 0xcf48,
+ 0xcf48, 0xcf48, 0xcf47, 0xcf47, 0xcf47, 0xcf46, 0xcf46, 0xcf46,
+ 0xcf45, 0xcf45, 0xcf45, 0xcf45, 0xcf44, 0xcf44, 0xcf44, 0xcf43,
+ 0xcf43, 0xcf43, 0xcf42, 0xcf42, 0xcf42, 0xcf42, 0xcf41, 0xcf41,
+ 0xcf41, 0xcf40, 0xcf40, 0xcf40, 0xcf40, 0xcf3f, 0xcf3f, 0xcf3f,
+ 0xcf3e, 0xcf3e, 0xcf3e, 0xcf3e, 0xcf3d, 0xcf3d, 0xcf3d, 0xcf3c,
+ 0xcf3c, 0xcf3c, 0xcf3b, 0xcf3b, 0xcf3b, 0xcf3b, 0xcf3a, 0xcf3a,
+ 0xcf3a, 0xcf39, 0xcf39, 0xcf39, 0xcf39, 0xcf38, 0xcf38, 0xcf38,
+ 0xcf37, 0xcf37, 0xcf37, 0xcf37, 0xcf36, 0xcf36, 0xcf36, 0xcf35,
+ 0xcf35, 0xcf35, 0xcf35, 0xcf34, 0xcf34, 0xcf34, 0xcf33, 0xcf33,
+ 0xcf33, 0xcf33, 0xcf32, 0xcf32, 0xcf32, 0xcf31, 0xcf31, 0xcf31,
+ 0xcf31, 0xcf30, 0xcf30, 0xcf30, 0xcf2f, 0xcf2f, 0xcf2f, 0xcf2f,
+ 0xcf2e, 0xcf2e, 0xcf2e, 0xcf2d, 0xcf2d, 0xcf2d, 0xcf2d, 0xcf2c,
+ 0xcf2c, 0xcf2c, 0xcf2b, 0xcf2b, 0xcf2b, 0xcf2b, 0xcf2a, 0xcf2a,
+ 0xcf2a, 0xcf29, 0xcf29, 0xcf29, 0xcf29, 0xcf28, 0xcf28, 0xcf28,
+ 0xcf28, 0xcf27, 0xcf27, 0xcf27, 0xcf26, 0xcf26, 0xcf26, 0xcf26,
+ 0xcf25, 0xcf25, 0xcf25, 0xcf24, 0xcf24, 0xcf24, 0xcf24, 0xcf23,
+ 0xcf23, 0xcf23, 0xcf23, 0xcf22, 0xcf22, 0xcf22, 0xcf21, 0xcf21,
+ 0xcf21, 0xcf21, 0xcf20, 0xcf20, 0xcf20, 0xcf1f, 0xcf1f, 0xcf1f,
+ 0xcf1f, 0xcf1e, 0xcf1e, 0xcf1e, 0xcf1e, 0xcf1d, 0xcf1d, 0xcf1d,
+ 0xcf1c, 0xcf1c, 0xcf1c, 0xcf1c, 0xcf1b, 0xcf1b, 0xcf1b, 0xcf1b,
+ 0xcf1a, 0xcf1a, 0xcf1a, 0xcf19, 0xcf19, 0xcf19, 0xcf19, 0xcf18,
+ 0xcf18, 0xcf18, 0xcf18, 0xcf17, 0xcf17, 0xcf17, 0xcf16, 0xcf16,
+ 0xcf16, 0xcf16, 0xcf15, 0xcf15, 0xcf15, 0xcf15, 0xcf14, 0xcf14,
+ 0xcf14, 0xcf14, 0xcf13, 0xcf13, 0xcf13, 0xcf12, 0xcf12, 0xcf12,
+ 0xcf12, 0xcf11, 0xcf11, 0xcf11, 0xcf11, 0xcf10, 0xcf10, 0xcf10,
+ 0xcf10, 0xcf0f, 0xcf0f, 0xcf0f, 0xcf0e, 0xcf0e, 0xcf0e, 0xcf0e,
+ 0xcf0d, 0xcf0d, 0xcf0d, 0xcf0d, 0xcf0c, 0xcf0c, 0xcf0c, 0xcf0c,
+ 0xcf0b, 0xcf0b, 0xcf0b, 0xcf0a, 0xcf0a, 0xcf0a, 0xcf0a, 0xcf09,
+ 0xcf09, 0xcf09, 0xcf09, 0xcf08, 0xcf08, 0xcf08, 0xcf08, 0xcf07,
+ 0xcf07, 0xcf07, 0xcf07, 0xcf06, 0xcf06, 0xcf06, 0xcf05, 0xcf05,
+ 0xcf05, 0xcf05, 0xcf04, 0xcf04, 0xcf04, 0xcf04, 0xcf03, 0xcf03,
+ 0xcf03, 0xcf03, 0xcf02, 0xcf02, 0xcf02, 0xcf02, 0xcf01, 0xcf01,
+ 0xcf01, 0xcf01, 0xcf00, 0xcf00, 0xcf00, 0xceff, 0xceff, 0xceff,
+ 0xceff, 0xcefe, 0xcefe, 0xcefe, 0xcefe, 0xcefd, 0xcefd, 0xcefd,
+ 0xcefd, 0xcefc, 0xcefc, 0xcefc, 0xcefc, 0xcefb, 0xcefb, 0xcefb,
+ 0xcefb, 0xcefa, 0xcefa, 0xcefa, 0xcefa, 0xcef9, 0xcef9, 0xcef9,
+ 0xcef9, 0xcef8, 0xcef8, 0xcef8, 0xcef8, 0xcef7, 0xcef7, 0xcef7,
+ 0xcef7, 0xcef6, 0xcef6, 0xcef6, 0xcef6, 0xcef5, 0xcef5, 0xcef5,
+ 0xcef4, 0xcef4, 0xcef4, 0xcef4, 0xcef3, 0xcef3, 0xcef3, 0xcef3,
+ 0xcef2, 0xcef2, 0xcef2, 0xcef2, 0xcef1, 0xcef1, 0xcef1, 0xcef1,
+ 0xcef0, 0xcef0, 0xcef0, 0xcef0, 0xceef, 0xceef, 0xceef, 0xceef,
+ 0xceee, 0xceee, 0xceed, 0xceed, 0xceec, 0xceec, 0xceeb, 0xceeb,
+ 0xceea, 0xceea, 0xcee9, 0xcee9, 0xcee8, 0xcee8, 0xcee8, 0xcee7,
+ 0xcee7, 0xcee6, 0xcee6, 0xcee5, 0xcee5, 0xcee4, 0xcee4, 0xcee3,
+ 0xcee3, 0xcee2, 0xcee2, 0xcee1, 0xcee1, 0xcee0, 0xcee0, 0xcedf,
+ 0xcedf, 0xcede, 0xcede, 0xcedd, 0xcedd, 0xcedc, 0xcedc, 0xcedb,
+ 0xcedb, 0xceda, 0xceda, 0xced9, 0xced9, 0xced8, 0xced8, 0xced7,
+ 0xced7, 0xced7, 0xced6, 0xced6, 0xced5, 0xced5, 0xced4, 0xced4,
+ 0xced3, 0xced3, 0xced2, 0xced2, 0xced1, 0xced1, 0xced0, 0xced0,
+ 0xcecf, 0xcecf, 0xcece, 0xcece, 0xcece, 0xcecd, 0xcecd, 0xcecc,
+ 0xcecc, 0xcecb, 0xcecb, 0xceca, 0xceca, 0xcec9, 0xcec9, 0xcec8,
+ 0xcec8, 0xcec7, 0xcec7, 0xcec7, 0xcec6, 0xcec6, 0xcec5, 0xcec5,
+ 0xcec4, 0xcec4, 0xcec3, 0xcec3, 0xcec2, 0xcec2, 0xcec1, 0xcec1,
+ 0xcec1, 0xcec0, 0xcec0, 0xcebf, 0xcebf, 0xcebe, 0xcebe, 0xcebd,
+ 0xcebd, 0xcebc, 0xcebc, 0xcebc, 0xcebb, 0xcebb, 0xceba, 0xceba,
+ 0xceb9, 0xceb9, 0xceb8, 0xceb8, 0xceb8, 0xceb7, 0xceb7, 0xceb6,
+ 0xceb6, 0xceb5, 0xceb5, 0xceb4, 0xceb4, 0xceb3, 0xceb3, 0xceb3,
+ 0xceb2, 0xceb2, 0xceb1, 0xceb1, 0xceb0, 0xceb0, 0xceaf, 0xceaf,
+ 0xceaf, 0xceae, 0xceae, 0xcead, 0xcead, 0xceac, 0xceac, 0xceac,
+ 0xceab, 0xceab, 0xceaa, 0xceaa, 0xcea9, 0xcea9, 0xcea8, 0xcea8,
+ 0xcea8, 0xcea7, 0xcea7, 0xcea6, 0xcea6, 0xcea5, 0xcea5, 0xcea5,
+ 0xcea4, 0xcea4, 0xcea3, 0xcea3, 0xcea2, 0xcea2, 0xcea2, 0xcea1,
+ 0xcea1, 0xcea0, 0xcea0, 0xce9f, 0xce9f, 0xce9f, 0xce9e, 0xce9e,
+ 0xce9d, 0xce9d, 0xce9c, 0xce9c, 0xce9c, 0xce9b, 0xce9b, 0xce9a,
+ 0xce9a, 0xce99, 0xce99, 0xce99, 0xce98, 0xce98, 0xce97, 0xce97,
+ 0xce96, 0xce96, 0xce96, 0xce95, 0xce95, 0xce94, 0xce94, 0xce94,
+ 0xce93, 0xce93, 0xce92, 0xce92, 0xce91, 0xce91, 0xce91, 0xce90,
+ 0xce90, 0xce8f, 0xce8f, 0xce8f, 0xce8e, 0xce8e, 0xce8d, 0xce8d,
+ 0xce8c, 0xce8c, 0xce8c, 0xce8b, 0xce8b, 0xce8a, 0xce8a, 0xce8a,
+ 0xce89, 0xce89, 0xce88, 0xce88, 0xce88, 0xce87, 0xce87, 0xce86,
+ 0xce86, 0xce85, 0xce85, 0xce85, 0xce84, 0xce84, 0xce83, 0xce83,
+ 0xce83, 0xce82, 0xce82, 0xce81, 0xce81, 0xce81, 0xce80, 0xce80,
+ 0xce7f, 0xce7f, 0xce7f, 0xce7e, 0xce7e, 0xce7d, 0xce7d, 0xce7d,
+ 0xce7c, 0xce7c, 0xce7b, 0xce7b, 0xce7b, 0xce7a, 0xce7a, 0xce79,
+ 0xce79, 0xce79, 0xce78, 0xce78, 0xce77, 0xce77, 0xce77, 0xce76,
+ 0xce76, 0xce75, 0xce75, 0xce75, 0xce74, 0xce74, 0xce73, 0xce73,
+ 0xce73, 0xce72, 0xce72, 0xce72, 0xce71, 0xce71, 0xce70, 0xce70,
+ 0xce70, 0xce6f, 0xce6f, 0xce6e, 0xce6e, 0xce6e, 0xce6d, 0xce6d,
+ 0xce6c, 0xce6c, 0xce6c, 0xce6b, 0xce6b, 0xce6b, 0xce6a, 0xce6a,
+ 0xce69, 0xce69, 0xce69, 0xce68, 0xce68, 0xce67, 0xce67, 0xce67,
+ 0xce66, 0xce66, 0xce66, 0xce65, 0xce65, 0xce64, 0xce64, 0xce64,
+ 0xce63, 0xce63, 0xce62, 0xce62, 0xce62, 0xce61, 0xce61, 0xce61,
+ 0xce60, 0xce60, 0xce5f, 0xce5f, 0xce5f, 0xce5e, 0xce5e, 0xce5e,
+ 0xce5d, 0xce5d, 0xce5c, 0xce5c, 0xce5c, 0xce5b, 0xce5b, 0xce5b,
+ 0xce5a, 0xce5a, 0xce59, 0xce59, 0xce59, 0xce58, 0xce58, 0xce58,
+ 0xce57, 0xce57, 0xce56, 0xce56, 0xce56, 0xce55, 0xce55, 0xce55,
+ 0xce54, 0xce54, 0xce53, 0xce53, 0xce53, 0xce52, 0xce52, 0xce52,
+ 0xce51, 0xce51, 0xce51, 0xce50, 0xce50, 0xce4f, 0xce4f, 0xce4f,
+ 0xce4e, 0xce4e, 0xce4e, 0xce4d, 0xce4d, 0xce4d, 0xce4c, 0xce4c,
+ 0xce4b, 0xce4b, 0xce4b, 0xce4a, 0xce4a, 0xce4a, 0xce49, 0xce49,
+ 0xce49, 0xce48, 0xce48, 0xce47, 0xce47, 0xce47, 0xce46, 0xce46,
+ 0xce46, 0xce45, 0xce45, 0xce45, 0xce44, 0xce44, 0xce43, 0xce43,
+ 0xce43, 0xce42, 0xce42, 0xce42, 0xce41, 0xce41, 0xce41, 0xce40,
+ 0xce40, 0xce40, 0xce3f, 0xce3f, 0xce3e, 0xce3e, 0xce3e, 0xce3d,
+ 0xce3d, 0xce3d, 0xce3c, 0xce3c, 0xce3c, 0xce3b, 0xce3b, 0xce3b,
+ 0xce3a, 0xce3a, 0xce3a, 0xce39, 0xce39, 0xce38, 0xce38, 0xce38,
+ 0xce37, 0xce37, 0xce37, 0xce36, 0xce36, 0xce36, 0xce35, 0xce35,
+ 0xce35, 0xce34, 0xce34, 0xce34, 0xce33, 0xce33, 0xce33, 0xce32,
+ 0xce32, 0xce32, 0xce31, 0xce31, 0xce30, 0xce30, 0xce30, 0xce2f,
+ 0xce2f, 0xce2f, 0xce2e, 0xce2e, 0xce2e, 0xce2d, 0xce2d, 0xce2d,
+ 0xce2c, 0xce2c, 0xce2c, 0xce2b, 0xce2b, 0xce2b, 0xce2a, 0xce2a,
+ 0xce2a, 0xce29, 0xce29, 0xce29, 0xce28, 0xce28, 0xce28, 0xce27,
+ 0xce27, 0xce27, 0xce26, 0xce26, 0xce26, 0xce25, 0xce25, 0xce25,
+ 0xce24, 0xce24, 0xce24, 0xce23, 0xce23, 0xce23, 0xce22, 0xce22,
+ 0xce22, 0xce21, 0xce21, 0xce21, 0xce20, 0xce20, 0xce20, 0xce1f,
+ 0xce1f, 0xce1f, 0xce1e, 0xce1e, 0xce1e, 0xce1d, 0xce1d, 0xce1d,
+ 0xce1c, 0xce1c, 0xce1c, 0xce1b, 0xce1b, 0xce1b, 0xce1a, 0xce1a,
+ 0xce1a, 0xce19, 0xce19, 0xce19, 0xce18, 0xce18, 0xce18, 0xce17,
+ 0xce17, 0xce17, 0xce16, 0xce16, 0xce16, 0xce15, 0xce15, 0xce15,
+ 0xce14, 0xce14, 0xce14, 0xce13, 0xce13, 0xce13, 0xce12, 0xce12,
+ 0xce12, 0xce11, 0xce11, 0xce11, 0xce10, 0xce10, 0xce10, 0xce0f,
+ 0xce0f, 0xce0f, 0xce0e, 0xce0e, 0xce0e, 0xce0d, 0xce0d, 0xce0d,
+ 0xce0d, 0xce0c, 0xce0c, 0xce0c, 0xce0b, 0xce0b, 0xce0b, 0xce0a,
+ 0xce0a, 0xce0a, 0xce09, 0xce09, 0xce09, 0xce08, 0xce08, 0xce08,
+ 0xce07, 0xce07, 0xce07, 0xce06, 0xce06, 0xce06, 0xce05, 0xce05,
+ 0xce05, 0xce05, 0xce04, 0xce04, 0xce04, 0xce03, 0xce03, 0xce03,
+ 0xce02, 0xce02, 0xce02, 0xce01, 0xce01, 0xce01, 0xce00, 0xce00,
+ 0xce00, 0xce00, 0xcdff, 0xcdff, 0xcdff, 0xcdfe, 0xcdfe, 0xcdfe,
+ 0xcdfd, 0xcdfd, 0xcdfd, 0xcdfc, 0xcdfc, 0xcdfc, 0xcdfb, 0xcdfb,
+ 0xcdfb, 0xcdfb, 0xcdfa, 0xcdfa, 0xcdfa, 0xcdf9, 0xcdf9, 0xcdf9,
+ 0xcdf8, 0xcdf8, 0xcdf8, 0xcdf7, 0xcdf7, 0xcdf7, 0xcdf6, 0xcdf6,
+ 0xcdf6, 0xcdf6, 0xcdf5, 0xcdf5, 0xcdf5, 0xcdf4, 0xcdf4, 0xcdf4,
+ 0xcdf3, 0xcdf3, 0xcdf3, 0xcdf3, 0xcdf2, 0xcdf2, 0xcdf2, 0xcdf1,
+ 0xcdf1, 0xcdf1, 0xcdf0, 0xcdf0, 0xcdf0, 0xcdef, 0xcdef, 0xcdef,
+ 0xcdef, 0xcdee, 0xcdee, 0xcdee, 0xcded, 0xcded, 0xcded, 0xcdec,
+ 0xcdec, 0xcdec, 0xcdec, 0xcdeb, 0xcdeb, 0xcdeb, 0xcdea, 0xcdea,
+ 0xcdea, 0xcde9, 0xcde9, 0xcde9, 0xcde9, 0xcde8, 0xcde8, 0xcde8,
+ 0xcde7, 0xcde7, 0xcde7, 0xcde6, 0xcde6, 0xcde6, 0xcde6, 0xcde5,
+ 0xcde5, 0xcde5, 0xcde4, 0xcde4, 0xcde4, 0xcde3, 0xcde3, 0xcde3,
+ 0xcde3, 0xcde2, 0xcde2, 0xcde2, 0xcde1, 0xcde1, 0xcde1, 0xcde0,
+ 0xcde0, 0xcde0, 0xcde0, 0xcddf, 0xcddf, 0xcddf, 0xcdde, 0xcdde,
+ 0xcdde, 0xcdde, 0xcddd, 0xcddd, 0xcddd, 0xcddc, 0xcddc, 0xcddc,
+ 0xcddb, 0xcddb, 0xcddb, 0xcddb, 0xcdda, 0xcdda, 0xcdda, 0xcdd9,
+ 0xcdd9, 0xcdd9, 0xcdd9, 0xcdd8, 0xcdd8, 0xcdd8, 0xcdd7, 0xcdd7,
+ 0xcdd7, 0xcdd7, 0xcdd6, 0xcdd6, 0xcdd6, 0xcdd5, 0xcdd5, 0xcdd5,
+ 0xcdd5, 0xcdd4, 0xcdd4, 0xcdd4, 0xcdd3, 0xcdd3, 0xcdd3, 0xcdd3,
+ 0xcdd2, 0xcdd2, 0xcdd2, 0xcdd1, 0xcdd1, 0xcdd1, 0xcdd1, 0xcdd0,
+ 0xcdd0, 0xcdd0, 0xcdcf, 0xcdcf, 0xcdcf, 0xcdcf, 0xcdce, 0xcdce,
+ 0xcdce, 0xcdcd, 0xcdcd, 0xcdcd, 0xcdcd, 0xcdcc, 0xcdcc, 0xcdcc,
+ 0xcdcb, 0xcdcb, 0xcdcb, 0xcdcb, 0xcdca, 0xcdca, 0xcdca, 0xcdc9,
+ 0xcdc9, 0xcdc9, 0xcdc9, 0xcdc8, 0xcdc8, 0xcdc8, 0xcdc7, 0xcdc7,
+ 0xcdc7, 0xcdc7, 0xcdc6, 0xcdc6, 0xcdc6, 0xcdc5, 0xcdc5, 0xcdc5,
+ 0xcdc5, 0xcdc4, 0xcdc4, 0xcdc4, 0xcdc4, 0xcdc3, 0xcdc3, 0xcdc3,
+ 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc2, 0xcdc1, 0xcdc1, 0xcdc1, 0xcdc0,
+ 0xcdc0, 0xcdc0, 0xcdc0, 0xcdbf, 0xcdbf, 0xcdbf, 0xcdbf, 0xcdbe,
+ 0xcdbe, 0xcdbe, 0xcdbd, 0xcdbd, 0xcdbd, 0xcdbd, 0xcdbc, 0xcdbc,
+ 0xcdbc, 0xcdbb, 0xcdbb, 0xcdbb, 0xcdbb, 0xcdba, 0xcdba, 0xcdba,
+ 0xcdba, 0xcdb9, 0xcdb9, 0xcdb9, 0xcdb8, 0xcdb8, 0xcdb8, 0xcdb8,
+ 0xcdb7, 0xcdb7, 0xcdb7, 0xcdb7, 0xcdb6, 0xcdb6, 0xcdb6, 0xcdb5,
+ 0xcdb5, 0xcdb5, 0xcdb5, 0xcdb4, 0xcdb4, 0xcdb4, 0xcdb4, 0xcdb3,
+ 0xcdb3, 0xcdb3, 0xcdb3, 0xcdb2, 0xcdb2, 0xcdb2, 0xcdb1, 0xcdb1,
+ 0xcdb1, 0xcdb1, 0xcdb0, 0xcdb0, 0xcdb0, 0xcdb0, 0xcdaf, 0xcdaf,
+ 0xcdaf, 0xcdae, 0xcdae, 0xcdae, 0xcdae, 0xcdad, 0xcdad, 0xcdad,
+ 0xcdad, 0xcdac, 0xcdac, 0xcdac, 0xcdac, 0xcdab, 0xcdab, 0xcdab,
+ 0xcdaa, 0xcdaa, 0xcdaa, 0xcdaa, 0xcda9, 0xcda9, 0xcda9, 0xcda9,
+ 0xcda8, 0xcda8, 0xcda8, 0xcda8, 0xcda7, 0xcda7, 0xcda7, 0xcda7,
+ 0xcda6, 0xcda6, 0xcda6, 0xcda5, 0xcda5, 0xcda5, 0xcda5, 0xcda4,
+ 0xcda4, 0xcda4, 0xcda4, 0xcda3, 0xcda3, 0xcda3, 0xcda3, 0xcda2,
+ 0xcda2, 0xcda2, 0xcda2, 0xcda1, 0xcda1, 0xcda1, 0xcda0, 0xcda0,
+ 0xcda0, 0xcda0, 0xcd9f, 0xcd9f, 0xcd9f, 0xcd9f, 0xcd9e, 0xcd9e,
+ 0xcd9e, 0xcd9e, 0xcd9d, 0xcd9d, 0xcd9d, 0xcd9d, 0xcd9c, 0xcd9c,
+ 0xcd9c, 0xcd9c, 0xcd9b, 0xcd9b, 0xcd9b, 0xcd9b, 0xcd9a, 0xcd9a,
+ 0xcd9a, 0xcd9a, 0xcd99, 0xcd99, 0xcd99, 0xcd98, 0xcd98, 0xcd98,
+ 0xcd98, 0xcd97, 0xcd97, 0xcd97, 0xcd97, 0xcd96, 0xcd96, 0xcd96,
+ 0xcd96, 0xcd95, 0xcd95, 0xcd95, 0xcd95, 0xcd94, 0xcd94, 0xcd94,
+ 0xcd94, 0xcd93, 0xcd93, 0xcd93, 0xcd93, 0xcd92, 0xcd92, 0xcd92,
+ 0xcd92, 0xcd91, 0xcd91, 0xcd91, 0xcd91, 0xcd90, 0xcd90, 0xcd90,
+ 0xcd90, 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8f, 0xcd8e, 0xcd8e, 0xcd8e,
+ 0xcd8e, 0xcd8d, 0xcd8d, 0xcd8d, 0xcd8d, 0xcd8c, 0xcd8c, 0xcd8c,
+ 0xcd8c, 0xcd8b, 0xcd8b, 0xcd8a, 0xcd8a, 0xcd89, 0xcd89, 0xcd88,
+ 0xcd88, 0xcd87, 0xcd87, 0xcd86, 0xcd86, 0xcd85, 0xcd85, 0xcd84,
+ 0xcd84, 0xcd83, 0xcd83, 0xcd82, 0xcd82, 0xcd81, 0xcd81, 0xcd80,
+ 0xcd80, 0xcd7f, 0xcd7f, 0xcd7e, 0xcd7e, 0xcd7d, 0xcd7d, 0xcd7c,
+ 0xcd7c, 0xcd7b, 0xcd7b, 0xcd7a, 0xcd7a, 0xcd79, 0xcd79, 0xcd78,
+ 0xcd78, 0xcd77, 0xcd77, 0xcd77, 0xcd76, 0xcd76, 0xcd75, 0xcd75,
+ 0xcd74, 0xcd74, 0xcd73, 0xcd73, 0xcd72, 0xcd72, 0xcd71, 0xcd71,
+ 0xcd70, 0xcd70, 0xcd6f, 0xcd6f, 0xcd6e, 0xcd6e, 0xcd6d, 0xcd6d,
+ 0xcd6d, 0xcd6c, 0xcd6c, 0xcd6b, 0xcd6b, 0xcd6a, 0xcd6a, 0xcd69,
+ 0xcd69, 0xcd68, 0xcd68, 0xcd67, 0xcd67, 0xcd66, 0xcd66, 0xcd66,
+ 0xcd65, 0xcd65, 0xcd64, 0xcd64, 0xcd63, 0xcd63, 0xcd62, 0xcd62,
+ 0xcd61, 0xcd61, 0xcd60, 0xcd60, 0xcd60, 0xcd5f, 0xcd5f, 0xcd5e,
+ 0xcd5e, 0xcd5d, 0xcd5d, 0xcd5c, 0xcd5c, 0xcd5b, 0xcd5b, 0xcd5a,
+ 0xcd5a, 0xcd5a, 0xcd59, 0xcd59, 0xcd58, 0xcd58, 0xcd57, 0xcd57,
+ 0xcd56, 0xcd56, 0xcd56, 0xcd55, 0xcd55, 0xcd54, 0xcd54, 0xcd53,
+ 0xcd53, 0xcd52, 0xcd52, 0xcd51, 0xcd51, 0xcd51, 0xcd50, 0xcd50,
+ 0xcd4f, 0xcd4f, 0xcd4e, 0xcd4e, 0xcd4d, 0xcd4d, 0xcd4d, 0xcd4c,
+ 0xcd4c, 0xcd4b, 0xcd4b, 0xcd4a, 0xcd4a, 0xcd4a, 0xcd49, 0xcd49,
+ 0xcd48, 0xcd48, 0xcd47, 0xcd47, 0xcd46, 0xcd46, 0xcd46, 0xcd45,
+ 0xcd45, 0xcd44, 0xcd44, 0xcd43, 0xcd43, 0xcd43, 0xcd42, 0xcd42,
+ 0xcd41, 0xcd41, 0xcd40, 0xcd40, 0xcd40, 0xcd3f, 0xcd3f, 0xcd3e,
+ 0xcd3e, 0xcd3d, 0xcd3d, 0xcd3c, 0xcd3c, 0xcd3c, 0xcd3b, 0xcd3b,
+ 0xcd3a, 0xcd3a, 0xcd3a, 0xcd39, 0xcd39, 0xcd38, 0xcd38, 0xcd37,
+ 0xcd37, 0xcd37, 0xcd36, 0xcd36, 0xcd35, 0xcd35, 0xcd34, 0xcd34,
+ 0xcd34, 0xcd33, 0xcd33, 0xcd32, 0xcd32, 0xcd31, 0xcd31, 0xcd31,
+ 0xcd30, 0xcd30, 0xcd2f, 0xcd2f, 0xcd2f, 0xcd2e, 0xcd2e, 0xcd2d,
+ 0xcd2d, 0xcd2c, 0xcd2c, 0xcd2c, 0xcd2b, 0xcd2b, 0xcd2a, 0xcd2a,
+ 0xcd2a, 0xcd29, 0xcd29, 0xcd28, 0xcd28, 0xcd28, 0xcd27, 0xcd27,
+ 0xcd26, 0xcd26, 0xcd25, 0xcd25, 0xcd25, 0xcd24, 0xcd24, 0xcd23,
+ 0xcd23, 0xcd23, 0xcd22, 0xcd22, 0xcd21, 0xcd21, 0xcd21, 0xcd20,
+ 0xcd20, 0xcd1f, 0xcd1f, 0xcd1f, 0xcd1e, 0xcd1e, 0xcd1d, 0xcd1d,
+ 0xcd1d, 0xcd1c, 0xcd1c, 0xcd1b, 0xcd1b, 0xcd1b, 0xcd1a, 0xcd1a,
+ 0xcd19, 0xcd19, 0xcd19, 0xcd18, 0xcd18, 0xcd17, 0xcd17, 0xcd17,
+ 0xcd16, 0xcd16, 0xcd15, 0xcd15, 0xcd15, 0xcd14, 0xcd14, 0xcd13,
+ 0xcd13, 0xcd13, 0xcd12, 0xcd12, 0xcd11, 0xcd11, 0xcd11, 0xcd10,
+ 0xcd10, 0xcd0f, 0xcd0f, 0xcd0f, 0xcd0e, 0xcd0e, 0xcd0d, 0xcd0d,
+ 0xcd0d, 0xcd0c, 0xcd0c, 0xcd0c, 0xcd0b, 0xcd0b, 0xcd0a, 0xcd0a,
+ 0xcd0a, 0xcd09, 0xcd09, 0xcd08, 0xcd08, 0xcd08, 0xcd07, 0xcd07,
+ 0xcd06, 0xcd06, 0xcd06, 0xcd05, 0xcd05, 0xcd05, 0xcd04, 0xcd04,
+ 0xcd03, 0xcd03, 0xcd03, 0xcd02, 0xcd02, 0xcd01, 0xcd01, 0xcd01,
+ 0xcd00, 0xcd00, 0xcd00, 0xccff, 0xccff, 0xccfe, 0xccfe, 0xccfe,
+ 0xccfd, 0xccfd, 0xccfd, 0xccfc, 0xccfc, 0xccfb, 0xccfb, 0xccfb,
+ 0xccfa, 0xccfa, 0xccfa, 0xccf9, 0xccf9, 0xccf8, 0xccf8, 0xccf8,
+ 0xccf7, 0xccf7, 0xccf7, 0xccf6, 0xccf6, 0xccf5, 0xccf5, 0xccf5,
+ 0xccf4, 0xccf4, 0xccf4, 0xccf3, 0xccf3, 0xccf2, 0xccf2, 0xccf2,
+ 0xccf1, 0xccf1, 0xccf1, 0xccf0, 0xccf0, 0xccef, 0xccef, 0xccef,
+ 0xccee, 0xccee, 0xccee, 0xcced, 0xcced, 0xcced, 0xccec, 0xccec,
+ 0xcceb, 0xcceb, 0xcceb, 0xccea, 0xccea, 0xccea, 0xcce9, 0xcce9,
+ 0xcce9, 0xcce8, 0xcce8, 0xcce7, 0xcce7, 0xcce7, 0xcce6, 0xcce6,
+ 0xcce6, 0xcce5, 0xcce5, 0xcce5, 0xcce4, 0xcce4, 0xcce3, 0xcce3,
+ 0xcce3, 0xcce2, 0xcce2, 0xcce2, 0xcce1, 0xcce1, 0xcce1, 0xcce0,
+ 0xcce0, 0xcce0, 0xccdf, 0xccdf, 0xccde, 0xccde, 0xccde, 0xccdd,
+ 0xccdd, 0xccdd, 0xccdc, 0xccdc, 0xccdc, 0xccdb, 0xccdb, 0xccdb,
+ 0xccda, 0xccda, 0xccd9, 0xccd9, 0xccd9, 0xccd8, 0xccd8, 0xccd8,
+ 0xccd7, 0xccd7, 0xccd7, 0xccd6, 0xccd6, 0xccd6, 0xccd5, 0xccd5,
+ 0xccd5, 0xccd4, 0xccd4, 0xccd3, 0xccd3, 0xccd3, 0xccd2, 0xccd2,
+ 0xccd2, 0xccd1, 0xccd1, 0xccd1, 0xccd0, 0xccd0, 0xccd0, 0xcccf,
+ 0xcccf, 0xcccf, 0xccce, 0xccce, 0xccce, 0xcccd, 0xcccd, 0xcccd,
+ 0xcccc, 0xcccc, 0xcccc, 0xcccb, 0xcccb, 0xcccb, 0xccca, 0xccca,
+ 0xccc9, 0xccc9, 0xccc9, 0xccc8, 0xccc8, 0xccc8, 0xccc7, 0xccc7,
+ 0xccc7, 0xccc6, 0xccc6, 0xccc6, 0xccc5, 0xccc5, 0xccc5, 0xccc4,
+ 0xccc4, 0xccc4, 0xccc3, 0xccc3, 0xccc3, 0xccc2, 0xccc2, 0xccc2,
+ 0xccc1, 0xccc1, 0xccc1, 0xccc0, 0xccc0, 0xccc0, 0xccbf, 0xccbf,
+ 0xccbf, 0xccbe, 0xccbe, 0xccbe, 0xccbd, 0xccbd, 0xccbd, 0xccbc,
+ 0xccbc, 0xccbc, 0xccbb, 0xccbb, 0xccbb, 0xccba, 0xccba, 0xccba,
+ 0xccb9, 0xccb9, 0xccb9, 0xccb8, 0xccb8, 0xccb8, 0xccb7, 0xccb7,
+ 0xccb7, 0xccb6, 0xccb6, 0xccb6, 0xccb5, 0xccb5, 0xccb5, 0xccb4,
+ 0xccb4, 0xccb4, 0xccb3, 0xccb3, 0xccb3, 0xccb2, 0xccb2, 0xccb2,
+ 0xccb1, 0xccb1, 0xccb1, 0xccb0, 0xccb0, 0xccb0, 0xccaf, 0xccaf,
+ 0xccaf, 0xccae, 0xccae, 0xccae, 0xccae, 0xccad, 0xccad, 0xccad,
+ 0xccac, 0xccac, 0xccac, 0xccab, 0xccab, 0xccab, 0xccaa, 0xccaa,
+ 0xccaa, 0xcca9, 0xcca9, 0xcca9, 0xcca8, 0xcca8, 0xcca8, 0xcca7,
+ 0xcca7, 0xcca7, 0xcca6, 0xcca6, 0xcca6, 0xcca5, 0xcca5, 0xcca5,
+ 0xcca5, 0xcca4, 0xcca4, 0xcca4, 0xcca3, 0xcca3, 0xcca3, 0xcca2,
+ 0xcca2, 0xcca2, 0xcca1, 0xcca1, 0xcca1, 0xcca0, 0xcca0, 0xcca0,
+ 0xcc9f, 0xcc9f, 0xcc9f, 0xcc9e, 0xcc9e, 0xcc9e, 0xcc9e, 0xcc9d,
+ 0xcc9d, 0xcc9d, 0xcc9c, 0xcc9c, 0xcc9c, 0xcc9b, 0xcc9b, 0xcc9b,
+ 0xcc9a, 0xcc9a, 0xcc9a, 0xcc99, 0xcc99, 0xcc99, 0xcc99, 0xcc98,
+ 0xcc98, 0xcc98, 0xcc97, 0xcc97, 0xcc97, 0xcc96, 0xcc96, 0xcc96,
+ 0xcc95, 0xcc95, 0xcc95, 0xcc95, 0xcc94, 0xcc94, 0xcc94, 0xcc93,
+ 0xcc93, 0xcc93, 0xcc92, 0xcc92, 0xcc92, 0xcc91, 0xcc91, 0xcc91,
+ 0xcc91, 0xcc90, 0xcc90, 0xcc90, 0xcc8f, 0xcc8f, 0xcc8f, 0xcc8e,
+ 0xcc8e, 0xcc8e, 0xcc8d, 0xcc8d, 0xcc8d, 0xcc8d, 0xcc8c, 0xcc8c,
+ 0xcc8c, 0xcc8b, 0xcc8b, 0xcc8b, 0xcc8a, 0xcc8a, 0xcc8a, 0xcc8a,
+ 0xcc89, 0xcc89, 0xcc89, 0xcc88, 0xcc88, 0xcc88, 0xcc87, 0xcc87,
+ 0xcc87, 0xcc87, 0xcc86, 0xcc86, 0xcc86, 0xcc85, 0xcc85, 0xcc85,
+ 0xcc84, 0xcc84, 0xcc84, 0xcc84, 0xcc83, 0xcc83, 0xcc83, 0xcc82,
+ 0xcc82, 0xcc82, 0xcc81, 0xcc81, 0xcc81, 0xcc81, 0xcc80, 0xcc80,
+ 0xcc80, 0xcc7f, 0xcc7f, 0xcc7f, 0xcc7e, 0xcc7e, 0xcc7e, 0xcc7e,
+ 0xcc7d, 0xcc7d, 0xcc7d, 0xcc7c, 0xcc7c, 0xcc7c, 0xcc7c, 0xcc7b,
+ 0xcc7b, 0xcc7b, 0xcc7a, 0xcc7a, 0xcc7a, 0xcc79, 0xcc79, 0xcc79,
+ 0xcc79, 0xcc78, 0xcc78, 0xcc78, 0xcc77, 0xcc77, 0xcc77, 0xcc77,
+ 0xcc76, 0xcc76, 0xcc76, 0xcc75, 0xcc75, 0xcc75, 0xcc75, 0xcc74,
+ 0xcc74, 0xcc74, 0xcc73, 0xcc73, 0xcc73, 0xcc72, 0xcc72, 0xcc72,
+ 0xcc72, 0xcc71, 0xcc71, 0xcc71, 0xcc70, 0xcc70, 0xcc70, 0xcc70,
+ 0xcc6f, 0xcc6f, 0xcc6f, 0xcc6e, 0xcc6e, 0xcc6e, 0xcc6e, 0xcc6d,
+ 0xcc6d, 0xcc6d, 0xcc6c, 0xcc6c, 0xcc6c, 0xcc6c, 0xcc6b, 0xcc6b,
+ 0xcc6b, 0xcc6a, 0xcc6a, 0xcc6a, 0xcc6a, 0xcc69, 0xcc69, 0xcc69,
+ 0xcc68, 0xcc68, 0xcc68, 0xcc68, 0xcc67, 0xcc67, 0xcc67, 0xcc67,
+ 0xcc66, 0xcc66, 0xcc66, 0xcc65, 0xcc65, 0xcc65, 0xcc65, 0xcc64,
+ 0xcc64, 0xcc64, 0xcc63, 0xcc63, 0xcc63, 0xcc63, 0xcc62, 0xcc62,
+ 0xcc62, 0xcc61, 0xcc61, 0xcc61, 0xcc61, 0xcc60, 0xcc60, 0xcc60,
+ 0xcc60, 0xcc5f, 0xcc5f, 0xcc5f, 0xcc5e, 0xcc5e, 0xcc5e, 0xcc5e,
+ 0xcc5d, 0xcc5d, 0xcc5d, 0xcc5c, 0xcc5c, 0xcc5c, 0xcc5c, 0xcc5b,
+ 0xcc5b, 0xcc5b, 0xcc5b, 0xcc5a, 0xcc5a, 0xcc5a, 0xcc59, 0xcc59,
+ 0xcc59, 0xcc59, 0xcc58, 0xcc58, 0xcc58, 0xcc58, 0xcc57, 0xcc57,
+ 0xcc57, 0xcc56, 0xcc56, 0xcc56, 0xcc56, 0xcc55, 0xcc55, 0xcc55,
+ 0xcc54, 0xcc54, 0xcc54, 0xcc54, 0xcc53, 0xcc53, 0xcc53, 0xcc53,
+ 0xcc52, 0xcc52, 0xcc52, 0xcc52, 0xcc51, 0xcc51, 0xcc51, 0xcc50,
+ 0xcc50, 0xcc50, 0xcc50, 0xcc4f, 0xcc4f, 0xcc4f, 0xcc4f, 0xcc4e,
+ 0xcc4e, 0xcc4e, 0xcc4d, 0xcc4d, 0xcc4d, 0xcc4d, 0xcc4c, 0xcc4c,
+ 0xcc4c, 0xcc4c, 0xcc4b, 0xcc4b, 0xcc4b, 0xcc4b, 0xcc4a, 0xcc4a,
+ 0xcc4a, 0xcc49, 0xcc49, 0xcc49, 0xcc49, 0xcc48, 0xcc48, 0xcc48,
+ 0xcc48, 0xcc47, 0xcc47, 0xcc47, 0xcc47, 0xcc46, 0xcc46, 0xcc46,
+ 0xcc45, 0xcc45, 0xcc45, 0xcc45, 0xcc44, 0xcc44, 0xcc44, 0xcc44,
+ 0xcc43, 0xcc43, 0xcc43, 0xcc43, 0xcc42, 0xcc42, 0xcc42, 0xcc42,
+ 0xcc41, 0xcc41, 0xcc41, 0xcc40, 0xcc40, 0xcc40, 0xcc40, 0xcc3f,
+ 0xcc3f, 0xcc3f, 0xcc3f, 0xcc3e, 0xcc3e, 0xcc3e, 0xcc3e, 0xcc3d,
+ 0xcc3d, 0xcc3d, 0xcc3d, 0xcc3c, 0xcc3c, 0xcc3c, 0xcc3c, 0xcc3b,
+ 0xcc3b, 0xcc3b, 0xcc3a, 0xcc3a, 0xcc3a, 0xcc3a, 0xcc39, 0xcc39,
+ 0xcc39, 0xcc39, 0xcc38, 0xcc38, 0xcc38, 0xcc38, 0xcc37, 0xcc37,
+ 0xcc37, 0xcc37, 0xcc36, 0xcc36, 0xcc36, 0xcc36, 0xcc35, 0xcc35,
+ 0xcc35, 0xcc35, 0xcc34, 0xcc34, 0xcc34, 0xcc34, 0xcc33, 0xcc33,
+ 0xcc33, 0xcc33, 0xcc32, 0xcc32, 0xcc32, 0xcc31, 0xcc31, 0xcc31,
+ 0xcc31, 0xcc30, 0xcc30, 0xcc30, 0xcc30, 0xcc2f, 0xcc2f, 0xcc2f,
+ 0xcc2f, 0xcc2e, 0xcc2e, 0xcc2e, 0xcc2e, 0xcc2d, 0xcc2d, 0xcc2d,
+ 0xcc2d, 0xcc2c, 0xcc2c, 0xcc2c, 0xcc2c, 0xcc2b, 0xcc2b, 0xcc2b,
+ 0xcc2b, 0xcc2a, 0xcc2a, 0xcc2a, 0xcc2a, 0xcc29, 0xcc29, 0xcc29,
+ 0xcc29, 0xcc28, 0xcc28, 0xcc27, 0xcc27, 0xcc26, 0xcc26, 0xcc25,
+ 0xcc25, 0xcc24, 0xcc24, 0xcc23, 0xcc23, 0xcc22, 0xcc22, 0xcc21,
+ 0xcc21, 0xcc20, 0xcc20, 0xcc1f, 0xcc1f, 0xcc1e, 0xcc1e, 0xcc1d,
+ 0xcc1d, 0xcc1c, 0xcc1c, 0xcc1b, 0xcc1b, 0xcc1a, 0xcc1a, 0xcc19,
+ 0xcc19, 0xcc18, 0xcc18, 0xcc17, 0xcc17, 0xcc17, 0xcc16, 0xcc16,
+ 0xcc15, 0xcc15, 0xcc14, 0xcc14, 0xcc13, 0xcc13, 0xcc12, 0xcc12,
+ 0xcc11, 0xcc11, 0xcc10, 0xcc10, 0xcc0f, 0xcc0f, 0xcc0e, 0xcc0e,
+ 0xcc0d, 0xcc0d, 0xcc0c, 0xcc0c, 0xcc0c, 0xcc0b, 0xcc0b, 0xcc0a,
+ 0xcc0a, 0xcc09, 0xcc09, 0xcc08, 0xcc08, 0xcc07, 0xcc07, 0xcc06,
+ 0xcc06, 0xcc05, 0xcc05, 0xcc04, 0xcc04, 0xcc04, 0xcc03, 0xcc03,
+ 0xcc02, 0xcc02, 0xcc01, 0xcc01, 0xcc00, 0xcc00, 0xcbff, 0xcbfe,
+ 0xcbfd, 0xcbfc, 0xcbfb, 0xcbfa, 0xcbf9, 0xcbf8, 0xcbf7, 0xcbf6,
+ 0xcbf6, 0xcbf5, 0xcbf4, 0xcbf3, 0xcbf2, 0xcbf1, 0xcbf0, 0xcbef,
+ 0xcbee, 0xcbed, 0xcbec, 0xcbec, 0xcbeb, 0xcbea, 0xcbe9, 0xcbe8,
+ 0xcbe7, 0xcbe6, 0xcbe5, 0xcbe4, 0xcbe3, 0xcbe3, 0xcbe2, 0xcbe1,
+ 0xcbe0, 0xcbdf, 0xcbde, 0xcbdd, 0xcbdc, 0xcbdb, 0xcbdb, 0xcbda,
+ 0xcbd9, 0xcbd8, 0xcbd7, 0xcbd6, 0xcbd5, 0xcbd4, 0xcbd3, 0xcbd3,
+ 0xcbd2, 0xcbd1, 0xcbd0, 0xcbcf, 0xcbce, 0xcbcd, 0xcbcc, 0xcbcb,
+ 0xcbcb, 0xcbca, 0xcbc9, 0xcbc8, 0xcbc7, 0xcbc6, 0xcbc5, 0xcbc4,
+ 0xcbc4, 0xcbc3, 0xcbc2, 0xcbc1, 0xcbc0, 0xcbbf, 0xcbbe, 0xcbbe,
+ 0xcbbd, 0xcbbc, 0xcbbb, 0xcbba, 0xcbb9, 0xcbb8, 0xcbb8, 0xcbb7,
+ 0xcbb6, 0xcbb5, 0xcbb4, 0xcbb3, 0xcbb2, 0xcbb1, 0xcbb1, 0xcbb0,
+ 0xcbaf, 0xcbae, 0xcbad, 0xcbac, 0xcbac, 0xcbab, 0xcbaa, 0xcba9,
+ 0xcba8, 0xcba7, 0xcba6, 0xcba6, 0xcba5, 0xcba4, 0xcba3, 0xcba2,
+ 0xcba1, 0xcba1, 0xcba0, 0xcb9f, 0xcb9e, 0xcb9d, 0xcb9c, 0xcb9b,
+ 0xcb9b, 0xcb9a, 0xcb99, 0xcb98, 0xcb97, 0xcb96, 0xcb96, 0xcb95,
+ 0xcb94, 0xcb93, 0xcb92, 0xcb91, 0xcb91, 0xcb90, 0xcb8f, 0xcb8e,
+ 0xcb8d, 0xcb8d, 0xcb8c, 0xcb8b, 0xcb8a, 0xcb89, 0xcb88, 0xcb88,
+ 0xcb87, 0xcb86, 0xcb85, 0xcb84, 0xcb83, 0xcb83, 0xcb82, 0xcb81,
+ 0xcb80, 0xcb7f, 0xcb7f, 0xcb7e, 0xcb7d, 0xcb7c, 0xcb7b, 0xcb7b,
+ 0xcb7a, 0xcb79, 0xcb78, 0xcb77, 0xcb76, 0xcb76, 0xcb75, 0xcb74,
+ 0xcb73, 0xcb72, 0xcb72, 0xcb71, 0xcb70, 0xcb6f, 0xcb6e, 0xcb6e,
+ 0xcb6d, 0xcb6c, 0xcb6b, 0xcb6a, 0xcb6a, 0xcb69, 0xcb68, 0xcb67,
+ 0xcb66, 0xcb66, 0xcb65, 0xcb64, 0xcb63, 0xcb63, 0xcb62, 0xcb61,
+ 0xcb60, 0xcb5f, 0xcb5f, 0xcb5e, 0xcb5d, 0xcb5c, 0xcb5b, 0xcb5b,
+ 0xcb5a, 0xcb59, 0xcb58, 0xcb57, 0xcb57, 0xcb56, 0xcb55, 0xcb54,
+ 0xcb54, 0xcb53, 0xcb52, 0xcb51, 0xcb50, 0xcb50, 0xcb4f, 0xcb4e,
+ 0xcb4d, 0xcb4d, 0xcb4c, 0xcb4b, 0xcb4a, 0xcb49, 0xcb49, 0xcb48,
+ 0xcb47, 0xcb46, 0xcb46, 0xcb45, 0xcb44, 0xcb43, 0xcb43, 0xcb42,
+ 0xcb41, 0xcb40, 0xcb3f, 0xcb3f, 0xcb3e, 0xcb3d, 0xcb3c, 0xcb3c,
+ 0xcb3b, 0xcb3a, 0xcb39, 0xcb39, 0xcb38, 0xcb37, 0xcb36, 0xcb36,
+ 0xcb35, 0xcb34, 0xcb33, 0xcb33, 0xcb32, 0xcb31, 0xcb30, 0xcb30,
+ 0xcb2f, 0xcb2e, 0xcb2d, 0xcb2d, 0xcb2c, 0xcb2b, 0xcb2a, 0xcb2a,
+ 0xcb29, 0xcb28, 0xcb27, 0xcb27, 0xcb26, 0xcb25, 0xcb24, 0xcb24,
+ 0xcb23, 0xcb22, 0xcb21, 0xcb21, 0xcb20, 0xcb1f, 0xcb1e, 0xcb1e,
+ 0xcb1d, 0xcb1c, 0xcb1b, 0xcb1b, 0xcb1a, 0xcb19, 0xcb18, 0xcb18,
+ 0xcb17, 0xcb16, 0xcb15, 0xcb15, 0xcb14, 0xcb13, 0xcb13, 0xcb12,
+ 0xcb11, 0xcb10, 0xcb10, 0xcb0f, 0xcb0e, 0xcb0d, 0xcb0d, 0xcb0c,
+ 0xcb0b, 0xcb0b, 0xcb0a, 0xcb09, 0xcb08, 0xcb08, 0xcb07, 0xcb06,
+ 0xcb05, 0xcb05, 0xcb04, 0xcb03, 0xcb03, 0xcb02, 0xcb01, 0xcb00,
+ 0xcb00, 0xcaff, 0xcafe, 0xcafe, 0xcafd, 0xcafc, 0xcafb, 0xcafb,
+ 0xcafa, 0xcaf9, 0xcaf9, 0xcaf8, 0xcaf7, 0xcaf6, 0xcaf6, 0xcaf5,
+ 0xcaf4, 0xcaf4, 0xcaf3, 0xcaf2, 0xcaf1, 0xcaf1, 0xcaf0, 0xcaef,
+ 0xcaef, 0xcaee, 0xcaed, 0xcaec, 0xcaec, 0xcaeb, 0xcaea, 0xcaea,
+ 0xcae9, 0xcae8, 0xcae8, 0xcae7, 0xcae6, 0xcae5, 0xcae5, 0xcae4,
+ 0xcae3, 0xcae3, 0xcae2, 0xcae1, 0xcae1, 0xcae0, 0xcadf, 0xcade,
+ 0xcade, 0xcadd, 0xcadc, 0xcadc, 0xcadb, 0xcada, 0xcada, 0xcad9,
+ 0xcad8, 0xcad7, 0xcad7, 0xcad6, 0xcad5, 0xcad5, 0xcad4, 0xcad3,
+ 0xcad3, 0xcad2, 0xcad1, 0xcad1, 0xcad0, 0xcacf, 0xcacf, 0xcace,
+ 0xcacd, 0xcacc, 0xcacc, 0xcacb, 0xcaca, 0xcaca, 0xcac9, 0xcac8,
+ 0xcac8, 0xcac7, 0xcac6, 0xcac6, 0xcac5, 0xcac4, 0xcac4, 0xcac3,
+ 0xcac2, 0xcac2, 0xcac1, 0xcac0, 0xcac0, 0xcabf, 0xcabe, 0xcabe,
+ 0xcabd, 0xcabc, 0xcabc, 0xcabb, 0xcaba, 0xcaba, 0xcab9, 0xcab8,
+ 0xcab7, 0xcab7, 0xcab6, 0xcab5, 0xcab5, 0xcab4, 0xcab3, 0xcab3,
+ 0xcab2, 0xcab1, 0xcab1, 0xcab0, 0xcaaf, 0xcaaf, 0xcaae, 0xcaad,
+ 0xcaad, 0xcaac, 0xcaac, 0xcaab, 0xcaaa, 0xcaaa, 0xcaa9, 0xcaa8,
+ 0xcaa8, 0xcaa7, 0xcaa6, 0xcaa6, 0xcaa5, 0xcaa4, 0xcaa4, 0xcaa3,
+ 0xcaa2, 0xcaa2, 0xcaa1, 0xcaa0, 0xcaa0, 0xca9f, 0xca9e, 0xca9e,
+ 0xca9d, 0xca9c, 0xca9c, 0xca9b, 0xca9a, 0xca9a, 0xca99, 0xca98,
+ 0xca98, 0xca97, 0xca97, 0xca96, 0xca95, 0xca95, 0xca94, 0xca93,
+ 0xca93, 0xca92, 0xca91, 0xca91, 0xca90, 0xca8f, 0xca8f, 0xca8e,
+ 0xca8d, 0xca8d, 0xca8c, 0xca8c, 0xca8b, 0xca8a, 0xca8a, 0xca89,
+ 0xca88, 0xca88, 0xca87, 0xca86, 0xca86, 0xca85, 0xca85, 0xca84,
+ 0xca83, 0xca83, 0xca82, 0xca81, 0xca81, 0xca80, 0xca7f, 0xca7f,
+ 0xca7e, 0xca7e, 0xca7d, 0xca7c, 0xca7c, 0xca7b, 0xca7a, 0xca7a,
+ 0xca79, 0xca78, 0xca78, 0xca77, 0xca77, 0xca76, 0xca75, 0xca75,
+ 0xca74, 0xca73, 0xca73, 0xca72, 0xca72, 0xca71, 0xca70, 0xca70,
+ 0xca6f, 0xca6e, 0xca6e, 0xca6d, 0xca6d, 0xca6c, 0xca6b, 0xca6b,
+ 0xca6a, 0xca69, 0xca69, 0xca68, 0xca68, 0xca67, 0xca66, 0xca66,
+ 0xca65, 0xca65, 0xca64, 0xca63, 0xca63, 0xca62, 0xca61, 0xca61,
+ 0xca60, 0xca60, 0xca5f, 0xca5e, 0xca5e, 0xca5d, 0xca5d, 0xca5c,
+ 0xca5b, 0xca5b, 0xca5a, 0xca59, 0xca59, 0xca58, 0xca58, 0xca57,
+ 0xca56, 0xca56, 0xca55, 0xca55, 0xca54, 0xca53, 0xca53, 0xca52,
+ 0xca52, 0xca51, 0xca50, 0xca50, 0xca4f, 0xca4e, 0xca4e, 0xca4d,
+ 0xca4d, 0xca4c, 0xca4b, 0xca4b, 0xca4a, 0xca4a, 0xca49, 0xca48,
+ 0xca48, 0xca47, 0xca47, 0xca46, 0xca45, 0xca45, 0xca44, 0xca44,
+ 0xca43, 0xca42, 0xca42, 0xca41, 0xca41, 0xca40, 0xca3f, 0xca3f,
+ 0xca3e, 0xca3e, 0xca3d, 0xca3d, 0xca3c, 0xca3b, 0xca3b, 0xca3a,
+ 0xca3a, 0xca39, 0xca38, 0xca38, 0xca37, 0xca37, 0xca36, 0xca35,
+ 0xca35, 0xca34, 0xca34, 0xca33, 0xca32, 0xca32, 0xca31, 0xca31,
+ 0xca30, 0xca30, 0xca2f, 0xca2e, 0xca2e, 0xca2d, 0xca2d, 0xca2c,
+ 0xca2b, 0xca2b, 0xca2a, 0xca2a, 0xca29, 0xca28, 0xca28, 0xca27,
+ 0xca27, 0xca26, 0xca26, 0xca25, 0xca24, 0xca24, 0xca23, 0xca23,
+ 0xca22, 0xca22, 0xca21, 0xca20, 0xca20, 0xca1f, 0xca1f, 0xca1e,
+ 0xca1d, 0xca1d, 0xca1c, 0xca1c, 0xca1b, 0xca1b, 0xca1a, 0xca19,
+ 0xca19, 0xca18, 0xca18, 0xca17, 0xca17, 0xca16, 0xca15, 0xca15,
+ 0xca14, 0xca14, 0xca13, 0xca13, 0xca12, 0xca11, 0xca11, 0xca10,
+ 0xca10, 0xca0f, 0xca0f, 0xca0e, 0xca0d, 0xca0d, 0xca0c, 0xca0c,
+ 0xca0b, 0xca0b, 0xca0a, 0xca0a, 0xca09, 0xca08, 0xca08, 0xca07,
+ 0xca07, 0xca06, 0xca06, 0xca05, 0xca04, 0xca04, 0xca03, 0xca03,
+ 0xca02, 0xca02, 0xca01, 0xca00, 0xca00, 0xc9ff, 0xc9ff, 0xc9fe,
+ 0xc9fe, 0xc9fd, 0xc9fd, 0xc9fc, 0xc9fb, 0xc9fb, 0xc9fa, 0xc9fa,
+ 0xc9f9, 0xc9f9, 0xc9f8, 0xc9f8, 0xc9f7, 0xc9f6, 0xc9f6, 0xc9f5,
+ 0xc9f5, 0xc9f4, 0xc9f4, 0xc9f3, 0xc9f3, 0xc9f2, 0xc9f1, 0xc9f1,
+ 0xc9f0, 0xc9f0, 0xc9ef, 0xc9ef, 0xc9ee, 0xc9ee, 0xc9ed, 0xc9ed,
+ 0xc9ec, 0xc9eb, 0xc9eb, 0xc9ea, 0xc9ea, 0xc9e9, 0xc9e9, 0xc9e8,
+ 0xc9e8, 0xc9e7, 0xc9e6, 0xc9e6, 0xc9e5, 0xc9e5, 0xc9e4, 0xc9e4,
+ 0xc9e3, 0xc9e3, 0xc9e2, 0xc9e2, 0xc9e1, 0xc9e0, 0xc9e0, 0xc9df,
+ 0xc9df, 0xc9de, 0xc9de, 0xc9dd, 0xc9dd, 0xc9dc, 0xc9dc, 0xc9db,
+ 0xc9db, 0xc9da, 0xc9d9, 0xc9d9, 0xc9d8, 0xc9d8, 0xc9d7, 0xc9d7,
+ 0xc9d6, 0xc9d6, 0xc9d5, 0xc9d5, 0xc9d4, 0xc9d4, 0xc9d3, 0xc9d2,
+ 0xc9d2, 0xc9d1, 0xc9d1, 0xc9d0, 0xc9d0, 0xc9cf, 0xc9cf, 0xc9ce,
+ 0xc9ce, 0xc9cd, 0xc9cd, 0xc9cc, 0xc9cc, 0xc9cb, 0xc9ca, 0xc9ca,
+ 0xc9c9, 0xc9c9, 0xc9c8, 0xc9c8, 0xc9c7, 0xc9c7, 0xc9c6, 0xc9c6,
+ 0xc9c5, 0xc9c5, 0xc9c4, 0xc9c4, 0xc9c3, 0xc9c3, 0xc9c2, 0xc9c1,
+ 0xc9c1, 0xc9c0, 0xc9c0, 0xc9bf, 0xc9bf, 0xc9be, 0xc9be, 0xc9bd,
+ 0xc9bd, 0xc9bc, 0xc9bc, 0xc9bb, 0xc9bb, 0xc9ba, 0xc9ba, 0xc9b9,
+ 0xc9b9, 0xc9b8, 0xc9b7, 0xc9b7, 0xc9b6, 0xc9b6, 0xc9b5, 0xc9b5,
+ 0xc9b4, 0xc9b4, 0xc9b3, 0xc9b3, 0xc9b2, 0xc9b2, 0xc9b1, 0xc9b1,
+ 0xc9b0, 0xc9b0, 0xc9af, 0xc9af, 0xc9ae, 0xc9ae, 0xc9ad, 0xc9ad,
+ 0xc9ac, 0xc9ac, 0xc9ab, 0xc9ab, 0xc9aa, 0xc9a9, 0xc9a9, 0xc9a8,
+ 0xc9a8, 0xc9a7, 0xc9a7, 0xc9a6, 0xc9a6, 0xc9a5, 0xc9a5, 0xc9a4,
+ 0xc9a4, 0xc9a3, 0xc9a3, 0xc9a2, 0xc9a2, 0xc9a1, 0xc9a1, 0xc9a0,
+ 0xc9a0, 0xc99f, 0xc99f, 0xc99e, 0xc99e, 0xc99d, 0xc99d, 0xc99c,
+ 0xc99c, 0xc99b, 0xc99b, 0xc99a, 0xc99a, 0xc999, 0xc999, 0xc998,
+ 0xc998, 0xc997, 0xc997, 0xc996, 0xc996, 0xc995, 0xc995, 0xc994,
+ 0xc994, 0xc993, 0xc993, 0xc992, 0xc992, 0xc991, 0xc991, 0xc990,
+ 0xc990, 0xc98f, 0xc98f, 0xc98e, 0xc98e, 0xc98d, 0xc98d, 0xc98c,
+ 0xc98c, 0xc98b, 0xc98a, 0xc989, 0xc988, 0xc987, 0xc986, 0xc985,
+ 0xc984, 0xc983, 0xc982, 0xc981, 0xc980, 0xc97f, 0xc97e, 0xc97d,
+ 0xc97c, 0xc97b, 0xc97a, 0xc979, 0xc978, 0xc977, 0xc976, 0xc975,
+ 0xc974, 0xc973, 0xc972, 0xc971, 0xc970, 0xc96f, 0xc96e, 0xc96d,
+ 0xc96c, 0xc96b, 0xc96a, 0xc969, 0xc968, 0xc967, 0xc966, 0xc965,
+ 0xc964, 0xc963, 0xc962, 0xc961, 0xc960, 0xc960, 0xc95f, 0xc95e,
+ 0xc95d, 0xc95c, 0xc95b, 0xc95a, 0xc959, 0xc958, 0xc957, 0xc956,
+ 0xc955, 0xc954, 0xc953, 0xc952, 0xc951, 0xc950, 0xc94f, 0xc94e,
+ 0xc94d, 0xc94d, 0xc94c, 0xc94b, 0xc94a, 0xc949, 0xc948, 0xc947,
+ 0xc946, 0xc945, 0xc944, 0xc943, 0xc942, 0xc941, 0xc940, 0xc93f,
+ 0xc93f, 0xc93e, 0xc93d, 0xc93c, 0xc93b, 0xc93a, 0xc939, 0xc938,
+ 0xc937, 0xc936, 0xc935, 0xc934, 0xc933, 0xc933, 0xc932, 0xc931,
+ 0xc930, 0xc92f, 0xc92e, 0xc92d, 0xc92c, 0xc92b, 0xc92a, 0xc929,
+ 0xc929, 0xc928, 0xc927, 0xc926, 0xc925, 0xc924, 0xc923, 0xc922,
+ 0xc921, 0xc920, 0xc91f, 0xc91f, 0xc91e, 0xc91d, 0xc91c, 0xc91b,
+ 0xc91a, 0xc919, 0xc918, 0xc917, 0xc917, 0xc916, 0xc915, 0xc914,
+ 0xc913, 0xc912, 0xc911, 0xc910, 0xc90f, 0xc90f, 0xc90e, 0xc90d,
+ 0xc90c, 0xc90b, 0xc90a, 0xc909, 0xc908, 0xc907, 0xc907, 0xc906,
+ 0xc905, 0xc904, 0xc903, 0xc902, 0xc901, 0xc900, 0xc900, 0xc8ff,
+ 0xc8fe, 0xc8fd, 0xc8fc, 0xc8fb, 0xc8fa, 0xc8f9, 0xc8f9, 0xc8f8,
+ 0xc8f7, 0xc8f6, 0xc8f5, 0xc8f4, 0xc8f3, 0xc8f3, 0xc8f2, 0xc8f1,
+ 0xc8f0, 0xc8ef, 0xc8ee, 0xc8ed, 0xc8ed, 0xc8ec, 0xc8eb, 0xc8ea,
+ 0xc8e9, 0xc8e8, 0xc8e7, 0xc8e7, 0xc8e6, 0xc8e5, 0xc8e4, 0xc8e3,
+ 0xc8e2, 0xc8e2, 0xc8e1, 0xc8e0, 0xc8df, 0xc8de, 0xc8dd, 0xc8dc,
+ 0xc8dc, 0xc8db, 0xc8da, 0xc8d9, 0xc8d8, 0xc8d7, 0xc8d7, 0xc8d6,
+ 0xc8d5, 0xc8d4, 0xc8d3, 0xc8d2, 0xc8d2, 0xc8d1, 0xc8d0, 0xc8cf,
+ 0xc8ce, 0xc8cd, 0xc8cd, 0xc8cc, 0xc8cb, 0xc8ca, 0xc8c9, 0xc8c8,
+ 0xc8c8, 0xc8c7, 0xc8c6, 0xc8c5, 0xc8c4, 0xc8c3, 0xc8c3, 0xc8c2,
+ 0xc8c1, 0xc8c0, 0xc8bf, 0xc8bf, 0xc8be, 0xc8bd, 0xc8bc, 0xc8bb,
+ 0xc8ba, 0xc8ba, 0xc8b9, 0xc8b8, 0xc8b7, 0xc8b6, 0xc8b6, 0xc8b5,
+ 0xc8b4, 0xc8b3, 0xc8b2, 0xc8b2, 0xc8b1, 0xc8b0, 0xc8af, 0xc8ae,
+ 0xc8ad, 0xc8ad, 0xc8ac, 0xc8ab, 0xc8aa, 0xc8a9, 0xc8a9, 0xc8a8,
+ 0xc8a7, 0xc8a6, 0xc8a5, 0xc8a5, 0xc8a4, 0xc8a3, 0xc8a2, 0xc8a1,
+ 0xc8a1, 0xc8a0, 0xc89f, 0xc89e, 0xc89e, 0xc89d, 0xc89c, 0xc89b,
+ 0xc89a, 0xc89a, 0xc899, 0xc898, 0xc897, 0xc896, 0xc896, 0xc895,
+ 0xc894, 0xc893, 0xc892, 0xc892, 0xc891, 0xc890, 0xc88f, 0xc88f,
+ 0xc88e, 0xc88d, 0xc88c, 0xc88b, 0xc88b, 0xc88a, 0xc889, 0xc888,
+ 0xc888, 0xc887, 0xc886, 0xc885, 0xc884, 0xc884, 0xc883, 0xc882,
+ 0xc881, 0xc881, 0xc880, 0xc87f, 0xc87e, 0xc87e, 0xc87d, 0xc87c,
+ 0xc87b, 0xc87a, 0xc87a, 0xc879, 0xc878, 0xc877, 0xc877, 0xc876,
+ 0xc875, 0xc874, 0xc874, 0xc873, 0xc872, 0xc871, 0xc871, 0xc870,
+ 0xc86f, 0xc86e, 0xc86e, 0xc86d, 0xc86c, 0xc86b, 0xc86a, 0xc86a,
+ 0xc869, 0xc868, 0xc867, 0xc867, 0xc866, 0xc865, 0xc864, 0xc864,
+ 0xc863, 0xc862, 0xc861, 0xc861, 0xc860, 0xc85f, 0xc85e, 0xc85e,
+ 0xc85d, 0xc85c, 0xc85c, 0xc85b, 0xc85a, 0xc859, 0xc859, 0xc858,
+ 0xc857, 0xc856, 0xc856, 0xc855, 0xc854, 0xc853, 0xc853, 0xc852,
+ 0xc851, 0xc850, 0xc850, 0xc84f, 0xc84e, 0xc84e, 0xc84d, 0xc84c,
+ 0xc84b, 0xc84b, 0xc84a, 0xc849, 0xc848, 0xc848, 0xc847, 0xc846,
+ 0xc845, 0xc845, 0xc844, 0xc843, 0xc843, 0xc842, 0xc841, 0xc840,
+ 0xc840, 0xc83f, 0xc83e, 0xc83d, 0xc83d, 0xc83c, 0xc83b, 0xc83b,
+ 0xc83a, 0xc839, 0xc838, 0xc838, 0xc837, 0xc836, 0xc836, 0xc835,
+ 0xc834, 0xc833, 0xc833, 0xc832, 0xc831, 0xc831, 0xc830, 0xc82f,
+ 0xc82e, 0xc82e, 0xc82d, 0xc82c, 0xc82c, 0xc82b, 0xc82a, 0xc829,
+ 0xc829, 0xc828, 0xc827, 0xc827, 0xc826, 0xc825, 0xc825, 0xc824,
+ 0xc823, 0xc822, 0xc822, 0xc821, 0xc820, 0xc820, 0xc81f, 0xc81e,
+ 0xc81e, 0xc81d, 0xc81c, 0xc81b, 0xc81b, 0xc81a, 0xc819, 0xc819,
+ 0xc818, 0xc817, 0xc817, 0xc816, 0xc815, 0xc814, 0xc814, 0xc813,
+ 0xc812, 0xc812, 0xc811, 0xc810, 0xc810, 0xc80f, 0xc80e, 0xc80e,
+ 0xc80d, 0xc80c, 0xc80c, 0xc80b, 0xc80a, 0xc809, 0xc809, 0xc808,
+ 0xc807, 0xc807, 0xc806, 0xc805, 0xc805, 0xc804, 0xc803, 0xc803,
+ 0xc802, 0xc801, 0xc801, 0xc800, 0xc7fe, 0xc7fd, 0xc7fc, 0xc7fa,
+ 0xc7f9, 0xc7f8, 0xc7f6, 0xc7f5, 0xc7f4, 0xc7f2, 0xc7f1, 0xc7f0,
+ 0xc7ee, 0xc7ed, 0xc7eb, 0xc7ea, 0xc7e9, 0xc7e7, 0xc7e6, 0xc7e5,
+ 0xc7e3, 0xc7e2, 0xc7e1, 0xc7df, 0xc7de, 0xc7dd, 0xc7db, 0xc7da,
+ 0xc7d9, 0xc7d7, 0xc7d6, 0xc7d5, 0xc7d3, 0xc7d2, 0xc7d1, 0xc7cf,
+ 0xc7ce, 0xc7cd, 0xc7cb, 0xc7ca, 0xc7c9, 0xc7c7, 0xc7c6, 0xc7c5,
+ 0xc7c4, 0xc7c2, 0xc7c1, 0xc7c0, 0xc7be, 0xc7bd, 0xc7bc, 0xc7ba,
+ 0xc7b9, 0xc7b8, 0xc7b6, 0xc7b5, 0xc7b4, 0xc7b2, 0xc7b1, 0xc7b0,
+ 0xc7af, 0xc7ad, 0xc7ac, 0xc7ab, 0xc7a9, 0xc7a8, 0xc7a7, 0xc7a5,
+ 0xc7a4, 0xc7a3, 0xc7a1, 0xc7a0, 0xc79f, 0xc79e, 0xc79c, 0xc79b,
+ 0xc79a, 0xc798, 0xc797, 0xc796, 0xc795, 0xc793, 0xc792, 0xc791,
+ 0xc78f, 0xc78e, 0xc78d, 0xc78c, 0xc78a, 0xc789, 0xc788, 0xc786,
+ 0xc785, 0xc784, 0xc783, 0xc781, 0xc780, 0xc77f, 0xc77d, 0xc77c,
+ 0xc77b, 0xc77a, 0xc778, 0xc777, 0xc776, 0xc775, 0xc773, 0xc772,
+ 0xc771, 0xc76f, 0xc76e, 0xc76d, 0xc76c, 0xc76a, 0xc769, 0xc768,
+ 0xc767, 0xc765, 0xc764, 0xc763, 0xc762, 0xc760, 0xc75f, 0xc75e,
+ 0xc75d, 0xc75b, 0xc75a, 0xc759, 0xc758, 0xc756, 0xc755, 0xc754,
+ 0xc753, 0xc751, 0xc750, 0xc74f, 0xc74e, 0xc74c, 0xc74b, 0xc74a,
+ 0xc749, 0xc747, 0xc746, 0xc745, 0xc744, 0xc742, 0xc741, 0xc740,
+ 0xc73f, 0xc73d, 0xc73c, 0xc73b, 0xc73a, 0xc739, 0xc737, 0xc736,
+ 0xc735, 0xc734, 0xc732, 0xc731, 0xc730, 0xc72f, 0xc72d, 0xc72c,
+ 0xc72b, 0xc72a, 0xc729, 0xc727, 0xc726, 0xc725, 0xc724, 0xc722,
+ 0xc721, 0xc720, 0xc71f, 0xc71e, 0xc71c, 0xc71b, 0xc71a, 0xc719,
+ 0xc717, 0xc716, 0xc715, 0xc714, 0xc713, 0xc711, 0xc710, 0xc70f,
+ 0xc70e, 0xc70d, 0xc70b, 0xc70a, 0xc709, 0xc708, 0xc707, 0xc705,
+ 0xc704, 0xc703, 0xc702, 0xc701, 0xc6ff, 0xc6fe, 0xc6fd, 0xc6fc,
+ 0xc6fb, 0xc6f9, 0xc6f8, 0xc6f7, 0xc6f6, 0xc6f5, 0xc6f3, 0xc6f2,
+ 0xc6f1, 0xc6f0, 0xc6ef, 0xc6ed, 0xc6ec, 0xc6eb, 0xc6ea, 0xc6e9,
+ 0xc6e8, 0xc6e6, 0xc6e5, 0xc6e4, 0xc6e3, 0xc6e2, 0xc6e0, 0xc6df,
+ 0xc6de, 0xc6dd, 0xc6dc, 0xc6db, 0xc6d9, 0xc6d8, 0xc6d7, 0xc6d6,
+ 0xc6d5, 0xc6d3, 0xc6d2, 0xc6d1, 0xc6d0, 0xc6cf, 0xc6ce, 0xc6cc,
+ 0xc6cb, 0xc6ca, 0xc6c9, 0xc6c8, 0xc6c7, 0xc6c5, 0xc6c4, 0xc6c3,
+ 0xc6c2, 0xc6c1, 0xc6c0, 0xc6be, 0xc6bd, 0xc6bc, 0xc6bb, 0xc6ba,
+ 0xc6b9, 0xc6b7, 0xc6b6, 0xc6b5, 0xc6b4, 0xc6b3, 0xc6b2, 0xc6b1,
+ 0xc6af, 0xc6ae, 0xc6ad, 0xc6ac, 0xc6ab, 0xc6aa, 0xc6a8, 0xc6a7,
+ 0xc6a6, 0xc6a5, 0xc6a4, 0xc6a3, 0xc6a2, 0xc6a0, 0xc69f, 0xc69e,
+ 0xc69d, 0xc69c, 0xc69b, 0xc69a, 0xc698, 0xc697, 0xc696, 0xc695,
+ 0xc694, 0xc693, 0xc692, 0xc691, 0xc68f, 0xc68e, 0xc68d, 0xc68c,
+ 0xc68b, 0xc68a, 0xc689, 0xc687, 0xc686, 0xc685, 0xc684, 0xc683,
+ 0xc682, 0xc681, 0xc680, 0xc67e, 0xc67d, 0xc67c, 0xc67b, 0xc67a,
+ 0xc679, 0xc678, 0xc677, 0xc675, 0xc674, 0xc673, 0xc672, 0xc671,
+ 0xc670, 0xc66f, 0xc66e, 0xc66c, 0xc66b, 0xc66a, 0xc669, 0xc668,
+ 0xc667, 0xc666, 0xc665, 0xc664, 0xc662, 0xc661, 0xc660, 0xc65f,
+ 0xc65e, 0xc65d, 0xc65c, 0xc65b, 0xc65a, 0xc658, 0xc657, 0xc656,
+ 0xc655, 0xc654, 0xc653, 0xc652, 0xc651, 0xc650, 0xc64f, 0xc64d,
+ 0xc64c, 0xc64b, 0xc64a, 0xc649, 0xc648, 0xc647, 0xc646, 0xc645,
+ 0xc644, 0xc642, 0xc641, 0xc640, 0xc63f, 0xc63e, 0xc63d, 0xc63c,
+ 0xc63b, 0xc63a, 0xc639, 0xc638, 0xc637, 0xc635, 0xc634, 0xc633,
+ 0xc632, 0xc631, 0xc630, 0xc62f, 0xc62e, 0xc62d, 0xc62c, 0xc62b,
+ 0xc62a, 0xc628, 0xc627, 0xc626, 0xc625, 0xc624, 0xc623, 0xc622,
+ 0xc621, 0xc620, 0xc61f, 0xc61e, 0xc61d, 0xc61c, 0xc61a, 0xc619,
+ 0xc618, 0xc617, 0xc616, 0xc615, 0xc614, 0xc613, 0xc612, 0xc611,
+ 0xc610, 0xc60f, 0xc60e, 0xc60d, 0xc60b, 0xc60a, 0xc609, 0xc608,
+ 0xc607, 0xc606, 0xc605, 0xc604, 0xc603, 0xc602, 0xc601, 0xc600,
+ 0xc5ff, 0xc5fe, 0xc5fd, 0xc5fc, 0xc5fb, 0xc5f9, 0xc5f8, 0xc5f7,
+ 0xc5f6, 0xc5f5, 0xc5f4, 0xc5f3, 0xc5f2, 0xc5f1, 0xc5f0, 0xc5ef,
+ 0xc5ee, 0xc5ed, 0xc5ec, 0xc5eb, 0xc5ea, 0xc5e9, 0xc5e8, 0xc5e7,
+ 0xc5e6, 0xc5e4, 0xc5e3, 0xc5e2, 0xc5e1, 0xc5e0, 0xc5df, 0xc5de,
+ 0xc5dd, 0xc5dc, 0xc5db, 0xc5da, 0xc5d9, 0xc5d8, 0xc5d7, 0xc5d6,
+ 0xc5d5, 0xc5d4, 0xc5d3, 0xc5d2, 0xc5d1, 0xc5d0, 0xc5cf, 0xc5ce,
+ 0xc5cd, 0xc5cc, 0xc5cb, 0xc5c9, 0xc5c8, 0xc5c7, 0xc5c6, 0xc5c5,
+ 0xc5c4, 0xc5c3, 0xc5c2, 0xc5c1, 0xc5c0, 0xc5bf, 0xc5be, 0xc5bd,
+ 0xc5bc, 0xc5bb, 0xc5ba, 0xc5b9, 0xc5b8, 0xc5b7, 0xc5b6, 0xc5b5,
+ 0xc5b4, 0xc5b3, 0xc5b2, 0xc5b1, 0xc5b0, 0xc5af, 0xc5ae, 0xc5ad,
+ 0xc5ac, 0xc5ab, 0xc5aa, 0xc5a9, 0xc5a8, 0xc5a7, 0xc5a6, 0xc5a5,
+ 0xc5a4, 0xc5a3, 0xc5a2, 0xc5a1, 0xc5a0, 0xc59f, 0xc59e, 0xc59d,
+ 0xc59c, 0xc59b, 0xc59a, 0xc599, 0xc598, 0xc597, 0xc596, 0xc595,
+ 0xc594, 0xc593, 0xc592, 0xc591, 0xc590, 0xc58f, 0xc58e, 0xc58d,
+ 0xc58c, 0xc58a, 0xc588, 0xc586, 0xc584, 0xc582, 0xc580, 0xc57e,
+ 0xc57c, 0xc57a, 0xc578, 0xc576, 0xc574, 0xc572, 0xc570, 0xc56e,
+ 0xc56c, 0xc56a, 0xc568, 0xc566, 0xc564, 0xc562, 0xc560, 0xc55e,
+ 0xc55c, 0xc55a, 0xc558, 0xc556, 0xc554, 0xc552, 0xc550, 0xc54e,
+ 0xc54d, 0xc54b, 0xc549, 0xc547, 0xc545, 0xc543, 0xc541, 0xc53f,
+ 0xc53d, 0xc53b, 0xc539, 0xc537, 0xc535, 0xc533, 0xc532, 0xc530,
+ 0xc52e, 0xc52c, 0xc52a, 0xc528, 0xc526, 0xc524, 0xc522, 0xc520,
+ 0xc51f, 0xc51d, 0xc51b, 0xc519, 0xc517, 0xc515, 0xc513, 0xc511,
+ 0xc50f, 0xc50e, 0xc50c, 0xc50a, 0xc508, 0xc506, 0xc504, 0xc502,
+ 0xc500, 0xc4ff, 0xc4fd, 0xc4fb, 0xc4f9, 0xc4f7, 0xc4f5, 0xc4f3,
+ 0xc4f2, 0xc4f0, 0xc4ee, 0xc4ec, 0xc4ea, 0xc4e8, 0xc4e6, 0xc4e5,
+ 0xc4e3, 0xc4e1, 0xc4df, 0xc4dd, 0xc4db, 0xc4da, 0xc4d8, 0xc4d6,
+ 0xc4d4, 0xc4d2, 0xc4d0, 0xc4cf, 0xc4cd, 0xc4cb, 0xc4c9, 0xc4c7,
+ 0xc4c5, 0xc4c4, 0xc4c2, 0xc4c0, 0xc4be, 0xc4bc, 0xc4bb, 0xc4b9,
+ 0xc4b7, 0xc4b5, 0xc4b3, 0xc4b2, 0xc4b0, 0xc4ae, 0xc4ac, 0xc4aa,
+ 0xc4a9, 0xc4a7, 0xc4a5, 0xc4a3, 0xc4a1, 0xc4a0, 0xc49e, 0xc49c,
+ 0xc49a, 0xc499, 0xc497, 0xc495, 0xc493, 0xc491, 0xc490, 0xc48e,
+ 0xc48c, 0xc48a, 0xc489, 0xc487, 0xc485, 0xc483, 0xc482, 0xc480,
+ 0xc47e, 0xc47c, 0xc47b, 0xc479, 0xc477, 0xc475, 0xc474, 0xc472,
+ 0xc470, 0xc46e, 0xc46d, 0xc46b, 0xc469, 0xc467, 0xc466, 0xc464,
+ 0xc462, 0xc461, 0xc45f, 0xc45d, 0xc45b, 0xc45a, 0xc458, 0xc456,
+ 0xc454, 0xc453, 0xc451, 0xc44f, 0xc44e, 0xc44c, 0xc44a, 0xc448,
+ 0xc447, 0xc445, 0xc443, 0xc442, 0xc440, 0xc43e, 0xc43d, 0xc43b,
+ 0xc439, 0xc437, 0xc436, 0xc434, 0xc432, 0xc431, 0xc42f, 0xc42d,
+ 0xc42c, 0xc42a, 0xc428, 0xc427, 0xc425, 0xc423, 0xc422, 0xc420,
+ 0xc41e, 0xc41d, 0xc41b, 0xc419, 0xc418, 0xc416, 0xc414, 0xc413,
+ 0xc411, 0xc40f, 0xc40e, 0xc40c, 0xc40a, 0xc409, 0xc407, 0xc405,
+ 0xc404, 0xc402, 0xc400, 0xc3fd, 0xc3fa, 0xc3f7, 0xc3f3, 0xc3f0,
+ 0xc3ed, 0xc3ea, 0xc3e6, 0xc3e3, 0xc3e0, 0xc3dc, 0xc3d9, 0xc3d6,
+ 0xc3d3, 0xc3cf, 0xc3cc, 0xc3c9, 0xc3c6, 0xc3c2, 0xc3bf, 0xc3bc,
+ 0xc3b9, 0xc3b5, 0xc3b2, 0xc3af, 0xc3ac, 0xc3a8, 0xc3a5, 0xc3a2,
+ 0xc39f, 0xc39c, 0xc398, 0xc395, 0xc392, 0xc38f, 0xc38c, 0xc388,
+ 0xc385, 0xc382, 0xc37f, 0xc37c, 0xc378, 0xc375, 0xc372, 0xc36f,
+ 0xc36c, 0xc368, 0xc365, 0xc362, 0xc35f, 0xc35c, 0xc359, 0xc355,
+ 0xc352, 0xc34f, 0xc34c, 0xc349, 0xc346, 0xc342, 0xc33f, 0xc33c,
+ 0xc339, 0xc336, 0xc333, 0xc330, 0xc32d, 0xc329, 0xc326, 0xc323,
+ 0xc320, 0xc31d, 0xc31a, 0xc317, 0xc314, 0xc310, 0xc30d, 0xc30a,
+ 0xc307, 0xc304, 0xc301, 0xc2fe, 0xc2fb, 0xc2f8, 0xc2f5, 0xc2f1,
+ 0xc2ee, 0xc2eb, 0xc2e8, 0xc2e5, 0xc2e2, 0xc2df, 0xc2dc, 0xc2d9,
+ 0xc2d6, 0xc2d3, 0xc2d0, 0xc2cd, 0xc2c9, 0xc2c6, 0xc2c3, 0xc2c0,
+ 0xc2bd, 0xc2ba, 0xc2b7, 0xc2b4, 0xc2b1, 0xc2ae, 0xc2ab, 0xc2a8,
+ 0xc2a5, 0xc2a2, 0xc29f, 0xc29c, 0xc299, 0xc296, 0xc293, 0xc290,
+ 0xc28d, 0xc28a, 0xc287, 0xc284, 0xc281, 0xc27e, 0xc27b, 0xc278,
+ 0xc275, 0xc272, 0xc26f, 0xc26c, 0xc269, 0xc266, 0xc263, 0xc260,
+ 0xc25d, 0xc25a, 0xc257, 0xc254, 0xc251, 0xc24e, 0xc24b, 0xc248,
+ 0xc245, 0xc242, 0xc23f, 0xc23c, 0xc239, 0xc236, 0xc233, 0xc230,
+ 0xc22e, 0xc22b, 0xc228, 0xc225, 0xc222, 0xc21f, 0xc21c, 0xc219,
+ 0xc216, 0xc213, 0xc210, 0xc20d, 0xc20a, 0xc207, 0xc205, 0xc202,
+ 0xc1ff, 0xc1fc, 0xc1f9, 0xc1f6, 0xc1f3, 0xc1f0, 0xc1ed, 0xc1ea,
+ 0xc1e8, 0xc1e5, 0xc1e2, 0xc1df, 0xc1dc, 0xc1d9, 0xc1d6, 0xc1d3,
+ 0xc1d0, 0xc1ce, 0xc1cb, 0xc1c8, 0xc1c5, 0xc1c2, 0xc1bf, 0xc1bc,
+ 0xc1ba, 0xc1b7, 0xc1b4, 0xc1b1, 0xc1ae, 0xc1ab, 0xc1a8, 0xc1a6,
+ 0xc1a3, 0xc1a0, 0xc19d, 0xc19a, 0xc197, 0xc194, 0xc192, 0xc18f,
+ 0xc18c, 0xc189, 0xc186, 0xc184, 0xc181, 0xc17e, 0xc17b, 0xc178,
+ 0xc175, 0xc173, 0xc170, 0xc16d, 0xc16a, 0xc167, 0xc165, 0xc162,
+ 0xc15f, 0xc15c, 0xc159, 0xc157, 0xc154, 0xc151, 0xc14e, 0xc14b,
+ 0xc149, 0xc146, 0xc143, 0xc140, 0xc13e, 0xc13b, 0xc138, 0xc135,
+ 0xc132, 0xc130, 0xc12d, 0xc12a, 0xc127, 0xc125, 0xc122, 0xc11f,
+ 0xc11c, 0xc11a, 0xc117, 0xc114, 0xc111, 0xc10f, 0xc10c, 0xc109,
+ 0xc106, 0xc104, 0xc101, 0xc0fe, 0xc0fb, 0xc0f9, 0xc0f6, 0xc0f3,
+ 0xc0f1, 0xc0ee, 0xc0eb, 0xc0e8, 0xc0e6, 0xc0e3, 0xc0e0, 0xc0de,
+ 0xc0db, 0xc0d8, 0xc0d5, 0xc0d3, 0xc0d0, 0xc0cd, 0xc0cb, 0xc0c8,
+ 0xc0c5, 0xc0c3, 0xc0c0, 0xc0bd, 0xc0ba, 0xc0b8, 0xc0b5, 0xc0b2,
+ 0xc0b0, 0xc0ad, 0xc0aa, 0xc0a8, 0xc0a5, 0xc0a2, 0xc0a0, 0xc09d,
+ 0xc09a, 0xc098, 0xc095, 0xc092, 0xc090, 0xc08d, 0xc08a, 0xc088,
+ 0xc085, 0xc082, 0xc080, 0xc07d, 0xc07a, 0xc078, 0xc075, 0xc073,
+ 0xc070, 0xc06d, 0xc06b, 0xc068, 0xc065, 0xc063, 0xc060, 0xc05d,
+ 0xc05b, 0xc058, 0xc056, 0xc053, 0xc050, 0xc04e, 0xc04b, 0xc049,
+ 0xc046, 0xc043, 0xc041, 0xc03e, 0xc03b, 0xc039, 0xc036, 0xc034,
+ 0xc031, 0xc02e, 0xc02c, 0xc029, 0xc027, 0xc024, 0xc021, 0xc01f,
+ 0xc01c, 0xc01a, 0xc017, 0xc015, 0xc012, 0xc00f, 0xc00d, 0xc00a,
+ 0xc008, 0xc005, 0xc003, 0xc000, 0xbffb, 0xbff6, 0xbff1, 0xbfeb,
+ 0xbfe6, 0xbfe1, 0xbfdc, 0xbfd7, 0xbfd2, 0xbfcd, 0xbfc8, 0xbfc3,
+ 0xbfbd, 0xbfb8, 0xbfb3, 0xbfae, 0xbfa9, 0xbfa4, 0xbf9f, 0xbf9a,
+ 0xbf95, 0xbf90, 0xbf8b, 0xbf86, 0xbf81, 0xbf7b, 0xbf76, 0xbf71,
+ 0xbf6c, 0xbf67, 0xbf62, 0xbf5d, 0xbf58, 0xbf53, 0xbf4e, 0xbf49,
+ 0xbf44, 0xbf3f, 0xbf3a, 0xbf35, 0xbf30, 0xbf2b, 0xbf26, 0xbf21,
+ 0xbf1c, 0xbf17, 0xbf12, 0xbf0d, 0xbf08, 0xbf03, 0xbefe, 0xbef9,
+ 0xbef4, 0xbeef, 0xbeea, 0xbee5, 0xbee0, 0xbedb, 0xbed6, 0xbed1,
+ 0xbecc, 0xbec8, 0xbec3, 0xbebe, 0xbeb9, 0xbeb4, 0xbeaf, 0xbeaa,
+ 0xbea5, 0xbea0, 0xbe9b, 0xbe96, 0xbe91, 0xbe8c, 0xbe87, 0xbe83,
+ 0xbe7e, 0xbe79, 0xbe74, 0xbe6f, 0xbe6a, 0xbe65, 0xbe60, 0xbe5b,
+ 0xbe57, 0xbe52, 0xbe4d, 0xbe48, 0xbe43, 0xbe3e, 0xbe39, 0xbe35,
+ 0xbe30, 0xbe2b, 0xbe26, 0xbe21, 0xbe1c, 0xbe17, 0xbe13, 0xbe0e,
+ 0xbe09, 0xbe04, 0xbdff, 0xbdfa, 0xbdf6, 0xbdf1, 0xbdec, 0xbde7,
+ 0xbde2, 0xbdde, 0xbdd9, 0xbdd4, 0xbdcf, 0xbdca, 0xbdc6, 0xbdc1,
+ 0xbdbc, 0xbdb7, 0xbdb2, 0xbdae, 0xbda9, 0xbda4, 0xbd9f, 0xbd9b,
+ 0xbd96, 0xbd91, 0xbd8c, 0xbd88, 0xbd83, 0xbd7e, 0xbd79, 0xbd75,
+ 0xbd70, 0xbd6b, 0xbd66, 0xbd62, 0xbd5d, 0xbd58, 0xbd53, 0xbd4f,
+ 0xbd4a, 0xbd45, 0xbd41, 0xbd3c, 0xbd37, 0xbd32, 0xbd2e, 0xbd29,
+ 0xbd24, 0xbd20, 0xbd1b, 0xbd16, 0xbd12, 0xbd0d, 0xbd08, 0xbd03,
+ 0xbcff, 0xbcfa, 0xbcf5, 0xbcf1, 0xbcec, 0xbce7, 0xbce3, 0xbcde,
+ 0xbcd9, 0xbcd5, 0xbcd0, 0xbccc, 0xbcc7, 0xbcc2, 0xbcbe, 0xbcb9,
+ 0xbcb4, 0xbcb0, 0xbcab, 0xbca6, 0xbca2, 0xbc9d, 0xbc99, 0xbc94,
+ 0xbc8f, 0xbc8b, 0xbc86, 0xbc82, 0xbc7d, 0xbc78, 0xbc74, 0xbc6f,
+ 0xbc6b, 0xbc66, 0xbc61, 0xbc5d, 0xbc58, 0xbc54, 0xbc4f, 0xbc4a,
+ 0xbc46, 0xbc41, 0xbc3d, 0xbc38, 0xbc34, 0xbc2f, 0xbc2b, 0xbc26,
+ 0xbc21, 0xbc1d, 0xbc18, 0xbc14, 0xbc0f, 0xbc0b, 0xbc06, 0xbc02,
+ 0xbbfa, 0xbbf1, 0xbbe8, 0xbbdf, 0xbbd6, 0xbbcd, 0xbbc4, 0xbbbb,
+ 0xbbb2, 0xbba9, 0xbba0, 0xbb97, 0xbb8e, 0xbb85, 0xbb7c, 0xbb73,
+ 0xbb6a, 0xbb61, 0xbb58, 0xbb4f, 0xbb46, 0xbb3d, 0xbb34, 0xbb2b,
+ 0xbb22, 0xbb19, 0xbb10, 0xbb07, 0xbafe, 0xbaf5, 0xbaed, 0xbae4,
+ 0xbadb, 0xbad2, 0xbac9, 0xbac0, 0xbab7, 0xbaae, 0xbaa5, 0xba9c,
+ 0xba94, 0xba8b, 0xba82, 0xba79, 0xba70, 0xba67, 0xba5f, 0xba56,
+ 0xba4d, 0xba44, 0xba3b, 0xba32, 0xba2a, 0xba21, 0xba18, 0xba0f,
+ 0xba06, 0xb9fe, 0xb9f5, 0xb9ec, 0xb9e3, 0xb9da, 0xb9d2, 0xb9c9,
+ 0xb9c0, 0xb9b7, 0xb9af, 0xb9a6, 0xb99d, 0xb995, 0xb98c, 0xb983,
+ 0xb97a, 0xb972, 0xb969, 0xb960, 0xb958, 0xb94f, 0xb946, 0xb93d,
+ 0xb935, 0xb92c, 0xb923, 0xb91b, 0xb912, 0xb909, 0xb901, 0xb8f8,
+ 0xb8ef, 0xb8e7, 0xb8de, 0xb8d6, 0xb8cd, 0xb8c4, 0xb8bc, 0xb8b3,
+ 0xb8ab, 0xb8a2, 0xb899, 0xb891, 0xb888, 0xb880, 0xb877, 0xb86e,
+ 0xb866, 0xb85d, 0xb855, 0xb84c, 0xb844, 0xb83b, 0xb832, 0xb82a,
+ 0xb821, 0xb819, 0xb810, 0xb808, 0xb7ff, 0xb7ee, 0xb7dd, 0xb7cc,
+ 0xb7bb, 0xb7aa, 0xb799, 0xb788, 0xb777, 0xb766, 0xb755, 0xb744,
+ 0xb733, 0xb722, 0xb711, 0xb700, 0xb6ef, 0xb6de, 0xb6cd, 0xb6bd,
+ 0xb6ac, 0xb69b, 0xb68a, 0xb679, 0xb668, 0xb658, 0xb647, 0xb636,
+ 0xb625, 0xb614, 0xb604, 0xb5f3, 0xb5e2, 0xb5d1, 0xb5c1, 0xb5b0,
+ 0xb59f, 0xb58e, 0xb57e, 0xb56d, 0xb55c, 0xb54c, 0xb53b, 0xb52a,
+ 0xb51a, 0xb509, 0xb4f8, 0xb4e8, 0xb4d7, 0xb4c7, 0xb4b6, 0xb4a5,
+ 0xb495, 0xb484, 0xb474, 0xb463, 0xb452, 0xb442, 0xb431, 0xb421,
+ 0xb410, 0xb400, 0xb3df, 0xb3be, 0xb39d, 0xb37c, 0xb35b, 0xb33a,
+ 0xb319, 0xb2f8, 0xb2d7, 0xb2b6, 0xb295, 0xb275, 0xb254, 0xb233,
+ 0xb212, 0xb1f2, 0xb1d1, 0xb1b0, 0xb18f, 0xb16f, 0xb14e, 0xb12d,
+ 0xb10d, 0xb0ec, 0xb0cb, 0xb0ab, 0xb08a, 0xb06a, 0xb049, 0xb029,
+ 0xb008, 0xafcf, 0xaf8e, 0xaf4d, 0xaf0c, 0xaecb, 0xae8b, 0xae4a,
+ 0xae09, 0xadc8, 0xad88, 0xad47, 0xad06, 0xacc6, 0xac85, 0xac45,
+ 0xac04, 0xab87, 0xab06, 0xaa85, 0xaa05, 0xa984, 0xa903, 0xa883,
+ 0xa802, 0xa703, 0xa602, 0xa502, 0xa401, 0xa201, 0xa001, 0x9c00,
+ 0x0000, 0x1fff, 0x23fe, 0x25fe, 0x27fc, 0x28fd, 0x29fc, 0x2afa,
+ 0x2bf8, 0x2c7b, 0x2cfa, 0x2d78, 0x2df7, 0x2e76, 0x2ef4, 0x2f72,
+ 0x2ff0, 0x3037, 0x3076, 0x30b5, 0x30f4, 0x3132, 0x3171, 0x31b0,
+ 0x31ee, 0x322d, 0x326b, 0x32aa, 0x32e8, 0x3326, 0x3364, 0x33a3,
+ 0x33e1, 0x340f, 0x342e, 0x344d, 0x346c, 0x348b, 0x34aa, 0x34c9,
+ 0x34e8, 0x3506, 0x3525, 0x3544, 0x3563, 0x3581, 0x35a0, 0x35bf,
+ 0x35dd, 0x35fc, 0x361a, 0x3639, 0x3657, 0x3676, 0x3694, 0x36b2,
+ 0x36d1, 0x36ef, 0x370d, 0x372c, 0x374a, 0x3768, 0x3786, 0x37a4,
+ 0x37c3, 0x37e1, 0x37ff, 0x380e, 0x381d, 0x382c, 0x383b, 0x384a,
+ 0x3859, 0x3868, 0x3877, 0x3886, 0x3895, 0x38a4, 0x38b3, 0x38c2,
+ 0x38d0, 0x38df, 0x38ee, 0x38fd, 0x390c, 0x391a, 0x3929, 0x3938,
+ 0x3947, 0x3955, 0x3964, 0x3973, 0x3982, 0x3990, 0x399f, 0x39ae,
+ 0x39bc, 0x39cb, 0x39d9, 0x39e8, 0x39f7, 0x3a05, 0x3a14, 0x3a22,
+ 0x3a31, 0x3a3f, 0x3a4e, 0x3a5c, 0x3a6b, 0x3a79, 0x3a88, 0x3a96,
+ 0x3aa5, 0x3ab3, 0x3ac1, 0x3ad0, 0x3ade, 0x3aed, 0x3afb, 0x3b09,
+ 0x3b18, 0x3b26, 0x3b34, 0x3b42, 0x3b51, 0x3b5f, 0x3b6d, 0x3b7c,
+ 0x3b8a, 0x3b98, 0x3ba6, 0x3bb4, 0x3bc3, 0x3bd1, 0x3bdf, 0x3bed,
+ 0x3bfb, 0x3c05, 0x3c0c, 0x3c13, 0x3c1a, 0x3c21, 0x3c28, 0x3c2f,
+ 0x3c36, 0x3c3d, 0x3c44, 0x3c4b, 0x3c52, 0x3c59, 0x3c60, 0x3c67,
+ 0x3c6e, 0x3c75, 0x3c7c, 0x3c83, 0x3c8a, 0x3c91, 0x3c97, 0x3c9e,
+ 0x3ca5, 0x3cac, 0x3cb3, 0x3cba, 0x3cc1, 0x3cc8, 0x3ccf, 0x3cd6,
+ 0x3cdc, 0x3ce3, 0x3cea, 0x3cf1, 0x3cf8, 0x3cff, 0x3d06, 0x3d0c,
+ 0x3d13, 0x3d1a, 0x3d21, 0x3d28, 0x3d2f, 0x3d35, 0x3d3c, 0x3d43,
+ 0x3d4a, 0x3d51, 0x3d57, 0x3d5e, 0x3d65, 0x3d6c, 0x3d72, 0x3d79,
+ 0x3d80, 0x3d87, 0x3d8d, 0x3d94, 0x3d9b, 0x3da1, 0x3da8, 0x3daf,
+ 0x3db6, 0x3dbc, 0x3dc3, 0x3dca, 0x3dd0, 0x3dd7, 0x3dde, 0x3de4,
+ 0x3deb, 0x3df2, 0x3df8, 0x3dff, 0x3e05, 0x3e0c, 0x3e13, 0x3e19,
+ 0x3e20, 0x3e27, 0x3e2d, 0x3e34, 0x3e3a, 0x3e41, 0x3e47, 0x3e4e,
+ 0x3e55, 0x3e5b, 0x3e62, 0x3e68, 0x3e6f, 0x3e75, 0x3e7c, 0x3e82,
+ 0x3e89, 0x3e8f, 0x3e96, 0x3e9c, 0x3ea3, 0x3ea9, 0x3eb0, 0x3eb6,
+ 0x3ebd, 0x3ec3, 0x3eca, 0x3ed0, 0x3ed7, 0x3edd, 0x3ee4, 0x3eea,
+ 0x3ef1, 0x3ef7, 0x3efe, 0x3f04, 0x3f0a, 0x3f11, 0x3f17, 0x3f1e,
+ 0x3f24, 0x3f2a, 0x3f31, 0x3f37, 0x3f3e, 0x3f44, 0x3f4a, 0x3f51,
+ 0x3f57, 0x3f5d, 0x3f64, 0x3f6a, 0x3f70, 0x3f77, 0x3f7d, 0x3f83,
+ 0x3f8a, 0x3f90, 0x3f96, 0x3f9d, 0x3fa3, 0x3fa9, 0x3fb0, 0x3fb6,
+ 0x3fbc, 0x3fc2, 0x3fc9, 0x3fcf, 0x3fd5, 0x3fdc, 0x3fe2, 0x3fe8,
+ 0x3fee, 0x3ff5, 0x3ffb, 0x4000, 0x4004, 0x4007, 0x400a, 0x400d,
+ 0x4010, 0x4013, 0x4016, 0x4019, 0x401c, 0x4020, 0x4023, 0x4026,
+ 0x4029, 0x402c, 0x402f, 0x4032, 0x4035, 0x4038, 0x403b, 0x403e,
+ 0x4041, 0x4044, 0x4048, 0x404b, 0x404e, 0x4051, 0x4054, 0x4057,
+ 0x405a, 0x405d, 0x4060, 0x4063, 0x4066, 0x4069, 0x406c, 0x406f,
+ 0x4072, 0x4075, 0x4078, 0x407b, 0x407e, 0x4081, 0x4084, 0x4087,
+ 0x408a, 0x408d, 0x4090, 0x4093, 0x4096, 0x4099, 0x409c, 0x409f,
+ 0x40a2, 0x40a5, 0x40a8, 0x40ab, 0x40ae, 0x40b1, 0x40b4, 0x40b7,
+ 0x40ba, 0x40bd, 0x40c0, 0x40c3, 0x40c6, 0x40c9, 0x40cc, 0x40cf,
+ 0x40d2, 0x40d5, 0x40d8, 0x40db, 0x40de, 0x40e1, 0x40e4, 0x40e7,
+ 0x40ea, 0x40ed, 0x40ef, 0x40f2, 0x40f5, 0x40f8, 0x40fb, 0x40fe,
+ 0x4101, 0x4104, 0x4107, 0x410a, 0x410d, 0x4110, 0x4113, 0x4115,
+ 0x4118, 0x411b, 0x411e, 0x4121, 0x4124, 0x4127, 0x412a, 0x412d,
+ 0x4130, 0x4132, 0x4135, 0x4138, 0x413b, 0x413e, 0x4141, 0x4144,
+ 0x4147, 0x414a, 0x414c, 0x414f, 0x4152, 0x4155, 0x4158, 0x415b,
+ 0x415e, 0x4160, 0x4163, 0x4166, 0x4169, 0x416c, 0x416f, 0x4172,
+ 0x4174, 0x4177, 0x417a, 0x417d, 0x4180, 0x4183, 0x4185, 0x4188,
+ 0x418b, 0x418e, 0x4191, 0x4194, 0x4196, 0x4199, 0x419c, 0x419f,
+ 0x41a2, 0x41a5, 0x41a7, 0x41aa, 0x41ad, 0x41b0, 0x41b3, 0x41b5,
+ 0x41b8, 0x41bb, 0x41be, 0x41c1, 0x41c3, 0x41c6, 0x41c9, 0x41cc,
+ 0x41ce, 0x41d1, 0x41d4, 0x41d7, 0x41da, 0x41dc, 0x41df, 0x41e2,
+ 0x41e5, 0x41e7, 0x41ea, 0x41ed, 0x41f0, 0x41f2, 0x41f5, 0x41f8,
+ 0x41fb, 0x41fd, 0x4200, 0x4203, 0x4206, 0x4208, 0x420b, 0x420e,
+ 0x4211, 0x4213, 0x4216, 0x4219, 0x421c, 0x421e, 0x4221, 0x4224,
+ 0x4227, 0x4229, 0x422c, 0x422f, 0x4231, 0x4234, 0x4237, 0x423a,
+ 0x423c, 0x423f, 0x4242, 0x4244, 0x4247, 0x424a, 0x424d, 0x424f,
+ 0x4252, 0x4255, 0x4257, 0x425a, 0x425d, 0x425f, 0x4262, 0x4265,
+ 0x4267, 0x426a, 0x426d, 0x426f, 0x4272, 0x4275, 0x4277, 0x427a,
+ 0x427d, 0x427f, 0x4282, 0x4285, 0x4287, 0x428a, 0x428d, 0x428f,
+ 0x4292, 0x4295, 0x4297, 0x429a, 0x429d, 0x429f, 0x42a2, 0x42a5,
+ 0x42a7, 0x42aa, 0x42ad, 0x42af, 0x42b2, 0x42b4, 0x42b7, 0x42ba,
+ 0x42bc, 0x42bf, 0x42c2, 0x42c4, 0x42c7, 0x42c9, 0x42cc, 0x42cf,
+ 0x42d1, 0x42d4, 0x42d6, 0x42d9, 0x42dc, 0x42de, 0x42e1, 0x42e3,
+ 0x42e6, 0x42e9, 0x42eb, 0x42ee, 0x42f0, 0x42f3, 0x42f6, 0x42f8,
+ 0x42fb, 0x42fd, 0x4300, 0x4303, 0x4305, 0x4308, 0x430a, 0x430d,
+ 0x430f, 0x4312, 0x4315, 0x4317, 0x431a, 0x431c, 0x431f, 0x4321,
+ 0x4324, 0x4327, 0x4329, 0x432c, 0x432e, 0x4331, 0x4333, 0x4336,
+ 0x4338, 0x433b, 0x433e, 0x4340, 0x4343, 0x4345, 0x4348, 0x434a,
+ 0x434d, 0x434f, 0x4352, 0x4354, 0x4357, 0x4359, 0x435c, 0x435e,
+ 0x4361, 0x4363, 0x4366, 0x4369, 0x436b, 0x436e, 0x4370, 0x4373,
+ 0x4375, 0x4378, 0x437a, 0x437d, 0x437f, 0x4382, 0x4384, 0x4387,
+ 0x4389, 0x438c, 0x438e, 0x4391, 0x4393, 0x4396, 0x4398, 0x439b,
+ 0x439d, 0x43a0, 0x43a2, 0x43a5, 0x43a7, 0x43a9, 0x43ac, 0x43ae,
+ 0x43b1, 0x43b3, 0x43b6, 0x43b8, 0x43bb, 0x43bd, 0x43c0, 0x43c2,
+ 0x43c5, 0x43c7, 0x43ca, 0x43cc, 0x43ce, 0x43d1, 0x43d3, 0x43d6,
+ 0x43d8, 0x43db, 0x43dd, 0x43e0, 0x43e2, 0x43e5, 0x43e7, 0x43e9,
+ 0x43ec, 0x43ee, 0x43f1, 0x43f3, 0x43f6, 0x43f8, 0x43fa, 0x43fd,
+ 0x43ff, 0x4401, 0x4402, 0x4403, 0x4404, 0x4406, 0x4407, 0x4408,
+ 0x4409, 0x440b, 0x440c, 0x440d, 0x440e, 0x440f, 0x4411, 0x4412,
+ 0x4413, 0x4414, 0x4415, 0x4417, 0x4418, 0x4419, 0x441a, 0x441b,
+ 0x441d, 0x441e, 0x441f, 0x4420, 0x4421, 0x4423, 0x4424, 0x4425,
+ 0x4426, 0x4427, 0x4428, 0x442a, 0x442b, 0x442c, 0x442d, 0x442e,
+ 0x4430, 0x4431, 0x4432, 0x4433, 0x4434, 0x4436, 0x4437, 0x4438,
+ 0x4439, 0x443a, 0x443b, 0x443d, 0x443e, 0x443f, 0x4440, 0x4441,
+ 0x4442, 0x4444, 0x4445, 0x4446, 0x4447, 0x4448, 0x444a, 0x444b,
+ 0x444c, 0x444d, 0x444e, 0x444f, 0x4451, 0x4452, 0x4453, 0x4454,
+ 0x4455, 0x4456, 0x4458, 0x4459, 0x445a, 0x445b, 0x445c, 0x445d,
+ 0x445e, 0x4460, 0x4461, 0x4462, 0x4463, 0x4464, 0x4465, 0x4467,
+ 0x4468, 0x4469, 0x446a, 0x446b, 0x446c, 0x446d, 0x446f, 0x4470,
+ 0x4471, 0x4472, 0x4473, 0x4474, 0x4476, 0x4477, 0x4478, 0x4479,
+ 0x447a, 0x447b, 0x447c, 0x447e, 0x447f, 0x4480, 0x4481, 0x4482,
+ 0x4483, 0x4484, 0x4485, 0x4487, 0x4488, 0x4489, 0x448a, 0x448b,
+ 0x448c, 0x448d, 0x448f, 0x4490, 0x4491, 0x4492, 0x4493, 0x4494,
+ 0x4495, 0x4496, 0x4498, 0x4499, 0x449a, 0x449b, 0x449c, 0x449d,
+ 0x449e, 0x449f, 0x44a1, 0x44a2, 0x44a3, 0x44a4, 0x44a5, 0x44a6,
+ 0x44a7, 0x44a8, 0x44aa, 0x44ab, 0x44ac, 0x44ad, 0x44ae, 0x44af,
+ 0x44b0, 0x44b1, 0x44b2, 0x44b4, 0x44b5, 0x44b6, 0x44b7, 0x44b8,
+ 0x44b9, 0x44ba, 0x44bb, 0x44bc, 0x44be, 0x44bf, 0x44c0, 0x44c1,
+ 0x44c2, 0x44c3, 0x44c4, 0x44c5, 0x44c6, 0x44c7, 0x44c9, 0x44ca,
+ 0x44cb, 0x44cc, 0x44cd, 0x44ce, 0x44cf, 0x44d0, 0x44d1, 0x44d2,
+ 0x44d4, 0x44d5, 0x44d6, 0x44d7, 0x44d8, 0x44d9, 0x44da, 0x44db,
+ 0x44dc, 0x44dd, 0x44de, 0x44e0, 0x44e1, 0x44e2, 0x44e3, 0x44e4,
+ 0x44e5, 0x44e6, 0x44e7, 0x44e8, 0x44e9, 0x44ea, 0x44eb, 0x44ed,
+ 0x44ee, 0x44ef, 0x44f0, 0x44f1, 0x44f2, 0x44f3, 0x44f4, 0x44f5,
+ 0x44f6, 0x44f7, 0x44f8, 0x44f9, 0x44fb, 0x44fc, 0x44fd, 0x44fe,
+ 0x44ff, 0x4500, 0x4501, 0x4502, 0x4503, 0x4504, 0x4505, 0x4506,
+ 0x4507, 0x4508, 0x450a, 0x450b, 0x450c, 0x450d, 0x450e, 0x450f,
+ 0x4510, 0x4511, 0x4512, 0x4513, 0x4514, 0x4515, 0x4516, 0x4517,
+ 0x4518, 0x4519, 0x451b, 0x451c, 0x451d, 0x451e, 0x451f, 0x4520,
+ 0x4521, 0x4522, 0x4523, 0x4524, 0x4525, 0x4526, 0x4527, 0x4528,
+ 0x4529, 0x452a, 0x452b, 0x452c, 0x452d, 0x452e, 0x4530, 0x4531,
+ 0x4532, 0x4533, 0x4534, 0x4535, 0x4536, 0x4537, 0x4538, 0x4539,
+ 0x453a, 0x453b, 0x453c, 0x453d, 0x453e, 0x453f, 0x4540, 0x4541,
+ 0x4542, 0x4543, 0x4544, 0x4545, 0x4546, 0x4547, 0x4548, 0x454a,
+ 0x454b, 0x454c, 0x454d, 0x454e, 0x454f, 0x4550, 0x4551, 0x4552,
+ 0x4553, 0x4554, 0x4555, 0x4556, 0x4557, 0x4558, 0x4559, 0x455a,
+ 0x455b, 0x455c, 0x455d, 0x455e, 0x455f, 0x4560, 0x4561, 0x4562,
+ 0x4563, 0x4564, 0x4565, 0x4566, 0x4567, 0x4568, 0x4569, 0x456a,
+ 0x456b, 0x456c, 0x456d, 0x456e, 0x456f, 0x4570, 0x4571, 0x4572,
+ 0x4573, 0x4574, 0x4575, 0x4576, 0x4577, 0x4578, 0x4579, 0x457a,
+ 0x457c, 0x457d, 0x457e, 0x457f, 0x4580, 0x4581, 0x4582, 0x4583,
+ 0x4584, 0x4585, 0x4586, 0x4587, 0x4588, 0x4589, 0x458a, 0x458b,
+ 0x458c, 0x458e, 0x4590, 0x4592, 0x4594, 0x4596, 0x4598, 0x459a,
+ 0x459c, 0x459d, 0x459f, 0x45a1, 0x45a3, 0x45a5, 0x45a7, 0x45a9,
+ 0x45ab, 0x45ad, 0x45af, 0x45b1, 0x45b3, 0x45b5, 0x45b7, 0x45b9,
+ 0x45bb, 0x45bd, 0x45bf, 0x45c1, 0x45c3, 0x45c5, 0x45c7, 0x45c9,
+ 0x45cb, 0x45cd, 0x45ce, 0x45d0, 0x45d2, 0x45d4, 0x45d6, 0x45d8,
+ 0x45da, 0x45dc, 0x45de, 0x45e0, 0x45e2, 0x45e4, 0x45e6, 0x45e7,
+ 0x45e9, 0x45eb, 0x45ed, 0x45ef, 0x45f1, 0x45f3, 0x45f5, 0x45f7,
+ 0x45f9, 0x45fb, 0x45fc, 0x45fe, 0x4600, 0x4602, 0x4604, 0x4606,
+ 0x4608, 0x460a, 0x460b, 0x460d, 0x460f, 0x4611, 0x4613, 0x4615,
+ 0x4617, 0x4619, 0x461a, 0x461c, 0x461e, 0x4620, 0x4622, 0x4624,
+ 0x4626, 0x4627, 0x4629, 0x462b, 0x462d, 0x462f, 0x4631, 0x4633,
+ 0x4634, 0x4636, 0x4638, 0x463a, 0x463c, 0x463e, 0x463f, 0x4641,
+ 0x4643, 0x4645, 0x4647, 0x4649, 0x464a, 0x464c, 0x464e, 0x4650,
+ 0x4652, 0x4653, 0x4655, 0x4657, 0x4659, 0x465b, 0x465d, 0x465e,
+ 0x4660, 0x4662, 0x4664, 0x4666, 0x4667, 0x4669, 0x466b, 0x466d,
+ 0x466f, 0x4670, 0x4672, 0x4674, 0x4676, 0x4677, 0x4679, 0x467b,
+ 0x467d, 0x467f, 0x4680, 0x4682, 0x4684, 0x4686, 0x4687, 0x4689,
+ 0x468b, 0x468d, 0x468e, 0x4690, 0x4692, 0x4694, 0x4696, 0x4697,
+ 0x4699, 0x469b, 0x469d, 0x469e, 0x46a0, 0x46a2, 0x46a4, 0x46a5,
+ 0x46a7, 0x46a9, 0x46aa, 0x46ac, 0x46ae, 0x46b0, 0x46b1, 0x46b3,
+ 0x46b5, 0x46b7, 0x46b8, 0x46ba, 0x46bc, 0x46be, 0x46bf, 0x46c1,
+ 0x46c3, 0x46c4, 0x46c6, 0x46c8, 0x46ca, 0x46cb, 0x46cd, 0x46cf,
+ 0x46d0, 0x46d2, 0x46d4, 0x46d6, 0x46d7, 0x46d9, 0x46db, 0x46dc,
+ 0x46de, 0x46e0, 0x46e1, 0x46e3, 0x46e5, 0x46e6, 0x46e8, 0x46ea,
+ 0x46ec, 0x46ed, 0x46ef, 0x46f1, 0x46f2, 0x46f4, 0x46f6, 0x46f7,
+ 0x46f9, 0x46fb, 0x46fc, 0x46fe, 0x4700, 0x4701, 0x4703, 0x4705,
+ 0x4706, 0x4708, 0x470a, 0x470b, 0x470d, 0x470f, 0x4710, 0x4712,
+ 0x4714, 0x4715, 0x4717, 0x4718, 0x471a, 0x471c, 0x471d, 0x471f,
+ 0x4721, 0x4722, 0x4724, 0x4726, 0x4727, 0x4729, 0x472b, 0x472c,
+ 0x472e, 0x472f, 0x4731, 0x4733, 0x4734, 0x4736, 0x4738, 0x4739,
+ 0x473b, 0x473c, 0x473e, 0x4740, 0x4741, 0x4743, 0x4745, 0x4746,
+ 0x4748, 0x4749, 0x474b, 0x474d, 0x474e, 0x4750, 0x4751, 0x4753,
+ 0x4755, 0x4756, 0x4758, 0x4759, 0x475b, 0x475d, 0x475e, 0x4760,
+ 0x4761, 0x4763, 0x4765, 0x4766, 0x4768, 0x4769, 0x476b, 0x476c,
+ 0x476e, 0x4770, 0x4771, 0x4773, 0x4774, 0x4776, 0x4777, 0x4779,
+ 0x477b, 0x477c, 0x477e, 0x477f, 0x4781, 0x4782, 0x4784, 0x4786,
+ 0x4787, 0x4789, 0x478a, 0x478c, 0x478d, 0x478f, 0x4790, 0x4792,
+ 0x4794, 0x4795, 0x4797, 0x4798, 0x479a, 0x479b, 0x479d, 0x479e,
+ 0x47a0, 0x47a2, 0x47a3, 0x47a5, 0x47a6, 0x47a8, 0x47a9, 0x47ab,
+ 0x47ac, 0x47ae, 0x47af, 0x47b1, 0x47b2, 0x47b4, 0x47b5, 0x47b7,
+ 0x47b8, 0x47ba, 0x47bc, 0x47bd, 0x47bf, 0x47c0, 0x47c2, 0x47c3,
+ 0x47c5, 0x47c6, 0x47c8, 0x47c9, 0x47cb, 0x47cc, 0x47ce, 0x47cf,
+ 0x47d1, 0x47d2, 0x47d4, 0x47d5, 0x47d7, 0x47d8, 0x47da, 0x47db,
+ 0x47dd, 0x47de, 0x47e0, 0x47e1, 0x47e3, 0x47e4, 0x47e6, 0x47e7,
+ 0x47e9, 0x47ea, 0x47ec, 0x47ed, 0x47ef, 0x47f0, 0x47f2, 0x47f3,
+ 0x47f5, 0x47f6, 0x47f8, 0x47f9, 0x47fa, 0x47fc, 0x47fd, 0x47ff,
+ 0x4800, 0x4801, 0x4802, 0x4802, 0x4803, 0x4804, 0x4805, 0x4805,
+ 0x4806, 0x4807, 0x4808, 0x4808, 0x4809, 0x480a, 0x480a, 0x480b,
+ 0x480c, 0x480d, 0x480d, 0x480e, 0x480f, 0x4810, 0x4810, 0x4811,
+ 0x4812, 0x4812, 0x4813, 0x4814, 0x4815, 0x4815, 0x4816, 0x4817,
+ 0x4817, 0x4818, 0x4819, 0x481a, 0x481a, 0x481b, 0x481c, 0x481c,
+ 0x481d, 0x481e, 0x481f, 0x481f, 0x4820, 0x4821, 0x4821, 0x4822,
+ 0x4823, 0x4824, 0x4824, 0x4825, 0x4826, 0x4826, 0x4827, 0x4828,
+ 0x4829, 0x4829, 0x482a, 0x482b, 0x482b, 0x482c, 0x482d, 0x482e,
+ 0x482e, 0x482f, 0x4830, 0x4830, 0x4831, 0x4832, 0x4832, 0x4833,
+ 0x4834, 0x4835, 0x4835, 0x4836, 0x4837, 0x4837, 0x4838, 0x4839,
+ 0x4839, 0x483a, 0x483b, 0x483b, 0x483c, 0x483d, 0x483e, 0x483e,
+ 0x483f, 0x4840, 0x4840, 0x4841, 0x4842, 0x4842, 0x4843, 0x4844,
+ 0x4844, 0x4845, 0x4846, 0x4847, 0x4847, 0x4848, 0x4849, 0x4849,
+ 0x484a, 0x484b, 0x484b, 0x484c, 0x484d, 0x484d, 0x484e, 0x484f,
+ 0x484f, 0x4850, 0x4851, 0x4851, 0x4852, 0x4853, 0x4853, 0x4854,
+ 0x4855, 0x4856, 0x4856, 0x4857, 0x4858, 0x4858, 0x4859, 0x485a,
+ 0x485a, 0x485b, 0x485c, 0x485c, 0x485d, 0x485e, 0x485e, 0x485f,
+ 0x4860, 0x4860, 0x4861, 0x4862, 0x4862, 0x4863, 0x4864, 0x4864,
+ 0x4865, 0x4866, 0x4866, 0x4867, 0x4868, 0x4868, 0x4869, 0x486a,
+ 0x486a, 0x486b, 0x486c, 0x486c, 0x486d, 0x486e, 0x486e, 0x486f,
+ 0x4870, 0x4870, 0x4871, 0x4872, 0x4872, 0x4873, 0x4874, 0x4874,
+ 0x4875, 0x4876, 0x4876, 0x4877, 0x4877, 0x4878, 0x4879, 0x4879,
+ 0x487a, 0x487b, 0x487b, 0x487c, 0x487d, 0x487d, 0x487e, 0x487f,
+ 0x487f, 0x4880, 0x4881, 0x4881, 0x4882, 0x4883, 0x4883, 0x4884,
+ 0x4884, 0x4885, 0x4886, 0x4886, 0x4887, 0x4888, 0x4888, 0x4889,
+ 0x488a, 0x488a, 0x488b, 0x488c, 0x488c, 0x488d, 0x488d, 0x488e,
+ 0x488f, 0x488f, 0x4890, 0x4891, 0x4891, 0x4892, 0x4893, 0x4893,
+ 0x4894, 0x4895, 0x4895, 0x4896, 0x4896, 0x4897, 0x4898, 0x4898,
+ 0x4899, 0x489a, 0x489a, 0x489b, 0x489c, 0x489c, 0x489d, 0x489d,
+ 0x489e, 0x489f, 0x489f, 0x48a0, 0x48a1, 0x48a1, 0x48a2, 0x48a2,
+ 0x48a3, 0x48a4, 0x48a4, 0x48a5, 0x48a6, 0x48a6, 0x48a7, 0x48a7,
+ 0x48a8, 0x48a9, 0x48a9, 0x48aa, 0x48ab, 0x48ab, 0x48ac, 0x48ac,
+ 0x48ad, 0x48ae, 0x48ae, 0x48af, 0x48b0, 0x48b0, 0x48b1, 0x48b1,
+ 0x48b2, 0x48b3, 0x48b3, 0x48b4, 0x48b4, 0x48b5, 0x48b6, 0x48b6,
+ 0x48b7, 0x48b8, 0x48b8, 0x48b9, 0x48b9, 0x48ba, 0x48bb, 0x48bb,
+ 0x48bc, 0x48bc, 0x48bd, 0x48be, 0x48be, 0x48bf, 0x48c0, 0x48c0,
+ 0x48c1, 0x48c1, 0x48c2, 0x48c3, 0x48c3, 0x48c4, 0x48c4, 0x48c5,
+ 0x48c6, 0x48c6, 0x48c7, 0x48c7, 0x48c8, 0x48c9, 0x48c9, 0x48ca,
+ 0x48ca, 0x48cb, 0x48cc, 0x48cc, 0x48cd, 0x48cd, 0x48ce, 0x48cf,
+ 0x48cf, 0x48d0, 0x48d0, 0x48d1, 0x48d2, 0x48d2, 0x48d3, 0x48d3,
+ 0x48d4, 0x48d5, 0x48d5, 0x48d6, 0x48d6, 0x48d7, 0x48d8, 0x48d8,
+ 0x48d9, 0x48d9, 0x48da, 0x48db, 0x48db, 0x48dc, 0x48dc, 0x48dd,
+ 0x48de, 0x48de, 0x48df, 0x48df, 0x48e0, 0x48e1, 0x48e1, 0x48e2,
+ 0x48e2, 0x48e3, 0x48e3, 0x48e4, 0x48e5, 0x48e5, 0x48e6, 0x48e6,
+ 0x48e7, 0x48e8, 0x48e8, 0x48e9, 0x48e9, 0x48ea, 0x48eb, 0x48eb,
+ 0x48ec, 0x48ec, 0x48ed, 0x48ed, 0x48ee, 0x48ef, 0x48ef, 0x48f0,
+ 0x48f0, 0x48f1, 0x48f2, 0x48f2, 0x48f3, 0x48f3, 0x48f4, 0x48f4,
+ 0x48f5, 0x48f6, 0x48f6, 0x48f7, 0x48f7, 0x48f8, 0x48f8, 0x48f9,
+ 0x48fa, 0x48fa, 0x48fb, 0x48fb, 0x48fc, 0x48fd, 0x48fd, 0x48fe,
+ 0x48fe, 0x48ff, 0x48ff, 0x4900, 0x4901, 0x4901, 0x4902, 0x4902,
+ 0x4903, 0x4903, 0x4904, 0x4905, 0x4905, 0x4906, 0x4906, 0x4907,
+ 0x4907, 0x4908, 0x4909, 0x4909, 0x490a, 0x490a, 0x490b, 0x490b,
+ 0x490c, 0x490c, 0x490d, 0x490e, 0x490e, 0x490f, 0x490f, 0x4910,
+ 0x4910, 0x4911, 0x4912, 0x4912, 0x4913, 0x4913, 0x4914, 0x4914,
+ 0x4915, 0x4916, 0x4916, 0x4917, 0x4917, 0x4918, 0x4918, 0x4919,
+ 0x4919, 0x491a, 0x491b, 0x491b, 0x491c, 0x491c, 0x491d, 0x491d,
+ 0x491e, 0x491e, 0x491f, 0x4920, 0x4920, 0x4921, 0x4921, 0x4922,
+ 0x4922, 0x4923, 0x4923, 0x4924, 0x4925, 0x4925, 0x4926, 0x4926,
+ 0x4927, 0x4927, 0x4928, 0x4928, 0x4929, 0x492a, 0x492a, 0x492b,
+ 0x492b, 0x492c, 0x492c, 0x492d, 0x492d, 0x492e, 0x492e, 0x492f,
+ 0x4930, 0x4930, 0x4931, 0x4931, 0x4932, 0x4932, 0x4933, 0x4933,
+ 0x4934, 0x4934, 0x4935, 0x4936, 0x4936, 0x4937, 0x4937, 0x4938,
+ 0x4938, 0x4939, 0x4939, 0x493a, 0x493a, 0x493b, 0x493c, 0x493c,
+ 0x493d, 0x493d, 0x493e, 0x493e, 0x493f, 0x493f, 0x4940, 0x4940,
+ 0x4941, 0x4941, 0x4942, 0x4943, 0x4943, 0x4944, 0x4944, 0x4945,
+ 0x4945, 0x4946, 0x4946, 0x4947, 0x4947, 0x4948, 0x4948, 0x4949,
+ 0x4949, 0x494a, 0x494b, 0x494b, 0x494c, 0x494c, 0x494d, 0x494d,
+ 0x494e, 0x494e, 0x494f, 0x494f, 0x4950, 0x4950, 0x4951, 0x4951,
+ 0x4952, 0x4953, 0x4953, 0x4954, 0x4954, 0x4955, 0x4955, 0x4956,
+ 0x4956, 0x4957, 0x4957, 0x4958, 0x4958, 0x4959, 0x4959, 0x495a,
+ 0x495a, 0x495b, 0x495b, 0x495c, 0x495d, 0x495d, 0x495e, 0x495e,
+ 0x495f, 0x495f, 0x4960, 0x4960, 0x4961, 0x4961, 0x4962, 0x4962,
+ 0x4963, 0x4963, 0x4964, 0x4964, 0x4965, 0x4965, 0x4966, 0x4966,
+ 0x4967, 0x4967, 0x4968, 0x4968, 0x4969, 0x496a, 0x496a, 0x496b,
+ 0x496b, 0x496c, 0x496c, 0x496d, 0x496d, 0x496e, 0x496e, 0x496f,
+ 0x496f, 0x4970, 0x4970, 0x4971, 0x4971, 0x4972, 0x4972, 0x4973,
+ 0x4973, 0x4974, 0x4974, 0x4975, 0x4975, 0x4976, 0x4976, 0x4977,
+ 0x4977, 0x4978, 0x4978, 0x4979, 0x4979, 0x497a, 0x497a, 0x497b,
+ 0x497b, 0x497c, 0x497c, 0x497d, 0x497d, 0x497e, 0x497e, 0x497f,
+ 0x497f, 0x4980, 0x4981, 0x4981, 0x4982, 0x4982, 0x4983, 0x4983,
+ 0x4984, 0x4984, 0x4985, 0x4985, 0x4986, 0x4986, 0x4987, 0x4987,
+ 0x4988, 0x4988, 0x4989, 0x4989, 0x498a, 0x498a, 0x498b, 0x498b,
+ 0x498c, 0x498d, 0x498e, 0x498f, 0x4990, 0x4991, 0x4992, 0x4993,
+ 0x4994, 0x4995, 0x4996, 0x4997, 0x4997, 0x4998, 0x4999, 0x499a,
+ 0x499b, 0x499c, 0x499d, 0x499e, 0x499f, 0x49a0, 0x49a1, 0x49a2,
+ 0x49a3, 0x49a4, 0x49a5, 0x49a6, 0x49a7, 0x49a8, 0x49a9, 0x49aa,
+ 0x49ab, 0x49ac, 0x49ad, 0x49ae, 0x49af, 0x49b0, 0x49b1, 0x49b2,
+ 0x49b3, 0x49b4, 0x49b5, 0x49b6, 0x49b7, 0x49b8, 0x49b9, 0x49ba,
+ 0x49ba, 0x49bb, 0x49bc, 0x49bd, 0x49be, 0x49bf, 0x49c0, 0x49c1,
+ 0x49c2, 0x49c3, 0x49c4, 0x49c5, 0x49c6, 0x49c7, 0x49c8, 0x49c9,
+ 0x49ca, 0x49cb, 0x49cc, 0x49cc, 0x49cd, 0x49ce, 0x49cf, 0x49d0,
+ 0x49d1, 0x49d2, 0x49d3, 0x49d4, 0x49d5, 0x49d6, 0x49d7, 0x49d8,
+ 0x49d9, 0x49da, 0x49da, 0x49db, 0x49dc, 0x49dd, 0x49de, 0x49df,
+ 0x49e0, 0x49e1, 0x49e2, 0x49e3, 0x49e4, 0x49e5, 0x49e5, 0x49e6,
+ 0x49e7, 0x49e8, 0x49e9, 0x49ea, 0x49eb, 0x49ec, 0x49ed, 0x49ee,
+ 0x49ef, 0x49f0, 0x49f0, 0x49f1, 0x49f2, 0x49f3, 0x49f4, 0x49f5,
+ 0x49f6, 0x49f7, 0x49f8, 0x49f9, 0x49f9, 0x49fa, 0x49fb, 0x49fc,
+ 0x49fd, 0x49fe, 0x49ff, 0x4a00, 0x4a01, 0x4a02, 0x4a02, 0x4a03,
+ 0x4a04, 0x4a05, 0x4a06, 0x4a07, 0x4a08, 0x4a09, 0x4a09, 0x4a0a,
+ 0x4a0b, 0x4a0c, 0x4a0d, 0x4a0e, 0x4a0f, 0x4a10, 0x4a11, 0x4a11,
+ 0x4a12, 0x4a13, 0x4a14, 0x4a15, 0x4a16, 0x4a17, 0x4a18, 0x4a18,
+ 0x4a19, 0x4a1a, 0x4a1b, 0x4a1c, 0x4a1d, 0x4a1e, 0x4a1f, 0x4a1f,
+ 0x4a20, 0x4a21, 0x4a22, 0x4a23, 0x4a24, 0x4a25, 0x4a25, 0x4a26,
+ 0x4a27, 0x4a28, 0x4a29, 0x4a2a, 0x4a2b, 0x4a2b, 0x4a2c, 0x4a2d,
+ 0x4a2e, 0x4a2f, 0x4a30, 0x4a31, 0x4a31, 0x4a32, 0x4a33, 0x4a34,
+ 0x4a35, 0x4a36, 0x4a36, 0x4a37, 0x4a38, 0x4a39, 0x4a3a, 0x4a3b,
+ 0x4a3c, 0x4a3c, 0x4a3d, 0x4a3e, 0x4a3f, 0x4a40, 0x4a41, 0x4a41,
+ 0x4a42, 0x4a43, 0x4a44, 0x4a45, 0x4a46, 0x4a46, 0x4a47, 0x4a48,
+ 0x4a49, 0x4a4a, 0x4a4b, 0x4a4b, 0x4a4c, 0x4a4d, 0x4a4e, 0x4a4f,
+ 0x4a50, 0x4a50, 0x4a51, 0x4a52, 0x4a53, 0x4a54, 0x4a54, 0x4a55,
+ 0x4a56, 0x4a57, 0x4a58, 0x4a59, 0x4a59, 0x4a5a, 0x4a5b, 0x4a5c,
+ 0x4a5d, 0x4a5d, 0x4a5e, 0x4a5f, 0x4a60, 0x4a61, 0x4a62, 0x4a62,
+ 0x4a63, 0x4a64, 0x4a65, 0x4a66, 0x4a66, 0x4a67, 0x4a68, 0x4a69,
+ 0x4a6a, 0x4a6a, 0x4a6b, 0x4a6c, 0x4a6d, 0x4a6e, 0x4a6e, 0x4a6f,
+ 0x4a70, 0x4a71, 0x4a72, 0x4a72, 0x4a73, 0x4a74, 0x4a75, 0x4a76,
+ 0x4a76, 0x4a77, 0x4a78, 0x4a79, 0x4a7a, 0x4a7a, 0x4a7b, 0x4a7c,
+ 0x4a7d, 0x4a7e, 0x4a7e, 0x4a7f, 0x4a80, 0x4a81, 0x4a82, 0x4a82,
+ 0x4a83, 0x4a84, 0x4a85, 0x4a85, 0x4a86, 0x4a87, 0x4a88, 0x4a89,
+ 0x4a89, 0x4a8a, 0x4a8b, 0x4a8c, 0x4a8c, 0x4a8d, 0x4a8e, 0x4a8f,
+ 0x4a90, 0x4a90, 0x4a91, 0x4a92, 0x4a93, 0x4a93, 0x4a94, 0x4a95,
+ 0x4a96, 0x4a97, 0x4a97, 0x4a98, 0x4a99, 0x4a9a, 0x4a9a, 0x4a9b,
+ 0x4a9c, 0x4a9d, 0x4a9d, 0x4a9e, 0x4a9f, 0x4aa0, 0x4aa1, 0x4aa1,
+ 0x4aa2, 0x4aa3, 0x4aa4, 0x4aa4, 0x4aa5, 0x4aa6, 0x4aa7, 0x4aa7,
+ 0x4aa8, 0x4aa9, 0x4aaa, 0x4aaa, 0x4aab, 0x4aac, 0x4aad, 0x4aad,
+ 0x4aae, 0x4aaf, 0x4ab0, 0x4ab0, 0x4ab1, 0x4ab2, 0x4ab3, 0x4ab3,
+ 0x4ab4, 0x4ab5, 0x4ab6, 0x4ab6, 0x4ab7, 0x4ab8, 0x4ab9, 0x4ab9,
+ 0x4aba, 0x4abb, 0x4abc, 0x4abc, 0x4abd, 0x4abe, 0x4abf, 0x4abf,
+ 0x4ac0, 0x4ac1, 0x4ac2, 0x4ac2, 0x4ac3, 0x4ac4, 0x4ac4, 0x4ac5,
+ 0x4ac6, 0x4ac7, 0x4ac7, 0x4ac8, 0x4ac9, 0x4aca, 0x4aca, 0x4acb,
+ 0x4acc, 0x4acd, 0x4acd, 0x4ace, 0x4acf, 0x4acf, 0x4ad0, 0x4ad1,
+ 0x4ad2, 0x4ad2, 0x4ad3, 0x4ad4, 0x4ad5, 0x4ad5, 0x4ad6, 0x4ad7,
+ 0x4ad7, 0x4ad8, 0x4ad9, 0x4ada, 0x4ada, 0x4adb, 0x4adc, 0x4add,
+ 0x4add, 0x4ade, 0x4adf, 0x4adf, 0x4ae0, 0x4ae1, 0x4ae2, 0x4ae2,
+ 0x4ae3, 0x4ae4, 0x4ae4, 0x4ae5, 0x4ae6, 0x4ae7, 0x4ae7, 0x4ae8,
+ 0x4ae9, 0x4ae9, 0x4aea, 0x4aeb, 0x4aec, 0x4aec, 0x4aed, 0x4aee,
+ 0x4aee, 0x4aef, 0x4af0, 0x4af0, 0x4af1, 0x4af2, 0x4af3, 0x4af3,
+ 0x4af4, 0x4af5, 0x4af5, 0x4af6, 0x4af7, 0x4af7, 0x4af8, 0x4af9,
+ 0x4afa, 0x4afa, 0x4afb, 0x4afc, 0x4afc, 0x4afd, 0x4afe, 0x4afe,
+ 0x4aff, 0x4b00, 0x4b01, 0x4b01, 0x4b02, 0x4b03, 0x4b03, 0x4b04,
+ 0x4b05, 0x4b05, 0x4b06, 0x4b07, 0x4b07, 0x4b08, 0x4b09, 0x4b0a,
+ 0x4b0a, 0x4b0b, 0x4b0c, 0x4b0c, 0x4b0d, 0x4b0e, 0x4b0e, 0x4b0f,
+ 0x4b10, 0x4b10, 0x4b11, 0x4b12, 0x4b12, 0x4b13, 0x4b14, 0x4b15,
+ 0x4b15, 0x4b16, 0x4b17, 0x4b17, 0x4b18, 0x4b19, 0x4b19, 0x4b1a,
+ 0x4b1b, 0x4b1b, 0x4b1c, 0x4b1d, 0x4b1d, 0x4b1e, 0x4b1f, 0x4b1f,
+ 0x4b20, 0x4b21, 0x4b21, 0x4b22, 0x4b23, 0x4b23, 0x4b24, 0x4b25,
+ 0x4b25, 0x4b26, 0x4b27, 0x4b27, 0x4b28, 0x4b29, 0x4b29, 0x4b2a,
+ 0x4b2b, 0x4b2b, 0x4b2c, 0x4b2d, 0x4b2d, 0x4b2e, 0x4b2f, 0x4b2f,
+ 0x4b30, 0x4b31, 0x4b31, 0x4b32, 0x4b33, 0x4b33, 0x4b34, 0x4b35,
+ 0x4b35, 0x4b36, 0x4b37, 0x4b37, 0x4b38, 0x4b39, 0x4b39, 0x4b3a,
+ 0x4b3b, 0x4b3b, 0x4b3c, 0x4b3d, 0x4b3d, 0x4b3e, 0x4b3f, 0x4b3f,
+ 0x4b40, 0x4b41, 0x4b41, 0x4b42, 0x4b42, 0x4b43, 0x4b44, 0x4b44,
+ 0x4b45, 0x4b46, 0x4b46, 0x4b47, 0x4b48, 0x4b48, 0x4b49, 0x4b4a,
+ 0x4b4a, 0x4b4b, 0x4b4c, 0x4b4c, 0x4b4d, 0x4b4d, 0x4b4e, 0x4b4f,
+ 0x4b4f, 0x4b50, 0x4b51, 0x4b51, 0x4b52, 0x4b53, 0x4b53, 0x4b54,
+ 0x4b55, 0x4b55, 0x4b56, 0x4b56, 0x4b57, 0x4b58, 0x4b58, 0x4b59,
+ 0x4b5a, 0x4b5a, 0x4b5b, 0x4b5c, 0x4b5c, 0x4b5d, 0x4b5d, 0x4b5e,
+ 0x4b5f, 0x4b5f, 0x4b60, 0x4b61, 0x4b61, 0x4b62, 0x4b63, 0x4b63,
+ 0x4b64, 0x4b64, 0x4b65, 0x4b66, 0x4b66, 0x4b67, 0x4b68, 0x4b68,
+ 0x4b69, 0x4b69, 0x4b6a, 0x4b6b, 0x4b6b, 0x4b6c, 0x4b6d, 0x4b6d,
+ 0x4b6e, 0x4b6e, 0x4b6f, 0x4b70, 0x4b70, 0x4b71, 0x4b72, 0x4b72,
+ 0x4b73, 0x4b73, 0x4b74, 0x4b75, 0x4b75, 0x4b76, 0x4b77, 0x4b77,
+ 0x4b78, 0x4b78, 0x4b79, 0x4b7a, 0x4b7a, 0x4b7b, 0x4b7b, 0x4b7c,
+ 0x4b7d, 0x4b7d, 0x4b7e, 0x4b7f, 0x4b7f, 0x4b80, 0x4b80, 0x4b81,
+ 0x4b82, 0x4b82, 0x4b83, 0x4b83, 0x4b84, 0x4b85, 0x4b85, 0x4b86,
+ 0x4b87, 0x4b87, 0x4b88, 0x4b88, 0x4b89, 0x4b8a, 0x4b8a, 0x4b8b,
+ 0x4b8b, 0x4b8c, 0x4b8d, 0x4b8d, 0x4b8e, 0x4b8e, 0x4b8f, 0x4b90,
+ 0x4b90, 0x4b91, 0x4b91, 0x4b92, 0x4b93, 0x4b93, 0x4b94, 0x4b94,
+ 0x4b95, 0x4b96, 0x4b96, 0x4b97, 0x4b97, 0x4b98, 0x4b99, 0x4b99,
+ 0x4b9a, 0x4b9a, 0x4b9b, 0x4b9c, 0x4b9c, 0x4b9d, 0x4b9d, 0x4b9e,
+ 0x4b9f, 0x4b9f, 0x4ba0, 0x4ba0, 0x4ba1, 0x4ba2, 0x4ba2, 0x4ba3,
+ 0x4ba3, 0x4ba4, 0x4ba5, 0x4ba5, 0x4ba6, 0x4ba6, 0x4ba7, 0x4ba8,
+ 0x4ba8, 0x4ba9, 0x4ba9, 0x4baa, 0x4baa, 0x4bab, 0x4bac, 0x4bac,
+ 0x4bad, 0x4bad, 0x4bae, 0x4baf, 0x4baf, 0x4bb0, 0x4bb0, 0x4bb1,
+ 0x4bb1, 0x4bb2, 0x4bb3, 0x4bb3, 0x4bb4, 0x4bb4, 0x4bb5, 0x4bb6,
+ 0x4bb6, 0x4bb7, 0x4bb7, 0x4bb8, 0x4bb8, 0x4bb9, 0x4bba, 0x4bba,
+ 0x4bbb, 0x4bbb, 0x4bbc, 0x4bbd, 0x4bbd, 0x4bbe, 0x4bbe, 0x4bbf,
+ 0x4bbf, 0x4bc0, 0x4bc1, 0x4bc1, 0x4bc2, 0x4bc2, 0x4bc3, 0x4bc3,
+ 0x4bc4, 0x4bc5, 0x4bc5, 0x4bc6, 0x4bc6, 0x4bc7, 0x4bc7, 0x4bc8,
+ 0x4bc9, 0x4bc9, 0x4bca, 0x4bca, 0x4bcb, 0x4bcb, 0x4bcc, 0x4bcd,
+ 0x4bcd, 0x4bce, 0x4bce, 0x4bcf, 0x4bcf, 0x4bd0, 0x4bd1, 0x4bd1,
+ 0x4bd2, 0x4bd2, 0x4bd3, 0x4bd3, 0x4bd4, 0x4bd5, 0x4bd5, 0x4bd6,
+ 0x4bd6, 0x4bd7, 0x4bd7, 0x4bd8, 0x4bd8, 0x4bd9, 0x4bda, 0x4bda,
+ 0x4bdb, 0x4bdb, 0x4bdc, 0x4bdc, 0x4bdd, 0x4bde, 0x4bde, 0x4bdf,
+ 0x4bdf, 0x4be0, 0x4be0, 0x4be1, 0x4be1, 0x4be2, 0x4be3, 0x4be3,
+ 0x4be4, 0x4be4, 0x4be5, 0x4be5, 0x4be6, 0x4be6, 0x4be7, 0x4be8,
+ 0x4be8, 0x4be9, 0x4be9, 0x4bea, 0x4bea, 0x4beb, 0x4beb, 0x4bec,
+ 0x4bed, 0x4bed, 0x4bee, 0x4bee, 0x4bef, 0x4bef, 0x4bf0, 0x4bf0,
+ 0x4bf1, 0x4bf1, 0x4bf2, 0x4bf3, 0x4bf3, 0x4bf4, 0x4bf4, 0x4bf5,
+ 0x4bf5, 0x4bf6, 0x4bf6, 0x4bf7, 0x4bf8, 0x4bf8, 0x4bf9, 0x4bf9,
+ 0x4bfa, 0x4bfa, 0x4bfb, 0x4bfb, 0x4bfc, 0x4bfc, 0x4bfd, 0x4bfe,
+ 0x4bfe, 0x4bff, 0x4bff, 0x4c00, 0x4c00, 0x4c00, 0x4c01, 0x4c01,
+ 0x4c01, 0x4c01, 0x4c02, 0x4c02, 0x4c02, 0x4c03, 0x4c03, 0x4c03,
+ 0x4c03, 0x4c04, 0x4c04, 0x4c04, 0x4c04, 0x4c05, 0x4c05, 0x4c05,
+ 0x4c05, 0x4c06, 0x4c06, 0x4c06, 0x4c07, 0x4c07, 0x4c07, 0x4c07,
+ 0x4c08, 0x4c08, 0x4c08, 0x4c08, 0x4c09, 0x4c09, 0x4c09, 0x4c09,
+ 0x4c0a, 0x4c0a, 0x4c0a, 0x4c0b, 0x4c0b, 0x4c0b, 0x4c0b, 0x4c0c,
+ 0x4c0c, 0x4c0c, 0x4c0c, 0x4c0d, 0x4c0d, 0x4c0d, 0x4c0d, 0x4c0e,
+ 0x4c0e, 0x4c0e, 0x4c0f, 0x4c0f, 0x4c0f, 0x4c0f, 0x4c10, 0x4c10,
+ 0x4c10, 0x4c10, 0x4c11, 0x4c11, 0x4c11, 0x4c11, 0x4c12, 0x4c12,
+ 0x4c12, 0x4c12, 0x4c13, 0x4c13, 0x4c13, 0x4c13, 0x4c14, 0x4c14,
+ 0x4c14, 0x4c15, 0x4c15, 0x4c15, 0x4c15, 0x4c16, 0x4c16, 0x4c16,
+ 0x4c16, 0x4c17, 0x4c17, 0x4c17, 0x4c17, 0x4c18, 0x4c18, 0x4c18,
+ 0x4c18, 0x4c19, 0x4c19, 0x4c19, 0x4c19, 0x4c1a, 0x4c1a, 0x4c1a,
+ 0x4c1a, 0x4c1b, 0x4c1b, 0x4c1b, 0x4c1c, 0x4c1c, 0x4c1c, 0x4c1c,
+ 0x4c1d, 0x4c1d, 0x4c1d, 0x4c1d, 0x4c1e, 0x4c1e, 0x4c1e, 0x4c1e,
+ 0x4c1f, 0x4c1f, 0x4c1f, 0x4c1f, 0x4c20, 0x4c20, 0x4c20, 0x4c20,
+ 0x4c21, 0x4c21, 0x4c21, 0x4c21, 0x4c22, 0x4c22, 0x4c22, 0x4c22,
+ 0x4c23, 0x4c23, 0x4c23, 0x4c23, 0x4c24, 0x4c24, 0x4c24, 0x4c24,
+ 0x4c25, 0x4c25, 0x4c25, 0x4c25, 0x4c26, 0x4c26, 0x4c26, 0x4c26,
+ 0x4c27, 0x4c27, 0x4c27, 0x4c27, 0x4c28, 0x4c28, 0x4c28, 0x4c28,
+ 0x4c29, 0x4c29, 0x4c2a, 0x4c2a, 0x4c2b, 0x4c2b, 0x4c2c, 0x4c2c,
+ 0x4c2d, 0x4c2d, 0x4c2e, 0x4c2e, 0x4c2f, 0x4c2f, 0x4c30, 0x4c30,
+ 0x4c31, 0x4c31, 0x4c32, 0x4c32, 0x4c33, 0x4c33, 0x4c34, 0x4c34,
+ 0x4c35, 0x4c35, 0x4c36, 0x4c36, 0x4c36, 0x4c37, 0x4c37, 0x4c38,
+ 0x4c38, 0x4c39, 0x4c39, 0x4c3a, 0x4c3a, 0x4c3b, 0x4c3b, 0x4c3c,
+ 0x4c3c, 0x4c3d, 0x4c3d, 0x4c3e, 0x4c3e, 0x4c3f, 0x4c3f, 0x4c40,
+ 0x4c40, 0x4c41, 0x4c41, 0x4c42, 0x4c42, 0x4c43, 0x4c43, 0x4c43,
+ 0x4c44, 0x4c44, 0x4c45, 0x4c45, 0x4c46, 0x4c46, 0x4c47, 0x4c47,
+ 0x4c48, 0x4c48, 0x4c49, 0x4c49, 0x4c4a, 0x4c4a, 0x4c4b, 0x4c4b,
+ 0x4c4b, 0x4c4c, 0x4c4c, 0x4c4d, 0x4c4d, 0x4c4e, 0x4c4e, 0x4c4f,
+ 0x4c4f, 0x4c50, 0x4c50, 0x4c51, 0x4c51, 0x4c52, 0x4c52, 0x4c52,
+ 0x4c53, 0x4c53, 0x4c54, 0x4c54, 0x4c55, 0x4c55, 0x4c56, 0x4c56,
+ 0x4c57, 0x4c57, 0x4c57, 0x4c58, 0x4c58, 0x4c59, 0x4c59, 0x4c5a,
+ 0x4c5a, 0x4c5b, 0x4c5b, 0x4c5c, 0x4c5c, 0x4c5c, 0x4c5d, 0x4c5d,
+ 0x4c5e, 0x4c5e, 0x4c5f, 0x4c5f, 0x4c60, 0x4c60, 0x4c61, 0x4c61,
+ 0x4c61, 0x4c62, 0x4c62, 0x4c63, 0x4c63, 0x4c64, 0x4c64, 0x4c65,
+ 0x4c65, 0x4c65, 0x4c66, 0x4c66, 0x4c67, 0x4c67, 0x4c68, 0x4c68,
+ 0x4c69, 0x4c69, 0x4c69, 0x4c6a, 0x4c6a, 0x4c6b, 0x4c6b, 0x4c6c,
+ 0x4c6c, 0x4c6c, 0x4c6d, 0x4c6d, 0x4c6e, 0x4c6e, 0x4c6f, 0x4c6f,
+ 0x4c70, 0x4c70, 0x4c70, 0x4c71, 0x4c71, 0x4c72, 0x4c72, 0x4c73,
+ 0x4c73, 0x4c73, 0x4c74, 0x4c74, 0x4c75, 0x4c75, 0x4c76, 0x4c76,
+ 0x4c76, 0x4c77, 0x4c77, 0x4c78, 0x4c78, 0x4c79, 0x4c79, 0x4c79,
+ 0x4c7a, 0x4c7a, 0x4c7b, 0x4c7b, 0x4c7c, 0x4c7c, 0x4c7c, 0x4c7d,
+ 0x4c7d, 0x4c7e, 0x4c7e, 0x4c7f, 0x4c7f, 0x4c7f, 0x4c80, 0x4c80,
+ 0x4c81, 0x4c81, 0x4c82, 0x4c82, 0x4c82, 0x4c83, 0x4c83, 0x4c84,
+ 0x4c84, 0x4c84, 0x4c85, 0x4c85, 0x4c86, 0x4c86, 0x4c87, 0x4c87,
+ 0x4c87, 0x4c88, 0x4c88, 0x4c89, 0x4c89, 0x4c89, 0x4c8a, 0x4c8a,
+ 0x4c8b, 0x4c8b, 0x4c8b, 0x4c8c, 0x4c8c, 0x4c8d, 0x4c8d, 0x4c8e,
+ 0x4c8e, 0x4c8e, 0x4c8f, 0x4c8f, 0x4c90, 0x4c90, 0x4c90, 0x4c91,
+ 0x4c91, 0x4c92, 0x4c92, 0x4c92, 0x4c93, 0x4c93, 0x4c94, 0x4c94,
+ 0x4c94, 0x4c95, 0x4c95, 0x4c96, 0x4c96, 0x4c97, 0x4c97, 0x4c97,
+ 0x4c98, 0x4c98, 0x4c99, 0x4c99, 0x4c99, 0x4c9a, 0x4c9a, 0x4c9b,
+ 0x4c9b, 0x4c9b, 0x4c9c, 0x4c9c, 0x4c9d, 0x4c9d, 0x4c9d, 0x4c9e,
+ 0x4c9e, 0x4c9f, 0x4c9f, 0x4c9f, 0x4ca0, 0x4ca0, 0x4ca0, 0x4ca1,
+ 0x4ca1, 0x4ca2, 0x4ca2, 0x4ca2, 0x4ca3, 0x4ca3, 0x4ca4, 0x4ca4,
+ 0x4ca4, 0x4ca5, 0x4ca5, 0x4ca6, 0x4ca6, 0x4ca6, 0x4ca7, 0x4ca7,
+ 0x4ca8, 0x4ca8, 0x4ca8, 0x4ca9, 0x4ca9, 0x4caa, 0x4caa, 0x4caa,
+ 0x4cab, 0x4cab, 0x4cab, 0x4cac, 0x4cac, 0x4cad, 0x4cad, 0x4cad,
+ 0x4cae, 0x4cae, 0x4caf, 0x4caf, 0x4caf, 0x4cb0, 0x4cb0, 0x4cb0,
+ 0x4cb1, 0x4cb1, 0x4cb2, 0x4cb2, 0x4cb2, 0x4cb3, 0x4cb3, 0x4cb4,
+ 0x4cb4, 0x4cb4, 0x4cb5, 0x4cb5, 0x4cb5, 0x4cb6, 0x4cb6, 0x4cb7,
+ 0x4cb7, 0x4cb7, 0x4cb8, 0x4cb8, 0x4cb8, 0x4cb9, 0x4cb9, 0x4cba,
+ 0x4cba, 0x4cba, 0x4cbb, 0x4cbb, 0x4cbb, 0x4cbc, 0x4cbc, 0x4cbd,
+ 0x4cbd, 0x4cbd, 0x4cbe, 0x4cbe, 0x4cbe, 0x4cbf, 0x4cbf, 0x4cc0,
+ 0x4cc0, 0x4cc0, 0x4cc1, 0x4cc1, 0x4cc1, 0x4cc2, 0x4cc2, 0x4cc3,
+ 0x4cc3, 0x4cc3, 0x4cc4, 0x4cc4, 0x4cc4, 0x4cc5, 0x4cc5, 0x4cc6,
+ 0x4cc6, 0x4cc6, 0x4cc7, 0x4cc7, 0x4cc7, 0x4cc8, 0x4cc8, 0x4cc8,
+ 0x4cc9, 0x4cc9, 0x4cca, 0x4cca, 0x4cca, 0x4ccb, 0x4ccb, 0x4ccb,
+ 0x4ccc, 0x4ccc, 0x4ccc, 0x4ccd, 0x4ccd, 0x4cce, 0x4cce, 0x4cce,
+ 0x4ccf, 0x4ccf, 0x4ccf, 0x4cd0, 0x4cd0, 0x4cd0, 0x4cd1, 0x4cd1,
+ 0x4cd2, 0x4cd2, 0x4cd2, 0x4cd3, 0x4cd3, 0x4cd3, 0x4cd4, 0x4cd4,
+ 0x4cd4, 0x4cd5, 0x4cd5, 0x4cd5, 0x4cd6, 0x4cd6, 0x4cd7, 0x4cd7,
+ 0x4cd7, 0x4cd8, 0x4cd8, 0x4cd8, 0x4cd9, 0x4cd9, 0x4cd9, 0x4cda,
+ 0x4cda, 0x4cda, 0x4cdb, 0x4cdb, 0x4cdb, 0x4cdc, 0x4cdc, 0x4cdd,
+ 0x4cdd, 0x4cdd, 0x4cde, 0x4cde, 0x4cde, 0x4cdf, 0x4cdf, 0x4cdf,
+ 0x4ce0, 0x4ce0, 0x4ce0, 0x4ce1, 0x4ce1, 0x4ce1, 0x4ce2, 0x4ce2,
+ 0x4ce2, 0x4ce3, 0x4ce3, 0x4ce4, 0x4ce4, 0x4ce4, 0x4ce5, 0x4ce5,
+ 0x4ce5, 0x4ce6, 0x4ce6, 0x4ce6, 0x4ce7, 0x4ce7, 0x4ce7, 0x4ce8,
+ 0x4ce8, 0x4ce8, 0x4ce9, 0x4ce9, 0x4ce9, 0x4cea, 0x4cea, 0x4cea,
+ 0x4ceb, 0x4ceb, 0x4ceb, 0x4cec, 0x4cec, 0x4cec, 0x4ced, 0x4ced,
+ 0x4ced, 0x4cee, 0x4cee, 0x4cef, 0x4cef, 0x4cef, 0x4cf0, 0x4cf0,
+ 0x4cf0, 0x4cf1, 0x4cf1, 0x4cf1, 0x4cf2, 0x4cf2, 0x4cf2, 0x4cf3,
+ 0x4cf3, 0x4cf3, 0x4cf4, 0x4cf4, 0x4cf4, 0x4cf5, 0x4cf5, 0x4cf5,
+ 0x4cf6, 0x4cf6, 0x4cf6, 0x4cf7, 0x4cf7, 0x4cf7, 0x4cf8, 0x4cf8,
+ 0x4cf8, 0x4cf9, 0x4cf9, 0x4cf9, 0x4cfa, 0x4cfa, 0x4cfa, 0x4cfb,
+ 0x4cfb, 0x4cfb, 0x4cfc, 0x4cfc, 0x4cfc, 0x4cfd, 0x4cfd, 0x4cfd,
+ 0x4cfe, 0x4cfe, 0x4cfe, 0x4cff, 0x4cff, 0x4cff, 0x4d00, 0x4d00,
+ 0x4d00, 0x4d01, 0x4d01, 0x4d01, 0x4d02, 0x4d02, 0x4d02, 0x4d03,
+ 0x4d03, 0x4d03, 0x4d03, 0x4d04, 0x4d04, 0x4d04, 0x4d05, 0x4d05,
+ 0x4d05, 0x4d06, 0x4d06, 0x4d06, 0x4d07, 0x4d07, 0x4d07, 0x4d08,
+ 0x4d08, 0x4d08, 0x4d09, 0x4d09, 0x4d09, 0x4d0a, 0x4d0a, 0x4d0a,
+ 0x4d0b, 0x4d0b, 0x4d0b, 0x4d0c, 0x4d0c, 0x4d0c, 0x4d0d, 0x4d0d,
+ 0x4d0d, 0x4d0d, 0x4d0e, 0x4d0e, 0x4d0e, 0x4d0f, 0x4d0f, 0x4d0f,
+ 0x4d10, 0x4d10, 0x4d10, 0x4d11, 0x4d11, 0x4d11, 0x4d12, 0x4d12,
+ 0x4d12, 0x4d13, 0x4d13, 0x4d13, 0x4d14, 0x4d14, 0x4d14, 0x4d14,
+ 0x4d15, 0x4d15, 0x4d15, 0x4d16, 0x4d16, 0x4d16, 0x4d17, 0x4d17,
+ 0x4d17, 0x4d18, 0x4d18, 0x4d18, 0x4d19, 0x4d19, 0x4d19, 0x4d1a,
+ 0x4d1a, 0x4d1a, 0x4d1a, 0x4d1b, 0x4d1b, 0x4d1b, 0x4d1c, 0x4d1c,
+ 0x4d1c, 0x4d1d, 0x4d1d, 0x4d1d, 0x4d1e, 0x4d1e, 0x4d1e, 0x4d1e,
+ 0x4d1f, 0x4d1f, 0x4d1f, 0x4d20, 0x4d20, 0x4d20, 0x4d21, 0x4d21,
+ 0x4d21, 0x4d22, 0x4d22, 0x4d22, 0x4d22, 0x4d23, 0x4d23, 0x4d23,
+ 0x4d24, 0x4d24, 0x4d24, 0x4d25, 0x4d25, 0x4d25, 0x4d26, 0x4d26,
+ 0x4d26, 0x4d26, 0x4d27, 0x4d27, 0x4d27, 0x4d28, 0x4d28, 0x4d28,
+ 0x4d29, 0x4d29, 0x4d29, 0x4d29, 0x4d2a, 0x4d2a, 0x4d2a, 0x4d2b,
+ 0x4d2b, 0x4d2b, 0x4d2c, 0x4d2c, 0x4d2c, 0x4d2d, 0x4d2d, 0x4d2d,
+ 0x4d2d, 0x4d2e, 0x4d2e, 0x4d2e, 0x4d2f, 0x4d2f, 0x4d2f, 0x4d30,
+ 0x4d30, 0x4d30, 0x4d30, 0x4d31, 0x4d31, 0x4d31, 0x4d32, 0x4d32,
+ 0x4d32, 0x4d32, 0x4d33, 0x4d33, 0x4d33, 0x4d34, 0x4d34, 0x4d34,
+ 0x4d35, 0x4d35, 0x4d35, 0x4d35, 0x4d36, 0x4d36, 0x4d36, 0x4d37,
+ 0x4d37, 0x4d37, 0x4d38, 0x4d38, 0x4d38, 0x4d38, 0x4d39, 0x4d39,
+ 0x4d39, 0x4d3a, 0x4d3a, 0x4d3a, 0x4d3a, 0x4d3b, 0x4d3b, 0x4d3b,
+ 0x4d3c, 0x4d3c, 0x4d3c, 0x4d3d, 0x4d3d, 0x4d3d, 0x4d3d, 0x4d3e,
+ 0x4d3e, 0x4d3e, 0x4d3f, 0x4d3f, 0x4d3f, 0x4d3f, 0x4d40, 0x4d40,
+ 0x4d40, 0x4d41, 0x4d41, 0x4d41, 0x4d41, 0x4d42, 0x4d42, 0x4d42,
+ 0x4d43, 0x4d43, 0x4d43, 0x4d43, 0x4d44, 0x4d44, 0x4d44, 0x4d45,
+ 0x4d45, 0x4d45, 0x4d45, 0x4d46, 0x4d46, 0x4d46, 0x4d47, 0x4d47,
+ 0x4d47, 0x4d47, 0x4d48, 0x4d48, 0x4d48, 0x4d49, 0x4d49, 0x4d49,
+ 0x4d49, 0x4d4a, 0x4d4a, 0x4d4a, 0x4d4b, 0x4d4b, 0x4d4b, 0x4d4b,
+ 0x4d4c, 0x4d4c, 0x4d4c, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4e,
+ 0x4d4e, 0x4d4e, 0x4d4f, 0x4d4f, 0x4d4f, 0x4d4f, 0x4d50, 0x4d50,
+ 0x4d50, 0x4d51, 0x4d51, 0x4d51, 0x4d51, 0x4d52, 0x4d52, 0x4d52,
+ 0x4d53, 0x4d53, 0x4d53, 0x4d53, 0x4d54, 0x4d54, 0x4d54, 0x4d54,
+ 0x4d55, 0x4d55, 0x4d55, 0x4d56, 0x4d56, 0x4d56, 0x4d56, 0x4d57,
+ 0x4d57, 0x4d57, 0x4d58, 0x4d58, 0x4d58, 0x4d58, 0x4d59, 0x4d59,
+ 0x4d59, 0x4d59, 0x4d5a, 0x4d5a, 0x4d5a, 0x4d5b, 0x4d5b, 0x4d5b,
+ 0x4d5b, 0x4d5c, 0x4d5c, 0x4d5c, 0x4d5c, 0x4d5d, 0x4d5d, 0x4d5d,
+ 0x4d5e, 0x4d5e, 0x4d5e, 0x4d5e, 0x4d5f, 0x4d5f, 0x4d5f, 0x4d5f,
+ 0x4d60, 0x4d60, 0x4d60, 0x4d61, 0x4d61, 0x4d61, 0x4d61, 0x4d62,
+ 0x4d62, 0x4d62, 0x4d62, 0x4d63, 0x4d63, 0x4d63, 0x4d64, 0x4d64,
+ 0x4d64, 0x4d64, 0x4d65, 0x4d65, 0x4d65, 0x4d65, 0x4d66, 0x4d66,
+ 0x4d66, 0x4d67, 0x4d67, 0x4d67, 0x4d67, 0x4d68, 0x4d68, 0x4d68,
+ 0x4d68, 0x4d69, 0x4d69, 0x4d69, 0x4d69, 0x4d6a, 0x4d6a, 0x4d6a,
+ 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6b, 0x4d6c, 0x4d6c, 0x4d6c, 0x4d6c,
+ 0x4d6d, 0x4d6d, 0x4d6d, 0x4d6d, 0x4d6e, 0x4d6e, 0x4d6e, 0x4d6f,
+ 0x4d6f, 0x4d6f, 0x4d6f, 0x4d70, 0x4d70, 0x4d70, 0x4d70, 0x4d71,
+ 0x4d71, 0x4d71, 0x4d71, 0x4d72, 0x4d72, 0x4d72, 0x4d72, 0x4d73,
+ 0x4d73, 0x4d73, 0x4d74, 0x4d74, 0x4d74, 0x4d74, 0x4d75, 0x4d75,
+ 0x4d75, 0x4d75, 0x4d76, 0x4d76, 0x4d76, 0x4d76, 0x4d77, 0x4d77,
+ 0x4d77, 0x4d77, 0x4d78, 0x4d78, 0x4d78, 0x4d78, 0x4d79, 0x4d79,
+ 0x4d79, 0x4d7a, 0x4d7a, 0x4d7a, 0x4d7a, 0x4d7b, 0x4d7b, 0x4d7b,
+ 0x4d7b, 0x4d7c, 0x4d7c, 0x4d7c, 0x4d7c, 0x4d7d, 0x4d7d, 0x4d7d,
+ 0x4d7d, 0x4d7e, 0x4d7e, 0x4d7e, 0x4d7e, 0x4d7f, 0x4d7f, 0x4d7f,
+ 0x4d7f, 0x4d80, 0x4d80, 0x4d80, 0x4d80, 0x4d81, 0x4d81, 0x4d81,
+ 0x4d81, 0x4d82, 0x4d82, 0x4d82, 0x4d82, 0x4d83, 0x4d83, 0x4d83,
+ 0x4d84, 0x4d84, 0x4d84, 0x4d84, 0x4d85, 0x4d85, 0x4d85, 0x4d85,
+ 0x4d86, 0x4d86, 0x4d86, 0x4d86, 0x4d87, 0x4d87, 0x4d87, 0x4d87,
+ 0x4d88, 0x4d88, 0x4d88, 0x4d88, 0x4d89, 0x4d89, 0x4d89, 0x4d89,
+ 0x4d8a, 0x4d8a, 0x4d8a, 0x4d8a, 0x4d8b, 0x4d8b, 0x4d8b, 0x4d8b,
+ 0x4d8c, 0x4d8c, 0x4d8d, 0x4d8d, 0x4d8e, 0x4d8e, 0x4d8f, 0x4d8f,
+ 0x4d90, 0x4d90, 0x4d91, 0x4d91, 0x4d92, 0x4d92, 0x4d93, 0x4d93,
+ 0x4d94, 0x4d94, 0x4d94, 0x4d95, 0x4d95, 0x4d96, 0x4d96, 0x4d97,
+ 0x4d97, 0x4d98, 0x4d98, 0x4d99, 0x4d99, 0x4d9a, 0x4d9a, 0x4d9b,
+ 0x4d9b, 0x4d9c, 0x4d9c, 0x4d9d, 0x4d9d, 0x4d9e, 0x4d9e, 0x4d9f,
+ 0x4d9f, 0x4da0, 0x4da0, 0x4da1, 0x4da1, 0x4da2, 0x4da2, 0x4da3,
+ 0x4da3, 0x4da3, 0x4da4, 0x4da4, 0x4da5, 0x4da5, 0x4da6, 0x4da6,
+ 0x4da7, 0x4da7, 0x4da8, 0x4da8, 0x4da9, 0x4da9, 0x4daa, 0x4daa,
+ 0x4dab, 0x4dab, 0x4dac, 0x4dac, 0x4dac, 0x4dad, 0x4dad, 0x4dae,
+ 0x4dae, 0x4daf, 0x4daf, 0x4db0, 0x4db0, 0x4db1, 0x4db1, 0x4db2,
+ 0x4db2, 0x4db3, 0x4db3, 0x4db3, 0x4db4, 0x4db4, 0x4db5, 0x4db5,
+ 0x4db6, 0x4db6, 0x4db7, 0x4db7, 0x4db8, 0x4db8, 0x4db9, 0x4db9,
+ 0x4db9, 0x4dba, 0x4dba, 0x4dbb, 0x4dbb, 0x4dbc, 0x4dbc, 0x4dbd,
+ 0x4dbd, 0x4dbe, 0x4dbe, 0x4dbe, 0x4dbf, 0x4dbf, 0x4dc0, 0x4dc0,
+ 0x4dc1, 0x4dc1, 0x4dc2, 0x4dc2, 0x4dc3, 0x4dc3, 0x4dc3, 0x4dc4,
+ 0x4dc4, 0x4dc5, 0x4dc5, 0x4dc6, 0x4dc6, 0x4dc7, 0x4dc7, 0x4dc7,
+ 0x4dc8, 0x4dc8, 0x4dc9, 0x4dc9, 0x4dca, 0x4dca, 0x4dcb, 0x4dcb,
+ 0x4dcb, 0x4dcc, 0x4dcc, 0x4dcd, 0x4dcd, 0x4dce, 0x4dce, 0x4dce,
+ 0x4dcf, 0x4dcf, 0x4dd0, 0x4dd0, 0x4dd1, 0x4dd1, 0x4dd2, 0x4dd2,
+ 0x4dd2, 0x4dd3, 0x4dd3, 0x4dd4, 0x4dd4, 0x4dd5, 0x4dd5, 0x4dd5,
+ 0x4dd6, 0x4dd6, 0x4dd7, 0x4dd7, 0x4dd8, 0x4dd8, 0x4dd8, 0x4dd9,
+ 0x4dd9, 0x4dda, 0x4dda, 0x4ddb, 0x4ddb, 0x4ddb, 0x4ddc, 0x4ddc,
+ 0x4ddd, 0x4ddd, 0x4dde, 0x4dde, 0x4dde, 0x4ddf, 0x4ddf, 0x4de0,
+ 0x4de0, 0x4de1, 0x4de1, 0x4de1, 0x4de2, 0x4de2, 0x4de3, 0x4de3,
+ 0x4de4, 0x4de4, 0x4de4, 0x4de5, 0x4de5, 0x4de6, 0x4de6, 0x4de6,
+ 0x4de7, 0x4de7, 0x4de8, 0x4de8, 0x4de9, 0x4de9, 0x4de9, 0x4dea,
+ 0x4dea, 0x4deb, 0x4deb, 0x4deb, 0x4dec, 0x4dec, 0x4ded, 0x4ded,
+ 0x4dee, 0x4dee, 0x4dee, 0x4def, 0x4def, 0x4df0, 0x4df0, 0x4df0,
+ 0x4df1, 0x4df1, 0x4df2, 0x4df2, 0x4df2, 0x4df3, 0x4df3, 0x4df4,
+ 0x4df4, 0x4df5, 0x4df5, 0x4df5, 0x4df6, 0x4df6, 0x4df7, 0x4df7,
+ 0x4df7, 0x4df8, 0x4df8, 0x4df9, 0x4df9, 0x4df9, 0x4dfa, 0x4dfa,
+ 0x4dfb, 0x4dfb, 0x4dfb, 0x4dfc, 0x4dfc, 0x4dfd, 0x4dfd, 0x4dfd,
+ 0x4dfe, 0x4dfe, 0x4dff, 0x4dff, 0x4dff, 0x4e00, 0x4e00, 0x4e01,
+ 0x4e01, 0x4e01, 0x4e02, 0x4e02, 0x4e03, 0x4e03, 0x4e03, 0x4e04,
+ 0x4e04, 0x4e05, 0x4e05, 0x4e05, 0x4e06, 0x4e06, 0x4e07, 0x4e07,
+ 0x4e07, 0x4e08, 0x4e08, 0x4e09, 0x4e09, 0x4e09, 0x4e0a, 0x4e0a,
+ 0x4e0a, 0x4e0b, 0x4e0b, 0x4e0c, 0x4e0c, 0x4e0c, 0x4e0d, 0x4e0d,
+ 0x4e0e, 0x4e0e, 0x4e0e, 0x4e0f, 0x4e0f, 0x4e10, 0x4e10, 0x4e10,
+ 0x4e11, 0x4e11, 0x4e11, 0x4e12, 0x4e12, 0x4e13, 0x4e13, 0x4e13,
+ 0x4e14, 0x4e14, 0x4e15, 0x4e15, 0x4e15, 0x4e16, 0x4e16, 0x4e16,
+ 0x4e17, 0x4e17, 0x4e18, 0x4e18, 0x4e18, 0x4e19, 0x4e19, 0x4e19,
+ 0x4e1a, 0x4e1a, 0x4e1b, 0x4e1b, 0x4e1b, 0x4e1c, 0x4e1c, 0x4e1c,
+ 0x4e1d, 0x4e1d, 0x4e1e, 0x4e1e, 0x4e1e, 0x4e1f, 0x4e1f, 0x4e1f,
+ 0x4e20, 0x4e20, 0x4e21, 0x4e21, 0x4e21, 0x4e22, 0x4e22, 0x4e22,
+ 0x4e23, 0x4e23, 0x4e24, 0x4e24, 0x4e24, 0x4e25, 0x4e25, 0x4e25,
+ 0x4e26, 0x4e26, 0x4e27, 0x4e27, 0x4e27, 0x4e28, 0x4e28, 0x4e28,
+ 0x4e29, 0x4e29, 0x4e29, 0x4e2a, 0x4e2a, 0x4e2b, 0x4e2b, 0x4e2b,
+ 0x4e2c, 0x4e2c, 0x4e2c, 0x4e2d, 0x4e2d, 0x4e2e, 0x4e2e, 0x4e2e,
+ 0x4e2f, 0x4e2f, 0x4e2f, 0x4e30, 0x4e30, 0x4e30, 0x4e31, 0x4e31,
+ 0x4e32, 0x4e32, 0x4e32, 0x4e33, 0x4e33, 0x4e33, 0x4e34, 0x4e34,
+ 0x4e34, 0x4e35, 0x4e35, 0x4e35, 0x4e36, 0x4e36, 0x4e37, 0x4e37,
+ 0x4e37, 0x4e38, 0x4e38, 0x4e38, 0x4e39, 0x4e39, 0x4e39, 0x4e3a,
+ 0x4e3a, 0x4e3a, 0x4e3b, 0x4e3b, 0x4e3c, 0x4e3c, 0x4e3c, 0x4e3d,
+ 0x4e3d, 0x4e3d, 0x4e3e, 0x4e3e, 0x4e3e, 0x4e3f, 0x4e3f, 0x4e3f,
+ 0x4e40, 0x4e40, 0x4e40, 0x4e41, 0x4e41, 0x4e42, 0x4e42, 0x4e42,
+ 0x4e43, 0x4e43, 0x4e43, 0x4e44, 0x4e44, 0x4e44, 0x4e45, 0x4e45,
+ 0x4e45, 0x4e46, 0x4e46, 0x4e46, 0x4e47, 0x4e47, 0x4e47, 0x4e48,
+ 0x4e48, 0x4e48, 0x4e49, 0x4e49, 0x4e4a, 0x4e4a, 0x4e4a, 0x4e4b,
+ 0x4e4b, 0x4e4b, 0x4e4c, 0x4e4c, 0x4e4c, 0x4e4d, 0x4e4d, 0x4e4d,
+ 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4f, 0x4e4f, 0x4e4f, 0x4e50, 0x4e50,
+ 0x4e50, 0x4e51, 0x4e51, 0x4e51, 0x4e52, 0x4e52, 0x4e52, 0x4e53,
+ 0x4e53, 0x4e53, 0x4e54, 0x4e54, 0x4e54, 0x4e55, 0x4e55, 0x4e55,
+ 0x4e56, 0x4e56, 0x4e56, 0x4e57, 0x4e57, 0x4e57, 0x4e58, 0x4e58,
+ 0x4e58, 0x4e59, 0x4e59, 0x4e59, 0x4e5a, 0x4e5a, 0x4e5a, 0x4e5b,
+ 0x4e5b, 0x4e5b, 0x4e5c, 0x4e5c, 0x4e5c, 0x4e5d, 0x4e5d, 0x4e5d,
+ 0x4e5e, 0x4e5e, 0x4e5e, 0x4e5f, 0x4e5f, 0x4e5f, 0x4e60, 0x4e60,
+ 0x4e60, 0x4e61, 0x4e61, 0x4e61, 0x4e62, 0x4e62, 0x4e62, 0x4e63,
+ 0x4e63, 0x4e63, 0x4e64, 0x4e64, 0x4e64, 0x4e65, 0x4e65, 0x4e65,
+ 0x4e66, 0x4e66, 0x4e66, 0x4e67, 0x4e67, 0x4e67, 0x4e68, 0x4e68,
+ 0x4e68, 0x4e69, 0x4e69, 0x4e69, 0x4e6a, 0x4e6a, 0x4e6a, 0x4e6b,
+ 0x4e6b, 0x4e6b, 0x4e6c, 0x4e6c, 0x4e6c, 0x4e6d, 0x4e6d, 0x4e6d,
+ 0x4e6d, 0x4e6e, 0x4e6e, 0x4e6e, 0x4e6f, 0x4e6f, 0x4e6f, 0x4e70,
+ 0x4e70, 0x4e70, 0x4e71, 0x4e71, 0x4e71, 0x4e72, 0x4e72, 0x4e72,
+ 0x4e73, 0x4e73, 0x4e73, 0x4e74, 0x4e74, 0x4e74, 0x4e75, 0x4e75,
+ 0x4e75, 0x4e75, 0x4e76, 0x4e76, 0x4e76, 0x4e77, 0x4e77, 0x4e77,
+ 0x4e78, 0x4e78, 0x4e78, 0x4e79, 0x4e79, 0x4e79, 0x4e7a, 0x4e7a,
+ 0x4e7a, 0x4e7b, 0x4e7b, 0x4e7b, 0x4e7b, 0x4e7c, 0x4e7c, 0x4e7c,
+ 0x4e7d, 0x4e7d, 0x4e7d, 0x4e7e, 0x4e7e, 0x4e7e, 0x4e7f, 0x4e7f,
+ 0x4e7f, 0x4e80, 0x4e80, 0x4e80, 0x4e80, 0x4e81, 0x4e81, 0x4e81,
+ 0x4e82, 0x4e82, 0x4e82, 0x4e83, 0x4e83, 0x4e83, 0x4e84, 0x4e84,
+ 0x4e84, 0x4e84, 0x4e85, 0x4e85, 0x4e85, 0x4e86, 0x4e86, 0x4e86,
+ 0x4e87, 0x4e87, 0x4e87, 0x4e88, 0x4e88, 0x4e88, 0x4e88, 0x4e89,
+ 0x4e89, 0x4e89, 0x4e8a, 0x4e8a, 0x4e8a, 0x4e8b, 0x4e8b, 0x4e8b,
+ 0x4e8b, 0x4e8c, 0x4e8c, 0x4e8c, 0x4e8d, 0x4e8d, 0x4e8d, 0x4e8e,
+ 0x4e8e, 0x4e8e, 0x4e8f, 0x4e8f, 0x4e8f, 0x4e8f, 0x4e90, 0x4e90,
+ 0x4e90, 0x4e91, 0x4e91, 0x4e91, 0x4e92, 0x4e92, 0x4e92, 0x4e92,
+ 0x4e93, 0x4e93, 0x4e93, 0x4e94, 0x4e94, 0x4e94, 0x4e94, 0x4e95,
+ 0x4e95, 0x4e95, 0x4e96, 0x4e96, 0x4e96, 0x4e97, 0x4e97, 0x4e97,
+ 0x4e97, 0x4e98, 0x4e98, 0x4e98, 0x4e99, 0x4e99, 0x4e99, 0x4e9a,
+ 0x4e9a, 0x4e9a, 0x4e9a, 0x4e9b, 0x4e9b, 0x4e9b, 0x4e9c, 0x4e9c,
+ 0x4e9c, 0x4e9c, 0x4e9d, 0x4e9d, 0x4e9d, 0x4e9e, 0x4e9e, 0x4e9e,
+ 0x4e9f, 0x4e9f, 0x4e9f, 0x4e9f, 0x4ea0, 0x4ea0, 0x4ea0, 0x4ea1,
+ 0x4ea1, 0x4ea1, 0x4ea1, 0x4ea2, 0x4ea2, 0x4ea2, 0x4ea3, 0x4ea3,
+ 0x4ea3, 0x4ea3, 0x4ea4, 0x4ea4, 0x4ea4, 0x4ea5, 0x4ea5, 0x4ea5,
+ 0x4ea5, 0x4ea6, 0x4ea6, 0x4ea6, 0x4ea7, 0x4ea7, 0x4ea7, 0x4ea8,
+ 0x4ea8, 0x4ea8, 0x4ea8, 0x4ea9, 0x4ea9, 0x4ea9, 0x4eaa, 0x4eaa,
+ 0x4eaa, 0x4eaa, 0x4eab, 0x4eab, 0x4eab, 0x4eac, 0x4eac, 0x4eac,
+ 0x4eac, 0x4ead, 0x4ead, 0x4ead, 0x4eae, 0x4eae, 0x4eae, 0x4eae,
+ 0x4eaf, 0x4eaf, 0x4eaf, 0x4eaf, 0x4eb0, 0x4eb0, 0x4eb0, 0x4eb1,
+ 0x4eb1, 0x4eb1, 0x4eb1, 0x4eb2, 0x4eb2, 0x4eb2, 0x4eb3, 0x4eb3,
+ 0x4eb3, 0x4eb3, 0x4eb4, 0x4eb4, 0x4eb4, 0x4eb5, 0x4eb5, 0x4eb5,
+ 0x4eb5, 0x4eb6, 0x4eb6, 0x4eb6, 0x4eb7, 0x4eb7, 0x4eb7, 0x4eb7,
+ 0x4eb8, 0x4eb8, 0x4eb8, 0x4eb8, 0x4eb9, 0x4eb9, 0x4eb9, 0x4eba,
+ 0x4eba, 0x4eba, 0x4eba, 0x4ebb, 0x4ebb, 0x4ebb, 0x4ebc, 0x4ebc,
+ 0x4ebc, 0x4ebc, 0x4ebd, 0x4ebd, 0x4ebd, 0x4ebd, 0x4ebe, 0x4ebe,
+ 0x4ebe, 0x4ebf, 0x4ebf, 0x4ebf, 0x4ebf, 0x4ec0, 0x4ec0, 0x4ec0,
+ 0x4ec0, 0x4ec1, 0x4ec1, 0x4ec1, 0x4ec2, 0x4ec2, 0x4ec2, 0x4ec2,
+ 0x4ec3, 0x4ec3, 0x4ec3, 0x4ec3, 0x4ec4, 0x4ec4, 0x4ec4, 0x4ec5,
+ 0x4ec5, 0x4ec5, 0x4ec5, 0x4ec6, 0x4ec6, 0x4ec6, 0x4ec6, 0x4ec7,
+ 0x4ec7, 0x4ec7, 0x4ec8, 0x4ec8, 0x4ec8, 0x4ec8, 0x4ec9, 0x4ec9,
+ 0x4ec9, 0x4ec9, 0x4eca, 0x4eca, 0x4eca, 0x4eca, 0x4ecb, 0x4ecb,
+ 0x4ecb, 0x4ecc, 0x4ecc, 0x4ecc, 0x4ecc, 0x4ecd, 0x4ecd, 0x4ecd,
+ 0x4ecd, 0x4ece, 0x4ece, 0x4ece, 0x4ece, 0x4ecf, 0x4ecf, 0x4ecf,
+ 0x4ed0, 0x4ed0, 0x4ed0, 0x4ed0, 0x4ed1, 0x4ed1, 0x4ed1, 0x4ed1,
+ 0x4ed2, 0x4ed2, 0x4ed2, 0x4ed2, 0x4ed3, 0x4ed3, 0x4ed3, 0x4ed4,
+ 0x4ed4, 0x4ed4, 0x4ed4, 0x4ed5, 0x4ed5, 0x4ed5, 0x4ed5, 0x4ed6,
+ 0x4ed6, 0x4ed6, 0x4ed6, 0x4ed7, 0x4ed7, 0x4ed7, 0x4ed7, 0x4ed8,
+ 0x4ed8, 0x4ed8, 0x4ed8, 0x4ed9, 0x4ed9, 0x4ed9, 0x4eda, 0x4eda,
+ 0x4eda, 0x4eda, 0x4edb, 0x4edb, 0x4edb, 0x4edb, 0x4edc, 0x4edc,
+ 0x4edc, 0x4edc, 0x4edd, 0x4edd, 0x4edd, 0x4edd, 0x4ede, 0x4ede,
+ 0x4ede, 0x4ede, 0x4edf, 0x4edf, 0x4edf, 0x4edf, 0x4ee0, 0x4ee0,
+ 0x4ee0, 0x4ee1, 0x4ee1, 0x4ee1, 0x4ee1, 0x4ee2, 0x4ee2, 0x4ee2,
+ 0x4ee2, 0x4ee3, 0x4ee3, 0x4ee3, 0x4ee3, 0x4ee4, 0x4ee4, 0x4ee4,
+ 0x4ee4, 0x4ee5, 0x4ee5, 0x4ee5, 0x4ee5, 0x4ee6, 0x4ee6, 0x4ee6,
+ 0x4ee6, 0x4ee7, 0x4ee7, 0x4ee7, 0x4ee7, 0x4ee8, 0x4ee8, 0x4ee8,
+ 0x4ee8, 0x4ee9, 0x4ee9, 0x4ee9, 0x4ee9, 0x4eea, 0x4eea, 0x4eea,
+ 0x4eea, 0x4eeb, 0x4eeb, 0x4eeb, 0x4eeb, 0x4eec, 0x4eec, 0x4eec,
+ 0x4eec, 0x4eed, 0x4eed, 0x4eed, 0x4eed, 0x4eee, 0x4eee, 0x4eee,
+ 0x4eee, 0x4eef, 0x4eef, 0x4ef0, 0x4ef0, 0x4ef1, 0x4ef1, 0x4ef2,
+ 0x4ef2, 0x4ef3, 0x4ef3, 0x4ef4, 0x4ef4, 0x4ef5, 0x4ef5, 0x4ef6,
+ 0x4ef6, 0x4ef7, 0x4ef7, 0x4ef8, 0x4ef8, 0x4ef9, 0x4ef9, 0x4efa,
+ 0x4efa, 0x4efb, 0x4efb, 0x4efc, 0x4efc, 0x4efd, 0x4efd, 0x4efe,
+ 0x4efe, 0x4eff, 0x4eff, 0x4f00, 0x4f00, 0x4f01, 0x4f01, 0x4f02,
+ 0x4f02, 0x4f03, 0x4f03, 0x4f04, 0x4f04, 0x4f04, 0x4f05, 0x4f05,
+ 0x4f06, 0x4f06, 0x4f07, 0x4f07, 0x4f08, 0x4f08, 0x4f09, 0x4f09,
+ 0x4f0a, 0x4f0a, 0x4f0b, 0x4f0b, 0x4f0c, 0x4f0c, 0x4f0d, 0x4f0d,
+ 0x4f0d, 0x4f0e, 0x4f0e, 0x4f0f, 0x4f0f, 0x4f10, 0x4f10, 0x4f11,
+ 0x4f11, 0x4f12, 0x4f12, 0x4f13, 0x4f13, 0x4f14, 0x4f14, 0x4f15,
+ 0x4f15, 0x4f15, 0x4f16, 0x4f16, 0x4f17, 0x4f17, 0x4f18, 0x4f18,
+ 0x4f19, 0x4f19, 0x4f1a, 0x4f1a, 0x4f1b, 0x4f1b, 0x4f1b, 0x4f1c,
+ 0x4f1c, 0x4f1d, 0x4f1d, 0x4f1e, 0x4f1e, 0x4f1f, 0x4f1f, 0x4f20,
+ 0x4f20, 0x4f20, 0x4f21, 0x4f21, 0x4f22, 0x4f22, 0x4f23, 0x4f23,
+ 0x4f24, 0x4f24, 0x4f25, 0x4f25, 0x4f25, 0x4f26, 0x4f26, 0x4f27,
+ 0x4f27, 0x4f28, 0x4f28, 0x4f29, 0x4f29, 0x4f29, 0x4f2a, 0x4f2a,
+ 0x4f2b, 0x4f2b, 0x4f2c, 0x4f2c, 0x4f2d, 0x4f2d, 0x4f2d, 0x4f2e,
+ 0x4f2e, 0x4f2f, 0x4f2f, 0x4f30, 0x4f30, 0x4f31, 0x4f31, 0x4f31,
+ 0x4f32, 0x4f32, 0x4f33, 0x4f33, 0x4f34, 0x4f34, 0x4f34, 0x4f35,
+ 0x4f35, 0x4f36, 0x4f36, 0x4f37, 0x4f37, 0x4f37, 0x4f38, 0x4f38,
+ 0x4f39, 0x4f39, 0x4f3a, 0x4f3a, 0x4f3b, 0x4f3b, 0x4f3b, 0x4f3c,
+ 0x4f3c, 0x4f3d, 0x4f3d, 0x4f3e, 0x4f3e, 0x4f3e, 0x4f3f, 0x4f3f,
+ 0x4f40, 0x4f40, 0x4f41, 0x4f41, 0x4f41, 0x4f42, 0x4f42, 0x4f43,
+ 0x4f43, 0x4f43, 0x4f44, 0x4f44, 0x4f45, 0x4f45, 0x4f46, 0x4f46,
+ 0x4f46, 0x4f47, 0x4f47, 0x4f48, 0x4f48, 0x4f49, 0x4f49, 0x4f49,
+ 0x4f4a, 0x4f4a, 0x4f4b, 0x4f4b, 0x4f4b, 0x4f4c, 0x4f4c, 0x4f4d,
+ 0x4f4d, 0x4f4e, 0x4f4e, 0x4f4e, 0x4f4f, 0x4f4f, 0x4f50, 0x4f50,
+ 0x4f50, 0x4f51, 0x4f51, 0x4f52, 0x4f52, 0x4f53, 0x4f53, 0x4f53,
+ 0x4f54, 0x4f54, 0x4f55, 0x4f55, 0x4f55, 0x4f56, 0x4f56, 0x4f57,
+ 0x4f57, 0x4f57, 0x4f58, 0x4f58, 0x4f59, 0x4f59, 0x4f59, 0x4f5a,
+ 0x4f5a, 0x4f5b, 0x4f5b, 0x4f5b, 0x4f5c, 0x4f5c, 0x4f5d, 0x4f5d,
+ 0x4f5d, 0x4f5e, 0x4f5e, 0x4f5f, 0x4f5f, 0x4f60, 0x4f60, 0x4f60,
+ 0x4f61, 0x4f61, 0x4f62, 0x4f62, 0x4f62, 0x4f63, 0x4f63, 0x4f63,
+ 0x4f64, 0x4f64, 0x4f65, 0x4f65, 0x4f65, 0x4f66, 0x4f66, 0x4f67,
+ 0x4f67, 0x4f67, 0x4f68, 0x4f68, 0x4f69, 0x4f69, 0x4f69, 0x4f6a,
+ 0x4f6a, 0x4f6b, 0x4f6b, 0x4f6b, 0x4f6c, 0x4f6c, 0x4f6d, 0x4f6d,
+ 0x4f6d, 0x4f6e, 0x4f6e, 0x4f6f, 0x4f6f, 0x4f6f, 0x4f70, 0x4f70,
+ 0x4f70, 0x4f71, 0x4f71, 0x4f72, 0x4f72, 0x4f72, 0x4f73, 0x4f73,
+ 0x4f74, 0x4f74, 0x4f74, 0x4f75, 0x4f75, 0x4f75, 0x4f76, 0x4f76,
+ 0x4f77, 0x4f77, 0x4f77, 0x4f78, 0x4f78, 0x4f79, 0x4f79, 0x4f79,
+ 0x4f7a, 0x4f7a, 0x4f7a, 0x4f7b, 0x4f7b, 0x4f7c, 0x4f7c, 0x4f7c,
+ 0x4f7d, 0x4f7d, 0x4f7d, 0x4f7e, 0x4f7e, 0x4f7f, 0x4f7f, 0x4f7f,
+ 0x4f80, 0x4f80, 0x4f80, 0x4f81, 0x4f81, 0x4f82, 0x4f82, 0x4f82,
+ 0x4f83, 0x4f83, 0x4f83, 0x4f84, 0x4f84, 0x4f85, 0x4f85, 0x4f85,
+ 0x4f86, 0x4f86, 0x4f86, 0x4f87, 0x4f87, 0x4f88, 0x4f88, 0x4f88,
+ 0x4f89, 0x4f89, 0x4f89, 0x4f8a, 0x4f8a, 0x4f8b, 0x4f8b, 0x4f8b,
+ 0x4f8c, 0x4f8c, 0x4f8c, 0x4f8d, 0x4f8d, 0x4f8d, 0x4f8e, 0x4f8e,
+ 0x4f8f, 0x4f8f, 0x4f8f, 0x4f90, 0x4f90, 0x4f90, 0x4f91, 0x4f91,
+ 0x4f92, 0x4f92, 0x4f92, 0x4f93, 0x4f93, 0x4f93, 0x4f94, 0x4f94,
+ 0x4f94, 0x4f95, 0x4f95, 0x4f95, 0x4f96, 0x4f96, 0x4f97, 0x4f97,
+ 0x4f97, 0x4f98, 0x4f98, 0x4f98, 0x4f99, 0x4f99, 0x4f99, 0x4f9a,
+ 0x4f9a, 0x4f9b, 0x4f9b, 0x4f9b, 0x4f9c, 0x4f9c, 0x4f9c, 0x4f9d,
+ 0x4f9d, 0x4f9d, 0x4f9e, 0x4f9e, 0x4f9e, 0x4f9f, 0x4f9f, 0x4f9f,
+ 0x4fa0, 0x4fa0, 0x4fa1, 0x4fa1, 0x4fa1, 0x4fa2, 0x4fa2, 0x4fa2,
+ 0x4fa3, 0x4fa3, 0x4fa3, 0x4fa4, 0x4fa4, 0x4fa4, 0x4fa5, 0x4fa5,
+ 0x4fa5, 0x4fa6, 0x4fa6, 0x4fa7, 0x4fa7, 0x4fa7, 0x4fa8, 0x4fa8,
+ 0x4fa8, 0x4fa9, 0x4fa9, 0x4fa9, 0x4faa, 0x4faa, 0x4faa, 0x4fab,
+ 0x4fab, 0x4fab, 0x4fac, 0x4fac, 0x4fac, 0x4fad, 0x4fad, 0x4fad,
+ 0x4fae, 0x4fae, 0x4fae, 0x4faf, 0x4faf, 0x4fb0, 0x4fb0, 0x4fb0,
+ 0x4fb1, 0x4fb1, 0x4fb1, 0x4fb2, 0x4fb2, 0x4fb2, 0x4fb3, 0x4fb3,
+ 0x4fb3, 0x4fb4, 0x4fb4, 0x4fb4, 0x4fb5, 0x4fb5, 0x4fb5, 0x4fb6,
+ 0x4fb6, 0x4fb6, 0x4fb7, 0x4fb7, 0x4fb7, 0x4fb8, 0x4fb8, 0x4fb8,
+ 0x4fb9, 0x4fb9, 0x4fb9, 0x4fba, 0x4fba, 0x4fba, 0x4fbb, 0x4fbb,
+ 0x4fbb, 0x4fbc, 0x4fbc, 0x4fbc, 0x4fbd, 0x4fbd, 0x4fbd, 0x4fbe,
+ 0x4fbe, 0x4fbe, 0x4fbf, 0x4fbf, 0x4fbf, 0x4fc0, 0x4fc0, 0x4fc0,
+ 0x4fc1, 0x4fc1, 0x4fc1, 0x4fc2, 0x4fc2, 0x4fc2, 0x4fc3, 0x4fc3,
+ 0x4fc3, 0x4fc4, 0x4fc4, 0x4fc4, 0x4fc5, 0x4fc5, 0x4fc5, 0x4fc6,
+ 0x4fc6, 0x4fc6, 0x4fc7, 0x4fc7, 0x4fc7, 0x4fc8, 0x4fc8, 0x4fc8,
+ 0x4fc9, 0x4fc9, 0x4fc9, 0x4fca, 0x4fca, 0x4fca, 0x4fcb, 0x4fcb,
+ 0x4fcb, 0x4fcc, 0x4fcc, 0x4fcc, 0x4fcd, 0x4fcd, 0x4fcd, 0x4fcd,
+ 0x4fce, 0x4fce, 0x4fce, 0x4fcf, 0x4fcf, 0x4fcf, 0x4fd0, 0x4fd0,
+ 0x4fd0, 0x4fd1, 0x4fd1, 0x4fd1, 0x4fd2, 0x4fd2, 0x4fd2, 0x4fd3,
+ 0x4fd3, 0x4fd3, 0x4fd4, 0x4fd4, 0x4fd4, 0x4fd5, 0x4fd5, 0x4fd5,
+ 0x4fd6, 0x4fd6, 0x4fd6, 0x4fd6, 0x4fd7, 0x4fd7, 0x4fd7, 0x4fd8,
+ 0x4fd8, 0x4fd8, 0x4fd9, 0x4fd9, 0x4fd9, 0x4fda, 0x4fda, 0x4fda,
+ 0x4fdb, 0x4fdb, 0x4fdb, 0x4fdc, 0x4fdc, 0x4fdc, 0x4fdc, 0x4fdd,
+ 0x4fdd, 0x4fdd, 0x4fde, 0x4fde, 0x4fde, 0x4fdf, 0x4fdf, 0x4fdf,
+ 0x4fe0, 0x4fe0, 0x4fe0, 0x4fe1, 0x4fe1, 0x4fe1, 0x4fe1, 0x4fe2,
+ 0x4fe2, 0x4fe2, 0x4fe3, 0x4fe3, 0x4fe3, 0x4fe4, 0x4fe4, 0x4fe4,
+ 0x4fe5, 0x4fe5, 0x4fe5, 0x4fe5, 0x4fe6, 0x4fe6, 0x4fe6, 0x4fe7,
+ 0x4fe7, 0x4fe7, 0x4fe8, 0x4fe8, 0x4fe8, 0x4fe9, 0x4fe9, 0x4fe9,
+ 0x4fe9, 0x4fea, 0x4fea, 0x4fea, 0x4feb, 0x4feb, 0x4feb, 0x4fec,
+ 0x4fec, 0x4fec, 0x4fed, 0x4fed, 0x4fed, 0x4fed, 0x4fee, 0x4fee,
+ 0x4fee, 0x4fef, 0x4fef, 0x4fef, 0x4ff0, 0x4ff0, 0x4ff0, 0x4ff0,
+ 0x4ff1, 0x4ff1, 0x4ff1, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff3, 0x4ff3,
+ 0x4ff3, 0x4ff3, 0x4ff4, 0x4ff4, 0x4ff4, 0x4ff5, 0x4ff5, 0x4ff5,
+ 0x4ff6, 0x4ff6, 0x4ff6, 0x4ff6, 0x4ff7, 0x4ff7, 0x4ff7, 0x4ff8,
+ 0x4ff8, 0x4ff8, 0x4ff9, 0x4ff9, 0x4ff9, 0x4ff9, 0x4ffa, 0x4ffa,
+ 0x4ffa, 0x4ffb, 0x4ffb, 0x4ffb, 0x4ffc, 0x4ffc, 0x4ffc, 0x4ffc,
+ 0x4ffd, 0x4ffd, 0x4ffd, 0x4ffe, 0x4ffe, 0x4ffe, 0x4ffe, 0x4fff,
+ 0x4fff, 0x4fff, 0x5000, 0x5000, 0x5000, 0x5000, 0x5000, 0x5001,
+ 0x5001, 0x5001, 0x5001, 0x5001, 0x5001, 0x5001, 0x5002, 0x5002,
+ 0x5002, 0x5002, 0x5002, 0x5002, 0x5002, 0x5003, 0x5003, 0x5003,
+ 0x5003, 0x5003, 0x5003, 0x5003, 0x5004, 0x5004, 0x5004, 0x5004,
+ 0x5004, 0x5004, 0x5004, 0x5005, 0x5005, 0x5005, 0x5005, 0x5005,
+ 0x5005, 0x5005, 0x5006, 0x5006, 0x5006, 0x5006, 0x5006, 0x5006,
+ 0x5006, 0x5007, 0x5007, 0x5007, 0x5007, 0x5007, 0x5007, 0x5007,
+ 0x5008, 0x5008, 0x5008, 0x5008, 0x5008, 0x5008, 0x5008, 0x5009,
+ 0x5009, 0x5009, 0x5009, 0x5009, 0x5009, 0x5009, 0x500a, 0x500a,
+ 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b,
+ 0x500b, 0x500b, 0x500b, 0x500b, 0x500c, 0x500c, 0x500c, 0x500c,
+ 0x500c, 0x500c, 0x500c, 0x500d, 0x500d, 0x500d, 0x500d, 0x500d,
+ 0x500d, 0x500d, 0x500e, 0x500e, 0x500e, 0x500e, 0x500e, 0x500e,
+ 0x500e, 0x500f, 0x500f, 0x500f, 0x500f, 0x500f, 0x500f, 0x500f,
+ 0x500f, 0x5010, 0x5010, 0x5010, 0x5010, 0x5010, 0x5010, 0x5010,
+ 0x5011, 0x5011, 0x5011, 0x5011, 0x5011, 0x5011, 0x5011, 0x5012,
+ 0x5012, 0x5012, 0x5012, 0x5012, 0x5012, 0x5012, 0x5012, 0x5013,
+ 0x5013, 0x5013, 0x5013, 0x5013, 0x5013, 0x5013, 0x5014, 0x5014,
+ 0x5014, 0x5014, 0x5014, 0x5014, 0x5014, 0x5015, 0x5015, 0x5015,
+ 0x5015, 0x5015, 0x5015, 0x5015, 0x5015, 0x5016, 0x5016, 0x5016,
+ 0x5016, 0x5016, 0x5016, 0x5016, 0x5017, 0x5017, 0x5017, 0x5017,
+ 0x5017, 0x5017, 0x5017, 0x5017, 0x5018, 0x5018, 0x5018, 0x5018,
+ 0x5018, 0x5018, 0x5018, 0x5019, 0x5019, 0x5019, 0x5019, 0x5019,
+ 0x5019, 0x5019, 0x5019, 0x501a, 0x501a, 0x501a, 0x501a, 0x501a,
+ 0x501a, 0x501a, 0x501b, 0x501b, 0x501b, 0x501b, 0x501b, 0x501b,
+ 0x501b, 0x501b, 0x501c, 0x501c, 0x501c, 0x501c, 0x501c, 0x501c,
+ 0x501c, 0x501d, 0x501d, 0x501d, 0x501d, 0x501d, 0x501d, 0x501d,
+ 0x501d, 0x501e, 0x501e, 0x501e, 0x501e, 0x501e, 0x501e, 0x501e,
+ 0x501e, 0x501f, 0x501f, 0x501f, 0x501f, 0x501f, 0x501f, 0x501f,
+ 0x5020, 0x5020, 0x5020, 0x5020, 0x5020, 0x5020, 0x5020, 0x5020,
+ 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021,
+ 0x5022, 0x5022, 0x5022, 0x5022, 0x5022, 0x5022, 0x5022, 0x5022,
+ 0x5023, 0x5023, 0x5023, 0x5023, 0x5023, 0x5023, 0x5023, 0x5023,
+ 0x5024, 0x5024, 0x5024, 0x5024, 0x5024, 0x5024, 0x5024, 0x5025,
+ 0x5025, 0x5025, 0x5025, 0x5025, 0x5025, 0x5025, 0x5025, 0x5026,
+ 0x5026, 0x5026, 0x5026, 0x5026, 0x5026, 0x5026, 0x5026, 0x5027,
+ 0x5027, 0x5027, 0x5027, 0x5027, 0x5027, 0x5027, 0x5027, 0x5028,
+ 0x5028, 0x5028, 0x5028, 0x5028, 0x5028, 0x5028, 0x5028, 0x5029,
+ 0x5029, 0x5029, 0x5029, 0x5029, 0x502a, 0x502a, 0x502a, 0x502a,
+ 0x502b, 0x502b, 0x502b, 0x502b, 0x502c, 0x502c, 0x502c, 0x502c,
+ 0x502d, 0x502d, 0x502d, 0x502d, 0x502e, 0x502e, 0x502e, 0x502e,
+ 0x502f, 0x502f, 0x502f, 0x502f, 0x5030, 0x5030, 0x5030, 0x5030,
+ 0x5031, 0x5031, 0x5031, 0x5031, 0x5032, 0x5032, 0x5032, 0x5032,
+ 0x5032, 0x5033, 0x5033, 0x5033, 0x5033, 0x5034, 0x5034, 0x5034,
+ 0x5034, 0x5035, 0x5035, 0x5035, 0x5035, 0x5036, 0x5036, 0x5036,
+ 0x5036, 0x5037, 0x5037, 0x5037, 0x5037, 0x5037, 0x5038, 0x5038,
+ 0x5038, 0x5038, 0x5039, 0x5039, 0x5039, 0x5039, 0x503a, 0x503a,
+ 0x503a, 0x503a, 0x503b, 0x503b, 0x503b, 0x503b, 0x503b, 0x503c,
+ 0x503c, 0x503c, 0x503c, 0x503d, 0x503d, 0x503d, 0x503d, 0x503e,
+ 0x503e, 0x503e, 0x503e, 0x503e, 0x503f, 0x503f, 0x503f, 0x503f,
+ 0x5040, 0x5040, 0x5040, 0x5040, 0x5041, 0x5041, 0x5041, 0x5041,
+ 0x5041, 0x5042, 0x5042, 0x5042, 0x5042, 0x5043, 0x5043, 0x5043,
+ 0x5043, 0x5043, 0x5044, 0x5044, 0x5044, 0x5044, 0x5045, 0x5045,
+ 0x5045, 0x5045, 0x5045, 0x5046, 0x5046, 0x5046, 0x5046, 0x5047,
+ 0x5047, 0x5047, 0x5047, 0x5047, 0x5048, 0x5048, 0x5048, 0x5048,
+ 0x5049, 0x5049, 0x5049, 0x5049, 0x5049, 0x504a, 0x504a, 0x504a,
+ 0x504a, 0x504b, 0x504b, 0x504b, 0x504b, 0x504b, 0x504c, 0x504c,
+ 0x504c, 0x504c, 0x504d, 0x504d, 0x504d, 0x504d, 0x504d, 0x504e,
+ 0x504e, 0x504e, 0x504e, 0x504e, 0x504f, 0x504f, 0x504f, 0x504f,
+ 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x5051, 0x5051, 0x5051,
+ 0x5051, 0x5051, 0x5052, 0x5052, 0x5052, 0x5052, 0x5053, 0x5053,
+ 0x5053, 0x5053, 0x5053, 0x5054, 0x5054, 0x5054, 0x5054, 0x5054,
+ 0x5055, 0x5055, 0x5055, 0x5055, 0x5056, 0x5056, 0x5056, 0x5056,
+ 0x5056, 0x5057, 0x5057, 0x5057, 0x5057, 0x5057, 0x5058, 0x5058,
+ 0x5058, 0x5058, 0x5058, 0x5059, 0x5059, 0x5059, 0x5059, 0x5059,
+ 0x505a, 0x505a, 0x505a, 0x505a, 0x505a, 0x505b, 0x505b, 0x505b,
+ 0x505b, 0x505c, 0x505c, 0x505c, 0x505c, 0x505c, 0x505d, 0x505d,
+ 0x505d, 0x505d, 0x505d, 0x505e, 0x505e, 0x505e, 0x505e, 0x505e,
+ 0x505f, 0x505f, 0x505f, 0x505f, 0x505f, 0x5060, 0x5060, 0x5060,
+ 0x5060, 0x5060, 0x5061, 0x5061, 0x5061, 0x5061, 0x5061, 0x5062,
+ 0x5062, 0x5062, 0x5062, 0x5062, 0x5063, 0x5063, 0x5063, 0x5063,
+ 0x5063, 0x5064, 0x5064, 0x5064, 0x5064, 0x5064, 0x5065, 0x5065,
+ 0x5065, 0x5065, 0x5065, 0x5066, 0x5066, 0x5066, 0x5066, 0x5066,
+ 0x5067, 0x5067, 0x5067, 0x5067, 0x5067, 0x5068, 0x5068, 0x5068,
+ 0x5068, 0x5068, 0x5069, 0x5069, 0x5069, 0x5069, 0x5069, 0x5069,
+ 0x506a, 0x506a, 0x506a, 0x506a, 0x506a, 0x506b, 0x506b, 0x506b,
+ 0x506b, 0x506b, 0x506c, 0x506c, 0x506c, 0x506c, 0x506c, 0x506d,
+ 0x506d, 0x506d, 0x506d, 0x506d, 0x506e, 0x506e, 0x506e, 0x506e,
+ 0x506e, 0x506e, 0x506f, 0x506f, 0x506f, 0x506f, 0x506f, 0x5070,
+ 0x5070, 0x5070, 0x5070, 0x5070, 0x5071, 0x5071, 0x5071, 0x5071,
+ 0x5071, 0x5072, 0x5072, 0x5072, 0x5072, 0x5072, 0x5072, 0x5073,
+ 0x5073, 0x5073, 0x5073, 0x5073, 0x5074, 0x5074, 0x5074, 0x5074,
+ 0x5074, 0x5074, 0x5075, 0x5075, 0x5075, 0x5075, 0x5075, 0x5076,
+ 0x5076, 0x5076, 0x5076, 0x5076, 0x5077, 0x5077, 0x5077, 0x5077,
+ 0x5077, 0x5077, 0x5078, 0x5078, 0x5078, 0x5078, 0x5078, 0x5079,
+ 0x5079, 0x5079, 0x5079, 0x5079, 0x5079, 0x507a, 0x507a, 0x507a,
+ 0x507a, 0x507a, 0x507b, 0x507b, 0x507b, 0x507b, 0x507b, 0x507b,
+ 0x507c, 0x507c, 0x507c, 0x507c, 0x507c, 0x507d, 0x507d, 0x507d,
+ 0x507d, 0x507d, 0x507d, 0x507e, 0x507e, 0x507e, 0x507e, 0x507e,
+ 0x507f, 0x507f, 0x507f, 0x507f, 0x507f, 0x507f, 0x5080, 0x5080,
+ 0x5080, 0x5080, 0x5080, 0x5080, 0x5081, 0x5081, 0x5081, 0x5081,
+ 0x5081, 0x5082, 0x5082, 0x5082, 0x5082, 0x5082, 0x5082, 0x5083,
+ 0x5083, 0x5083, 0x5083, 0x5083, 0x5083, 0x5084, 0x5084, 0x5084,
+ 0x5084, 0x5084, 0x5085, 0x5085, 0x5085, 0x5085, 0x5085, 0x5085,
+ 0x5086, 0x5086, 0x5086, 0x5086, 0x5086, 0x5086, 0x5087, 0x5087,
+ 0x5087, 0x5087, 0x5087, 0x5087, 0x5088, 0x5088, 0x5088, 0x5088,
+ 0x5088, 0x5089, 0x5089, 0x5089, 0x5089, 0x5089, 0x5089, 0x508a,
+ 0x508a, 0x508a, 0x508a, 0x508a, 0x508a, 0x508b, 0x508b, 0x508b,
+ 0x508b, 0x508b, 0x508b, 0x508c, 0x508c, 0x508c, 0x508c, 0x508c,
+ 0x508c, 0x508d, 0x508d, 0x508d, 0x508d, 0x508d, 0x508d, 0x508e,
+ 0x508e, 0x508e, 0x508e, 0x508e, 0x508e, 0x508f, 0x508f, 0x508f,
+ 0x508f, 0x508f, 0x508f, 0x5090, 0x5090, 0x5090, 0x5090, 0x5090,
+ 0x5090, 0x5091, 0x5091, 0x5091, 0x5091, 0x5091, 0x5091, 0x5092,
+ 0x5092, 0x5092, 0x5092, 0x5092, 0x5092, 0x5093, 0x5093, 0x5093,
+ 0x5093, 0x5093, 0x5093, 0x5094, 0x5094, 0x5094, 0x5094, 0x5094,
+ 0x5094, 0x5095, 0x5095, 0x5095, 0x5095, 0x5095, 0x5095, 0x5096,
+ 0x5096, 0x5096, 0x5096, 0x5096, 0x5096, 0x5097, 0x5097, 0x5097,
+ 0x5097, 0x5097, 0x5097, 0x5098, 0x5098, 0x5098, 0x5098, 0x5098,
+ 0x5098, 0x5099, 0x5099, 0x5099, 0x5099, 0x5099, 0x5099, 0x5099,
+ 0x509a, 0x509a, 0x509a, 0x509a, 0x509a, 0x509a, 0x509b, 0x509b,
+ 0x509b, 0x509b, 0x509b, 0x509b, 0x509c, 0x509c, 0x509c, 0x509c,
+ 0x509c, 0x509c, 0x509d, 0x509d, 0x509d, 0x509d, 0x509d, 0x509d,
+ 0x509d, 0x509e, 0x509e, 0x509e, 0x509e, 0x509e, 0x509e, 0x509f,
+ 0x509f, 0x509f, 0x509f, 0x509f, 0x509f, 0x50a0, 0x50a0, 0x50a0,
+ 0x50a0, 0x50a0, 0x50a0, 0x50a0, 0x50a1, 0x50a1, 0x50a1, 0x50a1,
+ 0x50a1, 0x50a1, 0x50a2, 0x50a2, 0x50a2, 0x50a2, 0x50a2, 0x50a2,
+ 0x50a2, 0x50a3, 0x50a3, 0x50a3, 0x50a3, 0x50a3, 0x50a3, 0x50a4,
+ 0x50a4, 0x50a4, 0x50a4, 0x50a4, 0x50a4, 0x50a5, 0x50a5, 0x50a5,
+ 0x50a5, 0x50a5, 0x50a5, 0x50a5, 0x50a6, 0x50a6, 0x50a6, 0x50a6,
+ 0x50a6, 0x50a6, 0x50a6, 0x50a7, 0x50a7, 0x50a7, 0x50a7, 0x50a7,
+ 0x50a7, 0x50a8, 0x50a8, 0x50a8, 0x50a8, 0x50a8, 0x50a8, 0x50a8,
+ 0x50a9, 0x50a9, 0x50a9, 0x50a9, 0x50a9, 0x50a9, 0x50aa, 0x50aa,
+ 0x50aa, 0x50aa, 0x50aa, 0x50aa, 0x50aa, 0x50ab, 0x50ab, 0x50ab,
+ 0x50ab, 0x50ab, 0x50ab, 0x50ab, 0x50ac, 0x50ac, 0x50ac, 0x50ac,
+ 0x50ac, 0x50ac, 0x50ad, 0x50ad, 0x50ad, 0x50ad, 0x50ad, 0x50ad,
+ 0x50ad, 0x50ae, 0x50ae, 0x50ae, 0x50ae, 0x50ae, 0x50ae, 0x50ae,
+ 0x50af, 0x50af, 0x50af, 0x50af, 0x50af, 0x50af, 0x50b0, 0x50b0,
+ 0x50b0, 0x50b0, 0x50b0, 0x50b0, 0x50b0, 0x50b1, 0x50b1, 0x50b1,
+ 0x50b1, 0x50b1, 0x50b1, 0x50b1, 0x50b2, 0x50b2, 0x50b2, 0x50b2,
+ 0x50b2, 0x50b2, 0x50b2, 0x50b3, 0x50b3, 0x50b3, 0x50b3, 0x50b3,
+ 0x50b3, 0x50b3, 0x50b4, 0x50b4, 0x50b4, 0x50b4, 0x50b4, 0x50b4,
+ 0x50b4, 0x50b5, 0x50b5, 0x50b5, 0x50b5, 0x50b5, 0x50b5, 0x50b5,
+ 0x50b6, 0x50b6, 0x50b6, 0x50b6, 0x50b6, 0x50b6, 0x50b7, 0x50b7,
+ 0x50b7, 0x50b7, 0x50b7, 0x50b7, 0x50b7, 0x50b8, 0x50b8, 0x50b8,
+ 0x50b8, 0x50b8, 0x50b8, 0x50b8, 0x50b9, 0x50b9, 0x50b9, 0x50b9,
+ 0x50b9, 0x50b9, 0x50b9, 0x50ba, 0x50ba, 0x50ba, 0x50ba, 0x50ba,
+ 0x50ba, 0x50ba, 0x50ba, 0x50bb, 0x50bb, 0x50bb, 0x50bb, 0x50bb,
+ 0x50bb, 0x50bb, 0x50bc, 0x50bc, 0x50bc, 0x50bc, 0x50bc, 0x50bc,
+ 0x50bc, 0x50bd, 0x50bd, 0x50bd, 0x50bd, 0x50bd, 0x50bd, 0x50bd,
+ 0x50be, 0x50be, 0x50be, 0x50be, 0x50be, 0x50be, 0x50be, 0x50bf,
+ 0x50bf, 0x50bf, 0x50bf, 0x50bf, 0x50bf, 0x50bf, 0x50c0, 0x50c0,
+ 0x50c0, 0x50c0, 0x50c0, 0x50c0, 0x50c0, 0x50c1, 0x50c1, 0x50c1,
+ 0x50c1, 0x50c1, 0x50c1, 0x50c1, 0x50c1, 0x50c2, 0x50c2, 0x50c2,
+ 0x50c2, 0x50c2, 0x50c2, 0x50c2, 0x50c3, 0x50c3, 0x50c3, 0x50c3,
+ 0x50c3, 0x50c3, 0x50c3, 0x50c4, 0x50c4, 0x50c4, 0x50c4, 0x50c4,
+ 0x50c4, 0x50c4, 0x50c4, 0x50c5, 0x50c5, 0x50c5, 0x50c5, 0x50c5,
+ 0x50c5, 0x50c5, 0x50c6, 0x50c6, 0x50c6, 0x50c6, 0x50c6, 0x50c6,
+ 0x50c6, 0x50c7, 0x50c7, 0x50c7, 0x50c7, 0x50c7, 0x50c7, 0x50c7,
+ 0x50c7, 0x50c8, 0x50c8, 0x50c8, 0x50c8, 0x50c8, 0x50c8, 0x50c8,
+ 0x50c9, 0x50c9, 0x50c9, 0x50c9, 0x50c9, 0x50c9, 0x50c9, 0x50c9,
+ 0x50ca, 0x50ca, 0x50ca, 0x50ca, 0x50ca, 0x50ca, 0x50ca, 0x50cb,
+ 0x50cb, 0x50cb, 0x50cb, 0x50cb, 0x50cb, 0x50cb, 0x50cb, 0x50cc,
+ 0x50cc, 0x50cc, 0x50cc, 0x50cc, 0x50cc, 0x50cc, 0x50cd, 0x50cd,
+ 0x50cd, 0x50cd, 0x50cd, 0x50cd, 0x50cd, 0x50cd, 0x50ce, 0x50ce,
+ 0x50ce, 0x50ce, 0x50ce, 0x50ce, 0x50ce, 0x50ce, 0x50cf, 0x50cf,
+ 0x50cf, 0x50cf, 0x50cf, 0x50cf, 0x50cf, 0x50d0, 0x50d0, 0x50d0,
+ 0x50d0, 0x50d0, 0x50d0, 0x50d0, 0x50d0, 0x50d1, 0x50d1, 0x50d1,
+ 0x50d1, 0x50d1, 0x50d1, 0x50d1, 0x50d1, 0x50d2, 0x50d2, 0x50d2,
+ 0x50d2, 0x50d2, 0x50d2, 0x50d2, 0x50d3, 0x50d3, 0x50d3, 0x50d3,
+ 0x50d3, 0x50d3, 0x50d3, 0x50d3, 0x50d4, 0x50d4, 0x50d4, 0x50d4,
+ 0x50d4, 0x50d4, 0x50d4, 0x50d4, 0x50d5, 0x50d5, 0x50d5, 0x50d5,
+ 0x50d5, 0x50d5, 0x50d5, 0x50d5, 0x50d6, 0x50d6, 0x50d6, 0x50d6,
+ 0x50d6, 0x50d6, 0x50d6, 0x50d6, 0x50d7, 0x50d7, 0x50d7, 0x50d7,
+ 0x50d7, 0x50d7, 0x50d7, 0x50d7, 0x50d8, 0x50d8, 0x50d8, 0x50d8,
+ 0x50d8, 0x50d8, 0x50d8, 0x50d8, 0x50d9, 0x50d9, 0x50d9, 0x50d9,
+ 0x50d9, 0x50d9, 0x50d9, 0x50d9, 0x50da, 0x50da, 0x50da, 0x50da,
+ 0x50da, 0x50da, 0x50db, 0x50db, 0x50db, 0x50db, 0x50dc, 0x50dc,
+ 0x50dc, 0x50dc, 0x50dd, 0x50dd, 0x50dd, 0x50dd, 0x50de, 0x50de,
+ 0x50de, 0x50de, 0x50df, 0x50df, 0x50df, 0x50df, 0x50e0, 0x50e0,
+ 0x50e0, 0x50e0, 0x50e1, 0x50e1, 0x50e1, 0x50e1, 0x50e2, 0x50e2,
+ 0x50e2, 0x50e2, 0x50e2, 0x50e3, 0x50e3, 0x50e3, 0x50e3, 0x50e4,
+ 0x50e4, 0x50e4, 0x50e4, 0x50e5, 0x50e5, 0x50e5, 0x50e5, 0x50e6,
+ 0x50e6, 0x50e6, 0x50e6, 0x50e7, 0x50e7, 0x50e7, 0x50e7, 0x50e8,
+ 0x50e8, 0x50e8, 0x50e8, 0x50e8, 0x50e9, 0x50e9, 0x50e9, 0x50e9,
+ 0x50ea, 0x50ea, 0x50ea, 0x50ea, 0x50eb, 0x50eb, 0x50eb, 0x50eb,
+ 0x50ec, 0x50ec, 0x50ec, 0x50ec, 0x50ec, 0x50ed, 0x50ed, 0x50ed,
+ 0x50ed, 0x50ee, 0x50ee, 0x50ee, 0x50ee, 0x50ef, 0x50ef, 0x50ef,
+ 0x50ef, 0x50ef, 0x50f0, 0x50f0, 0x50f0, 0x50f0, 0x50f1, 0x50f1,
+ 0x50f1, 0x50f1, 0x50f2, 0x50f2, 0x50f2, 0x50f2, 0x50f2, 0x50f3,
+ 0x50f3, 0x50f3, 0x50f3, 0x50f4, 0x50f4, 0x50f4, 0x50f4, 0x50f4,
+ 0x50f5, 0x50f5, 0x50f5, 0x50f5, 0x50f6, 0x50f6, 0x50f6, 0x50f6,
+ 0x50f6, 0x50f7, 0x50f7, 0x50f7, 0x50f7, 0x50f8, 0x50f8, 0x50f8,
+ 0x50f8, 0x50f8, 0x50f9, 0x50f9, 0x50f9, 0x50f9, 0x50fa, 0x50fa,
+ 0x50fa, 0x50fa, 0x50fa, 0x50fb, 0x50fb, 0x50fb, 0x50fb, 0x50fc,
+ 0x50fc, 0x50fc, 0x50fc, 0x50fc, 0x50fd, 0x50fd, 0x50fd, 0x50fd,
+ 0x50fe, 0x50fe, 0x50fe, 0x50fe, 0x50fe, 0x50ff, 0x50ff, 0x50ff,
+ 0x50ff, 0x5100, 0x5100, 0x5100, 0x5100, 0x5100, 0x5101, 0x5101,
+ 0x5101, 0x5101, 0x5101, 0x5102, 0x5102, 0x5102, 0x5102, 0x5103,
+ 0x5103, 0x5103, 0x5103, 0x5103, 0x5104, 0x5104, 0x5104, 0x5104,
+ 0x5104, 0x5105, 0x5105, 0x5105, 0x5105, 0x5105, 0x5106, 0x5106,
+ 0x5106, 0x5106, 0x5107, 0x5107, 0x5107, 0x5107, 0x5107, 0x5108,
+ 0x5108, 0x5108, 0x5108, 0x5108, 0x5109, 0x5109, 0x5109, 0x5109,
+ 0x5109, 0x510a, 0x510a, 0x510a, 0x510a, 0x510a, 0x510b, 0x510b,
+ 0x510b, 0x510b, 0x510c, 0x510c, 0x510c, 0x510c, 0x510c, 0x510d,
+ 0x510d, 0x510d, 0x510d, 0x510d, 0x510e, 0x510e, 0x510e, 0x510e,
+ 0x510e, 0x510f, 0x510f, 0x510f, 0x510f, 0x510f, 0x5110, 0x5110,
+ 0x5110, 0x5110, 0x5110, 0x5111, 0x5111, 0x5111, 0x5111, 0x5111,
+ 0x5112, 0x5112, 0x5112, 0x5112, 0x5112, 0x5113, 0x5113, 0x5113,
+ 0x5113, 0x5113, 0x5114, 0x5114, 0x5114, 0x5114, 0x5114, 0x5115,
+ 0x5115, 0x5115, 0x5115, 0x5115, 0x5116, 0x5116, 0x5116, 0x5116,
+ 0x5116, 0x5117, 0x5117, 0x5117, 0x5117, 0x5117, 0x5118, 0x5118,
+ 0x5118, 0x5118, 0x5118, 0x5119, 0x5119, 0x5119, 0x5119, 0x5119,
+ 0x511a, 0x511a, 0x511a, 0x511a, 0x511a, 0x511b, 0x511b, 0x511b,
+ 0x511b, 0x511b, 0x511c, 0x511c, 0x511c, 0x511c, 0x511c, 0x511c,
+ 0x511d, 0x511d, 0x511d, 0x511d, 0x511d, 0x511e, 0x511e, 0x511e,
+ 0x511e, 0x511e, 0x511f, 0x511f, 0x511f, 0x511f, 0x511f, 0x5120,
+ 0x5120, 0x5120, 0x5120, 0x5120, 0x5120, 0x5121, 0x5121, 0x5121,
+ 0x5121, 0x5121, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5123,
+ 0x5123, 0x5123, 0x5123, 0x5123, 0x5124, 0x5124, 0x5124, 0x5124,
+ 0x5124, 0x5124, 0x5125, 0x5125, 0x5125, 0x5125, 0x5125, 0x5126,
+ 0x5126, 0x5126, 0x5126, 0x5126, 0x5127, 0x5127, 0x5127, 0x5127,
+ 0x5127, 0x5127, 0x5128, 0x5128, 0x5128, 0x5128, 0x5128, 0x5129,
+ 0x5129, 0x5129, 0x5129, 0x5129, 0x5129, 0x512a, 0x512a, 0x512a,
+ 0x512a, 0x512a, 0x512b, 0x512b, 0x512b, 0x512b, 0x512b, 0x512b,
+ 0x512c, 0x512c, 0x512c, 0x512c, 0x512c, 0x512d, 0x512d, 0x512d,
+ 0x512d, 0x512d, 0x512d, 0x512e, 0x512e, 0x512e, 0x512e, 0x512e,
+ 0x512f, 0x512f, 0x512f, 0x512f, 0x512f, 0x512f, 0x5130, 0x5130,
+ 0x5130, 0x5130, 0x5130, 0x5131, 0x5131, 0x5131, 0x5131, 0x5131,
+ 0x5131, 0x5132, 0x5132, 0x5132, 0x5132, 0x5132, 0x5132, 0x5133,
+ 0x5133, 0x5133, 0x5133, 0x5133, 0x5134, 0x5134, 0x5134, 0x5134,
+ 0x5134, 0x5134, 0x5135, 0x5135, 0x5135, 0x5135, 0x5135, 0x5135,
+ 0x5136, 0x5136, 0x5136, 0x5136, 0x5136, 0x5137, 0x5137, 0x5137,
+ 0x5137, 0x5137, 0x5137, 0x5138, 0x5138, 0x5138, 0x5138, 0x5138,
+ 0x5138, 0x5139, 0x5139, 0x5139, 0x5139, 0x5139, 0x5139, 0x513a,
+ 0x513a, 0x513a, 0x513a, 0x513a, 0x513a, 0x513b, 0x513b, 0x513b,
+ 0x513b, 0x513b, 0x513c, 0x513c, 0x513c, 0x513c, 0x513c, 0x513c,
+ 0x513d, 0x513d, 0x513d, 0x513d, 0x513d, 0x513d, 0x513e, 0x513e,
+ 0x513e, 0x513e, 0x513e, 0x513e, 0x513f, 0x513f, 0x513f, 0x513f,
+ 0x513f, 0x513f, 0x5140, 0x5140, 0x5140, 0x5140, 0x5140, 0x5140,
+ 0x5141, 0x5141, 0x5141, 0x5141, 0x5141, 0x5141, 0x5142, 0x5142,
+ 0x5142, 0x5142, 0x5142, 0x5142, 0x5143, 0x5143, 0x5143, 0x5143,
+ 0x5143, 0x5143, 0x5144, 0x5144, 0x5144, 0x5144, 0x5144, 0x5144,
+ 0x5145, 0x5145, 0x5145, 0x5145, 0x5145, 0x5145, 0x5146, 0x5146,
+ 0x5146, 0x5146, 0x5146, 0x5146, 0x5147, 0x5147, 0x5147, 0x5147,
+ 0x5147, 0x5147, 0x5148, 0x5148, 0x5148, 0x5148, 0x5148, 0x5148,
+ 0x5149, 0x5149, 0x5149, 0x5149, 0x5149, 0x5149, 0x5149, 0x514a,
+ 0x514a, 0x514a, 0x514a, 0x514a, 0x514a, 0x514b, 0x514b, 0x514b,
+ 0x514b, 0x514b, 0x514b, 0x514c, 0x514c, 0x514c, 0x514c, 0x514c,
+ 0x514c, 0x514d, 0x514d, 0x514d, 0x514d, 0x514d, 0x514d, 0x514d,
+ 0x514e, 0x514e, 0x514e, 0x514e, 0x514e, 0x514e, 0x514f, 0x514f,
+ 0x514f, 0x514f, 0x514f, 0x514f, 0x5150, 0x5150, 0x5150, 0x5150,
+ 0x5150, 0x5150, 0x5150, 0x5151, 0x5151, 0x5151, 0x5151, 0x5151,
+ 0x5151, 0x5152, 0x5152, 0x5152, 0x5152, 0x5152, 0x5152, 0x5153,
+ 0x5153, 0x5153, 0x5153, 0x5153, 0x5153, 0x5153, 0x5154, 0x5154,
+ 0x5154, 0x5154, 0x5154, 0x5154, 0x5155, 0x5155, 0x5155, 0x5155,
+ 0x5155, 0x5155, 0x5155, 0x5156, 0x5156, 0x5156, 0x5156, 0x5156,
+ 0x5156, 0x5157, 0x5157, 0x5157, 0x5157, 0x5157, 0x5157, 0x5157,
+ 0x5158, 0x5158, 0x5158, 0x5158, 0x5158, 0x5158, 0x5159, 0x5159,
+ 0x5159, 0x5159, 0x5159, 0x5159, 0x5159, 0x515a, 0x515a, 0x515a,
+ 0x515a, 0x515a, 0x515a, 0x515b, 0x515b, 0x515b, 0x515b, 0x515b,
+ 0x515b, 0x515b, 0x515c, 0x515c, 0x515c, 0x515c, 0x515c, 0x515c,
+ 0x515c, 0x515d, 0x515d, 0x515d, 0x515d, 0x515d, 0x515d, 0x515e,
+ 0x515e, 0x515e, 0x515e, 0x515e, 0x515e, 0x515e, 0x515f, 0x515f,
+ 0x515f, 0x515f, 0x515f, 0x515f, 0x515f, 0x5160, 0x5160, 0x5160,
+ 0x5160, 0x5160, 0x5160, 0x5161, 0x5161, 0x5161, 0x5161, 0x5161,
+ 0x5161, 0x5161, 0x5162, 0x5162, 0x5162, 0x5162, 0x5162, 0x5162,
+ 0x5162, 0x5163, 0x5163, 0x5163, 0x5163, 0x5163, 0x5163, 0x5163,
+ 0x5164, 0x5164, 0x5164, 0x5164, 0x5164, 0x5164, 0x5164, 0x5165,
+ 0x5165, 0x5165, 0x5165, 0x5165, 0x5165, 0x5165, 0x5166, 0x5166,
+ 0x5166, 0x5166, 0x5166, 0x5166, 0x5167, 0x5167, 0x5167, 0x5167,
+ 0x5167, 0x5167, 0x5167, 0x5168, 0x5168, 0x5168, 0x5168, 0x5168,
+ 0x5168, 0x5168, 0x5169, 0x5169, 0x5169, 0x5169, 0x5169, 0x5169,
+ 0x5169, 0x516a, 0x516a, 0x516a, 0x516a, 0x516a, 0x516a, 0x516a,
+ 0x516b, 0x516b, 0x516b, 0x516b, 0x516b, 0x516b, 0x516b, 0x516c,
+ 0x516c, 0x516c, 0x516c, 0x516c, 0x516c, 0x516c, 0x516d, 0x516d,
+ 0x516d, 0x516d, 0x516d, 0x516d, 0x516d, 0x516d, 0x516e, 0x516e,
+ 0x516e, 0x516e, 0x516e, 0x516e, 0x516e, 0x516f, 0x516f, 0x516f,
+ 0x516f, 0x516f, 0x516f, 0x516f, 0x5170, 0x5170, 0x5170, 0x5170,
+ 0x5170, 0x5170, 0x5170, 0x5171, 0x5171, 0x5171, 0x5171, 0x5171,
+ 0x5171, 0x5171, 0x5172, 0x5172, 0x5172, 0x5172, 0x5172, 0x5172,
+ 0x5172, 0x5173, 0x5173, 0x5173, 0x5173, 0x5173, 0x5173, 0x5173,
+ 0x5173, 0x5174, 0x5174, 0x5174, 0x5174, 0x5174, 0x5174, 0x5174,
+ 0x5175, 0x5175, 0x5175, 0x5175, 0x5175, 0x5175, 0x5175, 0x5176,
+ 0x5176, 0x5176, 0x5176, 0x5176, 0x5176, 0x5176, 0x5176, 0x5177,
+ 0x5177, 0x5177, 0x5177, 0x5177, 0x5177, 0x5177, 0x5178, 0x5178,
+ 0x5178, 0x5178, 0x5178, 0x5178, 0x5178, 0x5178, 0x5179, 0x5179,
+ 0x5179, 0x5179, 0x5179, 0x5179, 0x5179, 0x517a, 0x517a, 0x517a,
+ 0x517a, 0x517a, 0x517a, 0x517a, 0x517b, 0x517b, 0x517b, 0x517b,
+ 0x517b, 0x517b, 0x517b, 0x517b, 0x517c, 0x517c, 0x517c, 0x517c,
+ 0x517c, 0x517c, 0x517c, 0x517d, 0x517d, 0x517d, 0x517d, 0x517d,
+ 0x517d, 0x517d, 0x517d, 0x517e, 0x517e, 0x517e, 0x517e, 0x517e,
+ 0x517e, 0x517e, 0x517e, 0x517f, 0x517f, 0x517f, 0x517f, 0x517f,
+ 0x517f, 0x517f, 0x5180, 0x5180, 0x5180, 0x5180, 0x5180, 0x5180,
+ 0x5180, 0x5180, 0x5181, 0x5181, 0x5181, 0x5181, 0x5181, 0x5181,
+ 0x5181, 0x5181, 0x5182, 0x5182, 0x5182, 0x5182, 0x5182, 0x5182,
+ 0x5182, 0x5183, 0x5183, 0x5183, 0x5183, 0x5183, 0x5183, 0x5183,
+ 0x5183, 0x5184, 0x5184, 0x5184, 0x5184, 0x5184, 0x5184, 0x5184,
+ 0x5184, 0x5185, 0x5185, 0x5185, 0x5185, 0x5185, 0x5185, 0x5185,
+ 0x5185, 0x5186, 0x5186, 0x5186, 0x5186, 0x5186, 0x5186, 0x5186,
+ 0x5187, 0x5187, 0x5187, 0x5187, 0x5187, 0x5187, 0x5187, 0x5187,
+ 0x5188, 0x5188, 0x5188, 0x5188, 0x5188, 0x5188, 0x5188, 0x5188,
+ 0x5189, 0x5189, 0x5189, 0x5189, 0x5189, 0x5189, 0x5189, 0x5189,
+ 0x518a, 0x518a, 0x518a, 0x518a, 0x518a, 0x518a, 0x518a, 0x518a,
+ 0x518b, 0x518b, 0x518b, 0x518b, 0x518b, 0x518b, 0x518b, 0x518b,
+ 0x518c, 0x518c, 0x518c, 0x518c, 0x518d, 0x518d, 0x518d, 0x518d,
+ 0x518e, 0x518e, 0x518e, 0x518e, 0x518f, 0x518f, 0x518f, 0x518f,
+ 0x5190, 0x5190, 0x5190, 0x5190, 0x5191, 0x5191, 0x5191, 0x5191,
+ 0x5191, 0x5192, 0x5192, 0x5192, 0x5192, 0x5193, 0x5193, 0x5193,
+ 0x5193, 0x5194, 0x5194, 0x5194, 0x5194, 0x5195, 0x5195, 0x5195,
+ 0x5195, 0x5196, 0x5196, 0x5196, 0x5196, 0x5197, 0x5197, 0x5197,
+ 0x5197, 0x5198, 0x5198, 0x5198, 0x5198, 0x5198, 0x5199, 0x5199,
+ 0x5199, 0x5199, 0x519a, 0x519a, 0x519a, 0x519a, 0x519b, 0x519b,
+ 0x519b, 0x519b, 0x519c, 0x519c, 0x519c, 0x519c, 0x519c, 0x519d,
+ 0x519d, 0x519d, 0x519d, 0x519e, 0x519e, 0x519e, 0x519e, 0x519f,
+ 0x519f, 0x519f, 0x519f, 0x51a0, 0x51a0, 0x51a0, 0x51a0, 0x51a0,
+ 0x51a1, 0x51a1, 0x51a1, 0x51a1, 0x51a2, 0x51a2, 0x51a2, 0x51a2,
+ 0x51a3, 0x51a3, 0x51a3, 0x51a3, 0x51a3, 0x51a4, 0x51a4, 0x51a4,
+ 0x51a4, 0x51a5, 0x51a5, 0x51a5, 0x51a5, 0x51a5, 0x51a6, 0x51a6,
+ 0x51a6, 0x51a6, 0x51a7, 0x51a7, 0x51a7, 0x51a7, 0x51a7, 0x51a8,
+ 0x51a8, 0x51a8, 0x51a8, 0x51a9, 0x51a9, 0x51a9, 0x51a9, 0x51a9,
+ 0x51aa, 0x51aa, 0x51aa, 0x51aa, 0x51ab, 0x51ab, 0x51ab, 0x51ab,
+ 0x51ab, 0x51ac, 0x51ac, 0x51ac, 0x51ac, 0x51ad, 0x51ad, 0x51ad,
+ 0x51ad, 0x51ad, 0x51ae, 0x51ae, 0x51ae, 0x51ae, 0x51af, 0x51af,
+ 0x51af, 0x51af, 0x51af, 0x51b0, 0x51b0, 0x51b0, 0x51b0, 0x51b1,
+ 0x51b1, 0x51b1, 0x51b1, 0x51b1, 0x51b2, 0x51b2, 0x51b2, 0x51b2,
+ 0x51b2, 0x51b3, 0x51b3, 0x51b3, 0x51b3, 0x51b4, 0x51b4, 0x51b4,
+ 0x51b4, 0x51b4, 0x51b5, 0x51b5, 0x51b5, 0x51b5, 0x51b5, 0x51b6,
+ 0x51b6, 0x51b6, 0x51b6, 0x51b7, 0x51b7, 0x51b7, 0x51b7, 0x51b7,
+ 0x51b8, 0x51b8, 0x51b8, 0x51b8, 0x51b8, 0x51b9, 0x51b9, 0x51b9,
+ 0x51b9, 0x51b9, 0x51ba, 0x51ba, 0x51ba, 0x51ba, 0x51ba, 0x51bb,
+ 0x51bb, 0x51bb, 0x51bb, 0x51bc, 0x51bc, 0x51bc, 0x51bc, 0x51bc,
+ 0x51bd, 0x51bd, 0x51bd, 0x51bd, 0x51bd, 0x51be, 0x51be, 0x51be,
+ 0x51be, 0x51be, 0x51bf, 0x51bf, 0x51bf, 0x51bf, 0x51bf, 0x51c0,
+ 0x51c0, 0x51c0, 0x51c0, 0x51c0, 0x51c1, 0x51c1, 0x51c1, 0x51c1,
+ 0x51c1, 0x51c2, 0x51c2, 0x51c2, 0x51c2, 0x51c2, 0x51c3, 0x51c3,
+ 0x51c3, 0x51c3, 0x51c3, 0x51c4, 0x51c4, 0x51c4, 0x51c4, 0x51c4,
+ 0x51c5, 0x51c5, 0x51c5, 0x51c5, 0x51c5, 0x51c6, 0x51c6, 0x51c6,
+ 0x51c6, 0x51c6, 0x51c7, 0x51c7, 0x51c7, 0x51c7, 0x51c7, 0x51c8,
+ 0x51c8, 0x51c8, 0x51c8, 0x51c8, 0x51c9, 0x51c9, 0x51c9, 0x51c9,
+ 0x51c9, 0x51ca, 0x51ca, 0x51ca, 0x51ca, 0x51ca, 0x51cb, 0x51cb,
+ 0x51cb, 0x51cb, 0x51cb, 0x51cc, 0x51cc, 0x51cc, 0x51cc, 0x51cc,
+ 0x51cd, 0x51cd, 0x51cd, 0x51cd, 0x51cd, 0x51ce, 0x51ce, 0x51ce,
+ 0x51ce, 0x51ce, 0x51ce, 0x51cf, 0x51cf, 0x51cf, 0x51cf, 0x51cf,
+ 0x51d0, 0x51d0, 0x51d0, 0x51d0, 0x51d0, 0x51d1, 0x51d1, 0x51d1,
+ 0x51d1, 0x51d1, 0x51d2, 0x51d2, 0x51d2, 0x51d2, 0x51d2, 0x51d3,
+ 0x51d3, 0x51d3, 0x51d3, 0x51d3, 0x51d3, 0x51d4, 0x51d4, 0x51d4,
+ 0x51d4, 0x51d4, 0x51d5, 0x51d5, 0x51d5, 0x51d5, 0x51d5, 0x51d6,
+ 0x51d6, 0x51d6, 0x51d6, 0x51d6, 0x51d6, 0x51d7, 0x51d7, 0x51d7,
+ 0x51d7, 0x51d7, 0x51d8, 0x51d8, 0x51d8, 0x51d8, 0x51d8, 0x51d9,
+ 0x51d9, 0x51d9, 0x51d9, 0x51d9, 0x51d9, 0x51da, 0x51da, 0x51da,
+ 0x51da, 0x51da, 0x51db, 0x51db, 0x51db, 0x51db, 0x51db, 0x51db,
+ 0x51dc, 0x51dc, 0x51dc, 0x51dc, 0x51dc, 0x51dd, 0x51dd, 0x51dd,
+ 0x51dd, 0x51dd, 0x51dd, 0x51de, 0x51de, 0x51de, 0x51de, 0x51de,
+ 0x51df, 0x51df, 0x51df, 0x51df, 0x51df, 0x51df, 0x51e0, 0x51e0,
+ 0x51e0, 0x51e0, 0x51e0, 0x51e1, 0x51e1, 0x51e1, 0x51e1, 0x51e1,
+ 0x51e1, 0x51e2, 0x51e2, 0x51e2, 0x51e2, 0x51e2, 0x51e2, 0x51e3,
+ 0x51e3, 0x51e3, 0x51e3, 0x51e3, 0x51e4, 0x51e4, 0x51e4, 0x51e4,
+ 0x51e4, 0x51e4, 0x51e5, 0x51e5, 0x51e5, 0x51e5, 0x51e5, 0x51e5,
+ 0x51e6, 0x51e6, 0x51e6, 0x51e6, 0x51e6, 0x51e7, 0x51e7, 0x51e7,
+ 0x51e7, 0x51e7, 0x51e7, 0x51e8, 0x51e8, 0x51e8, 0x51e8, 0x51e8,
+ 0x51e8, 0x51e9, 0x51e9, 0x51e9, 0x51e9, 0x51e9, 0x51ea, 0x51ea,
+ 0x51ea, 0x51ea, 0x51ea, 0x51ea, 0x51eb, 0x51eb, 0x51eb, 0x51eb,
+ 0x51eb, 0x51eb, 0x51ec, 0x51ec, 0x51ec, 0x51ec, 0x51ec, 0x51ec,
+ 0x51ed, 0x51ed, 0x51ed, 0x51ed, 0x51ed, 0x51ed, 0x51ee, 0x51ee,
+ 0x51ee, 0x51ee, 0x51ee, 0x51ee, 0x51ef, 0x51ef, 0x51ef, 0x51ef,
+ 0x51ef, 0x51f0, 0x51f0, 0x51f0, 0x51f0, 0x51f0, 0x51f0, 0x51f1,
+ 0x51f1, 0x51f1, 0x51f1, 0x51f1, 0x51f1, 0x51f2, 0x51f2, 0x51f2,
+ 0x51f2, 0x51f2, 0x51f2, 0x51f3, 0x51f3, 0x51f3, 0x51f3, 0x51f3,
+ 0x51f3, 0x51f4, 0x51f4, 0x51f4, 0x51f4, 0x51f4, 0x51f4, 0x51f5,
+ 0x51f5, 0x51f5, 0x51f5, 0x51f5, 0x51f5, 0x51f6, 0x51f6, 0x51f6,
+ 0x51f6, 0x51f6, 0x51f6, 0x51f7, 0x51f7, 0x51f7, 0x51f7, 0x51f7,
+ 0x51f7, 0x51f7, 0x51f8, 0x51f8, 0x51f8, 0x51f8, 0x51f8, 0x51f8,
+ 0x51f9, 0x51f9, 0x51f9, 0x51f9, 0x51f9, 0x51f9, 0x51fa, 0x51fa,
+ 0x51fa, 0x51fa, 0x51fa, 0x51fa, 0x51fb, 0x51fb, 0x51fb, 0x51fb,
+ 0x51fb, 0x51fb, 0x51fc, 0x51fc, 0x51fc, 0x51fc, 0x51fc, 0x51fc,
+ 0x51fd, 0x51fd, 0x51fd, 0x51fd, 0x51fd, 0x51fd, 0x51fd, 0x51fe,
+ 0x51fe, 0x51fe, 0x51fe, 0x51fe, 0x51fe, 0x51ff, 0x51ff, 0x51ff,
+ 0x51ff, 0x51ff, 0x51ff, 0x5200, 0x5200, 0x5200, 0x5200, 0x5200,
+ 0x5200, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201,
+ 0x5202, 0x5202, 0x5202, 0x5202, 0x5202, 0x5202, 0x5203, 0x5203,
+ 0x5203, 0x5203, 0x5203, 0x5203, 0x5204, 0x5204, 0x5204, 0x5204,
+ 0x5204, 0x5204, 0x5204, 0x5205, 0x5205, 0x5205, 0x5205, 0x5205,
+ 0x5205, 0x5206, 0x5206, 0x5206, 0x5206, 0x5206, 0x5206, 0x5206,
+ 0x5207, 0x5207, 0x5207, 0x5207, 0x5207, 0x5207, 0x5208, 0x5208,
+ 0x5208, 0x5208, 0x5208, 0x5208, 0x5208, 0x5209, 0x5209, 0x5209,
+ 0x5209, 0x5209, 0x5209, 0x520a, 0x520a, 0x520a, 0x520a, 0x520a,
+ 0x520a, 0x520a, 0x520b, 0x520b, 0x520b, 0x520b, 0x520b, 0x520b,
+ 0x520c, 0x520c, 0x520c, 0x520c, 0x520c, 0x520c, 0x520c, 0x520d,
+ 0x520d, 0x520d, 0x520d, 0x520d, 0x520d, 0x520d, 0x520e, 0x520e,
+ 0x520e, 0x520e, 0x520e, 0x520e, 0x520f, 0x520f, 0x520f, 0x520f,
+ 0x520f, 0x520f, 0x520f, 0x5210, 0x5210, 0x5210, 0x5210, 0x5210,
+ 0x5210, 0x5210, 0x5211, 0x5211, 0x5211, 0x5211, 0x5211, 0x5211,
+ 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5213,
+ 0x5213, 0x5213, 0x5213, 0x5213, 0x5213, 0x5213, 0x5214, 0x5214,
+ 0x5214, 0x5214, 0x5214, 0x5214, 0x5214, 0x5215, 0x5215, 0x5215,
+ 0x5215, 0x5215, 0x5215, 0x5215, 0x5216, 0x5216, 0x5216, 0x5216,
+ 0x5216, 0x5216, 0x5217, 0x5217, 0x5217, 0x5217, 0x5217, 0x5217,
+ 0x5217, 0x5218, 0x5218, 0x5218, 0x5218, 0x5218, 0x5218, 0x5218,
+ 0x5219, 0x5219, 0x5219, 0x5219, 0x5219, 0x5219, 0x5219, 0x521a,
+ 0x521a, 0x521a, 0x521a, 0x521a, 0x521a, 0x521a, 0x521b, 0x521b,
+ 0x521b, 0x521b, 0x521b, 0x521b, 0x521b, 0x521c, 0x521c, 0x521c,
+ 0x521c, 0x521c, 0x521c, 0x521c, 0x521d, 0x521d, 0x521d, 0x521d,
+ 0x521d, 0x521d, 0x521d, 0x521e, 0x521e, 0x521e, 0x521e, 0x521e,
+ 0x521e, 0x521e, 0x521f, 0x521f, 0x521f, 0x521f, 0x521f, 0x521f,
+ 0x521f, 0x521f, 0x5220, 0x5220, 0x5220, 0x5220, 0x5220, 0x5220,
+ 0x5220, 0x5221, 0x5221, 0x5221, 0x5221, 0x5221, 0x5221, 0x5221,
+ 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5223,
+ 0x5223, 0x5223, 0x5223, 0x5223, 0x5223, 0x5223, 0x5224, 0x5224,
+ 0x5224, 0x5224, 0x5224, 0x5224, 0x5224, 0x5224, 0x5225, 0x5225,
+ 0x5225, 0x5225, 0x5225, 0x5225, 0x5225, 0x5226, 0x5226, 0x5226,
+ 0x5226, 0x5226, 0x5226, 0x5226, 0x5227, 0x5227, 0x5227, 0x5227,
+ 0x5227, 0x5227, 0x5227, 0x5228, 0x5228, 0x5228, 0x5228, 0x5228,
+ 0x5228, 0x5228, 0x5228, 0x5229, 0x5229, 0x5229, 0x5229, 0x5229,
+ 0x5229, 0x5229, 0x522a, 0x522a, 0x522a, 0x522a, 0x522a, 0x522a,
+ 0x522a, 0x522a, 0x522b, 0x522b, 0x522b, 0x522b, 0x522b, 0x522b,
+ 0x522b, 0x522c, 0x522c, 0x522c, 0x522c, 0x522c, 0x522c, 0x522c,
+ 0x522c, 0x522d, 0x522d, 0x522d, 0x522d, 0x522d, 0x522d, 0x522d,
+ 0x522e, 0x522e, 0x522e, 0x522e, 0x522e, 0x522e, 0x522e, 0x522e,
+ 0x522f, 0x522f, 0x522f, 0x522f, 0x522f, 0x522f, 0x522f, 0x5230,
+ 0x5230, 0x5230, 0x5230, 0x5230, 0x5230, 0x5230, 0x5230, 0x5231,
+ 0x5231, 0x5231, 0x5231, 0x5231, 0x5231, 0x5231, 0x5232, 0x5232,
+ 0x5232, 0x5232, 0x5232, 0x5232, 0x5232, 0x5232, 0x5233, 0x5233,
+ 0x5233, 0x5233, 0x5233, 0x5233, 0x5233, 0x5233, 0x5234, 0x5234,
+ 0x5234, 0x5234, 0x5234, 0x5234, 0x5234, 0x5234, 0x5235, 0x5235,
+ 0x5235, 0x5235, 0x5235, 0x5235, 0x5235, 0x5236, 0x5236, 0x5236,
+ 0x5236, 0x5236, 0x5236, 0x5236, 0x5236, 0x5237, 0x5237, 0x5237,
+ 0x5237, 0x5237, 0x5237, 0x5237, 0x5237, 0x5238, 0x5238, 0x5238,
+ 0x5238, 0x5238, 0x5238, 0x5238, 0x5238, 0x5239, 0x5239, 0x5239,
+ 0x5239, 0x5239, 0x5239, 0x5239, 0x5239, 0x523a, 0x523a, 0x523a,
+ 0x523a, 0x523a, 0x523a, 0x523a, 0x523a, 0x523b, 0x523b, 0x523b,
+ 0x523b, 0x523b, 0x523b, 0x523b, 0x523c, 0x523c, 0x523c, 0x523c,
+ 0x523c, 0x523c, 0x523c, 0x523c, 0x523d, 0x523d, 0x523d, 0x523d,
+ 0x523d, 0x523d, 0x523e, 0x523e, 0x523e, 0x523e, 0x523f, 0x523f,
+ 0x523f, 0x523f, 0x523f, 0x5240, 0x5240, 0x5240, 0x5240, 0x5241,
+ 0x5241, 0x5241, 0x5241, 0x5242, 0x5242, 0x5242, 0x5242, 0x5243,
+ 0x5243, 0x5243, 0x5243, 0x5244, 0x5244, 0x5244, 0x5244, 0x5245,
+ 0x5245, 0x5245, 0x5245, 0x5246, 0x5246, 0x5246, 0x5246, 0x5247,
+ 0x5247, 0x5247, 0x5247, 0x5248, 0x5248, 0x5248, 0x5248, 0x5248,
+ 0x5249, 0x5249, 0x5249, 0x5249, 0x524a, 0x524a, 0x524a, 0x524a,
+ 0x524b, 0x524b, 0x524b, 0x524b, 0x524c, 0x524c, 0x524c, 0x524c,
+ 0x524d, 0x524d, 0x524d, 0x524d, 0x524d, 0x524e, 0x524e, 0x524e,
+ 0x524e, 0x524f, 0x524f, 0x524f, 0x524f, 0x5250, 0x5250, 0x5250,
+ 0x5250, 0x5251, 0x5251, 0x5251, 0x5251, 0x5251, 0x5252, 0x5252,
+ 0x5252, 0x5252, 0x5253, 0x5253, 0x5253, 0x5253, 0x5253, 0x5254,
+ 0x5254, 0x5254, 0x5254, 0x5255, 0x5255, 0x5255, 0x5255, 0x5256,
+ 0x5256, 0x5256, 0x5256, 0x5256, 0x5257, 0x5257, 0x5257, 0x5257,
+ 0x5258, 0x5258, 0x5258, 0x5258, 0x5258, 0x5259, 0x5259, 0x5259,
+ 0x5259, 0x525a, 0x525a, 0x525a, 0x525a, 0x525a, 0x525b, 0x525b,
+ 0x525b, 0x525b, 0x525c, 0x525c, 0x525c, 0x525c, 0x525c, 0x525d,
+ 0x525d, 0x525d, 0x525d, 0x525e, 0x525e, 0x525e, 0x525e, 0x525e,
+ 0x525f, 0x525f, 0x525f, 0x525f, 0x5260, 0x5260, 0x5260, 0x5260,
+ 0x5260, 0x5261, 0x5261, 0x5261, 0x5261, 0x5262, 0x5262, 0x5262,
+ 0x5262, 0x5262, 0x5263, 0x5263, 0x5263, 0x5263, 0x5263, 0x5264,
+ 0x5264, 0x5264, 0x5264, 0x5265, 0x5265, 0x5265, 0x5265, 0x5265,
+ 0x5266, 0x5266, 0x5266, 0x5266, 0x5266, 0x5267, 0x5267, 0x5267,
+ 0x5267, 0x5268, 0x5268, 0x5268, 0x5268, 0x5268, 0x5269, 0x5269,
+ 0x5269, 0x5269, 0x5269, 0x526a, 0x526a, 0x526a, 0x526a, 0x526a,
+ 0x526b, 0x526b, 0x526b, 0x526b, 0x526c, 0x526c, 0x526c, 0x526c,
+ 0x526c, 0x526d, 0x526d, 0x526d, 0x526d, 0x526d, 0x526e, 0x526e,
+ 0x526e, 0x526e, 0x526e, 0x526f, 0x526f, 0x526f, 0x526f, 0x526f,
+ 0x5270, 0x5270, 0x5270, 0x5270, 0x5270, 0x5271, 0x5271, 0x5271,
+ 0x5271, 0x5271, 0x5272, 0x5272, 0x5272, 0x5272, 0x5273, 0x5273,
+ 0x5273, 0x5273, 0x5273, 0x5274, 0x5274, 0x5274, 0x5274, 0x5274,
+ 0x5275, 0x5275, 0x5275, 0x5275, 0x5275, 0x5276, 0x5276, 0x5276,
+ 0x5276, 0x5276, 0x5277, 0x5277, 0x5277, 0x5277, 0x5277, 0x5278,
+ 0x5278, 0x5278, 0x5278, 0x5278, 0x5279, 0x5279, 0x5279, 0x5279,
+ 0x5279, 0x527a, 0x527a, 0x527a, 0x527a, 0x527a, 0x527a, 0x527b,
+ 0x527b, 0x527b, 0x527b, 0x527b, 0x527c, 0x527c, 0x527c, 0x527c,
+ 0x527c, 0x527d, 0x527d, 0x527d, 0x527d, 0x527d, 0x527e, 0x527e,
+ 0x527e, 0x527e, 0x527e, 0x527f, 0x527f, 0x527f, 0x527f, 0x527f,
+ 0x5280, 0x5280, 0x5280, 0x5280, 0x5280, 0x5281, 0x5281, 0x5281,
+ 0x5281, 0x5281, 0x5281, 0x5282, 0x5282, 0x5282, 0x5282, 0x5282,
+ 0x5283, 0x5283, 0x5283, 0x5283, 0x5283, 0x5284, 0x5284, 0x5284,
+ 0x5284, 0x5284, 0x5285, 0x5285, 0x5285, 0x5285, 0x5285, 0x5285,
+ 0x5286, 0x5286, 0x5286, 0x5286, 0x5286, 0x5287, 0x5287, 0x5287,
+ 0x5287, 0x5287, 0x5288, 0x5288, 0x5288, 0x5288, 0x5288, 0x5288,
+ 0x5289, 0x5289, 0x5289, 0x5289, 0x5289, 0x528a, 0x528a, 0x528a,
+ 0x528a, 0x528a, 0x528b, 0x528b, 0x528b, 0x528b, 0x528b, 0x528b,
+ 0x528c, 0x528c, 0x528c, 0x528c, 0x528c, 0x528d, 0x528d, 0x528d,
+ 0x528d, 0x528d, 0x528d, 0x528e, 0x528e, 0x528e, 0x528e, 0x528e,
+ 0x528f, 0x528f, 0x528f, 0x528f, 0x528f, 0x528f, 0x5290, 0x5290,
+ 0x5290, 0x5290, 0x5290, 0x5291, 0x5291, 0x5291, 0x5291, 0x5291,
+ 0x5291, 0x5292, 0x5292, 0x5292, 0x5292, 0x5292, 0x5293, 0x5293,
+ 0x5293, 0x5293, 0x5293, 0x5293, 0x5294, 0x5294, 0x5294, 0x5294,
+ 0x5294, 0x5294, 0x5295, 0x5295, 0x5295, 0x5295, 0x5295, 0x5296,
+ 0x5296, 0x5296, 0x5296, 0x5296, 0x5296, 0x5297, 0x5297, 0x5297,
+ 0x5297, 0x5297, 0x5297, 0x5298, 0x5298, 0x5298, 0x5298, 0x5298,
+ 0x5299, 0x5299, 0x5299, 0x5299, 0x5299, 0x5299, 0x529a, 0x529a,
+ 0x529a, 0x529a, 0x529a, 0x529a, 0x529b, 0x529b, 0x529b, 0x529b,
+ 0x529b, 0x529b, 0x529c, 0x529c, 0x529c, 0x529c, 0x529c, 0x529d,
+ 0x529d, 0x529d, 0x529d, 0x529d, 0x529d, 0x529e, 0x529e, 0x529e,
+ 0x529e, 0x529e, 0x529e, 0x529f, 0x529f, 0x529f, 0x529f, 0x529f,
+ 0x529f, 0x52a0, 0x52a0, 0x52a0, 0x52a0, 0x52a0, 0x52a0, 0x52a1,
+ 0x52a1, 0x52a1, 0x52a1, 0x52a1, 0x52a1, 0x52a2, 0x52a2, 0x52a2,
+ 0x52a2, 0x52a2, 0x52a2, 0x52a3, 0x52a3, 0x52a3, 0x52a3, 0x52a3,
+ 0x52a3, 0x52a4, 0x52a4, 0x52a4, 0x52a4, 0x52a4, 0x52a4, 0x52a5,
+ 0x52a5, 0x52a5, 0x52a5, 0x52a5, 0x52a5, 0x52a6, 0x52a6, 0x52a6,
+ 0x52a6, 0x52a6, 0x52a6, 0x52a7, 0x52a7, 0x52a7, 0x52a7, 0x52a7,
+ 0x52a7, 0x52a8, 0x52a8, 0x52a8, 0x52a8, 0x52a8, 0x52a8, 0x52a9,
+ 0x52a9, 0x52a9, 0x52a9, 0x52a9, 0x52a9, 0x52aa, 0x52aa, 0x52aa,
+ 0x52aa, 0x52aa, 0x52aa, 0x52ab, 0x52ab, 0x52ab, 0x52ab, 0x52ab,
+ 0x52ab, 0x52ac, 0x52ac, 0x52ac, 0x52ac, 0x52ac, 0x52ac, 0x52ad,
+ 0x52ad, 0x52ad, 0x52ad, 0x52ad, 0x52ad, 0x52ad, 0x52ae, 0x52ae,
+ 0x52ae, 0x52ae, 0x52ae, 0x52ae, 0x52af, 0x52af, 0x52af, 0x52af,
+ 0x52af, 0x52af, 0x52b0, 0x52b0, 0x52b0, 0x52b0, 0x52b0, 0x52b0,
+ 0x52b1, 0x52b1, 0x52b1, 0x52b1, 0x52b1, 0x52b1, 0x52b1, 0x52b2,
+ 0x52b2, 0x52b2, 0x52b2, 0x52b2, 0x52b2, 0x52b3, 0x52b3, 0x52b3,
+ 0x52b3, 0x52b3, 0x52b3, 0x52b4, 0x52b4, 0x52b4, 0x52b4, 0x52b4,
+ 0x52b4, 0x52b4, 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x52b5, 0x52b5,
+ 0x52b6, 0x52b6, 0x52b6, 0x52b6, 0x52b6, 0x52b6, 0x52b7, 0x52b7,
+ 0x52b7, 0x52b7, 0x52b7, 0x52b7, 0x52b7, 0x52b8, 0x52b8, 0x52b8,
+ 0x52b8, 0x52b8, 0x52b8, 0x52b9, 0x52b9, 0x52b9, 0x52b9, 0x52b9,
+ 0x52b9, 0x52b9, 0x52ba, 0x52ba, 0x52ba, 0x52ba, 0x52ba, 0x52ba,
+ 0x52bb, 0x52bb, 0x52bb, 0x52bb, 0x52bb, 0x52bb, 0x52bb, 0x52bc,
+ 0x52bc, 0x52bc, 0x52bc, 0x52bc, 0x52bc, 0x52bd, 0x52bd, 0x52bd,
+ 0x52bd, 0x52bd, 0x52bd, 0x52bd, 0x52be, 0x52be, 0x52be, 0x52be,
+ 0x52be, 0x52be, 0x52be, 0x52bf, 0x52bf, 0x52bf, 0x52bf, 0x52bf,
+ 0x52bf, 0x52c0, 0x52c0, 0x52c0, 0x52c0, 0x52c0, 0x52c0, 0x52c0,
+ 0x52c1, 0x52c1, 0x52c1, 0x52c1, 0x52c1, 0x52c1, 0x52c1, 0x52c2,
+ 0x52c2, 0x52c2, 0x52c2, 0x52c2, 0x52c2, 0x52c3, 0x52c3, 0x52c3,
+ 0x52c3, 0x52c3, 0x52c3, 0x52c3, 0x52c4, 0x52c4, 0x52c4, 0x52c4,
+ 0x52c4, 0x52c4, 0x52c4, 0x52c5, 0x52c5, 0x52c5, 0x52c5, 0x52c5,
+ 0x52c5, 0x52c5, 0x52c6, 0x52c6, 0x52c6, 0x52c6, 0x52c6, 0x52c6,
+ 0x52c6, 0x52c7, 0x52c7, 0x52c7, 0x52c7, 0x52c7, 0x52c7, 0x52c8,
+ 0x52c8, 0x52c8, 0x52c8, 0x52c8, 0x52c8, 0x52c8, 0x52c9, 0x52c9,
+ 0x52c9, 0x52c9, 0x52c9, 0x52c9, 0x52c9, 0x52ca, 0x52ca, 0x52ca,
+ 0x52ca, 0x52ca, 0x52ca, 0x52ca, 0x52cb, 0x52cb, 0x52cb, 0x52cb,
+ 0x52cb, 0x52cb, 0x52cb, 0x52cc, 0x52cc, 0x52cc, 0x52cc, 0x52cc,
+ 0x52cc, 0x52cc, 0x52cd, 0x52cd, 0x52cd, 0x52cd, 0x52cd, 0x52cd,
+ 0x52cd, 0x52ce, 0x52ce, 0x52ce, 0x52ce, 0x52ce, 0x52ce, 0x52ce,
+ 0x52cf, 0x52cf, 0x52cf, 0x52cf, 0x52cf, 0x52cf, 0x52cf, 0x52d0,
+ 0x52d0, 0x52d0, 0x52d0, 0x52d0, 0x52d0, 0x52d0, 0x52d1, 0x52d1,
+ 0x52d1, 0x52d1, 0x52d1, 0x52d1, 0x52d1, 0x52d2, 0x52d2, 0x52d2,
+ 0x52d2, 0x52d2, 0x52d2, 0x52d2, 0x52d2, 0x52d3, 0x52d3, 0x52d3,
+ 0x52d3, 0x52d3, 0x52d3, 0x52d3, 0x52d4, 0x52d4, 0x52d4, 0x52d4,
+ 0x52d4, 0x52d4, 0x52d4, 0x52d5, 0x52d5, 0x52d5, 0x52d5, 0x52d5,
+ 0x52d5, 0x52d5, 0x52d6, 0x52d6, 0x52d6, 0x52d6, 0x52d6, 0x52d6,
+ 0x52d6, 0x52d6, 0x52d7, 0x52d7, 0x52d7, 0x52d7, 0x52d7, 0x52d7,
+ 0x52d7, 0x52d8, 0x52d8, 0x52d8, 0x52d8, 0x52d8, 0x52d8, 0x52d8,
+ 0x52d9, 0x52d9, 0x52d9, 0x52d9, 0x52d9, 0x52d9, 0x52d9, 0x52d9,
+ 0x52da, 0x52da, 0x52da, 0x52da, 0x52da, 0x52da, 0x52da, 0x52db,
+ 0x52db, 0x52db, 0x52db, 0x52db, 0x52db, 0x52db, 0x52dc, 0x52dc,
+ 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dc, 0x52dd, 0x52dd,
+ 0x52dd, 0x52dd, 0x52dd, 0x52dd, 0x52dd, 0x52de, 0x52de, 0x52de,
+ 0x52de, 0x52de, 0x52de, 0x52de, 0x52de, 0x52df, 0x52df, 0x52df,
+ 0x52df, 0x52df, 0x52df, 0x52df, 0x52e0, 0x52e0, 0x52e0, 0x52e0,
+ 0x52e0, 0x52e0, 0x52e0, 0x52e0, 0x52e1, 0x52e1, 0x52e1, 0x52e1,
+ 0x52e1, 0x52e1, 0x52e1, 0x52e2, 0x52e2, 0x52e2, 0x52e2, 0x52e2,
+ 0x52e2, 0x52e2, 0x52e2, 0x52e3, 0x52e3, 0x52e3, 0x52e3, 0x52e3,
+ 0x52e3, 0x52e3, 0x52e3, 0x52e4, 0x52e4, 0x52e4, 0x52e4, 0x52e4,
+ 0x52e4, 0x52e4, 0x52e5, 0x52e5, 0x52e5, 0x52e5, 0x52e5, 0x52e5,
+ 0x52e5, 0x52e5, 0x52e6, 0x52e6, 0x52e6, 0x52e6, 0x52e6, 0x52e6,
+ 0x52e6, 0x52e6, 0x52e7, 0x52e7, 0x52e7, 0x52e7, 0x52e7, 0x52e7,
+ 0x52e7, 0x52e7, 0x52e8, 0x52e8, 0x52e8, 0x52e8, 0x52e8, 0x52e8,
+ 0x52e8, 0x52e9, 0x52e9, 0x52e9, 0x52e9, 0x52e9, 0x52e9, 0x52e9,
+ 0x52e9, 0x52ea, 0x52ea, 0x52ea, 0x52ea, 0x52ea, 0x52ea, 0x52ea,
+ 0x52ea, 0x52eb, 0x52eb, 0x52eb, 0x52eb, 0x52eb, 0x52eb, 0x52eb,
+ 0x52eb, 0x52ec, 0x52ec, 0x52ec, 0x52ec, 0x52ec, 0x52ec, 0x52ec,
+ 0x52ec, 0x52ed, 0x52ed, 0x52ed, 0x52ed, 0x52ed, 0x52ed, 0x52ed,
+ 0x52ed, 0x52ee, 0x52ee, 0x52ee, 0x52ee, 0x52ee, 0x52ee, 0x52ee,
+ 0x52ee, 0x52ef, 0x52ef, 0x52ef, 0x52ef, 0x52f0, 0x52f0, 0x52f0,
+ 0x52f0, 0x52f1, 0x52f1, 0x52f1, 0x52f1, 0x52f2, 0x52f2, 0x52f2,
+ 0x52f2, 0x52f3, 0x52f3, 0x52f3, 0x52f3, 0x52f4, 0x52f4, 0x52f4,
+ 0x52f4, 0x52f5, 0x52f5, 0x52f5, 0x52f5, 0x52f6, 0x52f6, 0x52f6,
+ 0x52f6, 0x52f7, 0x52f7, 0x52f7, 0x52f7, 0x52f8, 0x52f8, 0x52f8,
+ 0x52f8, 0x52f9, 0x52f9, 0x52f9, 0x52f9, 0x52f9, 0x52fa, 0x52fa,
+ 0x52fa, 0x52fa, 0x52fb, 0x52fb, 0x52fb, 0x52fb, 0x52fc, 0x52fc,
+ 0x52fc, 0x52fc, 0x52fd, 0x52fd, 0x52fd, 0x52fd, 0x52fe, 0x52fe,
+ 0x52fe, 0x52fe, 0x52fe, 0x52ff, 0x52ff, 0x52ff, 0x52ff, 0x5300,
+ 0x5300, 0x5300, 0x5300, 0x5301, 0x5301, 0x5301, 0x5301, 0x5301,
+ 0x5302, 0x5302, 0x5302, 0x5302, 0x5303, 0x5303, 0x5303, 0x5303,
+ 0x5304, 0x5304, 0x5304, 0x5304, 0x5304, 0x5305, 0x5305, 0x5305,
+ 0x5305, 0x5306, 0x5306, 0x5306, 0x5306, 0x5307, 0x5307, 0x5307,
+ 0x5307, 0x5307, 0x5308, 0x5308, 0x5308, 0x5308, 0x5309, 0x5309,
+ 0x5309, 0x5309, 0x5309, 0x530a, 0x530a, 0x530a, 0x530a, 0x530b,
+ 0x530b, 0x530b, 0x530b, 0x530b, 0x530c, 0x530c, 0x530c, 0x530c,
+ 0x530d, 0x530d, 0x530d, 0x530d, 0x530d, 0x530e, 0x530e, 0x530e,
+ 0x530e, 0x530f, 0x530f, 0x530f, 0x530f, 0x530f, 0x5310, 0x5310,
+ 0x5310, 0x5310, 0x5311, 0x5311, 0x5311, 0x5311, 0x5311, 0x5312,
+ 0x5312, 0x5312, 0x5312, 0x5313, 0x5313, 0x5313, 0x5313, 0x5313,
+ 0x5314, 0x5314, 0x5314, 0x5314, 0x5314, 0x5315, 0x5315, 0x5315,
+ 0x5315, 0x5316, 0x5316, 0x5316, 0x5316, 0x5316, 0x5317, 0x5317,
+ 0x5317, 0x5317, 0x5317, 0x5318, 0x5318, 0x5318, 0x5318, 0x5319,
+ 0x5319, 0x5319, 0x5319, 0x5319, 0x531a, 0x531a, 0x531a, 0x531a,
+ 0x531a, 0x531b, 0x531b, 0x531b, 0x531b, 0x531c, 0x531c, 0x531c,
+ 0x531c, 0x531c, 0x531d, 0x531d, 0x531d, 0x531d, 0x531d, 0x531e,
+ 0x531e, 0x531e, 0x531e, 0x531e, 0x531f, 0x531f, 0x531f, 0x531f,
+ 0x531f, 0x5320, 0x5320, 0x5320, 0x5320, 0x5320, 0x5321, 0x5321,
+ 0x5321, 0x5321, 0x5322, 0x5322, 0x5322, 0x5322, 0x5322, 0x5323,
+ 0x5323, 0x5323, 0x5323, 0x5323, 0x5324, 0x5324, 0x5324, 0x5324,
+ 0x5324, 0x5325, 0x5325, 0x5325, 0x5325, 0x5325, 0x5326, 0x5326,
+ 0x5326, 0x5326, 0x5326, 0x5327, 0x5327, 0x5327, 0x5327, 0x5327,
+ 0x5328, 0x5328, 0x5328, 0x5328, 0x5328, 0x5329, 0x5329, 0x5329,
+ 0x5329, 0x5329, 0x532a, 0x532a, 0x532a, 0x532a, 0x532a, 0x532b,
+ 0x532b, 0x532b, 0x532b, 0x532b, 0x532c, 0x532c, 0x532c, 0x532c,
+ 0x532c, 0x532d, 0x532d, 0x532d, 0x532d, 0x532d, 0x532e, 0x532e,
+ 0x532e, 0x532e, 0x532e, 0x532e, 0x532f, 0x532f, 0x532f, 0x532f,
+ 0x532f, 0x5330, 0x5330, 0x5330, 0x5330, 0x5330, 0x5331, 0x5331,
+ 0x5331, 0x5331, 0x5331, 0x5332, 0x5332, 0x5332, 0x5332, 0x5332,
+ 0x5333, 0x5333, 0x5333, 0x5333, 0x5333, 0x5333, 0x5334, 0x5334,
+ 0x5334, 0x5334, 0x5334, 0x5335, 0x5335, 0x5335, 0x5335, 0x5335,
+ 0x5336, 0x5336, 0x5336, 0x5336, 0x5336, 0x5337, 0x5337, 0x5337,
+ 0x5337, 0x5337, 0x5337, 0x5338, 0x5338, 0x5338, 0x5338, 0x5338,
+ 0x5339, 0x5339, 0x5339, 0x5339, 0x5339, 0x533a, 0x533a, 0x533a,
+ 0x533a, 0x533a, 0x533a, 0x533b, 0x533b, 0x533b, 0x533b, 0x533b,
+ 0x533c, 0x533c, 0x533c, 0x533c, 0x533c, 0x533d, 0x533d, 0x533d,
+ 0x533d, 0x533d, 0x533d, 0x533e, 0x533e, 0x533e, 0x533e, 0x533e,
+ 0x533f, 0x533f, 0x533f, 0x533f, 0x533f, 0x533f, 0x5340, 0x5340,
+ 0x5340, 0x5340, 0x5340, 0x5341, 0x5341, 0x5341, 0x5341, 0x5341,
+ 0x5341, 0x5342, 0x5342, 0x5342, 0x5342, 0x5342, 0x5343, 0x5343,
+ 0x5343, 0x5343, 0x5343, 0x5343, 0x5344, 0x5344, 0x5344, 0x5344,
+ 0x5344, 0x5344, 0x5345, 0x5345, 0x5345, 0x5345, 0x5345, 0x5346,
+ 0x5346, 0x5346, 0x5346, 0x5346, 0x5346, 0x5347, 0x5347, 0x5347,
+ 0x5347, 0x5347, 0x5348, 0x5348, 0x5348, 0x5348, 0x5348, 0x5348,
+ 0x5349, 0x5349, 0x5349, 0x5349, 0x5349, 0x5349, 0x534a, 0x534a,
+ 0x534a, 0x534a, 0x534a, 0x534a, 0x534b, 0x534b, 0x534b, 0x534b,
+ 0x534b, 0x534c, 0x534c, 0x534c, 0x534c, 0x534c, 0x534c, 0x534d,
+ 0x534d, 0x534d, 0x534d, 0x534d, 0x534d, 0x534e, 0x534e, 0x534e,
+ 0x534e, 0x534e, 0x534e, 0x534f, 0x534f, 0x534f, 0x534f, 0x534f,
+ 0x5350, 0x5350, 0x5350, 0x5350, 0x5350, 0x5350, 0x5351, 0x5351,
+ 0x5351, 0x5351, 0x5351, 0x5351, 0x5352, 0x5352, 0x5352, 0x5352,
+ 0x5352, 0x5352, 0x5353, 0x5353, 0x5353, 0x5353, 0x5353, 0x5353,
+ 0x5354, 0x5354, 0x5354, 0x5354, 0x5354, 0x5354, 0x5355, 0x5355,
+ 0x5355, 0x5355, 0x5355, 0x5355, 0x5356, 0x5356, 0x5356, 0x5356,
+ 0x5356, 0x5356, 0x5357, 0x5357, 0x5357, 0x5357, 0x5357, 0x5357,
+ 0x5358, 0x5358, 0x5358, 0x5358, 0x5358, 0x5358, 0x5359, 0x5359,
+ 0x5359, 0x5359, 0x5359, 0x5359, 0x535a, 0x535a, 0x535a, 0x535a,
+ 0x535a, 0x535a, 0x535b, 0x535b, 0x535b, 0x535b, 0x535b, 0x535b,
+ 0x535c, 0x535c, 0x535c, 0x535c, 0x535c, 0x535c, 0x535d, 0x535d,
+ 0x535d, 0x535d, 0x535d, 0x535d, 0x535d, 0x535e, 0x535e, 0x535e,
+ 0x535e, 0x535e, 0x535e, 0x535f, 0x535f, 0x535f, 0x535f, 0x535f,
+ 0x535f, 0x5360, 0x5360, 0x5360, 0x5360, 0x5360, 0x5360, 0x5361,
+ 0x5361, 0x5361, 0x5361, 0x5361, 0x5361, 0x5362, 0x5362, 0x5362,
+ 0x5362, 0x5362, 0x5362, 0x5362, 0x5363, 0x5363, 0x5363, 0x5363,
+ 0x5363, 0x5363, 0x5364, 0x5364, 0x5364, 0x5364, 0x5364, 0x5364,
+ 0x5365, 0x5365, 0x5365, 0x5365, 0x5365, 0x5365, 0x5365, 0x5366,
+ 0x5366, 0x5366, 0x5366, 0x5366, 0x5366, 0x5367, 0x5367, 0x5367,
+ 0x5367, 0x5367, 0x5367, 0x5367, 0x5368, 0x5368, 0x5368, 0x5368,
+ 0x5368, 0x5368, 0x5369, 0x5369, 0x5369, 0x5369, 0x5369, 0x5369,
+ 0x536a, 0x536a, 0x536a, 0x536a, 0x536a, 0x536a, 0x536a, 0x536b,
+ 0x536b, 0x536b, 0x536b, 0x536b, 0x536b, 0x536c, 0x536c, 0x536c,
+ 0x536c, 0x536c, 0x536c, 0x536c, 0x536d, 0x536d, 0x536d, 0x536d,
+ 0x536d, 0x536d, 0x536e, 0x536e, 0x536e, 0x536e, 0x536e, 0x536e,
+ 0x536e, 0x536f, 0x536f, 0x536f, 0x536f, 0x536f, 0x536f, 0x536f,
+ 0x5370, 0x5370, 0x5370, 0x5370, 0x5370, 0x5370, 0x5371, 0x5371,
+ 0x5371, 0x5371, 0x5371, 0x5371, 0x5371, 0x5372, 0x5372, 0x5372,
+ 0x5372, 0x5372, 0x5372, 0x5372, 0x5373, 0x5373, 0x5373, 0x5373,
+ 0x5373, 0x5373, 0x5374, 0x5374, 0x5374, 0x5374, 0x5374, 0x5374,
+ 0x5374, 0x5375, 0x5375, 0x5375, 0x5375, 0x5375, 0x5375, 0x5375,
+ 0x5376, 0x5376, 0x5376, 0x5376, 0x5376, 0x5376, 0x5376, 0x5377,
+ 0x5377, 0x5377, 0x5377, 0x5377, 0x5377, 0x5378, 0x5378, 0x5378,
+ 0x5378, 0x5378, 0x5378, 0x5378, 0x5379, 0x5379, 0x5379, 0x5379,
+ 0x5379, 0x5379, 0x5379, 0x537a, 0x537a, 0x537a, 0x537a, 0x537a,
+ 0x537a, 0x537a, 0x537b, 0x537b, 0x537b, 0x537b, 0x537b, 0x537b,
+ 0x537b, 0x537c, 0x537c, 0x537c, 0x537c, 0x537c, 0x537c, 0x537c,
+ 0x537d, 0x537d, 0x537d, 0x537d, 0x537d, 0x537d, 0x537d, 0x537e,
+ 0x537e, 0x537e, 0x537e, 0x537e, 0x537e, 0x537e, 0x537f, 0x537f,
+ 0x537f, 0x537f, 0x537f, 0x537f, 0x537f, 0x5380, 0x5380, 0x5380,
+ 0x5380, 0x5380, 0x5380, 0x5380, 0x5381, 0x5381, 0x5381, 0x5381,
+ 0x5381, 0x5381, 0x5381, 0x5382, 0x5382, 0x5382, 0x5382, 0x5382,
+ 0x5382, 0x5382, 0x5383, 0x5383, 0x5383, 0x5383, 0x5383, 0x5383,
+ 0x5383, 0x5384, 0x5384, 0x5384, 0x5384, 0x5384, 0x5384, 0x5384,
+ 0x5384, 0x5385, 0x5385, 0x5385, 0x5385, 0x5385, 0x5385, 0x5385,
+ 0x5386, 0x5386, 0x5386, 0x5386, 0x5386, 0x5386, 0x5386, 0x5387,
+ 0x5387, 0x5387, 0x5387, 0x5387, 0x5387, 0x5387, 0x5388, 0x5388,
+ 0x5388, 0x5388, 0x5388, 0x5388, 0x5388, 0x5388, 0x5389, 0x5389,
+ 0x5389, 0x5389, 0x5389, 0x5389, 0x5389, 0x538a, 0x538a, 0x538a,
+ 0x538a, 0x538a, 0x538a, 0x538a, 0x538b, 0x538b, 0x538b, 0x538b,
+ 0x538b, 0x538b, 0x538b, 0x538b, 0x538c, 0x538c, 0x538c, 0x538c,
+ 0x538c, 0x538c, 0x538c, 0x538d, 0x538d, 0x538d, 0x538d, 0x538d,
+ 0x538d, 0x538d, 0x538e, 0x538e, 0x538e, 0x538e, 0x538e, 0x538e,
+ 0x538e, 0x538e, 0x538f, 0x538f, 0x538f, 0x538f, 0x538f, 0x538f,
+ 0x538f, 0x5390, 0x5390, 0x5390, 0x5390, 0x5390, 0x5390, 0x5390,
+ 0x5390, 0x5391, 0x5391, 0x5391, 0x5391, 0x5391, 0x5391, 0x5391,
+ 0x5392, 0x5392, 0x5392, 0x5392, 0x5392, 0x5392, 0x5392, 0x5392,
+ 0x5393, 0x5393, 0x5393, 0x5393, 0x5393, 0x5393, 0x5393, 0x5393,
+ 0x5394, 0x5394, 0x5394, 0x5394, 0x5394, 0x5394, 0x5394, 0x5395,
+ 0x5395, 0x5395, 0x5395, 0x5395, 0x5395, 0x5395, 0x5395, 0x5396,
+ 0x5396, 0x5396, 0x5396, 0x5396, 0x5396, 0x5396, 0x5396, 0x5397,
+ 0x5397, 0x5397, 0x5397, 0x5397, 0x5397, 0x5397, 0x5398, 0x5398,
+ 0x5398, 0x5398, 0x5398, 0x5398, 0x5398, 0x5398, 0x5399, 0x5399,
+ 0x5399, 0x5399, 0x5399, 0x5399, 0x5399, 0x5399, 0x539a, 0x539a,
+ 0x539a, 0x539a, 0x539a, 0x539a, 0x539a, 0x539a, 0x539b, 0x539b,
+ 0x539b, 0x539b, 0x539b, 0x539b, 0x539b, 0x539b, 0x539c, 0x539c,
+ 0x539c, 0x539c, 0x539c, 0x539c, 0x539c, 0x539d, 0x539d, 0x539d,
+ 0x539d, 0x539d, 0x539d, 0x539d, 0x539d, 0x539e, 0x539e, 0x539e,
+ 0x539e, 0x539e, 0x539e, 0x539e, 0x539e, 0x539f, 0x539f, 0x539f,
+ 0x539f, 0x539f, 0x539f, 0x539f, 0x539f, 0x53a0, 0x53a0, 0x53a0,
+ 0x53a0, 0x53a0, 0x53a0, 0x53a1, 0x53a1, 0x53a1, 0x53a1, 0x53a2,
+ 0x53a2, 0x53a2, 0x53a2, 0x53a3, 0x53a3, 0x53a3, 0x53a3, 0x53a4,
+ 0x53a4, 0x53a4, 0x53a4, 0x53a5, 0x53a5, 0x53a5, 0x53a5, 0x53a6,
+ 0x53a6, 0x53a6, 0x53a6, 0x53a7, 0x53a7, 0x53a7, 0x53a7, 0x53a8,
+ 0x53a8, 0x53a8, 0x53a8, 0x53a9, 0x53a9, 0x53a9, 0x53a9, 0x53a9,
+ 0x53aa, 0x53aa, 0x53aa, 0x53aa, 0x53ab, 0x53ab, 0x53ab, 0x53ab,
+ 0x53ac, 0x53ac, 0x53ac, 0x53ac, 0x53ad, 0x53ad, 0x53ad, 0x53ad,
+ 0x53ae, 0x53ae, 0x53ae, 0x53ae, 0x53ae, 0x53af, 0x53af, 0x53af,
+ 0x53af, 0x53b0, 0x53b0, 0x53b0, 0x53b0, 0x53b1, 0x53b1, 0x53b1,
+ 0x53b1, 0x53b2, 0x53b2, 0x53b2, 0x53b2, 0x53b2, 0x53b3, 0x53b3,
+ 0x53b3, 0x53b3, 0x53b4, 0x53b4, 0x53b4, 0x53b4, 0x53b5, 0x53b5,
+ 0x53b5, 0x53b5, 0x53b5, 0x53b6, 0x53b6, 0x53b6, 0x53b6, 0x53b7,
+ 0x53b7, 0x53b7, 0x53b7, 0x53b8, 0x53b8, 0x53b8, 0x53b8, 0x53b8,
+ 0x53b9, 0x53b9, 0x53b9, 0x53b9, 0x53ba, 0x53ba, 0x53ba, 0x53ba,
+ 0x53ba, 0x53bb, 0x53bb, 0x53bb, 0x53bb, 0x53bc, 0x53bc, 0x53bc,
+ 0x53bc, 0x53bc, 0x53bd, 0x53bd, 0x53bd, 0x53bd, 0x53be, 0x53be,
+ 0x53be, 0x53be, 0x53be, 0x53bf, 0x53bf, 0x53bf, 0x53bf, 0x53c0,
+ 0x53c0, 0x53c0, 0x53c0, 0x53c0, 0x53c1, 0x53c1, 0x53c1, 0x53c1,
+ 0x53c2, 0x53c2, 0x53c2, 0x53c2, 0x53c2, 0x53c3, 0x53c3, 0x53c3,
+ 0x53c3, 0x53c4, 0x53c4, 0x53c4, 0x53c4, 0x53c4, 0x53c5, 0x53c5,
+ 0x53c5, 0x53c5, 0x53c6, 0x53c6, 0x53c6, 0x53c6, 0x53c6, 0x53c7,
+ 0x53c7, 0x53c7, 0x53c7, 0x53c7, 0x53c8, 0x53c8, 0x53c8, 0x53c8,
+ 0x53c9, 0x53c9, 0x53c9, 0x53c9, 0x53c9, 0x53ca, 0x53ca, 0x53ca,
+ 0x53ca, 0x53ca, 0x53cb, 0x53cb, 0x53cb, 0x53cb, 0x53cb, 0x53cc,
+ 0x53cc, 0x53cc, 0x53cc, 0x53cd, 0x53cd, 0x53cd, 0x53cd, 0x53cd,
+ 0x53ce, 0x53ce, 0x53ce, 0x53ce, 0x53ce, 0x53cf, 0x53cf, 0x53cf,
+ 0x53cf, 0x53cf, 0x53d0, 0x53d0, 0x53d0, 0x53d0, 0x53d0, 0x53d1,
+ 0x53d1, 0x53d1, 0x53d1, 0x53d2, 0x53d2, 0x53d2, 0x53d2, 0x53d2,
+ 0x53d3, 0x53d3, 0x53d3, 0x53d3, 0x53d3, 0x53d4, 0x53d4, 0x53d4,
+ 0x53d4, 0x53d4, 0x53d5, 0x53d5, 0x53d5, 0x53d5, 0x53d5, 0x53d6,
+ 0x53d6, 0x53d6, 0x53d6, 0x53d6, 0x53d7, 0x53d7, 0x53d7, 0x53d7,
+ 0x53d7, 0x53d8, 0x53d8, 0x53d8, 0x53d8, 0x53d8, 0x53d9, 0x53d9,
+ 0x53d9, 0x53d9, 0x53d9, 0x53da, 0x53da, 0x53da, 0x53da, 0x53da,
+ 0x53db, 0x53db, 0x53db, 0x53db, 0x53db, 0x53dc, 0x53dc, 0x53dc,
+ 0x53dc, 0x53dc, 0x53dd, 0x53dd, 0x53dd, 0x53dd, 0x53dd, 0x53de,
+ 0x53de, 0x53de, 0x53de, 0x53de, 0x53df, 0x53df, 0x53df, 0x53df,
+ 0x53df, 0x53e0, 0x53e0, 0x53e0, 0x53e0, 0x53e0, 0x53e1, 0x53e1,
+ 0x53e1, 0x53e1, 0x53e1, 0x53e1, 0x53e2, 0x53e2, 0x53e2, 0x53e2,
+ 0x53e2, 0x53e3, 0x53e3, 0x53e3, 0x53e3, 0x53e3, 0x53e4, 0x53e4,
+ 0x53e4, 0x53e4, 0x53e4, 0x53e5, 0x53e5, 0x53e5, 0x53e5, 0x53e5,
+ 0x53e6, 0x53e6, 0x53e6, 0x53e6, 0x53e6, 0x53e6, 0x53e7, 0x53e7,
+ 0x53e7, 0x53e7, 0x53e7, 0x53e8, 0x53e8, 0x53e8, 0x53e8, 0x53e8,
+ 0x53e9, 0x53e9, 0x53e9, 0x53e9, 0x53e9, 0x53e9, 0x53ea, 0x53ea,
+ 0x53ea, 0x53ea, 0x53ea, 0x53eb, 0x53eb, 0x53eb, 0x53eb, 0x53eb,
+ 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ec, 0x53ed, 0x53ed,
+ 0x53ed, 0x53ed, 0x53ed, 0x53ee, 0x53ee, 0x53ee, 0x53ee, 0x53ee,
+ 0x53ef, 0x53ef, 0x53ef, 0x53ef, 0x53ef, 0x53ef, 0x53f0, 0x53f0,
+ 0x53f0, 0x53f0, 0x53f0, 0x53f1, 0x53f1, 0x53f1, 0x53f1, 0x53f1,
+ 0x53f1, 0x53f2, 0x53f2, 0x53f2, 0x53f2, 0x53f2, 0x53f3, 0x53f3,
+ 0x53f3, 0x53f3, 0x53f3, 0x53f3, 0x53f4, 0x53f4, 0x53f4, 0x53f4,
+ 0x53f4, 0x53f4, 0x53f5, 0x53f5, 0x53f5, 0x53f5, 0x53f5, 0x53f6,
+ 0x53f6, 0x53f6, 0x53f6, 0x53f6, 0x53f6, 0x53f7, 0x53f7, 0x53f7,
+ 0x53f7, 0x53f7, 0x53f8, 0x53f8, 0x53f8, 0x53f8, 0x53f8, 0x53f8,
+ 0x53f9, 0x53f9, 0x53f9, 0x53f9, 0x53f9, 0x53f9, 0x53fa, 0x53fa,
+ 0x53fa, 0x53fa, 0x53fa, 0x53fb, 0x53fb, 0x53fb, 0x53fb, 0x53fb,
+ 0x53fb, 0x53fc, 0x53fc, 0x53fc, 0x53fc, 0x53fc, 0x53fc, 0x53fd,
+ 0x53fd, 0x53fd, 0x53fd, 0x53fd, 0x53fe, 0x53fe, 0x53fe, 0x53fe,
+ 0x53fe, 0x53fe, 0x53ff, 0x53ff, 0x53ff, 0x53ff, 0x53ff, 0x53ff,
+ 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400,
+ 0x5400, 0x5401, 0x5401, 0x5401, 0x5401, 0x5401, 0x5401, 0x5401,
+ 0x5401, 0x5401, 0x5401, 0x5401, 0x5401, 0x5402, 0x5402, 0x5402,
+ 0x5402, 0x5402, 0x5402, 0x5402, 0x5402, 0x5402, 0x5402, 0x5402,
+ 0x5403, 0x5403, 0x5403, 0x5403, 0x5403, 0x5403, 0x5403, 0x5403,
+ 0x5403, 0x5403, 0x5403, 0x5403, 0x5404, 0x5404, 0x5404, 0x5404,
+ 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404, 0x5404,
+ 0x5405, 0x5405, 0x5405, 0x5405, 0x5405, 0x5405, 0x5405, 0x5405,
+ 0x5405, 0x5405, 0x5405, 0x5405, 0x5406, 0x5406, 0x5406, 0x5406,
+ 0x5406, 0x5406, 0x5406, 0x5406, 0x5406, 0x5406, 0x5406, 0x5406,
+ 0x5406, 0x5407, 0x5407, 0x5407, 0x5407, 0x5407, 0x5407, 0x5407,
+ 0x5407, 0x5407, 0x5407, 0x5407, 0x5407, 0x5408, 0x5408, 0x5408,
+ 0x5408, 0x5408, 0x5408, 0x5408, 0x5408, 0x5408, 0x5408, 0x5408,
+ 0x5408, 0x5409, 0x5409, 0x5409, 0x5409, 0x5409, 0x5409, 0x5409,
+ 0x5409, 0x5409, 0x5409, 0x5409, 0x5409, 0x5409, 0x540a, 0x540a,
+ 0x540a, 0x540a, 0x540a, 0x540a, 0x540a, 0x540a, 0x540a, 0x540a,
+ 0x540a, 0x540a, 0x540b, 0x540b, 0x540b, 0x540b, 0x540b, 0x540b,
+ 0x540b, 0x540b, 0x540b, 0x540b, 0x540b, 0x540b, 0x540b, 0x540c,
+ 0x540c, 0x540c, 0x540c, 0x540c, 0x540c, 0x540c, 0x540c, 0x540c,
+ 0x540c, 0x540c, 0x540c, 0x540c, 0x540d, 0x540d, 0x540d, 0x540d,
+ 0x540d, 0x540d, 0x540d, 0x540d, 0x540d, 0x540d, 0x540d, 0x540d,
+ 0x540d, 0x540e, 0x540e, 0x540e, 0x540e, 0x540e, 0x540e, 0x540e,
+ 0x540e, 0x540e, 0x540e, 0x540e, 0x540e, 0x540e, 0x540f, 0x540f,
+ 0x540f, 0x540f, 0x540f, 0x540f, 0x540f, 0x540f, 0x540f, 0x540f,
+ 0x540f, 0x540f, 0x540f, 0x5410, 0x5410, 0x5410, 0x5410, 0x5410,
+ 0x5410, 0x5410, 0x5410, 0x5410, 0x5410, 0x5410, 0x5410, 0x5410,
+ 0x5411, 0x5411, 0x5411, 0x5411, 0x5411, 0x5411, 0x5411, 0x5411,
+ 0x5411, 0x5411, 0x5411, 0x5411, 0x5411, 0x5412, 0x5412, 0x5412,
+ 0x5412, 0x5412, 0x5412, 0x5412, 0x5412, 0x5412, 0x5412, 0x5412,
+ 0x5412, 0x5412, 0x5412, 0x5413, 0x5413, 0x5413, 0x5413, 0x5413,
+ 0x5413, 0x5413, 0x5413, 0x5413, 0x5413, 0x5413, 0x5413, 0x5413,
+ 0x5414, 0x5414, 0x5414, 0x5414, 0x5414, 0x5414, 0x5414, 0x5414,
+ 0x5414, 0x5414, 0x5414, 0x5414, 0x5414, 0x5414, 0x5415, 0x5415,
+ 0x5415, 0x5415, 0x5415, 0x5415, 0x5415, 0x5415, 0x5415, 0x5415,
+ 0x5415, 0x5415, 0x5415, 0x5415, 0x5416, 0x5416, 0x5416, 0x5416,
+ 0x5416, 0x5416, 0x5416, 0x5416, 0x5416, 0x5416, 0x5416, 0x5416,
+ 0x5416, 0x5417, 0x5417, 0x5417, 0x5417, 0x5417, 0x5417, 0x5417,
+ 0x5417, 0x5417, 0x5417, 0x5417, 0x5417, 0x5417, 0x5417, 0x5418,
+ 0x5418, 0x5418, 0x5418, 0x5418, 0x5418, 0x5418, 0x5418, 0x5418,
+ 0x5418, 0x5418, 0x5418, 0x5418, 0x5418, 0x5419, 0x5419, 0x5419,
+ 0x5419, 0x5419, 0x5419, 0x5419, 0x5419, 0x5419, 0x5419, 0x5419,
+ 0x5419, 0x5419, 0x5419, 0x5419, 0x541a, 0x541a, 0x541a, 0x541a,
+ 0x541a, 0x541a, 0x541a, 0x541a, 0x541a, 0x541a, 0x541a, 0x541a,
+ 0x541a, 0x541a, 0x541b, 0x541b, 0x541b, 0x541b, 0x541b, 0x541b,
+ 0x541b, 0x541b, 0x541b, 0x541b, 0x541b, 0x541b, 0x541b, 0x541b,
+ 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541c,
+ 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541c, 0x541d,
+ 0x541d, 0x541d, 0x541d, 0x541d, 0x541d, 0x541d, 0x541d, 0x541d,
+ 0x541d, 0x541d, 0x541d, 0x541d, 0x541d, 0x541e, 0x541e, 0x541e,
+ 0x541e, 0x541e, 0x541e, 0x541e, 0x541e, 0x541e, 0x541e, 0x541e,
+ 0x541e, 0x541e, 0x541e, 0x541e, 0x541f, 0x541f, 0x541f, 0x541f,
+ 0x541f, 0x541f, 0x541f, 0x541f, 0x541f, 0x541f, 0x541f, 0x541f,
+ 0x541f, 0x541f, 0x541f, 0x5420, 0x5420, 0x5420, 0x5420, 0x5420,
+ 0x5420, 0x5420, 0x5420, 0x5420, 0x5420, 0x5420, 0x5420, 0x5420,
+ 0x5420, 0x5420, 0x5421, 0x5421, 0x5421, 0x5421, 0x5421, 0x5421,
+ 0x5421, 0x5421, 0x5421, 0x5421, 0x5421, 0x5421, 0x5421, 0x5421,
+ 0x5421, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422,
+ 0x5422, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422, 0x5422,
+ 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5423,
+ 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5423, 0x5424,
+ 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5424,
+ 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5424, 0x5425,
+ 0x5425, 0x5425, 0x5425, 0x5425, 0x5425, 0x5425, 0x5425, 0x5425,
+ 0x5425, 0x5425, 0x5425, 0x5425, 0x5425, 0x5425, 0x5426, 0x5426,
+ 0x5426, 0x5426, 0x5426, 0x5426, 0x5426, 0x5426, 0x5426, 0x5426,
+ 0x5426, 0x5426, 0x5426, 0x5426, 0x5426, 0x5426, 0x5427, 0x5427,
+ 0x5427, 0x5427, 0x5427, 0x5427, 0x5427, 0x5427, 0x5427, 0x5427,
+ 0x5427, 0x5427, 0x5427, 0x5427, 0x5427, 0x5427, 0x5428, 0x5428,
+ 0x5428, 0x5428, 0x5428, 0x5428, 0x5428, 0x5428, 0x5428, 0x5428,
+ 0x5428, 0x5428, 0x5428, 0x5428, 0x5428, 0x5428, 0x5429, 0x5429,
+ 0x5429, 0x5429, 0x5429, 0x5429, 0x5429, 0x5429, 0x5429, 0x542a,
+ 0x542a, 0x542a, 0x542a, 0x542a, 0x542a, 0x542a, 0x542a, 0x542b,
+ 0x542b, 0x542b, 0x542b, 0x542b, 0x542b, 0x542b, 0x542b, 0x542c,
+ 0x542c, 0x542c, 0x542c, 0x542c, 0x542c, 0x542c, 0x542c, 0x542c,
+ 0x542d, 0x542d, 0x542d, 0x542d, 0x542d, 0x542d, 0x542d, 0x542d,
+ 0x542e, 0x542e, 0x542e, 0x542e, 0x542e, 0x542e, 0x542e, 0x542e,
+ 0x542f, 0x542f, 0x542f, 0x542f, 0x542f, 0x542f, 0x542f, 0x542f,
+ 0x542f, 0x5430, 0x5430, 0x5430, 0x5430, 0x5430, 0x5430, 0x5430,
+ 0x5430, 0x5431, 0x5431, 0x5431, 0x5431, 0x5431, 0x5431, 0x5431,
+ 0x5431, 0x5431, 0x5432, 0x5432, 0x5432, 0x5432, 0x5432, 0x5432,
+ 0x5432, 0x5432, 0x5433, 0x5433, 0x5433, 0x5433, 0x5433, 0x5433,
+ 0x5433, 0x5433, 0x5433, 0x5434, 0x5434, 0x5434, 0x5434, 0x5434,
+ 0x5434, 0x5434, 0x5434, 0x5434, 0x5435, 0x5435, 0x5435, 0x5435,
+ 0x5435, 0x5435, 0x5435, 0x5435, 0x5436, 0x5436, 0x5436, 0x5436,
+ 0x5436, 0x5436, 0x5436, 0x5436, 0x5436, 0x5437, 0x5437, 0x5437,
+ 0x5437, 0x5437, 0x5437, 0x5437, 0x5437, 0x5437, 0x5438, 0x5438,
+ 0x5438, 0x5438, 0x5438, 0x5438, 0x5438, 0x5438, 0x5438, 0x5439,
+ 0x5439, 0x5439, 0x5439, 0x5439, 0x5439, 0x5439, 0x5439, 0x5439,
+ 0x543a, 0x543a, 0x543a, 0x543a, 0x543a, 0x543a, 0x543a, 0x543a,
+ 0x543a, 0x543a, 0x543b, 0x543b, 0x543b, 0x543b, 0x543b, 0x543b,
+ 0x543b, 0x543b, 0x543b, 0x543c, 0x543c, 0x543c, 0x543c, 0x543c,
+ 0x543c, 0x543c, 0x543c, 0x543c, 0x543d, 0x543d, 0x543d, 0x543d,
+ 0x543d, 0x543d, 0x543d, 0x543d, 0x543d, 0x543e, 0x543e, 0x543e,
+ 0x543e, 0x543e, 0x543e, 0x543e, 0x543e, 0x543e, 0x543e, 0x543f,
+ 0x543f, 0x543f, 0x543f, 0x543f, 0x543f, 0x543f, 0x543f, 0x543f,
+ 0x5440, 0x5440, 0x5440, 0x5440, 0x5440, 0x5440, 0x5440, 0x5440,
+ 0x5440, 0x5440, 0x5441, 0x5441, 0x5441, 0x5441, 0x5441, 0x5441,
+ 0x5441, 0x5441, 0x5441, 0x5441, 0x5442, 0x5442, 0x5442, 0x5442,
+ 0x5442, 0x5442, 0x5442, 0x5442, 0x5442, 0x5443, 0x5443, 0x5443,
+ 0x5443, 0x5443, 0x5443, 0x5443, 0x5443, 0x5443, 0x5443, 0x5444,
+ 0x5444, 0x5444, 0x5444, 0x5444, 0x5444, 0x5444, 0x5444, 0x5444,
+ 0x5444, 0x5445, 0x5445, 0x5445, 0x5445, 0x5445, 0x5445, 0x5445,
+ 0x5445, 0x5445, 0x5445, 0x5446, 0x5446, 0x5446, 0x5446, 0x5446,
+ 0x5446, 0x5446, 0x5446, 0x5446, 0x5446, 0x5447, 0x5447, 0x5447,
+ 0x5447, 0x5447, 0x5447, 0x5447, 0x5447, 0x5447, 0x5447, 0x5448,
+ 0x5448, 0x5448, 0x5448, 0x5448, 0x5448, 0x5448, 0x5448, 0x5448,
+ 0x5448, 0x5448, 0x5449, 0x5449, 0x5449, 0x5449, 0x5449, 0x5449,
+ 0x5449, 0x5449, 0x5449, 0x5449, 0x544a, 0x544a, 0x544a, 0x544a,
+ 0x544a, 0x544a, 0x544a, 0x544a, 0x544a, 0x544a, 0x544b, 0x544b,
+ 0x544b, 0x544b, 0x544b, 0x544b, 0x544b, 0x544b, 0x544b, 0x544b,
+ 0x544b, 0x544c, 0x544c, 0x544c, 0x544c, 0x544c, 0x544c, 0x544c,
+ 0x544c, 0x544c, 0x544c, 0x544d, 0x544d, 0x544d, 0x544d, 0x544d,
+ 0x544d, 0x544d, 0x544d, 0x544d, 0x544d, 0x544d, 0x544e, 0x544e,
+ 0x544e, 0x544e, 0x544e, 0x544e, 0x544e, 0x544e, 0x544e, 0x544e,
+ 0x544e, 0x544f, 0x544f, 0x544f, 0x544f, 0x544f, 0x544f, 0x544f,
+ 0x544f, 0x544f, 0x544f, 0x5450, 0x5450, 0x5450, 0x5450, 0x5450,
+ 0x5450, 0x5450, 0x5450, 0x5450, 0x5450, 0x5450, 0x5451, 0x5451,
+ 0x5451, 0x5451, 0x5451, 0x5451, 0x5451, 0x5451, 0x5451, 0x5451,
+ 0x5451, 0x5452, 0x5452, 0x5452, 0x5452, 0x5452, 0x5452, 0x5452,
+ 0x5452, 0x5452, 0x5452, 0x5452, 0x5453, 0x5453, 0x5453, 0x5453,
+ 0x5453, 0x5453, 0x5453, 0x5453, 0x5453, 0x5453, 0x5453, 0x5454,
+ 0x5454, 0x5454, 0x5454, 0x5454, 0x5454, 0x5454, 0x5454, 0x5454,
+ 0x5454, 0x5454, 0x5454, 0x5455, 0x5455, 0x5455, 0x5455, 0x5455,
+ 0x5455, 0x5455, 0x5455, 0x5455, 0x5455, 0x5455, 0x5456, 0x5456,
+ 0x5456, 0x5456, 0x5456, 0x5456, 0x5456, 0x5456, 0x5456, 0x5456,
+ 0x5456, 0x5457, 0x5457, 0x5457, 0x5457, 0x5457, 0x5457, 0x5457,
+ 0x5457, 0x5457, 0x5457, 0x5457, 0x5457, 0x5458, 0x5458, 0x5458,
+ 0x5458, 0x5458, 0x5458, 0x5458, 0x5458, 0x5458, 0x5458, 0x5458,
+ 0x5459, 0x5459, 0x5459, 0x5459, 0x5459, 0x5459, 0x5459, 0x5459,
+ 0x5459, 0x5459, 0x5459, 0x5459, 0x545a, 0x545a, 0x545a, 0x545a,
+ 0x545a, 0x545a, 0x545a, 0x545a, 0x545a, 0x545a, 0x545a, 0x545a,
+ 0x545b, 0x545b, 0x545b, 0x545b, 0x545b, 0x545b, 0x545b, 0x545b,
+ 0x545b, 0x545b, 0x545b, 0x545b, 0x545c, 0x545c, 0x545c, 0x545c,
+ 0x545c, 0x545c, 0x545c, 0x545c, 0x545c, 0x545c, 0x545c, 0x545c,
+ 0x545d, 0x545d, 0x545d, 0x545d, 0x545d, 0x545d, 0x545d, 0x545d,
+ 0x545d, 0x545d, 0x545d, 0x545d, 0x545e, 0x545e, 0x545e, 0x545e,
+ 0x545e, 0x545e, 0x545e, 0x545e, 0x545e, 0x545e, 0x545e, 0x545e,
+ 0x545f, 0x545f, 0x545f, 0x545f, 0x545f, 0x545f, 0x545f, 0x545f,
+ 0x545f, 0x545f, 0x545f, 0x545f, 0x5460, 0x5460, 0x5460, 0x5460,
+ 0x5460, 0x5460, 0x5460, 0x5460, 0x5460, 0x5460, 0x5460, 0x5460,
+ 0x5461, 0x5461, 0x5461, 0x5461, 0x5461, 0x5461, 0x5461, 0x5461,
+ 0x5461, 0x5461, 0x5461, 0x5461, 0x5461, 0x5462, 0x5462, 0x5462,
+ 0x5462, 0x5462, 0x5462, 0x5462, 0x5462, 0x5462, 0x5462, 0x5462,
+ 0x5462, 0x5463, 0x5463, 0x5463, 0x5463, 0x5463, 0x5463, 0x5463,
+ 0x5463, 0x5463, 0x5463, 0x5463, 0x5463, 0x5463, 0x5464, 0x5464,
+ 0x5464, 0x5464, 0x5464, 0x5464, 0x5464, 0x5464, 0x5464, 0x5464,
+ 0x5464, 0x5464, 0x5464, 0x5465, 0x5465, 0x5465, 0x5465, 0x5465,
+ 0x5465, 0x5465, 0x5465, 0x5465, 0x5465, 0x5465, 0x5465, 0x5466,
+ 0x5466, 0x5466, 0x5466, 0x5466, 0x5466, 0x5466, 0x5466, 0x5466,
+ 0x5466, 0x5466, 0x5466, 0x5466, 0x5467, 0x5467, 0x5467, 0x5467,
+ 0x5467, 0x5467, 0x5467, 0x5467, 0x5467, 0x5467, 0x5467, 0x5467,
+ 0x5467, 0x5468, 0x5468, 0x5468, 0x5468, 0x5468, 0x5468, 0x5468,
+ 0x5468, 0x5468, 0x5468, 0x5468, 0x5468, 0x5468, 0x5469, 0x5469,
+ 0x5469, 0x5469, 0x5469, 0x5469, 0x5469, 0x5469, 0x5469, 0x5469,
+ 0x5469, 0x5469, 0x5469, 0x5469, 0x546a, 0x546a, 0x546a, 0x546a,
+ 0x546a, 0x546a, 0x546a, 0x546a, 0x546a, 0x546a, 0x546a, 0x546a,
+ 0x546a, 0x546b, 0x546b, 0x546b, 0x546b, 0x546b, 0x546b, 0x546b,
+ 0x546b, 0x546b, 0x546b, 0x546b, 0x546b, 0x546b, 0x546c, 0x546c,
+ 0x546c, 0x546c, 0x546c, 0x546c, 0x546c, 0x546c, 0x546c, 0x546c,
+ 0x546c, 0x546c, 0x546c, 0x546c, 0x546d, 0x546d, 0x546d, 0x546d,
+ 0x546d, 0x546d, 0x546d, 0x546d, 0x546d, 0x546d, 0x546d, 0x546d,
+ 0x546d, 0x546d, 0x546e, 0x546e, 0x546e, 0x546e, 0x546e, 0x546e,
+ 0x546e, 0x546e, 0x546e, 0x546e, 0x546e, 0x546e, 0x546e, 0x546f,
+ 0x546f, 0x546f, 0x546f, 0x546f, 0x546f, 0x546f, 0x546f, 0x546f,
+ 0x546f, 0x546f, 0x546f, 0x546f, 0x546f, 0x5470, 0x5470, 0x5470,
+ 0x5470, 0x5470, 0x5470, 0x5470, 0x5470, 0x5470, 0x5470, 0x5470,
+ 0x5470, 0x5470, 0x5470, 0x5471, 0x5471, 0x5471, 0x5471, 0x5471,
+ 0x5471, 0x5471, 0x5471, 0x5471, 0x5471, 0x5471, 0x5471, 0x5471,
+ 0x5471, 0x5472, 0x5472, 0x5472, 0x5472, 0x5472, 0x5472, 0x5472,
+ 0x5472, 0x5472, 0x5472, 0x5472, 0x5472, 0x5472, 0x5472, 0x5473,
+ 0x5473, 0x5473, 0x5473, 0x5473, 0x5473, 0x5473, 0x5473, 0x5473,
+ 0x5473, 0x5473, 0x5473, 0x5473, 0x5473, 0x5473, 0x5474, 0x5474,
+ 0x5474, 0x5474, 0x5474, 0x5474, 0x5474, 0x5474, 0x5474, 0x5474,
+ 0x5474, 0x5474, 0x5474, 0x5474, 0x5475, 0x5475, 0x5475, 0x5475,
+ 0x5475, 0x5475, 0x5475, 0x5475, 0x5475, 0x5475, 0x5475, 0x5475,
+ 0x5475, 0x5475, 0x5475, 0x5476, 0x5476, 0x5476, 0x5476, 0x5476,
+ 0x5476, 0x5476, 0x5476, 0x5476, 0x5476, 0x5476, 0x5476, 0x5476,
+ 0x5476, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477,
+ 0x5477, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477, 0x5477,
+ 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5478,
+ 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5478, 0x5479,
+ 0x5479, 0x5479, 0x5479, 0x5479, 0x5479, 0x5479, 0x5479, 0x5479,
+ 0x5479, 0x5479, 0x5479, 0x5479, 0x5479, 0x5479, 0x547a, 0x547a,
+ 0x547a, 0x547a, 0x547a, 0x547a, 0x547a, 0x547a, 0x547a, 0x547a,
+ 0x547a, 0x547a, 0x547a, 0x547a, 0x547a, 0x547b, 0x547b, 0x547b,
+ 0x547b, 0x547b, 0x547b, 0x547b, 0x547b, 0x547b, 0x547b, 0x547b,
+ 0x547b, 0x547b, 0x547b, 0x547b, 0x547c, 0x547c, 0x547c, 0x547c,
+ 0x547c, 0x547c, 0x547c, 0x547c, 0x547c, 0x547c, 0x547c, 0x547c,
+ 0x547c, 0x547c, 0x547c, 0x547c, 0x547d, 0x547d, 0x547d, 0x547d,
+ 0x547d, 0x547d, 0x547d, 0x547d, 0x547d, 0x547d, 0x547d, 0x547d,
+ 0x547d, 0x547d, 0x547d, 0x547e, 0x547e, 0x547e, 0x547e, 0x547e,
+ 0x547e, 0x547e, 0x547e, 0x547e, 0x547e, 0x547e, 0x547e, 0x547e,
+ 0x547e, 0x547e, 0x547e, 0x547f, 0x547f, 0x547f, 0x547f, 0x547f,
+ 0x547f, 0x547f, 0x547f, 0x547f, 0x547f, 0x547f, 0x547f, 0x547f,
+ 0x547f, 0x547f, 0x5480, 0x5480, 0x5480, 0x5480, 0x5480, 0x5480,
+ 0x5480, 0x5480, 0x5480, 0x5480, 0x5480, 0x5480, 0x5480, 0x5480,
+ 0x5480, 0x5480, 0x5481, 0x5481, 0x5481, 0x5481, 0x5481, 0x5481,
+ 0x5481, 0x5481, 0x5481, 0x5481, 0x5481, 0x5481, 0x5481, 0x5481,
+ 0x5481, 0x5482, 0x5482, 0x5482, 0x5482, 0x5482, 0x5482, 0x5482,
+ 0x5482, 0x5483, 0x5483, 0x5483, 0x5483, 0x5483, 0x5483, 0x5483,
+ 0x5483, 0x5484, 0x5484, 0x5484, 0x5484, 0x5484, 0x5484, 0x5484,
+ 0x5484, 0x5484, 0x5485, 0x5485, 0x5485, 0x5485, 0x5485, 0x5485,
+ 0x5485, 0x5485, 0x5486, 0x5486, 0x5486, 0x5486, 0x5486, 0x5486,
+ 0x5486, 0x5486, 0x5487, 0x5487, 0x5487, 0x5487, 0x5487, 0x5487,
+ 0x5487, 0x5487, 0x5487, 0x5488, 0x5488, 0x5488, 0x5488, 0x5488,
+ 0x5488, 0x5488, 0x5488, 0x5489, 0x5489, 0x5489, 0x5489, 0x5489,
+ 0x5489, 0x5489, 0x5489, 0x548a, 0x548a, 0x548a, 0x548a, 0x548a,
+ 0x548a, 0x548a, 0x548a, 0x548a, 0x548b, 0x548b, 0x548b, 0x548b,
+ 0x548b, 0x548b, 0x548b, 0x548b, 0x548b, 0x548c, 0x548c, 0x548c,
+ 0x548c, 0x548c, 0x548c, 0x548c, 0x548c, 0x548d, 0x548d, 0x548d,
+ 0x548d, 0x548d, 0x548d, 0x548d, 0x548d, 0x548d, 0x548e, 0x548e,
+ 0x548e, 0x548e, 0x548e, 0x548e, 0x548e, 0x548e, 0x548e, 0x548f,
+ 0x548f, 0x548f, 0x548f, 0x548f, 0x548f, 0x548f, 0x548f, 0x548f,
+ 0x5490, 0x5490, 0x5490, 0x5490, 0x5490, 0x5490, 0x5490, 0x5490,
+ 0x5490, 0x5491, 0x5491, 0x5491, 0x5491, 0x5491, 0x5491, 0x5491,
+ 0x5491, 0x5491, 0x5492, 0x5492, 0x5492, 0x5492, 0x5492, 0x5492,
+ 0x5492, 0x5492, 0x5492, 0x5493, 0x5493, 0x5493, 0x5493, 0x5493,
+ 0x5493, 0x5493, 0x5493, 0x5493, 0x5494, 0x5494, 0x5494, 0x5494,
+ 0x5494, 0x5494, 0x5494, 0x5494, 0x5494, 0x5495, 0x5495, 0x5495,
+ 0x5495, 0x5495, 0x5495, 0x5495, 0x5495, 0x5495, 0x5495, 0x5496,
+ 0x5496, 0x5496, 0x5496, 0x5496, 0x5496, 0x5496, 0x5496, 0x5496,
+ 0x5497, 0x5497, 0x5497, 0x5497, 0x5497, 0x5497, 0x5497, 0x5497,
+ 0x5497, 0x5497, 0x5498, 0x5498, 0x5498, 0x5498, 0x5498, 0x5498,
+ 0x5498, 0x5498, 0x5498, 0x5499, 0x5499, 0x5499, 0x5499, 0x5499,
+ 0x5499, 0x5499, 0x5499, 0x5499, 0x5499, 0x549a, 0x549a, 0x549a,
+ 0x549a, 0x549a, 0x549a, 0x549a, 0x549a, 0x549a, 0x549b, 0x549b,
+ 0x549b, 0x549b, 0x549b, 0x549b, 0x549b, 0x549b, 0x549b, 0x549b,
+ 0x549c, 0x549c, 0x549c, 0x549c, 0x549c, 0x549c, 0x549c, 0x549c,
+ 0x549c, 0x549c, 0x549d, 0x549d, 0x549d, 0x549d, 0x549d, 0x549d,
+ 0x549d, 0x549d, 0x549d, 0x549d, 0x549e, 0x549e, 0x549e, 0x549e,
+ 0x549e, 0x549e, 0x549e, 0x549e, 0x549e, 0x549e, 0x549f, 0x549f,
+ 0x549f, 0x549f, 0x549f, 0x549f, 0x549f, 0x549f, 0x549f, 0x549f,
+ 0x54a0, 0x54a0, 0x54a0, 0x54a0, 0x54a0, 0x54a0, 0x54a0, 0x54a0,
+ 0x54a0, 0x54a0, 0x54a1, 0x54a1, 0x54a1, 0x54a1, 0x54a1, 0x54a1,
+ 0x54a1, 0x54a1, 0x54a1, 0x54a1, 0x54a2, 0x54a2, 0x54a2, 0x54a2,
+ 0x54a2, 0x54a2, 0x54a2, 0x54a2, 0x54a2, 0x54a2, 0x54a2, 0x54a3,
+ 0x54a3, 0x54a3, 0x54a3, 0x54a3, 0x54a3, 0x54a3, 0x54a3, 0x54a3,
+ 0x54a3, 0x54a4, 0x54a4, 0x54a4, 0x54a4, 0x54a4, 0x54a4, 0x54a4,
+ 0x54a4, 0x54a4, 0x54a4, 0x54a4, 0x54a5, 0x54a5, 0x54a5, 0x54a5,
+ 0x54a5, 0x54a5, 0x54a5, 0x54a5, 0x54a5, 0x54a5, 0x54a6, 0x54a6,
+ 0x54a6, 0x54a6, 0x54a6, 0x54a6, 0x54a6, 0x54a6, 0x54a6, 0x54a6,
+ 0x54a6, 0x54a7, 0x54a7, 0x54a7, 0x54a7, 0x54a7, 0x54a7, 0x54a7,
+ 0x54a7, 0x54a7, 0x54a7, 0x54a7, 0x54a8, 0x54a8, 0x54a8, 0x54a8,
+ 0x54a8, 0x54a8, 0x54a8, 0x54a8, 0x54a8, 0x54a8, 0x54a9, 0x54a9,
+ 0x54a9, 0x54a9, 0x54a9, 0x54a9, 0x54a9, 0x54a9, 0x54a9, 0x54a9,
+ 0x54a9, 0x54aa, 0x54aa, 0x54aa, 0x54aa, 0x54aa, 0x54aa, 0x54aa,
+ 0x54aa, 0x54aa, 0x54aa, 0x54aa, 0x54ab, 0x54ab, 0x54ab, 0x54ab,
+ 0x54ab, 0x54ab, 0x54ab, 0x54ab, 0x54ab, 0x54ab, 0x54ab, 0x54ac,
+ 0x54ac, 0x54ac, 0x54ac, 0x54ac, 0x54ac, 0x54ac, 0x54ac, 0x54ac,
+ 0x54ac, 0x54ac, 0x54ad, 0x54ad, 0x54ad, 0x54ad, 0x54ad, 0x54ad,
+ 0x54ad, 0x54ad, 0x54ad, 0x54ad, 0x54ad, 0x54ad, 0x54ae, 0x54ae,
+ 0x54ae, 0x54ae, 0x54ae, 0x54ae, 0x54ae, 0x54ae, 0x54ae, 0x54ae,
+ 0x54ae, 0x54af, 0x54af, 0x54af, 0x54af, 0x54af, 0x54af, 0x54af,
+ 0x54af, 0x54af, 0x54af, 0x54af, 0x54b0, 0x54b0, 0x54b0, 0x54b0,
+ 0x54b0, 0x54b0, 0x54b0, 0x54b0, 0x54b0, 0x54b0, 0x54b0, 0x54b0,
+ 0x54b1, 0x54b1, 0x54b1, 0x54b1, 0x54b1, 0x54b1, 0x54b1, 0x54b1,
+ 0x54b1, 0x54b1, 0x54b1, 0x54b1, 0x54b2, 0x54b2, 0x54b2, 0x54b2,
+ 0x54b2, 0x54b2, 0x54b2, 0x54b2, 0x54b2, 0x54b2, 0x54b2, 0x54b3,
+ 0x54b3, 0x54b3, 0x54b3, 0x54b3, 0x54b3, 0x54b3, 0x54b3, 0x54b3,
+ 0x54b3, 0x54b3, 0x54b3, 0x54b4, 0x54b4, 0x54b4, 0x54b4, 0x54b4,
+ 0x54b4, 0x54b4, 0x54b4, 0x54b4, 0x54b4, 0x54b4, 0x54b4, 0x54b5,
+ 0x54b5, 0x54b5, 0x54b5, 0x54b5, 0x54b5, 0x54b5, 0x54b5, 0x54b5,
+ 0x54b5, 0x54b5, 0x54b5, 0x54b6, 0x54b6, 0x54b6, 0x54b6, 0x54b6,
+ 0x54b6, 0x54b6, 0x54b6, 0x54b6, 0x54b6, 0x54b6, 0x54b6, 0x54b7,
+ 0x54b7, 0x54b7, 0x54b7, 0x54b7, 0x54b7, 0x54b7, 0x54b7, 0x54b7,
+ 0x54b7, 0x54b7, 0x54b7, 0x54b8, 0x54b8, 0x54b8, 0x54b8, 0x54b8,
+ 0x54b8, 0x54b8, 0x54b8, 0x54b8, 0x54b8, 0x54b8, 0x54b8, 0x54b9,
+ 0x54b9, 0x54b9, 0x54b9, 0x54b9, 0x54b9, 0x54b9, 0x54b9, 0x54b9,
+ 0x54b9, 0x54b9, 0x54b9, 0x54b9, 0x54ba, 0x54ba, 0x54ba, 0x54ba,
+ 0x54ba, 0x54ba, 0x54ba, 0x54ba, 0x54ba, 0x54ba, 0x54ba, 0x54ba,
+ 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bb,
+ 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bb, 0x54bc, 0x54bc, 0x54bc,
+ 0x54bc, 0x54bc, 0x54bc, 0x54bc, 0x54bc, 0x54bc, 0x54bc, 0x54bc,
+ 0x54bc, 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54bd,
+ 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54bd, 0x54be, 0x54be,
+ 0x54be, 0x54be, 0x54be, 0x54be, 0x54be, 0x54be, 0x54be, 0x54be,
+ 0x54be, 0x54be, 0x54be, 0x54bf, 0x54bf, 0x54bf, 0x54bf, 0x54bf,
+ 0x54bf, 0x54bf, 0x54bf, 0x54bf, 0x54bf, 0x54bf, 0x54bf, 0x54bf,
+ 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c0,
+ 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c0, 0x54c1, 0x54c1, 0x54c1,
+ 0x54c1, 0x54c1, 0x54c1, 0x54c1, 0x54c1, 0x54c1, 0x54c1, 0x54c1,
+ 0x54c1, 0x54c1, 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c2,
+ 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c2, 0x54c3,
+ 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c3,
+ 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c3, 0x54c4, 0x54c4, 0x54c4,
+ 0x54c4, 0x54c4, 0x54c4, 0x54c4, 0x54c4, 0x54c4, 0x54c4, 0x54c4,
+ 0x54c4, 0x54c4, 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5,
+ 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5, 0x54c5,
+ 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c6,
+ 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c6, 0x54c7, 0x54c7, 0x54c7,
+ 0x54c7, 0x54c7, 0x54c7, 0x54c7, 0x54c7, 0x54c7, 0x54c7, 0x54c7,
+ 0x54c7, 0x54c7, 0x54c7, 0x54c8, 0x54c8, 0x54c8, 0x54c8, 0x54c8,
+ 0x54c8, 0x54c8, 0x54c8, 0x54c8, 0x54c8, 0x54c8, 0x54c8, 0x54c8,
+ 0x54c8, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9,
+ 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54c9, 0x54ca,
+ 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54ca,
+ 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54ca, 0x54cb, 0x54cb, 0x54cb,
+ 0x54cb, 0x54cb, 0x54cb, 0x54cb, 0x54cb, 0x54cb, 0x54cb, 0x54cb,
+ 0x54cb, 0x54cb, 0x54cb, 0x54cc, 0x54cc, 0x54cc, 0x54cc, 0x54cc,
+ 0x54cc, 0x54cc, 0x54cc, 0x54cc, 0x54cc, 0x54cc, 0x54cc, 0x54cc,
+ 0x54cc, 0x54cc, 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd,
+ 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd, 0x54cd,
+ 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce,
+ 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54ce, 0x54cf,
+ 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54cf,
+ 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54cf, 0x54d0, 0x54d0, 0x54d0,
+ 0x54d0, 0x54d0, 0x54d0, 0x54d0, 0x54d0, 0x54d0, 0x54d0, 0x54d0,
+ 0x54d0, 0x54d0, 0x54d0, 0x54d0, 0x54d1, 0x54d1, 0x54d1, 0x54d1,
+ 0x54d1, 0x54d1, 0x54d1, 0x54d1, 0x54d1, 0x54d1, 0x54d1, 0x54d1,
+ 0x54d1, 0x54d1, 0x54d1, 0x54d2, 0x54d2, 0x54d2, 0x54d2, 0x54d2,
+ 0x54d2, 0x54d2, 0x54d2, 0x54d2, 0x54d2, 0x54d2, 0x54d2, 0x54d2,
+ 0x54d2, 0x54d2, 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3,
+ 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3, 0x54d3,
+ 0x54d3, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4,
+ 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4, 0x54d4,
+ 0x54d4, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5,
+ 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5, 0x54d5,
+ 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6,
+ 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d6, 0x54d7,
+ 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7,
+ 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d7, 0x54d8,
+ 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8,
+ 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d8, 0x54d9,
+ 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9,
+ 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54d9, 0x54da,
+ 0x54da, 0x54da, 0x54da, 0x54da, 0x54da, 0x54da, 0x54da, 0x54da,
+ 0x54da, 0x54da, 0x54da, 0x54da, 0x54db, 0x54db, 0x54db, 0x54db,
+ 0x54db, 0x54db, 0x54db, 0x54db, 0x54dc, 0x54dc, 0x54dc, 0x54dc,
+ 0x54dc, 0x54dc, 0x54dc, 0x54dc, 0x54dd, 0x54dd, 0x54dd, 0x54dd,
+ 0x54dd, 0x54dd, 0x54dd, 0x54dd, 0x54de, 0x54de, 0x54de, 0x54de,
+ 0x54de, 0x54de, 0x54de, 0x54de, 0x54df, 0x54df, 0x54df, 0x54df,
+ 0x54df, 0x54df, 0x54df, 0x54df, 0x54e0, 0x54e0, 0x54e0, 0x54e0,
+ 0x54e0, 0x54e0, 0x54e0, 0x54e0, 0x54e0, 0x54e1, 0x54e1, 0x54e1,
+ 0x54e1, 0x54e1, 0x54e1, 0x54e1, 0x54e1, 0x54e2, 0x54e2, 0x54e2,
+ 0x54e2, 0x54e2, 0x54e2, 0x54e2, 0x54e2, 0x54e2, 0x54e3, 0x54e3,
+ 0x54e3, 0x54e3, 0x54e3, 0x54e3, 0x54e3, 0x54e3, 0x54e4, 0x54e4,
+ 0x54e4, 0x54e4, 0x54e4, 0x54e4, 0x54e4, 0x54e4, 0x54e4, 0x54e5,
+ 0x54e5, 0x54e5, 0x54e5, 0x54e5, 0x54e5, 0x54e5, 0x54e5, 0x54e5,
+ 0x54e6, 0x54e6, 0x54e6, 0x54e6, 0x54e6, 0x54e6, 0x54e6, 0x54e6,
+ 0x54e7, 0x54e7, 0x54e7, 0x54e7, 0x54e7, 0x54e7, 0x54e7, 0x54e7,
+ 0x54e7, 0x54e8, 0x54e8, 0x54e8, 0x54e8, 0x54e8, 0x54e8, 0x54e8,
+ 0x54e8, 0x54e8, 0x54e9, 0x54e9, 0x54e9, 0x54e9, 0x54e9, 0x54e9,
+ 0x54e9, 0x54e9, 0x54e9, 0x54ea, 0x54ea, 0x54ea, 0x54ea, 0x54ea,
+ 0x54ea, 0x54ea, 0x54ea, 0x54ea, 0x54eb, 0x54eb, 0x54eb, 0x54eb,
+ 0x54eb, 0x54eb, 0x54eb, 0x54eb, 0x54eb, 0x54ec, 0x54ec, 0x54ec,
+ 0x54ec, 0x54ec, 0x54ec, 0x54ec, 0x54ec, 0x54ec, 0x54ec, 0x54ed,
+ 0x54ed, 0x54ed, 0x54ed, 0x54ed, 0x54ed, 0x54ed, 0x54ed, 0x54ed,
+ 0x54ee, 0x54ee, 0x54ee, 0x54ee, 0x54ee, 0x54ee, 0x54ee, 0x54ee,
+ 0x54ee, 0x54ef, 0x54ef, 0x54ef, 0x54ef, 0x54ef, 0x54ef, 0x54ef,
+ 0x54ef, 0x54ef, 0x54ef, 0x54f0, 0x54f0, 0x54f0, 0x54f0, 0x54f0,
+ 0x54f0, 0x54f0, 0x54f0, 0x54f0, 0x54f1, 0x54f1, 0x54f1, 0x54f1,
+ 0x54f1, 0x54f1, 0x54f1, 0x54f1, 0x54f1, 0x54f1, 0x54f2, 0x54f2,
+ 0x54f2, 0x54f2, 0x54f2, 0x54f2, 0x54f2, 0x54f2, 0x54f2, 0x54f3,
+ 0x54f3, 0x54f3, 0x54f3, 0x54f3, 0x54f3, 0x54f3, 0x54f3, 0x54f3,
+ 0x54f3, 0x54f4, 0x54f4, 0x54f4, 0x54f4, 0x54f4, 0x54f4, 0x54f4,
+ 0x54f4, 0x54f4, 0x54f4, 0x54f5, 0x54f5, 0x54f5, 0x54f5, 0x54f5,
+ 0x54f5, 0x54f5, 0x54f5, 0x54f5, 0x54f5, 0x54f6, 0x54f6, 0x54f6,
+ 0x54f6, 0x54f6, 0x54f6, 0x54f6, 0x54f6, 0x54f6, 0x54f6, 0x54f7,
+ 0x54f7, 0x54f7, 0x54f7, 0x54f7, 0x54f7, 0x54f7, 0x54f7, 0x54f7,
+ 0x54f7, 0x54f8, 0x54f8, 0x54f8, 0x54f8, 0x54f8, 0x54f8, 0x54f8,
+ 0x54f8, 0x54f8, 0x54f8, 0x54f9, 0x54f9, 0x54f9, 0x54f9, 0x54f9,
+ 0x54f9, 0x54f9, 0x54f9, 0x54f9, 0x54f9, 0x54fa, 0x54fa, 0x54fa,
+ 0x54fa, 0x54fa, 0x54fa, 0x54fa, 0x54fa, 0x54fa, 0x54fa, 0x54fb,
+ 0x54fb, 0x54fb, 0x54fb, 0x54fb, 0x54fb, 0x54fb, 0x54fb, 0x54fb,
+ 0x54fb, 0x54fb, 0x54fc, 0x54fc, 0x54fc, 0x54fc, 0x54fc, 0x54fc,
+ 0x54fc, 0x54fc, 0x54fc, 0x54fc, 0x54fd, 0x54fd, 0x54fd, 0x54fd,
+ 0x54fd, 0x54fd, 0x54fd, 0x54fd, 0x54fd, 0x54fd, 0x54fd, 0x54fe,
+ 0x54fe, 0x54fe, 0x54fe, 0x54fe, 0x54fe, 0x54fe, 0x54fe, 0x54fe,
+ 0x54fe, 0x54ff, 0x54ff, 0x54ff, 0x54ff, 0x54ff, 0x54ff, 0x54ff,
+ 0x54ff, 0x54ff, 0x54ff, 0x54ff, 0x5500, 0x5500, 0x5500, 0x5500,
+ 0x5500, 0x5500, 0x5500, 0x5500, 0x5500, 0x5500, 0x5500, 0x5501,
+ 0x5501, 0x5501, 0x5501, 0x5501, 0x5501, 0x5501, 0x5501, 0x5501,
+ 0x5501, 0x5502, 0x5502, 0x5502, 0x5502, 0x5502, 0x5502, 0x5502,
+ 0x5502, 0x5502, 0x5502, 0x5502, 0x5503, 0x5503, 0x5503, 0x5503,
+ 0x5503, 0x5503, 0x5503, 0x5503, 0x5503, 0x5503, 0x5503, 0x5504,
+ 0x5504, 0x5504, 0x5504, 0x5504, 0x5504, 0x5504, 0x5504, 0x5504,
+ 0x5504, 0x5504, 0x5505, 0x5505, 0x5505, 0x5505, 0x5505, 0x5505,
+ 0x5505, 0x5505, 0x5505, 0x5505, 0x5505, 0x5505, 0x5506, 0x5506,
+ 0x5506, 0x5506, 0x5506, 0x5506, 0x5506, 0x5506, 0x5506, 0x5506,
+ 0x5506, 0x5507, 0x5507, 0x5507, 0x5507, 0x5507, 0x5507, 0x5507,
+ 0x5507, 0x5507, 0x5507, 0x5507, 0x5508, 0x5508, 0x5508, 0x5508,
+ 0x5508, 0x5508, 0x5508, 0x5508, 0x5508, 0x5508, 0x5508, 0x5508,
+ 0x5509, 0x5509, 0x5509, 0x5509, 0x5509, 0x5509, 0x5509, 0x5509,
+ 0x5509, 0x5509, 0x5509, 0x550a, 0x550a, 0x550a, 0x550a, 0x550a,
+ 0x550a, 0x550a, 0x550a, 0x550a, 0x550a, 0x550a, 0x550a, 0x550b,
+ 0x550b, 0x550b, 0x550b, 0x550b, 0x550b, 0x550b, 0x550b, 0x550b,
+ 0x550b, 0x550b, 0x550b, 0x550c, 0x550c, 0x550c, 0x550c, 0x550c,
+ 0x550c, 0x550c, 0x550c, 0x550c, 0x550c, 0x550c, 0x550d, 0x550d,
+ 0x550d, 0x550d, 0x550d, 0x550d, 0x550d, 0x550d, 0x550d, 0x550d,
+ 0x550d, 0x550d, 0x550e, 0x550e, 0x550e, 0x550e, 0x550e, 0x550e,
+ 0x550e, 0x550e, 0x550e, 0x550e, 0x550e, 0x550e, 0x550f, 0x550f,
+ 0x550f, 0x550f, 0x550f, 0x550f, 0x550f, 0x550f, 0x550f, 0x550f,
+ 0x550f, 0x550f, 0x5510, 0x5510, 0x5510, 0x5510, 0x5510, 0x5510,
+ 0x5510, 0x5510, 0x5510, 0x5510, 0x5510, 0x5510, 0x5510, 0x5511,
+ 0x5511, 0x5511, 0x5511, 0x5511, 0x5511, 0x5511, 0x5511, 0x5511,
+ 0x5511, 0x5511, 0x5511, 0x5512, 0x5512, 0x5512, 0x5512, 0x5512,
+ 0x5512, 0x5512, 0x5512, 0x5512, 0x5512, 0x5512, 0x5512, 0x5513,
+ 0x5513, 0x5513, 0x5513, 0x5513, 0x5513, 0x5513, 0x5513, 0x5513,
+ 0x5513, 0x5513, 0x5513, 0x5513, 0x5514, 0x5514, 0x5514, 0x5514,
+ 0x5514, 0x5514, 0x5514, 0x5514, 0x5514, 0x5514, 0x5514, 0x5514,
+ 0x5515, 0x5515, 0x5515, 0x5515, 0x5515, 0x5515, 0x5515, 0x5515,
+ 0x5515, 0x5515, 0x5515, 0x5515, 0x5515, 0x5516, 0x5516, 0x5516,
+ 0x5516, 0x5516, 0x5516, 0x5516, 0x5516, 0x5516, 0x5516, 0x5516,
+ 0x5516, 0x5516, 0x5517, 0x5517, 0x5517, 0x5517, 0x5517, 0x5517,
+ 0x5517, 0x5517, 0x5517, 0x5517, 0x5517, 0x5517, 0x5517, 0x5518,
+ 0x5518, 0x5518, 0x5518, 0x5518, 0x5518, 0x5518, 0x5518, 0x5518,
+ 0x5518, 0x5518, 0x5518, 0x5518, 0x5519, 0x5519, 0x5519, 0x5519,
+ 0x5519, 0x5519, 0x5519, 0x5519, 0x5519, 0x5519, 0x5519, 0x5519,
+ 0x5519, 0x551a, 0x551a, 0x551a, 0x551a, 0x551a, 0x551a, 0x551a,
+ 0x551a, 0x551a, 0x551a, 0x551a, 0x551a, 0x551a, 0x551b, 0x551b,
+ 0x551b, 0x551b, 0x551b, 0x551b, 0x551b, 0x551b, 0x551b, 0x551b,
+ 0x551b, 0x551b, 0x551b, 0x551c, 0x551c, 0x551c, 0x551c, 0x551c,
+ 0x551c, 0x551c, 0x551c, 0x551c, 0x551c, 0x551c, 0x551c, 0x551c,
+ 0x551d, 0x551d, 0x551d, 0x551d, 0x551d, 0x551d, 0x551d, 0x551d,
+ 0x551d, 0x551d, 0x551d, 0x551d, 0x551d, 0x551d, 0x551e, 0x551e,
+ 0x551e, 0x551e, 0x551e, 0x551e, 0x551e, 0x551e, 0x551e, 0x551e,
+ 0x551e, 0x551e, 0x551e, 0x551e, 0x551f, 0x551f, 0x551f, 0x551f,
+ 0x551f, 0x551f, 0x551f, 0x551f, 0x551f, 0x551f, 0x551f, 0x551f,
+ 0x551f, 0x5520, 0x5520, 0x5520, 0x5520, 0x5520, 0x5520, 0x5520,
+ 0x5520, 0x5520, 0x5520, 0x5520, 0x5520, 0x5520, 0x5520, 0x5521,
+ 0x5521, 0x5521, 0x5521, 0x5521, 0x5521, 0x5521, 0x5521, 0x5521,
+ 0x5521, 0x5521, 0x5521, 0x5521, 0x5521, 0x5522, 0x5522, 0x5522,
+ 0x5522, 0x5522, 0x5522, 0x5522, 0x5522, 0x5522, 0x5522, 0x5522,
+ 0x5522, 0x5522, 0x5522, 0x5523, 0x5523, 0x5523, 0x5523, 0x5523,
+ 0x5523, 0x5523, 0x5523, 0x5523, 0x5523, 0x5523, 0x5523, 0x5523,
+ 0x5523, 0x5524, 0x5524, 0x5524, 0x5524, 0x5524, 0x5524, 0x5524,
+ 0x5524, 0x5524, 0x5524, 0x5524, 0x5524, 0x5524, 0x5524, 0x5525,
+ 0x5525, 0x5525, 0x5525, 0x5525, 0x5525, 0x5525, 0x5525, 0x5525,
+ 0x5525, 0x5525, 0x5525, 0x5525, 0x5525, 0x5525, 0x5526, 0x5526,
+ 0x5526, 0x5526, 0x5526, 0x5526, 0x5526, 0x5526, 0x5526, 0x5526,
+ 0x5526, 0x5526, 0x5526, 0x5526, 0x5527, 0x5527, 0x5527, 0x5527,
+ 0x5527, 0x5527, 0x5527, 0x5527, 0x5527, 0x5527, 0x5527, 0x5527,
+ 0x5527, 0x5527, 0x5527, 0x5528, 0x5528, 0x5528, 0x5528, 0x5528,
+ 0x5528, 0x5528, 0x5528, 0x5528, 0x5528, 0x5528, 0x5528, 0x5528,
+ 0x5528, 0x5528, 0x5529, 0x5529, 0x5529, 0x5529, 0x5529, 0x5529,
+ 0x5529, 0x5529, 0x5529, 0x5529, 0x5529, 0x5529, 0x5529, 0x5529,
+ 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552a,
+ 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552a, 0x552b,
+ 0x552b, 0x552b, 0x552b, 0x552b, 0x552b, 0x552b, 0x552b, 0x552b,
+ 0x552b, 0x552b, 0x552b, 0x552b, 0x552b, 0x552b, 0x552c, 0x552c,
+ 0x552c, 0x552c, 0x552c, 0x552c, 0x552c, 0x552c, 0x552c, 0x552c,
+ 0x552c, 0x552c, 0x552c, 0x552c, 0x552c, 0x552d, 0x552d, 0x552d,
+ 0x552d, 0x552d, 0x552d, 0x552d, 0x552d, 0x552d, 0x552d, 0x552d,
+ 0x552d, 0x552d, 0x552d, 0x552d, 0x552d, 0x552e, 0x552e, 0x552e,
+ 0x552e, 0x552e, 0x552e, 0x552e, 0x552e, 0x552e, 0x552e, 0x552e,
+ 0x552e, 0x552e, 0x552e, 0x552e, 0x552f, 0x552f, 0x552f, 0x552f,
+ 0x552f, 0x552f, 0x552f, 0x552f, 0x552f, 0x552f, 0x552f, 0x552f,
+ 0x552f, 0x552f, 0x552f, 0x552f, 0x5530, 0x5530, 0x5530, 0x5530,
+ 0x5530, 0x5530, 0x5530, 0x5530, 0x5530, 0x5530, 0x5530, 0x5530,
+ 0x5530, 0x5530, 0x5530, 0x5531, 0x5531, 0x5531, 0x5531, 0x5531,
+ 0x5531, 0x5531, 0x5531, 0x5531, 0x5531, 0x5531, 0x5531, 0x5531,
+ 0x5531, 0x5531, 0x5531, 0x5532, 0x5532, 0x5532, 0x5532, 0x5532,
+ 0x5532, 0x5532, 0x5532, 0x5532, 0x5532, 0x5532, 0x5532, 0x5532,
+ 0x5532, 0x5532, 0x5532, 0x5533, 0x5533, 0x5533, 0x5533, 0x5533,
+ 0x5533, 0x5533, 0x5533, 0x5533, 0x5533, 0x5533, 0x5534, 0x5534,
+ 0x5534, 0x5534, 0x5534, 0x5534, 0x5534, 0x5534, 0x5535, 0x5535,
+ 0x5535, 0x5535, 0x5535, 0x5535, 0x5535, 0x5535, 0x5536, 0x5536,
+ 0x5536, 0x5536, 0x5536, 0x5536, 0x5536, 0x5536, 0x5537, 0x5537,
+ 0x5537, 0x5537, 0x5537, 0x5537, 0x5537, 0x5537, 0x5538, 0x5538,
+ 0x5538, 0x5538, 0x5538, 0x5538, 0x5538, 0x5538, 0x5538, 0x5539,
+ 0x5539, 0x5539, 0x5539, 0x5539, 0x5539, 0x5539, 0x5539, 0x553a,
+ 0x553a, 0x553a, 0x553a, 0x553a, 0x553a, 0x553a, 0x553a, 0x553a,
+ 0x553b, 0x553b, 0x553b, 0x553b, 0x553b, 0x553b, 0x553b, 0x553b,
+ 0x553c, 0x553c, 0x553c, 0x553c, 0x553c, 0x553c, 0x553c, 0x553c,
+ 0x553c, 0x553d, 0x553d, 0x553d, 0x553d, 0x553d, 0x553d, 0x553d,
+ 0x553d, 0x553e, 0x553e, 0x553e, 0x553e, 0x553e, 0x553e, 0x553e,
+ 0x553e, 0x553e, 0x553f, 0x553f, 0x553f, 0x553f, 0x553f, 0x553f,
+ 0x553f, 0x553f, 0x553f, 0x5540, 0x5540, 0x5540, 0x5540, 0x5540,
+ 0x5540, 0x5540, 0x5540, 0x5540, 0x5541, 0x5541, 0x5541, 0x5541,
+ 0x5541, 0x5541, 0x5541, 0x5541, 0x5541, 0x5542, 0x5542, 0x5542,
+ 0x5542, 0x5542, 0x5542, 0x5542, 0x5542, 0x5542, 0x5543, 0x5543,
+ 0x5543, 0x5543, 0x5543, 0x5543, 0x5543, 0x5543, 0x5543, 0x5544,
+ 0x5544, 0x5544, 0x5544, 0x5544, 0x5544, 0x5544, 0x5544, 0x5544,
+ 0x5545, 0x5545, 0x5545, 0x5545, 0x5545, 0x5545, 0x5545, 0x5545,
+ 0x5545, 0x5546, 0x5546, 0x5546, 0x5546, 0x5546, 0x5546, 0x5546,
+ 0x5546, 0x5546, 0x5547, 0x5547, 0x5547, 0x5547, 0x5547, 0x5547,
+ 0x5547, 0x5547, 0x5547, 0x5547, 0x5548, 0x5548, 0x5548, 0x5548,
+ 0x5548, 0x5548, 0x5548, 0x5548, 0x5548, 0x5549, 0x5549, 0x5549,
+ 0x5549, 0x5549, 0x5549, 0x5549, 0x5549, 0x5549, 0x5549, 0x554a,
+ 0x554a, 0x554a, 0x554a, 0x554a, 0x554a, 0x554a, 0x554a, 0x554a,
+ 0x554b, 0x554b, 0x554b, 0x554b, 0x554b, 0x554b, 0x554b, 0x554b,
+ 0x554b, 0x554b, 0x554c, 0x554c, 0x554c, 0x554c, 0x554c, 0x554c,
+ 0x554c, 0x554c, 0x554c, 0x554c, 0x554d, 0x554d, 0x554d, 0x554d,
+ 0x554d, 0x554d, 0x554d, 0x554d, 0x554d, 0x554d, 0x554e, 0x554e,
+ 0x554e, 0x554e, 0x554e, 0x554e, 0x554e, 0x554e, 0x554e, 0x554f,
+ 0x554f, 0x554f, 0x554f, 0x554f, 0x554f, 0x554f, 0x554f, 0x554f,
+ 0x554f, 0x5550, 0x5550, 0x5550, 0x5550, 0x5550, 0x5550, 0x5550,
+ 0x5550, 0x5550, 0x5550, 0x5551, 0x5551, 0x5551, 0x5551, 0x5551,
+ 0x5551, 0x5551, 0x5551, 0x5551, 0x5551, 0x5551, 0x5552, 0x5552,
+ 0x5552, 0x5552, 0x5552, 0x5552, 0x5552, 0x5552, 0x5552, 0x5552,
+ 0x5553, 0x5553, 0x5553, 0x5553, 0x5553, 0x5553, 0x5553, 0x5553,
+ 0x5553, 0x5553, 0x5554, 0x5554, 0x5554, 0x5554, 0x5554, 0x5554,
+ 0x5554, 0x5554, 0x5554, 0x5554, 0x5555, 0x5555, 0x5555, 0x5555,
+ 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5556,
+ 0x5556, 0x5556, 0x5556, 0x5556, 0x5556, 0x5556, 0x5556, 0x5556,
+ 0x5556, 0x5557, 0x5557, 0x5557, 0x5557, 0x5557, 0x5557, 0x5557,
+ 0x5557, 0x5557, 0x5557, 0x5557, 0x5558, 0x5558, 0x5558, 0x5558,
+ 0x5558, 0x5558, 0x5558, 0x5558, 0x5558, 0x5558, 0x5558, 0x5559,
+ 0x5559, 0x5559, 0x5559, 0x5559, 0x5559, 0x5559, 0x5559, 0x5559,
+ 0x5559, 0x5559, 0x555a, 0x555a, 0x555a, 0x555a, 0x555a, 0x555a,
+ 0x555a, 0x555a, 0x555a, 0x555a, 0x555b, 0x555b, 0x555b, 0x555b,
+ 0x555b, 0x555b, 0x555b, 0x555b, 0x555b, 0x555b, 0x555b, 0x555c,
+ 0x555c, 0x555c, 0x555c, 0x555c, 0x555c, 0x555c, 0x555c, 0x555c,
+ 0x555c, 0x555c, 0x555d, 0x555d, 0x555d, 0x555d, 0x555d, 0x555d,
+ 0x555d, 0x555d, 0x555d, 0x555d, 0x555d, 0x555d, 0x555e, 0x555e,
+ 0x555e, 0x555e, 0x555e, 0x555e, 0x555e, 0x555e, 0x555e, 0x555e,
+ 0x555e, 0x555f, 0x555f, 0x555f, 0x555f, 0x555f, 0x555f, 0x555f,
+ 0x555f, 0x555f, 0x555f, 0x555f, 0x5560, 0x5560, 0x5560, 0x5560,
+ 0x5560, 0x5560, 0x5560, 0x5560, 0x5560, 0x5560, 0x5560, 0x5561,
+ 0x5561, 0x5561, 0x5561, 0x5561, 0x5561, 0x5561, 0x5561, 0x5561,
+ 0x5561, 0x5561, 0x5561, 0x5562, 0x5562, 0x5562, 0x5562, 0x5562,
+ 0x5562, 0x5562, 0x5562, 0x5562, 0x5562, 0x5562, 0x5563, 0x5563,
+ 0x5563, 0x5563, 0x5563, 0x5563, 0x5563, 0x5563, 0x5563, 0x5563,
+ 0x5563, 0x5563, 0x5564, 0x5564, 0x5564, 0x5564, 0x5564, 0x5564,
+ 0x5564, 0x5564, 0x5564, 0x5564, 0x5564, 0x5564, 0x5565, 0x5565,
+ 0x5565, 0x5565, 0x5565, 0x5565, 0x5565, 0x5565, 0x5565, 0x5565,
+ 0x5565, 0x5565, 0x5566, 0x5566, 0x5566, 0x5566, 0x5566, 0x5566,
+ 0x5566, 0x5566, 0x5566, 0x5566, 0x5566, 0x5566, 0x5567, 0x5567,
+ 0x5567, 0x5567, 0x5567, 0x5567, 0x5567, 0x5567, 0x5567, 0x5567,
+ 0x5567, 0x5567, 0x5568, 0x5568, 0x5568, 0x5568, 0x5568, 0x5568,
+ 0x5568, 0x5568, 0x5568, 0x5568, 0x5568, 0x5568, 0x5569, 0x5569,
+ 0x5569, 0x5569, 0x5569, 0x5569, 0x5569, 0x5569, 0x5569, 0x5569,
+ 0x5569, 0x5569, 0x556a, 0x556a, 0x556a, 0x556a, 0x556a, 0x556a,
+ 0x556a, 0x556a, 0x556a, 0x556a, 0x556a, 0x556a, 0x556b, 0x556b,
+ 0x556b, 0x556b, 0x556b, 0x556b, 0x556b, 0x556b, 0x556b, 0x556b,
+ 0x556b, 0x556b, 0x556b, 0x556c, 0x556c, 0x556c, 0x556c, 0x556c,
+ 0x556c, 0x556c, 0x556c, 0x556c, 0x556c, 0x556c, 0x556c, 0x556d,
+ 0x556d, 0x556d, 0x556d, 0x556d, 0x556d, 0x556d, 0x556d, 0x556d,
+ 0x556d, 0x556d, 0x556d, 0x556d, 0x556e, 0x556e, 0x556e, 0x556e,
+ 0x556e, 0x556e, 0x556e, 0x556e, 0x556e, 0x556e, 0x556e, 0x556e,
+ 0x556f, 0x556f, 0x556f, 0x556f, 0x556f, 0x556f, 0x556f, 0x556f,
+ 0x556f, 0x556f, 0x556f, 0x556f, 0x556f, 0x5570, 0x5570, 0x5570,
+ 0x5570, 0x5570, 0x5570, 0x5570, 0x5570, 0x5570, 0x5570, 0x5570,
+ 0x5570, 0x5570, 0x5571, 0x5571, 0x5571, 0x5571, 0x5571, 0x5571,
+ 0x5571, 0x5571, 0x5571, 0x5571, 0x5571, 0x5571, 0x5571, 0x5572,
+ 0x5572, 0x5572, 0x5572, 0x5572, 0x5572, 0x5572, 0x5572, 0x5572,
+ 0x5572, 0x5572, 0x5572, 0x5572, 0x5573, 0x5573, 0x5573, 0x5573,
+ 0x5573, 0x5573, 0x5573, 0x5573, 0x5573, 0x5573, 0x5573, 0x5573,
+ 0x5573, 0x5574, 0x5574, 0x5574, 0x5574, 0x5574, 0x5574, 0x5574,
+ 0x5574, 0x5574, 0x5574, 0x5574, 0x5574, 0x5574, 0x5574, 0x5575,
+ 0x5575, 0x5575, 0x5575, 0x5575, 0x5575, 0x5575, 0x5575, 0x5575,
+ 0x5575, 0x5575, 0x5575, 0x5575, 0x5576, 0x5576, 0x5576, 0x5576,
+ 0x5576, 0x5576, 0x5576, 0x5576, 0x5576, 0x5576, 0x5576, 0x5576,
+ 0x5576, 0x5576, 0x5577, 0x5577, 0x5577, 0x5577, 0x5577, 0x5577,
+ 0x5577, 0x5577, 0x5577, 0x5577, 0x5577, 0x5577, 0x5577, 0x5578,
+ 0x5578, 0x5578, 0x5578, 0x5578, 0x5578, 0x5578, 0x5578, 0x5578,
+ 0x5578, 0x5578, 0x5578, 0x5578, 0x5578, 0x5579, 0x5579, 0x5579,
+ 0x5579, 0x5579, 0x5579, 0x5579, 0x5579, 0x5579, 0x5579, 0x5579,
+ 0x5579, 0x5579, 0x5579, 0x557a, 0x557a, 0x557a, 0x557a, 0x557a,
+ 0x557a, 0x557a, 0x557a, 0x557a, 0x557a, 0x557a, 0x557a, 0x557a,
+ 0x557a, 0x557b, 0x557b, 0x557b, 0x557b, 0x557b, 0x557b, 0x557b,
+ 0x557b, 0x557b, 0x557b, 0x557b, 0x557b, 0x557b, 0x557b, 0x557c,
+ 0x557c, 0x557c, 0x557c, 0x557c, 0x557c, 0x557c, 0x557c, 0x557c,
+ 0x557c, 0x557c, 0x557c, 0x557c, 0x557c, 0x557d, 0x557d, 0x557d,
+ 0x557d, 0x557d, 0x557d, 0x557d, 0x557d, 0x557d, 0x557d, 0x557d,
+ 0x557d, 0x557d, 0x557d, 0x557e, 0x557e, 0x557e, 0x557e, 0x557e,
+ 0x557e, 0x557e, 0x557e, 0x557e, 0x557e, 0x557e, 0x557e, 0x557e,
+ 0x557e, 0x557e, 0x557f, 0x557f, 0x557f, 0x557f, 0x557f, 0x557f,
+ 0x557f, 0x557f, 0x557f, 0x557f, 0x557f, 0x557f, 0x557f, 0x557f,
+ 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5580,
+ 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5580, 0x5581,
+ 0x5581, 0x5581, 0x5581, 0x5581, 0x5581, 0x5581, 0x5581, 0x5581,
+ 0x5581, 0x5581, 0x5581, 0x5581, 0x5581, 0x5581, 0x5582, 0x5582,
+ 0x5582, 0x5582, 0x5582, 0x5582, 0x5582, 0x5582, 0x5582, 0x5582,
+ 0x5582, 0x5582, 0x5582, 0x5582, 0x5583, 0x5583, 0x5583, 0x5583,
+ 0x5583, 0x5583, 0x5583, 0x5583, 0x5583, 0x5583, 0x5583, 0x5583,
+ 0x5583, 0x5583, 0x5583, 0x5584, 0x5584, 0x5584, 0x5584, 0x5584,
+ 0x5584, 0x5584, 0x5584, 0x5584, 0x5584, 0x5584, 0x5584, 0x5584,
+ 0x5584, 0x5584, 0x5584, 0x5585, 0x5585, 0x5585, 0x5585, 0x5585,
+ 0x5585, 0x5585, 0x5585, 0x5585, 0x5585, 0x5585, 0x5585, 0x5585,
+ 0x5585, 0x5585, 0x5586, 0x5586, 0x5586, 0x5586, 0x5586, 0x5586,
+ 0x5586, 0x5586, 0x5586, 0x5586, 0x5586, 0x5586, 0x5586, 0x5586,
+ 0x5586, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587,
+ 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587, 0x5587,
+ 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588,
+ 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588, 0x5588,
+ 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589,
+ 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589, 0x5589,
+ 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a,
+ 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a, 0x558a,
+ 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558b,
+ 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558b, 0x558c,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xfc00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
diff --git a/Source/OpenEXR/IlmThread/IlmThread.cpp b/Source/OpenEXR/IlmThread/IlmThread.cpp
new file mode 100644
index 0000000..71563d7
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThread.cpp
@@ -0,0 +1,80 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Thread -- dummy implementation for
+// platforms that do not support threading
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+//#if !defined (_WIN32) &&!(_WIN64) && !(HAVE_PTHREAD)
+
+#include "IlmThread.h"
+#include "Iex.h"
+
+namespace IlmThread {
+
+
+bool
+supportsThreads ()
+{
+ return false;
+}
+
+
+Thread::Thread ()
+{
+ throw Iex::NoImplExc ("Threads not supported on this platform.");
+}
+
+
+Thread::~Thread ()
+{
+ throw Iex::NoImplExc ("Threads not supported on this platform.");
+}
+
+
+void
+Thread::start ()
+{
+ throw Iex::NoImplExc ("Threads not supported on this platform.");
+}
+
+
+} // namespace IlmThread
+
+//#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThread.h b/Source/OpenEXR/IlmThread/IlmThread.h
new file mode 100644
index 0000000..e5ca595
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThread.h
@@ -0,0 +1,151 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_ILM_THREAD_H
+#define INCLUDED_ILM_THREAD_H
+
+//-----------------------------------------------------------------------------
+//
+// class Thread
+//
+// Class Thread is a portable interface to a system-dependent thread
+// primitive. In order to make a thread actually do something useful,
+// you must derive a subclass from class Thread and implement the
+// run() function. If the operating system supports threading then
+// the run() function will be executed int a new thread.
+//
+// The actual creation of the thread is done by the start() routine
+// which then calls the run() function. In general the start()
+// routine should be called from the constructor of the derived class.
+//
+// The base-class thread destructor will join/destroy the thread.
+//
+// IMPORTANT: Due to the mechanisms that encapsulate the low-level
+// threading primitives in a C++ class there is a race condition
+// with code resembling the following:
+//
+// {
+// WorkerThread myThread;
+// } // myThread goes out of scope, is destroyed
+// // and the thread is joined
+//
+// The race is between the parent thread joining the child thread
+// in the destructor of myThread, and the run() function in the
+// child thread. If the destructor gets executed first then run()
+// will be called with an invalid "this" pointer.
+//
+// This issue can be fixed by using a Semaphore to keep track of
+// whether the run() function has already been called. You can
+// include a Semaphore member variable within your derived class
+// which you post() on in the run() function, and wait() on in the
+// destructor before the thread is joined. Alternatively you could
+// do something like this:
+//
+// Semaphore runStarted;
+//
+// void WorkerThread::run ()
+// {
+// runStarted.post()
+// // do some work
+// ...
+// }
+//
+// {
+// WorkerThread myThread;
+// runStarted.wait (); // ensure that we have started
+// // the run function
+// } // myThread goes out of scope, is destroyed
+// // and the thread is joined
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if defined _WIN32 || defined _WIN64
+ #ifdef NOMINMAX
+ #undef NOMINMAX
+ #endif
+ #define NOMINMAX
+ #include <windows.h>
+ #include <process.h>
+#elif HAVE_PTHREAD
+ #include <pthread.h>
+#endif
+
+#if defined(OPENEXR_DLL) && !defined(ZENO_STATIC)
+ #ifdef ILMTHREAD_EXPORTS
+ #define ILMTHREAD_EXPORT __declspec(dllexport)
+ #else
+ #define ILMTHREAD_EXPORT __declspec(dllimport)
+ #endif
+#else
+ #define ILMTHREAD_EXPORT
+#endif
+
+namespace IlmThread {
+
+//
+// Query function to determine if the current platform supports
+// threads AND this library was compiled with threading enabled.
+//
+
+ILMTHREAD_EXPORT bool supportsThreads ();
+
+
+class ILMTHREAD_EXPORT Thread
+{
+ public:
+
+ Thread ();
+ virtual ~Thread ();
+
+ void start ();
+ virtual void run () = 0;
+
+ private:
+
+ #if defined _WIN32 || defined _WIN64
+ HANDLE _thread;
+ #elif HAVE_PTHREAD
+ pthread_t _thread;
+ #endif
+
+ void operator = (const Thread& t); // not implemented
+ Thread (const Thread& t); // not implemented
+};
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadMutex.cpp b/Source/OpenEXR/IlmThread/IlmThreadMutex.cpp
new file mode 100644
index 0000000..7a7a4a6
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadMutex.cpp
@@ -0,0 +1,59 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Mutex, class Lock -- dummy implementation
+// for platforms that do not support threading
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+//#if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD)
+
+#include "IlmThreadMutex.h"
+
+namespace IlmThread {
+
+
+Mutex::Mutex () {}
+Mutex::~Mutex () {}
+void Mutex::lock () const {}
+void Mutex::unlock () const {}
+
+
+} // namespace IlmThread
+
+//#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadMutex.h b/Source/OpenEXR/IlmThread/IlmThreadMutex.h
new file mode 100644
index 0000000..354282b
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadMutex.h
@@ -0,0 +1,158 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_ILM_THREAD_MUTEX_H
+#define INCLUDED_ILM_THREAD_MUTEX_H
+
+//-----------------------------------------------------------------------------
+//
+// class Mutex, class Lock
+//
+// Class Mutex is a wrapper for a system-dependent mutual exclusion
+// mechanism. Actual locking and unlocking of a Mutex object must
+// be performed using an instance of a Lock (defined below).
+//
+// Class lock provides safe locking and unlocking of mutexes even in
+// the presence of C++ exceptions. Constructing a Lock object locks
+// the mutex; destroying the Lock unlocks the mutex.
+//
+// Lock objects are not themselves thread-safe. You should never
+// share a Lock object among multiple threads.
+//
+// Typical usage:
+//
+// Mutex mtx; // Create a Mutex object that is visible
+// //to multiple threads
+//
+// ... // create some threads
+//
+// // Then, within each thread, construct a critical section like so:
+//
+// {
+// Lock lock (mtx); // Lock constructor locks the mutex
+// ... // do some computation on shared data
+// } // leaving the block unlocks the mutex
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if defined _WIN32 || defined _WIN64
+ #ifdef NOMINMAX
+ #undef NOMINMAX
+ #endif
+ #define NOMINMAX
+ #include <windows.h>
+#elif HAVE_PTHREAD
+ #include <pthread.h>
+#endif
+
+namespace IlmThread {
+
+class Lock;
+
+
+class Mutex
+{
+ public:
+
+ Mutex ();
+ virtual ~Mutex ();
+
+ private:
+
+ void lock () const;
+ void unlock () const;
+
+ #if defined _WIN32 || defined _WIN64
+ mutable CRITICAL_SECTION _mutex;
+ #elif HAVE_PTHREAD
+ mutable pthread_mutex_t _mutex;
+ #endif
+
+ void operator = (const Mutex& M); // not implemented
+ Mutex (const Mutex& M); // not implemented
+
+ friend class Lock;
+};
+
+
+class Lock
+{
+ public:
+
+ Lock (const Mutex& m, bool autoLock = true):
+ _mutex (m),
+ _locked (false)
+ {
+ if (autoLock)
+ {
+ _mutex.lock();
+ _locked = true;
+ }
+ }
+
+ ~Lock ()
+ {
+ if (_locked)
+ _mutex.unlock();
+ }
+
+ void acquire ()
+ {
+ _mutex.lock();
+ _locked = true;
+ }
+
+ void release ()
+ {
+ _mutex.unlock();
+ _locked = false;
+ }
+
+ bool locked ()
+ {
+ return _locked;
+ }
+
+ private:
+
+ const Mutex & _mutex;
+ bool _locked;
+};
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadMutexPosix.cpp b/Source/OpenEXR/IlmThread/IlmThreadMutexPosix.cpp
new file mode 100644
index 0000000..5f72c10
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadMutexPosix.cpp
@@ -0,0 +1,85 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Mutex -- implementation for
+// platforms that support Posix threads
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if HAVE_PTHREAD
+
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+#include <assert.h>
+
+namespace IlmThread {
+
+
+Mutex::Mutex ()
+{
+ if (int error = ::pthread_mutex_init (&_mutex, 0))
+ Iex::throwErrnoExc ("Cannot initialize mutex (%T).", error);
+}
+
+
+Mutex::~Mutex ()
+{
+ int error = ::pthread_mutex_destroy (&_mutex);
+ assert (error == 0);
+}
+
+
+void
+Mutex::lock () const
+{
+ if (int error = ::pthread_mutex_lock (&_mutex))
+ Iex::throwErrnoExc ("Cannot lock mutex (%T).", error);
+}
+
+
+void
+Mutex::unlock () const
+{
+ if (int error = ::pthread_mutex_unlock (&_mutex))
+ Iex::throwErrnoExc ("Cannot unlock mutex (%T).", error);
+}
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadMutexWin32.cpp b/Source/OpenEXR/IlmThread/IlmThreadMutexWin32.cpp
new file mode 100644
index 0000000..1a34c7e
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadMutexWin32.cpp
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Mutex -- implementation for Windows
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmThreadMutex.h"
+#include "Iex.h"
+
+namespace IlmThread {
+
+
+Mutex::Mutex ()
+{
+ ::InitializeCriticalSection (&_mutex);
+}
+
+
+Mutex::~Mutex ()
+{
+ ::DeleteCriticalSection (&_mutex);
+}
+
+
+void
+Mutex::lock () const
+{
+ ::EnterCriticalSection (&_mutex);
+}
+
+
+void
+Mutex::unlock () const
+{
+ ::LeaveCriticalSection (&_mutex);
+}
+
+
+} // namespace IlmThread
diff --git a/Source/OpenEXR/IlmThread/IlmThreadPool.cpp b/Source/OpenEXR/IlmThread/IlmThreadPool.cpp
new file mode 100644
index 0000000..1b134c3
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadPool.cpp
@@ -0,0 +1,456 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Task, class ThreadPool, class TaskGroup
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmThread.h"
+#include "IlmThreadMutex.h"
+#include "IlmThreadSemaphore.h"
+#include "IlmThreadPool.h"
+#include "Iex.h"
+#include <list>
+
+using namespace std;
+
+namespace IlmThread {
+namespace {
+
+class WorkerThread: public Thread
+{
+ public:
+
+ WorkerThread (ThreadPool::Data* data);
+
+ virtual void run ();
+
+ private:
+
+ ThreadPool::Data * _data;
+};
+
+} //namespace
+
+
+struct TaskGroup::Data
+{
+ Data ();
+ ~Data ();
+
+ void addTask () ;
+ void removeTask ();
+
+ Semaphore isEmpty; // used to signal that the taskgroup is empty
+ int numPending; // number of pending tasks to still execute
+};
+
+
+struct ThreadPool::Data
+{
+ Data ();
+ ~Data();
+
+ void finish ();
+ bool stopped () const;
+ void stop ();
+
+ Semaphore taskSemaphore; // threads wait on this for ready tasks
+ Mutex taskMutex; // mutual exclusion for the tasks list
+ list<Task*> tasks; // the list of tasks to execute
+ size_t numTasks; // fast access to list size
+ // (list::size() can be O(n))
+
+ Semaphore threadSemaphore; // signaled when a thread starts executing
+ Mutex threadMutex; // mutual exclusion for threads list
+ list<WorkerThread*> threads; // the list of all threads
+ size_t numThreads; // fast access to list size
+
+ bool stopping; // flag indicating whether to stop threads
+ Mutex stopMutex; // mutual exclusion for stopping flag
+};
+
+
+//
+// The global thread pool
+//
+
+ThreadPool gThreadPool (0);
+
+
+//
+// class WorkerThread
+//
+
+WorkerThread::WorkerThread (ThreadPool::Data* data):
+ _data (data)
+{
+ start();
+}
+
+
+void
+WorkerThread::run ()
+{
+ //
+ // Signal that the thread has started executing
+ //
+
+ _data->threadSemaphore.post();
+
+ while (true)
+ {
+ //
+ // Wait for a task to become available
+ //
+
+ _data->taskSemaphore.wait();
+
+ {
+ Lock taskLock (_data->taskMutex);
+
+ //
+ // If there is a task pending, pop off the next task in the FIFO
+ //
+
+ if (_data->numTasks > 0)
+ {
+ Task* task = _data->tasks.front();
+ TaskGroup* taskGroup = task->group();
+ _data->tasks.pop_front();
+ _data->numTasks--;
+
+ taskLock.release();
+ task->execute();
+ taskLock.acquire();
+
+ delete task;
+ taskGroup->_data->removeTask();
+ }
+ else if (_data->stopped())
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+//
+// struct TaskGroup::Data
+//
+
+TaskGroup::Data::Data (): isEmpty (1), numPending (0)
+{
+ // empty
+}
+
+
+TaskGroup::Data::~Data ()
+{
+ //
+ // A TaskGroup acts like an "inverted" semaphore: if the count
+ // is above 0 then waiting on the taskgroup will block. This
+ // destructor waits until the taskgroup is empty before returning.
+ //
+
+ isEmpty.wait ();
+}
+
+
+void
+TaskGroup::Data::addTask ()
+{
+ //
+ // Any access to the taskgroup is protected by a mutex that is
+ // held by the threadpool. Therefore it is safe to access
+ // numPending before we wait on the semaphore.
+ //
+
+ if (numPending++ == 0)
+ isEmpty.wait ();
+}
+
+
+void
+TaskGroup::Data::removeTask ()
+{
+ if (--numPending == 0)
+ isEmpty.post ();
+}
+
+
+//
+// struct ThreadPool::Data
+//
+
+ThreadPool::Data::Data (): numTasks (0), numThreads (0), stopping (false)
+{
+ // empty
+}
+
+
+ThreadPool::Data::~Data()
+{
+ Lock lock (threadMutex);
+ finish ();
+}
+
+
+void
+ThreadPool::Data::finish ()
+{
+ stop();
+
+ //
+ // Signal enough times to allow all threads to stop.
+ //
+ // Wait until all threads have started their run functions.
+ // If we do not wait before we destroy the threads then it's
+ // possible that the threads have not yet called their run
+ // functions.
+ // If this happens then the run function will be called off
+ // of an invalid object and we will crash, most likely with
+ // an error like: "pure virtual method called"
+ //
+
+ for (int i = 0; i < numThreads; i++)
+ {
+ taskSemaphore.post();
+ threadSemaphore.wait();
+ }
+
+ //
+ // Join all the threads
+ //
+
+ for (list<WorkerThread*>::iterator i = threads.begin();
+ i != threads.end();
+ ++i)
+ {
+ delete (*i);
+ }
+
+ Lock lock1 (taskMutex);
+ Lock lock2 (stopMutex);
+ threads.clear();
+ tasks.clear();
+ numThreads = 0;
+ numTasks = 0;
+ stopping = false;
+}
+
+
+bool
+ThreadPool::Data::stopped () const
+{
+ Lock lock (stopMutex);
+ return stopping;
+}
+
+
+void
+ThreadPool::Data::stop ()
+{
+ Lock lock (stopMutex);
+ stopping = true;
+}
+
+
+//
+// class Task
+//
+
+Task::Task (TaskGroup* g): _group(g)
+{
+ // empty
+}
+
+
+Task::~Task()
+{
+ // empty
+}
+
+
+TaskGroup*
+Task::group ()
+{
+ return _group;
+}
+
+
+TaskGroup::TaskGroup ():
+ _data (new Data())
+{
+ // empty
+}
+
+
+TaskGroup::~TaskGroup ()
+{
+ delete _data;
+}
+
+
+//
+// class ThreadPool
+//
+
+ThreadPool::ThreadPool (unsigned nthreads):
+ _data (new Data())
+{
+ setNumThreads (nthreads);
+}
+
+
+ThreadPool::~ThreadPool ()
+{
+ delete _data;
+}
+
+
+int
+ThreadPool::numThreads () const
+{
+ Lock lock (_data->threadMutex);
+ return _data->numThreads;
+}
+
+
+void
+ThreadPool::setNumThreads (int count)
+{
+ if (count < 0)
+ throw Iex::ArgExc ("Attempt to set the number of threads "
+ "in a thread pool to a negative value.");
+
+ //
+ // Lock access to thread list and size
+ //
+
+ Lock lock (_data->threadMutex);
+
+ if (count > _data->numThreads)
+ {
+ //
+ // Add more threads
+ //
+
+ while (_data->numThreads < count)
+ {
+ _data->threads.push_back (new WorkerThread (_data));
+ _data->numThreads++;
+ }
+ }
+ else if (count < _data->numThreads)
+ {
+ //
+ // Wait until all existing threads are finished processing,
+ // then delete all threads.
+ //
+
+ _data->finish ();
+
+ //
+ // Add in new threads
+ //
+
+ while (_data->numThreads < count)
+ {
+ _data->threads.push_back (new WorkerThread (_data));
+ _data->numThreads++;
+ }
+ }
+}
+
+
+void
+ThreadPool::addTask (Task* task)
+{
+ //
+ // Lock the threads, needed to access numThreads
+ //
+
+ Lock lock (_data->threadMutex);
+
+ if (_data->numThreads == 0)
+ {
+ task->execute ();
+ delete task;
+ }
+ else
+ {
+ //
+ // Get exclusive access to the tasks queue
+ //
+
+ {
+ Lock taskLock (_data->taskMutex);
+
+ //
+ // Push the new task into the FIFO
+ //
+
+ _data->tasks.push_back (task);
+ _data->numTasks++;
+ task->group()->_data->addTask();
+ }
+
+ //
+ // Signal that we have a new task to process
+ //
+
+ _data->taskSemaphore.post ();
+ }
+}
+
+
+ThreadPool&
+ThreadPool::globalThreadPool ()
+{
+ return gThreadPool;
+}
+
+
+void
+ThreadPool::addGlobalTask (Task* task)
+{
+ gThreadPool.addTask (task);
+}
+
+
+} // namespace IlmThread
diff --git a/Source/OpenEXR/IlmThread/IlmThreadPool.h b/Source/OpenEXR/IlmThread/IlmThreadPool.h
new file mode 100644
index 0000000..39be1a8
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadPool.h
@@ -0,0 +1,156 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_ILM_THREAD_POOL_H
+#define INCLUDED_ILM_THREAD_POOL_H
+
+//-----------------------------------------------------------------------------
+//
+// class Task, class ThreadPool, class TaskGroup
+//
+// Class ThreadPool manages a set of worker threads and accepts
+// tasks for processing. Tasks added to the thread pool are
+// executed concurrently by the worker threads.
+//
+// Class Thread provides an abstract interface for a task which
+// a ThreadPool works on. Derived classes need to implement the
+// execute() function which performs the actual task.
+//
+// Class TaskTroup allows synchronization on the completion of a set
+// of tasks. Every task that is added to a ThreadPool belongs to a
+// single TaskGroup. The destructor of the TaskGroup waits for all
+// tasks in the group to finish.
+//
+// Note: if you plan to use the ThreadPool interface in your own
+// applications note that the implementation of the ThreadPool calls
+// opertor delete on tasks as they complete. If you define a custom
+// operator new for your tasks, for instance to use a custom heap,
+// then you must also write an appropriate operator delete.
+//
+//-----------------------------------------------------------------------------
+
+namespace IlmThread {
+
+class TaskGroup;
+class Task;
+
+
+class ThreadPool
+{
+ public:
+
+ //-------------------------------------------------------
+ // Constructor -- creates numThreads worker threads which
+ // wait until a task is available.
+ //-------------------------------------------------------
+
+ ThreadPool (unsigned numThreads = 0);
+
+
+ //-----------------------------------------------------------
+ // Destructor -- waits for all tasks to complete, joins all
+ // the threads to the calling thread, and then destroys them.
+ //-----------------------------------------------------------
+
+ virtual ~ThreadPool ();
+
+
+ //--------------------------------------------------------
+ // Query and set the number of worker threads in the pool.
+ //
+ // Warning: never call setNumThreads from within a worker
+ // thread as this will almost certainly cause a deadlock
+ // or crash.
+ //--------------------------------------------------------
+
+ int numThreads () const;
+ void setNumThreads (int count);
+
+
+ //------------------------------------------------------------
+ // Add a task for processing. The ThreadPool can handle any
+ // number of tasks regardless of the number of worker threads.
+ // The tasks are first added onto a queue, and are executed
+ // by threads as they become available, in FIFO order.
+ //------------------------------------------------------------
+
+ void addTask (Task* task);
+
+
+ //-------------------------------------------
+ // Access functions for the global threadpool
+ //-------------------------------------------
+
+ static ThreadPool& globalThreadPool ();
+ static void addGlobalTask (Task* task);
+
+ struct Data;
+
+ protected:
+
+ Data * _data;
+};
+
+
+class Task
+{
+ public:
+
+ Task (TaskGroup* g);
+ virtual ~Task ();
+
+ virtual void execute () = 0;
+ TaskGroup * group();
+
+ protected:
+
+ TaskGroup * _group;
+};
+
+
+class TaskGroup
+{
+ public:
+
+ TaskGroup();
+ ~TaskGroup();
+
+ struct Data;
+ Data* const _data;
+};
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadPosix.cpp b/Source/OpenEXR/IlmThread/IlmThreadPosix.cpp
new file mode 100644
index 0000000..1fe74f7
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadPosix.cpp
@@ -0,0 +1,98 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Thread -- implementation for
+// platforms that support Posix threads
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if HAVE_PTHREAD
+
+#include "IlmThread.h"
+#include "Iex.h"
+#include <assert.h>
+
+extern "C"
+{
+ typedef void * (* Start) (void *);
+}
+
+namespace IlmThread {
+
+
+bool
+supportsThreads ()
+{
+ return true;
+}
+
+namespace {
+
+void
+threadLoop (void * t)
+{
+ return (reinterpret_cast<Thread*>(t))->run();
+}
+
+} // namespace
+
+
+Thread::Thread ()
+{
+ // empty
+}
+
+
+Thread::~Thread ()
+{
+ int error = ::pthread_join (_thread, 0);
+ assert (error == 0);
+}
+
+
+void
+Thread::start ()
+{
+ if (int error = ::pthread_create (&_thread, 0, Start (threadLoop), this))
+ Iex::throwErrnoExc ("Cannot create new thread (%T).", error);
+}
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadSemaphore.cpp b/Source/OpenEXR/IlmThread/IlmThreadSemaphore.cpp
new file mode 100644
index 0000000..486aeba
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadSemaphore.cpp
@@ -0,0 +1,60 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Semaphore -- dummy implementation for
+// for platforms that do not support threading
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+//#if !defined (_WIN32) && !(_WIN64) && !(HAVE_PTHREAD)
+#include "IlmThreadSemaphore.h"
+
+namespace IlmThread {
+
+
+Semaphore::Semaphore (unsigned int value) {}
+Semaphore::~Semaphore () {}
+void Semaphore::wait () {}
+bool Semaphore::tryWait () {return true;}
+void Semaphore::post () {}
+int Semaphore::value () const {return 0;}
+
+
+} // namespace IlmThread
+
+//#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadSemaphore.h b/Source/OpenEXR/IlmThread/IlmThreadSemaphore.h
new file mode 100644
index 0000000..a9ba60a
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadSemaphore.h
@@ -0,0 +1,110 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INCLUDED_ILM_THREAD_SEMAPHORE_H
+#define INCLUDED_ILM_THREAD_SEMAPHORE_H
+
+//-----------------------------------------------------------------------------
+//
+// class Semaphore -- a wrapper class for
+// system-dependent counting semaphores
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if defined _WIN32 || defined _WIN64
+ #ifdef NOMINMAX
+ #undef NOMINMAX
+ #endif
+ #define NOMINMAX
+ #include <windows.h>
+#elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES
+ #include <pthread.h>
+#elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES
+ #include <semaphore.h>
+#endif
+
+namespace IlmThread {
+
+
+class Semaphore
+{
+ public:
+
+ Semaphore (unsigned int value = 0);
+ virtual ~Semaphore();
+
+ void wait();
+ bool tryWait();
+ void post();
+ int value() const;
+
+ private:
+
+ #if defined _WIN32 || defined _WIN64
+
+ mutable HANDLE _semaphore;
+
+ #elif HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES
+
+ //
+ // If the platform has Posix threads but no semapohores,
+ // then we implement them ourselves using condition variables
+ //
+
+ struct sema_t
+ {
+ unsigned int count;
+ unsigned long numWaiting;
+ pthread_mutex_t mutex;
+ pthread_cond_t nonZero;
+ };
+
+ mutable sema_t _semaphore;
+
+ #elif HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES
+
+ mutable sem_t _semaphore;
+
+ #endif
+
+ void operator = (const Semaphore& s); // not implemented
+ Semaphore (const Semaphore& s); // not implemented
+};
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosix.cpp b/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosix.cpp
new file mode 100644
index 0000000..b5e206e
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosix.cpp
@@ -0,0 +1,103 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Semaphore -- implementation for platforms
+// that support Posix threads and Posix semaphores
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if HAVE_PTHREAD && HAVE_POSIX_SEMAPHORES
+
+#include "IlmThreadSemaphore.h"
+#include "Iex.h"
+#include <assert.h>
+
+namespace IlmThread {
+
+
+Semaphore::Semaphore (unsigned int value)
+{
+ if (::sem_init (&_semaphore, 0, value))
+ Iex::throwErrnoExc ("Cannot initialize semaphore (%T).");
+}
+
+
+Semaphore::~Semaphore ()
+{
+ int error = ::sem_destroy (&_semaphore);
+ assert (error == 0);
+}
+
+
+void
+Semaphore::wait ()
+{
+ ::sem_wait (&_semaphore);
+}
+
+
+bool
+Semaphore::tryWait ()
+{
+ return sem_trywait (&_semaphore) == 0;
+}
+
+
+void
+Semaphore::post ()
+{
+ if (::sem_post (&_semaphore))
+ Iex::throwErrnoExc ("Post operation on semaphore failed (%T).");
+}
+
+
+int
+Semaphore::value () const
+{
+ int value;
+
+ if (::sem_getvalue (&_semaphore, &value))
+ Iex::throwErrnoExc ("Cannot read semaphore value (%T).");
+
+ return value;
+}
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosixCompat.cpp b/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosixCompat.cpp
new file mode 100644
index 0000000..33f2a5b
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadSemaphorePosixCompat.cpp
@@ -0,0 +1,155 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Semaphore -- implementation for for platforms that do
+// support Posix threads but do not support Posix semaphores,
+// for example, OS X
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmBaseConfig.h"
+
+#if HAVE_PTHREAD && !HAVE_POSIX_SEMAPHORES
+
+#include "IlmThreadSemaphore.h"
+#include "Iex.h"
+#include <assert.h>
+
+namespace IlmThread {
+
+
+Semaphore::Semaphore (unsigned int value)
+{
+ if (int error = ::pthread_mutex_init (&_semaphore.mutex, 0))
+ Iex::throwErrnoExc ("Cannot initialize mutex (%T).", error);
+
+ if (int error = ::pthread_cond_init (&_semaphore.nonZero, 0))
+ Iex::throwErrnoExc ("Cannot initialize condition variable (%T).",
+ error);
+
+ _semaphore.count = value;
+ _semaphore.numWaiting = 0;
+}
+
+
+Semaphore::~Semaphore ()
+{
+ int error = ::pthread_cond_destroy (&_semaphore.nonZero);
+ assert (error == 0);
+ error = ::pthread_mutex_destroy (&_semaphore.mutex);
+ assert (error == 0);
+}
+
+
+void
+Semaphore::wait ()
+{
+ ::pthread_mutex_lock (&_semaphore.mutex);
+
+ _semaphore.numWaiting++;
+
+ while (_semaphore.count == 0)
+ {
+ if (int error = ::pthread_cond_wait (&_semaphore.nonZero,
+ &_semaphore.mutex))
+ {
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+
+ Iex::throwErrnoExc ("Cannot wait on condition variable (%T).",
+ error);
+ }
+ }
+
+ _semaphore.numWaiting--;
+ _semaphore.count--;
+
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+}
+
+
+bool
+Semaphore::tryWait ()
+{
+ ::pthread_mutex_lock (&_semaphore.mutex);
+
+ if (_semaphore.count == 0)
+ {
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+ return false;
+ }
+ else
+ {
+ _semaphore.count--;
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+ return true;
+ }
+}
+
+
+void
+Semaphore::post ()
+{
+ ::pthread_mutex_lock (&_semaphore.mutex);
+
+ if (_semaphore.numWaiting > 0)
+ {
+ if (int error = ::pthread_cond_signal (&_semaphore.nonZero))
+ {
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+
+ Iex::throwErrnoExc ("Cannot signal condition variable (%T).",
+ error);
+ }
+ }
+
+ _semaphore.count++;
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+}
+
+
+int
+Semaphore::value () const
+{
+ ::pthread_mutex_lock (&_semaphore.mutex);
+ int value = _semaphore.count;
+ ::pthread_mutex_unlock (&_semaphore.mutex);
+ return value;
+}
+
+
+} // namespace IlmThread
+
+#endif
diff --git a/Source/OpenEXR/IlmThread/IlmThreadSemaphoreWin32.cpp b/Source/OpenEXR/IlmThread/IlmThreadSemaphoreWin32.cpp
new file mode 100644
index 0000000..9c8479d
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadSemaphoreWin32.cpp
@@ -0,0 +1,146 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Semaphore -- implementation for Windows
+//
+//-----------------------------------------------------------------------------
+
+#include "IlmThreadSemaphore.h"
+#include "Iex.h"
+#include <string>
+#include <assert.h>
+#include <iostream>
+
+namespace IlmThread {
+
+using namespace Iex;
+
+namespace {
+
+std::string
+errorString ()
+{
+ LPSTR messageBuffer;
+ DWORD bufferLength;
+ std::string message;
+
+ //
+ // Call FormatMessage() to allow for message
+ // text to be acquired from the system.
+ //
+
+ if (bufferLength = FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ GetLastError (),
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ (LPSTR) &messageBuffer,
+ 0,
+ NULL))
+ {
+ message = messageBuffer;
+ LocalFree (messageBuffer);
+ }
+
+ return message;
+}
+
+} // namespace
+
+
+Semaphore::Semaphore (unsigned int value)
+{
+ if ((_semaphore = ::CreateSemaphore (0, value, 0x7fffffff, 0)) == 0)
+ {
+ THROW (LogicExc, "Could not create semaphore "
+ "(" << errorString() << ").");
+ }
+}
+
+
+Semaphore::~Semaphore()
+{
+ bool ok = ::CloseHandle (_semaphore);
+ assert (ok);
+}
+
+
+void
+Semaphore::wait()
+{
+ if (::WaitForSingleObject (_semaphore, INFINITE) != WAIT_OBJECT_0)
+ {
+ THROW (LogicExc, "Could not wait on semaphore "
+ "(" << errorString() << ").");
+ }
+}
+
+
+bool
+Semaphore::tryWait()
+{
+ return ::WaitForSingleObject (_semaphore, 0) == WAIT_OBJECT_0;
+}
+
+
+void
+Semaphore::post()
+{
+ if (!::ReleaseSemaphore (_semaphore, 1, 0))
+ {
+ THROW (LogicExc, "Could not post on semaphore "
+ "(" << errorString() << ").");
+ }
+}
+
+
+int
+Semaphore::value() const
+{
+ LONG v = -1;
+
+ if (!::ReleaseSemaphore (_semaphore, 0, &v) || v < 0)
+ {
+ THROW (LogicExc, "Could not get value of semaphore "
+ "(" << errorString () << ").");
+ }
+
+ return v;
+}
+
+} // namespace IlmThread
diff --git a/Source/OpenEXR/IlmThread/IlmThreadWin32.cpp b/Source/OpenEXR/IlmThread/IlmThreadWin32.cpp
new file mode 100644
index 0000000..9407b8e
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/IlmThreadWin32.cpp
@@ -0,0 +1,95 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2005, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// class Thread -- implementation for Windows
+//
+//-----------------------------------------------------------------------------
+
+
+#include "IlmThread.h"
+#include "Iex.h"
+#include <iostream>
+#include <assert.h>
+
+namespace IlmThread {
+
+
+bool
+supportsThreads ()
+{
+ return true;
+}
+
+namespace {
+
+unsigned __stdcall
+threadLoop (void * t)
+{
+ reinterpret_cast<Thread*>(t)->run();
+ _endthreadex (0);
+ return 0;
+}
+
+} // namespace
+
+
+Thread::Thread ()
+{
+ // empty
+}
+
+
+Thread::~Thread ()
+{
+ DWORD status = ::WaitForSingleObject (_thread, INFINITE);
+ assert (status == WAIT_OBJECT_0);
+ bool ok = ::CloseHandle (_thread);
+ assert (ok);
+}
+
+
+void
+Thread::start ()
+{
+ unsigned id;
+ _thread = (HANDLE)::_beginthreadex (0, 0, &threadLoop, this, 0, &id);
+
+ if (_thread == 0)
+ Iex::throwErrnoExc ("Cannot create new thread (%T).");
+}
+
+
+} // namespace IlmThread
diff --git a/Source/OpenEXR/IlmThread/Makefile.am b/Source/OpenEXR/IlmThread/Makefile.am
new file mode 100644
index 0000000..d46368a
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/Makefile.am
@@ -0,0 +1,26 @@
+## Process this file with automake to produce Makefile.in
+
+lib_LTLIBRARIES = libIlmThread.la
+
+libIlmThread_la_SOURCES = IlmThreadPool.h IlmThread.h \
+ IlmThreadSemaphore.h IlmThreadMutex.h \
+ IlmThreadPool.cpp IlmThread.cpp \
+ IlmThreadSemaphore.cpp IlmThreadMutex.cpp \
+ IlmThreadPosix.cpp IlmThreadSemaphorePosix.cpp \
+ IlmThreadSemaphorePosixCompat.cpp \
+ IlmThreadMutexPosix.cpp
+
+libIlmThread_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libIlmThread_la_LIBADD = ../Iex/libIex.la
+
+libIlmThreadincludedir = $(includedir)/OpenEXR
+
+libIlmThreadinclude_HEADERS = IlmThreadPool.h IlmThread.h \
+ IlmThreadSemaphore.h IlmThreadMutex.h
+
+noinst_HEADERS =
+
+EXTRA_DIST = $(noinst_HEADERS) IlmThreadMutexWin32.cpp IlmThreadSemaphoreWin32.cpp \
+ IlmThreadWin32.cpp
+
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)/Iex -I$(top_srcdir)/config \ No newline at end of file
diff --git a/Source/OpenEXR/IlmThread/Makefile.in b/Source/OpenEXR/IlmThread/Makefile.in
new file mode 100644
index 0000000..381795c
--- /dev/null
+++ b/Source/OpenEXR/IlmThread/Makefile.in
@@ -0,0 +1,522 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+SOURCES = $(libIlmThread_la_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = IlmThread
+DIST_COMMON = $(libIlmThreadinclude_HEADERS) $(noinst_HEADERS) \
+ $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/IlmBaseConfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libIlmThreadincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libIlmThread_la_DEPENDENCIES = ../Iex/libIex.la
+am_libIlmThread_la_OBJECTS = IlmThreadPool.lo IlmThread.lo \
+ IlmThreadSemaphore.lo IlmThreadMutex.lo IlmThreadPosix.lo \
+ IlmThreadSemaphorePosix.lo IlmThreadSemaphorePosixCompat.lo \
+ IlmThreadMutexPosix.lo
+libIlmThread_la_OBJECTS = $(am_libIlmThread_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libIlmThread_la_SOURCES)
+DIST_SOURCES = $(libIlmThread_la_SOURCES)
+libIlmThreadincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libIlmThreadinclude_HEADERS) $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CXXFLAGS = @AM_CXXFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+ILMBASE_VERSION = @ILMBASE_VERSION@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION = @LIBTOOL_VERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+acx_pthread_config = @acx_pthread_config@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+lib_LTLIBRARIES = libIlmThread.la
+libIlmThread_la_SOURCES = IlmThreadPool.h IlmThread.h \
+ IlmThreadSemaphore.h IlmThreadMutex.h \
+ IlmThreadPool.cpp IlmThread.cpp \
+ IlmThreadSemaphore.cpp IlmThreadMutex.cpp \
+ IlmThreadPosix.cpp IlmThreadSemaphorePosix.cpp \
+ IlmThreadSemaphorePosixCompat.cpp \
+ IlmThreadMutexPosix.cpp
+
+libIlmThread_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libIlmThread_la_LIBADD = ../Iex/libIex.la
+libIlmThreadincludedir = $(includedir)/OpenEXR
+libIlmThreadinclude_HEADERS = IlmThreadPool.h IlmThread.h \
+ IlmThreadSemaphore.h IlmThreadMutex.h
+
+noinst_HEADERS =
+EXTRA_DIST = $(noinst_HEADERS) IlmThreadMutexWin32.cpp IlmThreadSemaphoreWin32.cpp \
+ IlmThreadWin32.cpp
+
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)/Iex -I$(top_srcdir)/config
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu IlmThread/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu IlmThread/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libIlmThread.la: $(libIlmThread_la_OBJECTS) $(libIlmThread_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libIlmThread_la_LDFLAGS) $(libIlmThread_la_OBJECTS) $(libIlmThread_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadMutex.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadMutexPosix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadPool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadPosix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadSemaphore.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadSemaphorePosix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IlmThreadSemaphorePosixCompat.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libIlmThreadincludeHEADERS: $(libIlmThreadinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libIlmThreadincludedir)" || $(mkdir_p) "$(DESTDIR)$(libIlmThreadincludedir)"
+ @list='$(libIlmThreadinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libIlmThreadincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libIlmThreadincludedir)/$$f'"; \
+ $(libIlmThreadincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libIlmThreadincludedir)/$$f"; \
+ done
+
+uninstall-libIlmThreadincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libIlmThreadinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libIlmThreadincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libIlmThreadincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libIlmThreadincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libIlmThreadincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libIlmThreadincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am \
+ install-libIlmThreadincludeHEADERS install-libLTLIBRARIES \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am \
+ uninstall-libIlmThreadincludeHEADERS uninstall-libLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/OpenEXR/Imath/ImathBox.cpp b/Source/OpenEXR/Imath/ImathBox.cpp
new file mode 100644
index 0000000..07bddfd
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathBox.cpp
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+#include "ImathBox.h"
+
+// this file is necessary for template instantiation on windows
diff --git a/Source/OpenEXR/Imath/ImathBox.h b/Source/OpenEXR/Imath/ImathBox.h
new file mode 100644
index 0000000..c6c33da
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathBox.h
@@ -0,0 +1,277 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMATHBOX_H
+#define INCLUDED_IMATHBOX_H
+
+//-------------------------------------------------------------------
+//
+// class Imath::Box<class T>
+// --------------------------------
+//
+// This class imposes the following requirements on its
+// parameter class:
+//
+// 1) The class T must implement these operators:
+// + - < > <= >= =
+// with the signature (T,T) and the expected
+// return values for a numeric type.
+//
+// 2) The class T must implement operator=
+// with the signature (T,float and/or double)
+//
+// 3) The class T must have a constructor which takes
+// a float (and/or double) for use in initializing the box.
+//
+// 4) The class T must have a function T::dimensions()
+// which returns the number of dimensions in the class
+// (since its assumed its a vector) -- preferably, this
+// returns a constant expression.
+//
+//-------------------------------------------------------------------
+
+#include "ImathVec.h"
+
+namespace Imath {
+
+
+template <class T>
+class Box
+{
+ public:
+
+ //-------------------------
+ // Data Members are public
+ //-------------------------
+
+ T min;
+ T max;
+
+ //-----------------------------------------------------
+ // Constructors - an "empty" box is created by default
+ //-----------------------------------------------------
+
+ Box();
+ Box(const T& point);
+ Box(const T& minT, const T& maxT);
+
+ //--------------------
+ // Operators: ==, !=
+ //--------------------
+
+ bool operator == (const Box<T> &src) const;
+ bool operator != (const Box<T> &src) const;
+
+ //------------------
+ // Box manipulation
+ //------------------
+
+ void makeEmpty();
+ void extendBy(const T& point);
+ void extendBy(const Box<T>& box);
+
+ //---------------------------------------------------
+ // Query functions - these compute results each time
+ //---------------------------------------------------
+
+ T size() const;
+ T center() const;
+ bool intersects(const T &point) const;
+ bool intersects(const Box<T> &box) const;
+
+ unsigned int majorAxis() const;
+
+ //----------------
+ // Classification
+ //----------------
+
+ bool isEmpty() const;
+ bool hasVolume() const;
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+
+typedef Box <V2s> Box2s;
+typedef Box <V2i> Box2i;
+typedef Box <V2f> Box2f;
+typedef Box <V2d> Box2d;
+typedef Box <V3s> Box3s;
+typedef Box <V3i> Box3i;
+typedef Box <V3f> Box3f;
+typedef Box <V3d> Box3d;
+
+
+//----------------
+// Implementation
+//----------------
+
+
+template <class T>
+inline Box<T>::Box()
+{
+ makeEmpty();
+}
+
+template <class T>
+inline Box<T>::Box(const T& point)
+{
+ min = point;
+ max = point;
+}
+
+template <class T>
+inline Box<T>::Box(const T& minV, const T& maxV)
+{
+ min = minV;
+ max = maxV;
+}
+
+template <class T>
+inline bool
+Box<T>::operator == (const Box<T> &src) const
+{
+ return (min == src.min && max == src.max);
+}
+
+template <class T>
+inline bool
+Box<T>::operator != (const Box<T> &src) const
+{
+ return (min != src.min || max != src.max);
+}
+
+template <class T>
+inline void Box<T>::makeEmpty()
+{
+ min = T(T::baseTypeMax());
+ max = T(T::baseTypeMin());
+}
+
+template <class T>
+inline void Box<T>::extendBy(const T& point)
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if ( point[i] < min[i] ) min[i] = point[i];
+ if ( point[i] > max[i] ) max[i] = point[i];
+ }
+}
+
+template <class T>
+inline void Box<T>::extendBy(const Box<T>& box)
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if ( box.min[i] < min[i] ) min[i] = box.min[i];
+ if ( box.max[i] > max[i] ) max[i] = box.max[i];
+ }
+}
+
+template <class T>
+inline bool Box<T>::intersects(const T& point) const
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if (point[i] < min[i] || point[i] > max[i]) return false;
+ }
+ return true;
+}
+
+template <class T>
+inline bool Box<T>::intersects(const Box<T>& box) const
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if (box.max[i] < min[i] || box.min[i] > max[i]) return false;
+ }
+ return true;
+}
+
+template <class T>
+inline T Box<T>::size() const
+{
+ if (isEmpty())
+ return T (0);
+
+ return max-min;
+}
+
+template <class T>
+inline T Box<T>::center() const
+{
+ return (max+min)/2;
+}
+
+template <class T>
+inline bool Box<T>::isEmpty() const
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if (max[i] < min[i]) return true;
+ }
+ return false;
+}
+
+template <class T>
+inline bool Box<T>::hasVolume() const
+{
+ for (unsigned int i=0; i<min.dimensions(); i++)
+ {
+ if (max[i] <= min[i]) return false;
+ }
+ return true;
+}
+
+template<class T>
+inline unsigned int Box<T>::majorAxis() const
+{
+ unsigned int major = 0;
+ T s = size();
+
+ for (unsigned int i=1; i<min.dimensions(); i++)
+ {
+ if ( s[i] > s[major] ) major = i;
+ }
+
+ return major;
+}
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathBoxAlgo.h b/Source/OpenEXR/Imath/ImathBoxAlgo.h
new file mode 100644
index 0000000..cfed8f9
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathBoxAlgo.h
@@ -0,0 +1,794 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHBOXALGO_H
+#define INCLUDED_IMATHBOXALGO_H
+
+
+//---------------------------------------------------------------------------
+//
+// This file contains algorithms applied to or in conjunction
+// with bounding boxes (Imath::Box). These algorithms require
+// more headers to compile. The assumption made is that these
+// functions are called much less often than the basic box
+// functions or these functions require more support classes.
+//
+// Contains:
+//
+// T clip<T>(const T& in, const Box<T>& box)
+//
+// Vec3<T> closestPointOnBox(const Vec3<T>&, const Box<Vec3<T>>& )
+//
+// Vec3<T> closestPointInBox(const Vec3<T>&, const Box<Vec3<T>>& )
+//
+// void transform(Box<Vec3<T>>&, const Matrix44<T>&)
+//
+// bool findEntryAndExitPoints(const Line<T> &line,
+// const Box< Vec3<T> > &box,
+// Vec3<T> &enterPoint,
+// Vec3<T> &exitPoint)
+//
+// bool intersects(const Box<Vec3<T>> &box,
+// const Line3<T> &ray,
+// Vec3<T> intersectionPoint)
+//
+// bool intersects(const Box<Vec3<T>> &box, const Line3<T> &ray)
+//
+//---------------------------------------------------------------------------
+
+#include "ImathBox.h"
+#include "ImathMatrix.h"
+#include "ImathLineAlgo.h"
+#include "ImathPlane.h"
+
+namespace Imath {
+
+
+template <class T>
+inline T clip(const T& in, const Box<T>& box)
+{
+ //
+ // Clip a point so that it lies inside the given bbox
+ //
+
+ T out;
+
+ for (int i=0; i<(int)box.min.dimensions(); i++)
+ {
+ if (in[i] < box.min[i]) out[i] = box.min[i];
+ else if (in[i] > box.max[i]) out[i] = box.max[i];
+ else out[i] = in[i];
+ }
+
+ return out;
+}
+
+
+//
+// Return p if p is inside the box.
+//
+
+template <class T>
+Vec3<T>
+closestPointInBox(const Vec3<T>& p, const Box< Vec3<T> >& box )
+{
+ Imath::V3f b;
+
+ if (p.x < box.min.x)
+ b.x = box.min.x;
+ else if (p.x > box.max.x)
+ b.x = box.max.x;
+ else
+ b.x = p.x;
+
+ if (p.y < box.min.y)
+ b.y = box.min.y;
+ else if (p.y > box.max.y)
+ b.y = box.max.y;
+ else
+ b.y = p.y;
+
+ if (p.z < box.min.z)
+ b.z = box.min.z;
+ else if (p.z > box.max.z)
+ b.z = box.max.z;
+ else
+ b.z = p.z;
+
+ return b;
+}
+
+template <class T>
+Vec3<T> closestPointOnBox(const Vec3<T>& pt, const Box< Vec3<T> >& box )
+{
+ //
+ // This sucker is specialized to work with a Vec3f and a box
+ // made of Vec3fs.
+ //
+
+ Vec3<T> result;
+
+ // trivial cases first
+ if (box.isEmpty())
+ return pt;
+ else if (pt == box.center())
+ {
+ // middle of z side
+ result[0] = (box.max[0] + box.min[0])/2.0;
+ result[1] = (box.max[1] + box.min[1])/2.0;
+ result[2] = box.max[2];
+ }
+ else
+ {
+ // Find the closest point on a unit box (from -1 to 1),
+ // then scale up.
+
+ // Find the vector from center to the point, then scale
+ // to a unit box.
+ Vec3<T> vec = pt - box.center();
+ T sizeX = box.max[0]-box.min[0];
+ T sizeY = box.max[1]-box.min[1];
+ T sizeZ = box.max[2]-box.min[2];
+
+ T halfX = sizeX/2.0;
+ T halfY = sizeY/2.0;
+ T halfZ = sizeZ/2.0;
+ if (halfX > 0.0)
+ vec[0] /= halfX;
+ if (halfY > 0.0)
+ vec[1] /= halfY;
+ if (halfZ > 0.0)
+ vec[2] /= halfZ;
+
+ // Side to snap side that has greatest magnitude in the vector.
+ Vec3<T> mag;
+ mag[0] = fabs(vec[0]);
+ mag[1] = fabs(vec[1]);
+ mag[2] = fabs(vec[2]);
+
+ result = mag;
+
+ // Check if beyond corners
+ if (result[0] > 1.0)
+ result[0] = 1.0;
+ if (result[1] > 1.0)
+ result[1] = 1.0;
+ if (result[2] > 1.0)
+ result[2] = 1.0;
+
+ // snap to appropriate side
+ if ((mag[0] > mag[1]) && (mag[0] > mag[2]))
+ {
+ result[0] = 1.0;
+ }
+ else if ((mag[1] > mag[0]) && (mag[1] > mag[2]))
+ {
+ result[1] = 1.0;
+ }
+ else if ((mag[2] > mag[0]) && (mag[2] > mag[1]))
+ {
+ result[2] = 1.0;
+ }
+ else if ((mag[0] == mag[1]) && (mag[0] == mag[2]))
+ {
+ // corner
+ result = Vec3<T>(1,1,1);
+ }
+ else if (mag[0] == mag[1])
+ {
+ // edge parallel with z
+ result[0] = 1.0;
+ result[1] = 1.0;
+ }
+ else if (mag[0] == mag[2])
+ {
+ // edge parallel with y
+ result[0] = 1.0;
+ result[2] = 1.0;
+ }
+ else if (mag[1] == mag[2])
+ {
+ // edge parallel with x
+ result[1] = 1.0;
+ result[2] = 1.0;
+ }
+
+ // Now make everything point the right way
+ for (int i=0; i < 3; i++)
+ {
+ if (vec[i] < 0.0)
+ result[i] = -result[i];
+ }
+
+ // scale back up and move to center
+ result[0] *= halfX;
+ result[1] *= halfY;
+ result[2] *= halfZ;
+
+ result += box.center();
+ }
+ return result;
+}
+
+template <class S, class T>
+Box< Vec3<S> >
+transform(const Box< Vec3<S> >& box, const Matrix44<T>& m)
+{
+ //
+ // Transform a 3D box by a matrix, and compute a new box that
+ // tightly encloses the transformed box.
+ //
+ // If m is an affine transform, then we use James Arvo's fast
+ // method as described in "Graphics Gems", Academic Press, 1990,
+ // pp. 548-550.
+ //
+
+ //
+ // A transformed empty box is still empty
+ //
+
+ if (box.isEmpty())
+ return box;
+
+ //
+ // If the last column of m is (0 0 0 1) then m is an affine
+ // transform, and we use the fast Graphics Gems trick.
+ //
+
+ if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1)
+ {
+ Box< Vec3<S> > newBox;
+
+ for (int i = 0; i < 3; i++)
+ {
+ newBox.min[i] = newBox.max[i] = (S) m[3][i];
+
+ for (int j = 0; j < 3; j++)
+ {
+ float a, b;
+
+ a = (S) m[j][i] * box.min[j];
+ b = (S) m[j][i] * box.max[j];
+
+ if (a < b)
+ {
+ newBox.min[i] += a;
+ newBox.max[i] += b;
+ }
+ else
+ {
+ newBox.min[i] += b;
+ newBox.max[i] += a;
+ }
+ }
+ }
+
+ return newBox;
+ }
+
+ //
+ // M is a projection matrix. Do things the naive way:
+ // Transform the eight corners of the box, and find an
+ // axis-parallel box that encloses the transformed corners.
+ //
+
+ Vec3<S> points[8];
+
+ points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0];
+ points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0];
+
+ points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1];
+ points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1];
+
+ points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2];
+ points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2];
+
+ Box< Vec3<S> > newBox;
+
+ for (int i = 0; i < 8; i++)
+ newBox.extendBy (points[i] * m);
+
+ return newBox;
+}
+
+template <class T>
+Box< Vec3<T> >
+affineTransform(const Box< Vec3<T> > &bbox, const Matrix44<T> &M)
+{
+ float min0, max0, min1, max1, min2, max2, a, b;
+ float min0new, max0new, min1new, max1new, min2new, max2new;
+
+ min0 = bbox.min[0];
+ max0 = bbox.max[0];
+ min1 = bbox.min[1];
+ max1 = bbox.max[1];
+ min2 = bbox.min[2];
+ max2 = bbox.max[2];
+
+ min0new = max0new = M[3][0];
+ a = M[0][0] * min0;
+ b = M[0][0] * max0;
+ if (a < b) {
+ min0new += a;
+ max0new += b;
+ } else {
+ min0new += b;
+ max0new += a;
+ }
+ a = M[1][0] * min1;
+ b = M[1][0] * max1;
+ if (a < b) {
+ min0new += a;
+ max0new += b;
+ } else {
+ min0new += b;
+ max0new += a;
+ }
+ a = M[2][0] * min2;
+ b = M[2][0] * max2;
+ if (a < b) {
+ min0new += a;
+ max0new += b;
+ } else {
+ min0new += b;
+ max0new += a;
+ }
+
+ min1new = max1new = M[3][1];
+ a = M[0][1] * min0;
+ b = M[0][1] * max0;
+ if (a < b) {
+ min1new += a;
+ max1new += b;
+ } else {
+ min1new += b;
+ max1new += a;
+ }
+ a = M[1][1] * min1;
+ b = M[1][1] * max1;
+ if (a < b) {
+ min1new += a;
+ max1new += b;
+ } else {
+ min1new += b;
+ max1new += a;
+ }
+ a = M[2][1] * min2;
+ b = M[2][1] * max2;
+ if (a < b) {
+ min1new += a;
+ max1new += b;
+ } else {
+ min1new += b;
+ max1new += a;
+ }
+
+ min2new = max2new = M[3][2];
+ a = M[0][2] * min0;
+ b = M[0][2] * max0;
+ if (a < b) {
+ min2new += a;
+ max2new += b;
+ } else {
+ min2new += b;
+ max2new += a;
+ }
+ a = M[1][2] * min1;
+ b = M[1][2] * max1;
+ if (a < b) {
+ min2new += a;
+ max2new += b;
+ } else {
+ min2new += b;
+ max2new += a;
+ }
+ a = M[2][2] * min2;
+ b = M[2][2] * max2;
+ if (a < b) {
+ min2new += a;
+ max2new += b;
+ } else {
+ min2new += b;
+ max2new += a;
+ }
+
+ Box< Vec3<T> > xbbox;
+
+ xbbox.min[0] = min0new;
+ xbbox.max[0] = max0new;
+ xbbox.min[1] = min1new;
+ xbbox.max[1] = max1new;
+ xbbox.min[2] = min2new;
+ xbbox.max[2] = max2new;
+
+ return xbbox;
+}
+
+
+template <class T>
+bool findEntryAndExitPoints(const Line3<T>& line,
+ const Box<Vec3<T> >& box,
+ Vec3<T> &enterPoint,
+ Vec3<T> &exitPoint)
+{
+ if ( box.isEmpty() ) return false;
+ if ( line.distanceTo(box.center()) > box.size().length()/2. ) return false;
+
+ Vec3<T> points[8], inter, bary;
+ Plane3<T> plane;
+ int i, v0, v1, v2;
+ bool front = false, valid, validIntersection = false;
+
+ // set up the eight coords of the corners of the box
+ for(i = 0; i < 8; i++)
+ {
+ points[i].setValue( i & 01 ? box.min[0] : box.max[0],
+ i & 02 ? box.min[1] : box.max[1],
+ i & 04 ? box.min[2] : box.max[2]);
+ }
+
+ // intersect the 12 triangles.
+ for(i = 0; i < 12; i++)
+ {
+ switch(i)
+ {
+ case 0: v0 = 2; v1 = 1; v2 = 0; break; // +z
+ case 1: v0 = 2; v1 = 3; v2 = 1; break;
+
+ case 2: v0 = 4; v1 = 5; v2 = 6; break; // -z
+ case 3: v0 = 6; v1 = 5; v2 = 7; break;
+
+ case 4: v0 = 0; v1 = 6; v2 = 2; break; // -x
+ case 5: v0 = 0; v1 = 4; v2 = 6; break;
+
+ case 6: v0 = 1; v1 = 3; v2 = 7; break; // +x
+ case 7: v0 = 1; v1 = 7; v2 = 5; break;
+
+ case 8: v0 = 1; v1 = 4; v2 = 0; break; // -y
+ case 9: v0 = 1; v1 = 5; v2 = 4; break;
+
+ case 10: v0 = 2; v1 = 7; v2 = 3; break; // +y
+ case 11: v0 = 2; v1 = 6; v2 = 7; break;
+ }
+ if((valid=intersect (line, points[v0], points[v1], points[v2],
+ inter, bary, front)) == true)
+ {
+ if(front == true)
+ {
+ enterPoint = inter;
+ validIntersection = valid;
+ }
+ else
+ {
+ exitPoint = inter;
+ validIntersection = valid;
+ }
+ }
+ }
+ return validIntersection;
+}
+
+
+template<class T>
+bool
+intersects (const Box< Vec3<T> > &b, const Line3<T> &r, Vec3<T> &ip)
+{
+ //
+ // Intersect a ray, r, with a box, b, and compute the intersection
+ // point, ip:
+ //
+ // intersect() returns
+ //
+ // - true if the ray starts inside the box or if the
+ // ray starts outside and intersects the box
+ //
+ // - false if the ray starts outside the box and intersects it,
+ // but the intersection is behind the ray's origin.
+ //
+ // - false if the ray starts outside and does not intersect it
+ //
+ // The intersection point is
+ //
+ // - the ray's origin if the ray starts inside the box
+ //
+ // - a point on one of the faces of the box if the ray
+ // starts outside the box
+ //
+ // - undefined when intersect() returns false
+ //
+
+ if (b.isEmpty())
+ {
+ //
+ // No ray intersects an empty box
+ //
+
+ return false;
+ }
+
+ if (b.intersects (r.pos))
+ {
+ //
+ // The ray starts inside the box
+ //
+
+ ip = r.pos;
+ return true;
+ }
+
+ //
+ // The ray starts outside the box. Between one and three "frontfacing"
+ // sides of the box are oriented towards the ray, and between one and
+ // three "backfacing" sides are oriented away from the ray.
+ // We intersect the ray with the planes that contain the sides of the
+ // box, and compare the distances between the ray-plane intersections.
+ // The ray intersects the box if the most distant frontfacing intersection
+ // is nearer than the nearest backfacing intersection. If the ray does
+ // intersect the box, then the most distant frontfacing ray-plane
+ // intersection is the ray-box intersection.
+ //
+
+ const T TMAX = limits<T>::max();
+
+ T tFrontMax = -1;
+ T tBackMin = TMAX;
+
+ //
+ // Minimum and maximum X sides.
+ //
+
+ if (r.dir.x > 0)
+ {
+ if (r.pos.x > b.max.x)
+ return false;
+
+ T d = b.max.x - r.pos.x;
+
+ if (r.dir.x > 1 || d < TMAX * r.dir.x)
+ {
+ T t = d / r.dir.x;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.x <= b.min.x)
+ {
+ T d = b.min.x - r.pos.x;
+ T t = (r.dir.x > 1 || d < TMAX * r.dir.x)? d / r.dir.x: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = b.min.x;
+ ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
+ ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
+ }
+ }
+ }
+ else if (r.dir.x < 0)
+ {
+ if (r.pos.x < b.min.x)
+ return false;
+
+ T d = b.min.x - r.pos.x;
+
+ if (r.dir.x < -1 || d > TMAX * r.dir.x)
+ {
+ T t = d / r.dir.x;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.x >= b.max.x)
+ {
+ T d = b.max.x - r.pos.x;
+ T t = (r.dir.x < -1 || d > TMAX * r.dir.x)? d / r.dir.x: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = b.max.x;
+ ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
+ ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
+ }
+ }
+ }
+ else // r.dir.x == 0
+ {
+ if (r.pos.x < b.min.x || r.pos.x > b.max.x)
+ return false;
+ }
+
+ //
+ // Minimum and maximum Y sides.
+ //
+
+ if (r.dir.y > 0)
+ {
+ if (r.pos.y > b.max.y)
+ return false;
+
+ T d = b.max.y - r.pos.y;
+
+ if (r.dir.y > 1 || d < TMAX * r.dir.y)
+ {
+ T t = d / r.dir.y;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.y <= b.min.y)
+ {
+ T d = b.min.y - r.pos.y;
+ T t = (r.dir.y > 1 || d < TMAX * r.dir.y)? d / r.dir.y: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
+ ip.y = b.min.y;
+ ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
+ }
+ }
+ }
+ else if (r.dir.y < 0)
+ {
+ if (r.pos.y < b.min.y)
+ return false;
+
+ T d = b.min.y - r.pos.y;
+
+ if (r.dir.y < -1 || d > TMAX * r.dir.y)
+ {
+ T t = d / r.dir.y;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.y >= b.max.y)
+ {
+ T d = b.max.y - r.pos.y;
+ T t = (r.dir.y < -1 || d > TMAX * r.dir.y)? d / r.dir.y: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
+ ip.y = b.max.y;
+ ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z);
+ }
+ }
+ }
+ else // r.dir.y == 0
+ {
+ if (r.pos.y < b.min.y || r.pos.y > b.max.y)
+ return false;
+ }
+
+ //
+ // Minimum and maximum Z sides.
+ //
+
+ if (r.dir.z > 0)
+ {
+ if (r.pos.z > b.max.z)
+ return false;
+
+ T d = b.max.z - r.pos.z;
+
+ if (r.dir.z > 1 || d < TMAX * r.dir.z)
+ {
+ T t = d / r.dir.z;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.z <= b.min.z)
+ {
+ T d = b.min.z - r.pos.z;
+ T t = (r.dir.z > 1 || d < TMAX * r.dir.z)? d / r.dir.z: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
+ ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
+ ip.z = b.min.z;
+ }
+ }
+ }
+ else if (r.dir.z < 0)
+ {
+ if (r.pos.z < b.min.z)
+ return false;
+
+ T d = b.min.z - r.pos.z;
+
+ if (r.dir.z < -1 || d > TMAX * r.dir.z)
+ {
+ T t = d / r.dir.z;
+
+ if (tBackMin > t)
+ tBackMin = t;
+ }
+
+ if (r.pos.z >= b.max.z)
+ {
+ T d = b.max.z - r.pos.z;
+ T t = (r.dir.z < -1 || d > TMAX * r.dir.z)? d / r.dir.z: TMAX;
+
+ if (tFrontMax < t)
+ {
+ tFrontMax = t;
+
+ ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x);
+ ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y);
+ ip.z = b.max.z;
+ }
+ }
+ }
+ else // r.dir.z == 0
+ {
+ if (r.pos.z < b.min.z || r.pos.z > b.max.z)
+ return false;
+ }
+
+ return tFrontMax <= tBackMin;
+}
+
+
+template<class T>
+bool
+intersects (const Box< Vec3<T> > &box, const Line3<T> &ray)
+{
+ Vec3<T> ignored;
+ return intersects (box, ray, ignored);
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathColor.h b/Source/OpenEXR/Imath/ImathColor.h
new file mode 100644
index 0000000..605f10b
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathColor.h
@@ -0,0 +1,734 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHCOLOR_H
+#define INCLUDED_IMATHCOLOR_H
+
+//----------------------------------------------------
+//
+// A three and four component color class template.
+//
+//----------------------------------------------------
+
+#include "ImathVec.h"
+#include "half.h"
+
+namespace Imath {
+
+
+template <class T>
+class Color3: public Vec3 <T>
+{
+ public:
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Color3 (); // no initialization
+ explicit Color3 (T a); // (a a a)
+ Color3 (T a, T b, T c); // (a b c)
+
+
+ //---------------------------------
+ // Copy constructors and assignment
+ //---------------------------------
+
+ Color3 (const Color3 &c);
+ template <class S> Color3 (const Vec3<S> &v);
+
+ const Color3 & operator = (const Color3 &c);
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Color3 & operator += (const Color3 &c);
+ Color3 operator + (const Color3 &c) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Color3 & operator -= (const Color3 &c);
+ Color3 operator - (const Color3 &c) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Color3 operator - () const;
+ const Color3 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Color3 & operator *= (const Color3 &c);
+ const Color3 & operator *= (T a);
+ Color3 operator * (const Color3 &c) const;
+ Color3 operator * (T a) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Color3 & operator /= (const Color3 &c);
+ const Color3 & operator /= (T a);
+ Color3 operator / (const Color3 &c) const;
+ Color3 operator / (T a) const;
+};
+
+template <class T> class Color4
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T r, g, b, a;
+
+ T & operator [] (int i);
+ const T & operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Color4 (); // no initialization
+ explicit Color4 (T a); // (a a a a)
+ Color4 (T a, T b, T c, T d); // (a b c d)
+
+
+ //---------------------------------
+ // Copy constructors and assignment
+ //---------------------------------
+
+ Color4 (const Color4 &v);
+ template <class S> Color4 (const Color4<S> &v);
+
+ const Color4 & operator = (const Color4 &v);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ template <class S>
+ void setValue (S a, S b, S c, S d);
+
+ template <class S>
+ void setValue (const Color4<S> &v);
+
+ template <class S>
+ void getValue (S &a, S &b, S &c, S &d) const;
+
+ template <class S>
+ void getValue (Color4<S> &v) const;
+
+ T * getValue();
+ const T * getValue() const;
+
+
+ //---------
+ // Equality
+ //---------
+
+ template <class S>
+ bool operator == (const Color4<S> &v) const;
+
+ template <class S>
+ bool operator != (const Color4<S> &v) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Color4 & operator += (const Color4 &v);
+ Color4 operator + (const Color4 &v) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Color4 & operator -= (const Color4 &v);
+ Color4 operator - (const Color4 &v) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Color4 operator - () const;
+ const Color4 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Color4 & operator *= (const Color4 &v);
+ const Color4 & operator *= (T a);
+ Color4 operator * (const Color4 &v) const;
+ Color4 operator * (T a) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Color4 & operator /= (const Color4 &v);
+ const Color4 & operator /= (T a);
+ Color4 operator / (const Color4 &v) const;
+ Color4 operator / (T a) const;
+
+
+ //----------------------------------------------------------
+ // Number of dimensions, i.e. number of elements in a Color4
+ //----------------------------------------------------------
+
+ static unsigned int dimensions() {return 4;}
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+
+
+ //--------------------------------------------------------------
+ // Base type -- in templates, which accept a parameter, V, which
+ // could be a Color4<T>, you can refer to T as
+ // V::BaseType
+ //--------------------------------------------------------------
+
+ typedef T BaseType;
+};
+
+//--------------
+// Stream output
+//--------------
+
+template <class T>
+std::ostream & operator << (std::ostream &s, const Color4<T> &v);
+
+//----------------------------------------------------
+// Reverse multiplication: S * Color4<T>
+//----------------------------------------------------
+
+template <class S, class T> Color4<T> operator * (S a, const Color4<T> &v);
+
+//-------------------------
+// Typedefs for convenience
+//-------------------------
+
+typedef Color3<float> Color3f;
+typedef Color3<half> Color3h;
+typedef Color3<unsigned char> Color3c;
+typedef Color3<half> C3h;
+typedef Color3<float> C3f;
+typedef Color3<unsigned char> C3c;
+typedef Color4<float> Color4f;
+typedef Color4<half> Color4h;
+typedef Color4<unsigned char> Color4c;
+typedef Color4<float> C4f;
+typedef Color4<half> C4h;
+typedef Color4<unsigned char> C4c;
+typedef unsigned int PackedColor;
+
+
+//-------------------------
+// Implementation of Color3
+//-------------------------
+
+template <class T>
+inline
+Color3<T>::Color3 (): Vec3 <T> ()
+{
+ // empty
+}
+
+template <class T>
+inline
+Color3<T>::Color3 (T a): Vec3 <T> (a)
+{
+ // empty
+}
+
+template <class T>
+inline
+Color3<T>::Color3 (T a, T b, T c): Vec3 <T> (a, b, c)
+{
+ // empty
+}
+
+template <class T>
+inline
+Color3<T>::Color3 (const Color3 &c): Vec3 <T> (c)
+{
+ // empty
+}
+
+template <class T>
+template <class S>
+inline
+Color3<T>::Color3 (const Vec3<S> &v): Vec3 <T> (v)
+{
+ //empty
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator = (const Color3 &c)
+{
+ *((Vec3<T> *) this) = c;
+ return *this;
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator += (const Color3 &c)
+{
+ *((Vec3<T> *) this) += c;
+ return *this;
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator + (const Color3 &c) const
+{
+ return Color3 (*(Vec3<T> *)this + (const Vec3<T> &)c);
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator -= (const Color3 &c)
+{
+ *((Vec3<T> *) this) -= c;
+ return *this;
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator - (const Color3 &c) const
+{
+ return Color3 (*(Vec3<T> *)this - (const Vec3<T> &)c);
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator - () const
+{
+ return Color3 (-(*(Vec3<T> *)this));
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::negate ()
+{
+ ((Vec3<T> *) this)->negate();
+ return *this;
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator *= (const Color3 &c)
+{
+ *((Vec3<T> *) this) *= c;
+ return *this;
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator *= (T a)
+{
+ *((Vec3<T> *) this) *= a;
+ return *this;
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator * (const Color3 &c) const
+{
+ return Color3 (*(Vec3<T> *)this * (const Vec3<T> &)c);
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator * (T a) const
+{
+ return Color3 (*(Vec3<T> *)this * a);
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator /= (const Color3 &c)
+{
+ *((Vec3<T> *) this) /= c;
+ return *this;
+}
+
+template <class T>
+inline const Color3<T> &
+Color3<T>::operator /= (T a)
+{
+ *((Vec3<T> *) this) /= a;
+ return *this;
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator / (const Color3 &c) const
+{
+ return Color3 (*(Vec3<T> *)this / (const Vec3<T> &)c);
+}
+
+template <class T>
+inline Color3<T>
+Color3<T>::operator / (T a) const
+{
+ return Color3 (*(Vec3<T> *)this / a);
+}
+
+//-----------------------
+// Implementation of Color4
+//-----------------------
+
+template <class T>
+inline T &
+Color4<T>::operator [] (int i)
+{
+ return (&r)[i];
+}
+
+template <class T>
+inline const T &
+Color4<T>::operator [] (int i) const
+{
+ return (&r)[i];
+}
+
+template <class T>
+inline
+Color4<T>::Color4 ()
+{
+ // empty
+}
+
+template <class T>
+inline
+Color4<T>::Color4 (T x)
+{
+ r = g = b = a = x;
+}
+
+template <class T>
+inline
+Color4<T>::Color4 (T x, T y, T z, T w)
+{
+ r = x;
+ g = y;
+ b = z;
+ a = w;
+}
+
+template <class T>
+inline
+Color4<T>::Color4 (const Color4 &v)
+{
+ r = v.r;
+ g = v.g;
+ b = v.b;
+ a = v.a;
+}
+
+template <class T>
+template <class S>
+inline
+Color4<T>::Color4 (const Color4<S> &v)
+{
+ r = T (v.r);
+ g = T (v.g);
+ b = T (v.b);
+ a = T (v.a);
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator = (const Color4 &v)
+{
+ r = v.r;
+ g = v.g;
+ b = v.b;
+ a = v.a;
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline void
+Color4<T>::setValue (S x, S y, S z, S w)
+{
+ r = T (x);
+ g = T (y);
+ b = T (z);
+ a = T (w);
+}
+
+template <class T>
+template <class S>
+inline void
+Color4<T>::setValue (const Color4<S> &v)
+{
+ r = T (v.r);
+ g = T (v.g);
+ b = T (v.b);
+ a = T (v.a);
+}
+
+template <class T>
+template <class S>
+inline void
+Color4<T>::getValue (S &x, S &y, S &z, S &w) const
+{
+ x = S (r);
+ y = S (g);
+ z = S (b);
+ w = S (a);
+}
+
+template <class T>
+template <class S>
+inline void
+Color4<T>::getValue (Color4<S> &v) const
+{
+ v.r = S (r);
+ v.g = S (g);
+ v.b = S (b);
+ v.a = S (a);
+}
+
+template <class T>
+inline T *
+Color4<T>::getValue()
+{
+ return (T *) &r;
+}
+
+template <class T>
+inline const T *
+Color4<T>::getValue() const
+{
+ return (const T *) &r;
+}
+
+template <class T>
+template <class S>
+inline bool
+Color4<T>::operator == (const Color4<S> &v) const
+{
+ return r == v.r && g == v.g && b == v.b && a == v.a;
+}
+
+template <class T>
+template <class S>
+inline bool
+Color4<T>::operator != (const Color4<S> &v) const
+{
+ return r != v.r || g != v.g || b != v.b || a != v.a;
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator += (const Color4 &v)
+{
+ r += v.r;
+ g += v.g;
+ b += v.b;
+ a += v.a;
+ return *this;
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator + (const Color4 &v) const
+{
+ return Color4 (r + v.r, g + v.g, b + v.b, a + v.a);
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator -= (const Color4 &v)
+{
+ r -= v.r;
+ g -= v.g;
+ b -= v.b;
+ a -= v.a;
+ return *this;
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator - (const Color4 &v) const
+{
+ return Color4 (r - v.r, g - v.g, b - v.b, a - v.a);
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator - () const
+{
+ return Color4 (-r, -g, -b, -a);
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::negate ()
+{
+ r = -r;
+ g = -g;
+ b = -b;
+ a = -a;
+ return *this;
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator *= (const Color4 &v)
+{
+ r *= v.r;
+ g *= v.g;
+ b *= v.b;
+ a *= v.a;
+ return *this;
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator *= (T x)
+{
+ r *= x;
+ g *= x;
+ b *= x;
+ a *= x;
+ return *this;
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator * (const Color4 &v) const
+{
+ return Color4 (r * v.r, g * v.g, b * v.b, a * v.a);
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator * (T x) const
+{
+ return Color4 (r * x, g * x, b * x, a * x);
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator /= (const Color4 &v)
+{
+ r /= v.r;
+ g /= v.g;
+ b /= v.b;
+ a /= v.a;
+ return *this;
+}
+
+template <class T>
+inline const Color4<T> &
+Color4<T>::operator /= (T x)
+{
+ r /= x;
+ g /= x;
+ b /= x;
+ a /= x;
+ return *this;
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator / (const Color4 &v) const
+{
+ return Color4 (r / v.r, g / v.g, b / v.b, a / v.a);
+}
+
+template <class T>
+inline Color4<T>
+Color4<T>::operator / (T x) const
+{
+ return Color4 (r / x, g / x, b / x, a / x);
+}
+
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Color4<T> &v)
+{
+ return s << '(' << v.r << ' ' << v.g << ' ' << v.b << ' ' << v.a << ')';
+}
+
+//-----------------------------------------
+// Implementation of reverse multiplication
+//-----------------------------------------
+
+template <class S, class T>
+inline Color4<T>
+operator * (S x, const Color4<T> &v)
+{
+ return Color4<T> (x * v.r, x * v.g, x * v.b, x * v.a);
+}
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathColorAlgo.cpp b/Source/OpenEXR/Imath/ImathColorAlgo.cpp
new file mode 100644
index 0000000..c624680
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathColorAlgo.cpp
@@ -0,0 +1,178 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+//----------------------------------------------------------------------------
+//
+// Implementation of non-template items declared in ImathColorAlgo.h
+//
+//----------------------------------------------------------------------------
+
+#include "ImathColorAlgo.h"
+
+namespace Imath {
+
+
+Vec3<double>
+hsv2rgb_d(const Vec3<double> &hsv)
+{
+ double hue = hsv.x;
+ double sat = hsv.y;
+ double val = hsv.z;
+
+ double x = 0.0, y = 0.0, z = 0.0;
+
+ if (hue == 1) hue = 0;
+ else hue *= 6;
+
+ int i = int(Math<double>::floor(hue));
+ double f = hue-i;
+ double p = val*(1-sat);
+ double q = val*(1-(sat*f));
+ double t = val*(1-(sat*(1-f)));
+
+ switch (i)
+ {
+ case 0: x = val; y = t; z = p; break;
+ case 1: x = q; y = val; z = p; break;
+ case 2: x = p; y = val; z = t; break;
+ case 3: x = p; y = q; z = val; break;
+ case 4: x = t; y = p; z = val; break;
+ case 5: x = val; y = p; z = q; break;
+ }
+
+ return Vec3<double>(x,y,z);
+}
+
+
+Color4<double>
+hsv2rgb_d(const Color4<double> &hsv)
+{
+ double hue = hsv.r;
+ double sat = hsv.g;
+ double val = hsv.b;
+
+ double r = 0.0, g = 0.0, b = 0.0;
+
+ if (hue == 1) hue = 0;
+ else hue *= 6;
+
+ int i = int(Math<double>::floor(hue));
+ double f = hue-i;
+ double p = val*(1-sat);
+ double q = val*(1-(sat*f));
+ double t = val*(1-(sat*(1-f)));
+
+ switch (i)
+ {
+ case 0: r = val; g = t; b = p; break;
+ case 1: r = q; g = val; b = p; break;
+ case 2: r = p; g = val; b = t; break;
+ case 3: r = p; g = q; b = val; break;
+ case 4: r = t; g = p; b = val; break;
+ case 5: r = val; g = p; b = q; break;
+ }
+
+ return Color4<double>(r,g,b,hsv.a);
+}
+
+
+
+Vec3<double>
+rgb2hsv_d(const Vec3<double> &c)
+{
+ const double &x = c.x;
+ const double &y = c.y;
+ const double &z = c.z;
+
+ double max = (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);
+ double min = (x < y) ? ((x < z) ? x : z) : ((y < z) ? y : z);
+ double range = max - min;
+ double val = max;
+ double sat = 0;
+ double hue = 0;
+
+ if (max != 0) sat = range/max;
+
+ if (sat != 0)
+ {
+ double h;
+
+ if (x == max) h = (y - z) / range;
+ else if (y == max) h = 2 + (z - x) / range;
+ else h = 4 + (x - y) / range;
+
+ hue = h/6.;
+
+ if (hue < 0.)
+ hue += 1.0;
+ }
+ return Vec3<double>(hue,sat,val);
+}
+
+
+Color4<double>
+rgb2hsv_d(const Color4<double> &c)
+{
+ const double &r = c.r;
+ const double &g = c.g;
+ const double &b = c.b;
+
+ double max = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b);
+ double min = (r < g) ? ((r < b) ? r : b) : ((g < b) ? g : b);
+ double range = max - min;
+ double val = max;
+ double sat = 0;
+ double hue = 0;
+
+ if (max != 0) sat = range/max;
+
+ if (sat != 0)
+ {
+ double h;
+
+ if (r == max) h = (g - b) / range;
+ else if (g == max) h = 2 + (b - r) / range;
+ else h = 4 + (r - g) / range;
+
+ hue = h/6.;
+
+ if (hue < 0.)
+ hue += 1.0;
+ }
+ return Color4<double>(hue,sat,val,c.a);
+}
+
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathColorAlgo.h b/Source/OpenEXR/Imath/ImathColorAlgo.h
new file mode 100644
index 0000000..bd4652a
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathColorAlgo.h
@@ -0,0 +1,256 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHCOLORALGO_H
+#define INCLUDED_IMATHCOLORALGO_H
+
+
+#include "ImathColor.h"
+#include "ImathMath.h"
+#include "ImathLimits.h"
+
+namespace Imath {
+
+
+//
+// Non-templated helper routines for color conversion.
+// These routines eliminate type warnings under g++.
+//
+
+Vec3<double> hsv2rgb_d(const Vec3<double> &hsv);
+
+Color4<double> hsv2rgb_d(const Color4<double> &hsv);
+
+
+Vec3<double> rgb2hsv_d(const Vec3<double> &rgb);
+
+Color4<double> rgb2hsv_d(const Color4<double> &rgb);
+
+
+//
+// Color conversion functions and general color algorithms
+//
+// hsv2rgb(), rgb2hsv(), rgb2packed(), packed2rgb()
+// see each funtion definition for details.
+//
+
+template<class T>
+Vec3<T>
+hsv2rgb(const Vec3<T> &hsv)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ Vec3<double> v = Vec3<double>(hsv.x / double(limits<T>::max()),
+ hsv.y / double(limits<T>::max()),
+ hsv.z / double(limits<T>::max()));
+ Vec3<double> c = hsv2rgb_d(v);
+ return Vec3<T>((T) (c.x * limits<T>::max()),
+ (T) (c.y * limits<T>::max()),
+ (T) (c.z * limits<T>::max()));
+ }
+ else
+ {
+ Vec3<double> v = Vec3<double>(hsv.x, hsv.y, hsv.z);
+ Vec3<double> c = hsv2rgb_d(v);
+ return Vec3<T>((T) c.x, (T) c.y, (T) c.z);
+ }
+}
+
+
+template<class T>
+Color4<T>
+hsv2rgb(const Color4<T> &hsv)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ Color4<double> v = Color4<double>(hsv.r / float(limits<T>::max()),
+ hsv.g / float(limits<T>::max()),
+ hsv.b / float(limits<T>::max()),
+ hsv.a / float(limits<T>::max()));
+ Color4<double> c = hsv2rgb_d(v);
+ return Color4<T>((T) (c.r * limits<T>::max()),
+ (T) (c.g * limits<T>::max()),
+ (T) (c.b * limits<T>::max()),
+ (T) (c.a * limits<T>::max()));
+ }
+ else
+ {
+ Color4<double> v = Color4<double>(hsv.r, hsv.g, hsv.g, hsv.a);
+ Color4<double> c = hsv2rgb_d(v);
+ return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a);
+ }
+}
+
+
+template<class T>
+Vec3<T>
+rgb2hsv(const Vec3<T> &rgb)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ Vec3<double> v = Vec3<double>(rgb.x / double(limits<T>::max()),
+ rgb.y / double(limits<T>::max()),
+ rgb.z / double(limits<T>::max()));
+ Vec3<double> c = rgb2hsv_d(v);
+ return Vec3<T>((T) (c.x * limits<T>::max()),
+ (T) (c.y * limits<T>::max()),
+ (T) (c.z * limits<T>::max()));
+ }
+ else
+ {
+ Vec3<double> v = Vec3<double>(rgb.x, rgb.y, rgb.z);
+ Vec3<double> c = rgb2hsv_d(v);
+ return Vec3<T>((T) c.x, (T) c.y, (T) c.z);
+ }
+}
+
+
+template<class T>
+Color4<T>
+rgb2hsv(const Color4<T> &rgb)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ Color4<double> v = Color4<double>(rgb.r / float(limits<T>::max()),
+ rgb.g / float(limits<T>::max()),
+ rgb.b / float(limits<T>::max()),
+ rgb.a / float(limits<T>::max()));
+ Color4<double> c = rgb2hsv_d(v);
+ return Color4<T>((T) (c.r * limits<T>::max()),
+ (T) (c.g * limits<T>::max()),
+ (T) (c.b * limits<T>::max()),
+ (T) (c.a * limits<T>::max()));
+ }
+ else
+ {
+ Color4<double> v = Color4<double>(rgb.r, rgb.g, rgb.g, rgb.a);
+ Color4<double> c = rgb2hsv_d(v);
+ return Color4<T>((T) c.r, (T) c.g, (T) c.b, (T) c.a);
+ }
+}
+
+template <class T>
+PackedColor
+rgb2packed(const Vec3<T> &c)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ float x = c.x / float(limits<T>::max());
+ float y = c.y / float(limits<T>::max());
+ float z = c.z / float(limits<T>::max());
+ return rgb2packed( V3f(x,y,z) );
+ }
+ else
+ {
+ return ( (PackedColor) (c.x * 255) |
+ (((PackedColor) (c.y * 255)) << 8) |
+ (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 );
+ }
+}
+
+template <class T>
+PackedColor
+rgb2packed(const Color4<T> &c)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ float r = c.r / float(limits<T>::max());
+ float g = c.g / float(limits<T>::max());
+ float b = c.b / float(limits<T>::max());
+ float a = c.a / float(limits<T>::max());
+ return rgb2packed( C4f(r,g,b,a) );
+ }
+ else
+ {
+ return ( (PackedColor) (c.r * 255) |
+ (((PackedColor) (c.g * 255)) << 8) |
+ (((PackedColor) (c.b * 255)) << 16) |
+ (((PackedColor) (c.a * 255)) << 24));
+ }
+}
+
+//
+// This guy can't return the result because the template
+// parameter would not be in the function signiture. So instead,
+// its passed in as an argument.
+//
+
+template <class T>
+void
+packed2rgb(PackedColor packed, Vec3<T> &out)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ T f = limits<T>::max() / ((PackedColor)0xFF);
+ out.x = (packed & 0xFF) * f;
+ out.y = ((packed & 0xFF00) >> 8) * f;
+ out.z = ((packed & 0xFF0000) >> 16) * f;
+ }
+ else
+ {
+ T f = T(1) / T(255);
+ out.x = (packed & 0xFF) * f;
+ out.y = ((packed & 0xFF00) >> 8) * f;
+ out.z = ((packed & 0xFF0000) >> 16) * f;
+ }
+}
+
+template <class T>
+void
+packed2rgb(PackedColor packed, Color4<T> &out)
+{
+ if ( limits<T>::isIntegral() )
+ {
+ T f = limits<T>::max() / ((PackedColor)0xFF);
+ out.r = (packed & 0xFF) * f;
+ out.g = ((packed & 0xFF00) >> 8) * f;
+ out.b = ((packed & 0xFF0000) >> 16) * f;
+ out.a = ((packed & 0xFF000000) >> 24) * f;
+ }
+ else
+ {
+ T f = T(1) / T(255);
+ out.r = (packed & 0xFF) * f;
+ out.g = ((packed & 0xFF00) >> 8) * f;
+ out.b = ((packed & 0xFF0000) >> 16) * f;
+ out.a = ((packed & 0xFF000000) >> 24) * f;
+ }
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathEuler.h b/Source/OpenEXR/Imath/ImathEuler.h
new file mode 100644
index 0000000..8d29454
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathEuler.h
@@ -0,0 +1,903 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHEULER_H
+#define INCLUDED_IMATHEULER_H
+
+//----------------------------------------------------------------------
+//
+// template class Euler<T>
+//
+// This class represents euler angle orientations. The class
+// inherits from Vec3 to it can be freely cast. The additional
+// information is the euler priorities rep. This class is
+// essentially a rip off of Ken Shoemake's GemsIV code. It has
+// been modified minimally to make it more understandable, but
+// hardly enough to make it easy to grok completely.
+//
+// There are 24 possible combonations of Euler angle
+// representations of which 12 are common in CG and you will
+// probably only use 6 of these which in this scheme are the
+// non-relative-non-repeating types.
+//
+// The representations can be partitioned according to two
+// criteria:
+//
+// 1) Are the angles measured relative to a set of fixed axis
+// or relative to each other (the latter being what happens
+// when rotation matrices are multiplied together and is
+// almost ubiquitous in the cg community)
+//
+// 2) Is one of the rotations repeated (ala XYX rotation)
+//
+// When you construct a given representation from scratch you
+// must order the angles according to their priorities. So, the
+// easiest is a softimage or aerospace (yaw/pitch/roll) ordering
+// of ZYX.
+//
+// float x_rot = 1;
+// float y_rot = 2;
+// float z_rot = 3;
+//
+// Eulerf angles(z_rot, y_rot, x_rot, Eulerf::ZYX);
+// -or-
+// Eulerf angles( V3f(z_rot,y_rot,z_rot), Eulerf::ZYX );
+//
+// If instead, the order was YXZ for instance you would have to
+// do this:
+//
+// float x_rot = 1;
+// float y_rot = 2;
+// float z_rot = 3;
+//
+// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
+// -or-
+// Eulerf angles( V3f(y_rot,x_rot,z_rot), Eulerf::YXZ );
+//
+// Notice how the order you put the angles into the three slots
+// should correspond to the enum (YXZ) ordering. The input angle
+// vector is called the "ijk" vector -- not an "xyz" vector. The
+// ijk vector order is the same as the enum. If you treat the
+// Euler<> as a Vec<> (which it inherts from) you will find the
+// angles are ordered in the same way, i.e.:
+//
+// V3f v = angles;
+// // v.x == y_rot, v.y == x_rot, v.z == z_rot
+//
+// If you just want the x, y, and z angles stored in a vector in
+// that order, you can do this:
+//
+// V3f v = angles.toXYZVector()
+// // v.x == x_rot, v.y == y_rot, v.z == z_rot
+//
+// If you want to set the Euler with an XYZVector use the
+// optional layout argument:
+//
+// Eulerf angles(x_rot, y_rot, z_rot,
+// Eulerf::YXZ,
+// Eulerf::XYZLayout);
+//
+// This is the same as:
+//
+// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ);
+//
+// Note that this won't do anything intelligent if you have a
+// repeated axis in the euler angles (e.g. XYX)
+//
+// If you need to use the "relative" versions of these, you will
+// need to use the "r" enums.
+//
+// The units of the rotation angles are assumed to be radians.
+//
+//----------------------------------------------------------------------
+
+
+#include "ImathMath.h"
+#include "ImathVec.h"
+#include "ImathQuat.h"
+#include "ImathMatrix.h"
+#include "ImathLimits.h"
+#include <iostream>
+
+namespace Imath {
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// Disable MS VC++ warnings about conversion from double to float
+#pragma warning(disable:4244)
+#endif
+
+template <class T>
+class Euler : public Vec3<T>
+{
+ public:
+
+ using Vec3<T>::x;
+ using Vec3<T>::y;
+ using Vec3<T>::z;
+
+ enum Order
+ {
+ //
+ // All 24 possible orderings
+ //
+
+ XYZ = 0x0101, // "usual" orderings
+ XZY = 0x0001,
+ YZX = 0x1101,
+ YXZ = 0x1001,
+ ZXY = 0x2101,
+ ZYX = 0x2001,
+
+ XZX = 0x0011, // first axis repeated
+ XYX = 0x0111,
+ YXY = 0x1011,
+ YZY = 0x1111,
+ ZYZ = 0x2011,
+ ZXZ = 0x2111,
+
+ XYZr = 0x2000, // relative orderings -- not common
+ XZYr = 0x2100,
+ YZXr = 0x1000,
+ YXZr = 0x1100,
+ ZXYr = 0x0000,
+ ZYXr = 0x0100,
+
+ XZXr = 0x2110, // relative first axis repeated
+ XYXr = 0x2010,
+ YXYr = 0x1110,
+ YZYr = 0x1010,
+ ZYZr = 0x0110,
+ ZXZr = 0x0010,
+ // ||||
+ // VVVV
+ // Legend: ABCD
+ // A -> Initial Axis (0==x, 1==y, 2==z)
+ // B -> Parity Even (1==true)
+ // C -> Initial Repeated (1==true)
+ // D -> Frame Static (1==true)
+ //
+
+ Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX |
+ XZX | XYX | YXY | YZY | ZYZ | ZXZ |
+ XYZr| XZYr| YZXr| YXZr| ZXYr| ZYXr|
+ XZXr| XYXr| YXYr| YZYr| ZYZr| ZXZr,
+
+ Min = 0x0000,
+ Max = 0x2111,
+ Default = XYZ
+ };
+
+ enum Axis { X = 0, Y = 1, Z = 2 };
+
+ enum InputLayout { XYZLayout, IJKLayout };
+
+ //----------------------------------------------------------------
+ // Constructors -- all default to ZYX non-relative ala softimage
+ // (where there is no argument to specify it)
+ //----------------------------------------------------------------
+
+ Euler();
+ Euler(const Euler&);
+ Euler(Order p);
+ Euler(const Vec3<T> &v, Order o = Default, InputLayout l = IJKLayout);
+ Euler(T i, T j, T k, Order o = Default, InputLayout l = IJKLayout);
+ Euler(const Euler<T> &euler, Order newp);
+ Euler(const Matrix33<T> &, Order o = Default);
+ Euler(const Matrix44<T> &, Order o = Default);
+
+ //---------------------------------
+ // Algebraic functions/ Operators
+ //---------------------------------
+
+ const Euler<T>& operator= (const Euler<T>&);
+ const Euler<T>& operator= (const Vec3<T>&);
+
+ //--------------------------------------------------------
+ // Set the euler value
+ // This does NOT convert the angles, but setXYZVector()
+ // does reorder the input vector.
+ //--------------------------------------------------------
+
+ static bool legal(Order);
+
+ void setXYZVector(const Vec3<T> &);
+
+ Order order() const;
+ void setOrder(Order);
+
+ void set(Axis initial,
+ bool relative,
+ bool parityEven,
+ bool firstRepeats);
+
+ //---------------------------------------------------------
+ // Conversions, toXYZVector() reorders the angles so that
+ // the X rotation comes first, followed by the Y and Z
+ // in cases like XYX ordering, the repeated angle will be
+ // in the "z" component
+ //---------------------------------------------------------
+
+ void extract(const Matrix33<T>&);
+ void extract(const Matrix44<T>&);
+ void extract(const Quat<T>&);
+
+ Matrix33<T> toMatrix33() const;
+ Matrix44<T> toMatrix44() const;
+ Quat<T> toQuat() const;
+ Vec3<T> toXYZVector() const;
+
+ //---------------------------------------------------
+ // Use this function to unpack angles from ijk form
+ //---------------------------------------------------
+
+ void angleOrder(int &i, int &j, int &k) const;
+
+ //---------------------------------------------------
+ // Use this function to determine mapping from xyz to ijk
+ // - reshuffles the xyz to match the order
+ //---------------------------------------------------
+
+ void angleMapping(int &i, int &j, int &k) const;
+
+ //----------------------------------------------------------------------
+ //
+ // Utility methods for getting continuous rotations. None of these
+ // methods change the orientation given by its inputs (or at least
+ // that is the intent).
+ //
+ // angleMod() converts an angle to its equivalent in [-PI, PI]
+ //
+ // simpleXYZRotation() adjusts xyzRot so that its components differ
+ // from targetXyzRot by no more than +-PI
+ //
+ // nearestRotation() adjusts xyzRot so that its components differ
+ // from targetXyzRot by as little as possible.
+ // Note that xyz here really means ijk, because
+ // the order must be provided.
+ //
+ // makeNear() adjusts "this" Euler so that its components differ
+ // from target by as little as possible. This method
+ // might not make sense for Eulers with different order
+ // and it probably doesn't work for repeated axis and
+ // relative orderings (TODO).
+ //
+ //-----------------------------------------------------------------------
+
+ static float angleMod (T angle);
+ static void simpleXYZRotation (Vec3<T> &xyzRot,
+ const Vec3<T> &targetXyzRot);
+ static void nearestRotation (Vec3<T> &xyzRot,
+ const Vec3<T> &targetXyzRot,
+ Order order = XYZ);
+
+ void makeNear (const Euler<T> &target);
+
+ bool frameStatic() const { return _frameStatic; }
+ bool initialRepeated() const { return _initialRepeated; }
+ bool parityEven() const { return _parityEven; }
+ Axis initialAxis() const { return _initialAxis; }
+
+ protected:
+
+ bool _frameStatic : 1; // relative or static rotations
+ bool _initialRepeated : 1; // init axis repeated as last
+ bool _parityEven : 1; // "parity of axis permutation"
+#if defined _WIN32 || defined _WIN64
+ Axis _initialAxis ; // First axis of rotation
+#else
+ Axis _initialAxis : 2; // First axis of rotation
+#endif
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+typedef Euler<float> Eulerf;
+typedef Euler<double> Eulerd;
+
+
+//---------------
+// Implementation
+//---------------
+
+template<class T>
+inline void
+ Euler<T>::angleOrder(int &i, int &j, int &k) const
+{
+ i = _initialAxis;
+ j = _parityEven ? (i+1)%3 : (i > 0 ? i-1 : 2);
+ k = _parityEven ? (i > 0 ? i-1 : 2) : (i+1)%3;
+}
+
+template<class T>
+inline void
+ Euler<T>::angleMapping(int &i, int &j, int &k) const
+{
+ int m[3];
+
+ m[_initialAxis] = 0;
+ m[(_initialAxis+1) % 3] = _parityEven ? 1 : 2;
+ m[(_initialAxis+2) % 3] = _parityEven ? 2 : 1;
+ i = m[0];
+ j = m[1];
+ k = m[2];
+}
+
+template<class T>
+inline void
+Euler<T>::setXYZVector(const Vec3<T> &v)
+{
+ int i,j,k;
+ angleMapping(i,j,k);
+ (*this)[i] = v.x;
+ (*this)[j] = v.y;
+ (*this)[k] = v.z;
+}
+
+template<class T>
+inline Vec3<T>
+Euler<T>::toXYZVector() const
+{
+ int i,j,k;
+ angleMapping(i,j,k);
+ return Vec3<T>((*this)[i],(*this)[j],(*this)[k]);
+}
+
+
+template<class T>
+Euler<T>::Euler() :
+ Vec3<T>(0,0,0),
+ _frameStatic(true),
+ _initialRepeated(false),
+ _parityEven(true),
+ _initialAxis(X)
+{}
+
+template<class T>
+Euler<T>::Euler(typename Euler<T>::Order p) :
+ Vec3<T>(0,0,0),
+ _frameStatic(true),
+ _initialRepeated(false),
+ _parityEven(true),
+ _initialAxis(X)
+{
+ setOrder(p);
+}
+
+template<class T>
+inline Euler<T>::Euler( const Vec3<T> &v,
+ typename Euler<T>::Order p,
+ typename Euler<T>::InputLayout l )
+{
+ setOrder(p);
+ if ( l == XYZLayout ) setXYZVector(v);
+ else { x = v.x; y = v.y; z = v.z; }
+}
+
+template<class T>
+inline Euler<T>::Euler(const Euler<T> &euler)
+{
+ operator=(euler);
+}
+
+template<class T>
+inline Euler<T>::Euler(const Euler<T> &euler,Order p)
+{
+ setOrder(p);
+ Matrix33<T> M = euler.toMatrix33();
+ extract(M);
+}
+
+template<class T>
+inline Euler<T>::Euler( T xi, T yi, T zi,
+ typename Euler<T>::Order p,
+ typename Euler<T>::InputLayout l)
+{
+ setOrder(p);
+ if ( l == XYZLayout ) setXYZVector(Vec3<T>(xi,yi,zi));
+ else { x = xi; y = yi; z = zi; }
+}
+
+template<class T>
+inline Euler<T>::Euler( const Matrix33<T> &M, typename Euler::Order p )
+{
+ setOrder(p);
+ extract(M);
+}
+
+template<class T>
+inline Euler<T>::Euler( const Matrix44<T> &M, typename Euler::Order p )
+{
+ setOrder(p);
+ extract(M);
+}
+
+template<class T>
+inline void Euler<T>::extract(const Quat<T> &q)
+{
+ extract(q.toMatrix33());
+}
+
+template<class T>
+void Euler<T>::extract(const Matrix33<T> &M)
+{
+ int i,j,k;
+ angleOrder(i,j,k);
+
+ if (_initialRepeated)
+ {
+ //
+ // Extract the first angle, x.
+ //
+
+ x = Math<T>::atan2 (M[j][i], M[k][i]);
+
+ //
+ // Remove the x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Vec3<T> r (0, 0, 0);
+ r[i] = (_parityEven? -x: x);
+
+ Matrix44<T> N;
+ N.rotate (r);
+
+ N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
+ M[1][0], M[1][1], M[1][2], 0,
+ M[2][0], M[2][1], M[2][2], 0,
+ 0, 0, 0, 1);
+ //
+ // Extract the other two angles, y and z, from N.
+ //
+
+ T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
+ y = Math<T>::atan2 (sy, N[i][i]);
+ z = Math<T>::atan2 (N[j][k], N[j][j]);
+ }
+ else
+ {
+ //
+ // Extract the first angle, x.
+ //
+
+ x = Math<T>::atan2 (M[j][k], M[k][k]);
+
+ //
+ // Remove the x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Vec3<T> r (0, 0, 0);
+ r[i] = (_parityEven? -x: x);
+
+ Matrix44<T> N;
+ N.rotate (r);
+
+ N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0,
+ M[1][0], M[1][1], M[1][2], 0,
+ M[2][0], M[2][1], M[2][2], 0,
+ 0, 0, 0, 1);
+ //
+ // Extract the other two angles, y and z, from N.
+ //
+
+ T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
+ y = Math<T>::atan2 (-N[i][k], cy);
+ z = Math<T>::atan2 (-N[j][i], N[j][j]);
+ }
+
+ if (!_parityEven)
+ *this *= -1;
+
+ if (!_frameStatic)
+ {
+ T t = x;
+ x = z;
+ z = t;
+ }
+}
+
+template<class T>
+void Euler<T>::extract(const Matrix44<T> &M)
+{
+ int i,j,k;
+ angleOrder(i,j,k);
+
+ if (_initialRepeated)
+ {
+ //
+ // Extract the first angle, x.
+ //
+
+ x = Math<T>::atan2 (M[j][i], M[k][i]);
+
+ //
+ // Remove the x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Vec3<T> r (0, 0, 0);
+ r[i] = (_parityEven? -x: x);
+
+ Matrix44<T> N;
+ N.rotate (r);
+ N = N * M;
+
+ //
+ // Extract the other two angles, y and z, from N.
+ //
+
+ T sy = Math<T>::sqrt (N[j][i]*N[j][i] + N[k][i]*N[k][i]);
+ y = Math<T>::atan2 (sy, N[i][i]);
+ z = Math<T>::atan2 (N[j][k], N[j][j]);
+ }
+ else
+ {
+ //
+ // Extract the first angle, x.
+ //
+
+ x = Math<T>::atan2 (M[j][k], M[k][k]);
+
+ //
+ // Remove the x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Vec3<T> r (0, 0, 0);
+ r[i] = (_parityEven? -x: x);
+
+ Matrix44<T> N;
+ N.rotate (r);
+ N = N * M;
+
+ //
+ // Extract the other two angles, y and z, from N.
+ //
+
+ T cy = Math<T>::sqrt (N[i][i]*N[i][i] + N[i][j]*N[i][j]);
+ y = Math<T>::atan2 (-N[i][k], cy);
+ z = Math<T>::atan2 (-N[j][i], N[j][j]);
+ }
+
+ if (!_parityEven)
+ *this *= -1;
+
+ if (!_frameStatic)
+ {
+ T t = x;
+ x = z;
+ z = t;
+ }
+}
+
+template<class T>
+Matrix33<T> Euler<T>::toMatrix33() const
+{
+ int i,j,k;
+ angleOrder(i,j,k);
+
+ Vec3<T> angles;
+
+ if ( _frameStatic ) angles = (*this);
+ else angles = Vec3<T>(z,y,x);
+
+ if ( !_parityEven ) angles *= -1.0;
+
+ T ci = Math<T>::cos(angles.x);
+ T cj = Math<T>::cos(angles.y);
+ T ch = Math<T>::cos(angles.z);
+ T si = Math<T>::sin(angles.x);
+ T sj = Math<T>::sin(angles.y);
+ T sh = Math<T>::sin(angles.z);
+
+ T cc = ci*ch;
+ T cs = ci*sh;
+ T sc = si*ch;
+ T ss = si*sh;
+
+ Matrix33<T> M;
+
+ if ( _initialRepeated )
+ {
+ M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
+ M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
+ M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
+ }
+ else
+ {
+ M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
+ M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
+ M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
+ }
+
+ return M;
+}
+
+template<class T>
+Matrix44<T> Euler<T>::toMatrix44() const
+{
+ int i,j,k;
+ angleOrder(i,j,k);
+
+ Vec3<T> angles;
+
+ if ( _frameStatic ) angles = (*this);
+ else angles = Vec3<T>(z,y,x);
+
+ if ( !_parityEven ) angles *= -1.0;
+
+ T ci = Math<T>::cos(angles.x);
+ T cj = Math<T>::cos(angles.y);
+ T ch = Math<T>::cos(angles.z);
+ T si = Math<T>::sin(angles.x);
+ T sj = Math<T>::sin(angles.y);
+ T sh = Math<T>::sin(angles.z);
+
+ T cc = ci*ch;
+ T cs = ci*sh;
+ T sc = si*ch;
+ T ss = si*sh;
+
+ Matrix44<T> M;
+
+ if ( _initialRepeated )
+ {
+ M[i][i] = cj; M[j][i] = sj*si; M[k][i] = sj*ci;
+ M[i][j] = sj*sh; M[j][j] = -cj*ss+cc; M[k][j] = -cj*cs-sc;
+ M[i][k] = -sj*ch; M[j][k] = cj*sc+cs; M[k][k] = cj*cc-ss;
+ }
+ else
+ {
+ M[i][i] = cj*ch; M[j][i] = sj*sc-cs; M[k][i] = sj*cc+ss;
+ M[i][j] = cj*sh; M[j][j] = sj*ss+cc; M[k][j] = sj*cs-sc;
+ M[i][k] = -sj; M[j][k] = cj*si; M[k][k] = cj*ci;
+ }
+
+ return M;
+}
+
+template<class T>
+Quat<T> Euler<T>::toQuat() const
+{
+ Vec3<T> angles;
+ int i,j,k;
+ angleOrder(i,j,k);
+
+ if ( _frameStatic ) angles = (*this);
+ else angles = Vec3<T>(z,y,x);
+
+ if ( !_parityEven ) angles.y = -angles.y;
+
+ T ti = angles.x*0.5;
+ T tj = angles.y*0.5;
+ T th = angles.z*0.5;
+ T ci = Math<T>::cos(ti);
+ T cj = Math<T>::cos(tj);
+ T ch = Math<T>::cos(th);
+ T si = Math<T>::sin(ti);
+ T sj = Math<T>::sin(tj);
+ T sh = Math<T>::sin(th);
+ T cc = ci*ch;
+ T cs = ci*sh;
+ T sc = si*ch;
+ T ss = si*sh;
+
+ T parity = _parityEven ? 1.0 : -1.0;
+
+ Quat<T> q;
+ Vec3<T> a;
+
+ if ( _initialRepeated )
+ {
+ a[i] = cj*(cs + sc);
+ a[j] = sj*(cc + ss) * parity,
+ a[k] = sj*(cs - sc);
+ q.r = cj*(cc - ss);
+ }
+ else
+ {
+ a[i] = cj*sc - sj*cs,
+ a[j] = (cj*ss + sj*cc) * parity,
+ a[k] = cj*cs - sj*sc;
+ q.r = cj*cc + sj*ss;
+ }
+
+ q.v = a;
+
+ return q;
+}
+
+template<class T>
+inline bool
+Euler<T>::legal(typename Euler<T>::Order order)
+{
+ return (order & ~Legal) ? false : true;
+}
+
+template<class T>
+typename Euler<T>::Order
+Euler<T>::order() const
+{
+ int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0));
+
+ if (_parityEven) foo |= 0x0100;
+ if (_initialRepeated) foo |= 0x0010;
+ if (_frameStatic) foo++;
+
+ return (Order)foo;
+}
+
+template<class T>
+inline void Euler<T>::setOrder(typename Euler<T>::Order p)
+{
+ set( p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis
+ !(p & 0x1), // static?
+ !!(p & 0x100), // permutation even?
+ !!(p & 0x10)); // initial repeats?
+}
+
+template<class T>
+void Euler<T>::set(typename Euler<T>::Axis axis,
+ bool relative,
+ bool parityEven,
+ bool firstRepeats)
+{
+ _initialAxis = axis;
+ _frameStatic = !relative;
+ _parityEven = parityEven;
+ _initialRepeated = firstRepeats;
+}
+
+template<class T>
+const Euler<T>& Euler<T>::operator= (const Euler<T> &euler)
+{
+ x = euler.x;
+ y = euler.y;
+ z = euler.z;
+ _initialAxis = euler._initialAxis;
+ _frameStatic = euler._frameStatic;
+ _parityEven = euler._parityEven;
+ _initialRepeated = euler._initialRepeated;
+ return *this;
+}
+
+template<class T>
+const Euler<T>& Euler<T>::operator= (const Vec3<T> &v)
+{
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ return *this;
+}
+
+template<class T>
+std::ostream& operator << (std::ostream &o, const Euler<T> &euler)
+{
+ char a[3] = { 'X', 'Y', 'Z' };
+
+ const char* r = euler.frameStatic() ? "" : "r";
+ int i,j,k;
+ euler.angleOrder(i,j,k);
+
+ if ( euler.initialRepeated() ) k = i;
+
+ return o << "("
+ << euler.x << " "
+ << euler.y << " "
+ << euler.z << " "
+ << a[i] << a[j] << a[k] << r << ")";
+}
+
+template <class T>
+float
+Euler<T>::angleMod (T angle)
+{
+ angle = fmod(T (angle), T (2 * M_PI));
+
+ if (angle < -M_PI) angle += 2 * M_PI;
+ if (angle > +M_PI) angle -= 2 * M_PI;
+
+ return angle;
+}
+
+template <class T>
+void
+Euler<T>::simpleXYZRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot)
+{
+ Vec3<T> d = xyzRot - targetXyzRot;
+ xyzRot[0] = targetXyzRot[0] + angleMod(d[0]);
+ xyzRot[1] = targetXyzRot[1] + angleMod(d[1]);
+ xyzRot[2] = targetXyzRot[2] + angleMod(d[2]);
+}
+
+template <class T>
+void
+Euler<T>::nearestRotation (Vec3<T> &xyzRot, const Vec3<T> &targetXyzRot,
+ Order order)
+{
+ int i,j,k;
+ Euler<T> e (0,0,0, order);
+ e.angleOrder(i,j,k);
+
+ simpleXYZRotation(xyzRot, targetXyzRot);
+
+ Vec3<T> otherXyzRot;
+ otherXyzRot[i] = M_PI+xyzRot[i];
+ otherXyzRot[j] = M_PI-xyzRot[j];
+ otherXyzRot[k] = M_PI+xyzRot[k];
+
+ simpleXYZRotation(otherXyzRot, targetXyzRot);
+
+ Vec3<T> d = xyzRot - targetXyzRot;
+ Vec3<T> od = otherXyzRot - targetXyzRot;
+ T dMag = d.dot(d);
+ T odMag = od.dot(od);
+
+ if (odMag < dMag)
+ {
+ xyzRot = otherXyzRot;
+ }
+}
+
+template <class T>
+void
+Euler<T>::makeNear (const Euler<T> &target)
+{
+ Vec3<T> xyzRot = toXYZVector();
+ Euler<T> targetSameOrder = Euler<T>(target, order());
+ Vec3<T> targetXyz = targetSameOrder.toXYZVector();
+
+ nearestRotation(xyzRot, targetXyz, order());
+
+ setXYZVector(xyzRot);
+}
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(default:4244)
+#endif
+
+} // namespace Imath
+
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathExc.h b/Source/OpenEXR/Imath/ImathExc.h
new file mode 100644
index 0000000..db5c6c4
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathExc.h
@@ -0,0 +1,70 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHEXC_H
+#define INCLUDED_IMATHEXC_H
+
+
+//-----------------------------------------------
+//
+// Imath library-specific exceptions
+//
+//-----------------------------------------------
+
+#include "IexBaseExc.h"
+
+namespace Imath {
+
+
+DEFINE_EXC (NullVecExc, ::Iex::MathExc) // Attempt to normalize
+ // null vector
+
+DEFINE_EXC (NullQuatExc, ::Iex::MathExc) // Attempt to normalize
+ // null quaternion
+
+DEFINE_EXC (SingMatrixExc, ::Iex::MathExc) // Attempt to invert
+ // singular matrix
+
+DEFINE_EXC (ZeroScaleExc, ::Iex::MathExc) // Attempt to remove zero
+ // scaling from matrix
+
+DEFINE_EXC (IntVecNormalizeExc, ::Iex::MathExc) // Attempt to normalize
+ // a vector of whose elements
+ // are an integer type
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathFrame.h b/Source/OpenEXR/Imath/ImathFrame.h
new file mode 100644
index 0000000..7291231
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathFrame.h
@@ -0,0 +1,190 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHFRAME_H
+#define INCLUDED_IMATHFRAME_H
+
+namespace Imath {
+
+template<class T> class Vec3;
+template<class T> class Matrix44;
+
+//
+// These methods compute a set of reference frames, defined by their
+// transformation matrix, along a curve. It is designed so that the
+// array of points and the array of matrices used to fetch these routines
+// don't need to be ordered as the curve.
+//
+// A typical usage would be :
+//
+// m[0] = Imath::firstFrame( p[0], p[1], p[2] );
+// for( int i = 1; i < n - 1; i++ )
+// {
+// m[i] = Imath::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] );
+// }
+// m[n-1] = Imath::lastFrame( m[n-2], p[n-2], p[n-1] );
+//
+// See Graphics Gems I for the underlying algorithm.
+//
+
+template<class T> Matrix44<T> firstFrame( const Vec3<T>&, // First point
+ const Vec3<T>&, // Second point
+ const Vec3<T>& ); // Third point
+
+template<class T> Matrix44<T> nextFrame( const Matrix44<T>&, // Previous matrix
+ const Vec3<T>&, // Previous point
+ const Vec3<T>&, // Current point
+ Vec3<T>&, // Previous tangent
+ Vec3<T>& ); // Current tangent
+
+template<class T> Matrix44<T> lastFrame( const Matrix44<T>&, // Previous matrix
+ const Vec3<T>&, // Previous point
+ const Vec3<T>& ); // Last point
+
+//
+// firstFrame - Compute the first reference frame along a curve.
+//
+// This function returns the transformation matrix to the reference frame
+// defined by the three points 'pi', 'pj' and 'pk'. Note that if the two
+// vectors <pi,pj> and <pi,pk> are colinears, an arbitrary twist value will
+// be choosen.
+//
+// Throw 'NullVecExc' if 'pi' and 'pj' are equals.
+//
+
+template<class T> Matrix44<T> firstFrame
+(
+ const Vec3<T>& pi, // First point
+ const Vec3<T>& pj, // Second point
+ const Vec3<T>& pk ) // Third point
+{
+ Vec3<T> t = pj - pi; t.normalizeExc();
+
+ Vec3<T> n = t.cross( pk - pi ); n.normalize();
+ if( n.length() == 0.0f )
+ {
+ int i = fabs( t[0] ) < fabs( t[1] ) ? 0 : 1;
+ if( fabs( t[2] ) < fabs( t[i] )) i = 2;
+
+ Vec3<T> v( 0.0, 0.0, 0.0 ); v[i] = 1.0;
+ n = t.cross( v ); n.normalize();
+ }
+
+ Vec3<T> b = t.cross( n );
+
+ Matrix44<T> M;
+
+ M[0][0] = t[0]; M[0][1] = t[1]; M[0][2] = t[2]; M[0][3] = 0.0,
+ M[1][0] = n[0]; M[1][1] = n[1]; M[1][2] = n[2]; M[1][3] = 0.0,
+ M[2][0] = b[0]; M[2][1] = b[1]; M[2][2] = b[2]; M[2][3] = 0.0,
+ M[3][0] = pi[0]; M[3][1] = pi[1]; M[3][2] = pi[2]; M[3][3] = 1.0;
+
+ return M;
+}
+
+//
+// nextFrame - Compute the next reference frame along a curve.
+//
+// This function returns the transformation matrix to the next reference
+// frame defined by the previously computed transformation matrix and the
+// new point and tangent vector along the curve.
+//
+
+template<class T> Matrix44<T> nextFrame
+(
+ const Matrix44<T>& Mi, // Previous matrix
+ const Vec3<T>& pi, // Previous point
+ const Vec3<T>& pj, // Current point
+ Vec3<T>& ti, // Previous tangent vector
+ Vec3<T>& tj ) // Current tangent vector
+{
+ Vec3<T> a(0.0, 0.0, 0.0); // Rotation axis.
+ T r = 0.0; // Rotation angle.
+
+ if( ti.length() != 0.0 && tj.length() != 0.0 )
+ {
+ ti.normalize(); tj.normalize();
+ T dot = ti.dot( tj );
+
+ //
+ // This is *really* necessary :
+ //
+
+ if( dot > 1.0 ) dot = 1.0;
+ else if( dot < -1.0 ) dot = -1.0;
+
+ r = acosf( dot );
+ a = ti.cross( tj );
+ }
+
+ if( a.length() != 0.0 && r != 0.0 )
+ {
+ Matrix44<T> R; R.setAxisAngle( a, r );
+ Matrix44<T> Tj; Tj.translate( pj );
+ Matrix44<T> Ti; Ti.translate( -pi );
+
+ return Mi * Ti * R * Tj;
+ }
+ else
+ {
+ Matrix44<T> Tr; Tr.translate( pj - pi );
+
+ return Mi * Tr;
+ }
+}
+
+//
+// lastFrame - Compute the last reference frame along a curve.
+//
+// This function returns the transformation matrix to the last reference
+// frame defined by the previously computed transformation matrix and the
+// last point along the curve.
+//
+
+template<class T> Matrix44<T> lastFrame
+(
+ const Matrix44<T>& Mi, // Previous matrix
+ const Vec3<T>& pi, // Previous point
+ const Vec3<T>& pj ) // Last point
+{
+ Matrix44<T> Tr; Tr.translate( pj - pi );
+
+ return Mi * Tr;
+}
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathFrustum.h b/Source/OpenEXR/Imath/ImathFrustum.h
new file mode 100644
index 0000000..2945bcf
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathFrustum.h
@@ -0,0 +1,722 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHFRUSTUM_H
+#define INCLUDED_IMATHFRUSTUM_H
+
+
+#include "ImathVec.h"
+#include "ImathPlane.h"
+#include "ImathLine.h"
+#include "ImathMatrix.h"
+#include "ImathLimits.h"
+#include "ImathFun.h"
+#include "IexMathExc.h"
+
+#if defined _WIN32 || defined _WIN64
+ #ifdef near
+ #undef near
+ #endif
+ #ifdef far
+ #undef far
+ #endif
+#endif
+
+namespace Imath {
+
+//
+// template class Frustum<T>
+//
+// The frustum is always located with the eye point at the
+// origin facing down -Z. This makes the Frustum class
+// compatable with OpenGL (or anything that assumes a camera
+// looks down -Z, hence with a right-handed coordinate system)
+// but not with RenderMan which assumes the camera looks down
+// +Z. Additional functions are provided for conversion from
+// and from various camera coordinate spaces.
+//
+
+
+template<class T>
+class Frustum
+{
+ public:
+ Frustum();
+ Frustum(const Frustum &);
+ Frustum(T near, T far, T left, T right, T top, T bottom, bool ortho=false);
+ Frustum(T near, T far, T fovx, T fovy, T aspect);
+ virtual ~Frustum();
+
+ //--------------------
+ // Assignment operator
+ //--------------------
+
+ const Frustum &operator = (const Frustum &);
+
+ //--------------------
+ // Operators: ==, !=
+ //--------------------
+
+ bool operator == (const Frustum<T> &src) const;
+ bool operator != (const Frustum<T> &src) const;
+
+ //--------------------------------------------------------
+ // Set functions change the entire state of the Frustum
+ //--------------------------------------------------------
+
+ void set(T near, T far,
+ T left, T right,
+ T top, T bottom,
+ bool ortho=false);
+
+ void set(T near, T far, T fovx, T fovy, T aspect);
+
+ //------------------------------------------------------
+ // These functions modify an already valid frustum state
+ //------------------------------------------------------
+
+ void modifyNearAndFar(T near, T far);
+ void setOrthographic(bool);
+
+ //--------------
+ // Access
+ //--------------
+
+ bool orthographic() const { return _orthographic; }
+ T near() const { return _near; }
+ T far() const { return _far; }
+ T left() const { return _left; }
+ T right() const { return _right; }
+ T bottom() const { return _bottom; }
+ T top() const { return _top; }
+
+ //-----------------------------------------------------------------------
+ // Sets the planes in p to be the six bounding planes of the frustum, in
+ // the following order: top, right, bottom, left, near, far.
+ // Note that the planes have normals that point out of the frustum.
+ // The version of this routine that takes a matrix applies that matrix
+ // to transform the frustum before setting the planes.
+ //-----------------------------------------------------------------------
+
+ void planes(Plane3<T> p[6]);
+ void planes(Plane3<T> p[6], const Matrix44<T> &M);
+
+ //----------------------
+ // Derived Quantities
+ //----------------------
+
+ T fovx() const;
+ T fovy() const;
+ T aspect() const;
+ Matrix44<T> projectionMatrix() const;
+
+ //-----------------------------------------------------------------------
+ // Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1
+ // and -1 <= bottom <= top <= 1) of this Frustum, and returns a new
+ // Frustum whose near clipping-plane window is that rectangle in local
+ // space.
+ //-----------------------------------------------------------------------
+
+ Frustum<T> window(T left, T right, T top, T bottom) const;
+
+ //----------------------------------------------------------
+ // Projection is in screen space / Conversion from Z-Buffer
+ //----------------------------------------------------------
+
+ Line3<T> projectScreenToRay( const Vec2<T> & ) const;
+ Vec2<T> projectPointToScreen( const Vec3<T> & ) const;
+
+ T ZToDepth(long zval, long min, long max) const;
+ T normalizedZToDepth(T zval) const;
+ long DepthToZ(T depth, long zmin, long zmax) const;
+
+ T worldRadius(const Vec3<T> &p, T radius) const;
+ T screenRadius(const Vec3<T> &p, T radius) const;
+
+
+ protected:
+
+ Vec2<T> screenToLocal( const Vec2<T> & ) const;
+ Vec2<T> localToScreen( const Vec2<T> & ) const;
+
+ protected:
+ T _near;
+ T _far;
+ T _left;
+ T _right;
+ T _top;
+ T _bottom;
+ bool _orthographic;
+};
+
+
+template<class T>
+inline Frustum<T>::Frustum()
+{
+ set(T (0.1),
+ T (1000.0),
+ T (-1.0),
+ T (1.0),
+ T (1.0),
+ T (-1.0),
+ false);
+}
+
+template<class T>
+inline Frustum<T>::Frustum(const Frustum &f)
+{
+ *this = f;
+}
+
+template<class T>
+inline Frustum<T>::Frustum(T n, T f, T l, T r, T t, T b, bool o)
+{
+ set(n,f,l,r,t,b,o);
+}
+
+template<class T>
+inline Frustum<T>::Frustum(T near, T far, T fovx, T fovy, T aspect)
+{
+ set(near,far,fovx,fovy,aspect);
+}
+
+template<class T>
+Frustum<T>::~Frustum()
+{
+}
+
+template<class T>
+const Frustum<T> &
+Frustum<T>::operator = (const Frustum &f)
+{
+ _near = f._near;
+ _far = f._far;
+ _left = f._left;
+ _right = f._right;
+ _top = f._top;
+ _bottom = f._bottom;
+ _orthographic = f._orthographic;
+
+ return *this;
+}
+
+template <class T>
+bool
+Frustum<T>::operator == (const Frustum<T> &src) const
+{
+ return
+ _near == src._near &&
+ _far == src._far &&
+ _left == src._left &&
+ _right == src._right &&
+ _top == src._top &&
+ _bottom == src._bottom &&
+ _orthographic == src._orthographic;
+}
+
+template <class T>
+inline bool
+Frustum<T>::operator != (const Frustum<T> &src) const
+{
+ return !operator== (src);
+}
+
+template<class T>
+void Frustum<T>::set(T n, T f, T l, T r, T t, T b, bool o)
+{
+ _near = n;
+ _far = f;
+ _left = l;
+ _right = r;
+ _bottom = b;
+ _top = t;
+ _orthographic = o;
+}
+
+template<class T>
+void Frustum<T>::modifyNearAndFar(T n, T f)
+{
+ if ( _orthographic )
+ {
+ _near = n;
+ }
+ else
+ {
+ Line3<T> lowerLeft( Vec3<T>(0,0,0), Vec3<T>(_left,_bottom,-_near) );
+ Line3<T> upperRight( Vec3<T>(0,0,0), Vec3<T>(_right,_top,-_near) );
+ Plane3<T> nearPlane( Vec3<T>(0,0,-1), n );
+
+ Vec3<T> ll,ur;
+ nearPlane.intersect(lowerLeft,ll);
+ nearPlane.intersect(upperRight,ur);
+
+ _left = ll.x;
+ _right = ur.x;
+ _top = ur.y;
+ _bottom = ll.y;
+ _near = n;
+ _far = f;
+ }
+
+ _far = f;
+}
+
+template<class T>
+void Frustum<T>::setOrthographic(bool ortho)
+{
+ _orthographic = ortho;
+}
+
+template<class T>
+void Frustum<T>::set(T near, T far, T fovx, T fovy, T aspect)
+{
+ if (fovx != 0 && fovy != 0)
+ throw Iex::ArgExc ("fovx and fovy cannot both be non-zero.");
+
+ if (fovx != 0)
+ {
+ _right = near * Math<T>::tan(fovx/2.0);
+ _left = -_right;
+ _top = ((_right - _left)/aspect)/2.0;
+ _bottom = -_top;
+ }
+ else
+ {
+ _top = near * Math<T>::tan(fovy/2.0);
+ _bottom = -_top;
+ _right = (_top - _bottom) * aspect / 2.0;
+ _left = -_right;
+ }
+ _near = near;
+ _far = far;
+ _orthographic = false;
+}
+
+template<class T>
+T Frustum<T>::fovx() const
+{
+ return Math<T>::atan2(_right,_near) - Math<T>::atan2(_left,_near);
+}
+
+template<class T>
+T Frustum<T>::fovy() const
+{
+ return Math<T>::atan2(_top,_near) - Math<T>::atan2(_bottom,_near);
+}
+
+template<class T>
+T Frustum<T>::aspect() const
+{
+ T rightMinusLeft = _right-_left;
+ T topMinusBottom = _top-_bottom;
+
+ if (abs(topMinusBottom) < 1 &&
+ abs(rightMinusLeft) > limits<T>::max() * abs(topMinusBottom))
+ {
+ throw Iex::DivzeroExc ("Bad viewing frustum: "
+ "aspect ratio cannot be computed.");
+ }
+
+ return rightMinusLeft / topMinusBottom;
+}
+
+template<class T>
+Matrix44<T> Frustum<T>::projectionMatrix() const
+{
+ T rightPlusLeft = _right+_left;
+ T rightMinusLeft = _right-_left;
+
+ T topPlusBottom = _top+_bottom;
+ T topMinusBottom = _top-_bottom;
+
+ T farPlusNear = _far+_near;
+ T farMinusNear = _far-_near;
+
+ if ((abs(rightMinusLeft) < 1 &&
+ abs(rightPlusLeft) > limits<T>::max() * abs(rightMinusLeft)) ||
+ (abs(topMinusBottom) < 1 &&
+ abs(topPlusBottom) > limits<T>::max() * abs(topMinusBottom)) ||
+ (abs(farMinusNear) < 1 &&
+ abs(farPlusNear) > limits<T>::max() * abs(farMinusNear)))
+ {
+ throw Iex::DivzeroExc ("Bad viewing frustum: "
+ "projection matrix cannot be computed.");
+ }
+
+ if ( _orthographic )
+ {
+ T tx = -rightPlusLeft / rightMinusLeft;
+ T ty = -topPlusBottom / topMinusBottom;
+ T tz = -farPlusNear / farMinusNear;
+
+ if ((abs(rightMinusLeft) < 1 &&
+ 2 > limits<T>::max() * abs(rightMinusLeft)) ||
+ (abs(topMinusBottom) < 1 &&
+ 2 > limits<T>::max() * abs(topMinusBottom)) ||
+ (abs(farMinusNear) < 1 &&
+ 2 > limits<T>::max() * abs(farMinusNear)))
+ {
+ throw Iex::DivzeroExc ("Bad viewing frustum: "
+ "projection matrix cannot be computed.");
+ }
+
+ T A = 2 / rightMinusLeft;
+ T B = 2 / topMinusBottom;
+ T C = -2 / farMinusNear;
+
+ return Matrix44<T>( A, 0, 0, 0,
+ 0, B, 0, 0,
+ 0, 0, C, 0,
+ tx, ty, tz, 1.f );
+ }
+ else
+ {
+ T A = rightPlusLeft / rightMinusLeft;
+ T B = topPlusBottom / topMinusBottom;
+ T C = -farPlusNear / farMinusNear;
+
+ T farTimesNear = -2 * _far * _near;
+ if (abs(farMinusNear) < 1 &&
+ abs(farTimesNear) > limits<T>::max() * abs(farMinusNear))
+ {
+ throw Iex::DivzeroExc ("Bad viewing frustum: "
+ "projection matrix cannot be computed.");
+ }
+
+ T D = farTimesNear / farMinusNear;
+
+ T twoTimesNear = 2 * _near;
+
+ if ((abs(rightMinusLeft) < 1 &&
+ abs(twoTimesNear) > limits<T>::max() * abs(rightMinusLeft)) ||
+ (abs(topMinusBottom) < 1 &&
+ abs(twoTimesNear) > limits<T>::max() * abs(topMinusBottom)))
+ {
+ throw Iex::DivzeroExc ("Bad viewing frustum: "
+ "projection matrix cannot be computed.");
+ }
+
+ T E = twoTimesNear / rightMinusLeft;
+ T F = twoTimesNear / topMinusBottom;
+
+ return Matrix44<T>( E, 0, 0, 0,
+ 0, F, 0, 0,
+ A, B, C, -1,
+ 0, 0, D, 0 );
+ }
+}
+
+template<class T>
+Frustum<T> Frustum<T>::window(T l, T r, T t, T b) const
+{
+ // move it to 0->1 space
+
+ Vec2<T> bl = screenToLocal( Vec2<T>(l,b) );
+ Vec2<T> tr = screenToLocal( Vec2<T>(r,t) );
+
+ return Frustum<T>(_near, _far, bl.x, tr.x, tr.y, bl.y, _orthographic);
+}
+
+
+template<class T>
+Vec2<T> Frustum<T>::screenToLocal(const Vec2<T> &s) const
+{
+ return Vec2<T>( _left + (_right-_left) * (1.f+s.x) / 2.f,
+ _bottom + (_top-_bottom) * (1.f+s.y) / 2.f );
+}
+
+template<class T>
+Vec2<T> Frustum<T>::localToScreen(const Vec2<T> &p) const
+{
+ T leftPlusRight = _left - 2 * p.x + _right;
+ T leftMinusRight = _left-_right;
+ T bottomPlusTop = _bottom - 2 * p.y + _top;
+ T bottomMinusTop = _bottom-_top;
+
+ if ((abs(leftMinusRight) < 1 &&
+ abs(leftPlusRight) > limits<T>::max() * abs(leftMinusRight)) ||
+ (abs(bottomMinusTop) < 1 &&
+ abs(bottomPlusTop) > limits<T>::max() * abs(bottomMinusTop)))
+ {
+ throw Iex::DivzeroExc
+ ("Bad viewing frustum: "
+ "local-to-screen transformation cannot be computed");
+ }
+
+ return Vec2<T>( leftPlusRight / leftMinusRight,
+ bottomPlusTop / bottomMinusTop );
+}
+
+template<class T>
+Line3<T> Frustum<T>::projectScreenToRay(const Vec2<T> &p) const
+{
+ Vec2<T> point = screenToLocal(p);
+ if (orthographic())
+ return Line3<T>( Vec3<T>(point.x,point.y, 0.0),
+ Vec3<T>(point.x,point.y,-_near));
+ else
+ return Line3<T>( Vec3<T>(0, 0, 0), Vec3<T>(point.x,point.y,-_near));
+}
+
+template<class T>
+Vec2<T> Frustum<T>::projectPointToScreen(const Vec3<T> &point) const
+{
+ if (orthographic() || point.z == 0)
+ return localToScreen( Vec2<T>( point.x, point.y ) );
+ else
+ return localToScreen( Vec2<T>( point.x * _near / -point.z,
+ point.y * _near / -point.z ) );
+}
+
+template<class T>
+T Frustum<T>::ZToDepth(long zval,long zmin,long zmax) const
+{
+ int zdiff = zmax - zmin;
+
+ if (zdiff == 0)
+ {
+ throw Iex::DivzeroExc
+ ("Bad call to Frustum::ZToDepth: zmax == zmin");
+ }
+
+ if ( zval > zmax+1 ) zval -= zdiff;
+
+ T fzval = (T(zval) - T(zmin)) / T(zdiff);
+ return normalizedZToDepth(fzval);
+}
+
+template<class T>
+T Frustum<T>::normalizedZToDepth(T zval) const
+{
+ T Zp = zval * 2.0 - 1;
+
+ if ( _orthographic )
+ {
+ return -(Zp*(_far-_near) + (_far+_near))/2;
+ }
+ else
+ {
+ T farTimesNear = 2 * _far * _near;
+ T farMinusNear = Zp * (_far - _near) - _far - _near;
+
+ if (abs(farMinusNear) < 1 &&
+ abs(farTimesNear) > limits<T>::max() * abs(farMinusNear))
+ {
+ throw Iex::DivzeroExc
+ ("Frustum::normalizedZToDepth cannot be computed. The "
+ "near and far clipping planes of the viewing frustum "
+ "may be too close to each other");
+ }
+
+ return farTimesNear / farMinusNear;
+ }
+}
+
+template<class T>
+long Frustum<T>::DepthToZ(T depth,long zmin,long zmax) const
+{
+ long zdiff = zmax - zmin;
+ T farMinusNear = _far-_near;
+
+ if ( _orthographic )
+ {
+ T farPlusNear = 2*depth + _far + _near;
+
+ if (abs(farMinusNear) < 1 &&
+ abs(farPlusNear) > limits<T>::max() * abs(farMinusNear))
+ {
+ throw Iex::DivzeroExc
+ ("Bad viewing frustum: near and far clipping planes "
+ "are too close to each other");
+ }
+
+ T Zp = -farPlusNear/farMinusNear;
+ return long(0.5*(Zp+1)*zdiff) + zmin;
+ }
+ else
+ {
+ // Perspective
+
+ T farTimesNear = 2*_far*_near;
+ if (abs(depth) < 1 &&
+ abs(farTimesNear) > limits<T>::max() * abs(depth))
+ {
+ throw Iex::DivzeroExc
+ ("Bad call to DepthToZ function: value of `depth' "
+ "is too small");
+ }
+
+ T farPlusNear = farTimesNear/depth + _far + _near;
+ if (abs(farMinusNear) < 1 &&
+ abs(farPlusNear) > limits<T>::max() * abs(farMinusNear))
+ {
+ throw Iex::DivzeroExc
+ ("Bad viewing frustum: near and far clipping planes "
+ "are too close to each other");
+ }
+
+ T Zp = farPlusNear/farMinusNear;
+ return long(0.5*(Zp+1)*zdiff) + zmin;
+ }
+}
+
+template<class T>
+T Frustum<T>::screenRadius(const Vec3<T> &p, T radius) const
+{
+ // Derivation:
+ // Consider X-Z plane.
+ // X coord of projection of p = xp = p.x * (-_near / p.z)
+ // Let q be p + (radius, 0, 0).
+ // X coord of projection of q = xq = (p.x - radius) * (-_near / p.z)
+ // X coord of projection of segment from p to q = r = xp - xq
+ // = radius * (-_near / p.z)
+ // A similar analysis holds in the Y-Z plane.
+ // So r is the quantity we want to return.
+
+ if (abs(p.z) > 1 || abs(-_near) < limits<T>::max() * abs(p.z))
+ {
+ return radius * (-_near / p.z);
+ }
+ else
+ {
+ throw Iex::DivzeroExc
+ ("Bad call to Frustum::screenRadius: the magnitude of `p' "
+ "is too small");
+ }
+
+ return radius * (-_near / p.z);
+}
+
+template<class T>
+T Frustum<T>::worldRadius(const Vec3<T> &p, T radius) const
+{
+ if (abs(-_near) > 1 || abs(p.z) < limits<T>::max() * abs(-_near))
+ {
+ return radius * (p.z / -_near);
+ }
+ else
+ {
+ throw Iex::DivzeroExc
+ ("Bad viewing frustum: the near clipping plane is too "
+ "close to zero");
+ }
+}
+
+template<class T>
+void Frustum<T>::planes(Plane3<T> p[6])
+{
+ //
+ // Plane order: Top, Right, Bottom, Left, Near, Far.
+ // Normals point outwards.
+ //
+
+ if (! _orthographic)
+ {
+ Vec3<T> a( _left, _bottom, -_near);
+ Vec3<T> b( _left, _top, -_near);
+ Vec3<T> c( _right, _top, -_near);
+ Vec3<T> d( _right, _bottom, -_near);
+ Vec3<T> o(0,0,0);
+
+ p[0].set( o, c, b );
+ p[1].set( o, d, c );
+ p[2].set( o, a, d );
+ p[3].set( o, b, a );
+ }
+ else
+ {
+ p[0].set( Vec3<T>( 0, 1, 0), _top );
+ p[1].set( Vec3<T>( 1, 0, 0), _right );
+ p[2].set( Vec3<T>( 0,-1, 0),-_bottom );
+ p[3].set( Vec3<T>(-1, 0, 0),-_left );
+ }
+ p[4].set( Vec3<T>(0, 0, 1), -_near );
+ p[5].set( Vec3<T>(0, 0,-1), _far );
+}
+
+
+template<class T>
+void Frustum<T>::planes(Plane3<T> p[6], const Matrix44<T> &M)
+{
+ //
+ // Plane order: Top, Right, Bottom, Left, Near, Far.
+ // Normals point outwards.
+ //
+
+ Vec3<T> a = Vec3<T>( _left, _bottom, -_near) * M;
+ Vec3<T> b = Vec3<T>( _left, _top, -_near) * M;
+ Vec3<T> c = Vec3<T>( _right, _top, -_near) * M;
+ Vec3<T> d = Vec3<T>( _right, _bottom, -_near) * M;
+ if (! _orthographic)
+ {
+ double s = _far / double(_near);
+ T farLeft = (T) (s * _left);
+ T farRight = (T) (s * _right);
+ T farTop = (T) (s * _top);
+ T farBottom = (T) (s * _bottom);
+ Vec3<T> e = Vec3<T>( farLeft, farBottom, -_far) * M;
+ Vec3<T> f = Vec3<T>( farLeft, farTop, -_far) * M;
+ Vec3<T> g = Vec3<T>( farRight, farTop, -_far) * M;
+ Vec3<T> o = Vec3<T>(0,0,0) * M;
+ p[0].set( o, c, b );
+ p[1].set( o, d, c );
+ p[2].set( o, a, d );
+ p[3].set( o, b, a );
+ p[4].set( a, d, c );
+ p[5].set( e, f, g );
+ }
+ else
+ {
+ Vec3<T> e = Vec3<T>( _left, _bottom, -_far) * M;
+ Vec3<T> f = Vec3<T>( _left, _top, -_far) * M;
+ Vec3<T> g = Vec3<T>( _right, _top, -_far) * M;
+ Vec3<T> h = Vec3<T>( _right, _bottom, -_far) * M;
+ p[0].set( c, g, f );
+ p[1].set( d, h, g );
+ p[2].set( a, e, h );
+ p[3].set( b, f, e );
+ p[4].set( a, d, c );
+ p[5].set( e, f, g );
+ }
+}
+
+typedef Frustum<float> Frustumf;
+typedef Frustum<double> Frustumd;
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathFun.cpp b/Source/OpenEXR/Imath/ImathFun.cpp
new file mode 100644
index 0000000..defab93
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathFun.cpp
@@ -0,0 +1,181 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#include "ImathFun.h"
+
+namespace Imath {
+
+
+float
+succf (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+
+ if ((u.i & 0x7f800000) == 0x7f800000)
+ {
+ // Nan or infinity; don't change value.
+ }
+ else if (u.i == 0x00000000 || u.i == 0x80000000)
+ {
+ // Plus or minus zero.
+
+ u.i = 0x00000001;
+ }
+ else if (u.i > 0)
+ {
+ // Positive float, normalized or denormalized.
+ // Incrementing the largest positive float
+ // produces +infinity.
+
+ ++u.i;
+ }
+ else
+ {
+ // Negative normalized or denormalized float.
+
+ --u.i;
+ }
+
+ return u.f;
+}
+
+
+float
+predf (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+
+ if ((u.i & 0x7f800000) == 0x7f800000)
+ {
+ // Nan or infinity; don't change value.
+ }
+ else if (u.i == 0x00000000 || u.i == 0x80000000)
+ {
+ // Plus or minus zero.
+
+ u.i = 0x80000001;
+ }
+ else if (u.i > 0)
+ {
+ // Positive float, normalized or denormalized.
+
+ --u.i;
+ }
+ else
+ {
+ // Negative normalized or denormalized float.
+ // Decrementing the largest negative float
+ // produces -infinity.
+
+ ++u.i;
+ }
+
+ return u.f;
+}
+
+
+double
+succd (double d)
+{
+ union {double d; Int64 i;} u;
+ u.d = d;
+
+ if ((u.i & 0x7ff0000000000000LL) == 0x7ff0000000000000LL)
+ {
+ // Nan or infinity; don't change value.
+ }
+ else if (u.i == 0x0000000000000000LL || u.i == 0x8000000000000000LL)
+ {
+ // Plus or minus zero.
+
+ u.i = 0x0000000000000001LL;
+ }
+ else if (u.i > 0)
+ {
+ // Positive double, normalized or denormalized.
+ // Incrementing the largest positive double
+ // produces +infinity.
+
+ ++u.i;
+ }
+ else
+ {
+ // Negative normalized or denormalized double.
+
+ --u.i;
+ }
+
+ return u.d;
+}
+
+
+double
+predd (double d)
+{
+ union {double d; Int64 i;} u;
+ u.d = d;
+
+ if ((u.i & 0x7ff0000000000000LL) == 0x7ff0000000000000LL)
+ {
+ // Nan or infinity; don't change value.
+ }
+ else if (u.i == 0x0000000000000000LL || u.i == 0x8000000000000000LL)
+ {
+ // Plus or minus zero.
+
+ u.i = 0x8000000000000001LL;
+ }
+ else if (u.i > 0)
+ {
+ // Positive double, normalized or denormalized.
+
+ --u.i;
+ }
+ else
+ {
+ // Negative normalized or denormalized double.
+ // Decrementing the largest negative double
+ // produces -infinity.
+
+ ++u.i;
+ }
+
+ return u.d;
+}
+
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathFun.h b/Source/OpenEXR/Imath/ImathFun.h
new file mode 100644
index 0000000..fc403a8
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathFun.h
@@ -0,0 +1,267 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHFUN_H
+#define INCLUDED_IMATHFUN_H
+
+//-----------------------------------------------------------------------------
+//
+// Miscellaneous utility functions
+//
+//-----------------------------------------------------------------------------
+
+#include "ImathLimits.h"
+#include "ImathInt64.h"
+
+namespace Imath {
+
+template <class T>
+inline T
+abs (T a)
+{
+ return (a > 0) ? a : -a;
+}
+
+
+template <class T>
+inline int
+sign (T a)
+{
+ return (a > 0)? 1 : ((a < 0) ? -1 : 0);
+}
+
+
+template <class T, class Q>
+inline T
+lerp (T a, T b, Q t)
+{
+ return (T) (a * (1 - t) + b * t);
+}
+
+
+template <class T, class Q>
+inline T
+ulerp (T a, T b, Q t)
+{
+ return (T) ((a > b)? (a - (a - b) * t): (a + (b - a) * t));
+}
+
+
+template <class T>
+inline T
+lerpfactor(T m, T a, T b)
+{
+ //
+ // Return how far m is between a and b, that is return t such that
+ // if:
+ // t = lerpfactor(m, a, b);
+ // then:
+ // m = lerp(a, b, t);
+ //
+ // If a==b, return 0.
+ //
+
+ T d = b - a;
+ T n = m - a;
+
+ if (abs(d) > T(1) || abs(n) < limits<T>::max() * abs(d))
+ return n / d;
+
+ return T(0);
+}
+
+
+template <class T>
+inline T
+clamp (T a, T l, T h)
+{
+ return (a < l)? l : ((a > h)? h : a);
+}
+
+
+template <class T>
+inline int
+cmp (T a, T b)
+{
+ return Imath::sign (a - b);
+}
+
+
+template <class T>
+inline int
+cmpt (T a, T b, T t)
+{
+ return (Imath::abs (a - b) <= t)? 0 : cmp (a, b);
+}
+
+
+template <class T>
+inline bool
+iszero (T a, T t)
+{
+ return (Imath::abs (a) <= t) ? 1 : 0;
+}
+
+
+template <class T1, class T2, class T3>
+inline bool
+equal (T1 a, T2 b, T3 t)
+{
+ return Imath::abs (a - b) <= t;
+}
+
+template <class T>
+inline int
+floor (T x)
+{
+ return (x >= 0)? int (x): -(int (-x) + (-x > int (-x)));
+}
+
+
+template <class T>
+inline int
+ceil (T x)
+{
+ return -floor (-x);
+}
+
+template <class T>
+inline int
+trunc (T x)
+{
+ return (x >= 0) ? int(x) : -int(-x);
+}
+
+
+//
+// Integer division and remainder where the
+// remainder of x/y has the same sign as x:
+//
+// divs(x,y) == (abs(x) / abs(y)) * (sign(x) * sign(y))
+// mods(x,y) == x - y * divs(x,y)
+//
+
+inline int
+divs (int x, int y)
+{
+ return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)):
+ ((y >= 0)? -(-x / y): (-x / -y));
+}
+
+
+inline int
+mods (int x, int y)
+{
+ return (x >= 0)? ((y >= 0)? ( x % y): ( x % -y)):
+ ((y >= 0)? -(-x % y): -(-x % -y));
+}
+
+
+//
+// Integer division and remainder where the
+// remainder of x/y is always positive:
+//
+// divp(x,y) == floor (double(x) / double (y))
+// modp(x,y) == x - y * divp(x,y)
+//
+
+inline int
+divp (int x, int y)
+{
+ return (x >= 0)? ((y >= 0)? ( x / y): -( x / -y)):
+ ((y >= 0)? -((y-1-x) / y): ((-y-1-x) / -y));
+}
+
+
+inline int
+modp (int x, int y)
+{
+ return x - y * divp (x, y);
+}
+
+//----------------------------------------------------------
+// Successor and predecessor for floating-point numbers:
+//
+// succf(f) returns float(f+e), where e is the smallest
+// positive number such that float(f+e) != f.
+//
+// predf(f) returns float(f-e), where e is the smallest
+// positive number such that float(f-e) != f.
+//
+// succd(d) returns double(d+e), where e is the smallest
+// positive number such that double(d+e) != d.
+//
+// predd(d) returns double(d-e), where e is the smallest
+// positive number such that double(d-e) != d.
+//
+// Exceptions: If the input value is an infinity or a nan,
+// succf(), predf(), succd(), and predd() all
+// return the input value without changing it.
+//
+//----------------------------------------------------------
+
+float succf (float f);
+float predf (float f);
+
+double succd (double d);
+double predd (double d);
+
+//
+// Return true if the number is not a NaN or Infinity.
+//
+
+inline bool
+finitef (float f)
+{
+ union {float f; int i;} u;
+ u.f = f;
+
+ return (u.i & 0x7f800000) != 0x7f800000;
+}
+
+inline bool
+finited (double d)
+{
+ union {double d; Int64 i;} u;
+ u.d = d;
+
+ return (u.i & 0x7ff0000000000000LL) != 0x7ff0000000000000LL;
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathGL.h b/Source/OpenEXR/Imath/ImathGL.h
new file mode 100644
index 0000000..36be0fd
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathGL.h
@@ -0,0 +1,159 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMATHGL_H
+#define INCLUDED_IMATHGL_H
+
+#include <GL/gl.h>
+
+#include "ImathVec.h"
+#include "ImathMatrix.h"
+#include "IexMathExc.h"
+#include "ImathFun.h"
+
+inline void glVertex ( const Imath::V3f &v ) { glVertex3f(v.x,v.y,v.z); }
+inline void glVertex ( const Imath::V2f &v ) { glVertex2f(v.x,v.y); }
+inline void glNormal ( const Imath::V3f &n ) { glNormal3f(n.x,n.y,n.z); }
+inline void glColor ( const Imath::V3f &c ) { glColor3f(c.x,c.y,c.z); }
+inline void glTranslate ( const Imath::V3f &t ) { glTranslatef(t.x,t.y,t.z); }
+
+inline void glTexCoord( const Imath::V2f &t )
+{
+ glTexCoord2f(t.x,t.y);
+}
+
+inline void glDisableTexture()
+{
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDisable(GL_TEXTURE_2D);
+
+ glActiveTexture(GL_TEXTURE0);
+}
+
+namespace {
+
+const float GL_FLOAT_MAX = 1.8e+19; // sqrt (FLT_MAX)
+
+inline bool
+badFloat (float f)
+{
+ return !Imath::finitef (f) || f < - GL_FLOAT_MAX || f > GL_FLOAT_MAX;
+}
+
+} // namespace
+
+inline void
+throwBadMatrix (const Imath::M44f& m)
+{
+ if (badFloat (m[0][0]) ||
+ badFloat (m[0][1]) ||
+ badFloat (m[0][2]) ||
+ badFloat (m[0][3]) ||
+ badFloat (m[1][0]) ||
+ badFloat (m[1][1]) ||
+ badFloat (m[1][2]) ||
+ badFloat (m[1][3]) ||
+ badFloat (m[2][0]) ||
+ badFloat (m[2][1]) ||
+ badFloat (m[2][2]) ||
+ badFloat (m[2][3]) ||
+ badFloat (m[3][0]) ||
+ badFloat (m[3][1]) ||
+ badFloat (m[3][2]) ||
+ badFloat (m[3][3]))
+ throw Iex::OverflowExc ("GL matrix overflow");
+}
+
+inline void
+glMultMatrix( const Imath::M44f& m )
+{
+ throwBadMatrix (m);
+ glMultMatrixf( (GLfloat*)m[0] );
+}
+
+inline void
+glMultMatrix( const Imath::M44f* m )
+{
+ throwBadMatrix (*m);
+ glMultMatrixf( (GLfloat*)(*m)[0] );
+}
+
+inline void
+glLoadMatrix( const Imath::M44f& m )
+{
+ throwBadMatrix (m);
+ glLoadMatrixf( (GLfloat*)m[0] );
+}
+
+inline void
+glLoadMatrix( const Imath::M44f* m )
+{
+ throwBadMatrix (*m);
+ glLoadMatrixf( (GLfloat*)(*m)[0] );
+}
+
+
+namespace Imath {
+
+//
+// Class objects that push/pop the GL state. These objects assist with
+// proper cleanup of the state when exceptions are thrown.
+//
+
+class GLPushMatrix {
+ public:
+
+ GLPushMatrix () { glPushMatrix(); }
+ ~GLPushMatrix() { glPopMatrix(); }
+};
+
+class GLPushAttrib {
+ public:
+
+ GLPushAttrib (GLbitfield mask) { glPushAttrib (mask); }
+ ~GLPushAttrib() { glPopAttrib(); }
+};
+
+class GLBegin {
+ public:
+
+ GLBegin (GLenum mode) { glBegin (mode); }
+ ~GLBegin() { glEnd(); }
+};
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathGLU.h b/Source/OpenEXR/Imath/ImathGLU.h
new file mode 100644
index 0000000..e43d560
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathGLU.h
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHGLU_H
+#define INCLUDED_IMATHGLU_H
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include "ImathVec.h"
+
+inline
+void
+gluLookAt(const Imath::V3f &pos, const Imath::V3f &interest, const Imath::V3f &up)
+{
+ gluLookAt(pos.x, pos.y, pos.z,
+ interest.x, interest.y, interest.z,
+ up.x, up.y, up.z);
+}
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathHalfLimits.h b/Source/OpenEXR/Imath/ImathHalfLimits.h
new file mode 100644
index 0000000..2170f94
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathHalfLimits.h
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHHALFLIMITS_H
+#define INCLUDED_IMATHHALFLIMITS_H
+
+//--------------------------------------------------
+//
+// Imath-style limits for class half.
+//
+//--------------------------------------------------
+
+#include "ImathLimits.h"
+#include "half.h"
+
+namespace Imath {
+
+
+template <>
+struct limits <half>
+{
+ static float min() {return -HALF_MAX;}
+ static float max() {return HALF_MAX;}
+ static float smallest() {return HALF_MIN;}
+ static float epsilon() {return HALF_EPSILON;}
+ static bool isIntegral() {return false;}
+ static bool isSigned() {return true;}
+};
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathInt64.h b/Source/OpenEXR/Imath/ImathInt64.h
new file mode 100644
index 0000000..71ee4ec
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathInt64.h
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMATH_INT64_H
+#define INCLUDED_IMATH_INT64_H
+
+//----------------------------------------------------------------------------
+//
+// Int64 -- unsigned 64-bit integers
+//
+//----------------------------------------------------------------------------
+
+#include <limits.h>
+
+namespace Imath {
+
+
+#if (defined _WIN32 || defined _WIN64) && _MSC_VER >= 1300
+ typedef unsigned __int64 Int64;
+#elif ULONG_MAX == 18446744073709551615LU
+ typedef long unsigned int Int64;
+#else
+ typedef long long unsigned int Int64;
+#endif
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathInterval.h b/Source/OpenEXR/Imath/ImathInterval.h
new file mode 100644
index 0000000..2d9d7d3
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathInterval.h
@@ -0,0 +1,224 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHINTERVAL_H
+#define INCLUDED_IMATHINTERVAL_H
+
+
+//-------------------------------------------------------------------
+//
+// class Imath::Interval<class T>
+// --------------------------------
+//
+// An Interval has a min and a max and some miscellaneous
+// functions. It is basically a Box<T> that allows T to be
+// a scalar.
+//
+//-------------------------------------------------------------------
+
+#include "ImathVec.h"
+
+namespace Imath {
+
+
+template <class T>
+class Interval
+{
+ public:
+
+ //-------------------------
+ // Data Members are public
+ //-------------------------
+
+ T min;
+ T max;
+
+ //-----------------------------------------------------
+ // Constructors - an "empty" Interval is created by default
+ //-----------------------------------------------------
+
+ Interval();
+ Interval(const T& point);
+ Interval(const T& minT, const T& maxT);
+
+ //--------------------------------
+ // Operators: we get != from STL
+ //--------------------------------
+
+ bool operator == (const Interval<T> &src) const;
+
+ //------------------
+ // Interval manipulation
+ //------------------
+
+ void makeEmpty();
+ void extendBy(const T& point);
+ void extendBy(const Interval<T>& interval);
+
+ //---------------------------------------------------
+ // Query functions - these compute results each time
+ //---------------------------------------------------
+
+ T size() const;
+ T center() const;
+ bool intersects(const T &point) const;
+ bool intersects(const Interval<T> &interval) const;
+
+ //----------------
+ // Classification
+ //----------------
+
+ bool hasVolume() const;
+ bool isEmpty() const;
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+
+typedef Interval <float> Intervalf;
+typedef Interval <double> Intervald;
+typedef Interval <short> Intervals;
+typedef Interval <int> Intervali;
+
+//----------------
+// Implementation
+//----------------
+
+
+template <class T>
+inline Interval<T>::Interval()
+{
+ makeEmpty();
+}
+
+template <class T>
+inline Interval<T>::Interval(const T& point)
+{
+ min = point;
+ max = point;
+}
+
+template <class T>
+inline Interval<T>::Interval(const T& minV, const T& maxV)
+{
+ min = minV;
+ max = maxV;
+}
+
+template <class T>
+inline bool
+Interval<T>::operator == (const Interval<T> &src) const
+{
+ return (min == src.min && max == src.max);
+}
+
+template <class T>
+inline void
+Interval<T>::makeEmpty()
+{
+ min = limits<T>::max();
+ max = limits<T>::min();
+}
+
+template <class T>
+inline void
+Interval<T>::extendBy(const T& point)
+{
+ if ( point < min )
+ min = point;
+
+ if ( point > max )
+ max = point;
+}
+
+template <class T>
+inline void
+Interval<T>::extendBy(const Interval<T>& interval)
+{
+ if ( interval.min < min )
+ min = interval.min;
+
+ if ( interval.max > max )
+ max = interval.max;
+}
+
+template <class T>
+inline bool
+Interval<T>::intersects(const T& point) const
+{
+ return point >= min && point <= max;
+}
+
+template <class T>
+inline bool
+Interval<T>::intersects(const Interval<T>& interval) const
+{
+ return interval.max >= min && interval.min <= max;
+}
+
+template <class T>
+inline T
+Interval<T>::size() const
+{
+ return max-min;
+}
+
+template <class T>
+inline T
+Interval<T>::center() const
+{
+ return (max+min)/2;
+}
+
+template <class T>
+inline bool
+Interval<T>::isEmpty() const
+{
+ return max < min;
+}
+
+template <class T>
+inline bool Interval<T>::hasVolume() const
+{
+ return max > min;
+}
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathLimits.h b/Source/OpenEXR/Imath/ImathLimits.h
new file mode 100644
index 0000000..0a67e5b
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathLimits.h
@@ -0,0 +1,265 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHLIMITS_H
+#define INCLUDED_IMATHLIMITS_H
+
+//----------------------------------------------------------------
+//
+// Limitations of the basic C++ numerical data types
+//
+//----------------------------------------------------------------
+
+#include <float.h>
+#include <limits.h>
+
+//------------------------------------------
+// In Windows, min and max are macros. Yay.
+//------------------------------------------
+
+#if defined _WIN32 || defined _WIN64
+ #ifdef min
+ #undef min
+ #endif
+ #ifdef max
+ #undef max
+ #endif
+#endif
+
+namespace Imath {
+
+
+//-----------------------------------------------------------------
+//
+// Template class limits<T> returns information about the limits
+// of numerical data type T:
+//
+// min() largest possible negative value of type T
+//
+// max() largest possible positive value of type T
+//
+// smallest() smallest possible positive value of type T
+//
+// epsilon() smallest possible e of type T, for which
+// 1 + e != 1
+//
+// isIntegral() returns true if T is an integral type
+//
+// isSigned() returns true if T is signed
+//
+// Class limits<T> is useful to implement template classes or
+// functions which depend on the limits of a numerical type
+// which is not known in advance; for example:
+//
+// template <class T> max (T x[], int n)
+// {
+// T m = limits<T>::min();
+//
+// for (int i = 0; i < n; i++)
+// if (m < x[i])
+// m = x[i];
+//
+// return m;
+// }
+//
+// Class limits<T> has been implemented for the following types:
+//
+// char, signed char, unsigned char
+// short, unsigned short
+// int, unsigned int
+// long, unsigned long
+// float
+// double
+// long double
+//
+// Class limits<T> has only static member functions, all of which
+// are implemented as inlines. No objects of type limits<T> are
+// ever created.
+//
+//-----------------------------------------------------------------
+
+
+template <class T> struct limits
+{
+ static T min();
+ static T max();
+ static T smallest();
+ static T epsilon();
+ static bool isIntegral();
+ static bool isSigned();
+};
+
+
+//---------------
+// Implementation
+//---------------
+
+template <>
+struct limits <char>
+{
+ static char min() {return CHAR_MIN;}
+ static char max() {return CHAR_MAX;}
+ static char smallest() {return 1;}
+ static char epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return (char) ~0 < 0;}
+};
+
+template <>
+struct limits <signed char>
+{
+ static signed char min() {return SCHAR_MIN;}
+ static signed char max() {return SCHAR_MAX;}
+ static signed char smallest() {return 1;}
+ static signed char epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <unsigned char>
+{
+ static unsigned char min() {return 0;}
+ static unsigned char max() {return UCHAR_MAX;}
+ static unsigned char smallest() {return 1;}
+ static unsigned char epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return false;}
+};
+
+template <>
+struct limits <short>
+{
+ static short min() {return SHRT_MIN;}
+ static short max() {return SHRT_MAX;}
+ static short smallest() {return 1;}
+ static short epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <unsigned short>
+{
+ static unsigned short min() {return 0;}
+ static unsigned short max() {return USHRT_MAX;}
+ static unsigned short smallest() {return 1;}
+ static unsigned short epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return false;}
+};
+
+template <>
+struct limits <int>
+{
+ static int min() {return INT_MIN;}
+ static int max() {return INT_MAX;}
+ static int smallest() {return 1;}
+ static int epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <unsigned int>
+{
+ static unsigned int min() {return 0;}
+ static unsigned int max() {return UINT_MAX;}
+ static unsigned int smallest() {return 1;}
+ static unsigned int epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return false;}
+};
+
+template <>
+struct limits <long>
+{
+ static long min() {return LONG_MIN;}
+ static long max() {return LONG_MAX;}
+ static long smallest() {return 1;}
+ static long epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <unsigned long>
+{
+ static unsigned long min() {return 0;}
+ static unsigned long max() {return ULONG_MAX;}
+ static unsigned long smallest() {return 1;}
+ static unsigned long epsilon() {return 1;}
+ static bool isIntegral() {return true;}
+ static bool isSigned() {return false;}
+};
+
+template <>
+struct limits <float>
+{
+ static float min() {return -FLT_MAX;}
+ static float max() {return FLT_MAX;}
+ static float smallest() {return FLT_MIN;}
+ static float epsilon() {return FLT_EPSILON;}
+ static bool isIntegral() {return false;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <double>
+{
+ static double min() {return -DBL_MAX;}
+ static double max() {return DBL_MAX;}
+ static double smallest() {return DBL_MIN;}
+ static double epsilon() {return DBL_EPSILON;}
+ static bool isIntegral() {return false;}
+ static bool isSigned() {return true;}
+};
+
+template <>
+struct limits <long double>
+{
+ static long double min() {return -LDBL_MAX;}
+ static long double max() {return LDBL_MAX;}
+ static long double smallest() {return LDBL_MIN;}
+ static long double epsilon() {return LDBL_EPSILON;}
+ static bool isIntegral() {return false;}
+ static bool isSigned() {return true;}
+};
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathLine.h b/Source/OpenEXR/Imath/ImathLine.h
new file mode 100644
index 0000000..601fc6f
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathLine.h
@@ -0,0 +1,184 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHLINE_H
+#define INCLUDED_IMATHLINE_H
+
+//-------------------------------------
+//
+// A 3D line class template
+//
+//-------------------------------------
+
+#include "ImathVec.h"
+#include "ImathLimits.h"
+#include "ImathMatrix.h"
+
+namespace Imath {
+
+
+template <class T>
+class Line3
+{
+ public:
+
+ Vec3<T> pos;
+ Vec3<T> dir;
+
+ //-------------------------------------------------------------
+ // Constructors - default is normalized units along direction
+ //-------------------------------------------------------------
+
+ Line3() {}
+ Line3(const Vec3<T>& point1, const Vec3<T>& point2);
+
+ //------------------
+ // State Query/Set
+ //------------------
+
+ void set(const Vec3<T>& point1,
+ const Vec3<T>& point2);
+
+ //-------
+ // F(t)
+ //-------
+
+ Vec3<T> operator() (T parameter) const;
+
+ //---------
+ // Query
+ //---------
+
+ T distanceTo(const Vec3<T>& point) const;
+ T distanceTo(const Line3<T>& line) const;
+ Vec3<T> closestPointTo(const Vec3<T>& point) const;
+ Vec3<T> closestPointTo(const Line3<T>& line) const;
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+typedef Line3<float> Line3f;
+typedef Line3<double> Line3d;
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+inline Line3<T>::Line3(const Vec3<T> &p0, const Vec3<T> &p1)
+{
+ set(p0,p1);
+}
+
+template <class T>
+inline void Line3<T>::set(const Vec3<T> &p0, const Vec3<T> &p1)
+{
+ pos = p0; dir = p1-p0;
+ dir.normalize();
+}
+
+template <class T>
+inline Vec3<T> Line3<T>::operator()(T parameter) const
+{
+ return pos + dir * parameter;
+}
+
+template <class T>
+inline T Line3<T>::distanceTo(const Vec3<T>& point) const
+{
+ return (closestPointTo(point)-point).length();
+}
+
+template <class T>
+inline Vec3<T> Line3<T>::closestPointTo(const Vec3<T>& point) const
+{
+ return ((point - pos) ^ dir) * dir + pos;
+}
+
+template <class T>
+inline T Line3<T>::distanceTo(const Line3<T>& line) const
+{
+ T d = (dir % line.dir) ^ (line.pos - pos);
+ return (d >= 0)? d: -d;
+}
+
+template <class T>
+inline Vec3<T>
+Line3<T>::closestPointTo(const Line3<T>& line) const
+{
+ // Assumes the lines are normalized
+
+ Vec3<T> posLpos = pos - line.pos ;
+ T c = dir ^ posLpos;
+ T a = line.dir ^ dir;
+ T f = line.dir ^ posLpos ;
+ T num = c - a * f;
+
+ T denom = a*a - 1;
+
+ T absDenom = ((denom >= 0)? denom: -denom);
+
+ if (absDenom < 1)
+ {
+ T absNum = ((num >= 0)? num: -num);
+
+ if (absNum >= absDenom * limits<T>::max())
+ return pos;
+ }
+
+ return pos + dir * (num / denom);
+}
+
+template<class T>
+std::ostream& operator<< (std::ostream &o, const Line3<T> &line)
+{
+ return o << "(" << line.pos << ", " << line.dir << ")";
+}
+
+template<class S, class T>
+inline Line3<S> operator * (const Line3<S> &line, const Matrix44<T> &M)
+{
+ return Line3<S>( line.pos * M, (line.pos + line.dir) * M );
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathLineAlgo.h b/Source/OpenEXR/Imath/ImathLineAlgo.h
new file mode 100644
index 0000000..41855c9
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathLineAlgo.h
@@ -0,0 +1,287 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHLINEALGO_H
+#define INCLUDED_IMATHLINEALGO_H
+
+//------------------------------------------------------------------
+//
+// This file contains algorithms applied to or in conjunction
+// with lines (Imath::Line). These algorithms may require
+// more headers to compile. The assumption made is that these
+// functions are called much less often than the basic line
+// functions or these functions require more support classes
+//
+// Contains:
+//
+// bool closestPoints(const Line<T>& line1,
+// const Line<T>& line2,
+// Vec3<T>& point1,
+// Vec3<T>& point2)
+//
+// bool intersect( const Line3<T> &line,
+// const Vec3<T> &v0,
+// const Vec3<T> &v1,
+// const Vec3<T> &v2,
+// Vec3<T> &pt,
+// Vec3<T> &barycentric,
+// bool &front)
+//
+// V3f
+// closestVertex(const Vec3<T> &v0,
+// const Vec3<T> &v1,
+// const Vec3<T> &v2,
+// const Line3<T> &l)
+//
+// V3f
+// rotatePoint(const Vec3<T> p, Line3<T> l, float angle)
+//
+//------------------------------------------------------------------
+
+#include "ImathLine.h"
+#include "ImathVecAlgo.h"
+#include "ImathFun.h"
+
+namespace Imath {
+
+
+template <class T>
+bool
+closestPoints
+ (const Line3<T>& line1,
+ const Line3<T>& line2,
+ Vec3<T>& point1,
+ Vec3<T>& point2)
+{
+ //
+ // Compute point1 and point2 such that point1 is on line1, point2
+ // is on line2 and the distance between point1 and point2 is minimal.
+ // This function returns true if point1 and point2 can be computed,
+ // or false if line1 and line2 are parallel or nearly parallel.
+ // This function assumes that line1.dir and line2.dir are normalized.
+ //
+
+ Vec3<T> w = line1.pos - line2.pos;
+ T d1w = line1.dir ^ w;
+ T d2w = line2.dir ^ w;
+ T d1d2 = line1.dir ^ line2.dir;
+ T n1 = d1d2 * d2w - d1w;
+ T n2 = d2w - d1d2 * d1w;
+ T d = 1 - d1d2 * d1d2;
+ T absD = abs (d);
+
+ if ((absD > 1) ||
+ (abs (n1) < limits<T>::max() * absD &&
+ abs (n2) < limits<T>::max() * absD))
+ {
+ point1 = line1 (n1 / d);
+ point2 = line2 (n2 / d);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+template <class T>
+bool
+intersect
+ (const Line3<T> &line,
+ const Vec3<T> &v0,
+ const Vec3<T> &v1,
+ const Vec3<T> &v2,
+ Vec3<T> &pt,
+ Vec3<T> &barycentric,
+ bool &front)
+{
+ //
+ // Given a line and a triangle (v0, v1, v2), the intersect() function
+ // finds the intersection of the line and the plane that contains the
+ // triangle.
+ //
+ // If the intersection point cannot be computed, either because the
+ // line and the triangle's plane are nearly parallel or because the
+ // triangle's area is very small, intersect() returns false.
+ //
+ // If the intersection point is outside the triangle, intersect
+ // returns false.
+ //
+ // If the intersection point, pt, is inside the triangle, intersect()
+ // computes a front-facing flag and the barycentric coordinates of
+ // the intersection point, and returns true.
+ //
+ // The front-facing flag is true if the dot product of the triangle's
+ // normal, (v2-v1)%(v1-v0), and the line's direction is negative.
+ //
+ // The barycentric coordinates have the following property:
+ //
+ // pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z
+ //
+
+ Vec3<T> edge0 = v1 - v0;
+ Vec3<T> edge1 = v2 - v1;
+ Vec3<T> normal = edge1 % edge0;
+
+ T l = normal.length();
+
+ if (l != 0)
+ normal /= l;
+ else
+ return false; // zero-area triangle
+
+ //
+ // d is the distance of line.pos from the plane that contains the triangle.
+ // The intersection point is at line.pos + (d/nd) * line.dir.
+ //
+
+ T d = normal ^ (v0 - line.pos);
+ T nd = normal ^ line.dir;
+
+ if (abs (nd) > 1 || abs (d) < limits<T>::max() * abs (nd))
+ pt = line (d / nd);
+ else
+ return false; // line and plane are nearly parallel
+
+ //
+ // Compute the barycentric coordinates of the intersection point.
+ // The intersection is inside the triangle if all three barycentric
+ // coordinates are between zero and one.
+ //
+
+ {
+ Vec3<T> en = edge0.normalized();
+ Vec3<T> a = pt - v0;
+ Vec3<T> b = v2 - v0;
+ Vec3<T> c = (a - en * (en ^ a));
+ Vec3<T> d = (b - en * (en ^ b));
+ T e = c ^ d;
+ T f = d ^ d;
+
+ if (e >= 0 && e <= f)
+ barycentric.z = e / f;
+ else
+ return false; // outside
+ }
+
+ {
+ Vec3<T> en = edge1.normalized();
+ Vec3<T> a = pt - v1;
+ Vec3<T> b = v0 - v1;
+ Vec3<T> c = (a - en * (en ^ a));
+ Vec3<T> d = (b - en * (en ^ b));
+ T e = c ^ d;
+ T f = d ^ d;
+
+ if (e >= 0 && e <= f)
+ barycentric.x = e / f;
+ else
+ return false; // outside
+ }
+
+ barycentric.y = 1 - barycentric.x - barycentric.z;
+
+ if (barycentric.y < 0)
+ return false; // outside
+
+ front = ((line.dir ^ normal) < 0);
+ return true;
+}
+
+
+template <class T>
+Vec3<T>
+closestVertex
+ (const Vec3<T> &v0,
+ const Vec3<T> &v1,
+ const Vec3<T> &v2,
+ const Line3<T> &l)
+{
+ Vec3<T> nearest = v0;
+ T neardot = (v0 - l.closestPointTo(v0)).length2();
+
+ T tmp = (v1 - l.closestPointTo(v1)).length2();
+
+ if (tmp < neardot)
+ {
+ neardot = tmp;
+ nearest = v1;
+ }
+
+ tmp = (v2 - l.closestPointTo(v2)).length2();
+ if (tmp < neardot)
+ {
+ neardot = tmp;
+ nearest = v2;
+ }
+
+ return nearest;
+}
+
+
+template <class T>
+Vec3<T>
+rotatePoint (const Vec3<T> p, Line3<T> l, T angle)
+{
+ //
+ // Rotate the point p around the line l by the given angle.
+ //
+
+ //
+ // Form a coordinate frame with <x,y,a>. The rotation is the in xy
+ // plane.
+ //
+
+ Vec3<T> q = l.closestPointTo(p);
+ Vec3<T> x = p - q;
+ T radius = x.length();
+
+ x.normalize();
+ Vec3<T> y = (x % l.dir).normalize();
+
+ T cosangle = Math<T>::cos(angle);
+ T sinangle = Math<T>::sin(angle);
+
+ Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle;
+
+ return r;
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathMath.h b/Source/OpenEXR/Imath/ImathMath.h
new file mode 100644
index 0000000..d5b4616
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathMath.h
@@ -0,0 +1,208 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHMATH_H
+#define INCLUDED_IMATHMATH_H
+
+//----------------------------------------------------------------------------
+//
+// ImathMath.h
+//
+// This file contains template functions which call the double-
+// precision math functions defined in math.h (sin(), sqrt(),
+// exp() etc.), with specializations that call the faster
+// single-precision versions (sinf(), sqrtf(), expf() etc.)
+// when appropriate.
+//
+// Example:
+//
+// double x = Math<double>::sqrt (3); // calls ::sqrt(double);
+// float y = Math<float>::sqrt (3); // calls ::sqrtf(float);
+//
+// When would I want to use this?
+//
+// You may be writing a template which needs to call some function
+// defined in math.h, for example to extract a square root, but you
+// don't know whether to call the single- or the double-precision
+// version of this function (sqrt() or sqrtf()):
+//
+// template <class T>
+// T
+// glorp (T x)
+// {
+// return sqrt (x + 1); // should call ::sqrtf(float)
+// } // if x is a float, but we
+// // don't know if it is
+//
+// Using the templates in this file, you can make sure that
+// the appropriate version of the math function is called:
+//
+// template <class T>
+// T
+// glorp (T x, T y)
+// {
+// return Math<T>::sqrt (x + 1); // calls ::sqrtf(float) if x
+// } // is a float, ::sqrt(double)
+// // otherwise
+//
+//----------------------------------------------------------------------------
+
+#include "ImathPlatform.h"
+#include "ImathLimits.h"
+#include <math.h>
+
+namespace Imath {
+
+
+template <class T>
+struct Math
+{
+ static T acos (T x) {return ::acos (double(x));}
+ static T asin (T x) {return ::asin (double(x));}
+ static T atan (T x) {return ::atan (double(x));}
+ static T atan2 (T x, T y) {return ::atan2 (double(x), double(y));}
+ static T cos (T x) {return ::cos (double(x));}
+ static T sin (T x) {return ::sin (double(x));}
+ static T tan (T x) {return ::tan (double(x));}
+ static T cosh (T x) {return ::cosh (double(x));}
+ static T sinh (T x) {return ::sinh (double(x));}
+ static T tanh (T x) {return ::tanh (double(x));}
+ static T exp (T x) {return ::exp (double(x));}
+ static T log (T x) {return ::log (double(x));}
+ static T log10 (T x) {return ::log10 (double(x));}
+ static T modf (T x, T *iptr)
+ {
+ double ival;
+ T rval( ::modf (double(x),&ival));
+ *iptr = ival;
+ return rval;
+ }
+ static T pow (T x, T y) {return ::pow (double(x), double(y));}
+ static T sqrt (T x) {return ::sqrt (double(x));}
+ static T ceil (T x) {return ::ceil (double(x));}
+ static T fabs (T x) {return ::fabs (double(x));}
+ static T floor (T x) {return ::floor (double(x));}
+ static T fmod (T x, T y) {return ::fmod (double(x), double(y));}
+ static T hypot (T x, T y) {return ::hypot (double(x), double(y));}
+};
+
+
+template <>
+struct Math<float>
+{
+ static float acos (float x) {return ::acosf (x);}
+ static float asin (float x) {return ::asinf (x);}
+ static float atan (float x) {return ::atanf (x);}
+ static float atan2 (float x, float y) {return ::atan2f (x, y);}
+ static float cos (float x) {return ::cosf (x);}
+ static float sin (float x) {return ::sinf (x);}
+ static float tan (float x) {return ::tanf (x);}
+ static float cosh (float x) {return ::coshf (x);}
+ static float sinh (float x) {return ::sinhf (x);}
+ static float tanh (float x) {return ::tanhf (x);}
+ static float exp (float x) {return ::expf (x);}
+ static float log (float x) {return ::logf (x);}
+ static float log10 (float x) {return ::log10f (x);}
+ static float modf (float x, float *y) {return ::modff (x, y);}
+ static float pow (float x, float y) {return ::powf (x, y);}
+ static float sqrt (float x) {return ::sqrtf (x);}
+ static float ceil (float x) {return ::ceilf (x);}
+ static float fabs (float x) {return ::fabsf (x);}
+ static float floor (float x) {return ::floorf (x);}
+ static float fmod (float x, float y) {return ::fmodf (x, y);}
+#if !defined(_MSC_VER)
+ static float hypot (float x, float y) {return ::hypotf (x, y);}
+#else
+ static float hypot (float x, float y) {return ::sqrtf(x*x + y*y);}
+#endif
+};
+
+
+//--------------------------------------------------------------------------
+// Don Hatch's version of sin(x)/x, which is accurate for very small x.
+// Returns 1 for x == 0.
+//--------------------------------------------------------------------------
+
+template <class T>
+inline T
+sinx_over_x (T x)
+{
+ if (x * x < limits<T>::epsilon())
+ return T (1);
+ else
+ return Math<T>::sin (x) / x;
+}
+
+
+//--------------------------------------------------------------------------
+// Compare two numbers and test if they are "approximately equal":
+//
+// equalWithAbsError (x1, x2, e)
+//
+// Returns true if x1 is the same as x2 with an absolute error of
+// no more than e,
+//
+// abs (x1 - x2) <= e
+//
+// equalWithRelError (x1, x2, e)
+//
+// Returns true if x1 is the same as x2 with an relative error of
+// no more than e,
+//
+// abs (x1 - x2) <= e * x1
+//
+//--------------------------------------------------------------------------
+
+template <class T>
+inline bool
+equalWithAbsError (T x1, T x2, T e)
+{
+ return ((x1 > x2)? x1 - x2: x2 - x1) <= e;
+}
+
+
+template <class T>
+inline bool
+equalWithRelError (T x1, T x2, T e)
+{
+ return ((x1 > x2)? x1 - x2: x2 - x1) <= e * ((x1 > 0)? x1: -x1);
+}
+
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathMatrix.h b/Source/OpenEXR/Imath/ImathMatrix.h
new file mode 100644
index 0000000..d4a6d4e
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathMatrix.h
@@ -0,0 +1,3254 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHMATRIX_H
+#define INCLUDED_IMATHMATRIX_H
+
+//----------------------------------------------------------------
+//
+// 2D (3x3) and 3D (4x4) transformation matrix templates.
+//
+//----------------------------------------------------------------
+
+#include "ImathPlatform.h"
+#include "ImathFun.h"
+#include "ImathExc.h"
+#include "ImathVec.h"
+#include "ImathShear.h"
+
+#include <iostream>
+#include <iomanip>
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// suppress exception specification warnings
+#pragma warning(disable:4290)
+#endif
+
+
+namespace Imath {
+
+
+template <class T> class Matrix33
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T x[3][3];
+
+ T * operator [] (int i);
+ const T * operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Matrix33 ();
+ // 1 0 0
+ // 0 1 0
+ // 0 0 1
+
+ Matrix33 (T a);
+ // a a a
+ // a a a
+ // a a a
+
+ Matrix33 (const T a[3][3]);
+ // a[0][0] a[0][1] a[0][2]
+ // a[1][0] a[1][1] a[1][2]
+ // a[2][0] a[2][1] a[2][2]
+
+ Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i);
+
+ // a b c
+ // d e f
+ // g h i
+
+
+ //--------------------------------
+ // Copy constructor and assignment
+ //--------------------------------
+
+ Matrix33 (const Matrix33 &v);
+
+ const Matrix33 & operator = (const Matrix33 &v);
+ const Matrix33 & operator = (T a);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ T * getValue ();
+ const T * getValue () const;
+
+ template <class S>
+ void getValue (Matrix33<S> &v) const;
+ template <class S>
+ Matrix33 & setValue (const Matrix33<S> &v);
+
+ template <class S>
+ Matrix33 & setTheMatrix (const Matrix33<S> &v);
+
+
+ //---------
+ // Identity
+ //---------
+
+ void makeIdentity();
+
+
+ //---------
+ // Equality
+ //---------
+
+ bool operator == (const Matrix33 &v) const;
+ bool operator != (const Matrix33 &v) const;
+
+ //-----------------------------------------------------------------------
+ // Compare two matrices and test if they are "approximately equal":
+ //
+ // equalWithAbsError (m, e)
+ //
+ // Returns true if the coefficients of this and m are the same with
+ // an absolute error of no more than e, i.e., for all i, j
+ //
+ // abs (this[i][j] - m[i][j]) <= e
+ //
+ // equalWithRelError (m, e)
+ //
+ // Returns true if the coefficients of this and m are the same with
+ // a relative error of no more than e, i.e., for all i, j
+ //
+ // abs (this[i] - v[i][j]) <= e * abs (this[i][j])
+ //-----------------------------------------------------------------------
+
+ bool equalWithAbsError (const Matrix33<T> &v, T e) const;
+ bool equalWithRelError (const Matrix33<T> &v, T e) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Matrix33 & operator += (const Matrix33 &v);
+ const Matrix33 & operator += (T a);
+ Matrix33 operator + (const Matrix33 &v) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Matrix33 & operator -= (const Matrix33 &v);
+ const Matrix33 & operator -= (T a);
+ Matrix33 operator - (const Matrix33 &v) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Matrix33 operator - () const;
+ const Matrix33 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Matrix33 & operator *= (T a);
+ Matrix33 operator * (T a) const;
+
+
+ //-----------------------------------
+ // Matrix-times-matrix multiplication
+ //-----------------------------------
+
+ const Matrix33 & operator *= (const Matrix33 &v);
+ Matrix33 operator * (const Matrix33 &v) const;
+
+
+ //---------------------------------------------
+ // Vector-times-matrix multiplication; see also
+ // the "operator *" functions defined below.
+ //---------------------------------------------
+
+ template <class S>
+ void multVecMatrix(const Vec2<S> &src, Vec2<S> &dst) const;
+
+ template <class S>
+ void multDirMatrix(const Vec2<S> &src, Vec2<S> &dst) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Matrix33 & operator /= (T a);
+ Matrix33 operator / (T a) const;
+
+
+ //------------------
+ // Transposed matrix
+ //------------------
+
+ const Matrix33 & transpose ();
+ Matrix33 transposed () const;
+
+
+ //------------------------------------------------------------
+ // Inverse matrix: If singExc is false, inverting a singular
+ // matrix produces an identity matrix. If singExc is true,
+ // inverting a singular matrix throws a SingMatrixExc.
+ //
+ // inverse() and invert() invert matrices using determinants;
+ // gjInverse() and gjInvert() use the Gauss-Jordan method.
+ //
+ // inverse() and invert() are significantly faster than
+ // gjInverse() and gjInvert(), but the results may be slightly
+ // less accurate.
+ //
+ //------------------------------------------------------------
+
+ const Matrix33 & invert (bool singExc = false)
+ throw (Iex::MathExc);
+
+ Matrix33<T> inverse (bool singExc = false) const
+ throw (Iex::MathExc);
+
+ const Matrix33 & gjInvert (bool singExc = false)
+ throw (Iex::MathExc);
+
+ Matrix33<T> gjInverse (bool singExc = false) const
+ throw (Iex::MathExc);
+
+
+ //-----------------------------------------
+ // Set matrix to rotation by r (in radians)
+ //-----------------------------------------
+
+ template <class S>
+ const Matrix33 & setRotation (S r);
+
+
+ //-----------------------------
+ // Rotate the given matrix by r
+ //-----------------------------
+
+ template <class S>
+ const Matrix33 & rotate (S r);
+
+
+ //--------------------------------------------
+ // Set matrix to scale by given uniform factor
+ //--------------------------------------------
+
+ const Matrix33 & setScale (T s);
+
+
+ //------------------------------------
+ // Set matrix to scale by given vector
+ //------------------------------------
+
+ template <class S>
+ const Matrix33 & setScale (const Vec2<S> &s);
+
+
+ //----------------------
+ // Scale the matrix by s
+ //----------------------
+
+ template <class S>
+ const Matrix33 & scale (const Vec2<S> &s);
+
+
+ //------------------------------------------
+ // Set matrix to translation by given vector
+ //------------------------------------------
+
+ template <class S>
+ const Matrix33 & setTranslation (const Vec2<S> &t);
+
+
+ //-----------------------------
+ // Return translation component
+ //-----------------------------
+
+ Vec2<T> translation () const;
+
+
+ //--------------------------
+ // Translate the matrix by t
+ //--------------------------
+
+ template <class S>
+ const Matrix33 & translate (const Vec2<S> &t);
+
+
+ //-----------------------------------------------------------
+ // Set matrix to shear x for each y coord. by given factor xy
+ //-----------------------------------------------------------
+
+ template <class S>
+ const Matrix33 & setShear (const S &h);
+
+
+ //-------------------------------------------------------------
+ // Set matrix to shear x for each y coord. by given factor h[0]
+ // and to shear y for each x coord. by given factor h[1]
+ //-------------------------------------------------------------
+
+ template <class S>
+ const Matrix33 & setShear (const Vec2<S> &h);
+
+
+ //-----------------------------------------------------------
+ // Shear the matrix in x for each y coord. by given factor xy
+ //-----------------------------------------------------------
+
+ template <class S>
+ const Matrix33 & shear (const S &xy);
+
+
+ //-----------------------------------------------------------
+ // Shear the matrix in x for each y coord. by given factor xy
+ // and shear y for each x coord. by given factor yx
+ //-----------------------------------------------------------
+
+ template <class S>
+ const Matrix33 & shear (const Vec2<S> &h);
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+};
+
+
+template <class T> class Matrix44
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T x[4][4];
+
+ T * operator [] (int i);
+ const T * operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Matrix44 ();
+ // 1 0 0 0
+ // 0 1 0 0
+ // 0 0 1 0
+ // 0 0 0 1
+
+ Matrix44 (T a);
+ // a a a a
+ // a a a a
+ // a a a a
+ // a a a a
+
+ Matrix44 (const T a[4][4]) ;
+ // a[0][0] a[0][1] a[0][2] a[0][3]
+ // a[1][0] a[1][1] a[1][2] a[1][3]
+ // a[2][0] a[2][1] a[2][2] a[2][3]
+ // a[3][0] a[3][1] a[3][2] a[3][3]
+
+ Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h,
+ T i, T j, T k, T l, T m, T n, T o, T p);
+
+ // a b c d
+ // e f g h
+ // i j k l
+ // m n o p
+
+ Matrix44 (Matrix33<T> r, Vec3<T> t);
+ // r r r 0
+ // r r r 0
+ // r r r 0
+ // t t t 1
+
+
+ //--------------------------------
+ // Copy constructor and assignment
+ //--------------------------------
+
+ Matrix44 (const Matrix44 &v);
+
+ const Matrix44 & operator = (const Matrix44 &v);
+ const Matrix44 & operator = (T a);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ T * getValue ();
+ const T * getValue () const;
+
+ template <class S>
+ void getValue (Matrix44<S> &v) const;
+ template <class S>
+ Matrix44 & setValue (const Matrix44<S> &v);
+
+ template <class S>
+ Matrix44 & setTheMatrix (const Matrix44<S> &v);
+
+ //---------
+ // Identity
+ //---------
+
+ void makeIdentity();
+
+
+ //---------
+ // Equality
+ //---------
+
+ bool operator == (const Matrix44 &v) const;
+ bool operator != (const Matrix44 &v) const;
+
+ //-----------------------------------------------------------------------
+ // Compare two matrices and test if they are "approximately equal":
+ //
+ // equalWithAbsError (m, e)
+ //
+ // Returns true if the coefficients of this and m are the same with
+ // an absolute error of no more than e, i.e., for all i, j
+ //
+ // abs (this[i][j] - m[i][j]) <= e
+ //
+ // equalWithRelError (m, e)
+ //
+ // Returns true if the coefficients of this and m are the same with
+ // a relative error of no more than e, i.e., for all i, j
+ //
+ // abs (this[i] - v[i][j]) <= e * abs (this[i][j])
+ //-----------------------------------------------------------------------
+
+ bool equalWithAbsError (const Matrix44<T> &v, T e) const;
+ bool equalWithRelError (const Matrix44<T> &v, T e) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Matrix44 & operator += (const Matrix44 &v);
+ const Matrix44 & operator += (T a);
+ Matrix44 operator + (const Matrix44 &v) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Matrix44 & operator -= (const Matrix44 &v);
+ const Matrix44 & operator -= (T a);
+ Matrix44 operator - (const Matrix44 &v) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Matrix44 operator - () const;
+ const Matrix44 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Matrix44 & operator *= (T a);
+ Matrix44 operator * (T a) const;
+
+
+ //-----------------------------------
+ // Matrix-times-matrix multiplication
+ //-----------------------------------
+
+ const Matrix44 & operator *= (const Matrix44 &v);
+ Matrix44 operator * (const Matrix44 &v) const;
+
+ static void multiply (const Matrix44 &a, // assumes that
+ const Matrix44 &b, // &a != &c and
+ Matrix44 &c); // &b != &c.
+
+
+ //---------------------------------------------
+ // Vector-times-matrix multiplication; see also
+ // the "operator *" functions defined below.
+ //---------------------------------------------
+
+ template <class S>
+ void multVecMatrix(const Vec3<S> &src, Vec3<S> &dst) const;
+
+ template <class S>
+ void multDirMatrix(const Vec3<S> &src, Vec3<S> &dst) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Matrix44 & operator /= (T a);
+ Matrix44 operator / (T a) const;
+
+
+ //------------------
+ // Transposed matrix
+ //------------------
+
+ const Matrix44 & transpose ();
+ Matrix44 transposed () const;
+
+
+ //------------------------------------------------------------
+ // Inverse matrix: If singExc is false, inverting a singular
+ // matrix produces an identity matrix. If singExc is true,
+ // inverting a singular matrix throws a SingMatrixExc.
+ //
+ // inverse() and invert() invert matrices using determinants;
+ // gjInverse() and gjInvert() use the Gauss-Jordan method.
+ //
+ // inverse() and invert() are significantly faster than
+ // gjInverse() and gjInvert(), but the results may be slightly
+ // less accurate.
+ //
+ //------------------------------------------------------------
+
+ const Matrix44 & invert (bool singExc = false)
+ throw (Iex::MathExc);
+
+ Matrix44<T> inverse (bool singExc = false) const
+ throw (Iex::MathExc);
+
+ const Matrix44 & gjInvert (bool singExc = false)
+ throw (Iex::MathExc);
+
+ Matrix44<T> gjInverse (bool singExc = false) const
+ throw (Iex::MathExc);
+
+
+ //--------------------------------------------------------
+ // Set matrix to rotation by XYZ euler angles (in radians)
+ //--------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & setEulerAngles (const Vec3<S>& r);
+
+
+ //--------------------------------------------------------
+ // Set matrix to rotation around given axis by given angle
+ //--------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & setAxisAngle (const Vec3<S>& ax, S ang);
+
+
+ //-------------------------------------------
+ // Rotate the matrix by XYZ euler angles in r
+ //-------------------------------------------
+
+ template <class S>
+ const Matrix44 & rotate (const Vec3<S> &r);
+
+
+ //--------------------------------------------
+ // Set matrix to scale by given uniform factor
+ //--------------------------------------------
+
+ const Matrix44 & setScale (T s);
+
+
+ //------------------------------------
+ // Set matrix to scale by given vector
+ //------------------------------------
+
+ template <class S>
+ const Matrix44 & setScale (const Vec3<S> &s);
+
+
+ //----------------------
+ // Scale the matrix by s
+ //----------------------
+
+ template <class S>
+ const Matrix44 & scale (const Vec3<S> &s);
+
+
+ //------------------------------------------
+ // Set matrix to translation by given vector
+ //------------------------------------------
+
+ template <class S>
+ const Matrix44 & setTranslation (const Vec3<S> &t);
+
+
+ //-----------------------------
+ // Return translation component
+ //-----------------------------
+
+ const Vec3<T> translation () const;
+
+
+ //--------------------------
+ // Translate the matrix by t
+ //--------------------------
+
+ template <class S>
+ const Matrix44 & translate (const Vec3<S> &t);
+
+
+ //-------------------------------------------------------------
+ // Set matrix to shear by given vector h. The resulting matrix
+ // will shear x for each y coord. by a factor of h[0] ;
+ // will shear x for each z coord. by a factor of h[1] ;
+ // will shear y for each z coord. by a factor of h[2] .
+ //-------------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & setShear (const Vec3<S> &h);
+
+
+ //------------------------------------------------------------
+ // Set matrix to shear by given factors. The resulting matrix
+ // will shear x for each y coord. by a factor of h.xy ;
+ // will shear x for each z coord. by a factor of h.xz ;
+ // will shear y for each z coord. by a factor of h.yz ;
+ // will shear y for each x coord. by a factor of h.yx ;
+ // will shear z for each x coord. by a factor of h.zx ;
+ // will shear z for each y coord. by a factor of h.zy .
+ //------------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & setShear (const Shear6<S> &h);
+
+
+ //--------------------------------------------------------
+ // Shear the matrix by given vector. The composed matrix
+ // will be <shear> * <this>, where the shear matrix ...
+ // will shear x for each y coord. by a factor of h[0] ;
+ // will shear x for each z coord. by a factor of h[1] ;
+ // will shear y for each z coord. by a factor of h[2] .
+ //--------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & shear (const Vec3<S> &h);
+
+
+ //------------------------------------------------------------
+ // Shear the matrix by the given factors. The composed matrix
+ // will be <shear> * <this>, where the shear matrix ...
+ // will shear x for each y coord. by a factor of h.xy ;
+ // will shear x for each z coord. by a factor of h.xz ;
+ // will shear y for each z coord. by a factor of h.yz ;
+ // will shear y for each x coord. by a factor of h.yx ;
+ // will shear z for each x coord. by a factor of h.zx ;
+ // will shear z for each y coord. by a factor of h.zy .
+ //------------------------------------------------------------
+
+ template <class S>
+ const Matrix44 & shear (const Shear6<S> &h);
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+};
+
+
+//--------------
+// Stream output
+//--------------
+
+template <class T>
+std::ostream & operator << (std::ostream & s, const Matrix33<T> &m);
+
+template <class T>
+std::ostream & operator << (std::ostream & s, const Matrix44<T> &m);
+
+
+//---------------------------------------------
+// Vector-times-matrix multiplication operators
+//---------------------------------------------
+
+template <class S, class T>
+const Vec2<S> & operator *= (Vec2<S> &v, const Matrix33<T> &m);
+
+template <class S, class T>
+Vec2<S> operator * (const Vec2<S> &v, const Matrix33<T> &m);
+
+template <class S, class T>
+const Vec3<S> & operator *= (Vec3<S> &v, const Matrix33<T> &m);
+
+template <class S, class T>
+Vec3<S> operator * (const Vec3<S> &v, const Matrix33<T> &m);
+
+template <class S, class T>
+const Vec3<S> & operator *= (Vec3<S> &v, const Matrix44<T> &m);
+
+template <class S, class T>
+Vec3<S> operator * (const Vec3<S> &v, const Matrix44<T> &m);
+
+
+//-------------------------
+// Typedefs for convenience
+//-------------------------
+
+typedef Matrix33 <float> M33f;
+typedef Matrix33 <double> M33d;
+typedef Matrix44 <float> M44f;
+typedef Matrix44 <double> M44d;
+
+
+//---------------------------
+// Implementation of Matrix33
+//---------------------------
+
+template <class T>
+inline T *
+Matrix33<T>::operator [] (int i)
+{
+ return x[i];
+}
+
+template <class T>
+inline const T *
+Matrix33<T>::operator [] (int i) const
+{
+ return x[i];
+}
+
+template <class T>
+inline
+Matrix33<T>::Matrix33 ()
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+}
+
+template <class T>
+inline
+Matrix33<T>::Matrix33 (T a)
+{
+ x[0][0] = a;
+ x[0][1] = a;
+ x[0][2] = a;
+ x[1][0] = a;
+ x[1][1] = a;
+ x[1][2] = a;
+ x[2][0] = a;
+ x[2][1] = a;
+ x[2][2] = a;
+}
+
+template <class T>
+inline
+Matrix33<T>::Matrix33 (const T a[3][3])
+{
+ x[0][0] = a[0][0];
+ x[0][1] = a[0][1];
+ x[0][2] = a[0][2];
+ x[1][0] = a[1][0];
+ x[1][1] = a[1][1];
+ x[1][2] = a[1][2];
+ x[2][0] = a[2][0];
+ x[2][1] = a[2][1];
+ x[2][2] = a[2][2];
+}
+
+template <class T>
+inline
+Matrix33<T>::Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i)
+{
+ x[0][0] = a;
+ x[0][1] = b;
+ x[0][2] = c;
+ x[1][0] = d;
+ x[1][1] = e;
+ x[1][2] = f;
+ x[2][0] = g;
+ x[2][1] = h;
+ x[2][2] = i;
+}
+
+template <class T>
+inline
+Matrix33<T>::Matrix33 (const Matrix33 &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+}
+
+template <class T>
+inline const Matrix33<T> &
+Matrix33<T>::operator = (const Matrix33 &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ return *this;
+}
+
+template <class T>
+inline const Matrix33<T> &
+Matrix33<T>::operator = (T a)
+{
+ x[0][0] = a;
+ x[0][1] = a;
+ x[0][2] = a;
+ x[1][0] = a;
+ x[1][1] = a;
+ x[1][2] = a;
+ x[2][0] = a;
+ x[2][1] = a;
+ x[2][2] = a;
+ return *this;
+}
+
+template <class T>
+inline T *
+Matrix33<T>::getValue ()
+{
+ return (T *) &x[0][0];
+}
+
+template <class T>
+inline const T *
+Matrix33<T>::getValue () const
+{
+ return (const T *) &x[0][0];
+}
+
+template <class T>
+template <class S>
+inline void
+Matrix33<T>::getValue (Matrix33<S> &v) const
+{
+ v.x[0][0] = x[0][0];
+ v.x[0][1] = x[0][1];
+ v.x[0][2] = x[0][2];
+ v.x[1][0] = x[1][0];
+ v.x[1][1] = x[1][1];
+ v.x[1][2] = x[1][2];
+ v.x[2][0] = x[2][0];
+ v.x[2][1] = x[2][1];
+ v.x[2][2] = x[2][2];
+}
+
+template <class T>
+template <class S>
+inline Matrix33<T> &
+Matrix33<T>::setValue (const Matrix33<S> &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline Matrix33<T> &
+Matrix33<T>::setTheMatrix (const Matrix33<S> &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ return *this;
+}
+
+template <class T>
+inline void
+Matrix33<T>::makeIdentity()
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+}
+
+template <class T>
+bool
+Matrix33<T>::operator == (const Matrix33 &v) const
+{
+ return x[0][0] == v.x[0][0] &&
+ x[0][1] == v.x[0][1] &&
+ x[0][2] == v.x[0][2] &&
+ x[1][0] == v.x[1][0] &&
+ x[1][1] == v.x[1][1] &&
+ x[1][2] == v.x[1][2] &&
+ x[2][0] == v.x[2][0] &&
+ x[2][1] == v.x[2][1] &&
+ x[2][2] == v.x[2][2];
+}
+
+template <class T>
+bool
+Matrix33<T>::operator != (const Matrix33 &v) const
+{
+ return x[0][0] != v.x[0][0] ||
+ x[0][1] != v.x[0][1] ||
+ x[0][2] != v.x[0][2] ||
+ x[1][0] != v.x[1][0] ||
+ x[1][1] != v.x[1][1] ||
+ x[1][2] != v.x[1][2] ||
+ x[2][0] != v.x[2][0] ||
+ x[2][1] != v.x[2][1] ||
+ x[2][2] != v.x[2][2];
+}
+
+template <class T>
+bool
+Matrix33<T>::equalWithAbsError (const Matrix33<T> &m, T e) const
+{
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ if (!Imath::equalWithAbsError ((*this)[i][j], m[i][j], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+Matrix33<T>::equalWithRelError (const Matrix33<T> &m, T e) const
+{
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ if (!Imath::equalWithRelError ((*this)[i][j], m[i][j], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator += (const Matrix33<T> &v)
+{
+ x[0][0] += v.x[0][0];
+ x[0][1] += v.x[0][1];
+ x[0][2] += v.x[0][2];
+ x[1][0] += v.x[1][0];
+ x[1][1] += v.x[1][1];
+ x[1][2] += v.x[1][2];
+ x[2][0] += v.x[2][0];
+ x[2][1] += v.x[2][1];
+ x[2][2] += v.x[2][2];
+
+ return *this;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator += (T a)
+{
+ x[0][0] += a;
+ x[0][1] += a;
+ x[0][2] += a;
+ x[1][0] += a;
+ x[1][1] += a;
+ x[1][2] += a;
+ x[2][0] += a;
+ x[2][1] += a;
+ x[2][2] += a;
+
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator + (const Matrix33<T> &v) const
+{
+ return Matrix33 (x[0][0] + v.x[0][0],
+ x[0][1] + v.x[0][1],
+ x[0][2] + v.x[0][2],
+ x[1][0] + v.x[1][0],
+ x[1][1] + v.x[1][1],
+ x[1][2] + v.x[1][2],
+ x[2][0] + v.x[2][0],
+ x[2][1] + v.x[2][1],
+ x[2][2] + v.x[2][2]);
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator -= (const Matrix33<T> &v)
+{
+ x[0][0] -= v.x[0][0];
+ x[0][1] -= v.x[0][1];
+ x[0][2] -= v.x[0][2];
+ x[1][0] -= v.x[1][0];
+ x[1][1] -= v.x[1][1];
+ x[1][2] -= v.x[1][2];
+ x[2][0] -= v.x[2][0];
+ x[2][1] -= v.x[2][1];
+ x[2][2] -= v.x[2][2];
+
+ return *this;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator -= (T a)
+{
+ x[0][0] -= a;
+ x[0][1] -= a;
+ x[0][2] -= a;
+ x[1][0] -= a;
+ x[1][1] -= a;
+ x[1][2] -= a;
+ x[2][0] -= a;
+ x[2][1] -= a;
+ x[2][2] -= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator - (const Matrix33<T> &v) const
+{
+ return Matrix33 (x[0][0] - v.x[0][0],
+ x[0][1] - v.x[0][1],
+ x[0][2] - v.x[0][2],
+ x[1][0] - v.x[1][0],
+ x[1][1] - v.x[1][1],
+ x[1][2] - v.x[1][2],
+ x[2][0] - v.x[2][0],
+ x[2][1] - v.x[2][1],
+ x[2][2] - v.x[2][2]);
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator - () const
+{
+ return Matrix33 (-x[0][0],
+ -x[0][1],
+ -x[0][2],
+ -x[1][0],
+ -x[1][1],
+ -x[1][2],
+ -x[2][0],
+ -x[2][1],
+ -x[2][2]);
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::negate ()
+{
+ x[0][0] = -x[0][0];
+ x[0][1] = -x[0][1];
+ x[0][2] = -x[0][2];
+ x[1][0] = -x[1][0];
+ x[1][1] = -x[1][1];
+ x[1][2] = -x[1][2];
+ x[2][0] = -x[2][0];
+ x[2][1] = -x[2][1];
+ x[2][2] = -x[2][2];
+
+ return *this;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator *= (T a)
+{
+ x[0][0] *= a;
+ x[0][1] *= a;
+ x[0][2] *= a;
+ x[1][0] *= a;
+ x[1][1] *= a;
+ x[1][2] *= a;
+ x[2][0] *= a;
+ x[2][1] *= a;
+ x[2][2] *= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator * (T a) const
+{
+ return Matrix33 (x[0][0] * a,
+ x[0][1] * a,
+ x[0][2] * a,
+ x[1][0] * a,
+ x[1][1] * a,
+ x[1][2] * a,
+ x[2][0] * a,
+ x[2][1] * a,
+ x[2][2] * a);
+}
+
+template <class T>
+inline Matrix33<T>
+operator * (T a, const Matrix33<T> &v)
+{
+ return v * a;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator *= (const Matrix33<T> &v)
+{
+ Matrix33 tmp (T (0));
+
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ tmp.x[i][j] += x[i][k] * v.x[k][j];
+
+ *this = tmp;
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator * (const Matrix33<T> &v) const
+{
+ Matrix33 tmp (T (0));
+
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ for (int k = 0; k < 3; k++)
+ tmp.x[i][j] += x[i][k] * v.x[k][j];
+
+ return tmp;
+}
+
+template <class T>
+template <class S>
+void
+Matrix33<T>::multVecMatrix(const Vec2<S> &src, Vec2<S> &dst) const
+{
+ S a, b, w;
+
+ a = src[0] * x[0][0] + src[1] * x[1][0] + x[2][0];
+ b = src[0] * x[0][1] + src[1] * x[1][1] + x[2][1];
+ w = src[0] * x[0][2] + src[1] * x[1][2] + x[2][2];
+
+ dst.x = a / w;
+ dst.y = b / w;
+}
+
+template <class T>
+template <class S>
+void
+Matrix33<T>::multDirMatrix(const Vec2<S> &src, Vec2<S> &dst) const
+{
+ S a, b;
+
+ a = src[0] * x[0][0] + src[1] * x[1][0];
+ b = src[0] * x[0][1] + src[1] * x[1][1];
+
+ dst.x = a;
+ dst.y = b;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::operator /= (T a)
+{
+ x[0][0] /= a;
+ x[0][1] /= a;
+ x[0][2] /= a;
+ x[1][0] /= a;
+ x[1][1] /= a;
+ x[1][2] /= a;
+ x[2][0] /= a;
+ x[2][1] /= a;
+ x[2][2] /= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::operator / (T a) const
+{
+ return Matrix33 (x[0][0] / a,
+ x[0][1] / a,
+ x[0][2] / a,
+ x[1][0] / a,
+ x[1][1] / a,
+ x[1][2] / a,
+ x[2][0] / a,
+ x[2][1] / a,
+ x[2][2] / a);
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::transpose ()
+{
+ Matrix33 tmp (x[0][0],
+ x[1][0],
+ x[2][0],
+ x[0][1],
+ x[1][1],
+ x[2][1],
+ x[0][2],
+ x[1][2],
+ x[2][2]);
+ *this = tmp;
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::transposed () const
+{
+ return Matrix33 (x[0][0],
+ x[1][0],
+ x[2][0],
+ x[0][1],
+ x[1][1],
+ x[2][1],
+ x[0][2],
+ x[1][2],
+ x[2][2]);
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::gjInvert (bool singExc) throw (Iex::MathExc)
+{
+ *this = gjInverse (singExc);
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::gjInverse (bool singExc) const throw (Iex::MathExc)
+{
+ int i, j, k;
+ Matrix33 s;
+ Matrix33 t (*this);
+
+ // Forward elimination
+
+ for (i = 0; i < 2 ; i++)
+ {
+ int pivot = i;
+
+ T pivotsize = t[i][i];
+
+ if (pivotsize < 0)
+ pivotsize = -pivotsize;
+
+ for (j = i + 1; j < 3; j++)
+ {
+ T tmp = t[j][i];
+
+ if (tmp < 0)
+ tmp = -tmp;
+
+ if (tmp > pivotsize)
+ {
+ pivot = j;
+ pivotsize = tmp;
+ }
+ }
+
+ if (pivotsize == 0)
+ {
+ if (singExc)
+ throw ::Imath::SingMatrixExc ("Cannot invert singular matrix.");
+
+ return Matrix33();
+ }
+
+ if (pivot != i)
+ {
+ for (j = 0; j < 3; j++)
+ {
+ T tmp;
+
+ tmp = t[i][j];
+ t[i][j] = t[pivot][j];
+ t[pivot][j] = tmp;
+
+ tmp = s[i][j];
+ s[i][j] = s[pivot][j];
+ s[pivot][j] = tmp;
+ }
+ }
+
+ for (j = i + 1; j < 3; j++)
+ {
+ T f = t[j][i] / t[i][i];
+
+ for (k = 0; k < 3; k++)
+ {
+ t[j][k] -= f * t[i][k];
+ s[j][k] -= f * s[i][k];
+ }
+ }
+ }
+
+ // Backward substitution
+
+ for (i = 2; i >= 0; --i)
+ {
+ T f;
+
+ if ((f = t[i][i]) == 0)
+ {
+ if (singExc)
+ throw ::Imath::SingMatrixExc ("Cannot invert singular matrix.");
+
+ return Matrix33();
+ }
+
+ for (j = 0; j < 3; j++)
+ {
+ t[i][j] /= f;
+ s[i][j] /= f;
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ f = t[j][i];
+
+ for (k = 0; k < 3; k++)
+ {
+ t[j][k] -= f * t[i][k];
+ s[j][k] -= f * s[i][k];
+ }
+ }
+ }
+
+ return s;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::invert (bool singExc) throw (Iex::MathExc)
+{
+ *this = inverse (singExc);
+ return *this;
+}
+
+template <class T>
+Matrix33<T>
+Matrix33<T>::inverse (bool singExc) const throw (Iex::MathExc)
+{
+ if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1)
+ {
+ Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2],
+ x[2][1] * x[0][2] - x[0][1] * x[2][2],
+ x[0][1] * x[1][2] - x[1][1] * x[0][2],
+
+ x[2][0] * x[1][2] - x[1][0] * x[2][2],
+ x[0][0] * x[2][2] - x[2][0] * x[0][2],
+ x[1][0] * x[0][2] - x[0][0] * x[1][2],
+
+ x[1][0] * x[2][1] - x[2][0] * x[1][1],
+ x[2][0] * x[0][1] - x[0][0] * x[2][1],
+ x[0][0] * x[1][1] - x[1][0] * x[0][1]);
+
+ T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0];
+
+ if (Imath::abs (r) >= 1)
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ s[i][j] /= r;
+ }
+ }
+ }
+ else
+ {
+ T mr = Imath::abs (r) / limits<T>::smallest();
+
+ for (int i = 0; i < 3; ++i)
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ if (mr > Imath::abs (s[i][j]))
+ {
+ s[i][j] /= r;
+ }
+ else
+ {
+ if (singExc)
+ throw SingMatrixExc ("Cannot invert "
+ "singular matrix.");
+ return Matrix33();
+ }
+ }
+ }
+ }
+
+ return s;
+ }
+ else
+ {
+ Matrix33 s ( x[1][1],
+ -x[0][1],
+ 0,
+
+ -x[1][0],
+ x[0][0],
+ 0,
+
+ 0,
+ 0,
+ 1);
+
+ T r = x[0][0] * x[1][1] - x[1][0] * x[0][1];
+
+ if (Imath::abs (r) >= 1)
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ for (int j = 0; j < 2; ++j)
+ {
+ s[i][j] /= r;
+ }
+ }
+ }
+ else
+ {
+ T mr = Imath::abs (r) / limits<T>::smallest();
+
+ for (int i = 0; i < 2; ++i)
+ {
+ for (int j = 0; j < 2; ++j)
+ {
+ if (mr > Imath::abs (s[i][j]))
+ {
+ s[i][j] /= r;
+ }
+ else
+ {
+ if (singExc)
+ throw SingMatrixExc ("Cannot invert "
+ "singular matrix.");
+ return Matrix33();
+ }
+ }
+ }
+ }
+
+ s[2][0] = -x[2][0] * s[0][0] - x[2][1] * s[1][0];
+ s[2][1] = -x[2][0] * s[0][1] - x[2][1] * s[1][1];
+
+ return s;
+ }
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::setRotation (S r)
+{
+ S cos_r, sin_r;
+
+ cos_r = Math<T>::cos (r);
+ sin_r = Math<T>::sin (r);
+
+ x[0][0] = cos_r;
+ x[0][1] = sin_r;
+ x[0][2] = 0;
+
+ x[1][0] = -sin_r;
+ x[1][1] = cos_r;
+ x[1][2] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::rotate (S r)
+{
+ *this *= Matrix33<T>().setRotation (r);
+ return *this;
+}
+
+template <class T>
+const Matrix33<T> &
+Matrix33<T>::setScale (T s)
+{
+ x[0][0] = s;
+ x[0][1] = 0;
+ x[0][2] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = s;
+ x[1][2] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::setScale (const Vec2<S> &s)
+{
+ x[0][0] = s[0];
+ x[0][1] = 0;
+ x[0][2] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = s[1];
+ x[1][2] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::scale (const Vec2<S> &s)
+{
+ x[0][0] *= s[0];
+ x[0][1] *= s[0];
+ x[0][2] *= s[0];
+
+ x[1][0] *= s[1];
+ x[1][1] *= s[1];
+ x[1][2] *= s[1];
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::setTranslation (const Vec2<S> &t)
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+
+ x[2][0] = t[0];
+ x[2][1] = t[1];
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+inline Vec2<T>
+Matrix33<T>::translation () const
+{
+ return Vec2<T> (x[2][0], x[2][1]);
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::translate (const Vec2<S> &t)
+{
+ x[2][0] += t[0] * x[0][0] + t[1] * x[1][0];
+ x[2][1] += t[0] * x[0][1] + t[1] * x[1][1];
+ x[2][2] += t[0] * x[0][2] + t[1] * x[1][2];
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::setShear (const S &xy)
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+
+ x[1][0] = xy;
+ x[1][1] = 1;
+ x[1][2] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::setShear (const Vec2<S> &h)
+{
+ x[0][0] = 1;
+ x[0][1] = h[1];
+ x[0][2] = 0;
+
+ x[1][0] = h[0];
+ x[1][1] = 1;
+ x[1][2] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::shear (const S &xy)
+{
+ //
+ // In this case, we don't need a temp. copy of the matrix
+ // because we never use a value on the RHS after we've
+ // changed it on the LHS.
+ //
+
+ x[1][0] += xy * x[0][0];
+ x[1][1] += xy * x[0][1];
+ x[1][2] += xy * x[0][2];
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix33<T> &
+Matrix33<T>::shear (const Vec2<S> &h)
+{
+ Matrix33<T> P (*this);
+
+ x[0][0] = P[0][0] + h[1] * P[1][0];
+ x[0][1] = P[0][1] + h[1] * P[1][1];
+ x[0][2] = P[0][2] + h[1] * P[1][2];
+
+ x[1][0] = P[1][0] + h[0] * P[0][0];
+ x[1][1] = P[1][1] + h[0] * P[0][1];
+ x[1][2] = P[1][2] + h[0] * P[0][2];
+
+ return *this;
+}
+
+
+//---------------------------
+// Implementation of Matrix44
+//---------------------------
+
+template <class T>
+inline T *
+Matrix44<T>::operator [] (int i)
+{
+ return x[i];
+}
+
+template <class T>
+inline const T *
+Matrix44<T>::operator [] (int i) const
+{
+ return x[i];
+}
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 ()
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[1][3] = 0;
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+ x[2][3] = 0;
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+}
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 (T a)
+{
+ x[0][0] = a;
+ x[0][1] = a;
+ x[0][2] = a;
+ x[0][3] = a;
+ x[1][0] = a;
+ x[1][1] = a;
+ x[1][2] = a;
+ x[1][3] = a;
+ x[2][0] = a;
+ x[2][1] = a;
+ x[2][2] = a;
+ x[2][3] = a;
+ x[3][0] = a;
+ x[3][1] = a;
+ x[3][2] = a;
+ x[3][3] = a;
+}
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 (const T a[4][4])
+{
+ x[0][0] = a[0][0];
+ x[0][1] = a[0][1];
+ x[0][2] = a[0][2];
+ x[0][3] = a[0][3];
+ x[1][0] = a[1][0];
+ x[1][1] = a[1][1];
+ x[1][2] = a[1][2];
+ x[1][3] = a[1][3];
+ x[2][0] = a[2][0];
+ x[2][1] = a[2][1];
+ x[2][2] = a[2][2];
+ x[2][3] = a[2][3];
+ x[3][0] = a[3][0];
+ x[3][1] = a[3][1];
+ x[3][2] = a[3][2];
+ x[3][3] = a[3][3];
+}
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h,
+ T i, T j, T k, T l, T m, T n, T o, T p)
+{
+ x[0][0] = a;
+ x[0][1] = b;
+ x[0][2] = c;
+ x[0][3] = d;
+ x[1][0] = e;
+ x[1][1] = f;
+ x[1][2] = g;
+ x[1][3] = h;
+ x[2][0] = i;
+ x[2][1] = j;
+ x[2][2] = k;
+ x[2][3] = l;
+ x[3][0] = m;
+ x[3][1] = n;
+ x[3][2] = o;
+ x[3][3] = p;
+}
+
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 (Matrix33<T> r, Vec3<T> t)
+{
+ x[0][0] = r[0][0];
+ x[0][1] = r[0][1];
+ x[0][2] = r[0][2];
+ x[0][3] = 0;
+ x[1][0] = r[1][0];
+ x[1][1] = r[1][1];
+ x[1][2] = r[1][2];
+ x[1][3] = 0;
+ x[2][0] = r[2][0];
+ x[2][1] = r[2][1];
+ x[2][2] = r[2][2];
+ x[2][3] = 0;
+ x[3][0] = t[0];
+ x[3][1] = t[1];
+ x[3][2] = t[2];
+ x[3][3] = 1;
+}
+
+template <class T>
+inline
+Matrix44<T>::Matrix44 (const Matrix44 &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[0][3] = v.x[0][3];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[1][3] = v.x[1][3];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ x[2][3] = v.x[2][3];
+ x[3][0] = v.x[3][0];
+ x[3][1] = v.x[3][1];
+ x[3][2] = v.x[3][2];
+ x[3][3] = v.x[3][3];
+}
+
+template <class T>
+inline const Matrix44<T> &
+Matrix44<T>::operator = (const Matrix44 &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[0][3] = v.x[0][3];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[1][3] = v.x[1][3];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ x[2][3] = v.x[2][3];
+ x[3][0] = v.x[3][0];
+ x[3][1] = v.x[3][1];
+ x[3][2] = v.x[3][2];
+ x[3][3] = v.x[3][3];
+ return *this;
+}
+
+template <class T>
+inline const Matrix44<T> &
+Matrix44<T>::operator = (T a)
+{
+ x[0][0] = a;
+ x[0][1] = a;
+ x[0][2] = a;
+ x[0][3] = a;
+ x[1][0] = a;
+ x[1][1] = a;
+ x[1][2] = a;
+ x[1][3] = a;
+ x[2][0] = a;
+ x[2][1] = a;
+ x[2][2] = a;
+ x[2][3] = a;
+ x[3][0] = a;
+ x[3][1] = a;
+ x[3][2] = a;
+ x[3][3] = a;
+ return *this;
+}
+
+template <class T>
+inline T *
+Matrix44<T>::getValue ()
+{
+ return (T *) &x[0][0];
+}
+
+template <class T>
+inline const T *
+Matrix44<T>::getValue () const
+{
+ return (const T *) &x[0][0];
+}
+
+template <class T>
+template <class S>
+inline void
+Matrix44<T>::getValue (Matrix44<S> &v) const
+{
+ v.x[0][0] = x[0][0];
+ v.x[0][1] = x[0][1];
+ v.x[0][2] = x[0][2];
+ v.x[0][3] = x[0][3];
+ v.x[1][0] = x[1][0];
+ v.x[1][1] = x[1][1];
+ v.x[1][2] = x[1][2];
+ v.x[1][3] = x[1][3];
+ v.x[2][0] = x[2][0];
+ v.x[2][1] = x[2][1];
+ v.x[2][2] = x[2][2];
+ v.x[2][3] = x[2][3];
+ v.x[3][0] = x[3][0];
+ v.x[3][1] = x[3][1];
+ v.x[3][2] = x[3][2];
+ v.x[3][3] = x[3][3];
+}
+
+template <class T>
+template <class S>
+inline Matrix44<T> &
+Matrix44<T>::setValue (const Matrix44<S> &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[0][3] = v.x[0][3];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[1][3] = v.x[1][3];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ x[2][3] = v.x[2][3];
+ x[3][0] = v.x[3][0];
+ x[3][1] = v.x[3][1];
+ x[3][2] = v.x[3][2];
+ x[3][3] = v.x[3][3];
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline Matrix44<T> &
+Matrix44<T>::setTheMatrix (const Matrix44<S> &v)
+{
+ x[0][0] = v.x[0][0];
+ x[0][1] = v.x[0][1];
+ x[0][2] = v.x[0][2];
+ x[0][3] = v.x[0][3];
+ x[1][0] = v.x[1][0];
+ x[1][1] = v.x[1][1];
+ x[1][2] = v.x[1][2];
+ x[1][3] = v.x[1][3];
+ x[2][0] = v.x[2][0];
+ x[2][1] = v.x[2][1];
+ x[2][2] = v.x[2][2];
+ x[2][3] = v.x[2][3];
+ x[3][0] = v.x[3][0];
+ x[3][1] = v.x[3][1];
+ x[3][2] = v.x[3][2];
+ x[3][3] = v.x[3][3];
+ return *this;
+}
+
+template <class T>
+inline void
+Matrix44<T>::makeIdentity()
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[1][3] = 0;
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+ x[2][3] = 0;
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+}
+
+template <class T>
+bool
+Matrix44<T>::operator == (const Matrix44 &v) const
+{
+ return x[0][0] == v.x[0][0] &&
+ x[0][1] == v.x[0][1] &&
+ x[0][2] == v.x[0][2] &&
+ x[0][3] == v.x[0][3] &&
+ x[1][0] == v.x[1][0] &&
+ x[1][1] == v.x[1][1] &&
+ x[1][2] == v.x[1][2] &&
+ x[1][3] == v.x[1][3] &&
+ x[2][0] == v.x[2][0] &&
+ x[2][1] == v.x[2][1] &&
+ x[2][2] == v.x[2][2] &&
+ x[2][3] == v.x[2][3] &&
+ x[3][0] == v.x[3][0] &&
+ x[3][1] == v.x[3][1] &&
+ x[3][2] == v.x[3][2] &&
+ x[3][3] == v.x[3][3];
+}
+
+template <class T>
+bool
+Matrix44<T>::operator != (const Matrix44 &v) const
+{
+ return x[0][0] != v.x[0][0] ||
+ x[0][1] != v.x[0][1] ||
+ x[0][2] != v.x[0][2] ||
+ x[0][3] != v.x[0][3] ||
+ x[1][0] != v.x[1][0] ||
+ x[1][1] != v.x[1][1] ||
+ x[1][2] != v.x[1][2] ||
+ x[1][3] != v.x[1][3] ||
+ x[2][0] != v.x[2][0] ||
+ x[2][1] != v.x[2][1] ||
+ x[2][2] != v.x[2][2] ||
+ x[2][3] != v.x[2][3] ||
+ x[3][0] != v.x[3][0] ||
+ x[3][1] != v.x[3][1] ||
+ x[3][2] != v.x[3][2] ||
+ x[3][3] != v.x[3][3];
+}
+
+template <class T>
+bool
+Matrix44<T>::equalWithAbsError (const Matrix44<T> &m, T e) const
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ if (!Imath::equalWithAbsError ((*this)[i][j], m[i][j], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+Matrix44<T>::equalWithRelError (const Matrix44<T> &m, T e) const
+{
+ for (int i = 0; i < 4; i++)
+ for (int j = 0; j < 4; j++)
+ if (!Imath::equalWithRelError ((*this)[i][j], m[i][j], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator += (const Matrix44<T> &v)
+{
+ x[0][0] += v.x[0][0];
+ x[0][1] += v.x[0][1];
+ x[0][2] += v.x[0][2];
+ x[0][3] += v.x[0][3];
+ x[1][0] += v.x[1][0];
+ x[1][1] += v.x[1][1];
+ x[1][2] += v.x[1][2];
+ x[1][3] += v.x[1][3];
+ x[2][0] += v.x[2][0];
+ x[2][1] += v.x[2][1];
+ x[2][2] += v.x[2][2];
+ x[2][3] += v.x[2][3];
+ x[3][0] += v.x[3][0];
+ x[3][1] += v.x[3][1];
+ x[3][2] += v.x[3][2];
+ x[3][3] += v.x[3][3];
+
+ return *this;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator += (T a)
+{
+ x[0][0] += a;
+ x[0][1] += a;
+ x[0][2] += a;
+ x[0][3] += a;
+ x[1][0] += a;
+ x[1][1] += a;
+ x[1][2] += a;
+ x[1][3] += a;
+ x[2][0] += a;
+ x[2][1] += a;
+ x[2][2] += a;
+ x[2][3] += a;
+ x[3][0] += a;
+ x[3][1] += a;
+ x[3][2] += a;
+ x[3][3] += a;
+
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::operator + (const Matrix44<T> &v) const
+{
+ return Matrix44 (x[0][0] + v.x[0][0],
+ x[0][1] + v.x[0][1],
+ x[0][2] + v.x[0][2],
+ x[0][3] + v.x[0][3],
+ x[1][0] + v.x[1][0],
+ x[1][1] + v.x[1][1],
+ x[1][2] + v.x[1][2],
+ x[1][3] + v.x[1][3],
+ x[2][0] + v.x[2][0],
+ x[2][1] + v.x[2][1],
+ x[2][2] + v.x[2][2],
+ x[2][3] + v.x[2][3],
+ x[3][0] + v.x[3][0],
+ x[3][1] + v.x[3][1],
+ x[3][2] + v.x[3][2],
+ x[3][3] + v.x[3][3]);
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator -= (const Matrix44<T> &v)
+{
+ x[0][0] -= v.x[0][0];
+ x[0][1] -= v.x[0][1];
+ x[0][2] -= v.x[0][2];
+ x[0][3] -= v.x[0][3];
+ x[1][0] -= v.x[1][0];
+ x[1][1] -= v.x[1][1];
+ x[1][2] -= v.x[1][2];
+ x[1][3] -= v.x[1][3];
+ x[2][0] -= v.x[2][0];
+ x[2][1] -= v.x[2][1];
+ x[2][2] -= v.x[2][2];
+ x[2][3] -= v.x[2][3];
+ x[3][0] -= v.x[3][0];
+ x[3][1] -= v.x[3][1];
+ x[3][2] -= v.x[3][2];
+ x[3][3] -= v.x[3][3];
+
+ return *this;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator -= (T a)
+{
+ x[0][0] -= a;
+ x[0][1] -= a;
+ x[0][2] -= a;
+ x[0][3] -= a;
+ x[1][0] -= a;
+ x[1][1] -= a;
+ x[1][2] -= a;
+ x[1][3] -= a;
+ x[2][0] -= a;
+ x[2][1] -= a;
+ x[2][2] -= a;
+ x[2][3] -= a;
+ x[3][0] -= a;
+ x[3][1] -= a;
+ x[3][2] -= a;
+ x[3][3] -= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::operator - (const Matrix44<T> &v) const
+{
+ return Matrix44 (x[0][0] - v.x[0][0],
+ x[0][1] - v.x[0][1],
+ x[0][2] - v.x[0][2],
+ x[0][3] - v.x[0][3],
+ x[1][0] - v.x[1][0],
+ x[1][1] - v.x[1][1],
+ x[1][2] - v.x[1][2],
+ x[1][3] - v.x[1][3],
+ x[2][0] - v.x[2][0],
+ x[2][1] - v.x[2][1],
+ x[2][2] - v.x[2][2],
+ x[2][3] - v.x[2][3],
+ x[3][0] - v.x[3][0],
+ x[3][1] - v.x[3][1],
+ x[3][2] - v.x[3][2],
+ x[3][3] - v.x[3][3]);
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::operator - () const
+{
+ return Matrix44 (-x[0][0],
+ -x[0][1],
+ -x[0][2],
+ -x[0][3],
+ -x[1][0],
+ -x[1][1],
+ -x[1][2],
+ -x[1][3],
+ -x[2][0],
+ -x[2][1],
+ -x[2][2],
+ -x[2][3],
+ -x[3][0],
+ -x[3][1],
+ -x[3][2],
+ -x[3][3]);
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::negate ()
+{
+ x[0][0] = -x[0][0];
+ x[0][1] = -x[0][1];
+ x[0][2] = -x[0][2];
+ x[0][3] = -x[0][3];
+ x[1][0] = -x[1][0];
+ x[1][1] = -x[1][1];
+ x[1][2] = -x[1][2];
+ x[1][3] = -x[1][3];
+ x[2][0] = -x[2][0];
+ x[2][1] = -x[2][1];
+ x[2][2] = -x[2][2];
+ x[2][3] = -x[2][3];
+ x[3][0] = -x[3][0];
+ x[3][1] = -x[3][1];
+ x[3][2] = -x[3][2];
+ x[3][3] = -x[3][3];
+
+ return *this;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator *= (T a)
+{
+ x[0][0] *= a;
+ x[0][1] *= a;
+ x[0][2] *= a;
+ x[0][3] *= a;
+ x[1][0] *= a;
+ x[1][1] *= a;
+ x[1][2] *= a;
+ x[1][3] *= a;
+ x[2][0] *= a;
+ x[2][1] *= a;
+ x[2][2] *= a;
+ x[2][3] *= a;
+ x[3][0] *= a;
+ x[3][1] *= a;
+ x[3][2] *= a;
+ x[3][3] *= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::operator * (T a) const
+{
+ return Matrix44 (x[0][0] * a,
+ x[0][1] * a,
+ x[0][2] * a,
+ x[0][3] * a,
+ x[1][0] * a,
+ x[1][1] * a,
+ x[1][2] * a,
+ x[1][3] * a,
+ x[2][0] * a,
+ x[2][1] * a,
+ x[2][2] * a,
+ x[2][3] * a,
+ x[3][0] * a,
+ x[3][1] * a,
+ x[3][2] * a,
+ x[3][3] * a);
+}
+
+template <class T>
+inline Matrix44<T>
+operator * (T a, const Matrix44<T> &v)
+{
+ return v * a;
+}
+
+template <class T>
+inline const Matrix44<T> &
+Matrix44<T>::operator *= (const Matrix44<T> &v)
+{
+ Matrix44 tmp (T (0));
+
+ multiply (*this, v, tmp);
+ *this = tmp;
+ return *this;
+}
+
+template <class T>
+inline Matrix44<T>
+Matrix44<T>::operator * (const Matrix44<T> &v) const
+{
+ Matrix44 tmp (T (0));
+
+ multiply (*this, v, tmp);
+ return tmp;
+}
+
+template <class T>
+void
+Matrix44<T>::multiply (const Matrix44<T> &a,
+ const Matrix44<T> &b,
+ Matrix44<T> &c)
+{
+ register const T * restrict ap = &a.x[0][0];
+ register const T * restrict bp = &b.x[0][0];
+ register T * restrict cp = &c.x[0][0];
+
+ register T a0, a1, a2, a3;
+
+ a0 = ap[0];
+ a1 = ap[1];
+ a2 = ap[2];
+ a3 = ap[3];
+
+ cp[0] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12];
+ cp[1] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13];
+ cp[2] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14];
+ cp[3] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15];
+
+ a0 = ap[4];
+ a1 = ap[5];
+ a2 = ap[6];
+ a3 = ap[7];
+
+ cp[4] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12];
+ cp[5] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13];
+ cp[6] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14];
+ cp[7] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15];
+
+ a0 = ap[8];
+ a1 = ap[9];
+ a2 = ap[10];
+ a3 = ap[11];
+
+ cp[8] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12];
+ cp[9] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13];
+ cp[10] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14];
+ cp[11] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15];
+
+ a0 = ap[12];
+ a1 = ap[13];
+ a2 = ap[14];
+ a3 = ap[15];
+
+ cp[12] = a0 * bp[0] + a1 * bp[4] + a2 * bp[8] + a3 * bp[12];
+ cp[13] = a0 * bp[1] + a1 * bp[5] + a2 * bp[9] + a3 * bp[13];
+ cp[14] = a0 * bp[2] + a1 * bp[6] + a2 * bp[10] + a3 * bp[14];
+ cp[15] = a0 * bp[3] + a1 * bp[7] + a2 * bp[11] + a3 * bp[15];
+}
+
+template <class T> template <class S>
+void
+Matrix44<T>::multVecMatrix(const Vec3<S> &src, Vec3<S> &dst) const
+{
+ S a, b, c, w;
+
+ a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0] + x[3][0];
+ b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1] + x[3][1];
+ c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2] + x[3][2];
+ w = src[0] * x[0][3] + src[1] * x[1][3] + src[2] * x[2][3] + x[3][3];
+
+ dst.x = a / w;
+ dst.y = b / w;
+ dst.z = c / w;
+}
+
+template <class T> template <class S>
+void
+Matrix44<T>::multDirMatrix(const Vec3<S> &src, Vec3<S> &dst) const
+{
+ S a, b, c;
+
+ a = src[0] * x[0][0] + src[1] * x[1][0] + src[2] * x[2][0];
+ b = src[0] * x[0][1] + src[1] * x[1][1] + src[2] * x[2][1];
+ c = src[0] * x[0][2] + src[1] * x[1][2] + src[2] * x[2][2];
+
+ dst.x = a;
+ dst.y = b;
+ dst.z = c;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::operator /= (T a)
+{
+ x[0][0] /= a;
+ x[0][1] /= a;
+ x[0][2] /= a;
+ x[0][3] /= a;
+ x[1][0] /= a;
+ x[1][1] /= a;
+ x[1][2] /= a;
+ x[1][3] /= a;
+ x[2][0] /= a;
+ x[2][1] /= a;
+ x[2][2] /= a;
+ x[2][3] /= a;
+ x[3][0] /= a;
+ x[3][1] /= a;
+ x[3][2] /= a;
+ x[3][3] /= a;
+
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::operator / (T a) const
+{
+ return Matrix44 (x[0][0] / a,
+ x[0][1] / a,
+ x[0][2] / a,
+ x[0][3] / a,
+ x[1][0] / a,
+ x[1][1] / a,
+ x[1][2] / a,
+ x[1][3] / a,
+ x[2][0] / a,
+ x[2][1] / a,
+ x[2][2] / a,
+ x[2][3] / a,
+ x[3][0] / a,
+ x[3][1] / a,
+ x[3][2] / a,
+ x[3][3] / a);
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::transpose ()
+{
+ Matrix44 tmp (x[0][0],
+ x[1][0],
+ x[2][0],
+ x[3][0],
+ x[0][1],
+ x[1][1],
+ x[2][1],
+ x[3][1],
+ x[0][2],
+ x[1][2],
+ x[2][2],
+ x[3][2],
+ x[0][3],
+ x[1][3],
+ x[2][3],
+ x[3][3]);
+ *this = tmp;
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::transposed () const
+{
+ return Matrix44 (x[0][0],
+ x[1][0],
+ x[2][0],
+ x[3][0],
+ x[0][1],
+ x[1][1],
+ x[2][1],
+ x[3][1],
+ x[0][2],
+ x[1][2],
+ x[2][2],
+ x[3][2],
+ x[0][3],
+ x[1][3],
+ x[2][3],
+ x[3][3]);
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::gjInvert (bool singExc) throw (Iex::MathExc)
+{
+ *this = gjInverse (singExc);
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::gjInverse (bool singExc) const throw (Iex::MathExc)
+{
+ int i, j, k;
+ Matrix44 s;
+ Matrix44 t (*this);
+
+ // Forward elimination
+
+ for (i = 0; i < 3 ; i++)
+ {
+ int pivot = i;
+
+ T pivotsize = t[i][i];
+
+ if (pivotsize < 0)
+ pivotsize = -pivotsize;
+
+ for (j = i + 1; j < 4; j++)
+ {
+ T tmp = t[j][i];
+
+ if (tmp < 0)
+ tmp = -tmp;
+
+ if (tmp > pivotsize)
+ {
+ pivot = j;
+ pivotsize = tmp;
+ }
+ }
+
+ if (pivotsize == 0)
+ {
+ if (singExc)
+ throw ::Imath::SingMatrixExc ("Cannot invert singular matrix.");
+
+ return Matrix44();
+ }
+
+ if (pivot != i)
+ {
+ for (j = 0; j < 4; j++)
+ {
+ T tmp;
+
+ tmp = t[i][j];
+ t[i][j] = t[pivot][j];
+ t[pivot][j] = tmp;
+
+ tmp = s[i][j];
+ s[i][j] = s[pivot][j];
+ s[pivot][j] = tmp;
+ }
+ }
+
+ for (j = i + 1; j < 4; j++)
+ {
+ T f = t[j][i] / t[i][i];
+
+ for (k = 0; k < 4; k++)
+ {
+ t[j][k] -= f * t[i][k];
+ s[j][k] -= f * s[i][k];
+ }
+ }
+ }
+
+ // Backward substitution
+
+ for (i = 3; i >= 0; --i)
+ {
+ T f;
+
+ if ((f = t[i][i]) == 0)
+ {
+ if (singExc)
+ throw ::Imath::SingMatrixExc ("Cannot invert singular matrix.");
+
+ return Matrix44();
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ t[i][j] /= f;
+ s[i][j] /= f;
+ }
+
+ for (j = 0; j < i; j++)
+ {
+ f = t[j][i];
+
+ for (k = 0; k < 4; k++)
+ {
+ t[j][k] -= f * t[i][k];
+ s[j][k] -= f * s[i][k];
+ }
+ }
+ }
+
+ return s;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::invert (bool singExc) throw (Iex::MathExc)
+{
+ *this = inverse (singExc);
+ return *this;
+}
+
+template <class T>
+Matrix44<T>
+Matrix44<T>::inverse (bool singExc) const throw (Iex::MathExc)
+{
+ if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1)
+ return gjInverse(singExc);
+
+ Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2],
+ x[2][1] * x[0][2] - x[0][1] * x[2][2],
+ x[0][1] * x[1][2] - x[1][1] * x[0][2],
+ 0,
+
+ x[2][0] * x[1][2] - x[1][0] * x[2][2],
+ x[0][0] * x[2][2] - x[2][0] * x[0][2],
+ x[1][0] * x[0][2] - x[0][0] * x[1][2],
+ 0,
+
+ x[1][0] * x[2][1] - x[2][0] * x[1][1],
+ x[2][0] * x[0][1] - x[0][0] * x[2][1],
+ x[0][0] * x[1][1] - x[1][0] * x[0][1],
+ 0,
+
+ 0,
+ 0,
+ 0,
+ 1);
+
+ T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0];
+
+ if (Imath::abs (r) >= 1)
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ s[i][j] /= r;
+ }
+ }
+ }
+ else
+ {
+ T mr = Imath::abs (r) / limits<T>::smallest();
+
+ for (int i = 0; i < 3; ++i)
+ {
+ for (int j = 0; j < 3; ++j)
+ {
+ if (mr > Imath::abs (s[i][j]))
+ {
+ s[i][j] /= r;
+ }
+ else
+ {
+ if (singExc)
+ throw SingMatrixExc ("Cannot invert singular matrix.");
+
+ return Matrix44();
+ }
+ }
+ }
+ }
+
+ s[3][0] = -x[3][0] * s[0][0] - x[3][1] * s[1][0] - x[3][2] * s[2][0];
+ s[3][1] = -x[3][0] * s[0][1] - x[3][1] * s[1][1] - x[3][2] * s[2][1];
+ s[3][2] = -x[3][0] * s[0][2] - x[3][1] * s[1][2] - x[3][2] * s[2][2];
+
+ return s;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setEulerAngles (const Vec3<S>& r)
+{
+ S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx;
+
+ cos_rz = Math<T>::cos (r[2]);
+ cos_ry = Math<T>::cos (r[1]);
+ cos_rx = Math<T>::cos (r[0]);
+
+ sin_rz = Math<T>::sin (r[2]);
+ sin_ry = Math<T>::sin (r[1]);
+ sin_rx = Math<T>::sin (r[0]);
+
+ x[0][0] = cos_rz * cos_ry;
+ x[0][1] = sin_rz * cos_ry;
+ x[0][2] = -sin_ry;
+ x[0][3] = 0;
+
+ x[1][0] = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx;
+ x[1][1] = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx;
+ x[1][2] = cos_ry * sin_rx;
+ x[1][3] = 0;
+
+ x[2][0] = sin_rz * sin_rx + cos_rz * sin_ry * cos_rx;
+ x[2][1] = -cos_rz * sin_rx + sin_rz * sin_ry * cos_rx;
+ x[2][2] = cos_ry * cos_rx;
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setAxisAngle (const Vec3<S>& axis, S angle)
+{
+ Vec3<S> unit (axis.normalized());
+ S sine = Math<T>::sin (angle);
+ S cosine = Math<T>::cos (angle);
+
+ x[0][0] = unit[0] * unit[0] * (1 - cosine) + cosine;
+ x[0][1] = unit[0] * unit[1] * (1 - cosine) + unit[2] * sine;
+ x[0][2] = unit[0] * unit[2] * (1 - cosine) - unit[1] * sine;
+ x[0][3] = 0;
+
+ x[1][0] = unit[0] * unit[1] * (1 - cosine) - unit[2] * sine;
+ x[1][1] = unit[1] * unit[1] * (1 - cosine) + cosine;
+ x[1][2] = unit[1] * unit[2] * (1 - cosine) + unit[0] * sine;
+ x[1][3] = 0;
+
+ x[2][0] = unit[0] * unit[2] * (1 - cosine) + unit[1] * sine;
+ x[2][1] = unit[1] * unit[2] * (1 - cosine) - unit[0] * sine;
+ x[2][2] = unit[2] * unit[2] * (1 - cosine) + cosine;
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::rotate (const Vec3<S> &r)
+{
+ S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx;
+ S m00, m01, m02;
+ S m10, m11, m12;
+ S m20, m21, m22;
+
+ cos_rz = Math<S>::cos (r[2]);
+ cos_ry = Math<S>::cos (r[1]);
+ cos_rx = Math<S>::cos (r[0]);
+
+ sin_rz = Math<S>::sin (r[2]);
+ sin_ry = Math<S>::sin (r[1]);
+ sin_rx = Math<S>::sin (r[0]);
+
+ m00 = cos_rz * cos_ry;
+ m01 = sin_rz * cos_ry;
+ m02 = -sin_ry;
+ m10 = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx;
+ m11 = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx;
+ m12 = cos_ry * sin_rx;
+ m20 = -sin_rz * -sin_rx + cos_rz * sin_ry * cos_rx;
+ m21 = cos_rz * -sin_rx + sin_rz * sin_ry * cos_rx;
+ m22 = cos_ry * cos_rx;
+
+ Matrix44<T> P (*this);
+
+ x[0][0] = P[0][0] * m00 + P[1][0] * m01 + P[2][0] * m02;
+ x[0][1] = P[0][1] * m00 + P[1][1] * m01 + P[2][1] * m02;
+ x[0][2] = P[0][2] * m00 + P[1][2] * m01 + P[2][2] * m02;
+ x[0][3] = P[0][3] * m00 + P[1][3] * m01 + P[2][3] * m02;
+
+ x[1][0] = P[0][0] * m10 + P[1][0] * m11 + P[2][0] * m12;
+ x[1][1] = P[0][1] * m10 + P[1][1] * m11 + P[2][1] * m12;
+ x[1][2] = P[0][2] * m10 + P[1][2] * m11 + P[2][2] * m12;
+ x[1][3] = P[0][3] * m10 + P[1][3] * m11 + P[2][3] * m12;
+
+ x[2][0] = P[0][0] * m20 + P[1][0] * m21 + P[2][0] * m22;
+ x[2][1] = P[0][1] * m20 + P[1][1] * m21 + P[2][1] * m22;
+ x[2][2] = P[0][2] * m20 + P[1][2] * m21 + P[2][2] * m22;
+ x[2][3] = P[0][3] * m20 + P[1][3] * m21 + P[2][3] * m22;
+
+ return *this;
+}
+
+template <class T>
+const Matrix44<T> &
+Matrix44<T>::setScale (T s)
+{
+ x[0][0] = s;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = s;
+ x[1][2] = 0;
+ x[1][3] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = s;
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setScale (const Vec3<S> &s)
+{
+ x[0][0] = s[0];
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = s[1];
+ x[1][2] = 0;
+ x[1][3] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = s[2];
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::scale (const Vec3<S> &s)
+{
+ x[0][0] *= s[0];
+ x[0][1] *= s[0];
+ x[0][2] *= s[0];
+ x[0][3] *= s[0];
+
+ x[1][0] *= s[1];
+ x[1][1] *= s[1];
+ x[1][2] *= s[1];
+ x[1][3] *= s[1];
+
+ x[2][0] *= s[2];
+ x[2][1] *= s[2];
+ x[2][2] *= s[2];
+ x[2][3] *= s[2];
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setTranslation (const Vec3<S> &t)
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+
+ x[1][0] = 0;
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[1][3] = 0;
+
+ x[2][0] = 0;
+ x[2][1] = 0;
+ x[2][2] = 1;
+ x[2][3] = 0;
+
+ x[3][0] = t[0];
+ x[3][1] = t[1];
+ x[3][2] = t[2];
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+inline const Vec3<T>
+Matrix44<T>::translation () const
+{
+ return Vec3<T> (x[3][0], x[3][1], x[3][2]);
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::translate (const Vec3<S> &t)
+{
+ x[3][0] += t[0] * x[0][0] + t[1] * x[1][0] + t[2] * x[2][0];
+ x[3][1] += t[0] * x[0][1] + t[1] * x[1][1] + t[2] * x[2][1];
+ x[3][2] += t[0] * x[0][2] + t[1] * x[1][2] + t[2] * x[2][2];
+ x[3][3] += t[0] * x[0][3] + t[1] * x[1][3] + t[2] * x[2][3];
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setShear (const Vec3<S> &h)
+{
+ x[0][0] = 1;
+ x[0][1] = 0;
+ x[0][2] = 0;
+ x[0][3] = 0;
+
+ x[1][0] = h[0];
+ x[1][1] = 1;
+ x[1][2] = 0;
+ x[1][3] = 0;
+
+ x[2][0] = h[1];
+ x[2][1] = h[2];
+ x[2][2] = 1;
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::setShear (const Shear6<S> &h)
+{
+ x[0][0] = 1;
+ x[0][1] = h.yx;
+ x[0][2] = h.zx;
+ x[0][3] = 0;
+
+ x[1][0] = h.xy;
+ x[1][1] = 1;
+ x[1][2] = h.zy;
+ x[1][3] = 0;
+
+ x[2][0] = h.xz;
+ x[2][1] = h.yz;
+ x[2][2] = 1;
+ x[2][3] = 0;
+
+ x[3][0] = 0;
+ x[3][1] = 0;
+ x[3][2] = 0;
+ x[3][3] = 1;
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::shear (const Vec3<S> &h)
+{
+ //
+ // In this case, we don't need a temp. copy of the matrix
+ // because we never use a value on the RHS after we've
+ // changed it on the LHS.
+ //
+
+ for (int i=0; i < 4; i++)
+ {
+ x[2][i] += h[1] * x[0][i] + h[2] * x[1][i];
+ x[1][i] += h[0] * x[0][i];
+ }
+
+ return *this;
+}
+
+template <class T>
+template <class S>
+const Matrix44<T> &
+Matrix44<T>::shear (const Shear6<S> &h)
+{
+ Matrix44<T> P (*this);
+
+ for (int i=0; i < 4; i++)
+ {
+ x[0][i] = P[0][i] + h.yx * P[1][i] + h.zx * P[2][i];
+ x[1][i] = h.xy * P[0][i] + P[1][i] + h.zy * P[2][i];
+ x[2][i] = h.xz * P[0][i] + h.yz * P[1][i] + P[2][i];
+ }
+
+ return *this;
+}
+
+
+//--------------------------------
+// Implementation of stream output
+//--------------------------------
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Matrix33<T> &m)
+{
+ std::ios_base::fmtflags oldFlags = s.flags();
+ int width;
+
+ if (s.flags() & std::ios_base::fixed)
+ {
+ s.setf (std::ios_base::showpoint);
+ width = s.precision() + 5;
+ }
+ else
+ {
+ s.setf (std::ios_base::scientific);
+ s.setf (std::ios_base::showpoint);
+ width = s.precision() + 8;
+ }
+
+ s << "(" << std::setw (width) << m[0][0] <<
+ " " << std::setw (width) << m[0][1] <<
+ " " << std::setw (width) << m[0][2] << "\n" <<
+
+ " " << std::setw (width) << m[1][0] <<
+ " " << std::setw (width) << m[1][1] <<
+ " " << std::setw (width) << m[1][2] << "\n" <<
+
+ " " << std::setw (width) << m[2][0] <<
+ " " << std::setw (width) << m[2][1] <<
+ " " << std::setw (width) << m[2][2] << ")\n";
+
+ s.flags (oldFlags);
+ return s;
+}
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Matrix44<T> &m)
+{
+ std::ios_base::fmtflags oldFlags = s.flags();
+ int width;
+
+ if (s.flags() & std::ios_base::fixed)
+ {
+ s.setf (std::ios_base::showpoint);
+ width = s.precision() + 5;
+ }
+ else
+ {
+ s.setf (std::ios_base::scientific);
+ s.setf (std::ios_base::showpoint);
+ width = s.precision() + 8;
+ }
+
+ s << "(" << std::setw (width) << m[0][0] <<
+ " " << std::setw (width) << m[0][1] <<
+ " " << std::setw (width) << m[0][2] <<
+ " " << std::setw (width) << m[0][3] << "\n" <<
+
+ " " << std::setw (width) << m[1][0] <<
+ " " << std::setw (width) << m[1][1] <<
+ " " << std::setw (width) << m[1][2] <<
+ " " << std::setw (width) << m[1][3] << "\n" <<
+
+ " " << std::setw (width) << m[2][0] <<
+ " " << std::setw (width) << m[2][1] <<
+ " " << std::setw (width) << m[2][2] <<
+ " " << std::setw (width) << m[2][3] << "\n" <<
+
+ " " << std::setw (width) << m[3][0] <<
+ " " << std::setw (width) << m[3][1] <<
+ " " << std::setw (width) << m[3][2] <<
+ " " << std::setw (width) << m[3][3] << ")\n";
+
+ s.flags (oldFlags);
+ return s;
+}
+
+
+//---------------------------------------------------------------
+// Implementation of vector-times-matrix multiplication operators
+//---------------------------------------------------------------
+
+template <class S, class T>
+inline const Vec2<S> &
+operator *= (Vec2<S> &v, const Matrix33<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + m[2][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + m[2][1]);
+ S w = S(v.x * m[0][2] + v.y * m[1][2] + m[2][2]);
+
+ v.x = x / w;
+ v.y = y / w;
+
+ return v;
+}
+
+template <class S, class T>
+inline Vec2<S>
+operator * (const Vec2<S> &v, const Matrix33<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + m[2][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + m[2][1]);
+ S w = S(v.x * m[0][2] + v.y * m[1][2] + m[2][2]);
+
+ return Vec2<S> (x / w, y / w);
+}
+
+
+template <class S, class T>
+inline const Vec3<S> &
+operator *= (Vec3<S> &v, const Matrix33<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]);
+ S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]);
+
+ v.x = x;
+ v.y = y;
+ v.z = z;
+
+ return v;
+}
+
+
+template <class S, class T>
+inline Vec3<S>
+operator * (const Vec3<S> &v, const Matrix33<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]);
+ S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]);
+
+ return Vec3<S> (x, y, z);
+}
+
+
+template <class S, class T>
+inline const Vec3<S> &
+operator *= (Vec3<S> &v, const Matrix44<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]);
+ S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]);
+ S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]);
+
+ v.x = x / w;
+ v.y = y / w;
+ v.z = z / w;
+
+ return v;
+}
+
+template <class S, class T>
+inline Vec3<S>
+operator * (const Vec3<S> &v, const Matrix44<T> &m)
+{
+ S x = S(v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]);
+ S y = S(v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]);
+ S z = S(v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]);
+ S w = S(v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]);
+
+ return Vec3<S> (x / w, y / w, z / w);
+}
+
+} // namespace Imath
+
+
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathMatrixAlgo.cpp b/Source/OpenEXR/Imath/ImathMatrixAlgo.cpp
new file mode 100644
index 0000000..53e6f29
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathMatrixAlgo.cpp
@@ -0,0 +1,73 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+//----------------------------------------------------------------------------
+//
+// Implementation of non-template items declared in ImathMatrixAlgo.h
+//
+//----------------------------------------------------------------------------
+
+#include "ImathMatrixAlgo.h"
+
+#if defined(OPENEXR_DLL)
+ #define EXPORT_CONST __declspec(dllexport)
+#else
+ #define EXPORT_CONST const
+#endif
+
+namespace Imath {
+
+EXPORT_CONST M33f identity33f ( 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1);
+
+EXPORT_CONST M33d identity33d ( 1, 0, 0,
+ 0, 1, 0,
+ 0, 0, 1);
+
+EXPORT_CONST M44f identity44f ( 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+
+EXPORT_CONST M44d identity44d ( 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathMatrixAlgo.h b/Source/OpenEXR/Imath/ImathMatrixAlgo.h
new file mode 100644
index 0000000..0234f23
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathMatrixAlgo.h
@@ -0,0 +1,1114 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMATHMATRIXALGO_H
+#define INCLUDED_IMATHMATRIXALGO_H
+
+//-------------------------------------------------------------------------
+//
+// This file contains algorithms applied to or in conjunction with
+// transformation matrices (Imath::Matrix33 and Imath::Matrix44).
+// The assumption made is that these functions are called much less
+// often than the basic point functions or these functions require
+// more support classes.
+//
+// This file also defines a few predefined constant matrices.
+//
+//-------------------------------------------------------------------------
+
+#include "ImathMatrix.h"
+#include "ImathQuat.h"
+#include "ImathEuler.h"
+#include "ImathExc.h"
+#include "ImathVec.h"
+#include <math.h>
+
+
+#ifdef OPENEXR_DLL
+ #ifdef IMATH_EXPORTS
+ #define IMATH_EXPORT_CONST extern __declspec(dllexport)
+ #else
+ #define IMATH_EXPORT_CONST extern __declspec(dllimport)
+ #endif
+#else
+ #define IMATH_EXPORT_CONST extern const
+#endif
+
+
+namespace Imath {
+
+//------------------
+// Identity matrices
+//------------------
+
+IMATH_EXPORT_CONST M33f identity33f;
+IMATH_EXPORT_CONST M44f identity44f;
+IMATH_EXPORT_CONST M33d identity33d;
+IMATH_EXPORT_CONST M44d identity44d;
+
+//----------------------------------------------------------------------
+// Extract scale, shear, rotation, and translation values from a matrix:
+//
+// Notes:
+//
+// This implementation follows the technique described in the paper by
+// Spencer W. Thomas in the Graphics Gems II article: "Decomposing a
+// Matrix into Simple Transformations", p. 320.
+//
+// - Some of the functions below have an optional exc parameter
+// that determines the functions' behavior when the matrix'
+// scaling is very close to zero:
+//
+// If exc is true, the functions throw an Imath::ZeroScale exception.
+//
+// If exc is false:
+//
+// extractScaling (m, s) returns false, s is invalid
+// sansScaling (m) returns m
+// removeScaling (m) returns false, m is unchanged
+// sansScalingAndShear (m) returns m
+// removeScalingAndShear (m) returns false, m is unchanged
+// extractAndRemoveScalingAndShear (m, s, h)
+// returns false, m is unchanged,
+// (sh) are invalid
+// checkForZeroScaleInRow () returns false
+// extractSHRT (m, s, h, r, t) returns false, (shrt) are invalid
+//
+// - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX()
+// assume that the matrix does not include shear or non-uniform scaling,
+// but they do not examine the matrix to verify this assumption.
+// Matrices with shear or non-uniform scaling are likely to produce
+// meaningless results. Therefore, you should use the
+// removeScalingAndShear() routine, if necessary, prior to calling
+// extractEuler...() .
+//
+// - All functions assume that the matrix does not include perspective
+// transformation(s), but they do not examine the matrix to verify
+// this assumption. Matrices with perspective transformations are
+// likely to produce meaningless results.
+//
+//----------------------------------------------------------------------
+
+
+//
+// Declarations for 4x4 matrix.
+//
+
+template <class T> bool extractScaling
+ (const Matrix44<T> &mat,
+ Vec3<T> &scl,
+ bool exc = true);
+
+template <class T> Matrix44<T> sansScaling (const Matrix44<T> &mat,
+ bool exc = true);
+
+template <class T> bool removeScaling
+ (Matrix44<T> &mat,
+ bool exc = true);
+
+template <class T> bool extractScalingAndShear
+ (const Matrix44<T> &mat,
+ Vec3<T> &scl,
+ Vec3<T> &shr,
+ bool exc = true);
+
+template <class T> Matrix44<T> sansScalingAndShear
+ (const Matrix44<T> &mat,
+ bool exc = true);
+
+template <class T> bool removeScalingAndShear
+ (Matrix44<T> &mat,
+ bool exc = true);
+
+template <class T> bool extractAndRemoveScalingAndShear
+ (Matrix44<T> &mat,
+ Vec3<T> &scl,
+ Vec3<T> &shr,
+ bool exc = true);
+
+template <class T> void extractEulerXYZ
+ (const Matrix44<T> &mat,
+ Vec3<T> &rot);
+
+template <class T> void extractEulerZYX
+ (const Matrix44<T> &mat,
+ Vec3<T> &rot);
+
+template <class T> Quat<T> extractQuat (const Matrix44<T> &mat);
+
+template <class T> bool extractSHRT
+ (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Vec3<T> &r,
+ Vec3<T> &t,
+ bool exc /*= true*/,
+ typename Euler<T>::Order rOrder);
+
+template <class T> bool extractSHRT
+ (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Vec3<T> &r,
+ Vec3<T> &t,
+ bool exc = true);
+
+template <class T> bool extractSHRT
+ (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Euler<T> &r,
+ Vec3<T> &t,
+ bool exc = true);
+
+//
+// Internal utility function.
+//
+
+template <class T> bool checkForZeroScaleInRow
+ (const T &scl,
+ const Vec3<T> &row,
+ bool exc = true);
+
+//
+// Returns a matrix that rotates "fromDirection" vector to "toDirection"
+// vector.
+//
+
+template <class T> Matrix44<T> rotationMatrix (const Vec3<T> &fromDirection,
+ const Vec3<T> &toDirection);
+
+
+
+//
+// Returns a matrix that rotates the "fromDir" vector
+// so that it points towards "toDir". You may also
+// specify that you want the up vector to be pointing
+// in a certain direction "upDir".
+//
+
+template <class T> Matrix44<T> rotationMatrixWithUpDir
+ (const Vec3<T> &fromDir,
+ const Vec3<T> &toDir,
+ const Vec3<T> &upDir);
+
+
+//
+// Returns a matrix that rotates the z-axis so that it
+// points towards "targetDir". You must also specify
+// that you want the up vector to be pointing in a
+// certain direction "upDir".
+//
+// Notes: The following degenerate cases are handled:
+// (a) when the directions given by "toDir" and "upDir"
+// are parallel or opposite;
+// (the direction vectors must have a non-zero cross product)
+// (b) when any of the given direction vectors have zero length
+//
+
+template <class T> Matrix44<T> alignZAxisWithTargetDir
+ (Vec3<T> targetDir,
+ Vec3<T> upDir);
+
+
+//----------------------------------------------------------------------
+
+
+//
+// Declarations for 3x3 matrix.
+//
+
+
+template <class T> bool extractScaling
+ (const Matrix33<T> &mat,
+ Vec2<T> &scl,
+ bool exc = true);
+
+template <class T> Matrix33<T> sansScaling (const Matrix33<T> &mat,
+ bool exc = true);
+
+template <class T> bool removeScaling
+ (Matrix33<T> &mat,
+ bool exc = true);
+
+template <class T> bool extractScalingAndShear
+ (const Matrix33<T> &mat,
+ Vec2<T> &scl,
+ T &h,
+ bool exc = true);
+
+template <class T> Matrix33<T> sansScalingAndShear
+ (const Matrix33<T> &mat,
+ bool exc = true);
+
+template <class T> bool removeScalingAndShear
+ (Matrix33<T> &mat,
+ bool exc = true);
+
+template <class T> bool extractAndRemoveScalingAndShear
+ (Matrix33<T> &mat,
+ Vec2<T> &scl,
+ T &shr,
+ bool exc = true);
+
+template <class T> void extractEuler
+ (const Matrix33<T> &mat,
+ T &rot);
+
+template <class T> bool extractSHRT (const Matrix33<T> &mat,
+ Vec2<T> &s,
+ T &h,
+ T &r,
+ Vec2<T> &t,
+ bool exc = true);
+
+template <class T> bool checkForZeroScaleInRow
+ (const T &scl,
+ const Vec2<T> &row,
+ bool exc = true);
+
+
+
+
+//-----------------------------------------------------------------------------
+// Implementation for 4x4 Matrix
+//------------------------------
+
+
+template <class T>
+bool
+extractScaling (const Matrix44<T> &mat, Vec3<T> &scl, bool exc)
+{
+ Vec3<T> shr;
+ Matrix44<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+Matrix44<T>
+sansScaling (const Matrix44<T> &mat, bool exc)
+{
+ Vec3<T> scl;
+ Vec3<T> shr;
+ Vec3<T> rot;
+ Vec3<T> tran;
+
+ if (! extractSHRT (mat, scl, shr, rot, tran, exc))
+ return mat;
+
+ Matrix44<T> M;
+
+ M.translate (tran);
+ M.rotate (rot);
+ M.shear (shr);
+
+ return M;
+}
+
+
+template <class T>
+bool
+removeScaling (Matrix44<T> &mat, bool exc)
+{
+ Vec3<T> scl;
+ Vec3<T> shr;
+ Vec3<T> rot;
+ Vec3<T> tran;
+
+ if (! extractSHRT (mat, scl, shr, rot, tran, exc))
+ return false;
+
+ mat.makeIdentity ();
+ mat.translate (tran);
+ mat.rotate (rot);
+ mat.shear (shr);
+
+ return true;
+}
+
+
+template <class T>
+bool
+extractScalingAndShear (const Matrix44<T> &mat,
+ Vec3<T> &scl, Vec3<T> &shr, bool exc)
+{
+ Matrix44<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+Matrix44<T>
+sansScalingAndShear (const Matrix44<T> &mat, bool exc)
+{
+ Vec3<T> scl;
+ Vec3<T> shr;
+ Matrix44<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return mat;
+
+ return M;
+}
+
+
+template <class T>
+bool
+removeScalingAndShear (Matrix44<T> &mat, bool exc)
+{
+ Vec3<T> scl;
+ Vec3<T> shr;
+
+ if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+bool
+extractAndRemoveScalingAndShear (Matrix44<T> &mat,
+ Vec3<T> &scl, Vec3<T> &shr, bool exc)
+{
+ //
+ // This implementation follows the technique described in the paper by
+ // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a
+ // Matrix into Simple Transformations", p. 320.
+ //
+
+ Vec3<T> row[3];
+
+ row[0] = Vec3<T> (mat[0][0], mat[0][1], mat[0][2]);
+ row[1] = Vec3<T> (mat[1][0], mat[1][1], mat[1][2]);
+ row[2] = Vec3<T> (mat[2][0], mat[2][1], mat[2][2]);
+
+ T maxVal = 0;
+ for (int i=0; i < 3; i++)
+ for (int j=0; j < 3; j++)
+ if (Imath::abs (row[i][j]) > maxVal)
+ maxVal = Imath::abs (row[i][j]);
+
+ //
+ // We normalize the 3x3 matrix here.
+ // It was noticed that this can improve numerical stability significantly,
+ // especially when many of the upper 3x3 matrix's coefficients are very
+ // close to zero; we correct for this step at the end by multiplying the
+ // scaling factors by maxVal at the end (shear and rotation are not
+ // affected by the normalization).
+
+ if (maxVal != 0)
+ {
+ for (int i=0; i < 3; i++)
+ if (! checkForZeroScaleInRow (maxVal, row[i], exc))
+ return false;
+ else
+ row[i] /= maxVal;
+ }
+
+ // Compute X scale factor.
+ scl.x = row[0].length ();
+ if (! checkForZeroScaleInRow (scl.x, row[0], exc))
+ return false;
+
+ // Normalize first row.
+ row[0] /= scl.x;
+
+ // An XY shear factor will shear the X coord. as the Y coord. changes.
+ // There are 6 combinations (XY, XZ, YZ, YX, ZX, ZY), although we only
+ // extract the first 3 because we can effect the last 3 by shearing in
+ // XY, XZ, YZ combined rotations and scales.
+ //
+ // shear matrix < 1, YX, ZX, 0,
+ // XY, 1, ZY, 0,
+ // XZ, YZ, 1, 0,
+ // 0, 0, 0, 1 >
+
+ // Compute XY shear factor and make 2nd row orthogonal to 1st.
+ shr[0] = row[0].dot (row[1]);
+ row[1] -= shr[0] * row[0];
+
+ // Now, compute Y scale.
+ scl.y = row[1].length ();
+ if (! checkForZeroScaleInRow (scl.y, row[1], exc))
+ return false;
+
+ // Normalize 2nd row and correct the XY shear factor for Y scaling.
+ row[1] /= scl.y;
+ shr[0] /= scl.y;
+
+ // Compute XZ and YZ shears, orthogonalize 3rd row.
+ shr[1] = row[0].dot (row[2]);
+ row[2] -= shr[1] * row[0];
+ shr[2] = row[1].dot (row[2]);
+ row[2] -= shr[2] * row[1];
+
+ // Next, get Z scale.
+ scl.z = row[2].length ();
+ if (! checkForZeroScaleInRow (scl.z, row[2], exc))
+ return false;
+
+ // Normalize 3rd row and correct the XZ and YZ shear factors for Z scaling.
+ row[2] /= scl.z;
+ shr[1] /= scl.z;
+ shr[2] /= scl.z;
+
+ // At this point, the upper 3x3 matrix in mat is orthonormal.
+ // Check for a coordinate system flip. If the determinant
+ // is less than zero, then negate the matrix and the scaling factors.
+ if (row[0].dot (row[1].cross (row[2])) < 0)
+ for (int i=0; i < 3; i++)
+ {
+ scl[i] *= -1;
+ row[i] *= -1;
+ }
+
+ // Copy over the orthonormal rows into the returned matrix.
+ // The upper 3x3 matrix in mat is now a rotation matrix.
+ for (int i=0; i < 3; i++)
+ {
+ mat[i][0] = row[i][0];
+ mat[i][1] = row[i][1];
+ mat[i][2] = row[i][2];
+ }
+
+ // Correct the scaling factors for the normalization step that we
+ // performed above; shear and rotation are not affected by the
+ // normalization.
+ scl *= maxVal;
+
+ return true;
+}
+
+
+template <class T>
+void
+extractEulerXYZ (const Matrix44<T> &mat, Vec3<T> &rot)
+{
+ //
+ // Normalize the local x, y and z axes to remove scaling.
+ //
+
+ Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
+ Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
+ Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
+
+ i.normalize();
+ j.normalize();
+ k.normalize();
+
+ Matrix44<T> M (i[0], i[1], i[2], 0,
+ j[0], j[1], j[2], 0,
+ k[0], k[1], k[2], 0,
+ 0, 0, 0, 1);
+
+ //
+ // Extract the first angle, rot.x.
+ //
+
+ rot.x = Math<T>::atan2 (M[1][2], M[2][2]);
+
+ //
+ // Remove the rot.x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Matrix44<T> N;
+ N.rotate (Vec3<T> (-rot.x, 0, 0));
+ N = N * M;
+
+ //
+ // Extract the other two angles, rot.y and rot.z, from N.
+ //
+
+ T cy = Math<T>::sqrt (N[0][0]*N[0][0] + N[0][1]*N[0][1]);
+ rot.y = Math<T>::atan2 (-N[0][2], cy);
+ rot.z = Math<T>::atan2 (-N[1][0], N[1][1]);
+}
+
+
+template <class T>
+void
+extractEulerZYX (const Matrix44<T> &mat, Vec3<T> &rot)
+{
+ //
+ // Normalize the local x, y and z axes to remove scaling.
+ //
+
+ Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
+ Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
+ Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
+
+ i.normalize();
+ j.normalize();
+ k.normalize();
+
+ Matrix44<T> M (i[0], i[1], i[2], 0,
+ j[0], j[1], j[2], 0,
+ k[0], k[1], k[2], 0,
+ 0, 0, 0, 1);
+
+ //
+ // Extract the first angle, rot.x.
+ //
+
+ rot.x = -Math<T>::atan2 (M[1][0], M[0][0]);
+
+ //
+ // Remove the x rotation from M, so that the remaining
+ // rotation, N, is only around two axes, and gimbal lock
+ // cannot occur.
+ //
+
+ Matrix44<T> N;
+ N.rotate (Vec3<T> (0, 0, -rot.x));
+ N = N * M;
+
+ //
+ // Extract the other two angles, rot.y and rot.z, from N.
+ //
+
+ T cy = Math<T>::sqrt (N[2][2]*N[2][2] + N[2][1]*N[2][1]);
+ rot.y = -Math<T>::atan2 (-N[2][0], cy);
+ rot.z = -Math<T>::atan2 (-N[1][2], N[1][1]);
+}
+
+
+template <class T>
+Quat<T>
+extractQuat (const Matrix44<T> &mat)
+{
+ Matrix44<T> rot;
+
+ T tr, s;
+ T q[4];
+ int i, j, k;
+ Quat<T> quat;
+
+ int nxt[3] = {1, 2, 0};
+ tr = mat[0][0] + mat[1][1] + mat[2][2];
+
+ // check the diagonal
+ if (tr > 0.0) {
+ s = Math<T>::sqrt (tr + 1.0);
+ quat.r = s / 2.0;
+ s = 0.5 / s;
+
+ quat.v.x = (mat[1][2] - mat[2][1]) * s;
+ quat.v.y = (mat[2][0] - mat[0][2]) * s;
+ quat.v.z = (mat[0][1] - mat[1][0]) * s;
+ }
+ else {
+ // diagonal is negative
+ i = 0;
+ if (mat[1][1] > mat[0][0])
+ i=1;
+ if (mat[2][2] > mat[i][i])
+ i=2;
+
+ j = nxt[i];
+ k = nxt[j];
+ s = Math<T>::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + 1.0);
+
+ q[i] = s * 0.5;
+ if (s != 0.0)
+ s = 0.5 / s;
+
+ q[3] = (mat[j][k] - mat[k][j]) * s;
+ q[j] = (mat[i][j] + mat[j][i]) * s;
+ q[k] = (mat[i][k] + mat[k][i]) * s;
+
+ quat.v.x = q[0];
+ quat.v.y = q[1];
+ quat.v.z = q[2];
+ quat.r = q[3];
+ }
+
+ return quat;
+}
+
+template <class T>
+bool
+extractSHRT (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Vec3<T> &r,
+ Vec3<T> &t,
+ bool exc /* = true */ ,
+ typename Euler<T>::Order rOrder /* = Euler<T>::XYZ */ )
+{
+ Matrix44<T> rot;
+
+ rot = mat;
+ if (! extractAndRemoveScalingAndShear (rot, s, h, exc))
+ return false;
+
+ extractEulerXYZ (rot, r);
+
+ t.x = mat[3][0];
+ t.y = mat[3][1];
+ t.z = mat[3][2];
+
+ if (rOrder != Euler<T>::XYZ)
+ {
+ Imath::Euler<T> eXYZ (r, Imath::Euler<T>::XYZ);
+ Imath::Euler<T> e (eXYZ, rOrder);
+ r = e.toXYZVector ();
+ }
+
+ return true;
+}
+
+template <class T>
+bool
+extractSHRT (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Vec3<T> &r,
+ Vec3<T> &t,
+ bool exc)
+{
+ return extractSHRT(mat, s, h, r, t, exc, Imath::Euler<T>::XYZ);
+}
+
+template <class T>
+bool
+extractSHRT (const Matrix44<T> &mat,
+ Vec3<T> &s,
+ Vec3<T> &h,
+ Euler<T> &r,
+ Vec3<T> &t,
+ bool exc /* = true */)
+{
+ return extractSHRT (mat, s, h, r, t, exc, r.order ());
+}
+
+
+template <class T>
+bool
+checkForZeroScaleInRow (const T& scl,
+ const Vec3<T> &row,
+ bool exc /* = true */ )
+{
+ for (int i = 0; i < 3; i++)
+ {
+ if ((abs (scl) < 1 && abs (row[i]) >= limits<T>::max() * abs (scl)))
+ {
+ if (exc)
+ throw Imath::ZeroScaleExc ("Cannot remove zero scaling "
+ "from matrix.");
+ else
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+template <class T>
+Matrix44<T>
+rotationMatrix (const Vec3<T> &from, const Vec3<T> &to)
+{
+ Quat<T> q;
+ q.setRotation(from, to);
+ return q.toMatrix44();
+}
+
+
+template <class T>
+Matrix44<T>
+rotationMatrixWithUpDir (const Vec3<T> &fromDir,
+ const Vec3<T> &toDir,
+ const Vec3<T> &upDir)
+{
+ //
+ // The goal is to obtain a rotation matrix that takes
+ // "fromDir" to "toDir". We do this in two steps and
+ // compose the resulting rotation matrices;
+ // (a) rotate "fromDir" into the z-axis
+ // (b) rotate the z-axis into "toDir"
+ //
+
+ // The from direction must be non-zero; but we allow zero to and up dirs.
+ if (fromDir.length () == 0)
+ return Matrix44<T> ();
+
+ else
+ {
+ Matrix44<T> zAxis2FromDir = alignZAxisWithTargetDir
+ (fromDir, Vec3<T> (0, 1, 0));
+
+ Matrix44<T> fromDir2zAxis = zAxis2FromDir.transposed ();
+
+ Matrix44<T> zAxis2ToDir = alignZAxisWithTargetDir (toDir, upDir);
+
+ return fromDir2zAxis * zAxis2ToDir;
+ }
+}
+
+
+template <class T>
+Matrix44<T>
+alignZAxisWithTargetDir (Vec3<T> targetDir, Vec3<T> upDir)
+{
+ //
+ // Ensure that the target direction is non-zero.
+ //
+
+ if ( targetDir.length () == 0 )
+ targetDir = Vec3<T> (0, 0, 1);
+
+ //
+ // Ensure that the up direction is non-zero.
+ //
+
+ if ( upDir.length () == 0 )
+ upDir = Vec3<T> (0, 1, 0);
+
+ //
+ // Check for degeneracies. If the upDir and targetDir are parallel
+ // or opposite, then compute a new, arbitrary up direction that is
+ // not parallel or opposite to the targetDir.
+ //
+
+ if (upDir.cross (targetDir).length () == 0)
+ {
+ upDir = targetDir.cross (Vec3<T> (1, 0, 0));
+ if (upDir.length() == 0)
+ upDir = targetDir.cross(Vec3<T> (0, 0, 1));
+ }
+
+ //
+ // Compute the x-, y-, and z-axis vectors of the new coordinate system.
+ //
+
+ Vec3<T> targetPerpDir = upDir.cross (targetDir);
+ Vec3<T> targetUpDir = targetDir.cross (targetPerpDir);
+
+ //
+ // Rotate the x-axis into targetPerpDir (row 0),
+ // rotate the y-axis into targetUpDir (row 1),
+ // rotate the z-axis into targetDir (row 2).
+ //
+
+ Vec3<T> row[3];
+ row[0] = targetPerpDir.normalized ();
+ row[1] = targetUpDir .normalized ();
+ row[2] = targetDir .normalized ();
+
+ Matrix44<T> mat ( row[0][0], row[0][1], row[0][2], 0,
+ row[1][0], row[1][1], row[1][2], 0,
+ row[2][0], row[2][1], row[2][2], 0,
+ 0, 0, 0, 1 );
+
+ return mat;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Implementation for 3x3 Matrix
+//------------------------------
+
+
+template <class T>
+bool
+extractScaling (const Matrix33<T> &mat, Vec2<T> &scl, bool exc)
+{
+ T shr;
+ Matrix33<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+Matrix33<T>
+sansScaling (const Matrix33<T> &mat, bool exc)
+{
+ Vec2<T> scl;
+ T shr;
+ T rot;
+ Vec2<T> tran;
+
+ if (! extractSHRT (mat, scl, shr, rot, tran, exc))
+ return mat;
+
+ Matrix33<T> M;
+
+ M.translate (tran);
+ M.rotate (rot);
+ M.shear (shr);
+
+ return M;
+}
+
+
+template <class T>
+bool
+removeScaling (Matrix33<T> &mat, bool exc)
+{
+ Vec2<T> scl;
+ T shr;
+ T rot;
+ Vec2<T> tran;
+
+ if (! extractSHRT (mat, scl, shr, rot, tran, exc))
+ return false;
+
+ mat.makeIdentity ();
+ mat.translate (tran);
+ mat.rotate (rot);
+ mat.shear (shr);
+
+ return true;
+}
+
+
+template <class T>
+bool
+extractScalingAndShear (const Matrix33<T> &mat, Vec2<T> &scl, T &shr, bool exc)
+{
+ Matrix33<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+Matrix33<T>
+sansScalingAndShear (const Matrix33<T> &mat, bool exc)
+{
+ Vec2<T> scl;
+ T shr;
+ Matrix33<T> M (mat);
+
+ if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
+ return mat;
+
+ return M;
+}
+
+
+template <class T>
+bool
+removeScalingAndShear (Matrix33<T> &mat, bool exc)
+{
+ Vec2<T> scl;
+ T shr;
+
+ if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+extractAndRemoveScalingAndShear (Matrix33<T> &mat,
+ Vec2<T> &scl, T &shr, bool exc)
+{
+ Vec2<T> row[2];
+
+ row[0] = Vec2<T> (mat[0][0], mat[0][1]);
+ row[1] = Vec2<T> (mat[1][0], mat[1][1]);
+
+ T maxVal = 0;
+ for (int i=0; i < 2; i++)
+ for (int j=0; j < 2; j++)
+ if (Imath::abs (row[i][j]) > maxVal)
+ maxVal = Imath::abs (row[i][j]);
+
+ //
+ // We normalize the 2x2 matrix here.
+ // It was noticed that this can improve numerical stability significantly,
+ // especially when many of the upper 2x2 matrix's coefficients are very
+ // close to zero; we correct for this step at the end by multiplying the
+ // scaling factors by maxVal at the end (shear and rotation are not
+ // affected by the normalization).
+
+ if (maxVal != 0)
+ {
+ for (int i=0; i < 2; i++)
+ if (! checkForZeroScaleInRow (maxVal, row[i], exc))
+ return false;
+ else
+ row[i] /= maxVal;
+ }
+
+ // Compute X scale factor.
+ scl.x = row[0].length ();
+ if (! checkForZeroScaleInRow (scl.x, row[0], exc))
+ return false;
+
+ // Normalize first row.
+ row[0] /= scl.x;
+
+ // An XY shear factor will shear the X coord. as the Y coord. changes.
+ // There are 2 combinations (XY, YX), although we only extract the XY
+ // shear factor because we can effect the an YX shear factor by
+ // shearing in XY combined with rotations and scales.
+ //
+ // shear matrix < 1, YX, 0,
+ // XY, 1, 0,
+ // 0, 0, 1 >
+
+ // Compute XY shear factor and make 2nd row orthogonal to 1st.
+ shr = row[0].dot (row[1]);
+ row[1] -= shr * row[0];
+
+ // Now, compute Y scale.
+ scl.y = row[1].length ();
+ if (! checkForZeroScaleInRow (scl.y, row[1], exc))
+ return false;
+
+ // Normalize 2nd row and correct the XY shear factor for Y scaling.
+ row[1] /= scl.y;
+ shr /= scl.y;
+
+ // At this point, the upper 2x2 matrix in mat is orthonormal.
+ // Check for a coordinate system flip. If the determinant
+ // is -1, then flip the rotation matrix and adjust the scale(Y)
+ // and shear(XY) factors to compensate.
+ if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0)
+ {
+ row[1][0] *= -1;
+ row[1][1] *= -1;
+ scl[1] *= -1;
+ shr *= -1;
+ }
+
+ // Copy over the orthonormal rows into the returned matrix.
+ // The upper 2x2 matrix in mat is now a rotation matrix.
+ for (int i=0; i < 2; i++)
+ {
+ mat[i][0] = row[i][0];
+ mat[i][1] = row[i][1];
+ }
+
+ scl *= maxVal;
+
+ return true;
+}
+
+
+template <class T>
+void
+extractEuler (const Matrix33<T> &mat, T &rot)
+{
+ //
+ // Normalize the local x and y axes to remove scaling.
+ //
+
+ Vec2<T> i (mat[0][0], mat[0][1]);
+ Vec2<T> j (mat[1][0], mat[1][1]);
+
+ i.normalize();
+ j.normalize();
+
+ //
+ // Extract the angle, rot.
+ //
+
+ rot = - Math<T>::atan2 (j[0], i[0]);
+}
+
+
+template <class T>
+bool
+extractSHRT (const Matrix33<T> &mat,
+ Vec2<T> &s,
+ T &h,
+ T &r,
+ Vec2<T> &t,
+ bool exc)
+{
+ Matrix33<T> rot;
+
+ rot = mat;
+ if (! extractAndRemoveScalingAndShear (rot, s, h, exc))
+ return false;
+
+ extractEuler (rot, r);
+
+ t.x = mat[2][0];
+ t.y = mat[2][1];
+
+ return true;
+}
+
+
+template <class T>
+bool
+checkForZeroScaleInRow (const T& scl,
+ const Vec2<T> &row,
+ bool exc /* = true */ )
+{
+ for (int i = 0; i < 2; i++)
+ {
+ if ((abs (scl) < 1 && abs (row[i]) >= limits<T>::max() * abs (scl)))
+ {
+ if (exc)
+ throw Imath::ZeroScaleExc ("Cannot remove zero scaling "
+ "from matrix.");
+ else
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathPlane.h b/Source/OpenEXR/Imath/ImathPlane.h
new file mode 100644
index 0000000..aa59e3c
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathPlane.h
@@ -0,0 +1,256 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHPLANE_H
+#define INCLUDED_IMATHPLANE_H
+
+//----------------------------------------------------------------------
+//
+// template class Plane3
+//
+// The Imath::Plane3<> class represents a half space, so the
+// normal may point either towards or away from origin. The
+// plane P can be represented by Imath::Plane3 as either p or -p
+// corresponding to the two half-spaces on either side of the
+// plane. Any function which computes a distance will return
+// either negative or positive values for the distance indicating
+// which half-space the point is in. Note that reflection, and
+// intersection functions will operate as expected.
+//
+//----------------------------------------------------------------------
+
+#include "ImathVec.h"
+#include "ImathLine.h"
+
+namespace Imath {
+
+
+template <class T>
+class Plane3
+{
+ public:
+
+ Vec3<T> normal;
+ T distance;
+
+ Plane3() {}
+ Plane3(const Vec3<T> &normal, T distance);
+ Plane3(const Vec3<T> &point, const Vec3<T> &normal);
+ Plane3(const Vec3<T> &point1,
+ const Vec3<T> &point2,
+ const Vec3<T> &point3);
+
+ //----------------------
+ // Various set methods
+ //----------------------
+
+ void set(const Vec3<T> &normal,
+ T distance);
+
+ void set(const Vec3<T> &point,
+ const Vec3<T> &normal);
+
+ void set(const Vec3<T> &point1,
+ const Vec3<T> &point2,
+ const Vec3<T> &point3 );
+
+ //----------------------
+ // Utilities
+ //----------------------
+
+ bool intersect(const Line3<T> &line,
+ Vec3<T> &intersection) const;
+
+ bool intersectT(const Line3<T> &line,
+ T &parameter) const;
+
+ T distanceTo(const Vec3<T> &) const;
+
+ Vec3<T> reflectPoint(const Vec3<T> &) const;
+ Vec3<T> reflectVector(const Vec3<T> &) const;
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+typedef Plane3<float> Plane3f;
+typedef Plane3<double> Plane3d;
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+inline Plane3<T>::Plane3(const Vec3<T> &p0,
+ const Vec3<T> &p1,
+ const Vec3<T> &p2)
+{
+ set(p0,p1,p2);
+}
+
+template <class T>
+inline Plane3<T>::Plane3(const Vec3<T> &n, T d)
+{
+ set(n, d);
+}
+
+template <class T>
+inline Plane3<T>::Plane3(const Vec3<T> &p, const Vec3<T> &n)
+{
+ set(p, n);
+}
+
+template <class T>
+inline void Plane3<T>::set(const Vec3<T>& point1,
+ const Vec3<T>& point2,
+ const Vec3<T>& point3)
+{
+ normal = (point2 - point1) % (point3 - point1);
+ normal.normalize();
+ distance = normal ^ point1;
+}
+
+template <class T>
+inline void Plane3<T>::set(const Vec3<T>& point, const Vec3<T>& n)
+{
+ normal = n;
+ normal.normalize();
+ distance = normal ^ point;
+}
+
+template <class T>
+inline void Plane3<T>::set(const Vec3<T>& n, T d)
+{
+ normal = n;
+ normal.normalize();
+ distance = d;
+}
+
+template <class T>
+inline T Plane3<T>::distanceTo(const Vec3<T> &point) const
+{
+ return (point ^ normal) - distance;
+}
+
+template <class T>
+inline Vec3<T> Plane3<T>::reflectPoint(const Vec3<T> &point) const
+{
+ return normal * distanceTo(point) * -2.0 + point;
+}
+
+
+template <class T>
+inline Vec3<T> Plane3<T>::reflectVector(const Vec3<T> &v) const
+{
+ return normal * (normal ^ v) * 2.0 - v;
+}
+
+
+template <class T>
+inline bool Plane3<T>::intersect(const Line3<T>& line, Vec3<T>& point) const
+{
+ T d = normal ^ line.dir;
+ if ( d == 0.0 ) return false;
+ T t = - ((normal ^ line.pos) - distance) / d;
+ point = line(t);
+ return true;
+}
+
+template <class T>
+inline bool Plane3<T>::intersectT(const Line3<T>& line, T &t) const
+{
+ T d = normal ^ line.dir;
+ if ( d == 0.0 ) return false;
+ t = - ((normal ^ line.pos) - distance) / d;
+ return true;
+}
+
+template<class T>
+std::ostream &operator<< (std::ostream &o, const Plane3<T> &plane)
+{
+ return o << "(" << plane.normal << ", " << plane.distance
+ << ")";
+}
+
+template<class T>
+Plane3<T> operator* (const Plane3<T> &plane, const Matrix44<T> &M)
+{
+ // T
+ // -1
+ // Could also compute M but that would suck.
+ //
+
+ Vec3<T> dir1 = Vec3<T> (1, 0, 0) % plane.normal;
+ T dir1Len = dir1 ^ dir1;
+
+ Vec3<T> tmp = Vec3<T> (0, 1, 0) % plane.normal;
+ T tmpLen = tmp ^ tmp;
+
+ if (tmpLen > dir1Len)
+ {
+ dir1 = tmp;
+ dir1Len = tmpLen;
+ }
+
+ tmp = Vec3<T> (0, 0, 1) % plane.normal;
+ tmpLen = tmp ^ tmp;
+
+ if (tmpLen > dir1Len)
+ {
+ dir1 = tmp;
+ }
+
+ Vec3<T> dir2 = dir1 % plane.normal;
+ Vec3<T> point = plane.distance * plane.normal;
+
+ return Plane3<T> ( point * M,
+ (point + dir2) * M,
+ (point + dir1) * M );
+}
+
+template<class T>
+Plane3<T> operator- (const Plane3<T> &plane)
+{
+ return Plane3<T>(-plane.normal,-plane.distance);
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathPlatform.h b/Source/OpenEXR/Imath/ImathPlatform.h
new file mode 100644
index 0000000..d542265
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathPlatform.h
@@ -0,0 +1,92 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHPLATFORM_H
+#define INCLUDED_IMATHPLATFORM_H
+
+//----------------------------------------------------------------------------
+//
+// ImathPlatform.h
+//
+// This file contains functions and constants which aren't
+// provided by the system libraries, compilers, or includes on
+// certain platforms.
+//----------------------------------------------------------------------------
+
+#include <math.h>
+
+#if defined _WIN32 || defined _WIN64
+ #ifndef M_PI
+ #define M_PI 3.14159265358979323846
+ #endif
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Fixes for the "restrict" keyword. These #ifdef's for detecting
+// compiler versions courtesy of Boost's select_compiler_config.hpp;
+// here is the copyright notice for that file:
+//
+// (C) Copyright Boost.org 2001. Permission to copy, use, modify, sell and
+// and distribute this software is granted provided this copyright notice
+// appears in all copies. This software is provided "as is" without express
+// or implied warranty, and with no claim as to its suitability for any
+// purpose.
+//
+// Some compilers support "restrict", in which case we do nothing.
+// Other compilers support some variant of it (e.g. "__restrict").
+// If we don't know anything about the compiler, we define "restrict"
+// to be a no-op.
+//
+//-----------------------------------------------------------------------------
+
+#if defined __GNUC__
+ #if !defined(restrict)
+ #define restrict __restrict
+ #endif
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC)
+ // supports restrict, do nothing.
+
+#elif defined __sgi
+ // supports restrict, do nothing.
+
+#else
+ #define restrict
+
+#endif
+
+#endif // INCLUDED_IMATHPLATFORM_H
diff --git a/Source/OpenEXR/Imath/ImathQuat.h b/Source/OpenEXR/Imath/ImathQuat.h
new file mode 100644
index 0000000..dd3408c
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathQuat.h
@@ -0,0 +1,736 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHQUAT_H
+#define INCLUDED_IMATHQUAT_H
+
+//----------------------------------------------------------------------
+//
+// template class Quat<T>
+//
+// "Quaternions came from Hamilton ... and have been an unmixed
+// evil to those who have touched them in any way. Vector is a
+// useless survival ... and has never been of the slightest use
+// to any creature."
+//
+// - Lord Kelvin
+//
+// This class implements the quaternion numerical type -- you
+// will probably want to use this class to represent orientations
+// in R3 and to convert between various euler angle reps. You
+// should probably use Imath::Euler<> for that.
+//
+//----------------------------------------------------------------------
+
+#include "ImathExc.h"
+#include "ImathMatrix.h"
+
+#include <iostream>
+
+namespace Imath {
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// Disable MS VC++ warnings about conversion from double to float
+#pragma warning(disable:4244)
+#endif
+
+template <class T>
+class Quat;
+
+template<class T>
+Quat<T> slerp (const Quat<T> &q1,const Quat<T> &q2, T t);
+
+template<class T>
+Quat<T> squad (const Quat<T> &q1,const Quat<T> &q2,
+ const Quat<T> &qa,const Quat<T> &qb, T t);
+
+template<class T>
+void intermediate (const Quat<T> &q0, const Quat<T> &q1,
+ const Quat<T> &q2, const Quat<T> &q3,
+ Quat<T> &qa, Quat<T> &qb);
+
+template <class T>
+class Quat
+{
+ public:
+
+ T r; // real part
+ Vec3<T> v; // imaginary vector
+
+ //-----------------------------------------------------
+ // Constructors - default constructor is identity quat
+ //-----------------------------------------------------
+
+ Quat() : r(1), v(0,0,0) {}
+
+ template <class S>
+ Quat( const Quat<S>& q) : r(q.r), v(q.v) {}
+
+ Quat( T s, T i, T j, T k ) : r(s), v(i,j,k) {}
+
+ Quat( T s, Vec3<T> d ) : r(s), v(d) {}
+
+ static Quat<T> identity() { return Quat<T>(); }
+
+ //------------------------------------------------
+ // Basic Algebra - Operators and Methods
+ // The operator return values are *NOT* normalized
+ //
+ // operator^ is 4D dot product
+ // operator/ uses the inverse() quaternion
+ // operator~ is conjugate -- if (S+V) is quat then
+ // the conjugate (S+V)* == (S-V)
+ //
+ // some operators (*,/,*=,/=) treat the quat as
+ // a 4D vector when one of the operands is scalar
+ //------------------------------------------------
+
+ const Quat<T>& operator= (const Quat<T>&);
+ const Quat<T>& operator*= (const Quat<T>&);
+ const Quat<T>& operator*= (T);
+ const Quat<T>& operator/= (const Quat<T>&);
+ const Quat<T>& operator/= (T);
+ const Quat<T>& operator+= (const Quat<T>&);
+ const Quat<T>& operator-= (const Quat<T>&);
+ T& operator[] (int index); // as 4D vector
+ T operator[] (int index) const;
+
+ template <class S> bool operator == (const Quat<S> &q) const;
+ template <class S> bool operator != (const Quat<S> &q) const;
+
+ Quat<T>& invert(); // this -> 1 / this
+ Quat<T> inverse() const;
+ Quat<T>& normalize(); // returns this
+ Quat<T> normalized() const;
+ T length() const; // in R4
+
+ //-----------------------
+ // Rotation conversion
+ //-----------------------
+
+ Quat<T>& setAxisAngle(const Vec3<T>& axis, T radians);
+ Quat<T>& setRotation(const Vec3<T>& fromDirection,
+ const Vec3<T>& toDirection);
+
+ T angle() const;
+ Vec3<T> axis() const;
+
+ Matrix33<T> toMatrix33() const;
+ Matrix44<T> toMatrix44() const;
+
+ Quat<T> log() const;
+ Quat<T> exp() const;
+
+ private:
+
+ void setRotationInternal (const Vec3<T>& f0,
+ const Vec3<T>& t0,
+ Quat<T> &q);
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+typedef Quat<float> Quatf;
+typedef Quat<double> Quatd;
+
+
+//---------------
+// Implementation
+//---------------
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator= (const Quat<T>& q)
+{
+ r = q.r;
+ v = q.v;
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator*= (const Quat<T>& q)
+{
+ T rtmp = r * q.r - (v ^ q.v);
+ v = r * q.v + v * q.r + v % q.v;
+ r = rtmp;
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator*= (T t)
+{
+ r *= t;
+ v *= t;
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator/= (const Quat<T>& q)
+{
+ *this = *this * q.inverse();
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator/= (T t)
+{
+ r /= t;
+ v /= t;
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator+= (const Quat<T>& q)
+{
+ r += q.r;
+ v += q.v;
+ return *this;
+}
+
+template<class T>
+inline const Quat<T>& Quat<T>::operator-= (const Quat<T>& q)
+{
+ r -= q.r;
+ v -= q.v;
+ return *this;
+}
+template<class T>
+inline T& Quat<T>::operator[] (int index)
+{
+ return index ? v[index-1] : r;
+}
+
+template<class T>
+inline T Quat<T>::operator[] (int index) const
+{
+ return index ? v[index-1] : r;
+}
+
+template <class T>
+template <class S>
+inline bool
+Quat<T>::operator == (const Quat<S> &q) const
+{
+ return r == q.r && v == q.v;
+}
+
+template <class T>
+template <class S>
+inline bool
+Quat<T>::operator != (const Quat<S> &q) const
+{
+ return r != q.r || v != q.v;
+}
+
+template<class T>
+inline T operator^ (const Quat<T>& q1,const Quat<T>& q2)
+{
+ return q1.r * q2.r + (q1.v ^ q2.v);
+}
+
+template <class T>
+inline T Quat<T>::length() const
+{
+ return Math<T>::sqrt( r * r + (v ^ v) );
+}
+
+template <class T>
+inline Quat<T>& Quat<T>::normalize()
+{
+ if ( T l = length() ) { r /= l; v /= l; }
+ else { r = 1; v = Vec3<T>(0); }
+ return *this;
+}
+
+template <class T>
+inline Quat<T> Quat<T>::normalized() const
+{
+ if ( T l = length() ) return Quat( r / l, v / l );
+ return Quat();
+}
+
+template<class T>
+inline Quat<T> Quat<T>::inverse() const
+{
+ // 1 Q*
+ // - = ---- where Q* is conjugate (operator~)
+ // Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
+
+ T qdot = *this ^ *this;
+ return Quat( r / qdot, -v / qdot );
+}
+
+template<class T>
+inline Quat<T>& Quat<T>::invert()
+{
+ T qdot = (*this) ^ (*this);
+ r /= qdot;
+ v = -v / qdot;
+ return *this;
+}
+
+
+template<class T>
+T
+angle4D (const Quat<T> &q1, const Quat<T> &q2)
+{
+ //
+ // Compute the angle between two quaternions,
+ // interpreting the quaternions as 4D vectors.
+ //
+
+ Quat<T> d = q1 - q2;
+ T lengthD = Math<T>::sqrt (d ^ d);
+
+ Quat<T> s = q1 + q2;
+ T lengthS = Math<T>::sqrt (s ^ s);
+
+ return 2 * Math<T>::atan2 (lengthD, lengthS);
+}
+
+
+template<class T>
+Quat<T>
+slerp(const Quat<T> &q1,const Quat<T> &q2, T t)
+{
+ //
+ // Spherical linear interpolation.
+ // Assumes q1 and q2 are normalized and that q1 != -q2.
+ //
+ // This method does *not* interpolate along the shortest
+ // arc between q1 and q2. If you desire interpolation
+ // along the shortest arc, and q1^q2 is negative, then
+ // consider flipping the second quaternion explicitly.
+ //
+ // The implementation of squad() depends on a slerp()
+ // that interpolates as is, without the automatic
+ // flipping.
+ //
+ // Don Hatch explains the method we use here on his
+ // web page, The Right Way to Calculate Stuff, at
+ // http://www.plunk.org/~hatch/rightway.php
+ //
+
+ T a = angle4D (q1, q2);
+ T s = 1 - t;
+
+ Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
+ sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
+
+ return q.normalized();
+}
+
+
+template<class T>
+Quat<T> spline(const Quat<T> &q0, const Quat<T> &q1,
+ const Quat<T> &q2, const Quat<T> &q3,
+ T t)
+{
+ // Spherical Cubic Spline Interpolation -
+ // from Advanced Animation and Rendering
+ // Techniques by Watt and Watt, Page 366:
+ // A spherical curve is constructed using three
+ // spherical linear interpolations of a quadrangle
+ // of unit quaternions: q1, qa, qb, q2.
+ // Given a set of quaternion keys: q0, q1, q2, q3,
+ // this routine does the interpolation between
+ // q1 and q2 by constructing two intermediate
+ // quaternions: qa and qb. The qa and qb are
+ // computed by the intermediate function to
+ // guarantee the continuity of tangents across
+ // adjacent cubic segments. The qa represents in-tangent
+ // for q1 and the qb represents the out-tangent for q2.
+ //
+ // The q1 q2 is the cubic segment being interpolated.
+ // The q0 is from the previous adjacent segment and q3 is
+ // from the next adjacent segment. The q0 and q3 are used
+ // in computing qa and qb.
+ //
+
+ Quat<T> qa = intermediate (q0, q1, q2);
+ Quat<T> qb = intermediate (q1, q2, q3);
+ Quat<T> result = squad(q1, qa, qb, q2, t);
+
+ return result;
+}
+
+template<class T>
+Quat<T> squad(const Quat<T> &q1, const Quat<T> &qa,
+ const Quat<T> &qb, const Quat<T> &q2,
+ T t)
+{
+ // Spherical Quadrangle Interpolation -
+ // from Advanced Animation and Rendering
+ // Techniques by Watt and Watt, Page 366:
+ // It constructs a spherical cubic interpolation as
+ // a series of three spherical linear interpolations
+ // of a quadrangle of unit quaternions.
+ //
+
+ Quat<T> r1 = slerp(q1, q2, t);
+ Quat<T> r2 = slerp(qa, qb, t);
+ Quat<T> result = slerp(r1, r2, 2*t*(1-t));
+
+ return result;
+}
+
+template<class T>
+Quat<T> intermediate(const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2)
+{
+ // From advanced Animation and Rendering
+ // Techniques by Watt and Watt, Page 366:
+ // computing the inner quadrangle
+ // points (qa and qb) to guarantee tangent
+ // continuity.
+ //
+ Quat<T> q1inv = q1.inverse();
+ Quat<T> c1 = q1inv*q2;
+ Quat<T> c2 = q1inv*q0;
+ Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log());
+ Quat<T> qa = q1 * c3.exp();
+ qa.normalize();
+ return qa;
+}
+
+template <class T>
+inline Quat<T> Quat<T>::log() const
+{
+ //
+ // For unit quaternion, from Advanced Animation and
+ // Rendering Techniques by Watt and Watt, Page 366:
+ //
+
+ T theta = Math<T>::acos (std::min (r, (T) 1.0));
+
+ if (theta == 0)
+ return Quat<T> (0, v);
+
+ T sintheta = Math<T>::sin (theta);
+
+ T k;
+ if (abs (sintheta) < 1 && abs (theta) >= limits<T>::max() * abs (sintheta))
+ k = 1;
+ else
+ k = theta / sintheta;
+
+ return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k);
+}
+
+template <class T>
+inline Quat<T> Quat<T>::exp() const
+{
+ //
+ // For pure quaternion (zero scalar part):
+ // from Advanced Animation and Rendering
+ // Techniques by Watt and Watt, Page 366:
+ //
+
+ T theta = v.length();
+ T sintheta = Math<T>::sin (theta);
+
+ T k;
+ if (abs (theta) < 1 && abs (sintheta) >= limits<T>::max() * abs (theta))
+ k = 1;
+ else
+ k = sintheta / theta;
+
+ T costheta = Math<T>::cos (theta);
+
+ return Quat<T> (costheta, v.x * k, v.y * k, v.z * k);
+}
+
+template <class T>
+inline T Quat<T>::angle() const
+{
+ return 2.0*Math<T>::acos(r);
+}
+
+template <class T>
+inline Vec3<T> Quat<T>::axis() const
+{
+ return v.normalized();
+}
+
+template <class T>
+inline Quat<T>& Quat<T>::setAxisAngle(const Vec3<T>& axis, T radians)
+{
+ r = Math<T>::cos(radians/2);
+ v = axis.normalized() * Math<T>::sin(radians/2);
+ return *this;
+}
+
+
+template <class T>
+Quat<T>&
+Quat<T>::setRotation(const Vec3<T>& from, const Vec3<T>& to)
+{
+ //
+ // Create a quaternion that rotates vector from into vector to,
+ // such that the rotation is around an axis that is the cross
+ // product of from and to.
+ //
+ // This function calls function setRotationInternal(), which is
+ // numerically accurate only for rotation angles that are not much
+ // greater than pi/2. In order to achieve good accuracy for angles
+ // greater than pi/2, we split large angles in half, and rotate in
+ // two steps.
+ //
+
+ //
+ // Normalize from and to, yielding f0 and t0.
+ //
+
+ Vec3<T> f0 = from.normalized();
+ Vec3<T> t0 = to.normalized();
+
+ if ((f0 ^ t0) >= 0)
+ {
+ //
+ // The rotation angle is less than or equal to pi/2.
+ //
+
+ setRotationInternal (f0, t0, *this);
+ }
+ else
+ {
+ //
+ // The angle is greater than pi/2. After computing h0,
+ // which is halfway between f0 and t0, we rotate first
+ // from f0 to h0, then from h0 to t0.
+ //
+
+ Vec3<T> h0 = (f0 + t0).normalized();
+
+ if ((h0 ^ h0) != 0)
+ {
+ setRotationInternal (f0, h0, *this);
+
+ Quat<T> q;
+ setRotationInternal (h0, t0, q);
+
+ *this *= q;
+ }
+ else
+ {
+ //
+ // f0 and t0 point in exactly opposite directions.
+ // Pick an arbitrary axis that is orthogonal to f0,
+ // and rotate by pi.
+ //
+
+ r = T (0);
+
+ Vec3<T> f02 = f0 * f0;
+
+ if (f02.x <= f02.y && f02.x <= f02.z)
+ v = (f0 % Vec3<T> (1, 0, 0)).normalized();
+ else if (f02.y <= f02.z)
+ v = (f0 % Vec3<T> (0, 1, 0)).normalized();
+ else
+ v = (f0 % Vec3<T> (0, 0, 1)).normalized();
+ }
+ }
+
+ return *this;
+}
+
+
+template <class T>
+void
+Quat<T>::setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T> &q)
+{
+ //
+ // The following is equivalent to setAxisAngle(n,2*phi),
+ // where the rotation axis, is orthogonal to the f0 and
+ // t0 vectors, and 2*phi is the angle between f0 and t0.
+ //
+ // This function is called by setRotation(), above; it assumes
+ // that f0 and t0 are normalized and that the angle between
+ // them is not much greater than pi/2. This function becomes
+ // numerically inaccurate if f0 and t0 point into nearly
+ // opposite directions.
+ //
+
+ //
+ // Find a normalized vector, h0, that is half way between f0 and t0.
+ // The angle between f0 and h0 is phi.
+ //
+
+ Vec3<T> h0 = (f0 + t0).normalized();
+
+ //
+ // Store the rotation axis and rotation angle.
+ //
+
+ q.r = f0 ^ h0; // f0 ^ h0 == cos (phi)
+ q.v = f0 % h0; // (f0 % h0).length() == sin (phi)
+}
+
+
+template<class T>
+Matrix33<T> Quat<T>::toMatrix33() const
+{
+ return Matrix33<T>(1. - 2.0 * (v.y * v.y + v.z * v.z),
+ 2.0 * (v.x * v.y + v.z * r),
+ 2.0 * (v.z * v.x - v.y * r),
+
+ 2.0 * (v.x * v.y - v.z * r),
+ 1. - 2.0 * (v.z * v.z + v.x * v.x),
+ 2.0 * (v.y * v.z + v.x * r),
+
+ 2.0 * (v.z * v.x + v.y * r),
+ 2.0 * (v.y * v.z - v.x * r),
+ 1. - 2.0 * (v.y * v.y + v.x * v.x));
+}
+
+template<class T>
+Matrix44<T> Quat<T>::toMatrix44() const
+{
+ return Matrix44<T>(1. - 2.0 * (v.y * v.y + v.z * v.z),
+ 2.0 * (v.x * v.y + v.z * r),
+ 2.0 * (v.z * v.x - v.y * r),
+ 0.,
+ 2.0 * (v.x * v.y - v.z * r),
+ 1. - 2.0 * (v.z * v.z + v.x * v.x),
+ 2.0 * (v.y * v.z + v.x * r),
+ 0.,
+ 2.0 * (v.z * v.x + v.y * r),
+ 2.0 * (v.y * v.z - v.x * r),
+ 1. - 2.0 * (v.y * v.y + v.x * v.x),
+ 0.,
+ 0.,
+ 0.,
+ 0.,
+ 1.0 );
+}
+
+
+template<class T>
+inline Matrix33<T> operator* (const Matrix33<T> &M, const Quat<T> &q)
+{
+ return M * q.toMatrix33();
+}
+
+template<class T>
+inline Matrix33<T> operator* (const Quat<T> &q, const Matrix33<T> &M)
+{
+ return q.toMatrix33() * M;
+}
+
+template<class T>
+std::ostream& operator<< (std::ostream &o, const Quat<T> &q)
+{
+ return o << "(" << q.r
+ << " " << q.v.x
+ << " " << q.v.y
+ << " " << q.v.z
+ << ")";
+
+}
+
+template<class T>
+inline Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2)
+{
+ // (S1+V1) (S2+V2) = S1 S2 - V1.V2 + S1 V2 + V1 S2 + V1 x V2
+ return Quat<T>( q1.r * q2.r - (q1.v ^ q2.v),
+ q1.r * q2.v + q1.v * q2.r + q1.v % q2.v );
+}
+
+template<class T>
+inline Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2)
+{
+ return q1 * q2.inverse();
+}
+
+template<class T>
+inline Quat<T> operator/ (const Quat<T>& q,T t)
+{
+ return Quat<T>(q.r/t,q.v/t);
+}
+
+template<class T>
+inline Quat<T> operator* (const Quat<T>& q,T t)
+{
+ return Quat<T>(q.r*t,q.v*t);
+}
+
+template<class T>
+inline Quat<T> operator* (T t, const Quat<T>& q)
+{
+ return Quat<T>(q.r*t,q.v*t);
+}
+
+template<class T>
+inline Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2)
+{
+ return Quat<T>( q1.r + q2.r, q1.v + q2.v );
+}
+
+template<class T>
+inline Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2)
+{
+ return Quat<T>( q1.r - q2.r, q1.v - q2.v );
+}
+
+template<class T>
+inline Quat<T> operator~ (const Quat<T>& q)
+{
+ return Quat<T>( q.r, -q.v ); // conjugate: (S+V)* = S-V
+}
+
+template<class T>
+inline Quat<T> operator- (const Quat<T>& q)
+{
+ return Quat<T>( -q.r, -q.v );
+}
+
+template<class T>
+inline Vec3<T> operator* (const Vec3<T>& v, const Quat<T>& q)
+{
+ Vec3<T> a = q.v % v;
+ Vec3<T> b = q.v % a;
+ return v + T (2) * (q.r * a + b);
+}
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(default:4244)
+#endif
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathRandom.cpp b/Source/OpenEXR/Imath/ImathRandom.cpp
new file mode 100644
index 0000000..20a67ca
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathRandom.cpp
@@ -0,0 +1,195 @@
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+//
+// Routines that generate pseudo-random numbers compatible
+// with the standard erand48(), nrand48(), etc. functions.
+//
+//-----------------------------------------------------------------------------
+
+#include "ImathRandom.h"
+#include "ImathInt64.h"
+
+namespace Imath {
+namespace {
+
+//
+// Static state used by Imath::drand48(), Imath::lrand48() and Imath::srand48()
+//
+
+unsigned short staticState[3] = {0, 0, 0};
+
+
+void
+rand48Next (unsigned short state[3])
+{
+ //
+ // drand48() and friends are all based on a linear congruential
+ // sequence,
+ //
+ // x[n+1] = (a * x[n] + c) % m,
+ //
+ // where a and c are as specified below, and m == (1 << 48)
+ //
+
+ static const Int64 a = Int64 (0x5deece66dLL);
+ static const Int64 c = Int64 (0xbLL);
+
+ //
+ // Assemble the 48-bit value x[n] from the
+ // three 16-bit values stored in state.
+ //
+
+ Int64 x = (Int64 (state[2]) << 32) |
+ (Int64 (state[1]) << 16) |
+ Int64 (state[0]);
+
+ //
+ // Compute x[n+1], except for the "modulo m" part.
+ //
+
+ x = a * x + c;
+
+ //
+ // Disassemble the 48 least significant bits of x[n+1] into
+ // three 16-bit values. Discard the 16 most significant bits;
+ // this takes care of the "modulo m" operation.
+ //
+ // We assume that sizeof (unsigned short) == 2.
+ //
+
+ state[2] = x >> 32;
+ state[1] = x >> 16;
+ state[0] = x;
+}
+
+} // namespace
+
+
+double
+erand48 (unsigned short state[3])
+{
+ //
+ // Generate double-precision floating-point values between 0.0 and 1.0:
+ //
+ // The exponent is set to 0x3ff, which indicates a value greater
+ // than or equal to 1.0, and less than 2.0. The 48 most significant
+ // bits of the significand (mantissa) are filled with pseudo-random
+ // bits generated by rand48Next(). The remaining 4 bits are a copy
+ // of the 4 most significant bits of the significand. This results
+ // in bit patterns between 0x3ff0000000000000 and 0x3fffffffffffffff,
+ // which correspond to uniformly distributed floating-point values
+ // between 1.0 and 1.99999999999999978. Subtracting 1.0 from those
+ // values produces numbers between 0.0 and 0.99999999999999978, that
+ // is, between 0.0 and 1.0-DBL_EPSILON.
+ //
+
+ rand48Next (state);
+
+ union {double d; Int64 i;} u;
+
+ u.i = (Int64 (0x3ff) << 52) | // sign and exponent
+ (Int64 (state[2]) << 36) | // significand
+ (Int64 (state[1]) << 20) |
+ (Int64 (state[0]) << 4) |
+ (Int64 (state[2]) >> 12);
+
+ return u.d - 1;
+}
+
+
+double
+drand48 ()
+{
+ return Imath::erand48 (staticState);
+}
+
+
+long int
+nrand48 (unsigned short state[3])
+{
+ //
+ // Generate uniformly distributed integers between 0 and 0x7fffffff.
+ //
+
+ rand48Next (state);
+
+ return ((long int) (state[2]) << 15) |
+ ((long int) (state[1]) >> 1);
+}
+
+
+long int
+lrand48 ()
+{
+ return Imath::nrand48 (staticState);
+}
+
+
+void
+srand48 (long int seed)
+{
+ staticState[2] = seed >> 16;
+ staticState[1] = seed;
+ staticState[0] = 0x330e;
+}
+
+
+float
+Rand32::nextf ()
+{
+ //
+ // Generate single-precision floating-point values between 0.0 and 1.0:
+ //
+ // The exponent is set to 0x7f, which indicates a value greater than
+ // or equal to 1.0, and less than 2.0. The 23 bits of the significand
+ // (mantissa) are filled with pseudo-random bits generated by
+ // Rand32::next(). This results in in bit patterns between 0x3f800000
+ // and 0x3fffffff, which correspond to uniformly distributed floating-
+ // point values between 1.0 and 1.99999988. Subtracting 1.0 from
+ // those values produces numbers between 0.0 and 0.99999988, that is,
+ // between 0.0 and 1.0-FLT_EPSILON.
+ //
+
+ next ();
+
+ union {float f; unsigned int i;} u;
+
+ u.i = 0x3f800000 | (_state & 0x7fffff);
+ return u.f - 1;
+}
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathRandom.h b/Source/OpenEXR/Imath/ImathRandom.h
new file mode 100644
index 0000000..ec51888
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathRandom.h
@@ -0,0 +1,398 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INCLUDED_IMATHRANDOM_H
+#define INCLUDED_IMATHRANDOM_H
+
+//-----------------------------------------------------------------------------
+//
+// Generators for uniformly distributed pseudo-random numbers and
+// functions that use those generators to generate numbers with
+// non-uniform distributions:
+//
+// class Rand32
+// class Rand48
+// solidSphereRand()
+// hollowSphereRand()
+// gaussRand()
+// gaussSphereRand()
+//
+// Note: class Rand48() calls erand48() and nrand48(), which are not
+// available on all operating systems. For compatibility we include
+// our own versions of erand48() and nrand48(). Our functions have
+// been reverse-engineered from the corresponding Unix/Linux man page.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <math.h>
+
+namespace Imath {
+
+//-----------------------------------------------
+// Fast random-number generator that generates
+// a uniformly distributed sequence with a period
+// length of 2^32.
+//-----------------------------------------------
+
+class Rand32
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ Rand32 (unsigned long int seed = 0);
+
+
+ //--------------------------------
+ // Re-initialize with a given seed
+ //--------------------------------
+
+ void init (unsigned long int seed);
+
+
+ //----------------------------------------------------------
+ // Get the next value in the sequence (range: [false, true])
+ //----------------------------------------------------------
+
+ bool nextb ();
+
+
+ //---------------------------------------------------------------
+ // Get the next value in the sequence (range: [0 ... 0xffffffff])
+ //---------------------------------------------------------------
+
+ unsigned long int nexti ();
+
+
+ //------------------------------------------------------
+ // Get the next value in the sequence (range: [0 ... 1[)
+ //------------------------------------------------------
+
+ float nextf ();
+
+
+ //-------------------------------------------------------------------
+ // Get the next value in the sequence (range [rangeMin ... rangeMax[)
+ //-------------------------------------------------------------------
+
+ float nextf (float rangeMin, float rangeMax);
+
+
+ private:
+
+ void next ();
+
+ unsigned long int _state;
+};
+
+
+//--------------------------------------------------------
+// Random-number generator based on the C Standard Library
+// functions erand48(), nrand48() & company; generates a
+// uniformly distributed sequence.
+//--------------------------------------------------------
+
+class Rand48
+{
+ public:
+
+ //------------
+ // Constructor
+ //------------
+
+ Rand48 (unsigned long int seed = 0);
+
+
+ //--------------------------------
+ // Re-initialize with a given seed
+ //--------------------------------
+
+ void init (unsigned long int seed);
+
+
+ //----------------------------------------------------------
+ // Get the next value in the sequence (range: [false, true])
+ //----------------------------------------------------------
+
+ bool nextb ();
+
+
+ //---------------------------------------------------------------
+ // Get the next value in the sequence (range: [0 ... 0x7fffffff])
+ //---------------------------------------------------------------
+
+ long int nexti ();
+
+
+ //------------------------------------------------------
+ // Get the next value in the sequence (range: [0 ... 1[)
+ //------------------------------------------------------
+
+ double nextf ();
+
+
+ //-------------------------------------------------------------------
+ // Get the next value in the sequence (range [rangeMin ... rangeMax[)
+ //-------------------------------------------------------------------
+
+ double nextf (double rangeMin, double rangeMax);
+
+
+ private:
+
+ unsigned short int _state[3];
+};
+
+
+//------------------------------------------------------------
+// Return random points uniformly distributed in a sphere with
+// radius 1 around the origin (distance from origin <= 1).
+//------------------------------------------------------------
+
+template <class Vec, class Rand>
+Vec
+solidSphereRand (Rand &rand);
+
+
+//-------------------------------------------------------------
+// Return random points uniformly distributed on the surface of
+// a sphere with radius 1 around the origin.
+//-------------------------------------------------------------
+
+template <class Vec, class Rand>
+Vec
+hollowSphereRand (Rand &rand);
+
+
+//-----------------------------------------------
+// Return random numbers with a normal (Gaussian)
+// distribution with zero mean and unit variance.
+//-----------------------------------------------
+
+template <class Rand>
+float
+gaussRand (Rand &rand);
+
+
+//----------------------------------------------------
+// Return random points whose distance from the origin
+// has a normal (Gaussian) distribution with zero mean
+// and unit variance.
+//----------------------------------------------------
+
+template <class Vec, class Rand>
+Vec
+gaussSphereRand (Rand &rand);
+
+
+//---------------------------------
+// erand48(), nrand48() and friends
+//---------------------------------
+
+double erand48 (unsigned short state[3]);
+double drand48 ();
+long int nrand48 (unsigned short state[3]);
+long int lrand48 ();
+void srand48 (long int seed);
+
+
+//---------------
+// Implementation
+//---------------
+
+
+inline void
+Rand32::init (unsigned long int seed)
+{
+ _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
+}
+
+
+inline
+Rand32::Rand32 (unsigned long int seed)
+{
+ init (seed);
+}
+
+
+inline void
+Rand32::next ()
+{
+ _state = 1664525L * _state + 1013904223L;
+}
+
+
+inline bool
+Rand32::nextb ()
+{
+ next ();
+ // Return the 31st (most significant) bit, by and-ing with 2 ^ 31.
+ return !!(_state & 2147483648UL);
+}
+
+
+inline unsigned long int
+Rand32::nexti ()
+{
+ next ();
+ return _state & 0xffffffff;
+}
+
+
+inline float
+Rand32::nextf (float rangeMin, float rangeMax)
+{
+ float f = nextf();
+ return rangeMin * (1 - f) + rangeMax * f;
+}
+
+
+inline void
+Rand48::init (unsigned long int seed)
+{
+ seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
+
+ _state[0] = (unsigned short int) (seed);
+ _state[1] = (unsigned short int) (seed >> 16);
+ _state[2] = (unsigned short int) (seed);
+}
+
+
+inline
+Rand48::Rand48 (unsigned long int seed)
+{
+ init (seed);
+}
+
+
+inline bool
+Rand48::nextb ()
+{
+ return Imath::nrand48 (_state) & 1;
+}
+
+
+inline long int
+Rand48::nexti ()
+{
+ return Imath::nrand48 (_state);
+}
+
+
+inline double
+Rand48::nextf ()
+{
+ return Imath::erand48 (_state);
+}
+
+
+inline double
+Rand48::nextf (double rangeMin, double rangeMax)
+{
+ double f = nextf();
+ return rangeMin * (1 - f) + rangeMax * f;
+}
+
+
+template <class Vec, class Rand>
+Vec
+solidSphereRand (Rand &rand)
+{
+ Vec v;
+
+ do
+ {
+ for (unsigned int i = 0; i < Vec::dimensions(); i++)
+ v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
+ }
+ while (v.length2() > 1);
+
+ return v;
+}
+
+
+template <class Vec, class Rand>
+Vec
+hollowSphereRand (Rand &rand)
+{
+ Vec v;
+ typename Vec::BaseType length;
+
+ do
+ {
+ for (unsigned int i = 0; i < Vec::dimensions(); i++)
+ v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
+
+ length = v.length();
+ }
+ while (length > 1 || length == 0);
+
+ return v / length;
+}
+
+
+template <class Rand>
+float
+gaussRand (Rand &rand)
+{
+ float x; // Note: to avoid numerical problems with very small
+ float y; // numbers, we make these variables singe-precision
+ float length2; // floats, but later we call the double-precision log()
+ // and sqrt() functions instead of logf() and sqrtf().
+ do
+ {
+ x = float (rand.nextf (-1, 1));
+ y = float (rand.nextf (-1, 1));
+ length2 = x * x + y * y;
+ }
+ while (length2 >= 1 || length2 == 0);
+
+ return x * sqrt (-2 * log (double (length2)) / length2);
+}
+
+
+template <class Vec, class Rand>
+Vec
+gaussSphereRand (Rand &rand)
+{
+ return hollowSphereRand <Vec> (rand) * gaussRand (rand);
+}
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathRoots.h b/Source/OpenEXR/Imath/ImathRoots.h
new file mode 100644
index 0000000..a161864
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathRoots.h
@@ -0,0 +1,218 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHROOTS_H
+#define INCLUDED_IMATHROOTS_H
+
+//---------------------------------------------------------------------
+//
+// Functions to solve linear, quadratic or cubic equations
+//
+//---------------------------------------------------------------------
+
+#include <ImathMath.h>
+#include <complex>
+
+namespace Imath {
+
+//--------------------------------------------------------------------------
+// Find the real solutions of a linear, quadratic or cubic equation:
+//
+// function equation solved
+//
+// solveLinear (a, b, x) a * x + b == 0
+// solveQuadratic (a, b, c, x) a * x*x + b * x + c == 0
+// solveNormalizedCubic (r, s, t, x) x*x*x + r * x*x + s * x + t == 0
+// solveCubic (a, b, c, d, x) a * x*x*x + b * x*x + c * x + d == 0
+//
+// Return value:
+//
+// 3 three real solutions, stored in x[0], x[1] and x[2]
+// 2 two real solutions, stored in x[0] and x[1]
+// 1 one real solution, stored in x[1]
+// 0 no real solutions
+// -1 all real numbers are solutions
+//
+// Notes:
+//
+// * It is possible that an equation has real solutions, but that the
+// solutions (or some intermediate result) are not representable.
+// In this case, either some of the solutions returned are invalid
+// (nan or infinity), or, if floating-point exceptions have been
+// enabled with Iex::mathExcOn(), an Iex::MathExc exception is
+// thrown.
+//
+// * Cubic equations are solved using Cardano's Formula; even though
+// only real solutions are produced, some intermediate results are
+// complex (std::complex<T>).
+//
+//--------------------------------------------------------------------------
+
+template <class T> int solveLinear (T a, T b, T &x);
+template <class T> int solveQuadratic (T a, T b, T c, T x[2]);
+template <class T> int solveNormalizedCubic (T r, T s, T t, T x[3]);
+template <class T> int solveCubic (T a, T b, T c, T d, T x[3]);
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+int
+solveLinear (T a, T b, T &x)
+{
+ if (a != 0)
+ {
+ x = -b / a;
+ return 1;
+ }
+ else if (b != 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+template <class T>
+int
+solveQuadratic (T a, T b, T c, T x[2])
+{
+ if (a == 0)
+ {
+ return solveLinear (b, c, x[0]);
+ }
+ else
+ {
+ T D = b * b - 4 * a * c;
+
+ if (D > 0)
+ {
+ T s = Math<T>::sqrt (D);
+
+ x[0] = (-b + s) / (2 * a);
+ x[1] = (-b - s) / (2 * a);
+ return 2;
+ }
+ if (D == 0)
+ {
+ x[0] = -b / (2 * a);
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
+
+
+template <class T>
+int
+solveNormalizedCubic (T r, T s, T t, T x[3])
+{
+ T p = (3 * s - r * r) / 3;
+ T q = 2 * r * r * r / 27 - r * s / 3 + t;
+ T p3 = p / 3;
+ T q2 = q / 2;
+ T D = p3 * p3 * p3 + q2 * q2;
+
+ if (D == 0 && p3 == 0)
+ {
+ x[0] = -r / 3;
+ x[1] = -r / 3;
+ x[2] = -r / 3;
+ return 1;
+ }
+
+ std::complex<T> u = std::pow (-q / 2 + std::sqrt (std::complex<T> (D)),
+ T (1) / T (3));
+
+ std::complex<T> v = -p / (T (3) * u);
+
+ const T sqrt3 = T (1.73205080756887729352744634150587); // enough digits
+ // for long double
+ std::complex<T> y0 (u + v);
+
+ std::complex<T> y1 (-(u + v) / T (2) +
+ (u - v) / T (2) * std::complex<T> (0, sqrt3));
+
+ std::complex<T> y2 (-(u + v) / T (2) -
+ (u - v) / T (2) * std::complex<T> (0, sqrt3));
+
+ if (D > 0)
+ {
+ x[0] = y0.real() - r / 3;
+ return 1;
+ }
+ else if (D == 0)
+ {
+ x[0] = y0.real() - r / 3;
+ x[1] = y1.real() - r / 3;
+ return 2;
+ }
+ else
+ {
+ x[0] = y0.real() - r / 3;
+ x[1] = y1.real() - r / 3;
+ x[2] = y2.real() - r / 3;
+ return 3;
+ }
+}
+
+
+template <class T>
+int
+solveCubic (T a, T b, T c, T d, T x[3])
+{
+ if (a == 0)
+ {
+ return solveQuadratic (b, c, d, x);
+ }
+ else
+ {
+ return solveNormalizedCubic (b / a, c / a, d / a, x);
+ }
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathShear.cpp b/Source/OpenEXR/Imath/ImathShear.cpp
new file mode 100644
index 0000000..72541f5
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathShear.cpp
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+
+//----------------------------------------------------------------------------
+//
+// Specializations of the Shear6<T> template.
+//
+//----------------------------------------------------------------------------
+
+#include "ImathShear.h"
+
+namespace Imath {
+
+
+
+// empty
+
+
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathShear.h b/Source/OpenEXR/Imath/ImathShear.h
new file mode 100644
index 0000000..bad40a5
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathShear.h
@@ -0,0 +1,659 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHSHEAR_H
+#define INCLUDED_IMATHSHEAR_H
+
+//----------------------------------------------------
+//
+// Shear6 class template.
+//
+//----------------------------------------------------
+
+#include "ImathExc.h"
+#include "ImathLimits.h"
+#include "ImathMath.h"
+#include "ImathVec.h"
+
+#include <iostream>
+
+
+namespace Imath {
+
+
+
+
+template <class T> class Shear6
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T xy, xz, yz, yx, zx, zy;
+
+ T & operator [] (int i);
+ const T & operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Shear6 (); // (0 0 0 0 0 0)
+ Shear6 (T XY, T XZ, T YZ); // (XY XZ YZ 0 0 0)
+ Shear6 (const Vec3<T> &v); // (v.x v.y v.z 0 0 0)
+ template <class S> // (v.x v.y v.z 0 0 0)
+ Shear6 (const Vec3<S> &v);
+ Shear6 (T XY, T XZ, T YZ, // (XY XZ YZ YX ZX ZY)
+ T YX, T ZX, T ZY);
+
+
+ //---------------------------------
+ // Copy constructors and assignment
+ //---------------------------------
+
+ Shear6 (const Shear6 &h);
+ template <class S> Shear6 (const Shear6<S> &h);
+
+ const Shear6 & operator = (const Shear6 &h);
+ template <class S>
+ const Shear6 & operator = (const Vec3<S> &v);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ template <class S>
+ void setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY);
+
+ template <class S>
+ void setValue (const Shear6<S> &h);
+
+ template <class S>
+ void getValue (S &XY, S &XZ, S &YZ,
+ S &YX, S &ZX, S &ZY) const;
+
+ template <class S>
+ void getValue (Shear6<S> &h) const;
+
+ T * getValue();
+ const T * getValue() const;
+
+
+ //---------
+ // Equality
+ //---------
+
+ template <class S>
+ bool operator == (const Shear6<S> &h) const;
+
+ template <class S>
+ bool operator != (const Shear6<S> &h) const;
+
+ //-----------------------------------------------------------------------
+ // Compare two shears and test if they are "approximately equal":
+ //
+ // equalWithAbsError (h, e)
+ //
+ // Returns true if the coefficients of this and h are the same with
+ // an absolute error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - h[i]) <= e
+ //
+ // equalWithRelError (h, e)
+ //
+ // Returns true if the coefficients of this and h are the same with
+ // a relative error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - h[i]) <= e * abs (this[i])
+ //-----------------------------------------------------------------------
+
+ bool equalWithAbsError (const Shear6<T> &h, T e) const;
+ bool equalWithRelError (const Shear6<T> &h, T e) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Shear6 & operator += (const Shear6 &h);
+ Shear6 operator + (const Shear6 &h) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Shear6 & operator -= (const Shear6 &h);
+ Shear6 operator - (const Shear6 &h) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Shear6 operator - () const;
+ const Shear6 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Shear6 & operator *= (const Shear6 &h);
+ const Shear6 & operator *= (T a);
+ Shear6 operator * (const Shear6 &h) const;
+ Shear6 operator * (T a) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Shear6 & operator /= (const Shear6 &h);
+ const Shear6 & operator /= (T a);
+ Shear6 operator / (const Shear6 &h) const;
+ Shear6 operator / (T a) const;
+
+
+ //----------------------------------------------------------
+ // Number of dimensions, i.e. number of elements in a Shear6
+ //----------------------------------------------------------
+
+ static unsigned int dimensions() {return 6;}
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+
+
+ //--------------------------------------------------------------
+ // Base type -- in templates, which accept a parameter, V, which
+ // could be either a Vec2<T> or a Shear6<T>, you can refer to T as
+ // V::BaseType
+ //--------------------------------------------------------------
+
+ typedef T BaseType;
+};
+
+
+//--------------
+// Stream output
+//--------------
+
+template <class T>
+std::ostream & operator << (std::ostream &s, const Shear6<T> &h);
+
+
+//----------------------------------------------------
+// Reverse multiplication: scalar * Shear6<T>
+//----------------------------------------------------
+
+template <class S, class T> Shear6<T> operator * (S a, const Shear6<T> &h);
+
+
+//-------------------------
+// Typedefs for convenience
+//-------------------------
+
+typedef Vec3 <float> Shear3f;
+typedef Vec3 <double> Shear3d;
+typedef Shear6 <float> Shear6f;
+typedef Shear6 <double> Shear6d;
+
+
+
+
+//-----------------------
+// Implementation of Shear6
+//-----------------------
+
+template <class T>
+inline T &
+Shear6<T>::operator [] (int i)
+{
+ return (&xy)[i];
+}
+
+template <class T>
+inline const T &
+Shear6<T>::operator [] (int i) const
+{
+ return (&xy)[i];
+}
+
+template <class T>
+inline
+Shear6<T>::Shear6 ()
+{
+ xy = xz = yz = yx = zx = zy = 0;
+}
+
+template <class T>
+inline
+Shear6<T>::Shear6 (T XY, T XZ, T YZ)
+{
+ xy = XY;
+ xz = XZ;
+ yz = YZ;
+ yx = 0;
+ zx = 0;
+ zy = 0;
+}
+
+template <class T>
+inline
+Shear6<T>::Shear6 (const Vec3<T> &v)
+{
+ xy = v.x;
+ xz = v.y;
+ yz = v.z;
+ yx = 0;
+ zx = 0;
+ zy = 0;
+}
+
+template <class T>
+template <class S>
+inline
+Shear6<T>::Shear6 (const Vec3<S> &v)
+{
+ xy = T (v.x);
+ xz = T (v.y);
+ yz = T (v.z);
+ yx = 0;
+ zx = 0;
+ zy = 0;
+}
+
+template <class T>
+inline
+Shear6<T>::Shear6 (T XY, T XZ, T YZ, T YX, T ZX, T ZY)
+{
+ xy = XY;
+ xz = XZ;
+ yz = YZ;
+ yx = YX;
+ zx = ZX;
+ zy = ZY;
+}
+
+template <class T>
+inline
+Shear6<T>::Shear6 (const Shear6 &h)
+{
+ xy = h.xy;
+ xz = h.xz;
+ yz = h.yz;
+ yx = h.yx;
+ zx = h.zx;
+ zy = h.zy;
+}
+
+template <class T>
+template <class S>
+inline
+Shear6<T>::Shear6 (const Shear6<S> &h)
+{
+ xy = T (h.xy);
+ xz = T (h.xz);
+ yz = T (h.yz);
+ yx = T (h.yx);
+ zx = T (h.zx);
+ zy = T (h.zy);
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator = (const Shear6 &h)
+{
+ xy = h.xy;
+ xz = h.xz;
+ yz = h.yz;
+ yx = h.yx;
+ zx = h.zx;
+ zy = h.zy;
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline const Shear6<T> &
+Shear6<T>::operator = (const Vec3<S> &v)
+{
+ xy = T (v.x);
+ xz = T (v.y);
+ yz = T (v.z);
+ yx = 0;
+ zx = 0;
+ zy = 0;
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline void
+Shear6<T>::setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY)
+{
+ xy = T (XY);
+ xz = T (XZ);
+ yz = T (YZ);
+ yx = T (YX);
+ zx = T (ZX);
+ zy = T (ZY);
+}
+
+template <class T>
+template <class S>
+inline void
+Shear6<T>::setValue (const Shear6<S> &h)
+{
+ xy = T (h.xy);
+ xz = T (h.xz);
+ yz = T (h.yz);
+ yx = T (h.yx);
+ zx = T (h.zx);
+ zy = T (h.zy);
+}
+
+template <class T>
+template <class S>
+inline void
+Shear6<T>::getValue (S &XY, S &XZ, S &YZ, S &YX, S &ZX, S &ZY) const
+{
+ XY = S (xy);
+ XZ = S (xz);
+ YZ = S (yz);
+ YX = S (yx);
+ ZX = S (zx);
+ ZY = S (zy);
+}
+
+template <class T>
+template <class S>
+inline void
+Shear6<T>::getValue (Shear6<S> &h) const
+{
+ h.xy = S (xy);
+ h.xz = S (xz);
+ h.yz = S (yz);
+ h.yx = S (yx);
+ h.zx = S (zx);
+ h.zy = S (zy);
+}
+
+template <class T>
+inline T *
+Shear6<T>::getValue()
+{
+ return (T *) &xy;
+}
+
+template <class T>
+inline const T *
+Shear6<T>::getValue() const
+{
+ return (const T *) &xy;
+}
+
+template <class T>
+template <class S>
+inline bool
+Shear6<T>::operator == (const Shear6<S> &h) const
+{
+ return xy == h.xy && xz == h.xz && yz == h.yz &&
+ yx == h.yx && zx == h.zx && zy == h.zy;
+}
+
+template <class T>
+template <class S>
+inline bool
+Shear6<T>::operator != (const Shear6<S> &h) const
+{
+ return xy != h.xy || xz != h.xz || yz != h.yz ||
+ yx != h.yx || zx != h.zx || zy != h.zy;
+}
+
+template <class T>
+bool
+Shear6<T>::equalWithAbsError (const Shear6<T> &h, T e) const
+{
+ for (int i = 0; i < 6; i++)
+ if (!Imath::equalWithAbsError ((*this)[i], h[i], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+Shear6<T>::equalWithRelError (const Shear6<T> &h, T e) const
+{
+ for (int i = 0; i < 6; i++)
+ if (!Imath::equalWithRelError ((*this)[i], h[i], e))
+ return false;
+
+ return true;
+}
+
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator += (const Shear6 &h)
+{
+ xy += h.xy;
+ xz += h.xz;
+ yz += h.yz;
+ yx += h.yx;
+ zx += h.zx;
+ zy += h.zy;
+ return *this;
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator + (const Shear6 &h) const
+{
+ return Shear6 (xy + h.xy, xz + h.xz, yz + h.yz,
+ yx + h.yx, zx + h.zx, zy + h.zy);
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator -= (const Shear6 &h)
+{
+ xy -= h.xy;
+ xz -= h.xz;
+ yz -= h.yz;
+ yx -= h.yx;
+ zx -= h.zx;
+ zy -= h.zy;
+ return *this;
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator - (const Shear6 &h) const
+{
+ return Shear6 (xy - h.xy, xz - h.xz, yz - h.yz,
+ yx - h.yx, zx - h.zx, zy - h.zy);
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator - () const
+{
+ return Shear6 (-xy, -xz, -yz, -yx, -zx, -zy);
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::negate ()
+{
+ xy = -xy;
+ xz = -xz;
+ yz = -yz;
+ yx = -yx;
+ zx = -zx;
+ zy = -zy;
+ return *this;
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator *= (const Shear6 &h)
+{
+ xy *= h.xy;
+ xz *= h.xz;
+ yz *= h.yz;
+ yx *= h.yx;
+ zx *= h.zx;
+ zy *= h.zy;
+ return *this;
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator *= (T a)
+{
+ xy *= a;
+ xz *= a;
+ yz *= a;
+ yx *= a;
+ zx *= a;
+ zy *= a;
+ return *this;
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator * (const Shear6 &h) const
+{
+ return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz,
+ yx * h.yx, zx * h.zx, zy * h.zy);
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator * (T a) const
+{
+ return Shear6 (xy * a, xz * a, yz * a,
+ yx * a, zx * a, zy * a);
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator /= (const Shear6 &h)
+{
+ xy /= h.xy;
+ xz /= h.xz;
+ yz /= h.yz;
+ yx /= h.yx;
+ zx /= h.zx;
+ zy /= h.zy;
+ return *this;
+}
+
+template <class T>
+inline const Shear6<T> &
+Shear6<T>::operator /= (T a)
+{
+ xy /= a;
+ xz /= a;
+ yz /= a;
+ yx /= a;
+ zx /= a;
+ zy /= a;
+ return *this;
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator / (const Shear6 &h) const
+{
+ return Shear6 (xy / h.xy, xz / h.xz, yz / h.yz,
+ yx / h.yx, zx / h.zx, zy / h.zy);
+}
+
+template <class T>
+inline Shear6<T>
+Shear6<T>::operator / (T a) const
+{
+ return Shear6 (xy / a, xz / a, yz / a,
+ yx / a, zx / a, zy / a);
+}
+
+
+//-----------------------------
+// Stream output implementation
+//-----------------------------
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Shear6<T> &h)
+{
+ return s << '('
+ << h.xy << ' ' << h.xz << ' ' << h.yz
+ << h.yx << ' ' << h.zx << ' ' << h.zy
+ << ')';
+}
+
+
+//-----------------------------------------
+// Implementation of reverse multiplication
+//-----------------------------------------
+
+template <class S, class T>
+inline Shear6<T>
+operator * (S a, const Shear6<T> &h)
+{
+ return Shear6<T> (a * h.xy, a * h.xz, a * h.yz,
+ a * h.yx, a * h.zx, a * h.zy);
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathSphere.h b/Source/OpenEXR/Imath/ImathSphere.h
new file mode 100644
index 0000000..3860701
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathSphere.h
@@ -0,0 +1,177 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHSPHERE_H
+#define INCLUDED_IMATHSPHERE_H
+
+//-------------------------------------
+//
+// A 3D sphere class template
+//
+//-------------------------------------
+
+#include "ImathVec.h"
+#include "ImathBox.h"
+#include "ImathLine.h"
+
+namespace Imath {
+
+template <class T>
+class Sphere3
+{
+ public:
+
+ Vec3<T> center;
+ T radius;
+
+ //---------------
+ // Constructors
+ //---------------
+
+ Sphere3() : center(0,0,0), radius(0) {}
+ Sphere3(const Vec3<T> &c, T r) : center(c), radius(r) {}
+
+ //-------------------------------------------------------------------
+ // Utilities:
+ //
+ // s.circumscribe(b) sets center and radius of sphere s
+ // so that the s tightly encloses box b.
+ //
+ // s.intersectT (l, t) If sphere s and line l intersect, then
+ // intersectT() computes the smallest t,
+ // t >= 0, so that l(t) is a point on the
+ // sphere. intersectT() then returns true.
+ //
+ // If s and l do not intersect, intersectT()
+ // returns false.
+ //
+ // s.intersect (l, i) If sphere s and line l intersect, then
+ // intersect() calls s.intersectT(l,t) and
+ // computes i = l(t).
+ //
+ // If s and l do not intersect, intersect()
+ // returns false.
+ //
+ //-------------------------------------------------------------------
+
+ void circumscribe(const Box<Vec3<T> > &box);
+ bool intersect(const Line3<T> &l, Vec3<T> &intersection) const;
+ bool intersectT(const Line3<T> &l, T &t) const;
+};
+
+
+//--------------------
+// Convenient typedefs
+//--------------------
+
+typedef Sphere3<float> Sphere3f;
+typedef Sphere3<double> Sphere3d;
+
+
+//---------------
+// Implementation
+//---------------
+
+template <class T>
+void Sphere3<T>::circumscribe(const Box<Vec3<T> > &box)
+{
+ center = T(0.5) * (box.min + box.max);
+ radius = (box.max - center).length();
+}
+
+
+template <class T>
+bool Sphere3<T>::intersectT(const Line3<T> &line, T &t) const
+{
+ bool doesIntersect = true;
+
+ Vec3<T> v = line.pos - center;
+ T B = 2.0 * (line.dir ^ v);
+ T C = (v ^ v) - (radius * radius);
+
+ // compute discriminant
+ // if negative, there is no intersection
+
+ T discr = B*B - 4.0*C;
+
+ if (discr < 0.0)
+ {
+ // line and Sphere3 do not intersect
+
+ doesIntersect = false;
+ }
+ else
+ {
+ // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1)
+
+ T sqroot = Math<T>::sqrt(discr);
+ t = (-B - sqroot) * 0.5;
+
+ if (t < 0.0)
+ {
+ // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1)
+
+ t = (-B + sqroot) * 0.5;
+ }
+
+ if (t < 0.0)
+ doesIntersect = false;
+ }
+
+ return doesIntersect;
+}
+
+
+template <class T>
+bool Sphere3<T>::intersect(const Line3<T> &line, Vec3<T> &intersection) const
+{
+ T t;
+
+ if (intersectT (line, t))
+ {
+ intersection = line(t);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+
+} //namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathVec.cpp b/Source/OpenEXR/Imath/ImathVec.cpp
new file mode 100644
index 0000000..ea37a17
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathVec.cpp
@@ -0,0 +1,380 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+//----------------------------------------------------------------------------
+//
+// Specializations of the Vec2<T> and Vec3<T> templates.
+//
+//----------------------------------------------------------------------------
+
+#include "ImathVec.h"
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// suppress exception specification warnings
+#pragma warning(disable:4290)
+#endif
+
+
+namespace Imath {
+
+namespace
+{
+
+template<class T>
+bool
+normalizeOrThrow(Vec2<T> &v)
+{
+ int axis = -1;
+ for (int i = 0; i < 2; i ++)
+ {
+ if (v[i] != 0)
+ {
+ if (axis != -1)
+ {
+ throw IntVecNormalizeExc ("Cannot normalize an integer "
+ "vector unless it is parallel "
+ "to a principal axis");
+ }
+ axis = i;
+ }
+ }
+ v[axis] = (v[axis] > 0) ? 1 : -1;
+ return true;
+}
+
+
+template<class T>
+bool
+normalizeOrThrow(Vec3<T> &v)
+{
+ int axis = -1;
+ for (int i = 0; i < 3; i ++)
+ {
+ if (v[i] != 0)
+ {
+ if (axis != -1)
+ {
+ throw IntVecNormalizeExc ("Cannot normalize an integer "
+ "vector unless it is parallel "
+ "to a principal axis");
+ }
+ axis = i;
+ }
+ }
+ v[axis] = (v[axis] > 0) ? 1 : -1;
+ return true;
+}
+
+}
+
+
+// Vec2<short>
+
+template <>
+short
+Vec2<short>::length () const
+{
+ float lenF = Math<float>::sqrt (dot (*this));
+ short lenS = (short) (lenF + 0.5f);
+ return lenS;
+}
+
+template <>
+const Vec2<short> &
+Vec2<short>::normalize ()
+{
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+const Vec2<short> &
+Vec2<short>::normalizeExc () throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+const Vec2<short> &
+Vec2<short>::normalizeNonNull ()
+{
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+Vec2<short>
+Vec2<short>::normalized () const
+{
+ Vec2<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+template <>
+Vec2<short>
+Vec2<short>::normalizedExc () const throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ Vec2<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+template <>
+Vec2<short>
+Vec2<short>::normalizedNonNull () const
+{
+ Vec2<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+
+// Vec2<int>
+
+template <>
+int
+Vec2<int>::length () const
+{
+ float lenF = Math<float>::sqrt (dot (*this));
+ int lenI = (int) (lenF + 0.5f);
+ return lenI;
+}
+
+template <>
+const Vec2<int> &
+Vec2<int>::normalize ()
+{
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+const Vec2<int> &
+Vec2<int>::normalizeExc () throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+const Vec2<int> &
+Vec2<int>::normalizeNonNull ()
+{
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+Vec2<int>
+Vec2<int>::normalized () const
+{
+ Vec2<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+template <>
+Vec2<int>
+Vec2<int>::normalizedExc () const throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ Vec2<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+template <>
+Vec2<int>
+Vec2<int>::normalizedNonNull () const
+{
+ Vec2<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+
+// Vec3<short>
+
+template <>
+short
+Vec3<short>::length () const
+{
+ float lenF = Math<float>::sqrt (dot (*this));
+ short lenS = (short) (lenF + 0.5f);
+ return lenS;
+}
+
+template <>
+const Vec3<short> &
+Vec3<short>::normalize ()
+{
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+const Vec3<short> &
+Vec3<short>::normalizeExc () throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0) && (z == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+const Vec3<short> &
+Vec3<short>::normalizeNonNull ()
+{
+ normalizeOrThrow<short>(*this);
+ return *this;
+}
+
+template <>
+Vec3<short>
+Vec3<short>::normalized () const
+{
+ Vec3<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+template <>
+Vec3<short>
+Vec3<short>::normalizedExc () const throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0) && (z == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ Vec3<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+template <>
+Vec3<short>
+Vec3<short>::normalizedNonNull () const
+{
+ Vec3<short> v(*this);
+ normalizeOrThrow<short>(v);
+ return v;
+}
+
+
+// Vec3<int>
+
+template <>
+int
+Vec3<int>::length () const
+{
+ float lenF = Math<float>::sqrt (dot (*this));
+ int lenI = (int) (lenF + 0.5f);
+ return lenI;
+}
+
+template <>
+const Vec3<int> &
+Vec3<int>::normalize ()
+{
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+const Vec3<int> &
+Vec3<int>::normalizeExc () throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0) && (z == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+const Vec3<int> &
+Vec3<int>::normalizeNonNull ()
+{
+ normalizeOrThrow<int>(*this);
+ return *this;
+}
+
+template <>
+Vec3<int>
+Vec3<int>::normalized () const
+{
+ Vec3<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+template <>
+Vec3<int>
+Vec3<int>::normalizedExc () const throw (Iex::MathExc)
+{
+ if ((x == 0) && (y == 0) && (z == 0))
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ Vec3<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+template <>
+Vec3<int>
+Vec3<int>::normalizedNonNull () const
+{
+ Vec3<int> v(*this);
+ normalizeOrThrow<int>(v);
+ return v;
+}
+
+
+} // namespace Imath
diff --git a/Source/OpenEXR/Imath/ImathVec.h b/Source/OpenEXR/Imath/ImathVec.h
new file mode 100644
index 0000000..b7adc5f
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathVec.h
@@ -0,0 +1,1426 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHVEC_H
+#define INCLUDED_IMATHVEC_H
+
+//----------------------------------------------------
+//
+// 2D and 3D point/vector class templates!
+//
+//----------------------------------------------------
+
+#include "ImathExc.h"
+#include "ImathLimits.h"
+#include "ImathMath.h"
+
+#include <iostream>
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+// suppress exception specification warnings
+#pragma warning(disable:4290)
+#endif
+
+
+namespace Imath {
+
+
+template <class T> class Vec2
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T x, y;
+
+ T & operator [] (int i);
+ const T & operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Vec2 (); // no initialization
+ explicit Vec2 (T a); // (a a)
+ Vec2 (T a, T b); // (a b)
+
+
+ //---------------------------------
+ // Copy constructors and assignment
+ //---------------------------------
+
+ Vec2 (const Vec2 &v);
+ template <class S> Vec2 (const Vec2<S> &v);
+
+ const Vec2 & operator = (const Vec2 &v);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ template <class S>
+ void setValue (S a, S b);
+
+ template <class S>
+ void setValue (const Vec2<S> &v);
+
+ template <class S>
+ void getValue (S &a, S &b) const;
+
+ template <class S>
+ void getValue (Vec2<S> &v) const;
+
+ T * getValue ();
+ const T * getValue () const;
+
+
+ //---------
+ // Equality
+ //---------
+
+ template <class S>
+ bool operator == (const Vec2<S> &v) const;
+
+ template <class S>
+ bool operator != (const Vec2<S> &v) const;
+
+
+ //-----------------------------------------------------------------------
+ // Compare two vectors and test if they are "approximately equal":
+ //
+ // equalWithAbsError (v, e)
+ //
+ // Returns true if the coefficients of this and v are the same with
+ // an absolute error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - v[i]) <= e
+ //
+ // equalWithRelError (v, e)
+ //
+ // Returns true if the coefficients of this and v are the same with
+ // a relative error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - v[i]) <= e * abs (this[i])
+ //-----------------------------------------------------------------------
+
+ bool equalWithAbsError (const Vec2<T> &v, T e) const;
+ bool equalWithRelError (const Vec2<T> &v, T e) const;
+
+ //------------
+ // Dot product
+ //------------
+
+ T dot (const Vec2 &v) const;
+ T operator ^ (const Vec2 &v) const;
+
+
+ //------------------------------------------------
+ // Right-handed cross product, i.e. z component of
+ // Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
+ //------------------------------------------------
+
+ T cross (const Vec2 &v) const;
+ T operator % (const Vec2 &v) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Vec2 & operator += (const Vec2 &v);
+ Vec2 operator + (const Vec2 &v) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Vec2 & operator -= (const Vec2 &v);
+ Vec2 operator - (const Vec2 &v) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Vec2 operator - () const;
+ const Vec2 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Vec2 & operator *= (const Vec2 &v);
+ const Vec2 & operator *= (T a);
+ Vec2 operator * (const Vec2 &v) const;
+ Vec2 operator * (T a) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Vec2 & operator /= (const Vec2 &v);
+ const Vec2 & operator /= (T a);
+ Vec2 operator / (const Vec2 &v) const;
+ Vec2 operator / (T a) const;
+
+
+ //----------------------------------------------------------------
+ // Length and normalization: If v.length() is 0.0, v.normalize()
+ // and v.normalized() produce a null vector; v.normalizeExc() and
+ // v.normalizedExc() throw a NullVecExc.
+ // v.normalizeNonNull() and v.normalizedNonNull() are slightly
+ // faster than the other normalization routines, but if v.length()
+ // is 0.0, the result is undefined.
+ //----------------------------------------------------------------
+
+ T length () const;
+ T length2 () const;
+
+ const Vec2 & normalize (); // modifies *this
+ const Vec2 & normalizeExc () throw (Iex::MathExc);
+ const Vec2 & normalizeNonNull ();
+
+ Vec2<T> normalized () const; // does not modify *this
+ Vec2<T> normalizedExc () const throw (Iex::MathExc);
+ Vec2<T> normalizedNonNull () const;
+
+
+ //--------------------------------------------------------
+ // Number of dimensions, i.e. number of elements in a Vec2
+ //--------------------------------------------------------
+
+ static unsigned int dimensions() {return 2;}
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+
+
+ //--------------------------------------------------------------
+ // Base type -- in templates, which accept a parameter, V, which
+ // could be either a Vec2<T> or a Vec3<T>, you can refer to T as
+ // V::BaseType
+ //--------------------------------------------------------------
+
+ typedef T BaseType;
+};
+
+
+template <class T> class Vec3
+{
+ public:
+
+ //-------------------
+ // Access to elements
+ //-------------------
+
+ T x, y, z;
+
+ T & operator [] (int i);
+ const T & operator [] (int i) const;
+
+
+ //-------------
+ // Constructors
+ //-------------
+
+ Vec3 (); // no initialization
+ explicit Vec3 (T a); // (a a a)
+ Vec3 (T a, T b, T c); // (a b c)
+
+
+ //---------------------------------
+ // Copy constructors and assignment
+ //---------------------------------
+
+ Vec3 (const Vec3 &v);
+ template <class S> Vec3 (const Vec3<S> &v);
+
+ const Vec3 & operator = (const Vec3 &v);
+
+
+ //----------------------
+ // Compatibility with Sb
+ //----------------------
+
+ template <class S>
+ void setValue (S a, S b, S c);
+
+ template <class S>
+ void setValue (const Vec3<S> &v);
+
+ template <class S>
+ void getValue (S &a, S &b, S &c) const;
+
+ template <class S>
+ void getValue (Vec3<S> &v) const;
+
+ T * getValue();
+ const T * getValue() const;
+
+
+ //---------
+ // Equality
+ //---------
+
+ template <class S>
+ bool operator == (const Vec3<S> &v) const;
+
+ template <class S>
+ bool operator != (const Vec3<S> &v) const;
+
+ //-----------------------------------------------------------------------
+ // Compare two vectors and test if they are "approximately equal":
+ //
+ // equalWithAbsError (v, e)
+ //
+ // Returns true if the coefficients of this and v are the same with
+ // an absolute error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - v[i]) <= e
+ //
+ // equalWithRelError (v, e)
+ //
+ // Returns true if the coefficients of this and v are the same with
+ // a relative error of no more than e, i.e., for all i
+ //
+ // abs (this[i] - v[i]) <= e * abs (this[i])
+ //-----------------------------------------------------------------------
+
+ bool equalWithAbsError (const Vec3<T> &v, T e) const;
+ bool equalWithRelError (const Vec3<T> &v, T e) const;
+
+ //------------
+ // Dot product
+ //------------
+
+ T dot (const Vec3 &v) const;
+ T operator ^ (const Vec3 &v) const;
+
+
+ //---------------------------
+ // Right-handed cross product
+ //---------------------------
+
+ Vec3 cross (const Vec3 &v) const;
+ const Vec3 & operator %= (const Vec3 &v);
+ Vec3 operator % (const Vec3 &v) const;
+
+
+ //------------------------
+ // Component-wise addition
+ //------------------------
+
+ const Vec3 & operator += (const Vec3 &v);
+ Vec3 operator + (const Vec3 &v) const;
+
+
+ //---------------------------
+ // Component-wise subtraction
+ //---------------------------
+
+ const Vec3 & operator -= (const Vec3 &v);
+ Vec3 operator - (const Vec3 &v) const;
+
+
+ //------------------------------------
+ // Component-wise multiplication by -1
+ //------------------------------------
+
+ Vec3 operator - () const;
+ const Vec3 & negate ();
+
+
+ //------------------------------
+ // Component-wise multiplication
+ //------------------------------
+
+ const Vec3 & operator *= (const Vec3 &v);
+ const Vec3 & operator *= (T a);
+ Vec3 operator * (const Vec3 &v) const;
+ Vec3 operator * (T a) const;
+
+
+ //------------------------
+ // Component-wise division
+ //------------------------
+
+ const Vec3 & operator /= (const Vec3 &v);
+ const Vec3 & operator /= (T a);
+ Vec3 operator / (const Vec3 &v) const;
+ Vec3 operator / (T a) const;
+
+
+ //----------------------------------------------------------------
+ // Length and normalization: If v.length() is 0.0, v.normalize()
+ // and v.normalized() produce a null vector; v.normalizeExc() and
+ // v.normalizedExc() throw a NullVecExc.
+ // v.normalizeNonNull() and v.normalizedNonNull() are slightly
+ // faster than the other normalization routines, but if v.length()
+ // is 0.0, the result is undefined.
+ //----------------------------------------------------------------
+
+ T length () const;
+ T length2 () const;
+
+ const Vec3 & normalize (); // modifies *this
+ const Vec3 & normalizeExc () throw (Iex::MathExc);
+ const Vec3 & normalizeNonNull ();
+
+ Vec3<T> normalized () const; // does not modify *this
+ Vec3<T> normalizedExc () const throw (Iex::MathExc);
+ Vec3<T> normalizedNonNull () const;
+
+
+ //--------------------------------------------------------
+ // Number of dimensions, i.e. number of elements in a Vec3
+ //--------------------------------------------------------
+
+ static unsigned int dimensions() {return 3;}
+
+
+ //-------------------------------------------------
+ // Limitations of type T (see also class limits<T>)
+ //-------------------------------------------------
+
+ static T baseTypeMin() {return limits<T>::min();}
+ static T baseTypeMax() {return limits<T>::max();}
+ static T baseTypeSmallest() {return limits<T>::smallest();}
+ static T baseTypeEpsilon() {return limits<T>::epsilon();}
+
+
+ //--------------------------------------------------------------
+ // Base type -- in templates, which accept a parameter, V, which
+ // could be either a Vec2<T> or a Vec3<T>, you can refer to T as
+ // V::BaseType
+ //--------------------------------------------------------------
+
+ typedef T BaseType;
+};
+
+
+//--------------
+// Stream output
+//--------------
+
+template <class T>
+std::ostream & operator << (std::ostream &s, const Vec2<T> &v);
+
+template <class T>
+std::ostream & operator << (std::ostream &s, const Vec3<T> &v);
+
+
+//----------------------------------------------------
+// Reverse multiplication: S * Vec2<T> and S * Vec3<T>
+//----------------------------------------------------
+
+template <class T> Vec2<T> operator * (T a, const Vec2<T> &v);
+template <class T> Vec3<T> operator * (T a, const Vec3<T> &v);
+
+
+//-------------------------
+// Typedefs for convenience
+//-------------------------
+
+typedef Vec2 <short> V2s;
+typedef Vec2 <int> V2i;
+typedef Vec2 <float> V2f;
+typedef Vec2 <double> V2d;
+typedef Vec3 <short> V3s;
+typedef Vec3 <int> V3i;
+typedef Vec3 <float> V3f;
+typedef Vec3 <double> V3d;
+
+
+//-------------------------------------------------------------------
+// Specializations for Vec2<short>, Vec2<int>, Vec3<short>, Vec3<int>
+//-------------------------------------------------------------------
+
+// Vec2<short>
+
+template <> short
+Vec2<short>::length () const;
+
+template <> const Vec2<short> &
+Vec2<short>::normalize ();
+
+template <> const Vec2<short> &
+Vec2<short>::normalizeExc () throw (Iex::MathExc);
+
+template <> const Vec2<short> &
+Vec2<short>::normalizeNonNull ();
+
+template <> Vec2<short>
+Vec2<short>::normalized () const;
+
+template <> Vec2<short>
+Vec2<short>::normalizedExc () const throw (Iex::MathExc);
+
+template <> Vec2<short>
+Vec2<short>::normalizedNonNull () const;
+
+
+// Vec2<int>
+
+template <> int
+Vec2<int>::length () const;
+
+template <> const Vec2<int> &
+Vec2<int>::normalize ();
+
+template <> const Vec2<int> &
+Vec2<int>::normalizeExc () throw (Iex::MathExc);
+
+template <> const Vec2<int> &
+Vec2<int>::normalizeNonNull ();
+
+template <> Vec2<int>
+Vec2<int>::normalized () const;
+
+template <> Vec2<int>
+Vec2<int>::normalizedExc () const throw (Iex::MathExc);
+
+template <> Vec2<int>
+Vec2<int>::normalizedNonNull () const;
+
+
+// Vec3<short>
+
+template <> short
+Vec3<short>::length () const;
+
+template <> const Vec3<short> &
+Vec3<short>::normalize ();
+
+template <> const Vec3<short> &
+Vec3<short>::normalizeExc () throw (Iex::MathExc);
+
+template <> const Vec3<short> &
+Vec3<short>::normalizeNonNull ();
+
+template <> Vec3<short>
+Vec3<short>::normalized () const;
+
+template <> Vec3<short>
+Vec3<short>::normalizedExc () const throw (Iex::MathExc);
+
+template <> Vec3<short>
+Vec3<short>::normalizedNonNull () const;
+
+
+// Vec3<int>
+
+template <> int
+Vec3<int>::length () const;
+
+template <> const Vec3<int> &
+Vec3<int>::normalize ();
+
+template <> const Vec3<int> &
+Vec3<int>::normalizeExc () throw (Iex::MathExc);
+
+template <> const Vec3<int> &
+Vec3<int>::normalizeNonNull ();
+
+template <> Vec3<int>
+Vec3<int>::normalized () const;
+
+template <> Vec3<int>
+Vec3<int>::normalizedExc () const throw (Iex::MathExc);
+
+template <> Vec3<int>
+Vec3<int>::normalizedNonNull () const;
+
+
+//------------------------
+// Implementation of Vec2:
+//------------------------
+
+template <class T>
+inline T &
+Vec2<T>::operator [] (int i)
+{
+ return (&x)[i];
+}
+
+template <class T>
+inline const T &
+Vec2<T>::operator [] (int i) const
+{
+ return (&x)[i];
+}
+
+template <class T>
+inline
+Vec2<T>::Vec2 ()
+{
+ // empty
+}
+
+template <class T>
+inline
+Vec2<T>::Vec2 (T a)
+{
+ x = y = a;
+}
+
+template <class T>
+inline
+Vec2<T>::Vec2 (T a, T b)
+{
+ x = a;
+ y = b;
+}
+
+template <class T>
+inline
+Vec2<T>::Vec2 (const Vec2 &v)
+{
+ x = v.x;
+ y = v.y;
+}
+
+template <class T>
+template <class S>
+inline
+Vec2<T>::Vec2 (const Vec2<S> &v)
+{
+ x = T (v.x);
+ y = T (v.y);
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator = (const Vec2 &v)
+{
+ x = v.x;
+ y = v.y;
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline void
+Vec2<T>::setValue (S a, S b)
+{
+ x = T (a);
+ y = T (b);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec2<T>::setValue (const Vec2<S> &v)
+{
+ x = T (v.x);
+ y = T (v.y);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec2<T>::getValue (S &a, S &b) const
+{
+ a = S (x);
+ b = S (y);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec2<T>::getValue (Vec2<S> &v) const
+{
+ v.x = S (x);
+ v.y = S (y);
+}
+
+template <class T>
+inline T *
+Vec2<T>::getValue()
+{
+ return (T *) &x;
+}
+
+template <class T>
+inline const T *
+Vec2<T>::getValue() const
+{
+ return (const T *) &x;
+}
+
+template <class T>
+template <class S>
+inline bool
+Vec2<T>::operator == (const Vec2<S> &v) const
+{
+ return x == v.x && y == v.y;
+}
+
+template <class T>
+template <class S>
+inline bool
+Vec2<T>::operator != (const Vec2<S> &v) const
+{
+ return x != v.x || y != v.y;
+}
+
+template <class T>
+bool
+Vec2<T>::equalWithAbsError (const Vec2<T> &v, T e) const
+{
+ for (int i = 0; i < 2; i++)
+ if (!Imath::equalWithAbsError ((*this)[i], v[i], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+Vec2<T>::equalWithRelError (const Vec2<T> &v, T e) const
+{
+ for (int i = 0; i < 2; i++)
+ if (!Imath::equalWithRelError ((*this)[i], v[i], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+inline T
+Vec2<T>::dot (const Vec2 &v) const
+{
+ return x * v.x + y * v.y;
+}
+
+template <class T>
+inline T
+Vec2<T>::operator ^ (const Vec2 &v) const
+{
+ return dot (v);
+}
+
+template <class T>
+inline T
+Vec2<T>::cross (const Vec2 &v) const
+{
+ return x * v.y - y * v.x;
+
+}
+
+template <class T>
+inline T
+Vec2<T>::operator % (const Vec2 &v) const
+{
+ return x * v.y - y * v.x;
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator += (const Vec2 &v)
+{
+ x += v.x;
+ y += v.y;
+ return *this;
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator + (const Vec2 &v) const
+{
+ return Vec2 (x + v.x, y + v.y);
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator -= (const Vec2 &v)
+{
+ x -= v.x;
+ y -= v.y;
+ return *this;
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator - (const Vec2 &v) const
+{
+ return Vec2 (x - v.x, y - v.y);
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator - () const
+{
+ return Vec2 (-x, -y);
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::negate ()
+{
+ x = -x;
+ y = -y;
+ return *this;
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator *= (const Vec2 &v)
+{
+ x *= v.x;
+ y *= v.y;
+ return *this;
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator *= (T a)
+{
+ x *= a;
+ y *= a;
+ return *this;
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator * (const Vec2 &v) const
+{
+ return Vec2 (x * v.x, y * v.y);
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator * (T a) const
+{
+ return Vec2 (x * a, y * a);
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator /= (const Vec2 &v)
+{
+ x /= v.x;
+ y /= v.y;
+ return *this;
+}
+
+template <class T>
+inline const Vec2<T> &
+Vec2<T>::operator /= (T a)
+{
+ x /= a;
+ y /= a;
+ return *this;
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator / (const Vec2 &v) const
+{
+ return Vec2 (x / v.x, y / v.y);
+}
+
+template <class T>
+inline Vec2<T>
+Vec2<T>::operator / (T a) const
+{
+ return Vec2 (x / a, y / a);
+}
+
+template <class T>
+inline T
+Vec2<T>::length () const
+{
+ return Math<T>::sqrt (dot (*this));
+}
+
+template <class T>
+inline T
+Vec2<T>::length2 () const
+{
+ return dot (*this);
+}
+
+template <class T>
+const Vec2<T> &
+Vec2<T>::normalize ()
+{
+ T l = length();
+
+ if (l != 0)
+ {
+ x /= l;
+ y /= l;
+ }
+
+ return *this;
+}
+
+template <class T>
+const Vec2<T> &
+Vec2<T>::normalizeExc () throw (Iex::MathExc)
+{
+ T l = length();
+
+ if (l == 0)
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ x /= l;
+ y /= l;
+ return *this;
+}
+
+template <class T>
+inline
+const Vec2<T> &
+Vec2<T>::normalizeNonNull ()
+{
+ T l = length();
+ x /= l;
+ y /= l;
+ return *this;
+}
+
+template <class T>
+Vec2<T>
+Vec2<T>::normalized () const
+{
+ T l = length();
+
+ if (l == 0)
+ return Vec2 (T (0));
+
+ return Vec2 (x / l, y / l);
+}
+
+template <class T>
+Vec2<T>
+Vec2<T>::normalizedExc () const throw (Iex::MathExc)
+{
+ T l = length();
+
+ if (l == 0)
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ return Vec2 (x / l, y / l);
+}
+
+template <class T>
+inline
+Vec2<T>
+Vec2<T>::normalizedNonNull () const
+{
+ T l = length();
+ return Vec2 (x / l, y / l);
+}
+
+
+//-----------------------
+// Implementation of Vec3
+//-----------------------
+
+template <class T>
+inline T &
+Vec3<T>::operator [] (int i)
+{
+ return (&x)[i];
+}
+
+template <class T>
+inline const T &
+Vec3<T>::operator [] (int i) const
+{
+ return (&x)[i];
+}
+
+template <class T>
+inline
+Vec3<T>::Vec3 ()
+{
+ // empty
+}
+
+template <class T>
+inline
+Vec3<T>::Vec3 (T a)
+{
+ x = y = z = a;
+}
+
+template <class T>
+inline
+Vec3<T>::Vec3 (T a, T b, T c)
+{
+ x = a;
+ y = b;
+ z = c;
+}
+
+template <class T>
+inline
+Vec3<T>::Vec3 (const Vec3 &v)
+{
+ x = v.x;
+ y = v.y;
+ z = v.z;
+}
+
+template <class T>
+template <class S>
+inline
+Vec3<T>::Vec3 (const Vec3<S> &v)
+{
+ x = T (v.x);
+ y = T (v.y);
+ z = T (v.z);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator = (const Vec3 &v)
+{
+ x = v.x;
+ y = v.y;
+ z = v.z;
+ return *this;
+}
+
+template <class T>
+template <class S>
+inline void
+Vec3<T>::setValue (S a, S b, S c)
+{
+ x = T (a);
+ y = T (b);
+ z = T (c);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec3<T>::setValue (const Vec3<S> &v)
+{
+ x = T (v.x);
+ y = T (v.y);
+ z = T (v.z);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec3<T>::getValue (S &a, S &b, S &c) const
+{
+ a = S (x);
+ b = S (y);
+ c = S (z);
+}
+
+template <class T>
+template <class S>
+inline void
+Vec3<T>::getValue (Vec3<S> &v) const
+{
+ v.x = S (x);
+ v.y = S (y);
+ v.z = S (z);
+}
+
+template <class T>
+inline T *
+Vec3<T>::getValue()
+{
+ return (T *) &x;
+}
+
+template <class T>
+inline const T *
+Vec3<T>::getValue() const
+{
+ return (const T *) &x;
+}
+
+template <class T>
+template <class S>
+inline bool
+Vec3<T>::operator == (const Vec3<S> &v) const
+{
+ return x == v.x && y == v.y && z == v.z;
+}
+
+template <class T>
+template <class S>
+inline bool
+Vec3<T>::operator != (const Vec3<S> &v) const
+{
+ return x != v.x || y != v.y || z != v.z;
+}
+
+template <class T>
+bool
+Vec3<T>::equalWithAbsError (const Vec3<T> &v, T e) const
+{
+ for (int i = 0; i < 3; i++)
+ if (!Imath::equalWithAbsError ((*this)[i], v[i], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+bool
+Vec3<T>::equalWithRelError (const Vec3<T> &v, T e) const
+{
+ for (int i = 0; i < 3; i++)
+ if (!Imath::equalWithRelError ((*this)[i], v[i], e))
+ return false;
+
+ return true;
+}
+
+template <class T>
+inline T
+Vec3<T>::dot (const Vec3 &v) const
+{
+ return x * v.x + y * v.y + z * v.z;
+}
+
+template <class T>
+inline T
+Vec3<T>::operator ^ (const Vec3 &v) const
+{
+ return dot (v);
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::cross (const Vec3 &v) const
+{
+ return Vec3 (y * v.z - z * v.y,
+ z * v.x - x * v.z,
+ x * v.y - y * v.x);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator %= (const Vec3 &v)
+{
+ T a = y * v.z - z * v.y;
+ T b = z * v.x - x * v.z;
+ T c = x * v.y - y * v.x;
+ x = a;
+ y = b;
+ z = c;
+ return *this;
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator % (const Vec3 &v) const
+{
+ return Vec3 (y * v.z - z * v.y,
+ z * v.x - x * v.z,
+ x * v.y - y * v.x);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator += (const Vec3 &v)
+{
+ x += v.x;
+ y += v.y;
+ z += v.z;
+ return *this;
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator + (const Vec3 &v) const
+{
+ return Vec3 (x + v.x, y + v.y, z + v.z);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator -= (const Vec3 &v)
+{
+ x -= v.x;
+ y -= v.y;
+ z -= v.z;
+ return *this;
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator - (const Vec3 &v) const
+{
+ return Vec3 (x - v.x, y - v.y, z - v.z);
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator - () const
+{
+ return Vec3 (-x, -y, -z);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::negate ()
+{
+ x = -x;
+ y = -y;
+ z = -z;
+ return *this;
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator *= (const Vec3 &v)
+{
+ x *= v.x;
+ y *= v.y;
+ z *= v.z;
+ return *this;
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator *= (T a)
+{
+ x *= a;
+ y *= a;
+ z *= a;
+ return *this;
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator * (const Vec3 &v) const
+{
+ return Vec3 (x * v.x, y * v.y, z * v.z);
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator * (T a) const
+{
+ return Vec3 (x * a, y * a, z * a);
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator /= (const Vec3 &v)
+{
+ x /= v.x;
+ y /= v.y;
+ z /= v.z;
+ return *this;
+}
+
+template <class T>
+inline const Vec3<T> &
+Vec3<T>::operator /= (T a)
+{
+ x /= a;
+ y /= a;
+ z /= a;
+ return *this;
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator / (const Vec3 &v) const
+{
+ return Vec3 (x / v.x, y / v.y, z / v.z);
+}
+
+template <class T>
+inline Vec3<T>
+Vec3<T>::operator / (T a) const
+{
+ return Vec3 (x / a, y / a, z / a);
+}
+
+
+template <class T>
+inline T
+Vec3<T>::length () const
+{
+ return Math<T>::sqrt (dot (*this));
+}
+
+template <class T>
+inline T
+Vec3<T>::length2 () const
+{
+ return dot (*this);
+}
+
+template <class T>
+const Vec3<T> &
+Vec3<T>::normalize ()
+{
+ T l = length();
+
+ if (l != 0)
+ {
+ x /= l;
+ y /= l;
+ z /= l;
+ }
+
+ return *this;
+}
+
+template <class T>
+const Vec3<T> &
+Vec3<T>::normalizeExc () throw (Iex::MathExc)
+{
+ T l = length();
+
+ if (l == 0)
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ x /= l;
+ y /= l;
+ z /= l;
+ return *this;
+}
+
+template <class T>
+inline
+const Vec3<T> &
+Vec3<T>::normalizeNonNull ()
+{
+ T l = length();
+ x /= l;
+ y /= l;
+ z /= l;
+ return *this;
+}
+
+template <class T>
+Vec3<T>
+Vec3<T>::normalized () const
+{
+ T l = length();
+
+ if (l == 0)
+ return Vec3 (T (0));
+
+ return Vec3 (x / l, y / l, z / l);
+}
+
+template <class T>
+Vec3<T>
+Vec3<T>::normalizedExc () const throw (Iex::MathExc)
+{
+ T l = length();
+
+ if (l == 0)
+ throw NullVecExc ("Cannot normalize null vector.");
+
+ return Vec3 (x / l, y / l, z / l);
+}
+
+template <class T>
+inline
+Vec3<T>
+Vec3<T>::normalizedNonNull () const
+{
+ T l = length();
+ return Vec3 (x / l, y / l, z / l);
+}
+
+
+//-----------------------------
+// Stream output implementation
+//-----------------------------
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Vec2<T> &v)
+{
+ return s << '(' << v.x << ' ' << v.y << ')';
+}
+
+template <class T>
+std::ostream &
+operator << (std::ostream &s, const Vec3<T> &v)
+{
+ return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
+}
+
+
+//-----------------------------------------
+// Implementation of reverse multiplication
+//-----------------------------------------
+
+template <class T>
+inline Vec2<T>
+operator * (T a, const Vec2<T> &v)
+{
+ return Vec2<T> (a * v.x, a * v.y);
+}
+
+template <class T>
+inline Vec3<T>
+operator * (T a, const Vec3<T> &v)
+{
+ return Vec3<T> (a * v.x, a * v.y, a * v.z);
+}
+
+
+#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
+#pragma warning(default:4290)
+#endif
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/ImathVecAlgo.h b/Source/OpenEXR/Imath/ImathVecAlgo.h
new file mode 100644
index 0000000..9b726a7
--- /dev/null
+++ b/Source/OpenEXR/Imath/ImathVecAlgo.h
@@ -0,0 +1,146 @@
+///////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
+// Digital Ltd. LLC
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Industrial Light & Magic nor the names of
+// its contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+///////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef INCLUDED_IMATHVECALGO_H
+#define INCLUDED_IMATHVECALGO_H
+
+//-------------------------------------------------------------------------
+//
+// This file contains algorithms applied to or in conjunction
+// with points (Imath::Vec2 and Imath::Vec3).
+// The assumption made is that these functions are called much
+// less often than the basic point functions or these functions
+// require more support classes.
+//
+//-------------------------------------------------------------------------
+
+#include "ImathVec.h"
+#include "ImathLimits.h"
+
+namespace Imath {
+
+
+//--------------------------------------------------------------
+// Find the projection of vector t onto vector s (Vec2 and Vec3)
+//--------------------------------------------------------------
+
+template <class Vec> Vec project (const Vec &s, const Vec &t);
+
+
+//----------------------------------------------
+// Find a vector which is perpendicular to s and
+// in the same plane as s and t (Vec2 and Vec3)
+//----------------------------------------------
+
+template <class Vec> Vec orthogonal (const Vec &s, const Vec &t);
+
+
+//-----------------------------------------------
+// Find the direction of a ray s after reflection
+// off a plane with normal t (Vec2 and Vec3)
+//-----------------------------------------------
+
+template <class Vec> Vec reflect (const Vec &s, const Vec &t);
+
+
+//----------------------------------------------------------------------
+// Find the vertex of triangle (v0, v1, v2), which is closest to point p
+// (Vec2 and Vec3).
+//----------------------------------------------------------------------
+
+template <class Vec> Vec closestVertex (const Vec &v0,
+ const Vec &v1,
+ const Vec &v2,
+ const Vec &p);
+
+//---------------
+// Implementation
+//---------------
+
+template <class Vec>
+Vec
+project (const Vec &s, const Vec &t)
+{
+ Vec sNormalized = s.normalized();
+ return sNormalized * (sNormalized ^ t);
+}
+
+template <class Vec>
+Vec
+orthogonal (const Vec &s, const Vec &t)
+{
+ return t - project (s, t);
+}
+
+template <class Vec>
+Vec
+reflect (const Vec &s, const Vec &t)
+{
+ return s - typename Vec::BaseType(2) * (s - project(t, s));
+}
+
+template <class Vec>
+Vec
+closestVertex(const Vec &v0,
+ const Vec &v1,
+ const Vec &v2,
+ const Vec &p)
+{
+ Vec nearest = v0;
+ typename Vec::BaseType neardot = (v0 - p).length2();
+ typename Vec::BaseType tmp = (v1 - p).length2();
+
+ if (tmp < neardot)
+ {
+ neardot = tmp;
+ nearest = v1;
+ }
+
+ tmp = (v2 - p).length2();
+
+ if (tmp < neardot)
+ {
+ neardot = tmp;
+ nearest = v2;
+ }
+
+ return nearest;
+}
+
+
+} // namespace Imath
+
+#endif
diff --git a/Source/OpenEXR/Imath/Makefile.am b/Source/OpenEXR/Imath/Makefile.am
new file mode 100644
index 0000000..5f0484e
--- /dev/null
+++ b/Source/OpenEXR/Imath/Makefile.am
@@ -0,0 +1,34 @@
+## Process this file with automake to produce Makefile.in
+
+lib_LTLIBRARIES = libImath.la
+
+libImath_la_SOURCES = ImathShear.cpp ImathMatrixAlgo.cpp ImathVec.cpp \
+ ImathColorAlgo.cpp ImathFun.cpp \
+ ImathColorAlgo.h ImathMatrixAlgo.h ImathVec.h \
+ ImathShear.h ImathFun.h ImathBox.h ImathBoxAlgo.h \
+ ImathEuler.h ImathExc.h ImathLimits.h ImathLine.h \
+ ImathLineAlgo.h ImathMatrix.h ImathPlane.h \
+ ImathSphere.h ImathVecAlgo.h ImathQuat.h \
+ ImathFrustum.h ImathMath.h ImathGL.h \
+ ImathColor.h ImathRandom.h ImathRoots.h \
+ ImathHalfLimits.h ImathInterval.h ImathGLU.h \
+ ImathFrame.h ImathPlatform.h \
+ ImathBox.cpp ImathRandom.cpp ImathInt64.h
+
+libImath_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libImath_la_LIBADD = ../Iex/libIex.la
+
+libImathincludedir = $(includedir)/OpenEXR
+
+libImathinclude_HEADERS = ImathColorAlgo.h ImathMatrixAlgo.h ImathVec.h \
+ ImathShear.h ImathFun.h ImathBox.h ImathBoxAlgo.h \
+ ImathEuler.h ImathExc.h ImathLimits.h ImathLine.h \
+ ImathLineAlgo.h ImathMatrix.h ImathPlane.h \
+ ImathSphere.h ImathVecAlgo.h ImathQuat.h \
+ ImathFrustum.h ImathMath.h ImathGL.h \
+ ImathColor.h ImathRandom.h ImathRoots.h \
+ ImathHalfLimits.h ImathInterval.h ImathGLU.h \
+ ImathFrame.h ImathPlatform.h ImathInt64.h
+
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)/Iex -I$(top_srcdir)/Half \
+ -I$(top_srcdir)/config
diff --git a/Source/OpenEXR/Imath/Makefile.in b/Source/OpenEXR/Imath/Makefile.in
new file mode 100644
index 0000000..49d2fe7
--- /dev/null
+++ b/Source/OpenEXR/Imath/Makefile.in
@@ -0,0 +1,529 @@
+# Makefile.in generated by automake 1.9.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+SOURCES = $(libImath_la_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = Imath
+DIST_COMMON = $(libImathinclude_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/threads.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config/IlmBaseConfig.h
+CONFIG_CLEAN_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(libImathincludedir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libImath_la_DEPENDENCIES = ../Iex/libIex.la
+am_libImath_la_OBJECTS = ImathShear.lo ImathMatrixAlgo.lo ImathVec.lo \
+ ImathColorAlgo.lo ImathFun.lo ImathBox.lo ImathRandom.lo
+libImath_la_OBJECTS = $(am_libImath_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/config
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libImath_la_SOURCES)
+DIST_SOURCES = $(libImath_la_SOURCES)
+libImathincludeHEADERS_INSTALL = $(INSTALL_HEADER)
+HEADERS = $(libImathinclude_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CXXFLAGS = @AM_CXXFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+ILMBASE_VERSION = @ILMBASE_VERSION@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBTOOL_VERSION = @LIBTOOL_VERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREAD_CC = @PTHREAD_CC@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+acx_pthread_config = @acx_pthread_config@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+lib_LTLIBRARIES = libImath.la
+libImath_la_SOURCES = ImathShear.cpp ImathMatrixAlgo.cpp ImathVec.cpp \
+ ImathColorAlgo.cpp ImathFun.cpp \
+ ImathColorAlgo.h ImathMatrixAlgo.h ImathVec.h \
+ ImathShear.h ImathFun.h ImathBox.h ImathBoxAlgo.h \
+ ImathEuler.h ImathExc.h ImathLimits.h ImathLine.h \
+ ImathLineAlgo.h ImathMatrix.h ImathPlane.h \
+ ImathSphere.h ImathVecAlgo.h ImathQuat.h \
+ ImathFrustum.h ImathMath.h ImathGL.h \
+ ImathColor.h ImathRandom.h ImathRoots.h \
+ ImathHalfLimits.h ImathInterval.h ImathGLU.h \
+ ImathFrame.h ImathPlatform.h \
+ ImathBox.cpp ImathRandom.cpp ImathInt64.h
+
+libImath_la_LDFLAGS = -version-info @LIBTOOL_VERSION@ -no-undefined
+libImath_la_LIBADD = ../Iex/libIex.la
+libImathincludedir = $(includedir)/OpenEXR
+libImathinclude_HEADERS = ImathColorAlgo.h ImathMatrixAlgo.h ImathVec.h \
+ ImathShear.h ImathFun.h ImathBox.h ImathBoxAlgo.h \
+ ImathEuler.h ImathExc.h ImathLimits.h ImathLine.h \
+ ImathLineAlgo.h ImathMatrix.h ImathPlane.h \
+ ImathSphere.h ImathVecAlgo.h ImathQuat.h \
+ ImathFrustum.h ImathMath.h ImathGL.h \
+ ImathColor.h ImathRandom.h ImathRoots.h \
+ ImathHalfLimits.h ImathInterval.h ImathGLU.h \
+ ImathFrame.h ImathPlatform.h ImathInt64.h
+
+INCLUDES = -I$(top_builddir) -I$(top_srcdir)/Iex -I$(top_srcdir)/Half \
+ -I$(top_srcdir)/config
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Imath/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Imath/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libImath.la: $(libImath_la_OBJECTS) $(libImath_la_DEPENDENCIES)
+ $(CXXLINK) -rpath $(libdir) $(libImath_la_LDFLAGS) $(libImath_la_OBJECTS) $(libImath_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathBox.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathColorAlgo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathFun.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathMatrixAlgo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathRandom.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathShear.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ImathVec.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+install-libImathincludeHEADERS: $(libImathinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ test -z "$(libImathincludedir)" || $(mkdir_p) "$(DESTDIR)$(libImathincludedir)"
+ @list='$(libImathinclude_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f=$(am__strip_dir) \
+ echo " $(libImathincludeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libImathincludedir)/$$f'"; \
+ $(libImathincludeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libImathincludedir)/$$f"; \
+ done
+
+uninstall-libImathincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libImathinclude_HEADERS)'; for p in $$list; do \
+ f=$(am__strip_dir) \
+ echo " rm -f '$(DESTDIR)$(libImathincludedir)/$$f'"; \
+ rm -f "$(DESTDIR)$(libImathincludedir)/$$f"; \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libImathincludedir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-libImathincludeHEADERS
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libImathincludeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-exec \
+ install-exec-am install-info install-info-am \
+ install-libImathincludeHEADERS install-libLTLIBRARIES \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am \
+ uninstall-libImathincludeHEADERS uninstall-libLTLIBRARIES
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Source/OpenEXR/OpenEXR.2003.vcproj b/Source/OpenEXR/OpenEXR.2003.vcproj
new file mode 100644
index 0000000..07424e3
--- /dev/null
+++ b/Source/OpenEXR/OpenEXR.2003.vcproj
@@ -0,0 +1,737 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="OpenEXR"
+ ProjectGUID="{17A4874B-0606-4687-90B6-F91F8CB3B8AF}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories="./;./IlmImf;./Imath;./Iex;./Half;./IlmThread;../ZLib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="FALSE"
+ ForceConformanceInForLoopScope="TRUE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ Detect64BitPortabilityProblems="FALSE"
+ CompileAs="0"
+ DisableSpecificWarnings="4290"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\OpenEXR.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="./;./IlmImf;./Imath;./Iex;./Half;./IlmThread;../ZLib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ ForceConformanceInForLoopScope="TRUE"
+ RuntimeTypeInfo="TRUE"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ Detect64BitPortabilityProblems="FALSE"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4290"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\OpenEXR.lib"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <Filter
+ Name="IlmImf Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\IlmImf\ImfAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfB44Compressor.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfBoxAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelList.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelListAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticities.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticitiesAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressionAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressor.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfConvert.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCRgbaFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfDoubleAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmap.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmapAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFloatAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFrameBuffer.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFramesPerSecond.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHeader.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHuf.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInputFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIntAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIO.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCode.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCodeAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrderAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLut.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMatrixAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMisc.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOpaqueAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOutputFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPizCompressor.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImage.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImageAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPxr24Compressor.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRational.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRationalAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaYca.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRleCompressor.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfScanLineInputFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStandardAttributes.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStdIO.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStringAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTestFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfThreading.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescriptionAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledInputFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledMisc.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledOutputFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledRgbaFile.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileOffsets.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCode.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCodeAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVecAttribute.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVersion.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfWav.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfZipCompressor.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Imath Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\Imath\ImathBox.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColorAlgo.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFun.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrixAlgo.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRandom.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathShear.cpp">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVec.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Iex Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\Iex\IexBaseExc.cpp">
+ </File>
+ <File
+ RelativePath=".\Iex\IexThrowErrnoExc.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Half Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath=".\Half\half.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="IlmThread Source Files"
+ Filter="">
+ <File
+ RelativePath=".\IlmThread\IlmThread.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadMutex.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadPool.cpp">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadSemaphore.cpp">
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\IlmBaseConfig.h">
+ </File>
+ <File
+ RelativePath=".\OpenEXRConfig.h">
+ </File>
+ <Filter
+ Name="IlmImf Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\IlmImf\b44ExpLogTable.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfArray.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfAutoArray.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfB44Compressor.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfBoxAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelList.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelListAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticities.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticitiesAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompression.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressionAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressor.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfConvert.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCRgbaFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfDoubleAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmap.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmapAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFloatAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFrameBuffer.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFramesPerSecond.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHeader.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHuf.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInputFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInt64.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIntAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIO.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCode.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCodeAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrder.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrderAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLut.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMatrixAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMisc.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfName.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOpaqueAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOutputFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPixelType.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPizCompressor.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImage.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImageAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPxr24Compressor.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRational.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRationalAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgba.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaYca.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRleCompressor.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfScanLineInputFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStandardAttributes.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStdIO.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStringAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTestFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfThreading.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescription.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescriptionAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledInputFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledMisc.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledOutputFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledRgbaFile.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileOffsets.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCode.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCodeAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVecAttribute.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVersion.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfWav.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfXdr.h">
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfZipCompressor.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Imath Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\Imath\ImathBox.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathBoxAlgo.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColor.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColorAlgo.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathEuler.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathExc.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFrame.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFrustum.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFun.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathGL.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathGLU.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathHalfLimits.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathInterval.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLimits.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLine.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLineAlgo.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMath.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrix.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrixAlgo.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathPlane.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathPlatform.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathQuat.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRandom.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRoots.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathShear.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathSphere.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVec.h">
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVecAlgo.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Iex Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\Iex\Iex.h">
+ </File>
+ <File
+ RelativePath=".\Iex\IexBaseExc.h">
+ </File>
+ <File
+ RelativePath=".\Iex\IexErrnoExc.h">
+ </File>
+ <File
+ RelativePath=".\Iex\IexMacros.h">
+ </File>
+ <File
+ RelativePath=".\Iex\IexMathExc.h">
+ </File>
+ <File
+ RelativePath=".\Iex\IexThrowErrnoExc.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Half Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath=".\Half\eLut.h">
+ </File>
+ <File
+ RelativePath=".\Half\half.h">
+ </File>
+ <File
+ RelativePath=".\Half\halfFunction.h">
+ </File>
+ <File
+ RelativePath=".\Half\halfLimits.h">
+ </File>
+ <File
+ RelativePath=".\Half\toFloat.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="IlmThread Header Files"
+ Filter="">
+ <File
+ RelativePath=".\IlmThread\IlmThread.h">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadMutex.h">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadPool.h">
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadSemaphore.h">
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/OpenEXR/OpenEXR.2005.vcproj b/Source/OpenEXR/OpenEXR.2005.vcproj
new file mode 100644
index 0000000..130cee5
--- /dev/null
+++ b/Source/OpenEXR/OpenEXR.2005.vcproj
@@ -0,0 +1,978 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="OpenEXR"
+ ProjectGUID="{17A4874B-0606-4687-90B6-F91F8CB3B8AF}"
+ RootNamespace="OpenEXR"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="./;./IlmImf;./Imath;./Iex;./Half;./IlmThread;../ZLib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="false"
+ ForceConformanceInForLoopScope="true"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ CompileAs="0"
+ DisableSpecificWarnings="4290"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\OpenEXR.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="./;./IlmImf;./Imath;./Iex;./Half;./IlmThread;../ZLib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ ForceConformanceInForLoopScope="true"
+ RuntimeTypeInfo="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=""
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ DisableSpecificWarnings="4290"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\OpenEXR.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <Filter
+ Name="IlmImf Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\IlmImf\ImfAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfB44Compressor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfBoxAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelList.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelListAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticities.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticitiesAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressionAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfConvert.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCRgbaFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfDoubleAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmap.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmapAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFloatAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFrameBuffer.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFramesPerSecond.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHeader.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHuf.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInputFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIntAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCode.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCodeAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrderAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLut.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMatrixAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMisc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOpaqueAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOutputFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPizCompressor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImageAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPxr24Compressor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRational.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRationalAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaYca.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRleCompressor.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfScanLineInputFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStandardAttributes.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStdIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStringAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTestFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfThreading.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescriptionAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledInputFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledMisc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledOutputFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledRgbaFile.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileOffsets.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCode.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCodeAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVecAttribute.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVersion.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfWav.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfZipCompressor.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Imath Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\Imath\ImathBox.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColorAlgo.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFun.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrixAlgo.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRandom.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathShear.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVec.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Iex Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\Iex\IexBaseExc.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexThrowErrnoExc.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Half Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath=".\Half\half.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="IlmThread Source Files"
+ >
+ <File
+ RelativePath=".\IlmThread\IlmThread.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadMutex.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadPool.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadSemaphore.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\IlmBaseConfig.h"
+ >
+ </File>
+ <File
+ RelativePath=".\OpenEXRConfig.h"
+ >
+ </File>
+ <Filter
+ Name="IlmImf Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\IlmImf\b44ExpLogTable.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfArray.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfAutoArray.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfB44Compressor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfBoxAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelList.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChannelListAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticities.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfChromaticitiesAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompression.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressionAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCompressor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfConvert.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfCRgbaFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfDoubleAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmap.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfEnvmapAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFloatAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFrameBuffer.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfFramesPerSecond.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHeader.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfHuf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInputFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfInt64.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIntAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfIO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCode.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfKeyCodeAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrder.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLineOrderAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfLut.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMatrixAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfMisc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfName.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOpaqueAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfOutputFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPixelType.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPizCompressor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImage.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPreviewImageAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfPxr24Compressor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRational.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRationalAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgba.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRgbaYca.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfRleCompressor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfScanLineInputFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStandardAttributes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStdIO.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfStringAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTestFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfThreading.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescription.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileDescriptionAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledInputFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledMisc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledOutputFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTiledRgbaFile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTileOffsets.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCode.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfTimeCodeAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVecAttribute.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfVersion.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfWav.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfXdr.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmImf\ImfZipCompressor.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Imath Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\Imath\ImathBox.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathBoxAlgo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColor.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathColorAlgo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathEuler.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathExc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFrame.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFrustum.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathFun.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathGL.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathGLU.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathHalfLimits.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathInterval.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLimits.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLine.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathLineAlgo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMath.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrix.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathMatrixAlgo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathPlane.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathPlatform.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathQuat.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRandom.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathRoots.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathShear.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathSphere.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVec.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Imath\ImathVecAlgo.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Iex Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\Iex\Iex.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexBaseExc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexErrnoExc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexMacros.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexMathExc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Iex\IexThrowErrnoExc.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Half Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath=".\Half\eLut.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Half\half.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Half\halfFunction.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Half\halfLimits.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Half\toFloat.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="IlmThread Header Files"
+ >
+ <File
+ RelativePath=".\IlmThread\IlmThread.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadMutex.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadPool.h"
+ >
+ </File>
+ <File
+ RelativePath=".\IlmThread\IlmThreadSemaphore.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/OpenEXR/OpenEXRConfig.h b/Source/OpenEXR/OpenEXRConfig.h
new file mode 100644
index 0000000..cc8bb9d
--- /dev/null
+++ b/Source/OpenEXR/OpenEXRConfig.h
@@ -0,0 +1,46 @@
+//
+// Define and set to 1 if the target system has POSIX thread support
+// and you want OpenEXR to use it for multithreaded file I/O.
+//
+
+#undef HAVE_PTHREAD // currently disabled in FreeImage
+
+//
+// Define and set to 1 if the target system supports POSIX semaphores
+// and you want OpenEXR to use them; otherwise, OpenEXR will use its
+// own semaphore implementation.
+//
+
+#undef HAVE_POSIX_SEMAPHORES
+
+//
+// Define and set to 1 if the target system is a Darwin-based system
+// (e.g., OS X).
+//
+
+#undef HAVE_DARWIN
+
+//
+// Define and set to 1 if the target system supports a proc filesystem
+// compatible with the Linux kernel's proc filesystem. Note that this
+// is only used by a program in the IlmImfTest test suite, it's not
+// used by any OpenEXR library or application code.
+//
+
+#undef HAVE_LINUX_PROCFS
+
+//
+// Define and set to 1 if the target system includes the NVIDIA Cg
+// runtime. The exrdisplay program will use a fragment shader to
+// accelerate the display of OpenEXR images.
+//
+
+#undef HAVE_FRAGMENT_SHADERS
+
+//
+// Define and set to 1 if the target system has a complete <iomanip>
+// implementation, specifically if it supports the std::right
+// formatter.
+//
+
+#undef HAVE_COMPLETE_IOMANIP
diff --git a/Source/Plugin.h b/Source/Plugin.h
new file mode 100644
index 0000000..1b40527
--- /dev/null
+++ b/Source/Plugin.h
@@ -0,0 +1,138 @@
+// ==========================================================
+// FreeImage Plugin Interface
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Rui Lopes (ruiglopes@yahoo.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
+#endif
+
+#ifndef PLUGIN_H
+#define PLUGIN_H
+
+#include "FreeImage.h"
+#include "Utilities.h"
+
+// ==========================================================
+#define NO_EXR_PLUGIN // ESL@TPN added this on 7/11/08
+// ==========================================================
+
+struct Plugin;
+
+// =====================================================================
+// Plugin Node
+// =====================================================================
+
+FI_STRUCT (PluginNode) {
+ int m_id;
+ void *m_instance;
+ Plugin *m_plugin;
+ PluginNode *m_next;
+ BOOL m_enabled;
+
+ const char *m_format;
+ const char *m_description;
+ const char *m_extension;
+ const char *m_regexpr;
+};
+
+// =====================================================================
+// Internal Plugin List
+// =====================================================================
+
+class PluginList {
+public :
+ PluginList();
+ ~PluginList();
+
+ FREE_IMAGE_FORMAT AddNode(FI_InitProc proc, void *instance = NULL, const char *format = 0, const char *description = 0, const char *extension = 0, const char *regexpr = 0);
+ PluginNode *FindNodeFromFormat(const char *format);
+ PluginNode *FindNodeFromMime(const char *mime);
+ PluginNode *FindNodeFromFIF(int node_id);
+
+ int Size() const;
+ BOOL IsEmpty() const;
+
+private :
+ std::map<int, PluginNode *> m_plugin_map;
+ int m_node_count;
+};
+
+// ==========================================================
+// Plugin Initialisation Callback
+// ==========================================================
+
+void DLL_CALLCONV FreeImage_OutputMessage(int fif, const char *message, ...);
+
+// =====================================================================
+// Reimplementation of stricmp (it is not supported on some systems)
+// =====================================================================
+
+int FreeImage_stricmp(const char *s1, const char *s2);
+
+// ==========================================================
+// Internal functions
+// ==========================================================
+
+extern "C" {
+ BOOL DLL_CALLCONV FreeImage_Validate(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle);
+ void * DLL_CALLCONV FreeImage_Open(PluginNode *node, FreeImageIO *io, fi_handle handle, BOOL open_for_reading);
+ void DLL_CALLCONV FreeImage_Close(PluginNode *node, FreeImageIO *io, fi_handle handle, void *data); // plugin.cpp
+ PluginList * DLL_CALLCONV FreeImage_GetPluginList(); // plugin.cpp
+}
+
+// ==========================================================
+// Internal plugins
+// ==========================================================
+
+void DLL_CALLCONV InitBMP(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitCUT(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitICO(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitIFF(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitJPEG(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitKOALA(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitLBM(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitMNG(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPCD(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPCX(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPNG(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPNM(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPSD(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitRAS(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitTARGA(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitTIFF(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitWBMP(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitXBM(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitXPM(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitDDS(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitGIF(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitHDR(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitG3(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitSGI(Plugin *plugin, int format_id);
+#ifndef NO_EXR_PLUGIN
+void DLL_CALLCONV InitEXR(Plugin *plugin, int format_id);
+#endif
+void DLL_CALLCONV InitJ2K(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitJP2(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPFM(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitPICT(Plugin *plugin, int format_id);
+void DLL_CALLCONV InitRAW(Plugin *plugin, int format_id);
+
+#endif //!PLUGIN_H
diff --git a/Source/Quantizers.h b/Source/Quantizers.h
new file mode 100644
index 0000000..2a671fa
--- /dev/null
+++ b/Source/Quantizers.h
@@ -0,0 +1,225 @@
+// =============================================================
+// Quantizer objects and functions
+//
+// Design and implementation by:
+// - Hervé Drolon <drolon@infonie.fr>
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// =============================================================
+
+//
+////////////////////////////////////////////////////////////////
+
+#include "FreeImage.h"
+
+////////////////////////////////////////////////////////////////
+
+/**
+ Xiaolin Wu color quantization algorithm
+*/
+class WuQuantizer
+{
+public:
+
+typedef struct tagBox {
+ int r0; // min value, exclusive
+ int r1; // max value, inclusive
+ int g0;
+ int g1;
+ int b0;
+ int b1;
+ int vol;
+} Box;
+
+protected:
+ float *gm2;
+ LONG *wt, *mr, *mg, *mb;
+ WORD *Qadd;
+
+ // DIB data
+ unsigned width, height;
+ unsigned pitch;
+ FIBITMAP *m_dib;
+
+protected:
+ void Hist3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2, int ReserveSize, RGBQUAD *ReservePalette);
+ void M3D(LONG *vwt, LONG *vmr, LONG *vmg, LONG *vmb, float *m2);
+ LONG Vol(Box *cube, LONG *mmt);
+ LONG Bottom(Box *cube, BYTE dir, LONG *mmt);
+ LONG Top(Box *cube, BYTE dir, int pos, LONG *mmt);
+ float Var(Box *cube);
+ float Maximize(Box *cube, BYTE dir, int first, int last , int *cut,
+ LONG whole_r, LONG whole_g, LONG whole_b, LONG whole_w);
+ bool Cut(Box *set1, Box *set2);
+ void Mark(Box *cube, int label, BYTE *tag);
+
+public:
+ // Constructor - Input parameter: DIB 24-bit to be quantized
+ WuQuantizer(FIBITMAP *dib);
+ // Destructor
+ ~WuQuantizer();
+ // Quantizer - Return value: quantized 8-bit (color palette) DIB
+ FIBITMAP* Quantize(int PaletteSize, int ReserveSize, RGBQUAD *ReservePalette);
+};
+
+
+/**
+ NEUQUANT Neural-Net quantization algorithm by Anthony Dekker
+*/
+
+// ----------------------------------------------------------------
+// Constant definitions
+// ----------------------------------------------------------------
+
+/** number of colours used:
+ for 256 colours, fixed arrays need 8kb, plus space for the image
+*/
+//static const int netsize = 256;
+
+/**@name network definitions */
+//@{
+//static const int maxnetpos = (netsize - 1);
+/// bias for colour values
+static const int netbiasshift = 4;
+/// no. of learning cycles
+static const int ncycles = 100;
+//@}
+
+/**@name defs for freq and bias */
+//@{
+/// bias for fractions
+static const int intbiasshift = 16;
+static const int intbias = (((int)1) << intbiasshift);
+/// gamma = 1024
+static const int gammashift = 10;
+// static const int gamma = (((int)1) << gammashift);
+/// beta = 1 / 1024
+static const int betashift = 10;
+static const int beta = (intbias >> betashift);
+static const int betagamma = (intbias << (gammashift-betashift));
+//@}
+
+/**@name defs for decreasing radius factor */
+//@{
+/// for 256 cols, radius starts
+//static const int initrad = (netsize >> 3);
+/// at 32.0 biased by 6 bits
+static const int radiusbiasshift = 6;
+static const int radiusbias = (((int)1) << radiusbiasshift);
+/// and decreases by a
+//static const int initradius = (initrad * radiusbias);
+// factor of 1/30 each cycle
+static const int radiusdec = 30;
+//@}
+
+/**@name defs for decreasing alpha factor */
+//@{
+/// alpha starts at 1.0
+static const int alphabiasshift = 10;
+static const int initalpha = (((int)1) << alphabiasshift);
+//@}
+
+/**@name radbias and alpharadbias used for radpower calculation */
+//@{
+static const int radbiasshift = 8;
+static const int radbias = (((int)1) << radbiasshift);
+static const int alpharadbshift = (alphabiasshift+radbiasshift);
+static const int alpharadbias = (((int)1) << alpharadbshift);
+//@}
+
+class NNQuantizer
+{
+protected:
+ /**@name image parameters */
+ //@{
+ /// pointer to input dib
+ FIBITMAP *dib_ptr;
+ /// image width
+ int img_width;
+ /// image height
+ int img_height;
+ /// image line length
+ int img_line;
+ //@}
+
+ /**@name network parameters */
+ //@{
+
+ int netsize, maxnetpos, initrad, initradius;
+
+ /// BGRc
+ typedef int pixel[4];
+ /// the network itself
+ pixel *network;
+
+ /// for network lookup - really 256
+ int netindex[256];
+
+ /// bias array for learning
+ int *bias;
+ /// freq array for learning
+ int *freq;
+ /// radpower for precomputation
+ int *radpower;
+ //@}
+
+protected:
+ /// Initialise network in range (0,0,0) to (255,255,255) and set parameters
+ void initnet();
+
+ /// Unbias network to give byte values 0..255 and record position i to prepare for sort
+ void unbiasnet();
+
+ /// Insertion sort of network and building of netindex[0..255] (to do after unbias)
+ void inxbuild();
+
+ /// Search for BGR values 0..255 (after net is unbiased) and return colour index
+ int inxsearch(int b, int g, int r);
+
+ /// Search for biased BGR values
+ int contest(int b, int g, int r);
+
+ /// Move neuron i towards biased (b,g,r) by factor alpha
+ void altersingle(int alpha, int i, int b, int g, int r);
+
+ /// Move adjacent neurons by precomputed alpha*(1-((i-j)^2/[r]^2)) in radpower[|i-j|]
+ void alterneigh(int rad, int i, int b, int g, int r);
+
+ /** Main Learning Loop
+ @param sampling_factor sampling factor in [1..30]
+ */
+ void learn(int sampling_factor);
+
+ /// Get a pixel sample at position pos. Handle 4-byte boundary alignment.
+ void getSample(long pos, int *b, int *g, int *r);
+
+
+public:
+ /// Constructor
+ NNQuantizer(int PaletteSize);
+
+ /// Destructor
+ ~NNQuantizer();
+
+ /** Quantizer
+ @param dib input 24-bit dib to be quantized
+ @param sampling a sampling factor in range 1..30.
+ 1 => slower (but better), 30 => faster. Default value is 1
+ @return returns the quantized 8-bit (color palette) DIB
+ */
+ FIBITMAP* Quantize(FIBITMAP *dib, int ReserveSize, RGBQUAD *ReservePalette, int sampling = 1);
+
+};
+
diff --git a/Source/ToneMapping.h b/Source/ToneMapping.h
new file mode 100644
index 0000000..0519933
--- /dev/null
+++ b/Source/ToneMapping.h
@@ -0,0 +1,44 @@
+// ==========================================================
+// High Dynamic Range bitmap conversion routines
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef TONE_MAPPING_H
+#define TONE_MAPPING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BOOL ConvertInPlaceRGBFToYxy(FIBITMAP *dib);
+BOOL ConvertInPlaceYxyToRGBF(FIBITMAP *dib);
+FIBITMAP* ConvertRGBFToY(FIBITMAP *src);
+
+BOOL LuminanceFromYxy(FIBITMAP *dib, float *maxLum, float *minLum, float *worldLum);
+BOOL LuminanceFromY(FIBITMAP *dib, float *maxLum, float *minLum, float *Lav, float *Llav);
+
+void NormalizeY(FIBITMAP *Y, float minPrct, float maxPrct);
+
+FIBITMAP* ClampConvertRGBFTo24(FIBITMAP *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // TONE_MAPPING_H
diff --git a/Source/Utilities.h b/Source/Utilities.h
new file mode 100644
index 0000000..f1492cb
--- /dev/null
+++ b/Source/Utilities.h
@@ -0,0 +1,353 @@
+// ==========================================================
+// Utility functions
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+// - Hervé Drolon <drolon@infonie.fr>
+// - Ryan Rubley (ryan@lostreality.org)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef UTILITIES_H
+#define UTILITIES_H
+
+// ==========================================================
+// Standard includes used by the library
+// ==========================================================
+
+#include <math.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <assert.h>
+#include <limits.h>
+
+#include <string>
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+#include <stack>
+#include <sstream>
+#include <algorithm>
+
+// ==========================================================
+// Bitmap palette and pixels alignment
+// ==========================================================
+
+#define FIBITMAP_ALIGNMENT 16 // We will use a 16 bytes alignment boundary
+
+// Memory allocation on a specified alignment boundary
+// defined in BitmapAccess.cpp
+
+void* FreeImage_Aligned_Malloc(size_t amount, size_t alignment);
+void FreeImage_Aligned_Free(void* mem);
+
+// ==========================================================
+// File I/O structs
+// ==========================================================
+
+// these structs are for file I/O and should not be confused with similar
+// structs in FreeImage.h which are for in-memory bitmap handling
+
+#ifdef _WIN32
+#pragma pack(push, 1)
+#else
+#pragma pack(1)
+#endif // _WIN32
+
+typedef struct tagFILE_RGBA {
+ unsigned char r,g,b,a;
+} FILE_RGBA;
+
+typedef struct tagFILE_BGRA {
+ unsigned char b,g,r,a;
+} FILE_BGRA;
+
+typedef struct tagFILE_RGB {
+ unsigned char r,g,b;
+} FILE_RGB;
+
+typedef struct tagFILE_BGR {
+ unsigned char b,g,r;
+} FILE_BGR;
+
+#ifdef _WIN32
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif // _WIN32
+
+// ==========================================================
+// Utility functions
+// ==========================================================
+
+#ifndef _WIN32
+inline char*
+i2a(unsigned i, char *a, unsigned r) {
+ if (i/r > 0) a = i2a(i/r,a,r);
+ *a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i%r];
+ return a+1;
+}
+
+/**
+ Transforms integer i into an ascii string and stores the result in a;
+ string is encoded in the base indicated by r.
+ @param i Number to be converted
+ @param a String result
+ @param r Base of value; must be in the range 2 - 36
+ @return Returns a
+*/
+inline char *
+_itoa(int i, char *a, int r) {
+ r = ((r < 2) || (r > 36)) ? 10 : r;
+ if(i < 0) {
+ *a = '-';
+ *i2a(-i, a+1, r) = 0;
+ }
+ else *i2a(i, a, r) = 0;
+ return a;
+}
+
+#endif // !_WIN32
+
+inline unsigned char
+HINIBBLE (unsigned char byte) {
+ return byte & 0xF0;
+}
+
+inline unsigned char
+LOWNIBBLE (unsigned char byte) {
+ return byte & 0x0F;
+}
+
+inline int
+CalculateUsedBits(int bits) {
+ int bit_count = 0;
+ unsigned bit = 1;
+
+ for (unsigned i = 0; i < 32; i++) {
+ if ((bits & bit) == bit) {
+ bit_count++;
+ }
+
+ bit <<= 1;
+ }
+
+ return bit_count;
+}
+
+inline int
+CalculateLine(int width, int bitdepth) {
+ return ((width * bitdepth) + 7) / 8;
+}
+
+inline int
+CalculatePitch(int line) {
+ return line + 3 & ~3;
+}
+
+inline int
+CalculateUsedPaletteEntries(int bit_count) {
+ if ((bit_count >= 1) && (bit_count <= 8))
+ return 1 << bit_count;
+
+ return 0;
+}
+
+inline unsigned char *
+CalculateScanLine(unsigned char *bits, unsigned pitch, int scanline) {
+ return (bits + (pitch * scanline));
+}
+
+inline void
+ReplaceExtension(char *result, const char *filename, const char *extension) {
+ for (size_t i = strlen(filename) - 1; i > 0; --i) {
+ if (filename[i] == '.') {
+ memcpy(result, filename, i);
+ result[i] = '.';
+ memcpy(result + i + 1, extension, strlen(extension) + 1);
+ return;
+ }
+ }
+
+ memcpy(result, filename, strlen(filename));
+ result[strlen(filename)] = '.';
+ memcpy(result + strlen(filename) + 1, extension, strlen(extension) + 1);
+}
+
+// ==========================================================
+// Big Endian / Little Endian utility functions
+// ==========================================================
+
+inline WORD
+__SwapUInt16(WORD arg) {
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+ return _byteswap_ushort(arg);
+#elif defined(__i386__) && defined(__GNUC__)
+ __asm__("xchgb %b0, %h0" : "+q" (arg));
+ return arg;
+#elif defined(__ppc__) && defined(__GNUC__)
+ WORD result;
+ __asm__("lhbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg));
+ return result;
+#else
+ // swap bytes
+ WORD result;
+ result = ((arg << 8) & 0xFF00) | ((arg >> 8) & 0x00FF);
+ return result;
+#endif
+}
+
+inline DWORD
+__SwapUInt32(DWORD arg) {
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+ return _byteswap_ulong(arg);
+#elif defined(__i386__) && defined(__GNUC__)
+ __asm__("bswap %0" : "+r" (arg));
+ return arg;
+#elif defined(__ppc__) && defined(__GNUC__)
+ DWORD result;
+ __asm__("lwbrx %0,0,%1" : "=r" (result) : "r" (&arg), "m" (arg));
+ return result;
+#else
+ // swap words then bytes
+ DWORD result;
+ result = ((arg & 0x000000FF) << 24) | ((arg & 0x0000FF00) << 8) | ((arg >> 8) & 0x0000FF00) | ((arg >> 24) & 0x000000FF);
+ return result;
+#endif
+}
+
+/**
+for later use ...
+inline uint64_t
+SwapInt64(uint64_t arg) {
+#if defined(_MSC_VER) && _MSC_VER >= 1310
+ return _byteswap_uint64(arg);
+#else
+ union Swap {
+ uint64_t sv;
+ uint32_t ul[2];
+ } tmp, result;
+ tmp.sv = arg;
+ result.ul[0] = SwapInt32(tmp.ul[1]);
+ result.ul[1] = SwapInt32(tmp.ul[0]);
+ return result.sv;
+#endif
+}
+*/
+
+inline void
+SwapShort(WORD *sp) {
+ *sp = __SwapUInt16(*sp);
+}
+
+inline void
+SwapLong(DWORD *lp) {
+ *lp = __SwapUInt32(*lp);
+}
+
+// ==========================================================
+// Greyscale and color conversion
+// ==========================================================
+
+#define GREY(r, g, b) (BYTE)(((WORD)r * 77 + (WORD)g * 150 + (WORD)b * 29) >> 8) // .299R + .587G + .114B
+/*
+#define GREY(r, g, b) (BYTE)(((WORD)r * 169 + (WORD)g * 256 + (WORD)b * 87) >> 9) // .33R + 0.5G + .17B
+*/
+
+#define RGB565(b, g, r) ((((b) >> 3) << FI16_565_BLUE_SHIFT) | (((g) >> 2) << FI16_565_GREEN_SHIFT) | (((r) >> 3) << FI16_565_RED_SHIFT))
+#define RGB555(b, g, r) ((((b) >> 3) << FI16_555_BLUE_SHIFT) | (((g) >> 3) << FI16_555_GREEN_SHIFT) | (((r) >> 3) << FI16_555_RED_SHIFT))
+
+#define FORMAT_RGB565(dib) ((FreeImage_GetRedMask(dib) == FI16_565_RED_MASK) &&(FreeImage_GetGreenMask(dib) == FI16_565_GREEN_MASK) &&(FreeImage_GetBlueMask(dib) == FI16_565_BLUE_MASK))
+#define RGBQUAD_TO_WORD(dib, color) (FORMAT_RGB565(dib) ? RGB565((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed) : RGB555((color)->rgbBlue, (color)->rgbGreen, (color)->rgbRed))
+
+#define CREATE_GREYSCALE_PALETTE(palette, entries) \
+ for (unsigned i = 0, v = 0; i < entries; i++, v += 0x00FFFFFF / (entries - 1)) { \
+ ((unsigned *)palette)[i] = v; \
+ }
+
+#define CREATE_GREYSCALE_PALETTE_REVERSE(palette, entries) \
+ for (unsigned i = 0, v = 0x00FFFFFF; i < entries; i++, v -= (0x00FFFFFF / (entries - 1))) { \
+ ((unsigned *)palette)[i] = v; \
+ }
+
+// ==========================================================
+// Template utility functions
+// ==========================================================
+
+/// Max function
+template <class T> T MAX(T a, T b) {
+ return (a > b) ? a: b;
+}
+
+/// Min function
+template <class T> T MIN(T a, T b) {
+ return (a < b) ? a: b;
+}
+
+/// INPLACESWAP adopted from codeguru.com
+template <class T> void INPLACESWAP(T& a, T& b) {
+ a ^= b; b ^= a; a ^= b;
+}
+
+/** This procedure computes minimum min and maximum max
+ of n numbers using only (3n/2) - 2 comparisons.
+ min = L[i1] and max = L[i2].
+ ref: Aho A.V., Hopcroft J.E., Ullman J.D.,
+ The design and analysis of computer algorithms,
+ Addison-Wesley, Reading, 1974.
+*/
+template <class T> void
+MAXMIN(const T* L, long n, T& max, T& min) {
+ long i1, i2, i, j;
+ T x1, x2;
+ long k1, k2;
+
+ i1 = 0; i2 = 0; min = L[0]; max = L[0]; j = 0;
+ if((n % 2) != 0) j = 1;
+ for(i = j; i < n; i+= 2) {
+ k1 = i; k2 = i+1;
+ x1 = L[k1]; x2 = L[k2];
+ if(x1 > x2) {
+ k1 = k2; k2 = i;
+ x1 = x2; x2 = L[k2];
+ }
+ if(x1 < min) {
+ min = x1; i1 = k1;
+ }
+ if(x2 > max) {
+ max = x2; i2 = k2;
+ }
+ }
+}
+
+// ==========================================================
+// Generic error messages
+// ==========================================================
+
+static const char *FI_MSG_ERROR_MEMORY = "Memory allocation failed";
+static const char *FI_MSG_ERROR_DIB_MEMORY = "DIB allocation failed";
+static const char *FI_MSG_ERROR_PARSING = "Parsing error";
+static const char *FI_MSG_ERROR_MAGIC_NUMBER = "Invalid magic number";
+static const char *FI_MSG_ERROR_UNSUPPORTED_FORMAT = "Unsupported format";
+static const char *FI_MSG_ERROR_UNSUPPORTED_COMPRESSION = "Unsupported compression type";
+
+
+#endif // UTILITIES_H
diff --git a/Source/ZLib/ChangeLog b/Source/ZLib/ChangeLog
new file mode 100644
index 0000000..cf115de
--- /dev/null
+++ b/Source/ZLib/ChangeLog
@@ -0,0 +1,855 @@
+
+ ChangeLog file for zlib
+
+Changes in 1.2.3 (18 July 2005)
+- Apply security vulnerability fixes to contrib/infback9 as well
+- Clean up some text files (carriage returns, trailing space)
+- Update testzlib, vstudio, masmx64, and masmx86 in contrib [Vollant]
+
+Changes in 1.2.2.4 (11 July 2005)
+- Add inflatePrime() function for starting inflation at bit boundary
+- Avoid some Visual C warnings in deflate.c
+- Avoid more silly Visual C warnings in inflate.c and inftrees.c for 64-bit
+ compile
+- Fix some spelling errors in comments [Betts]
+- Correct inflateInit2() error return documentation in zlib.h
+- Added zran.c example of compressed data random access to examples
+ directory, shows use of inflatePrime()
+- Fix cast for assignments to strm->state in inflate.c and infback.c
+- Fix zlibCompileFlags() in zutil.c to use 1L for long shifts [Oberhumer]
+- Move declarations of gf2 functions to right place in crc32.c [Oberhumer]
+- Add cast in trees.c t avoid a warning [Oberhumer]
+- Avoid some warnings in fitblk.c, gun.c, gzjoin.c in examples [Oberhumer]
+- Update make_vms.com [Zinser]
+- Initialize state->write in inflateReset() since copied in inflate_fast()
+- Be more strict on incomplete code sets in inflate_table() and increase
+ ENOUGH and MAXD -- this repairs a possible security vulnerability for
+ invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
+ discovering the vulnerability and providing test cases.
+- Add ia64 support to configure for HP-UX [Smith]
+- Add error return to gzread() for format or i/o error [Levin]
+- Use malloc.h for OS/2 [Necasek]
+
+Changes in 1.2.2.3 (27 May 2005)
+- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
+- Typecast fread() return values in gzio.c [Vollant]
+- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
+- Fix crc check bug in gzread() after gzungetc() [Heiner]
+- Add the deflateTune() function to adjust internal compression parameters
+- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
+- Remove an incorrect assertion in examples/zpipe.c
+- Add C++ wrapper in infback9.h [Donais]
+- Fix bug in inflateCopy() when decoding fixed codes
+- Note in zlib.h how much deflateSetDictionary() actually uses
+- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
+- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
+- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
+- Add gzdirect() function to indicate transparent reads
+- Update contrib/minizip [Vollant]
+- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
+- Add casts in crc32.c to avoid warnings [Oberhumer]
+- Add contrib/masmx64 [Vollant]
+- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
+
+Changes in 1.2.2.2 (30 December 2004)
+- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
+ avoid implicit memcpy calls (portability for no-library compilation)
+- Increase sprintf() buffer size in gzdopen() to allow for large numbers
+- Add INFLATE_STRICT to check distances against zlib header
+- Improve WinCE errno handling and comments [Chang]
+- Remove comment about no gzip header processing in FAQ
+- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
+- Add updated make_vms.com [Coghlan], update README
+- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
+ fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
+- Add FAQ entry and comments in deflate.c on uninitialized memory access
+- Add Solaris 9 make options in configure [Gilbert]
+- Allow strerror() usage in gzio.c for STDC
+- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
+- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
+- Use z_off_t for adler32_combine() and crc32_combine() lengths
+- Make adler32() much faster for small len
+- Use OS_CODE in deflate() default gzip header
+
+Changes in 1.2.2.1 (31 October 2004)
+- Allow inflateSetDictionary() call for raw inflate
+- Fix inflate header crc check bug for file names and comments
+- Add deflateSetHeader() and gz_header structure for custom gzip headers
+- Add inflateGetheader() to retrieve gzip headers
+- Add crc32_combine() and adler32_combine() functions
+- Add alloc_func, free_func, in_func, out_func to Z_PREFIX list
+- Use zstreamp consistently in zlib.h (inflate_back functions)
+- Remove GUNZIP condition from definition of inflate_mode in inflate.h
+ and in contrib/inflate86/inffast.S [Truta, Anderson]
+- Add support for AMD64 in contrib/inflate86/inffas86.c [Anderson]
+- Update projects/README.projects and projects/visualc6 [Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Avoid warning under NO_GZCOMPRESS in gzio.c; fix typo [Truta]
+- Deprecate Z_ASCII; use Z_TEXT instead [Truta]
+- Use a new algorithm for setting strm->data_type in trees.c [Truta]
+- Do not define an exit() prototype in zutil.c unless DEBUG defined
+- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
+- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
+- Fix Darwin build version identification [Peterson]
+
+Changes in 1.2.2 (3 October 2004)
+- Update zlib.h comments on gzip in-memory processing
+- Set adler to 1 in inflateReset() to support Java test suite [Walles]
+- Add contrib/dotzlib [Ravn]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update contrib/minizip [Vollant]
+- Move contrib/visual-basic.txt to old/ [Truta]
+- Fix assembler builds in projects/visualc6/ [Truta]
+
+Changes in 1.2.1.2 (9 September 2004)
+- Update INDEX file
+- Fix trees.c to update strm->data_type (no one ever noticed!)
+- Fix bug in error case in inflate.c, infback.c, and infback9.c [Brown]
+- Add "volatile" to crc table flag declaration (for DYNAMIC_CRC_TABLE)
+- Add limited multitasking protection to DYNAMIC_CRC_TABLE
+- Add NO_vsnprintf for VMS in zutil.h [Mozilla]
+- Don't declare strerror() under VMS [Mozilla]
+- Add comment to DYNAMIC_CRC_TABLE to use get_crc_table() to initialize
+- Update contrib/ada [Anisimkov]
+- Update contrib/minizip [Vollant]
+- Fix configure to not hardcode directories for Darwin [Peterson]
+- Fix gzio.c to not return error on empty files [Brown]
+- Fix indentation; update version in contrib/delphi/ZLib.pas and
+ contrib/pascal/zlibpas.pas [Truta]
+- Update mkasm.bat in contrib/masmx86 [Truta]
+- Update contrib/untgz [Truta]
+- Add projects/README.projects [Truta]
+- Add project for MS Visual C++ 6.0 in projects/visualc6 [Cadieux, Truta]
+- Update win32/DLL_FAQ.txt [Truta]
+- Update list of Z_PREFIX symbols in zconf.h [Randers-Pehrson, Truta]
+- Remove an unnecessary assignment to curr in inftrees.c [Truta]
+- Add OS/2 to exe builds in configure [Poltorak]
+- Remove err dummy parameter in zlib.h [Kientzle]
+
+Changes in 1.2.1.1 (9 January 2004)
+- Update email address in README
+- Several FAQ updates
+- Fix a big fat bug in inftrees.c that prevented decoding valid
+ dynamic blocks with only literals and no distance codes --
+ Thanks to "Hot Emu" for the bug report and sample file
+- Add a note to puff.c on no distance codes case.
+
+Changes in 1.2.1 (17 November 2003)
+- Remove a tab in contrib/gzappend/gzappend.c
+- Update some interfaces in contrib for new zlib functions
+- Update zlib version number in some contrib entries
+- Add Windows CE definition for ptrdiff_t in zutil.h [Mai, Truta]
+- Support shared libraries on Hurd and KFreeBSD [Brown]
+- Fix error in NO_DIVIDE option of adler32.c
+
+Changes in 1.2.0.8 (4 November 2003)
+- Update version in contrib/delphi/ZLib.pas and contrib/pascal/zlibpas.pas
+- Add experimental NO_DIVIDE #define in adler32.c
+ - Possibly faster on some processors (let me know if it is)
+- Correct Z_BLOCK to not return on first inflate call if no wrap
+- Fix strm->data_type on inflate() return to correctly indicate EOB
+- Add deflatePrime() function for appending in the middle of a byte
+- Add contrib/gzappend for an example of appending to a stream
+- Update win32/DLL_FAQ.txt [Truta]
+- Delete Turbo C comment in README [Truta]
+- Improve some indentation in zconf.h [Truta]
+- Fix infinite loop on bad input in configure script [Church]
+- Fix gzeof() for concatenated gzip files [Johnson]
+- Add example to contrib/visual-basic.txt [Michael B.]
+- Add -p to mkdir's in Makefile.in [vda]
+- Fix configure to properly detect presence or lack of printf functions
+- Add AS400 support [Monnerat]
+- Add a little Cygwin support [Wilson]
+
+Changes in 1.2.0.7 (21 September 2003)
+- Correct some debug formats in contrib/infback9
+- Cast a type in a debug statement in trees.c
+- Change search and replace delimiter in configure from % to # [Beebe]
+- Update contrib/untgz to 0.2 with various fixes [Truta]
+- Add build support for Amiga [Nikl]
+- Remove some directories in old that have been updated to 1.2
+- Add dylib building for Mac OS X in configure and Makefile.in
+- Remove old distribution stuff from Makefile
+- Update README to point to DLL_FAQ.txt, and add comment on Mac OS X
+- Update links in README
+
+Changes in 1.2.0.6 (13 September 2003)
+- Minor FAQ updates
+- Update contrib/minizip to 1.00 [Vollant]
+- Remove test of gz functions in example.c when GZ_COMPRESS defined [Truta]
+- Update POSTINC comment for 68060 [Nikl]
+- Add contrib/infback9 with deflate64 decoding (unsupported)
+- For MVS define NO_vsnprintf and undefine FAR [van Burik]
+- Add pragma for fdopen on MVS [van Burik]
+
+Changes in 1.2.0.5 (8 September 2003)
+- Add OF to inflateBackEnd() declaration in zlib.h
+- Remember start when using gzdopen in the middle of a file
+- Use internal off_t counters in gz* functions to properly handle seeks
+- Perform more rigorous check for distance-too-far in inffast.c
+- Add Z_BLOCK flush option to return from inflate at block boundary
+- Set strm->data_type on return from inflate
+ - Indicate bits unused, if at block boundary, and if in last block
+- Replace size_t with ptrdiff_t in crc32.c, and check for correct size
+- Add condition so old NO_DEFLATE define still works for compatibility
+- FAQ update regarding the Windows DLL [Truta]
+- INDEX update: add qnx entry, remove aix entry [Truta]
+- Install zlib.3 into mandir [Wilson]
+- Move contrib/zlib_dll_FAQ.txt to win32/DLL_FAQ.txt; update [Truta]
+- Adapt the zlib interface to the new DLL convention guidelines [Truta]
+- Introduce ZLIB_WINAPI macro to allow the export of functions using
+ the WINAPI calling convention, for Visual Basic [Vollant, Truta]
+- Update msdos and win32 scripts and makefiles [Truta]
+- Export symbols by name, not by ordinal, in win32/zlib.def [Truta]
+- Add contrib/ada [Anisimkov]
+- Move asm files from contrib/vstudio/vc70_32 to contrib/asm386 [Truta]
+- Rename contrib/asm386 to contrib/masmx86 [Truta, Vollant]
+- Add contrib/masm686 [Truta]
+- Fix offsets in contrib/inflate86 and contrib/masmx86/inffas32.asm
+ [Truta, Vollant]
+- Update contrib/delphi; rename to contrib/pascal; add example [Truta]
+- Remove contrib/delphi2; add a new contrib/delphi [Truta]
+- Avoid inclusion of the nonstandard <memory.h> in contrib/iostream,
+ and fix some method prototypes [Truta]
+- Fix the ZCR_SEED2 constant to avoid warnings in contrib/minizip
+ [Truta]
+- Avoid the use of backslash (\) in contrib/minizip [Vollant]
+- Fix file time handling in contrib/untgz; update makefiles [Truta]
+- Update contrib/vstudio/vc70_32 to comply with the new DLL guidelines
+ [Vollant]
+- Remove contrib/vstudio/vc15_16 [Vollant]
+- Rename contrib/vstudio/vc70_32 to contrib/vstudio/vc7 [Truta]
+- Update README.contrib [Truta]
+- Invert the assignment order of match_head and s->prev[...] in
+ INSERT_STRING [Truta]
+- Compare TOO_FAR with 32767 instead of 32768, to avoid 16-bit warnings
+ [Truta]
+- Compare function pointers with 0, not with NULL or Z_NULL [Truta]
+- Fix prototype of syncsearch in inflate.c [Truta]
+- Introduce ASMINF macro to be enabled when using an ASM implementation
+ of inflate_fast [Truta]
+- Change NO_DEFLATE to NO_GZCOMPRESS [Truta]
+- Modify test_gzio in example.c to take a single file name as a
+ parameter [Truta]
+- Exit the example.c program if gzopen fails [Truta]
+- Add type casts around strlen in example.c [Truta]
+- Remove casting to sizeof in minigzip.c; give a proper type
+ to the variable compared with SUFFIX_LEN [Truta]
+- Update definitions of STDC and STDC99 in zconf.h [Truta]
+- Synchronize zconf.h with the new Windows DLL interface [Truta]
+- Use SYS16BIT instead of __32BIT__ to distinguish between
+ 16- and 32-bit platforms [Truta]
+- Use far memory allocators in small 16-bit memory models for
+ Turbo C [Truta]
+- Add info about the use of ASMV, ASMINF and ZLIB_WINAPI in
+ zlibCompileFlags [Truta]
+- Cygwin has vsnprintf [Wilson]
+- In Windows16, OS_CODE is 0, as in MSDOS [Truta]
+- In Cygwin, OS_CODE is 3 (Unix), not 11 (Windows32) [Wilson]
+
+Changes in 1.2.0.4 (10 August 2003)
+- Minor FAQ updates
+- Be more strict when checking inflateInit2's windowBits parameter
+- Change NO_GUNZIP compile option to NO_GZIP to cover deflate as well
+- Add gzip wrapper option to deflateInit2 using windowBits
+- Add updated QNX rule in configure and qnx directory [Bonnefoy]
+- Make inflate distance-too-far checks more rigorous
+- Clean up FAR usage in inflate
+- Add casting to sizeof() in gzio.c and minigzip.c
+
+Changes in 1.2.0.3 (19 July 2003)
+- Fix silly error in gzungetc() implementation [Vollant]
+- Update contrib/minizip and contrib/vstudio [Vollant]
+- Fix printf format in example.c
+- Correct cdecl support in zconf.in.h [Anisimkov]
+- Minor FAQ updates
+
+Changes in 1.2.0.2 (13 July 2003)
+- Add ZLIB_VERNUM in zlib.h for numerical preprocessor comparisons
+- Attempt to avoid warnings in crc32.c for pointer-int conversion
+- Add AIX to configure, remove aix directory [Bakker]
+- Add some casts to minigzip.c
+- Improve checking after insecure sprintf() or vsprintf() calls
+- Remove #elif's from crc32.c
+- Change leave label to inf_leave in inflate.c and infback.c to avoid
+ library conflicts
+- Remove inflate gzip decoding by default--only enable gzip decoding by
+ special request for stricter backward compatibility
+- Add zlibCompileFlags() function to return compilation information
+- More typecasting in deflate.c to avoid warnings
+- Remove leading underscore from _Capital #defines [Truta]
+- Fix configure to link shared library when testing
+- Add some Windows CE target adjustments [Mai]
+- Remove #define ZLIB_DLL in zconf.h [Vollant]
+- Add zlib.3 [Rodgers]
+- Update RFC URL in deflate.c and algorithm.txt [Mai]
+- Add zlib_dll_FAQ.txt to contrib [Truta]
+- Add UL to some constants [Truta]
+- Update minizip and vstudio [Vollant]
+- Remove vestigial NEED_DUMMY_RETURN from zconf.in.h
+- Expand use of NO_DUMMY_DECL to avoid all dummy structures
+- Added iostream3 to contrib [Schwardt]
+- Replace rewind() with fseek() for WinCE [Truta]
+- Improve setting of zlib format compression level flags
+ - Report 0 for huffman and rle strategies and for level == 0 or 1
+ - Report 2 only for level == 6
+- Only deal with 64K limit when necessary at compile time [Truta]
+- Allow TOO_FAR check to be turned off at compile time [Truta]
+- Add gzclearerr() function [Souza]
+- Add gzungetc() function
+
+Changes in 1.2.0.1 (17 March 2003)
+- Add Z_RLE strategy for run-length encoding [Truta]
+ - When Z_RLE requested, restrict matches to distance one
+ - Update zlib.h, minigzip.c, gzopen(), gzdopen() for Z_RLE
+- Correct FASTEST compilation to allow level == 0
+- Clean up what gets compiled for FASTEST
+- Incorporate changes to zconf.in.h [Vollant]
+ - Refine detection of Turbo C need for dummy returns
+ - Refine ZLIB_DLL compilation
+ - Include additional header file on VMS for off_t typedef
+- Try to use _vsnprintf where it supplants vsprintf [Vollant]
+- Add some casts in inffast.c
+- Enchance comments in zlib.h on what happens if gzprintf() tries to
+ write more than 4095 bytes before compression
+- Remove unused state from inflateBackEnd()
+- Remove exit(0) from minigzip.c, example.c
+- Get rid of all those darn tabs
+- Add "check" target to Makefile.in that does the same thing as "test"
+- Add "mostlyclean" and "maintainer-clean" targets to Makefile.in
+- Update contrib/inflate86 [Anderson]
+- Update contrib/testzlib, contrib/vstudio, contrib/minizip [Vollant]
+- Add msdos and win32 directories with makefiles [Truta]
+- More additions and improvements to the FAQ
+
+Changes in 1.2.0 (9 March 2003)
+- New and improved inflate code
+ - About 20% faster
+ - Does not allocate 32K window unless and until needed
+ - Automatically detects and decompresses gzip streams
+ - Raw inflate no longer needs an extra dummy byte at end
+ - Added inflateBack functions using a callback interface--even faster
+ than inflate, useful for file utilities (gzip, zip)
+ - Added inflateCopy() function to record state for random access on
+ externally generated deflate streams (e.g. in gzip files)
+ - More readable code (I hope)
+- New and improved crc32()
+ - About 50% faster, thanks to suggestions from Rodney Brown
+- Add deflateBound() and compressBound() functions
+- Fix memory leak in deflateInit2()
+- Permit setting dictionary for raw deflate (for parallel deflate)
+- Fix const declaration for gzwrite()
+- Check for some malloc() failures in gzio.c
+- Fix bug in gzopen() on single-byte file 0x1f
+- Fix bug in gzread() on concatenated file with 0x1f at end of buffer
+ and next buffer doesn't start with 0x8b
+- Fix uncompress() to return Z_DATA_ERROR on truncated input
+- Free memory at end of example.c
+- Remove MAX #define in trees.c (conflicted with some libraries)
+- Fix static const's in deflate.c, gzio.c, and zutil.[ch]
+- Declare malloc() and free() in gzio.c if STDC not defined
+- Use malloc() instead of calloc() in zutil.c if int big enough
+- Define STDC for AIX
+- Add aix/ with approach for compiling shared library on AIX
+- Add HP-UX support for shared libraries in configure
+- Add OpenUNIX support for shared libraries in configure
+- Use $cc instead of gcc to build shared library
+- Make prefix directory if needed when installing
+- Correct Macintosh avoidance of typedef Byte in zconf.h
+- Correct Turbo C memory allocation when under Linux
+- Use libz.a instead of -lz in Makefile (assure use of compiled library)
+- Update configure to check for snprintf or vsnprintf functions and their
+ return value, warn during make if using an insecure function
+- Fix configure problem with compile-time knowledge of HAVE_UNISTD_H that
+ is lost when library is used--resolution is to build new zconf.h
+- Documentation improvements (in zlib.h):
+ - Document raw deflate and inflate
+ - Update RFCs URL
+ - Point out that zlib and gzip formats are different
+ - Note that Z_BUF_ERROR is not fatal
+ - Document string limit for gzprintf() and possible buffer overflow
+ - Note requirement on avail_out when flushing
+ - Note permitted values of flush parameter of inflate()
+- Add some FAQs (and even answers) to the FAQ
+- Add contrib/inflate86/ for x86 faster inflate
+- Add contrib/blast/ for PKWare Data Compression Library decompression
+- Add contrib/puff/ simple inflate for deflate format description
+
+Changes in 1.1.4 (11 March 2002)
+- ZFREE was repeated on same allocation on some error conditions.
+ This creates a security problem described in
+ http://www.zlib.org/advisory-2002-03-11.txt
+- Returned incorrect error (Z_MEM_ERROR) on some invalid data
+- Avoid accesses before window for invalid distances with inflate window
+ less than 32K.
+- force windowBits > 8 to avoid a bug in the encoder for a window size
+ of 256 bytes. (A complete fix will be available in 1.1.5).
+
+Changes in 1.1.3 (9 July 1998)
+- fix "an inflate input buffer bug that shows up on rare but persistent
+ occasions" (Mark)
+- fix gzread and gztell for concatenated .gz files (Didier Le Botlan)
+- fix gzseek(..., SEEK_SET) in write mode
+- fix crc check after a gzeek (Frank Faubert)
+- fix miniunzip when the last entry in a zip file is itself a zip file
+ (J Lillge)
+- add contrib/asm586 and contrib/asm686 (Brian Raiter)
+ See http://www.muppetlabs.com/~breadbox/software/assembly.html
+- add support for Delphi 3 in contrib/delphi (Bob Dellaca)
+- add support for C++Builder 3 and Delphi 3 in contrib/delphi2 (Davide Moretti)
+- do not exit prematurely in untgz if 0 at start of block (Magnus Holmgren)
+- use macro EXTERN instead of extern to support DLL for BeOS (Sander Stoks)
+- added a FAQ file
+
+- Support gzdopen on Mac with Metrowerks (Jason Linhart)
+- Do not redefine Byte on Mac (Brad Pettit & Jason Linhart)
+- define SEEK_END too if SEEK_SET is not defined (Albert Chin-A-Young)
+- avoid some warnings with Borland C (Tom Tanner)
+- fix a problem in contrib/minizip/zip.c for 16-bit MSDOS (Gilles Vollant)
+- emulate utime() for WIN32 in contrib/untgz (Gilles Vollant)
+- allow several arguments to configure (Tim Mooney, Frodo Looijaard)
+- use libdir and includedir in Makefile.in (Tim Mooney)
+- support shared libraries on OSF1 V4 (Tim Mooney)
+- remove so_locations in "make clean" (Tim Mooney)
+- fix maketree.c compilation error (Glenn, Mark)
+- Python interface to zlib now in Python 1.5 (Jeremy Hylton)
+- new Makefile.riscos (Rich Walker)
+- initialize static descriptors in trees.c for embedded targets (Nick Smith)
+- use "foo-gz" in example.c for RISCOS and VMS (Nick Smith)
+- add the OS/2 files in Makefile.in too (Andrew Zabolotny)
+- fix fdopen and halloc macros for Microsoft C 6.0 (Tom Lane)
+- fix maketree.c to allow clean compilation of inffixed.h (Mark)
+- fix parameter check in deflateCopy (Gunther Nikl)
+- cleanup trees.c, use compressed_len only in debug mode (Christian Spieler)
+- Many portability patches by Christian Spieler:
+ . zutil.c, zutil.h: added "const" for zmem*
+ . Make_vms.com: fixed some typos
+ . Make_vms.com: msdos/Makefile.*: removed zutil.h from some dependency lists
+ . msdos/Makefile.msc: remove "default rtl link library" info from obj files
+ . msdos/Makefile.*: use model-dependent name for the built zlib library
+ . msdos/Makefile.emx, nt/Makefile.emx, nt/Makefile.gcc:
+ new makefiles, for emx (DOS/OS2), emx&rsxnt and mingw32 (Windows 9x / NT)
+- use define instead of typedef for Bytef also for MSC small/medium (Tom Lane)
+- replace __far with _far for better portability (Christian Spieler, Tom Lane)
+- fix test for errno.h in configure (Tim Newsham)
+
+Changes in 1.1.2 (19 March 98)
+- added contrib/minzip, mini zip and unzip based on zlib (Gilles Vollant)
+ See http://www.winimage.com/zLibDll/unzip.html
+- preinitialize the inflate tables for fixed codes, to make the code
+ completely thread safe (Mark)
+- some simplifications and slight speed-up to the inflate code (Mark)
+- fix gzeof on non-compressed files (Allan Schrum)
+- add -std1 option in configure for OSF1 to fix gzprintf (Martin Mokrejs)
+- use default value of 4K for Z_BUFSIZE for 16-bit MSDOS (Tim Wegner + Glenn)
+- added os2/Makefile.def and os2/zlib.def (Andrew Zabolotny)
+- add shared lib support for UNIX_SV4.2MP (MATSUURA Takanori)
+- do not wrap extern "C" around system includes (Tom Lane)
+- mention zlib binding for TCL in README (Andreas Kupries)
+- added amiga/Makefile.pup for Amiga powerUP SAS/C PPC (Andreas Kleinert)
+- allow "make install prefix=..." even after configure (Glenn Randers-Pehrson)
+- allow "configure --prefix $HOME" (Tim Mooney)
+- remove warnings in example.c and gzio.c (Glenn Randers-Pehrson)
+- move Makefile.sas to amiga/Makefile.sas
+
+Changes in 1.1.1 (27 Feb 98)
+- fix macros _tr_tally_* in deflate.h for debug mode (Glenn Randers-Pehrson)
+- remove block truncation heuristic which had very marginal effect for zlib
+ (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
+ compression ratio on some files. This also allows inlining _tr_tally for
+ matches in deflate_slow.
+- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
+
+Changes in 1.1.0 (24 Feb 98)
+- do not return STREAM_END prematurely in inflate (John Bowler)
+- revert to the zlib 1.0.8 inflate to avoid the gcc 2.8.0 bug (Jeremy Buhler)
+- compile with -DFASTEST to get compression code optimized for speed only
+- in minigzip, try mmap'ing the input file first (Miguel Albrecht)
+- increase size of I/O buffers in minigzip.c and gzio.c (not a big gain
+ on Sun but significant on HP)
+
+- add a pointer to experimental unzip library in README (Gilles Vollant)
+- initialize variable gcc in configure (Chris Herborth)
+
+Changes in 1.0.9 (17 Feb 1998)
+- added gzputs and gzgets functions
+- do not clear eof flag in gzseek (Mark Diekhans)
+- fix gzseek for files in transparent mode (Mark Diekhans)
+- do not assume that vsprintf returns the number of bytes written (Jens Krinke)
+- replace EXPORT with ZEXPORT to avoid conflict with other programs
+- added compress2 in zconf.h, zlib.def, zlib.dnt
+- new asm code from Gilles Vollant in contrib/asm386
+- simplify the inflate code (Mark):
+ . Replace ZALLOC's in huft_build() with single ZALLOC in inflate_blocks_new()
+ . ZALLOC the length list in inflate_trees_fixed() instead of using stack
+ . ZALLOC the value area for huft_build() instead of using stack
+ . Simplify Z_FINISH check in inflate()
+
+- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
+- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
+- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
+ the declaration of FAR (Gilles VOllant)
+- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
+- read_buf buf parameter of type Bytef* instead of charf*
+- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
+- do not redeclare unlink in minigzip.c for WIN32 (John Bowler)
+- fix check for presence of directories in "make install" (Ian Willis)
+
+Changes in 1.0.8 (27 Jan 1998)
+- fixed offsets in contrib/asm386/gvmat32.asm (Gilles Vollant)
+- fix gzgetc and gzputc for big endian systems (Markus Oberhumer)
+- added compress2() to allow setting the compression level
+- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
+- use constant arrays for the static trees in trees.c instead of computing
+ them at run time (thanks to Ken Raeburn for this suggestion). To create
+ trees.h, compile with GEN_TREES_H and run "make test".
+- check return code of example in "make test" and display result
+- pass minigzip command line options to file_compress
+- simplifying code of inflateSync to avoid gcc 2.8 bug
+
+- support CC="gcc -Wall" in configure -s (QingLong)
+- avoid a flush caused by ftell in gzopen for write mode (Ken Raeburn)
+- fix test for shared library support to avoid compiler warnings
+- zlib.lib -> zlib.dll in msdos/zlib.rc (Gilles Vollant)
+- check for TARGET_OS_MAC in addition to MACOS (Brad Pettit)
+- do not use fdopen for Metrowerks on Mac (Brad Pettit))
+- add checks for gzputc and gzputc in example.c
+- avoid warnings in gzio.c and deflate.c (Andreas Kleinert)
+- use const for the CRC table (Ken Raeburn)
+- fixed "make uninstall" for shared libraries
+- use Tracev instead of Trace in infblock.c
+- in example.c use correct compressed length for test_sync
+- suppress +vnocompatwarnings in configure for HPUX (not always supported)
+
+Changes in 1.0.7 (20 Jan 1998)
+- fix gzseek which was broken in write mode
+- return error for gzseek to negative absolute position
+- fix configure for Linux (Chun-Chung Chen)
+- increase stack space for MSC (Tim Wegner)
+- get_crc_table and inflateSyncPoint are EXPORTed (Gilles Vollant)
+- define EXPORTVA for gzprintf (Gilles Vollant)
+- added man page zlib.3 (Rick Rodgers)
+- for contrib/untgz, fix makedir() and improve Makefile
+
+- check gzseek in write mode in example.c
+- allocate extra buffer for seeks only if gzseek is actually called
+- avoid signed/unsigned comparisons (Tim Wegner, Gilles Vollant)
+- add inflateSyncPoint in zconf.h
+- fix list of exported functions in nt/zlib.dnt and mdsos/zlib.def
+
+Changes in 1.0.6 (19 Jan 1998)
+- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
+ gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
+- Fix a deflate bug occurring only with compression level 0 (thanks to
+ Andy Buckler for finding this one).
+- In minigzip, pass transparently also the first byte for .Z files.
+- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
+- check Z_FINISH in inflate (thanks to Marc Schluper)
+- Implement deflateCopy (thanks to Adam Costello)
+- make static libraries by default in configure, add --shared option.
+- move MSDOS or Windows specific files to directory msdos
+- suppress the notion of partial flush to simplify the interface
+ (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
+- suppress history buffer provided by application to simplify the interface
+ (this feature was not implemented anyway in 1.0.4)
+- next_in and avail_in must be initialized before calling inflateInit or
+ inflateInit2
+- add EXPORT in all exported functions (for Windows DLL)
+- added Makefile.nt (thanks to Stephen Williams)
+- added the unsupported "contrib" directory:
+ contrib/asm386/ by Gilles Vollant <info@winimage.com>
+ 386 asm code replacing longest_match().
+ contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
+ A C++ I/O streams interface to the zlib gz* functions
+ contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
+ Another C++ I/O streams interface
+ contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
+ A very simple tar.gz file extractor using zlib
+ contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
+ How to use compress(), uncompress() and the gz* functions from VB.
+- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
+ level) in minigzip (thanks to Tom Lane)
+
+- use const for rommable constants in deflate
+- added test for gzseek and gztell in example.c
+- add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
+- add undocumented function zError to convert error code to string
+ (for Tim Smithers)
+- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code.
+- Use default memcpy for Symantec MSDOS compiler.
+- Add EXPORT keyword for check_func (needed for Windows DLL)
+- add current directory to LD_LIBRARY_PATH for "make test"
+- create also a link for libz.so.1
+- added support for FUJITSU UXP/DS (thanks to Toshiaki Nomura)
+- use $(SHAREDLIB) instead of libz.so in Makefile.in (for HPUX)
+- added -soname for Linux in configure (Chun-Chung Chen,
+- assign numbers to the exported functions in zlib.def (for Windows DLL)
+- add advice in zlib.h for best usage of deflateSetDictionary
+- work around compiler bug on Atari (cast Z_NULL in call of s->checkfn)
+- allow compilation with ANSI keywords only enabled for TurboC in large model
+- avoid "versionString"[0] (Borland bug)
+- add NEED_DUMMY_RETURN for Borland
+- use variable z_verbose for tracing in debug mode (L. Peter Deutsch).
+- allow compilation with CC
+- defined STDC for OS/2 (David Charlap)
+- limit external names to 8 chars for MVS (Thomas Lund)
+- in minigzip.c, use static buffers only for 16-bit systems
+- fix suffix check for "minigzip -d foo.gz"
+- do not return an error for the 2nd of two consecutive gzflush() (Felix Lee)
+- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
+- added makelcc.bat for lcc-win32 (Tom St Denis)
+- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
+- Avoid expanded $Id: ChangeLog,v 1.3 2005/08/27 17:22:42 drolon Exp $. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion.
+- check for unistd.h in configure (for off_t)
+- remove useless check parameter in inflate_blocks_free
+- avoid useless assignment of s->check to itself in inflate_blocks_new
+- do not flush twice in gzclose (thanks to Ken Raeburn)
+- rename FOPEN as F_OPEN to avoid clash with /usr/include/sys/file.h
+- use NO_ERRNO_H instead of enumeration of operating systems with errno.h
+- work around buggy fclose on pipes for HP/UX
+- support zlib DLL with BORLAND C++ 5.0 (thanks to Glenn Randers-Pehrson)
+- fix configure if CC is already equal to gcc
+
+Changes in 1.0.5 (3 Jan 98)
+- Fix inflate to terminate gracefully when fed corrupted or invalid data
+- Use const for rommable constants in inflate
+- Eliminate memory leaks on error conditions in inflate
+- Removed some vestigial code in inflate
+- Update web address in README
+
+Changes in 1.0.4 (24 Jul 96)
+- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
+ bit, so the decompressor could decompress all the correct data but went
+ on to attempt decompressing extra garbage data. This affected minigzip too.
+- zlibVersion and gzerror return const char* (needed for DLL)
+- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
+- use z_error only for DEBUG (avoid problem with DLLs)
+
+Changes in 1.0.3 (2 Jul 96)
+- use z_streamp instead of z_stream *, which is now a far pointer in MSDOS
+ small and medium models; this makes the library incompatible with previous
+ versions for these models. (No effect in large model or on other systems.)
+- return OK instead of BUF_ERROR if previous deflate call returned with
+ avail_out as zero but there is nothing to do
+- added memcmp for non STDC compilers
+- define NO_DUMMY_DECL for more Mac compilers (.h files merged incorrectly)
+- define __32BIT__ if __386__ or i386 is defined (pb. with Watcom and SCO)
+- better check for 16-bit mode MSC (avoids problem with Symantec)
+
+Changes in 1.0.2 (23 May 96)
+- added Windows DLL support
+- added a function zlibVersion (for the DLL support)
+- fixed declarations using Bytef in infutil.c (pb with MSDOS medium model)
+- Bytef is define's instead of typedef'd only for Borland C
+- avoid reading uninitialized memory in example.c
+- mention in README that the zlib format is now RFC1950
+- updated Makefile.dj2
+- added algorithm.doc
+
+Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
+- fix array overlay in deflate.c which sometimes caused bad compressed data
+- fix inflate bug with empty stored block
+- fix MSDOS medium model which was broken in 0.99
+- fix deflateParams() which could generated bad compressed data.
+- Bytef is define'd instead of typedef'ed (work around Borland bug)
+- added an INDEX file
+- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
+ Watcom (Makefile.wat), Amiga SAS/C (Makefile.sas)
+- speed up adler32 for modern machines without auto-increment
+- added -ansi for IRIX in configure
+- static_init_done in trees.c is an int
+- define unlink as delete for VMS
+- fix configure for QNX
+- add configure branch for SCO and HPUX
+- avoid many warnings (unused variables, dead assignments, etc...)
+- no fdopen for BeOS
+- fix the Watcom fix for 32 bit mode (define FAR as empty)
+- removed redefinition of Byte for MKWERKS
+- work around an MWKERKS bug (incorrect merge of all .h files)
+
+Changes in 0.99 (27 Jan 96)
+- allow preset dictionary shared between compressor and decompressor
+- allow compression level 0 (no compression)
+- add deflateParams in zlib.h: allow dynamic change of compression level
+ and compression strategy.
+- test large buffers and deflateParams in example.c
+- add optional "configure" to build zlib as a shared library
+- suppress Makefile.qnx, use configure instead
+- fixed deflate for 64-bit systems (detected on Cray)
+- fixed inflate_blocks for 64-bit systems (detected on Alpha)
+- declare Z_DEFLATED in zlib.h (possible parameter for deflateInit2)
+- always return Z_BUF_ERROR when deflate() has nothing to do
+- deflateInit and inflateInit are now macros to allow version checking
+- prefix all global functions and types with z_ with -DZ_PREFIX
+- make falloc completely reentrant (inftrees.c)
+- fixed very unlikely race condition in ct_static_init
+- free in reverse order of allocation to help memory manager
+- use zlib-1.0/* instead of zlib/* inside the tar.gz
+- make zlib warning-free with "gcc -O3 -Wall -Wwrite-strings -Wpointer-arith
+ -Wconversion -Wstrict-prototypes -Wmissing-prototypes"
+- allow gzread on concatenated .gz files
+- deflateEnd now returns Z_DATA_ERROR if it was premature
+- deflate is finally (?) fully deterministic (no matches beyond end of input)
+- Document Z_SYNC_FLUSH
+- add uninstall in Makefile
+- Check for __cpluplus in zlib.h
+- Better test in ct_align for partial flush
+- avoid harmless warnings for Borland C++
+- initialize hash_head in deflate.c
+- avoid warning on fdopen (gzio.c) for HP cc -Aa
+- include stdlib.h for STDC compilers
+- include errno.h for Cray
+- ignore error if ranlib doesn't exist
+- call ranlib twice for NeXTSTEP
+- use exec_prefix instead of prefix for libz.a
+- renamed ct_* as _tr_* to avoid conflict with applications
+- clear z->msg in inflateInit2 before any error return
+- initialize opaque in example.c, gzio.c, deflate.c and inflate.c
+- fixed typo in zconf.h (_GNUC__ => __GNUC__)
+- check for WIN32 in zconf.h and zutil.c (avoid farmalloc in 32-bit mode)
+- fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
+- in fcalloc, normalize pointer if size > 65520 bytes
+- don't use special fcalloc for 32 bit Borland C++
+- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc...
+- use Z_BINARY instead of BINARY
+- document that gzclose after gzdopen will close the file
+- allow "a" as mode in gzopen.
+- fix error checking in gzread
+- allow skipping .gz extra-field on pipes
+- added reference to Perl interface in README
+- put the crc table in FAR data (I dislike more and more the medium model :)
+- added get_crc_table
+- added a dimension to all arrays (Borland C can't count).
+- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
+- guard against multiple inclusion of *.h (for precompiled header on Mac)
+- Watcom C pretends to be Microsoft C small model even in 32 bit mode.
+- don't use unsized arrays to avoid silly warnings by Visual C++:
+ warning C4746: 'inflate_mask' : unsized array treated as '__far'
+ (what's wrong with far data in far model?).
+- define enum out of inflate_blocks_state to allow compilation with C++
+
+Changes in 0.95 (16 Aug 95)
+- fix MSDOS small and medium model (now easier to adapt to any compiler)
+- inlined send_bits
+- fix the final (:-) bug for deflate with flush (output was correct but
+ not completely flushed in rare occasions).
+- default window size is same for compression and decompression
+ (it's now sufficient to set MAX_WBITS in zconf.h).
+- voidp -> voidpf and voidnp -> voidp (for consistency with other
+ typedefs and because voidnp was not near in large model).
+
+Changes in 0.94 (13 Aug 95)
+- support MSDOS medium model
+- fix deflate with flush (could sometimes generate bad output)
+- fix deflateReset (zlib header was incorrectly suppressed)
+- added support for VMS
+- allow a compression level in gzopen()
+- gzflush now calls fflush
+- For deflate with flush, flush even if no more input is provided.
+- rename libgz.a as libz.a
+- avoid complex expression in infcodes.c triggering Turbo C bug
+- work around a problem with gcc on Alpha (in INSERT_STRING)
+- don't use inline functions (problem with some gcc versions)
+- allow renaming of Byte, uInt, etc... with #define.
+- avoid warning about (unused) pointer before start of array in deflate.c
+- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
+- avoid reserved word 'new' in trees.c
+
+Changes in 0.93 (25 June 95)
+- temporarily disable inline functions
+- make deflate deterministic
+- give enough lookahead for PARTIAL_FLUSH
+- Set binary mode for stdin/stdout in minigzip.c for OS/2
+- don't even use signed char in inflate (not portable enough)
+- fix inflate memory leak for segmented architectures
+
+Changes in 0.92 (3 May 95)
+- don't assume that char is signed (problem on SGI)
+- Clear bit buffer when starting a stored block
+- no memcpy on Pyramid
+- suppressed inftest.c
+- optimized fill_window, put longest_match inline for gcc
+- optimized inflate on stored blocks.
+- untabify all sources to simplify patches
+
+Changes in 0.91 (2 May 95)
+- Default MEM_LEVEL is 8 (not 9 for Unix) as documented in zlib.h
+- Document the memory requirements in zconf.h
+- added "make install"
+- fix sync search logic in inflateSync
+- deflate(Z_FULL_FLUSH) now works even if output buffer too short
+- after inflateSync, don't scare people with just "lo world"
+- added support for DJGPP
+
+Changes in 0.9 (1 May 95)
+- don't assume that zalloc clears the allocated memory (the TurboC bug
+ was Mark's bug after all :)
+- let again gzread copy uncompressed data unchanged (was working in 0.71)
+- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
+- added a test of inflateSync in example.c
+- moved MAX_WBITS to zconf.h because users might want to change that.
+- document explicitly that zalloc(64K) on MSDOS must return a normalized
+ pointer (zero offset)
+- added Makefiles for Microsoft C, Turbo C, Borland C++
+- faster crc32()
+
+Changes in 0.8 (29 April 95)
+- added fast inflate (inffast.c)
+- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
+ is incompatible with previous versions of zlib which returned Z_OK.
+- work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
+ (actually that was not a compiler bug, see 0.81 above)
+- gzread no longer reads one extra byte in certain cases
+- In gzio destroy(), don't reference a freed structure
+- avoid many warnings for MSDOS
+- avoid the ERROR symbol which is used by MS Windows
+
+Changes in 0.71 (14 April 95)
+- Fixed more MSDOS compilation problems :( There is still a bug with
+ TurboC large model.
+
+Changes in 0.7 (14 April 95)
+- Added full inflate support.
+- Simplified the crc32() interface. The pre- and post-conditioning
+ (one's complement) is now done inside crc32(). WARNING: this is
+ incompatible with previous versions; see zlib.h for the new usage.
+
+Changes in 0.61 (12 April 95)
+- workaround for a bug in TurboC. example and minigzip now work on MSDOS.
+
+Changes in 0.6 (11 April 95)
+- added minigzip.c
+- added gzdopen to reopen a file descriptor as gzFile
+- added transparent reading of non-gziped files in gzread.
+- fixed bug in gzread (don't read crc as data)
+- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose).
+- don't allocate big arrays in the stack (for MSDOS)
+- fix some MSDOS compilation problems
+
+Changes in 0.5:
+- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
+ not yet Z_FULL_FLUSH.
+- support decompression but only in a single step (forced Z_FINISH)
+- added opaque object for zalloc and zfree.
+- added deflateReset and inflateReset
+- added a variable zlib_version for consistency checking.
+- renamed the 'filter' parameter of deflateInit2 as 'strategy'.
+ Added Z_FILTERED and Z_HUFFMAN_ONLY constants.
+
+Changes in 0.4:
+- avoid "zip" everywhere, use zlib instead of ziplib.
+- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
+ if compression method == 8.
+- added adler32 and crc32
+- renamed deflateOptions as deflateInit2, call one or the other but not both
+- added the method parameter for deflateInit2.
+- added inflateInit2
+- simplied considerably deflateInit and inflateInit by not supporting
+ user-provided history buffer. This is supported only in deflateInit2
+ and inflateInit2.
+
+Changes in 0.3:
+- prefix all macro names with Z_
+- use Z_FINISH instead of deflateEnd to finish compression.
+- added Z_HUFFMAN_ONLY
+- added gzerror()
diff --git a/Source/ZLib/FAQ b/Source/ZLib/FAQ
new file mode 100644
index 0000000..15d0436
--- /dev/null
+++ b/Source/ZLib/FAQ
@@ -0,0 +1,339 @@
+
+ Frequently Asked Questions about zlib
+
+
+If your question is not there, please check the zlib home page
+http://www.zlib.org which may have more recent information.
+The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
+
+
+ 1. Is zlib Y2K-compliant?
+
+ Yes. zlib doesn't handle dates.
+
+ 2. Where can I get a Windows DLL version?
+
+ The zlib sources can be compiled without change to produce a DLL.
+ See the file win32/DLL_FAQ.txt in the zlib distribution.
+ Pointers to the precompiled DLL are found in the zlib web site at
+ http://www.zlib.org.
+
+ 3. Where can I get a Visual Basic interface to zlib?
+
+ See
+ * http://www.dogma.net/markn/articles/zlibtool/zlibtool.htm
+ * contrib/visual-basic.txt in the zlib distribution
+ * win32/DLL_FAQ.txt in the zlib distribution
+
+ 4. compress() returns Z_BUF_ERROR.
+
+ Make sure that before the call of compress, the length of the compressed
+ buffer is equal to the total size of the compressed buffer and not
+ zero. For Visual Basic, check that this parameter is passed by reference
+ ("as any"), not by value ("as long").
+
+ 5. deflate() or inflate() returns Z_BUF_ERROR.
+
+ Before making the call, make sure that avail_in and avail_out are not
+ zero. When setting the parameter flush equal to Z_FINISH, also make sure
+ that avail_out is big enough to allow processing all pending input.
+ Note that a Z_BUF_ERROR is not fatal--another call to deflate() or
+ inflate() can be made with more input or output space. A Z_BUF_ERROR
+ may in fact be unavoidable depending on how the functions are used, since
+ it is not possible to tell whether or not there is more output pending
+ when strm.avail_out returns with zero.
+
+ 6. Where's the zlib documentation (man pages, etc.)?
+
+ It's in zlib.h for the moment, and Francis S. Lin has converted it to a
+ web page zlib.html. Volunteers to transform this to Unix-style man pages,
+ please contact us (zlib@gzip.org). Examples of zlib usage are in the files
+ example.c and minigzip.c.
+
+ 7. Why don't you use GNU autoconf or libtool or ...?
+
+ Because we would like to keep zlib as a very small and simple
+ package. zlib is rather portable and doesn't need much configuration.
+
+ 8. I found a bug in zlib.
+
+ Most of the time, such problems are due to an incorrect usage of
+ zlib. Please try to reproduce the problem with a small program and send
+ the corresponding source to us at zlib@gzip.org . Do not send
+ multi-megabyte data files without prior agreement.
+
+ 9. Why do I get "undefined reference to gzputc"?
+
+ If "make test" produces something like
+
+ example.o(.text+0x154): undefined reference to `gzputc'
+
+ check that you don't have old files libz.* in /usr/lib, /usr/local/lib or
+ /usr/X11R6/lib. Remove any old versions, then do "make install".
+
+10. I need a Delphi interface to zlib.
+
+ See the contrib/delphi directory in the zlib distribution.
+
+11. Can zlib handle .zip archives?
+
+ Not by itself, no. See the directory contrib/minizip in the zlib
+ distribution.
+
+12. Can zlib handle .Z files?
+
+ No, sorry. You have to spawn an uncompress or gunzip subprocess, or adapt
+ the code of uncompress on your own.
+
+13. How can I make a Unix shared library?
+
+ make clean
+ ./configure -s
+ make
+
+14. How do I install a shared zlib library on Unix?
+
+ After the above, then:
+
+ make install
+
+ However, many flavors of Unix come with a shared zlib already installed.
+ Before going to the trouble of compiling a shared version of zlib and
+ trying to install it, you may want to check if it's already there! If you
+ can #include <zlib.h>, it's there. The -lz option will probably link to it.
+
+15. I have a question about OttoPDF.
+
+ We are not the authors of OttoPDF. The real author is on the OttoPDF web
+ site: Joel Hainley, jhainley@myndkryme.com.
+
+16. Can zlib decode Flate data in an Adobe PDF file?
+
+ Yes. See http://www.fastio.com/ (ClibPDF), or http://www.pdflib.com/ .
+ To modify PDF forms, see http://sourceforge.net/projects/acroformtool/ .
+
+17. Why am I getting this "register_frame_info not found" error on Solaris?
+
+ After installing zlib 1.1.4 on Solaris 2.6, running applications using zlib
+ generates an error such as:
+
+ ld.so.1: rpm: fatal: relocation error: file /usr/local/lib/libz.so:
+ symbol __register_frame_info: referenced symbol not found
+
+ The symbol __register_frame_info is not part of zlib, it is generated by
+ the C compiler (cc or gcc). You must recompile applications using zlib
+ which have this problem. This problem is specific to Solaris. See
+ http://www.sunfreeware.com for Solaris versions of zlib and applications
+ using zlib.
+
+18. Why does gzip give an error on a file I make with compress/deflate?
+
+ The compress and deflate functions produce data in the zlib format, which
+ is different and incompatible with the gzip format. The gz* functions in
+ zlib on the other hand use the gzip format. Both the zlib and gzip
+ formats use the same compressed data format internally, but have different
+ headers and trailers around the compressed data.
+
+19. Ok, so why are there two different formats?
+
+ The gzip format was designed to retain the directory information about
+ a single file, such as the name and last modification date. The zlib
+ format on the other hand was designed for in-memory and communication
+ channel applications, and has a much more compact header and trailer and
+ uses a faster integrity check than gzip.
+
+20. Well that's nice, but how do I make a gzip file in memory?
+
+ You can request that deflate write the gzip format instead of the zlib
+ format using deflateInit2(). You can also request that inflate decode
+ the gzip format using inflateInit2(). Read zlib.h for more details.
+
+21. Is zlib thread-safe?
+
+ Yes. However any library routines that zlib uses and any application-
+ provided memory allocation routines must also be thread-safe. zlib's gz*
+ functions use stdio library routines, and most of zlib's functions use the
+ library memory allocation routines by default. zlib's Init functions allow
+ for the application to provide custom memory allocation routines.
+
+ Of course, you should only operate on any given zlib or gzip stream from a
+ single thread at a time.
+
+22. Can I use zlib in my commercial application?
+
+ Yes. Please read the license in zlib.h.
+
+23. Is zlib under the GNU license?
+
+ No. Please read the license in zlib.h.
+
+24. The license says that altered source versions must be "plainly marked". So
+ what exactly do I need to do to meet that requirement?
+
+ You need to change the ZLIB_VERSION and ZLIB_VERNUM #defines in zlib.h. In
+ particular, the final version number needs to be changed to "f", and an
+ identification string should be appended to ZLIB_VERSION. Version numbers
+ x.x.x.f are reserved for modifications to zlib by others than the zlib
+ maintainers. For example, if the version of the base zlib you are altering
+ is "1.2.3.4", then in zlib.h you should change ZLIB_VERNUM to 0x123f, and
+ ZLIB_VERSION to something like "1.2.3.f-zachary-mods-v3". You can also
+ update the version strings in deflate.c and inftrees.c.
+
+ For altered source distributions, you should also note the origin and
+ nature of the changes in zlib.h, as well as in ChangeLog and README, along
+ with the dates of the alterations. The origin should include at least your
+ name (or your company's name), and an email address to contact for help or
+ issues with the library.
+
+ Note that distributing a compiled zlib library along with zlib.h and
+ zconf.h is also a source distribution, and so you should change
+ ZLIB_VERSION and ZLIB_VERNUM and note the origin and nature of the changes
+ in zlib.h as you would for a full source distribution.
+
+25. Will zlib work on a big-endian or little-endian architecture, and can I
+ exchange compressed data between them?
+
+ Yes and yes.
+
+26. Will zlib work on a 64-bit machine?
+
+ It should. It has been tested on 64-bit machines, and has no dependence
+ on any data types being limited to 32-bits in length. If you have any
+ difficulties, please provide a complete problem report to zlib@gzip.org
+
+27. Will zlib decompress data from the PKWare Data Compression Library?
+
+ No. The PKWare DCL uses a completely different compressed data format
+ than does PKZIP and zlib. However, you can look in zlib's contrib/blast
+ directory for a possible solution to your problem.
+
+28. Can I access data randomly in a compressed stream?
+
+ No, not without some preparation. If when compressing you periodically
+ use Z_FULL_FLUSH, carefully write all the pending data at those points,
+ and keep an index of those locations, then you can start decompression
+ at those points. You have to be careful to not use Z_FULL_FLUSH too
+ often, since it can significantly degrade compression.
+
+29. Does zlib work on MVS, OS/390, CICS, etc.?
+
+ We don't know for sure. We have heard occasional reports of success on
+ these systems. If you do use it on one of these, please provide us with
+ a report, instructions, and patches that we can reference when we get
+ these questions. Thanks.
+
+30. Is there some simpler, easier to read version of inflate I can look at
+ to understand the deflate format?
+
+ First off, you should read RFC 1951. Second, yes. Look in zlib's
+ contrib/puff directory.
+
+31. Does zlib infringe on any patents?
+
+ As far as we know, no. In fact, that was originally the whole point behind
+ zlib. Look here for some more information:
+
+ http://www.gzip.org/#faq11
+
+32. Can zlib work with greater than 4 GB of data?
+
+ Yes. inflate() and deflate() will process any amount of data correctly.
+ Each call of inflate() or deflate() is limited to input and output chunks
+ of the maximum value that can be stored in the compiler's "unsigned int"
+ type, but there is no limit to the number of chunks. Note however that the
+ strm.total_in and strm_total_out counters may be limited to 4 GB. These
+ counters are provided as a convenience and are not used internally by
+ inflate() or deflate(). The application can easily set up its own counters
+ updated after each call of inflate() or deflate() to count beyond 4 GB.
+ compress() and uncompress() may be limited to 4 GB, since they operate in a
+ single call. gzseek() and gztell() may be limited to 4 GB depending on how
+ zlib is compiled. See the zlibCompileFlags() function in zlib.h.
+
+ The word "may" appears several times above since there is a 4 GB limit
+ only if the compiler's "long" type is 32 bits. If the compiler's "long"
+ type is 64 bits, then the limit is 16 exabytes.
+
+33. Does zlib have any security vulnerabilities?
+
+ The only one that we are aware of is potentially in gzprintf(). If zlib
+ is compiled to use sprintf() or vsprintf(), then there is no protection
+ against a buffer overflow of a 4K string space, other than the caller of
+ gzprintf() assuring that the output will not exceed 4K. On the other
+ hand, if zlib is compiled to use snprintf() or vsnprintf(), which should
+ normally be the case, then there is no vulnerability. The ./configure
+ script will display warnings if an insecure variation of sprintf() will
+ be used by gzprintf(). Also the zlibCompileFlags() function will return
+ information on what variant of sprintf() is used by gzprintf().
+
+ If you don't have snprintf() or vsnprintf() and would like one, you can
+ find a portable implementation here:
+
+ http://www.ijs.si/software/snprintf/
+
+ Note that you should be using the most recent version of zlib. Versions
+ 1.1.3 and before were subject to a double-free vulnerability.
+
+34. Is there a Java version of zlib?
+
+ Probably what you want is to use zlib in Java. zlib is already included
+ as part of the Java SDK in the java.util.zip package. If you really want
+ a version of zlib written in the Java language, look on the zlib home
+ page for links: http://www.zlib.org/
+
+35. I get this or that compiler or source-code scanner warning when I crank it
+ up to maximally-pedantic. Can't you guys write proper code?
+
+ Many years ago, we gave up attempting to avoid warnings on every compiler
+ in the universe. It just got to be a waste of time, and some compilers
+ were downright silly. So now, we simply make sure that the code always
+ works.
+
+36. Valgrind (or some similar memory access checker) says that deflate is
+ performing a conditional jump that depends on an uninitialized value.
+ Isn't that a bug?
+
+ No. That is intentional for performance reasons, and the output of
+ deflate is not affected. This only started showing up recently since
+ zlib 1.2.x uses malloc() by default for allocations, whereas earlier
+ versions used calloc(), which zeros out the allocated memory.
+
+37. Will zlib read the (insert any ancient or arcane format here) compressed
+ data format?
+
+ Probably not. Look in the comp.compression FAQ for pointers to various
+ formats and associated software.
+
+38. How can I encrypt/decrypt zip files with zlib?
+
+ zlib doesn't support encryption. The original PKZIP encryption is very weak
+ and can be broken with freely available programs. To get strong encryption,
+ use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
+ For PKZIP compatible "encryption", look at http://www.info-zip.org/
+
+39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
+
+ "gzip" is the gzip format, and "deflate" is the zlib format. They should
+ probably have called the second one "zlib" instead to avoid confusion
+ with the raw deflate compressed data format. While the HTTP 1.1 RFC 2616
+ correctly points to the zlib specification in RFC 1950 for the "deflate"
+ transfer encoding, there have been reports of servers and browsers that
+ incorrectly produce or expect raw deflate data per the deflate
+ specficiation in RFC 1951, most notably Microsoft. So even though the
+ "deflate" transfer encoding using the zlib format would be the more
+ efficient approach (and in fact exactly what the zlib format was designed
+ for), using the "gzip" transfer encoding is probably more reliable due to
+ an unfortunate choice of name on the part of the HTTP 1.1 authors.
+
+ Bottom line: use the gzip format for HTTP 1.1 encoding.
+
+40. Does zlib support the new "Deflate64" format introduced by PKWare?
+
+ No. PKWare has apparently decided to keep that format proprietary, since
+ they have not documented it as they have previous compression formats.
+ In any case, the compression improvements are so modest compared to other
+ more modern approaches, that it's not worth the effort to implement.
+
+41. Can you please sign these lengthy legal documents and fax them back to us
+ so that we can use your software in our product?
+
+ No. Go away. Shoo.
diff --git a/Source/ZLib/INDEX b/Source/ZLib/INDEX
new file mode 100644
index 0000000..4d7eac4
--- /dev/null
+++ b/Source/ZLib/INDEX
@@ -0,0 +1,51 @@
+ChangeLog history of changes
+FAQ Frequently Asked Questions about zlib
+INDEX this file
+Makefile makefile for Unix (generated by configure)
+Makefile.in makefile for Unix (template for configure)
+README guess what
+algorithm.txt description of the (de)compression algorithm
+configure configure script for Unix
+zconf.in.h template for zconf.h (used by configure)
+
+amiga/ makefiles for Amiga SAS C
+as400/ makefiles for IBM AS/400
+msdos/ makefiles for MSDOS
+old/ makefiles for various architectures and zlib documentation
+ files that have not yet been updated for zlib 1.2.x
+projects/ projects for various Integrated Development Environments
+qnx/ makefiles for QNX
+win32/ makefiles for Windows
+
+ zlib public header files (must be kept):
+zconf.h
+zlib.h
+
+ private source files used to build the zlib library:
+adler32.c
+compress.c
+crc32.c
+crc32.h
+deflate.c
+deflate.h
+gzio.c
+infback.c
+inffast.c
+inffast.h
+inffixed.h
+inflate.c
+inflate.h
+inftrees.c
+inftrees.h
+trees.c
+trees.h
+uncompr.c
+zutil.c
+zutil.h
+
+ source files for sample programs:
+example.c
+minigzip.c
+
+ unsupported contribution by third parties
+See contrib/README.contrib
diff --git a/Source/ZLib/Makefile b/Source/ZLib/Makefile
new file mode 100644
index 0000000..2fd6e45
--- /dev/null
+++ b/Source/ZLib/Makefile
@@ -0,0 +1,154 @@
+# Makefile for zlib
+# Copyright (C) 1995-2005 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# ./configure; make test
+# The call of configure is optional if you don't have special requirements
+# If you wish to build zlib as a shared library, use: ./configure -s
+
+# To use the asm code, type:
+# cp contrib/asm?86/match.S ./match.S
+# make LOC=-DASMV OBJA=match.o
+
+# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
+# make install
+# To install in $HOME instead of /usr/local, use:
+# make install prefix=$HOME
+
+CC=cc
+
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+LDFLAGS=libz.a
+LDSHARED=$(CC)
+CPP=$(CC) -E
+
+LIBS=libz.a
+SHAREDLIB=libz.so
+SHAREDLIBV=libz.so.1.2.3
+SHAREDLIBM=libz.so.1
+
+AR=ar rc
+RANLIB=ranlib
+TAR=tar
+SHELL=/bin/sh
+EXE=
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/share/man
+man3dir = ${mandir}/man3
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+ zutil.o inflate.o infback.o inftrees.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example$(EXE) minigzip$(EXE)
+
+check: test
+test: all
+ @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ echo hello world | ./minigzip | ./minigzip -d || \
+ echo ' *** minigzip test FAILED ***' ; \
+ if ./example; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+libz.a: $(OBJS) $(OBJA)
+ $(AR) $@ $(OBJS) $(OBJA)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+$(SHAREDLIBV): $(OBJS)
+ $(LDSHARED) -o $@ $(OBJS)
+ rm -f $(SHAREDLIB) $(SHAREDLIBM)
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIBM)
+
+example$(EXE): example.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip$(EXE): minigzip.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+install: $(LIBS)
+ -@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
+ -@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
+ -@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
+ -@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
+ cp zlib.h zconf.h $(includedir)
+ chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
+ cp $(LIBS) $(libdir)
+ cd $(libdir); chmod 755 $(LIBS)
+ -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
+ cd $(libdir); if test -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIB) $(SHAREDLIBM); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIB); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
+ (ldconfig || true) >/dev/null 2>&1; \
+ fi
+ cp zlib.3 $(man3dir)
+ chmod 644 $(man3dir)/zlib.3
+# The ranlib in install is needed on NeXTSTEP which checks file times
+# ldconfig is for Linux
+
+uninstall:
+ cd $(includedir); \
+ cd $(libdir); rm -f libz.a; \
+ if test -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
+ fi
+ cd $(man3dir); rm -f zlib.3
+
+mostlyclean: clean
+clean:
+ rm -f *.o *~ example$(EXE) minigzip$(EXE) \
+ libz.* foo.gz so_locations \
+ _match.s maketree contrib/infback9/*.o
+
+maintainer-clean: distclean
+distclean: clean
+ cp -p Makefile.in Makefile
+ cp -p zconf.in.h zconf.h
+ rm -f .DS_Store
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/Source/ZLib/Makefile.in b/Source/ZLib/Makefile.in
new file mode 100644
index 0000000..2fd6e45
--- /dev/null
+++ b/Source/ZLib/Makefile.in
@@ -0,0 +1,154 @@
+# Makefile for zlib
+# Copyright (C) 1995-2005 Jean-loup Gailly.
+# For conditions of distribution and use, see copyright notice in zlib.h
+
+# To compile and test, type:
+# ./configure; make test
+# The call of configure is optional if you don't have special requirements
+# If you wish to build zlib as a shared library, use: ./configure -s
+
+# To use the asm code, type:
+# cp contrib/asm?86/match.S ./match.S
+# make LOC=-DASMV OBJA=match.o
+
+# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
+# make install
+# To install in $HOME instead of /usr/local, use:
+# make install prefix=$HOME
+
+CC=cc
+
+CFLAGS=-O
+#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
+#CFLAGS=-g -DDEBUG
+#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
+# -Wstrict-prototypes -Wmissing-prototypes
+
+LDFLAGS=libz.a
+LDSHARED=$(CC)
+CPP=$(CC) -E
+
+LIBS=libz.a
+SHAREDLIB=libz.so
+SHAREDLIBV=libz.so.1.2.3
+SHAREDLIBM=libz.so.1
+
+AR=ar rc
+RANLIB=ranlib
+TAR=tar
+SHELL=/bin/sh
+EXE=
+
+prefix = /usr/local
+exec_prefix = ${prefix}
+libdir = ${exec_prefix}/lib
+includedir = ${prefix}/include
+mandir = ${prefix}/share/man
+man3dir = ${mandir}/man3
+
+OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
+ zutil.o inflate.o infback.o inftrees.o inffast.o
+
+OBJA =
+# to use the asm code: make OBJA=match.o
+
+TEST_OBJS = example.o minigzip.o
+
+all: example$(EXE) minigzip$(EXE)
+
+check: test
+test: all
+ @LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
+ echo hello world | ./minigzip | ./minigzip -d || \
+ echo ' *** minigzip test FAILED ***' ; \
+ if ./example; then \
+ echo ' *** zlib test OK ***'; \
+ else \
+ echo ' *** zlib test FAILED ***'; \
+ fi
+
+libz.a: $(OBJS) $(OBJA)
+ $(AR) $@ $(OBJS) $(OBJA)
+ -@ ($(RANLIB) $@ || true) >/dev/null 2>&1
+
+match.o: match.S
+ $(CPP) match.S > _match.s
+ $(CC) -c _match.s
+ mv _match.o match.o
+ rm -f _match.s
+
+$(SHAREDLIBV): $(OBJS)
+ $(LDSHARED) -o $@ $(OBJS)
+ rm -f $(SHAREDLIB) $(SHAREDLIBM)
+ ln -s $@ $(SHAREDLIB)
+ ln -s $@ $(SHAREDLIBM)
+
+example$(EXE): example.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
+
+minigzip$(EXE): minigzip.o $(LIBS)
+ $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
+
+install: $(LIBS)
+ -@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
+ -@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
+ -@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
+ -@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
+ cp zlib.h zconf.h $(includedir)
+ chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
+ cp $(LIBS) $(libdir)
+ cd $(libdir); chmod 755 $(LIBS)
+ -@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
+ cd $(libdir); if test -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIB) $(SHAREDLIBM); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIB); \
+ ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
+ (ldconfig || true) >/dev/null 2>&1; \
+ fi
+ cp zlib.3 $(man3dir)
+ chmod 644 $(man3dir)/zlib.3
+# The ranlib in install is needed on NeXTSTEP which checks file times
+# ldconfig is for Linux
+
+uninstall:
+ cd $(includedir); \
+ cd $(libdir); rm -f libz.a; \
+ if test -f $(SHAREDLIBV); then \
+ rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
+ fi
+ cd $(man3dir); rm -f zlib.3
+
+mostlyclean: clean
+clean:
+ rm -f *.o *~ example$(EXE) minigzip$(EXE) \
+ libz.* foo.gz so_locations \
+ _match.s maketree contrib/infback9/*.o
+
+maintainer-clean: distclean
+distclean: clean
+ cp -p Makefile.in Makefile
+ cp -p zconf.in.h zconf.h
+ rm -f .DS_Store
+
+tags:
+ etags *.[ch]
+
+depend:
+ makedepend -- $(CFLAGS) -- *.[ch]
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+adler32.o: zlib.h zconf.h
+compress.o: zlib.h zconf.h
+crc32.o: crc32.h zlib.h zconf.h
+deflate.o: deflate.h zutil.h zlib.h zconf.h
+example.o: zlib.h zconf.h
+gzio.o: zutil.h zlib.h zconf.h
+inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
+inftrees.o: zutil.h zlib.h zconf.h inftrees.h
+minigzip.o: zlib.h zconf.h
+trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
+uncompr.o: zlib.h zconf.h
+zutil.o: zutil.h zlib.h zconf.h
diff --git a/Source/ZLib/README b/Source/ZLib/README
new file mode 100644
index 0000000..758cc50
--- /dev/null
+++ b/Source/ZLib/README
@@ -0,0 +1,125 @@
+ZLIB DATA COMPRESSION LIBRARY
+
+zlib 1.2.3 is a general purpose data compression library. All the code is
+thread safe. The data format used by the zlib library is described by RFCs
+(Request for Comments) 1950 to 1952 in the files
+http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
+and rfc1952.txt (gzip format). These documents are also available in other
+formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+
+All functions of the compression library are documented in the file zlib.h
+(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
+of the library is given in the file example.c which also tests that the library
+is working correctly. Another example is given in the file minigzip.c. The
+compression library itself is composed of all source files except example.c and
+minigzip.c.
+
+To compile all files and run the test program, follow the instructions given at
+the top of Makefile. In short "make test; make install" should work for most
+machines. For Unix: "./configure; make test; make install". For MSDOS, use one
+of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
+
+Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
+<info@winimage.com> for the Windows DLL version. The zlib home page is
+http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem,
+please check this site to verify that you have the latest version of zlib;
+otherwise get the latest version and check whether the problem still exists or
+not.
+
+PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking
+for help.
+
+Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
+issue of Dr. Dobb's Journal; a copy of the article is available in
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+
+The changes made in version 1.2.3 are documented in the file ChangeLog.
+
+Unsupported third party contributions are provided in directory "contrib".
+
+A Java implementation of zlib is available in the Java Development Kit
+http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html
+See the zlib home page http://www.zlib.org for details.
+
+A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the
+CPAN (Comprehensive Perl Archive Network) sites
+http://www.cpan.org/modules/by-module/Compress/
+
+A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
+available in Python 1.5 and later versions, see
+http://www.python.org/doc/lib/module-zlib.html
+
+A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is
+availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
+
+An experimental package to read and write files in .zip format, written on top
+of zlib by Gilles Vollant <info@winimage.com>, is available in the
+contrib/minizip directory of zlib.
+
+
+Notes for some targets:
+
+- For Windows DLL versions, please see win32/DLL_FAQ.txt
+
+- For 64-bit Irix, deflate.c must be compiled without any optimization. With
+ -O, one libpng test fails. The test works in 32 bit mode (with the -n32
+ compiler flag). The compiler bug has been reported to SGI.
+
+- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
+ when compiled with cc.
+
+- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is
+ necessary to get gzprintf working correctly. This is done by configure.
+
+- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
+ other compilers. Use "make test" to check your compiler.
+
+- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers.
+
+- For PalmOs, see http://palmzlib.sourceforge.net/
+
+- When building a shared, i.e. dynamic library on Mac OS X, the library must be
+ installed before testing (do "make install" before "make test"), since the
+ library location is specified in the library.
+
+
+Acknowledgments:
+
+ The deflate format used by zlib was defined by Phil Katz. The deflate
+ and zlib specifications were written by L. Peter Deutsch. Thanks to all the
+ people who reported problems and suggested various improvements in zlib;
+ they are too numerous to cite here.
+
+Copyright notice:
+
+ (C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+If you use the zlib library in a product, we would appreciate *not*
+receiving lengthy legal documents to sign. The sources are provided
+for free but without warranty of any kind. The library has been
+entirely written by Jean-loup Gailly and Mark Adler; it does not
+include third-party code.
+
+If you redistribute modified sources, we would appreciate that you include
+in the file ChangeLog history information documenting your changes. Please
+read the FAQ for more information on the distribution of modified source
+versions.
diff --git a/Source/ZLib/ZLib.2003.vcproj b/Source/ZLib/ZLib.2003.vcproj
new file mode 100644
index 0000000..3a85454
--- /dev/null
+++ b/Source/ZLib/ZLib.2003.vcproj
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+
+<VisualStudioProject
+
+ ProjectType="Visual C++"
+
+ Version="7.10"
+
+ Name="ZLib"
+
+ SccProjectName="&quot;$/FreeImage/ZLib&quot;, KNAAAAAA"
+
+ SccLocalPath=".">
+
+ <Platforms>
+
+ <Platform
+
+ Name="Win32"/>
+
+ </Platforms>
+
+ <Configurations>
+
+ <Configuration
+
+ Name="Debug|Win32"
+
+ OutputDirectory=".\Debug"
+
+ IntermediateDirectory=".\Debug"
+
+ ConfigurationType="4"
+
+ UseOfMFC="0"
+
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+
+ CharacterSet="2">
+
+ <Tool
+
+ Name="VCCLCompilerTool"
+
+ Optimization="0"
+
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+
+ StringPooling="TRUE"
+
+ BasicRuntimeChecks="3"
+
+ RuntimeLibrary="1"
+
+ UsePrecompiledHeader="2"
+
+ PrecompiledHeaderFile=".\Debug/ZLib.pch"
+
+ AssemblerListingLocation=".\Debug/"
+
+ ObjectFile=".\Debug/"
+
+ ProgramDataBaseFileName=".\Debug/"
+
+ WarningLevel="3"
+
+ SuppressStartupBanner="TRUE"
+
+ DebugInformationFormat="4"/>
+
+ <Tool
+
+ Name="VCCustomBuildTool"/>
+
+ <Tool
+
+ Name="VCLibrarianTool"
+
+ OutputFile=".\Debug\ZLib.lib"
+
+ SuppressStartupBanner="TRUE"/>
+
+ <Tool
+
+ Name="VCMIDLTool"/>
+
+ <Tool
+
+ Name="VCPostBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreLinkEventTool"/>
+
+ <Tool
+
+ Name="VCResourceCompilerTool"
+
+ PreprocessorDefinitions="_DEBUG"
+
+ Culture="1033"/>
+
+ <Tool
+
+ Name="VCWebServiceProxyGeneratorTool"/>
+
+ <Tool
+
+ Name="VCXMLDataGeneratorTool"/>
+
+ <Tool
+
+ Name="VCManagedWrapperGeneratorTool"/>
+
+ <Tool
+
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+
+ </Configuration>
+
+ <Configuration
+
+ Name="Release|Win32"
+
+ OutputDirectory=".\Release"
+
+ IntermediateDirectory=".\Release"
+
+ ConfigurationType="4"
+
+ UseOfMFC="0"
+
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+
+ CharacterSet="2">
+
+ <Tool
+
+ Name="VCCLCompilerTool"
+
+ Optimization="2"
+
+ GlobalOptimizations="TRUE"
+
+ InlineFunctionExpansion="2"
+
+ EnableIntrinsicFunctions="TRUE"
+
+ FavorSizeOrSpeed="1"
+
+ OmitFramePointers="TRUE"
+
+ OptimizeForProcessor="3"
+
+ AdditionalIncludeDirectories="..\zlib"
+
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+
+ StringPooling="TRUE"
+
+ RuntimeLibrary="0"
+
+ BufferSecurityCheck="FALSE"
+
+ UsePrecompiledHeader="2"
+
+ PrecompiledHeaderFile=".\Release/ZLib.pch"
+
+ AssemblerListingLocation=".\Release/"
+
+ ObjectFile=".\Release/"
+
+ ProgramDataBaseFileName=".\Release/"
+
+ WarningLevel="3"
+
+ SuppressStartupBanner="TRUE"
+
+ CompileAs="0"/>
+
+ <Tool
+
+ Name="VCCustomBuildTool"/>
+
+ <Tool
+
+ Name="VCLibrarianTool"
+
+ OutputFile=".\Release\ZLib.lib"
+
+ SuppressStartupBanner="TRUE"/>
+
+ <Tool
+
+ Name="VCMIDLTool"/>
+
+ <Tool
+
+ Name="VCPostBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreBuildEventTool"/>
+
+ <Tool
+
+ Name="VCPreLinkEventTool"/>
+
+ <Tool
+
+ Name="VCResourceCompilerTool"
+
+ PreprocessorDefinitions="NDEBUG"
+
+ Culture="1033"/>
+
+ <Tool
+
+ Name="VCWebServiceProxyGeneratorTool"/>
+
+ <Tool
+
+ Name="VCXMLDataGeneratorTool"/>
+
+ <Tool
+
+ Name="VCManagedWrapperGeneratorTool"/>
+
+ <Tool
+
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+
+ </Configuration>
+
+ </Configurations>
+
+ <References>
+
+ </References>
+
+ <Files>
+
+ <Filter
+
+ Name="Source Files"
+
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+
+ <File
+
+ RelativePath="adler32.c">
+
+ </File>
+
+ <File
+
+ RelativePath="compress.c">
+
+ </File>
+
+ <File
+
+ RelativePath="crc32.c">
+
+ </File>
+
+ <File
+
+ RelativePath="deflate.c">
+
+ </File>
+
+ <File
+
+ RelativePath="gzio.c">
+
+ </File>
+
+ <File
+
+ RelativePath="infback.c">
+
+ </File>
+
+ <File
+
+ RelativePath="inffast.c">
+
+ </File>
+
+ <File
+
+ RelativePath="inflate.c">
+
+ </File>
+
+ <File
+
+ RelativePath="inftrees.c">
+
+ </File>
+
+ <File
+
+ RelativePath="trees.c">
+
+ </File>
+
+ <File
+
+ RelativePath="uncompr.c">
+
+ </File>
+
+ <File
+
+ RelativePath="zutil.c">
+
+ </File>
+
+ </Filter>
+
+ <Filter
+
+ Name="Header Files"
+
+ Filter="h;hpp;hxx;hm;inl">
+
+ <File
+
+ RelativePath="crc32.h">
+
+ </File>
+
+ <File
+
+ RelativePath="deflate.h">
+
+ </File>
+
+ <File
+
+ RelativePath="inffast.h">
+
+ </File>
+
+ <File
+
+ RelativePath="inffixed.h">
+
+ </File>
+
+ <File
+
+ RelativePath="inflate.h">
+
+ </File>
+
+ <File
+
+ RelativePath="inftrees.h">
+
+ </File>
+
+ <File
+
+ RelativePath="trees.h">
+
+ </File>
+
+ <File
+
+ RelativePath="zconf.h">
+
+ </File>
+
+ <File
+
+ RelativePath="zconf.in.h">
+
+ </File>
+
+ <File
+
+ RelativePath="zlib.h">
+
+ </File>
+
+ <File
+
+ RelativePath="zutil.h">
+
+ </File>
+
+ </Filter>
+
+ </Files>
+
+ <Globals>
+
+ </Globals>
+
+</VisualStudioProject>
+
diff --git a/Source/ZLib/ZLib.2005.vcproj b/Source/ZLib/ZLib.2005.vcproj
new file mode 100644
index 0000000..9882309
--- /dev/null
+++ b/Source/ZLib/ZLib.2005.vcproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="ZLib"
+ ProjectGUID="{33134F61-C1AD-4B6F-9CEA-503A9F140C52}"
+ RootNamespace="ZLib"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/ZLib.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Debug\ZLib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="..\zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/ZLib.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile=".\Release\ZLib.lib"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="adler32.c"
+ >
+ </File>
+ <File
+ RelativePath="compress.c"
+ >
+ </File>
+ <File
+ RelativePath="crc32.c"
+ >
+ </File>
+ <File
+ RelativePath="deflate.c"
+ >
+ </File>
+ <File
+ RelativePath="gzio.c"
+ >
+ </File>
+ <File
+ RelativePath="infback.c"
+ >
+ </File>
+ <File
+ RelativePath="inffast.c"
+ >
+ </File>
+ <File
+ RelativePath="inflate.c"
+ >
+ </File>
+ <File
+ RelativePath="inftrees.c"
+ >
+ </File>
+ <File
+ RelativePath="trees.c"
+ >
+ </File>
+ <File
+ RelativePath="uncompr.c"
+ >
+ </File>
+ <File
+ RelativePath="zutil.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="crc32.h"
+ >
+ </File>
+ <File
+ RelativePath="deflate.h"
+ >
+ </File>
+ <File
+ RelativePath="inffast.h"
+ >
+ </File>
+ <File
+ RelativePath="inffixed.h"
+ >
+ </File>
+ <File
+ RelativePath="inflate.h"
+ >
+ </File>
+ <File
+ RelativePath="inftrees.h"
+ >
+ </File>
+ <File
+ RelativePath="trees.h"
+ >
+ </File>
+ <File
+ RelativePath="zconf.h"
+ >
+ </File>
+ <File
+ RelativePath="zconf.in.h"
+ >
+ </File>
+ <File
+ RelativePath="zlib.h"
+ >
+ </File>
+ <File
+ RelativePath="zutil.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Source/ZLib/adler32.c b/Source/ZLib/adler32.c
new file mode 100644
index 0000000..cf312b8
--- /dev/null
+++ b/Source/ZLib/adler32.c
@@ -0,0 +1,149 @@
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: adler32.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#define BASE 65521UL /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* use NO_DIVIDE if your processor does not do division in hardware */
+#ifdef NO_DIVIDE
+# define MOD(a) \
+ do { \
+ if (a >= (BASE << 16)) a -= (BASE << 16); \
+ if (a >= (BASE << 15)) a -= (BASE << 15); \
+ if (a >= (BASE << 14)) a -= (BASE << 14); \
+ if (a >= (BASE << 13)) a -= (BASE << 13); \
+ if (a >= (BASE << 12)) a -= (BASE << 12); \
+ if (a >= (BASE << 11)) a -= (BASE << 11); \
+ if (a >= (BASE << 10)) a -= (BASE << 10); \
+ if (a >= (BASE << 9)) a -= (BASE << 9); \
+ if (a >= (BASE << 8)) a -= (BASE << 8); \
+ if (a >= (BASE << 7)) a -= (BASE << 7); \
+ if (a >= (BASE << 6)) a -= (BASE << 6); \
+ if (a >= (BASE << 5)) a -= (BASE << 5); \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD4(a) \
+ do { \
+ if (a >= (BASE << 4)) a -= (BASE << 4); \
+ if (a >= (BASE << 3)) a -= (BASE << 3); \
+ if (a >= (BASE << 2)) a -= (BASE << 2); \
+ if (a >= (BASE << 1)) a -= (BASE << 1); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD4(a) a %= BASE
+#endif
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(adler, buf, len)
+ uLong adler;
+ const Bytef *buf;
+ uInt len;
+{
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD4(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ DO16(buf);
+ buf += 16;
+ }
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(adler1, adler2, len2)
+ uLong adler1;
+ uLong adler2;
+ z_off_t len2;
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ rem = (unsigned)(len2 % BASE);
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum1 > BASE) sum1 -= BASE;
+ if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 > BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
diff --git a/Source/ZLib/algorithm.txt b/Source/ZLib/algorithm.txt
new file mode 100644
index 0000000..b022dde
--- /dev/null
+++ b/Source/ZLib/algorithm.txt
@@ -0,0 +1,209 @@
+1. Compression algorithm (deflate)
+
+The deflation algorithm used by gzip (also zip and zlib) is a variation of
+LZ77 (Lempel-Ziv 1977, see reference below). It finds duplicated strings in
+the input data. The second occurrence of a string is replaced by a
+pointer to the previous string, in the form of a pair (distance,
+length). Distances are limited to 32K bytes, and lengths are limited
+to 258 bytes. When a string does not occur anywhere in the previous
+32K bytes, it is emitted as a sequence of literal bytes. (In this
+description, `string' must be taken as an arbitrary sequence of bytes,
+and is not restricted to printable characters.)
+
+Literals or match lengths are compressed with one Huffman tree, and
+match distances are compressed with another tree. The trees are stored
+in a compact form at the start of each block. The blocks can have any
+size (except that the compressed data for one block must fit in
+available memory). A block is terminated when deflate() determines that
+it would be useful to start another block with fresh trees. (This is
+somewhat similar to the behavior of LZW-based _compress_.)
+
+Duplicated strings are found using a hash table. All input strings of
+length 3 are inserted in the hash table. A hash index is computed for
+the next 3 bytes. If the hash chain for this index is not empty, all
+strings in the chain are compared with the current input string, and
+the longest match is selected.
+
+The hash chains are searched starting with the most recent strings, to
+favor small distances and thus take advantage of the Huffman encoding.
+The hash chains are singly linked. There are no deletions from the
+hash chains, the algorithm simply discards matches that are too old.
+
+To avoid a worst-case situation, very long hash chains are arbitrarily
+truncated at a certain length, determined by a runtime option (level
+parameter of deflateInit). So deflate() does not always find the longest
+possible match but generally finds a match which is long enough.
+
+deflate() also defers the selection of matches with a lazy evaluation
+mechanism. After a match of length N has been found, deflate() searches for
+a longer match at the next input byte. If a longer match is found, the
+previous match is truncated to a length of one (thus producing a single
+literal byte) and the process of lazy evaluation begins again. Otherwise,
+the original match is kept, and the next match search is attempted only N
+steps later.
+
+The lazy match evaluation is also subject to a runtime parameter. If
+the current match is long enough, deflate() reduces the search for a longer
+match, thus speeding up the whole process. If compression ratio is more
+important than speed, deflate() attempts a complete second search even if
+the first match is already long enough.
+
+The lazy match evaluation is not performed for the fastest compression
+modes (level parameter 1 to 3). For these fast modes, new strings
+are inserted in the hash table only when no match was found, or
+when the match is not too long. This degrades the compression ratio
+but saves time since there are both fewer insertions and fewer searches.
+
+
+2. Decompression algorithm (inflate)
+
+2.1 Introduction
+
+The key question is how to represent a Huffman code (or any prefix code) so
+that you can decode fast. The most important characteristic is that shorter
+codes are much more common than longer codes, so pay attention to decoding the
+short codes fast, and let the long codes take longer to decode.
+
+inflate() sets up a first level table that covers some number of bits of
+input less than the length of longest code. It gets that many bits from the
+stream, and looks it up in the table. The table will tell if the next
+code is that many bits or less and how many, and if it is, it will tell
+the value, else it will point to the next level table for which inflate()
+grabs more bits and tries to decode a longer code.
+
+How many bits to make the first lookup is a tradeoff between the time it
+takes to decode and the time it takes to build the table. If building the
+table took no time (and if you had infinite memory), then there would only
+be a first level table to cover all the way to the longest code. However,
+building the table ends up taking a lot longer for more bits since short
+codes are replicated many times in such a table. What inflate() does is
+simply to make the number of bits in the first table a variable, and then
+to set that variable for the maximum speed.
+
+For inflate, which has 286 possible codes for the literal/length tree, the size
+of the first table is nine bits. Also the distance trees have 30 possible
+values, and the size of the first table is six bits. Note that for each of
+those cases, the table ended up one bit longer than the ``average'' code
+length, i.e. the code length of an approximately flat code which would be a
+little more than eight bits for 286 symbols and a little less than five bits
+for 30 symbols.
+
+
+2.2 More details on the inflate table lookup
+
+Ok, you want to know what this cleverly obfuscated inflate tree actually
+looks like. You are correct that it's not a Huffman tree. It is simply a
+lookup table for the first, let's say, nine bits of a Huffman symbol. The
+symbol could be as short as one bit or as long as 15 bits. If a particular
+symbol is shorter than nine bits, then that symbol's translation is duplicated
+in all those entries that start with that symbol's bits. For example, if the
+symbol is four bits, then it's duplicated 32 times in a nine-bit table. If a
+symbol is nine bits long, it appears in the table once.
+
+If the symbol is longer than nine bits, then that entry in the table points
+to another similar table for the remaining bits. Again, there are duplicated
+entries as needed. The idea is that most of the time the symbol will be short
+and there will only be one table look up. (That's whole idea behind data
+compression in the first place.) For the less frequent long symbols, there
+will be two lookups. If you had a compression method with really long
+symbols, you could have as many levels of lookups as is efficient. For
+inflate, two is enough.
+
+So a table entry either points to another table (in which case nine bits in
+the above example are gobbled), or it contains the translation for the symbol
+and the number of bits to gobble. Then you start again with the next
+ungobbled bit.
+
+You may wonder: why not just have one lookup table for how ever many bits the
+longest symbol is? The reason is that if you do that, you end up spending
+more time filling in duplicate symbol entries than you do actually decoding.
+At least for deflate's output that generates new trees every several 10's of
+kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code
+would take too long if you're only decoding several thousand symbols. At the
+other extreme, you could make a new table for every bit in the code. In fact,
+that's essentially a Huffman tree. But then you spend two much time
+traversing the tree while decoding, even for short symbols.
+
+So the number of bits for the first lookup table is a trade of the time to
+fill out the table vs. the time spent looking at the second level and above of
+the table.
+
+Here is an example, scaled down:
+
+The code being decoded, with 10 symbols, from 1 to 6 bits long:
+
+A: 0
+B: 10
+C: 1100
+D: 11010
+E: 11011
+F: 11100
+G: 11101
+H: 11110
+I: 111110
+J: 111111
+
+Let's make the first table three bits long (eight entries):
+
+000: A,1
+001: A,1
+010: A,1
+011: A,1
+100: B,2
+101: B,2
+110: -> table X (gobble 3 bits)
+111: -> table Y (gobble 3 bits)
+
+Each entry is what the bits decode as and how many bits that is, i.e. how
+many bits to gobble. Or the entry points to another table, with the number of
+bits to gobble implicit in the size of the table.
+
+Table X is two bits long since the longest code starting with 110 is five bits
+long:
+
+00: C,1
+01: C,1
+10: D,2
+11: E,2
+
+Table Y is three bits long since the longest code starting with 111 is six
+bits long:
+
+000: F,2
+001: F,2
+010: G,2
+011: G,2
+100: H,2
+101: H,2
+110: I,3
+111: J,3
+
+So what we have here are three tables with a total of 20 entries that had to
+be constructed. That's compared to 64 entries for a single table. Or
+compared to 16 entries for a Huffman tree (six two entry tables and one four
+entry table). Assuming that the code ideally represents the probability of
+the symbols, it takes on the average 1.25 lookups per symbol. That's compared
+to one lookup for the single table, or 1.66 lookups per symbol for the
+Huffman tree.
+
+There, I think that gives you a picture of what's going on. For inflate, the
+meaning of a particular symbol is often more than just a letter. It can be a
+byte (a "literal"), or it can be either a length or a distance which
+indicates a base value and a number of bits to fetch after the code that is
+added to the base value. Or it might be the special end-of-block code. The
+data structures created in inftrees.c try to encode all that information
+compactly in the tables.
+
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
+
+
+References:
+
+[LZ77] Ziv J., Lempel A., ``A Universal Algorithm for Sequential Data
+Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3,
+pp. 337-343.
+
+``DEFLATE Compressed Data Format Specification'' available in
+http://www.ietf.org/rfc/rfc1951.txt
diff --git a/Source/ZLib/compress.c b/Source/ZLib/compress.c
new file mode 100644
index 0000000..0baf863
--- /dev/null
+++ b/Source/ZLib/compress.c
@@ -0,0 +1,79 @@
+/* compress.c -- compress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: compress.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least 0.1% larger than sourceLen plus
+ 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+ int level;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+#ifdef MAXSEG_64K
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+#endif
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+ stream.opaque = (voidpf)0;
+
+ err = deflateInit(&stream, level);
+ if (err != Z_OK) return err;
+
+ err = deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ deflateEnd(&stream);
+ return err == Z_OK ? Z_BUF_ERROR : err;
+ }
+ *destLen = stream.total_out;
+
+ err = deflateEnd(&stream);
+ return err;
+}
+
+/* ===========================================================================
+ */
+int ZEXPORT compress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
+}
+
+/* ===========================================================================
+ If the default memLevel or windowBits for deflateInit() is changed, then
+ this function needs to be updated.
+ */
+uLong ZEXPORT compressBound (sourceLen)
+ uLong sourceLen;
+{
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
+}
diff --git a/Source/ZLib/configure b/Source/ZLib/configure
new file mode 100755
index 0000000..d7ffdc3
--- /dev/null
+++ b/Source/ZLib/configure
@@ -0,0 +1,459 @@
+#!/bin/sh
+# configure script for zlib. This script is needed only if
+# you wish to build a shared library and your system supports them,
+# of if you need special compiler, flags or install directory.
+# Otherwise, you can just use directly "make test; make install"
+#
+# To create a shared library, use "configure --shared"; by default a static
+# library is created. If the primitive shared library support provided here
+# does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz
+#
+# To impose specific compiler or flags or install directory, use for example:
+# prefix=$HOME CC=cc CFLAGS="-O4" ./configure
+# or for csh/tcsh users:
+# (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure)
+# LDSHARED is the command to be used to create a shared library
+
+# Incorrect settings of CC or CFLAGS may prevent creating a shared library.
+# If you have problems, try without defining CC and CFLAGS before reporting
+# an error.
+
+LIBS=libz.a
+LDFLAGS="-L. ${LIBS}"
+VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h`
+VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h`
+VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h`
+AR=${AR-"ar rc"}
+RANLIB=${RANLIB-"ranlib"}
+prefix=${prefix-/usr/local}
+exec_prefix=${exec_prefix-'${prefix}'}
+libdir=${libdir-'${exec_prefix}/lib'}
+includedir=${includedir-'${prefix}/include'}
+mandir=${mandir-'${prefix}/share/man'}
+shared_ext='.so'
+shared=0
+gcc=0
+old_cc="$CC"
+old_cflags="$CFLAGS"
+
+while test $# -ge 1
+do
+case "$1" in
+ -h* | --h*)
+ echo 'usage:'
+ echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]'
+ echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR]'
+ exit 0;;
+ -p*=* | --p*=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -e*=* | --e*=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;;
+ -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;;
+ -p* | --p*) prefix="$2"; shift; shift;;
+ -e* | --e*) exec_prefix="$2"; shift; shift;;
+ -l* | --l*) libdir="$2"; shift; shift;;
+ -i* | --i*) includedir="$2"; shift; shift;;
+ -s* | --s*) shared=1; shift;;
+ *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;;
+ esac
+done
+
+test=ztest$$
+cat > $test.c <<EOF
+extern int getchar();
+int hello() {return getchar();}
+EOF
+
+test -z "$CC" && echo Checking for gcc...
+cc=${CC-gcc}
+cflags=${CFLAGS-"-O3"}
+# to force the asm version use: CFLAGS="-O3 -DASMV" ./configure
+case "$cc" in
+ *gcc*) gcc=1;;
+esac
+
+if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
+ CC="$cc"
+ SFLAGS=${CFLAGS-"-fPIC -O3"}
+ CFLAGS="$cflags"
+ case `(uname -s || echo unknown) 2>/dev/null` in
+ Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1"};;
+ CYGWIN* | Cygwin* | cygwin* | OS/2* )
+ EXE='.exe';;
+ QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4
+ # (alain.bonnefoy@icbt.com)
+ LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};;
+ HP-UX*)
+ LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"}
+ case `(uname -m || echo unknown) 2>/dev/null` in
+ ia64)
+ shared_ext='.so'
+ SHAREDLIB='libz.so';;
+ *)
+ shared_ext='.sl'
+ SHAREDLIB='libz.sl';;
+ esac;;
+ Darwin*) shared_ext='.dylib'
+ SHAREDLIB=libz$shared_ext
+ SHAREDLIBV=libz.$VER$shared_ext
+ SHAREDLIBM=libz.$VER1$shared_ext
+ LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};;
+ *) LDSHARED=${LDSHARED-"$cc -shared"};;
+ esac
+else
+ # find system name and corresponding cc options
+ CC=${CC-cc}
+ case `(uname -sr || echo unknown) 2>/dev/null` in
+ HP-UX*) SFLAGS=${CFLAGS-"-O +z"}
+ CFLAGS=${CFLAGS-"-O"}
+# LDSHARED=${LDSHARED-"ld -b +vnocompatwarnings"}
+ LDSHARED=${LDSHARED-"ld -b"}
+ case `(uname -m || echo unknown) 2>/dev/null` in
+ ia64)
+ shared_ext='.so'
+ SHAREDLIB='libz.so';;
+ *)
+ shared_ext='.sl'
+ SHAREDLIB='libz.sl';;
+ esac;;
+ IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."}
+ CFLAGS=${CFLAGS-"-ansi -O2"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};;
+ OSF1*) SFLAGS=${CFLAGS-"-O -std1"}
+ CFLAGS=${CFLAGS-"-O -std1"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ QNX*) SFLAGS=${CFLAGS-"-4 -O"}
+ CFLAGS=${CFLAGS-"-4 -O"}
+ LDSHARED=${LDSHARED-"cc"}
+ RANLIB=${RANLIB-"true"}
+ AR="cc -A";;
+ SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "}
+ CFLAGS=${CFLAGS-"-O3"}
+ LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};;
+ SunOS\ 5*) SFLAGS=${CFLAGS-"-fast -xcg89 -KPIC -R."}
+ CFLAGS=${CFLAGS-"-fast -xcg89"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
+ CFLAGS=${CFLAGS-"-O2"}
+ LDSHARED=${LDSHARED-"ld"};;
+ SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
+ CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
+ LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
+ UNIX_System_V\ 4.2.0)
+ SFLAGS=${CFLAGS-"-KPIC -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ UNIX_SV\ 4.2MP)
+ SFLAGS=${CFLAGS-"-Kconform_pic -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ OpenUNIX\ 5)
+ SFLAGS=${CFLAGS-"-KPIC -O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -G"};;
+ AIX*) # Courtesy of dbakker@arrayasolutions.com
+ SFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+ CFLAGS=${CFLAGS-"-O -qmaxmem=8192"}
+ LDSHARED=${LDSHARED-"xlc -G"};;
+ # send working options for other systems to support@gzip.org
+ *) SFLAGS=${CFLAGS-"-O"}
+ CFLAGS=${CFLAGS-"-O"}
+ LDSHARED=${LDSHARED-"cc -shared"};;
+ esac
+fi
+
+SHAREDLIB=${SHAREDLIB-"libz$shared_ext"}
+SHAREDLIBV=${SHAREDLIBV-"libz$shared_ext.$VER"}
+SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"}
+
+if test $shared -eq 1; then
+ echo Checking for shared library support...
+ # we must test in two steps (cc then ld), required at least on SunOS 4.x
+ if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" &&
+ test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then
+ CFLAGS="$SFLAGS"
+ LIBS="$SHAREDLIBV"
+ echo Building shared library $SHAREDLIBV with $CC.
+ elif test -z "$old_cc" -a -z "$old_cflags"; then
+ echo No shared library support.
+ shared=0;
+ else
+ echo 'No shared library support; try without defining CC and CFLAGS'
+ shared=0;
+ fi
+fi
+if test $shared -eq 0; then
+ LDSHARED="$CC"
+ echo Building static library $LIBS version $VER with $CC.
+else
+ LDFLAGS="-L. ${SHAREDLIBV}"
+fi
+
+cat > $test.c <<EOF
+#include <unistd.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ sed < zconf.in.h "/HAVE_UNISTD_H/s%0%1%" > zconf.h
+ echo "Checking for unistd.h... Yes."
+else
+ cp -p zconf.in.h zconf.h
+ echo "Checking for unistd.h... No."
+fi
+
+cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+#include "zconf.h"
+
+int main()
+{
+#ifndef STDC
+ choke me
+#endif
+
+ return 0;
+}
+EOF
+
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking whether to use vs[n]printf() or s[n]printf()... using vs[n]printf()"
+
+ cat > $test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+ char buf[20];
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return 0;
+}
+
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+
+ if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
+ echo "Checking for vsnprintf() in stdio.h... Yes."
+
+ cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+ int n;
+ char buf[20];
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ return n;
+}
+
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+
+ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for return value of vsnprintf()... Yes."
+ else
+ CFLAGS="$CFLAGS -DHAS_vsnprintf_void"
+ echo "Checking for return value of vsnprintf()... No."
+ echo " WARNING: apparently vsnprintf() does not return a value. zlib"
+ echo " can build but will be open to possible string-format security"
+ echo " vulnerabilities."
+ fi
+ else
+ CFLAGS="$CFLAGS -DNO_vsnprintf"
+ echo "Checking for vsnprintf() in stdio.h... No."
+ echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib"
+ echo " can build but will be open to possible buffer-overflow security"
+ echo " vulnerabilities."
+
+ cat >$test.c <<EOF
+#include <stdio.h>
+#include <stdarg.h>
+
+int mytest(char *fmt, ...)
+{
+ int n;
+ char buf[20];
+ va_list ap;
+
+ va_start(ap, fmt);
+ n = vsprintf(buf, fmt, ap);
+ va_end(ap);
+ return n;
+}
+
+int main()
+{
+ return (mytest("Hello%d\n", 1));
+}
+EOF
+
+ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for return value of vsprintf()... Yes."
+ else
+ CFLAGS="$CFLAGS -DHAS_vsprintf_void"
+ echo "Checking for return value of vsprintf()... No."
+ echo " WARNING: apparently vsprintf() does not return a value. zlib"
+ echo " can build but will be open to possible string-format security"
+ echo " vulnerabilities."
+ fi
+ fi
+else
+ echo "Checking whether to use vs[n]printf() or s[n]printf()... using s[n]printf()"
+
+ cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+ char buf[20];
+
+ snprintf(buf, sizeof(buf), "%s", "foo");
+ return 0;
+}
+
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if test "`($CC $CFLAGS -o $test $test.c) 2>&1`" = ""; then
+ echo "Checking for snprintf() in stdio.h... Yes."
+
+ cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+ char buf[20];
+
+ return snprintf(buf, sizeof(buf), "%s", "foo");
+}
+
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for return value of snprintf()... Yes."
+ else
+ CFLAGS="$CFLAGS -DHAS_snprintf_void"
+ echo "Checking for return value of snprintf()... No."
+ echo " WARNING: apparently snprintf() does not return a value. zlib"
+ echo " can build but will be open to possible string-format security"
+ echo " vulnerabilities."
+ fi
+ else
+ CFLAGS="$CFLAGS -DNO_snprintf"
+ echo "Checking for snprintf() in stdio.h... No."
+ echo " WARNING: snprintf() not found, falling back to sprintf(). zlib"
+ echo " can build but will be open to possible buffer-overflow security"
+ echo " vulnerabilities."
+
+ cat >$test.c <<EOF
+#include <stdio.h>
+
+int mytest()
+{
+ char buf[20];
+
+ return sprintf(buf, "%s", "foo");
+}
+
+int main()
+{
+ return (mytest());
+}
+EOF
+
+ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for return value of sprintf()... Yes."
+ else
+ CFLAGS="$CFLAGS -DHAS_sprintf_void"
+ echo "Checking for return value of sprintf()... No."
+ echo " WARNING: apparently sprintf() does not return a value. zlib"
+ echo " can build but will be open to possible string-format security"
+ echo " vulnerabilities."
+ fi
+ fi
+fi
+
+cat >$test.c <<EOF
+#include <errno.h>
+int main() { return 0; }
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ echo "Checking for errno.h... Yes."
+else
+ echo "Checking for errno.h... No."
+ CFLAGS="$CFLAGS -DNO_ERRNO_H"
+fi
+
+cat > $test.c <<EOF
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+caddr_t hello() {
+ return mmap((caddr_t)0, (off_t)0, PROT_READ, MAP_SHARED, 0, (off_t)0);
+}
+EOF
+if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then
+ CFLAGS="$CFLAGS -DUSE_MMAP"
+ echo Checking for mmap support... Yes.
+else
+ echo Checking for mmap support... No.
+fi
+
+CPP=${CPP-"$CC -E"}
+case $CFLAGS in
+ *ASMV*)
+ if test "`nm $test.o | grep _hello`" = ""; then
+ CPP="$CPP -DNO_UNDERLINE"
+ echo Checking for underline in external names... No.
+ else
+ echo Checking for underline in external names... Yes.
+ fi;;
+esac
+
+rm -f $test.[co] $test $test$shared_ext
+
+# udpate Makefile
+sed < Makefile.in "
+/^CC *=/s#=.*#=$CC#
+/^CFLAGS *=/s#=.*#=$CFLAGS#
+/^CPP *=/s#=.*#=$CPP#
+/^LDSHARED *=/s#=.*#=$LDSHARED#
+/^LIBS *=/s#=.*#=$LIBS#
+/^SHAREDLIB *=/s#=.*#=$SHAREDLIB#
+/^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV#
+/^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM#
+/^AR *=/s#=.*#=$AR#
+/^RANLIB *=/s#=.*#=$RANLIB#
+/^EXE *=/s#=.*#=$EXE#
+/^prefix *=/s#=.*#=$prefix#
+/^exec_prefix *=/s#=.*#=$exec_prefix#
+/^libdir *=/s#=.*#=$libdir#
+/^includedir *=/s#=.*#=$includedir#
+/^mandir *=/s#=.*#=$mandir#
+/^LDFLAGS *=/s#=.*#=$LDFLAGS#
+" > Makefile
diff --git a/Source/ZLib/crc32.c b/Source/ZLib/crc32.c
new file mode 100644
index 0000000..39d5ea3
--- /dev/null
+++ b/Source/ZLib/crc32.c
@@ -0,0 +1,423 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+/* @(#) $Id: crc32.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for STDC and FAR definitions */
+
+#define local static
+
+/* Find a four-byte integer type for crc32_little() and crc32_big(). */
+#ifndef NOBYFOUR
+# ifdef STDC /* need ANSI C limits.h to determine sizes */
+# include <limits.h>
+# define BYFOUR
+# if (UINT_MAX == 0xffffffffUL)
+ typedef unsigned int u4;
+# else
+# if (ULONG_MAX == 0xffffffffUL)
+ typedef unsigned long u4;
+# else
+# if (USHRT_MAX == 0xffffffffUL)
+ typedef unsigned short u4;
+# else
+# undef BYFOUR /* can't find a four-byte integer type! */
+# endif
+# endif
+# endif
+# endif /* STDC */
+#endif /* !NOBYFOUR */
+
+/* Definitions for doing the crc four data bytes at a time. */
+#ifdef BYFOUR
+# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
+ (((w)&0xff00)<<8)+(((w)&0xff)<<24))
+ local unsigned long crc32_little OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+ local unsigned long crc32_big OF((unsigned long,
+ const unsigned char FAR *, unsigned));
+# define TBLS 8
+#else
+# define TBLS 1
+#endif /* BYFOUR */
+
+/* Local functions for crc concatenation */
+local unsigned long gf2_matrix_times OF((unsigned long *mat,
+ unsigned long vec));
+local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local volatile int crc_table_empty = 1;
+local unsigned long FAR crc_table[TBLS][256];
+local void make_crc_table OF((void));
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const unsigned long FAR *));
+#endif /* MAKECRCH */
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+ x (which is shifting right by one and adding x^32 mod p if the bit shifted
+ out is a one). We start with the highest power (least significant bit) of
+ q and repeat for all eight bits of q.
+
+ The first table is simply the CRC of all possible eight bit values. This is
+ all the information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes. The remaining tables
+ allow for word-at-a-time CRC calculation for both big-endian and little-
+ endian machines, where a word is four bytes.
+*/
+local void make_crc_table()
+{
+ unsigned long c;
+ int n, k;
+ unsigned long poly; /* polynomial exclusive-or pattern */
+ /* terms of polynomial defining this crc (except x^32): */
+ static volatile int first = 1; /* flag to limit concurrent making */
+ static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+ /* See if another task is already doing this (not thread-safe, but better
+ than nothing -- significantly reduces duration of vulnerability in
+ case the advice about DYNAMIC_CRC_TABLE is ignored) */
+ if (first) {
+ first = 0;
+
+ /* make exclusive-or pattern from polynomial (0xedb88320UL) */
+ poly = 0UL;
+ for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
+ poly |= 1UL << (31 - p[n]);
+
+ /* generate a crc for every 8-bit value */
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long)n;
+ for (k = 0; k < 8; k++)
+ c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+ crc_table[0][n] = c;
+ }
+
+#ifdef BYFOUR
+ /* generate crc for each value followed by one, two, and three zeros,
+ and then the byte reversal of those as well as the first table */
+ for (n = 0; n < 256; n++) {
+ c = crc_table[0][n];
+ crc_table[4][n] = REV(c);
+ for (k = 1; k < 4; k++) {
+ c = crc_table[0][c & 0xff] ^ (c >> 8);
+ crc_table[k][n] = c;
+ crc_table[k + 4][n] = REV(c);
+ }
+ }
+#endif /* BYFOUR */
+
+ crc_table_empty = 0;
+ }
+ else { /* not first */
+ /* wait for the other guy to finish (not efficient, but rare) */
+ while (crc_table_empty)
+ ;
+ }
+
+#ifdef MAKECRCH
+ /* write out CRC tables to crc32.h */
+ {
+ FILE *out;
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+ fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
+ fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
+ fprintf(out, "local const unsigned long FAR ");
+ fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
+ write_table(out, crc_table[0]);
+# ifdef BYFOUR
+ fprintf(out, "#ifdef BYFOUR\n");
+ for (k = 1; k < 8; k++) {
+ fprintf(out, " },\n {\n");
+ write_table(out, crc_table[k]);
+ }
+ fprintf(out, "#endif\n");
+# endif /* BYFOUR */
+ fprintf(out, " }\n};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+local void write_table(out, table)
+ FILE *out;
+ const unsigned long FAR *table;
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
+ n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+}
+#endif /* MAKECRCH */
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+const unsigned long FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const unsigned long FAR *)crc_table;
+}
+
+/* ========================================================================= */
+#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
+#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ if (buf == Z_NULL) return 0UL;
+
+#ifdef DYNAMIC_CRC_TABLE
+ if (crc_table_empty)
+ make_crc_table();
+#endif /* DYNAMIC_CRC_TABLE */
+
+#ifdef BYFOUR
+ if (sizeof(void *) == sizeof(ptrdiff_t)) {
+ u4 endian;
+
+ endian = 1;
+ if (*((unsigned char *)(&endian)))
+ return crc32_little(crc, buf, len);
+ else
+ return crc32_big(crc, buf, len);
+ }
+#endif /* BYFOUR */
+ crc = crc ^ 0xffffffffUL;
+ while (len >= 8) {
+ DO8;
+ len -= 8;
+ }
+ if (len) do {
+ DO1;
+ } while (--len);
+ return crc ^ 0xffffffffUL;
+}
+
+#ifdef BYFOUR
+
+/* ========================================================================= */
+#define DOLIT4 c ^= *buf4++; \
+ c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
+ crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
+#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+
+/* ========================================================================= */
+local unsigned long crc32_little(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = (u4)crc;
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ while (len >= 32) {
+ DOLIT32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOLIT4;
+ len -= 4;
+ }
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)c;
+}
+
+/* ========================================================================= */
+#define DOBIG4 c ^= *++buf4; \
+ c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
+ crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
+#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+
+/* ========================================================================= */
+local unsigned long crc32_big(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ unsigned len;
+{
+ register u4 c;
+ register const u4 FAR *buf4;
+
+ c = REV((u4)crc);
+ c = ~c;
+ while (len && ((ptrdiff_t)buf & 3)) {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ len--;
+ }
+
+ buf4 = (const u4 FAR *)(const void FAR *)buf;
+ buf4--;
+ while (len >= 32) {
+ DOBIG32;
+ len -= 32;
+ }
+ while (len >= 4) {
+ DOBIG4;
+ len -= 4;
+ }
+ buf4++;
+ buf = (const unsigned char FAR *)buf4;
+
+ if (len) do {
+ c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
+ } while (--len);
+ c = ~c;
+ return (unsigned long)(REV(c));
+}
+
+#endif /* BYFOUR */
+
+#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+local unsigned long gf2_matrix_times(mat, vec)
+ unsigned long *mat;
+ unsigned long vec;
+{
+ unsigned long sum;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= *mat;
+ vec >>= 1;
+ mat++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+local void gf2_matrix_square(square, mat)
+ unsigned long *square;
+ unsigned long *mat;
+{
+ int n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off_t len2;
+{
+ int n;
+ unsigned long row;
+ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
+ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
+
+ /* degenerate case */
+ if (len2 == 0)
+ return crc1;
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320L; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+}
diff --git a/Source/ZLib/crc32.h b/Source/ZLib/crc32.h
new file mode 100644
index 0000000..8053b61
--- /dev/null
+++ b/Source/ZLib/crc32.h
@@ -0,0 +1,441 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const unsigned long FAR crc_table[TBLS][256] =
+{
+ {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+#ifdef BYFOUR
+ },
+ {
+ 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
+ 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
+ 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
+ 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
+ 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
+ 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
+ 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
+ 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
+ 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
+ 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
+ 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
+ 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
+ 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
+ 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
+ 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
+ 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
+ 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
+ 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
+ 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
+ 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
+ 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
+ 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
+ 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
+ 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
+ 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
+ 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
+ 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
+ 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
+ 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
+ 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
+ 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
+ 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
+ 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
+ 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
+ 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
+ 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
+ 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
+ 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
+ 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
+ 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
+ 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
+ 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
+ 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
+ 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
+ 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
+ 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
+ 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
+ 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
+ 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
+ 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
+ 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
+ 0x9324fd72UL
+ },
+ {
+ 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
+ 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
+ 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
+ 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
+ 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
+ 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
+ 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
+ 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
+ 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
+ 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
+ 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
+ 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
+ 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
+ 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
+ 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
+ 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
+ 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
+ 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
+ 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
+ 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
+ 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
+ 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
+ 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
+ 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
+ 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
+ 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
+ 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
+ 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
+ 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
+ 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
+ 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
+ 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
+ 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
+ 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
+ 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
+ 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
+ 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
+ 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
+ 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
+ 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
+ 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
+ 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
+ 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
+ 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
+ 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
+ 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
+ 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
+ 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
+ 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
+ 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
+ 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
+ 0xbe9834edUL
+ },
+ {
+ 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
+ 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
+ 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
+ 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
+ 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
+ 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
+ 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
+ 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
+ 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
+ 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
+ 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
+ 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
+ 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
+ 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
+ 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
+ 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
+ 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
+ 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
+ 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
+ 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
+ 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
+ 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
+ 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
+ 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
+ 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
+ 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
+ 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
+ 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
+ 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
+ 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
+ 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
+ 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
+ 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
+ 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
+ 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
+ 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
+ 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
+ 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
+ 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
+ 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
+ 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
+ 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
+ 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
+ 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
+ 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
+ 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
+ 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
+ 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
+ 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
+ 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
+ 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
+ 0xde0506f1UL
+ },
+ {
+ 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
+ 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
+ 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
+ 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
+ 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
+ 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
+ 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
+ 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
+ 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
+ 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
+ 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
+ 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
+ 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
+ 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
+ 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
+ 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
+ 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
+ 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
+ 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
+ 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
+ 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
+ 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
+ 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
+ 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
+ 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
+ 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
+ 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
+ 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
+ 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
+ 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
+ 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
+ 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
+ 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
+ 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
+ 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
+ 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
+ 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
+ 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
+ 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
+ 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
+ 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
+ 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
+ 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
+ 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
+ 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
+ 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
+ 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
+ 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
+ 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
+ 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
+ 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
+ 0x8def022dUL
+ },
+ {
+ 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
+ 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
+ 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
+ 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
+ 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
+ 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
+ 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
+ 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
+ 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
+ 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
+ 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
+ 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
+ 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
+ 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
+ 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
+ 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
+ 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
+ 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
+ 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
+ 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
+ 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
+ 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
+ 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
+ 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
+ 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
+ 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
+ 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
+ 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
+ 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
+ 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
+ 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
+ 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
+ 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
+ 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
+ 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
+ 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
+ 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
+ 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
+ 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
+ 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
+ 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
+ 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
+ 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
+ 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
+ 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
+ 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
+ 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
+ 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
+ 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
+ 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
+ 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
+ 0x72fd2493UL
+ },
+ {
+ 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
+ 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
+ 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
+ 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
+ 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
+ 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
+ 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
+ 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
+ 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
+ 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
+ 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
+ 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
+ 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
+ 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
+ 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
+ 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
+ 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
+ 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
+ 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
+ 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
+ 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
+ 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
+ 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
+ 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
+ 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
+ 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
+ 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
+ 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
+ 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
+ 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
+ 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
+ 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
+ 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
+ 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
+ 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
+ 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
+ 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
+ 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
+ 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
+ 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
+ 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
+ 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
+ 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
+ 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
+ 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
+ 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
+ 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
+ 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
+ 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
+ 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
+ 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
+ 0xed3498beUL
+ },
+ {
+ 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
+ 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
+ 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
+ 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
+ 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
+ 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
+ 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
+ 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
+ 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
+ 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
+ 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
+ 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
+ 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
+ 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
+ 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
+ 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
+ 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
+ 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
+ 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
+ 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
+ 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
+ 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
+ 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
+ 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
+ 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
+ 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
+ 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
+ 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
+ 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
+ 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
+ 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
+ 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
+ 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
+ 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
+ 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
+ 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
+ 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
+ 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
+ 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
+ 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
+ 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
+ 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
+ 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
+ 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
+ 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
+ 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
+ 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
+ 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
+ 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
+ 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
+ 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
+ 0xf10605deUL
+#endif
+ }
+};
diff --git a/Source/ZLib/deflate.c b/Source/ZLib/deflate.c
new file mode 100644
index 0000000..1425fcd
--- /dev/null
+++ b/Source/ZLib/deflate.c
@@ -0,0 +1,1736 @@
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in http://www.ietf.org/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+/* @(#) $Id: deflate.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#include "deflate.h"
+
+const char deflate_copyright[] =
+ " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) OF((deflate_state *s, int flush));
+/* Compression function. Returns the block state after the call. */
+
+local void fill_window OF((deflate_state *s));
+local block_state deflate_stored OF((deflate_state *s, int flush));
+local block_state deflate_fast OF((deflate_state *s, int flush));
+#ifndef FASTEST
+local block_state deflate_slow OF((deflate_state *s, int flush));
+#endif
+local void lm_init OF((deflate_state *s));
+local void putShortMSB OF((deflate_state *s, uInt b));
+local void flush_pending OF((z_streamp strm));
+local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
+#ifndef FASTEST
+#ifdef ASMV
+ void match_init OF((void)); /* asm code initialization */
+ uInt longest_match OF((deflate_state *s, IPos cur_match));
+#else
+local uInt longest_match OF((deflate_state *s, IPos cur_match));
+#endif
+#endif
+local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
+
+#ifdef DEBUG
+local void check_match OF((deflate_state *s, IPos start, IPos match,
+ int length));
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+#ifdef FASTEST
+local const config configuration_table[2] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}}; /* max speed, no lazy matches */
+#else
+local const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* max speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* max compression */
+#endif
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+#ifndef NO_DUMMY_DECL
+struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
+#endif
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * If this file is compiled with -DFASTEST, the compression level is forced
+ * to 1, and no hash chains are maintained.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#ifdef FASTEST
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#else
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ match_head = s->prev[(str) & s->w_mask] = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+#endif
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int ZEXPORT deflateInit_(strm, level, version, stream_size)
+ z_streamp strm;
+ int level;
+ const char *version;
+ int stream_size;
+{
+ return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
+ version, stream_size)
+ z_streamp strm;
+ int level;
+ int method;
+ int windowBits;
+ int memLevel;
+ int strategy;
+ const char *version;
+ int stream_size;
+{
+ deflate_state *s;
+ int wrap = 1;
+ static const char my_version[] = ZLIB_VERSION;
+
+ ushf *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == Z_NULL || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+
+ strm->msg = Z_NULL;
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+
+ if (windowBits < 0) { /* suppress zlib wrapper */
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+#ifdef GZIP
+ else if (windowBits > 15) {
+ wrap = 2; /* write gzip wrapper instead */
+ windowBits -= 16;
+ }
+#endif
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
+ s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+ if (s == Z_NULL) return Z_MEM_ERROR;
+ strm->state = (struct internal_state FAR *)s;
+ s->strm = strm;
+
+ s->wrap = wrap;
+ s->gzhead = Z_NULL;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+ s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
+ s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
+ s->pending_buf = (uchf *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
+ s->pending_buf == Z_NULL) {
+ s->status = FINISH_STATE;
+ strm->msg = (char*)ERR_MSG(Z_MEM_ERROR);
+ deflateEnd (strm);
+ return Z_MEM_ERROR;
+ }
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return deflateReset(strm);
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
+ z_streamp strm;
+ const Bytef *dictionary;
+ uInt dictLength;
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL ||
+ strm->state->wrap == 2 ||
+ (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
+ return Z_STREAM_ERROR;
+
+ s = strm->state;
+ if (s->wrap)
+ strm->adler = adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+ }
+ zmemcpy(s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateReset (strm)
+ z_streamp strm;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->wrap < 0) {
+ s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */
+ }
+ s->status = s->wrap ? INIT_STATE : BUSY_STATE;
+ strm->adler =
+#ifdef GZIP
+ s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
+#endif
+ adler32(0L, Z_NULL, 0);
+ s->last_flush = Z_NO_FLUSH;
+
+ _tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateSetHeader (strm, head)
+ z_streamp strm;
+ gz_headerp head;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ if (strm->state->wrap != 2) return Z_STREAM_ERROR;
+ strm->state->gzhead = head;
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflatePrime (strm, bits, value)
+ z_streamp strm;
+ int bits;
+ int value;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ strm->state->bi_valid = bits;
+ strm->state->bi_buf = (ush)(value & ((1 << bits) - 1));
+ return Z_OK;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateParams(strm, level, strategy)
+ z_streamp strm;
+ int level;
+ int strategy;
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+
+#ifdef FASTEST
+ if (level != 0) level = 1;
+#else
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+#endif
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
+ z_streamp strm;
+ int good_length;
+ int max_lazy;
+ int nice_length;
+ int max_chain;
+{
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ s = strm->state;
+ s->good_match = good_length;
+ s->max_lazy_match = max_lazy;
+ s->nice_match = nice_length;
+ s->max_chain_length = max_chain;
+ return Z_OK;
+}
+
+/* =========================================================================
+ * For the default windowBits of 15 and memLevel of 8, this function returns
+ * a close to exact, as well as small, upper bound on the compressed size.
+ * They are coded as constants here for a reason--if the #define's are
+ * changed, then this function needs to be changed as well. The return
+ * value for 15 and 8 only works for those exact settings.
+ *
+ * For any setting other than those defaults for windowBits and memLevel,
+ * the value returned is a conservative worst case for the maximum expansion
+ * resulting from using fixed blocks instead of stored blocks, which deflate
+ * can emit on compressed data for some combinations of the parameters.
+ *
+ * This function could be more sophisticated to provide closer upper bounds
+ * for every combination of windowBits and memLevel, as well as wrap.
+ * But even the conservative upper bound of about 14% expansion does not
+ * seem onerous for output buffer allocation.
+ */
+uLong ZEXPORT deflateBound(strm, sourceLen)
+ z_streamp strm;
+ uLong sourceLen;
+{
+ deflate_state *s;
+ uLong destLen;
+
+ /* conservative upper bound */
+ destLen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+
+ /* if can't get parameters, return conservative bound */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return destLen;
+
+ /* if not default parameters, return conservative bound */
+ s = strm->state;
+ if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+ return destLen;
+
+ /* default settings: return tight bound for that case */
+ return compressBound(sourceLen);
+}
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+local void putShortMSB (s, b)
+ deflate_state *s;
+ uInt b;
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+local void flush_pending(strm)
+ z_streamp strm;
+{
+ unsigned len = strm->state->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ zmemcpy(strm->next_out, strm->state->pending_out, len);
+ strm->next_out += len;
+ strm->state->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ strm->state->pending -= len;
+ if (strm->state->pending == 0) {
+ strm->state->pending_out = strm->state->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int ZEXPORT deflate (strm, flush)
+ z_streamp strm;
+ int flush;
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == Z_NULL || strm->state == Z_NULL ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = strm->state;
+
+ if (strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ ERR_RETURN(strm, Z_STREAM_ERROR);
+ }
+ if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR);
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the header */
+ if (s->status == INIT_STATE) {
+#ifdef GZIP
+ if (s->wrap == 2) {
+ strm->adler = crc32(0L, Z_NULL, 0);
+ put_byte(s, 31);
+ put_byte(s, 139);
+ put_byte(s, 8);
+ if (s->gzhead == NULL) {
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, 0);
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, OS_CODE);
+ s->status = BUSY_STATE;
+ }
+ else {
+ put_byte(s, (s->gzhead->text ? 1 : 0) +
+ (s->gzhead->hcrc ? 2 : 0) +
+ (s->gzhead->extra == Z_NULL ? 0 : 4) +
+ (s->gzhead->name == Z_NULL ? 0 : 8) +
+ (s->gzhead->comment == Z_NULL ? 0 : 16)
+ );
+ put_byte(s, (Byte)(s->gzhead->time & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff));
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff));
+ put_byte(s, s->level == 9 ? 2 :
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
+ 4 : 0));
+ put_byte(s, s->gzhead->os & 0xff);
+ if (s->gzhead->extra != NULL) {
+ put_byte(s, s->gzhead->extra_len & 0xff);
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
+ }
+ if (s->gzhead->hcrc)
+ strm->adler = crc32(strm->adler, s->pending_buf,
+ s->pending);
+ s->gzindex = 0;
+ s->status = EXTRA_STATE;
+ }
+ }
+ else
+#endif
+ {
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags;
+
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2)
+ level_flags = 0;
+ else if (s->level < 6)
+ level_flags = 1;
+ else if (s->level == 6)
+ level_flags = 2;
+ else
+ level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = adler32(0L, Z_NULL, 0);
+ }
+ }
+#ifdef GZIP
+ if (s->status == EXTRA_STATE) {
+ if (s->gzhead->extra != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+
+ while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size)
+ break;
+ }
+ put_byte(s, s->gzhead->extra[s->gzindex]);
+ s->gzindex++;
+ }
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (s->gzindex == s->gzhead->extra_len) {
+ s->gzindex = 0;
+ s->status = NAME_STATE;
+ }
+ }
+ else
+ s->status = NAME_STATE;
+ }
+ if (s->status == NAME_STATE) {
+ if (s->gzhead->name != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->name[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0) {
+ s->gzindex = 0;
+ s->status = COMMENT_STATE;
+ }
+ }
+ else
+ s->status = COMMENT_STATE;
+ }
+ if (s->status == COMMENT_STATE) {
+ if (s->gzhead->comment != NULL) {
+ uInt beg = s->pending; /* start of bytes to update crc */
+ int val;
+
+ do {
+ if (s->pending == s->pending_buf_size) {
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ flush_pending(strm);
+ beg = s->pending;
+ if (s->pending == s->pending_buf_size) {
+ val = 1;
+ break;
+ }
+ }
+ val = s->gzhead->comment[s->gzindex++];
+ put_byte(s, val);
+ } while (val != 0);
+ if (s->gzhead->hcrc && s->pending > beg)
+ strm->adler = crc32(strm->adler, s->pending_buf + beg,
+ s->pending - beg);
+ if (val == 0)
+ s->status = HCRC_STATE;
+ }
+ else
+ s->status = HCRC_STATE;
+ }
+ if (s->status == HCRC_STATE) {
+ if (s->gzhead->hcrc) {
+ if (s->pending + 2 > s->pending_buf_size)
+ flush_pending(strm);
+ if (s->pending + 2 <= s->pending_buf_size) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ strm->adler = crc32(0L, Z_NULL, 0);
+ s->status = BUSY_STATE;
+ }
+ }
+ else
+ s->status = BUSY_STATE;
+ }
+#endif
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ ERR_RETURN(strm, Z_BUF_ERROR);
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ _tr_align(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ _tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->wrap <= 0) return Z_STREAM_END;
+
+ /* Write the trailer */
+#ifdef GZIP
+ if (s->wrap == 2) {
+ put_byte(s, (Byte)(strm->adler & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->adler >> 24) & 0xff));
+ put_byte(s, (Byte)(strm->total_in & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 8) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 16) & 0xff));
+ put_byte(s, (Byte)((strm->total_in >> 24) & 0xff));
+ }
+ else
+#endif
+ {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int ZEXPORT deflateEnd (strm)
+ z_streamp strm;
+{
+ int status;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+
+ status = strm->state->status;
+ if (status != INIT_STATE &&
+ status != EXTRA_STATE &&
+ status != NAME_STATE &&
+ status != COMMENT_STATE &&
+ status != HCRC_STATE &&
+ status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ /* Deallocate in reverse order of allocations: */
+ TRY_FREE(strm, strm->state->pending_buf);
+ TRY_FREE(strm, strm->state->head);
+ TRY_FREE(strm, strm->state->prev);
+ TRY_FREE(strm, strm->state->window);
+
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+/* =========================================================================
+ * Copy the source state to the destination state.
+ * To simplify the source, this is not supported for 16-bit MSDOS (which
+ * doesn't have enough memory anyway to duplicate compression states).
+ */
+int ZEXPORT deflateCopy (dest, source)
+ z_streamp dest;
+ z_streamp source;
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ushf *overlay;
+
+
+ if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = source->state;
+
+ zmemcpy(dest, source, sizeof(z_stream));
+
+ ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+ if (ds == Z_NULL) return Z_MEM_ERROR;
+ dest->state = (struct internal_state FAR *) ds;
+ zmemcpy(ds, ss, sizeof(deflate_state));
+ ds->strm = dest;
+
+ ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+ ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
+ ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
+ overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
+ ds->pending_buf = (uchf *) overlay;
+
+ if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
+ ds->pending_buf == Z_NULL) {
+ deflateEnd (dest);
+ return Z_MEM_ERROR;
+ }
+ /* following zmemcpy do not work for 16-bit MSDOS */
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif /* MAXSEG_64K */
+}
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+local int read_buf(strm, buf, size)
+ z_streamp strm;
+ Bytef *buf;
+ unsigned size;
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (strm->state->wrap == 1) {
+ strm->adler = adler32(strm->adler, strm->next_in, len);
+ }
+#ifdef GZIP
+ else if (strm->state->wrap == 2) {
+ strm->adler = crc32(strm->adler, strm->next_in, len);
+ }
+#endif
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+local void lm_init (s)
+ deflate_state *s;
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+#ifndef FASTEST
+#ifdef ASMV
+ match_init(); /* initialize the asm code */
+#endif
+#endif
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+#ifndef ASMV
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+local uInt longest_match(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Posf *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ushf*)scan;
+ register ush scan_end = *(ushf*)(scan+best_len-1);
+#else
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2. Note that the checks below
+ * for insufficient lookahead only occur occasionally for performance
+ * reasons. Therefore uninitialized memory will be accessed, and
+ * conditional jumps will be made that depend on those values.
+ * However the length of the match is limited to the lookahead, so
+ * the output of deflate is not affected by the uninitialized values.
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ushf*)(match+best_len-1) != scan_end ||
+ *(ushf*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ *(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ushf*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
+ return s->lookahead;
+}
+#endif /* ASMV */
+#endif /* FASTEST */
+
+/* ---------------------------------------------------------------------------
+ * Optimized version for level == 1 or strategy == Z_RLE only
+ */
+local uInt longest_match_fast(s, cur_match)
+ deflate_state *s;
+ IPos cur_match; /* current match */
+{
+ register Bytef *scan = s->window + s->strstart; /* current string */
+ register Bytef *match; /* matched string */
+ register int len; /* length of current match */
+ register Bytef *strend = s->window + s->strstart + MAX_MATCH;
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ Assert(cur_match < s->strstart, "no future");
+
+ match = s->window + cur_match;
+
+ /* Return failure if the match length is less than 2:
+ */
+ if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match += 2;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+
+ if (len < MIN_MATCH) return MIN_MATCH - 1;
+
+ s->match_start = cur_match;
+ return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
+}
+
+#ifdef DEBUG
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+local void check_match(s, start, match, length)
+ deflate_state *s;
+ IPos start, match;
+ int length;
+{
+ /* check that the match is indeed a match */
+ if (zmemcmp(s->window + match,
+ s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif /* DEBUG */
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+local void fill_window(s)
+ deflate_state *s;
+{
+ register unsigned n, m;
+ register Posf *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (sizeof(int) <= 2) {
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if
+ * strstart == 0 && lookahead == 1 (input done a byte at time)
+ */
+ more--;
+ }
+ }
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ /* %%% avoid this when Z_RLE */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+#ifndef FASTEST
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+#endif
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ _tr_flush_block(s, (s->block_start >= 0L ? \
+ (charf *)&s->window[(unsigned)s->block_start] : \
+ (charf *)Z_NULL), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+local block_state deflate_stored(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+local block_state deflate_fast(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+#ifdef FASTEST
+ if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
+ (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#else
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+#endif
+ /* longest_match() or longest_match_fast() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ _tr_tally_dist(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+#ifndef FASTEST
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else
+#endif
+ {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+#ifndef FASTEST
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+local block_state deflate_slow(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
+ s->match_length = longest_match (s, hash_head);
+ } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
+ s->match_length = longest_match_fast (s, hash_head);
+ }
+ /* longest_match() or longest_match_fast() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED
+#if TOO_FAR <= 32767
+ || (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR)
+#endif
+ )) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ _tr_tally_dist(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH, bflush);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ if (bflush) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ _tr_tally_lit(s, s->window[s->strstart-1], bflush);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif /* FASTEST */
+
+#if 0
+/* ===========================================================================
+ * For Z_RLE, simply look for runs of bytes, generate matches only of distance
+ * one. Do not maintain a hash table. (It will be regenerated if this run of
+ * deflate switches away from Z_RLE.)
+ */
+local block_state deflate_rle(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+ uInt run; /* length of run */
+ uInt max; /* maximum length of run */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan; /* scan for end of run */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the longest encodable run.
+ */
+ if (s->lookahead < MAX_MATCH) {
+ fill_window(s);
+ if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* See how many times the previous byte repeats */
+ run = 0;
+ if (s->strstart > 0) { /* if there is a previous byte, that is */
+ max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ scan = s->window + s->strstart - 1;
+ prev = *scan++;
+ do {
+ if (*scan++ != prev)
+ break;
+ } while (++run < max);
+ }
+
+ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
+ if (run >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, run);
+ _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
+ s->lookahead -= run;
+ s->strstart += run;
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+#endif
diff --git a/Source/ZLib/deflate.h b/Source/ZLib/deflate.h
new file mode 100644
index 0000000..640dca8
--- /dev/null
+++ b/Source/ZLib/deflate.h
@@ -0,0 +1,331 @@
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995-2004 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: deflate.h,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#ifndef DEFLATE_H
+#define DEFLATE_H
+
+#include "zutil.h"
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer creation by deflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip encoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GZIP
+#endif
+
+/* ===========================================================================
+ * Internal compression state.
+ */
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define EXTRA_STATE 69
+#define NAME_STATE 73
+#define COMMENT_STATE 91
+#define HCRC_STATE 103
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} FAR ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} FAR tree_desc;
+
+typedef ush Pos;
+typedef Pos FAR Posf;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct internal_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Bytef *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Bytef *pending_out; /* next pending byte to output to the stream */
+ uInt pending; /* nb of bytes in the pending buffer */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ gz_headerp gzhead; /* gzip header information to write */
+ uInt gzindex; /* where in extra, name, or comment */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Bytef *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Posf *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Posf *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uchf *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ushf *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG
+ ulg compressed_len; /* total bit length of compressed file mod 2^32 */
+ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} FAR deflate_state;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+void _tr_init OF((deflate_state *s));
+int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
+void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+void _tr_align OF((deflate_state *s));
+void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
+ int eof));
+
+#define d_code(dist) \
+ ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. _dist_code[256] and _dist_code[257] are never
+ * used.
+ */
+
+#ifndef DEBUG
+/* Inline versions of _tr_tally for speed: */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+ extern uch _length_code[];
+ extern uch _dist_code[];
+#else
+ extern const uch _length_code[];
+ extern const uch _dist_code[];
+#endif
+
+# define _tr_tally_lit(s, c, flush) \
+ { uch cc = (c); \
+ s->d_buf[s->last_lit] = 0; \
+ s->l_buf[s->last_lit++] = cc; \
+ s->dyn_ltree[cc].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+# define _tr_tally_dist(s, distance, length, flush) \
+ { uch len = (length); \
+ ush dist = (distance); \
+ s->d_buf[s->last_lit] = dist; \
+ s->l_buf[s->last_lit++] = len; \
+ dist--; \
+ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
+ s->dyn_dtree[d_code(dist)].Freq++; \
+ flush = (s->last_lit == s->lit_bufsize-1); \
+ }
+#else
+# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
+# define _tr_tally_dist(s, distance, length, flush) \
+ flush = _tr_tally(s, distance, length)
+#endif
+
+#endif /* DEFLATE_H */
diff --git a/Source/ZLib/example.c b/Source/ZLib/example.c
new file mode 100644
index 0000000..081b6be
--- /dev/null
+++ b/Source/ZLib/example.c
@@ -0,0 +1,565 @@
+/* example.c -- usage example of the zlib compression library
+ * Copyright (C) 1995-2004 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: example.c,v 1.3 2005/08/27 17:22:42 drolon Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#if defined(VMS) || defined(RISCOS)
+# define TESTFILE "foo-gz"
+#else
+# define TESTFILE "foo.gz"
+#endif
+
+#define CHECK_ERR(err, msg) { \
+ if (err != Z_OK) { \
+ fprintf(stderr, "%s error: %d\n", msg, err); \
+ exit(1); \
+ } \
+}
+
+const char hello[] = "hello, hello!";
+/* "hello world" would be more standard, but the repeated "hello"
+ * stresses the compression code better, sorry...
+ */
+
+const char dictionary[] = "hello";
+uLong dictId; /* Adler32 value of the dictionary */
+
+void test_compress OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_gzio OF((const char *fname,
+ Byte *uncompr, uLong uncomprLen));
+void test_deflate OF((Byte *compr, uLong comprLen));
+void test_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_deflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_large_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_flush OF((Byte *compr, uLong *comprLen));
+void test_sync OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+void test_dict_deflate OF((Byte *compr, uLong comprLen));
+void test_dict_inflate OF((Byte *compr, uLong comprLen,
+ Byte *uncompr, uLong uncomprLen));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Test compress() and uncompress()
+ */
+void test_compress(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ err = compress(compr, &comprLen, (const Bytef*)hello, len);
+ CHECK_ERR(err, "compress");
+
+ strcpy((char*)uncompr, "garbage");
+
+ err = uncompress(uncompr, &uncomprLen, compr, comprLen);
+ CHECK_ERR(err, "uncompress");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad uncompress\n");
+ exit(1);
+ } else {
+ printf("uncompress(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test read/write of .gz files
+ */
+void test_gzio(fname, uncompr, uncomprLen)
+ const char *fname; /* compressed file name */
+ Byte *uncompr;
+ uLong uncomprLen;
+{
+#ifdef NO_GZCOMPRESS
+ fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
+#else
+ int err;
+ int len = (int)strlen(hello)+1;
+ gzFile file;
+ z_off_t pos;
+
+ file = gzopen(fname, "wb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ gzputc(file, 'h');
+ if (gzputs(file, "ello") != 4) {
+ fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (gzprintf(file, ", %s!", "hello") != 8) {
+ fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
+ gzclose(file);
+
+ file = gzopen(fname, "rb");
+ if (file == NULL) {
+ fprintf(stderr, "gzopen error\n");
+ exit(1);
+ }
+ strcpy((char*)uncompr, "garbage");
+
+ if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
+ fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
+ exit(1);
+ } else {
+ printf("gzread(): %s\n", (char*)uncompr);
+ }
+
+ pos = gzseek(file, -8L, SEEK_CUR);
+ if (pos != 6 || gztell(file) != pos) {
+ fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
+ (long)pos, (long)gztell(file));
+ exit(1);
+ }
+
+ if (gzgetc(file) != ' ') {
+ fprintf(stderr, "gzgetc error\n");
+ exit(1);
+ }
+
+ if (gzungetc(' ', file) != ' ') {
+ fprintf(stderr, "gzungetc error\n");
+ exit(1);
+ }
+
+ gzgets(file, (char*)uncompr, (int)uncomprLen);
+ if (strlen((char*)uncompr) != 7) { /* " hello!" */
+ fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
+ exit(1);
+ }
+ if (strcmp((char*)uncompr, hello + 6)) {
+ fprintf(stderr, "bad gzgets after gzseek\n");
+ exit(1);
+ } else {
+ printf("gzgets() after gzseek: %s\n", (char*)uncompr);
+ }
+
+ gzclose(file);
+#endif
+}
+
+/* ===========================================================================
+ * Test deflate() with small buffers
+ */
+void test_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uLong len = (uLong)strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+
+ while (c_stream.total_in != len && c_stream.total_out < comprLen) {
+ c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ }
+ /* Finish the stream, still forcing small buffers: */
+ for (;;) {
+ c_stream.avail_out = 1;
+ err = deflate(&c_stream, Z_FINISH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "deflate");
+ }
+
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with small buffers
+ */
+void test_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 0;
+ d_stream.next_out = uncompr;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
+ d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate\n");
+ exit(1);
+ } else {
+ printf("inflate(): %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with large buffers and dynamic change of compression level
+ */
+void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_SPEED);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ /* At this point, uncompr is still mostly zeroes, so it should compress
+ * very well:
+ */
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+ if (c_stream.avail_in != 0) {
+ fprintf(stderr, "deflate not greedy\n");
+ exit(1);
+ }
+
+ /* Feed in already compressed data and switch to no compression: */
+ deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ c_stream.next_in = compr;
+ c_stream.avail_in = (uInt)comprLen/2;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ /* Switch back to compressing mode: */
+ deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ c_stream.next_in = uncompr;
+ c_stream.avail_in = (uInt)uncomprLen;
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with large buffers
+ */
+void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ for (;;) {
+ d_stream.next_out = uncompr; /* discard the output */
+ d_stream.avail_out = (uInt)uncomprLen;
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ CHECK_ERR(err, "large inflate");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
+ fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
+ exit(1);
+ } else {
+ printf("large_inflate(): OK\n");
+ }
+}
+
+/* ===========================================================================
+ * Test deflate() with full flush
+ */
+void test_flush(compr, comprLen)
+ Byte *compr;
+ uLong *comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+ uInt len = (uInt)strlen(hello)+1;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.next_out = compr;
+ c_stream.avail_in = 3;
+ c_stream.avail_out = (uInt)*comprLen;
+ err = deflate(&c_stream, Z_FULL_FLUSH);
+ CHECK_ERR(err, "deflate");
+
+ compr[3]++; /* force an error in first compressed block */
+ c_stream.avail_in = len - 3;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ CHECK_ERR(err, "deflate");
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+
+ *comprLen = c_stream.total_out;
+}
+
+/* ===========================================================================
+ * Test inflateSync()
+ */
+void test_sync(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = 2; /* just read the zlib header */
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ inflate(&d_stream, Z_NO_FLUSH);
+ CHECK_ERR(err, "inflate");
+
+ d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
+ err = inflateSync(&d_stream); /* but skip the damaged part */
+ CHECK_ERR(err, "inflateSync");
+
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_DATA_ERROR) {
+ fprintf(stderr, "inflate should report DATA_ERROR\n");
+ /* Because of incorrect adler32 */
+ exit(1);
+ }
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ printf("after inflateSync(): hel%s\n", (char *)uncompr);
+}
+
+/* ===========================================================================
+ * Test deflate() with preset dictionary
+ */
+void test_dict_deflate(compr, comprLen)
+ Byte *compr;
+ uLong comprLen;
+{
+ z_stream c_stream; /* compression stream */
+ int err;
+
+ c_stream.zalloc = (alloc_func)0;
+ c_stream.zfree = (free_func)0;
+ c_stream.opaque = (voidpf)0;
+
+ err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
+ CHECK_ERR(err, "deflateInit");
+
+ err = deflateSetDictionary(&c_stream,
+ (const Bytef*)dictionary, sizeof(dictionary));
+ CHECK_ERR(err, "deflateSetDictionary");
+
+ dictId = c_stream.adler;
+ c_stream.next_out = compr;
+ c_stream.avail_out = (uInt)comprLen;
+
+ c_stream.next_in = (Bytef*)hello;
+ c_stream.avail_in = (uInt)strlen(hello)+1;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ fprintf(stderr, "deflate should report Z_STREAM_END\n");
+ exit(1);
+ }
+ err = deflateEnd(&c_stream);
+ CHECK_ERR(err, "deflateEnd");
+}
+
+/* ===========================================================================
+ * Test inflate() with a preset dictionary
+ */
+void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
+ Byte *compr, *uncompr;
+ uLong comprLen, uncomprLen;
+{
+ int err;
+ z_stream d_stream; /* decompression stream */
+
+ strcpy((char*)uncompr, "garbage");
+
+ d_stream.zalloc = (alloc_func)0;
+ d_stream.zfree = (free_func)0;
+ d_stream.opaque = (voidpf)0;
+
+ d_stream.next_in = compr;
+ d_stream.avail_in = (uInt)comprLen;
+
+ err = inflateInit(&d_stream);
+ CHECK_ERR(err, "inflateInit");
+
+ d_stream.next_out = uncompr;
+ d_stream.avail_out = (uInt)uncomprLen;
+
+ for (;;) {
+ err = inflate(&d_stream, Z_NO_FLUSH);
+ if (err == Z_STREAM_END) break;
+ if (err == Z_NEED_DICT) {
+ if (d_stream.adler != dictId) {
+ fprintf(stderr, "unexpected dictionary");
+ exit(1);
+ }
+ err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
+ sizeof(dictionary));
+ }
+ CHECK_ERR(err, "inflate with dict");
+ }
+
+ err = inflateEnd(&d_stream);
+ CHECK_ERR(err, "inflateEnd");
+
+ if (strcmp((char*)uncompr, hello)) {
+ fprintf(stderr, "bad inflate with dict\n");
+ exit(1);
+ } else {
+ printf("inflate with dictionary: %s\n", (char *)uncompr);
+ }
+}
+
+/* ===========================================================================
+ * Usage: example [output.gz [input.gz]]
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ Byte *compr, *uncompr;
+ uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
+ uLong uncomprLen = comprLen;
+ static const char* myVersion = ZLIB_VERSION;
+
+ if (zlibVersion()[0] != myVersion[0]) {
+ fprintf(stderr, "incompatible zlib version\n");
+ exit(1);
+
+ } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
+ fprintf(stderr, "warning: different zlib version\n");
+ }
+
+ printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
+ ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
+
+ compr = (Byte*)calloc((uInt)comprLen, 1);
+ uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
+ /* compr and uncompr are cleared to avoid reading uninitialized
+ * data and to ensure that uncompr compresses well.
+ */
+ if (compr == Z_NULL || uncompr == Z_NULL) {
+ printf("out of memory\n");
+ exit(1);
+ }
+ test_compress(compr, comprLen, uncompr, uncomprLen);
+
+ test_gzio((argc > 1 ? argv[1] : TESTFILE),
+ uncompr, uncomprLen);
+
+ test_deflate(compr, comprLen);
+ test_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ test_flush(compr, &comprLen);
+ test_sync(compr, comprLen, uncompr, uncomprLen);
+ comprLen = uncomprLen;
+
+ test_dict_deflate(compr, comprLen);
+ test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
+
+ free(compr);
+ free(uncompr);
+
+ return 0;
+}
diff --git a/Source/ZLib/gzio.c b/Source/ZLib/gzio.c
new file mode 100644
index 0000000..6683b19
--- /dev/null
+++ b/Source/ZLib/gzio.c
@@ -0,0 +1,1026 @@
+/* gzio.c -- IO on .gz files
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
+ */
+
+/* @(#) $Id: gzio.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#include <stdio.h>
+
+#include "zutil.h"
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+#ifndef Z_BUFSIZE
+# ifdef MAXSEG_64K
+# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
+# else
+# define Z_BUFSIZE 16384
+# endif
+#endif
+#ifndef Z_PRINTF_BUFSIZE
+# define Z_PRINTF_BUFSIZE 4096
+#endif
+
+#ifdef __MVS__
+# pragma map (fdopen , "\174\174FDOPEN")
+ FILE *fdopen(int, const char *);
+#endif
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+#define ALLOC(size) malloc(size)
+#define TRYFREE(p) {if (p) free(p);}
+
+static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+/* gzip flag byte */
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+typedef struct gz_stream {
+ z_stream stream;
+ int z_err; /* error code for last stream operation */
+ int z_eof; /* set if end of input file */
+ FILE *file; /* .gz file */
+ Byte *inbuf; /* input buffer */
+ Byte *outbuf; /* output buffer */
+ uLong crc; /* crc32 of uncompressed data */
+ char *msg; /* error message */
+ char *path; /* path name for debugging only */
+ int transparent; /* 1 if input file is not a .gz file */
+ char mode; /* 'w' or 'r' */
+ z_off_t start; /* start of compressed data in file (header skipped) */
+ z_off_t in; /* bytes into deflate or inflate */
+ z_off_t out; /* bytes out of deflate or inflate */
+ int back; /* one character push-back */
+ int last; /* true if push-back is last character */
+} gz_stream;
+
+
+local gzFile gz_open OF((const char *path, const char *mode, int fd));
+local int do_flush OF((gzFile file, int flush));
+local int get_byte OF((gz_stream *s));
+local void check_header OF((gz_stream *s));
+local int destroy OF((gz_stream *s));
+local void putLong OF((FILE *file, uLong x));
+local uLong getLong OF((gz_stream *s));
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb"). The file is given either by file descriptor
+ or path name (if fd == -1).
+ gz_open returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR).
+*/
+local gzFile gz_open (path, mode, fd)
+ const char *path;
+ const char *mode;
+ int fd;
+{
+ int err;
+ int level = Z_DEFAULT_COMPRESSION; /* compression level */
+ int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
+ char *p = (char*)mode;
+ gz_stream *s;
+ char fmode[80]; /* copy of mode, without the compression level */
+ char *m = fmode;
+
+ if (!path || !mode) return Z_NULL;
+
+ s = (gz_stream *)ALLOC(sizeof(gz_stream));
+ if (!s) return Z_NULL;
+
+ s->stream.zalloc = (alloc_func)0;
+ s->stream.zfree = (free_func)0;
+ s->stream.opaque = (voidpf)0;
+ s->stream.next_in = s->inbuf = Z_NULL;
+ s->stream.next_out = s->outbuf = Z_NULL;
+ s->stream.avail_in = s->stream.avail_out = 0;
+ s->file = NULL;
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->in = 0;
+ s->out = 0;
+ s->back = EOF;
+ s->crc = crc32(0L, Z_NULL, 0);
+ s->msg = NULL;
+ s->transparent = 0;
+
+ s->path = (char*)ALLOC(strlen(path)+1);
+ if (s->path == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ strcpy(s->path, path); /* do this early for debugging */
+
+ s->mode = '\0';
+ do {
+ if (*p == 'r') s->mode = 'r';
+ if (*p == 'w' || *p == 'a') s->mode = 'w';
+ if (*p >= '0' && *p <= '9') {
+ level = *p - '0';
+ } else if (*p == 'f') {
+ strategy = Z_FILTERED;
+ } else if (*p == 'h') {
+ strategy = Z_HUFFMAN_ONLY;
+ } else if (*p == 'R') {
+ strategy = Z_RLE;
+ } else {
+ *m++ = *p; /* copy the mode */
+ }
+ } while (*p++ && m != fmode + sizeof(fmode));
+ if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL;
+
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateInit2(&(s->stream), level,
+ Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
+ /* windowBits is passed < 0 to suppress zlib header */
+
+ s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+#endif
+ if (err != Z_OK || s->outbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ } else {
+ s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
+
+ err = inflateInit2(&(s->stream), -MAX_WBITS);
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
+ * present after the compressed stream.
+ */
+ if (err != Z_OK || s->inbuf == Z_NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+
+ errno = 0;
+ s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
+
+ if (s->file == NULL) {
+ return destroy(s), (gzFile)Z_NULL;
+ }
+ if (s->mode == 'w') {
+ /* Write a very simple .gz header:
+ */
+ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
+ Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE);
+ s->start = 10L;
+ /* We use 10L instead of ftell(s->file) to because ftell causes an
+ * fflush on some systems. This version of the library doesn't use
+ * start anyway in write mode, so this initialization is not
+ * necessary.
+ */
+ } else {
+ check_header(s); /* skip the .gz header */
+ s->start = ftell(s->file) - s->stream.avail_in;
+ }
+
+ return (gzFile)s;
+}
+
+/* ===========================================================================
+ Opens a gzip (.gz) file for reading or writing.
+*/
+gzFile ZEXPORT gzopen (path, mode)
+ const char *path;
+ const char *mode;
+{
+ return gz_open (path, mode, -1);
+}
+
+/* ===========================================================================
+ Associate a gzFile with the file descriptor fd. fd is not dup'ed here
+ to mimic the behavio(u)r of fdopen.
+*/
+gzFile ZEXPORT gzdopen (fd, mode)
+ int fd;
+ const char *mode;
+{
+ char name[46]; /* allow for up to 128-bit integers */
+
+ if (fd < 0) return (gzFile)Z_NULL;
+ sprintf(name, "<fd:%d>", fd); /* for debugging */
+
+ return gz_open (name, mode, fd);
+}
+
+/* ===========================================================================
+ * Update the compression level and strategy
+ */
+int ZEXPORT gzsetparams (file, level, strategy)
+ gzFile file;
+ int level;
+ int strategy;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ /* Make room to allow flushing */
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+
+ return deflateParams (&(s->stream), level, strategy);
+}
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+local int get_byte(s)
+ gz_stream *s;
+{
+ if (s->z_eof) return EOF;
+ if (s->stream.avail_in == 0) {
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) s->z_err = Z_ERRNO;
+ return EOF;
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->stream.avail_in--;
+ return *(s->stream.next_in)++;
+}
+
+/* ===========================================================================
+ Check the gzip header of a gz_stream opened for reading. Set the stream
+ mode to transparent if the gzip magic header is not present; set s->err
+ to Z_DATA_ERROR if the magic header is present but the rest of the header
+ is incorrect.
+ IN assertion: the stream s has already been created sucessfully;
+ s->stream.avail_in is zero for the first time, but may be non-zero
+ for concatenated .gz files.
+*/
+local void check_header(s)
+ gz_stream *s;
+{
+ int method; /* method byte */
+ int flags; /* flags byte */
+ uInt len;
+ int c;
+
+ /* Assure two bytes in the buffer so we can peek ahead -- handle case
+ where first byte of header is at the end of the buffer after the last
+ gzip segment */
+ len = s->stream.avail_in;
+ if (len < 2) {
+ if (len) s->inbuf[0] = s->stream.next_in[0];
+ errno = 0;
+ len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
+ if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
+ s->stream.avail_in += len;
+ s->stream.next_in = s->inbuf;
+ if (s->stream.avail_in < 2) {
+ s->transparent = s->stream.avail_in;
+ return;
+ }
+ }
+
+ /* Peek ahead to check the gzip magic header */
+ if (s->stream.next_in[0] != gz_magic[0] ||
+ s->stream.next_in[1] != gz_magic[1]) {
+ s->transparent = 1;
+ return;
+ }
+ s->stream.avail_in -= 2;
+ s->stream.next_in += 2;
+
+ /* Check the rest of the gzip header */
+ method = get_byte(s);
+ flags = get_byte(s);
+ if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
+ s->z_err = Z_DATA_ERROR;
+ return;
+ }
+
+ /* Discard time, xflags and OS code: */
+ for (len = 0; len < 6; len++) (void)get_byte(s);
+
+ if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
+ len = (uInt)get_byte(s);
+ len += ((uInt)get_byte(s))<<8;
+ /* len is garbage if EOF but the loop below will quit anyway */
+ while (len-- != 0 && get_byte(s) != EOF) ;
+ }
+ if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & COMMENT) != 0) { /* skip the .gz file comment */
+ while ((c = get_byte(s)) != 0 && c != EOF) ;
+ }
+ if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
+ for (len = 0; len < 2; len++) (void)get_byte(s);
+ }
+ s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
+}
+
+ /* ===========================================================================
+ * Cleanup then free the given gz_stream. Return a zlib error code.
+ Try freeing in the reverse order of allocations.
+ */
+local int destroy (s)
+ gz_stream *s;
+{
+ int err = Z_OK;
+
+ if (!s) return Z_STREAM_ERROR;
+
+ TRYFREE(s->msg);
+
+ if (s->stream.state != NULL) {
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ err = Z_STREAM_ERROR;
+#else
+ err = deflateEnd(&(s->stream));
+#endif
+ } else if (s->mode == 'r') {
+ err = inflateEnd(&(s->stream));
+ }
+ }
+ if (s->file != NULL && fclose(s->file)) {
+#ifdef ESPIPE
+ if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */
+#endif
+ err = Z_ERRNO;
+ }
+ if (s->z_err < 0) err = s->z_err;
+
+ TRYFREE(s->inbuf);
+ TRYFREE(s->outbuf);
+ TRYFREE(s->path);
+ TRYFREE(s);
+ return err;
+}
+
+/* ===========================================================================
+ Reads the given number of uncompressed bytes from the compressed file.
+ gzread returns the number of bytes actually read (0 for end of file).
+*/
+int ZEXPORT gzread (file, buf, len)
+ gzFile file;
+ voidp buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+ Bytef *start = (Bytef*)buf; /* starting point for crc computation */
+ Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
+
+ if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
+
+ if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
+ if (s->z_err == Z_STREAM_END) return 0; /* EOF */
+
+ next_out = (Byte*)buf;
+ s->stream.next_out = (Bytef*)buf;
+ s->stream.avail_out = len;
+
+ if (s->stream.avail_out && s->back != EOF) {
+ *next_out++ = s->back;
+ s->stream.next_out++;
+ s->stream.avail_out--;
+ s->back = EOF;
+ s->out++;
+ start++;
+ if (s->last) {
+ s->z_err = Z_STREAM_END;
+ return 1;
+ }
+ }
+
+ while (s->stream.avail_out != 0) {
+
+ if (s->transparent) {
+ /* Copy first the lookahead bytes: */
+ uInt n = s->stream.avail_in;
+ if (n > s->stream.avail_out) n = s->stream.avail_out;
+ if (n > 0) {
+ zmemcpy(s->stream.next_out, s->stream.next_in, n);
+ next_out += n;
+ s->stream.next_out = next_out;
+ s->stream.next_in += n;
+ s->stream.avail_out -= n;
+ s->stream.avail_in -= n;
+ }
+ if (s->stream.avail_out > 0) {
+ s->stream.avail_out -=
+ (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
+ }
+ len -= s->stream.avail_out;
+ s->in += len;
+ s->out += len;
+ if (len == 0) s->z_eof = 1;
+ return (int)len;
+ }
+ if (s->stream.avail_in == 0 && !s->z_eof) {
+
+ errno = 0;
+ s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
+ if (s->stream.avail_in == 0) {
+ s->z_eof = 1;
+ if (ferror(s->file)) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ }
+ s->stream.next_in = s->inbuf;
+ }
+ s->in += s->stream.avail_in;
+ s->out += s->stream.avail_out;
+ s->z_err = inflate(&(s->stream), Z_NO_FLUSH);
+ s->in -= s->stream.avail_in;
+ s->out -= s->stream.avail_out;
+
+ if (s->z_err == Z_STREAM_END) {
+ /* Check CRC and original size */
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+ start = s->stream.next_out;
+
+ if (getLong(s) != s->crc) {
+ s->z_err = Z_DATA_ERROR;
+ } else {
+ (void)getLong(s);
+ /* The uncompressed length returned by above getlong() may be
+ * different from s->out in case of concatenated .gz files.
+ * Check for such files:
+ */
+ check_header(s);
+ if (s->z_err == Z_OK) {
+ inflateReset(&(s->stream));
+ s->crc = crc32(0L, Z_NULL, 0);
+ }
+ }
+ }
+ if (s->z_err != Z_OK || s->z_eof) break;
+ }
+ s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start));
+
+ if (len == s->stream.avail_out &&
+ (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
+ return -1;
+ return (int)(len - s->stream.avail_out);
+}
+
+
+/* ===========================================================================
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+int ZEXPORT gzgetc(file)
+ gzFile file;
+{
+ unsigned char c;
+
+ return gzread(file, &c, 1) == 1 ? c : -1;
+}
+
+
+/* ===========================================================================
+ Push one byte back onto the stream.
+*/
+int ZEXPORT gzungetc(c, file)
+ int c;
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF;
+ s->back = c;
+ s->out--;
+ s->last = (s->z_err == Z_STREAM_END);
+ if (s->last) s->z_err = Z_OK;
+ s->z_eof = 0;
+ return c;
+}
+
+
+/* ===========================================================================
+ Reads bytes from the compressed file until len-1 characters are
+ read, or a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. The string is then terminated
+ with a null character.
+ gzgets returns buf, or Z_NULL in case of error.
+
+ The current implementation is not optimized at all.
+*/
+char * ZEXPORT gzgets(file, buf, len)
+ gzFile file;
+ char *buf;
+ int len;
+{
+ char *b = buf;
+ if (buf == Z_NULL || len <= 0) return Z_NULL;
+
+ while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
+ *buf = '\0';
+ return b == buf && len > 0 ? Z_NULL : b;
+}
+
+
+#ifndef NO_GZCOMPRESS
+/* ===========================================================================
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of bytes actually written (0 in case of error).
+*/
+int ZEXPORT gzwrite (file, buf, len)
+ gzFile file;
+ voidpc buf;
+ unsigned len;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.next_in = (Bytef*)buf;
+ s->stream.avail_in = len;
+
+ while (s->stream.avail_in != 0) {
+
+ if (s->stream.avail_out == 0) {
+
+ s->stream.next_out = s->outbuf;
+ if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) {
+ s->z_err = Z_ERRNO;
+ break;
+ }
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ s->in += s->stream.avail_in;
+ s->out += s->stream.avail_out;
+ s->z_err = deflate(&(s->stream), Z_NO_FLUSH);
+ s->in -= s->stream.avail_in;
+ s->out -= s->stream.avail_out;
+ if (s->z_err != Z_OK) break;
+ }
+ s->crc = crc32(s->crc, (const Bytef *)buf, len);
+
+ return (int)(len - s->stream.avail_in);
+}
+
+
+/* ===========================================================================
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error).
+*/
+#ifdef STDC
+#include <stdarg.h>
+
+int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
+{
+ char buf[Z_PRINTF_BUFSIZE];
+ va_list va;
+ int len;
+
+ buf[sizeof(buf) - 1] = 0;
+ va_start(va, format);
+#ifdef NO_vsnprintf
+# ifdef HAS_vsprintf_void
+ (void)vsprintf(buf, format, va);
+ va_end(va);
+ for (len = 0; len < sizeof(buf); len++)
+ if (buf[len] == 0) break;
+# else
+ len = vsprintf(buf, format, va);
+ va_end(va);
+# endif
+#else
+# ifdef HAS_vsnprintf_void
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ va_end(va);
+ len = strlen(buf);
+# else
+ len = vsnprintf(buf, sizeof(buf), format, va);
+ va_end(va);
+# endif
+#endif
+ if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+ return 0;
+ return gzwrite(file, buf, (unsigned)len);
+}
+#else /* not ANSI C */
+
+int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
+ gzFile file;
+ const char *format;
+ int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
+ a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
+{
+ char buf[Z_PRINTF_BUFSIZE];
+ int len;
+
+ buf[sizeof(buf) - 1] = 0;
+#ifdef NO_snprintf
+# ifdef HAS_sprintf_void
+ sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ for (len = 0; len < sizeof(buf); len++)
+ if (buf[len] == 0) break;
+# else
+ len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#else
+# ifdef HAS_snprintf_void
+ snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+ len = strlen(buf);
+# else
+ len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8,
+ a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
+# endif
+#endif
+ if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
+ return 0;
+ return gzwrite(file, buf, len);
+}
+#endif
+
+/* ===========================================================================
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+int ZEXPORT gzputc(file, c)
+ gzFile file;
+ int c;
+{
+ unsigned char cc = (unsigned char) c; /* required for big endian systems */
+
+ return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
+}
+
+
+/* ===========================================================================
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+int ZEXPORT gzputs(file, s)
+ gzFile file;
+ const char *s;
+{
+ return gzwrite(file, (char*)s, (unsigned)strlen(s));
+}
+
+
+/* ===========================================================================
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function.
+*/
+local int do_flush (file, flush)
+ gzFile file;
+ int flush;
+{
+ uInt len;
+ int done = 0;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
+
+ s->stream.avail_in = 0; /* should be zero already anyway */
+
+ for (;;) {
+ len = Z_BUFSIZE - s->stream.avail_out;
+
+ if (len != 0) {
+ if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
+ s->z_err = Z_ERRNO;
+ return Z_ERRNO;
+ }
+ s->stream.next_out = s->outbuf;
+ s->stream.avail_out = Z_BUFSIZE;
+ }
+ if (done) break;
+ s->out += s->stream.avail_out;
+ s->z_err = deflate(&(s->stream), flush);
+ s->out -= s->stream.avail_out;
+
+ /* Ignore the second of two consecutive flushes: */
+ if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK;
+
+ /* deflate has finished flushing only when it hasn't used up
+ * all the available space in the output buffer:
+ */
+ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END);
+
+ if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break;
+ }
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+
+int ZEXPORT gzflush (file, flush)
+ gzFile file;
+ int flush;
+{
+ gz_stream *s = (gz_stream*)file;
+ int err = do_flush (file, flush);
+
+ if (err) return err;
+ fflush(s->file);
+ return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
+}
+#endif /* NO_GZCOMPRESS */
+
+/* ===========================================================================
+ Sets the starting position for the next gzread or gzwrite on the given
+ compressed file. The offset represents a number of bytes in the
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error.
+ SEEK_END is not implemented, returns error.
+ In this version of the library, gzseek can be extremely slow.
+*/
+z_off_t ZEXPORT gzseek (file, offset, whence)
+ gzFile file;
+ z_off_t offset;
+ int whence;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || whence == SEEK_END ||
+ s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) {
+ return -1L;
+ }
+
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ return -1L;
+#else
+ if (whence == SEEK_SET) {
+ offset -= s->in;
+ }
+ if (offset < 0) return -1L;
+
+ /* At this point, offset is the number of zero bytes to write. */
+ if (s->inbuf == Z_NULL) {
+ s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */
+ if (s->inbuf == Z_NULL) return -1L;
+ zmemzero(s->inbuf, Z_BUFSIZE);
+ }
+ while (offset > 0) {
+ uInt size = Z_BUFSIZE;
+ if (offset < Z_BUFSIZE) size = (uInt)offset;
+
+ size = gzwrite(file, s->inbuf, size);
+ if (size == 0) return -1L;
+
+ offset -= size;
+ }
+ return s->in;
+#endif
+ }
+ /* Rest of function is for reading only */
+
+ /* compute absolute position */
+ if (whence == SEEK_CUR) {
+ offset += s->out;
+ }
+ if (offset < 0) return -1L;
+
+ if (s->transparent) {
+ /* map to fseek */
+ s->back = EOF;
+ s->stream.avail_in = 0;
+ s->stream.next_in = s->inbuf;
+ if (fseek(s->file, offset, SEEK_SET) < 0) return -1L;
+
+ s->in = s->out = offset;
+ return offset;
+ }
+
+ /* For a negative seek, rewind and use positive seek */
+ if (offset >= s->out) {
+ offset -= s->out;
+ } else if (gzrewind(file) < 0) {
+ return -1L;
+ }
+ /* offset is now the number of bytes to skip. */
+
+ if (offset != 0 && s->outbuf == Z_NULL) {
+ s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
+ if (s->outbuf == Z_NULL) return -1L;
+ }
+ if (offset && s->back != EOF) {
+ s->back = EOF;
+ s->out++;
+ offset--;
+ if (s->last) s->z_err = Z_STREAM_END;
+ }
+ while (offset > 0) {
+ int size = Z_BUFSIZE;
+ if (offset < Z_BUFSIZE) size = (int)offset;
+
+ size = gzread(file, s->outbuf, (uInt)size);
+ if (size <= 0) return -1L;
+ offset -= size;
+ }
+ return s->out;
+}
+
+/* ===========================================================================
+ Rewinds input file.
+*/
+int ZEXPORT gzrewind (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'r') return -1;
+
+ s->z_err = Z_OK;
+ s->z_eof = 0;
+ s->back = EOF;
+ s->stream.avail_in = 0;
+ s->stream.next_in = s->inbuf;
+ s->crc = crc32(0L, Z_NULL, 0);
+ if (!s->transparent) (void)inflateReset(&s->stream);
+ s->in = 0;
+ s->out = 0;
+ return fseek(s->file, s->start, SEEK_SET);
+}
+
+/* ===========================================================================
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+*/
+z_off_t ZEXPORT gztell (file)
+ gzFile file;
+{
+ return gzseek(file, 0L, SEEK_CUR);
+}
+
+/* ===========================================================================
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+int ZEXPORT gzeof (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ /* With concatenated compressed files that can have embedded
+ * crc trailers, z_eof is no longer the only/best indicator of EOF
+ * on a gz_stream. Handle end-of-stream error explicitly here.
+ */
+ if (s == NULL || s->mode != 'r') return 0;
+ if (s->z_eof) return 1;
+ return s->z_err == Z_STREAM_END;
+}
+
+/* ===========================================================================
+ Returns 1 if reading and doing so transparently, otherwise zero.
+*/
+int ZEXPORT gzdirect (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL || s->mode != 'r') return 0;
+ return s->transparent;
+}
+
+/* ===========================================================================
+ Outputs a long in LSB order to the given file
+*/
+local void putLong (file, x)
+ FILE *file;
+ uLong x;
+{
+ int n;
+ for (n = 0; n < 4; n++) {
+ fputc((int)(x & 0xff), file);
+ x >>= 8;
+ }
+}
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets z_err in case
+ of error.
+*/
+local uLong getLong (s)
+ gz_stream *s;
+{
+ uLong x = (uLong)get_byte(s);
+ int c;
+
+ x += ((uLong)get_byte(s))<<8;
+ x += ((uLong)get_byte(s))<<16;
+ c = get_byte(s);
+ if (c == EOF) s->z_err = Z_DATA_ERROR;
+ x += ((uLong)c)<<24;
+ return x;
+}
+
+/* ===========================================================================
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state.
+*/
+int ZEXPORT gzclose (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) return Z_STREAM_ERROR;
+
+ if (s->mode == 'w') {
+#ifdef NO_GZCOMPRESS
+ return Z_STREAM_ERROR;
+#else
+ if (do_flush (file, Z_FINISH) != Z_OK)
+ return destroy((gz_stream*)file);
+
+ putLong (s->file, s->crc);
+ putLong (s->file, (uLong)(s->in & 0xffffffff));
+#endif
+ }
+ return destroy((gz_stream*)file);
+}
+
+#ifdef STDC
+# define zstrerror(errnum) strerror(errnum)
+#else
+# define zstrerror(errnum) ""
+#endif
+
+/* ===========================================================================
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+const char * ZEXPORT gzerror (file, errnum)
+ gzFile file;
+ int *errnum;
+{
+ char *m;
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) {
+ *errnum = Z_STREAM_ERROR;
+ return (const char*)ERR_MSG(Z_STREAM_ERROR);
+ }
+ *errnum = s->z_err;
+ if (*errnum == Z_OK) return (const char*)"";
+
+ m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg);
+
+ if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err);
+
+ TRYFREE(s->msg);
+ s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3);
+ if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR);
+ strcpy(s->msg, s->path);
+ strcat(s->msg, ": ");
+ strcat(s->msg, m);
+ return (const char*)s->msg;
+}
+
+/* ===========================================================================
+ Clear the error and end-of-file flags, and do the same for the real file.
+*/
+void ZEXPORT gzclearerr (file)
+ gzFile file;
+{
+ gz_stream *s = (gz_stream*)file;
+
+ if (s == NULL) return;
+ if (s->z_err != Z_STREAM_END) s->z_err = Z_OK;
+ s->z_eof = 0;
+ clearerr(s->file);
+}
diff --git a/Source/ZLib/infback.c b/Source/ZLib/infback.c
new file mode 100644
index 0000000..455dbc9
--- /dev/null
+++ b/Source/ZLib/infback.c
@@ -0,0 +1,623 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
+z_streamp strm;
+int windowBits;
+unsigned char FAR *window;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->write = 0;
+ state->whave = 0;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
+z_streamp strm;
+in_func in;
+void FAR *in_desc;
+out_func out;
+void FAR *out_desc;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+
+ /* process literal */
+ if (this.op == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(this.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(this.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly -- write leftover output */
+ ret = Z_STREAM_END;
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left))
+ ret = Z_BUF_ERROR;
+ }
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default: /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Return unused input */
+ inf_leave:
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(strm)
+z_streamp strm;
+{
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/Source/ZLib/inffast.c b/Source/ZLib/inffast.c
new file mode 100644
index 0000000..bbee92e
--- /dev/null
+++ b/Source/ZLib/inffast.c
@@ -0,0 +1,318 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifndef ASMINF
+
+/* Allow machine dependent optimization for post-increment or pre-increment.
+ Based on testing to date,
+ Pre-increment preferred for:
+ - PowerPC G3 (Adler)
+ - MIPS R5000 (Randers-Pehrson)
+ Post-increment preferred for:
+ - none
+ No measurable difference:
+ - Pentium III (Anderson)
+ - M68060 (Nikl)
+ */
+#ifdef POSTINC
+# define OFF 0
+# define PUP(a) *(a)++
+#else
+# define OFF 1
+# define PUP(a) *++(a)
+#endif
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void inflate_fast(strm, start)
+z_streamp strm;
+unsigned start; /* inflate()'s starting value for strm->avail_out */
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *in; /* local strm->next_in */
+ unsigned char FAR *last; /* while in < last, enough input available */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code this; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in - OFF;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out - OFF;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ write = state->write;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = lcode[hold & lmask];
+ dolen:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ PUP(out) = (unsigned char)(this.val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ this = dcode[hold & dmask];
+ dodist:
+ op = (unsigned)(this.bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(this.op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(this.val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(PUP(in)) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ from = window - OFF;
+ if (write == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (write < op) { /* wrap around window */
+ from += wsize + write - op;
+ op -= write;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = window - OFF;
+ if (write < len) { /* some from start of window */
+ op = write;
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += write - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ PUP(out) = PUP(from);
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ }
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ PUP(out) = PUP(from);
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ PUP(out) = PUP(from);
+ if (len > 1)
+ PUP(out) = PUP(from);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ this = dcode[this.val + (hold & ((1U << op) - 1))];
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ this = lcode[this.val + (hold & ((1U << op) - 1))];
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in + OFF;
+ strm->next_out = out + OFF;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and write == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/Source/ZLib/inffast.h b/Source/ZLib/inffast.h
new file mode 100644
index 0000000..1e88d2d
--- /dev/null
+++ b/Source/ZLib/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/Source/ZLib/inffixed.h b/Source/ZLib/inffixed.h
new file mode 100644
index 0000000..75ed4b5
--- /dev/null
+++ b/Source/ZLib/inffixed.h
@@ -0,0 +1,94 @@
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
+
+ /* WARNING: this file should *not* be used by applications. It
+ is part of the implementation of the compression library and
+ is subject to change. Applications should only use zlib.h.
+ */
+
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/Source/ZLib/inflate.c b/Source/ZLib/inflate.c
new file mode 100644
index 0000000..792fdee
--- /dev/null
+++ b/Source/ZLib/inflate.c
@@ -0,0 +1,1368 @@
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common write == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, unsigned out));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf,
+ unsigned len));
+
+int ZEXPORT inflateReset(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ strm->adler = 1; /* to support ill-conceived Java test suite */
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->wsize = 0;
+ state->whave = 0;
+ state->write = 0;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflatePrime(strm, bits, value)
+z_streamp strm;
+int bits;
+int value;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += value << state->bits;
+ state->bits += bits;
+ return Z_OK;
+}
+
+int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size)
+z_streamp strm;
+int windowBits;
+const char *version;
+int stream_size;
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+ }
+ if (strm->zfree == (free_func)0) strm->zfree = zcfree;
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ if (windowBits < 0) {
+ state->wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ state->wrap = (windowBits >> 4) + 1;
+#ifdef GUNZIP
+ if (windowBits < 48) windowBits &= 15;
+#endif
+ }
+ if (windowBits < 8 || windowBits > 15) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ return Z_STREAM_ERROR;
+ }
+ state->wbits = (unsigned)windowBits;
+ state->window = Z_NULL;
+ return inflateReset(strm);
+}
+
+int ZEXPORT inflateInit_(strm, version, stream_size)
+z_streamp strm;
+const char *version;
+int stream_size;
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(state)
+struct inflate_state FAR *state;
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits,
+ state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(strm, out)
+z_streamp strm;
+unsigned out;
+{
+ struct inflate_state FAR *state;
+ unsigned copy, dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->write = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ copy = out - strm->avail_out;
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
+ state->write = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->write;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->write, strm->next_out - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, strm->next_out - copy, copy);
+ state->write = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->write += dist;
+ if (state->write == state->wsize) state->write = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Reverse the bytes in a 32-bit value */
+#define REVERSE(q) \
+ ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(strm, flush)
+z_streamp strm;
+int flush;
+{
+ struct inflate_state FAR *state;
+ unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code this; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
+#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ state->flags = 0; /* expect zlib header */
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if (state->flags & 0x0200) CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if (state->flags & 0x0200) CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = len;
+ } while (len && copy < have);
+ if (state->flags & 0x0200)
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if (hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = REVERSE(hold);
+ INITBITS();
+ state->mode = DICT;
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ case TYPE:
+ if (flush == Z_BLOCK) goto inf_leave;
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY;
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.val < 16) {
+ NEEDBITS(this.bits);
+ DROPBITS(this.bits);
+ state->lens[state->have++] = this.val;
+ }
+ else {
+ if (this.val == 16) {
+ NEEDBITS(this.bits + 2);
+ DROPBITS(this.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (this.val == 17) {
+ NEEDBITS(this.bits + 3);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(this.bits + 7);
+ DROPBITS(this.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* build code tables */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ break;
+ }
+ for (;;) {
+ this = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (this.op && (this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ state->length = (unsigned)this.val;
+ if ((int)(this.op) == 0) {
+ Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", this.val));
+ state->mode = LIT;
+ break;
+ }
+ if (this.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = LENEXT;
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->mode = DIST;
+ case DIST:
+ for (;;) {
+ this = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((this.op & 0xf0) == 0) {
+ last = this;
+ for (;;) {
+ this = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + this.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(this.bits);
+ if (this.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)this.val;
+ state->extra = (unsigned)(this.op) & 15;
+ state->mode = DISTEXT;
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ if (state->offset > state->whave + out - left) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->write) {
+ copy -= state->write;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->write - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if (out)
+ strm->adler = state->check =
+ UPDATE(state->check, put - out, out);
+ out = left;
+ if ((
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ REVERSE(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if (hold != (state->total & 0xffffffffUL)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (state->mode < CHECK && out != strm->avail_out))
+ if (updatewindow(strm, out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if (state->wrap && out)
+ strm->adler = state->check =
+ UPDATE(state->check, strm->next_out - out, out);
+ strm->data_type = state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength)
+z_streamp strm;
+const Bytef *dictionary;
+uInt dictLength;
+{
+ struct inflate_state FAR *state;
+ unsigned long id;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary id */
+ if (state->mode == DICT) {
+ id = adler32(0L, Z_NULL, 0);
+ id = adler32(id, dictionary, dictLength);
+ if (id != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window */
+ if (updatewindow(strm, strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ if (dictLength > state->wsize) {
+ zmemcpy(state->window, dictionary + dictLength - state->wsize,
+ state->wsize);
+ state->whave = state->wsize;
+ }
+ else {
+ zmemcpy(state->window + state->wsize - dictLength, dictionary,
+ dictLength);
+ state->whave = dictLength;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(strm, head)
+z_streamp strm;
+gz_headerp head;
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(have, buf, len)
+unsigned FAR *have;
+unsigned char FAR *buf;
+unsigned len;
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(strm)
+z_streamp strm;
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(strm)
+z_streamp strm;
+{
+ struct inflate_state FAR *state;
+
+ if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+int ZEXPORT inflateCopy(dest, source)
+z_streamp dest;
+z_streamp source;
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL ||
+ source->zalloc == (alloc_func)0 || source->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy(dest, source, sizeof(z_stream));
+ zmemcpy(copy, state, sizeof(struct inflate_state));
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
diff --git a/Source/ZLib/inflate.h b/Source/ZLib/inflate.h
new file mode 100644
index 0000000..07bd3e7
--- /dev/null
+++ b/Source/ZLib/inflate.h
@@ -0,0 +1,115 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2004 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN, /* i: waiting for length/lit code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to the BAD or MEM mode -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME
+ NAME -> COMMENT -> HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ Read deflate blocks:
+ TYPE -> STORED or TABLE or LEN or CHECK
+ STORED -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN
+ Read deflate codes:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* state maintained between inflate() calls. Approximately 7K bytes. */
+struct inflate_state {
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags (0 if zlib) */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned write; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+};
diff --git a/Source/ZLib/inftrees.c b/Source/ZLib/inftrees.c
new file mode 100644
index 0000000..8a9c13f
--- /dev/null
+++ b/Source/ZLib/inftrees.c
@@ -0,0 +1,329 @@
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+
+#define MAXBITS 15
+
+const char inflate_copyright[] =
+ " inflate 1.2.3 Copyright 1995-2005 Mark Adler ";
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int inflate_table(type, lens, codes, table, bits, work)
+codetype type;
+unsigned short FAR *lens;
+unsigned codes;
+code FAR * FAR *table;
+unsigned FAR *bits;
+unsigned short FAR *work;
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code this; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ int end; /* use base and extra for symbol > end */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)1;
+ this.val = (unsigned short)0;
+ *(*table)++ = this; /* make a table to force an error */
+ *(*table)++ = this;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min <= MAXBITS; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked when a LENS table is being made
+ against the space in *table, ENOUGH, minus the maximum space needed by
+ the worst case distance code, MAXD. This should never happen, but the
+ sufficiency of ENOUGH has not been proven exhaustively, hence the check.
+ This assumes that when type == LENS, bits == 9.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ end = 19;
+ break;
+ case LENS:
+ base = lbase;
+ base -= 257;
+ extra = lext;
+ extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ this.bits = (unsigned char)(len - drop);
+ if ((int)(work[sym]) < end) {
+ this.op = (unsigned char)0;
+ this.val = work[sym];
+ }
+ else if ((int)(work[sym]) > end) {
+ this.op = (unsigned char)(extra[work[sym]]);
+ this.val = base[work[sym]];
+ }
+ else {
+ this.op = (unsigned char)(32 + 64); /* end of block */
+ this.val = 0;
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = this;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1U << curr;
+ if (type == LENS && used >= ENOUGH - MAXD)
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
+ }
+
+ /*
+ Fill in rest of table for incomplete codes. This loop is similar to the
+ loop above in incrementing huff for table indices. It is assumed that
+ len is equal to curr + drop, so there is no loop needed to increment
+ through high index bits. When the current sub-table is filled, the loop
+ drops back to the root table to fill in any remaining entries there.
+ */
+ this.op = (unsigned char)64; /* invalid code marker */
+ this.bits = (unsigned char)(len - drop);
+ this.val = (unsigned short)0;
+ while (huff != 0) {
+ /* when done with sub-table, drop back to root table */
+ if (drop != 0 && (huff & mask) != low) {
+ drop = 0;
+ len = root;
+ next = *table;
+ this.bits = (unsigned char)len;
+ }
+
+ /* put invalid code marker in table */
+ next[huff >> drop] = this;
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+ }
+
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
+}
diff --git a/Source/ZLib/inftrees.h b/Source/ZLib/inftrees.h
new file mode 100644
index 0000000..b1104c8
--- /dev/null
+++ b/Source/ZLib/inftrees.h
@@ -0,0 +1,55 @@
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-2005 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of dynamic tree. The maximum found in a long but non-
+ exhaustive search was 1444 code structures (852 for length/literals
+ and 592 for distances, the latter actually the result of an
+ exhaustive search). The true maximum is not known, but the value
+ below is more than safe. */
+#define ENOUGH 2048
+#define MAXD 592
+
+/* Type of code to build for inftable() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+extern int inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
diff --git a/Source/ZLib/minigzip.c b/Source/ZLib/minigzip.c
new file mode 100644
index 0000000..d6f6e52
--- /dev/null
+++ b/Source/ZLib/minigzip.c
@@ -0,0 +1,322 @@
+/* minigzip.c -- simulate gzip using the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * minigzip is a minimal implementation of the gzip utility. This is
+ * only an example of using zlib and isn't meant to replace the
+ * full-featured gzip. No attempt is made to deal with file systems
+ * limiting names to 14 or 8+3 characters, etc... Error checking is
+ * very limited. So use minigzip only for testing; use gzip for the
+ * real thing. On MSDOS, use only on file names without extension
+ * or in pipe mode.
+ */
+
+/* @(#) $Id: minigzip.c,v 1.3 2005/08/27 17:22:42 drolon Exp $ */
+
+#include <stdio.h>
+#include "zlib.h"
+
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+#endif
+
+#ifdef USE_MMAP
+# include <sys/types.h>
+# include <sys/mman.h>
+# include <sys/stat.h>
+#endif
+
+#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
+# include <fcntl.h>
+# include <io.h>
+# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
+#else
+# define SET_BINARY_MODE(file)
+#endif
+
+#ifdef VMS
+# define unlink delete
+# define GZ_SUFFIX "-gz"
+#endif
+#ifdef RISCOS
+# define unlink remove
+# define GZ_SUFFIX "-gz"
+# define fileno(file) file->__file
+#endif
+#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fileno */
+#endif
+
+#ifndef WIN32 /* unlink already in stdio.h for WIN32 */
+ extern int unlink OF((const char *));
+#endif
+
+#ifndef GZ_SUFFIX
+# define GZ_SUFFIX ".gz"
+#endif
+#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
+
+#define BUFLEN 16384
+#define MAX_NAME_LEN 1024
+
+#ifdef MAXSEG_64K
+# define local static
+ /* Needed for systems with limitation on stack size. */
+#else
+# define local
+#endif
+
+char *prog;
+
+void error OF((const char *msg));
+void gz_compress OF((FILE *in, gzFile out));
+#ifdef USE_MMAP
+int gz_compress_mmap OF((FILE *in, gzFile out));
+#endif
+void gz_uncompress OF((gzFile in, FILE *out));
+void file_compress OF((char *file, char *mode));
+void file_uncompress OF((char *file));
+int main OF((int argc, char *argv[]));
+
+/* ===========================================================================
+ * Display error message and exit
+ */
+void error(msg)
+ const char *msg;
+{
+ fprintf(stderr, "%s: %s\n", prog, msg);
+ exit(1);
+}
+
+/* ===========================================================================
+ * Compress input to output then close both files.
+ */
+
+void gz_compress(in, out)
+ FILE *in;
+ gzFile out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+#ifdef USE_MMAP
+ /* Try first compressing with mmap. If mmap fails (minigzip used in a
+ * pipe), use the normal fread loop.
+ */
+ if (gz_compress_mmap(in, out) == Z_OK) return;
+#endif
+ for (;;) {
+ len = (int)fread(buf, 1, sizeof(buf), in);
+ if (ferror(in)) {
+ perror("fread");
+ exit(1);
+ }
+ if (len == 0) break;
+
+ if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err));
+ }
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+}
+
+#ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */
+
+/* Try compressing the input file at once using mmap. Return Z_OK if
+ * if success, Z_ERRNO otherwise.
+ */
+int gz_compress_mmap(in, out)
+ FILE *in;
+ gzFile out;
+{
+ int len;
+ int err;
+ int ifd = fileno(in);
+ caddr_t buf; /* mmap'ed buffer for the entire input file */
+ off_t buf_len; /* length of the input file */
+ struct stat sb;
+
+ /* Determine the size of the file, needed for mmap: */
+ if (fstat(ifd, &sb) < 0) return Z_ERRNO;
+ buf_len = sb.st_size;
+ if (buf_len <= 0) return Z_ERRNO;
+
+ /* Now do the actual mmap: */
+ buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0);
+ if (buf == (caddr_t)(-1)) return Z_ERRNO;
+
+ /* Compress the whole file at once: */
+ len = gzwrite(out, (char *)buf, (unsigned)buf_len);
+
+ if (len != (int)buf_len) error(gzerror(out, &err));
+
+ munmap(buf, buf_len);
+ fclose(in);
+ if (gzclose(out) != Z_OK) error("failed gzclose");
+ return Z_OK;
+}
+#endif /* USE_MMAP */
+
+/* ===========================================================================
+ * Uncompress input to output then close both files.
+ */
+void gz_uncompress(in, out)
+ gzFile in;
+ FILE *out;
+{
+ local char buf[BUFLEN];
+ int len;
+ int err;
+
+ for (;;) {
+ len = gzread(in, buf, sizeof(buf));
+ if (len < 0) error (gzerror(in, &err));
+ if (len == 0) break;
+
+ if ((int)fwrite(buf, 1, (unsigned)len, out) != len) {
+ error("failed fwrite");
+ }
+ }
+ if (fclose(out)) error("failed fclose");
+
+ if (gzclose(in) != Z_OK) error("failed gzclose");
+}
+
+
+/* ===========================================================================
+ * Compress the given file: create a corresponding .gz file and remove the
+ * original.
+ */
+void file_compress(file, mode)
+ char *file;
+ char *mode;
+{
+ local char outfile[MAX_NAME_LEN];
+ FILE *in;
+ gzFile out;
+
+ strcpy(outfile, file);
+ strcat(outfile, GZ_SUFFIX);
+
+ in = fopen(file, "rb");
+ if (in == NULL) {
+ perror(file);
+ exit(1);
+ }
+ out = gzopen(outfile, mode);
+ if (out == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile);
+ exit(1);
+ }
+ gz_compress(in, out);
+
+ unlink(file);
+}
+
+
+/* ===========================================================================
+ * Uncompress the given file and remove the original.
+ */
+void file_uncompress(file)
+ char *file;
+{
+ local char buf[MAX_NAME_LEN];
+ char *infile, *outfile;
+ FILE *out;
+ gzFile in;
+ uInt len = (uInt)strlen(file);
+
+ strcpy(buf, file);
+
+ if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) {
+ infile = file;
+ outfile = buf;
+ outfile[len-3] = '\0';
+ } else {
+ outfile = file;
+ infile = buf;
+ strcat(infile, GZ_SUFFIX);
+ }
+ in = gzopen(infile, "rb");
+ if (in == NULL) {
+ fprintf(stderr, "%s: can't gzopen %s\n", prog, infile);
+ exit(1);
+ }
+ out = fopen(outfile, "wb");
+ if (out == NULL) {
+ perror(file);
+ exit(1);
+ }
+
+ gz_uncompress(in, out);
+
+ unlink(infile);
+}
+
+
+/* ===========================================================================
+ * Usage: minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...]
+ * -d : decompress
+ * -f : compress with Z_FILTERED
+ * -h : compress with Z_HUFFMAN_ONLY
+ * -r : compress with Z_RLE
+ * -1 to -9 : compression level
+ */
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int uncompr = 0;
+ gzFile file;
+ char outmode[20];
+
+ strcpy(outmode, "wb6 ");
+
+ prog = argv[0];
+ argc--, argv++;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "-d") == 0)
+ uncompr = 1;
+ else if (strcmp(*argv, "-f") == 0)
+ outmode[3] = 'f';
+ else if (strcmp(*argv, "-h") == 0)
+ outmode[3] = 'h';
+ else if (strcmp(*argv, "-r") == 0)
+ outmode[3] = 'R';
+ else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' &&
+ (*argv)[2] == 0)
+ outmode[2] = (*argv)[1];
+ else
+ break;
+ argc--, argv++;
+ }
+ if (outmode[3] == ' ')
+ outmode[3] = 0;
+ if (argc == 0) {
+ SET_BINARY_MODE(stdin);
+ SET_BINARY_MODE(stdout);
+ if (uncompr) {
+ file = gzdopen(fileno(stdin), "rb");
+ if (file == NULL) error("can't gzdopen stdin");
+ gz_uncompress(file, stdout);
+ } else {
+ file = gzdopen(fileno(stdout), outmode);
+ if (file == NULL) error("can't gzdopen stdout");
+ gz_compress(stdin, file);
+ }
+ } else {
+ do {
+ if (uncompr) {
+ file_uncompress(*argv);
+ } else {
+ file_compress(*argv, outmode);
+ }
+ } while (argv++, --argc);
+ }
+ return 0;
+}
diff --git a/Source/ZLib/trees.c b/Source/ZLib/trees.c
new file mode 100644
index 0000000..132bd66
--- /dev/null
+++ b/Source/ZLib/trees.c
@@ -0,0 +1,1219 @@
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-2005 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* @(#) $Id: trees.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+/* #define GEN_TREES_H */
+
+#include "deflate.h"
+
+#ifdef DEBUG
+# include <ctype.h>
+#endif
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+local const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+local const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+#define DIST_CODE_LEN 512 /* see definition of array dist_code below */
+
+#if defined(GEN_TREES_H) || !defined(STDC)
+/* non ANSI compilers may not accept trees.h */
+
+local ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see _tr_init
+ * below).
+ */
+
+local ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+uch _dist_code[DIST_CODE_LEN];
+/* Distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+uch _length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+local int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+local int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+#else
+# include "trees.h"
+#endif /* GEN_TREES_H */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULL */
+ const intf *extra_bits; /* extra bits for each code or NULL */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+local static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+local static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+local static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+local void tr_static_init OF((void));
+local void init_block OF((deflate_state *s));
+local void pqdownheap OF((deflate_state *s, ct_data *tree, int k));
+local void gen_bitlen OF((deflate_state *s, tree_desc *desc));
+local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count));
+local void build_tree OF((deflate_state *s, tree_desc *desc));
+local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local void send_tree OF((deflate_state *s, ct_data *tree, int max_code));
+local int build_bl_tree OF((deflate_state *s));
+local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
+ int blcodes));
+local void compress_block OF((deflate_state *s, ct_data *ltree,
+ ct_data *dtree));
+local void set_data_type OF((deflate_state *s));
+local unsigned bi_reverse OF((unsigned value, int length));
+local void bi_windup OF((deflate_state *s));
+local void bi_flush OF((deflate_state *s));
+local void copy_block OF((deflate_state *s, charf *buf, unsigned len,
+ int header));
+
+#ifdef GEN_TREES_H
+local void gen_trees_header OF((void));
+#endif
+
+#ifndef DEBUG
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG
+local void send_bits OF((deflate_state *s, int value, int length));
+
+local void send_bits(s, value, length)
+ deflate_state *s;
+ int value; /* value to send */
+ int length; /* number of bits */
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG */
+
+
+/* the arguments must not have side effects */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables.
+ */
+local void tr_static_init()
+{
+#if defined(GEN_TREES_H) || !defined(STDC)
+ static int static_init_done = 0;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* For some embedded targets, global variables are not initialized: */
+ static_l_desc.static_tree = static_ltree;
+ static_l_desc.extra_bits = extra_lbits;
+ static_d_desc.static_tree = static_dtree;
+ static_d_desc.extra_bits = extra_dbits;
+ static_bl_desc.extra_bits = extra_blbits;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ _length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ _length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ _dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ _dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+
+# ifdef GEN_TREES_H
+ gen_trees_header();
+# endif
+#endif /* defined(GEN_TREES_H) || !defined(STDC) */
+}
+
+/* ===========================================================================
+ * Genererate the file trees.h describing the static trees.
+ */
+#ifdef GEN_TREES_H
+# ifndef DEBUG
+# include <stdio.h>
+# endif
+
+# define SEPARATOR(i, last, width) \
+ ((i) == (last)? "\n};\n\n" : \
+ ((i) % (width) == (width)-1 ? ",\n" : ", "))
+
+void gen_trees_header()
+{
+ FILE *header = fopen("trees.h", "w");
+ int i;
+
+ Assert (header != NULL, "Can't open trees.h");
+ fprintf(header,
+ "/* header created automatically with -DGEN_TREES_H */\n\n");
+
+ fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n");
+ for (i = 0; i < L_CODES+2; i++) {
+ fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code,
+ static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5));
+ }
+
+ fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code,
+ static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
+ }
+
+ fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n");
+ for (i = 0; i < DIST_CODE_LEN; i++) {
+ fprintf(header, "%2u%s", _dist_code[i],
+ SEPARATOR(i, DIST_CODE_LEN-1, 20));
+ }
+
+ fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
+ for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
+ fprintf(header, "%2u%s", _length_code[i],
+ SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
+ }
+
+ fprintf(header, "local const int base_length[LENGTH_CODES] = {\n");
+ for (i = 0; i < LENGTH_CODES; i++) {
+ fprintf(header, "%1u%s", base_length[i],
+ SEPARATOR(i, LENGTH_CODES-1, 20));
+ }
+
+ fprintf(header, "local const int base_dist[D_CODES] = {\n");
+ for (i = 0; i < D_CODES; i++) {
+ fprintf(header, "%5u%s", base_dist[i],
+ SEPARATOR(i, D_CODES-1, 10));
+ }
+
+ fclose(header);
+}
+#endif /* GEN_TREES_H */
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+void _tr_init(s)
+ deflate_state *s;
+{
+ tr_static_init();
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG
+ s->compressed_len = 0L;
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+local void init_block(s)
+ deflate_state *s;
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+local void pqdownheap(s, tree, k)
+ deflate_state *s;
+ ct_data *tree; /* the tree to restore */
+ int k; /* node to move down */
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+local void gen_bitlen(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const intf *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if ((unsigned) tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+local void gen_codes (tree, max_code, bl_count)
+ ct_data *tree; /* the tree to decorate */
+ int max_code; /* largest code with non zero frequency */
+ ushf *bl_count; /* number of codes at each bit length */
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+local void build_tree(s, desc)
+ deflate_state *s;
+ tree_desc *desc; /* the tree descriptor */
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch)((s->depth[n] >= s->depth[m] ?
+ s->depth[n] : s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+local void scan_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+local void send_tree (s, tree, max_code)
+ deflate_state *s;
+ ct_data *tree; /* the tree to be scanned */
+ int max_code; /* and its largest code of non zero frequency */
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+local int build_bl_tree(s)
+ deflate_state *s;
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+local void send_all_trees(s, lcodes, dcodes, blcodes)
+ deflate_state *s;
+ int lcodes, dcodes, blcodes; /* number of codes for each tree */
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+void _tr_stored_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+#ifdef DEBUG
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+#endif
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+void _tr_align(s)
+ deflate_state *s;
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+#endif
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+#ifdef DEBUG
+ s->compressed_len += 10L;
+#endif
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file.
+ */
+void _tr_flush_block(s, buf, stored_len, eof)
+ deflate_state *s;
+ charf *buf; /* input block, or NULL if too old */
+ ulg stored_len; /* length of input block */
+ int eof; /* true if this is the last block for a file */
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is binary or text */
+ if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
+ set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute the block lengths in bytes. */
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ _tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->static_len;
+#endif
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+#ifdef DEBUG
+ s->compressed_len += 3 + s->opt_len;
+#endif
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ /* The above check is made mod 2^32, for files larger than 512 MB
+ * and uLong implemented on 32 bits.
+ */
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+#ifdef DEBUG
+ s->compressed_len += 7; /* align on byte boundary */
+#endif
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+int _tr_tally (s, dist, lc)
+ deflate_state *s;
+ unsigned dist; /* distance of matched string */
+ unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
+
+ s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+#ifdef TRUNCATE_BLOCK
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+#endif
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+local void compress_block(s, ltree, dtree)
+ deflate_state *s;
+ ct_data *ltree; /* literal tree */
+ ct_data *dtree; /* distance tree */
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = _length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
+ "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to BINARY or TEXT, using a crude approximation:
+ * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
+ * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * IN assertion: the fields Freq of dyn_ltree are set.
+ */
+local void set_data_type(s)
+ deflate_state *s;
+{
+ int n;
+
+ for (n = 0; n < 9; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ if (n == 9)
+ for (n = 14; n < 32; n++)
+ if (s->dyn_ltree[n].Freq != 0)
+ break;
+ s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+local unsigned bi_reverse(code, len)
+ unsigned code; /* the value to invert */
+ int len; /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+local void bi_flush(s)
+ deflate_state *s;
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+local void bi_windup(s)
+ deflate_state *s;
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+local void copy_block(s, buf, len, header)
+ deflate_state *s;
+ charf *buf; /* the input data */
+ unsigned len; /* its length */
+ int header; /* true if block header must be written */
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG
+ s->bits_sent += (ulg)len<<3;
+#endif
+ while (len--) {
+ put_byte(s, *buf++);
+ }
+}
diff --git a/Source/ZLib/trees.h b/Source/ZLib/trees.h
new file mode 100644
index 0000000..72facf9
--- /dev/null
+++ b/Source/ZLib/trees.h
@@ -0,0 +1,128 @@
+/* header created automatically with -DGEN_TREES_H */
+
+local const ct_data static_ltree[L_CODES+2] = {
+{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}},
+{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}},
+{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}},
+{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}},
+{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}},
+{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}},
+{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}},
+{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}},
+{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}},
+{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}},
+{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}},
+{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}},
+{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}},
+{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}},
+{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}},
+{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}},
+{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}},
+{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}},
+{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}},
+{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}},
+{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}},
+{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}},
+{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}},
+{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}},
+{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}},
+{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}},
+{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}},
+{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}},
+{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}},
+{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}},
+{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}},
+{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}},
+{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}},
+{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}},
+{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}},
+{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}},
+{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}},
+{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}},
+{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}},
+{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}},
+{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}},
+{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}},
+{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}},
+{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}},
+{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}},
+{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}},
+{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}},
+{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}},
+{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}},
+{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}},
+{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}},
+{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}},
+{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}},
+{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}},
+{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}},
+{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}},
+{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}},
+{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}}
+};
+
+local const ct_data static_dtree[D_CODES] = {
+{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}},
+{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}},
+{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}},
+{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}},
+{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}},
+{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
+};
+
+const uch _dist_code[DIST_CODE_LEN] = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+};
+
+const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+};
+
+local const int base_length[LENGTH_CODES] = {
+0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+64, 80, 96, 112, 128, 160, 192, 224, 0
+};
+
+local const int base_dist[D_CODES] = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+};
+
diff --git a/Source/ZLib/uncompr.c b/Source/ZLib/uncompr.c
new file mode 100644
index 0000000..c72165d
--- /dev/null
+++ b/Source/ZLib/uncompr.c
@@ -0,0 +1,61 @@
+/* uncompr.c -- decompress a memory buffer
+ * Copyright (C) 1995-2003 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: uncompr.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+/* ===========================================================================
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+ Bytef *dest;
+ uLongf *destLen;
+ const Bytef *source;
+ uLong sourceLen;
+{
+ z_stream stream;
+ int err;
+
+ stream.next_in = (Bytef*)source;
+ stream.avail_in = (uInt)sourceLen;
+ /* Check for source > 64K on 16-bit machine: */
+ if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
+
+ stream.next_out = dest;
+ stream.avail_out = (uInt)*destLen;
+ if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+
+ stream.zalloc = (alloc_func)0;
+ stream.zfree = (free_func)0;
+
+ err = inflateInit(&stream);
+ if (err != Z_OK) return err;
+
+ err = inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END) {
+ inflateEnd(&stream);
+ if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
+ return Z_DATA_ERROR;
+ return err;
+ }
+ *destLen = stream.total_out;
+
+ err = inflateEnd(&stream);
+ return err;
+}
diff --git a/Source/ZLib/zconf.h b/Source/ZLib/zconf.h
new file mode 100644
index 0000000..8d44368
--- /dev/null
+++ b/Source/ZLib/zconf.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.h,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/Source/ZLib/zconf.in.h b/Source/ZLib/zconf.in.h
new file mode 100644
index 0000000..ed0c4ce
--- /dev/null
+++ b/Source/ZLib/zconf.in.h
@@ -0,0 +1,332 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zconf.in.h,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ */
+#ifdef Z_PREFIX
+# define deflateInit_ z_deflateInit_
+# define deflate z_deflate
+# define deflateEnd z_deflateEnd
+# define inflateInit_ z_inflateInit_
+# define inflate z_inflate
+# define inflateEnd z_inflateEnd
+# define deflateInit2_ z_deflateInit2_
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateCopy z_deflateCopy
+# define deflateReset z_deflateReset
+# define deflateParams z_deflateParams
+# define deflateBound z_deflateBound
+# define deflatePrime z_deflatePrime
+# define inflateInit2_ z_inflateInit2_
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateCopy z_inflateCopy
+# define inflateReset z_inflateReset
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# define uncompress z_uncompress
+# define adler32 z_adler32
+# define crc32 z_crc32
+# define get_crc_table z_get_crc_table
+# define zError z_zError
+
+# define alloc_func z_alloc_func
+# define free_func z_free_func
+# define in_func z_in_func
+# define out_func z_out_func
+# define Byte z_Byte
+# define uInt z_uInt
+# define uLong z_uLong
+# define Bytef z_Bytef
+# define charf z_charf
+# define intf z_intf
+# define uIntf z_uIntf
+# define uLongf z_uLongf
+# define voidpf z_voidpf
+# define voidp z_voidp
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+# define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+# define MAXSEG_64K
+#endif
+#ifdef MSDOS
+# define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+# ifndef STDC
+# define STDC
+# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
+#endif
+
+#ifndef STDC
+# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+# define const /* note: need a more gentle solution here */
+# endif
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+# define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
+# define SMALL_MEDIUM
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
+# endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
+# ifdef FAR
+# undef FAR
+# endif
+# include <windows.h>
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
+# ifdef WIN32
+# define ZEXPORTVA WINAPIV
+# else
+# define ZEXPORTVA FAR CDECL
+# endif
+# endif
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
+# else
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
+# endif
+# endif
+#endif
+
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+# define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+# define ZEXPORTVA
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char Byte; /* 8 bits */
+#endif
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+ /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+# define Bytef Byte FAR
+#else
+ typedef Byte FAR Bytef;
+#endif
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
+# include <sys/types.h> /* for off_t */
+# include <unistd.h> /* for SEEK_* and off_t */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# define z_off_t off_t
+#endif
+#ifndef SEEK_SET
+# define SEEK_SET 0 /* Seek from beginning of file. */
+# define SEEK_CUR 1 /* Seek from current position. */
+# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
+#endif
+#ifndef z_off_t
+# define z_off_t long
+#endif
+
+#if defined(__OS400__)
+# define NO_vsnprintf
+#endif
+
+#if defined(__MVS__)
+# define NO_vsnprintf
+# ifdef FAR
+# undef FAR
+# endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+# pragma map(deflateInit_,"DEIN")
+# pragma map(deflateInit2_,"DEIN2")
+# pragma map(deflateEnd,"DEEND")
+# pragma map(deflateBound,"DEBND")
+# pragma map(inflateInit_,"ININ")
+# pragma map(inflateInit2_,"ININ2")
+# pragma map(inflateEnd,"INEND")
+# pragma map(inflateSync,"INSY")
+# pragma map(inflateSetDictionary,"INSEDI")
+# pragma map(compressBound,"CMBND")
+# pragma map(inflate_table,"INTABL")
+# pragma map(inflate_fast,"INFA")
+# pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/Source/ZLib/zlib.3 b/Source/ZLib/zlib.3
new file mode 100644
index 0000000..f6b0da1
--- /dev/null
+++ b/Source/ZLib/zlib.3
@@ -0,0 +1,159 @@
+.TH ZLIB 3 "18 July 2005"
+.SH NAME
+zlib \- compression/decompression library
+.SH SYNOPSIS
+[see
+.I zlib.h
+for full description]
+.SH DESCRIPTION
+The
+.I zlib
+library is a general purpose data compression library.
+The code is thread safe.
+It provides in-memory compression and decompression functions,
+including integrity checks of the uncompressed data.
+This version of the library supports only one compression method (deflation)
+but other algorithms will be added later
+and will have the same stream interface.
+.LP
+Compression can be done in a single step if the buffers are large enough
+(for example if an input file is mmap'ed),
+or can be done by repeated calls of the compression function.
+In the latter case,
+the application must provide more input and/or consume the output
+(providing more output space) before each call.
+.LP
+The library also supports reading and writing files in
+.IR gzip (1)
+(.gz) format
+with an interface similar to that of stdio.
+.LP
+The library does not install any signal handler.
+The decoder checks the consistency of the compressed data,
+so the library should never crash even in case of corrupted input.
+.LP
+All functions of the compression library are documented in the file
+.IR zlib.h .
+The distribution source includes examples of use of the library
+in the files
+.I example.c
+and
+.IR minigzip.c .
+.LP
+Changes to this version are documented in the file
+.I ChangeLog
+that accompanies the source,
+and are concerned primarily with bug fixes and portability enhancements.
+.LP
+A Java implementation of
+.I zlib
+is available in the Java Development Kit 1.1:
+.IP
+http://www.javasoft.com/products/JDK/1.1/docs/api/Package-java.util.zip.html
+.LP
+A Perl interface to
+.IR zlib ,
+written by Paul Marquess (pmqs@cpan.org),
+is available at CPAN (Comprehensive Perl Archive Network) sites,
+including:
+.IP
+http://www.cpan.org/modules/by-module/Compress/
+.LP
+A Python interface to
+.IR zlib ,
+written by A.M. Kuchling (amk@magnet.com),
+is available in Python 1.5 and later versions:
+.IP
+http://www.python.org/doc/lib/module-zlib.html
+.LP
+A
+.I zlib
+binding for
+.IR tcl (1),
+written by Andreas Kupries (a.kupries@westend.com),
+is availlable at:
+.IP
+http://www.westend.com/~kupries/doc/trf/man/man.html
+.LP
+An experimental package to read and write files in .zip format,
+written on top of
+.I zlib
+by Gilles Vollant (info@winimage.com),
+is available at:
+.IP
+http://www.winimage.com/zLibDll/unzip.html
+and also in the
+.I contrib/minizip
+directory of the main
+.I zlib
+web site.
+.SH "SEE ALSO"
+The
+.I zlib
+web site can be found at either of these locations:
+.IP
+http://www.zlib.org
+.br
+http://www.gzip.org/zlib/
+.LP
+The data format used by the zlib library is described by RFC
+(Request for Comments) 1950 to 1952 in the files:
+.IP
+http://www.ietf.org/rfc/rfc1950.txt (concerning zlib format)
+.br
+http://www.ietf.org/rfc/rfc1951.txt (concerning deflate format)
+.br
+http://www.ietf.org/rfc/rfc1952.txt (concerning gzip format)
+.LP
+These documents are also available in other formats from:
+.IP
+ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
+.LP
+Mark Nelson (markn@ieee.org) wrote an article about
+.I zlib
+for the Jan. 1997 issue of Dr. Dobb's Journal;
+a copy of the article is available at:
+.IP
+http://dogma.net/markn/articles/zlibtool/zlibtool.htm
+.SH "REPORTING PROBLEMS"
+Before reporting a problem,
+please check the
+.I zlib
+web site to verify that you have the latest version of
+.IR zlib ;
+otherwise,
+obtain the latest version and see if the problem still exists.
+Please read the
+.I zlib
+FAQ at:
+.IP
+http://www.gzip.org/zlib/zlib_faq.html
+.LP
+before asking for help.
+Send questions and/or comments to zlib@gzip.org,
+or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
+.SH AUTHORS
+Version 1.2.3
+Copyright (C) 1995-2005 Jean-loup Gailly (jloup@gzip.org)
+and Mark Adler (madler@alumni.caltech.edu).
+.LP
+This software is provided "as-is,"
+without any express or implied warranty.
+In no event will the authors be held liable for any damages
+arising from the use of this software.
+See the distribution directory with respect to requirements
+governing redistribution.
+The deflate format used by
+.I zlib
+was defined by Phil Katz.
+The deflate and
+.I zlib
+specifications were written by L. Peter Deutsch.
+Thanks to all the people who reported problems and suggested various
+improvements in
+.IR zlib ;
+who are too numerous to cite here.
+.LP
+UNIX manual page by R. P. C. Rodgers,
+U.S. National Library of Medicine (rodgers@nlm.nih.gov).
+.\" end of man page
diff --git a/Source/ZLib/zlib.h b/Source/ZLib/zlib.h
new file mode 100644
index 0000000..0228179
--- /dev/null
+++ b/Source/ZLib/zlib.h
@@ -0,0 +1,1357 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.2.3, July 18th, 2005
+
+ Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.3"
+#define ZLIB_VERNUM 0x1230
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip streams in memory as well.
+
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidpf opaque; /* private data object passed to zalloc and zfree */
+
+ int data_type; /* best guess about the data type: binary or text */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH 2
+#define Z_FULL_FLUSH 3
+#define Z_FINISH 4
+#define Z_BLOCK 5
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY 0
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+ /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumualte before producing output, in order to
+ maximize compression.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ the value returned by deflateBound (see below). If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not
+ fatal, and deflate() can be called again with more input and more output
+ space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+ the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
+ Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate() stop
+ if and when it gets to the next deflate block boundary. When decoding the
+ zlib or gzip format, this will cause inflate() to return immediately after
+ the header and before the first block. When doing a raw inflate, inflate()
+ will go ahead and process the first block, and will return when it gets to
+ the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ Also to assist in this, on return inflate() will set strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64
+ if inflate() is currently decoding the last block in the deflate stream,
+ plus 128 if inflate() returned immediately after decoding an end-of-block
+ code or decoding the complete header up to just before the first byte of the
+ deflate stream. The end-of-block will not be indicated until all of the
+ uncompressed data from that block has been written to strm->next_out. The
+ number of unused bits may in general be greater than seven, except when
+ bit 7 of data_type is set, in which case the number of unused bits will be
+ less than eight.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster approach
+ may be used for the single inflate() call.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the only effect of the flush parameter in this implementation
+ is on the return value of inflate(), as noted below, or when it returns early
+ because Z_BLOCK is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the adler32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the adler32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed adler32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() will decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically. Any information
+ contained in the gzip header is not retained, so applications that need that
+ information should instead use raw inflate, see inflateInit2() below, or
+ inflateBack() and perform their own processing of the gzip header and
+ trailer.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory,
+ Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+ output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may then
+ call inflateSync() to look for a good compression block if a partial recovery
+ of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy));
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute an adler32 check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero),
+ no header crc, and the operating system will be set to 255 (unknown). If a
+ gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
+ Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
+ parameter only affects the compression ratio but not the correctness of the
+ compressed output even if it is not set appropriately. Z_FIXED prevents the
+ use of dynamic Huffman codes, allowing for a simpler decoder for special
+ applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front. In addition, the
+ current implementation of deflate will use at most the window size minus
+ 262 bytes of the provided dictionary.
+
+ Upon return of this function, strm->adler is set to the adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.) If a raw deflate was requested, then the
+ adler32 value is not computed and strm->adler is not set.
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit()
+ or deflateInit2(). This would be used to allocate an output buffer
+ for deflation in a single pass, and so would be called before deflate().
+*/
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the
+ bits leftover from a previous deflate stream when appending to it. As such,
+ this function can only be used for raw deflate, and must be used before the
+ first deflate() call after a deflateInit2() or deflateReset(). bits must be
+ less than or equal to 16, and that many of the least significant bits of
+ value will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+ int windowBits));
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an adler32 or a crc32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
+ a crc32 instead of an adler32.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
+ is set to null if there is no error message. inflateInit2 does not perform
+ any decompression apart from reading the zlib header if present: this will
+ be done by inflate(). (So next_in and avail_in may be modified, but next_out
+ and avail_out are unchanged.)
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the adler32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called
+ immediately after inflateInit2() or inflateReset() and before any call of
+ inflate() to set the dictionary. The application must insure that the
+ dictionary that was used for compression is provided.
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULL dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULL). msg is left unchanged in both source and
+ destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK can be used to
+ force inflate() to return immediately after header processing is complete
+ and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When
+ any of extra, name, or comment are not Z_NULL and the respective field is
+ not present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the paramaters are invalid, Z_MEM_ERROR if the internal state could not
+ be allocated, or Z_VERSION_ERROR if the version of the library does not
+ match the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is more efficient than inflate() for
+ file i/o applications in that it avoids copying between the output and the
+ sliding window by simply making the window itself the output buffer. This
+ function trusts the application to not change the output buffer passed by
+ the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free
+ the allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects
+ only the raw deflate stream to decompress. This is different from the
+ normal behavior of inflate(), which expects either a zlib or gzip header and
+ trailer around the deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero--buf is ignored in that
+ case--and inflateBack() will return a buffer error. inflateBack() will call
+ out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out()
+ should return zero on success, or non-zero on failure. If out() returns
+ non-zero, inflateBack() will return with an error. Neither in() nor out()
+ are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format
+ error in the deflate stream (in which case strm->msg is set to indicate the
+ nature of the error), or Z_STREAM_ERROR if the stream was not properly
+ initialized. In the case of Z_BUF_ERROR, an input or output error can be
+ distinguished using strm->next_in which will be Z_NULL only if in() returned
+ an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to
+ out() returning non-zero. (in() will always be called before out(), so
+ strm->next_in is assured to be defined if out() returns non-zero.) Note
+ that inflateBack() cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+
+ /* utility functions */
+
+/*
+ The following utility functions are implemented on top of the
+ basic stream-oriented functions. To simplify the interface, some
+ default options are assumed (compression level and memory usage,
+ standard memory allocation functions). The source code of these
+ utility functions can easily be modified if you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Compresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be at least the value returned
+ by compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+ This function can be used to compress a whole file at once if the
+ input file is mmap'ed.
+ compress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
+/*
+ Compresses the source buffer into the destination buffer. The level
+ parameter has the same meaning as in deflateInit. sourceLen is the byte
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed buffer.
+
+ compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+ Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before
+ a compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
+/*
+ Decompresses the source buffer into the destination buffer. sourceLen is
+ the byte length of the source buffer. Upon entry, destLen is the total
+ size of the destination buffer, which must be large enough to hold the
+ entire uncompressed data. (The size of the uncompressed data must have
+ been saved previously by the compressor and transmitted to the decompressor
+ by some mechanism outside the scope of this compression library.)
+ Upon exit, destLen is the actual size of the compressed buffer.
+ This function can be used to decompress a whole file at once if the
+ input file is mmap'ed.
+
+ uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if there was not enough room in the output
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
+*/
+
+
+typedef voidp gzFile;
+
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+/*
+ Opens a gzip (.gz) file for reading or writing. The mode parameter
+ is as in fopen ("rb" or "wb") but can also include a compression level
+ ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+ Huffman only compression as in "wb1h", or 'R' for run-length encoding
+ as in "wb1R". (See the description of deflateInit2 for more information
+ about the strategy parameter.)
+
+ gzopen can be used to read a file which is not in gzip format; in this
+ case gzread will directly read from the file without decompression.
+
+ gzopen returns NULL if the file could not be opened or if there was
+ insufficient memory to allocate the (de)compression state; errno
+ can be checked to distinguish the two cases (if errno is zero, the
+ zlib error is Z_MEM_ERROR). */
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ gzdopen() associates a gzFile with the file descriptor fd. File
+ descriptors are obtained from calls like open, dup, creat, pipe or
+ fileno (in the file has been previously opened with fopen).
+ The mode parameter is as in gzopen.
+ The next call of gzclose on the returned gzFile will also close the
+ file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+ descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+ gzdopen returns NULL if there was insufficient memory to allocate
+ the (de)compression state.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+ Dynamically update the compression level or strategy. See the description
+ of deflateInit2 for the meaning of these parameters.
+ gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+ opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+ Reads the given number of uncompressed bytes from the compressed file.
+ If the input file was not in gzip format, gzread copies the given number
+ of bytes into the buffer.
+ gzread returns the number of uncompressed bytes actually read (0 for
+ end of file, -1 for error). */
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+ voidpc buf, unsigned len));
+/*
+ Writes the given number of uncompressed bytes into the compressed file.
+ gzwrite returns the number of uncompressed bytes actually written
+ (0 in case of error).
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...));
+/*
+ Converts, formats, and writes the args to the compressed file under
+ control of the format string, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written (0 in case of error). The number of
+ uncompressed bytes written is limited to 4095. The caller should assure that
+ this limit is not exceeded. If it is exceeded, then gzprintf() will return
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf()
+ because the secure snprintf() or vsnprintf() functions were not available.
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Writes the given null-terminated string to the compressed file, excluding
+ the terminating null character.
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Reads bytes from the compressed file until len-1 characters are read, or
+ a newline character is read and transferred to buf, or an end-of-file
+ condition is encountered. The string is then terminated with a null
+ character.
+ gzgets returns buf, or Z_NULL in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+ Writes c, converted to an unsigned char, into the compressed file.
+ gzputc returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+ Reads one byte from the compressed file. gzgetc returns this byte
+ or -1 in case of end of file or error.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+ Push one character back onto the stream to be read again later.
+ Only one character of push-back is allowed. gzungetc() returns the
+ character pushed, or -1 on failure. gzungetc() will fail if a
+ character has been pushed but not read yet, or if c is -1. The pushed
+ character will be discarded if the stream is repositioned with gzseek()
+ or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+ Flushes all pending output into the compressed file. The parameter
+ flush is as in the deflate() function. The return value is the zlib
+ error number (see function gzerror below). gzflush returns Z_OK if
+ the flush parameter is Z_FINISH and all output could be flushed.
+ gzflush should be called only when strictly necessary because it can
+ degrade compression.
+*/
+
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+/*
+ Sets the starting position for the next gzread or gzwrite on the
+ given compressed file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
+ the value SEEK_END is not supported.
+ If the file is opened for reading, this function is emulated but can be
+ extremely slow. If the file is opened for writing, only forward seeks are
+ supported; gzseek then compresses a sequence of zeroes up to the new
+ starting position.
+
+ gzseek returns the resulting offset location as measured in bytes from
+ the beginning of the uncompressed stream, or -1 in case of error, in
+ particular if the file is opened for writing and the new starting position
+ would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
+/*
+ Rewinds the given file. This function is supported only for reading.
+
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
+/*
+ Returns the starting position for the next gzread or gzwrite on the
+ given compressed file. This position represents a number of bytes in the
+ uncompressed data stream.
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Returns 1 when EOF has previously been detected reading the given
+ input stream, otherwise zero.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Returns 1 if file is being read directly without decompression, otherwise
+ zero.
+*/
+
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
+/*
+ Flushes all pending output if necessary, closes the compressed file
+ and deallocates all the (de)compression state. The return value is the zlib
+ error number (see function gzerror below).
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+ Returns the error message for the last error which occurred on the
+ given compressed file. errnum is set to zlib error number. If an
+ error occurred in the file system and not in the compression library,
+ errnum is set to Z_ERRNO and the application may consult errno
+ to get the exact error code.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clears the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+ /* checksum functions */
+
+/*
+ These functions are not related to compression but are exported
+ anyway because they might be useful in applications using the
+ compression library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+/*
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+/*
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. If buf is NULL, this function returns the required initial
+ value for the for the crc. Pre- and post-conditioning (one's complement) is
+ performed within this function so it shouldn't be done by the application.
+ Usage example:
+
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = crc32(crc, buffer, length);
+ }
+ if (crc != original_crc) error();
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+/*
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, sizeof(z_stream))
+
+
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z));
+ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/Source/ZLib/zutil.c b/Source/ZLib/zutil.c
new file mode 100644
index 0000000..3e7c07d
--- /dev/null
+++ b/Source/ZLib/zutil.c
@@ -0,0 +1,318 @@
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: zutil.c,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#include "zutil.h"
+
+#ifndef NO_DUMMY_DECL
+struct internal_state {int dummy;}; /* for buggy compilers */
+#endif
+
+const char * const z_errmsg[10] = {
+"need dictionary", /* Z_NEED_DICT 2 */
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+"incompatible version",/* Z_VERSION_ERROR (-6) */
+""};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch (sizeof(uInt)) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch (sizeof(uLong)) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch (sizeof(voidpf)) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch (sizeof(z_off_t)) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#ifdef STDC
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef DEBUG
+
+# ifndef verbose
+# define verbose 0
+# endif
+int z_verbose = verbose;
+
+void z_error (m)
+ char *m;
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
+#endif
+
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(err)
+ int err;
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE)
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
+
+#ifndef HAVE_MEMCPY
+
+void zmemcpy(dest, source, len)
+ Bytef* dest;
+ const Bytef* source;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = *source++; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+
+int zmemcmp(s1, s2, len)
+ const Bytef* s1;
+ const Bytef* s2;
+ uInt len;
+{
+ uInt j;
+
+ for (j = 0; j < len; j++) {
+ if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1;
+ }
+ return 0;
+}
+
+void zmemzero(dest, len)
+ Bytef* dest;
+ uInt len;
+{
+ if (len == 0) return;
+ do {
+ *dest++ = 0; /* ??? to be unrolled */
+ } while (--len != 0);
+}
+#endif
+
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
+ * and farmalloc(64K) returns a pointer with an offset of 8, so we
+ * must fix the pointer. Warning: the pointer must be put back to its
+ * original form in order to free it, use zcfree().
+ */
+
+#define MAX_PTR 10
+/* 10*64K = 640K */
+
+local int next_ptr = 0;
+
+typedef struct ptr_table_s {
+ voidpf org_ptr;
+ voidpf new_ptr;
+} ptr_table;
+
+local ptr_table table[MAX_PTR];
+/* This table is used to remember the original form of pointers
+ * to large buffers (64K). Such pointers are normalized with a zero offset.
+ * Since MSDOS is not a preemptive multitasking OS, this table is not
+ * protected from concurrent access. This hack doesn't work anyway on
+ * a protected system like OS/2. Use Microsoft C instead.
+ */
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ voidpf buf = opaque; /* just to make some compilers happy */
+ ulg bsize = (ulg)items*size;
+
+ /* If we allocate less than 65520 bytes, we assume that farmalloc
+ * will return a usable pointer which doesn't have to be normalized.
+ */
+ if (bsize < 65520L) {
+ buf = farmalloc(bsize);
+ if (*(ush*)&buf != 0) return buf;
+ } else {
+ buf = farmalloc(bsize + 16L);
+ }
+ if (buf == NULL || next_ptr >= MAX_PTR) return NULL;
+ table[next_ptr].org_ptr = buf;
+
+ /* Normalize the pointer to seg:0 */
+ *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4;
+ *(ush*)&buf = 0;
+ table[next_ptr++].new_ptr = buf;
+ return buf;
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ int n;
+ if (*(ush*)&ptr != 0) { /* object < 64K */
+ farfree(ptr);
+ return;
+ }
+ /* Find the original pointer */
+ for (n = 0; n < next_ptr; n++) {
+ if (ptr != table[n].new_ptr) continue;
+
+ farfree(table[n].org_ptr);
+ while (++n < next_ptr) {
+ table[n-1] = table[n];
+ }
+ next_ptr--;
+ return;
+ }
+ ptr = opaque; /* just to make some compilers happy */
+ Assert(0, "zcfree: ptr not found");
+}
+
+#endif /* __TURBOC__ */
+
+
+#ifdef M_I86
+/* Microsoft C in 16-bit mode */
+
+# define MY_ZCALLOC
+
+#if (!defined(_MSC_VER) || (_MSC_VER <= 600))
+# define _halloc halloc
+# define _hfree hfree
+#endif
+
+voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ return _halloc((long)items, size);
+}
+
+void zcfree (voidpf opaque, voidpf ptr)
+{
+ if (opaque) opaque = 0; /* to make compiler happy */
+ _hfree(ptr);
+}
+
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
+
+
+#ifndef MY_ZCALLOC /* Any system without a special alloc function */
+
+#ifndef STDC
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
+#endif
+
+voidpf zcalloc (opaque, items, size)
+ voidpf opaque;
+ unsigned items;
+ unsigned size;
+{
+ if (opaque) items += size - size; /* make compiler happy */
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
+}
+
+void zcfree (opaque, ptr)
+ voidpf opaque;
+ voidpf ptr;
+{
+ free(ptr);
+ if (opaque) return; /* make compiler happy */
+}
+
+#endif /* MY_ZCALLOC */
diff --git a/Source/ZLib/zutil.h b/Source/ZLib/zutil.h
new file mode 100644
index 0000000..27267e7
--- /dev/null
+++ b/Source/ZLib/zutil.h
@@ -0,0 +1,269 @@
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: zutil.h,v 1.5 2005/08/27 17:22:42 drolon Exp $ */
+
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#define ZLIB_INTERNAL
+#include "zlib.h"
+
+#ifdef STDC
+# ifndef _WIN32_WCE
+# include <stddef.h>
+# endif
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+# ifdef _WIN32_WCE
+ /* The Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used. We rename it to
+ * avoid conflict with other libraries that use the same workaround.
+ */
+# define errno z_errno
+# endif
+ extern int errno;
+#else
+# ifndef _WIN32_WCE
+# include <errno.h>
+# endif
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+ return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
+# define OS_CODE 0x00
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
+# endif
+#endif
+
+#ifdef AMIGA
+# define OS_CODE 0x01
+#endif
+
+#if defined(VAXC) || defined(VMS)
+# define OS_CODE 0x02
+# define F_OPEN(name, mode) \
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+#endif
+
+#if defined(ATARI) || defined(atarist)
+# define OS_CODE 0x05
+#endif
+
+#ifdef OS2
+# define OS_CODE 0x06
+# ifdef M_I86
+ #include <malloc.h>
+# endif
+#endif
+
+#if defined(MACOS) || defined(TARGET_OS_MAC)
+# define OS_CODE 0x07
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
+# endif
+#endif
+
+#ifdef TOPS20
+# define OS_CODE 0x0a
+#endif
+
+#ifdef WIN32
+# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */
+# define OS_CODE 0x0b
+# endif
+#endif
+
+#ifdef __50SERIES /* Prime/PRIMOS */
+# define OS_CODE 0x0f
+#endif
+
+#if defined(_BEOS_) || defined(RISCOS)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+#endif
+
+#if (defined(_MSC_VER) && (_MSC_VER > 600))
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# ifndef _PTRDIFF_T_DEFINED
+ typedef int ptrdiff_t;
+# define _PTRDIFF_T_DEFINED
+# endif
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
+#endif
+
+ /* common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+# define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+ /* functions */
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+ /* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+#endif
+#ifdef VMS
+# define NO_vsnprintf
+#endif
+
+#if defined(pyr)
+# define NO_MEMCPY
+#endif
+#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
+ /* Use our own functions for small and medium model with MSC <= 5.0.
+ * You may have to use the same strategy for Borland C (untested).
+ * The __SC__ check is for Symantec.
+ */
+# define NO_MEMCPY
+#endif
+#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY)
+# define HAVE_MEMCPY
+#endif
+#ifdef HAVE_MEMCPY
+# ifdef SMALL_MEDIUM /* MSDOS small or medium model */
+# define zmemcpy _fmemcpy
+# define zmemcmp _fmemcmp
+# define zmemzero(dest, len) _fmemset(dest, 0, len)
+# else
+# define zmemcpy memcpy
+# define zmemcmp memcmp
+# define zmemzero(dest, len) memset(dest, 0, len)
+# endif
+#else
+ extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ extern void zmemzero OF((Bytef* dest, uInt len));
+#endif
+
+/* Diagnostic functions */
+#ifdef DEBUG
+# include <stdio.h>
+ extern int z_verbose;
+ extern void z_error OF((char *m));
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) {if (z_verbose>=0) fprintf x ;}
+# define Tracev(x) {if (z_verbose>0) fprintf x ;}
+# define Tracevv(x) {if (z_verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
+void zcfree OF((voidpf opaque, voidpf ptr));
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+#endif /* ZUTIL_H */
diff --git a/TestAPI/GoogleTestSuite.cpp b/TestAPI/GoogleTestSuite.cpp
new file mode 100644
index 0000000..da7fee4
--- /dev/null
+++ b/TestAPI/GoogleTestSuite.cpp
@@ -0,0 +1,194 @@
+// Google test suite
+#include <string>
+using namespace std;
+
+#include <stdio.h>
+#include <windows.h>
+
+#include "FreeImage.h"
+
+/* =====================================================================================================================
+ ======================================================================================================================= */
+void scaleImage(wstring &path)
+{
+ wstring path_in = wstring(L"c:\\temp\\unsorted\\") + path;
+ wstring path_out = wstring(L"c:\\temp\\scaled\\") + path;
+
+ FIBITMAP *inputImage = NULL;
+
+ wstring ext((const wchar_t *) path_in.c_str() + path_in.length() - 4);
+ if((ext == L".jpg") || (ext == L".JPG")) {
+ inputImage = FreeImage_LoadU(FIF_JPEG, path_in.c_str(), 0);
+ }
+ else if((ext == L".png") || (ext == L".PNG")) {
+ inputImage = FreeImage_LoadU(FIF_PNG, path_in.c_str(), 0);
+ }
+ else if((ext == L".gif") || (ext == L".GIF")) {
+ inputImage = FreeImage_LoadU(FIF_GIF, path_in.c_str(), 0);
+ }
+ else {
+ return;
+ }
+
+ if(!inputImage) {
+ return;
+ }
+
+ FIBITMAP *outputImage = FreeImage_Rescale(inputImage, FreeImage_GetWidth(inputImage) / 2, FreeImage_GetHeight(inputImage) / 2, FILTER_BILINEAR);
+ FreeImage_Unload(inputImage);
+
+ if(!outputImage) {
+ return;
+ }
+
+ BOOL ret;
+ if((ext == L".jpg") || (ext == L".JPG")) {
+ ret = FreeImage_SaveU(FIF_JPEG, outputImage, path_out.c_str(), 0);
+ }
+ else if((ext == L".png") || (ext == L".PNG")) {
+ ret = FreeImage_SaveU(FIF_PNG, outputImage, path_out.c_str(), 0);
+ }
+ else if((ext == L".gif") || (ext == L".GIF")) {
+ ret = FreeImage_SaveU(FIF_GIF, outputImage, path_out.c_str(), 0);
+ }
+
+ // we are done
+ FreeImage_Unload(outputImage);
+}
+
+#define THUMBNAIL_SIZE 90 // fit inside a square whose size is 90 pixels
+
+/* =====================================================================================================================
+ ======================================================================================================================= */
+void makeThumbnail(wstring &path)
+{
+ wstring path_in = wstring(L"c:\\temp\\unsorted\\") + path;
+ wstring path_out = wstring(L"c:\\temp\\thumbs\\") + path + wstring(L".jpg");
+
+
+ FIBITMAP *dib = NULL;
+ int flags = 0; // default load flag
+ int originalWidth = 0; // original image width
+ int originalHeight = 0; // original image height
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeU(path_in.c_str());
+ if(fif == FIF_UNKNOWN) {
+ return ;
+ }
+
+ if(fif == FIF_JPEG) {
+ FITAG *tag = NULL;
+
+ // for JPEG images, we can speedup the loading part using LibJPEG downsampling feature while loading the
+ // image...
+ flags |= THUMBNAIL_SIZE << 16;
+
+ // load the dib
+ dib = FreeImage_LoadU(fif, path_in.c_str(), flags);
+ if(!dib) {
+ return ;
+ }
+
+ // the dib may have been downscaled by 2x, 4x or 8x retrieve the original width & height (stored as comments
+ // for this special case)
+ if(FreeImage_GetMetadata(FIMD_COMMENTS, dib, "OriginalJPEGWidth", &tag)) {
+ originalWidth = atoi((char *) FreeImage_GetTagValue(tag));
+ }
+ else {
+ originalWidth = FreeImage_GetWidth(dib);
+ }
+
+ if(FreeImage_GetMetadata(FIMD_COMMENTS, dib, "OriginalJPEGHeight", &tag)) {
+ originalHeight = atoi((char *) FreeImage_GetTagValue(tag));
+ }
+ else {
+ originalHeight = FreeImage_GetHeight(dib);
+ }
+ }
+ else {
+
+ // any cases other than the JPEG case: load the dib
+ dib = FreeImage_LoadU(fif, path_in.c_str(), flags);
+ if(!dib) {
+ return ;
+ }
+
+ originalWidth = FreeImage_GetWidth(dib);
+ originalHeight = FreeImage_GetHeight(dib);
+ }
+
+ // store ‘originalWidth’ and ‘originalHeight’ for later use … store any other metadata (such as Exif) for later
+ // use … ... create the requested thumbnail
+ FIBITMAP *thumbnail = FreeImage_MakeThumbnail(dib, THUMBNAIL_SIZE, TRUE);
+ FreeImage_Unload(dib);
+
+ // Save thumbnail
+ if(thumbnail) {
+ FreeImage_SaveU(FIF_JPEG, thumbnail, path_out.c_str(), 0);
+ FreeImage_Unload(thumbnail);
+ }
+
+}
+
+/* =====================================================================================================================
+ ======================================================================================================================= */
+int main(int argc, char *argv[])
+{
+ unsigned width = 512;
+ unsigned height = 512;
+
+#if defined(_DEBUG) && defined(WIN32)
+ // check for memory leaks at program exit (after the 'return 0') through a call to _CrtDumpMemoryLeaks note that
+ // in debug mode, objects allocated with the new operator may be destroyed *after* the end of the main function.
+ _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
+#endif
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_Initialise();
+#endif
+
+ WIN32_FIND_DATAW fileData;
+ HANDLE hList = FindFirstFileW(L"c:\\temp\\unsorted\\*", &fileData);
+
+ if(hList == INVALID_HANDLE_VALUE) {
+
+ // empty dir: nothing to do
+ return 0;
+ }
+
+ while(1) {
+
+ // Make sure that files and directories are 'non-special'
+ if(fileData.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE)) {
+
+ // TpnTrace::Trace(TRACE_INFO, "Skipping file(%S) because of attributes (0x%X)", fileData.cFileName, fileData.dwFileAttributes);
+ }
+ else {
+ wstring fileName(fileData.cFileName, wcslen(fileData.cFileName));
+
+ if((fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || (fileName == wstring(L".")) || (fileName == wstring(L".."))) {
+
+ // folder, nothing to do
+ }
+ else {
+
+ // process files
+ //scaleImage(fileName);
+ makeThumbnail(fileName);
+ }
+ }
+
+ if(!FindNextFileW(hList, &fileData)) {
+ if(GetLastError() == ERROR_NO_MORE_FILES) {
+ break;
+ }
+
+ break; // throw !!!
+ }
+ }
+
+ FindClose(hList);
+
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_DeInitialise();
+#endif
+ return 0;
+}
diff --git a/TestAPI/MainTestSuite.cpp b/TestAPI/MainTestSuite.cpp
new file mode 100644
index 0000000..e0dc4d5
--- /dev/null
+++ b/TestAPI/MainTestSuite.cpp
@@ -0,0 +1,100 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ printf("\n*** ");
+ if(fif != FIF_UNKNOWN) {
+ printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
+ }
+ printf(message);
+ printf(" ***\n");
+}
+
+// ----------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+ unsigned width = 512;
+ unsigned height = 512;
+
+#if defined(_DEBUG) && defined(WIN32)
+ // check for memory leaks at program exit (after the 'return 0')
+ // through a call to _CrtDumpMemoryLeaks
+ // note that in debug mode, objects allocated with the new operator
+ // may be destroyed *after* the end of the main function.
+ _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
+#endif
+
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_Initialise();
+#endif
+
+ // initialize our own FreeImage error handler
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // test plugins capabilities
+ showPlugins();
+
+ // test the clone function
+ testMakeThumbnail("image013.png");
+
+ // test the clone function
+ testAllocateCloneUnload("exif.jpg");
+
+ // test internal image types
+ testImageType(width, height);
+
+ // test loading / saving / converting image types using the TIFF plugin
+ testImageTypeTIFF(width, height);
+
+ // test multipage creation
+ testBuildMPage("sample.png", "sample.ico", FIF_ICO, 24);
+ testBuildMPage("sample.png", "sample.tif", FIF_TIFF, 24);
+ //testBuildMPage("sample.png", "sample.gif", FIF_GIF, 8);
+
+ // test multipage cache
+ testMPageCache("sample.png");
+
+ // test memory IO
+ testMemIO("sample.png");
+
+ // test JPEG lossless transform & cropping
+ testJPEG();
+
+ // test get/set channel
+ testImageChannels(width, height);
+
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_DeInitialise();
+#endif
+
+ return 0;
+}
+
diff --git a/TestAPI/Makefile b/TestAPI/Makefile
new file mode 100644
index 0000000..f204849
--- /dev/null
+++ b/TestAPI/Makefile
@@ -0,0 +1,8 @@
+
+default: all
+
+all:
+ g++ -I../Dist/ *.cpp ../Dist/libfreeimage.a -o testAPI
+
+clean:
+ rm -f *.o testAPI *.png *.tif
diff --git a/TestAPI/Test.2003.sln b/TestAPI/Test.2003.sln
new file mode 100644
index 0000000..10cde0f
--- /dev/null
+++ b/TestAPI/Test.2003.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.2003.vcproj", "{47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug.ActiveCfg = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug.Build.0 = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release.ActiveCfg = Release|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/TestAPI/Test.2003.vcproj b/TestAPI/Test.2003.vcproj
new file mode 100644
index 0000000..94a6291
--- /dev/null
+++ b/TestAPI/Test.2003.vcproj
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="Test"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;FREEIMAGE_LIB"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/Test.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib FreeImage.lib"
+ OutputFile=".\Release/Test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/Test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/Test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;FREEIMAGE_LIB"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/Test.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib FreeImaged.lib"
+ OutputFile=".\Debug/Test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/Test.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/Test.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\source\FreeImage.h">
+ </File>
+ <File
+ RelativePath="MainTestSuite.cpp">
+ </File>
+ <File
+ RelativePath="testImageType.cpp">
+ </File>
+ <File
+ RelativePath="testJPEG.cpp">
+ </File>
+ <File
+ RelativePath="testMemIO.cpp">
+ </File>
+ <File
+ RelativePath="testMPage.cpp">
+ </File>
+ <File
+ RelativePath="testPlugins.cpp">
+ </File>
+ <File
+ RelativePath="TestSuite.h">
+ </File>
+ <File
+ RelativePath="testTools.cpp">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/TestAPI/Test.2005.sln b/TestAPI/Test.2005.sln
new file mode 100644
index 0000000..4ecd2f8
--- /dev/null
+++ b/TestAPI/Test.2005.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.2005.vcproj", "{47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug|Win32.ActiveCfg = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug|Win32.Build.0 = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release|Win32.ActiveCfg = Release|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TestAPI/Test.2005.vcproj b/TestAPI/Test.2005.vcproj
new file mode 100644
index 0000000..56dea54
--- /dev/null
+++ b/TestAPI/Test.2005.vcproj
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="Test"
+ ProjectGUID="{47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}"
+ RootNamespace="Test"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/Test.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/Test.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib FreeImage.lib"
+ OutputFile=".\Release/Test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Release/Test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/Test.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/Test.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="odbc32.lib odbccp32.lib FreeImaged.lib"
+ OutputFile=".\Debug/Test.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/Test.pdb"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\source\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="MainTestSuite.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testChannels.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testImageType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testMemIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testMPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testPlugins.cpp"
+ >
+ </File>
+ <File
+ RelativePath="TestSuite.h"
+ >
+ </File>
+ <File
+ RelativePath="testTools.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/TestAPI/Test.2008.sln b/TestAPI/Test.2008.sln
new file mode 100644
index 0000000..8cb68dd
--- /dev/null
+++ b/TestAPI/Test.2008.sln
@@ -0,0 +1,70 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test", "Test.2008.vcproj", "{47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ {9E219DF2-315D-478E-8A07-8960C377CE1E} = {9E219DF2-315D-478E-8A07-8960C377CE1E}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImageLib", "..\SOURCE\FreeImageLib\FreeImageLib.2008.vcproj", "{9E219DF2-315D-478E-8A07-8960C377CE1E}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098} = {E3536C28-A7F1-4B53-8E52-7D2232F9E098}
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC} = {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC} = {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB} = {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9} = {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}
+ EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibJPEG", "..\source\LibJPEG\LibJPEG.2008.vcproj", "{5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibMNG", "..\source\LibMNG\LibMNG.2008.vcproj", "{912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibPNG", "..\source\LibPNG\LibPNG.2008.vcproj", "{7DB10B50-CE00-4D7A-B322-6824F05D2FCB}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibTIFF", "..\source\LibTIFF\LibTIFF.2008.vcproj", "{431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LibOpenJPEG", "..\source\LibOpenJPEG\LibOpenJPEG.2008.vcproj", "{E3536C28-A7F1-4B53-8E52-7D2232F9E098}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug|Win32.ActiveCfg = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Debug|Win32.Build.0 = Debug|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release|Win32.ActiveCfg = Release|Win32
+ {47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}.Release|Win32.Build.0 = Release|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Debug|Win32.ActiveCfg = Debug|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Debug|Win32.Build.0 = Debug|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Release|Win32.ActiveCfg = Release|Win32
+ {9E219DF2-315D-478E-8A07-8960C377CE1E}.Release|Win32.Build.0 = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Debug|Win32.Build.0 = Debug|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.ActiveCfg = Release|Win32
+ {5E1D4E5F-E10C-4BA3-B663-F33014FD21D9}.Release|Win32.Build.0 = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Debug|Win32.Build.0 = Debug|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.ActiveCfg = Release|Win32
+ {912A2D43-35A3-4AF2-B2EB-0D81EFFDA6DC}.Release|Win32.Build.0 = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.ActiveCfg = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Debug|Win32.Build.0 = Debug|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.ActiveCfg = Release|Win32
+ {7DB10B50-CE00-4D7A-B322-6824F05D2FCB}.Release|Win32.Build.0 = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.ActiveCfg = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Debug|Win32.Build.0 = Debug|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.ActiveCfg = Release|Win32
+ {431E3F3F-7C4D-430A-B8F1-4F165DB64EDC}.Release|Win32.Build.0 = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Debug|Win32.Build.0 = Debug|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.ActiveCfg = Release|Win32
+ {E3536C28-A7F1-4B53-8E52-7D2232F9E098}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TestAPI/Test.2008.vcproj b/TestAPI/Test.2008.vcproj
new file mode 100644
index 0000000..79b5606
--- /dev/null
+++ b/TestAPI/Test.2008.vcproj
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="Test"
+ ProjectGUID="{47EC92F9-8B13-4A52-B80E-9EEC1BFFED99}"
+ RootNamespace="Test"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/Test.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ InlineFunctionExpansion="1"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+
+
+
+
+ PrecompiledHeaderFile=""
+
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+
+ AdditionalLibraryDirectories="&quot;$(ProjectDir)\..\..\zlib-1.2.3\projects\vs2008\Win32_LIB_ASM_Release&quot;"
+ IgnoreDefaultLibraryNames=""
+
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+
+
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/Test.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ AdditionalIncludeDirectories="../Dist"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;FREEIMAGE_LIB;_CRT_SECURE_NO_DEPRECATE"
+
+
+
+
+ PrecompiledHeaderFile=""
+ BrowseInformation="1"
+
+
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="zlib.lib"
+
+ AdditionalLibraryDirectories="&quot;$(ProjectDir)\..\..\zlib-1.2.3\projects\vs2008\Win32_LIB_ASM_DEBUG&quot;"
+ IgnoreDefaultLibraryNames=""
+
+ SubSystem="1"
+
+
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="..\source\FreeImage.h"
+ >
+ </File>
+ <File
+ RelativePath="MainTestSuite.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testImageType.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testJPEG.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testMemIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testMPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="testPlugins.cpp"
+ >
+ </File>
+ <File
+ RelativePath="TestSuite.h"
+ >
+ </File>
+ <File
+ RelativePath="testTools.cpp"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/TestAPI/TestSuite.h b/TestAPI/TestSuite.h
new file mode 100644
index 0000000..c4b9572
--- /dev/null
+++ b/TestAPI/TestSuite.h
@@ -0,0 +1,81 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef TEST_FREEIMAGE_API_H
+#define TEST_FREEIMAGE_API_H
+
+#include "FreeImage.h"
+
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+#if (defined(WIN32) || defined(__WIN32__))
+#if (defined(_DEBUG))
+#include <crtdbg.h>
+#endif
+#endif // WIN32
+
+
+// Some useful tools
+// ==========================================================
+FIBITMAP* createZonePlateImage(unsigned width, unsigned height, int scale);
+
+// Test plugins capabilities
+// ==========================================================
+void showPlugins();
+
+// Image types test suite
+// ==========================================================
+void testAllocateCloneUnload(const char *lpszPathName);
+BOOL testAllocateCloneUnloadType(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height);
+void testImageType(unsigned width, unsigned height);
+void testImageTypeTIFF(unsigned width, unsigned height);
+
+// IO test suite
+// ==========================================================
+
+void testMemIO(const char *lpszPathName);
+
+void testMakeThumbnail(const char *src_file);
+
+// Multipage test suite
+// ==========================================================
+
+void testBuildMPage(char *src_filename, char *dst_filename, FREE_IMAGE_FORMAT dst_fif, unsigned bpp);
+void testMPageCache(char *src_filename);
+
+// JPEG test suite
+// ==========================================================
+
+void testJPEG();
+
+// Channels test suite
+// ==========================================================
+
+void testImageChannels(unsigned width, unsigned height);
+
+
+#endif // TEST_FREEIMAGE_API_H
+
+
diff --git a/TestAPI/exif.jpg b/TestAPI/exif.jpg
new file mode 100644
index 0000000..c9e425d
--- /dev/null
+++ b/TestAPI/exif.jpg
Binary files differ
diff --git a/TestAPI/sample.png b/TestAPI/sample.png
new file mode 100644
index 0000000..f6dec9b
--- /dev/null
+++ b/TestAPI/sample.png
Binary files differ
diff --git a/TestAPI/testChannels.cpp b/TestAPI/testChannels.cpp
new file mode 100644
index 0000000..40c7bc4
--- /dev/null
+++ b/TestAPI/testChannels.cpp
@@ -0,0 +1,131 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// Local test functions
+// ----------------------------------------------------------
+
+void test24BitsChannels(unsigned width, unsigned height) {
+ BOOL bResult = FALSE;
+
+ // create a test 8-bit image
+ FIBITMAP *src = createZonePlateImage(width, height, 128);
+ if(src != NULL) {
+ // convert to 24-bit
+ FIBITMAP *tmp = FreeImage_ConvertTo24Bits(src);
+ FreeImage_Unload(src);
+ src = tmp;
+ }
+ assert(src != NULL);
+
+ // save for further examination
+ bResult = FreeImage_Save(FIF_PNG, src, "zoneplate.png", PNG_DEFAULT);
+ assert(bResult);
+
+ // test get/set channel
+ // -------------------------
+ FIBITMAP *channel = FreeImage_GetChannel(src, FICC_GREEN);
+ assert(channel != NULL);
+ bResult = FreeImage_SetChannel(src, channel, FICC_GREEN);
+ assert(bResult);
+ FreeImage_Unload(channel);
+
+ FreeImage_Unload(src);
+}
+
+void test32BitsChannels(unsigned width, unsigned height) {
+ BOOL bResult = FALSE;
+
+ // create a test 8-bit image
+ FIBITMAP *src = createZonePlateImage(width, height, 128);
+ if(src != NULL) {
+ // convert to 32-bit
+ FIBITMAP *tmp = FreeImage_ConvertTo32Bits(src);
+ FreeImage_Unload(src);
+ src = tmp;
+ }
+ assert(src != NULL);
+
+ // save for further examination
+ bResult = FreeImage_Save(FIF_PNG, src, "zoneplate.png", PNG_DEFAULT);
+ assert(bResult);
+
+ // test get/set channel
+ // -------------------------
+ FIBITMAP *channel = FreeImage_GetChannel(src, FICC_ALPHA);
+ assert(channel != NULL);
+ bResult = FreeImage_SetChannel(src, channel, FICC_ALPHA);
+ assert(bResult);
+ FreeImage_Unload(channel);
+
+ FreeImage_Unload(src);
+}
+
+void testRGBAChannels(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height, BOOL bUseAlpha) {
+ BOOL bResult = FALSE;
+
+ // create a test image
+ FIBITMAP *src = FreeImage_AllocateT(image_type, width, height);
+ assert(src != NULL);
+
+ // test get/set channel
+ // -------------------------
+ {
+ FIBITMAP *channel = FreeImage_GetChannel(src, FICC_GREEN);
+ assert(channel != NULL);
+ bResult = FreeImage_SetChannel(src, channel, FICC_GREEN);
+ assert(bResult);
+ FreeImage_Unload(channel);
+ }
+
+ if(bUseAlpha) {
+ FIBITMAP *alpha = FreeImage_GetChannel(src, FICC_ALPHA);
+ assert(alpha != NULL);
+ bResult = FreeImage_SetChannel(src, alpha, FICC_ALPHA);
+ assert(bResult);
+ FreeImage_Unload(alpha);
+ }
+
+ FreeImage_Unload(src);
+}
+
+// Main test functions
+// ----------------------------------------------------------
+
+void testImageChannels(unsigned width, unsigned height) {
+
+ BOOL bResult = FALSE;
+
+ printf("testImageChannels ...");
+
+ test24BitsChannels(width, height);
+ test32BitsChannels(width, height);
+
+ testRGBAChannels(FIT_RGB16, width, height, FALSE);
+ testRGBAChannels(FIT_RGBA16, width, height, TRUE);
+
+ testRGBAChannels(FIT_RGBF, width, height, FALSE);
+ testRGBAChannels(FIT_RGBAF, width, height, TRUE);
+
+ printf("\tOK\n");
+}
diff --git a/TestAPI/testImageType.cpp b/TestAPI/testImageType.cpp
new file mode 100644
index 0000000..8933a88
--- /dev/null
+++ b/TestAPI/testImageType.cpp
@@ -0,0 +1,506 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// Local test functions
+// ----------------------------------------------------------
+
+BOOL testClone(const char *lpszPathName) {
+ FIBITMAP *dib1 = NULL, *dib2 = NULL;
+
+ try {
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(lpszPathName);
+
+ dib1 = FreeImage_Load(fif, lpszPathName, 0);
+ if(!dib1) throw(1);
+
+ dib2 = FreeImage_Clone(dib1);
+ if(!dib2) throw(1);
+
+ FreeImage_Unload(dib1);
+ FreeImage_Unload(dib2);
+
+ return TRUE;
+ }
+ catch(int) {
+ if(dib1) FreeImage_Unload(dib1);
+ if(dib2) FreeImage_Unload(dib2);
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+void testAllocateCloneUnload(const char *lpszPathName) {
+ printf("testAllocateCloneUnload ...");
+
+ BOOL bResult = testClone(lpszPathName);
+ assert(bResult);
+
+ printf("\tOK\n");
+}
+
+BOOL testAllocateCloneUnloadType(FREE_IMAGE_TYPE image_type, unsigned width, unsigned height) {
+ FIBITMAP *image = NULL;
+ FIBITMAP *clone = NULL;
+ FIBITMAP *standard = NULL;
+
+ unsigned x, y;
+
+ try {
+ // test allocation function
+ image = FreeImage_AllocateT(image_type, width, height, 8);
+ if(!image) throw(1);
+
+ FREE_IMAGE_TYPE type = FreeImage_GetImageType(image);
+ if(image_type != type) throw(1);
+
+ // test pixel access
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(FreeImage_GetBPP(image) == 8) {
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ BYTE *bits = (BYTE *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ }
+ break;
+ case FIT_UINT16:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ unsigned short *bits = (unsigned short *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_INT16:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ short *bits = (short *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_UINT32:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ unsigned long *bits = (unsigned long *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_INT32:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ long *bits = (long *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_FLOAT:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ float *bits = (float *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_DOUBLE:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ double *bits = (double *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x] = 128;
+ }
+ }
+ break;
+ case FIT_COMPLEX:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ FICOMPLEX *bits = (FICOMPLEX *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x].r = 128;
+ bits[x].i = 128;
+ }
+ }
+ break;
+ case FIT_RGB16:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ FIRGB16 *bits = (FIRGB16 *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x].red = 128;
+ bits[x].green = 128;
+ bits[x].blue = 128;
+ }
+ }
+ break;
+ case FIT_RGBF:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ FIRGBF *bits = (FIRGBF *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x].red = 128;
+ bits[x].green = 128;
+ bits[x].blue = 128;
+ }
+ }
+ break;
+ case FIT_RGBA16:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ FIRGBA16 *bits = (FIRGBA16 *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x].red = 128;
+ bits[x].green = 128;
+ bits[x].blue = 128;
+ bits[x].alpha = 128;
+ }
+ }
+ break;
+ case FIT_RGBAF:
+ for(y = 0; y < FreeImage_GetHeight(image); y++) {
+ FIRGBAF *bits = (FIRGBAF *)FreeImage_GetScanLine(image, y);
+ for(x = 0; x < FreeImage_GetWidth(image); x++) {
+ bits[x].red = 128;
+ bits[x].green = 128;
+ bits[x].blue = 128;
+ bits[x].alpha = 128;
+ }
+ }
+ break;
+ }
+
+
+ // test clone function
+ clone = FreeImage_Clone(image);
+ if(!clone) throw(1);
+
+ if(FreeImage_GetImageType(clone) != image_type) throw(1);
+
+ switch(image_type) {
+ case FIT_BITMAP:
+ if(FreeImage_GetBPP(clone) == 8) {
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ BYTE *bits = (BYTE *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ }
+ break;
+ case FIT_UINT16:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ unsigned short *bits = (unsigned short *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_INT16:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ short *bits = (short *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_UINT32:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ unsigned long *bits = (unsigned long *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_INT32:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ long *bits = (long *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_FLOAT:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ float *bits = (float *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_DOUBLE:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ double *bits = (double *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if(bits[x] != 128)
+ throw(1);
+ }
+ }
+ break;
+ case FIT_COMPLEX:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ FICOMPLEX *bits = (FICOMPLEX *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if((bits[x].r != 128) || ((bits[x].r - bits[x].i) != 0))
+ throw(1);
+ }
+ }
+ break;
+ case FIT_RGB16:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ FIRGB16 *bits = (FIRGB16 *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if((bits[x].red != 128) || (bits[x].green != 128) || (bits[x].blue != 128))
+ throw(1);
+ }
+ }
+ break;
+ case FIT_RGBF:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ FIRGBF *bits = (FIRGBF *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if((bits[x].red != 128) || (bits[x].green != 128) || (bits[x].blue != 128))
+ throw(1);
+ }
+ }
+ break;
+ case FIT_RGBA16:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ FIRGBA16 *bits = (FIRGBA16 *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if((bits[x].red != 128) || (bits[x].green != 128) || (bits[x].blue != 128) || (bits[x].alpha != 128))
+ throw(1);
+ }
+ }
+ break;
+ case FIT_RGBAF:
+ for(y = 0; y < FreeImage_GetHeight(clone); y++) {
+ FIRGBAF *bits = (FIRGBAF *)FreeImage_GetScanLine(clone, y);
+ for(x = 0; x < FreeImage_GetWidth(clone); x++) {
+ if((bits[x].red != 128) || (bits[x].green != 128) || (bits[x].blue != 128) || (bits[x].alpha != 128))
+ throw(1);
+ }
+ }
+ break;
+
+ }
+
+ // test unload function
+ FreeImage_Unload(clone);
+ clone = NULL;
+ FreeImage_Unload(image);
+ image = NULL;
+
+ } catch(int) {
+ if(image) FreeImage_Unload(image);
+ if(clone) FreeImage_Unload(clone);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL testLoadSaveConvertImageType(FIBITMAP *src, FREE_IMAGE_TYPE image_type, unsigned width, unsigned height) {
+ FIBITMAP *dst = NULL;
+ FIBITMAP *chk = NULL;
+ BOOL bResult = TRUE;
+
+ try {
+ // convert to type image_type
+ dst = FreeImage_ConvertToType(src, image_type);
+ if(!dst) throw(1);
+
+ // save image as TIFF
+ bResult = FreeImage_Save(FIF_TIFF, dst, "TestImageType.tif", TIFF_DEFAULT);
+ if(!bResult) throw(1);
+
+ // destroy dst
+ FreeImage_Unload(dst);
+ dst = NULL;
+
+ // load image
+ dst = FreeImage_Load(FIF_TIFF, "TestImageType.tif", TIFF_DEFAULT);
+ if(!dst) throw(1);
+
+ // convert to standard bitmap (linear scaling)
+ chk = FreeImage_ConvertToType(dst, FIT_BITMAP, TRUE);
+ if(!chk) throw(1);
+ FreeImage_Unload(dst);
+ dst = NULL;
+
+ // save image as TIFF
+ bResult = FreeImage_Save(FIF_TIFF, chk, "TestImageType.tif", TIFF_DEFAULT);
+ if(!bResult) throw(1);
+ FreeImage_Unload(chk);
+ chk = NULL;
+
+
+ } catch(int) {
+ if(dst) FreeImage_Unload(dst);
+ if(chk) FreeImage_Unload(chk);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOL testLoadSaveConvertComplexType(FIBITMAP *src, unsigned width, unsigned height, FREE_IMAGE_COLOR_CHANNEL channel) {
+ FIBITMAP *dst = NULL;
+ FIBITMAP *chk_double = NULL;
+ FIBITMAP *chk = NULL;
+ BOOL bResult = TRUE;
+
+ try {
+ // convert to type FICOMPLEX
+ dst = FreeImage_ConvertToType(src, FIT_COMPLEX);
+ if(!dst) throw(1);
+
+ // save image as TIFF
+ bResult = FreeImage_Save(FIF_TIFF, dst, "TestImageType.tif", TIFF_DEFAULT);
+ if(!bResult) throw(1);
+
+ // destroy dst
+ FreeImage_Unload(dst);
+ dst = NULL;
+
+ // load image
+ dst = FreeImage_Load(FIF_TIFF, "TestImageType.tif", TIFF_DEFAULT);
+ if(!dst) throw(1);
+
+
+ // convert to type FIT_DOUBLE
+ chk_double = FreeImage_GetComplexChannel(dst, channel);
+ if(!chk_double) throw(1);
+ FreeImage_Unload(dst);
+ dst = NULL;
+
+ // convert to standard bitmap (linear scaling)
+ chk = FreeImage_ConvertToType(chk_double, FIT_BITMAP, TRUE);
+ if(!chk) throw(1);
+ FreeImage_Unload(chk_double);
+ chk_double = NULL;
+
+ // save image as TIFF
+ bResult = FreeImage_Save(FIF_TIFF, chk, "TestImageType.tif", TIFF_DEFAULT);
+ if(!bResult) throw(1);
+ FreeImage_Unload(chk);
+ chk = NULL;
+
+
+ } catch(int) {
+ if(dst) FreeImage_Unload(dst);
+ if(chk_double) FreeImage_Unload(chk_double);
+ if(chk) FreeImage_Unload(chk);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+// Main test functions
+// ----------------------------------------------------------
+
+void testImageType(unsigned width, unsigned height) {
+ BOOL bResult = FALSE;
+
+ printf("testImageType ...");
+
+ bResult = testAllocateCloneUnloadType(FIT_BITMAP, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_UINT16, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_INT16, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_UINT32, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_INT32, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_FLOAT, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_DOUBLE, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_COMPLEX, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_RGB16, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_RGBA16, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_RGBF, width, height);
+ assert(bResult);
+ bResult = testAllocateCloneUnloadType(FIT_RGBAF, width, height);
+ assert(bResult);
+
+
+ printf("\tOK\n");
+}
+
+
+void testImageTypeTIFF(unsigned width, unsigned height) {
+ BOOL bResult = FALSE;
+
+ printf("testImageTypeTIFF ...");
+
+ // create a test 8-bit image
+ FIBITMAP *src = createZonePlateImage(width, height, 128);
+ assert(src != NULL);
+
+ // save for further examination
+ bResult = FreeImage_Save(FIF_PNG, src, "zoneplate.png", PNG_DEFAULT);
+ assert(bResult);
+
+ // test load /save / convert
+ // -------------------------
+
+ bResult = testLoadSaveConvertImageType(src, FIT_BITMAP, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_UINT16, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_INT16, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_UINT32, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_INT32, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_FLOAT, width, height);
+ assert(bResult);
+ bResult = testLoadSaveConvertImageType(src, FIT_DOUBLE, width, height);
+ assert(bResult);
+
+ // complex type
+ bResult = testLoadSaveConvertComplexType(src, width, height, FICC_REAL);
+ assert(bResult);
+ bResult = testLoadSaveConvertComplexType(src, width, height, FICC_IMAG);
+ assert(bResult);
+ bResult = testLoadSaveConvertComplexType(src, width, height, FICC_MAG);
+ assert(bResult);
+ bResult = testLoadSaveConvertComplexType(src, width, height, FICC_PHASE);
+ assert(bResult);
+
+ // free test image
+ FreeImage_Unload(src);
+
+ printf("\tOK\n");
+}
diff --git a/TestAPI/testJPEG.cpp b/TestAPI/testJPEG.cpp
new file mode 100644
index 0000000..2d8fe09
--- /dev/null
+++ b/TestAPI/testJPEG.cpp
@@ -0,0 +1,90 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// Local test functions
+// ----------------------------------------------------------
+
+void testJPEGTransform(const char *src_file) {
+ BOOL bResult;
+ BOOL perfect;
+
+ // perfect transformation
+ perfect = TRUE;
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_FLIP_H, perfect);
+ assert(bResult == FALSE);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_FLIP_V, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_TRANSPOSE, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_TRANSVERSE, perfect);
+ assert(bResult == FALSE);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_90, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_180, perfect);
+ assert(bResult == FALSE);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_270, perfect);
+ assert(bResult == FALSE);
+
+ // non perfect transformation
+ perfect = FALSE;
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_FLIP_H, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_FLIP_V, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_TRANSPOSE, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_TRANSVERSE, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_90, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_180, perfect);
+ assert(bResult);
+ bResult = FreeImage_JPEGTransform(src_file, "test.jpg", FIJPEG_OP_ROTATE_270, perfect);
+ assert(bResult);
+
+}
+
+void testJPEGCrop(const char *src_file) {
+ BOOL bResult;
+ bResult = FreeImage_JPEGCrop(src_file, "test.jpg", 50, 100, 359, 354);
+ assert(bResult);
+ bResult = FreeImage_JPEGCrop(src_file, "test.jpg", 50, 100, 650, 500);
+ assert(bResult == FALSE);
+}
+
+// Main test function
+// ----------------------------------------------------------
+
+void testJPEG() {
+ const char *src_file = "exif.jpg";
+
+ printf("testJPEG (should throw exceptions) ...");
+
+ // lossless transform - both perfect/non perfect
+ testJPEGTransform(src_file);
+ // cropping - both perfect/non perfect
+ testJPEGCrop(src_file);
+
+ printf("\tOK\n");
+}
diff --git a/TestAPI/testMPage.cpp b/TestAPI/testMPage.cpp
new file mode 100644
index 0000000..3ab80df
--- /dev/null
+++ b/TestAPI/testMPage.cpp
@@ -0,0 +1,98 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+void
+testBuildMPage(char *src_filename, char *dst_filename, FREE_IMAGE_FORMAT dst_fif, unsigned bpp) {
+ // get the file type
+ FREE_IMAGE_FORMAT src_fif = FreeImage_GetFileType(src_filename);
+ // load the file
+ FIBITMAP *src = FreeImage_Load(src_fif, src_filename, 0); //24bit image
+ unsigned src_bpp = FreeImage_GetBPP(src);
+ // convert to the requested bitdepth
+ if(src_bpp != bpp) {
+ FIBITMAP *tmp = NULL;
+ switch(bpp) {
+ case 8:
+ tmp = FreeImage_ConvertTo8Bits(src);
+ break;
+ case 24:
+ tmp = FreeImage_ConvertTo24Bits(src);
+ break;
+ }
+ assert(tmp != NULL);
+ FreeImage_Unload(src);
+ src = tmp;
+ }
+
+ FIMULTIBITMAP *out = FreeImage_OpenMultiBitmap(dst_fif, dst_filename, TRUE, FALSE, FALSE);
+ for(int size = 16; size <= 48; size += 16 ) {
+ FIBITMAP *rescaled = FreeImage_Rescale(src, size, size, FILTER_CATMULLROM);
+ if((src_bpp == 8) && FreeImage_IsTransparent(src)) {
+ // copy the transparency table
+ BYTE *trns = FreeImage_GetTransparencyTable(src);
+ int count = FreeImage_GetTransparencyCount(src);
+ FreeImage_SetTransparencyTable(rescaled, trns, count);
+ }
+ FreeImage_AppendPage(out, rescaled);
+ FreeImage_Unload(rescaled);
+ }
+
+ FreeImage_Unload(src);
+
+ FreeImage_CloseMultiBitmap(out, 0);
+
+}
+
+void testMPageCache(char *src_filename) {
+ const char *dst_filename = "mpages.tif";
+
+ BOOL keep_cache_in_memory = FALSE;
+
+ // get the file type
+ FREE_IMAGE_FORMAT src_fif = FreeImage_GetFileType(src_filename);
+ // load the file
+ FIBITMAP *src = FreeImage_Load(src_fif, src_filename, 0); //24bit image
+ assert(src != NULL);
+
+ // convert to 24-bit
+ if(FreeImage_GetBPP(src) != 24) {
+ FIBITMAP *tmp = FreeImage_ConvertTo24Bits(src);
+ assert(tmp != NULL);
+ FreeImage_Unload(src);
+ src = tmp;
+ }
+
+ FIMULTIBITMAP *out = FreeImage_OpenMultiBitmap(FIF_TIFF, dst_filename, TRUE, FALSE, keep_cache_in_memory);
+
+ // attempt to create 16 480X360 images in a 24-bit TIFF multipage file
+ FIBITMAP *rescaled = FreeImage_Rescale(src, 480, 360, FILTER_CATMULLROM);
+ for(int i = 0; i < 16; i++) {
+ FreeImage_AppendPage(out, rescaled);
+ }
+ FreeImage_Unload(rescaled);
+
+ FreeImage_Unload(src);
+
+ FreeImage_CloseMultiBitmap(out, 0);
+}
diff --git a/TestAPI/testMakeThumbnail.cpp b/TestAPI/testMakeThumbnail.cpp
new file mode 100644
index 0000000..f2c2ca8
--- /dev/null
+++ b/TestAPI/testMakeThumbnail.cpp
@@ -0,0 +1,42 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// Local test functions
+// ----------------------------------------------------------
+
+void testMakeThumbnail(const char *src_file) {
+ FIMEMORY *hmem = FreeImage_OpenMemory();
+
+ FIBITMAP *dib = FreeImage_Load(FIF_PNG, src_file, 0);
+ // perfect transformation
+ FIBITMAP *thumbnail = FreeImage_MakeThumbnail(dib, 600, TRUE);
+
+ FreeImage_SaveToMemory(FIF_PNG, thumbnail, hmem, 0);
+
+ FreeImage_CloseMemory(hmem);
+
+ FreeImage_Unload(thumbnail);
+ FreeImage_Unload(dib);
+}
+
diff --git a/TestAPI/testMemIO.cpp b/TestAPI/testMemIO.cpp
new file mode 100644
index 0000000..8250a57
--- /dev/null
+++ b/TestAPI/testMemIO.cpp
@@ -0,0 +1,146 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+void testSaveMemIO(const char *lpszPathName) {
+ FIMEMORY *hmem = NULL;
+
+ // load a regular file
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);
+
+ // open a memory handle
+ hmem = FreeImage_OpenMemory();
+
+ // save the file to memory
+ FreeImage_SaveToMemory(fif, dib, hmem, 0);
+
+ // at this point, hmem contains the entire PNG data in memory.
+ // the amount of space used by the memory is equal to file_size
+ long file_size = FreeImage_TellMemory(hmem);
+ printf("File size : %ld\n", file_size);
+
+
+ // its easy load an image from memory as well
+
+ // seek to the start of the memory stream
+ FreeImage_SeekMemory(hmem, 0L, SEEK_SET);
+
+ // get the file type
+ FREE_IMAGE_FORMAT mem_fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
+
+ // load an image from the memory handle
+ FIBITMAP *check = FreeImage_LoadFromMemory(mem_fif, hmem, 0);
+
+ // save as a regular file
+ FreeImage_Save(FIF_PNG, check, "dump.png", PNG_DEFAULT);
+
+ // make sure to free the data since FreeImage_SaveToMemory
+ // will cause it to be malloc'd
+ FreeImage_CloseMemory(hmem);
+
+ FreeImage_Unload(check);
+ FreeImage_Unload(dib);
+}
+
+ //you could also have image data in memory via some other method, and just set
+ //fmh.data to point to it, and set both fmh.datalen and fmh.filelen to the
+ //size of that data, then FreeImage_LoadFromMemory could load the image from that memory
+
+void testLoadMemIO(const char *lpszPathName) {
+ struct stat buf;
+ int result;
+
+ // get data associated with lpszPathName
+ result = stat(lpszPathName, &buf);
+ if(result == 0) {
+ // allocate a memory buffer and load temporary data
+ BYTE *mem_buffer = (BYTE*)malloc(buf.st_size * sizeof(BYTE));
+ if(mem_buffer) {
+ FILE *stream = fopen(lpszPathName, "rb");
+ if(stream) {
+ fread(mem_buffer, sizeof(BYTE), buf.st_size, stream);
+ fclose(stream);
+
+ // attach the binary data to a memory stream
+ FIMEMORY *hmem = FreeImage_OpenMemory(mem_buffer, buf.st_size);
+
+ // get the file type
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
+
+ // load an image from the memory stream
+ FIBITMAP *check = FreeImage_LoadFromMemory(fif, hmem, PNG_DEFAULT);
+
+ // save as a regular file
+ FreeImage_Save(FIF_PNG, check, "blob.png", PNG_DEFAULT);
+ FreeImage_Unload(check);
+
+ // close the stream
+ FreeImage_CloseMemory(hmem);
+
+ }
+ }
+ // user is responsible for freeing the data
+ free(mem_buffer);
+ }
+}
+
+void testAcquireMemIO(const char *lpszPathName) {
+ FIMEMORY *hmem = NULL;
+
+ // load a regular file
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);
+
+ // open and allocate a memory stream
+ hmem = FreeImage_OpenMemory();
+
+ // save the file to memory
+ FreeImage_SaveToMemory(FIF_PNG, dib, hmem, PNG_DEFAULT);
+
+ FreeImage_Unload(dib);
+
+ // get the buffer from the memory stream
+ BYTE *mem_buffer = NULL;
+ DWORD size_in_bytes = 0;
+
+ FreeImage_AcquireMemory(hmem, &mem_buffer, &size_in_bytes);
+
+ // save the buffer in a file stream
+ FILE *stream = fopen("buffer.png", "wb");
+ if(stream) {
+ fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream);
+ fclose(stream);
+ }
+
+ // close and free the memory stream
+ FreeImage_CloseMemory(hmem);
+
+}
+
+void testMemIO(const char *lpszPathName) {
+ testSaveMemIO(lpszPathName);
+ testLoadMemIO(lpszPathName);
+ testAcquireMemIO(lpszPathName);
+}
+
diff --git a/TestAPI/testPlugins.cpp b/TestAPI/testPlugins.cpp
new file mode 100644
index 0000000..e320963
--- /dev/null
+++ b/TestAPI/testPlugins.cpp
@@ -0,0 +1,38 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+// Show plugins
+// ----------------------------------------------------------
+void showPlugins() {
+ // print version & copyright infos
+
+ printf("FreeImage version: %s\n\n%s\n\n", FreeImage_GetVersion(), FreeImage_GetCopyrightMessage());
+
+ // print plugins info
+
+ for (int j = FreeImage_GetFIFCount() - 1; j >= 0; --j)
+ printf("bitmap type %d (%s): %s (%s)\n", j, FreeImage_GetFormatFromFIF((FREE_IMAGE_FORMAT)j), FreeImage_GetFIFDescription((FREE_IMAGE_FORMAT)j), FreeImage_GetFIFExtensionList((FREE_IMAGE_FORMAT)j));
+ printf("\n");
+}
+
diff --git a/TestAPI/testTools.cpp b/TestAPI/testTools.cpp
new file mode 100644
index 0000000..c180d81
--- /dev/null
+++ b/TestAPI/testTools.cpp
@@ -0,0 +1,82 @@
+// ==========================================================
+// FreeImage 3 Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "TestSuite.h"
+
+
+// ----------------------------------------------------------
+
+/** Create a Zone Plate test pattern.
+
+ The circular zone plate has zero horizontal and vertical frequencies at the center.
+ Horizontal frequencies increase as you move horizontally, and vertical frequencies increase as you move vertically.
+ These patterns are useful to:
+ <ul>
+ <li> evaluate image compression
+ <li> evaluate filter properties
+ <li> evaluate the quality of resampling algorithms
+ <li> adjust gamma correction - at the proper gamma setting, the møires should be minimized
+ </ul>
+ Reference:
+ [1] Ken Turkowski, Open Source Repository. [Online] http://www.worldserver.com/turk/opensource/
+*/
+FIBITMAP* createZonePlateImage(unsigned width, unsigned height, int scale) {
+ const double PI = 3.1415926535898;
+ BYTE sinTab[256];
+
+ FIBITMAP *dst;
+ int i, j, x, y;
+ int cX, cY, d;
+
+ // allocate a 8-bit dib
+ dst = FreeImage_Allocate(width, height, 8);
+ if(!dst)
+ return NULL;
+
+ // build a greyscale palette
+ RGBQUAD *pal = FreeImage_GetPalette(dst);
+ for(i = 0; i < 256; i++) {
+ pal[i].rgbRed = i;
+ pal[i].rgbGreen = i;
+ pal[i].rgbBlue = i;
+ }
+
+ // build the sinus table
+ for(i = 0; i < 256; i++) {
+ sinTab[i] = (BYTE)(127.5 * sin(PI * (i - 127.5) / 127.5) + 127.5);
+ }
+
+ cX = width / 2;
+ cY = height / 2;
+
+ // create a zone plate
+ for(i = height, y = -cY; i--; y++) {
+ BYTE *dst_bits = FreeImage_GetScanLine(dst, i);
+ for (j = width, x = -cX; j--; x++) {
+ d = ((x * x + y * y) * scale) >> 8;
+ dst_bits[j] = sinTab[d & 0xFF];
+ }
+ }
+
+ return dst;
+}
+
diff --git a/Whatsnew.txt b/Whatsnew.txt
new file mode 100644
index 0000000..d459977
--- /dev/null
+++ b/Whatsnew.txt
@@ -0,0 +1,977 @@
+What's New for FreeImage
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+September 28th, 2009 - 3.13.0
+! FreeImage now uses LibJPEG 7
+! FreeImage now uses LibRaw-Lite 0.7.2
+! FreeImage now uses libPNG 1.2.40
+! FreeImage now uses libTIFF 3.9.1
+! FreeImage_RotateClassic is deprecated (use FreeImage_Rotate instead)
++ [Herve Drolon] added support for all Photoshop supported color modes to PSD plugin
++ [Herve Drolon] added support for 32-bit to JNG/MNG plugin
++ [Amir Ebrahimi] added loading support for the PICT format
++ [Herve Drolon] added loading support for camera RAW formats (using LibRawLite wrapper for dcraw)
++ [Mihail Naydenov] added UNICODE functions FreeImage_JPEGTransformU and FreeImage_JPEGCropU
++ [Carsten Klein] added FreeImage_OpenMultiBitmapFromHandle
++ [Carsten Klein] added FreeImage_FillBackground
++ [Carsten Klein] added FreeImage_EnlargeCanvas
++ [Carsten Klein] added FreeImage_AllocateEx / FreeImage_AllocateExT
++ [Mihail Naydenov/Herve Drolon] added FreeImage_TmoReinhard05Ex
++ [Herve Drolon] added FIT_RGBA16 to FIT_RGBF conversion to FreeImage_ConvertToRGBF
++ [Herve Drolon] added FreeImage_Rotate (support for most image types, support background color)
+* [Christian Heimes] fixed function prototypes to use a void argument when no argument exist
+* [Herve Drolon] fixed RGB color ordering on Intel macs
+* [Herve Drolon] FreeImage_RotateClassic now keep transparency when applied to 8-bit images
+* [Herve Drolon] fixed handling of transparency info in FreeImage_Copy
+* [Herve Drolon] fixed a normalization error in FreeImage_GetAdjustColorsLookupTable
+* [Herve Drolon] fixed invalid Exif rotation in PluginJPEG for orientation cases 2 and 4
+* [Mihail Naydenov / Carsten Klein] fixed compilation issues with MinGW32
+* [Mihail Naydenov] improved the loading speed of all targa images
+* [Herve Drolon] FreeImage_TagToString now handles the Exif UserComment tag
+
+April 14th, 2009 - 3.12.0
+! FreeImage now uses libPNG 1.2.35
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2009-02-12)
+! FreeImage now uses OpenJPEG 1.3.0 (SVN patch 2008-08-21)
+! [Herve Drolon] FreeImage_CloneMetadata no longer clone the FIMD_ANIMATION metadata (this was causing problems when saving to GIF format)
++ [Herve Drolon] added full support for the PFM format
++ [Herve Drolon] added JPEG_EXIFROTATE load flag to the JPEG plugin
++ [Herve Drolon] added 16-bit RGB(A) and float RGB(A)F support to FreeImage_GetChannel / FreeImage_SetChannel
++ [Herve Drolon] added src FIT_RGBA16 to dst 32-bit FIT_BITMAP conversion to FreeImage_ConvertToType
+* [Carsten Klein] FreeImage_Copy now copies transparency info, resolution info, ICC profile and metadata
+* [Carsten Klein] check for negative top/left values in FreeImage_Paste
+* [Christian Heimes] changed exceptions with a "catch(char *text)" to a "catch(const char *text)" to make GCC 4.1 happy
+* [Deif Lou] fixed a bug in FreeImage_SetTransparentIndex
+* [Thomas Maiwald] BMP plugin: on saving, fixed correct setting of bfSize BMP file header for palettized images
+* [Timothy Lee] fixed handling of frame disposal in GIF_PLAYBACK mode (GIF plugin)
+* [Herve Drolon] fixed handling of Exif Olympus Type 2 maker notes (not yet supported but now safely ignored)
+* [Rich Geldreich] fixed DXT1 color endpoint precision problem in DDS plugin
+* [Mihail Naydenov] improved loading speed of 24-bit targa images
+* [Eugene Golushkov] improved big endian / little endian swapping functions
+* [Carsten Klein/Jean-Philippe Goerke] improved FreeImage_SetMetadata / FreeImage_GetMetadata accessors
+* [Christian Ruppert] improved Linux Makefiles
+* [Eugene Golushkov] fixed PluginBMP alignment bug while saving 16 or 24bit BMP on big endian or Apple machines
+
+July 28th, 2008 - 3.11.0
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2008-05-24)
+! FreeImage now uses OpenJPEG 1.3.0 (SVN patch 2008-05-22)
+! FreeImage now uses libMNG 1.0.10
+! FreeImage now uses libPNG 1.2.29
++ [Yves Schmid] added 48-bit RGB to 32-bit conversion support in FreeImage_ConvertTo32Bits
++ [Aaron Shumate] added RGB16-to-BITMAP and All-to-RGBF conversion support in FreeImage_ConvertToType
++ [Benjamin English] added a new OpenGL sample to FreeImage/Examples
++ [Lucian Sabo] added new compression flags to the PNG plugin
++ [Lucian Sabo] added new compression flags to the JPEG plugin (chroma subsampling options)
++ [Noam Gat] added support for SGI grayscale + alpha pics to SGI plugin
++ [Herve Drolon] added FreeImage_CloneMetadata
++ [Herve Drolon] added loading support for Windows Vista icons in ICO Plugin
++ [Herve Drolon] added loading and saving support for RGBF images to the TIF plugin (using the LogLuv codec)
+* [Will Bryant] fixed makefile for MacOSX Tiger and Leopard
+* [Maria Gullickson] fixed a 'divide by 0' error in PNM plugin and FreeImage_Rescale function
+* [Yves Schmid] fixed a bug with Exif metadata reading in TIFF images
+* [Herve Drolon] fixed some possible 64-bit portability issues with pointer calculations
+* [wangyn] fixed a bug with transparency handling of indexed images in PNG plugin
+* [Martin Dyring-Andersen] fixed a bug with GIFinfo structure initialization in GIF plugin
+* [Noam Gat] fixed a bug in SGI plugin: when the file reports as two-dimensional, the height factor does not get loaded
+* [Herve Drolon] added error messages in FreeImage_Load(U) / FreeImage_Save(U) in case of bad filenames
+* [Scott Smith/Herve Drolon] added missing IPTC tags and renamed some tag names to be compatible with ExifTool naming convention
+* [Martin Dyring-Andersen] fixed a crash problem with images containing exif data emitted by Picassa
+* [Herve Drolon] removed RGBA to RGB transparent conversion in EXR plugin
+* [Glenn Pierce] improved the speed of FreeImage_FlipHorizontal
+* [Carsten Klein] fixed 65535 pixels width/height limitation in FreeImage_Paste
+
+November 19th, 2007 - 3.10.0
+! FreeImage now uses libTIFF 3.9.0beta (CVS patch 2007-10-05)
+! FreeImage now uses OpenJPEG 1.2.0 (SVN patch 2007-07-13)
+! FreeImage now uses OpenEXR 1.6.1
+! FreeImage now uses libPNG 1.2.23
+! FreeImage now hides its internal functions and internal libraries when compiled with gcc
+- [Herve Drolon] removed VS C+ 6.0 project files : this IDE is no longer supported because of OpenEXR
++ [Herve Drolon] added VS 2005 project files
++ [Herve Drolon] added full support for the OpenEXR format
++ [Herve Drolon] added full support for the JPEG-2000 format
++ [Herve Drolon] added FreeImage_TmoFattal02 tone mapping operator
++ [Ryan Rubley] added support for RGB vs BGR regardless of endian
++ [Herve Drolon] added FreeImage_MultigridPoissonSolver
++ [Carsten Klein] added FreeImage_PreMultiplyWithAlpha
++ [Carsten Klein] added __stdcall version of FreeImage_OutputMessage
++ [Carsten Klein] added new palette and color manipulation functions (see below) :
+ added FreeImage_SetTransparentIndex
+ added FreeImage_GetTransparentIndex
+ added FreeImage_GetAdjustColorsLookupTable
+ added FreeImage_AdjustColors
+ added FreeImage_ApplyColorMapping
+ added FreeImage_SwapColors
+ added FreeImage_ApplyPaletteIndexMapping
+ added FreeImage_SwapPaletteIndices
+* [Herve Drolon] fixed a bug in TIFF plugin when reading 8-bit + 8-bit alpha images
+* [Herve Drolon] fixed a bug in TIFF plugin when reading images with uncommon bitdepths
+* [rodrigo] fixed FreeImage exception handling under gcc (added -fexceptions to gcc compiler flags)
+* [Martin Dyring-Andersen] fixed GIF plugin crashing on some corrupted files
+* [Herve Drolon] fixed a bug with RLE encoding for 8-bit BMP images
+* [Herve Drolon] fixed GPS metadata being skipped when reading metadata in Exif images
+* [Herve Drolon] fixed a bug when reading OS/2 BMP images with a negative height
+* [Ryan Rubley] fixed a bug with loading of GIFs with large amounts of solid color areas
+* [Ryan Rubley] fixed OS X compile error in BitmapAccess.cpp
+* [Herve Drolon] fixed a bug in FreeImage_Paste when pasting non-standard image types
+* [Herve Drolon] saving 1-bit TIF with the TIFF_CCITTFAX3 flag is now compliant with the TIFF Class F specification
+* [Carsten Klein] fixed topdown parameter in FreeImage_ConvertFromRawBits and FreeImage_ConvertToRawBits being handled in reverse
+* [Herve Drolon] fixed a bug when reading some RLE-4 encoded BMP data
+* [Carsten Klein] conversion from 1-bit to 32-bit now keep possibly present transparency
+
+February 11th, 2007 - 3.9.3
+! FreeImage now uses libPNG 1.2.16
+! [Ryan Rubley/Ryan Davis] reworked the MacOSX makefile in order to fully support Universal Binary builds of FreeImage
+! [Herve Drolon] makefiles are now generated from VS2003 project files instead of VS6 project files
+! [Herve Drolon] changed JPEG load/save flag option values
++ [Herve Drolon] added support for RGBAF images to FreeImage_ConvertToRGBF
++ [Herve Drolon] FreeImage_Paste now works with any bitmap type
++ [Herve Drolon] added full support for 64-bit RGBA images to the PNG and TIFF plugins
++ [Jascha Wetzel] added JPEG downsampling feature to PluginJPEG:Load
+* [Thomas Chmielewski] fixed a bug in FreeImage_Dither and Bayer dithering, added FID_BAYER16x16
+* [Raphael Gaquer] greatly improved the speed of the GIF encoder
+* [Herve Drolon] fixed saving of metadata in the PNG plugin
+* [rampelstinskin] fixed transparency table to alpha channel conversion for 4-bit images in FreeImage_ConvertTo32Bits
+* [Scott Smith] added missing IPTC tag named "Country/PrimaryLocationCode"
+* [Herve Drolon] changed #include <stdint.h> by #include <inttypes.h> in FreeImage.h (needed by Solaris 9)
+* [Pierre Arnaud] fixed the use of FreeImage in low memory condition by checking some returned values of the malloc function
+* [Pierre Arnaud] fixed TagLib::getTagFieldName not being thread safe
+
+October 30th, 2006 - 3.9.2
+! FreeImage now uses libTIFF 3.8.2 (with patch 2006-10-13)
++ [Herve Drolon] added full support for 16-bit greyscale and 48-bit RGB to the PNM plugin
++ [Herve Drolon] added IPTC writing support to JPEG & TIFF plugins
++ [Herve Drolon] added new Exif maker note tags
++ [Herve Drolon] added FreeImage_JPEGCrop
++ [Thorsten Radde] added support for 8-bit palettized bitmaps in FreeImage_RotateClassic
++ [Matt Rice] added automatic call to FreeImage_Initialise / FreeImage_DeInitialise when using FreeImage as a .so
++ [Martin Dyring-Andersen] added FreeImage_LoadMultiBitmapFromMemory to the multi-page API
++ [Herve Drolon] added support for tiled TIFF images
+* [Carsten Klein] fixed a bug in FreeImage_SetMetadata occuring when deleting a tag
+* [Herve Drolon] fixed a bug in PNG plugin when reading Macromedia 'false' PNG files
+* [Thorsten Radde] added resolution support to PluginPSD
+* [Ryan Rubley] fixed a bug in PluginGIF occuring with interlaced GIF
+* [Ryan Rubley] fixed a bug in the multipage cache mechanism (internal FreeImage_FindBlock function)
+* [Thorsten Radde] fixed a stack corruption in TIFF plugin occuring when reading exif tags
+* [checkered] fixed a bug in the multipage cache mechanism causing VS2005 to crash on multipage files
+* [Herve Drolon] fixed a bug with transparency support of 1- and 4-bit images
+* [Roar Flolo] fixed a bug in PSD plugin when reading non compressed RGB images (alpha channel initialization)
+* [Nicolas Hatier] fixed a bug in PluginGIF when using the GIF_PLAYBACK flag
+* [Herve Drolon] fixed a bug in TIFF plugin when saving 8-bit images using LZW with differenciation
+* [Herve Drolon] fixed 64-bit compilation issue with LibPNG and assembler code
+
+July 16th, 2006 - 3.9.1
+* [Ryan Rubley] fixed a bug in PluginGIF plugin causing FreeImage to crash on malformed GIF files
+
+July 6th, 2006 - 3.9.0
+! FreeImage now uses libPNG 1.2.12
+! FreeImage now uses libTIFF 3.8.2 (with patch 2006-06-24)
+! FreeImage_Allocate/FreeImage_Allocate now set the resolution to 72 dpi instead of 0
++ [Herve Drolon/Petr Pytelka] added a raw FAX G3 format loader
++ [Herve Drolon] added support for most image types to FreeImage_Rescale
++ [Herve Drolon] added FreeImage_MakeThumbnail
++ [Herve Drolon] added support for 64-bit images to FreeImage_ConvertTo32Bits
++ [Herve Drolon] added support for Exif tags to TIF plugin (read only)
++ [Herve Drolon] added FreeImage_ReadMemory
++ [Herve Drolon] added FreeImage_WriteMemory
++ [Herve Drolon] added new Exif maker note tags
++ [Sherman Wilcox] added a SGI file format loader
++ [Herve Drolon] added support for separated images to PluginTIFF
++ [Herve Drolon] added support for progressive-JPEG saving to PluginJPEG
+* [Carsten Klein] FreeImage_Dither and FreeImage_Threshold now work with palettized 8-bit dib
+* [Christophe Petit] fixed a bug in FreeImage_GetFIFFromFilenameU occuring with files without extension
+* [Leigh Brasington] fixed a bug in PluginGIF causing FreeImage not working on Win/98/ME
+* [Herve Drolon] fixed a bug in PluginTIFF with writing of JPEG-in-TIFF files
+* [Jojakim Stahl] fixed a bug occuring with 4-bit PCX files
+* [Sandor Szalacsi] fixed a bug in FreeImage_SetBackgroundColor (bkgnd clearing)
+* [Petr Pytelka] fixed PluginTIFF::_tiffSizeProc failing on some images
+* [Sherman Wilcox] fixed a bug in DDS plugin when loading images whose size is not a multiple of 4
+* [Sherman Wilcox] fixed a memory leak in PluginDDS::LoadDXT_Helper
+* [Sherman Wilcox] fixed DDS plugin bad behavior with invalid DDS files (such as files with zero length)
+* [Floris van den Berg] fixed a memory leak in the MultiPage cache mechanism
+* [Herve Drolon] replaced WIN32 #define by _WIN32 #define as this is needed by VS2005
+* [Herve Drolon] fixed a VS2005 error in FreeImage_DeletePage
+* [Petr Supina] fixed a pow(long,long) function not being standard ANSI C/C++
+* [Petr Supina] fixed FreeImage_FindBlock function not being standard ANSI C/C++
+* [Olaf Stoyke] added support for 64-bit Linux OS
+* [Craig Stark] fixed FreeImage support on Intel based Mac OS
+* [Herve Drolon] fixed PluginTIFF failing on bad fax tiff images (bad images are now loaded 'as is')
+* [Zack Simpson] fixed a bug occuring in rare situations with FreeImage_Aligned_Malloc
+
+September 5, 2005 - 3.8.0
+! FreeImage now uses libTIFF 3.7.3
+! FreeImage now uses ZLib 1.2.3
++ [Herve Drolon] added support for 48-bit images to FreeImage_ConvertTo24Bits
++ [Herve Drolon] added FreeImage_ConvertToGreyscale
++ [Herve Drolon] added support for 16-bit greyscale images to FreeImage_ConvertTo8Bits
++ [Petr Pytelka] added UNICODE functions (see below)
+ added FreeImage_LoadU
+ added FreeImage_SaveU
+ added FreeImage_GetFIFFromFilenameU
+ added FreeImage_GetFileTypeU
++ [Herve Drolon] FreeImage_Copy now works with any bitmap type
++ [Herve Drolon] added support for 1-bit images to FreeImage_Paste
+* [Ryan Rubley] fixed PluginGIF failing to link on some broken gcc versions
+* [Karl-Heinz Bussian] fixed a bug in LookupX11Color/LookupSVGColor with handling of grey color names
+* [Herve Drolon] FreeImage_Dither now uses FreeImage_ConvertToGreyscale and handles 4/8-bit palletized images
+* [Herve Drolon] FreeImage_Threshold now uses FreeImage_ConvertToGreyscale and handles 4/8-bit palletized images
+* [Craig Hockenberry] fixed PluginGIF::Save swapping the byte order for the height on big endian machines (e.g. PPC on Mac OS X.)
+* [Herve Drolon] fixed a bug in JPEG plugin when reading Exif maker notes from images produced by Nikon Editor
+* [Herve Drolon] fixed a bug in BMP plugin when reading some malformed RLE8 bmp
+* [Herve Drolon] fixed a bug in RAS plugin when loading 8-bit palettized images with less than 256 colors
+* [Herve Drolon] fixed a bug in FreeImage_Rescale with 16-,48-,64-bit images
+* [Herve Drolon] fixed a bug in the ICC profiles API when loading profile-less CMYK TIFF
+* [Herve Drolon] 4-bit PNG are now loaded as 4-bit and no longer converted to 8-bit
+* [Greg Ng] fixed a bug in FreeImage_ConvertToRGBF (FIT_BITMAP -> FIT_RGBF conversion)
+
+May 7, 2005 - 3.7.0
+! FreeImage now uses libTIFF 3.7.2
+! [Ryan Rubley] improved FreeImage_OpenMultiBitmap
++ [Detlev Vendt] added FreeImage_ZLibGUnzip
++ [Herve Drolon] added new image data types FIT_RGB16, FIT_RGBA16, FIT_RGBF, FIT_RGBAF
++ [Herve Drolon] FreeImage_FlipHorizontal & FreeImage_FlipVertical now work with any bitmap type
++ [Herve Drolon] added conversions to float and double in FreeImage_ConvertToType
++ [Herve Drolon] added FreeImage_ConvertToRGBF
++ [Herve Drolon] added support for 16-, 48- and 96-bit images to FreeImage_Rescale
++ [Ryan Rubley] added FreeImage_ColorQuantizeEx
++ [Ryan Rubley] added FIMD_ANIMATION and FIDT_PALETTE
++ [Ryan Rubley] added brand new PluginGIF with full animation multipage and metadata support
++ [Herve Drolon] added support for FIC_MINISWHITE 8-bit images to FreeImage_Rescale
++ [Herve Drolon] added HDR (High Dynamic Range) format (loader & writer)
++ [Herve Drolon] added support for 48-bit images in TIFF plugin
++ [Herve Drolon] added support for 48-bit images in PNG plugin
++ [Herve Drolon] added tone mapping operators (see below)
++ added FreeImage_ToneMapping
++ added FreeImage_TmoDrago03
++ added FreeImage_TmoReinhard05
++ [Petr Pytelka] added FreeImage_JPEGTransform
+* [Herve Drolon] allowed loading of corrupted JPEG with a premature end of file
+* [Herve Drolon] fixed a memory leak with loading of exif JPEG images
+* [Detlev Vendt] changed some 'pointer-to-int' casts to 'pointer-to-long' for 64bit machines
+* [Ryan Rubley] fixed a memory leak in the multipage API
+* [Ryan Rubley] updated VB6 wrapper generation for new functions
+* [Herve Drolon] fixed incorrect behavior when reading JPEG comments containing special characters
+* [Herve Drolon] fixed incorrect behavior when reading JPEG ICC profiles with a size greater than 64 KB
+* [Herve Drolon] fixed a bug in TIFF plugin when loading malformed multipage TIFF
+* [Herve Drolon] fixed PluginTIFF not being thread safe
+
+February 20, 2005 - 3.6.1
+* [Ryan Rubley] fixed a memory leak in the metadata API
+* [luedi] improved the robustness of FIBITMAP allocations
+
+February 13, 2005 - 3.6.0
+! FreeImage now uses libMNG 1.0.9
+! [Herve Drolon] improved the speed of FreeImage_Rescale
+! [Herve Drolon] improved FreeImage_RotateClassic (more compact code, a little faster)
+! [Herve Drolon] improved the metadata API using tag accessors
++ [Detlev Vendt] added LZW support to PluginGIF:Save
++ [Herve Drolon] added VS.Net 2003 project files
++ [Herve Drolon] added VERSIONINFO resource to the DLL
++ [Herve Drolon] added support for CMYK JPEG on loading
++ [Petr Supina] added 16-bytes alignment to FIBITMAP palette and pixels starting address
++ [Petr Supina] added support for MMX/SSE2 code in LibJPEG (based on Mozilla/Firefox code)
++ [Herve Drolon] added TIFF_JPEG compression flag to the TIFF plugin
++ [Detlev Vendt] added FreeImage_ZLibGZip
++ [Detlev Vendt] added FreeImage_ZLibCRC32
+* [Detlev Vendt] fixed PluginPNG not being thread safe
+* [Herve Drolon] fixed compiler warning C4018 occuring with VS.Net 2003
+
+December 29, 2004 - 3.5.3
+! FreeImage now uses ZLib 1.2.2
+! FreeImage now uses libPNG 1.2.8
+! FreeImage now uses libTIFF 3.7.1
+! [Herve Drolon] improved FreeImage_RotateClassic
+! [Detlev Vendt] improved FreeImage_Rescale (more compact code, preserving 8-bpp colors)
++ [Herve Drolon] added support for transparency saving in ICO plugin
++ [Herve Drolon] added support for 1-bit images to FreeImage_RotateClassic
++ [Herve Drolon] added FreeImage_SetDotsPerMeterX and FreeImage_SetDotsPerMeterY
+* [Nan Feng] fixed memory leak in FreeImage_DeleteTag (internal stuff)
+* [Nigel Stewart] added conditional #pragma with #ifdef _MSC_VER / #endif
+* [Herve Drolon] fixed the '65536 lines' limit on loading in PNM plugin
+
+November 27th, 2004 - 3.5.2
+* [Herve Drolon] fixed a second bug in FreeImage_Clone function
+
+November 26th, 2004 - 3.5.1
++ [Riley McNiff] added FreeImage_ConvertTo4Bits
+* [Herve Drolon] fixed a buffer overrun with some ILBM images
+* [Riley McNiff] fixed a potential problem when reading TIFF resolution info
+* [Dimitar Atanasov] fixed a bug in FreeImage_Clone function
+* [Dimitar Atanasov] fixed several bugs in TIFF plugin
+
+November 1st, 2004 - 3.5.0
+! FreeImage now uses libPNG 1.2.7
+! FreeImage now uses libTIFF 3.7.0
+! FreeImage now uses libMNG 1.0.8
+! [Herve Drolon] improved TIFF LZW compression using a predictor
+! [Detlev Vendt] FreeImagesPlus: corrected references to FreeImage.h and FreeImage.lib
++ [Herve Drolon] added support for loading/saving of 8-bit transparent TIFF
++ [Riley McNiff] added support for 4-bit dib in FreeImage_Paste
++ [Herve Drolon] added support for memory IO streams (see below)
++ added FreeImage_OpenMemory
++ added FreeImage_CloseMemory
++ added FreeImage_LoadFromMemory
++ added FreeImage_SaveToMemory
++ added FreeImage_TellMemory
++ added FreeImage_SeekMemory
++ added FreeImage_AcquireMemory
++ added FreeImage_GetFileTypeFromMemory
++ [Petr Pytelka] added FreeImage_GetFIFMimeType to the plugins function list
++ [Herve Drolon] added ICC profile support to JPEG plugin
++ [Herve Drolon] added support for metadata (see below)
++ added FreeImage_SetMetadata
++ added FreeImage_GetMetadata
++ added FreeImage_GetMetadataCount
++ added FreeImage_TagToString
++ added FreeImage_FindFirstMetadata
++ added FreeImage_FindNextMetadata
++ added FreeImage_FindCloseMetadata
+* [Riley McNiff] fixed a bug with FreeImage_SetPixelIndex and 4-bit images
+* [Petr Pytelka] fixed returned value in FreeImage_CloseMultiBitmap
+* [Petr Pytelka] fixed index of new page in FreeImage_InsertPage
+* [Aaron Shumate] fixed a minor bug in PNG plugin
+* [Aaron Shumate] fixed a bug in IFF plugin (odd-length chunks)
+* [Rupert Hewitt] fixed FreeImage not compiling on National Instruments Cvi Ccompiler
+* [Herve Drolon] fixed a bug in IFF plugin (ILBM data)
+* [Fred Harju] added a Makefile for Solaris 9
+* [Roddy Pratt] fixed FreeImage not linking under Borland C++ Builder
+* [Vadim Alexandrov] fixed a memory leak in the multipage API
+* [Herve Drolon] fixed a bug with DDS plugin behaviour on Big Endian OS
+* [Herve Drolon] fixed a bug with conversion of JPEG resolution info on saving
+
+July 8th, 2004 - 3.4.0
+! [Jim Keir] improved FreeImage_FlipVertical function
+! [Herve Drolon] LZW compression is now enabled in FreeImage
++ [Karl-Heinz Bussian] added constants to FreeImage.h to get at compile time the library version
++ [Karl-Heinz Bussian] added color lookup functions for X11 and SVG
++ [Herve Drolon] added TIFF tags TIFF_CCITTFAX3, TIFF_CCITTFAX4 and TIFF_LZW
++ [Detlev Vendt] added support for CMYK TIFF files with alpha channel
++ [Detlev Vendt] added (re-introduction of) PluginGIF
+* [Herve Drolon] fixed a bug with loading of FAX TIFF images (introduced with LibTIFF 3.6.1)
+* [Herve Drolon] fixed a bug in Floyd-Steinberg dithering algorithm
+* [Herve Drolon] fixed a bug in Targa plugin save function
+* [Herve Drolon] fixed a bug in FreeImage_AdjustCurve function
+* [Ryan Rubley] fixed a bug with FreeImage_Rescale's filters accuracy
+* [Ryan Rubley] fixed a bug in NN quantizer
+* [Herve Drolon] fixed a bug with TIFF files containing additional Photoshop alpha channels
+* [James Rossfeld] fixed a memory leak with some PSD images
+* [Herve Drolon] fixed a bug with saving of 32-bit non transparent PNG images
+* [Alexandr Zamaraev] fixed FreeImage not compiling with mingw32
+* [Herve Drolon] fixed FreeImage not compiling with VC.NET (pow function needs casts)
+
+May 2, 2004 - 3.3.0
+! [Ryan Rubley] FreeImage has been ported to MacOSX and should also work on other big endian processors
++ [Ryan Rubley] rewrote XPM plugin (better load support) and added save support
++ [Ryan Rubley] added ICO_MAKEALPHA flag to ICO plugin
++ [Ryan Rubley] Set/GetPixelColor now works with 16-bit pixels (555 or 565)
++ [Herve Drolon] PNG plugin now supports loading and saving of unsigned 16-bit greyscale images
+* [Herve Drolon] fixed a bug with loading of 8-bit and 16-bit PNG with a 8-bit alpha channel
+* [Herve Drolon] fixed a bug in NN quantizer algorithm with handling of 4-byte boundary alignment.
+* [Herve Drolon] fixed a bug in PluginIFF Validate function
+* [Herve Drolon] fixed a minor design issue in FreeImage_GetFIFFromFormat
+* [Brad Schick] fixed some compiler warnings with VC++ 7.1
+* [Herve Drolon] fixed a bug with saving of 8-bit palettized images to 24-bit JPEG (channel inversion)
+
+March 16, 2004 - 3.2.1
+! [Volker Gärtner] improved the DDS plugin
+! [Herve Drolon] FreeImage_Rescale now works on 8-, 24- and 32-bit images
+! [Herve Drolon] FreeImage_Copy now works on 1-, 4-, 8-, 16-, 24- and 32-bit images
+* [Floris van den Berg] fixed a bug in the MultiPage cache mechanism
+* [Herve Drolon] fixed a bug with loading/saving of 8-bit transparent tga images
+* [Herve Drolon] fixed a bug with loading of 1-bit TIFF (introduced with LibTIFF 3.6.1)
+
+February 18, 2004 - 3.2.0
+! FreeImage now uses libTIFF 3.6.1
++ [Herve Drolon] added FreeImage_HasBackgroundColor
++ [Herve Drolon] added FreeImage_GetBackgroundColor
++ [Herve Drolon] added FreeImage_SetBackgroundColor
++ [Herve Drolon] added FreeImage_Composite
++ [Herve Drolon] added ICC profile support to PNG plugin
++ [Herve Drolon] added background color support to PNG plugin
++ [Volker Gärtner] added support for DDS format (loader)
+* [Steve Johnson] improved FreeImage_OpenMultiBitmap/FreeImage_CloseMultiBitmap
+* [Steve Johnson] fixed a bug in FreeImage_InsertPage
+* [Herve Drolon] fixed a bug with JPEG compressed TIFF (red/blue swapping)
+* [Herve Drolon] fixed a bug in PluginTarga where 8-bit images were saved incorrectly
+
+January 26, 2004 - 3.1.0
+! FreeImage now uses ZLib 1.2.1
++ [Herve Drolon] added support for integer, real and complex image types (see below)
++ added FREE_IMAGE_TYPE enum
++ added FreeImage_AllocateT
++ added FreeImage_GetImageType
++ added FreeImage_FIFSupportsExportType
++ added FreeImage_ConvertToStandardType
++ added FreeImage_ConvertToType
++ added load/save support of all image types to TIFF plugin
++ [Peter Lemmens] added a Validate function to TARGA plugin
++ [Herve Drolon] added FreeImage_GetPixelIndex / FreeImage_SetPixelIndex
++ [Herve Drolon] added FreeImage_GetPixelColor / FreeImage_SetPixelColor
++ [Herve Drolon] added FreeImage_GetComplexChannel / FreeImage_SetComplexChannel
+* [Serge Ivanchenko] TIFF_DEFLATE compression is now enabled in TIFF plugin
+* [Herve Drolon] fixed a bug in NeuQuant color reduction algorithm
+
+November 16, 2003 - 3.0.4
+* [Tobias Persson] fixed FreeImage_GetChannel not working with FICC_ALPHA channel
+* [Detlev Vendt] fixed a minor bug with PNG plugin and PNG_IGNOREGAMMA flag
+* [Detlev Vendt] fixed a memory leak in PNG plugin save routine
+* [Detlev Vendt] fixed JPEG validation problem with .jpe files
+* [Ryan Rubley] added Source/LibTIFF/tif_extension.c to LibTIFF (needed for MacOSX)
+* [Herve Drolon] improved error handling in TIFF plugin
++ [Karl-Heinz Bussian] added FreeImage_IsLittleEndian
++ [Karl-Heinz Bussian] added JPEG save support for 8-bit miniswhite bitmaps (transparent conversion to minisblack)
++ [Karl-Heinz Bussian] FreeImage_GetColorType now recognizes 8-bit FIC_MINISWHITE images
+! [Herve Drolon] FreeImage_Rescale now supports rescaling of 32-bit images with alpha channel
+! [Herve Drolon] FreeImage_Invert now supports inversion of 32-bit images with alpha channel
+! [Herve Drolon] FreeImage_AdjustCurve now supports working with FICC_ALPHA channel
+
+November 2, 2003 - 3.0.3
+* [Ryan Rubley] improved makefile for Linux
+* [Ryan Rubley] fixed FreeImage not compiling under MacOSX
+* [Detlev Vendt] fixed still present inconsistancy with 32bpp transparency handling
+* [Herve Drolon] fixed incorrect loading of 4-bit greyscale images in TIFF plugin
+
+October 27, 2003 - 3.0.2
+! FreeImage now uses libMNG 1.0.6
+* [Herve Drolon] fixed a boolean test in PluginCUT returning always false
+* [Herve Drolon] fixed a warning in PluginIFF generated with g++
+* [Linus Tan] fixed a bug in FreeImage_Copy
+* [Herve Drolon] fixed FreeImage not compiling under Linux (thanks to Michal)
+
+October 20, 2003 - 3.0.1
+
+! FreeImage now uses libTIFF 3.6.0
+* [Detlev Vendt] fixed incorrect definition of the FREE_IMAGE_FORMAT enum
+* [Detlev Vendt] fixed a potential crash problem with Load / Save routines
+* [Herve Drolon] fixed incorrect loading of 16-bit greyscale images in TIFF plugin
+* [Dennis Lim] fixed a memory leak in Floyd & Steinberg dithering routine
+* [Herve Drolon] fixed a bug in BMP loader (incorrect loading of RLE4 bmp)
+* [Detlev Vendt] fixed some inconsistancy with 32bpp transparency handling
++ [David Boland] added a C# wrapper
+// Linux compatibility issues
+- [Michal Novotny] removed the round function in Utilities.h
+! [Herve Drolon] replaced the round routine by the clamp routine in PluginPCD
++ [Herve Drolon] added _itoa version in Utilities.h
+* [Michal Novotny] fixed untyped consts not accepted by g++ in PluginBMP
+
+September 8, 2003 - 3.0.0
+- [Herve Drolon] removed deprecated functions
+- [Herve Drolon] removed deprecated flags (TARGA_LOAD_RGB555, ICO_*, except ICO_DEFAULT)
+- [Herve Drolon] removed the FreeImage pointer table (internal stuff)
++ [Herve Drolon] added a C++ wrapper
++ [Herve Drolon] added the FreeImage Toolkit (see below)
++ added FreeImage_Rescale
++ added FreeImage_RotateClassic
++ added FreeImage_RotateEx
++ added FreeImage_FlipHorizontal
++ added FreeImage_FlipVertical
++ added FreeImage_Invert
++ added FreeImage_AdjustCurve
++ added FreeImage_AdjustGamma
++ added FreeImage_AdjustBrightness
++ added FreeImage_AdjustContrast
++ added FreeImage_GetHistogram
++ added FreeImage_GetChannel
++ added FreeImage_SetChannel
++ added FreeImage_Copy
++ added FreeImage_Paste
++ [Karl-Heinz Bussian] added XPM loader
++ [Karl-Heinz Bussian] added flags parameter to FreeImage_CloseMultiBitmap
++ [Karl-Heinz Bussian] added JPEG save support for 8-bit palettized bitmaps (transparent conversion to 24-bit)
++ [Herve Drolon] added interface to ZLib compression functions
++ [Herve Drolon] added ICO format to the multipage API (loader & writer)
++ [Herve Drolon] added a MIME type to all plugins
+* [Karl-Heinz Bussian] fixed incorrect conversion from 1-bit FIC_MINISWHITE bitmaps to 8-bit
+* [Herve Drolon] fixed a bug in FreeImage_CloseMultiBitmap
+* [Herve Drolon] fixed a potential memory leak in conversion functions (8-, 24-, 32-bit)
+* [Robert Walker] fixed incorrect conversion from 16-bit to 24-bit and 16-bit to 32-bit
+* [blurble] fixed TIFF validate signature problem (3DS files were recognized as TIFF)
+* [Kurt Jankowski-Tepe] fixed FreeImage not compiling on MinGW / LCC WIN32
+* [Jani Peltonen] fixed bug in PluginTARGA where 32-bit bitmaps are not always correctly flipped
+* [Detlev Vendt] fixed a bug with TIFF (memory leak with ICC profiles)
+
+May 25, 2003 - 2.6.1
++ [Detlev Vendt] added FIC_CMYK to FREE_IMAGE_COLOR_TYPE
++ [Detlev Vendt] added ICC profile support to the library (see below)
++ added FreeImage_GetICCProfile
++ added FreeImage_CreateICCProfile
++ added FreeImage_DestroyICCProfile
++ added FIICCPROFILE & FIICCPROFILE flags
++ added plugin function FreeImage_FIFSupportsICCProfiles
++ [Detlev Vendt] added ICC profile support for TIFF
++ [Herve Drolon] added XBM (X11 Bitmap Format) support : loading
+* [Herve Drolon] fixed incorrect IFF file detection (thanks Floris)
+* [Herve Drolon] fixed incorrect conversion from 1/4-bit greyscale bitmaps to 8-bit
+* [Herve Drolon] fixed a bug in TIFF writer when saving 1,4,8 bit dib (introduced in 2.6.0, sorry)
+* [Herve Drolon] fixed a palette problem in TIFF loader when loading 1-bit b & w images
+* [Herve Drolon] improved FreeImage_Dither to handle any bitdepth
+
+May 5th, 2003 - 2.6.0
+! FreeImage now uses libPNG 1.2.5
+! FreeImage now uses libMNG 1.0.5
+! [Markus Loibl] ActiveX wrapper is now distributed in a separate release (since 2.5.5)
+! [Herve Drolon] the function FreeImage_Free is now deprecated : use FreeImage_Unload instead
+! [Herve Drolon] updated the generic samples and removed deprecated functions
++ [Detlev Vendt] added CMYK support to TIFF save function
++ [Detlev Vendt] added TIFF_SAVE_CMYK flag constant
++ [Detlev Vendt] added 32-bit support (with transparency handling) to TIFF plugin
++ [Herve Drolon] added FreeImage_Threshold
++ [Herve Drolon] added FreeImage_Dither
++ [Herve Drolon] added FREE_IMAGE_DITHER parameter to FreeImage_Dither
+* [Herve Drolon] improved error handling in PluginMNG
+* [Herve Drolon] improved TIFF flags handling in TIFF save function
+* [Herve Drolon] fixed a potential crash-problem in FreeImage_OutputMessage (in case of a null message)
+* [Detlev Vendt] fixed a bug with the deprecated FreeImage_GetBitsRowCol (trailling backslash behind the DEPRECATE macro)
+
+July 24th, 2002 - 2.5.5
+! FreeImage now uses libPNG 1.2.4
+! FreeImage now uses libMNG 1.0.4
++ [Markus Loibl] added ActiveX wrapper
+
+June 22th, 2002 - 2.5.4
+* [Timothy Roughton] fixed FreeImage not compiling on LCC WIN32
+* [Markus Loibl] fixed PluginTIFF sometimes saving with wrong X/Y resolution
+* fixed crashbug when loading some RLE4 BMPs
+! FreeImage now uses LibPNG 1.2.3
+! [Markus Loibl] improved startup plugin locate handling code
+! [Gerhard Gruber] made some changes so that FreeImage compiles on VC5
++ [Markus Loibl] added flags TIFF_PACKBITS, TIFF_DEFLATE, TIFF_ADOBE_DEFLATE and TIFF_NONE
+
+May 21th, 2002 - 2.5.3
+* fixed wrong colors when loading 16-bit grayscale TIFF
+* fixed crash-problem with FreeImageQt
+* fixed PluginTIFF saving some bitmaps flipped vertically
+* [Laurent Rocher] fixed bug in FreeImage_GetLockedPageNumbers
+* [Laurent Rocher] fixed bug in FreeImage_UnlockPage
+! FreeImage now uses libpng 1.2.2
++ added TARGA save support
++ added BMP RLE8 save support
+
+March 30th, 2002 - 2.5.2
+* fixed bug in PluginTARGA where 32-bit bitmaps are not always correctly flipped
+* fixed FreeImage_GetLockedPageNumber being mentioned in FreeImage.h
+* fixed crash bug when handling read-only multipage bitmaps
+- removed internal function FreeImage_GetExtraDataPointer
+! FreeImage now uses zlib 1.1.4
++ added function FreeImage_GetLockedPageNumbers
+
+March 2nd 2002 - 2.5.1
+* fixed pluginTIFF not being able to save 32-bit bitmaps
+* fixed not being able to save PNM bitmaps through the LoadXXX wrappers
+* fixed a webcam generated BMP image being loaded with wrong colors
+! FI_ReadProc, FI_WriteProc, etc. do now carry the DLL_CALLCONV flag
+! the function FreeImage_GetBitsRowCol is now deprecated
+! FreeImage_SetTransparencyTable now taken an integer as count parameter
+! FreeImage_IsTransparent now always returns true for 32-bit bitmaps
+! PluginPNG::Save now ignores the result of FreeImage_IsTransparent
+! PluginTIFF now converts all 32-bit bitmaps to 24-bit, until our patch
+ to fully support alpha in TIFF is applied in libtiff
++ added full multi-paging support
++ added octal and hexadecimal number support to FreeImage_OutputMessage
+
+January 3rd 2002 - 2.5.0
+* fixed bug in FreeImage_SaveJPEG
+* fixed bug in FreeImage_LoadMNG
+* fixed bug in FreeImage_LoadPNG
+* fixed small Visual C++ 5.0 compiler issue in PluginMNG.cpp
+* fixed FreeImage crashing on JPEG 6.0 encoded TIFFs
+! FreeImage now uses libTIFF 3.5.7
+! FreeImage now uses libPNG 1.2.1
+! all the FreeImage_LoadXXX and FreeImage_SaveXXX functions are now deprecated
++ added Dr. Halo (*.cut) support
++ added printf-like format string support to SetOutputMessage
++ added basic multi-paging support: open, close, counting and grabbing
++ added deprecation manager
++ added FreeImage_Clone function
+
+October 3rd 2001 - 2.4.2
+* fixed missing BI_BITFIELDS support for 32-bit BMPs
+* fixed bug in FreeImage_ConvertLine16_555_To16_565 and vice versa
+* fixed bug in FreeImage_ConvertToRawBits
+* fixed PluginTIFF behaving incorrectly on PHOTOMETRIC_MASK images
+* fixed 16 bit TIFFs not loading correctly
+* fixed incorrect handling of CCITTFAX3 and CCITTFAX4 TIFFs
+* fixed JPEG encoded TIFFs not being supported
+! [Yours Detlev] patched libTIFF to handle EXTRASAMPLE_UNSPECIFIED
+! [Juergen Riecker] improved speed of PCX loading a lot
+! rewrote parts of FreeImage to improve support for c
+! the internal RGB555 and RGB565 macros now read BGR instead of RGB
+! FreeImage now uses libMNG 1.0.3
+! FreeImage now uses libPNG 1.2.0
+! FreeImage_Save now opens files with the "w+b" flag
+! renamed internal macro CalculateUsedColors to CalculateUsedPaletteEntries
+! enabling/disabling plugins no longer has effect on FIFSupportsReading
+! enabling/disabling plugins no longer has effect on FIFSupportsWriting
++ added flag PNG_IGNOREGAMMA
++ added function FreeImage_FIFSupportsExportBPP
+
+July 30th 2001 - 2.4.1
+* [Jan Nauta] fixed some plugin ids not being passed to plugins
+* [Jan Nauta] fixed some functions being natively called instead of indirect
+* [Jan Nauta] fixed BMPs with signature BA not being regognised
+* [Remo Eichenberger] fixed memory leak in the plugin system
+* fixed seek bug in PluginIFF's Validate
+* fixed transparency issue in PluginPNG
+* fixed uncaught exceptions in WUQuantizer and NNQuantizer
+* fixed some problems with PluginTARGA
+* fixed some problems with PluginICO
+* fixed some problems with PluginBMP
+! improved FreeImageQt's load function a little
+! tell/seek control for validation is now handled inside the plugin framework
+
+July 22th 2001 - 2.4.0
+* (Yours Detlev) fixed memory leak in FreeImage_GetFIFFromFilename
+* (Yours Detlev) fixed memory leak in the ICO plugin
+* (Yours Detlev) fixed memory leak in the PNG plugin
+* fixed potential NULL-pointer access bug in Plugin::AddNode
+* fixed problems with linking the static lib
+- removed LBM plugin. Its functionality is placed in the IFF plugin now
+- removed FreeImage_GetFIFByIndex
+! FreeImage now uses LibMNG 1.0.2
+! FreeImage_SetTransparent now only enables alpha when the bitmap is 8 or 32 bit
+! FreeImage_SetTransparencyTable now only enables alpha when the bitmap is 8 bit
+! FreeImage_LoadLBM now uses Mark Sibly's IFF plugin
+! FreeImage_SaveBMP now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SaveJPEG now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SavePNM now converts to 24-bit when bpp is 32 and transparency is off
+! FreeImage_SaveTIFF now converts to 24-bit when bpp is 32 and transparency is off
++ [Mark Sibly] added IFF (ILBM) support
++ added basic support for Photoshop files
++ added mime type support (FreeImage_GetFIFFromMime)
++ added functions FreeImage_SetPluginEnabled and FreeImage_IsPluginEnabled
+ Disabling plugins modifies the behaviour of the following functions:
+ * FreeImage_LoadFromHandle
+ * FreeImage_SaveToHandle
+ * FreeImage_FIFSupportsReading
+ * FreeImage_FIFSupportsWriting
+ * FreeImage_GetFIFFromFormat
+ * FreeImage_GetFIFFromFilename
+ * FreeImage_GetFIFFromMime
+ * FreeImage_Validate
+
+June 30th 2001 - 2.3.2
+* fixed missing "targa" extension in targa extension list
+* fixed small memory leak in PluginList::AddNode
+* fixed 32 bit PNG saving suddenly disappeared from the distro?
+* fixed 'black line' bug in LoadTARGA
+- removed project FreeImageM2
+- removed FreeImage_Combine
+! FreeImage_RegisterLocalPlugin now receives a FI_InitProc as first parameter
+! FreeImage_GetFIFFromFilename now also takes the format id into account
+! cleanup up the code a little for PluginPCD and PluginPCX
++ added static lib project
+
+June 11th 2001 - 2.3.1
+* [Machiel ten Brinke] fixed the loading of some 'ancient' TARGAs
+* [Rui Lopes] fixed some bugs in the external plugin registration
+* fixed the plugin system crashing when the init function isn't called
+- removed project FreeImagePy
+- removed 32 to 24 bit conversion while saving PNG in FreeImageQt
+! the scanline convert functions are now accessable in plugins
+! FreeImage now uses an STL map to store the plugin list
+! PluginSDK.h is now integrated into FreeImage.h
+! FreeImage_Register now receives the boolean parameter 'load_local_plugins_only'
+! FreeImage now uses LibPNG 1.0.12
++ [Rui Lopes] added plugin for GIF reading/writing support
++ added function FreeImage_SetTransparencyCount
++ added support for 32 bit PNG saving
++ added FreeImage_RegisterLocalPlugin to allow plugins inside apps
++ added FreeImage_RegisterExternalPlugin to manually load DLLs
++ added plugin for JBIG reading/writing support
+
+May 4th 2001 - 2.3.0
+* [Martin Weber] fixed some small bugs in the TARGA and BMP plugins
+* [Martin Weber] fixed tiny bug in new 16 bit conversions
+* [Martin Weber] fixed load flag inconsistency in the TARGA plugin
+* [Martin Weber] fixed plugin id / load reference inconsistency for PNM
+* [Jan Nauta] fixed bug in conversion 16 -> 16
+* [Herve Drolon] fixed small bug in 4-bit PCX loader
+- removed code that loads BMPs renamed to ICO in PluginICO
+! the flag TARGA_LOAD_RGB555 is now obsolete
+! the plugin list is now sorted internally
+! ConvertTo32Bits now stores the transparency table as alpha mask
+! FreeImage now uses LibMNG 1.0,1
+! FreeImage now uses LibPNG 1.0.11
++ added external plugin support via DLLs
++ added function FreeImage_GetFIFByIndex
++ added internal function CalculateScanLine
++ added transparency support for high-color PNGs
++ added transparency support for high-color TIFFs
++ added functions FreeImage_SetTransparent and FreeImage_IsTransparent
++ added constant FIC_RGBALPHA to FREE_IMAGE_COLOR_TYPE
+
+April 5th 2001 - 2.2.0
+* [Remo Eichenberger] fixed small bug concerning DLLMain and static LIB generation
+* fixed 1-bit bitmaps not properly loading in FreeImageQt
+* fixed bug in conversion 16->16
+* FreeImage now uses LibPNG 1.0.10
+! [Martin Weber] improved loading of BMP files
+! [Martin Weber] improved loading of TARGA files
+! [Dave Larson] improved visual appearance after 16 conversions
+! FreeImageQt now converts 32-bit bitmaps to 24-bit when saving PNGs and JPEGs
++ added functions FreeImage_Initialise and FreeImage_DeInitialise
++ added internal plugins
++ re-added combine/alphablend functions
+
+March 8th 2001 - 2.1.0
+* [Martin Hemming] fixed bug in 16-bit TARGA loading code
+* fixed PNG's with alpha masks not loading correctly
+! FreeImage is now dual-licensed: the FI-License and the GPL license
+! FreeImage now uses LibPNG 1.0.9
+! FreeImage now uses LibTIFF 3.5.6 Beta
+! FreeImage now uses LiBMNG 1.0.0
+! changed the ordering of the FREE_IMAGE_FORMAT table
+! improved linux support
+! improved test script
++ added transparency table support to SavePNG
++ added BI_BITFIELDS support to LoadBMP and SaveBMP
++ added reading support for OS/2 2.x BMPs
++ added support for MNG and JNG reading using LibMNG
++ added support for Deluxe Paint reading
++ added 'hot swap' support to the Core DLL
++ added 'hot swap' support to FreeImage Qt
++ added functions GetFIFFromFormat and GetFIFFromFilename
++ added functions FIFSupportsReading and FIFSupportsWriting
++ added function GetFIFRegExpr
+
+January 14th 2001 - 2.0.0
+* [Herve Drolon] fixed a bug in the conversion 4->8
+* [Herve Drolon] fixed a bug in metrics handling in SaveJPEG
+* [Herve Drolon] fixed a bug in the return value of the function SaveTIFF
+* fixed the presence of two WuQuantizer.cpp files in the distribution
+* fixed bug where a BMP renamed to ICO isn't loaded
+- removed FreeImage_ConvertToGreyScale. Use FreeImage_ConvertTo8Bits instead.
+- removed the boolean parameters from all conversion routines
+- removed page handling in LoadTIFF. A new range of functions will be added.
+! The void pointers used in FreeImage are now typed
+! LoadBMP now takes palettes in 24/32 bit images in respect
+! All effects and MMX functions are now stored in a new library (FreeEffects)
+! [Herve Drolon] fixed bug in FreeImage_GetColorType
+! [Herve Drolon] improved PCX loader. It can now read 1, 4, 8 and 24-bit images
+! [Manfred Tausch] improved FreeImage_Rotate
+! [Luca Piergentili] fixed crash bug when saving some 1-bit TIFFs
+! rewrote all bitdepth conversion routines making use of the new scanline converters
+! rewrote bitdepth conversion in FreeImageQt (uses less memory)
+! FreeImage is now compiled __stdcall
++ [Herve Drolon] added WBMP (Wireless Bitmap Format) support: loading and saving
++ [Herve Drolon] added 4, 16 and 32 bitdepth handling in GetColorType
++ [Herve Drolon] added handling of 8-bit greyscale bitmaps in SaveJPEG
++ [Herve Drolon] added NeuQuant color reduction algorithm to ColorQuantize
++ added DLL_CALLCONV (calling convention) flag
++ added bitmask support to all bitmaps
++ added a series of functions converting scanlines from one bitdepth to another
++ added functions ConvertFromRawBits and ConvertToRawBits
++ added project FreeImageM2: Magenta II MMT bindings for FreeImage
++ added basic foundation for linux support
+
+December 2th 2000 - 1.4.4
+* fixed small bug related to TIFFSetDirectory in FreeImage_LoadTIFF
+* fixed FreeImage_Rotate sometimes clipping too much pixels
+* fixed other small bug in FreeImage_Rotate
+* fixed FreeImage_Clone not taking the FREEIMAGEHEADER in account
+* fixed bug in FreeImageQt where 1-bit images are not correctly allocated
+* fixed FreeImage_Crop not copying the palette
+* fixed message function pointer crash bug
+* fixed bug where the palette wasn't copied when saving in FreeImageQt
+* fixed FreeImage_Clone not copying the transparency table
+- removed FreeImage_WritePaletteEntry
+! [Adam Gates] rewrote parts of FreeImage so that c compilers can handle it better
+! FreeImageQt doesn't statically link with the FreeImage lib anymore
+! FreeImageQt now uses atexit() to automatically unregister
+! rewrote parts of FreeImage_LoadBMP to increase speed
++ [Markus Loibl] added metrics handling code to LoadBMP, LoadJPEG, LoadTIFF and LoadPCX
++ added metrics handling code to FreeImageQt
++ added functions FIQT_IsLoaded, FIQT_GetVersion and FIQT_GetCopyrightMessage
++ added conversion 1 -> 16
++ added FreeImage_SaveJPEG and JPEG quality settings
++ added FreeImage_GetBitsRowCol
++ added function FIQT_SetOutputMessage to FreeImageQt
++ added FreeImage_GetFileTypeFromExtension and FIQT_GetFileTypeFromFormat
++ added project FreeImagePy: python bindings for FreeImage
+
+November 7th 2000 - 1.4.3
+* fixed FreeImage_SavePNG crash bug
+* fixed slighly corrupt size filter in FreeImage_Combine
+* fixed FreeImage_SaveTIFF not saving 4-bit images
+* [Herve Drolon] fixed bug in FreeImage_LoadTIFF
+* [Herve Drolon] fixed bug in FreeImage_GetColorType
+- removed fclose from FreeImage_SavePNM (who put it there?)
+! rewrote FreeImage_Rotate
+! FreeImageQt now automatically detects which formats are supported by Qt and which not
+! FreeImage_Allocate now returns a void pointer
+! FreeImage_Unload is now called FreeImage_Free
++ added 16-bit 5-5-5 support to FreeImage_LoadBMP
++ added RLE_DELTA support to FreeImage_LoadBMP
++ added directory support to FreeImage_LoadTIFF
++ added functions dealing with transparency
++ added transparency support to 8-bit PNG's in Qt
++ added FREE_IMAGE_QUANTIZE parameter to FreeImage_ColorQuantize
++ added custom FREEIMAGEHEADER header prepended to internal bitmaps
++ added new documentation
+
+October 18th 2000 - 1.4.2
+* fixed FreeImage_SaveBMP storing an incorrect bfSize value in the BITMAPFILEHEADER
+* fixed bug where JPEG and PNG wouldn't load in FreeImageQt
+* fixed FreeImage_Mirror mirroring one pixel less than needed
+! FreeImage_MaskedCombine24 is now called FreeImage_MaskedCombine24Ex
+! FreeImage_MaskedCombine32 is now called FreeImage_MaskedCombine32Ex
++ added 16-bit bitmap support to FreeImage_Mirror
++ added 16-bit bitmap support to FreeImage_ConvertTo8Bits
++ added simple version of FreeImage_MaskedCombine24
++ added simple version of FreeImage_MaskedCombine32
+
+October 17th 2000 - 1.4.1
+* [Herve Drolon] fixed bug in FreeImage_ConvertTo8Bits
+* fixed bug in conversion with 16 -> 24 and 16 -> 32
+- removed static library support
+- removed all unnecessary files from LibTIFF, LibPNG, LibJPEG and ZLib
+- removed all absolute seeks from the library
+! FreeImageQt now makes use of the DLL distro
+! rebuilt the entire directory structure
+! improved handling of BMP
+! renamed FreeImage_MaskedCombine to FreeImage_MaskedCombine32
++ [Alexander Dymerets] added 24-bit masked alpha blending with a seperate alpha mask
++ added FreeImage_Rotate (known bug in degrees 76 to 106)
++ added 4-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 8-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 32-bit bitmap support to FreeImage_ConvertTo16Bits
++ added 32-bit bitmap support to FreeImage_Mirror
++ added 16-bit 5-5-5 support to FreeImage_ConvertTo24Bits
++ added 16-bit 5-5-5 support to FreeImage_ConvertTo32Bits
+
+October 2th 2000 - 1.4.0
+* [Jani Kajala] fixed bug in conversion with 4 -> 24 and 8 -> 32
+* [Jani Kajala] fixed bug in FreeImage_Flip
+* [Jani Kajala] fixed minor bug in FreeImage_LoadBMP
+- [Herve Drolon] removed PBMFlags, PGMFlags and PPMFlags
+- [Herve Drolon] removed FI_LoadGeneric
+- removed FreeImage_Win32.h
+! [Herve Drolon] changed FI_GetFileType
+! [Herve Drolon] replaced FI_LoadPBM, FI_LoadPGM and FI_LoadPPM with FI_LoadPNM
+! [Herve Drolon] improved FreeImage_LoadPNG
+! FreeImage_WritePaletteEntry is now exported
++ [Herve Drolon] added FreeImage_SavePNG
++ [Herve Drolon] added FreeImage_SavePNM and PNMFlags
++ [Herve Drolon] added XXXFlags parameter to save functions
++ [Herve Drolon] added FreeImage_LoadRAS and FIF_RAS
++ added FreeImage_GetFileTypeFromExt
+
+September 7th 2000 - 1.3.5
++ added conversion 4 -> 8 to FI_ConvertTo8Bits
++ added simple version of FI_GetFileType
++ added project FreeImageQt; a port of the library to the TrollTech library
+
+August 31th 2000 - 1.3.4
+* fixed 'ice effect' bug in new 24 bit PCX code
+* fixed some bugs with the conversion 16 -> 24 and 16 -> 32
+! FI_Blur now returns void
+! A debug build of the library now produces FreeImaged.dll and FreeImaged.lib
+! TARGA_LOAD_ARGB8888 is now called TARGA_LOAD_RGB888
+! Alpha channels are now automatically loaded unless TARGA_LOAD_RGB888 is specified
+! cleaned up the code a lot
++ added 32-bit bitmap support to FreeImage_ConvertToGreyscale
++ added support for 32-bit bottom-left TARGA images
++ added internal functions FreeImage_WritePaletteEntry() and FreeImage_GetScanLine()
++ added FreeImage_Win32.h, containing Windows functions needed to create DIBs
++ added documentation through Doxygen
+
+July 30th 2000 - 1.3.3
+* [Jani Kajala] fixed some bugs with the conversion 4 -> 24 and 8 -> 24
+* [Jani Kajala] fixed some bugs with the conversion 4 -> 32 and 8 -> 32
+* fixed bug in FI_LoadPNM's ASCII number loader
+! [Herve Drolon] improved FI_LoadPNG
+! [Herve Drolon] changed FI_ConvertToGreyScale (added changeable macro for conversion)
+! improved FI_ConvertTo24Bits
+! improved FI_ConvertTo32Bits
+! freeImage now uses LibPNG 1.0.8
++ [Herve Drolon] added FI_ColorQuantize, based on Wu's color quantizer
++ added the conversion 1 -> 24
++ added the conversion 1 -> 32
++ added FI_ConvertTo8Bits
++ added FI_Invert (very useful for image processing)
++ added FI_GetColorType and 'enum FREE_IMAGE_COLOR_TYPE'
+
+June 30th 2000 - 1.3.2
+- removed color reduction functions from the project
+! [Herve Drolon] Improved FI_LoadTIFF code
+! renamed FI_ToGrayscale to FI_ConvertToGreyScale
+! renamed FI_IncreaseColors to FI_ConvertTo24Bits
+! LoadBMP now supports 32-bit bitmaps
+! [Jani Kajala] Improved FI_LoadTARGA and FI_LoadPCX code
++ added FI_ConvertTo32Bits to convert a bitmap to 32-bit
++ added FI_MaskCombine to combine two 32-bit bitmaps using a alpha mask
++ added FI_AddAlphaMask to enrich a 32-bit bitmap with an alpha mask
++ added FI_SaveTIFF
++ added 16-bit bitmap (565) support to the ConvertToXXX functions.
++ added FI_ConvertTo16Bits (555 and 565)
+
+June 1th 2000 - 1.3.1
+- removed Standard Template Library (STL) code
+* [Jani Kajala] fixed minor bug in FI_LoadTARGA
+* [Jani Kajala] fixed some minor bugs in FI_LoadPCX
+! streamlined FI_LoadJPEG a little
+! FreeImage now uses LibPNG 1.0.6
+! FreeImage now uses LibTIFF 3.5.5
+! FreeImage now uses malloc and free instead of new and delete
++ introduced compiler flags to disable certain features in the DLL
++ added experimental nearest color reduction (FI_ReduceColorsNearestColor)
+
+April 13th 2000 - 1.3.0
+* fixed some 8 bit PCX files loading incorrectly
+* fixed tiny bug in internally used CalculateUsedColors function
+- removed FI_SaveXPM. Only BMP is supported now.
+- removed Windows dependencies for easier porting
+! optimized FI_LoadKOALA a little
+! optimized FI_Combine using MMX technology
+! FI_Combine now receives an 'unsigned integer' as alpha blend parameter
+! FI_InCreaseColors and FI_ReduceColors don't dispose the old bitmap anymore
++ added PNM support (PGM, PPM and PBM; both binary and ascii)
++ [Alexander Dymerets] added FI_EnableMMX and FI_DisableMMX
++ added various effect functions (FI_Blur, FI_Brighten and FI_Crop)
+
+March 1st 2000 - 1.2.1
+* fixed some 24 bit PCX files loading incorrectly
+
+February 8th 2000 - 1.2.0
+* fixed last bitmap data block in JPEG files being truncated
+* fixed 4/8 bit BMP's incorrectly loading when the palette is smaller than the bitcount predicts
+- removed FI_Load. There is no reliable way to identify all image formats
+- removed FI_SetJpegDecodeMode.
+ Mode selection is now done using the 'DataEnum data' parameter of FI_LoadJPEG
+! read_proc/write_proc/tell_proc in FreeImageIO now are same as fread/fwrite/ftell
++ added a 'DataEnum data' parameter to all FI_LoadXXX functions.
++ added 16 bit TARGA support
++ added RLE support for TARGA images
++ added FI_GetDIBSize to get the size of a DIB in bytes
++ added Kodak PhotoCD support (Base, Base/4 and Base/16 encoding)
++ added KOALA support
++ added FI_GetFileType. Note: there is no reliable way to identify TARGA, ICO and PCD. Therefore they have been excluded
+In KOALA files only the files converted by a C64 emulator can be identified.
++ added FI_Combine to combine two 24-bit bitmaps with (optional) alpha blending
+
+January 15th 2000 - 1.1.1
+! FI_Copy is now called FI_Clone
++ added FI_ToGrayscale to convert a color bitmap to grayscale
++ added 32 bit TARGA support
++ added FI_IncreaseColors to increase the bitmap bitdepth from 4/8 bit to 24 bit
+
+January 14th 2000 - 1.1.0
+* FI_MIRROR: fixed nibbles not being mirrored in 4 bit images
+* FI_MIRROR: fixed bits not being mirrored in 1 bit images
+* fixed improper loading of 1, 4 and 8 bit OS/2 BMP's
+* fixed some inconsistensies in the calculation of lines and pitches
+* fixed incorrectly loading of Huffman and FAX encoded TIFFs
+* fixed LoadTGA accepting 16 bit TGA's and returning corrupt DIB's
+- removed LZW support for TIFFs
+! FreeImage now uses LibTIFF 3.5.4
++ added ICO support
++ added overridable file I/O support in the form of FreeImageIO and fi_handle
++ added FI_Load for generic image loading
++ added FI_ReduceColors for color reduction
++ added FI_Copy to copy a bitmap in memory
+
+January 5th 2000 - 1.0.0
diff --git a/Wrapper/Delphi/WhatsNew_Delphi.txt b/Wrapper/Delphi/WhatsNew_Delphi.txt
new file mode 100644
index 0000000..d225da0
--- /dev/null
+++ b/Wrapper/Delphi/WhatsNew_Delphi.txt
@@ -0,0 +1,71 @@
+What's New for FreeImage Delphi Wrapper
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+July 17, 2006
++ [Hervé Drolon] added FIF_FAXG3 and FIF_SGI definitions, added FreeImage_MakeThumbnail definition.
+
+January 20, 2006
+! [Anatoliy Pulyaevskiy] updated WinBitmap demo
+* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.ConvertToStandartType renamed to TFreeBitmap.ConvertToStandardType
+* [Anatoliy Pulyaevskiy] fixed using of SetFreeImageMarker (only for HDR dib)
+
+October 19, 2005
++ [Anatoliy Pulyaevskiy] updated wrapper for FreeImage 3.8.0
++ [Anatoliy Pulyaevskiy] added Delphi 5 support
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.OnChanging event
+! [Anatoliy Pulyaevskiy] changed declaration of TFreeBitmap.Assign method
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.CanSave function
+! [Anatoliy Pulyaevskiy] property TFreeBitmap.Dib now have read/write access
++ [Anatoliy Pulyaevskiy] added TFreeTag class incapsulating FreeImage FITAG type
+
+August 5, 2005
+* [kaare-nysite] fixed the prototype of FreeImage_ConvertFromRawBits
+
+June 21, 2005
+* [Maarten Veerman] fixed the prototype of FreeImage_OpenMultiBitmap
+
+February 17, 2005 - Version 1.3.0
++ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.6.0
+! [Anatoliy Pulyaevskiy] FreeImage.pas unit has been reworked
+
+January 14, 2005 - Version 1.2.1
++ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.3
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.SetHorizontalResolution and TFreeBitmap.SetVerticalResolution
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.MakeThumbnail procedure ( an adapted version of function given by Enzo Costantini)
++ [Enzo Costantini] added FIU_GetFIFType utility function
++ [Enzo Costantini] added TFreeWinBitmap.CopyToBitmapH function
+* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.Rotate (fix from FreeImage CVS)
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.ConvertToStandartType
+
+December 20, 2004 - Version 1.2.0
++ [Anatoliy Pulyaevskiy] added MultiBitmap Demo
+* [Anatoliy Pulyaevskiy] fixed TFreeMultiBitmap.LockPage due to error with Locking/Unlocking pages
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.ConvertTo4Bits
+* [Anatoliy Pulyaevskiy] TFreeBitmap.ConvertToGrayScale fixed converting bitmaps with FIC_MINISWHITE color type
+* [Anatoliy Pulyaevskiy] fixed TFreeWinBitmap.DrawEx FDisplayDib deleting
++ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.2
+
+November 12, 2004 - Version 1.1.0
++ [Anatoliy Pulyaevskiy] added TFreeBitmap.Assign(Source: PFIBITMAP)
+- [Anatoliy Pulyaevskiy] removed TFreeBitmap.SetDib
+! [Anatoliy Pulyaevskiy] TFreeBitmap.Dib property now read-only
+* [Anatoliy Pulyaevskiy] TFreeMultiBitmap.UnlockPage implemented
+* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.Rescale not applies changes
+
+November 8, 2004 - Version 1.0.0
++ [Anatoliy Pulyaevskiy] added Delphi version of FreeImagePlus
++ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.0
+
+January 7, 2004
++ [Tommy] added TargaImage unit
+
+October 28, 2003
++ [Peter Byström] updated the wrapper for FreeImage 3.0.2
+
+August 9, 2003
++ [Simon Beavis] added a wrapper for FreeImage 2.6.1
+
diff --git a/Wrapper/Delphi/_clean.bat b/Wrapper/Delphi/_clean.bat
new file mode 100755
index 0000000..43924b0
--- /dev/null
+++ b/Wrapper/Delphi/_clean.bat
@@ -0,0 +1,13 @@
+del /S *.~*
+del /S *.dcu
+del /S *.dsk
+del /S *.cfg
+del /S *.dof
+del /S *.obj
+del /S *.hpp
+del /S *.ddp
+del /S *.mps
+del /S *.mpt
+del /S *.bak
+del /S *.exe
+del /S *.stat \ No newline at end of file
diff --git a/Wrapper/Delphi/demo/ImagePreview/ImagePreview.dpr b/Wrapper/Delphi/demo/ImagePreview/ImagePreview.dpr
new file mode 100644
index 0000000..79fc38b
--- /dev/null
+++ b/Wrapper/Delphi/demo/ImagePreview/ImagePreview.dpr
@@ -0,0 +1,13 @@
+program ImagePreview;
+
+uses
+ Forms,
+ MainFrm in 'MainFrm.pas' {MainForm};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.CreateForm(TMainForm, MainForm);
+ Application.Run;
+end.
diff --git a/Wrapper/Delphi/demo/ImagePreview/MainFrm.dfm b/Wrapper/Delphi/demo/ImagePreview/MainFrm.dfm
new file mode 100644
index 0000000..d8cf90f
--- /dev/null
+++ b/Wrapper/Delphi/demo/ImagePreview/MainFrm.dfm
@@ -0,0 +1,135 @@
+object MainForm: TMainForm
+ Left = 304
+ Top = 165
+ Width = 467
+ Height = 405
+ Caption = 'Image Preview'
+ Color = clWhite
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'MS Sans Serif'
+ Font.Style = []
+ KeyPreview = True
+ OldCreateOrder = False
+ Position = poDesktopCenter
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnKeyUp = FormKeyUp
+ OnMouseWheel = ScrollBoxMouseWheel
+ OnShow = FormShow
+ PixelsPerInch = 96
+ TextHeight = 13
+ object ImgView32: TImgView32
+ Left = 0
+ Top = 0
+ Width = 459
+ Height = 371
+ Align = alClient
+ ParentShowHint = False
+ PopupMenu = PopupMenu
+ Scale = 1
+ ScrollBars.Color = clScrollBar
+ ScrollBars.ShowHandleGrip = True
+ ScrollBars.Style = rbsDefault
+ ShowHint = True
+ SizeGrip = sgAuto
+ TabOrder = 0
+ OnScroll = ImgView32Scroll
+ object AlphaView: TImgView32
+ Left = 8
+ Top = 8
+ Width = 161
+ Height = 145
+ Scale = 1
+ ScrollBars.Color = clScrollBar
+ ScrollBars.ShowHandleGrip = True
+ ScrollBars.Style = rbsDefault
+ SizeGrip = sgAuto
+ TabOrder = 2
+ Visible = False
+ end
+ end
+ object PopupMenu: TPopupMenu
+ Left = 304
+ Top = 28
+ object ZoomInItem: TMenuItem
+ Caption = 'Zoom In'
+ OnClick = ZoomInItemClick
+ end
+ object ZoomOutItem: TMenuItem
+ Caption = 'Zoom Out'
+ OnClick = ZoomOutItemClick
+ end
+ object ActualSizeItem: TMenuItem
+ Caption = 'Actual Size'
+ OnClick = ActualSizeItemClick
+ end
+ object N1: TMenuItem
+ Caption = '-'
+ end
+ object RotateClockwiseItem: TMenuItem
+ Caption = 'Rotate Clockwise'
+ OnClick = RotateClockwiseItemClick
+ end
+ object RotateAntiClockwiseItem: TMenuItem
+ Caption = 'Rotate Anti-Clockwise'
+ OnClick = RotateAntiClockwiseItemClick
+ end
+ object N4: TMenuItem
+ Caption = '-'
+ end
+ object FlipHorizontalItem: TMenuItem
+ Caption = 'Flip Horizontal'
+ OnClick = FlipHorizontalItemClick
+ end
+ object FilpVerticalItem: TMenuItem
+ Caption = 'Filp Vertical'
+ OnClick = FilpVerticalItemClick
+ end
+ object N3: TMenuItem
+ Caption = '-'
+ end
+ object ShowAlphaItem: TMenuItem
+ Caption = 'Show Just Alpha Channel'
+ OnClick = ShowAlphaItemClick
+ end
+ object ShowWithAlphaItem: TMenuItem
+ Caption = 'Show With Alpha Channel'
+ OnClick = ShowWithAlphaItemClick
+ end
+ object N2: TMenuItem
+ Caption = '-'
+ end
+ object OpenImageItem: TMenuItem
+ Caption = 'Open New Image'
+ OnClick = OpenImageItemClick
+ end
+ end
+ object FilterTimer: TTimer
+ Interval = 500
+ OnTimer = FilterTimerTimer
+ Left = 308
+ Top = 84
+ end
+ object OpenDialog: TOpenDialog
+ Filter =
+ 'All image files|*.bmp;*.cut;*.ico;*.iff;*.lbm;*.jng;*.jpg;*.jpeg' +
+ ';*.koa;*.mng;*.pbm;*.pcd;*.pcx;*.pgm;*.png;*.ppm;*.psd;*.ras;*.t' +
+ 'ga;*.tif;*.tiff;.wbmp;*.xbm;*.xpm)|Windows or OS/2 Bitmap File (' +
+ '*.BMP)|*.BMP|Dr. Halo (*.CUT)|*.CUT|Windows Icon (*.ICO)|*.ICO|A' +
+ 'miga IFF (*.IFF, *.LBM)|*.IFF;*.LBM|JPEG Network Graphics (*.JNG' +
+ ')|*.JNG|Independent JPEG Group (*.JPG)|*.JPG|Commodore 64 Koala ' +
+ '(*.KOA)|*.KOA|Multiple Network Graphics (*.MNG)|*.MNG|Portable B' +
+ 'itmap (*.PBM)|*.PBM|Kodak PhotoCD (*.PCD)|*.PCD|PCX bitmap forma' +
+ 't (*.PCX)|*.PCX|Portable Graymap (*.PGM)|*.PGM|Portable Network ' +
+ 'Graphics (*.PNG)|*.PNG|Portable Pixelmap (*.PPM)|*.PPM|Photoshop' +
+ ' (*.PSD)|*.PSD|Sun Rasterfile (*.RAS)|*.RAS|Targa files (*.TGA)|' +
+ '*.TGA|Tagged Image File Format (*.TIF)|*.TIF;*.TIFF|Wireless Bit' +
+ 'map (*.WBMP)|*.WBMP|X11 Bitmap Format (*.XBM)|*.XBM|X11 Pixmap F' +
+ 'ormat (*.XPM)|*.XPM'
+ Title = 'Open Image File'
+ Left = 328
+ Top = 228
+ end
+end
diff --git a/Wrapper/Delphi/demo/ImagePreview/MainFrm.pas b/Wrapper/Delphi/demo/ImagePreview/MainFrm.pas
new file mode 100644
index 0000000..df1ab8e
--- /dev/null
+++ b/Wrapper/Delphi/demo/ImagePreview/MainFrm.pas
@@ -0,0 +1,518 @@
+unit MainFrm;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, Menus, ExtCtrls, Math, GR32, GR32_Image, GR32_Transforms,
+ ExtDlgs;
+
+type
+ TMainForm = class(TForm)
+ PopupMenu: TPopupMenu;
+ ZoomInItem: TMenuItem;
+ ZoomOutItem: TMenuItem;
+ ActualSizeItem: TMenuItem;
+ ImgView32: TImgView32;
+ N1: TMenuItem;
+ AlphaView: TImgView32;
+ ShowAlphaItem: TMenuItem;
+ RotateClockwiseItem: TMenuItem;
+ RotateAntiClockwiseItem: TMenuItem;
+ N3: TMenuItem;
+ ShowWithAlphaItem: TMenuItem;
+ N4: TMenuItem;
+ FlipHorizontalItem: TMenuItem;
+ FilpVerticalItem: TMenuItem;
+ FilterTimer: TTimer;
+ OpenImageItem: TMenuItem;
+ N2: TMenuItem;
+ OpenDialog: TOpenDialog;
+ procedure FormCreate(Sender: TObject);
+ procedure FormDestroy(Sender: TObject);
+ procedure FormShow(Sender: TObject);
+ procedure ZoomInItemClick(Sender: TObject);
+ procedure ZoomOutItemClick(Sender: TObject);
+ procedure ActualSizeItemClick(Sender: TObject);
+ procedure ScrollBoxMouseWheel(Sender: TObject; Shift: TShiftState;
+ WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
+ procedure FormKeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+ procedure ShowAlphaItemClick(Sender: TObject);
+ procedure RotateClockwiseItemClick(Sender: TObject);
+ procedure RotateAntiClockwiseItemClick(Sender: TObject);
+ procedure ShowWithAlphaItemClick(Sender: TObject);
+ procedure FlipHorizontalItemClick(Sender: TObject);
+ procedure FilpVerticalItemClick(Sender: TObject);
+ procedure FilterTimerTimer(Sender: TObject);
+ procedure ImgView32Scroll(Sender: TObject);
+ procedure OpenImageItemClick(Sender: TObject);
+ private
+ { Private declarations }
+ OrigWidth : integer;
+ OrigHeight : integer;
+ BPP : longword;
+
+ procedure LoadImage( Name : string);
+ procedure RecalcWindowSize;
+ public
+ { Public declarations }
+ end;
+
+var
+ MainForm: TMainForm;
+
+implementation
+
+{$R *.dfm}
+
+uses FreeImage;
+
+// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+procedure TMainForm.FormCreate(Sender: TObject);
+begin
+ AlphaView.Visible := False;
+ AlphaView.Align := alClient;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.FormDestroy(Sender: TObject);
+begin
+ // ...
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.FormShow(Sender: TObject);
+begin
+ ImgView32.Bitmap.StretchFilter := sfSPline;
+ if ParamCount = 1 then
+ LoadImage(ParamStr(1));
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.LoadImage( Name : string);
+var
+ dib : PFIBITMAP;
+ PBH : PBITMAPINFOHEADER;
+ PBI : PBITMAPINFO;
+ t : FREE_IMAGE_FORMAT;
+ Ext : string;
+ BM : TBitmap;
+ x, y : integer;
+ BP : PLONGWORD;
+ DC : HDC;
+begin
+ try
+ t := FreeImage_GetFileType(PChar(Name), 16);
+
+ if t = FIF_UNKNOWN then
+ begin
+ // Check for types not supported by GetFileType
+ Ext := UpperCase(ExtractFileExt(Name));
+ if (Ext = '.TGA') or(Ext = '.TARGA') then
+ t := FIF_TARGA
+ else if Ext = '.MNG' then
+ t := FIF_MNG
+ else if Ext = '.PCD' then
+ t := FIF_PCD
+ else if Ext = '.WBMP' then
+ t := FIF_WBMP
+ else if Ext = '.CUT' then
+ t := FIF_CUT
+ else
+ raise Exception.Create('The file "' + Name + '" cannot be displayed because SFM does not recognise the file type.');
+ end;
+
+ dib := FreeImage_Load(t, PChar(name), 0);
+ if Dib = nil then
+ Close;
+ PBH := FreeImage_GetInfoHeader(dib);
+ PBI := FreeImage_GetInfo(dib^);
+
+ BPP := FreeImage_GetBPP(dib);
+
+ ShowWithAlphaItem.Enabled := BPP = 32;
+ ShowAlphaItem.Enabled := BPP = 32;
+
+ if BPP = 32 then
+ begin
+ ImgView32.Bitmap.SetSize(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib));
+
+ BP := PLONGWORD(FreeImage_GetBits(dib));
+ for y := ImgView32.Bitmap.Height - 1 downto 0 do
+ for x := 0 to ImgView32.Bitmap.Width - 1 do
+ begin
+ ImgView32.Bitmap.Pixel[x, y] := BP^;
+ inc(BP);
+ end;
+ end
+ else
+ begin
+ BM := TBitmap.Create;
+
+ BM.Assign(nil);
+ DC := GetDC(Handle);
+
+ BM.handle := CreateDIBitmap(DC,
+ PBH^,
+ CBM_INIT,
+ PChar(FreeImage_GetBits(dib)),
+ PBI^,
+ DIB_RGB_COLORS);
+
+ ImgView32.Bitmap.Assign(BM);
+ AlphaView.Bitmap.Assign(BM);
+
+ BM.Free;
+ ReleaseDC(Handle, DC);
+ end;
+ FreeImage_Unload(dib);
+
+ OrigWidth := ImgView32.Bitmap.Width;
+ OrigHeight := ImgView32.Bitmap.Height;
+
+ Caption := ExtractFileName( Name ) + ' (' + IntToStr(OrigWidth) +
+ ' x ' + IntToStr(OrigHeight) + ')';
+ if BPP = 32 then
+ Caption := Caption + ' + Alpha';
+
+ AlphaView.Bitmap.SetSize(OrigWidth, OrigWidth);
+
+ ImgView32.Hint := 'Name: ' + Name + #13 +
+ 'Width: ' + IntToStr(OrigWidth) + #13 +
+ 'Height: ' + IntToStr(OrigHeight) + #13 +
+ 'BPP: ' + IntToStr(BPP);
+
+ RecalcWindowSize;
+
+ Show;
+ except
+ on e:exception do
+ begin
+ Application.BringToFront;
+ MessageDlg(e.message, mtInformation, [mbOK], 0);
+ Close;
+ end;
+ end;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ZoomInItemClick(Sender: TObject);
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+
+ ImgView32.Scale := ImgView32.Scale * 2.0;
+ RecalcWindowSize;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ZoomOutItemClick(Sender: TObject);
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+
+ ImgView32.Scale := ImgView32.Scale / 2.0;
+ RecalcWindowSize;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ActualSizeItemClick(Sender: TObject);
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+
+ ImgView32.Scale := 1.0;
+
+ RecalcWindowSize;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.RecalcWindowSize;
+var
+ Rect : TRect;
+ CW, CH : integer;
+ WSH, WSW : integer;
+ TitleH : integer;
+ BorderY : integer;
+ BorderX : integer;
+begin
+ CW := ImgView32.Bitmap.Width + GetSystemMetrics(SM_CXVSCROLL);
+ CH := ImgView32.Bitmap.Height + GetSystemMetrics(SM_CYVSCROLL);
+
+ SystemParametersInfo( SPI_GETWORKAREA, 0, @Rect, 0);
+
+ WSH := Rect.Bottom - Rect.Top;
+ WSW := Rect.Right - Rect.Left;
+ TitleH := GetSystemMetrics(SM_CYCAPTION);
+ BorderY := GetSystemMetrics(SM_CYSIZEFRAME) * 2;
+ BorderX := GetSystemMetrics(SM_CXSIZEFRAME) * 2;
+
+ if (Top + CH + TitleH + BorderY > WSH) or (CH + TitleH + BorderY > WSH) then
+ begin
+ Top := Rect.Bottom - CH - BorderY;
+ if Top < 0 then
+ begin
+ Top := 0;
+ CH := WSH - TitleH - BorderY;
+ CW := CW + GetSystemMetrics(SM_CXVSCROLL);
+
+ if CW + BorderX > WSW then
+ CH := CH - GetSystemMetrics(SM_CYVSCROLL);
+ end;
+ end;
+
+ if (Left + CW + BorderX > WSW) or (CW + BorderX > WSW) then
+ begin
+ Left := Rect.Right - CW - BorderX;
+ if Left < 0 then
+ begin
+ Left := 0;
+ CW := WSW - BorderX;
+ CH := CH + GetSystemMetrics(SM_CYVSCROLL);
+
+ if CH + TitleH + BorderY > WSH then
+ CW := CW + GetSystemMetrics(SM_CXVSCROLL);
+ end
+ end;
+
+ ClientWidth := CW;
+ ClientHeight := CH;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ScrollBoxMouseWheel(Sender: TObject;
+ Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
+ var Handled: Boolean);
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+
+ if WheelDelta < 0 then
+ ImgView32.Scroll(0, 20)
+ else
+ ImgView32.Scroll(0, -20);
+ Handled := True;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word;
+ Shift: TShiftState);
+var
+ Amount : integer;
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+
+ if ssShift in Shift then
+ Amount := 20 * 2
+ else
+ Amount := 20;
+
+ case Key of
+ VK_ESCAPE:
+ Close;
+ VK_UP:
+ ImgView32.Scroll(0, -Amount);
+ VK_DOWN:
+ ImgView32.Scroll(0, Amount);
+ VK_LEFT:
+ ImgView32.Scroll(-Amount, 0);
+ VK_RIGHT:
+ ImgView32.Scroll(Amount, 0);
+ VK_HOME:
+ ImgView32.ScrollToCenter(0, 0);
+ VK_END:
+ ImgView32.ScrollToCenter(ImgView32.Bitmap.Width, ImgView32.Bitmap.Height);
+ VK_NEXT:
+ ImgView32.Scroll(0, (Trunc(ImgView32.Bitmap.Height div 4)));
+ VK_PRIOR:
+ ImgView32.Scroll(0, -(Trunc(ImgView32.Bitmap.Height div 4)));
+ end;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ShowAlphaItemClick(Sender: TObject);
+var
+ x, y : integer;
+ Col : TColor32;
+ Alpha : TColor;
+begin
+ if ShowAlphaItem.Checked then
+ begin
+ AlphaView.Visible := False;
+ AlphaView.Bitmap.Delete;
+ end
+ else
+ begin
+ AlphaView.Bitmap.Width := ImgView32.Bitmap.Width;
+ AlphaView.Bitmap.Height := ImgView32.Bitmap.Height;
+
+ for x := 0 to AlphaView.Bitmap.Width - 1 do
+ for y := 0 to AlphaView.Bitmap.Height - 1 do
+ begin
+ Col := ImgView32.Bitmap.Pixel[x, y];
+ Alpha := Col shr 24;
+ AlphaView.Bitmap.Pixel[x, y] := Alpha + (Alpha shl 8) + (Alpha shl 16);
+ end;
+ AlphaView.Visible := True;
+ end;
+ ShowAlphaItem.Checked := not ShowAlphaItem.Checked;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.RotateClockwiseItemClick(Sender: TObject);
+var
+ x : integer;
+ y : integer;
+ DestX : integer;
+ DestY : integer;
+ C : TColor32;
+begin
+ AlphaView.Bitmap.Assign(ImgView32.Bitmap);
+
+ ImgView32.BeginUpdate;
+ ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
+ ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
+
+ for x := 0 to AlphaView.Bitmap.Width - 1 do
+ for y := 0 to AlphaView.Bitmap.Height - 1 do
+ begin
+ C := AlphaView.Bitmap.Pixel[x, y];
+
+ DestX := (ImgView32.Bitmap.Width - 1) - Y;
+ DestY := X;
+
+ ImgView32.Bitmap.Pixels[DestX, DestY] := C;
+ end;
+
+ ImgView32.EndUpdate;
+ ImgView32.Refresh;
+end;
+
+// -----------------------------------------------------------------------------
+procedure TMainForm.RotateAntiClockwiseItemClick(Sender: TObject);
+var
+ x : integer;
+ y : integer;
+ DestX : integer;
+ DestY : integer;
+ C : TColor32;
+begin
+ AlphaView.Bitmap.Assign(ImgView32.Bitmap);
+
+ ImgView32.BeginUpdate;
+ ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
+ ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
+
+ for x := 0 to AlphaView.Bitmap.Width - 1 do
+ for y := 0 to AlphaView.Bitmap.Height - 1 do
+ begin
+ C := AlphaView.Bitmap.Pixel[x, y];
+
+ DestX := Y;
+ DestY := (ImgView32.Bitmap.Height - 1) -X;
+
+ ImgView32.Bitmap.Pixels[DestX, DestY] := C;
+ end;
+
+ ImgView32.EndUpdate;
+ ImgView32.Refresh;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ShowWithAlphaItemClick(Sender: TObject);
+begin
+ if ShowWithAlphaItem.Checked then
+ ImgView32.Bitmap.DrawMode := dmOpaque
+ else
+ ImgView32.Bitmap.DrawMode := dmBlend;
+ ShowWithAlphaItem.Checked := not ShowWithAlphaItem.Checked;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.FlipHorizontalItemClick(Sender: TObject);
+var
+ x : integer;
+ y : integer;
+ DestX : integer;
+ DestY : integer;
+ C : TColor32;
+begin
+ AlphaView.Bitmap.Assign(ImgView32.Bitmap);
+
+ ImgView32.BeginUpdate;
+ ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
+ ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
+
+ for x := 0 to AlphaView.Bitmap.Width - 1 do
+ for y := 0 to AlphaView.Bitmap.Height - 1 do
+ begin
+ C := AlphaView.Bitmap.Pixel[x, y];
+
+ DestX := (ImgView32.Bitmap.Width - 1) -X;
+ DestY := Y;
+
+ ImgView32.Bitmap.Pixels[DestX, DestY] := C;
+ end;
+
+ ImgView32.EndUpdate;
+ ImgView32.Refresh;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.FilpVerticalItemClick(Sender: TObject);
+var
+ x : integer;
+ y : integer;
+ DestX : integer;
+ DestY : integer;
+ C : TColor32;
+begin
+ AlphaView.Bitmap.Assign(ImgView32.Bitmap);
+
+ ImgView32.BeginUpdate;
+ ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
+ ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
+
+ for x := 0 to AlphaView.Bitmap.Width - 1 do
+ for y := 0 to AlphaView.Bitmap.Height - 1 do
+ begin
+ C := AlphaView.Bitmap.Pixel[x, y];
+
+ DestX := X;
+ DestY := (ImgView32.Bitmap.Height - 1) - Y;
+
+ ImgView32.Bitmap.Pixels[DestX, DestY] := C;
+ end;
+
+ ImgView32.EndUpdate;
+ ImgView32.Refresh;
+end;
+
+// -----------------------------------------------------------------------------
+procedure TMainForm.FilterTimerTimer(Sender: TObject);
+begin
+ FilterTimer.Enabled := False;
+ ImgView32.Bitmap.StretchFilter := sfSPline;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.ImgView32Scroll(Sender: TObject);
+begin
+ FilterTimer.Enabled := False;
+ if ImgView32.Bitmap.StretchFilter <> sfNearest then
+ ImgView32.Bitmap.StretchFilter := sfNearest;
+ FilterTimer.Enabled := True;
+end;
+// -----------------------------------------------------------------------------
+procedure TMainForm.OpenImageItemClick(Sender: TObject);
+begin
+ if OpenDialog.Execute then
+ begin
+ try
+ Screen.Cursor := crHourGlass;
+ LoadImage(OpenDialog.FileName);
+ finally
+ Screen.Cursor := crDefault;
+ end;
+ end;
+end;
+
+end.
diff --git a/Wrapper/Delphi/demo/ImagePreview/Readme.txt b/Wrapper/Delphi/demo/ImagePreview/Readme.txt
new file mode 100644
index 0000000..bb10764
--- /dev/null
+++ b/Wrapper/Delphi/demo/ImagePreview/Readme.txt
@@ -0,0 +1,8 @@
+This is a simple image viewing application that uses the FreeImage library to display images in many different formats.
+
+The app displays the image whose name is passed in as a command line argument.
+
+
+To compile the app you will also need the Graphics32 library available from www.g32.org. It has been tested with version 1.5.1 of Graphics32.
+
+SJB.
diff --git a/Wrapper/Delphi/demo/ImagePreview/Tiger.jpg b/Wrapper/Delphi/demo/ImagePreview/Tiger.jpg
new file mode 100644
index 0000000..c152073
--- /dev/null
+++ b/Wrapper/Delphi/demo/ImagePreview/Tiger.jpg
Binary files differ
diff --git a/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.dpr b/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.dpr
new file mode 100644
index 0000000..f435c14
--- /dev/null
+++ b/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.dpr
@@ -0,0 +1,13 @@
+program MultiBitmap;
+
+uses
+ Forms,
+ mbMainForm in 'mbMainForm.pas' {MainForm};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.CreateForm(TMainForm, MainForm);
+ Application.Run;
+end.
diff --git a/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.stat b/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.stat
new file mode 100644
index 0000000..6e11772
--- /dev/null
+++ b/Wrapper/Delphi/demo/MultiBitmap/MultiBitmap.stat
@@ -0,0 +1,10 @@
+[Stats]
+EditorSecs=82
+DesignerSecs=5
+InspectorSecs=1
+CompileSecs=850
+OtherSecs=5
+StartTime=20.12.2004 11:40:22
+RealKeys=0
+EffectiveKeys=0
+DebugSecs=19
diff --git a/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.dfm b/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.dfm
new file mode 100644
index 0000000..5029ce7
--- /dev/null
+++ b/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.dfm
@@ -0,0 +1,89 @@
+object MainForm: TMainForm
+ Left = 203
+ Top = 192
+ Width = 696
+ Height = 480
+ Caption = 'MultiBitmap Demo'
+ Color = clBtnFace
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'MS Shell Dlg 2'
+ Font.Style = []
+ OldCreateOrder = False
+ OnPaint = FormPaint
+ OnResize = FormResize
+ PixelsPerInch = 96
+ TextHeight = 13
+ object ToolBar: TToolBar
+ Left = 0
+ Top = 0
+ Width = 688
+ Height = 25
+ AutoSize = True
+ ButtonHeight = 21
+ ButtonWidth = 33
+ Caption = 'ToolBar'
+ EdgeBorders = [ebLeft, ebTop, ebRight, ebBottom]
+ Flat = True
+ Indent = 3
+ ShowCaptions = True
+ TabOrder = 0
+ object tbLoad: TToolButton
+ Left = 3
+ Top = 0
+ Caption = 'Load'
+ ImageIndex = 0
+ OnClick = tbLoadClick
+ end
+ object ToolButton1: TToolButton
+ Left = 36
+ Top = 0
+ Width = 8
+ Caption = 'ToolButton1'
+ ImageIndex = 1
+ Style = tbsSeparator
+ end
+ object tbClose: TToolButton
+ Left = 44
+ Top = 0
+ Caption = 'Close'
+ ImageIndex = 1
+ OnClick = tbCloseClick
+ end
+ object ToolButton2: TToolButton
+ Left = 77
+ Top = 0
+ Width = 8
+ Caption = 'ToolButton2'
+ ImageIndex = 2
+ Style = tbsSeparator
+ end
+ object Label1: TLabel
+ Left = 85
+ Top = 0
+ Width = 36
+ Height = 21
+ Caption = 'Pages: '
+ Layout = tlCenter
+ end
+ object cbPages: TComboBox
+ Left = 121
+ Top = 0
+ Width = 60
+ Height = 21
+ Style = csDropDownList
+ DropDownCount = 15
+ ItemHeight = 13
+ TabOrder = 0
+ OnChange = cbPagesChange
+ end
+ end
+ object OD: TOpenDialog
+ Filter = 'TIFF multibitmap (*.tiff, *.tif)|*.tiff; *.tif|ICO|*.ico'
+ Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
+ Title = 'Open multibitmap..'
+ Left = 64
+ Top = 96
+ end
+end
diff --git a/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.pas b/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.pas
new file mode 100644
index 0000000..07fd997
--- /dev/null
+++ b/Wrapper/Delphi/demo/MultiBitmap/mbMainForm.pas
@@ -0,0 +1,150 @@
+unit mbMainForm;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, ComCtrls, ToolWin, StdCtrls, FreeBitmap;
+
+type
+ TMainForm = class(TForm)
+ ToolBar: TToolBar;
+ tbLoad: TToolButton;
+ ToolButton1: TToolButton;
+ tbClose: TToolButton;
+ ToolButton2: TToolButton;
+ cbPages: TComboBox;
+ Label1: TLabel;
+ OD: TOpenDialog;
+ procedure tbLoadClick(Sender: TObject);
+ procedure FormPaint(Sender: TObject);
+ procedure tbCloseClick(Sender: TObject);
+ procedure cbPagesChange(Sender: TObject);
+ procedure FormResize(Sender: TObject);
+ private
+ FMultiBitmap: TFreeMultiBitmap;
+ FPage: TFreeWinBitmap;
+
+ procedure PageBitmapChangeHandler(Sender: TObject);
+ procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+
+ procedure OpenMultiBitmap(const FileName: string);
+ procedure CloseMultiBitmap;
+ procedure OpenPage(Number: Integer);
+ end;
+
+var
+ MainForm: TMainForm;
+
+implementation
+
+{$R *.dfm}
+
+{ TMainForm }
+
+procedure TMainForm.CloseMultiBitmap;
+begin
+ if FPage.IsValid then
+ FMultiBitmap.UnlockPage(Fpage, False);
+ FMultiBitmap.Close;
+ cbPages.Clear;
+end;
+
+constructor TMainForm.Create(AOwner: TComponent);
+begin
+ inherited;
+ FMultiBitmap := TFreeMultiBitmap.Create;
+ FPage := TFreeWinBitmap.Create;
+ FPage.OnChange := PageBitmapChangeHandler;
+end;
+
+destructor TMainForm.Destroy;
+begin
+ if FMultiBitmap.IsValid then
+ CloseMultiBitmap;
+ FMultiBitmap.Free;
+ inherited;
+end;
+
+procedure TMainForm.OpenMultiBitmap(const FileName: string);
+var
+ I, Cnt: Integer;
+begin
+ if FMultiBitmap.IsValid then CloseMultiBitmap;
+
+ FMultiBitmap.Open(FileName, False, True);
+
+ Cnt := FMultiBitmap.GetPageCount;
+ cbPages.OnChange := nil;
+ cbPages.Clear;
+ for I := 0 to Cnt - 1 do
+ cbPages.Items.Add(IntToStr(I));
+ cbPages.OnChange := cbPagesChange;
+end;
+
+procedure TMainForm.OpenPage(Number: Integer);
+begin
+ if not FMultiBitmap.IsValid then Exit;
+
+ if FPage.IsValid then
+ FMultiBitmap.UnlockPage(FPage, False);
+
+ FMultiBitmap.LockPage(Number, FPage);
+end;
+
+procedure TMainForm.PageBitmapChangeHandler(Sender: TObject);
+begin
+ Invalidate;
+end;
+
+procedure TMainForm.tbLoadClick(Sender: TObject);
+begin
+ if OD.Execute then
+ begin
+ try
+ OpenMultiBitmap(OD.FileName);
+ except
+ raise Exception.CreateFmt('Can not load file %s', [OD.FileName]);
+ end;
+ end;
+end;
+
+procedure TMainForm.WMEraseBkgnd(var Message: TWMEraseBkgnd);
+begin
+ Message.Result := 1;
+end;
+
+procedure TMainForm.FormPaint(Sender: TObject);
+begin
+ if not FPage.IsValid then
+ begin
+ Canvas.Brush.Color := clBtnFace;
+ Canvas.FillRect(ClientRect);
+ end
+ else
+ FPage.Draw(Canvas.Handle, ClientRect);
+end;
+
+procedure TMainForm.tbCloseClick(Sender: TObject);
+begin
+ if FMultiBitmap.IsValid then
+ CloseMultiBitmap;
+end;
+
+procedure TMainForm.cbPagesChange(Sender: TObject);
+var
+ Page: Integer;
+begin
+ Page := StrToInt(cbPages.Text);
+ OpenPage(Page);
+end;
+
+procedure TMainForm.FormResize(Sender: TObject);
+begin
+ Invalidate;
+end;
+
+end.
diff --git a/Wrapper/Delphi/demo/TargaUnit/Readme.txt b/Wrapper/Delphi/demo/TargaUnit/Readme.txt
new file mode 100644
index 0000000..de9ed24
--- /dev/null
+++ b/Wrapper/Delphi/demo/TargaUnit/Readme.txt
@@ -0,0 +1,22 @@
+TargaImage.pas is a TGraphic descendant for Delphi. Installing it
+will allow Delphi TImage and TDBImage components to read Targa files
+just like BMP & WMF files with no coding on your part.
+
+It also adds the TGA file type to the Delphi Open/Save Picture dialog
+boxes.
+
+To install this unit, place it in your one of your library folders
+and make it available to all your Delphi projects by using
+Component>Install Component from the Delphi menus.
+
+NOTE: any Delphi applications using this *must* have FreeImage.dll
+installed in your application's folder, or somewhere in the path.
+
+-----------------------
+
+Tommy
+Edinburgh, Scotland
+LeTene@battlefieldeurope.org
+
+
+
diff --git a/Wrapper/Delphi/demo/TargaUnit/TargaImage.pas b/Wrapper/Delphi/demo/TargaUnit/TargaImage.pas
new file mode 100644
index 0000000..798748d
--- /dev/null
+++ b/Wrapper/Delphi/demo/TargaUnit/TargaImage.pas
@@ -0,0 +1,212 @@
+unit TargaImage;
+
+// ==========================================================
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+// ==========================================================
+
+interface
+
+uses
+ Windows,
+ Classes,
+ FreeImage,
+ Graphics,
+ Types;
+
+type
+ TTargaImage = class(TGraphic)
+ private
+ fImage: PFIBITMAP;
+ fWidth: Integer;
+ fHeight: Integer;
+ protected
+ procedure Draw(ACanvas: TCanvas; const ARect: TRect); override;
+ function GetEmpty: Boolean; override;
+ function GetHeight: Integer; override;
+ function GetWidth: Integer; override;
+ procedure SetHeight(Value: Integer); override;
+ procedure SetWidth(Value: Integer); override;
+ public
+ constructor Create; override;
+ destructor Destroy; override;
+ procedure Assign(Source: TPersistent); override;
+ procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle; APalette: HPALETTE); override;
+ procedure LoadFromStream(Stream: TStream); override;
+ procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle; var APalette: HPALETTE); override;
+ procedure SaveToStream(Stream: TStream); override;
+ end;
+
+ procedure Register;
+
+implementation
+
+{ Design-time registration }
+
+procedure Register;
+begin
+ TPicture.RegisterFileFormat('tga', 'TARGA Files', TTargaImage);
+end;
+
+{ IO functions }
+
+function FI_ReadProc(buffer : pointer; size : Cardinal; count : Cardinal; handle : fi_handle) : UInt; stdcall;
+var
+ stream: TStream;
+ bytesToRead: Cardinal;
+begin
+ stream := TStream(handle);
+ bytesToRead := size*count;
+ Result := stream.Read(buffer^, bytesToRead);
+end;
+
+function FI_WriteProc(buffer : pointer; size, count : Cardinal; handle : fi_handle) : UInt; stdcall;
+var
+ stream: TStream;
+ bytesToWrite: Cardinal;
+begin
+ stream := TStream(handle);
+ bytesToWrite := size*count;
+ Result := stream.Write(buffer^, bytesToWrite);
+end;
+
+function FI_SeekProc(handle : fi_handle; offset : longint; origin : integer) : Integer; stdcall;
+begin
+ TStream(handle).Seek(offset, origin);
+ Result := 0;
+end;
+
+function FI_TellProc(handle : fi_handle) : LongInt; stdcall;
+begin
+ Result := TStream(handle).Position;
+end;
+
+{ TTargaImage }
+
+constructor TTargaImage.Create;
+begin
+ fImage := nil;
+ fWidth := 0;
+ fHeight := 0;
+ inherited;
+end;
+
+destructor TTargaImage.Destroy;
+begin
+ if Assigned(fImage) then
+ FreeImage_Unload(fImage);
+ inherited;
+end;
+
+procedure TTargaImage.Assign(Source: TPersistent);
+begin
+ if Source is TTargaImage then begin
+ fImage := FreeImage_Clone(TTargaImage(Source).fImage);
+ fWidth := FreeImage_GetWidth(fImage);
+ fHeight := FreeImage_GetHeight(fImage);
+ Changed(Self);
+ end else
+ inherited;
+end;
+
+procedure TTargaImage.Draw(ACanvas: TCanvas; const ARect: TRect);
+var
+ pbi: PBitmapInfo;
+begin
+ if Assigned(fImage) then begin
+ pbi := FreeImage_GetInfo(fImage^);
+ SetStretchBltMode(ACanvas.Handle, COLORONCOLOR);
+ StretchDIBits(ACanvas.Handle, ARect.left, ARect.top,
+ ARect.right-ARect.left, ARect.bottom-ARect.top,
+ 0, 0, fWidth, fHeight,
+ FreeImage_GetBits(fImage), pbi^, DIB_RGB_COLORS, SRCCOPY);
+ end;
+end;
+
+function TTargaImage.GetEmpty: Boolean;
+begin
+ Result := Assigned(fImage);
+end;
+
+function TTargaImage.GetHeight: Integer;
+begin
+ Result := fHeight;
+end;
+
+function TTargaImage.GetWidth: Integer;
+begin
+ Result := fWidth;
+end;
+
+procedure TTargaImage.LoadFromClipboardFormat(AFormat: Word; AData: THandle; APalette: HPALETTE);
+begin
+ if Assigned(fImage) then begin
+ end;
+end;
+
+procedure TTargaImage.LoadFromStream(Stream: TStream);
+var
+ io: FreeImageIO;
+begin
+ with io do begin
+ read_proc := FI_ReadProc;
+ write_proc := FI_WriteProc;
+ seek_proc := FI_SeekProc;
+ tell_proc := FI_TellProc;
+ end;
+ fImage := FreeImage_LoadFromHandle(FIF_TARGA, @io, Stream);
+ if Assigned(fImage) then begin
+ fWidth := FreeImage_GetWidth(fImage);
+ fHeight := FreeImage_GetHeight(fImage);
+ end;
+end;
+
+procedure TTargaImage.SaveToClipboardFormat(var AFormat: Word; var AData: THandle; var APalette: HPALETTE);
+begin
+end;
+
+procedure TTargaImage.SaveToStream(Stream: TStream);
+var
+ io: FreeImageIO;
+begin
+ with io do begin
+ read_proc := FI_ReadProc;
+ write_proc := FI_WriteProc;
+ seek_proc := FI_SeekProc;
+ tell_proc := FI_TellProc;
+ end;
+ FreeImage_SaveToHandle(FIF_TARGA, fImage, @io, Stream);
+end;
+
+procedure TTargaImage.SetHeight(Value: Integer);
+begin
+ if Assigned(fImage) then begin
+ fHeight := Value;
+ FreeImage_Rescale(fImage, fWidth, fHeight, FILTER_BICUBIC);
+ end;
+end;
+
+procedure TTargaImage.SetWidth(Value: Integer);
+begin
+ if Assigned(fImage) then begin
+ fWidth := Value;
+ FreeImage_Rescale(fImage, fWidth, fHeight, FILTER_BICUBIC);
+ end;
+end;
+
+initialization
+ TPicture.RegisterFileFormat('tga', 'TARGA Files', TTargaImage);
+end.
diff --git a/Wrapper/Delphi/demo/WinBitmap/MainDemo.dpr b/Wrapper/Delphi/demo/WinBitmap/MainDemo.dpr
new file mode 100644
index 0000000..b8ffadd
--- /dev/null
+++ b/Wrapper/Delphi/demo/WinBitmap/MainDemo.dpr
@@ -0,0 +1,13 @@
+program MainDemo;
+
+uses
+ Forms,
+ MainForm in 'MainForm.pas' {fwbMainForm};
+
+{$R *.res}
+
+begin
+ Application.Initialize;
+ Application.CreateForm(TfwbMainForm, fwbMainForm);
+ Application.Run;
+end.
diff --git a/Wrapper/Delphi/demo/WinBitmap/MainForm.dfm b/Wrapper/Delphi/demo/WinBitmap/MainForm.dfm
new file mode 100644
index 0000000..46d690b
--- /dev/null
+++ b/Wrapper/Delphi/demo/WinBitmap/MainForm.dfm
@@ -0,0 +1,607 @@
+object fwbMainForm: TfwbMainForm
+ Left = 205
+ Top = 206
+ Width = 696
+ Height = 480
+ Caption = 'FreeWinBitmap - MainDemo'
+ Color = clCaptionText
+ Font.Charset = DEFAULT_CHARSET
+ Font.Color = clWindowText
+ Font.Height = -11
+ Font.Name = 'Tahoma'
+ Font.Style = []
+ Menu = MainMenu
+ OldCreateOrder = False
+ ShowHint = True
+ OnCreate = FormCreate
+ OnDestroy = FormDestroy
+ OnPaint = FormPaint
+ OnResize = FormResize
+ PixelsPerInch = 96
+ TextHeight = 13
+ object StatusBar: TStatusBar
+ Left = 0
+ Top = 411
+ Width = 688
+ Height = 23
+ Panels = <
+ item
+ Alignment = taCenter
+ Width = 120
+ end
+ item
+ Alignment = taCenter
+ Width = 80
+ end
+ item
+ Width = 50
+ end>
+ end
+ object tbTools: TToolBar
+ Left = 0
+ Top = 0
+ Width = 688
+ Height = 29
+ Caption = 'ToolBar'
+ Color = clBtnFace
+ EdgeBorders = [ebTop, ebBottom]
+ Flat = True
+ Images = ImageList1
+ ParentColor = False
+ TabOrder = 1
+ object ToolButton1: TToolButton
+ Left = 0
+ Top = 0
+ Width = 8
+ Caption = 'ToolButton1'
+ ImageIndex = 1
+ Style = tbsSeparator
+ end
+ object btnOpen: TToolButton
+ Left = 8
+ Top = 0
+ Hint = 'Open image file...'
+ Caption = 'Open...'
+ ImageIndex = 0
+ OnClick = mnuFileOpenClick
+ end
+ object ToolButton4: TToolButton
+ Left = 31
+ Top = 0
+ Width = 8
+ Caption = 'ToolButton4'
+ ImageIndex = 4
+ Style = tbsSeparator
+ end
+ object btnCopy: TToolButton
+ Left = 39
+ Top = 0
+ Hint = 'Copy to clipboard'
+ Caption = 'Copy'
+ ImageIndex = 1
+ OnClick = btnCopyClick
+ end
+ object btnPaste: TToolButton
+ Left = 62
+ Top = 0
+ Hint = 'Paste from from clipboard'
+ Caption = 'Paste'
+ ImageIndex = 2
+ OnClick = btnPasteClick
+ end
+ object ToolButton3: TToolButton
+ Left = 85
+ Top = 0
+ Width = 8
+ Caption = 'ToolButton3'
+ ImageIndex = 4
+ Style = tbsSeparator
+ end
+ object btnClear: TToolButton
+ Left = 93
+ Top = 0
+ Caption = 'Clear'
+ ImageIndex = 3
+ OnClick = btnClearClick
+ end
+ end
+ object MainMenu: TMainMenu
+ Left = 120
+ Top = 48
+ object mnuFile: TMenuItem
+ Caption = '&File'
+ object mnuFileOpen: TMenuItem
+ Caption = '&Open'
+ OnClick = mnuFileOpenClick
+ end
+ object mnuExit: TMenuItem
+ Caption = 'E&xit'
+ OnClick = mnuExitClick
+ end
+ end
+ object mnuImage: TMenuItem
+ Caption = 'Image'
+ object mnuImageFlip: TMenuItem
+ Caption = 'Flip'
+ object mnuFlipHorz: TMenuItem
+ Caption = 'Horizontal'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuFlipVert: TMenuItem
+ Caption = 'Vertical'
+ OnClick = mnuFlipHorzClick
+ end
+ end
+ object mnuConvert: TMenuItem
+ Caption = 'Convert'
+ object mnuTo4Bits: TMenuItem
+ Caption = 'To 4 Bits'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuTo8Bits: TMenuItem
+ Caption = 'To 8 Bits'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuTo16Bits555: TMenuItem
+ Caption = 'To 16 Bits (555)'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuTo16Bits565: TMenuItem
+ Caption = 'To 16 Bits (565)'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuTo24Bits: TMenuItem
+ Caption = 'To 24 Bits'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuTo32Bits: TMenuItem
+ Caption = 'To 32 Bits'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuDither: TMenuItem
+ Caption = 'Dither'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuQuantize: TMenuItem
+ Caption = 'Quantize'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuGrayScale: TMenuItem
+ Caption = 'GrayScale'
+ OnClick = mnuFlipHorzClick
+ end
+ end
+ object mnuRotate: TMenuItem
+ Caption = 'Rotate'
+ object mnuClockwise: TMenuItem
+ Caption = 'Clockwise'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuAntiClockwise: TMenuItem
+ Caption = 'AntiClockwise'
+ OnClick = mnuFlipHorzClick
+ end
+ end
+ object mnuInvert: TMenuItem
+ Caption = 'Invert'
+ OnClick = mnuFlipHorzClick
+ end
+ object mnuClear: TMenuItem
+ Caption = 'Clear'
+ OnClick = mnuFlipHorzClick
+ end
+ end
+ end
+ object OD: TOpenDialog
+ Title = 'Open file ...'
+ Left = 152
+ Top = 48
+ end
+ object ImageList1: TImageList
+ Left = 184
+ Top = 48
+ Bitmap = {
+ 494C010104000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+ 0000000000003600000028000000400000003000000001002000000000000030
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000007088900060809000607880005070
+ 8000506070004058600040485000303840002030300020203000101820001010
+ 1000101020000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000080685000203040002030400020304000203040002030
+ 4000203040002030400020304000203040000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000DFE2F700EFF0FB0000000000000000007088900090A0B00070B0D0000090
+ D0000090D0000090D0000090C0001088C0001080B0001080B0002078A0002070
+ 900020486000B9BEBE0000000000000000000000000000000000000000000000
+ 00000000000000000000C0704000B0583000B0583000A0502000A05020009048
+ 2000904820009040200080402000000000007086900060809000506070004050
+ 6000304050002030400090706000F0E0D000B0A09000B0A09000B0A09000B0A0
+ 9000B0A09000B0A09000B0A0900020304000000000000000000000000000EFF1
+ FF001F3BF100EFF1FF000000000000000000000000000000000000000000CFD3
+ F3001F2DB900CFD2F30000000000000000008088900080C0D00090A8B00080E0
+ FF0060D0FF0050C8FF0050C8FF0040C0F00030B0F00030A8F00020A0E0001090
+ D00020688000656A700000000000000000000000000000000000000000000000
+ 00000000000000000000C0785000FFF8F000D0B0A000D0B0A000D0B0A000C0B0
+ A000C0A8A000C0A8900090402000000000007080900020B8F0000090D0000090
+ D0000090D0000090D00090786000F0E8E000F0D8D000E0D0C000E0C8C000D0C0
+ B000D0B8B000D0B8B000B0A09000203040000000000000000000F0F2FF00576F
+ FF001030FF001E34FF00EFF1FF00000000000000000000000000DFE2F7003F51
+ CF000018C0000F1EB400DFE2F700000000008090A00080D0F00090A8B00090C0
+ D00070D8FF0060D0FF0060D0FF0050C8FF0050C0FF0040B8F00030B0F00030A8
+ F0001088D00020486000E1E4E500000000000000000000000000000000000000
+ 00000000000000000000D0886000FFFFFF00E0906000D0805000D0805000D080
+ 5000D0805000C0A8A00090482000000000007088900070C8F00010B8F00010B0
+ F00000A8E0000098D000A0807000F0F0F000C0B0A000C0B0A000C0A8A000B0A0
+ 9000D0C0B000B0A09000B0A0900020304000000000000000000000000000F1F2
+ FF002D52FF001030FF000028FF00CFD5FF0000000000CFD3F3001F34C7000018
+ D0000F25C300BFC5EF0000000000000000008090A00080D8F00080C8E00090A8
+ B00080E0FF0070D0FF0060D8FF0060D0FF0060D0FF0050C8FF0040C0F00040B8
+ F00030B0F000206880007897A50000000000B0A0900060483000604830006048
+ 30006048300060483000D0907000FFFFFF00FFFFFF00FFF0F000F0E0D000F0D0
+ C000F0C0B000C0B0A00090482000000000008088900070D0F00030C0F00010B8
+ F00000A8F00000A0E000A0888000FFF8FF00F0F0F000F0E8E000F0D8D000E0D0
+ C000705850006050400050484000404040000000000000000000000000000000
+ 0000F1F2FF002D52FF001030FF000F2DFF00CFD3F6001F34D5000020E0000F25
+ D200DFE2F7000000000000000000000000008098A00090E0F00090E0FF0090A8
+ B00090B8C00070D8FF0060D8FF0060D8FF0060D8FF0060D0FF0050D0FF0050C8
+ FF0040B8F00030A0E0004B697800DEE1E400B0A09000FFF0F000F0E0D000E0D8
+ D000E0D0C000E0C8C000E0A08000FFFFFF00F0A88000E0987000E0906000D080
+ 5000D0805000D0B0A000A0482000000000008090A00080D8F00040C8F00030C0
+ F00010B8F00000A0E000B0908000FFFFFF00C0B0A000C0B0A000C0A8A000F0E0
+ D00080605000D0C8C00060504000000000000000000000000000000000000000
+ 000000000000E3E6FF005669FF001038FF000020F0000F2DF0002F42D800DFE2
+ F700000000000000000000000000000000008098A00090E0F000A0E8FF0080C8
+ E00090A8B00080E0FF0080E0FF0080E0FF0080E0FF0080E0FF0080E0FF0080E0
+ FF0070D8FF0070D8FF0050A8D000919BA500B0A09000FFF8F000E0B08000E0A0
+ 7000E0A07000D0987000E0A89000FFFFFF00FFFFFF00FFFFFF00FFF8F000F0E8
+ E000F0D0C000D0B0A000A0502000000000008098A00090E0F00060D8F00050C8
+ F00030C0F00010B0F000B0989000FFFFFF00FFFFFF00FFF8FF00F0F0F000F0E8
+ E000806850008060500000000000000000000000000000000000000000000000
+ 00000000000000000000C3CAFF002048FF001030FF000F2DF000CFD3F6000000
+ 00000000000000000000000000000000000090A0A000A0E8F000A0E8FF00A0E8
+ FF0090B0C00090B0C00090A8B00090A8B00080A0B00080A0B0008098A0008098
+ A0008090A0008090A0008088900070889000C0A89000FFFFFF00FFF8F000F0F0
+ F000F0E8E000F0E0D000E0B8A000FFFFFF00FFB09000FFB09000F0D8D000E090
+ 6000B0583000B0583000A0502000000000008098A000A0E8F00080E0F00070D8
+ F00050D0F00010B0F000B0A09000B0989000B0908000A0888000A08070009078
+ 6000907060000000000000000000000000000000000000000000000000000000
+ 000000000000CFD7FF004060FF003050FF002D4BFF001038FF000020F000DFE3
+ FD000000000000000000000000000000000090A0B000A0E8F000A0F0FF00A0E8
+ FF00A0E8FF0080D8FF0060D8FF0060D8FF0060D8FF0060D8FF0060D8FF0060D8
+ FF0070889000000000000000000000000000C0A8A000FFFFFF00FFC8A000F0B8
+ 9000E0B08000E0A07000F0C0A000FFFFFF00FFFFFF00FFFFFF00FFFFFF00F098
+ 7000F0C8B000B0583000EBD5CB000000000090A0A000B0F0FF00A0E8FF0090E0
+ F00070D0F00010A0D00010A0D00010A0D0001098D0000090D0000090D0000090
+ D000303840000000000000000000000000000000000000000000000000000000
+ 0000DBE1FF004060FF004058FF004B70FF00CFD5FF004B69FF002040FF000020
+ F000CFD5FC0000000000000000000000000090A0B000A0F0F000B0F0F000A0F0
+ FF00A0E8FF00A0E8FF0070D8FF0090A0A0008098A0008098A0008090A0008090
+ 900070889000000000000000000000000000C0B0A000FFFFFF00FFFFFF00FFF8
+ FF00FFF0F000F0E8E000F0C8B000FFFFFF00FFFFFF00FFFFFF00FFFFFF00F0A8
+ 8000C0683000EFD9CB00000000000000000090A0B000B0F0FF00A0F0FF006080
+ 9000607080005070800050687000506870005060700040587000207090000090
+ D00040486000000000000000000000000000000000000000000000000000E7EB
+ FF005070FF005078FF00708AFF00E7EBFF0000000000DBDFFF004B69FF003048
+ FF000020F000CFD5FC00000000000000000090A8B000A0D0E000B0F0F000B0F0
+ F000A0F0FF00A0E8FF0090A0B000B3C7CB000000000000000000000000000000
+ 000000000000906850009068500090685000D0B8B000FFFFFF00FFD8C000FFD0
+ B000F0E0D000B0A09000F0C8B000F0C0B000F0C0B000F0B8A000F0B09000F0B0
+ 9000F7E3D70000000000000000000000000090A8B000B0F0FF00B0F0FF006088
+ 900090C8D00090E8F00080D8E00060C8E0005098B000405860002080A0000090
+ D000505870000000000000000000000000000000000000000000F3F5FF006078
+ FF006078FF00697FFF00F3F5FF00000000000000000000000000E7EAFF004B69
+ FF003050FF000028FF00DFE3FD0000000000DCE3E60090A8B00090A8B00090A8
+ B00090A8B00090A8B000AAB3B400000000000000000000000000000000000000
+ 000000000000E1D4D2009068500090685000D0C0B000FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00C0A89000D0C8C00090706000E1DCD80000000000000000000000
+ 00000000000000000000000000000000000090A8B000B0F0F000B0F0FF00A0F0
+ F0007098A000A0F0F00060757C0080C8D000507080003060800060C0F00020B8
+ F00050607000000000000000000000000000000000000000000000000000E7EB
+ FF006987FF00F3F5FF000000000000000000000000000000000000000000E7EA
+ FF005773FF00E1E5FF0000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000090786000B7A498000000
+ 0000F9F6F600A0908000E1D9D20090786000E0C0B000FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00C0B0A000A0806000E1DCD8000000000000000000000000000000
+ 000000000000000000000000000000000000CED8DC0090A8B00090A8B00090A8
+ B0006090A000A0E8F000A0E8F00090D8E0004068700070889000808890007088
+ 9000D7DADC000000000000000000000000000000000000000000000000000000
+ 0000F3F5FF000000000000000000000000000000000000000000000000000000
+ 0000E7EAFF000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000000000000000D1CFC900A0908000A088
+ 8000B0988000CFC7BF000000000000000000E0C0B000E0C0B000D0C0B000D0C0
+ B000D0B8B000D0B0A000E6DEDC00000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000080B0C00080B0C00080A0B000DEE1E40000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000000000000000000000000000000000000424D3E000000000000003E000000
+ 2800000040000000300000000100010000000000800100000000000000000000
+ 000000000000000000000000FFFFFF0000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 00000000000000000000000000000000FFFFFFFFFFFFFFFF0007FFFFFC00FFF3
+ 0003FC010000E3E30003FC010000C1C10001FC010000E083000100010000F007
+ 000000010001F80F000000010003FC1F000000010007F80F000700010007F007
+ 000700030007E08300F800070007C1C101F8007F0007E3E3FF9000FF0007F7F7
+ FF8301FFF87FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000
+ 000000000000}
+ end
+end
diff --git a/Wrapper/Delphi/demo/WinBitmap/MainForm.pas b/Wrapper/Delphi/demo/WinBitmap/MainForm.pas
new file mode 100644
index 0000000..41b038b
--- /dev/null
+++ b/Wrapper/Delphi/demo/WinBitmap/MainForm.pas
@@ -0,0 +1,227 @@
+unit MainForm;
+
+interface
+
+uses
+ Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+ Dialogs, Menus, FreeBitmap, ComCtrls, ImgList, ToolWin;
+
+type
+ TfwbMainForm = class(TForm)
+ MainMenu: TMainMenu;
+ mnuFile: TMenuItem;
+ mnuFileOpen: TMenuItem;
+ mnuExit: TMenuItem;
+ OD: TOpenDialog;
+ StatusBar: TStatusBar;
+ mnuImage: TMenuItem;
+ mnuImageFlip: TMenuItem;
+ mnuFlipHorz: TMenuItem;
+ mnuFlipVert: TMenuItem;
+ mnuConvert: TMenuItem;
+ mnuTo8Bits: TMenuItem;
+ mnuTo16Bits555: TMenuItem;
+ mnuTo16Bits565: TMenuItem;
+ mnuTo24Bits: TMenuItem;
+ mnuTo32Bits: TMenuItem;
+ mnuDither: TMenuItem;
+ mnuQuantize: TMenuItem;
+ mnuGrayScale: TMenuItem;
+ mnuRotate: TMenuItem;
+ mnuClockwise: TMenuItem;
+ mnuAntiClockwise: TMenuItem;
+ mnuInvert: TMenuItem;
+ mnuClear: TMenuItem;
+ mnuTo4Bits: TMenuItem;
+ tbTools: TToolBar;
+ btnCopy: TToolButton;
+ ImageList1: TImageList;
+ ToolButton1: TToolButton;
+ btnPaste: TToolButton;
+ btnClear: TToolButton;
+ btnOpen: TToolButton;
+ ToolButton3: TToolButton;
+ ToolButton4: TToolButton;
+ procedure FormDestroy(Sender: TObject);
+ procedure FormPaint(Sender: TObject);
+ procedure FormCreate(Sender: TObject);
+ procedure mnuExitClick(Sender: TObject);
+ procedure mnuFileOpenClick(Sender: TObject);
+ procedure FormResize(Sender: TObject);
+ procedure mnuFlipHorzClick(Sender: TObject);
+ procedure btnCopyClick(Sender: TObject);
+ procedure btnClearClick(Sender: TObject);
+ procedure btnPasteClick(Sender: TObject);
+ private
+ FBitmap: TFreeWinBitmap;
+ procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
+ public
+ { Public declarations }
+ end;
+
+var
+ fwbMainForm: TfwbMainForm;
+
+implementation
+
+{$R *.dfm}
+
+uses
+ FreeUtils, FreeImage, Math;
+
+procedure TfwbMainForm.FormDestroy(Sender: TObject);
+begin
+ if Assigned(FBitmap) then
+ FBitmap.Free;
+end;
+
+procedure TfwbMainForm.FormPaint(Sender: TObject);
+var
+ dx, dy, w, h: Integer;
+ r1, r2: Double;
+ R: TRect;
+begin
+ if FBitmap.IsValid then // draw the bitmap
+ begin
+ // determine paint rect
+ r1 := FBitmap.GetWidth / FBitmap.GetHeight;
+ r2 := ClientWidth / ClientHeight;
+ if r1 > r2 then // fit by width
+ begin
+ w := ClientWidth;
+ h := Floor(w / r1);
+ dx := 0;
+ dy := (ClientHeight - h) div 2;
+ end
+ else // fit by height
+ begin
+ h := ClientHeight;
+ w := Floor(h * r1);
+ dy := 0;
+ dx := (ClientWidth - w) div 2;
+ end;
+ with ClientRect do
+ R := Bounds(Left + dx, Top + dy, w, h);
+ FBitmap.Draw(Canvas.Handle, R);
+
+ // erase area around the image
+ Canvas.Brush.Color := Color;
+ if dx > 0 then
+ begin
+ with ClientRect do
+ R := Bounds(Left, Top, dx, ClientHeight);
+ Canvas.FillRect(R);
+ with ClientRect do
+ R := Bounds(Right - dx, Top, dx, ClientHeight);
+ Canvas.FillRect(R);
+ end else
+ if dy > 0 then
+ begin
+ with ClientRect do
+ R := Bounds(Left, Top, ClientWidth, dy);
+ Canvas.FillRect(R);
+ with ClientRect do
+ R := Bounds(Left, Bottom - dy, ClientWidth, dy);
+ Canvas.FillRect(R);
+ end
+ end
+ else // clear
+ begin
+ Canvas.Brush.Color := Color;
+ Canvas.FillRect(ClientRect);
+ end
+end;
+
+procedure TfwbMainForm.FormCreate(Sender: TObject);
+begin
+ FBitmap := TFreeWinBitmap.Create;
+
+ mnuImage.Enabled := FBitmap.IsValid;
+ OD.Filter := FIU_GetAllFilters;
+end;
+
+procedure TfwbMainForm.mnuExitClick(Sender: TObject);
+begin
+ Close;
+end;
+
+procedure TfwbMainForm.mnuFileOpenClick(Sender: TObject);
+var
+ t: Cardinal;
+begin
+ if OD.Execute then
+ begin
+ t := GetTickCount;
+ FBitmap.Load(OD.FileName);
+ t := GetTickCount - t;
+ mnuImage.Enabled := FBitmap.IsValid;
+ StatusBar.Panels[0].Text := 'Loaded in ' + IntToStr(t) + ' msec.';
+ StatusBar.Panels[1].Text := Format('%dx%d', [FBitmap.GetWidth, FBitmap.GetHeight]);
+ Invalidate;
+ end;
+end;
+
+procedure TfwbMainForm.FormResize(Sender: TObject);
+begin
+ Invalidate
+end;
+
+procedure TfwbMainForm.WMEraseBkgnd(var Message: TMessage);
+begin
+ Message.Result := 1;
+end;
+
+procedure TfwbMainForm.mnuFlipHorzClick(Sender: TObject);
+begin
+ with FBitmap do
+ if Sender = mnuFlipHorz then
+ FLipHorizontal else
+ if Sender = mnuFlipVert then
+ FlipVertical else
+ if Sender = mnuTo4Bits then
+ ConvertTo4Bits else
+ if Sender = mnuTo8Bits then
+ ConvertTo8Bits else
+ if Sender = mnuTo16Bits555 then
+ ConvertTo16Bits555 else
+ if Sender = mnuTo16Bits565 then
+ ConvertTo16Bits565 else
+ if Sender = mnuTo24Bits then
+ ConvertTo24Bits else
+ if Sender = mnuTo32Bits then
+ ConvertTo32Bits else
+ if Sender = mnuDither then
+ Dither(FID_FS) else
+ if Sender = mnuQuantize then
+ ColorQuantize(FIQ_WUQUANT) else
+ if Sender = mnuGrayScale then
+ ConvertToGrayscale else
+ if Sender = mnuClockwise then
+ Rotate(-90) else
+ if Sender = mnuAntiClockwise then
+ Rotate(90) else
+ if Sender = mnuInvert then
+ Invert else
+ if Sender = mnuClear then
+ Clear;
+ Invalidate;
+end;
+
+procedure TfwbMainForm.btnCopyClick(Sender: TObject);
+begin
+ if FBitmap.IsValid then FBitmap.CopyToClipBoard(Handle);
+end;
+
+procedure TfwbMainForm.btnClearClick(Sender: TObject);
+begin
+ FBitmap.Clear;
+ Invalidate;
+end;
+
+procedure TfwbMainForm.btnPasteClick(Sender: TObject);
+begin
+ FBitmap.PasteFromClipBoard;
+ Invalidate;
+end;
+
+end.
diff --git a/Wrapper/Delphi/license.txt b/Wrapper/Delphi/license.txt
new file mode 100644
index 0000000..48215b6
--- /dev/null
+++ b/Wrapper/Delphi/license.txt
@@ -0,0 +1,3 @@
+The contents of FreeImageDW package are subject to the FreeImage Public License Version 1.0 (the "License"); you may not use this package except in compliance with the License. You may obtain a copy of the License at http://home.wxs.nl/~flvdberg/freeimage-license.txt
+
+Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. \ No newline at end of file
diff --git a/Wrapper/Delphi/src/FreeBitmap.pas b/Wrapper/Delphi/src/FreeBitmap.pas
new file mode 100644
index 0000000..778e1da
--- /dev/null
+++ b/Wrapper/Delphi/src/FreeBitmap.pas
@@ -0,0 +1,2123 @@
+unit FreeBitmap;
+
+// ==========================================================
+//
+// Delphi wrapper for FreeImage 3
+//
+// Design and implementation by
+// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
+//
+// Contributors:
+// - Enzo Costantini (enzocostantini@libero.it)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+// ==========================================================
+//
+// From begining all code of this file is based on C++ wrapper to
+// FreeImage - FreeImagePlus.
+//
+// ==========================================================
+
+interface
+
+uses
+ SysUtils, Classes, Windows, FreeImage;
+
+type
+ { TFreeObject }
+
+ TFreeObject = class(TObject)
+ public
+ function IsValid: Boolean; virtual;
+ end;
+
+ { TFreeTag }
+
+ TFreeTag = class(TFreeObject)
+ private
+ // fields
+ FTag: PFITAG;
+
+ // getters & setters
+ function GetCount: Cardinal;
+ function GetDescription: string;
+ function GetID: Word;
+ function GetKey: string;
+ function GetLength: Cardinal;
+ function GetTagType: FREE_IMAGE_MDTYPE;
+ function GetValue: Pointer;
+ procedure SetCount(const Value: Cardinal);
+ procedure SetDescription(const Value: string);
+ procedure SetID(const Value: Word);
+ procedure SetKey(const Value: string);
+ procedure SetLength(const Value: Cardinal);
+ procedure SetTagType(const Value: FREE_IMAGE_MDTYPE);
+ procedure SetValue(const Value: Pointer);
+ public
+ // construction & destruction
+ constructor Create(ATag: PFITAG = nil); virtual;
+ destructor Destroy; override;
+
+ // methods
+ function Clone: TFreeTag;
+ function IsValid: Boolean; override;
+ function ToString(Model: FREE_IMAGE_MDMODEL; Make: PChar = nil): string;
+
+ // properties
+ property Key: string read GetKey write SetKey;
+ property Description: string read GetDescription write SetDescription;
+ property ID: Word read GetID write SetID;
+ property TagType: FREE_IMAGE_MDTYPE read GetTagType write SetTagType;
+ property Count: Cardinal read GetCount write SetCount;
+ property Length: Cardinal read GetLength write SetLength;
+ property Value: Pointer read GetValue write SetValue;
+ property Tag: PFITAG read FTag;
+ end;
+
+ { forward declarations }
+
+ TFreeBitmap = class;
+ TFreeMemoryIO = class;
+
+ { TFreeBitmap }
+
+ TFreeBitmapChangingEvent = procedure(Sender: TFreeBitmap; var OldDib, NewDib: PFIBITMAP; var Handled: Boolean) of object;
+
+ TFreeBitmap = class(TFreeObject)
+ private
+ // fields
+ FDib: PFIBITMAP;
+ FOnChange: TNotifyEvent;
+ FOnChanging: TFreeBitmapChangingEvent;
+
+ procedure SetDib(Value: PFIBITMAP);
+ protected
+ function DoChanging(var OldDib, NewDib: PFIBITMAP): Boolean; dynamic;
+ function Replace(NewDib: PFIBITMAP): Boolean; dynamic;
+ public
+ constructor Create(ImageType: FREE_IMAGE_TYPE = FIT_BITMAP; Width: Integer = 0; Height: Integer = 0; Bpp: Integer = 0);
+ destructor Destroy; override;
+ function SetSize(ImageType: FREE_IMAGE_TYPE; Width, Height, Bpp: Integer; RedMask: Cardinal = 0; GreenMask: Cardinal = 0; BlueMask: Cardinal = 0): Boolean;
+ procedure Change; dynamic;
+ procedure Assign(Source: TFreeBitmap);
+ function CopySubImage(Left, Top, Right, Bottom: Integer; Dest: TFreeBitmap): Boolean;
+ function PasteSubImage(Src: TFreeBitmap; Left, Top: Integer; Alpha: Integer = 256): Boolean;
+ procedure Clear; virtual;
+ function Load(const FileName: string; Flag: Integer = 0): Boolean;
+ function LoadU(const FileName: WideString; Flag: Integer = 0): Boolean;
+ function LoadFromHandle(IO: PFreeImageIO; Handle: fi_handle; Flag: Integer = 0): Boolean;
+ function LoadFromMemory(MemIO: TFreeMemoryIO; Flag: Integer = 0): Boolean;
+ function LoadFromStream(Stream: TStream; Flag: Integer = 0): Boolean;
+ // save functions
+ function CanSave(fif: FREE_IMAGE_FORMAT): Boolean;
+ function Save(const FileName: string; Flag: Integer = 0): Boolean;
+ function SaveU(const FileName: WideString; Flag: Integer = 0): Boolean;
+ function SaveToHandle(fif: FREE_IMAGE_FORMAT; IO: PFreeImageIO; Handle: fi_handle; Flag: Integer = 0): Boolean;
+ function SaveToMemory(fif: FREE_IMAGE_FORMAT; MemIO: TFreeMemoryIO; Flag: Integer = 0): Boolean;
+ function SaveToStream(fif: FREE_IMAGE_FORMAT; Stream: TStream; Flag: Integer = 0): Boolean;
+ // image information
+ function GetImageType: FREE_IMAGE_TYPE;
+ function GetWidth: Integer;
+ function GetHeight: Integer;
+ function GetScanWidth: Integer;
+ function IsValid: Boolean; override;
+ function GetInfo: PBitmapInfo;
+ function GetInfoHeader: PBitmapInfoHeader;
+ function GetImageSize: Cardinal;
+ function GetBitsPerPixel: Integer;
+ function GetLine: Integer;
+ function GetHorizontalResolution: Double;
+ function GetVerticalResolution: Double;
+ procedure SetHorizontalResolution(Value: Double);
+ procedure SetVerticalResolution(Value: Double);
+ // palette operations
+ function GetPalette: PRGBQUAD;
+ function GetPaletteSize: Integer;
+ function GetColorsUsed: Integer;
+ function GetColorType: FREE_IMAGE_COLOR_TYPE;
+ function IsGrayScale: Boolean;
+ // pixels access
+ function AccessPixels: PByte;
+ function GetScanLine(ScanLine: Integer): PByte;
+ function GetPixelIndex(X, Y: Cardinal; var Value: PByte): Boolean;
+ function GetPixelColor(X, Y: Cardinal; var Value: PRGBQUAD): Boolean;
+ function SetPixelIndex(X, Y: Cardinal; Value: PByte): Boolean;
+ function SetPixelColor(X, Y: Cardinal; Value: PRGBQUAD): Boolean;
+ // convertion
+ function ConvertToStandardType(ScaleLinear: Boolean): Boolean;
+ function ConvertToType(ImageType: FREE_IMAGE_TYPE; ScaleLinear: Boolean): Boolean;
+ function Threshold(T: Byte): Boolean;
+ function ConvertTo4Bits: Boolean;
+ function ConvertTo8Bits: Boolean;
+ function ConvertTo16Bits555: Boolean;
+ function ConvertTo16Bits565: Boolean;
+ function ConvertTo24Bits: Boolean;
+ function ConvertTo32Bits: Boolean;
+ function ConvertToGrayscale: Boolean;
+ function ColorQuantize(Algorithm: FREE_IMAGE_QUANTIZE): Boolean;
+ function Dither(Algorithm: FREE_IMAGE_DITHER): Boolean;
+ function ConvertToRGBF: Boolean;
+ function ToneMapping(TMO: FREE_IMAGE_TMO; FirstParam, SecondParam: Double): Boolean;
+ // transparency
+ function IsTransparent: Boolean;
+ function GetTransparencyCount: Cardinal;
+ function GetTransparencyTable: PByte;
+ procedure SetTransparencyTable(Table: PByte; Count: Integer);
+ function HasFileBkColor: Boolean;
+ function GetFileBkColor(var BkColor: PRGBQuad): Boolean;
+ function SetFileBkColor(BkColor: PRGBQuad): Boolean;
+ // channel processing routines
+ function GetChannel(Bitmap: TFreeBitmap; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+ function SetChannel(Bitmap: TFreeBitmap; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+ function SplitChannels(RedChannel, GreenChannel, BlueChannel: TFreeBitmap): Boolean;
+ function CombineChannels(Red, Green, Blue: TFreeBitmap): Boolean;
+ // rotation and flipping
+ function RotateEx(Angle, XShift, YShift, XOrigin, YOrigin: Double; UseMask: Boolean): Boolean;
+ function Rotate(Angle: Double): Boolean;
+ function FlipHorizontal: Boolean;
+ function FlipVertical: Boolean;
+ // color manipulation routines
+ function Invert: Boolean;
+ function AdjustCurve(Lut: PByte; Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+ function AdjustGamma(Gamma: Double): Boolean;
+ function AdjustBrightness(Percentage: Double): Boolean;
+ function AdjustContrast(Percentage: Double): Boolean;
+ function GetHistogram(Histo: PDWORD; Channel: FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK): Boolean;
+ // upsampling / downsampling
+ procedure MakeThumbnail(const Width, Height: Integer; DestBitmap: TFreeBitmap);
+ function Rescale(NewWidth, NewHeight: Integer; Filter: FREE_IMAGE_FILTER; Dest: TFreeBitmap = nil): Boolean;
+ // metadata routines
+ function FindFirstMetadata(Model: FREE_IMAGE_MDMODEL; var Tag: TFreeTag): PFIMETADATA;
+ function FindNextMetadata(MDHandle: PFIMETADATA; var Tag: TFreeTag): Boolean;
+ procedure FindCloseMetadata(MDHandle: PFIMETADATA);
+ function SetMetadata(Model: FREE_IMAGE_MDMODEL; const Key: string; Tag: TFreeTag): Boolean;
+ function GetMetadata(Model: FREE_IMAGE_MDMODEL; const Key: string; var Tag: TFreeTag): Boolean;
+ function GetMetadataCount(Model: FREE_IMAGE_MDMODEL): Cardinal;
+
+ // properties
+ property Dib: PFIBITMAP read FDib write SetDib;
+ property OnChange: TNotifyEvent read FOnChange write FOnChange;
+ property OnChanging: TFreeBitmapChangingEvent read FOnChanging write FOnChanging;
+ end;
+
+ { TFreeWinBitmap }
+
+ TFreeWinBitmap = class(TFreeBitmap)
+ private
+ FDeleteMe: Boolean; // True - need to delete FDisplayDib
+ FDisplayDib: PFIBITMAP; // Image that paints on DC
+ public
+ constructor Create(ImageType: FREE_IMAGE_TYPE = FIT_BITMAP; Width: Integer = 0; Height: Integer = 0; Bpp: Integer = 0);
+ destructor Destroy; override;
+
+ procedure Clear; override;
+ function CopyToHandle: THandle;
+ function CopyFromHandle(HMem: THandle): Boolean;
+ function CopyFromBitmap(HBmp: HBITMAP): Boolean;
+ function CopyToBitmapH: HBITMAP;
+ function CopyToClipBoard(NewOwner: HWND): Boolean;
+ function PasteFromClipBoard: Boolean;
+ function CaptureWindow(ApplicationWindow, SelectedWindow: HWND): Boolean;
+
+ procedure Draw(DC: HDC; Rect: TRect);
+ procedure DrawEx(DC: HDC; Rect: TRect; UseFileBkg: Boolean = False; AppBkColor: PRGBQuad = nil; Bg: PFIBITMAP = nil);
+ end;
+
+ { TFreeMemoryIO }
+
+ TFreeMemoryIO = class(TFreeObject)
+ private
+ FHMem: PFIMEMORY;
+ public
+ // construction and destruction
+ constructor Create(Data: PByte = nil; SizeInBytes: DWORD = 0);
+ destructor Destroy; override;
+
+ function GetFileType: FREE_IMAGE_FORMAT;
+ function Read(fif: FREE_IMAGE_FORMAT; Flag: Integer = 0): PFIBITMAP;
+ function Write(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; Flag: Integer = 0): Boolean;
+ function Tell: Longint;
+ function Seek(Offset: Longint; Origin: Word): Boolean;
+ function Acquire(var Data: PByte; var SizeInBytes: DWORD): Boolean;
+ // overriden methods
+ function IsValid: Boolean; override;
+ end;
+
+ { TFreeMultiBitmap }
+
+ TFreeMultiBitmap = class(TFreeObject)
+ private
+ FMPage: PFIMULTIBITMAP;
+ FMemoryCache: Boolean;
+ public
+ // constructor and destructor
+ constructor Create(KeepCacheInMemory: Boolean = False);
+ destructor Destroy; override;
+
+ // methods
+ function Open(const FileName: string; CreateNew, ReadOnly: Boolean; Flags: Integer = 0): Boolean;
+ function Close(Flags: Integer = 0): Boolean;
+ function GetPageCount: Integer;
+ procedure AppendPage(Bitmap: TFreeBitmap);
+ procedure InsertPage(Page: Integer; Bitmap: TFreeBitmap);
+ procedure DeletePage(Page: Integer);
+ function MovePage(Target, Source: Integer): Boolean;
+ procedure LockPage(Page: Integer; DestBitmap: TFreeBitmap);
+ procedure UnlockPage(Bitmap: TFreeBitmap; Changed: Boolean);
+ function GetLockedPageNumbers(var Pages: Integer; var Count: Integer): Boolean;
+ // overriden methods
+ function IsValid: Boolean; override;
+
+ // properties
+ // change of this property influences only on the next opening of a file
+ property MemoryCache: Boolean read FMemoryCache write FMemoryCache;
+ end;
+
+implementation
+
+const
+ ThumbSize = 150;
+
+// marker used for clipboard copy / paste
+
+procedure SetFreeImageMarker(bmih: PBitmapInfoHeader; dib: PFIBITMAP);
+begin
+ // Windows constants goes from 0L to 5L
+ // Add $FF to avoid conflicts
+ bmih.biCompression := $FF + FreeImage_GetImageType(dib);
+end;
+
+function GetFreeImageMarker(bmih: PBitmapInfoHeader): FREE_IMAGE_TYPE;
+begin
+ Result := FREE_IMAGE_TYPE(bmih.biCompression - $FF);
+end;
+
+{ TFreePersistent }
+
+function TFreeObject.IsValid: Boolean;
+begin
+ Result := False
+end;
+
+{ TFreeBitmap }
+
+function TFreeBitmap.AccessPixels: PByte;
+begin
+ Result := FreeImage_GetBits(FDib)
+end;
+
+function TFreeBitmap.AdjustBrightness(Percentage: Double): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_AdjustBrightness(FDib, Percentage);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.AdjustContrast(Percentage: Double): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_AdjustContrast(FDib, Percentage);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.AdjustCurve(Lut: PByte;
+ Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_AdjustCurve(FDib, Lut, Channel);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.AdjustGamma(Gamma: Double): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_AdjustGamma(FDib, Gamma);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+procedure TFreeBitmap.Assign(Source: TFreeBitmap);
+var
+ SourceBmp: TFreeBitmap;
+ Clone: PFIBITMAP;
+begin
+ if Source = nil then
+ begin
+ Clear;
+ Exit;
+ end;
+
+ if Source is TFreeBitmap then
+ begin
+ SourceBmp := TFreeBitmap(Source);
+ if SourceBmp <> Self then
+ begin
+ if SourceBmp.IsValid then
+ begin
+ Clone := FreeImage_Clone(SourceBmp.FDib);
+ Replace(Clone);
+ end
+ else
+ Clear;
+ end;
+ end;
+end;
+
+function TFreeBitmap.CanSave(fif: FREE_IMAGE_FORMAT): Boolean;
+var
+ ImageType: FREE_IMAGE_TYPE;
+ Bpp: Word;
+begin
+ Result := False;
+ if not IsValid then Exit;
+
+ if fif <> FIF_UNKNOWN then
+ begin
+ // check that the dib can be saved in this format
+ ImageType := FreeImage_GetImageType(FDib);
+ if ImageType = FIT_BITMAP then
+ begin
+ // standard bitmap type
+ Bpp := FreeImage_GetBPP(FDib);
+ Result := FreeImage_FIFSupportsWriting(fif)
+ and FreeImage_FIFSupportsExportBPP(fif, Bpp);
+ end
+ else // special bitmap type
+ Result := FreeImage_FIFSupportsExportType(fif, ImageType);
+ end;
+end;
+
+procedure TFreeBitmap.Change;
+begin
+ if Assigned(FOnChange) then FOnChange(Self)
+end;
+
+procedure TFreeBitmap.Clear;
+begin
+ if FDib <> nil then
+ begin
+ FreeImage_Unload(FDib);
+ FDib := nil;
+ Change;
+ end;
+end;
+
+function TFreeBitmap.ColorQuantize(
+ Algorithm: FREE_IMAGE_QUANTIZE): Boolean;
+var
+ dib8: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib8 := FreeImage_ColorQuantize(FDib, Algorithm);
+ Result := Replace(dib8);
+ end
+ else
+ Result := False;
+end;
+
+function TFreeBitmap.CombineChannels(Red, Green,
+ Blue: TFreeBitmap): Boolean;
+var
+ Width, Height: Integer;
+begin
+ if FDib = nil then
+ begin
+ Width := Red.GetWidth;
+ Height := Red.GetHeight;
+ FDib := FreeImage_Allocate(Width, Height, 24, FI_RGBA_RED_MASK,
+ FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ end;
+
+ if FDib <> nil then
+ begin
+ Result := FreeImage_SetChannel(FDib, Red.FDib, FICC_RED) and
+ FreeImage_SetChannel(FDib, Green.FDib, FICC_GREEN) and
+ FreeImage_SetChannel(FDib, Blue.FDib, FICC_BLUE);
+
+ Change
+ end
+ else
+ Result := False;
+end;
+
+function TFreeBitmap.ConvertTo16Bits555: Boolean;
+var
+ dib16_555: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib16_555 := FreeImage_ConvertTo16Bits555(FDib);
+ Result := Replace(dib16_555);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ConvertTo16Bits565: Boolean;
+var
+ dib16_565: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib16_565 := FreeImage_ConvertTo16Bits565(FDib);
+ Result := Replace(dib16_565);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ConvertTo24Bits: Boolean;
+var
+ dibRGB: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dibRGB := FreeImage_ConvertTo24Bits(FDib);
+ Result := Replace(dibRGB);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ConvertTo32Bits: Boolean;
+var
+ dib32: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib32 := FreeImage_ConvertTo32Bits(FDib);
+ Result := Replace(dib32);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ConvertTo4Bits: Boolean;
+var
+ dib4: PFIBITMAP;
+begin
+ Result := False;
+ if IsValid then
+ begin
+ dib4 := FreeImage_ConvertTo4Bits(FDib);
+ Result := Replace(dib4);
+ end;
+end;
+
+function TFreeBitmap.ConvertTo8Bits: Boolean;
+var
+ dib8: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib8 := FreeImage_ConvertTo8Bits(FDib);
+ Result := Replace(dib8);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ConvertToGrayscale: Boolean;
+var
+ dib8: PFIBITMAP;
+begin
+ Result := False;
+
+ if IsValid then
+ begin
+ dib8 := FreeImage_ConvertToGreyscale(FDib);
+ Result := Replace(dib8);
+ end
+end;
+
+function TFreeBitmap.ConvertToRGBF: Boolean;
+var
+ ImageType: FREE_IMAGE_TYPE;
+ NewDib: PFIBITMAP;
+begin
+ Result := False;
+ if not IsValid then Exit;
+
+ ImageType := GetImageType;
+
+ if (ImageType = FIT_BITMAP) then
+ begin
+ if GetBitsPerPixel < 24 then
+ if not ConvertTo24Bits then
+ Exit
+ end;
+ NewDib := FreeImage_ConvertToRGBF(FDib);
+ Result := Replace(NewDib);
+end;
+
+function TFreeBitmap.ConvertToStandardType(ScaleLinear: Boolean): Boolean;
+var
+ dibStandard: PFIBITMAP;
+begin
+ if IsValid then
+ begin
+ dibStandard := FreeImage_ConvertToStandardType(FDib, ScaleLinear);
+ Result := Replace(dibStandard);
+ end
+ else
+ Result := False;
+end;
+
+function TFreeBitmap.ConvertToType(ImageType: FREE_IMAGE_TYPE;
+ ScaleLinear: Boolean): Boolean;
+var
+ dib: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib := FreeImage_ConvertToType(FDib, ImageType, ScaleLinear);
+ Result := Replace(dib)
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.CopySubImage(Left, Top, Right, Bottom: Integer;
+ Dest: TFreeBitmap): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Dest.FDib := FreeImage_Copy(FDib, Left, Top, Right, Bottom);
+ Result := Dest.IsValid;
+ end else
+ Result := False;
+end;
+
+constructor TFreeBitmap.Create(ImageType: FREE_IMAGE_TYPE; Width, Height,
+ Bpp: Integer);
+begin
+ inherited Create;
+
+ FDib := nil;
+ if (Width > 0) and (Height > 0) and (Bpp > 0) then
+ SetSize(ImageType, Width, Height, Bpp);
+end;
+
+destructor TFreeBitmap.Destroy;
+begin
+ if FDib <> nil then
+ FreeImage_Unload(FDib);
+ inherited;
+end;
+
+function TFreeBitmap.Dither(Algorithm: FREE_IMAGE_DITHER): Boolean;
+var
+ dib: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib := FreeImage_Dither(FDib, Algorithm);
+ Result := Replace(dib);
+ end
+ else
+ Result := False;
+end;
+
+function TFreeBitmap.DoChanging(var OldDib, NewDib: PFIBITMAP): Boolean;
+begin
+ Result := False;
+ if (OldDib <> NewDib) and Assigned(FOnChanging) then
+ FOnChanging(Self, OldDib, NewDib, Result);
+end;
+
+procedure TFreeBitmap.FindCloseMetadata(MDHandle: PFIMETADATA);
+begin
+ FreeImage_FindCloseMetadata(MDHandle);
+end;
+
+function TFreeBitmap.FindFirstMetadata(Model: FREE_IMAGE_MDMODEL;
+ var Tag: TFreeTag): PFIMETADATA;
+begin
+ Result := FreeImage_FindFirstMetadata(Model, FDib, Tag.FTag);
+end;
+
+function TFreeBitmap.FindNextMetadata(MDHandle: PFIMETADATA;
+ var Tag: TFreeTag): Boolean;
+begin
+ Result := FreeImage_FindNextMetadata(MDHandle, Tag.FTag);
+end;
+
+function TFreeBitmap.FlipHorizontal: Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_FlipHorizontal(FDib);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.FlipVertical: Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_FlipVertical(FDib);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.GetBitsPerPixel: Integer;
+begin
+ Result := FreeImage_GetBPP(FDib)
+end;
+
+function TFreeBitmap.GetChannel(Bitmap: TFreeBitmap;
+ Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Bitmap.Dib := FreeImage_GetChannel(FDib, Channel);
+ Result := Bitmap.IsValid;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.GetColorsUsed: Integer;
+begin
+ Result := FreeImage_GetColorsUsed(FDib)
+end;
+
+function TFreeBitmap.GetColorType: FREE_IMAGE_COLOR_TYPE;
+begin
+ Result := FreeImage_GetColorType(FDib);
+end;
+
+function TFreeBitmap.GetFileBkColor(var BkColor: PRGBQuad): Boolean;
+begin
+ Result := FreeImage_GetBackgroundColor(FDib, BkColor)
+end;
+
+function TFreeBitmap.GetHeight: Integer;
+begin
+ Result := FreeImage_GetHeight(FDib)
+end;
+
+function TFreeBitmap.GetHistogram(Histo: PDWORD;
+ Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+ if FDib <> nil then
+ Result := FreeImage_GetHistogram(FDib, Histo, Channel)
+ else
+ Result := False
+end;
+
+function TFreeBitmap.GetHorizontalResolution: Double;
+begin
+ Result := FreeImage_GetDotsPerMeterX(FDib) / 100
+end;
+
+function TFreeBitmap.GetImageSize: Cardinal;
+begin
+ Result := FreeImage_GetDIBSize(FDib);
+end;
+
+function TFreeBitmap.GetImageType: FREE_IMAGE_TYPE;
+begin
+ Result := FreeImage_GetImageType(FDib);
+end;
+
+function TFreeBitmap.GetInfo: PBitmapInfo;
+begin
+ Result := FreeImage_GetInfo(FDib^)
+end;
+
+function TFreeBitmap.GetInfoHeader: PBITMAPINFOHEADER;
+begin
+ Result := FreeImage_GetInfoHeader(FDib)
+end;
+
+function TFreeBitmap.GetLine: Integer;
+begin
+ Result := FreeImage_GetLine(FDib)
+end;
+
+function TFreeBitmap.GetMetadata(Model: FREE_IMAGE_MDMODEL;
+ const Key: string; var Tag: TFreeTag): Boolean;
+begin
+ Result := FreeImage_GetMetaData(Model, FDib, PChar(Key), Tag.FTag);
+end;
+
+function TFreeBitmap.GetMetadataCount(Model: FREE_IMAGE_MDMODEL): Cardinal;
+begin
+ Result := FreeImage_GetMetadataCount(Model, FDib);
+end;
+
+function TFreeBitmap.GetPalette: PRGBQUAD;
+begin
+ Result := FreeImage_GetPalette(FDib)
+end;
+
+function TFreeBitmap.GetPaletteSize: Integer;
+begin
+ Result := FreeImage_GetColorsUsed(FDib) * SizeOf(RGBQUAD)
+end;
+
+function TFreeBitmap.GetPixelColor(X, Y: Cardinal;
+ var Value: PRGBQUAD): Boolean;
+begin
+ Result := FreeImage_GetPixelColor(FDib, X, Y, Value)
+end;
+
+function TFreeBitmap.GetPixelIndex(X, Y: Cardinal;
+ var Value: PByte): Boolean;
+begin
+ Result := FreeImage_GetPixelIndex(FDib, X, Y, Value)
+end;
+
+function TFreeBitmap.GetScanLine(ScanLine: Integer): PByte;
+var
+ H: Integer;
+begin
+ H := FreeImage_GetHeight(FDib);
+ if ScanLine < H then
+ Result := FreeImage_GetScanLine(FDib, ScanLine)
+ else
+ Result := nil;
+end;
+
+function TFreeBitmap.GetScanWidth: Integer;
+begin
+ Result := FreeImage_GetPitch(FDib)
+end;
+
+function TFreeBitmap.GetTransparencyCount: Cardinal;
+begin
+ Result := FreeImage_GetTransparencyCount(FDib)
+end;
+
+function TFreeBitmap.GetTransparencyTable: PByte;
+begin
+ Result := FreeImage_GetTransparencyTable(FDib)
+end;
+
+function TFreeBitmap.GetVerticalResolution: Double;
+begin
+ Result := FreeImage_GetDotsPerMeterY(Fdib) / 100
+end;
+
+function TFreeBitmap.GetWidth: Integer;
+begin
+ Result := FreeImage_GetWidth(FDib)
+end;
+
+function TFreeBitmap.HasFileBkColor: Boolean;
+begin
+ Result := FreeImage_HasBackgroundColor(FDib)
+end;
+
+function TFreeBitmap.Invert: Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_Invert(FDib);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.IsGrayScale: Boolean;
+begin
+ Result := (FreeImage_GetBPP(FDib) = 8)
+ and (FreeImage_GetColorType(FDib) = FIC_PALETTE);
+end;
+
+function TFreeBitmap.IsTransparent: Boolean;
+begin
+ Result := FreeImage_IsTransparent(FDib);
+end;
+
+function TFreeBitmap.IsValid: Boolean;
+begin
+ Result := FDib <> nil
+end;
+
+function TFreeBitmap.Load(const FileName: string; Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+
+ // check the file signature and get its format
+ fif := FreeImage_GetFileType(PChar(Filename), 0);
+ if fif = FIF_UNKNOWN then
+ // no signature?
+ // try to guess the file format from the file extention
+ fif := FreeImage_GetFIFFromFilename(PChar(FileName));
+
+ // check that the plugin has reading capabilities ...
+ if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(FIF) then
+ begin
+ // free the previous dib
+ if FDib <> nil then
+ FreeImage_Unload(dib);
+
+ // load the file
+ FDib := FreeImage_Load(fif, PChar(FileName), Flag);
+
+ Change;
+ Result := IsValid;
+ end else
+ Result := False;
+end;
+
+function TFreeBitmap.LoadFromHandle(IO: PFreeImageIO; Handle: fi_handle;
+ Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ // check the file signature and get its format
+ fif := FreeImage_GetFileTypeFromHandle(IO, Handle, 16);
+ if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(fif) then
+ begin
+ // free the previous dib
+ if FDib <> nil then
+ FreeImage_Unload(FDib);
+
+ // load the file
+ FDib := FreeImage_LoadFromHandle(fif, IO, Handle, Flag);
+
+ Change;
+ Result := IsValid;
+ end else
+ Result := False;
+end;
+
+function TFreeBitmap.LoadFromMemory(MemIO: TFreeMemoryIO;
+ Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+
+ // check the file signature and get its format
+ fif := MemIO.GetFileType;
+ if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(fif) then
+ begin
+ // free the previous dib
+ if FDib <> nil then
+ FreeImage_Unload(FDib);
+
+ // load the file
+ FDib := MemIO.Read(fif, Flag);
+
+ Result := IsValid;
+ Change;
+ end else
+ Result := False;
+end;
+
+function TFreeBitmap.LoadFromStream(Stream: TStream;
+ Flag: Integer): Boolean;
+var
+ MemIO: TFreeMemoryIO;
+ Data: PByte;
+ MemStream: TMemoryStream;
+ Size: Cardinal;
+begin
+ Size := Stream.Size;
+
+ MemStream := TMemoryStream.Create;
+ try
+ MemStream.CopyFrom(Stream, Size);
+ Data := MemStream.Memory;
+
+ MemIO := TFreeMemoryIO.Create(Data, Size);
+ try
+ Result := LoadFromMemory(MemIO);
+ finally
+ MemIO.Free;
+ end;
+ finally
+ MemStream.Free;
+ end;
+end;
+
+function TFreeBitmap.LoadU(const FileName: WideString;
+ Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+
+ // check the file signature and get its format
+ fif := FreeImage_GetFileTypeU(PWideChar(Filename), 0);
+ if fif = FIF_UNKNOWN then
+ // no signature?
+ // try to guess the file format from the file extention
+ fif := FreeImage_GetFIFFromFilenameU(PWideChar(FileName));
+
+ // check that the plugin has reading capabilities ...
+ if (fif <> FIF_UNKNOWN) and FreeImage_FIFSupportsReading(FIF) then
+ begin
+ // free the previous dib
+ if FDib <> nil then
+ FreeImage_Unload(dib);
+
+ // load the file
+ FDib := FreeImage_LoadU(fif, PWideChar(FileName), Flag);
+
+ Change;
+ Result := IsValid;
+ end else
+ Result := False;
+end;
+
+procedure TFreeBitmap.MakeThumbnail(const Width, Height: Integer;
+ DestBitmap: TFreeBitmap);
+type
+ PRGB24 = ^TRGB24;
+ TRGB24 = packed record
+ B: Byte;
+ G: Byte;
+ R: Byte;
+ end;
+var
+ x, y, ix, iy: integer;
+ x1, x2, x3: integer;
+
+ xscale, yscale: single;
+ iRed, iGrn, iBlu, iRatio: Longword;
+ p, c1, c2, c3, c4, c5: TRGB24;
+ pt, pt1: PRGB24;
+ iSrc, iDst, s1: integer;
+ i, j, r, g, b, tmpY: integer;
+
+ RowDest, RowSource, RowSourceStart: integer;
+ w, h: Integer;
+ dxmin, dymin: integer;
+ ny1, ny2, ny3: integer;
+ dx, dy: integer;
+ lutX, lutY: array of integer;
+
+ SrcBmp, DestBmp: PFIBITMAP;
+begin
+ if not IsValid then Exit;
+
+ if (GetWidth <= ThumbSize) and (GetHeight <= ThumbSize) then
+ begin
+ DestBitmap.Assign(Self);
+ Exit;
+ end;
+
+ w := Width;
+ h := Height;
+
+ // prepare bitmaps
+ if GetBitsPerPixel <> 24 then
+ SrcBmp := FreeImage_ConvertTo24Bits(FDib)
+ else
+ SrcBmp := FDib;
+ DestBmp := FreeImage_Allocate(w, h, 24);
+ Assert(DestBmp <> nil, 'TFreeBitmap.MakeThumbnail error');
+
+{ iDst := (w * 24 + 31) and not 31;
+ iDst := iDst div 8; //BytesPerScanline
+ iSrc := (GetWidth * 24 + 31) and not 31;
+ iSrc := iSrc div 8;
+}
+ // BytesPerScanline
+ iDst := FreeImage_GetPitch(DestBmp);
+ iSrc := FreeImage_GetPitch(SrcBmp);
+
+ xscale := 1 / (w / FreeImage_GetWidth(SrcBmp));
+ yscale := 1 / (h / FreeImage_GetHeight(SrcBmp));
+
+ // X lookup table
+ SetLength(lutX, w);
+ x1 := 0;
+ x2 := trunc(xscale);
+ for x := 0 to w - 1 do
+ begin
+ lutX[x] := x2 - x1;
+ x1 := x2;
+ x2 := trunc((x + 2) * xscale);
+ end;
+
+ // Y lookup table
+ SetLength(lutY, h);
+ x1 := 0;
+ x2 := trunc(yscale);
+ for x := 0 to h - 1 do
+ begin
+ lutY[x] := x2 - x1;
+ x1 := x2;
+ x2 := trunc((x + 2) * yscale);
+ end;
+
+ Dec(w);
+ Dec(h);
+ RowDest := integer(FreeImage_GetScanLine(DestBmp, 0));
+ RowSourceStart := integer(FreeImage_GetScanLine(SrcBmp, 0));
+ RowSource := RowSourceStart;
+
+ for y := 0 to h do
+ // resampling
+ begin
+ dy := lutY[y];
+ x1 := 0;
+ x3 := 0;
+ for x := 0 to w do // loop through row
+ begin
+ dx:= lutX[x];
+ iRed:= 0;
+ iGrn:= 0;
+ iBlu:= 0;
+ RowSource := RowSourceStart;
+ for iy := 1 to dy do
+ begin
+ pt := PRGB24(RowSource + x1);
+ for ix := 1 to dx do
+ begin
+ iRed := iRed + pt.R;
+ iGrn := iGrn + pt.G;
+ iBlu := iBlu + pt.B;
+ inc(pt);
+ end;
+ RowSource := RowSource + iSrc;
+ end;
+ iRatio := 65535 div (dx * dy);
+ pt1 := PRGB24(RowDest + x3);
+ pt1.R := (iRed * iRatio) shr 16;
+ pt1.G := (iGrn * iRatio) shr 16;
+ pt1.B := (iBlu * iRatio) shr 16;
+ x1 := x1 + 3 * dx;
+ inc(x3,3);
+ end;
+ RowDest := RowDest + iDst;
+ RowSourceStart := RowSource;
+ end; // resampling
+
+ if FreeImage_GetHeight(DestBmp) >= 3 then
+ // Sharpening...
+ begin
+ s1 := integer(FreeImage_GetScanLine(DestBmp, 0));
+ iDst := integer(FreeImage_GetScanLine(DestBmp, 1)) - s1;
+ ny1 := Integer(s1);
+ ny2 := ny1 + iDst;
+ ny3 := ny2 + iDst;
+ for y := 1 to FreeImage_GetHeight(DestBmp) - 2 do
+ begin
+ for x := 0 to FreeImage_GetWidth(DestBmp) - 3 do
+ begin
+ x1 := x * 3;
+ x2 := x1 + 3;
+ x3 := x1 + 6;
+
+ c1 := pRGB24(ny1 + x1)^;
+ c2 := pRGB24(ny1 + x3)^;
+ c3 := pRGB24(ny2 + x2)^;
+ c4 := pRGB24(ny3 + x1)^;
+ c5 := pRGB24(ny3 + x3)^;
+
+ r := (c1.R + c2.R + (c3.R * -12) + c4.R + c5.R) div -8;
+ g := (c1.G + c2.G + (c3.G * -12) + c4.G + c5.G) div -8;
+ b := (c1.B + c2.B + (c3.B * -12) + c4.B + c5.B) div -8;
+
+ if r < 0 then r := 0 else if r > 255 then r := 255;
+ if g < 0 then g := 0 else if g > 255 then g := 255;
+ if b < 0 then b := 0 else if b > 255 then b := 255;
+
+ pt1 := pRGB24(ny2 + x2);
+ pt1.R := r;
+ pt1.G := g;
+ pt1.B := b;
+ end;
+ inc(ny1, iDst);
+ inc(ny2, iDst);
+ inc(ny3, iDst);
+ end;
+ end; // sharpening
+
+ if SrcBmp <> FDib then
+ FreeImage_Unload(SrcBmp);
+ DestBitmap.Replace(DestBmp);
+end;
+
+function TFreeBitmap.PasteSubImage(Src: TFreeBitmap; Left, Top,
+ Alpha: Integer): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_Paste(FDib, Src.Dib, Left, Top, Alpha);
+ Change;
+ end else
+ Result := False;
+end;
+
+function TFreeBitmap.Replace(NewDib: PFIBITMAP): Boolean;
+begin
+ Result := False;
+ if NewDib = nil then Exit;
+
+ if not DoChanging(FDib, NewDib) and IsValid then
+ FreeImage_Unload(FDib);
+
+ FDib := NewDib;
+ Result := True;
+ Change;
+end;
+
+function TFreeBitmap.Rescale(NewWidth, NewHeight: Integer;
+ Filter: FREE_IMAGE_FILTER; Dest: TFreeBitmap): Boolean;
+var
+ Bpp: Integer;
+ DstDib: PFIBITMAP;
+begin
+ Result := False;
+
+ if FDib <> nil then
+ begin
+ Bpp := FreeImage_GetBPP(FDib);
+
+ if Bpp < 8 then
+ if not ConvertToGrayscale then Exit
+ else
+ if Bpp = 16 then
+ // convert to 24-bit
+ if not ConvertTo24Bits then Exit;
+
+ // perform upsampling / downsampling
+ DstDib := FreeImage_Rescale(FDib, NewWidth, NewHeight, Filter);
+ if Dest = nil then
+ Result := Replace(DstDib)
+ else
+ Result := Dest.Replace(DstDib)
+ end
+end;
+
+function TFreeBitmap.Rotate(Angle: Double): Boolean;
+var
+ Bpp: Integer;
+ Rotated: PFIBITMAP;
+begin
+ Result := False;
+ if IsValid then
+ begin
+ Bpp := FreeImage_GetBPP(FDib);
+ if Bpp in [1, 8, 24, 32] then
+ begin
+ Rotated := FreeImage_RotateClassic(FDib, Angle);
+ Result := Replace(Rotated);
+ end
+ end;
+end;
+
+function TFreeBitmap.RotateEx(Angle, XShift, YShift, XOrigin,
+ YOrigin: Double; UseMask: Boolean): Boolean;
+var
+ Rotated: PFIBITMAP;
+begin
+ Result := False;
+ if FDib <> nil then
+ begin
+ if FreeImage_GetBPP(FDib) >= 8 then
+ begin
+ Rotated := FreeImage_RotateEx(FDib, Angle, XShift, YShift, XOrigin, YOrigin, UseMask);
+ Result := Replace(Rotated);
+ end
+ end;
+end;
+
+function TFreeBitmap.Save(const FileName: string; Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Result := False;
+
+ // try to guess the file format from the file extension
+ fif := FreeImage_GetFIFFromFilename(PChar(Filename));
+ if CanSave(fif) then
+ Result := FreeImage_Save(fif, FDib, PChar(FileName), Flag);
+end;
+
+function TFreeBitmap.SaveToHandle(fif: FREE_IMAGE_FORMAT; IO: PFreeImageIO;
+ Handle: fi_handle; Flag: Integer): Boolean;
+begin
+ Result := False;
+ if CanSave(fif) then
+ Result := FreeImage_SaveToHandle(fif, FDib, IO, Handle, Flag)
+end;
+
+function TFreeBitmap.SaveToMemory(fif: FREE_IMAGE_FORMAT;
+ MemIO: TFreeMemoryIO; Flag: Integer): Boolean;
+begin
+ Result := False;
+
+ if CanSave(fif) then
+ Result := MemIO.Write(fif, FDib, Flag)
+end;
+
+function TFreeBitmap.SaveToStream(fif: FREE_IMAGE_FORMAT; Stream: TStream;
+ Flag: Integer): Boolean;
+var
+ MemIO: TFreeMemoryIO;
+ Data: PByte;
+ Size: Cardinal;
+begin
+ MemIO := TFreeMemoryIO.Create;
+ try
+ Result := SaveToMemory(fif, MemIO, Flag);
+ if Result then
+ begin
+ MemIO.Acquire(Data, Size);
+ Stream.WriteBuffer(Data^, Size);
+ end;
+ finally
+ MemIO.Free;
+ end;
+end;
+
+function TFreeBitmap.SaveU(const FileName: WideString;
+ Flag: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Result := False;
+
+ // try to guess the file format from the file extension
+ fif := FreeImage_GetFIFFromFilenameU(PWideChar(Filename));
+ if CanSave(fif) then
+ Result := FreeImage_SaveU(fif, FDib, PWideChar(FileName), Flag);
+end;
+
+function TFreeBitmap.SetChannel(Bitmap: TFreeBitmap;
+ Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ Result := FreeImage_SetChannel(FDib, Bitmap.FDib, Channel);
+ Change;
+ end
+ else
+ Result := False
+end;
+
+procedure TFreeBitmap.SetDib(Value: PFIBITMAP);
+begin
+ Replace(Value);
+end;
+
+function TFreeBitmap.SetFileBkColor(BkColor: PRGBQuad): Boolean;
+begin
+ Result := FreeImage_SetBackgroundColor(FDib, BkColor);
+ Change;
+end;
+
+procedure TFreeBitmap.SetHorizontalResolution(Value: Double);
+begin
+ if IsValid then
+ begin
+ FreeImage_SetDotsPerMeterX(FDib, Trunc(Value * 100 + 0.5));
+ Change;
+ end;
+end;
+
+function TFreeBitmap.SetMetadata(Model: FREE_IMAGE_MDMODEL;
+ const Key: string; Tag: TFreeTag): Boolean;
+begin
+ Result := FreeImage_SetMetadata(Model, FDib, PChar(Key), Tag.Tag);
+end;
+
+function TFreeBitmap.SetPixelColor(X, Y: Cardinal;
+ Value: PRGBQUAD): Boolean;
+begin
+ Result := FreeImage_SetPixelColor(FDib, X, Y, Value);
+ Change;
+end;
+
+function TFreeBitmap.SetPixelIndex(X, Y: Cardinal; Value: PByte): Boolean;
+begin
+ Result := FreeImage_SetPixelIndex(FDib, X, Y, Value);
+ Change;
+end;
+
+function TFreeBitmap.SetSize(ImageType: FREE_IMAGE_TYPE; Width, Height,
+ Bpp: Integer; RedMask, GreenMask, BlueMask: Cardinal): Boolean;
+var
+ Pal: PRGBQuad;
+ I: Cardinal;
+begin
+ Result := False;
+
+ if FDib <> nil then
+ FreeImage_Unload(FDib);
+
+ FDib := FreeImage_Allocate(Width, Height, Bpp, RedMask, GreenMask, BlueMask);
+ if FDib = nil then Exit;
+
+ if ImageType = FIT_BITMAP then
+ case Bpp of
+ 1, 4, 8:
+ begin
+ Pal := FreeImage_GetPalette(FDib);
+ for I := 0 to FreeImage_GetColorsUsed(FDib) - 1 do
+ begin
+ Pal.rgbBlue := I;
+ Pal.rgbGreen := I;
+ Pal.rgbRed := I;
+ Inc(Pal, SizeOf(RGBQUAD));
+ end;
+ end;
+ end;
+
+ Result := True;
+ Change;
+end;
+
+procedure TFreeBitmap.SetTransparencyTable(Table: PByte; Count: Integer);
+begin
+ FreeImage_SetTransparencyTable(FDib, Table, Count);
+ Change;
+end;
+
+procedure TFreeBitmap.SetVerticalResolution(Value: Double);
+begin
+ if IsValid then
+ begin
+ FreeImage_SetDotsPerMeterY(FDib, Trunc(Value * 100 + 0.5));
+ Change;
+ end;
+end;
+
+function TFreeBitmap.SplitChannels(RedChannel, GreenChannel,
+ BlueChannel: TFreeBitmap): Boolean;
+begin
+ if FDib <> nil then
+ begin
+ RedChannel.FDib := FreeImage_GetChannel(FDib, FICC_RED);
+ GreenChannel.FDib := FreeImage_GetChannel(FDib, FICC_GREEN);
+ BlueChannel.FDib := FreeImage_GetChannel(FDib, FICC_BLUE);
+ Result := RedChannel.IsValid and GreenChannel.IsValid and BlueChannel.IsValid;
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.Threshold(T: Byte): Boolean;
+var
+ dib1: PFIBITMAP;
+begin
+ if FDib <> nil then
+ begin
+ dib1 := FreeImage_Threshold(FDib, T);
+ Result := Replace(dib1);
+ end
+ else
+ Result := False
+end;
+
+function TFreeBitmap.ToneMapping(TMO: FREE_IMAGE_TMO; FirstParam,
+ SecondParam: Double): Boolean;
+var
+ NewDib: PFIBITMAP;
+begin
+ Result := False;
+ if not IsValid then Exit;
+
+ NewDib := FreeImage_ToneMapping(Fdib, TMO, FirstParam, SecondParam);
+ Result := Replace(NewDib);
+end;
+
+{ TFreeWinBitmap }
+
+function TFreeWinBitmap.CaptureWindow(ApplicationWindow,
+ SelectedWindow: HWND): Boolean;
+var
+ XScreen, YScreen, XShift, YShift, Width, Height: Integer;
+ R: TRect;
+ dstDC, srcDC, memDC: HDC;
+ BM, oldBM: HBITMAP;
+begin
+ Result := False;
+
+ // get window size
+ GetWindowRect(SelectedWindow, R);
+
+ // check if the window is out of screen or maximized
+ XShift := 0;
+ YShift := 0;
+ XScreen := GetSystemMetrics(SM_CXSCREEN);
+ YScreen := GetSystemMetrics(SM_CYSCREEN);
+ if R.Right > XScreen then
+ R.Right := XScreen;
+ if R.Bottom > YScreen then
+ R.Bottom := YScreen;
+ if R.Left < 0 then
+ begin
+ XShift := -R.Left;
+ R.Left := 0;
+ end;
+ if R.Top < 0 then
+ begin
+ YShift := -R.Top;
+ R.Top := 0;
+ end;
+
+ Width := R.Right - R.Left;
+ Height := R.Bottom - R.Top;
+
+ if (Width <= 0) or (Height <= 0) then Exit;
+
+ // hide the application window
+ ShowWindow(ApplicationWindow, SW_HIDE);
+
+ // bring the window at the top most level
+ SetWindowPos(SelectedWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
+
+ // give enough time to refresh the window
+ Sleep(500);
+
+ // prepare the DCs
+ dstDc := GetDC(0);
+ srcDC := GetWindowDC(SelectedWindow); //full window (GetDC(SelectedWindow) = clientarea)
+ memDC := CreateCompatibleDC(dstDC);
+
+ // copy the screen to the bitmap
+ BM := CreateCompatibleBitmap(dstDC, Width, Height);
+ oldBM := HBITMAP(SelectObject(memDC, BM));
+ BitBlt(memDC, 0, 0, Width, Height, srcDC, XShift, YShift, SRCCOPY);
+
+ // redraw the application window
+ ShowWindow(ApplicationWindow, SW_SHOW);
+
+ // restore the position
+ SetWindowPos(SelectedWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
+ SetWindowPos(ApplicationWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
+
+ // convert the HBITMAP to FIBITMAP
+ CopyFromBitmap(BM);
+
+ // free objects
+ DeleteObject(SelectObject(memDC, oldBM));
+ DeleteObject(memDC);
+
+ if GetBitsPerPixel = 32 then ConvertTo24Bits;
+
+ Result := True;
+end;
+
+procedure TFreeWinBitmap.Clear;
+begin
+ if FDeleteMe then FreeImage_Unload(FDisplayDib);
+ inherited;
+end;
+
+function TFreeWinBitmap.CopyFromBitmap(HBmp: HBITMAP): Boolean;
+var
+ bm: BITMAP;
+ DC: HDC;
+ Success: Integer;
+begin
+ Result := False;
+
+ if HBmp <> 0 then
+ begin
+ // get information about the bitmap
+ GetObject(HBmp, SizeOf(BITMAP), @bm);
+
+ // create the image
+ SetSize(FIT_BITMAP, bm.bmWidth, bm.bmHeight, bm.bmBitsPixel);
+
+ // create the device context for the bitmap
+ DC := GetDC(0);
+
+ // copy the pixels
+ Success := GetDIBits(DC, // handle to DC
+ HBmp, // handle to Bitmap
+ 0, // first scan line
+ FreeImage_GetHeight(Dib), // number of scan lines to copy
+ FreeImage_GetBits(Dib), // array for bitmap bits
+ FreeImage_GetInfo(Dib^)^, // bitmap data buffer
+ DIB_RGB_COLORS // RGB
+ );
+
+ ReleaseDC(0, DC);
+
+ if Success = 0 then
+ raise Exception.Create('Error: GetDIBits failed')
+ else
+ Result := True;
+ end;
+end;
+
+function TFreeWinBitmap.CopyFromHandle(HMem: THandle): Boolean;
+var
+ Data: PByte;
+ bmih: PBitmapInfoHeader;
+ Palette: PRGBQuad;
+ Bits: PByte;
+ BitFields: array [0..2] of DWORD;
+ MaskSize: Longint;
+ image_type: FREE_IMAGE_TYPE;
+begin
+ Result := False;
+ Palette := nil;
+ BitFields[0] := 0; BitFields[1] := 0; BitFields[2] := 0;
+
+ // get a pointer to the bitmap
+ Data := GlobalLock(HMem);
+
+ // get a pointer to the bitmap header
+ bmih := PBitmapInfoHeader(Data);
+
+ // get a pointer to the palette
+ if bmih.biBitCount < 16 then
+ begin
+ Palette := PRGBQUAD(bmih);
+ Inc(PByte(Palette), SizeOf(BITMAPINFOHEADER));
+ end;
+
+ // get a pointer to the pixels
+ Bits := PByte(bmih);
+ Inc(Bits, SizeOf(BITMAPINFOHEADER) + SizeOF(RGBQUAD) * bmih.biClrUsed);
+
+ if bmih.biCompression = BI_BITFIELDS then
+ begin
+ // take into account the color masks that specify the red, green and blue
+ // components (16- and 32-bit)
+ MaskSize := 3 * SizeOf(DWORD);
+ CopyMemory(@BitFields[0], Bits, MaskSize);
+ Inc(Bits, MaskSize);
+ end;
+
+ if Data <> nil then
+ begin
+ image_type := FIT_BITMAP;
+
+ case GetFreeImageMarker(bmih) of
+ FIT_UINT16..FIT_RGBAF: image_type := GetFreeImageMarker(bmih);
+ end;
+
+ // allocate a new FIBITMAP
+ if not SetSize(image_type, bmih.biWidth, bmih.biHeight, bmih.biBitCount,
+ BitFields[2], BitFields[1], BitFields[0]) then
+ begin
+ GlobalUnlock(HMem);
+ Exit;
+ end;
+
+ // copy the bitmap header
+ CopyMemory(FreeImage_GetInfoHeader(Dib), bmih, SizeOf(BITMAPINFOHEADER));
+
+ // copy the palette
+ CopyMemory(FreeImage_GetPalette(Dib), Palette, bmih.biClrUsed * SizeOf(RGBQUAD));
+
+ // copy the bitmap
+ CopyMemory(FreeImage_GetBits(Dib), Bits, FreeImage_GetPitch(Dib) * FreeImage_GetHeight(Dib));
+
+ GlobalUnlock(HMem);
+ end;
+end;
+
+function TFreeWinBitmap.CopyToBitmapH: HBITMAP;
+var DC : HDC;
+begin
+ Result:=0;
+ if IsValid then
+ begin
+ DC:=GetDC(0);
+ Result:=CreateDIBitmap(DC,
+ FreeImage_GetInfoHeader(Dib)^,
+ CBM_INIT,
+ PAnsiChar(FreeImage_GetBits(Dib)),
+ FreeImage_GetInfo(Dib^)^,
+ DIB_RGB_COLORS);
+ ReleaseDC(0,DC);
+ end;
+end;
+
+function TFreeWinBitmap.CopyToClipBoard(NewOwner: HWND): Boolean;
+var
+ HDib: THandle;
+begin
+ Result := False;
+ HDib := CopyToHandle;
+
+ if OpenClipboard(NewOwner) and EmptyClipboard then
+ begin
+ if SetClipboardData(CF_DIB, HDib) = 0 then
+ begin
+ MessageBox(NewOwner, 'Unable to set clipboard data', 'FreeImage', MB_ICONERROR);
+ CloseClipboard;
+ Exit;
+ end;
+ end;
+ CloseClipboard;
+ Result := True;
+end;
+
+function TFreeWinBitmap.CopyToHandle: THandle;
+var
+ DibSize: Longint;
+ ADib, pdib: PByte;
+ bmih: PBITMAPINFOHEADER;
+ Pal: PRGBQuad;
+ Bits: PByte;
+begin
+ Result := 0;
+ if IsValid then
+ begin
+ // get equivalent DIB size
+ DibSize := SizeOf(BITMAPINFOHEADER);
+ Inc(DibSize, FreeImage_GetColorsUsed(Dib) * SizeOf(RGBQUAD));
+ Inc(DibSize, FreeImage_GetPitch(Dib) * FreeImage_GetHeight(Dib));
+
+ // allocate a DIB
+ Result := GlobalAlloc(GHND, DibSize);
+ ADib := GlobalLock(Result);
+
+ pdib := ADib;
+
+ // copy the BITMAPINFOHEADER
+ bmih := FreeImage_GetInfoHeader(Dib);
+ CopyMemory(pdib, bmih, SizeOf(BITMAPINFOHEADER));
+ Inc(pdib, SizeOf(BITMAPINFOHEADER));
+ if FreeImage_GetImageType(Dib) <> FIT_BITMAP then
+ SetFreeImageMarker(bmih, FDib);
+
+ // copy the palette
+ Pal := FreeImage_GetPalette(Dib);
+ CopyMemory(pdib, Pal, FreeImage_GetColorsUsed(Dib) * SizeOf(RGBQUAD));
+ Inc(pdib, FreeImage_GetColorsUsed(Dib) * SizeOf(RGBQUAD));
+
+ // copy the bitmap
+ Bits := FreeImage_GetBits(Dib);
+ CopyMemory(pdib, Bits, FreeImage_GetPitch(Dib) * FreeImage_GetHeight(Dib));
+
+ GlobalUnlock(Result);
+ end;
+end;
+
+constructor TFreeWinBitmap.Create(ImageType: FREE_IMAGE_TYPE; Width,
+ Height, Bpp: Integer);
+begin
+ inherited Create(ImageType, Width, Height, Bpp);
+
+ FDisplayDib := nil;
+ FDeleteMe := False;
+end;
+
+destructor TFreeWinBitmap.Destroy;
+begin
+ if FDeleteMe then
+ FreeImage_Unload(FDisplayDib);
+ inherited;
+end;
+
+procedure TFreeWinBitmap.Draw(DC: HDC; Rect: TRect);
+begin
+ DrawEx(DC, Rect);
+end;
+
+procedure TFreeWinBitmap.DrawEx(DC: HDC; Rect: TRect; UseFileBkg: Boolean;
+ AppBkColor: PRGBQuad; Bg: PFIBITMAP);
+var
+ ImageType: FREE_IMAGE_TYPE;
+ HasBackground, Transparent: Boolean;
+ DibDouble: PFIBITMAP;
+begin
+ if not IsValid then Exit;
+
+ // convert to standard bitmap if needed
+ if FDeleteMe then
+ begin
+ FreeImage_Unload(FDisplayDib);
+ FDisplayDib := nil;
+ FDeleteMe := False;
+ end;
+
+ ImageType := FreeImage_GetImageType(FDib);
+ if ImageType = FIT_BITMAP then
+ begin
+ HasBackground := FreeImage_HasBackgroundColor(Dib);
+ Transparent := FreeImage_IsTransparent(Dib);
+
+ if not Transparent and not HasBackground then
+ // copy pointer
+ FDisplayDib := Dib
+ else
+ begin
+ // create the transparent / alpha blended image
+ FDisplayDib := FreeImage_Composite(Dib, UseFileBkg, AppBkColor, Bg);
+ // remember to delete FDisplayDib
+ FDeleteMe := True;
+ end
+ end
+ else
+ begin
+ // convert to standard dib for display
+ if ImageType <> FIT_COMPLEX then
+ FDisplayDib := FreeImage_ConvertToStandardType(Dib, True)
+ else
+ begin
+ // convert to type FIT_DOUBLE
+ DibDouble := FreeImage_GetComplexChannel(Dib, FICC_MAG);
+ FDisplayDib := FreeImage_ConvertToStandardType(DibDouble, True);
+ // free image of type FIT_DOUBLE
+ FreeImage_Unload(DibDouble);
+ end;
+ // remember to delete FDisplayDib
+ FDeleteMe := True;
+ end;
+
+ // Draw the DIB
+ SetStretchBltMode(DC, COLORONCOLOR);
+ StretchDIBits(DC, Rect.Left, Rect.Top,
+ Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
+ 0, 0, FreeImage_GetWidth(FDisplayDib), FreeImage_GetHeight(FDisplayDib),
+ FreeImage_GetBits(FDisplayDib), FreeImage_GetInfo(FDisplayDib^)^, DIB_RGB_COLORS, SRCCOPY);
+end;
+
+function TFreeWinBitmap.PasteFromClipBoard: Boolean;
+var
+ HDib: THandle;
+begin
+ Result := False;
+ if not IsClipboardFormatAvailable(CF_DIB) then Exit;
+
+ if OpenClipboard(0) then
+ begin
+ HDib := GetClipboardData(CF_DIB);
+ CopyFromHandle(HDib);
+ Result := True;
+ end;
+ CloseClipboard;
+end;
+
+{ TFreeMultiBitmap }
+
+procedure TFreeMultiBitmap.AppendPage(Bitmap: TFreeBitmap);
+begin
+ if IsValid then
+ FreeImage_AppendPage(FMPage, Bitmap.FDib);
+end;
+
+function TFreeMultiBitmap.Close(Flags: Integer): Boolean;
+begin
+ Result := FreeImage_CloseMultiBitmap(FMPage, Flags);
+ FMPage := nil;
+end;
+
+constructor TFreeMultiBitmap.Create(KeepCacheInMemory: Boolean);
+begin
+ inherited Create;
+ FMemoryCache := KeepCacheInMemory;
+end;
+
+procedure TFreeMultiBitmap.DeletePage(Page: Integer);
+begin
+ if IsValid then
+ FreeImage_DeletePage(FMPage, Page);
+end;
+
+destructor TFreeMultiBitmap.Destroy;
+begin
+ if FMPage <> nil then Close;
+ inherited;
+end;
+
+function TFreeMultiBitmap.GetLockedPageNumbers(var Pages,
+ Count: Integer): Boolean;
+begin
+ Result := False;
+ if not IsValid then Exit;
+ Result := FreeImage_GetLockedPageNumbers(FMPage, Pages, Count)
+end;
+
+function TFreeMultiBitmap.GetPageCount: Integer;
+begin
+ Result := 0;
+ if IsValid then
+ Result := FreeImage_GetPageCount(FMPage)
+end;
+
+procedure TFreeMultiBitmap.InsertPage(Page: Integer; Bitmap: TFreeBitmap);
+begin
+ if IsValid then
+ FreeImage_InsertPage(FMPage, Page, Bitmap.FDib);
+end;
+
+function TFreeMultiBitmap.IsValid: Boolean;
+begin
+ Result := FMPage <> nil
+end;
+
+procedure TFreeMultiBitmap.LockPage(Page: Integer; DestBitmap: TFreeBitmap);
+begin
+ if not IsValid then Exit;
+
+ if Assigned(DestBitmap) then
+ begin
+ DestBitmap.Replace(FreeImage_LockPage(FMPage, Page));
+ end;
+end;
+
+function TFreeMultiBitmap.MovePage(Target, Source: Integer): Boolean;
+begin
+ Result := False;
+ if not IsValid then Exit;
+ Result := FreeImage_MovePage(FMPage, Target, Source);
+end;
+
+function TFreeMultiBitmap.Open(const FileName: string; CreateNew,
+ ReadOnly: Boolean; Flags: Integer): Boolean;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Result := False;
+
+ // try to guess the file format from the filename
+ fif := FreeImage_GetFIFFromFilename(PChar(FileName));
+
+ // check for supported file types
+ if (fif <> FIF_UNKNOWN) and (not fif in [FIF_TIFF, FIF_ICO, FIF_GIF]) then
+ Exit;
+
+ // open the stream
+ FMPage := FreeImage_OpenMultiBitmap(fif, PChar(FileName), CreateNew, ReadOnly, FMemoryCache, Flags);
+
+ Result := FMPage <> nil;
+end;
+
+procedure TFreeMultiBitmap.UnlockPage(Bitmap: TFreeBitmap;
+ Changed: Boolean);
+begin
+ if IsValid then
+ begin
+ FreeImage_UnlockPage(FMPage, Bitmap.FDib, Changed);
+ // clear the image so that it becomes invalid.
+ // don't use Bitmap.Clear method because it calls FreeImage_Unload
+ // just clear the pointer
+ Bitmap.FDib := nil;
+ Bitmap.Change;
+ end;
+end;
+
+{ TFreeMemoryIO }
+
+function TFreeMemoryIO.Acquire(var Data: PByte;
+ var SizeInBytes: DWORD): Boolean;
+begin
+ Result := FreeImage_AcquireMemory(FHMem, Data, SizeInBytes);
+end;
+
+constructor TFreeMemoryIO.Create(Data: PByte; SizeInBytes: DWORD);
+begin
+ inherited Create;
+ FHMem := FreeImage_OpenMemory(Data, SizeInBytes);
+end;
+
+destructor TFreeMemoryIO.Destroy;
+begin
+ FreeImage_CloseMemory(FHMem);
+ inherited;
+end;
+
+function TFreeMemoryIO.GetFileType: FREE_IMAGE_FORMAT;
+begin
+ Result := FreeImage_GetFileTypeFromMemory(FHMem);
+end;
+
+function TFreeMemoryIO.IsValid: Boolean;
+begin
+ Result := FHMem <> nil
+end;
+
+function TFreeMemoryIO.Read(fif: FREE_IMAGE_FORMAT;
+ Flag: Integer): PFIBITMAP;
+begin
+ Result := FreeImage_LoadFromMemory(fif, FHMem, Flag)
+end;
+
+function TFreeMemoryIO.Seek(Offset: Longint; Origin: Word): Boolean;
+begin
+ Result := FreeImage_SeekMemory(FHMem, Offset, Origin)
+end;
+
+function TFreeMemoryIO.Tell: Longint;
+begin
+ Result := FreeImage_TellMemory(FHMem)
+end;
+
+function TFreeMemoryIO.Write(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP;
+ Flag: Integer): Boolean;
+begin
+ Result := FreeImage_SaveToMemory(fif, dib, FHMem, Flag)
+end;
+
+{ TFreeTag }
+
+function TFreeTag.Clone: TFreeTag;
+var
+ CloneTag: PFITAG;
+begin
+ Result := nil;
+ if not IsValid then Exit;
+
+ CloneTag := FreeImage_CloneTag(FTag);
+ Result := TFreeTag.Create(CloneTag);
+end;
+
+constructor TFreeTag.Create(ATag: PFITAG);
+begin
+ inherited Create;
+
+ if ATag <> nil then
+ FTag := ATag
+ else
+ FTag := FreeImage_CreateTag;
+end;
+
+destructor TFreeTag.Destroy;
+begin
+ if IsValid then
+ FreeImage_DeleteTag(FTag);
+
+ inherited;
+end;
+
+function TFreeTag.GetCount: Cardinal;
+begin
+ Result := 0;
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagCount(FTag);
+end;
+
+function TFreeTag.GetDescription: string;
+begin
+ Result := '';
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagDescription(FTag);
+end;
+
+function TFreeTag.GetID: Word;
+begin
+ Result := 0;
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagID(FTag);
+end;
+
+function TFreeTag.GetKey: string;
+begin
+ Result := '';
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagKey(FTag);
+end;
+
+function TFreeTag.GetLength: Cardinal;
+begin
+ Result := 0;
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagLength(FTag);
+end;
+
+function TFreeTag.GetTagType: FREE_IMAGE_MDTYPE;
+begin
+ Result := FIDT_NOTYPE;
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagType(FTag);
+end;
+
+function TFreeTag.GetValue: Pointer;
+begin
+ Result := nil;
+ if not IsValid then Exit;
+
+ Result := FreeImage_GetTagValue(FTag);
+end;
+
+function TFreeTag.IsValid: Boolean;
+begin
+ Result := FTag <> nil;
+end;
+
+procedure TFreeTag.SetCount(const Value: Cardinal);
+begin
+ if IsValid then
+ FreeImage_SetTagCount(FTag, Value);
+end;
+
+procedure TFreeTag.SetDescription(const Value: string);
+begin
+ if IsValid then
+ FreeImage_SetTagDescription(FTag, PChar(Value));
+end;
+
+procedure TFreeTag.SetID(const Value: Word);
+begin
+ if IsValid then
+ FreeImage_SetTagID(FTag, Value);
+end;
+
+procedure TFreeTag.SetKey(const Value: string);
+begin
+ if IsValid then
+ FreeImage_SetTagKey(FTag, PChar(Value));
+end;
+
+procedure TFreeTag.SetLength(const Value: Cardinal);
+begin
+ if IsValid then
+ FreeImage_SetTagLength(FTag, Value);
+end;
+
+procedure TFreeTag.SetTagType(const Value: FREE_IMAGE_MDTYPE);
+begin
+ if IsValid then
+ FreeImage_SetTagType(FTag, Value);
+end;
+
+procedure TFreeTag.SetValue(const Value: Pointer);
+begin
+ if IsValid then
+ FreeImage_SetTagValue(FTag, Value);
+end;
+
+function TFreeTag.ToString(Model: FREE_IMAGE_MDMODEL; Make: PChar): string;
+begin
+ Result := FreeImage_TagToString(Model, FTag, Make);
+end;
+
+end.
diff --git a/Wrapper/Delphi/src/FreeImage.pas b/Wrapper/Delphi/src/FreeImage.pas
new file mode 100644
index 0000000..237fb57
--- /dev/null
+++ b/Wrapper/Delphi/src/FreeImage.pas
@@ -0,0 +1,738 @@
+unit FreeImage;
+
+// ==========================================================
+// Delphi wrapper for FreeImage 3
+//
+// Design and implementation by
+// - Simon Beavis
+// - Peter Byström
+// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+interface
+
+uses Windows;
+
+{$MINENUMSIZE 4} // Make sure enums are stored as an integer to be compatible with C/C++
+
+const
+ FIDLL = 'FreeImage.dll';
+
+// --------------------------------------------------------------------------
+// Bitmap types -------------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+ FIBITMAP = record
+ data : Pointer;
+ end;
+ PFIBITMAP = ^FIBITMAP;
+
+ FIMULTIBITMAP = record
+ data : Pointer;
+ end;
+ PFIMULTIBITMAP = ^FIMULTIBITMAP;
+
+// --------------------------------------------------------------------------
+// Indexes for byte arrays, masks and shifts for treating pixels as words ---
+// These coincide with the order of RGBQUAD and RGBTRIPLE -------------------
+// Little Endian (x86 / MS Windows, Linux) : BGR(A) order -------------------
+// --------------------------------------------------------------------------
+
+const
+ FI_RGBA_RED = 2;
+ FI_RGBA_GREEN = 1;
+ FI_RGBA_BLUE = 0;
+ FI_RGBA_ALPHA = 3;
+ FI_RGBA_RED_MASK = $00FF0000;
+ FI_RGBA_GREEN_MASK = $0000FF00;
+ FI_RGBA_BLUE_MASK = $000000FF;
+ FI_RGBA_ALPHA_MASK = $FF000000;
+ FI_RGBA_RED_SHIFT = 16;
+ FI_RGBA_GREEN_SHIFT = 8;
+ FI_RGBA_BLUE_SHIFT = 0;
+ FI_RGBA_ALPHA_SHIFT = 24;
+
+// --------------------------------------------------------------------------
+// The 16bit macros only include masks and shifts, --------------------------
+// since each color element is not byte aligned -----------------------------
+// --------------------------------------------------------------------------
+
+const
+ FI16_555_RED_MASK = $7C00;
+ FI16_555_GREEN_MASK = $03E0;
+ FI16_555_BLUE_MASK = $001F;
+ FI16_555_RED_SHIFT = 10;
+ FI16_555_GREEN_SHIFT = 5;
+ FI16_555_BLUE_SHIFT = 0;
+ FI16_565_RED_MASK = $F800;
+ FI16_565_GREEN_MASK = $07E0;
+ FI16_565_BLUE_MASK = $001F;
+ FI16_565_RED_SHIFT = 11;
+ FI16_565_GREEN_SHIFT = 5;
+ FI16_565_BLUE_SHIFT = 0;
+
+// --------------------------------------------------------------------------
+// ICC profile support ------------------------------------------------------
+// --------------------------------------------------------------------------
+
+const
+ FIICC_DEFAULT = $0;
+ FIICC_COLOR_IS_CMYK = $1;
+
+type
+ FIICCPROFILE = record
+ flags : WORD; // info flag
+ size : DWORD; // profile's size measured in bytes
+ data : Pointer; // points to a block of contiguous memory containing the profile
+ end;
+ PFIICCPROFILE = ^FIICCPROFILE;
+
+// --------------------------------------------------------------------------
+// Important enums ----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+ FREE_IMAGE_FORMAT = type Integer;
+ FREE_IMAGE_TYPE = type Integer;
+ FREE_IMAGE_COLOR_TYPE = type Integer;
+ FREE_IMAGE_QUANTIZE = type Integer;
+ FREE_IMAGE_DITHER = type Integer;
+ FREE_IMAGE_FILTER = type Integer;
+ FREE_IMAGE_COLOR_CHANNEL = type Integer;
+ FREE_IMAGE_MDTYPE = type Integer;
+ FREE_IMAGE_MDMODEL = type Integer;
+ FREE_IMAGE_JPEG_OPERATION = type Integer;
+ FREE_IMAGE_TMO = type Integer;
+
+const
+ // I/O image format identifiers.
+ FIF_UNKNOWN = FREE_IMAGE_FORMAT(-1);
+ FIF_BMP = FREE_IMAGE_FORMAT(0);
+ FIF_ICO = FREE_IMAGE_FORMAT(1);
+ FIF_JPEG = FREE_IMAGE_FORMAT(2);
+ FIF_JNG = FREE_IMAGE_FORMAT(3);
+ FIF_KOALA = FREE_IMAGE_FORMAT(4);
+ FIF_LBM = FREE_IMAGE_FORMAT(5);
+ FIF_IFF = FIF_LBM;
+ FIF_MNG = FREE_IMAGE_FORMAT(6);
+ FIF_PBM = FREE_IMAGE_FORMAT(7);
+ FIF_PBMRAW = FREE_IMAGE_FORMAT(8);
+ FIF_PCD = FREE_IMAGE_FORMAT(9);
+ FIF_PCX = FREE_IMAGE_FORMAT(10);
+ FIF_PGM = FREE_IMAGE_FORMAT(11);
+ FIF_PGMRAW = FREE_IMAGE_FORMAT(12);
+ FIF_PNG = FREE_IMAGE_FORMAT(13);
+ FIF_PPM = FREE_IMAGE_FORMAT(14);
+ FIF_PPMRAW = FREE_IMAGE_FORMAT(15);
+ FIF_RAS = FREE_IMAGE_FORMAT(16);
+ FIF_TARGA = FREE_IMAGE_FORMAT(17);
+ FIF_TIFF = FREE_IMAGE_FORMAT(18);
+ FIF_WBMP = FREE_IMAGE_FORMAT(19);
+ FIF_PSD = FREE_IMAGE_FORMAT(20);
+ FIF_CUT = FREE_IMAGE_FORMAT(21);
+ FIF_XBM = FREE_IMAGE_FORMAT(22);
+ FIF_XPM = FREE_IMAGE_FORMAT(23);
+ FIF_DDS = FREE_IMAGE_FORMAT(24);
+ FIF_GIF = FREE_IMAGE_FORMAT(25);
+ FIF_HDR = FREE_IMAGE_FORMAT(26);
+ FIF_FAXG3 = FREE_IMAGE_FORMAT(27);
+ FIF_SGI = FREE_IMAGE_FORMAT(28);
+
+ // Image type used in FreeImage.
+ FIT_UNKNOWN = FREE_IMAGE_TYPE(0); // unknown type
+ FIT_BITMAP = FREE_IMAGE_TYPE(1); // standard image: 1-, 4-, 8-, 16-, 24-, 32-bit
+ FIT_UINT16 = FREE_IMAGE_TYPE(2); // array of unsigned short: unsigned 16-bit
+ FIT_INT16 = FREE_IMAGE_TYPE(3); // array of short: signed 16-bit
+ FIT_UINT32 = FREE_IMAGE_TYPE(4); // array of unsigned long: unsigned 32-bit
+ FIT_INT32 = FREE_IMAGE_TYPE(5); // array of long: signed 32-bit
+ FIT_FLOAT = FREE_IMAGE_TYPE(6); // array of float: 32-bit IEEE floating point
+ FIT_DOUBLE = FREE_IMAGE_TYPE(7); // array of double: 64-bit IEEE floating point
+ FIT_COMPLEX = FREE_IMAGE_TYPE(8); // array of FICOMPLEX: 2 x 64-bit IEEE floating point
+ FIT_RGB16 = FREE_IMAGE_TYPE(9); // 48-bit RGB image: 3 x 16-bit
+ FIT_RGBA16 = FREE_IMAGE_TYPE(10); // 64-bit RGBA image: 4 x 16-bit
+ FIT_RGBF = FREE_IMAGE_TYPE(11); // 96-bit RGB float image: 3 x 32-bit IEEE floating point
+ FIT_RGBAF = FREE_IMAGE_TYPE(12); // 128-bit RGBA float image: 4 x 32-bit IEEE floating point
+
+ // Image color type used in FreeImage.
+ FIC_MINISWHITE = FREE_IMAGE_COLOR_TYPE(0); // min value is white
+ FIC_MINISBLACK = FREE_IMAGE_COLOR_TYPE(1); // min value is black
+ FIC_RGB = FREE_IMAGE_COLOR_TYPE(2); // RGB color model
+ FIC_PALETTE = FREE_IMAGE_COLOR_TYPE(3); // color map indexed
+ FIC_RGBALPHA = FREE_IMAGE_COLOR_TYPE(4); // RGB color model with alpha channel
+ FIC_CMYK = FREE_IMAGE_COLOR_TYPE(5); // CMYK color model
+
+ // Color quantization algorithms. Constants used in FreeImage_ColorQuantize.
+ FIQ_WUQUANT = FREE_IMAGE_QUANTIZE(0); // Xiaolin Wu color quantization algorithm
+ FIQ_NNQUANT = FREE_IMAGE_QUANTIZE(1); // NeuQuant neural-net quantization algorithm by Anthony Dekker
+
+ // Dithering algorithms. Constants used FreeImage_Dither.
+ FID_FS = FREE_IMAGE_DITHER(0); // Floyd & Steinberg error diffusion
+ FID_BAYER4x4 = FREE_IMAGE_DITHER(1); // Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+ FID_BAYER8x8 = FREE_IMAGE_DITHER(2); // Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+ FID_CLUSTER6x6 = FREE_IMAGE_DITHER(3); // Ordered clustered dot dithering (order 3 - 6x6 matrix)
+ FID_CLUSTER8x8 = FREE_IMAGE_DITHER(4); // Ordered clustered dot dithering (order 4 - 8x8 matrix)
+ FID_CLUSTER16x16 = FREE_IMAGE_DITHER(5); // Ordered clustered dot dithering (order 8 - 16x16 matrix)
+
+ // Lossless JPEG transformations Constants used in FreeImage_JPEGTransform
+ FIJPEG_OP_NONE = FREE_IMAGE_JPEG_OPERATION(0); // no transformation
+ FIJPEG_OP_FLIP_H = FREE_IMAGE_JPEG_OPERATION(1); // horizontal flip
+ FIJPEG_OP_FLIP_V = FREE_IMAGE_JPEG_OPERATION(2); // vertical flip
+ FIJPEG_OP_TRANSPOSE = FREE_IMAGE_JPEG_OPERATION(3); // transpose across UL-to-LR axis
+ FIJPEG_OP_TRANSVERSE = FREE_IMAGE_JPEG_OPERATION(4); // transpose across UR-to-LL axis
+ FIJPEG_OP_ROTATE_90 = FREE_IMAGE_JPEG_OPERATION(5); // 90-degree clockwise rotation
+ FIJPEG_OP_ROTATE_180 = FREE_IMAGE_JPEG_OPERATION(6); // 180-degree rotation
+ FIJPEG_OP_ROTATE_270 = FREE_IMAGE_JPEG_OPERATION(7); // 270-degree clockwise (or 90 ccw)
+
+ // Tone mapping operators. Constants used in FreeImage_ToneMapping.
+ FITMO_DRAGO03 = FREE_IMAGE_TMO(0); // Adaptive logarithmic mapping (F. Drago, 2003)
+ FITMO_REINHARD05 = FREE_IMAGE_TMO(1); // Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+
+ // Upsampling / downsampling filters. Constants used in FreeImage_Rescale.
+ FILTER_BOX = FREE_IMAGE_FILTER(0); // Box, pulse, Fourier window, 1st order (constant) b-spline
+ FILTER_BICUBIC = FREE_IMAGE_FILTER(1); // Mitchell & Netravali's two-param cubic filter
+ FILTER_BILINEAR = FREE_IMAGE_FILTER(2); // Bilinear filter
+ FILTER_BSPLINE = FREE_IMAGE_FILTER(3); // 4th order (cubic) b-spline
+ FILTER_CATMULLROM = FREE_IMAGE_FILTER(4); // Catmull-Rom spline, Overhauser spline
+ FILTER_LANCZOS3 = FREE_IMAGE_FILTER(5); // Lanczos3 filter
+
+ // Color channels. Constants used in color manipulation routines.
+ FICC_RGB = FREE_IMAGE_COLOR_CHANNEL(0); // Use red, green and blue channels
+ FICC_RED = FREE_IMAGE_COLOR_CHANNEL(1); // Use red channel
+ FICC_GREEN = FREE_IMAGE_COLOR_CHANNEL(2); // Use green channel
+ FICC_BLUE = FREE_IMAGE_COLOR_CHANNEL(3); // Use blue channel
+ FICC_ALPHA = FREE_IMAGE_COLOR_CHANNEL(4); // Use alpha channel
+ FICC_BLACK = FREE_IMAGE_COLOR_CHANNEL(5); // Use black channel
+ FICC_REAL = FREE_IMAGE_COLOR_CHANNEL(6); // Complex images: use real part
+ FICC_IMAG = FREE_IMAGE_COLOR_CHANNEL(7); // Complex images: use imaginary part
+ FICC_MAG = FREE_IMAGE_COLOR_CHANNEL(8); // Complex images: use magnitude
+ FICC_PHASE = FREE_IMAGE_COLOR_CHANNEL(9); // Complex images: use phase
+
+ // Tag data type information (based on TIFF specifications)
+ FIDT_NOTYPE = FREE_IMAGE_MDTYPE(0); // placeholder
+ FIDT_BYTE = FREE_IMAGE_MDTYPE(1); // 8-bit unsigned integer
+ FIDT_ASCII = FREE_IMAGE_MDTYPE(2); // 8-bit bytes w/ last byte null
+ FIDT_SHORT = FREE_IMAGE_MDTYPE(3); // 16-bit unsigned integer
+ FIDT_LONG = FREE_IMAGE_MDTYPE(4); // 32-bit unsigned integer
+ FIDT_RATIONAL = FREE_IMAGE_MDTYPE(5); // 64-bit unsigned fraction
+ FIDT_SBYTE = FREE_IMAGE_MDTYPE(6); // 8-bit signed integer
+ FIDT_UNDEFINED = FREE_IMAGE_MDTYPE(7); // 8-bit untyped data
+ FIDT_SSHORT = FREE_IMAGE_MDTYPE(8); // 16-bit signed integer
+ FIDT_SLONG = FREE_IMAGE_MDTYPE(9); // 32-bit signed integer
+ FIDT_SRATIONAL = FREE_IMAGE_MDTYPE(10); // 64-bit signed fraction
+ FIDT_FLOAT = FREE_IMAGE_MDTYPE(11); // 32-bit IEEE floating point
+ FIDT_DOUBLE = FREE_IMAGE_MDTYPE(12); // 64-bit IEEE floating point
+ FIDT_IFD = FREE_IMAGE_MDTYPE(13); // 32-bit unsigned integer (offset)
+ FIDT_PALETTE = FREE_IMAGE_MDTYPE(14); // 32-bit RGBQUAD
+
+ // Metadata models supported by FreeImage
+ FIMD_NODATA = FREE_IMAGE_MDMODEL(-1);
+ FIMD_COMMENTS = FREE_IMAGE_MDMODEL(0); // single comment or keywords
+ FIMD_EXIF_MAIN = FREE_IMAGE_MDMODEL(1); // Exif-TIFF metadata
+ FIMD_EXIF_EXIF = FREE_IMAGE_MDMODEL(2); // Exif-specific metadata
+ FIMD_EXIF_GPS = FREE_IMAGE_MDMODEL(3); // Exif GPS metadata
+ FIMD_EXIF_MAKERNOTE = FREE_IMAGE_MDMODEL(4); // Exif maker note metadata
+ FIMD_EXIF_INTEROP = FREE_IMAGE_MDMODEL(5); // Exif interoperability metadata
+ FIMD_IPTC = FREE_IMAGE_MDMODEL(6); // IPTC/NAA metadata
+ FIMD_XMP = FREE_IMAGE_MDMODEL(7); // Abobe XMP metadata
+ FIMD_GEOTIFF = FREE_IMAGE_MDMODEL(8); // GeoTIFF metadata (to be implemented)
+ FIMD_ANIMATION = FREE_IMAGE_MDMODEL(9); // Animation metadata
+ FIMD_CUSTOM = FREE_IMAGE_MDMODEL(10); // Used to attach other metadata types to a dib
+
+//{$endif}
+
+type
+ // Handle to a metadata model
+ FIMETADATA = record
+ data: Pointer;
+ end;
+ PFIMETADATA = ^FIMETADATA;
+
+ // Handle to a metadata tag
+ FITAG = record
+ data: Pointer;
+ end;
+ PFITAG = ^FITAG;
+
+// --------------------------------------------------------------------------
+// File IO routines ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+ FI_Handle = Pointer;
+ PCardinal = ^Cardinal;
+ PInt = ^Integer;
+
+ FI_ReadProc = function(buffer : pointer; size : Cardinal; count : Cardinal; handle : fi_handle) : PCardinal; stdcall;
+ FI_WriteProc = function(buffer : pointer; size, count : Cardinal; handle : FI_Handle) : PCardinal; stdcall;
+ FI_SeekProc = function(handle : fi_handle; offset : longint; origin : integer) : pint; stdcall;
+ FI_TellProc = function(handle : fi_handle) : PCardinal; stdcall;
+
+ FreeImageIO = packed record
+ read_proc : FI_ReadProc; // pointer to the function used to read data
+ write_proc: FI_WriteProc; // pointer to the function used to write data
+ seek_proc : FI_SeekProc; // pointer to the function used to seek
+ tell_proc : FI_TellProc; // pointer to the function used to aquire the current position
+ end;
+ PFreeImageIO = ^FreeImageIO;
+
+ // Handle to a memory I/O stream
+ FIMEMORY = record
+ data: Pointer;
+ end;
+ PFIMEMORY = ^FIMEMORY;
+
+const
+ // constants used in FreeImage_Seek for Origin parameter
+ SEEK_SET = 0;
+ SEEK_CUR = 1;
+ SEEK_END = 2;
+
+// --------------------------------------------------------------------------
+// Plugin routines ----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+type
+ PPluginStruct = ^PluginStruct;
+
+ FI_InitProc = procedure(Plugin: PPluginStruct; Format_ID: Integer); stdcall;
+ FI_FormatProc = function: PChar; stdcall;
+ FI_DescriptionProc = function: PChar; stdcall;
+ FI_ExtensionListProc = function: PChar; stdcall;
+ FI_RegExprProc = function: PChar; stdcall;
+ FI_OpenProc = function(IO: PFreeImageIO; Handle: FI_Handle; Read: Boolean): Pointer; stdcall;
+ FI_CloseProc = procedure(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer); stdcall;
+ FI_PageCountProc = function(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer): Integer; stdcall;
+ FI_PageCapabilityProc = function(IO: PFreeImageIO; Handle: FI_Handle; Data: Pointer): integer; stdcall;
+ FI_LoadProc = function(IO: PFreeImageIO; Handle: FI_Handle; Page, Flags: Integer; data: pointer): PFIBITMAP; stdcall;
+ FI_SaveProc = function(IO: PFreeImageIO; Dib: PFIBITMAP; Handle: FI_Handle; Page, Flags: Integer; Data: Pointer): Boolean; stdcall;
+ FI_ValidateProc = function(IO: PFreeImageIO; Handle: FI_Handle): Boolean; stdcall;
+ FI_MimeProc = function: PChar; stdcall;
+ FI_SupportsExportBPPProc = function(Bpp: integer): boolean; stdcall;
+ FI_SupportsExportTypeProc = function(AType: FREE_IMAGE_TYPE): Boolean; stdcall;
+ FI_SupportsICCProfilesProc = function: Boolean; stdcall;
+
+ PluginStruct = record
+ format_proc: FI_FormatProc;
+ description_proc: FI_DescriptionProc;
+ extension_proc: FI_ExtensionListProc;
+ regexpr_proc: FI_RegExprProc;
+ open_proc: FI_OpenProc;
+ close_proc: FI_CloseProc;
+ pagecount_proc: FI_PageCountProc;
+ pagecapability_proc: FI_PageCapabilityProc;
+ load_proc: FI_LoadProc;
+ save_proc: FI_SaveProc;
+ validate_proc: FI_ValidateProc;
+ mime_proc: FI_MimeProc;
+ supports_export_bpp_proc: FI_SupportsExportBPPProc;
+ supports_export_type_proc: FI_SupportsExportTypeProc;
+ supports_icc_profiles_proc: FI_SupportsICCProfilesProc;
+ end;
+
+// --------------------------------------------------------------------------
+// Load/Save flag constants -------------------------------------------------
+// --------------------------------------------------------------------------
+
+const
+ BMP_DEFAULT = 0;
+ BMP_SAVE_RLE = 1;
+ CUT_DEFAULT = 0;
+ DDS_DEFAULT = 0;
+ FAXG3_DEFAULT = 0;
+ GIF_DEFAULT = 0;
+ ICO_DEFAULT = 0;
+ ICO_MAKEALPHA = 1; // convert to 32bpp and create an alpha channel from the AND-mask when loading
+ IFF_DEFAULT = 0;
+ JPEG_DEFAULT = 0;
+ JPEG_FAST = 1;
+ JPEG_ACCURATE = 2;
+ JPEG_QUALITYSUPERB = $0080;
+ JPEG_QUALITYGOOD = $0100;
+ JPEG_QUALITYNORMAL = $0200;
+ JPEG_QUALITYAVERAGE = $0400;
+ JPEG_QUALITYBAD = $0800;
+ JPEG_CMYK = $1000; // load separated CMYK "as is" (use | to combine with other flags)
+ KOALA_DEFAULT = 0;
+ LBM_DEFAULT = 0;
+ MNG_DEFAULT = 0;
+ PCD_DEFAULT = 0;
+ PCD_BASE = 1; // load the bitmap sized 768 x 512
+ PCD_BASEDIV4 = 2; // load the bitmap sized 384 x 256
+ PCD_BASEDIV16 = 3; // load the bitmap sized 192 x 128
+ PCX_DEFAULT = 0;
+ PNG_DEFAULT = 0;
+ PNG_IGNOREGAMMA = 1; // avoid gamma correction
+ PNM_DEFAULT = 0;
+ PNM_SAVE_RAW = 0; // If set the writer saves in RAW format (i.e. P4, P5 or P6)
+ PNM_SAVE_ASCII = 1; // If set the writer saves in ASCII format (i.e. P1, P2 or P3)
+ PSD_DEFAULT = 0;
+ RAS_DEFAULT = 0;
+ SGI_DEFAULT = 0;
+ TARGA_DEFAULT = 0;
+ TARGA_LOAD_RGB888 = 1; // If set the loader converts RGB555 and ARGB8888 -> RGB888.
+ TIFF_DEFAULT = 0;
+ TIFF_CMYK = $0001; // reads/stores tags for separated CMYK (use | to combine with compression flags)
+ TIFF_PACKBITS = $0100; // save using PACKBITS compression
+ TIFF_DEFLATE = $0200; // save using DEFLATE compression
+ TIFF_ADOBE_DEFLATE = $0400; // save using ADOBE DEFLATE compression
+ TIFF_NONE = $0800; // save without any compression
+ TIFF_CCITTFAX3 = $1000; // save using CCITT Group 3 fax encoding
+ TIFF_CCITTFAX4 = $2000; // save using CCITT Group 4 fax encoding
+ TIFF_LZW = $4000; // save using LZW compression
+ TIFF_JPEG = $8000; // save using JPEG compression
+ WBMP_DEFAULT = 0;
+ XBM_DEFAULT = 0;
+ XPM_DEFAULT = 0;
+
+// --------------------------------------------------------------------------
+// Init/Error routines ------------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_Initialise(load_local_plugins_only : boolean = False); stdcall; external FIDLL name '_FreeImage_Initialise@4';
+procedure FreeImage_DeInitialise; stdcall; external FIDLL name '_FreeImage_DeInitialise@0';
+
+// --------------------------------------------------------------------------
+// Version routines ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetVersion : PChar; stdcall; external FIDLL name '_FreeImage_GetVersion@0';
+function FreeImage_GetCopyrightMessage : PChar; stdcall; external FIDLL name '_FreeImage_GetCopyrightMessage@0';
+
+// --------------------------------------------------------------------------
+// Message output functions -------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_OutPutMessageProc(fif: Integer; fmt: PChar); stdcall; external FIDLL name 'FreeImage_OutputMessageProc';
+type FreeImage_OutputMessageFunction = function(fif: FREE_IMAGE_FORMAT; msg: PChar): pointer; stdcall;
+procedure FreeImage_SetOutputMessage(omf: FreeImage_OutputMessageFunction); stdcall; external FIDLL name '_FreeImage_SetOutputMessage@4';
+
+// --------------------------------------------------------------------------
+// Allocate/Unload routines -------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_Allocate(width, height, bpp: integer; red_mask: Cardinal = 0; green_mask: Cardinal = 0; blue_mask: Cardinal = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Allocate@24';
+function FreeImage_AllocateT(Atype: FREE_IMAGE_TYPE; Width, Height: Integer; bpp: Integer = 8; red_mask: Cardinal = 0; green_mask: Cardinal = 0; blue_mask: Cardinal = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_AllocateT@28';
+function FreeImage_Clone(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Clone@4';
+procedure FreeImage_Unload(dib: PFIBITMAP); stdcall; external FIDLL name '_FreeImage_Unload@4';
+
+// --------------------------------------------------------------------------
+// Load / Save routines -----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_Load(fif: FREE_IMAGE_FORMAT; const filename: PChar; flags: integer = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Load@12';
+function FreeImage_LoadU(fif: FREE_IMAGE_FORMAT; const filename: PWideChar; flags: Integer = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_LoadU@12';
+function FreeImage_LoadFromHandle(fif: FREE_IMAGE_FORMAT; io: PFreeImageIO; handle: fi_handle; flags: integer = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_LoadFromHandle@16';
+function FreeImage_Save(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; filename: PChar; flags: integer = 0): Boolean; stdcall; external FIDLL name '_FreeImage_Save@16';
+function FreeImage_SaveU(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; const filename: PWideChar; flags: Integer = 0): Boolean; stdcall; external FIDLL name '_FreeImage_SaveU@16';
+function FreeImage_SaveToHandle(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; io : PFreeImageIO; handle : fi_handle; flags : integer = 0) : Boolean; stdcall; external FIDLL name '_FreeImage_SaveToHandle@20';
+
+// --------------------------------------------------------------------------
+// Memory I/O stream routines -----------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_OpenMemory(data: PByte = nil; size_in_bytes: DWORD = 0): PFIMEMORY; stdcall; external FIDLL name '_FreeImage_OpenMemory@8';
+procedure FreeImage_CloseMemory(stream: PFIMEMORY); stdcall; external FIDLL name '_FreeImage_CloseMemory@4';
+function FreeImage_LoadFromMemory(fif: FREE_IMAGE_FORMAT; stream: PFIMEMORY; flags: Integer = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_LoadFromMemory@12';
+function FreeImage_SaveToMemory(fif: FREE_IMAGE_FORMAT; dib: PFIBITMAP; stream: PFIMEMORY; flags: Integer = 0): Boolean; stdcall; external FIDLL name '_FreeImage_SaveToMemory@16';
+function FreeImage_TellMemory(stream: PFIMEMORY): Longint; stdcall; external FIDLL name '_FreeImage_TellMemory@4';
+function FreeImage_SeekMemory(stream: PFIMEMORY; offset: Longint; origin: Integer): Boolean; stdcall; external FIDLL name '_FreeImage_SeekMemory@12';
+function FreeImage_AcquireMemory(stream: PFIMEMORY; var data: PByte; var size_in_bytes: DWORD): Boolean; stdcall; external FIDLL name '_FreeImage_AcquireMemory@12';
+
+// --------------------------------------------------------------------------
+// Plugin Interface ---------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_RegisterLocalPlugin(proc_address: FI_InitProc; format, description, extension, regexpr: PChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_RegisterLocalPlugin@20';
+function FreeImage_RegisterExternalPlugin(path, format, description, extension, regexpr: PChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_RegisterExternalPlugin@20';
+function FreeImage_GetFIFCount: Integer; stdcall; external FIDLL name '_FreeImage_GetFIFCount@0';
+procedure FreeImage_SetPluginEnabled(fif: FREE_IMAGE_FORMAT; enable: Boolean); stdcall; external FIDLL Name '_FreeImage_SetPluginEnabled@8';
+function FreeImage_IsPluginEnabled(fif: FREE_IMAGE_FORMAT): Integer; stdcall; external FIDLL Name '_FreeImage_IsPluginEnabled@4';
+function FreeImage_GetFIFFromFormat(const format: PChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL Name '_FreeImage_GetFIFFromFormat@4';
+function FreeImage_GetFIFFromMime(const format: PChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL Name '_FreeImage_GetFIFFromMime@4';
+function FreeImage_GetFormatFromFIF(fif: FREE_IMAGE_FORMAT): PChar; stdcall; external FIDLL Name '_FreeImage_GetFormatFromFIF@4';
+function FreeImage_GetFIFExtensionList(fif: FREE_IMAGE_FORMAT): PChar; stdcall; external FIDLL Name '_FreeImage_GetFIFExtensionList@4';
+function FreeImage_GetFIFDescription(fif: FREE_IMAGE_FORMAT): PChar; stdcall; external FIDLL Name '_FreeImage_GetFIFDescription@4';
+function FreeImage_GetFIFRegExpr(fif: FREE_IMAGE_FORMAT): PChar; stdcall; external FIDLL Name '_FreeImage_GetFIFRegExpr@4';
+function FreeImage_GetFIFFromFilename(const fname: PChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL Name '_FreeImage_GetFIFFromFilename@4';
+function FreeImage_GetFIFFromFilenameU(const fname:PWideChar): FREE_IMAGE_FORMAT; stdcall; external FIDLL Name '_FreeImage_GetFIFFromFilenameU@4';
+function FreeImage_FIFSupportsReading(fif: FREE_IMAGE_FORMAT): Boolean; stdcall; external FIDLL Name '_FreeImage_FIFSupportsReading@4';
+function FreeImage_FIFSupportsWriting(fif: FREE_IMAGE_FORMAT): Boolean; stdcall; external FIDLL Name '_FreeImage_FIFSupportsWriting@4';
+function FreeImage_FIFSupportsExportBPP(fif: FREE_IMAGE_FORMAT; bpp: Integer): Boolean; stdcall; external FIDLL Name '_FreeImage_FIFSupportsExportBPP@8';
+function FreeImage_FIFSupportsICCProfiles(fif: FREE_IMAGE_FORMAT): Boolean; stdcall; external FIDLL Name '_FreeImage_FIFSupportsICCProfiles@4';
+function FreeImage_FIFSupportsExportType(fif: FREE_IMAGE_FORMAT; image_type: FREE_IMAGE_TYPE): Boolean; stdcall; external FIDLL name '_FreeImage_FIFSupportsExportType@8';
+
+// --------------------------------------------------------------------------
+// Multipaging interface ----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_OpenMultiBitmap(fif: FREE_IMAGE_FORMAT; filename: PChar; create_new, read_only, keep_cache_in_memory: Boolean; flags: integer = 0): PFIMULTIBITMAP; stdcall; external FIDLL Name '_FreeImage_OpenMultiBitmap@24';
+function FreeImage_CloseMultiBitmap(bitmap: PFIMULTIBITMAP; flags: Integer = 0): Boolean; stdcall; external FIDLL Name '_FreeImage_CloseMultiBitmap@8';
+function FreeImage_GetPageCount(bitmap: PFIMULTIBITMAP): Integer; stdcall; external FIDLL Name '_FreeImage_GetPageCount@4';
+procedure FreeImage_AppendPage(bitmap: PFIMULTIBITMAP; data: PFIBITMAP); stdcall; external FIDLL Name '_FreeImage_AppendPage@8';
+procedure FreeImage_InsertPage(bitmap: PFIMULTIBITMAP; page: Integer; data: PFIBITMAP); stdcall; external FIDLL Name '_FreeImage_InsertPage@12';
+procedure FreeImage_DeletePage(bitmap: PFIMULTIBITMAP; page: Integer); stdcall; external FIDLL Name '_FreeImage_DeletePage@8';
+function FreeImage_LockPage(bitmap: PFIMULTIBITMAP; page: Integer): PFIBITMAP; stdcall; external FIDLL Name '_FreeImage_LockPage@8';
+procedure FreeImage_UnlockPage(bitmap: PFIMULTIBITMAP; page: PFIBITMAP; changed: boolean); stdcall; external FIDLL Name '_FreeImage_UnlockPage@12';
+function FreeImage_MovePage(bitmap: PFIMULTIBITMAP; target, source: Integer): Boolean; stdcall; external FIDLL Name '_FreeImage_MovePage@12';
+function FreeImage_GetLockedPageNumbers(bitmap: PFIMULTIBITMAP; var pages: Integer; var count : integer): Boolean; stdcall; external FIDLL Name '_FreeImage_GetLockedPageNumbers@12';
+
+// --------------------------------------------------------------------------
+// Filetype request routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetFileType(const filename: PChar; size: Integer): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_GetFileType@8';
+function FreeImage_GetFileTypeU(const filename: PWideChar; size: Integer): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_GetFileTypeU@8';
+function FreeImage_GetFileTypeFromHandle(io: PFreeImageIO; handle: FI_Handle; size: Integer = 0): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_GetFileTypeFromHandle@12';
+function FreeImage_GetFileTypeFromMemory(stream: PFIMEMORY; size: Integer = 0): FREE_IMAGE_FORMAT; stdcall; external FIDLL name '_FreeImage_GetFileTypeFromMemory@8';
+
+// --------------------------------------------------------------------------
+// ImageType request routine ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetImageType(dib: PFIBITMAP): FREE_IMAGE_TYPE; stdcall; external FIDLL name '_FreeImage_GetImageType@4';
+
+// --------------------------------------------------------------------------
+// FreeImage helper routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_IsLittleEndian: Boolean; stdcall; external FIDLL name '_FreeImage_IsLittleEndian@0';
+function FreeImage_LookupX11Color(const szColor: PChar; var nRed, nGreen, nBlue: PByte): Boolean; stdcall; external FIDLL name '_FreeImage_LookupX11Color@16';
+function FreeImage_LookupSVGColor(const szColor: PChar; var nRed, nGreen, nBlue: PByte): Boolean; stdcall; external FIDLL name '_FreeImage_LookupSVGColor@16';
+
+// --------------------------------------------------------------------------
+// Pixels access routines ---------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetBits(dib: PFIBITMAP): PByte; stdcall; external FIDLL name '_FreeImage_GetBits@4';
+function FreeImage_GetScanLine(dib: PFIBITMAP; scanline: Integer): PByte; stdcall; external FIDLL name '_FreeImage_GetScanLine@8';
+
+function FreeImage_GetPixelIndex(dib: PFIBITMAP; X, Y: Longint; Value: PByte): Boolean; stdcall; external FIDLL name '_FreeImage_GetPixelIndex@16';
+function FreeImage_GetPixelColor(dib: PFIBITMAP; X, Y: Longint; Value: PRGBQuad): Boolean; stdcall; external FIDLL name '_FreeImage_GetPixelColor@16';
+function FreeImage_SetPixelIndex(dib: PFIBITMAP; X, Y: Longint; Value: PByte): Boolean; stdcall; external FIDLL name '_FreeImage_SetPixelIndex@16';
+function FreeImage_SetPixelColor(dib: PFIBITMAP; X, Y: Longint; Value: PRGBQuad): Boolean; stdcall; external FIDLL name '_FreeImage_SetPixelColor@16';
+
+// --------------------------------------------------------------------------
+// DIB info routines --------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetColorsUsed(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetColorsUsed@4';
+function FreeImage_GetBPP(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetBPP@4';
+function FreeImage_GetWidth(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetWidth@4';
+function FreeImage_GetHeight(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetHeight@4';
+function FreeImage_GetLine(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetLine@4';
+function FreeImage_GetPitch(dib : PFIBITMAP) : Cardinal; stdcall; external FIDLL name '_FreeImage_GetPitch@4';
+function FreeImage_GetDIBSize(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetDIBSize@4';
+function FreeImage_GetPalette(dib: PFIBITMAP): PRGBQUAD; stdcall; external FIDLL name '_FreeImage_GetPalette@4';
+
+function FreeImage_GetDotsPerMeterX(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetDotsPerMeterX@4';
+function FreeImage_GetDotsPerMeterY(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetDotsPerMeterY@4';
+procedure FreeImage_SetDotsPerMeterX(dib: PFIBITMAP; res: Cardinal); stdcall; external FIDLL name '_FreeImage_SetDotsPerMeterX@8';
+procedure FreeImage_SetDotsPerMeterY(dib: PFIBITMAP; res: Cardinal); stdcall; external FIDLL name '_FreeImage_SetDotsPerMeterY@8';
+
+function FreeImage_GetInfoHeader(dib: PFIBITMAP): PBITMAPINFOHEADER; stdcall; external FIDLL name '_FreeImage_GetInfoHeader@4';
+function FreeImage_GetInfo(var dib: FIBITMAP): PBITMAPINFO; stdcall; external FIDLL name '_FreeImage_GetInfo@4';
+function FreeImage_GetColorType(dib: PFIBITMAP): FREE_IMAGE_COLOR_TYPE; stdcall; external FIDLL name '_FreeImage_GetColorType@4';
+
+function FreeImage_GetRedMask(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetRedMask@4';
+function FreeImage_GetGreenMask(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetGreenMask@4';
+function FreeImage_GetBlueMask(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetBlueMask@4';
+
+function FreeImage_GetTransparencyCount(dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetTransparencyCount@4';
+function FreeImage_GetTransparencyTable(dib: PFIBITMAP): PByte; stdcall; external FIDLL name '_FreeImage_GetTransparencyTable@4';
+procedure FreeImage_SetTransparent(dib: PFIBITMAP; enabled: boolean); stdcall; external FIDLL name '_FreeImage_SetTransparent@8';
+procedure FreeImage_SetTransparencyTable(dib: PFIBITMAP; table: PByte; count: integer); stdcall; external FIDLL name '_FreeImage_SetTransparencyTable@12';
+function FreeImage_IsTransparent(dib: PFIBITMAP): boolean; stdcall; external FIDLL name '_FreeImage_IsTransparent@4';
+
+function FreeImage_HasBackgroundColor(dib: PFIBITMAP): Boolean; stdcall; external FIDLL name '_FreeImage_HasBackgroundColor@4';
+function FreeImage_GetBackgroundColor(dib: PFIBITMAP; var bkcolor: PRGBQUAD): Boolean; stdcall; external FIDLL name '_FreeImage_GetBackgroundColor@8';
+function FreeImage_SetBackgroundColor(dib: PFIBITMAP; bkcolor: PRGBQUAD): Boolean; stdcall; external FIDLL name '_FreeImage_SetBackgroundColor@8';
+
+// --------------------------------------------------------------------------
+// ICC profile routines -----------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_GetICCProfile(var dib: FIBITMAP): PFIICCPROFILE; stdcall; external FIDLL name '_FreeImage_GetICCProfile@4';
+function FreeImage_CreateICCProfile(var dib: FIBITMAP; data: Pointer; size: Longint): PFIICCPROFILE; stdcall; external FIDLL name 'FreeImage_CreateICCProfile@12';
+procedure FreeImage_DestroyICCProfile(var dib : FIBITMAP); stdcall; external FIDLL name 'FreeImage_DestroyICCProfile@4';
+
+// --------------------------------------------------------------------------
+// Line conversion routines -------------------------------------------------
+// --------------------------------------------------------------------------
+
+procedure FreeImage_ConvertLine1To4(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine1To4@12';
+procedure FreeImage_ConvertLine8To4(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQuad); stdcall; external FIDLL name '_FreeImage_ConvertLine8To4@16';
+procedure FreeImage_ConvertLine16To4_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To4_555@12';
+procedure FreeImage_ConvertLine16To4_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To4_565@12';
+procedure FreeImage_ConvertLine24To4(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine24To4@12';
+procedure FreeImage_ConvertLine32To4(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine32To4@12';
+
+procedure FreeImage_ConvertLine1To8(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine1To8@12';
+procedure FreeImage_ConvertLine4To8(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine4To8@12';
+procedure FreeImage_ConvertLine16To8_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To8_555@12';
+procedure FreeImage_ConvertLine16To8_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To8_565@12';
+procedure FreeImage_ConvertLine24To8(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine24To8@12';
+procedure FreeImage_ConvertLine32To8(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine32To8@12';
+
+procedure FreeImage_ConvertLine1To16_555(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine1To16_555@16';
+procedure FreeImage_ConvertLine4To16_555(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine4To16_555@16';
+procedure FreeImage_ConvertLine8To16_555(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine8To16_555@16';
+procedure FreeImage_ConvertLine16_565_To16_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16_565_To16_555@12';
+procedure FreeImage_ConvertLine24To16_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine24To16_555@12';
+procedure FreeImage_ConvertLine32To16_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine32To16_555@12';
+
+procedure FreeImage_ConvertLine1To16_565(target, source : PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine1To16_565@16';
+procedure FreeImage_ConvertLine4To16_565(target, source : PBYTE; width_in_pixels : Integer; palette : PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine4To16_565@16';
+procedure FreeImage_ConvertLine8To16_565(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine8To16_565@16';
+procedure FreeImage_ConvertLine16_555_To16_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16_555_To16_565@12';
+procedure FreeImage_ConvertLine24To16_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine24To16_565@12';
+procedure FreeImage_ConvertLine32To16_565(target, source : PBYTE; width_in_pixels : Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine32To16_565@12';
+
+procedure FreeImage_ConvertLine1To24(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine1To24@16';
+procedure FreeImage_ConvertLine4To24(target, source : PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine4To24@16';
+procedure FreeImage_ConvertLine8To24(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine8To24@16';
+procedure FreeImage_ConvertLine16To24_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To24_555@12';
+procedure FreeImage_ConvertLine16To24_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To24_565@12';
+procedure FreeImage_ConvertLine32To24(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine32To24@12';
+
+procedure FreeImage_ConvertLine1To32(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine1To32@16';
+procedure FreeImage_ConvertLine4To32(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine4To32@16';
+procedure FreeImage_ConvertLine8To32(target, source: PBYTE; width_in_pixels: Integer; palette: PRGBQUAD); stdcall; external FIDLL name '_FreeImage_ConvertLine8To32@16';
+procedure FreeImage_ConvertLine16To32_555(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To32_555@12';
+procedure FreeImage_ConvertLine16To32_565(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine16To32_565@12';
+procedure FreeImage_ConvertLine24To32(target, source: PBYTE; width_in_pixels: Integer); stdcall; external FIDLL name '_FreeImage_ConvertLine24To32@12';
+
+// --------------------------------------------------------------------------
+// Smart conversion routines ------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_ConvertTo4Bits(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo4Bits@4';
+function FreeImage_ConvertTo8Bits(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo8Bits@4';
+function FreeImage_ConvertToGreyscale(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertToGreyscale@4';
+function FreeImage_ConvertTo16Bits555(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo16Bits555@4';
+function FreeImage_ConvertTo16Bits565(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo16Bits565@4';
+function FreeImage_ConvertTo24Bits(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo24Bits@4';
+function FreeImage_ConvertTo32Bits(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertTo32Bits@4';
+function FreeImage_ColorQuantize(dib: PFIBITMAP; quantize: FREE_IMAGE_QUANTIZE): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ColorQuantize@8';
+function FreeImage_ColorQuantizeEx(dib: PFIBITMAP; quantize: FREE_IMAGE_QUANTIZE = FIQ_WUQUANT; PaletteSize: Integer = 256; ReserveSize: Integer = 0; ReservePalette: PRGBQuad = nil): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ColorQuantizeEx@20';
+function FreeImage_Threshold(dib: PFIBITMAP; T: Byte): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Threshold@8';
+function FreeImage_Dither(dib: PFIBITMAP; algorithm: FREE_IMAGE_DITHER): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Dither@8';
+
+function FreeImage_ConvertFromRawBits(bits: PBYTE; width, height, pitch: Integer; bpp, red_mask, green_mask, blue_mask: LongWord; topdown: Boolean): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertFromRawBits@36';
+procedure FreeImage_ConvertToRawBits(bits: PBYTE; dib: PFIBITMAP; pitch: Integer; bpp, red_mask, green_mask, blue_mask: LongWord; topdown: Boolean); stdcall; external FIDLL name '_FreeImage_ConvertToRawBits@32';
+
+function FreeImage_ConvertToRGBF(dib: PFIBITMAP): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertToRGBF@4';
+
+function FreeImage_ConvertToStandardType(src: PFIBITMAP; scale_linear: Boolean = True): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertToStandardType@8';
+function FreeImage_ConvertToType(src: PFIBITMAP; dst_type: FREE_IMAGE_TYPE; scale_linear: Boolean = True): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ConvertToType@12';
+
+// tone mapping operators
+function FreeImage_ToneMapping(dib: PFIBITMAP; tmo: FREE_IMAGE_TMO; first_param: Double = 0; second_param: Double = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_ToneMapping@24';
+function FreeImage_TmoDrago03(src: PFIBITMAP; gamma: Double = 2.2; exposure: Double = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_TmoDrago03@20';
+function FreeImage_TmoReinhard05(src: PFIBITMAP; intensity: Double = 0; contrast: Double = 0): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_TmoReinhard05@20';
+
+// --------------------------------------------------------------------------
+// ZLib interface -----------------------------------------------------------
+// --------------------------------------------------------------------------
+
+function FreeImage_ZLibCompress(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; stdcall; external FIDLL name '_FreeImage_ZLibCompress@16';
+function FreeImage_ZLibUncompress(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; stdcall; external FIDLL name '_FreeImage_ZLibUncompress@16';
+
+function FreeImage_ZLibGZip(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; stdcall; external FIDLL name '_FreeImage_ZLibGZip@16';
+function FreeImage_ZLibGUnzip(target: PBYTE; target_size: DWORD; source: PBYTE; source_size: DWORD): DWORD; stdcall; external FIDLL name '_FreeImage_ZLibGUnzip@16';
+function FreeImage_ZLibCRC32(crc: DWORD; source: PByte; source_size: DWORD): DWORD; stdcall; external FIDLL name '_FreeImage_ZLibCRC32@12';
+
+// --------------------------------------------------------------------------
+// Metadata routines --------------------------------------------------------
+// --------------------------------------------------------------------------
+
+// tag creation / destruction
+function FreeImage_CreateTag: PFITAG; stdcall; external FIDLL name '_FreeImage_CreateTag@0';
+procedure FreeImage_DeleteTag(tag: PFITAG); stdcall; external FIDLL name '_FreeImage_DeleteTag@4';
+function FreeImage_CloneTag(tag: PFITAG): PFITAG; stdcall; external FIDLL name '_FreeImage_CloneTag@4';
+
+// tag getters and setters
+function FreeImage_GetTagKey(tag: PFITAG): PChar; stdcall; external FIDLL name '_FreeImage_GetTagKey@4';
+function FreeImage_GetTagDescription(tag: PFITAG): PChar; stdcall; external FIDLL name '_FreeImage_GetTagDescription@4';
+function FreeImage_GetTagID(tag: PFITAG): Word; stdcall; external FIDLL name '_FreeImage_GetTagID@4';
+function FreeImage_GetTagType(tag: PFITAG): FREE_IMAGE_MDTYPE; stdcall; external FIDLL name '_FreeImage_GetTagType@4';
+function FreeImage_GetTagCount(tag: PFITAG): DWORD; stdcall; external FIDLL name '_FreeImage_GetTagCount@4';
+function FreeImage_GetTagLength(tag: PFITAG): DWORD; stdcall; external FIDLL name '_FreeImage_GetTagLength@4';
+function FreeImage_GetTagValue(tag: PFITAG): Pointer; stdcall; external FIDLL name '_FreeImage_GetTagValue@4';
+
+function FreeImage_SetTagKey(tag: PFITAG; const key: PChar): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagKey@8';
+function FreeImage_SetTagDescription(tag: PFITAG; const description: PChar): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagDescription@8';
+function FreeImage_SetTagID(tag: PFITAG; id: Word): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagID@8';
+function FreeImage_SetTagType(tag: PFITAG; atype: FREE_IMAGE_MDTYPE): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagType@8';
+function FreeImage_SetTagCount(tag: PFITAG; count: DWORD): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagCount@8';
+function FreeImage_SetTagLength(tag: PFITAG; length: DWORD): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagLength@8';
+function FreeImage_SetTagValue(tag: PFITAG; const value: Pointer): Boolean; stdcall; external FIDLL name '_FreeImage_SetTagValue@8';
+
+// iterator
+function FreeImage_FindFirstMetadata(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; var tag: PFITAG): PFIMETADATA; stdcall; external FIDLL name '_FreeImage_FindFirstMetadata@12';
+function FreeImage_FindNextMetadata(mdhandle: PFIMETADATA; var tag: PFITAG): Boolean; stdcall; external FIDLL name '_FreeImage_FindNextMetadata@8';
+procedure FreeImage_FindCloseMetadata(mdhandle: PFIMETADATA); stdcall; external FIDLL name '_FreeImage_FindCloseMetadata@4';
+
+// metadata setter and getter
+function FreeImage_SetMetadata(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; const key: PChar; tag: PFITAG): Boolean; stdcall; external FIDLL name '_FreeImage_SetMetadata@16';
+function FreeImage_GetMetaData(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP; const key: PChar; var tag: PFITAG): Boolean; stdcall; external FIDLL name '_FreeImage_GetMetadata@16';
+
+// helpers
+function FreeImage_GetMetadataCount(model: FREE_IMAGE_MDMODEL; dib: PFIBITMAP): Cardinal; stdcall; external FIDLL name '_FreeImage_GetMetadataCount@8';
+
+// tag to C string conversion
+function FreeImage_TagToString(model: FREE_IMAGE_MDMODEL; tag: PFITAG; Make: PChar = nil): PChar; stdcall; external FIDLL name '_FreeImage_TagToString@12';
+
+// --------------------------------------------------------------------------
+// Image manipulation toolkit -----------------------------------------------
+// --------------------------------------------------------------------------
+
+// rotation and flipping
+function FreeImage_RotateClassic(dib: PFIBITMAP; angle: Double): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_RotateClassic@12';
+function FreeImage_RotateEx(dib: PFIBITMAP; angle, x_shift, y_shift, x_origin, y_origin: Double; use_mask: Boolean): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_RotateEx@48';
+function FreeImage_FlipHorizontal(dib: PFIBITMAP): Boolean; stdcall; external FIDLL name '_FreeImage_FlipHorizontal@4';
+function FreeImage_FlipVertical(dib: PFIBITMAP): Boolean; stdcall; external FIDLL name '_FreeImage_FlipVertical@4';
+function FreeImage_JPEGTransform(const src_file: PChar; const dst_file: PChar; operation: FREE_IMAGE_JPEG_OPERATION; perfect: Boolean = False): Boolean; stdcall; external FIDLL name '_FreeImage_JPEGTransform@16';
+
+// upsampling / downsampling
+function FreeImage_Rescale(dib: PFIBITMAP; dst_width, dst_height: Integer; filter: FREE_IMAGE_FILTER): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Rescale@16';
+function FreeImage_MakeThumbnail(dib: PFIBITMAP; max_pixel_size: Integer; convert:boolean = TRUE): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_MakeThumbnail@12';
+
+// color manipulation routines (point operations)
+function FreeImage_AdjustCurve(dib: PFIBITMAP; LUT: PBYTE; channel: FREE_IMAGE_COLOR_CHANNEL): Boolean; stdcall; external FIDLL name '_FreeImage_AdjustCurve@12';
+function FreeImage_AdjustGamma(dib: PFIBITMAP; gamma: Double): Boolean; stdcall; external FIDLL name '_FreeImage_AdjustGamma@12';
+function FreeImage_AdjustBrightness(dib: PFIBITMAP; percentage: Double): Boolean; stdcall; external FIDLL name '_FreeImage_AdjustBrightness@12';
+function FreeImage_AdjustContrast(dib: PFIBITMAP; percentage: Double): Boolean; stdcall; external FIDLL name '_FreeImage_AdjustContrast@12';
+function FreeImage_Invert(dib: PFIBITMAP): Boolean; stdcall; external FIDLL name '_FreeImage_Invert@4';
+function FreeImage_GetHistogram(dib: PFIBITMAP; histo: PDWORD; channel: FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK): Boolean; stdcall; external FIDLL name '_FreeImage_GetHistogram@12';
+
+// channel processing routines
+function FreeImage_GetChannel(dib: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_GetChannel@8';
+function FreeImage_SetChannel(dib, dib8: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): Boolean; stdcall; external FIDLL name '_FreeImage_SetChannel@12';
+function FreeImage_GetComplexChannel(src: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_GetComplexChannel@8';
+function FreeImage_SetComplexChannel(src: PFIBITMAP; channel: FREE_IMAGE_COLOR_CHANNEL): Boolean; stdcall; external FIDLL name '_FreeImage_SetComplexChannel@12';
+
+// copy / paste / composite routines
+
+function FreeImage_Copy(dib: PFIBITMAP; left, top, right, bottom: Integer): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Copy@20';
+function FreeImage_Paste(dst, src: PFIBITMAP; left, top, alpha: Integer): Boolean; stdcall; external FIDLL name '_FreeImage_Paste@20';
+function FreeImage_Composite(fg: PFIBITMAP; useFileBkg: Boolean = False; appBkColor: PRGBQUAD = nil; bg: PFIBITMAP = nil): PFIBITMAP; stdcall; external FIDLL name '_FreeImage_Composite@16';
+
+{$MINENUMSIZE 1}
+implementation
+
+end.
diff --git a/Wrapper/Delphi/src/FreeUtils.pas b/Wrapper/Delphi/src/FreeUtils.pas
new file mode 100644
index 0000000..885f0ae
--- /dev/null
+++ b/Wrapper/Delphi/src/FreeUtils.pas
@@ -0,0 +1,127 @@
+unit FreeUtils;
+
+// ==========================================================
+//
+// Delphi wrapper for FreeImage 3
+//
+// Design and implementation by
+// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
+//
+// Contributors:
+// - Enzo Costantini (enzocostantini@libero.it)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+//
+// ==========================================================
+
+interface
+
+uses
+ SysUtils, Classes, FreeImage;
+
+function FIU_GetFIFType(filename: string): FREE_IMAGE_FORMAT;
+
+// returns FIF (plugin) description string
+function FIU_GetFIFDescription(fif: FREE_IMAGE_FORMAT): string;
+
+procedure FIU_GetAllDescriptions(var Descriptions: TStringList);
+
+// returns file extentions for FIF (e.g. '*.tif;*.tiff)
+function FIU_GetFIFExtList(fif: FREE_IMAGE_FORMAT): string;
+
+// returns file extentions for all plugins
+function FIU_GetFullExtList: string;
+
+// returns "Description + | + ExtList" for specified FIF
+function FIU_GetFIFFilter(fif: FREE_IMAGE_FORMAT): string;
+
+// All supported formats + Full filter list for FIFs + All files
+function FIU_GetAllFilters: string;
+
+implementation
+
+uses StrUtils;
+
+function FIU_GetFIFType(filename: string): FREE_IMAGE_FORMAT;
+begin
+ Result:=FreeImage_GetFileType(PAnsiChar(filename),0);
+end;
+
+function FIU_GetFIFDescription(fif: FREE_IMAGE_FORMAT): string;
+begin
+ Result := FreeImage_GetFIFDescription(fif)
+end;
+
+procedure FIU_GetAllDescriptions(var Descriptions: TStringList);
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Descriptions.Clear;
+ for fif := FIF_BMP to FIF_XPM do
+ Descriptions.Add(FreeImage_GetFIFDescription(fif) + ' (' + FIu_GetFIFExtList(fif) + ')')
+end;
+
+function FIU_GetFIFExtList(fif: FREE_IMAGE_FORMAT): string;
+var
+ ExtList: string;
+ I: Smallint;
+ C: Char;
+begin
+ Result := '*.';
+ ExtList := FreeImage_GetFIFExtensionList(fif);
+ for I := 1 to Length(ExtList) do
+ begin
+ C := ExtList[i];
+ if C <> ',' then
+ Result := Result + C
+ else
+ Result := Result + ';*.';
+ end
+end;
+
+function FIU_GetFullExtList: string;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Result := FIU_GetFIFExtList(FIF_BMP);
+ for fif := FIF_ICO to FIF_XPM do
+ Result := Result + ';' + FIU_GetFIFExtList(fif)
+end;
+
+function FIU_GetFIFFilter(fif: FREE_IMAGE_FORMAT): string;
+var
+ Text, ExtList: string;
+begin
+ Result := '';
+ if fif <> FIF_UNKNOWN then
+ begin
+ Text := Trim(FreeImage_GetFIFDescription(fif));
+ ExtList := FIU_GetFIFExtList(fif);
+ Result := Text + '(' + ExtList + ')' + '|' + ExtList
+ end
+end;
+
+function FIU_GetAllFilters: string;
+var
+ fif: FREE_IMAGE_FORMAT;
+begin
+ Result := 'All supported formats|' + FIU_GetFullExtList;
+ for fif := FIF_BMP to FIF_XPM do
+ begin
+ Result := Result + '|' + FIU_GetFIFFilter(fif)
+ end;
+end;
+
+end.
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/AssemblyInfo.cpp b/Wrapper/FreeImage.NET/cpp/FreeImageIO/AssemblyInfo.cpp
new file mode 100644
index 0000000..e550a32
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/AssemblyInfo.cpp
@@ -0,0 +1,58 @@
+#include "stdafx.h"
+
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("")];
+[assembly:AssemblyDescriptionAttribute("")];
+[assembly:AssemblyConfigurationAttribute("")];
+[assembly:AssemblyCompanyAttribute("")];
+[assembly:AssemblyProductAttribute("")];
+[assembly:AssemblyCopyrightAttribute("")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.0.*")];
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+// (*) If no key is specified, the assembly is not signed.
+// (*) KeyName refers to a key that has been installed in the Crypto Service
+// Provider (CSP) on your machine. KeyFile refers to a file which contains
+// a key.
+// (*) If the KeyFile and the KeyName values are both specified, the
+// following processing occurs:
+// (1) If the KeyName can be found in the CSP, that key is used.
+// (2) If the KeyName does not exist and the KeyFile does exist, the key
+// in the KeyFile is installed into the CSP and used.
+// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+// When specifying the KeyFile, the location of the KeyFile should be
+// relative to the project directory.
+// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+// documentation for more information on this.
+//
+[assembly:AssemblyDelaySignAttribute(false)];
+[assembly:AssemblyKeyFileAttribute("")];
+[assembly:AssemblyKeyNameAttribute("")];
+
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.cpp b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.cpp
new file mode 100644
index 0000000..c60ee8a
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.cpp
@@ -0,0 +1,69 @@
+// ==========================================================
+// FreeImageIO.Net
+//
+// Design and implementation by
+// - Marcos Pernambuco Motta (marcos.pernambuco@gmail.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "stdafx.h"
+#include "FreeImageIO.Net.h"
+
+
+extern "C" static unsigned __stdcall ReadProc (void *buffer, unsigned size, unsigned count, fi_handle handle)
+{
+ int total_read = 0;
+ struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
+ gcroot<unsigned char __gc []> mbuffer = new unsigned char __gc[size];
+ try
+ {
+ total_read = puh->_stream->Read(mbuffer,0,size);
+ Marshal::Copy(mbuffer,0,buffer,total_read);
+ } __finally {
+ mbuffer=NULL;
+ }
+ return (unsigned)total_read;
+}
+
+extern "C" static unsigned __stdcall WriteProc (void *buffer, unsigned size, unsigned count, fi_handle handle)
+{
+ struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
+ gcroot<unsigned char __gc []> mbuffer = new unsigned char __gc[size*count];
+ try
+ {
+
+ unsigned char __pin* pbuffer = &mbuffer[0];
+ memcpy(pbuffer,buffer,size*count);
+ puh->_stream->Write(mbuffer,0,size);
+ } __finally {
+ mbuffer=NULL;
+ }
+ return count;
+}
+
+extern "C" static int __stdcall SeekProc (fi_handle handle, long offset, int origin)
+{
+ struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
+ return (int)puh->_stream->Seek(offset,(SeekOrigin) origin);
+
+}
+
+extern "C" static long __stdcall TellProc(fi_handle handle)
+{
+ struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
+ return (long)puh->_stream->Position;
+}
+
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.h b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.h
new file mode 100644
index 0000000..358e871
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.h
@@ -0,0 +1,83 @@
+// ==========================================================
+// FreeImageIO.Net
+//
+// Design and implementation by
+// - Marcos Pernambuco Motta (marcos.pernambuco@gmail.com)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#pragma once
+#include <vcclr.h>
+#include "FreeImage.h"
+
+using namespace System;
+using namespace System::IO;
+using namespace System::Runtime::InteropServices;
+
+extern "C" {
+ // forward decls
+ unsigned __stdcall ReadProc (void *buffer, unsigned size, unsigned count, fi_handle handle);
+ unsigned __stdcall WriteProc (void *buffer, unsigned size, unsigned count, fi_handle handle);
+ int __stdcall SeekProc (fi_handle handle, long offset, int origin);
+ long __stdcall TellProc(fi_handle handle);
+
+ #pragma pack(push, 1)
+ __nogc struct UNMANAGED_HANDLER {
+ UNMANAGED_HANDLER() {
+ read_proc = &ReadProc;
+ write_proc = WriteProc;
+ seek_proc = SeekProc;
+ tell_proc = TellProc;
+ }
+ FI_ReadProc read_proc; // pointer to the function used to read data
+ FI_WriteProc write_proc; // pointer to the function used to write data
+ FI_SeekProc seek_proc; // pointer to the function used to seek
+ FI_TellProc tell_proc; // pointer to the function used to aquire the current position
+ gcroot<System::IO::Stream*> _stream;
+ };
+ #pragma pack(pop)
+}
+
+#define FREEIMAGE_DLL "freeimaged.dll"
+
+namespace FreeImageIODotNet
+{
+ __gc public class FreeImageStream
+ {
+ private:
+ struct UNMANAGED_HANDLER* _pUnmanaged;
+ public:
+ FreeImageStream(System::IO::Stream* stream)
+ {
+ FreeImage_SaveToHandle((FREE_IMAGE_FORMAT) 1,0,0,0,0);
+ _pUnmanaged = new struct UNMANAGED_HANDLER;
+ _pUnmanaged->_stream = stream;
+ }
+ ~FreeImageStream()
+ {
+ _pUnmanaged->_stream = NULL;
+ delete _pUnmanaged;
+ }
+
+ bool SaveImage(FREE_IMAGE_FORMAT fif, unsigned int dib, int flags) {
+ return (bool)FreeImage_SaveToHandle(fif,(FIBITMAP*) dib,(FreeImageIO*)_pUnmanaged,(fi_handle)_pUnmanaged,flags);
+ }
+
+ unsigned int LoadImage(FREE_IMAGE_FORMAT fif, int flags) {
+ return (unsigned int)FreeImage_LoadFromHandle(fif,(FreeImageIO*)_pUnmanaged,(fi_handle)_pUnmanaged,flags);
+ }
+ };
+}
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.vcproj b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.vcproj
new file mode 100644
index 0000000..ddb942f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.Net.vcproj
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="FreeImageIO.Net"
+ ProjectGUID="{E87923FF-1FBD-450D-9287-539A90DE9776}"
+ RootNamespace="FreeImageIONet"
+ Keyword="ManagedCProj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ ManagedExtensions="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/Zl"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG"
+ MinimalRebuild="FALSE"
+ BasicRuntimeChecks="0"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/noentry"
+ AdditionalDependencies="nochkclr.obj mscoree.lib msvcrt.lib FreeImaged.lib"
+ OutputFile="$(OutDir)\$(ProjectName).dll"
+ LinkIncremental="2"
+ GenerateDebugInformation="TRUE"
+ AssemblyDebug="1"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ ManagedExtensions="TRUE">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalOptions="/Zl"
+ PreprocessorDefinitions="WIN32;NDEBUG"
+ MinimalRebuild="FALSE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="3"
+ WarningLevel="3"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/noentry"
+ AdditionalDependencies="nochkclr.obj mscoree.lib msvcrt.lib FreeImage.lib"
+ OutputFile="$(OutDir)\$(ProjectName).dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="TRUE"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ <AssemblyReference
+ RelativePath="mscorlib.dll"/>
+ <AssemblyReference
+ RelativePath="System.dll"/>
+ <AssemblyReference
+ RelativePath="System.Data.dll"/>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\AssemblyInfo.cpp">
+ </File>
+ <File
+ RelativePath=".\FreeImageIO.Net.cpp">
+ </File>
+ <File
+ RelativePath=".\Stdafx.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\FreeImageIO.Net.h">
+ </File>
+ <File
+ RelativePath=".\resource.h">
+ </File>
+ <File
+ RelativePath=".\Stdafx.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ <File
+ RelativePath=".\app.ico">
+ </File>
+ <File
+ RelativePath=".\app.rc">
+ </File>
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.sln b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.sln
new file mode 100644
index 0000000..6026cc7
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/FreeImageIO.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImageIO.Net", "FreeImageIO.Net.vcproj", "{E87923FF-1FBD-450D-9287-539A90DE9776}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {E87923FF-1FBD-450D-9287-539A90DE9776}.Debug.ActiveCfg = Debug|Win32
+ {E87923FF-1FBD-450D-9287-539A90DE9776}.Debug.Build.0 = Debug|Win32
+ {E87923FF-1FBD-450D-9287-539A90DE9776}.Release.ActiveCfg = Release|Win32
+ {E87923FF-1FBD-450D-9287-539A90DE9776}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/ReadMe.txt b/Wrapper/FreeImage.NET/cpp/FreeImageIO/ReadMe.txt
new file mode 100644
index 0000000..f0d15f3
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/ReadMe.txt
@@ -0,0 +1,27 @@
+========================================================================
+FreeImageIO.Net
+
+Author: Marcos Pernambuco Motta (marcos.pernambuco@gmail.com)
+========================================================================
+
+This library allows programs that use FreeImage.Net to save images to or
+to load images from .Net Streams.
+
+The class FreeImageStream implements a FreeImageIO handler and routes
+IO calls (read,write,tell and seek) to a wrapped System.IO.Stream.
+
+Example:
+
+using FreeImageAPI;
+using FreeImageIODotNet;
+
+uint dib = FreeImageAPI.FreeImage.Allocate(width,height,32,0,0,0);
+
+// ... Image handling code goes here
+
+System.IO.FileStream stream = new System.IO.FileStream(@"c:\sample.png",System.IO.FileMode.Create);
+FreeImageStream imageStream = new FreeImageStream(stream);
+imageStream.SaveImage((int)FREE_IMAGE_FORMAT.FIF_PNG,dib,0);
+stream.Close();
+
+Compile with VS2003.
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.cpp b/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.cpp
new file mode 100644
index 0000000..0260fa9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.cpp
@@ -0,0 +1,5 @@
+// stdafx.cpp : source file that includes just the standard includes
+// FreeImageIO.Net.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.h b/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.h
new file mode 100644
index 0000000..07ec3fb
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/Stdafx.h
@@ -0,0 +1,6 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently,
+// but are changed infrequently
+
+#pragma once
+
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.ico b/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.ico
new file mode 100644
index 0000000..3a5525f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.ico
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.rc b/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.rc
new file mode 100644
index 0000000..b488dbd
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/app.rc
@@ -0,0 +1,52 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon placed first or with lowest ID value becomes application icon
+
+LANGUAGE 9, 1
+#pragma code_page(1252)
+1 ICON "app.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/Wrapper/FreeImage.NET/cpp/FreeImageIO/resource.h b/Wrapper/FreeImage.NET/cpp/FreeImageIO/resource.h
new file mode 100644
index 0000000..d5ac7c4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cpp/FreeImageIO/resource.h
@@ -0,0 +1,3 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by app.rc
diff --git a/Wrapper/FreeImage.NET/cs/Bin/delete.me b/Wrapper/FreeImage.NET/cs/Bin/delete.me
new file mode 100644
index 0000000..f8ec546
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Bin/delete.me
@@ -0,0 +1 @@
+You may safely delete this file.
diff --git a/Wrapper/FreeImage.NET/cs/Content.txt b/Wrapper/FreeImage.NET/cs/Content.txt
new file mode 100644
index 0000000..910206e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Content.txt
@@ -0,0 +1,43 @@
+
+This file gives you a short description of the .NET wrapper's folders
+and what's located in them.
+
+
+"Doc"
+Sandcastle Help File Builder project file for creating a Microsoft Help API
+documentation (CHM file).
+FreeImage.NET uses Eric Woodruff's Sandcastle Help File Builder GUI to
+generate the API documentation. See http://www.codeplex.com/SHFB
+
+"Library"
+Source code of the C# .NET wrapper. Builds the FreeImageNET.dll.
+
+"Samples"
+Example projects showing how to use the wrapper.
+
+"SourceFileMerger"
+Program to merge all the wrapper's source files into a single source file
+for easy integration into your projects on source code basis.
+
+"UnitTest"
+NUnit-based test project for the .NET wrapper. NUnit needs to be installed
+for this project to work.
+
+"UnitTestData" (not in CVS)
+Several images in each available color depth used by "UnitTest".
+
+"clear.bat"
+Batch file to clear the whole project, removing all temporary files.
+
+"FreeImage.chm" (not in CVS)
+The .NET wrapper's API documentation. Build with Microsoft's Sandcastle
+project from C# source code documentation.
+
+"FreeImage.NET.nunit"
+NUnit project file. NUnit needs to be installed for this project to work.
+
+"FreeImage.NET.sln"
+The Microsoft Visual Studio 2005 solution file.
+
+"Whats_New.NET.txt"
+The changelog. \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Doc/3.11.0/FreeImage.NET.shfbproj b/Wrapper/FreeImage.NET/cs/Doc/3.11.0/FreeImage.NET.shfbproj
new file mode 100644
index 0000000..1e4da12
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Doc/3.11.0/FreeImage.NET.shfbproj
@@ -0,0 +1,41 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <!-- The configuration and platform will be used to determine which
+ assemblies to include from solution and project documentation
+ sources -->
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{d68736d0-a80d-453c-a921-6ada865504b5}</ProjectGuid>
+ <SHFBSchemaVersion>1.8.0.0</SHFBSchemaVersion>
+ <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
+ Studio adds them anyway -->
+ <AssemblyName>Documentation</AssemblyName>
+ <RootNamespace>Documentation</RootNamespace>
+ <Name>Documentation</Name>
+ <!-- SHFB properties -->
+ <OutputPath>.\Out\</OutputPath>
+ <HtmlHelpName>FreeImage.NET</HtmlHelpName>
+ <HelpFileFormat>HtmlHelp1x</HelpFileFormat>
+ <KeepLogFile>False</KeepLogFile>
+ <FooterText>FreeImage - The productivity booster. FreeImage is licensed under the GNU General Public License %28GPL%29 and the FreeImage Public License %28FIPL%29.</FooterText>
+ <HelpTitle>FreeImage .NET Documentation</HelpTitle>
+ <NamingMethod>HashedMemberName</NamingMethod>
+ <SdkLinkType>Msdn</SdkLinkType>
+ <MissingTags>AutoDocumentCtors</MissingTags>
+ <VisibleItems>InheritedMembers, Protected</VisibleItems>
+ <DocumentationSources>
+ <DocumentationSource sourceFile="FreeImageNET.dll" />
+<DocumentationSource sourceFile="FreeImageNET.xml" /></DocumentationSources>
+ <PlugInConfigurations>
+ </PlugInConfigurations>
+ </PropertyGroup>
+ <!-- There are no properties for these two groups but they need to appear in
+ order for Visual Studio to perform the build. -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <!-- Import the SHFB build targets -->
+ <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Doc/3.12.0/FreeImage.NET.shfbproj b/Wrapper/FreeImage.NET/cs/Doc/3.12.0/FreeImage.NET.shfbproj
new file mode 100644
index 0000000..1e4da12
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Doc/3.12.0/FreeImage.NET.shfbproj
@@ -0,0 +1,41 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <!-- The configuration and platform will be used to determine which
+ assemblies to include from solution and project documentation
+ sources -->
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{d68736d0-a80d-453c-a921-6ada865504b5}</ProjectGuid>
+ <SHFBSchemaVersion>1.8.0.0</SHFBSchemaVersion>
+ <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
+ Studio adds them anyway -->
+ <AssemblyName>Documentation</AssemblyName>
+ <RootNamespace>Documentation</RootNamespace>
+ <Name>Documentation</Name>
+ <!-- SHFB properties -->
+ <OutputPath>.\Out\</OutputPath>
+ <HtmlHelpName>FreeImage.NET</HtmlHelpName>
+ <HelpFileFormat>HtmlHelp1x</HelpFileFormat>
+ <KeepLogFile>False</KeepLogFile>
+ <FooterText>FreeImage - The productivity booster. FreeImage is licensed under the GNU General Public License %28GPL%29 and the FreeImage Public License %28FIPL%29.</FooterText>
+ <HelpTitle>FreeImage .NET Documentation</HelpTitle>
+ <NamingMethod>HashedMemberName</NamingMethod>
+ <SdkLinkType>Msdn</SdkLinkType>
+ <MissingTags>AutoDocumentCtors</MissingTags>
+ <VisibleItems>InheritedMembers, Protected</VisibleItems>
+ <DocumentationSources>
+ <DocumentationSource sourceFile="FreeImageNET.dll" />
+<DocumentationSource sourceFile="FreeImageNET.xml" /></DocumentationSources>
+ <PlugInConfigurations>
+ </PlugInConfigurations>
+ </PropertyGroup>
+ <!-- There are no properties for these two groups but they need to appear in
+ order for Visual Studio to perform the build. -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <!-- Import the SHFB build targets -->
+ <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfb b/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfb
new file mode 100644
index 0000000..63a8885
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfb
@@ -0,0 +1,50 @@
+<project schemaVersion="1.6.0.2">
+ <assemblies>
+ <assembly assemblyPath="..\Bin\FreeImageNET.dll" xmlCommentsPath="..\Bin\FreeImageNET.XML" commentsOnly="False" />
+ </assemblies>
+ <namespaceSummaries>
+ <namespaceSummaryItem name="" isDocumented="False" />
+ <namespaceSummaryItem name="FreeImageAPI" isDocumented="True" />
+ <namespaceSummaryItem name="FreeImageAPI.Classes" isDocumented="True" />
+ <namespaceSummaryItem name="FreeImageAPI.IO" isDocumented="True" />
+ <namespaceSummaryItem name="FreeImageAPI.Metadata" isDocumented="True" />
+ <namespaceSummaryItem name="FreeImageAPI.Plugins" isDocumented="True" />
+ </namespaceSummaries>
+ <ProjectSummary />
+ <MissingTags>AutoDocumentCtors</MissingTags>
+ <VisibleItems>InheritedMembers, Protected</VisibleItems>
+ <HtmlHelp1xCompilerPath path="" />
+ <HtmlHelp2xCompilerPath path="" />
+ <OutputPath>.\Out\</OutputPath>
+ <SandcastlePath path="" />
+ <WorkingPath path="" />
+ <CleanIntermediates>True</CleanIntermediates>
+ <KeepLogFile>False</KeepLogFile>
+ <HelpFileFormat>HtmlHelp1x</HelpFileFormat>
+ <PurgeDuplicateTopics>True</PurgeDuplicateTopics>
+ <CppCommentsFixup>False</CppCommentsFixup>
+ <FrameworkVersion>2.0.50727</FrameworkVersion>
+ <BinaryTOC>True</BinaryTOC>
+ <IncludeFavorites>False</IncludeFavorites>
+ <Preliminary>False</Preliminary>
+ <RootNamespaceContainer>False</RootNamespaceContainer>
+ <RootNamespaceTitle />
+ <HelpTitle>FreeImage .NET Documentation</HelpTitle>
+ <HtmlHelpName>FreeImage.NET</HtmlHelpName>
+ <Language>en-US</Language>
+ <CopyrightHref />
+ <CopyrightText />
+ <FeedbackEMailAddress />
+ <HeaderText />
+ <FooterText>FreeImage - The productivity booster. FreeImage is licensed under the GNU General Public License (GPL) and the FreeImage Public License (FIPL).</FooterText>
+ <ProjectLinkType>Local</ProjectLinkType>
+ <SdkLinkType>Msdn</SdkLinkType>
+ <SdkLinkTarget>Self</SdkLinkTarget>
+ <PresentationStyle>vs2005</PresentationStyle>
+ <NamingMethod>HashedMemberName</NamingMethod>
+ <SyntaxFilters>Standard</SyntaxFilters>
+ <ShowFeedbackControl>False</ShowFeedbackControl>
+ <ContentPlacement>AboveNamespaces</ContentPlacement>
+ <ContentSiteMap path="" />
+ <TopicFileTransform path="" />
+</project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfbproj b/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfbproj
new file mode 100644
index 0000000..8e3936d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Doc/FreeImage.NET.shfbproj
@@ -0,0 +1,51 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+ <PropertyGroup>
+ <!-- The configuration and platform will be used to determine which
+ assemblies to include from solution and project documentation
+ sources -->
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{d68736d0-a80d-453c-a921-6ada865504b5}</ProjectGuid>
+ <SHFBSchemaVersion>1.8.0.0</SHFBSchemaVersion>
+ <!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
+ Studio adds them anyway -->
+ <AssemblyName>Documentation</AssemblyName>
+ <RootNamespace>Documentation</RootNamespace>
+ <Name>Documentation</Name>
+ <!-- SHFB properties -->
+ <OutputPath>.\Out\</OutputPath>
+ <HtmlHelpName>FreeImage.NET</HtmlHelpName>
+ <HelpFileFormat>HtmlHelp1x</HelpFileFormat>
+ <KeepLogFile>False</KeepLogFile>
+ <FooterText>FreeImage - The productivity booster. FreeImage is licensed under the GNU General Public License %28GPL%29 and the FreeImage Public License %28FIPL%29.</FooterText>
+ <HelpTitle>FreeImage .NET Documentation</HelpTitle>
+ <NamingMethod>HashedMemberName</NamingMethod>
+ <SdkLinkType>Msdn</SdkLinkType>
+ <MissingTags>AutoDocumentCtors</MissingTags>
+ <VisibleItems>InheritedMembers, Protected</VisibleItems>
+ <DocumentationSources>
+ <DocumentationSource sourceFile="..\Bin\FreeImageNET.dll" />
+ <DocumentationSource sourceFile="..\Bin\FreeImageNET.xml" />
+ </DocumentationSources>
+ <PlugInConfigurations>
+ <PlugInConfig id="Version Builder" enabled="True">
+ <configuration>
+ <currentProject label="FreeImage.NET" version="3.13.0" />
+ <versions>
+ <version label="FreeImage.NET" version="3.11.0" helpFileProject="3.11.0\FreeImage.NET.shfbproj" />
+ <version label="FreeImage.NET" version="3.12.0" helpFileProject="3.12.0\FreeImage.NET.shfbproj" />
+ </versions>
+ </configuration>
+ </PlugInConfig>
+ </PlugInConfigurations>
+ </PropertyGroup>
+ <!-- There are no properties for these two groups but they need to appear in
+ order for Visual Studio to perform the build. -->
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ </PropertyGroup>
+ <!-- Import the SHFB build targets -->
+ <Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Doc/SHFB.txt b/Wrapper/FreeImage.NET/cs/Doc/SHFB.txt
new file mode 100644
index 0000000..90a2e38
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Doc/SHFB.txt
@@ -0,0 +1,9 @@
+Eric Woodruff's Sandcastle Help File Builder 1.6.x.x (SHFB) is needed for FreeImage.NET wrapper
+help file creation. It can be downloaded from http://www.codeplex.com/SHFB
+
+As of FreeImage.NET version 1.08, version 1.8.01 of Sandcastle Help File Builder is used by FreeImage.NET
+and thus needed for FreeImage.NET wrapper help file creation. It can still be downloaded
+from http://www.codeplex.com/SHFB
+
+Microsoft's Sandcaste is also needed for SHFB to run correctly. It can be downloaded from
+http://www.microsoft.com/downloads/details.aspx?FamilyId=E82EA71D-DA89-42EE-A715-696E3A4873B2&displaylang=en
diff --git a/Wrapper/FreeImage.NET/cs/FreeImage.NET.nunit b/Wrapper/FreeImage.NET/cs/FreeImage.NET.nunit
new file mode 100644
index 0000000..c1da949
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/FreeImage.NET.nunit
@@ -0,0 +1,9 @@
+<NUnitProject>
+ <Settings activeconfig="Debug" />
+ <Config name="Debug" appbase="UnitTest\bin\Debug" binpathtype="Auto">
+ <assembly path="UnitTest.exe" />
+ </Config>
+ <Config name="Release" appbase="UnitTest\bin\Release" binpathtype="Auto">
+ <assembly path="UnitTest.exe" />
+ </Config>
+</NUnitProject> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/FreeImage.NET.sln b/Wrapper/FreeImage.NET/cs/FreeImage.NET.sln
new file mode 100644
index 0000000..f92e524
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/FreeImage.NET.sln
@@ -0,0 +1,214 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Library", "Library\Library.csproj", "{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceFileMerger", "SourceFileMerger\SourceFileMerger.csproj", "{2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTest", "UnitTest\UnitTest.csproj", "{FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 01 - Loading and saving", "Samples\Sample 01 - Loading and saving\Sample 01 - Loading and saving.csproj", "{0D294AB6-FAD4-4364-AAB6-43C1796116A9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 02 - Multipaged bitmaps", "Samples\Sample 02 - Multipaged bitmaps\Sample 02 - Multipaged bitmaps.csproj", "{AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 03 - Allocating", "Samples\Sample 03 - Allocating\Sample 03 - Allocating.csproj", "{A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 04 - Getting bitmap informations", "Samples\Sample 04 - Getting bitmap informations\Sample 04 - Getting bitmap informations.csproj", "{1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 05 - Working with pixels", "Samples\Sample 05 - Working with pixels\Sample 05 - Working with pixels.csproj", "{A501F134-8FB6-460B-AFE9-884A696C1C07}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 06 - Converting", "Samples\Sample 06 - Converting\Sample 06 - Converting.csproj", "{E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 07 - ICC Profiles", "Samples\Sample 07 - ICC Profiles\Sample 07 - ICC Profiles.csproj", "{3B1BB976-64A7-41FD-B7E2-59104161AF7E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 08 - Creating a plugin", "Samples\Sample 08 - Creating a plugin\Sample 08 - Creating a plugin.csproj", "{491042DB-495B-420C-A3BE-5D13019707C5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 09 - Working with streams", "Samples\Sample 09 - Working with streams\Sample 09 - Working with streams.csproj", "{92A454B2-67EF-4B70-99C9-F22B83B6FBFF}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 10 - Metadata", "Samples\Sample 10 - Metadata\Sample 10 - Metadata.csproj", "{55DCC37A-E56C-44D9-9C44-8DAB10CD3003}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample 11 - Using the FreeImageBitmap class", "Samples\Sample 11 - Using the FreeImageBitmap class\Sample 11 - Using the FreeImageBitmap class.csproj", "{996068CD-D07A-42E0-856F-ACC71E8565EF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|x64.ActiveCfg = Debug|x64
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|x64.Build.0 = Debug|x64
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|x86.ActiveCfg = Debug|x86
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Debug|x86.Build.0 = Debug|x86
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|x64.ActiveCfg = Release|x64
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|x64.Build.0 = Release|x64
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|x86.ActiveCfg = Release|x86
+ {6598A7CD-8F27-4D3F-A675-5AE63113A7C3}.Release|x86.Build.0 = Release|x86
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|x64.ActiveCfg = Debug|x64
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|x64.Build.0 = Debug|x64
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|x86.ActiveCfg = Debug|x86
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Debug|x86.Build.0 = Debug|x86
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|x64.ActiveCfg = Release|x64
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|x64.Build.0 = Release|x64
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|x86.ActiveCfg = Release|x86
+ {2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}.Release|x86.Build.0 = Release|x86
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|x64.ActiveCfg = Debug|x64
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|x64.Build.0 = Debug|x64
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|x86.ActiveCfg = Debug|x86
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Debug|x86.Build.0 = Debug|x86
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|x64.ActiveCfg = Release|x64
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|x64.Build.0 = Release|x64
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|x86.ActiveCfg = Release|x86
+ {FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}.Release|x86.Build.0 = Release|x86
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|x64.ActiveCfg = Debug|x64
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|x64.Build.0 = Debug|x64
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|x86.ActiveCfg = Debug|x86
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Debug|x86.Build.0 = Debug|x86
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|x64.ActiveCfg = Release|x64
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|x64.Build.0 = Release|x64
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|x86.ActiveCfg = Release|x86
+ {0D294AB6-FAD4-4364-AAB6-43C1796116A9}.Release|x86.Build.0 = Release|x86
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|x64.ActiveCfg = Debug|x64
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|x64.Build.0 = Debug|x64
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|x86.ActiveCfg = Debug|x86
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Debug|x86.Build.0 = Debug|x86
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|x64.ActiveCfg = Release|x64
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|x64.Build.0 = Release|x64
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|x86.ActiveCfg = Release|x86
+ {AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}.Release|x86.Build.0 = Release|x86
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|x64.ActiveCfg = Debug|x64
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|x64.Build.0 = Debug|x64
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|x86.ActiveCfg = Debug|x86
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Debug|x86.Build.0 = Debug|x86
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|x64.ActiveCfg = Release|x64
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|x64.Build.0 = Release|x64
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|x86.ActiveCfg = Release|x86
+ {A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}.Release|x86.Build.0 = Release|x86
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|x64.ActiveCfg = Debug|x64
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|x64.Build.0 = Debug|x64
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|x86.ActiveCfg = Debug|x86
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Debug|x86.Build.0 = Debug|x86
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|x64.ActiveCfg = Release|x64
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|x64.Build.0 = Release|x64
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|x86.ActiveCfg = Release|x86
+ {1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}.Release|x86.Build.0 = Release|x86
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|x64.ActiveCfg = Debug|x64
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|x64.Build.0 = Debug|x64
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|x86.ActiveCfg = Debug|x86
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Debug|x86.Build.0 = Debug|x86
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|x64.ActiveCfg = Release|x64
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|x64.Build.0 = Release|x64
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|x86.ActiveCfg = Release|x86
+ {A501F134-8FB6-460B-AFE9-884A696C1C07}.Release|x86.Build.0 = Release|x86
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|x64.ActiveCfg = Debug|x64
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|x64.Build.0 = Debug|x64
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|x86.ActiveCfg = Debug|x86
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Debug|x86.Build.0 = Debug|x86
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|x64.ActiveCfg = Release|x64
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|x64.Build.0 = Release|x64
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|x86.ActiveCfg = Release|x86
+ {E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}.Release|x86.Build.0 = Release|x86
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|x64.ActiveCfg = Debug|x64
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|x64.Build.0 = Debug|x64
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|x86.ActiveCfg = Debug|x86
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Debug|x86.Build.0 = Debug|x86
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|x64.ActiveCfg = Release|x64
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|x64.Build.0 = Release|x64
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|x86.ActiveCfg = Release|x86
+ {3B1BB976-64A7-41FD-B7E2-59104161AF7E}.Release|x86.Build.0 = Release|x86
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|x64.ActiveCfg = Debug|x64
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|x64.Build.0 = Debug|x64
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|x86.ActiveCfg = Debug|x86
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Debug|x86.Build.0 = Debug|x86
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|x64.ActiveCfg = Release|x64
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|x64.Build.0 = Release|x64
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|x86.ActiveCfg = Release|x86
+ {491042DB-495B-420C-A3BE-5D13019707C5}.Release|x86.Build.0 = Release|x86
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|x64.ActiveCfg = Debug|x64
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|x64.Build.0 = Debug|x64
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|x86.ActiveCfg = Debug|x86
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Debug|x86.Build.0 = Debug|x86
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|x64.ActiveCfg = Release|x64
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|x64.Build.0 = Release|x64
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|x86.ActiveCfg = Release|x86
+ {92A454B2-67EF-4B70-99C9-F22B83B6FBFF}.Release|x86.Build.0 = Release|x86
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|x64.ActiveCfg = Debug|x64
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|x64.Build.0 = Debug|x64
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|x86.ActiveCfg = Debug|x86
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Debug|x86.Build.0 = Debug|x86
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|Any CPU.Build.0 = Release|Any CPU
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|x64.ActiveCfg = Release|x64
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|x64.Build.0 = Release|x64
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|x86.ActiveCfg = Release|x86
+ {55DCC37A-E56C-44D9-9C44-8DAB10CD3003}.Release|x86.Build.0 = Release|x86
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|x64.ActiveCfg = Debug|x64
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|x64.Build.0 = Debug|x64
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|x86.ActiveCfg = Debug|x86
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Debug|x86.Build.0 = Debug|x86
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|x64.ActiveCfg = Release|x64
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|x64.Build.0 = Release|x64
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|x86.ActiveCfg = Release|x86
+ {996068CD-D07A-42E0-856F-ACC71E8565EF}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageBitmap.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageBitmap.cs
new file mode 100644
index 0000000..ebf207e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageBitmap.cs
@@ -0,0 +1,4378 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.11 $
+// $Date: 2009/09/15 11:49:52 $
+// $Id: FreeImageBitmap.cs,v 1.11 2009/09/15 11:49:52 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.IO.Compression;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Collections;
+using System.Collections.Generic;
+using FreeImageAPI.Metadata;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Encapsulates a FreeImage-bitmap.
+ /// </summary>
+ [Serializable, Guid("64a4c935-b757-499c-ab8c-6110316a9e51")]
+ public class FreeImageBitmap : MarshalByRefObject, ICloneable, IDisposable, IEnumerable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Indicates whether this instance is disposed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed;
+
+ /// <summary>
+ /// Tab object.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object tag;
+
+ /// <summary>
+ /// Object used to syncronize lock methods.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object lockObject = new object();
+
+ /// <summary>
+ /// Holds information used by SaveAdd() methods.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private SaveInformation saveInformation = new SaveInformation();
+
+ /// <summary>
+ /// The stream that this instance was loaded from or
+ /// null if it has been cloned or deserialized.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Stream stream;
+
+ /// <summary>
+ /// True if the stream must be disposed with this
+ /// instance.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposeStream;
+
+ /// <summary>
+ /// The number of frames contained by a mutlipage bitmap.
+ /// Default value is 1 and only changed if needed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int frameCount = 1;
+
+ /// <summary>
+ /// The index of the loaded frame.
+ /// Default value is 0 and only changed if needed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int frameIndex = 0;
+
+ /// <summary>
+ /// Format of the sourceimage.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FREE_IMAGE_FORMAT originalFormat = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+
+ /// <summary>
+ /// Handle to the encapsulated FreeImage-bitmap.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FIBITMAP dib;
+
+ private const string ErrorLoadingBitmap = "Unable to load bitmap.";
+ private const string ErrorLoadingFrame = "Unable to load frame.";
+ private const string ErrorCreatingBitmap = "Unable to create bitmap.";
+ private const string ErrorUnloadBitmap = "Unable to unload bitmap.";
+
+ #endregion
+
+ #region Constructors and Destructor
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// </summary>
+ protected FreeImageBitmap()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// For internal use only.
+ /// </summary>
+ /// <exception cref="Exception">The operation failed.</exception>
+ internal protected FreeImageBitmap(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ this.dib = dib;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ public FreeImageBitmap(FreeImageBitmap original)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ original.EnsureNotDisposed();
+ dib = FreeImage.Clone(original.dib);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = original.originalFormat;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(FreeImageBitmap original, Size newSize)
+ : this(original, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(FreeImageBitmap original, int width, int height)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ original.EnsureNotDisposed();
+ dib = FreeImage.Rescale(original.dib, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = original.originalFormat;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Image original)
+ : this(original as Bitmap)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(Image original, Size newSize)
+ : this(original as Bitmap, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(Image original, int width, int height)
+ : this(original as Bitmap, width, height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Bitmap original)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ dib = FreeImage.CreateFromBitmap(original, true);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = FreeImage.GetFormat(original.RawFormat);
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(Bitmap original, Size newSize)
+ : this(original, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(Bitmap original, int width, int height)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ FIBITMAP temp = FreeImage.CreateFromBitmap(original, true);
+ if (temp.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ dib = FreeImage.Rescale(temp, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ FreeImage.Unload(temp);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = FreeImage.GetFormat(original.RawFormat);
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="useIcm">Ignored.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, bool useIcm)
+ : this(stream)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream)
+ : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream in the specified format.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format)
+ : this(stream, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream with the specified loading flags.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_LOAD_FLAGS flags)
+ : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream in the specified format
+ /// with the specified loading flags.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ this.stream = stream;
+ disposeStream = false;
+ LoadFromStream(stream, format, flags);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename)
+ : this(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="useIcm">Ignored.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, bool useIcm)
+ : this(filename)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// with the specified loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags)
+ : this(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// in the specified format.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format)
+ : this(filename, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// in the specified format with the specified loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+
+ saveInformation.filename = filename;
+ stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ disposeStream = true;
+ LoadFromStream(stream, format, flags);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified size.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(int width, int height)
+ {
+ dib = FreeImage.Allocate(
+ width,
+ height,
+ 24,
+ FreeImage.FI_RGBA_RED_MASK,
+ FreeImage.FI_RGBA_GREEN_MASK,
+ FreeImage.FI_RGBA_BLUE_MASK);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified resource.
+ /// </summary>
+ /// <param name="type">The class used to extract the resource.</param>
+ /// <param name="resource">The name of the resource.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Type type, string resource)
+ : this(type.Module.Assembly.GetManifestResourceStream(type, resource))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size
+ /// and with the resolution of the specified <see cref="System.Drawing.Graphics"/> object.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="g">The Graphics object that specifies the resolution for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="g"/> is a null reference.</exception>
+ public FreeImageBitmap(int width, int height, Graphics g)
+ : this(width, height)
+ {
+ FreeImage.SetResolutionX(dib, (uint)g.DpiX);
+ FreeImage.SetResolutionX(dib, (uint)g.DpiY);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and format.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, PixelFormat format)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid");
+ }
+ dib = FreeImage.AllocateT(type, width, height, (int)bpp, redMask, greenMask, blueMask);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and type.
+ /// Only non standard bitmaps are supported.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="type">The type of the bitmap.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="type"/> is FIT_BITMAP or FIT_UNKNOWN.</exception>
+ /// <exception cref="ArgumentException"><paramref name="type"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, FREE_IMAGE_TYPE type)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if ((type == FREE_IMAGE_TYPE.FIT_BITMAP) || (type == FREE_IMAGE_TYPE.FIT_UNKNOWN))
+ {
+ throw new ArgumentException("type is invalid.");
+ }
+ dib = FreeImage.AllocateT(type, width, height, 0, 0u, 0u, 0u);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ scan0, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="bits">Array of bytes containing the bitmap data.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
+ public FreeImageBitmap(int width, int height, int stride, PixelFormat format, byte[] bits)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if (bits == null)
+ {
+ throw new ArgumentNullException("bits");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ bits, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
+ /// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, IntPtr scan0)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint redMask, greenMask, blueMask;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("bpp and type are invalid or not supported.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ scan0, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
+ /// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="bits">Array of bytes containing the bitmap data.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
+ public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, byte[] bits)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if (bits == null)
+ {
+ throw new ArgumentNullException("bits");
+ }
+ uint redMask, greenMask, blueMask;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("bpp and type are invalid or not supported.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ bits, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// </summary>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="SerializationException">The operation failed.</exception>
+ public FreeImageBitmap(SerializationInfo info, StreamingContext context)
+ {
+ try
+ {
+ byte[] data = (byte[])info.GetValue("Bitmap Data", typeof(byte[]));
+ if ((data != null) && (data.Length > 0))
+ {
+ MemoryStream memory = new MemoryStream(data);
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_TIFF;
+ dib = FreeImage.LoadFromStream(memory, ref format);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+
+ AddMemoryPressure();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new SerializationException("Deserialization failed.", ex);
+ }
+ }
+
+ /// <summary>
+ /// Frees all managed and unmanaged ressources.
+ /// </summary>
+ ~FreeImageBitmap()
+ {
+ Dispose(false);
+ }
+
+ #endregion
+
+ #region Operators
+
+ /// <summary>
+ /// Converts a <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
+ /// </summary>
+ /// <param name="value">A <see cref="FreeImageBitmap"/> instance.</param>
+ /// <returns>A new instance of <see cref="Bitmap"/> initialized to <paramref name="value"/>.</returns>
+ /// <remarks>
+ /// The explicit conversion from <see cref="FreeImageBitmap"/> into Bitmap
+ /// allows to create an instance on the fly and use it as if
+ /// was a Bitmap. This way it can be directly used with a
+ /// PixtureBox for example without having to call any
+ /// conversion operations.
+ /// </remarks>
+ public static explicit operator Bitmap(FreeImageBitmap value)
+ {
+ return value.ToBitmap();
+ }
+
+ /// <summary>
+ /// Converts a <see cref="Bitmap"/> instance to a <see cref="FreeImageBitmap"/> instance.
+ /// </summary>
+ /// <param name="value">A <see cref="Bitmap"/> instance.</param>
+ /// <returns>A new instance of <see cref="FreeImageBitmap"/> initialized to <paramref name="value"/>.</returns>
+ /// <remarks>
+ /// The explicit conversion from <see cref="Bitmap"/> into <see cref="FreeImageBitmap"/>
+ /// allows to create an instance on the fly to perform
+ /// image processing operations and converting it back.
+ /// </remarks>
+ public static explicit operator FreeImageBitmap(Bitmap value)
+ {
+ return new FreeImageBitmap(value);
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="FreeImageBitmap"/> objects have the same value.
+ /// </summary>
+ /// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// <b>true</b> if the value of left is the same as the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FreeImageBitmap left, FreeImageBitmap right)
+ {
+ if (object.ReferenceEquals(left, right))
+ {
+ return true;
+ }
+ else if (object.ReferenceEquals(left, null) || object.ReferenceEquals(right, null))
+ {
+ return false;
+ }
+ else
+ {
+ left.EnsureNotDisposed();
+ right.EnsureNotDisposed();
+ return FreeImage.Compare(left.dib, right.dib, FREE_IMAGE_COMPARE_FLAGS.COMPLETE);
+ }
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="FreeImageBitmap"/> objects have different values.
+ /// </summary>
+ /// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// true if the value of left is different from the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FreeImageBitmap left, FreeImageBitmap right)
+ {
+ return (!(left == right));
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Type of the bitmap.
+ /// </summary>
+ public FREE_IMAGE_TYPE ImageType
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetImageType(dib);
+ }
+ }
+
+ /// <summary>
+ /// Number of palette entries.
+ /// </summary>
+ public int ColorsUsed
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetColorsUsed(dib);
+ }
+ }
+
+ /// <summary>
+ /// The number of unique colors actually used by the bitmap. This might be different from
+ /// what ColorsUsed returns, which actually returns the palette size for palletised images.
+ /// Works for FIT_BITMAP type bitmaps only.
+ /// </summary>
+ public int UniqueColors
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetUniqueColors(dib);
+ }
+ }
+
+ /// <summary>
+ /// The size of one pixel in the bitmap in bits.
+ /// </summary>
+ public int ColorDepth
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetBPP(dib);
+ }
+ }
+
+ /// <summary>
+ /// Width of the bitmap in pixel units.
+ /// </summary>
+ public int Width
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetWidth(dib);
+ }
+ }
+
+ /// <summary>
+ /// Height of the bitmap in pixel units.
+ /// </summary>
+ public int Height
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetHeight(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary.
+ /// </summary>
+ public int Pitch
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetPitch(dib);
+ }
+ }
+
+ /// <summary>
+ /// Size of the bitmap in memory.
+ /// </summary>
+ public int DataSize
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetDIBSize(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns a structure that represents the palette of a FreeImage bitmap.
+ /// </summary>
+ /// <exception cref="InvalidOperationException"><see cref="HasPalette"/> is false.</exception>
+ public Palette Palette
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (HasPalette)
+ {
+ return new Palette(dib);
+ }
+ throw new InvalidOperationException("This bitmap does not have a palette.");
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the bitmap is RGB 555.
+ /// </summary>
+ public bool IsRGB555
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsRGB555(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the bitmap is RGB 565.
+ /// </summary>
+ public bool IsRGB565
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsRGB565(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public float HorizontalResolution
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (float)FreeImage.GetResolutionX(dib);
+ }
+ private set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionX(dib, (uint)value);
+ }
+ }
+
+ /// <summary>
+ /// Gets the vertical resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public float VerticalResolution
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (float)FreeImage.GetResolutionY(dib);
+ }
+ private set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionY(dib, (uint)value);
+ }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFOHEADER"/> structure of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public BITMAPINFOHEADER InfoHeader
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetInfoHeaderEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFO"/> structure of a this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public BITMAPINFO Info
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetInfoEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Investigates the color type of this <see cref="FreeImageBitmap"/>
+ /// by reading the bitmaps pixel bits and analysing them.
+ /// </summary>
+ public FREE_IMAGE_COLOR_TYPE ColorType
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetColorType(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the red color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint RedMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetRedMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the green color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint GreenMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetGreenMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the blue color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint BlueMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBlueMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Number of transparent colors in a palletised <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int TransparencyCount
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetTransparencyCount(dib);
+ }
+ }
+
+ /// <summary>
+ /// Get or sets transparency table of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public byte[] TransparencyTable
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetTransparencyTableEx(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparencyTable(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether this <see cref="FreeImageBitmap"/> is transparent.
+ /// </summary>
+ public bool IsTransparent
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsTransparent(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparent(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="FreeImageBitmap"/> has a file background color.
+ /// </summary>
+ public bool HasBackgroundColor
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.HasBackgroundColor(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the background color of this <see cref="FreeImageBitmap"/>.
+ /// In case the value is null, the background color is removed.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">Get: There is no background color available.</exception>
+ /// <exception cref="Exception">Set: Setting background color failed.</exception>
+ public Color? BackgroundColor
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (!FreeImage.HasBackgroundColor(dib))
+ {
+ throw new InvalidOperationException("No background color available.");
+ }
+ RGBQUAD rgbq;
+ FreeImage.GetBackgroundColor(dib, out rgbq);
+ return rgbq.Color;
+ }
+ set
+ {
+ EnsureNotDisposed();
+ if (!FreeImage.SetBackgroundColor(dib, (value.HasValue ? new RGBQUAD[] { value.Value } : null)))
+ {
+ throw new Exception("Setting background color failed.");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Pointer to the data-bits of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public IntPtr Bits
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBits(dib);
+ }
+ }
+
+ /// <summary>
+ /// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int Line
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetLine(dib);
+ }
+ }
+
+ /// <summary>
+ /// Pointer to the scanline of the top most pixel row of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public IntPtr Scan0
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetScanLine(dib, (int)(FreeImage.GetHeight(dib) - 1));
+ }
+ }
+
+ /// <summary>
+ /// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
+ /// In case this <see cref="FreeImageBitmap"/> is top down <b>Stride</b> will be positive, else negative.
+ /// </summary>
+ public int Stride
+ {
+ get
+ {
+ return -Line;
+ }
+ }
+
+ /// <summary>
+ /// Gets attribute flags for the pixel data of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public unsafe int Flags
+ {
+ get
+ {
+ EnsureNotDisposed();
+ int result = 0;
+ byte alpha;
+ int cd = ColorDepth;
+
+ if ((cd == 32) || (FreeImage.GetTransparencyCount(dib) != 0))
+ {
+ result += (int)ImageFlags.HasAlpha;
+ }
+
+ if (cd == 32)
+ {
+ uint width = FreeImage.GetWidth(dib);
+ uint height = FreeImage.GetHeight(dib);
+ for (int y = 0; y < height; y++)
+ {
+ RGBQUAD* scanline = (RGBQUAD*)FreeImage.GetScanLine(dib, y);
+ for (int x = 0; x < width; x++)
+ {
+ alpha = scanline[x].Color.A;
+ if (alpha != byte.MinValue && alpha != byte.MaxValue)
+ {
+ result += (int)ImageFlags.HasTranslucent;
+ y = (int)height;
+ break;
+ }
+ }
+ }
+ }
+ else if (FreeImage.GetTransparencyCount(dib) != 0)
+ {
+ byte[] transTable = FreeImage.GetTransparencyTableEx(dib);
+ for (int i = 0; i < transTable.Length; i++)
+ {
+ if (transTable[i] != byte.MinValue && transTable[i] != byte.MaxValue)
+ {
+ result += (int)ImageFlags.HasTranslucent;
+ break;
+ }
+ }
+ }
+
+ if (FreeImage.GetICCProfileEx(dib).IsCMYK)
+ {
+ result += (int)ImageFlags.ColorSpaceCmyk;
+ }
+ else
+ {
+ result += (int)ImageFlags.ColorSpaceRgb;
+ }
+
+ if (FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK ||
+ FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE)
+ {
+ result += (int)ImageFlags.ColorSpaceGray;
+ }
+
+ if (originalFormat == FREE_IMAGE_FORMAT.FIF_BMP ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_FAXG3 ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_ICO ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_JPEG ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PCX ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PNG ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PSD ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_TIFF)
+ {
+ result += (int)ImageFlags.HasRealDpi;
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Gets the width and height of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public SizeF PhysicalDimension
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new SizeF((float)FreeImage.GetWidth(dib), (float)FreeImage.GetHeight(dib));
+ }
+ }
+
+ /// <summary>
+ /// Gets the pixel format for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public PixelFormat PixelFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetPixelFormat(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets IDs of the property items stored in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int[] PropertyIdList
+ {
+ get
+ {
+ EnsureNotDisposed();
+ List<int> list = new List<int>();
+ ImageMetadata metaData = new ImageMetadata(dib, true);
+
+ foreach (MetadataModel metadataModel in metaData)
+ {
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ list.Add(metadataTag.ID);
+ }
+ }
+
+ return list.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Gets all the property items (pieces of metadata) stored in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public PropertyItem[] PropertyItems
+ {
+ get
+ {
+ EnsureNotDisposed();
+ List<PropertyItem> list = new List<PropertyItem>();
+ ImageMetadata metaData = new ImageMetadata(dib, true);
+
+ foreach (MetadataModel metadataModel in metaData)
+ {
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ list.Add(metadataTag.GetPropertyItem());
+ }
+ }
+
+ return list.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Gets the format of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public ImageFormat RawFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ Attribute guidAttribute =
+ Attribute.GetCustomAttribute(
+ typeof(FreeImageBitmap), typeof(System.Runtime.InteropServices.GuidAttribute)
+ );
+ return (guidAttribute == null) ?
+ null :
+ new ImageFormat(new Guid(((GuidAttribute)guidAttribute).Value));
+ }
+ }
+
+ /// <summary>
+ /// Gets the width and height, in pixels, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public Size Size
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new Size(Width, Height);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets an object that provides additional data about the <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public Object Tag
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return tag;
+ }
+ set
+ {
+ EnsureNotDisposed();
+ tag = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="FreeImageBitmap"/> has been disposed.
+ /// </summary>
+ public bool IsDisposed
+ {
+ get
+ {
+ return disposed;
+ }
+ }
+
+ /// <summary>
+ /// Gets a new instance of a metadata representing class.
+ /// </summary>
+ public ImageMetadata Metadata
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new ImageMetadata(dib, true);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the comment of this <see cref="FreeImageBitmap"/>.
+ /// Supported formats are JPEG, PNG and GIF.
+ /// </summary>
+ public string Comment
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetImageComment(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetImageComment(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Returns whether this <see cref="FreeImageBitmap"/> has a palette.
+ /// </summary>
+ public bool HasPalette
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (FreeImage.GetPalette(dib) != IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the entry used as transparent color in this <see cref="FreeImageBitmap"/>.
+ /// Only works for 1-, 4- and 8-bpp.
+ /// </summary>
+ public int TransparentIndex
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetTransparentIndex(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparentIndex(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of frames in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int FrameCount
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return frameCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets the ICCProfile structure of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public FIICCPROFILE ICCProfile
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetICCProfileEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets the format of the original image in case
+ /// this <see cref="FreeImageBitmap"/> was loaded from a file or stream.
+ /// </summary>
+ public FREE_IMAGE_FORMAT ImageFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return originalFormat;
+ }
+ }
+
+ /// <summary>
+ /// Gets the encapsulated FIBITMAP.
+ /// </summary>
+ internal FIBITMAP Dib
+ {
+ get { EnsureNotDisposed(); return dib; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Gets the bounds of this <see cref="FreeImageBitmap"/> in the specified unit.
+ /// </summary>
+ /// <param name="pageUnit">One of the <see cref="System.Drawing.GraphicsUnit"/> values indicating
+ /// the unit of measure for the bounding rectangle.</param>
+ /// <returns>The <see cref="System.Drawing.RectangleF"/> that represents the bounds of this
+ /// <see cref="FreeImageBitmap"/>, in the specified unit.</returns>
+ public RectangleF GetBounds(ref GraphicsUnit pageUnit)
+ {
+ EnsureNotDisposed();
+ pageUnit = GraphicsUnit.Pixel;
+ return new RectangleF(
+ 0f,
+ 0f,
+ (float)FreeImage.GetWidth(dib),
+ (float)FreeImage.GetHeight(dib));
+ }
+
+ /// <summary>
+ /// Gets the specified property item from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="propid">The ID of the property item to get.</param>
+ /// <returns>The <see cref="PropertyItem"/> this method gets.</returns>
+ public PropertyItem GetPropertyItem(int propid)
+ {
+ EnsureNotDisposed();
+ ImageMetadata metadata = new ImageMetadata(dib, true);
+ foreach (MetadataModel metadataModel in metadata)
+ {
+ foreach (MetadataTag tag in metadataModel)
+ {
+ if (tag.ID == propid)
+ {
+ return tag.GetPropertyItem();
+ }
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns a thumbnail for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="thumbWidth">The width, in pixels, of the requested thumbnail image.</param>
+ /// <param name="thumbHeight">The height, in pixels, of the requested thumbnail image.</param>
+ /// <param name="callback">Ignored.</param>
+ /// <param name="callBackData">Ignored.</param>
+ /// <returns>A <see cref="FreeImageBitmap"/> that represents the thumbnail.</returns>
+ public FreeImageBitmap GetThumbnailImage(int thumbWidth, int thumbHeight,
+ Image.GetThumbnailImageAbort callback, IntPtr callBackData)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Rescale(
+ dib, thumbWidth, thumbHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a thumbnail for this <see cref="FreeImageBitmap"/>, keeping aspect ratio.
+ /// <paramref name="maxPixelSize"/> defines the maximum width or height
+ /// of the thumbnail.
+ /// </summary>
+ /// <param name="maxPixelSize">Thumbnail square size.</param>
+ /// <param name="convert">When true HDR images are transperantly
+ /// converted to standard images.</param>
+ /// <returns>The thumbnail in a new instance.</returns>
+ public FreeImageBitmap GetThumbnailImage(int maxPixelSize, bool convert)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.MakeThumbnail(dib, maxPixelSize, convert);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
+ /// </summary>
+ /// <returns>A new instance of <see cref="Bitmap"/> initialized this instance.</returns>
+ public Bitmap ToBitmap()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBitmap(dib, true);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
+ /// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
+ /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
+ /// bottom-most line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline to retrieve.</param>
+ /// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
+ /// <paramref name="scanline"/>th scanline.</returns>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ /// <example>
+ /// <code>
+ /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
+ /// if (bitmap.ColorDepth == 32)
+ /// {
+ /// Scanline&lt;RGBQUAD&gt; scanline = bitmap.GetScanline&lt;RGBQUAD&gt;(0);
+ /// foreach (RGBQUAD pixel in scanline)
+ /// {
+ /// Console.WriteLine(pixel);
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ /// <exception cref="ArgumentException">
+ /// The bitmap's type or color depth are not supported.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="scanline"/> is no valid value.
+ /// </exception>
+ public Scanline<T> GetScanline<T>(int scanline) where T : struct
+ {
+ EnsureNotDisposed();
+ return new Scanline<T>(dib, scanline);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
+ /// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
+ /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
+ /// bottom-most line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline to retrieve.</param>
+ /// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
+ /// <paramref name="scanline"/>th scanline.</returns>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ /// <example>
+ /// <code>
+ /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
+ /// if (bitmap.ColorDepth == 32)
+ /// {
+ /// Scanline&lt;RGBQUAD&gt; scanline = (Scanline&lt;RGBQUAD&gt;)bitmap.GetScanline(0);
+ /// foreach (RGBQUAD pixel in scanline)
+ /// {
+ /// Console.WriteLine(pixel);
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ /// <exception cref="ArgumentException">
+ /// The type of the bitmap or color depth are not supported.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="scanline"/> is no valid value.
+ /// </exception>
+ public object GetScanline(int scanline)
+ {
+ EnsureNotDisposed();
+ object result = null;
+ int width = (int)FreeImage.GetWidth(dib);
+
+ switch (FreeImage.GetImageType(dib))
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+
+ switch (FreeImage.GetBPP(dib))
+ {
+ case 1u: result = new Scanline<FI1BIT>(dib, scanline, width); break;
+ case 4u: result = new Scanline<FI4BIT>(dib, scanline, width); break;
+ case 8u: result = new Scanline<Byte>(dib, scanline, width); break;
+ case 16u:
+ if ((RedMask == FreeImage.FI16_555_RED_MASK) &&
+ (GreenMask == FreeImage.FI16_555_GREEN_MASK) &&
+ (BlueMask == FreeImage.FI16_555_BLUE_MASK))
+ {
+ result = new Scanline<FI16RGB555>(dib, scanline, width);
+ }
+ else if ((RedMask == FreeImage.FI16_565_RED_MASK) &&
+ (GreenMask == FreeImage.FI16_565_GREEN_MASK) &&
+ (BlueMask == FreeImage.FI16_565_BLUE_MASK))
+ {
+ result = new Scanline<FI16RGB565>(dib, scanline, width);
+ }
+ else
+ {
+ result = new Scanline<UInt16>(dib, scanline, width);
+ }
+ break;
+ case 24u: result = new Scanline<RGBTRIPLE>(dib, scanline, width); break;
+ case 32u: result = new Scanline<RGBQUAD>(dib, scanline, width); break;
+ default: throw new ArgumentException("Color depth is not supported.");
+ }
+ break;
+
+ case FREE_IMAGE_TYPE.FIT_COMPLEX: result = new Scanline<FICOMPLEX>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE: result = new Scanline<Double>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT: result = new Scanline<Single>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_INT16: result = new Scanline<Int16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_INT32: result = new Scanline<Int32>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16: result = new Scanline<FIRGB16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16: result = new Scanline<FIRGBA16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF: result = new Scanline<FIRGBAF>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF: result = new Scanline<FIRGBF>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16: result = new Scanline<UInt16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32: result = new Scanline<UInt32>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ default: throw new ArgumentException("Type is not supported.");
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a pointer to the specified scanline.
+ /// Due to FreeImage bitmaps are bottum up,
+ /// scanline 0 is the most bottom line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline.</param>
+ /// <returns>Pointer to the scanline.</returns>
+ public IntPtr GetScanlinePointer(int scanline)
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetScanLine(dib, scanline);
+ }
+
+ /// <summary>
+ /// Returns a list of structures, representing the scanlines of this <see cref="FreeImageBitmap"/>.
+ /// Due to FreeImage bitmaps are bottum up, scanline 0 is the
+ /// bottom-most line of the image.
+ /// Each color depth has a different representing structure due to different memory layouts.
+ /// </summary>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type of IEnmuerable&lt;Scanline&lt;T&gt;&gt;</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ public IList GetScanlines()
+ {
+ EnsureNotDisposed();
+
+ int height = (int)FreeImage.GetHeight(dib);
+ IList list;
+
+ switch (FreeImage.GetImageType(dib))
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+
+ switch (FreeImage.GetBPP(dib))
+ {
+ case 1u: list = new List<Scanline<FI1BIT>>(height); break;
+ case 4u: list = new List<Scanline<FI4BIT>>(height); break;
+ case 8u: list = new List<Scanline<Byte>>(height); break;
+ case 16u:
+ if (FreeImage.IsRGB555(dib))
+ {
+ list = new List<Scanline<FI16RGB555>>(height);
+ }
+ else if (FreeImage.IsRGB565(dib))
+ {
+ list = new List<Scanline<FI16RGB565>>(height);
+ }
+ else
+ {
+ list = new List<Scanline<UInt16>>(height);
+ }
+ break;
+ case 24u: list = new List<Scanline<RGBTRIPLE>>(height); break;
+ case 32u: list = new List<Scanline<RGBQUAD>>(height); break;
+ default: throw new ArgumentException("Color depth is not supported.");
+ }
+ break;
+
+ case FREE_IMAGE_TYPE.FIT_COMPLEX: list = new List<Scanline<FICOMPLEX>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE: list = new List<Scanline<Double>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT: list = new List<Scanline<Single>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_INT16: list = new List<Scanline<Int16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_INT32: list = new List<Scanline<Int32>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16: list = new List<Scanline<FIRGB16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16: list = new List<Scanline<FIRGBA16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF: list = new List<Scanline<FIRGBAF>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF: list = new List<Scanline<FIRGBF>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16: list = new List<Scanline<UInt16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32: list = new List<Scanline<UInt32>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ default: throw new ArgumentException("Type is not supported.");
+ }
+
+ for (int i = 0; i < height; i++)
+ {
+ list.Add(GetScanline(i));
+ }
+
+ return list;
+ }
+
+ /// <summary>
+ /// Removes the specified property item from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="propid">The ID of the property item to remove.</param>
+ public void RemovePropertyItem(int propid)
+ {
+ EnsureNotDisposed();
+ ImageMetadata mdata = new ImageMetadata(dib, true);
+ foreach (MetadataModel model in mdata)
+ {
+ foreach (MetadataTag tag in model)
+ {
+ if (tag.ID == propid)
+ {
+ model.RemoveTag(tag.Key);
+ return;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method rotates, flips, or rotates and flips this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="rotateFlipType">A RotateFlipType member
+ /// that specifies the type of rotation and flip to apply to this <see cref="FreeImageBitmap"/>.</param>
+ public void RotateFlip(RotateFlipType rotateFlipType)
+ {
+ EnsureNotDisposed();
+
+ FIBITMAP newDib = new FIBITMAP();
+ uint bpp = FreeImage.GetBPP(dib);
+
+ switch (rotateFlipType)
+ {
+ case RotateFlipType.RotateNoneFlipX:
+
+ FreeImage.FlipHorizontal(dib);
+ break;
+
+ case RotateFlipType.RotateNoneFlipY:
+
+ FreeImage.FlipVertical(dib);
+ break;
+
+ case RotateFlipType.RotateNoneFlipXY:
+
+ FreeImage.FlipHorizontal(dib);
+ FreeImage.FlipVertical(dib);
+ break;
+
+ case RotateFlipType.Rotate90FlipNone:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ break;
+
+ case RotateFlipType.Rotate90FlipX:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipHorizontal(newDib);
+ break;
+
+ case RotateFlipType.Rotate90FlipY:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipVertical(newDib);
+ break;
+
+ case RotateFlipType.Rotate90FlipXY:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipHorizontal(newDib);
+ FreeImage.FlipVertical(newDib);
+ break;
+
+ case RotateFlipType.Rotate180FlipXY:
+ newDib = FreeImage.Clone(dib);
+ break;
+ }
+ ReplaceDib(newDib);
+ }
+
+ /// <summary>
+ /// Copies the metadata from another <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="bitmap">The bitmap to read the metadata from.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is a null reference.
+ /// </exception>
+ public void CloneMetadataFrom(FreeImageBitmap bitmap)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ FreeImage.CloneMetadata(dib, bitmap.dib);
+ }
+
+ /// <summary>
+ /// Copies the metadata from another <see cref="FreeImageBitmap"/> using
+ /// the provided options.
+ /// </summary>
+ /// <param name="bitmap">The bitmap to read the metadata from.</param>
+ /// <param name="flags">Specifies the way the metadata is copied.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is a null reference.
+ /// </exception>
+ public void CloneMetadataFrom(FreeImageBitmap bitmap, FREE_IMAGE_METADATA_COPY flags)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ FreeImage.CloneMetadataEx(bitmap.dib, dib, flags);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename)
+ {
+ Save(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file in the specified format.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename, FREE_IMAGE_FORMAT format)
+ {
+ Save(filename, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file in the specified format
+ /// using the specified saving flags.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ EnsureNotDisposed();
+ if (string.IsNullOrEmpty(filename))
+ {
+ throw new ArgumentException("filename");
+ }
+ if (!FreeImage.SaveEx(dib, filename, format, flags))
+ {
+ throw new Exception("Unable to save bitmap");
+ }
+
+ saveInformation.filename = filename;
+ saveInformation.format = format;
+ saveInformation.saveFlags = flags;
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified stream in the specified format.
+ /// </summary>
+ /// <param name="stream">The stream where this <see cref="FreeImageBitmap"/> will be saved.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(Stream stream, FREE_IMAGE_FORMAT format)
+ {
+ Save(stream, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified stream in the specified format
+ /// using the specified saving flags.
+ /// </summary>
+ /// <param name="stream">The stream where this <see cref="FreeImageBitmap"/> will be saved.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ EnsureNotDisposed();
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!FreeImage.SaveToStream(dib, stream, format, flags))
+ {
+ throw new Exception("Unable to save bitmap");
+ }
+
+ saveInformation.filename = null;
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/>
+ /// method.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not been saved to a file using Save(...) before.</exception>
+ public void SaveAdd()
+ {
+ SaveAdd(this);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(int insertPosition)
+ {
+ SaveAdd(this, insertPosition);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ public void SaveAdd(FreeImageBitmap bitmap)
+ {
+ if (saveInformation.filename == null)
+ {
+ throw new InvalidOperationException("This operation requires a previous call of Save().");
+ }
+
+ SaveAdd(
+ saveInformation.filename,
+ bitmap,
+ saveInformation.format,
+ saveInformation.loadFlags,
+ saveInformation.saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(FreeImageBitmap bitmap, int insertPosition)
+ {
+ if (saveInformation.filename == null)
+ {
+ throw new InvalidOperationException("This operation requires a previous call of Save().");
+ }
+
+ SaveAdd(
+ saveInformation.filename,
+ bitmap,
+ insertPosition,
+ saveInformation.format,
+ saveInformation.loadFlags,
+ saveInformation.saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ public void SaveAdd(string filename)
+ {
+ SaveAdd(
+ filename,
+ this,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(string filename, int insertPosition)
+ {
+ SaveAdd(
+ filename,
+ this,
+ insertPosition,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified using the specified parameters.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ public void SaveAdd(
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ SaveAdd(
+ filename,
+ this,
+ format,
+ loadFlags,
+ saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified using the specified parameters.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(
+ string filename,
+ int insertPosition,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ SaveAdd(
+ filename,
+ this,
+ insertPosition,
+ format,
+ loadFlags,
+ saveFlags);
+ }
+
+ /// <summary>
+ /// Selects the frame specified by the index.
+ /// </summary>
+ /// <param name="frameIndex">The index of the active frame.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="frameIndex"/> is out of range.</exception>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="InvalidOperationException">The source of the bitmap is not available.
+ /// </exception>
+ public void SelectActiveFrame(int frameIndex)
+ {
+ EnsureNotDisposed();
+ if ((frameIndex < 0) || (frameIndex >= frameCount))
+ {
+ throw new ArgumentOutOfRangeException("frameIndex");
+ }
+
+ if (frameIndex != this.frameIndex)
+ {
+ if (stream == null)
+ {
+ throw new InvalidOperationException("No source available.");
+ }
+
+ FREE_IMAGE_FORMAT format = originalFormat;
+ FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, saveInformation.loadFlags);
+ if (mdib.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ try
+ {
+ if (frameIndex >= FreeImage.GetPageCount(mdib))
+ {
+ throw new ArgumentOutOfRangeException("frameIndex");
+ }
+
+ FIBITMAP newDib = FreeImage.LockPage(mdib, frameIndex);
+ if (newDib.IsNull)
+ {
+ throw new Exception(ErrorLoadingFrame);
+ }
+
+ try
+ {
+ FIBITMAP clone = FreeImage.Clone(newDib);
+ if (clone.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ ReplaceDib(clone);
+ }
+ finally
+ {
+ if (!newDib.IsNull)
+ {
+ FreeImage.UnlockPage(mdib, newDib, false);
+ }
+ }
+ }
+ finally
+ {
+ if (!FreeImage.CloseMultiBitmapEx(ref mdib))
+ {
+ throw new Exception(ErrorUnloadBitmap);
+ }
+ }
+
+ this.frameIndex = frameIndex;
+ }
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmap()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetHbitmap(dib, IntPtr.Zero, false);
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="background">A <see cref="System.Drawing.Color"/> structure that specifies the background color.
+ /// This parameter is ignored if the bitmap is totally opaque.</param>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmap(Color background)
+ {
+ EnsureNotDisposed();
+ using (FreeImageBitmap temp = new FreeImageBitmap(this))
+ {
+ temp.BackgroundColor = background;
+ return temp.GetHbitmap();
+ }
+ }
+
+ /// <summary>
+ /// Returns the handle to an icon.
+ /// </summary>
+ /// <returns>A Windows handle to an icon with the same image as this <see cref="FreeImageBitmap"/>.</returns>
+ public IntPtr GetHicon()
+ {
+ EnsureNotDisposed();
+ using (Bitmap bitmap = FreeImage.GetBitmap(dib, true))
+ {
+ return bitmap.GetHicon();
+ }
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/> with the same
+ /// color depth as the primary device.
+ /// </summary>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmapForDevice()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBitmapForDevice(dib, IntPtr.Zero, false);
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Color"/> of the specified pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="x">The x-coordinate of the pixel to retrieve.</param>
+ /// <param name="y">The y-coordinate of the pixel to retrieve.</param>
+ /// <returns>A <see cref="System.Drawing.Color"/> structure that represents the color of the specified pixel.</returns>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="NotSupportedException">The type of this bitmap is not supported.</exception>
+ public unsafe Color GetPixel(int x, int y)
+ {
+ EnsureNotDisposed();
+ if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32)
+ {
+ RGBQUAD rgbq;
+ if (!FreeImage.GetPixelColor(dib, (uint)x, (uint)y, out rgbq))
+ {
+ throw new Exception("FreeImage.GetPixelColor() failed");
+ }
+ return rgbq.Color;
+ }
+ else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8)
+ {
+ byte index;
+ if (!FreeImage.GetPixelIndex(dib, (uint)x, (uint)y, out index))
+ {
+ throw new Exception("FreeImage.GetPixelIndex() failed");
+ }
+ RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib);
+ return palette[index].Color;
+ }
+ }
+ throw new NotSupportedException("The type of the image is not supported");
+ }
+
+ /// <summary>
+ /// Makes the default transparent color transparent for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public void MakeTransparent()
+ {
+ EnsureNotDisposed();
+ MakeTransparent(Color.Transparent);
+ }
+
+ /// <summary>
+ /// Makes the specified color transparent for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="transparentColor">The <see cref="System.Drawing.Color"/> structure that represents
+ /// the color to make transparent.</param>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public void MakeTransparent(Color transparentColor)
+ {
+ EnsureNotDisposed();
+ throw new System.NotImplementedException();
+ }
+
+ /// <summary>
+ /// Sets the <see cref="System.Drawing.Color"/> of the specified pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="x">The x-coordinate of the pixel to set.</param>
+ /// <param name="y">The y-coordinate of the pixel to set.</param>
+ /// <param name="color">A <see cref="System.Drawing.Color"/> structure that represents the color
+ /// to assign to the specified pixel.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="NotSupportedException">The type of this bitmap is not supported.</exception>
+ public unsafe void SetPixel(int x, int y, Color color)
+ {
+ EnsureNotDisposed();
+ if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32)
+ {
+ RGBQUAD rgbq = color;
+ if (!FreeImage.SetPixelColor(dib, (uint)x, (uint)y, ref rgbq))
+ {
+ throw new Exception("FreeImage.SetPixelColor() failed");
+ }
+ return;
+ }
+ else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8)
+ {
+ uint colorsUsed = FreeImage.GetColorsUsed(dib);
+ RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib);
+ for (int i = 0; i < colorsUsed; i++)
+ {
+ if (palette[i].Color == color)
+ {
+ byte index = (byte)i;
+ if (!FreeImage.SetPixelIndex(dib, (uint)x, (uint)y, ref index))
+ {
+ throw new Exception("FreeImage.SetPixelIndex() failed");
+ }
+ return;
+ }
+ }
+ throw new ArgumentOutOfRangeException("color");
+ }
+ }
+ throw new NotSupportedException("The type of the image is not supported");
+ }
+
+ /// <summary>
+ /// Sets the resolution for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="xDpi">The horizontal resolution, in dots per inch, of this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="yDpi">The vertical resolution, in dots per inch, of this <see cref="FreeImageBitmap"/>.</param>
+ public void SetResolution(float xDpi, float yDpi)
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionX(dib, (uint)xDpi);
+ FreeImage.SetResolutionY(dib, (uint)yDpi);
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public void UnlockBits(BitmapData bitmapdata)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> into a different color depth.
+ /// The parameter <paramref name="bpp"/> specifies color depth, greyscale conversion
+ /// and palette reorder.
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE"/> flag
+ /// will first perform a convesion to greyscale. This can be done with any target
+ /// color depth.</para>
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE"/> flag
+ /// will allow the algorithm to reorder the palette. This operation will not be performed to
+ /// non-greyscale images to prevent data loss by mistake.</para>
+ /// </summary>
+ /// <param name="bpp">A bitfield containing information about the conversion
+ /// to perform.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH bpp)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.ConvertColorDepth(dib, bpp, false));
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> <see cref="FREE_IMAGE_TYPE"/> to
+ /// <paramref name="type"/> initializing a new instance.
+ /// In case source and destination type are the same, the operation fails.
+ /// An error message can be catched using the 'Message' event.
+ /// </summary>
+ /// <param name="type">Destination type.</param>
+ /// <param name="scaleLinear">True to scale linear, else false.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool ConvertType(FREE_IMAGE_TYPE type, bool scaleLinear)
+ {
+ EnsureNotDisposed();
+ return (ImageType == type) ? false : ReplaceDib(FreeImage.ConvertToType(dib, type, scaleLinear));
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> <see cref="FreeImageBitmap"/> to <paramref name="type"/>.
+ /// In case source and destination type are the same, the operation fails.
+ /// An error message can be catched using the 'Message' event.
+ /// </summary>
+ /// <param name="type">Destination type.</param>
+ /// <param name="scaleLinear">True to scale linear, else false.</param>
+ /// <returns>The converted instance.</returns>
+ public FreeImageBitmap GetTypeConvertedInstance(FREE_IMAGE_TYPE type, bool scaleLinear)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ if (ImageType != type)
+ {
+ FIBITMAP newDib = FreeImage.ConvertToType(dib, type, scaleLinear);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> into a different color depth initializing
+ /// a new instance.
+ /// The parameter <paramref name="bpp"/> specifies color depth, greyscale conversion
+ /// and palette reorder.
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE"/> flag will
+ /// first perform a convesion to greyscale. This can be done with any target color depth.</para>
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE"/> flag will
+ /// allow the algorithm to reorder the palette. This operation will not be performed to
+ /// non-greyscale images to prevent data loss by mistake.</para>
+ /// </summary>
+ /// <param name="bpp">A bitfield containing information about the conversion
+ /// to perform.</param>
+ /// <returns>The converted instance.</returns>
+ public FreeImageBitmap GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH bpp)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.ConvertColorDepth(dib, bpp, false);
+ if (newDib == dib)
+ {
+ newDib = FreeImage.Clone(dib);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter.
+ /// </summary>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rescale(Size newSize, FREE_IMAGE_FILTER filter)
+ {
+ return Rescale(newSize.Width, newSize.Height, filter);
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter.
+ /// </summary>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rescale(int width, int height, FREE_IMAGE_FILTER filter)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.Rescale(dib, width, height, filter));
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter initializing a new instance.
+ /// </summary>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>The rescaled instance.</returns>
+ public FreeImageBitmap GetScaledInstance(Size newSize, FREE_IMAGE_FILTER filter)
+ {
+ return GetScaledInstance(newSize.Width, newSize.Height, filter);
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter initializing a new instance.
+ /// </summary>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>The rescaled instance.</returns>
+ public FreeImageBitmap GetScaledInstance(int width, int height, FREE_IMAGE_FILTER filter)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Rescale(dib, width, height, filter);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool EnlargeCanvas<T>(int left, int top, int right, int bottom, T? color) where T : struct
+ {
+ return EnlargeCanvas(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool EnlargeCanvas<T>(int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options));
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color returning a new instance.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <returns>The enlarged instance.</returns>
+ public FreeImageBitmap GetEnlargedInstance<T>(int left, int top, int right, int bottom,
+ T? color) where T : struct
+ {
+ return GetEnlargedInstance(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color returning a new instance.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns>The enlarged instance.</returns>
+ public FreeImageBitmap GetEnlargedInstance<T>(int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize)
+ {
+ return Quantize(algorithm, paletteSize, 0, (RGBQUAD[])null);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette)
+ {
+ return Quantize(algorithm, paletteSize, reservePalette.Length, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette)
+ {
+ return Quantize(algorithm, paletteSize, reserveSize, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette));
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> initializing a new 8 bit instance with the
+ /// specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, 0, (RGBQUAD[])null);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and <paramref name="reservePalette">palette</paramref>
+ /// initializing a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, reservePalette.Length, reservePalette);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and up to <paramref name="reserveSize"/>
+ /// entries from <paramref name="reservePalette">palette</paramref> initializing
+ /// a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, reserveSize, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and up to <paramref name="reserveSize"/>
+ /// entries from <paramref name="reservePalette">palette</paramref> initializing
+ /// a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global
+ /// operator based on logarithmic compression of luminance values, imitating
+ /// the human response to light.
+ /// </summary>
+ /// <param name="gamma">A gamma correction that is applied after the tone mapping.
+ /// A value of 1 means no correction.</param>
+ /// <param name="exposure">Scale factor allowing to adjust the brightness of the output image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoDrago03(double gamma, double exposure)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoDrago03(dib, gamma, exposure));
+ }
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global operator inspired
+ /// by photoreceptor physiology of the human visual system.
+ /// </summary>
+ /// <param name="intensity">Controls the overall image intensity in the range [-8, 8].</param>
+ /// <param name="contrast">Controls the overall image contrast in the range [0.3, 1.0[.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoReinhard05(double intensity, double contrast)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoReinhard05(dib, intensity, contrast));
+ }
+
+ /// <summary>
+ /// Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB.
+ /// </summary>
+ /// <param name="color_saturation">Color saturation (s parameter in the paper) in [0.4..0.6]</param>
+ /// <param name="attenuation">Atenuation factor (beta parameter in the paper) in [0.8..0.9]</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoFattal02(double color_saturation, double attenuation)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoFattal02(dib, color_saturation, attenuation));
+ }
+
+ /// <summary>
+ /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate(double angle)
+ {
+ EnsureNotDisposed();
+ bool result = false;
+ if (ColorDepth == 4)
+ {
+ result = ReplaceDib(FreeImage.Rotate4bit(dib, angle));
+ }
+ else
+ {
+ result = ReplaceDib(FreeImage.Rotate(dib, angle));
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate<T>(double angle, T? backgroundColor) where T : struct
+ {
+ EnsureNotDisposed();
+ bool result = false;
+ if (ColorDepth == 4)
+ {
+ result = ReplaceDib(FreeImage.Rotate4bit(dib, angle));
+ }
+ else
+ {
+ result = ReplaceDib(FreeImage.Rotate(dib, angle, backgroundColor));
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rotates this <see cref="FreeImageBitmap"/> by the specified angle initializing a new instance.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance<T>(double angle, T? backgroundColor) where T : struct
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib;
+ if (ColorDepth == 4)
+ {
+ newDib = FreeImage.Rotate4bit(dib, angle);
+ }
+ else
+ {
+ newDib = FreeImage.Rotate(dib, angle, backgroundColor);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rotates this <see cref="FreeImageBitmap"/> by the specified angle initializing a new instance.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance(double angle)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib;
+ if (ColorDepth == 4)
+ {
+ newDib = FreeImage.Rotate4bit(dib, angle);
+ }
+ else
+ {
+ newDib = FreeImage.Rotate(dib, angle);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This method performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="xShift">Horizontal image translation.</param>
+ /// <param name="yShift">Vertical image translation.</param>
+ /// <param name="xOrigin">Rotation center x-coordinate.</param>
+ /// <param name="yOrigin">Rotation center y-coordinate.</param>
+ /// <param name="useMask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate(double angle, double xShift, double yShift,
+ double xOrigin, double yOrigin, bool useMask)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.RotateEx(dib, angle, xShift, yShift, xOrigin, yOrigin, useMask));
+ }
+
+ /// <summary>
+ /// This method performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline initializing a new instance.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="xShift">Horizontal image translation.</param>
+ /// <param name="yShift">Vertical image translation.</param>
+ /// <param name="xOrigin">Rotation center x-coordinate.</param>
+ /// <param name="yOrigin">Rotation center y-coordinate.</param>
+ /// <param name="useMask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance(double angle, double xShift, double yShift,
+ double xOrigin, double yOrigin, bool useMask)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.RotateEx(
+ dib, angle, xShift, yShift, xOrigin, yOrigin, useMask);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Perfoms an histogram transformation on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="lookUpTable">The lookup table (LUT).
+ /// It's size is assumed to be 256 in length.</param>
+ /// <param name="channel">The color channel to be transformed.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustCurve(byte[] lookUpTable, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustCurve(dib, lookUpTable, channel);
+ }
+
+ /// <summary>
+ /// Performs gamma correction on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="gamma">The parameter represents the gamma value to use (gamma > 0).
+ /// A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustGamma(double gamma)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustGamma(dib, gamma);
+ }
+
+ /// <summary>
+ /// Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will make the image darker and greater than 0 will make the image brighter.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustBrightness(double percentage)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustBrightness(dib, percentage);
+ }
+
+ /// <summary>
+ /// Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustContrast(double percentage)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustContrast(dib, percentage);
+ }
+
+ /// <summary>
+ /// Inverts each pixel data.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Invert()
+ {
+ EnsureNotDisposed();
+ return FreeImage.Invert(dib);
+ }
+
+ /// <summary>
+ /// Computes the image histogram.
+ /// </summary>
+ /// <param name="channel">Channel to compute from.</param>
+ /// <param name="histogram">Array of integers containing the histogram.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool GetHistogram(FREE_IMAGE_COLOR_CHANNEL channel, out int[] histogram)
+ {
+ EnsureNotDisposed();
+ histogram = new int[256];
+ return FreeImage.GetHistogram(dib, histogram, channel);
+ }
+
+ /// <summary>
+ /// Retrieves the red, green, blue or alpha channel of a 24- or 32-bit image.
+ /// </summary>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>The color channel in a new instance.</returns>
+ public FreeImageBitmap GetChannel(FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.GetChannel(dib, channel);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Insert a 8-bit dib into a 24- or 32-bit image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool SetChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.SetChannel(dib, bitmap.dib, channel);
+ }
+
+ /// <summary>
+ /// Retrieves the real part, imaginary part, magnitude or phase of a complex image.
+ /// </summary>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>The color channel in a new instance.</returns>
+ public FreeImageBitmap GetComplexChannel(FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.GetComplexChannel(dib, channel);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Set the real or imaginary part of a complex image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool SetComplexChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.SetComplexChannel(dib, bitmap.dib, channel);
+ }
+
+ /// <summary>
+ /// Copy a sub part of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="rect">The subpart to copy.</param>
+ /// <returns>The sub part in a new instance.</returns>
+ public FreeImageBitmap Copy(Rectangle rect)
+ {
+ EnsureNotDisposed();
+ return Copy(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ /// <summary>
+ /// Copy a sub part of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>The sub part in a new instance.</returns>
+ public FreeImageBitmap Copy(int left, int top, int right, int bottom)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Copy(dib, left, top, right, bottom);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with this <see cref="FreeImageBitmap"/>.
+ /// The bit depth of <paramref name="bitmap"/> must be greater than or equal to the bit depth this instance.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to paste into this instance.</param>
+ /// <param name="left">Specifies the left position of the sub image.</param>
+ /// <param name="top">Specifies the top position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Paste(FreeImageBitmap bitmap, int left, int top, int alpha)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.Paste(dib, bitmap.dib, left, top, alpha);
+ }
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with tthis <see cref="FreeImageBitmap"/>.
+ /// The bit depth of <paramref name="bitmap"/> must be greater than or equal to the bit depth this instance.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to paste into this instance.</param>
+ /// <param name="point">Specifies the position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Paste(FreeImageBitmap bitmap, Point point, int alpha)
+ {
+ EnsureNotDisposed();
+ return Paste(bitmap, point.X, point.Y, alpha);
+ }
+
+ /// <summary>
+ /// This method composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// In case <paramref name="useBitmapBackground"/> is false and <paramref name="applicationBackground"/>
+ /// and <paramref name="bitmapBackGround"/>
+ /// are null, a checkerboard will be used as background.
+ /// </summary>
+ /// <param name="useBitmapBackground">When true the background of this instance is used
+ /// if it contains one.</param>
+ /// <param name="applicationBackground">Backgroundcolor used in case <paramref name="useBitmapBackground"/> is false
+ /// and <paramref name="applicationBackground"/> is not null.</param>
+ /// <param name="bitmapBackGround">Background used in case <paramref name="useBitmapBackground"/>
+ /// is false and <paramref name="applicationBackground"/> is a null reference.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Composite(bool useBitmapBackground, Color? applicationBackground, FreeImageBitmap bitmapBackGround)
+ {
+ EnsureNotDisposed();
+ bitmapBackGround.EnsureNotDisposed();
+ RGBQUAD? rgb = applicationBackground;
+ return ReplaceDib(
+ FreeImage.Composite(
+ dib,
+ useBitmapBackground,
+ rgb.HasValue ? new RGBQUAD[] { rgb.Value } : null,
+ bitmapBackGround.dib));
+ }
+
+ /// <summary>
+ /// Applies the alpha value of each pixel to its color components.
+ /// The aplha value stays unchanged.
+ /// Only works with 32-bits color depth.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool PreMultiplyWithAlpha()
+ {
+ EnsureNotDisposed();
+ return FreeImage.PreMultiplyWithAlpha(dib);
+ }
+
+ /// <summary>
+ /// Solves a Poisson equation, remap result pixels to [0..1] and returns the solution.
+ /// </summary>
+ /// <param name="ncycle">Number of cycles in the multigrid algorithm (usually 2 or 3)</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool MultigridPoissonSolver(int ncycle)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.MultigridPoissonSolver(dib, ncycle));
+ }
+
+ /// <summary>
+ /// Adjusts an image's brightness, contrast and gamma as well as it may
+ /// optionally invert the image within a single operation.
+ /// </summary>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para>
+ /// This parameter must not be zero or smaller than zero.
+ /// If so, it will be ignored and no gamma correction will be performed on the image.</param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustColors(double brightness, double contrast, double gamma, bool invert)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustColors(dib, brightness, contrast, gamma, invert);
+ }
+
+ /// <summary>
+ /// Applies color mapping for one or several colors on a 1-, 4- or 8-bit
+ /// palletized or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="srccolors">Array of colors to be used as the mapping source.</param>
+ /// <param name="dstcolors">Array of colors to be used as the mapping destination.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <param name="swap">If true, source and destination colors are swapped, that is,
+ /// each destination color is also mapped to the corresponding source color.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="srccolors"/> or <paramref name="dstcolors"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="srccolors"/> has a different length than <paramref name="dstcolors"/>.
+ /// </exception>
+ public uint ApplyColorMapping(RGBQUAD[] srccolors, RGBQUAD[] dstcolors, bool ignore_alpha, bool swap)
+ {
+ EnsureNotDisposed();
+ if (srccolors == null)
+ {
+ throw new ArgumentNullException("srccolors");
+ }
+ if (dstcolors == null)
+ {
+ throw new ArgumentNullException("dstcolors");
+ }
+ if (srccolors.Length != dstcolors.Length)
+ {
+ throw new ArgumentException("srccolors and dstcolors must have the same length.");
+ }
+ return FreeImage.ApplyColorMapping(dib, srccolors, dstcolors, (uint)srccolors.Length, ignore_alpha, swap);
+ }
+
+ /// <summary>
+ /// Swaps two specified colors on a 1-, 4- or 8-bit palletized
+ /// or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="color_a">One of the two colors to be swapped.</param>
+ /// <param name="color_b">The other of the two colors to be swapped.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ public uint SwapColors(RGBQUAD color_a, RGBQUAD color_b, bool ignore_alpha)
+ {
+ EnsureNotDisposed();
+ return FreeImage.SwapColors(dib, ref color_a, ref color_b, ignore_alpha);
+ }
+
+ /// <summary>
+ /// Applies palette index mapping for one or several indices
+ /// on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="srcindices">Array of palette indices to be used as the mapping source.</param>
+ /// <param name="dstindices">Array of palette indices to be used as the mapping destination.</param>
+ /// <param name="count">The number of palette indices to be mapped. This is the size of both
+ /// srcindices and dstindices</param>
+ /// <param name="swap">If true, source and destination palette indices are swapped, that is,
+ /// each destination index is also mapped to the corresponding source index.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="srccolors"/> or <paramref name="dstcolors"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="srccolors"/> has a different length than <paramref name="dstcolors"/>.
+ /// </exception>
+ public uint ApplyPaletteIndexMapping(byte[] srcindices, byte[] dstindices, uint count, bool swap)
+ {
+ EnsureNotDisposed();
+ if (srcindices == null)
+ {
+ throw new ArgumentNullException("srcindices");
+ }
+ if (dstindices == null)
+ {
+ throw new ArgumentNullException("dstindices");
+ }
+ if (srcindices.Length != dstindices.Length)
+ {
+ throw new ArgumentException("srcindices and dstindices must have the same length.");
+ }
+ return FreeImage.ApplyPaletteIndexMapping(dib, srcindices, dstindices, (uint)srcindices.Length, swap);
+ }
+
+ /// <summary>
+ /// Swaps two specified palette indices on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="index_a">One of the two palette indices to be swapped.</param>
+ /// <param name="index_b">The other of the two palette indices to be swapped.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ public uint SwapPaletteIndices(byte index_a, byte index_b)
+ {
+ EnsureNotDisposed();
+ return FreeImage.SwapPaletteIndices(dib, ref index_a, ref index_b);
+ }
+
+ /// <summary>
+ /// Sets all pixels of this <see cref="FreeImageBitmap"/> to the specified color.
+ /// See <see cref="FreeImage.FillBackground&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="color">The color to fill this <see cref="FreeImageBitmap"/> with.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool FillBackground<T>(T color) where T : struct
+ {
+ return FillBackground(color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Sets all pixels of this <see cref="FreeImageBitmap"/> to the specified color.
+ /// See <see cref="FreeImage.FillBackground&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="color">The color to fill this <see cref="FreeImageBitmap"/> with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool FillBackground<T>(T color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ return FreeImage.FillBackground(dib, color, options);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile.
+ /// </summary>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="data"/> is a null reference.</exception>
+ public FIICCPROFILE CreateICCProfile(byte[] data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+ return CreateICCProfile(data, data.Length);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile.
+ /// </summary>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <param name="size">The number of bytes of <paramref name="data"/> to use.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+ public FIICCPROFILE CreateICCProfile(byte[] data, int size)
+ {
+ EnsureNotDisposed();
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+ return FreeImage.CreateICCProfileEx(dib, data, size);
+ }
+
+ /// <summary>
+ /// Determines whether this and the specified instances are the same.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if this instance is the same <paramref name="obj"/>
+ /// or if both are null references; otherwise, false.</returns>
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FreeImageBitmap"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FreeImageBitmap"/>.</returns>
+ public override int GetHashCode()
+ {
+ return dib.GetHashCode();
+ }
+
+ #endregion
+
+ #region Static functions
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format for this <see cref="FreeImageBitmap"/> contains alpha information.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> to test.</param>
+ /// <returns><b>true</b> if pixfmt contains alpha information; otherwise, <b>false</b>.</returns>
+ public static bool IsAlphaPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsAlphaPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format is 32 bits per pixel.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> to test.</param>
+ /// <returns>true if pixfmt is canonical; otherwise, false.</returns>
+ public static bool IsCanonicalPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsCanonicalPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format is 64 bits per pixel.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> enumeration to test.</param>
+ /// <returns>true if pixfmt is extended; otherwise, false.</returns>
+ public static bool IsExtendedPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsExtendedPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a Windows handle to an icon.
+ /// </summary>
+ /// <param name="hicon">A handle to an icon.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> that this method creates.</returns>
+ public static FreeImageBitmap FromHicon(IntPtr hicon)
+ {
+ using (Bitmap bitmap = Bitmap.FromHicon(hicon))
+ {
+ return new FreeImageBitmap(bitmap);
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified Windows resource.
+ /// </summary>
+ /// <param name="hinstance">A handle to an instance of the executable
+ /// file that contains the resource.</param>
+ /// <param name="bitmapName">A string containing the name of the resource bitmap.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> that this method creates.</returns>
+ public static FreeImageBitmap FromResource(IntPtr hinstance, string bitmapName)
+ {
+ using (Bitmap bitmap = Bitmap.FromResource(hinstance, bitmapName))
+ {
+ return new FreeImageBitmap(bitmap);
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified file.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file
+ /// from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromFile(string filename)
+ {
+ return new FreeImageBitmap(filename);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified file
+ /// using embedded color management information in that file.
+ /// </summary>
+ /// <param name="filename">A string that contains the
+ /// name of the file from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromFile(string filename, bool useEmbeddedColorManagement)
+ {
+ return new FreeImageBitmap(filename);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a handle to a GDI bitmap.
+ /// </summary>
+ /// <param name="hbitmap">The GDI bitmap handle from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromHbitmap(IntPtr hbitmap)
+ {
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.CreateFromHbitmap(hbitmap, IntPtr.Zero);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a handle to a GDI bitmap and a handle to a GDI palette.
+ /// </summary>
+ /// <param name="hbitmap">The GDI bitmap handle from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="hpalette">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
+ {
+ return FromHbitmap(hbitmap);
+ }
+
+ /// <summary>
+ /// Frees a bitmap handle.
+ /// </summary>
+ /// <param name="hbitmap">Handle to a bitmap.</param>
+ /// <returns><b>true</b> on success, <b>false</b> on failure.</returns>
+ public static bool FreeHbitmap(IntPtr hbitmap)
+ {
+ return FreeImage.FreeHbitmap(hbitmap);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <param name="validateImageData">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Returns the color depth, in number of bits per pixel,
+ /// of the specified pixel format.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> member that specifies
+ /// the format for which to find the size.</param>
+ /// <returns>The color depth of the specified pixel format.</returns>
+ public static int GetPixelFormatSize(PixelFormat pixfmt)
+ {
+ return Bitmap.GetPixelFormatSize(pixfmt);
+ }
+
+ /// <summary>
+ /// Performs a lossless rotation or flipping on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source file.</param>
+ /// <param name="destination">Destination file; can be the source file; will be overwritten.</param>
+ /// <param name="operation">The operation to apply.</param>
+ /// <param name="perfect">To avoid lossy transformation, you can set the perfect parameter to true.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool JPEGTransform(string source, string destination, FREE_IMAGE_JPEG_OPERATION operation, bool perfect)
+ {
+ return FreeImage.JPEGTransform(source, destination, operation, perfect);
+ }
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source filename.</param>
+ /// <param name="destination">Destination filename.</param>
+ /// <param name="rect">Specifies the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="source"/> or <paramref name="destination"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="source"/> does not exist.
+ /// </exception>
+ public static bool JPEGCrop(string source, string destination, Rectangle rect)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (!File.Exists(source))
+ {
+ throw new FileNotFoundException("source");
+ }
+ if (destination == null)
+ {
+ throw new ArgumentNullException("destination");
+ }
+ return JPEGCrop(source, destination, rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source filename.</param>
+ /// <param name="destination">Destination filename.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="source"/> or <paramref name="destination"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="source"/> does not exist.
+ /// </exception>
+ public static bool JPEGCrop(string source, string destination, int left, int top, int right, int bottom)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (!File.Exists(source))
+ {
+ throw new FileNotFoundException("source");
+ }
+ if (destination == null)
+ {
+ throw new ArgumentNullException("destination");
+ }
+ return FreeImage.JPEGCrop(source, destination, left, top, right, bottom);
+ }
+
+ /// <summary>
+ /// Converts a X11 color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="color">Name of the color to convert.</param>
+ /// <param name="red">Red component.</param>
+ /// <param name="green">Green component.</param>
+ /// <param name="blue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="color"/> is null.</exception>
+ public static bool LookupX11Color(string color, out byte red, out byte green, out byte blue)
+ {
+ if (color == null)
+ {
+ throw new ArgumentNullException("color");
+ }
+ return FreeImage.LookupX11Color(color, out red, out green, out blue);
+ }
+
+ /// <summary>
+ /// Converts a SVG color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="color">Name of the color to convert.</param>
+ /// <param name="red">Red component.</param>
+ /// <param name="green">Green component.</param>
+ /// <param name="blue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="color"/> is null.</exception>
+ public static bool LookupSVGColor(string color, out byte red, out byte green, out byte blue)
+ {
+ if (color == null)
+ {
+ throw new ArgumentNullException("color");
+ }
+ return FreeImage.LookupSVGColor(color, out red, out green, out blue);
+ }
+
+ /// <summary>
+ /// Creates a lookup table to be used with AdjustCurve() which
+ /// may adjusts brightness and contrast, correct gamma and invert the image with a
+ /// single call to AdjustCurve().
+ /// </summary>
+ /// <param name="lookUpTable">Output lookup table to be used with AdjustCurve().
+ /// The size of <paramref name="lookUpTable"/> is assumed to be 256.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para></param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>The number of adjustments applied to the resulting lookup table
+ /// compared to a blind lookup table.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="lookUpTable"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="lookUpTable.Length"/> is not 256.</exception>
+ public static int GetAdjustColorsLookupTable(byte[] lookUpTable, double brightness, double contrast, double gamma, bool invert)
+ {
+ if (lookUpTable == null)
+ {
+ throw new ArgumentNullException("lookUpTable");
+ }
+ if (lookUpTable.Length != 256)
+ {
+ throw new ArgumentException("lookUpTable");
+ }
+ return FreeImage.GetAdjustColorsLookupTable(lookUpTable, brightness, contrast, gamma, invert);
+ }
+
+ /// <summary>
+ /// Adds a specified frame to the file specified using the specified parameters.
+ /// Use this method to save selected frames from an to a multiple-frame image.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> or <paramref name="bitmap"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public static void SaveAdd(
+ string filename,
+ FreeImageBitmap bitmap,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ bitmap.EnsureNotDisposed();
+
+ FIBITMAP dib = bitmap.dib;
+ if (dib.IsNull)
+ throw new ArgumentNullException("bitmap");
+
+ FIMULTIBITMAP mpBitmap =
+ FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true);
+
+ if (mpBitmap.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ FreeImage.AppendPage(mpBitmap, bitmap.dib);
+
+ if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags))
+ throw new Exception(ErrorUnloadBitmap);
+ }
+
+ /// <summary>
+ /// Adds a specified frame to the file specified using the specified parameters.
+ /// Use this method to save selected frames from an image to a multiple-frame image.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="insertPosition">The position of the inserted frame.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> or <paramref name="bitmap"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public static void SaveAdd(
+ string filename,
+ FreeImageBitmap bitmap,
+ int insertPosition,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ if (insertPosition < 0)
+ {
+ throw new ArgumentOutOfRangeException("insertPosition");
+ }
+ bitmap.EnsureNotDisposed();
+
+ FIBITMAP dib = bitmap.dib;
+ if (dib.IsNull)
+ throw new ArgumentNullException("bitmap");
+
+ FIMULTIBITMAP mpBitmap =
+ FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true);
+
+ if (mpBitmap.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ int pageCount = FreeImage.GetPageCount(mpBitmap);
+
+ if (insertPosition > pageCount)
+ throw new ArgumentOutOfRangeException("insertPosition");
+
+ if (insertPosition == pageCount)
+ FreeImage.AppendPage(mpBitmap, bitmap.dib);
+ else
+ FreeImage.InsertPage(mpBitmap, insertPosition, bitmap.dib);
+
+ if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags))
+ throw new Exception(ErrorUnloadBitmap);
+ }
+
+ /// <summary>
+ /// Returns a new instance of the <see cref="PropertyItem"/> class which
+ /// has no public accessible constructor.
+ /// </summary>
+ /// <returns>A new instace of <see cref="PropertyItem"/>.</returns>
+ public static PropertyItem CreateNewPropertyItem()
+ {
+ return FreeImage.CreatePropertyItem();
+ }
+
+ #endregion
+
+ #region Helper functions
+
+ /// <summary>
+ /// Throws an exception in case the instance has already been disposed.
+ /// </summary>
+ private void EnsureNotDisposed()
+ {
+ lock (lockObject)
+ {
+ if (!this.disposed)
+ {
+ return;
+ }
+ }
+ throw new ObjectDisposedException(ToString());
+ }
+
+ /// <summary>
+ /// Tries to replace the wrapped <see cref="FIBITMAP"/> with a new one.
+ /// In case the new dib is null or the same as the already
+ /// wrapped one, nothing will be changed and the result will
+ /// be false.
+ /// Otherwise the wrapped <see cref="FIBITMAP"/> will be unloaded and replaced.
+ /// </summary>
+ /// <param name="newDib">The new dib.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ private bool ReplaceDib(FIBITMAP newDib)
+ {
+ bool result = false;
+ if ((dib != newDib) && (!newDib.IsNull))
+ {
+ UnloadDib();
+ dib = newDib;
+ AddMemoryPressure();
+ result = true;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Unloads currently wrapped <see cref="FIBITMAP"/> or unlocks the locked page
+ /// in case it came from a multipaged bitmap.
+ /// </summary>
+ private void UnloadDib()
+ {
+ if (!dib.IsNull)
+ {
+ long size = FreeImage.GetDIBSize(dib);
+ FreeImage.UnloadEx(ref dib);
+ if (size > 0L)
+ GC.RemoveMemoryPressure(size);
+ }
+ }
+
+ /// <summary>
+ /// Informs the runtime about unmanaged allocoted memory.
+ /// </summary>
+ private void AddMemoryPressure()
+ {
+ long dataSize;
+ if ((dataSize = DataSize) > 0L)
+ GC.AddMemoryPressure(dataSize);
+ }
+
+ /// <summary>
+ /// Opens the stream and reads the number of available pages.
+ /// Then loads the first page to this instance.
+ /// </summary>
+ private void LoadFromStream(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, flags);
+ if (mdib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ try
+ {
+ frameCount = FreeImage.GetPageCount(mdib);
+ }
+ finally
+ {
+ if (!FreeImage.CloseMultiBitmapEx(ref mdib))
+ {
+ throw new Exception(ErrorUnloadBitmap);
+ }
+ }
+
+ dib = FreeImage.LoadFromStream(stream, flags, ref format);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+
+ saveInformation.loadFlags = flags;
+ originalFormat = format;
+ AddMemoryPressure();
+ }
+
+ #endregion
+
+ #region Interfaces
+
+ /// <summary>
+ /// Helper class to store informations for <see cref="FreeImageBitmap.SaveAdd()"/>.
+ /// </summary>
+ private sealed class SaveInformation : ICloneable
+ {
+ public string filename;
+ public FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ public FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT;
+ public FREE_IMAGE_SAVE_FLAGS saveFlags = FREE_IMAGE_SAVE_FLAGS.DEFAULT;
+
+ public object Clone()
+ {
+ return base.MemberwiseClone();
+ }
+ }
+
+ /// <summary>
+ /// Creates a deep copy of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>A deep copy of this <see cref="FreeImageBitmap"/>.</returns>
+ public object Clone()
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Clone(dib);
+ if (!dib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ result.saveInformation = (SaveInformation)saveInformation.Clone();
+ result.tag = tag;
+ result.originalFormat = originalFormat;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
+ /// releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
+ /// releasing, or resetting unmanaged resources.
+ /// </summary>
+ /// <param name="disposing">If true managed ressources are released.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ // Only clean up once
+ lock (lockObject)
+ {
+ if (disposed)
+ {
+ return;
+ }
+ disposed = true;
+ }
+
+ // Clean up managed resources
+ if (disposing)
+ {
+ if (stream != null)
+ {
+ if (disposeStream)
+ {
+ stream.Dispose();
+ }
+ stream = null;
+ }
+ }
+
+ tag = null;
+ saveInformation = null;
+
+ // Clean up unmanaged resources
+ UnloadDib();
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual scanlines in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the <see cref="FreeImageBitmap"/>.</returns>
+ /// <exception cref="ArgumentException">The bitmaps's type is not supported.</exception>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetScanlines().GetEnumerator();
+ }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ EnsureNotDisposed();
+ using (MemoryStream memory = new MemoryStream(DataSize))
+ {
+ if (!FreeImage.SaveToStream(dib, memory, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_LZW))
+ {
+ throw new SerializationException();
+ }
+ memory.Capacity = (int)memory.Length;
+ info.AddValue("Bitmap Data", memory.GetBuffer());
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageEngine.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageEngine.cs
new file mode 100644
index 0000000..584f87b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageEngine.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Class handling non-bitmap related functions.
+ /// </summary>
+ public static class FreeImageEngine
+ {
+ #region Callback
+
+ // Callback delegate
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly OutputMessageFunction outputMessageFunction;
+
+ static FreeImageEngine()
+ {
+ // Check if FreeImage.dll is present and cancel setting the callbackfuntion if not
+ if (!IsAvailable)
+ {
+ return;
+ }
+ // Create a delegate (function pointer) to 'OnMessage'
+ outputMessageFunction = new OutputMessageFunction(OnMessage);
+ // Set the callback
+ FreeImage.SetOutputMessage(outputMessageFunction);
+ }
+
+ /// <summary>
+ /// Internal callback
+ /// </summary>
+ private static void OnMessage(FREE_IMAGE_FORMAT fif, string message)
+ {
+ // Get a local copy of the multicast-delegate
+ OutputMessageFunction m = Message;
+
+ // Check the local copy instead of the static instance
+ // to prevent a second thread from setting the delegate
+ // to null, which would cause a nullreference exception
+ if (m != null)
+ {
+ // Invoke the multicast-delegate
+ m.Invoke(fif, message);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the FreeImage DLL is available or not.
+ /// </summary>
+ public static bool IsAvailable
+ {
+ get
+ {
+ return FreeImage.IsAvailable();
+ }
+ }
+
+ /// <summary>
+ /// Internal errors in FreeImage generate a logstring that can be
+ /// captured by this event.
+ /// </summary>
+ public static event OutputMessageFunction Message;
+
+ #endregion
+
+ /// <summary>
+ /// Gets a string containing the current version of the library.
+ /// </summary>
+ public static string Version
+ {
+ get
+ {
+ return FreeImage.GetVersion();
+ }
+ }
+
+ /// <summary>
+ /// Gets a string containing a standard copyright message.
+ /// </summary>
+ public static string CopyrightMessage
+ {
+ get
+ {
+ return FreeImage.GetCopyrightMessage();
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the platform is using Little Endian.
+ /// </summary>
+ public static bool IsLittleEndian
+ {
+ get
+ {
+ return FreeImage.IsLittleEndian();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImagePlugin.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImagePlugin.cs
new file mode 100644
index 0000000..3f02f60
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImagePlugin.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing a FreeImage format.
+ /// </summary>
+ public sealed class FreeImagePlugin
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly FREE_IMAGE_FORMAT fif;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="fif">The FreeImage format to wrap.</param>
+ internal FreeImagePlugin(FREE_IMAGE_FORMAT fif)
+ {
+ this.fif = fif;
+ }
+
+ /// <summary>
+ /// Gets the format of this instance.
+ /// </summary>
+ public FREE_IMAGE_FORMAT FIFormat
+ {
+ get
+ {
+ return fif;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether this plugin is enabled.
+ /// </summary>
+ public bool Enabled
+ {
+ get
+ {
+ return (FreeImage.IsPluginEnabled(fif) == 1);
+ }
+ set
+ {
+ FreeImage.SetPluginEnabled(fif, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets a string describing the format.
+ /// </summary>
+ public string Format
+ {
+ get
+ {
+ return FreeImage.GetFormatFromFIF(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets a comma-delimited file extension list describing the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ public string ExtentsionList
+ {
+ get
+ {
+ return FreeImage.GetFIFExtensionList(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets a descriptive string that describes the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ public string Description
+ {
+ get
+ {
+ return FreeImage.GetFIFDescription(fif);
+ }
+ }
+
+ /// <summary>
+ /// Returns a regular expression string that can be used by
+ /// a regular expression engine to identify the bitmap.
+ /// FreeImageQt makes use of this function.
+ /// </summary>
+ public string RegExpr
+ {
+ get
+ {
+ return FreeImage.GetFIFRegExpr(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can load bitmaps.
+ /// </summary>
+ public bool SupportsReading
+ {
+ get
+ {
+ return FreeImage.FIFSupportsReading(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can save bitmaps.
+ /// </summary>
+ public bool SupportsWriting
+ {
+ get
+ {
+ return FreeImage.FIFSupportsWriting(fif);
+ }
+ }
+
+ /// <summary>
+ /// Checks whether this plugin can save a bitmap in the desired data type.
+ /// </summary>
+ /// <param name="type">The desired image type.</param>
+ /// <returns>True if this plugin can save bitmaps as the desired type, else false.</returns>
+ public bool SupportsExportType(FREE_IMAGE_TYPE type)
+ {
+ return FreeImage.FIFSupportsExportType(fif, type);
+ }
+
+ /// <summary>
+ /// Checks whether this plugin can save bitmaps in the desired bit depth.
+ /// </summary>
+ /// <param name="bpp">The desired bit depth.</param>
+ /// <returns>True if this plugin can save bitmaps in the desired bit depth, else false.</returns>
+ public bool SupportsExportBPP(int bpp)
+ {
+ return FreeImage.FIFSupportsExportBPP(fif, bpp);
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can load or save an ICC profile.
+ /// </summary>
+ public bool SupportsICCProfiles
+ {
+ get
+ {
+ return FreeImage.FIFSupportsICCProfiles(fif);
+ }
+ }
+
+ /// <summary>
+ /// Checks whether an extension is valid for this format.
+ /// </summary>
+ /// <param name="extension">The desired extension.</param>
+ /// <returns>True if the extension is valid for this format, false otherwise.</returns>
+ public bool ValidExtension(string extension)
+ {
+ return FreeImage.IsExtensionValidForFIF(fif, extension);
+ }
+
+ /// <summary>
+ /// Checks whether an extension is valid for this format.
+ /// </summary>
+ /// <param name="extension">The desired extension.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the extension is valid for this format, false otherwise.</returns>
+ public bool ValidExtension(string extension, StringComparison comparisonType)
+ {
+ return FreeImage.IsExtensionValidForFIF(fif, extension, comparisonType);
+ }
+
+ /// <summary>
+ /// Checks whether a filename is valid for this format.
+ /// </summary>
+ /// <param name="filename">The desired filename.</param>
+ /// <returns>True if the filename is valid for this format, false otherwise.</returns>
+ public bool ValidFilename(string filename)
+ {
+ return FreeImage.IsFilenameValidForFIF(fif, filename);
+ }
+
+ /// <summary>
+ /// Checks whether a filename is valid for this format.
+ /// </summary>
+ /// <param name="filename">The desired filename.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the filename is valid for this format, false otherwise.</returns>
+ public bool ValidFilename(string filename, StringComparison comparisonType)
+ {
+ return FreeImage.IsFilenameValidForFIF(fif, filename, comparisonType);
+ }
+
+ /// <summary>
+ /// Gets a descriptive string that describes the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ /// <returns>A descriptive string that describes the bitmap formats.</returns>
+ public override string ToString()
+ {
+ return Description;
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageStreamIO.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageStreamIO.cs
new file mode 100644
index 0000000..2ef0087
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/FreeImageStreamIO.cs
@@ -0,0 +1,167 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/09/15 11:47:46 $
+// $Id: FreeImageStreamIO.cs,v 1.5 2009/09/15 11:47:46 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Internal class wrapping stream io functions.
+ /// </summary>
+ /// <remarks>
+ /// FreeImage can read files from a disk or a network drive but also allows the user to
+ /// implement their own loading or saving functions to load them directly from an ftp or web
+ /// server for example.
+ /// <para/>
+ /// In .NET streams are a common way to handle data. The <b>FreeImageStreamIO</b> class handles
+ /// the loading and saving from and to streams. It implements the funtions FreeImage needs
+ /// to load data from an an arbitrary source.
+ /// <para/>
+ /// The class is for internal use only.
+ /// </remarks>
+ internal static class FreeImageStreamIO
+ {
+ /// <summary>
+ /// <see cref="FreeImageAPI.IO.FreeImageIO"/> structure that can be used to read from streams via
+ /// <see cref="FreeImageAPI.FreeImage.LoadFromHandle(FREE_IMAGE_FORMAT, ref FreeImageIO, fi_handle, FREE_IMAGE_LOAD_FLAGS)"/>.
+ /// </summary>
+ public static readonly FreeImageIO io;
+
+ /// <summary>
+ /// Initializes a new instances which can be used to
+ /// create a FreeImage compatible <see cref="FreeImageAPI.IO.FreeImageIO"/> structure.
+ /// </summary>
+ static FreeImageStreamIO()
+ {
+ io.readProc = new ReadProc(streamRead);
+ io.writeProc = new WriteProc(streamWrite);
+ io.seekProc = new SeekProc(streamSeek);
+ io.tellProc = new TellProc(streamTell);
+ }
+
+ /// <summary>
+ /// Reads the requested data from the stream and writes it to the given address.
+ /// </summary>
+ static unsafe uint streamRead(IntPtr buffer, uint size, uint count, fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if ((stream == null) || (!stream.CanRead))
+ {
+ return 0;
+ }
+ uint readCount = 0;
+ byte* ptr = (byte*)buffer;
+ byte[] bufferTemp = new byte[size];
+ int read;
+ while (readCount < count)
+ {
+ read = stream.Read(bufferTemp, 0, (int)size);
+ if (read != (int)size)
+ {
+ stream.Seek(-read, SeekOrigin.Current);
+ break;
+ }
+ for (int i = 0; i < read; i++, ptr++)
+ {
+ *ptr = bufferTemp[i];
+ }
+ readCount++;
+ }
+ return (uint)readCount;
+ }
+
+ /// <summary>
+ /// Reads the given data and writes it into the stream.
+ /// </summary>
+ static unsafe uint streamWrite(IntPtr buffer, uint size, uint count, fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if ((stream == null) || (!stream.CanWrite))
+ {
+ return 0;
+ }
+ uint writeCount = 0;
+ byte[] bufferTemp = new byte[size];
+ byte* ptr = (byte*)buffer;
+ while (writeCount < count)
+ {
+ for (int i = 0; i < size; i++, ptr++)
+ {
+ bufferTemp[i] = *ptr;
+ }
+ try
+ {
+ stream.Write(bufferTemp, 0, bufferTemp.Length);
+ }
+ catch
+ {
+ return writeCount;
+ }
+ writeCount++;
+ }
+ return writeCount;
+ }
+
+ /// <summary>
+ /// Moves the streams position.
+ /// </summary>
+ static int streamSeek(fi_handle handle, int offset, SeekOrigin origin)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if (stream == null)
+ {
+ return 1;
+ }
+ stream.Seek((long)offset, origin);
+ return 0;
+ }
+
+ /// <summary>
+ /// Returns the streams current position
+ /// </summary>
+ static int streamTell(fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if (stream == null)
+ {
+ return -1;
+ }
+ return (int)stream.Position;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/GifInformation.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/GifInformation.cs
new file mode 100644
index 0000000..a2deb13
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/GifInformation.cs
@@ -0,0 +1,131 @@
+using System;
+using System.Diagnostics;
+using System.Drawing;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Provides additional information specific for GIF files. This class cannot be inherited.
+ /// </summary>
+ public class GifInformation : MDM_ANIMATION
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GifInformation"/> class
+ /// with the specified <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="bitmap">A reference to a <see cref="FreeImageBitmap"/> instance.</param>
+ public GifInformation(FreeImageBitmap bitmap)
+ : base(bitmap.Dib)
+ {
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this frame uses the
+ /// GIF image's global palette. If set to <b>false</b>, this
+ /// frame uses its local palette.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? UseGlobalPalette
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("NoLocalPalette");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("NoLocalPalette", val);
+ }
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image, intialized with all entries of the
+ /// current local palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The image does not have a palette.
+ /// </exception>
+ public void CreateGlobalPalette()
+ {
+ CreateGlobalPalette(new Palette(dib));
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image with the specified size, intialized
+ /// with the first <paramref name="size"/> entries of the current local palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="size">The size of the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(int size)
+ {
+ CreateGlobalPalette(new Palette(dib), size);
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image, intialized with the entries
+ /// of the specified palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="palette">The palette that contains the initial values for
+ /// the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(Palette palette)
+ {
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+
+ GlobalPalette = palette;
+ UseGlobalPalette = true;
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image with the specified size, intialized
+ /// with the first <paramref name="size"/> entries of the specified palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="palette">The palette that contains the initial values for
+ /// the newly created global palette.</param>
+ /// <param name="size">The size of the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(Palette palette, int size)
+ {
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+ if (size <= 0)
+ {
+ throw new ArgumentOutOfRangeException("size");
+ }
+
+ Palette pal = new Palette(size);
+ pal.CopyFrom(palette);
+ GlobalPalette = palette;
+ UseGlobalPalette = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/ImageMetadata.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/ImageMetadata.cs
new file mode 100644
index 0000000..e49f7e4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/ImageMetadata.cs
@@ -0,0 +1,286 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.7 $
+// $Date: 2009/02/27 16:34:59 $
+// $Id: ImageMetadata.cs,v 1.7 2009/02/27 16:34:59 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Class handling metadata of a FreeImage bitmap.
+ /// </summary>
+ public class ImageMetadata : IEnumerable, IComparable, IComparable<ImageMetadata>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly List<MetadataModel> data;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly FIBITMAP dib;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool hideEmptyModels;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="FIBITMAP"/>,
+ /// showing all known models.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public ImageMetadata(FIBITMAP dib) : this(dib, false) { }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="FIBITMAP"/>,
+ /// showing or hiding empry models.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hideEmptyModels">When <b>true</b>, empty metadata models
+ /// will be hidden until a tag to this model is added.</param>
+ public ImageMetadata(FIBITMAP dib, bool hideEmptyModels)
+ {
+ if (dib.IsNull) throw new ArgumentNullException("dib");
+ data = new List<MetadataModel>(FreeImage.FREE_IMAGE_MDMODELS.Length);
+ this.dib = dib;
+ this.hideEmptyModels = hideEmptyModels;
+
+ data.Add(new MDM_ANIMATION(dib));
+ data.Add(new MDM_COMMENTS(dib));
+ data.Add(new MDM_CUSTOM(dib));
+ data.Add(new MDM_EXIF_EXIF(dib));
+ data.Add(new MDM_EXIF_GPS(dib));
+ data.Add(new MDM_INTEROP(dib));
+ data.Add(new MDM_EXIF_MAIN(dib));
+ data.Add(new MDM_MAKERNOTE(dib));
+ data.Add(new MDM_GEOTIFF(dib));
+ data.Add(new MDM_IPTC(dib));
+ data.Add(new MDM_NODATA(dib));
+ data.Add(new MDM_XMP(dib));
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="MetadataModel"/> of the specified type.
+ /// <para>In case the getter returns <c>null</c> the model is not contained
+ /// by the list.</para>
+ /// <para><c>null</c> can be used calling the setter to destroy the model.</para>
+ /// </summary>
+ /// <param name="model">Type of the model.</param>
+ /// <returns>The <see cref="FreeImageAPI.Metadata.MetadataModel"/> object of the specified type.</returns>
+ public MetadataModel this[FREE_IMAGE_MDMODEL model]
+ {
+ get
+ {
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Model == model)
+ {
+ if (!data[i].Exists && hideEmptyModels)
+ {
+ return null;
+ }
+ return data[i];
+ }
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="FreeImageAPI.Metadata.MetadataModel"/> at the specified index.
+ /// <para>In case the getter returns <c>null</c> the model is not contained
+ /// by the list.</para>
+ /// <para><c>null</c> can be used calling the setter to destroy the model.</para>
+ /// </summary>
+ /// <param name="index">Index of the <see cref="FreeImageAPI.Metadata.MetadataModel"/> within
+ /// this instance.</param>
+ /// <returns>The <see cref="FreeImageAPI.Metadata.MetadataModel"/>
+ /// object at the specified index.</returns>
+ public MetadataModel this[int index]
+ {
+ get
+ {
+ if (index < 0 || index >= data.Count)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ return (hideEmptyModels && !data[index].Exists) ? null : data[index];
+ }
+ }
+
+ /// <summary>
+ /// Returns a list of all visible
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>.
+ /// </summary>
+ public List<MetadataModel> List
+ {
+ get
+ {
+ if (hideEmptyModels)
+ {
+ List<MetadataModel> result = new List<MetadataModel>();
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ result.Add(data[i]);
+ }
+ }
+ return result;
+ }
+ else
+ {
+ return data;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds new tag to the bitmap or updates its value in case it already exists.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="tag">The tag to add or update.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="tag"/> is null.</exception>
+ public bool AddTag(MetadataTag tag)
+ {
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (tag.Model == data[i].Model)
+ {
+ return data[i].AddTag(tag);
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the number of visible
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ if (hideEmptyModels)
+ {
+ int count = 0;
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+ else
+ {
+ return data.Count;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether empty
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see> are hidden.
+ /// </summary>
+ public bool HideEmptyModels
+ {
+ get
+ {
+ return hideEmptyModels;
+ }
+ set
+ {
+ hideEmptyModels = value;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>
+ /// in this <see cref="ImageMetadata"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for this <see cref="ImageMetadata"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ if (hideEmptyModels)
+ {
+ List<MetadataModel> tempList = new List<MetadataModel>(data.Count);
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ tempList.Add(data[i]);
+ }
+ }
+ return tempList.GetEnumerator();
+ }
+ else
+ {
+ return data.GetEnumerator();
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="ImageMetadata"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is ImageMetadata))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((ImageMetadata)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="ImageMetadata"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="ImageMetadata"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(ImageMetadata other)
+ {
+ return this.dib.CompareTo(other.dib);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/LocalPlugin.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/LocalPlugin.cs
new file mode 100644
index 0000000..a8d9278
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/LocalPlugin.cs
@@ -0,0 +1,466 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.9 $
+// $Date: 2009/09/15 11:47:46 $
+// $Id: LocalPlugin.cs,v 1.9 2009/09/15 11:47:46 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using FreeImageAPI.IO;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing own FreeImage-Plugins.
+ /// </summary>
+ /// <remarks>
+ /// FreeImages itself is plugin based. Each supported format is integrated by a seperat plugin,
+ /// that handles loading, saving, descriptions, identifing ect.
+ /// And of course the user can create own plugins and use them in FreeImage.
+ /// To do that the above mentioned predefined methodes need to be implemented.
+ /// <para/>
+ /// The class below handles the creation of such a plugin. The class itself is abstract
+ /// as well as some core functions that need to be implemented.
+ /// The class can be used to enable or disable the plugin in FreeImage after regististration or
+ /// retrieve the formatid, assigned by FreeImage.
+ /// The class handles the callback functions, garbage collector and pointer operation to make
+ /// the implementation as user friendly as possible.
+ /// <para/>
+ /// How to:
+ /// There are two functions that need to be implemented:
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> and
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.FormatProc"/>.
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> is used by the constructor
+ /// of the abstract class. FreeImage wants a list of the implemented functions. Each function is
+ /// represented by a function pointer (a .NET <see cref="System.Delegate"/>). In case a function
+ /// is not implemented FreeImage receives an empty <b>delegate</b>). To tell the constructor
+ /// which functions have been implemented the information is represented by a disjunction of
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.MethodFlags"/>.
+ /// <para/>
+ /// For example:
+ /// return MethodFlags.LoadProc | MethodFlags.SaveProc;
+ /// <para/>
+ /// The above statement means that LoadProc and SaveProc have been implemented by the user.
+ /// Keep in mind, that each function has a standard implementation that has static return
+ /// values that may cause errors if listed in
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> without a real implementation.
+ /// <para/>
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.FormatProc"/> is used by some checks of FreeImage and
+ /// must be implemented. <see cref="FreeImageAPI.Plugins.LocalPlugin.LoadProc"/> for example can be
+ /// implemented if the plugin supports reading, but it doesn't have to, the plugin could only
+ /// be used to save an already loaded bitmap in a special format.
+ /// </remarks>
+ public abstract class LocalPlugin
+ {
+ /// <summary>
+ /// Struct containing function pointers.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Plugin plugin;
+
+ /// <summary>
+ /// Delegate for register callback by FreeImage.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private InitProc initProc;
+
+ /// <summary>
+ /// The format id assiged to the plugin.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+
+ /// <summary>
+ /// When true the plugin was registered successfully else false.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool registered = false;
+
+ /// <summary>
+ /// A copy of the functions used to register.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly MethodFlags implementedMethods;
+
+ /// <summary>
+ /// MethodFlags defines values to fill a bitfield telling which
+ /// functions have been implemented by a plugin.
+ /// </summary>
+ [Flags]
+ protected enum MethodFlags
+ {
+ /// <summary>
+ /// No mothods implemented.
+ /// </summary>
+ None = 0x0,
+
+ /// <summary>
+ /// DescriptionProc has been implemented.
+ /// </summary>
+ DescriptionProc = 0x1,
+
+ /// <summary>
+ /// ExtensionListProc has been implemented.
+ /// </summary>
+ ExtensionListProc = 0x2,
+
+ /// <summary>
+ /// RegExprProc has been implemented.
+ /// </summary>
+ RegExprProc = 0x4,
+
+ /// <summary>
+ /// OpenProc has been implemented.
+ /// </summary>
+ OpenProc = 0x8,
+
+ /// <summary>
+ /// CloseProc has been implemented.
+ /// </summary>
+ CloseProc = 0x10,
+
+ /// <summary>
+ /// PageCountProc has been implemented.
+ /// </summary>
+ PageCountProc = 0x20,
+
+ /// <summary>
+ /// PageCapabilityProc has been implemented.
+ /// </summary>
+ PageCapabilityProc = 0x40,
+
+ /// <summary>
+ /// LoadProc has been implemented.
+ /// </summary>
+ LoadProc = 0x80,
+
+ /// <summary>
+ /// SaveProc has been implemented.
+ /// </summary>
+ SaveProc = 0x100,
+
+ /// <summary>
+ /// ValidateProc has been implemented.
+ /// </summary>
+ ValidateProc = 0x200,
+
+ /// <summary>
+ /// MimeProc has been implemented.
+ /// </summary>
+ MimeProc = 0x400,
+
+ /// <summary>
+ /// SupportsExportBPPProc has been implemented.
+ /// </summary>
+ SupportsExportBPPProc = 0x800,
+
+ /// <summary>
+ /// SupportsExportTypeProc has been implemented.
+ /// </summary>
+ SupportsExportTypeProc = 0x1000,
+
+ /// <summary>
+ /// SupportsICCProfilesProc has been implemented.
+ /// </summary>
+ SupportsICCProfilesProc = 0x2000
+ }
+
+ // Functions that must be implemented.
+
+ /// <summary>
+ /// Function that returns a bitfield containing the
+ /// implemented methods.
+ /// </summary>
+ /// <returns>Bitfield of the implemented methods.</returns>
+ protected abstract MethodFlags GetImplementedMethods();
+
+ /// <summary>
+ /// Implementation of <b>FormatProc</b>
+ /// </summary>
+ /// <returns>A string containing the plugins format.</returns>
+ protected abstract string FormatProc();
+
+ // Functions that can be implemented.
+
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string DescriptionProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string ExtensionListProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string RegExprProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual IntPtr OpenProc(ref FreeImageIO io, fi_handle handle, bool read) { return IntPtr.Zero; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual void CloseProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual int PageCountProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { return 0; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual int PageCapabilityProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { return 0; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual FIBITMAP LoadProc(ref FreeImageIO io, fi_handle handle, int page, int flags, IntPtr data) { return FIBITMAP.Zero; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool ValidateProc(ref FreeImageIO io, fi_handle handle) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string MimeProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsExportBPPProc(int bpp) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsExportTypeProc(FREE_IMAGE_TYPE type) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsICCProfilesProc() { return false; }
+
+ /// <summary>
+ /// The constructor automatically registeres the plugin in FreeImage.
+ /// To do this it prepares a FreeImage defined structure with function pointers
+ /// to the implemented functions or null if not implemented.
+ /// Before registing the functions they are pinned in memory so the garbage collector
+ /// can't move them around in memory after we passed there addresses to FreeImage.
+ /// </summary>
+ public LocalPlugin()
+ {
+ implementedMethods = GetImplementedMethods();
+
+ if ((implementedMethods & MethodFlags.DescriptionProc) != 0)
+ {
+ plugin.descriptionProc = new DescriptionProc(DescriptionProc);
+ }
+ if ((implementedMethods & MethodFlags.ExtensionListProc) != 0)
+ {
+ plugin.extensionListProc = new ExtensionListProc(ExtensionListProc);
+ }
+ if ((implementedMethods & MethodFlags.RegExprProc) != 0)
+ {
+ plugin.regExprProc = new RegExprProc(RegExprProc);
+ }
+ if ((implementedMethods & MethodFlags.OpenProc) != 0)
+ {
+ plugin.openProc = new OpenProc(OpenProc);
+ }
+ if ((implementedMethods & MethodFlags.CloseProc) != 0)
+ {
+ plugin.closeProc = new CloseProc(CloseProc);
+ }
+ if ((implementedMethods & MethodFlags.PageCountProc) != 0)
+ {
+ plugin.pageCountProc = new PageCountProc(PageCountProc);
+ }
+ if ((implementedMethods & MethodFlags.PageCapabilityProc) != 0)
+ {
+ plugin.pageCapabilityProc = new PageCapabilityProc(PageCapabilityProc);
+ }
+ if ((implementedMethods & MethodFlags.LoadProc) != 0)
+ {
+ plugin.loadProc = new LoadProc(LoadProc);
+ }
+ if ((implementedMethods & MethodFlags.SaveProc) != 0)
+ {
+ plugin.saveProc = new SaveProc(SaveProc);
+ }
+ if ((implementedMethods & MethodFlags.ValidateProc) != 0)
+ {
+ plugin.validateProc = new ValidateProc(ValidateProc);
+ }
+ if ((implementedMethods & MethodFlags.MimeProc) != 0)
+ {
+ plugin.mimeProc = new MimeProc(MimeProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsExportBPPProc) != 0)
+ {
+ plugin.supportsExportBPPProc = new SupportsExportBPPProc(SupportsExportBPPProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsExportTypeProc) != 0)
+ {
+ plugin.supportsExportTypeProc = new SupportsExportTypeProc(SupportsExportTypeProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsICCProfilesProc) != 0)
+ {
+ plugin.supportsICCProfilesProc = new SupportsICCProfilesProc(SupportsICCProfilesProc);
+ }
+
+ // FormatProc is always implemented
+ plugin.formatProc = new FormatProc(FormatProc);
+
+ // InitProc is the register call back.
+ initProc = new InitProc(RegisterProc);
+
+ // Register the plugin. The result will be saved and can be accessed later.
+ registered = FreeImage.RegisterLocalPlugin(initProc, null, null, null, null) != FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ if (registered)
+ {
+ PluginRepository.RegisterLocalPlugin(this);
+ }
+ }
+
+ private void RegisterProc(ref Plugin plugin, int format_id)
+ {
+ // Copy the function pointers
+ plugin = this.plugin;
+ // Retrieve the format if assigned to this plugin by FreeImage.
+ format = (FREE_IMAGE_FORMAT)format_id;
+ }
+
+ /// <summary>
+ /// Gets or sets if the plugin is enabled.
+ /// </summary>
+ public bool Enabled
+ {
+ get
+ {
+ if (registered)
+ {
+ return (FreeImage.IsPluginEnabled(format) > 0);
+ }
+ else
+ {
+ throw new ObjectDisposedException("plugin not registered");
+ }
+ }
+ set
+ {
+ if (registered)
+ {
+ FreeImage.SetPluginEnabled(format, value);
+ }
+ else
+ {
+ throw new ObjectDisposedException("plugin not registered");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets if the plugin was registered successfully.
+ /// </summary>
+ public bool Registered
+ {
+ get { return registered; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="FREE_IMAGE_FORMAT"/> FreeImage assigned to this plugin.
+ /// </summary>
+ public FREE_IMAGE_FORMAT Format
+ {
+ get
+ {
+ return format;
+ }
+ }
+
+ /// <summary>
+ /// Reads from an unmanaged stream.
+ /// </summary>
+ protected unsafe int Read(FreeImageIO io, fi_handle handle, uint size, uint count, ref byte[] buffer)
+ {
+ fixed (byte* ptr = buffer)
+ {
+ return (int)io.readProc(new IntPtr(ptr), size, count, handle);
+ }
+ }
+
+ /// <summary>
+ /// Reads a single byte from an unmanaged stream.
+ /// </summary>
+ protected unsafe int ReadByte(FreeImageIO io, fi_handle handle)
+ {
+ byte buffer = 0;
+ return (int)io.readProc(new IntPtr(&buffer), 1, 1, handle) > 0 ? buffer : -1;
+ }
+
+ /// <summary>
+ /// Writes to an unmanaged stream.
+ /// </summary>
+ protected unsafe int Write(FreeImageIO io, fi_handle handle, uint size, uint count, ref byte[] buffer)
+ {
+ fixed (byte* ptr = buffer)
+ {
+ return (int)io.writeProc(new IntPtr(ptr), size, count, handle);
+ }
+ }
+
+ /// <summary>
+ /// Writes a single byte to an unmanaged stream.
+ /// </summary>
+ protected unsafe int WriteByte(FreeImageIO io, fi_handle handle, byte value)
+ {
+ return (int)io.writeProc(new IntPtr(&value), 1, 1, handle);
+ }
+
+ /// <summary>
+ /// Seeks in an unmanaged stream.
+ /// </summary>
+ protected int Seek(FreeImageIO io, fi_handle handle, int offset, SeekOrigin origin)
+ {
+ return io.seekProc(handle, offset, origin);
+ }
+
+ /// <summary>
+ /// Retrieves the position of an unmanaged stream.
+ /// </summary>
+ protected int Tell(FreeImageIO io, fi_handle handle)
+ {
+ return io.tellProc(handle);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/MemoryArray.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/MemoryArray.cs
new file mode 100644
index 0000000..33e2c0f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/MemoryArray.cs
@@ -0,0 +1,828 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Represents unmanaged memory, containing an array of a given structure.
+ /// </summary>
+ /// <typeparam name="T">Structuretype represented by the instance.</typeparam>
+ /// <remarks>
+ /// <see cref="System.Boolean"/> and <see cref="System.Char"/> can not be marshalled.
+ /// <para/>
+ /// Use <see cref="System.Int32"/> instead of <see cref="System.Boolean"/> and
+ /// <see cref="System.Byte"/> instead of <see cref="System.Char"/>.
+ /// </remarks>
+ public unsafe class MemoryArray<T> : IDisposable, ICloneable, ICollection, IEnumerable<T>, IEquatable<MemoryArray<T>> where T : struct
+ {
+ /// <summary>
+ /// Baseaddress of the wrapped memory.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected byte* baseAddress;
+
+ /// <summary>
+ /// Number of elements being wrapped.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected int length;
+
+ /// <summary>
+ /// Size, in bytes, of each element.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly int size;
+
+ /// <summary>
+ /// Array of <b>T</b> containing a single element.
+ /// The array is used as a workaround, because there are no pointer for generic types.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected T[] buffer;
+
+ /// <summary>
+ /// Pointer to the element of <b>buffer</b>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected byte* ptr;
+
+ /// <summary>
+ /// Handle for pinning <b>buffer</b>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected GCHandle handle;
+
+ /// <summary>
+ /// Indicates whether the wrapped memory is handled like a bitfield.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool isOneBit;
+
+ /// <summary>
+ /// Indicates whther the wrapped memory is handles like 4-bit blocks.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool isFourBit;
+
+ /// <summary>
+ /// An object that can be used to synchronize access to the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected object syncRoot = null;
+
+ static MemoryArray()
+ {
+ T[] dummy = new T[2];
+ long marshalledSize = Marshal.SizeOf(typeof(T));
+ long structureSize =
+ Marshal.UnsafeAddrOfPinnedArrayElement(dummy, 1).ToInt64() -
+ Marshal.UnsafeAddrOfPinnedArrayElement(dummy, 0).ToInt64();
+ if (marshalledSize != structureSize)
+ {
+ throw new NotSupportedException(
+ "The desired type can not be handled, " +
+ "because its managed and unmanaged size in bytes are different.");
+ }
+
+ size = (int)marshalledSize;
+ }
+
+ /// <summary>
+ /// Initializes a new instance.
+ /// </summary>
+ protected MemoryArray()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryArray&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="baseAddress">Address of the memory block.</param>
+ /// <param name="length">Length of the array.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="baseAddress"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="length"/> is less or equal zero.</exception>
+ /// <exception cref="NotSupportedException">
+ /// The type is not supported.</exception>
+ public MemoryArray(IntPtr baseAddress, int length)
+ : this(baseAddress.ToPointer(), length)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryArray&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="baseAddress">Address of the memory block.</param>
+ /// <param name="length">Length of the array.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="baseAddress"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="length"/> is less or equal zero.</exception>
+ /// <exception cref="NotSupportedException">
+ /// The type is not supported.</exception>
+ public MemoryArray(void* baseAddress, int length)
+ {
+ if (typeof(T) == typeof(FI1BIT))
+ {
+ isOneBit = true;
+ }
+ else if (typeof(T) == typeof(FI4BIT))
+ {
+ isFourBit = true;
+ }
+
+ if (baseAddress == null)
+ {
+ throw new ArgumentNullException("baseAddress");
+ }
+ if (length < 1)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ this.baseAddress = (byte*)baseAddress;
+ this.length = (int)length;
+
+ if (!isOneBit && !isFourBit)
+ {
+ // Create an array containing a single element.
+ // Due to the fact, that it's not possible to create pointers
+ // of generic types, an array is used to obtain the memory
+ // address of an element of T.
+ this.buffer = new T[1];
+ // The array is pinned immediately to prevent the GC from
+ // moving it to a different position in memory.
+ this.handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ // The array and its content have beed pinned, so that its address
+ // can be safely requested and stored for the whole lifetime
+ // of the instace.
+ this.ptr = (byte*)handle.AddrOfPinnedObject();
+ }
+ }
+
+ /// <summary>
+ /// Frees the allocated <see cref="System.Runtime.InteropServices.GCHandle"/>.
+ /// </summary>
+ ~MemoryArray()
+ {
+ Dispose(false);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="MemoryArray&lt;T&gt;"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="MemoryArray&lt;T&gt;"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="MemoryArray&lt;T&gt;"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="MemoryArray&lt;T&gt;"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(MemoryArray<T> left, MemoryArray<T> right)
+ {
+ if (object.ReferenceEquals(left, right))
+ {
+ return true;
+ }
+ if (object.ReferenceEquals(right, null) ||
+ object.ReferenceEquals(left, null) ||
+ (left.length != right.length))
+ {
+ return false;
+ }
+ if (left.baseAddress == right.baseAddress)
+ {
+ return true;
+ }
+ return FreeImage.CompareMemory(left.baseAddress, right.baseAddress, (uint)left.length);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="MemoryArray&lt;T&gt;"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="MemoryArray&lt;T&gt;"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="MemoryArray&lt;T&gt;"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="MemoryArray&lt;T&gt;"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(MemoryArray<T> left, MemoryArray<T> right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Gets the value at the specified position.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array element to get.</param>
+ /// <returns>The value at the specified position.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public T GetValue(int index)
+ {
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ return GetValueInternal(index);
+ }
+
+ private T GetValueInternal(int index)
+ {
+ EnsureNotDisposed();
+ if (isOneBit)
+ {
+ return (T)(object)(FI1BIT)(((baseAddress[index / 8] & ((1 << (7 - (index % 8))))) == 0) ? 0 : 1);
+ }
+ else if (isFourBit)
+ {
+ return (T)(object)(FI4BIT)(((index % 2) == 0) ? (baseAddress[index / 2] >> 4) : (baseAddress[index / 2] & 0x0F));
+ }
+ else
+ {
+ CopyMemory(ptr, baseAddress + (index * size), size);
+ return buffer[0];
+ }
+ }
+
+ /// <summary>
+ /// Sets a value to the element at the specified position.
+ /// </summary>
+ /// <param name="value">The new value for the specified element.</param>
+ /// <param name="index">A 32-bit integer that represents the
+ /// position of the array element to set.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public void SetValue(T value, int index)
+ {
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ SetValueInternal(value, index);
+ }
+
+ private void SetValueInternal(T value, int index)
+ {
+ EnsureNotDisposed();
+ if (isOneBit)
+ {
+ if ((FI1BIT)(object)value != 0)
+ {
+ baseAddress[index / 8] |= (byte)(1 << (7 - (index % 8)));
+ }
+ else
+ {
+ baseAddress[index / 8] &= (byte)(~(1 << (7 - (index % 8))));
+ }
+ }
+ else if (isFourBit)
+ {
+ if ((index % 2) == 0)
+ {
+ baseAddress[index / 2] = (byte)((baseAddress[index / 2] & 0x0F) | ((FI4BIT)(object)value << 4));
+ }
+ else
+ {
+ baseAddress[index / 2] = (byte)((baseAddress[index / 2] & 0xF0) | ((FI4BIT)(object)value & 0x0F));
+ }
+ }
+ else
+ {
+ buffer[0] = value;
+ CopyMemory(baseAddress + (index * size), ptr, size);
+ }
+ }
+
+ /// <summary>
+ /// Gets the values at the specified position and length.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array elements to get.</param>
+ /// <param name="length"> A 32-bit integer that represents the length
+ /// of the array elements to get.</param>
+ /// <returns>The values at the specified position and length.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array.</exception>
+ public T[] GetValues(int index, int length)
+ {
+ EnsureNotDisposed();
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ if (((index + length) > this.length) || (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ T[] data = new T[length];
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ data[i] = GetValueInternal(i);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
+ byte* dst = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
+ CopyMemory(dst, baseAddress + (size * index), size * length);
+ handle.Free();
+ }
+ return data;
+ }
+
+ /// <summary>
+ /// Sets the values at the specified position.
+ /// </summary>
+ /// <param name="values">An array containing the new values for the specified elements.</param>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array elements to set.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="values"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="values.Length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array.</exception>
+ public void SetValues(T[] values, int index)
+ {
+ EnsureNotDisposed();
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ if ((index + values.Length) > this.length)
+ {
+ throw new ArgumentOutOfRangeException("values.Length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != values.Length; )
+ {
+ SetValueInternal(values[i++], index++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(values, GCHandleType.Pinned);
+ byte* src = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(values, 0);
+ CopyMemory(baseAddress + (index * size), src, size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the entire array to a compatible one-dimensional <see cref="System.Array"/>,
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="System.Array"/> that is the destination
+ /// of the elements copied from <see cref="MemoryArray&lt;T&gt;"/>.
+ /// The <see cref="System.Array"/> must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/>
+ /// at which copying begins.</param>
+ public void CopyTo(Array array, int index)
+ {
+ EnsureNotDisposed();
+ if (!(array is T[]))
+ {
+ throw new InvalidCastException("array");
+ }
+ try
+ {
+ CopyTo((T[])array, 0, index, length);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw new ArgumentException(ex.Message, ex);
+ }
+ }
+
+ /// <summary>
+ /// Copies a range of elements from the unmanaged array starting at the specified
+ /// <typeparamref name="sourceIndex"/> and pastes them to <paramref name="array"/>
+ /// starting at the specified <paramref name="destinationIndex"/>.
+ /// The length and the indexes are specified as 32-bit integers.
+ /// </summary>
+ /// <param name="array">The array that receives the data.</param>
+ /// <param name="sourceIndex">A 32-bit integer that represents the index
+ /// in the unmanaged array at which copying begins.</param>
+ /// <param name="destinationIndex">A 32-bit integer that represents the index in
+ /// the destination array at which storing begins.</param>
+ /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sourceIndex"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array
+ /// <para>-or-</para>
+ /// <paramref name="destinationIndex"/> is outside the range of valid indexes
+ /// for the array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array.
+ /// </exception>
+ public void CopyTo(T[] array, int sourceIndex, int destinationIndex, int length)
+ {
+ EnsureNotDisposed();
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+ if ((sourceIndex >= this.length) || (sourceIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("sourceIndex");
+ }
+ if ((destinationIndex >= array.Length) || (destinationIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("destinationIndex");
+ }
+ if ((sourceIndex + length > this.length) ||
+ (destinationIndex + length > array.Length) ||
+ (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != length; i++)
+ {
+ array[destinationIndex++] = GetValueInternal(sourceIndex++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ byte* dst = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(array, destinationIndex);
+ CopyMemory(dst, baseAddress + (size * sourceIndex), size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies a range of elements from the array starting at the specified
+ /// <typeparamref name="sourceIndex"/> and pastes them to the unmanaged array
+ /// starting at the specified <paramref name="destinationIndex"/>.
+ /// The length and the indexes are specified as 32-bit integers.
+ /// </summary>
+ /// <param name="array">The array that holds the data.</param>
+ /// <param name="sourceIndex">A 32-bit integer that represents the index
+ /// in the array at which copying begins.</param>
+ /// <param name="destinationIndex">A 32-bit integer that represents the index in
+ /// the unmanaged array at which storing begins.</param>
+ /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sourceIndex"/> is outside the range of valid indexes
+ /// for the array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array
+ /// <para>-or-</para>
+ /// <paramref name="destinationIndex"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array.
+ /// </exception>
+ public void CopyFrom(T[] array, int sourceIndex, int destinationIndex, int length)
+ {
+ EnsureNotDisposed();
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+ if ((destinationIndex >= this.length) || (destinationIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("destinationIndex");
+ }
+ if ((sourceIndex >= array.Length) || (sourceIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("sourceIndex");
+ }
+ if ((destinationIndex + length > this.length) ||
+ (sourceIndex + length > array.Length) ||
+ (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != length; i++)
+ {
+ SetValueInternal(array[sourceIndex++], destinationIndex++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ byte* src = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(array, sourceIndex);
+ CopyMemory(baseAddress + (size * destinationIndex), src, size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Returns the represented block of memory as an array of <see cref="Byte"/>.
+ /// </summary>
+ /// <returns>The represented block of memory.</returns>
+ public byte[] ToByteArray()
+ {
+ EnsureNotDisposed();
+ byte[] result;
+ if (isOneBit)
+ {
+ result = new byte[(length + 7) / 8];
+ }
+ else if (isFourBit)
+ {
+ result = new byte[(length + 3) / 4];
+ }
+ else
+ {
+ result = new byte[size * length];
+ }
+ fixed (byte* dst = result)
+ {
+ CopyMemory(dst, baseAddress, result.Length);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Gets or sets the value at the specified position in the array.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array element to get.</param>
+ /// <returns>The value at the specified position in the array.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public T this[int index]
+ {
+ get
+ {
+ return GetValue(index);
+ }
+ set
+ {
+ SetValue(value, index);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the values of the unmanaged array.
+ /// </summary>
+ public T[] Data
+ {
+ get
+ {
+ return GetValues(0, length);
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ if (value.Length != length)
+ {
+ throw new ArgumentOutOfRangeException("value.Lengt");
+ }
+ SetValues(value, 0);
+ }
+ }
+
+ /// <summary>
+ /// Gets the length of the unmanaged array.
+ /// </summary>
+ public int Length
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return length;
+ }
+ }
+
+ /// <summary>
+ /// Gets the base address of the represented memory block.
+ /// </summary>
+ public IntPtr BaseAddress
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new IntPtr(baseAddress);
+ }
+ }
+
+ /// <summary>
+ /// Creates a shallow copy of the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>A shallow copy of the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public object Clone()
+ {
+ EnsureNotDisposed();
+ return new MemoryArray<T>(baseAddress, length);
+ }
+
+ /// <summary>
+ /// Gets a 32-bit integer that represents the total number of elements
+ /// in the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ public int Count
+ {
+ get { EnsureNotDisposed(); return length; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="MemoryArray&lt;T&gt;"/>
+ /// is synchronized (thread safe).
+ /// </summary>
+ public bool IsSynchronized
+ {
+ get { EnsureNotDisposed(); return false; }
+ }
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ public object SyncRoot
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (syncRoot == null)
+ {
+ System.Threading.Interlocked.CompareExchange(ref syncRoot, new object(), null);
+ }
+ return syncRoot;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// elements in this <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ EnsureNotDisposed();
+ T[] values = GetValues(0, length);
+ for (int i = 0; i != values.Length; i++)
+ {
+ yield return values[i];
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// elements in this <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator&lt;T&gt;"/> for the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ IEnumerator<T> IEnumerable<T>.GetEnumerator()
+ {
+ EnsureNotDisposed();
+ T[] values = GetValues(0, length);
+ for (int i = 0; i != values.Length; i++)
+ {
+ yield return values[i];
+ }
+ }
+
+ /// <summary>
+ /// Releases all ressources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases allocated handles associated with this instance.
+ /// </summary>
+ /// <param name="disposing"><b>true</b> to release managed resources.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (baseAddress != null)
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ baseAddress = null;
+ buffer = null;
+ length = 0;
+ syncRoot = null;
+ }
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ObjectDisposedException"/> if
+ /// this instance is disposed.
+ /// </summary>
+ protected virtual void EnsureNotDisposed()
+ {
+ if (baseAddress == null)
+ throw new ObjectDisposedException("This instance is disposed.");
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MemoryArray&lt;T&gt;"/> structure is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure.
+ /// </summary>
+ /// <param name="obj">The structure to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="MemoryArray&lt;T&gt;"/>
+ /// instance equivalent to this <see cref="MemoryArray&lt;T&gt;"/> structure; otherwise,
+ /// <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ EnsureNotDisposed();
+ return ((obj is MemoryArray<T>) && Equals((MemoryArray<T>)obj));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MemoryArray&lt;T&gt;"/> structure is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure.
+ /// </summary>
+ /// <param name="other">The structure to test.</param>
+ /// <returns><b>true</b> if <paramref name="other"/> is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure; otherwise,
+ /// <b>false</b>.</returns>
+ public bool Equals(MemoryArray<T> other)
+ {
+ EnsureNotDisposed();
+ return ((this.baseAddress == other.baseAddress) && (this.length == other.length));
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>A hash code for the current <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public override int GetHashCode()
+ {
+ EnsureNotDisposed();
+ return (int)baseAddress ^ length;
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">Pointer to the starting address of the copy destination.</param>
+ /// <param name="src">Pointer to the starting address of the block of memory to be copied.</param>
+ /// <param name="len">Size of the block of memory to copy, in bytes.</param>
+ protected static unsafe void CopyMemory(byte* dest, byte* src, int len)
+ {
+ if (len >= 0x10)
+ {
+ do
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ *((int*)(dest + 8)) = *((int*)(src + 8));
+ *((int*)(dest + 12)) = *((int*)(src + 12));
+ dest += 0x10;
+ src += 0x10;
+ }
+ while ((len -= 0x10) >= 0x10);
+ }
+ if (len > 0)
+ {
+ if ((len & 8) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ dest += 8;
+ src += 8;
+ }
+ if ((len & 4) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ dest += 4;
+ src += 4;
+ }
+ if ((len & 2) != 0)
+ {
+ *((short*)dest) = *((short*)src);
+ dest += 2;
+ src += 2;
+ }
+ if ((len & 1) != 0)
+ {
+ *dest = *src;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModel.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModel.cs
new file mode 100644
index 0000000..5857db8
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModel.cs
@@ -0,0 +1,941 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.8 $
+// $Date: 2009/02/27 16:34:31 $
+// $Id: MetadataModel.cs,v 1.8 2009/02/27 16:34:31 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Base class that represents a collection of all tags contained in a metadata model.
+ /// </summary>
+ /// <remarks>
+ /// The <b>MetedataModel</b> class is an abstract base class, which is inherited by
+ /// several derived classes, one for each existing metadata model.
+ /// </remarks>
+ public abstract class MetadataModel : IEnumerable
+ {
+ /// <summary>
+ /// Handle to the encapsulated FreeImage-bitmap.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly FIBITMAP dib;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ protected MetadataModel(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ this.dib = dib;
+ }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public abstract FREE_IMAGE_MDMODEL Model
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Adds new tag to the bitmap or updates its value in case it already exists.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="tag">The tag to add or update.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="tag"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The tags model differs from this instances model.</exception>
+ public bool AddTag(MetadataTag tag)
+ {
+ if (tag == null)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ if (tag.Model != Model)
+ {
+ throw new ArgumentException("tag.Model");
+ }
+ return tag.AddToImage(dib);
+ }
+
+ /// <summary>
+ /// Adds a list of tags to the bitmap or updates their values in case they already exist.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="list">A list of tags to add or update.</param>
+ /// <returns>Returns the number of successfully added tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="list"/> is null.</exception>
+ public int AddTag(IEnumerable<MetadataTag> list)
+ {
+ if (list == null)
+ {
+ throw new ArgumentNullException("list");
+ }
+ int count = 0;
+ foreach (MetadataTag tag in list)
+ {
+ if (tag.Model == Model && tag.AddToImage(dib))
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /// <summary>
+ /// Removes the specified tag from the bitmap.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public bool RemoveTag(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ return FreeImage.SetMetadata(Model, dib, key, FITAG.Zero);
+ }
+
+ /// <summary>
+ /// Destroys the metadata model
+ /// which will remove all tags of this model from the bitmap.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool DestoryModel()
+ {
+ return FreeImage.SetMetadata(Model, dib, null, FITAG.Zero);
+ }
+
+ /// <summary>
+ /// Returns the specified metadata tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The metadata tag.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public MetadataTag GetTag(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag;
+ return FreeImage.GetMetadata(Model, dib, key, out tag) ? tag : null;
+ }
+
+ /// <summary>
+ /// Returns whether the specified tag exists.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>True in case the tag exists, else false.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public bool TagExists(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag;
+ return FreeImage.GetMetadata(Model, dib, key, out tag);
+ }
+
+ /// <summary>
+ /// Returns a list of all metadata tags this instance represents.
+ /// </summary>
+ public List<MetadataTag> List
+ {
+ get
+ {
+ List<MetadataTag> list = new List<MetadataTag>((int)FreeImage.GetMetadataCount(Model, dib));
+ MetadataTag tag;
+ FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ do
+ {
+ list.Add(tag);
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Returns the tag at the given index.
+ /// </summary>
+ /// <param name="index">Index of the tag to return.</param>
+ /// <returns>The tag at the given index.</returns>
+ protected MetadataTag GetTagFromIndex(int index)
+ {
+ if (index >= Count || index < 0)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ MetadataTag tag;
+ int count = 0;
+ FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ try
+ {
+ do
+ {
+ if (count++ == index)
+ {
+ break;
+ }
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ }
+ finally
+ {
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ }
+ return tag;
+ }
+
+ /// <summary>
+ /// Returns the metadata tag at the given index. This operation is slow when accessing all tags.
+ /// </summary>
+ /// <param name="index">Index of the tag.</param>
+ /// <returns>The metadata tag.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is greater or equal <b>Count</b>
+ /// or index is less than zero.</exception>
+ public MetadataTag this[int index]
+ {
+ get
+ {
+ return GetTagFromIndex(index);
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual MetadataTags in this MetadataModel.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ return List.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Returns the number of metadata tags this instance represents.
+ /// </summary>
+ public int Count
+ {
+ get { return (int)FreeImage.GetMetadataCount(Model, dib); }
+ }
+
+ /// <summary>
+ /// Returns whether this model exists in the bitmaps metadata structure.
+ /// </summary>
+ public bool Exists
+ {
+ get
+ {
+ return Count > 0;
+ }
+ }
+
+ /// <summary>
+ /// Searches for a pattern in each metadata tag and returns the result as a list.
+ /// </summary>
+ /// <param name="searchPattern">The regular expression to use for the search.</param>
+ /// <param name="flags">A bitfield that controls which fields should be searched in.</param>
+ /// <returns>A list containing all found metadata tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <typeparamref name="searchPattern"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <typeparamref name="searchPattern"/> is empty.</exception>
+ public List<MetadataTag> RegexSearch(string searchPattern, MD_SEARCH_FLAGS flags)
+ {
+ if (searchPattern == null)
+ {
+ throw new ArgumentNullException("searchString");
+ }
+ if (searchPattern.Length == 0)
+ {
+ throw new ArgumentException("searchString is empty");
+ }
+ List<MetadataTag> result = new List<MetadataTag>(Count);
+ Regex regex = new Regex(searchPattern);
+ List<MetadataTag> list = List;
+ foreach (MetadataTag tag in list)
+ {
+ if (((flags & MD_SEARCH_FLAGS.KEY) > 0) && regex.Match(tag.Key).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ if (((flags & MD_SEARCH_FLAGS.DESCRIPTION) > 0) && regex.Match(tag.Description).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ if (((flags & MD_SEARCH_FLAGS.TOSTRING) > 0) && regex.Match(tag.ToString()).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ }
+ result.Capacity = result.Count;
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the value of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">Type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The value of the specified tag.</returns>
+ protected T? GetTagValue<T>(string key) where T : struct
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ if (tag != null)
+ {
+ T[] value = tag.Value as T[];
+ if ((value != null) && (value.Length != 0))
+ {
+ return value[0];
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns an array containing the data of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">The type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>An array containing the data of the specified tag.</returns>
+ protected T[] GetTagArray<T>(string key) where T : struct
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ return (tag == null) ? null : tag.Value as T[];
+ }
+
+ /// <summary>
+ /// Returns the string contained by the specified tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The string contained by the specified tag.</returns>
+ protected string GetTagText(string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ return (tag == null) ? null : tag.Value as string;
+ }
+
+ /// <summary>
+ /// Returns an array containg the data of the specified tag
+ /// as unsigned 32bit integer.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>An array containg the data of the specified tag
+ /// as unsigned 32bit integer.</returns>
+ protected uint[] GetUInt32Array(string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ uint[] result = null;
+ MetadataTag tag = GetTag(key);
+ if (tag != null)
+ {
+ object value = tag.Value;
+ if (value != null)
+ {
+ if (value is ushort[])
+ {
+ ushort[] array = (ushort[])value;
+ result = new uint[array.Length];
+ for (int i = 0, j = array.Length; i < j; i++)
+ {
+ result[i] = (uint)array[i];
+ }
+ }
+ else if (value is uint[])
+ {
+ result = (uint[])value;
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the value of the tag as unsigned 32bit integer.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The value of the tag as unsigned 32bit integer.</returns>
+ protected uint? GetUInt32Value(string key)
+ {
+ uint[] value = GetUInt32Array(key);
+ return value == null ? default(uint?) : value[0];
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">The type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValue<T>(string key, T? value) where T : struct
+ {
+ SetTagValue(key, value.HasValue ? new T[] { value.Value } : null);
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValue(string key, object value)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ if (value == null)
+ {
+ RemoveTag(key);
+ }
+ else
+ {
+ MetadataTag tag = GetTag(key);
+ if (tag == null)
+ {
+ tag = new MetadataTag(Model);
+ tag.Key = key;
+ tag.Value = value;
+ AddTag(tag);
+ }
+ else
+ {
+ tag.Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag as undefined.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValueUndefined(string key, byte[] value)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ if (value == null)
+ {
+ RemoveTag(key);
+ }
+ else
+ {
+ MetadataTag tag = GetTag(key);
+ if (tag == null)
+ {
+ tag = new MetadataTag(Model);
+ tag.Key = key;
+ tag.SetValue(value, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED);
+ AddTag(tag);
+ }
+ else
+ {
+ tag.Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="DirectionReference"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="DirectionReference"/>.</param>
+ /// <returns>The equivalent <see cref="DirectionReference"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static DirectionReference? ToDirectionType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'T':
+ return DirectionReference.TrueDirection;
+ case 'M':
+ return DirectionReference.MagneticDirection;
+ default:
+ return DirectionReference.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="DirectionReference"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="DirectionReference"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="DirectionReference"/>.</returns>
+ protected static string ToString(DirectionReference? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case DirectionReference.TrueDirection:
+ return "T";
+ case DirectionReference.MagneticDirection:
+ return "M";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="VelocityUnit"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="VelocityUnit"/>.</param>
+ /// <returns>The equivalent <see cref="VelocityUnit"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static VelocityUnit? ToUnitType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'K':
+ return VelocityUnit.Kilometers;
+ case 'M':
+ return VelocityUnit.Miles;
+ case 'N':
+ return VelocityUnit.Knots;
+ default:
+ return VelocityUnit.Undefinied;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="VelocityUnit"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="VelocityUnit"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="VelocityUnit"/>.</returns>
+ protected static string ToString(VelocityUnit? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case VelocityUnit.Kilometers:
+ return "K";
+ case VelocityUnit.Miles:
+ return "M";
+ case VelocityUnit.Knots:
+ return "N";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="LongitudeType"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="LongitudeType"/>.</param>
+ /// <returns>The equivalent <see cref="LongitudeType"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static LongitudeType? ToLongitudeType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'E':
+ return LongitudeType.East;
+ case 'W':
+ return LongitudeType.West;
+ default:
+ return LongitudeType.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="LongitudeType"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="LongitudeType"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="LongitudeType"/>.</returns>
+ protected static string ToString(LongitudeType? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case LongitudeType.East:
+ return "E";
+ case LongitudeType.West:
+ return "W";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="LatitudeType"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="LatitudeType"/>.</param>
+ /// <returns>The equivalent <see cref="LatitudeType"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static LatitudeType? ToLatitudeType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'N':
+ return LatitudeType.North;
+ case 'S':
+ return LatitudeType.South;
+ default:
+ return LatitudeType.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="LatitudeType"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="LatitudeType"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="LatitudeType"/>.</returns>
+ protected static string ToString(LatitudeType? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case LatitudeType.North:
+ return "N";
+ case LatitudeType.South:
+ return "S";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="InteroperabilityMode"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="InteroperabilityMode"/>.</param>
+ /// <returns>The equivalent <see cref="InteroperabilityMode"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static InteroperabilityMode? ToInteroperabilityType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ if (s.StartsWith("R98"))
+ return InteroperabilityMode.R98;
+ if (s.StartsWith("THM"))
+ return InteroperabilityMode.THM;
+ return InteroperabilityMode.Undefined;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="InteroperabilityMode"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="InteroperabilityMode"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="InteroperabilityMode"/>.</returns>
+ protected static string ToString(InteroperabilityMode? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case InteroperabilityMode.R98:
+ return "R98";
+ case InteroperabilityMode.THM:
+ return "THM";
+ default:
+ return "\0\0\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Specified different unit types.
+ /// </summary>
+ public enum VelocityUnit
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefinied,
+
+ /// <summary>
+ /// Kilometers per hour.
+ /// </summary>
+ Kilometers,
+
+ /// <summary>
+ /// Miles per hour.
+ /// </summary>
+ Miles,
+
+ /// <summary>
+ /// Knots.
+ /// </summary>
+ Knots,
+ }
+
+ /// <summary>
+ /// Specifies different direction types.
+ /// </summary>
+ public enum DirectionReference
+ {
+ /// <summary>
+ /// No or unknown direction type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// True direction.
+ /// </summary>
+ TrueDirection,
+
+ /// <summary>
+ /// Magnatic direction.
+ /// </summary>
+ MagneticDirection,
+ }
+
+ /// <summary>
+ /// Specifies the type of a latitude value.
+ /// </summary>
+ public enum LatitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// North.
+ /// </summary>
+ North,
+
+ /// <summary>
+ /// South.
+ /// </summary>
+ South,
+ }
+
+ /// <summary>
+ /// Specifies the type of a longitude value.
+ /// </summary>
+ public enum LongitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// East.
+ /// </summary>
+ East,
+
+ /// <summary>
+ /// West.
+ /// </summary>
+ West,
+ }
+
+ /// <summary>
+ /// Specifies different altitude types.
+ /// </summary>
+ public enum AltitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// East.
+ /// </summary>
+ AboveSeaLevel,
+
+ /// <summary>
+ /// West.
+ /// </summary>
+ BelowSeaLevel,
+ }
+
+ /// <summary>
+ /// Specifies interoperability types.
+ /// </summary>
+ public enum InteroperabilityMode
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// Indicates a file conforming to R98 file specification of Recommended
+ /// Exif Interoperability Rules (ExifR98) or to DCF basic file stipulated
+ /// by Design Rule for Camera File System.
+ /// </summary>
+ R98,
+
+ /// <summary>
+ /// Indicates a file conforming to DCF thumbnail file stipulated by Design
+ /// rule for Camera File System.
+ /// </summary>
+ THM,
+ }
+
+ /// <summary>
+ /// Specifies orientation of images.
+ /// </summary>
+ public enum ExifImageOrientation : ushort
+ {
+ /// <summary>
+ /// Undefinied orientation.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// TopLeft.
+ /// </summary>
+ TopLeft = 1,
+
+ /// <summary>
+ /// TopRight.
+ /// </summary>
+ TopRight,
+
+ /// <summary>
+ /// BottomRight.
+ /// </summary>
+ BottomRight,
+
+ /// <summary>
+ /// BottomLeft.
+ /// </summary>
+ BottomLeft,
+
+ /// <summary>
+ /// LeftTop.
+ /// </summary>
+ LeftTop,
+
+ /// <summary>
+ /// RightTop.
+ /// </summary>
+ RightTop,
+
+ /// <summary>
+ /// RightBottom.
+ /// </summary>
+ RightBottom,
+
+ /// <summary>
+ /// LeftBottom.
+ /// </summary>
+ LeftBottom,
+ }
+
+ /// <summary>
+ /// Converts the model of the MetadataModel object to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return Model.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModels.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModels.cs
new file mode 100644
index 0000000..dfa9f90
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataModels.cs
@@ -0,0 +1,6724 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.6 $
+// $Date: 2009/09/15 11:49:24 $
+// $Id: MetadataModels.cs,v 1.6 2009/09/15 11:49:24 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Xml;
+using System.IO;
+using System.Text;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_ANIMATION"/>.
+ /// </summary>
+ public class MDM_ANIMATION : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_ANIMATION(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_ANIMATION; }
+ }
+
+ /// <summary>
+ /// Gets or sets the width of the entire canvas area, that each page is displayed in.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LogicalWidth
+ {
+ get
+ {
+ return GetTagValue<ushort>("LogicalWidth");
+ }
+ set
+ {
+ SetTagValue("LogicalWidth", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the height of the entire canvas area, that each page is displayed in.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LogicalHeight
+ {
+ get
+ {
+ return GetTagValue<ushort>("LogicalHeight");
+ }
+ set
+ {
+ SetTagValue("LogicalHeight", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the global palette of the GIF image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public Palette GlobalPalette
+ {
+ get
+ {
+ MetadataTag mdtag = GetTag("GlobalPalette");
+ return (mdtag == null) ? null : new Palette(mdtag);
+ }
+ set
+ {
+ SetTagValue("GlobalPalette", (value != null) ? null : value.Data);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of replays for the animation.
+ /// Use 0 (zero) to specify an infinte number of replays.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? LoopCount
+ {
+ get
+ {
+ return GetTagValue<uint>("Loop");
+ }
+ set
+ {
+ SetTagValue("Loop", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the horizontal offset within the logical canvas area, this frame is to be displayed at.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FrameLeft
+ {
+ get
+ {
+ return GetTagValue<ushort>("FrameLeft");
+ }
+ set
+ {
+ SetTagValue("FrameLeft", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the vertical offset within the logical canvas area, this frame is to be displayed at.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FrameTop
+ {
+ get
+ {
+ return GetTagValue<ushort>("FrameTop");
+ }
+ set
+ {
+ SetTagValue("FrameTop", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a flag to supress saving the dib's attached palette
+ /// (making it use the global palette). The local palette is the palette used by a page.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? NoLocalPalette
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("NoLocalPalette");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("NoLocalPalette", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the image is interlaced.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? Interlaced
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("Interlaced");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("Interlaced", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the amout of time in milliseconds this frame is to be displayed.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? FrameTime
+ {
+ get
+ {
+ return GetTagValue<uint>("FrameTime");
+ }
+ set
+ {
+ SetTagValue("FrameTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets this frame's disposal method. Generally, this method defines, how to
+ /// remove or replace a frame when the next frame has to be drawn.<para/>
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DisposalMethodType? DisposalMethod
+ {
+ get
+ {
+ return GetTagValue<DisposalMethodType>("DisposalMethod");
+ }
+ set
+ {
+ SetTagValue("DisposalMethod", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_COMMENTS"/>.
+ /// </summary>
+ public class MDM_COMMENTS : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_COMMENTS(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_COMMENTS; }
+ }
+
+ /// <summary>
+ /// Gets or sets the comment of the image.
+ /// Supported formats are JPEG, PNG and GIF.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Comment
+ {
+ get
+ {
+ return GetTagText("Comment");
+ }
+ set
+ {
+ SetTagValue("Comment", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_CUSTOM"/>.
+ /// </summary>
+ public class MDM_CUSTOM : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_CUSTOM(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_CUSTOM; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF"/>.
+ /// </summary>
+ public class MDM_EXIF_EXIF : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_EXIF(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF; }
+ }
+
+ /// <summary>
+ /// Gets or sets the version of this standard supported.
+ /// Constant length or 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ExifVersion
+ {
+ get
+ {
+ return GetTagArray<byte>("ExifVersion");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("ExifVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Flashpix format version supported by a FPXR file.
+ /// Constant length or 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] FlashpixVersion
+ {
+ get
+ {
+ return GetTagArray<byte>("FlashpixVersion");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("FlashpixVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the color space information tag.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>sRGB (default)</description>
+ /// </item>
+ /// <item>
+ /// <term>0xFFFF</term>
+ /// <description>uncalibrated</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ColorSpace
+ {
+ get
+ {
+ return GetTagValue<ushort>("ColorSpace");
+ }
+ set
+ {
+ SetTagValue("ColorSpace", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the valid width of a compressed image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? PixelXDimension
+ {
+ get
+ {
+ return GetUInt32Value("PixelXDimension");
+ }
+ set
+ {
+ RemoveTag("PixelXDimension");
+ if (value.HasValue)
+ {
+ SetTagValue("PixelXDimension", value.Value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the valid height of a compressed image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? PixelYDimension
+ {
+ get
+ {
+ return GetUInt32Value("PixelYDimension");
+ }
+ set
+ {
+ RemoveTag("PixelYDimension");
+ if (value.HasValue)
+ {
+ SetTagValue("PixelYDimension", value.Value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets components configuration. See remarks for further information.
+ /// Constant length of 4.
+ /// </summary>
+ /// <remarks>
+ /// The channels of each component are arranged in order from the 1st component to the 4th.
+ /// For uncompressed data the data arrangement is given in the PhotometricInterpretation tag.
+ /// However, since PhotometricInterpretation can only express the order of Y,Cb and Cr,
+ /// this tag is provided for cases when compressed data uses components other than Y, Cb,
+ /// and Cr and to enable support of other sequences.<para/>
+ /// Default = 4 5 6 0 (if RGB uncompressed)<para/>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>does not exist</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>Y</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>Cb</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>Cr</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ComponentsConfiguration
+ {
+ get
+ {
+ return GetTagArray<byte>("ComponentsConfiguration");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("ComponentsConfiguration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets compression mode used for a compressed image is indicated
+ /// in unit bits per pixel.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? CompressedBitsPerPixel
+ {
+ get
+ {
+ return GetTagValue<FIURational>("CompressedBitsPerPixel");
+ }
+ set
+ {
+ SetTagValue("CompressedBitsPerPixel", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag for manufacturers of Exif writers to record any desired information.
+ /// The contents are up to the manufacturer, but this tag should not be used for any other
+ /// than its intended purpose.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] MakerNote
+ {
+ get
+ {
+ return GetTagArray<byte>("FlashpixVersion");
+ }
+ set
+ {
+ SetTagValueUndefined("FlashpixVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag for Exif users to write keywords or comments on the image besides
+ /// those in ImageDescription, and without the character code limitations of the ImageDescription tag.
+ /// Minimum length of 8. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The character code used in the UserComment tag is identified based on an ID code in a fixed 8-byte
+ /// area at the start of the tag data area. The unused portion of the area is padded with NULL.
+ /// The ID code for the UserComment area may be a Defined code such as JIS or ASCII, or may be Undefined.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] UserComment
+ {
+ get
+ {
+ return GetTagArray<byte>("UserComment");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 8, int.MaxValue);
+ SetTagValueUndefined("UserComment", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of an audio file related to the image data.
+ /// The format is 8.3.
+ /// Constant length of 12
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string RelatedSoundFile
+ {
+ get
+ {
+ string text = GetTagText("RelatedSoundFile");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ FreeImage.Resize(ref value, 12);
+ value += '\0';
+ }
+ SetTagValue("RelatedSoundFile", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time when the original image data was generated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeOriginal
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTimeOriginal");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTimeOriginal", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time when the image was stored as digital data.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeDigitized
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTimeDigitized");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTimeDigitized", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTime tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTime
+ {
+ get
+ {
+ string text = GetTagText("SubsecTime");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTimeOriginal tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTimeOriginal
+ {
+ get
+ {
+ string text = GetTagText("SubsecTimeOriginal");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTimeOriginal", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTimeDigitized tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTimeDigitized
+ {
+ get
+ {
+ string text = GetTagText("SubsecTimeDigitized");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTimeDigitized", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or the exposure time, given in seconds (sec).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ExposureTime
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ExposureTime");
+ }
+ set
+ {
+ SetTagValue("ExposureTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or the F number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FNumber
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FNumber");
+ }
+ set
+ {
+ SetTagValue("FNumber", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the class of the program used by the camera to set exposure when the
+ /// picture is taken.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>not defined</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>normal program</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>aperture priority</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>shutter priority</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>create program</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>action program</description>
+ /// </item>
+ /// <item>
+ /// <term>7</term>
+ /// <description>portrait mode</description>
+ /// </item>
+ /// <item>
+ /// <term>8</term>
+ /// <description>landscape mode</description>
+ /// </item>
+ /// <item>
+ /// <term>others</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ExposureProgram
+ {
+ get
+ {
+ return GetTagValue<ushort>("ExposureProgram");
+ }
+ set
+ {
+ SetTagValue("ExposureProgram", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the spectral sensitivity of each channel of the camera used.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SpectralSensitivity
+ {
+ get
+ {
+ string text = GetTagText("SpectralSensitivity");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SpectralSensitivity", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the the ISO Speed and ISO Latitude of the camera or input device as
+ /// specified in ISO 12232.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] ISOSpeedRatings
+ {
+ get
+ {
+ return GetTagArray<ushort>("ISOSpeedRatings");
+ }
+ set
+ {
+ SetTagValue("ISOSpeedRatings", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Opto-Electric Conversion Function (OECF) specified in ISO 14524.
+ /// OECF is the relationship between the camera optical input and the image values.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] OECF
+ {
+ get
+ {
+ return GetTagArray<byte>("OECF");
+ }
+ set
+ {
+ SetTagValueUndefined("OECF", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the shutter speed. The unit is the APEX (Additive System of Photographic Exposure).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? ShutterSpeedValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("ShutterSpeedValue");
+ }
+ set
+ {
+ SetTagValue("ShutterSpeedValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the lens aperture. The unit is the APEX value.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ApertureValue
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ApertureValue");
+ }
+ set
+ {
+ SetTagValue("ApertureValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of brightness. The unit is the APEX value.
+ /// Ordinarily it is given in the range of -99.99 to 99.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? BrightnessValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("BrightnessValue");
+ }
+ set
+ {
+ SetTagValue("BrightnessValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure bias. The unit is the APEX value.
+ /// Ordinarily it is given in the range of –99.99 to 99.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? ExposureBiasValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("ExposureBiasValue");
+ }
+ set
+ {
+ SetTagValue("ExposureBiasValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the smallest F number of the lens. The unit is the APEX value.
+ /// Ordinarily it is given in the range of 00.00 to 99.99,
+ /// but it is not limited to this range.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? MaxApertureValue
+ {
+ get
+ {
+ return GetTagValue<FIURational>("MaxApertureValue");
+ }
+ set
+ {
+ SetTagValue("MaxApertureValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets distance to the subject, given in meters.
+ /// Note that if the numerator of the recorded value is FFFFFFFF, infinity shall be indicated;
+ /// and if the numerator is 0, distance unknown shall be indicated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? SubjectDistance
+ {
+ get
+ {
+ return GetTagValue<FIURational>("SubjectDistance");
+ }
+ set
+ {
+ SetTagValue("SubjectDistance", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the metering mode. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>average</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>center-weighted-average</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>spot</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>multi-spot</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>pattern</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>partial</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// <item>
+ /// <term>255</term>
+ /// <description>other</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? MeteringMode
+ {
+ get
+ {
+ return GetTagValue<ushort>("MeteringMode");
+ }
+ set
+ {
+ SetTagValue("MeteringMode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the kind of light source.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>daylight</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>fluorescent</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>tungsten</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>flash</description>
+ /// </item>
+ /// <item>
+ /// <term>9</term>
+ /// <description>fine weather</description>
+ /// </item>
+ /// <item>
+ /// <term>10</term>
+ /// <description>cloudy weather</description>
+ /// </item>
+ /// <item>
+ /// <term>11</term>
+ /// <description>shade</description>
+ /// </item>
+ /// <item>
+ /// <term>12</term>
+ /// <description>daylight fluorecent (D 5700 - 7100K)</description>
+ /// </item>
+ /// <item>
+ /// <term>13</term>
+ /// <description>day white fluorescent (N 4600 - 5400K)</description>
+ /// </item>
+ /// <item>
+ /// <term>14</term>
+ /// <description>cool white fluorescent (W 3900 - 4500K)</description>
+ /// </item>
+ /// <item>
+ /// <term>15</term>
+ /// <description>white fluorescent (WW 3200 - 3700K)</description>
+ /// </item>
+ /// <item>
+ /// <term>17</term>
+ /// <description>standard light A</description>
+ /// </item>
+ /// <item>
+ /// <term>18</term>
+ /// <description>standard light B</description>
+ /// </item>
+ /// <item>
+ /// <term>19</term>
+ /// <description>standard light C</description>
+ /// </item>
+ /// <item>
+ /// <term>20</term>
+ /// <description>D55</description>
+ /// </item>
+ /// <item>
+ /// <term>21</term>
+ /// <description>D65</description>
+ /// </item>
+ /// <item>
+ /// <term>22</term>
+ /// <description>D75</description>
+ /// </item>
+ /// <item>
+ /// <term>23</term>
+ /// <description>D50</description>
+ /// </item>
+ /// <item>
+ /// <term>24</term>
+ /// <description>ISO studio tungsten</description>
+ /// </item>
+ /// <item>
+ /// <term>255</term>
+ /// <description>other light source</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LightSource
+ {
+ get
+ {
+ return GetTagValue<ushort>("LightSource");
+ }
+ set
+ {
+ SetTagValue("LightSource", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the status of flash when the image was shot.
+ /// Bit 0 indicates the flash firing status, bits 1 and 2 indicate the flash return
+ /// status, bits 3 and 4 indicate the flash mode, bit 5 indicates whether the flash
+ /// function is present, and bit 6 indicates "red eye" mode.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Flash
+ {
+ get
+ {
+ return GetTagValue<ushort>("Flash");
+ }
+ set
+ {
+ SetTagValue("Flash", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the location and area of the main subject in
+ /// the overall scene. Variable length between 2 and 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] SubjectArea
+ {
+ get
+ {
+ return GetTagArray<ushort>("SubjectArea");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2, 4);
+ SetTagValue("SubjectArea", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the actual focal length of the lens, in mm.
+ /// Conversion is not made to the focal length of a 35 mm film camera.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalLength
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalLength");
+ }
+ set
+ {
+ SetTagValue("FocalLength", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the strobe energy at the time the image is captured,
+ /// as measured in Beam Candle Power Seconds (BCPS).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FlashEnergy
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FlashEnergy");
+ }
+ set
+ {
+ SetTagValue("FlashEnergy", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the camera or input device spatial frequency table and SFR values
+ /// in the direction of image width, image height, and diagonal direction,
+ /// as specified in ISO 12233.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] SpatialFrequencyResponse
+ {
+ get
+ {
+ return GetTagArray<byte>("SpatialFrequencyResponse");
+ }
+ set
+ {
+ SetTagValueUndefined("SpatialFrequencyResponse", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels in the image width (X) direction per
+ /// FocalPlaneResolutionUnit on the camera focal plane.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalPlaneXResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalPlaneXResolution");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneXResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels in the image height (Y) direction per
+ /// FocalPlaneResolutionUnit on the camera focal plane.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalPlaneYResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalPlaneYResolution");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneYResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit for measuring FocalPlaneXResolution and FocalPlaneYResolution.
+ /// This value is the same as the ResolutionUnit.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FocalPlaneResolutionUnit
+ {
+ get
+ {
+ return GetTagValue<ushort>("FocalPlaneResolutionUnit");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneResolutionUnit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the location of the main subject in the scene.
+ /// The value of this tag represents the pixel at the center of the main subject
+ /// relative to the left edge, prior to rotation processing as per the Rotation tag.
+ /// The first value indicates the X column number and second indicates the Y row number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SubjectLocation
+ {
+ get
+ {
+ return GetTagValue<ushort>("SubjectLocation");
+ }
+ set
+ {
+ SetTagValue("SubjectLocation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure index selected on the camera or input device at the
+ /// time the image was captured.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ExposureIndex
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ExposureIndex");
+ }
+ set
+ {
+ SetTagValue("ExposureIndex", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image sensor type on the camera or input device.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>not defined</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>one-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>two-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>three-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>color sequential area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>7</term>
+ /// <description>trilinear sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>8</term>
+ /// <description>color sequential linear sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SensingMethod
+ {
+ get
+ {
+ return GetTagValue<ushort>("SensingMethod");
+ }
+ set
+ {
+ SetTagValue("SensingMethod", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image source. If a DSC recorded the image, this tag value of this
+ /// tag always be set to 3, indicating that the image was recorded on a DSC.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte? FileSource
+ {
+ get
+ {
+ return GetTagValue<byte>("FileSource");
+ }
+ set
+ {
+ SetTagValueUndefined("FileSource", value.HasValue ? new byte[] { value.Value } : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of scene. If a DSC recorded the image, this tag value shall
+ /// always be set to 1, indicating that the image was directly photographed.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte? SceneType
+ {
+ get
+ {
+ return GetTagValue<byte>("SceneType");
+ }
+ set
+ {
+ SetTagValueUndefined("SceneType", value.HasValue ? new byte[] { value.Value } : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the color filter array (CFA) geometric pattern of the image sensor
+ /// when a one-chip color area sensor is used. It does not apply to all sensing methods.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] CFAPattern
+ {
+ get
+ {
+ return GetTagArray<byte>("CFAPattern");
+ }
+ set
+ {
+ SetTagValueUndefined("CFAPattern", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the use of special processing on image data, such as rendering geared to output.
+ /// When special processing is performed, the reader is expected to disable or minimize any
+ /// further processing. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal process</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>custom process</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? CustomRendered
+ {
+ get
+ {
+ return GetTagValue<ushort>("CustomRendered");
+ }
+ set
+ {
+ SetTagValue("CustomRendered", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure mode set when the image was shot.
+ /// In auto-bracketing mode, the camera shoots a series of frames of the same scene
+ /// at different exposure settings. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>auto exposure</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual exposure</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>auto bracket</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ExposureMode
+ {
+ get
+ {
+ return GetTagValue<ushort>("ExposureMode");
+ }
+ set
+ {
+ SetTagValue("ExposureMode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the white balance mode set when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>auto white balance</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual white balance</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? WhiteBalance
+ {
+ get
+ {
+ return GetTagValue<ushort>("WhiteBalance");
+ }
+ set
+ {
+ SetTagValue("WhiteBalance", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the digital zoom ratio when the image was shot.
+ /// If the numerator of the recorded value is 0, this indicates that digital zoom was not used.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? DigitalZoomRatio
+ {
+ get
+ {
+ return GetTagValue<FIURational>("DigitalZoomRatio");
+ }
+ set
+ {
+ SetTagValue("DigitalZoomRatio", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the equivalent focal length assuming a 35mm film camera, in mm.
+ /// A value of 0 means the focal length is unknown. Note that this tag differs
+ /// from the FocalLength tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FocalLengthIn35mmFilm
+ {
+ get
+ {
+ return GetTagValue<ushort>("DigitalZoomRatio");
+ }
+ set
+ {
+ SetTagValue("DigitalZoomRatio", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of scene that was shot.
+ /// It can also be used to record the mode in which the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>standard</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>landscape</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>portrait</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>night scene</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SceneCaptureType
+ {
+ get
+ {
+ return GetTagValue<ushort>("SceneCaptureType");
+ }
+ set
+ {
+ SetTagValue("SceneCaptureType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the degree of overall image gain adjustment.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>none</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>low gain up</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>high gain up</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>low gain down</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>high gain down</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? GainControl
+ {
+ get
+ {
+ return GetTagValue<ushort>("GainControl");
+ }
+ set
+ {
+ SetTagValue("GainControl", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of contrast processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>soft</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>hard</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Contrast
+ {
+ get
+ {
+ return GetTagValue<ushort>("Contrast");
+ }
+ set
+ {
+ SetTagValue("Contrast", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of saturation processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>low saturation</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>high saturation</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Saturation
+ {
+ get
+ {
+ return GetTagValue<ushort>("Saturation");
+ }
+ set
+ {
+ SetTagValue("Saturation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of sharpness processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>soft</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>hard</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Sharpness
+ {
+ get
+ {
+ return GetTagValue<ushort>("Sharpness");
+ }
+ set
+ {
+ SetTagValue("Sharpness", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets information on the picture-taking conditions of a particular camera model.
+ /// The tag is used only to indicate the picture-taking conditions in the reader.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] DeviceSettingDescription
+ {
+ get
+ {
+ return GetTagArray<byte>("DeviceSettingDescription");
+ }
+ set
+ {
+ SetTagValueUndefined("DeviceSettingDescription", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the distance to the subject.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>macro</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>close view</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>distant view</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SubjectDistanceRange
+ {
+ get
+ {
+ return GetTagValue<ushort>("SubjectDistanceRange");
+ }
+ set
+ {
+ SetTagValue("SubjectDistanceRange", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets an identifier assigned uniquely to each image.
+ /// It is recorded as an ASCII string equivalent to hexadecimal notation and 128-bit fixed length.
+ /// Constant length of 32.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageUniqueID
+ {
+ get
+ {
+ string text = GetTagText("ImageUniqueID");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ FreeImage.Resize(ref value, 32);
+ value += '\0';
+ }
+ SetTagValue("ImageUniqueID", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_GPS"/>.
+ /// </summary>
+ public class MDM_EXIF_GPS : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_GPS(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_GPS; }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS version ID. Constant length of 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] VersionID
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSVersionID");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValue("GPSVersionID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the <see cref="Latitude"/>
+ /// is north or south latitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public LatitudeType? LatitudeDirection
+ {
+ get
+ {
+ return ToLatitudeType(GetTagText("GPSLatitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSLatitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the latitude of the image. The latitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="LatitudeDirection"/>
+ public FIURational[] Latitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSLatitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSLatitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether <see cref="Longitude"/>
+ /// is east or west longitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public LongitudeType? LongitudeDirection
+ {
+ get
+ {
+ return ToLongitudeType(GetTagText("GPSLongitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSLongitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the longitude of the image. The longitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="LongitudeDirection"/>
+ public FIURational[] Longitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSLongitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSLongitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether <see cref="Altitude"/> is sea level and the altitude
+ /// is above sea level. If the altitude is below sea level <see cref="Altitude"/> is
+ /// indicated as an absolute value.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public AltitudeType? AltitudeDirection
+ {
+ get
+ {
+ byte? flag = GetTagValue<byte>("GPSAltitudeRef");
+ if (flag.HasValue)
+ {
+ switch (flag.Value)
+ {
+ case 0:
+ return AltitudeType.AboveSeaLevel;
+ case 1:
+ return AltitudeType.BelowSeaLevel;
+ default:
+ return AltitudeType.Undefined;
+ }
+ }
+ return null;
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ switch (value.Value)
+ {
+ case AltitudeType.AboveSeaLevel:
+ val = 0;
+ break;
+
+ case AltitudeType.BelowSeaLevel:
+ val = 1;
+ break;
+
+ default:
+ val = 2;
+ break;
+ }
+ }
+ SetTagValue("GPSAltitudeRef", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the altitude based on the reference in <see cref="AltitudeDirection"/>.
+ /// Altitude is expressed as one rational value. The reference unit is meters.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? Altitude
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSAltitude");
+ }
+ set
+ {
+ SetTagValue("GPSAltitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the sign of the <see cref="SignedAltitude"/>.
+ /// </summary>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public int? AltitudeSign
+ {
+ get
+ {
+ AltitudeType? seaLevel = AltitudeDirection;
+ if (seaLevel.HasValue)
+ {
+ return (seaLevel.Value == AltitudeType.BelowSeaLevel) ? -1 : 1;
+ }
+ return null;
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ AltitudeDirection = value.Value >= 0 ? AltitudeType.AboveSeaLevel : AltitudeType.BelowSeaLevel;
+ }
+ else
+ {
+ AltitudeDirection = null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the signed altitude.
+ /// Altitude is expressed as one rational value. The reference unit is meters.
+ /// </summary>
+ /// <exception cref="OverflowException">
+ /// Altitude is too large to fit into a FIRational.
+ /// </exception>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? SignedAltitude
+ {
+ get
+ {
+ FIRational? result = null;
+ FIURational? altitude = Altitude;
+ if (altitude.HasValue)
+ {
+ int sign = AltitudeSign ?? 1;
+ if (((int)altitude.Value.Numerator < 0) || ((int)altitude.Value.Denominator < 0))
+ throw new OverflowException();
+ result = new FIRational((int)altitude.Value.Numerator * sign, (int)altitude.Value.Denominator);
+ }
+ return result;
+ }
+ set
+ {
+ FIURational? val = null;
+ if (value.HasValue)
+ {
+ if (value.Value < 0)
+ {
+ AltitudeSign = -1;
+ value = -value.Value;
+ }
+ else
+ {
+ AltitudeSign = 1;
+ }
+ val = new FIURational((uint)value.Value.Numerator, (uint)value.Value.Denominator);
+ }
+ Altitude = val;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets or sets the time as UTC (Coordinated Universal Time). Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public TimeSpan? TimeStamp
+ {
+ get
+ {
+ FIURational[] stamp = GetTagArray<FIURational>("GPSTimeStamp");
+ if ((stamp == null) || stamp.Length != 3)
+ {
+ return null;
+ }
+ else
+ {
+ return new TimeSpan((int)stamp[0], (int)stamp[1], (int)stamp[2]);
+ }
+ }
+ set
+ {
+ FIURational[] stamp = null;
+ if (value.HasValue)
+ {
+ TimeSpan span = value.Value;
+ stamp = new FIURational[3];
+ stamp[0] = span.Hours;
+ stamp[1] = span.Minutes;
+ stamp[2] = span.Seconds;
+ }
+ SetTagValue("GPSTimeStamp", stamp);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS satellites used for measurements. This tag can be used to describe
+ /// the number of satellites, their ID number, angle of elevation, azimuth, SNR and other
+ /// information in ASCII notation. The format is not specified.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Satellites
+ {
+ get
+ {
+ string result = GetTagText("GPSSatellites");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("GPSTimeStamp", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the status of the GPS receiver when the image was recorded.
+ /// <b>true</b> indicates measurement was in progress;
+ /// <b>false</b> indicates measurement was Interoperability.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? Status
+ {
+ get
+ {
+ string text = GetTagText("GPSStatus");
+ return string.IsNullOrEmpty(text) ? default(bool?) : text[0] == 'A';
+ }
+ set
+ {
+ SetTagValue("GPSStatus", value.HasValue ? (value.Value ? "A\0" : "V\0") : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the GPS measurement mode.
+ /// <b>true</b> indicates three-dimensional measurement;
+ /// <b>false</b> indicated two-dimensional measurement was in progress.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? MeasureMode3D
+ {
+ get
+ {
+ string text = GetTagText("GPSMeasureMode");
+ return string.IsNullOrEmpty(text) ? default(bool?) : text[0] == '3';
+ }
+ set
+ {
+ SetTagValue("GPSMeasureMode", value.HasValue ? (value.Value ? "3\0" : "2\0") : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS DOP (data degree of precision). An HDOP value is written during
+ /// two-dimensional measurement, and PDOP during three-dimensional measurement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? DOP
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSDOP");
+ }
+ set
+ {
+ SetTagValue("GPSDOP", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit used to express the GPS receiver <see cref="Speed"/> of movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Speed"/>
+ public VelocityUnit? SpeedUnit
+ {
+ get
+ {
+ return ToUnitType(GetTagText("GPSSpeedRef"));
+ }
+ set
+ {
+ SetTagValue("GPSSpeedRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the speed of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="SpeedUnit"/>
+ public FIURational? Speed
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSSpeed");
+ }
+ set
+ {
+ SetTagValue("GPSSpeed", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference for giving the direction of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Track"/>
+ public DirectionReference? TrackDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSTrackRef"));
+ }
+ set
+ {
+ SetTagValue("GPSTrackRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of GPS receiver movement.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="TrackDirectionReference"/>
+ public FIURational? Track
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSTrack");
+ }
+ set
+ {
+ SetTagValue("GPSTrack", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference for giving the direction of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="ImageDirection"/>
+ public DirectionReference? ImageDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSImgDirectionRef"));
+ }
+ set
+ {
+ SetTagValue("GPSImgDirectionRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of the image when it was captured.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="ImageDirectionReference"/>
+ public FIURational? ImageDirection
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSImgDirection");
+ }
+ set
+ {
+ SetTagValue("GPSImgDirection", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the geodetic survey data used by the GPS receiver. If the survey data
+ /// is restricted to Japan, the value of this tag is 'TOKYO' or 'WGS-84'.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string MapDatum
+ {
+ get
+ {
+ string result = GetTagText("GPSMapDatum");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ SetTagValue("GPSMapDatum", value + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the destination point
+ /// is north or south latitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Latitude"/>
+ public LatitudeType? DestinationLatitudeDirection
+ {
+ get
+ {
+ return ToLatitudeType(GetTagText("GPSDestLatitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestLatitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the latitude of the destination point. The latitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationLatitudeDirection"/>
+ public FIURational[] DestinationLatitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSDestLatitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSDestLatitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the destination point
+ /// is east or west longitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Latitude"/>
+ public LongitudeType? DestinationLongitudeDirection
+ {
+ get
+ {
+ return ToLongitudeType(GetTagText("GPSDestLongitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestLongitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the longitude of the destination point. The longitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] DestinationLongitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSDestLongitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSDestLongitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference used for giving the bearing to the destination point.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationBearing"/>
+ public DirectionReference? DestinationDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSDestBearingRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestBearingRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the bearing to the destination point.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationDirectionReference"/>
+ public FIURational? DestinationBearing
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSDestBearing");
+ }
+ set
+ {
+ SetTagValue("GPSDestBearing", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit used to express the distance to the destination point.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationBearing"/>
+ public VelocityUnit? DestinationUnit
+ {
+ get
+ {
+ return ToUnitType(GetTagText("GPSDestDistanceRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestDistanceRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a character string recording the name of the method used
+ /// for location finding. The first byte indicates the character code used,
+ /// and this is followed by the name of the method. Since the Type is not ASCII,
+ /// NULL termination is not necessary.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ProcessingMethod
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSProcessingMethod");
+ }
+ set
+ {
+ SetTagValue("GPSProcessingMethod", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a character string recording the name of the GPS area.
+ /// The first byte indicates the character code used, and this is followed by
+ /// the name of the GPS area. Since the Type is not ASCII, NULL termination is
+ /// not necessary.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] AreaInformation
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSAreaInformation");
+ }
+ set
+ {
+ SetTagValue("GPSAreaInformation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets date and time information relative to UTC (Coordinated Universal Time).
+ /// </summary>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeStamp
+ {
+ get
+ {
+ DateTime? date = DateStamp;
+ TimeSpan? time = TimeStamp;
+ if ((date == null) && (time == null))
+ {
+ return null;
+ }
+ else
+ {
+ if (date == null)
+ {
+ date = DateTime.MinValue;
+ }
+ if (time == null)
+ {
+ time = TimeSpan.MinValue;
+ }
+ return date.Value.Add(time.Value);
+ }
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ DateStamp = value.Value.Date;
+ TimeStamp = value.Value.TimeOfDay;
+ }
+ else
+ {
+ DateStamp = null;
+ TimeStamp = null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets date information relative to UTC (Coordinated Universal Time).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateStamp
+ {
+ get
+ {
+ string stamp = GetTagText("GPSDateStamp");
+ if (stamp != null)
+ {
+ try
+ {
+ return DateTime.ParseExact(stamp, "yyyy:MM:dd\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return null;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("GPSDateStamp", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether differential correction was applied to
+ /// the GPS receiver.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? IsDifferential
+ {
+ get
+ {
+ ushort? value = GetTagValue<ushort>("GPSDifferential");
+ return value.HasValue ? (value != 0) : (default(bool?));
+ }
+ set
+ {
+ SetTagValue("GPSDifferential", value.HasValue ? (object)(value.Value ? (ushort)1 : (ushort)0) : (null));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_INTEROP"/>.
+ /// </summary>
+ public class MDM_INTEROP : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_INTEROP(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_INTEROP; }
+ }
+
+ /// <summary>
+ /// Gets or sets the identification of the Interoperability rule.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public InteroperabilityMode? Identification
+ {
+ get
+ {
+ return ToInteroperabilityType(GetTagText("InteroperabilityIndex"));
+ }
+ set
+ {
+ SetTagValue("InteroperabilityIndex", ToString(value) + '\0');
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN"/>.
+ /// <para/>
+ /// <b>This class is obsolete. Use class <see cref="MDM_EXIF_MAIN"/> instead.</b>
+ /// </summary>
+ [Obsolete("To be removed in future releases. Use MDM_EXIF_MAIN instead.")]
+ public class MDM_MAIN : MDM_EXIF_MAIN
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_MAIN(FIBITMAP dib) : base(dib) { }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN"/>.
+ /// </summary>
+ public class MDM_EXIF_MAIN : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_MAIN(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN; }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of columns of image data, equal to the number
+ /// of pixels per row. In JPEG compressed data a JPEG marker is used
+ /// instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? ImageWidth
+ {
+ get
+ {
+ return GetUInt32Value("ImageWidth");
+ }
+ set
+ {
+ RemoveTag("ImageWidth");
+ if (value.HasValue)
+ {
+ SetTagValue("ImageWidth", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of rows of image data. In JPEG compressed data a JPEG marker
+ /// is used instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? ImageHeight
+ {
+ get
+ {
+ return GetUInt32Value("ImageLength");
+ }
+ set
+ {
+ RemoveTag("ImageLength");
+ if (value.HasValue)
+ {
+ SetTagValue("ImageLength", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of bits per image component. In this standard
+ /// each component of the image is 8 bits, so the value for this tag is 8.
+ /// Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] BitsPerSample
+ {
+ get
+ {
+ return GetTagArray<ushort>("BitsPerSample");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("BitsPerSample", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets compression scheme used for the image data. When a primary image
+ /// is JPEG compressed, this designation is not necessary and is omitted.
+ /// When thumbnails use JPEG compression, this tag value is set to 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Compression
+ {
+ get
+ {
+ return GetTagValue<ushort>("Compression");
+ }
+ set
+ {
+ SetTagValue("Compression", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets pixel composition. In JPEG compressed data a JPEG marker is
+ /// used instead of this tag. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>2</term>
+ /// <description>RGB</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>YCbCr</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? PhotometricInterpretation
+ {
+ get
+ {
+ return GetTagValue<ushort>("PhotometricInterpretation");
+ }
+ set
+ {
+ SetTagValue("PhotometricInterpretation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image orientation viewed in terms of rows and columns.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ExifImageOrientation? Orientation
+ {
+ get
+ {
+ return (ExifImageOrientation?)GetTagValue<ushort>("Orientation");
+ }
+ set
+ {
+ SetTagValue("Orientation", (ushort?)value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of components per pixel. Since this standard applies
+ /// to RGB and YCbCr images, the value set for this tag is 3. In JPEG compressed
+ /// data a JPEG marker is used instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SamplesPerPixel
+ {
+ get
+ {
+ return GetTagValue<ushort>("SamplesPerPixel");
+ }
+ set
+ {
+ SetTagValue("SamplesPerPixel", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that indicates whether pixel components are recorded in
+ /// chunky or planar format. In JPEG compressed files a JPEG marker is used instead
+ /// of this tag. If this field does not exist, the TIFF default of 1 (chunky) is assumed.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>chunky format</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>planar format</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? PlanarConfiguration
+ {
+ get
+ {
+ return GetTagValue<ushort>("PlanarConfiguration");
+ }
+ set
+ {
+ SetTagValue("PlanarConfiguration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the sampling ratio of chrominance components in relation to
+ /// the luminance component. In JPEG compressed dat a JPEG marker is used
+ /// instead of this tag.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>[2,1]</term>
+ /// <description>YCbCr4:2:2</description>
+ /// </item>
+ /// <item>
+ /// <term>[2,2]</term>
+ /// <description>YCbCr4:2:0</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] YCbCrSubSampling
+ {
+ get
+ {
+ return GetTagArray<ushort>("YCbCrSubSampling");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2);
+ SetTagValue("YCbCrSubSampling", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets position of chrominance components in relation to the luminance component.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// This field is designated only for JPEG compressed data or uncompressed YCbCr data.
+ /// The TIFF default is 1 (centered); but when Y:Cb:Cr = 4:2:2 it is recommended in
+ /// this standard that 2 (co-sited) be used to record data, in order to improve the
+ /// image quality when viewed on TV systems.
+ /// <para/>
+ /// When this field does not exist, the reader shall assume the TIFF default.
+ /// In the case of Y:Cb:Cr = 4:2:0, the TIFF default (centered) is recommended.
+ /// If the reader does not have the capability of supporting both kinds of YCbCrPositioning,
+ /// it shall follow the TIFF default regardless of the value in this field.
+ /// It is preferable that readers be able to support both centered and co-sited positioning.
+ /// <para/>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>centered</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>co-sited</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? YCbCrPositioning
+ {
+ get
+ {
+ return GetTagValue<ushort>("YCbCrPositioning");
+ }
+ set
+ {
+ SetTagValue("YCbCrPositioning", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels per <see cref="ResolutionUnit"/>
+ /// in the <see cref="ImageWidth"/> direction. When the image resolution is unknown,
+ /// 72 [dpi] is designated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? XResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("XResolution");
+ }
+ set
+ {
+ SetTagValue("XResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels per <see cref="ResolutionUnit"/>
+ /// in the <see cref="ImageHeight"/> direction. When the image resolution is unknown,
+ /// 72 [dpi] is designated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? YResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("YResolution");
+ }
+ set
+ {
+ SetTagValue("YResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit for measuring <see cref="XResolution"/> and <see cref="YResolution"/>.
+ /// The same unit is used for both <see cref="XResolution"/> and <see cref="YResolution"/>.
+ /// If the image resolution in unknown, 2 (inches) is designated.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>2</term>
+ /// <description>inches</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>YCbCr4:2:0</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>centimeters</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ResolutionUnit
+ {
+ get
+ {
+ return GetTagValue<ushort>("ResolutionUnit");
+ }
+ set
+ {
+ SetTagValue("ResolutionUnit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the byte offset of that strip.
+ /// It is recommended that this be selected so the number of strip bytes
+ /// does not exceed 64 Kbytes.
+ /// With JPEG compressed data this designation is not needed and is omitted.
+ /// Constant length of <see cref="SamplesPerPixel"/> * StripsPerImage.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="RowsPerStrip"/>
+ /// <see cref="StripByteCounts"/>
+ public uint[] StripOffsets
+ {
+ get
+ {
+ return GetUInt32Array("StripOffsets");
+ }
+ set
+ {
+ RemoveTag("StripOffsets");
+ if (value != null)
+ {
+ SetTagValue("StripOffsets", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of rows per strip. This is the number of rows in the image of
+ /// one strip when an image is divided into strips. With JPEG compressed data this
+ /// designation is not needed and is omitted.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="StripByteCounts"/>
+ public uint? RowsPerStrip
+ {
+ get
+ {
+ return GetUInt32Value("RowsPerStrip");
+ }
+ set
+ {
+ RemoveTag("RowsPerStrip");
+ if (value.HasValue)
+ {
+ SetTagValue("RowsPerStrip", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the total number of bytes in each strip.
+ /// With JPEG compressed data this designation is not needed and is omitted.
+ /// Constant length of <see cref="SamplesPerPixel"/> * StripsPerImage.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint[] StripByteCounts
+ {
+ get
+ {
+ return GetUInt32Array("StripByteCounts");
+ }
+ set
+ {
+ RemoveTag("StripByteCounts");
+ if (value != null)
+ {
+ SetTagValue("StripByteCounts", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the offset to the start byte (SOI) of JPEG compressed thumbnail data.
+ /// This is not used for primary image JPEG data.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPEGInterchangeFormat
+ {
+ get
+ {
+ return GetTagValue<uint>("JPEGInterchangeFormat");
+ }
+ set
+ {
+ SetTagValue("JPEGInterchangeFormat", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of bytes of JPEG compressed thumbnail data.
+ /// </summary>
+ /// <remarks>
+ /// This is not used for primary image JPEG data.
+ /// JPEG thumbnails are not divided but are recorded as a continuous
+ /// JPEG bitstream from SOI to EOI. APPn and COM markers should not be recorded.
+ /// Compressed thumbnails shall be recorded in no more than 64 Kbytes,
+ /// including all other data to be recorded in APP1.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPEGInterchangeFormatLength
+ {
+ get
+ {
+ return GetTagValue<uint>("JPEGInterchangeFormatLength");
+ }
+ set
+ {
+ SetTagValue("JPEGInterchangeFormatLength", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a transfer function for the image, described in tabular style.
+ /// Constant length of 3 * 256.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] TransferFunction
+ {
+ get
+ {
+ return GetTagArray<ushort>("TransferFunction");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3 * 256);
+ SetTagValue("TransferFunction", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the chromaticity of the white point of the image.
+ /// Constant length of 2.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] WhitePoint
+ {
+ get
+ {
+ return GetTagArray<FIURational>("WhitePoint");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2);
+ SetTagValue("WhitePoint", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the chromaticity of the three primary colors of the image.
+ /// Constant length of 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] PrimaryChromaticities
+ {
+ get
+ {
+ return GetTagArray<FIURational>("PrimaryChromaticities");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 6);
+ SetTagValue("PrimaryChromaticities", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the matrix coefficients for transformation from RGB to YCbCr image data.
+ /// Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] YCbCrCoefficients
+ {
+ get
+ {
+ return GetTagArray<FIURational>("YCbCrCoefficients");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("PrimaryChromaticities", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference black point value and reference white point value.
+ /// Constant length of 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] ReferenceBlackWhite
+ {
+ get
+ {
+ return GetTagArray<FIURational>("ReferenceBlackWhite");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 6);
+ SetTagValue("ReferenceBlackWhite", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time of image creation.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTime
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTime");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTime", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a string giving the title of the image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageDescription
+ {
+ get
+ {
+ string result = GetTagText("ImageDescription");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("ImageDescription", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the manufacturer of the recording equipment.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Make
+ {
+ get
+ {
+ string result = GetTagText("Make");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Make", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the model name or model number of the equipment.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EquipmentModel
+ {
+ get
+ {
+ string result = GetTagText("Model");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Model", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name and version of the software or firmware of the camera
+ /// or image input device used to generate the image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Software
+ {
+ get
+ {
+ string result = GetTagText("Software");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Software", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of the camera owner, photographer or image creator.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Artist
+ {
+ get
+ {
+ string result = GetTagText("Artist");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Artist", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the photographer and editor copyrights.
+ /// Constant length of 1-2.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string[] Copyright
+ {
+ get
+ {
+ string[] result = null;
+ string text = GetTagText("Copyright");
+ if (!string.IsNullOrEmpty(text))
+ {
+ result = text.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value != null)
+ {
+ if (value.Length == 1)
+ {
+ if (value[0] != null)
+ {
+ val = value[0] + '\0';
+ }
+ }
+ else if (value.Length == 2)
+ {
+ if ((value[0] != null) && (value[1] != null))
+ {
+ val = value[0] + '\0' + value[1] + '\0';
+ }
+ }
+ }
+ SetTagValue("Copyright", val);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAKERNOTE"/>.
+ /// </summary>
+ public class MDM_MAKERNOTE : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_MAKERNOTE(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_MAKERNOTE; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_GEOTIFF"/>.
+ /// </summary>
+ public class MDM_GEOTIFF : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_GEOTIFF(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_GEOTIFF; }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoASCIIParamsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoASCIIParamsTag is used to store all of the <see cref="String"/> valued
+ /// GeoKeys, referenced by the <see cref="GeoKeyDirectory"/> property. Since keys
+ /// defined in the GeoKeyDirectoryTag use offsets into this tag, any special
+ /// comments may be placed at the beginning of this tag.
+ /// For the most part, the only keys that are <see cref="String"/> valued are
+ /// <i>Citation</i> keys, giving documentation and references for obscure
+ /// projections, datums, etc.
+ /// <para/>
+ /// Special handling is required for <see cref="String"/>-valued keys. While it
+ /// is true that TIFF 6.0 permits multiple NULL-delimited strings within a single
+ /// ASCII tag, the secondary strings might not appear in the output of naive
+ /// <i>tiffdump</i> programs. For this reason, the NULL delimiter of each ASCII key
+ /// value shall be converted to a "|" (pipe) character before being installed
+ /// back into the <see cref="String"/> holding tag, so that a dump of the tag
+ /// will look like this.
+ /// <para/>
+ /// AsciiTag="first_value|second_value|etc...last_value|"
+ /// <para/>
+ /// A baseline GeoTIFF-reader must check for and convert the final "|" pipe
+ /// character of a key back into a NULL before returning it to the client
+ /// software.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string GeoASCIIParams
+ {
+ get
+ {
+ string text = GetTagText("GeoASCIIParams");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("GeoASCIIParams", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoDoubleParamsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoDoubleParamsTag is used to store all of the <see cref="Double"/> valued
+ /// GeoKeys, referenced by the <see cref="GeoKeyDirectory"/> property. The meaning of
+ /// any value of this double array is determined from the GeoKeyDirectoryTag reference
+ /// pointing to it. <see cref="Single"/> values should first be converted to
+ /// <see cref="Double"/> and stored here.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] GeoDoubleParams
+ {
+ get
+ {
+ return GetTagArray<double>("GeoDoubleParams");
+ }
+ set
+ {
+ SetTagValue("GeoDoubleParams", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoKeyDirectoryTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoKeyDirectoryTag may be used to store the GeoKey Directory, which defines and
+ /// references the <i>GeoKeys</i>.
+ /// <para/>
+ /// The tag is an array of unsigned <see cref="UInt16"/> values, which are primarily
+ /// grouped into blocks of 4. The first 4 values are special, and contain GeoKey directory
+ /// header information. The header values consist of the following information, in order:
+ /// <para/>
+ /// Header={KeyDirectoryVersion, KeyRevision, MinorRevision, NumberOfKeys}
+ /// <para/>
+ /// where
+ /// <para/>
+ /// <i>KeyDirectoryVersion</i> indicates the current version of Key implementation, and will
+ /// only change if this Tag's Key structure is changed. (Similar to the TIFFVersion (42)).
+ /// The current DirectoryVersion number is 1. This value will most likely never change,
+ /// and may be used to ensure that this is a valid Key-implementation.
+ /// <para/>
+ /// <i>KeyRevision</i> indicates what revision of Key-Sets are used.
+ /// <para/>
+ /// <i>MinorRevision</i> indicates what set of Key-Codes are used. The complete revision number
+ /// is denoted &lt;KeyRevision&gt;.&lt;MinorRevision&gt;.
+ /// <para/>
+ /// <i>NumberOfKeys</i> indicates how many Keys are defined by the rest of this Tag.
+ /// <para/>
+ /// This header is immediately followed by a collection of &lt;NumberOfKeys&gt; KeyEntry
+ /// sets, each of which is also 4-<see cref="UInt16"/> long. Each KeyEntry is modeled on the
+ /// <i>TIFFEntry</i> format of the TIFF directory header, and is of the form:
+ /// <para/>
+ /// KeyEntry = { KeyID, TIFFTagLocation, Count, Value_Offset }
+ /// <para/>
+ /// where
+ /// <para/>
+ /// <i>KeyID</i> gives the Key-ID value of the Key (identical in function to TIFF tag ID,
+ /// but completely independent of TIFF tag-space),
+ /// <para/>
+ /// <i>TIFFTagLocation</i> indicates which TIFF tag contains the value(s) of the Key: if
+ /// TIFFTagLocation is 0, then the value is <see cref="UInt16"/>, and is contained in the
+ /// <i>Value_Offset</i> entry. Otherwise, the type (format) of the value is implied by the
+ /// TIFF-Type of the tag containing the value.
+ /// <para/>
+ /// <i>Count</i> indicates the number of values in this key.
+ /// <para/>
+ /// <i>Value_Offset</i> Value_Offset indicates the index-offset into the TagArray indicated
+ /// by TIFFTagLocation, if it is nonzero. If TIFFTagLocation is 0 (zero) , then Value_Offset
+ /// contains the actual (<see cref="UInt16"/>) value of the Key, and Count=1 is implied.
+ /// Note that the offset is not a byte-offset, but rather an index based on the natural data
+ /// type of the specified tag array.
+ /// <para/>
+ /// Following the KeyEntry definitions, the KeyDirectory tag may also contain additional
+ /// values. For example, if a key requires multiple <see cref="UInt16"/> values, they shall
+ /// be placed at the end of this tag, and the KeyEntry will set
+ /// TIFFTagLocation=GeoKeyDirectoryTag, with the Value_Offset pointing to the location of the
+ /// value(s).
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] GeoKeyDirectory
+ {
+ get
+ {
+ return GetTagArray<ushort>("GeoKeyDirectory");
+ }
+ set
+ {
+ SetTagValue("GeoKeyDirectory", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF ModelPixelScaleTag.
+ /// </summary>
+ /// <remarks>
+ /// The ModelPixelScaleTag tag may be used to specify the size of raster pixel spacing
+ /// in the model space units, when the raster space can be embedded in the model space
+ /// coordinate system without rotation, and consists of the following 3 values:
+ /// <para/>
+ /// ModelPixelScaleTag = (ScaleX, ScaleY, ScaleZ)
+ /// <para/>
+ /// where <i>ScaleX</i> and <i>ScaleY</i> give the horizontal and vertical spacing of
+ /// raster pixels. The <i>ScaleZ</i> is primarily used to map the pixel value of a
+ /// digital elevation model into the correct Z-scale, and so for most other purposes
+ /// this value should be zero (since most model spaces are 2-D, with Z=0).
+ /// <para/>
+ /// A single tiepoint in the <see cref="ModelTiePoints"/> tag, together with this tag,
+ /// completely determine the relationship between raster and model space; thus they
+ /// comprise the two tags which Baseline GeoTIFF files most often will use to place a
+ /// raster image into a "standard position" in model space.
+ /// <para/>
+ /// Like the <see cref="ModelTiePoints"/> tag, this tag information is independent of the
+ /// XPosition, YPosition, Resolution and Orientation tags of the standard TIFF 6.0 spec.
+ /// However, simple reversals of orientation between raster and model space
+ /// (e.g. horizontal or vertical flips) may be indicated by reversal of sign in the
+ /// corresponding component of the ModelPixelScaleTag. GeoTIFF compliant readers must
+ /// honor this signreversal convention.
+ /// <para/>
+ /// This tag must not be used if the raster image requires rotation or shearing to place
+ /// it into the standard model space. In such cases the transformation shall be defined
+ /// with the more general <see cref="ModelTransformationMatrix"/>.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoPixelScale</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelPixelScale"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoPixelScale</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelPixelScale
+ {
+ get
+ {
+ return GetTagArray<double>("GeoPixelScale");
+ }
+ set
+ {
+ SetTagValue("GeoPixelScale", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoTiePointsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoTiePointsTag stores raster -> model tiepoint pairs in the order
+ /// <para/>
+ /// ModelTiePoints = (...,I,J,K, X,Y,Z...),
+ /// <para/>
+ /// where <i>(I,J,K)</i> is the point at location <i>(I,J)</i> in raster space with
+ /// pixel-value <i>K</i>, and <i>(X,Y,Z)</i> is a vector in model space. In most cases
+ /// the model space is only two-dimensional, in which case both K and Z should be set
+ /// to zero; this third dimension is provided in anticipation of future support for 3D
+ /// digital elevation models and vertical coordinate systems.
+ /// <para/>
+ /// A raster image may be georeferenced simply by specifying its location, size and
+ /// orientation in the model coordinate space M. This may be done by specifying the
+ /// location of three of the four bounding corner points. However, tiepoints are only
+ /// to be considered exact at the points specified; thus defining such a set of
+ /// bounding tiepoints does not imply that the model space locations of the interior
+ /// of the image may be exactly computed by a linear interpolation of these tiepoints.
+ /// <para/>
+ /// However, since the relationship between the Raster space and the model space will
+ /// often be an exact, affine transformation, this relationship can be defined using
+ /// one set of tiepoints and the <see cref="ModelPixelScale"/>, described below, which
+ /// gives the vertical and horizontal raster grid cell size, specified in model units.
+ /// <para/>
+ /// If possible, the first tiepoint placed in this tag shall be the one establishing
+ /// the location of the point (0,0) in raster space. However, if this is not possible
+ /// (for example, if (0,0) is goes to a part of model space in which the projection is
+ /// ill-defined), then there is no particular order in which the tiepoints need be
+ /// listed.
+ /// <para/>
+ /// For orthorectification or mosaicking applications a large number of tiepoints may
+ /// be specified on a mesh over the raster image. However, the definition of associated
+ /// grid interpolation methods is not in the scope of the current GeoTIFF spec.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoTiePoints</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelTiePoints"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoTiePoints</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelTiePoints
+ {
+ get
+ {
+ return GetTagArray<double>("GeoTiePoints");
+ }
+ set
+ {
+ SetTagValue("GeoTiePoints", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF ModelTransformationMatrixTag.
+ /// </summary>
+ /// <remarks>
+ /// This tag may be used to specify the transformation matrix between the raster space
+ /// (and its dependent pixel-value space) and the (possibly 3D) model space.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoTransformationMatrix</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelTransformationMatrix"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoTransformationMatrix</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelTransformationMatrix
+ {
+ get
+ {
+ return GetTagArray<double>("GeoTransformationMatrix");
+ }
+ set
+ {
+ SetTagValue("GeoTransformationMatrix", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF IntergraphTransformationMatrixTag.
+ /// </summary>
+ /// <remarks>
+ /// The IntergraphTransformationMatrixTag conflicts with an internal software implementation
+ /// at Intergraph, and so its use is no longer encouraged. A GeoTIFF reader should look first
+ /// for the new tag, and only if it is not found should it check for this older tag. If found,
+ /// it should only consider it to be contain valid GeoTIFF matrix information if the tag-count
+ /// is 16; the Intergraph version uses 17 values.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] IntergraphTransformationMatrix
+ {
+ get
+ {
+ return GetTagArray<double>("Intergraph TransformationMatrix");
+ }
+ set
+ {
+ SetTagValue("Intergraph TransformationMatrix", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF JPLCartoIFDOffsetTag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPLCartoIFDOffset
+ {
+ get
+ {
+ return GetTagValue<uint>("JPL Carto IFD offset");
+ }
+ set
+ {
+ SetTagValue("JPL Carto IFD offset", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_IPTC"/>.
+ /// </summary>
+ public class MDM_IPTC : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_IPTC(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_IPTC; }
+ }
+
+ /// <summary>
+ /// Gets the Application Record Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public short? ApplicationRecordVersion
+ {
+ get
+ {
+ return GetTagValue<short>("ApplicationRecordVersion");
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Type Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectTypeReference
+ {
+ get
+ {
+ return GetTagText("ObjectTypeReference");
+ }
+ set
+ {
+ SetTagValue("ObjectTypeReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Attribute Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectAttributeReference
+ {
+ get
+ {
+ return GetTagText("ObjectAttributeReference");
+ }
+ set
+ {
+ SetTagValue("ObjectAttributeReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Name.
+ /// This is also referred to as Title.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectName
+ {
+ get
+ {
+ return GetTagText("ObjectName");
+ }
+ set
+ {
+ SetTagValue("ObjectName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Edit Status.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EditStatus
+ {
+ get
+ {
+ return GetTagText("EditStatus");
+ }
+ set
+ {
+ SetTagValue("EditStatus", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Editorial Update.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EditorialUpdate
+ {
+ get
+ {
+ return GetTagText("EditorialUpdate");
+ }
+ set
+ {
+ SetTagValue("EditorialUpdate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Urgency.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Urgency
+ {
+ get
+ {
+ return GetTagText("Urgency");
+ }
+ set
+ {
+ SetTagValue("Urgency", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Subject Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubjectReference
+ {
+ get
+ {
+ return GetTagText("SubjectReference");
+ }
+ set
+ {
+ SetTagValue("SubjectReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Category.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Category
+ {
+ get
+ {
+ return GetTagText("Category");
+ }
+ set
+ {
+ SetTagValue("Category", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Supplemental Categories.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SupplementalCategories
+ {
+ get
+ {
+ return GetTagText("SupplementalCategories");
+ }
+ set
+ {
+ SetTagValue("SupplementalCategories", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Fixture Identifier.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string FixtureIdentifier
+ {
+ get
+ {
+ return GetTagText("FixtureIdentifier");
+ }
+ set
+ {
+ SetTagValue("FixtureIdentifier", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Keywords.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Keywords
+ {
+ get
+ {
+ return GetTagText("Keywords");
+ }
+ set
+ {
+ SetTagValue("Keywords", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Content Location Code.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ContentLocationCode
+ {
+ get
+ {
+ return GetTagText("ContentLocationCode");
+ }
+ set
+ {
+ SetTagValue("ContentLocationCode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Content Location Name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ContentLocationName
+ {
+ get
+ {
+ return GetTagText("ContentLocationName");
+ }
+ set
+ {
+ SetTagValue("ContentLocationName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Release Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReleaseDate
+ {
+ get
+ {
+ return GetTagText("ReleaseDate");
+ }
+ set
+ {
+ SetTagValue("ReleaseDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Release Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReleaseTime
+ {
+ get
+ {
+ return GetTagText("ReleaseTime");
+ }
+ set
+ {
+ SetTagValue("ReleaseTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Expiration Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExpirationDate
+ {
+ get
+ {
+ return GetTagText("ExpirationDate");
+ }
+ set
+ {
+ SetTagValue("ExpirationDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Expiration Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExpirationTime
+ {
+ get
+ {
+ return GetTagText("ExpirationTime");
+ }
+ set
+ {
+ SetTagValue("ExpirationTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Special Instructions.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SpecialInstructions
+ {
+ get
+ {
+ return GetTagText("SpecialInstructions");
+ }
+ set
+ {
+ SetTagValue("SpecialInstructions", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Action Advised.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ActionAdvised
+ {
+ get
+ {
+ return GetTagText("ActionAdvised");
+ }
+ set
+ {
+ SetTagValue("ActionAdvised", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Service.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceService
+ {
+ get
+ {
+ return GetTagText("ReferenceService");
+ }
+ set
+ {
+ SetTagValue("ReferenceService", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceDate
+ {
+ get
+ {
+ return GetTagText("ReferenceDate");
+ }
+ set
+ {
+ SetTagValue("ReferenceDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceNumber
+ {
+ get
+ {
+ return GetTagText("ReferenceNumber");
+ }
+ set
+ {
+ SetTagValue("ReferenceNumber", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Date Created.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DateCreated
+ {
+ get
+ {
+ return GetTagText("DateCreated");
+ }
+ set
+ {
+ SetTagValue("DateCreated", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Time Created.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string TimeCreated
+ {
+ get
+ {
+ return GetTagText("TimeCreated");
+ }
+ set
+ {
+ SetTagValue("TimeCreated", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Digital Creation Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DigitalCreationDate
+ {
+ get
+ {
+ return GetTagText("DigitalCreationDate");
+ }
+ set
+ {
+ SetTagValue("DigitalCreationDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Digital Creation Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DigitalCreationTime
+ {
+ get
+ {
+ return GetTagText("DigitalCreationTime");
+ }
+ set
+ {
+ SetTagValue("DigitalCreationTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Originating Program.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OriginatingProgram
+ {
+ get
+ {
+ return GetTagText("OriginatingProgram");
+ }
+ set
+ {
+ SetTagValue("OriginatingProgram", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Program Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ProgramVersion
+ {
+ get
+ {
+ return GetTagText("ProgramVersion");
+ }
+ set
+ {
+ SetTagValue("ProgramVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Cycle.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectCycle
+ {
+ get
+ {
+ return GetTagText("ObjectCycle");
+ }
+ set
+ {
+ SetTagValue("ObjectCycle", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag By Line.
+ /// This is the author's name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ByLine
+ {
+ get
+ {
+ return GetTagText("By-line");
+ }
+ set
+ {
+ SetTagValue("By-line", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag By Line Title.
+ /// This is the author's position.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ByLineTitle
+ {
+ get
+ {
+ return GetTagText("By-lineTitle");
+ }
+ set
+ {
+ SetTagValue("By-lineTitle", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag City.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string City
+ {
+ get
+ {
+ return GetTagText("City");
+ }
+ set
+ {
+ SetTagValue("City", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Sub Location.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubLocation
+ {
+ get
+ {
+ return GetTagText("SubLocation");
+ }
+ set
+ {
+ SetTagValue("SubLocation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Province State.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ProvinceState
+ {
+ get
+ {
+ return GetTagText("ProvinceState");
+ }
+ set
+ {
+ SetTagValue("ProvinceState", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Country Primary Location Code.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CountryPrimaryLocationCode
+ {
+ get
+ {
+ return GetTagText("Country-PrimaryLocationCode");
+ }
+ set
+ {
+ SetTagValue("Country-PrimaryLocationCode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Country Primary Location Name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CountryPrimaryLocationName
+ {
+ get
+ {
+ return GetTagText("Country-PrimaryLocationName");
+ }
+ set
+ {
+ SetTagValue("Country-PrimaryLocationName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Original Transmission Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OriginalTransmissionReference
+ {
+ get
+ {
+ return GetTagText("OriginalTransmissionReference");
+ }
+ set
+ {
+ SetTagValue("OriginalTransmissionReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Headline.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Headline
+ {
+ get
+ {
+ return GetTagText("Headline");
+ }
+ set
+ {
+ SetTagValue("Headline", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Credit.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Credit
+ {
+ get
+ {
+ return GetTagText("Credit");
+ }
+ set
+ {
+ SetTagValue("Credit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Source.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Source
+ {
+ get
+ {
+ return GetTagText("Source");
+ }
+ set
+ {
+ SetTagValue("Source", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Copyright Notice.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CopyrightNotice
+ {
+ get
+ {
+ return GetTagText("CopyrightNotice");
+ }
+ set
+ {
+ SetTagValue("CopyrightNotice", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Contact.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Contact
+ {
+ get
+ {
+ return GetTagText("Contact");
+ }
+ set
+ {
+ SetTagValue("Contact", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Caption Abstract.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CaptionAbstract
+ {
+ get
+ {
+ return GetTagText("CaptionAbstract");
+ }
+ set
+ {
+ SetTagValue("CaptionAbstract", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Writer Editor.
+ /// This is also referred to as Caption Writer.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string WriterEditor
+ {
+ get
+ {
+ return GetTagText("WriterEditor");
+ }
+ set
+ {
+ SetTagValue("WriterEditor", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Rasterized Caption.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string RasterizedCaption
+ {
+ get
+ {
+ return GetTagText("RasterizedCaption");
+ }
+ set
+ {
+ SetTagValue("RasterizedCaption", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Image Type.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageType
+ {
+ get
+ {
+ return GetTagText("ImageType");
+ }
+ set
+ {
+ SetTagValue("ImageType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Image Orientation.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageOrientation
+ {
+ get
+ {
+ return GetTagText("ImageOrientation");
+ }
+ set
+ {
+ SetTagValue("ImageOrientation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Language Identifier.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string LanguageIdentifier
+ {
+ get
+ {
+ return GetTagText("LanguageIdentifier");
+ }
+ set
+ {
+ SetTagValue("LanguageIdentifier", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Type.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioType
+ {
+ get
+ {
+ return GetTagText("AudioType");
+ }
+ set
+ {
+ SetTagValue("AudioType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Sampling Rate.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioSamplingRate
+ {
+ get
+ {
+ return GetTagText("AudioSamplingRate");
+ }
+ set
+ {
+ SetTagValue("AudioSamplingRate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Sampling Resolution.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioSamplingResolution
+ {
+ get
+ {
+ return GetTagText("AudioSamplingResolution");
+ }
+ set
+ {
+ SetTagValue("AudioSamplingResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Duration.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioDuration
+ {
+ get
+ {
+ return GetTagText("AudioDuration");
+ }
+ set
+ {
+ SetTagValue("AudioDuration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Outcue.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioOutcue
+ {
+ get
+ {
+ return GetTagText("AudioOutcue");
+ }
+ set
+ {
+ SetTagValue("AudioOutcue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Job I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string JobID
+ {
+ get
+ {
+ return GetTagText("JobID");
+ }
+ set
+ {
+ SetTagValue("JobID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Master Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string MasterDocumentID
+ {
+ get
+ {
+ return GetTagText("MasterDocumentID");
+ }
+ set
+ {
+ SetTagValue("MasterDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Short Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ShortDocumentID
+ {
+ get
+ {
+ return GetTagText("ShortDocumentID");
+ }
+ set
+ {
+ SetTagValue("ShortDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Unique Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string UniqueDocumentID
+ {
+ get
+ {
+ return GetTagText("UniqueDocumentID");
+ }
+ set
+ {
+ SetTagValue("UniqueDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Owner I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OwnerID
+ {
+ get
+ {
+ return GetTagText("OwnerID");
+ }
+ set
+ {
+ SetTagValue("OwnerID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview File Format.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewFileFormat
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewFileFormat");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewFileFormat", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview File Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewFileVersion
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewFileVersion");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewFileVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview Data.
+ /// This is also referred to as Audio Outcue.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewData
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewData");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewData", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Prefs.
+ /// This is also referred to as photo-mechanic preferences.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Prefs
+ {
+ get
+ {
+ return GetTagText("Prefs");
+ }
+ set
+ {
+ SetTagValue("Prefs", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Classify State.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ClassifyState
+ {
+ get
+ {
+ return GetTagText("ClassifyState");
+ }
+ set
+ {
+ SetTagValue("ClassifyState", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Similarity Index.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SimilarityIndex
+ {
+ get
+ {
+ return GetTagText("SimilarityIndex");
+ }
+ set
+ {
+ SetTagValue("SimilarityIndex", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Document Notes.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DocumentNotes
+ {
+ get
+ {
+ return GetTagText("DocumentNotes");
+ }
+ set
+ {
+ SetTagValue("DocumentNotes", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Document History.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DocumentHistory
+ {
+ get
+ {
+ return GetTagText("DocumentHistory");
+ }
+ set
+ {
+ SetTagValue("DocumentHistory", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Exif Camera Info.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExifCameraInfo
+ {
+ get
+ {
+ return GetTagText("ExifCameraInfo");
+ }
+ set
+ {
+ SetTagValue("ExifCameraInfo", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_NODATA"/>.
+ /// </summary>
+ public class MDM_NODATA : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_NODATA(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_NODATA; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_XMP"/>.
+ /// </summary>
+ public class MDM_XMP : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_XMP(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_XMP; }
+ }
+
+ /// <summary>
+ /// Gets or sets the XMP XML content.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Xml
+ {
+ get
+ {
+ return GetTagText("XMLPacket");
+ }
+ set
+ {
+ SetTagValue("XMLPacket", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="XmlReader"/> initialized to read the XMP XML content.
+ /// Returns null, if the metadata tag <i>XMLPacket</i> is not present in
+ /// this model.
+ /// </summary>
+ public XmlReader XmlReader
+ {
+ get
+ {
+ string xmlString = Xml;
+ if (xmlString == null)
+ {
+ return null;
+ }
+ else
+ {
+ MemoryStream stream = new MemoryStream();
+ StreamWriter writer = new StreamWriter(stream);
+ writer.Write(xmlString);
+ return XmlReader.Create(stream);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataTag.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataTag.cs
new file mode 100644
index 0000000..5a811e0
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/MetadataTag.cs
@@ -0,0 +1,757 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.9 $
+// $Date: 2009/02/27 16:35:12 $
+// $Id: MetadataTag.cs,v 1.9 2009/02/27 16:35:12 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Manages metadata objects and operations.
+ /// </summary>
+ public sealed class MetadataTag : IComparable, IComparable<MetadataTag>, ICloneable, IEquatable<MetadataTag>, IDisposable
+ {
+ /// <summary>
+ /// The encapsulated FreeImage-tag.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal FITAG tag;
+
+ /// <summary>
+ /// The metadata model of <see cref="tag"/>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FREE_IMAGE_MDMODEL model;
+
+ /// <summary>
+ /// Indicates whether this instance has already been disposed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed = false;
+
+ /// <summary>
+ /// Indicates whether this instance was created by FreeImage or
+ /// by the user.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool selfCreated;
+
+ /// <summary>
+ /// List linking metadata-model and Type.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly Dictionary<FREE_IMAGE_MDTYPE, Type> idList;
+
+ /// <summary>
+ /// List linking Type and metadata-model.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly Dictionary<Type, FREE_IMAGE_MDTYPE> typeList;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ private MetadataTag()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="model">The new model the tag should be of.</param>
+ public MetadataTag(FREE_IMAGE_MDMODEL model)
+ {
+ this.model = model;
+ tag = FreeImage.CreateTag();
+ selfCreated = true;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to represent.</param>
+ /// <param name="dib">The bitmap <paramref name="tag"/> was extracted from.</param>
+ public MetadataTag(FITAG tag, FIBITMAP dib)
+ {
+ if (tag.IsNull)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ this.tag = tag;
+ model = GetModel(dib, tag);
+ selfCreated = false;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to represent.</param>
+ /// <param name="model">The model of <paramref name="tag"/>.</param>
+ public MetadataTag(FITAG tag, FREE_IMAGE_MDMODEL model)
+ {
+ if (tag.IsNull)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ this.tag = tag;
+ this.model = model;
+ selfCreated = false;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ static MetadataTag()
+ {
+ idList = new Dictionary<FREE_IMAGE_MDTYPE, Type>();
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_BYTE, typeof(byte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SHORT, typeof(ushort));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_LONG, typeof(uint));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_RATIONAL, typeof(FIURational));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SBYTE, typeof(sbyte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_UNDEFINED, typeof(byte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SSHORT, typeof(short));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SLONG, typeof(int));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SRATIONAL, typeof(FIRational));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_FLOAT, typeof(float));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_DOUBLE, typeof(double));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_IFD, typeof(uint));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_PALETTE, typeof(RGBQUAD));
+
+ typeList = new Dictionary<Type, FREE_IMAGE_MDTYPE>();
+ typeList.Add(typeof(ushort), FREE_IMAGE_MDTYPE.FIDT_SHORT);
+ typeList.Add(typeof(ushort[]), FREE_IMAGE_MDTYPE.FIDT_SHORT);
+ typeList.Add(typeof(string), FREE_IMAGE_MDTYPE.FIDT_ASCII);
+ typeList.Add(typeof(uint), FREE_IMAGE_MDTYPE.FIDT_LONG);
+ typeList.Add(typeof(uint[]), FREE_IMAGE_MDTYPE.FIDT_LONG);
+ typeList.Add(typeof(FIURational), FREE_IMAGE_MDTYPE.FIDT_RATIONAL);
+ typeList.Add(typeof(FIURational[]), FREE_IMAGE_MDTYPE.FIDT_RATIONAL);
+ typeList.Add(typeof(sbyte), FREE_IMAGE_MDTYPE.FIDT_SBYTE);
+ typeList.Add(typeof(sbyte[]), FREE_IMAGE_MDTYPE.FIDT_SBYTE);
+ typeList.Add(typeof(byte), FREE_IMAGE_MDTYPE.FIDT_BYTE);
+ typeList.Add(typeof(byte[]), FREE_IMAGE_MDTYPE.FIDT_BYTE);
+ typeList.Add(typeof(short), FREE_IMAGE_MDTYPE.FIDT_SSHORT);
+ typeList.Add(typeof(short[]), FREE_IMAGE_MDTYPE.FIDT_SSHORT);
+ typeList.Add(typeof(int), FREE_IMAGE_MDTYPE.FIDT_SLONG);
+ typeList.Add(typeof(int[]), FREE_IMAGE_MDTYPE.FIDT_SLONG);
+ typeList.Add(typeof(FIRational), FREE_IMAGE_MDTYPE.FIDT_SRATIONAL);
+ typeList.Add(typeof(FIRational[]), FREE_IMAGE_MDTYPE.FIDT_SRATIONAL);
+ typeList.Add(typeof(float), FREE_IMAGE_MDTYPE.FIDT_FLOAT);
+ typeList.Add(typeof(float[]), FREE_IMAGE_MDTYPE.FIDT_FLOAT);
+ typeList.Add(typeof(double), FREE_IMAGE_MDTYPE.FIDT_DOUBLE);
+ typeList.Add(typeof(double[]), FREE_IMAGE_MDTYPE.FIDT_DOUBLE);
+ typeList.Add(typeof(RGBQUAD), FREE_IMAGE_MDTYPE.FIDT_PALETTE);
+ typeList.Add(typeof(RGBQUAD[]), FREE_IMAGE_MDTYPE.FIDT_PALETTE);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ ~MetadataTag()
+ {
+ Dispose();
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="MetadataTag"/> objects have the same value.
+ /// </summary>
+ /// <param name="left">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// <b>true</b> if the value of left is the same as the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(MetadataTag left, MetadataTag right)
+ {
+ // Check whether both are null
+ if ((object)left == (object)right)
+ {
+ return true;
+ }
+ else if ((object)left == null || (object)right == null)
+ {
+ return false;
+ }
+ left.CheckDisposed();
+ right.CheckDisposed();
+ // Check all properties
+ if ((left.Key != right.Key) ||
+ (left.ID != right.ID) ||
+ (left.Description != right.Description) ||
+ (left.Count != right.Count) ||
+ (left.Length != right.Length) ||
+ (left.Model != right.Model) ||
+ (left.Type != right.Type))
+ {
+ return false;
+ }
+ if (left.Length == 0)
+ {
+ return true;
+ }
+ IntPtr ptr1 = FreeImage.GetTagValue(left.tag);
+ IntPtr ptr2 = FreeImage.GetTagValue(right.tag);
+ return FreeImage.CompareMemory(ptr1, ptr2, left.Length);
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="MetadataTag"/> objects have different values.
+ /// </summary>
+ /// <param name="left">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// true if the value of left is different from the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(MetadataTag left, MetadataTag right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Extracts the value of a <see cref="MetadataTag"/> instance to a <see cref="FITAG"/> handle.
+ /// </summary>
+ /// <param name="value">A <see cref="MetadataTag"/> instance.</param>
+ /// <returns>A new instance of <see cref="FITAG"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FITAG(MetadataTag value)
+ {
+ return value.tag;
+ }
+
+ private static FREE_IMAGE_MDMODEL GetModel(FIBITMAP dib, FITAG tag)
+ {
+ FITAG value;
+ foreach (FREE_IMAGE_MDMODEL model in FreeImage.FREE_IMAGE_MDMODELS)
+ {
+ FIMETADATA mData = FreeImage.FindFirstMetadata(model, dib, out value);
+ if (mData.IsNull)
+ {
+ continue;
+ }
+ try
+ {
+ do
+ {
+ if (value == tag)
+ {
+ return model;
+ }
+ }
+ while (FreeImage.FindNextMetadata(mData, out value));
+ }
+ finally
+ {
+ if (!mData.IsNull)
+ {
+ FreeImage.FindCloseMetadata(mData);
+ }
+ }
+ }
+ throw new ArgumentException("'tag' is no metadata object of 'dib'");
+ }
+
+ /// <summary>
+ /// Gets the model of the metadata.
+ /// </summary>
+ public FREE_IMAGE_MDMODEL Model
+ {
+ get { CheckDisposed(); return model; }
+ }
+
+ /// <summary>
+ /// Gets or sets the key of the metadata.
+ /// </summary>
+ public string Key
+ {
+ get { CheckDisposed(); return FreeImage.GetTagKey(tag); }
+ set
+ {
+ CheckDisposed();
+ if ((model != FREE_IMAGE_MDMODEL.FIMD_XMP) || (value == "XMLPacket"))
+ {
+ FreeImage.SetTagKey(tag, value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the description of the metadata.
+ /// </summary>
+ public string Description
+ {
+ get { CheckDisposed(); return FreeImage.GetTagDescription(tag); }
+ set { CheckDisposed(); FreeImage.SetTagDescription(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets or sets the ID of the metadata.
+ /// </summary>
+ public ushort ID
+ {
+ get { CheckDisposed(); return FreeImage.GetTagID(tag); }
+ set { CheckDisposed(); FreeImage.SetTagID(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the type of the metadata.
+ /// </summary>
+ public FREE_IMAGE_MDTYPE Type
+ {
+ get { CheckDisposed(); return FreeImage.GetTagType(tag); }
+ internal set { FreeImage.SetTagType(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the number of elements the metadata object contains.
+ /// </summary>
+ public uint Count
+ {
+ get { CheckDisposed(); return FreeImage.GetTagCount(tag); }
+ private set { FreeImage.SetTagCount(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the length of the value in bytes.
+ /// </summary>
+ public uint Length
+ {
+ get { CheckDisposed(); return FreeImage.GetTagLength(tag); }
+ private set { FreeImage.SetTagLength(tag, value); }
+ }
+
+ private unsafe byte[] GetData()
+ {
+ uint length = Length;
+ byte[] value = new byte[length];
+ byte* ptr = (byte*)FreeImage.GetTagValue(tag);
+ for (int i = 0; i < length; i++)
+ {
+ value[i] = ptr[i];
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the metadata.
+ /// </summary>
+ public object Value
+ {
+ get
+ {
+ unsafe
+ {
+ CheckDisposed();
+ int cnt = (int)Count;
+
+ if (Type == FREE_IMAGE_MDTYPE.FIDT_ASCII)
+ {
+ byte* value = (byte*)FreeImage.GetTagValue(tag);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < cnt; i++)
+ {
+ sb.Append(Convert.ToChar(value[i]));
+ }
+ return sb.ToString();
+ }
+ else if (Type == FREE_IMAGE_MDTYPE.FIDT_NOTYPE)
+ {
+ return null;
+ }
+
+ Array array = Array.CreateInstance(idList[Type], Count);
+ void* src = (void*)FreeImage.GetTagValue(tag);
+ FreeImage.CopyMemory(array, src, Length);
+ return array;
+ }
+ }
+ set
+ {
+ SetValue(value);
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of the metadata.
+ /// <para> In case value is of byte or byte[] <see cref="FREE_IMAGE_MDTYPE.FIDT_UNDEFINED"/> is assumed.</para>
+ /// <para> In case value is of uint or uint[] <see cref="FREE_IMAGE_MDTYPE.FIDT_LONG"/> is assumed.</para>
+ /// </summary>
+ /// <param name="value">New data of the metadata.</param>
+ /// <returns>True on success, false on failure.</returns>
+ /// <exception cref="NotSupportedException">
+ /// The data format is not supported.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is null.</exception>
+ public bool SetValue(object value)
+ {
+ Type type = value.GetType();
+ if (!typeList.ContainsKey(type))
+ {
+ throw new NotSupportedException("The type of value is not supported");
+ }
+ return SetValue(value, typeList[type]);
+ }
+
+ /// <summary>
+ /// Sets the value of the metadata.
+ /// </summary>
+ /// <param name="value">New data of the metadata.</param>
+ /// <param name="type">Type of the data.</param>
+ /// <returns>True on success, false on failure.</returns>
+ /// <exception cref="NotSupportedException">
+ /// The data type is not supported.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="value"/> and <paramref name="type"/> to not fit.</exception>
+ public bool SetValue(object value, FREE_IMAGE_MDTYPE type)
+ {
+ CheckDisposed();
+ if ((!value.GetType().IsArray) && (!(value is string)))
+ {
+ Array array = Array.CreateInstance(value.GetType(), 1);
+ array.SetValue(value, 0);
+ return SetArrayValue(array, type);
+ }
+ return SetArrayValue(value, type);
+ }
+
+ /// <summary>
+ /// Sets the value of this tag to the value of <paramref name="value"/>
+ /// using the given type.
+ /// </summary>
+ /// <param name="value">New value of the tag.</param>
+ /// <param name="type">Data-type of the tag.</param>
+ /// <returns></returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="type"/> is FIDT_ASCII and
+ /// <paramref name="value"/> is not String.
+ /// <paramref name="type"/> is not FIDT_ASCII and
+ /// <paramref name="value"/> is not Array.</exception>
+ /// <exception cref="NotSupportedException">
+ /// <paramref name="type"/> is FIDT_NOTYPE.</exception>
+ private unsafe bool SetArrayValue(object value, FREE_IMAGE_MDTYPE type)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ byte[] data = null;
+
+ if (type == FREE_IMAGE_MDTYPE.FIDT_ASCII)
+ {
+ string tempValue = value as string;
+ if (tempValue == null)
+ {
+ throw new ArgumentException("value");
+ }
+ Type = type;
+ Length = Count = (uint)tempValue.Length;
+ data = new byte[Length];
+
+ for (int i = 0; i < tempValue.Length; i++)
+ {
+ data[i] = (byte)tempValue[i];
+ }
+ }
+ else if (type == FREE_IMAGE_MDTYPE.FIDT_NOTYPE)
+ {
+ throw new NotSupportedException("type is not supported.");
+ }
+ else
+ {
+ Array array = value as Array;
+ if (array == null)
+ {
+ throw new ArgumentException("value");
+ }
+
+ if (array.Length != 0)
+ if (!CheckType(array.GetValue(0).GetType(), type))
+ throw new ArgumentException("The type of value is incorrect.");
+
+ Type = type;
+ Count = (uint)array.Length;
+ Length = (uint)(array.Length * Marshal.SizeOf(idList[type]));
+ data = new byte[Length];
+ FreeImage.CopyMemory(data, array, Length);
+ }
+
+ return FreeImage.SetTagValue(tag, data);
+ }
+
+ private static bool CheckType(Type dataType, FREE_IMAGE_MDTYPE type)
+ {
+ if (dataType != null)
+ switch (type)
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_ASCII:
+ return dataType == typeof(string);
+ case FREE_IMAGE_MDTYPE.FIDT_BYTE:
+ return dataType == typeof(byte);
+ case FREE_IMAGE_MDTYPE.FIDT_DOUBLE:
+ return dataType == typeof(double);
+ case FREE_IMAGE_MDTYPE.FIDT_FLOAT:
+ return dataType == typeof(float);
+ case FREE_IMAGE_MDTYPE.FIDT_IFD:
+ return dataType == typeof(uint);
+ case FREE_IMAGE_MDTYPE.FIDT_LONG:
+ return dataType == typeof(uint);
+ case FREE_IMAGE_MDTYPE.FIDT_NOTYPE:
+ return false;
+ case FREE_IMAGE_MDTYPE.FIDT_PALETTE:
+ return dataType == typeof(RGBQUAD);
+ case FREE_IMAGE_MDTYPE.FIDT_RATIONAL:
+ return dataType == typeof(FIURational);
+ case FREE_IMAGE_MDTYPE.FIDT_SBYTE:
+ return dataType == typeof(sbyte);
+ case FREE_IMAGE_MDTYPE.FIDT_SHORT:
+ return dataType == typeof(ushort);
+ case FREE_IMAGE_MDTYPE.FIDT_SLONG:
+ return dataType == typeof(int);
+ case FREE_IMAGE_MDTYPE.FIDT_SRATIONAL:
+ return dataType == typeof(FIRational);
+ case FREE_IMAGE_MDTYPE.FIDT_SSHORT:
+ return dataType == typeof(short);
+ case FREE_IMAGE_MDTYPE.FIDT_UNDEFINED:
+ return dataType == typeof(byte);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Add this metadata to an image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>True on success, false on failure.</returns>
+ public bool AddToImage(FIBITMAP dib)
+ {
+ CheckDisposed();
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (Key == null)
+ {
+ throw new ArgumentNullException("Key");
+ }
+ if (!selfCreated)
+ {
+ tag = FreeImage.CloneTag(tag);
+ if (tag.IsNull)
+ {
+ throw new Exception("FreeImage.CloneTag() failed.");
+ }
+ selfCreated = true;
+ }
+ if (!FreeImage.SetMetadata(Model, dib, Key, tag))
+ {
+ return false;
+ }
+ FREE_IMAGE_MDMODEL _model = Model;
+ string _key = Key;
+ selfCreated = false;
+ FreeImage.DeleteTag(tag);
+ return FreeImage.GetMetadata(_model, dib, _key, out tag);
+ }
+
+ /// <summary>
+ /// Gets a .NET PropertyItem for this metadata tag.
+ /// </summary>
+ /// <returns>The .NET PropertyItem.</returns>
+ public unsafe System.Drawing.Imaging.PropertyItem GetPropertyItem()
+ {
+ System.Drawing.Imaging.PropertyItem item = FreeImage.CreatePropertyItem();
+ item.Id = ID;
+ item.Len = (int)Length;
+ item.Type = (short)Type;
+ FreeImage.CopyMemory(item.Value = new byte[item.Len], FreeImage.GetTagValue(tag), item.Len);
+ return item;
+ }
+
+ /// <summary>
+ /// Converts the value of the <see cref="MetadataTag"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ CheckDisposed();
+ string fiString = FreeImage.TagToString(model, tag, 0);
+
+ if (String.IsNullOrEmpty(fiString))
+ {
+ return tag.ToString();
+ }
+ else
+ {
+ return fiString;
+ }
+ }
+
+ /// <summary>
+ /// Creates a deep copy of this <see cref="MetadataTag"/>.
+ /// </summary>
+ /// <returns>A deep copy of this <see cref="MetadataTag"/>.</returns>
+ public object Clone()
+ {
+ CheckDisposed();
+ MetadataTag clone = new MetadataTag();
+ clone.model = model;
+ clone.tag = FreeImage.CloneTag(tag);
+ clone.selfCreated = true;
+ return clone;
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="MetadataTag"/> instance
+ /// and is equivalent to this <see cref="MetadataTag"/> instance.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="MetadataTag"/> instance
+ /// equivalent to this <see cref="MetadataTag"/> instance; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is MetadataTag) && (Equals((MetadataTag)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MetadataTag"/> instance is equivalent to this <see cref="MetadataTag"/> instance.
+ /// </summary>
+ /// <param name="other">A <see cref="MetadataTag"/> instance to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> equivalent to this <see cref="MetadataTag"/> instance;
+ /// otherwise, <b>false</b>.</returns>
+ public bool Equals(MetadataTag other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="MetadataTag"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="MetadataTag"/>.</returns>
+ public override int GetHashCode()
+ {
+ return tag.GetHashCode();
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="MetadataTag"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is MetadataTag))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((MetadataTag)obj);
+ }
+
+ /// <summary>
+ /// Compares the current instance with another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer that indicates the relative order of the objects being compared.</returns>
+ public int CompareTo(MetadataTag other)
+ {
+ CheckDisposed();
+ other.CheckDisposed();
+ return tag.CompareTo(other.tag);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ public void Dispose()
+ {
+ if (!disposed)
+ {
+ disposed = true;
+ if (selfCreated)
+ {
+ FreeImage.DeleteTag(tag);
+ tag = FITAG.Zero;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this instance has already been disposed.
+ /// </summary>
+ public bool Disposed
+ {
+ get { return disposed; }
+ }
+
+ /// <summary>
+ /// Throwns an <see cref="ObjectDisposedException"/> in case
+ /// this instance has already been disposed.
+ /// </summary>
+ private void CheckDisposed()
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The object has already been disposed.");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/Palette.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/Palette.cs
new file mode 100644
index 0000000..58aa501
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/Palette.cs
@@ -0,0 +1,422 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Drawing;
+using System.IO;
+using FreeImageAPI.Metadata;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Provides methods for working with the standard bitmap palette.
+ /// </summary>
+ public sealed class Palette : MemoryArray<RGBQUAD>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private GCHandle paletteHandle;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private RGBQUAD[] array;
+
+ /// <summary>
+ /// Initializes a new instance for the given FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="dib"/> is not
+ /// <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/><para/>-or-<para/>
+ /// <paramref name="dib"/> has more than 8bpp.</exception>
+ public Palette(FIBITMAP dib)
+ : base(FreeImage.GetPalette(dib), (int)FreeImage.GetColorsUsed(dib))
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (FreeImage.GetImageType(dib) != FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ throw new ArgumentException("dib");
+ }
+ if (FreeImage.GetBPP(dib) > 8u)
+ {
+ throw new ArgumentException("dib");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given FITAG that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="tag">The tag containing the palette.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="tag"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="tag"/> is not
+ /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
+ public Palette(FITAG tag)
+ : base(FreeImage.GetTagValue(tag), (int)FreeImage.GetTagCount(tag))
+ {
+ if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
+ {
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given MetadataTag that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="tag">The tag containing the palette.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="tag"/> is not
+ /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
+ public Palette(MetadataTag tag)
+ : base(FreeImage.GetTagValue(tag.tag), (int)tag.Count)
+ {
+ if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
+ {
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given array of <see cref="RGBQUAD"/> that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="palette">A RGBQUAD array containing the palette data to initialize this instance.</param>
+ public Palette(RGBQUAD[] palette)
+ {
+ unsafe
+ {
+ this.array = (RGBQUAD[])palette.Clone();
+ this.paletteHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
+
+ base.baseAddress = (byte*)this.paletteHandle.AddrOfPinnedObject();
+ base.length = (int)this.array.Length;
+
+ // Create an array containing a single element.
+ // Due to the fact, that it's not possible to create pointers
+ // of generic types, an array is used to obtain the memory
+ // address of an element of T.
+ base.buffer = new RGBQUAD[1];
+ // The array is pinned immediately to prevent the GC from
+ // moving it to a different position in memory.
+ base.handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ // The array and its content have beed pinned, so that its address
+ // can be safely requested and stored for the whole lifetime
+ // of the instace.
+ base.ptr = (byte*)base.handle.AddrOfPinnedObject();
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given array of <see cref="Color"/> that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="palette">A Color array containing the palette data to initialize this instance.</param>
+ public Palette(Color[] palette)
+ : this(RGBQUAD.ToRGBQUAD(palette))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance with the specified size.
+ /// </summary>
+ /// <param name="size">The size of the palette.</param>
+ public Palette(int size)
+ : this(new RGBQUAD[size])
+ {
+ }
+
+ /// <summary>
+ /// Gets or sets the palette through an array of <see cref="RGBQUAD"/>.
+ /// </summary>
+ public RGBQUAD[] AsArray
+ {
+ get
+ {
+ return Data;
+ }
+ set
+ {
+ Data = value;
+ }
+ }
+
+ /// <summary>
+ /// Get an array of <see cref="System.Drawing.Color"/> that the block of memory represents.
+ /// This property is used for internal palette operations.
+ /// </summary>
+ internal unsafe Color[] ColorData
+ {
+ get
+ {
+ EnsureNotDisposed();
+ Color[] data = new Color[length];
+ for (int i = 0; i < length; i++)
+ {
+ data[i] = Color.FromArgb((int)(((uint*)baseAddress)[i] | 0xFF000000));
+ }
+ return data;
+ }
+ }
+
+ /// <summary>
+ /// Returns the palette as an array of <see cref="RGBQUAD"/>.
+ /// </summary>
+ /// <returns>The palette as an array of <see cref="RGBQUAD"/>.</returns>
+ public RGBQUAD[] ToArray()
+ {
+ return Data;
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color)
+ {
+ Colorize(color, 0.5d);
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <param name="splitSize">The position of the color within the new palette.
+ /// 0 &lt; <paramref name="splitSize"/> &lt; 1.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color, double splitSize)
+ {
+ Colorize(color, (int)(length * splitSize));
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <param name="splitSize">The position of the color within the new palette.
+ /// 0 &lt; <paramref name="splitSize"/> &lt; <see cref="MemoryArray&lt;T&gt;.Length"/>.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color, int splitSize)
+ {
+ EnsureNotDisposed();
+ if (splitSize < 1 || splitSize >= length)
+ {
+ throw new ArgumentOutOfRangeException("splitSize");
+ }
+
+ RGBQUAD[] pal = new RGBQUAD[length];
+
+ double red = color.R;
+ double green = color.G;
+ double blue = color.B;
+
+ int i = 0;
+ double r, g, b;
+
+ r = red / splitSize;
+ g = green / splitSize;
+ b = blue / splitSize;
+
+ for (; i <= splitSize; i++)
+ {
+ pal[i].rgbRed = (byte)(i * r);
+ pal[i].rgbGreen = (byte)(i * g);
+ pal[i].rgbBlue = (byte)(i * b);
+ }
+
+ r = (255 - red) / (length - splitSize);
+ g = (255 - green) / (length - splitSize);
+ b = (255 - blue) / (length - splitSize);
+
+ for (; i < length; i++)
+ {
+ pal[i].rgbRed = (byte)(red + ((i - splitSize) * r));
+ pal[i].rgbGreen = (byte)(green + ((i - splitSize) * g));
+ pal[i].rgbBlue = (byte)(blue + ((i - splitSize) * b));
+ }
+
+ Data = pal;
+ }
+
+ /// <summary>
+ /// Creates a linear grayscale palette.
+ /// </summary>
+ public void CreateGrayscalePalette()
+ {
+ Colorize(Color.White, length - 1);
+ }
+
+ /// <summary>
+ /// Creates a linear grayscale palette.
+ /// </summary>
+ /// <param name="inverse"><b>true</b> to create an inverse grayscale palette.</param>
+ public void CreateGrayscalePalette(bool inverse)
+ {
+ Colorize(Color.White, inverse ? 0 : length - 1);
+ }
+
+ /// <summary>
+ /// Creates a linear palette with the specified <see cref="Color"/>.
+ /// </summary>
+ /// <remarks>
+ /// A linear grayscale palette contains all shades of colors from
+ /// black to white. This method creates a similar palette with the white
+ /// color being replaced by the specified color.
+ /// </remarks>
+ /// <param name="color">The <see cref="Color"/> used to create the palette.</param>
+ /// <param name="inverse"><b>true</b> to create an inverse palette.</param>
+ public void CreateGrayscalePalette(Color color, bool inverse)
+ {
+ Colorize(color, inverse ? 0 : length - 1);
+ }
+
+ /// <summary>
+ /// Reverses the palette.
+ /// </summary>
+ public void Reverse()
+ {
+ EnsureNotDisposed();
+ if (array != null)
+ {
+ Array.Reverse(array);
+ }
+ else
+ {
+ RGBQUAD[] localArray = Data;
+ Array.Reverse(localArray);
+ Data = localArray;
+ }
+ }
+
+ /// <summary>
+ /// Copies the values from the specified <see cref="Palette"/> to this instance.
+ /// </summary>
+ /// <param name="palette">The palette to copy from.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CopyFrom(Palette palette)
+ {
+ EnsureNotDisposed();
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+ CopyFrom(palette.Data, 0, 0, Math.Min(palette.Length, this.Length));
+ }
+
+ /// <summary>
+ /// Copies the values from the specified <see cref="Palette"/> to this instance,
+ /// starting at the specified <paramref name="offset"/>.
+ /// </summary>
+ /// <param name="palette">The palette to copy from.</param>
+ /// <param name="offset">The position in this instance where the values
+ /// will be copied to.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="offset"/> is outside the range of valid indexes.</exception>
+ public void CopyFrom(Palette palette, int offset)
+ {
+ EnsureNotDisposed();
+ CopyFrom(palette.Data, 0, offset, Math.Min(palette.Length, this.Length - offset));
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> to the specified file.
+ /// </summary>
+ /// <param name="filename">
+ /// A string that contains the name of the file to which to save this <see cref="Palette"/>.
+ /// </param>
+ public void Save(string filename)
+ {
+ using (Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
+ {
+ Save(stream);
+ }
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> to the specified stream.
+ /// </summary>
+ /// <param name="stream">
+ /// The <see cref="Stream"/> where the image will be saved.
+ /// </param>
+ public void Save(Stream stream)
+ {
+ Save(new BinaryWriter(stream));
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> using the specified writer.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="BinaryWriter"/> used to save the image.
+ /// </param>
+ public void Save(BinaryWriter writer)
+ {
+ EnsureNotDisposed();
+ writer.Write(ToByteArray());
+ }
+
+ /// <summary>
+ /// Loads a palette from the specified file.
+ /// </summary>
+ /// <param name="filename">The name of the palette file.</param>
+ public void Load(string filename)
+ {
+ using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
+ {
+ Load(stream);
+ }
+ }
+
+ /// <summary>
+ /// Loads a palette from the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream to load the palette from.</param>
+ public void Load(Stream stream)
+ {
+ Load(new BinaryReader(stream));
+ }
+
+ /// <summary>
+ /// Loads a palette from the reader.
+ /// </summary>
+ /// <param name="reader">The reader to load the palette from.</param>
+ public void Load(BinaryReader reader)
+ {
+ EnsureNotDisposed();
+ unsafe
+ {
+ int size = length * sizeof(RGBQUAD);
+ byte[] data = reader.ReadBytes(size);
+ fixed (byte* src = data)
+ {
+ CopyMemory(baseAddress, src, data.Length);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Releases allocated handles associated with this instance.
+ /// </summary>
+ /// <param name="disposing"><b>true</b> to release managed resources.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (paletteHandle.IsAllocated)
+ paletteHandle.Free();
+ array = null;
+
+ base.Dispose(disposing);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/PluginRepository.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/PluginRepository.cs
new file mode 100644
index 0000000..8b077dc
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/PluginRepository.cs
@@ -0,0 +1,449 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing all registered <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> in FreeImage.
+ /// </summary>
+ public static class PluginRepository
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly List<FreeImagePlugin> plugins = null;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly List<FreeImagePlugin> localPlugins = null;
+
+ static PluginRepository()
+ {
+ plugins = new List<FreeImagePlugin>(FreeImage.GetFIFCount());
+ localPlugins = new List<FreeImagePlugin>(0);
+ for (int i = 0; i < plugins.Capacity; i++)
+ {
+ plugins.Add(new FreeImagePlugin((FREE_IMAGE_FORMAT)i));
+ }
+ }
+
+ /// <summary>
+ /// Adds local plugin to this class.
+ /// </summary>
+ /// <param name="localPlugin">The registered plugin.</param>
+ internal static void RegisterLocalPlugin(LocalPlugin localPlugin)
+ {
+ FreeImagePlugin plugin = new FreeImagePlugin(localPlugin.Format);
+ plugins.Add(plugin);
+ localPlugins.Add(plugin);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>, representing the given format.
+ /// </summary>
+ /// <param name="fif">The representing format.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(FREE_IMAGE_FORMAT fif)
+ {
+ return Plugin((int)fif);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>,
+ /// representing the format at the given index.
+ /// </summary>
+ /// <param name="index">The index of the representing format.</param>
+ /// <returns>An instance of <see cref="FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(int index)
+ {
+ return (index >= 0) ? plugins[index] : null;
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.
+ /// <typeparamref name="expression"/> is searched in:
+ /// <c>Format</c>, <c>RegExpr</c>,
+ /// <c>ValidExtension</c> and <c>ValidFilename</c>.
+ /// </summary>
+ /// <param name="expression">The expression to search for.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(string expression)
+ {
+ FreeImagePlugin result = null;
+ expression = expression.ToLower();
+
+ foreach (FreeImagePlugin plugin in plugins)
+ {
+ if (plugin.Format.ToLower().Contains(expression) ||
+ plugin.RegExpr.ToLower().Contains(expression) ||
+ plugin.ValidExtension(expression, StringComparison.CurrentCultureIgnoreCase) ||
+ plugin.ValidFilename(expression, StringComparison.CurrentCultureIgnoreCase))
+ {
+ result = plugin;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given format.
+ /// </summary>
+ /// <param name="format">The format of the Plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromFormat(string format)
+ {
+ return Plugin(FreeImage.GetFIFFromFormat(format));
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given filename.
+ /// </summary>
+ /// <param name="filename">The valid filename for the plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromFilename(string filename)
+ {
+ return Plugin(FreeImage.GetFIFFromFilename(filename));
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given mime.
+ /// </summary>
+ /// <param name="mime">The valid mime for the plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromMime(string mime)
+ {
+ return Plugin(FreeImage.GetFIFFromMime(mime));
+ }
+
+ /// <summary>
+ /// Gets the number of registered plugins.
+ /// </summary>
+ public static int FIFCount
+ {
+ get
+ {
+ return FreeImage.GetFIFCount();
+ }
+ }
+
+ /// <summary>
+ /// Gets a readonly collection of all plugins.
+ /// </summary>
+ public static ReadOnlyCollection<FreeImagePlugin> PluginList
+ {
+ get
+ {
+ return plugins.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are only able to
+ /// read but not to write.
+ /// </summary>
+ public static List<FreeImagePlugin> ReadOnlyPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsReading && !p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are only able to
+ /// write but not to read.
+ /// </summary>
+ public static List<FreeImagePlugin> WriteOnlyPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!p.SupportsReading && p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are not able to
+ /// read or write.
+ /// </summary>
+ public static List<FreeImagePlugin> StupidPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!p.SupportsReading && !p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are able to read.
+ /// </summary>
+ public static List<FreeImagePlugin> ReadablePlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsReading)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are able to write.
+ /// </summary>
+ public static List<FreeImagePlugin> WriteablePlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of local plugins.
+ /// </summary>
+ public static ReadOnlyCollection<FreeImagePlugin> LocalPlugins
+ {
+ get
+ {
+ return localPlugins.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of built-in plugins.
+ /// </summary>
+ public static List<FreeImagePlugin> BuiltInPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!localPlugins.Contains(p))
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Windows or OS/2 Bitmap File (*.BMP)
+ /// </summary>
+ public static FreeImagePlugin BMP { get { return plugins[0]; } }
+
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ public static FreeImagePlugin ICO { get { return plugins[1]; } }
+
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ public static FreeImagePlugin JPEG { get { return plugins[2]; } }
+
+ /// <summary>
+ /// JPEG Network Graphics (*.JNG)
+ /// </summary>
+ public static FreeImagePlugin JNG { get { return plugins[3]; } }
+
+ /// <summary>
+ /// Commodore 64 Koala format (*.KOA)
+ /// </summary>
+ public static FreeImagePlugin KOALA { get { return plugins[4]; } }
+
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ public static FreeImagePlugin LBM { get { return plugins[5]; } }
+
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ public static FreeImagePlugin IFF { get { return plugins[5]; } }
+
+ /// <summary>
+ /// Multiple Network Graphics (*.MNG)
+ /// </summary>
+ public static FreeImagePlugin MNG { get { return plugins[6]; } }
+
+ /// <summary>
+ /// Portable Bitmap (ASCII) (*.PBM)
+ /// </summary>
+ public static FreeImagePlugin PBM { get { return plugins[7]; } }
+
+ /// <summary>
+ /// Portable Bitmap (BINARY) (*.PBM)
+ /// </summary>
+ public static FreeImagePlugin PBMRAW { get { return plugins[8]; } }
+
+ /// <summary>
+ /// Kodak PhotoCD (*.PCD)
+ /// </summary>
+ public static FreeImagePlugin PCD { get { return plugins[9]; } }
+
+ /// <summary>
+ /// Zsoft Paintbrush PCX bitmap format (*.PCX)
+ /// </summary>
+ public static FreeImagePlugin PCX { get { return plugins[10]; } }
+
+ /// <summary>
+ /// Portable Graymap (ASCII) (*.PGM)
+ /// </summary>
+ public static FreeImagePlugin PGM { get { return plugins[11]; } }
+
+ /// <summary>
+ /// Portable Graymap (BINARY) (*.PGM)
+ /// </summary>
+ public static FreeImagePlugin PGMRAW { get { return plugins[12]; } }
+
+ /// <summary>
+ /// Portable Network Graphics (*.PNG)
+ /// </summary>
+ public static FreeImagePlugin PNG { get { return plugins[13]; } }
+
+ /// <summary>
+ /// Portable Pixelmap (ASCII) (*.PPM)
+ /// </summary>
+ public static FreeImagePlugin PPM { get { return plugins[14]; } }
+
+ /// <summary>
+ /// Portable Pixelmap (BINARY) (*.PPM)
+ /// </summary>
+ public static FreeImagePlugin PPMRAW { get { return plugins[15]; } }
+
+ /// <summary>
+ /// Sun Rasterfile (*.RAS)
+ /// </summary>
+ public static FreeImagePlugin RAS { get { return plugins[16]; } }
+
+ /// <summary>
+ /// truevision Targa files (*.TGA, *.TARGA)
+ /// </summary>
+ public static FreeImagePlugin TARGA { get { return plugins[17]; } }
+
+ /// <summary>
+ /// Tagged Image File Format (*.TIF, *.TIFF)
+ /// </summary>
+ public static FreeImagePlugin TIFF { get { return plugins[18]; } }
+
+ /// <summary>
+ /// Wireless Bitmap (*.WBMP)
+ /// </summary>
+ public static FreeImagePlugin WBMP { get { return plugins[19]; } }
+
+ /// <summary>
+ /// Adobe Photoshop (*.PSD)
+ /// </summary>
+ public static FreeImagePlugin PSD { get { return plugins[20]; } }
+
+ /// <summary>
+ /// Dr. Halo (*.CUT)
+ /// </summary>
+ public static FreeImagePlugin CUT { get { return plugins[21]; } }
+
+ /// <summary>
+ /// X11 Bitmap Format (*.XBM)
+ /// </summary>
+ public static FreeImagePlugin XBM { get { return plugins[22]; } }
+
+ /// <summary>
+ /// X11 Pixmap Format (*.XPM)
+ /// </summary>
+ public static FreeImagePlugin XPM { get { return plugins[23]; } }
+
+ /// <summary>
+ /// DirectDraw Surface (*.DDS)
+ /// </summary>
+ public static FreeImagePlugin DDS { get { return plugins[24]; } }
+
+ /// <summary>
+ /// Graphics Interchange Format (*.GIF)
+ /// </summary>
+ public static FreeImagePlugin GIF { get { return plugins[25]; } }
+
+ /// <summary>
+ /// High Dynamic Range (*.HDR)
+ /// </summary>
+ public static FreeImagePlugin HDR { get { return plugins[26]; } }
+
+ /// <summary>
+ /// Raw Fax format CCITT G3 (*.G3)
+ /// </summary>
+ public static FreeImagePlugin FAXG3 { get { return plugins[27]; } }
+
+ /// <summary>
+ /// Silicon Graphics SGI image format (*.SGI)
+ /// </summary>
+ public static FreeImagePlugin SGI { get { return plugins[28]; } }
+
+ /// <summary>
+ /// OpenEXR format (*.EXR)
+ /// </summary>
+ public static FreeImagePlugin EXR { get { return plugins[29]; } }
+
+ /// <summary>
+ /// JPEG-2000 format (*.J2K, *.J2C)
+ /// </summary>
+ public static FreeImagePlugin J2K { get { return plugins[30]; } }
+
+ /// <summary>
+ /// JPEG-2000 format (*.JP2)
+ /// </summary>
+ public static FreeImagePlugin JP2 { get { return plugins[31]; } }
+
+ /// <summary>
+ /// Portable FloatMap (*.PFM)
+ /// </summary>
+ public static FreeImagePlugin PFM { get { return plugins[32]; } }
+
+ /// <summary>
+ /// Macintosh PICT (*.PICT)
+ /// </summary>
+ public static FreeImagePlugin PICT { get { return plugins[33]; } }
+
+ /// <summary>
+ /// RAW camera image (*.*)
+ /// </summary>
+ public static FreeImagePlugin RAW { get { return plugins[34]; } }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/Scanline.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/Scanline.cs
new file mode 100644
index 0000000..fcbeac3
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/Scanline.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Provides methods for working with generic bitmap scanlines.
+ /// </summary>
+ /// <typeparam name="T">Type of the bitmaps' scanlines.</typeparam>
+ public sealed class Scanline<T> : MemoryArray<T> where T : struct
+ {
+ /// <summary>
+ /// Initializes a new instance based on the specified FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public Scanline(FIBITMAP dib)
+ : this(dib, 0)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="scanline">Index of the zero based scanline.</param>
+ public Scanline(FIBITMAP dib, int scanline)
+ : this(dib, scanline, (int)(typeof(T) == typeof(FI1BIT) ?
+ FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib) :
+ typeof(T) == typeof(FI4BIT) ?
+ FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib) / 4 :
+ (FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib)) / (Marshal.SizeOf(typeof(T)) * 8)))
+ {
+ }
+
+ internal Scanline(FIBITMAP dib, int scanline, int length)
+ : base(FreeImage.GetScanLine(dib, scanline), length)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if ((scanline < 0) || (scanline >= FreeImage.GetHeight(dib)))
+ {
+ throw new ArgumentOutOfRangeException("scanline");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Classes/StreamWrapper.cs b/Wrapper/FreeImage.NET/cs/Library/Classes/StreamWrapper.cs
new file mode 100644
index 0000000..720156b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Classes/StreamWrapper.cs
@@ -0,0 +1,312 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.6 $
+// $Date: 2009/02/23 12:28:56 $
+// $Id: StreamWrapper.cs,v 1.6 2009/02/23 12:28:56 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.IO;
+using System.Diagnostics;
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Class wrapping streams, implementing a buffer for read data,
+ /// so that seek operations can be made.
+ /// </summary>
+ /// <remarks>
+ /// FreeImage can load bitmaps from arbitrary sources.
+ /// .NET works with different streams like File- or NetConnection-strams.
+ /// NetConnection streams, which are used to load files from web servers,
+ /// for example cannot seek.
+ /// But FreeImage frequently uses the seek operation when loading bitmaps.
+ /// <b>StreamWrapper</b> wrapps a stream and makes it seekable by caching all read
+ /// data into an internal MemoryStream to jump back- and forward.
+ /// StreamWapper is for internal use and only for loading from streams.
+ /// </remarks>
+ internal class StreamWrapper : Stream
+ {
+ /// <summary>
+ /// The stream to wrap
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Stream stream;
+
+ /// <summary>
+ /// The caching stream
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private MemoryStream memoryStream = new MemoryStream();
+
+ /// <summary>
+ /// Indicates if the wrapped stream reached its end
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool eos = false;
+
+ /// <summary>
+ /// Tells the wrapper to block readings or not
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool blocking = false;
+
+ /// <summary>
+ /// Indicates if the wrapped stream is disposed or not
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed = false;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">The stream to wrap.</param>
+ /// <param name="blocking">When true the wrapper always tries to read the requested
+ /// amount of data from the wrapped stream.</param>
+ public StreamWrapper(Stream stream, bool blocking)
+ {
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ this.stream = stream;
+ this.blocking = blocking;
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ ~StreamWrapper()
+ {
+ Dispose(false);
+ }
+
+ // The wrapper only accepts readable streams
+ public override bool CanRead
+ {
+ get { checkDisposed(); return true; }
+ }
+
+ // We implement that feature
+ public override bool CanSeek
+ {
+ get { checkDisposed(); return true; }
+ }
+
+ // The wrapper is readonly
+ public override bool CanWrite
+ {
+ get { checkDisposed(); return false; }
+ }
+
+ // Just forward it
+ public override void Flush()
+ {
+ checkDisposed();
+ stream.Flush();
+ }
+
+ // Calling this property will cause the wrapper to read the stream
+ // to its end and cache it completely.
+ public override long Length
+ {
+ get
+ {
+ checkDisposed();
+ if (!eos)
+ {
+ Fill();
+ }
+ return memoryStream.Length;
+ }
+ }
+
+ // Gets or sets the current position
+ public override long Position
+ {
+ get
+ {
+ checkDisposed();
+ return memoryStream.Position;
+ }
+ set
+ {
+ checkDisposed();
+ Seek(value, SeekOrigin.Begin);
+ }
+ }
+
+ // Implements the reading feature
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ checkDisposed();
+ // total bytes read from memory-stream
+ int memoryBytes = 0;
+ // total bytes read from the original stream
+ int streamBytes = 0;
+ memoryBytes = memoryStream.Read(buffer, offset, count);
+ if ((count > memoryBytes) && (!eos))
+ {
+ // read the rest from the original stream (can be 0 bytes)
+ do
+ {
+ int read = stream.Read(
+ buffer,
+ offset + memoryBytes + streamBytes,
+ count - memoryBytes - streamBytes);
+ streamBytes += read;
+ if (read == 0)
+ {
+ eos = true;
+ break;
+ }
+ if (!blocking)
+ {
+ break;
+ }
+ } while ((memoryBytes + streamBytes) < count);
+ // copy the bytes from the original stream into the memory stream
+ // if 0 bytes were read we write 0 so the memory-stream is not changed
+ memoryStream.Write(buffer, offset + memoryBytes, streamBytes);
+ }
+ return memoryBytes + streamBytes;
+ }
+
+ // Implements the seeking feature
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ checkDisposed();
+ long newPosition = 0L;
+ // get new position
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ newPosition = offset;
+ break;
+ case SeekOrigin.Current:
+ newPosition = memoryStream.Position + offset;
+ break;
+ case SeekOrigin.End:
+ // to seek from the end have have to read to the end first
+ if (!eos)
+ {
+ Fill();
+ }
+ newPosition = memoryStream.Length + offset;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("origin");
+ }
+ // in case the new position is beyond the memory-streams end
+ // and the original streams end hasn't been reached
+ // the original stream is read until either the stream ends or
+ // enough bytes have been read
+ if ((newPosition > memoryStream.Length) && (!eos))
+ {
+ memoryStream.Position = memoryStream.Length;
+ int bytesToRead = (int)(newPosition - memoryStream.Length);
+ byte[] buffer = new byte[1024];
+ do
+ {
+ bytesToRead -= Read(buffer, 0, (bytesToRead >= buffer.Length) ? buffer.Length : bytesToRead);
+ } while ((bytesToRead > 0) && (!eos));
+ }
+ memoryStream.Position = (newPosition <= memoryStream.Length) ? newPosition : memoryStream.Length;
+ return 0;
+ }
+
+ // No write-support
+ public override void SetLength(long value)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ // No write-support
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ public void Reset()
+ {
+ checkDisposed();
+ Position = 0;
+ }
+
+ // Reads the wrapped stream until its end.
+ private void Fill()
+ {
+ if (!eos)
+ {
+ memoryStream.Position = memoryStream.Length;
+ int bytesRead = 0;
+ byte[] buffer = new byte[1024];
+ do
+ {
+ bytesRead = stream.Read(buffer, 0, buffer.Length);
+ memoryStream.Write(buffer, 0, bytesRead);
+ } while (bytesRead != 0);
+ eos = true;
+ }
+ }
+
+ public new void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private new void Dispose(bool disposing)
+ {
+ if (!disposed)
+ {
+ disposed = true;
+ if (disposing)
+ {
+ if (memoryStream != null)
+ {
+ memoryStream.Dispose();
+ }
+ }
+ }
+ }
+
+ public bool Disposed
+ {
+ get { return disposed; }
+ }
+
+ private void checkDisposed()
+ {
+ if (disposed) throw new ObjectDisposedException("StreamWrapper");
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Delegates.cs b/Wrapper/FreeImage.NET/cs/Library/Delegates.cs
new file mode 100644
index 0000000..dda88f2
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Delegates.cs
@@ -0,0 +1,191 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.4 $
+// $Date: 2009/09/15 11:39:10 $
+// $Id: Delegates.cs,v 1.4 2009/09/15 11:39:10 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using FreeImageAPI.IO;
+
+namespace FreeImageAPI
+{
+ // Delegates used by the FreeImageIO structure
+
+ /// <summary>
+ /// Delegate for capturing FreeImage error messages.
+ /// </summary>
+ /// <param name="fif">The format of the image.</param>
+ /// <param name="message">The errormessage.</param>
+ // DLL_API is missing in the definition of the callbackfuntion.
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi, ThrowOnUnmappableChar = false)]
+ public delegate void OutputMessageFunction(FREE_IMAGE_FORMAT fif, string message);
+}
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Delegate to the C++ function <b>fread</b>.
+ /// </summary>
+ /// <param name="buffer">Pointer to read from.</param>
+ /// <param name="size">Item size in bytes.</param>
+ /// <param name="count">Maximum number of items to be read.</param>
+ /// <param name="handle">Handle/stream to read from.</param>
+ /// <returns>Number of full items actually read,
+ /// which may be less than count if an error occurs or
+ /// if the end of the file is encountered before reaching count.</returns>
+ public delegate uint ReadProc(IntPtr buffer, uint size, uint count, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fwrite</b>.
+ /// </summary>
+ /// <param name="buffer">Pointer to data to be written.</param>
+ /// <param name="size">Item size in bytes.</param>
+ /// <param name="count">Maximum number of items to be written.</param>
+ /// <param name="handle">Handle/stream to write to.</param>
+ /// <returns>Number of full items actually written,
+ /// which may be less than count if an error occurs.
+ /// Also, if an error occurs, the file-position indicator cannot be determined.</returns>
+ public delegate uint WriteProc(IntPtr buffer, uint size, uint count, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fseek</b>.
+ /// </summary>
+ /// <param name="handle">Handle/stream to seek in.</param>
+ /// <param name="offset">Number of bytes from origin.</param>
+ /// <param name="origin">Initial position.</param>
+ /// <returns>If successful 0 is returned; otherwise a nonzero value. </returns>
+ public delegate int SeekProc(fi_handle handle, int offset, SeekOrigin origin);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>ftell</b>.
+ /// </summary>
+ /// <param name="handle">Handle/stream to retrieve its currents position from.</param>
+ /// <returns>The current position.</returns>
+ public delegate int TellProc(fi_handle handle);
+
+ // Delegates used by 'Plugin' structure
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Delegate to a function that returns a string which describes
+ /// the plugins format.
+ /// </summary>
+ public delegate string FormatProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// a more detailed description.
+ /// </summary>
+ public delegate string DescriptionProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a comma seperated list
+ /// of file extensions the plugin can read or write.
+ /// </summary>
+ public delegate string ExtensionListProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a regular expression that
+ /// can be used to idientify whether a file can be handled by the plugin.
+ /// </summary>
+ public delegate string RegExprProc();
+
+ /// <summary>
+ /// Delegate to a function that opens a file.
+ /// </summary>
+ public delegate IntPtr OpenProc(ref FreeImageIO io, fi_handle handle, bool read);
+
+ /// <summary>
+ /// Delegate to a function that closes a previosly opened file.
+ /// </summary>
+ public delegate void CloseProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that returns the number of pages of a multipage
+ /// bitmap if the plugin is capable of handling multipage bitmaps.
+ /// </summary>
+ public delegate int PageCountProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// UNKNOWN
+ /// </summary>
+ public delegate int PageCapabilityProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that loads and decodes a bitmap into memory.
+ /// </summary>
+ public delegate FIBITMAP LoadProc(ref FreeImageIO io, fi_handle handle, int page, int flags, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that saves a bitmap.
+ /// </summary>
+ public delegate bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that determines whether the source defined
+ /// by <param name="io"/> and <param name="handle"/> is a valid image.
+ /// </summary>
+ public delegate bool ValidateProc(ref FreeImageIO io, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// the plugin's mime type.
+ /// </summary>
+ public delegate string MimeProc();
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified color depth.
+ /// </summary>
+ public delegate bool SupportsExportBPPProc(int bpp);
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified image type.
+ /// </summary>
+ public delegate bool SupportsExportTypeProc(FREE_IMAGE_TYPE type);
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle
+ /// ICC-Profiles.
+ /// </summary>
+ public delegate bool SupportsICCProfilesProc();
+
+ /// <summary>
+ /// Callback function used by FreeImage to register plugins.
+ /// </summary>
+ public delegate void InitProc(ref Plugin plugin, int format_id);
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/DisposalMethodType.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/DisposalMethodType.cs
new file mode 100644
index 0000000..ac2cd0c
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/DisposalMethodType.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Specifies how a single frame will be handled after being displayed.
+ /// </summary>
+ public enum DisposalMethodType : byte
+ {
+ /// <summary>
+ /// Same behavior as <see cref="DisposalMethodType.Leave"/> but should not be used.
+ /// </summary>
+ Unspecified,
+
+ /// <summary>
+ /// The image is left in place and will be overdrawn by the next image.
+ /// </summary>
+ Leave,
+
+ /// <summary>
+ /// The area of the image will be blanked out by its background.
+ /// </summary>
+ Background,
+
+ /// <summary>
+ /// Restores the the area of the image to the state it was before it
+ /// has been dawn.
+ /// </summary>
+ Previous,
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_CHANNEL.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_CHANNEL.cs
new file mode 100644
index 0000000..fbf2d39
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_CHANNEL.cs
@@ -0,0 +1,84 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: FREE_IMAGE_COLOR_CHANNEL.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Color channels. Constants used in color manipulation routines.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_CHANNEL
+ {
+ /// <summary>
+ /// Use red, green and blue channels
+ /// </summary>
+ FICC_RGB = 0,
+ /// <summary>
+ /// Use red channel
+ /// </summary>
+ FICC_RED = 1,
+ /// <summary>
+ /// Use green channel
+ /// </summary>
+ FICC_GREEN = 2,
+ /// <summary>
+ /// Use blue channel
+ /// </summary>
+ FICC_BLUE = 3,
+ /// <summary>
+ /// Use alpha channel
+ /// </summary>
+ FICC_ALPHA = 4,
+ /// <summary>
+ /// Use black channel
+ /// </summary>
+ FICC_BLACK = 5,
+ /// <summary>
+ /// Complex images: use real part
+ /// </summary>
+ FICC_REAL = 6,
+ /// <summary>
+ /// Complex images: use imaginary part
+ /// </summary>
+ FICC_IMAG = 7,
+ /// <summary>
+ /// Complex images: use magnitude
+ /// </summary>
+ FICC_MAG = 8,
+ /// <summary>
+ /// Complex images: use phase
+ /// </summary>
+ FICC_PHASE = 9
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_DEPTH.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_DEPTH.cs
new file mode 100644
index 0000000..10ccd0c
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_DEPTH.cs
@@ -0,0 +1,105 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_COLOR_DEPTH.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Enumeration used for color conversions.
+ /// FREE_IMAGE_COLOR_DEPTH contains several colors to convert to.
+ /// The default value 'FICD_AUTO'.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_COLOR_DEPTH
+ {
+ /// <summary>
+ /// Unknown.
+ /// </summary>
+ FICD_UNKNOWN = 0,
+ /// <summary>
+ /// Auto selected by the used algorithm.
+ /// </summary>
+ FICD_AUTO = FICD_UNKNOWN,
+ /// <summary>
+ /// 1-bit.
+ /// </summary>
+ FICD_01_BPP = 1,
+ /// <summary>
+ /// 1-bit using dithering.
+ /// </summary>
+ FICD_01_BPP_DITHER = FICD_01_BPP,
+ /// <summary>
+ /// 1-bit using threshold.
+ /// </summary>
+ FICD_01_BPP_THRESHOLD = FICD_01_BPP | 2,
+ /// <summary>
+ /// 4-bit.
+ /// </summary>
+ FICD_04_BPP = 4,
+ /// <summary>
+ /// 8-bit.
+ /// </summary>
+ FICD_08_BPP = 8,
+ /// <summary>
+ /// 16-bit 555 (1 bit remains unused).
+ /// </summary>
+ FICD_16_BPP_555 = FICD_16_BPP | 2,
+ /// <summary>
+ /// 16-bit 565 (all bits are used).
+ /// </summary>
+ FICD_16_BPP = 16,
+ /// <summary>
+ /// 24-bit.
+ /// </summary>
+ FICD_24_BPP = 24,
+ /// <summary>
+ /// 32-bit.
+ /// </summary>
+ FICD_32_BPP = 32,
+ /// <summary>
+ /// Reorder palette (make it linear). Only affects 1-, 4- and 8-bit images.
+ /// <para>The palette is only reordered in case the image is greyscale
+ /// (all palette entries have the same red, green and blue value).</para>
+ /// </summary>
+ FICD_REORDER_PALETTE = 1024,
+ /// <summary>
+ /// Converts the image to greyscale.
+ /// </summary>
+ FICD_FORCE_GREYSCALE = 2048,
+ /// <summary>
+ /// Flag to mask out all non color depth flags.
+ /// </summary>
+ FICD_COLOR_MASK = FICD_01_BPP | FICD_04_BPP | FICD_08_BPP | FICD_16_BPP | FICD_24_BPP | FICD_32_BPP
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_OPTIONS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_OPTIONS.cs
new file mode 100644
index 0000000..07f357e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_OPTIONS.cs
@@ -0,0 +1,68 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2009/09/15 11:44:24 $
+// $Id: FREE_IMAGE_COLOR_OPTIONS.cs,v 1.1 2009/09/15 11:44:24 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Constants used in color filling routines.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_OPTIONS
+ {
+ /// <summary>
+ /// Default value.
+ /// </summary>
+ FICO_DEFAULT = 0x0,
+ /// <summary>
+ /// <see cref="RGBQUAD"/> color is RGB color (contains no valid alpha channel).
+ /// </summary>
+ FICO_RGB = 0x0,
+ /// <summary>
+ /// <see cref="RGBQUAD"/> color is RGBA color (contains a valid alpha channel).
+ /// </summary>
+ FICO_RGBA = 0x1,
+ /// <summary>
+ /// Lookup nearest RGB color from palette.
+ /// </summary>
+ FICO_NEAREST_COLOR = 0x0,
+ /// <summary>
+ /// Lookup equal RGB color from palette.
+ /// </summary>
+ FICO_EQUAL_COLOR = 0x2,
+ /// <summary>
+ /// <see cref="RGBQUAD.rgbReserved"/> contains the palette index to be used.
+ /// </summary>
+ FICO_ALPHA_IS_INDEX = 0x4,
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_TYPE.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_TYPE.cs
new file mode 100644
index 0000000..3fbb5aa
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COLOR_TYPE.cs
@@ -0,0 +1,68 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: FREE_IMAGE_COLOR_TYPE.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Image color types used in FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_TYPE
+ {
+ /// <summary>
+ /// min value is white
+ /// </summary>
+ FIC_MINISWHITE = 0,
+ /// <summary>
+ /// min value is black
+ /// </summary>
+ FIC_MINISBLACK = 1,
+ /// <summary>
+ /// RGB color model
+ /// </summary>
+ FIC_RGB = 2,
+ /// <summary>
+ /// color map indexed
+ /// </summary>
+ FIC_PALETTE = 3,
+ /// <summary>
+ /// RGB color model with alpha channel
+ /// </summary>
+ FIC_RGBALPHA = 4,
+ /// <summary>
+ /// CMYK color model
+ /// </summary>
+ FIC_CMYK = 5
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COMPARE_FLAGS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COMPARE_FLAGS.cs
new file mode 100644
index 0000000..047b003
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_COMPARE_FLAGS.cs
@@ -0,0 +1,65 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: FREE_IMAGE_COMPARE_FLAGS.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// List of combinable compare modes.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_COMPARE_FLAGS
+ {
+ /// <summary>
+ /// Compare headers.
+ /// </summary>
+ HEADER = 0x1,
+ /// <summary>
+ /// Compare palettes.
+ /// </summary>
+ PALETTE = 0x2,
+ /// <summary>
+ /// Compare pixel data.
+ /// </summary>
+ DATA = 0x4,
+ /// <summary>
+ /// Compare meta data.
+ /// </summary>
+ METADATA = 0x8,
+ /// <summary>
+ /// Compare everything.
+ /// </summary>
+ COMPLETE = (HEADER | PALETTE | DATA | METADATA)
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_DITHER.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_DITHER.cs
new file mode 100644
index 0000000..5cf364c
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_DITHER.cs
@@ -0,0 +1,73 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: FREE_IMAGE_DITHER.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Dithering algorithms.
+ /// Constants used in FreeImage_Dither.
+ /// </summary>
+ public enum FREE_IMAGE_DITHER
+ {
+ /// <summary>
+ /// Floyd and Steinberg error diffusion
+ /// </summary>
+ FID_FS = 0,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+ /// </summary>
+ FID_BAYER4x4 = 1,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+ /// </summary>
+ FID_BAYER8x8 = 2,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 3 - 6x6 matrix)
+ /// </summary>
+ FID_CLUSTER6x6 = 3,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 4 - 8x8 matrix)
+ /// </summary>
+ FID_CLUSTER8x8 = 4,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 8 - 16x16 matrix)
+ /// </summary>
+ FID_CLUSTER16x16 = 5,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 4 dithering matrix)
+ /// </summary>
+ FID_BAYER16x16 = 6
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FILTER.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FILTER.cs
new file mode 100644
index 0000000..6b283b1
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FILTER.cs
@@ -0,0 +1,68 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_FILTER.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Upsampling / downsampling filters. Constants used in FreeImage_Rescale.
+ /// </summary>
+ public enum FREE_IMAGE_FILTER
+ {
+ /// <summary>
+ /// Box, pulse, Fourier window, 1st order (constant) b-spline
+ /// </summary>
+ FILTER_BOX = 0,
+ /// <summary>
+ /// Mitchell and Netravali's two-param cubic filter
+ /// </summary>
+ FILTER_BICUBIC = 1,
+ /// <summary>
+ /// Bilinear filter
+ /// </summary>
+ FILTER_BILINEAR = 2,
+ /// <summary>
+ /// 4th order (cubic) b-spline
+ /// </summary>
+ FILTER_BSPLINE = 3,
+ /// <summary>
+ /// Catmull-Rom spline, Overhauser spline
+ /// </summary>
+ FILTER_CATMULLROM = 4,
+ /// <summary>
+ /// Lanczos3 filter
+ /// </summary>
+ FILTER_LANCZOS3 = 5
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FORMAT.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FORMAT.cs
new file mode 100644
index 0000000..ecccf17
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_FORMAT.cs
@@ -0,0 +1,192 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.2 $
+// $Date: 2009/09/15 11:44:42 $
+// $Id: FREE_IMAGE_FORMAT.cs,v 1.2 2009/09/15 11:44:42 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// I/O image format identifiers.
+ /// </summary>
+ public enum FREE_IMAGE_FORMAT
+ {
+ /// <summary>
+ /// Unknown format (returned value only, never use it as input value)
+ /// </summary>
+ FIF_UNKNOWN = -1,
+ /// <summary>
+ /// Windows or OS/2 Bitmap File (*.BMP)
+ /// </summary>
+ FIF_BMP = 0,
+ /// <summary>
+ /// Windows Icon (*.ICO)
+ /// </summary>
+ FIF_ICO = 1,
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ FIF_JPEG = 2,
+ /// <summary>
+ /// JPEG Network Graphics (*.JNG)
+ /// </summary>
+ FIF_JNG = 3,
+ /// <summary>
+ /// Commodore 64 Koala format (*.KOA)
+ /// </summary>
+ FIF_KOALA = 4,
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ FIF_LBM = 5,
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ FIF_IFF = 5,
+ /// <summary>
+ /// Multiple Network Graphics (*.MNG)
+ /// </summary>
+ FIF_MNG = 6,
+ /// <summary>
+ /// Portable Bitmap (ASCII) (*.PBM)
+ /// </summary>
+ FIF_PBM = 7,
+ /// <summary>
+ /// Portable Bitmap (BINARY) (*.PBM)
+ /// </summary>
+ FIF_PBMRAW = 8,
+ /// <summary>
+ /// Kodak PhotoCD (*.PCD)
+ /// </summary>
+ FIF_PCD = 9,
+ /// <summary>
+ /// Zsoft Paintbrush PCX bitmap format (*.PCX)
+ /// </summary>
+ FIF_PCX = 10,
+ /// <summary>
+ /// Portable Graymap (ASCII) (*.PGM)
+ /// </summary>
+ FIF_PGM = 11,
+ /// <summary>
+ /// Portable Graymap (BINARY) (*.PGM)
+ /// </summary>
+ FIF_PGMRAW = 12,
+ /// <summary>
+ /// Portable Network Graphics (*.PNG)
+ /// </summary>
+ FIF_PNG = 13,
+ /// <summary>
+ /// Portable Pixelmap (ASCII) (*.PPM)
+ /// </summary>
+ FIF_PPM = 14,
+ /// <summary>
+ /// Portable Pixelmap (BINARY) (*.PPM)
+ /// </summary>
+ FIF_PPMRAW = 15,
+ /// <summary>
+ /// Sun Rasterfile (*.RAS)
+ /// </summary>
+ FIF_RAS = 16,
+ /// <summary>
+ /// truevision Targa files (*.TGA, *.TARGA)
+ /// </summary>
+ FIF_TARGA = 17,
+ /// <summary>
+ /// Tagged Image File Format (*.TIF, *.TIFF)
+ /// </summary>
+ FIF_TIFF = 18,
+ /// <summary>
+ /// Wireless Bitmap (*.WBMP)
+ /// </summary>
+ FIF_WBMP = 19,
+ /// <summary>
+ /// Adobe Photoshop (*.PSD)
+ /// </summary>
+ FIF_PSD = 20,
+ /// <summary>
+ /// Dr. Halo (*.CUT)
+ /// </summary>
+ FIF_CUT = 21,
+ /// <summary>
+ /// X11 Bitmap Format (*.XBM)
+ /// </summary>
+ FIF_XBM = 22,
+ /// <summary>
+ /// X11 Pixmap Format (*.XPM)
+ /// </summary>
+ FIF_XPM = 23,
+ /// <summary>
+ /// DirectDraw Surface (*.DDS)
+ /// </summary>
+ FIF_DDS = 24,
+ /// <summary>
+ /// Graphics Interchange Format (*.GIF)
+ /// </summary>
+ FIF_GIF = 25,
+ /// <summary>
+ /// High Dynamic Range (*.HDR)
+ /// </summary>
+ FIF_HDR = 26,
+ /// <summary>
+ /// Raw Fax format CCITT G3 (*.G3)
+ /// </summary>
+ FIF_FAXG3 = 27,
+ /// <summary>
+ /// Silicon Graphics SGI image format (*.SGI)
+ /// </summary>
+ FIF_SGI = 28,
+ /// <summary>
+ /// OpenEXR format (*.EXR)
+ /// </summary>
+ FIF_EXR = 29,
+ /// <summary>
+ /// JPEG-2000 format (*.J2K, *.J2C)
+ /// </summary>
+ FIF_J2K = 30,
+ /// <summary>
+ /// JPEG-2000 format (*.JP2)
+ /// </summary>
+ FIF_JP2 = 31,
+ /// <summary>
+ /// Portable FloatMap (*.PFM)
+ /// </summary>
+ FIF_PFM = 32,
+ /// <summary>
+ /// Macintosh PICT (*.PICT)
+ /// </summary>
+ FIF_PICT = 33,
+ /// <summary>
+ /// RAW camera image (*.*)
+ /// </summary>
+ FIF_RAW = 34,
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_JPEG_OPERATION.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_JPEG_OPERATION.cs
new file mode 100644
index 0000000..d493f55
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_JPEG_OPERATION.cs
@@ -0,0 +1,76 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:38 $
+// $Id: FREE_IMAGE_JPEG_OPERATION.cs,v 1.1 2007/11/28 15:33:38 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Lossless JPEG transformations constants used in FreeImage_JPEGTransform.
+ /// </summary>
+ public enum FREE_IMAGE_JPEG_OPERATION
+ {
+ /// <summary>
+ /// no transformation
+ /// </summary>
+ FIJPEG_OP_NONE = 0,
+ /// <summary>
+ /// horizontal flip
+ /// </summary>
+ FIJPEG_OP_FLIP_H = 1,
+ /// <summary>
+ /// vertical flip
+ /// </summary>
+ FIJPEG_OP_FLIP_V = 2,
+ /// <summary>
+ /// transpose across UL-to-LR axis
+ /// </summary>
+ FIJPEG_OP_TRANSPOSE = 3,
+ /// <summary>
+ /// transpose across UR-to-LL axis
+ /// </summary>
+ FIJPEG_OP_TRANSVERSE = 4,
+ /// <summary>
+ /// 90-degree clockwise rotation
+ /// </summary>
+ FIJPEG_OP_ROTATE_90 = 5,
+ /// <summary>
+ /// 180-degree rotation
+ /// </summary>
+ FIJPEG_OP_ROTATE_180 = 6,
+ /// <summary>
+ /// 270-degree clockwise (or 90 ccw)
+ /// </summary>
+ FIJPEG_OP_ROTATE_270 = 7
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_LOAD_FLAGS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_LOAD_FLAGS.cs
new file mode 100644
index 0000000..5e2b4d4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_LOAD_FLAGS.cs
@@ -0,0 +1,111 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.2 $
+// $Date: 2009/09/15 11:45:16 $
+// $Id: FREE_IMAGE_LOAD_FLAGS.cs,v 1.2 2009/09/15 11:45:16 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags used in load functions.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_LOAD_FLAGS
+ {
+ /// <summary>
+ /// Default option for all types.
+ /// </summary>
+ DEFAULT = 0,
+ /// <summary>
+ /// Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color.
+ /// </summary>
+ GIF_LOAD256 = 1,
+ /// <summary>
+ /// 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading.
+ /// </summary>
+ GIF_PLAYBACK = 2,
+ /// <summary>
+ /// Convert to 32bpp and create an alpha channel from the AND-mask when loading.
+ /// </summary>
+ ICO_MAKEALPHA = 1,
+ /// <summary>
+ /// Load the file as fast as possible, sacrificing some quality.
+ /// </summary>
+ JPEG_FAST = 0x0001,
+ /// <summary>
+ /// Load the file with the best quality, sacrificing some speed.
+ /// </summary>
+ JPEG_ACCURATE = 0x0002,
+ /// <summary>
+ /// Load separated CMYK "as is" (use | to combine with other load flags).
+ /// </summary>
+ JPEG_CMYK = 0x0004,
+ /// <summary>
+ /// Load and rotate according to Exif 'Orientation' tag if available.
+ /// </summary>
+ JPEG_EXIFROTATE = 0x0008,
+ /// <summary>
+ /// Load the bitmap sized 768 x 512.
+ /// </summary>
+ PCD_BASE = 1,
+ /// <summary>
+ /// Load the bitmap sized 384 x 256.
+ /// </summary>
+ PCD_BASEDIV4 = 2,
+ /// <summary>
+ /// Load the bitmap sized 192 x 128.
+ /// </summary>
+ PCD_BASEDIV16 = 3,
+ /// <summary>
+ /// Avoid gamma correction.
+ /// </summary>
+ PNG_IGNOREGAMMA = 1,
+ /// <summary>
+ /// If set the loader converts RGB555 and ARGB8888 -> RGB888.
+ /// </summary>
+ TARGA_LOAD_RGB888 = 1,
+ /// <summary>
+ /// Reads tags for separated CMYK.
+ /// </summary>
+ TIFF_CMYK = 0x0001,
+ /// <summary>
+ /// Tries to load the JPEG preview image, embedded in
+ /// Exif Metadata or load the image as RGB 24-bit if no
+ /// preview image is available.
+ /// </summary>
+ RAW_PREVIEW = 0x1,
+ /// <summary>
+ /// Loads the image as RGB 24-bit.
+ /// </summary>
+ RAW_DISPLAY = 0x2,
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDMODEL.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDMODEL.cs
new file mode 100644
index 0000000..99907aa
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDMODEL.cs
@@ -0,0 +1,92 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_MDMODEL.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Metadata models supported by FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_MDMODEL
+ {
+ /// <summary>
+ /// No data
+ /// </summary>
+ FIMD_NODATA = -1,
+ /// <summary>
+ /// single comment or keywords
+ /// </summary>
+ FIMD_COMMENTS = 0,
+ /// <summary>
+ /// Exif-TIFF metadata
+ /// </summary>
+ FIMD_EXIF_MAIN = 1,
+ /// <summary>
+ /// Exif-specific metadata
+ /// </summary>
+ FIMD_EXIF_EXIF = 2,
+ /// <summary>
+ /// Exif GPS metadata
+ /// </summary>
+ FIMD_EXIF_GPS = 3,
+ /// <summary>
+ /// Exif maker note metadata
+ /// </summary>
+ FIMD_EXIF_MAKERNOTE = 4,
+ /// <summary>
+ /// Exif interoperability metadata
+ /// </summary>
+ FIMD_EXIF_INTEROP = 5,
+ /// <summary>
+ /// IPTC/NAA metadata
+ /// </summary>
+ FIMD_IPTC = 6,
+ /// <summary>
+ /// Abobe XMP metadata
+ /// </summary>
+ FIMD_XMP = 7,
+ /// <summary>
+ /// GeoTIFF metadata
+ /// </summary>
+ FIMD_GEOTIFF = 8,
+ /// <summary>
+ /// Animation metadata
+ /// </summary>
+ FIMD_ANIMATION = 9,
+ /// <summary>
+ /// Used to attach other metadata types to a dib
+ /// </summary>
+ FIMD_CUSTOM = 10
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDTYPE.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDTYPE.cs
new file mode 100644
index 0000000..6a3060b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_MDTYPE.cs
@@ -0,0 +1,105 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_MDTYPE.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Tag data type information (based on TIFF specifications)
+ /// Note: RATIONALs are the ratio of two 32-bit integer values.
+ /// </summary>
+ public enum FREE_IMAGE_MDTYPE
+ {
+ /// <summary>
+ /// placeholder
+ /// </summary>
+ FIDT_NOTYPE = 0,
+ /// <summary>
+ /// 8-bit unsigned integer
+ /// </summary>
+ FIDT_BYTE = 1,
+ /// <summary>
+ /// 8-bit bytes w/ last byte null
+ /// </summary>
+ FIDT_ASCII = 2,
+ /// <summary>
+ /// 16-bit unsigned integer
+ /// </summary>
+ FIDT_SHORT = 3,
+ /// <summary>
+ /// 32-bit unsigned integer
+ /// </summary>
+ FIDT_LONG = 4,
+ /// <summary>
+ /// 64-bit unsigned fraction
+ /// </summary>
+ FIDT_RATIONAL = 5,
+ /// <summary>
+ /// 8-bit signed integer
+ /// </summary>
+ FIDT_SBYTE = 6,
+ /// <summary>
+ /// 8-bit untyped data
+ /// </summary>
+ FIDT_UNDEFINED = 7,
+ /// <summary>
+ /// 16-bit signed integer
+ /// </summary>
+ FIDT_SSHORT = 8,
+ /// <summary>
+ /// 32-bit signed integer
+ /// </summary>
+ FIDT_SLONG = 9,
+ /// <summary>
+ /// 64-bit signed fraction
+ /// </summary>
+ FIDT_SRATIONAL = 10,
+ /// <summary>
+ /// 32-bit IEEE floating point
+ /// </summary>
+ FIDT_FLOAT = 11,
+ /// <summary>
+ /// 64-bit IEEE floating point
+ /// </summary>
+ FIDT_DOUBLE = 12,
+ /// <summary>
+ /// 32-bit unsigned integer (offset)
+ /// </summary>
+ FIDT_IFD = 13,
+ /// <summary>
+ /// 32-bit RGBQUAD
+ /// </summary>
+ FIDT_PALETTE = 14
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_METADATA_COPY.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_METADATA_COPY.cs
new file mode 100644
index 0000000..d487ea0
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_METADATA_COPY.cs
@@ -0,0 +1,56 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_METADATA_COPY.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags for copying data from a bitmap to another.
+ /// </summary>
+ public enum FREE_IMAGE_METADATA_COPY
+ {
+ /// <summary>
+ /// Exisiting metadata will remain unchanged.
+ /// </summary>
+ KEEP_EXISITNG = 0x0,
+ /// <summary>
+ /// Existing metadata will be cleared.
+ /// </summary>
+ CLEAR_EXISTING = 0x1,
+ /// <summary>
+ /// Existing metadata will be overwritten.
+ /// </summary>
+ REPLACE_EXISTING = 0x2
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_QUANTIZE.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_QUANTIZE.cs
new file mode 100644
index 0000000..aa05d7f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_QUANTIZE.cs
@@ -0,0 +1,53 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_QUANTIZE.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Color quantization algorithms.
+ /// Constants used in FreeImage_ColorQuantize.
+ /// </summary>
+ public enum FREE_IMAGE_QUANTIZE
+ {
+ /// <summary>
+ /// Xiaolin Wu color quantization algorithm
+ /// </summary>
+ FIQ_WUQUANT = 0,
+ /// <summary>
+ /// NeuQuant neural-net quantization algorithm by Anthony Dekker
+ /// </summary>
+ FIQ_NNQUANT = 1
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_SAVE_FLAGS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_SAVE_FLAGS.cs
new file mode 100644
index 0000000..ebd9e38
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_SAVE_FLAGS.cs
@@ -0,0 +1,183 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.2 $
+// $Date: 2008/06/16 15:14:24 $
+// $Id: FREE_IMAGE_SAVE_FLAGS.cs,v 1.2 2008/06/16 15:14:24 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags used in save functions.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_SAVE_FLAGS
+ {
+ /// <summary>
+ /// Default option for all types.
+ /// </summary>
+ DEFAULT = 0,
+ /// <summary>
+ /// Save with run length encoding.
+ /// </summary>
+ BMP_SAVE_RLE = 1,
+ /// <summary>
+ /// Save data as float instead of as half (not recommended).
+ /// </summary>
+ EXR_FLOAT = 0x0001,
+ /// <summary>
+ /// Save with no compression.
+ /// </summary>
+ EXR_NONE = 0x0002,
+ /// <summary>
+ /// Save with zlib compression, in blocks of 16 scan lines.
+ /// </summary>
+ EXR_ZIP = 0x0004,
+ /// <summary>
+ /// Save with piz-based wavelet compression.
+ /// </summary>
+ EXR_PIZ = 0x0008,
+ /// <summary>
+ /// Save with lossy 24-bit float compression.
+ /// </summary>
+ EXR_PXR24 = 0x0010,
+ /// <summary>
+ /// Save with lossy 44% float compression - goes to 22% when combined with EXR_LC.
+ /// </summary>
+ EXR_B44 = 0x0020,
+ /// <summary>
+ /// Save images with one luminance and two chroma channels, rather than as RGB (lossy compression).
+ /// </summary>
+ EXR_LC = 0x0040,
+ /// <summary>
+ /// Save with superb quality (100:1).
+ /// </summary>
+ JPEG_QUALITYSUPERB = 0x80,
+ /// <summary>
+ /// Save with good quality (75:1).
+ /// </summary>
+ JPEG_QUALITYGOOD = 0x0100,
+ /// <summary>
+ /// Save with normal quality (50:1).
+ /// </summary>
+ JPEG_QUALITYNORMAL = 0x0200,
+ /// <summary>
+ /// Save with average quality (25:1).
+ /// </summary>
+ JPEG_QUALITYAVERAGE = 0x0400,
+ /// <summary>
+ /// Save with bad quality (10:1).
+ /// </summary>
+ JPEG_QUALITYBAD = 0x0800,
+ /// <summary>
+ /// Save as a progressive-JPEG (use | to combine with other save flags).
+ /// </summary>
+ JPEG_PROGRESSIVE = 0x2000,
+ /// <summary>
+ /// Save with high 4x1 chroma subsampling (4:1:1).
+ /// </summary>
+ JPEG_SUBSAMPLING_411 = 0x1000,
+ /// <summary>
+ /// Save with medium 2x2 medium chroma (4:2:0).
+ /// </summary>
+ JPEG_SUBSAMPLING_420 = 0x4000,
+ /// <summary>
+ /// Save with low 2x1 chroma subsampling (4:2:2).
+ /// </summary>
+ JPEG_SUBSAMPLING_422 = 0x8000,
+ /// <summary>
+ /// Save with no chroma subsampling (4:4:4).
+ /// </summary>
+ JPEG_SUBSAMPLING_444 = 0x10000,
+ /// <summary>
+ /// Save using ZLib level 1 compression flag
+ /// (default value is <see cref="PNG_Z_DEFAULT_COMPRESSION"/>).
+ /// </summary>
+ PNG_Z_BEST_SPEED = 0x0001,
+ /// <summary>
+ /// Save using ZLib level 6 compression flag (default recommended value).
+ /// </summary>
+ PNG_Z_DEFAULT_COMPRESSION = 0x0006,
+ /// <summary>
+ /// save using ZLib level 9 compression flag
+ /// (default value is <see cref="PNG_Z_DEFAULT_COMPRESSION"/>).
+ /// </summary>
+ PNG_Z_BEST_COMPRESSION = 0x0009,
+ /// <summary>
+ /// Save without ZLib compression.
+ /// </summary>
+ PNG_Z_NO_COMPRESSION = 0x0100,
+ /// <summary>
+ /// Save using Adam7 interlacing (use | to combine with other save flags).
+ /// </summary>
+ PNG_INTERLACED = 0x0200,
+ /// <summary>
+ /// If set the writer saves in ASCII format (i.e. P1, P2 or P3).
+ /// </summary>
+ PNM_SAVE_ASCII = 1,
+ /// <summary>
+ /// Stores tags for separated CMYK (use | to combine with compression flags).
+ /// </summary>
+ TIFF_CMYK = 0x0001,
+ /// <summary>
+ /// Save using PACKBITS compression.
+ /// </summary>
+ TIFF_PACKBITS = 0x0100,
+ /// <summary>
+ /// Save using DEFLATE compression (a.k.a. ZLIB compression).
+ /// </summary>
+ TIFF_DEFLATE = 0x0200,
+ /// <summary>
+ /// Save using ADOBE DEFLATE compression.
+ /// </summary>
+ TIFF_ADOBE_DEFLATE = 0x0400,
+ /// <summary>
+ /// Save without any compression.
+ /// </summary>
+ TIFF_NONE = 0x0800,
+ /// <summary>
+ /// Save using CCITT Group 3 fax encoding.
+ /// </summary>
+ TIFF_CCITTFAX3 = 0x1000,
+ /// <summary>
+ /// Save using CCITT Group 4 fax encoding.
+ /// </summary>
+ TIFF_CCITTFAX4 = 0x2000,
+ /// <summary>
+ /// Save using LZW compression.
+ /// </summary>
+ TIFF_LZW = 0x4000,
+ /// <summary>
+ /// Save using JPEG compression.
+ /// </summary>
+ TIFF_JPEG = 0x8000
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TMO.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TMO.cs
new file mode 100644
index 0000000..36033e4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TMO.cs
@@ -0,0 +1,56 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:39 $
+// $Id: FREE_IMAGE_TMO.cs,v 1.1 2007/11/28 15:33:39 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Tone mapping operators. Constants used in FreeImage_ToneMapping.
+ /// </summary>
+ public enum FREE_IMAGE_TMO
+ {
+ /// <summary>
+ /// Adaptive logarithmic mapping (F. Drago, 2003)
+ /// </summary>
+ FITMO_DRAGO03 = 0,
+ /// <summary>
+ /// Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+ /// </summary>
+ FITMO_REINHARD05 = 1,
+ /// <summary>
+ /// Gradient domain high dynamic range compression (R. Fattal, 2002)
+ /// </summary>
+ FITMO_FATTAL02
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TYPE.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TYPE.cs
new file mode 100644
index 0000000..a407bca
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/FREE_IMAGE_TYPE.cs
@@ -0,0 +1,96 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: FREE_IMAGE_TYPE.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Image types used in FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_TYPE
+ {
+ /// <summary>
+ /// unknown type
+ /// </summary>
+ FIT_UNKNOWN = 0,
+ /// <summary>
+ /// standard image : 1-, 4-, 8-, 16-, 24-, 32-bit
+ /// </summary>
+ FIT_BITMAP = 1,
+ /// <summary>
+ /// array of unsigned short : unsigned 16-bit
+ /// </summary>
+ FIT_UINT16 = 2,
+ /// <summary>
+ /// array of short : signed 16-bit
+ /// </summary>
+ FIT_INT16 = 3,
+ /// <summary>
+ /// array of unsigned long : unsigned 32-bit
+ /// </summary>
+ FIT_UINT32 = 4,
+ /// <summary>
+ /// array of long : signed 32-bit
+ /// </summary>
+ FIT_INT32 = 5,
+ /// <summary>
+ /// array of float : 32-bit IEEE floating point
+ /// </summary>
+ FIT_FLOAT = 6,
+ /// <summary>
+ /// array of double : 64-bit IEEE floating point
+ /// </summary>
+ FIT_DOUBLE = 7,
+ /// <summary>
+ /// array of FICOMPLEX : 2 x 64-bit IEEE floating point
+ /// </summary>
+ FIT_COMPLEX = 8,
+ /// <summary>
+ /// 48-bit RGB image : 3 x 16-bit
+ /// </summary>
+ FIT_RGB16 = 9,
+ /// <summary>
+ /// 64-bit RGBA image : 4 x 16-bit
+ /// </summary>
+ FIT_RGBA16 = 10,
+ /// <summary>
+ /// 96-bit RGB float image : 3 x 32-bit IEEE floating point
+ /// </summary>
+ FIT_RGBF = 11,
+ /// <summary>
+ /// 128-bit RGBA float image : 4 x 32-bit IEEE floating point
+ /// </summary>
+ FIT_RGBAF = 12
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/ICC_FLAGS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/ICC_FLAGS.cs
new file mode 100644
index 0000000..2e1cdee
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/ICC_FLAGS.cs
@@ -0,0 +1,53 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:38 $
+// $Id: ICC_FLAGS.cs,v 1.1 2007/11/28 15:33:38 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags for ICC profiles.
+ /// </summary>
+ [System.Flags]
+ public enum ICC_FLAGS : ushort
+ {
+ /// <summary>
+ /// Default value.
+ /// </summary>
+ FIICC_DEFAULT = 0x00,
+ /// <summary>
+ /// The color is CMYK.
+ /// </summary>
+ FIICC_COLOR_IS_CMYK = 0x01
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Enumerations/MD_SEARCH_FLAGS.cs b/Wrapper/FreeImage.NET/cs/Library/Enumerations/MD_SEARCH_FLAGS.cs
new file mode 100644
index 0000000..923f7e9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Enumerations/MD_SEARCH_FLAGS.cs
@@ -0,0 +1,57 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.1 $
+// $Date: 2007/11/28 15:33:40 $
+// $Id: MD_SEARCH_FLAGS.cs,v 1.1 2007/11/28 15:33:40 cklein05 Exp $
+// ==========================================================
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// List different search modes.
+ /// </summary>
+ [System.Flags]
+ public enum MD_SEARCH_FLAGS
+ {
+ /// <summary>
+ /// The key of the metadata.
+ /// </summary>
+ KEY = 0x1,
+ /// <summary>
+ /// The description of the metadata
+ /// </summary>
+ DESCRIPTION = 0x2,
+ /// <summary>
+ /// The ToString value of the metadata
+ /// </summary>
+ TOSTRING = 0x4,
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/FreeImageStaticImports.cs b/Wrapper/FreeImage.NET/cs/Library/FreeImageStaticImports.cs
new file mode 100644
index 0000000..35e675d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/FreeImageStaticImports.cs
@@ -0,0 +1,2369 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.9 $
+// $Date: 2009/09/15 11:41:37 $
+// $Id: FreeImageStaticImports.cs,v 1.9 2009/09/15 11:41:37 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+using FreeImageAPI.Plugins;
+using FreeImageAPI.IO;
+
+namespace FreeImageAPI
+{
+ public static partial class FreeImage
+ {
+ #region Constants
+
+ /// <summary>
+ /// Filename of the FreeImage library.
+ /// </summary>
+ private const string FreeImageLibrary = "FreeImage";
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_RED = 2;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_GREEN = 1;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_BLUE = 0;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_ALPHA = 3;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_RED_MASK = 0x00FF0000;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_GREEN_MASK = 0x0000FF00;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_BLUE_MASK = 0x000000FF;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_ALPHA_MASK = 0xFF000000;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_RED_SHIFT = 16;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_GREEN_SHIFT = 8;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_BLUE_SHIFT = 0;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_ALPHA_SHIFT = 24;
+
+ /// <summary>
+ /// Mask indicating the position of color components of a 32 bit color.
+ /// </summary>
+ public const uint FI_RGBA_RGB_MASK = (FI_RGBA_RED_MASK | FI_RGBA_GREEN_MASK | FI_RGBA_BLUE_MASK);
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_RED_MASK = 0x7C00;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_GREEN_MASK = 0x03E0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_BLUE_MASK = 0x001F;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_RED_SHIFT = 10;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_GREEN_SHIFT = 5;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_BLUE_SHIFT = 0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_RED_MASK = 0xF800;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_GREEN_MASK = 0x07E0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_BLUE_MASK = 0x001F;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_RED_SHIFT = 11;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_GREEN_SHIFT = 5;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_BLUE_SHIFT = 0;
+
+ #endregion
+
+ #region General functions
+
+ /// <summary>
+ /// Initialises the library.
+ /// </summary>
+ /// <param name="load_local_plugins_only">
+ /// When the <paramref name="load_local_plugins_only"/> is true, FreeImage won't make use of external plugins.
+ /// </param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Initialise")]
+ private static extern void Initialise(bool load_local_plugins_only);
+
+ /// <summary>
+ /// Deinitialises the library.
+ /// </summary>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeInitialise")]
+ private static extern void DeInitialise();
+
+ /// <summary>
+ /// Returns a string containing the current version of the library.
+ /// </summary>
+ /// <returns>The current version of the library.</returns>
+ public static unsafe string GetVersion() { return PtrToStr(GetVersion_()); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetVersion")]
+ private static unsafe extern byte* GetVersion_();
+
+ /// <summary>
+ /// Returns a string containing a standard copyright message.
+ /// </summary>
+ /// <returns>A standard copyright message.</returns>
+ public static unsafe string GetCopyrightMessage() { return PtrToStr(GetCopyrightMessage_()); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetCopyrightMessage")]
+ private static unsafe extern byte* GetCopyrightMessage_();
+
+ /// <summary>
+ /// Calls the set error message function in FreeImage.
+ /// </summary>
+ /// <param name="fif">Format of the bitmaps.</param>
+ /// <param name="message">The error message.</param>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_OutputMessageProc")]
+ public static extern void OutputMessageProc(FREE_IMAGE_FORMAT fif, string message);
+
+ /// <summary>
+ /// You use the function FreeImage_SetOutputMessage to capture the log string
+ /// so that you can show it to the user of the program.
+ /// The callback is implemented in the <see cref="FreeImageEngine.Message"/> event of this class.
+ /// </summary>
+ /// <remarks>The function is private because FreeImage can only have a single
+ /// callback function. To use the callback use the <see cref="FreeImageEngine.Message"/>
+ /// event of this class.</remarks>
+ /// <param name="omf">Handler to the callback function.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetOutputMessage")]
+ internal static extern void SetOutputMessage(OutputMessageFunction omf);
+
+ #endregion
+
+ #region Bitmap management functions
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Allocate")]
+ public static extern FIBITMAP Allocate(int width, int height, int bpp,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateT")]
+ public static extern FIBITMAP AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateEx")]
+ internal static extern FIBITMAP AllocateEx(int width, int height, int bpp,
+ IntPtr color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateExT")]
+ internal static extern FIBITMAP AllocateExT(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ IntPtr color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ /// <summary>
+ /// Makes an exact reproduction of an existing bitmap, including metadata and attached profile if any.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Clone")]
+ public static extern FIBITMAP Clone(FIBITMAP dib);
+
+ /// <summary>
+ /// Deletes a previously loaded FIBITMAP from memory.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Unload")]
+ public static extern void Unload(FIBITMAP dib);
+
+ /// <summary>
+ /// Decodes a bitmap, allocates memory for it and returns it as a FIBITMAP.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="filename">Name of the file to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_LoadU")]
+ public static extern FIBITMAP Load(FREE_IMAGE_FORMAT fif, string filename, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Decodes a bitmap, allocates memory for it and returns it as a FIBITMAP.
+ /// The filename supports UNICODE.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="filename">Name of the file to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_LoadU")]
+ private static extern FIBITMAP LoadU(FREE_IMAGE_FORMAT fif, string filename, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Loads a bitmap from an arbitrary source.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="io">A FreeImageIO structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadFromHandle")]
+ public static extern FIBITMAP LoadFromHandle(FREE_IMAGE_FORMAT fif, ref FreeImageIO io, fi_handle handle, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a file.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_SaveU")]
+ public static extern bool Save(FREE_IMAGE_FORMAT fif, FIBITMAP dib, string filename, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a file.
+ /// The filename supports UNICODE.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_SaveU")]
+ private static extern bool SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP dib, string filename, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Saves a bitmap to an arbitrary source.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="io">A FreeImageIO structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SaveToHandle")]
+ public static extern bool SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP dib, ref FreeImageIO io, fi_handle handle,
+ FREE_IMAGE_SAVE_FLAGS flags);
+
+ #endregion
+
+ #region Memory I/O streams
+
+ /// <summary>
+ /// Open a memory stream.
+ /// </summary>
+ /// <param name="data">Pointer to the data in memory.</param>
+ /// <param name="size_in_bytes">Length of the data in byte.</param>
+ /// <returns>Handle to a memory stream.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMemory")]
+ public static extern FIMEMORY OpenMemory(IntPtr data, uint size_in_bytes);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMemory")]
+ internal static extern FIMEMORY OpenMemoryEx(byte[] data, uint size_in_bytes);
+
+ /// <summary>
+ /// Close and free a memory stream.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloseMemory")]
+ public static extern void CloseMemory(FIMEMORY stream);
+
+ /// <summary>
+ /// Decodes a bitmap from a stream, allocates memory for it and returns it as a FIBITMAP.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadFromMemory")]
+ public static extern FIBITMAP LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY stream, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a stream.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SaveToMemory")]
+ public static extern bool SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP dib, FIMEMORY stream, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Gets the current position of a memory handle.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <returns>The current file position if successful, -1 otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TellMemory")]
+ public static extern int TellMemory(FIMEMORY stream);
+
+ /// <summary>
+ /// Moves the memory handle to a specified location.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="offset">Number of bytes from origin.</param>
+ /// <param name="origin">Initial position.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SeekMemory")]
+ public static extern bool SeekMemory(FIMEMORY stream, int offset, System.IO.SeekOrigin origin);
+
+ /// <summary>
+ /// Provides a direct buffer access to a memory stream.
+ /// </summary>
+ /// <param name="stream">The target memory stream.</param>
+ /// <param name="data">Pointer to the data in memory.</param>
+ /// <param name="size_in_bytes">Size of the data in bytes.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AcquireMemory")]
+ public static extern bool AcquireMemory(FIMEMORY stream, ref IntPtr data, ref uint size_in_bytes);
+
+ /// <summary>
+ /// Reads data from a memory stream.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the data in.</param>
+ /// <param name="size">Size in bytes of the items.</param>
+ /// <param name="count">Number of items to read.</param>
+ /// <param name="stream">The stream to read from.
+ /// The memory pointer associated with stream is increased by the number of bytes actually read.</param>
+ /// <returns>The number of full items actually read.
+ /// May be less than count on error or stream-end.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ReadMemory")]
+ public static extern uint ReadMemory(byte[] buffer, uint size, uint count, FIMEMORY stream);
+
+ /// <summary>
+ /// Writes data to a memory stream.
+ /// </summary>
+ /// <param name="buffer">The buffer to read the data from.</param>
+ /// <param name="size">Size in bytes of the items.</param>
+ /// <param name="count">Number of items to write.</param>
+ /// <param name="stream">The stream to write to.
+ /// The memory pointer associated with stream is increased by the number of bytes actually written.</param>
+ /// <returns>The number of full items actually written.
+ /// May be less than count on error or stream-end.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_WriteMemory")]
+ public static extern uint WriteMemory(byte[] buffer, uint size, uint count, FIMEMORY stream);
+
+ /// <summary>
+ /// Open a multi-page bitmap from a memory stream.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="stream">The stream to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadMultiBitmapFromMemory")]
+ public static extern FIMULTIBITMAP LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY stream, FREE_IMAGE_LOAD_FLAGS flags);
+
+ #endregion
+
+ #region Plugin functions
+
+ /// <summary>
+ /// Registers a new plugin to be used in FreeImage.
+ /// </summary>
+ /// <param name="proc_address">Pointer to the function that initialises the plugin.</param>
+ /// <param name="format">A string describing the format of the plugin.</param>
+ /// <param name="description">A string describing the plugin.</param>
+ /// <param name="extension">A string witha comma sperated list of extensions. f.e: "pl,pl2,pl4"</param>
+ /// <param name="regexpr">A regular expression used to identify the bitmap.</param>
+ /// <returns>The format idientifier assigned by FreeImage.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_RegisterLocalPlugin")]
+ public static extern FREE_IMAGE_FORMAT RegisterLocalPlugin(InitProc proc_address,
+ string format, string description, string extension, string regexpr);
+
+ /// <summary>
+ /// Registers a new plugin to be used in FreeImage. The plugin is residing in a DLL.
+ /// The Init function must be called “Init” and must use the stdcall calling convention.
+ /// </summary>
+ /// <param name="path">Complete path to the dll file hosting the plugin.</param>
+ /// <param name="format">A string describing the format of the plugin.</param>
+ /// <param name="description">A string describing the plugin.</param>
+ /// <param name="extension">A string witha comma sperated list of extensions. f.e: "pl,pl2,pl4"</param>
+ /// <param name="regexpr">A regular expression used to identify the bitmap.</param>
+ /// <returns>The format idientifier assigned by FreeImage.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_RegisterExternalPlugin")]
+ public static extern FREE_IMAGE_FORMAT RegisterExternalPlugin(string path,
+ string format, string description, string extension, string regexpr);
+
+ /// <summary>
+ /// Retrieves the number of FREE_IMAGE_FORMAT identifiers being currently registered.
+ /// </summary>
+ /// <returns>The number of registered formats.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFCount")]
+ public static extern int GetFIFCount();
+
+ /// <summary>
+ /// Enables or disables a plugin.
+ /// </summary>
+ /// <param name="fif">The plugin to enable or disable.</param>
+ /// <param name="enable">True: enable the plugin. false: disable the plugin.</param>
+ /// <returns>The previous state of the plugin.
+ /// 1 - enabled. 0 - disables. -1 plugin does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPluginEnabled")]
+ public static extern int SetPluginEnabled(FREE_IMAGE_FORMAT fif, bool enable);
+
+ /// <summary>
+ /// Retrieves the state of a plugin.
+ /// </summary>
+ /// <param name="fif">The plugin to check.</param>
+ /// <returns>1 - enabled. 0 - disables. -1 plugin does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsPluginEnabled")]
+ public static extern int IsPluginEnabled(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a <see cref="FREE_IMAGE_FORMAT"/> identifier from the format string that was used to register the FIF.
+ /// </summary>
+ /// <param name="format">The string that was used to register the plugin.</param>
+ /// <returns>A <see cref="FREE_IMAGE_FORMAT"/> identifier from the format.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetFIFFromFormat")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromFormat(string format);
+
+ /// <summary>
+ /// Returns a <see cref="FREE_IMAGE_FORMAT"/> identifier from a MIME content type string
+ /// (MIME stands for Multipurpose Internet Mail Extension).
+ /// </summary>
+ /// <param name="mime">A MIME content type.</param>
+ /// <returns>A <see cref="FREE_IMAGE_FORMAT"/> identifier from the MIME.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetFIFFromMime")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromMime(string mime);
+
+ /// <summary>
+ /// Returns the string that was used to register a plugin from the system assigned <see cref="FREE_IMAGE_FORMAT"/>.
+ /// </summary>
+ /// <param name="fif">The assigned <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>The string that was used to register the plugin.</returns>
+ public static unsafe string GetFormatFromFIF(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFormatFromFIF_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFormatFromFIF")]
+ private static unsafe extern byte* GetFormatFromFIF_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a comma-delimited file extension list describing the bitmap formats the given plugin can read and/or write.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A comma-delimited file extension list.</returns>
+ public static unsafe string GetFIFExtensionList(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFExtensionList_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFExtensionList")]
+ private static unsafe extern byte* GetFIFExtensionList_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a descriptive string that describes the bitmap formats the given plugin can read and/or write.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A descriptive string that describes the bitmap formats.</returns>
+ public static unsafe string GetFIFDescription(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFDescription_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFDescription")]
+ private static unsafe extern byte* GetFIFDescription_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a regular expression string that can be used by a regular expression engine to identify the bitmap.
+ /// FreeImageQt makes use of this function.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A regular expression string.</returns>
+ public static unsafe string GetFIFRegExpr(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFRegExpr_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFRegExpr")]
+ private static unsafe extern byte* GetFIFRegExpr_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Given a <see cref="FREE_IMAGE_FORMAT"/> identifier, returns a MIME content type string (MIME stands for Multipurpose Internet Mail Extension).
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A MIME content type string.</returns>
+ public static unsafe string GetFIFMimeType(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFMimeType_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFMimeType")]
+ private static unsafe extern byte* GetFIFMimeType_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// This function takes a filename or a file-extension and returns the plugin that can
+ /// read/write files with that extension in the form of a <see cref="FREE_IMAGE_FORMAT"/> identifier.
+ /// </summary>
+ /// <param name="filename">The filename or -extension.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFIFFromFilenameU")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromFilename(string filename);
+
+ /// <summary>
+ /// This function takes a filename or a file-extension and returns the plugin that can
+ /// read/write files with that extension in the form of a <see cref="FREE_IMAGE_FORMAT"/> identifier.
+ /// Supports UNICODE filenames.
+ /// </summary>
+ /// <param name="filename">The filename or -extension.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFIFFromFilenameU")]
+ private static extern FREE_IMAGE_FORMAT GetFIFFromFilenameU(string filename);
+
+ /// <summary>
+ /// Checks if a plugin can load bitmaps.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can load bitmaps, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsReading")]
+ public static extern bool FIFSupportsReading(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Checks if a plugin can save bitmaps.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can save bitmaps, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsWriting")]
+ public static extern bool FIFSupportsWriting(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Checks if a plugin can save bitmaps in the desired bit depth.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <param name="bpp">The desired bit depth.</param>
+ /// <returns>True if the plugin can save bitmaps in the desired bit depth, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsExportBPP")]
+ public static extern bool FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int bpp);
+
+ /// <summary>
+ /// Checks if a plugin can save a bitmap in the desired data type.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <param name="type">The desired image type.</param>
+ /// <returns>True if the plugin can save bitmaps as the desired type, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsExportType")]
+ public static extern bool FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type);
+
+ /// <summary>
+ /// Checks if a plugin can load or save an ICC profile.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can load or save an ICC profile, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsICCProfiles")]
+ public static extern bool FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif);
+
+ #endregion
+
+ #region Multipage functions
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="fif">Format of the image.</param>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMultiBitmap")]
+ public static extern FIMULTIBITMAP OpenMultiBitmap(FREE_IMAGE_FORMAT fif, string filename, bool create_new,
+ bool read_only, bool keep_cache_in_memory, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Loads a FreeImage multi-pages bitmap from the specified handle
+ /// using the specified functions.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="fif">Format of the image.</param>
+ /// <param name="io">IO functions used to read from the specified handle.</param>
+ /// <param name="handle">The handle to load the bitmap from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMultiBitmapFromHandle")]
+ public static extern FIMULTIBITMAP OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, ref FreeImageIO io,
+ fi_handle handle, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only, applies any changes made to it.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloseMultiBitmap")]
+ private static extern bool CloseMultiBitmap_(FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Returns the number of pages currently available in the multi-paged bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Number of pages.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPageCount")]
+ public static extern int GetPageCount(FIMULTIBITMAP bitmap);
+
+ /// <summary>
+ /// Appends a new page to the end of the bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AppendPage")]
+ public static extern void AppendPage(FIMULTIBITMAP bitmap, FIBITMAP data);
+
+ /// <summary>
+ /// Inserts a new page before the given position in the bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Page has to be a number smaller than the current number of pages available in the bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_InsertPage")]
+ public static extern void InsertPage(FIMULTIBITMAP bitmap, int page, FIBITMAP data);
+
+ /// <summary>
+ /// Deletes the page on the given position.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Number of the page to delete.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeletePage")]
+ public static extern void DeletePage(FIMULTIBITMAP bitmap, int page);
+
+ /// <summary>
+ /// Locks a page in memory for editing.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Number of the page to lock.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LockPage")]
+ public static extern FIBITMAP LockPage(FIMULTIBITMAP bitmap, int page);
+
+ /// <summary>
+ /// Unlocks a previously locked page and gives it back to the multi-page engine.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ /// <param name="changed">If true, the page is applied to the multi-page bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_UnlockPage")]
+ public static extern void UnlockPage(FIMULTIBITMAP bitmap, FIBITMAP data, bool changed);
+
+ /// <summary>
+ /// Moves the source page to the position of the target page.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="target">New position of the page.</param>
+ /// <param name="source">Old position of the page.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MovePage")]
+ public static extern bool MovePage(FIMULTIBITMAP bitmap, int target, int source);
+
+ /// <summary>
+ /// Returns an array of page-numbers that are currently locked in memory.
+ /// When the pages parameter is null, the size of the array is returned in the count variable.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// int[] lockedPages = null;
+ /// int count = 0;
+ /// GetLockedPageNumbers(dib, lockedPages, ref count);
+ /// lockedPages = new int[count];
+ /// GetLockedPageNumbers(dib, lockedPages, ref count);
+ /// </code>
+ /// </example>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="pages">The list of locked pages in the multi-pages bitmap.
+ /// If set to null, count will contain the number of pages.</param>
+ /// <param name="count">If <paramref name="pages"/> is set to null count will contain the number of locked pages.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetLockedPageNumbers")]
+ public static extern bool GetLockedPageNumbers(FIMULTIBITMAP bitmap, int[] pages, ref int count);
+
+ #endregion
+
+ #region Filetype functions
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// </summary>
+ /// <param name="filename">Name of the file to analyze.</param>
+ /// <param name="size">Reserved parameter - use 0.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFileTypeU")]
+ public static extern FREE_IMAGE_FORMAT GetFileType(string filename, int size);
+
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// Supports UNICODE filenames.
+ /// </summary>
+ /// <param name="filename">Name of the file to analyze.</param>
+ /// <param name="size">Reserved parameter - use 0.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFileTypeU")]
+ private static extern FREE_IMAGE_FORMAT GetFileTypeU(string filename, int size);
+
+ /// <summary>
+ /// Uses the <see cref="FreeImageIO"/> structure as described in the topic bitmap management functions
+ /// to identify a bitmap type.
+ /// </summary>
+ /// <param name="io">A <see cref="FreeImageIO"/> structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="size">Size in bytes of the source.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFileTypeFromHandle")]
+ public static extern FREE_IMAGE_FORMAT GetFileTypeFromHandle(ref FreeImageIO io, fi_handle handle, int size);
+
+ /// <summary>
+ /// Uses a memory handle to identify a bitmap type.
+ /// </summary>
+ /// <param name="stream">Pointer to the stream.</param>
+ /// <param name="size">Size in bytes of the source.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFileTypeFromMemory")]
+ public static extern FREE_IMAGE_FORMAT GetFileTypeFromMemory(FIMEMORY stream, int size);
+
+ #endregion
+
+ #region Helper functions
+
+ /// <summary>
+ /// Returns whether the platform is using Little Endian.
+ /// </summary>
+ /// <returns>Returns true if the platform is using Litte Endian, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsLittleEndian")]
+ public static extern bool IsLittleEndian();
+
+ /// <summary>
+ /// Converts a X11 color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="szColor">Name of the color to convert.</param>
+ /// <param name="nRed">Red component.</param>
+ /// <param name="nGreen">Green component.</param>
+ /// <param name="nBlue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_LookupX11Color")]
+ public static extern bool LookupX11Color(string szColor, out byte nRed, out byte nGreen, out byte nBlue);
+
+ /// <summary>
+ /// Converts a SVG color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="szColor">Name of the color to convert.</param>
+ /// <param name="nRed">Red component.</param>
+ /// <param name="nGreen">Green component.</param>
+ /// <param name="nBlue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_LookupSVGColor")]
+ public static extern bool LookupSVGColor(string szColor, out byte nRed, out byte nGreen, out byte nBlue);
+
+ #endregion
+
+ #region Pixel access functions
+
+ /// <summary>
+ /// Returns a pointer to the data-bits of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the data-bits.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBits")]
+ public static extern IntPtr GetBits(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the start of the given scanline in the bitmap's data-bits.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="scanline">Number of the scanline.</param>
+ /// <returns>Pointer to the scanline.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetScanLine")]
+ public static extern IntPtr GetScanLine(FIBITMAP dib, int scanline);
+
+ /// <summary>
+ /// Get the pixel index of a palettized image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The pixel index.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPixelIndex")]
+ public static extern bool GetPixelIndex(FIBITMAP dib, uint x, uint y, out byte value);
+
+ /// <summary>
+ /// Get the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The pixel color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPixelColor")]
+ public static extern bool GetPixelColor(FIBITMAP dib, uint x, uint y, out RGBQUAD value);
+
+ /// <summary>
+ /// Set the pixel index of a palettized image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The new pixel index.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPixelIndex")]
+ public static extern bool SetPixelIndex(FIBITMAP dib, uint x, uint y, ref byte value);
+
+ /// <summary>
+ /// Set the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The new pixel color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPixelColor")]
+ public static extern bool SetPixelColor(FIBITMAP dib, uint x, uint y, ref RGBQUAD value);
+
+ #endregion
+
+ #region Bitmap information functions
+
+ /// <summary>
+ /// Retrieves the type of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetImageType")]
+ public static extern FREE_IMAGE_TYPE GetImageType(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the number of colors used in a bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Palette-size for palletised bitmaps, and 0 for high-colour bitmaps.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetColorsUsed")]
+ public static extern uint GetColorsUsed(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the size of one pixel in the bitmap in bits.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Size of one pixel in the bitmap in bits.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBPP")]
+ public static extern uint GetBPP(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in pixel units.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetWidth")]
+ public static extern uint GetWidth(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the height of the bitmap in pixel units.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Height of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetHeight")]
+ public static extern uint GetHeight(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap in bytes.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetLine")]
+ public static extern uint GetLine(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary,
+ /// also known as pitch or stride or scan width.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap in bytes.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPitch")]
+ public static extern uint GetPitch(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the size of the DIB-element of a FIBITMAP in memory.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Size of the DIB-element</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDIBSize")]
+ public static extern uint GetDIBSize(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the bitmap's palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the bitmap's palette.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPalette")]
+ public static extern IntPtr GetPalette(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The horizontal resolution, in pixels-per-meter.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDotsPerMeterX")]
+ public static extern uint GetDotsPerMeterX(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The vertical resolution, in pixels-per-meter.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDotsPerMeterY")]
+ public static extern uint GetDotsPerMeterY(FIBITMAP dib);
+
+ /// <summary>
+ /// Set the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new horizontal resolution.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetDotsPerMeterX")]
+ public static extern void SetDotsPerMeterX(FIBITMAP dib, uint res);
+
+ /// <summary>
+ /// Set the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new vertical resolution.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetDotsPerMeterY")]
+ public static extern void SetDotsPerMeterY(FIBITMAP dib, uint res);
+
+ /// <summary>
+ /// Returns a pointer to the <see cref="BITMAPINFOHEADER"/> of the DIB-element in a FIBITMAP.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Poiter to the header of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetInfoHeader")]
+ public static extern IntPtr GetInfoHeader(FIBITMAP dib);
+
+ /// <summary>
+ /// Alias for FreeImage_GetInfoHeader that returns a pointer to a <see cref="BITMAPINFO"/>
+ /// rather than to a <see cref="BITMAPINFOHEADER"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the <see cref="BITMAPINFO"/> structure for the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetInfo")]
+ public static extern IntPtr GetInfo(FIBITMAP dib);
+
+ /// <summary>
+ /// Investigates the color type of the bitmap by reading the bitmap's pixel bits and analysing them.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The color type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetColorType")]
+ public static extern FREE_IMAGE_COLOR_TYPE GetColorType(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the red color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for RED.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetRedMask")]
+ public static extern uint GetRedMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the green color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for green.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetGreenMask")]
+ public static extern uint GetGreenMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the blue color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for blue.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBlueMask")]
+ public static extern uint GetBlueMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the number of transparent colors in a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The number of transparent colors in a palletised bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparencyCount")]
+ public static extern uint GetTransparencyCount(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the bitmap's transparency table.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the bitmap's transparency table.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparencyTable")]
+ public static extern IntPtr GetTransparencyTable(FIBITMAP dib);
+
+ /// <summary>
+ /// Tells FreeImage if it should make use of the transparency table
+ /// or the alpha channel that may accompany a bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="enabled">True to enable the transparency, false to disable.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparent")]
+ public static extern void SetTransparent(FIBITMAP dib, bool enabled);
+
+ /// <summary>
+ /// Set the bitmap's transparency table. Only affects palletised bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="table">Pointer to the bitmap's new transparency table.</param>
+ /// <param name="count">The number of transparent colors in the new transparency table.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparencyTable")]
+ internal static extern void SetTransparencyTable(FIBITMAP dib, byte[] table, int count);
+
+ /// <summary>
+ /// Returns whether the transparency table is enabled.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true when the transparency table is enabled (1-, 4- or 8-bit images)
+ /// or when the input dib contains alpha values (32-bit images). Returns false otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsTransparent")]
+ public static extern bool IsTransparent(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns whether the bitmap has a file background color.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true when the image has a file background color, false otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_HasBackgroundColor")]
+ public static extern bool HasBackgroundColor(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the file background color of an image.
+ /// For 8-bit images, the color index in the palette is returned in the
+ /// rgbReserved member of the bkcolor parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The background color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBackgroundColor")]
+ public static extern bool GetBackgroundColor(FIBITMAP dib, out RGBQUAD bkcolor);
+
+ /// <summary>
+ /// Set the file background color of an image.
+ /// When saving an image to PNG, this background color is transparently saved to the PNG file.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The new background color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetBackgroundColor")]
+ public static unsafe extern bool SetBackgroundColor(FIBITMAP dib, ref RGBQUAD bkcolor);
+
+ /// <summary>
+ /// Set the file background color of an image.
+ /// When saving an image to PNG, this background color is transparently saved to the PNG file.
+ /// When the bkcolor parameter is null, the background color is removed from the image.
+ /// <para>
+ /// This overloaded version of the function with an array parameter is provided to allow
+ /// passing <c>null</c> in the <paramref name="bkcolor"/> parameter. This is similar to the
+ /// original C/C++ function. Passing <c>null</c> as <paramref name="bkcolor"/> parameter will
+ /// unset the dib's previously set background color.
+ /// </para>
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The new background color.
+ /// The first entry in the array is used.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <example>
+ /// <code>
+ /// // create a RGBQUAD color
+ /// RGBQUAD color = new RGBQUAD(Color.Green);
+ ///
+ /// // set the dib's background color (using the other version of the function)
+ /// FreeImage.SetBackgroundColor(dib, ref color);
+ ///
+ /// // remove it again (this only works due to the array parameter RGBQUAD[])
+ /// FreeImage.SetBackgroundColor(dib, null);
+ /// </code>
+ /// </example>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetBackgroundColor")]
+ public static unsafe extern bool SetBackgroundColor(FIBITMAP dib, RGBQUAD[] bkcolor);
+
+ /// <summary>
+ /// Sets the index of the palette entry to be used as transparent color
+ /// for the image specified. Does nothing on high color images.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="index">The index of the palette entry to be set as transparent color.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparentIndex")]
+ public static extern void SetTransparentIndex(FIBITMAP dib, int index);
+
+ /// <summary>
+ /// Returns the palette entry used as transparent color for the image specified.
+ /// Works for palletised images only and returns -1 for high color
+ /// images or if the image has no color set to be transparent.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>the index of the palette entry used as transparent color for
+ /// the image specified or -1 if there is no transparent color found
+ /// (e.g. the image is a high color image).</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparentIndex")]
+ public static extern int GetTransparentIndex(FIBITMAP dib);
+
+ #endregion
+
+ #region ICC profile functions
+
+ /// <summary>
+ /// Retrieves the <see cref="FIICCPROFILE"/> data of the bitmap.
+ /// This function can also be called safely, when the original format does not support profiles.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The <see cref="FIICCPROFILE"/> data of the bitmap.</returns>
+ public static FIICCPROFILE GetICCProfileEx(FIBITMAP dib) { unsafe { return *(FIICCPROFILE*)FreeImage.GetICCProfile(dib); } }
+
+ /// <summary>
+ /// Retrieves a pointer to the <see cref="FIICCPROFILE"/> data of the bitmap.
+ /// This function can also be called safely, when the original format does not support profiles.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the <see cref="FIICCPROFILE"/> data of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetICCProfile")]
+ public static extern IntPtr GetICCProfile(FIBITMAP dib);
+
+ /// <summary>
+ /// Creates a new <see cref="FIICCPROFILE"/> block from ICC profile data previously read from a file
+ /// or built by a color management system. The profile data is attached to the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">Pointer to the new <see cref="FIICCPROFILE"/> data.</param>
+ /// <param name="size">Size of the <see cref="FIICCPROFILE"/> data.</param>
+ /// <returns>Pointer to the created <see cref="FIICCPROFILE"/> structure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CreateICCProfile")]
+ public static extern IntPtr CreateICCProfile(FIBITMAP dib, byte[] data, int size);
+
+ /// <summary>
+ /// This function destroys an <see cref="FIICCPROFILE"/> previously created by <see cref="CreateICCProfile(FIBITMAP,byte[],int)"/>.
+ /// After this call the bitmap will contain no profile information.
+ /// This function should be called to ensure that a stored bitmap will not contain any profile information.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DestroyICCProfile")]
+ public static extern void DestroyICCProfile(FIBITMAP dib);
+
+ #endregion
+
+ #region Conversion functions
+
+ /// <summary>
+ /// Converts a bitmap to 4 bits.
+ /// If the bitmap was a high-color bitmap (16, 24 or 32-bit) or if it was a
+ /// monochrome or greyscale bitmap (1 or 8-bit), the end result will be a
+ /// greyscale bitmap, otherwise (1-bit palletised bitmaps) it will be a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo4Bits")]
+ public static extern FIBITMAP ConvertTo4Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 8 bits. If the bitmap was a high-color bitmap (16, 24 or 32-bit)
+ /// or if it was a monochrome or greyscale bitmap (1 or 4-bit), the end result will be a
+ /// greyscale bitmap, otherwise (1 or 4-bit palletised bitmaps) it will be a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo8Bits")]
+ public static extern FIBITMAP ConvertTo8Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to a 8-bit greyscale image with a linear ramp.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToGreyscale")]
+ public static extern FIBITMAP ConvertToGreyscale(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 16 bits, where each pixel has a color pattern of
+ /// 5 bits red, 5 bits green and 5 bits blue. One bit in each pixel is unused.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo16Bits555")]
+ public static extern FIBITMAP ConvertTo16Bits555(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 16 bits, where each pixel has a color pattern of
+ /// 5 bits red, 6 bits green and 5 bits blue.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo16Bits565")]
+ public static extern FIBITMAP ConvertTo16Bits565(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 24 bits. A clone of the input bitmap is returned for 24-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo24Bits")]
+ public static extern FIBITMAP ConvertTo24Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 32 bits. A clone of the input bitmap is returned for 32-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo32Bits")]
+ public static extern FIBITMAP ConvertTo32Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Quantizes a high-color 24-bit bitmap to an 8-bit palette color bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ColorQuantize")]
+ public static extern FIBITMAP ColorQuantize(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize);
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/> method that
+ /// provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// partial or full provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ColorQuantizeEx")]
+ public static extern FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, int ReserveSize, RGBQUAD[] ReservePalette);
+
+ /// <summary>
+ /// Converts a bitmap to 1-bit monochrome bitmap using a threshold T between [0..255].
+ /// The function first converts the bitmap to a 8-bit greyscale bitmap.
+ /// Then, any brightness level that is less than T is set to zero, otherwise to 1.
+ /// For 1-bit input bitmaps, the function clones the input bitmap and builds a monochrome palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="t">The threshold.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Threshold")]
+ public static extern FIBITMAP Threshold(FIBITMAP dib, byte t);
+
+ /// <summary>
+ /// Converts a bitmap to 1-bit monochrome bitmap using a dithering algorithm.
+ /// For 1-bit input bitmaps, the function clones the input bitmap and builds a monochrome palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="algorithm">The dithering algorithm to use.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Dither")]
+ public static extern FIBITMAP Dither(FIBITMAP dib, FREE_IMAGE_DITHER algorithm);
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block containing the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertFromRawBits")]
+ public static extern FIBITMAP ConvertFromRawBits(IntPtr bits, int width, int height, int pitch,
+ uint bpp, uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Array of bytes containing the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertFromRawBits")]
+ public static extern FIBITMAP ConvertFromRawBits(byte[] bits, int width, int height, int pitch,
+ uint bpp, uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a raw bitmap, that is a raw piece of memory.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block receiving the raw bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="pitch">The desired total width in bytes of a scanline in the raw bitmap,
+ /// including any padding bytes.</param>
+ /// <param name="bpp">The desired bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap will be stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRawBits")]
+ public static extern void ConvertToRawBits(IntPtr bits, FIBITMAP dib, int pitch, uint bpp,
+ uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a raw bitmap, that is a raw piece of memory.
+ /// </summary>
+ /// <param name="bits">Array of bytes receiving the raw bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="pitch">The desired total width in bytes of a scanline in the raw bitmap,
+ /// including any padding bytes.</param>
+ /// <param name="bpp">The desired bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap will be stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRawBits")]
+ public static extern void ConvertToRawBits(byte[] bits, FIBITMAP dib, int pitch, uint bpp,
+ uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a 24- or 32-bit RGB(A) standard image or a 48-bit RGB image to a FIT_RGBF type image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRGBF")]
+ public static extern FIBITMAP ConvertToRGBF(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a non standard image whose color type is FIC_MINISBLACK
+ /// to a standard 8-bit greyscale image.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="scale_linear">When true the conversion is done by scaling linearly
+ /// each pixel value from [min, max] to an integer value between [0..255],
+ /// where min and max are the minimum and maximum pixel values in the image.
+ /// When false the conversion is done by rounding each pixel value to an integer between [0..255].
+ ///
+ /// Rounding is done using the following formula:
+ ///
+ /// dst_pixel = (BYTE) MIN(255, MAX(0, q)) where int q = int(src_pixel + 0.5);</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToStandardType")]
+ public static extern FIBITMAP ConvertToStandardType(FIBITMAP src, bool scale_linear);
+
+ /// <summary>
+ /// Converts an image of any type to type dst_type.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="dst_type">Destination type.</param>
+ /// <param name="scale_linear">True to scale linear, else false.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToType")]
+ public static extern FIBITMAP ConvertToType(FIBITMAP src, FREE_IMAGE_TYPE dst_type, bool scale_linear);
+
+ #endregion
+
+ #region Tone mapping operators
+
+ /// <summary>
+ /// Converts a High Dynamic Range image (48-bit RGB or 96-bit RGBF) to a 24-bit RGB image, suitable for display.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tmo">The tone mapping operator to be used.</param>
+ /// <param name="first_param">Parmeter depending on the used algorithm</param>
+ /// <param name="second_param">Parmeter depending on the used algorithm</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ToneMapping")]
+ public static extern FIBITMAP ToneMapping(FIBITMAP dib, FREE_IMAGE_TMO tmo, double first_param, double second_param);
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global
+ /// operator based on logarithmic compression of luminance values, imitating the human response to light.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="gamma">A gamma correction that is applied after the tone mapping.
+ /// A value of 1 means no correction.</param>
+ /// <param name="exposure">Scale factor allowing to adjust the brightness of the output image.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoDrago03")]
+ public static extern FIBITMAP TmoDrago03(FIBITMAP src, double gamma, double exposure);
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global operator inspired
+ /// by photoreceptor physiology of the human visual system.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="intensity">Controls the overall image intensity in the range [-8, 8].</param>
+ /// <param name="contrast">Controls the overall image contrast in the range [0.3, 1.0[.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoReinhard05")]
+ public static extern FIBITMAP TmoReinhard05(FIBITMAP src, double intensity, double contrast);
+
+ /// <summary>
+ /// Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="color_saturation">Color saturation (s parameter in the paper) in [0.4..0.6]</param>
+ /// <param name="attenuation">Atenuation factor (beta parameter in the paper) in [0.8..0.9]</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoFattal02")]
+ public static extern FIBITMAP TmoFattal02(FIBITMAP src, double color_saturation, double attenuation);
+
+ #endregion
+
+ #region Compression functions
+
+ /// <summary>
+ /// Compresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must be at least 0.1% larger than source_size plus 12 bytes.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the compressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibCompress")]
+ public static extern uint ZLibCompress(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Decompresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must have been saved outlide of zlib.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the uncompressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibUncompress")]
+ public static extern uint ZLibUncompress(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Compresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must be at least 0.1% larger than source_size plus 24 bytes.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the compressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibGZip")]
+ public static extern uint ZLibGZip(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Decompresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must have been saved outlide of zlib.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the uncompressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibGUnzip")]
+ public static extern uint ZLibGUnzip(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Generates a CRC32 checksum.
+ /// </summary>
+ /// <param name="crc">The CRC32 checksum to begin with.</param>
+ /// <param name="source">Pointer to the source buffer.
+ /// If the value is 0, the function returns the required initial value for the crc.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns></returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibCRC32")]
+ public static extern uint ZLibCRC32(uint crc, byte[] source, uint source_size);
+
+ #endregion
+
+ #region Tag creation and destruction
+
+ /// <summary>
+ /// Allocates a new <see cref="FITAG"/> object.
+ /// This object must be destroyed with a call to
+ /// <see cref="FreeImageAPI.FreeImage.DeleteTag(FITAG)"/> when no longer in use.
+ /// </summary>
+ /// <returns>The new <see cref="FITAG"/>.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CreateTag")]
+ public static extern FITAG CreateTag();
+
+ /// <summary>
+ /// Delete a previously allocated <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to destroy.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeleteTag")]
+ public static extern void DeleteTag(FITAG tag);
+
+ /// <summary>
+ /// Creates and returns a copy of a <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to clone.</param>
+ /// <returns>The new <see cref="FITAG"/>.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloneTag")]
+ public static extern FITAG CloneTag(FITAG tag);
+
+ #endregion
+
+ #region Tag accessors
+
+ /// <summary>
+ /// Returns the tag field name (unique inside a metadata model).
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The field name.</returns>
+ public static unsafe string GetTagKey(FITAG tag) { return PtrToStr(GetTagKey_(tag)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetTagKey")]
+ private static unsafe extern byte* GetTagKey_(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag description.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The description or NULL if unavailable.</returns>
+ public static unsafe string GetTagDescription(FITAG tag) { return PtrToStr(GetTagDescription_(tag)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetTagDescription")]
+ private static unsafe extern byte* GetTagDescription_(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag ID.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The ID or 0 if unavailable.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagID")]
+ public static extern ushort GetTagID(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag data type.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The tag type.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagType")]
+ public static extern FREE_IMAGE_MDTYPE GetTagType(FITAG tag);
+
+ /// <summary>
+ /// Returns the number of components in the tag (in tag type units).
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The number of components.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagCount")]
+ public static extern uint GetTagCount(FITAG tag);
+
+ /// <summary>
+ /// Returns the length of the tag value in bytes.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The length of the tag value.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagLength")]
+ public static extern uint GetTagLength(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag value.
+ /// It is up to the programmer to interpret the returned pointer correctly,
+ /// according to the results of GetTagType and GetTagCount.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>Pointer to the value.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagValue")]
+ public static extern IntPtr GetTagValue(FITAG tag);
+
+ /// <summary>
+ /// Sets the tag field name.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="key">The new name.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetTagKey")]
+ public static extern bool SetTagKey(FITAG tag, string key);
+
+ /// <summary>
+ /// Sets the tag description.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="description">The new description.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetTagDescription")]
+ public static extern bool SetTagDescription(FITAG tag, string description);
+
+ /// <summary>
+ /// Sets the tag ID.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="id">The new ID.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagID")]
+ public static extern bool SetTagID(FITAG tag, ushort id);
+
+ /// <summary>
+ /// Sets the tag data type.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="type">The new type.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagType")]
+ public static extern bool SetTagType(FITAG tag, FREE_IMAGE_MDTYPE type);
+
+ /// <summary>
+ /// Sets the number of data in the tag.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="count">New number of data.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagCount")]
+ public static extern bool SetTagCount(FITAG tag, uint count);
+
+ /// <summary>
+ /// Sets the length of the tag value in bytes.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="length">The new length.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagLength")]
+ public static extern bool SetTagLength(FITAG tag, uint length);
+
+ /// <summary>
+ /// Sets the tag value.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="value">Pointer to the new value.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagValue")]
+ public static extern bool SetTagValue(FITAG tag, byte[] value);
+
+ #endregion
+
+ #region Metadata iterator
+
+ /// <summary>
+ /// Provides information about the first instance of a tag that matches the metadata model.
+ /// </summary>
+ /// <param name="model">The model to match.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Unique search handle that can be used to call FindNextMetadata or FindCloseMetadata.
+ /// Null if the metadata model does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindFirstMetadata")]
+ public static extern FIMETADATA FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, out FITAG tag);
+
+ /// <summary>
+ /// Find the next tag, if any, that matches the metadata model argument in a previous call
+ /// to FindFirstMetadata, and then alters the tag object contents accordingly.
+ /// </summary>
+ /// <param name="mdhandle">Unique search handle provided by FindFirstMetadata.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindNextMetadata")]
+ public static extern bool FindNextMetadata(FIMETADATA mdhandle, out FITAG tag);
+
+ /// <summary>
+ /// Closes the specified metadata search handle and releases associated resources.
+ /// </summary>
+ /// <param name="mdhandle">The handle to close.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindCloseMetadata")]
+ private static extern void FindCloseMetadata_(FIMETADATA mdhandle);
+
+ #endregion
+
+ #region Metadata setter and getter
+
+ /// <summary>
+ /// Retrieve a metadata attached to a dib.
+ /// </summary>
+ /// <param name="model">The metadata model to look for.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The metadata field name.</param>
+ /// <param name="tag">A FITAG structure returned by the function.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetMetadata")]
+ public static extern bool GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, string key, out FITAG tag);
+
+ /// <summary>
+ /// Attach a new FreeImage tag to a dib.
+ /// </summary>
+ /// <param name="model">The metadata model used to store the tag.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The tag field name.</param>
+ /// <param name="tag">The FreeImage tag to be attached.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetMetadata")]
+ public static extern bool SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, string key, FITAG tag);
+
+ #endregion
+
+ #region Metadata helper functions
+
+ /// <summary>
+ /// Returns the number of tags contained in the model metadata model attached to the input dib.
+ /// </summary>
+ /// <param name="model">The metadata model.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Number of tags contained in the metadata model.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetMetadataCount")]
+ public static extern uint GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP dib);
+
+ /// <summary>
+ /// Copies the metadata of FreeImage bitmap to another.
+ /// </summary>
+ /// <param name="dst">The FreeImage bitmap to copy the metadata to.</param>
+ /// <param name="src">The FreeImage bitmap to copy the metadata from.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloneMetadata")]
+ public static extern bool CloneMetadata(FIBITMAP dst, FIBITMAP src);
+
+ /// <summary>
+ /// Converts a FreeImage tag structure to a string that represents the interpreted tag value.
+ /// The function is not thread safe.
+ /// </summary>
+ /// <param name="model">The metadata model.</param>
+ /// <param name="tag">The interpreted tag value.</param>
+ /// <param name="Make">Reserved.</param>
+ /// <returns>The representing string.</returns>
+ public static unsafe string TagToString(FREE_IMAGE_MDMODEL model, FITAG tag, uint Make) { return PtrToStr(TagToString_(model, tag, Make)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_TagToString")]
+ private static unsafe extern byte* TagToString_(FREE_IMAGE_MDMODEL model, FITAG tag, uint Make);
+
+ #endregion
+
+ #region Rotation and flipping
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90°.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_RotateClassic")]
+ [Obsolete("RotateClassic is deprecated (use Rotate instead).")]
+ public static extern FIBITMAP RotateClassic(FIBITMAP dib, double angle);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Rotate")]
+ internal static extern FIBITMAP Rotate(FIBITMAP dib, double angle, IntPtr backgroundColor);
+
+ /// <summary>
+ /// This function performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="x_shift">Horizontal image translation.</param>
+ /// <param name="y_shift">Vertical image translation.</param>
+ /// <param name="x_origin">Rotation center x-coordinate.</param>
+ /// <param name="y_origin">Rotation center y-coordinate.</param>
+ /// <param name="use_mask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_RotateEx")]
+ public static extern FIBITMAP RotateEx(FIBITMAP dib, double angle,
+ double x_shift, double y_shift, double x_origin, double y_origin, bool use_mask);
+
+ /// <summary>
+ /// Flip the input dib horizontally along the vertical axis.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FlipHorizontal")]
+ public static extern bool FlipHorizontal(FIBITMAP dib);
+
+ /// <summary>
+ /// Flip the input dib vertically along the horizontal axis.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FlipVertical")]
+ public static extern bool FlipVertical(FIBITMAP dib);
+
+ /// <summary>
+ /// Performs a lossless rotation or flipping on a JPEG file.
+ /// </summary>
+ /// <param name="src_file">Source file.</param>
+ /// <param name="dst_file">Destination file; can be the source file; will be overwritten.</param>
+ /// <param name="operation">The operation to apply.</param>
+ /// <param name="perfect">To avoid lossy transformation, you can set the perfect parameter to true.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_JPEGTransformU")]
+ public static extern bool JPEGTransform(string src_file, string dst_file,
+ FREE_IMAGE_JPEG_OPERATION operation, bool perfect);
+
+ #endregion
+
+ #region Upsampling / downsampling
+
+ /// <summary>
+ /// Performs resampling (or scaling, zooming) of a greyscale or RGB(A) image
+ /// to the desired destination width and height.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="dst_width">Destination width.</param>
+ /// <param name="dst_height">Destination height.</param>
+ /// <param name="filter">The filter to apply.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Rescale")]
+ public static extern FIBITMAP Rescale(FIBITMAP dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter);
+
+ /// <summary>
+ /// Creates a thumbnail from a greyscale or RGB(A) image, keeping aspect ratio.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="max_pixel_size">Thumbnail square size.</param>
+ /// <param name="convert">When true HDR images are transperantly converted to standard images.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MakeThumbnail")]
+ public static extern FIBITMAP MakeThumbnail(FIBITMAP dib, int max_pixel_size, bool convert);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_EnlargeCanvas")]
+ internal static extern FIBITMAP EnlargeCanvas(FIBITMAP dib,
+ int left, int top, int right, int bottom, IntPtr color, FREE_IMAGE_COLOR_OPTIONS options);
+
+ #endregion
+
+ #region Color manipulation
+
+ /// <summary>
+ /// Perfoms an histogram transformation on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="lookUpTable">The lookup table.
+ /// It's size is assumed to be 256 in length.</param>
+ /// <param name="channel">The color channel to be transformed.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustCurve")]
+ public static extern bool AdjustCurve(FIBITMAP dib, byte[] lookUpTable, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Performs gamma correction on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="gamma">The parameter represents the gamma value to use (gamma > 0).
+ /// A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustGamma")]
+ public static extern bool AdjustGamma(FIBITMAP dib, double gamma);
+
+ /// <summary>
+ /// Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will make the image darker and greater than 0 will make the image brighter.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustBrightness")]
+ public static extern bool AdjustBrightness(FIBITMAP dib, double percentage);
+
+ /// <summary>
+ /// Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustContrast")]
+ public static extern bool AdjustContrast(FIBITMAP dib, double percentage);
+
+ /// <summary>
+ /// Inverts each pixel data.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Invert")]
+ public static extern bool Invert(FIBITMAP dib);
+
+ /// <summary>
+ /// Computes the image histogram.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="histo">Array of integers with a size of 256.</param>
+ /// <param name="channel">Channel to compute from.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetHistogram")]
+ public static extern bool GetHistogram(FIBITMAP dib, int[] histo, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ #endregion
+
+ #region Channel processing
+
+ /// <summary>
+ /// Retrieves the red, green, blue or alpha channel of a 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetChannel")]
+ public static extern FIBITMAP GetChannel(FIBITMAP dib, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Insert a 8-bit dib into a 24- or 32-bit image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="dib8">Handle to the bitmap to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetChannel")]
+ public static extern bool SetChannel(FIBITMAP dib, FIBITMAP dib8, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Retrieves the real part, imaginary part, magnitude or phase of a complex image.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetComplexChannel")]
+ public static extern FIBITMAP GetComplexChannel(FIBITMAP src, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Set the real or imaginary part of a complex image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="dst">Handle to a FreeImage bitmap.</param>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetComplexChannel")]
+ public static extern bool SetComplexChannel(FIBITMAP dst, FIBITMAP src, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ #endregion
+
+ #region Copy / Paste / Composite routines
+
+ /// <summary>
+ /// Copy a sub part of the current dib image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Copy")]
+ public static extern FIBITMAP Copy(FIBITMAP dib, int left, int top, int right, int bottom);
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with the current dib image.
+ /// The bit depth of the dst bitmap must be greater than or equal to the bit depth of the src.
+ /// </summary>
+ /// <param name="dst">Handle to a FreeImage bitmap.</param>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">Specifies the left position of the sub image.</param>
+ /// <param name="top">Specifies the top position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Paste")]
+ public static extern bool Paste(FIBITMAP dst, FIBITMAP src, int left, int top, int alpha);
+
+ /// <summary>
+ /// This function composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// </summary>
+ /// <param name="fg">Handle to a FreeImage bitmap.</param>
+ /// <param name="useFileBkg">When true the background of fg is used if it contains one.</param>
+ /// <param name="appBkColor">The application background is used if useFileBkg is false.</param>
+ /// <param name="bg">Image used as background when useFileBkg is false or fg has no background
+ /// and appBkColor is null.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Composite")]
+ public static extern FIBITMAP Composite(FIBITMAP fg, bool useFileBkg, ref RGBQUAD appBkColor, FIBITMAP bg);
+
+ /// <summary>
+ /// This function composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// </summary>
+ /// <param name="fg">Handle to a FreeImage bitmap.</param>
+ /// <param name="useFileBkg">When true the background of fg is used if it contains one.</param>
+ /// <param name="appBkColor">The application background is used if useFileBkg is false
+ /// and 'appBkColor' is not null.</param>
+ /// <param name="bg">Image used as background when useFileBkg is false or fg has no background
+ /// and appBkColor is null.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Composite")]
+ public static extern FIBITMAP Composite(FIBITMAP fg, bool useFileBkg, RGBQUAD[] appBkColor, FIBITMAP bg);
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="src_file">Source filename.</param>
+ /// <param name="dst_file">Destination filename.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_JPEGCropU")]
+ public static extern bool JPEGCrop(string src_file, string dst_file, int left, int top, int right, int bottom);
+
+ /// <summary>
+ /// Applies the alpha value of each pixel to its color components.
+ /// The aplha value stays unchanged.
+ /// Only works with 32-bits color depth.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_PreMultiplyWithAlpha")]
+ public static extern bool PreMultiplyWithAlpha(FIBITMAP dib);
+
+ #endregion
+
+ #region Miscellaneous algorithms
+
+ /// <summary>
+ /// Solves a Poisson equation, remap result pixels to [0..1] and returns the solution.
+ /// </summary>
+ /// <param name="Laplacian">Handle to a FreeImage bitmap.</param>
+ /// <param name="ncycle">Number of cycles in the multigrid algorithm (usually 2 or 3)</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MultigridPoissonSolver")]
+ public static extern FIBITMAP MultigridPoissonSolver(FIBITMAP Laplacian, int ncycle);
+
+ #endregion
+
+ #region Colors
+
+ /// <summary>
+ /// Creates a lookup table to be used with <see cref="AdjustCurve"/> which may adjusts brightness and
+ /// contrast, correct gamma and invert the image with a single call to <see cref="AdjustCurve"/>.
+ /// </summary>
+ /// <param name="lookUpTable">Output lookup table to be used with <see cref="AdjustCurve"/>.
+ /// The size of 'lookUpTable' is assumed to be 256.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para></param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>The number of adjustments applied to the resulting lookup table
+ /// compared to a blind lookup table.</returns>
+ /// <remarks>
+ /// This function creates a lookup table to be used with <see cref="AdjustCurve"/> which may adjust
+ /// brightness and contrast, correct gamma and invert the image with a single call to
+ /// <see cref="AdjustCurve"/>. If more than one of these image display properties need to be adjusted,
+ /// using a combined lookup table should be preferred over calling each adjustment function
+ /// separately. That's particularly true for huge images or if performance is an issue. Then,
+ /// the expensive process of iterating over all pixels of an image is performed only once and
+ /// not up to four times.
+ /// <para/>
+ /// Furthermore, the lookup table created does not depend on the order, in which each single
+ /// adjustment operation is performed. Due to rounding and byte casting issues, it actually
+ /// matters in which order individual adjustment operations are performed. Both of the following
+ /// snippets most likely produce different results:
+ /// <para/>
+ /// <code>
+ /// // snippet 1: contrast, brightness
+ /// AdjustContrast(dib, 15.0);
+ /// AdjustBrightness(dib, 50.0);
+ /// </code>
+ /// <para/>
+ /// <code>
+ /// // snippet 2: brightness, contrast
+ /// AdjustBrightness(dib, 50.0);
+ /// AdjustContrast(dib, 15.0);
+ /// </code>
+ /// <para/>
+ /// Better and even faster would be snippet 3:
+ /// <para/>
+ /// <code>
+ /// // snippet 3:
+ /// byte[] lut = new byte[256];
+ /// GetAdjustColorsLookupTable(lut, 50.0, 15.0, 1.0, false);
+ /// AdjustCurve(dib, lut, FREE_IMAGE_COLOR_CHANNEL.FICC_RGB);
+ /// </code>
+ /// <para/>
+ /// This function is also used internally by <see cref="AdjustColors"/>, which does not return the
+ /// lookup table, but uses it to call <see cref="AdjustCurve"/> on the passed image.
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetAdjustColorsLookupTable")]
+ public static extern int GetAdjustColorsLookupTable(byte[] lookUpTable, double brightness, double contrast, double gamma, bool invert);
+
+ /// <summary>
+ /// Adjusts an image's brightness, contrast and gamma as well as it may
+ /// optionally invert the image within a single operation.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para>
+ /// This parameter must not be zero or smaller than zero.
+ /// If so, it will be ignored and no gamma correction will be performed on the image.</param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <remarks>
+ /// This function adjusts an image's brightness, contrast and gamma as well as it
+ /// may optionally invert the image within a single operation. If more than one of
+ /// these image display properties need to be adjusted, using this function should
+ /// be preferred over calling each adjustment function separately. That's particularly
+ /// true for huge images or if performance is an issue.
+ /// <para/>
+ /// This function relies on <see cref="GetAdjustColorsLookupTable"/>,
+ /// which creates a single lookup table, that combines all adjustment operations requested.
+ /// <para/>
+ /// Furthermore, the lookup table created by <see cref="GetAdjustColorsLookupTable"/> does
+ /// not depend on the order, in which each single adjustment operation is performed.
+ /// Due to rounding and byte casting issues, it actually matters in which order individual
+ /// adjustment operations are performed. Both of the following snippets most likely produce
+ /// different results:
+ /// <para/>
+ /// <code>
+ /// // snippet 1: contrast, brightness
+ /// AdjustContrast(dib, 15.0);
+ /// AdjustBrightness(dib, 50.0);
+ /// </code>
+ /// <para/>
+ /// <code>
+ /// // snippet 2: brightness, contrast
+ /// AdjustBrightness(dib, 50.0);
+ /// AdjustContrast(dib, 15.0);
+ /// </code>
+ /// <para/>
+ /// Better and even faster would be snippet 3:
+ /// <para/>
+ /// <code>
+ /// // snippet 3:
+ /// AdjustColors(dib, 50.0, 15.0, 1.0, false);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustColors")]
+ public static extern bool AdjustColors(FIBITMAP dib, double brightness, double contrast, double gamma, bool invert);
+
+ /// <summary>
+ /// Applies color mapping for one or several colors on a 1-, 4- or 8-bit
+ /// palletized or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="srccolors">Array of colors to be used as the mapping source.</param>
+ /// <param name="dstcolors">Array of colors to be used as the mapping destination.</param>
+ /// <param name="count">The number of colors to be mapped. This is the size of both
+ /// srccolors and dstcolors.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <param name="swap">If true, source and destination colors are swapped, that is,
+ /// each destination color is also mapped to the corresponding source color.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function maps up to <paramref name="count"/> colors specified in
+ /// <paramref name="srccolors"/> to these specified in <paramref name="dstcolors"/>.
+ /// Thereby, color <i>srccolors[N]</i>, if found in the image, will be replaced by color
+ /// <i>dstcolors[N]</i>. If <paramref name="swap"/> is <b>true</b>, additionally all colors
+ /// specified in <paramref name="dstcolors"/> are also mapped to these specified
+ /// in <paramref name="srccolors"/>. For high color images, the actual image data will be
+ /// modified whereas, for palletized images only the palette will be changed.
+ /// <para/>
+ /// The function returns the number of pixels changed or zero, if no pixels were changed.
+ /// <para/>
+ /// Both arrays <paramref name="srccolors"/> and <paramref name="dstcolors"/> are assumed
+ /// not to hold less than <paramref name="count"/> colors.
+ /// <para/>
+ /// For 16-bit images, all colors specified are transparently converted to their
+ /// proper 16-bit representation (either in RGB555 or RGB565 format, which is determined
+ /// by the image's red- green- and blue-mask).
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="ApplyPaletteIndexMapping"/> does,
+ /// which modifies the actual image data on palletized images.</b>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ApplyColorMapping")]
+ public static extern uint ApplyColorMapping(FIBITMAP dib, RGBQUAD[] srccolors, RGBQUAD[] dstcolors, uint count, bool ignore_alpha, bool swap);
+
+ /// <summary>
+ /// Swaps two specified colors on a 1-, 4- or 8-bit palletized
+ /// or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="color_a">One of the two colors to be swapped.</param>
+ /// <param name="color_b">The other of the two colors to be swapped.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function swaps the two specified colors <paramref name="color_a"/> and
+ /// <paramref name="color_b"/> on a palletized or high color image.
+ /// For high color images, the actual image data will be modified whereas, for palletized
+ /// images only the palette will be changed.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="SwapPaletteIndices"/> does,
+ /// which modifies the actual image data on palletized images.</b>
+ /// <para/>
+ /// This is just a thin wrapper for <see cref="ApplyColorMapping"/> and resolves to:
+ /// <para/>
+ /// <code>
+ /// return ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, true);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SwapColors")]
+ public static extern uint SwapColors(FIBITMAP dib, ref RGBQUAD color_a, ref RGBQUAD color_b, bool ignore_alpha);
+
+ /// <summary>
+ /// Applies palette index mapping for one or several indices
+ /// on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="srcindices">Array of palette indices to be used as the mapping source.</param>
+ /// <param name="dstindices">Array of palette indices to be used as the mapping destination.</param>
+ /// <param name="count">The number of palette indices to be mapped. This is the size of both
+ /// srcindices and dstindices</param>
+ /// <param name="swap">If true, source and destination palette indices are swapped, that is,
+ /// each destination index is also mapped to the corresponding source index.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function maps up to <paramref name="count"/> palette indices specified in
+ /// <paramref name="srcindices"/> to these specified in <paramref name="dstindices"/>.
+ /// Thereby, index <i>srcindices[N]</i>, if present in the image, will be replaced by index
+ /// <i>dstindices[N]</i>. If <paramref name="swap"/> is <b>true</b>, additionally all indices
+ /// specified in <paramref name="dstindices"/> are also mapped to these specified in
+ /// <paramref name="srcindices"/>.
+ /// <para/>
+ /// The function returns the number of pixels changed or zero, if no pixels were changed.
+ /// Both arrays <paramref name="srcindices"/> and <paramref name="dstindices"/> are assumed not to
+ /// hold less than <paramref name="count"/> indices.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="ApplyColorMapping"/> does, which
+ /// modifies the actual image data on palletized images.</b>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ApplyPaletteIndexMapping")]
+ public static extern uint ApplyPaletteIndexMapping(FIBITMAP dib, byte[] srcindices, byte[] dstindices, uint count, bool swap);
+
+ /// <summary>
+ /// Swaps two specified palette indices on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="index_a">One of the two palette indices to be swapped.</param>
+ /// <param name="index_b">The other of the two palette indices to be swapped.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function swaps the two specified palette indices <i>index_a</i> and
+ /// <i>index_b</i> on a palletized image. Therefore, not the palette, but the
+ /// actual image data will be modified.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="SwapColors"/> does on palletized images,
+ /// which only swaps the colors in the palette.</b>
+ /// <para/>
+ /// This is just a thin wrapper for <see cref="ApplyColorMapping"/> and resolves to:
+ /// <para/>
+ /// <code>
+ /// return ApplyPaletteIndexMapping(dib, index_a, index_b, 1, true);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SwapPaletteIndices")]
+ public static extern uint SwapPaletteIndices(FIBITMAP dib, ref byte index_a, ref byte index_b);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FillBackground")]
+ internal static extern bool FillBackground(FIBITMAP dib, IntPtr color, FREE_IMAGE_COLOR_OPTIONS options);
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/FreeImageWrapper.cs b/Wrapper/FreeImage.NET/cs/Library/FreeImageWrapper.cs
new file mode 100644
index 0000000..4bbf619
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/FreeImageWrapper.cs
@@ -0,0 +1,5319 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.16 $
+// $Date: 2009/09/16 14:35:13 $
+// $Id: FreeImageWrapper.cs,v 1.16 2009/09/16 14:35:13 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using FreeImageAPI.IO;
+using FreeImageAPI.Metadata;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Static class importing functions from the FreeImage library
+ /// and providing additional functions.
+ /// </summary>
+ public static partial class FreeImage
+ {
+ #region Constants
+
+ /// <summary>
+ /// Array containing all 'FREE_IMAGE_MDMODEL's.
+ /// </summary>
+ public static readonly FREE_IMAGE_MDMODEL[] FREE_IMAGE_MDMODELS =
+ (FREE_IMAGE_MDMODEL[])Enum.GetValues(typeof(FREE_IMAGE_MDMODEL));
+
+ /// <summary>
+ /// Stores handles used to read from streams.
+ /// </summary>
+ private static Dictionary<FIMULTIBITMAP, fi_handle> streamHandles =
+ new Dictionary<FIMULTIBITMAP, fi_handle>();
+
+ /// <summary>
+ /// Version of the wrapper library.
+ /// </summary>
+ private static Version WrapperVersion;
+
+ private const int DIB_RGB_COLORS = 0;
+ private const int DIB_PAL_COLORS = 1;
+ private const int CBM_INIT = 0x4;
+
+ /// <summary>
+ /// An uncompressed format.
+ /// </summary>
+ public const int BI_RGB = 0;
+
+ /// <summary>
+ /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte
+ /// format consisting of a count byte followed by a byte containing a color index.
+ /// </summary>
+ public const int BI_RLE8 = 1;
+
+ /// <summary>
+ /// An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting
+ /// of a count byte followed by two word-length color indexes.
+ /// </summary>
+ public const int BI_RLE4 = 2;
+
+ /// <summary>
+ /// Specifies that the bitmap is not compressed and that the color table consists of three
+ /// <b>DWORD</b> color masks that specify the red, green, and blue components, respectively,
+ /// of each pixel. This is valid when used with 16- and 32-bpp bitmaps.
+ /// </summary>
+ public const int BI_BITFIELDS = 3;
+
+ /// <summary>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a JPEG image.
+ /// </summary>
+ public const int BI_JPEG = 4;
+
+ /// <summary>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a PNG image.
+ /// </summary>
+ public const int BI_PNG = 5;
+
+ #endregion
+
+ #region General functions
+
+ /// <summary>
+ /// Returns the internal version of this FreeImage .NET wrapper.
+ /// </summary>
+ /// <returns>The internal version of this FreeImage .NET wrapper.</returns>
+ public static Version GetWrapperVersion()
+ {
+ if (WrapperVersion == null)
+ {
+ try
+ {
+ object[] attributes = Assembly.GetAssembly(typeof(FreeImage))
+ .GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
+ if ((attributes != null) && (attributes.Length != 0))
+ {
+ AssemblyFileVersionAttribute attribute =
+ attributes[0] as AssemblyFileVersionAttribute;
+ if ((attribute != null) && (attribute.Version != null))
+ {
+ return (WrapperVersion = new Version(attribute.Version));
+ }
+ }
+ }
+ catch
+ {
+
+ }
+
+ WrapperVersion = new Version();
+ }
+
+ return WrapperVersion;
+ }
+
+ /// <summary>
+ /// Returns the version of the native FreeImage library.
+ /// </summary>
+ /// <returns>The version of the native FreeImage library.</returns>
+ public static Version GetNativeVersion()
+ {
+ return new Version(GetVersion());
+ }
+
+ /// <summary>
+ /// Returns a value indicating if the FreeImage library is available or not.
+ /// See remarks for further details.
+ /// </summary>
+ /// <returns><c>false</c> if the file is not available or out of date;
+ /// <c>true</c>, otherwise.</returns>
+ /// <remarks>
+ /// The FreeImage.NET library is a wrapper for the native C++ library
+ /// (FreeImage.dll ... dont mix ist up with this library FreeImageNet.dll).
+ /// The native library <b>must</b> be either in the same folder as the program's
+ /// executable or in a folder contained in the envirent variable <i>PATH</i>
+ /// (for example %WINDIR%\System32).<para/>
+ /// Further more must both libraries, including the program itself,
+ /// be the same architecture (x86 or x64).
+ /// </remarks>
+ public static bool IsAvailable()
+ {
+ try
+ {
+ // Call a static fast executing function
+ Version nativeVersion = new Version(GetVersion());
+ Version wrapperVersion = GetWrapperVersion();
+ // No exception thrown, the library seems to be present
+ return
+ (nativeVersion.Major >= wrapperVersion.Major) &&
+ (nativeVersion.Minor >= wrapperVersion.Minor) &&
+ (nativeVersion.Build >= wrapperVersion.Build);
+ }
+ catch (DllNotFoundException)
+ {
+ return false;
+ }
+ catch (EntryPointNotFoundException)
+ {
+ return false;
+ }
+ catch (BadImageFormatException)
+ {
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region Bitmap management functions
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Allocate(int width, int height, int bpp)
+ {
+ return Allocate(width, height, bpp, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp)
+ {
+ return AllocateT(type, width, height, bpp, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmaps.</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="Allocate"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="Allocate"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>.
+ /// So, please refer to the documentation of <see cref="FillBackground&lt;T&gt;"/> to
+ /// learn more about parameters <paramref name="color"/> and <paramref name="options"/>.
+ /// <para/>
+ /// The palette specified through parameter <paramref name="palette"/> is only copied to the
+ /// newly created image, if the desired bit depth is smaller than or equal to 8 bits per pixel.
+ /// In other words, the <paramref name="palette"/> parameter is only taken into account for
+ /// palletized images. So, for an 8-bit image, the length is 256, for an 4-bit image it is 16
+ /// and it is 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified <paramref name="color"/> is applied to the palette entry,
+ /// specified by the background color's <see cref="RGBQUAD.rgbReserved"/> field.
+ /// The image is then filled with this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="Allocate"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateEx(int width, int height, int bpp,
+ RGBQUAD? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette)
+ {
+ return AllocateEx(width, height, bpp, color, options, palette, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmaps.</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="Allocate"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="Allocate"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>.
+ /// So, please refer to the documentation of <see cref="FillBackground&lt;T&gt;"/> to
+ /// learn more about parameters <paramref name="color"/> and <paramref name="options"/>.
+ /// <para/>
+ /// The palette specified through parameter <paramref name="palette"/> is only copied to the
+ /// newly created image, if the desired bit depth is smaller than or equal to 8 bits per pixel.
+ /// In other words, the <paramref name="palette"/> parameter is only taken into account for
+ /// palletized images. So, for an 8-bit image, the length is 256, for an 4-bit image it is 16
+ /// and it is 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified <paramref name="color"/> is applied to the palette entry,
+ /// specified by the background color's <see cref="RGBQUAD.rgbReserved"/> field.
+ /// The image is then filled with this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="Allocate"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateEx(int width, int height, int bpp,
+ RGBQUAD? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask)
+ {
+ if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ RGBQUAD[] buffer = new RGBQUAD[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return AllocateEx(width, height, bpp, handle.AddrOfPinnedObject(),
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return AllocateEx(width, height, bpp, IntPtr.Zero,
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified type, width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="AllocateT"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="AllocateT"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the
+ /// documentation of <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters color and options.
+ /// <para/>
+ /// The palette specified through parameter palette is only copied to the newly created
+ /// image, if its image type is <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> and the desired bit
+ /// depth is smaller than or equal to 8 bits per pixel. In other words, the <paramref name="palette"/>
+ /// palette is only taken into account for palletized images. However, if the preceding conditions
+ /// match and if <paramref name="palette"/> is not <c>null</c>, the palette is assumed to be at
+ /// least as large as the size of a fully populated palette for the desired bit depth.
+ /// So, for an 8-bit image, this length is 256, for an 4-bit image it is 16 and it is
+ /// 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified color is applied to the palette entry, specified by the
+ /// background color's <see cref="RGBQUAD.rgbReserved"/> field. The image is then filled with
+ /// this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="AllocateT"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateExT<T>(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette) where T : struct
+ {
+ return AllocateExT(type, width, height, bpp, color, options, palette, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified type, width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="AllocateT"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="AllocateT"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the
+ /// documentation of <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters color and options.
+ /// <para/>
+ /// The palette specified through parameter palette is only copied to the newly created
+ /// image, if its image type is <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> and the desired bit
+ /// depth is smaller than or equal to 8 bits per pixel. In other words, the <paramref name="palette"/>
+ /// palette is only taken into account for palletized images. However, if the preceding conditions
+ /// match and if <paramref name="palette"/> is not <c>null</c>, the palette is assumed to be at
+ /// least as large as the size of a fully populated palette for the desired bit depth.
+ /// So, for an 8-bit image, this length is 256, for an 4-bit image it is 16 and it is
+ /// 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified color is applied to the palette entry, specified by the
+ /// background color's <see cref="RGBQUAD.rgbReserved"/> field. The image is then filled with
+ /// this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="AllocateT"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateExT<T>(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask) where T : struct
+ {
+ if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
+ return FIBITMAP.Zero;
+
+ if (!CheckColorType(type, color))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return AllocateExT(type, width, height, bpp, handle.AddrOfPinnedObject(),
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return AllocateExT(type, width, height, bpp, IntPtr.Zero,
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a .NET <see cref="System.Drawing.Bitmap"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The converted .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of <paramref name="dib"/> is not FIT_BITMAP.</exception>
+ public static Bitmap GetBitmap(FIBITMAP dib)
+ {
+ return GetBitmap(dib, true);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a .NET <see cref="System.Drawing.Bitmap"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="copyMetadata">When true existing metadata will be copied.</param>
+ /// <returns>The converted .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of <paramref name="dib"/> is not FIT_BITMAP.</exception>
+ internal static Bitmap GetBitmap(FIBITMAP dib, bool copyMetadata)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (GetImageType(dib) != FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ throw new ArgumentException("Only bitmaps with type of FIT_BITMAP can be converted.");
+ }
+
+ PixelFormat format = GetPixelFormat(dib);
+
+ if ((format == PixelFormat.Undefined) && (GetBPP(dib) == 16u))
+ {
+ throw new ArgumentException("Only 16bit 555 and 565 are supported.");
+ }
+
+ int height = (int)GetHeight(dib);
+ int width = (int)GetWidth(dib);
+ int pitch = (int)GetPitch(dib);
+
+ Bitmap result = new Bitmap(width, height, format);
+ BitmapData data;
+ // Locking the complete bitmap in writeonly mode
+ data = result.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format);
+ // Writing the bitmap data directly into the new created .NET bitmap.
+ ConvertToRawBits(data.Scan0, dib, pitch, GetBPP(dib),
+ GetRedMask(dib), GetGreenMask(dib), GetBlueMask(dib), true);
+ // Unlock the bitmap
+ result.UnlockBits(data);
+ // Apply the bitmaps resolution
+ result.SetResolution(GetResolutionX(dib), GetResolutionY(dib));
+ // Check whether the bitmap has a palette
+ if (GetPalette(dib) != IntPtr.Zero)
+ {
+ // Get the bitmaps palette to apply changes
+ ColorPalette palette = result.Palette;
+ // Get the orgininal palette
+ Color[] colorPalette = new Palette(dib).ColorData;
+ // Get the maximum number of palette entries to copy
+ int entriesToCopy = Math.Min(colorPalette.Length, palette.Entries.Length);
+
+ // Check whether the bitmap is transparent
+ if (IsTransparent(dib))
+ {
+ byte[] transTable = GetTransparencyTableEx(dib);
+ int i = 0;
+ int maxEntriesWithTrans = Math.Min(entriesToCopy, transTable.Length);
+ // Copy palette entries and include transparency
+ for (; i < maxEntriesWithTrans; i++)
+ {
+ palette.Entries[i] = Color.FromArgb(transTable[i], colorPalette[i]);
+ }
+ // Copy palette entries and that have no transparancy
+ for (; i < entriesToCopy; i++)
+ {
+ palette.Entries[i] = Color.FromArgb(0xFF, colorPalette[i]);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < entriesToCopy; i++)
+ {
+ palette.Entries[i] = colorPalette[i];
+ }
+ }
+
+ // Set the bitmaps palette
+ result.Palette = palette;
+ }
+ // Copy metadata
+ if (copyMetadata)
+ {
+ try
+ {
+ List<PropertyItem> list = new List<PropertyItem>();
+ // Get a list of all types
+ FITAG tag;
+ FIMETADATA mData;
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ // Get a unique search handle
+ mData = FindFirstMetadata(model, dib, out tag);
+ // Check if metadata exists for this type
+ if (mData.IsNull) continue;
+ do
+ {
+ PropertyItem propItem = CreatePropertyItem();
+ propItem.Len = (int)GetTagLength(tag);
+ propItem.Id = (int)GetTagID(tag);
+ propItem.Type = (short)GetTagType(tag);
+ byte[] buffer = new byte[propItem.Len];
+
+ unsafe
+ {
+ byte* src = (byte*)GetTagValue(tag);
+ fixed (byte* dst = buffer)
+ {
+ CopyMemory(dst, src, (uint)propItem.Len);
+ }
+ }
+
+ propItem.Value = buffer;
+ list.Add(propItem);
+ }
+ while (FindNextMetadata(mData, out tag));
+ FindCloseMetadata(mData);
+ }
+ foreach (PropertyItem propItem in list)
+ {
+ result.SetPropertyItem(propItem);
+ }
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts an .NET <see cref="System.Drawing.Bitmap"/> into a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="System.Drawing.Bitmap"/> to convert.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static FIBITMAP CreateFromBitmap(Bitmap bitmap)
+ {
+ return CreateFromBitmap(bitmap, false);
+ }
+
+ /// <summary>
+ /// Converts an .NET <see cref="System.Drawing.Bitmap"/> into a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="System.Drawing.Bitmap"/> to convert.</param>
+ /// <param name="copyMetadata">When true existing metadata will be copied.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ internal static FIBITMAP CreateFromBitmap(Bitmap bitmap, bool copyMetadata)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ uint bpp, red_mask, green_mask, blue_mask;
+ FREE_IMAGE_TYPE type;
+ if (!GetFormatParameters(bitmap.PixelFormat, out type, out bpp, out red_mask, out green_mask, out blue_mask))
+ {
+ throw new ArgumentException("The bitmaps pixelformat is invalid.");
+ }
+
+ // Locking the complete bitmap in readonly mode
+ BitmapData data = bitmap.LockBits(
+ new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
+ // Copying the bitmap data directly from the .NET bitmap
+ FIBITMAP result = ConvertFromRawBits(
+ data.Scan0,
+ type,
+ data.Width,
+ data.Height,
+ data.Stride,
+ bpp,
+ red_mask,
+ green_mask,
+ blue_mask,
+ true);
+ bitmap.UnlockBits(data);
+ // Handle palette
+ if (GetPalette(result) != IntPtr.Zero)
+ {
+ Palette palette = new Palette(result);
+ Color[] colors = bitmap.Palette.Entries;
+ // Only copy available palette entries
+ int entriesToCopy = Math.Min(palette.Length, colors.Length);
+ byte[] transTable = new byte[entriesToCopy];
+ for (int i = 0; i < entriesToCopy; i++)
+ {
+ RGBQUAD color = (RGBQUAD)colors[i];
+ color.rgbReserved = 0x00;
+ palette[i] = color;
+ transTable[i] = colors[i].A;
+ }
+ if ((bitmap.Flags & (int)ImageFlags.HasAlpha) != 0)
+ {
+ FreeImage.SetTransparencyTable(result, transTable);
+ }
+ }
+ // Handle meta data
+ // Disabled
+ //if (copyMetadata)
+ //{
+ // foreach (PropertyItem propItem in bitmap.PropertyItems)
+ // {
+ // FITAG tag = CreateTag();
+ // SetTagLength(tag, (uint)propItem.Len);
+ // SetTagID(tag, (ushort)propItem.Id);
+ // SetTagType(tag, (FREE_IMAGE_MDTYPE)propItem.Type);
+ // SetTagValue(tag, propItem.Value);
+ // SetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, result, "", tag);
+ // }
+ //}
+ return result;
+ }
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Array of bytes containing the raw bitmap.</param>
+ /// <param name="type">The type of the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static unsafe FIBITMAP ConvertFromRawBits(
+ byte[] bits,
+ FREE_IMAGE_TYPE type,
+ int width,
+ int height,
+ int pitch,
+ uint bpp,
+ uint red_mask,
+ uint green_mask,
+ uint blue_mask,
+ bool topdown)
+ {
+ fixed (byte* ptr = bits)
+ {
+ return ConvertFromRawBits(
+ (IntPtr)ptr,
+ type,
+ width,
+ height,
+ pitch,
+ bpp,
+ red_mask,
+ green_mask,
+ blue_mask,
+ topdown);
+ }
+ }
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block containing the raw bitmap.</param>
+ /// <param name="type">The type of the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static unsafe FIBITMAP ConvertFromRawBits(
+ IntPtr bits,
+ FREE_IMAGE_TYPE type,
+ int width,
+ int height,
+ int pitch,
+ uint bpp,
+ uint red_mask,
+ uint green_mask,
+ uint blue_mask,
+ bool topdown)
+ {
+ byte* addr = (byte*)bits;
+ if ((addr == null) || (width <= 0) || (height <= 0))
+ {
+ return FIBITMAP.Zero;
+ }
+
+ FIBITMAP dib = AllocateT(type, width, height, (int)bpp, red_mask, green_mask, blue_mask);
+ if (dib != FIBITMAP.Zero)
+ {
+ if (topdown)
+ {
+ for (int i = height - 1; i >= 0; --i)
+ {
+ CopyMemory((byte*)GetScanLine(dib, i), addr, (int)GetLine(dib));
+ addr += pitch;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; ++i)
+ {
+ CopyMemory((byte*)GetScanLine(dib, i), addr, (int)GetLine(dib));
+ addr += pitch;
+ }
+ }
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(Bitmap bitmap, string filename)
+ {
+ return SaveBitmap(
+ bitmap,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(Bitmap bitmap, string filename, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveBitmap(
+ bitmap,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags);
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="format">Format of the bitmap. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(
+ Bitmap bitmap,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ FIBITMAP dib = CreateFromBitmap(bitmap);
+ bool result = SaveEx(dib, filename, format, flags);
+ Unload(dib);
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The file will be loaded with default loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadEx(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadEx(filename, flags, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// The file will be loaded with default loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, ref FREE_IMAGE_FORMAT format)
+ {
+ return LoadEx(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.
+ /// </param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, FREE_IMAGE_LOAD_FLAGS flags, ref FREE_IMAGE_FORMAT format)
+ {
+ // check if file exists
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException(filename + " could not be found.");
+ }
+ FIBITMAP dib = new FIBITMAP();
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // query all plugins to see if one can read the file
+ format = GetFileType(filename, 0);
+ }
+ // check if the plugin is capable of loading files
+ if (FIFSupportsReading(format))
+ {
+ dib = Load(format, filename, flags);
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Loads a .NET <see cref="System.Drawing.Bitmap"/> from a file.
+ /// </summary>
+ /// <param name="filename">Name of the file to be loaded.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>The loaded .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of the image is not <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>.</exception>
+ public static Bitmap LoadBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags, ref FREE_IMAGE_FORMAT format)
+ {
+ FIBITMAP dib = LoadEx(filename, flags, ref format);
+ Bitmap result = GetBitmap(dib, true);
+ Unload(dib);
+ return result;
+ }
+
+ /// <summary>
+ /// Deletes a previously loaded FreeImage bitmap from memory and resets the handle to 0.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public static void UnloadEx(ref FIBITMAP dib)
+ {
+ if (!dib.IsNull)
+ {
+ Unload(dib);
+ dib.SetNull();
+ }
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(FIBITMAP dib, string filename)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// The bitmaps color depth can be set by 'colorDepth'.
+ /// If set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> a suitable color depth
+ /// will be taken if available.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if Save should take the
+ /// best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentException">
+ /// A direct color conversion failed.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ bool result = false;
+ // Gets format from filename if the format is unknown
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ format = GetFIFFromFilename(filename);
+ }
+ if (format != FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Checks writing support
+ if (FIFSupportsWriting(format) && FIFSupportsExportType(format, GetImageType(dib)))
+ {
+ // Check valid filename and correct it if needed
+ if (!IsFilenameValidForFIF(format, filename))
+ {
+ string extension = GetPrimaryExtensionFromFIF(format);
+ filename = Path.ChangeExtension(filename, extension);
+ }
+
+ FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
+ try
+ {
+ result = Save(format, dibToSave, filename, flags);
+ }
+ finally
+ {
+ // Always unload a temporary created bitmap.
+ if (dibToSave != dib)
+ {
+ UnloadEx(ref dibToSave);
+ }
+ // On success unload the bitmap
+ if (result && unloadSource)
+ {
+ UnloadEx(ref dib);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadFromStream(stream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadFromStream(stream, flags, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the
+ /// bitmaps real format is being analysed.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadFromStream it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream, ref FREE_IMAGE_FORMAT format)
+ {
+ return LoadFromStream(stream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the bitmaps real format is being analysed.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadFromStream it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(
+ Stream stream,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ ref FREE_IMAGE_FORMAT format)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ // Wrap the source stream if it is unable to seek (which is required by FreeImage)
+ stream = (stream.CanSeek) ? stream : new StreamWrapper(stream, true);
+
+ stream.Position = 0L;
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Get the format of the bitmap
+ format = GetFileTypeFromStream(stream);
+ // Restore the streams position
+ stream.Position = 0L;
+ }
+ if (!FIFSupportsReading(format))
+ {
+ return FIBITMAP.Zero;
+ }
+ // Create a 'FreeImageIO' structure for calling 'LoadFromHandle'
+ // using the internal structure 'FreeImageStreamIO'.
+ FreeImageIO io = FreeImageStreamIO.io;
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ return LoadFromHandle(format, ref io, handle, flags);
+ }
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ bool unloadSource)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ bool unloadSource)
+ {
+ return SaveToStream(
+ ref dib, stream,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should
+ /// take the best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ flags,
+ colorDepth,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should
+ /// take the best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanWrite)
+ {
+ throw new ArgumentException("stream is not capable of writing.");
+ }
+ if ((!FIFSupportsWriting(format)) || (!FIFSupportsExportType(format, GetImageType(dib))))
+ {
+ return false;
+ }
+
+ FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
+ bool result = false;
+
+ try
+ {
+ // Create a 'FreeImageIO' structure for calling 'SaveToHandle'
+ FreeImageIO io = FreeImageStreamIO.io;
+
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ result = SaveToHandle(format, dibToSave, ref io, handle, flags);
+ }
+ }
+ finally
+ {
+ // Always unload a temporary created bitmap.
+ if (dibToSave != dib)
+ {
+ UnloadEx(ref dibToSave);
+ }
+ // On success unload the bitmap
+ if (result && unloadSource)
+ {
+ UnloadEx(ref dib);
+ }
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region Plugin functions
+
+ /// <summary>
+ /// Checks if an extension is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="extension">The desired extension.</param>
+ /// <returns>True if the extension is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="extension"/> is null.</exception>
+ public static bool IsExtensionValidForFIF(FREE_IMAGE_FORMAT fif, string extension)
+ {
+ return IsExtensionValidForFIF(fif, extension, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ /// <summary>
+ /// Checks if an extension is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="extension">The desired extension.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the extension is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="extension"/> is null.</exception>
+ public static bool IsExtensionValidForFIF(FREE_IMAGE_FORMAT fif, string extension, StringComparison comparisonType)
+ {
+ if (extension == null)
+ {
+ throw new ArgumentNullException("extension");
+ }
+ bool result = false;
+ // Split up the string and compare each with the given extension
+ string tempList = GetFIFExtensionList(fif);
+ if (tempList != null)
+ {
+ string[] extensionList = tempList.Split(',');
+ foreach (string ext in extensionList)
+ {
+ if (extension.Equals(ext, comparisonType))
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Checks if a filename is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="filename">The desired filename.</param>
+ /// <returns>True if the filename is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> is null.</exception>
+ public static bool IsFilenameValidForFIF(FREE_IMAGE_FORMAT fif, string filename)
+ {
+ return IsFilenameValidForFIF(fif, filename, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ /// <summary>
+ /// Checks if a filename is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="filename">The desired filename.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the filename is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> is null.</exception>
+ public static bool IsFilenameValidForFIF(FREE_IMAGE_FORMAT fif, string filename, StringComparison comparisonType)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ bool result = false;
+ // Extract the filenames extension if it exists
+ string extension = Path.GetExtension(filename);
+ if (extension.Length != 0)
+ {
+ extension = extension.Remove(0, 1);
+ result = IsExtensionValidForFIF(fif, extension, comparisonType);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This function returns the primary (main or most commonly used?) extension of a certain
+ /// image format (fif). This is done by returning the first of all possible extensions
+ /// returned by GetFIFExtensionList().
+ /// That assumes, that the plugin returns the extensions in ordered form.</summary>
+ /// <param name="fif">The image format to obtain the primary extension for.</param>
+ /// <returns>The primary extension of the specified image format.</returns>
+ public static string GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT fif)
+ {
+ string result = null;
+ string extensions = GetFIFExtensionList(fif);
+ if (extensions != null)
+ {
+ int position = extensions.IndexOf(',');
+ if (position < 0)
+ {
+ result = extensions;
+ }
+ else
+ {
+ result = extensions.Substring(0, position);
+ }
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Multipage functions
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(string filename)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ false,
+ false);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(string filename, bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ false,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ create_new,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files real
+ /// format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ ref FREE_IMAGE_FORMAT format,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ create_new,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ ref FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ if (!File.Exists(filename) && !create_new)
+ {
+ throw new FileNotFoundException(filename + " could not be found.");
+ }
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Check if a plugin can read the data
+ format = GetFileType(filename, 0);
+ }
+ FIMULTIBITMAP dib = new FIMULTIBITMAP();
+ if (FIFSupportsReading(format))
+ {
+ dib = OpenMultiBitmap(format, filename, create_new, read_only, keep_cache_in_memory, flags);
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="stream">The stream to load the bitmap from.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ public static FIMULTIBITMAP OpenMultiBitmapFromStream(Stream stream)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapFromStream(stream, ref format, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="stream">The stream to load the bitmap from.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/></param>.
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ public static FIMULTIBITMAP OpenMultiBitmapFromStream(Stream stream, ref FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (stream == null)
+ return FIMULTIBITMAP.Zero;
+
+ if (!stream.CanSeek)
+ stream = new StreamWrapper(stream, true);
+
+ FIMULTIBITMAP mdib = FIMULTIBITMAP.Zero;
+ FreeImageIO io = FreeImageStreamIO.io;
+ fi_handle handle = new fi_handle(stream);
+
+ try
+ {
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ format = GetFileTypeFromHandle(ref io, handle, checked((int)stream.Length));
+ }
+
+ mdib = OpenMultiBitmapFromHandle(format, ref io, handle, flags);
+
+ if (mdib.IsNull)
+ {
+ handle.Dispose();
+ }
+ else
+ {
+ streamHandles.Add(mdib, handle);
+ }
+
+ return mdib;
+ }
+ catch
+ {
+ if (!mdib.IsNull)
+ CloseMultiBitmap(mdib, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+
+ if (handle != null)
+ handle.Dispose();
+
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only, applies any changes made to it.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmap(FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ if (CloseMultiBitmap_(bitmap, flags))
+ {
+ fi_handle handle;
+ if (streamHandles.TryGetValue(bitmap, out handle))
+ {
+ streamHandles.Remove(bitmap);
+ handle.Dispose();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only,
+ /// applies any changes made to it.
+ /// On success the handle will be reset to null.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmapEx(ref FIMULTIBITMAP bitmap)
+ {
+ return CloseMultiBitmapEx(ref bitmap, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only,
+ /// applies any changes made to it.
+ /// On success the handle will be reset to null.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmapEx(ref FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ bool result = false;
+ if (!bitmap.IsNull)
+ {
+ if (CloseMultiBitmap(bitmap, flags))
+ {
+ bitmap.SetNull();
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves the number of pages that are locked in a multi-paged bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Number of locked pages.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static int GetLockedPageCount(FIMULTIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ int result = 0;
+ GetLockedPageNumbers(dib, null, ref result);
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves a list locked pages of a multi-paged bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>List containing the indexes of the locked pages.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static int[] GetLockedPages(FIMULTIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ // Get the number of pages and create an array to save the information
+ int count = 0;
+ int[] result = null;
+ // Get count
+ if (GetLockedPageNumbers(dib, result, ref count))
+ {
+ result = new int[count];
+ // Fill array
+ if (!GetLockedPageNumbers(dib, result, ref count))
+ {
+ result = null;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap from a stream and returns the
+ /// FreeImage memory stream used as temporary buffer.
+ /// The bitmap can not be modified by calling
+ /// <see cref="FreeImage.AppendPage(FIMULTIBITMAP,FIBITMAP)"/>,
+ /// <see cref="FreeImage.InsertPage(FIMULTIBITMAP,Int32,FIBITMAP)"/>,
+ /// <see cref="FreeImage.MovePage(FIMULTIBITMAP,Int32,Int32)"/> or
+ /// <see cref="FreeImage.DeletePage(FIMULTIBITMAP,Int32)"/>.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="memory">The temporary memory buffer used to load the bitmap.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> can not read.</exception>
+ public static FIMULTIBITMAP LoadMultiBitmapFromStream(
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ out FIMEMORY memory)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream");
+ }
+ const int blockSize = 1024;
+ int bytesRead;
+ byte[] buffer = new byte[blockSize];
+
+ stream = stream.CanSeek ? stream : new StreamWrapper(stream, true);
+ memory = OpenMemory(IntPtr.Zero, 0);
+
+ do
+ {
+ bytesRead = stream.Read(buffer, 0, blockSize);
+ WriteMemory(buffer, (uint)blockSize, (uint)1, memory);
+ }
+ while (bytesRead == blockSize);
+
+ return LoadMultiBitmapFromMemory(format, memory, flags);
+ }
+
+ #endregion
+
+ #region Filetype functions
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// In case the stream is not seekable, the stream will have been used
+ /// and must be recreated for loading.
+ /// </summary>
+ /// <param name="stream">Name of the stream to analyze.</param>
+ /// <returns>Type of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> can not read.</exception>
+ public static FREE_IMAGE_FORMAT GetFileTypeFromStream(Stream stream)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ // Wrap the stream if it cannot seek
+ stream = (stream.CanSeek) ? stream : new StreamWrapper(stream, true);
+ // Create a 'FreeImageIO' structure for the stream
+ FreeImageIO io = FreeImageStreamIO.io;
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ return GetFileTypeFromHandle(ref io, handle, 0);
+ }
+ }
+
+ #endregion
+
+ #region Pixel access functions
+
+ /// <summary>
+ /// Retrieves an hBitmap for a FreeImage bitmap.
+ /// Call FreeHbitmap(IntPtr) to free the handle.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hdc">A reference device context.
+ /// Use IntPtr.Zero if no reference is available.</param>
+ /// <param name="unload">When true dib will be unloaded if the function succeeded.</param>
+ /// <returns>The hBitmap for the FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe IntPtr GetHbitmap(FIBITMAP dib, IntPtr hdc, bool unload)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ IntPtr hBitmap = IntPtr.Zero;
+ bool release = false;
+ IntPtr ppvBits = IntPtr.Zero;
+ // Check if we have destination
+ if (release = (hdc == IntPtr.Zero))
+ {
+ // We don't so request dc
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (hdc != IntPtr.Zero)
+ {
+ // Get pointer to the infoheader of the bitmap
+ IntPtr info = GetInfo(dib);
+ // Create a bitmap in the dc
+ hBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0);
+ if (hBitmap != IntPtr.Zero && ppvBits != IntPtr.Zero)
+ {
+ // Copy the data into the dc
+ CopyMemory(ppvBits, GetBits(dib), (GetHeight(dib) * GetPitch(dib)));
+ // Success: we unload the bitmap
+ if (unload)
+ {
+ Unload(dib);
+ }
+ }
+ // We have to release the dc
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ return hBitmap;
+ }
+
+ /// <summary>
+ /// Returns an HBITMAP created by the <c>CreateDIBitmap()</c> function which in turn
+ /// has always the same color depth as the reference DC, which may be provided
+ /// through <paramref name="hdc"/>. The desktop DC will be used,
+ /// if <c>IntPtr.Zero</c> DC is specified.
+ /// Call <see cref="FreeImage.FreeHbitmap(IntPtr)"/> to free the handle.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="unload">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>If the function succeeds, the return value is a handle to the
+ /// compatible bitmap. If the function fails, the return value is <see cref="IntPtr.Zero"/>.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static IntPtr GetBitmapForDevice(FIBITMAP dib, IntPtr hdc, bool unload)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ IntPtr hbitmap = IntPtr.Zero;
+ bool release = false;
+ if (release = (hdc == IntPtr.Zero))
+ {
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (hdc != IntPtr.Zero)
+ {
+ hbitmap = CreateDIBitmap(
+ hdc,
+ GetInfoHeader(dib),
+ CBM_INIT,
+ GetBits(dib),
+ GetInfo(dib),
+ DIB_RGB_COLORS);
+ if (unload)
+ {
+ Unload(dib);
+ }
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ return hbitmap;
+ }
+
+ /// <summary>
+ /// Creates a FreeImage DIB from a Device Context/Compatible Bitmap.
+ /// </summary>
+ /// <param name="hbitmap">Handle to the bitmap.</param>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="hbitmap"/> is null.</exception>
+ public unsafe static FIBITMAP CreateFromHbitmap(IntPtr hbitmap, IntPtr hdc)
+ {
+ if (hbitmap == IntPtr.Zero)
+ {
+ throw new ArgumentNullException("hbitmap");
+ }
+
+ FIBITMAP dib = new FIBITMAP();
+ BITMAP bm;
+ uint colors;
+ bool release;
+
+ if (GetObject(hbitmap, sizeof(BITMAP), (IntPtr)(&bm)) != 0)
+ {
+ dib = Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0, 0, 0);
+ if (!dib.IsNull)
+ {
+ colors = GetColorsUsed(dib);
+ if (release = (hdc == IntPtr.Zero))
+ {
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (GetDIBits(
+ hdc,
+ hbitmap,
+ 0,
+ (uint)bm.bmHeight,
+ GetBits(dib),
+ GetInfo(dib),
+ DIB_RGB_COLORS) != 0)
+ {
+ if (colors != 0)
+ {
+ BITMAPINFOHEADER* bmih = (BITMAPINFOHEADER*)GetInfo(dib);
+ bmih[0].biClrImportant = bmih[0].biClrUsed = colors;
+ }
+ }
+ else
+ {
+ UnloadEx(ref dib);
+ }
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ }
+
+ return dib;
+ }
+
+ /// <summary>
+ /// Frees a bitmap handle.
+ /// </summary>
+ /// <param name="hbitmap">Handle to a bitmap.</param>
+ /// <returns>True on success, false on failure.</returns>
+ public static bool FreeHbitmap(IntPtr hbitmap)
+ {
+ return DeleteObject(hbitmap);
+ }
+
+ #endregion
+
+ #region Bitmap information functions
+
+ /// <summary>
+ /// Retrieves a DIB's resolution in X-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The resolution in 'dots per inch'.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static uint GetResolutionX(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return (uint)(0.5d + 0.0254d * GetDotsPerMeterX(dib));
+ }
+
+ /// <summary>
+ /// Retrieves a DIB's resolution in Y-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The resolution in 'dots per inch'.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static uint GetResolutionY(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return (uint)(0.5d + 0.0254d * GetDotsPerMeterY(dib));
+ }
+
+ /// <summary>
+ /// Sets a DIB's resolution in X-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new resolution in 'dots per inch'.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static void SetResolutionX(FIBITMAP dib, uint res)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ SetDotsPerMeterX(dib, (uint)((double)res / 0.0254d + 0.5d));
+ }
+
+ /// <summary>
+ /// Sets a DIB's resolution in Y-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new resolution in 'dots per inch'.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static void SetResolutionY(FIBITMAP dib, uint res)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ SetDotsPerMeterY(dib, (uint)((double)res / 0.0254d + 0.5d));
+ }
+
+ /// <summary>
+ /// Returns whether the image is a greyscale image or not.
+ /// The function scans all colors in the bitmaps palette for entries where
+ /// red, green and blue are not all the same (not a grey color).
+ /// Supports 1-, 4- and 8-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>True if the image is a greyscale image, else false.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe bool IsGreyscaleImage(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ bool result = true;
+ uint bpp = GetBPP(dib);
+ switch (bpp)
+ {
+ case 1:
+ case 4:
+ case 8:
+ RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
+ uint paletteLength = GetColorsUsed(dib);
+ for (int i = 0; i < paletteLength; i++)
+ {
+ if (palette[i].rgbRed != palette[i].rgbGreen ||
+ palette[i].rgbRed != palette[i].rgbBlue)
+ {
+ result = false;
+ break;
+ }
+ }
+ break;
+ default:
+ result = false;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a structure that represents the palette of a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>A structure representing the bitmaps palette.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static Palette GetPaletteEx(FIBITMAP dib)
+ {
+ return new Palette(dib);
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFOHEADER"/> structure of a FreeImage bitmap.
+ /// The structure is a copy, so changes will have no effect on
+ /// the bitmap itself.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="BITMAPINFOHEADER"/> structure of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe BITMAPINFOHEADER GetInfoHeaderEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return *(BITMAPINFOHEADER*)GetInfoHeader(dib);
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFO"/> structure of a FreeImage bitmap.
+ /// The structure is a copy, so changes will have no effect on
+ /// the bitmap itself.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="BITMAPINFO"/> structure of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static BITMAPINFO GetInfoEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ BITMAPINFO result = new BITMAPINFO();
+ result.bmiHeader = GetInfoHeaderEx(dib);
+ IntPtr ptr = GetPalette(dib);
+ if (ptr == IntPtr.Zero)
+ {
+ result.bmiColors = new RGBQUAD[0];
+ }
+ else
+ {
+ result.bmiColors = new MemoryArray<RGBQUAD>(ptr, (int)result.bmiHeader.biClrUsed).Data;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the pixelformat of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="System.Drawing.Imaging.PixelFormat"/> of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static PixelFormat GetPixelFormat(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ PixelFormat result = PixelFormat.Undefined;
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (GetBPP(dib))
+ {
+ case 1:
+ result = PixelFormat.Format1bppIndexed;
+ break;
+ case 4:
+ result = PixelFormat.Format4bppIndexed;
+ break;
+ case 8:
+ result = PixelFormat.Format8bppIndexed;
+ break;
+ case 16:
+ if ((GetBlueMask(dib) == FI16_565_BLUE_MASK) &&
+ (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
+ (GetRedMask(dib) == FI16_565_RED_MASK))
+ {
+ result = PixelFormat.Format16bppRgb565;
+ }
+ if ((GetBlueMask(dib) == FI16_555_BLUE_MASK) &&
+ (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
+ (GetRedMask(dib) == FI16_555_RED_MASK))
+ {
+ result = PixelFormat.Format16bppRgb555;
+ }
+ break;
+ case 24:
+ result = PixelFormat.Format24bppRgb;
+ break;
+ case 32:
+ result = PixelFormat.Format32bppArgb;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves all parameters needed to create a new FreeImage bitmap from
+ /// the format of a .NET <see cref="System.Drawing.Image"/>.
+ /// </summary>
+ /// <param name="format">The <see cref="System.Drawing.Imaging.PixelFormat"/>
+ /// of the .NET <see cref="System.Drawing.Image"/>.</param>
+ /// <param name="type">Returns the type used for the new bitmap.</param>
+ /// <param name="bpp">Returns the color depth for the new bitmap.</param>
+ /// <param name="red_mask">Returns the red_mask for the new bitmap.</param>
+ /// <param name="green_mask">Returns the green_mask for the new bitmap.</param>
+ /// <param name="blue_mask">Returns the blue_mask for the new bitmap.</param>
+ /// <returns>True in case a matching conversion exists; else false.
+ /// </returns>
+ public static bool GetFormatParameters(
+ PixelFormat format,
+ out FREE_IMAGE_TYPE type,
+ out uint bpp,
+ out uint red_mask,
+ out uint green_mask,
+ out uint blue_mask)
+ {
+ bool result = false;
+ type = FREE_IMAGE_TYPE.FIT_UNKNOWN;
+ bpp = 0;
+ red_mask = 0;
+ green_mask = 0;
+ blue_mask = 0;
+ switch (format)
+ {
+ case PixelFormat.Format1bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 1;
+ result = true;
+ break;
+ case PixelFormat.Format4bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 4;
+ result = true;
+ break;
+ case PixelFormat.Format8bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 8;
+ result = true;
+ break;
+ case PixelFormat.Format16bppRgb565:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 16;
+ red_mask = FI16_565_RED_MASK;
+ green_mask = FI16_565_GREEN_MASK;
+ blue_mask = FI16_565_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format16bppRgb555:
+ case PixelFormat.Format16bppArgb1555:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 16;
+ red_mask = FI16_555_RED_MASK;
+ green_mask = FI16_555_GREEN_MASK;
+ blue_mask = FI16_555_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format24bppRgb:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 24;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format32bppRgb:
+ case PixelFormat.Format32bppArgb:
+ case PixelFormat.Format32bppPArgb:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 32;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format16bppGrayScale:
+ type = FREE_IMAGE_TYPE.FIT_UINT16;
+ bpp = 16;
+ result = true;
+ break;
+ case PixelFormat.Format48bppRgb:
+ type = FREE_IMAGE_TYPE.FIT_RGB16;
+ bpp = 48;
+ result = true;
+ break;
+ case PixelFormat.Format64bppArgb:
+ case PixelFormat.Format64bppPArgb:
+ type = FREE_IMAGE_TYPE.FIT_RGBA16;
+ bpp = 64;
+ result = true;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the <see cref="FREE_IMAGE_FORMAT"/> for the specified
+ /// <see cref="ImageFormat"/>.
+ /// </summary>
+ /// <param name="imageFormat">The <see cref="ImageFormat"/>
+ /// for which to return the corresponding <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> for the specified
+ /// <see cref="ImageFormat"/></returns>
+ public static FREE_IMAGE_FORMAT GetFormat(ImageFormat imageFormat)
+ {
+ if (imageFormat != null)
+ {
+ if (imageFormat.Equals(ImageFormat.Bmp))
+ return FREE_IMAGE_FORMAT.FIF_BMP;
+ if (imageFormat.Equals(ImageFormat.Gif))
+ return FREE_IMAGE_FORMAT.FIF_GIF;
+ if (imageFormat.Equals(ImageFormat.Icon))
+ return FREE_IMAGE_FORMAT.FIF_ICO;
+ if (imageFormat.Equals(ImageFormat.Jpeg))
+ return FREE_IMAGE_FORMAT.FIF_JPEG;
+ if (imageFormat.Equals(ImageFormat.Png))
+ return FREE_IMAGE_FORMAT.FIF_PNG;
+ if (imageFormat.Equals(ImageFormat.Tiff))
+ return FREE_IMAGE_FORMAT.FIF_TIFF;
+ }
+ return FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ }
+
+ /// <summary>
+ /// Retrieves all parameters needed to create a new FreeImage bitmap from
+ /// raw bits <see cref="System.Drawing.Image"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="FREE_IMAGE_TYPE"/>
+ /// of the data in memory.</param>
+ /// <param name="bpp">The color depth for the data.</param>
+ /// <param name="red_mask">Returns the red_mask for the data.</param>
+ /// <param name="green_mask">Returns the green_mask for the data.</param>
+ /// <param name="blue_mask">Returns the blue_mask for the data.</param>
+ /// <returns>True in case a matching conversion exists; else false.
+ /// </returns>
+ public static bool GetTypeParameters(
+ FREE_IMAGE_TYPE type,
+ int bpp,
+ out uint red_mask,
+ out uint green_mask,
+ out uint blue_mask)
+ {
+ bool result = false;
+ red_mask = 0;
+ green_mask = 0;
+ blue_mask = 0;
+ switch (type)
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+ switch (bpp)
+ {
+ case 1:
+ case 4:
+ case 8:
+ result = true;
+ break;
+ case 16:
+ result = true;
+ red_mask = FI16_555_RED_MASK;
+ green_mask = FI16_555_GREEN_MASK;
+ blue_mask = FI16_555_BLUE_MASK;
+ break;
+ case 24:
+ case 32:
+ result = true;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ break;
+ }
+ break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ break;
+ default:
+ result = true;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Compares two FreeImage bitmaps.
+ /// </summary>
+ /// <param name="dib1">The first bitmap to compare.</param>
+ /// <param name="dib2">The second bitmap to compare.</param>
+ /// <param name="flags">Determines which components of the bitmaps will be compared.</param>
+ /// <returns>True in case both bitmaps match the compare conditions, false otherwise.</returns>
+ public static bool Compare(FIBITMAP dib1, FIBITMAP dib2, FREE_IMAGE_COMPARE_FLAGS flags)
+ {
+ // Check whether one bitmap is null
+ if (dib1.IsNull ^ dib2.IsNull)
+ {
+ return false;
+ }
+ // Check whether both pointers are the same
+ if (dib1 == dib2)
+ {
+ return true;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.HEADER) > 0) && (!CompareHeader(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.PALETTE) > 0) && (!ComparePalette(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.DATA) > 0) && (!CompareData(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.METADATA) > 0) && (!CompareMetadata(dib1, dib2)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private static unsafe bool CompareHeader(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ IntPtr i1 = GetInfoHeader(dib1);
+ IntPtr i2 = GetInfoHeader(dib2);
+ return CompareMemory((void*)i1, (void*)i2, sizeof(BITMAPINFOHEADER));
+ }
+
+ private static unsafe bool ComparePalette(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ IntPtr pal1 = GetPalette(dib1), pal2 = GetPalette(dib2);
+ bool hasPalette1 = pal1 != IntPtr.Zero;
+ bool hasPalette2 = pal2 != IntPtr.Zero;
+ if (hasPalette1 ^ hasPalette2)
+ {
+ return false;
+ }
+ if (!hasPalette1)
+ {
+ return true;
+ }
+ uint colors = GetColorsUsed(dib1);
+ if (colors != GetColorsUsed(dib2))
+ {
+ return false;
+ }
+ return CompareMemory((void*)pal1, (void*)pal2, sizeof(RGBQUAD) * colors);
+ }
+
+ private static unsafe bool CompareData(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ uint width = GetWidth(dib1);
+ if (width != GetWidth(dib2))
+ {
+ return false;
+ }
+ uint height = GetHeight(dib1);
+ if (height != GetHeight(dib2))
+ {
+ return false;
+ }
+ uint bpp = GetBPP(dib1);
+ if (bpp != GetBPP(dib2))
+ {
+ return false;
+ }
+ if (GetColorType(dib1) != GetColorType(dib2))
+ {
+ return false;
+ }
+ FREE_IMAGE_TYPE type = GetImageType(dib1);
+ if (type != GetImageType(dib2))
+ {
+ return false;
+ }
+ if (GetRedMask(dib1) != GetRedMask(dib2))
+ {
+ return false;
+ }
+ if (GetGreenMask(dib1) != GetGreenMask(dib2))
+ {
+ return false;
+ }
+ if (GetBlueMask(dib1) != GetBlueMask(dib2))
+ {
+ return false;
+ }
+
+ byte* ptr1, ptr2;
+ int fullBytes;
+ int shift;
+ uint line = GetLine(dib1);
+
+ if (type == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (bpp)
+ {
+ case 32:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 24:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 16:
+ short* sPtr1, sPtr2;
+ short mask = (short)(GetRedMask(dib1) | GetGreenMask(dib1) | GetBlueMask(dib1));
+ if (mask == -1)
+ {
+ for (int i = 0; i < height; i++)
+ {
+ sPtr1 = (short*)GetScanLine(dib1, i);
+ sPtr2 = (short*)GetScanLine(dib2, i);
+ if (!CompareMemory(sPtr1, sPtr1, line))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ {
+ sPtr1 = (short*)GetScanLine(dib1, i);
+ sPtr2 = (short*)GetScanLine(dib2, i);
+ for (int x = 0; x < width; x++)
+ {
+ if ((sPtr1[x] & mask) != (sPtr2[x] & mask))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ break;
+ case 8:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 4:
+ fullBytes = (int)width / 2;
+ shift = (width % 2) == 0 ? 8 : 4;
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (fullBytes != 0)
+ {
+ if (!CompareMemory(ptr1, ptr2, fullBytes))
+ {
+ return false;
+ }
+ ptr1 += fullBytes;
+ ptr2 += fullBytes;
+ }
+ if (shift != 8)
+ {
+ if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
+ {
+ return false;
+ }
+ }
+ }
+ break;
+ case 1:
+ fullBytes = (int)width / 8;
+ shift = 8 - ((int)width % 8);
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (fullBytes != 0)
+ {
+ if (!CompareMemory(ptr1, ptr2, fullBytes))
+ {
+ return false;
+ }
+ ptr1 += fullBytes;
+ ptr2 += fullBytes;
+ }
+ if (shift != 8)
+ {
+ if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
+ {
+ return false;
+ }
+ }
+ }
+ break;
+ default:
+ throw new NotSupportedException("Only 1, 4, 8, 16, 24 and 32 bpp bitmaps are supported.");
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static bool CompareMetadata(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ MetadataTag tag1, tag2;
+
+ foreach (FREE_IMAGE_MDMODEL metadataModel in FREE_IMAGE_MDMODELS)
+ {
+ if (GetMetadataCount(metadataModel, dib1) !=
+ GetMetadataCount(metadataModel, dib2))
+ {
+ return false;
+ }
+ if (GetMetadataCount(metadataModel, dib1) == 0)
+ {
+ continue;
+ }
+
+ FIMETADATA mdHandle = FindFirstMetadata(metadataModel, dib1, out tag1);
+ if (mdHandle.IsNull)
+ {
+ continue;
+ }
+ do
+ {
+ if ((!GetMetadata(metadataModel, dib2, tag1.Key, out tag2)) || (tag1 != tag2))
+ {
+ FindCloseMetadata(mdHandle);
+ return false;
+ }
+ }
+ while (FindNextMetadata(mdHandle, out tag1));
+ FindCloseMetadata(mdHandle);
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Returns the FreeImage bitmap's transparency table.
+ /// The array is empty in case the bitmap has no transparency table.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The FreeImage bitmap's transparency table.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe byte[] GetTransparencyTableEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ uint count = GetTransparencyCount(dib);
+ byte[] result = new byte[count];
+ byte* ptr = (byte*)GetTransparencyTable(dib);
+ fixed (byte* dst = result)
+ {
+ CopyMemory(dst, ptr, count);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Set the FreeImage bitmap's transparency table. Only affects palletised bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="table">The FreeImage bitmap's new transparency table.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="table"/> is null.</exception>
+ public static void SetTransparencyTable(FIBITMAP dib, byte[] table)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (table == null)
+ {
+ throw new ArgumentNullException("table");
+ }
+ SetTransparencyTable(dib, table, table.Length);
+ }
+
+ /// <summary>
+ /// This function returns the number of unique colors actually used by the
+ /// specified 1-, 4-, 8-, 16-, 24- or 32-bit image. This might be different from
+ /// what function FreeImage_GetColorsUsed() returns, which actually returns the
+ /// palette size for palletised images. Works for
+ /// <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> type images only.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns the number of unique colors used by the image specified or
+ /// zero, if the image type cannot be handled.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe int GetUniqueColors(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ int result = 0;
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ BitArray bitArray;
+ int uniquePalEnts;
+ int hashcode;
+ byte[] lut;
+ int width = (int)GetWidth(dib);
+ int height = (int)GetHeight(dib);
+
+ switch (GetBPP(dib))
+ {
+ case 1:
+
+ result = 1;
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ break;
+ }
+
+ if ((*(byte*)GetScanLine(dib, 0) & 0x80) == 0)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ int mask = 0x80;
+ for (int x = 0; x < width; x++)
+ {
+ if ((scanline[x / 8] & mask) > 0)
+ {
+ return 2;
+ }
+ mask = (mask == 0x1) ? 0x80 : (mask >> 1);
+ }
+ }
+ }
+ else
+ {
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ int mask = 0x80;
+ for (int x = 0; x < width; x++)
+ {
+ if ((scanline[x / 8] & mask) == 0)
+ {
+ return 2;
+ }
+ mask = (mask == 0x1) ? 0x80 : (mask >> 1);
+ }
+ }
+ }
+ break;
+
+ case 4:
+
+ bitArray = new BitArray(0x10);
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ result = 1;
+ break;
+ }
+
+ for (int y = 0; (y < height) && (result < uniquePalEnts); y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ bool top = true;
+ for (int x = 0; (x < width) && (result < uniquePalEnts); x++)
+ {
+ if (top)
+ {
+ hashcode = lut[scanline[x / 2] >> 4];
+ }
+ else
+ {
+ hashcode = lut[scanline[x / 2] & 0xF];
+ }
+ top = !top;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 8:
+
+ bitArray = new BitArray(0x100);
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ result = 1;
+ break;
+ }
+
+ for (int y = 0; (y < height) && (result < uniquePalEnts); y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ for (int x = 0; (x < width) && (result < uniquePalEnts); x++)
+ {
+ hashcode = lut[scanline[x]];
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 16:
+
+ bitArray = new BitArray(0x10000);
+
+ for (int y = 0; y < height; y++)
+ {
+ short* scanline = (short*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline++)
+ {
+ hashcode = *scanline;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 24:
+
+ bitArray = new BitArray(0x1000000);
+
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline += 3)
+ {
+ hashcode = *((int*)scanline) & 0x00FFFFFF;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 32:
+
+ bitArray = new BitArray(0x1000000);
+
+ for (int y = 0; y < height; y++)
+ {
+ int* scanline = (int*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline++)
+ {
+ hashcode = *scanline & 0x00FFFFFF;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Verifies whether the FreeImage bitmap is 16bit 555.
+ /// </summary>
+ /// <param name="dib">The FreeImage bitmap to verify.</param>
+ /// <returns><b>true</b> if the bitmap is RGB16-555; otherwise <b>false</b>.</returns>
+ public static bool IsRGB555(FIBITMAP dib)
+ {
+ return ((GetRedMask(dib) == FI16_555_RED_MASK) &&
+ (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
+ (GetBlueMask(dib) == FI16_555_BLUE_MASK));
+ }
+
+ /// <summary>
+ /// Verifies whether the FreeImage bitmap is 16bit 565.
+ /// </summary>
+ /// <param name="dib">The FreeImage bitmap to verify.</param>
+ /// <returns><b>true</b> if the bitmap is RGB16-565; otherwise <b>false</b>.</returns>
+ public static bool IsRGB565(FIBITMAP dib)
+ {
+ return ((GetRedMask(dib) == FI16_565_RED_MASK) &&
+ (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
+ (GetBlueMask(dib) == FI16_565_BLUE_MASK));
+ }
+
+ #endregion
+
+ #region ICC profile functions
+
+ /// <summary>
+ /// Creates a new ICC-Profile for a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data)
+ {
+ return new FIICCPROFILE(dib, data);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile for a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <param name="size">The number of bytes of <paramref name="data"/> to use.</param>
+ /// <returns>The new ICC-Profile of the FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data, int size)
+ {
+ return new FIICCPROFILE(dib, data, size);
+ }
+
+ #endregion
+
+ #region Conversion functions
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ threshold,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting
+ /// with <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_DITHER ditherMethod)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ ditherMethod,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_QUANTIZE quantizationMethod)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ quantizationMethod,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ threshold,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_DITHER ditherMethod,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ ditherMethod,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_QUANTIZE quantizationMethod,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ quantizationMethod,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ internal static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold,
+ FREE_IMAGE_DITHER ditherMethod,
+ FREE_IMAGE_QUANTIZE quantizationMethod,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FIBITMAP result = new FIBITMAP();
+ FIBITMAP dibTemp = new FIBITMAP();
+ uint bpp = GetBPP(dib);
+ bool reorderPalette = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE) > 0);
+ bool forceGreyscale = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) > 0);
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (conversion & (FREE_IMAGE_COLOR_DEPTH)0xFF)
+ {
+ case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD:
+
+ if (bpp != 1)
+ {
+ if (forceGreyscale)
+ {
+ result = Threshold(dib, threshold);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ result = Threshold(dib, threshold);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER:
+
+ if (bpp != 1)
+ {
+ if (forceGreyscale)
+ {
+ result = Dither(dib, ditherMethod);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ result = Dither(dib, ditherMethod);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP:
+
+ if (bpp != 4)
+ {
+ // Special case when 1bpp and FIC_PALETTE
+ if (forceGreyscale ||
+ ((bpp == 1) && (GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_PALETTE)))
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo4Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 16, null, 4);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo4Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ }
+
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP:
+
+ if (bpp != 8)
+ {
+ if (forceGreyscale)
+ {
+ result = ConvertToGreyscale(dib);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantize(dibTemp, quantizationMethod);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale))
+ {
+ result = ConvertToGreyscale(dib);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP_555:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo16Bits555(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 16 || GetRedMask(dib) != FI16_555_RED_MASK || GetGreenMask(dib) != FI16_555_GREEN_MASK || GetBlueMask(dib) != FI16_555_BLUE_MASK)
+ {
+ result = ConvertTo16Bits555(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo16Bits565(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 16 || GetRedMask(dib) != FI16_565_RED_MASK || GetGreenMask(dib) != FI16_565_GREEN_MASK || GetBlueMask(dib) != FI16_565_BLUE_MASK)
+ {
+ result = ConvertTo16Bits565(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo24Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 24)
+ {
+ result = ConvertTo24Bits(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo32Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 32)
+ {
+ result = ConvertTo32Bits(dib);
+ }
+ break;
+ }
+ }
+
+ if (result.IsNull)
+ {
+ return dib;
+ }
+ if (unloadSource)
+ {
+ Unload(dib);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/>
+ /// method that provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <param name="minColorDepth"><b>true</b> to create a bitmap with the smallest possible
+ /// color depth for the specified <paramref name="PaletteSize"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, RGBQUAD[] ReservePalette, bool minColorDepth)
+ {
+ FIBITMAP result;
+ if (minColorDepth)
+ {
+ int bpp;
+ if (PaletteSize >= 256)
+ bpp = 8;
+ else if (PaletteSize > 2)
+ bpp = 4;
+ else
+ bpp = 1;
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, bpp);
+ }
+ else
+ {
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, 8);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/>
+ /// method that provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// partial or full provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <param name="bpp">The desired color depth of the created image.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, RGBQUAD[] ReservePalette, int bpp)
+ {
+ unsafe
+ {
+ FIBITMAP result = FIBITMAP.Zero;
+ FIBITMAP temp = FIBITMAP.Zero;
+ int reservedSize = (ReservePalette == null) ? 0 : ReservePalette.Length;
+
+ if (bpp == 8)
+ {
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, reservedSize, ReservePalette);
+ }
+ else if (bpp == 4)
+ {
+ temp = ColorQuantizeEx(dib, quantize, Math.Min(16, PaletteSize), reservedSize, ReservePalette);
+ if (!temp.IsNull)
+ {
+ result = Allocate((int)GetWidth(temp), (int)GetHeight(temp), 4, 0, 0, 0);
+ CloneMetadata(result, temp);
+ CopyMemory(GetPalette(result), GetPalette(temp), sizeof(RGBQUAD) * 16);
+
+ for (int y = (int)GetHeight(temp) - 1; y >= 0; y--)
+ {
+ Scanline<byte> srcScanline = new Scanline<byte>(temp, y);
+ Scanline<FI4BIT> dstScanline = new Scanline<FI4BIT>(result, y);
+
+ for (int x = (int)GetWidth(temp) - 1; x >= 0; x--)
+ {
+ dstScanline[x] = srcScanline[x];
+ }
+ }
+ }
+ }
+ else if (bpp == 1)
+ {
+ temp = ColorQuantizeEx(dib, quantize, 2, reservedSize, ReservePalette);
+ if (!temp.IsNull)
+ {
+ result = Allocate((int)GetWidth(temp), (int)GetHeight(temp), 1, 0, 0, 0);
+ CloneMetadata(result, temp);
+ CopyMemory(GetPalette(result), GetPalette(temp), sizeof(RGBQUAD) * 2);
+
+ for (int y = (int)GetHeight(temp) - 1; y >= 0; y--)
+ {
+ Scanline<byte> srcScanline = new Scanline<byte>(temp, y);
+ Scanline<FI1BIT> dstScanline = new Scanline<FI1BIT>(result, y);
+
+ for (int x = (int)GetWidth(temp) - 1; x >= 0; x--)
+ {
+ dstScanline[x] = srcScanline[x];
+ }
+ }
+ }
+ }
+
+ UnloadEx(ref temp);
+ return result;
+ }
+ }
+
+ #endregion
+
+ #region Metadata
+
+ /// <summary>
+ /// Copies metadata from one FreeImage bitmap to another.
+ /// </summary>
+ /// <param name="src">Source FreeImage bitmap containing the metadata.</param>
+ /// <param name="dst">FreeImage bitmap to copy the metadata to.</param>
+ /// <param name="flags">Flags to switch different copy modes.</param>
+ /// <returns>Returns -1 on failure else the number of copied tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="src"/> or <paramref name="dst"/> is null.</exception>
+ public static int CloneMetadataEx(FIBITMAP src, FIBITMAP dst, FREE_IMAGE_METADATA_COPY flags)
+ {
+ if (src.IsNull)
+ {
+ throw new ArgumentNullException("src");
+ }
+ if (dst.IsNull)
+ {
+ throw new ArgumentNullException("dst");
+ }
+
+ FITAG tag = new FITAG(), tag2 = new FITAG();
+ int copied = 0;
+
+ // Clear all existing metadata
+ if ((flags & FREE_IMAGE_METADATA_COPY.CLEAR_EXISTING) > 0)
+ {
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ if (!SetMetadata(model, dst, null, tag))
+ {
+ return -1;
+ }
+ }
+ }
+
+ bool keep = !((flags & FREE_IMAGE_METADATA_COPY.REPLACE_EXISTING) > 0);
+
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ FIMETADATA mData = FindFirstMetadata(model, src, out tag);
+ if (mData.IsNull) continue;
+ do
+ {
+ string key = GetTagKey(tag);
+ if (!(keep && GetMetadata(model, dst, key, out tag2)))
+ {
+ if (SetMetadata(model, dst, key, tag))
+ {
+ copied++;
+ }
+ }
+ }
+ while (FindNextMetadata(mData, out tag));
+ FindCloseMetadata(mData);
+ }
+
+ return copied;
+ }
+
+ /// <summary>
+ /// Returns the comment of a JPEG, PNG or GIF image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Comment of the FreeImage bitmp, or null in case no comment exists.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static string GetImageComment(FIBITMAP dib)
+ {
+ string result = null;
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FITAG tag;
+ if (GetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", out tag))
+ {
+ MetadataTag metadataTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ result = metadataTag.Value as string;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Sets the comment of a JPEG, PNG or GIF image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="comment">New comment of the FreeImage bitmap.
+ /// Use null to remove the comment.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool SetImageComment(FIBITMAP dib, string comment)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ bool result;
+ if (comment != null)
+ {
+ FITAG tag = CreateTag();
+ MetadataTag metadataTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ metadataTag.Value = comment;
+ result = SetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", tag);
+ DeleteTag(tag);
+ }
+ else
+ {
+ result = SetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", FITAG.Zero);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieve a metadata attached to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="model">The metadata model to look for.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The metadata field name.</param>
+ /// <param name="tag">A <see cref="MetadataTag"/> structure returned by the function.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool GetMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ string key,
+ out MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FITAG _tag;
+ bool result;
+ if (GetMetadata(model, dib, key, out _tag))
+ {
+ tag = new MetadataTag(_tag, model);
+ result = true;
+ }
+ else
+ {
+ tag = null;
+ result = false;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Attach a new metadata tag to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="model">The metadata model used to store the tag.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The tag field name.</param>
+ /// <param name="tag">The <see cref="MetadataTag"/> to be attached.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool SetMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ string key,
+ MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return SetMetadata(model, dib, key, tag.tag);
+ }
+
+ /// <summary>
+ /// Provides information about the first instance of a tag that matches the metadata model.
+ /// </summary>
+ /// <param name="model">The model to match.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Unique search handle that can be used to call FindNextMetadata or FindCloseMetadata.
+ /// Null if the metadata model does not exist.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIMETADATA FindFirstMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ out MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FITAG _tag;
+ FIMETADATA result = FindFirstMetadata(model, dib, out _tag);
+ if (result.IsNull)
+ {
+ tag = null;
+ return result;
+ }
+ tag = new MetadataTag(_tag, model);
+ if (metaDataSearchHandler.ContainsKey(result))
+ {
+ metaDataSearchHandler[result] = model;
+ }
+ else
+ {
+ metaDataSearchHandler.Add(result, model);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Find the next tag, if any, that matches the metadata model argument in a previous call
+ /// to FindFirstMetadata, and then alters the tag object contents accordingly.
+ /// </summary>
+ /// <param name="mdhandle">Unique search handle provided by FindFirstMetadata.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool FindNextMetadata(FIMETADATA mdhandle, out MetadataTag tag)
+ {
+ FITAG _tag;
+ bool result;
+ if (FindNextMetadata(mdhandle, out _tag))
+ {
+ tag = new MetadataTag(_tag, metaDataSearchHandler[mdhandle]);
+ result = true;
+ }
+ else
+ {
+ tag = null;
+ result = false;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Closes the specified metadata search handle and releases associated resources.
+ /// </summary>
+ /// <param name="mdhandle">The handle to close.</param>
+ public static void FindCloseMetadata(FIMETADATA mdhandle)
+ {
+ if (metaDataSearchHandler.ContainsKey(mdhandle))
+ {
+ metaDataSearchHandler.Remove(mdhandle);
+ }
+ FindCloseMetadata_(mdhandle);
+ }
+
+ /// <summary>
+ /// This dictionary links FIMETADATA handles and FREE_IMAGE_MDMODEL models.
+ /// </summary>
+ private static Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL> metaDataSearchHandler
+ = new Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL>(1);
+
+ #endregion
+
+ #region Rotation and Flipping
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90°.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Rotate(FIBITMAP dib, double angle)
+ {
+ return Rotate(dib, angle, IntPtr.Zero);
+ }
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90°.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Rotate<T>(FIBITMAP dib, double angle, T? backgroundColor) where T : struct
+ {
+ if (backgroundColor.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { backgroundColor.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return Rotate(dib, angle, handle.AddrOfPinnedObject());
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return Rotate(dib, angle, IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Rotates a 4-bit color FreeImage bitmap.
+ /// Allowed values for <paramref name="angle"/> are 90, 180 and 270.
+ /// In case <paramref name="angle"/> is 0 or 360 a clone is returned.
+ /// 0 is returned for other values or in case the rotation fails.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is kind of temporary due to FreeImage's lack of
+ /// rotating 4-bit images. It's particularly used by <see cref="FreeImageBitmap"/>'s
+ /// method RotateFlip. This function will be removed as soon as FreeImage
+ /// supports rotating 4-bit images.
+ /// </remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe FIBITMAP Rotate4bit(FIBITMAP dib, double angle)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FIBITMAP result = new FIBITMAP();
+ int ang = (int)angle;
+
+ if ((GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) &&
+ (GetBPP(dib) == 4) &&
+ ((ang % 90) == 0))
+ {
+ int width, height, xOrg, yOrg;
+ Scanline<FI4BIT>[] src, dst;
+ width = (int)GetWidth(dib);
+ height = (int)GetHeight(dib);
+ byte index = 0;
+ switch (ang)
+ {
+ case 90:
+ result = Allocate(height, width, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+ for (int y = 0; y < width; y++)
+ {
+ yOrg = height - 1;
+ for (int x = 0; x < height; x++, yOrg--)
+ {
+ index = src[yOrg][y];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 180:
+ result = Allocate(width, height, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+
+ yOrg = height - 1;
+ for (int y = 0; y < height; y++, yOrg--)
+ {
+ xOrg = width - 1;
+ for (int x = 0; x < width; x++, xOrg--)
+ {
+ index = src[yOrg][xOrg];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 270:
+ result = Allocate(height, width, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+ xOrg = width - 1;
+ for (int y = 0; y < width; y++, xOrg--)
+ {
+ for (int x = 0; x < height; x++)
+ {
+ index = src[x][xOrg];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 0:
+ case 360:
+ result = Clone(dib);
+ break;
+ }
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Upsampling / downsampling
+
+ /// <summary>
+ /// Enlarges or shrinks the FreeImage bitmap selectively per side and fills newly added areas
+ /// with the specified background color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function enlarges or shrinks an image selectively per side.
+ /// The main purpose of this function is to add borders to an image.
+ /// To add a border to any of the image's sides, a positive integer value must be passed in
+ /// any of the parameters <paramref name="left"/>, <paramref name="top"/>, <paramref name="right"/>
+ /// or <paramref name="bottom"/>. This value represents the border's
+ /// width in pixels. Newly created parts of the image (the border areas) are filled with the
+ /// specified <paramref name="color"/>.
+ /// Specifying a negative integer value for a certain side, will shrink or crop the image on
+ /// this side. Consequently, specifying zero for a certain side will not change the image's
+ /// extension on that side.
+ /// <para/>
+ /// So, calling this function with all parameters <paramref name="left"/>, <paramref name="top"/>,
+ /// <paramref name="right"/> and <paramref name="bottom"/> set to zero, is
+ /// effectively the same as calling function <see cref="Clone"/>; setting all parameters
+ /// <paramref name="left"/>, <paramref name="top"/>, <paramref name="right"/> and
+ /// <paramref name="bottom"/> to value equal to or smaller than zero, my easily be substituted
+ /// by a call to function <see cref="Copy"/>. Both these cases produce a new image, which is
+ /// guaranteed not to be larger than the input image. Thus, since the specified
+ /// <paramref name="color"/> is not needed in these cases, <paramref name="color"/>
+ /// may be <c>null</c>.
+ /// <para/>
+ /// Both parameters <paramref name="color"/> and <paramref name="options"/> work according to
+ /// function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the documentation of
+ /// <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters <paramref name="color"/>
+ /// and <paramref name="options"/>. For palletized images, the palette of the input image is
+ /// transparently copied to the newly created enlarged or shrunken image, so any color look-ups
+ /// are performed on this palette.
+ /// </remarks>
+ /// <example>
+ /// // create a white color<br/>
+ /// RGBQUAD c;<br/>
+ /// c.rgbRed = 0xFF;<br/>
+ /// c.rgbGreen = 0xFF;<br/>
+ /// c.rgbBlue = 0xFF;<br/>
+ /// c.rgbReserved = 0x00;<br/>
+ /// <br/>
+ /// // add a white, symmetric 10 pixel wide border to the image<br/>
+ /// dib2 = FreeImage_EnlargeCanvas(dib, 10, 10, 10, 10, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// <br/>
+ /// // add white, 20 pixel wide stripes to the top and bottom side of the image<br/>
+ /// dib3 = FreeImage_EnlargeCanvas(dib, 0, 20, 0, 20, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// <br/>
+ /// // add white, 30 pixel wide stripes to the right side of the image and<br/>
+ /// // cut off the 40 leftmost pixel columns<br/>
+ /// dib3 = FreeImage_EnlargeCanvas(dib, -40, 0, 30, 0, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// </example>
+ public static FIBITMAP EnlargeCanvas<T>(FIBITMAP dib, int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ if (dib.IsNull)
+ return FIBITMAP.Zero;
+
+ if (!CheckColorType(GetImageType(dib), color))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return EnlargeCanvas(dib, left, top, right, bottom, handle.AddrOfPinnedObject(), options);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return EnlargeCanvas(dib, left, top, right, bottom, IntPtr.Zero, options);
+ }
+ }
+
+ #endregion
+
+ #region Color
+
+ /// <summary>
+ /// Sets all pixels of the specified image to the color provided through the
+ /// <paramref name="color"/> parameter. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="color">The color to fill the bitmap with. See remarks for further details.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ /// <remarks>
+ /// This function sets all pixels of an image to the color provided through
+ /// the <paramref name="color"/> parameter. <see cref="RGBQUAD"/> is used for standard type images.
+ /// For non standard type images the underlaying structure is used.
+ /// <para/>
+ /// So, <paramref name="color"/> must be of type <see cref="Double"/>, if the image to be filled is of type
+ /// <see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/> and must be a <see cref="FIRGBF"/> structure if the
+ /// image is of type <see cref="FREE_IMAGE_TYPE.FIT_RGBF"/> and so on.
+ /// <para/>
+ /// However, the fill color is always specified through a <see cref="RGBQUAD"/> structure
+ /// for all images of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>.
+ /// So, for 32- and 24-bit images, the red, green and blue members of the <see cref="RGBQUAD"/>
+ /// structure are directly used for the image's red, green and blue channel respectively.
+ /// Although alpha transparent <see cref="RGBQUAD"/> colors are
+ /// supported, the alpha channel of a 32-bit image never gets modified by this function.
+ /// A fill color with an alpha value smaller than 255 gets blended with the image's actual
+ /// background color, which is determined from the image's bottom-left pixel.
+ /// So, currently using alpha enabled colors, assumes the image to be unicolor before the
+ /// fill operation. However, the <see cref="RGBQUAD.rgbReserved"/> field is only taken into account,
+ /// if option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_RGBA"/> has been specified.
+ /// <para/>
+ /// For 16-bit images, the red-, green- and blue components of the specified color are
+ /// transparently translated into either the 16-bit 555 or 565 representation. This depends
+ /// on the image's actual red- green- and blue masks.
+ /// <para/>
+ /// Special attention must be payed for palletized images. Generally, the RGB color specified
+ /// is looked up in the image's palette. The found palette index is then used to fill the image.
+ /// There are some option flags, that affect this lookup process:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT"/></term>
+ /// <description>
+ /// Uses the color, that is nearest to the specified color.
+ /// This is the default behavior and should always find a
+ /// color in the palette. However, the visual result may
+ /// far from what was expected and mainly depends on the
+ /// image's palette.
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_EQUAL_COLOR"/></term>
+ /// <description>
+ /// Searches the image's palette for the specified color
+ /// but only uses the returned palette index, if the specified
+ /// color exactly matches the palette entry. Of course,
+ /// depending on the image's actual palette entries, this
+ /// operation may fail. In this case, the function falls back
+ /// to option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// and uses the RGBQUAD's rgbReserved member (or its low nibble for 4-bit images
+ /// or its least significant bit (LSB) for 1-bit images) as
+ /// the palette index used for the fill operation.
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/></term>
+ /// <description>
+ /// Does not perform any color lookup from the palette, but
+ /// uses the RGBQUAD's alpha channel member rgbReserved as
+ /// the palette index to be used for the fill operation.
+ /// However, for 4-bit images, only the low nibble of the
+ /// rgbReserved member are used and for 1-bit images, only
+ /// the least significant bit (LSB) is used.
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </remarks>
+ public static bool FillBackground<T>(FIBITMAP dib, T color, FREE_IMAGE_COLOR_OPTIONS options)
+ where T : struct
+ {
+ if (dib.IsNull)
+ return false;
+
+ if (!CheckColorType(GetImageType(dib), color))
+ return false;
+
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return FillBackground(dib, handle.AddrOfPinnedObject(), options);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+
+ #endregion
+
+ #region Wrapper functions
+
+ /// <summary>
+ /// Returns the next higher possible color depth.
+ /// </summary>
+ /// <param name="bpp">Color depth to increase.</param>
+ /// <returns>The next higher color depth or 0 if there is no valid color depth.</returns>
+ internal static int GetNextColorDepth(int bpp)
+ {
+ int result = 0;
+ switch (bpp)
+ {
+ case 1:
+ result = 4;
+ break;
+ case 4:
+ result = 8;
+ break;
+ case 8:
+ result = 16;
+ break;
+ case 16:
+ result = 24;
+ break;
+ case 24:
+ result = 32;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the next lower possible color depth.
+ /// </summary>
+ /// <param name="bpp">Color depth to decrease.</param>
+ /// <returns>The next lower color depth or 0 if there is no valid color depth.</returns>
+ internal static int GetPrevousColorDepth(int bpp)
+ {
+ int result = 0;
+ switch (bpp)
+ {
+ case 32:
+ result = 24;
+ break;
+ case 24:
+ result = 16;
+ break;
+ case 16:
+ result = 8;
+ break;
+ case 8:
+ result = 4;
+ break;
+ case 4:
+ result = 1;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Reads a null-terminated c-string.
+ /// </summary>
+ /// <param name="ptr">Pointer to the first char of the string.</param>
+ /// <returns>The converted string.</returns>
+ internal static unsafe string PtrToStr(byte* ptr)
+ {
+ string result = null;
+ if (ptr != null)
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+
+ while (*ptr != 0)
+ {
+ sb.Append((char)(*(ptr++)));
+ }
+ result = sb.ToString();
+ }
+ return result;
+ }
+
+ internal static unsafe byte[] CreateShrunkenPaletteLUT(FIBITMAP dib, out int uniqueColors)
+ {
+ byte[] result = null;
+ uniqueColors = 0;
+
+ if ((!dib.IsNull) && (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) && (GetBPP(dib) <= 8))
+ {
+ int size = (int)GetColorsUsed(dib);
+ List<RGBQUAD> newPalette = new List<RGBQUAD>(size);
+ List<byte> lut = new List<byte>(size);
+ RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
+ RGBQUAD color;
+ int index;
+
+ for (int i = 0; i < size; i++)
+ {
+ color = palette[i];
+ color.rgbReserved = 255; // ignore alpha
+
+ index = newPalette.IndexOf(color);
+ if (index < 0)
+ {
+ newPalette.Add(color);
+ lut.Add((byte)(newPalette.Count - 1));
+ }
+ else
+ {
+ lut.Add((byte)index);
+ }
+ }
+ result = lut.ToArray();
+ uniqueColors = newPalette.Count;
+ }
+ return result;
+ }
+
+ internal static PropertyItem CreatePropertyItem()
+ {
+ return (PropertyItem)Activator.CreateInstance(typeof(PropertyItem), true);
+ }
+
+ private static unsafe void CopyPalette(FIBITMAP src, FIBITMAP dst)
+ {
+ RGBQUAD* orgPal = (RGBQUAD*)GetPalette(src);
+ RGBQUAD* newPal = (RGBQUAD*)GetPalette(dst);
+ uint size = (uint)(sizeof(RGBQUAD) * GetColorsUsed(src));
+ CopyMemory(newPal, orgPal, size);
+ }
+
+ private static unsafe Scanline<FI4BIT>[] Get04BitScanlines(FIBITMAP dib)
+ {
+ int height = (int)GetHeight(dib);
+ Scanline<FI4BIT>[] array = new Scanline<FI4BIT>[height];
+ for (int i = 0; i < height; i++)
+ {
+ array[i] = new Scanline<FI4BIT>(dib, i);
+ }
+ return array;
+ }
+
+ /// <summary>
+ /// Changes a bitmaps color depth.
+ /// Used by SaveEx and SaveToStream.
+ /// </summary>
+ private static FIBITMAP PrepareBitmapColorDepth(FIBITMAP dibToSave, FREE_IMAGE_FORMAT format, FREE_IMAGE_COLOR_DEPTH colorDepth)
+ {
+ FREE_IMAGE_TYPE type = GetImageType(dibToSave);
+ if (type == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ int bpp = (int)GetBPP(dibToSave);
+ int targetBpp = (int)(colorDepth & FREE_IMAGE_COLOR_DEPTH.FICD_COLOR_MASK);
+
+ if (colorDepth != FREE_IMAGE_COLOR_DEPTH.FICD_AUTO)
+ {
+ // A fix colordepth was chosen
+ if (FIFSupportsExportBPP(format, targetBpp))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, colorDepth, false);
+ }
+ else
+ {
+ throw new ArgumentException("FreeImage\n\nFreeImage Library plugin " +
+ GetFormatFromFIF(format) + " is unable to write images with a color depth of " +
+ targetBpp + " bpp.");
+ }
+ }
+ else
+ {
+ // Auto selection was chosen
+ if (!FIFSupportsExportBPP(format, bpp))
+ {
+ // The color depth is not supported
+ int bppUpper = bpp;
+ int bppLower = bpp;
+ // Check from the bitmaps current color depth in both directions
+ do
+ {
+ bppUpper = GetNextColorDepth(bppUpper);
+ if (FIFSupportsExportBPP(format, bppUpper))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppUpper, false);
+ break;
+ }
+ bppLower = GetPrevousColorDepth(bppLower);
+ if (FIFSupportsExportBPP(format, bppLower))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppLower, false);
+ break;
+ }
+ } while (!((bppLower == 0) && (bppUpper == 0)));
+ }
+ }
+ }
+ return dibToSave;
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(void* buf1, void* buf2, uint length)
+ {
+ return (length == RtlCompareMemory(buf1, buf2, length));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(void* buf1, void* buf2, long length)
+ {
+ return (length == RtlCompareMemory(buf1, buf2, checked((uint)length)));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(IntPtr buf1, IntPtr buf2, uint length)
+ {
+ return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), length));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(IntPtr buf1, IntPtr buf2, long length)
+ {
+ return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), checked((uint)length)));
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(void* dst, void* src, long size)
+ {
+ MoveMemory(dst, src, checked((uint)size));
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(IntPtr dst, IntPtr src, uint size)
+ {
+ MoveMemory(dst.ToPointer(), src.ToPointer(), size);
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(IntPtr dst, IntPtr src, long size)
+ {
+ MoveMemory(dst.ToPointer(), src.ToPointer(), checked((uint)size));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(byte* dest, byte* src, int len)
+ {
+ if (len >= 0x10)
+ {
+ do
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ *((int*)(dest + 8)) = *((int*)(src + 8));
+ *((int*)(dest + 12)) = *((int*)(src + 12));
+ dest += 0x10;
+ src += 0x10;
+ }
+ while ((len -= 0x10) >= 0x10);
+ }
+ if (len > 0)
+ {
+ if ((len & 8) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ dest += 8;
+ src += 8;
+ }
+ if ((len & 4) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ dest += 4;
+ src += 4;
+ }
+ if ((len & 2) != 0)
+ {
+ *((short*)dest) = *((short*)src);
+ dest += 2;
+ src += 2;
+ }
+ if ((len & 1) != 0)
+ {
+ *dest = *src;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(byte* dest, byte* src, long len)
+ {
+ CopyMemory(dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(void* dest, void* src, long len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(void* dest, void* src, int len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(IntPtr, IntPtr, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(IntPtr dest, IntPtr src, int len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(IntPtr, IntPtr, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(IntPtr dest, IntPtr src, long len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, void* src, int len)
+ {
+ GCHandle handle = GCHandle.Alloc(dest, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)handle.AddrOfPinnedObject(), (byte*)src, len);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, void* src, long len)
+ {
+ CopyMemory(dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, IntPtr src, int len)
+ {
+ CopyMemory(dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, IntPtr src, long len)
+ {
+ CopyMemory(dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(void* dest, Array src, int len)
+ {
+ GCHandle handle = GCHandle.Alloc(src, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)dest, (byte*)handle.AddrOfPinnedObject(), len);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(void* dest, Array src, long len)
+ {
+ CopyMemory((byte*)dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(IntPtr dest, Array src, int len)
+ {
+ CopyMemory((byte*)dest, src, len);
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(IntPtr dest, Array src, long len)
+ {
+ CopyMemory((byte*)dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of one array into another array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the content to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, Array src, int len)
+ {
+ GCHandle dHandle = GCHandle.Alloc(dest, GCHandleType.Pinned);
+ try
+ {
+ GCHandle sHandle = GCHandle.Alloc(src, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)dHandle.AddrOfPinnedObject(), (byte*)sHandle.AddrOfPinnedObject(), len);
+ }
+ finally
+ {
+ sHandle.Free();
+ }
+ }
+ finally
+ {
+ dHandle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the content of one array into another array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the content to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, Array src, long len)
+ {
+ CopyMemory(dest, src, checked((int)len));
+ }
+
+ internal static string ColorToString(Color color)
+ {
+ return string.Format(
+ System.Globalization.CultureInfo.CurrentCulture,
+ "{{Name={0}, ARGB=({1}, {2}, {3}, {4})}}",
+ new object[] { color.Name, color.A, color.R, color.G, color.B });
+ }
+
+ internal static void Resize(ref string str, int length)
+ {
+ if ((str != null) && (length >= 0) && (str.Length != length))
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, length);
+ str = new string(chars);
+ }
+ }
+
+ internal static void Resize(ref string str, int min, int max)
+ {
+ if ((str != null) && (min >= 0) && (max >= 0) && (min <= max))
+ {
+ if (str.Length < min)
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, min);
+ str = new string(chars);
+ }
+ else if (str.Length > max)
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, max);
+ str = new string(chars);
+ }
+ }
+ }
+
+ internal static void Resize<T>(ref T[] array, int length)
+ {
+ if ((array != null) && (length >= 0) && (array.Length != length))
+ {
+ Array.Resize(ref array, length);
+ }
+ }
+
+ internal static void Resize<T>(ref T[] array, int min, int max)
+ {
+ if ((array != null) && (min >= 0) && (max >= 0) && (min <= max))
+ {
+ if (array.Length < min)
+ {
+ Array.Resize(ref array, min);
+ }
+ else if (array.Length > max)
+ {
+ Array.Resize(ref array, max);
+ }
+ }
+ }
+
+ internal static bool CheckColorType<T>(FREE_IMAGE_TYPE imageType, T color)
+ {
+ Type type = typeof(T);
+ bool result;
+ switch (imageType)
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+ result = (type == typeof(RGBQUAD)); break;
+ case FREE_IMAGE_TYPE.FIT_COMPLEX:
+ result = (type == typeof(FICOMPLEX)); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE:
+ result = (type == typeof(double)); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT:
+ result = (type == typeof(float)); break;
+ case FREE_IMAGE_TYPE.FIT_INT16:
+ result = (type == typeof(Int16)); break;
+ case FREE_IMAGE_TYPE.FIT_INT32:
+ result = (type == typeof(Int32)); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16:
+ result = (type == typeof(FIRGB16)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16:
+ result = (type == typeof(FIRGBA16)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF:
+ result = (type == typeof(FIRGBAF)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF:
+ result = (type == typeof(FIRGBF)); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16:
+ result = (type == typeof(UInt16)); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32:
+ result = (type == typeof(UInt32)); break;
+ default:
+ result = false; break;
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Dll-Imports
+
+ /// <summary>
+ /// Retrieves a handle to a display device context (DC) for the client area of a specified window
+ /// or for the entire screen. You can use the returned handle in subsequent GDI functions to draw in the DC.
+ /// </summary>
+ /// <param name="hWnd">Handle to the window whose DC is to be retrieved.
+ /// If this value is IntPtr.Zero, GetDC retrieves the DC for the entire screen. </param>
+ /// <returns>If the function succeeds, the return value is a handle to the DC for the specified window's client area.
+ /// If the function fails, the return value is NULL.</returns>
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDC(IntPtr hWnd);
+
+ /// <summary>
+ /// Releases a device context (DC), freeing it for use by other applications.
+ /// The effect of the ReleaseDC function depends on the type of DC. It frees only common and window DCs.
+ /// It has no effect on class or private DCs.
+ /// </summary>
+ /// <param name="hWnd">Handle to the window whose DC is to be released.</param>
+ /// <param name="hDC">Handle to the DC to be released.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport("user32.dll")]
+ private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
+
+ /// <summary>
+ /// Creates a DIB that applications can write to directly.
+ /// The function gives you a pointer to the location of the bitmap bit values.
+ /// You can supply a handle to a file-mapping object that the function will use to create the bitmap,
+ /// or you can let the system allocate the memory for the bitmap.
+ /// </summary>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="pbmi">Pointer to a BITMAPINFO structure that specifies various attributes of the DIB,
+ /// including the bitmap dimensions and colors.</param>
+ /// <param name="iUsage">Specifies the type of data contained in the bmiColors array member of the BITMAPINFO structure
+ /// pointed to by pbmi (either logical palette indexes or literal RGB values).</param>
+ /// <param name="ppvBits">Pointer to a variable that receives a pointer to the location of the DIB bit values.</param>
+ /// <param name="hSection">Handle to a file-mapping object that the function will use to create the DIB.
+ /// This parameter can be NULL.</param>
+ /// <param name="dwOffset">Specifies the offset from the beginning of the file-mapping object referenced by hSection
+ /// where storage for the bitmap bit values is to begin. This value is ignored if hSection is NULL.</param>
+ /// <returns>If the function succeeds, the return value is a handle to the newly created DIB,
+ /// and *ppvBits points to the bitmap bit values. If the function fails, the return value is NULL, and *ppvBits is NULL.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDIBSection(
+ IntPtr hdc,
+ [In] IntPtr pbmi,
+ uint iUsage,
+ out IntPtr ppvBits,
+ IntPtr hSection,
+ uint dwOffset);
+
+ /// <summary>
+ /// Deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object.
+ /// After the object is deleted, the specified handle is no longer valid.
+ /// </summary>
+ /// <param name="hObject">Handle to a logical pen, brush, font, bitmap, region, or palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern bool DeleteObject(IntPtr hObject);
+
+ /// <summary>
+ /// Creates a compatible bitmap (DDB) from a DIB and, optionally, sets the bitmap bits.
+ /// </summary>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="lpbmih">Pointer to a bitmap information header structure.</param>
+ /// <param name="fdwInit">Specifies how the system initializes the bitmap bits - (use 4).</param>
+ /// <param name="lpbInit">Pointer to an array of bytes containing the initial bitmap data.</param>
+ /// <param name="lpbmi">Pointer to a BITMAPINFO structure that describes the dimensions
+ /// and color format of the array pointed to by the lpbInit parameter.</param>
+ /// <param name="fuUsage">Specifies whether the bmiColors member of the BITMAPINFO structure
+ /// was initialized - (use 0).</param>
+ /// <returns>Handle to a DIB or null on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDIBitmap(
+ IntPtr hdc,
+ IntPtr lpbmih,
+ uint fdwInit,
+ IntPtr lpbInit,
+ IntPtr lpbmi,
+ uint fuUsage);
+
+ /// <summary>
+ /// Retrieves information for the specified graphics object.
+ /// </summary>
+ /// <param name="hgdiobj">Handle to the graphics object of interest.</param>
+ /// <param name="cbBuffer">Specifies the number of bytes of information to
+ /// be written to the buffer.</param>
+ /// <param name="lpvObject">Pointer to a buffer that receives the information
+ /// about the specified graphics object.</param>
+ /// <returns>0 on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
+
+ /// <summary>
+ /// Retrieves the bits of the specified compatible bitmap and copies them into a buffer
+ /// as a DIB using the specified format.
+ /// </summary>
+ /// <param name="hdc">Handle to the device context.</param>
+ /// <param name="hbmp">Handle to the bitmap. This must be a compatible bitmap (DDB).</param>
+ /// <param name="uStartScan">Specifies the first scan line to retrieve.</param>
+ /// <param name="cScanLines">Specifies the number of scan lines to retrieve.</param>
+ /// <param name="lpvBits">Pointer to a buffer to receive the bitmap data.</param>
+ /// <param name="lpbmi">Pointer to a BITMAPINFO structure that specifies the desired
+ /// format for the DIB data.</param>
+ /// <param name="uUsage">Specifies the format of the bmiColors member of the
+ /// BITMAPINFO structure - (use 0).</param>
+ /// <returns>0 on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern unsafe int GetDIBits(
+ IntPtr hdc,
+ IntPtr hbmp,
+ uint uStartScan,
+ uint cScanLines,
+ IntPtr lpvBits,
+ IntPtr lpbmi,
+ uint uUsage);
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">Pointer to the starting address of the move destination.</param>
+ /// <param name="src">Pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">Size of the block of memory to move, in bytes.</param>
+ [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
+ public static unsafe extern void MoveMemory(void* dst, void* src, uint size);
+
+ /// <summary>
+ /// The RtlCompareMemory routine compares blocks of memory
+ /// and returns the number of bytes that are equivalent.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="count">Specifies the number of bytes to be compared.</param>
+ /// <returns>RtlCompareMemory returns the number of bytes that compare as equal.
+ /// If all bytes compare as equal, the input Length is returned.</returns>
+ [DllImport("ntdll.dll", EntryPoint = "RtlCompareMemory", SetLastError = false)]
+ internal static unsafe extern uint RtlCompareMemory(void* buf1, void* buf2, uint count);
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Library.csproj b/Wrapper/FreeImage.NET/cs/Library/Library.csproj
new file mode 100644
index 0000000..2af66bb
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Library.csproj
@@ -0,0 +1,190 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>FreeImageAPI</RootNamespace>
+ <AssemblyName>FreeImageNET</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ <RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <BaseAddress>4194304</BaseAddress>
+ <FileAlignment>512</FileAlignment>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>419</NoWarn>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <DocumentationFile>bin\Debug\FreeImageNET.XML</DocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>
+ </DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <FileAlignment>512</FileAlignment>
+ <BaseAddress>4194304</BaseAddress>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <NoWarn>419</NoWarn>
+ <DocumentationFile>bin\Release\FreeImageNET.XML</DocumentationFile>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DocumentationFile>bin\Debug\FreeImageNET.XML</DocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DocumentationFile>bin\Release\FreeImageNET.XML</DocumentationFile>
+ <Optimize>true</Optimize>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DocumentationFile>bin\Debug\FreeImageNET.XML</DocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DocumentationFile>bin\Release\FreeImageNET.XML</DocumentationFile>
+ <Optimize>true</Optimize>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Classes\FreeImagePlugin.cs" />
+ <Compile Include="Classes\FreeImageBitmap.cs" />
+ <Compile Include="Classes\FreeImageEngine.cs" />
+ <Compile Include="Classes\FreeImageStreamIO.cs" />
+ <Compile Include="Classes\GifInformation.cs" />
+ <Compile Include="Classes\ImageMetadata.cs" />
+ <Compile Include="Classes\LocalPlugin.cs" />
+ <Compile Include="Classes\MemoryArray.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Classes\MetadataModel.cs" />
+ <Compile Include="Classes\MetadataModels.cs" />
+ <Compile Include="Classes\MetadataTag.cs" />
+ <Compile Include="Classes\Palette.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Classes\PluginRepository.cs" />
+ <Compile Include="Classes\Scanline.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Classes\StreamWrapper.cs" />
+ <Compile Include="Delegates.cs" />
+ <Compile Include="Enumerations\DisposalMethodType.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_COLOR_OPTIONS.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_DITHER.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_FORMAT.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_TMO.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_TYPE.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_COLOR_CHANNEL.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_COLOR_TYPE.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_FILTER.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_JPEG_OPERATION.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_LOAD_FLAGS.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_MDMODEL.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_MDTYPE.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_QUANTIZE.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_SAVE_FLAGS.cs" />
+ <Compile Include="Enumerations\ICC_FLAGS.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_COLOR_DEPTH.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_COMPARE_FLAGS.cs" />
+ <Compile Include="Enumerations\FREE_IMAGE_METADATA_COPY.cs" />
+ <Compile Include="Enumerations\MD_SEARCH_FLAGS.cs" />
+ <Compile Include="Structs\BITMAP.cs" />
+ <Compile Include="Structs\BITMAPINFO.cs" />
+ <Compile Include="Structs\BITMAPINFOHEADER.cs" />
+ <Compile Include="Structs\FI16RGB555.cs" />
+ <Compile Include="Structs\FI16RGB565.cs" />
+ <Compile Include="Structs\FI1BIT.cs" />
+ <Compile Include="Structs\FIBITMAP.cs" />
+ <Compile Include="Structs\FICOMPLEX.cs" />
+ <Compile Include="Structs\FIICCPROFILE.cs" />
+ <Compile Include="Structs\FIMEMORY.cs" />
+ <Compile Include="Structs\FIMETADATA.cs" />
+ <Compile Include="Structs\FIMULTIBITMAP.cs" />
+ <Compile Include="Structs\FIRational.cs" />
+ <Compile Include="Structs\FIRGB16.cs" />
+ <Compile Include="Structs\FIRGBA16.cs" />
+ <Compile Include="Structs\FIRGBAF.cs" />
+ <Compile Include="Structs\FIRGBF.cs" />
+ <Compile Include="FreeImageStaticImports.cs" />
+ <Compile Include="FreeImageWrapper.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>
+ </SubType>
+ </Compile>
+ <Compile Include="Structs\FITAG.cs" />
+ <Compile Include="Structs\FIURational.cs" />
+ <Compile Include="Structs\fi_handle.cs" />
+ <Compile Include="Structs\FreeImageIO.cs" />
+ <Compile Include="Structs\FI4BIT.cs" />
+ <Compile Include="Structs\Plugin.cs" />
+ <Compile Include="Structs\RGBQUAD.cs" />
+ <Compile Include="Structs\RGBTRIPLE.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <PropertyGroup>
+ <PostBuildEvent>
+ </PostBuildEvent>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Library/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2228862
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Properties/AssemblyInfo.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Resources;
+//
+[assembly: AssemblyTitle("FreeImage.NET")]
+[assembly: AssemblyDescription(".NET wrapper for the FreeImage 3.13.0 DLL")]
+[assembly: AssemblyConfiguration("All")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("FreeImage.NET Wrapper")]
+[assembly: AssemblyCopyright("Copyright 2003-2009, FreeImage, DataGis")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("3.13.0.1")]
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyFileVersionAttribute("3.13.0.1")]
+[assembly: ComVisibleAttribute(false)]
+[assembly: NeutralResourcesLanguageAttribute("")]
+[assembly: GuidAttribute("64a4c935-b757-499c-ab8c-6110316a9e51")]
+// \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAP.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAP.cs
new file mode 100644
index 0000000..e64d33e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAP.cs
@@ -0,0 +1,104 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.2 $
+// $Date: 2008/06/16 15:15:36 $
+// $Id: BITMAP.cs,v 1.2 2008/06/16 15:15:36 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>BITMAP</b> structure defines the type, width, height, color format, and bit values of a bitmap.
+ /// </summary>
+ /// <remarks>
+ /// The bitmap formats currently used are monochrome and color. The monochrome bitmap uses a one-bit,
+ /// one-plane format. Each scan is a multiple of 32 bits.
+ /// <para/>
+ /// Scans are organized as follows for a monochrome bitmap of height n:
+ /// <para/>
+ /// <code>
+ /// Scan 0
+ /// Scan 1
+ /// .
+ /// .
+ /// .
+ /// Scan n-2
+ /// Scan n-1
+ /// </code>
+ /// <para/>
+ /// The pixels on a monochrome device are either black or white. If the corresponding bit in the
+ /// bitmap is 1, the pixel is set to the foreground color; if the corresponding bit in the bitmap
+ /// is zero, the pixel is set to the background color.
+ /// <para/>
+ /// All devices that have the RC_BITBLT device capability support bitmaps. For more information,
+ /// see <b>GetDeviceCaps</b>.
+ /// <para/>
+ /// Each device has a unique color format. To transfer a bitmap from one device to another,
+ /// use the <b>GetDIBits</b> and <b>SetDIBits</b> functions.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAP
+ {
+ /// <summary>
+ /// Specifies the bitmap type. This member must be zero.
+ /// </summary>
+ public int bmType;
+ /// <summary>
+ /// Specifies the width, in pixels, of the bitmap. The width must be greater than zero.
+ /// </summary>
+ public int bmWidth;
+ /// <summary>
+ /// Specifies the height, in pixels, of the bitmap. The height must be greater than zero.
+ /// </summary>
+ public int bmHeight;
+ /// <summary>
+ /// Specifies the number of bytes in each scan line. This value must be divisible by 2,
+ /// because the system assumes that the bit values of a bitmap form an array that is word aligned.
+ /// </summary>
+ public int bmWidthBytes;
+ /// <summary>
+ /// Specifies the count of color planes.
+ /// </summary>
+ public ushort bmPlanes;
+ /// <summary>
+ /// Specifies the number of bits required to indicate the color of a pixel.
+ /// </summary>
+ public ushort bmBitsPixel;
+ /// <summary>
+ /// Pointer to the location of the bit values for the bitmap.
+ /// The <b>bmBits</b> member must be a long pointer to an array of character (1-byte) values.
+ /// </summary>
+ public IntPtr bmBits;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFO.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFO.cs
new file mode 100644
index 0000000..8e1da37
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFO.cs
@@ -0,0 +1,203 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2008/06/16 15:16:07 $
+// $Id: BITMAPINFO.cs,v 1.3 2008/06/16 15:16:07 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>BITMAPINFO</b> structure defines the dimensions and color information for a DIB.
+ /// </summary>
+ /// <remarks>
+ /// A DIB consists of two distinct parts: a <b>BITMAPINFO</b> structure describing the dimensions
+ /// and colors of the bitmap, and an array of bytes defining the pixels of the bitmap. The bits in
+ /// the array are packed together, but each scan line must be padded with zeroes to end on a
+ /// <b>LONG</b> data-type boundary. If the height of the bitmap is positive, the bitmap is a
+ /// bottom-up DIB and its origin is the lower-left corner. If the height is negative, the bitmap is
+ /// a top-down DIB and its origin is the upper left corner.
+ /// <para/>
+ /// A bitmap is packed when the bitmap array immediately follows the <b>BITMAPINFO</b> header.
+ /// Packed bitmaps are referenced by a single pointer. For packed bitmaps, the <b>biClrUsed</b>
+ /// member must be set to an even number when using the DIB_PAL_COLORS mode so that the DIB bitmap
+ /// array starts on a <b>DWORD</b> boundary.
+ /// <para/>
+ /// <b>Note</b> The <b>bmiColors</b> member should not contain palette indexes if the bitmap is to
+ /// be stored in a file or transferred to another application.
+ /// <para/>
+ /// Unless the application has exclusive use and control of the bitmap, the bitmap color table
+ /// should contain explicit RGB values.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAPINFO : IEquatable<BITMAPINFO>
+ {
+ /// <summary>
+ /// Specifies a <see cref="FreeImageAPI.BITMAPINFOHEADER"/> structure that contains information
+ /// about the dimensions of color format.
+ /// </summary>
+ public BITMAPINFOHEADER bmiHeader;
+ /// <summary>
+ /// The <b>bmiColors</b> member contains one of the following:
+ /// <list type="bullets">
+ ///
+ /// <item>
+ /// <term>
+ /// An array of <see cref="FreeImageAPI.RGBQUAD"/>. The elements of the array that make up the
+ /// color table.
+ /// </term>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>
+ /// An array of 16-bit unsigned integers that specifies indexes into the currently realized
+ /// logical palette. This use of <b>bmiColors</b> is allowed for functions that use DIBs.
+ /// When <b>bmiColors</b> elements contain indexes to a realized logical palette, they must
+ /// also call the following bitmap functions:
+ /// </term>
+ /// </item>
+ ///
+ /// </list>
+ /// <b>CreateDIBitmap</b>
+ /// <para/>
+ /// <b>CreateDIBPatternBrush</b>
+ /// <para/>
+ /// <b>CreateDIBSection</b>
+ /// <para/>
+ /// The <i>iUsage</i> parameter of CreateDIBSection must be set to DIB_PAL_COLORS.
+ /// <para/>
+ /// The number of entries in the array depends on the values of the <b>biBitCount</b> and
+ /// <b>biClrUsed</b> members of the <see cref="FreeImageAPI.BITMAPINFOHEADER"/> structure.
+ /// <para/>
+ /// The colors in the <b>bmiColors</b> table appear in order of importance. For more information,
+ /// see the Remarks section.
+ /// </summary>
+ public RGBQUAD[] bmiColors;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFO"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFO"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFO"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFO"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(BITMAPINFO left, BITMAPINFO right)
+ {
+ if (left.bmiHeader != right.bmiHeader)
+ {
+ return false;
+ }
+ if ((left.bmiColors == null) && (right.bmiColors == null))
+ {
+ return true;
+ }
+ if ((left.bmiColors == null) || (right.bmiColors == null))
+ {
+ return false;
+ }
+ if (left.bmiColors.Length != right.bmiColors.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < left.bmiColors.Length; i++)
+ {
+ if (left.bmiColors[i] != right.bmiColors[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFO"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFO"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFO"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFO"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(BITMAPINFO left, BITMAPINFO right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="BITMAPINFO"/> structure is equivalent to this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="BITMAPINFO"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFO"/> structure
+ /// equivalent to this <see cref="BITMAPINFO"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(BITMAPINFO other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="BITMAPINFO"/> structure
+ /// and is equivalent to this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFO"/> structure
+ /// equivalent to this <see cref="BITMAPINFO"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is BITMAPINFO) && (this == ((BITMAPINFO)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="BITMAPINFO"/>.</returns>
+ public override int GetHashCode()
+ {
+ int hash = bmiHeader.GetHashCode();
+ if (bmiColors != null)
+ {
+ for (int c = 0; c < bmiColors.Length; c++)
+ {
+ hash ^= bmiColors[c].GetHashCode();
+ hash <<= 1;
+ }
+ hash <<= 1;
+ }
+ else
+ {
+ hash >>= 1;
+ }
+ return hash;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFOHEADER.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFOHEADER.cs
new file mode 100644
index 0000000..61a80b5
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/BITMAPINFOHEADER.cs
@@ -0,0 +1,352 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.4 $
+// $Date: 2008/06/16 15:17:37 $
+// $Id: BITMAPINFOHEADER.cs,v 1.4 2008/06/16 15:17:37 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// This structure contains information about the dimensions and color format
+ /// of a device-independent bitmap (DIB).
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="FreeImageAPI.BITMAPINFO"/> structure combines the
+ /// <b>BITMAPINFOHEADER</b> structure and a color table to provide a complete
+ /// definition of the dimensions and colors of a DIB.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAPINFOHEADER : IEquatable<BITMAPINFOHEADER>
+ {
+ /// <summary>
+ /// Specifies the size of the structure, in bytes.
+ /// </summary>
+ public uint biSize;
+ /// <summary>
+ /// Specifies the width of the bitmap, in pixels.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// the <b>biWidth</b> member specifies the width of the decompressed JPEG or PNG image file,
+ /// respectively.
+ /// </summary>
+ public int biWidth;
+ /// <summary>
+ /// Specifies the height of the bitmap, in pixels. If <b>biHeight</b> is positive, the bitmap
+ /// is a bottom-up DIB and its origin is the lower-left corner. If <b>biHeight</b> is negative,
+ /// the bitmap is a top-down DIB and its origin is the upper-left corner.
+ /// <para/>
+ /// If <b>biHeight</b> is negative, indicating a top-down DIB, <b>biCompression</b> must be
+ /// either BI_RGB or BI_BITFIELDS. Top-down DIBs cannot be compressed.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// the <b>biHeight</b> member specifies the height of the decompressed JPEG or PNG image file,
+ /// respectively.
+ /// </summary>
+ public int biHeight;
+ /// <summary>
+ /// Specifies the number of planes for the target device. This value must be set to 1.
+ /// </summary>
+ public ushort biPlanes;
+ /// <summary>
+ /// Specifies the number of bits per pixel.The biBitCount member of the <b>BITMAPINFOHEADER</b>
+ /// structure determines the number of bits that define each pixel and the maximum number of
+ /// colors in the bitmap. This member must be one of the following values.
+ /// <para/>
+ ///
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>0</term>
+ /// <description>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> The number of bits-per-pixel is specified
+ /// or is implied by the JPEG or PNG format.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>1</term>
+ /// <description>
+ /// The bitmap is monochrome, and the bmiColors member of <see cref="FreeImageAPI.BITMAPINFO"/>
+ /// contains two entries. Each bit in the bitmap array represents a pixel. If the bit is clear,
+ /// the pixel is displayed with the color of the first entry in the bmiColors table; if the bit
+ /// is set, the pixel has the color of the second entry in the table.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>4</term>
+ /// <description>
+ /// The bitmap has a maximum of 16 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// contains up to 16 entries. Each pixel in the bitmap is represented by a 4-bit index into the
+ /// color table. For example, if the first byte in the bitmap is 0x1F, the byte represents two
+ /// pixels. The first pixel contains the color in the second table entry, and the second pixel
+ /// contains the color in the sixteenth table entry.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>8</term>
+ /// <description>
+ /// The bitmap has a maximum of 256 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// contains up to 256 entries. In this case, each byte in the array represents a single pixel.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>16</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^16 colors. If the <b>biCompression</b> member of the
+ /// <b>BITMAPINFOHEADER</b> is BI_RGB, the <b>bmiColors</b> member of <b>BITMAPINFO</b> is NULL.
+ /// Each <b>WORD</b> in the bitmap array represents a single pixel. The relative intensities
+ /// of red, green, and blue are represented with five bits for each color component.
+ /// The value for blue is in the least significant five bits, followed by five bits each for
+ /// green and red. The most significant bit is not used. The <b>bmiColors</b> color table is used
+ /// for optimizing colors used on palette-based devices, and must contain the number of entries
+ /// specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// <para/>
+ /// If the <b>biCompression</b> member of the <b>BITMAPINFOHEADER</b> is BI_BITFIELDS, the
+ /// <b>bmiColors</b> member contains three <b>DWORD</b> color masks that specify the red, green,
+ /// and blue components, respectively, of each pixel. Each <b>WORD</b> in the bitmap array represents
+ /// a single pixel.
+ /// <para/>
+ /// <b>Windows NT/Windows 2000/XP:</b> When the <b>biCompression</b> member is BI_BITFIELDS,
+ /// bits set in each <b>DWORD</b> mask must be contiguous and should not overlap the bits
+ /// of another mask. All the bits in the pixel do not have to be used.
+ /// <para/>
+ /// <b>Windows 95/98/Me:</b> When the <b>biCompression</b> member is BI_BITFIELDS, the system
+ /// supports only the following 16bpp color masks: A 5-5-5 16-bit image, where the blue mask is
+ /// 0x001F, the green mask is 0x03E0, and the red mask is 0x7C00; and a 5-6-5 16-bit image,
+ /// where the blue mask is 0x001F, the green mask is 0x07E0, and the red mask is 0xF800.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>24</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^24 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// is NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue,
+ /// green, and red, respectively, for a pixel. The <b>bmiColors</b> color table is used for
+ /// optimizing colors used on palette-based devices, and must contain the number of entries
+ /// specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>32</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^32 colors. If the <b>biCompression</b> member of the
+ /// <b>BITMAPINFOHEADER</b> is BI_RGB, the <b>bmiColors</b> member of <b>BITMAPINFO</b> is NULL.
+ /// Each <b>DWORD</b> in the bitmap array represents the relative intensities of blue, green, and red,
+ /// respectively, for a pixel. The high byte in each <b>DWORD</b> is not used. The <b>bmiColors</b>
+ /// color table is used for optimizing colors used on palette-based devices, and must contain the
+ /// number of entries specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// <para/>
+ /// If the <b>biCompression</b> member of the <b>BITMAPINFOHEADER</b> is BI_BITFIELDS,
+ /// the <b>bmiColors</b> member contains three <b>DWORD</b> color masks that specify the red, green,
+ /// and blue components, respectively, of each pixel. Each <b>DWORD</b> in the bitmap array represents
+ /// a single pixel.
+ /// <para/>
+ /// <b>Windows NT/ 2000:</b> When the <b>biCompression</b> member is BI_BITFIELDS, bits set in each
+ /// <b>DWORD</b> mask must be contiguous and should not overlap the bits of another mask. All the
+ /// bits in the pixel do not need to be used.
+ /// <para/>
+ /// <b>Windows 95/98/Me:</b> When the <b>biCompression</b> member is BI_BITFIELDS, the system
+ /// supports only the following 32-bpp color mask: The blue mask is 0x000000FF, the green mask is
+ /// 0x0000FF00, and the red mask is 0x00FF0000.
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </summary>
+ public ushort biBitCount;
+ /// <summary>
+ /// Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be
+ /// compressed).
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>BI_RGB</term>
+ /// <description>An uncompressed format.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_RLE8</term>
+ /// <description>A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format
+ /// is a 2-byte format consisting of a count byte followed by a byte containing a color index.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_RLE4</term>
+ /// <description>An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format
+ /// consisting of a count byte followed by two word-length color indexes.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_BITFIELDS</term>
+ /// <description>Specifies that the bitmap is not compressed and that the color table consists
+ /// of three <b>DWORD</b> color masks that specify the red, green, and blue components, respectively,
+ /// of each pixel. This is valid when used with 16- and 32-bpp bitmaps.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_JPEG</term>
+ /// <description><b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a JPEG image.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_PNG</term>
+ /// <description><b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a PNG image.
+ /// </description>
+ /// </item>
+ ///
+ /// </list>
+ /// </summary>
+ public uint biCompression;
+ /// <summary>
+ /// Specifies the size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// <b>biSizeImage</b> indicates the size of the JPEG or PNG image buffer, respectively.
+ /// </summary>
+ public uint biSizeImage;
+ /// <summary>
+ /// Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// An application can use this value to select a bitmap from a resource group that best matches
+ /// the characteristics of the current device.
+ /// </summary>
+ public int biXPelsPerMeter;
+ /// <summary>
+ /// Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ public int biYPelsPerMeter;
+ /// <summary>
+ /// Specifies the number of color indexes in the color table that are actually used by the bitmap.
+ /// If this value is zero, the bitmap uses the maximum number of colors corresponding to the value
+ /// of the biBitCount member for the compression mode specified by <b>biCompression</b>.
+ /// <para/>
+ /// If <b>iClrUsed</b> is nonzero and the <b>biBitCount</b> member is less than 16, the <b>biClrUsed</b>
+ /// member specifies the actual number of colors the graphics engine or device driver accesses.
+ /// If <b>biBitCount</b> is 16 or greater, the <b>biClrUsed</b> member specifies the size of the color
+ /// table used to optimize performance of the system color palettes. If <b>biBitCount</b> equals 16 or 32,
+ /// the optimal color palette starts immediately following the three <b>DWORD</b> masks.
+ /// <para/>
+ /// When the bitmap array immediately follows the <see cref="BITMAPINFO"/> structure, it is a packed bitmap.
+ /// Packed bitmaps are referenced by a single pointer. Packed bitmaps require that the
+ /// <b>biClrUsed</b> member must be either zero or the actual size of the color table.
+ /// </summary>
+ public uint biClrUsed;
+ /// <summary>
+ /// Specifies the number of color indexes that are required for displaying the bitmap. If this value
+ /// is zero, all colors are required.
+ /// </summary>
+ public uint biClrImportant;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFOHEADER"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFOHEADER"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFOHEADER"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFOHEADER"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(BITMAPINFOHEADER left, BITMAPINFOHEADER right)
+ {
+ return ((left.biSize == right.biSize) &&
+ (left.biWidth == right.biWidth) &&
+ (left.biHeight == right.biHeight) &&
+ (left.biPlanes == right.biPlanes) &&
+ (left.biBitCount == right.biBitCount) &&
+ (left.biCompression == right.biCompression) &&
+ (left.biSizeImage == right.biSizeImage) &&
+ (left.biXPelsPerMeter == right.biXPelsPerMeter) &&
+ (left.biYPelsPerMeter == right.biYPelsPerMeter) &&
+ (left.biClrUsed == right.biClrUsed) &&
+ (left.biClrImportant == right.biClrImportant));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFOHEADER"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFOHEADER"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFOHEADER"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFOHEADER"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(BITMAPINFOHEADER left, BITMAPINFOHEADER right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="BITMAPINFOHEADER"/> structure is equivalent to this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="BITMAPINFOHEADER"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFOHEADER"/> structure
+ /// equivalent to this <see cref="BITMAPINFOHEADER"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(BITMAPINFOHEADER other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="BITMAPINFOHEADER"/> structure
+ /// and is equivalent to this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFOHEADER"/> structure
+ /// equivalent to this <see cref="BITMAPINFOHEADER"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is BITMAPINFOHEADER) && (this == (BITMAPINFOHEADER)obj));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="BITMAPINFOHEADER"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB555.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB555.cs
new file mode 100644
index 0000000..e4c189d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB555.cs
@@ -0,0 +1,277 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FI16RGB555.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI16RGB555</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 5 bits and so, takes values in the range from 0 to 31.
+ /// </summary>
+ /// <remarks>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FI16RGB555</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FI16RGB555</b> structure and my be used in all situations which require
+ /// an <b>FI16RGB555</b> type.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FI16RGB555</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FI16RGB555 fi16rgb;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// fi16rgb = new FI16RGB555(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// fi16rgb = Color.DarkSeaGreen;
+ /// // Convert the FI16RGB555 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = fi16rgb;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = fi16rgb.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FI16RGB555 : IComparable, IComparable<FI16RGB555>, IEquatable<FI16RGB555>
+ {
+ /// <summary>
+ /// The value of the color.
+ /// </summary>
+ private ushort value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FI16RGB555(Color color)
+ {
+ value = (ushort)(
+ (((color.R * 31) / 255) << FreeImage.FI16_555_RED_SHIFT) +
+ (((color.G * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT) +
+ (((color.B * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB555"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB555"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB555"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB555"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FI16RGB555 left, FI16RGB555 right)
+ {
+ return (left.value == right.value);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB555"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB555"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB555"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB555"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FI16RGB555 left, FI16RGB555 right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI16RGB555"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI16RGB555(Color value)
+ {
+ return new FI16RGB555(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI16RGB555"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI16RGB555"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FI16RGB555 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ ((value & FreeImage.FI16_555_RED_MASK) >> FreeImage.FI16_555_RED_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_555_GREEN_MASK) >> FreeImage.FI16_555_GREEN_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_555_BLUE_MASK) >> FreeImage.FI16_555_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)(
+ (((value.R * 31) / 255) << FreeImage.FI16_555_RED_SHIFT) +
+ (((value.G * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT) +
+ (((value.B * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the red color component.
+ /// </summary>
+ public byte Red
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_RED_MASK) >> FreeImage.FI16_555_RED_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_RED_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_RED_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the green color component.
+ /// </summary>
+ public byte Green
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_GREEN_MASK) >> FreeImage.FI16_555_GREEN_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_GREEN_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the blue color component.
+ /// </summary>
+ public byte Blue
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_BLUE_MASK) >> FreeImage.FI16_555_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_BLUE_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FI16RGB555"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FI16RGB555))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FI16RGB555)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FI16RGB555"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB555"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FI16RGB555 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FI16RGB555"/> structure
+ /// and is equivalent to this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB555"/> structure
+ /// equivalent to this <see cref="FI16RGB555"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FI16RGB555"/> structure is equivalent to this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB555"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB555"/> structure
+ /// equivalent to this <see cref="FI16RGB555"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FI16RGB555 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FI16RGB555"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI16RGB555"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB565.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB565.cs
new file mode 100644
index 0000000..8c1ca59
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FI16RGB565.cs
@@ -0,0 +1,277 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FI16RGB565.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI16RGB565</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 5 bits and so, takes values in the range from 0 to 31.
+ /// </summary>
+ /// <remarks>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FI16RGB565</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FI16RGB565</b> structure and my be used in all situations which require
+ /// an <b>FI16RGB565</b> type.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FI16RGB565</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FI16RGB565 fi16rgb;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// fi16rgb = new FI16RGB565(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// fi16rgb = Color.DarkSeaGreen;
+ /// // Convert the FI16RGB565 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = fi16rgb;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = fi16rgb.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FI16RGB565 : IComparable, IComparable<FI16RGB565>, IEquatable<FI16RGB565>
+ {
+ /// <summary>
+ /// The value of the color.
+ /// </summary>
+ private ushort value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FI16RGB565(Color color)
+ {
+ value = (ushort)(
+ (((color.R * 31) / 255) << FreeImage.FI16_565_RED_SHIFT) +
+ (((color.G * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT) +
+ (((color.B * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB565"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB565"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB565"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB565"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FI16RGB565 left, FI16RGB565 right)
+ {
+ return (left.value == right.value);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB565"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB565"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB565"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB565"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FI16RGB565 left, FI16RGB565 right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI16RGB565"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI16RGB565(Color value)
+ {
+ return new FI16RGB565(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI16RGB565"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI16RGB565"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FI16RGB565 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ ((value & FreeImage.FI16_565_RED_MASK) >> FreeImage.FI16_565_RED_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_565_GREEN_MASK) >> FreeImage.FI16_565_GREEN_SHIFT) * 255 / 63,
+ ((value & FreeImage.FI16_565_BLUE_MASK) >> FreeImage.FI16_565_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)(
+ (((value.R * 31) / 255) << FreeImage.FI16_565_RED_SHIFT) +
+ (((value.G * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT) +
+ (((value.B * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the red color component.
+ /// </summary>
+ public byte Red
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_RED_MASK) >> FreeImage.FI16_565_RED_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_RED_MASK)) | (((value * 31) / 255) << FreeImage.FI16_565_RED_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the green color component.
+ /// </summary>
+ public byte Green
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_GREEN_MASK) >> FreeImage.FI16_565_GREEN_SHIFT) * 255 / 63);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_GREEN_MASK)) | (((value * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the blue color component.
+ /// </summary>
+ public byte Blue
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_BLUE_MASK) >> FreeImage.FI16_565_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_BLUE_MASK)) | (((value * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FI16RGB565"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FI16RGB565))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FI16RGB565)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FI16RGB565"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB565"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FI16RGB565 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FI16RGB565"/> structure
+ /// and is equivalent to this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB565"/> structure
+ /// equivalent to this <see cref="FI16RGB565"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FI16RGB565"/> structure is equivalent to this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB565"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB565"/> structure
+ /// equivalent to this <see cref="FI16RGB565"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FI16RGB565 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FI16RGB565"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI16RGB565"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FI1BIT.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FI1BIT.cs
new file mode 100644
index 0000000..0ac49a3
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FI1BIT.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI1BIT</b> structure represents a single bit.
+ /// It's value can be <i>0</i> or <i>1</i>.
+ /// </summary>
+ [DebuggerDisplay("{value}"),
+ Serializable]
+ public struct FI1BIT
+ {
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FI1BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MaxValue = 0x01;
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FI1BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MinValue = 0x00;
+
+ /// <summary>
+ /// The value of the structure.
+ /// </summary>
+ private byte value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified value.
+ /// </summary>
+ /// <param name="value">The value to initialize with.</param>
+ private FI1BIT(byte value)
+ {
+ this.value = (byte)(value & MaxValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI1BIT"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI1BIT"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI1BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator byte(FI1BIT value)
+ {
+ return value.value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FI1BIT"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI1BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI1BIT(byte value)
+ {
+ return new FI1BIT(value);
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI1BIT"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FI4BIT.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FI4BIT.cs
new file mode 100644
index 0000000..0188c6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FI4BIT.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI4BIT</b> structure represents the half of a <see cref="Byte"/>.
+ /// It's valuerange is between <i>0</i> and <i>15</i>.
+ /// </summary>
+ [DebuggerDisplay("{value}"),
+ Serializable]
+ public struct FI4BIT
+ {
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FI4BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MaxValue = 0x0F;
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FI4BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MinValue = 0x00;
+
+ /// <summary>
+ /// The value of the structure.
+ /// </summary>
+ private byte value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified value.
+ /// </summary>
+ /// <param name="value">The value to initialize with.</param>
+ private FI4BIT(byte value)
+ {
+ this.value = (byte)(value & MaxValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI4BIT"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI4BIT"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI4BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator byte(FI4BIT value)
+ {
+ return value.value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FI4BIT"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI4BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI4BIT(byte value)
+ {
+ return new FI4BIT(value);
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI4BIT"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIBITMAP.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIBITMAP.cs
new file mode 100644
index 0000000..d12a586
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIBITMAP.cs
@@ -0,0 +1,175 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIBITMAP.cs,v 1.5 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIBITMAP</b> structure is a handle to a FreeImage bimtap.
+ /// </summary>
+ /// <remarks>
+ /// The handle represented by a <b>FIBITBAP</b> structure provides
+ /// access to either a singlepage bitmap or exactly one page of
+ /// a multipage bitmap.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIBITMAP : IComparable, IComparable<FIBITMAP>, IEquatable<FIBITMAP>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIBITMAP Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIBITMAP"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIBITMAP"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIBITMAP"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIBITMAP"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIBITMAP left, FIBITMAP right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIBITMAP"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIBITMAP"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIBITMAP"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIBITMAP"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIBITMAP left, FIBITMAP right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the handle is a null or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIBITMAP"/> handle is a null;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIBITMAP"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIBITMAP"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIBITMAP"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIBITMAP) && (this == ((FIBITMAP)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIBITMAP other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIBITMAP"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIBITMAP))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIBITMAP)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIBITMAP"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIBITMAP"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIBITMAP other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FICOMPLEX.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FICOMPLEX.cs
new file mode 100644
index 0000000..39e97fe
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FICOMPLEX.cs
@@ -0,0 +1,146 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.4 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FICOMPLEX.cs,v 1.4 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FICOMPLEX</b> structure describes a color consisting of a real and an imaginary part.
+ /// Each part is using 4 bytes of data.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FICOMPLEX : IComparable, IComparable<FICOMPLEX>, IEquatable<FICOMPLEX>
+ {
+ /// <summary>
+ /// Real part of the color.
+ /// </summary>
+ public double real;
+
+ /// <summary>
+ /// Imaginary part of the color.
+ /// </summary>
+ public double imag;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FICOMPLEX"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FICOMPLEX"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FICOMPLEX"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FICOMPLEX"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FICOMPLEX left, FICOMPLEX right)
+ {
+ return ((left.real == right.real) && (left.imag == right.imag));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FICOMPLEX"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FICOMPLEX"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FICOMPLEX"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FICOMPLEX"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FICOMPLEX left, FICOMPLEX right)
+ {
+ return ((left.real != right.real) || (left.imag == right.imag));
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FICOMPLEX"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FICOMPLEX))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FICOMPLEX)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FICOMPLEX"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FICOMPLEX"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FICOMPLEX other)
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FICOMPLEX"/> structure
+ /// and is equivalent to this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FICOMPLEX"/> structure
+ /// equivalent to this <see cref="FICOMPLEX"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FICOMPLEX) && (this == ((FICOMPLEX)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FICOMPLEX"/> structure is equivalent to this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FICOMPLEX"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FICOMPLEX"/> structure
+ /// equivalent to this <see cref="FICOMPLEX"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FICOMPLEX other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FICOMPLEX"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIICCPROFILE.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIICCPROFILE.cs
new file mode 100644
index 0000000..6afdf76
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIICCPROFILE.cs
@@ -0,0 +1,133 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2008/11/05 13:19:06 $
+// $Id: FIICCPROFILE.cs,v 1.5 2008/11/05 13:19:06 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// This Structure contains ICC-Profile data.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIICCPROFILE
+ {
+ private ICC_FLAGS flags;
+ private uint size;
+ private IntPtr data;
+
+ /// <summary>
+ /// Creates a new ICC-Profile for <paramref name="dib"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The ICC-Profile data.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public FIICCPROFILE(FIBITMAP dib, byte[] data)
+ : this(dib, data, (int)data.Length)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile for <paramref name="dib"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The ICC-Profile data.</param>
+ /// <param name="size">Number of bytes to use from data.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public unsafe FIICCPROFILE(FIBITMAP dib, byte[] data, int size)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FIICCPROFILE prof;
+ size = Math.Min(size, (int)data.Length);
+ prof = *(FIICCPROFILE*)FreeImage.CreateICCProfile(dib, data, size);
+ this.flags = prof.flags;
+ this.size = prof.size;
+ this.data = prof.data;
+ }
+
+ /// <summary>
+ /// Info flag of the profile.
+ /// </summary>
+ public ICC_FLAGS Flags
+ {
+ get { return flags; }
+ }
+
+ /// <summary>
+ /// Profile's size measured in bytes.
+ /// </summary>
+ public uint Size
+ {
+ get { return size; }
+ }
+
+ /// <summary>
+ /// Points to a block of contiguous memory containing the profile.
+ /// </summary>
+ public IntPtr DataPointer
+ {
+ get { return data; }
+ }
+
+ /// <summary>
+ /// Copy of the ICC-Profiles data.
+ /// </summary>
+ public unsafe byte[] Data
+ {
+ get
+ {
+ byte[] result;
+ FreeImage.CopyMemory(result = new byte[size], data.ToPointer(), size);
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Indicates whether the profile is CMYK.
+ /// </summary>
+ public bool IsCMYK
+ {
+ get
+ {
+ return ((flags & ICC_FLAGS.FIICC_COLOR_IS_CMYK) != 0);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIMEMORY.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMEMORY.cs
new file mode 100644
index 0000000..89a3015
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMEMORY.cs
@@ -0,0 +1,170 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIMEMORY.cs,v 1.5 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMEMORY</b> structure is a handle to an opened memory stream.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMEMORY : IComparable, IComparable<FIMEMORY>, IEquatable<FIMEMORY>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMEMORY Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMEMORY"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMEMORY"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMEMORY"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMEMORY"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMEMORY left, FIMEMORY right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMEMORY"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMEMORY"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMEMORY"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMEMORY"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMEMORY left, FIMEMORY right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMEMORY"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMEMORY"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMEMORY"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMEMORY"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMEMORY) && (this == ((FIMEMORY)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMEMORY other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMEMORY"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMEMORY))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMEMORY)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMEMORY"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMEMORY"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMEMORY other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIMETADATA.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMETADATA.cs
new file mode 100644
index 0000000..de1ea66
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMETADATA.cs
@@ -0,0 +1,178 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIMETADATA.cs,v 1.5 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMETADATA</b> structure is an unique search handle for metadata search operations.
+ /// </summary>
+ /// <remarks>
+ /// The <b>FIMETADATA</b> structure is usually returned by the
+ /// <see cref="FreeImageAPI.FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL, FIBITMAP, out FITAG)"/>
+ /// function and then used on subsequent calls to
+ /// <see cref="FreeImageAPI.FreeImage.FindNextMetadata(FIMETADATA, out FITAG)"/>.
+ /// When the <b>FIMETADATA</b> handle is no longer used, it needs to be freed by the
+ /// <see cref="FreeImageAPI.FreeImage.FindCloseMetadata(FIMETADATA)"/> function.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMETADATA : IComparable, IComparable<FIMETADATA>, IEquatable<FIMETADATA>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMETADATA Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMETADATA"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMETADATA"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMETADATA"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMETADATA"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMETADATA left, FIMETADATA right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMETADATA"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMETADATA"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMETADATA"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMETADATA"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMETADATA left, FIMETADATA right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMETADATA"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMETADATA"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMETADATA"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMETADATA"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMETADATA) && (this == ((FIMETADATA)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMETADATA other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMETADATA"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMETADATA))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMETADATA)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMETADATA"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMETADATA"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMETADATA other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIMULTIBITMAP.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMULTIBITMAP.cs
new file mode 100644
index 0000000..896a067
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIMULTIBITMAP.cs
@@ -0,0 +1,170 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIMULTIBITMAP.cs,v 1.5 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMULTIBITMAP</b> structure is a handle to a FreeImage multipaged bimtap.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMULTIBITMAP : IComparable, IComparable<FIMULTIBITMAP>, IEquatable<FIMULTIBITMAP>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMULTIBITMAP Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMULTIBITMAP"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMULTIBITMAP"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMULTIBITMAP"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMULTIBITMAP"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMULTIBITMAP left, FIMULTIBITMAP right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMULTIBITMAP"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMULTIBITMAP"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMULTIBITMAP"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMULTIBITMAP"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMULTIBITMAP left, FIMULTIBITMAP right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the handle is a null or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMULTIBITMAP"/> handle is a null;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMULTIBITMAP"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMULTIBITMAP"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMULTIBITMAP"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMULTIBITMAP) && (this == ((FIMULTIBITMAP)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMULTIBITMAP other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMULTIBITMAP"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMULTIBITMAP))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMULTIBITMAP)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMULTIBITMAP"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMULTIBITMAP"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMULTIBITMAP other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGB16.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGB16.cs
new file mode 100644
index 0000000..58e8aa9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGB16.cs
@@ -0,0 +1,267 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIRGB16.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGB16</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 16 bits and so, takes values in the range from 0 to 65535.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGB16</b> structure provides access to an underlying FreeImage <b>FIRGB16</b>
+ /// structure. To determine the red, green or blue component of a color,
+ /// use the red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGB16</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGB16</b> structure and my be used in all situations which require
+ /// an <b>FIRGB16</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component red, green or blue of <b>FIRGB16</b> is translated into
+ /// it's corresponding color component R, G or B of
+ /// <see cref="System.Drawing.Color"/> by right shifting 8 bits and shifting left 8 bits for the reverse conversion.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>FIRGB16</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>FIRGB16</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGB16</b>
+ /// </para>
+ /// <c>FIRGB16.component = Color.component &lt;&lt; 8</c>
+ /// <para>
+ /// <b>Conversion from FIRGB16 to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = FIRGB16.component &gt;&gt; 8</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGB16.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGB16(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGB16</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGB16 firgb16;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgb16 = new FIRGBA16(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgb16 = Color.DarkSeaGreen;
+ /// // Convert the FIRGB16 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgb16;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgb16.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGB16 : IComparable, IComparable<FIRGB16>, IEquatable<FIRGB16>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public ushort red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public ushort green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public ushort blue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGB16(Color color)
+ {
+ red = (ushort)(color.R << 8);
+ green = (ushort)(color.G << 8);
+ blue = (ushort)(color.B << 8);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGB16"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGB16"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGB16"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGB16"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGB16 left, FIRGB16 right)
+ {
+ return
+ ((left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGB16"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGB16"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGB16"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGB16"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGB16 left, FIRGB16 right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGB16"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGB16(Color value)
+ {
+ return new FIRGB16(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGB16"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGB16"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGB16 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb((red >> 8), (green >> 8), (blue >> 8));
+ }
+ set
+ {
+ red = (ushort)(value.R << 8);
+ green = (ushort)(value.G << 8);
+ blue = (ushort)(value.B << 8);
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGB16"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGB16))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGB16)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGB16"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGB16"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGB16 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGB16"/> structure
+ /// and is equivalent to this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGB16"/> structure
+ /// equivalent to this <see cref="FIRGB16"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGB16) && (this == ((FIRGB16)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGB16"/> structure is equivalent to this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGB16"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGB16"/> structure
+ /// equivalent to this <see cref="FIRGB16"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGB16 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGB16"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGB16"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBA16.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBA16.cs
new file mode 100644
index 0000000..5f0b3d8
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBA16.cs
@@ -0,0 +1,271 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIRGBA16.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBA16</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 16 bits and so, takes values in the range from 0 to 65535.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBA16</b> structure provides access to an underlying FreeImage <b>FIRGBA16</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the alpha, red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBA16</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBA16</b> structure and my be used in all situations which require
+ /// an <b>FIRGBA16</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBA16</b>
+ /// is translated into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an 8 bit right shift and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBA16</b>
+ /// </para>
+ /// <c>FIRGBA16.component = Color.component &lt;&lt; 8</c>
+ /// <para>
+ /// <b>Conversion from FIRGBA16 to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = FIRGBA16.component &gt;&gt; 8</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBA16.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBA16(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBA16</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBA16 firgba16;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgba16 = new FIRGBA16(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgba16 = Color.DarkSeaGreen;
+ /// // Convert the FIRGBA16 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgba16;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgba16.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBA16 : IComparable, IComparable<FIRGBA16>, IEquatable<FIRGBA16>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public ushort red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public ushort green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public ushort blue;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ public ushort alpha;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBA16(Color color)
+ {
+ red = (ushort)(color.R << 8);
+ green = (ushort)(color.G << 8);
+ blue = (ushort)(color.B << 8);
+ alpha = (ushort)(color.A << 8);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBA16"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBA16"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBA16"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBA16"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBA16 left, FIRGBA16 right)
+ {
+ return
+ ((left.alpha == right.alpha) &&
+ (left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBA16"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBA16"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBA16"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBA16"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBA16 left, FIRGBA16 right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBA16"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBA16(Color value)
+ {
+ return new FIRGBA16(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBA16"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBA16"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBA16 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb((alpha >> 8), (red >> 8), (green >> 8), (blue >> 8));
+ }
+ set
+ {
+ red = (ushort)(value.R << 8);
+ green = (ushort)(value.G << 8);
+ blue = (ushort)(value.B << 8);
+ alpha = (ushort)(value.A << 8);
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBA16"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBA16))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBA16)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBA16"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBA16"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBA16 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBA16"/> structure
+ /// and is equivalent to this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBA16"/> structure
+ /// equivalent to this <see cref="FIRGBA16"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBA16) && (this == ((FIRGBA16)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBA16"/> structure is equivalent to this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBA16"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBA16"/> structure
+ /// equivalent to this <see cref="FIRGBA16"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBA16 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBA16"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBA16"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBAF.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBAF.cs
new file mode 100644
index 0000000..b79bad9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBAF.cs
@@ -0,0 +1,276 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIRGBAF.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBAF</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 32 bits and takes values in the range from 0 to 1.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBAF</b> structure provides access to an underlying FreeImage <b>FIRGBAF</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the alpha, red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBAF</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBAF</b> structure and my be used in all situations which require
+ /// an <b>FIRGBAF</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBAF</b> is translated
+ /// into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by linearly mapping the values of one range
+ /// into the other range and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBAF</b>
+ /// </para>
+ /// <c>FIRGBAF.component = (float)Color.component / 255f</c>
+ /// <para>
+ /// <b>Conversion from FIRGBAF to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = (int)(FIRGBAF.component * 255f)</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBAF.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBAF(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBAF</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBAF firgbaf;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgbaf = new FIRGBAF(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgbaf = Color.DarkSeaGreen;
+ /// // Convert the FIRGBAF instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgbaf;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgbaf.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBAF : IComparable, IComparable<FIRGBAF>, IEquatable<FIRGBAF>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public float red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public float green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public float blue;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ public float alpha;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBAF(Color color)
+ {
+ red = (float)color.R / 255f;
+ green = (float)color.G / 255f;
+ blue = (float)color.B / 255f;
+ alpha = (float)color.A / 255f;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBAF"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBAF"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBAF"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBAF"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBAF left, FIRGBAF right)
+ {
+ return
+ ((left.alpha == right.alpha) &&
+ (left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBAF"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBAF"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBAF"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBAF"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBAF left, FIRGBAF right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBAF"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBAF(Color value)
+ {
+ return new FIRGBAF(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBAF"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBAF"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBAF value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ (int)(alpha * 255f),
+ (int)(red * 255f),
+ (int)(green * 255f),
+ (int)(blue * 255f));
+ }
+ set
+ {
+ red = (float)value.R / 255f;
+ green = (float)value.G / 255f;
+ blue = (float)value.B / 255f;
+ alpha = (float)value.A / 255f;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBAF"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBAF))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBAF)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBAF"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBAF"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBAF other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBAF"/> structure
+ /// and is equivalent to this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBAF"/> structure
+ /// equivalent to this <see cref="FIRGBAF"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBAF) && (this == ((FIRGBAF)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBAF"/> structure is equivalent to this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBAF"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBAF"/> structure
+ /// equivalent to this <see cref="FIRGBAF"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBAF other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBAF"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBAF"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBF.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBF.cs
new file mode 100644
index 0000000..e106669
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRGBF.cs
@@ -0,0 +1,272 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FIRGBF.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBF</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 32 bits and takes values in the range from 0 to 1.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBF</b> structure provides access to an underlying FreeImage <b>FIRGBF</b>
+ /// structure. To determine the red, green or blue component of a color, use the
+ /// red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBF</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBF</b> structure and my be used in all situations which require
+ /// an <b>FIRGBF</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBF</b> is translated
+ /// into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by linearly mapping the values of one range
+ /// into the other range and vice versa.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>FIRGBF</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>FIRGBF</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBF</b>
+ /// </para>
+ /// <c>FIRGBF.component = (float)Color.component / 255f</c>
+ /// <para>
+ /// <b>Conversion from FIRGBF to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = (int)(FIRGBF.component * 255f)</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBF.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBF(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBF</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBF firgbf;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgbf = new FIRGBF(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgbf = Color.DarkSeaGreen;
+ /// // Convert the FIRGBF instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgbf;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgbf.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBF : IComparable, IComparable<FIRGBF>, IEquatable<FIRGBF>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public float red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public float green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public float blue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBF(Color color)
+ {
+ red = (float)color.R / 255f;
+ green = (float)color.G / 255f;
+ blue = (float)color.B / 255f;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBF"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBF"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBF"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBF"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBF left, FIRGBF right)
+ {
+ return
+ ((left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBF"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBF"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBF"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBF"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBF left, FIRGBF right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBF"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBF(Color value)
+ {
+ return new FIRGBF(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBF"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBF"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBF value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ (int)(red * 255f),
+ (int)(green * 255f),
+ (int)(blue * 255f));
+ }
+ set
+ {
+ red = (float)value.R / 255f;
+ green = (float)value.G / 255f;
+ blue = (float)value.B / 255f;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBF"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBF))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBF)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBF"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBF"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBF other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBF"/> structure
+ /// and is equivalent to this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBF"/> structure
+ /// equivalent to this <see cref="FIRGBF"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBF) && (this == ((FIRGBF)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBF"/> structure is equivalent to this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBF"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBF"/> structure
+ /// equivalent to this <see cref="FIRGBF"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBF other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBF"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBF"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIRational.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRational.cs
new file mode 100644
index 0000000..06280b4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIRational.cs
@@ -0,0 +1,1011 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/27 16:36:23 $
+// $Id: FIRational.cs,v 1.5 2009/02/27 16:36:23 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRational</b> structure represents a fraction via two <see cref="Int32"/>
+ /// instances which are interpreted as numerator and denominator.
+ /// </summary>
+ /// <remarks>
+ /// The structure tries to approximate the value of <see cref="FreeImageAPI.FIRational(decimal)"/>
+ /// when creating a new instance by using a better algorithm than FreeImage does.
+ /// <para/>
+ /// The structure implements the following operators:
+ /// +, -, ++, --, ==, != , >, >==, &lt;, &lt;== and ~ (which switches nominator and denomiator).
+ /// <para/>
+ /// The structure can be converted into all .NET standard types either implicit or
+ /// explicit.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
+ public struct FIRational : IConvertible, IComparable, IFormattable, IComparable<FIRational>, IEquatable<FIRational>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int numerator;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int denominator;
+
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FIRational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIRational MaxValue = new FIRational(Int32.MaxValue, 1);
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FIRational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIRational MinValue = new FIRational(Int32.MinValue, 1);
+
+ /// <summary>
+ /// Represents the smallest positive <see cref="FIRational"/> value greater than zero. This field is constant.
+ /// </summary>
+ public static readonly FIRational Epsilon = new FIRational(1, Int32.MaxValue);
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="n">The numerator.</param>
+ /// <param name="d">The denominator.</param>
+ public FIRational(int n, int d)
+ {
+ numerator = n;
+ denominator = d;
+ Normalize();
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="tag">The tag to read the data from.</param>
+ public unsafe FIRational(FITAG tag)
+ {
+ switch (FreeImage.GetTagType(tag))
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_SRATIONAL:
+ int* value = (int*)FreeImage.GetTagValue(tag);
+ numerator = (int)value[0];
+ denominator = (int)value[1];
+ Normalize();
+ return;
+ default:
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="value">The value to convert into a fraction.</param>
+ /// <exception cref="OverflowException">
+ /// <paramref name="value"/> cannot be converted into a fraction
+ /// represented by two integer values.</exception>
+ public FIRational(decimal value)
+ {
+ try
+ {
+ int sign = value < 0 ? -1 : 1;
+ value = Math.Abs(value);
+ try
+ {
+ int[] contFract = CreateContinuedFraction(value);
+ CreateFraction(contFract, out numerator, out denominator);
+ Normalize();
+ }
+ catch
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ int maxDen = (Int32.MaxValue / (int)value) - 2;
+ maxDen = maxDen < 10000 ? maxDen : 10000;
+ ApproximateFraction(value, maxDen, out numerator, out denominator);
+ Normalize();
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ throw new OverflowException("Unable to convert value into a fraction");
+ }
+ }
+ numerator *= sign;
+ Normalize();
+ }
+ catch (Exception ex)
+ {
+ throw new OverflowException("Unable to calculate fraction.", ex);
+ }
+ }
+
+ /// <summary>
+ /// The numerator of the fraction.
+ /// </summary>
+ public int Numerator
+ {
+ get { return numerator; }
+ }
+
+ /// <summary>
+ /// The denominator of the fraction.
+ /// </summary>
+ public int Denominator
+ {
+ get { return denominator; }
+ }
+
+ /// <summary>
+ /// Returns the truncated value of the fraction.
+ /// </summary>
+ /// <returns></returns>
+ public int Truncate()
+ {
+ return denominator > 0 ? (int)(numerator / denominator) : 0;
+ }
+
+ /// <summary>
+ /// Returns whether the fraction is representing an integer value.
+ /// </summary>
+ public bool IsInteger
+ {
+ get
+ {
+ return (denominator == 1 ||
+ (denominator != 0 && (numerator % denominator == 0)) ||
+ (denominator == 0 && numerator == 0));
+ }
+ }
+
+ /// <summary>
+ /// Calculated the greatest common divisor of 'a' and 'b'.
+ /// </summary>
+ private static long Gcd(long a, long b)
+ {
+ a = Math.Abs(a);
+ b = Math.Abs(b);
+ long r;
+ while (b > 0)
+ {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+ return a;
+ }
+
+ /// <summary>
+ /// Calculated the smallest common multiple of 'a' and 'b'.
+ /// </summary>
+ private static long Scm(int n, int m)
+ {
+ return Math.Abs((long)n * (long)m) / Gcd(n, m);
+ }
+
+ /// <summary>
+ /// Normalizes the fraction.
+ /// </summary>
+ private void Normalize()
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ return;
+ }
+
+ if (numerator != 1 && denominator != 1)
+ {
+ int common = (int)Gcd(numerator, denominator);
+ if (common != 1 && common != 0)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+
+ if (denominator < 0)
+ {
+ numerator *= -1;
+ denominator *= -1;
+ }
+ }
+
+ /// <summary>
+ /// Normalizes a fraction.
+ /// </summary>
+ private static void Normalize(ref long numerator, ref long denominator)
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ else if (numerator != 1 && denominator != 1)
+ {
+ long common = Gcd(numerator, denominator);
+ if (common != 1)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ if (denominator < 0)
+ {
+ numerator *= -1;
+ denominator *= -1;
+ }
+ }
+
+ /// <summary>
+ /// Returns the digits after the point.
+ /// </summary>
+ private static int GetDigits(decimal value)
+ {
+ int result = 0;
+ value -= decimal.Truncate(value);
+ while (value != 0)
+ {
+ value *= 10;
+ value -= decimal.Truncate(value);
+ result++;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a continued fraction of a decimal value.
+ /// </summary>
+ private static int[] CreateContinuedFraction(decimal value)
+ {
+ int precision = GetDigits(value);
+ decimal epsilon = 0.0000001m;
+ List<int> list = new List<int>();
+ value = Math.Abs(value);
+
+ byte b = 0;
+
+ list.Add((int)value);
+ value -= ((int)value);
+
+ while (value != 0m)
+ {
+ if (++b == byte.MaxValue || value < epsilon)
+ {
+ break;
+ }
+ value = 1m / value;
+ if (Math.Abs((Math.Round(value, precision - 1) - value)) < epsilon)
+ {
+ value = Math.Round(value, precision - 1);
+ }
+ list.Add((int)value);
+ value -= ((int)value);
+ }
+ return list.ToArray();
+ }
+
+ /// <summary>
+ /// Creates a fraction from a continued fraction.
+ /// </summary>
+ private static void CreateFraction(int[] continuedFraction, out int numerator, out int denominator)
+ {
+ numerator = 1;
+ denominator = 0;
+ int temp;
+
+ for (int i = continuedFraction.Length - 1; i > -1; i--)
+ {
+ temp = numerator;
+ numerator = continuedFraction[i] * numerator + denominator;
+ denominator = temp;
+ }
+ }
+
+ /// <summary>
+ /// Tries 'brute force' to approximate <paramref name="value"/> with a fraction.
+ /// </summary>
+ private static void ApproximateFraction(decimal value, int maxDen, out int num, out int den)
+ {
+ num = 0;
+ den = 0;
+ decimal bestDifference = 1m;
+ decimal currentDifference = -1m;
+ int digits = GetDigits(value);
+
+ if (digits <= 9)
+ {
+ int mul = 1;
+ for (int i = 1; i <= digits; i++)
+ {
+ mul *= 10;
+ }
+ if (mul <= maxDen)
+ {
+ num = (int)(value * mul);
+ den = mul;
+ return;
+ }
+ }
+
+ for (int i = 1; i <= maxDen; i++)
+ {
+ int numerator = (int)Math.Floor(value * (decimal)i + 0.5m);
+ currentDifference = Math.Abs(value - (decimal)numerator / (decimal)i);
+ if (currentDifference < bestDifference)
+ {
+ num = numerator;
+ den = i;
+ bestDifference = currentDifference;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRational"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return ((IConvertible)this).ToDouble(null).ToString();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRational"/> structure
+ /// and is equivalent to this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRational"/> structure
+ /// equivalent to this <see cref="FIRational"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRational) && (this == ((FIRational)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRational"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Operators
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator +(FIRational r1)
+ {
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator -(FIRational r1)
+ {
+ r1.numerator *= -1;
+ return r1;
+ }
+
+ /// <summary>
+ /// Returns the reciprocal value of this instance.
+ /// </summary>
+ public static FIRational operator ~(FIRational r1)
+ {
+ int temp = r1.denominator;
+ r1.denominator = r1.numerator;
+ r1.numerator = temp;
+ r1.Normalize();
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator ++(FIRational r1)
+ {
+ checked
+ {
+ r1.numerator += r1.denominator;
+ }
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator --(FIRational r1)
+ {
+ checked
+ {
+ r1.numerator -= r1.denominator;
+ }
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator +(FIRational r1, FIRational r2)
+ {
+ long numerator = 0;
+ long denominator = Scm(r1.denominator, r2.denominator);
+ numerator = (r1.numerator * (denominator / r1.denominator)) + (r2.numerator * (denominator / r2.denominator));
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIRational((int)numerator, (int)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator -(FIRational r1, FIRational r2)
+ {
+ return r1 + (-r2);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator *(FIRational r1, FIRational r2)
+ {
+ long numerator = r1.numerator * r2.numerator;
+ long denominator = r1.denominator * r2.denominator;
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIRational((int)numerator, (int)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator /(FIRational r1, FIRational r2)
+ {
+ int temp = r2.denominator;
+ r2.denominator = r2.numerator;
+ r2.numerator = temp;
+ return r1 * r2;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator %(FIRational r1, FIRational r2)
+ {
+ r2.Normalize();
+ if (Math.Abs(r2.numerator) < r2.denominator)
+ return new FIRational(0, 0);
+ int div = (int)(r1 / r2);
+ return r1 - (r2 * div);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator ==(FIRational r1, FIRational r2)
+ {
+ r1.Normalize();
+ r2.Normalize();
+ return (r1.numerator == r2.numerator) && (r1.denominator == r2.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator !=(FIRational r1, FIRational r2)
+ {
+ return !(r1 == r2);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) > (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) < (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >=(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) >= (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <=(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) <= (r2.numerator * (denominator / r2.denominator));
+ }
+
+ #endregion
+
+ #region Conversions
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Boolean"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Boolean"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator bool(FIRational value)
+ {
+ return (value.numerator != 0);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Byte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator byte(FIRational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Char"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Char"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator char(FIRational value)
+ {
+ return (char)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Decimal"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Decimal"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator decimal(FIRational value)
+ {
+ return value.denominator == 0 ? 0m : (decimal)value.numerator / (decimal)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Double"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Double"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator double(FIRational value)
+ {
+ return value.denominator == 0 ? 0d : (double)value.numerator / (double)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator short(FIRational value)
+ {
+ return (short)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator int(FIRational value)
+ {
+ return (int)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator long(FIRational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Single"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Single"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator float(FIRational value)
+ {
+ return value.denominator == 0 ? 0f : (float)value.numerator / (float)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="SByte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="SByte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator sbyte(FIRational value)
+ {
+ return (sbyte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ushort(FIRational value)
+ {
+ return (ushort)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator uint(FIRational value)
+ {
+ return (uint)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ulong(FIRational value)
+ {
+ return (ulong)(double)value;
+ }
+
+ //
+
+ /// <summary>
+ /// Converts the value of a <see cref="Boolean"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Boolean"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(bool value)
+ {
+ return new FIRational(value ? 1 : 0, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(byte value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Char"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Char"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(char value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Decimal"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Decimal"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(decimal value)
+ {
+ return new FIRational(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Double"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Double"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(double value)
+ {
+ return new FIRational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int16"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(short value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int32"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(int value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int64"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(long value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="SByte"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="SByte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(sbyte value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Single"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Single"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(float value)
+ {
+ return new FIRational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt16"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(ushort value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(uint value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt64"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(ulong value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ #endregion
+
+ #region IConvertible Member
+
+ TypeCode IConvertible.GetTypeCode()
+ {
+ return TypeCode.Double;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return (bool)this;
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return (byte)this;
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return (char)this;
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return Convert.ToDateTime(((IConvertible)this).ToDouble(provider));
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return (short)this;
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return (int)this;
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return (long)this;
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return (sbyte)this;
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ string IConvertible.ToString(IFormatProvider provider)
+ {
+ return ToString(((double)this).ToString(), provider);
+ }
+
+ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+ {
+ return Convert.ChangeType(((IConvertible)this).ToDouble(provider), conversionType, provider);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return (ushort)this;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return (uint)this;
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return (ulong)this;
+ }
+
+ #endregion
+
+ #region IComparable Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRational"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRational))
+ {
+ throw new ArgumentException();
+ }
+ return CompareTo((FIRational)obj);
+ }
+
+ #endregion
+
+ #region IFormattable Member
+
+ /// <summary>
+ /// Formats the value of the current instance using the specified format.
+ /// </summary>
+ /// <param name="format">The String specifying the format to use.</param>
+ /// <param name="formatProvider">The IFormatProvider to use to format the value.</param>
+ /// <returns>A String containing the value of the current instance in the specified format.</returns>
+ public string ToString(string format, IFormatProvider formatProvider)
+ {
+ if (format == null)
+ {
+ format = "";
+ }
+ return String.Format(formatProvider, format, ((IConvertible)this).ToDouble(formatProvider));
+ }
+
+ #endregion
+
+ #region IEquatable<FIRational> Member
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRational"/> structure is equivalent to this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRational"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRational"/> structure
+ /// equivalent to this <see cref="FIRational"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRational other)
+ {
+ return (this == other);
+ }
+
+ #endregion
+
+ #region IComparable<FIRational> Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRational"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRational"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRational other)
+ {
+ FIRational difference = this - other;
+ difference.Normalize();
+ if (difference.numerator > 0) return 1;
+ if (difference.numerator < 0) return -1;
+ else return 0;
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FITAG.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FITAG.cs
new file mode 100644
index 0000000..e82a1aa
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FITAG.cs
@@ -0,0 +1,170 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: FITAG.cs,v 1.5 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FITAG</b> structure is a handle to a FreeImage metadata tag.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FITAG : IComparable, IComparable<FITAG>, IEquatable<FITAG>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FITAG Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FITAG"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FITAG"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FITAG"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FITAG"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FITAG left, FITAG right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FITAG"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FITAG"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FITAG"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FITAG"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FITAG left, FITAG right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FITAG"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FITAG"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FITAG"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FITAG"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FITAG) && (this == ((FITAG)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FITAG other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FITAG"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FITAG))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FITAG)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FITAG"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FITAG other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FIURational.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FIURational.cs
new file mode 100644
index 0000000..9c04983
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FIURational.cs
@@ -0,0 +1,1010 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.5 $
+// $Date: 2009/02/27 16:36:23 $
+// $Id: FIURational.cs,v 1.5 2009/02/27 16:36:23 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIURational</b> structure represents a fraction via two <see cref="UInt32"/>
+ /// instances which are interpreted as numerator and denominator.
+ /// </summary>
+ /// <remarks>
+ /// The structure tries to approximate the value of <see cref="FreeImageAPI.FIURational(decimal)"/>
+ /// when creating a new instance by using a better algorithm than FreeImage does.
+ /// <para/>
+ /// The structure implements the following operators:
+ /// +, ++, --, ==, != , >, >==, &lt;, &lt;== and ~ (which switches nominator and denomiator).
+ /// <para/>
+ /// The structure can be converted into all .NET standard types either implicit or
+ /// explicit.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
+ public struct FIURational : IConvertible, IComparable, IFormattable, IComparable<FIURational>, IEquatable<FIURational>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private uint numerator;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private uint denominator;
+
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FIURational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIURational MaxValue = new FIURational(UInt32.MaxValue, 1u);
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FIURational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIURational MinValue = new FIURational(0u, 1u);
+
+ /// <summary>
+ /// Represents the smallest positive <see cref="FIURational"/> value greater than zero. This field is constant.
+ /// </summary>
+ public static readonly FIURational Epsilon = new FIURational(1u, UInt32.MaxValue);
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="n">The numerator.</param>
+ /// <param name="d">The denominator.</param>
+ public FIURational(uint n, uint d)
+ {
+ numerator = n;
+ denominator = d;
+ Normalize();
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="tag">The tag to read the data from.</param>
+ public unsafe FIURational(FITAG tag)
+ {
+ switch (FreeImage.GetTagType(tag))
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_RATIONAL:
+ uint* pvalue = (uint*)FreeImage.GetTagValue(tag);
+ numerator = pvalue[0];
+ denominator = pvalue[1];
+ Normalize();
+ return;
+ default:
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ ///Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="value">The value to convert into a fraction.</param>
+ /// <exception cref="OverflowException">
+ /// <paramref name="value"/> cannot be converted into a fraction
+ /// represented by two unsigned integer values.</exception>
+ public FIURational(decimal value)
+ {
+ try
+ {
+ if (value < 0)
+ {
+ throw new OverflowException("value");
+ }
+ try
+ {
+ int[] contFract = CreateContinuedFraction(value);
+ CreateFraction(contFract, out numerator, out denominator);
+ Normalize();
+ }
+ catch
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ int maxDen = (Int32.MaxValue / (int)value) - 2;
+ maxDen = maxDen < 10000 ? maxDen : 10000;
+ ApproximateFraction(value, maxDen, out numerator, out denominator);
+ Normalize();
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ throw new OverflowException("Unable to convert value into a fraction");
+ }
+ }
+ Normalize();
+ }
+ catch (Exception ex)
+ {
+ throw new OverflowException("Unable to calculate fraction.", ex);
+ }
+ }
+
+ /// <summary>
+ /// The numerator of the fraction.
+ /// </summary>
+ public uint Numerator
+ {
+ get { return numerator; }
+ }
+
+ /// <summary>
+ /// The denominator of the fraction.
+ /// </summary>
+ public uint Denominator
+ {
+ get { return denominator; }
+ }
+
+ /// <summary>
+ /// Returns the truncated value of the fraction.
+ /// </summary>
+ /// <returns></returns>
+ public int Truncate()
+ {
+ return denominator > 0 ? (int)(numerator / denominator) : 0;
+ }
+
+ /// <summary>
+ /// Returns whether the fraction is representing an integer value.
+ /// </summary>
+ public bool IsInteger
+ {
+ get
+ {
+ return (denominator == 1 ||
+ (denominator != 0 && (numerator % denominator == 0)) ||
+ (denominator == 0 && numerator == 0));
+ }
+ }
+
+ /// <summary>
+ /// Calculated the greatest common divisor of 'a' and 'b'.
+ /// </summary>
+ private static ulong Gcd(ulong a, ulong b)
+ {
+ ulong r;
+ while (b > 0)
+ {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+ return a;
+ }
+
+ /// <summary>
+ /// Calculated the smallest common multiple of 'a' and 'b'.
+ /// </summary>
+ private static ulong Scm(uint n, uint m)
+ {
+ return (ulong)n * (ulong)m / Gcd(n, m);
+ }
+
+ /// <summary>
+ /// Normalizes the fraction.
+ /// </summary>
+ private void Normalize()
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ return;
+ }
+
+ if (numerator != 1 && denominator != 1)
+ {
+ uint common = (uint)Gcd(numerator, denominator);
+ if (common != 1 && common != 0)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Normalizes a fraction.
+ /// </summary>
+ private static void Normalize(ref ulong numerator, ref ulong denominator)
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ else if (numerator != 1 && denominator != 1)
+ {
+ ulong common = Gcd(numerator, denominator);
+ if (common != 1)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the digits after the point.
+ /// </summary>
+ private static int GetDigits(decimal value)
+ {
+ int result = 0;
+ value -= decimal.Truncate(value);
+ while (value != 0)
+ {
+ value *= 10;
+ value -= decimal.Truncate(value);
+ result++;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a continued fraction of a decimal value.
+ /// </summary>
+ private static int[] CreateContinuedFraction(decimal value)
+ {
+ int precision = GetDigits(value);
+ decimal epsilon = 0.0000001m;
+ List<int> list = new List<int>();
+ value = Math.Abs(value);
+
+ byte b = 0;
+
+ list.Add((int)value);
+ value -= ((int)value);
+
+ while (value != 0m)
+ {
+ if (++b == byte.MaxValue || value < epsilon)
+ {
+ break;
+ }
+ value = 1m / value;
+ if (Math.Abs((Math.Round(value, precision - 1) - value)) < epsilon)
+ {
+ value = Math.Round(value, precision - 1);
+ }
+ list.Add((int)value);
+ value -= ((int)value);
+ }
+ return list.ToArray();
+ }
+
+ /// <summary>
+ /// Creates a fraction from a continued fraction.
+ /// </summary>
+ private static void CreateFraction(int[] continuedFraction, out uint numerator, out uint denominator)
+ {
+ numerator = 1;
+ denominator = 0;
+ uint temp;
+
+ for (int i = continuedFraction.Length - 1; i > -1; i--)
+ {
+ temp = numerator;
+ numerator = (uint)(continuedFraction[i] * numerator + denominator);
+ denominator = temp;
+ }
+ }
+
+ /// <summary>
+ /// Tries 'brute force' to approximate <paramref name="value"/> with a fraction.
+ /// </summary>
+ private static void ApproximateFraction(decimal value, int maxDen, out uint num, out uint den)
+ {
+ num = 0;
+ den = 0;
+ decimal bestDifference = 1m;
+ decimal currentDifference = -1m;
+ int digits = GetDigits(value);
+
+ if (digits <= 9)
+ {
+ uint mul = 1;
+ for (int i = 1; i <= digits; i++)
+ {
+ mul *= 10;
+ }
+ if (mul <= maxDen)
+ {
+ num = (uint)(value * mul);
+ den = mul;
+ return;
+ }
+ }
+
+ for (uint u = 1; u <= maxDen; u++)
+ {
+ uint numerator = (uint)Math.Floor(value * (decimal)u + 0.5m);
+ currentDifference = Math.Abs(value - (decimal)numerator / (decimal)u);
+ if (currentDifference < bestDifference)
+ {
+ num = numerator;
+ den = u;
+ bestDifference = currentDifference;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIURational"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return ((IConvertible)this).ToDouble(null).ToString();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIURational"/> structure
+ /// and is equivalent to this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIURational"/> structure
+ /// equivalent to this <see cref="FIURational"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIURational) && (this == ((FIURational)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIURational"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Operators
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator +(FIURational value)
+ {
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the reciprocal value of this instance.
+ /// </summary>
+ public static FIURational operator ~(FIURational value)
+ {
+ uint temp = value.denominator;
+ value.denominator = value.numerator;
+ value.numerator = temp;
+ value.Normalize();
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator ++(FIURational value)
+ {
+ checked
+ {
+ value.numerator += value.denominator;
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator --(FIURational value)
+ {
+ checked
+ {
+ value.numerator -= value.denominator;
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator +(FIURational left, FIURational right)
+ {
+ ulong numerator = 0;
+ ulong denominator = Scm(left.denominator, right.denominator);
+ numerator = (left.numerator * (denominator / left.denominator)) +
+ (right.numerator * (denominator / right.denominator));
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIURational((uint)numerator, (uint)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator -(FIURational left, FIURational right)
+ {
+ checked
+ {
+ if (left.denominator != right.denominator)
+ {
+ uint denom = left.denominator;
+ left.numerator *= right.denominator;
+ left.denominator *= right.denominator;
+ right.numerator *= denom;
+ right.denominator *= denom;
+ }
+ left.numerator -= right.numerator;
+ left.Normalize();
+ return left;
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator *(FIURational left, FIURational r2)
+ {
+ ulong numerator = left.numerator * r2.numerator;
+ ulong denominator = left.denominator * r2.denominator;
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIURational((uint)numerator, (uint)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator /(FIURational left, FIURational right)
+ {
+ uint temp = right.denominator;
+ right.denominator = right.numerator;
+ right.numerator = temp;
+ return left * right;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator %(FIURational left, FIURational right)
+ {
+ right.Normalize();
+ if (Math.Abs(right.numerator) < right.denominator)
+ return new FIURational(0, 0);
+ int div = (int)(left / right);
+ return left - (right * div);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator ==(FIURational left, FIURational right)
+ {
+ left.Normalize();
+ right.Normalize();
+ return (left.numerator == right.numerator) && (left.denominator == right.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator !=(FIURational left, FIURational right)
+ {
+ left.Normalize();
+ right.Normalize();
+ return (left.numerator != right.numerator) || (left.denominator != right.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) >
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) <
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >=(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) >=
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <=(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) <=
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ #endregion
+
+ #region Conversions
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Boolean"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Boolean"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator bool(FIURational value)
+ {
+ return (value.numerator != 0);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Byte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator byte(FIURational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Char"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Char"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator char(FIURational value)
+ {
+ return (char)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Decimal"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Decimal"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator decimal(FIURational value)
+ {
+ return value.denominator == 0 ? 0m : (decimal)value.numerator / (decimal)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Double"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Double"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator double(FIURational value)
+ {
+ return value.denominator == 0 ? 0d : (double)value.numerator / (double)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator short(FIURational value)
+ {
+ return (short)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator int(FIURational value)
+ {
+ return (int)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator long(FIURational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Single"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Single"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator float(FIURational value)
+ {
+ return value.denominator == 0 ? 0f : (float)value.numerator / (float)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="SByte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="SByte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator sbyte(FIURational value)
+ {
+ return (sbyte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ushort(FIURational value)
+ {
+ return (ushort)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator uint(FIURational value)
+ {
+ return (uint)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ulong(FIURational value)
+ {
+ return (ulong)(double)value;
+ }
+
+ //
+
+ /// <summary>
+ /// Converts the value of a <see cref="Boolean"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Boolean"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(bool value)
+ {
+ return new FIURational(value ? 1u : 0u, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(byte value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Char"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Char"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(char value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Decimal"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Decimal"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(decimal value)
+ {
+ return new FIURational(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Double"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Double"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(double value)
+ {
+ return new FIURational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int16"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(short value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int32"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(int value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int64"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(long value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="SByte"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="SByte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(sbyte value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Single"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Single"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(float value)
+ {
+ return new FIURational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt16"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(ushort value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(uint value)
+ {
+ return new FIURational(value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt64"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(ulong value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ #endregion
+
+ #region IConvertible Member
+
+ TypeCode IConvertible.GetTypeCode()
+ {
+ return TypeCode.Double;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return (bool)this;
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return (byte)this;
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return (char)this;
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return Convert.ToDateTime(((IConvertible)this).ToDouble(provider));
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return (short)this;
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return (int)this;
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return (long)this;
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return (sbyte)this;
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ string IConvertible.ToString(IFormatProvider provider)
+ {
+ return ToString(((double)this).ToString(), provider);
+ }
+
+ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+ {
+ return Convert.ChangeType(((IConvertible)this).ToDouble(provider), conversionType, provider);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return (ushort)this;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return (uint)this;
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return (ulong)this;
+ }
+
+ #endregion
+
+ #region IComparable Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIURational"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIURational))
+ {
+ throw new ArgumentException();
+ }
+ return CompareTo((FIURational)obj);
+ }
+
+ #endregion
+
+ #region IFormattable Member
+
+ /// <summary>
+ /// Formats the value of the current instance using the specified format.
+ /// </summary>
+ /// <param name="format">The String specifying the format to use.</param>
+ /// <param name="formatProvider">The IFormatProvider to use to format the value.</param>
+ /// <returns>A String containing the value of the current instance in the specified format.</returns>
+ public string ToString(string format, IFormatProvider formatProvider)
+ {
+ if (format == null)
+ {
+ format = "";
+ }
+ return String.Format(formatProvider, format, ((IConvertible)this).ToDouble(formatProvider));
+ }
+
+ #endregion
+
+ #region IEquatable<FIURational> Member
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIURational"/> structure is equivalent to this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIURational"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIURational"/> structure
+ /// equivalent to this <see cref="FIURational"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIURational other)
+ {
+ return (this == other);
+ }
+
+ #endregion
+
+ #region IComparable<FIURational> Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIURational"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIURational"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIURational other)
+ {
+ FIURational difference = this - other;
+ difference.Normalize();
+ if (difference.numerator > 0) return 1;
+ if (difference.numerator < 0) return -1;
+ else return 0;
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/FreeImageIO.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/FreeImageIO.cs
new file mode 100644
index 0000000..d42575e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/FreeImageIO.cs
@@ -0,0 +1,66 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2008/06/17 13:49:23 $
+// $Id: FreeImageIO.cs,v 1.3 2008/06/17 13:49:23 cklein05 Exp $
+// ==========================================================
+
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Structure for implementing access to custom handles.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FreeImageIO
+ {
+ /// <summary>
+ /// Delegate to the C++ function <b>fread</b>.
+ /// </summary>
+ public ReadProc readProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fwrite</b>.
+ /// </summary>
+ public WriteProc writeProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fseek</b>.
+ /// </summary>
+ public SeekProc seekProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>ftell</b>.
+ /// </summary>
+ public TellProc tellProc;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/Plugin.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/Plugin.cs
new file mode 100644
index 0000000..8de1666
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/Plugin.cs
@@ -0,0 +1,132 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2008/06/17 13:48:22 $
+// $Id: Plugin.cs,v 1.3 2008/06/17 13:48:22 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Runtime.InteropServices;
+using FreeImageAPI.Plugins;
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// The structure contains functionpointers that make up a FreeImage plugin.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct Plugin
+ {
+ /// <summary>
+ /// Delegate to a function that returns a string which describes
+ /// the plugins format.
+ /// </summary>
+ public FormatProc formatProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// a more detailed description.
+ /// </summary>
+ public DescriptionProc descriptionProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a comma seperated list
+ /// of file extensions the plugin can read or write.
+ /// </summary>
+ public ExtensionListProc extensionListProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a regular expression that
+ /// can be used to idientify whether a file can be handled by the plugin.
+ /// </summary>
+ public RegExprProc regExprProc;
+
+ /// <summary>
+ /// Delegate to a function that opens a file.
+ /// </summary>
+ public OpenProc openProc;
+
+ /// <summary>
+ /// Delegate to a function that closes a previosly opened file.
+ /// </summary>
+ public CloseProc closeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns the number of pages of a multipage
+ /// bitmap if the plugin is capable of handling multipage bitmaps.
+ /// </summary>
+ public PageCountProc pageCountProc;
+
+ /// <summary>
+ /// UNKNOWN
+ /// </summary>
+ public PageCapabilityProc pageCapabilityProc;
+
+ /// <summary>
+ /// Delegate to a function that loads and decodes a bitmap into memory.
+ /// </summary>
+ public LoadProc loadProc;
+
+ /// <summary>
+ /// Delegate to a function that saves a bitmap.
+ /// </summary>
+ public SaveProc saveProc;
+
+ /// <summary>
+ /// Delegate to a function that determines whether the source is a valid image.
+ /// </summary>
+ public ValidateProc validateProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// the plugin's mime type.
+ /// </summary>
+ public MimeProc mimeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified color depth.
+ /// </summary>
+ public SupportsExportBPPProc supportsExportBPPProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified image type.
+ /// </summary>
+ public SupportsExportTypeProc supportsExportTypeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle
+ /// ICC-Profiles.
+ /// </summary>
+ public SupportsICCProfilesProc supportsICCProfilesProc;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/RGBQUAD.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/RGBQUAD.cs
new file mode 100644
index 0000000..a9f2287
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/RGBQUAD.cs
@@ -0,0 +1,342 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.4 $
+// $Date: 2009/02/20 07:40:53 $
+// $Id: RGBQUAD.cs,v 1.4 2009/02/20 07:40:53 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>RGBQUAD</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 8 bits and so, takes values in the range from 0 to 255.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>RGBQUAD</b> structure provides access to an underlying Win32 <b>RGBQUAD</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the rgbReserved, rgbRed, rgbGreen or rgbBlue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>RGBQUAD</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>RGBQUAD</b> structure and my be used in all situations which require
+ /// an <b>RGBQUAD</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component rgbReserved, rgbRed, rgbGreen or rgbBlue of <b>RGBQUAD</b>
+ /// is translated into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an one-to-one manner and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to RGBQUAD</b>
+ /// </para>
+ /// <c>RGBQUAD.component = Color.component</c>
+ /// <para>
+ /// <b>Conversion from RGBQUAD to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = RGBQUAD.component</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.RGBQUAD.Color"/>
+ /// property or the <see cref="FreeImageAPI.RGBQUAD(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>RGBQUAD</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// RGBQUAD rgbq;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// rgbq = new RGBQUAD(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// rgbq = Color.DarkSeaGreen;
+ /// // Convert the RGBQUAD instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = rgbq;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = rgbq.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Explicit)]
+ public struct RGBQUAD : IComparable, IComparable<RGBQUAD>, IEquatable<RGBQUAD>
+ {
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ [FieldOffset(0)]
+ public byte rgbBlue;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ [FieldOffset(1)]
+ public byte rgbGreen;
+
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ [FieldOffset(2)]
+ public byte rgbRed;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ [FieldOffset(3)]
+ public byte rgbReserved;
+
+ /// <summary>
+ /// The color's value.
+ /// </summary>
+ [FieldOffset(0)]
+ public uint uintValue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public RGBQUAD(Color color)
+ {
+ uintValue = 0u;
+ rgbBlue = color.B;
+ rgbGreen = color.G;
+ rgbRed = color.R;
+ rgbReserved = color.A;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBQUAD"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBQUAD"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="RGBQUAD"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBQUAD"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(RGBQUAD left, RGBQUAD right)
+ {
+ return (left.uintValue == right.uintValue);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBQUAD"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBQUAD"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="RGBQUAD"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBQUAD"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(RGBQUAD left, RGBQUAD right)
+ {
+ return (left.uintValue != right.uintValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBQUAD(Color value)
+ {
+ return new RGBQUAD(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBQUAD"/> structure to a Color structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBQUAD"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(RGBQUAD value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBQUAD(uint value)
+ {
+ RGBQUAD result = new RGBQUAD();
+ result.uintValue = value;
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBQUAD"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBQUAD"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator uint(RGBQUAD value)
+ {
+ return value.uintValue;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ rgbReserved,
+ rgbRed,
+ rgbGreen,
+ rgbBlue);
+ }
+ set
+ {
+ rgbRed = value.R;
+ rgbGreen = value.G;
+ rgbBlue = value.B;
+ rgbReserved = value.A;
+ }
+ }
+
+ /// <summary>
+ /// Converts an array of <see cref="Color"/> into an array of
+ /// <see cref="RGBQUAD"/>.
+ /// </summary>
+ /// <param name="array">The array to convert.</param>
+ /// <returns>An array of <see cref="RGBQUAD"/>.</returns>
+ public static RGBQUAD[] ToRGBQUAD(Color[] array)
+ {
+ if (array == null)
+ return null;
+
+ RGBQUAD[] result = new RGBQUAD[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ result[i] = array[i];
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts an array of <see cref="RGBQUAD"/> into an array of
+ /// <see cref="Color"/>.
+ /// </summary>
+ /// <param name="array">The array to convert.</param>
+ /// <returns>An array of <see cref="RGBQUAD"/>.</returns>
+ public static Color[] ToColor(RGBQUAD[] array)
+ {
+ if (array == null)
+ return null;
+
+ Color[] result = new Color[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ result[i] = array[i].Color;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="RGBQUAD"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is RGBQUAD))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((RGBQUAD)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="RGBQUAD"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBQUAD"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(RGBQUAD other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="RGBQUAD"/> structure
+ /// and is equivalent to this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBQUAD"/> structure
+ /// equivalent to this <see cref="RGBQUAD"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is RGBQUAD) && (this == ((RGBQUAD)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="RGBQUAD"/> structure is equivalent to this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBQUAD"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBQUAD"/> structure
+ /// equivalent to this <see cref="RGBQUAD"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(RGBQUAD other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="RGBQUAD"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="RGBQUAD"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/RGBTRIPLE.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/RGBTRIPLE.cs
new file mode 100644
index 0000000..01c5a9d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/RGBTRIPLE.cs
@@ -0,0 +1,295 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.3 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: RGBTRIPLE.cs,v 1.3 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>RGBTRIPLE</b> structure describes a color consisting of relative
+ /// intensities of red, green and blue value. Each single color component
+ /// consumes 8 bits and so, takes values in the range from 0 to 255.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>RGBTRIPLE</b> structure provides access to an underlying Win32 <b>RGBTRIPLE</b>
+ /// structure. To determine the red, green or blue component of a color, use the
+ /// rgbtRed, rgbtGreen or rgbtBlue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>RGBTRIPLE</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>RGBTRIPLE</b> structure and my be used in all situations which require
+ /// an <b>RGBTRIPLE</b> type.
+ /// </para>
+ /// <para>
+ /// Each of the color components rgbtRed, rgbtGreen or rgbtBlue of <b>RGBTRIPLE</b> is
+ /// translated into it's corresponding color component R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an one-to-one manner and vice versa.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>RGBTRIPLE</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>RGBTRIPLE</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to RGBTRIPLE</b>
+ /// </para>
+ /// <c>RGBTRIPLE.component = Color.component</c>
+ /// <para>
+ /// <b>Conversion from RGBTRIPLE to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = RGBTRIPLE.component</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.RGBTRIPLE.Color"/>
+ /// property or the <see cref="FreeImageAPI.RGBTRIPLE(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>RGBTRIPLE</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// RGBTRIPLE rgbt;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// rgbt = new RGBTRIPLE(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// rgbt = Color.DarkSeaGreen;
+ /// // Convert the RGBTRIPLE instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = rgbt;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = rgbt.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct RGBTRIPLE : IComparable, IComparable<RGBTRIPLE>, IEquatable<RGBTRIPLE>
+ {
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public byte rgbtBlue;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public byte rgbtGreen;
+
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public byte rgbtRed;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public RGBTRIPLE(Color color)
+ {
+ rgbtBlue = color.B;
+ rgbtGreen = color.G;
+ rgbtRed = color.R;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBTRIPLE"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBTRIPLE"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="RGBTRIPLE"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBTRIPLE"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(RGBTRIPLE left, RGBTRIPLE right)
+ {
+ return
+ left.rgbtBlue == right.rgbtBlue &&
+ left.rgbtGreen == right.rgbtGreen &&
+ left.rgbtRed == right.rgbtRed;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBTRIPLE"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBTRIPLE"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="RGBTRIPLE"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBTRIPLE"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(RGBTRIPLE left, RGBTRIPLE right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBTRIPLE(Color value)
+ {
+ return new RGBTRIPLE(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBTRIPLE"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBTRIPLE"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(RGBTRIPLE value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBTRIPLE(uint value)
+ {
+ RGBTRIPLE result = new RGBTRIPLE();
+ result.rgbtBlue = (byte)(value & 0xFF);
+ result.rgbtGreen = (byte)((value >> 8) & 0xFF);
+ result.rgbtRed = (byte)((value >> 16) & 0xFF);
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBTRIPLE"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBTRIPLE"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator uint(RGBTRIPLE value)
+ {
+ return (uint)((value.rgbtRed << 16) | (value.rgbtGreen << 8) | (value.rgbtBlue));
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ rgbtRed,
+ rgbtGreen,
+ rgbtBlue);
+ }
+ set
+ {
+ rgbtBlue = value.B;
+ rgbtGreen = value.G;
+ rgbtRed = value.R;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="RGBTRIPLE"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is RGBTRIPLE))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((RGBTRIPLE)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="RGBTRIPLE"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBTRIPLE"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(RGBTRIPLE other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="RGBTRIPLE"/> structure
+ /// and is equivalent to this <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBTRIPLE"/> structure
+ /// equivalent to this <see cref="RGBTRIPLE"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is RGBTRIPLE) && (this == ((RGBTRIPLE)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="RGBTRIPLE"/> structure is equivalent to this
+ /// <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBTRIPLE"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBTRIPLE"/> structure
+ /// equivalent to this <see cref="RGBTRIPLE"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(RGBTRIPLE other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="RGBTRIPLE"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="RGBTRIPLE"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/Structs/fi_handle.cs b/Wrapper/FreeImage.NET/cs/Library/Structs/fi_handle.cs
new file mode 100644
index 0000000..d2d1188
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/Structs/fi_handle.cs
@@ -0,0 +1,256 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// CVS
+// $Revision: 1.7 $
+// $Date: 2009/02/20 07:41:08 $
+// $Id: fi_handle.cs,v 1.7 2009/02/20 07:41:08 cklein05 Exp $
+// ==========================================================
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Wrapper for a custom handle.
+ /// </summary>
+ /// <remarks>
+ /// The <b>fi_handle</b> of FreeImage in C++ is a simple pointer, but in .NET
+ /// it's not that simple. This wrapper uses fi_handle in two different ways.
+ ///
+ /// We implement a new plugin and FreeImage gives us a handle (pointer) that
+ /// we can simply pass through to the given functions in a 'FreeImageIO'
+ /// structure.
+ /// But when we want to use LoadFromhandle or SaveToHandle we need
+ /// a fi_handle (that we receive again in our own functions).
+ /// This handle is for example a stream (see LoadFromStream / SaveToStream)
+ /// that we want to work with. To know which stream a read/write is meant for
+ /// we could use a hash value that the wrapper itself handles or we can
+ /// go the unmanaged way of using a handle.
+ /// Therefor we use a <see cref="GCHandle"/> to receive a unique pointer that we can
+ /// convert back into a .NET object.
+ /// When the <b>fi_handle</b> instance is no longer needed the instance must be disposed
+ /// by the creater manually! It is recommended to use the <c>using</c> statement to
+ /// be sure the instance is always disposed:
+ ///
+ /// <code>
+ /// using (fi_handle handle = new fi_handle(object))
+ /// {
+ /// callSomeFunctions(handle);
+ /// }
+ /// </code>
+ ///
+ /// What does that mean?
+ /// If we get a <b>fi_handle</b> from unmanaged code we get a pointer to unmanaged
+ /// memory that we do not have to care about, and just pass ist back to FreeImage.
+ /// If we have to create a handle our own we use the standard constructur
+ /// that fills the <see cref="IntPtr"/> with an pointer that represents the given object.
+ /// With calling <see cref="GetObject"/> the <see cref="IntPtr"/> is used to retrieve the original
+ /// object we passed through the constructor.
+ ///
+ /// This way we can implement a <b>fi_handle</b> that works with managed an unmanaged
+ /// code.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct fi_handle : IComparable, IComparable<fi_handle>, IEquatable<fi_handle>, IDisposable
+ {
+ /// <summary>
+ /// The handle to wrap.
+ /// </summary>
+ public IntPtr handle;
+
+ /// <summary>
+ /// Initializes a new instance wrapping a managed object.
+ /// </summary>
+ /// <param name="obj">The object to wrap.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="obj"/> is null.</exception>
+ public fi_handle(object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException("obj");
+ }
+ GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Normal);
+ handle = GCHandle.ToIntPtr(gch);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="fi_handle"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="fi_handle"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="fi_handle"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="fi_handle"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(fi_handle left, fi_handle right)
+ {
+ return (left.handle == right.handle);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="fi_handle"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="fi_handle"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="fi_handle"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="fi_handle"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(fi_handle left, fi_handle right)
+ {
+ return (left.handle != right.handle);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer.
+ /// </summary>
+ public bool IsNull
+ {
+ get
+ {
+ return (handle == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Returns the object assigned to the handle in case this instance
+ /// was created by managed code.
+ /// </summary>
+ /// <returns><see cref="Object"/> assigned to this handle or null on failure.</returns>
+ internal object GetObject()
+ {
+ object result = null;
+ if (handle != IntPtr.Zero)
+ {
+ try
+ {
+ result = GCHandle.FromIntPtr(handle).Target;
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="fi_handle"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return handle.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="fi_handle"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="fi_handle"/>.</returns>
+ public override int GetHashCode()
+ {
+ return handle.GetHashCode();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="fi_handle"/> structure
+ /// and is equivalent to this <see cref="fi_handle"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="fi_handle"/> structure
+ /// equivalent to this <see cref="fi_handle"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is fi_handle) && (this == ((fi_handle)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns>True if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(fi_handle other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="fi_handle"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is fi_handle))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((fi_handle)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="fi_handle"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="fi_handle"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(fi_handle other)
+ {
+ return handle.ToInt64().CompareTo(other.handle.ToInt64());
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ public void Dispose()
+ {
+ if (this.handle != IntPtr.Zero)
+ {
+ try
+ {
+ GCHandle.FromIntPtr(handle).Free();
+ }
+ catch
+ {
+ }
+ finally
+ {
+ this.handle = IntPtr.Zero;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Library/build.bat b/Wrapper/FreeImage.NET/cs/Library/build.bat
new file mode 100755
index 0000000..8c9f4db
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Library/build.bat
@@ -0,0 +1,7 @@
+@ECHO OFF
+IF NOT EXIST bin MD bin
+IF NOT EXIST bin\Release MD bin\Release
+csc.exe /out:bin\Release\FreeImageNET.dll /target:library /doc:bin\Release\FreeImageNET.XML /debug- /o /nowarn:419 /unsafe+ /filealign:512 /recurse:*.cs
+IF EXIST ..\Bin copy bin\Release\FreeImageNET.dll ..\Bin > NUL
+IF EXIST ..\Bin copy bin\Release\FreeImageNET.XML ..\Bin > NUL
+pause \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs
new file mode 100644
index 0000000..2e53888
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Program.cs
@@ -0,0 +1,179 @@
+using System;
+using System.IO;
+using FreeImageAPI;
+using System.Collections.Generic;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Runtime.InteropServices;
+
+namespace Sample01
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Check if FreeImage.dll is available (can be in %path%).
+ if (!FreeImage.IsAvailable())
+ {
+ Console.WriteLine("FreeImage.dll seems to be missing. Aborting.");
+ return;
+ }
+
+ Sample sample = new Sample();
+ // This example shows the basic loading and saving operations offered by FreeImage.
+ sample.Example01();
+
+ // This example shows a more comfortable way offered by the .NET Wrapper.
+ sample.Example02();
+
+ // This example shows the FreeImage-Errormessage-Callback
+ sample.Example03();
+ }
+ }
+
+ public class Sample
+ {
+ const string fileName = @"Sample.jpg";
+ const string outFileName = @"Sample.tif";
+ FIBITMAP dib = new FIBITMAP();
+ string message = null;
+
+ public void Example01()
+ {
+ if (!File.Exists(fileName))
+ {
+ Console.WriteLine(fileName + " does not exist. Aborting.");
+ return;
+ }
+
+ // Try to unload the bitmap handle (in case it is not null).
+ // Always assert that a handle (like dib) is unloaded before it is reused, because
+ // on unmanaged side there is no garbage collector that will clean up unreferenced
+ // objects.
+ // The following code will produce a memory leak (in case the bitmap is loaded
+ // successfully) because the handle to the first bitmap is lost:
+ // dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, fileName, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+ // dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, fileName, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+ if (!dib.IsNull)
+ FreeImage.Unload(dib);
+
+ // Loading a sample bitmap. In this case it's a .jpg file. 'Load' requires the file
+ // format or the loading process will fail. An additional flag (the default value is
+ // 'DEFAULT') can be set to enable special loading options.
+ dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, fileName, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+
+ // Check if the handle is null which means the bitmap could not be loaded.
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Loading bitmap failed. Aborting.");
+ // Check whether there was an error message.
+ return;
+ }
+
+ // Try flipping the bitmap.
+ if (!FreeImage.FlipHorizontal(dib))
+ {
+ Console.WriteLine("Unable to flip bitmap.");
+ // Check whether there was an error message.
+ }
+
+ // Store the bitmap back to disk. Again the desired format is needed. In this case the format is 'TIFF'.
+ // An output filename has to be chosen (which will be overwritten without a warning).
+ // A flag can be provided to enable pluginfunctions (compression is this case).
+ FreeImage.Save(FREE_IMAGE_FORMAT.FIF_TIFF, dib, outFileName, FREE_IMAGE_SAVE_FLAGS.TIFF_DEFLATE);
+
+ // The bitmap was saved to disk but is still allocated in memory, so the handle has to be freed.
+ if (!dib.IsNull)
+ FreeImage.Unload(dib);
+
+ // Make sure to set the handle to null so that it is clear that the handle is not pointing to a bitmap.
+ dib.SetNull();
+ }
+
+ public void Example02()
+ {
+ // 'UnloadEx' is a comfortable way of unloading a bitmap. The coder can call 'UnloadEx' even
+ // when the handle is pointing to null (in this case nothing will happen). In case the handle
+ // is valid (valid means that it is NOT pointing to null) the bitmap will be unloaded and the
+ // handle will be set to null manually.
+ FreeImage.UnloadEx(ref dib);
+
+ // 'LoadEx' is a comfortable way of loading a bitmap. 'LoadEx' tries to find out the format of
+ // the file and will use this to load it. It will use DEFAULT loading values.
+ dib = FreeImage.LoadEx(fileName);
+
+ // Check if the handle is null which means the bitmap could not be loaded.
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Loading bitmap failed. Aborting.");
+ return;
+ }
+
+ // 'SaveEx' (like 'LoadEx') will try to save the bitmap with default values.
+ // Before saving the bitmap, 'SaveEx' checks whether the extension is valid for the file type
+ // and if the plugin can use the colordepth of the bitmap. If not it will automatically convert
+ // the bitmap into the next best colordepth and save it.
+ if (!FreeImage.SaveEx(ref dib, @"Sample.gif", false))
+ {
+ Console.WriteLine("Saving bitmap failed.");
+ }
+
+ // The handle is still valid.
+ if (!FreeImage.SaveEx(
+ ref dib,
+ @"Sample", // No extension was selected so let 'SaveEx' decide.
+ FREE_IMAGE_FORMAT.FIF_PNG, // A format is needed this time.
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT, // PNG has no options so use default.
+ FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP, // 4bpp as result color depth.
+ true)) // We're done so unload
+ {
+ // SaveEx will not unload the bitmap in case saving failed.
+ // This way possible operations done to the bitmaps aren't lost.
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ public void Example03()
+ {
+ // Safely unload to prevent memory leak.
+ FreeImage.UnloadEx(ref dib);
+
+ // Load the example bitmap.
+ dib = FreeImage.LoadEx(fileName);
+
+ // Check whether loading succeeded.
+ if (dib.IsNull)
+ {
+ return;
+ }
+
+ // Add this class to the callback event.
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+
+ // Try to save the bitmap as a gif
+ if (!FreeImage.Save(FREE_IMAGE_FORMAT.FIF_GIF, dib, @"Sample_fail.gif", FREE_IMAGE_SAVE_FLAGS.DEFAULT))
+ {
+ // Saving failed
+ // Check whether there was an error callback
+ if (message != null)
+ {
+ // Print the message and delete it.
+ Console.WriteLine("Error message recieved: {0}", message);
+ message = null;
+ }
+ }
+
+ // Unload bitmap.
+ FreeImage.UnloadEx(ref dib);
+
+ // Remove this class from the callback event.
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ this.message = message;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5323808
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("ac0569fe-c021-4f40-bfe9-275baf0fd21a")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample 01 - Loading and saving.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample 01 - Loading and saving.csproj
new file mode 100644
index 0000000..4b65856
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample 01 - Loading and saving.csproj
@@ -0,0 +1,105 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{0D294AB6-FAD4-4364-AAB6-43C1796116A9}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample01</RootNamespace>
+ <AssemblyName>Sample01</AssemblyName>
+ <StartupObject>
+ </StartupObject>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Sample.jpg">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample.jpg b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample.jpg
new file mode 100644
index 0000000..b537c00
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 01 - Loading and saving/Sample.jpg
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Program.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Program.cs
new file mode 100644
index 0000000..dccc2d8
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Program.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+using FreeImageAPI;
+
+namespace Sample02
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Check if FreeImage.dll is available (can be in %path%).
+ if (!FreeImage.IsAvailable())
+ {
+ Console.WriteLine("FreeImage.dll seems to be missing. Aborting.");
+ return;
+ }
+
+ Sample sample = new Sample();
+ sample.Example();
+ }
+ }
+
+ public class Sample
+ {
+ const string fileName = @"multipaged.tif";
+ FIMULTIBITMAP dib = new FIMULTIBITMAP();
+ Random rand = new Random();
+
+ public void Example()
+ {
+ if (!File.Exists(fileName))
+ {
+ Console.WriteLine("File not found. Aborting.");
+ return;
+ }
+
+ // Load the multipaged bitmap.
+ // 'OpenMultiBitmapEx' tries to find the correct file format, loads the bitmap
+ // with default options, with write support and does not use caching.
+ dib = FreeImage.OpenMultiBitmapEx(fileName);
+
+ // Check whether loading succeeded.
+ if (dib.IsNull)
+ {
+ Console.WriteLine("File could not be loaded. Aborting.");
+ return;
+ }
+
+ // Get the number of bitmaps the multipaged bitmap contains.
+ int count = FreeImage.GetPageCount(dib);
+
+ // Multipaged bitmaps consist of multiple single FIBITMAPs
+ FIBITMAP page = new FIBITMAP();
+
+ // There are bitmaps we can work with.
+ if (count > 0)
+ {
+ // Lock a random bitmap to work with.
+ page = FreeImage.LockPage(dib, rand.Next(0, count));
+ }
+
+ // Check whether locking succeeded.
+ if (page.IsNull)
+ {
+ // Locking failed. Unload the bitmap and return.
+ FreeImage.CloseMultiBitmapEx(ref dib);
+ return;
+ }
+
+ // Get a list of locked pages. This can be usefull to check whether a page has already been locked.
+ int[] lockedPages = FreeImage.GetLockedPages(dib);
+
+ // Lets modify the page.
+ if (FreeImage.AdjustGamma(page, 2d))
+ {
+ Console.WriteLine("Successfully changed gamma of page {0}.", lockedPages[0]);
+ }
+ else
+ {
+ Console.WriteLine("Failed to adjust gamma ...");
+ }
+
+ // Print out the list of locked pages
+ foreach (int i in lockedPages)
+ Console.WriteLine("Page {0} is locked.", i);
+
+ // Use 'UnlockPage' instead of 'Unload' to free the page. Set the third parameter to 'true'
+ // so that FreeImage can store the changed page within the multipaged bitmap.
+ FreeImage.UnlockPage(dib, page, true);
+
+ // Retieve the list again to see whether unlocking succeeded.
+ lockedPages = FreeImage.GetLockedPages(dib);
+
+ // No output should be produced here.
+ foreach (int i in lockedPages)
+ Console.WriteLine("Page {0} is still locked.", i);
+
+ // If there are more than one page we can swap them
+ if (count > 1)
+ {
+ if (!FreeImage.MovePage(dib, 1, 0))
+ {
+ Console.WriteLine("Swapping pages failed.");
+ }
+ }
+
+ if (count > 2)
+ {
+ // Lock page 2
+ page = FreeImage.LockPage(dib, 2);
+ if (!page.IsNull)
+ {
+ // Clone the page for later appending
+ FIBITMAP temp = FreeImage.Clone(page);
+
+ // Unlock the page again
+ FreeImage.UnlockPage(dib, page, false);
+
+ // Delete the page form the multipaged bitmap
+ FreeImage.DeletePage(dib, 2);
+
+ // Append the clone again
+ FreeImage.AppendPage(dib, temp);
+
+ // Check whether the number of pages is still the same
+ Console.WriteLine("Pages before: {0}. Pages after: {1}", count, FreeImage.GetPageCount(dib));
+
+ // Unload clone to prevent memory leak
+ FreeImage.UnloadEx(ref temp);
+ }
+ }
+
+ // We are done and close the multipaged bitmap.
+ if (!FreeImage.CloseMultiBitmapEx(ref dib))
+ {
+ Console.WriteLine("Closing bitmap failed!");
+ }
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..6ada91e
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("35960522-c01a-40d2-a86b-37b9839b131c")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Sample 02 - Multipaged bitmaps.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Sample 02 - Multipaged bitmaps.csproj
new file mode 100644
index 0000000..2a8c92b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/Sample 02 - Multipaged bitmaps.csproj
@@ -0,0 +1,97 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{AF8B72BD-1A8B-4E6B-A0F1-0BD57497777B}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample02</RootNamespace>
+ <AssemblyName>Sample02</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="multipaged.tif">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/multipaged.tif b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/multipaged.tif
new file mode 100644
index 0000000..886a7c9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 02 - Multipaged bitmaps/multipaged.tif
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Program.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Program.cs
new file mode 100644
index 0000000..b7e9524
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Program.cs
@@ -0,0 +1,74 @@
+using System;
+using System.IO;
+using FreeImageAPI;
+
+namespace Sample03
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Check if FreeImage.dll is available (can be in %path%).
+ if (!FreeImage.IsAvailable())
+ {
+ Console.WriteLine("FreeImage.dll seems to be missing. Aborting.");
+ return;
+ }
+
+ // Add this class to the message event
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+
+ Sample sample = new Sample();
+ sample.Example();
+
+ // Remove this class from the message event
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ static void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ Console.WriteLine("Error for {0}: {1}", fif.ToString(), message);
+ }
+ }
+
+ public class Sample
+ {
+ FIBITMAP dib = new FIBITMAP();
+
+ public void Example()
+ {
+ // Allocating a new bitmap with 99x99 pixels, 16-bit color depth and an allocation of 5 bits for each color.
+ dib = FreeImage.Allocate(99, 99, 16, FreeImage.FI16_555_RED_MASK, FreeImage.FI16_555_GREEN_MASK, FreeImage.FI16_555_BLUE_MASK);
+
+ // Saving bitmap.
+ if (!FreeImage.SaveEx(ref dib, "example01.bmp", true))
+ {
+ Console.WriteLine("Saving 'example.bmp' failed.");
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ // Allocation a new bitmap with 71x33 pixels, 4-bit color depth. Bitmaps below 16-bit have paletts.
+ // Each pixel references an index within the palette wich contains the true color.
+ // Therefor no bit-masks are needed and can be set to 0.
+ dib = FreeImage.Allocate(71, 33, 4, 0, 0, 0);
+
+ // Saving bitmap.
+ if (!FreeImage.SaveEx(ref dib, "example02.tif", true))
+ {
+ Console.WriteLine("Saving 'example02.tif' failed.");
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ // Allocation a new bitmap. This time 'AllocateT' is used because 'Allocate' can only create standard bitmaps.
+ // In this case a RGBF bitmap is created. Red, green and blue are represented by a float-value so no bit-masks are needed.
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_RGBF, 50, 75, 9, 0, 0, 0);
+
+ // Saving bitmap.
+ if (!FreeImage.SaveEx(ref dib, "example03.hdr", true))
+ {
+ Console.WriteLine("Saving 'example03.hdr' failed.");
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..f60e31d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("7139f1dc-3312-4c76-aeb3-891f869409b3")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Sample 03 - Allocating.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Sample 03 - Allocating.csproj
new file mode 100644
index 0000000..a404277
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 03 - Allocating/Sample 03 - Allocating.csproj
@@ -0,0 +1,91 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A7E452A1-1A43-47C4-8BF3-DA28E1402FB9}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample03</RootNamespace>
+ <AssemblyName>Sample03</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.Designer.cs
new file mode 100644
index 0000000..cb3836a
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.Designer.cs
@@ -0,0 +1,205 @@
+namespace Sample04
+{
+ partial class MainForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.ofd = new System.Windows.Forms.OpenFileDialog();
+ this.bOpenFile = new System.Windows.Forms.Button();
+ this.lWidth = new System.Windows.Forms.Label();
+ this.lHeight = new System.Windows.Forms.Label();
+ this.lBPP = new System.Windows.Forms.Label();
+ this.lRedMask = new System.Windows.Forms.Label();
+ this.lGreenMask = new System.Windows.Forms.Label();
+ this.lBlueMask = new System.Windows.Forms.Label();
+ this.lImageType = new System.Windows.Forms.Label();
+ this.lDPIY = new System.Windows.Forms.Label();
+ this.lDPIX = new System.Windows.Forms.Label();
+ this.lFormat = new System.Windows.Forms.Label();
+ this.lHeader = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // ofd
+ //
+ this.ofd.Filter = "All files (*.*)|*.*";
+ //
+ // bOpenFile
+ //
+ this.bOpenFile.Location = new System.Drawing.Point(12, 358);
+ this.bOpenFile.Name = "bOpenFile";
+ this.bOpenFile.Size = new System.Drawing.Size(75, 23);
+ this.bOpenFile.TabIndex = 4;
+ this.bOpenFile.Text = "Open file";
+ this.bOpenFile.UseVisualStyleBackColor = true;
+ this.bOpenFile.Click += new System.EventHandler(this.bOpenFile_Click);
+ //
+ // lWidth
+ //
+ this.lWidth.AutoSize = true;
+ this.lWidth.Location = new System.Drawing.Point(9, 51);
+ this.lWidth.Name = "lWidth";
+ this.lWidth.Size = new System.Drawing.Size(46, 16);
+ this.lWidth.TabIndex = 0;
+ this.lWidth.Text = "Width:";
+ //
+ // lHeight
+ //
+ this.lHeight.AutoSize = true;
+ this.lHeight.Location = new System.Drawing.Point(9, 76);
+ this.lHeight.Name = "lHeight";
+ this.lHeight.Size = new System.Drawing.Size(53, 16);
+ this.lHeight.TabIndex = 1;
+ this.lHeight.Text = "Height: ";
+ //
+ // lBPP
+ //
+ this.lBPP.AutoSize = true;
+ this.lBPP.Location = new System.Drawing.Point(9, 101);
+ this.lBPP.Name = "lBPP";
+ this.lBPP.Size = new System.Drawing.Size(80, 16);
+ this.lBPP.TabIndex = 2;
+ this.lBPP.Text = "Color Depth:";
+ //
+ // lRedMask
+ //
+ this.lRedMask.AutoSize = true;
+ this.lRedMask.Location = new System.Drawing.Point(9, 129);
+ this.lRedMask.Name = "lRedMask";
+ this.lRedMask.Size = new System.Drawing.Size(68, 16);
+ this.lRedMask.TabIndex = 3;
+ this.lRedMask.Text = "Red Mask:";
+ //
+ // lGreenMask
+ //
+ this.lGreenMask.AutoSize = true;
+ this.lGreenMask.Location = new System.Drawing.Point(9, 188);
+ this.lGreenMask.Name = "lGreenMask";
+ this.lGreenMask.Size = new System.Drawing.Size(80, 16);
+ this.lGreenMask.TabIndex = 5;
+ this.lGreenMask.Text = "Green Mask:";
+ //
+ // lBlueMask
+ //
+ this.lBlueMask.AutoSize = true;
+ this.lBlueMask.Location = new System.Drawing.Point(9, 158);
+ this.lBlueMask.Name = "lBlueMask";
+ this.lBlueMask.Size = new System.Drawing.Size(70, 16);
+ this.lBlueMask.TabIndex = 6;
+ this.lBlueMask.Text = "Blue Mask:";
+ //
+ // lImageType
+ //
+ this.lImageType.AutoSize = true;
+ this.lImageType.Location = new System.Drawing.Point(9, 215);
+ this.lImageType.Name = "lImageType";
+ this.lImageType.Size = new System.Drawing.Size(81, 16);
+ this.lImageType.TabIndex = 7;
+ this.lImageType.Text = "Image Type:";
+ //
+ // lDPIY
+ //
+ this.lDPIY.AutoSize = true;
+ this.lDPIY.Location = new System.Drawing.Point(9, 244);
+ this.lDPIY.Name = "lDPIY";
+ this.lDPIY.Size = new System.Drawing.Size(43, 16);
+ this.lDPIY.TabIndex = 8;
+ this.lDPIY.Text = "DPI Y:";
+ //
+ // lDPIX
+ //
+ this.lDPIX.AutoSize = true;
+ this.lDPIX.Location = new System.Drawing.Point(9, 273);
+ this.lDPIX.Name = "lDPIX";
+ this.lDPIX.Size = new System.Drawing.Size(44, 16);
+ this.lDPIX.TabIndex = 9;
+ this.lDPIX.Text = "DPI X:";
+ //
+ // lFormat
+ //
+ this.lFormat.AutoSize = true;
+ this.lFormat.Location = new System.Drawing.Point(9, 302);
+ this.lFormat.Name = "lFormat";
+ this.lFormat.Size = new System.Drawing.Size(78, 16);
+ this.lFormat.TabIndex = 10;
+ this.lFormat.Text = "File Format:";
+ //
+ // lHeader
+ //
+ this.lHeader.AutoSize = true;
+ this.lHeader.Location = new System.Drawing.Point(117, 19);
+ this.lHeader.Name = "lHeader";
+ this.lHeader.Size = new System.Drawing.Size(162, 16);
+ this.lHeader.TabIndex = 11;
+ this.lHeader.Text = "Bitmap-Information Viewer";
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(400, 393);
+ this.Controls.Add(this.lHeader);
+ this.Controls.Add(this.lFormat);
+ this.Controls.Add(this.lDPIX);
+ this.Controls.Add(this.lDPIY);
+ this.Controls.Add(this.lImageType);
+ this.Controls.Add(this.lBlueMask);
+ this.Controls.Add(this.lGreenMask);
+ this.Controls.Add(this.bOpenFile);
+ this.Controls.Add(this.lRedMask);
+ this.Controls.Add(this.lBPP);
+ this.Controls.Add(this.lHeight);
+ this.Controls.Add(this.lWidth);
+ this.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Sample04";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.OpenFileDialog ofd;
+ private System.Windows.Forms.Button bOpenFile;
+ private System.Windows.Forms.Label lWidth;
+ private System.Windows.Forms.Label lHeight;
+ private System.Windows.Forms.Label lBPP;
+ private System.Windows.Forms.Label lRedMask;
+ private System.Windows.Forms.Label lGreenMask;
+ private System.Windows.Forms.Label lBlueMask;
+ private System.Windows.Forms.Label lImageType;
+ private System.Windows.Forms.Label lDPIY;
+ private System.Windows.Forms.Label lDPIX;
+ private System.Windows.Forms.Label lFormat;
+ private System.Windows.Forms.Label lHeader;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.cs
new file mode 100644
index 0000000..cf72567
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Windows.Forms;
+using FreeImageAPI;
+
+namespace Sample04
+{
+ public partial class MainForm : Form
+ {
+ string message = null;
+
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+
+ public MainForm()
+ {
+ InitializeComponent();
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ ~MainForm()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ if (this.message == null)
+ {
+ this.message = message;
+ }
+ else
+ {
+ this.message += "\n" + message;
+ }
+ }
+
+ private void bOpenFile_Click(object sender, EventArgs e)
+ {
+ // Resetting filename
+ ofd.FileName = "";
+
+ // Was a file selected
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ // Format is stored in 'format' on successfull load.
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+
+ // Try loading the file
+ FIBITMAP dib = FreeImage.LoadEx(ofd.FileName, ref format);
+
+ try
+ {
+ // Error handling
+ if (dib.IsNull)
+ {
+ // Chech whether FreeImage generated an error messe
+ if (message != null)
+ {
+ MessageBox.Show("File could not be loaded!\nError:{0}", message);
+ }
+ else
+ {
+ MessageBox.Show("File could not be loaded!", message);
+ }
+ return;
+ }
+
+ // Read width
+ lWidth.Text = String.Format("Width: {0}", FreeImage.GetWidth(dib));
+
+ // Read height
+ lHeight.Text = String.Format("Width: {0}", FreeImage.GetWidth(dib));
+
+ // Read color depth
+ lBPP.Text = String.Format("Color Depth: {0}", FreeImage.GetBPP(dib));
+
+ // Read red bitmask (16 - 32 bpp)
+ lRedMask.Text = String.Format("Red Mask: 0x{0:X8}", FreeImage.GetRedMask(dib));
+
+ // Read green bitmask (16 - 32 bpp)
+ lBlueMask.Text = String.Format("Green Mask: 0x{0:X8}", FreeImage.GetGreenMask(dib));
+
+ // Read blue bitmask (16 - 32 bpp)
+ lGreenMask.Text = String.Format("Blue Mask: 0x{0:X8}", FreeImage.GetBlueMask(dib));
+
+ // Read image type (FI_BITMAP, FIT_RGB16, FIT_COMPLEX ect)
+ lImageType.Text = String.Format("Image Type: {0}", FreeImage.GetImageType(dib));
+
+ // Read x-axis dpi
+ lDPIX.Text = String.Format("DPI X: {0}", FreeImage.GetResolutionX(dib));
+
+ // Read y-axis dpi
+ lDPIY.Text = String.Format("DPI Y: {0}", FreeImage.GetResolutionY(dib));
+
+ // Read file format
+ lFormat.Text = String.Format("File Format: {0}", FreeImage.GetFormatFromFIF(format));
+ }
+ catch
+ {
+ }
+
+ // Always unload bitmap
+ FreeImage.UnloadEx(ref dib);
+
+ // Reset the error massage buffer
+ message = null;
+ }
+ // No file was selected
+ else
+ {
+ MessageBox.Show("No file loaded.", "Error");
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.resx
new file mode 100644
index 0000000..63f7f57
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/MainForm.resx
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <metadata name="ofd.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c14bca6
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("7c8fdc9a-a8f9-4996-99c8-9df47513edeb")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Sample 04 - Getting bitmap informations.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Sample 04 - Getting bitmap informations.csproj
new file mode 100644
index 0000000..aac021d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 04 - Getting bitmap informations/Sample 04 - Getting bitmap informations.csproj
@@ -0,0 +1,104 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{1F4BCDD7-5BD9-4237-8B14-C52B2A9FF52A}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample04</RootNamespace>
+ <AssemblyName>Sample04</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MainForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="MainForm.Designer.cs">
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="MainForm.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Program.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Program.cs
new file mode 100644
index 0000000..40f878f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Program.cs
@@ -0,0 +1,213 @@
+using System;
+using FreeImageAPI;
+using System.Drawing;
+
+namespace Sample05
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Check if FreeImage.dll is available (can be in %path%).
+ if (!FreeImage.IsAvailable())
+ {
+ Console.WriteLine("FreeImage.dll seems to be missing. Aborting.");
+ return;
+ }
+
+ Sample sample = new Sample();
+
+ // The example will flip the bitmap by manually accessing the
+ // bitmaps scanlines and swapping them
+ sample.Example01();
+
+ // The example will access each pixel of the bitmap manually
+ // and change its color intensity to 3/4 of the original value
+ // which will have a darker bitmap as result.
+ sample.Example02();
+
+ // The example will access and swap the bitmaps palette from
+ // 'FIC_MINISBLACK' to 'FIC_MINISWHITE'. Then it will swap each pixels
+ // palette index so that each pixel is assigned to the its old value
+ // so that the bitmaps "pixeldata" stays the same.
+ sample.Example03();
+ }
+ }
+
+ public class Sample
+ {
+ FIBITMAP dib = new FIBITMAP();
+
+ public void Example01()
+ {
+ // Load sample file
+ dib = FreeImage.LoadEx("Sample.jpg", FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+
+ // Check whether loading succeeded
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Sample.jpg could not be loaded. Aborting.");
+ return;
+ }
+
+ // Check whether the bitmap has 24 bpp color depth to ensure
+ // using RGBTRIPPLE is correct.
+ if (FreeImage.GetBPP(dib) != 24)
+ {
+ Console.WriteLine("Sample.jpg is no 24 bpp bitmap. Aborting.");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Store height of the bitmap
+ int height = (int)FreeImage.GetHeight(dib);
+
+ // Iterate over half of the bitmaps scanlines and swap
+ // line[1] with line[height], line[2] with line[height-1] etc which will
+ // flip the image.
+ for (int i = 0; i < (height / 2); i++)
+ {
+ // Get scanline from the bottom part of the bitmap
+ Scanline<RGBTRIPLE> scanlineBottom = new Scanline<RGBTRIPLE>(dib, i);
+
+ // Get scanline from the top part of the bitmap
+ Scanline<RGBTRIPLE> scanlineTop = new Scanline<RGBTRIPLE>(dib, height - 1 - i);
+
+ // Get arrays of RGBTRIPPLEs that contain the bitmaps real pixel data
+ // of the two scanlines.
+ RGBTRIPLE[] rgbtBottom = scanlineBottom.Data;
+ RGBTRIPLE[] rgbtTop = scanlineTop.Data;
+
+ // Restore the scanline across to switch the bitmaps lines.
+ scanlineBottom.Data = rgbtTop;
+ scanlineTop.Data = rgbtBottom;
+ }
+
+ // Store the bitmap to disk
+ if (!FreeImage.SaveEx(ref dib, "SampleOut01.jpg", FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYGOOD, true))
+ {
+ Console.WriteLine("Error while saving 'SampleOut01.jpg'");
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ public void Example02()
+ {
+ dib = FreeImage.LoadEx("Sample.jpg", FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+
+ // Check whether loading succeeded
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Sample.jpg could not be loaded. Aborting.");
+ return;
+ }
+
+ // Check whether the bitmap has 24 bpp color depth to ensure
+ // using RGBTRIPPLE is correct.
+ if (FreeImage.GetBPP(dib) != 24)
+ {
+ Console.WriteLine("Sample.jpg is no 24 bpp bitmap. Aborting.");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Iterate over all scanlines
+ for (int i = 0; i < FreeImage.GetHeight(dib); i++)
+ {
+ // Get scanline
+ Scanline<RGBTRIPLE> scanline = new Scanline<RGBTRIPLE>(dib, i);
+
+ // Get pixeldata from scanline
+ RGBTRIPLE[] rgbt = scanline.Data;
+
+ // Iterate over each pixel reducing the colors intensity to 3/4 which
+ // will darken the bitmap.
+ for (int j = 0; j < rgbt.Length; j++)
+ {
+ rgbt[j].rgbtBlue = (byte)((int)rgbt[j].rgbtBlue * 3 / 4);
+ rgbt[j].rgbtGreen = (byte)((int)rgbt[j].rgbtGreen * 3 / 4);
+ rgbt[j].rgbtRed = (byte)((int)rgbt[j].rgbtRed * 3 / 4);
+
+ // In case no direct access to the data is implemented
+ // the following way is equivalent:
+ //
+ // Color color = rgbt[j].color;
+ // rgbt[j].color = Color.FromArgb(color.R * 3 / 4, color.G * 3 / 4, color.B * 3 / 4);
+ }
+
+ // Write the darkened scanline back to memory
+ scanline.Data = rgbt;
+ }
+
+ // Store the bitmap to disk
+ if (!FreeImage.SaveEx(ref dib, "SampleOut02.jpg", FREE_IMAGE_SAVE_FLAGS.JPEG_QUALITYGOOD, true))
+ {
+ Console.WriteLine("Error while saving 'SampleOut02.jpg'");
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ public void Example03()
+ {
+ dib = FreeImage.LoadEx("Sample.tif");
+
+ // Check whether loading succeeded
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Sample.tif could not be loaded. Aborting.");
+ return;
+ }
+
+ // Check whether the bitmap has 4 bpp color depth to ensure
+ // using FI4B is correct.
+ if (FreeImage.GetBPP(dib) != 4)
+ {
+ Console.WriteLine("Sample.tif is no 4 bpp bitmap. Aborting.");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Get the bitmaps palette
+ Palette palette = FreeImage.GetPaletteEx(dib);
+
+ int size = (int)palette.Length;
+
+ // Check whether the palette has a color (is valid)
+ if (size == 0)
+ {
+ Console.WriteLine("Sample.tif has no valid palette. Aborting.");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Swapping the palette
+ for (int i = 0; i < size / 2; i++)
+ {
+ RGBQUAD temp = palette[i];
+ palette[i] = palette[size - 1 - i];
+ palette[size - 1 - i] = temp;
+ }
+
+ // Iterate over each scanline
+ for (int i = 0; i < FreeImage.GetHeight(dib); i++)
+ {
+ // Get scanline
+ Scanline<FI4BIT> scanline = new Scanline<FI4BIT>(dib, i);
+
+ // Iterate over all pixels swapping the palette index
+ // so that the color will stay the same
+ for (int j = 0; j < scanline.Length; j++)
+ {
+ scanline[j] = (byte)(size - 1 - scanline[j]);
+ }
+ }
+
+ // Save the bitmap to disk
+ if (!FreeImage.SaveEx(ref dib, "SampleOut03.tif", FREE_IMAGE_SAVE_FLAGS.TIFF_LZW, true))
+ {
+ Console.WriteLine("Error while saving 'SampleOut03.tif'");
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..35304a0
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("fd43331d-5ea4-40f8-86d5-8f820d606912")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample 05 - Working with pixels.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample 05 - Working with pixels.csproj
new file mode 100644
index 0000000..0c3b449
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample 05 - Working with pixels.csproj
@@ -0,0 +1,100 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{A501F134-8FB6-460B-AFE9-884A696C1C07}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample05</RootNamespace>
+ <AssemblyName>Sample05</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Sample.jpg">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="Sample.tif">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.jpg b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.jpg
new file mode 100644
index 0000000..df1918c
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.jpg
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.tif b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.tif
new file mode 100644
index 0000000..7b37c6b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 05 - Working with pixels/Sample.tif
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.Designer.cs
new file mode 100644
index 0000000..5ae81a8
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.Designer.cs
@@ -0,0 +1,120 @@
+namespace Sample06
+{
+ partial class MainForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.picBox = new System.Windows.Forms.PictureBox();
+ this.bExample01 = new System.Windows.Forms.Button();
+ this.bOriginal = new System.Windows.Forms.Button();
+ this.bExample02 = new System.Windows.Forms.Button();
+ this.bExample03 = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.picBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // picBox
+ //
+ this.picBox.BackColor = System.Drawing.Color.White;
+ this.picBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.picBox.Location = new System.Drawing.Point(12, 12);
+ this.picBox.Name = "picBox";
+ this.picBox.Size = new System.Drawing.Size(747, 465);
+ this.picBox.TabIndex = 0;
+ this.picBox.TabStop = false;
+ //
+ // bExample01
+ //
+ this.bExample01.Location = new System.Drawing.Point(93, 483);
+ this.bExample01.Name = "bExample01";
+ this.bExample01.Size = new System.Drawing.Size(88, 23);
+ this.bExample01.TabIndex = 1;
+ this.bExample01.Text = "Example 01";
+ this.bExample01.UseVisualStyleBackColor = true;
+ this.bExample01.Click += new System.EventHandler(this.bExample01_Click);
+ //
+ // bOriginal
+ //
+ this.bOriginal.Location = new System.Drawing.Point(12, 483);
+ this.bOriginal.Name = "bOriginal";
+ this.bOriginal.Size = new System.Drawing.Size(75, 23);
+ this.bOriginal.TabIndex = 2;
+ this.bOriginal.Text = "Original";
+ this.bOriginal.UseVisualStyleBackColor = true;
+ this.bOriginal.Click += new System.EventHandler(this.bOriginal_Click);
+ //
+ // bExample02
+ //
+ this.bExample02.Location = new System.Drawing.Point(187, 483);
+ this.bExample02.Name = "bExample02";
+ this.bExample02.Size = new System.Drawing.Size(88, 23);
+ this.bExample02.TabIndex = 3;
+ this.bExample02.Text = "Example 02";
+ this.bExample02.UseVisualStyleBackColor = true;
+ this.bExample02.Click += new System.EventHandler(this.bExample02_Click);
+ //
+ // bExample03
+ //
+ this.bExample03.Location = new System.Drawing.Point(281, 483);
+ this.bExample03.Name = "bExample03";
+ this.bExample03.Size = new System.Drawing.Size(88, 23);
+ this.bExample03.TabIndex = 4;
+ this.bExample03.Text = "Example 03";
+ this.bExample03.UseVisualStyleBackColor = true;
+ this.bExample03.Click += new System.EventHandler(this.bExample03_Click);
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(771, 518);
+ this.Controls.Add(this.bExample03);
+ this.Controls.Add(this.bExample02);
+ this.Controls.Add(this.bOriginal);
+ this.Controls.Add(this.bExample01);
+ this.Controls.Add(this.picBox);
+ this.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Sample06";
+ ((System.ComponentModel.ISupportInitialize)(this.picBox)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox picBox;
+ private System.Windows.Forms.Button bExample01;
+ private System.Windows.Forms.Button bOriginal;
+ private System.Windows.Forms.Button bExample02;
+ private System.Windows.Forms.Button bExample03;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.cs
new file mode 100644
index 0000000..b7409bb
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using FreeImageAPI;
+using System.Drawing.Imaging;
+
+namespace Sample06
+{
+ public partial class MainForm : Form
+ {
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ private void bExample01_Click(object sender, EventArgs e)
+ {
+ // Load bitmap
+ FIBITMAP dib = FreeImage.LoadEx("Sample.jpg");
+
+ // Check success
+ if (dib.IsNull)
+ {
+ MessageBox.Show("Could not load Sample.jpg", "Error");
+ return;
+ }
+
+ // Check whether bitmap is 24-bit
+ if (FreeImage.GetBPP(dib) != 24)
+ {
+ MessageBox.Show("Sample.jpg is not 24-bit.", "Error");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Convert the 24-bit bitmap to 8-bit and forcing the result will be greyscale
+ dib = FreeImage.ConvertColorDepth(dib, FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP | FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE, true);
+
+ if (FreeImage.GetBPP(dib) == 8)
+ {
+ // Convert the FreeImage-Bitmap into a .NET bitmap
+ Bitmap bitmap = FreeImage.GetBitmap(dib);
+
+ // Dispose the bitmap of the pictureBox
+ if (picBox.Image != null)
+ {
+ picBox.Image.Dispose();
+ }
+
+ // Assign the bitmap to the picturebox
+ picBox.Image = bitmap;
+ }
+
+ // Unload source bitmap
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ private void bOriginal_Click(object sender, EventArgs e)
+ {
+ // Load bitmap
+ FIBITMAP dib = FreeImage.LoadEx("Sample.jpg");
+
+ // Check success
+ if (dib.IsNull)
+ {
+ MessageBox.Show("Could not load Sample.jpg", "Error");
+ return;
+ }
+
+ // Convert the FreeImage-Bitmap into a .NET bitmap
+ Bitmap bitmap = FreeImage.GetBitmap(dib);
+
+ // Check success
+ if (bitmap != null)
+ {
+ // Dispose old bitmap
+ if (picBox.Image != null)
+ {
+ picBox.Image.Dispose();
+ }
+
+ // Assign new bitmap
+ picBox.Image = bitmap;
+ }
+
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ private void bExample02_Click(object sender, EventArgs e)
+ {
+ FIBITMAP dib = FreeImage.LoadEx("Sample.jpg");
+
+ // Check success
+ if (dib.IsNull)
+ {
+ MessageBox.Show("Could not load Sample.jpg", "Error");
+ return;
+ }
+
+ // Convert bitmap to 8 bit
+ dib = FreeImage.ConvertColorDepth(dib, FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP, true);
+
+ // Check whether conversion succeeded
+ if (FreeImage.GetBPP(dib) != 8)
+ {
+ MessageBox.Show("Converting Sample.jpg to 8-bit failed.", "Error");
+ FreeImage.UnloadEx(ref dib);
+ return;
+ }
+
+ // Convert the FreeImage-Bitmap into a .NET bitmap
+ Bitmap bitmap = FreeImage.GetBitmap(dib);
+
+ // Dispose old bitmap
+ if (picBox.Image != null)
+ {
+ picBox.Image.Dispose();
+ }
+
+ // Assign new bitmap
+ picBox.Image = bitmap;
+
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ private void bExample03_Click(object sender, EventArgs e)
+ {
+ // Load bitmap
+ Bitmap bitmap = (Bitmap)Bitmap.FromFile("Sample.jpg");
+
+ // Convert the .NET bitmap into a FreeImage-Bitmap
+ FIBITMAP dib = FreeImage.CreateFromBitmap(bitmap);
+
+ // Unload bitmap
+ bitmap.Dispose();
+
+ // Rescale the bitmap
+ FIBITMAP temp = FreeImage.Rescale(dib, 300, 300, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+
+ Random rand = new Random();
+
+ // Rotate the bitmap
+ dib = FreeImage.Rotate(temp, rand.NextDouble() * 360d);
+
+ // Unload bitmap
+ FreeImage.UnloadEx(ref temp);
+
+ // Convert the FreeImage-Bitmap into a .NET bitmap
+ bitmap = FreeImage.GetBitmap(dib);
+
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+
+ // Unload bitmap
+ if (picBox.Image != null)
+ {
+ picBox.Image.Dispose();
+ }
+
+ // Assign new bitmap
+ picBox.Image = bitmap;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.resx
new file mode 100644
index 0000000..ff31a6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/MainForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fdd8539
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("69a8cbdd-43da-49e3-8d0b-2680c4ca2851")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample 06 - Converting.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample 06 - Converting.csproj
new file mode 100644
index 0000000..6a15213
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample 06 - Converting.csproj
@@ -0,0 +1,109 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{E2EA945D-E22C-47B3-9DD9-3A0B07FA3F81}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample06</RootNamespace>
+ <AssemblyName>Sample06</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MainForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="MainForm.Designer.cs">
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="MainForm.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Sample.jpg">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample.jpg b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample.jpg
new file mode 100644
index 0000000..b537c00
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 06 - Converting/Sample.jpg
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Program.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Program.cs
new file mode 100644
index 0000000..b03d1f2
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Program.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using FreeImageAPI;
+
+namespace Sample07
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ // Check if FreeImage.dll is available (can be in %path%).
+ if (!FreeImage.IsAvailable())
+ {
+ Console.WriteLine("FreeImage.dll seems to be missing. Aborting.");
+ return;
+ }
+
+ Sample sample = new Sample();
+ // This example shows how to work with ICC-Profiles.
+ sample.Example();
+ }
+ }
+
+ public class Sample
+ {
+ public void Example()
+ {
+ // Load the sample bitmap.
+ FIBITMAP dib = FreeImage.LoadEx("Sample.jpg");
+
+ // Check success
+ if (dib.IsNull)
+ {
+ Console.WriteLine("Sample.jpg could not be loaded. Aborting.");
+ return;
+ }
+
+ // Get the bitmaps ICC-Profile.
+ FIICCPROFILE icc = FreeImage.GetICCProfileEx(dib);
+
+ // Print the profiles address.
+ Console.WriteLine("The profiles memory-address is : 0x{0}", icc.DataPointer.ToString("X"));
+
+ // Print the profiles size
+ Console.WriteLine("The profiles size is : {0} bytes", icc.Size);
+
+ // Create data for a new profile.
+ byte[] data = new byte[256];
+ for (int i = 0; i < data.Length; i++)
+ data[i] = (byte)i;
+
+ // Create the new profile
+ icc = new FIICCPROFILE(dib, data);
+
+ Console.WriteLine("The profiles memory-address is : 0x{0}", icc.DataPointer.ToString("X"));
+ Console.WriteLine("The profiles size is : {0} bytes", icc.Size);
+
+ // Create the new profile but only use the first 64 bytes
+ icc = new FIICCPROFILE(dib, data, 64);
+
+ Console.WriteLine("The profiles memory-address is : 0x{0}", icc.DataPointer.ToString("X"));
+ Console.WriteLine("The profiles size is : {0} bytes", icc.Size);
+
+ // CreateICCProfileEx(...) does the same as above
+ icc = FreeImage.CreateICCProfileEx(dib, data, 16);
+
+ Console.WriteLine("The profiles memory-address is : 0x{0}", icc.DataPointer.ToString("X"));
+ Console.WriteLine("The profiles size is : {0} bytes", icc.Size);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b7cddbb
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("c9991d1d-684a-4736-b088-369a216b35b6")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample 07 - ICC Profiles.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample 07 - ICC Profiles.csproj
new file mode 100644
index 0000000..180680a
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample 07 - ICC Profiles.csproj
@@ -0,0 +1,96 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{3B1BB976-64A7-41FD-B7E2-59104161AF7E}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample07</RootNamespace>
+ <AssemblyName>Sample07</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Sample.jpg">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample.jpg b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample.jpg
new file mode 100644
index 0000000..c9e425d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 07 - ICC Profiles/Sample.jpg
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..cc1b67a
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("dc891ffc-ab5c-451f-97da-2c0d5d90edcc")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample 08 - Creating a plugin.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample 08 - Creating a plugin.csproj
new file mode 100644
index 0000000..fa8d4fd
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample 08 - Creating a plugin.csproj
@@ -0,0 +1,110 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{491042DB-495B-420C-A3BE-5D13019707C5}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample08</RootNamespace>
+ <AssemblyName>Sample08</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SampleForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="SampleForm.Designer.cs">
+ <DependentUpon>SampleForm.cs</DependentUpon>
+ </Compile>
+ <Compile Include="SerializationPlugin.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Sample.jpg">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="SampleForm.resx">
+ <DependentUpon>SampleForm.cs</DependentUpon>
+ <SubType>Designer</SubType>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample.jpg b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample.jpg
new file mode 100644
index 0000000..b537c00
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/Sample.jpg
Binary files differ
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.Designer.cs
new file mode 100644
index 0000000..135a92f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.Designer.cs
@@ -0,0 +1,119 @@
+namespace Sample08
+{
+ partial class SampleForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.pictureBox = new System.Windows.Forms.PictureBox();
+ this.bLoad = new System.Windows.Forms.Button();
+ this.SaveToSer = new System.Windows.Forms.Button();
+ this.LoadSerBitmap = new System.Windows.Forms.Button();
+ this.bClearBitmap = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox
+ //
+ this.pictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
+ this.pictureBox.Location = new System.Drawing.Point(12, 12);
+ this.pictureBox.Name = "pictureBox";
+ this.pictureBox.Size = new System.Drawing.Size(600, 400);
+ this.pictureBox.TabIndex = 0;
+ this.pictureBox.TabStop = false;
+ //
+ // bLoad
+ //
+ this.bLoad.Location = new System.Drawing.Point(12, 418);
+ this.bLoad.Name = "bLoad";
+ this.bLoad.Size = new System.Drawing.Size(98, 23);
+ this.bLoad.TabIndex = 1;
+ this.bLoad.Text = "Load any bitmap";
+ this.bLoad.UseVisualStyleBackColor = true;
+ this.bLoad.Click += new System.EventHandler(this.bLoad_Click);
+ //
+ // SaveToSer
+ //
+ this.SaveToSer.Location = new System.Drawing.Point(324, 418);
+ this.SaveToSer.Name = "SaveToSer";
+ this.SaveToSer.Size = new System.Drawing.Size(98, 23);
+ this.SaveToSer.TabIndex = 2;
+ this.SaveToSer.Text = "Save as .ser";
+ this.SaveToSer.UseVisualStyleBackColor = true;
+ this.SaveToSer.Click += new System.EventHandler(this.SaveToSer_Click);
+ //
+ // LoadSerBitmap
+ //
+ this.LoadSerBitmap.Location = new System.Drawing.Point(220, 418);
+ this.LoadSerBitmap.Name = "LoadSerBitmap";
+ this.LoadSerBitmap.Size = new System.Drawing.Size(98, 23);
+ this.LoadSerBitmap.TabIndex = 3;
+ this.LoadSerBitmap.Text = "Load .ser bitmap";
+ this.LoadSerBitmap.UseVisualStyleBackColor = true;
+ this.LoadSerBitmap.Click += new System.EventHandler(this.LoadSerBitmap_Click);
+ //
+ // bClearBitmap
+ //
+ this.bClearBitmap.Location = new System.Drawing.Point(116, 418);
+ this.bClearBitmap.Name = "bClearBitmap";
+ this.bClearBitmap.Size = new System.Drawing.Size(98, 23);
+ this.bClearBitmap.TabIndex = 4;
+ this.bClearBitmap.Text = "Clear screen";
+ this.bClearBitmap.UseVisualStyleBackColor = true;
+ this.bClearBitmap.Click += new System.EventHandler(this.bClearBitmap_Click);
+ //
+ // SampleForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(627, 448);
+ this.Controls.Add(this.bClearBitmap);
+ this.Controls.Add(this.LoadSerBitmap);
+ this.Controls.Add(this.SaveToSer);
+ this.Controls.Add(this.bLoad);
+ this.Controls.Add(this.pictureBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "SampleForm";
+ this.ShowIcon = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Sample 08";
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pictureBox;
+ private System.Windows.Forms.Button bLoad;
+ private System.Windows.Forms.Button SaveToSer;
+ private System.Windows.Forms.Button LoadSerBitmap;
+ private System.Windows.Forms.Button bClearBitmap;
+ }
+}
+
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.cs
new file mode 100644
index 0000000..87b83ed
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using FreeImageAPI;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+
+namespace Sample08
+{
+ public partial class SampleForm : Form
+ {
+ SerializationPlugin serialPlugin;
+
+ [STAThread]
+ static void Main()
+ {
+ // Check if FreeImage is available
+ if (!FreeImage.IsAvailable())
+ {
+ throw new Exception("FreeImage is not available!");
+ }
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new SampleForm());
+ }
+
+ public SampleForm()
+ {
+ InitializeComponent();
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+
+ // Creating a new instance of the plugin will register it automatically.
+ serialPlugin = new SerializationPlugin();
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ // Show the message
+ MessageBox.Show(String.Format("Format: {0}\nMessage: {1}", fif, message), "FreeImage Message");
+ }
+
+ private void bLoad_Click(object sender, EventArgs e)
+ {
+ // Create a new dialog instance
+ OpenFileDialog ofd = new OpenFileDialog();
+ try
+ {
+ // Apply settings
+ ofd.CheckPathExists = true;
+ ofd.CheckFileExists = true;
+ ofd.RestoreDirectory = true;
+ ofd.Filter = "All files (*.*)|*.*";
+
+ // Get filename
+ if (ofd.ShowDialog(this) == DialogResult.OK)
+ {
+ Bitmap bitmap = null;
+ try
+ {
+ // Try loading the selected file
+ // a ser-file will create an exception
+ bitmap = (Bitmap)Bitmap.FromFile(ofd.FileName);
+ }
+ catch
+ {
+ MessageBox.Show("Unable to load bitmap from file.", "Error");
+ return;
+ }
+
+ // Unload old bitmap
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ }
+
+ // Set new bitmap
+ pictureBox.Image = bitmap;
+ MessageBox.Show("Bitmap loaded successfully", "Success");
+ }
+ else
+ {
+ MessageBox.Show("Action aborted.");
+ }
+ }
+ finally
+ {
+ // Unload dialog
+ ofd.Dispose();
+ }
+ }
+
+ private void LoadSerBitmap_Click(object sender, EventArgs e)
+ {
+ // Creat a new dialog
+ OpenFileDialog ofd = new OpenFileDialog();
+
+ FIBITMAP dib = new FIBITMAP();
+ try
+ {
+ // Apply settings
+ ofd.CheckPathExists = true;
+ ofd.CheckFileExists = true;
+ ofd.RestoreDirectory = true;
+ ofd.Filter = "Serialized bitmap (*.ser)|*.ser";
+
+ // Get filename
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ // Try loading the file forcing the new format
+ dib = FreeImage.Load(serialPlugin.Format, ofd.FileName, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ if (dib.IsNull)
+ {
+ MessageBox.Show("Loading bitmap failed", "Error");
+ return;
+ }
+
+ // Convert the loaded bitmap into a .NET bitmap
+ Bitmap bitmap = FreeImage.GetBitmap(dib);
+ if (bitmap == null)
+ {
+ MessageBox.Show("Converting bitmap failed.", "Error");
+ return;
+ }
+
+ // Unload the picturebox
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ }
+
+ // Apply the loaded bitmap
+ pictureBox.Image = bitmap;
+ MessageBox.Show("Bitmap loaded successfully", "Success");
+ }
+ else
+ {
+ MessageBox.Show("Action aborted.");
+ }
+ }
+ finally
+ {
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+
+ // Unload dialog
+ ofd.Dispose();
+ }
+ }
+
+ private void SaveToSer_Click(object sender, EventArgs e)
+ {
+ // Create a new dialog
+ SaveFileDialog sfd = new SaveFileDialog();
+
+ FIBITMAP dib = new FIBITMAP();
+ try
+ {
+ // Check if the picture box contains a bitmap that can be saved.
+ if (pictureBox.Image == null)
+ {
+ MessageBox.Show("No bitmap loaded.", "Error");
+ return;
+ }
+
+ // Convert the picture-boxes bitmap into a FreeImage bitmap.
+ dib = FreeImage.CreateFromBitmap((Bitmap)pictureBox.Image);
+ if (dib.IsNull)
+ {
+ MessageBox.Show("Unable to convert bitmap to FIBITMAP.", "Error");
+ return;
+ }
+
+ // Apply settings
+ sfd.Filter = "Serialized bitmap (*.ser)|*.ser";
+ sfd.FileName = "Bitmap.ser";
+ sfd.OverwritePrompt = true;
+ sfd.RestoreDirectory = true;
+
+ // Get filename
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ // Save bitmap in the new format
+ if (FreeImage.SaveEx(dib, sfd.FileName, serialPlugin.Format))
+ MessageBox.Show("Bitmap saved successfully.", "Success");
+ else
+ MessageBox.Show("Saving bitmap failed.", "Failure");
+ }
+ else
+ {
+ MessageBox.Show("Action aborted.");
+ }
+ }
+ finally
+ {
+ // Unload bitmap
+ FreeImage.UnloadEx(ref dib);
+
+ // Unload dialog
+ sfd.Dispose();
+ }
+ }
+
+ private void bClearBitmap_Click(object sender, EventArgs e)
+ {
+ // Unload the picture-box
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ pictureBox.Image = null;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.resx
new file mode 100644
index 0000000..ff31a6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SampleForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SerializationPlugin.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SerializationPlugin.cs
new file mode 100644
index 0000000..a8ef7d5
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 08 - Creating a plugin/SerializationPlugin.cs
@@ -0,0 +1,222 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.IO;
+using System.IO.Compression;
+using FreeImageAPI;
+using FreeImageAPI.IO;
+using FreeImageAPI.Plugins;
+
+namespace Sample08
+{
+ public sealed class SerializationPlugin : LocalPlugin
+ {
+ // Header for the file
+ private byte[] header = new byte[] { 0xff, 0x12, 0x0f, 0xff, 0x01, 0x00 };
+
+ // Structure that will store all bitmap data.
+ [Serializable]
+ private struct SerialDib
+ {
+ public uint width;
+ public uint height;
+ public int pitch;
+ public uint bpp;
+ public uint red_mask;
+ public uint green_mask;
+ public uint blue_mask;
+ public byte[] data;
+ }
+
+ // Implementation of 'GetImplementedMethods()'
+ // All implemented methods are listed.
+ protected override LocalPlugin.MethodFlags GetImplementedMethods()
+ {
+ return
+ MethodFlags.DescriptionProc |
+ MethodFlags.SupportsExportBPPProc |
+ MethodFlags.SupportsExportTypeProc |
+ MethodFlags.SupportsICCProfilesProc |
+ MethodFlags.LoadProc |
+ MethodFlags.SaveProc |
+ MethodFlags.ValidateProc |
+ MethodFlags.ExtensionListProc;
+ }
+
+ // Returns a format string.
+ protected override string FormatProc()
+ {
+ return "Serialization";
+ }
+
+ // Returns a more specific description
+ protected override string DescriptionProc()
+ {
+ return "Serializes bitmaps for .NET";
+ }
+
+ // Returns whether a color depth is supported.
+ protected override bool SupportsExportBPPProc(int bpp)
+ {
+ return ((bpp == 1) ||
+ (bpp == 4) ||
+ (bpp == 8) ||
+ (bpp == 16) ||
+ (bpp == 24) ||
+ (bpp == 32));
+ }
+
+ // This plugin can only export standard bitmaps
+ protected override bool SupportsExportTypeProc(FREE_IMAGE_TYPE type)
+ {
+ return (type == FREE_IMAGE_TYPE.FIT_BITMAP);
+ }
+
+ // This plugin does not support icc profiles
+ protected override bool SupportsICCProfilesProc()
+ {
+ return false;
+ }
+
+ // The function reads the first bytes of the file and compares it
+ // with the predefined header.
+ protected override bool ValidateProc(ref FreeImageIO io, fi_handle handle)
+ {
+ for (int i = 0; i < header.Length; i++)
+ if (ReadByte(io, handle) != header[i])
+ return false;
+ return true;
+ }
+
+ // Loading function
+ protected override FIBITMAP LoadProc(ref FreeImageIO io, fi_handle handle, int page, int flags, IntPtr data)
+ {
+ // Check if the data has the correct format
+ if (!ValidateProc(ref io, handle))
+ {
+ // Create a free-image message
+ FreeImage.OutputMessageProc(format, "Invalid format.");
+ // return 0 (operation failed)
+ return FIBITMAP.Zero;
+ }
+
+ SerialDib sdib;
+ int read = 0;
+ System.IO.MemoryStream stream = new System.IO.MemoryStream();
+ byte[] buffer = new byte[1024];
+
+ do
+ {
+ // Use the helper function 'Read' to read from the source
+ read = Read(io, handle, 1, 1024, ref buffer);
+
+ // Store the data in a temporary buffer
+ stream.Write(buffer, 0, read);
+ }
+ while (read != 0);
+
+ // Set the memory stream back to the beginning.
+ stream.Position = 0;
+
+ // Unzip the stream
+ GZipStream zipStream = new GZipStream(stream, CompressionMode.Decompress);
+
+ // Create a serializer
+ BinaryFormatter formatter = new BinaryFormatter();
+
+ // Deserialize the stream
+ sdib = (SerialDib)formatter.Deserialize(zipStream);
+
+ // Unload the stream
+ zipStream.Dispose();
+
+ // Use 'ConvertFromRawBits and the deserialized struct to recreate the bitmap
+ // In this case the marshaller is used to create the needed IntPtr to the data
+ // array.
+ FIBITMAP dib = FreeImage.ConvertFromRawBits(
+ Marshal.UnsafeAddrOfPinnedArrayElement(sdib.data, 0),
+ (int)sdib.width, (int)sdib.height, sdib.pitch, sdib.bpp,
+ sdib.red_mask, sdib.green_mask, sdib.blue_mask,
+ false);
+
+ // Unload the temporary stream
+ stream.Dispose();
+
+ // Return the created bitmap
+ return dib;
+ }
+
+ // Saving function
+ protected override bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data)
+ {
+ SerialDib sdib;
+ uint size = FreeImage.GetDIBSize(dib);
+
+ // Store all data needed to recreate the bitmap
+ sdib.width = FreeImage.GetWidth(dib);
+ sdib.height = FreeImage.GetHeight(dib);
+ sdib.pitch = (int)FreeImage.GetPitch(dib);
+ sdib.bpp = FreeImage.GetBPP(dib);
+ sdib.red_mask = FreeImage.GetRedMask(dib);
+ sdib.green_mask = FreeImage.GetGreenMask(dib);
+ sdib.blue_mask = FreeImage.GetBlueMask(dib);
+ sdib.data = new byte[size];
+
+ // Copy the bitmaps data into the structures byte-array
+ // The marshaller is used to create an IntPtr for using
+ // 'ConvertToRawBits'.
+ FreeImage.ConvertToRawBits(Marshal.UnsafeAddrOfPinnedArrayElement(sdib.data, 0),
+ dib, sdib.pitch, sdib.bpp,
+ sdib.red_mask, sdib.green_mask, sdib.blue_mask,
+ false);
+
+ // Use the healper function to write the header to the destination
+ if (Write(io, handle, (uint)header.Length, 1, ref header) != 1)
+ return false;
+
+ // Create a serializer
+ BinaryFormatter formatter = new BinaryFormatter();
+
+ // Create a temporary stream
+ MemoryStream stream = new MemoryStream();
+
+ // Create a compression stream
+ GZipStream zipStream = new GZipStream(stream, CompressionMode.Compress);
+
+ // Serialize the structure into the compression stream
+ formatter.Serialize(zipStream, sdib);
+
+ // Unload the compression stream
+ zipStream.Dispose();
+
+ // Get the result data
+ byte[] buffer = stream.GetBuffer();
+
+ // Use the healper function 'Write' to write the data to the destination
+ if (Write(io, handle, 1, (uint)buffer.Length, ref buffer) != buffer.Length)
+ {
+ // Unload the temporary stream
+ stream.Dispose();
+ return false;
+ }
+
+ // Unload the temporary stream
+ stream.Dispose();
+ return true;
+ }
+
+ // Return a list of supported file extensions (comma seperated)
+ protected override string ExtensionListProc()
+ {
+ return "ser";
+ }
+
+ // Implementation of 'ToString()'
+ public override string ToString()
+ {
+ return DescriptionProc();
+ }
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..979d488
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("7f29fbaa-d2b3-4011-b34f-5a109bc282af")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Sample 09 - Working with streams.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Sample 09 - Working with streams.csproj
new file mode 100644
index 0000000..c89a986
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/Sample 09 - Working with streams.csproj
@@ -0,0 +1,105 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{92A454B2-67EF-4B70-99C9-F22B83B6FBFF}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample09</RootNamespace>
+ <AssemblyName>Sample09</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SampleForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="SampleForm.Designer.cs">
+ <DependentUpon>SampleForm.cs</DependentUpon>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="SampleForm.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>SampleForm.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.Designer.cs
new file mode 100644
index 0000000..8d90e17
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.Designer.cs
@@ -0,0 +1,115 @@
+namespace Sample09
+{
+ partial class SampleForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.picBox = new System.Windows.Forms.PictureBox();
+ this.tbURL = new System.Windows.Forms.TextBox();
+ this.lUrl = new System.Windows.Forms.Label();
+ this.bLoadUrl = new System.Windows.Forms.Button();
+ this.bSave = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.picBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // picBox
+ //
+ this.picBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.picBox.Location = new System.Drawing.Point(12, 12);
+ this.picBox.Name = "picBox";
+ this.picBox.Size = new System.Drawing.Size(536, 299);
+ this.picBox.TabIndex = 0;
+ this.picBox.TabStop = false;
+ //
+ // tbURL
+ //
+ this.tbURL.Location = new System.Drawing.Point(155, 317);
+ this.tbURL.Name = "tbURL";
+ this.tbURL.Size = new System.Drawing.Size(393, 20);
+ this.tbURL.TabIndex = 1;
+ this.tbURL.Text = "http://freeimage.sourceforge.net/images/logo.jpg";
+ //
+ // lUrl
+ //
+ this.lUrl.AutoSize = true;
+ this.lUrl.Location = new System.Drawing.Point(9, 320);
+ this.lUrl.Name = "lUrl";
+ this.lUrl.Size = new System.Drawing.Size(137, 13);
+ this.lUrl.TabIndex = 2;
+ this.lUrl.Text = "Enter the URL of an Image:";
+ //
+ // bLoadUrl
+ //
+ this.bLoadUrl.Location = new System.Drawing.Point(12, 344);
+ this.bLoadUrl.Name = "bLoadUrl";
+ this.bLoadUrl.Size = new System.Drawing.Size(75, 23);
+ this.bLoadUrl.TabIndex = 3;
+ this.bLoadUrl.Text = "Load URL";
+ this.bLoadUrl.UseVisualStyleBackColor = true;
+ this.bLoadUrl.Click += new System.EventHandler(this.bLoadUrl_Click);
+ //
+ // bSave
+ //
+ this.bSave.Location = new System.Drawing.Point(93, 344);
+ this.bSave.Name = "bSave";
+ this.bSave.Size = new System.Drawing.Size(75, 23);
+ this.bSave.TabIndex = 4;
+ this.bSave.Text = "Save to disk";
+ this.bSave.UseVisualStyleBackColor = true;
+ this.bSave.Click += new System.EventHandler(this.bSave_Click);
+ //
+ // SampleForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(560, 379);
+ this.Controls.Add(this.bSave);
+ this.Controls.Add(this.bLoadUrl);
+ this.Controls.Add(this.lUrl);
+ this.Controls.Add(this.tbURL);
+ this.Controls.Add(this.picBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "SampleForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Sample09";
+ ((System.ComponentModel.ISupportInitialize)(this.picBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox picBox;
+ private System.Windows.Forms.TextBox tbURL;
+ private System.Windows.Forms.Label lUrl;
+ private System.Windows.Forms.Button bLoadUrl;
+ private System.Windows.Forms.Button bSave;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.cs
new file mode 100644
index 0000000..2440394
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using FreeImageAPI;
+using System.Net;
+using System.IO;
+
+namespace Sample09
+{
+ public partial class SampleForm : Form
+ {
+ [STAThread]
+ static void Main()
+ {
+ // Check if FreeImage is available
+ if (!FreeImage.IsAvailable())
+ {
+ throw new Exception("FreeImage is not available!");
+ }
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new SampleForm());
+ }
+
+ public SampleForm()
+ {
+ InitializeComponent();
+ }
+
+ private void bLoadUrl_Click(object sender, EventArgs e)
+ {
+ // Verify url
+ if (String.IsNullOrEmpty(tbURL.Text))
+ {
+ MessageBox.Show("Please enter a valid URL.", "Error");
+ return;
+ }
+ FIBITMAP dib = new FIBITMAP();
+ Stream sourceStream = null;
+ try
+ {
+ // Build a stream to read from
+ WebRequest request = (WebRequest)HttpWebRequest.Create(tbURL.Text);
+ WebResponse response = request.GetResponse();
+ sourceStream = response.GetResponseStream();
+ if (sourceStream == null)
+ {
+ throw new Exception();
+ }
+ // Load the image from stream
+ dib = FreeImage.LoadFromStream(sourceStream);
+ // Check success
+ if (dib.IsNull)
+ {
+ throw new Exception();
+ }
+ // Convert the bitmap into a .NET bitmap
+ Bitmap bitmap = FreeImage.GetBitmap(dib);
+ if (bitmap == null)
+ {
+ throw new Exception();
+ }
+ // Show the bitmap
+ if (picBox.Image != null)
+ {
+ picBox.Image.Dispose();
+ }
+ picBox.Image = bitmap;
+ }
+ catch
+ {
+ // Error handling
+ MessageBox.Show("Error loading URL.", "Error");
+ }
+ finally
+ {
+ // Clean up memory
+ FreeImage.UnloadEx(ref dib);
+ if (sourceStream != null) sourceStream.Dispose();
+ }
+ }
+
+ private void bSave_Click(object sender, EventArgs e)
+ {
+ // Check if there is a loaded bitmap
+ if (picBox.Image == null)
+ {
+ MessageBox.Show("No image loaded.", "Error");
+ return;
+ }
+ SaveFileDialog sfd = null;
+ FileStream fStream = null;
+ FIBITMAP dib = new FIBITMAP();
+ try
+ {
+ sfd = new SaveFileDialog();
+ sfd.CreatePrompt = false;
+ sfd.FileName = "";
+ sfd.Filter = "TIF (*tif)|*.tif";
+ sfd.OverwritePrompt = true;
+ sfd.RestoreDirectory = true;
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ // Convert the .NET bitmap into a FreeImage-Bitmap
+ dib = FreeImage.CreateFromBitmap((Bitmap)picBox.Image);
+ if (dib.IsNull)
+ {
+ throw new Exception();
+ }
+ // Create a filestream to write to
+ fStream = new FileStream(sfd.FileName, FileMode.Create);
+ if (!FreeImage.SaveToStream(
+ ref dib,
+ fStream,
+ FREE_IMAGE_FORMAT.FIF_TIFF,
+ FREE_IMAGE_SAVE_FLAGS.TIFF_LZW,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false))
+ {
+ throw new Exception();
+ }
+ MessageBox.Show("Image saved successfully.", "Success");
+ }
+ else
+ {
+ MessageBox.Show("Operation aborted.", "Aborted");
+ }
+ }
+ catch
+ {
+ MessageBox.Show("Error saving image.", "Error");
+ }
+ finally
+ {
+ // Clean up
+ if (sfd != null) sfd.Dispose();
+ if (fStream != null) fStream.Dispose();
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.resx
new file mode 100644
index 0000000..ff31a6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 09 - Working with streams/SampleForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.Designer.cs
new file mode 100644
index 0000000..327e378
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.Designer.cs
@@ -0,0 +1,87 @@
+namespace Sample10
+{
+ partial class MainForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.bLoad = new System.Windows.Forms.Button();
+ this.bQuit = new System.Windows.Forms.Button();
+ this.tvMetadata = new System.Windows.Forms.TreeView();
+ this.SuspendLayout();
+ //
+ // bLoad
+ //
+ this.bLoad.Location = new System.Drawing.Point(12, 336);
+ this.bLoad.Name = "bLoad";
+ this.bLoad.Size = new System.Drawing.Size(75, 23);
+ this.bLoad.TabIndex = 0;
+ this.bLoad.Text = "Load Image";
+ this.bLoad.UseVisualStyleBackColor = true;
+ this.bLoad.Click += new System.EventHandler(this.bLoad_Click);
+ //
+ // bQuit
+ //
+ this.bQuit.Location = new System.Drawing.Point(328, 336);
+ this.bQuit.Name = "bQuit";
+ this.bQuit.Size = new System.Drawing.Size(75, 23);
+ this.bQuit.TabIndex = 1;
+ this.bQuit.Text = "Quit";
+ this.bQuit.UseVisualStyleBackColor = true;
+ this.bQuit.Click += new System.EventHandler(this.bQuit_Click);
+ //
+ // tvMetadata
+ //
+ this.tvMetadata.Location = new System.Drawing.Point(12, 12);
+ this.tvMetadata.Name = "tvMetadata";
+ this.tvMetadata.Size = new System.Drawing.Size(389, 318);
+ this.tvMetadata.TabIndex = 2;
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(415, 371);
+ this.Controls.Add(this.tvMetadata);
+ this.Controls.Add(this.bQuit);
+ this.Controls.Add(this.bLoad);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "MainForm";
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button bLoad;
+ private System.Windows.Forms.Button bQuit;
+ private System.Windows.Forms.TreeView tvMetadata;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.cs
new file mode 100644
index 0000000..d97f2ea
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using FreeImageAPI;
+using FreeImageAPI.Metadata;
+
+namespace Sample10
+{
+ public partial class MainForm : Form
+ {
+ [STAThread]
+ static void Main()
+ {
+ // Check if FreeImage.dll is available
+ if (!FreeImage.IsAvailable())
+ {
+ MessageBox.Show("FreeImage is not available. Aborting.", "Error");
+ }
+
+ // Add this class to the FreeImage-Message-Callback
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+
+ static void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ // Display the data
+ MessageBox.Show(
+ String.Format("FreeImage-Message:\n{1}\nFormat:{0}", fif.ToString(), message),
+ "FreeImage-Message");
+ }
+
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ private void bQuit_Click(object sender, EventArgs e)
+ {
+ Application.Exit();
+ }
+
+ private void bLoad_Click(object sender, EventArgs e)
+ {
+ // Create variables
+ OpenFileDialog ofd = new OpenFileDialog();
+ FIBITMAP dib = new FIBITMAP();
+ try
+ {
+ // Apply settings
+ ofd.CheckFileExists = true;
+ ofd.CheckPathExists = true;
+ ofd.FileName = "";
+ ofd.Filter = "All files (*.*)|*.*";
+ ofd.Multiselect = false;
+ ofd.RestoreDirectory = true;
+ // Get image filename
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ // Load the image
+ dib = FreeImage.LoadEx(ofd.FileName);
+ // Check if image was loaded successfully
+ if (dib.IsNull) throw new Exception("Failed to load image.");
+ // Clear the treeview
+ tvMetadata.Nodes.Clear();
+ // Create a wrapper for all metadata the image contains
+ ImageMetadata iMetadata = new ImageMetadata(dib);
+ // Get each metadata model
+ foreach (MetadataModel metadataModel in iMetadata)
+ {
+ // Create a new node for each model
+ TreeNode modelNode = tvMetadata.Nodes.Add(metadataModel.ToString());
+
+ // Get each metadata tag and create a subnode for it
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ modelNode.Nodes.Add(metadataTag.Key + ": " + metadataTag.ToString());
+ }
+ }
+ }
+ else
+ {
+ MessageBox.Show("Operation aborted.", "Aborted");
+ }
+ }
+ // Display error message
+ catch (Exception ex)
+ {
+ while (ex.InnerException != null)
+ ex = ex.InnerException;
+ MessageBox.Show(ex.ToString(), "Exception caught");
+ }
+ // Clean up
+ finally
+ {
+ ofd.Dispose();
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.resx
new file mode 100644
index 0000000..ff31a6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/MainForm.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2e84d4c
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("e8da4fa8-cc15-4b0e-8c57-d55ceb771559")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Sample 10 - Metadata.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Sample 10 - Metadata.csproj
new file mode 100644
index 0000000..d07ad5b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 10 - Metadata/Sample 10 - Metadata.csproj
@@ -0,0 +1,103 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{55DCC37A-E56C-44D9-9C44-8DAB10CD3003}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample10</RootNamespace>
+ <AssemblyName>Sample10</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MainForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="MainForm.Designer.cs">
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="MainForm.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.Designer.cs
new file mode 100644
index 0000000..eb122c9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.Designer.cs
@@ -0,0 +1,382 @@
+namespace Sample11
+{
+ partial class MainForm
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.pictureBox = new System.Windows.Forms.PictureBox();
+ this.bLoadImage = new System.Windows.Forms.Button();
+ this.bSaveImage = new System.Windows.Forms.Button();
+ this.ofd = new System.Windows.Forms.OpenFileDialog();
+ this.sfd = new System.Windows.Forms.SaveFileDialog();
+ this.lWidth = new System.Windows.Forms.Label();
+ this.lHeight = new System.Windows.Forms.Label();
+ this.lBpp = new System.Windows.Forms.Label();
+ this.lMetadataCount = new System.Windows.Forms.Label();
+ this.bGreyscale = new System.Windows.Forms.Button();
+ this.cbSelectFrame = new System.Windows.Forms.ComboBox();
+ this.lComment = new System.Windows.Forms.Label();
+ this.bAdjustGamma = new System.Windows.Forms.Button();
+ this.vGamma = new System.Windows.Forms.NumericUpDown();
+ this.bRedChannelOnly = new System.Windows.Forms.Button();
+ this.bBlueChannel = new System.Windows.Forms.Button();
+ this.bGreenChannel = new System.Windows.Forms.Button();
+ this.bAllChannels = new System.Windows.Forms.Button();
+ this.lSelectFrame = new System.Windows.Forms.Label();
+ this.lImageFormat = new System.Windows.Forms.Label();
+ this.bRotate = new System.Windows.Forms.Button();
+ this.vRotate = new System.Windows.Forms.TrackBar();
+ this.lRotate = new System.Windows.Forms.Label();
+ this.lColors = new System.Windows.Forms.Label();
+ this.nShowMetadata = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.vGamma)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this.vRotate)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox
+ //
+ this.pictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
+ this.pictureBox.Location = new System.Drawing.Point(14, 15);
+ this.pictureBox.Margin = new System.Windows.Forms.Padding(4);
+ this.pictureBox.Name = "pictureBox";
+ this.pictureBox.Size = new System.Drawing.Size(542, 395);
+ this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.pictureBox.TabIndex = 0;
+ this.pictureBox.TabStop = false;
+ //
+ // bLoadImage
+ //
+ this.bLoadImage.Location = new System.Drawing.Point(564, 15);
+ this.bLoadImage.Margin = new System.Windows.Forms.Padding(4);
+ this.bLoadImage.Name = "bLoadImage";
+ this.bLoadImage.Size = new System.Drawing.Size(125, 28);
+ this.bLoadImage.TabIndex = 1;
+ this.bLoadImage.Text = "Load image";
+ this.bLoadImage.UseVisualStyleBackColor = true;
+ this.bLoadImage.Click += new System.EventHandler(this.bLoadImage_Click);
+ //
+ // bSaveImage
+ //
+ this.bSaveImage.Location = new System.Drawing.Point(564, 51);
+ this.bSaveImage.Margin = new System.Windows.Forms.Padding(4);
+ this.bSaveImage.Name = "bSaveImage";
+ this.bSaveImage.Size = new System.Drawing.Size(125, 28);
+ this.bSaveImage.TabIndex = 2;
+ this.bSaveImage.Text = "Save image";
+ this.bSaveImage.UseVisualStyleBackColor = true;
+ this.bSaveImage.Click += new System.EventHandler(this.bSaveImage_Click);
+ //
+ // ofd
+ //
+ this.ofd.AddExtension = false;
+ this.ofd.AutoUpgradeEnabled = false;
+ this.ofd.Filter = "All files|*.*";
+ this.ofd.RestoreDirectory = true;
+ this.ofd.SupportMultiDottedExtensions = true;
+ //
+ // sfd
+ //
+ this.sfd.AddExtension = false;
+ this.sfd.Filter = "All files|*.*";
+ this.sfd.RestoreDirectory = true;
+ this.sfd.SupportMultiDottedExtensions = true;
+ //
+ // lWidth
+ //
+ this.lWidth.AutoSize = true;
+ this.lWidth.Location = new System.Drawing.Point(563, 350);
+ this.lWidth.Name = "lWidth";
+ this.lWidth.Size = new System.Drawing.Size(57, 16);
+ this.lWidth.TabIndex = 6;
+ this.lWidth.Text = "Width: 0";
+ //
+ // lHeight
+ //
+ this.lHeight.AutoSize = true;
+ this.lHeight.Location = new System.Drawing.Point(649, 350);
+ this.lHeight.Name = "lHeight";
+ this.lHeight.Size = new System.Drawing.Size(60, 16);
+ this.lHeight.TabIndex = 7;
+ this.lHeight.Text = "Height: 0";
+ //
+ // lBpp
+ //
+ this.lBpp.AutoSize = true;
+ this.lBpp.Location = new System.Drawing.Point(740, 350);
+ this.lBpp.Name = "lBpp";
+ this.lBpp.Size = new System.Drawing.Size(45, 16);
+ this.lBpp.TabIndex = 8;
+ this.lBpp.Text = "Bpp: 0";
+ //
+ // lMetadataCount
+ //
+ this.lMetadataCount.AutoSize = true;
+ this.lMetadataCount.Location = new System.Drawing.Point(809, 350);
+ this.lMetadataCount.Name = "lMetadataCount";
+ this.lMetadataCount.Size = new System.Drawing.Size(77, 16);
+ this.lMetadataCount.TabIndex = 9;
+ this.lMetadataCount.Text = "Metadata: 0";
+ //
+ // bGreyscale
+ //
+ this.bGreyscale.Location = new System.Drawing.Point(564, 121);
+ this.bGreyscale.Name = "bGreyscale";
+ this.bGreyscale.Size = new System.Drawing.Size(125, 28);
+ this.bGreyscale.TabIndex = 10;
+ this.bGreyscale.Text = "Conv to greyscale";
+ this.bGreyscale.UseVisualStyleBackColor = true;
+ this.bGreyscale.Click += new System.EventHandler(this.bGreyscale_Click);
+ //
+ // cbSelectFrame
+ //
+ this.cbSelectFrame.FormattingEnabled = true;
+ this.cbSelectFrame.Location = new System.Drawing.Point(695, 156);
+ this.cbSelectFrame.Name = "cbSelectFrame";
+ this.cbSelectFrame.Size = new System.Drawing.Size(121, 24);
+ this.cbSelectFrame.TabIndex = 11;
+ this.cbSelectFrame.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
+ //
+ // lComment
+ //
+ this.lComment.AutoSize = true;
+ this.lComment.Location = new System.Drawing.Point(563, 373);
+ this.lComment.Name = "lComment";
+ this.lComment.Size = new System.Drawing.Size(107, 16);
+ this.lComment.TabIndex = 12;
+ this.lComment.Text = "Image-comment:";
+ //
+ // bAdjustGamma
+ //
+ this.bAdjustGamma.Location = new System.Drawing.Point(564, 185);
+ this.bAdjustGamma.Name = "bAdjustGamma";
+ this.bAdjustGamma.Size = new System.Drawing.Size(125, 28);
+ this.bAdjustGamma.TabIndex = 13;
+ this.bAdjustGamma.Text = "Adjust gamma";
+ this.bAdjustGamma.UseVisualStyleBackColor = true;
+ this.bAdjustGamma.Click += new System.EventHandler(this.bAdjustGamma_Click);
+ //
+ // vGamma
+ //
+ this.vGamma.DecimalPlaces = 2;
+ this.vGamma.Increment = new decimal(new int[] {
+ 0,
+ 0,
+ 0,
+ 0});
+ this.vGamma.Location = new System.Drawing.Point(695, 189);
+ this.vGamma.Maximum = new decimal(new int[] {
+ 2,
+ 0,
+ 0,
+ 0});
+ this.vGamma.Name = "vGamma";
+ this.vGamma.Size = new System.Drawing.Size(121, 23);
+ this.vGamma.TabIndex = 14;
+ //
+ // bRedChannelOnly
+ //
+ this.bRedChannelOnly.Location = new System.Drawing.Point(564, 219);
+ this.bRedChannelOnly.Name = "bRedChannelOnly";
+ this.bRedChannelOnly.Size = new System.Drawing.Size(125, 28);
+ this.bRedChannelOnly.TabIndex = 15;
+ this.bRedChannelOnly.Text = "Red channel";
+ this.bRedChannelOnly.UseVisualStyleBackColor = true;
+ this.bRedChannelOnly.Click += new System.EventHandler(this.bRedChannelOnly_Click);
+ //
+ // bBlueChannel
+ //
+ this.bBlueChannel.Location = new System.Drawing.Point(564, 287);
+ this.bBlueChannel.Name = "bBlueChannel";
+ this.bBlueChannel.Size = new System.Drawing.Size(125, 28);
+ this.bBlueChannel.TabIndex = 16;
+ this.bBlueChannel.Text = "Blue channel";
+ this.bBlueChannel.UseVisualStyleBackColor = true;
+ this.bBlueChannel.Click += new System.EventHandler(this.bBlueChannel_Click);
+ //
+ // bGreenChannel
+ //
+ this.bGreenChannel.Location = new System.Drawing.Point(564, 253);
+ this.bGreenChannel.Name = "bGreenChannel";
+ this.bGreenChannel.Size = new System.Drawing.Size(125, 28);
+ this.bGreenChannel.TabIndex = 17;
+ this.bGreenChannel.Text = "Green channel";
+ this.bGreenChannel.UseVisualStyleBackColor = true;
+ this.bGreenChannel.Click += new System.EventHandler(this.bGreenChannel_Click);
+ //
+ // bAllChannels
+ //
+ this.bAllChannels.Location = new System.Drawing.Point(563, 321);
+ this.bAllChannels.Name = "bAllChannels";
+ this.bAllChannels.Size = new System.Drawing.Size(126, 28);
+ this.bAllChannels.TabIndex = 18;
+ this.bAllChannels.Text = "All channels";
+ this.bAllChannels.UseVisualStyleBackColor = true;
+ this.bAllChannels.Click += new System.EventHandler(this.bAllChannels_Click);
+ //
+ // lSelectFrame
+ //
+ this.lSelectFrame.AutoSize = true;
+ this.lSelectFrame.Location = new System.Drawing.Point(563, 159);
+ this.lSelectFrame.Name = "lSelectFrame";
+ this.lSelectFrame.Size = new System.Drawing.Size(86, 16);
+ this.lSelectFrame.TabIndex = 19;
+ this.lSelectFrame.Text = "Select frame:";
+ //
+ // lImageFormat
+ //
+ this.lImageFormat.AutoSize = true;
+ this.lImageFormat.Location = new System.Drawing.Point(563, 395);
+ this.lImageFormat.Name = "lImageFormat";
+ this.lImageFormat.Size = new System.Drawing.Size(92, 16);
+ this.lImageFormat.TabIndex = 20;
+ this.lImageFormat.Text = "Image-format:";
+ //
+ // bRotate
+ //
+ this.bRotate.Location = new System.Drawing.Point(564, 86);
+ this.bRotate.Name = "bRotate";
+ this.bRotate.Size = new System.Drawing.Size(125, 28);
+ this.bRotate.TabIndex = 21;
+ this.bRotate.Text = "Rotate";
+ this.bRotate.UseVisualStyleBackColor = true;
+ this.bRotate.Click += new System.EventHandler(this.bRotate_Click);
+ //
+ // vRotate
+ //
+ this.vRotate.Location = new System.Drawing.Point(695, 80);
+ this.vRotate.Maximum = 360;
+ this.vRotate.Name = "vRotate";
+ this.vRotate.Size = new System.Drawing.Size(170, 45);
+ this.vRotate.TabIndex = 22;
+ this.vRotate.TickFrequency = 10;
+ this.vRotate.TickStyle = System.Windows.Forms.TickStyle.Both;
+ this.vRotate.Scroll += new System.EventHandler(this.vRotate_Scroll);
+ //
+ // lRotate
+ //
+ this.lRotate.AutoSize = true;
+ this.lRotate.Location = new System.Drawing.Point(871, 92);
+ this.lRotate.Name = "lRotate";
+ this.lRotate.Size = new System.Drawing.Size(15, 16);
+ this.lRotate.TabIndex = 23;
+ this.lRotate.Text = "0";
+ //
+ // lColors
+ //
+ this.lColors.AutoSize = true;
+ this.lColors.Location = new System.Drawing.Point(740, 394);
+ this.lColors.Name = "lColors";
+ this.lColors.Size = new System.Drawing.Size(60, 16);
+ this.lColors.TabIndex = 24;
+ this.lColors.Text = "Colors: 0";
+ //
+ // nShowMetadata
+ //
+ this.nShowMetadata.Location = new System.Drawing.Point(696, 15);
+ this.nShowMetadata.Name = "nShowMetadata";
+ this.nShowMetadata.Size = new System.Drawing.Size(125, 28);
+ this.nShowMetadata.TabIndex = 25;
+ this.nShowMetadata.Text = "Show metadata";
+ this.nShowMetadata.UseVisualStyleBackColor = true;
+ this.nShowMetadata.Click += new System.EventHandler(this.nShowMetadata_Click);
+ //
+ // MainForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 16F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(908, 423);
+ this.Controls.Add(this.nShowMetadata);
+ this.Controls.Add(this.lColors);
+ this.Controls.Add(this.lRotate);
+ this.Controls.Add(this.vRotate);
+ this.Controls.Add(this.bRotate);
+ this.Controls.Add(this.lImageFormat);
+ this.Controls.Add(this.lSelectFrame);
+ this.Controls.Add(this.bAllChannels);
+ this.Controls.Add(this.bGreenChannel);
+ this.Controls.Add(this.bBlueChannel);
+ this.Controls.Add(this.bRedChannelOnly);
+ this.Controls.Add(this.vGamma);
+ this.Controls.Add(this.bAdjustGamma);
+ this.Controls.Add(this.lComment);
+ this.Controls.Add(this.cbSelectFrame);
+ this.Controls.Add(this.bGreyscale);
+ this.Controls.Add(this.lMetadataCount);
+ this.Controls.Add(this.lBpp);
+ this.Controls.Add(this.lHeight);
+ this.Controls.Add(this.lWidth);
+ this.Controls.Add(this.bSaveImage);
+ this.Controls.Add(this.bLoadImage);
+ this.Controls.Add(this.pictureBox);
+ this.DoubleBuffered = true;
+ this.Font = new System.Drawing.Font("Tahoma", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Margin = new System.Windows.Forms.Padding(4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "MainForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "Sample 11";
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.vGamma)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this.vRotate)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pictureBox;
+ private System.Windows.Forms.Button bLoadImage;
+ private System.Windows.Forms.Button bSaveImage;
+ private System.Windows.Forms.OpenFileDialog ofd;
+ private System.Windows.Forms.SaveFileDialog sfd;
+ private System.Windows.Forms.Label lWidth;
+ private System.Windows.Forms.Label lHeight;
+ private System.Windows.Forms.Label lBpp;
+ private System.Windows.Forms.Label lMetadataCount;
+ private System.Windows.Forms.Button bGreyscale;
+ private System.Windows.Forms.ComboBox cbSelectFrame;
+ private System.Windows.Forms.Label lComment;
+ private System.Windows.Forms.Button bAdjustGamma;
+ private System.Windows.Forms.NumericUpDown vGamma;
+ private System.Windows.Forms.Button bRedChannelOnly;
+ private System.Windows.Forms.Button bBlueChannel;
+ private System.Windows.Forms.Button bGreenChannel;
+ private System.Windows.Forms.Button bAllChannels;
+ private System.Windows.Forms.Label lSelectFrame;
+ private System.Windows.Forms.Label lImageFormat;
+ private System.Windows.Forms.Button bRotate;
+ private System.Windows.Forms.TrackBar vRotate;
+ private System.Windows.Forms.Label lRotate;
+ private System.Windows.Forms.Label lColors;
+ private System.Windows.Forms.Button nShowMetadata;
+ }
+}
+
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.cs
new file mode 100644
index 0000000..0cb9973
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.cs
@@ -0,0 +1,412 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using FreeImageAPI;
+using FreeImageAPI.Metadata;
+using FreeImageAPI.Plugins;
+
+namespace Sample11
+{
+ public partial class MainForm : Form
+ {
+ public MainForm()
+ {
+ InitializeComponent();
+ }
+
+ [STAThread]
+ static void Main()
+ {
+ // Capture messages generated by FreeImage
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImageEngine_Message);
+
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainForm());
+ }
+
+ static void FreeImageEngine_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ // Display the message
+ // FreeImage continues code executing when all
+ // addes subscribers of 'Message' finished returned.
+ MessageBox.Show(message, "FreeImage-Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+
+ // The FreeImageBitmap this sample will work with.
+ FreeImageBitmap bitmap = null;
+
+ // Replaces the current bitmap with the given one.
+ private void ReplaceBitmap(FreeImageBitmap newBitmap)
+ {
+ // Checks whether the bitmap is usable
+ if (newBitmap == null || newBitmap.IsDisposed)
+ {
+ MessageBox.Show(
+ "Unexpected error.",
+ "Error",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ }
+
+ // Check whether the image type of the new bitmap is 'FIT_BITMAP'.
+ // If not convert to 'FIT_BITMAP'.
+ if (newBitmap.ImageType != FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ if (!newBitmap.ConvertType(FREE_IMAGE_TYPE.FIT_BITMAP, true))
+ {
+ MessageBox.Show(
+ "Error converting bitmap to standard type.",
+ "Error",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ return;
+ }
+ }
+
+ // Dispose the old bitmap only in case it exists and
+ // the old instance is another than the new one.
+ if ((bitmap != null) && !object.ReferenceEquals(bitmap, newBitmap))
+ {
+ bitmap.Dispose();
+ }
+ // Dispose the picturebox's bitmap in case it exists.
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ }
+
+ // Set the new bitmap.
+ pictureBox.Image = (Bitmap)(bitmap = newBitmap);
+
+ // Update gui.
+ UpdateBitmapInformations();
+ UpdateFrameSelection();
+ }
+
+ // Get bitmap properties and display them in the gui.
+ private void UpdateBitmapInformations()
+ {
+ if (Bitmap)
+ {
+ // Get width
+ lWidth.Text = String.Format("Width: {0}", bitmap.Width);
+ // Get Height
+ lHeight.Text = String.Format("Height: {0}", bitmap.Height);
+ // Get color depth
+ lBpp.Text = String.Format("Bpp: {0}", bitmap.ColorDepth);
+ // Get number of metadata
+ ImageMetadata mData = bitmap.Metadata;
+ mData.HideEmptyModels = true;
+ int mCnt = 0;
+ foreach (MetadataModel model in mData.List)
+ {
+ mCnt += model.Count;
+ }
+ lMetadataCount.Text = String.Format("Metadata: {0}", mCnt);
+ // Get image comment
+ lComment.Text = String.Format("Image-comment: {0}", bitmap.Comment != null ? bitmap.Comment : String.Empty);
+ // Get the number of real colors in the image
+ lColors.Text = String.Format("Colors: {0}", bitmap.UniqueColors);
+ }
+ else
+ {
+ // Reset all values
+ lWidth.Text = String.Format("Width: {0}", 0);
+ lHeight.Text = String.Format("Height: {0}", 0);
+ lBpp.Text = String.Format("Bpp: {0}", 0);
+ lMetadataCount.Text = String.Format("Metadata: {0}", 0);
+ lComment.Text = String.Format("Image-comment: {0}", String.Empty);
+ lColors.Text = String.Format("Colors: {0}", 0);
+ }
+ }
+
+ // Update combobox for frame selection.
+ private void UpdateFrameSelection()
+ {
+ cbSelectFrame.Items.Clear();
+ if (Bitmap)
+ {
+ // Get number of frames in the bitmap
+ if (bitmap.FrameCount > 1)
+ {
+ // Add an entry for each frame to the combobox
+ for (int i = 0; i < bitmap.FrameCount; i++)
+ {
+ cbSelectFrame.Items.Add(String.Format("Frame {0}", i + 1));
+ }
+ }
+ }
+ }
+
+ // Returns true in case the variable 'bitmap'
+ // is set and not disposed.
+ private bool Bitmap
+ {
+ get { return ((bitmap != null) && (!bitmap.IsDisposed)); }
+ }
+
+ private void bLoadImage_Click(object sender, EventArgs e)
+ {
+ if (ofd.ShowDialog() == DialogResult.OK)
+ {
+ try
+ {
+ // Load the file using autodetection
+ FreeImageBitmap fib = new FreeImageBitmap(ofd.FileName);
+ // Rescale the image so that it fits the picturebox
+ // Get the plugin that was used to load the bitmap
+ FreeImagePlugin plug = PluginRepository.Plugin(fib.ImageFormat);
+ lImageFormat.Text = String.Format("Image-format: {0}", plug.Format);
+ // Replace the existing bitmap with the new one
+ ReplaceBitmap(fib);
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ private void bSaveImage_Click(object sender, EventArgs e)
+ {
+ if (pictureBox.Image != null)
+ {
+ try
+ {
+ if (sfd.ShowDialog() == DialogResult.OK)
+ {
+ // Save the bitmap using autodetection
+ using (FreeImageBitmap temp = new FreeImageBitmap(pictureBox.Image))
+ {
+ temp.Save(sfd.FileName);
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ private void bRotate_Click(object sender, EventArgs e)
+ {
+ if (Bitmap)
+ {
+ // Create a temporary rescaled bitmap
+ using (FreeImageBitmap temp = bitmap.GetScaledInstance(
+ pictureBox.DisplayRectangle.Width, pictureBox.DisplayRectangle.Height,
+ FREE_IMAGE_FILTER.FILTER_CATMULLROM))
+ {
+ if (temp != null)
+ {
+ // Rotate the bitmap
+ temp.Rotate((double)vRotate.Value);
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ }
+ // Display the result
+ pictureBox.Image = (Bitmap)temp;
+ }
+ }
+ }
+ }
+
+ private void bGreyscale_Click(object sender, EventArgs e)
+ {
+ if (Bitmap)
+ {
+ // Convert the bitmap to 8bpp and greyscale
+ ReplaceBitmap(bitmap.GetColorConvertedInstance(
+ FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP |
+ FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE));
+ }
+ }
+
+ private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ ComboBox cb = sender as ComboBox;
+ if ((cb != null) && (cb.Items.Count > 0))
+ {
+ if (Bitmap)
+ {
+ try
+ {
+ // Switch the selected frame
+ bitmap.SelectActiveFrame(cb.SelectedIndex);
+ ReplaceBitmap(bitmap);
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ MessageBox.Show("Error changing frame.", "Error");
+ }
+ }
+ }
+ }
+
+ private void bAdjustGamma_Click(object sender, EventArgs e)
+ {
+ if (Bitmap)
+ {
+ // Adjust the gamma value
+ bitmap.AdjustGamma((double)vGamma.Value);
+ ReplaceBitmap(bitmap);
+ }
+ }
+
+ private void bRedChannelOnly_Click(object sender, EventArgs e)
+ {
+ // Mask out green and blue
+ SetColorChannels(0xFF, 0x00, 0x00);
+ }
+
+ private void bGreenChannel_Click(object sender, EventArgs e)
+ {
+ // Mask out red and blue
+ SetColorChannels(0x00, 0xFF, 0x00);
+ }
+
+ private void bBlueChannel_Click(object sender, EventArgs e)
+ {
+ // Mask out red and green
+ SetColorChannels(0x00, 0x00, 0xFF);
+ }
+
+ private void bAllChannels_Click(object sender, EventArgs e)
+ {
+ if (Bitmap)
+ {
+ // Restore the bitmap using the original
+ ReplaceBitmap(bitmap);
+ }
+ }
+
+ private void SetColorChannels(int redmask, int greenmask, int bluemask)
+ {
+ if (Bitmap)
+ {
+ // Create a temporary clone.
+ using (FreeImageBitmap bitmap = (FreeImageBitmap)this.bitmap.Clone())
+ {
+ if (bitmap != null)
+ {
+ // Check whether the bitmap has a palette
+ if (bitmap.HasPalette)
+ {
+ // Use the Palette class to handle the bitmap's
+ // palette. A palette always consist of RGBQUADs.
+ Palette palette = bitmap.Palette;
+ // Apply the new values for all three color components.
+ for (int i = 0; i < palette.Length; i++)
+ {
+ RGBQUAD rgbq = palette[i];
+
+ rgbq.rgbRed = (byte)(rgbq.rgbRed & redmask);
+ rgbq.rgbGreen = (byte)(rgbq.rgbGreen & greenmask);
+ rgbq.rgbBlue = (byte)(rgbq.rgbBlue & bluemask);
+
+ palette[i] = rgbq;
+ }
+ }
+ // In case the bitmap has no palette it must have a color depth
+ // of 16, 24 or 32. Each color depth needs a different wrapping
+ // structure for the bitmaps data. These structures can be accessed
+ // by using the foreach clause.
+ else if (bitmap.ColorDepth == 16)
+ {
+ // Iterate over each scanline
+ // For 16bpp use either Scanline<FI16RGB555> or Scanline<FI16RGB565>
+ if (bitmap.IsRGB555)
+ {
+ foreach (Scanline<FI16RGB555> scanline in bitmap)
+ {
+ for (int x = 0; x < scanline.Length; x++)
+ {
+ FI16RGB555 pixel = scanline[x];
+ pixel.Red = (byte)(pixel.Red & redmask);
+ pixel.Green = (byte)(pixel.Green & greenmask);
+ pixel.Blue = (byte)(pixel.Blue & bluemask);
+ scanline[x] = pixel;
+ }
+ }
+ }
+ else if (bitmap.IsRGB565)
+ {
+ foreach (Scanline<FI16RGB565> scanline in bitmap)
+ {
+ for (int x = 0; x < scanline.Length; x++)
+ {
+ FI16RGB565 pixel = scanline[x];
+ pixel.Red = (byte)(pixel.Red & redmask);
+ pixel.Green = (byte)(pixel.Green & greenmask);
+ pixel.Blue = (byte)(pixel.Blue & bluemask);
+ scanline[x] = pixel;
+ }
+ }
+ }
+ }
+ else if (bitmap.ColorDepth == 24)
+ {
+ // Iterate over each scanline
+ // For 24bpp Scanline<RGBTRIPLE> must be used
+ foreach (Scanline<RGBTRIPLE> scanline in bitmap)
+ {
+ for (int x = 0; x < scanline.Length; x++)
+ {
+ RGBTRIPLE pixel = scanline[x];
+ pixel.rgbtRed = (byte)(pixel.rgbtRed & redmask);
+ pixel.rgbtGreen = (byte)(pixel.rgbtGreen & greenmask);
+ pixel.rgbtBlue = (byte)(pixel.rgbtBlue & bluemask);
+ scanline[x] = pixel;
+ }
+ }
+ }
+ else if (bitmap.ColorDepth == 32)
+ {
+ // Iterate over each scanline
+ // For 32bpp Scanline<RGBQUAD> must be used
+ foreach (Scanline<RGBQUAD> scanline in bitmap)
+ {
+ for (int x = 0; x < scanline.Length; x++)
+ {
+ RGBQUAD pixel = scanline[x];
+ pixel.rgbRed = (byte)(pixel.rgbRed & redmask);
+ pixel.rgbGreen = (byte)(pixel.rgbGreen & greenmask);
+ pixel.rgbBlue = (byte)(pixel.rgbBlue & bluemask);
+ scanline[x] = pixel;
+ }
+ }
+ }
+ // Dispose only the picturebox's bitmap
+ if (pictureBox.Image != null)
+ {
+ pictureBox.Image.Dispose();
+ }
+ pictureBox.Image = (Bitmap)bitmap;
+ }
+ }
+ }
+ }
+
+ private void vRotate_Scroll(object sender, EventArgs e)
+ {
+ TrackBar bar = sender as TrackBar;
+ if (bar != null)
+ {
+ lRotate.Text = bar.Value.ToString();
+ }
+ }
+
+ private void nShowMetadata_Click(object sender, EventArgs e)
+ {
+ if (Bitmap)
+ {
+ MetaDataFrame mFrame = new MetaDataFrame();
+ mFrame.Tag = bitmap.Metadata;
+ mFrame.ShowDialog(this);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.resx
new file mode 100644
index 0000000..5becef4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MainForm.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <metadata name="ofd.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>17, 17</value>
+ </metadata>
+ <metadata name="sfd.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+ <value>84, 17</value>
+ </metadata>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.Designer.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.Designer.cs
new file mode 100644
index 0000000..15077c9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.Designer.cs
@@ -0,0 +1,63 @@
+namespace Sample11
+{
+ partial class MetaDataFrame
+ {
+ /// <summary>
+ /// Erforderliche Designervariable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Verwendete Ressourcen bereinigen.
+ /// </summary>
+ /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ /// <summary>
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.tvMetadata = new System.Windows.Forms.TreeView();
+ this.SuspendLayout();
+ //
+ // tvMetadata
+ //
+ this.tvMetadata.Location = new System.Drawing.Point(12, 12);
+ this.tvMetadata.Name = "tvMetadata";
+ this.tvMetadata.Size = new System.Drawing.Size(389, 318);
+ this.tvMetadata.TabIndex = 3;
+ //
+ // MetaDataFrame
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(417, 349);
+ this.Controls.Add(this.tvMetadata);
+ this.DoubleBuffered = true;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "MetaDataFrame";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Metadata";
+ this.Load += new System.EventHandler(this.MetaDataFrame_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TreeView tvMetadata;
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.cs
new file mode 100644
index 0000000..57ba257
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.cs
@@ -0,0 +1,49 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using FreeImageAPI;
+using FreeImageAPI.Metadata;
+
+namespace Sample11
+{
+ public partial class MetaDataFrame : Form
+ {
+ public MetaDataFrame()
+ {
+ InitializeComponent();
+ }
+
+ private void MetaDataFrame_Load(object sender, EventArgs e)
+ {
+ ImageMetadata iMetadata = this.Tag as ImageMetadata;
+ if (iMetadata != null)
+ {
+ bool backup = iMetadata.HideEmptyModels;
+ iMetadata.HideEmptyModels = false;
+ try
+ {
+ // Get each metadata model
+ foreach (MetadataModel metadataModel in iMetadata)
+ {
+ // Create a new node for each model
+ TreeNode modelNode = tvMetadata.Nodes.Add(metadataModel.ToString());
+
+ // Get each metadata tag and create a subnode for it
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ modelNode.Nodes.Add(metadataTag.Key + ": " + metadataTag.ToString());
+ }
+ }
+ }
+ // Display error message
+ catch (Exception ex)
+ {
+ while (ex.InnerException != null)
+ ex = ex.InnerException;
+ MessageBox.Show(ex.ToString(), "Exception caught");
+ }
+ iMetadata.HideEmptyModels = backup;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.resx b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.resx
new file mode 100644
index 0000000..ff31a6d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/MetaDataFrame.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..645371f
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("219019e1-9a57-46c7-b9d7-3928a9277fd6")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Sample 11 - Using the FreeImageBitmap class.csproj b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Sample 11 - Using the FreeImageBitmap class.csproj
new file mode 100644
index 0000000..e864616
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Samples/Sample 11 - Using the FreeImageBitmap class/Sample 11 - Using the FreeImageBitmap class.csproj
@@ -0,0 +1,115 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{996068CD-D07A-42E0-856F-ACC71E8565EF}</ProjectGuid>
+ <OutputType>WinExe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Sample11</RootNamespace>
+ <AssemblyName>Sample11</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <FileAlignment>512</FileAlignment>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Windows.Forms" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="MainForm.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="MainForm.Designer.cs">
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </Compile>
+ <Compile Include="MetaDataFrame.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ <Compile Include="MetaDataFrame.Designer.cs">
+ <DependentUpon>MetaDataFrame.cs</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <EmbeddedResource Include="MainForm.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>MainForm.cs</DependentUpon>
+ </EmbeddedResource>
+ <EmbeddedResource Include="MetaDataFrame.resx">
+ <SubType>Designer</SubType>
+ <DependentUpon>MetaDataFrame.cs</DependentUpon>
+ </EmbeddedResource>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Library\Library.csproj">
+ <Project>{6598A7CD-8F27-4D3F-A675-5AE63113A7C3}</Project>
+ <Name>Library</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/SourceFileMerger/FreeImage.cs.template b/Wrapper/FreeImage.NET/cs/SourceFileMerger/FreeImage.cs.template
new file mode 100644
index 0000000..f02974d
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/SourceFileMerger/FreeImage.cs.template
@@ -0,0 +1,219 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// To build the project without VS use the following commandline:
+// "csc.exe /out:FreeImageNET.dll /target:library /doc:FreeImageNET.XML /debug- /o /unsafe+ /filealign:512 FreeImage.cs"
+// ==========================================================
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using FreeImageAPI;
+using FreeImageAPI.IO;
+using FreeImageAPI.Metadata;
+using FreeImageAPI.Plugins;
+
+/////////////////////////////////////////////////////
+// //
+// FreeImage.h import //
+// //
+/////////////////////////////////////////////////////
+
+ #region Structs
+
+#include "Structs\BITMAP.cs"
+
+#include "Structs\BITMAPINFOHEADER.cs"
+
+#include "Structs\BITMAPINFO.cs"
+
+#include "Structs\FIBITMAP.cs"
+
+#include "Structs\FIMULTIBITMAP.cs"
+
+#include "Structs\FIMEMORY.cs"
+
+#include "Structs\FIMETADATA.cs"
+
+#include "Structs\FITAG.cs"
+
+#include "Structs\FreeImageIO.cs"
+
+#include "Structs\RGBQUAD.cs"
+
+#include "Structs\RGBTRIPLE.cs"
+
+#include "Structs\FIRGBA16.cs"
+
+#include "Structs\FIRGB16.cs"
+
+#include "Structs\FIRGBAF.cs"
+
+#include "Structs\FIRGBF.cs"
+
+#include "Structs\FICOMPLEX.cs"
+
+#include "Structs\FIICCPROFILE.cs"
+
+#include "Structs\Plugin.cs"
+
+ #endregion
+
+ #region Enums
+
+#include "Enumerations\DisposalMethodType.cs"
+
+#include "Enumerations\FREE_IMAGE_FORMAT.cs"
+
+#include "Enumerations\FREE_IMAGE_TYPE.cs"
+
+#include "Enumerations\FREE_IMAGE_COLOR_OPTIONS.cs"
+
+#include "Enumerations\FREE_IMAGE_COLOR_TYPE.cs"
+
+#include "Enumerations\FREE_IMAGE_QUANTIZE.cs"
+
+#include "Enumerations\FREE_IMAGE_DITHER.cs"
+
+#include "Enumerations\FREE_IMAGE_JPEG_OPERATION.cs"
+
+#include "Enumerations\FREE_IMAGE_TMO.cs"
+
+#include "Enumerations\FREE_IMAGE_FILTER.cs"
+
+#include "Enumerations\FREE_IMAGE_COLOR_CHANNEL.cs"
+
+#include "Enumerations\FREE_IMAGE_MDTYPE.cs"
+
+#include "Enumerations\FREE_IMAGE_MDMODEL.cs"
+
+#include "Enumerations\FREE_IMAGE_LOAD_FLAGS.cs"
+
+#include "Enumerations\FREE_IMAGE_SAVE_FLAGS.cs"
+
+#include "Enumerations\ICC_FLAGS.cs"
+
+ #endregion
+
+ #region Delegates
+
+#include "Delegates.cs"
+
+ #endregion
+
+#include "FreeImageStaticImports.cs"
+
+/////////////////////////////////////////////////////
+// //
+// Wrapper functions //
+// //
+/////////////////////////////////////////////////////
+
+ #region Structs
+
+#include "Structs\fi_handle.cs"
+
+#include "Structs\FI1BIT.cs"
+
+#include "Structs\FI4BIT.cs"
+
+#include "Structs\FI16RGB555.cs"
+
+#include "Structs\FI16RGB565.cs"
+
+#include "Structs\FIRational.cs"
+
+#include "Structs\FIURational.cs"
+
+ #endregion
+
+ #region Classes
+
+#include "Classes\FreeImageBitmap.cs"
+
+#include "Classes\FreeImageEngine.cs"
+
+#include "Classes\FreeImagePlugin.cs"
+
+#include "Classes\FreeImageStreamIO.cs"
+
+#include "Classes\GifInformation.cs"
+
+#include "Classes\ImageMetadata.cs"
+
+#include "Classes\LocalPlugin.cs"
+
+#include "Classes\MemoryArray.cs"
+
+#include "Classes\MetadataModel.cs"
+
+ #region Metadata Models
+
+ #include "Classes\MetadataModels.cs"
+
+ #endregion
+
+#include "Classes\MetadataTag.cs"
+
+#include "Classes\Palette.cs"
+
+#include "Classes\PluginRepository.cs"
+
+#include "Classes\Scanline.cs"
+
+#include "Classes\StreamWrapper.cs"
+
+ #endregion
+
+ #region Enums
+
+#include "Enumerations\FREE_IMAGE_COLOR_DEPTH.cs"
+
+#include "Enumerations\FREE_IMAGE_COMPARE_FLAGS.cs"
+
+#include "Enumerations\FREE_IMAGE_METADATA_COPY.cs"
+
+#include "Enumerations\MD_SEARCH_FLAGS.cs"
+
+ #endregion
+
+#include "FreeImageWrapper.cs" \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/SourceFileMerger/Program.cs b/Wrapper/FreeImage.NET/cs/SourceFileMerger/Program.cs
new file mode 100644
index 0000000..7daa066
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/SourceFileMerger/Program.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace FreeImageNET_SFM
+{
+ class Program
+ {
+ static private Regex searchPattern = new Regex("#include[ \\t]*\"(.*)\"", RegexOptions.Compiled);
+ static private FileStream fStream = null;
+ static private TextWriter textOut = null;
+ private const string baseFolder = @"..\..\..\Library\";
+ private const string templateName = @"FreeImage.cs.template";
+
+ static int Main(string[] args)
+ {
+ try
+ {
+ if (!File.Exists(templateName))
+ {
+ Console.WriteLine(templateName + " not found."); return 1;
+ }
+
+ try
+ {
+ fStream = new FileStream(@"FreeImage.cs", FileMode.Create);
+ }
+ catch
+ {
+ Console.WriteLine("Unable to create output file."); return 2;
+ }
+
+ textOut = new StreamWriter(fStream);
+
+ string[] content = File.ReadAllLines(templateName);
+
+ for (int lineNumber = 0; lineNumber < content.Length; lineNumber++)
+ {
+ string line = content[lineNumber].Trim();
+ Match match = searchPattern.Match(line);
+
+ if (match.Success && match.Groups.Count == 2 && match.Groups[1].Value != null)
+ {
+ if (!File.Exists(baseFolder + match.Groups[1].Value))
+ {
+ throw new FileNotFoundException(baseFolder + match.Groups[1].Value + " does not exist.");
+ }
+
+ ParseFile(baseFolder + match.Groups[1].Value);
+ }
+ else
+ {
+ textOut.WriteLine(content[lineNumber]);
+ }
+ }
+
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.ToString());
+ //Console.WriteLine("Error while parsing.");
+ return 3;
+ }
+ finally
+ {
+ if (textOut != null)
+ {
+ textOut.Flush();
+ textOut.Close();
+ }
+ }
+ }
+
+ private static void ParseFile(string fileName)
+ {
+ int lineNumber = 0;
+ string line;
+ Match match;
+ string[] content = File.ReadAllLines(fileName);
+
+ if (fileName.Contains("AssemblyInfo.cs"))
+ {
+ while (content[lineNumber].Trim().StartsWith("using") && lineNumber < content.Length)
+ {
+ lineNumber++;
+ }
+ lineNumber++;
+ }
+ else
+ {
+ while (!(content[lineNumber].Trim().StartsWith("namespace")) && lineNumber < content.Length)
+ {
+ lineNumber++;
+ }
+ //lineNumber += 2;
+ }
+
+ for (; lineNumber < content.Length; lineNumber++)
+ {
+ line = content[lineNumber].Trim();
+ match = searchPattern.Match(line);
+
+ if (match.Success && match.Groups.Count == 2 && match.Groups[1].Value != null)
+ {
+ if (!File.Exists(baseFolder + match.Groups[1].Value))
+ {
+ throw new FileNotFoundException(baseFolder + match.Groups[1].Value + " does not exist.");
+ }
+
+ ParseFile(baseFolder + match.Groups[1].Value);
+ }
+ else
+ {
+ textOut.WriteLine(content[lineNumber]);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/SourceFileMerger/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/SourceFileMerger/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ff214a9
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/SourceFileMerger/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("4fcae9f3-1b12-4137-9c5b-047124da37e9")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/SourceFileMerger/SourceFileMerger.csproj b/Wrapper/FreeImage.NET/cs/SourceFileMerger/SourceFileMerger.csproj
new file mode 100644
index 0000000..6bc856b
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/SourceFileMerger/SourceFileMerger.csproj
@@ -0,0 +1,97 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{2AD35641-C1EA-492C-B081-F4AA5AAE8FA1}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>FreeImageNET_SFM</RootNamespace>
+ <AssemblyName>sourcefilemerger</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>none</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <FileAlignment>512</FileAlignment>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <Optimize>true</Optimize>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>none</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="FreeImage.cs.template">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+ <PropertyGroup>
+ <PostBuildEvent>
+ </PostBuildEvent>
+ </PropertyGroup>
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/FreeImage.cs b/Wrapper/FreeImage.NET/cs/UnitTest/FreeImage.cs
new file mode 100644
index 0000000..2e07db4
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/FreeImage.cs
@@ -0,0 +1,30578 @@
+// ==========================================================
+// FreeImage 3 .NET wrapper
+// Original FreeImage 3 functions and .NET compatible derived functions
+//
+// Design and implementation by
+// - Jean-Philippe Goerke (jpgoerke@users.sourceforge.net)
+// - Carsten Klein (cklein05@users.sourceforge.net)
+//
+// Contributors:
+// - David Boland (davidboland@vodafone.ie)
+//
+// Main reference : MSDN Knowlede Base
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+// ==========================================================
+// To build the project without VS use the following commandline:
+// "csc.exe /out:FreeImageNET.dll /target:library /doc:FreeImageNET.XML /debug- /o /unsafe+ /filealign:512 FreeImage.cs"
+// ==========================================================
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using FreeImageAPI;
+using FreeImageAPI.IO;
+using FreeImageAPI.Metadata;
+using FreeImageAPI.Plugins;
+
+/////////////////////////////////////////////////////
+// //
+// FreeImage.h import //
+// //
+/////////////////////////////////////////////////////
+
+ #region Structs
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>BITMAP</b> structure defines the type, width, height, color format, and bit values of a bitmap.
+ /// </summary>
+ /// <remarks>
+ /// The bitmap formats currently used are monochrome and color. The monochrome bitmap uses a one-bit,
+ /// one-plane format. Each scan is a multiple of 32 bits.
+ /// <para/>
+ /// Scans are organized as follows for a monochrome bitmap of height n:
+ /// <para/>
+ /// <code>
+ /// Scan 0
+ /// Scan 1
+ /// .
+ /// .
+ /// .
+ /// Scan n-2
+ /// Scan n-1
+ /// </code>
+ /// <para/>
+ /// The pixels on a monochrome device are either black or white. If the corresponding bit in the
+ /// bitmap is 1, the pixel is set to the foreground color; if the corresponding bit in the bitmap
+ /// is zero, the pixel is set to the background color.
+ /// <para/>
+ /// All devices that have the RC_BITBLT device capability support bitmaps. For more information,
+ /// see <b>GetDeviceCaps</b>.
+ /// <para/>
+ /// Each device has a unique color format. To transfer a bitmap from one device to another,
+ /// use the <b>GetDIBits</b> and <b>SetDIBits</b> functions.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAP
+ {
+ /// <summary>
+ /// Specifies the bitmap type. This member must be zero.
+ /// </summary>
+ public int bmType;
+ /// <summary>
+ /// Specifies the width, in pixels, of the bitmap. The width must be greater than zero.
+ /// </summary>
+ public int bmWidth;
+ /// <summary>
+ /// Specifies the height, in pixels, of the bitmap. The height must be greater than zero.
+ /// </summary>
+ public int bmHeight;
+ /// <summary>
+ /// Specifies the number of bytes in each scan line. This value must be divisible by 2,
+ /// because the system assumes that the bit values of a bitmap form an array that is word aligned.
+ /// </summary>
+ public int bmWidthBytes;
+ /// <summary>
+ /// Specifies the count of color planes.
+ /// </summary>
+ public ushort bmPlanes;
+ /// <summary>
+ /// Specifies the number of bits required to indicate the color of a pixel.
+ /// </summary>
+ public ushort bmBitsPixel;
+ /// <summary>
+ /// Pointer to the location of the bit values for the bitmap.
+ /// The <b>bmBits</b> member must be a long pointer to an array of character (1-byte) values.
+ /// </summary>
+ public IntPtr bmBits;
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// This structure contains information about the dimensions and color format
+ /// of a device-independent bitmap (DIB).
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="FreeImageAPI.BITMAPINFO"/> structure combines the
+ /// <b>BITMAPINFOHEADER</b> structure and a color table to provide a complete
+ /// definition of the dimensions and colors of a DIB.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAPINFOHEADER : IEquatable<BITMAPINFOHEADER>
+ {
+ /// <summary>
+ /// Specifies the size of the structure, in bytes.
+ /// </summary>
+ public uint biSize;
+ /// <summary>
+ /// Specifies the width of the bitmap, in pixels.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// the <b>biWidth</b> member specifies the width of the decompressed JPEG or PNG image file,
+ /// respectively.
+ /// </summary>
+ public int biWidth;
+ /// <summary>
+ /// Specifies the height of the bitmap, in pixels. If <b>biHeight</b> is positive, the bitmap
+ /// is a bottom-up DIB and its origin is the lower-left corner. If <b>biHeight</b> is negative,
+ /// the bitmap is a top-down DIB and its origin is the upper-left corner.
+ /// <para/>
+ /// If <b>biHeight</b> is negative, indicating a top-down DIB, <b>biCompression</b> must be
+ /// either BI_RGB or BI_BITFIELDS. Top-down DIBs cannot be compressed.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// the <b>biHeight</b> member specifies the height of the decompressed JPEG or PNG image file,
+ /// respectively.
+ /// </summary>
+ public int biHeight;
+ /// <summary>
+ /// Specifies the number of planes for the target device. This value must be set to 1.
+ /// </summary>
+ public ushort biPlanes;
+ /// <summary>
+ /// Specifies the number of bits per pixel.The biBitCount member of the <b>BITMAPINFOHEADER</b>
+ /// structure determines the number of bits that define each pixel and the maximum number of
+ /// colors in the bitmap. This member must be one of the following values.
+ /// <para/>
+ ///
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>0</term>
+ /// <description>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> The number of bits-per-pixel is specified
+ /// or is implied by the JPEG or PNG format.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>1</term>
+ /// <description>
+ /// The bitmap is monochrome, and the bmiColors member of <see cref="FreeImageAPI.BITMAPINFO"/>
+ /// contains two entries. Each bit in the bitmap array represents a pixel. If the bit is clear,
+ /// the pixel is displayed with the color of the first entry in the bmiColors table; if the bit
+ /// is set, the pixel has the color of the second entry in the table.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>4</term>
+ /// <description>
+ /// The bitmap has a maximum of 16 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// contains up to 16 entries. Each pixel in the bitmap is represented by a 4-bit index into the
+ /// color table. For example, if the first byte in the bitmap is 0x1F, the byte represents two
+ /// pixels. The first pixel contains the color in the second table entry, and the second pixel
+ /// contains the color in the sixteenth table entry.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>8</term>
+ /// <description>
+ /// The bitmap has a maximum of 256 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// contains up to 256 entries. In this case, each byte in the array represents a single pixel.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>16</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^16 colors. If the <b>biCompression</b> member of the
+ /// <b>BITMAPINFOHEADER</b> is BI_RGB, the <b>bmiColors</b> member of <b>BITMAPINFO</b> is NULL.
+ /// Each <b>WORD</b> in the bitmap array represents a single pixel. The relative intensities
+ /// of red, green, and blue are represented with five bits for each color component.
+ /// The value for blue is in the least significant five bits, followed by five bits each for
+ /// green and red. The most significant bit is not used. The <b>bmiColors</b> color table is used
+ /// for optimizing colors used on palette-based devices, and must contain the number of entries
+ /// specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// <para/>
+ /// If the <b>biCompression</b> member of the <b>BITMAPINFOHEADER</b> is BI_BITFIELDS, the
+ /// <b>bmiColors</b> member contains three <b>DWORD</b> color masks that specify the red, green,
+ /// and blue components, respectively, of each pixel. Each <b>WORD</b> in the bitmap array represents
+ /// a single pixel.
+ /// <para/>
+ /// <b>Windows NT/Windows 2000/XP:</b> When the <b>biCompression</b> member is BI_BITFIELDS,
+ /// bits set in each <b>DWORD</b> mask must be contiguous and should not overlap the bits
+ /// of another mask. All the bits in the pixel do not have to be used.
+ /// <para/>
+ /// <b>Windows 95/98/Me:</b> When the <b>biCompression</b> member is BI_BITFIELDS, the system
+ /// supports only the following 16bpp color masks: A 5-5-5 16-bit image, where the blue mask is
+ /// 0x001F, the green mask is 0x03E0, and the red mask is 0x7C00; and a 5-6-5 16-bit image,
+ /// where the blue mask is 0x001F, the green mask is 0x07E0, and the red mask is 0xF800.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>24</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^24 colors, and the <b>bmiColors</b> member of <b>BITMAPINFO</b>
+ /// is NULL. Each 3-byte triplet in the bitmap array represents the relative intensities of blue,
+ /// green, and red, respectively, for a pixel. The <b>bmiColors</b> color table is used for
+ /// optimizing colors used on palette-based devices, and must contain the number of entries
+ /// specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>32</term>
+ /// <description>
+ /// The bitmap has a maximum of 2^32 colors. If the <b>biCompression</b> member of the
+ /// <b>BITMAPINFOHEADER</b> is BI_RGB, the <b>bmiColors</b> member of <b>BITMAPINFO</b> is NULL.
+ /// Each <b>DWORD</b> in the bitmap array represents the relative intensities of blue, green, and red,
+ /// respectively, for a pixel. The high byte in each <b>DWORD</b> is not used. The <b>bmiColors</b>
+ /// color table is used for optimizing colors used on palette-based devices, and must contain the
+ /// number of entries specified by the <b>biClrUsed</b> member of the <b>BITMAPINFOHEADER</b>.
+ /// <para/>
+ /// If the <b>biCompression</b> member of the <b>BITMAPINFOHEADER</b> is BI_BITFIELDS,
+ /// the <b>bmiColors</b> member contains three <b>DWORD</b> color masks that specify the red, green,
+ /// and blue components, respectively, of each pixel. Each <b>DWORD</b> in the bitmap array represents
+ /// a single pixel.
+ /// <para/>
+ /// <b>Windows NT/ 2000:</b> When the <b>biCompression</b> member is BI_BITFIELDS, bits set in each
+ /// <b>DWORD</b> mask must be contiguous and should not overlap the bits of another mask. All the
+ /// bits in the pixel do not need to be used.
+ /// <para/>
+ /// <b>Windows 95/98/Me:</b> When the <b>biCompression</b> member is BI_BITFIELDS, the system
+ /// supports only the following 32-bpp color mask: The blue mask is 0x000000FF, the green mask is
+ /// 0x0000FF00, and the red mask is 0x00FF0000.
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </summary>
+ public ushort biBitCount;
+ /// <summary>
+ /// Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be
+ /// compressed).
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ ///
+ /// <item>
+ /// <term>BI_RGB</term>
+ /// <description>An uncompressed format.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_RLE8</term>
+ /// <description>A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format
+ /// is a 2-byte format consisting of a count byte followed by a byte containing a color index.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_RLE4</term>
+ /// <description>An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format
+ /// consisting of a count byte followed by two word-length color indexes.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_BITFIELDS</term>
+ /// <description>Specifies that the bitmap is not compressed and that the color table consists
+ /// of three <b>DWORD</b> color masks that specify the red, green, and blue components, respectively,
+ /// of each pixel. This is valid when used with 16- and 32-bpp bitmaps.</description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_JPEG</term>
+ /// <description><b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a JPEG image.
+ /// </description>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>BI_PNG</term>
+ /// <description><b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a PNG image.
+ /// </description>
+ /// </item>
+ ///
+ /// </list>
+ /// </summary>
+ public uint biCompression;
+ /// <summary>
+ /// Specifies the size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
+ /// <para/>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> If <b>biCompression</b> is BI_JPEG or BI_PNG,
+ /// <b>biSizeImage</b> indicates the size of the JPEG or PNG image buffer, respectively.
+ /// </summary>
+ public uint biSizeImage;
+ /// <summary>
+ /// Specifies the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// An application can use this value to select a bitmap from a resource group that best matches
+ /// the characteristics of the current device.
+ /// </summary>
+ public int biXPelsPerMeter;
+ /// <summary>
+ /// Specifies the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ public int biYPelsPerMeter;
+ /// <summary>
+ /// Specifies the number of color indexes in the color table that are actually used by the bitmap.
+ /// If this value is zero, the bitmap uses the maximum number of colors corresponding to the value
+ /// of the biBitCount member for the compression mode specified by <b>biCompression</b>.
+ /// <para/>
+ /// If <b>iClrUsed</b> is nonzero and the <b>biBitCount</b> member is less than 16, the <b>biClrUsed</b>
+ /// member specifies the actual number of colors the graphics engine or device driver accesses.
+ /// If <b>biBitCount</b> is 16 or greater, the <b>biClrUsed</b> member specifies the size of the color
+ /// table used to optimize performance of the system color palettes. If <b>biBitCount</b> equals 16 or 32,
+ /// the optimal color palette starts immediately following the three <b>DWORD</b> masks.
+ /// <para/>
+ /// When the bitmap array immediately follows the <see cref="BITMAPINFO"/> structure, it is a packed bitmap.
+ /// Packed bitmaps are referenced by a single pointer. Packed bitmaps require that the
+ /// <b>biClrUsed</b> member must be either zero or the actual size of the color table.
+ /// </summary>
+ public uint biClrUsed;
+ /// <summary>
+ /// Specifies the number of color indexes that are required for displaying the bitmap. If this value
+ /// is zero, all colors are required.
+ /// </summary>
+ public uint biClrImportant;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFOHEADER"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFOHEADER"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFOHEADER"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFOHEADER"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(BITMAPINFOHEADER left, BITMAPINFOHEADER right)
+ {
+ return ((left.biSize == right.biSize) &&
+ (left.biWidth == right.biWidth) &&
+ (left.biHeight == right.biHeight) &&
+ (left.biPlanes == right.biPlanes) &&
+ (left.biBitCount == right.biBitCount) &&
+ (left.biCompression == right.biCompression) &&
+ (left.biSizeImage == right.biSizeImage) &&
+ (left.biXPelsPerMeter == right.biXPelsPerMeter) &&
+ (left.biYPelsPerMeter == right.biYPelsPerMeter) &&
+ (left.biClrUsed == right.biClrUsed) &&
+ (left.biClrImportant == right.biClrImportant));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFOHEADER"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFOHEADER"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFOHEADER"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFOHEADER"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(BITMAPINFOHEADER left, BITMAPINFOHEADER right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="BITMAPINFOHEADER"/> structure is equivalent to this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="BITMAPINFOHEADER"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFOHEADER"/> structure
+ /// equivalent to this <see cref="BITMAPINFOHEADER"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(BITMAPINFOHEADER other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="BITMAPINFOHEADER"/> structure
+ /// and is equivalent to this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFOHEADER"/> structure
+ /// equivalent to this <see cref="BITMAPINFOHEADER"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is BITMAPINFOHEADER) && (this == (BITMAPINFOHEADER)obj));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="BITMAPINFOHEADER"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="BITMAPINFOHEADER"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>BITMAPINFO</b> structure defines the dimensions and color information for a DIB.
+ /// </summary>
+ /// <remarks>
+ /// A DIB consists of two distinct parts: a <b>BITMAPINFO</b> structure describing the dimensions
+ /// and colors of the bitmap, and an array of bytes defining the pixels of the bitmap. The bits in
+ /// the array are packed together, but each scan line must be padded with zeroes to end on a
+ /// <b>LONG</b> data-type boundary. If the height of the bitmap is positive, the bitmap is a
+ /// bottom-up DIB and its origin is the lower-left corner. If the height is negative, the bitmap is
+ /// a top-down DIB and its origin is the upper left corner.
+ /// <para/>
+ /// A bitmap is packed when the bitmap array immediately follows the <b>BITMAPINFO</b> header.
+ /// Packed bitmaps are referenced by a single pointer. For packed bitmaps, the <b>biClrUsed</b>
+ /// member must be set to an even number when using the DIB_PAL_COLORS mode so that the DIB bitmap
+ /// array starts on a <b>DWORD</b> boundary.
+ /// <para/>
+ /// <b>Note</b> The <b>bmiColors</b> member should not contain palette indexes if the bitmap is to
+ /// be stored in a file or transferred to another application.
+ /// <para/>
+ /// Unless the application has exclusive use and control of the bitmap, the bitmap color table
+ /// should contain explicit RGB values.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct BITMAPINFO : IEquatable<BITMAPINFO>
+ {
+ /// <summary>
+ /// Specifies a <see cref="FreeImageAPI.BITMAPINFOHEADER"/> structure that contains information
+ /// about the dimensions of color format.
+ /// </summary>
+ public BITMAPINFOHEADER bmiHeader;
+ /// <summary>
+ /// The <b>bmiColors</b> member contains one of the following:
+ /// <list type="bullets">
+ ///
+ /// <item>
+ /// <term>
+ /// An array of <see cref="FreeImageAPI.RGBQUAD"/>. The elements of the array that make up the
+ /// color table.
+ /// </term>
+ /// </item>
+ ///
+ /// <item>
+ /// <term>
+ /// An array of 16-bit unsigned integers that specifies indexes into the currently realized
+ /// logical palette. This use of <b>bmiColors</b> is allowed for functions that use DIBs.
+ /// When <b>bmiColors</b> elements contain indexes to a realized logical palette, they must
+ /// also call the following bitmap functions:
+ /// </term>
+ /// </item>
+ ///
+ /// </list>
+ /// <b>CreateDIBitmap</b>
+ /// <para/>
+ /// <b>CreateDIBPatternBrush</b>
+ /// <para/>
+ /// <b>CreateDIBSection</b>
+ /// <para/>
+ /// The <i>iUsage</i> parameter of CreateDIBSection must be set to DIB_PAL_COLORS.
+ /// <para/>
+ /// The number of entries in the array depends on the values of the <b>biBitCount</b> and
+ /// <b>biClrUsed</b> members of the <see cref="FreeImageAPI.BITMAPINFOHEADER"/> structure.
+ /// <para/>
+ /// The colors in the <b>bmiColors</b> table appear in order of importance. For more information,
+ /// see the Remarks section.
+ /// </summary>
+ public RGBQUAD[] bmiColors;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFO"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFO"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFO"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFO"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(BITMAPINFO left, BITMAPINFO right)
+ {
+ if (left.bmiHeader != right.bmiHeader)
+ {
+ return false;
+ }
+ if ((left.bmiColors == null) && (right.bmiColors == null))
+ {
+ return true;
+ }
+ if ((left.bmiColors == null) || (right.bmiColors == null))
+ {
+ return false;
+ }
+ if (left.bmiColors.Length != right.bmiColors.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < left.bmiColors.Length; i++)
+ {
+ if (left.bmiColors[i] != right.bmiColors[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="BITMAPINFO"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="BITMAPINFO"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="BITMAPINFO"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="BITMAPINFO"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(BITMAPINFO left, BITMAPINFO right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="BITMAPINFO"/> structure is equivalent to this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="BITMAPINFO"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFO"/> structure
+ /// equivalent to this <see cref="BITMAPINFO"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(BITMAPINFO other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="BITMAPINFO"/> structure
+ /// and is equivalent to this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="BITMAPINFO"/> structure
+ /// equivalent to this <see cref="BITMAPINFO"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is BITMAPINFO) && (this == ((BITMAPINFO)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="BITMAPINFO"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="BITMAPINFO"/>.</returns>
+ public override int GetHashCode()
+ {
+ int hash = bmiHeader.GetHashCode();
+ if (bmiColors != null)
+ {
+ for (int c = 0; c < bmiColors.Length; c++)
+ {
+ hash ^= bmiColors[c].GetHashCode();
+ hash <<= 1;
+ }
+ hash <<= 1;
+ }
+ else
+ {
+ hash >>= 1;
+ }
+ return hash;
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIBITMAP</b> structure is a handle to a FreeImage bimtap.
+ /// </summary>
+ /// <remarks>
+ /// The handle represented by a <b>FIBITBAP</b> structure provides
+ /// access to either a singlepage bitmap or exactly one page of
+ /// a multipage bitmap.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIBITMAP : IComparable, IComparable<FIBITMAP>, IEquatable<FIBITMAP>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIBITMAP Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIBITMAP"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIBITMAP"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIBITMAP"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIBITMAP"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIBITMAP left, FIBITMAP right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIBITMAP"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIBITMAP"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIBITMAP"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIBITMAP"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIBITMAP left, FIBITMAP right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the handle is a null or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIBITMAP"/> handle is a null;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIBITMAP"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIBITMAP"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIBITMAP"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIBITMAP) && (this == ((FIBITMAP)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIBITMAP other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIBITMAP"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIBITMAP))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIBITMAP)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIBITMAP"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIBITMAP"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIBITMAP other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMULTIBITMAP</b> structure is a handle to a FreeImage multipaged bimtap.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMULTIBITMAP : IComparable, IComparable<FIMULTIBITMAP>, IEquatable<FIMULTIBITMAP>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMULTIBITMAP Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMULTIBITMAP"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMULTIBITMAP"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMULTIBITMAP"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMULTIBITMAP"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMULTIBITMAP left, FIMULTIBITMAP right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMULTIBITMAP"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMULTIBITMAP"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMULTIBITMAP"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMULTIBITMAP"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMULTIBITMAP left, FIMULTIBITMAP right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the handle is a null or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMULTIBITMAP"/> handle is a null;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMULTIBITMAP"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMULTIBITMAP"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMULTIBITMAP"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMULTIBITMAP) && (this == ((FIMULTIBITMAP)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMULTIBITMAP other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMULTIBITMAP"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMULTIBITMAP))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMULTIBITMAP)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMULTIBITMAP"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMULTIBITMAP"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMULTIBITMAP other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMEMORY</b> structure is a handle to an opened memory stream.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMEMORY : IComparable, IComparable<FIMEMORY>, IEquatable<FIMEMORY>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMEMORY Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMEMORY"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMEMORY"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMEMORY"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMEMORY"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMEMORY left, FIMEMORY right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMEMORY"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMEMORY"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMEMORY"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMEMORY"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMEMORY left, FIMEMORY right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMEMORY"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMEMORY"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMEMORY"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMEMORY"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMEMORY) && (this == ((FIMEMORY)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMEMORY other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMEMORY"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMEMORY))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMEMORY)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMEMORY"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMEMORY"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMEMORY other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIMETADATA</b> structure is an unique search handle for metadata search operations.
+ /// </summary>
+ /// <remarks>
+ /// The <b>FIMETADATA</b> structure is usually returned by the
+ /// <see cref="FreeImageAPI.FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL, FIBITMAP, out FITAG)"/>
+ /// function and then used on subsequent calls to
+ /// <see cref="FreeImageAPI.FreeImage.FindNextMetadata(FIMETADATA, out FITAG)"/>.
+ /// When the <b>FIMETADATA</b> handle is no longer used, it needs to be freed by the
+ /// <see cref="FreeImageAPI.FreeImage.FindCloseMetadata(FIMETADATA)"/> function.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIMETADATA : IComparable, IComparable<FIMETADATA>, IEquatable<FIMETADATA>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FIMETADATA Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMETADATA"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMETADATA"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIMETADATA"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMETADATA"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIMETADATA left, FIMETADATA right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIMETADATA"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIMETADATA"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIMETADATA"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIMETADATA"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIMETADATA left, FIMETADATA right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FIMETADATA"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIMETADATA"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIMETADATA"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIMETADATA"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIMETADATA) && (this == ((FIMETADATA)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIMETADATA other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIMETADATA"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIMETADATA))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIMETADATA)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIMETADATA"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIMETADATA"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIMETADATA other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FITAG</b> structure is a handle to a FreeImage metadata tag.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FITAG : IComparable, IComparable<FITAG>, IEquatable<FITAG>
+ {
+ private IntPtr data;
+
+ /// <summary>
+ /// A read-only field that represents a handle that has been initialized to zero.
+ /// </summary>
+ public static readonly FITAG Zero;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FITAG"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FITAG"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FITAG"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FITAG"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FITAG left, FITAG right)
+ {
+ return (left.data == right.data);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FITAG"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FITAG"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FITAG"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FITAG"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FITAG left, FITAG right)
+ {
+ return (left.data != right.data);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer or not.
+ /// </summary>
+ /// <value><b>true</b> if this <see cref="FITAG"/> is a null pointer;
+ /// otherwise, <b>false</b>.</value>
+ public bool IsNull
+ {
+ get
+ {
+ return (data == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Sets the handle to <i>null</i>.
+ /// </summary>
+ public void SetNull()
+ {
+ data = IntPtr.Zero;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FITAG"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return data.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FITAG"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FITAG"/>.</returns>
+ public override int GetHashCode()
+ {
+ return data.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Object"/>.</param>
+ /// <returns><b>true</b> if the specified <see cref="Object"/> is equal to the current <see cref="Object"/>; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FITAG) && (this == ((FITAG)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns><b>true</b> if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(FITAG other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FITAG"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FITAG))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FITAG)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FITAG"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FITAG other)
+ {
+ return this.data.ToInt64().CompareTo(other.data.ToInt64());
+ }
+ }
+}
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Structure for implementing access to custom handles.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FreeImageIO
+ {
+ /// <summary>
+ /// Delegate to the C++ function <b>fread</b>.
+ /// </summary>
+ public ReadProc readProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fwrite</b>.
+ /// </summary>
+ public WriteProc writeProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fseek</b>.
+ /// </summary>
+ public SeekProc seekProc;
+
+ /// <summary>
+ /// Delegate to the C++ function <b>ftell</b>.
+ /// </summary>
+ public TellProc tellProc;
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>RGBQUAD</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 8 bits and so, takes values in the range from 0 to 255.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>RGBQUAD</b> structure provides access to an underlying Win32 <b>RGBQUAD</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the rgbReserved, rgbRed, rgbGreen or rgbBlue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>RGBQUAD</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>RGBQUAD</b> structure and my be used in all situations which require
+ /// an <b>RGBQUAD</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component rgbReserved, rgbRed, rgbGreen or rgbBlue of <b>RGBQUAD</b>
+ /// is translated into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an one-to-one manner and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to RGBQUAD</b>
+ /// </para>
+ /// <c>RGBQUAD.component = Color.component</c>
+ /// <para>
+ /// <b>Conversion from RGBQUAD to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = RGBQUAD.component</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.RGBQUAD.Color"/>
+ /// property or the <see cref="FreeImageAPI.RGBQUAD(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>RGBQUAD</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// RGBQUAD rgbq;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// rgbq = new RGBQUAD(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// rgbq = Color.DarkSeaGreen;
+ /// // Convert the RGBQUAD instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = rgbq;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = rgbq.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Explicit)]
+ public struct RGBQUAD : IComparable, IComparable<RGBQUAD>, IEquatable<RGBQUAD>
+ {
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ [FieldOffset(0)]
+ public byte rgbBlue;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ [FieldOffset(1)]
+ public byte rgbGreen;
+
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ [FieldOffset(2)]
+ public byte rgbRed;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ [FieldOffset(3)]
+ public byte rgbReserved;
+
+ /// <summary>
+ /// The color's value.
+ /// </summary>
+ [FieldOffset(0)]
+ public uint uintValue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public RGBQUAD(Color color)
+ {
+ uintValue = 0u;
+ rgbBlue = color.B;
+ rgbGreen = color.G;
+ rgbRed = color.R;
+ rgbReserved = color.A;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBQUAD"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBQUAD"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="RGBQUAD"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBQUAD"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(RGBQUAD left, RGBQUAD right)
+ {
+ return (left.uintValue == right.uintValue);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBQUAD"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBQUAD"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="RGBQUAD"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBQUAD"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(RGBQUAD left, RGBQUAD right)
+ {
+ return (left.uintValue != right.uintValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBQUAD(Color value)
+ {
+ return new RGBQUAD(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBQUAD"/> structure to a Color structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBQUAD"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(RGBQUAD value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBQUAD(uint value)
+ {
+ RGBQUAD result = new RGBQUAD();
+ result.uintValue = value;
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBQUAD"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBQUAD"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBQUAD"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator uint(RGBQUAD value)
+ {
+ return value.uintValue;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ rgbReserved,
+ rgbRed,
+ rgbGreen,
+ rgbBlue);
+ }
+ set
+ {
+ rgbRed = value.R;
+ rgbGreen = value.G;
+ rgbBlue = value.B;
+ rgbReserved = value.A;
+ }
+ }
+
+ /// <summary>
+ /// Converts an array of <see cref="Color"/> into an array of
+ /// <see cref="RGBQUAD"/>.
+ /// </summary>
+ /// <param name="array">The array to convert.</param>
+ /// <returns>An array of <see cref="RGBQUAD"/>.</returns>
+ public static RGBQUAD[] ToRGBQUAD(Color[] array)
+ {
+ if (array == null)
+ return null;
+
+ RGBQUAD[] result = new RGBQUAD[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ result[i] = array[i];
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts an array of <see cref="RGBQUAD"/> into an array of
+ /// <see cref="Color"/>.
+ /// </summary>
+ /// <param name="array">The array to convert.</param>
+ /// <returns>An array of <see cref="RGBQUAD"/>.</returns>
+ public static Color[] ToColor(RGBQUAD[] array)
+ {
+ if (array == null)
+ return null;
+
+ Color[] result = new Color[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ result[i] = array[i].Color;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="RGBQUAD"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is RGBQUAD))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((RGBQUAD)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="RGBQUAD"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBQUAD"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(RGBQUAD other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="RGBQUAD"/> structure
+ /// and is equivalent to this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBQUAD"/> structure
+ /// equivalent to this <see cref="RGBQUAD"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is RGBQUAD) && (this == ((RGBQUAD)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="RGBQUAD"/> structure is equivalent to this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBQUAD"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBQUAD"/> structure
+ /// equivalent to this <see cref="RGBQUAD"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(RGBQUAD other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="RGBQUAD"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="RGBQUAD"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="RGBQUAD"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>RGBTRIPLE</b> structure describes a color consisting of relative
+ /// intensities of red, green and blue value. Each single color component
+ /// consumes 8 bits and so, takes values in the range from 0 to 255.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>RGBTRIPLE</b> structure provides access to an underlying Win32 <b>RGBTRIPLE</b>
+ /// structure. To determine the red, green or blue component of a color, use the
+ /// rgbtRed, rgbtGreen or rgbtBlue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>RGBTRIPLE</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>RGBTRIPLE</b> structure and my be used in all situations which require
+ /// an <b>RGBTRIPLE</b> type.
+ /// </para>
+ /// <para>
+ /// Each of the color components rgbtRed, rgbtGreen or rgbtBlue of <b>RGBTRIPLE</b> is
+ /// translated into it's corresponding color component R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an one-to-one manner and vice versa.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>RGBTRIPLE</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>RGBTRIPLE</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to RGBTRIPLE</b>
+ /// </para>
+ /// <c>RGBTRIPLE.component = Color.component</c>
+ /// <para>
+ /// <b>Conversion from RGBTRIPLE to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = RGBTRIPLE.component</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.RGBTRIPLE.Color"/>
+ /// property or the <see cref="FreeImageAPI.RGBTRIPLE(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>RGBTRIPLE</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// RGBTRIPLE rgbt;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// rgbt = new RGBTRIPLE(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// rgbt = Color.DarkSeaGreen;
+ /// // Convert the RGBTRIPLE instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = rgbt;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = rgbt.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct RGBTRIPLE : IComparable, IComparable<RGBTRIPLE>, IEquatable<RGBTRIPLE>
+ {
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public byte rgbtBlue;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public byte rgbtGreen;
+
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public byte rgbtRed;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public RGBTRIPLE(Color color)
+ {
+ rgbtBlue = color.B;
+ rgbtGreen = color.G;
+ rgbtRed = color.R;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBTRIPLE"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBTRIPLE"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="RGBTRIPLE"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBTRIPLE"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(RGBTRIPLE left, RGBTRIPLE right)
+ {
+ return
+ left.rgbtBlue == right.rgbtBlue &&
+ left.rgbtGreen == right.rgbtGreen &&
+ left.rgbtRed == right.rgbtRed;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="RGBTRIPLE"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="RGBTRIPLE"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="RGBTRIPLE"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="RGBTRIPLE"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(RGBTRIPLE left, RGBTRIPLE right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBTRIPLE(Color value)
+ {
+ return new RGBTRIPLE(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBTRIPLE"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBTRIPLE"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(RGBTRIPLE value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator RGBTRIPLE(uint value)
+ {
+ RGBTRIPLE result = new RGBTRIPLE();
+ result.rgbtBlue = (byte)(value & 0xFF);
+ result.rgbtGreen = (byte)((value >> 8) & 0xFF);
+ result.rgbtRed = (byte)((value >> 16) & 0xFF);
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="RGBTRIPLE"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="RGBTRIPLE"/> structure.</param>
+ /// <returns>A new instance of <see cref="RGBTRIPLE"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator uint(RGBTRIPLE value)
+ {
+ return (uint)((value.rgbtRed << 16) | (value.rgbtGreen << 8) | (value.rgbtBlue));
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ rgbtRed,
+ rgbtGreen,
+ rgbtBlue);
+ }
+ set
+ {
+ rgbtBlue = value.B;
+ rgbtGreen = value.G;
+ rgbtRed = value.R;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="RGBTRIPLE"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is RGBTRIPLE))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((RGBTRIPLE)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="RGBTRIPLE"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBTRIPLE"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(RGBTRIPLE other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="RGBTRIPLE"/> structure
+ /// and is equivalent to this <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBTRIPLE"/> structure
+ /// equivalent to this <see cref="RGBTRIPLE"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is RGBTRIPLE) && (this == ((RGBTRIPLE)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="RGBTRIPLE"/> structure is equivalent to this
+ /// <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="RGBTRIPLE"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="RGBTRIPLE"/> structure
+ /// equivalent to this <see cref="RGBTRIPLE"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(RGBTRIPLE other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="RGBTRIPLE"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="RGBTRIPLE"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="RGBTRIPLE"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBA16</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 16 bits and so, takes values in the range from 0 to 65535.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBA16</b> structure provides access to an underlying FreeImage <b>FIRGBA16</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the alpha, red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBA16</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBA16</b> structure and my be used in all situations which require
+ /// an <b>FIRGBA16</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBA16</b>
+ /// is translated into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by an 8 bit right shift and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBA16</b>
+ /// </para>
+ /// <c>FIRGBA16.component = Color.component &lt;&lt; 8</c>
+ /// <para>
+ /// <b>Conversion from FIRGBA16 to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = FIRGBA16.component &gt;&gt; 8</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBA16.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBA16(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBA16</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBA16 firgba16;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgba16 = new FIRGBA16(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgba16 = Color.DarkSeaGreen;
+ /// // Convert the FIRGBA16 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgba16;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgba16.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBA16 : IComparable, IComparable<FIRGBA16>, IEquatable<FIRGBA16>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public ushort red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public ushort green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public ushort blue;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ public ushort alpha;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBA16(Color color)
+ {
+ red = (ushort)(color.R << 8);
+ green = (ushort)(color.G << 8);
+ blue = (ushort)(color.B << 8);
+ alpha = (ushort)(color.A << 8);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBA16"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBA16"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBA16"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBA16"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBA16 left, FIRGBA16 right)
+ {
+ return
+ ((left.alpha == right.alpha) &&
+ (left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBA16"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBA16"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBA16"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBA16"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBA16 left, FIRGBA16 right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBA16"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBA16(Color value)
+ {
+ return new FIRGBA16(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBA16"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBA16"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBA16 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb((alpha >> 8), (red >> 8), (green >> 8), (blue >> 8));
+ }
+ set
+ {
+ red = (ushort)(value.R << 8);
+ green = (ushort)(value.G << 8);
+ blue = (ushort)(value.B << 8);
+ alpha = (ushort)(value.A << 8);
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBA16"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBA16))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBA16)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBA16"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBA16"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBA16 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBA16"/> structure
+ /// and is equivalent to this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBA16"/> structure
+ /// equivalent to this <see cref="FIRGBA16"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBA16) && (this == ((FIRGBA16)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBA16"/> structure is equivalent to this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBA16"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBA16"/> structure
+ /// equivalent to this <see cref="FIRGBA16"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBA16 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBA16"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBA16"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBA16"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGB16</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 16 bits and so, takes values in the range from 0 to 65535.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGB16</b> structure provides access to an underlying FreeImage <b>FIRGB16</b>
+ /// structure. To determine the red, green or blue component of a color,
+ /// use the red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGB16</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGB16</b> structure and my be used in all situations which require
+ /// an <b>FIRGB16</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component red, green or blue of <b>FIRGB16</b> is translated into
+ /// it's corresponding color component R, G or B of
+ /// <see cref="System.Drawing.Color"/> by right shifting 8 bits and shifting left 8 bits for the reverse conversion.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>FIRGB16</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>FIRGB16</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGB16</b>
+ /// </para>
+ /// <c>FIRGB16.component = Color.component &lt;&lt; 8</c>
+ /// <para>
+ /// <b>Conversion from FIRGB16 to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = FIRGB16.component &gt;&gt; 8</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGB16.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGB16(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGB16</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGB16 firgb16;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgb16 = new FIRGBA16(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgb16 = Color.DarkSeaGreen;
+ /// // Convert the FIRGB16 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgb16;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgb16.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGB16 : IComparable, IComparable<FIRGB16>, IEquatable<FIRGB16>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public ushort red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public ushort green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public ushort blue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGB16(Color color)
+ {
+ red = (ushort)(color.R << 8);
+ green = (ushort)(color.G << 8);
+ blue = (ushort)(color.B << 8);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGB16"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGB16"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGB16"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGB16"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGB16 left, FIRGB16 right)
+ {
+ return
+ ((left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGB16"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGB16"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGB16"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGB16"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGB16 left, FIRGB16 right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGB16"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGB16(Color value)
+ {
+ return new FIRGB16(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGB16"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGB16"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGB16 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb((red >> 8), (green >> 8), (blue >> 8));
+ }
+ set
+ {
+ red = (ushort)(value.R << 8);
+ green = (ushort)(value.G << 8);
+ blue = (ushort)(value.B << 8);
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGB16"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGB16))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGB16)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGB16"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGB16"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGB16 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGB16"/> structure
+ /// and is equivalent to this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGB16"/> structure
+ /// equivalent to this <see cref="FIRGB16"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGB16) && (this == ((FIRGB16)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGB16"/> structure is equivalent to this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGB16"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGB16"/> structure
+ /// equivalent to this <see cref="FIRGB16"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGB16 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGB16"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGB16"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGB16"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBAF</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 32 bits and takes values in the range from 0 to 1.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBAF</b> structure provides access to an underlying FreeImage <b>FIRGBAF</b>
+ /// structure. To determine the alpha, red, green or blue component of a color,
+ /// use the alpha, red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBAF</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBAF</b> structure and my be used in all situations which require
+ /// an <b>FIRGBAF</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBAF</b> is translated
+ /// into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by linearly mapping the values of one range
+ /// into the other range and vice versa.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBAF</b>
+ /// </para>
+ /// <c>FIRGBAF.component = (float)Color.component / 255f</c>
+ /// <para>
+ /// <b>Conversion from FIRGBAF to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = (int)(FIRGBAF.component * 255f)</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBAF.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBAF(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBAF</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBAF firgbaf;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgbaf = new FIRGBAF(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgbaf = Color.DarkSeaGreen;
+ /// // Convert the FIRGBAF instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgbaf;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgbaf.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBAF : IComparable, IComparable<FIRGBAF>, IEquatable<FIRGBAF>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public float red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public float green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public float blue;
+
+ /// <summary>
+ /// The alpha color component.
+ /// </summary>
+ public float alpha;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBAF(Color color)
+ {
+ red = (float)color.R / 255f;
+ green = (float)color.G / 255f;
+ blue = (float)color.B / 255f;
+ alpha = (float)color.A / 255f;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBAF"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBAF"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBAF"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBAF"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBAF left, FIRGBAF right)
+ {
+ return
+ ((left.alpha == right.alpha) &&
+ (left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBAF"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBAF"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBAF"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBAF"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBAF left, FIRGBAF right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBAF"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBAF(Color value)
+ {
+ return new FIRGBAF(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBAF"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBAF"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBAF value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ (int)(alpha * 255f),
+ (int)(red * 255f),
+ (int)(green * 255f),
+ (int)(blue * 255f));
+ }
+ set
+ {
+ red = (float)value.R / 255f;
+ green = (float)value.G / 255f;
+ blue = (float)value.B / 255f;
+ alpha = (float)value.A / 255f;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBAF"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBAF))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBAF)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBAF"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBAF"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBAF other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBAF"/> structure
+ /// and is equivalent to this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBAF"/> structure
+ /// equivalent to this <see cref="FIRGBAF"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBAF) && (this == ((FIRGBAF)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBAF"/> structure is equivalent to this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBAF"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBAF"/> structure
+ /// equivalent to this <see cref="FIRGBAF"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBAF other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBAF"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBAF"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBAF"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRGBF</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 32 bits and takes values in the range from 0 to 1.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <b>FIRGBF</b> structure provides access to an underlying FreeImage <b>FIRGBF</b>
+ /// structure. To determine the red, green or blue component of a color, use the
+ /// red, green or blue fields, respectively.
+ /// </para>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FIRGBF</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FIRGBF</b> structure and my be used in all situations which require
+ /// an <b>FIRGBF</b> type.
+ /// </para>
+ /// <para>
+ /// Each color component alpha, red, green or blue of <b>FIRGBF</b> is translated
+ /// into it's corresponding color component A, R, G or B of
+ /// <see cref="System.Drawing.Color"/> by linearly mapping the values of one range
+ /// into the other range and vice versa.
+ /// When converting from <see cref="System.Drawing.Color"/> into <b>FIRGBF</b>, the
+ /// color's alpha value is ignored and assumed to be 255 when converting from
+ /// <b>FIRGBF</b> into <see cref="System.Drawing.Color"/>, creating a fully
+ /// opaque color.
+ /// </para>
+ /// <para>
+ /// <b>Conversion from System.Drawing.Color to FIRGBF</b>
+ /// </para>
+ /// <c>FIRGBF.component = (float)Color.component / 255f</c>
+ /// <para>
+ /// <b>Conversion from FIRGBF to System.Drawing.Color</b>
+ /// </para>
+ /// <c>Color.component = (int)(FIRGBF.component * 255f)</c>
+ /// <para>
+ /// The same conversion is also applied when the <see cref="FreeImageAPI.FIRGBF.Color"/>
+ /// property or the <see cref="FreeImageAPI.FIRGBF(System.Drawing.Color)"/> constructor
+ /// is invoked.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FIRGBF</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FIRGBF firgbf;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// firgbf = new FIRGBF(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// firgbf = Color.DarkSeaGreen;
+ /// // Convert the FIRGBF instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = firgbf;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = firgbf.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIRGBF : IComparable, IComparable<FIRGBF>, IEquatable<FIRGBF>
+ {
+ /// <summary>
+ /// The red color component.
+ /// </summary>
+ public float red;
+
+ /// <summary>
+ /// The green color component.
+ /// </summary>
+ public float green;
+
+ /// <summary>
+ /// The blue color component.
+ /// </summary>
+ public float blue;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FIRGBF(Color color)
+ {
+ red = (float)color.R / 255f;
+ green = (float)color.G / 255f;
+ blue = (float)color.B / 255f;
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBF"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBF"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FIRGBF"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBF"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FIRGBF left, FIRGBF right)
+ {
+ return
+ ((left.blue == right.blue) &&
+ (left.green == right.green) &&
+ (left.red == right.red));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FIRGBF"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FIRGBF"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FIRGBF"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FIRGBF"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FIRGBF left, FIRGBF right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRGBF"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRGBF(Color value)
+ {
+ return new FIRGBF(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRGBF"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRGBF"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FIRGBF value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ (int)(red * 255f),
+ (int)(green * 255f),
+ (int)(blue * 255f));
+ }
+ set
+ {
+ red = (float)value.R / 255f;
+ green = (float)value.G / 255f;
+ blue = (float)value.B / 255f;
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRGBF"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRGBF))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FIRGBF)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRGBF"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBF"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRGBF other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRGBF"/> structure
+ /// and is equivalent to this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBF"/> structure
+ /// equivalent to this <see cref="FIRGBF"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRGBF) && (this == ((FIRGBF)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRGBF"/> structure is equivalent to this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRGBF"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRGBF"/> structure
+ /// equivalent to this <see cref="FIRGBF"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRGBF other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRGBF"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRGBF"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRGBF"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FICOMPLEX</b> structure describes a color consisting of a real and an imaginary part.
+ /// Each part is using 4 bytes of data.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FICOMPLEX : IComparable, IComparable<FICOMPLEX>, IEquatable<FICOMPLEX>
+ {
+ /// <summary>
+ /// Real part of the color.
+ /// </summary>
+ public double real;
+
+ /// <summary>
+ /// Imaginary part of the color.
+ /// </summary>
+ public double imag;
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FICOMPLEX"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FICOMPLEX"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FICOMPLEX"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FICOMPLEX"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FICOMPLEX left, FICOMPLEX right)
+ {
+ return ((left.real == right.real) && (left.imag == right.imag));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FICOMPLEX"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FICOMPLEX"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FICOMPLEX"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FICOMPLEX"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FICOMPLEX left, FICOMPLEX right)
+ {
+ return ((left.real != right.real) || (left.imag == right.imag));
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FICOMPLEX"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FICOMPLEX))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FICOMPLEX)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FICOMPLEX"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FICOMPLEX"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FICOMPLEX other)
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FICOMPLEX"/> structure
+ /// and is equivalent to this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FICOMPLEX"/> structure
+ /// equivalent to this <see cref="FICOMPLEX"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FICOMPLEX) && (this == ((FICOMPLEX)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FICOMPLEX"/> structure is equivalent to this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FICOMPLEX"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FICOMPLEX"/> structure
+ /// equivalent to this <see cref="FICOMPLEX"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FICOMPLEX other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FICOMPLEX"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FICOMPLEX"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// This Structure contains ICC-Profile data.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FIICCPROFILE
+ {
+ private ICC_FLAGS flags;
+ private uint size;
+ private IntPtr data;
+
+ /// <summary>
+ /// Creates a new ICC-Profile for <paramref name="dib"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The ICC-Profile data.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public FIICCPROFILE(FIBITMAP dib, byte[] data)
+ : this(dib, data, (int)data.Length)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile for <paramref name="dib"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The ICC-Profile data.</param>
+ /// <param name="size">Number of bytes to use from data.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public unsafe FIICCPROFILE(FIBITMAP dib, byte[] data, int size)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FIICCPROFILE prof;
+ size = Math.Min(size, (int)data.Length);
+ prof = *(FIICCPROFILE*)FreeImage.CreateICCProfile(dib, data, size);
+ this.flags = prof.flags;
+ this.size = prof.size;
+ this.data = prof.data;
+ }
+
+ /// <summary>
+ /// Info flag of the profile.
+ /// </summary>
+ public ICC_FLAGS Flags
+ {
+ get { return flags; }
+ }
+
+ /// <summary>
+ /// Profile's size measured in bytes.
+ /// </summary>
+ public uint Size
+ {
+ get { return size; }
+ }
+
+ /// <summary>
+ /// Points to a block of contiguous memory containing the profile.
+ /// </summary>
+ public IntPtr DataPointer
+ {
+ get { return data; }
+ }
+
+ /// <summary>
+ /// Copy of the ICC-Profiles data.
+ /// </summary>
+ public unsafe byte[] Data
+ {
+ get
+ {
+ byte[] result;
+ FreeImage.CopyMemory(result = new byte[size], data.ToPointer(), size);
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Indicates whether the profile is CMYK.
+ /// </summary>
+ public bool IsCMYK
+ {
+ get
+ {
+ return ((flags & ICC_FLAGS.FIICC_COLOR_IS_CMYK) != 0);
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// The structure contains functionpointers that make up a FreeImage plugin.
+ /// </summary>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct Plugin
+ {
+ /// <summary>
+ /// Delegate to a function that returns a string which describes
+ /// the plugins format.
+ /// </summary>
+ public FormatProc formatProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// a more detailed description.
+ /// </summary>
+ public DescriptionProc descriptionProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a comma seperated list
+ /// of file extensions the plugin can read or write.
+ /// </summary>
+ public ExtensionListProc extensionListProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a regular expression that
+ /// can be used to idientify whether a file can be handled by the plugin.
+ /// </summary>
+ public RegExprProc regExprProc;
+
+ /// <summary>
+ /// Delegate to a function that opens a file.
+ /// </summary>
+ public OpenProc openProc;
+
+ /// <summary>
+ /// Delegate to a function that closes a previosly opened file.
+ /// </summary>
+ public CloseProc closeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns the number of pages of a multipage
+ /// bitmap if the plugin is capable of handling multipage bitmaps.
+ /// </summary>
+ public PageCountProc pageCountProc;
+
+ /// <summary>
+ /// UNKNOWN
+ /// </summary>
+ public PageCapabilityProc pageCapabilityProc;
+
+ /// <summary>
+ /// Delegate to a function that loads and decodes a bitmap into memory.
+ /// </summary>
+ public LoadProc loadProc;
+
+ /// <summary>
+ /// Delegate to a function that saves a bitmap.
+ /// </summary>
+ public SaveProc saveProc;
+
+ /// <summary>
+ /// Delegate to a function that determines whether the source is a valid image.
+ /// </summary>
+ public ValidateProc validateProc;
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// the plugin's mime type.
+ /// </summary>
+ public MimeProc mimeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified color depth.
+ /// </summary>
+ public SupportsExportBPPProc supportsExportBPPProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified image type.
+ /// </summary>
+ public SupportsExportTypeProc supportsExportTypeProc;
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle
+ /// ICC-Profiles.
+ /// </summary>
+ public SupportsICCProfilesProc supportsICCProfilesProc;
+ }
+}
+
+ #endregion
+
+ #region Enums
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Specifies how a single frame will be handled after being displayed.
+ /// </summary>
+ public enum DisposalMethodType : byte
+ {
+ /// <summary>
+ /// Same behavior as <see cref="DisposalMethodType.Leave"/> but should not be used.
+ /// </summary>
+ Unspecified,
+
+ /// <summary>
+ /// The image is left in place and will be overdrawn by the next image.
+ /// </summary>
+ Leave,
+
+ /// <summary>
+ /// The area of the image will be blanked out by its background.
+ /// </summary>
+ Background,
+
+ /// <summary>
+ /// Restores the the area of the image to the state it was before it
+ /// has been dawn.
+ /// </summary>
+ Previous,
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// I/O image format identifiers.
+ /// </summary>
+ public enum FREE_IMAGE_FORMAT
+ {
+ /// <summary>
+ /// Unknown format (returned value only, never use it as input value)
+ /// </summary>
+ FIF_UNKNOWN = -1,
+ /// <summary>
+ /// Windows or OS/2 Bitmap File (*.BMP)
+ /// </summary>
+ FIF_BMP = 0,
+ /// <summary>
+ /// Windows Icon (*.ICO)
+ /// </summary>
+ FIF_ICO = 1,
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ FIF_JPEG = 2,
+ /// <summary>
+ /// JPEG Network Graphics (*.JNG)
+ /// </summary>
+ FIF_JNG = 3,
+ /// <summary>
+ /// Commodore 64 Koala format (*.KOA)
+ /// </summary>
+ FIF_KOALA = 4,
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ FIF_LBM = 5,
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ FIF_IFF = 5,
+ /// <summary>
+ /// Multiple Network Graphics (*.MNG)
+ /// </summary>
+ FIF_MNG = 6,
+ /// <summary>
+ /// Portable Bitmap (ASCII) (*.PBM)
+ /// </summary>
+ FIF_PBM = 7,
+ /// <summary>
+ /// Portable Bitmap (BINARY) (*.PBM)
+ /// </summary>
+ FIF_PBMRAW = 8,
+ /// <summary>
+ /// Kodak PhotoCD (*.PCD)
+ /// </summary>
+ FIF_PCD = 9,
+ /// <summary>
+ /// Zsoft Paintbrush PCX bitmap format (*.PCX)
+ /// </summary>
+ FIF_PCX = 10,
+ /// <summary>
+ /// Portable Graymap (ASCII) (*.PGM)
+ /// </summary>
+ FIF_PGM = 11,
+ /// <summary>
+ /// Portable Graymap (BINARY) (*.PGM)
+ /// </summary>
+ FIF_PGMRAW = 12,
+ /// <summary>
+ /// Portable Network Graphics (*.PNG)
+ /// </summary>
+ FIF_PNG = 13,
+ /// <summary>
+ /// Portable Pixelmap (ASCII) (*.PPM)
+ /// </summary>
+ FIF_PPM = 14,
+ /// <summary>
+ /// Portable Pixelmap (BINARY) (*.PPM)
+ /// </summary>
+ FIF_PPMRAW = 15,
+ /// <summary>
+ /// Sun Rasterfile (*.RAS)
+ /// </summary>
+ FIF_RAS = 16,
+ /// <summary>
+ /// truevision Targa files (*.TGA, *.TARGA)
+ /// </summary>
+ FIF_TARGA = 17,
+ /// <summary>
+ /// Tagged Image File Format (*.TIF, *.TIFF)
+ /// </summary>
+ FIF_TIFF = 18,
+ /// <summary>
+ /// Wireless Bitmap (*.WBMP)
+ /// </summary>
+ FIF_WBMP = 19,
+ /// <summary>
+ /// Adobe Photoshop (*.PSD)
+ /// </summary>
+ FIF_PSD = 20,
+ /// <summary>
+ /// Dr. Halo (*.CUT)
+ /// </summary>
+ FIF_CUT = 21,
+ /// <summary>
+ /// X11 Bitmap Format (*.XBM)
+ /// </summary>
+ FIF_XBM = 22,
+ /// <summary>
+ /// X11 Pixmap Format (*.XPM)
+ /// </summary>
+ FIF_XPM = 23,
+ /// <summary>
+ /// DirectDraw Surface (*.DDS)
+ /// </summary>
+ FIF_DDS = 24,
+ /// <summary>
+ /// Graphics Interchange Format (*.GIF)
+ /// </summary>
+ FIF_GIF = 25,
+ /// <summary>
+ /// High Dynamic Range (*.HDR)
+ /// </summary>
+ FIF_HDR = 26,
+ /// <summary>
+ /// Raw Fax format CCITT G3 (*.G3)
+ /// </summary>
+ FIF_FAXG3 = 27,
+ /// <summary>
+ /// Silicon Graphics SGI image format (*.SGI)
+ /// </summary>
+ FIF_SGI = 28,
+ /// <summary>
+ /// OpenEXR format (*.EXR)
+ /// </summary>
+ FIF_EXR = 29,
+ /// <summary>
+ /// JPEG-2000 format (*.J2K, *.J2C)
+ /// </summary>
+ FIF_J2K = 30,
+ /// <summary>
+ /// JPEG-2000 format (*.JP2)
+ /// </summary>
+ FIF_JP2 = 31,
+ /// <summary>
+ /// Portable FloatMap (*.PFM)
+ /// </summary>
+ FIF_PFM = 32,
+ /// <summary>
+ /// Macintosh PICT (*.PICT)
+ /// </summary>
+ FIF_PICT = 33,
+ /// <summary>
+ /// RAW camera image (*.*)
+ /// </summary>
+ FIF_RAW = 34,
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Image types used in FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_TYPE
+ {
+ /// <summary>
+ /// unknown type
+ /// </summary>
+ FIT_UNKNOWN = 0,
+ /// <summary>
+ /// standard image : 1-, 4-, 8-, 16-, 24-, 32-bit
+ /// </summary>
+ FIT_BITMAP = 1,
+ /// <summary>
+ /// array of unsigned short : unsigned 16-bit
+ /// </summary>
+ FIT_UINT16 = 2,
+ /// <summary>
+ /// array of short : signed 16-bit
+ /// </summary>
+ FIT_INT16 = 3,
+ /// <summary>
+ /// array of unsigned long : unsigned 32-bit
+ /// </summary>
+ FIT_UINT32 = 4,
+ /// <summary>
+ /// array of long : signed 32-bit
+ /// </summary>
+ FIT_INT32 = 5,
+ /// <summary>
+ /// array of float : 32-bit IEEE floating point
+ /// </summary>
+ FIT_FLOAT = 6,
+ /// <summary>
+ /// array of double : 64-bit IEEE floating point
+ /// </summary>
+ FIT_DOUBLE = 7,
+ /// <summary>
+ /// array of FICOMPLEX : 2 x 64-bit IEEE floating point
+ /// </summary>
+ FIT_COMPLEX = 8,
+ /// <summary>
+ /// 48-bit RGB image : 3 x 16-bit
+ /// </summary>
+ FIT_RGB16 = 9,
+ /// <summary>
+ /// 64-bit RGBA image : 4 x 16-bit
+ /// </summary>
+ FIT_RGBA16 = 10,
+ /// <summary>
+ /// 96-bit RGB float image : 3 x 32-bit IEEE floating point
+ /// </summary>
+ FIT_RGBF = 11,
+ /// <summary>
+ /// 128-bit RGBA float image : 4 x 32-bit IEEE floating point
+ /// </summary>
+ FIT_RGBAF = 12
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Constants used in color filling routines.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_OPTIONS
+ {
+ /// <summary>
+ /// Default value.
+ /// </summary>
+ FICO_DEFAULT = 0x0,
+ /// <summary>
+ /// <see cref="RGBQUAD"/> color is RGB color (contains no valid alpha channel).
+ /// </summary>
+ FICO_RGB = 0x0,
+ /// <summary>
+ /// <see cref="RGBQUAD"/> color is RGBA color (contains a valid alpha channel).
+ /// </summary>
+ FICO_RGBA = 0x1,
+ /// <summary>
+ /// Lookup nearest RGB color from palette.
+ /// </summary>
+ FICO_NEAREST_COLOR = 0x0,
+ /// <summary>
+ /// Lookup equal RGB color from palette.
+ /// </summary>
+ FICO_EQUAL_COLOR = 0x2,
+ /// <summary>
+ /// <see cref="RGBQUAD.rgbReserved"/> contains the palette index to be used.
+ /// </summary>
+ FICO_ALPHA_IS_INDEX = 0x4,
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Image color types used in FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_TYPE
+ {
+ /// <summary>
+ /// min value is white
+ /// </summary>
+ FIC_MINISWHITE = 0,
+ /// <summary>
+ /// min value is black
+ /// </summary>
+ FIC_MINISBLACK = 1,
+ /// <summary>
+ /// RGB color model
+ /// </summary>
+ FIC_RGB = 2,
+ /// <summary>
+ /// color map indexed
+ /// </summary>
+ FIC_PALETTE = 3,
+ /// <summary>
+ /// RGB color model with alpha channel
+ /// </summary>
+ FIC_RGBALPHA = 4,
+ /// <summary>
+ /// CMYK color model
+ /// </summary>
+ FIC_CMYK = 5
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Color quantization algorithms.
+ /// Constants used in FreeImage_ColorQuantize.
+ /// </summary>
+ public enum FREE_IMAGE_QUANTIZE
+ {
+ /// <summary>
+ /// Xiaolin Wu color quantization algorithm
+ /// </summary>
+ FIQ_WUQUANT = 0,
+ /// <summary>
+ /// NeuQuant neural-net quantization algorithm by Anthony Dekker
+ /// </summary>
+ FIQ_NNQUANT = 1
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Dithering algorithms.
+ /// Constants used in FreeImage_Dither.
+ /// </summary>
+ public enum FREE_IMAGE_DITHER
+ {
+ /// <summary>
+ /// Floyd and Steinberg error diffusion
+ /// </summary>
+ FID_FS = 0,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+ /// </summary>
+ FID_BAYER4x4 = 1,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+ /// </summary>
+ FID_BAYER8x8 = 2,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 3 - 6x6 matrix)
+ /// </summary>
+ FID_CLUSTER6x6 = 3,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 4 - 8x8 matrix)
+ /// </summary>
+ FID_CLUSTER8x8 = 4,
+ /// <summary>
+ /// Ordered clustered dot dithering (order 8 - 16x16 matrix)
+ /// </summary>
+ FID_CLUSTER16x16 = 5,
+ /// <summary>
+ /// Bayer ordered dispersed dot dithering (order 4 dithering matrix)
+ /// </summary>
+ FID_BAYER16x16 = 6
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Lossless JPEG transformations constants used in FreeImage_JPEGTransform.
+ /// </summary>
+ public enum FREE_IMAGE_JPEG_OPERATION
+ {
+ /// <summary>
+ /// no transformation
+ /// </summary>
+ FIJPEG_OP_NONE = 0,
+ /// <summary>
+ /// horizontal flip
+ /// </summary>
+ FIJPEG_OP_FLIP_H = 1,
+ /// <summary>
+ /// vertical flip
+ /// </summary>
+ FIJPEG_OP_FLIP_V = 2,
+ /// <summary>
+ /// transpose across UL-to-LR axis
+ /// </summary>
+ FIJPEG_OP_TRANSPOSE = 3,
+ /// <summary>
+ /// transpose across UR-to-LL axis
+ /// </summary>
+ FIJPEG_OP_TRANSVERSE = 4,
+ /// <summary>
+ /// 90-degree clockwise rotation
+ /// </summary>
+ FIJPEG_OP_ROTATE_90 = 5,
+ /// <summary>
+ /// 180-degree rotation
+ /// </summary>
+ FIJPEG_OP_ROTATE_180 = 6,
+ /// <summary>
+ /// 270-degree clockwise (or 90 ccw)
+ /// </summary>
+ FIJPEG_OP_ROTATE_270 = 7
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Tone mapping operators. Constants used in FreeImage_ToneMapping.
+ /// </summary>
+ public enum FREE_IMAGE_TMO
+ {
+ /// <summary>
+ /// Adaptive logarithmic mapping (F. Drago, 2003)
+ /// </summary>
+ FITMO_DRAGO03 = 0,
+ /// <summary>
+ /// Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+ /// </summary>
+ FITMO_REINHARD05 = 1,
+ /// <summary>
+ /// Gradient domain high dynamic range compression (R. Fattal, 2002)
+ /// </summary>
+ FITMO_FATTAL02
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Upsampling / downsampling filters. Constants used in FreeImage_Rescale.
+ /// </summary>
+ public enum FREE_IMAGE_FILTER
+ {
+ /// <summary>
+ /// Box, pulse, Fourier window, 1st order (constant) b-spline
+ /// </summary>
+ FILTER_BOX = 0,
+ /// <summary>
+ /// Mitchell and Netravali's two-param cubic filter
+ /// </summary>
+ FILTER_BICUBIC = 1,
+ /// <summary>
+ /// Bilinear filter
+ /// </summary>
+ FILTER_BILINEAR = 2,
+ /// <summary>
+ /// 4th order (cubic) b-spline
+ /// </summary>
+ FILTER_BSPLINE = 3,
+ /// <summary>
+ /// Catmull-Rom spline, Overhauser spline
+ /// </summary>
+ FILTER_CATMULLROM = 4,
+ /// <summary>
+ /// Lanczos3 filter
+ /// </summary>
+ FILTER_LANCZOS3 = 5
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Color channels. Constants used in color manipulation routines.
+ /// </summary>
+ public enum FREE_IMAGE_COLOR_CHANNEL
+ {
+ /// <summary>
+ /// Use red, green and blue channels
+ /// </summary>
+ FICC_RGB = 0,
+ /// <summary>
+ /// Use red channel
+ /// </summary>
+ FICC_RED = 1,
+ /// <summary>
+ /// Use green channel
+ /// </summary>
+ FICC_GREEN = 2,
+ /// <summary>
+ /// Use blue channel
+ /// </summary>
+ FICC_BLUE = 3,
+ /// <summary>
+ /// Use alpha channel
+ /// </summary>
+ FICC_ALPHA = 4,
+ /// <summary>
+ /// Use black channel
+ /// </summary>
+ FICC_BLACK = 5,
+ /// <summary>
+ /// Complex images: use real part
+ /// </summary>
+ FICC_REAL = 6,
+ /// <summary>
+ /// Complex images: use imaginary part
+ /// </summary>
+ FICC_IMAG = 7,
+ /// <summary>
+ /// Complex images: use magnitude
+ /// </summary>
+ FICC_MAG = 8,
+ /// <summary>
+ /// Complex images: use phase
+ /// </summary>
+ FICC_PHASE = 9
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Tag data type information (based on TIFF specifications)
+ /// Note: RATIONALs are the ratio of two 32-bit integer values.
+ /// </summary>
+ public enum FREE_IMAGE_MDTYPE
+ {
+ /// <summary>
+ /// placeholder
+ /// </summary>
+ FIDT_NOTYPE = 0,
+ /// <summary>
+ /// 8-bit unsigned integer
+ /// </summary>
+ FIDT_BYTE = 1,
+ /// <summary>
+ /// 8-bit bytes w/ last byte null
+ /// </summary>
+ FIDT_ASCII = 2,
+ /// <summary>
+ /// 16-bit unsigned integer
+ /// </summary>
+ FIDT_SHORT = 3,
+ /// <summary>
+ /// 32-bit unsigned integer
+ /// </summary>
+ FIDT_LONG = 4,
+ /// <summary>
+ /// 64-bit unsigned fraction
+ /// </summary>
+ FIDT_RATIONAL = 5,
+ /// <summary>
+ /// 8-bit signed integer
+ /// </summary>
+ FIDT_SBYTE = 6,
+ /// <summary>
+ /// 8-bit untyped data
+ /// </summary>
+ FIDT_UNDEFINED = 7,
+ /// <summary>
+ /// 16-bit signed integer
+ /// </summary>
+ FIDT_SSHORT = 8,
+ /// <summary>
+ /// 32-bit signed integer
+ /// </summary>
+ FIDT_SLONG = 9,
+ /// <summary>
+ /// 64-bit signed fraction
+ /// </summary>
+ FIDT_SRATIONAL = 10,
+ /// <summary>
+ /// 32-bit IEEE floating point
+ /// </summary>
+ FIDT_FLOAT = 11,
+ /// <summary>
+ /// 64-bit IEEE floating point
+ /// </summary>
+ FIDT_DOUBLE = 12,
+ /// <summary>
+ /// 32-bit unsigned integer (offset)
+ /// </summary>
+ FIDT_IFD = 13,
+ /// <summary>
+ /// 32-bit RGBQUAD
+ /// </summary>
+ FIDT_PALETTE = 14
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Metadata models supported by FreeImage.
+ /// </summary>
+ public enum FREE_IMAGE_MDMODEL
+ {
+ /// <summary>
+ /// No data
+ /// </summary>
+ FIMD_NODATA = -1,
+ /// <summary>
+ /// single comment or keywords
+ /// </summary>
+ FIMD_COMMENTS = 0,
+ /// <summary>
+ /// Exif-TIFF metadata
+ /// </summary>
+ FIMD_EXIF_MAIN = 1,
+ /// <summary>
+ /// Exif-specific metadata
+ /// </summary>
+ FIMD_EXIF_EXIF = 2,
+ /// <summary>
+ /// Exif GPS metadata
+ /// </summary>
+ FIMD_EXIF_GPS = 3,
+ /// <summary>
+ /// Exif maker note metadata
+ /// </summary>
+ FIMD_EXIF_MAKERNOTE = 4,
+ /// <summary>
+ /// Exif interoperability metadata
+ /// </summary>
+ FIMD_EXIF_INTEROP = 5,
+ /// <summary>
+ /// IPTC/NAA metadata
+ /// </summary>
+ FIMD_IPTC = 6,
+ /// <summary>
+ /// Abobe XMP metadata
+ /// </summary>
+ FIMD_XMP = 7,
+ /// <summary>
+ /// GeoTIFF metadata
+ /// </summary>
+ FIMD_GEOTIFF = 8,
+ /// <summary>
+ /// Animation metadata
+ /// </summary>
+ FIMD_ANIMATION = 9,
+ /// <summary>
+ /// Used to attach other metadata types to a dib
+ /// </summary>
+ FIMD_CUSTOM = 10
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags used in load functions.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_LOAD_FLAGS
+ {
+ /// <summary>
+ /// Default option for all types.
+ /// </summary>
+ DEFAULT = 0,
+ /// <summary>
+ /// Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color.
+ /// </summary>
+ GIF_LOAD256 = 1,
+ /// <summary>
+ /// 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading.
+ /// </summary>
+ GIF_PLAYBACK = 2,
+ /// <summary>
+ /// Convert to 32bpp and create an alpha channel from the AND-mask when loading.
+ /// </summary>
+ ICO_MAKEALPHA = 1,
+ /// <summary>
+ /// Load the file as fast as possible, sacrificing some quality.
+ /// </summary>
+ JPEG_FAST = 0x0001,
+ /// <summary>
+ /// Load the file with the best quality, sacrificing some speed.
+ /// </summary>
+ JPEG_ACCURATE = 0x0002,
+ /// <summary>
+ /// Load separated CMYK "as is" (use | to combine with other load flags).
+ /// </summary>
+ JPEG_CMYK = 0x0004,
+ /// <summary>
+ /// Load and rotate according to Exif 'Orientation' tag if available.
+ /// </summary>
+ JPEG_EXIFROTATE = 0x0008,
+ /// <summary>
+ /// Load the bitmap sized 768 x 512.
+ /// </summary>
+ PCD_BASE = 1,
+ /// <summary>
+ /// Load the bitmap sized 384 x 256.
+ /// </summary>
+ PCD_BASEDIV4 = 2,
+ /// <summary>
+ /// Load the bitmap sized 192 x 128.
+ /// </summary>
+ PCD_BASEDIV16 = 3,
+ /// <summary>
+ /// Avoid gamma correction.
+ /// </summary>
+ PNG_IGNOREGAMMA = 1,
+ /// <summary>
+ /// If set the loader converts RGB555 and ARGB8888 -> RGB888.
+ /// </summary>
+ TARGA_LOAD_RGB888 = 1,
+ /// <summary>
+ /// Reads tags for separated CMYK.
+ /// </summary>
+ TIFF_CMYK = 0x0001,
+ /// <summary>
+ /// Tries to load the JPEG preview image, embedded in
+ /// Exif Metadata or load the image as RGB 24-bit if no
+ /// preview image is available.
+ /// </summary>
+ RAW_PREVIEW = 0x1,
+ /// <summary>
+ /// Loads the image as RGB 24-bit.
+ /// </summary>
+ RAW_DISPLAY = 0x2,
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags used in save functions.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_SAVE_FLAGS
+ {
+ /// <summary>
+ /// Default option for all types.
+ /// </summary>
+ DEFAULT = 0,
+ /// <summary>
+ /// Save with run length encoding.
+ /// </summary>
+ BMP_SAVE_RLE = 1,
+ /// <summary>
+ /// Save data as float instead of as half (not recommended).
+ /// </summary>
+ EXR_FLOAT = 0x0001,
+ /// <summary>
+ /// Save with no compression.
+ /// </summary>
+ EXR_NONE = 0x0002,
+ /// <summary>
+ /// Save with zlib compression, in blocks of 16 scan lines.
+ /// </summary>
+ EXR_ZIP = 0x0004,
+ /// <summary>
+ /// Save with piz-based wavelet compression.
+ /// </summary>
+ EXR_PIZ = 0x0008,
+ /// <summary>
+ /// Save with lossy 24-bit float compression.
+ /// </summary>
+ EXR_PXR24 = 0x0010,
+ /// <summary>
+ /// Save with lossy 44% float compression - goes to 22% when combined with EXR_LC.
+ /// </summary>
+ EXR_B44 = 0x0020,
+ /// <summary>
+ /// Save images with one luminance and two chroma channels, rather than as RGB (lossy compression).
+ /// </summary>
+ EXR_LC = 0x0040,
+ /// <summary>
+ /// Save with superb quality (100:1).
+ /// </summary>
+ JPEG_QUALITYSUPERB = 0x80,
+ /// <summary>
+ /// Save with good quality (75:1).
+ /// </summary>
+ JPEG_QUALITYGOOD = 0x0100,
+ /// <summary>
+ /// Save with normal quality (50:1).
+ /// </summary>
+ JPEG_QUALITYNORMAL = 0x0200,
+ /// <summary>
+ /// Save with average quality (25:1).
+ /// </summary>
+ JPEG_QUALITYAVERAGE = 0x0400,
+ /// <summary>
+ /// Save with bad quality (10:1).
+ /// </summary>
+ JPEG_QUALITYBAD = 0x0800,
+ /// <summary>
+ /// Save as a progressive-JPEG (use | to combine with other save flags).
+ /// </summary>
+ JPEG_PROGRESSIVE = 0x2000,
+ /// <summary>
+ /// Save with high 4x1 chroma subsampling (4:1:1).
+ /// </summary>
+ JPEG_SUBSAMPLING_411 = 0x1000,
+ /// <summary>
+ /// Save with medium 2x2 medium chroma (4:2:0).
+ /// </summary>
+ JPEG_SUBSAMPLING_420 = 0x4000,
+ /// <summary>
+ /// Save with low 2x1 chroma subsampling (4:2:2).
+ /// </summary>
+ JPEG_SUBSAMPLING_422 = 0x8000,
+ /// <summary>
+ /// Save with no chroma subsampling (4:4:4).
+ /// </summary>
+ JPEG_SUBSAMPLING_444 = 0x10000,
+ /// <summary>
+ /// Save using ZLib level 1 compression flag
+ /// (default value is <see cref="PNG_Z_DEFAULT_COMPRESSION"/>).
+ /// </summary>
+ PNG_Z_BEST_SPEED = 0x0001,
+ /// <summary>
+ /// Save using ZLib level 6 compression flag (default recommended value).
+ /// </summary>
+ PNG_Z_DEFAULT_COMPRESSION = 0x0006,
+ /// <summary>
+ /// save using ZLib level 9 compression flag
+ /// (default value is <see cref="PNG_Z_DEFAULT_COMPRESSION"/>).
+ /// </summary>
+ PNG_Z_BEST_COMPRESSION = 0x0009,
+ /// <summary>
+ /// Save without ZLib compression.
+ /// </summary>
+ PNG_Z_NO_COMPRESSION = 0x0100,
+ /// <summary>
+ /// Save using Adam7 interlacing (use | to combine with other save flags).
+ /// </summary>
+ PNG_INTERLACED = 0x0200,
+ /// <summary>
+ /// If set the writer saves in ASCII format (i.e. P1, P2 or P3).
+ /// </summary>
+ PNM_SAVE_ASCII = 1,
+ /// <summary>
+ /// Stores tags for separated CMYK (use | to combine with compression flags).
+ /// </summary>
+ TIFF_CMYK = 0x0001,
+ /// <summary>
+ /// Save using PACKBITS compression.
+ /// </summary>
+ TIFF_PACKBITS = 0x0100,
+ /// <summary>
+ /// Save using DEFLATE compression (a.k.a. ZLIB compression).
+ /// </summary>
+ TIFF_DEFLATE = 0x0200,
+ /// <summary>
+ /// Save using ADOBE DEFLATE compression.
+ /// </summary>
+ TIFF_ADOBE_DEFLATE = 0x0400,
+ /// <summary>
+ /// Save without any compression.
+ /// </summary>
+ TIFF_NONE = 0x0800,
+ /// <summary>
+ /// Save using CCITT Group 3 fax encoding.
+ /// </summary>
+ TIFF_CCITTFAX3 = 0x1000,
+ /// <summary>
+ /// Save using CCITT Group 4 fax encoding.
+ /// </summary>
+ TIFF_CCITTFAX4 = 0x2000,
+ /// <summary>
+ /// Save using LZW compression.
+ /// </summary>
+ TIFF_LZW = 0x4000,
+ /// <summary>
+ /// Save using JPEG compression.
+ /// </summary>
+ TIFF_JPEG = 0x8000
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags for ICC profiles.
+ /// </summary>
+ [System.Flags]
+ public enum ICC_FLAGS : ushort
+ {
+ /// <summary>
+ /// Default value.
+ /// </summary>
+ FIICC_DEFAULT = 0x00,
+ /// <summary>
+ /// The color is CMYK.
+ /// </summary>
+ FIICC_COLOR_IS_CMYK = 0x01
+ }
+}
+
+ #endregion
+
+ #region Delegates
+
+namespace FreeImageAPI
+{
+ // Delegates used by the FreeImageIO structure
+
+ /// <summary>
+ /// Delegate for capturing FreeImage error messages.
+ /// </summary>
+ /// <param name="fif">The format of the image.</param>
+ /// <param name="message">The errormessage.</param>
+ // DLL_API is missing in the definition of the callbackfuntion.
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi, ThrowOnUnmappableChar = false)]
+ public delegate void OutputMessageFunction(FREE_IMAGE_FORMAT fif, string message);
+}
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Delegate to the C++ function <b>fread</b>.
+ /// </summary>
+ /// <param name="buffer">Pointer to read from.</param>
+ /// <param name="size">Item size in bytes.</param>
+ /// <param name="count">Maximum number of items to be read.</param>
+ /// <param name="handle">Handle/stream to read from.</param>
+ /// <returns>Number of full items actually read,
+ /// which may be less than count if an error occurs or
+ /// if the end of the file is encountered before reaching count.</returns>
+ public delegate uint ReadProc(IntPtr buffer, uint size, uint count, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fwrite</b>.
+ /// </summary>
+ /// <param name="buffer">Pointer to data to be written.</param>
+ /// <param name="size">Item size in bytes.</param>
+ /// <param name="count">Maximum number of items to be written.</param>
+ /// <param name="handle">Handle/stream to write to.</param>
+ /// <returns>Number of full items actually written,
+ /// which may be less than count if an error occurs.
+ /// Also, if an error occurs, the file-position indicator cannot be determined.</returns>
+ public delegate uint WriteProc(IntPtr buffer, uint size, uint count, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>fseek</b>.
+ /// </summary>
+ /// <param name="handle">Handle/stream to seek in.</param>
+ /// <param name="offset">Number of bytes from origin.</param>
+ /// <param name="origin">Initial position.</param>
+ /// <returns>If successful 0 is returned; otherwise a nonzero value. </returns>
+ public delegate int SeekProc(fi_handle handle, int offset, SeekOrigin origin);
+
+ /// <summary>
+ /// Delegate to the C++ function <b>ftell</b>.
+ /// </summary>
+ /// <param name="handle">Handle/stream to retrieve its currents position from.</param>
+ /// <returns>The current position.</returns>
+ public delegate int TellProc(fi_handle handle);
+
+ // Delegates used by 'Plugin' structure
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Delegate to a function that returns a string which describes
+ /// the plugins format.
+ /// </summary>
+ public delegate string FormatProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// a more detailed description.
+ /// </summary>
+ public delegate string DescriptionProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a comma seperated list
+ /// of file extensions the plugin can read or write.
+ /// </summary>
+ public delegate string ExtensionListProc();
+
+ /// <summary>
+ /// Delegate to a function that returns a regular expression that
+ /// can be used to idientify whether a file can be handled by the plugin.
+ /// </summary>
+ public delegate string RegExprProc();
+
+ /// <summary>
+ /// Delegate to a function that opens a file.
+ /// </summary>
+ public delegate IntPtr OpenProc(ref FreeImageIO io, fi_handle handle, bool read);
+
+ /// <summary>
+ /// Delegate to a function that closes a previosly opened file.
+ /// </summary>
+ public delegate void CloseProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that returns the number of pages of a multipage
+ /// bitmap if the plugin is capable of handling multipage bitmaps.
+ /// </summary>
+ public delegate int PageCountProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// UNKNOWN
+ /// </summary>
+ public delegate int PageCapabilityProc(ref FreeImageIO io, fi_handle handle, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that loads and decodes a bitmap into memory.
+ /// </summary>
+ public delegate FIBITMAP LoadProc(ref FreeImageIO io, fi_handle handle, int page, int flags, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that saves a bitmap.
+ /// </summary>
+ public delegate bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data);
+
+ /// <summary>
+ /// Delegate to a function that determines whether the source defined
+ /// by <param name="io"/> and <param name="handle"/> is a valid image.
+ /// </summary>
+ public delegate bool ValidateProc(ref FreeImageIO io, fi_handle handle);
+
+ /// <summary>
+ /// Delegate to a function that returns a string which contains
+ /// the plugin's mime type.
+ /// </summary>
+ public delegate string MimeProc();
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified color depth.
+ /// </summary>
+ public delegate bool SupportsExportBPPProc(int bpp);
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle the
+ /// specified image type.
+ /// </summary>
+ public delegate bool SupportsExportTypeProc(FREE_IMAGE_TYPE type);
+
+ /// <summary>
+ /// Delegate to a function that returns whether the plugin can handle
+ /// ICC-Profiles.
+ /// </summary>
+ public delegate bool SupportsICCProfilesProc();
+
+ /// <summary>
+ /// Callback function used by FreeImage to register plugins.
+ /// </summary>
+ public delegate void InitProc(ref Plugin plugin, int format_id);
+}
+
+ #endregion
+
+namespace FreeImageAPI
+{
+ public static partial class FreeImage
+ {
+ #region Constants
+
+ /// <summary>
+ /// Filename of the FreeImage library.
+ /// </summary>
+ private const string FreeImageLibrary = "FreeImage";
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_RED = 2;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_GREEN = 1;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_BLUE = 0;
+
+ /// <summary>
+ /// Number of bytes to shift left within a 4 byte block.
+ /// </summary>
+ public const int FI_RGBA_ALPHA = 3;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_RED_MASK = 0x00FF0000;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_GREEN_MASK = 0x0000FF00;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_BLUE_MASK = 0x000000FF;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const uint FI_RGBA_ALPHA_MASK = 0xFF000000;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_RED_SHIFT = 16;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_GREEN_SHIFT = 8;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_BLUE_SHIFT = 0;
+
+ /// <summary>
+ /// Number of bits to shift left within a 32 bit block.
+ /// </summary>
+ public const int FI_RGBA_ALPHA_SHIFT = 24;
+
+ /// <summary>
+ /// Mask indicating the position of color components of a 32 bit color.
+ /// </summary>
+ public const uint FI_RGBA_RGB_MASK = (FI_RGBA_RED_MASK | FI_RGBA_GREEN_MASK | FI_RGBA_BLUE_MASK);
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_RED_MASK = 0x7C00;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_GREEN_MASK = 0x03E0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_555_BLUE_MASK = 0x001F;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_RED_SHIFT = 10;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_GREEN_SHIFT = 5;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_555_BLUE_SHIFT = 0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_RED_MASK = 0xF800;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_GREEN_MASK = 0x07E0;
+
+ /// <summary>
+ /// Mask indicating the position of the given color.
+ /// </summary>
+ public const int FI16_565_BLUE_MASK = 0x001F;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_RED_SHIFT = 11;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_GREEN_SHIFT = 5;
+
+ /// <summary>
+ /// Number of bits to shift left within a 16 bit block.
+ /// </summary>
+ public const int FI16_565_BLUE_SHIFT = 0;
+
+ #endregion
+
+ #region General functions
+
+ /// <summary>
+ /// Initialises the library.
+ /// </summary>
+ /// <param name="load_local_plugins_only">
+ /// When the <paramref name="load_local_plugins_only"/> is true, FreeImage won't make use of external plugins.
+ /// </param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Initialise")]
+ private static extern void Initialise(bool load_local_plugins_only);
+
+ /// <summary>
+ /// Deinitialises the library.
+ /// </summary>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeInitialise")]
+ private static extern void DeInitialise();
+
+ /// <summary>
+ /// Returns a string containing the current version of the library.
+ /// </summary>
+ /// <returns>The current version of the library.</returns>
+ public static unsafe string GetVersion() { return PtrToStr(GetVersion_()); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetVersion")]
+ private static unsafe extern byte* GetVersion_();
+
+ /// <summary>
+ /// Returns a string containing a standard copyright message.
+ /// </summary>
+ /// <returns>A standard copyright message.</returns>
+ public static unsafe string GetCopyrightMessage() { return PtrToStr(GetCopyrightMessage_()); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetCopyrightMessage")]
+ private static unsafe extern byte* GetCopyrightMessage_();
+
+ /// <summary>
+ /// Calls the set error message function in FreeImage.
+ /// </summary>
+ /// <param name="fif">Format of the bitmaps.</param>
+ /// <param name="message">The error message.</param>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_OutputMessageProc")]
+ public static extern void OutputMessageProc(FREE_IMAGE_FORMAT fif, string message);
+
+ /// <summary>
+ /// You use the function FreeImage_SetOutputMessage to capture the log string
+ /// so that you can show it to the user of the program.
+ /// The callback is implemented in the <see cref="FreeImageEngine.Message"/> event of this class.
+ /// </summary>
+ /// <remarks>The function is private because FreeImage can only have a single
+ /// callback function. To use the callback use the <see cref="FreeImageEngine.Message"/>
+ /// event of this class.</remarks>
+ /// <param name="omf">Handler to the callback function.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetOutputMessage")]
+ internal static extern void SetOutputMessage(OutputMessageFunction omf);
+
+ #endregion
+
+ #region Bitmap management functions
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Allocate")]
+ public static extern FIBITMAP Allocate(int width, int height, int bpp,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateT")]
+ public static extern FIBITMAP AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateEx")]
+ internal static extern FIBITMAP AllocateEx(int width, int height, int bpp,
+ IntPtr color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AllocateExT")]
+ internal static extern FIBITMAP AllocateExT(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ IntPtr color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask);
+
+ /// <summary>
+ /// Makes an exact reproduction of an existing bitmap, including metadata and attached profile if any.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Clone")]
+ public static extern FIBITMAP Clone(FIBITMAP dib);
+
+ /// <summary>
+ /// Deletes a previously loaded FIBITMAP from memory.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Unload")]
+ public static extern void Unload(FIBITMAP dib);
+
+ /// <summary>
+ /// Decodes a bitmap, allocates memory for it and returns it as a FIBITMAP.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="filename">Name of the file to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_LoadU")]
+ public static extern FIBITMAP Load(FREE_IMAGE_FORMAT fif, string filename, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Decodes a bitmap, allocates memory for it and returns it as a FIBITMAP.
+ /// The filename supports UNICODE.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="filename">Name of the file to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_LoadU")]
+ private static extern FIBITMAP LoadU(FREE_IMAGE_FORMAT fif, string filename, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Loads a bitmap from an arbitrary source.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="io">A FreeImageIO structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadFromHandle")]
+ public static extern FIBITMAP LoadFromHandle(FREE_IMAGE_FORMAT fif, ref FreeImageIO io, fi_handle handle, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a file.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_SaveU")]
+ public static extern bool Save(FREE_IMAGE_FORMAT fif, FIBITMAP dib, string filename, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a file.
+ /// The filename supports UNICODE.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_SaveU")]
+ private static extern bool SaveU(FREE_IMAGE_FORMAT fif, FIBITMAP dib, string filename, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Saves a bitmap to an arbitrary source.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="io">A FreeImageIO structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SaveToHandle")]
+ public static extern bool SaveToHandle(FREE_IMAGE_FORMAT fif, FIBITMAP dib, ref FreeImageIO io, fi_handle handle,
+ FREE_IMAGE_SAVE_FLAGS flags);
+
+ #endregion
+
+ #region Memory I/O streams
+
+ /// <summary>
+ /// Open a memory stream.
+ /// </summary>
+ /// <param name="data">Pointer to the data in memory.</param>
+ /// <param name="size_in_bytes">Length of the data in byte.</param>
+ /// <returns>Handle to a memory stream.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMemory")]
+ public static extern FIMEMORY OpenMemory(IntPtr data, uint size_in_bytes);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMemory")]
+ internal static extern FIMEMORY OpenMemoryEx(byte[] data, uint size_in_bytes);
+
+ /// <summary>
+ /// Close and free a memory stream.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloseMemory")]
+ public static extern void CloseMemory(FIMEMORY stream);
+
+ /// <summary>
+ /// Decodes a bitmap from a stream, allocates memory for it and returns it as a FIBITMAP.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadFromMemory")]
+ public static extern FIBITMAP LoadFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY stream, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Saves a previosly loaded FIBITMAP to a stream.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SaveToMemory")]
+ public static extern bool SaveToMemory(FREE_IMAGE_FORMAT fif, FIBITMAP dib, FIMEMORY stream, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Gets the current position of a memory handle.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <returns>The current file position if successful, -1 otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TellMemory")]
+ public static extern int TellMemory(FIMEMORY stream);
+
+ /// <summary>
+ /// Moves the memory handle to a specified location.
+ /// </summary>
+ /// <param name="stream">Handle to a memory stream.</param>
+ /// <param name="offset">Number of bytes from origin.</param>
+ /// <param name="origin">Initial position.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SeekMemory")]
+ public static extern bool SeekMemory(FIMEMORY stream, int offset, System.IO.SeekOrigin origin);
+
+ /// <summary>
+ /// Provides a direct buffer access to a memory stream.
+ /// </summary>
+ /// <param name="stream">The target memory stream.</param>
+ /// <param name="data">Pointer to the data in memory.</param>
+ /// <param name="size_in_bytes">Size of the data in bytes.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AcquireMemory")]
+ public static extern bool AcquireMemory(FIMEMORY stream, ref IntPtr data, ref uint size_in_bytes);
+
+ /// <summary>
+ /// Reads data from a memory stream.
+ /// </summary>
+ /// <param name="buffer">The buffer to store the data in.</param>
+ /// <param name="size">Size in bytes of the items.</param>
+ /// <param name="count">Number of items to read.</param>
+ /// <param name="stream">The stream to read from.
+ /// The memory pointer associated with stream is increased by the number of bytes actually read.</param>
+ /// <returns>The number of full items actually read.
+ /// May be less than count on error or stream-end.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ReadMemory")]
+ public static extern uint ReadMemory(byte[] buffer, uint size, uint count, FIMEMORY stream);
+
+ /// <summary>
+ /// Writes data to a memory stream.
+ /// </summary>
+ /// <param name="buffer">The buffer to read the data from.</param>
+ /// <param name="size">Size in bytes of the items.</param>
+ /// <param name="count">Number of items to write.</param>
+ /// <param name="stream">The stream to write to.
+ /// The memory pointer associated with stream is increased by the number of bytes actually written.</param>
+ /// <returns>The number of full items actually written.
+ /// May be less than count on error or stream-end.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_WriteMemory")]
+ public static extern uint WriteMemory(byte[] buffer, uint size, uint count, FIMEMORY stream);
+
+ /// <summary>
+ /// Open a multi-page bitmap from a memory stream.
+ /// </summary>
+ /// <param name="fif">Type of the bitmap.</param>
+ /// <param name="stream">The stream to decode.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LoadMultiBitmapFromMemory")]
+ public static extern FIMULTIBITMAP LoadMultiBitmapFromMemory(FREE_IMAGE_FORMAT fif, FIMEMORY stream, FREE_IMAGE_LOAD_FLAGS flags);
+
+ #endregion
+
+ #region Plugin functions
+
+ /// <summary>
+ /// Registers a new plugin to be used in FreeImage.
+ /// </summary>
+ /// <param name="proc_address">Pointer to the function that initialises the plugin.</param>
+ /// <param name="format">A string describing the format of the plugin.</param>
+ /// <param name="description">A string describing the plugin.</param>
+ /// <param name="extension">A string witha comma sperated list of extensions. f.e: "pl,pl2,pl4"</param>
+ /// <param name="regexpr">A regular expression used to identify the bitmap.</param>
+ /// <returns>The format idientifier assigned by FreeImage.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_RegisterLocalPlugin")]
+ public static extern FREE_IMAGE_FORMAT RegisterLocalPlugin(InitProc proc_address,
+ string format, string description, string extension, string regexpr);
+
+ /// <summary>
+ /// Registers a new plugin to be used in FreeImage. The plugin is residing in a DLL.
+ /// The Init function must be called �Init� and must use the stdcall calling convention.
+ /// </summary>
+ /// <param name="path">Complete path to the dll file hosting the plugin.</param>
+ /// <param name="format">A string describing the format of the plugin.</param>
+ /// <param name="description">A string describing the plugin.</param>
+ /// <param name="extension">A string witha comma sperated list of extensions. f.e: "pl,pl2,pl4"</param>
+ /// <param name="regexpr">A regular expression used to identify the bitmap.</param>
+ /// <returns>The format idientifier assigned by FreeImage.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_RegisterExternalPlugin")]
+ public static extern FREE_IMAGE_FORMAT RegisterExternalPlugin(string path,
+ string format, string description, string extension, string regexpr);
+
+ /// <summary>
+ /// Retrieves the number of FREE_IMAGE_FORMAT identifiers being currently registered.
+ /// </summary>
+ /// <returns>The number of registered formats.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFCount")]
+ public static extern int GetFIFCount();
+
+ /// <summary>
+ /// Enables or disables a plugin.
+ /// </summary>
+ /// <param name="fif">The plugin to enable or disable.</param>
+ /// <param name="enable">True: enable the plugin. false: disable the plugin.</param>
+ /// <returns>The previous state of the plugin.
+ /// 1 - enabled. 0 - disables. -1 plugin does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPluginEnabled")]
+ public static extern int SetPluginEnabled(FREE_IMAGE_FORMAT fif, bool enable);
+
+ /// <summary>
+ /// Retrieves the state of a plugin.
+ /// </summary>
+ /// <param name="fif">The plugin to check.</param>
+ /// <returns>1 - enabled. 0 - disables. -1 plugin does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsPluginEnabled")]
+ public static extern int IsPluginEnabled(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a <see cref="FREE_IMAGE_FORMAT"/> identifier from the format string that was used to register the FIF.
+ /// </summary>
+ /// <param name="format">The string that was used to register the plugin.</param>
+ /// <returns>A <see cref="FREE_IMAGE_FORMAT"/> identifier from the format.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetFIFFromFormat")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromFormat(string format);
+
+ /// <summary>
+ /// Returns a <see cref="FREE_IMAGE_FORMAT"/> identifier from a MIME content type string
+ /// (MIME stands for Multipurpose Internet Mail Extension).
+ /// </summary>
+ /// <param name="mime">A MIME content type.</param>
+ /// <returns>A <see cref="FREE_IMAGE_FORMAT"/> identifier from the MIME.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetFIFFromMime")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromMime(string mime);
+
+ /// <summary>
+ /// Returns the string that was used to register a plugin from the system assigned <see cref="FREE_IMAGE_FORMAT"/>.
+ /// </summary>
+ /// <param name="fif">The assigned <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>The string that was used to register the plugin.</returns>
+ public static unsafe string GetFormatFromFIF(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFormatFromFIF_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFormatFromFIF")]
+ private static unsafe extern byte* GetFormatFromFIF_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a comma-delimited file extension list describing the bitmap formats the given plugin can read and/or write.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A comma-delimited file extension list.</returns>
+ public static unsafe string GetFIFExtensionList(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFExtensionList_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFExtensionList")]
+ private static unsafe extern byte* GetFIFExtensionList_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a descriptive string that describes the bitmap formats the given plugin can read and/or write.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A descriptive string that describes the bitmap formats.</returns>
+ public static unsafe string GetFIFDescription(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFDescription_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFDescription")]
+ private static unsafe extern byte* GetFIFDescription_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Returns a regular expression string that can be used by a regular expression engine to identify the bitmap.
+ /// FreeImageQt makes use of this function.
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A regular expression string.</returns>
+ public static unsafe string GetFIFRegExpr(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFRegExpr_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFRegExpr")]
+ private static unsafe extern byte* GetFIFRegExpr_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Given a <see cref="FREE_IMAGE_FORMAT"/> identifier, returns a MIME content type string (MIME stands for Multipurpose Internet Mail Extension).
+ /// </summary>
+ /// <param name="fif">The desired <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>A MIME content type string.</returns>
+ public static unsafe string GetFIFMimeType(FREE_IMAGE_FORMAT fif) { return PtrToStr(GetFIFMimeType_(fif)); }
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFIFMimeType")]
+ private static unsafe extern byte* GetFIFMimeType_(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// This function takes a filename or a file-extension and returns the plugin that can
+ /// read/write files with that extension in the form of a <see cref="FREE_IMAGE_FORMAT"/> identifier.
+ /// </summary>
+ /// <param name="filename">The filename or -extension.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFIFFromFilenameU")]
+ public static extern FREE_IMAGE_FORMAT GetFIFFromFilename(string filename);
+
+ /// <summary>
+ /// This function takes a filename or a file-extension and returns the plugin that can
+ /// read/write files with that extension in the form of a <see cref="FREE_IMAGE_FORMAT"/> identifier.
+ /// Supports UNICODE filenames.
+ /// </summary>
+ /// <param name="filename">The filename or -extension.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFIFFromFilenameU")]
+ private static extern FREE_IMAGE_FORMAT GetFIFFromFilenameU(string filename);
+
+ /// <summary>
+ /// Checks if a plugin can load bitmaps.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can load bitmaps, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsReading")]
+ public static extern bool FIFSupportsReading(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Checks if a plugin can save bitmaps.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can save bitmaps, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsWriting")]
+ public static extern bool FIFSupportsWriting(FREE_IMAGE_FORMAT fif);
+
+ /// <summary>
+ /// Checks if a plugin can save bitmaps in the desired bit depth.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <param name="bpp">The desired bit depth.</param>
+ /// <returns>True if the plugin can save bitmaps in the desired bit depth, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsExportBPP")]
+ public static extern bool FIFSupportsExportBPP(FREE_IMAGE_FORMAT fif, int bpp);
+
+ /// <summary>
+ /// Checks if a plugin can save a bitmap in the desired data type.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <param name="type">The desired image type.</param>
+ /// <returns>True if the plugin can save bitmaps as the desired type, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsExportType")]
+ public static extern bool FIFSupportsExportType(FREE_IMAGE_FORMAT fif, FREE_IMAGE_TYPE type);
+
+ /// <summary>
+ /// Checks if a plugin can load or save an ICC profile.
+ /// </summary>
+ /// <param name="fif">The <see cref="FREE_IMAGE_FORMAT"/> of the plugin.</param>
+ /// <returns>True if the plugin can load or save an ICC profile, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FIFSupportsICCProfiles")]
+ public static extern bool FIFSupportsICCProfiles(FREE_IMAGE_FORMAT fif);
+
+ #endregion
+
+ #region Multipage functions
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="fif">Format of the image.</param>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMultiBitmap")]
+ public static extern FIMULTIBITMAP OpenMultiBitmap(FREE_IMAGE_FORMAT fif, string filename, bool create_new,
+ bool read_only, bool keep_cache_in_memory, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Loads a FreeImage multi-pages bitmap from the specified handle
+ /// using the specified functions.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="fif">Format of the image.</param>
+ /// <param name="io">IO functions used to read from the specified handle.</param>
+ /// <param name="handle">The handle to load the bitmap from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_OpenMultiBitmapFromHandle")]
+ public static extern FIMULTIBITMAP OpenMultiBitmapFromHandle(FREE_IMAGE_FORMAT fif, ref FreeImageIO io,
+ fi_handle handle, FREE_IMAGE_LOAD_FLAGS flags);
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only, applies any changes made to it.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloseMultiBitmap")]
+ private static extern bool CloseMultiBitmap_(FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags);
+
+ /// <summary>
+ /// Returns the number of pages currently available in the multi-paged bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Number of pages.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPageCount")]
+ public static extern int GetPageCount(FIMULTIBITMAP bitmap);
+
+ /// <summary>
+ /// Appends a new page to the end of the bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AppendPage")]
+ public static extern void AppendPage(FIMULTIBITMAP bitmap, FIBITMAP data);
+
+ /// <summary>
+ /// Inserts a new page before the given position in the bitmap.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Page has to be a number smaller than the current number of pages available in the bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_InsertPage")]
+ public static extern void InsertPage(FIMULTIBITMAP bitmap, int page, FIBITMAP data);
+
+ /// <summary>
+ /// Deletes the page on the given position.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Number of the page to delete.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeletePage")]
+ public static extern void DeletePage(FIMULTIBITMAP bitmap, int page);
+
+ /// <summary>
+ /// Locks a page in memory for editing.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="page">Number of the page to lock.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_LockPage")]
+ public static extern FIBITMAP LockPage(FIMULTIBITMAP bitmap, int page);
+
+ /// <summary>
+ /// Unlocks a previously locked page and gives it back to the multi-page engine.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="data">Handle to a FreeImage bitmap.</param>
+ /// <param name="changed">If true, the page is applied to the multi-page bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_UnlockPage")]
+ public static extern void UnlockPage(FIMULTIBITMAP bitmap, FIBITMAP data, bool changed);
+
+ /// <summary>
+ /// Moves the source page to the position of the target page.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="target">New position of the page.</param>
+ /// <param name="source">Old position of the page.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MovePage")]
+ public static extern bool MovePage(FIMULTIBITMAP bitmap, int target, int source);
+
+ /// <summary>
+ /// Returns an array of page-numbers that are currently locked in memory.
+ /// When the pages parameter is null, the size of the array is returned in the count variable.
+ /// </summary>
+ /// <example>
+ /// <code>
+ /// int[] lockedPages = null;
+ /// int count = 0;
+ /// GetLockedPageNumbers(dib, lockedPages, ref count);
+ /// lockedPages = new int[count];
+ /// GetLockedPageNumbers(dib, lockedPages, ref count);
+ /// </code>
+ /// </example>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="pages">The list of locked pages in the multi-pages bitmap.
+ /// If set to null, count will contain the number of pages.</param>
+ /// <param name="count">If <paramref name="pages"/> is set to null count will contain the number of locked pages.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetLockedPageNumbers")]
+ public static extern bool GetLockedPageNumbers(FIMULTIBITMAP bitmap, int[] pages, ref int count);
+
+ #endregion
+
+ #region Filetype functions
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// </summary>
+ /// <param name="filename">Name of the file to analyze.</param>
+ /// <param name="size">Reserved parameter - use 0.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFileTypeU")]
+ public static extern FREE_IMAGE_FORMAT GetFileType(string filename, int size);
+
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// Supports UNICODE filenames.
+ /// </summary>
+ /// <param name="filename">Name of the file to analyze.</param>
+ /// <param name="size">Reserved parameter - use 0.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_GetFileTypeU")]
+ private static extern FREE_IMAGE_FORMAT GetFileTypeU(string filename, int size);
+
+ /// <summary>
+ /// Uses the <see cref="FreeImageIO"/> structure as described in the topic bitmap management functions
+ /// to identify a bitmap type.
+ /// </summary>
+ /// <param name="io">A <see cref="FreeImageIO"/> structure with functionpointers to handle the source.</param>
+ /// <param name="handle">A handle to the source.</param>
+ /// <param name="size">Size in bytes of the source.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFileTypeFromHandle")]
+ public static extern FREE_IMAGE_FORMAT GetFileTypeFromHandle(ref FreeImageIO io, fi_handle handle, int size);
+
+ /// <summary>
+ /// Uses a memory handle to identify a bitmap type.
+ /// </summary>
+ /// <param name="stream">Pointer to the stream.</param>
+ /// <param name="size">Size in bytes of the source.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetFileTypeFromMemory")]
+ public static extern FREE_IMAGE_FORMAT GetFileTypeFromMemory(FIMEMORY stream, int size);
+
+ #endregion
+
+ #region Helper functions
+
+ /// <summary>
+ /// Returns whether the platform is using Little Endian.
+ /// </summary>
+ /// <returns>Returns true if the platform is using Litte Endian, else false.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsLittleEndian")]
+ public static extern bool IsLittleEndian();
+
+ /// <summary>
+ /// Converts a X11 color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="szColor">Name of the color to convert.</param>
+ /// <param name="nRed">Red component.</param>
+ /// <param name="nGreen">Green component.</param>
+ /// <param name="nBlue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_LookupX11Color")]
+ public static extern bool LookupX11Color(string szColor, out byte nRed, out byte nGreen, out byte nBlue);
+
+ /// <summary>
+ /// Converts a SVG color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="szColor">Name of the color to convert.</param>
+ /// <param name="nRed">Red component.</param>
+ /// <param name="nGreen">Green component.</param>
+ /// <param name="nBlue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_LookupSVGColor")]
+ public static extern bool LookupSVGColor(string szColor, out byte nRed, out byte nGreen, out byte nBlue);
+
+ #endregion
+
+ #region Pixel access functions
+
+ /// <summary>
+ /// Returns a pointer to the data-bits of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the data-bits.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBits")]
+ public static extern IntPtr GetBits(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the start of the given scanline in the bitmap's data-bits.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="scanline">Number of the scanline.</param>
+ /// <returns>Pointer to the scanline.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetScanLine")]
+ public static extern IntPtr GetScanLine(FIBITMAP dib, int scanline);
+
+ /// <summary>
+ /// Get the pixel index of a palettized image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The pixel index.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPixelIndex")]
+ public static extern bool GetPixelIndex(FIBITMAP dib, uint x, uint y, out byte value);
+
+ /// <summary>
+ /// Get the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The pixel color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPixelColor")]
+ public static extern bool GetPixelColor(FIBITMAP dib, uint x, uint y, out RGBQUAD value);
+
+ /// <summary>
+ /// Set the pixel index of a palettized image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The new pixel index.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPixelIndex")]
+ public static extern bool SetPixelIndex(FIBITMAP dib, uint x, uint y, ref byte value);
+
+ /// <summary>
+ /// Set the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="x">Pixel position in horizontal direction.</param>
+ /// <param name="y">Pixel position in vertical direction.</param>
+ /// <param name="value">The new pixel color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetPixelColor")]
+ public static extern bool SetPixelColor(FIBITMAP dib, uint x, uint y, ref RGBQUAD value);
+
+ #endregion
+
+ #region Bitmap information functions
+
+ /// <summary>
+ /// Retrieves the type of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetImageType")]
+ public static extern FREE_IMAGE_TYPE GetImageType(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the number of colors used in a bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Palette-size for palletised bitmaps, and 0 for high-colour bitmaps.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetColorsUsed")]
+ public static extern uint GetColorsUsed(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the size of one pixel in the bitmap in bits.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Size of one pixel in the bitmap in bits.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBPP")]
+ public static extern uint GetBPP(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in pixel units.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetWidth")]
+ public static extern uint GetWidth(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the height of the bitmap in pixel units.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Height of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetHeight")]
+ public static extern uint GetHeight(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap in bytes.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetLine")]
+ public static extern uint GetLine(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary,
+ /// also known as pitch or stride or scan width.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>With of the bitmap in bytes.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPitch")]
+ public static extern uint GetPitch(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the size of the DIB-element of a FIBITMAP in memory.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Size of the DIB-element</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDIBSize")]
+ public static extern uint GetDIBSize(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the bitmap's palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the bitmap's palette.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetPalette")]
+ public static extern IntPtr GetPalette(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The horizontal resolution, in pixels-per-meter.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDotsPerMeterX")]
+ public static extern uint GetDotsPerMeterX(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The vertical resolution, in pixels-per-meter.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetDotsPerMeterY")]
+ public static extern uint GetDotsPerMeterY(FIBITMAP dib);
+
+ /// <summary>
+ /// Set the horizontal resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new horizontal resolution.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetDotsPerMeterX")]
+ public static extern void SetDotsPerMeterX(FIBITMAP dib, uint res);
+
+ /// <summary>
+ /// Set the vertical resolution, in pixels-per-meter, of the target device for the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new vertical resolution.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetDotsPerMeterY")]
+ public static extern void SetDotsPerMeterY(FIBITMAP dib, uint res);
+
+ /// <summary>
+ /// Returns a pointer to the <see cref="BITMAPINFOHEADER"/> of the DIB-element in a FIBITMAP.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Poiter to the header of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetInfoHeader")]
+ public static extern IntPtr GetInfoHeader(FIBITMAP dib);
+
+ /// <summary>
+ /// Alias for FreeImage_GetInfoHeader that returns a pointer to a <see cref="BITMAPINFO"/>
+ /// rather than to a <see cref="BITMAPINFOHEADER"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the <see cref="BITMAPINFO"/> structure for the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetInfo")]
+ public static extern IntPtr GetInfo(FIBITMAP dib);
+
+ /// <summary>
+ /// Investigates the color type of the bitmap by reading the bitmap's pixel bits and analysing them.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The color type of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetColorType")]
+ public static extern FREE_IMAGE_COLOR_TYPE GetColorType(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the red color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for RED.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetRedMask")]
+ public static extern uint GetRedMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the green color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for green.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetGreenMask")]
+ public static extern uint GetGreenMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a bit pattern describing the blue color component of a pixel in a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The bit pattern for blue.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBlueMask")]
+ public static extern uint GetBlueMask(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the number of transparent colors in a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The number of transparent colors in a palletised bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparencyCount")]
+ public static extern uint GetTransparencyCount(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns a pointer to the bitmap's transparency table.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the bitmap's transparency table.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparencyTable")]
+ public static extern IntPtr GetTransparencyTable(FIBITMAP dib);
+
+ /// <summary>
+ /// Tells FreeImage if it should make use of the transparency table
+ /// or the alpha channel that may accompany a bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="enabled">True to enable the transparency, false to disable.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparent")]
+ public static extern void SetTransparent(FIBITMAP dib, bool enabled);
+
+ /// <summary>
+ /// Set the bitmap's transparency table. Only affects palletised bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="table">Pointer to the bitmap's new transparency table.</param>
+ /// <param name="count">The number of transparent colors in the new transparency table.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparencyTable")]
+ internal static extern void SetTransparencyTable(FIBITMAP dib, byte[] table, int count);
+
+ /// <summary>
+ /// Returns whether the transparency table is enabled.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true when the transparency table is enabled (1-, 4- or 8-bit images)
+ /// or when the input dib contains alpha values (32-bit images). Returns false otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_IsTransparent")]
+ public static extern bool IsTransparent(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns whether the bitmap has a file background color.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true when the image has a file background color, false otherwise.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_HasBackgroundColor")]
+ public static extern bool HasBackgroundColor(FIBITMAP dib);
+
+ /// <summary>
+ /// Returns the file background color of an image.
+ /// For 8-bit images, the color index in the palette is returned in the
+ /// rgbReserved member of the bkcolor parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The background color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetBackgroundColor")]
+ public static extern bool GetBackgroundColor(FIBITMAP dib, out RGBQUAD bkcolor);
+
+ /// <summary>
+ /// Set the file background color of an image.
+ /// When saving an image to PNG, this background color is transparently saved to the PNG file.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The new background color.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetBackgroundColor")]
+ public static unsafe extern bool SetBackgroundColor(FIBITMAP dib, ref RGBQUAD bkcolor);
+
+ /// <summary>
+ /// Set the file background color of an image.
+ /// When saving an image to PNG, this background color is transparently saved to the PNG file.
+ /// When the bkcolor parameter is null, the background color is removed from the image.
+ /// <para>
+ /// This overloaded version of the function with an array parameter is provided to allow
+ /// passing <c>null</c> in the <paramref name="bkcolor"/> parameter. This is similar to the
+ /// original C/C++ function. Passing <c>null</c> as <paramref name="bkcolor"/> parameter will
+ /// unset the dib's previously set background color.
+ /// </para>
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="bkcolor">The new background color.
+ /// The first entry in the array is used.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <example>
+ /// <code>
+ /// // create a RGBQUAD color
+ /// RGBQUAD color = new RGBQUAD(Color.Green);
+ ///
+ /// // set the dib's background color (using the other version of the function)
+ /// FreeImage.SetBackgroundColor(dib, ref color);
+ ///
+ /// // remove it again (this only works due to the array parameter RGBQUAD[])
+ /// FreeImage.SetBackgroundColor(dib, null);
+ /// </code>
+ /// </example>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetBackgroundColor")]
+ public static unsafe extern bool SetBackgroundColor(FIBITMAP dib, RGBQUAD[] bkcolor);
+
+ /// <summary>
+ /// Sets the index of the palette entry to be used as transparent color
+ /// for the image specified. Does nothing on high color images.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="index">The index of the palette entry to be set as transparent color.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTransparentIndex")]
+ public static extern void SetTransparentIndex(FIBITMAP dib, int index);
+
+ /// <summary>
+ /// Returns the palette entry used as transparent color for the image specified.
+ /// Works for palletised images only and returns -1 for high color
+ /// images or if the image has no color set to be transparent.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>the index of the palette entry used as transparent color for
+ /// the image specified or -1 if there is no transparent color found
+ /// (e.g. the image is a high color image).</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTransparentIndex")]
+ public static extern int GetTransparentIndex(FIBITMAP dib);
+
+ #endregion
+
+ #region ICC profile functions
+
+ /// <summary>
+ /// Retrieves the <see cref="FIICCPROFILE"/> data of the bitmap.
+ /// This function can also be called safely, when the original format does not support profiles.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The <see cref="FIICCPROFILE"/> data of the bitmap.</returns>
+ public static FIICCPROFILE GetICCProfileEx(FIBITMAP dib) { unsafe { return *(FIICCPROFILE*)FreeImage.GetICCProfile(dib); } }
+
+ /// <summary>
+ /// Retrieves a pointer to the <see cref="FIICCPROFILE"/> data of the bitmap.
+ /// This function can also be called safely, when the original format does not support profiles.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Pointer to the <see cref="FIICCPROFILE"/> data of the bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetICCProfile")]
+ public static extern IntPtr GetICCProfile(FIBITMAP dib);
+
+ /// <summary>
+ /// Creates a new <see cref="FIICCPROFILE"/> block from ICC profile data previously read from a file
+ /// or built by a color management system. The profile data is attached to the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">Pointer to the new <see cref="FIICCPROFILE"/> data.</param>
+ /// <param name="size">Size of the <see cref="FIICCPROFILE"/> data.</param>
+ /// <returns>Pointer to the created <see cref="FIICCPROFILE"/> structure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CreateICCProfile")]
+ public static extern IntPtr CreateICCProfile(FIBITMAP dib, byte[] data, int size);
+
+ /// <summary>
+ /// This function destroys an <see cref="FIICCPROFILE"/> previously created by <see cref="CreateICCProfile(FIBITMAP,byte[],int)"/>.
+ /// After this call the bitmap will contain no profile information.
+ /// This function should be called to ensure that a stored bitmap will not contain any profile information.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DestroyICCProfile")]
+ public static extern void DestroyICCProfile(FIBITMAP dib);
+
+ #endregion
+
+ #region Conversion functions
+
+ /// <summary>
+ /// Converts a bitmap to 4 bits.
+ /// If the bitmap was a high-color bitmap (16, 24 or 32-bit) or if it was a
+ /// monochrome or greyscale bitmap (1 or 8-bit), the end result will be a
+ /// greyscale bitmap, otherwise (1-bit palletised bitmaps) it will be a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo4Bits")]
+ public static extern FIBITMAP ConvertTo4Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 8 bits. If the bitmap was a high-color bitmap (16, 24 or 32-bit)
+ /// or if it was a monochrome or greyscale bitmap (1 or 4-bit), the end result will be a
+ /// greyscale bitmap, otherwise (1 or 4-bit palletised bitmaps) it will be a palletised bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo8Bits")]
+ public static extern FIBITMAP ConvertTo8Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to a 8-bit greyscale image with a linear ramp.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToGreyscale")]
+ public static extern FIBITMAP ConvertToGreyscale(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 16 bits, where each pixel has a color pattern of
+ /// 5 bits red, 5 bits green and 5 bits blue. One bit in each pixel is unused.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo16Bits555")]
+ public static extern FIBITMAP ConvertTo16Bits555(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 16 bits, where each pixel has a color pattern of
+ /// 5 bits red, 6 bits green and 5 bits blue.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo16Bits565")]
+ public static extern FIBITMAP ConvertTo16Bits565(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 24 bits. A clone of the input bitmap is returned for 24-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo24Bits")]
+ public static extern FIBITMAP ConvertTo24Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a bitmap to 32 bits. A clone of the input bitmap is returned for 32-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertTo32Bits")]
+ public static extern FIBITMAP ConvertTo32Bits(FIBITMAP dib);
+
+ /// <summary>
+ /// Quantizes a high-color 24-bit bitmap to an 8-bit palette color bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ColorQuantize")]
+ public static extern FIBITMAP ColorQuantize(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize);
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/> method that
+ /// provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// partial or full provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ColorQuantizeEx")]
+ public static extern FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, int ReserveSize, RGBQUAD[] ReservePalette);
+
+ /// <summary>
+ /// Converts a bitmap to 1-bit monochrome bitmap using a threshold T between [0..255].
+ /// The function first converts the bitmap to a 8-bit greyscale bitmap.
+ /// Then, any brightness level that is less than T is set to zero, otherwise to 1.
+ /// For 1-bit input bitmaps, the function clones the input bitmap and builds a monochrome palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="t">The threshold.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Threshold")]
+ public static extern FIBITMAP Threshold(FIBITMAP dib, byte t);
+
+ /// <summary>
+ /// Converts a bitmap to 1-bit monochrome bitmap using a dithering algorithm.
+ /// For 1-bit input bitmaps, the function clones the input bitmap and builds a monochrome palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="algorithm">The dithering algorithm to use.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Dither")]
+ public static extern FIBITMAP Dither(FIBITMAP dib, FREE_IMAGE_DITHER algorithm);
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block containing the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertFromRawBits")]
+ public static extern FIBITMAP ConvertFromRawBits(IntPtr bits, int width, int height, int pitch,
+ uint bpp, uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Array of bytes containing the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertFromRawBits")]
+ public static extern FIBITMAP ConvertFromRawBits(byte[] bits, int width, int height, int pitch,
+ uint bpp, uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a raw bitmap, that is a raw piece of memory.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block receiving the raw bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="pitch">The desired total width in bytes of a scanline in the raw bitmap,
+ /// including any padding bytes.</param>
+ /// <param name="bpp">The desired bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap will be stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRawBits")]
+ public static extern void ConvertToRawBits(IntPtr bits, FIBITMAP dib, int pitch, uint bpp,
+ uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a raw bitmap, that is a raw piece of memory.
+ /// </summary>
+ /// <param name="bits">Array of bytes receiving the raw bitmap.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="pitch">The desired total width in bytes of a scanline in the raw bitmap,
+ /// including any padding bytes.</param>
+ /// <param name="bpp">The desired bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The desired bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap will be stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRawBits")]
+ public static extern void ConvertToRawBits(byte[] bits, FIBITMAP dib, int pitch, uint bpp,
+ uint red_mask, uint green_mask, uint blue_mask, bool topdown);
+
+ /// <summary>
+ /// Converts a 24- or 32-bit RGB(A) standard image or a 48-bit RGB image to a FIT_RGBF type image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToRGBF")]
+ public static extern FIBITMAP ConvertToRGBF(FIBITMAP dib);
+
+ /// <summary>
+ /// Converts a non standard image whose color type is FIC_MINISBLACK
+ /// to a standard 8-bit greyscale image.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="scale_linear">When true the conversion is done by scaling linearly
+ /// each pixel value from [min, max] to an integer value between [0..255],
+ /// where min and max are the minimum and maximum pixel values in the image.
+ /// When false the conversion is done by rounding each pixel value to an integer between [0..255].
+ ///
+ /// Rounding is done using the following formula:
+ ///
+ /// dst_pixel = (BYTE) MIN(255, MAX(0, q)) where int q = int(src_pixel + 0.5);</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToStandardType")]
+ public static extern FIBITMAP ConvertToStandardType(FIBITMAP src, bool scale_linear);
+
+ /// <summary>
+ /// Converts an image of any type to type dst_type.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="dst_type">Destination type.</param>
+ /// <param name="scale_linear">True to scale linear, else false.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ConvertToType")]
+ public static extern FIBITMAP ConvertToType(FIBITMAP src, FREE_IMAGE_TYPE dst_type, bool scale_linear);
+
+ #endregion
+
+ #region Tone mapping operators
+
+ /// <summary>
+ /// Converts a High Dynamic Range image (48-bit RGB or 96-bit RGBF) to a 24-bit RGB image, suitable for display.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tmo">The tone mapping operator to be used.</param>
+ /// <param name="first_param">Parmeter depending on the used algorithm</param>
+ /// <param name="second_param">Parmeter depending on the used algorithm</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ToneMapping")]
+ public static extern FIBITMAP ToneMapping(FIBITMAP dib, FREE_IMAGE_TMO tmo, double first_param, double second_param);
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global
+ /// operator based on logarithmic compression of luminance values, imitating the human response to light.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="gamma">A gamma correction that is applied after the tone mapping.
+ /// A value of 1 means no correction.</param>
+ /// <param name="exposure">Scale factor allowing to adjust the brightness of the output image.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoDrago03")]
+ public static extern FIBITMAP TmoDrago03(FIBITMAP src, double gamma, double exposure);
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global operator inspired
+ /// by photoreceptor physiology of the human visual system.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="intensity">Controls the overall image intensity in the range [-8, 8].</param>
+ /// <param name="contrast">Controls the overall image contrast in the range [0.3, 1.0[.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoReinhard05")]
+ public static extern FIBITMAP TmoReinhard05(FIBITMAP src, double intensity, double contrast);
+
+ /// <summary>
+ /// Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="color_saturation">Color saturation (s parameter in the paper) in [0.4..0.6]</param>
+ /// <param name="attenuation">Atenuation factor (beta parameter in the paper) in [0.8..0.9]</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_TmoFattal02")]
+ public static extern FIBITMAP TmoFattal02(FIBITMAP src, double color_saturation, double attenuation);
+
+ #endregion
+
+ #region Compression functions
+
+ /// <summary>
+ /// Compresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must be at least 0.1% larger than source_size plus 12 bytes.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the compressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibCompress")]
+ public static extern uint ZLibCompress(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Decompresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must have been saved outlide of zlib.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the uncompressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibUncompress")]
+ public static extern uint ZLibUncompress(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Compresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must be at least 0.1% larger than source_size plus 24 bytes.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the compressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibGZip")]
+ public static extern uint ZLibGZip(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Decompresses a source buffer into a target buffer, using the ZLib library.
+ /// </summary>
+ /// <param name="target">Pointer to the target buffer.</param>
+ /// <param name="target_size">Size of the target buffer.
+ /// Must have been saved outlide of zlib.</param>
+ /// <param name="source">Pointer to the source buffer.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns>The actual size of the uncompressed buffer, or 0 if an error occurred.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibGUnzip")]
+ public static extern uint ZLibGUnzip(byte[] target, uint target_size, byte[] source, uint source_size);
+
+ /// <summary>
+ /// Generates a CRC32 checksum.
+ /// </summary>
+ /// <param name="crc">The CRC32 checksum to begin with.</param>
+ /// <param name="source">Pointer to the source buffer.
+ /// If the value is 0, the function returns the required initial value for the crc.</param>
+ /// <param name="source_size">Size of the source buffer.</param>
+ /// <returns></returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ZLibCRC32")]
+ public static extern uint ZLibCRC32(uint crc, byte[] source, uint source_size);
+
+ #endregion
+
+ #region Tag creation and destruction
+
+ /// <summary>
+ /// Allocates a new <see cref="FITAG"/> object.
+ /// This object must be destroyed with a call to
+ /// <see cref="FreeImageAPI.FreeImage.DeleteTag(FITAG)"/> when no longer in use.
+ /// </summary>
+ /// <returns>The new <see cref="FITAG"/>.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CreateTag")]
+ public static extern FITAG CreateTag();
+
+ /// <summary>
+ /// Delete a previously allocated <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to destroy.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_DeleteTag")]
+ public static extern void DeleteTag(FITAG tag);
+
+ /// <summary>
+ /// Creates and returns a copy of a <see cref="FITAG"/> object.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to clone.</param>
+ /// <returns>The new <see cref="FITAG"/>.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloneTag")]
+ public static extern FITAG CloneTag(FITAG tag);
+
+ #endregion
+
+ #region Tag accessors
+
+ /// <summary>
+ /// Returns the tag field name (unique inside a metadata model).
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The field name.</returns>
+ public static unsafe string GetTagKey(FITAG tag) { return PtrToStr(GetTagKey_(tag)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetTagKey")]
+ private static unsafe extern byte* GetTagKey_(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag description.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The description or NULL if unavailable.</returns>
+ public static unsafe string GetTagDescription(FITAG tag) { return PtrToStr(GetTagDescription_(tag)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetTagDescription")]
+ private static unsafe extern byte* GetTagDescription_(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag ID.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The ID or 0 if unavailable.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagID")]
+ public static extern ushort GetTagID(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag data type.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The tag type.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagType")]
+ public static extern FREE_IMAGE_MDTYPE GetTagType(FITAG tag);
+
+ /// <summary>
+ /// Returns the number of components in the tag (in tag type units).
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The number of components.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagCount")]
+ public static extern uint GetTagCount(FITAG tag);
+
+ /// <summary>
+ /// Returns the length of the tag value in bytes.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>The length of the tag value.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagLength")]
+ public static extern uint GetTagLength(FITAG tag);
+
+ /// <summary>
+ /// Returns the tag value.
+ /// It is up to the programmer to interpret the returned pointer correctly,
+ /// according to the results of GetTagType and GetTagCount.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <returns>Pointer to the value.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetTagValue")]
+ public static extern IntPtr GetTagValue(FITAG tag);
+
+ /// <summary>
+ /// Sets the tag field name.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="key">The new name.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetTagKey")]
+ public static extern bool SetTagKey(FITAG tag, string key);
+
+ /// <summary>
+ /// Sets the tag description.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="description">The new description.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetTagDescription")]
+ public static extern bool SetTagDescription(FITAG tag, string description);
+
+ /// <summary>
+ /// Sets the tag ID.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="id">The new ID.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagID")]
+ public static extern bool SetTagID(FITAG tag, ushort id);
+
+ /// <summary>
+ /// Sets the tag data type.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="type">The new type.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagType")]
+ public static extern bool SetTagType(FITAG tag, FREE_IMAGE_MDTYPE type);
+
+ /// <summary>
+ /// Sets the number of data in the tag.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="count">New number of data.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagCount")]
+ public static extern bool SetTagCount(FITAG tag, uint count);
+
+ /// <summary>
+ /// Sets the length of the tag value in bytes.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="length">The new length.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagLength")]
+ public static extern bool SetTagLength(FITAG tag, uint length);
+
+ /// <summary>
+ /// Sets the tag value.
+ /// </summary>
+ /// <param name="tag">The tag field.</param>
+ /// <param name="value">Pointer to the new value.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetTagValue")]
+ public static extern bool SetTagValue(FITAG tag, byte[] value);
+
+ #endregion
+
+ #region Metadata iterator
+
+ /// <summary>
+ /// Provides information about the first instance of a tag that matches the metadata model.
+ /// </summary>
+ /// <param name="model">The model to match.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Unique search handle that can be used to call FindNextMetadata or FindCloseMetadata.
+ /// Null if the metadata model does not exist.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindFirstMetadata")]
+ public static extern FIMETADATA FindFirstMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, out FITAG tag);
+
+ /// <summary>
+ /// Find the next tag, if any, that matches the metadata model argument in a previous call
+ /// to FindFirstMetadata, and then alters the tag object contents accordingly.
+ /// </summary>
+ /// <param name="mdhandle">Unique search handle provided by FindFirstMetadata.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindNextMetadata")]
+ public static extern bool FindNextMetadata(FIMETADATA mdhandle, out FITAG tag);
+
+ /// <summary>
+ /// Closes the specified metadata search handle and releases associated resources.
+ /// </summary>
+ /// <param name="mdhandle">The handle to close.</param>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FindCloseMetadata")]
+ private static extern void FindCloseMetadata_(FIMETADATA mdhandle);
+
+ #endregion
+
+ #region Metadata setter and getter
+
+ /// <summary>
+ /// Retrieve a metadata attached to a dib.
+ /// </summary>
+ /// <param name="model">The metadata model to look for.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The metadata field name.</param>
+ /// <param name="tag">A FITAG structure returned by the function.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_GetMetadata")]
+ public static extern bool GetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, string key, out FITAG tag);
+
+ /// <summary>
+ /// Attach a new FreeImage tag to a dib.
+ /// </summary>
+ /// <param name="model">The metadata model used to store the tag.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The tag field name.</param>
+ /// <param name="tag">The FreeImage tag to be attached.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_SetMetadata")]
+ public static extern bool SetMetadata(FREE_IMAGE_MDMODEL model, FIBITMAP dib, string key, FITAG tag);
+
+ #endregion
+
+ #region Metadata helper functions
+
+ /// <summary>
+ /// Returns the number of tags contained in the model metadata model attached to the input dib.
+ /// </summary>
+ /// <param name="model">The metadata model.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Number of tags contained in the metadata model.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetMetadataCount")]
+ public static extern uint GetMetadataCount(FREE_IMAGE_MDMODEL model, FIBITMAP dib);
+
+ /// <summary>
+ /// Copies the metadata of FreeImage bitmap to another.
+ /// </summary>
+ /// <param name="dst">The FreeImage bitmap to copy the metadata to.</param>
+ /// <param name="src">The FreeImage bitmap to copy the metadata from.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_CloneMetadata")]
+ public static extern bool CloneMetadata(FIBITMAP dst, FIBITMAP src);
+
+ /// <summary>
+ /// Converts a FreeImage tag structure to a string that represents the interpreted tag value.
+ /// The function is not thread safe.
+ /// </summary>
+ /// <param name="model">The metadata model.</param>
+ /// <param name="tag">The interpreted tag value.</param>
+ /// <param name="Make">Reserved.</param>
+ /// <returns>The representing string.</returns>
+ public static unsafe string TagToString(FREE_IMAGE_MDMODEL model, FITAG tag, uint Make) { return PtrToStr(TagToString_(model, tag, Make)); }
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Ansi, EntryPoint = "FreeImage_TagToString")]
+ private static unsafe extern byte* TagToString_(FREE_IMAGE_MDMODEL model, FITAG tag, uint Make);
+
+ #endregion
+
+ #region Rotation and flipping
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90�.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_RotateClassic")]
+ [Obsolete("RotateClassic is deprecated (use Rotate instead).")]
+ public static extern FIBITMAP RotateClassic(FIBITMAP dib, double angle);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Rotate")]
+ internal static extern FIBITMAP Rotate(FIBITMAP dib, double angle, IntPtr backgroundColor);
+
+ /// <summary>
+ /// This function performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="x_shift">Horizontal image translation.</param>
+ /// <param name="y_shift">Vertical image translation.</param>
+ /// <param name="x_origin">Rotation center x-coordinate.</param>
+ /// <param name="y_origin">Rotation center y-coordinate.</param>
+ /// <param name="use_mask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_RotateEx")]
+ public static extern FIBITMAP RotateEx(FIBITMAP dib, double angle,
+ double x_shift, double y_shift, double x_origin, double y_origin, bool use_mask);
+
+ /// <summary>
+ /// Flip the input dib horizontally along the vertical axis.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FlipHorizontal")]
+ public static extern bool FlipHorizontal(FIBITMAP dib);
+
+ /// <summary>
+ /// Flip the input dib vertically along the horizontal axis.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FlipVertical")]
+ public static extern bool FlipVertical(FIBITMAP dib);
+
+ /// <summary>
+ /// Performs a lossless rotation or flipping on a JPEG file.
+ /// </summary>
+ /// <param name="src_file">Source file.</param>
+ /// <param name="dst_file">Destination file; can be the source file; will be overwritten.</param>
+ /// <param name="operation">The operation to apply.</param>
+ /// <param name="perfect">To avoid lossy transformation, you can set the perfect parameter to true.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_JPEGTransformU")]
+ public static extern bool JPEGTransform(string src_file, string dst_file,
+ FREE_IMAGE_JPEG_OPERATION operation, bool perfect);
+
+ #endregion
+
+ #region Upsampling / downsampling
+
+ /// <summary>
+ /// Performs resampling (or scaling, zooming) of a greyscale or RGB(A) image
+ /// to the desired destination width and height.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="dst_width">Destination width.</param>
+ /// <param name="dst_height">Destination height.</param>
+ /// <param name="filter">The filter to apply.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Rescale")]
+ public static extern FIBITMAP Rescale(FIBITMAP dib, int dst_width, int dst_height, FREE_IMAGE_FILTER filter);
+
+ /// <summary>
+ /// Creates a thumbnail from a greyscale or RGB(A) image, keeping aspect ratio.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="max_pixel_size">Thumbnail square size.</param>
+ /// <param name="convert">When true HDR images are transperantly converted to standard images.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MakeThumbnail")]
+ public static extern FIBITMAP MakeThumbnail(FIBITMAP dib, int max_pixel_size, bool convert);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_EnlargeCanvas")]
+ internal static extern FIBITMAP EnlargeCanvas(FIBITMAP dib,
+ int left, int top, int right, int bottom, IntPtr color, FREE_IMAGE_COLOR_OPTIONS options);
+
+ #endregion
+
+ #region Color manipulation
+
+ /// <summary>
+ /// Perfoms an histogram transformation on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="lookUpTable">The lookup table.
+ /// It's size is assumed to be 256 in length.</param>
+ /// <param name="channel">The color channel to be transformed.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustCurve")]
+ public static extern bool AdjustCurve(FIBITMAP dib, byte[] lookUpTable, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Performs gamma correction on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="gamma">The parameter represents the gamma value to use (gamma > 0).
+ /// A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustGamma")]
+ public static extern bool AdjustGamma(FIBITMAP dib, double gamma);
+
+ /// <summary>
+ /// Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will make the image darker and greater than 0 will make the image brighter.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustBrightness")]
+ public static extern bool AdjustBrightness(FIBITMAP dib, double percentage);
+
+ /// <summary>
+ /// Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustContrast")]
+ public static extern bool AdjustContrast(FIBITMAP dib, double percentage);
+
+ /// <summary>
+ /// Inverts each pixel data.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Invert")]
+ public static extern bool Invert(FIBITMAP dib);
+
+ /// <summary>
+ /// Computes the image histogram.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="histo">Array of integers with a size of 256.</param>
+ /// <param name="channel">Channel to compute from.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetHistogram")]
+ public static extern bool GetHistogram(FIBITMAP dib, int[] histo, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ #endregion
+
+ #region Channel processing
+
+ /// <summary>
+ /// Retrieves the red, green, blue or alpha channel of a 24- or 32-bit image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetChannel")]
+ public static extern FIBITMAP GetChannel(FIBITMAP dib, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Insert a 8-bit dib into a 24- or 32-bit image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="dib8">Handle to the bitmap to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetChannel")]
+ public static extern bool SetChannel(FIBITMAP dib, FIBITMAP dib8, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Retrieves the real part, imaginary part, magnitude or phase of a complex image.
+ /// </summary>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetComplexChannel")]
+ public static extern FIBITMAP GetComplexChannel(FIBITMAP src, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /// <summary>
+ /// Set the real or imaginary part of a complex image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="dst">Handle to a FreeImage bitmap.</param>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SetComplexChannel")]
+ public static extern bool SetComplexChannel(FIBITMAP dst, FIBITMAP src, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ #endregion
+
+ #region Copy / Paste / Composite routines
+
+ /// <summary>
+ /// Copy a sub part of the current dib image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Copy")]
+ public static extern FIBITMAP Copy(FIBITMAP dib, int left, int top, int right, int bottom);
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with the current dib image.
+ /// The bit depth of the dst bitmap must be greater than or equal to the bit depth of the src.
+ /// </summary>
+ /// <param name="dst">Handle to a FreeImage bitmap.</param>
+ /// <param name="src">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">Specifies the left position of the sub image.</param>
+ /// <param name="top">Specifies the top position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Paste")]
+ public static extern bool Paste(FIBITMAP dst, FIBITMAP src, int left, int top, int alpha);
+
+ /// <summary>
+ /// This function composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// </summary>
+ /// <param name="fg">Handle to a FreeImage bitmap.</param>
+ /// <param name="useFileBkg">When true the background of fg is used if it contains one.</param>
+ /// <param name="appBkColor">The application background is used if useFileBkg is false.</param>
+ /// <param name="bg">Image used as background when useFileBkg is false or fg has no background
+ /// and appBkColor is null.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Composite")]
+ public static extern FIBITMAP Composite(FIBITMAP fg, bool useFileBkg, ref RGBQUAD appBkColor, FIBITMAP bg);
+
+ /// <summary>
+ /// This function composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// </summary>
+ /// <param name="fg">Handle to a FreeImage bitmap.</param>
+ /// <param name="useFileBkg">When true the background of fg is used if it contains one.</param>
+ /// <param name="appBkColor">The application background is used if useFileBkg is false
+ /// and 'appBkColor' is not null.</param>
+ /// <param name="bg">Image used as background when useFileBkg is false or fg has no background
+ /// and appBkColor is null.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_Composite")]
+ public static extern FIBITMAP Composite(FIBITMAP fg, bool useFileBkg, RGBQUAD[] appBkColor, FIBITMAP bg);
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="src_file">Source filename.</param>
+ /// <param name="dst_file">Destination filename.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, CharSet = CharSet.Unicode, EntryPoint = "FreeImage_JPEGCropU")]
+ public static extern bool JPEGCrop(string src_file, string dst_file, int left, int top, int right, int bottom);
+
+ /// <summary>
+ /// Applies the alpha value of each pixel to its color components.
+ /// The aplha value stays unchanged.
+ /// Only works with 32-bits color depth.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_PreMultiplyWithAlpha")]
+ public static extern bool PreMultiplyWithAlpha(FIBITMAP dib);
+
+ #endregion
+
+ #region Miscellaneous algorithms
+
+ /// <summary>
+ /// Solves a Poisson equation, remap result pixels to [0..1] and returns the solution.
+ /// </summary>
+ /// <param name="Laplacian">Handle to a FreeImage bitmap.</param>
+ /// <param name="ncycle">Number of cycles in the multigrid algorithm (usually 2 or 3)</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_MultigridPoissonSolver")]
+ public static extern FIBITMAP MultigridPoissonSolver(FIBITMAP Laplacian, int ncycle);
+
+ #endregion
+
+ #region Colors
+
+ /// <summary>
+ /// Creates a lookup table to be used with <see cref="AdjustCurve"/> which may adjusts brightness and
+ /// contrast, correct gamma and invert the image with a single call to <see cref="AdjustCurve"/>.
+ /// </summary>
+ /// <param name="lookUpTable">Output lookup table to be used with <see cref="AdjustCurve"/>.
+ /// The size of 'lookUpTable' is assumed to be 256.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para></param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>The number of adjustments applied to the resulting lookup table
+ /// compared to a blind lookup table.</returns>
+ /// <remarks>
+ /// This function creates a lookup table to be used with <see cref="AdjustCurve"/> which may adjust
+ /// brightness and contrast, correct gamma and invert the image with a single call to
+ /// <see cref="AdjustCurve"/>. If more than one of these image display properties need to be adjusted,
+ /// using a combined lookup table should be preferred over calling each adjustment function
+ /// separately. That's particularly true for huge images or if performance is an issue. Then,
+ /// the expensive process of iterating over all pixels of an image is performed only once and
+ /// not up to four times.
+ /// <para/>
+ /// Furthermore, the lookup table created does not depend on the order, in which each single
+ /// adjustment operation is performed. Due to rounding and byte casting issues, it actually
+ /// matters in which order individual adjustment operations are performed. Both of the following
+ /// snippets most likely produce different results:
+ /// <para/>
+ /// <code>
+ /// // snippet 1: contrast, brightness
+ /// AdjustContrast(dib, 15.0);
+ /// AdjustBrightness(dib, 50.0);
+ /// </code>
+ /// <para/>
+ /// <code>
+ /// // snippet 2: brightness, contrast
+ /// AdjustBrightness(dib, 50.0);
+ /// AdjustContrast(dib, 15.0);
+ /// </code>
+ /// <para/>
+ /// Better and even faster would be snippet 3:
+ /// <para/>
+ /// <code>
+ /// // snippet 3:
+ /// byte[] lut = new byte[256];
+ /// GetAdjustColorsLookupTable(lut, 50.0, 15.0, 1.0, false);
+ /// AdjustCurve(dib, lut, FREE_IMAGE_COLOR_CHANNEL.FICC_RGB);
+ /// </code>
+ /// <para/>
+ /// This function is also used internally by <see cref="AdjustColors"/>, which does not return the
+ /// lookup table, but uses it to call <see cref="AdjustCurve"/> on the passed image.
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_GetAdjustColorsLookupTable")]
+ public static extern int GetAdjustColorsLookupTable(byte[] lookUpTable, double brightness, double contrast, double gamma, bool invert);
+
+ /// <summary>
+ /// Adjusts an image's brightness, contrast and gamma as well as it may
+ /// optionally invert the image within a single operation.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para>
+ /// This parameter must not be zero or smaller than zero.
+ /// If so, it will be ignored and no gamma correction will be performed on the image.</param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <remarks>
+ /// This function adjusts an image's brightness, contrast and gamma as well as it
+ /// may optionally invert the image within a single operation. If more than one of
+ /// these image display properties need to be adjusted, using this function should
+ /// be preferred over calling each adjustment function separately. That's particularly
+ /// true for huge images or if performance is an issue.
+ /// <para/>
+ /// This function relies on <see cref="GetAdjustColorsLookupTable"/>,
+ /// which creates a single lookup table, that combines all adjustment operations requested.
+ /// <para/>
+ /// Furthermore, the lookup table created by <see cref="GetAdjustColorsLookupTable"/> does
+ /// not depend on the order, in which each single adjustment operation is performed.
+ /// Due to rounding and byte casting issues, it actually matters in which order individual
+ /// adjustment operations are performed. Both of the following snippets most likely produce
+ /// different results:
+ /// <para/>
+ /// <code>
+ /// // snippet 1: contrast, brightness
+ /// AdjustContrast(dib, 15.0);
+ /// AdjustBrightness(dib, 50.0);
+ /// </code>
+ /// <para/>
+ /// <code>
+ /// // snippet 2: brightness, contrast
+ /// AdjustBrightness(dib, 50.0);
+ /// AdjustContrast(dib, 15.0);
+ /// </code>
+ /// <para/>
+ /// Better and even faster would be snippet 3:
+ /// <para/>
+ /// <code>
+ /// // snippet 3:
+ /// AdjustColors(dib, 50.0, 15.0, 1.0, false);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_AdjustColors")]
+ public static extern bool AdjustColors(FIBITMAP dib, double brightness, double contrast, double gamma, bool invert);
+
+ /// <summary>
+ /// Applies color mapping for one or several colors on a 1-, 4- or 8-bit
+ /// palletized or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="srccolors">Array of colors to be used as the mapping source.</param>
+ /// <param name="dstcolors">Array of colors to be used as the mapping destination.</param>
+ /// <param name="count">The number of colors to be mapped. This is the size of both
+ /// srccolors and dstcolors.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <param name="swap">If true, source and destination colors are swapped, that is,
+ /// each destination color is also mapped to the corresponding source color.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function maps up to <paramref name="count"/> colors specified in
+ /// <paramref name="srccolors"/> to these specified in <paramref name="dstcolors"/>.
+ /// Thereby, color <i>srccolors[N]</i>, if found in the image, will be replaced by color
+ /// <i>dstcolors[N]</i>. If <paramref name="swap"/> is <b>true</b>, additionally all colors
+ /// specified in <paramref name="dstcolors"/> are also mapped to these specified
+ /// in <paramref name="srccolors"/>. For high color images, the actual image data will be
+ /// modified whereas, for palletized images only the palette will be changed.
+ /// <para/>
+ /// The function returns the number of pixels changed or zero, if no pixels were changed.
+ /// <para/>
+ /// Both arrays <paramref name="srccolors"/> and <paramref name="dstcolors"/> are assumed
+ /// not to hold less than <paramref name="count"/> colors.
+ /// <para/>
+ /// For 16-bit images, all colors specified are transparently converted to their
+ /// proper 16-bit representation (either in RGB555 or RGB565 format, which is determined
+ /// by the image's red- green- and blue-mask).
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="ApplyPaletteIndexMapping"/> does,
+ /// which modifies the actual image data on palletized images.</b>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ApplyColorMapping")]
+ public static extern uint ApplyColorMapping(FIBITMAP dib, RGBQUAD[] srccolors, RGBQUAD[] dstcolors, uint count, bool ignore_alpha, bool swap);
+
+ /// <summary>
+ /// Swaps two specified colors on a 1-, 4- or 8-bit palletized
+ /// or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="color_a">One of the two colors to be swapped.</param>
+ /// <param name="color_b">The other of the two colors to be swapped.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function swaps the two specified colors <paramref name="color_a"/> and
+ /// <paramref name="color_b"/> on a palletized or high color image.
+ /// For high color images, the actual image data will be modified whereas, for palletized
+ /// images only the palette will be changed.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="SwapPaletteIndices"/> does,
+ /// which modifies the actual image data on palletized images.</b>
+ /// <para/>
+ /// This is just a thin wrapper for <see cref="ApplyColorMapping"/> and resolves to:
+ /// <para/>
+ /// <code>
+ /// return ApplyColorMapping(dib, color_a, color_b, 1, ignore_alpha, true);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SwapColors")]
+ public static extern uint SwapColors(FIBITMAP dib, ref RGBQUAD color_a, ref RGBQUAD color_b, bool ignore_alpha);
+
+ /// <summary>
+ /// Applies palette index mapping for one or several indices
+ /// on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="srcindices">Array of palette indices to be used as the mapping source.</param>
+ /// <param name="dstindices">Array of palette indices to be used as the mapping destination.</param>
+ /// <param name="count">The number of palette indices to be mapped. This is the size of both
+ /// srcindices and dstindices</param>
+ /// <param name="swap">If true, source and destination palette indices are swapped, that is,
+ /// each destination index is also mapped to the corresponding source index.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function maps up to <paramref name="count"/> palette indices specified in
+ /// <paramref name="srcindices"/> to these specified in <paramref name="dstindices"/>.
+ /// Thereby, index <i>srcindices[N]</i>, if present in the image, will be replaced by index
+ /// <i>dstindices[N]</i>. If <paramref name="swap"/> is <b>true</b>, additionally all indices
+ /// specified in <paramref name="dstindices"/> are also mapped to these specified in
+ /// <paramref name="srcindices"/>.
+ /// <para/>
+ /// The function returns the number of pixels changed or zero, if no pixels were changed.
+ /// Both arrays <paramref name="srcindices"/> and <paramref name="dstindices"/> are assumed not to
+ /// hold less than <paramref name="count"/> indices.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="ApplyColorMapping"/> does, which
+ /// modifies the actual image data on palletized images.</b>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_ApplyPaletteIndexMapping")]
+ public static extern uint ApplyPaletteIndexMapping(FIBITMAP dib, byte[] srcindices, byte[] dstindices, uint count, bool swap);
+
+ /// <summary>
+ /// Swaps two specified palette indices on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="index_a">One of the two palette indices to be swapped.</param>
+ /// <param name="index_b">The other of the two palette indices to be swapped.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <remarks>
+ /// This function swaps the two specified palette indices <i>index_a</i> and
+ /// <i>index_b</i> on a palletized image. Therefore, not the palette, but the
+ /// actual image data will be modified.
+ /// <para/>
+ /// <b>Note, that this behaviour is different from what <see cref="SwapColors"/> does on palletized images,
+ /// which only swaps the colors in the palette.</b>
+ /// <para/>
+ /// This is just a thin wrapper for <see cref="ApplyColorMapping"/> and resolves to:
+ /// <para/>
+ /// <code>
+ /// return ApplyPaletteIndexMapping(dib, index_a, index_b, 1, true);
+ /// </code>
+ /// </remarks>
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_SwapPaletteIndices")]
+ public static extern uint SwapPaletteIndices(FIBITMAP dib, ref byte index_a, ref byte index_b);
+
+ [DllImport(FreeImageLibrary, EntryPoint = "FreeImage_FillBackground")]
+ internal static extern bool FillBackground(FIBITMAP dib, IntPtr color, FREE_IMAGE_COLOR_OPTIONS options);
+
+ #endregion
+ }
+}
+
+/////////////////////////////////////////////////////
+// //
+// Wrapper functions //
+// //
+/////////////////////////////////////////////////////
+
+ #region Structs
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Wrapper for a custom handle.
+ /// </summary>
+ /// <remarks>
+ /// The <b>fi_handle</b> of FreeImage in C++ is a simple pointer, but in .NET
+ /// it's not that simple. This wrapper uses fi_handle in two different ways.
+ ///
+ /// We implement a new plugin and FreeImage gives us a handle (pointer) that
+ /// we can simply pass through to the given functions in a 'FreeImageIO'
+ /// structure.
+ /// But when we want to use LoadFromhandle or SaveToHandle we need
+ /// a fi_handle (that we receive again in our own functions).
+ /// This handle is for example a stream (see LoadFromStream / SaveToStream)
+ /// that we want to work with. To know which stream a read/write is meant for
+ /// we could use a hash value that the wrapper itself handles or we can
+ /// go the unmanaged way of using a handle.
+ /// Therefor we use a <see cref="GCHandle"/> to receive a unique pointer that we can
+ /// convert back into a .NET object.
+ /// When the <b>fi_handle</b> instance is no longer needed the instance must be disposed
+ /// by the creater manually! It is recommended to use the <c>using</c> statement to
+ /// be sure the instance is always disposed:
+ ///
+ /// <code>
+ /// using (fi_handle handle = new fi_handle(object))
+ /// {
+ /// callSomeFunctions(handle);
+ /// }
+ /// </code>
+ ///
+ /// What does that mean?
+ /// If we get a <b>fi_handle</b> from unmanaged code we get a pointer to unmanaged
+ /// memory that we do not have to care about, and just pass ist back to FreeImage.
+ /// If we have to create a handle our own we use the standard constructur
+ /// that fills the <see cref="IntPtr"/> with an pointer that represents the given object.
+ /// With calling <see cref="GetObject"/> the <see cref="IntPtr"/> is used to retrieve the original
+ /// object we passed through the constructor.
+ ///
+ /// This way we can implement a <b>fi_handle</b> that works with managed an unmanaged
+ /// code.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct fi_handle : IComparable, IComparable<fi_handle>, IEquatable<fi_handle>, IDisposable
+ {
+ /// <summary>
+ /// The handle to wrap.
+ /// </summary>
+ public IntPtr handle;
+
+ /// <summary>
+ /// Initializes a new instance wrapping a managed object.
+ /// </summary>
+ /// <param name="obj">The object to wrap.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="obj"/> is null.</exception>
+ public fi_handle(object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException("obj");
+ }
+ GCHandle gch = GCHandle.Alloc(obj, GCHandleType.Normal);
+ handle = GCHandle.ToIntPtr(gch);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="fi_handle"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="fi_handle"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="fi_handle"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="fi_handle"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(fi_handle left, fi_handle right)
+ {
+ return (left.handle == right.handle);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="fi_handle"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="fi_handle"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="fi_handle"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="fi_handle"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(fi_handle left, fi_handle right)
+ {
+ return (left.handle != right.handle);
+ }
+
+ /// <summary>
+ /// Gets whether the pointer is a null pointer.
+ /// </summary>
+ public bool IsNull
+ {
+ get
+ {
+ return (handle == IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Returns the object assigned to the handle in case this instance
+ /// was created by managed code.
+ /// </summary>
+ /// <returns><see cref="Object"/> assigned to this handle or null on failure.</returns>
+ internal object GetObject()
+ {
+ object result = null;
+ if (handle != IntPtr.Zero)
+ {
+ try
+ {
+ result = GCHandle.FromIntPtr(handle).Target;
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="fi_handle"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return handle.ToString();
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="fi_handle"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="fi_handle"/>.</returns>
+ public override int GetHashCode()
+ {
+ return handle.GetHashCode();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="fi_handle"/> structure
+ /// and is equivalent to this <see cref="fi_handle"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="fi_handle"/> structure
+ /// equivalent to this <see cref="fi_handle"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is fi_handle) && (this == ((fi_handle)obj)));
+ }
+
+ /// <summary>
+ /// Indicates whether the current object is equal to another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this object.</param>
+ /// <returns>True if the current object is equal to the other parameter; otherwise, <b>false</b>.</returns>
+ public bool Equals(fi_handle other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="fi_handle"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is fi_handle))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((fi_handle)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="fi_handle"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="fi_handle"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(fi_handle other)
+ {
+ return handle.ToInt64().CompareTo(other.handle.ToInt64());
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ public void Dispose()
+ {
+ if (this.handle != IntPtr.Zero)
+ {
+ try
+ {
+ GCHandle.FromIntPtr(handle).Free();
+ }
+ catch
+ {
+ }
+ finally
+ {
+ this.handle = IntPtr.Zero;
+ }
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI1BIT</b> structure represents a single bit.
+ /// It's value can be <i>0</i> or <i>1</i>.
+ /// </summary>
+ [DebuggerDisplay("{value}"),
+ Serializable]
+ public struct FI1BIT
+ {
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FI1BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MaxValue = 0x01;
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FI1BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MinValue = 0x00;
+
+ /// <summary>
+ /// The value of the structure.
+ /// </summary>
+ private byte value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified value.
+ /// </summary>
+ /// <param name="value">The value to initialize with.</param>
+ private FI1BIT(byte value)
+ {
+ this.value = (byte)(value & MaxValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI1BIT"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI1BIT"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI1BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator byte(FI1BIT value)
+ {
+ return value.value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FI1BIT"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI1BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI1BIT(byte value)
+ {
+ return new FI1BIT(value);
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI1BIT"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI4BIT</b> structure represents the half of a <see cref="Byte"/>.
+ /// It's valuerange is between <i>0</i> and <i>15</i>.
+ /// </summary>
+ [DebuggerDisplay("{value}"),
+ Serializable]
+ public struct FI4BIT
+ {
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FI4BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MaxValue = 0x0F;
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FI4BIT"/>. This field is constant.
+ /// </summary>
+ public const byte MinValue = 0x00;
+
+ /// <summary>
+ /// The value of the structure.
+ /// </summary>
+ private byte value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified value.
+ /// </summary>
+ /// <param name="value">The value to initialize with.</param>
+ private FI4BIT(byte value)
+ {
+ this.value = (byte)(value & MaxValue);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI4BIT"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI4BIT"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI4BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator byte(FI4BIT value)
+ {
+ return value.value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FI4BIT"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI4BIT"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI4BIT(byte value)
+ {
+ return new FI4BIT(value);
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI4BIT"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI16RGB555</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 5 bits and so, takes values in the range from 0 to 31.
+ /// </summary>
+ /// <remarks>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FI16RGB555</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FI16RGB555</b> structure and my be used in all situations which require
+ /// an <b>FI16RGB555</b> type.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FI16RGB555</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FI16RGB555 fi16rgb;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// fi16rgb = new FI16RGB555(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// fi16rgb = Color.DarkSeaGreen;
+ /// // Convert the FI16RGB555 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = fi16rgb;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = fi16rgb.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FI16RGB555 : IComparable, IComparable<FI16RGB555>, IEquatable<FI16RGB555>
+ {
+ /// <summary>
+ /// The value of the color.
+ /// </summary>
+ private ushort value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FI16RGB555(Color color)
+ {
+ value = (ushort)(
+ (((color.R * 31) / 255) << FreeImage.FI16_555_RED_SHIFT) +
+ (((color.G * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT) +
+ (((color.B * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB555"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB555"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB555"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB555"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FI16RGB555 left, FI16RGB555 right)
+ {
+ return (left.value == right.value);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB555"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB555"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB555"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB555"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FI16RGB555 left, FI16RGB555 right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI16RGB555"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI16RGB555(Color value)
+ {
+ return new FI16RGB555(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI16RGB555"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI16RGB555"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FI16RGB555 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ ((value & FreeImage.FI16_555_RED_MASK) >> FreeImage.FI16_555_RED_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_555_GREEN_MASK) >> FreeImage.FI16_555_GREEN_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_555_BLUE_MASK) >> FreeImage.FI16_555_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)(
+ (((value.R * 31) / 255) << FreeImage.FI16_555_RED_SHIFT) +
+ (((value.G * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT) +
+ (((value.B * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the red color component.
+ /// </summary>
+ public byte Red
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_RED_MASK) >> FreeImage.FI16_555_RED_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_RED_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_RED_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the green color component.
+ /// </summary>
+ public byte Green
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_GREEN_MASK) >> FreeImage.FI16_555_GREEN_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_GREEN_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_GREEN_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the blue color component.
+ /// </summary>
+ public byte Blue
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_555_BLUE_MASK) >> FreeImage.FI16_555_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_555_BLUE_MASK)) | (((value * 31) / 255) << FreeImage.FI16_555_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FI16RGB555"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FI16RGB555))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FI16RGB555)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FI16RGB555"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB555"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FI16RGB555 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FI16RGB555"/> structure
+ /// and is equivalent to this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB555"/> structure
+ /// equivalent to this <see cref="FI16RGB555"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FI16RGB555"/> structure is equivalent to this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB555"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB555"/> structure
+ /// equivalent to this <see cref="FI16RGB555"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FI16RGB555 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FI16RGB555"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FI16RGB555"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI16RGB555"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FI16RGB565</b> structure describes a color consisting of relative
+ /// intensities of red, green, blue and alpha value. Each single color
+ /// component consumes 5 bits and so, takes values in the range from 0 to 31.
+ /// </summary>
+ /// <remarks>
+ /// <para>For easy integration of the underlying structure into the .NET framework,
+ /// the <b>FI16RGB565</b> structure implements implicit conversion operators to
+ /// convert the represented color to and from the <see cref="System.Drawing.Color"/>
+ /// type. This makes the <see cref="System.Drawing.Color"/> type a real replacement
+ /// for the <b>FI16RGB565</b> structure and my be used in all situations which require
+ /// an <b>FI16RGB565</b> type.
+ /// </para>
+ /// </remarks>
+ /// <example>
+ /// The following code example demonstrates the various conversions between the
+ /// <b>FI16RGB565</b> structure and the <see cref="System.Drawing.Color"/> structure.
+ /// <code>
+ /// FI16RGB565 fi16rgb;
+ /// // Initialize the structure using a native .NET Color structure.
+ /// fi16rgb = new FI16RGB565(Color.Indigo);
+ /// // Initialize the structure using the implicit operator.
+ /// fi16rgb = Color.DarkSeaGreen;
+ /// // Convert the FI16RGB565 instance into a native .NET Color
+ /// // using its implicit operator.
+ /// Color color = fi16rgb;
+ /// // Using the structure's Color property for converting it
+ /// // into a native .NET Color.
+ /// Color another = fi16rgb.Color;
+ /// </code>
+ /// </example>
+ [Serializable, StructLayout(LayoutKind.Sequential)]
+ public struct FI16RGB565 : IComparable, IComparable<FI16RGB565>, IEquatable<FI16RGB565>
+ {
+ /// <summary>
+ /// The value of the color.
+ /// </summary>
+ private ushort value;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="System.Drawing.Color"/>.
+ /// </summary>
+ /// <param name="color"><see cref="System.Drawing.Color"/> to initialize with.</param>
+ public FI16RGB565(Color color)
+ {
+ value = (ushort)(
+ (((color.R * 31) / 255) << FreeImage.FI16_565_RED_SHIFT) +
+ (((color.G * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT) +
+ (((color.B * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB565"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB565"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB565"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB565"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FI16RGB565 left, FI16RGB565 right)
+ {
+ return (left.value == right.value);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="FI16RGB565"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="FI16RGB565"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="FI16RGB565"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="FI16RGB565"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FI16RGB565 left, FI16RGB565 right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="System.Drawing.Color"/> structure to a <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Drawing.Color"/> structure.</param>
+ /// <returns>A new instance of <see cref="FI16RGB565"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FI16RGB565(Color value)
+ {
+ return new FI16RGB565(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FI16RGB565"/> structure to a <see cref="System.Drawing.Color"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FI16RGB565"/> structure.</param>
+ /// <returns>A new instance of <see cref="System.Drawing.Color"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator Color(FI16RGB565 value)
+ {
+ return value.Color;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="System.Drawing.Color"/> of the structure.
+ /// </summary>
+ public Color Color
+ {
+ get
+ {
+ return Color.FromArgb(
+ ((value & FreeImage.FI16_565_RED_MASK) >> FreeImage.FI16_565_RED_SHIFT) * 255 / 31,
+ ((value & FreeImage.FI16_565_GREEN_MASK) >> FreeImage.FI16_565_GREEN_SHIFT) * 255 / 63,
+ ((value & FreeImage.FI16_565_BLUE_MASK) >> FreeImage.FI16_565_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)(
+ (((value.R * 31) / 255) << FreeImage.FI16_565_RED_SHIFT) +
+ (((value.G * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT) +
+ (((value.B * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the red color component.
+ /// </summary>
+ public byte Red
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_RED_MASK) >> FreeImage.FI16_565_RED_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_RED_MASK)) | (((value * 31) / 255) << FreeImage.FI16_565_RED_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the green color component.
+ /// </summary>
+ public byte Green
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_GREEN_MASK) >> FreeImage.FI16_565_GREEN_SHIFT) * 255 / 63);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_GREEN_MASK)) | (((value * 63) / 255) << FreeImage.FI16_565_GREEN_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the blue color component.
+ /// </summary>
+ public byte Blue
+ {
+ get
+ {
+ return (byte)(((value & FreeImage.FI16_565_BLUE_MASK) >> FreeImage.FI16_565_BLUE_SHIFT) * 255 / 31);
+ }
+ set
+ {
+ this.value = (ushort)((this.value & (~FreeImage.FI16_565_BLUE_MASK)) | (((value * 31) / 255) << FreeImage.FI16_565_BLUE_SHIFT));
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FI16RGB565"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FI16RGB565))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((FI16RGB565)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FI16RGB565"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB565"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FI16RGB565 other)
+ {
+ return this.Color.ToArgb().CompareTo(other.Color.ToArgb());
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FI16RGB565"/> structure
+ /// and is equivalent to this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB565"/> structure
+ /// equivalent to this <see cref="FI16RGB565"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FI16RGB565"/> structure is equivalent to this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FI16RGB565"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FI16RGB565"/> structure
+ /// equivalent to this <see cref="FI16RGB565"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FI16RGB565 other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FI16RGB565"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FI16RGB565"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FI16RGB565"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return FreeImage.ColorToString(Color);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIRational</b> structure represents a fraction via two <see cref="Int32"/>
+ /// instances which are interpreted as numerator and denominator.
+ /// </summary>
+ /// <remarks>
+ /// The structure tries to approximate the value of <see cref="FreeImageAPI.FIRational(decimal)"/>
+ /// when creating a new instance by using a better algorithm than FreeImage does.
+ /// <para/>
+ /// The structure implements the following operators:
+ /// +, -, ++, --, ==, != , >, >==, &lt;, &lt;== and ~ (which switches nominator and denomiator).
+ /// <para/>
+ /// The structure can be converted into all .NET standard types either implicit or
+ /// explicit.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
+ public struct FIRational : IConvertible, IComparable, IFormattable, IComparable<FIRational>, IEquatable<FIRational>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int numerator;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int denominator;
+
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FIRational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIRational MaxValue = new FIRational(Int32.MaxValue, 1);
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FIRational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIRational MinValue = new FIRational(Int32.MinValue, 1);
+
+ /// <summary>
+ /// Represents the smallest positive <see cref="FIRational"/> value greater than zero. This field is constant.
+ /// </summary>
+ public static readonly FIRational Epsilon = new FIRational(1, Int32.MaxValue);
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="n">The numerator.</param>
+ /// <param name="d">The denominator.</param>
+ public FIRational(int n, int d)
+ {
+ numerator = n;
+ denominator = d;
+ Normalize();
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="tag">The tag to read the data from.</param>
+ public unsafe FIRational(FITAG tag)
+ {
+ switch (FreeImage.GetTagType(tag))
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_SRATIONAL:
+ int* value = (int*)FreeImage.GetTagValue(tag);
+ numerator = (int)value[0];
+ denominator = (int)value[1];
+ Normalize();
+ return;
+ default:
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="value">The value to convert into a fraction.</param>
+ /// <exception cref="OverflowException">
+ /// <paramref name="value"/> cannot be converted into a fraction
+ /// represented by two integer values.</exception>
+ public FIRational(decimal value)
+ {
+ try
+ {
+ int sign = value < 0 ? -1 : 1;
+ value = Math.Abs(value);
+ try
+ {
+ int[] contFract = CreateContinuedFraction(value);
+ CreateFraction(contFract, out numerator, out denominator);
+ Normalize();
+ }
+ catch
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ int maxDen = (Int32.MaxValue / (int)value) - 2;
+ maxDen = maxDen < 10000 ? maxDen : 10000;
+ ApproximateFraction(value, maxDen, out numerator, out denominator);
+ Normalize();
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ throw new OverflowException("Unable to convert value into a fraction");
+ }
+ }
+ numerator *= sign;
+ Normalize();
+ }
+ catch (Exception ex)
+ {
+ throw new OverflowException("Unable to calculate fraction.", ex);
+ }
+ }
+
+ /// <summary>
+ /// The numerator of the fraction.
+ /// </summary>
+ public int Numerator
+ {
+ get { return numerator; }
+ }
+
+ /// <summary>
+ /// The denominator of the fraction.
+ /// </summary>
+ public int Denominator
+ {
+ get { return denominator; }
+ }
+
+ /// <summary>
+ /// Returns the truncated value of the fraction.
+ /// </summary>
+ /// <returns></returns>
+ public int Truncate()
+ {
+ return denominator > 0 ? (int)(numerator / denominator) : 0;
+ }
+
+ /// <summary>
+ /// Returns whether the fraction is representing an integer value.
+ /// </summary>
+ public bool IsInteger
+ {
+ get
+ {
+ return (denominator == 1 ||
+ (denominator != 0 && (numerator % denominator == 0)) ||
+ (denominator == 0 && numerator == 0));
+ }
+ }
+
+ /// <summary>
+ /// Calculated the greatest common divisor of 'a' and 'b'.
+ /// </summary>
+ private static long Gcd(long a, long b)
+ {
+ a = Math.Abs(a);
+ b = Math.Abs(b);
+ long r;
+ while (b > 0)
+ {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+ return a;
+ }
+
+ /// <summary>
+ /// Calculated the smallest common multiple of 'a' and 'b'.
+ /// </summary>
+ private static long Scm(int n, int m)
+ {
+ return Math.Abs((long)n * (long)m) / Gcd(n, m);
+ }
+
+ /// <summary>
+ /// Normalizes the fraction.
+ /// </summary>
+ private void Normalize()
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ return;
+ }
+
+ if (numerator != 1 && denominator != 1)
+ {
+ int common = (int)Gcd(numerator, denominator);
+ if (common != 1 && common != 0)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+
+ if (denominator < 0)
+ {
+ numerator *= -1;
+ denominator *= -1;
+ }
+ }
+
+ /// <summary>
+ /// Normalizes a fraction.
+ /// </summary>
+ private static void Normalize(ref long numerator, ref long denominator)
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ else if (numerator != 1 && denominator != 1)
+ {
+ long common = Gcd(numerator, denominator);
+ if (common != 1)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ if (denominator < 0)
+ {
+ numerator *= -1;
+ denominator *= -1;
+ }
+ }
+
+ /// <summary>
+ /// Returns the digits after the point.
+ /// </summary>
+ private static int GetDigits(decimal value)
+ {
+ int result = 0;
+ value -= decimal.Truncate(value);
+ while (value != 0)
+ {
+ value *= 10;
+ value -= decimal.Truncate(value);
+ result++;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a continued fraction of a decimal value.
+ /// </summary>
+ private static int[] CreateContinuedFraction(decimal value)
+ {
+ int precision = GetDigits(value);
+ decimal epsilon = 0.0000001m;
+ List<int> list = new List<int>();
+ value = Math.Abs(value);
+
+ byte b = 0;
+
+ list.Add((int)value);
+ value -= ((int)value);
+
+ while (value != 0m)
+ {
+ if (++b == byte.MaxValue || value < epsilon)
+ {
+ break;
+ }
+ value = 1m / value;
+ if (Math.Abs((Math.Round(value, precision - 1) - value)) < epsilon)
+ {
+ value = Math.Round(value, precision - 1);
+ }
+ list.Add((int)value);
+ value -= ((int)value);
+ }
+ return list.ToArray();
+ }
+
+ /// <summary>
+ /// Creates a fraction from a continued fraction.
+ /// </summary>
+ private static void CreateFraction(int[] continuedFraction, out int numerator, out int denominator)
+ {
+ numerator = 1;
+ denominator = 0;
+ int temp;
+
+ for (int i = continuedFraction.Length - 1; i > -1; i--)
+ {
+ temp = numerator;
+ numerator = continuedFraction[i] * numerator + denominator;
+ denominator = temp;
+ }
+ }
+
+ /// <summary>
+ /// Tries 'brute force' to approximate <paramref name="value"/> with a fraction.
+ /// </summary>
+ private static void ApproximateFraction(decimal value, int maxDen, out int num, out int den)
+ {
+ num = 0;
+ den = 0;
+ decimal bestDifference = 1m;
+ decimal currentDifference = -1m;
+ int digits = GetDigits(value);
+
+ if (digits <= 9)
+ {
+ int mul = 1;
+ for (int i = 1; i <= digits; i++)
+ {
+ mul *= 10;
+ }
+ if (mul <= maxDen)
+ {
+ num = (int)(value * mul);
+ den = mul;
+ return;
+ }
+ }
+
+ for (int i = 1; i <= maxDen; i++)
+ {
+ int numerator = (int)Math.Floor(value * (decimal)i + 0.5m);
+ currentDifference = Math.Abs(value - (decimal)numerator / (decimal)i);
+ if (currentDifference < bestDifference)
+ {
+ num = numerator;
+ den = i;
+ bestDifference = currentDifference;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIRational"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return ((IConvertible)this).ToDouble(null).ToString();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIRational"/> structure
+ /// and is equivalent to this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRational"/> structure
+ /// equivalent to this <see cref="FIRational"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIRational) && (this == ((FIRational)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIRational"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Operators
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator +(FIRational r1)
+ {
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator -(FIRational r1)
+ {
+ r1.numerator *= -1;
+ return r1;
+ }
+
+ /// <summary>
+ /// Returns the reciprocal value of this instance.
+ /// </summary>
+ public static FIRational operator ~(FIRational r1)
+ {
+ int temp = r1.denominator;
+ r1.denominator = r1.numerator;
+ r1.numerator = temp;
+ r1.Normalize();
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator ++(FIRational r1)
+ {
+ checked
+ {
+ r1.numerator += r1.denominator;
+ }
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator --(FIRational r1)
+ {
+ checked
+ {
+ r1.numerator -= r1.denominator;
+ }
+ return r1;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator +(FIRational r1, FIRational r2)
+ {
+ long numerator = 0;
+ long denominator = Scm(r1.denominator, r2.denominator);
+ numerator = (r1.numerator * (denominator / r1.denominator)) + (r2.numerator * (denominator / r2.denominator));
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIRational((int)numerator, (int)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator -(FIRational r1, FIRational r2)
+ {
+ return r1 + (-r2);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator *(FIRational r1, FIRational r2)
+ {
+ long numerator = r1.numerator * r2.numerator;
+ long denominator = r1.denominator * r2.denominator;
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIRational((int)numerator, (int)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator /(FIRational r1, FIRational r2)
+ {
+ int temp = r2.denominator;
+ r2.denominator = r2.numerator;
+ r2.numerator = temp;
+ return r1 * r2;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIRational operator %(FIRational r1, FIRational r2)
+ {
+ r2.Normalize();
+ if (Math.Abs(r2.numerator) < r2.denominator)
+ return new FIRational(0, 0);
+ int div = (int)(r1 / r2);
+ return r1 - (r2 * div);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator ==(FIRational r1, FIRational r2)
+ {
+ r1.Normalize();
+ r2.Normalize();
+ return (r1.numerator == r2.numerator) && (r1.denominator == r2.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator !=(FIRational r1, FIRational r2)
+ {
+ return !(r1 == r2);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) > (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) < (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >=(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) >= (r2.numerator * (denominator / r2.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <=(FIRational r1, FIRational r2)
+ {
+ long denominator = Scm(r1.denominator, r2.denominator);
+ return (r1.numerator * (denominator / r1.denominator)) <= (r2.numerator * (denominator / r2.denominator));
+ }
+
+ #endregion
+
+ #region Conversions
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Boolean"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Boolean"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator bool(FIRational value)
+ {
+ return (value.numerator != 0);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Byte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator byte(FIRational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Char"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Char"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator char(FIRational value)
+ {
+ return (char)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Decimal"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Decimal"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator decimal(FIRational value)
+ {
+ return value.denominator == 0 ? 0m : (decimal)value.numerator / (decimal)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Double"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Double"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator double(FIRational value)
+ {
+ return value.denominator == 0 ? 0d : (double)value.numerator / (double)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator short(FIRational value)
+ {
+ return (short)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator int(FIRational value)
+ {
+ return (int)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="Int64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator long(FIRational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="Single"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Single"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator float(FIRational value)
+ {
+ return value.denominator == 0 ? 0f : (float)value.numerator / (float)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to a <see cref="SByte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="SByte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator sbyte(FIRational value)
+ {
+ return (sbyte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ushort(FIRational value)
+ {
+ return (ushort)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator uint(FIRational value)
+ {
+ return (uint)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIRational"/> structure to an <see cref="UInt64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIRational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ulong(FIRational value)
+ {
+ return (ulong)(double)value;
+ }
+
+ //
+
+ /// <summary>
+ /// Converts the value of a <see cref="Boolean"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Boolean"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(bool value)
+ {
+ return new FIRational(value ? 1 : 0, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(byte value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Char"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Char"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(char value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Decimal"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Decimal"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(decimal value)
+ {
+ return new FIRational(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Double"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Double"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(double value)
+ {
+ return new FIRational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int16"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(short value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int32"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(int value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int64"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(long value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="SByte"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="SByte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(sbyte value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Single"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Single"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(float value)
+ {
+ return new FIRational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt16"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIRational(ushort value)
+ {
+ return new FIRational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(uint value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt64"/> structure to a <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIRational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIRational(ulong value)
+ {
+ return new FIRational((int)value, 1);
+ }
+
+ #endregion
+
+ #region IConvertible Member
+
+ TypeCode IConvertible.GetTypeCode()
+ {
+ return TypeCode.Double;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return (bool)this;
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return (byte)this;
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return (char)this;
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return Convert.ToDateTime(((IConvertible)this).ToDouble(provider));
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return (short)this;
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return (int)this;
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return (long)this;
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return (sbyte)this;
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ string IConvertible.ToString(IFormatProvider provider)
+ {
+ return ToString(((double)this).ToString(), provider);
+ }
+
+ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+ {
+ return Convert.ChangeType(((IConvertible)this).ToDouble(provider), conversionType, provider);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return (ushort)this;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return (uint)this;
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return (ulong)this;
+ }
+
+ #endregion
+
+ #region IComparable Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIRational"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIRational))
+ {
+ throw new ArgumentException();
+ }
+ return CompareTo((FIRational)obj);
+ }
+
+ #endregion
+
+ #region IFormattable Member
+
+ /// <summary>
+ /// Formats the value of the current instance using the specified format.
+ /// </summary>
+ /// <param name="format">The String specifying the format to use.</param>
+ /// <param name="formatProvider">The IFormatProvider to use to format the value.</param>
+ /// <returns>A String containing the value of the current instance in the specified format.</returns>
+ public string ToString(string format, IFormatProvider formatProvider)
+ {
+ if (format == null)
+ {
+ format = "";
+ }
+ return String.Format(formatProvider, format, ((IConvertible)this).ToDouble(formatProvider));
+ }
+
+ #endregion
+
+ #region IEquatable<FIRational> Member
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIRational"/> structure is equivalent to this <see cref="FIRational"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRational"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIRational"/> structure
+ /// equivalent to this <see cref="FIRational"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIRational other)
+ {
+ return (this == other);
+ }
+
+ #endregion
+
+ #region IComparable<FIRational> Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIRational"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIRational"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIRational other)
+ {
+ FIRational difference = this - other;
+ difference.Normalize();
+ if (difference.numerator > 0) return 1;
+ if (difference.numerator < 0) return -1;
+ else return 0;
+ }
+
+ #endregion
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// The <b>FIURational</b> structure represents a fraction via two <see cref="UInt32"/>
+ /// instances which are interpreted as numerator and denominator.
+ /// </summary>
+ /// <remarks>
+ /// The structure tries to approximate the value of <see cref="FreeImageAPI.FIURational(decimal)"/>
+ /// when creating a new instance by using a better algorithm than FreeImage does.
+ /// <para/>
+ /// The structure implements the following operators:
+ /// +, ++, --, ==, != , >, >==, &lt;, &lt;== and ~ (which switches nominator and denomiator).
+ /// <para/>
+ /// The structure can be converted into all .NET standard types either implicit or
+ /// explicit.
+ /// </remarks>
+ [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
+ public struct FIURational : IConvertible, IComparable, IFormattable, IComparable<FIURational>, IEquatable<FIURational>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private uint numerator;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private uint denominator;
+
+ /// <summary>
+ /// Represents the largest possible value of <see cref="FIURational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIURational MaxValue = new FIURational(UInt32.MaxValue, 1u);
+
+ /// <summary>
+ /// Represents the smallest possible value of <see cref="FIURational"/>. This field is constant.
+ /// </summary>
+ public static readonly FIURational MinValue = new FIURational(0u, 1u);
+
+ /// <summary>
+ /// Represents the smallest positive <see cref="FIURational"/> value greater than zero. This field is constant.
+ /// </summary>
+ public static readonly FIURational Epsilon = new FIURational(1u, UInt32.MaxValue);
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="n">The numerator.</param>
+ /// <param name="d">The denominator.</param>
+ public FIURational(uint n, uint d)
+ {
+ numerator = n;
+ denominator = d;
+ Normalize();
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="tag">The tag to read the data from.</param>
+ public unsafe FIURational(FITAG tag)
+ {
+ switch (FreeImage.GetTagType(tag))
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_RATIONAL:
+ uint* pvalue = (uint*)FreeImage.GetTagValue(tag);
+ numerator = pvalue[0];
+ denominator = pvalue[1];
+ Normalize();
+ return;
+ default:
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ ///Initializes a new instance based on the specified parameters.
+ /// </summary>
+ /// <param name="value">The value to convert into a fraction.</param>
+ /// <exception cref="OverflowException">
+ /// <paramref name="value"/> cannot be converted into a fraction
+ /// represented by two unsigned integer values.</exception>
+ public FIURational(decimal value)
+ {
+ try
+ {
+ if (value < 0)
+ {
+ throw new OverflowException("value");
+ }
+ try
+ {
+ int[] contFract = CreateContinuedFraction(value);
+ CreateFraction(contFract, out numerator, out denominator);
+ Normalize();
+ }
+ catch
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ int maxDen = (Int32.MaxValue / (int)value) - 2;
+ maxDen = maxDen < 10000 ? maxDen : 10000;
+ ApproximateFraction(value, maxDen, out numerator, out denominator);
+ Normalize();
+ if (Math.Abs(((decimal)numerator / (decimal)denominator) - value) > 0.0001m)
+ {
+ throw new OverflowException("Unable to convert value into a fraction");
+ }
+ }
+ Normalize();
+ }
+ catch (Exception ex)
+ {
+ throw new OverflowException("Unable to calculate fraction.", ex);
+ }
+ }
+
+ /// <summary>
+ /// The numerator of the fraction.
+ /// </summary>
+ public uint Numerator
+ {
+ get { return numerator; }
+ }
+
+ /// <summary>
+ /// The denominator of the fraction.
+ /// </summary>
+ public uint Denominator
+ {
+ get { return denominator; }
+ }
+
+ /// <summary>
+ /// Returns the truncated value of the fraction.
+ /// </summary>
+ /// <returns></returns>
+ public int Truncate()
+ {
+ return denominator > 0 ? (int)(numerator / denominator) : 0;
+ }
+
+ /// <summary>
+ /// Returns whether the fraction is representing an integer value.
+ /// </summary>
+ public bool IsInteger
+ {
+ get
+ {
+ return (denominator == 1 ||
+ (denominator != 0 && (numerator % denominator == 0)) ||
+ (denominator == 0 && numerator == 0));
+ }
+ }
+
+ /// <summary>
+ /// Calculated the greatest common divisor of 'a' and 'b'.
+ /// </summary>
+ private static ulong Gcd(ulong a, ulong b)
+ {
+ ulong r;
+ while (b > 0)
+ {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+ return a;
+ }
+
+ /// <summary>
+ /// Calculated the smallest common multiple of 'a' and 'b'.
+ /// </summary>
+ private static ulong Scm(uint n, uint m)
+ {
+ return (ulong)n * (ulong)m / Gcd(n, m);
+ }
+
+ /// <summary>
+ /// Normalizes the fraction.
+ /// </summary>
+ private void Normalize()
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ return;
+ }
+
+ if (numerator != 1 && denominator != 1)
+ {
+ uint common = (uint)Gcd(numerator, denominator);
+ if (common != 1 && common != 0)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Normalizes a fraction.
+ /// </summary>
+ private static void Normalize(ref ulong numerator, ref ulong denominator)
+ {
+ if (denominator == 0)
+ {
+ numerator = 0;
+ denominator = 1;
+ }
+ else if (numerator != 1 && denominator != 1)
+ {
+ ulong common = Gcd(numerator, denominator);
+ if (common != 1)
+ {
+ numerator /= common;
+ denominator /= common;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the digits after the point.
+ /// </summary>
+ private static int GetDigits(decimal value)
+ {
+ int result = 0;
+ value -= decimal.Truncate(value);
+ while (value != 0)
+ {
+ value *= 10;
+ value -= decimal.Truncate(value);
+ result++;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a continued fraction of a decimal value.
+ /// </summary>
+ private static int[] CreateContinuedFraction(decimal value)
+ {
+ int precision = GetDigits(value);
+ decimal epsilon = 0.0000001m;
+ List<int> list = new List<int>();
+ value = Math.Abs(value);
+
+ byte b = 0;
+
+ list.Add((int)value);
+ value -= ((int)value);
+
+ while (value != 0m)
+ {
+ if (++b == byte.MaxValue || value < epsilon)
+ {
+ break;
+ }
+ value = 1m / value;
+ if (Math.Abs((Math.Round(value, precision - 1) - value)) < epsilon)
+ {
+ value = Math.Round(value, precision - 1);
+ }
+ list.Add((int)value);
+ value -= ((int)value);
+ }
+ return list.ToArray();
+ }
+
+ /// <summary>
+ /// Creates a fraction from a continued fraction.
+ /// </summary>
+ private static void CreateFraction(int[] continuedFraction, out uint numerator, out uint denominator)
+ {
+ numerator = 1;
+ denominator = 0;
+ uint temp;
+
+ for (int i = continuedFraction.Length - 1; i > -1; i--)
+ {
+ temp = numerator;
+ numerator = (uint)(continuedFraction[i] * numerator + denominator);
+ denominator = temp;
+ }
+ }
+
+ /// <summary>
+ /// Tries 'brute force' to approximate <paramref name="value"/> with a fraction.
+ /// </summary>
+ private static void ApproximateFraction(decimal value, int maxDen, out uint num, out uint den)
+ {
+ num = 0;
+ den = 0;
+ decimal bestDifference = 1m;
+ decimal currentDifference = -1m;
+ int digits = GetDigits(value);
+
+ if (digits <= 9)
+ {
+ uint mul = 1;
+ for (int i = 1; i <= digits; i++)
+ {
+ mul *= 10;
+ }
+ if (mul <= maxDen)
+ {
+ num = (uint)(value * mul);
+ den = mul;
+ return;
+ }
+ }
+
+ for (uint u = 1; u <= maxDen; u++)
+ {
+ uint numerator = (uint)Math.Floor(value * (decimal)u + 0.5m);
+ currentDifference = Math.Abs(value - (decimal)numerator / (decimal)u);
+ if (currentDifference < bestDifference)
+ {
+ num = numerator;
+ den = u;
+ bestDifference = currentDifference;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts the numeric value of the <see cref="FIURational"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return ((IConvertible)this).ToDouble(null).ToString();
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="FIURational"/> structure
+ /// and is equivalent to this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIURational"/> structure
+ /// equivalent to this <see cref="FIURational"/> structure; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is FIURational) && (this == ((FIURational)obj)));
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FIURational"/>.</returns>
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Operators
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator +(FIURational value)
+ {
+ return value;
+ }
+
+ /// <summary>
+ /// Returns the reciprocal value of this instance.
+ /// </summary>
+ public static FIURational operator ~(FIURational value)
+ {
+ uint temp = value.denominator;
+ value.denominator = value.numerator;
+ value.numerator = temp;
+ value.Normalize();
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator ++(FIURational value)
+ {
+ checked
+ {
+ value.numerator += value.denominator;
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator --(FIURational value)
+ {
+ checked
+ {
+ value.numerator -= value.denominator;
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator +(FIURational left, FIURational right)
+ {
+ ulong numerator = 0;
+ ulong denominator = Scm(left.denominator, right.denominator);
+ numerator = (left.numerator * (denominator / left.denominator)) +
+ (right.numerator * (denominator / right.denominator));
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIURational((uint)numerator, (uint)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator -(FIURational left, FIURational right)
+ {
+ checked
+ {
+ if (left.denominator != right.denominator)
+ {
+ uint denom = left.denominator;
+ left.numerator *= right.denominator;
+ left.denominator *= right.denominator;
+ right.numerator *= denom;
+ right.denominator *= denom;
+ }
+ left.numerator -= right.numerator;
+ left.Normalize();
+ return left;
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator *(FIURational left, FIURational r2)
+ {
+ ulong numerator = left.numerator * r2.numerator;
+ ulong denominator = left.denominator * r2.denominator;
+ Normalize(ref numerator, ref denominator);
+ checked
+ {
+ return new FIURational((uint)numerator, (uint)denominator);
+ }
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator /(FIURational left, FIURational right)
+ {
+ uint temp = right.denominator;
+ right.denominator = right.numerator;
+ right.numerator = temp;
+ return left * right;
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static FIURational operator %(FIURational left, FIURational right)
+ {
+ right.Normalize();
+ if (Math.Abs(right.numerator) < right.denominator)
+ return new FIURational(0, 0);
+ int div = (int)(left / right);
+ return left - (right * div);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator ==(FIURational left, FIURational right)
+ {
+ left.Normalize();
+ right.Normalize();
+ return (left.numerator == right.numerator) && (left.denominator == right.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator !=(FIURational left, FIURational right)
+ {
+ left.Normalize();
+ right.Normalize();
+ return (left.numerator != right.numerator) || (left.denominator != right.denominator);
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) >
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) <
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator >=(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) >=
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ /// <summary>
+ /// Standard implementation of the operator.
+ /// </summary>
+ public static bool operator <=(FIURational left, FIURational right)
+ {
+ ulong denominator = Scm(left.denominator, right.denominator);
+ return (left.numerator * (denominator / left.denominator)) <=
+ (right.numerator * (denominator / right.denominator));
+ }
+
+ #endregion
+
+ #region Conversions
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Boolean"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Boolean"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator bool(FIURational value)
+ {
+ return (value.numerator != 0);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Byte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Byte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator byte(FIURational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Char"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Char"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator char(FIURational value)
+ {
+ return (char)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Decimal"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Decimal"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator decimal(FIURational value)
+ {
+ return value.denominator == 0 ? 0m : (decimal)value.numerator / (decimal)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Double"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Double"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator double(FIURational value)
+ {
+ return value.denominator == 0 ? 0d : (double)value.numerator / (double)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator short(FIURational value)
+ {
+ return (short)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator int(FIURational value)
+ {
+ return (int)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="Int64"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Int64"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator long(FIURational value)
+ {
+ return (byte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="Single"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="Single"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator float(FIURational value)
+ {
+ return value.denominator == 0 ? 0f : (float)value.numerator / (float)value.denominator;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to a <see cref="SByte"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="SByte"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator sbyte(FIURational value)
+ {
+ return (sbyte)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt16"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt16"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ushort(FIURational value)
+ {
+ return (ushort)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator uint(FIURational value)
+ {
+ return (uint)(double)value;
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="FIURational"/> structure to an <see cref="UInt32"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="FIURational"/> structure.</param>
+ /// <returns>A new instance of <see cref="UInt32"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator ulong(FIURational value)
+ {
+ return (ulong)(double)value;
+ }
+
+ //
+
+ /// <summary>
+ /// Converts the value of a <see cref="Boolean"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Boolean"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(bool value)
+ {
+ return new FIURational(value ? 1u : 0u, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Byte"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Byte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(byte value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Char"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Char"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(char value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Decimal"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Decimal"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(decimal value)
+ {
+ return new FIURational(value);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Double"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Double"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(double value)
+ {
+ return new FIURational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int16"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(short value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int32"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(int value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="Int64"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="Int64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(long value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="SByte"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="SByte"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(sbyte value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of a <see cref="Single"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">A <see cref="Single"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(float value)
+ {
+ return new FIURational((decimal)value);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt16"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt16"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FIURational(ushort value)
+ {
+ return new FIURational(value, 1);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt32"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt32"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(uint value)
+ {
+ return new FIURational(value, 1u);
+ }
+
+ /// <summary>
+ /// Converts the value of an <see cref="UInt64"/> structure to a <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="value">An <see cref="UInt64"/> structure.</param>
+ /// <returns>A new instance of <see cref="FIURational"/> initialized to <paramref name="value"/>.</returns>
+ public static explicit operator FIURational(ulong value)
+ {
+ return new FIURational((uint)value, 1u);
+ }
+
+ #endregion
+
+ #region IConvertible Member
+
+ TypeCode IConvertible.GetTypeCode()
+ {
+ return TypeCode.Double;
+ }
+
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return (bool)this;
+ }
+
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return (byte)this;
+ }
+
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return (char)this;
+ }
+
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ return Convert.ToDateTime(((IConvertible)this).ToDouble(provider));
+ }
+
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return (short)this;
+ }
+
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return (int)this;
+ }
+
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return (long)this;
+ }
+
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return (sbyte)this;
+ }
+
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return this;
+ }
+
+ string IConvertible.ToString(IFormatProvider provider)
+ {
+ return ToString(((double)this).ToString(), provider);
+ }
+
+ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+ {
+ return Convert.ChangeType(((IConvertible)this).ToDouble(provider), conversionType, provider);
+ }
+
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return (ushort)this;
+ }
+
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return (uint)this;
+ }
+
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return (ulong)this;
+ }
+
+ #endregion
+
+ #region IComparable Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="FIURational"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is FIURational))
+ {
+ throw new ArgumentException();
+ }
+ return CompareTo((FIURational)obj);
+ }
+
+ #endregion
+
+ #region IFormattable Member
+
+ /// <summary>
+ /// Formats the value of the current instance using the specified format.
+ /// </summary>
+ /// <param name="format">The String specifying the format to use.</param>
+ /// <param name="formatProvider">The IFormatProvider to use to format the value.</param>
+ /// <returns>A String containing the value of the current instance in the specified format.</returns>
+ public string ToString(string format, IFormatProvider formatProvider)
+ {
+ if (format == null)
+ {
+ format = "";
+ }
+ return String.Format(formatProvider, format, ((IConvertible)this).ToDouble(formatProvider));
+ }
+
+ #endregion
+
+ #region IEquatable<FIURational> Member
+
+ /// <summary>
+ /// Tests whether the specified <see cref="FIURational"/> structure is equivalent to this <see cref="FIURational"/> structure.
+ /// </summary>
+ /// <param name="other">A <see cref="FIURational"/> structure to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="FIURational"/> structure
+ /// equivalent to this <see cref="FIURational"/> structure; otherwise, <b>false</b>.</returns>
+ public bool Equals(FIURational other)
+ {
+ return (this == other);
+ }
+
+ #endregion
+
+ #region IComparable<FIURational> Member
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="FIURational"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="FIURational"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(FIURational other)
+ {
+ FIURational difference = this - other;
+ difference.Normalize();
+ if (difference.numerator > 0) return 1;
+ if (difference.numerator < 0) return -1;
+ else return 0;
+ }
+
+ #endregion
+ }
+}
+
+ #endregion
+
+ #region Classes
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Encapsulates a FreeImage-bitmap.
+ /// </summary>
+ [Serializable, Guid("64a4c935-b757-499c-ab8c-6110316a9e51")]
+ public class FreeImageBitmap : MarshalByRefObject, ICloneable, IDisposable, IEnumerable, ISerializable
+ {
+ #region Fields
+
+ /// <summary>
+ /// Indicates whether this instance is disposed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed;
+
+ /// <summary>
+ /// Tab object.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object tag;
+
+ /// <summary>
+ /// Object used to syncronize lock methods.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object lockObject = new object();
+
+ /// <summary>
+ /// Holds information used by SaveAdd() methods.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private SaveInformation saveInformation = new SaveInformation();
+
+ /// <summary>
+ /// The stream that this instance was loaded from or
+ /// null if it has been cloned or deserialized.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Stream stream;
+
+ /// <summary>
+ /// True if the stream must be disposed with this
+ /// instance.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposeStream;
+
+ /// <summary>
+ /// The number of frames contained by a mutlipage bitmap.
+ /// Default value is 1 and only changed if needed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int frameCount = 1;
+
+ /// <summary>
+ /// The index of the loaded frame.
+ /// Default value is 0 and only changed if needed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private int frameIndex = 0;
+
+ /// <summary>
+ /// Format of the sourceimage.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FREE_IMAGE_FORMAT originalFormat = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+
+ /// <summary>
+ /// Handle to the encapsulated FreeImage-bitmap.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FIBITMAP dib;
+
+ private const string ErrorLoadingBitmap = "Unable to load bitmap.";
+ private const string ErrorLoadingFrame = "Unable to load frame.";
+ private const string ErrorCreatingBitmap = "Unable to create bitmap.";
+ private const string ErrorUnloadBitmap = "Unable to unload bitmap.";
+
+ #endregion
+
+ #region Constructors and Destructor
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// </summary>
+ protected FreeImageBitmap()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// For internal use only.
+ /// </summary>
+ /// <exception cref="Exception">The operation failed.</exception>
+ internal protected FreeImageBitmap(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ this.dib = dib;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ public FreeImageBitmap(FreeImageBitmap original)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ original.EnsureNotDisposed();
+ dib = FreeImage.Clone(original.dib);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = original.originalFormat;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(FreeImageBitmap original, Size newSize)
+ : this(original, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(FreeImageBitmap original, int width, int height)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ original.EnsureNotDisposed();
+ dib = FreeImage.Rescale(original.dib, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = original.originalFormat;
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Image original)
+ : this(original as Bitmap)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(Image original, Size newSize)
+ : this(original as Bitmap, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(Image original, int width, int height)
+ : this(original as Bitmap, width, height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Bitmap original)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ dib = FreeImage.CreateFromBitmap(original, true);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = FreeImage.GetFormat(original.RawFormat);
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="newSize.Width"/> or <paramref name="newSize.Height"/> are less or equal zero.
+ /// </exception>
+ public FreeImageBitmap(Bitmap original, Size newSize)
+ : this(original, newSize.Width, newSize.Height)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified image with the specified size.
+ /// </summary>
+ /// <param name="original">The original to clone from.</param>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="original"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(Bitmap original, int width, int height)
+ {
+ if (original == null)
+ {
+ throw new ArgumentNullException("original");
+ }
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ FIBITMAP temp = FreeImage.CreateFromBitmap(original, true);
+ if (temp.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ dib = FreeImage.Rescale(temp, width, height, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ FreeImage.Unload(temp);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ originalFormat = FreeImage.GetFormat(original.RawFormat);
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="useIcm">Ignored.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, bool useIcm)
+ : this(stream)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream)
+ : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream in the specified format.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format)
+ : this(stream, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream with the specified loading flags.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_LOAD_FLAGS flags)
+ : this(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified stream in the specified format
+ /// with the specified loading flags.
+ /// </summary>
+ /// <param name="stream">Stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <remarks>
+ /// You must keep the stream open for the lifetime of the <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ public FreeImageBitmap(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ this.stream = stream;
+ disposeStream = false;
+ LoadFromStream(stream, format, flags);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename)
+ : this(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="useIcm">Ignored.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, bool useIcm)
+ : this(filename)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// with the specified loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags)
+ : this(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, flags)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// in the specified format.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format)
+ : this(filename, format, FREE_IMAGE_LOAD_FLAGS.DEFAULT)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified file
+ /// in the specified format with the specified loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ public FreeImageBitmap(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+
+ saveInformation.filename = filename;
+ stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);
+ disposeStream = true;
+ LoadFromStream(stream, format, flags);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class
+ /// bases on the specified size.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(int width, int height)
+ {
+ dib = FreeImage.Allocate(
+ width,
+ height,
+ 24,
+ FreeImage.FI_RGBA_RED_MASK,
+ FreeImage.FI_RGBA_GREEN_MASK,
+ FreeImage.FI_RGBA_BLUE_MASK);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified resource.
+ /// </summary>
+ /// <param name="type">The class used to extract the resource.</param>
+ /// <param name="resource">The name of the resource.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ public FreeImageBitmap(Type type, string resource)
+ : this(type.Module.Assembly.GetManifestResourceStream(type, resource))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size
+ /// and with the resolution of the specified <see cref="System.Drawing.Graphics"/> object.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="g">The Graphics object that specifies the resolution for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="g"/> is a null reference.</exception>
+ public FreeImageBitmap(int width, int height, Graphics g)
+ : this(width, height)
+ {
+ FreeImage.SetResolutionX(dib, (uint)g.DpiX);
+ FreeImage.SetResolutionX(dib, (uint)g.DpiY);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and format.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, PixelFormat format)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid");
+ }
+ dib = FreeImage.AllocateT(type, width, height, (int)bpp, redMask, greenMask, blueMask);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size and type.
+ /// Only non standard bitmaps are supported.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="type">The type of the bitmap.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="type"/> is FIT_BITMAP or FIT_UNKNOWN.</exception>
+ /// <exception cref="ArgumentException"><paramref name="type"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, FREE_IMAGE_TYPE type)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if ((type == FREE_IMAGE_TYPE.FIT_BITMAP) || (type == FREE_IMAGE_TYPE.FIT_UNKNOWN))
+ {
+ throw new ArgumentException("type is invalid.");
+ }
+ dib = FreeImage.AllocateT(type, width, height, 0, 0u, 0u, 0u);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ scan0, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="format">The PixelFormat enumeration for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="bits">Array of bytes containing the bitmap data.</param>
+ /// <remarks>
+ /// Although this constructor supports creating images in both formats
+ /// <see cref="System.Drawing.Imaging.PixelFormat.Format32bppPArgb"/>
+ /// and <see cref="System.Drawing.Imaging.PixelFormat.Format64bppPArgb"/>, bitmaps
+ /// created in these formats are treated like any normal 32-bit RGBA and 64-bit RGBA
+ /// images respectively. Currently, there is no support for automatic premultiplying images in
+ /// <see cref="FreeImageBitmap"/>.
+ /// </remarks>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
+ public FreeImageBitmap(int width, int height, int stride, PixelFormat format, byte[] bits)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if (bits == null)
+ {
+ throw new ArgumentNullException("bits");
+ }
+ uint bpp, redMask, greenMask, blueMask;
+ FREE_IMAGE_TYPE type;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetFormatParameters(format, out type, out bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("format is invalid.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ bits, type, width, height, stride, bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
+ /// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="scan0">Pointer to an array of bytes that contains the pixel data.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, IntPtr scan0)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ uint redMask, greenMask, blueMask;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("bpp and type are invalid or not supported.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ scan0, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class bases on the specified size,
+ /// pixel format and pixel data.
+ /// </summary>
+ /// <param name="width">The width, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">The height, in pixels, of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="stride">Integer that specifies the byte offset between the beginning
+ /// of one scan line and the next. This is usually (but not necessarily)
+ /// the number of bytes in the pixel format (for example, 2 for 16 bits per pixel)
+ /// multiplied by the width of the bitmap. The value passed to this parameter must
+ /// be a multiple of four..</param>
+ /// <param name="bpp">The color depth of the new <see cref="FreeImageBitmap"/></param>
+ /// <param name="type">The type for the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="bits">Array of bytes containing the bitmap data.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="ArgumentException"><paramref name="format"/> is invalid.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="width"/> or <paramref name="height"/> are less or equal zero.</exception>
+ /// <exception cref="ArgumentNullException"><paramref name="bits"/> is null</exception>
+ public FreeImageBitmap(int width, int height, int stride, int bpp, FREE_IMAGE_TYPE type, byte[] bits)
+ {
+ if (width <= 0)
+ {
+ throw new ArgumentOutOfRangeException("width");
+ }
+ if (height <= 0)
+ {
+ throw new ArgumentOutOfRangeException("height");
+ }
+ if (bits == null)
+ {
+ throw new ArgumentNullException("bits");
+ }
+ uint redMask, greenMask, blueMask;
+ bool topDown = (stride > 0);
+ stride = (stride > 0) ? stride : (stride * -1);
+
+ if (!FreeImage.GetTypeParameters(type, bpp, out redMask, out greenMask, out blueMask))
+ {
+ throw new ArgumentException("bpp and type are invalid or not supported.");
+ }
+
+ dib = FreeImage.ConvertFromRawBits(
+ bits, type, width, height, stride, (uint)bpp, redMask, greenMask, blueMask, topDown);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ AddMemoryPressure();
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FreeImageBitmap"/> class.
+ /// </summary>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="SerializationException">The operation failed.</exception>
+ public FreeImageBitmap(SerializationInfo info, StreamingContext context)
+ {
+ try
+ {
+ byte[] data = (byte[])info.GetValue("Bitmap Data", typeof(byte[]));
+ if ((data != null) && (data.Length > 0))
+ {
+ MemoryStream memory = new MemoryStream(data);
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_TIFF;
+ dib = FreeImage.LoadFromStream(memory, ref format);
+
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+
+ AddMemoryPressure();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new SerializationException("Deserialization failed.", ex);
+ }
+ }
+
+ /// <summary>
+ /// Frees all managed and unmanaged ressources.
+ /// </summary>
+ ~FreeImageBitmap()
+ {
+ Dispose(false);
+ }
+
+ #endregion
+
+ #region Operators
+
+ /// <summary>
+ /// Converts a <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
+ /// </summary>
+ /// <param name="value">A <see cref="FreeImageBitmap"/> instance.</param>
+ /// <returns>A new instance of <see cref="Bitmap"/> initialized to <paramref name="value"/>.</returns>
+ /// <remarks>
+ /// The explicit conversion from <see cref="FreeImageBitmap"/> into Bitmap
+ /// allows to create an instance on the fly and use it as if
+ /// was a Bitmap. This way it can be directly used with a
+ /// PixtureBox for example without having to call any
+ /// conversion operations.
+ /// </remarks>
+ public static explicit operator Bitmap(FreeImageBitmap value)
+ {
+ return value.ToBitmap();
+ }
+
+ /// <summary>
+ /// Converts a <see cref="Bitmap"/> instance to a <see cref="FreeImageBitmap"/> instance.
+ /// </summary>
+ /// <param name="value">A <see cref="Bitmap"/> instance.</param>
+ /// <returns>A new instance of <see cref="FreeImageBitmap"/> initialized to <paramref name="value"/>.</returns>
+ /// <remarks>
+ /// The explicit conversion from <see cref="Bitmap"/> into <see cref="FreeImageBitmap"/>
+ /// allows to create an instance on the fly to perform
+ /// image processing operations and converting it back.
+ /// </remarks>
+ public static explicit operator FreeImageBitmap(Bitmap value)
+ {
+ return new FreeImageBitmap(value);
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="FreeImageBitmap"/> objects have the same value.
+ /// </summary>
+ /// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// <b>true</b> if the value of left is the same as the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(FreeImageBitmap left, FreeImageBitmap right)
+ {
+ if (object.ReferenceEquals(left, right))
+ {
+ return true;
+ }
+ else if (object.ReferenceEquals(left, null) || object.ReferenceEquals(right, null))
+ {
+ return false;
+ }
+ else
+ {
+ left.EnsureNotDisposed();
+ right.EnsureNotDisposed();
+ return FreeImage.Compare(left.dib, right.dib, FREE_IMAGE_COMPARE_FLAGS.COMPLETE);
+ }
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="FreeImageBitmap"/> objects have different values.
+ /// </summary>
+ /// <param name="left">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="FreeImageBitmap"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// true if the value of left is different from the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(FreeImageBitmap left, FreeImageBitmap right)
+ {
+ return (!(left == right));
+ }
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Type of the bitmap.
+ /// </summary>
+ public FREE_IMAGE_TYPE ImageType
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetImageType(dib);
+ }
+ }
+
+ /// <summary>
+ /// Number of palette entries.
+ /// </summary>
+ public int ColorsUsed
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetColorsUsed(dib);
+ }
+ }
+
+ /// <summary>
+ /// The number of unique colors actually used by the bitmap. This might be different from
+ /// what ColorsUsed returns, which actually returns the palette size for palletised images.
+ /// Works for FIT_BITMAP type bitmaps only.
+ /// </summary>
+ public int UniqueColors
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetUniqueColors(dib);
+ }
+ }
+
+ /// <summary>
+ /// The size of one pixel in the bitmap in bits.
+ /// </summary>
+ public int ColorDepth
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetBPP(dib);
+ }
+ }
+
+ /// <summary>
+ /// Width of the bitmap in pixel units.
+ /// </summary>
+ public int Width
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetWidth(dib);
+ }
+ }
+
+ /// <summary>
+ /// Height of the bitmap in pixel units.
+ /// </summary>
+ public int Height
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetHeight(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns the width of the bitmap in bytes, rounded to the next 32-bit boundary.
+ /// </summary>
+ public int Pitch
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetPitch(dib);
+ }
+ }
+
+ /// <summary>
+ /// Size of the bitmap in memory.
+ /// </summary>
+ public int DataSize
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetDIBSize(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns a structure that represents the palette of a FreeImage bitmap.
+ /// </summary>
+ /// <exception cref="InvalidOperationException"><see cref="HasPalette"/> is false.</exception>
+ public Palette Palette
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (HasPalette)
+ {
+ return new Palette(dib);
+ }
+ throw new InvalidOperationException("This bitmap does not have a palette.");
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the bitmap is RGB 555.
+ /// </summary>
+ public bool IsRGB555
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsRGB555(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the bitmap is RGB 565.
+ /// </summary>
+ public bool IsRGB565
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsRGB565(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets the horizontal resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public float HorizontalResolution
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (float)FreeImage.GetResolutionX(dib);
+ }
+ private set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionX(dib, (uint)value);
+ }
+ }
+
+ /// <summary>
+ /// Gets the vertical resolution, in pixels per inch, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public float VerticalResolution
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (float)FreeImage.GetResolutionY(dib);
+ }
+ private set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionY(dib, (uint)value);
+ }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFOHEADER"/> structure of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public BITMAPINFOHEADER InfoHeader
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetInfoHeaderEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFO"/> structure of a this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public BITMAPINFO Info
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetInfoEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Investigates the color type of this <see cref="FreeImageBitmap"/>
+ /// by reading the bitmaps pixel bits and analysing them.
+ /// </summary>
+ public FREE_IMAGE_COLOR_TYPE ColorType
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetColorType(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the red color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint RedMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetRedMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the green color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint GreenMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetGreenMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Bit pattern describing the blue color component of a pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public uint BlueMask
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBlueMask(dib);
+ }
+ }
+
+ /// <summary>
+ /// Number of transparent colors in a palletised <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int TransparencyCount
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetTransparencyCount(dib);
+ }
+ }
+
+ /// <summary>
+ /// Get or sets transparency table of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public byte[] TransparencyTable
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetTransparencyTableEx(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparencyTable(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether this <see cref="FreeImageBitmap"/> is transparent.
+ /// </summary>
+ public bool IsTransparent
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.IsTransparent(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparent(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="FreeImageBitmap"/> has a file background color.
+ /// </summary>
+ public bool HasBackgroundColor
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.HasBackgroundColor(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the background color of this <see cref="FreeImageBitmap"/>.
+ /// In case the value is null, the background color is removed.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">Get: There is no background color available.</exception>
+ /// <exception cref="Exception">Set: Setting background color failed.</exception>
+ public Color? BackgroundColor
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (!FreeImage.HasBackgroundColor(dib))
+ {
+ throw new InvalidOperationException("No background color available.");
+ }
+ RGBQUAD rgbq;
+ FreeImage.GetBackgroundColor(dib, out rgbq);
+ return rgbq.Color;
+ }
+ set
+ {
+ EnsureNotDisposed();
+ if (!FreeImage.SetBackgroundColor(dib, (value.HasValue ? new RGBQUAD[] { value.Value } : null)))
+ {
+ throw new Exception("Setting background color failed.");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Pointer to the data-bits of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public IntPtr Bits
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBits(dib);
+ }
+ }
+
+ /// <summary>
+ /// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int Line
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (int)FreeImage.GetLine(dib);
+ }
+ }
+
+ /// <summary>
+ /// Pointer to the scanline of the top most pixel row of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public IntPtr Scan0
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetScanLine(dib, (int)(FreeImage.GetHeight(dib) - 1));
+ }
+ }
+
+ /// <summary>
+ /// Width, in bytes, of this <see cref="FreeImageBitmap"/>.
+ /// In case this <see cref="FreeImageBitmap"/> is top down <b>Stride</b> will be positive, else negative.
+ /// </summary>
+ public int Stride
+ {
+ get
+ {
+ return -Line;
+ }
+ }
+
+ /// <summary>
+ /// Gets attribute flags for the pixel data of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public unsafe int Flags
+ {
+ get
+ {
+ EnsureNotDisposed();
+ int result = 0;
+ byte alpha;
+ int cd = ColorDepth;
+
+ if ((cd == 32) || (FreeImage.GetTransparencyCount(dib) != 0))
+ {
+ result += (int)ImageFlags.HasAlpha;
+ }
+
+ if (cd == 32)
+ {
+ uint width = FreeImage.GetWidth(dib);
+ uint height = FreeImage.GetHeight(dib);
+ for (int y = 0; y < height; y++)
+ {
+ RGBQUAD* scanline = (RGBQUAD*)FreeImage.GetScanLine(dib, y);
+ for (int x = 0; x < width; x++)
+ {
+ alpha = scanline[x].Color.A;
+ if (alpha != byte.MinValue && alpha != byte.MaxValue)
+ {
+ result += (int)ImageFlags.HasTranslucent;
+ y = (int)height;
+ break;
+ }
+ }
+ }
+ }
+ else if (FreeImage.GetTransparencyCount(dib) != 0)
+ {
+ byte[] transTable = FreeImage.GetTransparencyTableEx(dib);
+ for (int i = 0; i < transTable.Length; i++)
+ {
+ if (transTable[i] != byte.MinValue && transTable[i] != byte.MaxValue)
+ {
+ result += (int)ImageFlags.HasTranslucent;
+ break;
+ }
+ }
+ }
+
+ if (FreeImage.GetICCProfileEx(dib).IsCMYK)
+ {
+ result += (int)ImageFlags.ColorSpaceCmyk;
+ }
+ else
+ {
+ result += (int)ImageFlags.ColorSpaceRgb;
+ }
+
+ if (FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK ||
+ FreeImage.GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_MINISWHITE)
+ {
+ result += (int)ImageFlags.ColorSpaceGray;
+ }
+
+ if (originalFormat == FREE_IMAGE_FORMAT.FIF_BMP ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_FAXG3 ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_ICO ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_JPEG ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PCX ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PNG ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_PSD ||
+ originalFormat == FREE_IMAGE_FORMAT.FIF_TIFF)
+ {
+ result += (int)ImageFlags.HasRealDpi;
+ }
+
+ return result;
+ }
+ }
+
+ /// <summary>
+ /// Gets the width and height of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public SizeF PhysicalDimension
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new SizeF((float)FreeImage.GetWidth(dib), (float)FreeImage.GetHeight(dib));
+ }
+ }
+
+ /// <summary>
+ /// Gets the pixel format for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public PixelFormat PixelFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetPixelFormat(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets IDs of the property items stored in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int[] PropertyIdList
+ {
+ get
+ {
+ EnsureNotDisposed();
+ List<int> list = new List<int>();
+ ImageMetadata metaData = new ImageMetadata(dib, true);
+
+ foreach (MetadataModel metadataModel in metaData)
+ {
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ list.Add(metadataTag.ID);
+ }
+ }
+
+ return list.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Gets all the property items (pieces of metadata) stored in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public PropertyItem[] PropertyItems
+ {
+ get
+ {
+ EnsureNotDisposed();
+ List<PropertyItem> list = new List<PropertyItem>();
+ ImageMetadata metaData = new ImageMetadata(dib, true);
+
+ foreach (MetadataModel metadataModel in metaData)
+ {
+ foreach (MetadataTag metadataTag in metadataModel)
+ {
+ list.Add(metadataTag.GetPropertyItem());
+ }
+ }
+
+ return list.ToArray();
+ }
+ }
+
+ /// <summary>
+ /// Gets the format of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public ImageFormat RawFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ Attribute guidAttribute =
+ Attribute.GetCustomAttribute(
+ typeof(FreeImageBitmap), typeof(System.Runtime.InteropServices.GuidAttribute)
+ );
+ return (guidAttribute == null) ?
+ null :
+ new ImageFormat(new Guid(((GuidAttribute)guidAttribute).Value));
+ }
+ }
+
+ /// <summary>
+ /// Gets the width and height, in pixels, of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public Size Size
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new Size(Width, Height);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets an object that provides additional data about the <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public Object Tag
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return tag;
+ }
+ set
+ {
+ EnsureNotDisposed();
+ tag = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="FreeImageBitmap"/> has been disposed.
+ /// </summary>
+ public bool IsDisposed
+ {
+ get
+ {
+ return disposed;
+ }
+ }
+
+ /// <summary>
+ /// Gets a new instance of a metadata representing class.
+ /// </summary>
+ public ImageMetadata Metadata
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new ImageMetadata(dib, true);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the comment of this <see cref="FreeImageBitmap"/>.
+ /// Supported formats are JPEG, PNG and GIF.
+ /// </summary>
+ public string Comment
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetImageComment(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetImageComment(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Returns whether this <see cref="FreeImageBitmap"/> has a palette.
+ /// </summary>
+ public bool HasPalette
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return (FreeImage.GetPalette(dib) != IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the entry used as transparent color in this <see cref="FreeImageBitmap"/>.
+ /// Only works for 1-, 4- and 8-bpp.
+ /// </summary>
+ public int TransparentIndex
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetTransparentIndex(dib);
+ }
+ set
+ {
+ EnsureNotDisposed();
+ FreeImage.SetTransparentIndex(dib, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of frames in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public int FrameCount
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return frameCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets the ICCProfile structure of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public FIICCPROFILE ICCProfile
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetICCProfileEx(dib);
+ }
+ }
+
+ /// <summary>
+ /// Gets the format of the original image in case
+ /// this <see cref="FreeImageBitmap"/> was loaded from a file or stream.
+ /// </summary>
+ public FREE_IMAGE_FORMAT ImageFormat
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return originalFormat;
+ }
+ }
+
+ /// <summary>
+ /// Gets the encapsulated FIBITMAP.
+ /// </summary>
+ internal FIBITMAP Dib
+ {
+ get { EnsureNotDisposed(); return dib; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Gets the bounds of this <see cref="FreeImageBitmap"/> in the specified unit.
+ /// </summary>
+ /// <param name="pageUnit">One of the <see cref="System.Drawing.GraphicsUnit"/> values indicating
+ /// the unit of measure for the bounding rectangle.</param>
+ /// <returns>The <see cref="System.Drawing.RectangleF"/> that represents the bounds of this
+ /// <see cref="FreeImageBitmap"/>, in the specified unit.</returns>
+ public RectangleF GetBounds(ref GraphicsUnit pageUnit)
+ {
+ EnsureNotDisposed();
+ pageUnit = GraphicsUnit.Pixel;
+ return new RectangleF(
+ 0f,
+ 0f,
+ (float)FreeImage.GetWidth(dib),
+ (float)FreeImage.GetHeight(dib));
+ }
+
+ /// <summary>
+ /// Gets the specified property item from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="propid">The ID of the property item to get.</param>
+ /// <returns>The <see cref="PropertyItem"/> this method gets.</returns>
+ public PropertyItem GetPropertyItem(int propid)
+ {
+ EnsureNotDisposed();
+ ImageMetadata metadata = new ImageMetadata(dib, true);
+ foreach (MetadataModel metadataModel in metadata)
+ {
+ foreach (MetadataTag tag in metadataModel)
+ {
+ if (tag.ID == propid)
+ {
+ return tag.GetPropertyItem();
+ }
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns a thumbnail for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="thumbWidth">The width, in pixels, of the requested thumbnail image.</param>
+ /// <param name="thumbHeight">The height, in pixels, of the requested thumbnail image.</param>
+ /// <param name="callback">Ignored.</param>
+ /// <param name="callBackData">Ignored.</param>
+ /// <returns>A <see cref="FreeImageBitmap"/> that represents the thumbnail.</returns>
+ public FreeImageBitmap GetThumbnailImage(int thumbWidth, int thumbHeight,
+ Image.GetThumbnailImageAbort callback, IntPtr callBackData)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Rescale(
+ dib, thumbWidth, thumbHeight, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a thumbnail for this <see cref="FreeImageBitmap"/>, keeping aspect ratio.
+ /// <paramref name="maxPixelSize"/> defines the maximum width or height
+ /// of the thumbnail.
+ /// </summary>
+ /// <param name="maxPixelSize">Thumbnail square size.</param>
+ /// <param name="convert">When true HDR images are transperantly
+ /// converted to standard images.</param>
+ /// <returns>The thumbnail in a new instance.</returns>
+ public FreeImageBitmap GetThumbnailImage(int maxPixelSize, bool convert)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.MakeThumbnail(dib, maxPixelSize, convert);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> instance to a <see cref="Bitmap"/> instance.
+ /// </summary>
+ /// <returns>A new instance of <see cref="Bitmap"/> initialized this instance.</returns>
+ public Bitmap ToBitmap()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBitmap(dib, true);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
+ /// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
+ /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
+ /// bottom-most line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline to retrieve.</param>
+ /// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
+ /// <paramref name="scanline"/>th scanline.</returns>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ /// <example>
+ /// <code>
+ /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
+ /// if (bitmap.ColorDepth == 32)
+ /// {
+ /// Scanline&lt;RGBQUAD&gt; scanline = bitmap.GetScanline&lt;RGBQUAD&gt;(0);
+ /// foreach (RGBQUAD pixel in scanline)
+ /// {
+ /// Console.WriteLine(pixel);
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ /// <exception cref="ArgumentException">
+ /// The bitmap's type or color depth are not supported.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="scanline"/> is no valid value.
+ /// </exception>
+ public Scanline<T> GetScanline<T>(int scanline) where T : struct
+ {
+ EnsureNotDisposed();
+ return new Scanline<T>(dib, scanline);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="Scanline&lt;T&gt;"/>, representing the scanline
+ /// specified by <paramref name="scanline"/> of this <see cref="FreeImageBitmap"/>.
+ /// Since FreeImage bitmaps are always bottum up aligned, keep in mind that scanline 0 is the
+ /// bottom-most line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline to retrieve.</param>
+ /// <returns>An instance of <see cref="Scanline&lt;T&gt;"/> representing the
+ /// <paramref name="scanline"/>th scanline.</returns>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ /// <example>
+ /// <code>
+ /// FreeImageBitmap bitmap = new FreeImageBitmap(@"C:\Pictures\picture.bmp");
+ /// if (bitmap.ColorDepth == 32)
+ /// {
+ /// Scanline&lt;RGBQUAD&gt; scanline = (Scanline&lt;RGBQUAD&gt;)bitmap.GetScanline(0);
+ /// foreach (RGBQUAD pixel in scanline)
+ /// {
+ /// Console.WriteLine(pixel);
+ /// }
+ /// }
+ /// </code>
+ /// </example>
+ /// <exception cref="ArgumentException">
+ /// The type of the bitmap or color depth are not supported.
+ /// </exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="scanline"/> is no valid value.
+ /// </exception>
+ public object GetScanline(int scanline)
+ {
+ EnsureNotDisposed();
+ object result = null;
+ int width = (int)FreeImage.GetWidth(dib);
+
+ switch (FreeImage.GetImageType(dib))
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+
+ switch (FreeImage.GetBPP(dib))
+ {
+ case 1u: result = new Scanline<FI1BIT>(dib, scanline, width); break;
+ case 4u: result = new Scanline<FI4BIT>(dib, scanline, width); break;
+ case 8u: result = new Scanline<Byte>(dib, scanline, width); break;
+ case 16u:
+ if ((RedMask == FreeImage.FI16_555_RED_MASK) &&
+ (GreenMask == FreeImage.FI16_555_GREEN_MASK) &&
+ (BlueMask == FreeImage.FI16_555_BLUE_MASK))
+ {
+ result = new Scanline<FI16RGB555>(dib, scanline, width);
+ }
+ else if ((RedMask == FreeImage.FI16_565_RED_MASK) &&
+ (GreenMask == FreeImage.FI16_565_GREEN_MASK) &&
+ (BlueMask == FreeImage.FI16_565_BLUE_MASK))
+ {
+ result = new Scanline<FI16RGB565>(dib, scanline, width);
+ }
+ else
+ {
+ result = new Scanline<UInt16>(dib, scanline, width);
+ }
+ break;
+ case 24u: result = new Scanline<RGBTRIPLE>(dib, scanline, width); break;
+ case 32u: result = new Scanline<RGBQUAD>(dib, scanline, width); break;
+ default: throw new ArgumentException("Color depth is not supported.");
+ }
+ break;
+
+ case FREE_IMAGE_TYPE.FIT_COMPLEX: result = new Scanline<FICOMPLEX>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE: result = new Scanline<Double>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT: result = new Scanline<Single>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_INT16: result = new Scanline<Int16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_INT32: result = new Scanline<Int32>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16: result = new Scanline<FIRGB16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16: result = new Scanline<FIRGBA16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF: result = new Scanline<FIRGBAF>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF: result = new Scanline<FIRGBF>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16: result = new Scanline<UInt16>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32: result = new Scanline<UInt32>(dib, scanline, width); break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ default: throw new ArgumentException("Type is not supported.");
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a pointer to the specified scanline.
+ /// Due to FreeImage bitmaps are bottum up,
+ /// scanline 0 is the most bottom line of the image.
+ /// </summary>
+ /// <param name="scanline">Number of the scanline.</param>
+ /// <returns>Pointer to the scanline.</returns>
+ public IntPtr GetScanlinePointer(int scanline)
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetScanLine(dib, scanline);
+ }
+
+ /// <summary>
+ /// Returns a list of structures, representing the scanlines of this <see cref="FreeImageBitmap"/>.
+ /// Due to FreeImage bitmaps are bottum up, scanline 0 is the
+ /// bottom-most line of the image.
+ /// Each color depth has a different representing structure due to different memory layouts.
+ /// </summary>
+ /// <remarks>
+ /// List of return-types of <b>T</b>:<para/>
+ /// <list type="table">
+ /// <listheader><term>Color Depth / Type</term><description><see cref="Type">Result Type of IEnmuerable&lt;Scanline&lt;T&gt;&gt;</see></description></listheader>
+ /// <item><term>1 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI1BIT"/></description></item>
+ /// <item><term>4 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI4BIT"/></description></item>
+ /// <item><term>8 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="Byte"/></description></item>
+ /// <item><term>16 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="UInt16"/></description></item>
+ /// <item><term>16 - 555 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB555"/></description></item>
+ /// <item><term>16 - 565 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="FI16RGB565"/></description></item>
+ /// <item><term>24 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBTRIPLE"/></description></item>
+ /// <item><term>32 (<see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>)</term><description><see cref="RGBQUAD"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_COMPLEX"/></term><description><see cref="FICOMPLEX"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/></term><description><see cref="Double"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_FLOAT"/></term><description><see cref="Single"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT16"/></term><description><see cref="Int16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_INT32"/></term><description><see cref="Int32"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGB16"/></term><description><see cref="FIRGB16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBA16"/></term><description><see cref="FIRGBA16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBAF"/></term><description><see cref="FIRGBAF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_RGBF"/></term><description><see cref="FIRGBF"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT16"/></term><description><see cref="UInt16"/></description></item>
+ /// <item><term><see cref="FREE_IMAGE_TYPE.FIT_UINT32"/></term><description><see cref="UInt32"/></description></item>
+ /// </list>
+ /// </remarks>
+ public IList GetScanlines()
+ {
+ EnsureNotDisposed();
+
+ int height = (int)FreeImage.GetHeight(dib);
+ IList list;
+
+ switch (FreeImage.GetImageType(dib))
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+
+ switch (FreeImage.GetBPP(dib))
+ {
+ case 1u: list = new List<Scanline<FI1BIT>>(height); break;
+ case 4u: list = new List<Scanline<FI4BIT>>(height); break;
+ case 8u: list = new List<Scanline<Byte>>(height); break;
+ case 16u:
+ if (FreeImage.IsRGB555(dib))
+ {
+ list = new List<Scanline<FI16RGB555>>(height);
+ }
+ else if (FreeImage.IsRGB565(dib))
+ {
+ list = new List<Scanline<FI16RGB565>>(height);
+ }
+ else
+ {
+ list = new List<Scanline<UInt16>>(height);
+ }
+ break;
+ case 24u: list = new List<Scanline<RGBTRIPLE>>(height); break;
+ case 32u: list = new List<Scanline<RGBQUAD>>(height); break;
+ default: throw new ArgumentException("Color depth is not supported.");
+ }
+ break;
+
+ case FREE_IMAGE_TYPE.FIT_COMPLEX: list = new List<Scanline<FICOMPLEX>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE: list = new List<Scanline<Double>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT: list = new List<Scanline<Single>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_INT16: list = new List<Scanline<Int16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_INT32: list = new List<Scanline<Int32>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16: list = new List<Scanline<FIRGB16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16: list = new List<Scanline<FIRGBA16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF: list = new List<Scanline<FIRGBAF>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF: list = new List<Scanline<FIRGBF>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16: list = new List<Scanline<UInt16>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32: list = new List<Scanline<UInt32>>(height); break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ default: throw new ArgumentException("Type is not supported.");
+ }
+
+ for (int i = 0; i < height; i++)
+ {
+ list.Add(GetScanline(i));
+ }
+
+ return list;
+ }
+
+ /// <summary>
+ /// Removes the specified property item from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="propid">The ID of the property item to remove.</param>
+ public void RemovePropertyItem(int propid)
+ {
+ EnsureNotDisposed();
+ ImageMetadata mdata = new ImageMetadata(dib, true);
+ foreach (MetadataModel model in mdata)
+ {
+ foreach (MetadataTag tag in model)
+ {
+ if (tag.ID == propid)
+ {
+ model.RemoveTag(tag.Key);
+ return;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// This method rotates, flips, or rotates and flips this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="rotateFlipType">A RotateFlipType member
+ /// that specifies the type of rotation and flip to apply to this <see cref="FreeImageBitmap"/>.</param>
+ public void RotateFlip(RotateFlipType rotateFlipType)
+ {
+ EnsureNotDisposed();
+
+ FIBITMAP newDib = new FIBITMAP();
+ uint bpp = FreeImage.GetBPP(dib);
+
+ switch (rotateFlipType)
+ {
+ case RotateFlipType.RotateNoneFlipX:
+
+ FreeImage.FlipHorizontal(dib);
+ break;
+
+ case RotateFlipType.RotateNoneFlipY:
+
+ FreeImage.FlipVertical(dib);
+ break;
+
+ case RotateFlipType.RotateNoneFlipXY:
+
+ FreeImage.FlipHorizontal(dib);
+ FreeImage.FlipVertical(dib);
+ break;
+
+ case RotateFlipType.Rotate90FlipNone:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ break;
+
+ case RotateFlipType.Rotate90FlipX:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipHorizontal(newDib);
+ break;
+
+ case RotateFlipType.Rotate90FlipY:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipVertical(newDib);
+ break;
+
+ case RotateFlipType.Rotate90FlipXY:
+
+ newDib = (bpp == 4u) ? FreeImage.Rotate4bit(dib, 90d) : FreeImage.Rotate(dib, 90d);
+ FreeImage.FlipHorizontal(newDib);
+ FreeImage.FlipVertical(newDib);
+ break;
+
+ case RotateFlipType.Rotate180FlipXY:
+ newDib = FreeImage.Clone(dib);
+ break;
+ }
+ ReplaceDib(newDib);
+ }
+
+ /// <summary>
+ /// Copies the metadata from another <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="bitmap">The bitmap to read the metadata from.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is a null reference.
+ /// </exception>
+ public void CloneMetadataFrom(FreeImageBitmap bitmap)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ FreeImage.CloneMetadata(dib, bitmap.dib);
+ }
+
+ /// <summary>
+ /// Copies the metadata from another <see cref="FreeImageBitmap"/> using
+ /// the provided options.
+ /// </summary>
+ /// <param name="bitmap">The bitmap to read the metadata from.</param>
+ /// <param name="flags">Specifies the way the metadata is copied.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is a null reference.
+ /// </exception>
+ public void CloneMetadataFrom(FreeImageBitmap bitmap, FREE_IMAGE_METADATA_COPY flags)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ FreeImage.CloneMetadataEx(bitmap.dib, dib, flags);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename)
+ {
+ Save(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file in the specified format.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename, FREE_IMAGE_FORMAT format)
+ {
+ Save(filename, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified file in the specified format
+ /// using the specified saving flags.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file to which
+ /// to save this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentException"><paramref name="filename"/> is null or empty.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(string filename, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ EnsureNotDisposed();
+ if (string.IsNullOrEmpty(filename))
+ {
+ throw new ArgumentException("filename");
+ }
+ if (!FreeImage.SaveEx(dib, filename, format, flags))
+ {
+ throw new Exception("Unable to save bitmap");
+ }
+
+ saveInformation.filename = filename;
+ saveInformation.format = format;
+ saveInformation.saveFlags = flags;
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified stream in the specified format.
+ /// </summary>
+ /// <param name="stream">The stream where this <see cref="FreeImageBitmap"/> will be saved.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(Stream stream, FREE_IMAGE_FORMAT format)
+ {
+ Save(stream, format, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves this <see cref="FreeImageBitmap"/> to the specified stream in the specified format
+ /// using the specified saving flags.
+ /// </summary>
+ /// <param name="stream">The stream where this <see cref="FreeImageBitmap"/> will be saved.</param>
+ /// <param name="format">An <see cref="FREE_IMAGE_FORMAT"/> that specifies the format of the saved image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="stream"/> is a null reference.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public void Save(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ EnsureNotDisposed();
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!FreeImage.SaveToStream(dib, stream, format, flags))
+ {
+ throw new Exception("Unable to save bitmap");
+ }
+
+ saveInformation.filename = null;
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/>
+ /// method.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not been saved to a file using Save(...) before.</exception>
+ public void SaveAdd()
+ {
+ SaveAdd(this);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(int insertPosition)
+ {
+ SaveAdd(this, insertPosition);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ public void SaveAdd(FreeImageBitmap bitmap)
+ {
+ if (saveInformation.filename == null)
+ {
+ throw new InvalidOperationException("This operation requires a previous call of Save().");
+ }
+
+ SaveAdd(
+ saveInformation.filename,
+ bitmap,
+ saveInformation.format,
+ saveInformation.loadFlags,
+ saveInformation.saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified in a previous call to the <see cref="Save(String)"/> method.
+ /// </summary>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="InvalidOperationException">
+ /// This instance has not yet been saved to a file using the Save(...) method.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(FreeImageBitmap bitmap, int insertPosition)
+ {
+ if (saveInformation.filename == null)
+ {
+ throw new InvalidOperationException("This operation requires a previous call of Save().");
+ }
+
+ SaveAdd(
+ saveInformation.filename,
+ bitmap,
+ insertPosition,
+ saveInformation.format,
+ saveInformation.loadFlags,
+ saveInformation.saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ public void SaveAdd(string filename)
+ {
+ SaveAdd(
+ filename,
+ this,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(string filename, int insertPosition)
+ {
+ SaveAdd(
+ filename,
+ this,
+ insertPosition,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified using the specified parameters.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ public void SaveAdd(
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ SaveAdd(
+ filename,
+ this,
+ format,
+ loadFlags,
+ saveFlags);
+ }
+
+ /// <summary>
+ /// Adds a frame to the file specified using the specified parameters.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="insertPosition">The position at which the frame should be inserted.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="filename"/> is a null reference.</exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image has failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public void SaveAdd(
+ string filename,
+ int insertPosition,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ SaveAdd(
+ filename,
+ this,
+ insertPosition,
+ format,
+ loadFlags,
+ saveFlags);
+ }
+
+ /// <summary>
+ /// Selects the frame specified by the index.
+ /// </summary>
+ /// <param name="frameIndex">The index of the active frame.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="frameIndex"/> is out of range.</exception>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="InvalidOperationException">The source of the bitmap is not available.
+ /// </exception>
+ public void SelectActiveFrame(int frameIndex)
+ {
+ EnsureNotDisposed();
+ if ((frameIndex < 0) || (frameIndex >= frameCount))
+ {
+ throw new ArgumentOutOfRangeException("frameIndex");
+ }
+
+ if (frameIndex != this.frameIndex)
+ {
+ if (stream == null)
+ {
+ throw new InvalidOperationException("No source available.");
+ }
+
+ FREE_IMAGE_FORMAT format = originalFormat;
+ FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, saveInformation.loadFlags);
+ if (mdib.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ try
+ {
+ if (frameIndex >= FreeImage.GetPageCount(mdib))
+ {
+ throw new ArgumentOutOfRangeException("frameIndex");
+ }
+
+ FIBITMAP newDib = FreeImage.LockPage(mdib, frameIndex);
+ if (newDib.IsNull)
+ {
+ throw new Exception(ErrorLoadingFrame);
+ }
+
+ try
+ {
+ FIBITMAP clone = FreeImage.Clone(newDib);
+ if (clone.IsNull)
+ {
+ throw new Exception(ErrorCreatingBitmap);
+ }
+ ReplaceDib(clone);
+ }
+ finally
+ {
+ if (!newDib.IsNull)
+ {
+ FreeImage.UnlockPage(mdib, newDib, false);
+ }
+ }
+ }
+ finally
+ {
+ if (!FreeImage.CloseMultiBitmapEx(ref mdib))
+ {
+ throw new Exception(ErrorUnloadBitmap);
+ }
+ }
+
+ this.frameIndex = frameIndex;
+ }
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmap()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetHbitmap(dib, IntPtr.Zero, false);
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="background">A <see cref="System.Drawing.Color"/> structure that specifies the background color.
+ /// This parameter is ignored if the bitmap is totally opaque.</param>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmap(Color background)
+ {
+ EnsureNotDisposed();
+ using (FreeImageBitmap temp = new FreeImageBitmap(this))
+ {
+ temp.BackgroundColor = background;
+ return temp.GetHbitmap();
+ }
+ }
+
+ /// <summary>
+ /// Returns the handle to an icon.
+ /// </summary>
+ /// <returns>A Windows handle to an icon with the same image as this <see cref="FreeImageBitmap"/>.</returns>
+ public IntPtr GetHicon()
+ {
+ EnsureNotDisposed();
+ using (Bitmap bitmap = FreeImage.GetBitmap(dib, true))
+ {
+ return bitmap.GetHicon();
+ }
+ }
+
+ /// <summary>
+ /// Creates a GDI bitmap object from this <see cref="FreeImageBitmap"/> with the same
+ /// color depth as the primary device.
+ /// </summary>
+ /// <returns>A handle to the GDI bitmap object that this method creates.</returns>
+ public IntPtr GetHbitmapForDevice()
+ {
+ EnsureNotDisposed();
+ return FreeImage.GetBitmapForDevice(dib, IntPtr.Zero, false);
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Color"/> of the specified pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="x">The x-coordinate of the pixel to retrieve.</param>
+ /// <param name="y">The y-coordinate of the pixel to retrieve.</param>
+ /// <returns>A <see cref="System.Drawing.Color"/> structure that represents the color of the specified pixel.</returns>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="NotSupportedException">The type of this bitmap is not supported.</exception>
+ public unsafe Color GetPixel(int x, int y)
+ {
+ EnsureNotDisposed();
+ if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32)
+ {
+ RGBQUAD rgbq;
+ if (!FreeImage.GetPixelColor(dib, (uint)x, (uint)y, out rgbq))
+ {
+ throw new Exception("FreeImage.GetPixelColor() failed");
+ }
+ return rgbq.Color;
+ }
+ else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8)
+ {
+ byte index;
+ if (!FreeImage.GetPixelIndex(dib, (uint)x, (uint)y, out index))
+ {
+ throw new Exception("FreeImage.GetPixelIndex() failed");
+ }
+ RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib);
+ return palette[index].Color;
+ }
+ }
+ throw new NotSupportedException("The type of the image is not supported");
+ }
+
+ /// <summary>
+ /// Makes the default transparent color transparent for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ public void MakeTransparent()
+ {
+ EnsureNotDisposed();
+ MakeTransparent(Color.Transparent);
+ }
+
+ /// <summary>
+ /// Makes the specified color transparent for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="transparentColor">The <see cref="System.Drawing.Color"/> structure that represents
+ /// the color to make transparent.</param>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public void MakeTransparent(Color transparentColor)
+ {
+ EnsureNotDisposed();
+ throw new System.NotImplementedException();
+ }
+
+ /// <summary>
+ /// Sets the <see cref="System.Drawing.Color"/> of the specified pixel in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="x">The x-coordinate of the pixel to set.</param>
+ /// <param name="y">The y-coordinate of the pixel to set.</param>
+ /// <param name="color">A <see cref="System.Drawing.Color"/> structure that represents the color
+ /// to assign to the specified pixel.</param>
+ /// <exception cref="Exception">The operation failed.</exception>
+ /// <exception cref="NotSupportedException">The type of this bitmap is not supported.</exception>
+ public unsafe void SetPixel(int x, int y, Color color)
+ {
+ EnsureNotDisposed();
+ if (FreeImage.GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ if (ColorDepth == 16 || ColorDepth == 24 || ColorDepth == 32)
+ {
+ RGBQUAD rgbq = color;
+ if (!FreeImage.SetPixelColor(dib, (uint)x, (uint)y, ref rgbq))
+ {
+ throw new Exception("FreeImage.SetPixelColor() failed");
+ }
+ return;
+ }
+ else if (ColorDepth == 1 || ColorDepth == 4 || ColorDepth == 8)
+ {
+ uint colorsUsed = FreeImage.GetColorsUsed(dib);
+ RGBQUAD* palette = (RGBQUAD*)FreeImage.GetPalette(dib);
+ for (int i = 0; i < colorsUsed; i++)
+ {
+ if (palette[i].Color == color)
+ {
+ byte index = (byte)i;
+ if (!FreeImage.SetPixelIndex(dib, (uint)x, (uint)y, ref index))
+ {
+ throw new Exception("FreeImage.SetPixelIndex() failed");
+ }
+ return;
+ }
+ }
+ throw new ArgumentOutOfRangeException("color");
+ }
+ }
+ throw new NotSupportedException("The type of the image is not supported");
+ }
+
+ /// <summary>
+ /// Sets the resolution for this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="xDpi">The horizontal resolution, in dots per inch, of this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="yDpi">The vertical resolution, in dots per inch, of this <see cref="FreeImageBitmap"/>.</param>
+ public void SetResolution(float xDpi, float yDpi)
+ {
+ EnsureNotDisposed();
+ FreeImage.SetResolutionX(dib, (uint)xDpi);
+ FreeImage.SetResolutionY(dib, (uint)yDpi);
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// This function is not yet implemented.
+ /// </summary>
+ /// <exception cref="NotImplementedException">
+ /// This method is not implemented.</exception>
+ public void UnlockBits(BitmapData bitmapdata)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> into a different color depth.
+ /// The parameter <paramref name="bpp"/> specifies color depth, greyscale conversion
+ /// and palette reorder.
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE"/> flag
+ /// will first perform a convesion to greyscale. This can be done with any target
+ /// color depth.</para>
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE"/> flag
+ /// will allow the algorithm to reorder the palette. This operation will not be performed to
+ /// non-greyscale images to prevent data loss by mistake.</para>
+ /// </summary>
+ /// <param name="bpp">A bitfield containing information about the conversion
+ /// to perform.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool ConvertColorDepth(FREE_IMAGE_COLOR_DEPTH bpp)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.ConvertColorDepth(dib, bpp, false));
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> <see cref="FREE_IMAGE_TYPE"/> to
+ /// <paramref name="type"/> initializing a new instance.
+ /// In case source and destination type are the same, the operation fails.
+ /// An error message can be catched using the 'Message' event.
+ /// </summary>
+ /// <param name="type">Destination type.</param>
+ /// <param name="scaleLinear">True to scale linear, else false.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool ConvertType(FREE_IMAGE_TYPE type, bool scaleLinear)
+ {
+ EnsureNotDisposed();
+ return (ImageType == type) ? false : ReplaceDib(FreeImage.ConvertToType(dib, type, scaleLinear));
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> <see cref="FreeImageBitmap"/> to <paramref name="type"/>.
+ /// In case source and destination type are the same, the operation fails.
+ /// An error message can be catched using the 'Message' event.
+ /// </summary>
+ /// <param name="type">Destination type.</param>
+ /// <param name="scaleLinear">True to scale linear, else false.</param>
+ /// <returns>The converted instance.</returns>
+ public FreeImageBitmap GetTypeConvertedInstance(FREE_IMAGE_TYPE type, bool scaleLinear)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ if (ImageType != type)
+ {
+ FIBITMAP newDib = FreeImage.ConvertToType(dib, type, scaleLinear);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts this <see cref="FreeImageBitmap"/> into a different color depth initializing
+ /// a new instance.
+ /// The parameter <paramref name="bpp"/> specifies color depth, greyscale conversion
+ /// and palette reorder.
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE"/> flag will
+ /// first perform a convesion to greyscale. This can be done with any target color depth.</para>
+ /// <para>Adding the <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE"/> flag will
+ /// allow the algorithm to reorder the palette. This operation will not be performed to
+ /// non-greyscale images to prevent data loss by mistake.</para>
+ /// </summary>
+ /// <param name="bpp">A bitfield containing information about the conversion
+ /// to perform.</param>
+ /// <returns>The converted instance.</returns>
+ public FreeImageBitmap GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH bpp)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.ConvertColorDepth(dib, bpp, false);
+ if (newDib == dib)
+ {
+ newDib = FreeImage.Clone(dib);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter.
+ /// </summary>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rescale(Size newSize, FREE_IMAGE_FILTER filter)
+ {
+ return Rescale(newSize.Width, newSize.Height, filter);
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter.
+ /// </summary>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rescale(int width, int height, FREE_IMAGE_FILTER filter)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.Rescale(dib, width, height, filter));
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter initializing a new instance.
+ /// </summary>
+ /// <param name="newSize">The Size structure that represent the
+ /// size of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>The rescaled instance.</returns>
+ public FreeImageBitmap GetScaledInstance(Size newSize, FREE_IMAGE_FILTER filter)
+ {
+ return GetScaledInstance(newSize.Width, newSize.Height, filter);
+ }
+
+ /// <summary>
+ /// Rescales this <see cref="FreeImageBitmap"/> to the specified size using the
+ /// specified filter initializing a new instance.
+ /// </summary>
+ /// <param name="width">Width of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="height">Height of the new <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="filter">Filter to use for resizing.</param>
+ /// <returns>The rescaled instance.</returns>
+ public FreeImageBitmap GetScaledInstance(int width, int height, FREE_IMAGE_FILTER filter)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Rescale(dib, width, height, filter);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool EnlargeCanvas<T>(int left, int top, int right, int bottom, T? color) where T : struct
+ {
+ return EnlargeCanvas(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool EnlargeCanvas<T>(int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options));
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color returning a new instance.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <returns>The enlarged instance.</returns>
+ public FreeImageBitmap GetEnlargedInstance<T>(int left, int top, int right, int bottom,
+ T? color) where T : struct
+ {
+ return GetEnlargedInstance(left, top, right, bottom, color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Enlarges or shrinks this <see cref="FreeImageBitmap"/> selectively per side and fills
+ /// newly added areas with the specified background color returning a new instance.
+ /// See <see cref="FreeImage.EnlargeCanvas&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns>The enlarged instance.</returns>
+ public FreeImageBitmap GetEnlargedInstance<T>(int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.EnlargeCanvas(dib, left, top, right, bottom, color, options);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize)
+ {
+ return Quantize(algorithm, paletteSize, 0, (RGBQUAD[])null);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette)
+ {
+ return Quantize(algorithm, paletteSize, reservePalette.Length, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette)
+ {
+ return Quantize(algorithm, paletteSize, reserveSize, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit to 8bit creating a new
+ /// palette with the specified <paramref name="paletteSize"/> using the specified
+ /// <paramref name="algorithm"/> and the specified
+ /// <paramref name="reservePalette">palette</paramref> up to the
+ /// specified <paramref name="paletteSize">length</paramref>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette of ReservePalette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Quantize(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette));
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> initializing a new 8 bit instance with the
+ /// specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, 0, (RGBQUAD[])null);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and <paramref name="reservePalette">palette</paramref>
+ /// initializing a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, Palette reservePalette)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, reservePalette.Length, reservePalette);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and up to <paramref name="reserveSize"/>
+ /// entries from <paramref name="reservePalette">palette</paramref> initializing
+ /// a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, Palette reservePalette)
+ {
+ return GetQuantizedInstance(algorithm, paletteSize, reserveSize, reservePalette.Data);
+ }
+
+ /// <summary>
+ /// Quantizes this <see cref="FreeImageBitmap"/> from 24 bit, using the specified
+ /// <paramref name="algorithm"/> and up to <paramref name="reserveSize"/>
+ /// entries from <paramref name="reservePalette">palette</paramref> initializing
+ /// a new 8 bit instance with the specified <paramref name="paletteSize"/>.
+ /// </summary>
+ /// <param name="algorithm">The color reduction algorithm to be used.</param>
+ /// <param name="paletteSize">Size of the desired output palette.</param>
+ /// <param name="reserveSize">Size of the provided palette.</param>
+ /// <param name="reservePalette">The provided palette.</param>
+ /// <returns>The quantized instance.</returns>
+ public FreeImageBitmap GetQuantizedInstance(FREE_IMAGE_QUANTIZE algorithm, int paletteSize, int reserveSize, RGBQUAD[] reservePalette)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.ColorQuantizeEx(dib, algorithm, paletteSize, reserveSize, reservePalette);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global
+ /// operator based on logarithmic compression of luminance values, imitating
+ /// the human response to light.
+ /// </summary>
+ /// <param name="gamma">A gamma correction that is applied after the tone mapping.
+ /// A value of 1 means no correction.</param>
+ /// <param name="exposure">Scale factor allowing to adjust the brightness of the output image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoDrago03(double gamma, double exposure)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoDrago03(dib, gamma, exposure));
+ }
+
+ /// <summary>
+ /// Converts a High Dynamic Range image to a 24-bit RGB image using a global operator inspired
+ /// by photoreceptor physiology of the human visual system.
+ /// </summary>
+ /// <param name="intensity">Controls the overall image intensity in the range [-8, 8].</param>
+ /// <param name="contrast">Controls the overall image contrast in the range [0.3, 1.0[.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoReinhard05(double intensity, double contrast)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoReinhard05(dib, intensity, contrast));
+ }
+
+ /// <summary>
+ /// Apply the Gradient Domain High Dynamic Range Compression to a RGBF image and convert to 24-bit RGB.
+ /// </summary>
+ /// <param name="color_saturation">Color saturation (s parameter in the paper) in [0.4..0.6]</param>
+ /// <param name="attenuation">Atenuation factor (beta parameter in the paper) in [0.8..0.9]</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool TmoFattal02(double color_saturation, double attenuation)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.TmoFattal02(dib, color_saturation, attenuation));
+ }
+
+ /// <summary>
+ /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate(double angle)
+ {
+ EnsureNotDisposed();
+ bool result = false;
+ if (ColorDepth == 4)
+ {
+ result = ReplaceDib(FreeImage.Rotate4bit(dib, angle));
+ }
+ else
+ {
+ result = ReplaceDib(FreeImage.Rotate(dib, angle));
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This method rotates a 1-, 4-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate<T>(double angle, T? backgroundColor) where T : struct
+ {
+ EnsureNotDisposed();
+ bool result = false;
+ if (ColorDepth == 4)
+ {
+ result = ReplaceDib(FreeImage.Rotate4bit(dib, angle));
+ }
+ else
+ {
+ result = ReplaceDib(FreeImage.Rotate(dib, angle, backgroundColor));
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rotates this <see cref="FreeImageBitmap"/> by the specified angle initializing a new instance.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance<T>(double angle, T? backgroundColor) where T : struct
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib;
+ if (ColorDepth == 4)
+ {
+ newDib = FreeImage.Rotate4bit(dib, angle);
+ }
+ else
+ {
+ newDib = FreeImage.Rotate(dib, angle, backgroundColor);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Rotates this <see cref="FreeImageBitmap"/> by the specified angle initializing a new instance.
+ /// For 1- and 4-bit images, rotation is limited to angles whose value is an integer
+ /// multiple of 90.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance(double angle)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib;
+ if (ColorDepth == 4)
+ {
+ newDib = FreeImage.Rotate4bit(dib, angle);
+ }
+ else
+ {
+ newDib = FreeImage.Rotate(dib, angle);
+ }
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This method performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="xShift">Horizontal image translation.</param>
+ /// <param name="yShift">Vertical image translation.</param>
+ /// <param name="xOrigin">Rotation center x-coordinate.</param>
+ /// <param name="yOrigin">Rotation center y-coordinate.</param>
+ /// <param name="useMask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Rotate(double angle, double xShift, double yShift,
+ double xOrigin, double yOrigin, bool useMask)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.RotateEx(dib, angle, xShift, yShift, xOrigin, yOrigin, useMask));
+ }
+
+ /// <summary>
+ /// This method performs a rotation and / or translation of an 8-bit greyscale,
+ /// 24- or 32-bit image, using a 3rd order (cubic) B-Spline initializing a new instance.
+ /// </summary>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="xShift">Horizontal image translation.</param>
+ /// <param name="yShift">Vertical image translation.</param>
+ /// <param name="xOrigin">Rotation center x-coordinate.</param>
+ /// <param name="yOrigin">Rotation center y-coordinate.</param>
+ /// <param name="useMask">When true the irrelevant part of the image is set to a black color,
+ /// otherwise, a mirroring technique is used to fill irrelevant pixels.</param>
+ /// <returns>The rotated instance.</returns>
+ public FreeImageBitmap GetRotatedInstance(double angle, double xShift, double yShift,
+ double xOrigin, double yOrigin, bool useMask)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.RotateEx(
+ dib, angle, xShift, yShift, xOrigin, yOrigin, useMask);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Perfoms an histogram transformation on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="lookUpTable">The lookup table (LUT).
+ /// It's size is assumed to be 256 in length.</param>
+ /// <param name="channel">The color channel to be transformed.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustCurve(byte[] lookUpTable, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustCurve(dib, lookUpTable, channel);
+ }
+
+ /// <summary>
+ /// Performs gamma correction on a 8-, 24- or 32-bit image.
+ /// </summary>
+ /// <param name="gamma">The parameter represents the gamma value to use (gamma > 0).
+ /// A value of 1.0 leaves the image alone, less than one darkens it, and greater than one lightens it.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustGamma(double gamma)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustGamma(dib, gamma);
+ }
+
+ /// <summary>
+ /// Adjusts the brightness of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will make the image darker and greater than 0 will make the image brighter.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustBrightness(double percentage)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustBrightness(dib, percentage);
+ }
+
+ /// <summary>
+ /// Adjusts the contrast of a 8-, 24- or 32-bit image by a certain amount.
+ /// </summary>
+ /// <param name="percentage">A value 0 means no change,
+ /// less than 0 will decrease the contrast and greater than 0 will increase the contrast of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustContrast(double percentage)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustContrast(dib, percentage);
+ }
+
+ /// <summary>
+ /// Inverts each pixel data.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Invert()
+ {
+ EnsureNotDisposed();
+ return FreeImage.Invert(dib);
+ }
+
+ /// <summary>
+ /// Computes the image histogram.
+ /// </summary>
+ /// <param name="channel">Channel to compute from.</param>
+ /// <param name="histogram">Array of integers containing the histogram.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool GetHistogram(FREE_IMAGE_COLOR_CHANNEL channel, out int[] histogram)
+ {
+ EnsureNotDisposed();
+ histogram = new int[256];
+ return FreeImage.GetHistogram(dib, histogram, channel);
+ }
+
+ /// <summary>
+ /// Retrieves the red, green, blue or alpha channel of a 24- or 32-bit image.
+ /// </summary>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>The color channel in a new instance.</returns>
+ public FreeImageBitmap GetChannel(FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.GetChannel(dib, channel);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Insert a 8-bit dib into a 24- or 32-bit image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool SetChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.SetChannel(dib, bitmap.dib, channel);
+ }
+
+ /// <summary>
+ /// Retrieves the real part, imaginary part, magnitude or phase of a complex image.
+ /// </summary>
+ /// <param name="channel">The color channel to extract.</param>
+ /// <returns>The color channel in a new instance.</returns>
+ public FreeImageBitmap GetComplexChannel(FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.GetComplexChannel(dib, channel);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Set the real or imaginary part of a complex image.
+ /// Both images must have to same width and height.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to insert.</param>
+ /// <param name="channel">The color channel to replace.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool SetComplexChannel(FreeImageBitmap bitmap, FREE_IMAGE_COLOR_CHANNEL channel)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.SetComplexChannel(dib, bitmap.dib, channel);
+ }
+
+ /// <summary>
+ /// Copy a sub part of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="rect">The subpart to copy.</param>
+ /// <returns>The sub part in a new instance.</returns>
+ public FreeImageBitmap Copy(Rectangle rect)
+ {
+ EnsureNotDisposed();
+ return Copy(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ /// <summary>
+ /// Copy a sub part of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>The sub part in a new instance.</returns>
+ public FreeImageBitmap Copy(int left, int top, int right, int bottom)
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Copy(dib, left, top, right, bottom);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with this <see cref="FreeImageBitmap"/>.
+ /// The bit depth of <paramref name="bitmap"/> must be greater than or equal to the bit depth this instance.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to paste into this instance.</param>
+ /// <param name="left">Specifies the left position of the sub image.</param>
+ /// <param name="top">Specifies the top position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Paste(FreeImageBitmap bitmap, int left, int top, int alpha)
+ {
+ EnsureNotDisposed();
+ bitmap.EnsureNotDisposed();
+ return FreeImage.Paste(dib, bitmap.dib, left, top, alpha);
+ }
+
+ /// <summary>
+ /// Alpha blend or combine a sub part image with tthis <see cref="FreeImageBitmap"/>.
+ /// The bit depth of <paramref name="bitmap"/> must be greater than or equal to the bit depth this instance.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="FreeImageBitmap"/> to paste into this instance.</param>
+ /// <param name="point">Specifies the position of the sub image.</param>
+ /// <param name="alpha">alpha blend factor.
+ /// The source and destination images are alpha blended if alpha=0..255.
+ /// If alpha > 255, then the source image is combined to the destination image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Paste(FreeImageBitmap bitmap, Point point, int alpha)
+ {
+ EnsureNotDisposed();
+ return Paste(bitmap, point.X, point.Y, alpha);
+ }
+
+ /// <summary>
+ /// This method composite a transparent foreground image against a single background color or
+ /// against a background image.
+ /// In case <paramref name="useBitmapBackground"/> is false and <paramref name="applicationBackground"/>
+ /// and <paramref name="bitmapBackGround"/>
+ /// are null, a checkerboard will be used as background.
+ /// </summary>
+ /// <param name="useBitmapBackground">When true the background of this instance is used
+ /// if it contains one.</param>
+ /// <param name="applicationBackground">Backgroundcolor used in case <paramref name="useBitmapBackground"/> is false
+ /// and <paramref name="applicationBackground"/> is not null.</param>
+ /// <param name="bitmapBackGround">Background used in case <paramref name="useBitmapBackground"/>
+ /// is false and <paramref name="applicationBackground"/> is a null reference.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool Composite(bool useBitmapBackground, Color? applicationBackground, FreeImageBitmap bitmapBackGround)
+ {
+ EnsureNotDisposed();
+ bitmapBackGround.EnsureNotDisposed();
+ RGBQUAD? rgb = applicationBackground;
+ return ReplaceDib(
+ FreeImage.Composite(
+ dib,
+ useBitmapBackground,
+ rgb.HasValue ? new RGBQUAD[] { rgb.Value } : null,
+ bitmapBackGround.dib));
+ }
+
+ /// <summary>
+ /// Applies the alpha value of each pixel to its color components.
+ /// The aplha value stays unchanged.
+ /// Only works with 32-bits color depth.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool PreMultiplyWithAlpha()
+ {
+ EnsureNotDisposed();
+ return FreeImage.PreMultiplyWithAlpha(dib);
+ }
+
+ /// <summary>
+ /// Solves a Poisson equation, remap result pixels to [0..1] and returns the solution.
+ /// </summary>
+ /// <param name="ncycle">Number of cycles in the multigrid algorithm (usually 2 or 3)</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool MultigridPoissonSolver(int ncycle)
+ {
+ EnsureNotDisposed();
+ return ReplaceDib(FreeImage.MultigridPoissonSolver(dib, ncycle));
+ }
+
+ /// <summary>
+ /// Adjusts an image's brightness, contrast and gamma as well as it may
+ /// optionally invert the image within a single operation.
+ /// </summary>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para>
+ /// This parameter must not be zero or smaller than zero.
+ /// If so, it will be ignored and no gamma correction will be performed on the image.</param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool AdjustColors(double brightness, double contrast, double gamma, bool invert)
+ {
+ EnsureNotDisposed();
+ return FreeImage.AdjustColors(dib, brightness, contrast, gamma, invert);
+ }
+
+ /// <summary>
+ /// Applies color mapping for one or several colors on a 1-, 4- or 8-bit
+ /// palletized or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="srccolors">Array of colors to be used as the mapping source.</param>
+ /// <param name="dstcolors">Array of colors to be used as the mapping destination.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <param name="swap">If true, source and destination colors are swapped, that is,
+ /// each destination color is also mapped to the corresponding source color.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="srccolors"/> or <paramref name="dstcolors"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="srccolors"/> has a different length than <paramref name="dstcolors"/>.
+ /// </exception>
+ public uint ApplyColorMapping(RGBQUAD[] srccolors, RGBQUAD[] dstcolors, bool ignore_alpha, bool swap)
+ {
+ EnsureNotDisposed();
+ if (srccolors == null)
+ {
+ throw new ArgumentNullException("srccolors");
+ }
+ if (dstcolors == null)
+ {
+ throw new ArgumentNullException("dstcolors");
+ }
+ if (srccolors.Length != dstcolors.Length)
+ {
+ throw new ArgumentException("srccolors and dstcolors must have the same length.");
+ }
+ return FreeImage.ApplyColorMapping(dib, srccolors, dstcolors, (uint)srccolors.Length, ignore_alpha, swap);
+ }
+
+ /// <summary>
+ /// Swaps two specified colors on a 1-, 4- or 8-bit palletized
+ /// or a 16-, 24- or 32-bit high color image.
+ /// </summary>
+ /// <param name="color_a">One of the two colors to be swapped.</param>
+ /// <param name="color_b">The other of the two colors to be swapped.</param>
+ /// <param name="ignore_alpha">If true, 32-bit images and colors are treated as 24-bit.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ public uint SwapColors(RGBQUAD color_a, RGBQUAD color_b, bool ignore_alpha)
+ {
+ EnsureNotDisposed();
+ return FreeImage.SwapColors(dib, ref color_a, ref color_b, ignore_alpha);
+ }
+
+ /// <summary>
+ /// Applies palette index mapping for one or several indices
+ /// on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="srcindices">Array of palette indices to be used as the mapping source.</param>
+ /// <param name="dstindices">Array of palette indices to be used as the mapping destination.</param>
+ /// <param name="count">The number of palette indices to be mapped. This is the size of both
+ /// srcindices and dstindices</param>
+ /// <param name="swap">If true, source and destination palette indices are swapped, that is,
+ /// each destination index is also mapped to the corresponding source index.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="srccolors"/> or <paramref name="dstcolors"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="srccolors"/> has a different length than <paramref name="dstcolors"/>.
+ /// </exception>
+ public uint ApplyPaletteIndexMapping(byte[] srcindices, byte[] dstindices, uint count, bool swap)
+ {
+ EnsureNotDisposed();
+ if (srcindices == null)
+ {
+ throw new ArgumentNullException("srcindices");
+ }
+ if (dstindices == null)
+ {
+ throw new ArgumentNullException("dstindices");
+ }
+ if (srcindices.Length != dstindices.Length)
+ {
+ throw new ArgumentException("srcindices and dstindices must have the same length.");
+ }
+ return FreeImage.ApplyPaletteIndexMapping(dib, srcindices, dstindices, (uint)srcindices.Length, swap);
+ }
+
+ /// <summary>
+ /// Swaps two specified palette indices on a 1-, 4- or 8-bit palletized image.
+ /// </summary>
+ /// <param name="index_a">One of the two palette indices to be swapped.</param>
+ /// <param name="index_b">The other of the two palette indices to be swapped.</param>
+ /// <returns>The total number of pixels changed.</returns>
+ public uint SwapPaletteIndices(byte index_a, byte index_b)
+ {
+ EnsureNotDisposed();
+ return FreeImage.SwapPaletteIndices(dib, ref index_a, ref index_b);
+ }
+
+ /// <summary>
+ /// Sets all pixels of this <see cref="FreeImageBitmap"/> to the specified color.
+ /// See <see cref="FreeImage.FillBackground&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="color">The color to fill this <see cref="FreeImageBitmap"/> with.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool FillBackground<T>(T color) where T : struct
+ {
+ return FillBackground(color, FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT);
+ }
+
+ /// <summary>
+ /// Sets all pixels of this <see cref="FreeImageBitmap"/> to the specified color.
+ /// See <see cref="FreeImage.FillBackground&lt;T&gt;"/> for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="color">The color to fill this <see cref="FreeImageBitmap"/> with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ public bool FillBackground<T>(T color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ EnsureNotDisposed();
+ return FreeImage.FillBackground(dib, color, options);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile.
+ /// </summary>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="data"/> is a null reference.</exception>
+ public FIICCPROFILE CreateICCProfile(byte[] data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+ return CreateICCProfile(data, data.Length);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile.
+ /// </summary>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <param name="size">The number of bytes of <paramref name="data"/> to use.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="data"/> is null.</exception>
+ public FIICCPROFILE CreateICCProfile(byte[] data, int size)
+ {
+ EnsureNotDisposed();
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+ return FreeImage.CreateICCProfileEx(dib, data, size);
+ }
+
+ /// <summary>
+ /// Determines whether this and the specified instances are the same.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if this instance is the same <paramref name="obj"/>
+ /// or if both are null references; otherwise, false.</returns>
+ public override bool Equals(object obj)
+ {
+ return ReferenceEquals(this, obj);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="FreeImageBitmap"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="FreeImageBitmap"/>.</returns>
+ public override int GetHashCode()
+ {
+ return dib.GetHashCode();
+ }
+
+ #endregion
+
+ #region Static functions
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format for this <see cref="FreeImageBitmap"/> contains alpha information.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> to test.</param>
+ /// <returns><b>true</b> if pixfmt contains alpha information; otherwise, <b>false</b>.</returns>
+ public static bool IsAlphaPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsAlphaPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format is 32 bits per pixel.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> to test.</param>
+ /// <returns>true if pixfmt is canonical; otherwise, false.</returns>
+ public static bool IsCanonicalPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsCanonicalPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Returns a value that indicates whether the pixel format is 64 bits per pixel.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> enumeration to test.</param>
+ /// <returns>true if pixfmt is extended; otherwise, false.</returns>
+ public static bool IsExtendedPixelFormat(PixelFormat pixfmt)
+ {
+ return Bitmap.IsExtendedPixelFormat(pixfmt);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a Windows handle to an icon.
+ /// </summary>
+ /// <param name="hicon">A handle to an icon.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> that this method creates.</returns>
+ public static FreeImageBitmap FromHicon(IntPtr hicon)
+ {
+ using (Bitmap bitmap = Bitmap.FromHicon(hicon))
+ {
+ return new FreeImageBitmap(bitmap);
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified Windows resource.
+ /// </summary>
+ /// <param name="hinstance">A handle to an instance of the executable
+ /// file that contains the resource.</param>
+ /// <param name="bitmapName">A string containing the name of the resource bitmap.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> that this method creates.</returns>
+ public static FreeImageBitmap FromResource(IntPtr hinstance, string bitmapName)
+ {
+ using (Bitmap bitmap = Bitmap.FromResource(hinstance, bitmapName))
+ {
+ return new FreeImageBitmap(bitmap);
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified file.
+ /// </summary>
+ /// <param name="filename">A string that contains the name of the file
+ /// from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromFile(string filename)
+ {
+ return new FreeImageBitmap(filename);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified file
+ /// using embedded color management information in that file.
+ /// </summary>
+ /// <param name="filename">A string that contains the
+ /// name of the file from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromFile(string filename, bool useEmbeddedColorManagement)
+ {
+ return new FreeImageBitmap(filename);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a handle to a GDI bitmap.
+ /// </summary>
+ /// <param name="hbitmap">The GDI bitmap handle from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromHbitmap(IntPtr hbitmap)
+ {
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.CreateFromHbitmap(hbitmap, IntPtr.Zero);
+ if (!newDib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from a handle to a GDI bitmap and a handle to a GDI palette.
+ /// </summary>
+ /// <param name="hbitmap">The GDI bitmap handle from which to create the <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="hpalette">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromHbitmap(IntPtr hbitmap, IntPtr hpalette)
+ {
+ return FromHbitmap(hbitmap);
+ }
+
+ /// <summary>
+ /// Frees a bitmap handle.
+ /// </summary>
+ /// <param name="hbitmap">Handle to a bitmap.</param>
+ /// <returns><b>true</b> on success, <b>false</b> on failure.</returns>
+ public static bool FreeHbitmap(IntPtr hbitmap)
+ {
+ return FreeImage.FreeHbitmap(hbitmap);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="FreeImageBitmap"/> from the specified data stream.
+ /// </summary>
+ /// <param name="stream">A <see cref="Stream"/> that contains the data for this <see cref="FreeImageBitmap"/>.</param>
+ /// <param name="useEmbeddedColorManagement">Ignored.</param>
+ /// <param name="validateImageData">Ignored.</param>
+ /// <returns>The <see cref="FreeImageBitmap"/> this method creates.</returns>
+ public static FreeImageBitmap FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData)
+ {
+ return new FreeImageBitmap(stream);
+ }
+
+ /// <summary>
+ /// Returns the color depth, in number of bits per pixel,
+ /// of the specified pixel format.
+ /// </summary>
+ /// <param name="pixfmt">The <see cref="System.Drawing.Imaging.PixelFormat"/> member that specifies
+ /// the format for which to find the size.</param>
+ /// <returns>The color depth of the specified pixel format.</returns>
+ public static int GetPixelFormatSize(PixelFormat pixfmt)
+ {
+ return Bitmap.GetPixelFormatSize(pixfmt);
+ }
+
+ /// <summary>
+ /// Performs a lossless rotation or flipping on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source file.</param>
+ /// <param name="destination">Destination file; can be the source file; will be overwritten.</param>
+ /// <param name="operation">The operation to apply.</param>
+ /// <param name="perfect">To avoid lossy transformation, you can set the perfect parameter to true.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool JPEGTransform(string source, string destination, FREE_IMAGE_JPEG_OPERATION operation, bool perfect)
+ {
+ return FreeImage.JPEGTransform(source, destination, operation, perfect);
+ }
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source filename.</param>
+ /// <param name="destination">Destination filename.</param>
+ /// <param name="rect">Specifies the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="source"/> or <paramref name="destination"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="source"/> does not exist.
+ /// </exception>
+ public static bool JPEGCrop(string source, string destination, Rectangle rect)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (!File.Exists(source))
+ {
+ throw new FileNotFoundException("source");
+ }
+ if (destination == null)
+ {
+ throw new ArgumentNullException("destination");
+ }
+ return JPEGCrop(source, destination, rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ /// <summary>
+ /// Performs a lossless crop on a JPEG file.
+ /// </summary>
+ /// <param name="source">Source filename.</param>
+ /// <param name="destination">Destination filename.</param>
+ /// <param name="left">Specifies the left position of the cropped rectangle.</param>
+ /// <param name="top">Specifies the top position of the cropped rectangle.</param>
+ /// <param name="right">Specifies the right position of the cropped rectangle.</param>
+ /// <param name="bottom">Specifies the bottom position of the cropped rectangle.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="source"/> or <paramref name="destination"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="source"/> does not exist.
+ /// </exception>
+ public static bool JPEGCrop(string source, string destination, int left, int top, int right, int bottom)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (!File.Exists(source))
+ {
+ throw new FileNotFoundException("source");
+ }
+ if (destination == null)
+ {
+ throw new ArgumentNullException("destination");
+ }
+ return FreeImage.JPEGCrop(source, destination, left, top, right, bottom);
+ }
+
+ /// <summary>
+ /// Converts a X11 color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="color">Name of the color to convert.</param>
+ /// <param name="red">Red component.</param>
+ /// <param name="green">Green component.</param>
+ /// <param name="blue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="color"/> is null.</exception>
+ public static bool LookupX11Color(string color, out byte red, out byte green, out byte blue)
+ {
+ if (color == null)
+ {
+ throw new ArgumentNullException("color");
+ }
+ return FreeImage.LookupX11Color(color, out red, out green, out blue);
+ }
+
+ /// <summary>
+ /// Converts a SVG color name into a corresponding RGB value.
+ /// </summary>
+ /// <param name="color">Name of the color to convert.</param>
+ /// <param name="red">Red component.</param>
+ /// <param name="green">Green component.</param>
+ /// <param name="blue">Blue component.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="color"/> is null.</exception>
+ public static bool LookupSVGColor(string color, out byte red, out byte green, out byte blue)
+ {
+ if (color == null)
+ {
+ throw new ArgumentNullException("color");
+ }
+ return FreeImage.LookupSVGColor(color, out red, out green, out blue);
+ }
+
+ /// <summary>
+ /// Creates a lookup table to be used with AdjustCurve() which
+ /// may adjusts brightness and contrast, correct gamma and invert the image with a
+ /// single call to AdjustCurve().
+ /// </summary>
+ /// <param name="lookUpTable">Output lookup table to be used with AdjustCurve().
+ /// The size of <paramref name="lookUpTable"/> is assumed to be 256.</param>
+ /// <param name="brightness">Percentage brightness value where -100 &lt;= brightness &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will make the image darker and greater
+ /// than 0 will make the image brighter.</para></param>
+ /// <param name="contrast">Percentage contrast value where -100 &lt;= contrast &lt;= 100.
+ /// <para>A value of 0 means no change, less than 0 will decrease the contrast
+ /// and greater than 0 will increase the contrast of the image.</para></param>
+ /// <param name="gamma">Gamma value to be used for gamma correction.
+ /// <para>A value of 1.0 leaves the image alone, less than one darkens it,
+ /// and greater than one lightens it.</para></param>
+ /// <param name="invert">If set to true, the image will be inverted.</param>
+ /// <returns>The number of adjustments applied to the resulting lookup table
+ /// compared to a blind lookup table.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="lookUpTable"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="lookUpTable.Length"/> is not 256.</exception>
+ public static int GetAdjustColorsLookupTable(byte[] lookUpTable, double brightness, double contrast, double gamma, bool invert)
+ {
+ if (lookUpTable == null)
+ {
+ throw new ArgumentNullException("lookUpTable");
+ }
+ if (lookUpTable.Length != 256)
+ {
+ throw new ArgumentException("lookUpTable");
+ }
+ return FreeImage.GetAdjustColorsLookupTable(lookUpTable, brightness, contrast, gamma, invert);
+ }
+
+ /// <summary>
+ /// Adds a specified frame to the file specified using the specified parameters.
+ /// Use this method to save selected frames from an to a multiple-frame image.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> or <paramref name="bitmap"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ public static void SaveAdd(
+ string filename,
+ FreeImageBitmap bitmap,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ bitmap.EnsureNotDisposed();
+
+ FIBITMAP dib = bitmap.dib;
+ if (dib.IsNull)
+ throw new ArgumentNullException("bitmap");
+
+ FIMULTIBITMAP mpBitmap =
+ FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true);
+
+ if (mpBitmap.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ FreeImage.AppendPage(mpBitmap, bitmap.dib);
+
+ if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags))
+ throw new Exception(ErrorUnloadBitmap);
+ }
+
+ /// <summary>
+ /// Adds a specified frame to the file specified using the specified parameters.
+ /// Use this method to save selected frames from an image to a multiple-frame image.
+ /// </summary>
+ /// <param name="filename">File to add this frame to.</param>
+ /// <param name="bitmap">A <see cref="FreeImageBitmap"/> that contains the frame to add.</param>
+ /// <param name="insertPosition">The position of the inserted frame.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="loadFlags">Flags to enable or disable plugin-features.</param>
+ /// <param name="saveFlags">Flags to enable or disable plugin-features.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> or <paramref name="bitmap"/> is null.
+ /// </exception>
+ /// <exception cref="FileNotFoundException"><paramref name="filename"/> does not exist.</exception>
+ /// <exception cref="Exception">Saving the image failed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="insertPosition"/> is out of range.</exception>
+ public static void SaveAdd(
+ string filename,
+ FreeImageBitmap bitmap,
+ int insertPosition,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS loadFlags,
+ FREE_IMAGE_SAVE_FLAGS saveFlags)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException("filename");
+ }
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ if (insertPosition < 0)
+ {
+ throw new ArgumentOutOfRangeException("insertPosition");
+ }
+ bitmap.EnsureNotDisposed();
+
+ FIBITMAP dib = bitmap.dib;
+ if (dib.IsNull)
+ throw new ArgumentNullException("bitmap");
+
+ FIMULTIBITMAP mpBitmap =
+ FreeImage.OpenMultiBitmapEx(filename, ref format, loadFlags, false, false, true);
+
+ if (mpBitmap.IsNull)
+ throw new Exception(ErrorLoadingBitmap);
+
+ int pageCount = FreeImage.GetPageCount(mpBitmap);
+
+ if (insertPosition > pageCount)
+ throw new ArgumentOutOfRangeException("insertPosition");
+
+ if (insertPosition == pageCount)
+ FreeImage.AppendPage(mpBitmap, bitmap.dib);
+ else
+ FreeImage.InsertPage(mpBitmap, insertPosition, bitmap.dib);
+
+ if (!FreeImage.CloseMultiBitmap(mpBitmap, saveFlags))
+ throw new Exception(ErrorUnloadBitmap);
+ }
+
+ /// <summary>
+ /// Returns a new instance of the <see cref="PropertyItem"/> class which
+ /// has no public accessible constructor.
+ /// </summary>
+ /// <returns>A new instace of <see cref="PropertyItem"/>.</returns>
+ public static PropertyItem CreateNewPropertyItem()
+ {
+ return FreeImage.CreatePropertyItem();
+ }
+
+ #endregion
+
+ #region Helper functions
+
+ /// <summary>
+ /// Throws an exception in case the instance has already been disposed.
+ /// </summary>
+ private void EnsureNotDisposed()
+ {
+ lock (lockObject)
+ {
+ if (!this.disposed)
+ {
+ return;
+ }
+ }
+ throw new ObjectDisposedException(ToString());
+ }
+
+ /// <summary>
+ /// Tries to replace the wrapped <see cref="FIBITMAP"/> with a new one.
+ /// In case the new dib is null or the same as the already
+ /// wrapped one, nothing will be changed and the result will
+ /// be false.
+ /// Otherwise the wrapped <see cref="FIBITMAP"/> will be unloaded and replaced.
+ /// </summary>
+ /// <param name="newDib">The new dib.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ private bool ReplaceDib(FIBITMAP newDib)
+ {
+ bool result = false;
+ if ((dib != newDib) && (!newDib.IsNull))
+ {
+ UnloadDib();
+ dib = newDib;
+ AddMemoryPressure();
+ result = true;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Unloads currently wrapped <see cref="FIBITMAP"/> or unlocks the locked page
+ /// in case it came from a multipaged bitmap.
+ /// </summary>
+ private void UnloadDib()
+ {
+ if (!dib.IsNull)
+ {
+ long size = FreeImage.GetDIBSize(dib);
+ FreeImage.UnloadEx(ref dib);
+ if (size > 0L)
+ GC.RemoveMemoryPressure(size);
+ }
+ }
+
+ /// <summary>
+ /// Informs the runtime about unmanaged allocoted memory.
+ /// </summary>
+ private void AddMemoryPressure()
+ {
+ long dataSize;
+ if ((dataSize = DataSize) > 0L)
+ GC.AddMemoryPressure(dataSize);
+ }
+
+ /// <summary>
+ /// Opens the stream and reads the number of available pages.
+ /// Then loads the first page to this instance.
+ /// </summary>
+ private void LoadFromStream(Stream stream, FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmapFromStream(stream, ref format, flags);
+ if (mdib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+ try
+ {
+ frameCount = FreeImage.GetPageCount(mdib);
+ }
+ finally
+ {
+ if (!FreeImage.CloseMultiBitmapEx(ref mdib))
+ {
+ throw new Exception(ErrorUnloadBitmap);
+ }
+ }
+
+ dib = FreeImage.LoadFromStream(stream, flags, ref format);
+ if (dib.IsNull)
+ {
+ throw new Exception(ErrorLoadingBitmap);
+ }
+
+ saveInformation.loadFlags = flags;
+ originalFormat = format;
+ AddMemoryPressure();
+ }
+
+ #endregion
+
+ #region Interfaces
+
+ /// <summary>
+ /// Helper class to store informations for <see cref="FreeImageBitmap.SaveAdd()"/>.
+ /// </summary>
+ private sealed class SaveInformation : ICloneable
+ {
+ public string filename;
+ public FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ public FREE_IMAGE_LOAD_FLAGS loadFlags = FREE_IMAGE_LOAD_FLAGS.DEFAULT;
+ public FREE_IMAGE_SAVE_FLAGS saveFlags = FREE_IMAGE_SAVE_FLAGS.DEFAULT;
+
+ public object Clone()
+ {
+ return base.MemberwiseClone();
+ }
+ }
+
+ /// <summary>
+ /// Creates a deep copy of this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>A deep copy of this <see cref="FreeImageBitmap"/>.</returns>
+ public object Clone()
+ {
+ EnsureNotDisposed();
+ FreeImageBitmap result = null;
+ FIBITMAP newDib = FreeImage.Clone(dib);
+ if (!dib.IsNull)
+ {
+ result = new FreeImageBitmap(newDib);
+ result.saveInformation = (SaveInformation)saveInformation.Clone();
+ result.tag = tag;
+ result.originalFormat = originalFormat;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
+ /// releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing,
+ /// releasing, or resetting unmanaged resources.
+ /// </summary>
+ /// <param name="disposing">If true managed ressources are released.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ // Only clean up once
+ lock (lockObject)
+ {
+ if (disposed)
+ {
+ return;
+ }
+ disposed = true;
+ }
+
+ // Clean up managed resources
+ if (disposing)
+ {
+ if (stream != null)
+ {
+ if (disposeStream)
+ {
+ stream.Dispose();
+ }
+ stream = null;
+ }
+ }
+
+ tag = null;
+ saveInformation = null;
+
+ // Clean up unmanaged resources
+ UnloadDib();
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual scanlines in this <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the <see cref="FreeImageBitmap"/>.</returns>
+ /// <exception cref="ArgumentException">The bitmaps's type is not supported.</exception>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetScanlines().GetEnumerator();
+ }
+
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ EnsureNotDisposed();
+ using (MemoryStream memory = new MemoryStream(DataSize))
+ {
+ if (!FreeImage.SaveToStream(dib, memory, FREE_IMAGE_FORMAT.FIF_TIFF, FREE_IMAGE_SAVE_FLAGS.TIFF_LZW))
+ {
+ throw new SerializationException();
+ }
+ memory.Capacity = (int)memory.Length;
+ info.AddValue("Bitmap Data", memory.GetBuffer());
+ }
+ }
+
+ #endregion
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Class handling non-bitmap related functions.
+ /// </summary>
+ public static class FreeImageEngine
+ {
+ #region Callback
+
+ // Callback delegate
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly OutputMessageFunction outputMessageFunction;
+
+ static FreeImageEngine()
+ {
+ // Check if FreeImage.dll is present and cancel setting the callbackfuntion if not
+ if (!IsAvailable)
+ {
+ return;
+ }
+ // Create a delegate (function pointer) to 'OnMessage'
+ outputMessageFunction = new OutputMessageFunction(OnMessage);
+ // Set the callback
+ FreeImage.SetOutputMessage(outputMessageFunction);
+ }
+
+ /// <summary>
+ /// Internal callback
+ /// </summary>
+ private static void OnMessage(FREE_IMAGE_FORMAT fif, string message)
+ {
+ // Get a local copy of the multicast-delegate
+ OutputMessageFunction m = Message;
+
+ // Check the local copy instead of the static instance
+ // to prevent a second thread from setting the delegate
+ // to null, which would cause a nullreference exception
+ if (m != null)
+ {
+ // Invoke the multicast-delegate
+ m.Invoke(fif, message);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating if the FreeImage DLL is available or not.
+ /// </summary>
+ public static bool IsAvailable
+ {
+ get
+ {
+ return FreeImage.IsAvailable();
+ }
+ }
+
+ /// <summary>
+ /// Internal errors in FreeImage generate a logstring that can be
+ /// captured by this event.
+ /// </summary>
+ public static event OutputMessageFunction Message;
+
+ #endregion
+
+ /// <summary>
+ /// Gets a string containing the current version of the library.
+ /// </summary>
+ public static string Version
+ {
+ get
+ {
+ return FreeImage.GetVersion();
+ }
+ }
+
+ /// <summary>
+ /// Gets a string containing a standard copyright message.
+ /// </summary>
+ public static string CopyrightMessage
+ {
+ get
+ {
+ return FreeImage.GetCopyrightMessage();
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the platform is using Little Endian.
+ /// </summary>
+ public static bool IsLittleEndian
+ {
+ get
+ {
+ return FreeImage.IsLittleEndian();
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing a FreeImage format.
+ /// </summary>
+ public sealed class FreeImagePlugin
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly FREE_IMAGE_FORMAT fif;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="fif">The FreeImage format to wrap.</param>
+ internal FreeImagePlugin(FREE_IMAGE_FORMAT fif)
+ {
+ this.fif = fif;
+ }
+
+ /// <summary>
+ /// Gets the format of this instance.
+ /// </summary>
+ public FREE_IMAGE_FORMAT FIFormat
+ {
+ get
+ {
+ return fif;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether this plugin is enabled.
+ /// </summary>
+ public bool Enabled
+ {
+ get
+ {
+ return (FreeImage.IsPluginEnabled(fif) == 1);
+ }
+ set
+ {
+ FreeImage.SetPluginEnabled(fif, value);
+ }
+ }
+
+ /// <summary>
+ /// Gets a string describing the format.
+ /// </summary>
+ public string Format
+ {
+ get
+ {
+ return FreeImage.GetFormatFromFIF(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets a comma-delimited file extension list describing the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ public string ExtentsionList
+ {
+ get
+ {
+ return FreeImage.GetFIFExtensionList(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets a descriptive string that describes the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ public string Description
+ {
+ get
+ {
+ return FreeImage.GetFIFDescription(fif);
+ }
+ }
+
+ /// <summary>
+ /// Returns a regular expression string that can be used by
+ /// a regular expression engine to identify the bitmap.
+ /// FreeImageQt makes use of this function.
+ /// </summary>
+ public string RegExpr
+ {
+ get
+ {
+ return FreeImage.GetFIFRegExpr(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can load bitmaps.
+ /// </summary>
+ public bool SupportsReading
+ {
+ get
+ {
+ return FreeImage.FIFSupportsReading(fif);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can save bitmaps.
+ /// </summary>
+ public bool SupportsWriting
+ {
+ get
+ {
+ return FreeImage.FIFSupportsWriting(fif);
+ }
+ }
+
+ /// <summary>
+ /// Checks whether this plugin can save a bitmap in the desired data type.
+ /// </summary>
+ /// <param name="type">The desired image type.</param>
+ /// <returns>True if this plugin can save bitmaps as the desired type, else false.</returns>
+ public bool SupportsExportType(FREE_IMAGE_TYPE type)
+ {
+ return FreeImage.FIFSupportsExportType(fif, type);
+ }
+
+ /// <summary>
+ /// Checks whether this plugin can save bitmaps in the desired bit depth.
+ /// </summary>
+ /// <param name="bpp">The desired bit depth.</param>
+ /// <returns>True if this plugin can save bitmaps in the desired bit depth, else false.</returns>
+ public bool SupportsExportBPP(int bpp)
+ {
+ return FreeImage.FIFSupportsExportBPP(fif, bpp);
+ }
+
+ /// <summary>
+ /// Gets whether this plugin can load or save an ICC profile.
+ /// </summary>
+ public bool SupportsICCProfiles
+ {
+ get
+ {
+ return FreeImage.FIFSupportsICCProfiles(fif);
+ }
+ }
+
+ /// <summary>
+ /// Checks whether an extension is valid for this format.
+ /// </summary>
+ /// <param name="extension">The desired extension.</param>
+ /// <returns>True if the extension is valid for this format, false otherwise.</returns>
+ public bool ValidExtension(string extension)
+ {
+ return FreeImage.IsExtensionValidForFIF(fif, extension);
+ }
+
+ /// <summary>
+ /// Checks whether an extension is valid for this format.
+ /// </summary>
+ /// <param name="extension">The desired extension.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the extension is valid for this format, false otherwise.</returns>
+ public bool ValidExtension(string extension, StringComparison comparisonType)
+ {
+ return FreeImage.IsExtensionValidForFIF(fif, extension, comparisonType);
+ }
+
+ /// <summary>
+ /// Checks whether a filename is valid for this format.
+ /// </summary>
+ /// <param name="filename">The desired filename.</param>
+ /// <returns>True if the filename is valid for this format, false otherwise.</returns>
+ public bool ValidFilename(string filename)
+ {
+ return FreeImage.IsFilenameValidForFIF(fif, filename);
+ }
+
+ /// <summary>
+ /// Checks whether a filename is valid for this format.
+ /// </summary>
+ /// <param name="filename">The desired filename.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the filename is valid for this format, false otherwise.</returns>
+ public bool ValidFilename(string filename, StringComparison comparisonType)
+ {
+ return FreeImage.IsFilenameValidForFIF(fif, filename, comparisonType);
+ }
+
+ /// <summary>
+ /// Gets a descriptive string that describes the bitmap formats
+ /// this plugin can read and/or write.
+ /// </summary>
+ /// <returns>A descriptive string that describes the bitmap formats.</returns>
+ public override string ToString()
+ {
+ return Description;
+ }
+ }
+}
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Internal class wrapping stream io functions.
+ /// </summary>
+ /// <remarks>
+ /// FreeImage can read files from a disk or a network drive but also allows the user to
+ /// implement their own loading or saving functions to load them directly from an ftp or web
+ /// server for example.
+ /// <para/>
+ /// In .NET streams are a common way to handle data. The <b>FreeImageStreamIO</b> class handles
+ /// the loading and saving from and to streams. It implements the funtions FreeImage needs
+ /// to load data from an an arbitrary source.
+ /// <para/>
+ /// The class is for internal use only.
+ /// </remarks>
+ internal static class FreeImageStreamIO
+ {
+ /// <summary>
+ /// <see cref="FreeImageAPI.IO.FreeImageIO"/> structure that can be used to read from streams via
+ /// <see cref="FreeImageAPI.FreeImage.LoadFromHandle(FREE_IMAGE_FORMAT, ref FreeImageIO, fi_handle, FREE_IMAGE_LOAD_FLAGS)"/>.
+ /// </summary>
+ public static readonly FreeImageIO io;
+
+ /// <summary>
+ /// Initializes a new instances which can be used to
+ /// create a FreeImage compatible <see cref="FreeImageAPI.IO.FreeImageIO"/> structure.
+ /// </summary>
+ static FreeImageStreamIO()
+ {
+ io.readProc = new ReadProc(streamRead);
+ io.writeProc = new WriteProc(streamWrite);
+ io.seekProc = new SeekProc(streamSeek);
+ io.tellProc = new TellProc(streamTell);
+ }
+
+ /// <summary>
+ /// Reads the requested data from the stream and writes it to the given address.
+ /// </summary>
+ static unsafe uint streamRead(IntPtr buffer, uint size, uint count, fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if ((stream == null) || (!stream.CanRead))
+ {
+ return 0;
+ }
+ uint readCount = 0;
+ byte* ptr = (byte*)buffer;
+ byte[] bufferTemp = new byte[size];
+ int read;
+ while (readCount < count)
+ {
+ read = stream.Read(bufferTemp, 0, (int)size);
+ if (read != (int)size)
+ {
+ stream.Seek(-read, SeekOrigin.Current);
+ break;
+ }
+ for (int i = 0; i < read; i++, ptr++)
+ {
+ *ptr = bufferTemp[i];
+ }
+ readCount++;
+ }
+ return (uint)readCount;
+ }
+
+ /// <summary>
+ /// Reads the given data and writes it into the stream.
+ /// </summary>
+ static unsafe uint streamWrite(IntPtr buffer, uint size, uint count, fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if ((stream == null) || (!stream.CanWrite))
+ {
+ return 0;
+ }
+ uint writeCount = 0;
+ byte[] bufferTemp = new byte[size];
+ byte* ptr = (byte*)buffer;
+ while (writeCount < count)
+ {
+ for (int i = 0; i < size; i++, ptr++)
+ {
+ bufferTemp[i] = *ptr;
+ }
+ try
+ {
+ stream.Write(bufferTemp, 0, bufferTemp.Length);
+ }
+ catch
+ {
+ return writeCount;
+ }
+ writeCount++;
+ }
+ return writeCount;
+ }
+
+ /// <summary>
+ /// Moves the streams position.
+ /// </summary>
+ static int streamSeek(fi_handle handle, int offset, SeekOrigin origin)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if (stream == null)
+ {
+ return 1;
+ }
+ stream.Seek((long)offset, origin);
+ return 0;
+ }
+
+ /// <summary>
+ /// Returns the streams current position
+ /// </summary>
+ static int streamTell(fi_handle handle)
+ {
+ Stream stream = handle.GetObject() as Stream;
+ if (stream == null)
+ {
+ return -1;
+ }
+ return (int)stream.Position;
+ }
+ }
+}
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Provides additional information specific for GIF files. This class cannot be inherited.
+ /// </summary>
+ public class GifInformation : MDM_ANIMATION
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GifInformation"/> class
+ /// with the specified <see cref="FreeImageBitmap"/>.
+ /// </summary>
+ /// <param name="bitmap">A reference to a <see cref="FreeImageBitmap"/> instance.</param>
+ public GifInformation(FreeImageBitmap bitmap)
+ : base(bitmap.Dib)
+ {
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this frame uses the
+ /// GIF image's global palette. If set to <b>false</b>, this
+ /// frame uses its local palette.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? UseGlobalPalette
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("NoLocalPalette");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("NoLocalPalette", val);
+ }
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image, intialized with all entries of the
+ /// current local palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">
+ /// The image does not have a palette.
+ /// </exception>
+ public void CreateGlobalPalette()
+ {
+ CreateGlobalPalette(new Palette(dib));
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image with the specified size, intialized
+ /// with the first <paramref name="size"/> entries of the current local palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="size">The size of the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(int size)
+ {
+ CreateGlobalPalette(new Palette(dib), size);
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image, intialized with the entries
+ /// of the specified palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="palette">The palette that contains the initial values for
+ /// the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(Palette palette)
+ {
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+
+ GlobalPalette = palette;
+ UseGlobalPalette = true;
+ }
+
+ /// <summary>
+ /// Creates a global palette for the GIF image with the specified size, intialized
+ /// with the first <paramref name="size"/> entries of the specified palette.
+ /// The property <see cref="UseGlobalPalette"/> will be set to <b>true</b> when
+ /// invoking this method. This effectively enables the newly created global palette.
+ /// </summary>
+ /// <param name="palette">The palette that contains the initial values for
+ /// the newly created global palette.</param>
+ /// <param name="size">The size of the newly created global palette.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CreateGlobalPalette(Palette palette, int size)
+ {
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+ if (size <= 0)
+ {
+ throw new ArgumentOutOfRangeException("size");
+ }
+
+ Palette pal = new Palette(size);
+ pal.CopyFrom(palette);
+ GlobalPalette = palette;
+ UseGlobalPalette = true;
+ }
+ }
+}
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Class handling metadata of a FreeImage bitmap.
+ /// </summary>
+ public class ImageMetadata : IEnumerable, IComparable, IComparable<ImageMetadata>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly List<MetadataModel> data;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly FIBITMAP dib;
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool hideEmptyModels;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="FIBITMAP"/>,
+ /// showing all known models.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public ImageMetadata(FIBITMAP dib) : this(dib, false) { }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="FIBITMAP"/>,
+ /// showing or hiding empry models.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hideEmptyModels">When <b>true</b>, empty metadata models
+ /// will be hidden until a tag to this model is added.</param>
+ public ImageMetadata(FIBITMAP dib, bool hideEmptyModels)
+ {
+ if (dib.IsNull) throw new ArgumentNullException("dib");
+ data = new List<MetadataModel>(FreeImage.FREE_IMAGE_MDMODELS.Length);
+ this.dib = dib;
+ this.hideEmptyModels = hideEmptyModels;
+
+ data.Add(new MDM_ANIMATION(dib));
+ data.Add(new MDM_COMMENTS(dib));
+ data.Add(new MDM_CUSTOM(dib));
+ data.Add(new MDM_EXIF_EXIF(dib));
+ data.Add(new MDM_EXIF_GPS(dib));
+ data.Add(new MDM_INTEROP(dib));
+ data.Add(new MDM_EXIF_MAIN(dib));
+ data.Add(new MDM_MAKERNOTE(dib));
+ data.Add(new MDM_GEOTIFF(dib));
+ data.Add(new MDM_IPTC(dib));
+ data.Add(new MDM_NODATA(dib));
+ data.Add(new MDM_XMP(dib));
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="MetadataModel"/> of the specified type.
+ /// <para>In case the getter returns <c>null</c> the model is not contained
+ /// by the list.</para>
+ /// <para><c>null</c> can be used calling the setter to destroy the model.</para>
+ /// </summary>
+ /// <param name="model">Type of the model.</param>
+ /// <returns>The <see cref="FreeImageAPI.Metadata.MetadataModel"/> object of the specified type.</returns>
+ public MetadataModel this[FREE_IMAGE_MDMODEL model]
+ {
+ get
+ {
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Model == model)
+ {
+ if (!data[i].Exists && hideEmptyModels)
+ {
+ return null;
+ }
+ return data[i];
+ }
+ }
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="FreeImageAPI.Metadata.MetadataModel"/> at the specified index.
+ /// <para>In case the getter returns <c>null</c> the model is not contained
+ /// by the list.</para>
+ /// <para><c>null</c> can be used calling the setter to destroy the model.</para>
+ /// </summary>
+ /// <param name="index">Index of the <see cref="FreeImageAPI.Metadata.MetadataModel"/> within
+ /// this instance.</param>
+ /// <returns>The <see cref="FreeImageAPI.Metadata.MetadataModel"/>
+ /// object at the specified index.</returns>
+ public MetadataModel this[int index]
+ {
+ get
+ {
+ if (index < 0 || index >= data.Count)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ return (hideEmptyModels && !data[index].Exists) ? null : data[index];
+ }
+ }
+
+ /// <summary>
+ /// Returns a list of all visible
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>.
+ /// </summary>
+ public List<MetadataModel> List
+ {
+ get
+ {
+ if (hideEmptyModels)
+ {
+ List<MetadataModel> result = new List<MetadataModel>();
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ result.Add(data[i]);
+ }
+ }
+ return result;
+ }
+ else
+ {
+ return data;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds new tag to the bitmap or updates its value in case it already exists.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="tag">The tag to add or update.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="tag"/> is null.</exception>
+ public bool AddTag(MetadataTag tag)
+ {
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (tag.Model == data[i].Model)
+ {
+ return data[i].AddTag(tag);
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns the number of visible
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>.
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ if (hideEmptyModels)
+ {
+ int count = 0;
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+ else
+ {
+ return data.Count;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether empty
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see> are hidden.
+ /// </summary>
+ public bool HideEmptyModels
+ {
+ get
+ {
+ return hideEmptyModels;
+ }
+ set
+ {
+ hideEmptyModels = value;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel">MetadataModels</see>
+ /// in this <see cref="ImageMetadata"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for this <see cref="ImageMetadata"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ if (hideEmptyModels)
+ {
+ List<MetadataModel> tempList = new List<MetadataModel>(data.Count);
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (data[i].Exists)
+ {
+ tempList.Add(data[i]);
+ }
+ }
+ return tempList.GetEnumerator();
+ }
+ else
+ {
+ return data.GetEnumerator();
+ }
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="ImageMetadata"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is ImageMetadata))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((ImageMetadata)obj);
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="ImageMetadata"/> object.
+ /// </summary>
+ /// <param name="other">A <see cref="ImageMetadata"/> to compare.</param>
+ /// <returns>A signed number indicating the relative values of this instance
+ /// and <paramref name="other"/>.</returns>
+ public int CompareTo(ImageMetadata other)
+ {
+ return this.dib.CompareTo(other.dib);
+ }
+ }
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing own FreeImage-Plugins.
+ /// </summary>
+ /// <remarks>
+ /// FreeImages itself is plugin based. Each supported format is integrated by a seperat plugin,
+ /// that handles loading, saving, descriptions, identifing ect.
+ /// And of course the user can create own plugins and use them in FreeImage.
+ /// To do that the above mentioned predefined methodes need to be implemented.
+ /// <para/>
+ /// The class below handles the creation of such a plugin. The class itself is abstract
+ /// as well as some core functions that need to be implemented.
+ /// The class can be used to enable or disable the plugin in FreeImage after regististration or
+ /// retrieve the formatid, assigned by FreeImage.
+ /// The class handles the callback functions, garbage collector and pointer operation to make
+ /// the implementation as user friendly as possible.
+ /// <para/>
+ /// How to:
+ /// There are two functions that need to be implemented:
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> and
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.FormatProc"/>.
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> is used by the constructor
+ /// of the abstract class. FreeImage wants a list of the implemented functions. Each function is
+ /// represented by a function pointer (a .NET <see cref="System.Delegate"/>). In case a function
+ /// is not implemented FreeImage receives an empty <b>delegate</b>). To tell the constructor
+ /// which functions have been implemented the information is represented by a disjunction of
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.MethodFlags"/>.
+ /// <para/>
+ /// For example:
+ /// return MethodFlags.LoadProc | MethodFlags.SaveProc;
+ /// <para/>
+ /// The above statement means that LoadProc and SaveProc have been implemented by the user.
+ /// Keep in mind, that each function has a standard implementation that has static return
+ /// values that may cause errors if listed in
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.GetImplementedMethods"/> without a real implementation.
+ /// <para/>
+ /// <see cref="FreeImageAPI.Plugins.LocalPlugin.FormatProc"/> is used by some checks of FreeImage and
+ /// must be implemented. <see cref="FreeImageAPI.Plugins.LocalPlugin.LoadProc"/> for example can be
+ /// implemented if the plugin supports reading, but it doesn't have to, the plugin could only
+ /// be used to save an already loaded bitmap in a special format.
+ /// </remarks>
+ public abstract class LocalPlugin
+ {
+ /// <summary>
+ /// Struct containing function pointers.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private Plugin plugin;
+
+ /// <summary>
+ /// Delegate for register callback by FreeImage.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private InitProc initProc;
+
+ /// <summary>
+ /// The format id assiged to the plugin.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+
+ /// <summary>
+ /// When true the plugin was registered successfully else false.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool registered = false;
+
+ /// <summary>
+ /// A copy of the functions used to register.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly MethodFlags implementedMethods;
+
+ /// <summary>
+ /// MethodFlags defines values to fill a bitfield telling which
+ /// functions have been implemented by a plugin.
+ /// </summary>
+ [Flags]
+ protected enum MethodFlags
+ {
+ /// <summary>
+ /// No mothods implemented.
+ /// </summary>
+ None = 0x0,
+
+ /// <summary>
+ /// DescriptionProc has been implemented.
+ /// </summary>
+ DescriptionProc = 0x1,
+
+ /// <summary>
+ /// ExtensionListProc has been implemented.
+ /// </summary>
+ ExtensionListProc = 0x2,
+
+ /// <summary>
+ /// RegExprProc has been implemented.
+ /// </summary>
+ RegExprProc = 0x4,
+
+ /// <summary>
+ /// OpenProc has been implemented.
+ /// </summary>
+ OpenProc = 0x8,
+
+ /// <summary>
+ /// CloseProc has been implemented.
+ /// </summary>
+ CloseProc = 0x10,
+
+ /// <summary>
+ /// PageCountProc has been implemented.
+ /// </summary>
+ PageCountProc = 0x20,
+
+ /// <summary>
+ /// PageCapabilityProc has been implemented.
+ /// </summary>
+ PageCapabilityProc = 0x40,
+
+ /// <summary>
+ /// LoadProc has been implemented.
+ /// </summary>
+ LoadProc = 0x80,
+
+ /// <summary>
+ /// SaveProc has been implemented.
+ /// </summary>
+ SaveProc = 0x100,
+
+ /// <summary>
+ /// ValidateProc has been implemented.
+ /// </summary>
+ ValidateProc = 0x200,
+
+ /// <summary>
+ /// MimeProc has been implemented.
+ /// </summary>
+ MimeProc = 0x400,
+
+ /// <summary>
+ /// SupportsExportBPPProc has been implemented.
+ /// </summary>
+ SupportsExportBPPProc = 0x800,
+
+ /// <summary>
+ /// SupportsExportTypeProc has been implemented.
+ /// </summary>
+ SupportsExportTypeProc = 0x1000,
+
+ /// <summary>
+ /// SupportsICCProfilesProc has been implemented.
+ /// </summary>
+ SupportsICCProfilesProc = 0x2000
+ }
+
+ // Functions that must be implemented.
+
+ /// <summary>
+ /// Function that returns a bitfield containing the
+ /// implemented methods.
+ /// </summary>
+ /// <returns>Bitfield of the implemented methods.</returns>
+ protected abstract MethodFlags GetImplementedMethods();
+
+ /// <summary>
+ /// Implementation of <b>FormatProc</b>
+ /// </summary>
+ /// <returns>A string containing the plugins format.</returns>
+ protected abstract string FormatProc();
+
+ // Functions that can be implemented.
+
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string DescriptionProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string ExtensionListProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string RegExprProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual IntPtr OpenProc(ref FreeImageIO io, fi_handle handle, bool read) { return IntPtr.Zero; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual void CloseProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual int PageCountProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { return 0; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual int PageCapabilityProc(ref FreeImageIO io, fi_handle handle, IntPtr data) { return 0; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual FIBITMAP LoadProc(ref FreeImageIO io, fi_handle handle, int page, int flags, IntPtr data) { return FIBITMAP.Zero; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SaveProc(ref FreeImageIO io, FIBITMAP dib, fi_handle handle, int page, int flags, IntPtr data) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool ValidateProc(ref FreeImageIO io, fi_handle handle) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual string MimeProc() { return ""; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsExportBPPProc(int bpp) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsExportTypeProc(FREE_IMAGE_TYPE type) { return false; }
+ /// <summary>
+ /// Function that can be implemented.
+ /// </summary>
+ protected virtual bool SupportsICCProfilesProc() { return false; }
+
+ /// <summary>
+ /// The constructor automatically registeres the plugin in FreeImage.
+ /// To do this it prepares a FreeImage defined structure with function pointers
+ /// to the implemented functions or null if not implemented.
+ /// Before registing the functions they are pinned in memory so the garbage collector
+ /// can't move them around in memory after we passed there addresses to FreeImage.
+ /// </summary>
+ public LocalPlugin()
+ {
+ implementedMethods = GetImplementedMethods();
+
+ if ((implementedMethods & MethodFlags.DescriptionProc) != 0)
+ {
+ plugin.descriptionProc = new DescriptionProc(DescriptionProc);
+ }
+ if ((implementedMethods & MethodFlags.ExtensionListProc) != 0)
+ {
+ plugin.extensionListProc = new ExtensionListProc(ExtensionListProc);
+ }
+ if ((implementedMethods & MethodFlags.RegExprProc) != 0)
+ {
+ plugin.regExprProc = new RegExprProc(RegExprProc);
+ }
+ if ((implementedMethods & MethodFlags.OpenProc) != 0)
+ {
+ plugin.openProc = new OpenProc(OpenProc);
+ }
+ if ((implementedMethods & MethodFlags.CloseProc) != 0)
+ {
+ plugin.closeProc = new CloseProc(CloseProc);
+ }
+ if ((implementedMethods & MethodFlags.PageCountProc) != 0)
+ {
+ plugin.pageCountProc = new PageCountProc(PageCountProc);
+ }
+ if ((implementedMethods & MethodFlags.PageCapabilityProc) != 0)
+ {
+ plugin.pageCapabilityProc = new PageCapabilityProc(PageCapabilityProc);
+ }
+ if ((implementedMethods & MethodFlags.LoadProc) != 0)
+ {
+ plugin.loadProc = new LoadProc(LoadProc);
+ }
+ if ((implementedMethods & MethodFlags.SaveProc) != 0)
+ {
+ plugin.saveProc = new SaveProc(SaveProc);
+ }
+ if ((implementedMethods & MethodFlags.ValidateProc) != 0)
+ {
+ plugin.validateProc = new ValidateProc(ValidateProc);
+ }
+ if ((implementedMethods & MethodFlags.MimeProc) != 0)
+ {
+ plugin.mimeProc = new MimeProc(MimeProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsExportBPPProc) != 0)
+ {
+ plugin.supportsExportBPPProc = new SupportsExportBPPProc(SupportsExportBPPProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsExportTypeProc) != 0)
+ {
+ plugin.supportsExportTypeProc = new SupportsExportTypeProc(SupportsExportTypeProc);
+ }
+ if ((implementedMethods & MethodFlags.SupportsICCProfilesProc) != 0)
+ {
+ plugin.supportsICCProfilesProc = new SupportsICCProfilesProc(SupportsICCProfilesProc);
+ }
+
+ // FormatProc is always implemented
+ plugin.formatProc = new FormatProc(FormatProc);
+
+ // InitProc is the register call back.
+ initProc = new InitProc(RegisterProc);
+
+ // Register the plugin. The result will be saved and can be accessed later.
+ registered = FreeImage.RegisterLocalPlugin(initProc, null, null, null, null) != FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ if (registered)
+ {
+ PluginRepository.RegisterLocalPlugin(this);
+ }
+ }
+
+ private void RegisterProc(ref Plugin plugin, int format_id)
+ {
+ // Copy the function pointers
+ plugin = this.plugin;
+ // Retrieve the format if assigned to this plugin by FreeImage.
+ format = (FREE_IMAGE_FORMAT)format_id;
+ }
+
+ /// <summary>
+ /// Gets or sets if the plugin is enabled.
+ /// </summary>
+ public bool Enabled
+ {
+ get
+ {
+ if (registered)
+ {
+ return (FreeImage.IsPluginEnabled(format) > 0);
+ }
+ else
+ {
+ throw new ObjectDisposedException("plugin not registered");
+ }
+ }
+ set
+ {
+ if (registered)
+ {
+ FreeImage.SetPluginEnabled(format, value);
+ }
+ else
+ {
+ throw new ObjectDisposedException("plugin not registered");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets if the plugin was registered successfully.
+ /// </summary>
+ public bool Registered
+ {
+ get { return registered; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="FREE_IMAGE_FORMAT"/> FreeImage assigned to this plugin.
+ /// </summary>
+ public FREE_IMAGE_FORMAT Format
+ {
+ get
+ {
+ return format;
+ }
+ }
+
+ /// <summary>
+ /// Reads from an unmanaged stream.
+ /// </summary>
+ protected unsafe int Read(FreeImageIO io, fi_handle handle, uint size, uint count, ref byte[] buffer)
+ {
+ fixed (byte* ptr = buffer)
+ {
+ return (int)io.readProc(new IntPtr(ptr), size, count, handle);
+ }
+ }
+
+ /// <summary>
+ /// Reads a single byte from an unmanaged stream.
+ /// </summary>
+ protected unsafe int ReadByte(FreeImageIO io, fi_handle handle)
+ {
+ byte buffer = 0;
+ return (int)io.readProc(new IntPtr(&buffer), 1, 1, handle) > 0 ? buffer : -1;
+ }
+
+ /// <summary>
+ /// Writes to an unmanaged stream.
+ /// </summary>
+ protected unsafe int Write(FreeImageIO io, fi_handle handle, uint size, uint count, ref byte[] buffer)
+ {
+ fixed (byte* ptr = buffer)
+ {
+ return (int)io.writeProc(new IntPtr(ptr), size, count, handle);
+ }
+ }
+
+ /// <summary>
+ /// Writes a single byte to an unmanaged stream.
+ /// </summary>
+ protected unsafe int WriteByte(FreeImageIO io, fi_handle handle, byte value)
+ {
+ return (int)io.writeProc(new IntPtr(&value), 1, 1, handle);
+ }
+
+ /// <summary>
+ /// Seeks in an unmanaged stream.
+ /// </summary>
+ protected int Seek(FreeImageIO io, fi_handle handle, int offset, SeekOrigin origin)
+ {
+ return io.seekProc(handle, offset, origin);
+ }
+
+ /// <summary>
+ /// Retrieves the position of an unmanaged stream.
+ /// </summary>
+ protected int Tell(FreeImageIO io, fi_handle handle)
+ {
+ return io.tellProc(handle);
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Represents unmanaged memory, containing an array of a given structure.
+ /// </summary>
+ /// <typeparam name="T">Structuretype represented by the instance.</typeparam>
+ /// <remarks>
+ /// <see cref="System.Boolean"/> and <see cref="System.Char"/> can not be marshalled.
+ /// <para/>
+ /// Use <see cref="System.Int32"/> instead of <see cref="System.Boolean"/> and
+ /// <see cref="System.Byte"/> instead of <see cref="System.Char"/>.
+ /// </remarks>
+ public unsafe class MemoryArray<T> : IDisposable, ICloneable, ICollection, IEnumerable<T>, IEquatable<MemoryArray<T>> where T : struct
+ {
+ /// <summary>
+ /// Baseaddress of the wrapped memory.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected byte* baseAddress;
+
+ /// <summary>
+ /// Number of elements being wrapped.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected int length;
+
+ /// <summary>
+ /// Size, in bytes, of each element.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly int size;
+
+ /// <summary>
+ /// Array of <b>T</b> containing a single element.
+ /// The array is used as a workaround, because there are no pointer for generic types.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected T[] buffer;
+
+ /// <summary>
+ /// Pointer to the element of <b>buffer</b>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected byte* ptr;
+
+ /// <summary>
+ /// Handle for pinning <b>buffer</b>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected GCHandle handle;
+
+ /// <summary>
+ /// Indicates whether the wrapped memory is handled like a bitfield.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool isOneBit;
+
+ /// <summary>
+ /// Indicates whther the wrapped memory is handles like 4-bit blocks.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly bool isFourBit;
+
+ /// <summary>
+ /// An object that can be used to synchronize access to the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected object syncRoot = null;
+
+ static MemoryArray()
+ {
+ T[] dummy = new T[2];
+ long marshalledSize = Marshal.SizeOf(typeof(T));
+ long structureSize =
+ Marshal.UnsafeAddrOfPinnedArrayElement(dummy, 1).ToInt64() -
+ Marshal.UnsafeAddrOfPinnedArrayElement(dummy, 0).ToInt64();
+ if (marshalledSize != structureSize)
+ {
+ throw new NotSupportedException(
+ "The desired type can not be handled, " +
+ "because its managed and unmanaged size in bytes are different.");
+ }
+
+ size = (int)marshalledSize;
+ }
+
+ /// <summary>
+ /// Initializes a new instance.
+ /// </summary>
+ protected MemoryArray()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryArray&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="baseAddress">Address of the memory block.</param>
+ /// <param name="length">Length of the array.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="baseAddress"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="length"/> is less or equal zero.</exception>
+ /// <exception cref="NotSupportedException">
+ /// The type is not supported.</exception>
+ public MemoryArray(IntPtr baseAddress, int length)
+ : this(baseAddress.ToPointer(), length)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MemoryArray&lt;T&gt;"/> class.
+ /// </summary>
+ /// <param name="baseAddress">Address of the memory block.</param>
+ /// <param name="length">Length of the array.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="baseAddress"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="length"/> is less or equal zero.</exception>
+ /// <exception cref="NotSupportedException">
+ /// The type is not supported.</exception>
+ public MemoryArray(void* baseAddress, int length)
+ {
+ if (typeof(T) == typeof(FI1BIT))
+ {
+ isOneBit = true;
+ }
+ else if (typeof(T) == typeof(FI4BIT))
+ {
+ isFourBit = true;
+ }
+
+ if (baseAddress == null)
+ {
+ throw new ArgumentNullException("baseAddress");
+ }
+ if (length < 1)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ this.baseAddress = (byte*)baseAddress;
+ this.length = (int)length;
+
+ if (!isOneBit && !isFourBit)
+ {
+ // Create an array containing a single element.
+ // Due to the fact, that it's not possible to create pointers
+ // of generic types, an array is used to obtain the memory
+ // address of an element of T.
+ this.buffer = new T[1];
+ // The array is pinned immediately to prevent the GC from
+ // moving it to a different position in memory.
+ this.handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ // The array and its content have beed pinned, so that its address
+ // can be safely requested and stored for the whole lifetime
+ // of the instace.
+ this.ptr = (byte*)handle.AddrOfPinnedObject();
+ }
+ }
+
+ /// <summary>
+ /// Frees the allocated <see cref="System.Runtime.InteropServices.GCHandle"/>.
+ /// </summary>
+ ~MemoryArray()
+ {
+ Dispose(false);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="MemoryArray&lt;T&gt;"/> structures are equivalent.
+ /// </summary>
+ /// <param name="left">The <see cref="MemoryArray&lt;T&gt;"/> that is to the left of the equality operator.</param>
+ /// <param name="right">The <see cref="MemoryArray&lt;T&gt;"/> that is to the right of the equality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="MemoryArray&lt;T&gt;"/> structures are equal; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(MemoryArray<T> left, MemoryArray<T> right)
+ {
+ if (object.ReferenceEquals(left, right))
+ {
+ return true;
+ }
+ if (object.ReferenceEquals(right, null) ||
+ object.ReferenceEquals(left, null) ||
+ (left.length != right.length))
+ {
+ return false;
+ }
+ if (left.baseAddress == right.baseAddress)
+ {
+ return true;
+ }
+ return FreeImage.CompareMemory(left.baseAddress, right.baseAddress, (uint)left.length);
+ }
+
+ /// <summary>
+ /// Tests whether two specified <see cref="MemoryArray&lt;T&gt;"/> structures are different.
+ /// </summary>
+ /// <param name="left">The <see cref="MemoryArray&lt;T&gt;"/> that is to the left of the inequality operator.</param>
+ /// <param name="right">The <see cref="MemoryArray&lt;T&gt;"/> that is to the right of the inequality operator.</param>
+ /// <returns>
+ /// <b>true</b> if the two <see cref="MemoryArray&lt;T&gt;"/> structures are different; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(MemoryArray<T> left, MemoryArray<T> right)
+ {
+ return (!(left == right));
+ }
+
+ /// <summary>
+ /// Gets the value at the specified position.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array element to get.</param>
+ /// <returns>The value at the specified position.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public T GetValue(int index)
+ {
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+
+ return GetValueInternal(index);
+ }
+
+ private T GetValueInternal(int index)
+ {
+ EnsureNotDisposed();
+ if (isOneBit)
+ {
+ return (T)(object)(FI1BIT)(((baseAddress[index / 8] & ((1 << (7 - (index % 8))))) == 0) ? 0 : 1);
+ }
+ else if (isFourBit)
+ {
+ return (T)(object)(FI4BIT)(((index % 2) == 0) ? (baseAddress[index / 2] >> 4) : (baseAddress[index / 2] & 0x0F));
+ }
+ else
+ {
+ CopyMemory(ptr, baseAddress + (index * size), size);
+ return buffer[0];
+ }
+ }
+
+ /// <summary>
+ /// Sets a value to the element at the specified position.
+ /// </summary>
+ /// <param name="value">The new value for the specified element.</param>
+ /// <param name="index">A 32-bit integer that represents the
+ /// position of the array element to set.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public void SetValue(T value, int index)
+ {
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ SetValueInternal(value, index);
+ }
+
+ private void SetValueInternal(T value, int index)
+ {
+ EnsureNotDisposed();
+ if (isOneBit)
+ {
+ if ((FI1BIT)(object)value != 0)
+ {
+ baseAddress[index / 8] |= (byte)(1 << (7 - (index % 8)));
+ }
+ else
+ {
+ baseAddress[index / 8] &= (byte)(~(1 << (7 - (index % 8))));
+ }
+ }
+ else if (isFourBit)
+ {
+ if ((index % 2) == 0)
+ {
+ baseAddress[index / 2] = (byte)((baseAddress[index / 2] & 0x0F) | ((FI4BIT)(object)value << 4));
+ }
+ else
+ {
+ baseAddress[index / 2] = (byte)((baseAddress[index / 2] & 0xF0) | ((FI4BIT)(object)value & 0x0F));
+ }
+ }
+ else
+ {
+ buffer[0] = value;
+ CopyMemory(baseAddress + (index * size), ptr, size);
+ }
+ }
+
+ /// <summary>
+ /// Gets the values at the specified position and length.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array elements to get.</param>
+ /// <param name="length"> A 32-bit integer that represents the length
+ /// of the array elements to get.</param>
+ /// <returns>The values at the specified position and length.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array.</exception>
+ public T[] GetValues(int index, int length)
+ {
+ EnsureNotDisposed();
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ if (((index + length) > this.length) || (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ T[] data = new T[length];
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ data[i] = GetValueInternal(i);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
+ byte* dst = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
+ CopyMemory(dst, baseAddress + (size * index), size * length);
+ handle.Free();
+ }
+ return data;
+ }
+
+ /// <summary>
+ /// Sets the values at the specified position.
+ /// </summary>
+ /// <param name="values">An array containing the new values for the specified elements.</param>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array elements to set.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="values"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="values.Length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array.</exception>
+ public void SetValues(T[] values, int index)
+ {
+ EnsureNotDisposed();
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+ if ((index >= this.length) || (index < 0))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ if ((index + values.Length) > this.length)
+ {
+ throw new ArgumentOutOfRangeException("values.Length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != values.Length; )
+ {
+ SetValueInternal(values[i++], index++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(values, GCHandleType.Pinned);
+ byte* src = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(values, 0);
+ CopyMemory(baseAddress + (index * size), src, size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the entire array to a compatible one-dimensional <see cref="System.Array"/>,
+ /// starting at the specified index of the target array.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="System.Array"/> that is the destination
+ /// of the elements copied from <see cref="MemoryArray&lt;T&gt;"/>.
+ /// The <see cref="System.Array"/> must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/>
+ /// at which copying begins.</param>
+ public void CopyTo(Array array, int index)
+ {
+ EnsureNotDisposed();
+ if (!(array is T[]))
+ {
+ throw new InvalidCastException("array");
+ }
+ try
+ {
+ CopyTo((T[])array, 0, index, length);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw new ArgumentException(ex.Message, ex);
+ }
+ }
+
+ /// <summary>
+ /// Copies a range of elements from the unmanaged array starting at the specified
+ /// <typeparamref name="sourceIndex"/> and pastes them to <paramref name="array"/>
+ /// starting at the specified <paramref name="destinationIndex"/>.
+ /// The length and the indexes are specified as 32-bit integers.
+ /// </summary>
+ /// <param name="array">The array that receives the data.</param>
+ /// <param name="sourceIndex">A 32-bit integer that represents the index
+ /// in the unmanaged array at which copying begins.</param>
+ /// <param name="destinationIndex">A 32-bit integer that represents the index in
+ /// the destination array at which storing begins.</param>
+ /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sourceIndex"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array
+ /// <para>-or-</para>
+ /// <paramref name="destinationIndex"/> is outside the range of valid indexes
+ /// for the array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array.
+ /// </exception>
+ public void CopyTo(T[] array, int sourceIndex, int destinationIndex, int length)
+ {
+ EnsureNotDisposed();
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+ if ((sourceIndex >= this.length) || (sourceIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("sourceIndex");
+ }
+ if ((destinationIndex >= array.Length) || (destinationIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("destinationIndex");
+ }
+ if ((sourceIndex + length > this.length) ||
+ (destinationIndex + length > array.Length) ||
+ (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != length; i++)
+ {
+ array[destinationIndex++] = GetValueInternal(sourceIndex++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ byte* dst = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(array, destinationIndex);
+ CopyMemory(dst, baseAddress + (size * sourceIndex), size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies a range of elements from the array starting at the specified
+ /// <typeparamref name="sourceIndex"/> and pastes them to the unmanaged array
+ /// starting at the specified <paramref name="destinationIndex"/>.
+ /// The length and the indexes are specified as 32-bit integers.
+ /// </summary>
+ /// <param name="array">The array that holds the data.</param>
+ /// <param name="sourceIndex">A 32-bit integer that represents the index
+ /// in the array at which copying begins.</param>
+ /// <param name="destinationIndex">A 32-bit integer that represents the index in
+ /// the unmanaged array at which storing begins.</param>
+ /// <param name="length">A 32-bit integer that represents the number of elements to copy.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="array"/> is a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sourceIndex"/> is outside the range of valid indexes
+ /// for the array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the array
+ /// <para>-or-</para>
+ /// <paramref name="destinationIndex"/> is outside the range of valid indexes
+ /// for the unmanaged array or <paramref name="length"/> is greater than the number of elements
+ /// from <paramref name="index"/> to the end of the unmanaged array.
+ /// </exception>
+ public void CopyFrom(T[] array, int sourceIndex, int destinationIndex, int length)
+ {
+ EnsureNotDisposed();
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+ if ((destinationIndex >= this.length) || (destinationIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("destinationIndex");
+ }
+ if ((sourceIndex >= array.Length) || (sourceIndex < 0))
+ {
+ throw new ArgumentOutOfRangeException("sourceIndex");
+ }
+ if ((destinationIndex + length > this.length) ||
+ (sourceIndex + length > array.Length) ||
+ (length < 1))
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ if (isOneBit || isFourBit)
+ {
+ for (int i = 0; i != length; i++)
+ {
+ SetValueInternal(array[sourceIndex++], destinationIndex++);
+ }
+ }
+ else
+ {
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ byte* src = (byte*)Marshal.UnsafeAddrOfPinnedArrayElement(array, sourceIndex);
+ CopyMemory(baseAddress + (size * destinationIndex), src, size * length);
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Returns the represented block of memory as an array of <see cref="Byte"/>.
+ /// </summary>
+ /// <returns>The represented block of memory.</returns>
+ public byte[] ToByteArray()
+ {
+ EnsureNotDisposed();
+ byte[] result;
+ if (isOneBit)
+ {
+ result = new byte[(length + 7) / 8];
+ }
+ else if (isFourBit)
+ {
+ result = new byte[(length + 3) / 4];
+ }
+ else
+ {
+ result = new byte[size * length];
+ }
+ fixed (byte* dst = result)
+ {
+ CopyMemory(dst, baseAddress, result.Length);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Gets or sets the value at the specified position in the array.
+ /// </summary>
+ /// <param name="index">A 32-bit integer that represents the position
+ /// of the array element to get.</param>
+ /// <returns>The value at the specified position in the array.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is outside the range of valid indexes
+ /// for the unmanaged array.</exception>
+ public T this[int index]
+ {
+ get
+ {
+ return GetValue(index);
+ }
+ set
+ {
+ SetValue(value, index);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the values of the unmanaged array.
+ /// </summary>
+ public T[] Data
+ {
+ get
+ {
+ return GetValues(0, length);
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ if (value.Length != length)
+ {
+ throw new ArgumentOutOfRangeException("value.Lengt");
+ }
+ SetValues(value, 0);
+ }
+ }
+
+ /// <summary>
+ /// Gets the length of the unmanaged array.
+ /// </summary>
+ public int Length
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return length;
+ }
+ }
+
+ /// <summary>
+ /// Gets the base address of the represented memory block.
+ /// </summary>
+ public IntPtr BaseAddress
+ {
+ get
+ {
+ EnsureNotDisposed();
+ return new IntPtr(baseAddress);
+ }
+ }
+
+ /// <summary>
+ /// Creates a shallow copy of the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>A shallow copy of the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public object Clone()
+ {
+ EnsureNotDisposed();
+ return new MemoryArray<T>(baseAddress, length);
+ }
+
+ /// <summary>
+ /// Gets a 32-bit integer that represents the total number of elements
+ /// in the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ public int Count
+ {
+ get { EnsureNotDisposed(); return length; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="MemoryArray&lt;T&gt;"/>
+ /// is synchronized (thread safe).
+ /// </summary>
+ public bool IsSynchronized
+ {
+ get { EnsureNotDisposed(); return false; }
+ }
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ public object SyncRoot
+ {
+ get
+ {
+ EnsureNotDisposed();
+ if (syncRoot == null)
+ {
+ System.Threading.Interlocked.CompareExchange(ref syncRoot, new object(), null);
+ }
+ return syncRoot;
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// elements in this <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ EnsureNotDisposed();
+ T[] values = GetValues(0, length);
+ for (int i = 0; i != values.Length; i++)
+ {
+ yield return values[i];
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual
+ /// elements in this <see cref="MemoryArray&lt;T&gt;"/>.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator&lt;T&gt;"/> for the <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ IEnumerator<T> IEnumerable<T>.GetEnumerator()
+ {
+ EnsureNotDisposed();
+ T[] values = GetValues(0, length);
+ for (int i = 0; i != values.Length; i++)
+ {
+ yield return values[i];
+ }
+ }
+
+ /// <summary>
+ /// Releases all ressources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases allocated handles associated with this instance.
+ /// </summary>
+ /// <param name="disposing"><b>true</b> to release managed resources.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (baseAddress != null)
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ baseAddress = null;
+ buffer = null;
+ length = 0;
+ syncRoot = null;
+ }
+ }
+
+ /// <summary>
+ /// Throws an <see cref="ObjectDisposedException"/> if
+ /// this instance is disposed.
+ /// </summary>
+ protected virtual void EnsureNotDisposed()
+ {
+ if (baseAddress == null)
+ throw new ObjectDisposedException("This instance is disposed.");
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MemoryArray&lt;T&gt;"/> structure is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure.
+ /// </summary>
+ /// <param name="obj">The structure to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="MemoryArray&lt;T&gt;"/>
+ /// instance equivalent to this <see cref="MemoryArray&lt;T&gt;"/> structure; otherwise,
+ /// <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ EnsureNotDisposed();
+ return ((obj is MemoryArray<T>) && Equals((MemoryArray<T>)obj));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MemoryArray&lt;T&gt;"/> structure is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure.
+ /// </summary>
+ /// <param name="other">The structure to test.</param>
+ /// <returns><b>true</b> if <paramref name="other"/> is equivalent to this
+ /// <see cref="MemoryArray&lt;T&gt;"/> structure; otherwise,
+ /// <b>false</b>.</returns>
+ public bool Equals(MemoryArray<T> other)
+ {
+ EnsureNotDisposed();
+ return ((this.baseAddress == other.baseAddress) && (this.length == other.length));
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a particular type.
+ /// </summary>
+ /// <returns>A hash code for the current <see cref="MemoryArray&lt;T&gt;"/>.</returns>
+ public override int GetHashCode()
+ {
+ EnsureNotDisposed();
+ return (int)baseAddress ^ length;
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">Pointer to the starting address of the copy destination.</param>
+ /// <param name="src">Pointer to the starting address of the block of memory to be copied.</param>
+ /// <param name="len">Size of the block of memory to copy, in bytes.</param>
+ protected static unsafe void CopyMemory(byte* dest, byte* src, int len)
+ {
+ if (len >= 0x10)
+ {
+ do
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ *((int*)(dest + 8)) = *((int*)(src + 8));
+ *((int*)(dest + 12)) = *((int*)(src + 12));
+ dest += 0x10;
+ src += 0x10;
+ }
+ while ((len -= 0x10) >= 0x10);
+ }
+ if (len > 0)
+ {
+ if ((len & 8) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ dest += 8;
+ src += 8;
+ }
+ if ((len & 4) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ dest += 4;
+ src += 4;
+ }
+ if ((len & 2) != 0)
+ {
+ *((short*)dest) = *((short*)src);
+ dest += 2;
+ src += 2;
+ }
+ if ((len & 1) != 0)
+ {
+ *dest = *src;
+ }
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Base class that represents a collection of all tags contained in a metadata model.
+ /// </summary>
+ /// <remarks>
+ /// The <b>MetedataModel</b> class is an abstract base class, which is inherited by
+ /// several derived classes, one for each existing metadata model.
+ /// </remarks>
+ public abstract class MetadataModel : IEnumerable
+ {
+ /// <summary>
+ /// Handle to the encapsulated FreeImage-bitmap.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ protected readonly FIBITMAP dib;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ protected MetadataModel(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ this.dib = dib;
+ }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public abstract FREE_IMAGE_MDMODEL Model
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Adds new tag to the bitmap or updates its value in case it already exists.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="tag">The tag to add or update.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="tag"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The tags model differs from this instances model.</exception>
+ public bool AddTag(MetadataTag tag)
+ {
+ if (tag == null)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ if (tag.Model != Model)
+ {
+ throw new ArgumentException("tag.Model");
+ }
+ return tag.AddToImage(dib);
+ }
+
+ /// <summary>
+ /// Adds a list of tags to the bitmap or updates their values in case they already exist.
+ /// <see cref="FreeImageAPI.Metadata.MetadataTag.Key"/> will be used as key.
+ /// </summary>
+ /// <param name="list">A list of tags to add or update.</param>
+ /// <returns>Returns the number of successfully added tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="list"/> is null.</exception>
+ public int AddTag(IEnumerable<MetadataTag> list)
+ {
+ if (list == null)
+ {
+ throw new ArgumentNullException("list");
+ }
+ int count = 0;
+ foreach (MetadataTag tag in list)
+ {
+ if (tag.Model == Model && tag.AddToImage(dib))
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ /// <summary>
+ /// Removes the specified tag from the bitmap.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public bool RemoveTag(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ return FreeImage.SetMetadata(Model, dib, key, FITAG.Zero);
+ }
+
+ /// <summary>
+ /// Destroys the metadata model
+ /// which will remove all tags of this model from the bitmap.
+ /// </summary>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public bool DestoryModel()
+ {
+ return FreeImage.SetMetadata(Model, dib, null, FITAG.Zero);
+ }
+
+ /// <summary>
+ /// Returns the specified metadata tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The metadata tag.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public MetadataTag GetTag(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag;
+ return FreeImage.GetMetadata(Model, dib, key, out tag) ? tag : null;
+ }
+
+ /// <summary>
+ /// Returns whether the specified tag exists.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>True in case the tag exists, else false.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="key"/> is null.</exception>
+ public bool TagExists(string key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag;
+ return FreeImage.GetMetadata(Model, dib, key, out tag);
+ }
+
+ /// <summary>
+ /// Returns a list of all metadata tags this instance represents.
+ /// </summary>
+ public List<MetadataTag> List
+ {
+ get
+ {
+ List<MetadataTag> list = new List<MetadataTag>((int)FreeImage.GetMetadataCount(Model, dib));
+ MetadataTag tag;
+ FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ do
+ {
+ list.Add(tag);
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Returns the tag at the given index.
+ /// </summary>
+ /// <param name="index">Index of the tag to return.</param>
+ /// <returns>The tag at the given index.</returns>
+ protected MetadataTag GetTagFromIndex(int index)
+ {
+ if (index >= Count || index < 0)
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ MetadataTag tag;
+ int count = 0;
+ FIMETADATA mdHandle = FreeImage.FindFirstMetadata(Model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ try
+ {
+ do
+ {
+ if (count++ == index)
+ {
+ break;
+ }
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ }
+ finally
+ {
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ }
+ return tag;
+ }
+
+ /// <summary>
+ /// Returns the metadata tag at the given index. This operation is slow when accessing all tags.
+ /// </summary>
+ /// <param name="index">Index of the tag.</param>
+ /// <returns>The metadata tag.</returns>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="index"/> is greater or equal <b>Count</b>
+ /// or index is less than zero.</exception>
+ public MetadataTag this[int index]
+ {
+ get
+ {
+ return GetTagFromIndex(index);
+ }
+ }
+
+ /// <summary>
+ /// Retrieves an object that can iterate through the individual MetadataTags in this MetadataModel.
+ /// </summary>
+ /// <returns>An <see cref="IEnumerator"/> for the
+ /// <see cref="FreeImageAPI.Metadata.MetadataModel"/>.</returns>
+ public IEnumerator GetEnumerator()
+ {
+ return List.GetEnumerator();
+ }
+
+ /// <summary>
+ /// Returns the number of metadata tags this instance represents.
+ /// </summary>
+ public int Count
+ {
+ get { return (int)FreeImage.GetMetadataCount(Model, dib); }
+ }
+
+ /// <summary>
+ /// Returns whether this model exists in the bitmaps metadata structure.
+ /// </summary>
+ public bool Exists
+ {
+ get
+ {
+ return Count > 0;
+ }
+ }
+
+ /// <summary>
+ /// Searches for a pattern in each metadata tag and returns the result as a list.
+ /// </summary>
+ /// <param name="searchPattern">The regular expression to use for the search.</param>
+ /// <param name="flags">A bitfield that controls which fields should be searched in.</param>
+ /// <returns>A list containing all found metadata tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <typeparamref name="searchPattern"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <typeparamref name="searchPattern"/> is empty.</exception>
+ public List<MetadataTag> RegexSearch(string searchPattern, MD_SEARCH_FLAGS flags)
+ {
+ if (searchPattern == null)
+ {
+ throw new ArgumentNullException("searchString");
+ }
+ if (searchPattern.Length == 0)
+ {
+ throw new ArgumentException("searchString is empty");
+ }
+ List<MetadataTag> result = new List<MetadataTag>(Count);
+ Regex regex = new Regex(searchPattern);
+ List<MetadataTag> list = List;
+ foreach (MetadataTag tag in list)
+ {
+ if (((flags & MD_SEARCH_FLAGS.KEY) > 0) && regex.Match(tag.Key).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ if (((flags & MD_SEARCH_FLAGS.DESCRIPTION) > 0) && regex.Match(tag.Description).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ if (((flags & MD_SEARCH_FLAGS.TOSTRING) > 0) && regex.Match(tag.ToString()).Success)
+ {
+ result.Add(tag);
+ continue;
+ }
+ }
+ result.Capacity = result.Count;
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the value of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">Type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The value of the specified tag.</returns>
+ protected T? GetTagValue<T>(string key) where T : struct
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ if (tag != null)
+ {
+ T[] value = tag.Value as T[];
+ if ((value != null) && (value.Length != 0))
+ {
+ return value[0];
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns an array containing the data of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">The type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>An array containing the data of the specified tag.</returns>
+ protected T[] GetTagArray<T>(string key) where T : struct
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ return (tag == null) ? null : tag.Value as T[];
+ }
+
+ /// <summary>
+ /// Returns the string contained by the specified tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The string contained by the specified tag.</returns>
+ protected string GetTagText(string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ MetadataTag tag = GetTag(key);
+ return (tag == null) ? null : tag.Value as string;
+ }
+
+ /// <summary>
+ /// Returns an array containg the data of the specified tag
+ /// as unsigned 32bit integer.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>An array containg the data of the specified tag
+ /// as unsigned 32bit integer.</returns>
+ protected uint[] GetUInt32Array(string key)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ uint[] result = null;
+ MetadataTag tag = GetTag(key);
+ if (tag != null)
+ {
+ object value = tag.Value;
+ if (value != null)
+ {
+ if (value is ushort[])
+ {
+ ushort[] array = (ushort[])value;
+ result = new uint[array.Length];
+ for (int i = 0, j = array.Length; i < j; i++)
+ {
+ result[i] = (uint)array[i];
+ }
+ }
+ else if (value is uint[])
+ {
+ result = (uint[])value;
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the value of the tag as unsigned 32bit integer.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <returns>The value of the tag as unsigned 32bit integer.</returns>
+ protected uint? GetUInt32Value(string key)
+ {
+ uint[] value = GetUInt32Array(key);
+ return value == null ? default(uint?) : value[0];
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag.
+ /// </summary>
+ /// <typeparam name="T">The type of the tag's data.</typeparam>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValue<T>(string key, T? value) where T : struct
+ {
+ SetTagValue(key, value.HasValue ? new T[] { value.Value } : null);
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValue(string key, object value)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ if (value == null)
+ {
+ RemoveTag(key);
+ }
+ else
+ {
+ MetadataTag tag = GetTag(key);
+ if (tag == null)
+ {
+ tag = new MetadataTag(Model);
+ tag.Key = key;
+ tag.Value = value;
+ AddTag(tag);
+ }
+ else
+ {
+ tag.Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of the specified tag as undefined.
+ /// </summary>
+ /// <param name="key">The key of the tag.</param>
+ /// <param name="value">The new value of the specified tag or null.</param>
+ protected void SetTagValueUndefined(string key, byte[] value)
+ {
+ if (string.IsNullOrEmpty(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ if (value == null)
+ {
+ RemoveTag(key);
+ }
+ else
+ {
+ MetadataTag tag = GetTag(key);
+ if (tag == null)
+ {
+ tag = new MetadataTag(Model);
+ tag.Key = key;
+ tag.SetValue(value, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED);
+ AddTag(tag);
+ }
+ else
+ {
+ tag.Value = value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="DirectionReference"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="DirectionReference"/>.</param>
+ /// <returns>The equivalent <see cref="DirectionReference"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static DirectionReference? ToDirectionType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'T':
+ return DirectionReference.TrueDirection;
+ case 'M':
+ return DirectionReference.MagneticDirection;
+ default:
+ return DirectionReference.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="DirectionReference"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="DirectionReference"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="DirectionReference"/>.</returns>
+ protected static string ToString(DirectionReference? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case DirectionReference.TrueDirection:
+ return "T";
+ case DirectionReference.MagneticDirection:
+ return "M";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="VelocityUnit"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="VelocityUnit"/>.</param>
+ /// <returns>The equivalent <see cref="VelocityUnit"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static VelocityUnit? ToUnitType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'K':
+ return VelocityUnit.Kilometers;
+ case 'M':
+ return VelocityUnit.Miles;
+ case 'N':
+ return VelocityUnit.Knots;
+ default:
+ return VelocityUnit.Undefinied;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="VelocityUnit"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="VelocityUnit"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="VelocityUnit"/>.</returns>
+ protected static string ToString(VelocityUnit? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case VelocityUnit.Kilometers:
+ return "K";
+ case VelocityUnit.Miles:
+ return "M";
+ case VelocityUnit.Knots:
+ return "N";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="LongitudeType"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="LongitudeType"/>.</param>
+ /// <returns>The equivalent <see cref="LongitudeType"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static LongitudeType? ToLongitudeType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'E':
+ return LongitudeType.East;
+ case 'W':
+ return LongitudeType.West;
+ default:
+ return LongitudeType.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="LongitudeType"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="LongitudeType"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="LongitudeType"/>.</returns>
+ protected static string ToString(LongitudeType? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case LongitudeType.East:
+ return "E";
+ case LongitudeType.West:
+ return "W";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="LatitudeType"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="LatitudeType"/>.</param>
+ /// <returns>The equivalent <see cref="LatitudeType"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static LatitudeType? ToLatitudeType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ switch (s[0])
+ {
+ case 'N':
+ return LatitudeType.North;
+ case 'S':
+ return LatitudeType.South;
+ default:
+ return LatitudeType.Undefined;
+ }
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="LatitudeType"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="LatitudeType"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="LatitudeType"/>.</returns>
+ protected static string ToString(LatitudeType? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case LatitudeType.North:
+ return "N";
+ case LatitudeType.South:
+ return "S";
+ default:
+ return "\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="InteroperabilityMode"/> for the
+ /// specified <see cref="String"/>.
+ /// </summary>
+ /// <param name="s">The string containing the <see cref="InteroperabilityMode"/>.</param>
+ /// <returns>The equivalent <see cref="InteroperabilityMode"/> for the
+ /// specified <see cref="String"/>.</returns>
+ protected static InteroperabilityMode? ToInteroperabilityType(string s)
+ {
+ if (string.IsNullOrEmpty(s))
+ return null;
+ if (s.StartsWith("R98"))
+ return InteroperabilityMode.R98;
+ if (s.StartsWith("THM"))
+ return InteroperabilityMode.THM;
+ return InteroperabilityMode.Undefined;
+ }
+
+ /// <summary>
+ /// Returns the equivalent <see cref="String"/> for the
+ /// specified <see cref="InteroperabilityMode"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="InteroperabilityMode"/> to convert.</param>
+ /// <returns>The equivalent <see cref="String"/> for the
+ /// specified <see cref="InteroperabilityMode"/>.</returns>
+ protected static string ToString(InteroperabilityMode? type)
+ {
+ if (type.HasValue)
+ {
+ switch (type.Value)
+ {
+ case InteroperabilityMode.R98:
+ return "R98";
+ case InteroperabilityMode.THM:
+ return "THM";
+ default:
+ return "\0\0\0";
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Specified different unit types.
+ /// </summary>
+ public enum VelocityUnit
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefinied,
+
+ /// <summary>
+ /// Kilometers per hour.
+ /// </summary>
+ Kilometers,
+
+ /// <summary>
+ /// Miles per hour.
+ /// </summary>
+ Miles,
+
+ /// <summary>
+ /// Knots.
+ /// </summary>
+ Knots,
+ }
+
+ /// <summary>
+ /// Specifies different direction types.
+ /// </summary>
+ public enum DirectionReference
+ {
+ /// <summary>
+ /// No or unknown direction type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// True direction.
+ /// </summary>
+ TrueDirection,
+
+ /// <summary>
+ /// Magnatic direction.
+ /// </summary>
+ MagneticDirection,
+ }
+
+ /// <summary>
+ /// Specifies the type of a latitude value.
+ /// </summary>
+ public enum LatitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// North.
+ /// </summary>
+ North,
+
+ /// <summary>
+ /// South.
+ /// </summary>
+ South,
+ }
+
+ /// <summary>
+ /// Specifies the type of a longitude value.
+ /// </summary>
+ public enum LongitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// East.
+ /// </summary>
+ East,
+
+ /// <summary>
+ /// West.
+ /// </summary>
+ West,
+ }
+
+ /// <summary>
+ /// Specifies different altitude types.
+ /// </summary>
+ public enum AltitudeType
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// East.
+ /// </summary>
+ AboveSeaLevel,
+
+ /// <summary>
+ /// West.
+ /// </summary>
+ BelowSeaLevel,
+ }
+
+ /// <summary>
+ /// Specifies interoperability types.
+ /// </summary>
+ public enum InteroperabilityMode
+ {
+ /// <summary>
+ /// No or unknown type.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// Indicates a file conforming to R98 file specification of Recommended
+ /// Exif Interoperability Rules (ExifR98) or to DCF basic file stipulated
+ /// by Design Rule for Camera File System.
+ /// </summary>
+ R98,
+
+ /// <summary>
+ /// Indicates a file conforming to DCF thumbnail file stipulated by Design
+ /// rule for Camera File System.
+ /// </summary>
+ THM,
+ }
+
+ /// <summary>
+ /// Specifies orientation of images.
+ /// </summary>
+ public enum ExifImageOrientation : ushort
+ {
+ /// <summary>
+ /// Undefinied orientation.
+ /// </summary>
+ Undefined,
+
+ /// <summary>
+ /// TopLeft.
+ /// </summary>
+ TopLeft = 1,
+
+ /// <summary>
+ /// TopRight.
+ /// </summary>
+ TopRight,
+
+ /// <summary>
+ /// BottomRight.
+ /// </summary>
+ BottomRight,
+
+ /// <summary>
+ /// BottomLeft.
+ /// </summary>
+ BottomLeft,
+
+ /// <summary>
+ /// LeftTop.
+ /// </summary>
+ LeftTop,
+
+ /// <summary>
+ /// RightTop.
+ /// </summary>
+ RightTop,
+
+ /// <summary>
+ /// RightBottom.
+ /// </summary>
+ RightBottom,
+
+ /// <summary>
+ /// LeftBottom.
+ /// </summary>
+ LeftBottom,
+ }
+
+ /// <summary>
+ /// Converts the model of the MetadataModel object to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ return Model.ToString();
+ }
+ }
+}
+
+ #region Metadata Models
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_ANIMATION"/>.
+ /// </summary>
+ public class MDM_ANIMATION : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_ANIMATION(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_ANIMATION; }
+ }
+
+ /// <summary>
+ /// Gets or sets the width of the entire canvas area, that each page is displayed in.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LogicalWidth
+ {
+ get
+ {
+ return GetTagValue<ushort>("LogicalWidth");
+ }
+ set
+ {
+ SetTagValue("LogicalWidth", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the height of the entire canvas area, that each page is displayed in.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LogicalHeight
+ {
+ get
+ {
+ return GetTagValue<ushort>("LogicalHeight");
+ }
+ set
+ {
+ SetTagValue("LogicalHeight", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the global palette of the GIF image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public Palette GlobalPalette
+ {
+ get
+ {
+ MetadataTag mdtag = GetTag("GlobalPalette");
+ return (mdtag == null) ? null : new Palette(mdtag);
+ }
+ set
+ {
+ SetTagValue("GlobalPalette", (value != null) ? null : value.Data);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of replays for the animation.
+ /// Use 0 (zero) to specify an infinte number of replays.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? LoopCount
+ {
+ get
+ {
+ return GetTagValue<uint>("Loop");
+ }
+ set
+ {
+ SetTagValue("Loop", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the horizontal offset within the logical canvas area, this frame is to be displayed at.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FrameLeft
+ {
+ get
+ {
+ return GetTagValue<ushort>("FrameLeft");
+ }
+ set
+ {
+ SetTagValue("FrameLeft", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the vertical offset within the logical canvas area, this frame is to be displayed at.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FrameTop
+ {
+ get
+ {
+ return GetTagValue<ushort>("FrameTop");
+ }
+ set
+ {
+ SetTagValue("FrameTop", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a flag to supress saving the dib's attached palette
+ /// (making it use the global palette). The local palette is the palette used by a page.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? NoLocalPalette
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("NoLocalPalette");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("NoLocalPalette", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the image is interlaced.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? Interlaced
+ {
+ get
+ {
+ byte? useGlobalPalette = GetTagValue<byte>("Interlaced");
+ return useGlobalPalette.HasValue ? (useGlobalPalette.Value != 0) : default(bool?);
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ val = (byte)(value.Value ? 1 : 0);
+ }
+ SetTagValue("Interlaced", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the amout of time in milliseconds this frame is to be displayed.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? FrameTime
+ {
+ get
+ {
+ return GetTagValue<uint>("FrameTime");
+ }
+ set
+ {
+ SetTagValue("FrameTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets this frame's disposal method. Generally, this method defines, how to
+ /// remove or replace a frame when the next frame has to be drawn.<para/>
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DisposalMethodType? DisposalMethod
+ {
+ get
+ {
+ return GetTagValue<DisposalMethodType>("DisposalMethod");
+ }
+ set
+ {
+ SetTagValue("DisposalMethod", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_COMMENTS"/>.
+ /// </summary>
+ public class MDM_COMMENTS : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_COMMENTS(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_COMMENTS; }
+ }
+
+ /// <summary>
+ /// Gets or sets the comment of the image.
+ /// Supported formats are JPEG, PNG and GIF.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Comment
+ {
+ get
+ {
+ return GetTagText("Comment");
+ }
+ set
+ {
+ SetTagValue("Comment", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_CUSTOM"/>.
+ /// </summary>
+ public class MDM_CUSTOM : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_CUSTOM(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_CUSTOM; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF"/>.
+ /// </summary>
+ public class MDM_EXIF_EXIF : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_EXIF(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF; }
+ }
+
+ /// <summary>
+ /// Gets or sets the version of this standard supported.
+ /// Constant length or 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ExifVersion
+ {
+ get
+ {
+ return GetTagArray<byte>("ExifVersion");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("ExifVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Flashpix format version supported by a FPXR file.
+ /// Constant length or 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] FlashpixVersion
+ {
+ get
+ {
+ return GetTagArray<byte>("FlashpixVersion");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("FlashpixVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the color space information tag.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>sRGB (default)</description>
+ /// </item>
+ /// <item>
+ /// <term>0xFFFF</term>
+ /// <description>uncalibrated</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ColorSpace
+ {
+ get
+ {
+ return GetTagValue<ushort>("ColorSpace");
+ }
+ set
+ {
+ SetTagValue("ColorSpace", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the valid width of a compressed image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? PixelXDimension
+ {
+ get
+ {
+ return GetUInt32Value("PixelXDimension");
+ }
+ set
+ {
+ RemoveTag("PixelXDimension");
+ if (value.HasValue)
+ {
+ SetTagValue("PixelXDimension", value.Value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the valid height of a compressed image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? PixelYDimension
+ {
+ get
+ {
+ return GetUInt32Value("PixelYDimension");
+ }
+ set
+ {
+ RemoveTag("PixelYDimension");
+ if (value.HasValue)
+ {
+ SetTagValue("PixelYDimension", value.Value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets components configuration. See remarks for further information.
+ /// Constant length of 4.
+ /// </summary>
+ /// <remarks>
+ /// The channels of each component are arranged in order from the 1st component to the 4th.
+ /// For uncompressed data the data arrangement is given in the PhotometricInterpretation tag.
+ /// However, since PhotometricInterpretation can only express the order of Y,Cb and Cr,
+ /// this tag is provided for cases when compressed data uses components other than Y, Cb,
+ /// and Cr and to enable support of other sequences.<para/>
+ /// Default = 4 5 6 0 (if RGB uncompressed)<para/>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>does not exist</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>Y</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>Cb</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>Cr</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>R</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ComponentsConfiguration
+ {
+ get
+ {
+ return GetTagArray<byte>("ComponentsConfiguration");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValueUndefined("ComponentsConfiguration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets compression mode used for a compressed image is indicated
+ /// in unit bits per pixel.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? CompressedBitsPerPixel
+ {
+ get
+ {
+ return GetTagValue<FIURational>("CompressedBitsPerPixel");
+ }
+ set
+ {
+ SetTagValue("CompressedBitsPerPixel", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag for manufacturers of Exif writers to record any desired information.
+ /// The contents are up to the manufacturer, but this tag should not be used for any other
+ /// than its intended purpose.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] MakerNote
+ {
+ get
+ {
+ return GetTagArray<byte>("FlashpixVersion");
+ }
+ set
+ {
+ SetTagValueUndefined("FlashpixVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag for Exif users to write keywords or comments on the image besides
+ /// those in ImageDescription, and without the character code limitations of the ImageDescription tag.
+ /// Minimum length of 8. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The character code used in the UserComment tag is identified based on an ID code in a fixed 8-byte
+ /// area at the start of the tag data area. The unused portion of the area is padded with NULL.
+ /// The ID code for the UserComment area may be a Defined code such as JIS or ASCII, or may be Undefined.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] UserComment
+ {
+ get
+ {
+ return GetTagArray<byte>("UserComment");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 8, int.MaxValue);
+ SetTagValueUndefined("UserComment", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of an audio file related to the image data.
+ /// The format is 8.3.
+ /// Constant length of 12
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string RelatedSoundFile
+ {
+ get
+ {
+ string text = GetTagText("RelatedSoundFile");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ FreeImage.Resize(ref value, 12);
+ value += '\0';
+ }
+ SetTagValue("RelatedSoundFile", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time when the original image data was generated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeOriginal
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTimeOriginal");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTimeOriginal", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time when the image was stored as digital data.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeDigitized
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTimeDigitized");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTimeDigitized", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTime tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTime
+ {
+ get
+ {
+ string text = GetTagText("SubsecTime");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTimeOriginal tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTimeOriginal
+ {
+ get
+ {
+ string text = GetTagText("SubsecTimeOriginal");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTimeOriginal", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a tag used to record fractions of seconds for the DateTimeDigitized tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubsecTimeDigitized
+ {
+ get
+ {
+ string text = GetTagText("SubsecTimeDigitized");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SubsecTimeDigitized", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or the exposure time, given in seconds (sec).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ExposureTime
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ExposureTime");
+ }
+ set
+ {
+ SetTagValue("ExposureTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or the F number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FNumber
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FNumber");
+ }
+ set
+ {
+ SetTagValue("FNumber", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the class of the program used by the camera to set exposure when the
+ /// picture is taken.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>not defined</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>normal program</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>aperture priority</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>shutter priority</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>create program</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>action program</description>
+ /// </item>
+ /// <item>
+ /// <term>7</term>
+ /// <description>portrait mode</description>
+ /// </item>
+ /// <item>
+ /// <term>8</term>
+ /// <description>landscape mode</description>
+ /// </item>
+ /// <item>
+ /// <term>others</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ExposureProgram
+ {
+ get
+ {
+ return GetTagValue<ushort>("ExposureProgram");
+ }
+ set
+ {
+ SetTagValue("ExposureProgram", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the spectral sensitivity of each channel of the camera used.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SpectralSensitivity
+ {
+ get
+ {
+ string text = GetTagText("SpectralSensitivity");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("SpectralSensitivity", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the the ISO Speed and ISO Latitude of the camera or input device as
+ /// specified in ISO 12232.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] ISOSpeedRatings
+ {
+ get
+ {
+ return GetTagArray<ushort>("ISOSpeedRatings");
+ }
+ set
+ {
+ SetTagValue("ISOSpeedRatings", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the Opto-Electric Conversion Function (OECF) specified in ISO 14524.
+ /// OECF is the relationship between the camera optical input and the image values.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] OECF
+ {
+ get
+ {
+ return GetTagArray<byte>("OECF");
+ }
+ set
+ {
+ SetTagValueUndefined("OECF", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the shutter speed. The unit is the APEX (Additive System of Photographic Exposure).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? ShutterSpeedValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("ShutterSpeedValue");
+ }
+ set
+ {
+ SetTagValue("ShutterSpeedValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the lens aperture. The unit is the APEX value.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ApertureValue
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ApertureValue");
+ }
+ set
+ {
+ SetTagValue("ApertureValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of brightness. The unit is the APEX value.
+ /// Ordinarily it is given in the range of -99.99 to 99.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? BrightnessValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("BrightnessValue");
+ }
+ set
+ {
+ SetTagValue("BrightnessValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure bias. The unit is the APEX value.
+ /// Ordinarily it is given in the range of �99.99 to 99.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? ExposureBiasValue
+ {
+ get
+ {
+ return GetTagValue<FIRational>("ExposureBiasValue");
+ }
+ set
+ {
+ SetTagValue("ExposureBiasValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the smallest F number of the lens. The unit is the APEX value.
+ /// Ordinarily it is given in the range of 00.00 to 99.99,
+ /// but it is not limited to this range.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? MaxApertureValue
+ {
+ get
+ {
+ return GetTagValue<FIURational>("MaxApertureValue");
+ }
+ set
+ {
+ SetTagValue("MaxApertureValue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets distance to the subject, given in meters.
+ /// Note that if the numerator of the recorded value is FFFFFFFF, infinity shall be indicated;
+ /// and if the numerator is 0, distance unknown shall be indicated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? SubjectDistance
+ {
+ get
+ {
+ return GetTagValue<FIURational>("SubjectDistance");
+ }
+ set
+ {
+ SetTagValue("SubjectDistance", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the metering mode. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>average</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>center-weighted-average</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>spot</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>multi-spot</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>pattern</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>partial</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// <item>
+ /// <term>255</term>
+ /// <description>other</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? MeteringMode
+ {
+ get
+ {
+ return GetTagValue<ushort>("MeteringMode");
+ }
+ set
+ {
+ SetTagValue("MeteringMode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the kind of light source.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>daylight</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>fluorescent</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>tungsten</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>flash</description>
+ /// </item>
+ /// <item>
+ /// <term>9</term>
+ /// <description>fine weather</description>
+ /// </item>
+ /// <item>
+ /// <term>10</term>
+ /// <description>cloudy weather</description>
+ /// </item>
+ /// <item>
+ /// <term>11</term>
+ /// <description>shade</description>
+ /// </item>
+ /// <item>
+ /// <term>12</term>
+ /// <description>daylight fluorecent (D 5700 - 7100K)</description>
+ /// </item>
+ /// <item>
+ /// <term>13</term>
+ /// <description>day white fluorescent (N 4600 - 5400K)</description>
+ /// </item>
+ /// <item>
+ /// <term>14</term>
+ /// <description>cool white fluorescent (W 3900 - 4500K)</description>
+ /// </item>
+ /// <item>
+ /// <term>15</term>
+ /// <description>white fluorescent (WW 3200 - 3700K)</description>
+ /// </item>
+ /// <item>
+ /// <term>17</term>
+ /// <description>standard light A</description>
+ /// </item>
+ /// <item>
+ /// <term>18</term>
+ /// <description>standard light B</description>
+ /// </item>
+ /// <item>
+ /// <term>19</term>
+ /// <description>standard light C</description>
+ /// </item>
+ /// <item>
+ /// <term>20</term>
+ /// <description>D55</description>
+ /// </item>
+ /// <item>
+ /// <term>21</term>
+ /// <description>D65</description>
+ /// </item>
+ /// <item>
+ /// <term>22</term>
+ /// <description>D75</description>
+ /// </item>
+ /// <item>
+ /// <term>23</term>
+ /// <description>D50</description>
+ /// </item>
+ /// <item>
+ /// <term>24</term>
+ /// <description>ISO studio tungsten</description>
+ /// </item>
+ /// <item>
+ /// <term>255</term>
+ /// <description>other light source</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? LightSource
+ {
+ get
+ {
+ return GetTagValue<ushort>("LightSource");
+ }
+ set
+ {
+ SetTagValue("LightSource", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the status of flash when the image was shot.
+ /// Bit 0 indicates the flash firing status, bits 1 and 2 indicate the flash return
+ /// status, bits 3 and 4 indicate the flash mode, bit 5 indicates whether the flash
+ /// function is present, and bit 6 indicates "red eye" mode.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Flash
+ {
+ get
+ {
+ return GetTagValue<ushort>("Flash");
+ }
+ set
+ {
+ SetTagValue("Flash", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the location and area of the main subject in
+ /// the overall scene. Variable length between 2 and 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] SubjectArea
+ {
+ get
+ {
+ return GetTagArray<ushort>("SubjectArea");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2, 4);
+ SetTagValue("SubjectArea", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the actual focal length of the lens, in mm.
+ /// Conversion is not made to the focal length of a 35 mm film camera.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalLength
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalLength");
+ }
+ set
+ {
+ SetTagValue("FocalLength", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the strobe energy at the time the image is captured,
+ /// as measured in Beam Candle Power Seconds (BCPS).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FlashEnergy
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FlashEnergy");
+ }
+ set
+ {
+ SetTagValue("FlashEnergy", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the camera or input device spatial frequency table and SFR values
+ /// in the direction of image width, image height, and diagonal direction,
+ /// as specified in ISO 12233.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] SpatialFrequencyResponse
+ {
+ get
+ {
+ return GetTagArray<byte>("SpatialFrequencyResponse");
+ }
+ set
+ {
+ SetTagValueUndefined("SpatialFrequencyResponse", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels in the image width (X) direction per
+ /// FocalPlaneResolutionUnit on the camera focal plane.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalPlaneXResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalPlaneXResolution");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneXResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels in the image height (Y) direction per
+ /// FocalPlaneResolutionUnit on the camera focal plane.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? FocalPlaneYResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("FocalPlaneYResolution");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneYResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit for measuring FocalPlaneXResolution and FocalPlaneYResolution.
+ /// This value is the same as the ResolutionUnit.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FocalPlaneResolutionUnit
+ {
+ get
+ {
+ return GetTagValue<ushort>("FocalPlaneResolutionUnit");
+ }
+ set
+ {
+ SetTagValue("FocalPlaneResolutionUnit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the location of the main subject in the scene.
+ /// The value of this tag represents the pixel at the center of the main subject
+ /// relative to the left edge, prior to rotation processing as per the Rotation tag.
+ /// The first value indicates the X column number and second indicates the Y row number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SubjectLocation
+ {
+ get
+ {
+ return GetTagValue<ushort>("SubjectLocation");
+ }
+ set
+ {
+ SetTagValue("SubjectLocation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure index selected on the camera or input device at the
+ /// time the image was captured.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? ExposureIndex
+ {
+ get
+ {
+ return GetTagValue<FIURational>("ExposureIndex");
+ }
+ set
+ {
+ SetTagValue("ExposureIndex", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image sensor type on the camera or input device.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are defined:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>not defined</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>one-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>two-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>three-chip color area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>5</term>
+ /// <description>color sequential area sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>7</term>
+ /// <description>trilinear sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>8</term>
+ /// <description>color sequential linear sensor</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SensingMethod
+ {
+ get
+ {
+ return GetTagValue<ushort>("SensingMethod");
+ }
+ set
+ {
+ SetTagValue("SensingMethod", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image source. If a DSC recorded the image, this tag value of this
+ /// tag always be set to 3, indicating that the image was recorded on a DSC.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte? FileSource
+ {
+ get
+ {
+ return GetTagValue<byte>("FileSource");
+ }
+ set
+ {
+ SetTagValueUndefined("FileSource", value.HasValue ? new byte[] { value.Value } : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of scene. If a DSC recorded the image, this tag value shall
+ /// always be set to 1, indicating that the image was directly photographed.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte? SceneType
+ {
+ get
+ {
+ return GetTagValue<byte>("SceneType");
+ }
+ set
+ {
+ SetTagValueUndefined("SceneType", value.HasValue ? new byte[] { value.Value } : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the color filter array (CFA) geometric pattern of the image sensor
+ /// when a one-chip color area sensor is used. It does not apply to all sensing methods.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] CFAPattern
+ {
+ get
+ {
+ return GetTagArray<byte>("CFAPattern");
+ }
+ set
+ {
+ SetTagValueUndefined("CFAPattern", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the use of special processing on image data, such as rendering geared to output.
+ /// When special processing is performed, the reader is expected to disable or minimize any
+ /// further processing. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal process</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>custom process</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? CustomRendered
+ {
+ get
+ {
+ return GetTagValue<ushort>("CustomRendered");
+ }
+ set
+ {
+ SetTagValue("CustomRendered", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the exposure mode set when the image was shot.
+ /// In auto-bracketing mode, the camera shoots a series of frames of the same scene
+ /// at different exposure settings. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>auto exposure</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual exposure</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>auto bracket</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ExposureMode
+ {
+ get
+ {
+ return GetTagValue<ushort>("ExposureMode");
+ }
+ set
+ {
+ SetTagValue("ExposureMode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the white balance mode set when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>auto white balance</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>manual white balance</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? WhiteBalance
+ {
+ get
+ {
+ return GetTagValue<ushort>("WhiteBalance");
+ }
+ set
+ {
+ SetTagValue("WhiteBalance", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the digital zoom ratio when the image was shot.
+ /// If the numerator of the recorded value is 0, this indicates that digital zoom was not used.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? DigitalZoomRatio
+ {
+ get
+ {
+ return GetTagValue<FIURational>("DigitalZoomRatio");
+ }
+ set
+ {
+ SetTagValue("DigitalZoomRatio", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the equivalent focal length assuming a 35mm film camera, in mm.
+ /// A value of 0 means the focal length is unknown. Note that this tag differs
+ /// from the FocalLength tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? FocalLengthIn35mmFilm
+ {
+ get
+ {
+ return GetTagValue<ushort>("DigitalZoomRatio");
+ }
+ set
+ {
+ SetTagValue("DigitalZoomRatio", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the type of scene that was shot.
+ /// It can also be used to record the mode in which the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>standard</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>landscape</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>portrait</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>night scene</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SceneCaptureType
+ {
+ get
+ {
+ return GetTagValue<ushort>("SceneCaptureType");
+ }
+ set
+ {
+ SetTagValue("SceneCaptureType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the degree of overall image gain adjustment.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>none</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>low gain up</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>high gain up</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>low gain down</description>
+ /// </item>
+ /// <item>
+ /// <term>4</term>
+ /// <description>high gain down</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? GainControl
+ {
+ get
+ {
+ return GetTagValue<ushort>("GainControl");
+ }
+ set
+ {
+ SetTagValue("GainControl", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of contrast processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>soft</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>hard</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Contrast
+ {
+ get
+ {
+ return GetTagValue<ushort>("Contrast");
+ }
+ set
+ {
+ SetTagValue("Contrast", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of saturation processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>low saturation</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>high saturation</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Saturation
+ {
+ get
+ {
+ return GetTagValue<ushort>("Saturation");
+ }
+ set
+ {
+ SetTagValue("Saturation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of sharpness processing applied by the camera
+ /// when the image was shot.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>normal</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>soft</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>hard</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Sharpness
+ {
+ get
+ {
+ return GetTagValue<ushort>("Sharpness");
+ }
+ set
+ {
+ SetTagValue("Sharpness", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets information on the picture-taking conditions of a particular camera model.
+ /// The tag is used only to indicate the picture-taking conditions in the reader.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] DeviceSettingDescription
+ {
+ get
+ {
+ return GetTagArray<byte>("DeviceSettingDescription");
+ }
+ set
+ {
+ SetTagValueUndefined("DeviceSettingDescription", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the distance to the subject.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>0</term>
+ /// <description>unknown</description>
+ /// </item>
+ /// <item>
+ /// <term>1</term>
+ /// <description>macro</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>close view</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>distant view</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SubjectDistanceRange
+ {
+ get
+ {
+ return GetTagValue<ushort>("SubjectDistanceRange");
+ }
+ set
+ {
+ SetTagValue("SubjectDistanceRange", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets an identifier assigned uniquely to each image.
+ /// It is recorded as an ASCII string equivalent to hexadecimal notation and 128-bit fixed length.
+ /// Constant length of 32.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageUniqueID
+ {
+ get
+ {
+ string text = GetTagText("ImageUniqueID");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ FreeImage.Resize(ref value, 32);
+ value += '\0';
+ }
+ SetTagValue("ImageUniqueID", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_GPS"/>.
+ /// </summary>
+ public class MDM_EXIF_GPS : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_GPS(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_GPS; }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS version ID. Constant length of 4.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] VersionID
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSVersionID");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 4);
+ SetTagValue("GPSVersionID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the <see cref="Latitude"/>
+ /// is north or south latitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public LatitudeType? LatitudeDirection
+ {
+ get
+ {
+ return ToLatitudeType(GetTagText("GPSLatitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSLatitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the latitude of the image. The latitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="LatitudeDirection"/>
+ public FIURational[] Latitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSLatitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSLatitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether <see cref="Longitude"/>
+ /// is east or west longitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public LongitudeType? LongitudeDirection
+ {
+ get
+ {
+ return ToLongitudeType(GetTagText("GPSLongitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSLongitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the longitude of the image. The longitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="LongitudeDirection"/>
+ public FIURational[] Longitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSLongitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSLongitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether <see cref="Altitude"/> is sea level and the altitude
+ /// is above sea level. If the altitude is below sea level <see cref="Altitude"/> is
+ /// indicated as an absolute value.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public AltitudeType? AltitudeDirection
+ {
+ get
+ {
+ byte? flag = GetTagValue<byte>("GPSAltitudeRef");
+ if (flag.HasValue)
+ {
+ switch (flag.Value)
+ {
+ case 0:
+ return AltitudeType.AboveSeaLevel;
+ case 1:
+ return AltitudeType.BelowSeaLevel;
+ default:
+ return AltitudeType.Undefined;
+ }
+ }
+ return null;
+ }
+ set
+ {
+ byte? val = null;
+ if (value.HasValue)
+ {
+ switch (value.Value)
+ {
+ case AltitudeType.AboveSeaLevel:
+ val = 0;
+ break;
+
+ case AltitudeType.BelowSeaLevel:
+ val = 1;
+ break;
+
+ default:
+ val = 2;
+ break;
+ }
+ }
+ SetTagValue("GPSAltitudeRef", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the altitude based on the reference in <see cref="AltitudeDirection"/>.
+ /// Altitude is expressed as one rational value. The reference unit is meters.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? Altitude
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSAltitude");
+ }
+ set
+ {
+ SetTagValue("GPSAltitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the sign of the <see cref="SignedAltitude"/>.
+ /// </summary>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public int? AltitudeSign
+ {
+ get
+ {
+ AltitudeType? seaLevel = AltitudeDirection;
+ if (seaLevel.HasValue)
+ {
+ return (seaLevel.Value == AltitudeType.BelowSeaLevel) ? -1 : 1;
+ }
+ return null;
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ AltitudeDirection = value.Value >= 0 ? AltitudeType.AboveSeaLevel : AltitudeType.BelowSeaLevel;
+ }
+ else
+ {
+ AltitudeDirection = null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the signed altitude.
+ /// Altitude is expressed as one rational value. The reference unit is meters.
+ /// </summary>
+ /// <exception cref="OverflowException">
+ /// Altitude is too large to fit into a FIRational.
+ /// </exception>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIRational? SignedAltitude
+ {
+ get
+ {
+ FIRational? result = null;
+ FIURational? altitude = Altitude;
+ if (altitude.HasValue)
+ {
+ int sign = AltitudeSign ?? 1;
+ if (((int)altitude.Value.Numerator < 0) || ((int)altitude.Value.Denominator < 0))
+ throw new OverflowException();
+ result = new FIRational((int)altitude.Value.Numerator * sign, (int)altitude.Value.Denominator);
+ }
+ return result;
+ }
+ set
+ {
+ FIURational? val = null;
+ if (value.HasValue)
+ {
+ if (value.Value < 0)
+ {
+ AltitudeSign = -1;
+ value = -value.Value;
+ }
+ else
+ {
+ AltitudeSign = 1;
+ }
+ val = new FIURational((uint)value.Value.Numerator, (uint)value.Value.Denominator);
+ }
+ Altitude = val;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets or sets the time as UTC (Coordinated Universal Time). Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public TimeSpan? TimeStamp
+ {
+ get
+ {
+ FIURational[] stamp = GetTagArray<FIURational>("GPSTimeStamp");
+ if ((stamp == null) || stamp.Length != 3)
+ {
+ return null;
+ }
+ else
+ {
+ return new TimeSpan((int)stamp[0], (int)stamp[1], (int)stamp[2]);
+ }
+ }
+ set
+ {
+ FIURational[] stamp = null;
+ if (value.HasValue)
+ {
+ TimeSpan span = value.Value;
+ stamp = new FIURational[3];
+ stamp[0] = span.Hours;
+ stamp[1] = span.Minutes;
+ stamp[2] = span.Seconds;
+ }
+ SetTagValue("GPSTimeStamp", stamp);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS satellites used for measurements. This tag can be used to describe
+ /// the number of satellites, their ID number, angle of elevation, azimuth, SNR and other
+ /// information in ASCII notation. The format is not specified.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Satellites
+ {
+ get
+ {
+ string result = GetTagText("GPSSatellites");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("GPSTimeStamp", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the status of the GPS receiver when the image was recorded.
+ /// <b>true</b> indicates measurement was in progress;
+ /// <b>false</b> indicates measurement was Interoperability.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? Status
+ {
+ get
+ {
+ string text = GetTagText("GPSStatus");
+ return string.IsNullOrEmpty(text) ? default(bool?) : text[0] == 'A';
+ }
+ set
+ {
+ SetTagValue("GPSStatus", value.HasValue ? (value.Value ? "A\0" : "V\0") : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the GPS measurement mode.
+ /// <b>true</b> indicates three-dimensional measurement;
+ /// <b>false</b> indicated two-dimensional measurement was in progress.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? MeasureMode3D
+ {
+ get
+ {
+ string text = GetTagText("GPSMeasureMode");
+ return string.IsNullOrEmpty(text) ? default(bool?) : text[0] == '3';
+ }
+ set
+ {
+ SetTagValue("GPSMeasureMode", value.HasValue ? (value.Value ? "3\0" : "2\0") : null);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the GPS DOP (data degree of precision). An HDOP value is written during
+ /// two-dimensional measurement, and PDOP during three-dimensional measurement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? DOP
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSDOP");
+ }
+ set
+ {
+ SetTagValue("GPSDOP", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit used to express the GPS receiver <see cref="Speed"/> of movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Speed"/>
+ public VelocityUnit? SpeedUnit
+ {
+ get
+ {
+ return ToUnitType(GetTagText("GPSSpeedRef"));
+ }
+ set
+ {
+ SetTagValue("GPSSpeedRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the speed of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="SpeedUnit"/>
+ public FIURational? Speed
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSSpeed");
+ }
+ set
+ {
+ SetTagValue("GPSSpeed", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference for giving the direction of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Track"/>
+ public DirectionReference? TrackDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSTrackRef"));
+ }
+ set
+ {
+ SetTagValue("GPSTrackRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of GPS receiver movement.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="TrackDirectionReference"/>
+ public FIURational? Track
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSTrack");
+ }
+ set
+ {
+ SetTagValue("GPSTrack", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference for giving the direction of GPS receiver movement.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="ImageDirection"/>
+ public DirectionReference? ImageDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSImgDirectionRef"));
+ }
+ set
+ {
+ SetTagValue("GPSImgDirectionRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the direction of the image when it was captured.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="ImageDirectionReference"/>
+ public FIURational? ImageDirection
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSImgDirection");
+ }
+ set
+ {
+ SetTagValue("GPSImgDirection", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the geodetic survey data used by the GPS receiver. If the survey data
+ /// is restricted to Japan, the value of this tag is 'TOKYO' or 'WGS-84'.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string MapDatum
+ {
+ get
+ {
+ string result = GetTagText("GPSMapDatum");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ SetTagValue("GPSMapDatum", value + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the destination point
+ /// is north or south latitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Latitude"/>
+ public LatitudeType? DestinationLatitudeDirection
+ {
+ get
+ {
+ return ToLatitudeType(GetTagText("GPSDestLatitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestLatitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the latitude of the destination point. The latitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationLatitudeDirection"/>
+ public FIURational[] DestinationLatitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSDestLatitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSDestLatitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the destination point
+ /// is east or west longitude.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="Latitude"/>
+ public LongitudeType? DestinationLongitudeDirection
+ {
+ get
+ {
+ return ToLongitudeType(GetTagText("GPSDestLongitudeRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestLongitudeRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the longitude of the destination point. The longitude is expressed as three rational
+ /// values giving the degrees, minutes, and seconds, respectively. Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] DestinationLongitude
+ {
+ get
+ {
+ return GetTagArray<FIURational>("GPSDestLongitude");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("GPSDestLongitude", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference used for giving the bearing to the destination point.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationBearing"/>
+ public DirectionReference? DestinationDirectionReference
+ {
+ get
+ {
+ return ToDirectionType(GetTagText("GPSDestBearingRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestBearingRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the bearing to the destination point.
+ /// The range of values is from 0.00 to 359.99.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationDirectionReference"/>
+ public FIURational? DestinationBearing
+ {
+ get
+ {
+ return GetTagValue<FIURational>("GPSDestBearing");
+ }
+ set
+ {
+ SetTagValue("GPSDestBearing", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit used to express the distance to the destination point.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="DestinationBearing"/>
+ public VelocityUnit? DestinationUnit
+ {
+ get
+ {
+ return ToUnitType(GetTagText("GPSDestDistanceRef"));
+ }
+ set
+ {
+ SetTagValue("GPSDestDistanceRef", ToString(value) + '\0');
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a character string recording the name of the method used
+ /// for location finding. The first byte indicates the character code used,
+ /// and this is followed by the name of the method. Since the Type is not ASCII,
+ /// NULL termination is not necessary.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] ProcessingMethod
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSProcessingMethod");
+ }
+ set
+ {
+ SetTagValue("GPSProcessingMethod", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a character string recording the name of the GPS area.
+ /// The first byte indicates the character code used, and this is followed by
+ /// the name of the GPS area. Since the Type is not ASCII, NULL termination is
+ /// not necessary.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public byte[] AreaInformation
+ {
+ get
+ {
+ return GetTagArray<byte>("GPSAreaInformation");
+ }
+ set
+ {
+ SetTagValue("GPSAreaInformation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets date and time information relative to UTC (Coordinated Universal Time).
+ /// </summary>
+ /// <remarks>
+ /// This is a derived property. There is no metadata tag directly associated
+ /// with this property value.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTimeStamp
+ {
+ get
+ {
+ DateTime? date = DateStamp;
+ TimeSpan? time = TimeStamp;
+ if ((date == null) && (time == null))
+ {
+ return null;
+ }
+ else
+ {
+ if (date == null)
+ {
+ date = DateTime.MinValue;
+ }
+ if (time == null)
+ {
+ time = TimeSpan.MinValue;
+ }
+ return date.Value.Add(time.Value);
+ }
+ }
+ set
+ {
+ if (value.HasValue)
+ {
+ DateStamp = value.Value.Date;
+ TimeStamp = value.Value.TimeOfDay;
+ }
+ else
+ {
+ DateStamp = null;
+ TimeStamp = null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets date information relative to UTC (Coordinated Universal Time).
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateStamp
+ {
+ get
+ {
+ string stamp = GetTagText("GPSDateStamp");
+ if (stamp != null)
+ {
+ try
+ {
+ return DateTime.ParseExact(stamp, "yyyy:MM:dd\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return null;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("GPSDateStamp", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether differential correction was applied to
+ /// the GPS receiver.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public bool? IsDifferential
+ {
+ get
+ {
+ ushort? value = GetTagValue<ushort>("GPSDifferential");
+ return value.HasValue ? (value != 0) : (default(bool?));
+ }
+ set
+ {
+ SetTagValue("GPSDifferential", value.HasValue ? (object)(value.Value ? (ushort)1 : (ushort)0) : (null));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_INTEROP"/>.
+ /// </summary>
+ public class MDM_INTEROP : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_INTEROP(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_INTEROP; }
+ }
+
+ /// <summary>
+ /// Gets or sets the identification of the Interoperability rule.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public InteroperabilityMode? Identification
+ {
+ get
+ {
+ return ToInteroperabilityType(GetTagText("InteroperabilityIndex"));
+ }
+ set
+ {
+ SetTagValue("InteroperabilityIndex", ToString(value) + '\0');
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN"/>.
+ /// <para/>
+ /// <b>This class is obsolete. Use class <see cref="MDM_EXIF_MAIN"/> instead.</b>
+ /// </summary>
+ [Obsolete("To be removed in future releases. Use MDM_EXIF_MAIN instead.")]
+ public class MDM_MAIN : MDM_EXIF_MAIN
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_MAIN(FIBITMAP dib) : base(dib) { }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN"/>.
+ /// </summary>
+ public class MDM_EXIF_MAIN : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_EXIF_MAIN(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN; }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of columns of image data, equal to the number
+ /// of pixels per row. In JPEG compressed data a JPEG marker is used
+ /// instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? ImageWidth
+ {
+ get
+ {
+ return GetUInt32Value("ImageWidth");
+ }
+ set
+ {
+ RemoveTag("ImageWidth");
+ if (value.HasValue)
+ {
+ SetTagValue("ImageWidth", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of rows of image data. In JPEG compressed data a JPEG marker
+ /// is used instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? ImageHeight
+ {
+ get
+ {
+ return GetUInt32Value("ImageLength");
+ }
+ set
+ {
+ RemoveTag("ImageLength");
+ if (value.HasValue)
+ {
+ SetTagValue("ImageLength", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of bits per image component. In this standard
+ /// each component of the image is 8 bits, so the value for this tag is 8.
+ /// Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] BitsPerSample
+ {
+ get
+ {
+ return GetTagArray<ushort>("BitsPerSample");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("BitsPerSample", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets compression scheme used for the image data. When a primary image
+ /// is JPEG compressed, this designation is not necessary and is omitted.
+ /// When thumbnails use JPEG compression, this tag value is set to 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? Compression
+ {
+ get
+ {
+ return GetTagValue<ushort>("Compression");
+ }
+ set
+ {
+ SetTagValue("Compression", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets pixel composition. In JPEG compressed data a JPEG marker is
+ /// used instead of this tag. See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>2</term>
+ /// <description>RGB</description>
+ /// </item>
+ /// <item>
+ /// <term>6</term>
+ /// <description>YCbCr</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? PhotometricInterpretation
+ {
+ get
+ {
+ return GetTagValue<ushort>("PhotometricInterpretation");
+ }
+ set
+ {
+ SetTagValue("PhotometricInterpretation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the image orientation viewed in terms of rows and columns.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ExifImageOrientation? Orientation
+ {
+ get
+ {
+ return (ExifImageOrientation?)GetTagValue<ushort>("Orientation");
+ }
+ set
+ {
+ SetTagValue("Orientation", (ushort?)value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of components per pixel. Since this standard applies
+ /// to RGB and YCbCr images, the value set for this tag is 3. In JPEG compressed
+ /// data a JPEG marker is used instead of this tag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? SamplesPerPixel
+ {
+ get
+ {
+ return GetTagValue<ushort>("SamplesPerPixel");
+ }
+ set
+ {
+ SetTagValue("SamplesPerPixel", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value that indicates whether pixel components are recorded in
+ /// chunky or planar format. In JPEG compressed files a JPEG marker is used instead
+ /// of this tag. If this field does not exist, the TIFF default of 1 (chunky) is assumed.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>chunky format</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>planar format</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? PlanarConfiguration
+ {
+ get
+ {
+ return GetTagValue<ushort>("PlanarConfiguration");
+ }
+ set
+ {
+ SetTagValue("PlanarConfiguration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the sampling ratio of chrominance components in relation to
+ /// the luminance component. In JPEG compressed dat a JPEG marker is used
+ /// instead of this tag.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>[2,1]</term>
+ /// <description>YCbCr4:2:2</description>
+ /// </item>
+ /// <item>
+ /// <term>[2,2]</term>
+ /// <description>YCbCr4:2:0</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] YCbCrSubSampling
+ {
+ get
+ {
+ return GetTagArray<ushort>("YCbCrSubSampling");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2);
+ SetTagValue("YCbCrSubSampling", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets position of chrominance components in relation to the luminance component.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// This field is designated only for JPEG compressed data or uncompressed YCbCr data.
+ /// The TIFF default is 1 (centered); but when Y:Cb:Cr = 4:2:2 it is recommended in
+ /// this standard that 2 (co-sited) be used to record data, in order to improve the
+ /// image quality when viewed on TV systems.
+ /// <para/>
+ /// When this field does not exist, the reader shall assume the TIFF default.
+ /// In the case of Y:Cb:Cr = 4:2:0, the TIFF default (centered) is recommended.
+ /// If the reader does not have the capability of supporting both kinds of YCbCrPositioning,
+ /// it shall follow the TIFF default regardless of the value in this field.
+ /// It is preferable that readers be able to support both centered and co-sited positioning.
+ /// <para/>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>1</term>
+ /// <description>centered</description>
+ /// </item>
+ /// <item>
+ /// <term>2</term>
+ /// <description>co-sited</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>reserved</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? YCbCrPositioning
+ {
+ get
+ {
+ return GetTagValue<ushort>("YCbCrPositioning");
+ }
+ set
+ {
+ SetTagValue("YCbCrPositioning", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels per <see cref="ResolutionUnit"/>
+ /// in the <see cref="ImageWidth"/> direction. When the image resolution is unknown,
+ /// 72 [dpi] is designated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? XResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("XResolution");
+ }
+ set
+ {
+ SetTagValue("XResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of pixels per <see cref="ResolutionUnit"/>
+ /// in the <see cref="ImageHeight"/> direction. When the image resolution is unknown,
+ /// 72 [dpi] is designated.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational? YResolution
+ {
+ get
+ {
+ return GetTagValue<FIURational>("YResolution");
+ }
+ set
+ {
+ SetTagValue("YResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the unit for measuring <see cref="XResolution"/> and <see cref="YResolution"/>.
+ /// The same unit is used for both <see cref="XResolution"/> and <see cref="YResolution"/>.
+ /// If the image resolution in unknown, 2 (inches) is designated.
+ /// See remarks for further information.
+ /// </summary>
+ /// <remarks>
+ /// The following values are definied:<para/>
+ /// <list type="table">
+ /// <listheader>
+ /// <term>ID</term>
+ /// <description>Description</description>
+ /// </listheader>
+ /// <item>
+ /// <term>2</term>
+ /// <description>inches</description>
+ /// </item>
+ /// <item>
+ /// <term>3</term>
+ /// <description>YCbCr4:2:0</description>
+ /// </item>
+ /// <item>
+ /// <term>other</term>
+ /// <description>centimeters</description>
+ /// </item>
+ /// </list>
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort? ResolutionUnit
+ {
+ get
+ {
+ return GetTagValue<ushort>("ResolutionUnit");
+ }
+ set
+ {
+ SetTagValue("ResolutionUnit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the byte offset of that strip.
+ /// It is recommended that this be selected so the number of strip bytes
+ /// does not exceed 64 Kbytes.
+ /// With JPEG compressed data this designation is not needed and is omitted.
+ /// Constant length of <see cref="SamplesPerPixel"/> * StripsPerImage.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="RowsPerStrip"/>
+ /// <see cref="StripByteCounts"/>
+ public uint[] StripOffsets
+ {
+ get
+ {
+ return GetUInt32Array("StripOffsets");
+ }
+ set
+ {
+ RemoveTag("StripOffsets");
+ if (value != null)
+ {
+ SetTagValue("StripOffsets", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets number of rows per strip. This is the number of rows in the image of
+ /// one strip when an image is divided into strips. With JPEG compressed data this
+ /// designation is not needed and is omitted.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ /// <seealso cref="StripByteCounts"/>
+ public uint? RowsPerStrip
+ {
+ get
+ {
+ return GetUInt32Value("RowsPerStrip");
+ }
+ set
+ {
+ RemoveTag("RowsPerStrip");
+ if (value.HasValue)
+ {
+ SetTagValue("RowsPerStrip", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the total number of bytes in each strip.
+ /// With JPEG compressed data this designation is not needed and is omitted.
+ /// Constant length of <see cref="SamplesPerPixel"/> * StripsPerImage.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint[] StripByteCounts
+ {
+ get
+ {
+ return GetUInt32Array("StripByteCounts");
+ }
+ set
+ {
+ RemoveTag("StripByteCounts");
+ if (value != null)
+ {
+ SetTagValue("StripByteCounts", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the offset to the start byte (SOI) of JPEG compressed thumbnail data.
+ /// This is not used for primary image JPEG data.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPEGInterchangeFormat
+ {
+ get
+ {
+ return GetTagValue<uint>("JPEGInterchangeFormat");
+ }
+ set
+ {
+ SetTagValue("JPEGInterchangeFormat", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the number of bytes of JPEG compressed thumbnail data.
+ /// </summary>
+ /// <remarks>
+ /// This is not used for primary image JPEG data.
+ /// JPEG thumbnails are not divided but are recorded as a continuous
+ /// JPEG bitstream from SOI to EOI. APPn and COM markers should not be recorded.
+ /// Compressed thumbnails shall be recorded in no more than 64 Kbytes,
+ /// including all other data to be recorded in APP1.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPEGInterchangeFormatLength
+ {
+ get
+ {
+ return GetTagValue<uint>("JPEGInterchangeFormatLength");
+ }
+ set
+ {
+ SetTagValue("JPEGInterchangeFormatLength", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a transfer function for the image, described in tabular style.
+ /// Constant length of 3 * 256.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] TransferFunction
+ {
+ get
+ {
+ return GetTagArray<ushort>("TransferFunction");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3 * 256);
+ SetTagValue("TransferFunction", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the chromaticity of the white point of the image.
+ /// Constant length of 2.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] WhitePoint
+ {
+ get
+ {
+ return GetTagArray<FIURational>("WhitePoint");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 2);
+ SetTagValue("WhitePoint", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the chromaticity of the three primary colors of the image.
+ /// Constant length of 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] PrimaryChromaticities
+ {
+ get
+ {
+ return GetTagArray<FIURational>("PrimaryChromaticities");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 6);
+ SetTagValue("PrimaryChromaticities", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the matrix coefficients for transformation from RGB to YCbCr image data.
+ /// Constant length of 3.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] YCbCrCoefficients
+ {
+ get
+ {
+ return GetTagArray<FIURational>("YCbCrCoefficients");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 3);
+ SetTagValue("PrimaryChromaticities", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the reference black point value and reference white point value.
+ /// Constant length of 6.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public FIURational[] ReferenceBlackWhite
+ {
+ get
+ {
+ return GetTagArray<FIURational>("ReferenceBlackWhite");
+ }
+ set
+ {
+ FreeImage.Resize(ref value, 6);
+ SetTagValue("ReferenceBlackWhite", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the date and time of image creation.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public DateTime? DateTime
+ {
+ get
+ {
+ DateTime? result = null;
+ string text = GetTagText("DateTime");
+ if (text != null)
+ {
+ try
+ {
+ result = System.DateTime.ParseExact(text, "yyyy:MM:dd HH:mm:ss\0", null);
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value.HasValue)
+ {
+ try
+ {
+ val = value.Value.ToString("yyyy:MM:dd HH:mm:ss\0");
+ }
+ catch
+ {
+ }
+ }
+ SetTagValue("DateTime", val);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a string giving the title of the image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageDescription
+ {
+ get
+ {
+ string result = GetTagText("ImageDescription");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("ImageDescription", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the manufacturer of the recording equipment.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Make
+ {
+ get
+ {
+ string result = GetTagText("Make");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Make", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the model name or model number of the equipment.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EquipmentModel
+ {
+ get
+ {
+ string result = GetTagText("Model");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Model", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name and version of the software or firmware of the camera
+ /// or image input device used to generate the image.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Software
+ {
+ get
+ {
+ string result = GetTagText("Software");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Software", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the name of the camera owner, photographer or image creator.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Artist
+ {
+ get
+ {
+ string result = GetTagText("Artist");
+ if (!string.IsNullOrEmpty(result))
+ {
+ result = result.Substring(0, result.Length - 1);
+ }
+ return result;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("Artist", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the photographer and editor copyrights.
+ /// Constant length of 1-2.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string[] Copyright
+ {
+ get
+ {
+ string[] result = null;
+ string text = GetTagText("Copyright");
+ if (!string.IsNullOrEmpty(text))
+ {
+ result = text.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
+ }
+ return result;
+ }
+ set
+ {
+ string val = null;
+ if (value != null)
+ {
+ if (value.Length == 1)
+ {
+ if (value[0] != null)
+ {
+ val = value[0] + '\0';
+ }
+ }
+ else if (value.Length == 2)
+ {
+ if ((value[0] != null) && (value[1] != null))
+ {
+ val = value[0] + '\0' + value[1] + '\0';
+ }
+ }
+ }
+ SetTagValue("Copyright", val);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_EXIF_MAKERNOTE"/>.
+ /// </summary>
+ public class MDM_MAKERNOTE : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_MAKERNOTE(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_EXIF_MAKERNOTE; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_GEOTIFF"/>.
+ /// </summary>
+ public class MDM_GEOTIFF : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_GEOTIFF(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_GEOTIFF; }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoASCIIParamsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoASCIIParamsTag is used to store all of the <see cref="String"/> valued
+ /// GeoKeys, referenced by the <see cref="GeoKeyDirectory"/> property. Since keys
+ /// defined in the GeoKeyDirectoryTag use offsets into this tag, any special
+ /// comments may be placed at the beginning of this tag.
+ /// For the most part, the only keys that are <see cref="String"/> valued are
+ /// <i>Citation</i> keys, giving documentation and references for obscure
+ /// projections, datums, etc.
+ /// <para/>
+ /// Special handling is required for <see cref="String"/>-valued keys. While it
+ /// is true that TIFF 6.0 permits multiple NULL-delimited strings within a single
+ /// ASCII tag, the secondary strings might not appear in the output of naive
+ /// <i>tiffdump</i> programs. For this reason, the NULL delimiter of each ASCII key
+ /// value shall be converted to a "|" (pipe) character before being installed
+ /// back into the <see cref="String"/> holding tag, so that a dump of the tag
+ /// will look like this.
+ /// <para/>
+ /// AsciiTag="first_value|second_value|etc...last_value|"
+ /// <para/>
+ /// A baseline GeoTIFF-reader must check for and convert the final "|" pipe
+ /// character of a key back into a NULL before returning it to the client
+ /// software.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string GeoASCIIParams
+ {
+ get
+ {
+ string text = GetTagText("GeoASCIIParams");
+ if (!string.IsNullOrEmpty(text))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text;
+ }
+ set
+ {
+ if (value != null)
+ {
+ value += '\0';
+ }
+ SetTagValue("GeoASCIIParams", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoDoubleParamsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoDoubleParamsTag is used to store all of the <see cref="Double"/> valued
+ /// GeoKeys, referenced by the <see cref="GeoKeyDirectory"/> property. The meaning of
+ /// any value of this double array is determined from the GeoKeyDirectoryTag reference
+ /// pointing to it. <see cref="Single"/> values should first be converted to
+ /// <see cref="Double"/> and stored here.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] GeoDoubleParams
+ {
+ get
+ {
+ return GetTagArray<double>("GeoDoubleParams");
+ }
+ set
+ {
+ SetTagValue("GeoDoubleParams", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoKeyDirectoryTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoKeyDirectoryTag may be used to store the GeoKey Directory, which defines and
+ /// references the <i>GeoKeys</i>.
+ /// <para/>
+ /// The tag is an array of unsigned <see cref="UInt16"/> values, which are primarily
+ /// grouped into blocks of 4. The first 4 values are special, and contain GeoKey directory
+ /// header information. The header values consist of the following information, in order:
+ /// <para/>
+ /// Header={KeyDirectoryVersion, KeyRevision, MinorRevision, NumberOfKeys}
+ /// <para/>
+ /// where
+ /// <para/>
+ /// <i>KeyDirectoryVersion</i> indicates the current version of Key implementation, and will
+ /// only change if this Tag's Key structure is changed. (Similar to the TIFFVersion (42)).
+ /// The current DirectoryVersion number is 1. This value will most likely never change,
+ /// and may be used to ensure that this is a valid Key-implementation.
+ /// <para/>
+ /// <i>KeyRevision</i> indicates what revision of Key-Sets are used.
+ /// <para/>
+ /// <i>MinorRevision</i> indicates what set of Key-Codes are used. The complete revision number
+ /// is denoted &lt;KeyRevision&gt;.&lt;MinorRevision&gt;.
+ /// <para/>
+ /// <i>NumberOfKeys</i> indicates how many Keys are defined by the rest of this Tag.
+ /// <para/>
+ /// This header is immediately followed by a collection of &lt;NumberOfKeys&gt; KeyEntry
+ /// sets, each of which is also 4-<see cref="UInt16"/> long. Each KeyEntry is modeled on the
+ /// <i>TIFFEntry</i> format of the TIFF directory header, and is of the form:
+ /// <para/>
+ /// KeyEntry = { KeyID, TIFFTagLocation, Count, Value_Offset }
+ /// <para/>
+ /// where
+ /// <para/>
+ /// <i>KeyID</i> gives the Key-ID value of the Key (identical in function to TIFF tag ID,
+ /// but completely independent of TIFF tag-space),
+ /// <para/>
+ /// <i>TIFFTagLocation</i> indicates which TIFF tag contains the value(s) of the Key: if
+ /// TIFFTagLocation is 0, then the value is <see cref="UInt16"/>, and is contained in the
+ /// <i>Value_Offset</i> entry. Otherwise, the type (format) of the value is implied by the
+ /// TIFF-Type of the tag containing the value.
+ /// <para/>
+ /// <i>Count</i> indicates the number of values in this key.
+ /// <para/>
+ /// <i>Value_Offset</i> Value_Offset indicates the index-offset into the TagArray indicated
+ /// by TIFFTagLocation, if it is nonzero. If TIFFTagLocation is 0 (zero) , then Value_Offset
+ /// contains the actual (<see cref="UInt16"/>) value of the Key, and Count=1 is implied.
+ /// Note that the offset is not a byte-offset, but rather an index based on the natural data
+ /// type of the specified tag array.
+ /// <para/>
+ /// Following the KeyEntry definitions, the KeyDirectory tag may also contain additional
+ /// values. For example, if a key requires multiple <see cref="UInt16"/> values, they shall
+ /// be placed at the end of this tag, and the KeyEntry will set
+ /// TIFFTagLocation=GeoKeyDirectoryTag, with the Value_Offset pointing to the location of the
+ /// value(s).
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public ushort[] GeoKeyDirectory
+ {
+ get
+ {
+ return GetTagArray<ushort>("GeoKeyDirectory");
+ }
+ set
+ {
+ SetTagValue("GeoKeyDirectory", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF ModelPixelScaleTag.
+ /// </summary>
+ /// <remarks>
+ /// The ModelPixelScaleTag tag may be used to specify the size of raster pixel spacing
+ /// in the model space units, when the raster space can be embedded in the model space
+ /// coordinate system without rotation, and consists of the following 3 values:
+ /// <para/>
+ /// ModelPixelScaleTag = (ScaleX, ScaleY, ScaleZ)
+ /// <para/>
+ /// where <i>ScaleX</i> and <i>ScaleY</i> give the horizontal and vertical spacing of
+ /// raster pixels. The <i>ScaleZ</i> is primarily used to map the pixel value of a
+ /// digital elevation model into the correct Z-scale, and so for most other purposes
+ /// this value should be zero (since most model spaces are 2-D, with Z=0).
+ /// <para/>
+ /// A single tiepoint in the <see cref="ModelTiePoints"/> tag, together with this tag,
+ /// completely determine the relationship between raster and model space; thus they
+ /// comprise the two tags which Baseline GeoTIFF files most often will use to place a
+ /// raster image into a "standard position" in model space.
+ /// <para/>
+ /// Like the <see cref="ModelTiePoints"/> tag, this tag information is independent of the
+ /// XPosition, YPosition, Resolution and Orientation tags of the standard TIFF 6.0 spec.
+ /// However, simple reversals of orientation between raster and model space
+ /// (e.g. horizontal or vertical flips) may be indicated by reversal of sign in the
+ /// corresponding component of the ModelPixelScaleTag. GeoTIFF compliant readers must
+ /// honor this signreversal convention.
+ /// <para/>
+ /// This tag must not be used if the raster image requires rotation or shearing to place
+ /// it into the standard model space. In such cases the transformation shall be defined
+ /// with the more general <see cref="ModelTransformationMatrix"/>.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoPixelScale</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelPixelScale"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoPixelScale</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelPixelScale
+ {
+ get
+ {
+ return GetTagArray<double>("GeoPixelScale");
+ }
+ set
+ {
+ SetTagValue("GeoPixelScale", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF GeoTiePointsTag.
+ /// </summary>
+ /// <remarks>
+ /// The GeoTiePointsTag stores raster -> model tiepoint pairs in the order
+ /// <para/>
+ /// ModelTiePoints = (...,I,J,K, X,Y,Z...),
+ /// <para/>
+ /// where <i>(I,J,K)</i> is the point at location <i>(I,J)</i> in raster space with
+ /// pixel-value <i>K</i>, and <i>(X,Y,Z)</i> is a vector in model space. In most cases
+ /// the model space is only two-dimensional, in which case both K and Z should be set
+ /// to zero; this third dimension is provided in anticipation of future support for 3D
+ /// digital elevation models and vertical coordinate systems.
+ /// <para/>
+ /// A raster image may be georeferenced simply by specifying its location, size and
+ /// orientation in the model coordinate space M. This may be done by specifying the
+ /// location of three of the four bounding corner points. However, tiepoints are only
+ /// to be considered exact at the points specified; thus defining such a set of
+ /// bounding tiepoints does not imply that the model space locations of the interior
+ /// of the image may be exactly computed by a linear interpolation of these tiepoints.
+ /// <para/>
+ /// However, since the relationship between the Raster space and the model space will
+ /// often be an exact, affine transformation, this relationship can be defined using
+ /// one set of tiepoints and the <see cref="ModelPixelScale"/>, described below, which
+ /// gives the vertical and horizontal raster grid cell size, specified in model units.
+ /// <para/>
+ /// If possible, the first tiepoint placed in this tag shall be the one establishing
+ /// the location of the point (0,0) in raster space. However, if this is not possible
+ /// (for example, if (0,0) is goes to a part of model space in which the projection is
+ /// ill-defined), then there is no particular order in which the tiepoints need be
+ /// listed.
+ /// <para/>
+ /// For orthorectification or mosaicking applications a large number of tiepoints may
+ /// be specified on a mesh over the raster image. However, the definition of associated
+ /// grid interpolation methods is not in the scope of the current GeoTIFF spec.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoTiePoints</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelTiePoints"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoTiePoints</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelTiePoints
+ {
+ get
+ {
+ return GetTagArray<double>("GeoTiePoints");
+ }
+ set
+ {
+ SetTagValue("GeoTiePoints", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF ModelTransformationMatrixTag.
+ /// </summary>
+ /// <remarks>
+ /// This tag may be used to specify the transformation matrix between the raster space
+ /// (and its dependent pixel-value space) and the (possibly 3D) model space.
+ /// <para/>
+ /// <br/><b>Naming differences</b><para/>
+ /// In the native FreeImage library and thus, in the FreeImage API documentation, this
+ /// property's key is named <i>GeoTransformationMatrix</i>. Since the GeoTIFF specification
+ /// as well as Java's <c>EXIFTIFFTagSet</c> class call this tag
+ /// <see cref="ModelTransformationMatrix"/>, this property was renamed accordingly.
+ /// However, when accessing this property's tag by its <see cref="MetadataTag"/> object,
+ /// the native FreeImage tag key <i>GeoTransformationMatrix</i> must be used.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] ModelTransformationMatrix
+ {
+ get
+ {
+ return GetTagArray<double>("GeoTransformationMatrix");
+ }
+ set
+ {
+ SetTagValue("GeoTransformationMatrix", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF IntergraphTransformationMatrixTag.
+ /// </summary>
+ /// <remarks>
+ /// The IntergraphTransformationMatrixTag conflicts with an internal software implementation
+ /// at Intergraph, and so its use is no longer encouraged. A GeoTIFF reader should look first
+ /// for the new tag, and only if it is not found should it check for this older tag. If found,
+ /// it should only consider it to be contain valid GeoTIFF matrix information if the tag-count
+ /// is 16; the Intergraph version uses 17 values.
+ /// <para/>
+ /// <br/><b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public double[] IntergraphTransformationMatrix
+ {
+ get
+ {
+ return GetTagArray<double>("Intergraph TransformationMatrix");
+ }
+ set
+ {
+ SetTagValue("Intergraph TransformationMatrix", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the GeoTIFF JPLCartoIFDOffsetTag.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public uint? JPLCartoIFDOffset
+ {
+ get
+ {
+ return GetTagValue<uint>("JPL Carto IFD offset");
+ }
+ set
+ {
+ SetTagValue("JPL Carto IFD offset", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_IPTC"/>.
+ /// </summary>
+ public class MDM_IPTC : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_IPTC(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_IPTC; }
+ }
+
+ /// <summary>
+ /// Gets the Application Record Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public short? ApplicationRecordVersion
+ {
+ get
+ {
+ return GetTagValue<short>("ApplicationRecordVersion");
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Type Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectTypeReference
+ {
+ get
+ {
+ return GetTagText("ObjectTypeReference");
+ }
+ set
+ {
+ SetTagValue("ObjectTypeReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Attribute Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectAttributeReference
+ {
+ get
+ {
+ return GetTagText("ObjectAttributeReference");
+ }
+ set
+ {
+ SetTagValue("ObjectAttributeReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Name.
+ /// This is also referred to as Title.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectName
+ {
+ get
+ {
+ return GetTagText("ObjectName");
+ }
+ set
+ {
+ SetTagValue("ObjectName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Edit Status.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EditStatus
+ {
+ get
+ {
+ return GetTagText("EditStatus");
+ }
+ set
+ {
+ SetTagValue("EditStatus", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Editorial Update.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string EditorialUpdate
+ {
+ get
+ {
+ return GetTagText("EditorialUpdate");
+ }
+ set
+ {
+ SetTagValue("EditorialUpdate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Urgency.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Urgency
+ {
+ get
+ {
+ return GetTagText("Urgency");
+ }
+ set
+ {
+ SetTagValue("Urgency", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Subject Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubjectReference
+ {
+ get
+ {
+ return GetTagText("SubjectReference");
+ }
+ set
+ {
+ SetTagValue("SubjectReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Category.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Category
+ {
+ get
+ {
+ return GetTagText("Category");
+ }
+ set
+ {
+ SetTagValue("Category", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Supplemental Categories.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SupplementalCategories
+ {
+ get
+ {
+ return GetTagText("SupplementalCategories");
+ }
+ set
+ {
+ SetTagValue("SupplementalCategories", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Fixture Identifier.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string FixtureIdentifier
+ {
+ get
+ {
+ return GetTagText("FixtureIdentifier");
+ }
+ set
+ {
+ SetTagValue("FixtureIdentifier", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Keywords.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Keywords
+ {
+ get
+ {
+ return GetTagText("Keywords");
+ }
+ set
+ {
+ SetTagValue("Keywords", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Content Location Code.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ContentLocationCode
+ {
+ get
+ {
+ return GetTagText("ContentLocationCode");
+ }
+ set
+ {
+ SetTagValue("ContentLocationCode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Content Location Name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ContentLocationName
+ {
+ get
+ {
+ return GetTagText("ContentLocationName");
+ }
+ set
+ {
+ SetTagValue("ContentLocationName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Release Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReleaseDate
+ {
+ get
+ {
+ return GetTagText("ReleaseDate");
+ }
+ set
+ {
+ SetTagValue("ReleaseDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Release Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReleaseTime
+ {
+ get
+ {
+ return GetTagText("ReleaseTime");
+ }
+ set
+ {
+ SetTagValue("ReleaseTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Expiration Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExpirationDate
+ {
+ get
+ {
+ return GetTagText("ExpirationDate");
+ }
+ set
+ {
+ SetTagValue("ExpirationDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Expiration Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExpirationTime
+ {
+ get
+ {
+ return GetTagText("ExpirationTime");
+ }
+ set
+ {
+ SetTagValue("ExpirationTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Special Instructions.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SpecialInstructions
+ {
+ get
+ {
+ return GetTagText("SpecialInstructions");
+ }
+ set
+ {
+ SetTagValue("SpecialInstructions", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Action Advised.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ActionAdvised
+ {
+ get
+ {
+ return GetTagText("ActionAdvised");
+ }
+ set
+ {
+ SetTagValue("ActionAdvised", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Service.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceService
+ {
+ get
+ {
+ return GetTagText("ReferenceService");
+ }
+ set
+ {
+ SetTagValue("ReferenceService", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceDate
+ {
+ get
+ {
+ return GetTagText("ReferenceDate");
+ }
+ set
+ {
+ SetTagValue("ReferenceDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Reference Number.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ReferenceNumber
+ {
+ get
+ {
+ return GetTagText("ReferenceNumber");
+ }
+ set
+ {
+ SetTagValue("ReferenceNumber", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Date Created.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DateCreated
+ {
+ get
+ {
+ return GetTagText("DateCreated");
+ }
+ set
+ {
+ SetTagValue("DateCreated", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Time Created.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string TimeCreated
+ {
+ get
+ {
+ return GetTagText("TimeCreated");
+ }
+ set
+ {
+ SetTagValue("TimeCreated", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Digital Creation Date.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DigitalCreationDate
+ {
+ get
+ {
+ return GetTagText("DigitalCreationDate");
+ }
+ set
+ {
+ SetTagValue("DigitalCreationDate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Digital Creation Time.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DigitalCreationTime
+ {
+ get
+ {
+ return GetTagText("DigitalCreationTime");
+ }
+ set
+ {
+ SetTagValue("DigitalCreationTime", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Originating Program.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OriginatingProgram
+ {
+ get
+ {
+ return GetTagText("OriginatingProgram");
+ }
+ set
+ {
+ SetTagValue("OriginatingProgram", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Program Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ProgramVersion
+ {
+ get
+ {
+ return GetTagText("ProgramVersion");
+ }
+ set
+ {
+ SetTagValue("ProgramVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Cycle.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectCycle
+ {
+ get
+ {
+ return GetTagText("ObjectCycle");
+ }
+ set
+ {
+ SetTagValue("ObjectCycle", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag By Line.
+ /// This is the author's name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ByLine
+ {
+ get
+ {
+ return GetTagText("By-line");
+ }
+ set
+ {
+ SetTagValue("By-line", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag By Line Title.
+ /// This is the author's position.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ByLineTitle
+ {
+ get
+ {
+ return GetTagText("By-lineTitle");
+ }
+ set
+ {
+ SetTagValue("By-lineTitle", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag City.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string City
+ {
+ get
+ {
+ return GetTagText("City");
+ }
+ set
+ {
+ SetTagValue("City", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Sub Location.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SubLocation
+ {
+ get
+ {
+ return GetTagText("SubLocation");
+ }
+ set
+ {
+ SetTagValue("SubLocation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Province State.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ProvinceState
+ {
+ get
+ {
+ return GetTagText("ProvinceState");
+ }
+ set
+ {
+ SetTagValue("ProvinceState", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Country Primary Location Code.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CountryPrimaryLocationCode
+ {
+ get
+ {
+ return GetTagText("Country-PrimaryLocationCode");
+ }
+ set
+ {
+ SetTagValue("Country-PrimaryLocationCode", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Country Primary Location Name.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CountryPrimaryLocationName
+ {
+ get
+ {
+ return GetTagText("Country-PrimaryLocationName");
+ }
+ set
+ {
+ SetTagValue("Country-PrimaryLocationName", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Original Transmission Reference.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OriginalTransmissionReference
+ {
+ get
+ {
+ return GetTagText("OriginalTransmissionReference");
+ }
+ set
+ {
+ SetTagValue("OriginalTransmissionReference", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Headline.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Headline
+ {
+ get
+ {
+ return GetTagText("Headline");
+ }
+ set
+ {
+ SetTagValue("Headline", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Credit.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Credit
+ {
+ get
+ {
+ return GetTagText("Credit");
+ }
+ set
+ {
+ SetTagValue("Credit", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Source.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Source
+ {
+ get
+ {
+ return GetTagText("Source");
+ }
+ set
+ {
+ SetTagValue("Source", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Copyright Notice.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CopyrightNotice
+ {
+ get
+ {
+ return GetTagText("CopyrightNotice");
+ }
+ set
+ {
+ SetTagValue("CopyrightNotice", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Contact.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Contact
+ {
+ get
+ {
+ return GetTagText("Contact");
+ }
+ set
+ {
+ SetTagValue("Contact", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Caption Abstract.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string CaptionAbstract
+ {
+ get
+ {
+ return GetTagText("CaptionAbstract");
+ }
+ set
+ {
+ SetTagValue("CaptionAbstract", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Writer Editor.
+ /// This is also referred to as Caption Writer.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string WriterEditor
+ {
+ get
+ {
+ return GetTagText("WriterEditor");
+ }
+ set
+ {
+ SetTagValue("WriterEditor", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Rasterized Caption.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string RasterizedCaption
+ {
+ get
+ {
+ return GetTagText("RasterizedCaption");
+ }
+ set
+ {
+ SetTagValue("RasterizedCaption", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Image Type.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageType
+ {
+ get
+ {
+ return GetTagText("ImageType");
+ }
+ set
+ {
+ SetTagValue("ImageType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Image Orientation.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ImageOrientation
+ {
+ get
+ {
+ return GetTagText("ImageOrientation");
+ }
+ set
+ {
+ SetTagValue("ImageOrientation", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Language Identifier.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string LanguageIdentifier
+ {
+ get
+ {
+ return GetTagText("LanguageIdentifier");
+ }
+ set
+ {
+ SetTagValue("LanguageIdentifier", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Type.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioType
+ {
+ get
+ {
+ return GetTagText("AudioType");
+ }
+ set
+ {
+ SetTagValue("AudioType", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Sampling Rate.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioSamplingRate
+ {
+ get
+ {
+ return GetTagText("AudioSamplingRate");
+ }
+ set
+ {
+ SetTagValue("AudioSamplingRate", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Sampling Resolution.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioSamplingResolution
+ {
+ get
+ {
+ return GetTagText("AudioSamplingResolution");
+ }
+ set
+ {
+ SetTagValue("AudioSamplingResolution", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Duration.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioDuration
+ {
+ get
+ {
+ return GetTagText("AudioDuration");
+ }
+ set
+ {
+ SetTagValue("AudioDuration", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Audio Outcue.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string AudioOutcue
+ {
+ get
+ {
+ return GetTagText("AudioOutcue");
+ }
+ set
+ {
+ SetTagValue("AudioOutcue", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Job I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string JobID
+ {
+ get
+ {
+ return GetTagText("JobID");
+ }
+ set
+ {
+ SetTagValue("JobID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Master Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string MasterDocumentID
+ {
+ get
+ {
+ return GetTagText("MasterDocumentID");
+ }
+ set
+ {
+ SetTagValue("MasterDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Short Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ShortDocumentID
+ {
+ get
+ {
+ return GetTagText("ShortDocumentID");
+ }
+ set
+ {
+ SetTagValue("ShortDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Unique Document I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string UniqueDocumentID
+ {
+ get
+ {
+ return GetTagText("UniqueDocumentID");
+ }
+ set
+ {
+ SetTagValue("UniqueDocumentID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Owner I D.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string OwnerID
+ {
+ get
+ {
+ return GetTagText("OwnerID");
+ }
+ set
+ {
+ SetTagValue("OwnerID", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview File Format.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewFileFormat
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewFileFormat");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewFileFormat", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview File Version.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewFileVersion
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewFileVersion");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewFileVersion", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Object Preview Data.
+ /// This is also referred to as Audio Outcue.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ObjectPreviewData
+ {
+ get
+ {
+ return GetTagText("ObjectPreviewData");
+ }
+ set
+ {
+ SetTagValue("ObjectPreviewData", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Prefs.
+ /// This is also referred to as photo-mechanic preferences.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Prefs
+ {
+ get
+ {
+ return GetTagText("Prefs");
+ }
+ set
+ {
+ SetTagValue("Prefs", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Classify State.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ClassifyState
+ {
+ get
+ {
+ return GetTagText("ClassifyState");
+ }
+ set
+ {
+ SetTagValue("ClassifyState", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Similarity Index.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string SimilarityIndex
+ {
+ get
+ {
+ return GetTagText("SimilarityIndex");
+ }
+ set
+ {
+ SetTagValue("SimilarityIndex", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Document Notes.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DocumentNotes
+ {
+ get
+ {
+ return GetTagText("DocumentNotes");
+ }
+ set
+ {
+ SetTagValue("DocumentNotes", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Document History.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string DocumentHistory
+ {
+ get
+ {
+ return GetTagText("DocumentHistory");
+ }
+ set
+ {
+ SetTagValue("DocumentHistory", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the IPTC/NAA tag Exif Camera Info.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string ExifCameraInfo
+ {
+ get
+ {
+ return GetTagText("ExifCameraInfo");
+ }
+ set
+ {
+ SetTagValue("ExifCameraInfo", value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_NODATA"/>.
+ /// </summary>
+ public class MDM_NODATA : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_NODATA(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_NODATA; }
+ }
+ }
+
+ /// <summary>
+ /// Represents a collection of all tags contained in the metadata model
+ /// <see cref="FREE_IMAGE_MDMODEL.FIMD_XMP"/>.
+ /// </summary>
+ public class MDM_XMP : MetadataModel
+ {
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public MDM_XMP(FIBITMAP dib) : base(dib) { }
+
+ /// <summary>
+ /// Retrieves the datamodel that this instance represents.
+ /// </summary>
+ public override FREE_IMAGE_MDMODEL Model
+ {
+ get { return FREE_IMAGE_MDMODEL.FIMD_XMP; }
+ }
+
+ /// <summary>
+ /// Gets or sets the XMP XML content.
+ /// </summary>
+ /// <remarks>
+ /// <b>Handling of null values</b><para/>
+ /// A null value indicates, that the corresponding metadata tag is not
+ /// present in the metadata model.
+ /// Setting this property's value to a non-null reference creates the
+ /// metadata tag if necessary.
+ /// Setting this property's value to a null reference deletes the
+ /// metadata tag from the metadata model.
+ /// </remarks>
+ public string Xml
+ {
+ get
+ {
+ return GetTagText("XMLPacket");
+ }
+ set
+ {
+ SetTagValue("XMLPacket", value);
+ }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="XmlReader"/> initialized to read the XMP XML content.
+ /// Returns null, if the metadata tag <i>XMLPacket</i> is not present in
+ /// this model.
+ /// </summary>
+ public XmlReader XmlReader
+ {
+ get
+ {
+ string xmlString = Xml;
+ if (xmlString == null)
+ {
+ return null;
+ }
+ else
+ {
+ MemoryStream stream = new MemoryStream();
+ StreamWriter writer = new StreamWriter(stream);
+ writer.Write(xmlString);
+ return XmlReader.Create(stream);
+ }
+ }
+ }
+ }
+}
+
+ #endregion
+
+namespace FreeImageAPI.Metadata
+{
+ /// <summary>
+ /// Manages metadata objects and operations.
+ /// </summary>
+ public sealed class MetadataTag : IComparable, IComparable<MetadataTag>, ICloneable, IEquatable<MetadataTag>, IDisposable
+ {
+ /// <summary>
+ /// The encapsulated FreeImage-tag.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ internal FITAG tag;
+
+ /// <summary>
+ /// The metadata model of <see cref="tag"/>.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private FREE_IMAGE_MDMODEL model;
+
+ /// <summary>
+ /// Indicates whether this instance has already been disposed.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed = false;
+
+ /// <summary>
+ /// Indicates whether this instance was created by FreeImage or
+ /// by the user.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool selfCreated;
+
+ /// <summary>
+ /// List linking metadata-model and Type.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly Dictionary<FREE_IMAGE_MDTYPE, Type> idList;
+
+ /// <summary>
+ /// List linking Type and metadata-model.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly Dictionary<Type, FREE_IMAGE_MDTYPE> typeList;
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ private MetadataTag()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="model">The new model the tag should be of.</param>
+ public MetadataTag(FREE_IMAGE_MDMODEL model)
+ {
+ this.model = model;
+ tag = FreeImage.CreateTag();
+ selfCreated = true;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to represent.</param>
+ /// <param name="dib">The bitmap <paramref name="tag"/> was extracted from.</param>
+ public MetadataTag(FITAG tag, FIBITMAP dib)
+ {
+ if (tag.IsNull)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ this.tag = tag;
+ model = GetModel(dib, tag);
+ selfCreated = false;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of this class.
+ /// </summary>
+ /// <param name="tag">The <see cref="FITAG"/> to represent.</param>
+ /// <param name="model">The model of <paramref name="tag"/>.</param>
+ public MetadataTag(FITAG tag, FREE_IMAGE_MDMODEL model)
+ {
+ if (tag.IsNull)
+ {
+ throw new ArgumentNullException("tag");
+ }
+ this.tag = tag;
+ this.model = model;
+ selfCreated = false;
+
+ if (model == FREE_IMAGE_MDMODEL.FIMD_XMP)
+ {
+ Key = "XMLPacket";
+ }
+ }
+
+ static MetadataTag()
+ {
+ idList = new Dictionary<FREE_IMAGE_MDTYPE, Type>();
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_BYTE, typeof(byte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SHORT, typeof(ushort));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_LONG, typeof(uint));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_RATIONAL, typeof(FIURational));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SBYTE, typeof(sbyte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_UNDEFINED, typeof(byte));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SSHORT, typeof(short));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SLONG, typeof(int));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_SRATIONAL, typeof(FIRational));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_FLOAT, typeof(float));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_DOUBLE, typeof(double));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_IFD, typeof(uint));
+ idList.Add(FREE_IMAGE_MDTYPE.FIDT_PALETTE, typeof(RGBQUAD));
+
+ typeList = new Dictionary<Type, FREE_IMAGE_MDTYPE>();
+ typeList.Add(typeof(ushort), FREE_IMAGE_MDTYPE.FIDT_SHORT);
+ typeList.Add(typeof(ushort[]), FREE_IMAGE_MDTYPE.FIDT_SHORT);
+ typeList.Add(typeof(string), FREE_IMAGE_MDTYPE.FIDT_ASCII);
+ typeList.Add(typeof(uint), FREE_IMAGE_MDTYPE.FIDT_LONG);
+ typeList.Add(typeof(uint[]), FREE_IMAGE_MDTYPE.FIDT_LONG);
+ typeList.Add(typeof(FIURational), FREE_IMAGE_MDTYPE.FIDT_RATIONAL);
+ typeList.Add(typeof(FIURational[]), FREE_IMAGE_MDTYPE.FIDT_RATIONAL);
+ typeList.Add(typeof(sbyte), FREE_IMAGE_MDTYPE.FIDT_SBYTE);
+ typeList.Add(typeof(sbyte[]), FREE_IMAGE_MDTYPE.FIDT_SBYTE);
+ typeList.Add(typeof(byte), FREE_IMAGE_MDTYPE.FIDT_BYTE);
+ typeList.Add(typeof(byte[]), FREE_IMAGE_MDTYPE.FIDT_BYTE);
+ typeList.Add(typeof(short), FREE_IMAGE_MDTYPE.FIDT_SSHORT);
+ typeList.Add(typeof(short[]), FREE_IMAGE_MDTYPE.FIDT_SSHORT);
+ typeList.Add(typeof(int), FREE_IMAGE_MDTYPE.FIDT_SLONG);
+ typeList.Add(typeof(int[]), FREE_IMAGE_MDTYPE.FIDT_SLONG);
+ typeList.Add(typeof(FIRational), FREE_IMAGE_MDTYPE.FIDT_SRATIONAL);
+ typeList.Add(typeof(FIRational[]), FREE_IMAGE_MDTYPE.FIDT_SRATIONAL);
+ typeList.Add(typeof(float), FREE_IMAGE_MDTYPE.FIDT_FLOAT);
+ typeList.Add(typeof(float[]), FREE_IMAGE_MDTYPE.FIDT_FLOAT);
+ typeList.Add(typeof(double), FREE_IMAGE_MDTYPE.FIDT_DOUBLE);
+ typeList.Add(typeof(double[]), FREE_IMAGE_MDTYPE.FIDT_DOUBLE);
+ typeList.Add(typeof(RGBQUAD), FREE_IMAGE_MDTYPE.FIDT_PALETTE);
+ typeList.Add(typeof(RGBQUAD[]), FREE_IMAGE_MDTYPE.FIDT_PALETTE);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ ~MetadataTag()
+ {
+ Dispose();
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="MetadataTag"/> objects have the same value.
+ /// </summary>
+ /// <param name="left">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// <b>true</b> if the value of left is the same as the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator ==(MetadataTag left, MetadataTag right)
+ {
+ // Check whether both are null
+ if ((object)left == (object)right)
+ {
+ return true;
+ }
+ else if ((object)left == null || (object)right == null)
+ {
+ return false;
+ }
+ left.CheckDisposed();
+ right.CheckDisposed();
+ // Check all properties
+ if ((left.Key != right.Key) ||
+ (left.ID != right.ID) ||
+ (left.Description != right.Description) ||
+ (left.Count != right.Count) ||
+ (left.Length != right.Length) ||
+ (left.Model != right.Model) ||
+ (left.Type != right.Type))
+ {
+ return false;
+ }
+ if (left.Length == 0)
+ {
+ return true;
+ }
+ IntPtr ptr1 = FreeImage.GetTagValue(left.tag);
+ IntPtr ptr2 = FreeImage.GetTagValue(right.tag);
+ return FreeImage.CompareMemory(ptr1, ptr2, left.Length);
+ }
+
+ /// <summary>
+ /// Determines whether two specified <see cref="MetadataTag"/> objects have different values.
+ /// </summary>
+ /// <param name="left">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <param name="right">A <see cref="MetadataTag"/> or a null reference (<b>Nothing</b> in Visual Basic).</param>
+ /// <returns>
+ /// true if the value of left is different from the value of right; otherwise, <b>false</b>.
+ /// </returns>
+ public static bool operator !=(MetadataTag left, MetadataTag right)
+ {
+ return !(left == right);
+ }
+
+ /// <summary>
+ /// Extracts the value of a <see cref="MetadataTag"/> instance to a <see cref="FITAG"/> handle.
+ /// </summary>
+ /// <param name="value">A <see cref="MetadataTag"/> instance.</param>
+ /// <returns>A new instance of <see cref="FITAG"/> initialized to <paramref name="value"/>.</returns>
+ public static implicit operator FITAG(MetadataTag value)
+ {
+ return value.tag;
+ }
+
+ private static FREE_IMAGE_MDMODEL GetModel(FIBITMAP dib, FITAG tag)
+ {
+ FITAG value;
+ foreach (FREE_IMAGE_MDMODEL model in FreeImage.FREE_IMAGE_MDMODELS)
+ {
+ FIMETADATA mData = FreeImage.FindFirstMetadata(model, dib, out value);
+ if (mData.IsNull)
+ {
+ continue;
+ }
+ try
+ {
+ do
+ {
+ if (value == tag)
+ {
+ return model;
+ }
+ }
+ while (FreeImage.FindNextMetadata(mData, out value));
+ }
+ finally
+ {
+ if (!mData.IsNull)
+ {
+ FreeImage.FindCloseMetadata(mData);
+ }
+ }
+ }
+ throw new ArgumentException("'tag' is no metadata object of 'dib'");
+ }
+
+ /// <summary>
+ /// Gets the model of the metadata.
+ /// </summary>
+ public FREE_IMAGE_MDMODEL Model
+ {
+ get { CheckDisposed(); return model; }
+ }
+
+ /// <summary>
+ /// Gets or sets the key of the metadata.
+ /// </summary>
+ public string Key
+ {
+ get { CheckDisposed(); return FreeImage.GetTagKey(tag); }
+ set
+ {
+ CheckDisposed();
+ if ((model != FREE_IMAGE_MDMODEL.FIMD_XMP) || (value == "XMLPacket"))
+ {
+ FreeImage.SetTagKey(tag, value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the description of the metadata.
+ /// </summary>
+ public string Description
+ {
+ get { CheckDisposed(); return FreeImage.GetTagDescription(tag); }
+ set { CheckDisposed(); FreeImage.SetTagDescription(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets or sets the ID of the metadata.
+ /// </summary>
+ public ushort ID
+ {
+ get { CheckDisposed(); return FreeImage.GetTagID(tag); }
+ set { CheckDisposed(); FreeImage.SetTagID(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the type of the metadata.
+ /// </summary>
+ public FREE_IMAGE_MDTYPE Type
+ {
+ get { CheckDisposed(); return FreeImage.GetTagType(tag); }
+ internal set { FreeImage.SetTagType(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the number of elements the metadata object contains.
+ /// </summary>
+ public uint Count
+ {
+ get { CheckDisposed(); return FreeImage.GetTagCount(tag); }
+ private set { FreeImage.SetTagCount(tag, value); }
+ }
+
+ /// <summary>
+ /// Gets the length of the value in bytes.
+ /// </summary>
+ public uint Length
+ {
+ get { CheckDisposed(); return FreeImage.GetTagLength(tag); }
+ private set { FreeImage.SetTagLength(tag, value); }
+ }
+
+ private unsafe byte[] GetData()
+ {
+ uint length = Length;
+ byte[] value = new byte[length];
+ byte* ptr = (byte*)FreeImage.GetTagValue(tag);
+ for (int i = 0; i < length; i++)
+ {
+ value[i] = ptr[i];
+ }
+ return value;
+ }
+
+ /// <summary>
+ /// Gets or sets the value of the metadata.
+ /// </summary>
+ public object Value
+ {
+ get
+ {
+ unsafe
+ {
+ CheckDisposed();
+ int cnt = (int)Count;
+
+ if (Type == FREE_IMAGE_MDTYPE.FIDT_ASCII)
+ {
+ byte* value = (byte*)FreeImage.GetTagValue(tag);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < cnt; i++)
+ {
+ sb.Append(Convert.ToChar(value[i]));
+ }
+ return sb.ToString();
+ }
+ else if (Type == FREE_IMAGE_MDTYPE.FIDT_NOTYPE)
+ {
+ return null;
+ }
+
+ Array array = Array.CreateInstance(idList[Type], Count);
+ void* src = (void*)FreeImage.GetTagValue(tag);
+ FreeImage.CopyMemory(array, src, Length);
+ return array;
+ }
+ }
+ set
+ {
+ SetValue(value);
+ }
+ }
+
+ /// <summary>
+ /// Sets the value of the metadata.
+ /// <para> In case value is of byte or byte[] <see cref="FREE_IMAGE_MDTYPE.FIDT_UNDEFINED"/> is assumed.</para>
+ /// <para> In case value is of uint or uint[] <see cref="FREE_IMAGE_MDTYPE.FIDT_LONG"/> is assumed.</para>
+ /// </summary>
+ /// <param name="value">New data of the metadata.</param>
+ /// <returns>True on success, false on failure.</returns>
+ /// <exception cref="NotSupportedException">
+ /// The data format is not supported.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is null.</exception>
+ public bool SetValue(object value)
+ {
+ Type type = value.GetType();
+ if (!typeList.ContainsKey(type))
+ {
+ throw new NotSupportedException("The type of value is not supported");
+ }
+ return SetValue(value, typeList[type]);
+ }
+
+ /// <summary>
+ /// Sets the value of the metadata.
+ /// </summary>
+ /// <param name="value">New data of the metadata.</param>
+ /// <param name="type">Type of the data.</param>
+ /// <returns>True on success, false on failure.</returns>
+ /// <exception cref="NotSupportedException">
+ /// The data type is not supported.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="value"/> and <paramref name="type"/> to not fit.</exception>
+ public bool SetValue(object value, FREE_IMAGE_MDTYPE type)
+ {
+ CheckDisposed();
+ if ((!value.GetType().IsArray) && (!(value is string)))
+ {
+ Array array = Array.CreateInstance(value.GetType(), 1);
+ array.SetValue(value, 0);
+ return SetArrayValue(array, type);
+ }
+ return SetArrayValue(value, type);
+ }
+
+ /// <summary>
+ /// Sets the value of this tag to the value of <paramref name="value"/>
+ /// using the given type.
+ /// </summary>
+ /// <param name="value">New value of the tag.</param>
+ /// <param name="type">Data-type of the tag.</param>
+ /// <returns></returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="value"/> is a null reference.
+ /// </exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="type"/> is FIDT_ASCII and
+ /// <paramref name="value"/> is not String.
+ /// <paramref name="type"/> is not FIDT_ASCII and
+ /// <paramref name="value"/> is not Array.</exception>
+ /// <exception cref="NotSupportedException">
+ /// <paramref name="type"/> is FIDT_NOTYPE.</exception>
+ private unsafe bool SetArrayValue(object value, FREE_IMAGE_MDTYPE type)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ byte[] data = null;
+
+ if (type == FREE_IMAGE_MDTYPE.FIDT_ASCII)
+ {
+ string tempValue = value as string;
+ if (tempValue == null)
+ {
+ throw new ArgumentException("value");
+ }
+ Type = type;
+ Length = Count = (uint)tempValue.Length;
+ data = new byte[Length];
+
+ for (int i = 0; i < tempValue.Length; i++)
+ {
+ data[i] = (byte)tempValue[i];
+ }
+ }
+ else if (type == FREE_IMAGE_MDTYPE.FIDT_NOTYPE)
+ {
+ throw new NotSupportedException("type is not supported.");
+ }
+ else
+ {
+ Array array = value as Array;
+ if (array == null)
+ {
+ throw new ArgumentException("value");
+ }
+
+ if (array.Length != 0)
+ if (!CheckType(array.GetValue(0).GetType(), type))
+ throw new ArgumentException("The type of value is incorrect.");
+
+ Type = type;
+ Count = (uint)array.Length;
+ Length = (uint)(array.Length * Marshal.SizeOf(idList[type]));
+ data = new byte[Length];
+ FreeImage.CopyMemory(data, array, Length);
+ }
+
+ return FreeImage.SetTagValue(tag, data);
+ }
+
+ private static bool CheckType(Type dataType, FREE_IMAGE_MDTYPE type)
+ {
+ if (dataType != null)
+ switch (type)
+ {
+ case FREE_IMAGE_MDTYPE.FIDT_ASCII:
+ return dataType == typeof(string);
+ case FREE_IMAGE_MDTYPE.FIDT_BYTE:
+ return dataType == typeof(byte);
+ case FREE_IMAGE_MDTYPE.FIDT_DOUBLE:
+ return dataType == typeof(double);
+ case FREE_IMAGE_MDTYPE.FIDT_FLOAT:
+ return dataType == typeof(float);
+ case FREE_IMAGE_MDTYPE.FIDT_IFD:
+ return dataType == typeof(uint);
+ case FREE_IMAGE_MDTYPE.FIDT_LONG:
+ return dataType == typeof(uint);
+ case FREE_IMAGE_MDTYPE.FIDT_NOTYPE:
+ return false;
+ case FREE_IMAGE_MDTYPE.FIDT_PALETTE:
+ return dataType == typeof(RGBQUAD);
+ case FREE_IMAGE_MDTYPE.FIDT_RATIONAL:
+ return dataType == typeof(FIURational);
+ case FREE_IMAGE_MDTYPE.FIDT_SBYTE:
+ return dataType == typeof(sbyte);
+ case FREE_IMAGE_MDTYPE.FIDT_SHORT:
+ return dataType == typeof(ushort);
+ case FREE_IMAGE_MDTYPE.FIDT_SLONG:
+ return dataType == typeof(int);
+ case FREE_IMAGE_MDTYPE.FIDT_SRATIONAL:
+ return dataType == typeof(FIRational);
+ case FREE_IMAGE_MDTYPE.FIDT_SSHORT:
+ return dataType == typeof(short);
+ case FREE_IMAGE_MDTYPE.FIDT_UNDEFINED:
+ return dataType == typeof(byte);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Add this metadata to an image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>True on success, false on failure.</returns>
+ public bool AddToImage(FIBITMAP dib)
+ {
+ CheckDisposed();
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (Key == null)
+ {
+ throw new ArgumentNullException("Key");
+ }
+ if (!selfCreated)
+ {
+ tag = FreeImage.CloneTag(tag);
+ if (tag.IsNull)
+ {
+ throw new Exception("FreeImage.CloneTag() failed.");
+ }
+ selfCreated = true;
+ }
+ if (!FreeImage.SetMetadata(Model, dib, Key, tag))
+ {
+ return false;
+ }
+ FREE_IMAGE_MDMODEL _model = Model;
+ string _key = Key;
+ selfCreated = false;
+ FreeImage.DeleteTag(tag);
+ return FreeImage.GetMetadata(_model, dib, _key, out tag);
+ }
+
+ /// <summary>
+ /// Gets a .NET PropertyItem for this metadata tag.
+ /// </summary>
+ /// <returns>The .NET PropertyItem.</returns>
+ public unsafe System.Drawing.Imaging.PropertyItem GetPropertyItem()
+ {
+ System.Drawing.Imaging.PropertyItem item = FreeImage.CreatePropertyItem();
+ item.Id = ID;
+ item.Len = (int)Length;
+ item.Type = (short)Type;
+ FreeImage.CopyMemory(item.Value = new byte[item.Len], FreeImage.GetTagValue(tag), item.Len);
+ return item;
+ }
+
+ /// <summary>
+ /// Converts the value of the <see cref="MetadataTag"/> object
+ /// to its equivalent string representation.
+ /// </summary>
+ /// <returns>The string representation of the value of this instance.</returns>
+ public override string ToString()
+ {
+ CheckDisposed();
+ string fiString = FreeImage.TagToString(model, tag, 0);
+
+ if (String.IsNullOrEmpty(fiString))
+ {
+ return tag.ToString();
+ }
+ else
+ {
+ return fiString;
+ }
+ }
+
+ /// <summary>
+ /// Creates a deep copy of this <see cref="MetadataTag"/>.
+ /// </summary>
+ /// <returns>A deep copy of this <see cref="MetadataTag"/>.</returns>
+ public object Clone()
+ {
+ CheckDisposed();
+ MetadataTag clone = new MetadataTag();
+ clone.model = model;
+ clone.tag = FreeImage.CloneTag(tag);
+ clone.selfCreated = true;
+ return clone;
+ }
+
+ /// <summary>
+ /// Tests whether the specified object is a <see cref="MetadataTag"/> instance
+ /// and is equivalent to this <see cref="MetadataTag"/> instance.
+ /// </summary>
+ /// <param name="obj">The object to test.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> is a <see cref="MetadataTag"/> instance
+ /// equivalent to this <see cref="MetadataTag"/> instance; otherwise, <b>false</b>.</returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is MetadataTag) && (Equals((MetadataTag)obj)));
+ }
+
+ /// <summary>
+ /// Tests whether the specified <see cref="MetadataTag"/> instance is equivalent to this <see cref="MetadataTag"/> instance.
+ /// </summary>
+ /// <param name="other">A <see cref="MetadataTag"/> instance to compare to this instance.</param>
+ /// <returns><b>true</b> if <paramref name="obj"/> equivalent to this <see cref="MetadataTag"/> instance;
+ /// otherwise, <b>false</b>.</returns>
+ public bool Equals(MetadataTag other)
+ {
+ return (this == other);
+ }
+
+ /// <summary>
+ /// Returns a hash code for this <see cref="MetadataTag"/> structure.
+ /// </summary>
+ /// <returns>An integer value that specifies the hash code for this <see cref="MetadataTag"/>.</returns>
+ public override int GetHashCode()
+ {
+ return tag.GetHashCode();
+ }
+
+ /// <summary>
+ /// Compares this instance with a specified <see cref="Object"/>.
+ /// </summary>
+ /// <param name="obj">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer indicating the lexical relationship between the two comparands.</returns>
+ /// <exception cref="ArgumentException"><paramref name="obj"/> is not a <see cref="MetadataTag"/>.</exception>
+ public int CompareTo(object obj)
+ {
+ if (obj == null)
+ {
+ return 1;
+ }
+ if (!(obj is MetadataTag))
+ {
+ throw new ArgumentException("obj");
+ }
+ return CompareTo((MetadataTag)obj);
+ }
+
+ /// <summary>
+ /// Compares the current instance with another object of the same type.
+ /// </summary>
+ /// <param name="other">An object to compare with this instance.</param>
+ /// <returns>A 32-bit signed integer that indicates the relative order of the objects being compared.</returns>
+ public int CompareTo(MetadataTag other)
+ {
+ CheckDisposed();
+ other.CheckDisposed();
+ return tag.CompareTo(other.tag);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ public void Dispose()
+ {
+ if (!disposed)
+ {
+ disposed = true;
+ if (selfCreated)
+ {
+ FreeImage.DeleteTag(tag);
+ tag = FITAG.Zero;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this instance has already been disposed.
+ /// </summary>
+ public bool Disposed
+ {
+ get { return disposed; }
+ }
+
+ /// <summary>
+ /// Throwns an <see cref="ObjectDisposedException"/> in case
+ /// this instance has already been disposed.
+ /// </summary>
+ private void CheckDisposed()
+ {
+ if (disposed)
+ {
+ throw new ObjectDisposedException("The object has already been disposed.");
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Provides methods for working with the standard bitmap palette.
+ /// </summary>
+ public sealed class Palette : MemoryArray<RGBQUAD>
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private GCHandle paletteHandle;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private RGBQUAD[] array;
+
+ /// <summary>
+ /// Initializes a new instance for the given FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="dib"/> is not
+ /// <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/><para/>-or-<para/>
+ /// <paramref name="dib"/> has more than 8bpp.</exception>
+ public Palette(FIBITMAP dib)
+ : base(FreeImage.GetPalette(dib), (int)FreeImage.GetColorsUsed(dib))
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (FreeImage.GetImageType(dib) != FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ throw new ArgumentException("dib");
+ }
+ if (FreeImage.GetBPP(dib) > 8u)
+ {
+ throw new ArgumentException("dib");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given FITAG that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="tag">The tag containing the palette.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="tag"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="tag"/> is not
+ /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
+ public Palette(FITAG tag)
+ : base(FreeImage.GetTagValue(tag), (int)FreeImage.GetTagCount(tag))
+ {
+ if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
+ {
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given MetadataTag that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="tag">The tag containing the palette.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException"><paramref name="tag"/> is not
+ /// <see cref="FREE_IMAGE_MDTYPE.FIDT_PALETTE"/>.</exception>
+ public Palette(MetadataTag tag)
+ : base(FreeImage.GetTagValue(tag.tag), (int)tag.Count)
+ {
+ if (FreeImage.GetTagType(tag) != FREE_IMAGE_MDTYPE.FIDT_PALETTE)
+ {
+ throw new ArgumentException("tag");
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given array of <see cref="RGBQUAD"/> that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="palette">A RGBQUAD array containing the palette data to initialize this instance.</param>
+ public Palette(RGBQUAD[] palette)
+ {
+ unsafe
+ {
+ this.array = (RGBQUAD[])palette.Clone();
+ this.paletteHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
+
+ base.baseAddress = (byte*)this.paletteHandle.AddrOfPinnedObject();
+ base.length = (int)this.array.Length;
+
+ // Create an array containing a single element.
+ // Due to the fact, that it's not possible to create pointers
+ // of generic types, an array is used to obtain the memory
+ // address of an element of T.
+ base.buffer = new RGBQUAD[1];
+ // The array is pinned immediately to prevent the GC from
+ // moving it to a different position in memory.
+ base.handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ // The array and its content have beed pinned, so that its address
+ // can be safely requested and stored for the whole lifetime
+ // of the instace.
+ base.ptr = (byte*)base.handle.AddrOfPinnedObject();
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance for the given array of <see cref="Color"/> that contains
+ /// a palette.
+ /// </summary>
+ /// <param name="palette">A Color array containing the palette data to initialize this instance.</param>
+ public Palette(Color[] palette)
+ : this(RGBQUAD.ToRGBQUAD(palette))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance with the specified size.
+ /// </summary>
+ /// <param name="size">The size of the palette.</param>
+ public Palette(int size)
+ : this(new RGBQUAD[size])
+ {
+ }
+
+ /// <summary>
+ /// Gets or sets the palette through an array of <see cref="RGBQUAD"/>.
+ /// </summary>
+ public RGBQUAD[] AsArray
+ {
+ get
+ {
+ return Data;
+ }
+ set
+ {
+ Data = value;
+ }
+ }
+
+ /// <summary>
+ /// Get an array of <see cref="System.Drawing.Color"/> that the block of memory represents.
+ /// This property is used for internal palette operations.
+ /// </summary>
+ internal unsafe Color[] ColorData
+ {
+ get
+ {
+ EnsureNotDisposed();
+ Color[] data = new Color[length];
+ for (int i = 0; i < length; i++)
+ {
+ data[i] = Color.FromArgb((int)(((uint*)baseAddress)[i] | 0xFF000000));
+ }
+ return data;
+ }
+ }
+
+ /// <summary>
+ /// Returns the palette as an array of <see cref="RGBQUAD"/>.
+ /// </summary>
+ /// <returns>The palette as an array of <see cref="RGBQUAD"/>.</returns>
+ public RGBQUAD[] ToArray()
+ {
+ return Data;
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color)
+ {
+ Colorize(color, 0.5d);
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <param name="splitSize">The position of the color within the new palette.
+ /// 0 &lt; <paramref name="splitSize"/> &lt; 1.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color, double splitSize)
+ {
+ Colorize(color, (int)(length * splitSize));
+ }
+
+ /// <summary>
+ /// Creates a linear palette based on the provided <paramref name="color"/>.
+ /// </summary>
+ /// <param name="color">The <see cref="System.Drawing.Color"/> used to colorize the palette.</param>
+ /// <param name="splitSize">The position of the color within the new palette.
+ /// 0 &lt; <paramref name="splitSize"/> &lt; <see cref="MemoryArray&lt;T&gt;.Length"/>.</param>
+ /// <remarks>
+ /// Only call this method on linear palettes.
+ /// </remarks>
+ public void Colorize(Color color, int splitSize)
+ {
+ EnsureNotDisposed();
+ if (splitSize < 1 || splitSize >= length)
+ {
+ throw new ArgumentOutOfRangeException("splitSize");
+ }
+
+ RGBQUAD[] pal = new RGBQUAD[length];
+
+ double red = color.R;
+ double green = color.G;
+ double blue = color.B;
+
+ int i = 0;
+ double r, g, b;
+
+ r = red / splitSize;
+ g = green / splitSize;
+ b = blue / splitSize;
+
+ for (; i <= splitSize; i++)
+ {
+ pal[i].rgbRed = (byte)(i * r);
+ pal[i].rgbGreen = (byte)(i * g);
+ pal[i].rgbBlue = (byte)(i * b);
+ }
+
+ r = (255 - red) / (length - splitSize);
+ g = (255 - green) / (length - splitSize);
+ b = (255 - blue) / (length - splitSize);
+
+ for (; i < length; i++)
+ {
+ pal[i].rgbRed = (byte)(red + ((i - splitSize) * r));
+ pal[i].rgbGreen = (byte)(green + ((i - splitSize) * g));
+ pal[i].rgbBlue = (byte)(blue + ((i - splitSize) * b));
+ }
+
+ Data = pal;
+ }
+
+ /// <summary>
+ /// Creates a linear grayscale palette.
+ /// </summary>
+ public void CreateGrayscalePalette()
+ {
+ Colorize(Color.White, length - 1);
+ }
+
+ /// <summary>
+ /// Creates a linear grayscale palette.
+ /// </summary>
+ /// <param name="inverse"><b>true</b> to create an inverse grayscale palette.</param>
+ public void CreateGrayscalePalette(bool inverse)
+ {
+ Colorize(Color.White, inverse ? 0 : length - 1);
+ }
+
+ /// <summary>
+ /// Creates a linear palette with the specified <see cref="Color"/>.
+ /// </summary>
+ /// <remarks>
+ /// A linear grayscale palette contains all shades of colors from
+ /// black to white. This method creates a similar palette with the white
+ /// color being replaced by the specified color.
+ /// </remarks>
+ /// <param name="color">The <see cref="Color"/> used to create the palette.</param>
+ /// <param name="inverse"><b>true</b> to create an inverse palette.</param>
+ public void CreateGrayscalePalette(Color color, bool inverse)
+ {
+ Colorize(color, inverse ? 0 : length - 1);
+ }
+
+ /// <summary>
+ /// Reverses the palette.
+ /// </summary>
+ public void Reverse()
+ {
+ EnsureNotDisposed();
+ if (array != null)
+ {
+ Array.Reverse(array);
+ }
+ else
+ {
+ RGBQUAD[] localArray = Data;
+ Array.Reverse(localArray);
+ Data = localArray;
+ }
+ }
+
+ /// <summary>
+ /// Copies the values from the specified <see cref="Palette"/> to this instance.
+ /// </summary>
+ /// <param name="palette">The palette to copy from.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ public void CopyFrom(Palette palette)
+ {
+ EnsureNotDisposed();
+ if (palette == null)
+ {
+ throw new ArgumentNullException("palette");
+ }
+ CopyFrom(palette.Data, 0, 0, Math.Min(palette.Length, this.Length));
+ }
+
+ /// <summary>
+ /// Copies the values from the specified <see cref="Palette"/> to this instance,
+ /// starting at the specified <paramref name="offset"/>.
+ /// </summary>
+ /// <param name="palette">The palette to copy from.</param>
+ /// <param name="offset">The position in this instance where the values
+ /// will be copied to.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="palette"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="offset"/> is outside the range of valid indexes.</exception>
+ public void CopyFrom(Palette palette, int offset)
+ {
+ EnsureNotDisposed();
+ CopyFrom(palette.Data, 0, offset, Math.Min(palette.Length, this.Length - offset));
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> to the specified file.
+ /// </summary>
+ /// <param name="filename">
+ /// A string that contains the name of the file to which to save this <see cref="Palette"/>.
+ /// </param>
+ public void Save(string filename)
+ {
+ using (Stream stream = new FileStream(filename, FileMode.Create, FileAccess.Write))
+ {
+ Save(stream);
+ }
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> to the specified stream.
+ /// </summary>
+ /// <param name="stream">
+ /// The <see cref="Stream"/> where the image will be saved.
+ /// </param>
+ public void Save(Stream stream)
+ {
+ Save(new BinaryWriter(stream));
+ }
+
+ /// <summary>
+ /// Saves this <see cref="Palette"/> using the specified writer.
+ /// </summary>
+ /// <param name="writer">
+ /// The <see cref="BinaryWriter"/> used to save the image.
+ /// </param>
+ public void Save(BinaryWriter writer)
+ {
+ EnsureNotDisposed();
+ writer.Write(ToByteArray());
+ }
+
+ /// <summary>
+ /// Loads a palette from the specified file.
+ /// </summary>
+ /// <param name="filename">The name of the palette file.</param>
+ public void Load(string filename)
+ {
+ using (Stream stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
+ {
+ Load(stream);
+ }
+ }
+
+ /// <summary>
+ /// Loads a palette from the specified stream.
+ /// </summary>
+ /// <param name="stream">The stream to load the palette from.</param>
+ public void Load(Stream stream)
+ {
+ Load(new BinaryReader(stream));
+ }
+
+ /// <summary>
+ /// Loads a palette from the reader.
+ /// </summary>
+ /// <param name="reader">The reader to load the palette from.</param>
+ public void Load(BinaryReader reader)
+ {
+ EnsureNotDisposed();
+ unsafe
+ {
+ int size = length * sizeof(RGBQUAD);
+ byte[] data = reader.ReadBytes(size);
+ fixed (byte* src = data)
+ {
+ CopyMemory(baseAddress, src, data.Length);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Releases allocated handles associated with this instance.
+ /// </summary>
+ /// <param name="disposing"><b>true</b> to release managed resources.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (paletteHandle.IsAllocated)
+ paletteHandle.Free();
+ array = null;
+
+ base.Dispose(disposing);
+ }
+ }
+}
+
+namespace FreeImageAPI.Plugins
+{
+ /// <summary>
+ /// Class representing all registered <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> in FreeImage.
+ /// </summary>
+ public static class PluginRepository
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly List<FreeImagePlugin> plugins = null;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private static readonly List<FreeImagePlugin> localPlugins = null;
+
+ static PluginRepository()
+ {
+ plugins = new List<FreeImagePlugin>(FreeImage.GetFIFCount());
+ localPlugins = new List<FreeImagePlugin>(0);
+ for (int i = 0; i < plugins.Capacity; i++)
+ {
+ plugins.Add(new FreeImagePlugin((FREE_IMAGE_FORMAT)i));
+ }
+ }
+
+ /// <summary>
+ /// Adds local plugin to this class.
+ /// </summary>
+ /// <param name="localPlugin">The registered plugin.</param>
+ internal static void RegisterLocalPlugin(LocalPlugin localPlugin)
+ {
+ FreeImagePlugin plugin = new FreeImagePlugin(localPlugin.Format);
+ plugins.Add(plugin);
+ localPlugins.Add(plugin);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>, representing the given format.
+ /// </summary>
+ /// <param name="fif">The representing format.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(FREE_IMAGE_FORMAT fif)
+ {
+ return Plugin((int)fif);
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>,
+ /// representing the format at the given index.
+ /// </summary>
+ /// <param name="index">The index of the representing format.</param>
+ /// <returns>An instance of <see cref="FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(int index)
+ {
+ return (index >= 0) ? plugins[index] : null;
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.
+ /// <typeparamref name="expression"/> is searched in:
+ /// <c>Format</c>, <c>RegExpr</c>,
+ /// <c>ValidExtension</c> and <c>ValidFilename</c>.
+ /// </summary>
+ /// <param name="expression">The expression to search for.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin Plugin(string expression)
+ {
+ FreeImagePlugin result = null;
+ expression = expression.ToLower();
+
+ foreach (FreeImagePlugin plugin in plugins)
+ {
+ if (plugin.Format.ToLower().Contains(expression) ||
+ plugin.RegExpr.ToLower().Contains(expression) ||
+ plugin.ValidExtension(expression, StringComparison.CurrentCultureIgnoreCase) ||
+ plugin.ValidFilename(expression, StringComparison.CurrentCultureIgnoreCase))
+ {
+ result = plugin;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given format.
+ /// </summary>
+ /// <param name="format">The format of the Plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromFormat(string format)
+ {
+ return Plugin(FreeImage.GetFIFFromFormat(format));
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given filename.
+ /// </summary>
+ /// <param name="filename">The valid filename for the plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromFilename(string filename)
+ {
+ return Plugin(FreeImage.GetFIFFromFilename(filename));
+ }
+
+ /// <summary>
+ /// Returns an instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/> for the given mime.
+ /// </summary>
+ /// <param name="mime">The valid mime for the plugin.</param>
+ /// <returns>An instance of <see cref="FreeImageAPI.Plugins.FreeImagePlugin"/>.</returns>
+ public static FreeImagePlugin PluginFromMime(string mime)
+ {
+ return Plugin(FreeImage.GetFIFFromMime(mime));
+ }
+
+ /// <summary>
+ /// Gets the number of registered plugins.
+ /// </summary>
+ public static int FIFCount
+ {
+ get
+ {
+ return FreeImage.GetFIFCount();
+ }
+ }
+
+ /// <summary>
+ /// Gets a readonly collection of all plugins.
+ /// </summary>
+ public static ReadOnlyCollection<FreeImagePlugin> PluginList
+ {
+ get
+ {
+ return plugins.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are only able to
+ /// read but not to write.
+ /// </summary>
+ public static List<FreeImagePlugin> ReadOnlyPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsReading && !p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are only able to
+ /// write but not to read.
+ /// </summary>
+ public static List<FreeImagePlugin> WriteOnlyPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!p.SupportsReading && p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are not able to
+ /// read or write.
+ /// </summary>
+ public static List<FreeImagePlugin> StupidPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!p.SupportsReading && !p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are able to read.
+ /// </summary>
+ public static List<FreeImagePlugin> ReadablePlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsReading)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of plugins that are able to write.
+ /// </summary>
+ public static List<FreeImagePlugin> WriteablePlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (p.SupportsWriting)
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of local plugins.
+ /// </summary>
+ public static ReadOnlyCollection<FreeImagePlugin> LocalPlugins
+ {
+ get
+ {
+ return localPlugins.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Gets a list of built-in plugins.
+ /// </summary>
+ public static List<FreeImagePlugin> BuiltInPlugins
+ {
+ get
+ {
+ List<FreeImagePlugin> list = new List<FreeImagePlugin>();
+ foreach (FreeImagePlugin p in plugins)
+ {
+ if (!localPlugins.Contains(p))
+ {
+ list.Add(p);
+ }
+ }
+ return list;
+ }
+ }
+
+ /// <summary>
+ /// Windows or OS/2 Bitmap File (*.BMP)
+ /// </summary>
+ public static FreeImagePlugin BMP { get { return plugins[0]; } }
+
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ public static FreeImagePlugin ICO { get { return plugins[1]; } }
+
+ /// <summary>
+ /// Independent JPEG Group (*.JPG, *.JIF, *.JPEG, *.JPE)
+ /// </summary>
+ public static FreeImagePlugin JPEG { get { return plugins[2]; } }
+
+ /// <summary>
+ /// JPEG Network Graphics (*.JNG)
+ /// </summary>
+ public static FreeImagePlugin JNG { get { return plugins[3]; } }
+
+ /// <summary>
+ /// Commodore 64 Koala format (*.KOA)
+ /// </summary>
+ public static FreeImagePlugin KOALA { get { return plugins[4]; } }
+
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ public static FreeImagePlugin LBM { get { return plugins[5]; } }
+
+ /// <summary>
+ /// Amiga IFF (*.IFF, *.LBM)
+ /// </summary>
+ public static FreeImagePlugin IFF { get { return plugins[5]; } }
+
+ /// <summary>
+ /// Multiple Network Graphics (*.MNG)
+ /// </summary>
+ public static FreeImagePlugin MNG { get { return plugins[6]; } }
+
+ /// <summary>
+ /// Portable Bitmap (ASCII) (*.PBM)
+ /// </summary>
+ public static FreeImagePlugin PBM { get { return plugins[7]; } }
+
+ /// <summary>
+ /// Portable Bitmap (BINARY) (*.PBM)
+ /// </summary>
+ public static FreeImagePlugin PBMRAW { get { return plugins[8]; } }
+
+ /// <summary>
+ /// Kodak PhotoCD (*.PCD)
+ /// </summary>
+ public static FreeImagePlugin PCD { get { return plugins[9]; } }
+
+ /// <summary>
+ /// Zsoft Paintbrush PCX bitmap format (*.PCX)
+ /// </summary>
+ public static FreeImagePlugin PCX { get { return plugins[10]; } }
+
+ /// <summary>
+ /// Portable Graymap (ASCII) (*.PGM)
+ /// </summary>
+ public static FreeImagePlugin PGM { get { return plugins[11]; } }
+
+ /// <summary>
+ /// Portable Graymap (BINARY) (*.PGM)
+ /// </summary>
+ public static FreeImagePlugin PGMRAW { get { return plugins[12]; } }
+
+ /// <summary>
+ /// Portable Network Graphics (*.PNG)
+ /// </summary>
+ public static FreeImagePlugin PNG { get { return plugins[13]; } }
+
+ /// <summary>
+ /// Portable Pixelmap (ASCII) (*.PPM)
+ /// </summary>
+ public static FreeImagePlugin PPM { get { return plugins[14]; } }
+
+ /// <summary>
+ /// Portable Pixelmap (BINARY) (*.PPM)
+ /// </summary>
+ public static FreeImagePlugin PPMRAW { get { return plugins[15]; } }
+
+ /// <summary>
+ /// Sun Rasterfile (*.RAS)
+ /// </summary>
+ public static FreeImagePlugin RAS { get { return plugins[16]; } }
+
+ /// <summary>
+ /// truevision Targa files (*.TGA, *.TARGA)
+ /// </summary>
+ public static FreeImagePlugin TARGA { get { return plugins[17]; } }
+
+ /// <summary>
+ /// Tagged Image File Format (*.TIF, *.TIFF)
+ /// </summary>
+ public static FreeImagePlugin TIFF { get { return plugins[18]; } }
+
+ /// <summary>
+ /// Wireless Bitmap (*.WBMP)
+ /// </summary>
+ public static FreeImagePlugin WBMP { get { return plugins[19]; } }
+
+ /// <summary>
+ /// Adobe Photoshop (*.PSD)
+ /// </summary>
+ public static FreeImagePlugin PSD { get { return plugins[20]; } }
+
+ /// <summary>
+ /// Dr. Halo (*.CUT)
+ /// </summary>
+ public static FreeImagePlugin CUT { get { return plugins[21]; } }
+
+ /// <summary>
+ /// X11 Bitmap Format (*.XBM)
+ /// </summary>
+ public static FreeImagePlugin XBM { get { return plugins[22]; } }
+
+ /// <summary>
+ /// X11 Pixmap Format (*.XPM)
+ /// </summary>
+ public static FreeImagePlugin XPM { get { return plugins[23]; } }
+
+ /// <summary>
+ /// DirectDraw Surface (*.DDS)
+ /// </summary>
+ public static FreeImagePlugin DDS { get { return plugins[24]; } }
+
+ /// <summary>
+ /// Graphics Interchange Format (*.GIF)
+ /// </summary>
+ public static FreeImagePlugin GIF { get { return plugins[25]; } }
+
+ /// <summary>
+ /// High Dynamic Range (*.HDR)
+ /// </summary>
+ public static FreeImagePlugin HDR { get { return plugins[26]; } }
+
+ /// <summary>
+ /// Raw Fax format CCITT G3 (*.G3)
+ /// </summary>
+ public static FreeImagePlugin FAXG3 { get { return plugins[27]; } }
+
+ /// <summary>
+ /// Silicon Graphics SGI image format (*.SGI)
+ /// </summary>
+ public static FreeImagePlugin SGI { get { return plugins[28]; } }
+
+ /// <summary>
+ /// OpenEXR format (*.EXR)
+ /// </summary>
+ public static FreeImagePlugin EXR { get { return plugins[29]; } }
+
+ /// <summary>
+ /// JPEG-2000 format (*.J2K, *.J2C)
+ /// </summary>
+ public static FreeImagePlugin J2K { get { return plugins[30]; } }
+
+ /// <summary>
+ /// JPEG-2000 format (*.JP2)
+ /// </summary>
+ public static FreeImagePlugin JP2 { get { return plugins[31]; } }
+
+ /// <summary>
+ /// Portable FloatMap (*.PFM)
+ /// </summary>
+ public static FreeImagePlugin PFM { get { return plugins[32]; } }
+
+ /// <summary>
+ /// Macintosh PICT (*.PICT)
+ /// </summary>
+ public static FreeImagePlugin PICT { get { return plugins[33]; } }
+
+ /// <summary>
+ /// RAW camera image (*.*)
+ /// </summary>
+ public static FreeImagePlugin RAW { get { return plugins[34]; } }
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Provides methods for working with generic bitmap scanlines.
+ /// </summary>
+ /// <typeparam name="T">Type of the bitmaps' scanlines.</typeparam>
+ public sealed class Scanline<T> : MemoryArray<T> where T : struct
+ {
+ /// <summary>
+ /// Initializes a new instance based on the specified FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public Scanline(FIBITMAP dib)
+ : this(dib, 0)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance based on the specified FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="scanline">Index of the zero based scanline.</param>
+ public Scanline(FIBITMAP dib, int scanline)
+ : this(dib, scanline, (int)(typeof(T) == typeof(FI1BIT) ?
+ FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib) :
+ typeof(T) == typeof(FI4BIT) ?
+ FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib) / 4 :
+ (FreeImage.GetBPP(dib) * FreeImage.GetWidth(dib)) / (Marshal.SizeOf(typeof(T)) * 8)))
+ {
+ }
+
+ internal Scanline(FIBITMAP dib, int scanline, int length)
+ : base(FreeImage.GetScanLine(dib, scanline), length)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if ((scanline < 0) || (scanline >= FreeImage.GetHeight(dib)))
+ {
+ throw new ArgumentOutOfRangeException("scanline");
+ }
+ }
+ }
+}
+
+namespace FreeImageAPI.IO
+{
+ /// <summary>
+ /// Class wrapping streams, implementing a buffer for read data,
+ /// so that seek operations can be made.
+ /// </summary>
+ /// <remarks>
+ /// FreeImage can load bitmaps from arbitrary sources.
+ /// .NET works with different streams like File- or NetConnection-strams.
+ /// NetConnection streams, which are used to load files from web servers,
+ /// for example cannot seek.
+ /// But FreeImage frequently uses the seek operation when loading bitmaps.
+ /// <b>StreamWrapper</b> wrapps a stream and makes it seekable by caching all read
+ /// data into an internal MemoryStream to jump back- and forward.
+ /// StreamWapper is for internal use and only for loading from streams.
+ /// </remarks>
+ internal class StreamWrapper : Stream
+ {
+ /// <summary>
+ /// The stream to wrap
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly Stream stream;
+
+ /// <summary>
+ /// The caching stream
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private MemoryStream memoryStream = new MemoryStream();
+
+ /// <summary>
+ /// Indicates if the wrapped stream reached its end
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool eos = false;
+
+ /// <summary>
+ /// Tells the wrapper to block readings or not
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool blocking = false;
+
+ /// <summary>
+ /// Indicates if the wrapped stream is disposed or not
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private bool disposed = false;
+
+ /// <summary>
+ /// Initializes a new instance based on the specified <see cref="Stream"/>.
+ /// </summary>
+ /// <param name="stream">The stream to wrap.</param>
+ /// <param name="blocking">When true the wrapper always tries to read the requested
+ /// amount of data from the wrapped stream.</param>
+ public StreamWrapper(Stream stream, bool blocking)
+ {
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ this.stream = stream;
+ this.blocking = blocking;
+ }
+
+ /// <summary>
+ /// Releases all resources used by the instance.
+ /// </summary>
+ ~StreamWrapper()
+ {
+ Dispose(false);
+ }
+
+ // The wrapper only accepts readable streams
+ public override bool CanRead
+ {
+ get { checkDisposed(); return true; }
+ }
+
+ // We implement that feature
+ public override bool CanSeek
+ {
+ get { checkDisposed(); return true; }
+ }
+
+ // The wrapper is readonly
+ public override bool CanWrite
+ {
+ get { checkDisposed(); return false; }
+ }
+
+ // Just forward it
+ public override void Flush()
+ {
+ checkDisposed();
+ stream.Flush();
+ }
+
+ // Calling this property will cause the wrapper to read the stream
+ // to its end and cache it completely.
+ public override long Length
+ {
+ get
+ {
+ checkDisposed();
+ if (!eos)
+ {
+ Fill();
+ }
+ return memoryStream.Length;
+ }
+ }
+
+ // Gets or sets the current position
+ public override long Position
+ {
+ get
+ {
+ checkDisposed();
+ return memoryStream.Position;
+ }
+ set
+ {
+ checkDisposed();
+ Seek(value, SeekOrigin.Begin);
+ }
+ }
+
+ // Implements the reading feature
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ checkDisposed();
+ // total bytes read from memory-stream
+ int memoryBytes = 0;
+ // total bytes read from the original stream
+ int streamBytes = 0;
+ memoryBytes = memoryStream.Read(buffer, offset, count);
+ if ((count > memoryBytes) && (!eos))
+ {
+ // read the rest from the original stream (can be 0 bytes)
+ do
+ {
+ int read = stream.Read(
+ buffer,
+ offset + memoryBytes + streamBytes,
+ count - memoryBytes - streamBytes);
+ streamBytes += read;
+ if (read == 0)
+ {
+ eos = true;
+ break;
+ }
+ if (!blocking)
+ {
+ break;
+ }
+ } while ((memoryBytes + streamBytes) < count);
+ // copy the bytes from the original stream into the memory stream
+ // if 0 bytes were read we write 0 so the memory-stream is not changed
+ memoryStream.Write(buffer, offset + memoryBytes, streamBytes);
+ }
+ return memoryBytes + streamBytes;
+ }
+
+ // Implements the seeking feature
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ checkDisposed();
+ long newPosition = 0L;
+ // get new position
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ newPosition = offset;
+ break;
+ case SeekOrigin.Current:
+ newPosition = memoryStream.Position + offset;
+ break;
+ case SeekOrigin.End:
+ // to seek from the end have have to read to the end first
+ if (!eos)
+ {
+ Fill();
+ }
+ newPosition = memoryStream.Length + offset;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("origin");
+ }
+ // in case the new position is beyond the memory-streams end
+ // and the original streams end hasn't been reached
+ // the original stream is read until either the stream ends or
+ // enough bytes have been read
+ if ((newPosition > memoryStream.Length) && (!eos))
+ {
+ memoryStream.Position = memoryStream.Length;
+ int bytesToRead = (int)(newPosition - memoryStream.Length);
+ byte[] buffer = new byte[1024];
+ do
+ {
+ bytesToRead -= Read(buffer, 0, (bytesToRead >= buffer.Length) ? buffer.Length : bytesToRead);
+ } while ((bytesToRead > 0) && (!eos));
+ }
+ memoryStream.Position = (newPosition <= memoryStream.Length) ? newPosition : memoryStream.Length;
+ return 0;
+ }
+
+ // No write-support
+ public override void SetLength(long value)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ // No write-support
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new Exception("The method or operation is not implemented.");
+ }
+
+ public void Reset()
+ {
+ checkDisposed();
+ Position = 0;
+ }
+
+ // Reads the wrapped stream until its end.
+ private void Fill()
+ {
+ if (!eos)
+ {
+ memoryStream.Position = memoryStream.Length;
+ int bytesRead = 0;
+ byte[] buffer = new byte[1024];
+ do
+ {
+ bytesRead = stream.Read(buffer, 0, buffer.Length);
+ memoryStream.Write(buffer, 0, bytesRead);
+ } while (bytesRead != 0);
+ eos = true;
+ }
+ }
+
+ public new void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private new void Dispose(bool disposing)
+ {
+ if (!disposed)
+ {
+ disposed = true;
+ if (disposing)
+ {
+ if (memoryStream != null)
+ {
+ memoryStream.Dispose();
+ }
+ }
+ }
+ }
+
+ public bool Disposed
+ {
+ get { return disposed; }
+ }
+
+ private void checkDisposed()
+ {
+ if (disposed) throw new ObjectDisposedException("StreamWrapper");
+ }
+ }
+}
+
+ #endregion
+
+ #region Enums
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Enumeration used for color conversions.
+ /// FREE_IMAGE_COLOR_DEPTH contains several colors to convert to.
+ /// The default value 'FICD_AUTO'.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_COLOR_DEPTH
+ {
+ /// <summary>
+ /// Unknown.
+ /// </summary>
+ FICD_UNKNOWN = 0,
+ /// <summary>
+ /// Auto selected by the used algorithm.
+ /// </summary>
+ FICD_AUTO = FICD_UNKNOWN,
+ /// <summary>
+ /// 1-bit.
+ /// </summary>
+ FICD_01_BPP = 1,
+ /// <summary>
+ /// 1-bit using dithering.
+ /// </summary>
+ FICD_01_BPP_DITHER = FICD_01_BPP,
+ /// <summary>
+ /// 1-bit using threshold.
+ /// </summary>
+ FICD_01_BPP_THRESHOLD = FICD_01_BPP | 2,
+ /// <summary>
+ /// 4-bit.
+ /// </summary>
+ FICD_04_BPP = 4,
+ /// <summary>
+ /// 8-bit.
+ /// </summary>
+ FICD_08_BPP = 8,
+ /// <summary>
+ /// 16-bit 555 (1 bit remains unused).
+ /// </summary>
+ FICD_16_BPP_555 = FICD_16_BPP | 2,
+ /// <summary>
+ /// 16-bit 565 (all bits are used).
+ /// </summary>
+ FICD_16_BPP = 16,
+ /// <summary>
+ /// 24-bit.
+ /// </summary>
+ FICD_24_BPP = 24,
+ /// <summary>
+ /// 32-bit.
+ /// </summary>
+ FICD_32_BPP = 32,
+ /// <summary>
+ /// Reorder palette (make it linear). Only affects 1-, 4- and 8-bit images.
+ /// <para>The palette is only reordered in case the image is greyscale
+ /// (all palette entries have the same red, green and blue value).</para>
+ /// </summary>
+ FICD_REORDER_PALETTE = 1024,
+ /// <summary>
+ /// Converts the image to greyscale.
+ /// </summary>
+ FICD_FORCE_GREYSCALE = 2048,
+ /// <summary>
+ /// Flag to mask out all non color depth flags.
+ /// </summary>
+ FICD_COLOR_MASK = FICD_01_BPP | FICD_04_BPP | FICD_08_BPP | FICD_16_BPP | FICD_24_BPP | FICD_32_BPP
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// List of combinable compare modes.
+ /// </summary>
+ [System.Flags]
+ public enum FREE_IMAGE_COMPARE_FLAGS
+ {
+ /// <summary>
+ /// Compare headers.
+ /// </summary>
+ HEADER = 0x1,
+ /// <summary>
+ /// Compare palettes.
+ /// </summary>
+ PALETTE = 0x2,
+ /// <summary>
+ /// Compare pixel data.
+ /// </summary>
+ DATA = 0x4,
+ /// <summary>
+ /// Compare meta data.
+ /// </summary>
+ METADATA = 0x8,
+ /// <summary>
+ /// Compare everything.
+ /// </summary>
+ COMPLETE = (HEADER | PALETTE | DATA | METADATA)
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Flags for copying data from a bitmap to another.
+ /// </summary>
+ public enum FREE_IMAGE_METADATA_COPY
+ {
+ /// <summary>
+ /// Exisiting metadata will remain unchanged.
+ /// </summary>
+ KEEP_EXISITNG = 0x0,
+ /// <summary>
+ /// Existing metadata will be cleared.
+ /// </summary>
+ CLEAR_EXISTING = 0x1,
+ /// <summary>
+ /// Existing metadata will be overwritten.
+ /// </summary>
+ REPLACE_EXISTING = 0x2
+ }
+}
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// List different search modes.
+ /// </summary>
+ [System.Flags]
+ public enum MD_SEARCH_FLAGS
+ {
+ /// <summary>
+ /// The key of the metadata.
+ /// </summary>
+ KEY = 0x1,
+ /// <summary>
+ /// The description of the metadata
+ /// </summary>
+ DESCRIPTION = 0x2,
+ /// <summary>
+ /// The ToString value of the metadata
+ /// </summary>
+ TOSTRING = 0x4,
+ }
+}
+
+ #endregion
+
+namespace FreeImageAPI
+{
+ /// <summary>
+ /// Static class importing functions from the FreeImage library
+ /// and providing additional functions.
+ /// </summary>
+ public static partial class FreeImage
+ {
+ #region Constants
+
+ /// <summary>
+ /// Array containing all 'FREE_IMAGE_MDMODEL's.
+ /// </summary>
+ public static readonly FREE_IMAGE_MDMODEL[] FREE_IMAGE_MDMODELS =
+ (FREE_IMAGE_MDMODEL[])Enum.GetValues(typeof(FREE_IMAGE_MDMODEL));
+
+ /// <summary>
+ /// Stores handles used to read from streams.
+ /// </summary>
+ private static Dictionary<FIMULTIBITMAP, fi_handle> streamHandles =
+ new Dictionary<FIMULTIBITMAP, fi_handle>();
+
+ /// <summary>
+ /// Version of the wrapper library.
+ /// </summary>
+ private static Version WrapperVersion;
+
+ private const int DIB_RGB_COLORS = 0;
+ private const int DIB_PAL_COLORS = 1;
+ private const int CBM_INIT = 0x4;
+
+ /// <summary>
+ /// An uncompressed format.
+ /// </summary>
+ public const int BI_RGB = 0;
+
+ /// <summary>
+ /// A run-length encoded (RLE) format for bitmaps with 8 bpp. The compression format is a 2-byte
+ /// format consisting of a count byte followed by a byte containing a color index.
+ /// </summary>
+ public const int BI_RLE8 = 1;
+
+ /// <summary>
+ /// An RLE format for bitmaps with 4 bpp. The compression format is a 2-byte format consisting
+ /// of a count byte followed by two word-length color indexes.
+ /// </summary>
+ public const int BI_RLE4 = 2;
+
+ /// <summary>
+ /// Specifies that the bitmap is not compressed and that the color table consists of three
+ /// <b>DWORD</b> color masks that specify the red, green, and blue components, respectively,
+ /// of each pixel. This is valid when used with 16- and 32-bpp bitmaps.
+ /// </summary>
+ public const int BI_BITFIELDS = 3;
+
+ /// <summary>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a JPEG image.
+ /// </summary>
+ public const int BI_JPEG = 4;
+
+ /// <summary>
+ /// <b>Windows 98/Me, Windows 2000/XP:</b> Indicates that the image is a PNG image.
+ /// </summary>
+ public const int BI_PNG = 5;
+
+ #endregion
+
+ #region General functions
+
+ /// <summary>
+ /// Returns the internal version of this FreeImage .NET wrapper.
+ /// </summary>
+ /// <returns>The internal version of this FreeImage .NET wrapper.</returns>
+ public static Version GetWrapperVersion()
+ {
+ if (WrapperVersion == null)
+ {
+ try
+ {
+ object[] attributes = Assembly.GetAssembly(typeof(FreeImage))
+ .GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false);
+ if ((attributes != null) && (attributes.Length != 0))
+ {
+ AssemblyFileVersionAttribute attribute =
+ attributes[0] as AssemblyFileVersionAttribute;
+ if ((attribute != null) && (attribute.Version != null))
+ {
+ return (WrapperVersion = new Version(attribute.Version));
+ }
+ }
+ }
+ catch
+ {
+
+ }
+
+ WrapperVersion = new Version();
+ }
+
+ return WrapperVersion;
+ }
+
+ /// <summary>
+ /// Returns the version of the native FreeImage library.
+ /// </summary>
+ /// <returns>The version of the native FreeImage library.</returns>
+ public static Version GetNativeVersion()
+ {
+ return new Version(GetVersion());
+ }
+
+ /// <summary>
+ /// Returns a value indicating if the FreeImage library is available or not.
+ /// See remarks for further details.
+ /// </summary>
+ /// <returns><c>false</c> if the file is not available or out of date;
+ /// <c>true</c>, otherwise.</returns>
+ /// <remarks>
+ /// The FreeImage.NET library is a wrapper for the native C++ library
+ /// (FreeImage.dll ... dont mix ist up with this library FreeImageNet.dll).
+ /// The native library <b>must</b> be either in the same folder as the program's
+ /// executable or in a folder contained in the envirent variable <i>PATH</i>
+ /// (for example %WINDIR%\System32).<para/>
+ /// Further more must both libraries, including the program itself,
+ /// be the same architecture (x86 or x64).
+ /// </remarks>
+ public static bool IsAvailable()
+ {
+ try
+ {
+ // Call a static fast executing function
+ Version nativeVersion = new Version(GetVersion());
+ Version wrapperVersion = GetWrapperVersion();
+ // No exception thrown, the library seems to be present
+ return
+ (nativeVersion.Major >= wrapperVersion.Major) &&
+ (nativeVersion.Minor >= wrapperVersion.Minor) &&
+ (nativeVersion.Build >= wrapperVersion.Build);
+ }
+ catch (DllNotFoundException)
+ {
+ return false;
+ }
+ catch (EntryPointNotFoundException)
+ {
+ return false;
+ }
+ catch (BadImageFormatException)
+ {
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region Bitmap management functions
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Allocate(int width, int height, int bpp)
+ {
+ return Allocate(width, height, bpp, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Creates a new bitmap in memory.
+ /// </summary>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new Bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP AllocateT(FREE_IMAGE_TYPE type, int width, int height, int bpp)
+ {
+ return AllocateT(type, width, height, bpp, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmaps.</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="Allocate"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="Allocate"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>.
+ /// So, please refer to the documentation of <see cref="FillBackground&lt;T&gt;"/> to
+ /// learn more about parameters <paramref name="color"/> and <paramref name="options"/>.
+ /// <para/>
+ /// The palette specified through parameter <paramref name="palette"/> is only copied to the
+ /// newly created image, if the desired bit depth is smaller than or equal to 8 bits per pixel.
+ /// In other words, the <paramref name="palette"/> parameter is only taken into account for
+ /// palletized images. So, for an 8-bit image, the length is 256, for an 4-bit image it is 16
+ /// and it is 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified <paramref name="color"/> is applied to the palette entry,
+ /// specified by the background color's <see cref="RGBQUAD.rgbReserved"/> field.
+ /// The image is then filled with this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="Allocate"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateEx(int width, int height, int bpp,
+ RGBQUAD? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette)
+ {
+ return AllocateEx(width, height, bpp, color, options, palette, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmaps.</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="Allocate"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="Allocate"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>.
+ /// So, please refer to the documentation of <see cref="FillBackground&lt;T&gt;"/> to
+ /// learn more about parameters <paramref name="color"/> and <paramref name="options"/>.
+ /// <para/>
+ /// The palette specified through parameter <paramref name="palette"/> is only copied to the
+ /// newly created image, if the desired bit depth is smaller than or equal to 8 bits per pixel.
+ /// In other words, the <paramref name="palette"/> parameter is only taken into account for
+ /// palletized images. So, for an 8-bit image, the length is 256, for an 4-bit image it is 16
+ /// and it is 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified <paramref name="color"/> is applied to the palette entry,
+ /// specified by the background color's <see cref="RGBQUAD.rgbReserved"/> field.
+ /// The image is then filled with this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="Allocate"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateEx(int width, int height, int bpp,
+ RGBQUAD? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask)
+ {
+ if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ RGBQUAD[] buffer = new RGBQUAD[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return AllocateEx(width, height, bpp, handle.AddrOfPinnedObject(),
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return AllocateEx(width, height, bpp, IntPtr.Zero,
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified type, width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="AllocateT"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="AllocateT"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the
+ /// documentation of <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters color and options.
+ /// <para/>
+ /// The palette specified through parameter palette is only copied to the newly created
+ /// image, if its image type is <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> and the desired bit
+ /// depth is smaller than or equal to 8 bits per pixel. In other words, the <paramref name="palette"/>
+ /// palette is only taken into account for palletized images. However, if the preceding conditions
+ /// match and if <paramref name="palette"/> is not <c>null</c>, the palette is assumed to be at
+ /// least as large as the size of a fully populated palette for the desired bit depth.
+ /// So, for an 8-bit image, this length is 256, for an 4-bit image it is 16 and it is
+ /// 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified color is applied to the palette entry, specified by the
+ /// background color's <see cref="RGBQUAD.rgbReserved"/> field. The image is then filled with
+ /// this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="AllocateT"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateExT<T>(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette) where T : struct
+ {
+ return AllocateExT(type, width, height, bpp, color, options, palette, 0, 0, 0);
+ }
+
+ /// <summary>
+ /// Allocates a new image of the specified type, width, height and bit depth and optionally
+ /// fills it with the specified color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="type">Type of the image.</param>
+ /// <param name="width">Width of the new bitmap.</param>
+ /// <param name="height">Height of the new bitmap.</param>
+ /// <param name="bpp">Bit depth of the new bitmap.
+ /// Supported pixel depth: 1-, 4-, 8-, 16-, 24-, 32-bit per pixel for standard bitmap</param>
+ /// <param name="color">The color to fill the bitmap with or <c>null</c>.</param>
+ /// <param name="options">Options to enable or disable function-features.</param>
+ /// <param name="palette">The palette of the bitmap or <c>null</c>.</param>
+ /// <param name="red_mask">Red part of the color layout.
+ /// eg: 0xFF0000</param>
+ /// <param name="green_mask">Green part of the color layout.
+ /// eg: 0x00FF00</param>
+ /// <param name="blue_mask">Blue part of the color layout.
+ /// eg: 0x0000FF</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is an extension to <see cref="AllocateT"/>, which additionally supports
+ /// specifying a palette to be set for the newly create image, as well as specifying a
+ /// background color, the newly created image should initially be filled with.
+ /// <para/>
+ /// Basically, this function internally relies on function <see cref="AllocateT"/>, followed by a
+ /// call to <see cref="FillBackground&lt;T&gt;"/>. This is why both parameters
+ /// <paramref name="color"/> and <paramref name="options"/> behave the same as it is
+ /// documented for function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the
+ /// documentation of <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters color and options.
+ /// <para/>
+ /// The palette specified through parameter palette is only copied to the newly created
+ /// image, if its image type is <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> and the desired bit
+ /// depth is smaller than or equal to 8 bits per pixel. In other words, the <paramref name="palette"/>
+ /// palette is only taken into account for palletized images. However, if the preceding conditions
+ /// match and if <paramref name="palette"/> is not <c>null</c>, the palette is assumed to be at
+ /// least as large as the size of a fully populated palette for the desired bit depth.
+ /// So, for an 8-bit image, this length is 256, for an 4-bit image it is 16 and it is
+ /// 2 for a 1-bit image. In other words, this function does not support partial palettes.
+ /// <para/>
+ /// However, specifying a palette is not necesarily needed, even for palletized images. This
+ /// function is capable of implicitly creating a palette, if <paramref name="palette"/> is <c>null</c>.
+ /// If the specified background color is a greyscale value (red = green = blue) or if option
+ /// <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/> is specified, a greyscale palette
+ /// is created. For a 1-bit image, only if the specified background color is either black or white,
+ /// a monochrome palette, consisting of black and white only is created. In any case, the darker
+ /// colors are stored at the smaller palette indices.
+ /// <para/>
+ /// If the specified background color is not a greyscale value, or is neither black nor white
+ /// for a 1-bit image, solely this specified color is injected into the otherwise black-initialized
+ /// palette. For this operation, option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// is implicit, so the specified color is applied to the palette entry, specified by the
+ /// background color's <see cref="RGBQUAD.rgbReserved"/> field. The image is then filled with
+ /// this palette index.
+ /// <para/>
+ /// This function returns a newly created image as function <see cref="AllocateT"/> does, if both
+ /// parameters <paramref name="color"/> and <paramref name="palette"/> are <c>null</c>.
+ /// If only <paramref name="color"/> is <c>null</c>, the palette pointed to by
+ /// parameter <paramref name="palette"/> is initially set for the new image, if a palletized
+ /// image of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> is created.
+ /// However, in the latter case, this function returns an image, whose
+ /// pixels are all initialized with zeros so, the image will be filled with the color of the
+ /// first palette entry.
+ /// </remarks>
+ public static FIBITMAP AllocateExT<T>(FREE_IMAGE_TYPE type, int width, int height, int bpp,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options, RGBQUAD[] palette,
+ uint red_mask, uint green_mask, uint blue_mask) where T : struct
+ {
+ if ((palette != null) && (bpp <= 8) && (palette.Length < (1 << bpp)))
+ return FIBITMAP.Zero;
+
+ if (!CheckColorType(type, color))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return AllocateExT(type, width, height, bpp, handle.AddrOfPinnedObject(),
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return AllocateExT(type, width, height, bpp, IntPtr.Zero,
+ options, palette, red_mask, green_mask, blue_mask);
+ }
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a .NET <see cref="System.Drawing.Bitmap"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The converted .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of <paramref name="dib"/> is not FIT_BITMAP.</exception>
+ public static Bitmap GetBitmap(FIBITMAP dib)
+ {
+ return GetBitmap(dib, true);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap to a .NET <see cref="System.Drawing.Bitmap"/>.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="copyMetadata">When true existing metadata will be copied.</param>
+ /// <returns>The converted .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of <paramref name="dib"/> is not FIT_BITMAP.</exception>
+ internal static Bitmap GetBitmap(FIBITMAP dib, bool copyMetadata)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (GetImageType(dib) != FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ throw new ArgumentException("Only bitmaps with type of FIT_BITMAP can be converted.");
+ }
+
+ PixelFormat format = GetPixelFormat(dib);
+
+ if ((format == PixelFormat.Undefined) && (GetBPP(dib) == 16u))
+ {
+ throw new ArgumentException("Only 16bit 555 and 565 are supported.");
+ }
+
+ int height = (int)GetHeight(dib);
+ int width = (int)GetWidth(dib);
+ int pitch = (int)GetPitch(dib);
+
+ Bitmap result = new Bitmap(width, height, format);
+ BitmapData data;
+ // Locking the complete bitmap in writeonly mode
+ data = result.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format);
+ // Writing the bitmap data directly into the new created .NET bitmap.
+ ConvertToRawBits(data.Scan0, dib, pitch, GetBPP(dib),
+ GetRedMask(dib), GetGreenMask(dib), GetBlueMask(dib), true);
+ // Unlock the bitmap
+ result.UnlockBits(data);
+ // Apply the bitmaps resolution
+ result.SetResolution(GetResolutionX(dib), GetResolutionY(dib));
+ // Check whether the bitmap has a palette
+ if (GetPalette(dib) != IntPtr.Zero)
+ {
+ // Get the bitmaps palette to apply changes
+ ColorPalette palette = result.Palette;
+ // Get the orgininal palette
+ Color[] colorPalette = new Palette(dib).ColorData;
+ // Get the maximum number of palette entries to copy
+ int entriesToCopy = Math.Min(colorPalette.Length, palette.Entries.Length);
+
+ // Check whether the bitmap is transparent
+ if (IsTransparent(dib))
+ {
+ byte[] transTable = GetTransparencyTableEx(dib);
+ int i = 0;
+ int maxEntriesWithTrans = Math.Min(entriesToCopy, transTable.Length);
+ // Copy palette entries and include transparency
+ for (; i < maxEntriesWithTrans; i++)
+ {
+ palette.Entries[i] = Color.FromArgb(transTable[i], colorPalette[i]);
+ }
+ // Copy palette entries and that have no transparancy
+ for (; i < entriesToCopy; i++)
+ {
+ palette.Entries[i] = Color.FromArgb(0xFF, colorPalette[i]);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < entriesToCopy; i++)
+ {
+ palette.Entries[i] = colorPalette[i];
+ }
+ }
+
+ // Set the bitmaps palette
+ result.Palette = palette;
+ }
+ // Copy metadata
+ if (copyMetadata)
+ {
+ try
+ {
+ List<PropertyItem> list = new List<PropertyItem>();
+ // Get a list of all types
+ FITAG tag;
+ FIMETADATA mData;
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ // Get a unique search handle
+ mData = FindFirstMetadata(model, dib, out tag);
+ // Check if metadata exists for this type
+ if (mData.IsNull) continue;
+ do
+ {
+ PropertyItem propItem = CreatePropertyItem();
+ propItem.Len = (int)GetTagLength(tag);
+ propItem.Id = (int)GetTagID(tag);
+ propItem.Type = (short)GetTagType(tag);
+ byte[] buffer = new byte[propItem.Len];
+
+ unsafe
+ {
+ byte* src = (byte*)GetTagValue(tag);
+ fixed (byte* dst = buffer)
+ {
+ CopyMemory(dst, src, (uint)propItem.Len);
+ }
+ }
+
+ propItem.Value = buffer;
+ list.Add(propItem);
+ }
+ while (FindNextMetadata(mData, out tag));
+ FindCloseMetadata(mData);
+ }
+ foreach (PropertyItem propItem in list)
+ {
+ result.SetPropertyItem(propItem);
+ }
+ }
+ catch
+ {
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Converts an .NET <see cref="System.Drawing.Bitmap"/> into a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="System.Drawing.Bitmap"/> to convert.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static FIBITMAP CreateFromBitmap(Bitmap bitmap)
+ {
+ return CreateFromBitmap(bitmap, false);
+ }
+
+ /// <summary>
+ /// Converts an .NET <see cref="System.Drawing.Bitmap"/> into a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bitmap">The <see cref="System.Drawing.Bitmap"/> to convert.</param>
+ /// <param name="copyMetadata">When true existing metadata will be copied.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>Copying metadata has been disabled until a proper way
+ /// of reading and storing metadata in a .NET bitmap is found.</remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ internal static FIBITMAP CreateFromBitmap(Bitmap bitmap, bool copyMetadata)
+ {
+ if (bitmap == null)
+ {
+ throw new ArgumentNullException("bitmap");
+ }
+ uint bpp, red_mask, green_mask, blue_mask;
+ FREE_IMAGE_TYPE type;
+ if (!GetFormatParameters(bitmap.PixelFormat, out type, out bpp, out red_mask, out green_mask, out blue_mask))
+ {
+ throw new ArgumentException("The bitmaps pixelformat is invalid.");
+ }
+
+ // Locking the complete bitmap in readonly mode
+ BitmapData data = bitmap.LockBits(
+ new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
+ // Copying the bitmap data directly from the .NET bitmap
+ FIBITMAP result = ConvertFromRawBits(
+ data.Scan0,
+ type,
+ data.Width,
+ data.Height,
+ data.Stride,
+ bpp,
+ red_mask,
+ green_mask,
+ blue_mask,
+ true);
+ bitmap.UnlockBits(data);
+ // Handle palette
+ if (GetPalette(result) != IntPtr.Zero)
+ {
+ Palette palette = new Palette(result);
+ Color[] colors = bitmap.Palette.Entries;
+ // Only copy available palette entries
+ int entriesToCopy = Math.Min(palette.Length, colors.Length);
+ byte[] transTable = new byte[entriesToCopy];
+ for (int i = 0; i < entriesToCopy; i++)
+ {
+ RGBQUAD color = (RGBQUAD)colors[i];
+ color.rgbReserved = 0x00;
+ palette[i] = color;
+ transTable[i] = colors[i].A;
+ }
+ if ((bitmap.Flags & (int)ImageFlags.HasAlpha) != 0)
+ {
+ FreeImage.SetTransparencyTable(result, transTable);
+ }
+ }
+ // Handle meta data
+ // Disabled
+ //if (copyMetadata)
+ //{
+ // foreach (PropertyItem propItem in bitmap.PropertyItems)
+ // {
+ // FITAG tag = CreateTag();
+ // SetTagLength(tag, (uint)propItem.Len);
+ // SetTagID(tag, (ushort)propItem.Id);
+ // SetTagType(tag, (FREE_IMAGE_MDTYPE)propItem.Type);
+ // SetTagValue(tag, propItem.Value);
+ // SetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, result, "", tag);
+ // }
+ //}
+ return result;
+ }
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Array of bytes containing the raw bitmap.</param>
+ /// <param name="type">The type of the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static unsafe FIBITMAP ConvertFromRawBits(
+ byte[] bits,
+ FREE_IMAGE_TYPE type,
+ int width,
+ int height,
+ int pitch,
+ uint bpp,
+ uint red_mask,
+ uint green_mask,
+ uint blue_mask,
+ bool topdown)
+ {
+ fixed (byte* ptr = bits)
+ {
+ return ConvertFromRawBits(
+ (IntPtr)ptr,
+ type,
+ width,
+ height,
+ pitch,
+ bpp,
+ red_mask,
+ green_mask,
+ blue_mask,
+ topdown);
+ }
+ }
+
+ /// <summary>
+ /// Converts a raw bitmap to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="bits">Pointer to the memory block containing the raw bitmap.</param>
+ /// <param name="type">The type of the raw bitmap.</param>
+ /// <param name="width">The width in pixels of the raw bitmap.</param>
+ /// <param name="height">The height in pixels of the raw bitmap.</param>
+ /// <param name="pitch">Defines the total width of a scanline in the raw bitmap,
+ /// including padding bytes.</param>
+ /// <param name="bpp">The bit depth (bits per pixel) of the raw bitmap.</param>
+ /// <param name="red_mask">The bit mask describing the bits used to store a single
+ /// pixel's red component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="green_mask">The bit mask describing the bits used to store a single
+ /// pixel's green component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="blue_mask">The bit mask describing the bits used to store a single
+ /// pixel's blue component in the raw bitmap. This is only applied to 16-bpp raw bitmaps.</param>
+ /// <param name="topdown">If true, the raw bitmap is stored in top-down order (top-left pixel first)
+ /// and in bottom-up order (bottom-left pixel first) otherwise.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static unsafe FIBITMAP ConvertFromRawBits(
+ IntPtr bits,
+ FREE_IMAGE_TYPE type,
+ int width,
+ int height,
+ int pitch,
+ uint bpp,
+ uint red_mask,
+ uint green_mask,
+ uint blue_mask,
+ bool topdown)
+ {
+ byte* addr = (byte*)bits;
+ if ((addr == null) || (width <= 0) || (height <= 0))
+ {
+ return FIBITMAP.Zero;
+ }
+
+ FIBITMAP dib = AllocateT(type, width, height, (int)bpp, red_mask, green_mask, blue_mask);
+ if (dib != FIBITMAP.Zero)
+ {
+ if (topdown)
+ {
+ for (int i = height - 1; i >= 0; --i)
+ {
+ CopyMemory((byte*)GetScanLine(dib, i), addr, (int)GetLine(dib));
+ addr += pitch;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; ++i)
+ {
+ CopyMemory((byte*)GetScanLine(dib, i), addr, (int)GetLine(dib));
+ addr += pitch;
+ }
+ }
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(Bitmap bitmap, string filename)
+ {
+ return SaveBitmap(
+ bitmap,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(Bitmap bitmap, string filename, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveBitmap(
+ bitmap,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags);
+ }
+
+ /// <summary>
+ /// Saves a .NET <see cref="System.Drawing.Bitmap"/> to a file.
+ /// </summary>
+ /// <param name="bitmap">The .NET <see cref="System.Drawing.Bitmap"/> to save.</param>
+ /// <param name="filename">Name of the file to save to.</param>
+ /// <param name="format">Format of the bitmap. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="bitmap"/> or <paramref name="filename"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// The bitmaps pixelformat is invalid.</exception>
+ public static bool SaveBitmap(
+ Bitmap bitmap,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ FIBITMAP dib = CreateFromBitmap(bitmap);
+ bool result = SaveEx(dib, filename, format, flags);
+ Unload(dib);
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The file will be loaded with default loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadEx(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadEx(filename, flags, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// The file will be loaded with default loading flags.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, ref FREE_IMAGE_FORMAT format)
+ {
+ return LoadEx(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.
+ /// </param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ public static FIBITMAP LoadEx(string filename, FREE_IMAGE_LOAD_FLAGS flags, ref FREE_IMAGE_FORMAT format)
+ {
+ // check if file exists
+ if (!File.Exists(filename))
+ {
+ throw new FileNotFoundException(filename + " could not be found.");
+ }
+ FIBITMAP dib = new FIBITMAP();
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // query all plugins to see if one can read the file
+ format = GetFileType(filename, 0);
+ }
+ // check if the plugin is capable of loading files
+ if (FIFSupportsReading(format))
+ {
+ dib = Load(format, filename, flags);
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Loads a .NET <see cref="System.Drawing.Bitmap"/> from a file.
+ /// </summary>
+ /// <param name="filename">Name of the file to be loaded.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>The loaded .NET <see cref="System.Drawing.Bitmap"/>.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists.</exception>
+ /// <exception cref="ArgumentException">
+ /// The image type of the image is not <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>.</exception>
+ public static Bitmap LoadBitmap(string filename, FREE_IMAGE_LOAD_FLAGS flags, ref FREE_IMAGE_FORMAT format)
+ {
+ FIBITMAP dib = LoadEx(filename, flags, ref format);
+ Bitmap result = GetBitmap(dib, true);
+ Unload(dib);
+ return result;
+ }
+
+ /// <summary>
+ /// Deletes a previously loaded FreeImage bitmap from memory and resets the handle to 0.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ public static void UnloadEx(ref FIBITMAP dib)
+ {
+ if (!dib.IsNull)
+ {
+ Unload(dib);
+ dib.SetNull();
+ }
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(FIBITMAP dib, string filename)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// The format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ bool unloadSource)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveEx(
+ ref dib,
+ filename,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a file.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the format is taken off the filename.
+ /// If no suitable format was found false will be returned.
+ /// Save flags can be provided by the flags parameter.
+ /// The bitmaps color depth can be set by 'colorDepth'.
+ /// If set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> a suitable color depth
+ /// will be taken if available.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="filename">The complete name of the file to save to.
+ /// The extension will be corrected if it is no valid extension for the
+ /// selected format or if no extension was specified.</param>
+ /// <param name="format">Format of the image. If the format should be taken from the
+ /// filename use <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if Save should take the
+ /// best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentException">
+ /// A direct color conversion failed.</exception>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="filename"/> is null.</exception>
+ public static bool SaveEx(
+ ref FIBITMAP dib,
+ string filename,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ bool result = false;
+ // Gets format from filename if the format is unknown
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ format = GetFIFFromFilename(filename);
+ }
+ if (format != FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Checks writing support
+ if (FIFSupportsWriting(format) && FIFSupportsExportType(format, GetImageType(dib)))
+ {
+ // Check valid filename and correct it if needed
+ if (!IsFilenameValidForFIF(format, filename))
+ {
+ string extension = GetPrimaryExtensionFromFIF(format);
+ filename = Path.ChangeExtension(filename, extension);
+ }
+
+ FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
+ try
+ {
+ result = Save(format, dibToSave, filename, flags);
+ }
+ finally
+ {
+ // Always unload a temporary created bitmap.
+ if (dibToSave != dib)
+ {
+ UnloadEx(ref dibToSave);
+ }
+ // On success unload the bitmap
+ if (result && unloadSource)
+ {
+ UnloadEx(ref dib);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadFromStream(stream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return LoadFromStream(stream, flags, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the
+ /// bitmaps real format is being analysed.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadFromStream it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(Stream stream, ref FREE_IMAGE_FORMAT format)
+ {
+ return LoadFromStream(stream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>
+ /// the bitmaps real format is being analysed.
+ /// The stream must be set to the correct position before calling LoadFromStream.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadFromStream it will be returned in format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> is not capable of reading.</exception>
+ public static FIBITMAP LoadFromStream(
+ Stream stream,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ ref FREE_IMAGE_FORMAT format)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ // Wrap the source stream if it is unable to seek (which is required by FreeImage)
+ stream = (stream.CanSeek) ? stream : new StreamWrapper(stream, true);
+
+ stream.Position = 0L;
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Get the format of the bitmap
+ format = GetFileTypeFromStream(stream);
+ // Restore the streams position
+ stream.Position = 0L;
+ }
+ if (!FIFSupportsReading(format))
+ {
+ return FIBITMAP.Zero;
+ }
+ // Create a 'FreeImageIO' structure for calling 'LoadFromHandle'
+ // using the internal structure 'FreeImageStreamIO'.
+ FreeImageIO io = FreeImageStreamIO.io;
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ return LoadFromHandle(format, ref io, handle, flags);
+ }
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ bool unloadSource)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ bool unloadSource)
+ {
+ return SaveToStream(
+ ref dib, stream,
+ format,
+ flags,
+ FREE_IMAGE_COLOR_DEPTH.FICD_AUTO,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should
+ /// take the best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth)
+ {
+ return SaveToStream(
+ ref dib,
+ stream,
+ format,
+ flags,
+ colorDepth,
+ false);
+ }
+
+ /// <summary>
+ /// Saves a previously loaded FreeImage bitmap to a stream.
+ /// The stream must be set to the correct position before calling SaveToStream.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="stream">The stream to write to.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="colorDepth">The new color depth of the bitmap.
+ /// Set to <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_AUTO"/> if SaveToStream should
+ /// take the best suitable color depth.
+ /// If a color depth is selected that the provided format cannot write an
+ /// error-message will be thrown.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> cannot write.</exception>
+ public static bool SaveToStream(
+ ref FIBITMAP dib,
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_SAVE_FLAGS flags,
+ FREE_IMAGE_COLOR_DEPTH colorDepth,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanWrite)
+ {
+ throw new ArgumentException("stream is not capable of writing.");
+ }
+ if ((!FIFSupportsWriting(format)) || (!FIFSupportsExportType(format, GetImageType(dib))))
+ {
+ return false;
+ }
+
+ FIBITMAP dibToSave = PrepareBitmapColorDepth(dib, format, colorDepth);
+ bool result = false;
+
+ try
+ {
+ // Create a 'FreeImageIO' structure for calling 'SaveToHandle'
+ FreeImageIO io = FreeImageStreamIO.io;
+
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ result = SaveToHandle(format, dibToSave, ref io, handle, flags);
+ }
+ }
+ finally
+ {
+ // Always unload a temporary created bitmap.
+ if (dibToSave != dib)
+ {
+ UnloadEx(ref dibToSave);
+ }
+ // On success unload the bitmap
+ if (result && unloadSource)
+ {
+ UnloadEx(ref dib);
+ }
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region Plugin functions
+
+ /// <summary>
+ /// Checks if an extension is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="extension">The desired extension.</param>
+ /// <returns>True if the extension is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="extension"/> is null.</exception>
+ public static bool IsExtensionValidForFIF(FREE_IMAGE_FORMAT fif, string extension)
+ {
+ return IsExtensionValidForFIF(fif, extension, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ /// <summary>
+ /// Checks if an extension is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="extension">The desired extension.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the extension is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="extension"/> is null.</exception>
+ public static bool IsExtensionValidForFIF(FREE_IMAGE_FORMAT fif, string extension, StringComparison comparisonType)
+ {
+ if (extension == null)
+ {
+ throw new ArgumentNullException("extension");
+ }
+ bool result = false;
+ // Split up the string and compare each with the given extension
+ string tempList = GetFIFExtensionList(fif);
+ if (tempList != null)
+ {
+ string[] extensionList = tempList.Split(',');
+ foreach (string ext in extensionList)
+ {
+ if (extension.Equals(ext, comparisonType))
+ {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Checks if a filename is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="filename">The desired filename.</param>
+ /// <returns>True if the filename is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> is null.</exception>
+ public static bool IsFilenameValidForFIF(FREE_IMAGE_FORMAT fif, string filename)
+ {
+ return IsFilenameValidForFIF(fif, filename, StringComparison.CurrentCultureIgnoreCase);
+ }
+
+ /// <summary>
+ /// Checks if a filename is valid for a certain format.
+ /// </summary>
+ /// <param name="fif">The desired format.</param>
+ /// <param name="filename">The desired filename.</param>
+ /// <param name="comparisonType">The string comparison type.</param>
+ /// <returns>True if the filename is valid for the given format, false otherwise.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="filename"/> is null.</exception>
+ public static bool IsFilenameValidForFIF(FREE_IMAGE_FORMAT fif, string filename, StringComparison comparisonType)
+ {
+ if (filename == null)
+ {
+ throw new ArgumentNullException("filename");
+ }
+ bool result = false;
+ // Extract the filenames extension if it exists
+ string extension = Path.GetExtension(filename);
+ if (extension.Length != 0)
+ {
+ extension = extension.Remove(0, 1);
+ result = IsExtensionValidForFIF(fif, extension, comparisonType);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// This function returns the primary (main or most commonly used?) extension of a certain
+ /// image format (fif). This is done by returning the first of all possible extensions
+ /// returned by GetFIFExtensionList().
+ /// That assumes, that the plugin returns the extensions in ordered form.</summary>
+ /// <param name="fif">The image format to obtain the primary extension for.</param>
+ /// <returns>The primary extension of the specified image format.</returns>
+ public static string GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT fif)
+ {
+ string result = null;
+ string extensions = GetFIFExtensionList(fif);
+ if (extensions != null)
+ {
+ int position = extensions.IndexOf(',');
+ if (position < 0)
+ {
+ result = extensions;
+ }
+ else
+ {
+ result = extensions.Substring(0, position);
+ }
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Multipage functions
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(string filename)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ false,
+ false);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(string filename, bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ false,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ create_new,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files real
+ /// format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ ref FREE_IMAGE_FORMAT format,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ return OpenMultiBitmapEx(
+ filename,
+ ref format,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ create_new,
+ read_only,
+ keep_cache_in_memory);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="filename">The complete name of the file to load.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/>.
+ /// In case a suitable format was found by LoadEx it will be returned in format.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="create_new">When true a new bitmap is created.</param>
+ /// <param name="read_only">When true the bitmap will be loaded read only.</param>
+ /// <param name="keep_cache_in_memory">When true performance is increased at the cost of memory.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="FileNotFoundException">
+ /// <paramref name="filename"/> does not exists while opening.</exception>
+ public static FIMULTIBITMAP OpenMultiBitmapEx(
+ string filename,
+ ref FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ bool create_new,
+ bool read_only,
+ bool keep_cache_in_memory)
+ {
+ if (!File.Exists(filename) && !create_new)
+ {
+ throw new FileNotFoundException(filename + " could not be found.");
+ }
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ // Check if a plugin can read the data
+ format = GetFileType(filename, 0);
+ }
+ FIMULTIBITMAP dib = new FIMULTIBITMAP();
+ if (FIFSupportsReading(format))
+ {
+ dib = OpenMultiBitmap(format, filename, create_new, read_only, keep_cache_in_memory, flags);
+ }
+ return dib;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// </summary>
+ /// <param name="stream">The stream to load the bitmap from.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ public static FIMULTIBITMAP OpenMultiBitmapFromStream(Stream stream)
+ {
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ return OpenMultiBitmapFromStream(stream, ref format, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap.
+ /// In case the loading format is <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> the files
+ /// real format is being analysed. If no plugin can read the file, format remains
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/> and 0 is returned.
+ /// Load flags can be provided by the flags parameter.
+ /// </summary>
+ /// <param name="stream">The stream to load the bitmap from.</param>
+ /// <param name="format">Format of the image. If the format is unknown use
+ /// <see cref="FREE_IMAGE_FORMAT.FIF_UNKNOWN"/></param>.
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ public static FIMULTIBITMAP OpenMultiBitmapFromStream(Stream stream, ref FREE_IMAGE_FORMAT format, FREE_IMAGE_LOAD_FLAGS flags)
+ {
+ if (stream == null)
+ return FIMULTIBITMAP.Zero;
+
+ if (!stream.CanSeek)
+ stream = new StreamWrapper(stream, true);
+
+ FIMULTIBITMAP mdib = FIMULTIBITMAP.Zero;
+ FreeImageIO io = FreeImageStreamIO.io;
+ fi_handle handle = new fi_handle(stream);
+
+ try
+ {
+ if (format == FREE_IMAGE_FORMAT.FIF_UNKNOWN)
+ {
+ format = GetFileTypeFromHandle(ref io, handle, checked((int)stream.Length));
+ }
+
+ mdib = OpenMultiBitmapFromHandle(format, ref io, handle, flags);
+
+ if (mdib.IsNull)
+ {
+ handle.Dispose();
+ }
+ else
+ {
+ streamHandles.Add(mdib, handle);
+ }
+
+ return mdib;
+ }
+ catch
+ {
+ if (!mdib.IsNull)
+ CloseMultiBitmap(mdib, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+
+ if (handle != null)
+ handle.Dispose();
+
+ throw;
+ }
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only, applies any changes made to it.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmap(FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ if (CloseMultiBitmap_(bitmap, flags))
+ {
+ fi_handle handle;
+ if (streamHandles.TryGetValue(bitmap, out handle))
+ {
+ streamHandles.Remove(bitmap);
+ handle.Dispose();
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only,
+ /// applies any changes made to it.
+ /// On success the handle will be reset to null.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmapEx(ref FIMULTIBITMAP bitmap)
+ {
+ return CloseMultiBitmapEx(ref bitmap, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ /// <summary>
+ /// Closes a previously opened multi-page bitmap and, when the bitmap was not opened read-only,
+ /// applies any changes made to it.
+ /// On success the handle will be reset to null.
+ /// </summary>
+ /// <param name="bitmap">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool CloseMultiBitmapEx(ref FIMULTIBITMAP bitmap, FREE_IMAGE_SAVE_FLAGS flags)
+ {
+ bool result = false;
+ if (!bitmap.IsNull)
+ {
+ if (CloseMultiBitmap(bitmap, flags))
+ {
+ bitmap.SetNull();
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves the number of pages that are locked in a multi-paged bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>Number of locked pages.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static int GetLockedPageCount(FIMULTIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ int result = 0;
+ GetLockedPageNumbers(dib, null, ref result);
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves a list locked pages of a multi-paged bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage multi-paged bitmap.</param>
+ /// <returns>List containing the indexes of the locked pages.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static int[] GetLockedPages(FIMULTIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ // Get the number of pages and create an array to save the information
+ int count = 0;
+ int[] result = null;
+ // Get count
+ if (GetLockedPageNumbers(dib, result, ref count))
+ {
+ result = new int[count];
+ // Fill array
+ if (!GetLockedPageNumbers(dib, result, ref count))
+ {
+ result = null;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Loads a FreeImage multi-paged bitmap from a stream and returns the
+ /// FreeImage memory stream used as temporary buffer.
+ /// The bitmap can not be modified by calling
+ /// <see cref="FreeImage.AppendPage(FIMULTIBITMAP,FIBITMAP)"/>,
+ /// <see cref="FreeImage.InsertPage(FIMULTIBITMAP,Int32,FIBITMAP)"/>,
+ /// <see cref="FreeImage.MovePage(FIMULTIBITMAP,Int32,Int32)"/> or
+ /// <see cref="FreeImage.DeletePage(FIMULTIBITMAP,Int32)"/>.
+ /// </summary>
+ /// <param name="stream">The stream to read from.</param>
+ /// <param name="format">Format of the image.</param>
+ /// <param name="flags">Flags to enable or disable plugin-features.</param>
+ /// <param name="memory">The temporary memory buffer used to load the bitmap.</param>
+ /// <returns>Handle to a FreeImage multi-paged bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> can not read.</exception>
+ public static FIMULTIBITMAP LoadMultiBitmapFromStream(
+ Stream stream,
+ FREE_IMAGE_FORMAT format,
+ FREE_IMAGE_LOAD_FLAGS flags,
+ out FIMEMORY memory)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream");
+ }
+ const int blockSize = 1024;
+ int bytesRead;
+ byte[] buffer = new byte[blockSize];
+
+ stream = stream.CanSeek ? stream : new StreamWrapper(stream, true);
+ memory = OpenMemory(IntPtr.Zero, 0);
+
+ do
+ {
+ bytesRead = stream.Read(buffer, 0, blockSize);
+ WriteMemory(buffer, (uint)blockSize, (uint)1, memory);
+ }
+ while (bytesRead == blockSize);
+
+ return LoadMultiBitmapFromMemory(format, memory, flags);
+ }
+
+ #endregion
+
+ #region Filetype functions
+
+ /// <summary>
+ /// Orders FreeImage to analyze the bitmap signature.
+ /// In case the stream is not seekable, the stream will have been used
+ /// and must be recreated for loading.
+ /// </summary>
+ /// <param name="stream">Name of the stream to analyze.</param>
+ /// <returns>Type of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="stream"/> is null.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="stream"/> can not read.</exception>
+ public static FREE_IMAGE_FORMAT GetFileTypeFromStream(Stream stream)
+ {
+ if (stream == null)
+ {
+ throw new ArgumentNullException("stream");
+ }
+ if (!stream.CanRead)
+ {
+ throw new ArgumentException("stream is not capable of reading.");
+ }
+ // Wrap the stream if it cannot seek
+ stream = (stream.CanSeek) ? stream : new StreamWrapper(stream, true);
+ // Create a 'FreeImageIO' structure for the stream
+ FreeImageIO io = FreeImageStreamIO.io;
+ using (fi_handle handle = new fi_handle(stream))
+ {
+ return GetFileTypeFromHandle(ref io, handle, 0);
+ }
+ }
+
+ #endregion
+
+ #region Pixel access functions
+
+ /// <summary>
+ /// Retrieves an hBitmap for a FreeImage bitmap.
+ /// Call FreeHbitmap(IntPtr) to free the handle.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hdc">A reference device context.
+ /// Use IntPtr.Zero if no reference is available.</param>
+ /// <param name="unload">When true dib will be unloaded if the function succeeded.</param>
+ /// <returns>The hBitmap for the FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe IntPtr GetHbitmap(FIBITMAP dib, IntPtr hdc, bool unload)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ IntPtr hBitmap = IntPtr.Zero;
+ bool release = false;
+ IntPtr ppvBits = IntPtr.Zero;
+ // Check if we have destination
+ if (release = (hdc == IntPtr.Zero))
+ {
+ // We don't so request dc
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (hdc != IntPtr.Zero)
+ {
+ // Get pointer to the infoheader of the bitmap
+ IntPtr info = GetInfo(dib);
+ // Create a bitmap in the dc
+ hBitmap = CreateDIBSection(hdc, info, DIB_RGB_COLORS, out ppvBits, IntPtr.Zero, 0);
+ if (hBitmap != IntPtr.Zero && ppvBits != IntPtr.Zero)
+ {
+ // Copy the data into the dc
+ CopyMemory(ppvBits, GetBits(dib), (GetHeight(dib) * GetPitch(dib)));
+ // Success: we unload the bitmap
+ if (unload)
+ {
+ Unload(dib);
+ }
+ }
+ // We have to release the dc
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ return hBitmap;
+ }
+
+ /// <summary>
+ /// Returns an HBITMAP created by the <c>CreateDIBitmap()</c> function which in turn
+ /// has always the same color depth as the reference DC, which may be provided
+ /// through <paramref name="hdc"/>. The desktop DC will be used,
+ /// if <c>IntPtr.Zero</c> DC is specified.
+ /// Call <see cref="FreeImage.FreeHbitmap(IntPtr)"/> to free the handle.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="unload">When true the structure will be unloaded on success.
+ /// If the function failed and returned false, the bitmap was not unloaded.</param>
+ /// <returns>If the function succeeds, the return value is a handle to the
+ /// compatible bitmap. If the function fails, the return value is <see cref="IntPtr.Zero"/>.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static IntPtr GetBitmapForDevice(FIBITMAP dib, IntPtr hdc, bool unload)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ IntPtr hbitmap = IntPtr.Zero;
+ bool release = false;
+ if (release = (hdc == IntPtr.Zero))
+ {
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (hdc != IntPtr.Zero)
+ {
+ hbitmap = CreateDIBitmap(
+ hdc,
+ GetInfoHeader(dib),
+ CBM_INIT,
+ GetBits(dib),
+ GetInfo(dib),
+ DIB_RGB_COLORS);
+ if (unload)
+ {
+ Unload(dib);
+ }
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ return hbitmap;
+ }
+
+ /// <summary>
+ /// Creates a FreeImage DIB from a Device Context/Compatible Bitmap.
+ /// </summary>
+ /// <param name="hbitmap">Handle to the bitmap.</param>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="hbitmap"/> is null.</exception>
+ public unsafe static FIBITMAP CreateFromHbitmap(IntPtr hbitmap, IntPtr hdc)
+ {
+ if (hbitmap == IntPtr.Zero)
+ {
+ throw new ArgumentNullException("hbitmap");
+ }
+
+ FIBITMAP dib = new FIBITMAP();
+ BITMAP bm;
+ uint colors;
+ bool release;
+
+ if (GetObject(hbitmap, sizeof(BITMAP), (IntPtr)(&bm)) != 0)
+ {
+ dib = Allocate(bm.bmWidth, bm.bmHeight, bm.bmBitsPixel, 0, 0, 0);
+ if (!dib.IsNull)
+ {
+ colors = GetColorsUsed(dib);
+ if (release = (hdc == IntPtr.Zero))
+ {
+ hdc = GetDC(IntPtr.Zero);
+ }
+ if (GetDIBits(
+ hdc,
+ hbitmap,
+ 0,
+ (uint)bm.bmHeight,
+ GetBits(dib),
+ GetInfo(dib),
+ DIB_RGB_COLORS) != 0)
+ {
+ if (colors != 0)
+ {
+ BITMAPINFOHEADER* bmih = (BITMAPINFOHEADER*)GetInfo(dib);
+ bmih[0].biClrImportant = bmih[0].biClrUsed = colors;
+ }
+ }
+ else
+ {
+ UnloadEx(ref dib);
+ }
+ if (release)
+ {
+ ReleaseDC(IntPtr.Zero, hdc);
+ }
+ }
+ }
+
+ return dib;
+ }
+
+ /// <summary>
+ /// Frees a bitmap handle.
+ /// </summary>
+ /// <param name="hbitmap">Handle to a bitmap.</param>
+ /// <returns>True on success, false on failure.</returns>
+ public static bool FreeHbitmap(IntPtr hbitmap)
+ {
+ return DeleteObject(hbitmap);
+ }
+
+ #endregion
+
+ #region Bitmap information functions
+
+ /// <summary>
+ /// Retrieves a DIB's resolution in X-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The resolution in 'dots per inch'.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static uint GetResolutionX(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return (uint)(0.5d + 0.0254d * GetDotsPerMeterX(dib));
+ }
+
+ /// <summary>
+ /// Retrieves a DIB's resolution in Y-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The resolution in 'dots per inch'.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static uint GetResolutionY(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return (uint)(0.5d + 0.0254d * GetDotsPerMeterY(dib));
+ }
+
+ /// <summary>
+ /// Sets a DIB's resolution in X-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new resolution in 'dots per inch'.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static void SetResolutionX(FIBITMAP dib, uint res)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ SetDotsPerMeterX(dib, (uint)((double)res / 0.0254d + 0.5d));
+ }
+
+ /// <summary>
+ /// Sets a DIB's resolution in Y-direction measured in 'dots per inch' (DPI) and not in
+ /// 'dots per meter'.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="res">The new resolution in 'dots per inch'.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static void SetResolutionY(FIBITMAP dib, uint res)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ SetDotsPerMeterY(dib, (uint)((double)res / 0.0254d + 0.5d));
+ }
+
+ /// <summary>
+ /// Returns whether the image is a greyscale image or not.
+ /// The function scans all colors in the bitmaps palette for entries where
+ /// red, green and blue are not all the same (not a grey color).
+ /// Supports 1-, 4- and 8-bit bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>True if the image is a greyscale image, else false.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe bool IsGreyscaleImage(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ bool result = true;
+ uint bpp = GetBPP(dib);
+ switch (bpp)
+ {
+ case 1:
+ case 4:
+ case 8:
+ RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
+ uint paletteLength = GetColorsUsed(dib);
+ for (int i = 0; i < paletteLength; i++)
+ {
+ if (palette[i].rgbRed != palette[i].rgbGreen ||
+ palette[i].rgbRed != palette[i].rgbBlue)
+ {
+ result = false;
+ break;
+ }
+ }
+ break;
+ default:
+ result = false;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns a structure that represents the palette of a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>A structure representing the bitmaps palette.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static Palette GetPaletteEx(FIBITMAP dib)
+ {
+ return new Palette(dib);
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFOHEADER"/> structure of a FreeImage bitmap.
+ /// The structure is a copy, so changes will have no effect on
+ /// the bitmap itself.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="BITMAPINFOHEADER"/> structure of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe BITMAPINFOHEADER GetInfoHeaderEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return *(BITMAPINFOHEADER*)GetInfoHeader(dib);
+ }
+
+ /// <summary>
+ /// Returns the <see cref="BITMAPINFO"/> structure of a FreeImage bitmap.
+ /// The structure is a copy, so changes will have no effect on
+ /// the bitmap itself.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="BITMAPINFO"/> structure of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static BITMAPINFO GetInfoEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ BITMAPINFO result = new BITMAPINFO();
+ result.bmiHeader = GetInfoHeaderEx(dib);
+ IntPtr ptr = GetPalette(dib);
+ if (ptr == IntPtr.Zero)
+ {
+ result.bmiColors = new RGBQUAD[0];
+ }
+ else
+ {
+ result.bmiColors = new MemoryArray<RGBQUAD>(ptr, (int)result.bmiHeader.biClrUsed).Data;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the pixelformat of the bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns><see cref="System.Drawing.Imaging.PixelFormat"/> of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static PixelFormat GetPixelFormat(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ PixelFormat result = PixelFormat.Undefined;
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (GetBPP(dib))
+ {
+ case 1:
+ result = PixelFormat.Format1bppIndexed;
+ break;
+ case 4:
+ result = PixelFormat.Format4bppIndexed;
+ break;
+ case 8:
+ result = PixelFormat.Format8bppIndexed;
+ break;
+ case 16:
+ if ((GetBlueMask(dib) == FI16_565_BLUE_MASK) &&
+ (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
+ (GetRedMask(dib) == FI16_565_RED_MASK))
+ {
+ result = PixelFormat.Format16bppRgb565;
+ }
+ if ((GetBlueMask(dib) == FI16_555_BLUE_MASK) &&
+ (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
+ (GetRedMask(dib) == FI16_555_RED_MASK))
+ {
+ result = PixelFormat.Format16bppRgb555;
+ }
+ break;
+ case 24:
+ result = PixelFormat.Format24bppRgb;
+ break;
+ case 32:
+ result = PixelFormat.Format32bppArgb;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieves all parameters needed to create a new FreeImage bitmap from
+ /// the format of a .NET <see cref="System.Drawing.Image"/>.
+ /// </summary>
+ /// <param name="format">The <see cref="System.Drawing.Imaging.PixelFormat"/>
+ /// of the .NET <see cref="System.Drawing.Image"/>.</param>
+ /// <param name="type">Returns the type used for the new bitmap.</param>
+ /// <param name="bpp">Returns the color depth for the new bitmap.</param>
+ /// <param name="red_mask">Returns the red_mask for the new bitmap.</param>
+ /// <param name="green_mask">Returns the green_mask for the new bitmap.</param>
+ /// <param name="blue_mask">Returns the blue_mask for the new bitmap.</param>
+ /// <returns>True in case a matching conversion exists; else false.
+ /// </returns>
+ public static bool GetFormatParameters(
+ PixelFormat format,
+ out FREE_IMAGE_TYPE type,
+ out uint bpp,
+ out uint red_mask,
+ out uint green_mask,
+ out uint blue_mask)
+ {
+ bool result = false;
+ type = FREE_IMAGE_TYPE.FIT_UNKNOWN;
+ bpp = 0;
+ red_mask = 0;
+ green_mask = 0;
+ blue_mask = 0;
+ switch (format)
+ {
+ case PixelFormat.Format1bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 1;
+ result = true;
+ break;
+ case PixelFormat.Format4bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 4;
+ result = true;
+ break;
+ case PixelFormat.Format8bppIndexed:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 8;
+ result = true;
+ break;
+ case PixelFormat.Format16bppRgb565:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 16;
+ red_mask = FI16_565_RED_MASK;
+ green_mask = FI16_565_GREEN_MASK;
+ blue_mask = FI16_565_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format16bppRgb555:
+ case PixelFormat.Format16bppArgb1555:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 16;
+ red_mask = FI16_555_RED_MASK;
+ green_mask = FI16_555_GREEN_MASK;
+ blue_mask = FI16_555_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format24bppRgb:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 24;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format32bppRgb:
+ case PixelFormat.Format32bppArgb:
+ case PixelFormat.Format32bppPArgb:
+ type = FREE_IMAGE_TYPE.FIT_BITMAP;
+ bpp = 32;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ result = true;
+ break;
+ case PixelFormat.Format16bppGrayScale:
+ type = FREE_IMAGE_TYPE.FIT_UINT16;
+ bpp = 16;
+ result = true;
+ break;
+ case PixelFormat.Format48bppRgb:
+ type = FREE_IMAGE_TYPE.FIT_RGB16;
+ bpp = 48;
+ result = true;
+ break;
+ case PixelFormat.Format64bppArgb:
+ case PixelFormat.Format64bppPArgb:
+ type = FREE_IMAGE_TYPE.FIT_RGBA16;
+ bpp = 64;
+ result = true;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the <see cref="FREE_IMAGE_FORMAT"/> for the specified
+ /// <see cref="ImageFormat"/>.
+ /// </summary>
+ /// <param name="imageFormat">The <see cref="ImageFormat"/>
+ /// for which to return the corresponding <see cref="FREE_IMAGE_FORMAT"/>.</param>
+ /// <returns>The <see cref="FREE_IMAGE_FORMAT"/> for the specified
+ /// <see cref="ImageFormat"/></returns>
+ public static FREE_IMAGE_FORMAT GetFormat(ImageFormat imageFormat)
+ {
+ if (imageFormat != null)
+ {
+ if (imageFormat.Equals(ImageFormat.Bmp))
+ return FREE_IMAGE_FORMAT.FIF_BMP;
+ if (imageFormat.Equals(ImageFormat.Gif))
+ return FREE_IMAGE_FORMAT.FIF_GIF;
+ if (imageFormat.Equals(ImageFormat.Icon))
+ return FREE_IMAGE_FORMAT.FIF_ICO;
+ if (imageFormat.Equals(ImageFormat.Jpeg))
+ return FREE_IMAGE_FORMAT.FIF_JPEG;
+ if (imageFormat.Equals(ImageFormat.Png))
+ return FREE_IMAGE_FORMAT.FIF_PNG;
+ if (imageFormat.Equals(ImageFormat.Tiff))
+ return FREE_IMAGE_FORMAT.FIF_TIFF;
+ }
+ return FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ }
+
+ /// <summary>
+ /// Retrieves all parameters needed to create a new FreeImage bitmap from
+ /// raw bits <see cref="System.Drawing.Image"/>.
+ /// </summary>
+ /// <param name="type">The <see cref="FREE_IMAGE_TYPE"/>
+ /// of the data in memory.</param>
+ /// <param name="bpp">The color depth for the data.</param>
+ /// <param name="red_mask">Returns the red_mask for the data.</param>
+ /// <param name="green_mask">Returns the green_mask for the data.</param>
+ /// <param name="blue_mask">Returns the blue_mask for the data.</param>
+ /// <returns>True in case a matching conversion exists; else false.
+ /// </returns>
+ public static bool GetTypeParameters(
+ FREE_IMAGE_TYPE type,
+ int bpp,
+ out uint red_mask,
+ out uint green_mask,
+ out uint blue_mask)
+ {
+ bool result = false;
+ red_mask = 0;
+ green_mask = 0;
+ blue_mask = 0;
+ switch (type)
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+ switch (bpp)
+ {
+ case 1:
+ case 4:
+ case 8:
+ result = true;
+ break;
+ case 16:
+ result = true;
+ red_mask = FI16_555_RED_MASK;
+ green_mask = FI16_555_GREEN_MASK;
+ blue_mask = FI16_555_BLUE_MASK;
+ break;
+ case 24:
+ case 32:
+ result = true;
+ red_mask = FI_RGBA_RED_MASK;
+ green_mask = FI_RGBA_GREEN_MASK;
+ blue_mask = FI_RGBA_BLUE_MASK;
+ break;
+ }
+ break;
+ case FREE_IMAGE_TYPE.FIT_UNKNOWN:
+ break;
+ default:
+ result = true;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Compares two FreeImage bitmaps.
+ /// </summary>
+ /// <param name="dib1">The first bitmap to compare.</param>
+ /// <param name="dib2">The second bitmap to compare.</param>
+ /// <param name="flags">Determines which components of the bitmaps will be compared.</param>
+ /// <returns>True in case both bitmaps match the compare conditions, false otherwise.</returns>
+ public static bool Compare(FIBITMAP dib1, FIBITMAP dib2, FREE_IMAGE_COMPARE_FLAGS flags)
+ {
+ // Check whether one bitmap is null
+ if (dib1.IsNull ^ dib2.IsNull)
+ {
+ return false;
+ }
+ // Check whether both pointers are the same
+ if (dib1 == dib2)
+ {
+ return true;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.HEADER) > 0) && (!CompareHeader(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.PALETTE) > 0) && (!ComparePalette(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.DATA) > 0) && (!CompareData(dib1, dib2)))
+ {
+ return false;
+ }
+ if (((flags & FREE_IMAGE_COMPARE_FLAGS.METADATA) > 0) && (!CompareMetadata(dib1, dib2)))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ private static unsafe bool CompareHeader(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ IntPtr i1 = GetInfoHeader(dib1);
+ IntPtr i2 = GetInfoHeader(dib2);
+ return CompareMemory((void*)i1, (void*)i2, sizeof(BITMAPINFOHEADER));
+ }
+
+ private static unsafe bool ComparePalette(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ IntPtr pal1 = GetPalette(dib1), pal2 = GetPalette(dib2);
+ bool hasPalette1 = pal1 != IntPtr.Zero;
+ bool hasPalette2 = pal2 != IntPtr.Zero;
+ if (hasPalette1 ^ hasPalette2)
+ {
+ return false;
+ }
+ if (!hasPalette1)
+ {
+ return true;
+ }
+ uint colors = GetColorsUsed(dib1);
+ if (colors != GetColorsUsed(dib2))
+ {
+ return false;
+ }
+ return CompareMemory((void*)pal1, (void*)pal2, sizeof(RGBQUAD) * colors);
+ }
+
+ private static unsafe bool CompareData(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ uint width = GetWidth(dib1);
+ if (width != GetWidth(dib2))
+ {
+ return false;
+ }
+ uint height = GetHeight(dib1);
+ if (height != GetHeight(dib2))
+ {
+ return false;
+ }
+ uint bpp = GetBPP(dib1);
+ if (bpp != GetBPP(dib2))
+ {
+ return false;
+ }
+ if (GetColorType(dib1) != GetColorType(dib2))
+ {
+ return false;
+ }
+ FREE_IMAGE_TYPE type = GetImageType(dib1);
+ if (type != GetImageType(dib2))
+ {
+ return false;
+ }
+ if (GetRedMask(dib1) != GetRedMask(dib2))
+ {
+ return false;
+ }
+ if (GetGreenMask(dib1) != GetGreenMask(dib2))
+ {
+ return false;
+ }
+ if (GetBlueMask(dib1) != GetBlueMask(dib2))
+ {
+ return false;
+ }
+
+ byte* ptr1, ptr2;
+ int fullBytes;
+ int shift;
+ uint line = GetLine(dib1);
+
+ if (type == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (bpp)
+ {
+ case 32:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 24:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 16:
+ short* sPtr1, sPtr2;
+ short mask = (short)(GetRedMask(dib1) | GetGreenMask(dib1) | GetBlueMask(dib1));
+ if (mask == -1)
+ {
+ for (int i = 0; i < height; i++)
+ {
+ sPtr1 = (short*)GetScanLine(dib1, i);
+ sPtr2 = (short*)GetScanLine(dib2, i);
+ if (!CompareMemory(sPtr1, sPtr1, line))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ {
+ sPtr1 = (short*)GetScanLine(dib1, i);
+ sPtr2 = (short*)GetScanLine(dib2, i);
+ for (int x = 0; x < width; x++)
+ {
+ if ((sPtr1[x] & mask) != (sPtr2[x] & mask))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ break;
+ case 8:
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ break;
+ case 4:
+ fullBytes = (int)width / 2;
+ shift = (width % 2) == 0 ? 8 : 4;
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (fullBytes != 0)
+ {
+ if (!CompareMemory(ptr1, ptr2, fullBytes))
+ {
+ return false;
+ }
+ ptr1 += fullBytes;
+ ptr2 += fullBytes;
+ }
+ if (shift != 8)
+ {
+ if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
+ {
+ return false;
+ }
+ }
+ }
+ break;
+ case 1:
+ fullBytes = (int)width / 8;
+ shift = 8 - ((int)width % 8);
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (fullBytes != 0)
+ {
+ if (!CompareMemory(ptr1, ptr2, fullBytes))
+ {
+ return false;
+ }
+ ptr1 += fullBytes;
+ ptr2 += fullBytes;
+ }
+ if (shift != 8)
+ {
+ if ((ptr1[0] >> shift) != (ptr2[0] >> shift))
+ {
+ return false;
+ }
+ }
+ }
+ break;
+ default:
+ throw new NotSupportedException("Only 1, 4, 8, 16, 24 and 32 bpp bitmaps are supported.");
+ }
+ }
+ else
+ {
+ for (int i = 0; i < height; i++)
+ {
+ ptr1 = (byte*)GetScanLine(dib1, i);
+ ptr2 = (byte*)GetScanLine(dib2, i);
+ if (!CompareMemory(ptr1, ptr2, line))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static bool CompareMetadata(FIBITMAP dib1, FIBITMAP dib2)
+ {
+ MetadataTag tag1, tag2;
+
+ foreach (FREE_IMAGE_MDMODEL metadataModel in FREE_IMAGE_MDMODELS)
+ {
+ if (GetMetadataCount(metadataModel, dib1) !=
+ GetMetadataCount(metadataModel, dib2))
+ {
+ return false;
+ }
+ if (GetMetadataCount(metadataModel, dib1) == 0)
+ {
+ continue;
+ }
+
+ FIMETADATA mdHandle = FindFirstMetadata(metadataModel, dib1, out tag1);
+ if (mdHandle.IsNull)
+ {
+ continue;
+ }
+ do
+ {
+ if ((!GetMetadata(metadataModel, dib2, tag1.Key, out tag2)) || (tag1 != tag2))
+ {
+ FindCloseMetadata(mdHandle);
+ return false;
+ }
+ }
+ while (FindNextMetadata(mdHandle, out tag1));
+ FindCloseMetadata(mdHandle);
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Returns the FreeImage bitmap's transparency table.
+ /// The array is empty in case the bitmap has no transparency table.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>The FreeImage bitmap's transparency table.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe byte[] GetTransparencyTableEx(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ uint count = GetTransparencyCount(dib);
+ byte[] result = new byte[count];
+ byte* ptr = (byte*)GetTransparencyTable(dib);
+ fixed (byte* dst = result)
+ {
+ CopyMemory(dst, ptr, count);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Set the FreeImage bitmap's transparency table. Only affects palletised bitmaps.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="table">The FreeImage bitmap's new transparency table.</param>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> or <paramref name="table"/> is null.</exception>
+ public static void SetTransparencyTable(FIBITMAP dib, byte[] table)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ if (table == null)
+ {
+ throw new ArgumentNullException("table");
+ }
+ SetTransparencyTable(dib, table, table.Length);
+ }
+
+ /// <summary>
+ /// This function returns the number of unique colors actually used by the
+ /// specified 1-, 4-, 8-, 16-, 24- or 32-bit image. This might be different from
+ /// what function FreeImage_GetColorsUsed() returns, which actually returns the
+ /// palette size for palletised images. Works for
+ /// <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/> type images only.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Returns the number of unique colors used by the image specified or
+ /// zero, if the image type cannot be handled.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe int GetUniqueColors(FIBITMAP dib)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ int result = 0;
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ BitArray bitArray;
+ int uniquePalEnts;
+ int hashcode;
+ byte[] lut;
+ int width = (int)GetWidth(dib);
+ int height = (int)GetHeight(dib);
+
+ switch (GetBPP(dib))
+ {
+ case 1:
+
+ result = 1;
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ break;
+ }
+
+ if ((*(byte*)GetScanLine(dib, 0) & 0x80) == 0)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ int mask = 0x80;
+ for (int x = 0; x < width; x++)
+ {
+ if ((scanline[x / 8] & mask) > 0)
+ {
+ return 2;
+ }
+ mask = (mask == 0x1) ? 0x80 : (mask >> 1);
+ }
+ }
+ }
+ else
+ {
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ int mask = 0x80;
+ for (int x = 0; x < width; x++)
+ {
+ if ((scanline[x / 8] & mask) == 0)
+ {
+ return 2;
+ }
+ mask = (mask == 0x1) ? 0x80 : (mask >> 1);
+ }
+ }
+ }
+ break;
+
+ case 4:
+
+ bitArray = new BitArray(0x10);
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ result = 1;
+ break;
+ }
+
+ for (int y = 0; (y < height) && (result < uniquePalEnts); y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ bool top = true;
+ for (int x = 0; (x < width) && (result < uniquePalEnts); x++)
+ {
+ if (top)
+ {
+ hashcode = lut[scanline[x / 2] >> 4];
+ }
+ else
+ {
+ hashcode = lut[scanline[x / 2] & 0xF];
+ }
+ top = !top;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 8:
+
+ bitArray = new BitArray(0x100);
+ lut = CreateShrunkenPaletteLUT(dib, out uniquePalEnts);
+ if (uniquePalEnts == 1)
+ {
+ result = 1;
+ break;
+ }
+
+ for (int y = 0; (y < height) && (result < uniquePalEnts); y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ for (int x = 0; (x < width) && (result < uniquePalEnts); x++)
+ {
+ hashcode = lut[scanline[x]];
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 16:
+
+ bitArray = new BitArray(0x10000);
+
+ for (int y = 0; y < height; y++)
+ {
+ short* scanline = (short*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline++)
+ {
+ hashcode = *scanline;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 24:
+
+ bitArray = new BitArray(0x1000000);
+
+ for (int y = 0; y < height; y++)
+ {
+ byte* scanline = (byte*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline += 3)
+ {
+ hashcode = *((int*)scanline) & 0x00FFFFFF;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+
+ case 32:
+
+ bitArray = new BitArray(0x1000000);
+
+ for (int y = 0; y < height; y++)
+ {
+ int* scanline = (int*)GetScanLine(dib, y);
+ for (int x = 0; x < width; x++, scanline++)
+ {
+ hashcode = *scanline & 0x00FFFFFF;
+ if (!bitArray[hashcode])
+ {
+ bitArray[hashcode] = true;
+ result++;
+ }
+ }
+ }
+ break;
+ }
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Verifies whether the FreeImage bitmap is 16bit 555.
+ /// </summary>
+ /// <param name="dib">The FreeImage bitmap to verify.</param>
+ /// <returns><b>true</b> if the bitmap is RGB16-555; otherwise <b>false</b>.</returns>
+ public static bool IsRGB555(FIBITMAP dib)
+ {
+ return ((GetRedMask(dib) == FI16_555_RED_MASK) &&
+ (GetGreenMask(dib) == FI16_555_GREEN_MASK) &&
+ (GetBlueMask(dib) == FI16_555_BLUE_MASK));
+ }
+
+ /// <summary>
+ /// Verifies whether the FreeImage bitmap is 16bit 565.
+ /// </summary>
+ /// <param name="dib">The FreeImage bitmap to verify.</param>
+ /// <returns><b>true</b> if the bitmap is RGB16-565; otherwise <b>false</b>.</returns>
+ public static bool IsRGB565(FIBITMAP dib)
+ {
+ return ((GetRedMask(dib) == FI16_565_RED_MASK) &&
+ (GetGreenMask(dib) == FI16_565_GREEN_MASK) &&
+ (GetBlueMask(dib) == FI16_565_BLUE_MASK));
+ }
+
+ #endregion
+
+ #region ICC profile functions
+
+ /// <summary>
+ /// Creates a new ICC-Profile for a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <returns>The new ICC-Profile of the bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data)
+ {
+ return new FIICCPROFILE(dib, data);
+ }
+
+ /// <summary>
+ /// Creates a new ICC-Profile for a FreeImage bitmap.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="data">The data of the new ICC-Profile.</param>
+ /// <param name="size">The number of bytes of <paramref name="data"/> to use.</param>
+ /// <returns>The new ICC-Profile of the FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIICCPROFILE CreateICCProfileEx(FIBITMAP dib, byte[] data, int size)
+ {
+ return new FIICCPROFILE(dib, data, size);
+ }
+
+ #endregion
+
+ #region Conversion functions
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ threshold,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting
+ /// with <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_DITHER ditherMethod)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ ditherMethod,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ false);
+ }
+
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_QUANTIZE quantizationMethod)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ quantizationMethod,
+ false);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ threshold,
+ FREE_IMAGE_DITHER.FID_FS,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_DITHER ditherMethod,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ ditherMethod,
+ FREE_IMAGE_QUANTIZE.FIQ_WUQUANT,
+ unloadSource);
+ }
+
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ FREE_IMAGE_QUANTIZE quantizationMethod,
+ bool unloadSource)
+ {
+ return ConvertColorDepth(
+ dib,
+ conversion,
+ 128,
+ FREE_IMAGE_DITHER.FID_FS,
+ quantizationMethod,
+ unloadSource);
+ }
+
+ /// <summary>
+ /// Converts a FreeImage bitmap from one color depth to another.
+ /// If the conversion fails the original FreeImage bitmap is returned.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="conversion">The desired output format.</param>
+ /// <param name="threshold">Threshold value when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD"/>.</param>
+ /// <param name="ditherMethod">Dither algorithm when converting with
+ /// <see cref="FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER"/>.</param>
+ /// <param name="quantizationMethod">The quantization algorithm for conversion to 8-bit color depth.</param>
+ /// <param name="unloadSource">When true the structure will be unloaded on success.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ internal static FIBITMAP ConvertColorDepth(
+ FIBITMAP dib,
+ FREE_IMAGE_COLOR_DEPTH conversion,
+ byte threshold,
+ FREE_IMAGE_DITHER ditherMethod,
+ FREE_IMAGE_QUANTIZE quantizationMethod,
+ bool unloadSource)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FIBITMAP result = new FIBITMAP();
+ FIBITMAP dibTemp = new FIBITMAP();
+ uint bpp = GetBPP(dib);
+ bool reorderPalette = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_REORDER_PALETTE) > 0);
+ bool forceGreyscale = ((conversion & FREE_IMAGE_COLOR_DEPTH.FICD_FORCE_GREYSCALE) > 0);
+
+ if (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ switch (conversion & (FREE_IMAGE_COLOR_DEPTH)0xFF)
+ {
+ case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_THRESHOLD:
+
+ if (bpp != 1)
+ {
+ if (forceGreyscale)
+ {
+ result = Threshold(dib, threshold);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ result = Threshold(dib, threshold);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_01_BPP_DITHER:
+
+ if (bpp != 1)
+ {
+ if (forceGreyscale)
+ {
+ result = Dither(dib, ditherMethod);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 2, null, 1);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ result = Dither(dib, ditherMethod);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_04_BPP:
+
+ if (bpp != 4)
+ {
+ // Special case when 1bpp and FIC_PALETTE
+ if (forceGreyscale ||
+ ((bpp == 1) && (GetColorType(dib) == FREE_IMAGE_COLOR_TYPE.FIC_PALETTE)))
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo4Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantizeEx(dibTemp, quantizationMethod, 16, null, 4);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) ||
+ (reorderPalette && isGreyscale))
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo4Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ }
+
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP:
+
+ if (bpp != 8)
+ {
+ if (forceGreyscale)
+ {
+ result = ConvertToGreyscale(dib);
+ }
+ else
+ {
+ dibTemp = ConvertTo24Bits(dib);
+ result = ColorQuantize(dibTemp, quantizationMethod);
+ Unload(dibTemp);
+ }
+ }
+ else
+ {
+ bool isGreyscale = IsGreyscaleImage(dib);
+ if ((forceGreyscale && (!isGreyscale)) || (reorderPalette && isGreyscale))
+ {
+ result = ConvertToGreyscale(dib);
+ }
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP_555:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo16Bits555(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 16 || GetRedMask(dib) != FI16_555_RED_MASK || GetGreenMask(dib) != FI16_555_GREEN_MASK || GetBlueMask(dib) != FI16_555_BLUE_MASK)
+ {
+ result = ConvertTo16Bits555(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_16_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo16Bits565(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 16 || GetRedMask(dib) != FI16_565_RED_MASK || GetGreenMask(dib) != FI16_565_GREEN_MASK || GetBlueMask(dib) != FI16_565_BLUE_MASK)
+ {
+ result = ConvertTo16Bits565(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo24Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 24)
+ {
+ result = ConvertTo24Bits(dib);
+ }
+ break;
+
+ case FREE_IMAGE_COLOR_DEPTH.FICD_32_BPP:
+
+ if (forceGreyscale)
+ {
+ dibTemp = ConvertToGreyscale(dib);
+ result = ConvertTo32Bits(dibTemp);
+ Unload(dibTemp);
+ }
+ else if (bpp != 32)
+ {
+ result = ConvertTo32Bits(dib);
+ }
+ break;
+ }
+ }
+
+ if (result.IsNull)
+ {
+ return dib;
+ }
+ if (unloadSource)
+ {
+ Unload(dib);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/>
+ /// method that provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <param name="minColorDepth"><b>true</b> to create a bitmap with the smallest possible
+ /// color depth for the specified <paramref name="PaletteSize"/>.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, RGBQUAD[] ReservePalette, bool minColorDepth)
+ {
+ FIBITMAP result;
+ if (minColorDepth)
+ {
+ int bpp;
+ if (PaletteSize >= 256)
+ bpp = 8;
+ else if (PaletteSize > 2)
+ bpp = 4;
+ else
+ bpp = 1;
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, bpp);
+ }
+ else
+ {
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, ReservePalette, 8);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// ColorQuantizeEx is an extension to the <see cref="ColorQuantize(FIBITMAP, FREE_IMAGE_QUANTIZE)"/>
+ /// method that provides additional options used to quantize a 24-bit image to any
+ /// number of colors (up to 256), as well as quantize a 24-bit image using a
+ /// partial or full provided palette.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="quantize">Specifies the color reduction algorithm to be used.</param>
+ /// <param name="PaletteSize">Size of the desired output palette.</param>
+ /// <param name="ReservePalette">The provided palette.</param>
+ /// <param name="bpp">The desired color depth of the created image.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP ColorQuantizeEx(FIBITMAP dib, FREE_IMAGE_QUANTIZE quantize, int PaletteSize, RGBQUAD[] ReservePalette, int bpp)
+ {
+ unsafe
+ {
+ FIBITMAP result = FIBITMAP.Zero;
+ FIBITMAP temp = FIBITMAP.Zero;
+ int reservedSize = (ReservePalette == null) ? 0 : ReservePalette.Length;
+
+ if (bpp == 8)
+ {
+ result = ColorQuantizeEx(dib, quantize, PaletteSize, reservedSize, ReservePalette);
+ }
+ else if (bpp == 4)
+ {
+ temp = ColorQuantizeEx(dib, quantize, Math.Min(16, PaletteSize), reservedSize, ReservePalette);
+ if (!temp.IsNull)
+ {
+ result = Allocate((int)GetWidth(temp), (int)GetHeight(temp), 4, 0, 0, 0);
+ CloneMetadata(result, temp);
+ CopyMemory(GetPalette(result), GetPalette(temp), sizeof(RGBQUAD) * 16);
+
+ for (int y = (int)GetHeight(temp) - 1; y >= 0; y--)
+ {
+ Scanline<byte> srcScanline = new Scanline<byte>(temp, y);
+ Scanline<FI4BIT> dstScanline = new Scanline<FI4BIT>(result, y);
+
+ for (int x = (int)GetWidth(temp) - 1; x >= 0; x--)
+ {
+ dstScanline[x] = srcScanline[x];
+ }
+ }
+ }
+ }
+ else if (bpp == 1)
+ {
+ temp = ColorQuantizeEx(dib, quantize, 2, reservedSize, ReservePalette);
+ if (!temp.IsNull)
+ {
+ result = Allocate((int)GetWidth(temp), (int)GetHeight(temp), 1, 0, 0, 0);
+ CloneMetadata(result, temp);
+ CopyMemory(GetPalette(result), GetPalette(temp), sizeof(RGBQUAD) * 2);
+
+ for (int y = (int)GetHeight(temp) - 1; y >= 0; y--)
+ {
+ Scanline<byte> srcScanline = new Scanline<byte>(temp, y);
+ Scanline<FI1BIT> dstScanline = new Scanline<FI1BIT>(result, y);
+
+ for (int x = (int)GetWidth(temp) - 1; x >= 0; x--)
+ {
+ dstScanline[x] = srcScanline[x];
+ }
+ }
+ }
+ }
+
+ UnloadEx(ref temp);
+ return result;
+ }
+ }
+
+ #endregion
+
+ #region Metadata
+
+ /// <summary>
+ /// Copies metadata from one FreeImage bitmap to another.
+ /// </summary>
+ /// <param name="src">Source FreeImage bitmap containing the metadata.</param>
+ /// <param name="dst">FreeImage bitmap to copy the metadata to.</param>
+ /// <param name="flags">Flags to switch different copy modes.</param>
+ /// <returns>Returns -1 on failure else the number of copied tags.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="src"/> or <paramref name="dst"/> is null.</exception>
+ public static int CloneMetadataEx(FIBITMAP src, FIBITMAP dst, FREE_IMAGE_METADATA_COPY flags)
+ {
+ if (src.IsNull)
+ {
+ throw new ArgumentNullException("src");
+ }
+ if (dst.IsNull)
+ {
+ throw new ArgumentNullException("dst");
+ }
+
+ FITAG tag = new FITAG(), tag2 = new FITAG();
+ int copied = 0;
+
+ // Clear all existing metadata
+ if ((flags & FREE_IMAGE_METADATA_COPY.CLEAR_EXISTING) > 0)
+ {
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ if (!SetMetadata(model, dst, null, tag))
+ {
+ return -1;
+ }
+ }
+ }
+
+ bool keep = !((flags & FREE_IMAGE_METADATA_COPY.REPLACE_EXISTING) > 0);
+
+ foreach (FREE_IMAGE_MDMODEL model in FREE_IMAGE_MDMODELS)
+ {
+ FIMETADATA mData = FindFirstMetadata(model, src, out tag);
+ if (mData.IsNull) continue;
+ do
+ {
+ string key = GetTagKey(tag);
+ if (!(keep && GetMetadata(model, dst, key, out tag2)))
+ {
+ if (SetMetadata(model, dst, key, tag))
+ {
+ copied++;
+ }
+ }
+ }
+ while (FindNextMetadata(mData, out tag));
+ FindCloseMetadata(mData);
+ }
+
+ return copied;
+ }
+
+ /// <summary>
+ /// Returns the comment of a JPEG, PNG or GIF image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <returns>Comment of the FreeImage bitmp, or null in case no comment exists.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static string GetImageComment(FIBITMAP dib)
+ {
+ string result = null;
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FITAG tag;
+ if (GetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", out tag))
+ {
+ MetadataTag metadataTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ result = metadataTag.Value as string;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Sets the comment of a JPEG, PNG or GIF image.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="comment">New comment of the FreeImage bitmap.
+ /// Use null to remove the comment.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool SetImageComment(FIBITMAP dib, string comment)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ bool result;
+ if (comment != null)
+ {
+ FITAG tag = CreateTag();
+ MetadataTag metadataTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ metadataTag.Value = comment;
+ result = SetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", tag);
+ DeleteTag(tag);
+ }
+ else
+ {
+ result = SetMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, "Comment", FITAG.Zero);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Retrieve a metadata attached to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="model">The metadata model to look for.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The metadata field name.</param>
+ /// <param name="tag">A <see cref="MetadataTag"/> structure returned by the function.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool GetMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ string key,
+ out MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FITAG _tag;
+ bool result;
+ if (GetMetadata(model, dib, key, out _tag))
+ {
+ tag = new MetadataTag(_tag, model);
+ result = true;
+ }
+ else
+ {
+ tag = null;
+ result = false;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Attach a new metadata tag to a FreeImage bitmap.
+ /// </summary>
+ /// <param name="model">The metadata model used to store the tag.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="key">The tag field name.</param>
+ /// <param name="tag">The <see cref="MetadataTag"/> to be attached.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static bool SetMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ string key,
+ MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ return SetMetadata(model, dib, key, tag.tag);
+ }
+
+ /// <summary>
+ /// Provides information about the first instance of a tag that matches the metadata model.
+ /// </summary>
+ /// <param name="model">The model to match.</param>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Unique search handle that can be used to call FindNextMetadata or FindCloseMetadata.
+ /// Null if the metadata model does not exist.</returns>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static FIMETADATA FindFirstMetadata(
+ FREE_IMAGE_MDMODEL model,
+ FIBITMAP dib,
+ out MetadataTag tag)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+ FITAG _tag;
+ FIMETADATA result = FindFirstMetadata(model, dib, out _tag);
+ if (result.IsNull)
+ {
+ tag = null;
+ return result;
+ }
+ tag = new MetadataTag(_tag, model);
+ if (metaDataSearchHandler.ContainsKey(result))
+ {
+ metaDataSearchHandler[result] = model;
+ }
+ else
+ {
+ metaDataSearchHandler.Add(result, model);
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Find the next tag, if any, that matches the metadata model argument in a previous call
+ /// to FindFirstMetadata, and then alters the tag object contents accordingly.
+ /// </summary>
+ /// <param name="mdhandle">Unique search handle provided by FindFirstMetadata.</param>
+ /// <param name="tag">Tag that matches the metadata model.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ public static bool FindNextMetadata(FIMETADATA mdhandle, out MetadataTag tag)
+ {
+ FITAG _tag;
+ bool result;
+ if (FindNextMetadata(mdhandle, out _tag))
+ {
+ tag = new MetadataTag(_tag, metaDataSearchHandler[mdhandle]);
+ result = true;
+ }
+ else
+ {
+ tag = null;
+ result = false;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Closes the specified metadata search handle and releases associated resources.
+ /// </summary>
+ /// <param name="mdhandle">The handle to close.</param>
+ public static void FindCloseMetadata(FIMETADATA mdhandle)
+ {
+ if (metaDataSearchHandler.ContainsKey(mdhandle))
+ {
+ metaDataSearchHandler.Remove(mdhandle);
+ }
+ FindCloseMetadata_(mdhandle);
+ }
+
+ /// <summary>
+ /// This dictionary links FIMETADATA handles and FREE_IMAGE_MDMODEL models.
+ /// </summary>
+ private static Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL> metaDataSearchHandler
+ = new Dictionary<FIMETADATA, FREE_IMAGE_MDMODEL>(1);
+
+ #endregion
+
+ #region Rotation and Flipping
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90�.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Rotate(FIBITMAP dib, double angle)
+ {
+ return Rotate(dib, angle, IntPtr.Zero);
+ }
+
+ /// <summary>
+ /// This function rotates a 1-, 8-bit greyscale or a 24-, 32-bit color image by means of 3 shears.
+ /// 1-bit images rotation is limited to integer multiple of 90�.
+ /// <c>null</c> is returned for other values.
+ /// </summary>
+ /// <typeparam name="T">The type of the color to use as background.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <param name="backgroundColor">The color used used to fill the bitmap's background.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ public static FIBITMAP Rotate<T>(FIBITMAP dib, double angle, T? backgroundColor) where T : struct
+ {
+ if (backgroundColor.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { backgroundColor.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return Rotate(dib, angle, handle.AddrOfPinnedObject());
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return Rotate(dib, angle, IntPtr.Zero);
+ }
+ }
+
+ /// <summary>
+ /// Rotates a 4-bit color FreeImage bitmap.
+ /// Allowed values for <paramref name="angle"/> are 90, 180 and 270.
+ /// In case <paramref name="angle"/> is 0 or 360 a clone is returned.
+ /// 0 is returned for other values or in case the rotation fails.
+ /// </summary>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="angle">The angle of rotation.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function is kind of temporary due to FreeImage's lack of
+ /// rotating 4-bit images. It's particularly used by <see cref="FreeImageBitmap"/>'s
+ /// method RotateFlip. This function will be removed as soon as FreeImage
+ /// supports rotating 4-bit images.
+ /// </remarks>
+ /// <exception cref="ArgumentNullException">
+ /// <paramref name="dib"/> is null.</exception>
+ public static unsafe FIBITMAP Rotate4bit(FIBITMAP dib, double angle)
+ {
+ if (dib.IsNull)
+ {
+ throw new ArgumentNullException("dib");
+ }
+
+ FIBITMAP result = new FIBITMAP();
+ int ang = (int)angle;
+
+ if ((GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) &&
+ (GetBPP(dib) == 4) &&
+ ((ang % 90) == 0))
+ {
+ int width, height, xOrg, yOrg;
+ Scanline<FI4BIT>[] src, dst;
+ width = (int)GetWidth(dib);
+ height = (int)GetHeight(dib);
+ byte index = 0;
+ switch (ang)
+ {
+ case 90:
+ result = Allocate(height, width, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+ for (int y = 0; y < width; y++)
+ {
+ yOrg = height - 1;
+ for (int x = 0; x < height; x++, yOrg--)
+ {
+ index = src[yOrg][y];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 180:
+ result = Allocate(width, height, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+
+ yOrg = height - 1;
+ for (int y = 0; y < height; y++, yOrg--)
+ {
+ xOrg = width - 1;
+ for (int x = 0; x < width; x++, xOrg--)
+ {
+ index = src[yOrg][xOrg];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 270:
+ result = Allocate(height, width, 4, 0, 0, 0);
+ if (result.IsNull)
+ {
+ break;
+ }
+ CopyPalette(dib, result);
+ src = Get04BitScanlines(dib);
+ dst = Get04BitScanlines(result);
+ xOrg = width - 1;
+ for (int y = 0; y < width; y++, xOrg--)
+ {
+ for (int x = 0; x < height; x++)
+ {
+ index = src[x][xOrg];
+ dst[y][x] = index;
+ }
+ }
+ break;
+ case 0:
+ case 360:
+ result = Clone(dib);
+ break;
+ }
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Upsampling / downsampling
+
+ /// <summary>
+ /// Enlarges or shrinks the FreeImage bitmap selectively per side and fills newly added areas
+ /// with the specified background color. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="left">The number of pixels, the image should be enlarged on its left side.
+ /// Negative values shrink the image on its left side.</param>
+ /// <param name="top">The number of pixels, the image should be enlarged on its top side.
+ /// Negative values shrink the image on its top side.</param>
+ /// <param name="right">The number of pixels, the image should be enlarged on its right side.
+ /// Negative values shrink the image on its right side.</param>
+ /// <param name="bottom">The number of pixels, the image should be enlarged on its bottom side.
+ /// Negative values shrink the image on its bottom side.</param>
+ /// <param name="color">The color, the enlarged sides of the image should be filled with.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns>Handle to a FreeImage bitmap.</returns>
+ /// <remarks>
+ /// This function enlarges or shrinks an image selectively per side.
+ /// The main purpose of this function is to add borders to an image.
+ /// To add a border to any of the image's sides, a positive integer value must be passed in
+ /// any of the parameters <paramref name="left"/>, <paramref name="top"/>, <paramref name="right"/>
+ /// or <paramref name="bottom"/>. This value represents the border's
+ /// width in pixels. Newly created parts of the image (the border areas) are filled with the
+ /// specified <paramref name="color"/>.
+ /// Specifying a negative integer value for a certain side, will shrink or crop the image on
+ /// this side. Consequently, specifying zero for a certain side will not change the image's
+ /// extension on that side.
+ /// <para/>
+ /// So, calling this function with all parameters <paramref name="left"/>, <paramref name="top"/>,
+ /// <paramref name="right"/> and <paramref name="bottom"/> set to zero, is
+ /// effectively the same as calling function <see cref="Clone"/>; setting all parameters
+ /// <paramref name="left"/>, <paramref name="top"/>, <paramref name="right"/> and
+ /// <paramref name="bottom"/> to value equal to or smaller than zero, my easily be substituted
+ /// by a call to function <see cref="Copy"/>. Both these cases produce a new image, which is
+ /// guaranteed not to be larger than the input image. Thus, since the specified
+ /// <paramref name="color"/> is not needed in these cases, <paramref name="color"/>
+ /// may be <c>null</c>.
+ /// <para/>
+ /// Both parameters <paramref name="color"/> and <paramref name="options"/> work according to
+ /// function <see cref="FillBackground&lt;T&gt;"/>. So, please refer to the documentation of
+ /// <see cref="FillBackground&lt;T&gt;"/> to learn more about parameters <paramref name="color"/>
+ /// and <paramref name="options"/>. For palletized images, the palette of the input image is
+ /// transparently copied to the newly created enlarged or shrunken image, so any color look-ups
+ /// are performed on this palette.
+ /// </remarks>
+ /// <example>
+ /// // create a white color<br/>
+ /// RGBQUAD c;<br/>
+ /// c.rgbRed = 0xFF;<br/>
+ /// c.rgbGreen = 0xFF;<br/>
+ /// c.rgbBlue = 0xFF;<br/>
+ /// c.rgbReserved = 0x00;<br/>
+ /// <br/>
+ /// // add a white, symmetric 10 pixel wide border to the image<br/>
+ /// dib2 = FreeImage_EnlargeCanvas(dib, 10, 10, 10, 10, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// <br/>
+ /// // add white, 20 pixel wide stripes to the top and bottom side of the image<br/>
+ /// dib3 = FreeImage_EnlargeCanvas(dib, 0, 20, 0, 20, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// <br/>
+ /// // add white, 30 pixel wide stripes to the right side of the image and<br/>
+ /// // cut off the 40 leftmost pixel columns<br/>
+ /// dib3 = FreeImage_EnlargeCanvas(dib, -40, 0, 30, 0, c, FREE_IMAGE_COLOR_OPTIONS.FICO_RGB);<br/>
+ /// </example>
+ public static FIBITMAP EnlargeCanvas<T>(FIBITMAP dib, int left, int top, int right, int bottom,
+ T? color, FREE_IMAGE_COLOR_OPTIONS options) where T : struct
+ {
+ if (dib.IsNull)
+ return FIBITMAP.Zero;
+
+ if (!CheckColorType(GetImageType(dib), color))
+ return FIBITMAP.Zero;
+
+ if (color.HasValue)
+ {
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color.Value };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return EnlargeCanvas(dib, left, top, right, bottom, handle.AddrOfPinnedObject(), options);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+ else
+ {
+ return EnlargeCanvas(dib, left, top, right, bottom, IntPtr.Zero, options);
+ }
+ }
+
+ #endregion
+
+ #region Color
+
+ /// <summary>
+ /// Sets all pixels of the specified image to the color provided through the
+ /// <paramref name="color"/> parameter. See remarks for further details.
+ /// </summary>
+ /// <typeparam name="T">The type of the specified color.</typeparam>
+ /// <param name="dib">Handle to a FreeImage bitmap.</param>
+ /// <param name="color">The color to fill the bitmap with. See remarks for further details.</param>
+ /// <param name="options">Options that affect the color search process for palletized images.</param>
+ /// <returns><c>true</c> on success, <c>false</c> on failure.</returns>
+ /// <remarks>
+ /// This function sets all pixels of an image to the color provided through
+ /// the <paramref name="color"/> parameter. <see cref="RGBQUAD"/> is used for standard type images.
+ /// For non standard type images the underlaying structure is used.
+ /// <para/>
+ /// So, <paramref name="color"/> must be of type <see cref="Double"/>, if the image to be filled is of type
+ /// <see cref="FREE_IMAGE_TYPE.FIT_DOUBLE"/> and must be a <see cref="FIRGBF"/> structure if the
+ /// image is of type <see cref="FREE_IMAGE_TYPE.FIT_RGBF"/> and so on.
+ /// <para/>
+ /// However, the fill color is always specified through a <see cref="RGBQUAD"/> structure
+ /// for all images of type <see cref="FREE_IMAGE_TYPE.FIT_BITMAP"/>.
+ /// So, for 32- and 24-bit images, the red, green and blue members of the <see cref="RGBQUAD"/>
+ /// structure are directly used for the image's red, green and blue channel respectively.
+ /// Although alpha transparent <see cref="RGBQUAD"/> colors are
+ /// supported, the alpha channel of a 32-bit image never gets modified by this function.
+ /// A fill color with an alpha value smaller than 255 gets blended with the image's actual
+ /// background color, which is determined from the image's bottom-left pixel.
+ /// So, currently using alpha enabled colors, assumes the image to be unicolor before the
+ /// fill operation. However, the <see cref="RGBQUAD.rgbReserved"/> field is only taken into account,
+ /// if option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_RGBA"/> has been specified.
+ /// <para/>
+ /// For 16-bit images, the red-, green- and blue components of the specified color are
+ /// transparently translated into either the 16-bit 555 or 565 representation. This depends
+ /// on the image's actual red- green- and blue masks.
+ /// <para/>
+ /// Special attention must be payed for palletized images. Generally, the RGB color specified
+ /// is looked up in the image's palette. The found palette index is then used to fill the image.
+ /// There are some option flags, that affect this lookup process:
+ /// <list type="table">
+ /// <listheader>
+ /// <term>Value</term>
+ /// <description>Meaning</description>
+ /// </listheader>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_DEFAULT"/></term>
+ /// <description>
+ /// Uses the color, that is nearest to the specified color.
+ /// This is the default behavior and should always find a
+ /// color in the palette. However, the visual result may
+ /// far from what was expected and mainly depends on the
+ /// image's palette.
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_EQUAL_COLOR"/></term>
+ /// <description>
+ /// Searches the image's palette for the specified color
+ /// but only uses the returned palette index, if the specified
+ /// color exactly matches the palette entry. Of course,
+ /// depending on the image's actual palette entries, this
+ /// operation may fail. In this case, the function falls back
+ /// to option <see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/>
+ /// and uses the RGBQUAD's rgbReserved member (or its low nibble for 4-bit images
+ /// or its least significant bit (LSB) for 1-bit images) as
+ /// the palette index used for the fill operation.
+ /// </description>
+ /// </item>
+ /// <item>
+ /// <term><see cref="FREE_IMAGE_COLOR_OPTIONS.FICO_ALPHA_IS_INDEX"/></term>
+ /// <description>
+ /// Does not perform any color lookup from the palette, but
+ /// uses the RGBQUAD's alpha channel member rgbReserved as
+ /// the palette index to be used for the fill operation.
+ /// However, for 4-bit images, only the low nibble of the
+ /// rgbReserved member are used and for 1-bit images, only
+ /// the least significant bit (LSB) is used.
+ /// </description>
+ /// </item>
+ /// </list>
+ /// </remarks>
+ public static bool FillBackground<T>(FIBITMAP dib, T color, FREE_IMAGE_COLOR_OPTIONS options)
+ where T : struct
+ {
+ if (dib.IsNull)
+ return false;
+
+ if (!CheckColorType(GetImageType(dib), color))
+ return false;
+
+ GCHandle handle = new GCHandle();
+ try
+ {
+ T[] buffer = new T[] { color };
+ handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
+ return FillBackground(dib, handle.AddrOfPinnedObject(), options);
+ }
+ finally
+ {
+ if (handle.IsAllocated)
+ handle.Free();
+ }
+ }
+
+ #endregion
+
+ #region Wrapper functions
+
+ /// <summary>
+ /// Returns the next higher possible color depth.
+ /// </summary>
+ /// <param name="bpp">Color depth to increase.</param>
+ /// <returns>The next higher color depth or 0 if there is no valid color depth.</returns>
+ internal static int GetNextColorDepth(int bpp)
+ {
+ int result = 0;
+ switch (bpp)
+ {
+ case 1:
+ result = 4;
+ break;
+ case 4:
+ result = 8;
+ break;
+ case 8:
+ result = 16;
+ break;
+ case 16:
+ result = 24;
+ break;
+ case 24:
+ result = 32;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Returns the next lower possible color depth.
+ /// </summary>
+ /// <param name="bpp">Color depth to decrease.</param>
+ /// <returns>The next lower color depth or 0 if there is no valid color depth.</returns>
+ internal static int GetPrevousColorDepth(int bpp)
+ {
+ int result = 0;
+ switch (bpp)
+ {
+ case 32:
+ result = 24;
+ break;
+ case 24:
+ result = 16;
+ break;
+ case 16:
+ result = 8;
+ break;
+ case 8:
+ result = 4;
+ break;
+ case 4:
+ result = 1;
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Reads a null-terminated c-string.
+ /// </summary>
+ /// <param name="ptr">Pointer to the first char of the string.</param>
+ /// <returns>The converted string.</returns>
+ internal static unsafe string PtrToStr(byte* ptr)
+ {
+ string result = null;
+ if (ptr != null)
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+
+ while (*ptr != 0)
+ {
+ sb.Append((char)(*(ptr++)));
+ }
+ result = sb.ToString();
+ }
+ return result;
+ }
+
+ internal static unsafe byte[] CreateShrunkenPaletteLUT(FIBITMAP dib, out int uniqueColors)
+ {
+ byte[] result = null;
+ uniqueColors = 0;
+
+ if ((!dib.IsNull) && (GetImageType(dib) == FREE_IMAGE_TYPE.FIT_BITMAP) && (GetBPP(dib) <= 8))
+ {
+ int size = (int)GetColorsUsed(dib);
+ List<RGBQUAD> newPalette = new List<RGBQUAD>(size);
+ List<byte> lut = new List<byte>(size);
+ RGBQUAD* palette = (RGBQUAD*)GetPalette(dib);
+ RGBQUAD color;
+ int index;
+
+ for (int i = 0; i < size; i++)
+ {
+ color = palette[i];
+ color.rgbReserved = 255; // ignore alpha
+
+ index = newPalette.IndexOf(color);
+ if (index < 0)
+ {
+ newPalette.Add(color);
+ lut.Add((byte)(newPalette.Count - 1));
+ }
+ else
+ {
+ lut.Add((byte)index);
+ }
+ }
+ result = lut.ToArray();
+ uniqueColors = newPalette.Count;
+ }
+ return result;
+ }
+
+ internal static PropertyItem CreatePropertyItem()
+ {
+ return (PropertyItem)Activator.CreateInstance(typeof(PropertyItem), true);
+ }
+
+ private static unsafe void CopyPalette(FIBITMAP src, FIBITMAP dst)
+ {
+ RGBQUAD* orgPal = (RGBQUAD*)GetPalette(src);
+ RGBQUAD* newPal = (RGBQUAD*)GetPalette(dst);
+ uint size = (uint)(sizeof(RGBQUAD) * GetColorsUsed(src));
+ CopyMemory(newPal, orgPal, size);
+ }
+
+ private static unsafe Scanline<FI4BIT>[] Get04BitScanlines(FIBITMAP dib)
+ {
+ int height = (int)GetHeight(dib);
+ Scanline<FI4BIT>[] array = new Scanline<FI4BIT>[height];
+ for (int i = 0; i < height; i++)
+ {
+ array[i] = new Scanline<FI4BIT>(dib, i);
+ }
+ return array;
+ }
+
+ /// <summary>
+ /// Changes a bitmaps color depth.
+ /// Used by SaveEx and SaveToStream.
+ /// </summary>
+ private static FIBITMAP PrepareBitmapColorDepth(FIBITMAP dibToSave, FREE_IMAGE_FORMAT format, FREE_IMAGE_COLOR_DEPTH colorDepth)
+ {
+ FREE_IMAGE_TYPE type = GetImageType(dibToSave);
+ if (type == FREE_IMAGE_TYPE.FIT_BITMAP)
+ {
+ int bpp = (int)GetBPP(dibToSave);
+ int targetBpp = (int)(colorDepth & FREE_IMAGE_COLOR_DEPTH.FICD_COLOR_MASK);
+
+ if (colorDepth != FREE_IMAGE_COLOR_DEPTH.FICD_AUTO)
+ {
+ // A fix colordepth was chosen
+ if (FIFSupportsExportBPP(format, targetBpp))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, colorDepth, false);
+ }
+ else
+ {
+ throw new ArgumentException("FreeImage\n\nFreeImage Library plugin " +
+ GetFormatFromFIF(format) + " is unable to write images with a color depth of " +
+ targetBpp + " bpp.");
+ }
+ }
+ else
+ {
+ // Auto selection was chosen
+ if (!FIFSupportsExportBPP(format, bpp))
+ {
+ // The color depth is not supported
+ int bppUpper = bpp;
+ int bppLower = bpp;
+ // Check from the bitmaps current color depth in both directions
+ do
+ {
+ bppUpper = GetNextColorDepth(bppUpper);
+ if (FIFSupportsExportBPP(format, bppUpper))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppUpper, false);
+ break;
+ }
+ bppLower = GetPrevousColorDepth(bppLower);
+ if (FIFSupportsExportBPP(format, bppLower))
+ {
+ dibToSave = ConvertColorDepth(dibToSave, (FREE_IMAGE_COLOR_DEPTH)bppLower, false);
+ break;
+ }
+ } while (!((bppLower == 0) && (bppUpper == 0)));
+ }
+ }
+ }
+ return dibToSave;
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(void* buf1, void* buf2, uint length)
+ {
+ return (length == RtlCompareMemory(buf1, buf2, length));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(void* buf1, void* buf2, long length)
+ {
+ return (length == RtlCompareMemory(buf1, buf2, checked((uint)length)));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(IntPtr buf1, IntPtr buf2, uint length)
+ {
+ return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), length));
+ }
+
+ /// <summary>
+ /// Compares blocks of memory.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="length">Specifies the number of bytes to be compared.</param>
+ /// <returns>true, if all bytes compare as equal, false otherwise.</returns>
+ public static unsafe bool CompareMemory(IntPtr buf1, IntPtr buf2, long length)
+ {
+ return (length == RtlCompareMemory(buf1.ToPointer(), buf2.ToPointer(), checked((uint)length)));
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(void* dst, void* src, long size)
+ {
+ MoveMemory(dst, src, checked((uint)size));
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(IntPtr dst, IntPtr src, uint size)
+ {
+ MoveMemory(dst.ToPointer(), src.ToPointer(), size);
+ }
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">A pointer to the starting address of the move destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">The size of the block of memory to move, in bytes.</param>
+ public static unsafe void MoveMemory(IntPtr dst, IntPtr src, long size)
+ {
+ MoveMemory(dst.ToPointer(), src.ToPointer(), checked((uint)size));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(byte* dest, byte* src, int len)
+ {
+ if (len >= 0x10)
+ {
+ do
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ *((int*)(dest + 8)) = *((int*)(src + 8));
+ *((int*)(dest + 12)) = *((int*)(src + 12));
+ dest += 0x10;
+ src += 0x10;
+ }
+ while ((len -= 0x10) >= 0x10);
+ }
+ if (len > 0)
+ {
+ if ((len & 8) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ *((int*)(dest + 4)) = *((int*)(src + 4));
+ dest += 8;
+ src += 8;
+ }
+ if ((len & 4) != 0)
+ {
+ *((int*)dest) = *((int*)src);
+ dest += 4;
+ src += 4;
+ }
+ if ((len & 2) != 0)
+ {
+ *((short*)dest) = *((short*)src);
+ dest += 2;
+ src += 2;
+ }
+ if ((len & 1) != 0)
+ {
+ *dest = *src;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(byte* dest, byte* src, long len)
+ {
+ CopyMemory(dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(void* dest, void* src, long len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(void*, void*, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(void* dest, void* src, int len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(IntPtr, IntPtr, uint)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(IntPtr dest, IntPtr src, int len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ /// <remarks>
+ /// <b>CopyMemory</b> runs faster than <see cref="MoveMemory(IntPtr, IntPtr, long)"/>.
+ /// However, if both blocks overlap the result is undefined.
+ /// </remarks>
+ public static unsafe void CopyMemory(IntPtr dest, IntPtr src, long len)
+ {
+ CopyMemory((byte*)dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, void* src, int len)
+ {
+ GCHandle handle = GCHandle.Alloc(dest, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)handle.AddrOfPinnedObject(), (byte*)src, len);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, void* src, long len)
+ {
+ CopyMemory(dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, IntPtr src, int len)
+ {
+ CopyMemory(dest, (byte*)src, len);
+ }
+
+ /// <summary>
+ /// Copies a block of memory into an array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">A pointer to the starting address of the block of memory to copy.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, IntPtr src, long len)
+ {
+ CopyMemory(dest, (byte*)src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(void* dest, Array src, int len)
+ {
+ GCHandle handle = GCHandle.Alloc(src, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)dest, (byte*)handle.AddrOfPinnedObject(), len);
+ }
+ finally
+ {
+ handle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(void* dest, Array src, long len)
+ {
+ CopyMemory((byte*)dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(IntPtr dest, Array src, int len)
+ {
+ CopyMemory((byte*)dest, src, len);
+ }
+
+ /// <summary>
+ /// Copies the content of an array to a memory location.
+ /// </summary>
+ /// <param name="dest">A pointer to the starting address of the copied block's destination.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the block of memory to copy, in bytes.</param>
+ public static unsafe void CopyMemory(IntPtr dest, Array src, long len)
+ {
+ CopyMemory((byte*)dest, src, checked((int)len));
+ }
+
+ /// <summary>
+ /// Copies the content of one array into another array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the content to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, Array src, int len)
+ {
+ GCHandle dHandle = GCHandle.Alloc(dest, GCHandleType.Pinned);
+ try
+ {
+ GCHandle sHandle = GCHandle.Alloc(src, GCHandleType.Pinned);
+ try
+ {
+ CopyMemory((byte*)dHandle.AddrOfPinnedObject(), (byte*)sHandle.AddrOfPinnedObject(), len);
+ }
+ finally
+ {
+ sHandle.Free();
+ }
+ }
+ finally
+ {
+ dHandle.Free();
+ }
+ }
+
+ /// <summary>
+ /// Copies the content of one array into another array.
+ /// </summary>
+ /// <param name="dest">An array used as the destination of the copy process.</param>
+ /// <param name="src">An array used as the source of the copy process.</param>
+ /// <param name="len">The size of the content to copy, in bytes.</param>
+ public static unsafe void CopyMemory(Array dest, Array src, long len)
+ {
+ CopyMemory(dest, src, checked((int)len));
+ }
+
+ internal static string ColorToString(Color color)
+ {
+ return string.Format(
+ System.Globalization.CultureInfo.CurrentCulture,
+ "{{Name={0}, ARGB=({1}, {2}, {3}, {4})}}",
+ new object[] { color.Name, color.A, color.R, color.G, color.B });
+ }
+
+ internal static void Resize(ref string str, int length)
+ {
+ if ((str != null) && (length >= 0) && (str.Length != length))
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, length);
+ str = new string(chars);
+ }
+ }
+
+ internal static void Resize(ref string str, int min, int max)
+ {
+ if ((str != null) && (min >= 0) && (max >= 0) && (min <= max))
+ {
+ if (str.Length < min)
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, min);
+ str = new string(chars);
+ }
+ else if (str.Length > max)
+ {
+ char[] chars = str.ToCharArray();
+ Array.Resize(ref chars, max);
+ str = new string(chars);
+ }
+ }
+ }
+
+ internal static void Resize<T>(ref T[] array, int length)
+ {
+ if ((array != null) && (length >= 0) && (array.Length != length))
+ {
+ Array.Resize(ref array, length);
+ }
+ }
+
+ internal static void Resize<T>(ref T[] array, int min, int max)
+ {
+ if ((array != null) && (min >= 0) && (max >= 0) && (min <= max))
+ {
+ if (array.Length < min)
+ {
+ Array.Resize(ref array, min);
+ }
+ else if (array.Length > max)
+ {
+ Array.Resize(ref array, max);
+ }
+ }
+ }
+
+ internal static bool CheckColorType<T>(FREE_IMAGE_TYPE imageType, T color)
+ {
+ Type type = typeof(T);
+ bool result;
+ switch (imageType)
+ {
+ case FREE_IMAGE_TYPE.FIT_BITMAP:
+ result = (type == typeof(RGBQUAD)); break;
+ case FREE_IMAGE_TYPE.FIT_COMPLEX:
+ result = (type == typeof(FICOMPLEX)); break;
+ case FREE_IMAGE_TYPE.FIT_DOUBLE:
+ result = (type == typeof(double)); break;
+ case FREE_IMAGE_TYPE.FIT_FLOAT:
+ result = (type == typeof(float)); break;
+ case FREE_IMAGE_TYPE.FIT_INT16:
+ result = (type == typeof(Int16)); break;
+ case FREE_IMAGE_TYPE.FIT_INT32:
+ result = (type == typeof(Int32)); break;
+ case FREE_IMAGE_TYPE.FIT_RGB16:
+ result = (type == typeof(FIRGB16)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBA16:
+ result = (type == typeof(FIRGBA16)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBAF:
+ result = (type == typeof(FIRGBAF)); break;
+ case FREE_IMAGE_TYPE.FIT_RGBF:
+ result = (type == typeof(FIRGBF)); break;
+ case FREE_IMAGE_TYPE.FIT_UINT16:
+ result = (type == typeof(UInt16)); break;
+ case FREE_IMAGE_TYPE.FIT_UINT32:
+ result = (type == typeof(UInt32)); break;
+ default:
+ result = false; break;
+ }
+ return result;
+ }
+
+ #endregion
+
+ #region Dll-Imports
+
+ /// <summary>
+ /// Retrieves a handle to a display device context (DC) for the client area of a specified window
+ /// or for the entire screen. You can use the returned handle in subsequent GDI functions to draw in the DC.
+ /// </summary>
+ /// <param name="hWnd">Handle to the window whose DC is to be retrieved.
+ /// If this value is IntPtr.Zero, GetDC retrieves the DC for the entire screen. </param>
+ /// <returns>If the function succeeds, the return value is a handle to the DC for the specified window's client area.
+ /// If the function fails, the return value is NULL.</returns>
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetDC(IntPtr hWnd);
+
+ /// <summary>
+ /// Releases a device context (DC), freeing it for use by other applications.
+ /// The effect of the ReleaseDC function depends on the type of DC. It frees only common and window DCs.
+ /// It has no effect on class or private DCs.
+ /// </summary>
+ /// <param name="hWnd">Handle to the window whose DC is to be released.</param>
+ /// <param name="hDC">Handle to the DC to be released.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport("user32.dll")]
+ private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);
+
+ /// <summary>
+ /// Creates a DIB that applications can write to directly.
+ /// The function gives you a pointer to the location of the bitmap bit values.
+ /// You can supply a handle to a file-mapping object that the function will use to create the bitmap,
+ /// or you can let the system allocate the memory for the bitmap.
+ /// </summary>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="pbmi">Pointer to a BITMAPINFO structure that specifies various attributes of the DIB,
+ /// including the bitmap dimensions and colors.</param>
+ /// <param name="iUsage">Specifies the type of data contained in the bmiColors array member of the BITMAPINFO structure
+ /// pointed to by pbmi (either logical palette indexes or literal RGB values).</param>
+ /// <param name="ppvBits">Pointer to a variable that receives a pointer to the location of the DIB bit values.</param>
+ /// <param name="hSection">Handle to a file-mapping object that the function will use to create the DIB.
+ /// This parameter can be NULL.</param>
+ /// <param name="dwOffset">Specifies the offset from the beginning of the file-mapping object referenced by hSection
+ /// where storage for the bitmap bit values is to begin. This value is ignored if hSection is NULL.</param>
+ /// <returns>If the function succeeds, the return value is a handle to the newly created DIB,
+ /// and *ppvBits points to the bitmap bit values. If the function fails, the return value is NULL, and *ppvBits is NULL.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDIBSection(
+ IntPtr hdc,
+ [In] IntPtr pbmi,
+ uint iUsage,
+ out IntPtr ppvBits,
+ IntPtr hSection,
+ uint dwOffset);
+
+ /// <summary>
+ /// Deletes a logical pen, brush, font, bitmap, region, or palette, freeing all system resources associated with the object.
+ /// After the object is deleted, the specified handle is no longer valid.
+ /// </summary>
+ /// <param name="hObject">Handle to a logical pen, brush, font, bitmap, region, or palette.</param>
+ /// <returns>Returns true on success, false on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern bool DeleteObject(IntPtr hObject);
+
+ /// <summary>
+ /// Creates a compatible bitmap (DDB) from a DIB and, optionally, sets the bitmap bits.
+ /// </summary>
+ /// <param name="hdc">Handle to a device context.</param>
+ /// <param name="lpbmih">Pointer to a bitmap information header structure.</param>
+ /// <param name="fdwInit">Specifies how the system initializes the bitmap bits - (use 4).</param>
+ /// <param name="lpbInit">Pointer to an array of bytes containing the initial bitmap data.</param>
+ /// <param name="lpbmi">Pointer to a BITMAPINFO structure that describes the dimensions
+ /// and color format of the array pointed to by the lpbInit parameter.</param>
+ /// <param name="fuUsage">Specifies whether the bmiColors member of the BITMAPINFO structure
+ /// was initialized - (use 0).</param>
+ /// <returns>Handle to a DIB or null on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern IntPtr CreateDIBitmap(
+ IntPtr hdc,
+ IntPtr lpbmih,
+ uint fdwInit,
+ IntPtr lpbInit,
+ IntPtr lpbmi,
+ uint fuUsage);
+
+ /// <summary>
+ /// Retrieves information for the specified graphics object.
+ /// </summary>
+ /// <param name="hgdiobj">Handle to the graphics object of interest.</param>
+ /// <param name="cbBuffer">Specifies the number of bytes of information to
+ /// be written to the buffer.</param>
+ /// <param name="lpvObject">Pointer to a buffer that receives the information
+ /// about the specified graphics object.</param>
+ /// <returns>0 on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);
+
+ /// <summary>
+ /// Retrieves the bits of the specified compatible bitmap and copies them into a buffer
+ /// as a DIB using the specified format.
+ /// </summary>
+ /// <param name="hdc">Handle to the device context.</param>
+ /// <param name="hbmp">Handle to the bitmap. This must be a compatible bitmap (DDB).</param>
+ /// <param name="uStartScan">Specifies the first scan line to retrieve.</param>
+ /// <param name="cScanLines">Specifies the number of scan lines to retrieve.</param>
+ /// <param name="lpvBits">Pointer to a buffer to receive the bitmap data.</param>
+ /// <param name="lpbmi">Pointer to a BITMAPINFO structure that specifies the desired
+ /// format for the DIB data.</param>
+ /// <param name="uUsage">Specifies the format of the bmiColors member of the
+ /// BITMAPINFO structure - (use 0).</param>
+ /// <returns>0 on failure.</returns>
+ [DllImport("gdi32.dll")]
+ private static extern unsafe int GetDIBits(
+ IntPtr hdc,
+ IntPtr hbmp,
+ uint uStartScan,
+ uint cScanLines,
+ IntPtr lpvBits,
+ IntPtr lpbmi,
+ uint uUsage);
+
+ /// <summary>
+ /// Moves a block of memory from one location to another.
+ /// </summary>
+ /// <param name="dst">Pointer to the starting address of the move destination.</param>
+ /// <param name="src">Pointer to the starting address of the block of memory to be moved.</param>
+ /// <param name="size">Size of the block of memory to move, in bytes.</param>
+ [DllImport("Kernel32.dll", EntryPoint = "RtlMoveMemory", SetLastError = false)]
+ public static unsafe extern void MoveMemory(void* dst, void* src, uint size);
+
+ /// <summary>
+ /// The RtlCompareMemory routine compares blocks of memory
+ /// and returns the number of bytes that are equivalent.
+ /// </summary>
+ /// <param name="buf1">A pointer to a block of memory to compare.</param>
+ /// <param name="buf2">A pointer to a block of memory to compare.</param>
+ /// <param name="count">Specifies the number of bytes to be compared.</param>
+ /// <returns>RtlCompareMemory returns the number of bytes that compare as equal.
+ /// If all bytes compare as equal, the input Length is returned.</returns>
+ [DllImport("ntdll.dll", EntryPoint = "RtlCompareMemory", SetLastError = false)]
+ internal static unsafe extern uint RtlCompareMemory(void* buf1, void* buf2, uint count);
+
+ #endregion
+ }
+}
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/ImageManager.cs b/Wrapper/FreeImage.NET/cs/UnitTest/ImageManager.cs
new file mode 100644
index 0000000..b554473
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/ImageManager.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO;
+
+namespace FreeImageNETUnitTest
+{
+ internal enum ImageType : byte
+ {
+ Even,
+ Odd,
+ JPEG,
+ Metadata,
+ Multipaged
+ }
+
+ internal enum ImageColorType : byte
+ {
+ Type_01_Dither,
+ Type_01_Threshold,
+ Type_04,
+ Type_04_Greyscale_MinIsBlack,
+ Type_04_Greyscale_Unordered,
+ Type_08,
+ Type_08_Greyscale_MinIsBlack,
+ Type_08_Greyscale_Unordered,
+ Type_16_555,
+ Type_16_565,
+ Type_24,
+ Type_32,
+ }
+
+ internal class ImageManager
+ {
+ public readonly string baseDirectory = null;
+
+ public ImageManager()
+ : this(new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.Parent.FullName + @"\UnitTestData\Images\")
+ {
+ }
+
+ public ImageManager(string baseDirectory)
+ {
+ if (!Directory.Exists(baseDirectory))
+ throw new DirectoryNotFoundException();
+ this.baseDirectory = baseDirectory;
+ }
+
+ public string GetBitmapPath(ImageType type, ImageColorType colorType)
+ {
+ string filename = null;
+
+ switch (type)
+ {
+ case ImageType.Even:
+ switch (colorType)
+ {
+ case ImageColorType.Type_01_Dither:
+ filename = baseDirectory + @"Even\Image_01_dither.tif";
+ break;
+ case ImageColorType.Type_01_Threshold:
+ filename = baseDirectory + @"Even\Image_01_threshold.tif";
+ break;
+ case ImageColorType.Type_04:
+ filename = baseDirectory + @"Even\Image_04.tif";
+ break;
+ case ImageColorType.Type_04_Greyscale_MinIsBlack:
+ filename = baseDirectory + @"Even\Image_04_gs_minisblack.tif";
+ break;
+ case ImageColorType.Type_04_Greyscale_Unordered:
+ filename = baseDirectory + @"Even\Image_04_gs_unordered.tif";
+ break;
+ case ImageColorType.Type_08:
+ filename = baseDirectory + @"Even\Image_08.tif";
+ break;
+ case ImageColorType.Type_08_Greyscale_MinIsBlack:
+ filename = baseDirectory + @"Even\Image_08_gs_minisblack.tif";
+ break;
+ case ImageColorType.Type_08_Greyscale_Unordered:
+ filename = baseDirectory + @"Even\Image_08_gs_unordered.tif";
+ break;
+ case ImageColorType.Type_16_555:
+ filename = baseDirectory + @"Even\Image_16_555.bmp";
+ break;
+ case ImageColorType.Type_16_565:
+ filename = baseDirectory + @"Even\Image_16_565.bmp";
+ break;
+ case ImageColorType.Type_24:
+ filename = baseDirectory + @"Even\Image_24.tif";
+ break;
+ case ImageColorType.Type_32:
+ filename = baseDirectory + @"Even\Image_32.tif";
+ break;
+ }
+ break;
+ case ImageType.Odd:
+ switch (colorType)
+ {
+ case ImageColorType.Type_01_Dither:
+ filename = baseDirectory + @"Odd\Image_01_dither.tif";
+ break;
+ case ImageColorType.Type_01_Threshold:
+ filename = baseDirectory + @"Odd\Image_01_threshold.tif";
+ break;
+ case ImageColorType.Type_04:
+ filename = baseDirectory + @"Odd\Image_04.tif";
+ break;
+ case ImageColorType.Type_04_Greyscale_MinIsBlack:
+ filename = baseDirectory + @"Odd\Image_04_gs_minisblack.tif";
+ break;
+ case ImageColorType.Type_04_Greyscale_Unordered:
+ filename = baseDirectory + @"Odd\Image_04_gs_unordered.tif";
+ break;
+ case ImageColorType.Type_08:
+ filename = baseDirectory + @"Odd\Image_08.tif";
+ break;
+ case ImageColorType.Type_08_Greyscale_MinIsBlack:
+ filename = baseDirectory + @"Odd\Image_08_gs_minisblack.tif";
+ break;
+ case ImageColorType.Type_08_Greyscale_Unordered:
+ filename = baseDirectory + @"Odd\Image_08_gs_unordered.tif";
+ break;
+ case ImageColorType.Type_16_555:
+ filename = baseDirectory + @"Odd\Image_16_555.bmp";
+ break;
+ case ImageColorType.Type_16_565:
+ filename = baseDirectory + @"Odd\Image_16_565.bmp";
+ break;
+ case ImageColorType.Type_24:
+ filename = baseDirectory + @"Odd\Image_24.tif";
+ break;
+ }
+ break;
+ case ImageType.JPEG:
+ filename = baseDirectory + @"JPEG\Image.jpg";
+ break;
+ case ImageType.Metadata:
+ filename = baseDirectory + @"Metadata\exif.jpg";
+ break;
+ case ImageType.Multipaged:
+ filename = baseDirectory + @"Multipaged\Image.tif";
+ break;
+ }
+ return filename;
+ }
+
+ public FreeImageAPI.FIBITMAP GetBitmap(ImageType type, ImageColorType colorType)
+ {
+ FreeImageAPI.FIBITMAP result = new FreeImageAPI.FIBITMAP();
+ string filename = GetBitmapPath(type, colorType);
+ if (!String.IsNullOrEmpty(filename) && File.Exists(filename))
+ result = FreeImageAPI.FreeImage.LoadEx(filename);
+ return result;
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/NUnit.txt b/Wrapper/FreeImage.NET/cs/UnitTest/NUnit.txt
new file mode 100644
index 0000000..cca3df5
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/NUnit.txt
@@ -0,0 +1,14 @@
+NUnit 2.x is needed for FreeImage .NET wrapper unit tests. It can be
+downloaded from http://www.nunit.org/
+
+After installing NUnit, double click on the NUnit project file
+FreeImage.NET.nunit located in the FreeImage .NET wrapper Source folder
+to load the project.
+
+The FreeImage .NET wrapper unit test project UnitTest.csproj, located
+under Source\UnitTest, must be compiled in 'Debug' mode prior to opening
+the NUnit project.
+
+The FreeImage .NET wrapper unit test project UnitTest.csproj currently
+relies on the FreeImage .NET wrapper single source file, created by the
+Source File Merger, located in the Source\SourceFileMerger folder. \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/Properties/AssemblyInfo.cs b/Wrapper/FreeImage.NET/cs/UnitTest/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..de39cbd
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/Properties/AssemblyInfo.cs
@@ -0,0 +1,16 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("FreeImageAPI.Properties")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("DataGis")]
+[assembly: AssemblyProduct("FreeImageAPI.Properties")]
+[assembly: AssemblyCopyright("Copyright © DataGis 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+[assembly: Guid("51678252-9a4b-492d-96c9-37ebe08d1f29")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.cs b/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.cs
new file mode 100644
index 0000000..6794e34
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.cs
@@ -0,0 +1,5555 @@
+using System;
+using System.Drawing;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.IO;
+using System.Drawing.Imaging;
+using System.Net;
+using FreeImageNETUnitTest;
+using System.Reflection;
+using System.Threading;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Collections;
+using FreeImageAPI;
+using FreeImageAPI.IO;
+using FreeImageAPI.Metadata;
+using FreeImageAPI.Plugins;
+using NUnit.Framework;
+
+namespace FreeImageNETUnitTest
+{
+ [TestFixture]
+ public class ImportedFunctionsTest
+ {
+ ImageManager iManager = new ImageManager();
+ FIBITMAP dib;
+ string freeImageCallback = null;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [TestFixtureTearDown]
+ public void DeInit()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [SetUp]
+ public void InitEachTime()
+ {
+ }
+
+ [TearDown]
+ public void DeInitEachTime()
+ {
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ freeImageCallback = message;
+ }
+
+ [Test]
+ public void FreeImage_GetVersion()
+ {
+ string version = FreeImage.GetVersion();
+ Assert.IsNotEmpty(version);
+ }
+
+ [Test]
+ public void FreeImage_GetCopyrightMessage()
+ {
+ string copyright = FreeImage.GetCopyrightMessage();
+ Assert.IsNotEmpty(copyright);
+ }
+
+ [Test]
+ public void FreeImage_OutputMessageProc_SetOutputMessage()
+ {
+ Assert.IsNull(freeImageCallback);
+ FreeImage.SetOutputMessage(new OutputMessageFunction(FreeImage_Message));
+ FreeImage.OutputMessageProc(FREE_IMAGE_FORMAT.FIF_UNKNOWN, "unit test");
+ FreeImage.SetOutputMessage(null);
+ Assert.IsNotNull(freeImageCallback);
+ freeImageCallback = null;
+ }
+
+ [Test]
+ public void FreeImage_Allocate()
+ {
+ dib = FreeImage.Allocate(
+ 133,
+ 77,
+ 8,
+ FreeImage.FI_RGBA_RED_MASK,
+ FreeImage.FI_RGBA_GREEN_MASK,
+ FreeImage.FI_RGBA_BLUE_MASK);
+
+ Assert.That(!dib.IsNull);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AllocateT()
+ {
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_RGBA16, 31, 555, 64, 0, 0, 0);
+
+ Assert.That(!dib.IsNull);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Clone()
+ {
+ dib = FreeImage.Allocate(1, 1, 32, 0, 0, 0);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.Clone(dib);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Load()
+ {
+ Assert.That(dib.IsNull);
+ dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, iManager.baseDirectory + @"JPEG\Image.jpg", FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.That(!dib.IsNull);
+ FreeImage.UnloadEx(ref dib);
+ Assert.That(dib.IsNull);
+ }
+
+ [Test]
+ public void FreeImage_Unload()
+ {
+ Assert.That(dib.IsNull);
+ dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, iManager.baseDirectory + @"JPEG\Image.jpg", FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.IsNotNull(dib);
+ FreeImage.Unload(dib);
+ dib.SetNull();
+ }
+
+ [Test]
+ public void FreeImage_LoadFromHandle()
+ {
+ byte[] data = File.ReadAllBytes(iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_16_555));
+ MemoryStream mStream = new MemoryStream(data);
+ FreeImageIO io = FreeImageStreamIO.io;
+
+ using (fi_handle handle = new fi_handle(mStream))
+ {
+ dib = FreeImage.LoadFromHandle(FREE_IMAGE_FORMAT.FIF_BMP, ref io, handle, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.That(!dib.IsNull);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ [Test]
+ public void FreeImage_Save()
+ {
+ string filename = @"test.bmp";
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.Save(FREE_IMAGE_FORMAT.FIF_BMP, dib, filename, FREE_IMAGE_SAVE_FLAGS.DEFAULT));
+ Assert.IsTrue(File.Exists(filename));
+ File.Delete(filename);
+ Assert.IsFalse(File.Exists(filename));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SaveToHandle()
+ {
+ FreeImageIO io = new FreeImageIO();
+ FreeImage.SaveToHandle(FREE_IMAGE_FORMAT.FIF_BMP, dib, ref io, new fi_handle(), FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ [Test]
+ public void FreeImage_Memory()
+ {
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.That(!dib.IsNull);
+ FIMEMORY mem = FreeImage.OpenMemory(IntPtr.Zero, 0);
+ Assert.AreNotEqual(0, mem);
+ FreeImage.SaveToMemory(FREE_IMAGE_FORMAT.FIF_TIFF, dib, mem, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ Assert.AreNotEqual(0, FreeImage.TellMemory(mem));
+ Assert.IsTrue(FreeImage.SeekMemory(mem, 0, System.IO.SeekOrigin.Begin));
+
+ FIBITMAP temp = FreeImage.LoadFromMemory(FREE_IMAGE_FORMAT.FIF_TIFF, mem, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.AreNotEqual(0, temp);
+ FreeImage.UnloadEx(ref temp);
+
+ uint size = 0;
+ byte[] ptr = new byte[1];
+ IntPtr buffer = IntPtr.Zero;
+ Assert.IsTrue(FreeImage.AcquireMemory(mem, ref buffer, ref size));
+ Assert.AreNotEqual(IntPtr.Zero, ptr);
+ Assert.AreNotEqual(0, size);
+
+ Assert.AreEqual(1, FreeImage.WriteMemory(ptr, 1, 1, mem));
+ FreeImage.SeekMemory(mem, 1, System.IO.SeekOrigin.Begin);
+ Assert.AreEqual(1, FreeImage.TellMemory(mem));
+ Assert.AreEqual(2, FreeImage.ReadMemory(ptr, 1, 2, mem));
+ FreeImage.CloseMemory(mem);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_RegisterLocalPlugin()
+ {
+ InitProc proc = null;
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.RegisterLocalPlugin(proc, "", "", "", ""));
+ }
+
+ [Test]
+ public void FreeImage_RegisterExternalPlugin()
+ {
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.RegisterExternalPlugin("", "", "", "", ""));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFCount()
+ {
+ Assert.AreNotEqual(0, FreeImage.GetFIFCount());
+ }
+
+ [Test]
+ public void FreeImage_SetPluginEnabled_IsPluginEnabled()
+ {
+ FreeImage.SetPluginEnabled(FREE_IMAGE_FORMAT.FIF_PNG, false);
+ Assert.AreEqual(0, FreeImage.IsPluginEnabled(FREE_IMAGE_FORMAT.FIF_PNG));
+ FreeImage.SetPluginEnabled(FREE_IMAGE_FORMAT.FIF_PNG, true);
+ Assert.AreEqual(1, FreeImage.IsPluginEnabled(FREE_IMAGE_FORMAT.FIF_PNG));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFFromFormat()
+ {
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromFormat(""));
+ Assert.AreNotEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromFormat("TIFF"));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFFromMime()
+ {
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromMime(""));
+ Assert.AreNotEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromMime("image/jpeg"));
+ }
+
+ [Test]
+ public void FreeImage_GetFormatFromFIF()
+ {
+ Assert.IsNotEmpty(FreeImage.GetFormatFromFIF(FREE_IMAGE_FORMAT.FIF_JNG));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFExtensionList()
+ {
+ Assert.IsNotEmpty(FreeImage.GetFIFExtensionList(FREE_IMAGE_FORMAT.FIF_PGM));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFDescription()
+ {
+ Assert.IsNotEmpty(FreeImage.GetFIFDescription(FREE_IMAGE_FORMAT.FIF_PBM));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFRegExpr()
+ {
+ Assert.IsNotEmpty(FreeImage.GetFIFRegExpr(FREE_IMAGE_FORMAT.FIF_JPEG));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFMimeType()
+ {
+ Assert.IsNotEmpty(FreeImage.GetFIFMimeType(FREE_IMAGE_FORMAT.FIF_ICO));
+ }
+
+ [Test]
+ public void FreeImage_GetFIFFromFilename()
+ {
+ Assert.AreNotEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromFilename("test.bmp"));
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFIFFromFilename("test.000"));
+ }
+
+ [Test]
+ public void FreeImage_FIFSupportsReading()
+ {
+ Assert.IsTrue(FreeImage.FIFSupportsReading(FREE_IMAGE_FORMAT.FIF_TIFF));
+ }
+
+ [Test]
+ public void FreeImage_FIFSupportsWriting()
+ {
+ Assert.IsTrue(FreeImage.FIFSupportsWriting(FREE_IMAGE_FORMAT.FIF_GIF));
+ }
+
+ [Test]
+ public void FreeImage_FIFSupportsExportBPP()
+ {
+ Assert.IsTrue(FreeImage.FIFSupportsExportBPP(FREE_IMAGE_FORMAT.FIF_BMP, 32));
+ Assert.IsFalse(FreeImage.FIFSupportsExportBPP(FREE_IMAGE_FORMAT.FIF_GIF, 32));
+ }
+
+ [Test]
+ public void FreeImage_FIFSupportsExportType()
+ {
+ Assert.IsTrue(FreeImage.FIFSupportsExportType(FREE_IMAGE_FORMAT.FIF_BMP, FREE_IMAGE_TYPE.FIT_BITMAP));
+ Assert.IsFalse(FreeImage.FIFSupportsExportType(FREE_IMAGE_FORMAT.FIF_BMP, FREE_IMAGE_TYPE.FIT_COMPLEX));
+ }
+
+ [Test]
+ public void FreeImage_FIFSupportsICCProfiles()
+ {
+ Assert.IsTrue(FreeImage.FIFSupportsICCProfiles(FREE_IMAGE_FORMAT.FIF_JPEG));
+ Assert.IsFalse(FreeImage.FIFSupportsICCProfiles(FREE_IMAGE_FORMAT.FIF_BMP));
+ }
+
+ [Test]
+ public void FreeImage_MultiBitmap()
+ {
+ FIBITMAP temp;
+ FIMULTIBITMAP mdib = FreeImage.OpenMultiBitmap(
+ FREE_IMAGE_FORMAT.FIF_TIFF,
+ @"test.tif",
+ true,
+ false,
+ true,
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.AreNotEqual(0, mdib);
+ Assert.AreEqual(0, FreeImage.GetPageCount(mdib));
+ dib = FreeImage.Allocate(10, 10, 8, 0, 0, 0);
+ FreeImage.AppendPage(mdib, dib);
+ Assert.AreEqual(1, FreeImage.GetPageCount(mdib));
+ FreeImage.AppendPage(mdib, dib);
+ Assert.AreEqual(2, FreeImage.GetPageCount(mdib));
+ FreeImage.AppendPage(mdib, dib);
+ Assert.AreEqual(3, FreeImage.GetPageCount(mdib));
+ FreeImage.CloseMultiBitmapEx(ref mdib);
+ FreeImage.UnloadEx(ref dib);
+ mdib.SetNull();
+ mdib = FreeImage.OpenMultiBitmap(FREE_IMAGE_FORMAT.FIF_TIFF, @"test.tif", false, false, true, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.AreNotEqual(0, mdib);
+ Assert.AreEqual(3, FreeImage.GetPageCount(mdib));
+ dib = FreeImage.LockPage(mdib, 1);
+ temp = FreeImage.LockPage(mdib, 2);
+
+ int[] pages = null;
+ int count = 0;
+ FreeImage.GetLockedPageNumbers(mdib, pages, ref count);
+ Assert.AreEqual(2, count);
+ pages = new int[count];
+ FreeImage.GetLockedPageNumbers(mdib, pages, ref count);
+ Assert.AreEqual(2, pages.Length);
+ FreeImage.UnlockPage(mdib, dib, false);
+ FreeImage.UnlockPage(mdib, temp, true);
+ dib.SetNull();
+ Assert.IsTrue(FreeImage.MovePage(mdib, 0, 1));
+ FreeImage.CloseMultiBitmapEx(ref mdib);
+ Assert.IsTrue(System.IO.File.Exists("test.tif"));
+ System.IO.File.Delete("test.tif");
+ }
+
+ [Test]
+ public void FreeImage_GetFileType()
+ {
+ Assert.AreNotEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFileType(iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_08_Greyscale_Unordered), 0));
+ }
+
+ [Test]
+ public void FreeImage_GetFileTypeFromHandle()
+ {
+ FreeImageIO io = FreeImageStreamIO.io;
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFileTypeFromHandle(ref io, new fi_handle(), 0));
+ }
+
+ [Test]
+ public void FreeImage_GetFileTypeFromMemory()
+ {
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_UNKNOWN, FreeImage.GetFileTypeFromMemory(new FIMEMORY(), 0));
+ }
+
+ [Test]
+ public void FreeImage_IsLittleEndian()
+ {
+ Assert.IsTrue(FreeImage.IsLittleEndian());
+ }
+
+ [Test]
+ public void FreeImage_LookupX11Color()
+ {
+ byte red, green, blue;
+ FreeImage.LookupX11Color("lawngreen", out red, out green, out blue);
+ Assert.AreEqual(124, red);
+ Assert.AreEqual(252, green);
+ Assert.AreEqual(0, blue);
+ }
+
+ [Test]
+ public void FreeImage_LookupSVGColor()
+ {
+ byte red, green, blue;
+ FreeImage.LookupX11Color("orchid", out red, out green, out blue);
+ Assert.AreEqual(218, red);
+ Assert.AreEqual(112, green);
+ Assert.AreEqual(214, blue);
+ }
+
+ [Test]
+ public void FreeImage_GetBits()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_01_Threshold);
+ Assert.That(!dib.IsNull);
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetBits(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetScanLine()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetScanLine(dib, 0));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetPixelIndex_SetPixelIndex()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_04_Greyscale_Unordered);
+ Assert.That(!dib.IsNull);
+ byte index_old, index_new;
+ Assert.IsTrue(FreeImage.GetPixelIndex(dib, 31, 10, out index_old));
+ index_new = index_old == byte.MaxValue ? (byte)0 : (byte)(index_old + 1);
+ Assert.IsTrue(FreeImage.SetPixelIndex(dib, 31, 10, ref index_new));
+ Assert.IsTrue(FreeImage.GetPixelIndex(dib, 31, 10, out index_old));
+ Assert.AreEqual(index_new, index_old);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetPixelColor_SetPixelColor()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ RGBQUAD value_old, value_new;
+ Assert.IsTrue(FreeImage.GetPixelColor(dib, 77, 61, out value_old));
+ value_new = (value_old == (RGBQUAD)Color.White) ? Color.Black : Color.White;
+ Assert.IsTrue(FreeImage.SetPixelColor(dib, 77, 61, ref value_new));
+ Assert.IsTrue(FreeImage.GetPixelColor(dib, 77, 61, out value_old));
+ Assert.AreEqual(value_new, value_old);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Bitmap_information_functions()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_BITMAP, FreeImage.GetImageType(dib));
+ Assert.AreNotEqual(0, FreeImage.GetColorsUsed(dib));
+ Assert.AreEqual(8, FreeImage.GetBPP(dib));
+ Assert.AreNotEqual(0, FreeImage.GetWidth(dib));
+ Assert.AreNotEqual(0, FreeImage.GetHeight(dib));
+ Assert.AreNotEqual(0, FreeImage.GetLine(dib));
+ Assert.AreNotEqual(0, FreeImage.GetPitch(dib));
+ Assert.AreNotEqual(0, FreeImage.GetDIBSize(dib));
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetPalette(dib));
+ FreeImage.SetDotsPerMeterX(dib, 1234);
+ FreeImage.SetDotsPerMeterY(dib, 4321);
+ Assert.AreEqual(1234, FreeImage.GetDotsPerMeterX(dib));
+ Assert.AreEqual(4321, FreeImage.GetDotsPerMeterY(dib));
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetInfoHeader(dib));
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetInfo(dib));
+ Assert.AreEqual(FREE_IMAGE_COLOR_TYPE.FIC_MINISBLACK, FreeImage.GetColorType(dib));
+ Assert.AreEqual(0, FreeImage.GetRedMask(dib));
+ Assert.AreEqual(0, FreeImage.GetGreenMask(dib));
+ Assert.AreEqual(0, FreeImage.GetBlueMask(dib));
+ Assert.AreEqual(0, FreeImage.GetTransparencyCount(dib));
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.GetTransparencyTable(dib));
+ FreeImage.SetTransparent(dib, false);
+ FreeImage.SetTransparencyTable(dib, new byte[] { });
+ Assert.IsTrue(FreeImage.IsTransparent(dib));
+ Assert.IsFalse(FreeImage.HasBackgroundColor(dib));
+ RGBQUAD rgb = Color.Teal;
+ Assert.IsTrue(FreeImage.SetBackgroundColor(dib, ref rgb));
+ Assert.IsTrue(FreeImage.GetBackgroundColor(dib, out rgb));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetICCProfile()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+ new FIICCPROFILE(dib, new byte[] { 0xFF, 0xAA, 0x00, 0x33 });
+ FIICCPROFILE p = FreeImage.GetICCProfileEx(dib);
+ Assert.AreEqual(4, p.Size);
+ Assert.AreEqual(0xAA, p.Data[1]);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_CreateICCProfile()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+ byte[] data = new byte[256];
+ Assert.AreNotEqual(IntPtr.Zero, FreeImage.CreateICCProfile(dib, data, 256));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_DestroyICCProfile()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+ FreeImage.DestroyICCProfile(dib);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo4Bits()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo4Bits(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(4, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo8Bits()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo8Bits(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(8, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertToGreyscale()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertToGreyscale(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(8, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo16Bits555()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo16Bits555(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(16, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo16Bits565()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo16Bits565(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(16, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo24Bits()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo24Bits(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(24, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertTo32Bits()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertTo32Bits(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(32, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ColorQuantize()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ColorQuantize(dib, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(8, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ColorQuantizeEx()
+ {
+ FIBITMAP paletteDib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08);
+ Assert.IsFalse(paletteDib.IsNull);
+ Palette palette = FreeImage.GetPaletteEx(paletteDib);
+ RGBQUAD[] table = palette.Data;
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.ColorQuantizeEx(dib, FREE_IMAGE_QUANTIZE.FIQ_WUQUANT, (int)palette.Length, (int)palette.Length, table);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(8, FreeImage.GetBPP(temp));
+
+ FreeImage.UnloadEx(ref paletteDib);
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Threshold()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.Threshold(dib, 128);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(1, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Dither()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.Dither(dib, FREE_IMAGE_DITHER.FID_FS);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(1, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_RawBits()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ IntPtr buffer = Marshal.AllocHGlobal((int)FreeImage.GetDIBSize(dib));
+ FreeImage.ConvertToRawBits(
+ buffer,
+ dib,
+ (int)FreeImage.GetPitch(dib),
+ FreeImage.GetBPP(dib),
+ FreeImage.GetRedMask(dib),
+ FreeImage.GetGreenMask(dib),
+ FreeImage.GetBlueMask(dib),
+ true);
+ FIBITMAP temp = FreeImage.ConvertFromRawBits(
+ buffer,
+ (int)FreeImage.GetWidth(dib),
+ (int)FreeImage.GetHeight(dib),
+ (int)FreeImage.GetPitch(dib),
+ FreeImage.GetBPP(dib),
+ FreeImage.GetRedMask(dib),
+ FreeImage.GetGreenMask(dib),
+ FreeImage.GetBlueMask(dib),
+ true);
+
+ Assert.AreNotEqual(0, temp);
+
+ Marshal.FreeHGlobal(buffer);
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertToRGBF()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertToRGBF(dib);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_RGBF, FreeImage.GetImageType(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertToStandardType()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertToStandardType(dib, true);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(FREE_IMAGE_COLOR_TYPE.FIC_PALETTE, FreeImage.GetColorType(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertToType()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_Unordered);
+ Assert.That(!dib.IsNull);
+ FIBITMAP temp = FreeImage.ConvertToType(dib, FREE_IMAGE_TYPE.FIT_UINT32, true);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_UINT32, FreeImage.GetImageType(temp));
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ToneMapping()
+ {
+ FIBITMAP temp;
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP rgbf = FreeImage.ConvertToRGBF(dib);
+ Assert.AreNotEqual(0, rgbf);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_RGBF, FreeImage.GetImageType(rgbf));
+ Assert.AreEqual(96, FreeImage.GetBPP(rgbf));
+
+ temp = FreeImage.ToneMapping(rgbf, FREE_IMAGE_TMO.FITMO_REINHARD05, 1f, 1.1f);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(24, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+
+ FreeImage.UnloadEx(ref rgbf);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_TmoDrago03()
+ {
+ FIBITMAP temp;
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP rgbf = FreeImage.ConvertToRGBF(dib);
+ Assert.AreNotEqual(0, rgbf);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_RGBF, FreeImage.GetImageType(rgbf));
+ Assert.AreEqual(96, FreeImage.GetBPP(rgbf));
+
+ temp = FreeImage.TmoDrago03(rgbf, 1f, 1.2f);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(24, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+
+ FreeImage.UnloadEx(ref rgbf);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_TmoReinhard05()
+ {
+ FIBITMAP temp;
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP rgbf = FreeImage.ConvertToRGBF(dib);
+ Assert.AreNotEqual(0, rgbf);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_RGBF, FreeImage.GetImageType(rgbf));
+ Assert.AreEqual(96, FreeImage.GetBPP(rgbf));
+
+ temp = FreeImage.TmoReinhard05(rgbf, 0f, 0.25f);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(24, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+
+ FreeImage.UnloadEx(ref rgbf);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_TmoFattal02()
+ {
+ FIBITMAP temp;
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP rgbf = FreeImage.ConvertToRGBF(dib);
+ Assert.AreNotEqual(0, rgbf);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_RGBF, FreeImage.GetImageType(rgbf));
+ Assert.AreEqual(96, FreeImage.GetBPP(rgbf));
+
+ temp = FreeImage.TmoFattal02(rgbf, 1f, 0.79f);
+ Assert.AreNotEqual(0, temp);
+ Assert.AreEqual(24, FreeImage.GetBPP(temp));
+ FreeImage.UnloadEx(ref temp);
+
+ FreeImage.UnloadEx(ref rgbf);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ZLibCompress_ZLibUncompress()
+ {
+ Random rand = new Random(DateTime.Now.Millisecond);
+ byte[] source = new byte[10240];
+ byte[] compressed = new byte[(int)(10355f * 1.01 + 12f)];
+ byte[] uncompressed = new byte[10240];
+ rand.NextBytes(source);
+ Assert.AreNotEqual(0, FreeImage.ZLibCompress(compressed, (uint)compressed.Length, source, (uint)source.Length));
+ Assert.AreNotEqual(0, FreeImage.ZLibUncompress(uncompressed, (uint)source.Length, compressed, (uint)compressed.Length));
+ for (int i = 0; i < source.Length; i++)
+ if (source[i] != uncompressed[i])
+ Assert.Fail();
+ }
+
+ [Test]
+ public void FreeImage_ZLibGZip_ZLibGUnzip()
+ {
+ Random rand = new Random(DateTime.Now.Millisecond);
+ byte[] source = new byte[10240];
+ byte[] compressed = new byte[(int)(10355f * 1.01 + 24f)];
+ byte[] uncompressed = new byte[10240];
+ rand.NextBytes(source);
+ Assert.AreNotEqual(0, FreeImage.ZLibGZip(compressed, (uint)compressed.Length, source, (uint)source.Length));
+ Assert.AreNotEqual(0, FreeImage.ZLibGUnzip(uncompressed, (uint)source.Length, compressed, (uint)compressed.Length));
+ for (int i = 0; i < source.Length; i++)
+ if (source[i] != uncompressed[i])
+ Assert.Fail();
+ }
+
+ [Test]
+ public void FreeImage_ZLibCRC32()
+ {
+ byte[] buffer = new byte[0];
+ Assert.AreEqual(0xFEBCA008, FreeImage.ZLibCRC32(0xFEBCA008, buffer, 0));
+ }
+
+ [Test]
+ public void FreeImage_CreateTag()
+ {
+ FITAG tag = FreeImage.CreateTag();
+ Assert.AreNotEqual(0, tag);
+ FITAG tag_clone = FreeImage.CloneTag(tag);
+ Assert.AreNotEqual(0, tag_clone);
+ FreeImage.DeleteTag(tag);
+ FreeImage.DeleteTag(tag_clone);
+ }
+
+ [Test]
+ public void FreeImage_Tag_accessors()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ Assert.IsTrue(FreeImage.FindNextMetadata(mData, out tag));
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagKey()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagKey(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagDescription()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagDescription(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagID()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagID(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagType()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagType(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagCount()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagCount(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagLength()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagLength(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTagValue()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.GetTagValue(tag);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagKey()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagKey(tag, "");
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagDescription()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagDescription(tag, "");
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagID()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagID(tag, 44);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagType()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagType(tag, FREE_IMAGE_MDTYPE.FIDT_ASCII);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagCount()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagCount(tag, 3);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagLength()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ FreeImage.SetTagLength(tag, 6);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTagValue()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ int length = (int)FreeImage.GetTagLength(tag);
+ FREE_IMAGE_MDTYPE type = FreeImage.GetTagType(tag);
+ int count = (int)FreeImage.GetTagCount(tag);
+
+ byte[] buffer = new byte[length * count];
+
+ FreeImage.SetTagValue(tag, buffer);
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetMetadataCount()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ Assert.AreNotEqual(0, FreeImage.GetMetadataCount(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_TagToString()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+
+ FITAG tag;
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, dib, out tag);
+ Assert.AreNotEqual(0, mData);
+ Assert.AreNotEqual(0, tag);
+
+ Assert.IsNotEmpty(FreeImage.TagToString(FREE_IMAGE_MDMODEL.FIMD_EXIF_EXIF, tag, 0));
+
+ FreeImage.FindCloseMetadata(mData);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_RotateClassic()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.RotateClassic(dib, 45d);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_RotateEx()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.RotateEx(dib, 261d, 0d, 33d, 51d, 9d, true);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_FlipHorizontal()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.FlipHorizontal(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_FlipVertical()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.FlipVertical(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_JPEGTransform()
+ {
+ string filename = iManager.GetBitmapPath(ImageType.JPEG, ImageColorType.Type_24);
+ string filenameOut = filename + ".out.jpg";
+ Assert.IsTrue(File.Exists(filename));
+
+ Assert.IsTrue(FreeImage.JPEGTransform(filename, filenameOut, FREE_IMAGE_JPEG_OPERATION.FIJPEG_OP_FLIP_V, false));
+ Assert.IsTrue(File.Exists(filenameOut));
+
+ FIBITMAP temp = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, filenameOut, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+ Assert.AreNotEqual(0, temp);
+
+ File.Delete(filenameOut);
+ Assert.IsFalse(File.Exists(filenameOut));
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Rescale()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_555);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.Rescale(dib, 100, 100, FREE_IMAGE_FILTER.FILTER_BICUBIC);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_MakeThumbnail()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_555);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.MakeThumbnail(dib, 50, false);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AdjustCurve()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ byte[] lut = new byte[256];
+ Assert.IsTrue(FreeImage.AdjustCurve(dib, lut, FREE_IMAGE_COLOR_CHANNEL.FICC_GREEN));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AdjustGamma()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.AdjustGamma(dib, 1.3d));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AdjustBrightness()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.AdjustBrightness(dib, 1.3d));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AdjustContrast()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.AdjustContrast(dib, 1.3d));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Invert()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_555);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.Invert(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetHistogram()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ int[] histo = new int[256];
+ Assert.IsTrue(FreeImage.GetHistogram(dib, histo, FREE_IMAGE_COLOR_CHANNEL.FICC_RED));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetChannel()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.GetChannel(dib, FREE_IMAGE_COLOR_CHANNEL.FICC_GREEN);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetChannel()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ FIBITMAP dib8 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.AreNotEqual(0, dib8);
+ Assert.AreEqual(FreeImage.GetWidth(dib), FreeImage.GetWidth(dib8));
+ Assert.AreEqual(FreeImage.GetHeight(dib), FreeImage.GetHeight(dib8));
+
+ Assert.IsTrue(FreeImage.SetChannel(dib, dib8, FREE_IMAGE_COLOR_CHANNEL.FICC_BLUE));
+
+ FreeImage.UnloadEx(ref dib8);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetComplexChannel()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.ConvertToType(dib, FREE_IMAGE_TYPE.FIT_COMPLEX, true);
+ Assert.AreNotEqual(0, temp);
+
+ FIBITMAP temp2 = FreeImage.GetComplexChannel(temp, FREE_IMAGE_COLOR_CHANNEL.FICC_IMAG);
+ Assert.AreNotEqual(0, temp2);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref temp2);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetComplexChannel()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_Unordered);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.ConvertToType(dib, FREE_IMAGE_TYPE.FIT_COMPLEX, true);
+ Assert.AreNotEqual(0, temp);
+
+ FIBITMAP temp2 = FreeImage.GetComplexChannel(temp, FREE_IMAGE_COLOR_CHANNEL.FICC_IMAG);
+ Assert.AreNotEqual(0, temp2);
+
+ Assert.IsTrue(FreeImage.SetComplexChannel(temp, temp2, FREE_IMAGE_COLOR_CHANNEL.FICC_IMAG));
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref temp2);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Copy()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.Copy(dib, 5, 9, 44, 2);
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Paste()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+
+ FIBITMAP temp = FreeImage.Allocate(3, 3, 8, 0, 0, 0);
+ Assert.IsTrue(FreeImage.Paste(dib, temp, 31, 3, 256));
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Composite()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+ RGBQUAD rgbq = new RGBQUAD();
+
+ FIBITMAP temp = FreeImage.Composite(dib, false, ref rgbq, new FIBITMAP());
+ Assert.AreNotEqual(0, temp);
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_JPEGCrop()
+ {
+ string filename = iManager.GetBitmapPath(ImageType.JPEG, ImageColorType.Type_01_Dither);
+ Assert.IsTrue(File.Exists(filename));
+ string filenameOut = filename + ".out.jpg";
+
+ Assert.IsTrue(FreeImage.JPEGCrop(filename, filenameOut, 3, 2, 1, 5));
+ Assert.IsTrue(File.Exists(filenameOut));
+
+ FIBITMAP temp = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_JPEG, filenameOut, FREE_IMAGE_LOAD_FLAGS.JPEG_ACCURATE);
+ Assert.AreNotEqual(0, temp);
+
+ File.Delete(filenameOut);
+ Assert.IsFalse(File.Exists(filenameOut));
+
+ FreeImage.UnloadEx(ref temp);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_PreMultiplyWithAlpha()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.IsTrue(FreeImage.PreMultiplyWithAlpha(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_MultigridPoissonSolver()
+ {
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_FLOAT, 10, 10, 32, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ FIBITMAP dib2 = FreeImage.MultigridPoissonSolver(dib, 2);
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+ }
+
+ [Test]
+ public void FreeImage_GetAdjustColorsLookupTable()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ byte[] lut = new byte[256];
+ FreeImage.GetAdjustColorsLookupTable(lut, 55d, 0d, 2.1d, false);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_AdjustColors()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.IsTrue(FreeImage.AdjustColors(dib, -4d, 22d, 1.1d, false));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Ignore]
+ public void FreeImage_ApplyColorMapping()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ FreeImage_ApplyColorMapping2(dib);
+ }
+
+ private void FreeImage_ApplyColorMapping2(FIBITMAP dib)
+ {
+ Assert.IsFalse(dib.IsNull);
+
+ Scanline<RGBQUAD> rgbqa = new Scanline<RGBQUAD>(dib, 0);
+
+ RGBQUAD[] src = new RGBQUAD[1];
+ RGBQUAD[] dst = new RGBQUAD[1];
+ src[0] = rgbqa[0];
+ dst[0].Color = src[0].Color == Color.White ? Color.Thistle : Color.White;
+
+ uint count = FreeImage.ApplyColorMapping(dib, src, dst, 1, true, false); // Memory
+ Assert.That(count > 0);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SwapColors()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_08);
+ Assert.IsFalse(dib.IsNull);
+
+ RGBQUAD src = new RGBQUAD(Color.FromArgb(93, 119, 170));
+ RGBQUAD dst = new RGBQUAD(Color.FromArgb(90, 130, 148));
+
+ uint count = FreeImage.SwapColors(dib, ref src, ref dst, true);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ApplyPaletteIndexMapping()
+ {
+ // alle farbtiefen
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_04);
+ Assert.IsFalse(dib.IsNull);
+
+ byte[] src = { 0, 3, 1 };
+ byte[] dst = { 3, 1, 0 };
+
+ uint count = FreeImage.ApplyPaletteIndexMapping(dib, src, dst, 3, false);
+ Assert.That(count > 0);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SwapPaletteIndices()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_04);
+ Assert.IsFalse(dib.IsNull);
+
+ byte src = 0;
+ byte dst = 3;
+
+ uint count = FreeImage.SwapPaletteIndices(dib, ref src, ref dst);
+ Assert.That(count > 0);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetTransparentIndex()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04);
+ Assert.IsFalse(dib.IsNull);
+
+ FreeImage.SetTransparentIndex(dib, 0);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetTransparentIndex()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04);
+ Assert.IsFalse(dib.IsNull);
+
+ int i = FreeImage.GetTransparentIndex(dib);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ [TestFixture]
+ public class ImportedStructsTest
+ {
+ ImageManager iManager = new ImageManager();
+ FIBITMAP dib = new FIBITMAP();
+ string freeImageCallback = null;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [TestFixtureTearDown]
+ public void DeInit()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [SetUp]
+ public void InitEachTime()
+ {
+ }
+
+ [TearDown]
+ public void DeInitEachTime()
+ {
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ freeImageCallback = message;
+ }
+
+ public bool EqualColors(Color color1, Color color2)
+ {
+ if (color1.A != color2.A) return false;
+ if (color1.R != color2.R) return false;
+ if (color1.G != color2.G) return false;
+ if (color1.B != color2.B) return false;
+ return true;
+ }
+
+ [Test]
+ public void RGBQUAD()
+ {
+ RGBQUAD rgbq = new RGBQUAD();
+ Assert.AreEqual(0, rgbq.rgbBlue);
+ Assert.AreEqual(0, rgbq.rgbGreen);
+ Assert.AreEqual(0, rgbq.rgbRed);
+ Assert.AreEqual(0, rgbq.rgbReserved);
+
+ rgbq = new RGBQUAD(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgbq.Color));
+
+ rgbq = new RGBQUAD(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173, rgbq.rgbBlue);
+ Assert.AreEqual(95, rgbq.rgbGreen);
+ Assert.AreEqual(83, rgbq.rgbRed);
+ Assert.AreEqual(133, rgbq.rgbReserved);
+
+ rgbq.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgbq.Color));
+
+ rgbq.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgbq.Color));
+
+ rgbq.Color = Color.White;
+ Assert.AreEqual(255, rgbq.rgbBlue);
+ Assert.AreEqual(255, rgbq.rgbGreen);
+ Assert.AreEqual(255, rgbq.rgbRed);
+ Assert.AreEqual(255, rgbq.rgbReserved);
+
+ rgbq.Color = Color.Black;
+ Assert.AreEqual(0, rgbq.rgbBlue);
+ Assert.AreEqual(0, rgbq.rgbGreen);
+ Assert.AreEqual(0, rgbq.rgbRed);
+ Assert.AreEqual(255, rgbq.rgbReserved);
+
+ rgbq = Color.DarkGoldenrod;
+ Color color = rgbq;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Test]
+ public void RGBTRIPLE()
+ {
+ RGBTRIPLE rgbt = new RGBTRIPLE();
+ Assert.AreEqual(0, rgbt.rgbtBlue);
+ Assert.AreEqual(0, rgbt.rgbtGreen);
+ Assert.AreEqual(0, rgbt.rgbtRed);
+
+ rgbt = new RGBTRIPLE(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgbt.Color));
+
+ rgbt = new RGBTRIPLE(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173, rgbt.rgbtBlue);
+ Assert.AreEqual(95, rgbt.rgbtGreen);
+ Assert.AreEqual(83, rgbt.rgbtRed);
+
+ rgbt.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgbt.Color));
+
+ rgbt.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgbt.Color));
+
+ rgbt.Color = Color.White;
+ Assert.AreEqual(255, rgbt.rgbtBlue);
+ Assert.AreEqual(255, rgbt.rgbtGreen);
+ Assert.AreEqual(255, rgbt.rgbtRed);
+
+ rgbt.Color = Color.Black;
+ Assert.AreEqual(0, rgbt.rgbtBlue);
+ Assert.AreEqual(0, rgbt.rgbtGreen);
+ Assert.AreEqual(0, rgbt.rgbtRed);
+
+ rgbt = Color.DarkGoldenrod;
+ Color color = rgbt;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Test]
+ public void FIRGB16()
+ {
+ FIRGB16 rgb = new FIRGB16();
+ Assert.AreEqual(0 * 256, rgb.blue);
+ Assert.AreEqual(0 * 256, rgb.green);
+ Assert.AreEqual(0 * 256, rgb.red);
+
+ rgb = new FIRGB16(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgb.Color));
+
+ rgb = new FIRGB16(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173 * 256, rgb.blue);
+ Assert.AreEqual(95 * 256, rgb.green);
+ Assert.AreEqual(83 * 256, rgb.red);
+
+ rgb.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgb.Color));
+
+ rgb.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgb.Color));
+
+ rgb.Color = Color.White;
+ Assert.AreEqual(255 * 256, rgb.blue);
+ Assert.AreEqual(255 * 256, rgb.green);
+ Assert.AreEqual(255 * 256, rgb.red);
+
+ rgb.Color = Color.Black;
+ Assert.AreEqual(0 * 256, rgb.blue);
+ Assert.AreEqual(0 * 256, rgb.green);
+ Assert.AreEqual(0 * 256, rgb.red);
+
+ rgb = Color.DarkGoldenrod;
+ Color color = rgb;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Test]
+ public void FIRGBA16()
+ {
+ FIRGBA16 rgb = new FIRGBA16();
+ Assert.AreEqual(0 * 256, rgb.blue);
+ Assert.AreEqual(0 * 256, rgb.green);
+ Assert.AreEqual(0 * 256, rgb.red);
+ Assert.AreEqual(0 * 256, rgb.alpha);
+
+ rgb = new FIRGBA16(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgb.Color));
+
+ rgb = new FIRGBA16(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173 * 256, rgb.blue);
+ Assert.AreEqual(95 * 256, rgb.green);
+ Assert.AreEqual(83 * 256, rgb.red);
+ Assert.AreEqual(133 * 256, rgb.alpha);
+
+ rgb.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgb.Color));
+
+ rgb.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgb.Color));
+
+ rgb.Color = Color.White;
+ Assert.AreEqual(255 * 256, rgb.blue);
+ Assert.AreEqual(255 * 256, rgb.green);
+ Assert.AreEqual(255 * 256, rgb.red);
+ Assert.AreEqual(255 * 256, rgb.alpha);
+
+ rgb.Color = Color.Black;
+ Assert.AreEqual(0 * 256, rgb.blue);
+ Assert.AreEqual(0 * 256, rgb.green);
+ Assert.AreEqual(0 * 256, rgb.red);
+ Assert.AreEqual(255 * 256, rgb.alpha);
+
+ rgb = Color.DarkGoldenrod;
+ Color color = rgb;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Test]
+ public void FIRGBF()
+ {
+ FIRGBF rgb = new FIRGBF();
+ Assert.AreEqual(0 / 255f, rgb.blue);
+ Assert.AreEqual(0 / 255f, rgb.green);
+ Assert.AreEqual(0 / 255f, rgb.red);
+
+ rgb = new FIRGBF(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgb.Color));
+
+ rgb = new FIRGBF(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173 / 255f, rgb.blue);
+ Assert.AreEqual(95 / 255f, rgb.green);
+ Assert.AreEqual(83 / 255f, rgb.red);
+
+ rgb.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgb.Color));
+
+ rgb.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgb.Color));
+
+ rgb.Color = Color.White;
+ Assert.AreEqual(255 / 255f, rgb.blue);
+ Assert.AreEqual(255 / 255f, rgb.green);
+ Assert.AreEqual(255 / 255f, rgb.red);
+
+ rgb.Color = Color.Black;
+ Assert.AreEqual(0 / 255f, rgb.blue);
+ Assert.AreEqual(0 / 255f, rgb.green);
+ Assert.AreEqual(0 / 255f, rgb.red);
+
+ rgb = Color.DarkGoldenrod;
+ Color color = rgb;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Test]
+ public void FIRGBAF()
+ {
+ FIRGBAF rgb = new FIRGBAF();
+ Assert.AreEqual(0 / 255f, rgb.blue);
+ Assert.AreEqual(0 / 255f, rgb.green);
+ Assert.AreEqual(0 / 255f, rgb.red);
+ Assert.AreEqual(0 / 255f, rgb.alpha);
+
+ rgb = new FIRGBAF(Color.Chartreuse);
+ Assert.That(EqualColors(Color.Chartreuse, rgb.Color));
+
+ rgb = new FIRGBAF(Color.FromArgb(133, 83, 95, 173));
+ Assert.AreEqual(173 / 255f, rgb.blue);
+ Assert.AreEqual(95 / 255f, rgb.green);
+ Assert.AreEqual(83 / 255f, rgb.red);
+ Assert.AreEqual(133 / 255f, rgb.alpha);
+
+ rgb.Color = Color.Crimson;
+ Assert.That(EqualColors(Color.Crimson, rgb.Color));
+
+ rgb.Color = Color.MidnightBlue;
+ Assert.That(EqualColors(Color.MidnightBlue, rgb.Color));
+
+ rgb.Color = Color.White;
+ Assert.AreEqual(255 / 255f, rgb.blue);
+ Assert.AreEqual(255 / 255f, rgb.green);
+ Assert.AreEqual(255 / 255f, rgb.red);
+ Assert.AreEqual(255 / 255f, rgb.alpha);
+
+ rgb.Color = Color.Black;
+ Assert.AreEqual(0 / 255f, rgb.blue);
+ Assert.AreEqual(0 / 255f, rgb.green);
+ Assert.AreEqual(0 / 255f, rgb.red);
+ Assert.AreEqual(255 / 255f, rgb.alpha);
+
+ rgb = Color.DarkGoldenrod;
+ Color color = rgb;
+ Assert.That(EqualColors(Color.DarkGoldenrod, color));
+ }
+
+ [Ignore]
+ public void FICOMPLEX()
+ {
+ }
+
+ [Test]
+ public void FIBITMAP()
+ {
+ FIBITMAP var = new FIBITMAP();
+ Assert.IsTrue(var.IsNull);
+ }
+
+ [Test]
+ public void fi_handle()
+ {
+ fi_handle var = new fi_handle();
+ Assert.IsTrue(var.IsNull);
+
+ string test = "hello word!";
+ using (var = new fi_handle(test))
+ {
+ Assert.IsFalse(var.IsNull);
+
+ object obj = var.GetObject();
+ Assert.That(obj is string);
+ Assert.AreSame(obj, test);
+ }
+ }
+
+ [Test]
+ public void FIICCPROFILE()
+ {
+ Random rand = new Random(DateTime.Now.Millisecond);
+ FIICCPROFILE var = new FIICCPROFILE();
+ Assert.AreEqual(0, var.Data.Length);
+ Assert.AreEqual(IntPtr.Zero, var.DataPointer);
+ Assert.AreEqual(0, var.Size);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ byte[] data = new byte[512];
+ rand.NextBytes(data);
+
+ var = FreeImage.GetICCProfileEx(dib);
+ Assert.AreEqual(0, var.Size);
+
+ var = new FIICCPROFILE(dib, data, 256);
+ Assert.AreEqual(256, var.Data.Length);
+ Assert.AreNotEqual(IntPtr.Zero, var.DataPointer);
+ Assert.AreEqual(256, var.Size);
+ byte[] dataComp = var.Data;
+ for (int i = 0; i < data.Length && i < dataComp.Length; i++)
+ if (data[i] != dataComp[i])
+ Assert.Fail();
+
+ FreeImage.DestroyICCProfile(dib);
+ var = FreeImage.GetICCProfileEx(dib);
+ Assert.AreEqual(0, var.Size);
+
+ var = new FIICCPROFILE(dib, data);
+ Assert.AreEqual(512, var.Data.Length);
+ Assert.AreNotEqual(IntPtr.Zero, var.DataPointer);
+ Assert.AreEqual(512, var.Size);
+ dataComp = var.Data;
+ for (int i = 0; i < data.Length && i < dataComp.Length; i++)
+ if (data[i] != dataComp[i])
+ Assert.Fail();
+
+ var = FreeImage.GetICCProfileEx(dib);
+ Assert.AreEqual(512, var.Data.Length);
+ Assert.AreNotEqual(IntPtr.Zero, var.DataPointer);
+ Assert.AreEqual(512, var.Size);
+
+ FreeImage.DestroyICCProfile(dib);
+ var = FreeImage.GetICCProfileEx(dib);
+ Assert.AreEqual(0, var.Size);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ [TestFixture]
+ public class WrapperStructsTest
+ {
+ ImageManager iManager = new ImageManager();
+ FIBITMAP dib = new FIBITMAP();
+ string freeImageCallback = null;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [TestFixtureTearDown]
+ public void DeInit()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [SetUp]
+ public void InitEachTime()
+ {
+ }
+
+ [TearDown]
+ public void DeInitEachTime()
+ {
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ freeImageCallback = message;
+ }
+
+ public bool EqualColors(Color color1, Color color2)
+ {
+ if (color1.A != color2.A) return false;
+ if (color1.R != color2.R) return false;
+ if (color1.G != color2.G) return false;
+ if (color1.B != color2.B) return false;
+ return true;
+ }
+
+ [Test]
+ public void FIRational()
+ {
+ FIRational rational1 = new FIRational();
+ FIRational rational2 = new FIRational();
+ FIRational rational3 = new FIRational();
+
+ //
+ // Constructors
+ //
+
+ Assert.That(rational1.Numerator == 0);
+ Assert.That(rational1.Denominator == 0);
+
+ rational1 = new FIRational(412, 33);
+ Assert.That(rational1.Numerator == 412);
+ Assert.That(rational1.Denominator == 33);
+
+ rational2 = new FIRational(rational1);
+ Assert.That(rational2.Numerator == 412);
+ Assert.That(rational2.Denominator == 33);
+
+ rational3 = new FIRational(5.75m);
+ Assert.That(rational3.Numerator == 23);
+ Assert.That(rational3.Denominator == 4);
+
+ //
+ // == !=
+ //
+
+ rational1 = new FIRational(421, 51);
+ rational2 = rational1;
+ Assert.That(rational1 == rational2);
+ Assert.That(!(rational1 != rational2));
+
+ rational2 = new FIRational(1, 7);
+ Assert.That(rational1 != rational2);
+ Assert.That(!(rational1 == rational2));
+
+ //
+ // > >= < <=
+ //
+
+ rational1 = new FIRational(51, 4);
+ rational2 = new FIRational(27, 9);
+ Assert.That(rational1 != rational2);
+ Assert.That(rational1 > rational2);
+ Assert.That(rational1 >= rational2);
+
+ rational1 = new FIRational(-412, 4);
+ Assert.That(rational1 != rational2);
+ Assert.That(rational1 < rational2);
+ Assert.That(rational1 <= rational2);
+
+ //
+ // + / -
+ //
+
+ rational1 = new FIRational(41, 3);
+ rational2 = new FIRational(612, 412);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(-7852, 63);
+ rational2 = new FIRational(666111, -7654);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(-513, 88);
+ rational2 = new FIRational(413, 5);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(-513, 88);
+ rational2 = new FIRational(413, 5);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(7531, 23144);
+ rational2 = new FIRational(-412, 78777);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(513, -42123);
+ rational2 = new FIRational(-42, 77);
+ rational3 = rational1 - rational2;
+ Assert.That((rational3 + rational2) == rational1);
+
+ rational1 = new FIRational(44, 11);
+ rational1 = -rational1;
+ Assert.That(rational1.Numerator == -4 && rational1.Denominator == 1);
+
+ //
+ // %
+ //
+
+ rational1 = new FIRational(23, 8);
+ rational2 = new FIRational(77, 777);
+ Assert.That((rational1 % rational2) == 0);
+
+ rational2 = -rational2;
+ Assert.That((rational1 % rational2) == 0);
+
+ rational2 = new FIRational(7, 4);
+ rational3 = new FIRational(9, 8);
+ Assert.That((rational1 % rational2) == rational3);
+
+ rational2 = -rational2;
+ Assert.That((rational1 % rational2) == rational3);
+
+ //
+ // ~
+ //
+
+ rational1 = new FIRational(41, 77);
+ rational1 = ~rational1;
+ Assert.That(rational1.Numerator == 77 && rational1.Denominator == 41);
+
+ //
+ // -
+ //
+
+ rational1 = new FIRational(52, 4);
+ rational1 = -rational1;
+ Assert.That(rational1 < 0);
+
+ //
+ // ++ --
+ //
+
+ rational1 = new FIRational(5, 3);
+ rational1++;
+ rational2 = new FIRational(8, 3);
+ Assert.That(rational1 == rational2);
+
+ rational1 = new FIRational(41, -43);
+ rational1++;
+ Assert.That(rational1 > 0.0f);
+
+ rational1--;
+ Assert.That(rational1 == new FIRational(41, -43));
+
+ rational1 = new FIRational(8134, 312);
+ Assert.That(rational1 != 26);
+
+ //
+ // Direct assigns
+ //
+
+ rational1 = (FIRational)0.75m;
+ Assert.That(rational1.Numerator == 3 && rational1.Denominator == 4);
+ rational1 = (FIRational)0.33;
+ Assert.That(rational1.Numerator == 33 && rational1.Denominator == 100);
+ rational1 = (FIRational)62.975m;
+ Assert.That(((decimal)rational1.Numerator / (decimal)rational1.Denominator) == 62.975m);
+ rational1 = (FIRational)(-73.0975m);
+ Assert.That(((decimal)rational1.Numerator / (decimal)rational1.Denominator) == -73.0975m);
+ rational1 = (FIRational)(7m / 9m);
+ Assert.That(rational1.Numerator == 7 && rational1.Denominator == 9);
+ rational1 = (FIRational)(-15m / 9m);
+ Assert.That(rational1.Numerator == -5 && rational1.Denominator == 3);
+ rational1 = (FIRational)(0.7777m);
+ Assert.That(rational1.Denominator != 9);
+
+ //
+ // Properties
+ //
+
+ rational1 = new FIRational(515, 5);
+ Assert.That(rational1.IsInteger);
+
+ rational1 = new FIRational(876, 77);
+ Assert.That(rational1.Truncate() == (876 / 77));
+
+ //
+ // Special cases
+ //
+
+ rational1 = new FIRational(0, 10000);
+ Assert.That(rational1 == 0m);
+
+ rational1 = new FIRational(10000, 0);
+ Assert.That(rational1 == 0f);
+
+ rational1 = new FIRational(0, 0);
+ Assert.That(rational1 == 0d);
+
+ rational1 = new FIRational(-1, 0);
+ Assert.That(rational1 == 0);
+
+ rational1 = new FIRational(0, -1);
+ Assert.That(rational1 == 0);
+ }
+
+ [Ignore]
+ public void StreamWrapper()
+ {
+ string url = @"http://freeimage.sourceforge.net/images/logo.jpg";
+
+ //
+ // Non blocking
+ //
+
+ HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
+ Assert.IsNotNull(req);
+
+ req.Timeout = 1000;
+ HttpWebResponse resp;
+ try
+ {
+ resp = (HttpWebResponse)req.GetResponse();
+ }
+ catch
+ {
+ return;
+ }
+ Assert.IsNotNull(resp);
+
+ Stream stream = resp.GetResponseStream();
+ Assert.IsNotNull(stream);
+
+ StreamWrapper wrapper = new StreamWrapper(stream, false);
+ Assert.IsNotNull(wrapper);
+ Assert.IsTrue(wrapper.CanRead && wrapper.CanSeek && !wrapper.CanWrite);
+
+ byte[] buffer = new byte[1024 * 100];
+ int read;
+ int count = 0;
+
+ do
+ {
+ read = wrapper.Read(buffer, count, buffer.Length - count);
+ count += read;
+ } while (read != 0);
+
+ Assert.AreEqual(7972, count);
+ Assert.AreEqual(7972, wrapper.Length);
+
+ wrapper.Position = 0;
+ Assert.AreEqual(0, wrapper.Position);
+
+ byte[] test = new byte[buffer.Length];
+ int countTest = 0;
+
+ do
+ {
+ read = wrapper.Read(test, countTest, test.Length - countTest);
+ countTest += read;
+ } while (read != 0);
+
+ Assert.AreEqual(count, countTest);
+
+ for (int i = 0; i < countTest; i++)
+ if (buffer[i] != test[i])
+ Assert.Fail();
+
+ resp.Close();
+ wrapper.Dispose();
+ stream.Dispose();
+
+ //
+ // Blocking
+ //
+
+ req = (HttpWebRequest)HttpWebRequest.Create(url);
+ Assert.IsNotNull(req);
+
+ resp = (HttpWebResponse)req.GetResponse();
+ Assert.IsNotNull(resp);
+
+ stream = resp.GetResponseStream();
+ Assert.IsNotNull(stream);
+
+ wrapper = new StreamWrapper(stream, true);
+ Assert.IsNotNull(wrapper);
+ Assert.IsTrue(wrapper.CanRead && wrapper.CanSeek && !wrapper.CanWrite);
+
+ buffer = new byte[1024 * 100];
+ count = 0;
+
+ count = wrapper.Read(buffer, 0, buffer.Length);
+ Assert.AreEqual(7972, count);
+
+ resp.Close();
+ stream.Dispose();
+ wrapper.Dispose();
+
+ //
+ // Position & Read byte
+ //
+
+ buffer = new byte[] { 0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD };
+ stream = new MemoryStream(buffer);
+ wrapper = new StreamWrapper(stream, false);
+
+ Assert.That(0x00 == wrapper.ReadByte());
+ Assert.That(0x01 == wrapper.ReadByte());
+ Assert.That(0x02 == wrapper.ReadByte());
+ Assert.That(0xFF == wrapper.ReadByte());
+ Assert.That(0xFE == wrapper.ReadByte());
+ Assert.That(0xFD == wrapper.ReadByte());
+ Assert.That(-1 == wrapper.ReadByte());
+
+ Assert.That(wrapper.Length == buffer.Length);
+
+ wrapper.Seek(0, SeekOrigin.Begin);
+ Assert.That(0x00 == wrapper.ReadByte());
+ wrapper.Seek(3, SeekOrigin.Begin);
+ Assert.That(0xFF == wrapper.ReadByte());
+ wrapper.Seek(0, SeekOrigin.End);
+ Assert.That(-1 == wrapper.ReadByte());
+ wrapper.Seek(-2, SeekOrigin.End);
+ Assert.That(0xFE == wrapper.ReadByte());
+ wrapper.Seek(0, SeekOrigin.Begin);
+ Assert.That(0x00 == wrapper.ReadByte());
+ wrapper.Seek(2, SeekOrigin.Current);
+ Assert.That(0xFF == wrapper.ReadByte());
+ wrapper.Seek(1, SeekOrigin.Current);
+ Assert.That(0xFD == wrapper.ReadByte());
+ Assert.That(wrapper.Position != 0);
+ wrapper.Reset();
+ Assert.That(wrapper.Position == 0);
+
+ wrapper.Dispose();
+ stream.Position = 0;
+ wrapper = new StreamWrapper(stream, false);
+
+ wrapper.Seek(10, SeekOrigin.Begin);
+ Assert.That(wrapper.Position == buffer.Length);
+
+ wrapper.Dispose();
+ stream.Dispose();
+ }
+
+ [Ignore]
+ public void LocalPlugin()
+ {
+ }
+
+ [Test]
+ public void FreeImageStreamIO()
+ {
+ Random rand = new Random();
+ byte[] bBuffer = new byte[256];
+ IntPtr buffer = Marshal.AllocHGlobal(256);
+
+ MemoryStream stream = new MemoryStream();
+ Assert.IsNotNull(stream);
+ using (fi_handle handle = new fi_handle(stream))
+ {
+
+ FreeImageIO io = FreeImageAPI.IO.FreeImageStreamIO.io;
+ Assert.IsNotNull(io.readProc);
+ Assert.IsNotNull(io.writeProc);
+ Assert.IsNotNull(io.seekProc);
+ Assert.IsNotNull(io.tellProc);
+
+ //
+ // Procs
+ //
+
+ rand.NextBytes(bBuffer);
+
+ stream.Write(bBuffer, 0, bBuffer.Length);
+ Assert.That(io.tellProc(handle) == stream.Position);
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.Begin) == 0);
+ Assert.That(io.tellProc(handle) == 0);
+ Assert.That(io.tellProc(handle) == stream.Position);
+
+ // Read one block
+ Assert.That(io.readProc(buffer, (uint)bBuffer.Length, 1, handle) == 1);
+ for (int i = 0; i < bBuffer.Length; i++)
+ Assert.That(Marshal.ReadByte(buffer, i) == bBuffer[i]);
+
+ Assert.That(io.tellProc(handle) == stream.Position);
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.Begin) == 0);
+ Assert.That(io.tellProc(handle) == stream.Position);
+
+ // Read 1 byte block
+ Assert.That(io.readProc(buffer, 1, (uint)bBuffer.Length, handle) == bBuffer.Length);
+ for (int i = 0; i < bBuffer.Length; i++)
+ Assert.That(Marshal.ReadByte(buffer, i) == bBuffer[i]);
+
+ Assert.That(io.tellProc(handle) == stream.Position);
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.Begin) == 0);
+ Assert.That(io.tellProc(handle) == stream.Position);
+
+ rand.NextBytes(bBuffer);
+ for (int i = 0; i < bBuffer.Length; i++)
+ Marshal.WriteByte(buffer, i, bBuffer[i]);
+
+ // Write one block
+
+ Assert.That(io.writeProc(buffer, (uint)bBuffer.Length, 1, handle) == 1);
+ for (int i = 0; i < bBuffer.Length; i++)
+ Assert.That(Marshal.ReadByte(buffer, i) == bBuffer[i]);
+ Assert.That(io.tellProc(handle) == stream.Position);
+
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.Begin) == 0);
+ Assert.That(io.tellProc(handle) == 0);
+
+ // write 1 byte block
+
+ Assert.That(io.writeProc(buffer, 1, (uint)bBuffer.Length, handle) == bBuffer.Length);
+ for (int i = 0; i < bBuffer.Length; i++)
+ Assert.That(Marshal.ReadByte(buffer, i) == bBuffer[i]);
+ Assert.That(io.tellProc(handle) == stream.Position);
+
+ // Seek and tell
+
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.Begin) == 0);
+ Assert.That(io.tellProc(handle) == 0);
+
+ Assert.That(io.seekProc(handle, 127, SeekOrigin.Current) == 0);
+ Assert.That(io.tellProc(handle) == 127);
+
+ Assert.That(io.seekProc(handle, 0, SeekOrigin.End) == 0);
+ Assert.That(io.tellProc(handle) == 256);
+
+ Marshal.FreeHGlobal(buffer);
+ stream.Dispose();
+ }
+ }
+
+ [Test]
+ public void MetadataTag()
+ {
+ FITAG tag;
+ MetadataTag metaTag;
+
+ Random rand = new Random();
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.That(FreeImage.GetMetadataCount(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib) > 0);
+
+ FIMETADATA mData = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib, out tag);
+ Assert.IsFalse(tag.IsNull);
+ Assert.IsFalse(mData.IsNull);
+
+ //
+ // Constructors
+ //
+
+ metaTag = new MetadataTag(tag, dib);
+ Assert.That(metaTag.Model == FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN);
+
+ metaTag = new MetadataTag(tag, FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN);
+ Assert.That(metaTag.Model == FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN);
+
+ //
+ // Properties
+ //
+
+ metaTag.ID = ushort.MinValue;
+ Assert.That(metaTag.ID == ushort.MinValue);
+
+ metaTag.ID = ushort.MaxValue;
+ Assert.That(metaTag.ID == ushort.MaxValue);
+
+ metaTag.ID = ushort.MaxValue / 2;
+ Assert.That(metaTag.ID == ushort.MaxValue / 2);
+
+ metaTag.Description = "";
+ Assert.That(metaTag.Description == "");
+
+ metaTag.Description = "A";
+ Assert.That(metaTag.Description == "A");
+
+ metaTag.Description = "ABCDEFG";
+ Assert.That(metaTag.Description == "ABCDEFG");
+
+ metaTag.Key = "";
+ Assert.That(metaTag.Key == "");
+
+ metaTag.Key = "A";
+ Assert.That(metaTag.Key == "A");
+
+ metaTag.Key = "ABCDEFG";
+ Assert.That(metaTag.Key == "ABCDEFG");
+
+ //
+ // SetValue
+ //
+
+ try
+ {
+ metaTag.SetValue(null, FREE_IMAGE_MDTYPE.FIDT_ASCII);
+ Assert.Fail();
+ }
+ catch
+ {
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_ASCII
+ //
+
+ string testString = "";
+
+ Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((string)metaTag.Value).Length == 0);
+
+ testString = "X";
+
+ Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((string)metaTag.Value).Length == testString.Length);
+ Assert.That(((string)metaTag.Value) == testString);
+
+ testString = "TEST-STRING";
+
+ Assert.IsTrue(metaTag.SetValue(testString, FREE_IMAGE_MDTYPE.FIDT_ASCII));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((string)metaTag.Value).Length == testString.Length);
+ Assert.That(((string)metaTag.Value) == testString);
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_BYTE
+ //
+
+ byte testByte;
+ byte[] testByteArray;
+
+ Assert.IsTrue(metaTag.SetValue(byte.MinValue, FREE_IMAGE_MDTYPE.FIDT_BYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(((byte[])metaTag.Value)[0] == byte.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(byte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_BYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(((byte[])metaTag.Value)[0] == byte.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testByte = (byte)rand.Next(byte.MinValue, byte.MaxValue);
+ testByteArray = new byte[rand.Next(0, 31)];
+
+ for (int j = 0; j < testByteArray.Length; j++)
+ testByteArray[j] = (byte)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testByte, FREE_IMAGE_MDTYPE.FIDT_BYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 1);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_BYTE);
+ Assert.That(((byte[])metaTag.Value)[0] == testByte);
+
+ Assert.IsTrue(metaTag.SetValue(testByteArray, FREE_IMAGE_MDTYPE.FIDT_BYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == testByteArray.Length);
+ Assert.That(metaTag.Count == testByteArray.Length);
+ Assert.That(metaTag.Length == testByteArray.Length * 1);
+
+ byte[] value = (byte[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testByteArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_DOUBLE
+ //
+
+ double testDouble;
+ double[] testDoubleArray;
+
+ Assert.IsTrue(metaTag.SetValue(double.MinValue, FREE_IMAGE_MDTYPE.FIDT_DOUBLE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((double[])metaTag.Value).Length == 1);
+ Assert.That(((double[])metaTag.Value)[0] == double.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(double.MaxValue, FREE_IMAGE_MDTYPE.FIDT_DOUBLE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((double[])metaTag.Value).Length == 1);
+ Assert.That(((double[])metaTag.Value)[0] == double.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testDouble = (double)rand.NextDouble();
+ testDoubleArray = new double[rand.Next(0, 31)];
+
+ for (int j = 0; j < testDoubleArray.Length; j++)
+ testDoubleArray[j] = rand.NextDouble();
+
+ Assert.IsTrue(metaTag.SetValue(testDouble, FREE_IMAGE_MDTYPE.FIDT_DOUBLE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((double[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 8);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_DOUBLE);
+ Assert.That(((double[])metaTag.Value)[0] == testDouble);
+
+ Assert.IsTrue(metaTag.SetValue(testDoubleArray, FREE_IMAGE_MDTYPE.FIDT_DOUBLE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((double[])metaTag.Value).Length == testDoubleArray.Length);
+ Assert.That(metaTag.Count == testDoubleArray.Length);
+ Assert.That(metaTag.Length == testDoubleArray.Length * 8);
+
+ double[] value = (double[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testDoubleArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_FLOAT
+ //
+
+ float testfloat;
+ float[] testFloatArray;
+
+ Assert.IsTrue(metaTag.SetValue(float.MinValue, FREE_IMAGE_MDTYPE.FIDT_FLOAT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((float[])metaTag.Value).Length == 1);
+ Assert.That(((float[])metaTag.Value)[0] == float.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(float.MaxValue, FREE_IMAGE_MDTYPE.FIDT_FLOAT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((float[])metaTag.Value).Length == 1);
+ Assert.That(((float[])metaTag.Value)[0] == float.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testfloat = (float)rand.NextDouble();
+ testFloatArray = new float[rand.Next(0, 31)];
+
+ for (int j = 0; j < testFloatArray.Length; j++)
+ testFloatArray[j] = (float)rand.NextDouble();
+
+ Assert.IsTrue(metaTag.SetValue(testfloat, FREE_IMAGE_MDTYPE.FIDT_FLOAT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((float[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 4);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_FLOAT);
+ Assert.That(((float[])metaTag.Value)[0] == testfloat);
+
+ Assert.IsTrue(metaTag.SetValue(testFloatArray, FREE_IMAGE_MDTYPE.FIDT_FLOAT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((float[])metaTag.Value).Length == testFloatArray.Length);
+ Assert.That(metaTag.Count == testFloatArray.Length);
+ Assert.That(metaTag.Length == testFloatArray.Length * 4);
+
+ float[] value = (float[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testFloatArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_IFD
+ //
+
+ uint testUint;
+ uint[] testUintArray;
+
+ Assert.IsTrue(metaTag.SetValue(uint.MinValue, FREE_IMAGE_MDTYPE.FIDT_IFD));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(((uint[])metaTag.Value)[0] == uint.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(uint.MaxValue, FREE_IMAGE_MDTYPE.FIDT_IFD));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(((uint[])metaTag.Value)[0] == uint.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testUint = (uint)rand.NextDouble();
+ testUintArray = new uint[rand.Next(0, 31)];
+
+ for (int j = 0; j < testUintArray.Length; j++)
+ testUintArray[j] = (uint)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testUint, FREE_IMAGE_MDTYPE.FIDT_IFD));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 4);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_IFD);
+ Assert.That(((uint[])metaTag.Value)[0] == testUint);
+
+ Assert.IsTrue(metaTag.SetValue(testUintArray, FREE_IMAGE_MDTYPE.FIDT_IFD));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == testUintArray.Length);
+ Assert.That(metaTag.Count == testUintArray.Length);
+ Assert.That(metaTag.Length == testUintArray.Length * 4);
+
+ uint[] value = (uint[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testUintArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_LONG
+ //
+
+ Assert.IsTrue(metaTag.SetValue(uint.MinValue, FREE_IMAGE_MDTYPE.FIDT_LONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(((uint[])metaTag.Value)[0] == uint.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(uint.MaxValue, FREE_IMAGE_MDTYPE.FIDT_LONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(((uint[])metaTag.Value)[0] == uint.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testUint = (uint)rand.NextDouble();
+ testUintArray = new uint[rand.Next(0, 31)];
+
+ for (int j = 0; j < testUintArray.Length; j++)
+ testUintArray[j] = (uint)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testUint, FREE_IMAGE_MDTYPE.FIDT_LONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 4);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_LONG);
+ Assert.That(((uint[])metaTag.Value)[0] == testUint);
+
+ Assert.IsTrue(metaTag.SetValue(testUintArray, FREE_IMAGE_MDTYPE.FIDT_LONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((uint[])metaTag.Value).Length == testUintArray.Length);
+ Assert.That(metaTag.Count == testUintArray.Length);
+ Assert.That(metaTag.Length == testUintArray.Length * 4);
+
+ uint[] value = (uint[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testUintArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_NOTYPE
+ //
+
+ try
+ {
+ metaTag.SetValue(new object(), FREE_IMAGE_MDTYPE.FIDT_NOTYPE);
+ Assert.Fail();
+ }
+ catch (NotSupportedException)
+ {
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_PALETTE
+ //
+
+ RGBQUAD testRGBQUAD;
+ RGBQUAD[] testRGBQUADArray;
+
+ for (int i = 0; i < 10; i++)
+ {
+ testRGBQUAD = new RGBQUAD(Color.FromArgb(rand.Next()));
+ testRGBQUADArray = new RGBQUAD[rand.Next(0, 31)];
+
+ for (int j = 0; j < testRGBQUADArray.Length; j++)
+ testRGBQUADArray[j] = new RGBQUAD(Color.FromArgb(rand.Next()));
+
+ Assert.IsTrue(metaTag.SetValue(testRGBQUAD, FREE_IMAGE_MDTYPE.FIDT_PALETTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((RGBQUAD[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 4);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_PALETTE);
+ Assert.That(((RGBQUAD[])metaTag.Value)[0] == testRGBQUAD);
+
+ Assert.IsTrue(metaTag.SetValue(testRGBQUADArray, FREE_IMAGE_MDTYPE.FIDT_PALETTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((RGBQUAD[])metaTag.Value).Length == testRGBQUADArray.Length);
+ Assert.That(metaTag.Count == testRGBQUADArray.Length);
+ Assert.That(metaTag.Length == testRGBQUADArray.Length * 4);
+
+ RGBQUAD[] value = (RGBQUAD[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testRGBQUADArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_RATIONAL
+ //
+
+ FIURational testFIURational;
+ FIURational[] testFIURationalArray;
+
+ for (int i = 0; i < 10; i++)
+ {
+ testFIURational = new FIURational((uint)rand.Next(), (uint)rand.Next());
+ testFIURationalArray = new FIURational[rand.Next(0, 31)];
+
+ for (int j = 0; j < testFIURationalArray.Length; j++)
+ testFIURationalArray[j] = new FIURational((uint)rand.Next(), (uint)rand.Next());
+
+ Assert.IsTrue(metaTag.SetValue(testFIURational, FREE_IMAGE_MDTYPE.FIDT_RATIONAL));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((FIURational[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 8);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_RATIONAL);
+ Assert.That(((FIURational[])metaTag.Value)[0] == testFIURational);
+
+ Assert.IsTrue(metaTag.SetValue(testFIURationalArray, FREE_IMAGE_MDTYPE.FIDT_RATIONAL));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((FIURational[])metaTag.Value).Length == testFIURationalArray.Length);
+ Assert.That(metaTag.Count == testFIURationalArray.Length);
+ Assert.That(metaTag.Length == testFIURationalArray.Length * 8);
+
+ FIURational[] value = (FIURational[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testFIURationalArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_SBYTE
+ //
+
+ sbyte testSByte;
+ sbyte[] testSByteArray;
+
+ Assert.IsTrue(metaTag.SetValue(sbyte.MinValue, FREE_IMAGE_MDTYPE.FIDT_SBYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((sbyte[])metaTag.Value).Length == 1);
+ Assert.That(((sbyte[])metaTag.Value)[0] == sbyte.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(sbyte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SBYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((sbyte[])metaTag.Value).Length == 1);
+ Assert.That(((sbyte[])metaTag.Value)[0] == sbyte.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testSByte = (sbyte)rand.Next(sbyte.MinValue, sbyte.MaxValue);
+ testSByteArray = new sbyte[rand.Next(0, 31)];
+
+ for (int j = 0; j < testSByteArray.Length; j++)
+ testSByteArray[j] = (sbyte)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testSByte, FREE_IMAGE_MDTYPE.FIDT_SBYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((sbyte[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 1);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SBYTE);
+ Assert.That(((sbyte[])metaTag.Value)[0] == testSByte);
+
+ Assert.IsTrue(metaTag.SetValue(testSByteArray, FREE_IMAGE_MDTYPE.FIDT_SBYTE));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((sbyte[])metaTag.Value).Length == testSByteArray.Length);
+ Assert.That(metaTag.Count == testSByteArray.Length);
+ Assert.That(metaTag.Length == testSByteArray.Length * 1);
+
+ sbyte[] value = (sbyte[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testSByteArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_SHORT
+ //
+
+ ushort testUShort;
+ ushort[] testUShortArray;
+
+ Assert.IsTrue(metaTag.SetValue(ushort.MinValue, FREE_IMAGE_MDTYPE.FIDT_SHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((ushort[])metaTag.Value).Length == 1);
+ Assert.That(((ushort[])metaTag.Value)[0] == ushort.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(ushort.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((ushort[])metaTag.Value).Length == 1);
+ Assert.That(((ushort[])metaTag.Value)[0] == ushort.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testUShort = (ushort)rand.Next(ushort.MinValue, sbyte.MaxValue);
+ testUShortArray = new ushort[rand.Next(0, 31)];
+
+ for (int j = 0; j < testUShortArray.Length; j++)
+ testUShortArray[j] = (ushort)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testUShort, FREE_IMAGE_MDTYPE.FIDT_SHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((ushort[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 2);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SHORT);
+ Assert.That(((ushort[])metaTag.Value)[0] == testUShort);
+
+ Assert.IsTrue(metaTag.SetValue(testUShortArray, FREE_IMAGE_MDTYPE.FIDT_SHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((ushort[])metaTag.Value).Length == testUShortArray.Length);
+ Assert.That(metaTag.Count == testUShortArray.Length);
+ Assert.That(metaTag.Length == testUShortArray.Length * 2);
+
+ ushort[] value = (ushort[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testUShortArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_SLONG
+ //
+
+ int testInt;
+ int[] testIntArray;
+
+ Assert.IsTrue(metaTag.SetValue(int.MinValue, FREE_IMAGE_MDTYPE.FIDT_SLONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((int[])metaTag.Value).Length == 1);
+ Assert.That(((int[])metaTag.Value)[0] == int.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(int.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SLONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((int[])metaTag.Value).Length == 1);
+ Assert.That(((int[])metaTag.Value)[0] == int.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testInt = (int)rand.NextDouble();
+ testIntArray = new int[rand.Next(0, 31)];
+
+ for (int j = 0; j < testIntArray.Length; j++)
+ testIntArray[j] = rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testInt, FREE_IMAGE_MDTYPE.FIDT_SLONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((int[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 4);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SLONG);
+ Assert.That(((int[])metaTag.Value)[0] == testInt);
+
+ Assert.IsTrue(metaTag.SetValue(testIntArray, FREE_IMAGE_MDTYPE.FIDT_SLONG));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((int[])metaTag.Value).Length == testIntArray.Length);
+ Assert.That(metaTag.Count == testIntArray.Length);
+ Assert.That(metaTag.Length == testIntArray.Length * 4);
+
+ int[] value = (int[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testIntArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_SRATIONAL
+ //
+
+ FIRational testFIRational;
+ FIRational[] testFIRationalArray;
+
+ for (int i = 0; i < 10; i++)
+ {
+ testFIRational = new FIRational(rand.Next(), rand.Next());
+ testFIRationalArray = new FIRational[rand.Next(0, 31)];
+
+ for (int j = 0; j < testFIRationalArray.Length; j++)
+ testFIRationalArray[j] = new FIRational(rand.Next(), rand.Next());
+
+ Assert.IsTrue(metaTag.SetValue(testFIRational, FREE_IMAGE_MDTYPE.FIDT_SRATIONAL));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((FIRational[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 8);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SRATIONAL);
+ Assert.That(((FIRational[])metaTag.Value)[0] == testFIRational);
+
+ Assert.IsTrue(metaTag.SetValue(testFIRationalArray, FREE_IMAGE_MDTYPE.FIDT_SRATIONAL));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((FIRational[])metaTag.Value).Length == testFIRationalArray.Length);
+ Assert.That(metaTag.Count == testFIRationalArray.Length);
+ Assert.That(metaTag.Length == testFIRationalArray.Length * 8);
+
+ FIRational[] value = (FIRational[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testFIRationalArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_SSHORT
+ //
+
+ short testShort;
+ short[] testShortArray;
+
+ Assert.IsTrue(metaTag.SetValue(short.MinValue, FREE_IMAGE_MDTYPE.FIDT_SSHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((short[])metaTag.Value).Length == 1);
+ Assert.That(((short[])metaTag.Value)[0] == short.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(short.MaxValue, FREE_IMAGE_MDTYPE.FIDT_SSHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((short[])metaTag.Value).Length == 1);
+ Assert.That(((short[])metaTag.Value)[0] == short.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testShort = (short)rand.Next(short.MinValue, short.MaxValue);
+ testShortArray = new short[rand.Next(0, 31)];
+
+ for (int j = 0; j < testShortArray.Length; j++)
+ testShortArray[j] = (short)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testShort, FREE_IMAGE_MDTYPE.FIDT_SSHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((short[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 2);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_SSHORT);
+ Assert.That(((short[])metaTag.Value)[0] == testShort);
+
+ Assert.IsTrue(metaTag.SetValue(testShortArray, FREE_IMAGE_MDTYPE.FIDT_SSHORT));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((short[])metaTag.Value).Length == testShortArray.Length);
+ Assert.That(metaTag.Count == testShortArray.Length);
+ Assert.That(metaTag.Length == testShortArray.Length * 2);
+
+ short[] value = (short[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testShortArray[j] == value[j]);
+ }
+
+ //
+ // FREE_IMAGE_MDTYPE.FIDT_UNDEFINED
+ //
+
+ Assert.IsTrue(metaTag.SetValue(byte.MinValue, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(((byte[])metaTag.Value)[0] == byte.MinValue);
+
+ Assert.IsTrue(metaTag.SetValue(byte.MaxValue, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(((byte[])metaTag.Value)[0] == byte.MaxValue);
+
+ for (int i = 0; i < 10; i++)
+ {
+ testByte = (byte)rand.Next(byte.MinValue, byte.MaxValue);
+ testByteArray = new byte[rand.Next(0, 31)];
+
+ for (int j = 0; j < testByteArray.Length; j++)
+ testByteArray[j] = (byte)rand.Next();
+
+ Assert.IsTrue(metaTag.SetValue(testByte, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == 1);
+ Assert.That(metaTag.Count == 1);
+ Assert.That(metaTag.Length == 1);
+ Assert.That(metaTag.Type == FREE_IMAGE_MDTYPE.FIDT_UNDEFINED);
+ Assert.That(((byte[])metaTag.Value)[0] == testByte);
+
+ Assert.IsTrue(metaTag.SetValue(testByteArray, FREE_IMAGE_MDTYPE.FIDT_UNDEFINED));
+ Assert.IsNotNull(metaTag.Value);
+ Assert.That(((byte[])metaTag.Value).Length == testByteArray.Length);
+ Assert.That(metaTag.Count == testByteArray.Length);
+ Assert.That(metaTag.Length == testByteArray.Length * 1);
+
+ byte[] value = (byte[])metaTag.Value;
+
+ for (int j = 0; j < value.Length; j++)
+ Assert.That(testByteArray[j] == value[j]);
+ }
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void MetadataModel()
+ {
+ MetadataTag tag;
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ MetadataModel model = new MDM_GEOTIFF(dib);
+ Assert.AreEqual(0, model.Count);
+ Assert.IsFalse(model.Exists);
+ Assert.IsEmpty(model.List);
+ Assert.AreEqual(model.Model, FREE_IMAGE_MDMODEL.FIMD_GEOTIFF);
+ Assert.IsTrue(model.DestoryModel());
+ foreach (MetadataTag m in model) Assert.Fail();
+
+ tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_GEOTIFF);
+ tag.Key = "KEY";
+ tag.Value = 54321f;
+ Assert.IsTrue(model.AddTag(tag));
+
+ Assert.AreEqual(1, model.Count);
+ Assert.IsTrue(model.Exists);
+ Assert.IsNotEmpty(model.List);
+ Assert.AreEqual(model.Model, FREE_IMAGE_MDMODEL.FIMD_GEOTIFF);
+
+ Assert.IsTrue(model.DestoryModel());
+ Assert.AreEqual(0, model.Count);
+ Assert.IsFalse(model.Exists);
+ Assert.IsEmpty(model.List);
+ Assert.AreEqual(model.Model, FREE_IMAGE_MDMODEL.FIMD_GEOTIFF);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void ImageMetadata()
+ {
+ ImageMetadata metadata;
+ List<MetadataModel> modelList;
+ MetadataTag tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ tag.Key = "KEY";
+ tag.ID = 11;
+ tag.Value = new double[] { 0d, 41d, -523d, -0.41d };
+
+ dib = FreeImage.Allocate(1, 1, 1, 1, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ metadata = new ImageMetadata(dib, true);
+ Assert.AreEqual(0, metadata.Count);
+ Assert.IsTrue(metadata.HideEmptyModels);
+ Assert.IsEmpty(metadata.List);
+
+ metadata = new ImageMetadata(dib, false);
+ Assert.AreEqual(FreeImage.FREE_IMAGE_MDMODELS.Length, metadata.Count);
+ Assert.IsFalse(metadata.HideEmptyModels);
+ Assert.IsNotEmpty(metadata.List);
+
+ metadata.HideEmptyModels = true;
+ metadata.AddTag(tag);
+
+ Assert.AreEqual(1, metadata.Count);
+ Assert.IsNotEmpty(metadata.List);
+
+ modelList = metadata.List;
+ Assert.AreEqual(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, modelList[0].Model);
+
+ System.Collections.IEnumerator enumerator = metadata.GetEnumerator();
+ Assert.IsTrue(enumerator.MoveNext());
+ Assert.IsNotNull((MetadataModel)enumerator.Current);
+ Assert.IsFalse(enumerator.MoveNext());
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ [TestFixture]
+ public class WrapperFunctionsTest
+ {
+ ImageManager iManager = new ImageManager();
+ FIBITMAP dib = new FIBITMAP();
+ string freeImageCallback = null;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [TestFixtureTearDown]
+ public void DeInit()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [SetUp]
+ public void InitEachTime()
+ {
+ }
+
+ [TearDown]
+ public void DeInitEachTime()
+ {
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ freeImageCallback = message;
+ }
+
+ public bool EqualColors(Color color1, Color color2)
+ {
+ if (color1.A != color2.A) return false;
+ if (color1.R != color2.R) return false;
+ if (color1.G != color2.G) return false;
+ if (color1.B != color2.B) return false;
+ return true;
+ }
+
+ //
+ // Tests
+ //
+
+ [Test]
+ public void FreeImage_GetWrapperVersion()
+ {
+ //Assert.That(FreeImage.GetWrapperVersion() ==
+ // String.Format("{0}.{1}.{2}",
+ // FreeImage.FREEIMAGE_MAJOR_VERSION,
+ // FreeImage.FREEIMAGE_MINOR_VERSION,
+ // FreeImage.FREEIMAGE_RELEASE_SERIAL));
+ }
+
+ [Test]
+ public void FreeImage_IsAvailable()
+ {
+ Assert.IsTrue(FreeImage.IsAvailable());
+ }
+
+ [Test]
+ public void FreeImage_GetBitmap()
+ {
+ Bitmap bitmap = null;
+
+ try
+ {
+ bitmap = FreeImage.GetBitmap(new FIBITMAP());
+ }
+ catch
+ {
+ }
+ Assert.IsNull(bitmap);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+
+ bitmap = FreeImage.GetBitmap(dib);
+ Assert.IsNotNull(bitmap);
+ Assert.AreEqual((int)FreeImage.GetHeight(dib), bitmap.Height);
+ Assert.AreEqual((int)FreeImage.GetWidth(dib), bitmap.Width);
+
+ bitmap.Dispose();
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_CreateFromBitmap()
+ {
+ Bitmap bitmap = (Bitmap)Bitmap.FromFile(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_24));
+ Assert.IsNotNull(bitmap);
+
+ dib = FreeImage.CreateFromBitmap(bitmap);
+ Assert.That(!dib.IsNull);
+
+ Assert.AreEqual((int)FreeImage.GetHeight(dib), bitmap.Height);
+ Assert.AreEqual((int)FreeImage.GetWidth(dib), bitmap.Width);
+
+ bitmap.Dispose();
+ FreeImage.UnloadEx(ref dib);
+
+ try
+ {
+ dib = FreeImage.CreateFromBitmap(null);
+ Assert.Fail();
+ }
+ catch
+ {
+ }
+ }
+
+ [Test]
+ public void FreeImage_SaveBitmap()
+ {
+ Bitmap bitmap = (Bitmap)Bitmap.FromFile(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_24));
+ Assert.IsNotNull(bitmap);
+
+ Assert.IsTrue(FreeImage.SaveBitmap(bitmap, @"test.png", FREE_IMAGE_FORMAT.FIF_PNG, FREE_IMAGE_SAVE_FLAGS.DEFAULT));
+ bitmap.Dispose();
+
+ Assert.IsTrue(File.Exists(@"test.png"));
+
+ dib = FreeImage.Load(FREE_IMAGE_FORMAT.FIF_PNG, @"test.png", FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ Assert.That(!dib.IsNull);
+
+ FreeImage.UnloadEx(ref dib);
+
+ File.Delete(@"test.png");
+ Assert.IsFalse(File.Exists(@"test.png"));
+ bitmap.Dispose();
+ }
+
+ [Test]
+ public void FreeImage_LoadEx()
+ {
+ dib = FreeImage.LoadEx(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_16_555));
+ Assert.That(!dib.IsNull);
+ FreeImage.UnloadEx(ref dib);
+
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_TIFF;
+
+ dib = FreeImage.LoadEx(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_16_565), ref format);
+ Assert.That(dib.IsNull);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_TIFF, format);
+ FreeImage.UnloadEx(ref dib);
+
+ format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ dib = FreeImage.LoadEx(iManager.GetBitmapPath(ImageType.JPEG, ImageColorType.Type_16_565),
+ FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ Assert.That(!dib.IsNull);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_JPEG, format);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_UnloadEx()
+ {
+ Assert.That(dib.IsNull);
+ FreeImage.UnloadEx(ref dib);
+ Assert.That(dib.IsNull);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_555);
+ Assert.That(!dib.IsNull);
+
+ FreeImage.UnloadEx(ref dib);
+ Assert.That(dib.IsNull);
+ }
+
+ [Test]
+ public void FreeImage_SaveEx()
+ {
+ FREE_IMAGE_FORMAT format;
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08);
+ Assert.That(!dib.IsNull);
+
+ Assert.IsTrue(FreeImage.SaveEx(dib, @"test.png"));
+ Assert.IsTrue(File.Exists(@"test.png"));
+ format = FreeImage.GetFileType(@"test.png", 0);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_PNG, format);
+ File.Delete(@"test.png");
+ Assert.IsFalse(File.Exists(@"test.png"));
+
+ Assert.IsTrue(FreeImage.SaveEx(ref dib, @"test.tiff", FREE_IMAGE_SAVE_FLAGS.DEFAULT, false));
+ Assert.IsTrue(File.Exists(@"test.tiff"));
+ format = FreeImage.GetFileType(@"test.tiff", 0);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_TIFF, format);
+ File.Delete(@"test.tiff");
+ Assert.IsFalse(File.Exists(@"test.tiff"));
+
+ Assert.IsTrue(FreeImage.SaveEx(
+ ref dib,
+ @"test.gif",
+ FREE_IMAGE_FORMAT.FIF_UNKNOWN,
+ FREE_IMAGE_SAVE_FLAGS.DEFAULT,
+ FREE_IMAGE_COLOR_DEPTH.FICD_08_BPP,
+ false));
+
+ Assert.IsTrue(File.Exists(@"test.gif"));
+ format = FreeImage.GetFileType(@"test.gif", 0);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_GIF, format);
+ File.Delete(@"test.gif");
+ Assert.IsFalse(File.Exists(@"test.gif"));
+
+ Assert.IsFalse(FreeImage.SaveEx(dib, @""));
+ Assert.IsFalse(FreeImage.SaveEx(dib, @"test.test"));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_LoadFromStream()
+ {
+ FREE_IMAGE_FORMAT format;
+ FileStream fStream;
+
+ fStream = new FileStream(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_16_565), FileMode.Open);
+ Assert.IsNotNull(fStream);
+
+ dib = FreeImage.LoadFromStream(fStream);
+ Assert.That(!dib.IsNull);
+ Assert.That(FreeImage.GetBPP(dib) == 16);
+ Assert.That(FreeImage.GetGreenMask(dib) == FreeImage.FI16_565_GREEN_MASK);
+
+ FreeImage.UnloadEx(ref dib);
+ fStream.Close();
+
+ fStream = new FileStream(iManager.GetBitmapPath(ImageType.Metadata, ImageColorType.Type_01_Dither), FileMode.Open);
+ Assert.IsNotNull(fStream);
+
+ format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ dib = FreeImage.LoadFromStream(fStream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ Assert.That(!dib.IsNull);
+ Assert.That(FreeImage.GetBPP(dib) == 24);
+ Assert.That(format == FREE_IMAGE_FORMAT.FIF_JPEG);
+ FreeImage.UnloadEx(ref dib);
+ fStream.Close();
+
+ fStream = new FileStream(iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_32), FileMode.Open);
+ format = FREE_IMAGE_FORMAT.FIF_TIFF;
+ dib = FreeImage.LoadFromStream(fStream, FREE_IMAGE_LOAD_FLAGS.DEFAULT, ref format);
+ Assert.That(!dib.IsNull);
+ Assert.That(FreeImage.GetBPP(dib) == 32);
+ Assert.That(format == FREE_IMAGE_FORMAT.FIF_TIFF);
+
+ FreeImage.UnloadEx(ref dib);
+
+ Assert.That(dib.IsNull);
+ dib = FreeImage.LoadFromStream(new MemoryStream(new byte[] { }));
+ Assert.That(dib.IsNull);
+
+ format = FREE_IMAGE_FORMAT.FIF_BMP;
+ fStream.Position = 0;
+ dib = FreeImage.LoadFromStream(fStream, ref format);
+ Assert.That(dib.IsNull);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_BMP, format);
+
+ fStream.Close();
+ }
+
+ [Test]
+ public void FreeImage_SaveToStream()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+
+ Stream stream = new FileStream(@"out_stream.bmp", FileMode.Create);
+ Assert.IsNotNull(stream);
+
+ Assert.IsTrue(FreeImage.SaveEx(ref dib, @"out_file.bmp", FREE_IMAGE_FORMAT.FIF_BMP, false));
+ Assert.IsTrue(FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_BMP));
+ stream.Flush();
+ stream.Dispose();
+
+ Assert.IsTrue(File.Exists(@"out_stream.bmp"));
+ Assert.IsTrue(File.Exists(@"out_file.bmp"));
+ byte[] buffer1 = File.ReadAllBytes(@"out_stream.bmp");
+ byte[] buffer2 = File.ReadAllBytes(@"out_file.bmp");
+ Assert.AreEqual(buffer1.Length, buffer2.Length);
+ for (int i = 0; i < buffer1.Length; i++)
+ if (buffer1[i] != buffer2[i])
+ Assert.Fail();
+
+ File.Delete(@"out_stream.bmp");
+ File.Delete(@"out_file.bmp");
+ Assert.IsFalse(File.Exists(@"out_stream.bmp"));
+ Assert.IsFalse(File.Exists(@"out_file.bmp"));
+
+ stream = new MemoryStream();
+ Assert.IsFalse(FreeImage.SaveToStream(dib, stream, FREE_IMAGE_FORMAT.FIF_FAXG3));
+ stream.Dispose();
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_IsExtensionValidForFIF()
+ {
+ Assert.IsTrue(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_BMP, "bmp", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsTrue(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_BMP, "BMP", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsFalse(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_BMP, "DUMMY", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsTrue(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_PCX, "pcx", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsTrue(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_TIFF, "tif", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsTrue(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_TIFF, "TIFF", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsFalse(FreeImage.IsExtensionValidForFIF(FREE_IMAGE_FORMAT.FIF_ICO, "ICO", StringComparison.CurrentCulture));
+ }
+
+ [Test]
+ public void FreeImage_IsFilenameValidForFIF()
+ {
+ Assert.IsTrue(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_JPEG, "file.jpg"));
+ Assert.IsTrue(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_JPEG, "file.jpeg"));
+ Assert.IsFalse(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_JPEG, "file.bmp"));
+ Assert.IsTrue(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_GIF, "file.gif"));
+ Assert.IsTrue(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_GIF, "file.GIF"));
+ Assert.IsTrue(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_GIF, "file.GIF", StringComparison.CurrentCultureIgnoreCase));
+ Assert.IsFalse(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_GIF, "file.txt"));
+ Assert.IsFalse(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_UNKNOWN, "file.jpg"));
+ Assert.IsFalse(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_UNKNOWN, "file.bmp"));
+ Assert.IsFalse(FreeImage.IsFilenameValidForFIF(FREE_IMAGE_FORMAT.FIF_UNKNOWN, "file.tif"));
+ }
+
+ [Test]
+ public void FreeImage_GetPrimaryExtensionFromFIF()
+ {
+ Assert.AreEqual("gif", FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_GIF));
+ Assert.AreEqual("tif", FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_TIFF));
+ Assert.AreNotEqual("tiff", FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_TIFF));
+ Assert.AreEqual("psd", FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_PSD));
+ Assert.AreEqual("iff", FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_IFF));
+ Assert.IsNull(FreeImage.GetPrimaryExtensionFromFIF(FREE_IMAGE_FORMAT.FIF_UNKNOWN));
+ }
+
+ [Test]
+ public void FreeImage_OpenMultiBitmapEx()
+ {
+ FIMULTIBITMAP dib = FreeImage.OpenMultiBitmapEx(iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_01_Dither));
+ Assert.IsFalse(dib.IsNull);
+ Assert.AreEqual(4, FreeImage.GetPageCount(dib));
+ FreeImage.CloseMultiBitmap(dib, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+
+ FREE_IMAGE_FORMAT format = FREE_IMAGE_FORMAT.FIF_UNKNOWN;
+ dib = FreeImage.OpenMultiBitmapEx(
+ iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_04), ref format, FREE_IMAGE_LOAD_FLAGS.DEFAULT,
+ false, true, true);
+ Assert.IsFalse(dib.IsNull);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_TIFF, format);
+ FreeImage.CloseMultiBitmap(dib, FREE_IMAGE_SAVE_FLAGS.DEFAULT);
+ }
+
+ [Test]
+ public void FreeImage_GetLockedPageCount()
+ {
+ FIMULTIBITMAP dib = FreeImage.OpenMultiBitmapEx(iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_01_Dither));
+ FIBITMAP page1, page2, page3;
+ Assert.IsFalse(dib.IsNull);
+ Assert.AreEqual(4, FreeImage.GetPageCount(dib));
+ Assert.AreEqual(0, FreeImage.GetLockedPageCount(dib));
+
+ page1 = FreeImage.LockPage(dib, 0);
+ Assert.AreEqual(1, FreeImage.GetLockedPageCount(dib));
+
+ page2 = FreeImage.LockPage(dib, 1);
+ Assert.AreEqual(2, FreeImage.GetLockedPageCount(dib));
+
+ page3 = FreeImage.LockPage(dib, 2);
+ Assert.AreEqual(3, FreeImage.GetLockedPageCount(dib));
+
+ FreeImage.UnlockPage(dib, page3, true);
+ Assert.AreEqual(2, FreeImage.GetLockedPageCount(dib));
+
+ FreeImage.UnlockPage(dib, page2, true);
+ Assert.AreEqual(1, FreeImage.GetLockedPageCount(dib));
+
+ FreeImage.UnlockPage(dib, page1, true);
+ Assert.AreEqual(0, FreeImage.GetLockedPageCount(dib));
+
+ FreeImage.CloseMultiBitmapEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetLockedPages()
+ {
+ FIMULTIBITMAP dib = FreeImage.OpenMultiBitmapEx(iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_01_Dither));
+ FIBITMAP page1, page2, page3;
+ int[] lockedList;
+ Assert.IsFalse(dib.IsNull);
+ Assert.AreEqual(4, FreeImage.GetPageCount(dib));
+ Assert.AreEqual(0, FreeImage.GetLockedPageCount(dib));
+
+ page1 = FreeImage.LockPage(dib, 0);
+ Assert.AreEqual(1, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.Contains(0, lockedList);
+
+ page2 = FreeImage.LockPage(dib, 1);
+ Assert.AreEqual(2, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.Contains(0, lockedList);
+ Assert.Contains(1, lockedList);
+
+ page3 = FreeImage.LockPage(dib, 3);
+ Assert.AreEqual(3, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.Contains(0, lockedList);
+ Assert.Contains(1, lockedList);
+ Assert.Contains(3, lockedList);
+
+ FreeImage.UnlockPage(dib, page2, true);
+ Assert.AreEqual(2, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.Contains(0, lockedList);
+ Assert.Contains(3, lockedList);
+
+ FreeImage.UnlockPage(dib, page1, true);
+ Assert.AreEqual(1, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.Contains(3, lockedList);
+
+ FreeImage.UnlockPage(dib, page3, true);
+ Assert.AreEqual(0, FreeImage.GetLockedPageCount(dib));
+ lockedList = FreeImage.GetLockedPages(dib);
+ Assert.AreEqual(0, lockedList.Length);
+
+ FreeImage.CloseMultiBitmapEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetFileTypeFromStream()
+ {
+ FileStream fStream = new FileStream(iManager.GetBitmapPath(ImageType.JPEG, ImageColorType.Type_01_Dither), FileMode.Open);
+ Assert.IsNotNull(fStream);
+
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_JPEG, FreeImage.GetFileTypeFromStream(fStream));
+ fStream.Dispose();
+
+ fStream = new FileStream(iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_16_565), FileMode.Open);
+ Assert.AreEqual(FREE_IMAGE_FORMAT.FIF_BMP, FreeImage.GetFileTypeFromStream(fStream));
+ fStream.Close();
+ }
+
+ [Test]
+ public void FreeImage_GetHbitmap()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ IntPtr hBitmap = FreeImage.GetHbitmap(dib, IntPtr.Zero, false);
+ Bitmap bitmap = Bitmap.FromHbitmap(hBitmap);
+ Assert.IsNotNull(bitmap);
+ Assert.AreEqual(FreeImage.GetWidth(dib), bitmap.Width);
+ Assert.AreEqual(FreeImage.GetHeight(dib), bitmap.Height);
+
+ bitmap.Dispose();
+ FreeImage.FreeHbitmap(hBitmap);
+ FreeImage.UnloadEx(ref dib);
+
+ try
+ {
+ hBitmap = FreeImage.GetHbitmap(dib, IntPtr.Zero, false);
+ Assert.Fail();
+ }
+ catch
+ {
+ }
+ }
+
+ [Test]
+ public void FreeImage_GetResolutionX()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(72, FreeImage.GetResolutionX(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetResolutionY()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(72, FreeImage.GetResolutionY(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetResolutionX()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(72, FreeImage.GetResolutionX(dib));
+
+ FreeImage.SetResolutionX(dib, 12u);
+ Assert.AreEqual(12, FreeImage.GetResolutionX(dib));
+
+ FreeImage.SetResolutionX(dib, 1u);
+ Assert.AreEqual(1, FreeImage.GetResolutionX(dib));
+
+ FreeImage.SetResolutionX(dib, 66u);
+ Assert.AreEqual(66, FreeImage.GetResolutionX(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetResolutionY()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(72, FreeImage.GetResolutionY(dib));
+
+ FreeImage.SetResolutionY(dib, 12u);
+ Assert.AreEqual(12, FreeImage.GetResolutionY(dib));
+
+ FreeImage.SetResolutionY(dib, 1u);
+ Assert.AreEqual(1, FreeImage.GetResolutionY(dib));
+
+ FreeImage.SetResolutionY(dib, 66u);
+ Assert.AreEqual(66, FreeImage.GetResolutionY(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_IsGreyscaleImage()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.IsFalse(FreeImage.IsGreyscaleImage(dib));
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_Unordered);
+ Assert.IsTrue(FreeImage.IsGreyscaleImage(dib));
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_MinIsBlack);
+ Assert.IsTrue(FreeImage.IsGreyscaleImage(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetPaletteEx()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Palette palette = null;
+
+ try
+ {
+ palette = FreeImage.GetPaletteEx(dib);
+ Assert.Fail();
+ }
+ catch
+ {
+ }
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_08_Greyscale_MinIsBlack);
+ try
+ {
+ palette = FreeImage.GetPaletteEx(dib);
+ }
+ catch
+ {
+ Assert.Fail();
+ }
+ Assert.AreEqual(256, palette.Length);
+ for (int index = 0; index < 256; index++)
+ {
+ Assert.AreEqual(index, palette[index].rgbRed);
+ Assert.AreEqual(index, palette[index].rgbGreen);
+ Assert.AreEqual(index, palette[index].rgbBlue);
+ }
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetInfoHeaderEx()
+ {
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04);
+ Assert.IsFalse(dib.IsNull);
+
+ BITMAPINFOHEADER iHeader = FreeImage.GetInfoHeaderEx(dib);
+ Assert.AreEqual(4, iHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), iHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), iHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+
+ iHeader = FreeImage.GetInfoHeaderEx(dib);
+ Assert.AreEqual(1, iHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), iHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), iHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.IsFalse(dib.IsNull);
+
+ iHeader = FreeImage.GetInfoHeaderEx(dib);
+ Assert.AreEqual(24, iHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), iHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), iHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetInfoEx()
+ {
+ BITMAPINFO info;
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_01_Dither);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_04_Greyscale_MinIsBlack);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_08_Greyscale_Unordered);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_555);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_565);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_24);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.That(!dib.IsNull);
+ info = FreeImage.GetInfoEx(dib);
+ Assert.AreEqual(FreeImage.GetBPP(dib), info.bmiHeader.biBitCount);
+ Assert.AreEqual(FreeImage.GetWidth(dib), info.bmiHeader.biWidth);
+ Assert.AreEqual(FreeImage.GetHeight(dib), info.bmiHeader.biHeight);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetPixelFormat()
+ {
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_01_Threshold);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(PixelFormat.Format1bppIndexed, FreeImage.GetPixelFormat(dib));
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_04_Greyscale_Unordered);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(PixelFormat.Format4bppIndexed, FreeImage.GetPixelFormat(dib));
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_555);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(PixelFormat.Format16bppRgb555, FreeImage.GetPixelFormat(dib));
+ FreeImage.UnloadEx(ref dib);
+
+ dib = iManager.GetBitmap(ImageType.Odd, ImageColorType.Type_16_565);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.AreEqual(PixelFormat.Format16bppRgb565, FreeImage.GetPixelFormat(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetFormatParameters()
+ {
+ uint bpp, red, green, blue;
+ FREE_IMAGE_TYPE type;
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format16bppArgb1555, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(16, bpp);
+ Assert.AreEqual(red, FreeImage.FI16_555_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI16_555_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI16_555_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format16bppGrayScale, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(16, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_UINT16);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format16bppRgb555, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(16, bpp);
+ Assert.AreEqual(red, FreeImage.FI16_555_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI16_555_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI16_555_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format16bppRgb565, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(16, bpp);
+ Assert.AreEqual(red, FreeImage.FI16_565_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI16_565_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI16_565_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format1bppIndexed, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(1, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format24bppRgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(24, bpp);
+ Assert.AreEqual(red, FreeImage.FI_RGBA_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI_RGBA_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI_RGBA_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format32bppArgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(32, bpp);
+ Assert.AreEqual(red, FreeImage.FI_RGBA_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI_RGBA_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI_RGBA_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format32bppPArgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(32, bpp);
+ Assert.AreEqual(red, FreeImage.FI_RGBA_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI_RGBA_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI_RGBA_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format32bppRgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(32, bpp);
+ Assert.AreEqual(red, FreeImage.FI_RGBA_RED_MASK);
+ Assert.AreEqual(green, FreeImage.FI_RGBA_GREEN_MASK);
+ Assert.AreEqual(blue, FreeImage.FI_RGBA_BLUE_MASK);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format48bppRgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(48, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_RGB16);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format4bppIndexed, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(4, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format64bppArgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(64, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_RGBA16);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format64bppPArgb, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(64, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_RGBA16);
+
+ Assert.IsTrue(FreeImage.GetFormatParameters(PixelFormat.Format8bppIndexed, out type, out bpp, out red, out green, out blue));
+ Assert.AreEqual(8, bpp);
+ Assert.AreEqual(red, 0);
+ Assert.AreEqual(green, 0);
+ Assert.AreEqual(blue, 0);
+ Assert.AreEqual(type, FREE_IMAGE_TYPE.FIT_BITMAP);
+ }
+
+ [Test]
+ public void FreeImage_Compare()
+ {
+ FIBITMAP dib2;
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+ dib2 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_01_Threshold);
+ Assert.IsFalse(dib2.IsNull);
+
+ Assert.IsFalse(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+ Assert.IsTrue(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.HEADER));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_MinIsBlack);
+ dib2 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_04_Greyscale_Unordered);
+
+ Assert.IsFalse(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ dib2 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_32);
+ Assert.IsTrue(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+ dib2 = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib2.IsNull);
+
+ Assert.IsTrue(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_555);
+ Assert.IsFalse(dib.IsNull);
+ dib2 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_555);
+ Assert.IsFalse(dib2.IsNull);
+
+ Assert.IsTrue(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+
+ dib = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_565);
+ Assert.IsFalse(dib.IsNull);
+ dib2 = iManager.GetBitmap(ImageType.Even, ImageColorType.Type_16_565);
+ Assert.IsFalse(dib2.IsNull);
+
+ Assert.IsTrue(FreeImage.Compare(dib, dib2, FREE_IMAGE_COMPARE_FLAGS.COMPLETE));
+
+ FreeImage.UnloadEx(ref dib);
+ FreeImage.UnloadEx(ref dib2);
+ }
+
+ [Test]
+ public void FreeImage_CreateICCProfileEx()
+ {
+ FIICCPROFILE prof;
+ byte[] data = new byte[173];
+ Random rand = new Random(DateTime.Now.Millisecond);
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_BITMAP, 1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ prof = FreeImage.GetICCProfileEx(dib);
+ Assert.That(prof.DataPointer == IntPtr.Zero);
+
+ rand.NextBytes(data);
+ prof = FreeImage.CreateICCProfileEx(dib, data);
+ Assert.That(prof.Size == data.Length);
+ for (int i = 0; i < data.Length; i++)
+ if (prof.Data[i] != data[i])
+ Assert.Fail();
+
+ FreeImage.DestroyICCProfile(dib);
+ prof = FreeImage.GetICCProfileEx(dib);
+ Assert.That(prof.DataPointer == IntPtr.Zero);
+
+ FreeImage.CreateICCProfileEx(dib, new byte[0], 0);
+ prof = FreeImage.GetICCProfileEx(dib);
+ Assert.That(prof.DataPointer == IntPtr.Zero);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_ConvertColorDepth()
+ {
+ int bpp = 1;
+ FIBITMAP dib2;
+
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_BITMAP, 80, 80, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ do
+ {
+ dib2 = FreeImage.ConvertColorDepth(dib, (FREE_IMAGE_COLOR_DEPTH)bpp);
+ Assert.IsFalse(dib2.IsNull);
+ Assert.AreEqual(bpp, FreeImage.GetBPP(dib2));
+ if (dib != dib2)
+ FreeImage.UnloadEx(ref dib2);
+ } while (0 != (bpp = FreeImage.GetNextColorDepth(bpp)));
+
+ FreeImage.UnloadEx(ref dib);
+
+ dib = FreeImage.AllocateT(FREE_IMAGE_TYPE.FIT_BITMAP, 80, 80, 32,
+ FreeImage.FI_RGBA_RED_MASK, FreeImage.FI_RGBA_GREEN_MASK, FreeImage.FI_RGBA_BLUE_MASK);
+ Assert.IsFalse(dib.IsNull);
+ bpp = 32;
+
+ do
+ {
+ dib2 = FreeImage.ConvertColorDepth(dib, (FREE_IMAGE_COLOR_DEPTH)bpp);
+ Assert.IsFalse(dib2.IsNull);
+ Assert.AreEqual(bpp, FreeImage.GetBPP(dib2));
+ if (dib != dib2)
+ FreeImage.UnloadEx(ref dib2);
+ } while (0 != (bpp = FreeImage.GetPrevousColorDepth(bpp)));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetNextColorDepth()
+ {
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(5));
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(0));
+ Assert.AreEqual(4, FreeImage.GetNextColorDepth(1));
+ Assert.AreEqual(8, FreeImage.GetNextColorDepth(4));
+ Assert.AreEqual(16, FreeImage.GetNextColorDepth(8));
+ Assert.AreEqual(24, FreeImage.GetNextColorDepth(16));
+ Assert.AreEqual(32, FreeImage.GetNextColorDepth(24));
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(32));
+ }
+
+ [Test]
+ public void FreeImage_GetPrevousColorDepth()
+ {
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(5));
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(0));
+ Assert.AreEqual(4, FreeImage.GetNextColorDepth(1));
+ Assert.AreEqual(8, FreeImage.GetNextColorDepth(4));
+ Assert.AreEqual(16, FreeImage.GetNextColorDepth(8));
+ Assert.AreEqual(24, FreeImage.GetNextColorDepth(16));
+ Assert.AreEqual(32, FreeImage.GetNextColorDepth(24));
+ Assert.AreEqual(0, FreeImage.GetNextColorDepth(32));
+ }
+
+ [Test]
+ public unsafe void FreeImage_PtrToStr()
+ {
+ string testString;
+ string resString;
+ IntPtr buffer;
+ int index;
+
+ testString = "Test string";
+ buffer = Marshal.AllocHGlobal(testString.Length + 1);
+
+ for (index = 0; index < testString.Length; index++)
+ {
+ Marshal.WriteByte(buffer, index, (byte)testString[index]);
+ }
+ Marshal.WriteByte(buffer, index, (byte)0);
+
+ resString = FreeImage.PtrToStr((byte*)buffer);
+ Assert.That(resString == testString);
+
+ Marshal.FreeHGlobal(buffer);
+
+ testString = @"äöü?=§%/!)§(%&)(§";
+ buffer = Marshal.AllocHGlobal(testString.Length + 1);
+
+ for (index = 0; index < testString.Length; index++)
+ {
+ Marshal.WriteByte(buffer, index, (byte)testString[index]);
+ }
+ Marshal.WriteByte(buffer, index, (byte)0);
+
+ resString = FreeImage.PtrToStr((byte*)buffer);
+ Assert.That(resString == testString);
+
+ Marshal.FreeHGlobal(buffer);
+ }
+
+ [Test]
+ public void FreeImage_CopyMetadata()
+ {
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+ int mdCount = 0;
+
+ FIBITMAP dib2 = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib2.IsNull);
+
+ FREE_IMAGE_MDMODEL[] modelList = (FREE_IMAGE_MDMODEL[])Enum.GetValues(typeof(FREE_IMAGE_MDMODEL));
+ FITAG tag, tag2;
+ FIMETADATA mdHandle;
+
+ foreach (FREE_IMAGE_MDMODEL model in modelList)
+ {
+ mdHandle = FreeImage.FindFirstMetadata(model, dib2, out tag);
+ Assert.IsTrue(mdHandle.IsNull);
+ mdCount += (int)FreeImage.GetMetadataCount(model, dib);
+ }
+
+ Assert.AreEqual(mdCount, FreeImage.CloneMetadataEx(dib, dib2, FREE_IMAGE_METADATA_COPY.CLEAR_EXISTING));
+
+ foreach (FREE_IMAGE_MDMODEL model in modelList)
+ {
+ mdHandle = FreeImage.FindFirstMetadata(model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ do
+ {
+ Assert.IsTrue(FreeImage.GetMetadata(model, dib2, FreeImage.GetTagKey(tag), out tag2));
+ Assert.That(FreeImage.GetTagCount(tag) == FreeImage.GetTagCount(tag2));
+ Assert.That(FreeImage.GetTagDescription(tag) == FreeImage.GetTagDescription(tag2));
+ Assert.That(FreeImage.GetTagID(tag) == FreeImage.GetTagID(tag2));
+ Assert.That(FreeImage.GetTagKey(tag) == FreeImage.GetTagKey(tag2));
+ Assert.That(FreeImage.GetTagLength(tag) == FreeImage.GetTagLength(tag2));
+ Assert.That(FreeImage.GetTagType(tag) == FreeImage.GetTagType(tag2));
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ }
+
+ Assert.AreEqual(0, FreeImage.CloneMetadataEx(dib, dib2, FREE_IMAGE_METADATA_COPY.KEEP_EXISITNG));
+
+ foreach (FREE_IMAGE_MDMODEL model in modelList)
+ {
+ mdHandle = FreeImage.FindFirstMetadata(model, dib, out tag);
+ if (!mdHandle.IsNull)
+ {
+ do
+ {
+ Assert.IsTrue(FreeImage.GetMetadata(model, dib2, FreeImage.GetTagKey(tag), out tag2));
+ Assert.AreEqual(FreeImage.GetTagCount(tag), FreeImage.GetTagCount(tag2));
+ Assert.AreEqual(FreeImage.GetTagDescription(tag), FreeImage.GetTagDescription(tag2));
+ Assert.AreEqual(FreeImage.GetTagID(tag), FreeImage.GetTagID(tag2));
+ Assert.AreEqual(FreeImage.GetTagKey(tag), FreeImage.GetTagKey(tag2));
+ Assert.AreEqual(FreeImage.GetTagLength(tag), FreeImage.GetTagLength(tag2));
+ Assert.AreEqual(FreeImage.GetTagType(tag), FreeImage.GetTagType(tag2));
+ }
+ while (FreeImage.FindNextMetadata(mdHandle, out tag));
+ FreeImage.FindCloseMetadata(mdHandle);
+ }
+ }
+
+ const string newTagDescription = "NEW_TAG_DESCRIPTION";
+
+ Assert.IsTrue(FreeImage.GetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib, "Copyright", out tag));
+ Assert.IsTrue(FreeImage.SetTagDescription(tag, newTagDescription));
+ Assert.AreEqual(mdCount, FreeImage.CloneMetadataEx(dib, dib2, FREE_IMAGE_METADATA_COPY.REPLACE_EXISTING));
+ Assert.IsTrue(FreeImage.GetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib2, "Copyright", out tag2));
+ Assert.AreEqual(newTagDescription, FreeImage.GetTagDescription(tag2));
+
+ FreeImage.UnloadEx(ref dib2);
+ FreeImage.UnloadEx(ref dib);
+
+ dib2 = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+
+ Assert.AreEqual(0, FreeImage.CloneMetadataEx(dib, dib2, FREE_IMAGE_METADATA_COPY.CLEAR_EXISTING));
+
+ FreeImage.UnloadEx(ref dib2);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetImageComment()
+ {
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+ const string comment = "C O M M E N T";
+
+ Assert.IsNull(FreeImage.GetImageComment(dib));
+ Assert.IsTrue(FreeImage.SetImageComment(dib, comment));
+ Assert.AreEqual(comment, FreeImage.GetImageComment(dib));
+ Assert.IsTrue(FreeImage.SetImageComment(dib, null));
+ Assert.IsNull(FreeImage.GetImageComment(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetImageComment()
+ {
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+ const string comment = "C O M M E N T";
+
+ Assert.IsNull(FreeImage.GetImageComment(dib));
+ Assert.IsTrue(FreeImage.SetImageComment(dib, comment));
+ Assert.AreEqual(comment, FreeImage.GetImageComment(dib));
+ Assert.IsTrue(FreeImage.SetImageComment(dib, null));
+ Assert.IsNull(FreeImage.GetImageComment(dib));
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetMetadata()
+ {
+ MetadataTag tag;
+
+ dib = iManager.GetBitmap(ImageType.Metadata, ImageColorType.Type_01_Dither);
+ Assert.IsFalse(dib.IsNull);
+
+ Assert.IsFalse(FreeImage.GetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib, "~~~~~", out tag));
+ Assert.IsNull(tag);
+
+ Assert.IsTrue(FreeImage.GetMetadata(FREE_IMAGE_MDMODEL.FIMD_EXIF_MAIN, dib, "Artist", out tag));
+ Assert.IsFalse(tag.tag.IsNull);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetMetadata()
+ {
+ MetadataTag tag;
+ Random rand = new Random();
+
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ ushort value = (ushort)rand.Next();
+
+ tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_CUSTOM);
+ tag.ID = value;
+
+ Assert.IsTrue(FreeImage.SetMetadata(FREE_IMAGE_MDMODEL.FIMD_CUSTOM, dib, "~~~~~", tag));
+ Assert.IsTrue(FreeImage.GetMetadata(FREE_IMAGE_MDMODEL.FIMD_CUSTOM, dib, "~~~~~", out tag));
+ Assert.AreEqual(value, tag.ID);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_FindFirstMetadata()
+ {
+ MetadataTag tag;
+ FIMETADATA mdHandle;
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ FREE_IMAGE_MDMODEL[] models = (FREE_IMAGE_MDMODEL[])Enum.GetValues(typeof(FREE_IMAGE_MDMODEL));
+ foreach (FREE_IMAGE_MDMODEL model in models)
+ {
+ mdHandle = FreeImage.FindFirstMetadata(model, dib, out tag);
+ Assert.IsTrue(mdHandle.IsNull);
+ }
+
+ tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ tag.Key = "KEY";
+ tag.Value = 12345;
+ tag.AddToImage(dib);
+
+ mdHandle = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, out tag);
+ Assert.IsFalse(mdHandle.IsNull);
+
+ FreeImage.FindCloseMetadata(mdHandle);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_FindNextMetadata()
+ {
+ MetadataTag tag;
+ FIMETADATA mdHandle;
+ dib = FreeImage.Allocate(1, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ FREE_IMAGE_MDMODEL[] models = (FREE_IMAGE_MDMODEL[])Enum.GetValues(typeof(FREE_IMAGE_MDMODEL));
+ foreach (FREE_IMAGE_MDMODEL model in models)
+ {
+ mdHandle = FreeImage.FindFirstMetadata(model, dib, out tag);
+ Assert.IsTrue(mdHandle.IsNull);
+ }
+
+ tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ tag.Key = "KEY1";
+ tag.Value = 12345;
+ tag.AddToImage(dib);
+
+ tag = new MetadataTag(FREE_IMAGE_MDMODEL.FIMD_COMMENTS);
+ tag.Key = "KEY2";
+ tag.Value = 54321;
+ tag.AddToImage(dib);
+
+ mdHandle = FreeImage.FindFirstMetadata(FREE_IMAGE_MDMODEL.FIMD_COMMENTS, dib, out tag);
+ Assert.IsFalse(mdHandle.IsNull);
+
+ Assert.IsTrue(FreeImage.FindNextMetadata(mdHandle, out tag));
+ Assert.IsFalse(FreeImage.FindNextMetadata(mdHandle, out tag));
+
+ FreeImage.FindCloseMetadata(mdHandle);
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_SetGetTransparencyTableEx()
+ {
+ dib = FreeImage.Allocate(10, 10, 6, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ byte[] transTable = FreeImage.GetTransparencyTableEx(dib);
+ Assert.That(transTable.Length == 0);
+
+ Random rand = new Random();
+ transTable = new byte[rand.Next(0, 255)];
+ int length = transTable.Length;
+
+ for (int i = 0; i < transTable.Length; i++)
+ transTable[i] = (byte)i;
+
+ FreeImage.SetTransparencyTable(dib, transTable);
+ transTable = null;
+ transTable = FreeImage.GetTransparencyTableEx(dib);
+ Assert.That(transTable.Length == length);
+ for (int i = 0; i < transTable.Length; i++)
+ Assert.That(transTable[i] == i);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_GetUniqueColors()
+ {
+ Palette palette;
+
+ //
+ // 1bpp
+ //
+
+ dib = FreeImage.Allocate(10, 1, 1, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ palette = new Palette(dib);
+ palette[0] = Color.FromArgb(43, 255, 255, 255);
+ palette[1] = Color.FromArgb(222, 0, 0, 0);
+
+ Scanline<FI1BIT> sl1bit = new Scanline<FI1BIT>(dib, 0);
+ for (int x = 0; x < sl1bit.Length; x++)
+ {
+ sl1bit[x] = 0;
+ }
+
+ Assert.AreEqual(1, FreeImage.GetUniqueColors(dib));
+
+ sl1bit[5] = 1;
+ Assert.AreEqual(2, FreeImage.GetUniqueColors(dib));
+
+ palette[1] = Color.FromArgb(222, 255, 255, 255);
+ Assert.AreEqual(1, FreeImage.GetUniqueColors(dib));
+
+ sl1bit[5] = 0;
+ Assert.AreEqual(1, FreeImage.GetUniqueColors(dib));
+
+ FreeImage.UnloadEx(ref dib);
+
+ //
+ // 4bpp
+ //
+
+ dib = FreeImage.Allocate(10, 1, 4, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ palette = new Palette(dib);
+ palette[0] = new RGBQUAD(Color.FromArgb(43, 255, 255, 255));
+ palette[1] = new RGBQUAD(Color.FromArgb(222, 51, 2, 211));
+ palette[2] = new RGBQUAD(Color.FromArgb(29, 25, 31, 52));
+ palette[3] = new RGBQUAD(Color.FromArgb(173, 142, 61, 178));
+ palette[4] = new RGBQUAD(Color.FromArgb(143, 41, 67, 199));
+ palette[5] = new RGBQUAD(Color.FromArgb(2, 0, 2, 221));
+
+ Scanline<FI4BIT> sl4bit = new Scanline<FI4BIT>(dib, 0);
+
+ for (int x = 0; x < sl4bit.Length; x++)
+ {
+ sl4bit[x] = 0;
+ }
+
+ Assert.AreEqual(1, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[1] = 1;
+ Assert.AreEqual(2, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[2] = 1;
+ Assert.AreEqual(2, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[3] = 2;
+ Assert.AreEqual(3, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[4] = 3;
+ Assert.AreEqual(4, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[5] = 4;
+ Assert.AreEqual(5, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[6] = 5;
+ Assert.AreEqual(6, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[7] = 6;
+ Assert.AreEqual(7, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[8] = 7;
+ Assert.AreEqual(7, FreeImage.GetUniqueColors(dib));
+
+ sl4bit[9] = 7;
+ Assert.AreEqual(7, FreeImage.GetUniqueColors(dib));
+
+ FreeImage.UnloadEx(ref dib);
+
+ //
+ // 8bpp
+ //
+
+ dib = FreeImage.Allocate(10, 1, 8, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ palette = new Palette(dib);
+ palette[0] = new RGBQUAD(Color.FromArgb(43, 255, 255, 255));
+ palette[1] = new RGBQUAD(Color.FromArgb(222, 51, 2, 211));
+ palette[2] = new RGBQUAD(Color.FromArgb(29, 25, 31, 52));
+ palette[3] = new RGBQUAD(Color.FromArgb(173, 142, 61, 178));
+ palette[4] = new RGBQUAD(Color.FromArgb(143, 41, 67, 199));
+ palette[5] = new RGBQUAD(Color.FromArgb(2, 0, 2, 221));
+
+ Scanline<byte> sl8bit = new Scanline<byte>(dib, 0);
+
+ for (int x = 0; x < sl8bit.Length; x++)
+ {
+ sl8bit[x] = 0;
+ }
+
+ Assert.AreEqual(1, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[1] = 1;
+ Assert.AreEqual(2, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[2] = 2;
+ Assert.AreEqual(3, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[3] = 3;
+ Assert.AreEqual(4, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[4] = 4;
+ Assert.AreEqual(5, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[5] = 6;
+ Assert.AreEqual(6, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[5] = 7;
+ Assert.AreEqual(6, FreeImage.GetUniqueColors(dib));
+
+ sl8bit[5] = 8;
+ Assert.AreEqual(6, FreeImage.GetUniqueColors(dib));
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_CreateShrunkenPaletteLUT()
+ {
+ Random rand = new Random();
+ dib = FreeImage.Allocate(1, 1, 8, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ Palette palette = new Palette(dib);
+ byte[] lut;
+ int colors;
+
+ for (int x = 0; x < palette.Length; x++)
+ {
+ palette[x] = 0xFF000000;
+ }
+
+ lut = FreeImage.CreateShrunkenPaletteLUT(dib, out colors);
+ Assert.AreEqual(1, colors);
+
+ for (int x = 0; x < palette.Length; x++)
+ {
+ Assert.AreEqual(0, lut[x]);
+ }
+
+ palette[1] = 0x00000001;
+ lut = FreeImage.CreateShrunkenPaletteLUT(dib, out colors);
+ Assert.AreEqual(2, colors);
+
+ Assert.AreEqual(0, lut[0]);
+ Assert.AreEqual(1, lut[1]);
+
+ for (int x = 2; x < palette.Length; x++)
+ {
+ Assert.AreEqual(0, lut[x]);
+ }
+
+ for (int x = 0; x < palette.Length; x++)
+ {
+ palette[x] = (uint)x;
+ }
+
+ lut = FreeImage.CreateShrunkenPaletteLUT(dib, out colors);
+ Assert.AreEqual(256, colors);
+
+ for (int x = 0; x < palette.Length; x++)
+ {
+ Assert.AreEqual(x, lut[x]);
+ }
+
+ uint[] testColors = new uint[] { 0xFF4F387C, 0xFF749178, 0xFF84D51A, 0xFF746B71, 0x74718163, 0x91648106 };
+ palette[0] = testColors[0];
+ palette[1] = testColors[1];
+ palette[2] = testColors[2];
+ palette[3] = testColors[3];
+ palette[4] = testColors[4];
+ palette[5] = testColors[5];
+
+ for (int x = testColors.Length; x < palette.Length; x++)
+ {
+ palette[x] = testColors[rand.Next(0, testColors.Length - 1)];
+ }
+
+ lut = FreeImage.CreateShrunkenPaletteLUT(dib, out colors);
+ Assert.AreEqual(testColors.Length, colors);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public void FreeImage_Rotate4bit()
+ {
+ Palette orgPal, rotPal;
+ FIBITMAP rotated;
+ byte index;
+ dib = FreeImage.Allocate(2, 3, 4, 0, 0, 0);
+ Assert.IsFalse(dib.IsNull);
+
+ index = 1; if (!FreeImage.SetPixelIndex(dib, 0, 0, ref index)) throw new Exception();
+ index = 2; if (!FreeImage.SetPixelIndex(dib, 1, 0, ref index)) throw new Exception();
+ index = 3; if (!FreeImage.SetPixelIndex(dib, 0, 1, ref index)) throw new Exception();
+ index = 4; if (!FreeImage.SetPixelIndex(dib, 1, 1, ref index)) throw new Exception();
+ index = 5; if (!FreeImage.SetPixelIndex(dib, 0, 2, ref index)) throw new Exception();
+ index = 6; if (!FreeImage.SetPixelIndex(dib, 1, 2, ref index)) throw new Exception();
+
+ //
+ // 90 deg
+ //
+
+ rotated = FreeImage.Rotate4bit(dib, 90d);
+ Assert.IsFalse(rotated.IsNull);
+ Assert.AreEqual(3, FreeImage.GetWidth(rotated));
+ Assert.AreEqual(2, FreeImage.GetHeight(rotated));
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_BITMAP, FreeImage.GetImageType(rotated));
+ Assert.AreEqual(4, FreeImage.GetBPP(rotated));
+ orgPal = new Palette(dib);
+ rotPal = new Palette(rotated);
+ Assert.IsNotNull(orgPal);
+ Assert.IsNotNull(rotPal);
+ Assert.AreEqual(orgPal.Length, rotPal.Length);
+ for (int i = 0; i < orgPal.Length; i++)
+ {
+ Assert.AreEqual(orgPal[i], rotPal[i]);
+ }
+
+ FreeImage.GetPixelIndex(rotated, 0, 0, out index);
+ Assert.AreEqual(5, index);
+ FreeImage.GetPixelIndex(rotated, 1, 0, out index);
+ Assert.AreEqual(3, index);
+ FreeImage.GetPixelIndex(rotated, 2, 0, out index);
+ Assert.AreEqual(1, index);
+ FreeImage.GetPixelIndex(rotated, 0, 1, out index);
+ Assert.AreEqual(6, index);
+ FreeImage.GetPixelIndex(rotated, 1, 1, out index);
+ Assert.AreEqual(4, index);
+ FreeImage.GetPixelIndex(rotated, 2, 1, out index);
+ Assert.AreEqual(2, index);
+ FreeImage.UnloadEx(ref rotated);
+
+ //
+ // 180 deg
+ //
+
+ rotated = FreeImage.Rotate4bit(dib, 180d);
+ Assert.IsFalse(rotated.IsNull);
+ Assert.AreEqual(FreeImage.GetWidth(dib), FreeImage.GetWidth(rotated));
+ Assert.AreEqual(FreeImage.GetHeight(dib), FreeImage.GetHeight(rotated));
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_BITMAP, FreeImage.GetImageType(rotated));
+ Assert.AreEqual(4, FreeImage.GetBPP(rotated));
+ orgPal = new Palette(dib);
+ rotPal = new Palette(rotated);
+ Assert.IsNotNull(orgPal);
+ Assert.IsNotNull(rotPal);
+ Assert.AreEqual(orgPal.Length, rotPal.Length);
+ for (int i = 0; i < orgPal.Length; i++)
+ {
+ Assert.AreEqual(orgPal[i], rotPal[i]);
+ }
+
+ FreeImage.GetPixelIndex(rotated, 0, 0, out index);
+ Assert.AreEqual(6, index);
+ FreeImage.GetPixelIndex(rotated, 1, 0, out index);
+ Assert.AreEqual(5, index);
+ FreeImage.GetPixelIndex(rotated, 0, 1, out index);
+ Assert.AreEqual(4, index);
+ FreeImage.GetPixelIndex(rotated, 1, 1, out index);
+ Assert.AreEqual(3, index);
+ FreeImage.GetPixelIndex(rotated, 0, 2, out index);
+ Assert.AreEqual(2, index);
+ FreeImage.GetPixelIndex(rotated, 1, 2, out index);
+ Assert.AreEqual(1, index);
+ FreeImage.UnloadEx(ref rotated);
+
+ //
+ // 270 deg
+ //
+
+ rotated = FreeImage.Rotate4bit(dib, 270d);
+ Assert.IsFalse(rotated.IsNull);
+ Assert.AreEqual(3, FreeImage.GetWidth(rotated));
+ Assert.AreEqual(2, FreeImage.GetHeight(rotated));
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_BITMAP, FreeImage.GetImageType(rotated));
+ Assert.AreEqual(4, FreeImage.GetBPP(rotated));
+ orgPal = new Palette(dib);
+ rotPal = new Palette(rotated);
+ Assert.IsNotNull(orgPal);
+ Assert.IsNotNull(rotPal);
+ Assert.AreEqual(orgPal.Length, rotPal.Length);
+ for (int i = 0; i < orgPal.Length; i++)
+ {
+ Assert.AreEqual(orgPal[i], rotPal[i]);
+ }
+
+ FreeImage.GetPixelIndex(rotated, 0, 0, out index);
+ Assert.AreEqual(2, index);
+ FreeImage.GetPixelIndex(rotated, 1, 0, out index);
+ Assert.AreEqual(4, index);
+ FreeImage.GetPixelIndex(rotated, 2, 0, out index);
+ Assert.AreEqual(6, index);
+ FreeImage.GetPixelIndex(rotated, 0, 1, out index);
+ Assert.AreEqual(1, index);
+ FreeImage.GetPixelIndex(rotated, 1, 1, out index);
+ Assert.AreEqual(3, index);
+ FreeImage.GetPixelIndex(rotated, 2, 1, out index);
+ Assert.AreEqual(5, index);
+ FreeImage.UnloadEx(ref rotated);
+
+ FreeImage.UnloadEx(ref dib);
+ }
+ }
+
+ [TestFixture]
+ public class FreeImageBitmapTest
+ {
+ ImageManager iManager = new ImageManager();
+ FIBITMAP dib = new FIBITMAP();
+ string freeImageCallback = null;
+
+ [TestFixtureSetUp]
+ public void Init()
+ {
+ FreeImageEngine.Message += new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [TestFixtureTearDown]
+ public void DeInit()
+ {
+ FreeImageEngine.Message -= new OutputMessageFunction(FreeImage_Message);
+ }
+
+ [SetUp]
+ public void InitEachTime()
+ {
+ }
+
+ [TearDown]
+ public void DeInitEachTime()
+ {
+ }
+
+ void FreeImage_Message(FREE_IMAGE_FORMAT fif, string message)
+ {
+ freeImageCallback = message;
+ }
+
+ [Test]
+ public void FreeImageBitmapConstructors()
+ {
+ Image bitmap;
+ FreeImageBitmap fib, fib2;
+ Stream stream;
+ Graphics g;
+ string filename = iManager.GetBitmapPath(ImageType.Odd, ImageColorType.Type_24);
+ Assert.IsNotNull(filename);
+ Assert.IsTrue(File.Exists(filename));
+
+ bitmap = new Bitmap(filename);
+ Assert.IsNotNull(bitmap);
+
+ fib = new FreeImageBitmap(bitmap);
+ Assert.AreEqual(bitmap.Width, fib.Width);
+ Assert.AreEqual(bitmap.Height, fib.Height);
+ fib.Dispose();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(bitmap, new Size(100, 100));
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+ bitmap.Dispose();
+
+ fib = new FreeImageBitmap(filename);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(filename, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(filename, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ fib.Dispose();
+
+ stream = new FileStream(filename, FileMode.Open);
+ Assert.IsNotNull(stream);
+
+ fib = new FreeImageBitmap(stream);
+ fib.Dispose();
+ stream.Seek(0, SeekOrigin.Begin);
+
+ fib = new FreeImageBitmap(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN);
+ fib.Dispose();
+ stream.Seek(0, SeekOrigin.Begin);
+
+ fib = new FreeImageBitmap(stream, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ fib.Dispose();
+ stream.Seek(0, SeekOrigin.Begin);
+
+ fib = new FreeImageBitmap(stream, FREE_IMAGE_FORMAT.FIF_UNKNOWN, FREE_IMAGE_LOAD_FLAGS.DEFAULT);
+ fib.Dispose();
+ stream.Dispose();
+
+ fib = new FreeImageBitmap(100, 100);
+ Assert.AreEqual(24, fib.ColorDepth);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ using (bitmap = new Bitmap(filename))
+ {
+ Assert.IsNotNull(bitmap);
+ using (g = Graphics.FromImage(bitmap))
+ {
+ Assert.IsNotNull(g);
+ fib = new FreeImageBitmap(100, 100, g);
+ }
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format1bppIndexed);
+ Assert.AreEqual(PixelFormat.Format1bppIndexed, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format4bppIndexed);
+ Assert.AreEqual(PixelFormat.Format4bppIndexed, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format8bppIndexed);
+ Assert.AreEqual(PixelFormat.Format8bppIndexed, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format16bppRgb555);
+ Assert.AreEqual(PixelFormat.Format16bppRgb555, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format16bppRgb565);
+ Assert.AreEqual(PixelFormat.Format16bppRgb565, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format24bppRgb);
+ Assert.AreEqual(PixelFormat.Format24bppRgb, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format32bppArgb);
+ Assert.AreEqual(PixelFormat.Format32bppArgb, fib.PixelFormat);
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(100, fib.Height);
+
+ stream = new MemoryStream();
+ BinaryFormatter formatter = new BinaryFormatter();
+
+ formatter.Serialize(stream, fib);
+ Assert.Greater(stream.Length, 0);
+ stream.Position = 0;
+
+ fib2 = formatter.Deserialize(stream) as FreeImageBitmap;
+ stream.Dispose();
+ fib.Dispose();
+ fib2.Dispose();
+
+ fib = new FreeImageBitmap(filename);
+ fib2 = new FreeImageBitmap(fib);
+ fib2.Dispose();
+
+ fib2 = new FreeImageBitmap(fib, new Size(31, 22));
+ Assert.AreEqual(31, fib2.Width);
+ Assert.AreEqual(22, fib2.Height);
+ fib2.Dispose();
+ fib.Dispose();
+
+ dib = FreeImage.Allocate(1000, 800, 24, 0xFF0000, 0xFF00, 0xFF);
+ Assert.IsFalse(dib.IsNull);
+
+ fib = new FreeImageBitmap(1000, 800, -(int)FreeImage.GetPitch(dib), FreeImage.GetPixelFormat(dib), FreeImage.GetScanLine(dib, 0));
+ fib.Dispose();
+ FreeImage.UnloadEx(ref dib);
+ }
+
+ [Test]
+ public unsafe void Properties()
+ {
+ string filename = iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_32);
+ Assert.IsNotNull(filename);
+ Assert.IsTrue(File.Exists(filename));
+
+ FreeImageBitmap fib = new FreeImageBitmap(filename);
+ Assert.IsFalse(fib.HasPalette);
+
+ try
+ {
+ Palette palette = fib.Palette;
+ Assert.Fail();
+ }
+ catch
+ {
+ }
+
+ Assert.IsFalse(fib.HasBackgroundColor);
+ fib.BackgroundColor = Color.LightSeaGreen;
+ Assert.IsTrue(fib.HasBackgroundColor);
+ Assert.That(
+ Color.LightSeaGreen.B == fib.BackgroundColor.Value.B &&
+ Color.LightSeaGreen.G == fib.BackgroundColor.Value.G &&
+ Color.LightSeaGreen.R == fib.BackgroundColor.Value.R);
+ fib.BackgroundColor = null;
+ Assert.IsFalse(fib.HasBackgroundColor);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(100, 100, PixelFormat.Format1bppIndexed);
+ ImageFlags flags = (ImageFlags)fib.Flags;
+ Assert.That((flags & ImageFlags.ColorSpaceRgb) == ImageFlags.ColorSpaceRgb);
+ Assert.That((flags & ImageFlags.HasAlpha) != ImageFlags.HasAlpha);
+ Assert.That((flags & ImageFlags.HasRealDpi) != ImageFlags.HasRealDpi);
+ Assert.That((flags & ImageFlags.HasTranslucent) != ImageFlags.HasTranslucent);
+ fib.Dispose();
+
+ dib = FreeImage.Allocate(100, 100, 32, 0xFF0000, 0xFF00, 0xFF);
+ FIICCPROFILE* prof = (FIICCPROFILE*)FreeImage.CreateICCProfile(dib, new byte[] { 0, 1, 2, 3 }, 4);
+ fib = new FreeImageBitmap(dib);
+ Scanline<RGBQUAD> sc = (Scanline<RGBQUAD>)fib.GetScanline(0);
+ RGBQUAD rgbq = sc[0];
+ rgbq.rgbReserved = 127;
+ sc[0] = rgbq;
+ flags = (ImageFlags)fib.Flags;
+ Assert.That((flags & ImageFlags.HasAlpha) == ImageFlags.HasAlpha);
+ Assert.That((flags & ImageFlags.HasRealDpi) != ImageFlags.HasRealDpi);
+ Assert.That((flags & ImageFlags.HasTranslucent) == ImageFlags.HasTranslucent);
+ fib.Dispose();
+ fib = null;
+ GC.Collect(2, GCCollectionMode.Forced);
+ GC.WaitForPendingFinalizers();
+
+ fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Metadata, ImageColorType.Type_01_Dither));
+ int[] propList = fib.PropertyIdList;
+ Assert.IsNotNull(propList);
+ Assert.Greater(propList.Length, 0);
+ PropertyItem[] propItemList = fib.PropertyItems;
+ Assert.IsNotNull(propItemList);
+ Assert.Greater(propItemList.Length, 0);
+ Assert.IsNotNull(fib.RawFormat);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Multipaged, ImageColorType.Type_01_Dither));
+ Assert.Greater(fib.FrameCount, 1);
+ fib.Dispose();
+ }
+
+ [Test]
+ public void GetBounds()
+ {
+ Random rand = new Random();
+ int height = rand.Next(1, 100), width = rand.Next(1, 100);
+ FreeImageBitmap fib = new FreeImageBitmap(width, height, PixelFormat.Format24bppRgb);
+
+ Assert.AreEqual(fib.VerticalResolution, fib.HorizontalResolution);
+ GraphicsUnit unit;
+ RectangleF rect;
+
+ unit = GraphicsUnit.Display;
+ rect = fib.GetBounds(ref unit);
+
+ Assert.AreEqual(GraphicsUnit.Pixel, unit);
+ Assert.AreEqual(width, (int)rect.Width);
+ Assert.AreEqual(height, (int)rect.Height);
+ fib.Dispose();
+ }
+
+ [Test]
+ public void GetPropertyItem()
+ {
+ FreeImageBitmap fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Metadata, ImageColorType.Type_01_Dither));
+ int[] list = fib.PropertyIdList;
+ Assert.IsNotNull(list);
+ Assert.Greater(list.Length, 0);
+
+ for (int i = 0; i < list.Length; i++)
+ {
+ PropertyItem item = fib.GetPropertyItem(list[i]);
+ Assert.IsNotNull(item);
+ }
+ fib.Dispose();
+ }
+
+ [Test]
+ public void RemovePropertyItem()
+ {
+ FreeImageBitmap fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Metadata, ImageColorType.Type_01_Dither));
+ Random rand = new Random();
+ int[] list = fib.PropertyIdList;
+ int length = list.Length;
+ Assert.Greater(list.Length, 0);
+
+ int id = list[rand.Next(0, list.Length - 1)];
+ Assert.IsNotNull(fib.GetPropertyItem(id));
+ fib.RemovePropertyItem(id);
+ list = fib.PropertyIdList;
+ Assert.That((list.Length + 1) == length);
+ fib.Dispose();
+ }
+
+ [Test]
+ public unsafe void RotateFlip()
+ {
+ FreeImageBitmap fib = new FreeImageBitmap(2, 2, PixelFormat.Format32bppArgb);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.RotateNoneFlipX);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.RotateNoneFlipY);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.RotateNoneFlipXY);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.Rotate90FlipNone);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.Rotate90FlipX);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ ResetRotateBitmap(fib);
+ fib.RotateFlip(RotateFlipType.Rotate90FlipY);
+ Assert.AreEqual(0x00000004, ((int*)fib.GetScanlinePointer(0))[0]);
+ Assert.AreEqual(0x00000002, ((int*)fib.GetScanlinePointer(0))[1]);
+ Assert.AreEqual(0x00000003, ((int*)fib.GetScanlinePointer(1))[0]);
+ Assert.AreEqual(0x00000001, ((int*)fib.GetScanlinePointer(1))[1]);
+
+ fib.Dispose();
+ }
+
+ private unsafe void ResetRotateBitmap(FreeImageBitmap fib)
+ {
+ ((int*)fib.GetScanlinePointer(0))[0] = 0x00000001;
+ ((int*)fib.GetScanlinePointer(0))[1] = 0x00000002;
+ ((int*)fib.GetScanlinePointer(1))[0] = 0x00000003;
+ ((int*)fib.GetScanlinePointer(1))[1] = 0x00000004;
+ }
+
+ [Test]
+ public unsafe void GetSetPixel()
+ {
+ Random rand = new Random();
+ FreeImageBitmap fib = new FreeImageBitmap(2, 1, PixelFormat.Format1bppIndexed);
+ Palette palette = fib.Palette;
+ for (int i = 0; i < palette.Length; i++)
+ {
+ palette[i] = (uint)rand.Next(int.MinValue, int.MaxValue);
+ fib.SetPixel(i, 0, palette[i]);
+ }
+ for (int i = 0; i < palette.Length; i++)
+ {
+ Assert.AreEqual(fib.GetPixel(i, 0), palette[i].Color);
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(16, 1, PixelFormat.Format4bppIndexed);
+ palette = fib.Palette;
+ for (int i = 0; i < palette.Length; i++)
+ {
+ palette[i] = (uint)rand.Next(int.MinValue, int.MaxValue);
+ fib.SetPixel(i, 0, palette[i]);
+ }
+ for (int i = 0; i < palette.Length; i++)
+ {
+ Assert.AreEqual(fib.GetPixel(i, 0), palette[i].Color);
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(256, 1, PixelFormat.Format8bppIndexed);
+ palette = fib.Palette;
+ for (int i = 0; i < palette.Length; i++)
+ {
+ palette[i] = (uint)rand.Next(int.MinValue, int.MaxValue);
+ fib.SetPixel(i, 0, palette[i]);
+ }
+ for (int i = 0; i < palette.Length; i++)
+ {
+ Assert.AreEqual(fib.GetPixel(i, 0), palette[i].Color);
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(1000, 1, PixelFormat.Format16bppRgb555);
+ for (int i = 0; i < 1000; i++)
+ {
+ Color orgColor = Color.FromArgb(rand.Next(int.MinValue, int.MaxValue));
+ fib.SetPixel(i, 0, orgColor);
+ Color newColor = fib.GetPixel(i, 0);
+ Assert.That(Math.Abs(orgColor.B - newColor.B) <= 8);
+ Assert.That(Math.Abs(orgColor.G - newColor.G) <= 8);
+ Assert.That(Math.Abs(orgColor.R - newColor.R) <= 8);
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(1000, 1, PixelFormat.Format24bppRgb);
+ for (int i = 0; i < 1000; i++)
+ {
+ Color orgColor = Color.FromArgb(rand.Next(int.MinValue, int.MaxValue));
+ fib.SetPixel(i, 0, orgColor);
+ Color newColor = fib.GetPixel(i, 0);
+ Assert.AreEqual(orgColor.B, newColor.B);
+ Assert.AreEqual(orgColor.G, newColor.G);
+ Assert.AreEqual(orgColor.R, newColor.R);
+ }
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(1000, 1, PixelFormat.Format32bppArgb);
+ for (int i = 0; i < 1000; i++)
+ {
+ Color orgColor = Color.FromArgb(rand.Next(int.MinValue, int.MaxValue));
+ fib.SetPixel(i, 0, orgColor);
+ Color newColor = fib.GetPixel(i, 0);
+ Assert.AreEqual(orgColor.B, newColor.B);
+ Assert.AreEqual(orgColor.G, newColor.G);
+ Assert.AreEqual(orgColor.R, newColor.R);
+ Assert.AreEqual(orgColor.A, newColor.A);
+ }
+ fib.Dispose();
+ }
+
+ [Test]
+ public void SaveAdd()
+ {
+ string filename = @"saveadd.tif";
+ FreeImageBitmap fib = new FreeImageBitmap(100, 100, PixelFormat.Format24bppRgb);
+ try
+ {
+ fib.SaveAdd();
+ Assert.Fail();
+ }
+ catch { }
+ Assert.IsFalse(File.Exists(filename));
+ fib.Save(filename);
+ fib.AdjustBrightness(0.3d);
+ fib.SaveAdd();
+ FreeImageBitmap other = new FreeImageBitmap(100, 100, PixelFormat.Format24bppRgb);
+ foreach (Scanline<RGBTRIPLE> scanline in other)
+ {
+ for (int i = 0; i < scanline.Length; i++)
+ {
+ scanline[i] = new RGBTRIPLE(Color.FromArgb(0x339955));
+ }
+ }
+ fib.SaveAdd(other);
+ other.SaveAdd(filename);
+ other.Dispose();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(filename);
+ Assert.AreEqual(4, fib.FrameCount);
+ fib.Dispose();
+ File.Delete(filename);
+ Assert.IsFalse(File.Exists(filename));
+ }
+
+ [Test]
+ public void Clone()
+ {
+ FreeImageBitmap fib = new FreeImageBitmap(iManager.GetBitmapPath(ImageType.Even, ImageColorType.Type_24));
+ object obj = new object();
+ fib.Tag = obj;
+ FreeImageBitmap clone = fib.Clone() as FreeImageBitmap;
+ Assert.IsNotNull(clone);
+ Assert.AreEqual(fib.Width, clone.Width);
+ Assert.AreEqual(fib.Height, clone.Height);
+ Assert.AreEqual(fib.ColorDepth, clone.ColorDepth);
+ Assert.AreSame(fib.Tag, clone.Tag);
+ Assert.AreEqual(fib.ImageFormat, clone.ImageFormat);
+ clone.Dispose();
+ fib.Dispose();
+ }
+
+ [Ignore]
+ public void LockBits()
+ {
+ }
+
+ [Ignore]
+ public void UnlockBits()
+ {
+ }
+
+ [Test]
+ public void GetTypeConvertedInstance()
+ {
+ using (FreeImageBitmap fib = new FreeImageBitmap(10, 10, PixelFormat.Format8bppIndexed))
+ {
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_BITMAP, fib.ImageType);
+ using (FreeImageBitmap conv = fib.GetTypeConvertedInstance(FREE_IMAGE_TYPE.FIT_DOUBLE, true))
+ {
+ Assert.IsNotNull(conv);
+ Assert.AreEqual(FREE_IMAGE_TYPE.FIT_DOUBLE, conv.ImageType);
+ }
+ }
+ }
+
+ [Test]
+ public void GetColorConvertedInstance()
+ {
+ using (FreeImageBitmap fib = new FreeImageBitmap(10, 10, PixelFormat.Format32bppArgb))
+ {
+ Assert.AreEqual(32, fib.ColorDepth);
+ using (FreeImageBitmap conv = fib.GetColorConvertedInstance(FREE_IMAGE_COLOR_DEPTH.FICD_24_BPP))
+ {
+ Assert.IsNotNull(conv);
+ Assert.AreEqual(24, conv.ColorDepth);
+ }
+ }
+ }
+
+ [Test]
+ public void GetScaledInstance()
+ {
+ using (FreeImageBitmap fib = new FreeImageBitmap(100, 80, PixelFormat.Format32bppArgb))
+ {
+ Assert.AreEqual(100, fib.Width);
+ Assert.AreEqual(80, fib.Height);
+ using (FreeImageBitmap conv = fib.GetScaledInstance(80, 60, FREE_IMAGE_FILTER.FILTER_BICUBIC))
+ {
+ Assert.IsNotNull(conv);
+ Assert.AreEqual(80, conv.Width);
+ Assert.AreEqual(60, conv.Height);
+ }
+ }
+ }
+
+ [Test]
+ public unsafe void GetRotatedInstance()
+ {
+ using (FreeImageBitmap fib = new FreeImageBitmap(2, 2, PixelFormat.Format32bppArgb))
+ {
+ ((int*)fib.GetScanlinePointer(0))[0] = 0x1;
+ ((int*)fib.GetScanlinePointer(0))[1] = 0x2;
+ ((int*)fib.GetScanlinePointer(1))[0] = 0x3;
+ ((int*)fib.GetScanlinePointer(1))[1] = 0x4;
+ using (FreeImageBitmap conv = fib.GetRotatedInstance(90d))
+ {
+ Assert.IsNotNull(conv);
+ Assert.AreEqual(((int*)conv.GetScanlinePointer(0))[0], 0x3);
+ Assert.AreEqual(((int*)conv.GetScanlinePointer(0))[1], 0x1);
+ Assert.AreEqual(((int*)conv.GetScanlinePointer(1))[0], 0x4);
+ Assert.AreEqual(((int*)conv.GetScanlinePointer(1))[1], 0x2);
+ }
+ }
+ }
+
+ [Test]
+ public void GetScanline()
+ {
+ FreeImageBitmap fib;
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format1bppIndexed);
+ Scanline<FI1BIT> scanline1 = (Scanline<FI1BIT>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format4bppIndexed);
+ Scanline<FI4BIT> scanline2 = (Scanline<FI4BIT>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format8bppIndexed);
+ Scanline<Byte> scanline3 = (Scanline<Byte>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format16bppRgb555);
+ Scanline<FI16RGB555> scanline4 = (Scanline<FI16RGB555>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format16bppRgb565);
+ Scanline<FI16RGB565> scanline5 = (Scanline<FI16RGB565>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format24bppRgb);
+ Scanline<RGBTRIPLE> scanline6 = (Scanline<RGBTRIPLE>)fib.GetScanline(0);
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format32bppArgb);
+ Scanline<RGBQUAD> scanline7 = (Scanline<RGBQUAD>)fib.GetScanline(0);
+ fib.Dispose();
+ }
+
+ [Test]
+ public void GetScanlines()
+ {
+ FreeImageBitmap fib;
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format1bppIndexed);
+ IList<Scanline<FI1BIT>> scanline01 = (IList<Scanline<FI1BIT>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format4bppIndexed);
+ IList<Scanline<FI4BIT>> scanline02 = (IList<Scanline<FI4BIT>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format8bppIndexed);
+ IList<Scanline<Byte>> scanline03 = (IList<Scanline<Byte>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format16bppRgb555);
+ IList<Scanline<FI16RGB555>> scanline04 = (IList<Scanline<FI16RGB555>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format16bppRgb565);
+ IList<Scanline<FI16RGB565>> scanline05 = (IList<Scanline<FI16RGB565>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format24bppRgb);
+ IList<Scanline<RGBTRIPLE>> scanline06 = (IList<Scanline<RGBTRIPLE>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, PixelFormat.Format32bppArgb);
+ IList<Scanline<RGBQUAD>> scanline07 = (IList<Scanline<RGBQUAD>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_COMPLEX);
+ IList<Scanline<FICOMPLEX>> scanline08 = (IList<Scanline<FICOMPLEX>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_DOUBLE);
+ IList<Scanline<Double>> scanline09 = (IList<Scanline<Double>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_FLOAT);
+ IList<Scanline<Single>> scanline10 = (IList<Scanline<Single>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_INT16);
+ IList<Scanline<Int16>> scanline11 = (IList<Scanline<Int16>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_INT32);
+ IList<Scanline<Int32>> scanline12 = (IList<Scanline<Int32>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_RGB16);
+ IList<Scanline<FIRGB16>> scanline13 = (IList<Scanline<FIRGB16>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_RGBA16);
+ IList<Scanline<FIRGBA16>> scanline14 = (IList<Scanline<FIRGBA16>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_RGBAF);
+ IList<Scanline<FIRGBAF>> scanline15 = (IList<Scanline<FIRGBAF>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_RGBF);
+ IList<Scanline<FIRGBF>> scanline16 = (IList<Scanline<FIRGBF>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_UINT16);
+ IList<Scanline<UInt16>> scanline17 = (IList<Scanline<UInt16>>)fib.GetScanlines();
+ fib.Dispose();
+
+ fib = new FreeImageBitmap(10, 10, FREE_IMAGE_TYPE.FIT_UINT32);
+ IList<Scanline<UInt32>> scanline18 = (IList<Scanline<UInt32>>)fib.GetScanlines();
+ fib.Dispose();
+ }
+
+ [Test]
+ public void Operators()
+ {
+ FreeImageBitmap fib1 = null, fib2 = null;
+ Assert.IsTrue(fib1 == fib2);
+ Assert.IsFalse(fib1 != fib2);
+ Assert.IsTrue(fib1 == null);
+ Assert.IsFalse(fib1 != null);
+
+ fib1 = new FreeImageBitmap(10, 10, PixelFormat.Format24bppRgb);
+ Assert.IsFalse(fib1 == fib2);
+ Assert.IsTrue(fib1 != fib2);
+
+ fib2 = fib1;
+ fib1 = null;
+ Assert.IsFalse(fib1 == fib2);
+ Assert.IsTrue(fib1 != fib2);
+
+ fib1 = new FreeImageBitmap(10, 9, PixelFormat.Format24bppRgb);
+ Assert.IsFalse(fib1 == fib2);
+ Assert.IsTrue(fib1 != fib2);
+
+ fib2.Dispose();
+ fib2 = fib1;
+
+ Assert.IsTrue(fib1 == fib2);
+ Assert.IsFalse(fib1 != fib2);
+
+ fib2 = fib1.Clone() as FreeImageBitmap;
+ Assert.IsTrue(fib1 == fib2);
+ Assert.IsFalse(fib1 != fib2);
+
+ fib1.Dispose();
+ fib2.Dispose();
+ }
+ }
+
+ public class Program
+ {
+ static ImageManager iManager = new ImageManager();
+ static ImportedFunctionsTest ift = new ImportedFunctionsTest();
+ static ImportedStructsTest ist = new ImportedStructsTest();
+ static WrapperStructsTest wst = new WrapperStructsTest();
+ static WrapperFunctionsTest wft = new WrapperFunctionsTest();
+ static FreeImageBitmapTest fib = new FreeImageBitmapTest();
+
+ public static void Main()
+ {
+ List<TestClass> classList = new List<TestClass>(5);
+ classList.Add(new TestClass(ift));
+ classList.Add(new TestClass(ist));
+ classList.Add(new TestClass(wst));
+ classList.Add(new TestClass(wft));
+ classList.Add(new TestClass(fib));
+
+ for (int i = 0; i < 10000; )
+ {
+ for (int j = 0; j < classList.Count; j++)
+ classList[j].ExecuteTests();
+ Console.WriteLine("Loop {0}", ++i);
+ //GC.Collect();
+ }
+ }
+ }
+
+ public class TestClass
+ {
+ private object classMember = null;
+
+ private MethodInfo classSetUp = null;
+ private MethodInfo classTearDown = null;
+
+ private MethodInfo testSetUp = null;
+ private MethodInfo testTearDown = null;
+
+ private List<MethodInfo> methodList = null;
+
+ private static object[] parameters = { };
+
+ public TestClass(object classMember)
+ {
+ this.classMember = classMember;
+ MethodInfo[] infos = classMember.GetType().GetMethods(System.Reflection.BindingFlags.Public | BindingFlags.Instance);
+ methodList = new List<MethodInfo>(infos.Length);
+
+ foreach (MethodInfo info in infos)
+ {
+ object[] attributes = info.GetCustomAttributes(false);
+ foreach (Attribute attribute in attributes)
+ {
+ if (attribute.GetType() == typeof(TestAttribute))
+ {
+ methodList.Add(info);
+ break;
+ }
+ else if (attribute.GetType() == typeof(TestFixtureSetUpAttribute))
+ {
+ classSetUp = info;
+ break;
+ }
+ else if (attribute.GetType() == typeof(TestFixtureTearDownAttribute))
+ {
+ classTearDown = info;
+ break;
+ }
+ else if (attribute.GetType() == typeof(SetUpAttribute))
+ {
+ testSetUp = info;
+ break;
+ }
+ else if (attribute.GetType() == typeof(TearDownAttribute))
+ {
+ testTearDown = info;
+ break;
+ }
+ }
+ }
+ }
+
+ public void ExecuteTests()
+ {
+ if (classSetUp != null)
+ classSetUp.Invoke(classMember, parameters);
+
+ foreach (MethodInfo method in methodList)
+ {
+ if (testSetUp != null)
+ testSetUp.Invoke(classMember, parameters);
+
+ try
+ {
+ Console.WriteLine(method.ToString());
+ method.Invoke(classMember, parameters);
+ }
+ catch (Exception ex)
+ {
+ while (ex.InnerException != null)
+ ex = ex.InnerException;
+ Console.WriteLine(ex.ToString());
+ Environment.Exit(99);
+ }
+
+ if (testTearDown != null)
+ testTearDown.Invoke(classMember, parameters);
+ }
+
+ if (classTearDown != null)
+ classTearDown.Invoke(classMember, parameters);
+ }
+ }
+} \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.csproj b/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.csproj
new file mode 100644
index 0000000..86c5b76
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/UnitTest/UnitTest.csproj
@@ -0,0 +1,105 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{FC7B3A04-FACE-4F07-9CFD-8C6ED06E3CDC}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>FreeImageAPI</RootNamespace>
+ <AssemblyName>UnitTest</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>659,660,661</NoWarn>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <NoWarn>659,660,661</NoWarn>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>659,660,661</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <Optimize>true</Optimize>
+ <NoWarn>659,660,661</NoWarn>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x86</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
+ <DebugSymbols>true</DebugSymbols>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <NoWarn>659,660,661</NoWarn>
+ <DebugType>full</DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <Optimize>true</Optimize>
+ <NoWarn>659,660,661</NoWarn>
+ <DebugType>
+ </DebugType>
+ <PlatformTarget>x64</PlatformTarget>
+ <UseVSHostingProcess>false</UseVSHostingProcess>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\..\..\..\..\..\..\Programme\NUnit 2.4.8\bin\nunit.framework.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.XML" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="FreeImage.cs" />
+ <Compile Include="ImageManager.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UnitTest.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Wrapper/FreeImage.NET/cs/Whats_New.NET.txt b/Wrapper/FreeImage.NET/cs/Whats_New.NET.txt
new file mode 100644
index 0000000..0be6135
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/Whats_New.NET.txt
@@ -0,0 +1,111 @@
+What's New for FreeImage.NET
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+September 15, 2009 - 3.13.0.1
++ [Jean-Philippe Goerke] Added PFM, PICT and RAW file formats.
++ [Jean-Philippe Goerke] Added loading flag JPEG_EXIFROTATE.
++ [Jean-Philippe Goerke] Added method GetNativeVersion() to the FreeImage class.
+! [Jean-Philippe Goerke] Changed FreeImage.IsAvailable() now returning false in case the native library is out of date or unusable.
+- [Jean-Philippe Goerke] Removed FREEIMAGE_MAJOR_VERSION, FREEIMAGE_MINOR_VERSION and FREEIMAGE_RELEASE_SERIAL constants from class FreeImage.
++ [Jean-Philippe Goerke] Added enumeration FREE_IMAGE_COLOR_OPTIONS.
++ [Jean-Philippe Goerke] Added new overloads for FreeImage.Allocate() and FreeImage.AllocateT().
++ [Jean-Philippe Goerke] Added methods AllocateEx(), AllocateExT(), FillBackground() and EnlargeCanvas() to class FreeImage.
++ [Jean-Philippe Goerke] Added methods FillBackground(), EnlargeCanvas() and GetEnlargedInstance() to class FreeImageBitmap.
+- [Jean-Philippe Goerke] Removed unused ConvertLineXtoY() methods.
+* [kruno13] Fixed a bug in the FreeImageBitmap constructors.
+- [Jean-Philippe Goerke] Removed unneeded GCHandles used with delegates.
++ [Jean-Philippe Goerke] Added overloaded method OpenMultiBitmapFromStream to class FreeImage.
++ [Jean-Philippe Goerke] FreeImageBitmap now supports loading multipage bitmaps from streams. Warning: The stream must remain open for the bitmap's lifetime.
+* [mshanke] Fixed some IPTC metadata incorrect namings.
+! [Jean-Philippe Goerke] Method FreeImage.RotateClassic is now deprecated.
++ [Jean-Philippe Goerke] Added method Rotate() to the FreeImage class.
+! [Jean-Philippe Goerke] FreeImageBitmap now uses the method Rotate instead of RotateClassic.
+
+April 20, 2009 - 1.10
+! [Jean-Philippe Goerke] Updated wrapper-version to 1.10 including some minor changes.
+
+February 27, 2009 - 1.09
++ [Jean-Philippe Goerke] Help file creation now uses the Version Builder plugin of Sandcastle Help File Builder to generate an MSDN-like Version Information paragraph in the help file.
++ [Jean-Philippe Goerke] Added new metadata model class MDM_EXIF_MAIN to replace MDM_MAIN. Class MDM_MAIN still exists but is marked obsolete and will be removed in a future release.
++ [Jean-Philippe Goerke] Added various properties to access the value of metadata tags directly to all MDM_* classes expect MDM_CUSTOM, MDM_NODATA and MDM_MAKERNOTE.
+! [Jean-Philippe Goerke] Now classes deriving from MetadataModel, expect obsoltete class MDM_MAIN, are no longer sealed.
+! [Jean-Philippe Goerke] Class GifInformation now derives from MDM_ANIMATION. Moved properties into base class MDM_ANIMATION.
++ [Jean-Philippe Goerke] Added enumerations AltitudeType, DirectionReference, InteroperabilityMode, LatitudeType, LongitudeType, ImageOrientation and VelocityUnit to class MetadataModel.
+* [Jean-Philippe Goerke] Fixed a bug in MetadataTag.Count, MetadataTag.Length and MetadataTag.Value.
++ [Jean-Philippe Goerke] Added attribute DebuggerBrowsable(DebuggerBrowsableState.Never) to some protected and private fields.
+
+February 23, 2009 - 1.08
+! [Jean-Philippe Goerke] FreeImage.NET now uses Sandcastle Help File Builder 1.8.0.1
++ [Jean-Philippe Goerke] Added new Sandcastle Help File Builder project file FreeImage.NET.shfbproj.
+* [headkaze] Fixed a bug in FreeImage.CreateFromBitmap, which now incorporates any transparency information from palletized .NET Bitmaps.
++ [Jean-Philippe Goerke] Added new overloaded method CreateGlobalPalette() to class GifInformation to create global palettes from local palettes.
+! [Jean-Philippe Goerke] Renamed internal method FreeImage.SetTransparencyTable_ to FreeImage.SetTransparencyTable.
++ [Jean-Philippe Goerke] Added attribute DebuggerBrowsable(DebuggerBrowsableState.Never) to many protected and private fields.
+
+February 20, 2009 - 1.07
+* [Jean-Philippe Goerke] Fixed a bug in FreeImage.IsFilenameValidForFIF and FreeImage.IsExtensionValidForFIF.
+* [Jean-Philippe Goerke] Fixed a bug in FreeImage.SaveEx that could prevent saving supported non-bitmap types.
+* [Jean-Philippe Goerke] Fixed a small bug in FreeImage.CompareData.
++ [Jean-Philippe Goerke] Added two overloads of ColorQuantizeEx() in class FreeImage to return images with a color depth smaller than 8.
+! [Jean-Philippe Goerke] Updated FreeImage.ConvertColorDepth to support 1- and 4-bpp color conversions (FreeImage_ConvertTo4Bits only creates grayscale results).
+* [headkaze] Fixed a bug in FreeImage.GetBitmap, which now adds any transparency information to palletized .NET Bitmaps.
+* [headkaze] Fixed a bug in FreeImage.GetBitmap and FreeImage.CreateFromBitmap to support palettes with sizes different from 2, 16 and 256 entries.
+! [Jean-Philippe Goerke] Improved handling of multipage bitmaps in FreeImageBitmap class.
++ [Jean-Philippe Goerke] Added new overloads for FreeImageBitmap.SaveAdd() to allow inserting frames at a specified page index.
++ [Jean-Philippe Goerke] Added new class GifInformation which provides access to GIF format specific metadata (GlobalPalette, Animation, etc.).
++ [Jean-Philippe Goerke] Added enumeration DisposalMethodType.
+! [Jean-Philippe Goerke] Updated class MemoryArray<T>, which now is Disposable and has a new static constructor.
+! [Jean-Philippe Goerke] Removed code using reflection from class ImageMetadata.
++ [Jean-Philippe Goerke] Added new ctor(FITAG) and ctor(MetadataTag) to class Palette to support palettes stored in metadata tags.
++ [Jean-Philippe Goerke] Added new ctor(RGBQUAD[]), ctor(Color[]) and ctor(int) to create new stand-alone palettes to class Palette.
++ [Jean-Philippe Goerke] Added overloaded CreateGrayscalePalette(), Reverse() and CopyFrom() to class Palette.
+! [Jean-Philippe Goerke] Changed the behavior of MetadataTag.Value. byte and byte[] are now stored as FREE_IMAGE_MDTYPE.FIDT_BYTE instead of FREE_IMAGE_MDTYPE.FIDT_UNDEFINED.
++ [Jean-Philippe Goerke] Added a type check to MetadataTag.SetValue(object), MetadataTag.SetValue(object, FREE_IMAGE_MDTYPE) and the setter of MetadataTag.Value.
+
+November 18, 2008 - 1.06
+* [Jean-Philippe Goerke] Fixed a bug in FreeImage.SaveEx.
+! [Jean-Philippe Goerke] Improved method FreeImage.IsFilenameValidForFIF.
+
+November 5, 2008 - 1.05
+! [Jean-Philippe Goerke] Updated documentation of FreeImage.ConvertFromRawBits and FreeImage.ConvertToRawBits.
++ [Jean-Philippe Goerke] Added new overload ConvertFromRawBits(byte[],int,int,int,uint,uint,uint,uint,bool) to the FreeImage class.
++ [Jean-Philippe Goerke] Added new overload ConvertFromRawBits(byte[],FREE_IMAGE_TYPE,int,int,int,uint,uint,uint,uint bool) to the FreeImage class.
++ [Jean-Philippe Goerke] Added new overload ConvertToRawBits(byte[],FIBITMAP,int,uint,uint,uint,uint,bool) to the FreeImage class.
+! [Jean-Philippe Goerke] Improved method FreeImage.CreatePropertyItem.
++ [Jean-Philippe Goerke] Added overloads for CopyMemory to class FreeImage which support direct usage of arrays.
+! [Jean-Philippe Goerke] Replaced calls to FreeImage.MoveMemory with FreeImage.CopyMemory.
+! [Jean-Philippe Goerke] Class FreeImageBitmap now derives from MarshalByRefObject.
++ [Jean-Philippe Goerke] Added new ctor(int,int,int,PixelFormat,byte[]) and ctor(int,int,int,int,FREE_IMAGE_TYPE,byte[]) to the FreeImageBitmap class.
+
+August 29, 2008 - 1.04
++ [Jean-Philippe Goerke] Added new target architectures x86 and x64 to the Visual Studio 2005 solution and project files.
++ [Jean-Philippe Goerke] Added static readonly field Zero to FIBITMAP, FIMEMORY, FIMETADATA, FIMULTIBITMAP and FITAG.
+! [Jean-Philippe Goerke] Changed CreateFromBitmap to handle all formats contained by System.Drawing.Imaging.PixelFormat.
++ [Jean-Philippe Goerke] Added overload for ConvertFromRawBits to class FreeImage which supports creating images of any FREE_IMAGE_TYPE from raw bits.
++ [Jean-Philippe Goerke] Added method GetTypeParameters to class FreeImage.
+! [Jean-Philippe Goerke] Both constructors FreeImageBitmap.ctor(int,int,PixelFormat) and FreeImageBitmap.ctor(int,int,int,PixelFormat,IntPtr) now work with all formats defined in PixelFormat.
++ [Jean-Philippe Goerke] Added new constructor FreeImageBitmap.ctor(int,int,int,int,FREE_IMAGE_TYPE,IntPtr) to FreeImageBitmap class.
+
+August 18, 2008 - 1.03
+* [Eric T. Wilson] Added GC.AddMemoryPressure and GC.RemoveMemoryPressure to FreeImageBitmap class.
++ [Eric T. Wilson] Added ToBitmap method to FreeImageBitmap class.
+! [Eric T. Wilson] Changed implicit conversion operators to and from System.Drawing.Bitmap to explicit operators.
+- [Eric T. Wilson] Removed Message event from FreeImage class. Use event FreeImageEngine.Message instead.
+- [Eric T. Wilson] Removed contructors ctor(int) and ctor(IntPtr) from FIBITMAP, FIMULTIBITMAP, FIMEMORY, FIMETADATA and FITAG.
+- [Eric T. Wilson] Removed implicit conversion operators from and to int and IntPtr from FIBITMAP, FIMULTIBITMAP, FIMEMORY, FIMETADATA and FITAG.
++ [Jean-Philippe Goerke] Added SetNull method to FIBITMAP, FIMULTIBITMAP, FIMEMORY, FIMETADATA and FITAG.
+! [Jean-Philippe Goerke] Changed handling of multipage images in FreeImageBitmap: As with System.Drawing.Bitmap, any changes applied to an active frame are no longer written back to the multipage image loaded.
+* [Jean-Philippe Goerke] Fixed a bug in FreeImage.SaveToStream(ref FIBITMAP, Stream, FREE_IMAGE_FORMAT, FREE_IMAGE_SAVE_FLAGS, FREE_IMAGE_COLOR_DEPTH, bool): changed catch block into a finally block.
+
+July 25, 2008 - 1.02
++ [Jean-Philippe Goerke] Improved handling of XMP metadata in MetadataTag.cs: Key is now set to "XMLPacket" not changeable if Model is FREE_IMAGE_MDMODEL.FIMD_XMP.
+
+July 01, 2008 - 1.01
++ [Jean-Philippe Goerke] Added methods Quantize and GetQuantizedInstance to the FreeImageBitmap class.
+
+November 12, 2007 - 1.00
++ [Jean-Philippe Goerke] Initial release.
diff --git a/Wrapper/FreeImage.NET/cs/clean.bat b/Wrapper/FreeImage.NET/cs/clean.bat
new file mode 100755
index 0000000..e359a24
--- /dev/null
+++ b/Wrapper/FreeImage.NET/cs/clean.bat
@@ -0,0 +1,48 @@
+@ECHO OFF
+
+rd "Library\bin" /s /q
+rd "Library\obj" /s /q
+
+rd "Samples\Sample 01 - Loading and saving\bin" /s /q
+rd "Samples\Sample 01 - Loading and saving\obj" /s /q
+
+rd "Samples\Sample 02 - Multipaged bitmaps\bin" /s /q
+rd "Samples\Sample 02 - Multipaged bitmaps\obj" /s /q
+
+rd "Samples\Sample 03 - Allocating\bin" /s /q
+rd "Samples\Sample 03 - Allocating\obj" /s /q
+
+rd "Samples\Sample 04 - Getting bitmap informations\bin" /s /q
+rd "Samples\Sample 04 - Getting bitmap informations\obj" /s /q
+
+rd "Samples\Sample 05 - Working with pixels\bin" /s /q
+rd "Samples\Sample 05 - Working with pixels\obj" /s /q
+
+rd "Samples\Sample 06 - Converting\bin" /s /q
+rd "Samples\Sample 06 - Converting\obj" /s /q
+
+rd "Samples\Sample 07 - ICC Profiles\bin" /s /q
+rd "Samples\Sample 07 - ICC Profiles\obj" /s /q
+
+rd "Samples\Sample 08 - Creating a plugin\bin" /s /q
+rd "Samples\Sample 08 - Creating a plugin\obj" /s /q
+
+rd "Samples\Sample 09 - Working with streams\bin" /s /q
+rd "Samples\Sample 09 - Working with streams\obj" /s /q
+
+rd "Samples\Sample 10 - Metadata\bin" /s /q
+rd "Samples\Sample 10 - Metadata\obj" /s /q
+
+rd "Samples\Sample 11 - Using the FreeImageBitmap class\bin" /s /q
+rd "Samples\Sample 11 - Using the FreeImageBitmap class\obj" /s /q
+
+rd "SourceFileMerger\bin" /s /q
+rd "SourceFileMerger\obj" /s /q
+
+rd "UnitTest\bin" /s /q
+rd "UnitTest\obj" /s /q
+
+del "FreeImage.net.VisualState.xml"
+del "TestResult.xml"
+del *.suo /A:H /S /Q
+del *.user /S /Q \ No newline at end of file
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.2003.sln b/Wrapper/FreeImagePlus/FreeImagePlus.2003.sln
new file mode 100644
index 0000000..4317117
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.2003.sln
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImagePlus", "FreeImagePlus.2003.vcproj", "{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug.ActiveCfg = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug.Build.0 = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.2003.vcproj b/Wrapper/FreeImagePlus/FreeImagePlus.2003.vcproj
new file mode 100644
index 0000000..9c7f6b7
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.2003.vcproj
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="FreeImagePlus"
+ ProjectGUID="{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="TRUE"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="TRUE"
+ OptimizeForProcessor="3"
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_SECURE_NO_DEPRECATE"
+ StringPooling="TRUE"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="FALSE"
+ TreatWChar_tAsBuiltInType="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/FreeImagePlus.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImage.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\Release/FreeImagePlus.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/FreeImagePlus.pdb"
+ ImportLibrary=".\Release/FreeImagePlus.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImagePlus.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImagePlus.lib dist\
+
+copy Release\FreeImagePlus.dll dist\
+
+copy FreeImagePlus.h dist\
+
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_SECURE_NO_DEPRECATE"
+ StringPooling="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ TreatWChar_tAsBuiltInType="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/FreeImagePlus.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImaged.lib odbc32.lib odbccp32.lib"
+ OutputFile="Debug/FreeImagePlusd.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/FreeImagePlusd.pdb"
+ ImportLibrary=".\Debug/FreeImagePlusd.lib"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImagePlus.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImagePlusd.lib dist\
+
+copy Debug\FreeImagePlusd.dll dist\
+
+copy FreeImagePlus.h dist\
+
+"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="src\fipImage.cpp">
+ </File>
+ <File
+ RelativePath="src\fipMemoryIO.cpp">
+ </File>
+ <File
+ RelativePath="src\fipMetadataFind.cpp">
+ </File>
+ <File
+ RelativePath="src\fipMultiPage.cpp">
+ </File>
+ <File
+ RelativePath="src\fipTag.cpp">
+ </File>
+ <File
+ RelativePath="src\fipWinImage.cpp">
+ </File>
+ <File
+ RelativePath="src\FreeImagePlus.cpp">
+ </File>
+ <File
+ RelativePath="FreeImagePlus.rc">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="FreeImagePlus.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ </Filter>
+ <File
+ RelativePath="WhatsNew_FIP.txt">
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.2005.sln b/Wrapper/FreeImagePlus/FreeImagePlus.2005.sln
new file mode 100644
index 0000000..c8ca720
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.2005.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeImagePlus", "FreeImagePlus.2005.vcproj", "{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.ActiveCfg = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Debug|Win32.Build.0 = Debug|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.ActiveCfg = Release|Win32
+ {94F36908-A4E2-4533-939D-64FF6EADA5A1}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.2005.vcproj b/Wrapper/FreeImagePlus/FreeImagePlus.2005.vcproj
new file mode 100644
index 0000000..2d3a94a
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.2005.vcproj
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="FreeImagePlus"
+ ProjectGUID="{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ RootNamespace="FreeImagePlus"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImagePlus.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ BufferSecurityCheck="false"
+ TreatWChar_tAsBuiltInType="true"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Release/FreeImagePlus.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImage.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\Release/FreeImagePlus.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Release/FreeImagePlus.pdb"
+ ImportLibrary=".\Release/FreeImagePlus.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImagePlus.lib dist\&#x0D;&#x0A;&#x0D;&#x0A;copy Release\FreeImagePlus.dll dist\&#x0D;&#x0A;&#x0D;&#x0A;copy FreeImagePlus.h dist\&#x0D;&#x0A;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImagePlus.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ PrecompiledHeaderFile=".\Debug/FreeImagePlus.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImaged.lib odbc32.lib odbccp32.lib"
+ OutputFile="Debug/FreeImagePlusd.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/FreeImagePlusd.pdb"
+ ImportLibrary=".\Debug/FreeImagePlusd.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImagePlusd.lib dist\&#x0D;&#x0A;&#x0D;&#x0A;copy Debug\FreeImagePlusd.dll dist\&#x0D;&#x0A;&#x0D;&#x0A;copy FreeImagePlus.h dist\&#x0D;&#x0A;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="src\fipImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMetadataFind.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipWinImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\FreeImagePlus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="FreeImagePlus.rc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="FreeImagePlus.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="WhatsNew_FIP.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.2008.vcproj b/Wrapper/FreeImagePlus/FreeImagePlus.2008.vcproj
new file mode 100644
index 0000000..bac2aeb
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.2008.vcproj
@@ -0,0 +1,269 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="FreeImagePlus"
+ ProjectGUID="{94F36908-A4E2-4533-939D-64FF6EADA5A1}"
+ RootNamespace="FreeImagePlus"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/FreeImagePlus.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+
+ BufferSecurityCheck="false"
+
+
+
+ PrecompiledHeaderFile=".\Release/FreeImagePlus.pch"
+
+
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImage.lib odbc32.lib odbccp32.lib"
+ OutputFile=".\Release/FreeImagePlus.dll"
+
+ SuppressStartupBanner="true"
+ ProgramDatabaseFile=".\Release/FreeImagePlus.pdb"
+
+
+ ImportLibrary=".\Release/FreeImagePlus.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Release\FreeImagePlus.lib dist\&#x0D;&#x0A;&#x0D;&#x0A;copy Release\FreeImagePlus.dll dist\&#x0D;&#x0A;&#x0D;&#x0A;copy FreeImagePlus.h dist\&#x0D;&#x0A;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/FreeImagePlus.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+
+ AdditionalIncludeDirectories=".,../../Source"
+ PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;_USRDLL;FIP_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
+ StringPooling="true"
+
+
+
+
+ PrecompiledHeaderFile=".\Debug/FreeImagePlus.pch"
+
+
+ CompileAs="0"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="../../Dist/FreeImaged.lib odbc32.lib odbccp32.lib"
+ OutputFile="Debug/FreeImagePlusd.dll"
+
+ SuppressStartupBanner="true"
+
+ ProgramDatabaseFile=".\Debug/FreeImagePlusd.pdb"
+
+
+ ImportLibrary=".\Debug/FreeImagePlusd.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="copy Debug\FreeImagePlusd.lib dist\&#x0D;&#x0A;&#x0D;&#x0A;copy Debug\FreeImagePlusd.dll dist\&#x0D;&#x0A;&#x0D;&#x0A;copy FreeImagePlus.h dist\&#x0D;&#x0A;&#x0D;&#x0A;"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="src\fipImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMemoryIO.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMetadataFind.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipMultiPage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipTag.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\fipWinImage.cpp"
+ >
+ </File>
+ <File
+ RelativePath="src\FreeImagePlus.cpp"
+ >
+ </File>
+ <File
+ RelativePath="FreeImagePlus.rc"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="FreeImagePlus.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ </Filter>
+ <File
+ RelativePath="WhatsNew_FIP.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.h b/Wrapper/FreeImagePlus/FreeImagePlus.h
new file mode 100644
index 0000000..b6406c1
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.h
@@ -0,0 +1,1577 @@
+// ==========================================================
+// FreeImagePlus 3
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef FREEIMAGEPLUS_H
+#define FREEIMAGEPLUS_H
+
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+#include "FreeImage.h"
+
+
+// Compiler options ---------------------------------------------------------
+
+#if defined(FREEIMAGE_LIB)
+ #define FIP_API
+ #define FIP_CALLCONV
+#else
+ #if defined(_WIN32) || defined(__WIN32__)
+ #define WIN32_LEAN_AND_MEAN
+ #define FIP_CALLCONV __stdcall
+ // The following ifdef block is the standard way of creating macros which make exporting
+ // from a DLL simpler. All files within this DLL are compiled with the FIP_EXPORTS
+ // symbol defined on the command line. this symbol should not be defined on any project
+ // that uses this DLL. This way any other project whose source files include this file see
+ // FIP_API functions as being imported from a DLL, wheras this DLL sees symbols
+ // defined with this macro as being exported.
+ #ifdef FIP_EXPORTS
+ #define FIP_API __declspec(dllexport)
+ #else
+ #define FIP_API __declspec(dllimport)
+ #endif // FIP_EXPORTS
+ #else
+ // try the gcc visibility support (see http://gcc.gnu.org/wiki/Visibility)
+ #if defined(__GNUC__) && ((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ #ifndef GCC_HASCLASSVISIBILITY
+ #define GCC_HASCLASSVISIBILITY
+ #endif
+ #endif
+ #define FIP_CALLCONV
+ #if defined(GCC_HASCLASSVISIBILITY)
+ #define FIP_API __attribute__ ((visibility("default")))
+ #else
+ #define FIP_API
+ #endif
+ #endif // WIN32 / !WIN32
+#endif // FREEIMAGE_LIB
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------
+
+/** Abstract base class for all objects used by the library.
+ @version FreeImage 3
+ @author Hervé Drolon
+*/
+
+class FIP_API fipObject
+{
+public:
+ /// Destructor
+ virtual ~fipObject(){};
+
+ /**@name Information functions */
+ //@{
+ /// Returns TRUE if the object is allocated, FALSE otherwise
+ virtual BOOL isValid() const = 0;
+ //@}
+};
+
+// ----------------------------------------------------------
+
+class fipMemoryIO;
+class fipMultiPage;
+class fipTag;
+
+/** A class used to manage all photo related images and all image types used by the library.
+
+ fipImage encapsulates the FIBITMAP format. It relies on the FreeImage library, especially for
+ loading / saving images and for bit depth conversion.
+ @version FreeImage 3
+ @author Hervé Drolon
+*/
+
+class FIP_API fipImage : public fipObject
+{
+protected:
+ /// DIB data
+ FIBITMAP *_dib;
+ /// Original (or last saved) fif format if available, FIF_UNKNOWN otherwise
+ FREE_IMAGE_FORMAT _fif;
+ /// TRUE whenever the display need to be refreshed
+ mutable BOOL _bHasChanged;
+
+public:
+ friend class fipMultiPage;
+
+public:
+
+ /**@name Creation & Destruction */
+ //@{
+ /**
+ Constructor
+ @see FreeImage_AllocateT
+ */
+ fipImage(FREE_IMAGE_TYPE image_type = FIT_BITMAP, WORD width = 0, WORD height = 0, WORD bpp = 0);
+ /// Destructor
+ virtual ~fipImage();
+ /**
+ Image allocator
+ @see FreeImage_AllocateT
+ */
+ BOOL setSize(FREE_IMAGE_TYPE image_type, WORD width, WORD height, WORD bpp, unsigned red_mask = 0, unsigned green_mask = 0, unsigned blue_mask = 0);
+ /// Destroy image data
+ virtual void clear();
+ //@}
+
+ /**@name Copying */
+ //@{
+ /**
+ Copy constructor
+ @see FreeImage_Clone
+ */
+ fipImage(const fipImage& src);
+ /**
+ Copy constructor
+ @see FreeImage_Clone
+ */
+ fipImage& operator=(const fipImage& src);
+ /**
+ <b>Assignement operator</b><br>
+ Copy the input pointer and manage its destruction
+ @see operator FIBITMAP*()
+ */
+ fipImage& operator=(FIBITMAP *dib);
+
+
+ /**
+ @brief Copy a sub part of the current image and returns it as a fipImage object.
+
+ This method works with any bitmap type.
+ @param dst Output subimage
+ @param left Specifies the left position of the cropped rectangle.
+ @param top Specifies the top position of the cropped rectangle.
+ @param right Specifies the right position of the cropped rectangle.
+ @param bottom Specifies the bottom position of the cropped rectangle.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_Copy
+ */
+ BOOL copySubImage(fipImage& dst, int left, int top, int right, int bottom) const;
+
+ /**
+ @brief Alpha blend or combine a sub part image with the current image.
+
+ The bit depth of dst bitmap must be greater than or equal to the bit depth of src.
+ Upper promotion of src is done internally. Supported bit depth equals to 4, 8, 16, 24 or 32.
+ @param src Source subimage
+ @param left Specifies the left position of the sub image.
+ @param top Specifies the top position of the sub image.
+ @param alpha Alpha blend factor. The source and destination images are alpha blended if
+ alpha = 0..255. If alpha > 255, then the source image is combined to the destination image.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_Paste
+ */
+ BOOL pasteSubImage(fipImage& src, int left, int top, int alpha = 256);
+
+ /**
+ @brief Crop a sub part of the current image and update it accordingly.
+
+ This method works with any bitmap type.
+ @param left Specifies the left position of the cropped rectangle.
+ @param top Specifies the top position of the cropped rectangle.
+ @param right Specifies the right position of the cropped rectangle.
+ @param bottom Specifies the bottom position of the cropped rectangle.
+ @return Returns TRUE if successful, FALSE otherwise.
+ */
+ BOOL crop(int left, int top, int right, int bottom);
+
+ //@}
+
+ /** @name File type identification
+ */
+ //@{
+ /**
+ @brief Identifies an image from disk, given its file name
+ @param lpszPathName Path and file name of the image to identify.
+ @return Returns the found FreeImage format if successful, returns FIF_UNKNOWN otherwise.
+ @see FreeImage_GetFileType, FreeImage_GetFIFFromFilename, FreeImage documentation
+ */
+ static FREE_IMAGE_FORMAT identifyFIF(const char* lpszPathName);
+
+ /**
+ UNICODE version of identifyFIF (this function only works under WIN32 and does nothing on other OS)
+ @see FreeImage_GetFileTypeU, FreeImage_GetFIFFromFilenameU, FreeImage documentation
+ */
+ static FREE_IMAGE_FORMAT identifyFIFU(const wchar_t* lpszPathName);
+
+ /**
+ @brief Identifies an image using the specified FreeImageIO struct and fi_handle.
+ @param io FreeImageIO structure
+ @param handle FreeImage fi_handle
+ @return Returns the found FreeImage format if successful, returns FIF_UNKNOWN otherwise.
+ @see FreeImage_GetFileTypeFromHandle, FreeImage documentation
+ */
+ static FREE_IMAGE_FORMAT identifyFIFFromHandle(FreeImageIO *io, fi_handle handle);
+
+ /**
+ @brief Identifies an image using the specified memory stream.
+ @param hmem FreeImage memory stream
+ @return Returns the found FreeImage format if successful, returns FIF_UNKNOWN otherwise.
+ @see FreeImage_GetFileTypeFromMemory, FreeImage documentation
+ */
+ static FREE_IMAGE_FORMAT identifyFIFFromMemory(FIMEMORY *hmem);
+
+ //@}
+
+
+ /** @name Loading & Saving
+ * Loading and saving is handled by the FreeImage library.
+ */
+ //@{
+ /**
+ @brief Loads an image from disk, given its file name and an optional flag.
+ @param lpszPathName Path and file name of the image to load.
+ @param flag The signification of this flag depends on the image to be read.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_Load, FreeImage documentation
+ */
+ BOOL load(const char* lpszPathName, int flag = 0);
+
+ /**
+ UNICODE version of load (this function only works under WIN32 and does nothing on other OS)
+ @see load
+ */
+ BOOL loadU(const wchar_t* lpszPathName, int flag = 0);
+
+ /**
+ @brief Loads an image using the specified FreeImageIO struct and fi_handle, and an optional flag.
+ @param io FreeImageIO structure
+ @param handle FreeImage fi_handle
+ @param flag The signification of this flag depends on the image to be read.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_LoadFromHandle, FreeImage documentation
+ */
+ BOOL loadFromHandle(FreeImageIO *io, fi_handle handle, int flag = 0);
+
+ /**
+ @brief Loads an image using the specified memory stream and an optional flag.
+ @param memIO FreeImage memory stream
+ @param flag The signification of this flag depends on the image to be read.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_LoadFromMemory, FreeImage documentation
+ */
+ BOOL loadFromMemory(fipMemoryIO& memIO, int flag = 0);
+
+ /**
+ @brief Saves an image to disk, given its file name and an optional flag.
+ @param lpszPathName Path and file name of the image to save.
+ @param flag The signification of this flag depends on the image to be saved.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_Save, FreeImage documentation
+ */
+ BOOL save(const char* lpszPathName, int flag = 0) const;
+
+ /**
+ UNICODE version of save (this function only works under WIN32 and does nothing on other OS)
+ @see save
+ */
+ BOOL saveU(const wchar_t* lpszPathName, int flag = 0) const;
+
+ /**
+ @brief Saves an image using the specified FreeImageIO struct and fi_handle, and an optional flag.
+ @param fif Format identifier (FreeImage format)
+ @param io FreeImageIO structure
+ @param handle FreeImage fi_handle
+ @param flag The signification of this flag depends on the image to be saved.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_SaveToHandle, FreeImage documentation
+ */
+ BOOL saveToHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flag = 0) const;
+
+ /**
+ @brief Saves an image using the specified memory stream and an optional flag.
+ @param fif Format identifier (FreeImage format)
+ @param memIO FreeImage memory stream
+ @param flag The signification of this flag depends on the image to be saved.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_SaveToMemory, FreeImage documentation
+ */
+ BOOL saveToMemory(FREE_IMAGE_FORMAT fif, fipMemoryIO& memIO, int flag = 0) const;
+
+ //@}
+
+ /** @name Information functions
+ * Accessors to the DIB BITMAPINFO structure.
+ */
+ //@{
+
+ /**
+ Returns the data type of the image
+ @see FreeImage_GetImageType
+ */
+ FREE_IMAGE_TYPE getImageType() const;
+
+ /**
+ Returns the image width in pixels
+ @see FreeImage_GetWidth
+ */
+ WORD getWidth() const;
+
+ /**
+ Returns the image height in pixels
+ @see FreeImage_GetHeight
+ */
+ WORD getHeight() const;
+
+ /**
+ Returns the width of the bitmap in bytes rounded to the nearest DWORD.
+ @see FreeImage_GetPitch
+ */
+ WORD getScanWidth() const;
+
+ /**
+ Returns a pointer to the FIBITMAP data. Used for direct access from FREEIMAGE functions
+ or from your own low level C functions.<br>
+ <b>Sample use</b> : <br>
+ <pre>
+ fipImage src, dst;
+ src.load("test.png");
+ dst = FreeImage_ConvertTo8Bits(src);
+ FreeImage_Save(FIF_TIFF, dst, "test.tif", 0);
+ </pre>
+ @see operator=(FIBITMAP *dib)
+ */
+ operator FIBITMAP*() {
+ return _dib;
+ }
+
+ /// Returns TRUE if the image is allocated, FALSE otherwise
+ BOOL isValid() const;
+
+ /**
+ Returns a pointer to the bitmap's BITMAPINFO header.
+ @see FreeImage_GetInfo
+ */
+ BITMAPINFO* getInfo() const;
+
+ /**
+ Returns a pointer to the bitmap's BITMAPINFOHEADER.
+ @see FreeImage_GetInfoHeader
+ */
+ BITMAPINFOHEADER* getInfoHeader() const;
+
+ /**
+ Returns the size of the bitmap in bytes.
+ The size of the bitmap is the BITMAPINFOHEADER + the size of the palette + the size of the bitmap data.
+ @see FreeImage_GetDIBSize
+ */
+ LONG getImageSize() const;
+
+ /**
+ Returns the bitdepth of the bitmap. <br>
+ When the image type is FIT_BITMAP, valid bitdepth can be 1, 4, 8, 16, 24 or 32.
+ @see FreeImage_GetBPP, getImageType
+ */
+ WORD getBitsPerPixel() const;
+
+ /**
+ Returns the width of the bitmap in bytes.<br>
+ <b>This is not the size of the scanline</b>.
+ @see FreeImage_GetLine, getScanWidth
+ */
+ WORD getLine() const;
+
+ /**
+ Returns the bitmap resolution along the X axis, in pixels / cm
+ @see FreeImage_GetDotsPerMeterX
+ */
+ double getHorizontalResolution() const;
+
+ /**
+ Returns the bitmap resolution along the Y axis, in pixels / cm
+ @see FreeImage_GetDotsPerMeterY
+ */
+ double getVerticalResolution() const;
+
+ /**
+ set the bitmap resolution along the X axis, in pixels / cm
+ @see FreeImage_GetInfoHeader
+ */
+ void setHorizontalResolution(double value);
+
+ /**
+ set the bitmap resolution along the Y axis, in pixels / cm
+ @see FreeImage_GetInfoHeader
+ */
+ void setVerticalResolution(double value);
+
+ //@}
+
+ /**@name Palette operations */
+ //@{
+ /**
+ Returns a pointer to the bitmap's palette. If the bitmap doesn't have a palette, getPalette returns NULL.
+ @see FreeImage_GetPalette
+ */
+ RGBQUAD* getPalette() const;
+
+ /**
+ Returns the palette size in <b>bytes</b>.
+ @see FreeImage_GetColorsUsed
+ */
+ WORD getPaletteSize() const;
+
+ /**
+ Retrieves the number of colours used in the bitmap. If the bitmap is non-palletised, 0 is returned.
+ @see FreeImage_GetColorsUsed
+ */
+ WORD getColorsUsed() const;
+
+ /**
+ Investigates the colour type of the bitmap.
+ @see FreeImage_GetColorType, FREE_IMAGE_COLOR_TYPE
+ */
+ FREE_IMAGE_COLOR_TYPE getColorType() const;
+
+ /**
+ Returns TRUE if the bitmap is a 8-bit bitmap with a greyscale palette, FALSE otherwise
+ @see FreeImage_GetBPP, FreeImage_GetColorType
+ */
+ BOOL isGrayscale() const;
+ //@}
+
+ /**@name Pixel access */
+ //@{
+
+ /** @brief Returns a pointer to the bitmap bits.
+
+ It is up to you to interpret these bytes correctly,
+ according to the results of FreeImage_GetBPP and
+ GetRedMask, FreeImage_GetGreenMask and FreeImage_GetBlueMask.<br>
+ Use this function with getScanWidth to iterates through the pixels.
+ @see FreeImage_GetBits
+ */
+ BYTE* accessPixels() const;
+
+ /** @brief Returns a pointer to the start of the given scanline in the bitmap’s data-bits.
+ This pointer can be cast according to the result returned by getImageType.<br>
+ Use this function with getScanWidth to iterates through the pixels.
+ @see FreeImage_GetScanLine, FreeImage documentation
+ */
+ BYTE* getScanLine(WORD scanline) const;
+
+ /**
+ Get the pixel index of a 1-, 4- or 8-bit palettized image at position (x, y), including range check (slow access).
+ @param x Pixel position in horizontal direction
+ @param y Pixel position in vertical direction
+ @param value Pixel index (returned value)
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_GetPixelIndex
+ */
+ BOOL getPixelIndex(unsigned x, unsigned y, BYTE *value) const;
+
+ /**
+ Get the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ @param x Pixel position in horizontal direction
+ @param y Pixel position in vertical direction
+ @param value Pixel color (returned value)
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_GetPixelColor
+ */
+ BOOL getPixelColor(unsigned x, unsigned y, RGBQUAD *value) const;
+
+ /**
+ Set the pixel index of a 1-, 4- or 8-bit palettized image at position (x, y), including range check (slow access).
+ @param x Pixel position in horizontal direction
+ @param y Pixel position in vertical direction
+ @param value Pixel index
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_SetPixelIndex
+ */
+ BOOL setPixelIndex(unsigned x, unsigned y, BYTE *value);
+
+ /**
+ Set the pixel color of a 16-, 24- or 32-bit image at position (x, y), including range check (slow access).
+ @param x Pixel position in horizontal direction
+ @param y Pixel position in vertical direction
+ @param value Pixel color
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_SetPixelColor
+ */
+ BOOL setPixelColor(unsigned x, unsigned y, RGBQUAD *value);
+
+ //@}
+
+ /** @name Conversion routines
+ * Bitmaps are always loaded in their default bit depth. If you want the bitmap to be stored in another bit depth, the class provides several conversion functions.
+ */
+ //@{
+ /**
+ Converts an image to a type supported by FreeImage.
+ @param image_type New image type
+ @param scale_linear TRUE if image pixels must be scaled linearly when converting to a standard bitmap
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertToType, FreeImage_ConvertToStandardType
+ */
+ BOOL convertToType(FREE_IMAGE_TYPE image_type, BOOL scale_linear = TRUE);
+
+ /**
+ Converts the bitmap to 1 bit using a threshold T.
+ @param T Threshold value in [0..255]
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_Threshold
+ */
+ BOOL threshold(BYTE T);
+
+ /**
+ Converts a 8-bit image to a monochrome 1-bit image using a dithering algorithm.
+ @param algorithm Dithering algorithm to use.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_Dither, FREE_IMAGE_DITHER
+ */
+ BOOL dither(FREE_IMAGE_DITHER algorithm);
+
+ /**
+ Converts the bitmap to 4 bits. Unless the bitmap is a 1-bit palettized bitmap, colour values are converted to greyscale.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo4Bits
+ */
+ BOOL convertTo4Bits();
+
+ /**
+ Converts the bitmap to 8 bits. If the bitmap is 24 or 32-bit RGB, the colour values are converted to greyscale.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo8Bits
+ */
+ BOOL convertTo8Bits();
+
+ /**
+ Converts the bitmap to 8 bits.<br>
+ For palletized bitmaps, the color map is converted to a greyscale ramp.
+ @see FreeImage_ConvertToGreyscale
+ @return Returns TRUE if successfull, FALSE otherwise.
+ */
+ BOOL convertToGrayscale();
+
+ /**
+ Quantizes a full colour 24-bit bitmap to a palletised 8-bit bitmap.<br>
+ The quantize parameter specifies which colour reduction algorithm should be used.
+ @param algorithm Color quantization algorithm to use.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ColorQuantize, FREE_IMAGE_QUANTIZE
+ */
+ BOOL colorQuantize(FREE_IMAGE_QUANTIZE algorithm);
+
+ /**
+ Converts the bitmap to 16 bits. The resulting bitmap has a layout of 5 bits red, 5 bits green, 5 bits blue and 1 unused bit.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo16Bits555
+ */
+ BOOL convertTo16Bits555();
+
+ /**
+ Converts the bitmap to 16 bits. The resulting bitmap has a layout of 5 bits red, 6 bits green and 5 bits blue.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo16Bits565
+ */
+ BOOL convertTo16Bits565();
+
+ /**
+ Converts the bitmap to 24 bits.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo24Bits
+ */
+ BOOL convertTo24Bits();
+
+ /**
+ Converts the bitmap to 32 bits.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertTo32Bits
+ */
+ BOOL convertTo32Bits();
+
+ /**
+ Converts the bitmap to a 96-bit RGBF image.
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ConvertToRGBF
+ */
+ BOOL convertToRGBF();
+
+ /**
+ Converts a High Dynamic Range image (48-bit RGB or 96-bit RGB Float) to a 24-bit RGB image.
+ @param tmo Tone mapping operator
+ @param first_param First tone mapping algorithm parameter (algorithm dependant)
+ @param second_param Second tone mapping algorithm parameter (algorithm dependant)
+ @param third_param Third tone mapping algorithm parameter (algorithm dependant)
+ @param fourth_param Fourth tone mapping algorithm parameter (algorithm dependant)
+ @return Returns TRUE if successfull, FALSE otherwise.
+ @see FreeImage_ToneMapping, FreeImage_TmoReinhard05Ex
+ */
+ BOOL toneMapping(FREE_IMAGE_TMO tmo, double first_param = 0, double second_param = 0, double third_param = 1, double fourth_param = 0);
+
+ //@}
+
+ /** @name Transparency support: background colour and alpha channel */
+ //@{
+
+ /**
+ Returns TRUE if the image is transparent, returns FALSE otherwise
+ @see FreeImage_IsTransparent
+ */
+ BOOL isTransparent() const;
+
+ /**
+ 8-bit transparency : get the number of transparent colors.
+ @return Returns the number of transparent colors in a palletised bitmap.
+ @see FreeImage_GetTransparencyCount
+ */
+ unsigned getTransparencyCount() const;
+
+ /**
+ 8-bit transparency : get the bitmap’s transparency table.
+ @return Returns a pointer to the bitmap’s transparency table.
+ @see FreeImage_GetTransparencyTable
+ */
+ BYTE* getTransparencyTable() const;
+
+ /**
+ 8-bit transparency : set the bitmap’s transparency table.
+ @see FreeImage_SetTransparencyTable
+ */
+ void setTransparencyTable(BYTE *table, int count);
+
+ /**
+ Returns TRUE when the image has a file background color, FALSE otherwise.
+ @see FreeImage_HasBackgroundColor
+ */
+ BOOL hasFileBkColor() const;
+
+ /**
+ @brief Retrieves the file background color of an image.
+
+ For 8-bit images, the color index
+ in the palette is returned in the rgbReserved member of the bkcolor parameter.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_GetBackgroundColor
+ */
+ BOOL getFileBkColor(RGBQUAD *bkcolor) const;
+
+ /**
+ @brief Set the file background color of an image.
+
+ When saving an image to PNG, this background color is transparently saved to the PNG file.
+ When the bkcolor parameter is NULL, the background color is removed from the image.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_SetBackgroundColor
+ */
+ BOOL setFileBkColor(RGBQUAD *bkcolor);
+ //@}
+
+ /**@name Channel processing support */
+ //@{
+ /** @brief Retrieves the red, green, blue or alpha channel of a 24- or 32-bit BGR[A] image.
+ @param image Output image to be extracted
+ @param channel Color channel to extract
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_GetChannel, FREE_IMAGE_COLOR_CHANNEL
+ */
+ BOOL getChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) const;
+
+ /**
+ @brief Insert a 8-bit dib into a 24- or 32-bit image.
+ @param image Input 8-bit image to insert
+ @param channel Color channel to replace
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_SetChannel, FREE_IMAGE_COLOR_CHANNEL
+ */
+ BOOL setChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /** @brief Split a 24-bit RGB image into 3 greyscale images corresponding to the red, green and blue channels.
+ @param RedChannel Output red channel.
+ @param GreenChannel Output green channel.
+ @param BlueChannel Output blue channel.
+ @return Returns FALSE if the dib isn't a valid image, if it's not a 24-bit image or if
+ one of the output channel can't be allocated. Returns TRUE otherwise.
+ @see FreeImage_GetChannel
+ */
+ BOOL splitChannels(fipImage& RedChannel, fipImage& GreenChannel, fipImage& BlueChannel);
+
+ /** @brief Builds a 24-bit RGB image given its red, green and blue channel.
+ @param red Input red channel.
+ @param green Input green channel.
+ @param blue Input blue channel.
+ @return Returns FALSE if the dib can't be allocated, if the input channels are not 8-bit images. Returns TRUE otherwise.
+ @see FreeImage_SetChannel
+ */
+ BOOL combineChannels(fipImage& red, fipImage& green, fipImage& blue);
+ //@}
+
+ /**@name Rotation and flipping */
+ //@{
+ /**
+ Image translation and rotation using B-Splines.
+ @param angle Image rotation angle, in degree
+ @param x_shift Image horizontal shift
+ @param y_shift Image vertical shift
+ @param x_origin Origin of the x-axis
+ @param y_origin Origin of the y-axis
+ @param use_mask Whether or not to mask the image. Image mirroring is applied when use_mask is set to FALSE
+ @return Returns the translated & rotated dib if successful, returns NULL otherwise
+ @see FreeImage_RotateEx
+ */
+ BOOL rotateEx(double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask);
+
+ /**
+ Image rotation by means of three shears.
+ @param angle Image rotation angle, in degree
+ @param bkcolor Background color (image type dependent), default to black background
+ @return Returns rotated dib if successful, returns NULL otherwise
+ @see FreeImage_Rotate
+ */
+ BOOL rotate(double angle, const void *bkcolor = NULL);
+
+ /**
+ Flip the image horizontally along the vertical axis
+ @see FreeImage_FlipHorizontal
+ */
+ BOOL flipHorizontal();
+
+ /**
+ Flip the image vertically along the horizontal axis
+ @see FreeImage_FlipVertical
+ */
+ BOOL flipVertical();
+ //@}
+
+ /**@name Color manipulation routines */
+ //@{
+ /**
+ Inverts each pixel data.
+ @return Returns TRUE if successful, FALSE otherwise.
+ @see FreeImage_Invert
+ */
+ BOOL invert();
+
+ /** @brief Perfoms an histogram transformation on a 8, 24 or 32-bit image
+ according to the values of a lookup table (LUT).
+
+ The transformation is done as follows.<br>
+ Image 8-bit : if the image has a color palette, the LUT is applied to this palette,
+ otherwise, it is applied to the grey values.<br>
+ Image 24-bit & 32-bit : if channel == IPL_CC_RGB, the same LUT is applied to each color
+ plane (R,G, and B). Otherwise, the LUT is applied to the specified channel only.
+ @param LUT Lookup table. <b>The size of 'LUT' is assumed to be 256.</b>
+ @param channel The color channel to be processed (only used with 24 & 32-bit DIB).
+ @return Returns TRUE if the operation was successful, FALSE otherwise
+ @see FreeImage_AdjustCurve, FREE_IMAGE_COLOR_CHANNEL
+ */
+ BOOL adjustCurve(BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel);
+
+ /** @brief Performs gamma correction on a 8, 24 or 32-bit image.
+ @param gamma Gamma value to use. A value of 1.0 leaves the image alone,
+ less than one darkens it, and greater than one lightens it.
+ @return Returns TRUE if the operation was successful, FALSE otherwise
+ @see FreeImage_AdjustGamma, adjustCurve
+ */
+ BOOL adjustGamma(double gamma);
+
+ /** @brief Adjusts the brightness of a 8, 24 or 32-bit image by a certain amount.
+ @param percentage Where -100 <= percentage <= 100<br>
+ A value 0 means no change, less than 0 will make the image darker
+ and greater than 0 will make the image brighter.
+ @return Returns TRUE if the operation was succesful, FALSE otherwise
+ @see FreeImage_AdjustBrightness, adjustCurve
+ */
+ BOOL adjustBrightness(double percentage);
+
+ /** @brief Adjusts the contrast of a 8, 24 or 32-bit image by a certain amount.
+ @param percentage Where -100 <= percentage <= 100<br>
+ A value 0 means no change, less than 0 will decrease the contrast
+ and greater than 0 will increase the contrast of the image.
+ @return Returns TRUE if the operation was succesfull, FALSE otherwise
+ @see FreeImage_AdjustContrast, adjustCurve
+ */
+ BOOL adjustContrast(double percentage);
+
+ /**
+ Adjusts an image's brightness, contrast and gamma within a single operation.
+ If more than one of these image display properties need to be adjusted,
+ using this function should be preferred over calling each adjustment function separately.
+ That's particularly true for huge images or if performance is an issue.
+ @see adjustBrightness
+ @see adjustContrast
+ @see adjustGamma
+ @see FreeImage_AdjustColors
+ */
+ BOOL adjustBrightnessContrastGamma(double brightness, double contrast, double gamma);
+
+ /** @brief Computes image histogram
+
+ For 24-bit and 32-bit images, histogram can be computed from red, green, blue and
+ black channels. For 8-bit images, histogram is computed from the black channel. Other
+ bit depth is not supported.
+ @param histo pointer to an histogram array. <b>Size of this array is assumed to be 256</b>.
+ @param channel Color channel to use
+ @return Returns TRUE if the operation was succesfull, FALSE otherwise
+ @see FreeImage_GetHistogram
+ */
+ BOOL getHistogram(DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel = FICC_BLACK) const;
+ //@}
+
+ /**@name Upsampling / downsampling */
+ //@{
+
+ /** @brief Rescale the image to a new width / height.
+
+ @param new_width New image width
+ @param new_height New image height
+ @param filter The filter parameter specifies which resampling filter should be used.
+ @return Returns TRUE if the operation was successful, FALSE otherwise
+ @see FreeImage_Rescale, FREE_IMAGE_FILTER
+ */
+ BOOL rescale(WORD new_width, WORD new_height, FREE_IMAGE_FILTER filter);
+
+ /** @brief Creates a thumbnail image keeping aspect ratio
+
+ @param max_size Maximum width or height in pixel units
+ @param convert When set to TRUE, converts the image to a standard type
+ @return Returns TRUE if the operation was successful, FALSE otherwise
+ @see FreeImage_MakeThumbnail
+ */
+ BOOL makeThumbnail(WORD max_size, BOOL convert = TRUE);
+ //@}
+
+ /**@name Image status */
+ //@{
+ /**
+ Set the image status as 'modified'.<br>
+ When using the fipWinImage class, the image status is used to refresh the display.
+ It is changed to FALSE whenever the display has just been refreshed.
+ @param bStatus TRUE if the image should be marked as modified, FALSE otherwise
+ @see isModified
+ */
+ void setModified(BOOL bStatus = TRUE) {
+ _bHasChanged = bStatus;
+ }
+
+ /**
+ Get the image status
+ @return Returns TRUE if the image is marked as modified, FALSE otherwise
+ @see setModified
+ */
+ BOOL isModified() {
+ return _bHasChanged;
+ }
+ //@}
+
+ /**@name Metadata */
+ //@{
+ /**
+ Returns the number of tags contained in the <i>model</i> metadata model
+ attached to the dib
+ @param model Metadata model to look for
+ */
+ unsigned getMetadataCount(FREE_IMAGE_MDMODEL model) const;
+ /**
+ Retrieve a metadata attached to the dib
+ @param model Metadata model to look for
+ @param key Metadata field name
+ @param tag Returned tag
+ @return Returns TRUE if the operation was succesfull, FALSE otherwise
+ @see FreeImage_GetMetadata
+ */
+ BOOL getMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag) const;
+ /**
+ Attach a new FreeImage tag to the dib.<br>
+ <b>Sample use</b> : <br>
+ <pre>
+ fipImage image;
+ // ...
+ fipTag tag;
+ tag.setKeyValue("Caption/Abstract", "my caption");
+ image.setMetadata(FIMD_IPTC, tag.getKey(), tag);
+ tag.setKeyValue("Keywords", "FreeImage;Library;Images;Compression");
+ image.setMetadata(FIMD_IPTC, tag.getKey(), tag);
+ </pre>
+
+ @param model Metadata model used to store the tag
+ @param key Tag field name
+ @param tag Tag to be attached
+ @return Returns TRUE if the operation was succesfull, FALSE otherwise
+ @see FreeImage_SetMetadata
+ */
+ BOOL setMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag);
+ //@}
+
+
+ protected:
+ /**@name Internal use */
+ //@{
+ BOOL replace(FIBITMAP *new_dib);
+ //@}
+
+};
+
+// ----------------------------------------------------------
+
+/** A class designed for MS Windows (TM) platforms.
+
+ fipWinImage provides methods used to :
+ <ul>
+ <li>Display a DIB on the screen
+ <li>Copy / Paste a DIB to/from Windows devices (HANDLE, HBITMAP, Clipboard)
+ <li>Capture a window (HWND) and convert it to an image
+ </ul>
+ @version FreeImage 3
+ @author Hervé Drolon
+*/
+#ifdef _WIN32
+
+class FIP_API fipWinImage : public fipImage
+{
+public:
+ /**@name Creation & Destruction */
+ //@{
+ /// Constructor
+ fipWinImage(FREE_IMAGE_TYPE image_type = FIT_BITMAP, WORD width = 0, WORD height = 0, WORD bpp = 0);
+
+ /// Destructor
+ virtual ~fipWinImage();
+
+ /// Destroy image data
+ virtual void clear();
+
+ /// Returns TRUE if the image is allocated, FALSE otherwise
+ BOOL isValid() const;
+ //@}
+
+ /**@name Copying */
+ //@{
+
+ /**
+ Copy constructor.
+ Delete internal _display_dib data and copy the base class image data.
+ Tone mapping parameters are left unchanged.
+ @see FreeImage_Clone
+ */
+ fipWinImage& operator=(const fipImage& src);
+
+ /**
+ Copy constructor
+ Delete internal _display_dib data and copy tone mapping parameters.
+ Copy also the base class image data.
+ @see FreeImage_Clone
+ */
+ fipWinImage& operator=(const fipWinImage& src);
+
+ /** Clone function used for clipboard copy.<br>
+ Convert the FIBITMAP image to a DIB,
+ and transfer the DIB in a global bitmap handle.<br>
+ For non standard bitmaps, the BITMAPINFOHEADER->biCompression field is set to 0xFF + FreeImage_GetImageType(_dib),
+ in order to recognize the bitmap as non standard.
+ */
+ HANDLE copyToHandle() const;
+
+ /** Copy constructor used for clipboard paste.<br>
+ Converts a global object to a FIBITMAP. The clipboard format must be CF_DIB.<br>
+ When the BITMAPINFOHEADER->biCompression field is set to 0xFF + [one of the predefined FREE_IMAGE_TYPE],
+ the bitmap is recognized as non standard and correctly copied.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL copyFromHandle(HANDLE hMem);
+
+ /** Copy constructor.<br>
+ Converts a HBITMAP object to a FIBITMAP.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL copyFromBitmap(HBITMAP hbmp);
+ //@}
+
+ /**@name Clipboard operations */
+ //@{
+ /**
+ Clipboard copy.
+ @param hWndNewOwner Handle to the window to be associated with the open clipboard.
+ In MFC, you can use AfxGetApp()->m_pMainWnd->GetSafeHwnd().
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL copyToClipboard(HWND hWndNewOwner) const;
+
+ /**
+ Retrieves data from the clipboard. The clipboard format must be CF_DIB.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL pasteFromClipboard();
+ //@}
+
+ /**@name Screen capture */
+ //@{
+ /** Capture a window and convert it to an image
+ @param hWndApplicationWindow Handle to the application main window
+ @param hWndSelectedWindow Handle to the window to be captured
+ @return Returns TRUE if successful, returns FALSE otherwise
+ */
+ BOOL captureWindow(HWND hWndApplicationWindow, HWND hWndSelectedWindow);
+ //@}
+
+
+ /**@name Painting operations */
+ //@{
+
+ /** @brief Draw (stretch) the image on a HDC, using StretchDIBits.
+
+ When the image is transparent or has a file background, this function composite
+ the foreground image against a checkerboard background image.
+ @param hDC Handle to the device context
+ @param rcDest Destination rectangle
+ @see FreeImage_Composite
+ */
+ void draw(HDC hDC, RECT& rcDest) const {
+ drawEx(hDC, rcDest, FALSE, NULL, NULL);
+ }
+
+ /** @brief Draw (stretch) the image on a HDC, using StretchDIBits.
+
+ When the image is transparent or has a file background, this function can composite
+ the foreground image against a checkerboard background image, against a single background color or
+ against a user background image.<br>
+ When the image is a High Dynamic Range image (48-bit or RGB float), this function will apply a
+ tone mapping operator before drawing the image.<br>
+ The original image (located in the fipImage class) will not be affected by any of the operations
+ that could be done in order to display it.
+ @param hDC Handle to the device context
+ @param rcDest Destination rectangle
+ @param useFileBkg When set to TRUE, the function uses the file color background if there is one
+ @param appBkColor When a color is given, the function uses it as the background color
+ @param bg When a FIBITMAP is given, the function uses it as the background image
+ @see FreeImage_Composite
+ @see setToneMappingOperator
+ */
+ void drawEx(HDC hDC, RECT& rcDest, BOOL useFileBkg = FALSE, RGBQUAD *appBkColor = NULL, FIBITMAP *bg = NULL) const;
+
+ /**
+ Select a tone mapping algorithm used for drawing and set the image as modified
+ so that the display will be refreshed.
+ @param tmo Tone mapping operator
+ @param first_param First tone mapping algorithm parameter
+ @param second_param Second tone mapping algorithm parameter
+ @param third_param Third tone mapping algorithm parameter
+ @param fourth_param Fourth tone mapping algorithm parameter
+ @see FreeImage_ToneMapping
+ */
+ void setToneMappingOperator(FREE_IMAGE_TMO tmo, double first_param = 0, double second_param = 0, double third_param = 1, double fourth_param = 0);
+
+ /**
+ Get the tone mapping algorithm used for drawing, with its parameters.
+ @param tmo Tone mapping operator
+ @param first_param First tone mapping algorithm parameter
+ @param second_param Second tone mapping algorithm parameter
+ @param third_param Third tone mapping algorithm parameter
+ @param fourth_param Fourth tone mapping algorithm parameter
+ @see FreeImage_ToneMapping
+ */
+ void getToneMappingOperator(FREE_IMAGE_TMO *tmo, double *first_param, double *second_param, double *third_param, double *fourth_param) const;
+
+ //@}
+
+protected:
+ /// DIB used for display (this allow to display non-standard bitmaps)
+ mutable FIBITMAP *_display_dib;
+ /// remember to delete _display_dib
+ mutable BOOL _bDeleteMe;
+ /// tone mapping operator
+ FREE_IMAGE_TMO _tmo;
+ /// first tone mapping algorithm parameter
+ double _tmo_param_1;
+ /// second tone mapping algorithm parameter
+ double _tmo_param_2;
+ /// third tone mapping algorithm parameter
+ double _tmo_param_3;
+ /// fourth tone mapping algorithm parameter
+ double _tmo_param_4;
+};
+
+#endif // _WIN32
+
+// ----------------------------------------------------------
+
+/** Memory handle
+
+ fipMemoryIO is a class that allows you to load / save images from / to a memory stream.
+ @version FreeImage 3
+ @author Hervé Drolon
+*/
+class FIP_API fipMemoryIO : public fipObject
+{
+protected:
+ /// Pointer to a memory stream
+ FIMEMORY *_hmem;
+
+public :
+ /** Constructor.
+ Wrap a memory buffer containing image data.<br>
+ The memory buffer is read only and has to be freed by the user
+ when no longer in use.<br>
+ When default arguments are used, open a memory file as read/write.
+ @param data Pointer to the memory buffer
+ @param size_in_bytes Buffer size in bytes
+ @see FreeImage_OpenMemory
+ */
+ fipMemoryIO(BYTE *data = NULL, DWORD size_in_bytes = 0);
+
+ /** Destructor.
+ Free any allocated memory
+ @see FreeImage_CloseMemory
+ */
+ virtual ~fipMemoryIO();
+
+ /** Returns TRUE if the internal memory buffer is a valid buffer, returns FALSE otherwise
+ */
+ BOOL isValid() const;
+
+ /** Returns the buffer image format
+ @see FreeImage_GetFileTypeFromMemory
+ */
+ FREE_IMAGE_FORMAT getFileType() const;
+
+ /**
+ Returns a pointer to the FIMEMORY data. Used for direct access from FREEIMAGE functions
+ or from your own low level C functions.
+ */
+ operator FIMEMORY*() {
+ return _hmem;
+ }
+
+ /**@name Memory IO routines */
+ //@{
+ /**
+ Loads a dib from a memory stream
+ @param fif Format identifier (FreeImage format)
+ @param flags The signification of this flag depends on the image to be loaded.
+ @return Returns the loaded dib if successful, returns NULL otherwise
+ @see FreeImage_LoadFromMemory
+ */
+ FIBITMAP* load(FREE_IMAGE_FORMAT fif, int flags = 0) const;
+ /**
+ Saves a dib to a memory stream
+ @param fif Format identifier (FreeImage format)
+ @param dib Image to be saved
+ @param flags The signification of this flag depends on the image to be saved.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SaveToMemory
+ */
+ BOOL save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, int flags = 0);
+ /**
+ Reads data from a memory stream
+ @param buffer Storage location for data
+ @param size Item size in bytes
+ @param count Maximum number of items to be read
+ @return Returns the number of full items actually read, which may be less than count if an error occurs
+ @see FreeImage_ReadMemory
+ */
+ unsigned read(void *buffer, unsigned size, unsigned count) const;
+ /**
+ Writes data to a memory stream
+ @param buffer Pointer to data to be written
+ @param size Item size in bytes
+ @param count Maximum number of items to be written
+ @return Returns the number of full items actually written, which may be less than count if an error occurs
+ @see FreeImage_WriteMemory
+ */
+ unsigned write(const void *buffer, unsigned size, unsigned count);
+ /**
+ Gets the current position of a memory pointer
+ @see FreeImage_TellMemory
+ */
+ long tell() const;
+ /**
+ Moves the memory pointer to a specified location
+ @see FreeImage_SeekMemory
+ */
+ BOOL seek(long offset, int origin);
+ /**
+ Provides a direct buffer access to a memory stream
+ @param data Pointer to the memory buffer (returned value)
+ @param size_in_bytes Buffer size in bytes (returned value)
+ @see FreeImage_AcquireMemory
+ */
+ BOOL acquire(BYTE **data, DWORD *size_in_bytes);
+ //@}
+
+private:
+ /// Disable copy
+ fipMemoryIO(const fipMemoryIO& src);
+ /// Disable copy
+ fipMemoryIO& operator=(const fipMemoryIO& src);
+
+};
+
+// ----------------------------------------------------------
+
+/** Multi-page file stream
+
+ fipMultiPage encapsulates the multi-page API. It supports reading/writing
+ multi-page TIFF, ICO and GIF files.
+*/
+class FIP_API fipMultiPage : public fipObject
+{
+protected:
+ /// Pointer to a multi-page file stream
+ FIMULTIBITMAP *_mpage;
+ /// TRUE when using a memory cache, FALSE otherwise
+ BOOL _bMemoryCache;
+
+public:
+ /**
+ Constructor
+ @param keep_cache_in_memory When it is TRUE, all gathered bitmap data in the page manipulation process is kept in memory, otherwise it is lazily flushed to a temporary file on the hard disk in 64 Kb blocks.
+ */
+ fipMultiPage(BOOL keep_cache_in_memory = FALSE);
+
+ /**
+ Destructor
+ Close the file stream if not already done.
+ */
+ virtual ~fipMultiPage();
+
+ /// Returns TRUE if the multi-page stream is opened
+ BOOL isValid() const;
+
+ /**
+ Open a file stream
+ @param lpszPathName Name of the multi-page bitmap file
+ @param create_new When TRUE, it means that a new bitmap will be created rather than an existing one being opened
+ @param read_only When TRUE the bitmap is opened read-only
+ @param flags Load flags. The signification of this flag depends on the image to be loaded.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_OpenMultiBitmap
+ */
+ BOOL open(const char* lpszPathName, BOOL create_new, BOOL read_only, int flags = 0);
+
+ /**
+ Open a multi-page memory stream as read only.
+ @param memIO Memory stream. The memory stream MUST BE a wrapped user buffer.
+ @param flags Load flags. The signification of this flag depends on the image to be loaded.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_LoadMultiBitmapFromMemory
+ */
+ BOOL open(fipMemoryIO& memIO, int flags = 0);
+
+ /**
+ Close a file stream
+ @param flags Save flags. The signification of this flag depends on the image to be saved.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_CloseMultiBitmap
+ */
+ BOOL close(int flags = 0);
+
+ /**
+ Returns the number of pages currently available in the multi-paged bitmap
+ @see FreeImage_GetPageCount
+ */
+ int getPageCount() const;
+
+ /**
+ Appends a new page to the end of the bitmap
+ @param image Image to append
+ @see FreeImage_AppendPage
+ */
+ void appendPage(fipImage& image);
+
+ /**
+ Inserts a new page before the given position in the bitmap
+ @param page Page number. Page has to be a number smaller than the current number of pages available in the bitmap.
+ @param image Image to insert
+ @see FreeImage_InsertPage
+ */
+ void insertPage(int page, fipImage& image);
+
+ /**
+ Deletes the page on the given position
+ @param page Page number
+ @see FreeImage_DeletePage
+ */
+ void deletePage(int page);
+
+ /**
+ Moves the source page to the position of the target page.
+ @param target Target page position
+ @param source Source page position
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_MovePage
+ */
+ BOOL movePage(int target, int source);
+
+ /**
+ Locks a page in memory for editing. You must call unlockPage to free the page<br>
+ <b>Usage : </b><br>
+ <pre>
+ fipMultiPage mpage;
+ // ...
+ fipImage image; // You must declare this before
+ image = mpage.lockPage(2);
+ if(image.isValid()) {
+ // ...
+ mpage.unlockPage(image, TRUE);
+ }
+ </pre>
+ @param page Page number
+ @return Returns the page if successful, returns NULL otherwise
+ @see FreeImage_LockPage
+ */
+ FIBITMAP* lockPage(int page);
+
+ /**
+ Unlocks a previously locked page and gives it back to the multi-page engine
+ @param image Page to unlock
+ @param changed When TRUE, the page is marked changed and the new page data is applied in the multi-page bitmap.
+ @see FreeImage_UnlockPage
+ */
+ void unlockPage(fipImage& image, BOOL changed);
+
+ /**
+ Returns an array of page-numbers that are currently locked in memory.
+ When the pages parameter is NULL, the size of the array is returned in the count variable.
+ You can then allocate the array of the desired size and call
+ getLockedPageNumbers again to populate the array.
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_GetLockedPageNumbers
+ */
+ BOOL getLockedPageNumbers(int *pages, int *count) const;
+};
+
+// ----------------------------------------------------------
+
+/**
+FreeImage Tag
+
+FreeImage uses this structure to store metadata information.
+*/
+class FIP_API fipTag : public fipObject
+{
+protected:
+ /// Pointer to a FreeImage tag
+ FITAG *_tag;
+
+public:
+ /**@name Creation & Destruction */
+ //@{
+ /**
+ Constructor
+ @see FreeImage_CreateTag
+ */
+ fipTag();
+ /**
+ Destructor
+ @see FreeImage_DeleteTag
+ */
+ virtual ~fipTag();
+ /**
+ Construct a FIDT_ASCII tag (ASCII string).<br>
+ This method is useful to store comments or IPTC tags.
+ @param name Field name
+ @param value Field value
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_CreateTag
+ */
+ BOOL setKeyValue(const char *key, const char *value);
+
+ //@}
+
+ /**@name Copying */
+ //@{
+ /**
+ Copy constructor
+ @see FreeImage_CloneTag
+ */
+ fipTag(const fipTag& tag);
+ /**
+ Copy constructor
+ @see FreeImage_CloneTag
+ */
+ fipTag& operator=(const fipTag& tag);
+ /**
+ <b>Assignement operator</b><br>
+ Copy the input pointer and manage its destruction
+ @see operator FITAG*()
+ */
+ fipTag& operator=(FITAG *tag);
+ //@}
+
+ /**
+ Returns a pointer to the FITAG data. Used for direct access from FREEIMAGE functions
+ or from your own low level C functions.
+ @see operator=(FITAG *tag)
+ */
+ operator FITAG*() {
+ return _tag;
+ }
+
+ /// Returns TRUE if the tag is allocated, FALSE otherwise
+ BOOL isValid() const;
+
+ /**@name Tag accessors */
+ //@{
+ /**
+ Returns the tag field name (unique inside a metadata model).
+ @see FreeImage_GetTagKey
+ */
+ const char *getKey() const;
+ /**
+ Returns the tag description if available, returns NULL otherwise
+ @see FreeImage_GetTagDescription
+ */
+ const char *getDescription() const;
+ /**
+ Returns the tag ID if available, returns 0 otherwise
+ @see FreeImage_GetTagID
+ */
+ WORD getID() const;
+ /**
+ Returns the tag data type
+ @see FreeImage_GetTagType
+ */
+ FREE_IMAGE_MDTYPE getType() const;
+ /**
+ Returns the number of components in the tag (in tag type units)
+ @see FreeImage_GetTagCount
+ */
+ DWORD getCount() const;
+ /**
+ Returns the length of the tag value in bytes
+ @see FreeImage_GetTagLength
+ */
+ DWORD getLength() const;
+ /**
+ Returns the tag value
+ @see FreeImage_GetTagValue
+ */
+ const void *getValue() const;
+ /**
+ Set the tag field name
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagKey
+ */
+ BOOL setKey(const char *key);
+ /**
+ Set the (usually optional) tag description
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagDescription
+ */
+ BOOL setDescription(const char *description);
+ /**
+ Set the (usually optional) tad ID
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagID
+ */
+ BOOL setID(WORD id);
+ /**
+ Set the tag data type
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagType
+ */
+ BOOL setType(FREE_IMAGE_MDTYPE type);
+ /**
+ Set the number of data in the tag
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagCount
+ */
+ BOOL setCount(DWORD count);
+ /**
+ Set the length of the tag value, in bytes
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagLength
+ */
+ BOOL setLength(DWORD length);
+ /**
+ Set the tag value
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_SetTagValue
+ */
+ BOOL setValue(const void *value);
+
+ //@}
+
+ /**
+ Converts a FreeImage tag structure to a string that represents the interpreted tag value
+ @param model Metadata model specification (metadata model from which the tag was extracted)
+ @param Make Camera model (not used yet)
+ */
+ const char* toString(FREE_IMAGE_MDMODEL model, char *Make = NULL) const;
+
+};
+
+/**
+Metadata iterator
+
+<b>Usage : </b><br>
+<pre>
+fipImage image;
+// ...
+fipTag tag;
+fipMetadataFind finder;
+if( finder.findFirstMetadata(FIMD_EXIF_MAIN, image, tag) ) {
+ do {
+ // process the tag
+ cout << tag.getKey() << "\n";
+
+ } while( finder.findNextMetadata(tag) );
+}
+// the class can be called again with another metadata model
+if( finder.findFirstMetadata(FIMD_EXIF_EXIF, image, tag) ) {
+ do {
+ // process the tag
+ cout << tag.getKey() << "\n";
+
+ } while( finder.findNextMetadata(tag) );
+}
+</pre>
+*/
+class FIP_API fipMetadataFind : public fipObject
+{
+protected:
+ /// Pointer to a search handle
+ FIMETADATA *_mdhandle;
+
+public:
+ /// Returns TRUE if the search handle is allocated, FALSE otherwise
+ BOOL isValid() const;
+
+ /// Constructor
+ fipMetadataFind();
+ /**
+ Destructor
+ @see FreeImage_FindCloseMetadata
+ */
+ virtual ~fipMetadataFind();
+ /**
+ Provides information about the first instance of a tag that matches
+ the metadata model specified in the <i>model</i> argument.
+ @param model Metadata model
+ @param image Input image
+ @param tag Returned tag
+ @return Returns TRUE if successful, returns FALSE otherwise
+ @see FreeImage_FindFirstMetadata
+ */
+ BOOL findFirstMetadata(FREE_IMAGE_MDMODEL model, fipImage& image, fipTag& tag);
+ /**
+ Find the next tag, if any, that matches the metadata model argument
+ in a previous call to findFirstMetadata
+ @param tag Returned tag
+ @return Returns TRUE if successful, returns FALSE otherwise, indicating that no more matching tags could be found
+ @see FreeImage_FindNextMetadata
+ */
+ BOOL findNextMetadata(fipTag& tag);
+
+};
+
+#endif // FREEIMAGEPLUS_H
diff --git a/Wrapper/FreeImagePlus/FreeImagePlus.rc b/Wrapper/FreeImagePlus/FreeImagePlus.rc
new file mode 100644
index 0000000..b8d754a
--- /dev/null
+++ b/Wrapper/FreeImagePlus/FreeImagePlus.rc
@@ -0,0 +1,95 @@
+//Microsoft Developer Studio generated resource script.
+//
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 3,13,0,0
+ PRODUCTVERSION 3,13,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904e2"
+ BEGIN
+ VALUE "Comments", "FreeImage is an Open Source library project for developers who would like to support popular graphics image formats like PNG, BMP, JPEG, TIFF and others as needed by today's multimedia applications.\0"
+ VALUE "CompanyName", "FreeImage\0"
+ VALUE "FileDescription", "FreeImagePlus library\0"
+ VALUE "FileVersion", "3, 13, 0, 0\0"
+ VALUE "InternalName", "FreeImagePlus\0"
+ VALUE "LegalCopyright", "Copyright © 2003-2009 by FreeImage\0"
+ VALUE "LegalTrademarks", "See http://freeimage.sourceforge.net\0"
+ VALUE "OriginalFilename", "FreeImagePlus.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "FreeImagePlus\0"
+ VALUE "ProductVersion", "3, 13, 0, 0\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1250
+ END
+END
+
+#endif // !_MAC
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/Wrapper/FreeImagePlus/WhatsNew_FIP.txt b/Wrapper/FreeImagePlus/WhatsNew_FIP.txt
new file mode 100644
index 0000000..e1160af
--- /dev/null
+++ b/Wrapper/FreeImagePlus/WhatsNew_FIP.txt
@@ -0,0 +1,150 @@
+What's New for FreeImagePlus
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+September 1rd, 2009
+! [Herve Drolon] changed prototypes for fipWinImage::setToneMappingOperator and fipWinImage::getToneMappingOperator
+! [Herve Drolon] changed prototype for fipImage::toneMapping
+! [Herve Drolon] changed prototype for fipImage::rotate (now support optional supplied background color)
++ [Herve Drolon] added FreeImage_TmoReinhard05Ex capability to fipImage & fipWinImage
+
+August 11th, 2009
+* [Mihail Naydenov] fixed fipImage::operator=(FIBITMAP *dib) for cases where dib == _dib
+
+July 10th, 2009
++ [Herve Drolon] added fipImage::adjustBrightnessContrastGamma(double brightness, double contrast, double gamma)
+
+October 27th, 2008
++ [Herve Drolon] added FIF static identification functions to fipImage
+
+August 3rd, 2008
+* [dimitriy.b] fixed warnings about "non virtual destructor with virtual class members" with gcc 4.1.2
+* [Herve Drolon] fixed display of RGBAF EXR images in fipWinImage::drawEx
+
+October 10th, 2007
+* [Terry Russell] fixed a memory leak in fipWinImage::captureWindow
+
+January 20th, 2007
++ [Herve Drolon] added support for 64-bit RGBA images
+
+January 11th, 2007
++ [Herve Drolon] added setKeyValue method (a ASCII tag constructor) to fipTag
++ [Herve Drolon] added PSD format support to fipMultiPage::open
+
+October 30th, 2006 - 3.9.2
++ [Herve Drolon] added BOOL fipMultiPage::open(fipMemoryIO& memIO, int flags)
++ [Herve Drolon] added fipMemoryIO::operator FIMEMORY*()
+* [Herve Drolon] fixed missing 'isValid' method in fipMetadataFind
+
+July 16th, 2006 - 3.9.1
+* [Herve Drolon] fixed a bug in fipWinImage::copyFromBitmap occuring with palettized images
+
+July 6th, 2006 - 3.9.0
+! [Herve Drolon] renamed fipMemoryIO::read to fipMemoryIO::load
+! [Herve Drolon] renamed fipMemoryIO::write to fipMemoryIO::save
++ [Herve Drolon] added fipMemoryIO::read (wrapper for FreeImage_ReadMemory)
++ [Herve Drolon] added fipMemoryIO::write (wrapper for FreeImage_WriteMemory)
++ [Herve Drolon] added version info to the DLL
++ [Herve Drolon] added fipImage::crop
++ [Herve Drolon] added support for most image types to fipImage::rescale
++ [Herve Drolon] added fipImage::makeThumbnail
++ [Herve Drolon] added fipTag
++ [Herve Drolon] added fipMetadataFind
+* [Sandor Szalacsi] improved fipWinWimage::drawEx behavior with non transparent PNG having a file background
+* [Herve Drolon] fixed a bug in fipWinImage::setToneMappingOperator
+* [Conrado PLG] added const keyword to fip methods
+* [Conrado PLG] made the copy constructors of fipMemoryIO private
+
+September 5, 2005 - 3.8.0
+[Herve Drolon]
+! fipImage::convertToGrayscale now uses FreeImage_ConvertToGreyscale
+! fipWinImage::captureWindow now converts 32-bit images to 24-bit
++ added UNICODE function fipImage::loadU
++ added UNICODE function fipImage::saveU
++ added load flags to fipMultiPage::open
++ fipWinImage::copyTo/FromHandle now work with non-standard bitmap types
++ added copy constructors to fipWinImage
++ added fipImage::clear() and fipWinImage::clear()
+* fixed a bug in fipWinWimage::drawEx with non transparent PNG having a file background
+* fixed fipMultiPage not reading GIF files
+* fixed a bug in fipImage::rescale whan handling FIT_UINT16 bitmaps
+
+May 3rd, 2005
+[Herve Drolon]
++ added accessors fipImage::setModified and fipImage::isModified
++ added fipImage::convertToRGBF
++ added fipImage::toneMapping
++ added tone mapping functions to fipWinImage (see get/setToneMappingOperator)
++ added tone mapping capabilities to fipWinImage::drawEx
+
+January 5th, 2005
+[Herve Drolon]
+! changed the prototype of get/set Resolution functions
+
+December 19th, 2004
+[Herve Drolon]
+! updated fipImage::rotate to handle 1-bit images
+
+November 18th, 2004
+[Herve Drolon]
++ added fipImage::convertTo4Bits
+
+August 18th, 2004
+[Herve Drolon]
+- removed fipInternetIO
+- removed copy constructor fipImage::fipImage(const FIBITMAP*)
+- removed copy constructor fipWinImage::fipWinImage(const FIBITMAP*)
+! fipMemoryIO rewritten. It now wraps the FreeImage memory stream API
+! fipGenericImage is now called fipObject
++ added fipImage::loadFromMemory
++ added fipImage::saveToMemory
++ added fipMultiPage
+
+March, 17th, 2004
+[Herve Drolon]
+! fipImage::setSize now accepts color masks
+* fixed fipWinImage::copyFromHandle not working with DIB having color masks
+
+February 11th, 2004
+[Herve Drolon]
+- removed fipImage::getRedChannel
+- removed fipImage::getGreenChannel
+- removed fipImage::getBlueChannel
+- removed fipImage::getAlphaChannel
+- removed fipImage::setAlphaChannel
++ added fipImage::setChannel
++ added fipImage::isTransparent
++ added fipImage::getTransparencyCount
++ added fipImage::getTransparencyTable
++ added fipImage::setTransparencyTable
++ added fipImage::hasFileBkColor
++ added fipImage::getFileBkColor
++ added fipImage::setFileBkColor
++ added fipWinImage::drawEx
+! fipWinImage::draw now works with transparent images
+
+January 26th, 2004
+[Herve Drolon]
++ added fipMemoryIO
++ added fipInternetIO (WIN32 only)
++ added fipImage::getImageType
++ added fipImage::convertToType
++ added fipWinImage::copyToClipboard
++ added fipWinImage::pasteFromClipboard
++ added fipWinImage::captureWindow
+
+! changed fipImage constructor
+! fipWinImage::copyFromHandle now returns a BOOL
+! fipWinImage::copyFromBitmap now returns a BOOL
+
+November 2, 2003
++ [Herve Drolon] added fipImage::getScanLine
+
+October 20, 2003
+* [Dennis Lim] fixed a bug in fipImage constructor
+! [Herve Drolon] fixed a bug with fipImage::saveToHandle prototype
+
+September 8th 2003 - Wrapper for FreeImage 3.0.0
diff --git a/Wrapper/FreeImagePlus/clean.bat b/Wrapper/FreeImagePlus/clean.bat
new file mode 100755
index 0000000..9020551
--- /dev/null
+++ b/Wrapper/FreeImagePlus/clean.bat
@@ -0,0 +1,9 @@
+rd Release /s /q
+rd Debug /s /q
+del dist\*.dll /s /q
+del dist\*.lib /s /q
+del dist\*.h /s /q
+del *.ncb /s /q
+del *.plg /s /q
+del *.opt /s /q
+del *.suo /s /q /a:h
diff --git a/Wrapper/FreeImagePlus/dist/delete.me b/Wrapper/FreeImagePlus/dist/delete.me
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Wrapper/FreeImagePlus/dist/delete.me
diff --git a/Wrapper/FreeImagePlus/doc/FreeImagePlus.dox b/Wrapper/FreeImagePlus/doc/FreeImagePlus.dox
new file mode 100644
index 0000000..3b0d411
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/FreeImagePlus.dox
@@ -0,0 +1,222 @@
+# Doxyfile 1.4.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = FreeImagePlus
+PROJECT_NUMBER = "FreeImage 3.11.0"
+OUTPUT_DIRECTORY = C:/Projects/FreeImage/Wrapper/FreeImagePlus/
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+USE_WINDOWS_ENCODING = YES
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF =
+ALWAYS_DETAILED_SEC = YES
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = YES
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+DISTRIBUTE_GROUP_DOC = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE = C:\Projects\FreeImage\Wrapper\FreeImagePlus\doc\doxygen.log
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = C:/Projects/FreeImage/Source/FreeImage.h \
+ C:/Projects/FreeImage/Wrapper/FreeImagePlus/FreeImagePlus.h
+FILE_PATTERNS = *.h
+RECURSIVE = YES
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER = C:/Projects/FreeImage/Wrapper/FreeImagePlus/doc/header.html
+HTML_FOOTER = C:/Projects/FreeImage/Wrapper/FreeImagePlus/doc/footer.html
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = YES
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = YES
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = YES
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = _WIN32
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+MAX_DOT_GRAPH_DEPTH = 0
+DOT_TRANSPARENT = NO
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/Wrapper/FreeImagePlus/doc/footer.html b/Wrapper/FreeImagePlus/doc/footer.html
new file mode 100644
index 0000000..ed36a62
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/footer.html
@@ -0,0 +1,7 @@
+<hr>
+<p align="right">
+<img src="freeimage.png"><br>
+</p>
+</BODY>
+</HTML>
+
diff --git a/Wrapper/FreeImagePlus/doc/freeimage.png b/Wrapper/FreeImagePlus/doc/freeimage.png
new file mode 100644
index 0000000..4fa7923
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/freeimage.png
Binary files differ
diff --git a/Wrapper/FreeImagePlus/doc/freeimagedoc.jpg b/Wrapper/FreeImagePlus/doc/freeimagedoc.jpg
new file mode 100644
index 0000000..0a31440
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/freeimagedoc.jpg
Binary files differ
diff --git a/Wrapper/FreeImagePlus/doc/header.html b/Wrapper/FreeImagePlus/doc/header.html
new file mode 100644
index 0000000..fdbb2ea
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/header.html
@@ -0,0 +1,7 @@
+<HTML>
+<HEAD>
+<TITLE>FreeImagePlus</TITLE>
+<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
diff --git a/Wrapper/FreeImagePlus/doc/main.html b/Wrapper/FreeImagePlus/doc/main.html
new file mode 100644
index 0000000..9f6013a
--- /dev/null
+++ b/Wrapper/FreeImagePlus/doc/main.html
@@ -0,0 +1,18 @@
+<HTML>
+<HEAD>
+<TITLE>FreeImagePlus</TITLE>
+<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
+</HEAD>
+<BODY BGCOLOR="#FFFFFF">
+<!-- Generated by Doxygen 1.2.17 -->
+<center>
+<a class="qindex" href="main.html">Main Page</a> &nbsp; <a class="qindex" href="hierarchy.html">Class Hierarchy</a> &nbsp; <a class="qindex" href="classes.html">Alphabetical List</a> &nbsp; <a class="qindex" href="annotated.html">Compound List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; </center>
+<hr>
+<p>
+<p align="center">
+<img src="freeimagedoc.jpg"><br>
+</p>
+<h3 align="center">A C++ wrapper for FreeImage 3</h3>
+</BODY>
+</HTML>
+
diff --git a/Wrapper/FreeImagePlus/src/FreeImagePlus.cpp b/Wrapper/FreeImagePlus/src/FreeImagePlus.cpp
new file mode 100644
index 0000000..efb8fe9
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/FreeImagePlus.cpp
@@ -0,0 +1,46 @@
+// ==========================================================
+// FreeImagePlus.cpp : Defines the entry point for the DLL application.
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifdef _WIN32
+#include <windows.h>
+#endif // _WIN32
+
+#include "FreeImagePlus.h"
+
+//----------------------------------------------------------------------
+
+#ifdef _WIN32
+
+BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+
+#endif // _WIN32
diff --git a/Wrapper/FreeImagePlus/src/fipImage.cpp b/Wrapper/FreeImagePlus/src/fipImage.cpp
new file mode 100644
index 0000000..c1b2ca3
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipImage.cpp
@@ -0,0 +1,910 @@
+// ==========================================================
+// fipImage class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+
+///////////////////////////////////////////////////////////////////
+// Protected functions
+
+BOOL fipImage::replace(FIBITMAP *new_dib) {
+ if(new_dib == NULL)
+ return FALSE;
+ if(_dib)
+ FreeImage_Unload(_dib);
+ _dib = new_dib;
+ _bHasChanged = TRUE;
+ return TRUE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Creation & Destruction
+
+fipImage::fipImage(FREE_IMAGE_TYPE image_type, WORD width, WORD height, WORD bpp) {
+ _dib = NULL;
+ _bHasChanged = FALSE;
+ if(width && height && bpp)
+ setSize(image_type, width, height, bpp);
+}
+
+fipImage::~fipImage() {
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ _dib = NULL;
+ }
+}
+
+BOOL fipImage::setSize(FREE_IMAGE_TYPE image_type, WORD width, WORD height, WORD bpp, unsigned red_mask, unsigned green_mask, unsigned blue_mask) {
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ }
+ if((_dib = FreeImage_AllocateT(image_type, width, height, bpp, red_mask, green_mask, blue_mask)) == NULL)
+ return FALSE;
+
+ if(image_type == FIT_BITMAP) {
+ // Create palette if needed
+ switch(bpp) {
+ case 1:
+ case 4:
+ case 8:
+ RGBQUAD *pal = FreeImage_GetPalette(_dib);
+ for(unsigned i = 0; i < FreeImage_GetColorsUsed(_dib); i++) {
+ pal[i].rgbRed = i;
+ pal[i].rgbGreen = i;
+ pal[i].rgbBlue = i;
+ }
+ break;
+ }
+ }
+
+ _bHasChanged = TRUE;
+
+ return TRUE;
+}
+
+void fipImage::clear() {
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ _dib = NULL;
+ }
+ _bHasChanged = TRUE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Copying
+
+fipImage::fipImage(const fipImage& Image) {
+ _dib = NULL;
+ _fif = FIF_UNKNOWN;
+ FIBITMAP *clone = FreeImage_Clone((FIBITMAP*)Image._dib);
+ replace(clone);
+}
+
+fipImage& fipImage::operator=(const fipImage& Image) {
+ if(this != &Image) {
+ FIBITMAP *clone = FreeImage_Clone((FIBITMAP*)Image._dib);
+ replace(clone);
+ }
+ return *this;
+}
+
+fipImage& fipImage::operator=(FIBITMAP *dib) {
+ if(_dib != dib) {
+ replace(dib);
+ }
+ return *this;
+}
+
+BOOL fipImage::copySubImage(fipImage& dst, int left, int top, int right, int bottom) const {
+ if(_dib) {
+ dst = FreeImage_Copy(_dib, left, top, right, bottom);
+ return dst.isValid();
+ }
+ return FALSE;
+}
+
+BOOL fipImage::pasteSubImage(fipImage& src, int left, int top, int alpha) {
+ if(_dib) {
+ BOOL bResult = FreeImage_Paste(_dib, src._dib, left, top, alpha);
+ _bHasChanged = TRUE;
+ return bResult;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::crop(int left, int top, int right, int bottom) {
+ if(_dib) {
+ FIBITMAP *dst = FreeImage_Copy(_dib, left, top, right, bottom);
+ return replace(dst);
+ }
+ return FALSE;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Information functions
+
+FREE_IMAGE_TYPE fipImage::getImageType() const {
+ return FreeImage_GetImageType(_dib);
+}
+
+WORD fipImage::getWidth() const {
+ return FreeImage_GetWidth(_dib);
+}
+
+WORD fipImage::getHeight() const {
+ return FreeImage_GetHeight(_dib);
+}
+
+WORD fipImage::getScanWidth() const {
+ return FreeImage_GetPitch(_dib);
+}
+
+BOOL fipImage::isValid() const {
+ return (_dib != NULL) ? TRUE:FALSE;
+}
+
+BITMAPINFO* fipImage::getInfo() const {
+ return FreeImage_GetInfo(_dib);
+}
+
+BITMAPINFOHEADER* fipImage::getInfoHeader() const {
+ return FreeImage_GetInfoHeader(_dib);
+}
+
+LONG fipImage::getImageSize() const {
+ return FreeImage_GetDIBSize(_dib);
+}
+
+WORD fipImage::getBitsPerPixel() const {
+ return FreeImage_GetBPP(_dib);
+}
+
+WORD fipImage::getLine() const {
+ return FreeImage_GetLine(_dib);
+}
+
+double fipImage::getHorizontalResolution() const {
+ return (FreeImage_GetDotsPerMeterX(_dib) / (double)100);
+}
+
+double fipImage::getVerticalResolution() const {
+ return (FreeImage_GetDotsPerMeterY(_dib) / (double)100);
+}
+
+void fipImage::setHorizontalResolution(double value) {
+ FreeImage_SetDotsPerMeterX(_dib, (unsigned)(value * 100 + 0.5));
+}
+
+void fipImage::setVerticalResolution(double value) {
+ FreeImage_SetDotsPerMeterY(_dib, (unsigned)(value * 100 + 0.5));
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Palette operations
+
+RGBQUAD* fipImage::getPalette() const {
+ return FreeImage_GetPalette(_dib);
+}
+
+WORD fipImage::getPaletteSize() const {
+ return FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD);
+}
+
+WORD fipImage::getColorsUsed() const {
+ return FreeImage_GetColorsUsed(_dib);
+}
+
+FREE_IMAGE_COLOR_TYPE fipImage::getColorType() const {
+ return FreeImage_GetColorType(_dib);
+}
+
+BOOL fipImage::isGrayscale() const {
+ return ((FreeImage_GetBPP(_dib) == 8) && (FreeImage_GetColorType(_dib) != FIC_PALETTE));
+}
+
+///////////////////////////////////////////////////////////////////
+// Pixel access
+
+BYTE* fipImage::accessPixels() const {
+ return FreeImage_GetBits(_dib);
+}
+
+BYTE* fipImage::getScanLine(WORD scanline) const {
+ if(scanline < FreeImage_GetHeight(_dib)) {
+ return FreeImage_GetScanLine(_dib, scanline);
+ }
+ return NULL;
+}
+
+BOOL fipImage::getPixelIndex(unsigned x, unsigned y, BYTE *value) const {
+ return FreeImage_GetPixelIndex(_dib, x, y, value);
+}
+
+BOOL fipImage::getPixelColor(unsigned x, unsigned y, RGBQUAD *value) const {
+ return FreeImage_GetPixelColor(_dib, x, y, value);
+}
+
+BOOL fipImage::setPixelIndex(unsigned x, unsigned y, BYTE *value) {
+ _bHasChanged = TRUE;
+ return FreeImage_SetPixelIndex(_dib, x, y, value);
+}
+
+BOOL fipImage::setPixelColor(unsigned x, unsigned y, RGBQUAD *value) {
+ _bHasChanged = TRUE;
+ return FreeImage_SetPixelColor(_dib, x, y, value);
+}
+
+///////////////////////////////////////////////////////////////////
+// File type identification
+
+FREE_IMAGE_FORMAT fipImage::identifyFIF(const char* lpszPathName) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+
+ return fif;
+}
+
+FREE_IMAGE_FORMAT fipImage::identifyFIFU(const wchar_t* lpszPathName) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileTypeU(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilenameU(lpszPathName);
+ }
+
+ return fif;
+}
+
+FREE_IMAGE_FORMAT fipImage::identifyFIFFromHandle(FreeImageIO *io, fi_handle handle) {
+ if(io && handle) {
+ // check the file signature and get its format
+ return FreeImage_GetFileTypeFromHandle(io, handle, 16);
+ }
+ return FIF_UNKNOWN;
+}
+
+FREE_IMAGE_FORMAT fipImage::identifyFIFFromMemory(FIMEMORY *hmem) {
+ if(hmem != NULL) {
+ return FreeImage_GetFileTypeFromMemory(hmem, 0);
+ }
+ return FIF_UNKNOWN;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Loading & Saving
+
+BOOL fipImage::load(const char* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileType(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // Free the previous dib
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ }
+ // Load the file
+ _dib = FreeImage_Load(fif, lpszPathName, flag);
+ _bHasChanged = TRUE;
+ if(_dib == NULL)
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::loadU(const wchar_t* lpszPathName, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ // (the second argument is currently not used by FreeImage)
+ fif = FreeImage_GetFileTypeU(lpszPathName, 0);
+ if(fif == FIF_UNKNOWN) {
+ // no signature ?
+ // try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilenameU(lpszPathName);
+ }
+ // check that the plugin has reading capabilities ...
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // Free the previous dib
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ }
+ // Load the file
+ _dib = FreeImage_LoadU(fif, lpszPathName, flag);
+ _bHasChanged = TRUE;
+ if(_dib == NULL)
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::loadFromHandle(FreeImageIO *io, fi_handle handle, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ fif = FreeImage_GetFileTypeFromHandle(io, handle, 16);
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // Free the previous dib
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ }
+ // Load the file
+ _dib = FreeImage_LoadFromHandle(fif, io, handle, flag);
+ _bHasChanged = TRUE;
+ if(_dib == NULL)
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::loadFromMemory(fipMemoryIO& memIO, int flag) {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+
+ // check the file signature and get its format
+ fif = memIO.getFileType();
+ if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
+ // Free the previous dib
+ if(_dib) {
+ FreeImage_Unload(_dib);
+ }
+ // Load the file
+ _dib = memIO.load(fif, flag);
+ _bHasChanged = TRUE;
+ if(_dib == NULL)
+ return FALSE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::save(const char* lpszPathName, int flag) const {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ BOOL bSuccess = FALSE;
+
+ // Try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilename(lpszPathName);
+ if(fif != FIF_UNKNOWN ) {
+ // Check that the dib can be saved in this format
+ BOOL bCanSave;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib);
+ if(image_type == FIT_BITMAP) {
+ // standard bitmap type
+ WORD bpp = FreeImage_GetBPP(_dib);
+ bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp));
+ } else {
+ // special bitmap type
+ bCanSave = FreeImage_FIFSupportsExportType(fif, image_type);
+ }
+
+ if(bCanSave) {
+ bSuccess = FreeImage_Save(fif, _dib, lpszPathName, flag);
+ return bSuccess;
+ }
+ }
+ return bSuccess;
+}
+
+BOOL fipImage::saveU(const wchar_t* lpszPathName, int flag) const {
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
+ BOOL bSuccess = FALSE;
+
+ // Try to guess the file format from the file extension
+ fif = FreeImage_GetFIFFromFilenameU(lpszPathName);
+ if(fif != FIF_UNKNOWN ) {
+ // Check that the dib can be saved in this format
+ BOOL bCanSave;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib);
+ if(image_type == FIT_BITMAP) {
+ // standard bitmap type
+ WORD bpp = FreeImage_GetBPP(_dib);
+ bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp));
+ } else {
+ // special bitmap type
+ bCanSave = FreeImage_FIFSupportsExportType(fif, image_type);
+ }
+
+ if(bCanSave) {
+ bSuccess = FreeImage_SaveU(fif, _dib, lpszPathName, flag);
+ return bSuccess;
+ }
+ }
+ return bSuccess;
+}
+
+BOOL fipImage::saveToHandle(FREE_IMAGE_FORMAT fif, FreeImageIO *io, fi_handle handle, int flag) const {
+ BOOL bSuccess = FALSE;
+
+ if(fif != FIF_UNKNOWN ) {
+ // Check that the dib can be saved in this format
+ BOOL bCanSave;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib);
+ if(image_type == FIT_BITMAP) {
+ // standard bitmap type
+ WORD bpp = FreeImage_GetBPP(_dib);
+ bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp));
+ } else {
+ // special bitmap type
+ bCanSave = FreeImage_FIFSupportsExportType(fif, image_type);
+ }
+
+ if(bCanSave) {
+ bSuccess = FreeImage_SaveToHandle(fif, _dib, io, handle, flag);
+ return bSuccess;
+ }
+ }
+ return bSuccess;
+}
+
+BOOL fipImage::saveToMemory(FREE_IMAGE_FORMAT fif, fipMemoryIO& memIO, int flag) const {
+ BOOL bSuccess = FALSE;
+
+ if(fif != FIF_UNKNOWN ) {
+ // Check that the dib can be saved in this format
+ BOOL bCanSave;
+
+ FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(_dib);
+ if(image_type == FIT_BITMAP) {
+ // standard bitmap type
+ WORD bpp = FreeImage_GetBPP(_dib);
+ bCanSave = (FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp));
+ } else {
+ // special bitmap type
+ bCanSave = FreeImage_FIFSupportsExportType(fif, image_type);
+ }
+
+ if(bCanSave) {
+ bSuccess = memIO.save(fif, _dib, flag);
+ return bSuccess;
+ }
+ }
+ return bSuccess;
+}
+
+///////////////////////////////////////////////////////////////////
+// Conversion routines
+
+BOOL fipImage::convertToType(FREE_IMAGE_TYPE image_type, BOOL scale_linear) {
+ if(_dib) {
+ FIBITMAP *dib = FreeImage_ConvertToType(_dib, image_type, scale_linear);
+ return replace(dib);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::threshold(BYTE T) {
+ if(_dib) {
+ FIBITMAP *dib1 = FreeImage_Threshold(_dib, T);
+ return replace(dib1);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo4Bits() {
+ if(_dib) {
+ FIBITMAP *dib4 = FreeImage_ConvertTo4Bits(_dib);
+ return replace(dib4);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo8Bits() {
+ if(_dib) {
+ FIBITMAP *dib8 = FreeImage_ConvertTo8Bits(_dib);
+ return replace(dib8);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo16Bits555() {
+ if(_dib) {
+ FIBITMAP *dib16_555 = FreeImage_ConvertTo16Bits555(_dib);
+ return replace(dib16_555);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo16Bits565() {
+ if(_dib) {
+ FIBITMAP *dib16_565 = FreeImage_ConvertTo16Bits565(_dib);
+ return replace(dib16_565);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo24Bits() {
+ if(_dib) {
+ FIBITMAP *dibRGB = FreeImage_ConvertTo24Bits(_dib);
+ return replace(dibRGB);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertTo32Bits() {
+ if(_dib) {
+ FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib);
+ return replace(dib32);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertToGrayscale() {
+ if(_dib) {
+ FIBITMAP *dib8 = FreeImage_ConvertToGreyscale(_dib);
+ return replace(dib8);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::colorQuantize(FREE_IMAGE_QUANTIZE algorithm) {
+ if(_dib) {
+ FIBITMAP *dib8 = FreeImage_ColorQuantize(_dib, algorithm);
+ return replace(dib8);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::dither(FREE_IMAGE_DITHER algorithm) {
+ if(_dib) {
+ FIBITMAP *dib = FreeImage_Dither(_dib, algorithm);
+ return replace(dib);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::convertToRGBF() {
+ if(_dib) {
+ FIBITMAP *dib = FreeImage_ConvertToRGBF(_dib);
+ return replace(dib);
+ }
+ return FALSE;
+
+}
+
+BOOL fipImage::toneMapping(FREE_IMAGE_TMO tmo, double first_param, double second_param, double third_param, double fourth_param) {
+ if(_dib) {
+ FIBITMAP *dst = NULL;
+ // Apply a tone mapping algorithm and convert to 24-bit
+ switch(tmo) {
+ case FITMO_REINHARD05:
+ dst = FreeImage_TmoReinhard05Ex(_dib, first_param, second_param, third_param, fourth_param);
+ break;
+ default:
+ dst = FreeImage_ToneMapping(_dib, tmo, first_param, second_param);
+ break;
+ }
+
+ return replace(dst);
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Transparency support: background colour and alpha channel
+
+BOOL fipImage::isTransparent() const {
+ return FreeImage_IsTransparent(_dib);
+}
+
+unsigned fipImage::getTransparencyCount() const {
+ return FreeImage_GetTransparencyCount(_dib);
+}
+
+BYTE* fipImage::getTransparencyTable() const {
+ return FreeImage_GetTransparencyTable(_dib);
+}
+
+void fipImage::setTransparencyTable(BYTE *table, int count) {
+ FreeImage_SetTransparencyTable(_dib, table, count);
+ _bHasChanged = TRUE;
+}
+
+BOOL fipImage::hasFileBkColor() const {
+ return FreeImage_HasBackgroundColor(_dib);
+}
+
+BOOL fipImage::getFileBkColor(RGBQUAD *bkcolor) const {
+ return FreeImage_GetBackgroundColor(_dib, bkcolor);
+}
+
+BOOL fipImage::setFileBkColor(RGBQUAD *bkcolor) {
+ _bHasChanged = TRUE;
+ return FreeImage_SetBackgroundColor(_dib, bkcolor);
+}
+
+///////////////////////////////////////////////////////////////////
+// Channel processing support
+
+BOOL fipImage::getChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) const {
+ if(_dib) {
+ image = FreeImage_GetChannel(_dib, channel);
+ return image.isValid();
+ }
+ return FALSE;
+}
+
+BOOL fipImage::setChannel(fipImage& image, FREE_IMAGE_COLOR_CHANNEL channel) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+ return FreeImage_SetChannel(_dib, image._dib, channel);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::splitChannels(fipImage& RedChannel, fipImage& GreenChannel, fipImage& BlueChannel) {
+ if(_dib) {
+ RedChannel = FreeImage_GetChannel(_dib, FICC_RED);
+ GreenChannel = FreeImage_GetChannel(_dib, FICC_GREEN);
+ BlueChannel = FreeImage_GetChannel(_dib, FICC_BLUE);
+
+ return (RedChannel.isValid() && GreenChannel.isValid() && BlueChannel.isValid());
+ }
+ return FALSE;
+}
+
+BOOL fipImage::combineChannels(fipImage& red, fipImage& green, fipImage& blue) {
+ if(!_dib) {
+ int width = red.getWidth();
+ int height = red.getHeight();
+ _dib = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ }
+
+ if(_dib) {
+ BOOL bResult = TRUE;
+ bResult &= FreeImage_SetChannel(_dib, red._dib, FICC_RED);
+ bResult &= FreeImage_SetChannel(_dib, green._dib, FICC_GREEN);
+ bResult &= FreeImage_SetChannel(_dib, blue._dib, FICC_BLUE);
+
+ _bHasChanged = TRUE;
+
+ return bResult;
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Rotation and flipping
+
+BOOL fipImage::rotateEx(double angle, double x_shift, double y_shift, double x_origin, double y_origin, BOOL use_mask) {
+ if(_dib) {
+ if(FreeImage_GetBPP(_dib) >= 8) {
+ FIBITMAP *rotated = FreeImage_RotateEx(_dib, angle, x_shift, y_shift, x_origin, y_origin, use_mask);
+ return replace(rotated);
+ }
+ }
+ return FALSE;
+}
+
+BOOL fipImage::rotate(double angle, const void *bkcolor) {
+ if(_dib) {
+ switch(FreeImage_GetImageType(_dib)) {
+ case FIT_BITMAP:
+ switch(FreeImage_GetBPP(_dib)) {
+ case 1:
+ case 8:
+ case 24:
+ case 32:
+ break;
+ default:
+ return FALSE;
+ }
+ break;
+
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ FIBITMAP *rotated = FreeImage_Rotate(_dib, angle, bkcolor);
+ return replace(rotated);
+
+ }
+ return FALSE;
+}
+
+BOOL fipImage::flipVertical() {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_FlipVertical(_dib);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::flipHorizontal() {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_FlipHorizontal(_dib);
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Color manipulation routines
+
+BOOL fipImage::invert() {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_Invert(_dib);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::adjustCurve(BYTE *LUT, FREE_IMAGE_COLOR_CHANNEL channel) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_AdjustCurve(_dib, LUT, channel);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::adjustGamma(double gamma) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_AdjustGamma(_dib, gamma);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::adjustBrightness(double percentage) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_AdjustBrightness(_dib, percentage);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::adjustContrast(double percentage) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_AdjustContrast(_dib, percentage);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::adjustBrightnessContrastGamma(double brightness, double contrast, double gamma) {
+ if(_dib) {
+ _bHasChanged = TRUE;
+
+ return FreeImage_AdjustColors(_dib, brightness, contrast, gamma, FALSE);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::getHistogram(DWORD *histo, FREE_IMAGE_COLOR_CHANNEL channel) const {
+ if(_dib) {
+ return FreeImage_GetHistogram(_dib, histo, channel);
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Upsampling / downsampling routine
+
+BOOL fipImage::rescale(WORD new_width, WORD new_height, FREE_IMAGE_FILTER filter) {
+ if(_dib) {
+ switch(FreeImage_GetImageType(_dib)) {
+ case FIT_BITMAP:
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ // Perform upsampling / downsampling
+ FIBITMAP *dst = FreeImage_Rescale(_dib, new_width, new_height, filter);
+ return replace(dst);
+ }
+ return FALSE;
+}
+
+BOOL fipImage::makeThumbnail(WORD max_size, BOOL convert) {
+ if(_dib) {
+ switch(FreeImage_GetImageType(_dib)) {
+ case FIT_BITMAP:
+ case FIT_UINT16:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_FLOAT:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ // Perform downsampling
+ FIBITMAP *dst = FreeImage_MakeThumbnail(_dib, max_size, convert);
+ return replace(dst);
+ }
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Metadata
+
+unsigned fipImage::getMetadataCount(FREE_IMAGE_MDMODEL model) const {
+ return FreeImage_GetMetadataCount(model, _dib);
+}
+
+BOOL fipImage::getMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag) const {
+ FITAG *searchedTag = NULL;
+ FreeImage_GetMetadata(model, _dib, key, &searchedTag);
+ if(searchedTag != NULL) {
+ tag = FreeImage_CloneTag(searchedTag);
+ return TRUE;
+ } else {
+ // clear the tag
+ tag = (FITAG*)NULL;
+ }
+ return FALSE;
+}
+
+BOOL fipImage::setMetadata(FREE_IMAGE_MDMODEL model, const char *key, fipTag& tag) {
+ return FreeImage_SetMetadata(model, _dib, key, tag);
+}
+
diff --git a/Wrapper/FreeImagePlus/src/fipMemoryIO.cpp b/Wrapper/FreeImagePlus/src/fipMemoryIO.cpp
new file mode 100644
index 0000000..e8fb7db
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipMemoryIO.cpp
@@ -0,0 +1,78 @@
+// ==========================================================
+// fipMemoryIO class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+fipMemoryIO::fipMemoryIO(BYTE *data, DWORD size_in_bytes) {
+ _hmem = FreeImage_OpenMemory(data, size_in_bytes);
+}
+
+fipMemoryIO::~fipMemoryIO() {
+ FreeImage_CloseMemory(_hmem);
+}
+
+BOOL fipMemoryIO::isValid() const {
+ return (_hmem != NULL);
+}
+
+FREE_IMAGE_FORMAT fipMemoryIO::getFileType() const {
+ if(_hmem != NULL) {
+ return FreeImage_GetFileTypeFromMemory(_hmem, 0);
+ }
+
+ return FIF_UNKNOWN;
+}
+
+FIBITMAP* fipMemoryIO::load(FREE_IMAGE_FORMAT fif, int flags) const {
+ return FreeImage_LoadFromMemory(fif, _hmem, flags);
+}
+
+BOOL fipMemoryIO::save(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, int flags) {
+ return FreeImage_SaveToMemory(fif, dib, _hmem, flags);
+}
+
+unsigned fipMemoryIO::read(void *buffer, unsigned size, unsigned count) const {
+ return FreeImage_ReadMemory(buffer, size, count, _hmem);
+}
+
+unsigned fipMemoryIO::write(const void *buffer, unsigned size, unsigned count) {
+ return FreeImage_WriteMemory(buffer, size, count, _hmem);
+}
+
+long fipMemoryIO::tell() const {
+ return FreeImage_TellMemory(_hmem);
+}
+
+BOOL fipMemoryIO::seek(long offset, int origin) {
+ return FreeImage_SeekMemory(_hmem, offset, origin);
+}
+
+BOOL fipMemoryIO::acquire(BYTE **data, DWORD *size_in_bytes) {
+ return FreeImage_AcquireMemory(_hmem, data, size_in_bytes);
+}
+
+
diff --git a/Wrapper/FreeImagePlus/src/fipMetadataFind.cpp b/Wrapper/FreeImagePlus/src/fipMetadataFind.cpp
new file mode 100644
index 0000000..57d01f6
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipMetadataFind.cpp
@@ -0,0 +1,54 @@
+// ==========================================================
+// fipMetadataFind class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+
+BOOL fipMetadataFind::isValid() const {
+ return (_mdhandle != NULL) ? TRUE : FALSE;
+}
+
+fipMetadataFind::fipMetadataFind() : _mdhandle(NULL) {
+}
+
+fipMetadataFind::~fipMetadataFind() {
+ FreeImage_FindCloseMetadata(_mdhandle);
+}
+
+BOOL fipMetadataFind::findFirstMetadata(FREE_IMAGE_MDMODEL model, fipImage& image, fipTag& tag) {
+ FITAG *firstTag = NULL;
+ if(_mdhandle) FreeImage_FindCloseMetadata(_mdhandle);
+ _mdhandle = FreeImage_FindFirstMetadata(model, image, &firstTag);
+ if(_mdhandle) {
+ tag = FreeImage_CloneTag(firstTag);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL fipMetadataFind::findNextMetadata(fipTag& tag) {
+ FITAG *nextTag = NULL;
+ if( FreeImage_FindNextMetadata(_mdhandle, &nextTag) ) {
+ tag = FreeImage_CloneTag(nextTag);
+ return TRUE;
+ }
+ return FALSE;
+}
+
diff --git a/Wrapper/FreeImagePlus/src/fipMultiPage.cpp b/Wrapper/FreeImagePlus/src/fipMultiPage.cpp
new file mode 100644
index 0000000..4046393
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipMultiPage.cpp
@@ -0,0 +1,118 @@
+// ==========================================================
+// fipMultiPage class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+
+fipMultiPage::fipMultiPage(BOOL keep_cache_in_memory) : _mpage(NULL), _bMemoryCache(keep_cache_in_memory) {
+}
+
+fipMultiPage::~fipMultiPage() {
+ if(_mpage) {
+ // close the stream
+ close(0);
+ }
+}
+
+BOOL fipMultiPage::isValid() const {
+ return (NULL != _mpage) ? TRUE : FALSE;
+}
+
+BOOL fipMultiPage::open(const char* lpszPathName, BOOL create_new, BOOL read_only, int flags) {
+ // try to guess the file format from the filename
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(lpszPathName);
+
+ // check for supported file types
+ if((fif == FIF_UNKNOWN) || (fif != FIF_TIFF) && (fif != FIF_ICO) && (fif != FIF_GIF) && (fif != FIF_PSD))
+ return FALSE;
+
+ // open the stream
+ _mpage = FreeImage_OpenMultiBitmap(fif, lpszPathName, create_new, read_only, _bMemoryCache, flags);
+
+ return (NULL != _mpage ) ? TRUE : FALSE;
+}
+
+BOOL fipMultiPage::open(fipMemoryIO& memIO, int flags) {
+ // try to guess the file format from the filename
+ FREE_IMAGE_FORMAT fif = memIO.getFileType();
+
+ // check for supported file types
+ if((fif == FIF_UNKNOWN) || (fif != FIF_TIFF) && (fif != FIF_ICO) && (fif != FIF_GIF))
+ return FALSE;
+
+ // open the stream
+ _mpage = FreeImage_LoadMultiBitmapFromMemory(fif, memIO, flags);
+
+ return (NULL != _mpage ) ? TRUE : FALSE;
+}
+
+
+BOOL fipMultiPage::close(int flags) {
+ BOOL bSuccess = FALSE;
+ if(_mpage) {
+ // close the stream
+ bSuccess = FreeImage_CloseMultiBitmap(_mpage, flags);
+ _mpage = NULL;
+ }
+
+ return bSuccess;
+}
+
+int fipMultiPage::getPageCount() const {
+ return _mpage ? FreeImage_GetPageCount(_mpage) : 0;
+}
+
+void fipMultiPage::appendPage(fipImage& image) {
+ if(_mpage)
+ FreeImage_AppendPage(_mpage, image);
+}
+
+void fipMultiPage::insertPage(int page, fipImage& image) {
+ if(_mpage)
+ FreeImage_InsertPage(_mpage, page, image);
+}
+
+void fipMultiPage::deletePage(int page) {
+ if(_mpage)
+ FreeImage_DeletePage(_mpage, page);
+}
+
+BOOL fipMultiPage::movePage(int target, int source) {
+ return _mpage ? FreeImage_MovePage(_mpage, target, source) : FALSE;
+}
+
+FIBITMAP* fipMultiPage::lockPage(int page) {
+ return _mpage ? FreeImage_LockPage(_mpage, page) : NULL;
+}
+
+void fipMultiPage::unlockPage(fipImage& image, BOOL changed) {
+ if(_mpage) {
+ FreeImage_UnlockPage(_mpage, image, changed);
+ // clear the image so that it becomes invalid.
+ // this is possible because of the friend declaration
+ image._dib = NULL;
+ image._bHasChanged = FALSE;
+ }
+}
+
+BOOL fipMultiPage::getLockedPageNumbers(int *pages, int *count) const {
+ return _mpage ? FreeImage_GetLockedPageNumbers(_mpage, pages, count) : FALSE;
+}
+
diff --git a/Wrapper/FreeImagePlus/src/fipTag.cpp b/Wrapper/FreeImagePlus/src/fipTag.cpp
new file mode 100644
index 0000000..b00a095
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipTag.cpp
@@ -0,0 +1,134 @@
+// ==========================================================
+// fipTag class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include <string.h>
+#include "FreeImagePlus.h"
+
+fipTag::fipTag() {
+ _tag = FreeImage_CreateTag();
+}
+
+fipTag::~fipTag() {
+ FreeImage_DeleteTag(_tag);
+}
+
+BOOL fipTag::setKeyValue(const char *key, const char *value) {
+ if(_tag) {
+ FreeImage_DeleteTag(_tag);
+ _tag = NULL;
+ }
+ // create a tag
+ _tag = FreeImage_CreateTag();
+ if(_tag) {
+ BOOL bSuccess = TRUE;
+ // fill the tag
+ DWORD tag_length = (DWORD)(strlen(value) + 1);
+ bSuccess &= FreeImage_SetTagKey(_tag, key);
+ bSuccess &= FreeImage_SetTagLength(_tag, tag_length);
+ bSuccess &= FreeImage_SetTagCount(_tag, tag_length);
+ bSuccess &= FreeImage_SetTagType(_tag, FIDT_ASCII);
+ bSuccess &= FreeImage_SetTagValue(_tag, value);
+ return bSuccess;
+ }
+ return FALSE;
+}
+
+fipTag::fipTag(const fipTag& tag) {
+ _tag = FreeImage_CloneTag(tag._tag);
+}
+
+fipTag& fipTag::operator=(const fipTag& tag) {
+ if(this != &tag) {
+ if(_tag) FreeImage_DeleteTag(_tag);
+ _tag = FreeImage_CloneTag(tag._tag);
+ }
+ return *this;
+}
+
+fipTag& fipTag::operator=(FITAG *tag) {
+ if(_tag) FreeImage_DeleteTag(_tag);
+ _tag = tag;
+ return *this;
+}
+
+BOOL fipTag::isValid() const {
+ return (_tag != NULL) ? TRUE : FALSE;
+}
+
+const char* fipTag::getKey() const {
+ return FreeImage_GetTagKey(_tag);
+}
+
+const char* fipTag::getDescription() const {
+ return FreeImage_GetTagDescription(_tag);
+}
+
+WORD fipTag::getID() const {
+ return FreeImage_GetTagID(_tag);
+}
+
+FREE_IMAGE_MDTYPE fipTag::getType() const {
+ return FreeImage_GetTagType(_tag);
+}
+
+DWORD fipTag::getCount() const {
+ return FreeImage_GetTagCount(_tag);
+}
+
+DWORD fipTag::getLength() const {
+ return FreeImage_GetTagLength(_tag);
+}
+
+const void* fipTag::getValue() const {
+ return FreeImage_GetTagValue(_tag);
+}
+
+BOOL fipTag::setKey(const char *key) {
+ return FreeImage_SetTagKey(_tag, key);
+}
+
+BOOL fipTag::setDescription(const char *description) {
+ return FreeImage_SetTagDescription(_tag, description);
+}
+
+BOOL fipTag::setID(WORD id) {
+ return FreeImage_SetTagID(_tag, id);
+}
+
+BOOL fipTag::setType(FREE_IMAGE_MDTYPE type) {
+ return FreeImage_SetTagType(_tag, type);
+}
+
+BOOL fipTag::setCount(DWORD count) {
+ return FreeImage_SetTagCount(_tag, count);
+}
+
+BOOL fipTag::setLength(DWORD length) {
+ return FreeImage_SetTagLength(_tag, length);
+}
+
+BOOL fipTag::setValue(const void *value) {
+ return FreeImage_SetTagValue(_tag, value);
+}
+
+const char* fipTag::toString(FREE_IMAGE_MDMODEL model, char *Make) const {
+ return FreeImage_TagToString(model, _tag, Make);
+}
diff --git a/Wrapper/FreeImagePlus/src/fipWinImage.cpp b/Wrapper/FreeImagePlus/src/fipWinImage.cpp
new file mode 100644
index 0000000..9139152
--- /dev/null
+++ b/Wrapper/FreeImagePlus/src/fipWinImage.cpp
@@ -0,0 +1,481 @@
+// ==========================================================
+// fipWinImage class implementation
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#include "FreeImagePlus.h"
+
+#ifdef _WIN32
+
+// marker used for clipboard copy / paste
+
+static inline void
+SET_FREEIMAGE_MARKER(BITMAPINFOHEADER *bmih, FIBITMAP *dib) {
+ // Windows constants goes from 0L to 5L
+ // Add 0xFF to avoid conflicts
+ bmih->biCompression = 0xFF + FreeImage_GetImageType(dib);
+}
+
+static inline FREE_IMAGE_TYPE
+GET_FREEIMAGE_MARKER(BITMAPINFOHEADER *bmih) {
+ return (FREE_IMAGE_TYPE)(bmih->biCompression - 0xFF);
+}
+
+///////////////////////////////////////////////////////////////////
+// Construction / Destruction
+
+fipWinImage::fipWinImage(FREE_IMAGE_TYPE image_type, WORD width, WORD height, WORD bpp) : fipImage(image_type, width, height, bpp) {
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // default tone mapping operator
+ _tmo = FITMO_DRAGO03;
+ _tmo_param_1 = 0;
+ _tmo_param_2 = 0;
+ _tmo_param_3 = 1;
+ _tmo_param_4 = 0;
+}
+
+fipWinImage::~fipWinImage() {
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+}
+
+void fipWinImage::clear() {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // delete base class data
+ fipImage::clear();
+}
+
+BOOL fipWinImage::isValid() const {
+ return fipImage::isValid();
+}
+
+///////////////////////////////////////////////////////////////////
+// Copying
+
+fipWinImage& fipWinImage::operator=(const fipImage& Image) {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // clone the base class
+ fipImage::operator=(Image);
+
+ return *this;
+}
+
+fipWinImage& fipWinImage::operator=(const fipWinImage& Image) {
+ if(this != &Image) {
+ // delete _display_dib
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ }
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ // copy tmo data
+ _tmo = Image._tmo;
+ _tmo_param_1 = Image._tmo_param_1;
+ _tmo_param_2 = Image._tmo_param_2;
+ _tmo_param_3 = Image._tmo_param_3;
+ _tmo_param_4 = Image._tmo_param_4;
+
+ // clone the base class
+ fipImage::operator=(Image);
+ }
+ return *this;
+}
+
+HANDLE fipWinImage::copyToHandle() const {
+ HANDLE hMem = NULL;
+
+ if(_dib) {
+
+ // Get equivalent DIB size
+ long dib_size = sizeof(BITMAPINFOHEADER);
+ dib_size += FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD);
+ dib_size += FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib);
+
+ // Allocate a DIB
+ hMem = GlobalAlloc(GHND, dib_size);
+ BYTE *dib = (BYTE*)GlobalLock(hMem);
+
+ memset(dib, 0, dib_size);
+
+ BYTE *p_dib = (BYTE*)dib;
+
+ // Copy the BITMAPINFOHEADER
+
+ BITMAPINFOHEADER *bih = FreeImage_GetInfoHeader(_dib);
+ memcpy(p_dib, bih, sizeof(BITMAPINFOHEADER));
+ if(FreeImage_GetImageType(_dib) != FIT_BITMAP) {
+ // this hack is used to store the bitmap type in the biCompression member of the BITMAPINFOHEADER
+ SET_FREEIMAGE_MARKER((BITMAPINFOHEADER*)p_dib, _dib);
+ }
+ p_dib += sizeof(BITMAPINFOHEADER);
+
+ // Copy the palette
+
+ RGBQUAD *pal = FreeImage_GetPalette(_dib);
+ memcpy(p_dib, pal, FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD));
+ p_dib += FreeImage_GetColorsUsed(_dib) * sizeof(RGBQUAD);
+
+ // Copy the bitmap
+
+ BYTE *bits = FreeImage_GetBits(_dib);
+ memcpy(p_dib, bits, FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib));
+
+ GlobalUnlock(hMem);
+ }
+
+ return hMem;
+}
+
+BOOL fipWinImage::copyFromHandle(HANDLE hMem) {
+ BYTE *lpVoid = NULL;
+ BITMAPINFOHEADER *pHead = NULL;
+ RGBQUAD *pPalette = NULL;
+ BYTE *bits = NULL;
+ DWORD bitfields[3] = {0, 0, 0};
+
+ // Get a pointer to the bitmap
+ lpVoid = (BYTE *)GlobalLock(hMem);
+
+ // Get a pointer to the bitmap header
+ pHead = (BITMAPINFOHEADER *)lpVoid;
+
+ // Get a pointer to the palette
+ if(pHead->biBitCount < 16)
+ pPalette = (RGBQUAD *)(((BYTE *)pHead) + sizeof(BITMAPINFOHEADER));
+
+ // Get a pointer to the pixels
+ bits = ((BYTE*)pHead + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pHead->biClrUsed);
+
+ if(pHead->biCompression == BI_BITFIELDS) {
+ // Take into account the color masks that specify the red, green, and blue components (16- and 32-bit)
+ unsigned mask_size = 3 * sizeof(DWORD);
+ memcpy(&bitfields[0], bits, mask_size);
+ bits += mask_size;
+ }
+
+ if(lpVoid) {
+
+ // Allocate a new FIBITMAP
+
+ FREE_IMAGE_TYPE image_type = FIT_BITMAP;
+ // Use a hack to decide if the clipboard contains non standard bitmaps ...
+ switch(GET_FREEIMAGE_MARKER(pHead)) {
+ case FIT_UINT16:
+ case FIT_INT16:
+ case FIT_UINT32:
+ case FIT_INT32:
+ case FIT_FLOAT:
+ case FIT_DOUBLE:
+ case FIT_COMPLEX:
+ case FIT_RGB16:
+ case FIT_RGBA16:
+ case FIT_RGBF:
+ case FIT_RGBAF:
+ image_type = GET_FREEIMAGE_MARKER(pHead);
+ break;
+ }
+ if(!setSize(image_type, (WORD)pHead->biWidth, (WORD)pHead->biHeight, pHead->biBitCount, bitfields[2], bitfields[1], bitfields[0])) {
+ GlobalUnlock(lpVoid);
+ return FALSE;
+ }
+
+ // Copy the bitmap header
+ memcpy(FreeImage_GetInfoHeader(_dib), pHead, sizeof(BITMAPINFOHEADER));
+
+
+ // Copy the palette
+ memcpy(FreeImage_GetPalette(_dib), pPalette, pHead->biClrUsed * sizeof(RGBQUAD));
+
+ // Copy the bitmap
+ memcpy(FreeImage_GetBits(_dib), bits, FreeImage_GetPitch(_dib) * FreeImage_GetHeight(_dib));
+
+ GlobalUnlock(lpVoid);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL fipWinImage::copyFromBitmap(HBITMAP hbmp) {
+ if(hbmp) {
+ int Success;
+ BITMAP bm;
+ // Get informations about the bitmap
+ GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm);
+ // Create the image
+ setSize(FIT_BITMAP, (WORD)bm.bmWidth, (WORD)bm.bmHeight, (WORD)bm.bmBitsPixel);
+
+ // The GetDIBits function clears the biClrUsed and biClrImportant BITMAPINFO members (dont't know why)
+ // So we save these infos below. This is needed for palettized images only.
+ int nColors = FreeImage_GetColorsUsed(_dib);
+
+ // Create a device context for the bitmap
+ HDC dc = GetDC(NULL);
+ // Copy the pixels
+ Success = GetDIBits(dc, // handle to DC
+ hbmp, // handle to bitmap
+ 0, // first scan line to set
+ FreeImage_GetHeight(_dib), // number of scan lines to copy
+ FreeImage_GetBits(_dib), // array for bitmap bits
+ FreeImage_GetInfo(_dib), // bitmap data buffer
+ DIB_RGB_COLORS // RGB
+ );
+ if(Success == 0) {
+ FreeImage_OutputMessageProc(FIF_UNKNOWN, "Error : GetDIBits failed");
+ ReleaseDC(NULL, dc);
+ return FALSE;
+ }
+ ReleaseDC(NULL, dc);
+
+ // restore BITMAPINFO members
+
+ FreeImage_GetInfoHeader(_dib)->biClrUsed = nColors;
+ FreeImage_GetInfoHeader(_dib)->biClrImportant = nColors;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL fipWinImage::copyToClipboard(HWND hWndNewOwner) const {
+ HANDLE hDIB = copyToHandle();
+
+ if(OpenClipboard(hWndNewOwner)) {
+ if(EmptyClipboard()) {
+ if(SetClipboardData(CF_DIB, hDIB) == NULL) {
+ MessageBox(hWndNewOwner, "Unable to set Clipboard data", "FreeImage", MB_ICONERROR);
+ CloseClipboard();
+ return FALSE;
+ }
+ }
+ }
+ CloseClipboard();
+
+ return TRUE;
+}
+
+BOOL fipWinImage::pasteFromClipboard() {
+ if(!IsClipboardFormatAvailable(CF_DIB))
+ return FALSE;
+
+ if(OpenClipboard(NULL)) {
+ HANDLE hDIB = GetClipboardData(CF_DIB);
+ copyFromHandle(hDIB);
+ CloseClipboard();
+ return TRUE;
+ }
+ CloseClipboard();
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////
+// Screen capture
+
+BOOL fipWinImage::captureWindow(HWND hWndApplicationWindow, HWND hWndSelectedWindow) {
+ int xScreen, yScreen, xshift, yshift;
+ RECT r;
+
+ // Get window size
+ GetWindowRect(hWndSelectedWindow, &r);
+
+ // Check if the window is out of the screen or maximixed
+ xshift = 0;
+ yshift = 0;
+ xScreen = GetSystemMetrics(SM_CXSCREEN);
+ yScreen = GetSystemMetrics(SM_CYSCREEN);
+ if(r.right > xScreen)
+ r.right = xScreen;
+ if(r.bottom > yScreen)
+ r.bottom = yScreen;
+ if(r.left < 0) {
+ xshift = -r.left;
+ r.left = 0;
+ }
+ if(r.top < 0){
+ yshift = -r.top;
+ r.top = 0;
+ }
+
+ int width = r.right - r.left;
+ int height = r.bottom - r.top;
+
+ if(width <= 0 || height <= 0)
+ return FALSE;
+
+ // Hide the application window.
+ ShowWindow(hWndApplicationWindow, SW_HIDE);
+ // Bring the window at the top most level
+ SetWindowPos(hWndSelectedWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ // Give enough time to refresh the window
+ Sleep(500);
+
+ // Prepare the DCs
+ HDC dstDC = GetDC(NULL);
+ HDC srcDC = GetWindowDC(hWndSelectedWindow); // full window (GetDC(hWndSelectedWindow) = clientarea)
+ HDC memDC = CreateCompatibleDC(dstDC);
+
+ // Copy the screen to the bitmap
+ HBITMAP bm = CreateCompatibleBitmap(dstDC, width, height);
+ HBITMAP oldbm = (HBITMAP)SelectObject(memDC, bm);
+ BitBlt(memDC, 0, 0, width, height, srcDC, xshift, yshift, SRCCOPY);
+
+ // Redraw the application window.
+ ShowWindow(hWndApplicationWindow, SW_SHOW);
+
+ // Restore the position
+ SetWindowPos(hWndSelectedWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ SetWindowPos(hWndApplicationWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+
+ // Convert the HBITMAP to a FIBITMAP
+ copyFromBitmap(bm);
+
+ // Free objects
+ DeleteObject(SelectObject(memDC, oldbm));
+ DeleteDC(memDC);
+
+ // Convert 32-bit images to 24-bit
+ if(getBitsPerPixel() == 32) {
+ convertTo24Bits();
+ }
+
+ return TRUE;
+}
+
+
+///////////////////////////////////////////////////////////////////
+// Painting operations
+
+void fipWinImage::drawEx(HDC hDC, RECT& rcDest, BOOL useFileBkg, RGBQUAD *appBkColor, FIBITMAP *bg) const {
+ // Convert to a standard bitmap if needed
+ if(_bHasChanged) {
+ if(_bDeleteMe) {
+ FreeImage_Unload(_display_dib);
+ _display_dib = NULL;
+ _bDeleteMe = FALSE;
+ }
+
+ FREE_IMAGE_TYPE image_type = getImageType();
+ if(image_type == FIT_BITMAP) {
+ BOOL bHasBackground = FreeImage_HasBackgroundColor(_dib);
+ BOOL bIsTransparent = FreeImage_IsTransparent(_dib);
+
+ if(!bIsTransparent && (!bHasBackground || !useFileBkg)) {
+ // Copy pointer
+ _display_dib = _dib;
+ }
+ else {
+ // Create the transparent / alpha blended image
+ _display_dib = FreeImage_Composite(_dib, useFileBkg, appBkColor, bg);
+ if(_display_dib) {
+ // Remember to delete _display_dib
+ _bDeleteMe = TRUE;
+ } else {
+ // Something failed: copy pointers
+ _display_dib = _dib;
+ }
+ }
+ } else {
+ // Convert to a standard dib for display
+
+ if(image_type == FIT_COMPLEX) {
+ // Convert to type FIT_DOUBLE
+ FIBITMAP *dib_double = FreeImage_GetComplexChannel(_dib, FICC_MAG);
+ // Convert to a standard bitmap (linear scaling)
+ _display_dib = FreeImage_ConvertToStandardType(dib_double, TRUE);
+ // Free image of type FIT_DOUBLE
+ FreeImage_Unload(dib_double);
+ } else if((image_type == FIT_RGBF) || (image_type == FIT_RGBAF) || (image_type == FIT_RGB16)) {
+ // Apply a tone mapping algorithm and convert to 24-bit
+ switch(_tmo) {
+ case FITMO_REINHARD05:
+ _display_dib = FreeImage_TmoReinhard05Ex(_dib, _tmo_param_1, _tmo_param_2, _tmo_param_3, _tmo_param_4);
+ break;
+ default:
+ _display_dib = FreeImage_ToneMapping(_dib, _tmo, _tmo_param_1, _tmo_param_2);
+ break;
+ }
+ } else if(image_type == FIT_RGBA16) {
+ // Convert to 32-bit
+ FIBITMAP *dib32 = FreeImage_ConvertTo32Bits(_dib);
+ if(dib32) {
+ // Create the transparent / alpha blended image
+ _display_dib = FreeImage_Composite(dib32, useFileBkg, appBkColor, bg);
+ FreeImage_Unload(dib32);
+ }
+ } else {
+ // Other cases: convert to a standard bitmap (linear scaling)
+ _display_dib = FreeImage_ConvertToStandardType(_dib, TRUE);
+ }
+ // Remember to delete _display_dib
+ _bDeleteMe = TRUE;
+ }
+
+ _bHasChanged = FALSE;
+ }
+
+ // Draw the dib
+ SetStretchBltMode(hDC, COLORONCOLOR);
+ StretchDIBits(hDC, rcDest.left, rcDest.top,
+ rcDest.right-rcDest.left, rcDest.bottom-rcDest.top,
+ 0, 0, FreeImage_GetWidth(_display_dib), FreeImage_GetHeight(_display_dib),
+ FreeImage_GetBits(_display_dib), FreeImage_GetInfo(_display_dib), DIB_RGB_COLORS, SRCCOPY);
+
+}
+
+void fipWinImage::setToneMappingOperator(FREE_IMAGE_TMO tmo, double first_param, double second_param, double third_param, double fourth_param) {
+ // avoid costly operations if possible ...
+ if((_tmo != tmo) || (_tmo_param_1 != first_param) || (_tmo_param_2 != second_param) || (_tmo_param_3 != third_param) || (_tmo_param_4 != fourth_param)) {
+ _tmo = tmo;
+ _tmo_param_1 = first_param;
+ _tmo_param_2 = second_param;
+ _tmo_param_3 = third_param;
+ _tmo_param_4 = fourth_param;
+
+ FREE_IMAGE_TYPE image_type = getImageType();
+ if((image_type == FIT_RGBF) || (image_type == FIT_RGB16)) {
+ _bHasChanged = TRUE;
+ }
+ }
+}
+
+void fipWinImage::getToneMappingOperator(FREE_IMAGE_TMO *tmo, double *first_param, double *second_param, double *third_param, double *fourth_param) const {
+ *tmo = _tmo;
+ *first_param = _tmo_param_1;
+ *second_param = _tmo_param_2;
+ *third_param = _tmo_param_3;
+ *fourth_param = _tmo_param_4;
+}
+
+
+#endif // _WIN32
diff --git a/Wrapper/FreeImagePlus/test/fipTest.2003.sln b/Wrapper/FreeImagePlus/test/fipTest.2003.sln
new file mode 100644
index 0000000..be2ce0c
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTest.2003.sln
@@ -0,0 +1,23 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fipTest", "fipTest.2003.vcproj", "{D1ABE87A-65A2-4AA2-9C94-73B9B4898C3B}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectDependencies) = postSolution
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {D1ABE87A-65A2-4AA2-9C94-73B9B4898C3B}.Debug.ActiveCfg = Debug|Win32
+ {D1ABE87A-65A2-4AA2-9C94-73B9B4898C3B}.Debug.Build.0 = Debug|Win32
+ {D1ABE87A-65A2-4AA2-9C94-73B9B4898C3B}.Release.ActiveCfg = Release|Win32
+ {D1ABE87A-65A2-4AA2-9C94-73B9B4898C3B}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
diff --git a/Wrapper/FreeImagePlus/test/fipTest.2003.vcproj b/Wrapper/FreeImagePlus/test/fipTest.2003.vcproj
new file mode 100644
index 0000000..f0ba3ce
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTest.2003.vcproj
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="fipTest"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/fipTest.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="FreeImaged.lib FreeImagePlusd.lib"
+ OutputFile=".\Debug/fipTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/fipTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/fipTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/fipTest.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="FreeImage.lib FreeImagePlus.lib"
+ OutputFile=".\Release/fipTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/fipTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/fipTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="fipTest.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fipTest.h">
+ </File>
+ <File
+ RelativePath="fipTestMemIO.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fipTestMPage.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImagePlus/test/fipTest.2005.vcproj b/Wrapper/FreeImagePlus/test/fipTest.2005.vcproj
new file mode 100644
index 0000000..f0ba3ce
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTest.2005.vcproj
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="fipTest"
+ SccProjectName=""
+ SccLocalPath="">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="5"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Debug/fipTest.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="FreeImaged.lib FreeImagePlusd.lib"
+ OutputFile=".\Debug/fipTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ ProgramDatabaseFile=".\Debug/fipTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Debug/fipTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="1"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="1"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ StringPooling="TRUE"
+ RuntimeLibrary="4"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="2"
+ PrecompiledHeaderFile=".\Release/fipTest.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="FreeImage.lib FreeImagePlus.lib"
+ OutputFile=".\Release/fipTest.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ ProgramDatabaseFile=".\Release/fipTest.pdb"
+ SubSystem="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ TypeLibraryName=".\Release/fipTest.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1036"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath="fipTest.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fipTest.h">
+ </File>
+ <File
+ RelativePath="fipTestMemIO.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="fipTestMPage.cpp">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions=""
+ BasicRuntimeChecks="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ PreprocessorDefinitions=""/>
+ </FileConfiguration>
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/Wrapper/FreeImagePlus/test/fipTest.cpp b/Wrapper/FreeImagePlus/test/fipTest.cpp
new file mode 100644
index 0000000..47c263c
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTest.cpp
@@ -0,0 +1,66 @@
+// ==========================================================
+// FreeImagePlus Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "fipTest.h"
+
+// ----------------------------------------------------------
+
+/**
+ FreeImage error handler
+ @param fif Format / Plugin responsible for the error
+ @param message Error message
+*/
+void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
+ printf("\n*** ");
+ printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
+ printf(message);
+ printf(" ***\n");
+}
+
+// ----------------------------------------------------------
+
+int main(int argc, char *argv[]) {
+ char *lpszTestFile = "test.jpg";
+ char *lpszMultiPage = "test.tif";
+
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_Initialise();
+#endif
+
+ // initialize our own FreeImage error handler
+
+ FreeImage_SetOutputMessage(FreeImageErrorHandler);
+
+ // test memory IO
+ testMemIO(lpszTestFile);
+
+ // test multipage IO
+ testMultiPage(lpszMultiPage);
+
+#if defined(FREEIMAGE_LIB) || !defined(WIN32)
+ FreeImage_DeInitialise();
+#endif
+
+ return 0;
+}
+
+
diff --git a/Wrapper/FreeImagePlus/test/fipTest.h b/Wrapper/FreeImagePlus/test/fipTest.h
new file mode 100644
index 0000000..3f8325b
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTest.h
@@ -0,0 +1,53 @@
+// ==========================================================
+// FreeImagePlus Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+#ifndef TEST_FREEIMAGEPLUS_API_H
+#define TEST_FREEIMAGEPLUS_API_H
+
+#include "../FreeImagePlus.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/stat.h>
+
+#include <iostream>
+
+// --------------------------------------------------------------------------
+// Memory IO test scripts
+
+/// Test saving to a memory stream
+void testSaveMemIO(const char *lpszPathName);
+/// Test loading from a buffer attached to a memory stream
+void testLoadMemIO(const char *lpszPathName);
+/// Test extracting a memory buffer from a memory stream
+void testAcquireMemIO(const char *lpszPathName);
+/// Test Loading / Saving from / to a memory stream using fipImage
+void testImageMemIO(const char *lpszPathName);
+/// Test the above functions
+void testMemIO(const char *lpszPathName);
+
+// --------------------------------------------------------------------------
+// Multipage test scripts
+
+BOOL testCloneMultiPage(const char *input, const char *output, int output_flag);
+void testMultiPage(const char *lpszMultiPage);
+
+
+#endif // TEST_FREEIMAGEPLUS_API_H
diff --git a/Wrapper/FreeImagePlus/test/fipTestMPage.cpp b/Wrapper/FreeImagePlus/test/fipTestMPage.cpp
new file mode 100644
index 0000000..3d84edc
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTestMPage.cpp
@@ -0,0 +1,76 @@
+// ==========================================================
+// FreeImagePlus Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "fipTest.h"
+
+// --------------------------------------------------------------------------
+// Multipage test scripts
+
+BOOL testCloneMultiPage(const char *input, const char *output, int output_flag) {
+
+ BOOL bMemoryCache = TRUE;
+
+ fipMultiPage src(bMemoryCache);
+ fipMultiPage dst(bMemoryCache);
+
+ // You MUST declare this before using it.
+ // We will use the assignement operator, i.e. operator=()
+ fipImage image;
+
+ // Open src file (read-only, use memory cache)
+ src.open(input, FALSE, TRUE);
+
+ if(src.isValid()) {
+ // Open dst file (creation, use memory cache)
+ dst.open(output, TRUE, FALSE);
+
+ // Get src page count
+ int count = src.getPageCount();
+
+ // Clone src to dst
+ for(int page = 0; page < count; page++) {
+ // Load the bitmap at position 'page'
+ image = src.lockPage(page);
+ if(image.isValid()) {
+ // add a new bitmap to dst
+ dst.appendPage(image);
+ // Unload the bitmap (do not apply any change to src)
+ src.unlockPage(image, FALSE);
+ }
+ }
+
+ // Close src
+ src.close(0);
+ // Save and close dst
+ dst.close(output_flag);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void testMultiPage(const char *lpszMultiPage) {
+ testCloneMultiPage(lpszMultiPage, "clone.tif", 0);
+}
+
+
diff --git a/Wrapper/FreeImagePlus/test/fipTestMemIO.cpp b/Wrapper/FreeImagePlus/test/fipTestMemIO.cpp
new file mode 100644
index 0000000..74ed949
--- /dev/null
+++ b/Wrapper/FreeImagePlus/test/fipTestMemIO.cpp
@@ -0,0 +1,165 @@
+// ==========================================================
+// FreeImagePlus Test Script
+//
+// Design and implementation by
+// - Hervé Drolon (drolon@infonie.fr)
+//
+// This file is part of FreeImage 3
+//
+// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+// THIS DISCLAIMER.
+//
+// Use at your own risk!
+// ==========================================================
+
+
+#include "fipTest.h"
+
+// --------------------------------------------------------------------------
+// Memory IO test scripts
+
+/**
+Test saving to a memory stream
+*/
+void testSaveMemIO(const char *lpszPathName) {
+
+ // load a regular file
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);
+
+ // open a memory handle
+ fipMemoryIO memIO;
+
+ // save the file to memory
+ memIO.save(fif, dib, 0);
+
+ // at this point, memIO contains the entire PNG data in memory.
+ // the amount of space used by the memory is equal to file_size
+ long file_size = memIO.tell();
+ assert(file_size != 0);
+
+ // its easy load an image from memory as well
+
+ // seek to the start of the memory stream
+ memIO.seek(0L, SEEK_SET);
+
+ // get the file type
+ FREE_IMAGE_FORMAT mem_fif = memIO.getFileType();
+
+ // load an image from the memory handle
+ FIBITMAP *check = memIO.load(mem_fif, 0);
+
+ // save as a regular file
+ FreeImage_Save(FIF_PNG, check, "dump.png", PNG_DEFAULT);
+
+ FreeImage_Unload(check);
+ FreeImage_Unload(dib);
+
+ // The memIO object will be destroyed automatically
+}
+
+/**
+Test loading from a buffer attached to a memory stream
+*/
+void testLoadMemIO(const char *lpszPathName) {
+ struct stat buf;
+ int result;
+
+ // get data associated with lpszPathName
+ result = stat(lpszPathName, &buf);
+ if(result == 0) {
+ // allocate a memory buffer and load temporary data
+ BYTE *mem_buffer = (BYTE*)malloc(buf.st_size * sizeof(BYTE));
+ if(mem_buffer) {
+ FILE *stream = fopen(lpszPathName, "rb");
+ if(stream) {
+ fread(mem_buffer, sizeof(BYTE), buf.st_size, stream);
+ fclose(stream);
+
+ // attach the binary data to a memory stream
+ fipMemoryIO memIO(mem_buffer, buf.st_size);
+
+ // get the file type
+ FREE_IMAGE_FORMAT fif = memIO.getFileType();
+
+ // load an image from the memory stream
+ FIBITMAP *check = memIO.load(fif, PNG_DEFAULT);
+
+ // save as a regular file
+ FreeImage_Save(FIF_PNG, check, "blob.png", PNG_DEFAULT);
+
+ // close the stream (memIO is destroyed)
+ }
+
+ // user is responsible for freeing the data
+ free(mem_buffer);
+ }
+ }
+}
+
+/**
+Test extracting a memory buffer from a memory stream
+*/
+void testAcquireMemIO(const char *lpszPathName) {
+
+ // load a regular file
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFileType(lpszPathName);
+ FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, 0);
+
+ // open and allocate a memory stream
+ fipMemoryIO memIO;
+
+ // save the file to memory
+ memIO.save(FIF_PNG, dib, PNG_DEFAULT);
+
+ // get the buffer from the memory stream
+ BYTE *mem_buffer = NULL;
+ DWORD size_in_bytes = 0;
+
+ memIO.acquire(&mem_buffer, &size_in_bytes);
+
+ // save the buffer in a file stream
+ FILE *stream = fopen("buffer.png", "wb");
+ if(stream) {
+ fwrite(mem_buffer, sizeof(BYTE), size_in_bytes, stream);
+ fclose(stream);
+ }
+
+ // close and free the memory stream (memIO is destroyed)
+}
+
+/**
+Test Loading / Saving from / to a memory stream using fipImage
+*/
+void testImageMemIO(const char *lpszPathName) {
+ BOOL bSuccess = FALSE;
+
+ fipMemoryIO memIO;
+ fipImage image;
+
+ // load a regular file
+ bSuccess = image.load(lpszPathName);
+ if(bSuccess) {
+ // save the file to a memory stream
+ bSuccess = image.saveToMemory(FIF_PNG, memIO, PNG_DEFAULT);
+
+ // load the file from the memory stream
+ memIO.seek(0L, SEEK_SET);
+ bSuccess = image.loadFromMemory(memIO, 0);
+ }
+}
+
+void testMemIO(const char *lpszPathName) {
+ testSaveMemIO(lpszPathName);
+ testLoadMemIO(lpszPathName);
+ testAcquireMemIO(lpszPathName);
+ testImageMemIO(lpszPathName);
+}
+
diff --git a/Wrapper/VB6/awk_script/genbas.sh b/Wrapper/VB6/awk_script/genbas.sh
new file mode 100755
index 0000000..3becd65
--- /dev/null
+++ b/Wrapper/VB6/awk_script/genbas.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+HDR=../../../Source/FreeImage.h
+BAS=../modFreeImage.bas
+DLL=FreeImage.dll
+
+echo Attribute VB_Name = \"FreeImage\" > $BAS
+echo Option Explicit >> $BAS
+
+echo >> $BAS
+gcc -E -P -dD $HDR | egrep '^#[ ]*define[ ]+[A-Z][0-9A-Z_]*[ ]+([0-9]+|0x[0-9A-Fa-f]+|"[^"]*")' | awk '{sub(/0x/,"\\&H",$3);if($2!="TRUE"&&$2!="FALSE"&&$2!="NULL")printf("Const %s As %s = %s\n",$2,substr($3,1,1)=="\""?"String":"Long",$3);}' >> $BAS
+
+echo >> $BAS
+gcc -E -P $HDR | indent -kr | tr -s '\n' | awk '{if(e&&$0~"^}"){e=0;printf("End Enum\n");}if(e){printf("\t%s",$1);if($2=="="){sub(/,/,"",$3);printf(" = %s",$3);}printf("\n");}if($0~"^enum "){e=1;printf("Public Enum %s\n",$2);}}' >> $BAS
+
+echo >> $BAS
+gcc -E -P $HDR | indent -kr | tr -s '\n' | awk '{if(e&&$0~"^}"){e=0;if(n==""){n=$2;sub(/,|;/,"",n);}printf("Public Type %s\n%sEnd Type\n",n,s);}if(e){if(substr($2,1,1)=="*")$1=$1 " *";gsub(/;|\*/,"",$2);sub(/\[1\]/,"(0)",$2);if($1=="BYTE")$1="Byte";else if($1=="WORD")$1="Integer";else if($1=="double")$1="Double";else if($1!="BITMAPINFOHEADER"&&$1!="RGBQUAD") $1="Long";s=s "\t" $2 " As " $1 "\n";}if($0~"^struct "){e=1;n=$2;s="";}if($0~"^typedef struct [^ ]+ {"){e=1;n="";s=""}}' >> $BAS
+
+echo >> $BAS
+export DLL
+grep ^DLL_API $HDR | sed 's/DLL_API //;s/ *DLL_CALLCONV /,/;s/ FI_DEFAULT(\([^)]*\))/=\1/g;s/(/,/g;s/)/,/g' | awk -F"," -f genbasfuncs.awk >> $BAS
diff --git a/Wrapper/VB6/awk_script/genbasfuncs.awk b/Wrapper/VB6/awk_script/genbasfuncs.awk
new file mode 100644
index 0000000..876b68a
--- /dev/null
+++ b/Wrapper/VB6/awk_script/genbasfuncs.awk
@@ -0,0 +1,136 @@
+# this awk script helps create the vb6 declarations
+function splittypenamedefault(s,tnd, i,t,n,d,a)
+{
+ i = index(s,"=");
+ if(i>0) {
+ d = substr(s,i+1);
+ s = substr(s,1,i-1);
+ } else {
+ d = "";
+ }
+ for(i=length(s);substr(s,i,1)~/[A-Za-z0-9_]/&&i>0;i--) { }
+ if(i>0) {
+ t = substr(s,1,i);
+ n = substr(s,i+1);
+ if(t~/\/\*.*\*\//) {
+ split(t,a,/\/\*/);
+ t = a[2];
+ split(t,a,/\*\//);
+ t = a[1];
+ }
+ if(substr(t,1,1)==" ") {
+ t = substr(t,2);
+ }
+ if(substr(t,length(t),1)==" ") {
+ t = substr(t,1,length(t)-1);
+ }
+ } else {
+ t = s;
+ n = "";
+ }
+ if(t=="...") {
+ n = "VarArgs()";
+ }
+ if(n=="type") {
+ n = n "_";
+ }
+ if(d=="FALSE"||d=="NULL") {
+ d = "0";
+ }
+ if(d=="TRUE") {
+ d = "1";
+ }
+ tnd[0] = t;
+ tnd[1] = n;
+ tnd[2] = d;
+}
+function vbpasstypesize(t,pts, a)
+{
+ if(t=="void") {
+ t = "";
+ } else if(t=="char"||t=="unsigned char") {
+ t = "ByVal,Byte,4";
+ } else if(t=="char *"||t=="unsigned char *"||t=="const char *"||t=="const char*") {
+ t = "ByVal,String,4";
+ } else if(t=="WORD") {
+ t = "ByVal,Integer,4";
+ } else if(t=="int"||t=="unsigned"||t=="unsigned int"||t=="long"||t=="unsigned long") {
+ t = "ByVal,Long,4";
+ } else if(t=="void *"||t=="const void *"||t=="int *"||t=="unsigned int *"||t=="long *"||t=="unsigned long *") {
+ t = "ByRef,Long,4";
+ } else if(t=="float") {
+ t = "ByVal,Single,4";
+ } else if(t=="float *") {
+ t = "ByRef,Single,4";
+ } else if(t=="double") {
+ t = "ByVal,Double,8";
+ } else if(t=="double *") {
+ t = "ByRef,Double,4";
+ } else if(t=="wchar_t *") {
+ t = "ByVal,Long,4";
+ } else if(t=="BYTE") {
+ t = "ByVal,Byte,4";
+ } else if(t=="BOOL"||t=="DWORD") {
+ t = "ByVal,Long,4";
+ } else if(t=="BYTE *"||t=="DWORD *") {
+ t = "ByRef,Long,4";
+ } else if(t=="FREE_IMAGE_FORMAT"||t=="FREE_IMAGE_TYPE"||t=="FREE_IMAGE_COLOR_TYPE"||t=="FREE_IMAGE_QUANTIZE"||t=="FREE_IMAGE_DITHER"||t=="FREE_IMAGE_FILTER"||t=="FREE_IMAGE_COLOR_CHANNEL"||t=="FREE_IMAGE_MDMODEL"||t=="FREE_IMAGE_MDTYPE") {
+ t = "ByVal," t ",4";
+ } else if(t=="FIBITMAP *"||t=="FIMULTIBITMAP *"||t=="RGBQUAD *"||t=="BITMAPINFO *"||t=="BITMAPINFOHEADER *"||t=="FIICCPROFILE *"||t=="FreeImageIO *"||t=="fi_handle"||t=="FITAG *"||t=="FIMEMORY *"||t=="FIMETADATA *") {
+ t = "ByVal,Long,4";
+ } else if(t=="BYTE **"||t=="FITAG **") {
+ t = "ByRef,Long,4";
+ } else if(t=="FI_InitProc"||t=="FreeImage_OutputMessageFunction") {
+ t = "ByVal,Long,4";
+ } else if(t~/V:.*/) {
+ t = "ByVal," substr(t,3);
+ } else if(t~/R:.*/) {
+ t = "ByRef," substr(t,3);
+ } else if(t=="...") {
+ t = "ParamArray,Variant,0";
+ } else {
+ t = "UNKNOWN," t ",0";
+ }
+ split(t,a,/,/);
+ pts[0] = a[1];
+ pts[1] = a[2];
+ pts[2] = a[3];
+}
+{
+ printf("Public Declare ");
+ if($1=="void") {
+ printf("Sub");
+ } else {
+ printf("Function");
+ }
+ s = 0;
+ for(i=3; i<NF; i++) {
+ splittypenamedefault($(i),tnd);
+ vbpasstypesize(tnd[0],pts);
+ s += pts[2];
+ }
+ printf(" %s Lib \"%s\" Alias \"_%s@%d\" (",$2,ENVIRON["DLL"],$2,s);
+ for(i=3; i<NF; i++) {
+ splittypenamedefault($(i),tnd);
+ vbpasstypesize(tnd[0],pts);
+ if( pts[1] != "" ) {
+ if( tnd[2] != "" ) {
+ printf("Optional %s %s As %s = %s",pts[0],tnd[1],pts[1],tnd[2]);
+ } else {
+ printf("%s %s As %s",pts[0],tnd[1],pts[1]);
+ }
+ }
+ if( i != NF-1 ) {
+ printf(", ");
+ }
+ }
+ printf(")");
+ if($1!="void") {
+ vbpasstypesize($1,pts);
+ if( pts[1] == "String" ) {
+ pts[1] = "Long";
+ }
+ printf(" As %s",pts[1]);
+ }
+ printf("\n");
+}
diff --git a/Wrapper/VB6/awk_script/readme.txt b/Wrapper/VB6/awk_script/readme.txt
new file mode 100644
index 0000000..320129d
--- /dev/null
+++ b/Wrapper/VB6/awk_script/readme.txt
@@ -0,0 +1,14 @@
+This awk script is used to generate a VB6 module with all the VB6 declaration needed to call FreeImage functions.
+
+How to use this script
+----------------------
+Under Linux / Unix, just execute the following commands :
+
+chmod 755 genbas.sh
+./genbas.sh
+
+
+This will generate a file named modFreeImage.bas that you can include in your VB6 project in order to have access to all FreeImage functions.
+
+Ryan Rubley
+<ark42 at users.sourceforge.net>
diff --git a/Wrapper/VB6/mfreeimage/MFreeImage.bas b/Wrapper/VB6/mfreeimage/MFreeImage.bas
new file mode 100644
index 0000000..af68700
--- /dev/null
+++ b/Wrapper/VB6/mfreeimage/MFreeImage.bas
@@ -0,0 +1,11766 @@
+Attribute VB_Name = "MFreeImage"
+'// ==========================================================
+'// Visual Basic Wrapper for FreeImage 3
+'// Original FreeImage 3 functions and VB compatible derived functions
+'// Design and implementation by
+'// - Carsten Klein (cklein05@users.sourceforge.net)
+'//
+'// Main reference : Curland, Matthew., Advanced Visual Basic 6, Addison Wesley, ISBN 0201707128, (c) 2000
+'// Steve McMahon, creator of the excellent site vbAccelerator at http://www.vbaccelerator.com/
+'// MSDN Knowlede Base
+'//
+'// This file is part of FreeImage 3
+'//
+'// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
+'// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+'// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
+'// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
+'// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
+'// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
+'// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
+'// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
+'// THIS DISCLAIMER.
+'//
+'// Use at your own risk!
+'// ==========================================================
+
+'// ==========================================================
+'// CVS
+'// $Revision: 2.5 $
+'// $Date: 2009/09/08 17:02:32 $
+'// $Id: MFreeImage.bas,v 2.5 2009/09/08 17:02:32 cklein05 Exp $
+'// ==========================================================
+
+
+Option Explicit
+
+'--------------------------------------------------------------------------------
+' General notes on implementation and design
+'--------------------------------------------------------------------------------
+
+' General:
+
+' Most of the pointer type parameters used in the FreeImage API are actually
+' declared as Long in VB. That is also true for return values. 'Out' parameters
+' are declared ByRef, so they can receive the provided address of the pointer.
+' 'In' parameters are declared ByVal since in VB the Long variable is not a
+' pointer type but contains the address of the pointer.
+
+
+' Functions returning a special type:
+
+' Some of the following external function declarations of the FreeImage 3 functions
+' are declared Private. Additionally the token 'Int' is appended to the VB function
+' name, what means 'Internal' to avoid naming confusion. All of these return a value
+' of a certain type that can't be used with a declared function in VB directly but
+' would need the function to be declared in a type library. Since this wrapper module
+' should not depend on a compile time type library, these functions require some extra
+' work to be done and also a VB wrapper function to make them look like the C/C++
+' function.
+
+
+' Functions returning Strings:
+
+' Some of the declared FreeImage functions are defined as 'const char *' in C/C++
+' and so actually return a string pointer. Without using a type library for declaring
+' these functions, in VB it is impossible to declare these functions to return a
+' VB String type. So each of these functions is wrapped by a VB implemented function
+' named correctly according to the FreeImage API, actually returning a 'real' VB String.
+
+
+' Functions returning Booleans:
+
+' A Boolean is a numeric 32 bit value in both C/C++ and VB. In C/C++ TRUE is defined
+' as 1 whereas in VB True is -1 (all bits set). When a function is declared as 'Boolean'
+' in VB, the return value (all 32 bits) of the called function is just used "as is" and
+' maybe assigned to a VB boolean variable. A Boolean in VB is 'False' when the numeric
+' value is NULL (0) and 'True' in any other case. So, at a first glance, everything
+' would be great since both numeric values -1 (VB True) and 1 (C/C++ TRUE) are actually
+' 'True' in VB.
+' But, if you have a VB variable (or a function returning a Boolean) with just some bits
+' set and use the VB 'Not' operator, the result is not what you would expect. In this
+' case, if bTest is True, (Not bTest) is also True. The 'Not' operator just toggles all
+' bits by XOR-ing the value with -1. So, the result is not so surprisingly any more:
+' The C/C++ TRUE value is 0...0001. When all bits are XORed with 1, the result is
+' 1...1110 what is also not NULL (0) so this is still 'True' in VB.
+' The resolution is to convert these return values into real VB Booleans in a wrapper
+' function, one for each declared FreeImage function. Therefore each C/C++ BOOL
+' function is declared Private as xxxInt(...). A Public Boolean wrapper function
+' xxx(...) returns a real Boolean with 'xxx = (xxxInt(...) = 1)'.
+
+
+' Extended and derived functions:
+
+' Some of the functions are additionally provided in an extended, call it a more VB
+' friendly version, named '...Ex'. For example look at the 'FreeImage_GetPaletteEx'
+' function. Most of them are dealing with arrays and so actually return a VB style
+' array of correct type.
+
+' The wrapper also includes some derived functions that should make life easier for
+' not only a VB programmer.
+
+' Better VB interoperability is given by offering conversion between DIBs and
+' VB Picture objects. See the FreeImage_CreateFromOlePicture and
+' FreeImage_GetOlePicture functions.
+
+' Both known VB functions LoadPicture() and SavePicture() are provided in extended
+' versions calles LoadPictureEx() and SavePictureEx() offering the FreeImage 3´s
+' image file types.
+
+' The FreeImage 3 error handling is provided in VB after calling the VB specific
+' function FreeImage_InitErrorHandler()
+
+
+' Enumerations:
+
+' All of the enumaration members are additionally 'declared' as constants in a
+' conditional compiler directive '#If...#Then' block that is actually unreachable.
+' For example see:
+'
+' Public Enum FREE_IMAGE_QUANTIZE
+' FIQ_WUQUANT = 0 ' Xiaolin Wu color quantization algorithm
+' FIQ_NNQUANT = 1 ' NeuQuant neural-net quantization algorithm by Anthony Dekker
+' End Enum
+' #If False Then
+' Const FIQ_WUQUANT = 0
+' Const FIQ_NNQUANT = 1
+' #End If
+'
+' Since this module is supposed to be used directly in VB projects rather than in
+' compiled form (mybe through an ActiveX-DLL), this is for tweaking some ugly VB
+' behaviour regarding enumerations. Enum members are automatically adjusted in case
+' by the VB IDE whenever you type these members in wrong case. Since these are also
+' constants now, they are no longer adjusted to wrong case but always corrected
+' according to the definition of the constant. As the expression '#If False Then'
+' actually never comes true, these constants are not really defined either when running
+' in the VB IDE nor in compiled form.
+
+
+'--------------------------------------------------------------------------------
+' ToDo and known issues (unordered and with no priority)
+'--------------------------------------------------------------------------------
+
+' ToDo: more inline documentation for mask image creation and icon functions
+' needed
+
+'--------------------------------------------------------------------------------
+' Change Log
+'--------------------------------------------------------------------------------
+
+'* : fixed
+'- : removed
+'! : changed
+'+ : added
+'
+'September 08, 2009 - 2.5
+'! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 13 to match current version 3.13.0
+'+ [Carsten Klein] added load flag constant JPEG_EXIFROTATE and new member FILO_JPEG_EXIFROTATE to enumeration FREE_IMAGE_LOAD_OPTIONS.
+'+ [Carsten Klein] added support for the PFM image format.
+'+ [Carsten Klein] added support for the PICT and RAW image formats.
+'+ [Carsten Klein] added UNICODE functions FreeImage_JPEGTransformU and FreeImage_JPEGCropU.
+'+ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_OPTIONS, which contains options to specify colors, used with FreeImage_FillBackground and FreeImage_EnlargeCanvas.
+'+ [Carsten Klein] added function FreeImage_FillBackground: although this returns BOOL in C/C++, the VB version only returns a Long.
+'+ [Carsten Klein] added wrapper functions FreeImage_FillBackgroundEx and FreeImage_FillBackgroundByLong, taking an RGBQUAD and a Long 'Color' argument respectively and return a true VB Boolean.
+'+ [Carsten Klein] added function FreeImage_EnlargeCanvas.
+'+ [Carsten Klein] added functions FreeImage_AllocateEx and FreeImage_AllocateExT.
+'+ [Carsten Klein] added function FreeImage_TmoReinhard05Ex.
+'+ [Carsten Klein] added function FreeImage_Rotate.
+'+ [Carsten Klein] added wrapper function FreeImage_RotateIOP.
+'
+'! now FreeImage version 3.13.0
+'
+'March 18, 2009 - 2.4.2
+'+ [Carsten Klein] added enumeration FREE_IMAGE_FRAME_DISPOSAL_METHODS, which provides the frame disposal options needed to create animated GIF files.
+'
+'July 29, 2008 - 2.4.1
+'* [Carsten Klein] minor documentation updates
+'! [Carsten Klein] renamed member FICF_PALETTISED_8BPP of enumeration FREE_IMAGE_CONVERSION_FLAGS into FICF_PALLETISED_8BPP.
+'
+'June 30, 2008 - 2.4
+'* [Carsten Klein] fixed some minor issues in FreeImage_PaintTransparent()
+'
+'June 06, 2008 - 2.3
+'+ [Carsten Klein] added new compression flags to the JPEG and PNG plugins
+'! [Carsten Klein] renamed wrapper function FreeImage_CloneMetadata() to FreeImage_CloneMetadataEx(): now, there is a native function called FreeImage_CloneMetadata().
+'+ [Carsten Klein] added private and internal function declaration for FreeImage_CloneMetadata() along with it's public Boolean returning wrapper function.
+'- [Carsten Klein] removed the FreeImage_ColorQuantizeEx() stuff from both functions FreeImage_ConvertColorDepth() and FreeImage_ConvertColorDepthIOP(): removed parameters PaletteSize, ReserveSize and ReservePalette.
+'- [Carsten Klein] changed declaration of FreeImage_ColorQuantizeEx() to be a internal function private to the wrapper with an 'Int' appendix.
+'+ [Carsten Klein] added two more VB-friendly public wrapper functions FreeImage_ColorQuantizeEx() and FreeImage_ColorQuantizeExIOP().
+'+ [Carsten Klein] added wrapper function FreeImage_GetPalettePtr(): gets the pointer to a specified array of RGBQUADs: intended to be used together with any of the ColorQuantizeEx functions.
+'! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 11 to match current version 3.11.0
+'
+'! now FreeImage version 3.11.0
+'
+'December 14, 2007 - 2.2.1
+'+ [Carsten Klein] added constants for member 'biCompression' in BITMAPINFOHEADER struct
+'+ [Carsten Klein] added wrapper function FreeImage_GetInfoHeaderEx(), which returns a fully populated BITMAPINFOHEADER struct for a bitmap.
+'* [Carsten Klein] fixed a bug in FreeImage_GetFileTypeFromMemoryEx(): now calls FreeImage_CloseMemory() releasing the hStream to prevent memory leaks.
+'+ [Carsten Klein] added wrapper function FreeImage_GetColorizedPalette(): returns a colorized greyscale palettte.
+'+ [Carsten Klein] added wrapper function FreeImage_Colorize(): applies a colorized greyscale palettte obtained from FreeImage_GetColorizedPalette() to a bitmap.
+'+ [Carsten Klein] added wrapper function FreeImage_Sepia(): calls FreeImage_Colorize() with proper parameters to apply a so called sepia palette to a bitmap.
+'
+'December 12, 2007 - 2.2
+'* [Carsten Klein] fixed a small bug in FreeImage_PaintTransparent, which now calls function FreeImage_ConvertTo32Bits instead of FreeImage_ConvertTo32Bits2.
+'
+'November 15, 2007 - 2.1
+'* [Carsten Klein] adjusted page numbers of the API documentation in FreeImage function declarations to match FreeImage 3.10.0 API documentation
+'- [Carsten Klein] removed parameter 'bUnloadSource' from function FreeImage_GetOlePictureIcon(): an hIcon should not be destroyed if OleCreatePictureIndirect() is called with fOwn = True.
+'! [Carsten Klein] refactored FreeImage_GetOlePicture(): now relies on FreeImage_GetBitmap().
+'
+'November 10, 2007 - 2.0.8
+'! [Carsten Klein] changed declaration of FreeImage_SetOutputMessage(): now points transparently to the __stdcall version of this function in the library.
+'+ [Carsten Klein] added function declaraton for FreeImage_MultigridPoissonSolver().
+'+ [Carsten Klein] added function declaraton for FreeImage_GetTransparentIndex() and FreeImage_SetTransparentIndex().
+'+ [Carsten Klein] added private and internal function declaration for FreeImage_AdjustColors() along with it's public Boolean returning wrapper function.
+'+ [Carsten Klein] added function declaraton for FreeImage_GetAdjustColorsLookupTable().
+'+ [Carsten Klein] added wrapper function FreeImage_GetAdjustColorsLookupTableEx(): this takes a real VB style Byte array ton receive the lookup table created.
+'+ [Carsten Klein] added function declaraton for FreeImage_ApplyColorMapping().
+'+ [Carsten Klein] added wrapper function FreeImage_ApplyColorMappingEx(): this takes a real VB style RGBQUAD array.
+'+ [Carsten Klein] added function declaratons for FreeImage_SwapColors() and FreeImage_SwapColorsByLong().
+'+ [Carsten Klein] added function declaraton for FreeImage_ApplyIndexMapping().
+'+ [Carsten Klein] added wrapper function FreeImage_ApplyIndexMappingEx(): this takes a real VB style Byte array.
+'+ [Carsten Klein] added function declaraton for FreeImage_SwapPaletteIndices().
+'
+'November 05, 2007 - 2.0.7
+'+ [Carsten Klein] added 4 bit color depth to both function pGetNextColorDepth() and pGetPrevousColorDepth()
+'- [Carsten Klein] removed member FICF_PREPARE_RESCALE from enumeration FREE_IMAGE_CONVERSION_FLAGS
+'- [Carsten Klein] removed all references to FICF_PREPARE_RESCALE: Converting color depth before rescaling an image is no longer performed by the wrapper. Since FreeImage now transparently converts color depth on rescaling, doing this in the wrapper is no longer needed.
+'! [Carsten Klein] refactored wrapper function FreeImage_ConvertColorDepth(): removed case FICF_PREPARE_RESCALE; is now more similar to C# wrapper's version of this function.
+'! [Carsten Klein] refactored wrapper function FreeImage_SaveEx(): removed case FICF_PREPARE_RESCALE; is now more similar to C# wrapper's version of this function.
+'
+'September 14, 2007 - 2.0.6
+'+ [Carsten Klein] added function declaration and Boolean wrapper function for FreeImage_PreMultiplyWithAlpha().
+'
+'July 26, 2007 - 2.0.5
+'+ [Carsten Klein] added wrapper function FreeImage_GetBitmap(): returns an HBITMAP created by the CreateDIBSection() function and so has the same color depth as the original DIB.
+'+ [Carsten Klein] added wrapper function FreeImage_GetBitmapForDevice(): returns an HBITMAP created by the CreateDIBitmap() function and so has the same color depth as the specified reference DC or as the desktop, if the 'hDC' parameter was omitted.
+'- [Carsten Klein] removed function declaration for GetWindowDC(): this function is no longer used.
+'* [Carsten Klein] fixed a bug in wrapper function FreeImage_IsExtensionValidForFIF(): string comparison now includes a comma.
+'* [Carsten Klein] fixed a bug in wrapper function FreeImage_IsFilenameValidForFIF(): string comparison now includes a comma.
+'
+'July 25, 2007 - 2.0.4
+'* [Carsten Klein] fixed a bug in function FreeImage_GetPaletteExClone(): now actually returns the palette as RGBQUAD array plus some other minor improvements
+'+ [Carsten Klein] added wrapper function FreeImage_GetPaletteExLongClone(): this function returns a VB style Byte array that is only wrapped around FreeImage's pointer to a DIB's transparency table.
+'+ [Carsten Klein] added wrapper function FreeImage_GetTransparencyTableEx(): this function returns a VB style Byte array that is only wrapped around FreeImage's pointer to a DIB's transparency table.
+'! [Carsten Klein] changed name of wrapper function FreeImage_GetTransparencyTableEx(): this function is now named FreeImage_GetTransparencyTableExClone(), since it actually returns a clone (deep copy) of an image's transparency table (compare with FreeImage_GetPaletteExClone()).
+'+ [Carsten Klein] added wrapper function FreeImage_SetPalette(): sets an image's palette through a VB style RGBQUAD array.
+'+ [Carsten Klein] added wrapper function FreeImage_SetPaletteLong(): sets an image's palette through a VB style Long array.
+'+ [Carsten Klein] added function declaration for CreateDIBsection()
+'+ [Carsten Klein] added function declaration for DeleteDC()
+'* [Carsten Klein] fixed a bug in wrapper function FreeImage_CreateFromScreen(): now the memory DC is deleted with the DeleteDC() function and no longer with the DeleteObject() function.
+'
+'July 05, 2007 - 2.0.3
+'+ [Carsten Klein] added wrapper function FreeImage_GetFileTypeFromMemoryEx(): more VB friendly version of FreeImage_GetFileTypeFromMemory() which may take an array rather than a FIMEMORY stream.
+'
+'May 21, 2007 - 2.0.2
+'! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 10 to match current version 3.10.0
+'! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 0 to match current version 3.10.0
+'+ [Carsten Klein] added image format constants FIF_EXR, FIF_J2K and FIF_JP2 to enumeration FREE_IMAGE_FORMAT.
+'+ [Carsten Klein] added tone mapping operator constant FITMO_FATTAL02 to enumeration FREE_IMAGE_TMO.
+'+ [Carsten Klein] added save option constants J2K_DEFAULT and JP2_DEFAULT for JPEG2000 format.
+'+ [Carsten Klein] added save option constants EXR_DEFAULT, EXR_FLOAT, EXR_NONE, EXR_ZIP, EXR_PIZ, EXR_PXR24, EXR_B44 and EXR_LC for EXR format.
+'+ [Carsten Klein] added save option constants for EXR format to enumeration FREE_IMAGE_SAVE_OPTIONS.
+'+ [Carsten Klein] added declared function FreeImage_TmoFattal02(): adds support for Gradient domain high dynamic range compression (R. Fattal, 2002)
+'
+'! now FreeImage version 3.10.0
+'
+'February 24, 2007 - 2.0.1
+'* [Carsten Klein] fixed a bug in function FreeImage_CreateFromScreen(): now size of image created is according to window to be captured if parameter 'hwnd' <> 0.
+'+ [Carsten Klein] added parameter 'bClientAreaOnly' to function FreeImage_CreateFromScreen().
+'+ [Carsten Klein] added blitting option 'CAPTUREBLT' when calling function BitBlt() in function FreeImage_CreateFromScreen().
+'- [Carsten Klein] removed unused variable 'hDIB' from functions FreeImage_CreateFromScreen() and FreeImage_LoadEx(). Thanks to Bruce Rusk for pointing that out.
+'
+'February 16, 2007 - 2.0
+'! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 3 to match current version 3.9.3
+'! [Carsten Klein] changed JPEG load/save flag option values: changed constants and both enumerations FREE_IMAGE_SAVE_OPTIONS and FREE_IMAGE_SAVE_OPTIONS.
+'+ [Carsten Klein] added ICC Color Profile support:
+'! changed signature of declared function FreeImage_GetICCProfile(): is now declared 'Private' and suffixed with '...Int()'.
+'+ added wrapper function FreeImage_GetICCProfile(): is the public wrapper function for private function FreeImage_GetICCProfileInt(), returing a real FIICCPROFILE structure.
+'+ added constant FREE_IMAGE_ICC_COLOR_MODEL_MASK.
+'+ added enumeration FREE_IMAGE_ICC_COLOR_MODEL.
+'+ added wrapper function FreeImage_GetICCProfileColorModel(): returns the color profile's color model (FIICCPROFILE.flags member).
+'+ added wrapper function FreeImage_GetICCProfileSize(): returns the color profile data's size in bytes.
+'+ added wrapper function FreeImage_GetICCProfileDataPointer(): returns the pointer to the color profile data.
+'+ added wrapper function FreeImage_HasICCProfile(): returns whether a color profile is available for a dib or not.
+'! [Carsten Klein] changed behaviour of wrapper function FreeImage_RescaleEx() and all it's derived functions: no clone is returned if the actual and desired image size are the same.
+'+ [Carsten Klein] added parameter 'bForceCloneCreation' to wrapper function FreeImage_RescaleEx() and all it's derived functions.
+'
+'! now FreeImage version 3.9.3
+'
+'January 09, 2007 - 1.9.4
+'! [Carsten Klein] changed scope of declared function FreeImage_GetFileTypeUInt(): is now private according to all other '...Int' functions wrapped by a VB-friendly function.
+'! [Carsten Klein] changed scope of declared function FreeImage_GetFIFFromFilenameUInt(): is now private according to all other '...Int' functions wrapped by a VB-friendly function.
+'! [Carsten Klein] changed signature of declared functions FreeImage_GetBackgroundColorInt() and FreeImage_SetBackgroundColorInt(): now both have a 'ByRef bkcolor As RGBQUAD' parameter instead of 'ByVal bkcolor As Long'.
+'+ [Carsten Klein] added declared functions FreeImage_GetBackgroundColorAsLongInt(): this has a 'ByRef bkcolor As Long' parameter and provides the background color as a Long value.
+'+ [Carsten Klein] added declared functions FreeImage_SetBackgroundColorAsLongInt(): this has a 'ByRef bkcolor As Long' parameter and takes the background color as a Long value.
+'! [Carsten Klein] changed signature of wrapper functions FreeImage_GetBackgroundColor() and FreeImage_SetBackgroundColor(): now both have a 'ByRef bkcolor As RGBQUAD' parameter instead of 'ByVal bkcolor As Long'.
+'+ [Carsten Klein] added wrapper functions FreeImage_GetBackgroundColorAsLong() and FreeImage_SetBackgroundColorAsLong(): both have a 'ByRef bkcolor As Long' parameter and so offer getting and setting the background color through a Long value.
+'+ [Carsten Klein] added wrapper functions FreeImage_GetBackgroundColorEx() and FreeImage_SetBackgroundColorEx(): both both take 4 ByRef Byte parameters 'Alpha', 'Red', 'Green' and 'Blue', one for each color component.
+'
+'January 05, 2007 - 1.9.3
+'+ [Carsten Klein] added wrapper function FreeImage_GetLockedPageNumbersEx(): this returns a real VB-style array of Longs containing the page numbers of all locked pages.
+'
+'January 02, 2007 - 1.9.2
+'* [Carsten Klein] fixed a bug in inline description of function FreeImage_GetPaletteEx(): now tells to use function FreeImage_DestroyLockedArrayRGBQUAD() to free an array returned by this function.
+'* [Carsten Klein] fixed some minor bugs in inline documentation.
+'* [Carsten Klein] fixed a serious bug in function FreeImage_SaveEx(): parameter 'bUnloadSource' is now interpreted correctly under all circumstances.
+'* [Carsten Klein] fixed some minor issues in function FreeImage_SaveEx().
+'
+'December 29, 2006 - 1.9.1
+'+ [Carsten Klein] added enumeration item FID_BAYER16x16: now supports Bayer ordered dispersed dot dithering (order 4 dithering matrix).
+'
+'October 31, 2006 - 1.9
+'* [Carsten Klein] adjusted page numbers of the API documentation in header comments in FreeImage function declarations to match FreeImage 3.9.2 API documentation
+'! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 2 to match current version 3.9.2
+'+ [Carsten Klein] added function declaration for FreeImage_JPEGCrop(): added both declaration and Boolean returning wrapper function.
+'! [Carsten Klein] changed data type of all occurences of parameter 'Flags' from Long to either FREE_IMAGE_LOAD_OPTIONS or FREE_IMAGE_SAVE_OPTIONS enum. This is true for declared functions as well as for wrapper functions.
+'+ [Carsten Klein] added function declaration for FreeImage_LoadMultiBitmapFromMemory().
+'+ [Carsten Klein] added wrapper function FreeImage_LoadMultiBitmapFromMemoryEx(): this is dealing with a VB style array (SAFEARRAY) like FreeImage_LoadFromMemoryEx() does.
+'
+'! now FreeImage version 3.9.2
+'
+'October 30, 2006 - 1.8
+'* [Carsten Klein] fixed a memory leak in wrapper function SavePictureEx(). Thanks to Roogames for reporting that bug.
+'! [Carsten Klein] changed return type of wrapper function SavePictureEx() to Boolean.
+'+ [Carsten Klein] added wrapper function FreeImage_SaveEx() which brings all the features, as there are inline size- and color conversion and format guessing, so far only known from SavePictureEx() for DIBs.
+'! [Carsten Klein] changed wrapper function SavePictureEx(): now this is only a thin wrapper for function FreeImage_SaveEx().
+'+ [Carsten Klein] added enumeration FREE_IMAGE_LOAD_OPTIONS.
+'- [Carsten Klein] refactored enumeration FREE_IMAGE_SAVE_OPTIONS: removed unnecessary items from enumeration.
+'! [Carsten Klein] changed wrapper function LoadPictureEx(): added parameter 'Options' (enum FREE_IMAGE_LOAD_OPTIONS) to specify image loading options (called 'flags' in FreeImage).
+'+ [Carsten Klein] added wrapper function FreeImage_LoadEx() which brings all the features, as there are inline size- and color conversion and format guessing, so far only known from LoadPictureEx() for DIBs.
+'! [Carsten Klein] changed wrapper function LoadPictureEx(): now this is only a thin wrapper for function FreeImage_LoadEx().
+'
+'October 13, 2006 - 1.7.2
+'+ [Carsten Klein] added User32 function GetDesktopWindow()
+'+ added User32 function GetWindowDC()
+'- [Carsten Klein] removed unused constants DI_MASK, DI_IMAGE and DI_NORMAL
+'+ added GDI32 function GetDeviceCaps() with constants HORZRES and VERTRES
+'+ added GDI32 function SelectObject()
+'+ added GDI32 function DeleteObject()
+'+ added GDI32 function CreateCompatibleBitmap()
+'+ added GDI32 function CreateCompatibleDC()
+'+ added GDI32 function BitBlt()
+'+ [Carsten Klein] added wrapper function FreeImage_CreateFromScreen(): this function lets you capture the whole screen or any certain window
+'
+'October 10, 2006 - 1.7.1
+'! [Carsten Klein] changed parameter name 'Page' into 'hPageDib' in declared function FreeImage_UnlockPage(). 'hPageDib' must be the (dib-)handle obtained from FreeImage_LockPage() and not the page number. Now, the declaration is less confusing. Thanks to Ender Wiggin.
+'
+'August 4, 2006 - 1.7
+'* [Carsten Klein] fixed a bug in pGetTagFromTagPtr(): removed overflow error when converting unsigned short tags (FIDT_SHORT) with values between 32768 and 65535. Thanks to André Hendriks.
+'! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 1 to match current version 3.9.1
+'
+'! now FreeImage version 3.9.1
+'
+'July 17, 2006 - 1.6
+'+ [Carsten Klein] added more public wrapper functions for tag copying and cloning:
+'+ added function FreeImage_CopyMetadata()
+'+ added function FreeImage_CloneMetadata()
+'- [Carsten Klein] removed dead API functions, dead structures and dead variables
+'* [Carsten Klein] fixed a bug in FreeImage_ConvertColorDepth(): now color images are converted to 24 bits when used with FICF_PREPARE_RESCALE, all others to 8 bit
+'
+'July 16, 2006 - 1.5.6
+'+ [Carsten Klein] added more public wrapper functions for VB friendly tag access: these functions deal with a FREE_IMAGE_TAG structure instead of FreeImage's Tag pointer.
+'+ added function FreeImage_SetMetadataEx()
+'+ added function FreeImage_CreateTagEx()
+'+ added function FreeImage_AppendTag()
+'+ added function FreeImage_RemoveTag()
+'+ added function FreeImage_RemoveTagEx()
+'+ added function FreeImage_TagExists()
+'+ added function FreeImage_TagExistsEx()
+'+ added function FreeImage_DeleteTagEx()
+'+ added function FreeImage_CloneTagEx()
+'+ added function FreeImage_RemoveMetadataModel()
+'+ added function FreeImage_UpdateMetadata()
+'+ added function FreeImage_UnsignedLong()
+'+ added function FreeImage_UnsignedShort()
+'+ added function FreeImage_CreateRational()
+'+ added function FreeImage_CreateSignedRational()
+'+ added function FreeImage_GetImageComment()
+'+ added function FreeImage_SetImageComment()
+'+ [Carsten Klein] added some private helper functions to leverage tag updating:
+'+ added helper function pTagToTagPtr()
+'+ added helper function pGetValueBuffer()
+'+ added helper function pGetRationalValueBuffer()
+'+ added helper function pGetVariantAsByteBuffer()
+'+ added helper function pGetElementSize()
+'
+'July 5, 2006 - 1.5.5
+'! [Carsten Klein] changed function signature of FreeImage_FindNextMetadataEx(): optional parameter 'Model' is now present; see the function's inline documentation
+'
+'June 30, 2006 - 1.5.4
+'* [Carsten Klein] fixed bug in functions creating a FreeImage DIB from a windows hBitmap: workaround for palletized bitmaps is now implemented
+'* fixed function FreeImage_CreateFromOLEPicture()
+'* fixed function FreeImage_CreateFromDC()
+'
+'June 22, 2006 - 1.5.3
+'! [Carsten Klein] changed function declaration of FreeImage_GetMetadataInt(): parameter 'model' is now 'ByVal' and Tag is a Long pointer
+'! [Carsten Klein] changed function declaration of FreeImage_SetMetadataInt(): parameter 'model' is now 'ByVal' and Tag is a Long pointer
+'! [Carsten Klein] changed function declaration of FreeImage_GetMetadata(): parameter Tag is a Long pointer now
+'! [Carsten Klein] changed function declaration of FreeImage_SetMetadata(): parameter Tag is a Long pointer now
+'+ [Carsten Klein] added function declarations for tag creation and destruction:
+'+ added declaration for function FreeImage_CreateTag()
+'+ added declaration for procedure FreeImage_DeleteTag()
+'+ added declaration for function FreeImage_CloneTag()
+'+ [Carsten Klein] added new items to structure FREE_IMAGE_TAG:
+'+ added item 'Model As FREE_IMAGE_MDMODEL'
+'+ added item 'TagPtr As Long'
+'+ [Carsten Klein] added wrapper functions for more VB friendly Tag access: these functions deal with a FREE_IMAGE_TAG structure instead of FreeImage's Tag pointer.
+'+ added function FreeImage_FindFirstMetadataEx()
+'+ added function FreeImage_FindNextMetadataEx()
+'+ added function FreeImage_GetAllMetadataTags()
+'+ added function FreeImage_GetMetadataEx()
+'* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations
+'- [Carsten Klein] removed workaround for thresholding and dithering non-MINISBLACK 8 bit images in function FreeImage_ConvertColorDepth(): was fixed in FreeImage 3.9.0
+'* [Carsten Klein] fixed all pending issues in function FreeImage_PaintDC(): is now in production state
+'
+'June 14, 2006 - 1.5.2
+'! [Carsten Klein] changed signature of function FreeImage_CreateMask()
+'+ [Carsten Klein] added function FreeImage_CreateMaskImage(): this creates a monochrome mask from a source image
+'+ [Carsten Klein] added function FreeImage_CreateMaskInPlace(): this creates a monochrome mask from a source image
+'+ [Carsten Klein] added enumeration FREE_IMAGE_ICON_TRANSPARENCY_OPTION_FLAGS
+'+ [Carsten Klein] added wrapper function FreeImage_CreateSimpleBWMaskImage(): wrapper for FreeImage_CreateMaskImage() with reduced number of parameters; creates a b/w mask
+'+ [Carsten Klein] added wrapper function FreeImage_CreateSimpleBWMaskInPlace(): wrapper for FreeImage_CreateMaskInPlace() with reduced number of parameters; creates a b/w mask
+'+ [Carsten Klein] added function declaration for FreeImage_MakeThumbnail()
+'+ [Carsten Klein] added function for FreeImage_GetOlePictureThumbnail()
+'+ [Carsten Klein] added function for FreeImage_MakeThumbnailIOP()
+'+ [Carsten Klein] documented function FreeImage_ReadMemoryEx()
+'+ [Carsten Klein] documented function FreeImage_WriteMemoryEx()
+'! [Carsten Klein] divided FreeImage_TagFromPointer into an interface only function with a private helper function pGetTagFromTagPtr():
+'+ added helper function pGetTagFromTagPtr()
+'! [Carsten Klein] added private helper functions to leverage the FIDT_RATIONAL and FIDT_SRATIONAL data type:
+'+ added helper function pNormalizeRational()
+'+ added helper function pNormalizeSRational()
+'+ added helper function gcd()
+'+ added helper function floor()
+'! [Carsten Klein] changed name of structure 'FITAG_int' to 'FITAG': is now as in FreeImage library
+'! [Carsten Klein] changed name of structure 'FITAG' to 'FREE_IMAGE_TAG': this new structure plays an important role in the wrapper's new VB friendly tag accessing concept
+'! [Carsten Klein] changed function declaration of FreeImage_GetMetadataCount(): parameter 'model' is now 'ByVal'
+'! [Carsten Klein] changed function declaration of FreeImage_TagToString(): parameter 'model' is now 'ByVal' and function returns a Long
+'! [Carsten Klein] renamed function declaration of FreeImage_TagToString() to FreeImage_TagToStringInt(): function is now Private and wrapped by a VB String returning function
+'+ [Carsten Klein] added wrapper function FreeImage_TagToString() returning a real VB String
+'+ [Carsten Klein] added structure FIRATIONAL: structure to hold an image tag's rational value
+'+ [Carsten Klein] added new items to structure FREE_IMAGE_TAG:
+'+ added item 'StringValue As String'
+'+ added item 'Palette() As RGBQUAD'
+'+ added item 'RationalValue() As FIRATIONAL'
+'
+'June 13, 2006 - 1.5.1
+'! [Carsten Klein] changed version constant 'FREEIMAGE_MINOR_VERSION' to 9 to meet version 3.9.0
+'* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations to match FreeImage 3.9.0 API documentation
+'+ [Carsten Klein] added function declaration for new Memory I/O functions in 3.9.0
+'+ added declaration FreeImage_ReadMemory()
+'+ added declaration FreeImage_WriteMemory()
+'! [Carsten Klein] changed/added optional parameter 'element_size' to private function pGetMemoryBlockPtrFromVariant(): caller now can get size in bytes one array element
+'+ [Carsten Klein] added wrapper functions for new Memory I/O functions in 3.9.0
+'+ added function FreeImage_ReadMemoryEx()
+'+ added function FreeImage_WriteMemoryEx()
+'+ [Carsten Klein] added constants and updated enumerations for new 3.9.0 file formats 'FAXG3' and 'SGI'
+'+ [Carsten Klein] added Windows GDI icon related declarations:
+'+ added function declaration for CreateIconIndirect()
+'+ added function declaration for DestroyIcon()
+'+ added structure ICONINFO
+'+ [Carsten Klein] added function FreeImage_GetIcon(): returns a hIcon handle
+'+ [Carsten Klein] added function FreeImage_GetOlePictureIcon(): returns a VB Picture object of type vbPicTypeIcon
+'+ [Carsten Klein] added enumeration FREE_IMAGE_MASK_FLAGS
+'+ [Carsten Klein] added function FreeImage_CreateMaskColors(): returns an array filled with items from an argument list; synonym for VB's Array() function
+'+ [Carsten Klein] added enumeration FREE_IMAGE_teMask(): this creates a monochrome mask from a source image
+'+ [Carsten Klein] added function FreeImage_CreaMASK_CREATION_OPTION_FLAGS
+'
+'! now FreeImage version 3.9.0
+'
+'June 12, 2006 - 1.5
+'* [Carsten Klein] fixed bug in wrapper function FreeImage_PaintDCEx(): now handles boolean test correctly: 'If ((hDC <> 0) And (hDIB <> 0)) Then -> Thanks to ender_wiggin for reporting that bug.
+'+ [Carsten Klein] added private function pGetIOlePictureFromContainer(): used to get IPicture from image hosting control (Form, PictureBox) including custom drawings
+'+ [Carsten Klein] added wrapper function FreeImage_CreateFromImageContainer(): used to create FreeImage DIB from image hosting control (Form, PictureBox) including custom drawings
+'+ [Carsten Klein] added wrapper function SaveImageContainerEx(): derivate of wrapper function 'SavePictureEx()': saves content of image hosting control (Form, PictureBox) including custom drawings
+'
+'February 27, 2006 - 1.4.8
+'+ [Carsten Klein] added inline documentation for these wrapper functions:
+'+ documented function FreeImage_CompareColorsLongLong()
+'+ documented function FreeImage_CompareColorsRGBTRIPLELong()
+'+ documented function FreeImage_CompareColorsRGBQUADLong()
+'+ documented function FreeImage_SearchPalette()
+'! [Carsten Klein] changed and updated general remarks in section "General notes on implementation and design"
+'! [Carsten Klein] changed all function declarations of FreeImage functions that return a BOOL in C/C++: see "Functions returning Booleans" in section "General notes on implementation and design"
+'! [Carsten Klein] changed all function signatures of functions that are derived from or extend FreeImage BOOL functions: see "Functions returning Booleans" in section "General notes on implementation and design"
+'+ [Carsten Klein] added wrapper functions for all FreeImage functions that return a BOOL in C/C++: see "Functions returning Booleans" in section "General notes on implementation and design"
+'+ [Carsten Klein] added wrapper function FreeImage_CreateFromDC(): creates an DIB from a DC. Thanks to Evan (wxforecaster) for this suggestion.
+'+ [Carsten Klein] added declaration of GDI function GetCurrentObject() and constant OBJ_BITMAP
+'+ [Carsten Klein] added wrapper function FreeImage_IsAvailable(): used to test for existence of FreeImage Library (FreeImage.dll)
+'
+'February 9, 2006 - 1.4.7
+'+ [Carsten Klein] added private helper function pGetPreviousColorDepth()
+'+ [Carsten Klein] added private helper function pGetNextColorDepth()
+'! [Carsten Klein] changed/extended signature of wrapper function SavePictureEx(): now includes a parameter 'ColorDepth'
+'+ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_DEPTH
+'+ [Carsten Klein] added error handling capabilities to wrapper function SavePictureEx()
+'+ [Carsten Klein] added/updated inline documentation of wrapper function SavePictureEx()
+'
+'October 31, 2005 - 1.4.6
+'+ [Carsten Klein] added wrapper function FreeImage_SwapColorLong(): this converts from a RGB to a BGR color value stored in a Long and vice versa
+'
+'October 27, 2005 - 1.4.5
+'+ [Carsten Klein] added function FreeImage_IsTransparencyTableTransparent(): checks for transparency directly on the transparency table
+'
+'October 13, 2005 - 1.4.4
+'+ [Carsten Klein] added some functions to compare colors in different formats and with tolerance:
+'+ added function FreeImage_CompareColorsLongLong()
+'+ added function FreeImage_CompareColorsRGBTRIPLELong()
+'+ added function FreeImage_CompareColorsRGBQUADLong()
+'+ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_FORMAT_FLAGS
+'+ [Carsten Klein] added enumeration FREE_IMAGE_TRANSPARENCY_STATE_FLAGS
+'+ [Carsten Klein] added function FreeImage_SearchPalette(): to search the palette index for a given color
+'
+'October 13, 2005 - 1.4.3
+'+ [Carsten Klein] added additional function declaration FreeImage_SetPixelColorByLong(): now color values may be provided in a long value
+'+ [Carsten Klein] added additional function declaration FreeImage_GetPixelColorByLong(): now color values may be received in a long value
+'+ [Carsten Klein] added function FreeImage_SetPixelColorEx(): color values may be provided by four different byte values
+'+ [Carsten Klein] added function FreeImage_GetPixelColorEx(): color values are returned through four different byte values
+'
+'October 11, 2005 - 1.4.2
+'* [Carsten Klein] fixed bug in wrapper function FreeImage_GetBitsExRGBQUAD(): now tests for and works with 32 bit images
+'
+'October 10, 2005 - 1.4.1
+'* [Carsten Klein] fixed serious bug in FreeImage_GetBitsEx...() functions: created custom array descriptor now really has two dimensions
+'* fixed wrapper function FreeImage_GetBitsEx()
+'* fixed wrapper function FreeImage_GetBitsExRGBTRIPLE()
+'* fixed wrapper function FreeImage_GetBitsExRGBQUAD()
+'
+'September 9, 2005 - 1.4
+'! [Carsten Klein] changed wrapper function FreeImage_ConvertColorDepth(): now uses FreeImage_ConvertToGreyscale
+'+ [Carsten Klein] added version numbers to change log
+'+ [Carsten Klein] added comments to IOlePicture aware toolkit and conversion functions
+'* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations
+'
+'! now FreeImage version 3.8.0
+'
+'September 8, 2005 - 1.3.5
+'! [Carsten Klein] changed version constant 'FREEIMAGE_MINOR_VERSION' to 8 to meet version 3.8.0
+'+ [Carsten Klein] added function declarations for UNICODE dealing functions with additional token 'Int' appended:
+'+ added function FreeImage_LoadUInt()
+'+ added function FreeImage_SaveUInt()
+'+ added function FreeImage_GetFileTypeUInt()
+'+ added function FreeImage_GetFIFFromFilenameUInt()
+'+ [Carsten Klein] added wrapper functions to ease the use of UNICODE dealing functions:
+'+ added function FreeImage_LoadU()
+'+ added function FreeImage_SaveU()
+'+ added function FreeImage_GetFileTypeU()
+'+ added function FreeImage_GetFIFFromFilenameU()
+'+ [Carsten Klein] added function declaration for FreeImage_ConvertToGreyscale()
+'
+'July 18, 2005 - 1.3.4
+'! [Carsten Klein] changed inline comments in these wrapper functions:
+'! changed FreeImage_GetBitsEx(): mixed up width and height in SAFEAARAY creation
+'! changed FreeImage_GetBitsExRGBTRIPLE(): mixed up width and height in SAFEAARAY creation
+'! changed FreeImage_GetBitsExRGBQUAD(): mixed up width and height in SAFEAARAY creation
+'+ [Carsten Klein] added wrapper function FreeImage_GetScanLinesRGBTRIPLE():
+'
+'June 30, 2005 - 1.3.3
+'+ [Carsten Klein] added Kernel32 function FillMemory()
+'
+'June 24, 2005 - 1.3.2
+'+ [Carsten Klein] added pixel access functions FreeImage_GetBitsExRGBTRIPLE() and FreeImage_GetBitsExRGBQUAD()
+'+ [Carsten Klein] added IOlePicture based wrapper function FreeImage_ConvertColorDepthIOP()
+'+ [Carsten Klein] added IOlePicture based wrapper functions for FreeImage_RescaleIOP():
+'+ added function FreeImage_FreeImage_RescaleByPixelIOP()
+'+ added function FreeImage_FreeImage_RescaleByPercentIOP()
+'+ added function FreeImage_FreeImage_RescaleByFactorIOP()
+'+ [Carsten Klein] added IOlePicture based wrapper function FreeImage_RescaleIOP()
+'* [Carsten Klein] fixed a bug in FreeImage_GetOlePicture(): now OlePictures returned through IPicture may be used directly by other functions accepting IPicture types without any assignment to IPictureDisp
+'
+'June 24, 2005 - 1.3.1
+'! [Carsten Klein] changed inproper function declaration of function FreeImage_AdjustCurve(): now parameter 'LUT' is passed ByVal
+'+ [Carsten Klein] added wrapper function FreeImage_AdjustCurveEx()
+'+ [Carsten Klein] added IOlePicture based wrapper functions for FreeImage toolkit functions:
+'+ added function FreeImage_RotateClassicIOP()
+'+ added function FreeImage_RotateExIOP()
+'+ added function FreeImage_FlipHorizontalIOP()
+'+ added function FreeImage_FlipVerticalIOP()
+'+ added function FreeImage_AdjustCurveIOP()
+'+ added function FreeImage_AdjustGammaIOP()
+'+ added function FreeImage_AdjustBrightnessIOP()
+'+ added function FreeImage_AdjustContrastIOP()
+'+ added function FreeImage_InvertIOP()
+'+ added function FreeImage_GetChannelIOP()
+'+ added function FreeImage_CopyIOP()
+'+ added function FreeImage_PasteIOP()
+'
+'June 22, 2005 - 1.3
+'+ [Carsten Klein] added inline comments and documentation for pixel access functions
+'
+'June 18, 2005 - 1.2.9
+'+ [Carsten Klein] added function FreeImage_GetBitsEx()
+'+ [Carsten Klein] added structure SAFEARRAY2D to create 2 dimensional custom arrays
+'+ [Carsten Klein] added function declarations for converting scanlines to 4 bpp:
+'+ added declaration for FreeImage_ConvertLine1To4()
+'+ added declaration for FreeImage_ConvertLine8To4()
+'+ added declaration for FreeImage_ConvertLine16To4_555()
+'+ added declaration for FreeImage_ConvertLine16To4_565()
+'+ added declaration for FreeImage_ConvertLine24To4()
+'+ added declaration for FreeImage_ConvertLine32To4()
+'
+'June 16, 2005 - 1.2.8
+'! [Carsten Klein] changed inproper function declaration for all functions FreeImage_ConvertLineXXXX(): now parameters 'target' and 'Source' are passed ByVal
+'
+'June 15, 2005 - 1.2.7
+'+ [Carsten Klein] added function FreeImage_DestroyLockedArrayByPtr() to destroy a locked array by it's pointer (VB can't pass a array of structures through a Variant type)
+'+ [Carsten Klein] added some wrapper functions for FreeImage_DestroyLockedArrayByPtr() for common FreeImage structures:
+'+ added function FreeImage_DestroyLockedArrayRGBTRIPLE()
+'+ added function FreeImage_DestroyLockedArrayRGBQUAD()
+'+ added function FreeImage_DestroyLockedArrayFICOMPLEX()
+'+ added function FreeImage_DestroyLockedArrayFIRGB16()
+'+ added function FreeImage_DestroyLockedArrayFIRGBA16()
+'+ added function FreeImage_DestroyLockedArrayFIRGBF()
+'+ added function FreeImage_DestroyLockedArrayFIRGBAF()
+'+ [Carsten Klein] added functions to return scanlines as VB style arrays in all supported FreeImage formats:
+'+ added function FreeImage_GetScanLineBITMAP8()
+'+ added function FreeImage_GetScanLineBITMAP16()
+'+ added function FreeImage_GetScanLineBITMAP24()
+'+ added function FreeImage_GetScanLineBITMAP32()
+'+ added function FreeImage_GetScanLineINT16()
+'+ added function FreeImage_GetScanLineINT32()
+'+ added function FreeImage_GetScanLineFLOAT()
+'+ added function FreeImage_GetScanLineDOUBLE()
+'+ added function FreeImage_GetScanLineCOMPLEX()
+'+ added function FreeImage_GetScanLineRGB16()
+'+ added function FreeImage_GetScanLineRGBA16()
+'+ added function FreeImage_GetScanLineRGBF()
+'+ added function FreeImage_GetScanLineRGBAF()
+'
+'June 14, 2005 - 1.2.6
+'! [Carsten Klein] updated documentation on array-dealing functions using arrays with custom array descriptors
+'+ [Carsten Klein] added function FreeImage_DestroyLockedArray() to destroy a self created array 'FADF_AUTO Or FADF_FIXEDSIZE' array
+'+ [Carsten Klein] added function FreeImage_GetPaletteExLong() to return palette data in an array of type Long
+'+ [Carsten Klein] added parameters 'lPaletteSize', 'vntReservePalette' and 'lReserveSize' to FreeImage_ConvertColorDepth()
+'
+'June 13, 2005 - 1.2.5
+'* [Carsten Klein] fixed a bug in helper function pGetMemoryBlockPtrFromVariant(): now 'size_in_bytes' will never exceed the size of an array provided
+'
+'June 12, 2005 - 1.2.4
+'+ [Carsten Klein] added ZLib compression function wrappers dealing with VB style arrays:
+'+ added function FreeImage_ZLibCompressVB()
+'+ added function FreeImage_ZLibUncompressVB()
+'+ added function FreeImage_ZLibGZipVB()
+'+ added function FreeImage_ZLibGUnzipVB()
+'
+'June 10, 2005 - 1.2.3
+'+ [Carsten Klein] added ZLib compression function wrappers dealing with VB style arrays:
+'+ added function FreeImage_ZLibCompressEx()
+'+ added function FreeImage_ZLibUncompressEx()
+'+ added function FreeImage_ZLibGZipEx()
+'+ added function FreeImage_ZLibCRC32Ex()
+'+ added function FreeImage_ZLibGUnzipEx()
+'+ [Carsten Klein] added more VB friendly ZLib compression function wrappers:
+'+ added function FreeImage_ZLibCompressVB()
+'+ added function FreeImage_ZLibUncompressVB()
+'+ added function FreeImage_ZLibGZipVB()
+'+ added function FreeImage_ZLibGUnzipVB()
+'! [Carsten Klein] fixed wrong function declaration of functions FreeImage_ZLibGUnzip(): alias was '_FreeImage_ZLibZlibGUnzip@16' (double ZLib)
+'! [Carsten Klein] fixed function pGetArrayPtrFromVariantArray() that now can deal with uninitialized arrays
+'! fixed function pGetMemoryBlockPtrFromVariant() that now can deal with uninitialized arrays
+'! [Carsten Klein] fixed wrong function declaration of functions FreeImage_AdjustBrightness(): ...@8 -> ...@12
+'! fixed wrong function declaration of functions FreeImage_AdjustContrast(): ...@8 -> ...@12
+'! fixed wrong function declaration of functions FreeImage_AdjustGamma(): ...@8 -> ...@12
+'! fixed wrong function declaration of functions FreeImage_RotateClassic(): ...@8 -> ...@12
+'! fixed wrong function declaration of functions FreeImage_RotateEx(): ...@28 -> ...@48
+'
+'June 9, 2005 - 1.2.2
+'! [Carsten Klein] fixed wrong function declaration of function FreeImage_OpenMultiBitmap(): added parameter 'flags' (...@20 -> ...@24)
+'
+'June 8, 2005 - 1.2.1
+'! [Carsten Klein] refactored function FreeImage_LoadFromMemoryEx(): now using pGetMemoryBlockPtrFromVariant()
+'+ [Carsten Klein] added private function pGetMemoryBlockPtrFromVariant() to get poiner and size of a memory block from a Variant parameter
+'! [Carsten Klein] changed declaration of ZLib related functions: 'target' and 'Source' are now 'ByVal Long'
+'
+'June 7, 2005 - 1.2
+'+ [Carsten Klein] added some more inline comments and documentation
+'+ [Carsten Klein] added optional parameter 'bUnloadSource' to function FreeImage_SaveToMemoryEx()
+'+ added optional parameter 'bUnloadSource' to function FreeImage_SaveToMemoryEx2()
+'+ [Carsten Klein] added optional parameter 'InPercent' to function SavePictureEx()
+'! implemented the capability to resize the image on saving in function SavePictureEx()
+'+ [Carsten Klein] added parameters 'InPercent' and 'Format' to function LoadPictureEx()
+'* [Carsten Klein] fixed wrong function declaration of function FreeImage_JPEGTransform() (...@12 -> ...@16)
+'
+'June 6, 2005 - 1.1.2
+'+ [Carsten Klein] added some more inline comments and documentation
+'
+'May 30, 2005 - 1.1.1
+'* [Carsten Klein] fixed percent calculating bug in function FreeImage_RescaleEx()
+'! changed behaviour of parameter 'bIsPercentValue' -> it now has no effect on integer values
+'+ added function FreeImage_RescaleByPixel() to avoid confusion with overloading
+'+ added function FreeImage_RescaleByPercent() to avoid confusion with overloading
+'+ added function FreeImage_RescaleByFactor() to avoid confusion with overloading
+'! [Carsten Klein] changed name of parameter 'bUnloadDIB' to 'bUnloadSource' of function FreeImage_GetOlePicture()
+'+ [Carsten Klein] added some more inline comments and documentation
+'* [Carsten Klein] fixed a potential runtime error in function FreeImage_SetTransparencyTableEx(): 'Count' will no longer exceed 256
+'
+'May 24, 2005 - 1.1
+'+ [Carsten Klein] added a new VB wrapper
+
+
+'--------------------------------------------------------------------------------
+' Win32 API function, struct and constant declarations
+'--------------------------------------------------------------------------------
+
+Private Const ERROR_SUCCESS As Long = 0
+
+'KERNEL32
+Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
+ ByRef Destination As Any, _
+ ByRef Source As Any, _
+ ByVal Length As Long)
+
+Private Declare Sub FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" ( _
+ ByRef Destination As Any, _
+ ByVal Length As Long, _
+ ByVal Fill As Byte)
+
+Private Declare Function lstrlen Lib "kernel32.dll" Alias "lstrlenA" ( _
+ ByVal lpString As Long) As Long
+
+
+'OLEAUT32
+Private Declare Function OleCreatePictureIndirect Lib "oleaut32.dll" ( _
+ ByRef lpPictDesc As PictDesc, _
+ ByRef riid As Guid, _
+ ByVal fOwn As Long, _
+ ByRef lplpvObj As IPicture) As Long
+
+Private Declare Function SafeArrayAllocDescriptor Lib "oleaut32.dll" ( _
+ ByVal cDims As Long, _
+ ByRef ppsaOut As Long) As Long
+
+Private Declare Function SafeArrayDestroyDescriptor Lib "oleaut32.dll" ( _
+ ByVal psa As Long) As Long
+
+Private Declare Sub SafeArrayDestroyData Lib "oleaut32.dll" ( _
+ ByVal psa As Long)
+
+
+
+'SAFEARRAY
+Private Const FADF_AUTO As Long = (&H1)
+Private Const FADF_FIXEDSIZE As Long = (&H10)
+
+Private Type SAVEARRAY1D
+ cDims As Integer
+ fFeatures As Integer
+ cbElements As Long
+ cLocks As Long
+ pvData As Long
+ cElements As Long
+ lLbound As Long
+End Type
+
+Private Type SAVEARRAY2D
+ cDims As Integer
+ fFeatures As Integer
+ cbElements As Long
+ cLocks As Long
+ pvData As Long
+ cElements1 As Long
+ lLbound1 As Long
+ cElements2 As Long
+ lLbound2 As Long
+End Type
+
+
+'MSVBVM60
+Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" ( _
+ ByRef Ptr() As Any) As Long
+
+
+'USER32
+Private Declare Function ReleaseDC Lib "user32.dll" ( _
+ ByVal hWnd As Long, _
+ ByVal hDC As Long) As Long
+
+Private Declare Function GetDC Lib "user32.dll" ( _
+ ByVal hWnd As Long) As Long
+
+Private Declare Function GetDesktopWindow Lib "user32.dll" () As Long
+
+Private Declare Function GetDCEx Lib "user32.dll" ( _
+ ByVal hWnd As Long, _
+ ByVal hrgnclip As Long, _
+ ByVal fdwOptions As Long) As Long
+
+Private Const DCX_WINDOW As Long = &H1&
+
+Private Declare Function GetWindowRect Lib "user32.dll" ( _
+ ByVal hWnd As Long, _
+ ByRef lpRect As RECT) As Long
+
+Private Declare Function GetClientRect Lib "user32.dll" ( _
+ ByVal hWnd As Long, _
+ ByRef lpRect As RECT) As Long
+
+
+Private Type RECT
+ Left As Long
+ Top As Long
+ Right As Long
+ Bottom As Long
+End Type
+
+Private Type Guid
+ Data1 As Long
+ Data2 As Integer
+ Data3 As Integer
+ Data4(0 To 7) As Byte
+End Type
+
+Private Type PictDesc
+ cbSizeofStruct As Long
+ picType As Long
+ hImage As Long
+ xExt As Long
+ yExt As Long
+End Type
+
+Private Type BITMAP_API
+ bmType As Long
+ bmWidth As Long
+ bmHeight As Long
+ bmWidthBytes As Long
+ bmPlanes As Integer
+ bmBitsPixel As Integer
+ bmBits As Long
+End Type
+
+Private Type ICONINFO
+ fIcon As Long
+ xHotspot As Long
+ yHotspot As Long
+ hBmMask As Long
+ hbmColor As Long
+End Type
+
+Private Type BLENDFUNCTION
+ BlendOp As Byte
+ BlendFlags As Byte
+ SourceConstantAlpha As Byte
+ AlphaFormat As Byte
+End Type
+
+'GDI32
+Private Declare Function GetDeviceCaps Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal nIndex As Long) As Long
+
+Private Const HORZRES As Long = 8
+Private Const VERTRES As Long = 10
+
+Private Declare Function GetStretchBltMode Lib "gdi32.dll" ( _
+ ByVal hDC As Long) As Long
+
+Private Declare Function SetStretchBltMode Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal nStretchMode As Long) As Long
+
+Private Declare Function SetDIBitsToDevice Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByVal dx As Long, _
+ ByVal dy As Long, _
+ ByVal SrcX As Long, _
+ ByVal SrcY As Long, _
+ ByVal Scan As Long, _
+ ByVal NumScans As Long, _
+ ByVal Bits As Long, _
+ ByVal BitsInfo As Long, _
+ ByVal wUsage As Long) As Long
+
+Private Declare Function StretchDIBits Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByVal dx As Long, _
+ ByVal dy As Long, _
+ ByVal SrcX As Long, _
+ ByVal SrcY As Long, _
+ ByVal wSrcWidth As Long, _
+ ByVal wSrcHeight As Long, _
+ ByVal lpBits As Long, _
+ ByVal lpBitsInfo As Long, _
+ ByVal wUsage As Long, _
+ ByVal dwRop As Long) As Long
+
+Private Declare Function CreateDIBitmap Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal lpInfoHeader As Long, _
+ ByVal dwUsage As Long, _
+ ByVal lpInitBits As Long, _
+ ByVal lpInitInfo As Long, _
+ ByVal wUsage As Long) As Long
+
+Private Declare Function CreateDIBSection Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal pbmi As Long, _
+ ByVal iUsage As Long, _
+ ByRef ppvBits As Long, _
+ ByVal hSection As Long, _
+ ByVal dwOffset As Long) As Long
+
+Private Const CBM_INIT As Long = &H4
+
+Private Declare Function CreateCompatibleBitmap Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal nWidth As Long, _
+ ByVal nHeight As Long) As Long
+
+Private Declare Function CreateCompatibleDC Lib "gdi32.dll" ( _
+ ByVal hDC As Long) As Long
+
+Private Declare Function DeleteDC Lib "gdi32.dll" ( _
+ ByVal hDC As Long) As Long
+
+Private Declare Function BitBlt Lib "gdi32.dll" ( _
+ ByVal hDestDC As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByVal nWidth As Long, _
+ ByVal nHeight As Long, _
+ ByVal hSrcDC As Long, _
+ ByVal xSrc As Long, _
+ ByVal ySrc As Long, _
+ ByVal dwRop As Long) As Long
+
+Private Declare Function GetDIBits Lib "gdi32.dll" ( _
+ ByVal aHDC As Long, _
+ ByVal hBitmap As Long, _
+ ByVal nStartScan As Long, _
+ ByVal nNumScans As Long, _
+ ByVal lpBits As Long, _
+ ByVal lpBI As Long, _
+ ByVal wUsage As Long) As Long
+
+Private Declare Function GetObjectAPI Lib "gdi32.dll" Alias "GetObjectA" ( _
+ ByVal hObject As Long, _
+ ByVal nCount As Long, _
+ ByRef lpObject As Any) As Long
+
+Private Declare Function SelectObject Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal hObject As Long) As Long
+
+Private Declare Function DeleteObject Lib "gdi32.dll" ( _
+ ByVal hObject As Long) As Long
+
+Private Declare Function GetCurrentObject Lib "gdi32.dll" ( _
+ ByVal hDC As Long, _
+ ByVal uObjectType As Long) As Long
+
+Private Const OBJ_BITMAP As Long = 7
+
+
+Private Declare Function DestroyIcon Lib "user32.dll" ( _
+ ByVal hIcon As Long) As Long
+
+Private Declare Function CreateIconIndirect Lib "user32.dll" ( _
+ ByRef piconinfo As ICONINFO) As Long
+
+Private Const BLACKONWHITE As Long = 1
+Private Const WHITEONBLACK As Long = 2
+Private Const COLORONCOLOR As Long = 3
+
+'MSIMG32
+Private Declare Function AlphaBlend Lib "msimg32.dll" ( _
+ ByVal hdcDest As Long, _
+ ByVal nXOriginDest As Long, _
+ ByVal nYOriginDest As Long, _
+ ByVal nWidthDest As Long, _
+ ByVal nHeightDest As Long, _
+ ByVal hdcSrc As Long, _
+ ByVal nXOriginSrc As Long, _
+ ByVal nYOriginSrc As Long, _
+ ByVal nWidthSrc As Long, _
+ ByVal nHeightSrc As Long, _
+ ByVal lBlendFunction As Long) As Long
+
+Private Const AC_SRC_OVER = &H0
+Private Const AC_SRC_ALPHA = &H1
+
+
+Public Enum STRETCH_MODE
+ SM_BLACKONWHITE = BLACKONWHITE
+ SM_WHITEONBLACK = WHITEONBLACK
+ SM_COLORONCOLOR = COLORONCOLOR
+End Enum
+#If False Then
+ Const SM_BLACKONWHITE = BLACKONWHITE
+ Const SM_WHITEONBLACK = WHITEONBLACK
+ Const SM_COLORONCOLOR = COLORONCOLOR
+#End If
+
+
+Private Const SRCAND As Long = &H8800C6
+Private Const SRCCOPY As Long = &HCC0020
+Private Const SRCERASE As Long = &H440328
+Private Const SRCINVERT As Long = &H660046
+Private Const SRCPAINT As Long = &HEE0086
+Private Const CAPTUREBLT As Long = &H40000000
+
+Public Enum RASTER_OPERATOR
+ ROP_SRCAND = SRCAND
+ ROP_SRCCOPY = SRCCOPY
+ ROP_SRCERASE = SRCERASE
+ ROP_SRCINVERT = SRCINVERT
+ ROP_SRCPAINT = SRCPAINT
+End Enum
+#If False Then
+ Const ROP_SRCAND = SRCAND
+ Const ROP_SRCCOPY = SRCCOPY
+ Const ROP_SRCERASE = SRCERASE
+ Const ROP_SRCINVERT = SRCINVERT
+ Const ROP_SRCPAINT = SRCPAINT
+#End If
+
+Private Const DIB_PAL_COLORS As Long = 1
+Private Const DIB_RGB_COLORS As Long = 0
+
+Public Enum DRAW_MODE
+ DM_DRAW_DEFAULT = &H0
+ DM_MIRROR_NONE = DM_DRAW_DEFAULT
+ DM_MIRROR_VERTICAL = &H1
+ DM_MIRROR_HORIZONTAL = &H2
+ DM_MIRROR_BOTH = DM_MIRROR_VERTICAL Or DM_MIRROR_HORIZONTAL
+End Enum
+#If False Then
+ Const DM_DRAW_DEFAULT = &H0
+ Const DM_MIRROR_NONE = DM_DRAW_DEFAULT
+ Const DM_MIRROR_VERTICAL = &H1
+ Const DM_MIRROR_HORIZONTAL = &H2
+ Const DM_MIRROR_BOTH = DM_MIRROR_VERTICAL Or DM_MIRROR_HORIZONTAL
+#End If
+
+Public Enum HISTOGRAM_ORIENTATION
+ HOR_TOP_DOWN = &H0
+ HOR_BOTTOM_UP = &H1
+End Enum
+#If False Then
+ Const HOR_TOP_DOWN = &H0
+ Const HOR_BOTTOM_UP = &H1
+#End If
+
+
+'--------------------------------------------------------------------------------
+' FreeImage 3 types, constants and enumerations
+'--------------------------------------------------------------------------------
+
+'FREEIMAGE
+
+' Version information
+Public Const FREEIMAGE_MAJOR_VERSION As Long = 3
+Public Const FREEIMAGE_MINOR_VERSION As Long = 13
+Public Const FREEIMAGE_RELEASE_SERIAL As Long = 0
+
+' Memory stream pointer operation flags
+Public Const SEEK_SET As Long = 0
+Public Const SEEK_CUR As Long = 1
+Public Const SEEK_END As Long = 2
+
+' Indexes for byte arrays, masks and shifts for treating pixels as words
+' These coincide with the order of RGBQUAD and RGBTRIPLE
+' Little Endian (x86 / MS Windows, Linux) : BGR(A) order
+Public Const FI_RGBA_RED As Long = 2
+Public Const FI_RGBA_GREEN As Long = 1
+Public Const FI_RGBA_BLUE As Long = 0
+Public Const FI_RGBA_ALPHA As Long = 3
+Public Const FI_RGBA_RED_MASK As Long = &HFF0000
+Public Const FI_RGBA_GREEN_MASK As Long = &HFF00
+Public Const FI_RGBA_BLUE_MASK As Long = &HFF
+Public Const FI_RGBA_ALPHA_MASK As Long = &HFF000000
+Public Const FI_RGBA_RED_SHIFT As Long = 16
+Public Const FI_RGBA_GREEN_SHIFT As Long = 8
+Public Const FI_RGBA_BLUE_SHIFT As Long = 0
+Public Const FI_RGBA_ALPHA_SHIFT As Long = 24
+
+' The 16 bit macros only include masks and shifts, since each color element is not byte aligned
+Public Const FI16_555_RED_MASK As Long = &H7C00
+Public Const FI16_555_GREEN_MASK As Long = &H3E0
+Public Const FI16_555_BLUE_MASK As Long = &H1F
+Public Const FI16_555_RED_SHIFT As Long = 10
+Public Const FI16_555_GREEN_SHIFT As Long = 5
+Public Const FI16_555_BLUE_SHIFT As Long = 0
+Public Const FI16_565_RED_MASK As Long = &HF800
+Public Const FI16_565_GREEN_MASK As Long = &H7E0
+Public Const FI16_565_BLUE_MASK As Long = &H1F
+Public Const FI16_565_RED_SHIFT As Long = 11
+Public Const FI16_565_GREEN_SHIFT As Long = 5
+Public Const FI16_565_BLUE_SHIFT As Long = 0
+
+' ICC profile support
+Public Const FIICC_DEFAULT As Long = &H0
+Public Const FIICC_COLOR_IS_CMYK As Long = &H1
+
+Private Const FREE_IMAGE_ICC_COLOR_MODEL_MASK As Long = &H1
+Public Enum FREE_IMAGE_ICC_COLOR_MODEL
+ FIICC_COLOR_MODEL_RGB = &H0
+ FIICC_COLOR_MODEL_CMYK = &H1
+End Enum
+
+' Load / Save flag constants
+Public Const BMP_DEFAULT As Long = 0
+Public Const BMP_SAVE_RLE As Long = 1
+Public Const CUT_DEFAULT As Long = 0
+Public Const DDS_DEFAULT As Long = 0
+Public Const EXR_DEFAULT As Long = 0 ' save data as half with piz-based wavelet compression
+Public Const EXR_FLOAT As Long = &H1 ' save data as float instead of as half (not recommended)
+Public Const EXR_NONE As Long = &H2 ' save with no compression
+Public Const EXR_ZIP As Long = &H4 ' save with zlib compression, in blocks of 16 scan lines
+Public Const EXR_PIZ As Long = &H8 ' save with piz-based wavelet compression
+Public Const EXR_PXR24 As Long = &H10 ' save with lossy 24-bit float compression
+Public Const EXR_B44 As Long = &H20 ' save with lossy 44% float compression - goes to 22% when combined with EXR_LC
+Public Const EXR_LC As Long = &H40 ' save images with one luminance and two chroma channels, rather than as RGB (lossy compression)
+Public Const FAXG3_DEFAULT As Long = 0
+Public Const GIF_DEFAULT As Long = 0
+Public Const GIF_LOAD256 As Long = 1 ' Load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color
+Public Const GIF_PLAYBACK As Long = 2 ''Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+Public Const HDR_DEFAULT As Long = 0
+Public Const ICO_DEFAULT As Long = 0
+Public Const ICO_MAKEALPHA As Long = 1 ' convert to 32bpp and create an alpha channel from the AND-mask when loading
+Public Const IFF_DEFAULT As Long = 0
+Public Const J2K_DEFAULT As Long = 0 ' save with a 16:1 rate
+Public Const JP2_DEFAULT As Long = 0 ' save with a 16:1 rate
+Public Const JPEG_DEFAULT As Long = 0 ' loading (see JPEG_FAST); saving (see JPEG_QUALITYGOOD|JPEG_SUBSAMPLING_420)
+Public Const JPEG_FAST As Long = &H1 ' load the file as fast as possible, sacrificing some quality
+Public Const JPEG_ACCURATE As Long = &H2 ' load the file with the best quality, sacrificing some speed
+Public Const JPEG_CMYK As Long = &H4 ' load separated CMYK "as is" (use 'OR' to combine with other flags)
+Public Const JPEG_EXIFROTATE As Long = &H8 ' load and rotate according to Exif 'Orientation' tag if available
+Public Const JPEG_QUALITYSUPERB As Long = &H80 ' save with superb quality (100:1)
+Public Const JPEG_QUALITYGOOD As Long = &H100 ' save with good quality (75:1)
+Public Const JPEG_QUALITYNORMAL As Long = &H200 ' save with normal quality (50:1)
+Public Const JPEG_QUALITYAVERAGE As Long = &H400 ' save with average quality (25:1)
+Public Const JPEG_QUALITYBAD As Long = &H800 ' save with bad quality (10:1)
+Public Const JPEG_PROGRESSIVE As Long = &H2000 ' save as a progressive-JPEG (use 'OR' to combine with other save flags)
+Public Const JPEG_SUBSAMPLING_411 As Long = &H1000 ' save with high 4x1 chroma subsampling (4:1:1)
+Public Const JPEG_SUBSAMPLING_420 As Long = &H4000 ' save with medium 2x2 medium chroma subsampling (4:2:0) - default value
+Public Const JPEG_SUBSAMPLING_422 As Long = &H8000 ' save with low 2x1 chroma subsampling (4:2:2)
+Public Const JPEG_SUBSAMPLING_444 As Long = &H10000 ' save with no chroma subsampling (4:4:4)
+Public Const KOALA_DEFAULT As Long = 0
+Public Const LBM_DEFAULT As Long = 0
+Public Const MNG_DEFAULT As Long = 0
+Public Const PCD_DEFAULT As Long = 0
+Public Const PCD_BASE As Long = 1 ' load the bitmap sized 768 x 512
+Public Const PCD_BASEDIV4 As Long = 2 ' load the bitmap sized 384 x 256
+Public Const PCD_BASEDIV16 As Long = 3 ' load the bitmap sized 192 x 128
+Public Const PCX_DEFAULT As Long = 0
+Public Const PFM_DEFAULT As Long = 0
+Public Const PICT_DEFAULT As Long = 0
+Public Const PNG_DEFAULT As Long = 0
+Public Const PNG_IGNOREGAMMA As Long = 1 ' avoid gamma correction
+Public Const PNG_Z_BEST_SPEED As Long = &H1 ' save using ZLib level 1 compression flag (default value is 6)
+Public Const PNG_Z_DEFAULT_COMPRESSION As Long = &H6 ' save using ZLib level 6 compression flag (default recommended value)
+Public Const PNG_Z_BEST_COMPRESSION As Long = &H9 ' save using ZLib level 9 compression flag (default value is 6)
+Public Const PNG_Z_NO_COMPRESSION As Long = &H100 ' save without ZLib compression
+Public Const PNG_INTERLACED As Long = &H200 ' save using Adam7 interlacing (use | to combine with other save flags)
+Public Const PNM_DEFAULT As Long = 0
+Public Const PNM_SAVE_RAW As Long = 0 ' if set the writer saves in RAW format (i.e. P4, P5 or P6)
+Public Const PNM_SAVE_ASCII As Long = 1 ' if set the writer saves in ASCII format (i.e. P1, P2 or P3)
+Public Const PSD_DEFAULT As Long = 0
+Public Const RAS_DEFAULT As Long = 0
+Public Const RAW_DEFAULT As Long = 0 ' load the file as linear RGB 48-bit
+Public Const RAW_PREVIEW = 1 ' try to load the embedded JPEG preview with included Exif Data or default to RGB 24-bit
+Public Const RAW_DISPLAY = 2 ' load the file as RGB 24-bit
+Public Const SGI_DEFAULT As Long = 0
+Public Const TARGA_DEFAULT As Long = 0
+Public Const TARGA_LOAD_RGB888 As Long = 1 ' if set the loader converts RGB555 and ARGB8888 -> RGB888
+Public Const TIFF_DEFAULT As Long = 0
+Public Const TIFF_CMYK As Long = &H1 ' reads/stores tags for separated CMYK (use 'OR' to combine with compression flags)
+Public Const TIFF_PACKBITS As Long = &H100 ' save using PACKBITS compression
+Public Const TIFF_DEFLATE As Long = &H200 ' save using DEFLATE compression (a.k.a. ZLIB compression)
+Public Const TIFF_ADOBE_DEFLATE As Long = &H400 ' save using ADOBE DEFLATE compression
+Public Const TIFF_NONE As Long = &H800 ' save without any compression
+Public Const TIFF_CCITTFAX3 As Long = &H1000 ' save using CCITT Group 3 fax encoding
+Public Const TIFF_CCITTFAX4 As Long = &H2000 ' save using CCITT Group 4 fax encoding
+Public Const TIFF_LZW As Long = &H4000 ' save using LZW compression
+Public Const TIFF_JPEG As Long = &H8000 ' save using JPEG compression
+Public Const WBMP_DEFAULT As Long = 0
+Public Const XBM_DEFAULT As Long = 0
+Public Const XPM_DEFAULT As Long = 0
+
+Public Enum FREE_IMAGE_FORMAT
+ FIF_UNKNOWN = -1
+ FIF_BMP = 0
+ FIF_ICO = 1
+ FIF_JPEG = 2
+ FIF_JNG = 3
+ FIF_KOALA = 4
+ FIF_LBM = 5
+ FIF_IFF = FIF_LBM
+ FIF_MNG = 6
+ FIF_PBM = 7
+ FIF_PBMRAW = 8
+ FIF_PCD = 9
+ FIF_PCX = 10
+ FIF_PGM = 11
+ FIF_PGMRAW = 12
+ FIF_PNG = 13
+ FIF_PPM = 14
+ FIF_PPMRAW = 15
+ FIF_RAS = 16
+ FIF_TARGA = 17
+ FIF_TIFF = 18
+ FIF_WBMP = 19
+ FIF_PSD = 20
+ FIF_CUT = 21
+ FIF_XBM = 22
+ FIF_XPM = 23
+ FIF_DDS = 24
+ FIF_GIF = 25
+ FIF_HDR = 26
+ FIF_FAXG3 = 27
+ FIF_SGI = 28
+ FIF_EXR = 29
+ FIF_J2K = 30
+ FIF_JP2 = 31
+ FIF_PFM = 32
+ FIF_PICT = 33
+ FIF_RAW = 34
+End Enum
+#If False Then
+ Const FIF_UNKNOWN = -1
+ Const FIF_BMP = 0
+ Const FIF_ICO = 1
+ Const FIF_JPEG = 2
+ Const FIF_JNG = 3
+ Const FIF_KOALA = 4
+ Const FIF_LBM = 5
+ Const FIF_IFF = FIF_LBM
+ Const FIF_MNG = 6
+ Const FIF_PBM = 7
+ Const FIF_PBMRAW = 8
+ Const FIF_PCD = 9
+ Const FIF_PCX = 10
+ Const FIF_PGM = 11
+ Const FIF_PGMRAW = 12
+ Const FIF_PNG = 13
+ Const FIF_PPM = 14
+ Const FIF_PPMRAW = 15
+ Const FIF_RAS = 16
+ Const FIF_TARGA = 17
+ Const FIF_TIFF = 18
+ Const FIF_WBMP = 19
+ Const FIF_PSD = 20
+ Const FIF_CUT = 21
+ Const FIF_XBM = 22
+ Const FIF_XPM = 23
+ Const FIF_DDS = 24
+ Const FIF_GIF = 25
+ Const FIF_HDR = 26
+ Const FIF_FAXG3 = 27
+ Const FIF_SGI = 28
+ Const FIF_EXR = 29
+ Const FIF_J2K = 30
+ Const FIF_JP2 = 31
+ Const FIF_PFM = 32
+ Const FIF_PICT = 33
+ Const FIF_RAW = 34
+#End If
+
+Public Enum FREE_IMAGE_LOAD_OPTIONS
+ FILO_LOAD_DEFAULT = 0
+ FILO_GIF_DEFAULT = GIF_DEFAULT
+ FILO_GIF_LOAD256 = GIF_LOAD256 ' load the image as a 256 color image with ununsed palette entries, if it's 16 or 2 color
+ FILO_GIF_PLAYBACK = GIF_PLAYBACK ' 'play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+ FILO_ICO_DEFAULT = ICO_DEFAULT
+ FILO_ICO_MAKEALPHA = ICO_MAKEALPHA ' convert to 32bpp and create an alpha channel from the AND-mask when loading
+ FILO_JPEG_DEFAULT = JPEG_DEFAULT ' for loading this is a synonym for FILO_JPEG_FAST
+ FILO_JPEG_FAST = JPEG_FAST ' load the file as fast as possible, sacrificing some quality
+ FILO_JPEG_ACCURATE = JPEG_ACCURATE ' load the file with the best quality, sacrificing some speed
+ FILO_JPEG_CMYK = JPEG_CMYK ' load separated CMYK "as is" (use 'OR' to combine with other load flags)
+ FILO_JPEG_EXIFROTATE = JPEG_EXIFROTATE ' load and rotate according to Exif 'Orientation' tag if available
+ FILO_PCD_DEFAULT = PCD_DEFAULT
+ FILO_PCD_BASE = PCD_BASE ' load the bitmap sized 768 x 512
+ FILO_PCD_BASEDIV4 = PCD_BASEDIV4 ' load the bitmap sized 384 x 256
+ FILO_PCD_BASEDIV16 = PCD_BASEDIV16 ' load the bitmap sized 192 x 128
+ FILO_PNG_DEFAULT = PNG_DEFAULT
+ FILO_PNG_IGNOREGAMMA = PNG_IGNOREGAMMA ' avoid gamma correction
+ FILO_RAW_DEFAULT = RAW_DEFAULT ' load the file as linear RGB 48-bit
+ FILO_RAW_PREVIEW = RAW_PREVIEW ' try to load the embedded JPEG preview with included Exif Data or default to RGB 24-bit
+ FILO_RAW_DISPLAY = RAW_DISPLAY ' load the file as RGB 24-bit
+ FILO_TARGA_DEFAULT = TARGA_LOAD_RGB888
+ FILO_TARGA_LOAD_RGB888 = TARGA_LOAD_RGB888 ' if set the loader converts RGB555 and ARGB8888 -> RGB888
+ FISO_TIFF_DEFAULT = TIFF_DEFAULT
+ FISO_TIFF_CMYK = TIFF_CMYK ' reads tags for separated CMYK
+End Enum
+#If False Then
+ Const FILO_LOAD_DEFAULT = 0
+ Const FILO_GIF_DEFAULT = GIF_DEFAULT
+ Const FILO_GIF_LOAD256 = GIF_LOAD256
+ Const FILO_GIF_PLAYBACK = GIF_PLAYBACK
+ Const FILO_ICO_DEFAULT = ICO_DEFAULT
+ Const FILO_ICO_MAKEALPHA = ICO_MAKEALPHA
+ Const FILO_JPEG_DEFAULT = JPEG_DEFAULT
+ Const FILO_JPEG_FAST = JPEG_FAST
+ Const FILO_JPEG_ACCURATE = JPEG_ACCURATE
+ Const FILO_JPEG_CMYK = JPEG_CMYK
+ Const FILO_JPEG_EXIFROTATE = JPEG_EXIFROTATE
+ Const FILO_PCD_DEFAULT = PCD_DEFAULT
+ Const FILO_PCD_BASE = PCD_BASE
+ Const FILO_PCD_BASEDIV4 = PCD_BASEDIV4
+ Const FILO_PCD_BASEDIV16 = PCD_BASEDIV16
+ Const FILO_PNG_DEFAULT = PNG_DEFAULT
+ Const FILO_PNG_IGNOREGAMMA = PNG_IGNOREGAMMA
+ Const FILO_TARGA_DEFAULT = TARGA_LOAD_RGB888
+ Const FILO_TARGA_LOAD_RGB888 = TARGA_LOAD_RGB888
+ Const FISO_TIFF_DEFAULT = TIFF_DEFAULT
+ Const FISO_TIFF_CMYK = TIFF_CMYK
+#End If
+
+Public Enum FREE_IMAGE_SAVE_OPTIONS
+ FISO_SAVE_DEFAULT = 0
+ FISO_BMP_DEFAULT = BMP_DEFAULT
+ FISO_BMP_SAVE_RLE = BMP_SAVE_RLE
+ FISO_EXR_DEFAULT = EXR_DEFAULT ' save data as half with piz-based wavelet compression
+ FISO_EXR_FLOAT = EXR_FLOAT ' save data as float instead of as half (not recommended)
+ FISO_EXR_NONE = EXR_NONE ' save with no compression
+ FISO_EXR_ZIP = EXR_ZIP ' save with zlib compression, in blocks of 16 scan lines
+ FISO_EXR_PIZ = EXR_PIZ ' save with piz-based wavelet compression
+ FISO_EXR_PXR24 = EXR_PXR24 ' save with lossy 24-bit float compression
+ FISO_EXR_B44 = EXR_B44 ' save with lossy 44% float compression - goes to 22% when combined with EXR_LC
+ FISO_EXR_LC = EXR_LC ' save images with one luminance and two chroma channels, rather than as RGB (lossy compression)
+ FISO_JPEG_DEFAULT = JPEG_DEFAULT ' for saving this is a synonym for FISO_JPEG_QUALITYGOOD
+ FISO_JPEG_QUALITYSUPERB = JPEG_QUALITYSUPERB ' save with superb quality (100:1)
+ FISO_JPEG_QUALITYGOOD = JPEG_QUALITYGOOD ' save with good quality (75:1)
+ FISO_JPEG_QUALITYNORMAL = JPEG_QUALITYNORMAL ' save with normal quality (50:1)
+ FISO_JPEG_QUALITYAVERAGE = JPEG_QUALITYAVERAGE ' save with average quality (25:1)
+ FISO_JPEG_QUALITYBAD = JPEG_QUALITYBAD ' save with bad quality (10:1)
+ FISO_JPEG_PROGRESSIVE = JPEG_PROGRESSIVE ' save as a progressive-JPEG (use 'OR' to combine with other save flags)
+ FISO_JPEG_SUBSAMPLING_411 = JPEG_SUBSAMPLING_411 ' save with high 4x1 chroma subsampling (4:1:1)
+ FISO_JPEG_SUBSAMPLING_420 = JPEG_SUBSAMPLING_420 ' save with medium 2x2 medium chroma subsampling (4:2:0) - default value
+ FISO_JPEG_SUBSAMPLING_422 = JPEG_SUBSAMPLING_422 ' save with low 2x1 chroma subsampling (4:2:2)
+ FISO_JPEG_SUBSAMPLING_444 = JPEG_SUBSAMPLING_444 ' save with no chroma subsampling (4:4:4)
+ FISO_PNG_Z_BEST_SPEED = PNG_Z_BEST_SPEED ' save using ZLib level 1 compression flag (default value is 6)
+ FISO_PNG_Z_DEFAULT_COMPRESSION = PNG_Z_DEFAULT_COMPRESSION ' save using ZLib level 6 compression flag (default recommended value)
+ FISO_PNG_Z_BEST_COMPRESSION = PNG_Z_BEST_COMPRESSION ' save using ZLib level 9 compression flag (default value is 6)
+ FISO_PNG_Z_NO_COMPRESSION = PNG_Z_NO_COMPRESSION ' save without ZLib compression
+ FISO_PNG_INTERLACED = PNG_INTERLACED ' save using Adam7 interlacing (use | to combine with other save flags)
+ FISO_PNM_DEFAULT = PNM_DEFAULT
+ FISO_PNM_SAVE_RAW = PNM_SAVE_RAW ' if set the writer saves in RAW format (i.e. P4, P5 or P6)
+ FISO_PNM_SAVE_ASCII = PNM_SAVE_ASCII ' if set the writer saves in ASCII format (i.e. P1, P2 or P3)
+ FISO_TIFF_DEFAULT = TIFF_DEFAULT
+ FISO_TIFF_CMYK = TIFF_CMYK ' stores tags for separated CMYK (use 'OR' to combine with compression flags)
+ FISO_TIFF_PACKBITS = TIFF_PACKBITS ' save using PACKBITS compression
+ FISO_TIFF_DEFLATE = TIFF_DEFLATE ' save using DEFLATE compression (a.k.a. ZLIB compression)
+ FISO_TIFF_ADOBE_DEFLATE = TIFF_ADOBE_DEFLATE ' save using ADOBE DEFLATE compression
+ FISO_TIFF_NONE = TIFF_NONE ' save without any compression
+ FISO_TIFF_CCITTFAX3 = TIFF_CCITTFAX3 ' save using CCITT Group 3 fax encoding
+ FISO_TIFF_CCITTFAX4 = TIFF_CCITTFAX4 ' save using CCITT Group 4 fax encoding
+ FISO_TIFF_LZW = TIFF_LZW ' save using LZW compression
+ FISO_TIFF_JPEG = TIFF_JPEG ' save using JPEG compression
+End Enum
+#If False Then
+ Const FISO_SAVE_DEFAULT = 0
+ Const FISO_BMP_DEFAULT = BMP_DEFAULT
+ Const FISO_BMP_SAVE_RLE = BMP_SAVE_RLE
+ Const FISO_JPEG_DEFAULT = JPEG_DEFAULT
+ Const FISO_JPEG_QUALITYSUPERB = JPEG_QUALITYSUPERB
+ Const FISO_JPEG_QUALITYGOOD = JPEG_QUALITYGOOD
+ Const FISO_JPEG_QUALITYNORMAL = JPEG_QUALITYNORMAL
+ Const FISO_JPEG_QUALITYAVERAGE = JPEG_QUALITYAVERAGE
+ Const FISO_JPEG_QUALITYBAD = JPEG_QUALITYBAD
+ Const FISO_JPEG_PROGRESSIVE = JPEG_PROGRESSIVE
+ Const FISO_JPEG_SUBSAMPLING_411 = JPEG_SUBSAMPLING_411
+ Const FISO_JPEG_SUBSAMPLING_420 = JPEG_SUBSAMPLING_420
+ Const FISO_JPEG_SUBSAMPLING_422 = JPEG_SUBSAMPLING_422
+ Const FISO_JPEG_SUBSAMPLING_444 = JPEG_SUBSAMPLING_444
+ Const FISO_PNM_DEFAULT = PNM_DEFAULT
+ Const FISO_PNM_SAVE_RAW = PNM_SAVE_RAW
+ Const FISO_PNM_SAVE_ASCII = PNM_SAVE_ASCII
+ Const FISO_TIFF_DEFAULT = TIFF_DEFAULT
+ Const FISO_TIFF_CMYK = TIFF_CMYK
+ Const FISO_TIFF_PACKBITS = TIFF_PACKBITS
+ Const FISO_TIFF_DEFLATE = TIFF_DEFLATE
+ Const FISO_TIFF_ADOBE_DEFLATE = TIFF_ADOBE_DEFLATE
+ Const FISO_TIFF_NONE = TIFF_NONE
+ Const FISO_TIFF_CCITTFAX3 = TIFF_CCITTFAX3
+ Const FISO_TIFF_CCITTFAX4 = TIFF_CCITTFAX4
+ Const FISO_TIFF_LZW = TIFF_LZW
+ Const FISO_TIFF_JPEG = TIFF_JPEG
+#End If
+
+Public Enum FREE_IMAGE_TYPE
+ FIT_UNKNOWN = 0 ' unknown type
+ FIT_BITMAP = 1 ' standard image : 1-, 4-, 8-, 16-, 24-, 32-bit
+ FIT_UINT16 = 2 ' array of unsigned short : unsigned 16-bit
+ FIT_INT16 = 3 ' array of short : signed 16-bit
+ FIT_UINT32 = 4 ' array of unsigned long : unsigned 32-bit
+ FIT_INT32 = 5 ' array of long : signed 32-bit
+ FIT_FLOAT = 6 ' array of float : 32-bit IEEE floating point
+ FIT_DOUBLE = 7 ' array of double : 64-bit IEEE floating point
+ FIT_COMPLEX = 8 ' array of FICOMPLEX : 2 x 64-bit IEEE floating point
+ FIT_RGB16 = 9 ' 48-bit RGB image : 3 x 16-bit
+ FIT_RGBA16 = 10 ' 64-bit RGBA image : 4 x 16-bit
+ FIT_RGBF = 11 ' 96-bit RGB float image : 3 x 32-bit IEEE floating point
+ FIT_RGBAF = 12 ' 128-bit RGBA float image : 4 x 32-bit IEEE floating point
+End Enum
+#If False Then
+ Const FIT_UNKNOWN = 0
+ Const FIT_BITMAP = 1
+ Const FIT_UINT16 = 2
+ Const FIT_INT16 = 3
+ Const FIT_UINT32 = 4
+ Const FIT_INT32 = 5
+ Const FIT_FLOAT = 6
+ Const FIT_DOUBLE = 7
+ Const FIT_COMPLEX = 8
+ Const FIT_RGB16 = 9
+ Const FIT_RGBA16 = 10
+ Const FIT_RGBF = 11
+ Const FIT_RGBAF = 12
+#End If
+
+Public Enum FREE_IMAGE_COLOR_TYPE
+ FIC_MINISWHITE = 0 ' min value is white
+ FIC_MINISBLACK = 1 ' min value is black
+ FIC_RGB = 2 ' RGB color model
+ FIC_PALETTE = 3 ' color map indexed
+ FIC_RGBALPHA = 4 ' RGB color model with alpha channel
+ FIC_CMYK = 5 ' CMYK color model
+End Enum
+#If False Then
+ Const FIC_MINISWHITE = 0
+ Const FIC_MINISBLACK = 1
+ Const FIC_RGB = 2
+ Const FIC_PALETTE = 3
+ Const FIC_RGBALPHA = 4
+ Const FIC_CMYK = 5
+#End If
+
+Public Enum FREE_IMAGE_QUANTIZE
+ FIQ_WUQUANT = 0 ' Xiaolin Wu color quantization algorithm
+ FIQ_NNQUANT = 1 ' NeuQuant neural-net quantization algorithm by Anthony Dekker
+End Enum
+#If False Then
+ Const FIQ_WUQUANT = 0
+ Const FIQ_NNQUANT = 1
+#End If
+
+Public Enum FREE_IMAGE_DITHER
+ FID_FS = 0 ' Floyd & Steinberg error diffusion
+ FID_BAYER4x4 = 1 ' Bayer ordered dispersed dot dithering (order 2 dithering matrix)
+ FID_BAYER8x8 = 2 ' Bayer ordered dispersed dot dithering (order 3 dithering matrix)
+ FID_CLUSTER6x6 = 3 ' Ordered clustered dot dithering (order 3 - 6x6 matrix)
+ FID_CLUSTER8x8 = 4 ' Ordered clustered dot dithering (order 4 - 8x8 matrix)
+ FID_CLUSTER16x16 = 5 ' Ordered clustered dot dithering (order 8 - 16x16 matrix)
+ FID_BAYER16x16 = 6 ' Bayer ordered dispersed dot dithering (order 4 dithering matrix)
+End Enum
+#If False Then
+ Const FID_FS = 0
+ Const FID_BAYER4x4 = 1
+ Const FID_BAYER8x8 = 2
+ Const FID_CLUSTER6x6 = 3
+ Const FID_CLUSTER8x8 = 4
+ Const FID_CLUSTER16x16 = 5
+ Const FID_BAYER16x16 = 6
+#End If
+
+Public Enum FREE_IMAGE_JPEG_OPERATION
+ FIJPEG_OP_NONE = 0 ' no transformation
+ FIJPEG_OP_FLIP_H = 1 ' horizontal flip
+ FIJPEG_OP_FLIP_V = 2 ' vertical flip
+ FIJPEG_OP_TRANSPOSE = 3 ' transpose across UL-to-LR axis
+ FIJPEG_OP_TRANSVERSE = 4 ' transpose across UR-to-LL axis
+ FIJPEG_OP_ROTATE_90 = 5 ' 90-degree clockwise rotation
+ FIJPEG_OP_ROTATE_180 = 6 ' 180-degree rotation
+ FIJPEG_OP_ROTATE_270 = 7 ' 270-degree clockwise (or 90 ccw)
+End Enum
+#If False Then
+ Const FIJPEG_OP_NONE = 0
+ Const FIJPEG_OP_FLIP_H = 1
+ Const FIJPEG_OP_FLIP_V = 2
+ Const FIJPEG_OP_TRANSPOSE = 3
+ Const FIJPEG_OP_TRANSVERSE = 4
+ Const FIJPEG_OP_ROTATE_90 = 5
+ Const FIJPEG_OP_ROTATE_180 = 6
+ Const FIJPEG_OP_ROTATE_270 = 7
+#End If
+
+Public Enum FREE_IMAGE_TMO
+ FITMO_DRAGO03 = 0 ' Adaptive logarithmic mapping (F. Drago, 2003)
+ FITMO_REINHARD05 = 1 ' Dynamic range reduction inspired by photoreceptor physiology (E. Reinhard, 2005)
+ FITMO_FATTAL02 = 2 ' Gradient domain high dynamic range compression (R. Fattal, 2002)
+End Enum
+#If False Then
+ Const FITMO_DRAGO03 = 0
+ Const FITMO_REINHARD05 = 1
+ Const FITMO_FATTAL02 = 2
+#End If
+
+Public Enum FREE_IMAGE_FILTER
+ FILTER_BOX = 0 ' Box, pulse, Fourier window, 1st order (constant) b-spline
+ FILTER_BICUBIC = 1 ' Mitchell & Netravali's two-param cubic filter
+ FILTER_BILINEAR = 2 ' Bilinear filter
+ FILTER_BSPLINE = 3 ' 4th order (cubic) b-spline
+ FILTER_CATMULLROM = 4 ' Catmull-Rom spline, Overhauser spline
+ FILTER_LANCZOS3 = 5 ' Lanczos3 filter
+End Enum
+#If False Then
+ Const FILTER_BOX = 0
+ Const FILTER_BICUBIC = 1
+ Const FILTER_BILINEAR = 2
+ Const FILTER_BSPLINE = 3
+ Const FILTER_CATMULLROM = 4
+ Const FILTER_LANCZOS3 = 5
+#End If
+
+Public Enum FREE_IMAGE_COLOR_CHANNEL
+ FICC_RGB = 0 ' Use red, green and blue channels
+ FICC_RED = 1 ' Use red channel
+ FICC_GREEN = 2 ' Use green channel
+ FICC_BLUE = 3 ' Use blue channel
+ FICC_ALPHA = 4 ' Use alpha channel
+ FICC_BLACK = 5 ' Use black channel
+ FICC_REAL = 6 ' Complex images: use real part
+ FICC_IMAG = 7 ' Complex images: use imaginary part
+ FICC_MAG = 8 ' Complex images: use magnitude
+ FICC_PHASE = 9 ' Complex images: use phase
+End Enum
+#If False Then
+ Const FICC_RGB = 0
+ Const FICC_RED = 1
+ Const FICC_GREEN = 2
+ Const FICC_BLUE = 3
+ Const FICC_ALPHA = 4
+ Const FICC_BLACK = 5
+ Const FICC_REAL = 6
+ Const FICC_IMAG = 7
+ Const FICC_MAG = 8
+ Const FICC_PHASE = 9
+#End If
+
+Public Enum FREE_IMAGE_MDTYPE
+ FIDT_NOTYPE = 0 ' placeholder
+ FIDT_BYTE = 1 ' 8-bit unsigned integer
+ FIDT_ASCII = 2 ' 8-bit bytes w/ last byte null
+ FIDT_SHORT = 3 ' 16-bit unsigned integer
+ FIDT_LONG = 4 ' 32-bit unsigned integer
+ FIDT_RATIONAL = 5 ' 64-bit unsigned fraction
+ FIDT_SBYTE = 6 ' 8-bit signed integer
+ FIDT_UNDEFINED = 7 ' 8-bit untyped data
+ FIDT_SSHORT = 8 ' 16-bit signed integer
+ FIDT_SLONG = 9 ' 32-bit signed integer
+ FIDT_SRATIONAL = 10 ' 64-bit signed fraction
+ FIDT_FLOAT = 11 ' 32-bit IEEE floating point
+ FIDT_DOUBLE = 12 ' 64-bit IEEE floating point
+ FIDT_IFD = 13 ' 32-bit unsigned integer (offset)
+ FIDT_PALETTE = 14 ' 32-bit RGBQUAD
+End Enum
+#If False Then
+ Const FIDT_NOTYPE = 0
+ Const FIDT_BYTE = 1
+ Const FIDT_ASCII = 2
+ Const FIDT_SHORT = 3
+ Const FIDT_LONG = 4
+ Const FIDT_RATIONAL = 5
+ Const FIDT_SBYTE = 6
+ Const FIDT_UNDEFINED = 7
+ Const FIDT_SSHORT = 8
+ Const FIDT_SLONG = 9
+ Const FIDT_SRATIONAL = 10
+ Const FIDT_FLOAT = 11
+ Const FIDT_DOUBLE = 12
+ Const FIDT_IFD = 13
+ Const FIDT_PALETTE = 14
+#End If
+
+Public Enum FREE_IMAGE_MDMODEL
+ FIMD_NODATA = -1 '
+ FIMD_COMMENTS = 0 ' single comment or keywords
+ FIMD_EXIF_MAIN = 1 ' Exif-TIFF metadata
+ FIMD_EXIF_EXIF = 2 ' Exif-specific metadata
+ FIMD_EXIF_GPS = 3 ' Exif GPS metadata
+ FIMD_EXIF_MAKERNOTE = 4 ' Exif maker note metadata
+ FIMD_EXIF_INTEROP = 5 ' Exif interoperability metadata
+ FIMD_IPTC = 6 ' IPTC/NAA metadata
+ FIMD_XMP = 7 ' Abobe XMP metadata
+ FIMD_GEOTIFF = 8 ' GeoTIFF metadata
+ FIMD_ANIMATION = 9 ' Animation metadata
+ FIMD_CUSTOM = 10 ' Used to attach other metadata types to a dib
+End Enum
+#If False Then
+ FIMD_NODATA = -1
+ FIMD_COMMENTS = 0
+ FIMD_EXIF_MAIN = 1
+ FIMD_EXIF_EXIF = 2
+ FIMD_EXIF_GPS = 3
+ FIMD_EXIF_MAKERNOTE = 4
+ FIMD_EXIF_INTEROP = 5
+ FIMD_IPTC = 6
+ FIMD_XMP = 7
+ FIMD_GEOTIFF = 8
+ FIMD_ANIMATION = 9
+ FIMD_CUSTOM = 10
+#End If
+
+' These are the GIF_DISPOSAL metadata constants
+Public Enum FREE_IMAGE_FRAME_DISPOSAL_METHODS
+ FIFD_GIF_DISPOSAL_UNSPECIFIED = 0
+ FIFD_GIF_DISPOSAL_LEAVE = 1
+ FIFD_GIF_DISPOSAL_BACKGROUND = 2
+ FIFD_GIF_DISPOSAL_PREVIOUS = 3
+End Enum
+
+' Constants used in FreeImage_FillBackground and FreeImage_EnlargeCanvas
+Public Enum FREE_IMAGE_COLOR_OPTIONS
+ FI_COLOR_IS_RGB_COLOR = &H0 ' RGBQUAD color is a RGB color (contains no valid alpha channel)
+ FI_COLOR_IS_RGBA_COLOR = &H1 ' RGBQUAD color is a RGBA color (contains a valid alpha channel)
+ FI_COLOR_FIND_EQUAL_COLOR = &H2 ' For palettized images: lookup equal RGB color from palette
+ FI_COLOR_ALPHA_IS_INDEX = &H4 ' The color's rgbReserved member (alpha) contains the palette index to be used
+End Enum
+Public Const FI_COLOR_PALETTE_SEARCH_MASK = _
+ (FI_COLOR_FIND_EQUAL_COLOR Or FI_COLOR_ALPHA_IS_INDEX) ' Flag to test, if any color lookup is performed
+
+' the next enums are only used by derived functions of the
+' FreeImage 3 VB wrapper
+Public Enum FREE_IMAGE_CONVERSION_FLAGS
+ FICF_MONOCHROME = &H1
+ FICF_MONOCHROME_THRESHOLD = FICF_MONOCHROME
+ FICF_MONOCHROME_DITHER = &H3
+ FICF_GREYSCALE_4BPP = &H4
+ FICF_PALLETISED_8BPP = &H8
+ FICF_GREYSCALE_8BPP = FICF_PALLETISED_8BPP Or FICF_MONOCHROME
+ FICF_GREYSCALE = FICF_GREYSCALE_8BPP
+ FICF_RGB_15BPP = &HF
+ FICF_RGB_16BPP = &H10
+ FICF_RGB_24BPP = &H18
+ FICF_RGB_32BPP = &H20
+ FICF_RGB_ALPHA = FICF_RGB_32BPP
+ FICF_KEEP_UNORDERED_GREYSCALE_PALETTE = &H0
+ FICF_REORDER_GREYSCALE_PALETTE = &H1000
+End Enum
+#If False Then
+ Const FICF_MONOCHROME = &H1
+ Const FICF_MONOCHROME_THRESHOLD = FICF_MONOCHROME
+ Const FICF_MONOCHROME_DITHER = &H3
+ Const FICF_GREYSCALE_4BPP = &H4
+ Const FICF_PALLETISED_8BPP = &H8
+ Const FICF_GREYSCALE_8BPP = FICF_PALLETISED_8BPP Or FICF_MONOCHROME
+ Const FICF_GREYSCALE = FICF_GREYSCALE_8BPP
+ Const FICF_RGB_15BPP = &HF
+ Const FICF_RGB_16BPP = &H10
+ Const FICF_RGB_24BPP = &H18
+ Const FICF_RGB_32BPP = &H20
+ Const FICF_RGB_ALPHA = FICF_RGB_32BPP
+ Const FICF_KEEP_UNORDERED_GREYSCALE_PALETTE = &H0
+ Const FICF_REORDER_GREYSCALE_PALETTE = &H1000
+#End If
+
+Public Enum FREE_IMAGE_COLOR_DEPTH
+ FICD_AUTO = &H0
+ FICD_MONOCHROME = &H1
+ FICD_MONOCHROME_THRESHOLD = FICF_MONOCHROME
+ FICD_MONOCHROME_DITHER = &H3
+ FICD_1BPP = FICD_MONOCHROME
+ FICD_4BPP = &H4
+ FICD_8BPP = &H8
+ FICD_15BPP = &HF
+ FICD_16BPP = &H10
+ FICD_24BPP = &H18
+ FICD_32BPP = &H20
+End Enum
+#If False Then
+ Const FICD_AUTO = &H0
+ Const FICD_MONOCHROME = &H1
+ Const FICD_MONOCHROME_THRESHOLD = FICF_MONOCHROME
+ Const FICD_MONOCHROME_DITHER = &H3
+ Const FICD_1BPP = FICD_MONOCHROME
+ Const FICD_4BPP = &H4
+ Const FICD_8BPP = &H8
+ Const FICD_15BPP = &HF
+ Const FICD_16BPP = &H10
+ Const FICD_24BPP = &H18
+ Const FICD_32BPP = &H20
+#End If
+
+Public Enum FREE_IMAGE_ADJUST_MODE
+ AM_STRECH = &H1
+ AM_DEFAULT = AM_STRECH
+ AM_ADJUST_BOTH = AM_STRECH
+ AM_ADJUST_WIDTH = &H2
+ AM_ADJUST_HEIGHT = &H4
+ AM_ADJUST_OPTIMAL_SIZE = &H8
+End Enum
+#If False Then
+ Const AM_STRECH = &H1
+ Const AM_DEFAULT = AM_STRECH
+ Const AM_ADJUST_BOTH = AM_STRECH
+ Const AM_ADJUST_WIDTH = &H2
+ Const AM_ADJUST_HEIGHT = &H4
+ Const AM_ADJUST_OPTIMAL_SIZE = &H8
+#End If
+
+Public Enum FREE_IMAGE_MASK_FLAGS
+ FIMF_MASK_NONE = &H0
+ FIMF_MASK_FULL_TRANSPARENCY = &H1
+ FIMF_MASK_ALPHA_TRANSPARENCY = &H2
+ FIMF_MASK_COLOR_TRANSPARENCY = &H4
+ FIMF_MASK_FORCE_TRANSPARENCY = &H8
+ FIMF_MASK_INVERSE_MASK = &H10
+End Enum
+#If False Then
+ Const FIMF_MASK_NONE = &H0
+ Const FIMF_MASK_FULL_TRANSPARENCY = &H1
+ Const FIMF_MASK_ALPHA_TRANSPARENCY = &H2
+ Const FIMF_MASK_COLOR_TRANSPARENCY = &H4
+ Const FIMF_MASK_FORCE_TRANSPARENCY = &H8
+ Const FIMF_MASK_INVERSE_MASK = &H10
+#End If
+
+Public Enum FREE_IMAGE_COLOR_FORMAT_FLAGS
+ FICFF_COLOR_RGB = &H1
+ FICFF_COLOR_BGR = &H2
+ FICFF_COLOR_PALETTE_INDEX = &H4
+
+ FICFF_COLOR_HAS_ALPHA = &H100
+
+ FICFF_COLOR_ARGB = FICFF_COLOR_RGB Or FICFF_COLOR_HAS_ALPHA
+ FICFF_COLOR_ABGR = FICFF_COLOR_BGR Or FICFF_COLOR_HAS_ALPHA
+
+ FICFF_COLOR_FORMAT_ORDER_MASK = FICFF_COLOR_RGB Or FICFF_COLOR_BGR
+End Enum
+#If False Then
+ Const FICFF_COLOR_RGB = &H1
+ Const FICFF_COLOR_BGR = &H2
+ Const FICFF_COLOR_PALETTE_INDEX = &H4
+
+ Const FICFF_COLOR_HAS_ALPHA = &H100
+
+ Const FICFF_COLOR_ARGB = FICFF_COLOR_RGB Or FICFF_COLOR_HAS_ALPHA
+ Const FICFF_COLOR_ABGR = FICFF_COLOR_BGR Or FICFF_COLOR_HAS_ALPHA
+
+ Const FICFF_COLOR_FORMAT_ORDER_MASK = FICFF_COLOR_RGB Or FICFF_COLOR_BGR
+#End If
+
+Public Enum FREE_IMAGE_MASK_CREATION_OPTION_FLAGS
+ MCOF_CREATE_MASK_IMAGE = &H1
+ MCOF_MODIFY_SOURCE_IMAGE = &H2
+ MCOF_CREATE_AND_MODIFY = MCOF_CREATE_MASK_IMAGE Or MCOF_MODIFY_SOURCE_IMAGE
+End Enum
+#If False Then
+ Const MCOF_CREATE_MASK_IMAGE = &H1
+ Const MCOF_MODIFY_SOURCE_IMAGE = &H2
+ Const MCOF_CREATE_AND_MODIFY = MCOF_CREATE_MASK_IMAGE Or MCOF_MODIFY_SOURCE_IMAGE
+#End If
+
+Public Enum FREE_IMAGE_TRANSPARENCY_STATE_FLAGS
+ FITSF_IGNORE_TRANSPARENCY = &H0
+ FITSF_NONTRANSPARENT = &H1
+ FITSF_TRANSPARENT = &H2
+ FITSF_INCLUDE_ALPHA_TRANSPARENCY = &H4
+End Enum
+#If False Then
+ Const FITSF_IGNORE_TRANSPARENCY = &H0
+ Const FITSF_NONTRANSPARENT = &H1
+ Const FITSF_TRANSPARENT = &H2
+ Const FITSF_INCLUDE_ALPHA_TRANSPARENCY = &H4
+#End If
+
+Public Enum FREE_IMAGE_ICON_TRANSPARENCY_OPTION_FLAGS
+ ITOF_NO_TRANSPARENCY = &H0
+ ITOF_USE_TRANSPARENCY_INFO = &H1
+ ITOF_USE_TRANSPARENCY_INFO_ONLY = ITOF_USE_TRANSPARENCY_INFO
+ ITOF_USE_COLOR_TRANSPARENCY = &H2
+ ITOF_USE_COLOR_TRANSPARENCY_ONLY = ITOF_USE_COLOR_TRANSPARENCY
+ ITOF_USE_TRANSPARENCY_INFO_OR_COLOR = ITOF_USE_TRANSPARENCY_INFO Or ITOF_USE_COLOR_TRANSPARENCY
+ ITOF_USE_DEFAULT_TRANSPARENCY = ITOF_USE_TRANSPARENCY_INFO_OR_COLOR
+ ITOF_USE_COLOR_TOP_LEFT_PIXEL = &H0
+ ITOF_USE_COLOR_FIRST_PIXEL = ITOF_USE_COLOR_TOP_LEFT_PIXEL
+ ITOF_USE_COLOR_TOP_RIGHT_PIXEL = &H20
+ ITOF_USE_COLOR_BOTTOM_LEFT_PIXEL = &H40
+ ITOF_USE_COLOR_BOTTOM_RIGHT_PIXEL = &H80
+ ITOF_USE_COLOR_SPECIFIED = &H100
+ ITOF_FORCE_TRANSPARENCY_INFO = &H400
+End Enum
+#If False Then
+ Const ITOF_NO_TRANSPARENCY = &H0
+ Const ITOF_USE_TRANSPARENCY_INFO = &H1
+ Const ITOF_USE_TRANSPARENCY_INFO_ONLY = ITOF_USE_TRANSPARENCY_INFO
+ Const ITOF_USE_COLOR_TRANSPARENCY = &H2
+ Const ITOF_USE_COLOR_TRANSPARENCY_ONLY = ITOF_USE_COLOR_TRANSPARENCY
+ Const ITOF_USE_TRANSPARENCY_INFO_OR_COLOR = ITOF_USE_TRANSPARENCY_INFO Or ITOF_USE_COLOR_TRANSPARENCY
+ Const ITOF_USE_DEFAULT_TRANSPARENCY = ITOF_USE_TRANSPARENCY_INFO_OR_COLOR
+ Const ITOF_USE_COLOR_TOP_LEFT_PIXEL = &H0
+ Const ITOF_USE_COLOR_FIRST_PIXEL = ITOF_USE_COLOR_TOP_LEFT_PIXEL
+ Const ITOF_USE_COLOR_TOP_RIGHT_PIXEL = &H20
+ Const ITOF_USE_COLOR_BOTTOM_LEFT_PIXEL = &H40
+ Const ITOF_USE_COLOR_BOTTOM_RIGHT_PIXEL = &H80
+ Const ITOF_USE_COLOR_SPECIFIED = &H100
+ Const ITOF_FORCE_TRANSPARENCY_INFO = &H400
+#End If
+
+Private Const ITOF_USE_COLOR_BITMASK As Long = ITOF_USE_COLOR_TOP_RIGHT_PIXEL Or _
+ ITOF_USE_COLOR_BOTTOM_LEFT_PIXEL Or _
+ ITOF_USE_COLOR_BOTTOM_RIGHT_PIXEL Or _
+ ITOF_USE_COLOR_SPECIFIED
+
+
+Public Type RGBQUAD
+ rgbBlue As Byte
+ rgbGreen As Byte
+ rgbRed As Byte
+ rgbReserved As Byte
+End Type
+
+Public Type RGBTRIPLE
+ rgbtBlue As Byte
+ rgbtGreen As Byte
+ rgbtRed As Byte
+End Type
+
+Public Type BITMAPINFOHEADER
+ biSize As Long
+ biWidth As Long
+ biHeight As Long
+ biPlanes As Integer
+ biBitCount As Integer
+ biCompression As Long
+ biSizeImage As Long
+ biXPelsPerMeter As Long
+ biYPelsPerMeter As Long
+ biClrUsed As Long
+ biClrImportant As Long
+End Type
+
+Public Type BITMAPINFO
+ bmiHeader As BITMAPINFOHEADER
+ bmiColors(0) As RGBQUAD
+End Type
+
+Public Const BI_RGB As Long = 0
+Public Const BI_RLE8 As Long = 1
+Public Const BI_RLE4 As Long = 2
+Public Const BI_BITFIELDS As Long = 3
+Public Const BI_JPEG As Long = 4
+Public Const BI_PNG As Long = 5
+
+Public Type FIICCPROFILE
+ Flags As Integer
+ Size As Long
+ Data As Long
+End Type
+
+Public Type FIRGB16
+ Red As Integer
+ Green As Integer
+ Blue As Integer
+End Type
+
+Public Type FIRGBA16
+ Red As Integer
+ Green As Integer
+ Blue As Integer
+ Alpha As Integer
+End Type
+
+Public Type FIRGBF
+ Red As Single
+ Green As Single
+ Blue As Single
+End Type
+
+Public Type FIRGBAF
+ Red As Single
+ Green As Single
+ Blue As Single
+ Alpha As Single
+End Type
+
+Public Type FICOMPLEX
+ r As Double ' real part
+ i As Double ' imaginary part
+End Type
+
+Public Type FITAG
+ Key As Long
+ Description As Long
+ Id As Integer
+ Type As Integer
+ Count As Long
+ Length As Long
+ Value As Long
+End Type
+
+Public Type FIRATIONAL
+ Numerator As Variant
+ Denominator As Variant
+End Type
+
+Public Type FREE_IMAGE_TAG
+ Model As FREE_IMAGE_MDMODEL
+ TagPtr As Long
+ Key As String
+ Description As String
+ Id As Long
+ Type As FREE_IMAGE_MDTYPE
+ Count As Long
+ Length As Long
+ StringValue As String
+ Palette() As RGBQUAD
+ RationalValue() As FIRATIONAL
+ Value As Variant
+End Type
+
+Public Type FreeImageIO
+ read_proc As Long
+ write_proc As Long
+ seek_proc As Long
+ tell_proc As Long
+End Type
+
+Public Type Plugin
+ format_proc As Long
+ description_proc As Long
+ extension_proc As Long
+ regexpr_proc As Long
+ open_proc As Long
+ close_proc As Long
+ pagecount_proc As Long
+ pagecapability_proc As Long
+ load_proc As Long
+ save_proc As Long
+ validate_proc As Long
+ mime_proc As Long
+ supports_export_bpp_proc As Long
+ supports_export_type_proc As Long
+ supports_icc_profiles_proc As Long
+End Type
+
+' the next structures are only used by derived functions of the
+' FreeImage 3 VB wrapper
+Public Type ScanLineRGBTRIBLE
+ Data() As RGBTRIPLE
+End Type
+
+Public Type ScanLinesRGBTRIBLE
+ Scanline() As ScanLineRGBTRIBLE
+End Type
+
+'--------------------------------------------------------------------------------
+' FreeImage 3 function declarations
+'--------------------------------------------------------------------------------
+
+' The FreeImage 3 functions are declared in the same order as they are described
+' in the FreeImage 3 API documentation. The documentation's outline is included
+' as comments.
+
+'--------------------------------------------------------------------------------
+' Bitmap functions
+'--------------------------------------------------------------------------------
+
+' General functions (p. 3 to 4)
+Public Declare Sub FreeImage_Initialise Lib "FreeImage.dll" Alias "_FreeImage_Initialise@4" ( _
+ Optional ByVal load_local_plugins_only As Long = 0)
+
+Public Declare Sub FreeImage_DeInitialise Lib "FreeImage.dll" Alias "_FreeImage_DeInitialise@0" ()
+
+Private Declare Function FreeImage_GetVersionInt Lib "FreeImage.dll" Alias "_FreeImage_GetVersion@0" () As Long
+
+Private Declare Function FreeImage_GetCopyrightMessageInt Lib "FreeImage.dll" Alias "_FreeImage_GetCopyrightMessage@0" () As Long
+
+Public Declare Sub FreeImage_SetOutputMessage Lib "FreeImage.dll" Alias "_FreeImage_SetOutputMessageStdCall@4" ( _
+ ByVal omf As Long)
+
+
+' Bitmap management functions (p. 5 to 11)
+Public Declare Function FreeImage_Allocate Lib "FreeImage.dll" Alias "_FreeImage_Allocate@24" ( _
+ ByVal Width As Long, _
+ ByVal Height As Long, _
+ ByVal bpp As Long, _
+ Optional ByVal red_mask As Long = 0, _
+ Optional ByVal green_mask As Long = 0, _
+ Optional ByVal blue_mask As Long = 0) As Long
+
+Public Declare Function FreeImage_AllocateT Lib "FreeImage.dll" Alias "_FreeImage_AllocateT@28" ( _
+ ByVal type_ As FREE_IMAGE_TYPE, _
+ ByVal Width As Long, _
+ ByVal Height As Long, _
+ Optional ByVal bpp As Long = 8, _
+ Optional ByVal red_mask As Long = 0, _
+ Optional ByVal green_mask As Long = 0, _
+ Optional ByVal blue_mask As Long = 0) As Long
+
+Public Declare Function FreeImage_Load Lib "FreeImage.dll" Alias "_FreeImage_Load@12" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Filename As String, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+Private Declare Function FreeImage_LoadUInt Lib "FreeImage.dll" Alias "_FreeImage_LoadU@12" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Filename As Long, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+Public Declare Function FreeImage_LoadFromHandle Lib "FreeImage.dll" Alias "_FreeImage_LoadFromHandle@16" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal io As Long, _
+ ByVal Handle As Long, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+Private Declare Function FreeImage_SaveInt Lib "FreeImage.dll" Alias "_FreeImage_Save@16" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Filename As String, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Long
+
+Private Declare Function FreeImage_SaveUInt Lib "FreeImage.dll" Alias "_FreeImage_SaveU@16" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Filename As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Long
+
+Private Declare Function FreeImage_SaveToHandleInt Lib "FreeImage.dll" Alias "_FreeImage_SaveToHandle@20" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal io As Long, _
+ ByVal Handle As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Long
+
+Public Declare Function FreeImage_Clone Lib "FreeImage.dll" Alias "_FreeImage_Clone@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Sub FreeImage_Unload Lib "FreeImage.dll" Alias "_FreeImage_Unload@4" ( _
+ ByVal dib As Long)
+
+
+' Bitmap information functions (p. 13 to 19)
+Public Declare Function FreeImage_GetImageType Lib "FreeImage.dll" Alias "_FreeImage_GetImageType@4" ( _
+ ByVal dib As Long) As FREE_IMAGE_TYPE
+
+Public Declare Function FreeImage_GetColorsUsed Lib "FreeImage.dll" Alias "_FreeImage_GetColorsUsed@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetBPP Lib "FreeImage.dll" Alias "_FreeImage_GetBPP@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetWidth Lib "FreeImage.dll" Alias "_FreeImage_GetWidth@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetHeight Lib "FreeImage.dll" Alias "_FreeImage_GetHeight@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetLine Lib "FreeImage.dll" Alias "_FreeImage_GetLine@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetPitch Lib "FreeImage.dll" Alias "_FreeImage_GetPitch@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetDIBSize Lib "FreeImage.dll" Alias "_FreeImage_GetDIBSize@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetPalette Lib "FreeImage.dll" Alias "_FreeImage_GetPalette@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetDotsPerMeterX Lib "FreeImage.dll" Alias "_FreeImage_GetDotsPerMeterX@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetDotsPerMeterY Lib "FreeImage.dll" Alias "_FreeImage_GetDotsPerMeterY@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Sub FreeImage_SetDotsPerMeterX Lib "FreeImage.dll" Alias "_FreeImage_SetDotsPerMeterX@8" ( _
+ ByVal dib As Long, _
+ ByVal res As Long)
+
+Public Declare Sub FreeImage_SetDotsPerMeterY Lib "FreeImage.dll" Alias "_FreeImage_SetDotsPerMeterY@8" ( _
+ ByVal dib As Long, _
+ ByVal res As Long)
+
+Public Declare Function FreeImage_GetInfoHeader Lib "FreeImage.dll" Alias "_FreeImage_GetInfoHeader@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetInfo Lib "FreeImage.dll" Alias "_FreeImage_GetInfo@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetColorType Lib "FreeImage.dll" Alias "_FreeImage_GetColorType@4" ( _
+ ByVal dib As Long) As FREE_IMAGE_COLOR_TYPE
+
+Public Declare Function FreeImage_GetRedMask Lib "FreeImage.dll" Alias "_FreeImage_GetRedMask@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetGreenMask Lib "FreeImage.dll" Alias "_FreeImage_GetGreenMask@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetBlueMask Lib "FreeImage.dll" Alias "_FreeImage_GetBlueMask@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetTransparencyCount Lib "FreeImage.dll" Alias "_FreeImage_GetTransparencyCount@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetTransparencyTable Lib "FreeImage.dll" Alias "_FreeImage_GetTransparencyTable@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Sub FreeImage_SetTransparencyTable Lib "FreeImage.dll" Alias "_FreeImage_SetTransparencyTable@12" ( _
+ ByVal dib As Long, _
+ ByVal Table As Long, _
+ ByVal Count As Long)
+
+Public Declare Sub FreeImage_SetTransparent Lib "FreeImage.dll" Alias "_FreeImage_SetTransparent@8" ( _
+ ByVal dib As Long, _
+ ByVal Enabled As Long)
+
+Private Declare Function FreeImage_IsTransparentInt Lib "FreeImage.dll" Alias "_FreeImage_IsTransparent@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetTransparentIndex Lib "FreeImage.dll" Alias "_FreeImage_GetTransparentIndex@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_SetTransparentIndex Lib "FreeImage.dll" Alias "_FreeImage_SetTransparentIndex@8" ( _
+ ByVal dib As Long, _
+ ByVal Index As Long) As Long
+
+Private Declare Function FreeImage_HasBackgroundColorInt Lib "FreeImage.dll" Alias "_FreeImage_HasBackgroundColor@4" ( _
+ ByVal dib As Long) As Long
+
+Private Declare Function FreeImage_GetBackgroundColorInt Lib "FreeImage.dll" Alias "_FreeImage_GetBackgroundColor@8" ( _
+ ByVal dib As Long, _
+ ByRef bkcolor As RGBQUAD) As Long
+
+Private Declare Function FreeImage_GetBackgroundColorAsLongInt Lib "FreeImage.dll" Alias "_FreeImage_GetBackgroundColor@8" ( _
+ ByVal dib As Long, _
+ ByRef bkcolor As Long) As Long
+
+Private Declare Function FreeImage_SetBackgroundColorInt Lib "FreeImage.dll" Alias "_FreeImage_SetBackgroundColor@8" ( _
+ ByVal dib As Long, _
+ ByRef bkcolor As RGBQUAD) As Long
+
+Private Declare Function FreeImage_SetBackgroundColorAsLongInt Lib "FreeImage.dll" Alias "_FreeImage_SetBackgroundColor@8" ( _
+ ByVal dib As Long, _
+ ByRef bkcolor As Long) As Long
+
+
+' Filetype functions (p. 20 to 21)
+Public Declare Function FreeImage_GetFileType Lib "FreeImage.dll" Alias "_FreeImage_GetFileType@8" ( _
+ ByVal Filename As String, _
+ Optional ByVal Size As Long = 0) As FREE_IMAGE_FORMAT
+
+Private Declare Function FreeImage_GetFileTypeUInt Lib "FreeImage.dll" Alias "_FreeImage_GetFileTypeU@8" ( _
+ ByVal Filename As Long, _
+ Optional ByVal Size As Long = 0) As FREE_IMAGE_FORMAT
+
+Public Declare Function FreeImage_GetFileTypeFromHandle Lib "FreeImage.dll" Alias "_FreeImage_GetFileTypeFromHandle@12" ( _
+ ByVal io As Long, _
+ ByVal Handle As Long, _
+ Optional ByVal Size As Long = 0) As FREE_IMAGE_FORMAT
+
+Public Declare Function FreeImage_GetFileTypeFromMemory Lib "FreeImage.dll" Alias "_FreeImage_GetFileTypeFromMemory@8" ( _
+ ByVal Stream As Long, _
+ Optional ByVal Size As Long = 0) As FREE_IMAGE_FORMAT
+
+
+' Pixel access functions (p. 22 to 27)
+Public Declare Function FreeImage_GetBits Lib "FreeImage.dll" Alias "_FreeImage_GetBits@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_GetScanline Lib "FreeImage.dll" Alias "_FreeImage_GetScanLine@8" ( _
+ ByVal dib As Long, _
+ ByVal Scanline As Long) As Long
+
+Private Declare Function FreeImage_GetPixelIndexInt Lib "FreeImage.dll" Alias "_FreeImage_GetPixelIndex@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Byte) As Long
+
+Private Declare Function FreeImage_GetPixelColorInt Lib "FreeImage.dll" Alias "_FreeImage_GetPixelColor@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As RGBQUAD) As Long
+
+Private Declare Function FreeImage_GetPixelColorByLongInt Lib "FreeImage.dll" Alias "_FreeImage_GetPixelColor@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Long) As Long
+
+Private Declare Function FreeImage_SetPixelIndexInt Lib "FreeImage.dll" Alias "_FreeImage_SetPixelIndex@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Byte) As Long
+
+Private Declare Function FreeImage_SetPixelColorInt Lib "FreeImage.dll" Alias "_FreeImage_SetPixelColor@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As RGBQUAD) As Long
+
+Private Declare Function FreeImage_SetPixelColorByLongInt Lib "FreeImage.dll" Alias "_FreeImage_SetPixelColor@16" ( _
+ ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Long) As Long
+
+
+
+' Conversion functions (p. 28 to 33)
+Public Declare Function FreeImage_ConvertTo4Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo4Bits@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertTo8Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo8Bits@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertToGreyscale Lib "FreeImage.dll" Alias "_FreeImage_ConvertToGreyscale@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertTo16Bits555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo16Bits555@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertTo16Bits565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo16Bits565@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertTo24Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo24Bits@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ConvertTo32Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo32Bits@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_ColorQuantize Lib "FreeImage.dll" Alias "_FreeImage_ColorQuantize@8" ( _
+ ByVal dib As Long, _
+ ByVal quantize As FREE_IMAGE_QUANTIZE) As Long
+
+Private Declare Function FreeImage_ColorQuantizeExInt Lib "FreeImage.dll" Alias "_FreeImage_ColorQuantizeEx@20" ( _
+ ByVal dib As Long, _
+ Optional ByVal quantize As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT, _
+ Optional ByVal PaletteSize As Long = 256, _
+ Optional ByVal ReserveSize As Long = 0, _
+ Optional ByVal ReservePalette As Long = 0) As Long
+
+Public Declare Function FreeImage_Threshold Lib "FreeImage.dll" Alias "_FreeImage_Threshold@8" ( _
+ ByVal dib As Long, _
+ ByVal t As Byte) As Long
+
+Public Declare Function FreeImage_Dither Lib "FreeImage.dll" Alias "_FreeImage_Dither@8" ( _
+ ByVal dib As Long, _
+ ByVal algorithm As FREE_IMAGE_DITHER) As Long
+
+Public Declare Function FreeImage_ConvertFromRawBits Lib "FreeImage.dll" Alias "_FreeImage_ConvertFromRawBits@36" ( _
+ ByRef Bits As Long, _
+ ByVal Width As Long, _
+ ByVal Height As Long, _
+ ByVal pitch As Long, _
+ ByVal bpp As Long, _
+ ByVal red_mask As Long, _
+ ByVal green_mask As Long, _
+ ByVal blue_mask As Long, _
+ Optional ByVal topdown As Long = 0) As Long
+
+Public Declare Sub FreeImage_ConvertToRawBits Lib "FreeImage.dll" Alias "_FreeImage_ConvertToRawBits@32" ( _
+ ByRef Bits As Long, _
+ ByVal dib As Long, _
+ ByVal pitch As Long, _
+ ByVal bpp As Long, _
+ ByVal red_mask As Long, _
+ ByVal green_mask As Long, _
+ ByVal blue_mask As Long, _
+ Optional ByVal topdown As Long = 0)
+
+Public Declare Function FreeImage_ConvertToStandardType Lib "FreeImage.dll" Alias "_FreeImage_ConvertToStandardType@8" ( _
+ ByVal src As Long, _
+ Optional ByVal scale_linear As Long = 1) As Long
+
+Public Declare Function FreeImage_ConvertToType Lib "FreeImage.dll" Alias "_FreeImage_ConvertToType@12" ( _
+ ByVal src As Long, _
+ ByVal dst_type As FREE_IMAGE_TYPE, _
+ Optional ByVal scale_linear As Long = 1) As Long
+
+Public Declare Function FreeImage_ConvertToRGBF Lib "FreeImage.dll" Alias "_FreeImage_ConvertToRGBF@4" ( _
+ ByVal dib As Long) As Long
+
+
+' Tone mapping operators (p. 34 to 35)
+Public Declare Function FreeImage_ToneMapping Lib "FreeImage.dll" Alias "_FreeImage_ToneMapping@24" ( _
+ ByVal dib As Long, _
+ ByVal tmo As FREE_IMAGE_TMO, _
+ Optional ByVal first_param As Double = 0, _
+ Optional ByVal second_param As Double = 0) As Long
+
+Public Declare Function FreeImage_TmoDrago03 Lib "FreeImage.dll" Alias "_FreeImage_TmoDrago03@20" ( _
+ ByVal src As Long, _
+ Optional ByVal gamma As Double = 2.2, _
+ Optional ByVal exposure As Double = 0) As Long
+
+Public Declare Function FreeImage_TmoReinhard05 Lib "FreeImage.dll" Alias "_FreeImage_TmoReinhard05@20" ( _
+ ByVal src As Long, _
+ Optional ByVal intensity As Double = 0, _
+ Optional ByVal Contrast As Double = 0) As Long
+
+Public Declare Function FreeImage_TmoReinhard05Ex Lib "FreeImage.dll" Alias "_FreeImage_TmoReinhard05Ex@36" ( _
+ ByVal src As Long, _
+ Optional ByVal intensity As Double = 0, _
+ Optional ByVal Contrast As Double = 0, _
+ Optional adaptation As Double = 1, _
+ Optional color_correction As Double = 0) As Long
+
+Public Declare Function FreeImage_TmoFattal02 Lib "FreeImage.dll" Alias "_FreeImage_TmoFattal02@20" ( _
+ ByVal src As Long, _
+ Optional ByVal color_saturation As Double = 0.5, _
+ Optional ByVal attenuation As Double = 0.85) As Long
+
+
+' ICC profile functions (p. 36 to 37)
+Private Declare Function FreeImage_GetICCProfileInt Lib "FreeImage.dll" Alias "_FreeImage_GetICCProfile@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_CreateICCProfile Lib "FreeImage.dll" Alias "_FreeImage_CreateICCProfile@12" ( _
+ ByVal dib As Long, _
+ ByRef Data As Long, _
+ ByVal Size As Long) As Long
+
+Public Declare Sub FreeImage_DestroyICCProfile Lib "FreeImage.dll" Alias "_FreeImage_DestroyICCProfile@4" ( _
+ ByVal dib As Long)
+
+
+' Plugin functions (p. 38 to 44)
+Public Declare Function FreeImage_GetFIFCount Lib "FreeImage.dll" Alias "_FreeImage_GetFIFCount@0" () As Long
+
+Public Declare Function FreeImage_SetPluginEnabled Lib "FreeImage.dll" Alias "_FreeImage_SetPluginEnabled@8" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal enable As Long) As Long
+
+Public Declare Function FreeImage_IsPluginEnabled Lib "FreeImage.dll" Alias "_FreeImage_IsPluginEnabled@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Public Declare Function FreeImage_GetFIFFromFormat Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromFormat@4" ( _
+ ByVal Format As String) As FREE_IMAGE_FORMAT
+
+Public Declare Function FreeImage_GetFIFFromMime Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromMime@4" ( _
+ ByVal mime As String) As FREE_IMAGE_FORMAT
+
+Private Declare Function FreeImage_GetFIFMimeTypeInt Lib "FreeImage.dll" Alias "_FreeImage_GetFIFMimeType@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_GetFormatFromFIFInt Lib "FreeImage.dll" Alias "_FreeImage_GetFormatFromFIF@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_GetFIFExtensionListInt Lib "FreeImage.dll" Alias "_FreeImage_GetFIFExtensionList@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_GetFIFDescriptionInt Lib "FreeImage.dll" Alias "_FreeImage_GetFIFDescription@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_GetFIFRegExprInt Lib "FreeImage.dll" Alias "_FreeImage_GetFIFRegExpr@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Public Declare Function FreeImage_GetFIFFromFilename Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromFilename@4" ( _
+ ByVal Filename As String) As FREE_IMAGE_FORMAT
+
+Private Declare Function FreeImage_GetFIFFromFilenameUInt Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromFilenameU@4" ( _
+ ByVal Filename As Long) As FREE_IMAGE_FORMAT
+
+Private Declare Function FreeImage_FIFSupportsReadingInt Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsReading@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_FIFSupportsWritingInt Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsWriting@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Private Declare Function FreeImage_FIFSupportsExportTypeInt Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsExportType@8" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal type_ As FREE_IMAGE_TYPE) As Long
+
+Private Declare Function FreeImage_FIFSupportsExportBPPInt Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsExportBPP@8" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal bpp As Long) As Long
+
+Private Declare Function FreeImage_FIFSupportsICCProfilesInt Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsICCProfiles@4" ( _
+ ByVal fif As FREE_IMAGE_FORMAT) As Long
+
+Public Declare Function FreeImage_RegisterLocalPlugin Lib "FreeImage.dll" Alias "_FreeImage_RegisterLocalPlugin@20" ( _
+ ByVal proc_address As Long, _
+ Optional ByVal Format As String = 0, _
+ Optional ByVal Description As String = 0, _
+ Optional ByVal extension As String = 0, _
+ Optional ByVal regexpr As String = 0) As FREE_IMAGE_FORMAT
+
+Public Declare Function FreeImage_RegisterExternalPlugin Lib "FreeImage.dll" Alias "_FreeImage_RegisterExternalPlugin@20" ( _
+ ByVal Path As String, _
+ Optional ByVal Format As String = 0, _
+ Optional ByVal Description As String = 0, _
+ Optional ByVal extension As String = 0, _
+ Optional ByVal regexpr As String = 0) As FREE_IMAGE_FORMAT
+
+
+' Multipage functions (p. 45 to 46)
+Public Declare Function FreeImage_OpenMultiBitmap Lib "FreeImage.dll" Alias "_FreeImage_OpenMultiBitmap@24" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Filename As String, _
+ ByVal create_new As Long, _
+ ByVal read_only As Long, _
+ Optional ByVal keep_cache_in_memory As Long = 0, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+Private Declare Function FreeImage_CloseMultiBitmapInt Lib "FreeImage.dll" Alias "_FreeImage_CloseMultiBitmap@8" ( _
+ ByVal bitmap As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Long
+
+Public Declare Function FreeImage_GetPageCount Lib "FreeImage.dll" Alias "_FreeImage_GetPageCount@4" ( _
+ ByVal bitmap As Long) As Long
+
+Public Declare Sub FreeImage_AppendPage Lib "FreeImage.dll" Alias "_FreeImage_AppendPage@8" ( _
+ ByVal bitmap As Long, _
+ ByVal Data As Long)
+
+Public Declare Sub FreeImage_InsertPage Lib "FreeImage.dll" Alias "_FreeImage_InsertPage@12" ( _
+ ByVal bitmap As Long, _
+ ByVal Page As Long, _
+ ByVal Data As Long)
+
+Public Declare Sub FreeImage_DeletePage Lib "FreeImage.dll" Alias "_FreeImage_DeletePage@8" ( _
+ ByVal bitmap As Long, _
+ ByVal Page As Long)
+
+Public Declare Function FreeImage_LockPage Lib "FreeImage.dll" Alias "_FreeImage_LockPage@8" ( _
+ ByVal bitmap As Long, _
+ ByVal Page As Long) As Long
+
+Public Declare Sub FreeImage_UnlockPage Lib "FreeImage.dll" Alias "_FreeImage_UnlockPage@12" ( _
+ ByVal bitmap As Long, _
+ ByVal hPageDib As Long, _
+ ByVal Changed As Long)
+
+Private Declare Function FreeImage_MovePageInt Lib "FreeImage.dll" Alias "_FreeImage_MovePage@12" ( _
+ ByVal bitmap As Long, _
+ ByVal Target As Long, _
+ ByVal Source As Long) As Long
+
+Private Declare Function FreeImage_GetLockedPageNumbersInt Lib "FreeImage.dll" Alias "_FreeImage_GetLockedPageNumbers@12" ( _
+ ByVal bitmap As Long, _
+ ByRef Pages As Long, _
+ ByRef Count As Long) As Long
+
+
+' Memory I/O streams (p. 48 to 52)
+Public Declare Function FreeImage_OpenMemory Lib "FreeImage.dll" Alias "_FreeImage_OpenMemory@8" ( _
+ Optional ByRef Data As Byte = 0, _
+ Optional ByVal size_in_bytes As Long = 0) As Long
+
+Public Declare Function FreeImage_OpenMemoryByPtr Lib "FreeImage.dll" Alias "_FreeImage_OpenMemory@8" ( _
+ Optional ByVal data_ptr As Long, _
+ Optional ByVal size_in_bytes As Long = 0) As Long
+
+Public Declare Sub FreeImage_CloseMemory Lib "FreeImage.dll" Alias "_FreeImage_CloseMemory@4" ( _
+ ByVal Stream As Long)
+
+Public Declare Function FreeImage_LoadFromMemory Lib "FreeImage.dll" Alias "_FreeImage_LoadFromMemory@12" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Stream As Long, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+Private Declare Function FreeImage_SaveToMemoryInt Lib "FreeImage.dll" Alias "_FreeImage_SaveToMemory@16" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Stream As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Long
+
+Private Declare Function FreeImage_AcquireMemoryInt Lib "FreeImage.dll" Alias "_FreeImage_AcquireMemory@12" ( _
+ ByVal Stream As Long, _
+ ByRef Data As Long, _
+ ByRef size_in_bytes As Long) As Long
+
+Public Declare Function FreeImage_TellMemory Lib "FreeImage.dll" Alias "_FreeImage_TellMemory@4" ( _
+ ByVal Stream As Long) As Long
+
+Private Declare Function FreeImage_SeekMemoryInt Lib "FreeImage.dll" Alias "_FreeImage_SeekMemory@12" ( _
+ ByVal Stream As Long, _
+ ByVal Offset As Long, _
+ ByVal Origin As Long) As Long
+
+Public Declare Function FreeImage_ReadMemory Lib "FreeImage.dll" Alias "_FreeImage_ReadMemory@16" ( _
+ ByVal Buffer As Long, _
+ ByVal Size As Long, _
+ ByVal Count As Long, _
+ ByVal Stream As Long) As Long
+
+Public Declare Function FreeImage_WriteMemory Lib "FreeImage.dll" Alias "_FreeImage_WriteMemory@16" ( _
+ ByVal Buffer As Long, _
+ ByVal Size As Long, _
+ ByVal Count As Long, _
+ ByVal Stream As Long) As Long
+
+Public Declare Function FreeImage_LoadMultiBitmapFromMemory Lib "FreeImage.dll" Alias "_FreeImage_LoadMultiBitmapFromMemory@12" ( _
+ ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Stream As Long, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+
+' Compression functions (p. 54 to 56)
+Public Declare Function FreeImage_ZLibCompress Lib "FreeImage.dll" Alias "_FreeImage_ZLibCompress@16" ( _
+ ByVal Target As Long, _
+ ByVal target_size As Long, _
+ ByVal Source As Long, _
+ ByVal source_size As Long) As Long
+
+Public Declare Function FreeImage_ZLibUncompress Lib "FreeImage.dll" Alias "_FreeImage_ZLibUncompress@16" ( _
+ ByVal Target As Long, _
+ ByVal target_size As Long, _
+ ByVal Source As Long, _
+ ByVal source_size As Long) As Long
+
+Public Declare Function FreeImage_ZLibGZip Lib "FreeImage.dll" Alias "_FreeImage_ZLibGZip@16" ( _
+ ByVal Target As Long, _
+ ByVal target_size As Long, _
+ ByVal Source As Long, _
+ ByVal source_size As Long) As Long
+
+Public Declare Function FreeImage_ZLibGUnzip Lib "FreeImage.dll" Alias "_FreeImage_ZLibGUnzip@16" ( _
+ ByVal Target As Long, _
+ ByVal target_size As Long, _
+ ByVal Source As Long, _
+ ByVal source_size As Long) As Long
+
+Public Declare Function FreeImage_ZLibCRC32 Lib "FreeImage.dll" Alias "_FreeImage_ZLibCRC32@12" ( _
+ ByVal crc As Long, _
+ ByVal Source As Long, _
+ ByVal source_size As Long) As Long
+
+
+' Helper functions (p. 57 to 57)
+Private Declare Function FreeImage_IsLittleEndianInt Lib "FreeImage.dll" Alias "_FreeImage_IsLittleEndian@0" () As Long
+
+Private Declare Function FreeImage_LookupX11ColorInt Lib "FreeImage.dll" Alias "_FreeImage_LookupX11Color@16" ( _
+ ByVal szColor As String, _
+ ByRef nRed As Long, _
+ ByRef nGreen As Long, _
+ ByRef nBlue As Long) As Long
+
+Private Declare Function FreeImage_LookupSVGColorInt Lib "FreeImage.dll" Alias "_FreeImage_LookupSVGColor@16" ( _
+ ByVal szColor As String, _
+ ByRef nRed As Long, _
+ ByRef nGreen As Long, _
+ ByRef nBlue As Long) As Long
+
+
+'--------------------------------------------------------------------------------
+' Metadata functions
+'--------------------------------------------------------------------------------
+
+' Tag creation and destruction (p. 61 to 61)
+Private Declare Function FreeImage_CreateTag Lib "FreeImage.dll" Alias "_FreeImage_CreateTag@0" () As Long
+
+Private Declare Sub FreeImage_DeleteTag Lib "FreeImage.dll" Alias "_FreeImage_DeleteTag@4" ( _
+ ByVal Tag As Long)
+
+Private Declare Function FreeImage_CloneTag Lib "FreeImage.dll" Alias "_FreeImage_CloneTag@4" ( _
+ ByVal Tag As Long) As Long
+
+
+' Tag accessors (p. 62 to 64) (only those needed by wrapper functions)
+Private Declare Function FreeImage_SetTagKey Lib "FreeImage.dll" Alias "_FreeImage_SetTagKey@8" ( _
+ ByVal Tag As Long, _
+ ByVal Key As String) As Long
+
+Private Declare Function FreeImage_SetTagValue Lib "FreeImage.dll" Alias "_FreeImage_SetTagValue@8" ( _
+ ByVal Tag As Long, _
+ ByVal lpVoidPtr As Long) As Long
+
+' Metadata iterator (p. 65 to 65)
+Public Declare Function FreeImage_FindFirstMetadata Lib "FreeImage.dll" Alias "_FreeImage_FindFirstMetadata@12" ( _
+ ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal dib As Long, _
+ ByRef Tag As Long) As Long
+
+Private Declare Function FreeImage_FindNextMetadataInt Lib "FreeImage.dll" Alias "_FreeImage_FindNextMetadata@8" ( _
+ ByVal mdhandle As Long, _
+ ByRef Tag As Long) As Long
+
+Public Declare Sub FreeImage_FindCloseMetadata Lib "FreeImage.dll" Alias "_FreeImage_FindCloseMetadata@4" ( _
+ ByVal mdhandle As Long)
+
+Public Declare Function FreeImage_CloneMetadataInt Lib "FreeImage.dll" Alias "_FreeImage_CloneMetadata@8" ( _
+ ByVal dst As Long, _
+ ByVal src As Long) As Long
+
+
+' Metadata accessors (p. 66 to 66)
+Private Declare Function FreeImage_SetMetadataInt Lib "FreeImage.dll" Alias "_FreeImage_SetMetadata@16" ( _
+ ByVal Model As Long, _
+ ByVal dib As Long, _
+ ByVal Key As String, _
+ ByVal Tag As Long) As Long
+
+Private Declare Function FreeImage_GetMetadataInt Lib "FreeImage.dll" Alias "_FreeImage_GetMetadata@16" ( _
+ ByVal Model As Long, _
+ ByVal dib As Long, _
+ ByVal Key As String, _
+ ByRef Tag As Long) As Long
+
+
+' Metadata helper functions (p. 68 to 68)
+Public Declare Function FreeImage_GetMetadataCount Lib "FreeImage.dll" Alias "_FreeImage_GetMetadataCount@8" ( _
+ ByVal Model As Long, _
+ ByVal dib As Long) As Long
+
+Private Declare Function FreeImage_TagToStringInt Lib "FreeImage.dll" Alias "_FreeImage_TagToString@12" ( _
+ ByVal Model As Long, _
+ ByVal Tag As Long, _
+ Optional ByVal Make As String = vbNullString) As Long
+
+
+'--------------------------------------------------------------------------------
+' Toolkit functions
+'--------------------------------------------------------------------------------
+
+' Rotating and flipping (p. 70 to 72)
+Public Declare Function FreeImage_RotateClassic Lib "FreeImage.dll" Alias "_FreeImage_RotateClassic@12" ( _
+ ByVal dib As Long, _
+ ByVal angle As Double) As Long
+
+Public Declare Function FreeImage_Rotate Lib "FreeImage.dll" Alias "_FreeImage_Rotate@16" ( _
+ ByVal dib As Long, _
+ ByVal angle As Double, _
+ Optional ByRef Color As Any) As Long
+
+Public Declare Function FreeImage_RotateEx Lib "FreeImage.dll" Alias "_FreeImage_RotateEx@48" ( _
+ ByVal dib As Long, _
+ ByVal angle As Double, _
+ ByVal x_shift As Double, _
+ ByVal y_shift As Double, _
+ ByVal x_origin As Double, _
+ ByVal y_origin As Double, _
+ ByVal use_mask As Long) As Long
+
+Private Declare Function FreeImage_FlipHorizontalInt Lib "FreeImage.dll" Alias "_FreeImage_FlipHorizontal@4" ( _
+ ByVal dib As Long) As Long
+
+Private Declare Function FreeImage_FlipVerticalInt Lib "FreeImage.dll" Alias "_FreeImage_FlipVertical@4" ( _
+ ByVal dib As Long) As Long
+
+Private Declare Function FreeImage_JPEGTransformInt Lib "FreeImage.dll" Alias "_FreeImage_JPEGTransform@16" ( _
+ ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal operation As FREE_IMAGE_JPEG_OPERATION, _
+ Optional ByVal prefect As Long = 0) As Long
+
+Private Declare Function FreeImage_JPEGTransformUInt Lib "FreeImage.dll" Alias "_FreeImage_JPEGTransformU@16" ( _
+ ByVal src_file As Long, _
+ ByVal dst_file As Long, _
+ ByVal operation As FREE_IMAGE_JPEG_OPERATION, _
+ Optional ByVal prefect As Long = 0) As Long
+
+
+' Upsampling and downsampling (p. 73 to 74)
+Public Declare Function FreeImage_Rescale Lib "FreeImage.dll" Alias "_FreeImage_Rescale@16" ( _
+ ByVal dib As Long, _
+ ByVal dst_width As Long, _
+ ByVal dst_height As Long, _
+ ByVal Filter As FREE_IMAGE_FILTER) As Long
+
+Public Declare Function FreeImage_MakeThumbnail Lib "FreeImage.dll" Alias "_FreeImage_MakeThumbnail@12" ( _
+ ByVal dib As Long, _
+ ByVal max_pixel_size As Long, _
+ Optional ByVal convert As Boolean = True) As Long
+
+
+' Color manipulation (p. 75 to 80)
+Private Declare Function FreeImage_AdjustCurveInt Lib "FreeImage.dll" Alias "_FreeImage_AdjustCurve@12" ( _
+ ByVal dib As Long, _
+ ByVal LUT As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+
+Private Declare Function FreeImage_AdjustGammaInt Lib "FreeImage.dll" Alias "_FreeImage_AdjustGamma@12" ( _
+ ByVal dib As Long, _
+ ByVal gamma As Double) As Long
+
+Private Declare Function FreeImage_AdjustBrightnessInt Lib "FreeImage.dll" Alias "_FreeImage_AdjustBrightness@12" ( _
+ ByVal dib As Long, _
+ ByVal percentage As Double) As Long
+
+Private Declare Function FreeImage_AdjustContrastInt Lib "FreeImage.dll" Alias "_FreeImage_AdjustContrast@12" ( _
+ ByVal dib As Long, _
+ ByVal percentage As Double) As Long
+
+Private Declare Function FreeImage_InvertInt Lib "FreeImage.dll" Alias "_FreeImage_Invert@4" ( _
+ ByVal dib As Long) As Long
+
+Private Declare Function FreeImage_GetHistogramInt Lib "FreeImage.dll" Alias "_FreeImage_GetHistogram@12" ( _
+ ByVal dib As Long, _
+ ByRef histo As Long, _
+ Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK) As Long
+
+Public Declare Function FreeImage_GetAdjustColorsLookupTable Lib "FreeImage.dll" Alias "_FreeImage_GetAdjustColorsLookupTable@32" ( _
+ ByVal LUT As Long, _
+ Optional ByVal Brightness As Double, _
+ Optional ByVal Contrast As Double, _
+ Optional ByVal gamma As Double = 1, _
+ Optional ByVal invert As Boolean) As Long
+
+Private Declare Function FreeImage_AdjustColorsInt Lib "FreeImage.dll" Alias "_FreeImage_AdjustColors@32" ( _
+ ByVal dib As Long, _
+ Optional ByVal Brightness As Double, _
+ Optional ByVal Contrast As Double, _
+ Optional ByVal gamma As Double = 1, _
+ Optional ByVal invert As Boolean) As Long
+
+Public Declare Function FreeImage_ApplyColorMapping Lib "FreeImage.dll" Alias "_FreeImage_ApplyColorMapping@24" ( _
+ ByVal dib As Long, _
+ ByVal srccolors As Long, _
+ ByVal dstcolors As Long, _
+ ByVal Count As Long, _
+ Optional ByVal ignore_alpha As Boolean = True, _
+ Optional ByVal swap As Boolean) As Long
+
+Public Declare Function FreeImage_SwapColors Lib "FreeImage.dll" Alias "_FreeImage_SwapColors@16" ( _
+ ByVal dib As Long, _
+ ByRef color_a As RGBQUAD, _
+ ByRef color_b As RGBQUAD, _
+ Optional ByVal ignore_alpha As Boolean = True) As Long
+
+Public Declare Function FreeImage_SwapColorsByLong Lib "FreeImage.dll" Alias "_FreeImage_SwapColors@16" ( _
+ ByVal dib As Long, _
+ ByRef color_a As Long, _
+ ByRef color_b As Long, _
+ Optional ByVal ignore_alpha As Boolean = True) As Long
+
+Public Declare Function FreeImage_ApplyIndexMapping Lib "FreeImage.dll" Alias "_FreeImage_ApplyIndexMapping@20" ( _
+ ByVal dib As Long, _
+ ByVal srcindices As Long, _
+ ByVal dstindices As Long, _
+ ByVal Count As Long, _
+ Optional ByVal swap As Boolean) As Long
+
+Public Declare Function FreeImage_SwapPaletteIndices Lib "FreeImage.dll" Alias "_FreeImage_SwapPaletteIndices@12" ( _
+ ByVal dib As Long, _
+ ByRef index_a As Byte, _
+ ByRef index_b As Byte) As Long
+
+' Channel processing (p. 81 to 81)
+Public Declare Function FreeImage_GetChannel Lib "FreeImage.dll" Alias "_FreeImage_GetChannel@8" ( _
+ ByVal dib As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+
+Private Declare Function FreeImage_SetChannelInt Lib "FreeImage.dll" Alias "_FreeImage_SetChannel@12" ( _
+ ByVal dib As Long, _
+ ByVal dib8 As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+
+Public Declare Function FreeImage_GetComplexChannel Lib "FreeImage.dll" Alias "_FreeImage_GetComplexChannel@8" ( _
+ ByVal src As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+
+Private Declare Function FreeImage_SetComplexChannelInt Lib "FreeImage.dll" Alias "_FreeImage_SetComplexChannel@12" ( _
+ ByVal dst As Long, _
+ ByVal src As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+
+
+' Copy / Paste / Composite routines (p. 82 to 84)
+Public Declare Function FreeImage_Copy Lib "FreeImage.dll" Alias "_FreeImage_Copy@20" ( _
+ ByVal dib As Long, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As Long
+
+Private Declare Function FreeImage_PasteInt Lib "FreeImage.dll" Alias "_FreeImage_Paste@20" ( _
+ ByVal dst As Long, _
+ ByVal src As Long, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Alpha As Long) As Long
+
+Public Declare Function FreeImage_Composite Lib "FreeImage.dll" Alias "_FreeImage_Composite@16" ( _
+ ByVal fg As Long, _
+ Optional ByVal useFileBkg As Boolean = False, _
+ Optional ByVal appBkColor As Long, _
+ Optional ByVal bg As Long = 0) As Long
+
+Public Declare Function FreeImage_CompositeByLong Lib "FreeImage.dll" Alias "_FreeImage_Composite@16" ( _
+ ByVal fg As Long, _
+ Optional ByVal useFileBkg As Boolean = False, _
+ Optional ByRef appBkColor As Long = 0, _
+ Optional ByVal bg As Long = 0) As Long
+
+Private Declare Function FreeImage_JPEGCropInt Lib "FreeImage.dll" Alias "_FreeImage_JPEGCrop@24" ( _
+ ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As Long
+
+Private Declare Function FreeImage_JPEGCropUInt Lib "FreeImage.dll" Alias "_FreeImage_JPEGCropU@24" ( _
+ ByVal src_file As Long, _
+ ByVal dst_file As Long, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As Long
+
+Private Declare Function FreeImage_PreMultiplyWithAlphaInt Lib "FreeImage.dll" Alias "_FreeImage_PreMultiplyWithAlpha@4" ( _
+ ByVal dib As Long) As Long
+
+Public Declare Function FreeImage_FillBackground Lib "FreeImage.dll" Alias "_FreeImage_FillBackground@12" ( _
+ ByVal dib As Long, _
+ ByRef Color As Any, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS = FI_COLOR_IS_RGB_COLOR) As Long
+
+Public Declare Function FreeImage_EnlargeCanvas Lib "FreeImage.dll" Alias "_FreeImage_EnlargeCanvas@28" ( _
+ ByVal dib As Long, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long, _
+ ByRef Color As Any, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS = FI_COLOR_IS_RGB_COLOR) As Long
+
+Public Declare Function FreeImage_AllocateEx Lib "FreeImage.dll" Alias "_FreeImage_AllocateEx@36" ( _
+ ByVal Width As Long, _
+ ByVal Height As Long, _
+ Optional ByVal bpp As Long = 8, _
+ Optional ByRef Color As Any, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS, _
+ Optional ByVal lpPalette As Long = 0, _
+ Optional ByVal red_mask As Long = 0, _
+ Optional ByVal green_mask As Long = 0, _
+ Optional ByVal blue_mask As Long = 0) As Long
+
+Public Declare Function FreeImage_AllocateExT Lib "FreeImage.dll" Alias "_FreeImage_AllocateExT@36" ( _
+ ByVal type_ As FREE_IMAGE_TYPE, _
+ ByVal Width As Long, _
+ ByVal Height As Long, _
+ Optional ByVal bpp As Long = 8, _
+ Optional ByRef Color As Any, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS, _
+ Optional ByVal lpPalette As Long = 0, _
+ Optional ByVal red_mask As Long = 0, _
+ Optional ByVal green_mask As Long = 0, _
+ Optional ByVal blue_mask As Long = 0) As Long
+
+' miscellaneous algorithms (p. 85 to 85)
+Public Declare Function FreeImage_MultigridPoissonSolver Lib "FreeImage.dll" Alias "_FreeImage_MultigridPoissonSolver@8" ( _
+ ByVal Laplacian As Long, _
+ Optional ByVal ncycle As Long = 3) As Long
+
+
+'--------------------------------------------------------------------------------
+' Line converting functions
+'--------------------------------------------------------------------------------
+
+' convert to 4 bpp
+Public Declare Sub FreeImage_ConvertLine1To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To4@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine8To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To8@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To4_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To4_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To4_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To4_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine24To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To24@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine32To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To4@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+
+' convert to 8 bpp
+Public Declare Sub FreeImage_ConvertLine1To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To8@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine4To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To8@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To8_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To8_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To8_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To8_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine24To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To8@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine32To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To8@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+
+' convert to 16 bpp
+Public Declare Sub FreeImage_ConvertLine1To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To16_555@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine4To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To16_555@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine8To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To16_555@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine16_565_To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16_565_To16_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine24To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To16_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine32To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To16_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine1To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To16_565@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine4To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To16_565@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine8To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To16_565@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine16_555_To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16_555_To16_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine24To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To16_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine32To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To16_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+
+' convert to 24 bpp
+Public Declare Sub FreeImage_ConvertLine1To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To24@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine4To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To24@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine8To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To24@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To24_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To24_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To24_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To24_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine32To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To24@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+
+' convert to 32 bpp
+Public Declare Sub FreeImage_ConvertLine1To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To32@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine4To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To32@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine8To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To32@16" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long, _
+ ByVal Palette As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To32_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To32_555@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine16To32_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To32_565@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+Public Declare Sub FreeImage_ConvertLine24To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To32@12" ( _
+ ByVal Target As Long, _
+ ByVal Source As Long, _
+ ByVal width_in_pixels As Long)
+
+
+
+'--------------------------------------------------------------------------------
+' Initialization functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_IsAvailable(Optional ByRef Version As String) As Boolean
+
+ On Error Resume Next
+ Version = FreeImage_GetVersion()
+ FreeImage_IsAvailable = (Err.Number = ERROR_SUCCESS)
+ On Error GoTo 0
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Error handling functions
+'--------------------------------------------------------------------------------
+
+Public Sub FreeImage_InitErrorHandler()
+
+ ' Call this function once for using the FreeImage 3 error handling callback.
+ ' The 'FreeImage_ErrorHandler' function is called on each FreeImage 3 error.
+
+ Call FreeImage_SetOutputMessage(AddressOf FreeImage_ErrorHandler)
+
+End Sub
+
+Private Sub FreeImage_ErrorHandler(ByVal fif As FREE_IMAGE_FORMAT, ByVal Message As Long)
+
+Dim strErrorMessage As String
+Dim strImageFormat As String
+
+ ' This function is called whenever the FreeImage 3 libraray throws an error.
+ ' Currently this function gets the error message and the format name of the
+ ' involved image type as VB string printing each to the VB Debug console. Feel
+ ' free to modify this function to call an error handling routine of your on.
+
+ strErrorMessage = pGetStringFromPointerA(Message)
+ strImageFormat = FreeImage_GetFormatFromFIF(fif)
+
+ Debug.Print "[FreeImage] Error: " & strErrorMessage
+ Debug.Print " Image: " & strImageFormat
+ Debug.Print " Code: " & fif
+
+End Sub
+
+
+
+'--------------------------------------------------------------------------------
+' String returning functions wrappers
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetVersion() As String
+
+ ' This function returns the version of the FreeImage 3 library
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ FreeImage_GetVersion = pGetStringFromPointerA(FreeImage_GetVersionInt)
+
+End Function
+
+Public Function FreeImage_GetCopyrightMessage() As String
+
+ ' This function returns the copyright message of the FreeImage 3 library
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ FreeImage_GetCopyrightMessage = pGetStringFromPointerA(FreeImage_GetCopyrightMessageInt)
+
+End Function
+
+Public Function FreeImage_GetFormatFromFIF(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+ ' This function returns the result of the 'FreeImage_GetFormatFromFIF' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' The parameter 'fif' works according to the FreeImage 3 API documentation.
+
+ FreeImage_GetFormatFromFIF = pGetStringFromPointerA(FreeImage_GetFormatFromFIFInt(fif))
+
+End Function
+
+Public Function FreeImage_GetFIFExtensionList(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+ ' This function returns the result of the 'FreeImage_GetFIFExtensionList' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' The parameter 'fif' works according to the FreeImage 3 API documentation.
+
+ FreeImage_GetFIFExtensionList = pGetStringFromPointerA(FreeImage_GetFIFExtensionListInt(fif))
+
+End Function
+
+Public Function FreeImage_GetFIFDescription(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+ ' This function returns the result of the 'FreeImage_GetFIFDescription' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' The parameter 'fif' works according to the FreeImage 3 API documentation.
+
+ FreeImage_GetFIFDescription = pGetStringFromPointerA(FreeImage_GetFIFDescriptionInt(fif))
+
+End Function
+
+Public Function FreeImage_GetFIFRegExpr(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+ ' This function returns the result of the 'FreeImage_GetFIFRegExpr' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' The parameter 'fif' works according to the FreeImage 3 API documentation.
+
+ FreeImage_GetFIFRegExpr = pGetStringFromPointerA(FreeImage_GetFIFRegExprInt(fif))
+
+End Function
+
+Public Function FreeImage_GetFIFMimeType(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+ ' This function returns the result of the 'FreeImage_GetFIFMimeType' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' The parameter 'fif' works according to the FreeImage 3 API documentation.
+
+ FreeImage_GetFIFMimeType = pGetStringFromPointerA(FreeImage_GetFIFMimeTypeInt(fif))
+
+End Function
+
+Public Function FreeImage_TagToString(ByVal Model As Long, _
+ ByVal Tag As Long, _
+ Optional ByVal Make As String = vbNullString) As String
+
+ ' This function returns the result of the 'FreeImage_TagToString' function
+ ' as VB String. Read paragraph 2 of the "General notes on implementation
+ ' and design" section to learn more about that technique.
+
+ ' All parameters work according to the FreeImage 3 API documentation.
+
+ FreeImage_TagToString = pGetStringFromPointerA(FreeImage_TagToStringInt(Model, Tag, Make))
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' UNICODE dealing functions wrappers
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_LoadU(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Filename As String, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT) As Long
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_LoadU = FreeImage_LoadUInt(fif, StrPtr(Filename), Flags)
+
+End Function
+
+Public Function FreeImage_SaveU(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Filename As String, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Boolean
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_SaveU = (FreeImage_SaveUInt(fif, dib, StrPtr(Filename), Flags) = 1)
+
+End Function
+
+Public Function FreeImage_GetFileTypeU(ByVal Filename As String, _
+ Optional ByVal Size As Long = 0) As FREE_IMAGE_FORMAT
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_GetFileTypeU = FreeImage_GetFileTypeUInt(StrPtr(Filename), Size)
+
+End Function
+
+Public Function FreeImage_GetFIFFromFilenameU(ByVal Filename As String) As FREE_IMAGE_FORMAT
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_GetFIFFromFilenameU = FreeImage_GetFIFFromFilenameUInt(StrPtr(Filename))
+
+End Function
+
+Public Function FreeImage_JPEGTransformU(ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal operation As FREE_IMAGE_JPEG_OPERATION, _
+ Optional ByVal prefect As Long = 0) As Boolean
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_JPEGTransformU = (FreeImage_JPEGTransformInt(StrPtr(src_file), StrPtr(dst_file), _
+ operation, prefect) = 1)
+
+End Function
+
+Public Function FreeImage_JPEGCropU(ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As Boolean
+
+ ' This function is just a thin wrapper to ease the call to an
+ ' UNICODE function. Since VB's BSTR strings are actually UNICODE
+ ' strings, we just need to pass the pointer to the string data
+ ' returned by the (undocumented) function StrPtr().
+
+ FreeImage_JPEGCropU = (FreeImage_JPEGCropInt(StrPtr(src_file), StrPtr(dst_file), Left, Top, Right, _
+ Bottom) = 1)
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' BOOL/Boolean returning functions wrappers
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_Save(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Filename As String, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_Save = (FreeImage_SaveInt(fif, dib, Filename, Flags) = 1)
+
+End Function
+
+Public Function FreeImage_SaveToHandle(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal io As Long, _
+ ByVal Handle As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SaveToHandle = (FreeImage_SaveToHandleInt(fif, dib, io, Handle, Flags) = 1)
+
+End Function
+
+Public Function FreeImage_IsTransparent(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_IsTransparent = (FreeImage_IsTransparentInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_HasBackgroundColor(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_HasBackgroundColor = (FreeImage_HasBackgroundColorInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_GetBackgroundColor(ByVal dib As Long, _
+ ByRef bkcolor As RGBQUAD) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetBackgroundColor = (FreeImage_GetBackgroundColorInt(dib, bkcolor) = 1)
+
+End Function
+
+Public Function FreeImage_GetBackgroundColorAsLong(ByVal dib As Long, _
+ ByVal bkcolor As Long) As Boolean
+
+ ' This function gets the background color of an image as FreeImage_GetBackgroundColor() does but
+ ' provides it's result as a Long value.
+
+ FreeImage_GetBackgroundColorAsLong = (FreeImage_GetBackgroundColorAsLongInt(dib, bkcolor) = 1)
+
+End Function
+
+Public Function FreeImage_GetBackgroundColorEx(ByVal dib As Long, _
+ ByRef Alpha As Byte, _
+ ByRef Red As Byte, _
+ ByRef Green As Byte, _
+ ByRef Blue As Byte) As Boolean
+
+Dim bkcolor As RGBQUAD
+
+ ' This function gets the background color of an image as FreeImage_GetBackgroundColor() does but
+ ' provides it's result as four different byte values, one for each color component.
+
+ FreeImage_GetBackgroundColorEx = (FreeImage_GetBackgroundColorInt(dib, bkcolor) = 1)
+ With bkcolor
+ Alpha = .rgbReserved
+ Red = .rgbRed
+ Green = .rgbGreen
+ Blue = .rgbBlue
+ End With
+
+End Function
+
+Public Function FreeImage_SetBackgroundColor(ByVal dib As Long, _
+ ByRef bkcolor As RGBQUAD) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetBackgroundColor = (FreeImage_SetBackgroundColorInt(dib, bkcolor) = 1)
+
+End Function
+
+Public Function FreeImage_SetBackgroundColorAsLong(ByVal dib As Long, _
+ ByVal bkcolor As Long) As Boolean
+
+ ' This function sets the background color of an image as FreeImage_SetBackgroundColor() does but
+ ' the color value to set must be provided as a Long value.
+
+ FreeImage_SetBackgroundColorAsLong = (FreeImage_SetBackgroundColorAsLongInt(dib, bkcolor) = 1)
+
+End Function
+
+Public Function FreeImage_SetBackgroundColorEx(ByVal dib As Long, _
+ ByVal Alpha As Byte, _
+ ByVal Red As Byte, _
+ ByVal Green As Byte, _
+ ByVal Blue As Byte) As Boolean
+
+Dim bkcolor As RGBQUAD
+
+ ' This function sets the color at position (x|y) as FreeImage_SetPixelColor() does but
+ ' the color value to set must be provided four different byte values, one for each
+ ' color component.
+
+ With bkcolor
+ .rgbReserved = Alpha
+ .rgbRed = Red
+ .rgbGreen = Green
+ .rgbBlue = Blue
+ End With
+ FreeImage_SetBackgroundColorEx = (FreeImage_SetBackgroundColorInt(dib, bkcolor) = 1)
+
+End Function
+
+Public Function FreeImage_GetPixelIndex(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Byte) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetPixelIndex = (FreeImage_GetPixelIndexInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_GetPixelColor(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As RGBQUAD) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetPixelColor = (FreeImage_GetPixelColorInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_GetPixelColorByLong(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Long) As Boolean
+
+ ' This function gets the color at position (x|y) as FreeImage_GetPixelColor() does but
+ ' provides it's result as a Long value.
+
+ FreeImage_GetPixelColorByLong = (FreeImage_GetPixelColorByLongInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_GetPixelColorEx(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Alpha As Byte, _
+ ByRef Red As Byte, _
+ ByRef Green As Byte, _
+ ByRef Blue As Byte) As Boolean
+
+Dim Value As RGBQUAD
+
+ ' This function gets the color at position (x|y) as FreeImage_GetPixelColor() does but
+ ' provides it's result as four different byte values, one for each color component.
+
+ FreeImage_GetPixelColorEx = (FreeImage_GetPixelColorInt(dib, x, y, Value) = 1)
+ With Value
+ Alpha = .rgbReserved
+ Red = .rgbRed
+ Green = .rgbGreen
+ Blue = .rgbBlue
+ End With
+
+End Function
+
+Public Function FreeImage_SetPixelIndex(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Byte) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetPixelIndex = (FreeImage_SetPixelIndexInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_SetPixelColor(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As RGBQUAD) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetPixelColor = (FreeImage_SetPixelColorInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_SetPixelColorByLong(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByRef Value As Long) As Boolean
+
+ ' This function sets the color at position (x|y) as FreeImage_SetPixelColor() does but
+ ' the color value to set must be provided as a Long value.
+
+ FreeImage_SetPixelColorByLong = (FreeImage_SetPixelColorByLongInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_SetPixelColorEx(ByVal dib As Long, _
+ ByVal x As Long, _
+ ByVal y As Long, _
+ ByVal Alpha As Byte, _
+ ByVal Red As Byte, _
+ ByVal Green As Byte, _
+ ByVal Blue As Byte) As Boolean
+
+Dim Value As RGBQUAD
+
+ ' This function sets the color at position (x|y) as FreeImage_SetPixelColor() does but
+ ' the color value to set must be provided four different byte values, one for each
+ ' color component.
+
+ With Value
+ .rgbReserved = Alpha
+ .rgbRed = Red
+ .rgbGreen = Green
+ .rgbBlue = Blue
+ End With
+ FreeImage_SetPixelColorEx = (FreeImage_SetPixelColorInt(dib, x, y, Value) = 1)
+
+End Function
+
+Public Function FreeImage_FIFSupportsReading(ByVal fif As FREE_IMAGE_FORMAT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FIFSupportsReading = (FreeImage_FIFSupportsReadingInt(fif) = 1)
+
+End Function
+
+Public Function FreeImage_FIFSupportsWriting(ByVal fif As FREE_IMAGE_FORMAT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FIFSupportsWriting = (FreeImage_FIFSupportsWritingInt(fif) = 1)
+
+End Function
+
+Public Function FreeImage_FIFSupportsExportType(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal type_ As FREE_IMAGE_TYPE) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FIFSupportsExportType = (FreeImage_FIFSupportsExportTypeInt(fif, type_) = 1)
+
+End Function
+
+Public Function FreeImage_FIFSupportsExportBPP(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal bpp As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FIFSupportsExportBPP = (FreeImage_FIFSupportsExportBPPInt(fif, bpp) = 1)
+
+End Function
+
+Public Function FreeImage_FIFSupportsICCProfiles(ByVal fif As FREE_IMAGE_FORMAT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FIFSupportsICCProfiles = (FreeImage_FIFSupportsICCProfilesInt(fif) = 1)
+
+End Function
+
+Public Function FreeImage_CloseMultiBitmap(ByVal bitmap As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_CloseMultiBitmap = (FreeImage_CloseMultiBitmapInt(bitmap, Flags) = 1)
+
+End Function
+
+Public Function FreeImage_MovePage(ByVal bitmap As Long, _
+ ByVal Target As Long, _
+ ByVal Source As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_MovePage = (FreeImage_MovePageInt(bitmap, Target, Source) = 1)
+
+End Function
+
+Public Function FreeImage_GetLockedPageNumbers(ByVal bitmap As Long, _
+ ByRef Pages As Long, _
+ ByRef Count As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetLockedPageNumbers = (FreeImage_GetLockedPageNumbersInt(bitmap, Pages, Count) = 1)
+
+End Function
+
+Public Function FreeImage_SaveToMemory(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByVal Stream As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SaveToMemory = (FreeImage_SaveToMemoryInt(fif, dib, Stream, Flags) = 1)
+
+End Function
+
+Public Function FreeImage_AcquireMemory(ByVal Stream As Long, _
+ ByRef Data As Long, _
+ ByRef size_in_bytes As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AcquireMemory = (FreeImage_AcquireMemoryInt(Stream, Data, size_in_bytes) = 1)
+
+End Function
+
+Public Function FreeImage_SeekMemory(ByVal Stream As Long, _
+ ByVal Offset As Long, _
+ ByVal Origin As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SeekMemory = (FreeImage_SeekMemoryInt(Stream, Offset, Origin) = 1)
+
+End Function
+
+Public Function FreeImage_IsLittleEndian() As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_IsLittleEndian = (FreeImage_IsLittleEndianInt() = 1)
+
+End Function
+
+Public Function FreeImage_LookupX11Color(ByVal szColor As String, _
+ ByRef nRed As Long, _
+ ByRef nGreen As Long, _
+ ByRef nBlue As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_LookupX11Color = (FreeImage_LookupX11ColorInt(szColor, nRed, nGreen, nBlue) = 1)
+
+End Function
+
+Public Function FreeImage_LookupSVGColor(ByVal szColor As String, _
+ ByRef nRed As Long, _
+ ByRef nGreen As Long, _
+ ByRef nBlue As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_LookupSVGColor = (FreeImage_LookupSVGColorInt(szColor, nRed, nGreen, nBlue) = 1)
+
+End Function
+
+Public Function FreeImage_FindNextMetadata(ByVal mdhandle As Long, _
+ ByRef Tag As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FindNextMetadata = (FreeImage_FindNextMetadataInt(mdhandle, Tag) = 1)
+
+End Function
+
+Public Function FreeImage_CloneMetadata(ByVal dst As Long, _
+ ByVal src As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_CloneMetadata = (FreeImage_CloneMetadataInt(dst, src) = 1)
+
+End Function
+
+Public Function FreeImage_GetMetadata(ByRef Model As Long, _
+ ByVal dib As Long, _
+ ByVal Key As String, _
+ ByVal Tag As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetMetadata = (FreeImage_GetMetadataInt(Model, dib, Key, Tag) = 1)
+
+End Function
+
+Public Function FreeImage_SetMetadata(ByRef Model As Long, _
+ ByVal dib As Long, _
+ ByVal Key As String, _
+ ByVal Tag As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetMetadata = (FreeImage_SetMetadataInt(Model, dib, Key, Tag) = 1)
+
+End Function
+
+Public Function FreeImage_FlipHorizontal(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FlipHorizontal = (FreeImage_FlipHorizontalInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_FlipVertical(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FlipVertical = (FreeImage_FlipVerticalInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_JPEGTransform(ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal operation As FREE_IMAGE_JPEG_OPERATION, _
+ Optional ByVal prefect As Long = 0) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_JPEGTransform = (FreeImage_JPEGTransformInt(src_file, dst_file, operation, prefect) = 1)
+
+End Function
+
+Public Function FreeImage_AdjustCurve(ByVal dib As Long, _
+ ByVal LUT As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AdjustCurve = (FreeImage_AdjustCurveInt(dib, LUT, channel) = 1)
+
+End Function
+
+Public Function FreeImage_AdjustGamma(ByVal dib As Long, _
+ ByVal gamma As Double) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AdjustGamma = (FreeImage_AdjustGammaInt(dib, gamma) = 1)
+
+End Function
+
+Public Function FreeImage_AdjustBrightness(ByVal dib As Long, _
+ ByVal percentage As Double) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AdjustBrightness = (FreeImage_AdjustBrightnessInt(dib, percentage) = 1)
+
+End Function
+
+Public Function FreeImage_AdjustContrast(ByVal dib As Long, _
+ ByVal percentage As Double) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AdjustContrast = (FreeImage_AdjustContrastInt(dib, percentage) = 1)
+
+End Function
+
+Public Function FreeImage_Invert(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_Invert = (FreeImage_InvertInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_GetHistogram(ByVal dib As Long, _
+ ByRef histo As Long, _
+ Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_GetHistogram = (FreeImage_GetHistogramInt(dib, histo, channel) = 1)
+
+End Function
+
+Public Function FreeImage_AdjustColors(ByVal dib As Long, _
+ Optional ByVal Brightness As Double, _
+ Optional ByVal Contrast As Double, _
+ Optional ByVal gamma As Double = 1, _
+ Optional ByVal invert As Boolean) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_AdjustColors = (FreeImage_AdjustColorsInt(dib, Brightness, Contrast, gamma, invert) = 1)
+
+End Function
+
+Public Function FreeImage_SetChannel(ByVal dib As Long, _
+ ByVal dib8 As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetChannel = (FreeImage_SetChannelInt(dib, dib8, channel) = 1)
+
+End Function
+
+Public Function FreeImage_SetComplexChannel(ByVal dst As Long, _
+ ByVal src As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_SetComplexChannel = (FreeImage_SetComplexChannelInt(dst, src, channel) = 1)
+
+End Function
+
+Public Function FreeImage_Paste(ByVal dst As Long, _
+ ByVal src As Long, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Alpha As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_Paste = (FreeImage_PasteInt(dst, src, Left, Top, Alpha) = 1)
+
+End Function
+
+Public Function FreeImage_PreMultiplyWithAlpha(ByVal dib As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_PreMultiplyWithAlpha = (FreeImage_PreMultiplyWithAlphaInt(dib) = 1)
+
+End Function
+
+Public Function FreeImage_JPEGCrop(ByVal src_file As String, _
+ ByVal dst_file As String, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As Boolean
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_JPEGCrop = (FreeImage_JPEGCropInt(src_file, dst_file, Left, Top, Right, Bottom) = 1)
+
+End Function
+
+Public Function FreeImage_FillBackgroundEx(ByVal dib As Long, _
+ ByRef Color As RGBQUAD, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS = FI_COLOR_IS_RGB_COLOR) As Long
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FillBackgroundEx = (FreeImage_FillBackground(dib, Color, Options) = 1)
+
+End Function
+
+Public Function FreeImage_FillBackgroundByLong(ByVal dib As Long, _
+ ByRef Color As Long, _
+ Optional ByVal Options As FREE_IMAGE_COLOR_OPTIONS = FI_COLOR_IS_RGB_COLOR) As Long
+
+ ' Thin wrapper function returning a real VB Boolean value
+
+ FreeImage_FillBackgroundByLong = (FreeImage_FillBackground(dib, Color, Options) = 1)
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Extended functions derived from FreeImage 3 functions usually dealing
+' with arrays
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetPaletteEx(ByVal dib As Long) As RGBQUAD()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a VB style array of type RGBQUAD, containing
+ ' the palette data of the dib. This array provides read and write access
+ ' to the actual palette data provided by FreeImage. This is done by
+ ' creating a VB array with an own SAFEARRAY descriptor making the
+ ' array point to the palette pointer returned by FreeImage_GetPalette().
+
+ ' This makes you use code like you would in C/C++:
+
+ ' // this code assumes there is a bitmap loaded and
+ ' // present in a variable called ‘dib’
+ ' if(FreeImage_GetBPP(dib) == 8) {
+ ' // Build a greyscale palette
+ ' RGBQUAD *pal = FreeImage_GetPalette(dib);
+ ' for (int i = 0; i < 256; i++) {
+ ' pal[i].rgbRed = i;
+ ' pal[i].rgbGreen = i;
+ ' pal[i].rgbBlue = i;
+ ' }
+
+ ' As in C/C++ the array is only valid while the DIB is loaded and the
+ ' palette data remains where the pointer returned by FreeImage_GetPalette
+ ' has pointed to when this function was called. So, a good thing would
+ ' be, not to keep the returned array in scope over the lifetime of the
+ ' dib. Best practise is, to use this function within another routine and
+ ' assign the return value (the array) to a local variable only. As soon
+ ' as this local variable goes out of scope (when the calling function
+ ' returns to it's caller), the array and the descriptor is automatically
+ ' cleaned up by VB.
+
+ ' This function does not make a deep copy of the palette data, but only
+ ' wraps a VB array around the FreeImage palette data. So, it can be called
+ ' frequently "on demand" or somewhat "in place" without a significant
+ ' performance loss.
+
+ ' To learn more about this technique I recommend reading chapter 2 (Leveraging
+ ' Arrays) of Matthew Curland's book "Advanced Visual Basic 6"
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the FreeImage_DestroyLockedArrayRGBQUAD() function.
+
+
+ If (dib) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes of RGBQUAD structure
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetColorsUsed(dib) ' the number of elements in the array is
+ ' the number of used colors in the dib
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetPalette(dib) ' let the array point to the memory block, the
+ ' FreeImage palette pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(1, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named as the function is an array variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetPaletteEx), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetPaletteExClone(ByVal dib As Long) As RGBQUAD()
+
+Dim lColors As Long
+Dim atPal() As RGBQUAD
+
+ ' This function returns a redundant clone of a dib's palette as a
+ ' VB style array of type RGBQUAD.
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ lColors = FreeImage_GetColorsUsed(dib)
+ If (lColors > 0) Then
+ ReDim atPal(lColors - 1)
+ Call CopyMemory(atPal(0), ByVal FreeImage_GetPalette(dib), lColors * 4)
+ Call swap(ByVal VarPtrArray(atPal), ByVal VarPtrArray(FreeImage_GetPaletteExClone))
+ End If
+
+End Function
+
+Public Function FreeImage_GetPaletteExLong(ByVal dib As Long) As Long()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a VB style array of type Long, containing
+ ' the palette data of the dib. This array provides read and write access
+ ' to the actual palette data provided by FreeImage. This is done by
+ ' creating a VB array with an own SAFEARRAY descriptor making the
+ ' array point to the palette pointer returned by FreeImage_GetPalette().
+
+ ' The function actually returns an array of type RGBQUAD with each
+ ' element packed into a Long. This is possible, since the RGBQUAD
+ ' structure is also four bytes in size. Palette data, stored in an
+ ' array of type Long may be passed ByRef to a function through an
+ ' optional paremeter. For an example have a look at function
+ ' FreeImage_ConvertColorDepth()
+
+ ' This makes you use code like you would in C/C++:
+
+ ' // this code assumes there is a bitmap loaded and
+ ' // present in a variable called ‘dib’
+ ' if(FreeImage_GetBPP(dib) == 8) {
+ ' // Build a greyscale palette
+ ' RGBQUAD *pal = FreeImage_GetPalette(dib);
+ ' for (int i = 0; i < 256; i++) {
+ ' pal[i].rgbRed = i;
+ ' pal[i].rgbGreen = i;
+ ' pal[i].rgbBlue = i;
+ ' }
+
+ ' As in C/C++ the array is only valid while the DIB is loaded and the
+ ' palette data remains where the pointer returned by FreeImage_GetPalette()
+ ' has pointed to when this function was called. So, a good thing would
+ ' be, not to keep the returned array in scope over the lifetime of the
+ ' dib. Best practise is, to use this function within another routine and
+ ' assign the return value (the array) to a local variable only. As soon
+ ' as this local variable goes out of scope (when the calling function
+ ' returns to it's caller), the array and the descriptor is automatically
+ ' cleaned up by VB.
+
+ ' This function does not make a deep copy of the palette data, but only
+ ' wraps a VB array around the FreeImage palette data. So, it can be called
+ ' frequently "on demand" or somewhat "in place" without a significant
+ ' performance loss.
+
+ ' To learn more about this technique I recommend reading chapter 2 (Leveraging
+ ' Arrays) of Matthew Curland's book "Advanced Visual Basic 6"
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+
+ If (dib) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes of RGBQUAD structure
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetColorsUsed(dib) ' the number of elements in the array is
+ ' the number of used colors in the dib
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetPalette(dib) ' let the array point to the memory block, the
+ ' FreeImage palette pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(1, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named as the function is an array variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetPaletteExLong), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetPaletteExLongClone(ByVal dib As Long) As Long()
+
+Dim lColors As Long
+Dim alPal() As Long
+
+ ' This function returns a redundant clone of a dib's palette as a
+ ' VB style array of type Long.
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ lColors = FreeImage_GetColorsUsed(dib)
+ If (lColors > 0) Then
+ ReDim alPal(lColors - 1)
+ Call CopyMemory(alPal(0), ByVal FreeImage_GetPalette(dib), lColors * 4)
+ Call swap(ByVal VarPtrArray(alPal), ByVal VarPtrArray(FreeImage_GetPaletteExLongClone))
+ End If
+
+End Function
+
+Public Function FreeImage_SetPalette(ByVal dib As Long, ByRef Palette() As RGBQUAD) As Long
+
+ ' This function sets the palette of a palletised bitmap using a RGBQUAD array. Does
+ ' nothing on high color bitmaps.
+
+ ' This operation makes a deep copy of the provided palette data so, after this function
+ ' has returned, changes to the RGBQUAD array are no longer reflected by the bitmap's
+ ' palette.
+
+ FreeImage_SetPalette = FreeImage_GetColorsUsed(dib)
+ If (FreeImage_SetPalette > 0) Then
+ Call CopyMemory(ByVal FreeImage_GetPalette(dib), Palette(0), FreeImage_SetPalette * 4)
+ End If
+
+End Function
+
+Public Function FreeImage_SetPaletteLong(ByVal dib As Long, ByRef Palette() As Long) As Long
+
+ ' This function sets the palette of a palletised bitmap using a RGBQUAD array. Does
+ ' nothing on high color bitmaps.
+
+ ' This operation makes a deep copy of the provided palette data so, after this function
+ ' has returned, changes to the Long array are no longer reflected by the bitmap's
+ ' palette.
+
+ FreeImage_SetPaletteLong = FreeImage_GetColorsUsed(dib)
+ If (FreeImage_SetPaletteLong > 0) Then
+ Call CopyMemory(ByVal FreeImage_GetPalette(dib), Palette(0), FreeImage_SetPaletteLong * 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetTransparencyTableEx(ByVal dib As Long) As Byte()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a VB style Byte array, containing the transparency
+ ' table of the dib. This array provides read and write access to the actual
+ ' transparency table provided by FreeImage. This is done by creating a VB array
+ ' with an own SAFEARRAY descriptor making the array point to the transparency
+ ' table pointer returned by FreeImage_GetTransparencyTable().
+
+ ' This makes you use code like you would in C/C++:
+
+ ' // this code assumes there is a bitmap loaded and
+ ' // present in a variable called ‘dib’
+ ' if(FreeImage_GetBPP(dib) == 8) {
+ ' // Remove transparency information
+ ' byte *transt = FreeImage_GetTransparencyTable(dib);
+ ' for (int i = 0; i < 256; i++) {
+ ' transt[i].rgbRed = 255;
+ ' }
+
+ ' As in C/C++ the array is only valid while the DIB is loaded and the transparency
+ ' table remains where the pointer returned by FreeImage_GetTransparencyTable() has
+ ' pointed to when this function was called. So, a good thing would be, not to keep
+ ' the returned array in scope over the lifetime of the DIB. Best practise is, to use
+ ' this function within another routine and assign the return value (the array) to a
+ ' local variable only. As soon as this local variable goes out of scope (when the
+ ' calling function returns to it's caller), the array and the descriptor is
+ ' automatically cleaned up by VB.
+
+ ' This function does not make a deep copy of the transparency table, but only
+ ' wraps a VB array around the FreeImage transparency table. So, it can be called
+ ' frequently "on demand" or somewhat "in place" without a significant
+ ' performance loss.
+
+ ' To learn more about this technique I recommend reading chapter 2 (Leveraging
+ ' Arrays) of Matthew Curland's book "Advanced Visual Basic 6"
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the FreeImage_DestroyLockedArray() function.
+
+
+ If (dib) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 1 ' size in bytes of a byte element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetTransparencyCount(dib) ' the number of elements in the array is
+ ' equal to the number transparency table entries
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetTransparencyTable(dib) ' let the array point to the memory block, the
+ ' FreeImage transparency table pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(1, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor(); lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named as the function is an array variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetTransparencyTableEx), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetTransparencyTableExClone(ByVal dib As Long) As Byte()
+
+Dim abBuffer() As Byte
+Dim lpTransparencyTable As Long
+Dim lEntries As Long
+
+ ' This function returns a copy of a DIB's transparency table as VB style
+ ' array of type Byte. So, the array provides read access only from the DIB's
+ ' point of view.
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ lpTransparencyTable = FreeImage_GetTransparencyTable(dib)
+ If (lpTransparencyTable) Then
+ lEntries = FreeImage_GetTransparencyCount(dib)
+ ReDim abBuffer(lEntries - 1)
+ Call CopyMemory(abBuffer(0), ByVal lpTransparencyTable, lEntries)
+ Call swap(ByVal VarPtrArray(abBuffer), ByVal VarPtrArray(FreeImage_GetTransparencyTableExClone))
+ End If
+
+End Function
+
+Public Sub FreeImage_SetTransparencyTableEx(ByVal dib As Long, _
+ ByRef Table() As Byte, _
+ Optional ByRef Count As Long = -1)
+
+ ' This function sets a DIB's transparency table to the contents of the
+ ' parameter table(). When the optional parameter Count is omitted, the
+ ' number of entries used is taken from the number of elements stored in
+ ' the array, but will never be never greater than 256.
+
+ ' The parameter 'dib' works according to the FreeImage 3 API documentation.
+
+ If ((Count > UBound(Table) + 1) Or _
+ (Count < 0)) Then
+ Count = UBound(Table) + 1
+ End If
+
+ If (Count > 256) Then
+ Count = 256
+ End If
+
+ Call FreeImage_SetTransparencyTable(dib, VarPtr(Table(0)), Count)
+
+End Sub
+
+Public Function FreeImage_IsTransparencyTableTransparent(ByVal dib As Long) As Boolean
+
+Dim abTransTable() As Byte
+Dim i As Long
+
+ ' This function checks whether a dib's transparency table contains any transparent
+ ' colors or not.
+
+ ' When an image has a transparency table and is transparent, what can be tested
+ ' with 'FreeImage_IsTransparent()', the image still may display opaque when there
+ ' are no transparent colors defined in the image's transparency table. This
+ ' function reads the dib's transparency table directly to determine whether
+ ' there are transparent colors defined or not.
+
+ ' The return value of this function does not relay on the image's transparency
+ ' setting but only on the image's transparency table
+
+ If (dib) Then
+ abTransTable = FreeImage_GetTransparencyTableEx(dib)
+ For i = 0 To UBound(abTransTable)
+ FreeImage_IsTransparencyTableTransparent = (abTransTable(i) < 255)
+ If (FreeImage_IsTransparencyTableTransparent) Then
+ Exit For
+ End If
+ Next i
+ End If
+
+End Function
+
+Public Function FreeImage_GetAdjustColorsLookupTableEx(ByRef LUT() As Byte, _
+ Optional ByVal Brightness As Double, _
+ Optional ByVal Contrast As Double, _
+ Optional ByVal gamma As Double = 1, _
+ Optional ByVal invert As Boolean) As Long
+
+ ' This function is an extended wrapper for FreeImage_GetAdjustColorsLookupTable(), which
+ ' takes a real VB style Byte array LUT() to receive the created lookup table. The LUT()
+ ' parameter must not be fixed sized or locked, since it is (re-)dimensioned in this
+ ' function to contain 256 entries.
+
+ ' All parameters work according to the FreeImage 3 API documentation.
+
+ ReDim LUT(255)
+ FreeImage_GetAdjustColorsLookupTableEx = _
+ FreeImage_GetAdjustColorsLookupTable(VarPtr(LUT(0)), Brightness, Contrast, gamma, invert)
+
+End Function
+
+Public Function FreeImage_ApplyColorMappingEx(ByVal dib As Long, _
+ ByRef srccolors() As RGBQUAD, _
+ ByRef dstcolors() As RGBQUAD, _
+ Optional ByRef Count As Long = -1, _
+ Optional ByVal ignore_alpha As Boolean = True, _
+ Optional ByVal swap As Boolean) As Long
+
+Dim nsrc As Long
+Dim ndst As Long
+
+ ' This function is an extended wrapper for FreeImage_ApplyColorMapping(), which takes
+ ' real VB style RGBQUAD arrays for source and destination colors along with an optional
+ ' ByRef count parameter.
+
+ ' If 'Count' is omitted upon entry, the number of entries of the smaller of both arrays
+ ' is used for 'Count' and also passed back to the caller, due to this parameter's ByRef
+ ' nature.
+
+ ' All other parameters work according to the FreeImage 3 API documentation.
+
+ nsrc = UBound(srccolors)
+ ndst = UBound(dstcolors)
+ If (Count = -1) Then
+ If (nsrc < ndst) Then
+ Count = nsrc
+ Else
+ Count = ndst
+ End If
+ Else
+ If (Count < nsrc) Then
+ Count = nsrc
+ End If
+ If (Count < ndst) Then
+ Count = ndst
+ End If
+ End If
+
+ FreeImage_ApplyColorMappingEx = FreeImage_ApplyColorMapping(dib, _
+ VarPtr(srccolors(0)), VarPtr(dstcolors(0)), Count, ignore_alpha, swap)
+
+End Function
+
+Public Function FreeImage_ApplyIndexMappingEx(ByVal dib As Long, _
+ ByRef srcindices() As Byte, _
+ ByRef dstindices() As Byte, _
+ Optional ByRef Count As Long = -1, _
+ Optional ByVal swap As Boolean) As Long
+
+Dim nsrc As Long
+Dim ndst As Long
+
+ ' This function is an extended wrapper for FreeImage_ApplyIndexMapping(), which takes
+ ' real VB style Byte arrays for source and destination indices along with an optional
+ ' ByRef count parameter.
+
+ ' If 'Count' is omitted upon entry, the number of entries of the smaller of both arrays
+ ' is used for 'Count' and also passed back to the caller, due to this parameter's ByRef
+ ' nature.
+
+ ' All other parameters work according to the FreeImage 3 API documentation.
+
+ nsrc = UBound(srcindices)
+ ndst = UBound(srcindices)
+ If (Count = -1) Then
+ If (nsrc < ndst) Then
+ Count = nsrc
+ Else
+ Count = ndst
+ End If
+ Else
+ If (Count < nsrc) Then
+ Count = nsrc
+ End If
+ If (Count < ndst) Then
+ Count = ndst
+ End If
+ End If
+
+ FreeImage_ApplyIndexMappingEx = FreeImage_ApplyIndexMapping(dib, _
+ VarPtr(srcindices(0)), VarPtr(srcindices(0)), Count, swap)
+
+End Function
+
+Public Function FreeImage_GetHistogramEx(ByVal dib As Long, _
+ Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK, _
+ Optional ByRef success As Boolean) As Long()
+
+Dim alResult() As Long
+
+ ' This function returns a DIB's histogram data as VB style array of
+ ' type Long. Since histogram data is never modified directly, it seems
+ ' enough to return a clone of the data and no read/write accessible
+ ' array wrapped around the actual pointer.
+
+ ' All parameters work according to the FreeImage 3 API documentation.
+
+ ReDim alResult(255)
+ success = (FreeImage_GetHistogramInt(dib, alResult(0), channel) = 1)
+ If (success) Then
+ Call swap(VarPtrArray(FreeImage_GetHistogramEx), VarPtrArray(alResult))
+ End If
+
+End Function
+
+Public Function FreeImage_SetChannelEx(ByVal dib As Long, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL, _
+ ByVal dib_channel As Long, _
+ Optional ByVal channel_src As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK, _
+ Optional ByVal Left As Long, _
+ Optional ByVal Top As Long) As Long
+
+Dim lBits As Long
+Dim hDIBSrc As Long
+Dim lWidthDst As Long
+Dim lHeightDst As Long
+Dim lWidthSrc As Long
+Dim lHeightSrc As Long
+
+ ' still under development and NOT ready to use
+
+ lBits = FreeImage_GetBPP(dib)
+ If ((lBits = 24) Or (lBits = 32)) Then
+
+ lBits = FreeImage_GetBPP(dib_channel)
+ If (lBits >= 8) Then
+
+ If (lBits > 8) Then
+ hDIBSrc = FreeImage_GetChannel(dib_channel, channel_src)
+ Else
+ hDIBSrc = dib_channel
+ End If
+
+ If (hDIBSrc) Then
+
+ lWidthDst = FreeImage_GetWidth(dib)
+ lHeightDst = FreeImage_GetHeight(dib)
+
+ lWidthSrc = FreeImage_GetWidth(hDIBSrc)
+ lHeightSrc = FreeImage_GetHeight(hDIBSrc)
+
+ If ((lWidthSrc <> lWidthDst) Or _
+ (lHeightSrc <> lHeightDst) Or _
+ (Left <> 0) Or _
+ (Top <> 0)) Then
+
+
+
+ End If
+
+ FreeImage_SetChannelEx = FreeImage_SetChannel(dib, hDIBSrc, channel)
+ Call FreeImage_Unload(hDIBSrc)
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustCurveEx(ByVal dib As Long, _
+ ByRef LUT As Variant, _
+ Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK) As Boolean
+
+Dim lpLUTData As Long
+Dim lSizeInBytes As Long
+
+ ' This function extends the FreeImage function 'FreeImage_AdjustCurve'
+ ' to a more VB suitable function. The parameter 'LUT' of type Variant may
+ ' either be an array of type Byte or may contain the pointer to a memory
+ ' block, what in VB is always the address of the memory block, since VB
+ ' actually doesn's support native pointers.
+
+ ' In case of providing the memory block as an array, make sure, that the
+ ' array contains exactly 256 items. In case of providing an address of a
+ ' memory block, the size of the memory block is assumed to be 256 bytes
+ ' and it is up to the caller to ensure that it is large enough.
+
+ If (IsArray(LUT)) Then
+ lpLUTData = pGetMemoryBlockPtrFromVariant(LUT, lSizeInBytes)
+
+ ElseIf (IsNumeric(LUT)) Then
+ lSizeInBytes = 256
+ lpLUTData = CLng(LUT)
+
+ End If
+
+ If ((lpLUTData <> 0) And (lSizeInBytes = 256)) Then
+ FreeImage_AdjustCurveEx = (FreeImage_AdjustCurveInt(dib, lpLUTData, channel) = 1)
+ End If
+
+End Function
+
+Public Function FreeImage_GetLockedPageNumbersEx(ByVal bitmap As Long, _
+ Optional ByRef Count As Long) As Long()
+
+Dim lpPages As Long
+Dim alResult() As Long
+
+ ' This function extends the FreeImage function FreeImage_GetLockedPageNumbers()
+ ' to a more VB suitable function. The original FreeImage parameter 'pages', which
+ ' is a pointer to an array of Long, containing all locked page numbers, was turned
+ ' into a return value, which is a real VB-style array of type Long. The original
+ ' Boolean return value, indicating if there are any locked pages, was dropped from
+ ' this function. The caller has to check the 'Count' parameter, which works according
+ ' to the FreeImage API documentation.
+
+ ' This function returns an array of Longs, dimensioned from 0 to (Count - 1), that
+ ' contains the page numbers of all currently locked pages of 'BITMAP', if 'Count' is
+ ' greater than 0 after the function returns. If 'Count' is 0, there are no pages
+ ' locked and the function returns an uninitialized array.
+
+ If (FreeImage_GetLockedPageNumbersInt(bitmap, lpPages, Count) = 1) Then
+ ReDim alResult(Count - 1)
+ Call CopyMemory(alResult(0), ByVal lpPages, Count * 4)
+ End If
+
+End Function
+
+' Memory and Stream functions
+
+Public Function FreeImage_GetFileTypeFromMemoryEx(ByRef Data As Variant, _
+ Optional ByRef size_in_bytes As Long = 0) As FREE_IMAGE_FORMAT
+
+Dim hStream As Long
+Dim lDataPtr As Long
+
+ ' This function extends the FreeImage function FreeImage_GetFileTypeFromMemory()
+ ' to a more VB suitable function. The parameter data of type Variant my
+ ' me either an array of type Byte, Integer or Long or may contain the pointer
+ ' to a memory block, what in VB is always the address of the memory block,
+ ' since VB actually doesn's support native pointers.
+
+ ' In case of providing the memory block as an array, the size_in_bytes may
+ ' be omitted, zero or less than zero. Then, the size of the memory block
+ ' is calculated correctly. When size_in_bytes is given, it is up to the caller
+ ' to ensure, it is correct.
+
+ ' In case of providing an address of a memory block, size_in_bytes must not
+ ' be omitted.
+
+
+ ' get both pointer and size in bytes of the memory block provided
+ ' through the Variant parameter 'data'.
+ lDataPtr = pGetMemoryBlockPtrFromVariant(Data, size_in_bytes)
+
+ ' open the memory stream
+ hStream = FreeImage_OpenMemoryByPtr(lDataPtr, size_in_bytes)
+ If (hStream) Then
+ ' on success, detect image type
+ FreeImage_GetFileTypeFromMemoryEx = FreeImage_GetFileTypeFromMemory(hStream)
+ Call FreeImage_CloseMemory(hStream)
+ Else
+ FreeImage_GetFileTypeFromMemoryEx = FIF_UNKNOWN
+ End If
+
+End Function
+
+Public Function FreeImage_LoadFromMemoryEx(ByRef Data As Variant, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT, _
+ Optional ByRef size_in_bytes As Long = 0, _
+ Optional ByRef fif As FREE_IMAGE_FORMAT) As Long
+
+Dim hStream As Long
+Dim lDataPtr As Long
+
+ ' This function extends the FreeImage function FreeImage_LoadFromMemory()
+ ' to a more VB suitable function. The parameter data of type Variant my
+ ' me either an array of type Byte, Integer or Long or may contain the pointer
+ ' to a memory block, what in VB is always the address of the memory block,
+ ' since VB actually doesn's support native pointers.
+
+ ' The parameter 'Flags' works according to the FreeImage API documentation.
+
+ ' In case of providing the memory block as an array, the size_in_bytes may
+ ' be omitted, zero or less than zero. Then, the size of the memory block
+ ' is calculated correctly. When size_in_bytes is given, it is up to the caller
+ ' to ensure, it is correct.
+
+ ' In case of providing an address of a memory block, size_in_bytes must not
+ ' be omitted.
+
+ ' The parameter fif is an OUT parameter, that will contain the image type
+ ' detected. Any values set by the caller will never be used within this
+ ' function.
+
+
+ ' get both pointer and size in bytes of the memory block provided
+ ' through the Variant parameter 'data'.
+ lDataPtr = pGetMemoryBlockPtrFromVariant(Data, size_in_bytes)
+
+ ' open the memory stream
+ hStream = FreeImage_OpenMemoryByPtr(lDataPtr, size_in_bytes)
+ If (hStream) Then
+ ' on success, detect image type
+ fif = FreeImage_GetFileTypeFromMemory(hStream)
+ If (fif <> FIF_UNKNOWN) Then
+ ' load the image from memory stream only, if known image type
+ FreeImage_LoadFromMemoryEx = FreeImage_LoadFromMemory(fif, hStream, Flags)
+ End If
+ ' close the memory stream when open
+ Call FreeImage_CloseMemory(hStream)
+ End If
+
+End Function
+
+Public Function FreeImage_SaveToMemoryEx(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByRef Data() As Byte, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT, _
+ Optional ByVal bUnloadSource As Boolean) As Boolean
+
+Dim hStream As Long
+Dim lpData As Long
+Dim lSizeInBytes As Long
+
+ ' This function saves a FreeImage DIB into memory by using the VB Byte
+ ' array data(). It makes a deep copy of the image data and closes the
+ ' memory stream opened before it returns to the caller.
+
+ ' The Byte array 'data()' must not be a fixed sized array and will be
+ ' redimensioned according to the size needed to hold all the data.
+
+ ' The parameters 'fif', 'dib' and 'flags' work according to the FreeImage 3
+ ' API documentation.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image
+ ' after it has been saved into memory. There is no need to clean up the DIB
+ ' at the caller's site.
+
+ ' The function returns True on success and False otherwise.
+
+
+ hStream = FreeImage_OpenMemory()
+ If (hStream) Then
+ FreeImage_SaveToMemoryEx = FreeImage_SaveToMemory(fif, dib, hStream, Flags)
+ If (FreeImage_SaveToMemoryEx) Then
+ If (FreeImage_AcquireMemoryInt(hStream, lpData, lSizeInBytes)) Then
+ On Error Resume Next
+ ReDim Data(lSizeInBytes - 1)
+ If (Err.Number = ERROR_SUCCESS) Then
+ On Error GoTo 0
+ Call CopyMemory(Data(0), ByVal lpData, lSizeInBytes)
+ Else
+ On Error GoTo 0
+ FreeImage_SaveToMemoryEx = False
+ End If
+ Else
+ FreeImage_SaveToMemoryEx = False
+ End If
+ End If
+ Call FreeImage_CloseMemory(hStream)
+ Else
+ FreeImage_SaveToMemoryEx = False
+ End If
+
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(dib)
+ End If
+
+End Function
+
+Public Function FreeImage_SaveToMemoryEx2(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal dib As Long, _
+ ByRef Data() As Byte, _
+ ByRef Stream As Long, _
+ Optional ByVal Flags As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT, _
+ Optional ByVal bUnloadSource As Boolean) As Boolean
+
+ ' This function saves a FreeImage DIB into memory by using the VB Byte
+ ' array data(). It does not makes a deep copy of the image data, but uses
+ ' the function 'FreeImage_AcquireMemoryEx' to wrap the array 'data()'
+ ' around the memory block pointed to by the result of the
+ ' 'FreeImage_AcquireMemory' function.
+
+ ' The Byte array 'data()' must not be a fixed sized array and will be
+ ' redimensioned according to the size needed to hold all the data.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ ' The parameter 'stream' is an IN/OUT parameter, tracking the memory
+ ' stream, the VB array 'data()' is based on. This parameter may contain
+ ' an already opened FreeImage memory stream when the function is called and
+ ' contains a valid memory stream when the function returns in each case.
+ ' After all, it is up to the caller to close that memory stream correctly.
+ ' The array 'data()' will no longer be valid and accessable after the stream
+ ' has been closed, so it should only be closed after the passed byte array
+ ' variable either goes out of the caller's scope or is redimensioned.
+
+ ' The parameters 'fif', 'dib' and 'flags' work according to the FreeImage 3
+ ' API documentation.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image
+ ' after it has been saved into memory. There is no need to clean up the DIB
+ ' at the caller's site.
+
+ ' The function returns True on success and False otherwise.
+
+
+ If (Stream = 0) Then
+ Stream = FreeImage_OpenMemory()
+ End If
+ If (Stream) Then
+ FreeImage_SaveToMemoryEx2 = FreeImage_SaveToMemory(fif, dib, Stream, Flags)
+ If (FreeImage_SaveToMemoryEx2) Then
+ FreeImage_SaveToMemoryEx2 = FreeImage_AcquireMemoryEx(Stream, Data)
+ End If
+
+ ' do not close the memory stream, since the returned array data()
+ ' points to the stream's data
+ ' the caller must close the stream after he is done
+ ' with the array
+ Else
+ FreeImage_SaveToMemoryEx2 = False
+ End If
+
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(dib)
+ End If
+
+End Function
+
+Public Function FreeImage_AcquireMemoryEx(ByVal Stream As Long, _
+ ByRef Data() As Byte, _
+ Optional ByRef size_in_bytes As Long) As Boolean
+
+Dim lpData As Long
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function wraps the byte array data() around acquired memory
+ ' of the memory stream specified by then stream parameter. The adjusted
+ ' array then points directly to the stream's data pointer and so
+ ' provides full read and write access. All data contained in the array
+ ' will be lost and freed properly.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+
+ If (Stream) Then
+ If (FreeImage_AcquireMemoryInt(Stream, lpData, size_in_bytes)) Then
+ With tSA
+ .cbElements = 1 ' one element is one byte
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = size_in_bytes ' the number of elements in the array is
+ ' the size in bytes of the memory block
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = lpData ' let the array point to the memory block
+ ' received by FreeImage_AcquireMemory
+ End With
+
+ lpSA = deref(VarPtrArray(Data))
+ Call SafeArrayDestroyData(ByVal lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Else
+ FreeImage_AcquireMemoryEx = False
+ End If
+ Else
+ FreeImage_AcquireMemoryEx = False
+ End If
+
+End Function
+
+Public Function FreeImage_ReadMemoryEx(ByRef Buffer As Variant, _
+ ByVal Stream As Long, _
+ Optional ByRef Count As Long, _
+ Optional ByRef Size As Long) As Long
+
+Dim lBufferPtr As Long
+Dim lSizeInBytes As Long
+Dim lSize As Long
+Dim lCount As Long
+
+ ' This function is a wrapper for 'FreeImage_ReadMemory()' using VB style
+ ' arrays instead of a void pointer.
+
+ ' The variant parameter 'Buffer' may be a Byte, Integer or Long array or
+ ' may contain a pointer to a memory block (the memory block's address).
+
+ ' In the latter case, this function behaves exactly
+ ' like 'FreeImage_ReadMemory()'. Then, 'Count' and 'Size' must be valid
+ ' upon entry.
+
+ ' If 'Buffer' is an initialized (dimensioned) array, 'Count' and 'Size' may
+ ' be omitted. Then, the array's layout is used to determine 'Count'
+ ' and 'Size'. In that case, any provided value in 'Count' and 'Size' upon
+ ' entry will override these calculated values as long as they are not
+ ' exceeding the size of the array in 'Buffer'.
+
+ ' If 'Buffer' is an uninitialized (not yet dimensioned) array of any valid
+ ' type (Byte, Integer or Long) and, at least 'Count' is specified, the
+ ' array in 'Buffer' is redimensioned by this function. If 'Buffer' is a
+ ' fixed-size or otherwise locked array, a runtime error (10) occurs.
+ ' If 'Size' is omitted, the array's element size is assumed to be the
+ ' desired value.
+
+ ' As FreeImage's function 'FreeImage_ReadMemory()', this function returns
+ ' the number of items actually read.
+
+ ' Example: (very freaky...)
+ '
+ ' Dim alLongBuffer() As Long
+ ' Dim lRet as Long
+ '
+ ' ' now reading 303 integers (2 byte) into an array of Longs
+ ' lRet = FreeImage_ReadMemoryEx(alLongBuffer, lMyStream, 303, 2)
+ '
+ ' ' now, lRet contains 303 and UBound(alLongBuffer) is 151 since
+ ' ' we need at least 152 Longs (0..151) to store (303 * 2) = 606 bytes
+ ' ' so, the higest two bytes of alLongBuffer(151) contain only unset
+ ' ' bits. Got it?
+
+ ' Remark: This function's parameter order differs from FreeImage's
+ ' original funtion 'FreeImage_ReadMemory()'!
+
+ If (VarType(Buffer) And vbArray) Then
+ ' get both pointer and size in bytes of the memory block provided
+ ' through the Variant parameter 'Buffer'.
+ lBufferPtr = pGetMemoryBlockPtrFromVariant(Buffer, lSizeInBytes, lSize)
+ If (lBufferPtr = 0) Then
+ ' array is not initialized
+ If (Count > 0) Then
+ ' only if we have a 'Count' value, redim the array
+ If (Size <= 0) Then
+ ' if 'Size' is omitted, use array's element size
+ Size = lSize
+ End If
+
+ Select Case lSize
+
+ Case 2
+ ' Remark: -Int(-a) == ceil(a); a > 0
+ ReDim Buffer(-Int(-Count * Size / 2) - 1) As Integer
+
+ Case 4
+ ' Remark: -Int(-a) == ceil(a); a > 0
+ ReDim Buffer(-Int(-Count * Size / 4) - 1) As Long
+
+ Case Else
+ ReDim Buffer((Count * Size) - 1) As Byte
+
+ End Select
+ lBufferPtr = pGetMemoryBlockPtrFromVariant(Buffer, lSizeInBytes, lSize)
+ End If
+ End If
+ If (lBufferPtr) Then
+ lCount = lSizeInBytes / lSize
+ If (Size <= 0) Then
+ ' use array's natural value for 'Size' when
+ ' omitted
+ Size = lSize
+ End If
+ If (Count <= 0) Then
+ ' use array's natural value for 'Count' when
+ ' omitted
+ Count = lCount
+ End If
+ If ((Size * Count) > (lSize * lCount)) Then
+ If (Size = lSize) Then
+ Count = lCount
+ Else
+ ' Remark: -Fix(-a) == floor(a); a > 0
+ Count = -Fix(-lSizeInBytes / Size)
+ If (Count = 0) Then
+ Size = lSize
+ Count = lCount
+ End If
+ End If
+ End If
+ FreeImage_ReadMemoryEx = FreeImage_ReadMemory(lBufferPtr, Size, Count, Stream)
+ End If
+
+ ElseIf (VarType(Buffer) = vbLong) Then
+ ' if Buffer is a Long, it specifies the address of a memory block
+ ' then, we do not know anything about its size, so assume that 'Size'
+ ' and 'Count' are correct and forward these directly to the FreeImage
+ ' call.
+ FreeImage_ReadMemoryEx = FreeImage_ReadMemory(CLng(Buffer), Size, Count, Stream)
+
+ End If
+
+End Function
+
+Public Function FreeImage_WriteMemoryEx(ByRef Buffer As Variant, _
+ ByVal Stream As Long, _
+ Optional ByRef Count As Long, _
+ Optional ByRef Size As Long) As Long
+
+Dim lBufferPtr As Long
+Dim lSizeInBytes As Long
+Dim lSize As Long
+Dim lCount As Long
+
+ ' This function is a wrapper for 'FreeImage_WriteMemory()' using VB style
+ ' arrays instead of a void pointer.
+
+ ' The variant parameter 'Buffer' may be a Byte, Integer or Long array or
+ ' may contain a pointer to a memory block (the memory block's address).
+
+ ' In the latter case, this function behaves exactly
+ ' like 'FreeImage_WriteMemory()'. Then, 'Count' and 'Size' must be valid
+ ' upon entry.
+
+ ' If 'Buffer' is an initialized (dimensioned) array, 'Count' and 'Size' may
+ ' be omitted. Then, the array's layout is used to determine 'Count'
+ ' and 'Size'. In that case, any provided value in 'Count' and 'Size' upon
+ ' entry will override these calculated values as long as they are not
+ ' exceeding the size of the array in 'Buffer'.
+
+ ' If 'Buffer' is an uninitialized (not yet dimensioned) array of any
+ ' type, the function will do nothing an returns 0.
+
+ ' Remark: This function's parameter order differs from FreeImage's
+ ' original funtion 'FreeImage_ReadMemory()'!
+
+ If (VarType(Buffer) And vbArray) Then
+ ' get both pointer and size in bytes of the memory block provided
+ ' through the Variant parameter 'Buffer'.
+ lBufferPtr = pGetMemoryBlockPtrFromVariant(Buffer, lSizeInBytes, lSize)
+ If (lBufferPtr) Then
+ lCount = lSizeInBytes / lSize
+ If (Size <= 0) Then
+ ' use array's natural value for 'Size' when
+ ' omitted
+ Size = lSize
+ End If
+ If (Count <= 0) Then
+ ' use array's natural value for 'Count' when
+ ' omitted
+ Count = lCount
+ End If
+ If ((Size * Count) > (lSize * lCount)) Then
+ If (Size = lSize) Then
+ Count = lCount
+ Else
+ ' Remark: -Fix(-a) == floor(a); a > 0
+ Count = -Fix(-lSizeInBytes / Size)
+ If (Count = 0) Then
+ Size = lSize
+ Count = lCount
+ End If
+ End If
+ End If
+ FreeImage_WriteMemoryEx = FreeImage_WriteMemory(lBufferPtr, Size, Count, Stream)
+ End If
+
+ ElseIf (VarType(Buffer) = vbLong) Then
+ ' if Buffer is a Long, it specifies the address of a memory block
+ ' then, we do not know anything about its size, so assume that 'Size'
+ ' and 'Count' are correct and forward these directly to the FreeImage
+ ' call.
+ FreeImage_WriteMemoryEx = FreeImage_WriteMemory(CLng(Buffer), Size, Count, Stream)
+
+ End If
+
+End Function
+
+Public Function FreeImage_LoadMultiBitmapFromMemoryEx(ByRef Data As Variant, _
+ Optional ByVal Flags As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT, _
+ Optional ByRef size_in_bytes As Long = 0, _
+ Optional ByRef fif As FREE_IMAGE_FORMAT) As Long
+
+Dim hStream As Long
+Dim lDataPtr As Long
+
+ ' This function extends the FreeImage function FreeImage_LoadMultiBitmapFromMemoryEx()
+ ' to a more VB suitable function. The parameter data of type Variant my
+ ' me either an array of type Byte, Integer or Long or may contain the pointer
+ ' to a memory block, what in VB is always the address of the memory block,
+ ' since VB actually doesn's support native pointers.
+
+ ' The parameter 'Flags' works according to the FreeImage API documentation.
+
+ ' In case of providing the memory block as an array, the size_in_bytes may
+ ' be omitted, zero or less than zero. Then, the size of the memory block
+ ' is calculated correctly. When size_in_bytes is given, it is up to the caller
+ ' to ensure, it is correct.
+
+ ' In case of providing an address of a memory block, size_in_bytes must not
+ ' be omitted.
+
+ ' The parameter fif is an OUT parameter, that will contain the image type
+ ' detected. Any values set by the caller will never be used within this
+ ' function.
+
+ ' get both pointer and size in bytes of the memory block provided
+ ' through the Variant parameter 'data'.
+ lDataPtr = pGetMemoryBlockPtrFromVariant(Data, size_in_bytes)
+
+ ' open the memory stream
+ hStream = FreeImage_OpenMemoryByPtr(lDataPtr, size_in_bytes)
+ If (hStream) Then
+ ' on success, detect image type
+ fif = FreeImage_GetFileTypeFromMemory(hStream)
+ If (fif <> FIF_UNKNOWN) Then
+ ' load the image from memory stream only, if known image type
+ FreeImage_LoadMultiBitmapFromMemoryEx = FreeImage_LoadMultiBitmapFromMemory(fif, hStream, Flags)
+ End If
+ ' close the memory stream when open
+ Call FreeImage_CloseMemory(hStream)
+ End If
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Tag accessing VB friendly helper functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_CreateTagEx(ByVal Model As FREE_IMAGE_MDMODEL, _
+ Optional ByVal Key As String, _
+ Optional ByVal TagType As FREE_IMAGE_MDTYPE = FIDT_NOTYPE, _
+ Optional ByRef Value As Variant, _
+ Optional ByRef Count As Long, _
+ Optional ByVal Id As Long) As FREE_IMAGE_TAG
+
+ ' This function is a wrapper for FreeImage_CreateTag() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. So, the return value is
+ ' not a pointer to a FITAG structure but a FREE_IMAGE_TAG structure.
+
+ ' In contrast to FreeImage's original FreeImage_CreateTag() function, the
+ ' parameter 'Model' must be specified, the parameters 'Key', 'TagType',
+ ' 'Value', 'Count' and 'Id' my be specified.
+
+ ' The 'Model' is needed, since each FREE_IMAGE_TAG structure needs a
+ ' valid 'Model' member.
+
+ ' All other parameters are optional and enable the caller to specify the tag's
+ ' values upon tag creation. Any parameter specified, is set to it's corresponding
+ ' member in the FREE_IMAGE_TAG structure.
+
+ ' The caller should check the returned FREE_IMAGE_TAG structure's 'TagPtr' member.
+ ' If this function succeeded, the 'TagPtr' member is non zero. A value of zero
+ ' indicates an error condition sourced from FreeImage_CreateTag().
+
+ With FreeImage_CreateTagEx
+ .TagPtr = FreeImage_CreateTag()
+ If (.TagPtr <> 0) Then
+ .Model = Model
+ If (LenB(Key) > 0) Then
+ .Key = Key
+ End If
+ .Type = TagType
+ .Count = Count
+ .Id = Id
+ If (Not IsMissing(Value)) Then
+ .Value = Value
+ End If
+ Call pTagToTagPtr(FreeImage_CreateTagEx)
+ FreeImage_CreateTagEx = pGetTagFromTagPtr(Model, .TagPtr)
+ End If
+ End With
+
+End Function
+
+Public Function FreeImage_AppendTag(ByVal dib As Long, _
+ ByVal Model As FREE_IMAGE_MDMODEL, _
+ Optional ByVal Key As String, _
+ Optional ByVal TagType As FREE_IMAGE_MDTYPE = FIDT_NOTYPE, _
+ Optional ByRef Value As Variant, _
+ Optional ByRef Count As Long, _
+ Optional ByVal Id As Long, _
+ Optional ByVal OverwriteExisting As Boolean = True) As FREE_IMAGE_TAG
+
+Dim lpTag As Long
+
+ ' This function is a shortcut wrapper for FreeImage_CreateTagEx() and
+ ' FreeImage_SetMetadataEx(). It creates a new tag as FreeImage_CreateTagEx() does
+ ' and appends it to the image's metadata model.
+
+ ' The parameter 'dib' specifies the image, the new tag should be appended to,
+ ' parameters 'Model', 'Key', 'TagType', 'Value', 'Count' and 'Id' are these,
+ ' FreeImage_CreateTagEx() has and are just forwarded unchanged.
+
+ ' The boolean parameter 'OverwriteExisting' determines, whether to overwrite or
+ ' replace an already existing tag with the newly created. If the tag specified
+ ' by it's model and key already exists and 'OverwriteExisting' is False, an
+ ' empty FREE_IMAGE_TAG structure is returned.
+
+ ' So, as with FreeImage_CreateTagEx(), the caller should check the returned
+ ' FREE_IMAGE_TAG structure's 'TagPtr' member. If this function succeeded, the
+ ' 'TagPtr' member is non zero. A value of zero indicates an error condition
+ ' sourced from either the FreeImage_CreateTag() function or may result from
+ ' an already existing tag that should not be overwritten.
+
+ If ((FreeImage_GetMetadataInt(Model, dib, Key, lpTag) = 0) Or _
+ (OverwriteExisting)) Then
+
+ FreeImage_AppendTag = FreeImage_CreateTagEx(Model, Key, TagType, Value, Count, Id)
+ If (FreeImage_AppendTag.TagPtr <> 0) Then
+ Call FreeImage_SetMetadataEx(dib, FreeImage_AppendTag, Key, Model, True)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_RemoveTag(ByVal dib As Long, _
+ ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal Key As String) As Boolean
+
+ ' This function is a wrapper function, that removes a tag, that is actually
+ ' part of an image's metadata model. The tag named 'key' of the metadata
+ ' model specified in parameter 'Model' of the image 'dib' will be removed.
+
+ ' Removing a tag is actually done by calling FreeImage_SetMetadata() with
+ ' a NULL pointer for 'FITAG *tag' as described in the API documentation.
+
+ ' The function returns the boolean value returned from FreeImage_SetMetadata(),
+ ' which is always TRUE when removing a tag in this fashion. So, this function's
+ ' caller has no feedback telling if the tag was really present and removed
+ ' successfully.
+
+ ' Up to version 3.9.1 of FreeImage, there seems to be a bug in removing an
+ ' tag from an image's metadata model. Although the removed tag is not accessible
+ ' through FreeImage_GetMetadata() any more, iterations with
+ ' Freeimage_FindFirst/NextMetadata() will still return this tag an a NULL
+ ' pointer.
+
+ ' This bug was reported on the Developers Forum. You can revisit the posting at:
+ ' http://sourceforge.net/forum/forum.php?thread_id=1536883&forum_id=36111
+
+ FreeImage_RemoveTag = (FreeImage_SetMetadataInt(Model, dib, Key, 0) <> 0)
+
+End Function
+
+Public Function FreeImage_RemoveTagEx(ByVal dib As Long, _
+ ByRef Tag As FREE_IMAGE_TAG) As Boolean
+
+ ' This function is a FREE_IMAGE_TAG based wrapper for FreeImage_RemoveTag()
+
+ With Tag
+ FreeImage_RemoveTagEx = FreeImage_RemoveTag(dib, .Model, .Key)
+ End With
+
+End Function
+
+Public Function FreeImage_TagExists(ByVal dib As Long, _
+ ByVal Model As FREE_IMAGE_MDMODEL, _
+ Optional ByVal Key As String) As Boolean
+
+Dim lpTag As Long
+
+ ' This function is a small helper function, returning a boolean value
+ ' that determines, whether a certain tag specified by metadata model
+ ' and key exists for an image specified by 'dib'.
+
+ FreeImage_TagExists = (FreeImage_GetMetadataInt(Model, dib, Key, lpTag) <> 0)
+
+End Function
+
+Public Function FreeImage_TagExistsEx(ByVal dib As Long, _
+ ByRef Tag As FREE_IMAGE_TAG) As Boolean
+
+ ' This function is a FREE_IMAGE_TAG based wrapper for FreeImage_TagExists()
+
+ With Tag
+ FreeImage_TagExistsEx = FreeImage_TagExists(dib, .Model, .Key)
+ End With
+
+End Function
+
+Public Sub FreeImage_DeleteTagEx(ByRef Tag As FREE_IMAGE_TAG)
+
+ ' This function is a wrapper for FreeImage_DeleteTag() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. So, the parameter 'Tag'
+ ' is not a pointer to a FITAG structure but a FREE_IMAGE_TAG structure.
+
+ ' This function deletes the underlaying FreeImage FITAG structure,
+ ' specified the the member 'TagPtr' of the FREE_IMAGE_TAG structure
+ ' and also sets all other members of Tag to a null value.
+
+ ' Do not get confused with the wrapper functions FreeImage_RemoveTag()
+ ' and FreeImage_RemoveTagEx(). These functions remove a tag from an
+ ' image's metadata model. This function only deletes of frees (a better
+ ' name would be 'FreeImage_FreeTag') a tag created with
+ ' FreeImage_CreateTagEx(). Do not delete any tags obtained from any other
+ ' function.
+
+ With Tag
+ If (.TagPtr <> 0) Then
+ Call FreeImage_DeleteTag(.TagPtr)
+ End If
+ .TagPtr = 0
+ .Count = 0
+ .Description = vbNullString
+ .Id = 0
+ .Key = vbNullString
+ .Length = 0
+ .Model = FIMD_NODATA
+ Erase .Palette
+ Erase .RationalValue
+ .StringValue = vbNullString
+ .Type = FIDT_NOTYPE
+ .Value = Empty
+ End With
+
+End Sub
+
+Public Function FreeImage_CloneTagEx(ByRef Tag As FREE_IMAGE_TAG, _
+ Optional ByVal Model As FREE_IMAGE_MDMODEL = FIMD_NODATA) As FREE_IMAGE_TAG
+
+ ' This function is a thin wrapper for FreeImage_CloneTag() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. The parameter 'Tag' works
+ ' according to the FreeImage API documentation expect that Tag is not a
+ ' pointer to a FITAG structure but a FREE_IMAGE_TAG structure.
+
+ ' The additional optional paremeter 'Model' is needed, since the
+ ' transformation from a FreeImage FITAG structure to the VB friendly
+ ' FREE_IMAGE_TAG structure always need the model to be specified.
+ ' When 'Model' is missing (equal to FREE_IMAGE_TAG), the model to be
+ ' used is taken from the Tag's member 'Model' itself.
+
+ ' See function FreeImage_FindNextMetadataEx() to learn more about the
+ ' optional parameter 'Model'
+
+ ' Tags obtained from FreeImage_CloneTagEx() must be deleted with
+ ' FreeImage_DeleteTagEx() as long as they are not used with
+ ' FreeImage_SetMetadataEx() with the parameter 'RefreshTag' set to True.
+
+ If (Tag.TagPtr <> 0) Then
+ If (Model = FIMD_NODATA) Then
+ Model = Tag.Model
+ End If
+ FreeImage_CloneTagEx = pGetTagFromTagPtr(Model, FreeImage_CloneTag(Tag.TagPtr))
+ End If
+
+End Function
+
+Public Function FreeImage_RemoveMetadataModel(ByVal dib As Long, _
+ ByVal Model As FREE_IMAGE_MDMODEL) As Boolean
+
+ ' This function removes a complete metadata model 'Model' from an image specified
+ ' by 'dib'.
+
+ If (Model <> FIMD_NODATA) Then
+ FreeImage_RemoveMetadataModel = (FreeImage_SetMetadataInt(Model, dib, vbNullString, 0) <> 0)
+ End If
+
+End Function
+
+Public Function FreeImage_FindFirstMetadataEx(ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal dib As Long, _
+ ByRef Tag As FREE_IMAGE_TAG) As Long
+
+ ' This function is a wrapper for FreeImage_FindFirstMetadata() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. All parameters 'dib', 'Tag',
+ ' and 'Model' as the function's return value work according to the
+ ' FreeImage API documentation expect that Tag is not a pointer to a FITAG
+ ' structure but a FREE_IMAGE_TAG structure.
+
+ ' Tags obtained from FreeImage_GetMetadataEx() must not be deleted with
+ ' FreeImage_DeleteTagEx().
+
+ With Tag
+ FreeImage_FindFirstMetadataEx = FreeImage_FindFirstMetadata(Model, dib, .TagPtr)
+ If (FreeImage_FindFirstMetadataEx <> 0) Then
+ Tag = pGetTagFromTagPtr(Model, .TagPtr)
+ End If
+ End With
+
+End Function
+
+Public Function FreeImage_FindNextMetadataEx(ByVal mdhandle As Long, _
+ ByRef Tag As FREE_IMAGE_TAG, _
+ Optional ByVal Model As FREE_IMAGE_MDMODEL = FIMD_NODATA) As Boolean
+
+ ' This function is a wrapper for FreeImage_FindNextMetadataEx() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. All parameters 'mdhandle' and 'Tag'
+ ' as the function's return value work according to the FreeImage API
+ ' documentation expect that Tag is not a pointer to a FITAG structure but a
+ ' FREE_IMAGE_TAG structure.
+
+ ' The additional optional paremeter 'Model' is needed, since the VB friendly
+ ' FREE_IMAGE_TAG structure also contains the member 'StringValue'. This member
+ ' is filled with the result of FreeImage_TagToString() which always needs
+ ' the model to be specified. Since there should be no static oder global
+ ' variables id the FreeImage VB wrapper, the model must be known each time
+ ' a FreeImage FITAG structure is converted to a FREE_IMAGE_TAG structure.
+ ' (A global VB collection could be used to map the mdhandle to the model,
+ ' but we don't want any globals here)
+
+ ' So, when 'Model' is missing (equal to FREE_IMAGE_TAG), the model to be used
+ ' is taken from the Tag's member 'Model' itself. This is useful when using this
+ ' function in a loop iterating all tags per model (what else would you do
+ ' with that function?). The Tag's member 'Model' is populated by
+ ' FreeImage_FindFirstMetadataEx() and remains valid during the whole loop, ready
+ ' to be used in this function.
+
+ ' Tags obtained from FreeImage_GetMetadataEx() must not be deleted with
+ ' FreeImage_DeleteTagEx().
+
+ With Tag
+ FreeImage_FindNextMetadataEx = (FreeImage_FindNextMetadataInt(mdhandle, .TagPtr) <> 0)
+ If (FreeImage_FindNextMetadataEx) Then
+ If (Model = FIMD_NODATA) Then
+ Model = .Model
+ End If
+ Tag = pGetTagFromTagPtr(Model, .TagPtr)
+ End If
+ End With
+
+End Function
+
+Public Function FreeImage_GetAllMetadataTags(ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal dib As Long, _
+ ByRef Tag() As FREE_IMAGE_TAG) As Long
+
+Dim hMD As Long
+Dim lpTag As Long
+Dim i As Long
+
+ ' This function is a helper function returning (through a ByRef parameter)
+ ' an array of FREE_IMAGE_TAG structures containing all the image's tags of
+ ' the metadata model specified by the 'Model' parameter.
+
+ ' The parameter 'Tag()' must be an redimensionable array of FREE_IMAGE_TAG
+ ' and is redimensioned accordingly. The function returns the number of
+ ' tags stored in 'Tag()'.
+
+ ' All tags obtained from FreeImage_GetAllMetadataTags() must not be deleted
+ ' with FreeImage_DeleteTagEx().
+
+ i = FreeImage_GetMetadataCount(Model, dib)
+ If (i > 0) Then
+ ReDim Tag(i - 1)
+ FreeImage_GetAllMetadataTags = i
+ i = 0
+ hMD = FreeImage_FindFirstMetadata(Model, dib, lpTag)
+ If (hMD <> 0) Then
+ Do
+ Tag(i) = pGetTagFromTagPtr(Model, lpTag)
+ i = i + 1
+ Loop While (FreeImage_FindNextMetadataInt(hMD, lpTag) <> 0)
+ Call FreeImage_FindCloseMetadata(hMD)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetMetadataEx(ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal dib As Long, _
+ ByVal Key As String, _
+ ByRef Tag As FREE_IMAGE_TAG) As Boolean
+
+ ' This function is a wrapper for FreeImage_GetMetadata() working with
+ ' the VB friendly FREE_IMAGE_TAG structure. All parameters 'dib', 'Tag',
+ ' 'key' and 'Model' as the function's return value work according to the
+ ' FreeImage API documentation expect that Tag is not a pointer to a FITAG
+ ' structure but a FREE_IMAGE_TAG structure.
+
+ ' Tags obtained from FreeImage_GetMetadataEx() must not be deleted with
+ ' FreeImage_DeleteTagEx().
+
+ With Tag
+ If (FreeImage_GetMetadataInt(Model, dib, Key, .TagPtr) <> 0) Then
+ Tag = pGetTagFromTagPtr(Model, .TagPtr)
+ FreeImage_GetMetadataEx = True
+ End If
+ End With
+
+End Function
+
+Public Function FreeImage_SetMetadataEx(ByVal dib As Long, _
+ ByRef Tag As FREE_IMAGE_TAG, _
+ Optional ByVal Key As String, _
+ Optional ByVal Model As FREE_IMAGE_MDMODEL = FIMD_NODATA, _
+ Optional ByVal RefreshTag As Boolean) As Boolean
+
+ ' This function is a wrapper for FreeImage_SetMetadata() using the wrapper's
+ ' VB friendly FREE_IMAGE_TAG structure as an replacement for the original
+ ' function's pointer to a FITAG structure.
+
+ ' All parameters 'dib', 'Tag', 'key' and 'Model' as the function's return value
+ ' work according to the FreeImage API documentation expect that Tag is not a
+ ' pointer to a FITAG structure but a FREE_IMAGE_TAG structure.
+
+ ' As with FreeImage_SetMetadata(), this function sould only be called with
+ ' new tags, created with FreeImage_CreateTagEx(), a wrapper function for
+ ' FreeImage_CreateTag() working with the VB friendly FREE_IMAGE_TAG structure.
+
+ ' Normally, after a newly created tag must be deleted/freed with a call to
+ ' FreeImage_DeleteTagEx(), a wrapper function for FreeImage_DeleteTag() working
+ ' with the VB friendly FREE_IMAGE_TAG structure (bored already?), after
+ ' the tag was appended to an image's metadata model with
+ ' FreeImage_SetMetadataEx(). But...
+
+ ' There is a wrapper specific additional boolean parameter 'RefreshTag', that
+ ' is similar to the parameter 'UnloadSource' found in many wrapper functions.
+ ' When 'RefreshTag' is True upon entry, the tag specified in the 'Tag'
+ ' parameter is deleted (the underlaying FITAG structure is deleted with
+ ' FreeImage_DeteleTag() and all other members of the FREE_IMAGE_TAG structure
+ ' are set to null values) and is reassigned with the tag, that is now part
+ ' of the image's metadata model. The tag now referenced in the 'Tag'
+ ' parameter must NOT be deleted any more by the caller of this function, since
+ ' this tag refers to the actual tag data stored with the image. This is like
+ ' a FREE_IMAGE_TAG structure obtained from FreeImage_GetMetadata() or
+ ' FreeImage_FindFirst/NextMetadata(). Any changes made to this FREE_IMAGE_TAG
+ ' structure may be applied to the image with a later call to
+ ' FreeImage_UpdateMetadata().
+
+
+ With Tag
+ If (Model = FIMD_NODATA) Then
+ Model = .Model
+ End If
+ If (LenB(Key) = 0) Then
+ Key = .Key
+ End If
+ If (FreeImage_SetMetadataInt(Model, dib, Key, .TagPtr) <> 0) Then
+ FreeImage_SetMetadataEx = True
+ End If
+ If (RefreshTag) Then
+ Call FreeImage_DeleteTagEx(Tag)
+ Call FreeImage_GetMetadataEx(Model, dib, Key, Tag)
+ End If
+ End With
+
+End Function
+
+Public Function FreeImage_GetImageComment(ByVal dib As Long) As String
+
+Dim tTag As FREE_IMAGE_TAG
+
+ ' This function is a small wrapper around FreeImage_GetMetadata() that
+ ' returns the comment of a JPEG, PNG of GIF image.
+
+ If (FreeImage_GetMetadataEx(FIMD_COMMENTS, dib, "Comment", tTag)) Then
+ FreeImage_GetImageComment = tTag.Value
+ End If
+
+End Function
+
+Public Function FreeImage_SetImageComment(ByVal dib As Long, _
+ Optional ByVal Comment As String) As Boolean
+
+Dim tTag As FREE_IMAGE_TAG
+
+ ' This function is a small wrapper around FreeImage_SetMetadata() that
+ ' sets the comment of a JPEG, PNG of GIF image.
+
+ If (LenB(Comment) > 0) Then
+ tTag = FreeImage_AppendTag(dib, FIMD_COMMENTS, "Comment", FIDT_ASCII, Comment)
+ FreeImage_SetImageComment = (tTag.TagPtr <> 0)
+ Else
+ Call FreeImage_RemoveMetadataModel(dib, FIMD_COMMENTS)
+ FreeImage_SetImageComment = True
+ End If
+
+End Function
+
+Public Function FreeImage_CopyMetadata(ByVal SrcDIB As Long, _
+ ByVal DstDIB As Long, _
+ Optional ByVal ReplaceExisting As Boolean = True, _
+ Optional ByVal Model As FREE_IMAGE_MDMODEL = FIMD_NODATA) As Long
+
+Dim hMDFind As Long
+Dim lpTag As Long
+Dim strKey As String
+Dim bSetTag As Boolean
+
+ ' This derived helper function copies several metadata tags from one
+ ' image to another. This is useful when cloning images explicitly with
+ ' FreeImage_Clone() or implicitly with FreeImage_ConvertColorDepth() or
+ ' with any of the FreeImage_RescaleXXX() functions. Whenever the "same"
+ ' image is represented by a new 'dib' pointer, the image was internally
+ ' recreated. All of the data, associated with the image, like metadata,
+ ' DPI settings or ICC profiles are no more available in the new version of
+ ' the image.
+
+ ' Setting the DPI for X and Y direction is quite easy with the wrapper
+ ' functions FreeImage_Get/SetResolutionX/Y(). This function makes it even
+ ' easier to keep track of all associated metadata tags for a cloned image!
+
+ ' Both parameters 'SrcDIB' and 'DstDIB' specify the source and destination
+ ' image. Metadata is copied from 'SrcDIB' to 'DstDIB'.
+
+ ' The optional parameter 'ReplaceExisting' determines whether existing tags
+ ' should be replaced or not. If there are no tags in 'DstDIB' it is recommended,
+ ' to set 'ReplaceExisting' to True (or to omit it, since True is it's default
+ ' value) for better performance; when set to True, no tests for tag existence
+ ' in the destination image will be run.
+
+ ' The optional parameter 'Model' may specify a certain metadata model to be
+ ' copied. If this parameter is omitted or set to any value not defined in the
+ ' FREE_IMAGE_MDMODEL enumeration, all metadata models will be copied
+ ' sequentially.
+
+ ' This function returns the number of tags copied or zero when there are no tags
+ ' in the source image or an error occured.
+
+ ' For the standard use case described above (keeping track of all metadata after
+ ' an image was cloned) the calling this function boils down to a very short form:
+
+ ' lTagsCopied = FreeImage_CopyMetadata(hDibSrc, hDibDst)
+
+ If ((SrcDIB <> 0) And (DstDIB <> 0)) Then
+ If ((Model >= FIMD_COMMENTS) And (Model <= FIMD_CUSTOM)) Then
+ hMDFind = FreeImage_FindFirstMetadata(Model, SrcDIB, lpTag)
+ If (hMDFind) Then
+ Do
+ strKey = pGetStringFromPointerA(deref(deref(lpTag)))
+ bSetTag = ReplaceExisting
+ If (Not bSetTag) Then
+ bSetTag = (Not FreeImage_TagExists(DstDIB, Model, strKey))
+ End If
+ If (bSetTag) Then
+ If (FreeImage_SetMetadataInt(Model, DstDIB, strKey, lpTag) <> 0) Then
+ FreeImage_CopyMetadata = FreeImage_CopyMetadata + 1
+ End If
+ End If
+ Loop While (FreeImage_FindNextMetadata(hMDFind, lpTag))
+ Call FreeImage_FindCloseMetadata(hMDFind)
+ End If
+ Else
+ For Model = FIMD_COMMENTS To FIMD_CUSTOM
+ FreeImage_CopyMetadata = FreeImage_CopyMetadata _
+ + FreeImage_CopyMetadata(SrcDIB, DstDIB, _
+ ReplaceExisting, Model)
+ Next Model
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_CloneMetadataEx(ByVal SrcDIB As Long, _
+ ByVal DstDIB As Long, _
+ Optional ByVal Model As FREE_IMAGE_MDMODEL = FIMD_NODATA) As Long
+
+ ' This derived helper function copies several metadata tags from one
+ ' image to another. It is very similar to FreeImage_CopyMetadata().
+
+ ' The main difference is, that this function aims to create exactly the same
+ ' metadata layout in the destination image. In contrast to
+ ' FreeImage_CopyMetadata(), this function removes all metadata tags in the
+ ' desination image that are not part of the metadata set in the source image.
+ ' So, this function is particularly useful for destination images that may
+ ' have already some tags associated and you want to make shure, that it will
+ ' get exactly the same metadata set as the source image.
+
+ ' This function will most likely be used in a end user application and should
+ ' be invoked through a menu command called: "Set/Apply Metadata From Source Image..."
+
+ ' This function returns the number of tags copied or zero if there are no tags
+ ' in the source image or an error occured.
+
+ If ((SrcDIB <> 0) And (DstDIB <> 0)) Then
+ If ((Model >= FIMD_COMMENTS) And (Model <= FIMD_CUSTOM)) Then
+ If (FreeImage_RemoveMetadataModel(DstDIB, Model)) Then
+ FreeImage_CloneMetadataEx = FreeImage_CopyMetadata(SrcDIB, DstDIB, _
+ True, Model)
+ End If
+ Else
+ For Model = FIMD_COMMENTS To FIMD_CUSTOM
+ FreeImage_CloneMetadataEx = FreeImage_CloneMetadataEx _
+ + FreeImage_CloneMetadataEx(SrcDIB, DstDIB, _
+ Model)
+ Next Model
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_TagFromPointer(ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal Tag As Long) As FREE_IMAGE_TAG
+
+ ' This is a generic function that returns a VB wrapper Tag
+ ' structure (FREE_IMAGE_TAG) from a FreeImage FITAG *tag pointer.
+
+ ' This function is still public due to legacy reasons. Since there are
+ ' functions like 'FreeImage_GetMetadataEx()', 'FreeImage_GetAllMetadataTags()'
+ ' or 'FreeImage_FindFirst/NextMetadataEx()', this function won't be needed
+ ' any more in most cases.
+
+ FreeImage_TagFromPointer = pGetTagFromTagPtr(Model, Tag)
+
+End Function
+
+Public Function FreeImage_UpdateMetadata(ByRef Tag As FREE_IMAGE_TAG) As Boolean
+
+ ' This function updates any changes made in a FREE_IMAGE_TAG
+ ' structure.
+
+ FreeImage_UpdateMetadata = pTagToTagPtr(Tag)
+
+End Function
+
+Public Function FreeImage_UnsignedLong(ByVal Value As Long) As Variant
+
+ ' This function converts a signed long (VB's Long data type) into
+ ' an unsigned long (not really supported by VB).
+
+ ' Basically, this function checks, whether the positive range of
+ ' a signed long is sufficient to hold the value (indeed, it checks
+ ' the value since the range is obviously constant). If yes,
+ ' it returns a Variant with subtype Long ('Variant/Long' in VB's
+ ' watch window). In this case, the function did not make any real
+ ' changes at all. If not, the value is stored in a Currency variable,
+ ' which is able to store the whole range of an unsigned long. Then,
+ ' the function returns a Variant with subtype Currency
+ ' ('Variant/Currency' in VB's watch window).
+
+ If (Value < 0) Then
+ Dim curTemp As Currency
+ Call CopyMemory(curTemp, Value, 4)
+ FreeImage_UnsignedLong = curTemp * 10000
+ Else
+ FreeImage_UnsignedLong = Value
+ End If
+
+End Function
+
+Public Function FreeImage_UnsignedShort(ByVal Value As Integer) As Variant
+
+ ' This function converts a signed short (VB's Integer data type) into
+ ' an unsigned short (not really supported by VB).
+
+ ' Basically, this function checks, whether the positive range of
+ ' a signed short is sufficient to hold the value (indeed, it checks
+ ' the value since the range is obviously constant). If yes,
+ ' it returns a Variant with subtype Integer ('Variant/Integer' in VB's
+ ' watch window). In this case, the function did not make any real
+ ' changes at all. If not, the value is stored in a Long variable,
+ ' which is able to store the whole range of an unsigned short. Then,
+ ' the function returns a Variant with subtype Long
+ ' ('Variant/Long' in VB's watch window).
+
+ If (Value < 0) Then
+ Dim lTemp As Long
+ Call CopyMemory(lTemp, Value, 2)
+ FreeImage_UnsignedShort = lTemp
+ Else
+ FreeImage_UnsignedShort = Value
+ End If
+
+End Function
+
+Public Function FreeImage_CreateRational(ByRef Numerator As Variant, _
+ ByRef Denominator As Variant, _
+ Optional ByVal NormalizeValue As Boolean = True) As FIRATIONAL
+
+ ' This function creates an unsigned rational (FIDT_RATIONAL) value to be used with
+ ' FreeImage's metadata models. In the VB wrapper, any rational value is stored in a
+ ' structure (FIRATIONAL), containing both 'Numerator' and 'Denominator' members. The
+ ' rational's value is then defined as the fraction Numerator/Denominator.
+
+ ' Both values 'Numerator' and 'Denominator' are actually ULONGs (unsigned longs), a
+ ' data type not supported by VB (a VB Long variable is always signed). Therefore,
+ ' 'Numerator' and 'Denominator' are typed as Variant. Whenever the range of a signed
+ ' long is sufficient to store the value (all values between 0 and 0x7FFFFFFF
+ ' (2147483647 decimal)), the Variant gets a Long subtype. If not, a Currency subtype is
+ ' used just to give you the mathematical correct value of the unsigned long.
+
+ ' The optional parameter 'NormalizeValue' controls, whether the resulting fraction
+ ' should be normalized (cancelled down) or not.
+
+ ' When calling this function, you can use hexadecimal constants for passing unsinged
+ ' longs via the parameters 'Numerator' and 'Denominator'.
+
+ ' 2147483647
+ ' Example: tRational = FreeImage_CreateRational(&HFFFFFFFF, 12345) -> ----------
+ ' 12345
+
+ With FreeImage_CreateRational
+ .Numerator = FreeImage_UnsignedLong(Numerator)
+ .Denominator = FreeImage_UnsignedLong(Denominator)
+ End With
+
+ If (NormalizeValue) Then
+ Call pNormalizeRational(FreeImage_CreateRational)
+ End If
+
+End Function
+
+Public Function FreeImage_CreateSignedRational(ByRef Numerator As Variant, _
+ ByRef Denominator As Variant, _
+ Optional ByVal NormalizeValue As Boolean = True) As FIRATIONAL
+
+ ' This function creates a signed rational (FIDT_RATIONAL) value to be used with
+ ' FreeImage's metadata models. In the VB wrapper, any rational value is stored in a
+ ' structure (FIRATIONAL), containing both 'Numerator' and 'Denominator' members. The
+ ' rational's value is then defined as the fraction Numerator/Denominator.
+
+ ' Both values 'Numerator' and 'Denominator' are actually LONGs (signed longs), the
+ ' same data type as a VB Long. Since, 'Numerator' and 'Denominator' are typed as
+ ' Variant, all possible values between -2,147,483,648 and + 2,147,483,647 are stored
+ ' in a Variant with subtype Long (cp. 'FreeImage_CreateRational()').
+
+ ' The optional parameter 'NormalizeValue' controls, whether the resulting fraction
+ ' should be normalized (cancelled down) or not.
+
+ ' When calling this function, you can use hexadecimal constants for passing unsinged
+ ' longs via the parameters 'Numerator' and 'Denominator'.
+
+ ' -1 1
+ ' Example: tRational = FreeImage_CreateSignedRational(&HFFFFFFFF, 12345) -> ----- = - -----
+ ' 12345 12345
+
+ With FreeImage_CreateSignedRational
+ .Numerator = CLng(Numerator)
+ .Denominator = CLng(Denominator)
+ End With
+
+ If (NormalizeValue) Then
+ Call pNormalizeSRational(FreeImage_CreateSignedRational)
+ End If
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Derived and hopefully useful functions
+'--------------------------------------------------------------------------------
+
+' Plugin and filename functions
+
+Public Function FreeImage_IsExtensionValidForFIF(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal extension As String, _
+ Optional ByVal Compare As VbCompareMethod = vbBinaryCompare) As Boolean
+
+ ' This function tests, whether a given filename extension is valid
+ ' for a certain image format (fif).
+
+ FreeImage_IsExtensionValidForFIF = (InStr(1, _
+ FreeImage_GetFIFExtensionList(fif) & ",", _
+ extension & ",", _
+ Compare) > 0)
+
+End Function
+
+Public Function FreeImage_IsFilenameValidForFIF(ByVal fif As FREE_IMAGE_FORMAT, _
+ ByVal Filename As String, _
+ Optional ByVal Compare As VbCompareMethod = vbBinaryCompare) As Boolean
+
+Dim strExtension As String
+Dim i As Long
+
+ ' This function tests, whether a given complete filename is valid
+ ' for a certain image format (fif).
+
+ i = InStrRev(Filename, ".")
+ If (i) Then
+ strExtension = Mid$(Filename, i + 1)
+ FreeImage_IsFilenameValidForFIF = (InStr(1, _
+ FreeImage_GetFIFExtensionList(fif) & ",", _
+ strExtension & ",", _
+ Compare) > 0)
+ End If
+
+End Function
+
+Public Function FreeImage_GetPrimaryExtensionFromFIF(ByVal fif As FREE_IMAGE_FORMAT) As String
+
+Dim strExtensionList As String
+Dim i As Long
+
+ ' This function returns the primary (main or most commonly used?) extension
+ ' of a certain image format (fif). This is done by returning the first of
+ ' all possible extensions returned by FreeImage_GetFIFExtensionList(). That
+ ' assumes, that the plugin returns the extensions in ordered form. If not,
+ ' in most cases it is even enough, to receive any extension.
+
+ ' This function is primarily used by the function 'SavePictureEx'.
+
+ strExtensionList = FreeImage_GetFIFExtensionList(fif)
+ i = InStr(strExtensionList, ",")
+ If (i) Then
+ FreeImage_GetPrimaryExtensionFromFIF = Left$(strExtensionList, i - 1)
+ Else
+ FreeImage_GetPrimaryExtensionFromFIF = strExtensionList
+ End If
+
+End Function
+
+Public Function FreeImage_IsGreyscaleImage(ByVal dib As Long) As Boolean
+
+Dim atRGB() As RGBQUAD
+Dim i As Long
+
+ ' This function returns a boolean value that is true, if the DIB is actually
+ ' a greyscale image. Here, the only test condition is, that each palette
+ ' entry must be a grey value, what means that each color component has the
+ ' same value (red = green = blue).
+
+ ' The FreeImage libraray doesn't offer a function to determine if a DIB is
+ ' greyscale. The only thing you can do is to use the 'FreeImage_GetColorType'
+ ' function, that returns either FIC_MINISWHITE or FIC_MINISBLACK for
+ ' greyscale images. However, a DIB needs to have a ordered greyscale palette
+ ' (linear ramp or inverse linear ramp) to be judged as FIC_MINISWHITE or
+ ' FIC_MINISBLACK. DIB's with an unordered palette that are actually (visually)
+ ' greyscale, are said to be (color-)palletized. That's also true for any 4 bpp
+ ' image, since it will never have a palette that satifies the tests done
+ ' in the 'FreeImage_GetColorType' function.
+
+ ' So, there is a chance to omit some color depth conversions, when displaying
+ ' an image in greyscale fashion. Maybe the problem will be solved in the
+ ' FreeImage library one day.
+
+ Select Case FreeImage_GetBPP(dib)
+
+ Case 1, 4, 8
+ atRGB = FreeImage_GetPaletteEx(dib)
+ FreeImage_IsGreyscaleImage = True
+ For i = 0 To UBound(atRGB)
+ With atRGB(i)
+ If ((.rgbRed <> .rgbGreen) Or (.rgbRed <> .rgbBlue)) Then
+ FreeImage_IsGreyscaleImage = False
+ Exit For
+ End If
+ End With
+ Next i
+
+ End Select
+
+End Function
+
+' Bitmap resolution functions
+
+Public Function FreeImage_GetResolutionX(ByVal dib As Long) As Long
+
+ ' This function gets a DIB's resolution in X-direction measured
+ ' in 'dots per inch' (DPI) and not in 'dots per meter'.
+
+ FreeImage_GetResolutionX = Int(0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib))
+
+End Function
+
+Public Sub FreeImage_SetResolutionX(ByVal dib As Long, ByVal res As Long)
+
+ ' This function sets a DIB's resolution in X-direction measured
+ ' in 'dots per inch' (DPI) and not in 'dots per meter'.
+
+ Call FreeImage_SetDotsPerMeterX(dib, Int(res / 0.0254 + 0.5))
+
+End Sub
+
+Public Function FreeImage_GetResolutionY(ByVal dib As Long) As Long
+
+ ' This function gets a DIB's resolution in Y-direction measured
+ ' in 'dots per inch' (DPI) and not in 'dots per meter'.
+
+ FreeImage_GetResolutionY = Int(0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib))
+
+End Function
+
+Public Sub FreeImage_SetResolutionY(ByVal dib As Long, ByVal res As Long)
+
+ ' This function sets a DIB's resolution in Y-direction measured
+ ' in 'dots per inch' (DPI) and not in 'dots per meter'.
+
+ Call FreeImage_SetDotsPerMeterY(dib, Int(res / 0.0254 + 0.5))
+
+End Sub
+
+' ICC Color Profile functions
+
+Public Function FreeImage_GetICCProfile(ByVal dib As Long) As FIICCPROFILE
+
+ ' This function is a wrapper for the FreeImage_GetICCProfile() function, returning
+ ' a real FIICCPROFILE structure.
+
+ ' Since the original FreeImage function returns a pointer to the FIICCPROFILE
+ ' structure (FIICCPROFILE *), as with string returning functions, this wrapper is
+ ' needed as VB can't declare a function returning a pointer to anything. So,
+ ' analogous to string returning functions, FreeImage_GetICCProfile() is declared
+ ' private as FreeImage_GetICCProfileInt() and made publicly available with this
+ ' wrapper function.
+
+ Call CopyMemory(FreeImage_GetICCProfile, _
+ ByVal FreeImage_GetICCProfileInt(dib), _
+ LenB(FreeImage_GetICCProfile))
+
+End Function
+
+Public Function FreeImage_GetICCProfileColorModel(ByVal dib As Long) As FREE_IMAGE_ICC_COLOR_MODEL
+
+ ' This function is a thin wrapper around FreeImage_GetICCProfile() returning
+ ' the color model in which the ICC color profile data is in, if there is actually
+ ' a ICC color profile available for the dib specified.
+
+ ' If there is NO color profile along with that bitmap, this function returns the color
+ ' model that should (or must) be used for any color profile data to be assigned to the
+ ' dib. That depends on the bitmap's color type.
+
+ If (FreeImage_HasICCProfile(dib)) Then
+ FreeImage_GetICCProfileColorModel = (deref(FreeImage_GetICCProfileInt(dib)) _
+ And FREE_IMAGE_ICC_COLOR_MODEL_MASK)
+ Else
+ ' use FreeImage_GetColorType() to determine, whether this is a CMYK bitmap or not
+ If (FreeImage_GetColorType(dib) = FIC_CMYK) Then
+ FreeImage_GetICCProfileColorModel = FIICC_COLOR_MODEL_CMYK
+ Else
+ FreeImage_GetICCProfileColorModel = FIICC_COLOR_MODEL_RGB
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetICCProfileSize(ByVal dib As Long) As Long
+
+ ' This function is a thin wrapper around FreeImage_GetICCProfile() returning
+ ' only the size in bytes of the ICC profile data for the dib specified or zero,
+ ' if there is no ICC profile data for the dib.
+
+ FreeImage_GetICCProfileSize = deref(FreeImage_GetICCProfileInt(dib) + 4)
+
+End Function
+
+Public Function FreeImage_GetICCProfileDataPointer(ByVal dib As Long) As Long
+
+ ' This function is a thin wrapper around FreeImage_GetICCProfile() returning
+ ' only the pointer (the address) of the ICC profile data for the dib specified,
+ ' or zero if there is no ICC profile data for the dib.
+
+ FreeImage_GetICCProfileDataPointer = deref(FreeImage_GetICCProfileInt(dib) + 8)
+
+End Function
+
+Public Function FreeImage_HasICCProfile(ByVal dib As Long) As Boolean
+
+ ' This function is a thin wrapper around FreeImage_GetICCProfile() returning
+ ' True, if there is an ICC color profile available for the dib specified or
+ ' returns False otherwise.
+
+ FreeImage_HasICCProfile = (FreeImage_GetICCProfileSize(dib) <> 0)
+
+End Function
+
+' Bitmap Info functions
+
+Public Function FreeImage_GetInfoHeaderEx(ByVal dib As Long) As BITMAPINFOHEADER
+
+Dim lpInfoHeader As Long
+
+ ' This function is a wrapper around FreeImage_GetInfoHeader() and returns a fully
+ ' populated BITMAPINFOHEADER structure for a given bitmap.
+
+ lpInfoHeader = FreeImage_GetInfoHeader(dib)
+ If (lpInfoHeader) Then
+ Call CopyMemory(FreeImage_GetInfoHeaderEx, ByVal lpInfoHeader, LenB(FreeImage_GetInfoHeaderEx))
+ End If
+
+End Function
+
+' Image color depth conversion wrapper
+
+Public Function FreeImage_ConvertColorDepth(ByVal hDIB As Long, _
+ ByVal eConversionFlag As FREE_IMAGE_CONVERSION_FLAGS, _
+ Optional ByVal bUnloadSource As Boolean, _
+ Optional ByVal bThreshold As Byte = 128, _
+ Optional ByVal eDitherMethod As FREE_IMAGE_DITHER = FID_FS, _
+ Optional ByVal eQuantizationMethod As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT) As Long
+
+Dim hDIBNew As Long
+Dim hDIBTemp As Long
+Dim lBPP As Long
+Dim bForceLinearRamp As Boolean
+Dim lpReservePalette As Long
+Dim bAdjustReservePaletteSize As Boolean
+
+ ' This function is an easy-to-use wrapper for color depth conversion, intended
+ ' to work around some tweaks in the FreeImage library.
+
+ ' The parameters 'bThreshold' and 'eDitherMode' control how thresholding or
+ ' dithering are performed. The 'eQuantizationMethod' parameter determines, what
+ ' quantization algorithm will be used when converting to 8 bit color images.
+
+ ' The 'eConversionFlag' parameter, which can contain a single value or an OR'ed
+ ' combination of some of the FREE_IMAGE_CONVERSION_FLAGS enumeration values,
+ ' determines the desired output image format.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image, so
+ ' you can "change" an image with this function rather than getting a new DIB
+ ' pointer. There is no more need for a second DIB variable at the caller's site.
+
+ bForceLinearRamp = ((eConversionFlag And FICF_REORDER_GREYSCALE_PALETTE) = 0)
+ lBPP = FreeImage_GetBPP(hDIB)
+
+ If (hDIB) Then
+
+ Select Case (eConversionFlag And (Not FICF_REORDER_GREYSCALE_PALETTE))
+
+ Case FICF_MONOCHROME_THRESHOLD
+ If (lBPP > 1) Then
+ hDIBNew = FreeImage_Threshold(hDIB, bThreshold)
+ End If
+
+ Case FICF_MONOCHROME_DITHER
+ If (lBPP > 1) Then
+ hDIBNew = FreeImage_Dither(hDIB, eDitherMethod)
+ End If
+
+ Case FICF_GREYSCALE_4BPP
+ If (lBPP <> 4) Then
+ ' If the color depth is 1 bpp and the we don't have a linear ramp palette
+ ' the bitmap is first converted to an 8 bpp greyscale bitmap with a linear
+ ' ramp palette and then to 4 bpp.
+ If ((lBPP = 1) And (FreeImage_GetColorType(hDIB) = FIC_PALETTE)) Then
+ hDIBTemp = hDIB
+ hDIB = FreeImage_ConvertToGreyscale(hDIB)
+ Call FreeImage_Unload(hDIBTemp)
+ End If
+ hDIBNew = FreeImage_ConvertTo4Bits(hDIB)
+ Else
+ ' The bitmap is already 4 bpp but may not have a linear ramp.
+ ' If we force a linear ramp the bitmap is converted to 8 bpp with a linear ramp
+ ' and then back to 4 bpp.
+ If (((Not bForceLinearRamp) And (Not FreeImage_IsGreyscaleImage(hDIB))) Or _
+ (bForceLinearRamp And (FreeImage_GetColorType(hDIB) = FIC_PALETTE))) Then
+ hDIBTemp = FreeImage_ConvertToGreyscale(hDIB)
+ hDIBNew = FreeImage_ConvertTo4Bits(hDIBTemp)
+ Call FreeImage_Unload(hDIBTemp)
+ End If
+ End If
+
+ Case FICF_GREYSCALE_8BPP
+ ' Convert, if the bitmap is not at 8 bpp or does not have a linear ramp palette.
+ If ((lBPP <> 8) Or (((Not bForceLinearRamp) And (Not FreeImage_IsGreyscaleImage(hDIB))) Or _
+ (bForceLinearRamp And (FreeImage_GetColorType(hDIB) = FIC_PALETTE)))) Then
+ hDIBNew = FreeImage_ConvertToGreyscale(hDIB)
+ End If
+
+ Case FICF_PALLETISED_8BPP
+ ' note, that the FreeImage library only quantizes 24 bit images
+ ' do not convert any 8 bit images
+ If (lBPP <> 8) Then
+ ' images with a color depth of 24 bits can directly be
+ ' converted with the FreeImage_ColorQuantize function;
+ ' other images need to be converted to 24 bits first
+ If (lBPP = 24) Then
+ hDIBNew = FreeImage_ColorQuantize(hDIB, eQuantizationMethod)
+ Else
+ hDIBTemp = FreeImage_ConvertTo24Bits(hDIB)
+ hDIBNew = FreeImage_ColorQuantize(hDIBTemp, eQuantizationMethod)
+ Call FreeImage_Unload(hDIBTemp)
+ End If
+ End If
+
+ Case FICF_RGB_15BPP
+ If (lBPP <> 15) Then
+ hDIBNew = FreeImage_ConvertTo16Bits555(hDIB)
+ End If
+
+ Case FICF_RGB_16BPP
+ If (lBPP <> 16) Then
+ hDIBNew = FreeImage_ConvertTo16Bits565(hDIB)
+ End If
+
+ Case FICF_RGB_24BPP
+ If (lBPP <> 24) Then
+ hDIBNew = FreeImage_ConvertTo24Bits(hDIB)
+ End If
+
+ Case FICF_RGB_32BPP
+ If (lBPP <> 32) Then
+ hDIBNew = FreeImage_ConvertTo32Bits(hDIB)
+ End If
+
+ End Select
+
+ If (hDIBNew) Then
+ FreeImage_ConvertColorDepth = hDIBNew
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(hDIB)
+ End If
+ Else
+ FreeImage_ConvertColorDepth = hDIB
+ End If
+
+ End If
+
+End Function
+
+Public Function FreeImage_ColorQuantizeEx(ByVal dib As Long, _
+ Optional ByVal quantize As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT, _
+ Optional ByVal bUnloadSource As Boolean = False, _
+ Optional ByVal PaletteSize As Long = 256, _
+ Optional ByVal ReserveSize As Long = 0, _
+ Optional ByRef ReservePalette As Variant = Null) As Long
+
+Dim hTmp As Long
+Dim lpPalette As Long
+Dim lBlockSize As Long
+Dim lElementSize As Long
+
+ ' This function is a more VB-friendly wrapper around FreeImage_ColorQuantizeEx,
+ ' which lets you specify the ReservePalette to be used not only as a pointer, but
+ ' also as a real VB-style array of type Long, where each Long item takes a color
+ ' in ARGB format (&HAARRGGBB). The native FreeImage function FreeImage_ColorQuantizeEx
+ ' is declared private and named FreeImage_ColorQuantizeExInt and so hidden from the
+ ' world outside the wrapper.
+
+ ' In contrast to the FreeImage API documentation, ReservePalette is of type Variant
+ ' and may either be a pointer to palette data (pointer to an array of type RGBQUAD
+ ' == VarPtr(atMyPalette(0)) in VB) or an array of type Long, which then must contain
+ ' the palette data in ARGB format. You can receive palette data as an array Longs
+ ' from function FreeImage_GetPaletteExLong.
+ ' Although ReservePalette is of type Variant, arrays of type RGBQUAD can not be
+ ' passed, as long as RGBQUAD is not declared as a public type in a public object
+ ' module. So, when dealing with RGBQUAD arrays, you are stuck on VarPtr or may
+ ' use function FreeImage_GetPalettePtr, which is a more meaningfully named
+ ' convenience wrapper around VarPtr.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image, so
+ ' you can "change" an image with this function rather than getting a new DIB
+ ' pointer. There is no more need for a second DIB variable at the caller's site.
+
+ ' All other parameters work according to the FreeImage API documentation.
+
+ ' Note: Currently, any provided ReservePalette is only used, if quantize is
+ ' FIQ_NNQUANT. This seems to be either a bug or an undocumented
+ ' limitation of the FreeImage library (up to version 3.11.0).
+
+ If (dib) Then
+ If (FreeImage_GetBPP(dib) <> 24) Then
+ hTmp = dib
+ dib = FreeImage_ConvertTo24Bits(dib)
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(hTmp)
+ End If
+ bUnloadSource = True
+ End If
+
+ ' adjust PaletteSize
+ If (PaletteSize < 2) Then
+ PaletteSize = 2
+ ElseIf (PaletteSize > 256) Then
+ PaletteSize = 256
+ End If
+
+ lpPalette = pGetMemoryBlockPtrFromVariant(ReservePalette, lBlockSize, lElementSize)
+
+ FreeImage_ColorQuantizeEx = FreeImage_ColorQuantizeExInt(dib, _
+ quantize, PaletteSize, ReserveSize, lpPalette)
+
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(dib)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetPalettePtr(ByRef Palette() As RGBQUAD) As Long
+
+ ' Returns a pointer to an array of RGBQUAD. This is sometimes refered to as
+ ' a palette.
+
+ FreeImage_GetPalettePtr = VarPtr(Palette(0))
+
+End Function
+
+
+' Image Rescale wrapper functions
+
+Public Function FreeImage_RescaleEx(ByVal hDIB As Long, _
+ Optional ByVal vntDstWidth As Variant, _
+ Optional ByVal vntDstHeight As Variant, _
+ Optional ByVal bIsPercentValue As Boolean, _
+ Optional ByVal bUnloadSource As Boolean, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As Long
+
+Dim lNewWidth As Long
+Dim lNewHeight As Long
+Dim hDIBNew As Long
+
+ ' This function is a easy-to-use wrapper for rescaling an image with the
+ ' FreeImage library. It returns a pointer to a new rescaled DIB provided
+ ' by FreeImage.
+
+ ' The parameters 'vntDstWidth', 'vntDstHeight' and 'bIsPercentValue' control
+ ' the size of the new image. Here, the function tries to fake something like
+ ' overloading known from Java. It depends on the parameter's data type passed
+ ' through the Variant, how the provided values for width and height are
+ ' actually interpreted. The following rules apply:
+
+ ' In general, non integer values are either interpreted as percent values or
+ ' factors, the original image size will be multiplied with. The 'bIsPercentValue'
+ ' parameter controls whether the values are percent values or factors. Integer
+ ' values are always considered to be the direct new image size, not depending on
+ ' the original image size. In that case, the 'bIsPercentValue' parameter has no
+ ' effect. If one of the parameters is omitted, the image will not be resized in
+ ' that direction (either in width or height) and keeps it's original size. It is
+ ' possible to omit both, but that makes actually no sense.
+
+ ' The following table shows some of possible data type and value combinations
+ ' that might by used with that function: (assume an original image sized 100x100 px)
+
+ ' Parameter | Values | Values | Values | Values | Values |
+ ' ----------------------------------------------------------------------
+ ' vntDstWidth | 75.0 | 0.85 | 200 | 120 | 400.0 |
+ ' vntDstHeight | 120.0 | 1.3 | 230 | - | 400.0 |
+ ' bIsPercentValue | True | False | d.c. | d.c. | False | <- wrong option?
+ ' ----------------------------------------------------------------------
+ ' Result Size | 75x120 | 85x130 | 200x230 | 120x100 |40000x40000 |
+ ' Remarks | percent | factor | direct | |maybe not |
+ ' |what you |
+ ' |wanted, |
+ ' |right? |
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image, so
+ ' you can "change" an image with this function rather than getting a new DIB
+ ' pointer. There is no more need for a second DIB variable at the caller's site.
+
+ ' As of version 2.0 of the FreeImage VB wrapper, this function and all it's derived
+ ' functions like FreeImage_RescaleByPixel() or FreeImage_RescaleByPercent(), do NOT
+ ' return a clone of the image, if the new size desired is the same as the source
+ ' image's size. That behaviour can be forced by setting the new parameter
+ ' 'bForceCloneCreation' to True. Then, an image is also rescaled (and so
+ ' effectively cloned), if the new width and height is exactly the same as the source
+ ' image's width and height.
+
+ ' Since this diversity may be confusing to VB developers, this function is also
+ ' callable through three different functions called 'FreeImage_RescaleByPixel',
+ ' 'FreeImage_RescaleByPercent' and 'FreeImage_RescaleByFactor'.
+
+ If (Not IsMissing(vntDstWidth)) Then
+ Select Case VarType(vntDstWidth)
+
+ Case vbDouble, vbSingle, vbDecimal, vbCurrency
+ lNewWidth = FreeImage_GetWidth(hDIB) * vntDstWidth
+ If (bIsPercentValue) Then
+ lNewWidth = lNewWidth / 100
+ End If
+
+ Case Else
+ lNewWidth = vntDstWidth
+
+ End Select
+ End If
+
+ If (Not IsMissing(vntDstHeight)) Then
+ Select Case VarType(vntDstHeight)
+
+ Case vbDouble, vbSingle, vbDecimal
+ lNewHeight = FreeImage_GetHeight(hDIB) * vntDstHeight
+ If (bIsPercentValue) Then
+ lNewHeight = lNewHeight / 100
+ End If
+
+ Case Else
+ lNewHeight = vntDstHeight
+
+ End Select
+ End If
+
+ If ((lNewWidth > 0) And (lNewHeight > 0)) Then
+ If (bForceCloneCreation) Then
+ hDIBNew = FreeImage_Rescale(hDIB, lNewWidth, lNewHeight, eFilter)
+
+ ElseIf (lNewWidth <> FreeImage_GetWidth(hDIB)) Then
+ If (lNewHeight <> FreeImage_GetHeight(hDIB)) Then
+ hDIBNew = FreeImage_Rescale(hDIB, lNewWidth, lNewHeight, eFilter)
+ End If
+ End If
+
+ ElseIf (lNewWidth > 0) Then
+ If ((lNewWidth <> FreeImage_GetWidth(hDIB)) Or _
+ (bForceCloneCreation)) Then
+ lNewHeight = lNewWidth / (FreeImage_GetWidth(hDIB) / FreeImage_GetHeight(hDIB))
+ hDIBNew = FreeImage_Rescale(hDIB, lNewWidth, lNewHeight, eFilter)
+ End If
+
+ ElseIf (lNewHeight > 0) Then
+ If ((lNewHeight <> FreeImage_GetHeight(hDIB)) Or _
+ (bForceCloneCreation)) Then
+ lNewWidth = lNewHeight * (FreeImage_GetWidth(hDIB) / FreeImage_GetHeight(hDIB))
+ hDIBNew = FreeImage_Rescale(hDIB, lNewWidth, lNewHeight, eFilter)
+ End If
+
+ End If
+
+ If (hDIBNew) Then
+ FreeImage_RescaleEx = hDIBNew
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(hDIB)
+ End If
+ Else
+ FreeImage_RescaleEx = hDIB
+ End If
+
+End Function
+
+Public Function FreeImage_RescaleByPixel(ByVal hDIB As Long, _
+ Optional ByVal lDstWidthPixel As Long, _
+ Optional ByVal lDstHeightPixel As Long, _
+ Optional ByVal bUnloadSource As Boolean, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As Long
+
+ ' Thin wrapper for function 'FreeImage_RescaleEx' for removing method
+ ' overload fake. This function rescales the image directly to the size
+ ' specified by the 'lDstWidthPixel' and 'lDstHeightPixel' parameters.
+
+ FreeImage_RescaleByPixel = FreeImage_RescaleEx(hDIB, _
+ lDstWidthPixel, _
+ lDstHeightPixel, _
+ False, _
+ bUnloadSource, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+Public Function FreeImage_RescaleByPercent(ByVal hDIB As Long, _
+ Optional ByVal dblDstWidthPercent As Double, _
+ Optional ByVal dblDstHeightPercent As Double, _
+ Optional ByVal bUnloadSource As Boolean, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As Long
+
+ ' Thin wrapper for function 'FreeImage_RescaleEx' for removing method
+ ' overload fake. This function rescales the image by a percent value
+ ' based on the image's original size.
+
+ FreeImage_RescaleByPercent = FreeImage_RescaleEx(hDIB, _
+ dblDstWidthPercent, _
+ dblDstHeightPercent, _
+ True, _
+ bUnloadSource, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+Public Function FreeImage_RescaleByFactor(ByVal hDIB As Long, _
+ Optional ByVal dblDstWidthFactor As Double, _
+ Optional ByVal dblDstHeightFactor As Double, _
+ Optional ByVal bUnloadSource As Boolean, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As Long
+
+ ' Thin wrapper for function 'FreeImage_RescaleEx' for removing method
+ ' overload fake. This function rescales the image by a factor
+ ' based on the image's original size.
+
+ FreeImage_RescaleByFactor = FreeImage_RescaleEx(hDIB, _
+ dblDstWidthFactor, _
+ dblDstHeightFactor, _
+ False, _
+ bUnloadSource, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+' Painting functions
+
+Public Function FreeImage_PaintDC(ByVal hDC As Long, _
+ ByVal hDIB As Long, _
+ Optional ByVal lXDest As Long = 0, _
+ Optional ByVal lYDest As Long = 0, _
+ Optional ByVal lXSrc As Long = 0, _
+ Optional ByVal lYSrc As Long = 0, _
+ Optional ByVal lnSrcWidth As Long, _
+ Optional ByVal lnSrcHeight As Long) As Long
+
+ ' This function draws a FreeImage DIB directly onto a device context (DC). There
+ ' are many (selfexplaining?) parameters that control the visual result.
+
+ ' Parameters 'lXDest' and 'lYDest' specify the point where the output should
+ ' be painted and 'lXSrc', 'lYSrc', 'lnSrcWidth' and 'lnSrcHeight' span a rectangle
+ ' in the source image 'hDIB' that defines the area to be painted.
+
+ If ((hDC <> 0) And (hDIB <> 0)) Then
+
+ If (lnSrcWidth = 0) Then
+ lnSrcWidth = FreeImage_GetWidth(hDIB)
+ End If
+
+ If (lnSrcHeight = 0) Then
+ lnSrcHeight = FreeImage_GetHeight(hDIB)
+ End If
+
+ FreeImage_PaintDC = SetDIBitsToDevice(hDC, _
+ lXDest, lYDest - lYSrc, _
+ lnSrcWidth, lnSrcHeight, _
+ lXSrc, lYSrc, 0, lnSrcHeight, _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS)
+ End If
+
+End Function
+
+Public Function FreeImage_PaintDCEx(ByVal hDC As Long, _
+ ByVal hDIB As Long, _
+ Optional ByVal lXDest As Long = 0, _
+ Optional ByVal lYDest As Long = 0, _
+ Optional ByVal lnDestWidth As Long, _
+ Optional ByVal lnDestHeight As Long, _
+ Optional ByVal lXSrc As Long = 0, _
+ Optional ByVal lYSrc As Long = 0, _
+ Optional ByVal lnSrcWidth As Long, _
+ Optional ByVal lnSrcHeight As Long, _
+ Optional ByVal eDrawMode As DRAW_MODE = DM_DRAW_DEFAULT, _
+ Optional ByVal eRasterOperator As RASTER_OPERATOR = ROP_SRCCOPY, _
+ Optional ByVal eStretchMode As STRETCH_MODE = SM_COLORONCOLOR) As Long
+
+Dim eLastStretchMode As STRETCH_MODE
+
+ ' This function draws a FreeImage DIB directly onto a device context (DC). There
+ ' are many (selfexplaining?) parameters that control the visual result.
+
+ ' The main differences of this function compared to the 'FreeImage_PaintDC' are,
+ ' that this function supports mirroring and stretching of the image to be
+ ' painted and so, is somewhat slower than 'FreeImage_PaintDC'.
+
+ If ((hDC <> 0) And (hDIB <> 0)) Then
+
+ eLastStretchMode = GetStretchBltMode(hDC)
+ Call SetStretchBltMode(hDC, eStretchMode)
+
+ If (lnSrcWidth = 0) Then
+ lnSrcWidth = FreeImage_GetWidth(hDIB)
+ End If
+ If (lnDestWidth = 0) Then
+ lnDestWidth = lnSrcWidth
+ End If
+
+ If (lnSrcHeight = 0) Then
+ lnSrcHeight = FreeImage_GetHeight(hDIB)
+ End If
+ If (lnDestHeight = 0) Then
+ lnDestHeight = lnSrcHeight
+ End If
+
+ If (eDrawMode And DM_MIRROR_VERTICAL) Then
+ lYDest = lnDestHeight
+ lnDestHeight = -lnDestHeight
+ End If
+
+ If (eDrawMode And DM_MIRROR_HORIZONTAL) Then
+ lXDest = lnDestWidth
+ lnDestWidth = -lnDestWidth
+ End If
+
+ Call StretchDIBits(hDC, _
+ lXDest, lYDest, lnDestWidth, lnDestHeight, _
+ lXSrc, lYSrc, lnSrcWidth, lnSrcHeight, _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS, _
+ eRasterOperator)
+
+ Call SetStretchBltMode(hDC, eLastStretchMode)
+ End If
+
+End Function
+
+Public Function FreeImage_PaintTransparent(ByVal hDC As Long, _
+ ByVal hDIB As Long, _
+ Optional ByVal lXDest As Long = 0, _
+ Optional ByVal lYDest As Long = 0, _
+ Optional ByVal lnDestWidth As Long, _
+ Optional ByVal lnDestHeight As Long, _
+ Optional ByVal lXSrc As Long = 0, _
+ Optional ByVal lYSrc As Long = 0, _
+ Optional ByVal lnSrcWidth As Long, _
+ Optional ByVal lnSrcHeight As Long, _
+ Optional ByVal Alpha As Byte = 255) As Long
+
+Dim lpPalette As Long
+Dim bIsTransparent As Boolean
+
+ ' This function paints a device independent bitmap to any device context and
+ ' thereby honors any transparency information associated with the bitmap.
+ ' Furthermore, through the 'Alpha' parameter, an overall transparency level
+ ' may be specified.
+
+ ' For palletised images, any color set to be transparent in the transparency
+ ' table, will be transparent. For high color images, only 32-bit images may
+ ' have any transparency information associated in their alpha channel. Only
+ ' these may be painted with transparency by this function.
+
+ ' Since this is a wrapper for the Windows GDI function AlphaBlend(), 31-bit
+ ' images, containing alpha (or per-pixel) transparency, must be 'premultiplied'
+ ' for alpha transparent regions to actually show transparent. See MSDN help
+ ' on the AlphaBlend() function.
+
+ ' FreeImage also offers a function to premultiply 32-bit bitmaps with their alpha
+ ' channel, according to the needs of AlphaBlend(). Have a look at function
+ ' FreeImage_PreMultiplyWithAlpha().
+
+ ' Overall transparency level may be specified for all bitmaps in all color
+ ' depths supported by FreeImage. If needed, bitmaps are transparently converted
+ ' to 32-bit and unloaded after the paint operation. This is also true for palletised
+ ' bitmaps.
+
+ ' Parameters 'hDC' and 'hDIB' seem to be very self-explanatory. All other parameters
+ ' are optional. The group of '*Dest*' parameters span a rectangle on the destination
+ ' device context, used as drawing area for the bitmap. If these are omitted, the
+ ' bitmap will be drawn starting at position 0,0 in the bitmap's actual size.
+ ' The group of '*Src*' parameters span a rectangle on the source bitmap, used as
+ ' cropping area for the paint operation. If both rectangles differ in size in any
+ ' direction, the part of the image actually painted is stretched for to fit into
+ ' the drawing area. If any of the parameters '*Width' or '*Height' are omitted,
+ ' the bitmap's actual size (width or height) will be used.
+
+ ' The 'Alpha' parameter specifies the overall transparency. It takes values in the
+ ' range from 0 to 255. Using 0 will paint the bitmap fully transparent, 255 will
+ ' paint the image fully opaque. The 'Alpha' value controls, how the non per-pixel
+ ' portions of the image will be drawn.
+
+ If ((hDC <> 0) And (hDIB <> 0)) Then
+
+ ' get image width if not specified
+ If (lnSrcWidth = 0) Then
+ lnSrcWidth = FreeImage_GetWidth(hDIB)
+ End If
+ If (lnDestWidth = 0) Then
+ lnDestWidth = lnSrcWidth
+ End If
+
+ ' get image height if not specified
+ If (lnSrcHeight = 0) Then
+ lnSrcHeight = FreeImage_GetHeight(hDIB)
+ End If
+ If (lnDestHeight = 0) Then
+ lnDestHeight = lnSrcHeight
+ End If
+
+ lpPalette = FreeImage_GetPalette(hDIB)
+ If (lpPalette) Then
+
+ Dim lPaletteSize As Long
+ Dim alPalOrg(255) As Long
+ Dim alPalMod(255) As Long
+ Dim alPalMask(255) As Long
+ Dim abTT() As Byte
+ Dim i As Long
+
+ lPaletteSize = FreeImage_GetColorsUsed(hDIB) * 4
+ Call CopyMemory(alPalOrg(0), ByVal lpPalette, lPaletteSize)
+ Call CopyMemory(alPalMod(0), ByVal lpPalette, lPaletteSize)
+ abTT = FreeImage_GetTransparencyTableEx(hDIB)
+
+ If ((Alpha = 255) And _
+ (lnDestHeight >= lnSrcHeight) And (lnDestWidth >= lnSrcWidth)) Then
+
+ ' create a mask palette and a modified version of the
+ ' original palette
+ For i = 0 To UBound(abTT)
+ If (abTT(i) = 0) Then
+ alPalMask(i) = &HFFFFFFFF
+ alPalMod(i) = &H0
+ bIsTransparent = True
+ End If
+ Next i
+
+ If (Not bIsTransparent) Then
+
+ ' if there is no transparency in the image, paint it with
+ ' a single SRCCOPY
+ Call StretchDIBits(hDC, _
+ lXDest, lYDest, lnDestWidth, lnDestHeight, _
+ lXSrc, lYSrc, lnSrcWidth, lnSrcHeight, _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS, SRCCOPY)
+ Else
+
+ ' set mask palette and paint with SRCAND
+ Call CopyMemory(ByVal lpPalette, alPalMask(0), lPaletteSize)
+ Call StretchDIBits(hDC, _
+ lXDest, lYDest, lnDestWidth, lnDestHeight, _
+ lXSrc, lYSrc, lnSrcWidth, lnSrcHeight, _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS, SRCAND)
+
+ ' set mask modified and paint with SRCPAINT
+ Call CopyMemory(ByVal lpPalette, alPalMod(0), lPaletteSize)
+ Call StretchDIBits(hDC, _
+ lXDest, lYDest, lnDestWidth, lnDestHeight, _
+ lXSrc, lYSrc, lnSrcWidth, lnSrcHeight, _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS, SRCPAINT)
+
+ ' restore original palette
+ Call CopyMemory(ByVal lpPalette, alPalOrg(0), lPaletteSize)
+ End If
+
+ ' we are done, do not paint with AlphaBlend() any more
+ hDIB = 0
+ Else
+
+ ' create a premultiplied palette
+ ' since we have no real per pixel transparency in a palletized
+ ' image, we only need to set all transparent colors to null.
+ For i = 0 To UBound(abTT)
+ If (abTT(i) = 0) Then
+ alPalMod(i) = 0
+ End If
+ Next i
+
+ ' set premultiplied palette and convert to 32 bits
+ Call CopyMemory(ByVal lpPalette, alPalMod(0), lPaletteSize)
+ hDIB = FreeImage_ConvertTo32Bits(hDIB)
+
+ ' restore original palette
+ Call CopyMemory(ByVal lpPalette, alPalOrg(0), lPaletteSize)
+ End If
+ End If
+
+ If (hDIB) Then
+ Dim hMemDC As Long
+ Dim hBitmap As Long
+ Dim hBitmapOld As Long
+ Dim tBF As BLENDFUNCTION
+ Dim lBF As Long
+
+ hMemDC = CreateCompatibleDC(0)
+ If (hMemDC) Then
+ hBitmap = FreeImage_GetBitmap(hDIB, hMemDC)
+ hBitmapOld = SelectObject(hMemDC, hBitmap)
+
+ With tBF
+ .BlendOp = AC_SRC_OVER
+ .SourceConstantAlpha = Alpha
+ If (FreeImage_GetBPP(hDIB) = 32) Then
+ .AlphaFormat = AC_SRC_ALPHA
+ End If
+ End With
+ Call CopyMemory(lBF, tBF, 4)
+
+ Call AlphaBlend(hDC, lXDest, lYDest, lnDestWidth, lnDestHeight, _
+ hMemDC, lXSrc, lYSrc, lnSrcWidth, lnSrcHeight, _
+ lBF)
+
+ Call SelectObject(hMemDC, hBitmapOld)
+ Call DeleteObject(hBitmap)
+ Call DeleteDC(hMemDC)
+ If (lpPalette) Then
+ Call FreeImage_Unload(hDIB)
+ End If
+ End If
+ End If
+ End If
+
+End Function
+
+
+'--------------------------------------------------------------------------------
+' Pixel access functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetBitsEx(ByVal dib As Long) As Byte()
+
+Dim tSA As SAVEARRAY2D
+Dim lpSA As Long
+
+ ' This function returns a two dimensional Byte array containing a DIB's
+ ' data-bits. This is done by wrapping a true VB array around the memory
+ ' block the returned pointer of FreeImage_GetBits() is pointing to. So, the
+ ' array returned provides full read and write acces to the image's data.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the FreeImage_DestroyLockedArray() function.
+
+ If (dib) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 1 ' size in bytes per array element
+ .cDims = 2 ' the array has 2 dimensions
+ .cElements1 = FreeImage_GetHeight(dib) ' the number of elements in y direction (height of dib)
+ .cElements2 = FreeImage_GetPitch(dib) ' the number of elements in x direction (byte width of dib)
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetBits(dib) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(2, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named like the function is an array
+ ' variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetBitsEx), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetBitsExRGBTRIPLE(ByVal dib As Long) As RGBTRIPLE()
+
+Dim tSA As SAVEARRAY2D
+Dim lpSA As Long
+
+ ' This function returns a two dimensional RGBTRIPLE array containing a DIB's
+ ' data-bits. This is done by wrapping a true VB array around the memory
+ ' block the returned pointer of 'FreeImage_GetBits' is pointing to. So, the
+ ' array returned provides full read and write acces to the image's data.
+
+ ' This function only works with 24 bpp images and, since each FreeImage scanline
+ ' is aligned to a 32-bit boundary, only if the image's width in pixels multiplied
+ ' by three modulo four is zero. That means, that the image layout in memory must
+ ' "naturally" be aligned to a 32-bit boundary, since arrays do not support padding.
+
+ ' So, the function only returns an initialized array, if this equotion is true:
+ ' (((ImageWidthPixels * 3) Mod 4) = 0)
+
+ ' In other words, this is true for all images with no padding.
+
+ ' For instance, only images with these widths will be suitable for this function:
+ ' 100, 104, 108, 112, 116, 120, 124, ...
+
+ ' Have a look at the wrapper function 'FreeImage_GetScanlinesRGBTRIPLE()' to have
+ ' a way to work around that limitation.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ If (dib) Then
+
+ If (FreeImage_GetBPP(dib) = 24) Then
+ If (((FreeImage_GetWidth(dib) * 3) Mod 4) = 0) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 3 ' size in bytes per array element
+ .cDims = 2 ' the array has 2 dimensions
+ .cElements1 = FreeImage_GetHeight(dib) ' the number of elements in y direction (height of dib)
+ .cElements2 = FreeImage_GetWidth(dib) ' the number of elements in x direction (byte width of dib)
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetBits(dib) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(2, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named like the function is an array
+ ' variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetBitsExRGBTRIPLE), lpSA, 4)
+ Else
+
+ ' we could throw an error here
+ End If
+ Else
+
+ ' we could throw an error here
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetBitsExRGBQUAD(ByVal dib As Long) As RGBQUAD()
+
+Dim tSA As SAVEARRAY2D
+Dim lpSA As Long
+
+ ' This function returns a two dimensional RGBQUAD array containing a DIB's
+ ' data-bits. This is done by wrapping a true VB array around the memory
+ ' block the returned pointer of 'FreeImage_GetBits' is pointing to. So, the
+ ' array returned provides full read and write acces to the image's data.
+
+ ' This function only works with 32 bpp images. Since each scanline must
+ ' "naturally" start at a 32-bit boundary if each pixel uses 32 bits, there
+ ' are no padding problems like these known with 'FreeImage_GetBitsExRGBTRIPLE',
+ ' so, this function is suitable for all 32 bpp images of any size.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ If (dib) Then
+
+ If (FreeImage_GetBPP(dib) = 32) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes per array element
+ .cDims = 2 ' the array has 2 dimensions
+ .cElements1 = FreeImage_GetHeight(dib) ' the number of elements in y direction (height of dib)
+ .cElements2 = FreeImage_GetWidth(dib) ' the number of elements in x direction (byte width of dib)
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetBits(dib) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(2, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named like the function is an array
+ ' variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetBitsExRGBQUAD), lpSA, 4)
+ Else
+
+ ' we could throw an error here
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLinesRGBTRIPLE(ByVal dib As Long, _
+ ByRef scanlines As ScanLinesRGBTRIBLE, _
+ Optional ByVal reverse As Boolean) As Long
+Dim lHeight As Long
+Dim i As Long
+
+ ' still undocumented
+ ' for now, have a look at function FreeImage_GetBitsExRGBTRIPLE()
+
+ If (dib) Then
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ If (FreeImage_GetBPP(dib) = 24) Then
+
+ lHeight = FreeImage_GetHeight(dib)
+ ReDim scanlines.Scanline(lHeight - 1)
+ For i = 0 To lHeight - 1
+ If (Not reverse) Then
+ scanlines.Scanline(i).Data = FreeImage_GetScanLineBITMAP24(dib, i)
+ Else
+ scanlines.Scanline(i).Data = FreeImage_GetScanLineBITMAP24(dib, lHeight - i - 1)
+ End If
+ Next i
+ End If
+ End If
+ End If
+
+ FreeImage_GetScanLinesRGBTRIPLE = lHeight
+
+End Function
+
+Public Function FreeImage_GetScanLineEx(ByVal dib As Long, _
+ ByVal Scanline As Long) As Byte()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a one dimensional Byte array containing a whole
+ ' scanline's data-bits. This is done by wrapping a true VB array around
+ ' the memory block the returned pointer of 'FreeImage_GetScanline' is
+ ' pointing to. So, the array returned provides full read and write acces
+ ' to the image's data.
+
+ ' This is the most generic function of a complete function set dealing with
+ ' scanline data, since this function returns an array of type Byte. It is
+ ' up to the caller of the function to interpret these bytes correctly,
+ ' according to the results of FreeImage_GetBPP and FreeImage_GetImageType.
+
+ ' You may consider using any of the non-generic functions named
+ ' 'FreeImage_GetScanLineXXX', that return an array of proper type, according
+ ' to the images bit depth and type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ If (dib) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 1 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetLine(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' allocate memory for an array descriptor
+ ' we cannot use the memory block used by tSA, since it is
+ ' released when tSA goes out of scope, leaving us with an
+ ' array with zeroed descriptor
+ ' we use nearly the same method that VB uses, so VB is able
+ ' to cleanup the array variable and it's descriptor; the
+ ' array data is not touched when cleaning up, since both AUTO
+ ' and FIXEDSIZE flags are set
+ Call SafeArrayAllocDescriptor(1, lpSA)
+
+ ' copy our own array descriptor over the descriptor allocated
+ ' by SafeArrayAllocDescriptor; lpSA is a pointer to that memory
+ ' location
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+
+ ' the implicit variable named like the function is an array
+ ' variable in VB
+ ' make it point to the allocated array descriptor
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineEx), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineBITMAP8(ByVal dib As Long, _
+ ByVal Scanline As Long) As Byte()
+
+ ' This function returns a one dimensional Byte array containing a whole
+ ' scanline's data-bits of a 8 bit bitmap image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' This function is just a thin wrapper for 'FreeImage_GetScanLineEx' but
+ ' includes checking of the image's bit depth and type, as all of the
+ ' non-generic scanline functions do.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ Select Case FreeImage_GetBPP(dib)
+
+ Case 1, 4, 8
+ FreeImage_GetScanLineBITMAP8 = FreeImage_GetScanLineEx(dib, Scanline)
+
+ End Select
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineBITMAP16(ByVal dib As Long, _
+ ByVal Scanline As Long) As Integer()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a one dimensional Integer array containing a whole
+ ' scanline's data-bits of a 16 bit bitmap image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ If (FreeImage_GetBPP(dib) = 16) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 2 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineBITMAP16), lpSA, 4)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineBITMAP24(ByVal dib As Long, _
+ ByVal Scanline As Long) As RGBTRIPLE()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a one dimensional RGBTRIPLE array containing a whole
+ ' scanline's data-bits of a 24 bit bitmap image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayRGBTRIPLE' function.
+
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ If (FreeImage_GetBPP(dib) = 24) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 3 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineBITMAP24), lpSA, 4)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineBITMAP32(ByVal dib As Long, _
+ ByVal Scanline As Long) As RGBQUAD()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+
+ ' This function returns a one dimensional RGBQUAD array containing a whole
+ ' scanline's data-bits of a 32 bit bitmap image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayRGBQUAD' function.
+
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ If (FreeImage_GetBPP(dib) = 32) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineBITMAP32), lpSA, 4)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineINT16(ByVal dib As Long, _
+ ByVal Scanline As Long) As Integer()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional Integer array containing a whole
+ ' scanline's data-bits of a FIT_INT16 or FIT_UINT16 image. This is done
+ ' by wrapping a true VB array around the memory block the returned pointer
+ ' of 'FreeImage_GetScanline' is pointing to. So, the array returned
+ ' provides full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' Since VB does not distinguish between signed and unsigned data types, both
+ ' image types FIT_INT16 and FIT_UINT16 are handled with this function. If 'dib'
+ ' specifies an image of type FIT_UINT16, it is up to the caller to treat the
+ ' array's Integers as unsigned, although VB knows signed Integers only.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If ((eImageType = FIT_INT16) Or _
+ (eImageType = FIT_UINT16)) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 2 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineINT16), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineINT32(ByVal dib As Long, _
+ ByVal Scanline As Long) As Long()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional Long array containing a whole
+ ' scanline's data-bits of a FIT_INT32 or FIT_UINT32 image. This is done
+ ' by wrapping a true VB array around the memory block the returned pointer
+ ' of 'FreeImage_GetScanline' is pointing to. So, the array returned
+ ' provides full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' Since VB does not distinguish between signed and unsigned data types, both
+ ' image types FIT_INT32 and FIT_UINT32 are handled with this function. If 'dib'
+ ' specifies an image of type FIT_UINT32, it is up to the caller to treat the
+ ' array's Longs as unsigned, although VB knows signed Longs only.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If ((eImageType = FIT_INT32) Or _
+ (eImageType = FIT_UINT32)) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineINT32), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineFLOAT(ByVal dib As Long, _
+ ByVal Scanline As Long) As Single()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional Single array containing a whole
+ ' scanline's data-bits of a FIT_FLOAT image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_FLOAT) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 4 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineFLOAT), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineDOUBLE(ByVal dib As Long, _
+ ByVal Scanline As Long) As Double()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional Double array containing a whole
+ ' scanline's data-bits of a FIT_DOUBLE image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArray' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_DOUBLE) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 8 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineDOUBLE), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineCOMPLEX(ByVal dib As Long, _
+ ByVal Scanline As Long) As FICOMPLEX()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional FICOMPLEX array containing a whole
+ ' scanline's data-bits of a FIT_COMPLEX image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayFICOMPLEX' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_COMPLEX) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 16 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineCOMPLEX), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineRGB16(ByVal dib As Long, _
+ ByVal Scanline As Long) As FIRGB16()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional FIRGB16 array containing a whole
+ ' scanline's data-bits of a FIT_RGB16 image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayFIRGB16' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_RGB16) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 6 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineRGB16), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineRGBA16(ByVal dib As Long, _
+ ByVal Scanline As Long) As FIRGBA16()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional FIRGBA16 array containing a whole
+ ' scanline's data-bits of a FIT_RGBA16 image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayFIRGBA16' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_RGBA16) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 8 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineRGBA16), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineRGBF(ByVal dib As Long, _
+ ByVal Scanline As Long) As FIRGBF()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional FIRGBF array containing a whole
+ ' scanline's data-bits of a FIT_RGBF image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayFIRGBF' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_RGBF) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 12 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineRGBF), lpSA, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_GetScanLineRGBAF(ByVal dib As Long, _
+ ByVal Scanline As Long) As FIRGBAF()
+
+Dim tSA As SAVEARRAY1D
+Dim lpSA As Long
+Dim eImageType As FREE_IMAGE_TYPE
+
+ ' This function returns a one dimensional FIRGBAF array containing a whole
+ ' scanline's data-bits of a FIT_RGBAF image. This is done by wrapping
+ ' a true VB array around the memory block the returned pointer of
+ ' 'FreeImage_GetScanline' is pointing to. So, the array returned provides
+ ' full read and write acces to the image's data.
+
+ ' The function includes checking of the image's bit depth and type and
+ ' returns a non-initialized array if 'dib' is an image of inproper type.
+
+ ' To reuse the caller's array variable, this function's result was assigned to,
+ ' before it goes out of scope, the caller's array variable must be destroyed with
+ ' the 'FreeImage_DestroyLockedArrayFIRGBAF' function.
+
+ eImageType = FreeImage_GetImageType(dib)
+ If (eImageType = FIT_RGBAF) Then
+
+ ' create a proper SAVEARRAY descriptor
+ With tSA
+ .cbElements = 12 ' size in bytes per array element
+ .cDims = 1 ' the array has only 1 dimension
+ .cElements = FreeImage_GetWidth(dib) ' the number of elements in the array
+ .fFeatures = FADF_AUTO Or FADF_FIXEDSIZE ' need AUTO and FIXEDSIZE for safety issues,
+ ' so the array can not be modified in size
+ ' or erased; according to Matthew Curland never
+ ' use FIXEDSIZE alone
+ .pvData = FreeImage_GetScanline(dib, _
+ Scanline) ' let the array point to the memory block, the
+ ' FreeImage scanline data pointer points to
+ End With
+
+ ' For a complete source code documentation have a
+ ' look at the function 'FreeImage_GetScanLineEx'
+ Call SafeArrayAllocDescriptor(1, lpSA)
+ Call CopyMemory(ByVal lpSA, tSA, Len(tSA))
+ Call CopyMemory(ByVal VarPtrArray(FreeImage_GetScanLineRGBAF), lpSA, 4)
+ End If
+
+End Function
+
+'--------------------------------------------------------------------------------
+' HBITMAP conversion functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetBitmap(ByVal dib As Long, _
+ Optional ByVal hDC As Long, _
+ Optional ByVal bUnloadSource As Boolean) As Long
+
+Dim bReleaseDC As Boolean
+Dim ppvBits As Long
+
+ ' This function returns an HBITMAP created by the CreateDIBSection() function which
+ ' in turn has the same color depth as the original DIB. A reference DC may be provided
+ ' through the 'hDC' parameter. The desktop DC will be used, if no reference DC is
+ ' specified.
+
+ If (dib) Then
+ If (hDC = 0) Then
+ hDC = GetDC(0)
+ bReleaseDC = True
+ End If
+ If (hDC) Then
+ FreeImage_GetBitmap = CreateDIBSection(hDC, FreeImage_GetInfo(dib), DIB_RGB_COLORS, ppvBits, 0, 0)
+ If ((FreeImage_GetBitmap <> 0) And (ppvBits <> 0)) Then
+ Call CopyMemory(ByVal ppvBits, ByVal FreeImage_GetBits(dib), _
+ FreeImage_GetHeight(dib) * FreeImage_GetPitch(dib))
+ End If
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(dib)
+ End If
+ If (bReleaseDC) Then
+ Call ReleaseDC(0, hDC)
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetBitmapForDevice(ByVal dib As Long, _
+ Optional ByVal hDC As Long, _
+ Optional ByVal bUnloadSource As Boolean) As Long
+
+Dim bReleaseDC As Boolean
+
+ ' This function returns an HBITMAP created by the CreateDIBitmap() function which
+ ' in turn has always the same color depth as the reference DC, which may be provided
+ ' through the 'hDC' parameter. The desktop DC will be used, if no reference DC is
+ ' specified.
+
+ If (dib) Then
+ If (hDC = 0) Then
+ hDC = GetDC(0)
+ bReleaseDC = True
+ End If
+ If (hDC) Then
+ FreeImage_GetBitmapForDevice = _
+ CreateDIBitmap(hDC, FreeImage_GetInfoHeader(dib), CBM_INIT, _
+ FreeImage_GetBits(dib), FreeImage_GetInfo(dib), DIB_RGB_COLORS)
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(dib)
+ End If
+ If (bReleaseDC) Then
+ Call ReleaseDC(0, hDC)
+ End If
+ End If
+ End If
+
+End Function
+
+'--------------------------------------------------------------------------------
+' OlePicture conversion functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetOlePicture(ByVal hDIB As Long, _
+ Optional ByVal hDC As Long, _
+ Optional ByVal bUnloadSource As Boolean) As IPicture
+
+Dim hBmp As Long
+Dim tPicDesc As PictDesc
+Dim tGuid As Guid
+Dim cPictureDisp As IPictureDisp
+
+ ' This function creates a VB Picture object (OlePicture) from a FreeImage DIB.
+ ' The original image must not remain valid nor loaded after the VB Picture
+ ' object has been created.
+
+ ' The optional parameter 'hDC' determines the device context (DC) used for
+ ' transforming the device independent bitmap (DIB) to a device dependent
+ ' bitmap (DDB). This device context's color depth is responsible for this
+ ' transformation. This parameter may be null or omitted. In that case, the
+ ' windows desktop's device context will be used, what will be the desired
+ ' way in almost any cases.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image
+ ' after the OlePicture has been created, so you can easiely "switch" from a
+ ' FreeImage DIB to a VB Picture object. There is no need to clean up the DIB
+ ' at the caller's site.
+
+ If (hDIB) Then
+ hBmp = FreeImage_GetBitmap(hDIB, hDC, bUnloadSource)
+ If (hBmp) Then
+ ' fill tPictDesc structure with necessary parts
+ With tPicDesc
+ .cbSizeofStruct = Len(tPicDesc)
+ .picType = vbPicTypeBitmap
+ .hImage = hBmp
+ End With
+
+ ' fill in IDispatch Interface ID
+ With tGuid
+ .Data1 = &H20400
+ .Data4(0) = &HC0
+ .Data4(7) = &H46
+ End With
+
+ ' create a picture object
+ Call OleCreatePictureIndirect(tPicDesc, tGuid, True, cPictureDisp)
+ Set FreeImage_GetOlePicture = cPictureDisp
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_GetOlePictureIcon(ByVal hIcon As Long) As IPicture
+
+Dim tPicDesc As PictDesc
+Dim tGuid As Guid
+Dim cPictureDisp As IPictureDisp
+
+ ' This function creates a VB Picture object (OlePicture) of type picTypeIcon
+ ' from FreeImage hIcon handle. The hIcon handle must not remain valid nor loaded
+ ' after the VB Picture object has been created.
+
+ ' The optional 'bUnloadSource' parameter is for destroying the hIcon image
+ ' after the OlePicture has been created, so you can easiely "switch" from a
+ ' hIcon handle to a VB Picture object. There is no need to clean up the hIcon
+ ' at the caller's site.
+
+ If (hIcon) Then
+ ' fill tPictDesc structure with necessary parts
+ With tPicDesc
+ .cbSizeofStruct = 12
+ .picType = vbPicTypeIcon
+ .hImage = hIcon
+ End With
+
+ ' fill in IDispatch Interface ID
+ With tGuid
+ .Data1 = &H20400
+ .Data4(0) = &HC0
+ .Data4(7) = &H46
+ End With
+
+ ' create a picture object
+ Call OleCreatePictureIndirect(tPicDesc, tGuid, True, cPictureDisp)
+ Set FreeImage_GetOlePictureIcon = cPictureDisp
+ End If
+
+End Function
+
+Public Function FreeImage_GetOlePictureThumbnail(ByVal hDIB As Long, _
+ ByVal lMaxSize As Long, _
+ Optional ByVal hDC As Long, _
+ Optional ByVal bUnloadSource As Boolean) As IPicture
+
+Dim hDIBThumbnail As Long
+
+ ' This function is a IOlePicture aware wrapper for FreeImage_MakeThumbnail(). It
+ ' returns a VB Picture object instead of a FreeImage DIB.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image
+ ' after the OlePicture has been created, so you can easiely "switch" from a
+ ' FreeImage DIB to a VB Picture object. There is no need to clean up the DIB
+ ' at the caller's site.
+
+ hDIBThumbnail = FreeImage_MakeThumbnail(hDIB, lMaxSize)
+ Set FreeImage_GetOlePictureThumbnail = FreeImage_GetOlePicture(hDIBThumbnail, hDC, True)
+
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+Public Function FreeImage_CreateFromOlePicture(ByRef IOlePicture As IPicture) As Long
+
+Dim hBmp As Long
+Dim tBM As BITMAP_API
+Dim hDIB As Long
+Dim hDC As Long
+Dim lResult As Long
+Dim nColors As Long
+Dim lpInfo As Long
+
+ ' Creates a FreeImage DIB from a VB Picture object (OlePicture). This function
+ ' returns a pointer to the DIB as, for instance, the FreeImage function
+ ' 'FreeImage_Load' does. So, this could be a real replacement for 'FreeImage_Load'
+ ' when working with VB Picture objects.
+
+ If (Not IOlePicture Is Nothing) Then
+ hBmp = IOlePicture.Handle
+ If (hBmp) Then
+ lResult = GetObjectAPI(hBmp, Len(tBM), tBM)
+ If (lResult) Then
+ hDIB = FreeImage_Allocate(tBM.bmWidth, _
+ tBM.bmHeight, _
+ tBM.bmBitsPixel)
+ If (hDIB) Then
+ ' The GetDIBits function clears the biClrUsed and biClrImportant BITMAPINFO
+ ' members (dont't know why). So we save these infos below.
+ ' This is needed for palletized images only.
+ nColors = FreeImage_GetColorsUsed(hDIB)
+
+ hDC = GetDC(0)
+ lResult = GetDIBits(hDC, hBmp, 0, _
+ FreeImage_GetHeight(hDIB), _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS)
+ If (lResult) Then
+ FreeImage_CreateFromOlePicture = hDIB
+ If (nColors) Then
+ ' restore BITMAPINFO members
+ ' FreeImage_GetInfo(dib)->biClrUsed = nColors;
+ ' FreeImage_GetInfo(dib)->biClrImportant = nColors;
+ lpInfo = FreeImage_GetInfo(hDIB)
+ Call CopyMemory(ByVal lpInfo + 32, nColors, 4)
+ Call CopyMemory(ByVal lpInfo + 36, nColors, 4)
+ End If
+ Else
+ Call FreeImage_Unload(hDIB)
+ End If
+ Call ReleaseDC(0, hDC)
+ End If
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_CreateFromDC(ByVal hDC As Long, _
+ Optional ByRef hBmp As Long) As Long
+
+Dim tBM As BITMAP_API
+Dim hDIB As Long
+Dim lResult As Long
+Dim nColors As Long
+Dim lpInfo As Long
+
+ ' Creates a FreeImage DIB from a Device Context/Compatible Bitmap. This
+ ' function returns a pointer to the DIB as, for instance, 'FreeImage_Load()'
+ ' does. So, this could be a real replacement for FreeImage_Load() or
+ ' 'FreeImage_CreateFromOlePicture()' when working with DCs and BITMAPs directly
+
+ ' The 'hDC' parameter specifies a window device context (DC), the optional
+ ' parameter 'hBmp' may specify a handle to a memory bitmap. When 'hBmp' is
+ ' omitted, the bitmap currently selected into the given DC is used to create
+ ' the DIB.
+
+ ' When 'hBmp' is not missing but NULL (0), the function uses the DC's currently
+ ' selected bitmap. This bitmap's handle is stored in the ('ByRef'!) 'hBmp' parameter
+ ' and so, is avaliable at the caller's site when the function returns.
+
+ ' The DIB returned by this function is a copy of the image specified by 'hBMP' or
+ ' the DC's current bitmap when 'hBMP' is missing. The 'hDC' and also the 'hBMP'
+ ' remain untouched in this function, there will be no objects destroyed or freed.
+ ' The caller is responsible to destroy or free the DC and BITMAP if necessary.
+
+ ' first, check whether we got a hBmp or not
+ If (hBmp = 0) Then
+ ' if not, the parameter may be missing or is NULL so get the
+ ' DC's current bitmap
+ hBmp = GetCurrentObject(hDC, OBJ_BITMAP)
+ End If
+
+ lResult = GetObjectAPI(hBmp, Len(tBM), tBM)
+ If (lResult) Then
+ hDIB = FreeImage_Allocate(tBM.bmWidth, _
+ tBM.bmHeight, _
+ tBM.bmBitsPixel)
+ If (hDIB) Then
+ ' The GetDIBits function clears the biClrUsed and biClrImportant BITMAPINFO
+ ' members (dont't know why). So we save these infos below.
+ ' This is needed for palletized images only.
+ nColors = FreeImage_GetColorsUsed(hDIB)
+
+ lResult = GetDIBits(hDC, hBmp, 0, _
+ FreeImage_GetHeight(hDIB), _
+ FreeImage_GetBits(hDIB), _
+ FreeImage_GetInfo(hDIB), _
+ DIB_RGB_COLORS)
+
+ If (lResult) Then
+ FreeImage_CreateFromDC = hDIB
+ If (nColors) Then
+ ' restore BITMAPINFO members
+ ' FreeImage_GetInfo(dib)->biClrUsed = nColors;
+ ' FreeImage_GetInfo(dib)->biClrImportant = nColors;
+ lpInfo = FreeImage_GetInfo(hDIB)
+ Call CopyMemory(ByVal lpInfo + 32, nColors, 4)
+ Call CopyMemory(ByVal lpInfo + 36, nColors, 4)
+ End If
+ Else
+ Call FreeImage_Unload(hDIB)
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_CreateFromImageContainer(ByRef Container As Object, _
+ Optional ByVal IncludeDrawings As Boolean) As Long
+
+ ' Creates a FreeImage DIB from a VB container control that has at least a
+ ' 'Picture' property. This function returns a pointer to the DIB as, for
+ ' instance, 'FreeImage_Load()' does. So, this could be a real replacement for
+ ' FreeImage_Load() or 'FreeImage_CreateFromOlePicture()' when working with
+ ' image hosting controls like Forms or PictureBoxes.
+
+ ' The 'IncludeDrawings' parameter controls whether drawings, drawn with VB
+ ' methods like 'Container.Print()', 'Container.Line(x1, y1)-(x2, y2)' or
+ ' 'Container.Circle(x, y), radius' as the controls 'BackColor' should be included
+ ' into the newly created DIB. However, this only works, with control's that
+ ' have their 'AutoRedraw' property set to 'True'.
+
+ ' To get the control's picture as well as it's BackColor and custom drawings,
+ ' this function uses the control's 'Image' property instead of the 'Picture'
+ ' property.
+
+ ' This function treats Forms and PictureBox controls explicitly, since the
+ ' property sets and behaviours of these controls are publicly known. For any
+ ' other control, the function checks for the existence of an 'Image' and
+ ' 'AutoRedraw' property. If these are present and 'IncludeDrawings' is 'True',
+ ' the function uses the control's 'Image' property instead of the 'Picture'
+ ' property. This my be the case for UserControls. In any other case, the function
+ ' uses the control's 'Picture' property if present. If none of these properties
+ ' is present, a runtime error (5) is generated.
+
+ ' Most of this function is actually implemented in the wrapper's private helper
+ ' function 'pGetIOlePictureFromContainer'.
+
+ If (Not Container Is Nothing) Then
+ FreeImage_CreateFromImageContainer = FreeImage_CreateFromOlePicture( _
+ pGetIOlePictureFromContainer(Container, _
+ IncludeDrawings))
+ End If
+
+End Function
+
+Public Function FreeImage_CreateFromScreen(Optional ByVal hWnd As Long, _
+ Optional ByVal bClientAreaOnly As Boolean) As Long
+
+Dim hDC As Long
+Dim lWidth As Long
+Dim lHeight As Long
+Dim hMemDC As Long
+Dim hMemBMP As Long
+Dim hMemOldBMP As Long
+Dim tR As RECT
+
+ ' Creates a FreeImage DIB from the screen which may either be the whole
+ ' desktop/screen or a certain window. A certain window may be specified
+ ' by it's window handle through the 'hWnd' parameter. By omitting this
+ ' parameter, the whole screen/desktop window will be captured.
+
+ If (hWnd = 0) Then
+ hWnd = GetDesktopWindow()
+ hDC = GetDCEx(hWnd, 0, 0)
+ ' get desktop's width and height
+ lWidth = GetDeviceCaps(hDC, HORZRES)
+ lHeight = GetDeviceCaps(hDC, VERTRES)
+
+ ElseIf (bClientAreaOnly) Then
+ ' get window's client area DC
+ hDC = GetDCEx(hWnd, 0, 0)
+ Call GetClientRect(hWnd, tR)
+ lWidth = tR.Right
+ lHeight = tR.Bottom
+
+ Else
+ ' get window DC
+ hDC = GetDCEx(hWnd, 0, DCX_WINDOW)
+ Call GetWindowRect(hWnd, tR)
+ lWidth = tR.Right - tR.Left
+ lHeight = tR.Bottom - tR.Top
+
+ End If
+
+ ' create compatible memory DC and bitmap
+ hMemDC = CreateCompatibleDC(hDC)
+ hMemBMP = CreateCompatibleBitmap(hDC, lWidth, lHeight)
+ ' select compatible bitmap
+ hMemOldBMP = SelectObject(hMemDC, hMemBMP)
+ ' blit bits
+ Call BitBlt(hMemDC, 0, 0, lWidth, lHeight, hDC, 0, 0, SRCCOPY Or CAPTUREBLT)
+
+ ' create FreeImgage dib from memory DC
+ FreeImage_CreateFromScreen = FreeImage_CreateFromDC(hMemDC, hMemBMP)
+
+ ' clean up
+ Call SelectObject(hMemDC, hMemOldBMP)
+ Call DeleteObject(hMemBMP)
+ Call DeleteDC(hMemDC)
+ Call ReleaseDC(hWnd, hDC)
+
+End Function
+
+Public Function FreeImage_CreateMask(ByVal hDIB As Long, _
+ Optional ByVal eMaskCreationOptions As FREE_IMAGE_MASK_CREATION_OPTION_FLAGS = MCOF_CREATE_MASK_IMAGE, _
+ Optional ByVal lBitDepth As Long = 1, _
+ Optional ByVal eMaskOptions As FREE_IMAGE_MASK_FLAGS = FIMF_MASK_FULL_TRANSPARENCY, _
+ Optional ByVal vntMaskColors As Variant, _
+ Optional ByVal eMaskColorsFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lColorTolerance As Long, _
+ Optional ByVal lciMaskColorDst As Long = vbWhite, _
+ Optional ByVal eMaskColorDstFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lciUnmaskColorDst As Long = vbBlack, _
+ Optional ByVal eUnmaskColorDstFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal vlciMaskColorSrc As Variant, _
+ Optional ByVal eMaskColorSrcFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal vlciUnmaskColorSrc As Variant, _
+ Optional ByVal eUnmaskColorSrcFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB) As Long
+
+Dim hDIBResult As Long
+Dim lBitDepthSrc As Long
+Dim lWidth As Long
+Dim lHeight As Long
+
+Dim bMaskColors As Boolean
+Dim bMaskTransparency As Boolean
+Dim bMaskFullTransparency As Boolean
+Dim bMaskAlphaTransparency As Boolean
+Dim bInvertMask As Boolean
+Dim bHaveMaskColorSrc As Boolean
+Dim bHaveUnmaskColorSrc As Boolean
+Dim bCreateMaskImage As Boolean
+Dim bModifySourceImage As Boolean
+Dim alcMaskColors() As Long
+Dim lMaskColorsMaxIndex As Long
+
+Dim lciMaskColorSrc As Long
+Dim lciUnmaskColorSrc As Long
+
+Dim alPaletteSrc() As Long
+Dim abTransparencyTableSrc() As Byte
+Dim abBitsBSrc() As Byte
+Dim atBitsTSrc As ScanLinesRGBTRIBLE
+Dim atBitsQSrc() As RGBQUAD
+Dim abBitValues(7) As Byte
+Dim abBitMasks(7) As Byte
+Dim abBitShifts(7) As Byte
+
+Dim atPaletteDst() As RGBQUAD
+Dim abBitsBDst() As Byte
+Dim atBitsTDst As ScanLinesRGBTRIBLE
+Dim atBitsQDst() As RGBQUAD
+
+Dim bMaskPixel As Boolean
+Dim x As Long
+Dim x2 As Long
+Dim lPixelIndex As Long
+Dim y As Long
+Dim i As Long
+
+ 'TODO: comment this function
+
+ ' check for a proper bit depth of the destination (mask) image
+ If ((hDIB) And ((lBitDepth = 1) Or _
+ (lBitDepth = 4) Or _
+ (lBitDepth = 8) Or _
+ (lBitDepth = 24) Or _
+ (lBitDepth = 32))) Then
+
+ ' check for a proper bit depth of the source image
+ lBitDepthSrc = FreeImage_GetBPP(hDIB)
+ If ((lBitDepthSrc = 4) Or _
+ (lBitDepthSrc = 8) Or _
+ (lBitDepthSrc = 24) Or _
+ (lBitDepthSrc = 32)) Then
+
+
+ ' get some information from eMaskCreationOptions
+ bCreateMaskImage = (eMaskCreationOptions And MCOF_CREATE_MASK_IMAGE)
+ bModifySourceImage = (eMaskCreationOptions And MCOF_MODIFY_SOURCE_IMAGE)
+
+
+ If (bCreateMaskImage) Then
+
+ ' check mask color format
+ If (eMaskColorDstFormat And FICFF_COLOR_BGR) Then
+ ' if mask color is in BGR format, convert to RGB format
+ lciMaskColorDst = FreeImage_SwapColorLong(lciMaskColorDst)
+
+ ElseIf (eMaskColorDstFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ ' if mask color is specified as palette index, check, whether the
+ ' source image is a palletized image
+ Select Case lBitDepthSrc
+
+ Case 1
+ lciMaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciMaskColorDst And &H1)
+
+ Case 4
+ lciMaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciMaskColorDst And &HF)
+
+ Case 8
+ lciMaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciMaskColorDst And &HFF)
+
+ End Select
+ End If
+
+ ' check unmask color format
+ If (eUnmaskColorDstFormat And FICFF_COLOR_BGR) Then
+ ' if unmask color is in BGR format, convert to RGB format
+ lciUnmaskColorDst = FreeImage_SwapColorLong(lciUnmaskColorDst)
+
+ ElseIf (eUnmaskColorDstFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ ' if unmask color is specified as palette index, check, whether the
+ ' source image is a palletized image
+ Select Case lBitDepthSrc
+
+ Case 1
+ lciUnmaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciUnmaskColorDst And &H1)
+
+ Case 4
+ lciUnmaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciUnmaskColorDst And &HF)
+
+ Case 8
+ lciUnmaskColorDst = FreeImage_GetPaletteExLong(hDIB)(lciUnmaskColorDst And &HFF)
+
+ End Select
+ End If
+ End If
+
+
+ If (bModifySourceImage) Then
+
+ ' check, whether source image can be modified
+ bHaveMaskColorSrc = (Not IsMissing(vlciMaskColorSrc))
+ bHaveUnmaskColorSrc = (Not IsMissing(vlciUnmaskColorSrc))
+
+ Select Case lBitDepthSrc
+
+ Case 4, 8
+ If (bHaveMaskColorSrc) Then
+
+ ' get mask color as Long
+ lciMaskColorSrc = vlciMaskColorSrc
+
+ If (eMaskColorSrcFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ If (lBitDepthSrc = 4) Then
+ lciMaskColorSrc = (lciMaskColorSrc And &HF)
+ Else
+ lciMaskColorSrc = (lciMaskColorSrc And &HFF)
+ End If
+ Else
+ If (eMaskColorSrcFormat And FICFF_COLOR_BGR) Then
+ lciMaskColorSrc = FreeImage_SwapColorLong(lciMaskColorSrc, True)
+ End If
+ lciMaskColorSrc = FreeImage_SearchPalette(hDIB, lciMaskColorSrc)
+ bHaveMaskColorSrc = (lciMaskColorSrc <> -1)
+ End If
+ End If
+
+ If (bHaveUnmaskColorSrc) Then
+
+ ' get unmask color as Long
+ lciUnmaskColorSrc = vlciUnmaskColorSrc
+
+ If (eUnmaskColorSrcFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ If (lBitDepthSrc = 4) Then
+ lciUnmaskColorSrc = (lciUnmaskColorSrc And &HF)
+ Else
+ lciUnmaskColorSrc = (lciUnmaskColorSrc And &HFF)
+ End If
+ Else
+ If (eUnmaskColorSrcFormat And FICFF_COLOR_BGR) Then
+ lciUnmaskColorSrc = FreeImage_SwapColorLong(lciUnmaskColorSrc, True)
+ End If
+ lciUnmaskColorSrc = FreeImage_SearchPalette(hDIB, lciUnmaskColorSrc)
+ bHaveUnmaskColorSrc = (lciUnmaskColorSrc <> -1)
+ End If
+ End If
+
+ ' check, if source image still can be modified in any way
+ bModifySourceImage = (bHaveMaskColorSrc Or bHaveUnmaskColorSrc)
+
+ Case 24, 32
+ If (bHaveMaskColorSrc) Then
+
+ ' get mask color as Long
+ lciMaskColorSrc = vlciMaskColorSrc
+
+ If (eMaskColorSrcFormat And FICFF_COLOR_BGR) Then
+ lciMaskColorSrc = FreeImage_SwapColorLong(lciMaskColorSrc, (lBitDepthSrc = 24))
+ End If
+ End If
+
+ If (bHaveUnmaskColorSrc) Then
+
+ ' get unmask color as Long
+ lciUnmaskColorSrc = vlciUnmaskColorSrc
+
+ If (eUnmaskColorSrcFormat And FICFF_COLOR_BGR) Then
+ lciUnmaskColorSrc = FreeImage_SwapColorLong(lciUnmaskColorSrc, (lBitDepthSrc = 24))
+ End If
+ End If
+
+ End Select
+
+ End If
+
+
+ If ((bModifySourceImage) Or (bCreateMaskImage)) Then
+
+ ' get some information from eMaskOptions
+
+ ' check for inverse mask
+ bInvertMask = (eMaskOptions And FIMF_MASK_INVERSE_MASK)
+
+ ' check for mask colors
+ bMaskColors = (eMaskOptions And FIMF_MASK_COLOR_TRANSPARENCY)
+ bMaskColors = bMaskColors And (Not IsMissing(vntMaskColors))
+ If (bMaskColors) Then
+ ' validate specified mask colors; all mask colors are transferred to
+ ' an internal array of type Long
+ If (Not IsArray(vntMaskColors)) Then
+ ' color masking is only done when the single mask color is
+ ' a numeric (color) value
+ bMaskColors = IsNumeric(vntMaskColors)
+ If (bMaskColors) Then
+ ' this is not an array of mask colors but only a single
+ ' color; this is also transferred into an internal array
+ lMaskColorsMaxIndex = 0
+ ReDim alcMaskColors(lMaskColorsMaxIndex)
+ alcMaskColors(lMaskColorsMaxIndex) = vntMaskColors
+ End If
+ Else
+ ' transfer all valid color values (numeric) into an internal
+ ' array
+ ReDim alcMaskColors(UBound(vntMaskColors))
+ For i = LBound(vntMaskColors) To UBound(vntMaskColors)
+ bMaskColors = (IsNumeric(vntMaskColors(i)))
+ If (Not bMaskColors) Then
+ Exit For
+ Else
+ alcMaskColors(lMaskColorsMaxIndex) = vntMaskColors(i)
+ lMaskColorsMaxIndex = lMaskColorsMaxIndex + 1
+ End If
+ Next i
+ If (bMaskColors) Then
+ lMaskColorsMaxIndex = lMaskColorsMaxIndex - 1
+ End If
+ End If
+ End If
+
+ ' check for transparency options
+ If ((FreeImage_IsTransparent(hDIB)) Or _
+ ((eMaskOptions And FIMF_MASK_FORCE_TRANSPARENCY) > 0)) Then
+ bMaskFullTransparency = (eMaskOptions And FIMF_MASK_FULL_TRANSPARENCY)
+ bMaskAlphaTransparency = (eMaskOptions And FIMF_MASK_ALPHA_TRANSPARENCY)
+ bMaskTransparency = (bMaskFullTransparency Or bMaskAlphaTransparency)
+ End If
+
+ ' get image dimension
+ lWidth = FreeImage_GetWidth(hDIB)
+ lHeight = FreeImage_GetHeight(hDIB)
+
+ ' create proper accessors for the source image
+ Select Case lBitDepthSrc
+
+ Case 4, 8
+ ' images with a bit depth of 4 or 8 bits will both be
+ ' read through a byte array
+ abBitsBSrc = FreeImage_GetBitsEx(hDIB)
+ ' depending on where to get the transparency information from,
+ ' a palette or a transpareny table will be needed
+ If (bMaskColors) Then
+ alPaletteSrc = FreeImage_GetPaletteExLong(hDIB)
+ End If
+ If (bMaskTransparency) Then
+ abTransparencyTableSrc = FreeImage_GetTransparencyTableExClone(hDIB)
+ End If
+
+ ' for 4 bit source images
+ If (lBitDepthSrc = 4) Then
+ ' two additional arrays need to be filled with values
+ ' to mask and shift nibbles to bytes
+ ' index 0 stands for the high nibble of the byte
+ abBitMasks(0) = &HF0
+ abBitShifts(0) = &H10 ' a shift to right is implemented
+ ' as division in VB
+ ' index 1 stands for the low nibble of the byte
+ abBitMasks(1) = &HF
+ abBitShifts(1) = &H1 ' no shift needed for low nibble
+ End If
+
+ Case 24
+ ' images with a depth of 24 bits could not be used
+ ' through a two dimensional array in most cases, so get
+ ' an array of individual scanlines (see remarks concerning
+ ' pitch at function 'FreeImage_GetBitsExRGBTriple()')
+ Call FreeImage_GetScanLinesRGBTRIPLE(hDIB, atBitsTSrc)
+
+ Case 32
+ atBitsQSrc = FreeImage_GetBitsExRGBQUAD(hDIB)
+
+ End Select
+
+
+ ' create mask image if needed
+ If (bCreateMaskImage) Then
+
+ ' create mask image
+ hDIBResult = FreeImage_Allocate(lWidth, lHeight, lBitDepth)
+ ' if destination bit depth is 8 or below, a proper palette will
+ ' be needed, so create a palette where the unmask color is at
+ ' index 0 and the mask color is at index 1
+ If (lBitDepth <= 8) Then
+ atPaletteDst = FreeImage_GetPaletteEx(hDIBResult)
+ Call CopyMemory(atPaletteDst(0), lciUnmaskColorDst, 4)
+ Call CopyMemory(atPaletteDst(1), lciMaskColorDst, 4)
+ End If
+
+ ' create proper accessors for the new mask image
+ Select Case lBitDepth
+
+ Case 1
+ abBitsBDst = FreeImage_GetBitsEx(hDIBResult)
+ x = 1
+ For i = 7 To 0 Step -1
+ abBitValues(i) = x
+ x = x * 2
+ Next i
+
+ Case 4
+ abBitsBDst = FreeImage_GetBitsEx(hDIBResult)
+ abBitValues(0) = &H10
+ abBitValues(1) = &H1
+
+ Case 8
+ abBitsBDst = FreeImage_GetBitsEx(hDIBResult)
+
+ Case 24
+ ' images with a depth of 24 bits could not be used
+ ' through a two dimensional array in most cases, so get
+ ' an array of individual scanlines (see remarks concerning
+ ' pitch at function 'FreeImage_GetBitsExRGBTriple()')
+ Call FreeImage_GetScanLinesRGBTRIPLE(hDIBResult, atBitsTDst)
+
+ Case 32
+ atBitsQDst = FreeImage_GetBitsExRGBQUAD(hDIBResult)
+
+ End Select
+ End If
+
+ ' walk the hole image
+ For y = 0 To lHeight - 1
+ For x = 0 To lWidth - 1
+
+ ' should transparency information be considered to create
+ ' the mask?
+ If (bMaskTransparency) Then
+
+ Select Case lBitDepthSrc
+
+ Case 4
+ x2 = x \ 2
+ lPixelIndex = (abBitsBSrc(x2, y) And abBitMasks(x Mod 2)) \ abBitShifts(x Mod 2)
+ bMaskPixel = (abTransparencyTableSrc(lPixelIndex) = 0)
+ If (Not bMaskPixel) Then
+ bMaskPixel = ((abTransparencyTableSrc(lPixelIndex) < 255) And _
+ (bMaskAlphaTransparency))
+ End If
+
+ Case 8
+ bMaskPixel = (abTransparencyTableSrc(abBitsBSrc(x, y)) = 0)
+ If (Not bMaskPixel) Then
+ bMaskPixel = ((abTransparencyTableSrc(abBitsBSrc(x, y)) < 255) And _
+ (bMaskAlphaTransparency))
+ End If
+
+ Case 24
+ ' no transparency information in 24 bit images
+ ' reset bMaskPixel
+ bMaskPixel = False
+
+ Case 32
+ bMaskPixel = (atBitsQSrc(x, y).rgbReserved = 0)
+ If (Not bMaskPixel) Then
+ bMaskPixel = ((atBitsQSrc(x, y).rgbReserved < 255) And _
+ (bMaskAlphaTransparency))
+ End If
+
+ End Select
+ Else
+ ' clear 'bMaskPixel' if no transparency information was checked
+ ' since the flag might be still True from the last loop
+ bMaskPixel = False
+ End If
+
+ ' should color information be considered to create the mask?
+ ' do this only if the current pixel is not yet part of the mask
+ If ((bMaskColors) And (Not bMaskPixel)) Then
+
+ Select Case lBitDepthSrc
+
+ Case 4
+ x2 = x \ 2
+ lPixelIndex = (abBitsBSrc(x2, y) And abBitMasks(x Mod 2)) \ abBitShifts(x Mod 2)
+ If (eMaskColorsFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ For i = 0 To lMaskColorsMaxIndex
+ If (lColorTolerance = 0) Then
+ bMaskPixel = (lPixelIndex = alcMaskColors(i))
+ Else
+ bMaskPixel = (FreeImage_CompareColorsLongLong( _
+ alPaletteSrc(lPixelIndex), _
+ alPaletteSrc(alcMaskColors(i)), _
+ lColorTolerance, _
+ FICFF_COLOR_RGB, FICFF_COLOR_RGB) = 0)
+ End If
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+ Else
+ For i = 0 To lMaskColorsMaxIndex
+ bMaskPixel = (FreeImage_CompareColorsLongLong( _
+ alPaletteSrc(lPixelIndex), _
+ alcMaskColors(i), lColorTolerance, _
+ FICFF_COLOR_RGB, _
+ (eMaskColorsFormat And FICFF_COLOR_FORMAT_ORDER_MASK)) = 0)
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+ End If
+
+ Case 8
+ If (eMaskColorsFormat And FICFF_COLOR_PALETTE_INDEX) Then
+ For i = 0 To lMaskColorsMaxIndex
+ If (lColorTolerance = 0) Then
+ bMaskPixel = (abBitsBSrc(x, y) = alcMaskColors(i))
+ Else
+ bMaskPixel = (FreeImage_CompareColorsLongLong( _
+ alPaletteSrc(abBitsBSrc(x, y)), _
+ alPaletteSrc(alcMaskColors(i)), _
+ lColorTolerance, _
+ FICFF_COLOR_RGB, FICFF_COLOR_RGB) = 0)
+ End If
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+ Else
+ For i = 0 To lMaskColorsMaxIndex
+ bMaskPixel = (FreeImage_CompareColorsLongLong( _
+ alPaletteSrc(abBitsBSrc(x, y)), _
+ alcMaskColors(i), lColorTolerance, _
+ FICFF_COLOR_RGB, _
+ (eMaskColorsFormat And FICFF_COLOR_FORMAT_ORDER_MASK)) = 0)
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+ End If
+
+ Case 24
+ For i = 0 To lMaskColorsMaxIndex
+ bMaskPixel = (FreeImage_CompareColorsRGBTRIPLELong( _
+ atBitsTSrc.Scanline(y).Data(x), _
+ alcMaskColors(i), lColorTolerance, _
+ (eMaskColorsFormat And FICFF_COLOR_FORMAT_ORDER_MASK)) = 0)
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+
+ Case 32
+ For i = 0 To lMaskColorsMaxIndex
+ bMaskPixel = (FreeImage_CompareColorsRGBQUADLong( _
+ atBitsQSrc(x, y), _
+ alcMaskColors(i), lColorTolerance, _
+ (eMaskColorsFormat And FICFF_COLOR_FORMAT_ORDER_MASK)) = 0)
+ If (bMaskPixel) Then
+ Exit For
+ End If
+ Next i
+
+ End Select
+
+ End If
+
+ ' check whether a mask image needs to be created
+ If (bCreateMaskImage) Then
+
+ ' write current pixel to destination (mask) image
+ Select Case lBitDepth
+
+ Case 1
+ x2 = x \ 8
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ abBitsBDst(x2, y) = abBitsBDst(x2, y) Or abBitValues(x Mod 8)
+ End If
+
+ Case 4
+ x2 = x \ 2
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ abBitsBDst(x2, y) = abBitsBDst(x2, y) Or abBitValues(x Mod 2)
+ End If
+
+ Case 8
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ abBitsBDst(x, y) = 1
+ End If
+
+ Case 24
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ Call CopyMemory(atBitsTDst.Scanline(y).Data(x), lciMaskColorDst, 3)
+ Else
+ Call CopyMemory(atBitsTDst.Scanline(y).Data(x), lciUnmaskColorDst, 3)
+ End If
+
+ Case 32
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ Call CopyMemory(atBitsQDst(x, y), lciMaskColorDst, 4)
+ Else
+ Call CopyMemory(atBitsQDst(x, y), lciUnmaskColorDst, 4)
+ End If
+
+ End Select
+ End If
+
+ ' check whether a source image needs to be modified
+ If (bModifySourceImage) Then
+
+ Select Case lBitDepthSrc
+
+ Case 4
+ x2 = x \ 2
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ If (bHaveMaskColorSrc) Then
+ abBitsBSrc(x2, y) = _
+ (abBitsBSrc(x2, y) And (Not abBitMasks(x Mod 2))) Or _
+ (lciMaskColorSrc * abBitShifts(x Mod 2))
+ End If
+ ElseIf (bHaveUnmaskColorSrc) Then
+ abBitsBSrc(x2, y) = _
+ (abBitsBSrc(x2, y) And (Not abBitMasks(x Mod 2))) Or _
+ (lciUnmaskColorSrc * abBitShifts(x Mod 2))
+ End If
+
+ Case 8
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ If (bHaveMaskColorSrc) Then
+ abBitsBSrc(x, y) = lciMaskColorSrc
+ End If
+ ElseIf (bHaveUnmaskColorSrc) Then
+ abBitsBSrc(x, y) = lciUnmaskColorSrc
+ End If
+
+ Case 24
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ If (bHaveMaskColorSrc) Then
+ Call CopyMemory(atBitsTSrc.Scanline(y).Data(x), lciMaskColorSrc, 3)
+ End If
+ ElseIf (bHaveUnmaskColorSrc) Then
+ Call CopyMemory(atBitsTSrc.Scanline(y).Data(x), lciUnmaskColorSrc, 3)
+ End If
+
+ Case 32
+ If ((bMaskPixel) Xor (bInvertMask)) Then
+ If (bHaveMaskColorSrc) Then
+ Call CopyMemory(atBitsQSrc(x, y), lciMaskColorSrc, 4)
+ End If
+ ElseIf (bHaveUnmaskColorSrc) Then
+ Call CopyMemory(atBitsQSrc(x, y), lciUnmaskColorSrc, 4)
+ End If
+
+ End Select
+ End If
+
+ Next x
+ Next y
+ End If
+ End If
+ End If
+
+ FreeImage_CreateMask = hDIBResult
+
+End Function
+
+Public Function FreeImage_CreateMaskImage(ByVal hDIB As Long, _
+ Optional ByVal lBitDepth As Long = 1, _
+ Optional ByVal eMaskOptions As FREE_IMAGE_MASK_FLAGS = FIMF_MASK_FULL_TRANSPARENCY, _
+ Optional ByVal vntMaskColors As Variant, _
+ Optional ByVal eMaskColorsFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lColorTolerance As Long, _
+ Optional ByVal lciMaskColor As Long = vbWhite, _
+ Optional ByVal eMaskColorFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lciUnmaskColor As Long = vbBlack, _
+ Optional ByVal eUnmaskColorFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB) As Long
+
+ 'TODO: comment this function
+
+ FreeImage_CreateMaskImage = FreeImage_CreateMask(hDIB, MCOF_CREATE_MASK_IMAGE, _
+ lBitDepth, eMaskOptions, _
+ vntMaskColors, eMaskColorsFormat, _
+ lColorTolerance, _
+ lciMaskColor, eMaskColorFormat, _
+ lciUnmaskColor, eUnmaskColorFormat)
+
+End Function
+
+Public Function FreeImage_CreateSimpleBWMaskImage(ByVal hDIB As Long, _
+ Optional ByVal lBitDepth As Long = 1, _
+ Optional ByVal eMaskOptions As FREE_IMAGE_MASK_FLAGS = FIMF_MASK_FULL_TRANSPARENCY, _
+ Optional ByVal vntMaskColors As Variant, _
+ Optional ByVal eMaskColorsFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lColorTolerance As Long) As Long
+
+ 'TODO: comment this function
+
+ FreeImage_CreateSimpleBWMaskImage = FreeImage_CreateMask(hDIB, MCOF_CREATE_MASK_IMAGE, _
+ lBitDepth, eMaskOptions, _
+ vntMaskColors, eMaskColorsFormat, _
+ lColorTolerance, _
+ vbWhite, FICFF_COLOR_RGB, _
+ vbBlack, FICFF_COLOR_RGB)
+
+End Function
+
+Public Function FreeImage_CreateMaskInPlace(ByVal hDIB As Long, _
+ Optional ByVal lBitDepth As Long = 1, _
+ Optional ByVal eMaskOptions As FREE_IMAGE_MASK_FLAGS = FIMF_MASK_FULL_TRANSPARENCY, _
+ Optional ByVal vntMaskColors As Variant, _
+ Optional ByVal eMaskColorsFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lColorTolerance As Long, _
+ Optional ByVal vlciMaskColor As Variant, _
+ Optional ByVal eMaskColorFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal vlciUnmaskColor As Variant, _
+ Optional ByVal eUnmaskColorFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB) As Long
+
+ 'TODO: comment this function
+
+ FreeImage_CreateMaskInPlace = FreeImage_CreateMask(hDIB, MCOF_MODIFY_SOURCE_IMAGE, _
+ lBitDepth, eMaskOptions, _
+ vntMaskColors, eMaskColorsFormat, _
+ lColorTolerance, _
+ , , , , _
+ vlciMaskColor, eMaskColorFormat, _
+ vlciUnmaskColor, eUnmaskColorFormat)
+
+End Function
+
+Public Function FreeImage_CreateSimpleBWMaskInPlace(ByVal hDIB As Long, _
+ Optional ByVal lBitDepth As Long = 1, _
+ Optional ByVal eMaskOptions As FREE_IMAGE_MASK_FLAGS = FIMF_MASK_FULL_TRANSPARENCY, _
+ Optional ByVal vntMaskColors As Variant, _
+ Optional ByVal eMaskColorsFormat As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal lColorTolerance As Long) As Long
+
+ 'TODO: comment this function
+
+ FreeImage_CreateSimpleBWMaskInPlace = FreeImage_CreateMask(hDIB, MCOF_MODIFY_SOURCE_IMAGE, _
+ lBitDepth, eMaskOptions, _
+ vntMaskColors, eMaskColorsFormat, _
+ lColorTolerance, _
+ , , , , _
+ vbWhite, FICFF_COLOR_RGB, _
+ vbBlack, FICFF_COLOR_RGB)
+
+End Function
+
+Public Function FreeImage_CreateMaskColors(ParamArray MaskColors() As Variant) As Variant
+
+ ' this is just a FreeImage signed function that emulates VB's
+ ' builtin Array() function, that makes a variant array from
+ ' a ParamArray; so, a caller of the FreeImage_CreateMask() function
+ ' can specify all mask colors inline in the call statement
+
+ ' hDibMask = FreeImage_CreateMask(hDib, 1, FIMF_MASK_COLOR_TRANSPARENCY, _
+ ' FreeImage_CreateMaskColors(vbRed, vbGreen, vbBlack), _
+ ' FICFF_COLOR_BGR, .... )
+
+ ' keep in mind, that VB colors (vbRed, vbBlue, etc.) are OLE colors that have
+ ' BRG format
+
+ FreeImage_CreateMaskColors = MaskColors
+
+End Function
+
+Public Function FreeImage_SwapColorLong(ByVal lcColor As Long, _
+ Optional ByVal bExcludeAlpha As Boolean) As Long
+
+ ' This function swaps both color components Red (R) and Blue (B) in either
+ ' and RGB or BGR format color value stored in a Long value. This function is
+ ' used to convert from a RGB to a BGR color value and vice versa.
+
+ If (Not bExcludeAlpha) Then
+ FreeImage_SwapColorLong = ((lcColor And &HFF000000) Or _
+ ((lcColor And &HFF&) * &H10000) Or _
+ (lcColor And &HFF00&) Or _
+ ((lcColor And &HFF0000) \ &H10000))
+ Else
+ FreeImage_SwapColorLong = (((lcColor And &HFF&) * &H10000) Or _
+ (lcColor And &HFF00&) Or _
+ ((lcColor And &HFF0000) \ &H10000))
+ End If
+
+End Function
+
+Public Function FreeImage_CompareColorsLongLong(ByVal lcColorA As Long, _
+ ByVal lcColorB As Long, _
+ Optional ByVal lTolerance As Long = 0, _
+ Optional ByVal eColorTypeA As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_ARGB, _
+ Optional ByVal eColorTypeB As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_ARGB) As Long
+
+Dim bFormatEqual As Boolean
+Dim bAlphaEqual As Boolean
+
+ ' This function compares two colors that both are specified as a 32 bit Long
+ ' value.
+
+ ' Use both parameters 'eColorTypeA' and 'eColorTypeB' to specify each color's
+ ' format and 'lTolerance' to specify the matching tolerance.
+
+ ' The function returns the result of the mathematical substraction
+ ' lcColorA - lcColorB, so if both colors are equal, the function returns NULL (0)
+ ' and any other value if both colors are different. Alpha transparency is taken into
+ ' account only if both colors are said to have an alpha transparency component by
+ ' both parameters 'eColorTypeA' and 'eColorTypeB'. If at least one of both colors
+ ' has no alpha transparency component, the comparison only includes the bits for
+ ' the red, green and blue component.
+
+ ' The matching tolerance is applied to each color component (red, green, blue and
+ ' alpha) separately. So, when 'lTolerance' contains a value greater than zero, the
+ ' function returns NULL (0) when either both colors are exactly the same or the
+ ' differences of each corresponding color components are smaller or equal than
+ ' the given tolerance value.
+
+
+ If (((eColorTypeA And FICFF_COLOR_PALETTE_INDEX) Or _
+ (eColorTypeB And FICFF_COLOR_PALETTE_INDEX)) = 0) Then
+
+ bFormatEqual = ((eColorTypeA And FICFF_COLOR_FORMAT_ORDER_MASK) = _
+ (eColorTypeB And FICFF_COLOR_FORMAT_ORDER_MASK))
+
+ bAlphaEqual = ((eColorTypeA And FICFF_COLOR_HAS_ALPHA) And _
+ (eColorTypeB And FICFF_COLOR_HAS_ALPHA))
+
+ If (bFormatEqual) Then
+ If (bAlphaEqual) Then
+ FreeImage_CompareColorsLongLong = lcColorA - lcColorB
+ Else
+ FreeImage_CompareColorsLongLong = (lcColorA And &HFFFFFF) - (lcColorB And &HFFFFFF)
+ End If
+ Else
+ If (bAlphaEqual) Then
+ FreeImage_CompareColorsLongLong = lcColorA - ((lcColorB And &HFF000000) Or _
+ ((lcColorB And &HFF&) * &H10000) Or _
+ (lcColorB And &HFF00&) Or _
+ ((lcColorB And &HFF0000) \ &H10000))
+ Else
+ FreeImage_CompareColorsLongLong = (lcColorA And &HFFFFFF) - _
+ (((lcColorB And &HFF&) * &H10000) Or _
+ (lcColorB And &HFF00&) Or _
+ ((lcColorB And &HFF0000) \ &H10000))
+ End If
+ End If
+
+ If ((lTolerance > 0) And (FreeImage_CompareColorsLongLong <> 0)) Then
+ If (bFormatEqual) Then
+ If (Abs(((lcColorA \ &H10000) And &HFF) - ((lcColorB \ &H10000) And &HFF)) <= lTolerance) Then
+ If (Abs(((lcColorA \ &H100) And &HFF) - ((lcColorB \ &H100) And &HFF)) <= lTolerance) Then
+ If (Abs((lcColorA And &HFF) - (lcColorB And &HFF)) <= lTolerance) Then
+ If (bAlphaEqual) Then
+ If (Abs(((lcColorA \ &H1000000) And &HFF) - _
+ ((lcColorB \ &H1000000) And &HFF)) <= lTolerance) Then
+ FreeImage_CompareColorsLongLong = 0
+ End If
+ Else
+ FreeImage_CompareColorsLongLong = 0
+ End If
+ End If
+ End If
+ End If
+ Else
+ If (Abs(((lcColorA \ &H10000) And &HFF) - (lcColorB And &HFF)) <= lTolerance) Then
+ If (Abs(((lcColorA \ &H100) And &HFF) - ((lcColorB \ &H100) And &HFF)) <= lTolerance) Then
+ If (Abs((lcColorA And &HFF) - ((lcColorB \ &H10000) And &HFF)) <= lTolerance) Then
+ If (bAlphaEqual) Then
+ If (Abs(((lcColorA \ &H1000000) And &HFF) - _
+ ((lcColorB \ &H1000000) And &HFF)) <= lTolerance) Then
+ FreeImage_CompareColorsLongLong = 0
+ End If
+ Else
+ FreeImage_CompareColorsLongLong = 0
+ End If
+ End If
+ End If
+ End If
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_CompareColorsRGBTRIPLELong(ByRef tcColorA As RGBTRIPLE, _
+ ByVal lcColorB As Long, _
+ Optional ByVal lTolerance As Long = 0, _
+ Optional ByVal eColorTypeB As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB) As Long
+
+Dim lcColorA As Long
+
+ ' This is a function derived from 'FreeImage_CompareColorsLongLong()' to make color
+ ' comparisons between two colors whereby one color is provided as RGBTRIPLE and the
+ ' other color is provided as Long value.
+
+ ' Have a look at the documentation of 'FreeImage_CompareColorsLongLong()' to learn
+ ' more about color comparisons.
+
+ Call CopyMemory(lcColorA, tcColorA, 3)
+ FreeImage_CompareColorsRGBTRIPLELong = _
+ FreeImage_CompareColorsLongLong(lcColorA, lcColorB, _
+ lTolerance, FICFF_COLOR_RGB, eColorTypeB)
+
+End Function
+
+Public Function FreeImage_CompareColorsRGBQUADLong(ByRef tcColorA As RGBQUAD, _
+ ByVal lcColorB As Long, _
+ Optional ByVal lTolerance As Long = 0, _
+ Optional ByVal eColorTypeB As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_ARGB) As Long
+
+Dim lcColorA As Long
+
+ ' This is a function derived from 'FreeImage_CompareColorsLongLong()' to make color
+ ' comparisons between two colors whereby one color is provided as RGBQUAD and the
+ ' other color is provided as Long value.
+
+ ' Have a look at the documentation of 'FreeImage_CompareColorsLongLong()' to learn
+ ' more about color comparisons.
+
+ Call CopyMemory(lcColorA, tcColorA, 4)
+ FreeImage_CompareColorsRGBQUADLong = _
+ FreeImage_CompareColorsLongLong(lcColorA, lcColorB, _
+ lTolerance, FICFF_COLOR_ARGB, eColorTypeB)
+
+End Function
+
+Public Function FreeImage_SearchPalette(ByVal dib As Long, _
+ ByVal lcColor As Long, _
+ Optional ByVal lTolerance As Long = 0, _
+ Optional ByVal eColorType As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal eTransparencyState As FREE_IMAGE_TRANSPARENCY_STATE_FLAGS = FITSF_IGNORE_TRANSPARENCY) As Long
+
+Dim i As Long
+Dim alPalette() As Long
+Dim abTransparencyTable() As Byte
+
+ ' This function searches an image's color palette for a certain color specified as a
+ ' 32 bit Long value in either RGB or BGR format.
+
+ ' A search tolerance may be specified in the 'lTolerance' parameter.
+
+ ' Use the 'eTransparencyState' parameter to control, how the transparency state of
+ ' the found palette entry affects the result. These values may be used:
+
+ ' FITSF_IGNORE_TRANSPARENCY: Returns the index of the first palette entry which
+ ' matches the red, green and blue components.
+ '
+ ' FITSF_NONTRANSPARENT: Returns the index of the first palette entry which
+ ' matches the red, green and blue components and is
+ ' nontransparent (fully opaque).
+ '
+ ' FITSF_TRANSPARENT: Returns the index of the first palette entry which
+ ' matches the red, green and blue components and is
+ ' fully transparent.
+ '
+ ' FITSF_INCLUDE_ALPHA_TRANSPARENCY: Returns the index of the first palette entry which
+ ' matches the red, green and blue components as well
+ ' as the alpha transparency.
+
+ ' When alpha transparency should be included in the palette search ('FITSF_INCLUDE_ALPHA_TRANSPARENCY'),
+ ' the alpha transparency of the color searched is taken from the left most byte of 'lcColor'
+ ' (lcColor is either in format ARGB or ABGR). The the alpha transparency of the palette entry
+ ' actually comes from the image's transparency table rather than from the palette, since palettes
+ ' do not contain transparency information.
+
+ If (FreeImage_GetImageType(dib) = FIT_BITMAP) Then
+ Select Case FreeImage_GetColorType(dib)
+
+ Case FIC_PALETTE, FIC_MINISBLACK, FIC_MINISWHITE
+ FreeImage_SearchPalette = -1
+ alPalette = FreeImage_GetPaletteExLong(dib)
+ abTransparencyTable = FreeImage_GetTransparencyTableExClone(dib)
+ For i = 0 To UBound(alPalette)
+ If (FreeImage_CompareColorsLongLong(lcColor, alPalette(i), _
+ lTolerance, _
+ eColorType, FICFF_COLOR_RGB) = 0) Then
+ Select Case eTransparencyState
+
+ Case FITSF_IGNORE_TRANSPARENCY
+ FreeImage_SearchPalette = i
+ Exit For
+
+ Case FITSF_NONTRANSPARENT
+ If (abTransparencyTable(i) = 255) Then
+ FreeImage_SearchPalette = i
+ Exit For
+ End If
+
+ Case FITSF_TRANSPARENT
+ If (abTransparencyTable(i) = 0) Then
+ FreeImage_SearchPalette = i
+ Exit For
+ End If
+
+ Case FITSF_INCLUDE_ALPHA_TRANSPARENCY
+ If (abTransparencyTable(i) = ((lcColor And &HFF000000) \ 1000000)) Then
+ FreeImage_SearchPalette = i
+ Exit For
+ End If
+
+ End Select
+ End If
+ Next i
+
+ Case Else
+ FreeImage_SearchPalette = -1
+
+ End Select
+ Else
+ FreeImage_SearchPalette = -1
+ End If
+
+End Function
+
+Public Function FreeImage_GetIcon(ByVal hDIB As Long, _
+ Optional ByVal eTransparencyOptions As FREE_IMAGE_ICON_TRANSPARENCY_OPTION_FLAGS = ITOF_USE_DEFAULT_TRANSPARENCY, _
+ Optional ByVal lciTransparentColor As Long, _
+ Optional ByVal eTransparentColorType As FREE_IMAGE_COLOR_FORMAT_FLAGS = FICFF_COLOR_RGB, _
+ Optional ByVal hDC As Long, _
+ Optional ByVal bUnloadSource As Boolean) As Long
+
+Dim tIconInfo As ICONINFO
+Dim bReleaseDC As Boolean
+Dim bModifySourceImage As Boolean
+Dim eMaskFlags As FREE_IMAGE_MASK_FLAGS
+Dim lBitDepth As Long
+Dim bPixelIndex As Byte
+Dim hDIBSrc As Long
+Dim hDIBMask As Long
+Dim hBMPMask As Long
+Dim hBmp As Long
+
+ ' The optional 'bUnloadSource' parameter is for unloading the original image
+ ' after the OlePicture has been created, so you can easiely "switch" from a
+ ' FreeImage DIB to a VB Picture object. There is no need to clean up the DIB
+ ' at the caller's site.
+
+ If (hDIB) Then
+
+ lBitDepth = FreeImage_GetBPP(hDIB)
+
+ ' check whether the image supports transparency
+ Select Case lBitDepth
+
+ Case 4, 8
+ If (eTransparencyOptions And ITOF_USE_TRANSPARENCY_INFO) Then
+ If (FreeImage_IsTransparent(hDIB)) Then
+ eMaskFlags = FIMF_MASK_FULL_TRANSPARENCY
+ ElseIf (eTransparencyOptions And ITOF_FORCE_TRANSPARENCY_INFO) Then
+ If (FreeImage_IsTransparencyTableTransparent(hDIB)) Then
+ eMaskFlags = (FIMF_MASK_FULL_TRANSPARENCY And _
+ FIMF_MASK_FORCE_TRANSPARENCY)
+ End If
+ End If
+ End If
+ If ((eMaskFlags = FIMF_MASK_NONE) And _
+ (eTransparencyOptions And ITOF_USE_COLOR_TRANSPARENCY)) Then
+
+ eMaskFlags = FIMF_MASK_COLOR_TRANSPARENCY
+
+ Select Case (eTransparencyOptions And ITOF_USE_COLOR_BITMASK)
+
+ Case ITOF_USE_COLOR_TOP_LEFT_PIXEL
+ Call FreeImage_GetPixelIndex(hDIB, _
+ 0, FreeImage_GetHeight(hDIB) - 1, _
+ bPixelIndex)
+ lciTransparentColor = bPixelIndex
+ eTransparentColorType = FICFF_COLOR_PALETTE_INDEX
+
+ Case ITOF_USE_COLOR_TOP_RIGHT_PIXEL
+ Call FreeImage_GetPixelIndex(hDIB, _
+ FreeImage_GetWidth(hDIB) - 1, FreeImage_GetHeight(hDIB) - 1, _
+ bPixelIndex)
+ lciTransparentColor = bPixelIndex
+ eTransparentColorType = FICFF_COLOR_PALETTE_INDEX
+
+ Case ITOF_USE_COLOR_BOTTOM_LEFT_PIXEL
+ Call FreeImage_GetPixelIndex(hDIB, _
+ 0, 0, _
+ bPixelIndex)
+ lciTransparentColor = bPixelIndex
+ eTransparentColorType = FICFF_COLOR_PALETTE_INDEX
+
+ Case ITOF_USE_COLOR_BOTTOM_RIGHT_PIXEL
+ Call FreeImage_GetPixelIndex(hDIB, _
+ FreeImage_GetWidth(hDIB) - 1, 0, _
+ bPixelIndex)
+ lciTransparentColor = bPixelIndex
+ eTransparentColorType = FICFF_COLOR_PALETTE_INDEX
+
+ End Select
+ End If
+
+ bModifySourceImage = True
+
+ Case 24, 32
+ If ((lBitDepth = 32) And _
+ (eTransparencyOptions And ITOF_USE_TRANSPARENCY_INFO)) Then
+ If (FreeImage_IsTransparent(hDIB)) Then
+ eMaskFlags = FIMF_MASK_FULL_TRANSPARENCY
+ End If
+ End If
+ If ((eMaskFlags = FIMF_MASK_NONE) And _
+ (eTransparencyOptions And ITOF_USE_COLOR_TRANSPARENCY)) Then
+
+ eMaskFlags = FIMF_MASK_COLOR_TRANSPARENCY
+
+ Select Case (eTransparencyOptions And ITOF_USE_COLOR_BITMASK)
+
+ Case ITOF_USE_COLOR_TOP_LEFT_PIXEL
+ Call FreeImage_GetPixelColorByLong(hDIB, _
+ FreeImage_GetHeight(hDIB) - 1, 0, _
+ lciTransparentColor)
+ eTransparentColorType = FICFF_COLOR_RGB
+
+ Case ITOF_USE_COLOR_TOP_RIGHT_PIXEL
+ Call FreeImage_GetPixelColorByLong(hDIB, _
+ FreeImage_GetHeight(hDIB) - 1, FreeImage_GetWidth(hDIB) - 1, _
+ lciTransparentColor)
+ eTransparentColorType = FICFF_COLOR_RGB
+
+ Case ITOF_USE_COLOR_BOTTOM_LEFT_PIXEL
+ Call FreeImage_GetPixelColorByLong(hDIB, _
+ 0, 0, _
+ lciTransparentColor)
+ eTransparentColorType = FICFF_COLOR_RGB
+
+ Case ITOF_USE_COLOR_BOTTOM_RIGHT_PIXEL
+ Call FreeImage_GetPixelColorByLong(hDIB, _
+ 0, FreeImage_GetWidth(hDIB) - 1, _
+ lciTransparentColor)
+ eTransparentColorType = FICFF_COLOR_RGB
+
+ End Select
+ End If
+
+ bModifySourceImage = (lBitDepth = 24)
+
+ End Select
+
+
+ If (bModifySourceImage) Then
+ hDIBSrc = FreeImage_Clone(hDIB)
+ hDIBMask = FreeImage_CreateMask(hDIBSrc, MCOF_CREATE_AND_MODIFY, _
+ 1, eMaskFlags, _
+ lciTransparentColor, eTransparentColorType, _
+ , , , , , _
+ FreeImage_SearchPalette(hDIBSrc, 0, , , _
+ FITSF_NONTRANSPARENT), _
+ FICFF_COLOR_PALETTE_INDEX)
+ Else
+ hDIBSrc = hDIB
+ hDIBMask = FreeImage_CreateMaskImage(hDIB, 1, FIMF_MASK_FULL_TRANSPARENCY)
+ End If
+
+ If (hDC = 0) Then
+ hDC = GetDC(0)
+ bReleaseDC = True
+ End If
+
+ hBmp = CreateDIBitmap(hDC, _
+ FreeImage_GetInfoHeader(hDIBSrc), _
+ CBM_INIT, _
+ FreeImage_GetBits(hDIBSrc), _
+ FreeImage_GetInfo(hDIBSrc), _
+ DIB_RGB_COLORS)
+
+
+ hBMPMask = CreateDIBitmap(hDC, _
+ FreeImage_GetInfoHeader(hDIBMask), _
+ CBM_INIT, _
+ FreeImage_GetBits(hDIBMask), _
+ FreeImage_GetInfo(hDIBMask), _
+ DIB_RGB_COLORS)
+
+ If (bModifySourceImage) Then
+ Call FreeImage_Unload(hDIBSrc)
+ End If
+
+ If (bUnloadSource) Then
+ Call FreeImage_Unload(hDIB)
+ End If
+
+
+ If ((hBmp <> 0) And (hBMPMask <> 0)) Then
+
+ With tIconInfo
+ .fIcon = True
+ .hBmMask = hBMPMask
+ .hbmColor = hBmp
+ End With
+
+ FreeImage_GetIcon = CreateIconIndirect(tIconInfo)
+ End If
+
+ If (bReleaseDC) Then
+ Call ReleaseDC(0, hDC)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustPictureBox(ByRef pbox As Object, _
+ Optional ByVal adjust_mode As FREE_IMAGE_ADJUST_MODE = AM_DEFAULT, _
+ Optional ByVal Filter As FREE_IMAGE_FILTER = FILTER_BICUBIC) As IPicture
+
+Dim tR As RECT
+Dim hDIB As Long
+Dim hDIBTemp As Long
+Dim lNewWidth As Long
+Dim lNewHeight As Long
+
+Const vbObjectOrWithBlockVariableNotSet As Long = 91
+
+ ' This function adjusts an already loaded picture in a VB PictureBox
+ ' control in size. This is done by converting the picture to a dib
+ ' by FreeImage_CreateFromOlePicture. After resizing the dib it is
+ ' converted back to a Ole Picture object and re-assigned to the
+ ' PictureBox control.
+
+ ' The pbox paramater is actually of type Object so any object or control
+ ' providing Picture, hWnd, Width and Height properties can be used instead
+ ' of a PictureBox control
+
+ ' This may be useful when using compile time provided images in VB like
+ ' logos or backgrounds that need to be resized during runtime. Using
+ ' FreeImage's sophisticated rescaling methods is a much better aproach
+ ' than using VB's stretchable Image control.
+
+ ' One reason for resizing a usually fixed size logo or background image
+ ' may be the following scenario:
+
+ ' When running on a Windos machine using smaller or bigger fonts (what can
+ ' be configured in the control panel by using different dpi fonts), the
+ ' operation system automatically adjusts the sizes of Forms, Labels,
+ ' TextBoxes, Frames and even PictureBoxes. So, the hole VB application is
+ ' perfectly adapted to these font metrics with the exception of compile time
+ ' provided images. Although the PictureBox control is resized, the containing
+ ' image remains untouched. This problem could be solved with this function.
+
+ ' This function is also wrapped by the function 'AdjustPicture', giving you
+ ' a more VB common function name.
+
+
+ If (Not pbox Is Nothing) Then
+ Call GetClientRect(pbox.hWnd, tR)
+ If ((tR.Right <> pbox.Picture.Width) Or _
+ (tR.Bottom <> pbox.Picture.Height)) Then
+ hDIB = FreeImage_CreateFromOlePicture(pbox.Picture)
+ If (hDIB) Then
+ If (adjust_mode = AM_ADJUST_OPTIMAL_SIZE) Then
+ If (pbox.Picture.Width >= pbox.Picture.Height) Then
+ adjust_mode = AM_ADJUST_WIDTH
+ Else
+ adjust_mode = AM_ADJUST_HEIGHT
+ End If
+ End If
+
+ Select Case adjust_mode
+
+ Case AM_STRECH
+ lNewWidth = tR.Right
+ lNewHeight = tR.Bottom
+
+ Case AM_ADJUST_WIDTH
+ lNewWidth = tR.Right
+ lNewHeight = lNewWidth / (pbox.Picture.Width / pbox.Picture.Height)
+
+ Case AM_ADJUST_HEIGHT
+ lNewHeight = tR.Bottom
+ lNewWidth = lNewHeight * (pbox.Picture.Width / pbox.Picture.Height)
+
+ End Select
+
+ hDIBTemp = hDIB
+ hDIB = FreeImage_Rescale(hDIB, lNewWidth, lNewHeight, Filter)
+ Call FreeImage_Unload(hDIBTemp)
+ Set pbox.Picture = FreeImage_GetOlePicture(hDIB, , True)
+ Set FreeImage_AdjustPictureBox = pbox.Picture
+ End If
+ End If
+ Else
+ Call Err.Raise(vbObjectOrWithBlockVariableNotSet)
+ End If
+
+End Function
+
+Public Function AdjustPicture(ByRef Control As Object, _
+ Optional ByRef Mode As FREE_IMAGE_ADJUST_MODE = AM_DEFAULT, _
+ Optional ByRef Filter As FREE_IMAGE_FILTER = FILTER_BICUBIC) As IPicture
+
+ ' This function is a more VB friendly signed wrapper for
+ ' the FreeImage_AdjustPictureBox function.
+
+ Set AdjustPicture = FreeImage_AdjustPictureBox(Control, Mode, Filter)
+
+End Function
+
+Public Function FreeImage_LoadEx(ByVal Filename As String, _
+ Optional ByVal Options As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT, _
+ Optional ByVal Width As Variant, _
+ Optional ByVal Height As Variant, _
+ Optional ByVal InPercent As Boolean = False, _
+ Optional ByVal Filter As FREE_IMAGE_FILTER, _
+ Optional ByRef Format As FREE_IMAGE_FORMAT = FIF_UNKNOWN) As Long
+
+Const vbInvalidPictureError As Long = 481
+
+ ' The function provides all image formats, the FreeImage library can read. The
+ ' image format is determined from the image file to load, the optional parameter
+ ' 'Format' is an OUT parameter that will contain the image format that has
+ ' been loaded.
+
+ ' The parameters 'Width', 'Height', 'InPercent' and 'Filter' make it possible
+ ' to "load" the image in a resized version. 'Width', 'Height' specify the desired
+ ' width and height, 'Filter' determines, what image filter should be used
+ ' on the resizing process.
+
+ ' The parameters 'Width', 'Height', 'InPercent' and 'Filter' map directly to the
+ ' according parameters of the 'FreeImage_RescaleEx' function. So, read the
+ ' documentation of the 'FreeImage_RescaleEx' for a complete understanding of the
+ ' usage of these parameters.
+
+
+ Format = FreeImage_GetFIFFromFilename(Filename)
+ If (Format <> FIF_UNKNOWN) Then
+ If (FreeImage_FIFSupportsReading(Format)) Then
+ FreeImage_LoadEx = FreeImage_Load(Format, Filename, Options)
+ If (FreeImage_LoadEx) Then
+
+ If ((Not IsMissing(Width)) Or _
+ (Not IsMissing(Height))) Then
+ FreeImage_LoadEx = FreeImage_RescaleEx(FreeImage_LoadEx, Width, Height, InPercent, True, Filter)
+ End If
+ Else
+ Call Err.Raise(vbInvalidPictureError)
+ End If
+ Else
+ Call Err.Raise(vbInvalidPictureError)
+ End If
+ Else
+ Call Err.Raise(vbInvalidPictureError)
+ End If
+
+End Function
+
+Public Function LoadPictureEx(Optional ByRef Filename As Variant, _
+ Optional ByRef Options As FREE_IMAGE_LOAD_OPTIONS = FILO_LOAD_DEFAULT, _
+ Optional ByRef Width As Variant, _
+ Optional ByRef Height As Variant, _
+ Optional ByRef InPercent As Boolean = False, _
+ Optional ByRef Filter As FREE_IMAGE_FILTER, _
+ Optional ByRef Format As FREE_IMAGE_FORMAT = FIF_UNKNOWN) As IPicture
+
+Dim hDIB As Long
+
+ ' This function is an extended version of the VB method 'LoadPicture'. As
+ ' the VB version it takes a filename parameter to load the image and throws
+ ' the same errors in most cases.
+
+ ' This function now is only a thin wrapper for the FreeImage_LoadEx() wrapper
+ ' function (as compared to releases of this wrapper prior to version 1.8). So,
+ ' have a look at this function's discussion of the parameters.
+
+
+ If (Not IsMissing(Filename)) Then
+ hDIB = FreeImage_LoadEx(Filename, Options, Width, Height, InPercent, Filter, Format)
+ Set LoadPictureEx = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_SaveEx(ByVal dib As Long, _
+ ByVal Filename As String, _
+ Optional ByVal Format As FREE_IMAGE_FORMAT = FIF_UNKNOWN, _
+ Optional ByVal Options As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT, _
+ Optional ByVal ColorDepth As FREE_IMAGE_COLOR_DEPTH = FICD_AUTO, _
+ Optional ByVal Width As Variant, _
+ Optional ByVal Height As Variant, _
+ Optional ByVal InPercent As Boolean = False, _
+ Optional ByVal Filter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bUnloadSource As Boolean) As Boolean
+
+Dim hDIBRescale As Long
+Dim bConvertedOnRescale As Boolean
+Dim bIsNewDIB As Boolean
+Dim lBPP As Long
+Dim lBPPOrg As Long
+Dim strExtension As String
+
+ ' This function is an easy to use replacement for FreeImage's FreeImage_Save()
+ ' function which supports inline size- and color conversions as well as an
+ ' auto image format detection algorithm that determines the desired image format
+ ' by the given filename. An even more sophisticated algorithm may auto-detect
+ ' the proper color depth for a explicitly given or auto-detected image format.
+
+ ' The function provides all image formats, and save options, the FreeImage
+ ' library can write. The optional parameter 'Format' may contain the desired
+ ' image format. When omitted, the function tries to get the image format from
+ ' the filename extension.
+
+ ' The optional parameter 'ColorDepth' may contain the desired color depth for
+ ' the saved image. This can be either any value of the FREE_IMAGE_COLOR_DEPTH
+ ' enumeration or the value FICD_AUTO what is the default value of the parameter.
+ ' When 'ColorDepth' is FICD_AUTO, the function tries to get the most suitable
+ ' color depth for the specified image format if the image's current color depth
+ ' is not supported by the specified image format. Therefore, the function
+ ' firstly reduces the color depth step by step until a proper color depth is
+ ' found since an incremention would only increase the file's size with no
+ ' quality benefit. Only when there is no lower color depth is found for the
+ ' image format, the function starts to increase the color depth.
+
+ ' Keep in mind that an explicitly specified color depth that is not supported
+ ' by the image format results in a runtime error. For example, when saving
+ ' a 24 bit image as GIF image, a runtime error occurs.
+
+ ' The function checks, whether the given filename has a valid extension or
+ ' not. If not, the "primary" extension for the used image format will be
+ ' appended to the filename. The parameter 'Filename' remains untouched in
+ ' this case.
+
+ ' To learn more about the "primary" extension, read the documentation for
+ ' the 'FreeImage_GetPrimaryExtensionFromFIF' function.
+
+ ' The parameters 'Width', 'Height', 'InPercent' and 'Filter' make it possible
+ ' to save the image in a resized version. 'Width', 'Height' specify the desired
+ ' width and height, 'Filter' determines, what image filter should be used
+ ' on the resizing process. Since FreeImage_SaveEx relies on FreeImage_RescaleEx,
+ ' please refer to the documentation of FreeImage_RescaleEx to learn more
+ ' about these four parameters.
+
+ ' The optional 'bUnloadSource' parameter is for unloading the saved image, so
+ ' you can save and unload an image with this function in one operation.
+ ' CAUTION: at current, the image is unloaded, even if the image was not
+ ' saved correctly!
+
+
+ If (dib) Then
+
+ If ((Not IsMissing(Width)) Or _
+ (Not IsMissing(Height))) Then
+
+ lBPP = FreeImage_GetBPP(dib)
+ hDIBRescale = FreeImage_RescaleEx(dib, Width, Height, InPercent, bUnloadSource, Filter)
+ bIsNewDIB = (hDIBRescale <> dib)
+ dib = hDIBRescale
+ bConvertedOnRescale = (lBPP <> FreeImage_GetBPP(dib))
+ End If
+
+ If (Format = FIF_UNKNOWN) Then
+ Format = FreeImage_GetFIFFromFilename(Filename)
+ End If
+ If (Format <> FIF_UNKNOWN) Then
+ If ((FreeImage_FIFSupportsWriting(Format)) And _
+ (FreeImage_FIFSupportsExportType(Format, FIT_BITMAP))) Then
+
+ If (Not FreeImage_IsFilenameValidForFIF(Format, Filename)) Then
+ strExtension = "." & FreeImage_GetPrimaryExtensionFromFIF(Format)
+ End If
+
+ ' check color depth
+ If (ColorDepth <> FICD_AUTO) Then
+ ' mask out bit 1 (0x02) for the case ColorDepth is FICD_MONOCHROME_DITHER (0x03)
+ ' FREE_IMAGE_COLOR_DEPTH values are true bit depths in general expect FICD_MONOCHROME_DITHER
+ ' by masking out bit 1, 'FreeImage_FIFSupportsExportBPP()' tests for bitdepth 1
+ ' what is correct again for dithered images.
+ ColorDepth = (ColorDepth And (Not &H2))
+ If (Not FreeImage_FIFSupportsExportBPP(Format, ColorDepth)) Then
+ Call Err.Raise(5, _
+ "MFreeImage", _
+ Error$(5) & vbCrLf & vbCrLf & _
+ "FreeImage Library plugin '" & _
+ FreeImage_GetFormatFromFIF(Format) & "' " & _
+ "is unable to write images with a color depth " & _
+ "of " & ColorDepth & " bpp.")
+
+ ElseIf (FreeImage_GetBPP(dib) <> ColorDepth) Then
+ dib = FreeImage_ConvertColorDepth(dib, ColorDepth, (bUnloadSource Or bIsNewDIB))
+ bIsNewDIB = True
+
+ End If
+ Else
+
+ If (lBPP = 0) Then
+ lBPP = FreeImage_GetBPP(dib)
+ End If
+
+ If (Not FreeImage_FIFSupportsExportBPP(Format, lBPP)) Then
+ lBPPOrg = lBPP
+ Do
+ lBPP = pGetPreviousColorDepth(lBPP)
+ Loop While ((Not FreeImage_FIFSupportsExportBPP(Format, lBPP)) Or _
+ (lBPP = 0))
+ If (lBPP = 0) Then
+ lBPP = lBPPOrg
+ Do
+ lBPP = pGetNextColorDepth(lBPP)
+ Loop While ((Not FreeImage_FIFSupportsExportBPP(Format, lBPP)) Or _
+ (lBPP = 0))
+ End If
+
+ If (lBPP <> 0) Then
+ dib = FreeImage_ConvertColorDepth(dib, lBPP, (bUnloadSource Or bIsNewDIB))
+ bIsNewDIB = True
+ End If
+
+ ElseIf (bConvertedOnRescale) Then
+ ' restore original color depth
+ ' always unload current DIB here, since 'bIsNewDIB' is True
+ dib = FreeImage_ConvertColorDepth(dib, lBPP, True)
+
+ End If
+ End If
+
+ FreeImage_SaveEx = FreeImage_Save(Format, dib, Filename & strExtension, Options)
+ If ((bIsNewDIB) Or (bUnloadSource)) Then
+ Call FreeImage_Unload(dib)
+ End If
+ Else
+ Call Err.Raise(5, _
+ "MFreeImage", _
+ Error$(5) & vbCrLf & vbCrLf & _
+ "FreeImage Library plugin '" & _
+ FreeImage_GetFormatFromFIF(Format) & "' " & _
+ "is unable to write images of the image format requested.")
+ End If
+ Else
+ ' unknown image format error
+ Call Err.Raise(5, _
+ "MFreeImage", _
+ Error$(5) & vbCrLf & vbCrLf & _
+ "Unknown image format. Neither an explicit image format " & _
+ "was specified nor any known image format was parsed " & _
+ "from the filename given.")
+ End If
+ End If
+
+End Function
+
+Public Function SavePictureEx(ByRef Picture As IPicture, _
+ ByRef Filename As String, _
+ Optional ByRef Format As FREE_IMAGE_FORMAT = FIF_UNKNOWN, _
+ Optional ByRef Options As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT, _
+ Optional ByRef ColorDepth As FREE_IMAGE_COLOR_DEPTH = FICD_AUTO, _
+ Optional ByRef Width As Variant, _
+ Optional ByRef Height As Variant, _
+ Optional ByRef InPercent As Boolean = False, _
+ Optional ByRef Filter As FREE_IMAGE_FILTER = FILTER_BICUBIC) As Boolean
+
+Dim hDIB As Long
+
+Const vbObjectOrWithBlockVariableNotSet As Long = 91
+Const vbInvalidPictureError As Long = 481
+
+ ' This function is an extended version of the VB method 'SavePicture'. As
+ ' the VB version it takes a Picture object and a filename parameter to
+ ' save the image and throws the same errors in most cases.
+
+ ' This function now is only a thin wrapper for the FreeImage_SaveEx() wrapper
+ ' function (as compared to releases of this wrapper prior to version 1.8). So,
+ ' have a look at this function's discussion of the parameters.
+
+
+ If (Not Picture Is Nothing) Then
+ hDIB = FreeImage_CreateFromOlePicture(Picture)
+ If (hDIB) Then
+ SavePictureEx = FreeImage_SaveEx(hDIB, Filename, Format, Options, _
+ ColorDepth, Width, Height, InPercent, _
+ FILTER_BICUBIC, True)
+ Else
+ Call Err.Raise(vbInvalidPictureError)
+ End If
+ Else
+ Call Err.Raise(vbObjectOrWithBlockVariableNotSet)
+ End If
+
+End Function
+
+Public Function SaveImageContainerEx(ByRef Container As Object, _
+ ByRef Filename As String, _
+ Optional ByVal IncludeDrawings As Boolean, _
+ Optional ByRef Format As FREE_IMAGE_FORMAT = FIF_UNKNOWN, _
+ Optional ByRef Options As FREE_IMAGE_SAVE_OPTIONS = FISO_SAVE_DEFAULT, _
+ Optional ByRef ColorDepth As FREE_IMAGE_COLOR_DEPTH = FICD_AUTO, _
+ Optional ByRef Width As Variant, _
+ Optional ByRef Height As Variant, _
+ Optional ByRef InPercent As Boolean = False, _
+ Optional ByRef Filter As FREE_IMAGE_FILTER = FILTER_BICUBIC) As Long
+
+ ' This function is an extended version of the VB method 'SavePicture'. As
+ ' the VB version it takes an image hosting control and a filename parameter to
+ ' save the image and throws the same errors in most cases.
+
+ ' This function merges the functionality of both wrapper functions
+ ' 'SavePictureEx()' and 'FreeImage_CreateFromImageContainer()'. Basically this
+ ' function is identical to 'SavePictureEx' expect that is does not take a
+ ' IOlePicture (IPicture) object but a VB image hosting container control.
+
+ ' Please, refer to each of this two function's inline documentation for a
+ ' more detailed description.
+
+ Call SavePictureEx(pGetIOlePictureFromContainer(Container, IncludeDrawings), _
+ Filename, _
+ Format, _
+ Options, _
+ ColorDepth, _
+ Width, _
+ Height, _
+ InPercent, _
+ Filter)
+
+End Function
+
+
+'--------------------------------------------------------------------------------
+' OlePicture aware toolkit, rescale and conversion functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_RescaleIOP(ByRef IOlePicture As IPicture, _
+ Optional ByVal vntDstWidth As Variant, _
+ Optional ByVal vntDstHeight As Variant, _
+ Optional ByVal bIsPercentValue As Boolean, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for wrapper function FreeImage_RescaleEx()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ hDIB = FreeImage_RescaleEx(hDIB, vntDstWidth, vntDstHeight, _
+ bIsPercentValue, True, eFilter, bForceCloneCreation)
+ Set FreeImage_RescaleIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_RescaleByPixelIOP(ByRef IOlePicture As IPicture, _
+ Optional ByVal lDstWidthPixel As Long, _
+ Optional ByVal lDstHeightPixel As Long, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As IPicture
+
+ ' Thin wrapper for function 'FreeImage_RescaleExIOP' for removing method
+ ' overload fake. This function rescales the image directly to the size
+ ' specified by the 'lDstWidthPixel' and 'lDstHeightPixel' parameters.
+
+ Set FreeImage_RescaleByPixelIOP = FreeImage_RescaleIOP(IOlePicture, _
+ lDstWidthPixel, _
+ lDstHeightPixel, _
+ False, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+Public Function FreeImage_RescaleByPercentIOP(ByRef IOlePicture As IPicture, _
+ Optional ByVal dblDstWidthPercent As Double, _
+ Optional ByVal dblDstHeightPercent As Double, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As IPicture
+
+ ' Thin wrapper for function 'FreeImage_RescaleExIOP' for removing method
+ ' overload fake. This function rescales the image by a percent value
+ ' based on the image's original size.
+
+ Set FreeImage_RescaleByPercentIOP = FreeImage_RescaleIOP(IOlePicture, _
+ dblDstWidthPercent, _
+ dblDstHeightPercent, _
+ True, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+Public Function FreeImage_RescaleByFactorIOP(ByRef IOlePicture As IPicture, _
+ Optional ByVal dblDstWidthFactor As Double, _
+ Optional ByVal dblDstHeightFactor As Double, _
+ Optional ByVal eFilter As FREE_IMAGE_FILTER = FILTER_BICUBIC, _
+ Optional ByVal bForceCloneCreation As Boolean) As IPicture
+
+ ' Thin wrapper for function 'FreeImage_RescaleExIOP' for removing method
+ ' overload fake. This function rescales the image by a factor
+ ' based on the image's original size.
+
+ Set FreeImage_RescaleByFactorIOP = FreeImage_RescaleIOP(IOlePicture, _
+ dblDstWidthFactor, _
+ dblDstHeightFactor, _
+ False, _
+ eFilter, _
+ bForceCloneCreation)
+
+End Function
+
+Public Function FreeImage_MakeThumbnailIOP(ByRef IOlePicture As IPicture, _
+ ByVal max_pixel_size As Long) As IPicture
+
+Dim hDIB As Long
+Dim hDIBThumbnail As Long
+
+ ' IOlePicture based wrapper for wrapper function FreeImage_MakeThumbnail()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ hDIBThumbnail = FreeImage_MakeThumbnail(hDIB, max_pixel_size)
+ If (hDIBThumbnail) Then
+ Set FreeImage_MakeThumbnailIOP = FreeImage_GetOlePicture(hDIBThumbnail, , True)
+ End If
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+Public Function FreeImage_ConvertColorDepthIOP(ByRef IOlePicture As IPicture, _
+ ByVal eConversionFlag As FREE_IMAGE_CONVERSION_FLAGS, _
+ Optional ByVal bThreshold As Byte = 128, _
+ Optional ByVal eDitherMethod As FREE_IMAGE_DITHER = FID_FS, _
+ Optional ByVal eQuantizationMethod As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for wrapper function FreeImage_ConvertColorDepth()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ hDIB = FreeImage_ConvertColorDepth(hDIB, eConversionFlag, True, _
+ bThreshold, eDitherMethod, eQuantizationMethod)
+ Set FreeImage_ConvertColorDepthIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_ColorQuantizeExIOP(ByRef IOlePicture As IPicture, _
+ Optional ByVal quantize As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT, _
+ Optional ByVal PaletteSize As Long = 256, _
+ Optional ByVal ReserveSize As Long = 0, _
+ Optional ByRef ReservePalette As Variant = Null) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for wrapper function FreeImage_ColorQuantizeEx()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ hDIB = FreeImage_ColorQuantizeEx(hDIB, quantize, True, _
+ PaletteSize, ReserveSize, ReservePalette)
+ Set FreeImage_ColorQuantizeExIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_RotateClassicIOP(ByRef IOlePicture As IPicture, _
+ ByVal angle As Double) As IPicture
+
+Dim hDIB As Long
+Dim hDIBNew As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_RotateClassic()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 1, 8, 24, 32
+ hDIBNew = FreeImage_RotateClassic(hDIB, angle)
+ Set FreeImage_RotateClassicIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+
+ End Select
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+Public Function FreeImage_RotateIOP(ByRef IOlePicture As IPicture, _
+ ByVal angle As Double, _
+ Optional ByVal ColorPtr As Long) As IPicture
+
+Dim hDIB As Long
+Dim hDIBNew As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_Rotate()
+
+ ' The optional ColorPtr parameter takes a pointer to (e.g. the address of) an
+ ' RGB color value. So, all these assignments are valid for ColorPtr:
+ '
+ ' Dim tColor As RGBQUAD
+ '
+ ' VarPtr(tColor)
+ ' VarPtr(&H33FF80)
+ ' VarPtr(vbWhite) ' However, the VB color constants are in BGR format!
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 1, 8, 24, 32
+ hDIBNew = FreeImage_Rotate(hDIB, angle, ByVal ColorPtr)
+ Set FreeImage_RotateIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+
+ End Select
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+Public Function FreeImage_RotateExIOP(ByRef IOlePicture As IPicture, _
+ ByVal angle As Double, _
+ ByVal x_shift As Double, _
+ ByVal y_shift As Double, _
+ ByVal x_origin As Double, _
+ ByVal y_origin As Double, _
+ ByVal use_mask As Long) As IPicture
+
+Dim hDIB As Long
+Dim hDIBNew As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_RotateEx()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 8, 24, 32
+ hDIBNew = FreeImage_RotateEx(hDIB, angle, x_shift, y_shift, _
+ x_origin, y_origin, use_mask)
+ Set FreeImage_RotateExIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+
+ End Select
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+Public Function FreeImage_FlipHorizontalIOP(ByRef IOlePicture As IPicture) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_FlipHorizontal()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Call FreeImage_FlipHorizontalInt(hDIB)
+ Set FreeImage_FlipHorizontalIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_FlipVerticalIOP(ByRef IOlePicture As IPicture) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_FlipVertical()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Call FreeImage_FlipVerticalInt(hDIB)
+ Set FreeImage_FlipVerticalIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustCurveIOP(ByRef IOlePicture As IPicture, _
+ ByRef LUT As Variant, _
+ Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_AdjustCurve()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 8, 24, 32
+ Call FreeImage_AdjustCurveEx(hDIB, LUT, channel)
+ Set FreeImage_AdjustCurveIOP = FreeImage_GetOlePicture(hDIB, , True)
+
+ End Select
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustGammaIOP(ByRef IOlePicture As IPicture, _
+ ByVal gamma As Double) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_AdjustGamma()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 8, 24, 32
+ Call FreeImage_AdjustGammaInt(hDIB, gamma)
+ Set FreeImage_AdjustGammaIOP = FreeImage_GetOlePicture(hDIB, , True)
+
+ End Select
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustBrightnessIOP(ByRef IOlePicture As IPicture, _
+ ByVal percentage As Double) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_AdjustBrightness()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 8, 24, 32
+ Call FreeImage_AdjustBrightnessInt(hDIB, percentage)
+ Set FreeImage_AdjustBrightnessIOP = FreeImage_GetOlePicture(hDIB, , True)
+
+ End Select
+ End If
+
+End Function
+
+Public Function FreeImage_AdjustContrastIOP(ByRef IOlePicture As IPicture, _
+ ByVal percentage As Double) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_AdjustContrast()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 8, 24, 32
+ Call FreeImage_AdjustContrastInt(hDIB, percentage)
+ Set FreeImage_AdjustContrastIOP = FreeImage_GetOlePicture(hDIB, , True)
+
+ End Select
+ End If
+
+End Function
+
+Public Function FreeImage_InvertIOP(ByRef IOlePicture As IPicture) As IPicture
+
+Dim hDIB As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_Invert()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Call FreeImage_InvertInt(hDIB)
+ Set FreeImage_InvertIOP = FreeImage_GetOlePicture(hDIB, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_GetChannelIOP(ByRef IOlePicture As IPicture, _
+ ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As IPicture
+
+Dim hDIB As Long
+Dim hDIBNew As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_GetChannel()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ Select Case FreeImage_GetBPP(hDIB)
+
+ Case 24, 32
+ hDIBNew = FreeImage_GetChannel(hDIB, channel)
+ Set FreeImage_GetChannelIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+
+ End Select
+ Call FreeImage_Unload(hDIB)
+ End If
+
+End Function
+
+' Placeholder for FreeImage_SetChannelIOP() function
+
+'''Public Function FreeImage_SetChannelIOP(ByRef IOlePicture As IPicture, _
+''' ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As IPicture
+'''
+'''Dim hDIB As Long
+'''Dim hDIBNew As Long
+'''
+''' hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+''' If (hDIB) Then
+''' Select Case FreeImage_GetBPP(hDIB)
+'''
+''' Case 24, 32
+''' hDIBNew = FreeImage_GetChannel(hDIB, channel)
+''' Set FreeImage_GetChannelIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+'''
+''' End Select
+''' Call FreeImage_Unload(hDIB)
+''' End If
+'''
+'''End Function
+
+Public Function FreeImage_CopyIOP(ByRef IOlePicture As IPicture, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Right As Long, _
+ ByVal Bottom As Long) As IPicture
+
+Dim hDIB As Long
+Dim hDIBNew As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_Copy()
+
+ hDIB = FreeImage_CreateFromOlePicture(IOlePicture)
+ If (hDIB) Then
+ hDIBNew = FreeImage_Copy(hDIB, Left, Top, Right, Bottom)
+ Call FreeImage_Unload(hDIB)
+ Set FreeImage_CopyIOP = FreeImage_GetOlePicture(hDIBNew, , True)
+ End If
+
+End Function
+
+Public Function FreeImage_PasteIOP(ByRef IOlePictureDst As IPicture, _
+ ByRef IOlePictureSrc As IPicture, _
+ ByVal Left As Long, _
+ ByVal Top As Long, _
+ ByVal Alpha As Long, _
+ Optional ByVal keep_original_dst_image As Boolean = False) As IPicture
+
+Dim hDIBDst As Long
+Dim hDIBSrc As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_Paste()
+
+ hDIBDst = FreeImage_CreateFromOlePicture(IOlePictureDst)
+ If (hDIBDst) Then
+ hDIBSrc = FreeImage_CreateFromOlePicture(IOlePictureSrc)
+ If (hDIBSrc) Then
+ If FreeImage_Paste(hDIBDst, hDIBSrc, Left, Top, Alpha) Then
+ Set FreeImage_PasteIOP = FreeImage_GetOlePicture(hDIBDst, , True)
+ If (Not keep_original_dst_image) Then
+ Set IOlePictureDst = FreeImage_PasteIOP
+ End If
+ End If
+ Call FreeImage_Unload(hDIBSrc)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_CompositeIOP(ByRef IOlePictureFG As IPicture, _
+ Optional ByVal useFileBkg As Boolean = False, _
+ Optional ByVal appBkColor As OLE_COLOR = 0, _
+ Optional ByRef IOlePictureBG As IPicture) As IPicture
+
+Dim hDIBfg As Long
+Dim hDIBbg As Long
+Dim hDIBResult As Long
+
+ ' IOlePicture based wrapper for FreeImage function FreeImage_Composite()
+
+ hDIBfg = FreeImage_CreateFromOlePicture(IOlePictureFG)
+ If (hDIBfg) Then
+
+ hDIBbg = FreeImage_CreateFromOlePicture(IOlePictureBG)
+ If (appBkColor) Then
+ appBkColor = VarPtr(appBkColor)
+ End If
+
+ hDIBResult = FreeImage_Composite(hDIBfg, useFileBkg, appBkColor, hDIBbg)
+ If (hDIBResult) Then
+ Set FreeImage_CompositeIOP = FreeImage_GetOlePicture(hDIBResult, , True)
+ End If
+
+ Call FreeImage_Unload(hDIBfg)
+ If (hDIBbg) Then
+ Call FreeImage_Unload(hDIBbg)
+ End If
+ End If
+
+End Function
+
+
+'--------------------------------------------------------------------------------
+' VB-coded Toolkit functions
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_GetColorizedPalette(ByVal Color As OLE_COLOR, _
+ Optional ByVal SplitValue As Variant = 0.5) As RGBQUAD()
+
+Dim atPalette(255) As RGBQUAD
+Dim lSplitIndex As Long
+Dim lSplitIndexInv As Long
+Dim lRed As Long
+Dim lGreen As Long
+Dim lBlue As Long
+Dim i As Long
+
+ ' compute the split index
+ Select Case VarType(SplitValue)
+
+ Case vbByte, vbInteger, vbLong
+ lSplitIndex = SplitValue
+
+ Case vbDouble, vbSingle, vbDecimal
+ lSplitIndex = 256 * SplitValue
+
+ Case Else
+ lSplitIndex = 128
+
+ End Select
+
+ ' check ranges of split index
+ If (lSplitIndex < 0) Then
+ lSplitIndex = 0
+ ElseIf (lSplitIndex > 255) Then
+ lSplitIndex = 255
+ End If
+ lSplitIndexInv = 256 - lSplitIndex
+
+ ' extract color components red, green and blue
+ lRed = (Color And &HFF)
+ lGreen = ((Color \ &H100&) And &HFF)
+ lBlue = ((Color \ &H10000) And &HFF)
+
+ For i = 0 To lSplitIndex - 1
+ With atPalette(i)
+ .rgbRed = (lRed / lSplitIndex) * i
+ .rgbGreen = (lGreen / lSplitIndex) * i
+ .rgbBlue = (lBlue / lSplitIndex) * i
+ End With
+ Next i
+ For i = lSplitIndex To 255
+ With atPalette(i)
+ .rgbRed = lRed + ((255 - lRed) / lSplitIndexInv) * (i - lSplitIndex)
+ .rgbGreen = lGreen + ((255 - lGreen) / lSplitIndexInv) * (i - lSplitIndex)
+ .rgbBlue = lBlue + ((255 - lBlue) / lSplitIndexInv) * (i - lSplitIndex)
+ End With
+ Next i
+
+ FreeImage_GetColorizedPalette = atPalette
+
+End Function
+
+Public Function FreeImage_Colorize(ByVal dib As Long, _
+ ByVal Color As OLE_COLOR, _
+ Optional ByVal SplitValue As Variant = 0.5) As Long
+
+ FreeImage_Colorize = FreeImage_ConvertToGreyscale(dib)
+ Call FreeImage_SetPalette(FreeImage_Colorize, FreeImage_GetColorizedPalette(Color, SplitValue))
+
+End Function
+
+Public Function FreeImage_Sepia(ByVal dib As Long, _
+ Optional ByVal SplitValue As Variant = 0.5) As Long
+
+ FreeImage_Sepia = FreeImage_Colorize(dib, &H658AA2, SplitValue) ' RGB(162, 138, 101)
+
+End Function
+
+
+'--------------------------------------------------------------------------------
+' Compression functions wrappers
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_ZLibCompressEx(ByRef Target As Variant, _
+ Optional ByRef target_size As Long, _
+ Optional ByRef Source As Variant, _
+ Optional ByVal source_size As Long, _
+ Optional ByVal Offset As Long = 0) As Long
+
+Dim lSourceDataPtr As Long
+Dim lTargetDataPtr As Long
+Dim bTargetCreated As Boolean
+
+ ' This function is a more VB friendly wrapper for compressing data with
+ ' the 'FreeImage_ZLibCompress' function.
+
+ ' The parameter 'target' may either be a VB style array of Byte, Integer
+ ' or Long or a pointer to a memory block. If 'target' is a pointer to a
+ ' memory block (when it contains an address), 'target_size' must be
+ ' specified and greater than zero. If 'target' is an initialized array,
+ ' the whole array will be used to store compressed data when 'target_size'
+ ' is missing or below or equal to zero. If 'target_size' is specified, only
+ ' the first target_size bytes of the array will be used.
+ ' In each case, all rules according to the FreeImage API documentation
+ ' apply, what means that the target buffer must be at least 0.1% greater
+ ' than the source buffer plus 12 bytes.
+ ' If 'target' is an uninitialized array, the contents of 'target_size'
+ ' will be ignored and the size of the array 'target' will be handled
+ ' internally. When the function returns, 'target' will be initialized
+ ' as an array of Byte and sized correctly to hold all the compressed
+ ' data.
+
+ ' Nearly all, that is true for the parameters 'target' and 'target_size',
+ ' is also true for 'Source' and 'source_size', expect that 'Source' should
+ ' never be an uninitialized array. In that case, the function returns
+ ' immediately.
+
+ ' The optional parameter 'offset' may contain a number of bytes to remain
+ ' untouched at the beginning of 'target', when an uninitialized array is
+ ' provided through 'target'. When 'target' is either a pointer or an
+ ' initialized array, 'offset' will be ignored. This parameter is currently
+ ' used by 'FreeImage_ZLibCompressVB' to store the length of the uncompressed
+ ' data at the first four bytes of 'target'.
+
+
+ ' get the pointer and the size in bytes of the source
+ ' memory block
+ lSourceDataPtr = pGetMemoryBlockPtrFromVariant(Source, source_size)
+ If (lSourceDataPtr) Then
+ ' when we got a valid pointer, get the pointer and the size in bytes
+ ' of the target memory block
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ If (lTargetDataPtr = 0) Then
+ ' if 'target' is a null pointer, we will initialized it as an array
+ ' of bytes; here we will take 'offset' into account
+ ReDim Target(source_size + Int(source_size * 0.1) + _
+ 12 + Offset) As Byte
+ ' get pointer and size in bytes (will never be a null pointer)
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ ' adjust according to 'offset'
+ lTargetDataPtr = lTargetDataPtr + Offset
+ target_size = target_size - Offset
+ bTargetCreated = True
+ End If
+
+ ' compress source data
+ FreeImage_ZLibCompressEx = FreeImage_ZLibCompress(lTargetDataPtr, _
+ target_size, _
+ lSourceDataPtr, _
+ source_size)
+
+ ' the function returns the number of bytes needed to store the
+ ' compressed data or zero on failure
+ If (FreeImage_ZLibCompressEx) Then
+ If (bTargetCreated) Then
+ ' when we created the array, we need to adjust it's size
+ ' according to the length of the compressed data
+ ReDim Preserve Target(FreeImage_ZLibCompressEx - 1 + Offset)
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibUncompressEx(ByRef Target As Variant, _
+ Optional ByRef target_size As Long, _
+ Optional ByRef Source As Variant, _
+ Optional ByVal source_size As Long) As Long
+
+Dim lSourceDataPtr As Long
+Dim lTargetDataPtr As Long
+
+ ' This function is a more VB friendly wrapper for compressing data with
+ ' the 'FreeImage_ZLibUncompress' function.
+
+ ' The parameter 'target' may either be a VB style array of Byte, Integer
+ ' or Long or a pointer to a memory block. If 'target' is a pointer to a
+ ' memory block (when it contains an address), 'target_size' must be
+ ' specified and greater than zero. If 'target' is an initialized array,
+ ' the whole array will be used to store uncompressed data when 'target_size'
+ ' is missing or below or equal to zero. If 'target_size' is specified, only
+ ' the first target_size bytes of the array will be used.
+ ' In each case, all rules according to the FreeImage API documentation
+ ' apply, what means that the target buffer must be at least as large, to
+ ' hold all the uncompressed data.
+ ' Unlike the function 'FreeImage_ZLibCompressEx', 'target' can not be
+ ' an uninitialized array, since the size of the uncompressed data can
+ ' not be determined by the ZLib functions, but must be specified by a
+ ' mechanism outside the FreeImage compression functions' scope.
+
+ ' Nearly all, that is true for the parameters 'target' and 'target_size',
+ ' is also true for 'Source' and 'source_size'.
+
+
+ ' get the pointer and the size in bytes of the source
+ ' memory block
+ lSourceDataPtr = pGetMemoryBlockPtrFromVariant(Source, source_size)
+ If (lSourceDataPtr) Then
+ ' when we got a valid pointer, get the pointer and the size in bytes
+ ' of the target memory block
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ If (lTargetDataPtr) Then
+ ' if we do not have a null pointer, uncompress the data
+ FreeImage_ZLibUncompressEx = FreeImage_ZLibUncompress(lTargetDataPtr, _
+ target_size, _
+ lSourceDataPtr, _
+ source_size)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibGZipEx(ByRef Target As Variant, _
+ Optional ByRef target_size As Long, _
+ Optional ByRef Source As Variant, _
+ Optional ByVal source_size As Long, _
+ Optional ByVal Offset As Long = 0) As Long
+
+Dim lSourceDataPtr As Long
+Dim lTargetDataPtr As Long
+Dim bTargetCreated As Boolean
+
+ ' This function is a more VB friendly wrapper for compressing data with
+ ' the 'FreeImage_ZLibGZip' function.
+
+ ' The parameter 'target' may either be a VB style array of Byte, Integer
+ ' or Long or a pointer to a memory block. If 'target' is a pointer to a
+ ' memory block (when it contains an address), 'target_size' must be
+ ' specified and greater than zero. If 'target' is an initialized array,
+ ' the whole array will be used to store compressed data when 'target_size'
+ ' is missing or below or equal to zero. If 'target_size' is specified, only
+ ' the first target_size bytes of the array will be used.
+ ' In each case, all rules according to the FreeImage API documentation
+ ' apply, what means that the target buffer must be at least 0.1% greater
+ ' than the source buffer plus 24 bytes.
+ ' If 'target' is an uninitialized array, the contents of 'target_size'
+ ' will be ignored and the size of the array 'target' will be handled
+ ' internally. When the function returns, 'target' will be initialized
+ ' as an array of Byte and sized correctly to hold all the compressed
+ ' data.
+
+ ' Nearly all, that is true for the parameters 'target' and 'target_size',
+ ' is also true for 'Source' and 'source_size', expect that 'Source' should
+ ' never be an uninitialized array. In that case, the function returns
+ ' immediately.
+
+ ' The optional parameter 'offset' may contain a number of bytes to remain
+ ' untouched at the beginning of 'target', when an uninitialized array is
+ ' provided through 'target'. When 'target' is either a pointer or an
+ ' initialized array, 'offset' will be ignored. This parameter is currently
+ ' used by 'FreeImage_ZLibGZipVB' to store the length of the uncompressed
+ ' data at the first four bytes of 'target'.
+
+
+ ' get the pointer and the size in bytes of the source
+ ' memory block
+ lSourceDataPtr = pGetMemoryBlockPtrFromVariant(Source, source_size)
+ If (lSourceDataPtr) Then
+ ' when we got a valid pointer, get the pointer and the size in bytes
+ ' of the target memory block
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ If (lTargetDataPtr = 0) Then
+ ' if 'target' is a null pointer, we will initialized it as an array
+ ' of bytes; here we will take 'offset' into account
+ ReDim Target(source_size + Int(source_size * 0.1) + _
+ 24 + Offset) As Byte
+ ' get pointer and size in bytes (will never be a null pointer)
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ ' adjust according to 'offset'
+ lTargetDataPtr = lTargetDataPtr + Offset
+ target_size = target_size - Offset
+ bTargetCreated = True
+ End If
+
+ ' compress source data
+ FreeImage_ZLibGZipEx = FreeImage_ZLibGZip(lTargetDataPtr, _
+ target_size, _
+ lSourceDataPtr, _
+ source_size)
+
+ ' the function returns the number of bytes needed to store the
+ ' compressed data or zero on failure
+ If (FreeImage_ZLibGZipEx) Then
+ If (bTargetCreated) Then
+ ' when we created the array, we need to adjust it's size
+ ' according to the length of the compressed data
+ ReDim Preserve Target(FreeImage_ZLibGZipEx - 1 + Offset)
+ End If
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibCRC32Ex(ByVal crc As Long, _
+ Optional ByRef Source As Variant, _
+ Optional ByVal source_size As Long) As Long
+
+Dim lSourceDataPtr As Long
+
+ ' This function is a more VB friendly wrapper for compressing data with
+ ' the 'FreeImage_ZLibCRC32' function.
+
+ ' The parameter 'Source' may either be a VB style array of Byte, Integer
+ ' or Long or a pointer to a memory block. If 'Source' is a pointer to a
+ ' memory block (when it contains an address), 'source_size' must be
+ ' specified and greater than zero. If 'Source' is an initialized array,
+ ' the whole array will be used to calculate the new CRC when 'source_size'
+ ' is missing or below or equal to zero. If 'source_size' is specified, only
+ ' the first source_size bytes of the array will be used.
+
+
+ ' get the pointer and the size in bytes of the source
+ ' memory block
+ lSourceDataPtr = pGetMemoryBlockPtrFromVariant(Source, source_size)
+ If (lSourceDataPtr) Then
+ ' if we do not have a null pointer, calculate the CRC including 'crc'
+ FreeImage_ZLibCRC32Ex = FreeImage_ZLibCRC32(crc, _
+ lSourceDataPtr, _
+ source_size)
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibGUnzipEx(ByRef Target As Variant, _
+ Optional ByRef target_size As Long, _
+ Optional ByRef Source As Variant, _
+ Optional ByVal source_size As Long) As Long
+
+Dim lSourceDataPtr As Long
+Dim lTargetDataPtr As Long
+
+ ' This function is a more VB friendly wrapper for compressing data with
+ ' the 'FreeImage_ZLibGUnzip' function.
+
+ ' The parameter 'target' may either be a VB style array of Byte, Integer
+ ' or Long or a pointer to a memory block. If 'target' is a pointer to a
+ ' memory block (when it contains an address), 'target_size' must be
+ ' specified and greater than zero. If 'target' is an initialized array,
+ ' the whole array will be used to store uncompressed data when 'target_size'
+ ' is missing or below or equal to zero. If 'target_size' is specified, only
+ ' the first target_size bytes of the array will be used.
+ ' In each case, all rules according to the FreeImage API documentation
+ ' apply, what means that the target buffer must be at least as large, to
+ ' hold all the uncompressed data.
+ ' Unlike the function 'FreeImage_ZLibGZipEx', 'target' can not be
+ ' an uninitialized array, since the size of the uncompressed data can
+ ' not be determined by the ZLib functions, but must be specified by a
+ ' mechanism outside the FreeImage compression functions' scope.
+
+ ' Nearly all, that is true for the parameters 'target' and 'target_size',
+ ' is also true for 'Source' and 'source_size'.
+
+
+ ' get the pointer and the size in bytes of the source
+ ' memory block
+ lSourceDataPtr = pGetMemoryBlockPtrFromVariant(Source, source_size)
+ If (lSourceDataPtr) Then
+ ' when we got a valid pointer, get the pointer and the size in bytes
+ ' of the target memory block
+ lTargetDataPtr = pGetMemoryBlockPtrFromVariant(Target, target_size)
+ If (lTargetDataPtr) Then
+ ' if we do not have a null pointer, uncompress the data
+ FreeImage_ZLibGUnzipEx = FreeImage_ZLibGUnzip(lTargetDataPtr, _
+ target_size, _
+ lSourceDataPtr, _
+ source_size)
+ End If
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibCompressVB(ByRef Data() As Byte, _
+ Optional ByVal IncludeSize As Boolean = True) As Byte()
+
+Dim lOffset As Long
+Dim lArrayDataPtr As Long
+
+ ' This function is another, even more VB friendly wrapper for the FreeImage
+ ' 'FreeImage_ZLibCompress' function, that uses the 'FreeImage_ZLibCompressEx'
+ ' function. This function is very easy to use, since it deals only with VB
+ ' style Byte arrays.
+
+ ' The parameter 'data()' is a Byte array, providing the uncompressed source
+ ' data that will be compressed.
+
+ ' The optional parameter 'IncludeSize' determines whether the size of the
+ ' uncompressed data should be stored in the first four bytes of the returned
+ ' byte buffer containing the compressed data or not. When 'IncludeSize' is
+ ' True, the size of the uncompressed source data will be stored. This works
+ ' in conjunction with the corresponding 'FreeImage_ZLibUncompressVB' function.
+
+ ' The function returns a VB style Byte array containing the compressed data.
+
+
+ ' start population the memory block with compressed data
+ ' at offset 4 bytes, when the unclompressed size should
+ ' be included
+ If (IncludeSize) Then
+ lOffset = 4
+ End If
+
+ Call FreeImage_ZLibCompressEx(FreeImage_ZLibCompressVB, , Data, , lOffset)
+
+ If (IncludeSize) Then
+ ' get the pointer actual pointing to the array data of
+ ' the Byte array 'FreeImage_ZLibCompressVB'
+ lArrayDataPtr = deref(deref(VarPtrArray(FreeImage_ZLibCompressVB)) + 12)
+
+ ' copy uncompressed size into the first 4 bytes
+ Call CopyMemory(ByVal lArrayDataPtr, UBound(Data) + 1, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibUncompressVB(ByRef Data() As Byte, _
+ Optional ByVal SizeIncluded As Boolean = True, _
+ Optional ByVal SizeNeeded As Long) As Byte()
+
+Dim abBuffer() As Byte
+
+ ' This function is another, even more VB friendly wrapper for the FreeImage
+ ' 'FreeImage_ZLibUncompress' function, that uses the 'FreeImage_ZLibUncompressEx'
+ ' function. This function is very easy to use, since it deals only with VB
+ ' style Byte arrays.
+
+ ' The parameter 'data()' is a Byte array, providing the compressed source
+ ' data that will be uncompressed either withthe size of the uncompressed
+ ' data included or not.
+
+ ' When the optional parameter 'SizeIncluded' is True, the function assumes,
+ ' that the first four bytes contain the size of the uncompressed data as a
+ ' Long value. In that case, 'SizeNeeded' will be ignored.
+
+ ' When the size of the uncompressed data is not included in the buffer 'data()'
+ ' containing the compressed data, the optional parameter 'SizeNeeded' must
+ ' specify the size in bytes needed to hold all the uncompressed data.
+
+ ' The function returns a VB style Byte array containing the uncompressed data.
+
+
+ If (SizeIncluded) Then
+ ' get uncompressed size from the first 4 bytes and allocate
+ ' buffer accordingly
+ Call CopyMemory(SizeNeeded, Data(0), 4)
+ ReDim abBuffer(SizeNeeded - 1)
+ Call FreeImage_ZLibUncompressEx(abBuffer, , VarPtr(Data(4)), UBound(Data) - 3)
+ Call swap(VarPtrArray(FreeImage_ZLibUncompressVB), VarPtrArray(abBuffer))
+
+ ElseIf (SizeNeeded) Then
+ ' no size included in compressed data, so just forward the
+ ' call to 'FreeImage_ZLibUncompressEx' and trust on SizeNeeded
+ ReDim abBuffer(SizeNeeded - 1)
+ Call FreeImage_ZLibUncompressEx(abBuffer, , Data)
+ Call swap(VarPtrArray(FreeImage_ZLibUncompressVB), VarPtrArray(abBuffer))
+
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibGZipVB(ByRef Data() As Byte, _
+ Optional ByVal IncludeSize As Boolean = True) As Byte()
+
+Dim lOffset As Long
+Dim lArrayDataPtr As Long
+
+ ' This function is another, even more VB friendly wrapper for the FreeImage
+ ' 'FreeImage_ZLibGZip' function, that uses the 'FreeImage_ZLibGZipEx'
+ ' function. This function is very easy to use, since it deals only with VB
+ ' style Byte arrays.
+
+ ' The parameter 'data()' is a Byte array, providing the uncompressed source
+ ' data that will be compressed.
+
+ ' The optional parameter 'IncludeSize' determines whether the size of the
+ ' uncompressed data should be stored in the first four bytes of the returned
+ ' byte buffer containing the compressed data or not. When 'IncludeSize' is
+ ' True, the size of the uncompressed source data will be stored. This works
+ ' in conjunction with the corresponding 'FreeImage_ZLibGUnzipVB' function.
+
+ ' The function returns a VB style Byte array containing the compressed data.
+
+
+ ' start population the memory block with compressed data
+ ' at offset 4 bytes, when the unclompressed size should
+ ' be included
+ If (IncludeSize) Then
+ lOffset = 4
+ End If
+
+ Call FreeImage_ZLibGZipEx(FreeImage_ZLibGZipVB, , Data, , lOffset)
+
+ If (IncludeSize) Then
+ ' get the pointer actual pointing to the array data of
+ ' the Byte array 'FreeImage_ZLibCompressVB'
+ lArrayDataPtr = deref(deref(VarPtrArray(FreeImage_ZLibGZipVB)) + 12)
+
+ ' copy uncompressed size into the first 4 bytes
+ Call CopyMemory(ByVal lArrayDataPtr, UBound(Data) + 1, 4)
+ End If
+
+End Function
+
+Public Function FreeImage_ZLibGUnzipVB(ByRef Data() As Byte, _
+ Optional ByVal SizeIncluded As Boolean = True, _
+ Optional ByVal SizeNeeded As Long) As Byte()
+
+Dim abBuffer() As Byte
+
+ ' This function is another, even more VB friendly wrapper for the FreeImage
+ ' 'FreeImage_ZLibGUnzip' function, that uses the 'FreeImage_ZLibGUnzipEx'
+ ' function. This function is very easy to use, since it deals only with VB
+ ' style Byte arrays.
+
+ ' The parameter 'data()' is a Byte array, providing the compressed source
+ ' data that will be uncompressed either withthe size of the uncompressed
+ ' data included or not.
+
+ ' When the optional parameter 'SizeIncluded' is True, the function assumes,
+ ' that the first four bytes contain the size of the uncompressed data as a
+ ' Long value. In that case, 'SizeNeeded' will be ignored.
+
+ ' When the size of the uncompressed data is not included in the buffer 'data()'
+ ' containing the compressed data, the optional parameter 'SizeNeeded' must
+ ' specify the size in bytes needed to hold all the uncompressed data.
+
+ ' The function returns a VB style Byte array containing the uncompressed data.
+
+
+ If (SizeIncluded) Then
+ ' get uncompressed size from the first 4 bytes and allocate
+ ' buffer accordingly
+ Call CopyMemory(SizeNeeded, Data(0), 4)
+ ReDim abBuffer(SizeNeeded - 1)
+ Call FreeImage_ZLibGUnzipEx(abBuffer, , VarPtr(Data(4)), UBound(Data) - 3)
+ Call swap(VarPtrArray(FreeImage_ZLibGUnzipVB), VarPtrArray(abBuffer))
+
+ ElseIf (SizeNeeded) Then
+ ' no size included in compressed data, so just forward the
+ ' call to 'FreeImage_ZLibUncompressEx' and trust on SizeNeeded
+ ReDim abBuffer(SizeNeeded - 1)
+ Call FreeImage_ZLibGUnzipEx(abBuffer, , Data)
+ Call swap(VarPtrArray(FreeImage_ZLibGUnzipVB), VarPtrArray(abBuffer))
+
+ End If
+
+End Function
+
+
+'--------------------------------------------------------------------------------
+' Public functions to destroy custom safearrays
+'--------------------------------------------------------------------------------
+
+Public Function FreeImage_DestroyLockedArray(ByRef Data As Variant) As Long
+
+Dim lpArrayPtr As Long
+
+ ' This function destroys an array, that was self created with a custom
+ ' array descriptor of type ('fFeatures' member) 'FADF_AUTO Or FADF_FIXEDSIZE'.
+ ' Such arrays are returned by mostly all of the array-dealing wrapper
+ ' functions. Since these should not destroy the actual array data, when
+ ' going out of scope, they are craeted as 'FADF_FIXEDSIZE'.'
+
+ ' So, VB sees them as fixed or temporarily locked, when you try to manipulate
+ ' the array's dimensions. There will occur some strange effects, you should
+ ' know about:
+
+ ' 1. When trying to 'ReDim' the array, this run-time error will occur:
+ ' Error #10, 'This array is fixed or temporarily locked'
+
+ ' 2. When trying to assign another array to the array variable, this
+ ' run-time error will occur:
+ ' Error #13, 'Type mismatch'
+
+ ' 3. The 'Erase' statement has no effect on the array
+
+ ' Although VB clears up these arrays correctly, when the array variable
+ ' goes out of scope, you have to destroy the array manually, when you want
+ ' to reuse the array variable in current scope.
+
+ ' For an example assume, that you want do walk all scanlines in an image:
+
+ ' For i = 0 To FreeImage_GetHeight(dib)
+ '
+ ' ' assign scanline-array to array variable
+ ' abByte = FreeImage_GetScanLineEx(dib, i)
+ '
+ ' ' do some work on it...
+ '
+ ' ' destroy the array (only the array, not the actual data)
+ ' Call FreeImage_DestroyLockedArray(dbByte)
+ ' Next i
+
+ ' The function returns zero on success and any other value on failure
+
+ ' !! Attention !!
+ ' This function uses a Variant parameter for passing the array to be
+ ' destroyed. Since VB does not allow to pass an array of non public
+ ' structures through a Variant parameter, this function can not be used
+ ' with arrays of cutom type.
+
+ ' You will get this compiler error: "Only public user defined types defined
+ ' in public object modules can be used as parameters or return types for
+ ' public procedures of class modules or as fields of public user defined types"
+
+ ' So, there is a function in the wrapper called 'FreeImage_DestroyLockedArrayByPtr'
+ ' that takes a pointer to the array variable which can be used to work around
+ ' that VB limitation and furthermore can be used for any of these self-created
+ ' arrays. To get the array variable's pointer, a declared version of the
+ ' VB 'VarPtr' function can be used which works for all types of arrays expect
+ ' String arrays. Declare this function like this in your code:
+
+ ' Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" ( _
+ ByRef Ptr() As Any) As Long
+
+ ' Then an array could be destroyed by calling the 'FreeImage_DestroyLockedArrayByPtr'
+ ' function like this:
+
+ ' lResult = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(MyLockedArray))
+
+ ' Additionally there are some handy wrapper functions available, one for each
+ ' commonly used structure in FreeImage like RGBTRIPLE, RGBQUAD, FICOMPLEX etc.
+
+
+ ' Currently, these functions do return 'FADF_AUTO Or FADF_FIXEDSIZE' arrays
+ ' that must be destroyed using this or any of it's derived functions:
+
+ ' FreeImage_GetPaletteEx() with FreeImage_DestroyLockedArrayRGBQUAD()
+ ' FreeImage_GetPaletteLong() with FreeImage_DestroyLockedArray()
+ ' FreeImage_SaveToMemoryEx2() with FreeImage_DestroyLockedArray()
+ ' FreeImage_AcquireMemoryEx() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineEx() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineBITMAP8() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineBITMAP16() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineBITMAP24() with FreeImage_DestroyLockedArrayRGBTRIPLE()
+ ' FreeImage_GetScanLineBITMAP32() with FreeImage_DestroyLockedArrayRGBQUAD()
+ ' FreeImage_GetScanLineINT16() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineINT32() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineFLOAT() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineDOUBLE() with FreeImage_DestroyLockedArray()
+ ' FreeImage_GetScanLineCOMPLEX() with FreeImage_DestroyLockedArrayFICOMPLEX()
+ ' FreeImage_GetScanLineRGB16() with FreeImage_DestroyLockedArrayFIRGB16()
+ ' FreeImage_GetScanLineRGBA16() with FreeImage_DestroyLockedArrayFIRGBA16()
+ ' FreeImage_GetScanLineRGBF() with FreeImage_DestroyLockedArrayFIRGBF()
+ ' FreeImage_GetScanLineRGBAF() with FreeImage_DestroyLockedArrayFIRGBAF()
+
+
+ ' ensure, this is an array
+ If (VarType(Data) And vbArray) Then
+
+ ' data is a VB array, what means a SAFEARRAY in C/C++, that is
+ ' passed through a ByRef Variant variable, that is a pointer to
+ ' a VARIANTARG structure
+
+ ' the VARIANTARG structure looks like this:
+
+ ' typedef struct tagVARIANT VARIANTARG;
+ ' struct tagVARIANT
+ ' {
+ ' Union
+ ' {
+ ' struct __tagVARIANT
+ ' {
+ ' VARTYPE vt;
+ ' WORD wReserved1;
+ ' WORD wReserved2;
+ ' WORD wReserved3;
+ ' Union
+ ' {
+ ' [...]
+ ' SAFEARRAY *parray; // used when not VT_BYREF
+ ' [...]
+ ' SAFEARRAY **pparray; // used when VT_BYREF
+ ' [...]
+
+ ' the data element (SAFEARRAY) has an offset of 8, since VARTYPE
+ ' and WORD both have a length of 2 bytes; the pointer to the
+ ' VARIANTARG structure is the VarPtr of the Variant variable in VB
+
+ ' getting the contents of the data element (in C/C++: *(data + 8))
+ lpArrayPtr = deref(VarPtr(Data) + 8)
+
+ ' call the 'FreeImage_DestroyLockedArrayByPtr' function to destroy
+ ' the array properly
+ Call FreeImage_DestroyLockedArrayByPtr(lpArrayPtr)
+ Else
+
+ FreeImage_DestroyLockedArray = -1
+ End If
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayByPtr(ByVal lpArrayPtr As Long) As Long
+
+Dim lpSA As Long
+
+ ' This function destroys a self-created array with a custom array
+ ' descriptor by a pointer to the array variable.
+
+ ' dereference the pointer once (in C/C++: *lpArrayPtr)
+ lpSA = deref(lpArrayPtr)
+ ' now 'lpSA' is a pointer to the actual SAFEARRAY structure
+ ' and could be a null pointer when the array is not initialized
+ ' then, we have nothing to do here but return (-1) to indicate
+ ' an "error"
+ If (lpSA) Then
+
+ ' destroy the array descriptor
+ Call SafeArrayDestroyDescriptor(lpSA)
+
+ ' make 'lpSA' a null pointer, that is an uninitialized array;
+ ' keep in mind, that we here use 'lpArrayPtr' as a ByVal argument,
+ ' since 'lpArrayPtr' is a pointer to lpSA (the address of lpSA);
+ ' we need to zero these four bytes, 'lpArrayPtr' points to
+ Call CopyMemory(ByVal lpArrayPtr, 0&, 4)
+ Else
+
+ ' the array is already uninitialized, so return an "error" value
+ FreeImage_DestroyLockedArrayByPtr = -1
+ End If
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayRGBTRIPLE(ByRef Data() As RGBTRIPLE) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'RGBTRIPLE'.
+
+ FreeImage_DestroyLockedArrayRGBTRIPLE = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayRGBQUAD(ByRef Data() As RGBQUAD) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'RGBQUAD'.
+
+ FreeImage_DestroyLockedArrayRGBQUAD = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayFICOMPLEX(ByRef Data() As FICOMPLEX) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'FICOMPLEX'.
+
+ FreeImage_DestroyLockedArrayFICOMPLEX = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayFIRGB16(ByRef Data() As FIRGB16) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'FIRGB16'.
+
+ FreeImage_DestroyLockedArrayFIRGB16 = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayFIRGBA16(ByRef Data() As FIRGBA16) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'FIRGBA16'.
+
+ FreeImage_DestroyLockedArrayFIRGBA16 = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayFIRGBF(ByRef Data() As FIRGBF) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'FIRGBF'.
+
+ FreeImage_DestroyLockedArrayFIRGBF = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+Public Function FreeImage_DestroyLockedArrayFIRGBAF(ByRef Data() As FIRGBAF) As Long
+
+ ' This function is a thin wrapper for 'FreeImage_DestroyLockedArrayByPtr'
+ ' for destroying arrays of type 'FIRGBAF'.
+
+ FreeImage_DestroyLockedArrayFIRGBAF = FreeImage_DestroyLockedArrayByPtr(VarPtrArray(Data))
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Private IOlePicture related helper functions
+'--------------------------------------------------------------------------------
+
+Private Function pGetIOlePictureFromContainer(ByRef Container As Object, _
+ Optional ByVal IncludeDrawings As Boolean) As IPicture
+
+ ' Returns a VB IOlePicture object (IPicture) from a VB image hosting control.
+ ' See the inline documentation of function 'FreeImage_CreateFromImageContainer'
+ ' for a detailed description of this helper function.
+
+ If (Not Container Is Nothing) Then
+
+ Select Case TypeName(Container)
+
+ Case "PictureBox", "Form"
+ If (IncludeDrawings) Then
+ If (Not Container.AutoRedraw) Then
+ Call Err.Raise(5, _
+ "MFreeImage", _
+ Error$(5) & vbCrLf & vbCrLf & _
+ "Custom drawings can only be included into the DIB when " & _
+ "the container's 'AutoRedraw' property is set to True.")
+ Exit Function
+ End If
+ Set pGetIOlePictureFromContainer = Container.Image
+ Else
+ Set pGetIOlePictureFromContainer = Container.Picture
+ End If
+
+ Case Else
+
+ Dim bHasPicture As Boolean
+ Dim bHasImage As Boolean
+ Dim bIsAutoRedraw As Boolean
+
+ On Error Resume Next
+ bHasPicture = (Container.Picture <> 0)
+ bHasImage = (Container.Image <> 0)
+ bIsAutoRedraw = Container.AutoRedraw
+ On Error GoTo 0
+
+ If ((IncludeDrawings) And _
+ (bHasImage) And _
+ (bIsAutoRedraw)) Then
+ Set pGetIOlePictureFromContainer = Container.Image
+
+ ElseIf (bHasPicture) Then
+ Set pGetIOlePictureFromContainer = Container.Picture
+
+ Else
+ Call Err.Raise(5, _
+ "MFreeImage", _
+ Error$(5) & vbCrLf & vbCrLf & _
+ "Cannot create DIB from container control. Container " & _
+ "control has no 'Picture' property.")
+
+ End If
+
+ End Select
+
+ End If
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Private image and color helper functions
+'--------------------------------------------------------------------------------
+
+Private Function pGetPreviousColorDepth(ByVal lBPP As Long) As Long
+
+ ' This function returns the 'previous' color depth of a given
+ ' color depth. Here, 'previous' means the next smaller color
+ ' depth.
+
+ Select Case lBPP
+
+ Case 32
+ pGetPreviousColorDepth = 24
+
+ Case 24
+ pGetPreviousColorDepth = 16
+
+ Case 16
+ pGetPreviousColorDepth = 15
+
+ Case 15
+ pGetPreviousColorDepth = 8
+
+ Case 8
+ pGetPreviousColorDepth = 4
+
+ Case 4
+ pGetPreviousColorDepth = 1
+
+ End Select
+
+End Function
+
+Private Function pGetNextColorDepth(ByVal lBPP As Long) As Long
+
+ ' This function returns the 'next' color depth of a given
+ ' color depth. Here, 'next' means the next greater color
+ ' depth.
+
+ Select Case lBPP
+
+ Case 1
+ pGetNextColorDepth = 4
+
+ Case 4
+ pGetNextColorDepth = 8
+
+ Case 8
+ pGetNextColorDepth = 15
+
+ Case 15
+ pGetNextColorDepth = 16
+
+ Case 16
+ pGetNextColorDepth = 24
+
+ Case 24
+ pGetNextColorDepth = 32
+
+ End Select
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Private metadata helper functions
+'--------------------------------------------------------------------------------
+
+Private Function pGetTagFromTagPtr(ByVal Model As FREE_IMAGE_MDMODEL, _
+ ByVal lpTag As Long) As FREE_IMAGE_TAG
+
+Dim tTag As FITAG
+Dim lTemp As Long
+Dim i As Long
+
+ ' This function converts data stored in a real FreeImage tag
+ ' pointer (FITAG **tag) into a VB friendly structure FREE_IMAGE_TAG.
+
+ If (lpTag <> 0) Then
+
+ ' this is like (only like!) tTag tag = (FITAG) lpTag; in C/C++
+ ' we copy Len(tTag) bytes from the address in lpTag in to a
+ ' private FITAG structure tTag so we have easy access to all
+ ' FITAG members
+ Call CopyMemory(tTag, ByVal deref(lpTag), Len(tTag))
+
+ With pGetTagFromTagPtr
+
+ ' first fill all members expect 'Value' in our
+ ' VB friendly FREE_IMAGE_TAG structure
+
+ ' since we use this VB friendly FREE_IMAGE_TAG structure
+ ' for later tag modification too, we also need to store the
+ ' tag model and the pointer to the actual FreeImage FITAG
+ ' structure
+ .Model = Model
+ .TagPtr = lpTag
+
+ ' although FITAG's 'count' and 'length' members are
+ ' unsigned longs, we do not expect values greater
+ ' than 2,147,483,647, so we store them in normal VB
+ ' signed longs
+ .Count = tTag.Count
+ .Length = tTag.Length
+
+ ' strings are stored as pointers to the actual string
+ ' data in FITAG
+ .Description = pGetStringFromPointerA(tTag.Description)
+ .Key = pGetStringFromPointerA(tTag.Key)
+
+ ' FITAG's 'id' and 'type' members are unsigned shorts;
+ ' first of all 'id' may exceed the range of a signed
+ ' short (Integer data type in VB), so we store them in
+ ' signed longs and use CopyMemory for to keep the
+ ' unsigned bit layout
+ Call CopyMemory(.Id, tTag.Id, 2)
+ Call CopyMemory(.Type, tTag.Type, 2)
+
+ ' StringValue is the result of FreeImage_TagToString(); we
+ ' also store this tag representation in our structure
+ .StringValue = FreeImage_TagToString(Model, lpTag)
+
+
+ ' now comes the hard part, getting the tag's value
+
+ Select Case .Type
+
+ Case FIDT_BYTE, _
+ FIDT_UNDEFINED
+ If (.Count > 1) Then
+ Dim abBytes() As Byte
+ ' for a byte array, just redim a VB Byte array and
+ ' copy Count bytes from the pointer
+ ReDim abBytes(.Count - 1)
+ Call CopyMemory(abBytes(0), ByVal tTag.Value, .Count)
+ .Value = abBytes
+ Else
+ ' copy a single byte into a Long and assign
+ ' with CByte()
+ Call CopyMemory(lTemp, ByVal tTag.Value, 1)
+ .Value = CByte(lTemp)
+ End If
+
+ Case FIDT_ASCII
+ ' for an ASCII string, 'value' is just a pointer to the
+ ' string's actual data
+ .Value = pGetStringFromPointerA(tTag.Value)
+
+ Case FIDT_SHORT
+ Dim iTemp As Integer
+ If (.Count > 1) Then
+ ' for a unsigned long array, first redim Value to
+ ' proper size
+ ReDim .Value(.Count - 1)
+ ' iterate over all items
+ For i = 0 To .Count - 1
+ ' copy each value into a Long and
+ ' assign with FreeImage_UnsignedShort() to the
+ ' corresponding item in the (Variant) Value array
+ Call CopyMemory(iTemp, ByVal tTag.Value + i * 2, 2)
+ .Value(i) = FreeImage_UnsignedShort(iTemp)
+ Next i
+ Else
+ ' copy a single byte into a Long and assign
+ ' with FreeImgage_UnsignedShort()
+ Call CopyMemory(iTemp, ByVal tTag.Value, 2)
+ ' this works although FreeImage_UnsignedShort() takes
+ ' an Integer parameter since lTemp was 0 before and
+ ' we copied only 2 bytes so, VB's implicit conversion
+ ' to Integer will never produce an overflow
+ .Value = FreeImage_UnsignedShort(iTemp)
+ End If
+
+ Case FIDT_LONG, _
+ FIDT_IFD
+ If (.Count > 1) Then
+ ' for a unsigned long array, first redim Value to
+ ' proper size
+ ReDim .Value(.Count - 1)
+ ' iterate over all items
+ For i = 0 To .Count - 1
+ ' copy each value into a (signed) Long and
+ ' assign with FreeImage_UnsignedLong() to the
+ ' corresponding item in the (Variant) Value array
+ Call CopyMemory(lTemp, ByVal tTag.Value + i * 4, 4)
+ .Value(i) = FreeImage_UnsignedLong(lTemp)
+ Next i
+ Else
+ ' copy a single unsigned long into a (signed) Long and
+ ' assign with FreeImage_UnsignedLong()
+ Call CopyMemory(lTemp, ByVal tTag.Value, 2)
+ .Value = FreeImage_UnsignedLong(lTemp)
+ End If
+
+ Case FIDT_RATIONAL, _
+ FIDT_SRATIONAL
+ ' rational values are always stored in the FREE_IMAGE_TAG
+ ' structure's FIRATIONAL array 'RationalValue' so, allocate
+ ' enough space in both the 'Value' and 'RationalValue'
+ ' members to hold 'Count' items
+ ReDim .Value(.Count - 1)
+ ReDim .RationalValue(.Count - 1)
+ For i = 0 To .Count - 1
+ ' iterate over all items
+ With .RationalValue(i)
+ ' for each item, copy both numerator and denominator
+ ' into a (signed) Long and assign it to the corresponding
+ ' member of the FIRATIONAL structure so, we first assume
+ ' havinge a signed rational (FIDT_SRATIONAL) here
+ Call CopyMemory(lTemp, ByVal tTag.Value + i * 8, 4)
+ .Numerator = lTemp
+ Call CopyMemory(lTemp, ByVal tTag.Value + i * 8 + 4, 4)
+ .Denominator = lTemp
+ End With
+ ' if we have an unsigned rational (FIDT_RATIONAL), convert
+ ' numerator and denominator
+ If (.Type = FIDT_RATIONAL) Then
+ ' convert with FreeImage_UnsignedLong()
+ With .RationalValue(i)
+ .Numerator = FreeImage_UnsignedLong(.Numerator)
+ .Denominator = FreeImage_UnsignedLong(.Denominator)
+ End With
+ ' normalze the unsigned rational value
+ Call pNormalizeRational(.RationalValue(i))
+ Else
+ ' normalze the signed rational value
+ Call pNormalizeSRational(.RationalValue(i))
+ End If
+ ' store the current fraction's (maybe only approximated) value in
+ ' the 'Value' member of the FREE_IMAGE_TAG structure
+ .Value(i) = .RationalValue(i).Numerator / .RationalValue(i).Denominator
+ Next i
+
+ Case FIDT_SBYTE
+ If (.Count > 1) Then
+ ' for a signed byte array, first redim Value to
+ ' proper size
+ ReDim .Value(.Count - 1)
+ ' iterate over all items
+ For i = 0 To .Count - 1
+ ' copy each signed byte value into a Long and
+ ' check, whether it is negative (bit 7 set)
+ Call CopyMemory(lTemp, ByVal tTag.Value, 1)
+ If (lTemp And 128) Then
+ ' if negative, calculate the negative value
+ ' and store it in an Integer
+ .Value(i) = CInt(-256 - (Not (lTemp - 1)))
+ Else
+ ' if positive, assign to Value as byte
+ .Value(i) = CByte(lTemp)
+ End If
+ Next i
+ Else
+ ' copy a single signed byte into a Long and
+ ' check, whether it is negative (bit 7 set)
+ Call CopyMemory(lTemp, ByVal tTag.Value, 1)
+ If (lTemp And 128) Then
+ ' if negative, calculate the negative value
+ ' and store it in an Integer
+ .Value = CInt(-256 - (Not (lTemp - 1)))
+ Else
+ ' if positive, assign to Value as byte
+ .Value = CByte(lTemp)
+ End If
+ End If
+
+ Case FIDT_SSHORT
+ If (.Count > 1) Then
+ Dim aiSShorts() As Integer
+ ' for a signed short array, just redim a VB Integer array and
+ ' copy Count bytes from the pointer
+ ReDim aiSShorts(.Count - 1)
+ Call CopyMemory(aiSShorts(0), ByVal tTag.Value, .Count * 2)
+ .Value = aiSShorts
+ Else
+ ' copy a single signed short into a Long and assign
+ ' with CInt()
+ Call CopyMemory(lTemp, ByVal tTag.Value, 2)
+ .Value = CInt(lTemp)
+ End If
+
+ Case FIDT_SLONG
+ If (.Count > 1) Then
+ Dim alSLongs() As Long
+ ' for a signed long array, just redim a VB Long array and
+ ' copy Count bytes from the pointer
+ ReDim alSLongs(.Count - 1)
+ Call CopyMemory(alSLongs(0), ByVal tTag.Value, .Count * 4)
+ .Value = alSLongs
+ Else
+ ' copy a single signed long into a Long and assign
+ ' directly
+ Call CopyMemory(lTemp, ByVal tTag.Value, 4)
+ .Value = lTemp
+ End If
+
+ Case FIDT_FLOAT
+ If (.Count > 1) Then
+ Dim asngFloats() As Single
+ ' for a float array, just redim a VB Single array and
+ ' copy Count bytes from the pointer
+ ReDim asngFloats(.Count - 1)
+ Call CopyMemory(asngFloats(0), ByVal tTag.Value, .Count * 4)
+ .Value = asngFloats
+ Else
+ Dim sngFloat As Single
+ ' copy a single float into a Single and assign
+ ' directly
+ Call CopyMemory(sngFloat, ByVal tTag.Value, 4)
+ .Value = sngFloat
+ End If
+
+ Case FIDT_DOUBLE
+ If (.Count > 1) Then
+ Dim adblDoubles() As Double
+ ' for a double array, just redim a VB Double array and
+ ' copy Count bytes from the pointer
+ ReDim adblDoubles(.Count - 1)
+ Call CopyMemory(adblDoubles(0), ByVal tTag.Value, .Count * 8)
+ .Value = adblDoubles
+ Else
+ Dim dblDouble As Double
+ ' copy a single double into a Double and assign
+ ' directly
+ Call CopyMemory(dblDouble, ByVal tTag.Value, 8)
+ .Value = dblDouble
+ End If
+
+ Case FIDT_PALETTE
+ ' copy 'Count' palette entries (RGBQUAD) form the value
+ ' pointer into the proper dimensioned array of RGBQUAD
+ ReDim .Palette(.Count - 1)
+ For i = 0 To .Count - 1
+ Call CopyMemory(.Palette(i), ByVal tTag.Value + i * 4, 4)
+ Next i
+
+ End Select
+
+ End With
+ End If
+
+End Function
+
+Private Sub pNormalizeRational(ByRef tRationalValue As FIRATIONAL)
+
+Dim vntCommon As Long
+
+ ' This function normalizes an unsigned fraction stored in a FIRATIONAL
+ ' structure by cancelling down the fraction. This is commonly done
+ ' by dividing both numerator and denominator by their greates
+ ' common divisor (gcd)
+
+ With tRationalValue
+ If ((.Numerator <> 1) And (.Denominator <> 1)) Then
+ vntCommon = gcd(.Numerator, .Denominator)
+ If (vntCommon <> 1) Then
+ ' convert values back to an unsigned long (may
+ ' result in a subtype Currency if the range of the
+ ' VB Long is insufficient for storing the value!)
+ .Numerator = FreeImage_UnsignedLong(.Numerator / vntCommon)
+ .Denominator = FreeImage_UnsignedLong(.Denominator / vntCommon)
+ End If
+ End If
+ End With
+
+End Sub
+
+Private Sub pNormalizeSRational(ByRef tRationalValue As FIRATIONAL)
+
+Dim lCommon As Long
+
+ ' This function normalizes a signed fraction stored in a FIRATIONAL
+ ' structure by cancelling down the fraction. This is commonly done
+ ' by dividing both numerator and denominator by their greates
+ ' common divisor (gcd)
+
+ With tRationalValue
+ If ((.Numerator <> 1) And (.Denominator <> 1)) Then
+ lCommon = gcd(.Numerator, .Denominator)
+ If (lCommon <> 1) Then
+ ' using the CLng() function for not to get
+ ' a subtype Double here
+ .Numerator = CLng(.Numerator / lCommon)
+ .Denominator = CLng(.Denominator / lCommon)
+ End If
+ End If
+
+ ' adjust the position of the negative sign if one is present:
+ ' it should preceed the numerator, not the denominator
+ If (.Denominator < 0) Then
+ .Denominator = -.Denominator
+ .Numerator = -.Numerator
+ End If
+ End With
+
+End Sub
+
+Private Function gcd(ByVal a As Variant, ByVal b As Variant) As Variant
+
+Dim vntTemp As Variant
+
+ ' calculate greatest common divisor
+
+ Do While (b)
+ vntTemp = b
+ ' calculate b = a % b (modulo)
+ ' this could be just:
+ ' b = a Mod b
+ ' but VB's Mod operator fails for unsigned
+ ' long values stored in currency variables
+ ' so, we use the mathematical definition of
+ ' the modulo operator taken from WikipediA.
+ b = a - floor(a / b) * b
+ a = vntTemp
+ Loop
+ gcd = a
+
+End Function
+
+Private Function floor(ByRef a As Variant) As Variant
+
+ ' this is a VB version of the floor() function
+ If (a < 0) Then
+ floor = VBA.Int(a)
+ Else
+ floor = -VBA.Fix(-a)
+ End If
+
+End Function
+
+Private Function pTagToTagPtr(ByRef Tag As FREE_IMAGE_TAG) As Boolean
+
+Dim tTagSave As FITAG
+Dim lpTag As Long
+Dim abValueBuffer() As Byte
+Dim lLength As Long
+Dim lCount As Long
+
+ ' This function converts tag data stored in a VB friendly structure
+ ' FREE_IMAGE_TAG into a real FreeImage tag pointer (FITAG **tag).
+
+ ' This function is called, whenever tag data should be updated for an
+ ' image, since the FreeImage's tag pointer remains valid during the
+ ' whole lifetime of a DIB. So, changes written to that pointer (or
+ ' even better, the FITAG structure at the address, the pointer points
+ ' to), are real updates to the image's tag.
+
+ With Tag
+
+ lpTag = deref(.TagPtr)
+
+ ' save current (FITAG) tag for an optional 'undo' operation
+ ' invoked on failure
+ Call CopyMemory(tTagSave, ByVal lpTag, Len(tTagSave))
+
+ ' set tag id
+ Call CopyMemory(ByVal lpTag + 8, .Id, 2)
+ ' set tag type
+ Call CopyMemory(ByVal lpTag + 10, .Type, 2)
+ ' set tag key (use native FreeImage function to handle
+ ' memory allocation)
+ Call FreeImage_SetTagKey(.TagPtr, .Key)
+
+ ' here, we update the tag's value
+ ' generally, we create a plain byte buffer containing all the
+ ' value's data and use FreeImage_SetTagValue() with the
+ ' const void *value pointer set to the byte buffer's address.
+
+ ' the variable abValueBuffer is our byte buffer that is,
+ ' depending on the FreeImage tag data type, allocated and filled
+ ' accordingly
+ ' The variables 'lLength' and 'lCount' are set up correctly for
+ ' each data type and will be filled into the FITAG structure
+ ' before calling FreeImage_SetTagValue(); after all, the VB
+ ' Tag structure's (FREE_IMAGE_TAG) 'Count' and 'Length' members
+ ' are updated with 'lLength' and 'lCount'.
+
+ Select Case .Type
+
+ Case FIDT_ASCII
+ ' use StrConv() to get an ASCII byte array from a VB String (BSTR)
+ abValueBuffer = StrConv(.Value, vbFromUnicode)
+ ' according to FreeImage's source code, both 'count' and 'length'
+ ' must be the length of the string
+ lCount = Len(.Value)
+ lLength = lCount
+
+ Case FIDT_PALETTE
+ ' ensure, that there are at least 'Count' entries in the
+ ' palette array
+ lCount = .Count
+ If (UBound(.Palette) + 1 < lCount) Then
+ ' if not, adjust Count
+ lCount = UBound(.Palette) + 1
+ End If
+ ' 4 bytes per element
+ lLength = lCount * 4
+ ' allocate buffer and copy data from Palatte array
+ ReDim abValueBuffer(lLength - 1)
+ Call CopyMemory(abValueBuffer(0), .Palette(LBound(.Palette)), lLength)
+
+ Case FIDT_RATIONAL, _
+ FIDT_SRATIONAL
+ ' we use a helper function to get a byte buffer for any type of
+ ' rational value
+ lCount = pGetRationalValueBuffer(.RationalValue, abValueBuffer)
+ If (lCount > .Count) Then
+ lCount = .Count
+ End If
+ ' eight bytes per element (2 longs)
+ lLength = lCount * 8
+
+ Case Else
+ ' we use a helper function to get a byte buffer for any other type
+ lCount = pGetValueBuffer(.Value, .Type, lLength, abValueBuffer)
+ If (lCount > .Count) Then
+ lCount = .Count
+ End If
+ ' lLength was used as an OUT parameter when calling pGetValueBuffer
+ ' it now contains the size of one element in bytes so, multiply with
+ ' lCount to get the total length
+ lLength = lLength * lCount
+
+ End Select
+
+ ' set tag length
+ Call CopyMemory(ByVal lpTag + 16, lLength, 4)
+ ' set tag count
+ Call CopyMemory(ByVal lpTag + 12, lCount, 4)
+
+ If (FreeImage_SetTagValue(.TagPtr, VarPtr(abValueBuffer(0))) <> 0) Then
+
+ ' update Tag's members
+ ' update Count
+ .Count = lCount
+ ' update Length
+ .Length = lLength
+ ' update StringValue
+ .StringValue = FreeImage_TagToString(.Model, .TagPtr)
+ pTagToTagPtr = True
+ Else
+
+ ' restore saved (FITAG) tag values on failure
+ Call CopyMemory(ByVal lpTag, tTagSave, Len(tTagSave))
+ End If
+
+ End With
+
+End Function
+
+Private Function pGetValueBuffer(ByRef Value As Variant, _
+ ByVal MetaDataVarType As FREE_IMAGE_MDTYPE, _
+ ByRef ElementSize As Long, _
+ ByRef abBuffer() As Byte) As Long
+
+Dim lElementCount As Long
+Dim bIsArray As Boolean
+Dim abValueBuffer(7) As Byte
+Dim cBytes As Long
+Dim i As Long
+
+ ' This function copies any value provided in the Variant 'Value'
+ ' parameter into the byte array abBuffer. 'Value' may contain an
+ ' array as well. The values in the byte buffer are aligned to fit
+ ' the FreeImage data type for tag values specified in
+ ' 'MetaDataVarType'. For integer values, it does not matter, in
+ ' which VB data type the values are provided. For example, it is
+ ' possible to transform a provided byte array into a unsigned long
+ ' array.
+
+ ' The parameter 'ElementSize' is an OUT value, providing the actual
+ ' size per element in the byte buffer in bytes to the caller.
+
+ ' This function works for the types FIDT_BYTE, FIDT_SHORT, FIDT_LONG,
+ ' FIDT_SBYTE , FIDT_SSHORT, FIDT_SLONG, FIDT_FLOAT, FIDT_DOUBLE
+ ' and FIDT_IFD
+
+ ElementSize = pGetElementSize(MetaDataVarType)
+ If (Not IsArray(Value)) Then
+ lElementCount = 1
+ Else
+ On Error Resume Next
+ lElementCount = UBound(Value) - LBound(Value) + 1
+ On Error GoTo 0
+ bIsArray = True
+ End If
+
+ If (lElementCount > 0) Then
+ ReDim abBuffer((lElementCount * ElementSize) - 1)
+
+ If (Not bIsArray) Then
+ cBytes = pGetVariantAsByteBuffer(Value, abValueBuffer)
+ If (cBytes > ElementSize) Then
+ cBytes = ElementSize
+ End If
+ Call CopyMemory(abBuffer(0), abValueBuffer(0), cBytes)
+ Else
+ For i = LBound(Value) To UBound(Value)
+ cBytes = pGetVariantAsByteBuffer(Value(i), abValueBuffer)
+ If (cBytes > ElementSize) Then
+ cBytes = ElementSize
+ End If
+ Call CopyMemory(abBuffer(0 + (i * ElementSize)), abValueBuffer(0), cBytes)
+ Next i
+ End If
+
+ pGetValueBuffer = lElementCount
+ End If
+
+End Function
+
+Private Function pGetRationalValueBuffer(ByRef RationalValues() As FIRATIONAL, _
+ ByRef abBuffer() As Byte) As Long
+
+Dim lElementCount As Long
+Dim abValueBuffer(7) As Byte
+Dim cBytes As Long
+Dim i As Long
+
+ ' This function copies a number of elements from the FIRATIONAL array
+ ' 'RationalValues' into the byte buffer 'abBuffer'.
+
+ ' From the caller's point of view, this function is the same as
+ ' 'pGetValueBuffer', except, it only works for arrays of FIRATIONAL.
+
+ ' This function works for the types FIDT_RATIONAL and FIDT_SRATIONAL.
+
+ lElementCount = UBound(RationalValues) - LBound(RationalValues) + 1
+ ReDim abBuffer(lElementCount * 8 + 1)
+
+ For i = LBound(RationalValues) To UBound(RationalValues)
+ cBytes = pGetVariantAsByteBuffer(RationalValues(i).Numerator, abValueBuffer)
+ If (cBytes > 4) Then
+ cBytes = 4
+ End If
+ Call CopyMemory(abBuffer(0 + (i * 8)), abValueBuffer(0), cBytes)
+
+ cBytes = pGetVariantAsByteBuffer(RationalValues(i).Denominator, abValueBuffer)
+ If (cBytes > 4) Then
+ cBytes = 4
+ End If
+ Call CopyMemory(abBuffer(4 + (i * 8)), abValueBuffer(0), cBytes)
+ Next i
+
+ pGetRationalValueBuffer = lElementCount
+
+End Function
+
+Private Function pGetVariantAsByteBuffer(ByRef Value As Variant, _
+ ByRef abBuffer() As Byte) As Long
+
+Dim lLength As Long
+
+ ' This function fills a byte buffer 'abBuffer' with data taken
+ ' from a Variant parameter. Depending on the Variant's type and,
+ ' width, it copies N (lLength) bytes into the buffer starting
+ ' at the buffer's first byte at abBuffer(0). The function returns
+ ' the number of bytes copied.
+
+ ' It is much easier to assign the Variant to a variable of
+ ' the proper native type first, since gathering a Variant's
+ ' actual value is a hard job to implement for each subtype.
+
+ Select Case VarType(Value)
+
+ Case vbByte
+ abBuffer(0) = Value
+ lLength = 1
+
+ Case vbInteger
+ Dim iInteger As Integer
+ iInteger = Value
+ lLength = 2
+ Call CopyMemory(abBuffer(0), iInteger, lLength)
+
+ Case vbLong
+ Dim lLong As Long
+ lLong = Value
+ lLength = 4
+ Call CopyMemory(abBuffer(0), lLong, lLength)
+
+ Case vbCurrency
+ Dim cCurrency As Currency
+ ' since the Currency data type is a so called scaled
+ ' integer, we have to divide by 10.000 first to get the
+ ' proper bit layout.
+ cCurrency = Value / 10000
+ lLength = 8
+ Call CopyMemory(abBuffer(0), cCurrency, lLength)
+
+ Case vbSingle
+ Dim sSingle As Single
+ sSingle = Value
+ lLength = 4
+ Call CopyMemory(abBuffer(0), sSingle, lLength)
+
+ Case vbDouble
+ Dim dblDouble As Double
+ dblDouble = Value
+ lLength = 8
+ Call CopyMemory(abBuffer(0), dblDouble, lLength)
+
+ End Select
+
+ pGetVariantAsByteBuffer = lLength
+
+End Function
+
+Private Function pGetElementSize(ByVal VarType As FREE_IMAGE_MDTYPE) As Long
+
+ ' This function returns the width in bytes for any of the
+ ' FreeImage metadata tag data types.
+
+ Select Case VarType
+
+ Case FIDT_BYTE, _
+ FIDT_SBYTE, _
+ FIDT_UNDEFINED, _
+ FIDT_ASCII
+ pGetElementSize = 1
+
+ Case FIDT_SHORT, _
+ FIDT_SSHORT
+ pGetElementSize = 2
+
+ Case FIDT_LONG, _
+ FIDT_SLONG, _
+ FIDT_FLOAT, _
+ FIDT_PALETTE, _
+ FIDT_IFD
+ pGetElementSize = 4
+
+ Case Else
+ pGetElementSize = 8
+
+ End Select
+
+End Function
+
+
+
+'--------------------------------------------------------------------------------
+' Private pointer manipulation helper functions
+'--------------------------------------------------------------------------------
+
+Private Function pGetStringFromPointerA(ByRef lPtr As Long) As String
+
+Dim abBuffer() As Byte
+Dim lLength As Long
+
+ ' This function creates and returns a VB BSTR variable from
+ ' a C/C++ style string pointer by making a redundant deep
+ ' copy of the string's characters.
+
+ If (lPtr) Then
+ ' get the length of the ANSI string pointed to by lPtr
+ lLength = lstrlen(lPtr)
+ If (lLength) Then
+ ' copy characters to a byte array
+ ReDim abBuffer(lLength - 1)
+ Call CopyMemory(abBuffer(0), ByVal lPtr, lLength)
+ ' convert from byte array to unicode BSTR
+ pGetStringFromPointerA = StrConv(abBuffer, vbUnicode)
+ End If
+ End If
+
+End Function
+
+Private Function deref(ByVal lPtr As Long) As Long
+
+ ' This function dereferences a pointer and returns the
+ ' contents as it's return value.
+
+ ' in C/C++ this would be:
+ ' return *(lPtr);
+
+ Call CopyMemory(deref, ByVal lPtr, 4)
+
+End Function
+
+Private Sub swap(ByVal lpSrc As Long, _
+ ByVal lpDst As Long)
+
+Dim lpTmp As Long
+
+ ' This function swaps two DWORD memory blocks pointed to
+ ' by lpSrc and lpDst, whereby lpSrc and lpDst are actually
+ ' no pointer types but contain the pointer's address.
+
+ ' in C/C++ this would be:
+ ' void swap(int lpSrc, int lpDst) {
+ ' int tmp = *(int*)lpSrc;
+ ' *(int*)lpSrc = *(int*)lpDst;
+ ' *(int*)lpDst = tmp;
+ ' }
+
+ Call CopyMemory(lpTmp, ByVal lpSrc, 4)
+ Call CopyMemory(ByVal lpSrc, ByVal lpDst, 4)
+ Call CopyMemory(ByVal lpDst, lpTmp, 4)
+
+End Sub
+
+Private Function pGetMemoryBlockPtrFromVariant(ByRef Data As Variant, _
+ Optional ByRef size_in_bytes As Long, _
+ Optional ByRef element_size As Long) As Long
+
+ ' This function returns the pointer to the memory block provided through
+ ' the Variant parameter 'data', which could be either a Byte, Integer or
+ ' Long array or the address of the memory block itself. In the last case,
+ ' the parameter 'size_in_bytes' must not be omitted or zero, since it's
+ ' correct value (the size of the memory block) can not be determined by
+ ' the address only. So, the function fails, if 'size_in_bytes' is omitted
+ ' or zero and 'data' is not an array but contains a Long value (the address
+ ' of a memory block) by returning Null.
+
+ ' If 'data' contains either a Byte, Integer or Long array, the pointer to
+ ' the actual array data is returned. The parameter 'size_in_bytes' will
+ ' be adjusted correctly, if it was less or equal zero upon entry.
+
+ ' The function returns Null (zero) if there was no supported memory block
+ ' provided.
+
+ ' do we have an array?
+ If (VarType(Data) And vbArray) Then
+ Select Case (VarType(Data) And (Not vbArray))
+
+ Case vbByte
+ element_size = 1
+ pGetMemoryBlockPtrFromVariant = pGetArrayPtrFromVariantArray(Data)
+ If (pGetMemoryBlockPtrFromVariant) Then
+ If (size_in_bytes <= 0) Then
+ size_in_bytes = (UBound(Data) + 1)
+
+ ElseIf (size_in_bytes > (UBound(Data) + 1)) Then
+ size_in_bytes = (UBound(Data) + 1)
+
+ End If
+ End If
+
+ Case vbInteger
+ element_size = 2
+ pGetMemoryBlockPtrFromVariant = pGetArrayPtrFromVariantArray(Data)
+ If (pGetMemoryBlockPtrFromVariant) Then
+ If (size_in_bytes <= 0) Then
+ size_in_bytes = (UBound(Data) + 1) * 2
+
+ ElseIf (size_in_bytes > ((UBound(Data) + 1) * 2)) Then
+ size_in_bytes = (UBound(Data) + 1) * 2
+
+ End If
+ End If
+
+ Case vbLong
+ element_size = 4
+ pGetMemoryBlockPtrFromVariant = pGetArrayPtrFromVariantArray(Data)
+ If (pGetMemoryBlockPtrFromVariant) Then
+ If (size_in_bytes <= 0) Then
+ size_in_bytes = (UBound(Data) + 1) * 4
+
+ ElseIf (size_in_bytes > ((UBound(Data) + 1) * 4)) Then
+ size_in_bytes = (UBound(Data) + 1) * 4
+
+ End If
+ End If
+
+ End Select
+ Else
+ element_size = 1
+ If ((VarType(Data) = vbLong) And _
+ (size_in_bytes >= 0)) Then
+ pGetMemoryBlockPtrFromVariant = Data
+ End If
+ End If
+
+End Function
+
+Private Function pGetArrayPtrFromVariantArray(ByRef Data As Variant) As Long
+
+Dim eVarType As VbVarType
+Dim lDataPtr As Long
+
+ ' This function returns a pointer to the first array element of
+ ' a VB array (SAFEARRAY) that is passed through a Variant type
+ ' parameter. (Don't try this at home...)
+
+ ' cache VarType in variable
+ eVarType = VarType(Data)
+
+ ' ensure, this is an array
+ If (eVarType And vbArray) Then
+
+ ' data is a VB array, what means a SAFEARRAY in C/C++, that is
+ ' passed through a ByRef Variant variable, that is a pointer to
+ ' a VARIANTARG structure
+
+ ' the VARIANTARG structure looks like this:
+
+ ' typedef struct tagVARIANT VARIANTARG;
+ ' struct tagVARIANT
+ ' {
+ ' Union
+ ' {
+ ' struct __tagVARIANT
+ ' {
+ ' VARTYPE vt;
+ ' WORD wReserved1;
+ ' WORD wReserved2;
+ ' WORD wReserved3;
+ ' Union
+ ' {
+ ' [...]
+ ' SAFEARRAY *parray; // used when not VT_BYREF
+ ' [...]
+ ' SAFEARRAY **pparray; // used when VT_BYREF
+ ' [...]
+
+ ' the data element (SAFEARRAY) has an offset of 8, since VARTYPE
+ ' and WORD both have a length of 2 bytes; the pointer to the
+ ' VARIANTARG structure is the VarPtr of the Variant variable in VB
+
+ ' getting the contents of the data element (in C/C++: *(data + 8))
+ lDataPtr = deref(VarPtr(Data) + 8)
+
+ ' dereference the pointer again (in C/C++: *(lDataPtr))
+ lDataPtr = deref(lDataPtr)
+
+ ' test, whether 'lDataPtr' now is a Null pointer
+ ' in that case, the array is not yet initialized and so we can't dereference
+ ' it another time since we have no permisson to acces address 0
+
+ ' the contents of 'lDataPtr' may be Null now in case of an uninitialized
+ ' array; then we can't access any of the SAFEARRAY members since the array
+ ' variable doesn't event point to a SAFEARRAY structure, so we will return
+ ' the null pointer
+
+ If (lDataPtr) Then
+ ' the contents of lDataPtr now is a pointer to the SAFEARRAY structure
+
+ ' the SAFEARRAY structure looks like this:
+
+ ' typedef struct FARSTRUCT tagSAFEARRAY {
+ ' unsigned short cDims; // Count of dimensions in this array.
+ ' unsigned short fFeatures; // Flags used by the SafeArray
+ ' // routines documented below.
+ ' #if defined(WIN32)
+ ' unsigned long cbElements; // Size of an element of the array.
+ ' // Does not include size of
+ ' // pointed-to data.
+ ' unsigned long cLocks; // Number of times the array has been
+ ' // locked without corresponding unlock.
+ ' #Else
+ ' unsigned short cbElements;
+ ' unsigned short cLocks;
+ ' unsigned long handle; // Used on Macintosh only.
+ ' #End If
+ ' void HUGEP* pvData; // Pointer to the data.
+ ' SAFEARRAYBOUND rgsabound[1]; // One bound for each dimension.
+ ' } SAFEARRAY;
+
+ ' since we live in WIN32, the pvData element has an offset
+ ' of 12 bytes from the base address of the structure,
+ ' so dereference the pvData pointer, what indeed is a pointer
+ ' to the actual array (in C/C++: *(lDataPtr + 12))
+ lDataPtr = deref(lDataPtr + 12)
+ End If
+
+ ' return this value
+ pGetArrayPtrFromVariantArray = lDataPtr
+
+ ' a more shorter form of this function would be:
+ ' (doesn't work for uninitialized arrays, but will likely crash!)
+ 'pGetArrayPtrFromVariantArray = deref(deref(deref(VarPtr(data) + 8)) + 12)
+ End If
+
+End Function
diff --git a/Wrapper/VB6/mfreeimage/WhatsNew_VB.txt b/Wrapper/VB6/mfreeimage/WhatsNew_VB.txt
new file mode 100644
index 0000000..8862b66
--- /dev/null
+++ b/Wrapper/VB6/mfreeimage/WhatsNew_VB.txt
@@ -0,0 +1,551 @@
+What's New for FreeImage VB Wrapper
+
+* : fixed
+- : removed
+! : changed
++ : added
+
+September 08, 2009 - 2.5
+! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 13 to match current version 3.13.0
++ [Carsten Klein] added load flag constant JPEG_EXIFROTATE and new member FILO_JPEG_EXIFROTATE to enumeration FREE_IMAGE_LOAD_OPTIONS.
++ [Carsten Klein] added support for the PFM image format.
++ [Carsten Klein] added support for the PICT and RAW image formats.
++ [Carsten Klein] added UNICODE functions FreeImage_JPEGTransformU and FreeImage_JPEGCropU.
++ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_OPTIONS, which contains options to specify colors, used with FreeImage_FillBackground and FreeImage_EnlargeCanvas.
++ [Carsten Klein] added function FreeImage_FillBackground: although this returns BOOL in C/C++, the VB version only returns a Long.
++ [Carsten Klein] added wrapper functions FreeImage_FillBackgroundEx and FreeImage_FillBackgroundByLong, taking an RGBQUAD and a Long 'Color' argument respectively and return a true VB Boolean.
++ [Carsten Klein] added function FreeImage_EnlargeCanvas.
++ [Carsten Klein] added functions FreeImage_AllocateEx and FreeImage_AllocateExT.
++ [Carsten Klein] added function FreeImage_TmoReinhard05Ex.
++ [Carsten Klein] added function FreeImage_Rotate.
++ [Carsten Klein] added wrapper function FreeImage_RotateIOP.
+
+! now FreeImage version 3.13.0
+
+March 18, 2009 - 2.4.2
++ [Carsten Klein] added enumeration FREE_IMAGE_FRAME_DISPOSAL_METHODS, which provides the frame disposal options needed to create animated GIF files.
+
+July 29, 2008 - 2.4.1
+* [Carsten Klein] minor documentation updates
+! [Carsten Klein] renamed member FICF_PALETTISED_8BPP of enumeration FREE_IMAGE_CONVERSION_FLAGS into FICF_PALLETISED_8BPP.
+
+June 30, 2008 - 2.4
+* [Carsten Klein] fixed some minor issues in FreeImage_PaintTransparent()
+
+June 06, 2008 - 2.3
++ [Carsten Klein] added new compression flags to the JPEG and PNG plugins
+! [Carsten Klein] renamed wrapper function FreeImage_CloneMetadata() to FreeImage_CloneMetadataEx(): now, there is a native function called FreeImage_CloneMetadata().
++ [Carsten Klein] added private and internal function declaration for FreeImage_CloneMetadata() along with it's public Boolean returning wrapper function.
+- [Carsten Klein] removed the FreeImage_ColorQuantizeEx() stuff from both functions FreeImage_ConvertColorDepth() and FreeImage_ConvertColorDepthIOP(): removed parameters PaletteSize, ReserveSize and ReservePalette.
+- [Carsten Klein] changed declaration of FreeImage_ColorQuantizeEx() to be a internal function private to the wrapper with an 'Int' appendix.
++ [Carsten Klein] added two more VB-friendly public wrapper functions FreeImage_ColorQuantizeEx() and FreeImage_ColorQuantizeExIOP().
++ [Carsten Klein] added wrapper function FreeImage_GetPalettePtr(): gets the pointer to a specified array of RGBQUADs: intended to be used together with any of the ColorQuantizeEx functions.
+! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 11 to match current version 3.11.0
+
+! now FreeImage version 3.11.0
+
+December 14, 2007 - 2.2.1
++ [Carsten Klein] added constants for member 'biCompression' in BITMAPINFOHEADER struct
++ [Carsten Klein] added wrapper function FreeImage_GetInfoHeaderEx(), which returns a fully populated BITMAPINFOHEADER struct for a bitmap.
+* [Carsten Klein] fixed a bug in FreeImage_GetFileTypeFromMemoryEx(): now calls FreeImage_CloseMemory() releasing the hStream to prevent memory leaks.
++ [Carsten Klein] added wrapper function FreeImage_GetColorizedPalette(): returns a colorized greyscale palettte.
++ [Carsten Klein] added wrapper function FreeImage_Colorize(): applies a colorized greyscale palettte obtained from FreeImage_GetColorizedPalette() to a bitmap.
++ [Carsten Klein] added wrapper function FreeImage_Sepia(): calls FreeImage_Colorize() with proper parameters to apply a so called sepia palette to a bitmap.
+
+December 12, 2007 - 2.2
+* [Carsten Klein] Fixed a small bug in FreeImage_PaintTransparent, which now calls function FreeImage_ConvertTo32Bits instead of FreeImage_ConvertTo32Bits2.
+
+November 15, 2007 - 2.1
+* [Carsten Klein] adjusted page numbers of the API documentation in FreeImage function declarations to match FreeImage 3.10.0 API documentation
+- [Carsten Klein] removed parameter 'bUnloadSource' from function FreeImage_GetOlePictureIcon(): an hIcon should not be destroyed if OleCreatePictureIndirect() is called with fOwn = True.
+! [Carsten Klein] refactored FreeImage_GetOlePicture(): now relies on FreeImage_GetBitmap().
+
+November 10, 2007 - 2.0.8
+! [Carsten Klein] changed declaration of FreeImage_SetOutputMessage(): now points transparently to the __stdcall version of this function in the library.
++ [Carsten Klein] added function declaraton for FreeImage_MultigridPoissonSolver().
++ [Carsten Klein] added function declaraton for FreeImage_GetTransparentIndex() and FreeImage_SetTransparentIndex().
++ [Carsten Klein] added private and internal function declaraton for FreeImage_AdjustColors() along with it's public Boolean returning wrapper function.
++ [Carsten Klein] added function declaraton for FreeImage_GetAdjustColorsLookupTable().
++ [Carsten Klein] added wrapper function FreeImage_GetAdjustColorsLookupTableEx(): this takes a real VB style Byte array ton receive the lookup table created.
++ [Carsten Klein] added function declaraton for FreeImage_ApplyColorMapping().
++ [Carsten Klein] added wrapper function FreeImage_ApplyColorMappingEx(): this takes a real VB style RGBQUAD array.
++ [Carsten Klein] added function declaratons for FreeImage_SwapColors() and FreeImage_SwapColorsByLong().
++ [Carsten Klein] added function declaraton for FreeImage_ApplyIndexMapping().
++ [Carsten Klein] added wrapper function FreeImage_ApplyIndexMappingEx(): this takes a real VB style Byte array.
++ [Carsten Klein] added function declaraton for FreeImage_SwapPaletteIndices().
+
+November 05, 2007 - 2.0.7
++ [Carsten Klein] added 4 bit color depth to both function pGetNextColorDepth() and pGetPrevousColorDepth()
+- [Carsten Klein] removed member FICF_PREPARE_RESCALE from enumeration FREE_IMAGE_CONVERSION_FLAGS
+- [Carsten Klein] removed all references to FICF_PREPARE_RESCALE: Converting color depth before rescaling an image is no longer performed by the wrapper. Since FreeImage now transparently converts color depth on rescaling, doing this in the wrapper is no longer needed.
+! [Carsten Klein] refactored wrapper function FreeImage_ConvertColorDepth(): removed case FICF_PREPARE_RESCALE; is now more similar to C# wrapper's version of this function.
+! [Carsten Klein] refactored wrapper function FreeImage_SaveEx(): removed case FICF_PREPARE_RESCALE; is now more similar to C# wrapper's version of this function.
+
+September 14, 2007 - 2.0.6
++ [Carsten Klein] added function declaration and Boolean wrapper function for FreeImage_PreMultiplyWithAlpha().
+
+July 26, 2007 - 2.0.5
++ [Carsten Klein] added wrapper function FreeImage_GetBitmap(): returns an HBITMAP created by the CreateDIBSection() function and so has the same color depth as the original DIB.
++ [Carsten Klein] added wrapper function FreeImage_GetBitmapForDevice(): returns an HBITMAP created by the CreateDIBitmap() function and so has the same color depth as the specified reference DC or as the desktop, if the 'hDC' parameter was omitted.
+- [Carsten Klein] removed function declaration for GetWindowDC(): this function is no longer used.
+* [Carsten Klein] fixed a bug in wrapper function FreeImage_IsExtensionValidForFIF(): string comparison now includes a comma.
+* [Carsten Klein] fixed a bug in wrapper function FreeImage_IsFilenameValidForFIF(): string comparison now includes a comma.
+
+July 25, 2007 - 2.0.4
+* [Carsten Klein] fixed a bug in function FreeImage_GetPaletteExClone(): now actually returns the palette as RGBQUAD array plus some other minor improvements
++ [Carsten Klein] added wrapper function FreeImage_GetPaletteExLongClone(): this function returns a VB style Byte array that is only wrapped around FreeImage's pointer to a DIB's transparency table.
++ [Carsten Klein] added wrapper function FreeImage_GetTransparencyTableEx(): this function returns a VB style Byte array that is only wrapped around FreeImage's pointer to a DIB's transparency table.
+! [Carsten Klein] changed name of wrapper function FreeImage_GetTransparencyTableEx(): this function is now named FreeImage_GetTransparencyTableExClone(), since it actually returns a clone (deep copy) of an image's transparency table (compare with FreeImage_GetPaletteExClone()).
++ [Carsten Klein] added wrapper function FreeImage_SetPalette(): sets an image's palette through a VB style RGBQUAD array.
++ [Carsten Klein] added wrapper function FreeImage_SetPaletteLong(): sets an image's palette through a VB style Long array.
++ [Carsten Klein] added function declaration for CreateDIBsection()
++ [Carsten Klein] added function declaration for DeleteDC()
+* [Carsten Klein] fixed a bug in wrapper function FreeImage_CreateFromScreen(): now the memory DC is deleted with the DeleteDC() function and no longer with the DeleteObject() function.
+
+July 05, 2007 - 2.0.3
++ [Carsten Klein] added wrapper function FreeImage_GetFileTypeFromMemoryEx(): more VB friendly version of FreeImage_GetFileTypeFromMemory() which may take an array rather than a FIMEMORY stream.
+
+May 21, 2007 - 2.0.2
+! [Carsten Klein] changed constant FREEIMAGE_MINOR_VERSION: set to 10 to match current version 3.10.0
+! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 0 to match current version 3.10.0
++ [Carsten Klein] added image format constants FIF_EXR, FIF_J2K and FIF_JP2 to enumeration FREE_IMAGE_FORMAT.
++ [Carsten Klein] added tone mapping operator constant FITMO_FATTAL02 to enumeration FREE_IMAGE_TMO.
++ [Carsten Klein] added save option constants J2K_DEFAULT and JP2_DEFAULT for JPEG2000 format.
++ [Carsten Klein] added save option constants EXR_DEFAULT, EXR_FLOAT, EXR_NONE, EXR_ZIP, EXR_PIZ, EXR_PXR24, EXR_B44 and EXR_LC for EXR format.
++ [Carsten Klein] added save option constants for EXR format to enumeration FREE_IMAGE_SAVE_OPTIONS.
++ [Carsten Klein] added declared function FreeImage_TmoFattal02(): adds support for Gradient domain high dynamic range compression (R. Fattal, 2002)
+
+! now FreeImage version 3.10.0
+
+February 24, 2007 - 2.0.1
+* [Carsten Klein] fixed a bug in function FreeImage_CreateFromScreen(): now size of image created is according to window to be captured if parameter 'hwnd' <> 0.
++ [Carsten Klein] added parameter 'bClientAreaOnly' to function FreeImage_CreateFromScreen().
++ [Carsten Klein] added blitting option 'CAPTUREBLT' when calling function BitBlt() in function FreeImage_CreateFromScreen().
+- [Carsten Klein] removed unused variable 'hDIB' from functions FreeImage_CreateFromScreen() and FreeImage_LoadEx(). Thanks to Bruce Rusk for pointing that out.
+
+February 16, 2007 - 2.0
+! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 3 to match current version 3.9.3
+! [Carsten Klein] changed JPEG load/save flag option values: changed constants and both enumerations FREE_IMAGE_LOAD_OPTIONS and FREE_IMAGE_SAVE_OPTIONS.
++ [Carsten Klein] added ICC Color Profile support:
+! changed signature of declared function FreeImage_GetICCProfile(): is now declared 'Private' and suffixed with '...Int()'.
++ added wrapper function FreeImage_GetICCProfile(): is the public wrapper function for private function FreeImage_GetICCProfileInt(), returing a real FIICCPROFILE structure.
++ added constant FREE_IMAGE_ICC_COLOR_MODEL_MASK.
++ added enumeration FREE_IMAGE_ICC_COLOR_MODEL.
++ added wrapper function FreeImage_GetICCProfileColorModel(): returns the color profile's color model (FIICCPROFILE.flags member).
++ added wrapper function FreeImage_GetICCProfileSize(): returns the color profile data's size in bytes.
++ added wrapper function FreeImage_GetICCProfileDataPointer(): returns the pointer to the color profile data.
++ added wrapper function FreeImage_HasICCProfile(): returns whether a color profile is available for a dib or not.
+! [Carsten Klein] changed behaviour of wrapper function FreeImage_RescaleEx() and all it's derived functions: no clone is returned if the actual and desired image size are the same.
++ [Carsten Klein] added parameter 'bForceCloneCreation' to wrapper function FreeImage_RescaleEx() and all it's derived functions.
+
+! now FreeImage version 3.9.3
+
+January 09, 2007 - 1.9.4
+! [Carsten Klein] changed scope of declared function FreeImage_GetFileTypeUInt(): is now private according to all other '...Int' functions wrapped by a VB-friendly function.
+! [Carsten Klein] changed scope of declared function FreeImage_GetFIFFromFilenameUInt(): is now private according to all other '...Int' functions wrapped by a VB-friendly function.
+! [Carsten Klein] changed signature of declared functions FreeImage_GetBackgroundColorInt() and FreeImage_SetBackgroundColorInt(): now both have a 'ByRef bkcolor As RGBQUAD' parameter instead of 'ByVal bkcolor As Long'.
++ [Carsten Klein] added declared functions FreeImage_GetBackgroundColorAsLongInt(): this has a 'ByRef bkcolor As Long' parameter and provides the background color as a Long value.
++ [Carsten Klein] added declared functions FreeImage_SetBackgroundColorAsLongInt(): this has a 'ByRef bkcolor As Long' parameter and takes the background color as a Long value.
+! [Carsten Klein] changed signature of wrapper functions FreeImage_GetBackgroundColor() and FreeImage_SetBackgroundColor(): now both have a 'ByRef bkcolor As RGBQUAD' parameter instead of 'ByVal bkcolor As Long'.
++ [Carsten Klein] added wrapper functions FreeImage_GetBackgroundColorAsLong() and FreeImage_SetBackgroundColorAsLong(): both have a 'ByRef bkcolor As Long' parameter and so offer getting and setting the background color through a Long value.
++ [Carsten Klein] added wrapper functions FreeImage_GetBackgroundColorEx() and FreeImage_SetBackgroundColorEx(): both both take 4 ByRef Byte parameters 'Alpha', 'Red', 'Green' and 'Blue', one for each color component.
+
+January 05, 2007 - 1.9.3
++ [Carsten Klein] added wrapper function FreeImage_GetLockedPageNumbersEx(): this returns a real VB-style array of Longs containing the page numbers of all locked pages.
+
+January 02, 2007 - 1.9.2
+* [Carsten Klein] fixed a bug in inline description of function FreeImage_GetPaletteEx(): now tells to use function FreeImage_DestroyLockedArrayRGBQUAD() to free an array returned by this function.
+* [Carsten Klein] fixed some minor bugs in inline documentation.
+* [Carsten Klein] fixed a serious bug in function FreeImage_SaveEx(): parameter 'bUnloadSource' is now interpreted correctly under all circumstances.
+* [Carsten Klein] fixed some minor issues in function FreeImage_SaveEx().
+
+December 29, 2006 - 1.9.1
++ [Carsten Klein] added enumeration item FID_BAYER16x16: now supports Bayer ordered dispersed dot dithering (order 4 dithering matrix).
+
+October 31, 2006 - 1.9
+* [Carsten Klein] adjusted page numbers of the API documentation in header comments in FreeImage function declarations to match FreeImage 3.9.2 API documentation
+! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 2 to match current version 3.9.2
++ [Carsten Klein] added function declaration for FreeImage_JPEGCrop(): added both declaration and Boolean returning wrapper function.
+! [Carsten Klein] changed data type of all occurences of parameter 'Flags' from Long to either FREE_IMAGE_LOAD_OPTIONS or FREE_IMAGE_SAVE_OPTIONS enum. This is true for declared funcitons as well as for wrapper functions.
++ [Carsten Klein] added function declaration for FreeImage_LoadMultiBitmapFromMemory().
++ [Carsten Klein] added wrapper function FreeImage_LoadMultiBitmapFromMemoryEx(): this is dealing with a VB style array (SAFEARRAY) like FreeImage_LoadFromMemoryEx() does.
+
+! now FreeImage version 3.9.2
+
+October 30, 2006 - 1.8
+* [Carsten Klein] fixed a memory leak in wrapper function SavePictureEx(). Thanks to Roogames for reporting that bug.
+! [Carsten Klein] changed return type of wrapper function SavePictureEx() to Boolean.
++ [Carsten Klein] added wrapper function FreeImage_SaveEx() which brings all the features, as there are inline size- and color conversion and format guessing, so far only known from SavePictureEx() for DIBs.
+! [Carsten Klein] changed wrapper function SavePictureEx(): now this is only a thin wrapper for function FreeImage_SaveEx().
++ [Carsten Klein] added enumeration FREE_IMAGE_LOAD_OPTIONS.
+- [Carsten Klein] refactored enumeration FREE_IMAGE_SAVE_OPTIONS: removed unnecessary items from enumeration.
+! [Carsten Klein] changed wrapper function LoadPictureEx(): added parameter 'Options' (enum FREE_IMAGE_LOAD_OPTIONS) to specify image loading options (called 'flags' in FreeImage).
++ [Carsten Klein] added wrapper function FreeImage_LoadEx() which brings all the features, as there are inline size- and color conversion and format guessing, so far only known from LoadPictureEx() for DIBs.
+! [Carsten Klein] changed wrapper function LoadPictureEx(): now this is only a thin wrapper for function FreeImage_LoadEx().
+
+October 13, 2006 - 1.7.2
++ [Carsten Klein] added User32 function GetDesktopWindow()
++ added User32 function GetWindowDC()
+- [Carsten Klein] removed unused constants DI_MASK, DI_IMAGE and DI_NORMAL
++ added GDI32 function GetDeviceCaps() with constants HORZRES and VERTRES
++ added GDI32 function SelectObject()
++ added GDI32 function DeleteObject()
++ added GDI32 function CreateCompatibleBitmap()
++ added GDI32 function CreateCompatibleDC()
++ added GDI32 function BitBlt()
++ [Carsten Klein] added wrapper function FreeImage_CreateFromScreen(): this function lets you capture the whole screen or any certain window
+
+October 10, 2006 - 1.7.1
+! [Carsten Klein] changed parameter name 'Page' into 'hPageDib' in declared function FreeImage_UnlockPage(). 'hPageDib' must be the (dib-)handle obtained from FreeImage_LockPage() and not the page number. Now, the declaration is less confusing. Thanks to Ender Wiggin.
+
+August 4, 2006 - 1.7
+* [Carsten Klein] fixed a bug in pGetTagFromTagPtr(): removed overflow error when converting unsigned short tags (FIDT_SHORT) with values between 32768 and 65535. Thanks to André Hendriks.
+! [Carsten Klein] changed constant FREEIMAGE_RELEASE_SERIAL: set to 1 to match current version 3.9.1
+
+! now FreeImage version 3.9.1
+
+July 17, 2006 - 1.6
++ [Carsten Klein] added more public wrapper functions for tag copying and cloning:
++ added function FreeImage_CopyMetadata()
++ added function FreeImage_CloneMetadata()
+- [Carsten Klein] removed dead API functions, dead structures and dead variables
+* [Carsten Klein] fixed a bug in FreeImage_ConvertColorDepth(): now color images are converted to 24 bits when used with FICF_PREPARE_RESCALE, all others to 8 bit
+
+July 16, 2006 - 1.5.6
++ [Carsten Klein] added more public wrapper functions for VB friendly tag access: these functions deal with a FREE_IMAGE_TAG structure instead of FreeImage's Tag pointer.
++ added function FreeImage_SetMetadataEx()
++ added function FreeImage_CreateTagEx()
++ added function FreeImage_AppendTag()
++ added function FreeImage_RemoveTag()
++ added function FreeImage_RemoveTagEx()
++ added function FreeImage_TagExists()
++ added function FreeImage_TagExistsEx()
++ added function FreeImage_DeleteTagEx()
++ added function FreeImage_CloneTagEx()
++ added function FreeImage_RemoveMetadataModel()
++ added function FreeImage_UpdateMetadata()
++ added function FreeImage_UnsignedLong()
++ added function FreeImage_UnsignedShort()
++ added function FreeImage_CreateRational()
++ added function FreeImage_CreateSignedRational()
++ added function FreeImage_GetImageComment()
++ added function FreeImage_SetImageComment()
++ [Carsten Klein] added some private helper functions to leverage tag updating:
++ added helper function pTagToTagPtr()
++ added helper function pGetValueBuffer()
++ added helper function pGetRationalValueBuffer()
++ added helper function pGetVariantAsByteBuffer()
++ added helper function pGetElementSize()
+
+July 5, 2006 - 1.5.5
+! [Carsten Klein] changed function signature of FreeImage_FindNextMetadataEx(): optional parameter 'Model' is now present; see the function's inline documentation
+
+June 30, 2006 - 1.5.4
+* [Carsten Klein] fixed bug in functions creating a FreeImage DIB from a windows hBitmap: workaround for palettized bitmaps is now implemented
+* fixed function FreeImage_CreateFromOLEPicture()
+* fixed function FreeImage_CreateFromDC()
+
+June 22, 2006 - 1.5.3
+! [Carsten Klein] changed function declaration of FreeImage_GetMetadataInt(): parameter 'model' is now 'ByVal' and Tag is a Long pointer
+! [Carsten Klein] changed function declaration of FreeImage_SetMetadataInt(): parameter 'model' is now 'ByVal' and Tag is a Long pointer
+! [Carsten Klein] changed function declaration of FreeImage_GetMetadata(): parameter Tag is a Long pointer now
+! [Carsten Klein] changed function declaration of FreeImage_SetMetadata(): parameter Tag is a Long pointer now
++ [Carsten Klein] added function declarations for tag creation and destruction:
++ added declaration for function FreeImage_CreateTag()
++ added declaration for procedure FreeImage_DeleteTag()
++ added declaration for function FreeImage_CloneTag()
++ [Carsten Klein] added new items to structure FREE_IMAGE_TAG:
++ added item 'Model As FREE_IMAGE_MDMODEL'
++ added item 'TagPtr As Long'
++ [Carsten Klein] added wrapper functions for more VB friendly Tag access: these functions deal with a FREE_IMAGE_TAG structure instead of FreeImage's Tag pointer.
++ added function FreeImage_FindFirstMetadataEx()
++ added function FreeImage_FindNextMetadataEx()
++ added function FreeImage_GetAllMetadataTags()
++ added function FreeImage_GetMetadataEx()
+* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations
+- [Carsten Klein] removed workaround for thresholding and dithering non-MINISBLACK 8 bit images in function FreeImage_ConvertColorDepth(): was fixed in FreeImage 3.9.0
+* [Carsten Klein] fixed all pending issues in function FreeImage_PaintDC(): is now in production state
+
+June 14, 2006 - 1.5.2
+! [Carsten Klein] changed signature of function FreeImage_CreateMask()
++ [Carsten Klein] added function FreeImage_CreateMaskImage(): this creates a monochrome mask from a source image
++ [Carsten Klein] added function FreeImage_CreateMaskInPlace(): this creates a monochrome mask from a source image
++ [Carsten Klein] added enumeration FREE_IMAGE_ICON_TRANSPARENCY_OPTION_FLAGS
++ [Carsten Klein] added wrapper function FreeImage_CreateSimpleBWMaskImage(): wrapper for FreeImage_CreateMaskImage() with reduced number of parameters; creates a b/w mask
++ [Carsten Klein] added wrapper function FreeImage_CreateSimpleBWMaskInPlace(): wrapper for FreeImage_CreateMaskInPlace() with reduced number of parameters; creates a b/w mask
++ [Carsten Klein] added function declaration for FreeImage_MakeThumbnail()
++ [Carsten Klein] added function for FreeImage_GetOlePictureThumbnail()
++ [Carsten Klein] added function for FreeImage_MakeThumbnailIOP()
++ [Carsten Klein] documented function FreeImage_ReadMemoryEx()
++ [Carsten Klein] documented function FreeImage_WriteMemoryEx()
+! [Carsten Klein] divided FreeImage_TagFromPointer into an interface only function with a private helper function pGetTagFromTagPtr():
++ added helper function pGetTagFromTagPtr()
+! [Carsten Klein] added private helper functions to leverage the FIDT_RATIONAL and FIDT_SRATIONAL data type:
++ added helper function pNormalizeRational()
++ added helper function pNormalizeSRational()
++ added helper function gcd()
++ added helper function floor()
+! [Carsten Klein] changed name of structure 'FITAG_int' to 'FITAG': is now as in FreeImage library
+! [Carsten Klein] changed name of structure 'FITAG' to 'FREE_IMAGE_TAG': this new structure plays an important role in the wrapper's new VB friendly tag accessing concept
+! [Carsten Klein] changed function declaration of FreeImage_GetMetadataCount(): parameter 'model' is now 'ByVal'
+! [Carsten Klein] changed function declaration of FreeImage_TagToString(): parameter 'model' is now 'ByVal' and function returns a Long
+! [Carsten Klein] renamed function declaration of FreeImage_TagToString() to FreeImage_TagToStringInt(): function is now Private and wrapped by a VB String returning function
++ [Carsten Klein] added wrapper function FreeImage_TagToString() returning a real VB String
++ [Carsten Klein] added structure FIRATIONAL: structure to hold an image tag's rational value
++ [Carsten Klein] added new items to structure FREE_IMAGE_TAG:
++ added item 'StringValue As String'
++ added item 'Palette() As RGBQUAD'
++ added item 'RationalValue() As FIRATIONAL'
+
+June 13, 2006 - 1.5.1
+! [Carsten Klein] changed version constant 'FREEIMAGE_MINOR_VERSION' to 9 to meet version 3.9.0
+* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations to match FreeImage 3.9.0 API documentation
++ [Carsten Klein] added function declaration for new Memory I/O functions in 3.9.0
++ added declaration FreeImage_ReadMemory()
++ added declaration FreeImage_WriteMemory()
+! [Carsten Klein] changed/added optional parameter 'element_size' to private function pGetMemoryBlockPtrFromVariant(): caller now can get size in bytes one array element
++ [Carsten Klein] added wrapper functions for new Memory I/O functions in 3.9.0
++ added function FreeImage_ReadMemoryEx()
++ added function FreeImage_WriteMemoryEx()
++ [Carsten Klein] added constants and updated enumerations for new 3.9.0 file formats 'FAXG3' and 'SGI'
++ [Carsten Klein] added Windows GDI icon related declarations:
++ added function declaration for CreateIconIndirect()
++ added function declaration for DestroyIcon()
++ added structure ICONINFO
++ [Carsten Klein] added function FreeImage_GetIcon(): returns a hIcon handle
++ [Carsten Klein] added function FreeImage_GetOlePictureIcon(): returns a VB Picture object of type vbPicTypeIcon
++ [Carsten Klein] added enumeration FREE_IMAGE_MASK_FLAGS
++ [Carsten Klein] added function FreeImage_CreateMaskColors(): returns an array filled with items from an argument list; synonym for VB's Array() function
++ [Carsten Klein] added enumeration FREE_IMAGE_teMask(): this creates a monochrome mask from a source image
++ [Carsten Klein] added function FreeImage_CreaMASK_CREATION_OPTION_FLAGS
+
+! now FreeImage version 3.9.0
+
+June 12, 2006 - 1.5
+* [Carsten Klein] fixed bug in wrapper function FreeImage_PaintDCEx(): now handles boolean test correctly: 'If ((hDC <> 0) And (hDIB <> 0)) Then -> Thanks to ender_wiggin for reporting that bug.
++ [Carsten Klein] added private function pGetIOlePictureFromContainer(): used to get IPicture from image hosting control (Form, PictureBox) including custom drawings
++ [Carsten Klein] added wrapper function FreeImage_CreateFromImageContainer(): used to create FreeImage DIB from image hosting control (Form, PictureBox) including custom drawings
++ [Carsten Klein] added wrapper function SaveImageContainerEx(): derivate of wrapper function 'SavePictureEx()': saves content of image hosting control (Form, PictureBox) including custom drawings
+
+February 27, 2006 - 1.4.8
++ [Carsten Klein] added inline documentation for these wrapper functions:
++ documented function FreeImage_CompareColorsLongLong()
++ documented function FreeImage_CompareColorsRGBTRIPLELong()
++ documented function FreeImage_CompareColorsRGBQUADLong()
++ documented function FreeImage_SearchPalette()
+! [Carsten Klein] changed and updated general remarks in section "General notes on implementation and design"
+! [Carsten Klein] changed all function declarations of FreeImage functions that return a BOOL in C/C++: see "Functions returning Booleans" in section "General notes on implementation and design"
+! [Carsten Klein] changed all function signatures of functions that are derived from or extend FreeImage BOOL functions: see "Functions returning Booleans" in section "General notes on implementation and design"
++ [Carsten Klein] added wrapper functions for all FreeImage functions that return a BOOL in C/C++: see "Functions returning Booleans" in section "General notes on implementation and design"
++ [Carsten Klein] added wrapper function FreeImage_CreateFromDC(): creates an DIB from a DC. Thanks to Evan (wxforecaster) for this suggestion.
++ [Carsten Klein] added declaration of GDI function GetCurrentObject() and constant OBJ_BITMAP
++ [Carsten Klein] added wrapper function FreeImage_IsAvailable(): used to test for existence of FreeImage Library (FreeImage.dll)
+
+February 9, 2006 - 1.4.7
++ [Carsten Klein] added private helper function pGetPreviousColorDepth()
++ [Carsten Klein] added private helper function pGetNextColorDepth()
+! [Carsten Klein] changed/extended signature of wrapper function SavePictureEx(): now includes a parameter 'ColorDepth'
++ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_DEPTH
++ [Carsten Klein] added error handling capabilities to wrapper function SavePictureEx()
++ [Carsten Klein] added/updated inline documentation of wrapper function SavePictureEx()
+
+October 31, 2005 - 1.4.6
++ [Carsten Klein] added wrapper function FreeImage_SwapColorLong(): this converts from a RGB to a BGR color value stored in a Long and vice versa
+
+October 27, 2005 - 1.4.5
++ [Carsten Klein] added function FreeImage_IsTransparencyTableTransparent(): checks for transparency directly on the transparency table
+
+October 13, 2005 - 1.4.4
++ [Carsten Klein] added some functions to compare colors in different formats and with tolerance:
++ added function FreeImage_CompareColorsLongLong()
++ added function FreeImage_CompareColorsRGBTRIPLELong()
++ added function FreeImage_CompareColorsRGBQUADLong()
++ [Carsten Klein] added enumeration FREE_IMAGE_COLOR_FORMAT_FLAGS
++ [Carsten Klein] added enumeration FREE_IMAGE_TRANSPARENCY_STATE_FLAGS
++ [Carsten Klein] added function FreeImage_SearchPalette(): to search the palette index for a given color
+
+October 13, 2005 - 1.4.3
++ [Carsten Klein] added additional function declaration FreeImage_SetPixelColorByLong(): now color values may be provided in a long value
++ [Carsten Klein] added additional function declaration FreeImage_GetPixelColorByLong(): now color values may be received in a long value
++ [Carsten Klein] added function FreeImage_SetPixelColorEx(): color values may be provided by four different byte values
++ [Carsten Klein] added function FreeImage_GetPixelColorEx(): color values are returned through four different byte values
+
+October 11, 2005 - 1.4.2
+* [Carsten Klein] fixed bug in wrapper function FreeImage_GetBitsExRGBQUAD(): now tests for and works with 32 bit images
+
+October 10, 2005 - 1.4.1
+* [Carsten Klein] fixed serious bug in FreeImage_GetBitsEx...() functions: created custom array descriptor now really has two dimensions
+* fixed wrapper function FreeImage_GetBitsEx()
+* fixed wrapper function FreeImage_GetBitsExRGBTRIPLE()
+* fixed wrapper function FreeImage_GetBitsExRGBQUAD()
+
+September 9, 2005 - 1.4
+! [Carsten Klein] changed wrapper function FreeImage_ConvertColorDepth(): now uses FreeImage_ConvertToGreyscale
++ [Carsten Klein] added version numbers to change log
++ [Carsten Klein] added comments to IOlePicture aware toolkit and conversion functions
+* [Carsten Klein] fixed and adjusted page numbers of the API documentation in header comments in FreeImage function declarations
+
+! now FreeImage version 3.8.0
+
+September 8, 2005 - 1.3.5
+! [Carsten Klein] changed version constant 'FREEIMAGE_MINOR_VERSION' to 8 to meet version 3.8.0
++ [Carsten Klein] added function declarations for UNICODE dealing functions with additional token 'Int' appended:
++ added function FreeImage_LoadUInt()
++ added function FreeImage_SaveUInt()
++ added function FreeImage_GetFileTypeUInt()
++ added function FreeImage_GetFIFFromFilenameUInt()
++ [Carsten Klein] added wrapper functions to ease the use of UNICODE dealing functions:
++ added function FreeImage_LoadU()
++ added function FreeImage_SaveU()
++ added function FreeImage_GetFileTypeU()
++ added function FreeImage_GetFIFFromFilenameU()
++ [Carsten Klein] added function declaration for FreeImage_ConvertToGreyscale()
+
+July 18, 2005 - 1.3.4
+! [Carsten Klein] changed inline comments in these wrapper functions:
+! changed FreeImage_GetBitsEx(): mixed up width and height in SAFEAARAY creation
+! changed FreeImage_GetBitsExRGBTRIPLE(): mixed up width and height in SAFEAARAY creation
+! changed FreeImage_GetBitsExRGBQUAD(): mixed up width and height in SAFEAARAY creation
++ [Carsten Klein] added wrapper function FreeImage_GetScanLinesRGBTRIPLE():
+
+June 30, 2005 - 1.3.3
++ [Carsten Klein] added Kernel32 function FillMemory()
+
+June 24, 2005 - 1.3.2
++ [Carsten Klein] added pixel access functions FreeImage_GetBitsExRGBTRIPLE() and FreeImage_GetBitsExRGBQUAD()
++ [Carsten Klein] added IOlePicture based wrapper function FreeImage_ConvertColorDepthIOP()
++ [Carsten Klein] added IOlePicture based wrapper functions for FreeImage_RescaleIOP():
++ added function FreeImage_FreeImage_RescaleByPixelIOP()
++ added function FreeImage_FreeImage_RescaleByPercentIOP()
++ added function FreeImage_FreeImage_RescaleByFactorIOP()
++ [Carsten Klein] added IOlePicture based wrapper function FreeImage_RescaleIOP()
+* [Carsten Klein] fixed a bug in FreeImage_GetOlePicture(): now OlePictures returned through IPicture may be used directly by other functions accepting IPicture types without any assignment to IPictureDisp
+
+June 24, 2005 - 1.3.1
+! [Carsten Klein] changed inproper function declaration of function FreeImage_AdjustCurve(): now parameter 'LUT' is passed ByVal
++ [Carsten Klein] added wrapper function FreeImage_AdjustCurveEx()
++ [Carsten Klein] added IOlePicture based wrapper functions for FreeImage toolkit functions:
++ added function FreeImage_RotateClassicIOP()
++ added function FreeImage_RotateExIOP()
++ added function FreeImage_FlipHorizontalIOP()
++ added function FreeImage_FlipVerticalIOP()
++ added function FreeImage_AdjustCurveIOP()
++ added function FreeImage_AdjustGammaIOP()
++ added function FreeImage_AdjustBrightnessIOP()
++ added function FreeImage_AdjustContrastIOP()
++ added function FreeImage_InvertIOP()
++ added function FreeImage_GetChannelIOP()
++ added function FreeImage_CopyIOP()
++ added function FreeImage_PasteIOP()
+
+June 22, 2005 - 1.3
++ [Carsten Klein] added inline comments and documentation for pixel access functions
+
+June 18, 2005 - 1.2.9
++ [Carsten Klein] added function FreeImage_GetBitsEx()
++ [Carsten Klein] added structure SAFEARRAY2D to create 2 dimensional custom arrays
++ [Carsten Klein] added function declarations for converting scanlines to 4 bpp:
++ added declaration for FreeImage_ConvertLine1To4()
++ added declaration for FreeImage_ConvertLine8To4()
++ added declaration for FreeImage_ConvertLine16To4_555()
++ added declaration for FreeImage_ConvertLine16To4_565()
++ added declaration for FreeImage_ConvertLine24To4()
++ added declaration for FreeImage_ConvertLine32To4()
+
+June 16, 2005 - 1.2.8
+! [Carsten Klein] changed inproper function declaration for all functions FreeImage_ConvertLineXXXX(): now parameters 'target' and 'Source' are passed ByVal
+
+June 15, 2005 - 1.2.7
++ [Carsten Klein] added function FreeImage_DestroyLockedArrayByPtr() to destroy a locked array by it's pointer (VB can't pass a array of structures through a Variant type)
++ [Carsten Klein] added some wrapper functions for FreeImage_DestroyLockedArrayByPtr() for common FreeImage structures:
++ added function FreeImage_DestroyLockedArrayRGBTRIPLE()
++ added function FreeImage_DestroyLockedArrayRGBQUAD()
++ added function FreeImage_DestroyLockedArrayFICOMPLEX()
++ added function FreeImage_DestroyLockedArrayFIRGB16()
++ added function FreeImage_DestroyLockedArrayFIRGBA16()
++ added function FreeImage_DestroyLockedArrayFIRGBF()
++ added function FreeImage_DestroyLockedArrayFIRGBAF()
++ [Carsten Klein] added functions to return scanlines as VB style arrays in all supported FreeImage formats:
++ added function FreeImage_GetScanLineBITMAP8()
++ added function FreeImage_GetScanLineBITMAP16()
++ added function FreeImage_GetScanLineBITMAP24()
++ added function FreeImage_GetScanLineBITMAP32()
++ added function FreeImage_GetScanLineINT16()
++ added function FreeImage_GetScanLineINT32()
++ added function FreeImage_GetScanLineFLOAT()
++ added function FreeImage_GetScanLineDOUBLE()
++ added function FreeImage_GetScanLineCOMPLEX()
++ added function FreeImage_GetScanLineRGB16()
++ added function FreeImage_GetScanLineRGBA16()
++ added function FreeImage_GetScanLineRGBF()
++ added function FreeImage_GetScanLineRGBAF()
+
+June 14, 2005 - 1.2.6
+! [Carsten Klein] updated documentation on array-dealing functions using arrays with custom array descriptors
++ [Carsten Klein] added function FreeImage_DestroyLockedArray() to destroy a self created array 'FADF_AUTO Or FADF_FIXEDSIZE' array
++ [Carsten Klein] added function FreeImage_GetPaletteExLong() to return palette data in an array of type Long
++ [Carsten Klein] added parameters 'lPaletteSize', 'vntReservePalette' and 'lReserveSize' to FreeImage_ConvertColorDepth()
+
+June 13, 2005 - 1.2.5
+* [Carsten Klein] fixed a bug in helper function pGetMemoryBlockPtrFromVariant(): now 'size_in_bytes' will never exceed the size of an array provided
+
+June 12, 2005 - 1.2.4
++ [Carsten Klein] added ZLib compression function wrappers dealing with VB style arrays:
++ added function FreeImage_ZLibCompressVB()
++ added function FreeImage_ZLibUncompressVB()
++ added function FreeImage_ZLibGZipVB()
++ added function FreeImage_ZLibGUnzipVB()
+
+June 10, 2005 - 1.2.3
++ [Carsten Klein] added ZLib compression function wrappers dealing with VB style arrays:
++ added function FreeImage_ZLibCompressEx()
++ added function FreeImage_ZLibUncompressEx()
++ added function FreeImage_ZLibGZipEx()
++ added function FreeImage_ZLibCRC32Ex()
++ added function FreeImage_ZLibGUnzipEx()
++ [Carsten Klein] added more VB friendly ZLib compression function wrappers:
++ added function FreeImage_ZLibCompressVB()
++ added function FreeImage_ZLibUncompressVB()
++ added function FreeImage_ZLibGZipVB()
++ added function FreeImage_ZLibGUnzipVB()
+! [Carsten Klein] fixed wrong function declaration of functions FreeImage_ZLibGUnzip(): alias was '_FreeImage_ZLibZlibGUnzip@16' (double ZLib)
+! [Carsten Klein] fixed function pGetArrayPtrFromVariantArray() that now can deal with uninitialized arrays
+! fixed function pGetMemoryBlockPtrFromVariant() that now can deal with uninitialized arrays
+! [Carsten Klein] fixed wrong function declaration of functions FreeImage_AdjustBrightness(): ...@8 -> ...@12
+! fixed wrong function declaration of functions FreeImage_AdjustContrast(): ...@8 -> ...@12
+! fixed wrong function declaration of functions FreeImage_AdjustGamma(): ...@8 -> ...@12
+! fixed wrong function declaration of functions FreeImage_RotateClassic(): ...@8 -> ...@12
+! fixed wrong function declaration of functions FreeImage_RotateEx(): ...@28 -> ...@48
+
+June 9, 2005 - 1.2.2
+! [Carsten Klein] fixed wrong function declaration of function FreeImage_OpenMultiBitmap(): added parameter 'flags' (...@20 -> ...@24)
+
+June 8, 2005 - 1.2.1
+! [Carsten Klein] refactored function FreeImage_LoadFromMemoryEx(): now using pGetMemoryBlockPtrFromVariant()
++ [Carsten Klein] added private function pGetMemoryBlockPtrFromVariant() to get poiner and size of a memory block from a Variant parameter
+! [Carsten Klein] changed declaration of ZLib related functions: 'target' and 'Source' are now 'ByVal Long'
+
+June 7, 2005 - 1.2
++ [Carsten Klein] added some more inline comments and documentation
++ [Carsten Klein] added optional parameter 'bUnloadSource' to function FreeImage_SaveToMemoryEx()
++ added optional parameter 'bUnloadSource' to function FreeImage_SaveToMemoryEx2()
++ [Carsten Klein] added optional parameter 'InPercent' to function SavePictureEx()
+! implemented the capability to resize the image on saving in function SavePictureEx()
++ [Carsten Klein] added parameters 'InPercent' and 'Format' to function LoadPictureEx()
+* [Carsten Klein] fixed wrong function declaration of function FreeImage_JPEGTransform() (...@12 -> ...@16)
+
+June 6, 2005 - 1.1.2
++ [Carsten Klein] added some more inline comments and documentation
+
+May 30, 2005 - 1.1.1
+* [Carsten Klein] fixed percent calculating bug in function FreeImage_RescaleEx()
+! changed behaviour of parameter 'bIsPercentValue' -> it now has no effect on integer values
++ added function FreeImage_RescaleByPixel() to avoid confusion with overloading
++ added function FreeImage_RescaleByPercent() to avoid confusion with overloading
++ added function FreeImage_RescaleByFactor() to avoid confusion with overloading
+! [Carsten Klein] changed name of parameter 'bUnloadDIB' to 'bUnloadSource' of function FreeImage_GetOlePicture()
++ [Carsten Klein] added some more inline comments and documentation
+* [Carsten Klein] fixed a potential runtime error in function FreeImage_SetTransparencyTableEx(): 'Count' will no longer exceed 256
+
+May 24, 2005 - 1.1
++ [Carsten Klein] added a new VB wrapper
diff --git a/Wrapper/VB6/modFreeImage.bas b/Wrapper/VB6/modFreeImage.bas
new file mode 100644
index 0000000..373d28f
--- /dev/null
+++ b/Wrapper/VB6/modFreeImage.bas
@@ -0,0 +1,512 @@
+Attribute VB_Name = "FreeImage"
+Option Explicit
+
+Const unix As Long = 1
+Const linux As Long = 1
+Const i386 As Long = 1
+Const FREEIMAGE_MAJOR_VERSION As Long = 3
+Const FREEIMAGE_MINOR_VERSION As Long = 7
+Const FREEIMAGE_RELEASE_SERIAL As Long = 0
+Const SEEK_SET As Long = 0
+Const SEEK_CUR As Long = 1
+Const SEEK_END As Long = 2
+Const FI_RGBA_RED As Long = 2
+Const FI_RGBA_GREEN As Long = 1
+Const FI_RGBA_BLUE As Long = 0
+Const FI_RGBA_ALPHA As Long = 3
+Const FI_RGBA_RED_MASK As Long = &H00FF0000
+Const FI_RGBA_GREEN_MASK As Long = &H0000FF00
+Const FI_RGBA_BLUE_MASK As Long = &H000000FF
+Const FI_RGBA_ALPHA_MASK As Long = &HFF000000
+Const FI_RGBA_RED_SHIFT As Long = 16
+Const FI_RGBA_GREEN_SHIFT As Long = 8
+Const FI_RGBA_BLUE_SHIFT As Long = 0
+Const FI_RGBA_ALPHA_SHIFT As Long = 24
+Const FI16_555_RED_MASK As Long = &H7C00
+Const FI16_555_GREEN_MASK As Long = &H03E0
+Const FI16_555_BLUE_MASK As Long = &H001F
+Const FI16_555_RED_SHIFT As Long = 10
+Const FI16_555_GREEN_SHIFT As Long = 5
+Const FI16_555_BLUE_SHIFT As Long = 0
+Const FI16_565_RED_MASK As Long = &HF800
+Const FI16_565_GREEN_MASK As Long = &H07E0
+Const FI16_565_BLUE_MASK As Long = &H001F
+Const FI16_565_RED_SHIFT As Long = 11
+Const FI16_565_GREEN_SHIFT As Long = 5
+Const FI16_565_BLUE_SHIFT As Long = 0
+Const FIICC_DEFAULT As Long = &H00
+Const FIICC_COLOR_IS_CMYK As Long = &H01
+Const BMP_DEFAULT As Long = 0
+Const BMP_SAVE_RLE As Long = 1
+Const CUT_DEFAULT As Long = 0
+Const DDS_DEFAULT As Long = 0
+Const GIF_DEFAULT As Long = 0
+Const GIF_LOAD256 As Long = 1
+Const GIF_PLAYBACK As Long = 2
+Const HDR_DEFAULT As Long = 0
+Const ICO_DEFAULT As Long = 0
+Const ICO_MAKEALPHA As Long = 1
+Const IFF_DEFAULT As Long = 0
+Const JPEG_DEFAULT As Long = 0
+Const JPEG_FAST As Long = 1
+Const JPEG_ACCURATE As Long = 2
+Const JPEG_QUALITYSUPERB As Long = &H80
+Const JPEG_QUALITYGOOD As Long = &H100
+Const JPEG_QUALITYNORMAL As Long = &H200
+Const JPEG_QUALITYAVERAGE As Long = &H400
+Const JPEG_QUALITYBAD As Long = &H800
+Const JPEG_CMYK As Long = &H1000
+Const KOALA_DEFAULT As Long = 0
+Const LBM_DEFAULT As Long = 0
+Const MNG_DEFAULT As Long = 0
+Const PCD_DEFAULT As Long = 0
+Const PCD_BASE As Long = 1
+Const PCD_BASEDIV4 As Long = 2
+Const PCD_BASEDIV16 As Long = 3
+Const PCX_DEFAULT As Long = 0
+Const PNG_DEFAULT As Long = 0
+Const PNG_IGNOREGAMMA As Long = 1
+Const PNM_DEFAULT As Long = 0
+Const PNM_SAVE_RAW As Long = 0
+Const PNM_SAVE_ASCII As Long = 1
+Const PSD_DEFAULT As Long = 0
+Const RAS_DEFAULT As Long = 0
+Const TARGA_DEFAULT As Long = 0
+Const TARGA_LOAD_RGB888 As Long = 1
+Const TIFF_DEFAULT As Long = 0
+Const TIFF_CMYK As Long = &H0001
+Const TIFF_PACKBITS As Long = &H0100
+Const TIFF_DEFLATE As Long = &H0200
+Const TIFF_ADOBE_DEFLATE As Long = &H0400
+Const TIFF_NONE As Long = &H0800
+Const TIFF_CCITTFAX3 As Long = &H1000
+Const TIFF_CCITTFAX4 As Long = &H2000
+Const TIFF_LZW As Long = &H4000
+Const TIFF_JPEG As Long = &H8000
+Const WBMP_DEFAULT As Long = 0
+Const XBM_DEFAULT As Long = 0
+Const XPM_DEFAULT As Long = 0
+
+Public Enum FREE_IMAGE_FORMAT
+ FIF_UNKNOWN = -1
+ FIF_BMP = 0
+ FIF_ICO = 1
+ FIF_JPEG = 2
+ FIF_JNG = 3
+ FIF_KOALA = 4
+ FIF_LBM = 5
+ FIF_IFF = FIF_LBM
+ FIF_MNG = 6
+ FIF_PBM = 7
+ FIF_PBMRAW = 8
+ FIF_PCD = 9
+ FIF_PCX = 10
+ FIF_PGM = 11
+ FIF_PGMRAW = 12
+ FIF_PNG = 13
+ FIF_PPM = 14
+ FIF_PPMRAW = 15
+ FIF_RAS = 16
+ FIF_TARGA = 17
+ FIF_TIFF = 18
+ FIF_WBMP = 19
+ FIF_PSD = 20
+ FIF_CUT = 21
+ FIF_XBM = 22
+ FIF_XPM = 23
+ FIF_DDS = 24
+ FIF_GIF = 25
+ FIF_HDR = 26
+End Enum
+Public Enum FREE_IMAGE_TYPE
+ FIT_UNKNOWN = 0
+ FIT_BITMAP = 1
+ FIT_UINT16 = 2
+ FIT_INT16 = 3
+ FIT_UINT32 = 4
+ FIT_INT32 = 5
+ FIT_FLOAT = 6
+ FIT_DOUBLE = 7
+ FIT_COMPLEX = 8
+ FIT_RGB16 = 9
+ FIT_RGBA16 = 10
+ FIT_RGBF = 11
+ FIT_RGBAF = 12
+End Enum
+Public Enum FREE_IMAGE_COLOR_TYPE
+ FIC_MINISWHITE = 0
+ FIC_MINISBLACK = 1
+ FIC_RGB = 2
+ FIC_PALETTE = 3
+ FIC_RGBALPHA = 4
+ FIC_CMYK = 5
+End Enum
+Public Enum FREE_IMAGE_QUANTIZE
+ FIQ_WUQUANT = 0
+ FIQ_NNQUANT = 1
+End Enum
+Public Enum FREE_IMAGE_DITHER
+ FID_FS = 0
+ FID_BAYER4x4 = 1
+ FID_BAYER8x8 = 2
+ FID_CLUSTER6x6 = 3
+ FID_CLUSTER8x8 = 4
+ FID_CLUSTER16x16 = 5
+End Enum
+Public Enum FREE_IMAGE_JPEG_OPERATION
+ FIJPEG_OP_NONE = 0
+ FIJPEG_OP_FLIP_H = 1
+ FIJPEG_OP_FLIP_V = 2
+ FIJPEG_OP_TRANSPOSE = 3
+ FIJPEG_OP_TRANSVERSE = 4
+ FIJPEG_OP_ROTATE_90 = 5
+ FIJPEG_OP_ROTATE_180 = 6
+ FIJPEG_OP_ROTATE_270 = 7
+End Enum
+Public Enum FREE_IMAGE_TMO
+ FITMO_DRAGO03 = 0
+ FITMO_REINHARD05 = 1
+End Enum
+Public Enum FREE_IMAGE_FILTER
+ FILTER_BOX = 0
+ FILTER_BICUBIC = 1
+ FILTER_BILINEAR = 2
+ FILTER_BSPLINE = 3
+ FILTER_CATMULLROM = 4
+ FILTER_LANCZOS3 = 5
+End Enum
+Public Enum FREE_IMAGE_COLOR_CHANNEL
+ FICC_RGB = 0
+ FICC_RED = 1
+ FICC_GREEN = 2
+ FICC_BLUE = 3
+ FICC_ALPHA = 4
+ FICC_BLACK = 5
+ FICC_REAL = 6
+ FICC_IMAG = 7
+ FICC_MAG = 8
+ FICC_PHASE = 9
+End Enum
+Public Enum FREE_IMAGE_MDTYPE
+ FIDT_NOTYPE = 0
+ FIDT_BYTE = 1
+ FIDT_ASCII = 2
+ FIDT_SHORT = 3
+ FIDT_LONG = 4
+ FIDT_RATIONAL = 5
+ FIDT_SBYTE = 6
+ FIDT_UNDEFINED = 7
+ FIDT_SSHORT = 8
+ FIDT_SLONG = 9
+ FIDT_SRATIONAL = 10
+ FIDT_FLOAT = 11
+ FIDT_DOUBLE = 12
+ FIDT_IFD = 13
+ FIDT_PALETTE = 14
+End Enum
+Public Enum FREE_IMAGE_MDMODEL
+ FIMD_NODATA = -1
+ FIMD_COMMENTS = 0
+ FIMD_EXIF_MAIN = 1
+ FIMD_EXIF_EXIF = 2
+ FIMD_EXIF_GPS = 3
+ FIMD_EXIF_MAKERNOTE = 4
+ FIMD_EXIF_INTEROP = 5
+ FIMD_IPTC = 6
+ FIMD_XMP = 7
+ FIMD_GEOTIFF = 8
+ FIMD_ANIMATION = 9
+ FIMD_CUSTOM = 10
+End Enum
+
+Public Type FIBITMAP
+ data As Long
+End Type
+Public Type FIMULTIBITMAP
+ data As Long
+End Type
+Public Type RGBQUAD
+ rgbBlue As Byte
+ rgbGreen As Byte
+ rgbRed As Byte
+ rgbReserved As Byte
+End Type
+Public Type RGBTRIPLE
+ rgbtBlue As Byte
+ rgbtGreen As Byte
+ rgbtRed As Byte
+End Type
+Public Type BITMAPINFOHEADER
+ biSize As Long
+ biWidth As Long
+ biHeight As Long
+ biPlanes As Integer
+ biBitCount As Integer
+ biCompression As Long
+ biSizeImage As Long
+ biXPelsPerMeter As Long
+ biYPelsPerMeter As Long
+ biClrUsed As Long
+ biClrImportant As Long
+End Type
+Public Type BITMAPINFO
+ bmiHeader As BITMAPINFOHEADER
+ bmiColors(0) As RGBQUAD
+End Type
+Public Type FIRGB16
+ red As Integer
+ green As Integer
+ blue As Integer
+End Type
+Public Type FIRGBA16
+ red As Integer
+ green As Integer
+ blue As Integer
+ alpha As Integer
+End Type
+Public Type FIRGBF
+ red As Long
+ green As Long
+ blue As Long
+End Type
+Public Type FIRGBAF
+ red As Long
+ green As Long
+ blue As Long
+ alpha As Long
+End Type
+Public Type FICOMPLEX
+ r As Double
+ i As Double
+End Type
+Public Type FIICCPROFILE
+ flags As Integer
+ size As Long
+ data As Long
+End Type
+Public Type FIMETADATA
+ data As Long
+End Type
+Public Type FITAG
+ data As Long
+End Type
+Public Type FreeImageIO
+ read_proc As Long
+ write_proc As Long
+ seek_proc As Long
+ tell_proc As Long
+End Type
+Public Type FIMEMORY
+ data As Long
+End Type
+Public Type Plugin
+ format_proc As Long
+ description_proc As Long
+ extension_proc As Long
+ regexpr_proc As Long
+ open_proc As Long
+ close_proc As Long
+ pagecount_proc As Long
+ pagecapability_proc As Long
+ load_proc As Long
+ save_proc As Long
+ validate_proc As Long
+ mime_proc As Long
+ supports_export_bpp_proc As Long
+ supports_export_type_proc As Long
+ supports_icc_profiles_proc As Long
+End Type
+
+Public Declare Sub FreeImage_Initialise Lib "FreeImage.dll" Alias "_FreeImage_Initialise@4" (Optional ByVal load_local_plugins_only As Long = 0)
+Public Declare Sub FreeImage_DeInitialise Lib "FreeImage.dll" Alias "_FreeImage_DeInitialise@0" ()
+Public Declare Function FreeImage_GetVersion Lib "FreeImage.dll" Alias "_FreeImage_GetVersion@0" () As Long
+Public Declare Function FreeImage_GetCopyrightMessage Lib "FreeImage.dll" Alias "_FreeImage_GetCopyrightMessage@0" () As Long
+Public Declare Sub FreeImage_OutputMessageProc Lib "FreeImage.dll" Alias "_FreeImage_OutputMessageProc@8" (ByVal fif As Long, ByVal fmt As String, ParamArray VarArgs() As Variant)
+Public Declare Sub FreeImage_SetOutputMessage Lib "FreeImage.dll" Alias "_FreeImage_SetOutputMessage@4" (ByVal omf As Long)
+Public Declare Function FreeImage_Allocate Lib "FreeImage.dll" Alias "_FreeImage_Allocate@24" (ByVal width As Long, ByVal height As Long, ByVal bpp As Long, Optional ByVal red_mask As Long = 0, Optional ByVal green_mask As Long = 0, Optional ByVal blue_mask As Long = 0) As Long
+Public Declare Function FreeImage_AllocateT Lib "FreeImage.dll" Alias "_FreeImage_AllocateT@28" (ByVal type_ As FREE_IMAGE_TYPE, ByVal width As Long, ByVal height As Long, Optional ByVal bpp As Long = 8, Optional ByVal red_mask As Long = 0, Optional ByVal green_mask As Long = 0, Optional ByVal blue_mask As Long = 0) As Long
+Public Declare Function FreeImage_Clone Lib "FreeImage.dll" Alias "_FreeImage_Clone@4" (ByVal dib As Long) As Long
+Public Declare Sub FreeImage_Unload Lib "FreeImage.dll" Alias "_FreeImage_Unload@4" (ByVal dib As Long)
+Public Declare Function FreeImage_Load Lib "FreeImage.dll" Alias "_FreeImage_Load@12" (ByVal fif As FREE_IMAGE_FORMAT, ByVal filename As String, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_LoadFromHandle Lib "FreeImage.dll" Alias "_FreeImage_LoadFromHandle@16" (ByVal fif As FREE_IMAGE_FORMAT, ByVal io As Long, ByVal handle As Long, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_Save Lib "FreeImage.dll" Alias "_FreeImage_Save@16" (ByVal fif As FREE_IMAGE_FORMAT, ByVal dib As Long, ByVal filename As String, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_SaveToHandle Lib "FreeImage.dll" Alias "_FreeImage_SaveToHandle@20" (ByVal fif As FREE_IMAGE_FORMAT, ByVal dib As Long, ByVal io As Long, ByVal handle As Long, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_OpenMemory Lib "FreeImage.dll" Alias "_FreeImage_OpenMemory@8" (Optional ByRef data As Long = 0, Optional ByVal size_in_bytes As Long = 0) As Long
+Public Declare Sub FreeImage_CloseMemory Lib "FreeImage.dll" Alias "_FreeImage_CloseMemory@4" (ByVal stream As Long)
+Public Declare Function FreeImage_LoadFromMemory Lib "FreeImage.dll" Alias "_FreeImage_LoadFromMemory@12" (ByVal fif As FREE_IMAGE_FORMAT, ByVal stream As Long, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_SaveToMemory Lib "FreeImage.dll" Alias "_FreeImage_SaveToMemory@16" (ByVal fif As FREE_IMAGE_FORMAT, ByVal dib As Long, ByVal stream As Long, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_TellMemory Lib "FreeImage.dll" Alias "_FreeImage_TellMemory@4" (ByVal stream As Long) As Long
+Public Declare Function FreeImage_SeekMemory Lib "FreeImage.dll" Alias "_FreeImage_SeekMemory@12" (ByVal stream As Long, ByVal offset As Long, ByVal origin As Long) As Long
+Public Declare Function FreeImage_AcquireMemory Lib "FreeImage.dll" Alias "_FreeImage_AcquireMemory@12" (ByVal stream As Long, ByRef data As Long, ByRef size_in_bytes As Long) As Long
+Public Declare Function FreeImage_RegisterLocalPlugin Lib "FreeImage.dll" Alias "_FreeImage_RegisterLocalPlugin@20" (ByVal proc_address As Long, Optional ByVal format As String = 0, Optional ByVal description As String = 0, Optional ByVal extension As String = 0, Optional ByVal regexpr As String = 0) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_RegisterExternalPlugin Lib "FreeImage.dll" Alias "_FreeImage_RegisterExternalPlugin@20" (ByVal path As String, Optional ByVal format As String = 0, Optional ByVal description As String = 0, Optional ByVal extension As String = 0, Optional ByVal regexpr As String = 0) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetFIFCount Lib "FreeImage.dll" Alias "_FreeImage_GetFIFCount@0" () As Long
+Public Declare Function FreeImage_SetPluginEnabled Lib "FreeImage.dll" Alias "_FreeImage_SetPluginEnabled@8" (ByVal fif As FREE_IMAGE_FORMAT, ByVal enable As Long) As Long
+Public Declare Function FreeImage_IsPluginEnabled Lib "FreeImage.dll" Alias "_FreeImage_IsPluginEnabled@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFFromFormat Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromFormat@4" (ByVal format As String) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetFIFFromMime Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromMime@4" (ByVal mime As String) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetFormatFromFIF Lib "FreeImage.dll" Alias "_FreeImage_GetFormatFromFIF@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFExtensionList Lib "FreeImage.dll" Alias "_FreeImage_GetFIFExtensionList@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFDescription Lib "FreeImage.dll" Alias "_FreeImage_GetFIFDescription@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFRegExpr Lib "FreeImage.dll" Alias "_FreeImage_GetFIFRegExpr@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFMimeType Lib "FreeImage.dll" Alias "_FreeImage_GetFIFMimeType@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_GetFIFFromFilename Lib "FreeImage.dll" Alias "_FreeImage_GetFIFFromFilename@4" (ByVal filename As String) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_FIFSupportsReading Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsReading@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_FIFSupportsWriting Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsWriting@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_FIFSupportsExportBPP Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsExportBPP@8" (ByVal fif As FREE_IMAGE_FORMAT, ByVal bpp As Long) As Long
+Public Declare Function FreeImage_FIFSupportsExportType Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsExportType@8" (ByVal fif As FREE_IMAGE_FORMAT, ByVal type_ As FREE_IMAGE_TYPE) As Long
+Public Declare Function FreeImage_FIFSupportsICCProfiles Lib "FreeImage.dll" Alias "_FreeImage_FIFSupportsICCProfiles@4" (ByVal fif As FREE_IMAGE_FORMAT) As Long
+Public Declare Function FreeImage_OpenMultiBitmap Lib "FreeImage.dll" Alias "_FreeImage_OpenMultiBitmap@24" (ByVal fif As FREE_IMAGE_FORMAT, ByVal filename As String, ByVal create_new As Long, ByVal read_only As Long, Optional ByVal keep_cache_in_memory As Long = 0, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_CloseMultiBitmap Lib "FreeImage.dll" Alias "_FreeImage_CloseMultiBitmap@8" (ByVal bitmap As Long, Optional ByVal flags As Long = 0) As Long
+Public Declare Function FreeImage_GetPageCount Lib "FreeImage.dll" Alias "_FreeImage_GetPageCount@4" (ByVal bitmap As Long) As Long
+Public Declare Sub FreeImage_AppendPage Lib "FreeImage.dll" Alias "_FreeImage_AppendPage@8" (ByVal bitmap As Long, ByVal data As Long)
+Public Declare Sub FreeImage_InsertPage Lib "FreeImage.dll" Alias "_FreeImage_InsertPage@12" (ByVal bitmap As Long, ByVal page As Long, ByVal data As Long)
+Public Declare Sub FreeImage_DeletePage Lib "FreeImage.dll" Alias "_FreeImage_DeletePage@8" (ByVal bitmap As Long, ByVal page As Long)
+Public Declare Function FreeImage_LockPage Lib "FreeImage.dll" Alias "_FreeImage_LockPage@8" (ByVal bitmap As Long, ByVal page As Long) As Long
+Public Declare Sub FreeImage_UnlockPage Lib "FreeImage.dll" Alias "_FreeImage_UnlockPage@12" (ByVal bitmap As Long, ByVal page As Long, ByVal changed As Long)
+Public Declare Function FreeImage_MovePage Lib "FreeImage.dll" Alias "_FreeImage_MovePage@12" (ByVal bitmap As Long, ByVal target As Long, ByVal source As Long) As Long
+Public Declare Function FreeImage_GetLockedPageNumbers Lib "FreeImage.dll" Alias "_FreeImage_GetLockedPageNumbers@12" (ByVal bitmap As Long, ByRef pages As Long, ByRef count As Long) As Long
+Public Declare Function FreeImage_GetFileType Lib "FreeImage.dll" Alias "_FreeImage_GetFileType@8" (ByVal filename As String, Optional ByVal size As Long = 0) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetFileTypeFromHandle Lib "FreeImage.dll" Alias "_FreeImage_GetFileTypeFromHandle@12" (ByVal io As Long, ByVal handle As Long, Optional ByVal size As Long = 0) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetFileTypeFromMemory Lib "FreeImage.dll" Alias "_FreeImage_GetFileTypeFromMemory@8" (ByVal stream As Long, Optional ByVal size As Long = 0) As FREE_IMAGE_FORMAT
+Public Declare Function FreeImage_GetImageType Lib "FreeImage.dll" Alias "_FreeImage_GetImageType@4" (ByVal dib As Long) As FREE_IMAGE_TYPE
+Public Declare Function FreeImage_IsLittleEndian Lib "FreeImage.dll" Alias "_FreeImage_IsLittleEndian@0" () As Long
+Public Declare Function FreeImage_LookupX11Color Lib "FreeImage.dll" Alias "_FreeImage_LookupX11Color@16" (ByVal szColor As String, ByRef nRed As Long, ByRef nGreen As Long, ByRef nBlue As Long) As Long
+Public Declare Function FreeImage_LookupSVGColor Lib "FreeImage.dll" Alias "_FreeImage_LookupSVGColor@16" (ByVal szColor As String, ByRef nRed As Long, ByRef nGreen As Long, ByRef nBlue As Long) As Long
+Public Declare Function FreeImage_GetBits Lib "FreeImage.dll" Alias "_FreeImage_GetBits@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetScanLine Lib "FreeImage.dll" Alias "_FreeImage_GetScanLine@8" (ByVal dib As Long, ByVal scanline As Long) As Long
+Public Declare Function FreeImage_GetPixelIndex Lib "FreeImage.dll" Alias "_FreeImage_GetPixelIndex@16" (ByVal dib As Long, ByVal x As Long, ByVal y As Long, ByRef value As Long) As Long
+Public Declare Function FreeImage_GetPixelColor Lib "FreeImage.dll" Alias "_FreeImage_GetPixelColor@16" (ByVal dib As Long, ByVal x As Long, ByVal y As Long, ByVal value As Long) As Long
+Public Declare Function FreeImage_SetPixelIndex Lib "FreeImage.dll" Alias "_FreeImage_SetPixelIndex@16" (ByVal dib As Long, ByVal x As Long, ByVal y As Long, ByRef value As Long) As Long
+Public Declare Function FreeImage_SetPixelColor Lib "FreeImage.dll" Alias "_FreeImage_SetPixelColor@16" (ByVal dib As Long, ByVal x As Long, ByVal y As Long, ByVal value As Long) As Long
+Public Declare Function FreeImage_GetColorsUsed Lib "FreeImage.dll" Alias "_FreeImage_GetColorsUsed@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetBPP Lib "FreeImage.dll" Alias "_FreeImage_GetBPP@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetWidth Lib "FreeImage.dll" Alias "_FreeImage_GetWidth@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetHeight Lib "FreeImage.dll" Alias "_FreeImage_GetHeight@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetLine Lib "FreeImage.dll" Alias "_FreeImage_GetLine@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetPitch Lib "FreeImage.dll" Alias "_FreeImage_GetPitch@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetDIBSize Lib "FreeImage.dll" Alias "_FreeImage_GetDIBSize@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetPalette Lib "FreeImage.dll" Alias "_FreeImage_GetPalette@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetDotsPerMeterX Lib "FreeImage.dll" Alias "_FreeImage_GetDotsPerMeterX@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetDotsPerMeterY Lib "FreeImage.dll" Alias "_FreeImage_GetDotsPerMeterY@4" (ByVal dib As Long) As Long
+Public Declare Sub FreeImage_SetDotsPerMeterX Lib "FreeImage.dll" Alias "_FreeImage_SetDotsPerMeterX@8" (ByVal dib As Long, ByVal res As Long)
+Public Declare Sub FreeImage_SetDotsPerMeterY Lib "FreeImage.dll" Alias "_FreeImage_SetDotsPerMeterY@8" (ByVal dib As Long, ByVal res As Long)
+Public Declare Function FreeImage_GetInfoHeader Lib "FreeImage.dll" Alias "_FreeImage_GetInfoHeader@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetInfo Lib "FreeImage.dll" Alias "_FreeImage_GetInfo@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetColorType Lib "FreeImage.dll" Alias "_FreeImage_GetColorType@4" (ByVal dib As Long) As FREE_IMAGE_COLOR_TYPE
+Public Declare Function FreeImage_GetRedMask Lib "FreeImage.dll" Alias "_FreeImage_GetRedMask@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetGreenMask Lib "FreeImage.dll" Alias "_FreeImage_GetGreenMask@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetBlueMask Lib "FreeImage.dll" Alias "_FreeImage_GetBlueMask@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetTransparencyCount Lib "FreeImage.dll" Alias "_FreeImage_GetTransparencyCount@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetTransparencyTable Lib "FreeImage.dll" Alias "_FreeImage_GetTransparencyTable@4" (ByVal dib As Long) As Long
+Public Declare Sub FreeImage_SetTransparent Lib "FreeImage.dll" Alias "_FreeImage_SetTransparent@8" (ByVal dib As Long, ByVal enabled As Long)
+Public Declare Sub FreeImage_SetTransparencyTable Lib "FreeImage.dll" Alias "_FreeImage_SetTransparencyTable@12" (ByVal dib As Long, ByRef table As Long, ByVal count As Long)
+Public Declare Function FreeImage_IsTransparent Lib "FreeImage.dll" Alias "_FreeImage_IsTransparent@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_HasBackgroundColor Lib "FreeImage.dll" Alias "_FreeImage_HasBackgroundColor@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetBackgroundColor Lib "FreeImage.dll" Alias "_FreeImage_GetBackgroundColor@8" (ByVal dib As Long, ByVal bkcolor As Long) As Long
+Public Declare Function FreeImage_SetBackgroundColor Lib "FreeImage.dll" Alias "_FreeImage_SetBackgroundColor@8" (ByVal dib As Long, ByVal bkcolor As Long) As Long
+Public Declare Function FreeImage_GetICCProfile Lib "FreeImage.dll" Alias "_FreeImage_GetICCProfile@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_CreateICCProfile Lib "FreeImage.dll" Alias "_FreeImage_CreateICCProfile@12" (ByVal dib As Long, ByRef data As Long, ByVal size As Long) As Long
+Public Declare Sub FreeImage_DestroyICCProfile Lib "FreeImage.dll" Alias "_FreeImage_DestroyICCProfile@4" (ByVal dib As Long)
+Public Declare Sub FreeImage_ConvertLine1To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To4@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine8To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To4@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine16To4_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To4_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine16To4_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To4_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine24To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To4@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine32To4 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To4@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine1To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To8@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine4To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To8@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine16To8_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To8_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine16To8_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To8_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine24To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To8@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine32To8 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To8@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine1To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To16_555@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine4To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To16_555@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine8To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To16_555@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine16_565_To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16_565_To16_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine24To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To16_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine32To16_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To16_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine1To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To16_565@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine4To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To16_565@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine8To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To16_565@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine16_555_To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16_555_To16_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine24To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To16_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine32To16_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To16_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine1To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To24@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine4To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To24@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine8To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To24@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine16To24_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To24_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine16To24_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To24_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine32To24 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine32To24@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine1To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine1To32@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine4To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine4To32@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine8To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine8To32@16" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long, ByVal palette As Long)
+Public Declare Sub FreeImage_ConvertLine16To32_555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To32_555@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine16To32_565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine16To32_565@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Sub FreeImage_ConvertLine24To32 Lib "FreeImage.dll" Alias "_FreeImage_ConvertLine24To32@12" (ByRef target As Long, ByRef source As Long, ByVal width_in_pixels As Long)
+Public Declare Function FreeImage_ConvertTo4Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo4Bits@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertTo8Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo8Bits@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertTo16Bits555 Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo16Bits555@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertTo16Bits565 Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo16Bits565@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertTo24Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo24Bits@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertTo32Bits Lib "FreeImage.dll" Alias "_FreeImage_ConvertTo32Bits@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ColorQuantize Lib "FreeImage.dll" Alias "_FreeImage_ColorQuantize@8" (ByVal dib As Long, ByVal quantize As FREE_IMAGE_QUANTIZE) As Long
+Public Declare Function FreeImage_ColorQuantizeEx Lib "FreeImage.dll" Alias "_FreeImage_ColorQuantizeEx@20" (ByVal dib As Long, Optional ByVal quantize As FREE_IMAGE_QUANTIZE = FIQ_WUQUANT, Optional ByVal PaletteSize As Long = 256, Optional ByVal ReserveSize As Long = 0, Optional ByVal ReservePalette As Long = 0) As Long
+Public Declare Function FreeImage_Threshold Lib "FreeImage.dll" Alias "_FreeImage_Threshold@8" (ByVal dib As Long, ByVal T As Byte) As Long
+Public Declare Function FreeImage_Dither Lib "FreeImage.dll" Alias "_FreeImage_Dither@8" (ByVal dib As Long, ByVal algorithm As FREE_IMAGE_DITHER) As Long
+Public Declare Function FreeImage_ConvertFromRawBits Lib "FreeImage.dll" Alias "_FreeImage_ConvertFromRawBits@36" (ByRef bits As Long, ByVal width As Long, ByVal height As Long, ByVal pitch As Long, ByVal bpp As Long, ByVal red_mask As Long, ByVal green_mask As Long, ByVal blue_mask As Long, Optional ByVal topdown As Long = 0) As Long
+Public Declare Sub FreeImage_ConvertToRawBits Lib "FreeImage.dll" Alias "_FreeImage_ConvertToRawBits@32" (ByRef bits As Long, ByVal dib As Long, ByVal pitch As Long, ByVal bpp As Long, ByVal red_mask As Long, ByVal green_mask As Long, ByVal blue_mask As Long, Optional ByVal topdown As Long = 0)
+Public Declare Function FreeImage_ConvertToRGBF Lib "FreeImage.dll" Alias "_FreeImage_ConvertToRGBF@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_ConvertToStandardType Lib "FreeImage.dll" Alias "_FreeImage_ConvertToStandardType@8" (ByVal src As Long, Optional ByVal scale_linear As Long = 1) As Long
+Public Declare Function FreeImage_ConvertToType Lib "FreeImage.dll" Alias "_FreeImage_ConvertToType@12" (ByVal src As Long, ByVal dst_type As FREE_IMAGE_TYPE, Optional ByVal scale_linear As Long = 1) As Long
+Public Declare Function FreeImage_ToneMapping Lib "FreeImage.dll" Alias "_FreeImage_ToneMapping@20" (ByVal dib As Long, UNKNOWN tmo As FREE_IMAGE_TMO, Optional ByVal first_param As Double = 0, Optional ByVal second_param As Double = 0) As Long
+Public Declare Function FreeImage_TmoDrago03 Lib "FreeImage.dll" Alias "_FreeImage_TmoDrago03@20" (ByVal src As Long, Optional ByVal gamma As Double = 2.2, Optional ByVal exposure As Double = 0) As FIBITMAP*
+Public Declare Function FreeImage_TmoReinhard05 Lib "FreeImage.dll" Alias "_FreeImage_TmoReinhard05@20" (ByVal src As Long, Optional ByVal intensity As Double = 0, Optional ByVal contrast As Double = 0) As FIBITMAP*
+Public Declare Function FreeImage_ZLibCompress Lib "FreeImage.dll" Alias "_FreeImage_ZLibCompress@16" (ByRef target As Long, ByVal target_size As Long, ByRef source As Long, ByVal source_size As Long) As Long
+Public Declare Function FreeImage_ZLibUncompress Lib "FreeImage.dll" Alias "_FreeImage_ZLibUncompress@16" (ByRef target As Long, ByVal target_size As Long, ByRef source As Long, ByVal source_size As Long) As Long
+Public Declare Function FreeImage_ZLibGZip Lib "FreeImage.dll" Alias "_FreeImage_ZLibGZip@16" (ByRef target As Long, ByVal target_size As Long, ByRef source As Long, ByVal source_size As Long) As Long
+Public Declare Function FreeImage_ZLibGUnzip Lib "FreeImage.dll" Alias "_FreeImage_ZLibGUnzip@16" (ByRef target As Long, ByVal target_size As Long, ByRef source As Long, ByVal source_size As Long) As Long
+Public Declare Function FreeImage_ZLibCRC32 Lib "FreeImage.dll" Alias "_FreeImage_ZLibCRC32@12" (ByVal crc As Long, ByRef source As Long, ByVal source_size As Long) As Long
+Public Declare Function FreeImage_CreateTag Lib "FreeImage.dll" Alias "_FreeImage_CreateTag@0" () As Long
+Public Declare Sub FreeImage_DeleteTag Lib "FreeImage.dll" Alias "_FreeImage_DeleteTag@4" (ByVal tag As Long)
+Public Declare Function FreeImage_CloneTag Lib "FreeImage.dll" Alias "_FreeImage_CloneTag@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetTagKey Lib "FreeImage.dll" Alias "_FreeImage_GetTagKey@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetTagDescription Lib "FreeImage.dll" Alias "_FreeImage_GetTagDescription@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetTagID Lib "FreeImage.dll" Alias "_FreeImage_GetTagID@4" (ByVal tag As Long) As Integer
+Public Declare Function FreeImage_GetTagType Lib "FreeImage.dll" Alias "_FreeImage_GetTagType@4" (ByVal tag As Long) As FREE_IMAGE_MDTYPE
+Public Declare Function FreeImage_GetTagCount Lib "FreeImage.dll" Alias "_FreeImage_GetTagCount@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetTagLength Lib "FreeImage.dll" Alias "_FreeImage_GetTagLength@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetTagValue Lib "FreeImage.dll" Alias "_FreeImage_GetTagValue@4" (ByVal tag As Long) As Long
+Public Declare Function FreeImage_SetTagKey Lib "FreeImage.dll" Alias "_FreeImage_SetTagKey@8" (ByVal tag As Long, ByVal key As String) As Long
+Public Declare Function FreeImage_SetTagDescription Lib "FreeImage.dll" Alias "_FreeImage_SetTagDescription@8" (ByVal tag As Long, ByVal description As String) As Long
+Public Declare Function FreeImage_SetTagID Lib "FreeImage.dll" Alias "_FreeImage_SetTagID@8" (ByVal tag As Long, ByVal id As Integer) As Long
+Public Declare Function FreeImage_SetTagType Lib "FreeImage.dll" Alias "_FreeImage_SetTagType@8" (ByVal tag As Long, ByVal type_ As FREE_IMAGE_MDTYPE) As Long
+Public Declare Function FreeImage_SetTagCount Lib "FreeImage.dll" Alias "_FreeImage_SetTagCount@8" (ByVal tag As Long, ByVal count As Long) As Long
+Public Declare Function FreeImage_SetTagLength Lib "FreeImage.dll" Alias "_FreeImage_SetTagLength@8" (ByVal tag As Long, ByVal length As Long) As Long
+Public Declare Function FreeImage_SetTagValue Lib "FreeImage.dll" Alias "_FreeImage_SetTagValue@8" (ByVal tag As Long, ByRef value As Long) As Long
+Public Declare Function FreeImage_FindFirstMetadata Lib "FreeImage.dll" Alias "_FreeImage_FindFirstMetadata@12" (ByVal model As FREE_IMAGE_MDMODEL, ByVal dib As Long, ByRef tag As Long) As Long
+Public Declare Function FreeImage_FindNextMetadata Lib "FreeImage.dll" Alias "_FreeImage_FindNextMetadata@8" (ByVal mdhandle As Long, ByRef tag As Long) As Long
+Public Declare Sub FreeImage_FindCloseMetadata Lib "FreeImage.dll" Alias "_FreeImage_FindCloseMetadata@4" (ByVal mdhandle As Long)
+Public Declare Function FreeImage_SetMetadata Lib "FreeImage.dll" Alias "_FreeImage_SetMetadata@16" (ByVal model As FREE_IMAGE_MDMODEL, ByVal dib As Long, ByVal key As String, ByVal tag As Long) As Long
+Public Declare Function FreeImage_GetMetadata Lib "FreeImage.dll" Alias "_FreeImage_GetMetadata@16" (ByVal model As FREE_IMAGE_MDMODEL, ByVal dib As Long, ByVal key As String, ByRef tag As Long) As Long
+Public Declare Function FreeImage_GetMetadataCount Lib "FreeImage.dll" Alias "_FreeImage_GetMetadataCount@8" (ByVal model As FREE_IMAGE_MDMODEL, ByVal dib As Long) As Long
+Public Declare Function FreeImage_TagToString Lib "FreeImage.dll" Alias "_FreeImage_TagToString@12" (ByVal model As FREE_IMAGE_MDMODEL, ByVal tag As Long, Optional ByVal Make As String = 0) As Long
+Public Declare Function FreeImage_RotateClassic Lib "FreeImage.dll" Alias "_FreeImage_RotateClassic@12" (ByVal dib As Long, ByVal angle As Double) As Long
+Public Declare Function FreeImage_RotateEx Lib "FreeImage.dll" Alias "_FreeImage_RotateEx@48" (ByVal dib As Long, ByVal angle As Double, ByVal x_shift As Double, ByVal y_shift As Double, ByVal x_origin As Double, ByVal y_origin As Double, ByVal use_mask As Long) As Long
+Public Declare Function FreeImage_FlipHorizontal Lib "FreeImage.dll" Alias "_FreeImage_FlipHorizontal@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_FlipVertical Lib "FreeImage.dll" Alias "_FreeImage_FlipVertical@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_JPEGTransform Lib "FreeImage.dll" Alias "_FreeImage_JPEGTransform@12" (ByVal src_file As String, ByVal dst_file As String, UNKNOWN operation As FREE_IMAGE_JPEG_OPERATION, Optional ByVal perfect As Long = 0) As Long
+Public Declare Function FreeImage_Rescale Lib "FreeImage.dll" Alias "_FreeImage_Rescale@16" (ByVal dib As Long, ByVal dst_width As Long, ByVal dst_height As Long, ByVal filter As FREE_IMAGE_FILTER) As Long
+Public Declare Function FreeImage_AdjustCurve Lib "FreeImage.dll" Alias "_FreeImage_AdjustCurve@12" (ByVal dib As Long, ByRef LUT As Long, ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+Public Declare Function FreeImage_AdjustGamma Lib "FreeImage.dll" Alias "_FreeImage_AdjustGamma@12" (ByVal dib As Long, ByVal gamma As Double) As Long
+Public Declare Function FreeImage_AdjustBrightness Lib "FreeImage.dll" Alias "_FreeImage_AdjustBrightness@12" (ByVal dib As Long, ByVal percentage As Double) As Long
+Public Declare Function FreeImage_AdjustContrast Lib "FreeImage.dll" Alias "_FreeImage_AdjustContrast@12" (ByVal dib As Long, ByVal percentage As Double) As Long
+Public Declare Function FreeImage_Invert Lib "FreeImage.dll" Alias "_FreeImage_Invert@4" (ByVal dib As Long) As Long
+Public Declare Function FreeImage_GetHistogram Lib "FreeImage.dll" Alias "_FreeImage_GetHistogram@12" (ByVal dib As Long, ByRef histo As Long, Optional ByVal channel As FREE_IMAGE_COLOR_CHANNEL = FICC_BLACK) As Long
+Public Declare Function FreeImage_GetChannel Lib "FreeImage.dll" Alias "_FreeImage_GetChannel@8" (ByVal dib As Long, ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+Public Declare Function FreeImage_SetChannel Lib "FreeImage.dll" Alias "_FreeImage_SetChannel@12" (ByVal dib As Long, ByVal dib8 As Long, ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+Public Declare Function FreeImage_GetComplexChannel Lib "FreeImage.dll" Alias "_FreeImage_GetComplexChannel@8" (ByVal src As Long, ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+Public Declare Function FreeImage_SetComplexChannel Lib "FreeImage.dll" Alias "_FreeImage_SetComplexChannel@12" (ByVal dst As Long, ByVal src As Long, ByVal channel As FREE_IMAGE_COLOR_CHANNEL) As Long
+Public Declare Function FreeImage_Copy Lib "FreeImage.dll" Alias "_FreeImage_Copy@20" (ByVal dib As Long, ByVal left As Long, ByVal top As Long, ByVal right As Long, ByVal bottom As Long) As Long
+Public Declare Function FreeImage_Paste Lib "FreeImage.dll" Alias "_FreeImage_Paste@20" (ByVal dst As Long, ByVal src As Long, ByVal left As Long, ByVal top As Long, ByVal alpha As Long) As Long
+Public Declare Function FreeImage_Composite Lib "FreeImage.dll" Alias "_FreeImage_Composite@16" (ByVal fg As Long, Optional ByVal useFileBkg As Long = 0, Optional ByVal appBkColor As Long = 0, Optional ByVal bg As Long = 0) As Long
diff --git a/Wrapper/VB6/test/SimpleTest.frm b/Wrapper/VB6/test/SimpleTest.frm
new file mode 100644
index 0000000..1847542
--- /dev/null
+++ b/Wrapper/VB6/test/SimpleTest.frm
@@ -0,0 +1,45 @@
+VERSION 5.00
+Begin VB.Form SimpleTest
+ Caption = "SimpleTest"
+ ClientHeight = 1035
+ ClientLeft = 60
+ ClientTop = 345
+ ClientWidth = 2325
+ LinkTopic = "Form1"
+ ScaleHeight = 1035
+ ScaleWidth = 2325
+ StartUpPosition = 3 'Windows Default
+ Begin VB.CommandButton btnTest
+ Caption = "Test"
+ Height = 495
+ Left = 240
+ TabIndex = 0
+ Top = 240
+ Width = 1575
+ End
+End
+Attribute VB_Name = "SimpleTest"
+Attribute VB_GlobalNameSpace = False
+Attribute VB_Creatable = False
+Attribute VB_PredeclaredId = True
+Attribute VB_Exposed = False
+Option Explicit
+' NOTE :
+' To run this test program, you will have to copy the FreeImage.dll file
+' in this directory.
+' Change also the "test.tif" file name with a path to any tif file on your
+' hard disk
+'
+Private Sub btnTest_Click()
+ Dim dib As Long
+ Dim bOK As Long
+ ' Load a tif image
+ dib = FreeImage_Load(FIF_TIFF, "test.tif", 0)
+
+ ' Save this image as PNG
+ bOK = FreeImage_Save(FIF_PNG, dib, "test.png", 0)
+
+ ' Unload the dib
+ FreeImage_Unload (dib)
+
+End Sub
diff --git a/Wrapper/VB6/test/SimpleTest.vbp b/Wrapper/VB6/test/SimpleTest.vbp
new file mode 100644
index 0000000..8ee5610
--- /dev/null
+++ b/Wrapper/VB6/test/SimpleTest.vbp
@@ -0,0 +1,38 @@
+Type=Exe
+Reference=*\G{00020430-0000-0000-C000-000000000046}#2.0#0#..\..\..\..\..\WINNT\system32\stdole2.tlb#OLE Automation
+Form=SimpleTest.frm
+Module=FreeImage; ..\modFreeImage.bas
+IconForm="SimpleTest"
+Startup="SimpleTest"
+HelpFile=""
+Title="SimpleTest"
+ExeName32="SimpleTest.exe"
+Command32=""
+Name="TestFreeImage"
+HelpContextID="0"
+CompatibleMode="0"
+MajorVer=1
+MinorVer=0
+RevisionVer=0
+AutoIncrementVer=0
+ServerSupportFiles=0
+VersionCompanyName="HDN"
+CompilationType=0
+OptimizationType=0
+FavorPentiumPro(tm)=0
+CodeViewDebugInfo=0
+NoAliasing=0
+BoundsCheck=0
+OverflowCheck=0
+FlPointCheck=0
+FDIVCheck=0
+UnroundedFP=0
+StartMode=0
+Unattended=0
+Retained=0
+ThreadPerObject=0
+MaxNumberOfThreads=1
+DebugStartupOption=0
+
+[MS Transaction Server]
+AutoRefresh=1
diff --git a/clean.bat b/clean.bat
new file mode 100755
index 0000000..b764e58
--- /dev/null
+++ b/clean.bat
@@ -0,0 +1,59 @@
+rd Release /s /q
+rd Debug /s /q
+rd Source\FreeImageQt\Release /s /q
+rd Source\FreeImageQt\Debug /s /q
+rd Source\FreeImageLib\Debug /s /q
+rd Source\FreeImageLib\Release /s /q
+rd Source\Source\Release /s /q
+rd Source\Source\Debug /s /q
+rd Source\LibJPEG\Debug /s /q
+rd Source\LibJPEG\Release /s /q
+rd Source\LibPNG\Debug /s /q
+rd Source\LibPNG\Release /s /q
+rd Source\LibMNG\Debug /s /q
+rd Source\LibMNG\Release /s /q
+rd Source\LibTIFF\Debug /s /q
+rd Source\LibTIFF\Release /s /q
+rd Source\Zlib\Debug /s /q
+rd Source\Zlib\Release /s /q
+rd Source\OpenEXR\Debug /s /q
+rd Source\OpenEXR\Release /s /q
+rd Source\LibOpenJPEG\Debug /s /q
+rd Source\LibOpenJPEG\Release /s /q
+rd Source\LibRawLite\Debug /s /q
+rd Source\LibRawLite\Release /s /q
+rd TestAPI\Debug /s /q
+rd TestAPI\Release /s /q
+del TestAPI\blob.png
+del TestAPI\buffer.png
+del TestAPI\dump.png
+del TestAPI\TestImageType.tif
+del TestAPI\zoneplate.png
+del TestAPI\sample.ico
+del TestAPI\sample.tif
+del TestAPI\sample.gif
+del TestAPI\test.jpg
+del TestAPI\mpages.tif
+del Dist\FreeImage.h
+del *.pch /s /q
+del *.ncb /s /q
+del *.opt /s /q
+del *.plg /s /q
+del *.obj /s /q
+del *.dll /s /q
+del *.exe /s /q
+del *.bsc /s /q
+del *.bak /s /q
+del *.pdb /s /q
+del *.sql /s /q
+del *.mdb /s /q
+del *.lib /s /q
+del *.exp /s /q
+del *.ilk /s /q
+del *.idb /s /q
+del *.aps /s /q
+del *.suo /s /q /a:h
+del *.o /s /q
+del *.user /s /q
+
+
diff --git a/clean.sh b/clean.sh
new file mode 100755
index 0000000..31d5c18
--- /dev/null
+++ b/clean.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+rm -rf Release
+rm -rf Debug
+rm -rf Source/FreeImageQt/Release
+rm -rf Source/FreeImageQt/Debug
+rm -rf Source/FreeImageLib/Debug
+rm -rf Source/FreeImageLib/Release
+rm -rf Source/Source/Release
+rm -rf Source/Source/Debug
+rm -rf Source/LibJPEG/Debug
+rm -rf Source/LibJPEG/Release
+rm -rf Source/LibPNG/Debug
+rm -rf Source/LibPNG/Release
+rm -rf Source/LibMNG/Debug
+rm -rf Source/LibMNG/Release
+rm -rf Source/LibTIFF/Debug
+rm -rf Source/LibTIFF/Release
+rm -rf Source/Zlib/Debug
+rm -rf Source/Zlib/Release
+rm -rf Source/OpenEXR/Debug
+rm -rf Source/OpenEXR/Release
+rm -rf Source/LibOpenJPEG/Debug
+rm -rf Source/LibOpenJPEG/Release
+rm -rf Source/LibRawLite/Debug
+rm -rf Source/LibRawLite/Release
+rm -rf TestAPI/Debug
+rm -rf TestAPI/Release
+find . -name '*.pch' -exec rm -f {} ";"
+find . -name '*.ncb' -exec rm -f {} ";"
+find . -name '*.opt' -exec rm -f {} ";"
+find . -name '*.plg' -exec rm -f {} ";"
+find . -name '*.obj' -exec rm -f {} ";"
+find . -name '*.dll' -exec rm -f {} ";"
+find . -name '*.exe' -exec rm -f {} ";"
+find . -name '*.bsc' -exec rm -f {} ";"
+find . -name '*.bak' -exec rm -f {} ";"
+find . -name '*.pdb' -exec rm -f {} ";"
+find . -name '*.sql' -exec rm -f {} ";"
+find . -name '*.mdb' -exec rm -f {} ";"
+find . -name '*.lib' -exec rm -f {} ";"
+find . -name '*.exp' -exec rm -f {} ";"
+find . -name '*.ilk' -exec rm -f {} ";"
+find . -name '*.idb' -exec rm -f {} ";"
+find . -name '*.o' -exec rm -f {} ";"
+find . -name '*.o-ppc' -exec rm -f {} ";"
+find . -name '*.o-i386' -exec rm -f {} ";"
diff --git a/fipMakefile.srcs b/fipMakefile.srcs
new file mode 100644
index 0000000..1b6df56
--- /dev/null
+++ b/fipMakefile.srcs
@@ -0,0 +1,4 @@
+VER_MAJOR = 3
+VER_MINOR = 13.0
+SRCS = ./Source/FreeImage/BitmapAccess.cpp ./Source/FreeImage/ColorLookup.cpp ./Source/FreeImage/FreeImage.cpp ./Source/FreeImage/FreeImageC.c ./Source/FreeImage/FreeImageIO.cpp ./Source/FreeImage/GetType.cpp ./Source/FreeImage/MemoryIO.cpp ./Source/FreeImage/PixelAccess.cpp ././Source/FreeImage/J2KHelper.cpp ./Source/FreeImage/Plugin.cpp ./Source/FreeImage/PluginBMP.cpp ./Source/FreeImage/PluginCUT.cpp ./Source/FreeImage/PluginDDS.cpp ././Source/FreeImage/PluginEXR.cpp ./Source/FreeImage/PluginG3.cpp ./Source/FreeImage/PluginGIF.cpp ./Source/FreeImage/PluginHDR.cpp ./Source/FreeImage/PluginICO.cpp ./Source/FreeImage/PluginIFF.cpp ././Source/FreeImage/PluginJ2K.cpp ././Source/FreeImage/PluginJP2.cpp ./Source/FreeImage/PluginJPEG.cpp ./Source/FreeImage/PluginKOALA.cpp ./Source/FreeImage/PluginMNG.cpp ./Source/FreeImage/PluginPCD.cpp ./Source/FreeImage/PluginPCX.cpp ././Source/FreeImage/PluginPFM.cpp ././Source/FreeImage/PluginPICT.cpp ./Source/FreeImage/PluginPNG.cpp ./Source/FreeImage/PluginPNM.cpp ./Source/FreeImage/PluginPSD.cpp ./Source/FreeImage/PluginRAS.cpp ././Source/FreeImage/PluginRAW.cpp ./Source/FreeImage/PluginSGI.cpp ./Source/FreeImage/PluginTARGA.cpp ./Source/FreeImage/PluginTIFF.cpp ./Source/FreeImage/PluginWBMP.cpp ./Source/FreeImage/PluginXBM.cpp ./Source/FreeImage/PluginXPM.cpp ././Source/FreeImage/PSDParser.cpp ././Source/FreeImage/TIFFLogLuv.cpp ./Source/FreeImage/Conversion.cpp ./Source/FreeImage/Conversion16_555.cpp ./Source/FreeImage/Conversion16_565.cpp ./Source/FreeImage/Conversion24.cpp ./Source/FreeImage/Conversion32.cpp ./Source/FreeImage/Conversion4.cpp ./Source/FreeImage/Conversion8.cpp ./Source/FreeImage/ConversionRGBF.cpp ./Source/FreeImage/ConversionType.cpp ./Source/FreeImage/Halftoning.cpp ./Source/FreeImage/tmoColorConvert.cpp ./Source/FreeImage/tmoDrago03.cpp ././Source/FreeImage/tmoFattal02.cpp ./Source/FreeImage/tmoReinhard05.cpp ./Source/FreeImage/ToneMapping.cpp ./Source/FreeImage/NNQuantizer.cpp ./Source/FreeImage/WuQuantizer.cpp ././Source/DeprecationManager/Deprecated.cpp ./Source/DeprecationManager/DeprecationMgr.cpp ./Source/FreeImage/CacheFile.cpp ./Source/FreeImage/MultiPage.cpp ./Source/FreeImage/ZLibInterface.cpp ./Source/Metadata/Exif.cpp ./Source/Metadata/FIRational.cpp ./Source/Metadata/FreeImageTag.cpp ./Source/Metadata/IPTC.cpp ./Source/Metadata/TagConversion.cpp ./Source/Metadata/TagLib.cpp ./Source/Metadata/XTIFF.cpp ././Source/FreeImageToolkit/Background.cpp ./Source/FreeImageToolkit/BSplineRotate.cpp ./Source/FreeImageToolkit/Channels.cpp ./Source/FreeImageToolkit/ClassicRotate.cpp ./Source/FreeImageToolkit/Colors.cpp ./Source/FreeImageToolkit/CopyPaste.cpp ./Source/FreeImageToolkit/Display.cpp ./Source/FreeImageToolkit/Flip.cpp ./Source/FreeImageToolkit/JPEGTransform.cpp ././Source/FreeImageToolkit/MultigridPoissonSolver.cpp ./Source/FreeImageToolkit/Rescale.cpp ./Source/FreeImageToolkit/Resize.cpp Source/LibJPEG/./jaricom.c Source/LibJPEG/jcapimin.c Source/LibJPEG/jcapistd.c Source/LibJPEG/./jcarith.c Source/LibJPEG/jccoefct.c Source/LibJPEG/jccolor.c Source/LibJPEG/jcdctmgr.c Source/LibJPEG/jchuff.c Source/LibJPEG/jcinit.c Source/LibJPEG/jcmainct.c Source/LibJPEG/jcmarker.c Source/LibJPEG/jcmaster.c Source/LibJPEG/jcomapi.c Source/LibJPEG/jcparam.c Source/LibJPEG/jcprepct.c Source/LibJPEG/jcsample.c Source/LibJPEG/jctrans.c Source/LibJPEG/jdapimin.c Source/LibJPEG/jdapistd.c Source/LibJPEG/./jdarith.c Source/LibJPEG/jdatadst.c Source/LibJPEG/jdatasrc.c Source/LibJPEG/jdcoefct.c Source/LibJPEG/jdcolor.c Source/LibJPEG/jddctmgr.c Source/LibJPEG/jdhuff.c Source/LibJPEG/jdinput.c Source/LibJPEG/jdmainct.c Source/LibJPEG/jdmarker.c Source/LibJPEG/jdmaster.c Source/LibJPEG/jdmerge.c Source/LibJPEG/jdpostct.c Source/LibJPEG/jdsample.c Source/LibJPEG/jdtrans.c Source/LibJPEG/jerror.c Source/LibJPEG/jfdctflt.c Source/LibJPEG/jfdctfst.c Source/LibJPEG/jfdctint.c Source/LibJPEG/jidctflt.c Source/LibJPEG/jidctfst.c Source/LibJPEG/jidctint.c Source/LibJPEG/jmemmgr.c Source/LibJPEG/jmemnobs.c Source/LibJPEG/jquant1.c Source/LibJPEG/jquant2.c Source/LibJPEG/jutils.c Source/LibJPEG/transupp.c Source/LibMNG/libmng_callback_xs.c Source/LibMNG/libmng_chunk_descr.c Source/LibMNG/libmng_chunk_io.c Source/LibMNG/libmng_chunk_prc.c Source/LibMNG/libmng_chunk_xs.c Source/LibMNG/libmng_cms.c Source/LibMNG/libmng_display.c Source/LibMNG/libmng_dither.c Source/LibMNG/libmng_error.c Source/LibMNG/libmng_filter.c Source/LibMNG/libmng_hlapi.c Source/LibMNG/libmng_jpeg.c Source/LibMNG/libmng_object_prc.c Source/LibMNG/libmng_pixels.c Source/LibMNG/libmng_prop_xs.c Source/LibMNG/libmng_read.c Source/LibMNG/libmng_trace.c Source/LibMNG/libmng_write.c Source/LibMNG/libmng_zlib.c Source/LibPNG/png.c Source/LibPNG/pngerror.c Source/LibPNG/pnggccrd.c Source/LibPNG/pngget.c Source/LibPNG/pngmem.c Source/LibPNG/pngpread.c Source/LibPNG/pngread.c Source/LibPNG/pngrio.c Source/LibPNG/pngrtran.c Source/LibPNG/pngrutil.c Source/LibPNG/pngset.c Source/LibPNG/pngtrans.c Source/LibPNG/pngvcrd.c Source/LibPNG/pngwio.c Source/LibPNG/pngwrite.c Source/LibPNG/pngwtran.c Source/LibPNG/pngwutil.c Source/LibTIFF/tif_aux.c Source/LibTIFF/tif_close.c Source/LibTIFF/tif_codec.c Source/LibTIFF/tif_color.c Source/LibTIFF/tif_compress.c Source/LibTIFF/tif_dir.c Source/LibTIFF/tif_dirinfo.c Source/LibTIFF/tif_dirread.c Source/LibTIFF/tif_dirwrite.c Source/LibTIFF/tif_dumpmode.c Source/LibTIFF/tif_error.c Source/LibTIFF/tif_extension.c Source/LibTIFF/tif_fax3.c Source/LibTIFF/tif_fax3sm.c Source/LibTIFF/tif_flush.c Source/LibTIFF/tif_getimage.c Source/LibTIFF/tif_jpeg.c Source/LibTIFF/tif_luv.c Source/LibTIFF/tif_lzw.c Source/LibTIFF/tif_next.c Source/LibTIFF/tif_open.c Source/LibTIFF/tif_packbits.c Source/LibTIFF/tif_pixarlog.c Source/LibTIFF/tif_predict.c Source/LibTIFF/tif_print.c Source/LibTIFF/tif_read.c Source/LibTIFF/tif_strip.c Source/LibTIFF/tif_swab.c Source/LibTIFF/tif_thunder.c Source/LibTIFF/tif_tile.c Source/LibTIFF/tif_version.c Source/LibTIFF/tif_warning.c Source/LibTIFF/tif_write.c Source/LibTIFF/tif_zip.c Source/ZLib/adler32.c Source/ZLib/compress.c Source/ZLib/crc32.c Source/ZLib/deflate.c Source/ZLib/gzio.c Source/ZLib/infback.c Source/ZLib/inffast.c Source/ZLib/inflate.c Source/ZLib/inftrees.c Source/ZLib/trees.c Source/ZLib/uncompr.c Source/ZLib/zutil.c Source/LibOpenJPEG/bio.c Source/LibOpenJPEG/cio.c Source/LibOpenJPEG/dwt.c Source/LibOpenJPEG/event.c Source/LibOpenJPEG/image.c Source/LibOpenJPEG/j2k.c Source/LibOpenJPEG/j2k_lib.c Source/LibOpenJPEG/jp2.c Source/LibOpenJPEG/jpt.c Source/LibOpenJPEG/mct.c Source/LibOpenJPEG/mqc.c Source/LibOpenJPEG/openjpeg.c Source/LibOpenJPEG/pi.c Source/LibOpenJPEG/raw.c Source/LibOpenJPEG/t1.c Source/LibOpenJPEG/t2.c Source/LibOpenJPEG/tcd.c Source/LibOpenJPEG/tgt.c Source/OpenEXR/./IlmImf/ImfAttribute.cpp Source/OpenEXR/./IlmImf/ImfB44Compressor.cpp Source/OpenEXR/./IlmImf/ImfBoxAttribute.cpp Source/OpenEXR/./IlmImf/ImfChannelList.cpp Source/OpenEXR/./IlmImf/ImfChannelListAttribute.cpp Source/OpenEXR/./IlmImf/ImfChromaticities.cpp Source/OpenEXR/./IlmImf/ImfChromaticitiesAttribute.cpp Source/OpenEXR/./IlmImf/ImfCompressionAttribute.cpp Source/OpenEXR/./IlmImf/ImfCompressor.cpp Source/OpenEXR/./IlmImf/ImfConvert.cpp Source/OpenEXR/./IlmImf/ImfCRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfDoubleAttribute.cpp Source/OpenEXR/./IlmImf/ImfEnvmap.cpp Source/OpenEXR/./IlmImf/ImfEnvmapAttribute.cpp Source/OpenEXR/./IlmImf/ImfFloatAttribute.cpp Source/OpenEXR/./IlmImf/ImfFrameBuffer.cpp Source/OpenEXR/./IlmImf/ImfFramesPerSecond.cpp Source/OpenEXR/./IlmImf/ImfHeader.cpp Source/OpenEXR/./IlmImf/ImfHuf.cpp Source/OpenEXR/./IlmImf/ImfInputFile.cpp Source/OpenEXR/./IlmImf/ImfIntAttribute.cpp Source/OpenEXR/./IlmImf/ImfIO.cpp Source/OpenEXR/./IlmImf/ImfKeyCode.cpp Source/OpenEXR/./IlmImf/ImfKeyCodeAttribute.cpp Source/OpenEXR/./IlmImf/ImfLineOrderAttribute.cpp Source/OpenEXR/./IlmImf/ImfLut.cpp Source/OpenEXR/./IlmImf/ImfMatrixAttribute.cpp Source/OpenEXR/./IlmImf/ImfMisc.cpp Source/OpenEXR/./IlmImf/ImfOpaqueAttribute.cpp Source/OpenEXR/./IlmImf/ImfOutputFile.cpp Source/OpenEXR/./IlmImf/ImfPizCompressor.cpp Source/OpenEXR/./IlmImf/ImfPreviewImage.cpp Source/OpenEXR/./IlmImf/ImfPreviewImageAttribute.cpp Source/OpenEXR/./IlmImf/ImfPxr24Compressor.cpp Source/OpenEXR/./IlmImf/ImfRational.cpp Source/OpenEXR/./IlmImf/ImfRationalAttribute.cpp Source/OpenEXR/./IlmImf/ImfRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfRgbaYca.cpp Source/OpenEXR/./IlmImf/ImfRleCompressor.cpp Source/OpenEXR/./IlmImf/ImfScanLineInputFile.cpp Source/OpenEXR/./IlmImf/ImfStandardAttributes.cpp Source/OpenEXR/./IlmImf/ImfStdIO.cpp Source/OpenEXR/./IlmImf/ImfStringAttribute.cpp Source/OpenEXR/./IlmImf/ImfTestFile.cpp Source/OpenEXR/./IlmImf/ImfThreading.cpp Source/OpenEXR/./IlmImf/ImfTileDescriptionAttribute.cpp Source/OpenEXR/./IlmImf/ImfTiledInputFile.cpp Source/OpenEXR/./IlmImf/ImfTiledMisc.cpp Source/OpenEXR/./IlmImf/ImfTiledOutputFile.cpp Source/OpenEXR/./IlmImf/ImfTiledRgbaFile.cpp Source/OpenEXR/./IlmImf/ImfTileOffsets.cpp Source/OpenEXR/./IlmImf/ImfTimeCode.cpp Source/OpenEXR/./IlmImf/ImfTimeCodeAttribute.cpp Source/OpenEXR/./IlmImf/ImfVecAttribute.cpp Source/OpenEXR/./IlmImf/ImfVersion.cpp Source/OpenEXR/./IlmImf/ImfWav.cpp Source/OpenEXR/./IlmImf/ImfZipCompressor.cpp Source/OpenEXR/./Imath/ImathBox.cpp Source/OpenEXR/./Imath/ImathColorAlgo.cpp Source/OpenEXR/./Imath/ImathFun.cpp Source/OpenEXR/./Imath/ImathMatrixAlgo.cpp Source/OpenEXR/./Imath/ImathRandom.cpp Source/OpenEXR/./Imath/ImathShear.cpp Source/OpenEXR/./Imath/ImathVec.cpp Source/OpenEXR/./Iex/IexBaseExc.cpp Source/OpenEXR/./Iex/IexThrowErrnoExc.cpp Source/OpenEXR/./Half/half.cpp Source/OpenEXR/./IlmThread/IlmThread.cpp Source/OpenEXR/./IlmThread/IlmThreadMutex.cpp Source/OpenEXR/./IlmThread/IlmThreadPool.cpp Source/OpenEXR/./IlmThread/IlmThreadSemaphore.cpp Source/LibRawLite/./internal/dcraw_common.cpp Source/LibRawLite/./internal/dcraw_fileio.cpp Source/LibRawLite/./src/libraw_c_api.cpp Source/LibRawLite/./src/libraw_cxx.cpp Wrapper/FreeImagePlus/src/fipImage.cpp Wrapper/FreeImagePlus/src/fipMemoryIO.cpp Wrapper/FreeImagePlus/src/fipMetadataFind.cpp Wrapper/FreeImagePlus/src/fipMultiPage.cpp Wrapper/FreeImagePlus/src/fipTag.cpp Wrapper/FreeImagePlus/src/fipWinImage.cpp Wrapper/FreeImagePlus/src/FreeImagePlus.cpp
+INCLUDE = -I. -ISource -ISource/Metadata -ISource/FreeImageToolkit -ISource/LibJPEG -ISource/LibMNG -ISource/LibPNG -ISource/LibTIFF -ISource/ZLib -ISource/LibOpenJPEG -ISource/OpenEXR -ISource/OpenEXR/Half -ISource/OpenEXR/Iex -ISource/OpenEXR/IlmImf -ISource/OpenEXR/IlmThread -ISource/OpenEXR/Imath -ISource/LibRawLite -ISource/LibRawLite/dcraw -ISource/LibRawLite/internal -ISource/LibRawLite/libraw -ISource/LibRawLite/src -IWrapper/FreeImagePlus
diff --git a/genfipsrclist.sh b/genfipsrclist.sh
new file mode 100755
index 0000000..3bf7c09
--- /dev/null
+++ b/genfipsrclist.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+DIRLIST=". Source Source/Metadata Source/FreeImageToolkit Source/LibJPEG Source/LibMNG Source/LibPNG Source/LibTIFF Source/ZLib Source/LibOpenJPEG Source/OpenEXR Source/OpenEXR/Half Source/OpenEXR/Iex Source/OpenEXR/IlmImf Source/OpenEXR/IlmThread Source/OpenEXR/Imath Source/LibRawLite Source/LibRawLite/dcraw Source/LibRawLite/internal Source/LibRawLite/libraw Source/LibRawLite/src Wrapper/FreeImagePlus"
+
+
+echo "VER_MAJOR = 3" > fipMakefile.srcs
+echo "VER_MINOR = 13.0" >> fipMakefile.srcs
+
+echo -n "SRCS = " >> fipMakefile.srcs
+for DIR in $DIRLIST; do
+ VCPRJS=`echo $DIR/*.2003.vcproj`
+ if [ "$VCPRJS" != "$DIR/*.2003.vcproj" ]; then
+ egrep 'RelativePath=.*\.(c|cpp)' $DIR/*.2003.vcproj | cut -d'"' -f2 | tr '\\' '/' | awk '{print "'$DIR'/"$0}' | tr '\r\n' ' ' | tr -s ' ' >> fipMakefile.srcs
+ fi
+done
+echo >> fipMakefile.srcs
+
+echo -n "INCLUDE =" >> fipMakefile.srcs
+for DIR in $DIRLIST; do
+ echo -n " -I$DIR" >> fipMakefile.srcs
+done
+echo >> fipMakefile.srcs
+
diff --git a/gensrclist.sh b/gensrclist.sh
new file mode 100755
index 0000000..2f994a7
--- /dev/null
+++ b/gensrclist.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+DIRLIST=". Source Source/Metadata Source/FreeImageToolkit Source/LibJPEG Source/LibMNG Source/LibPNG Source/LibTIFF Source/ZLib Source/LibOpenJPEG Source/OpenEXR Source/OpenEXR/Half Source/OpenEXR/Iex Source/OpenEXR/IlmImf Source/OpenEXR/IlmThread Source/OpenEXR/Imath Source/LibRawLite Source/LibRawLite/dcraw Source/LibRawLite/internal Source/LibRawLite/libraw Source/LibRawLite/src"
+
+echo "VER_MAJOR = 3" > Makefile.srcs
+echo "VER_MINOR = 13.0" >> Makefile.srcs
+
+echo -n "SRCS = " >> Makefile.srcs
+for DIR in $DIRLIST; do
+ VCPRJS=`echo $DIR/*.2003.vcproj`
+ if [ "$VCPRJS" != "$DIR/*.2003.vcproj" ]; then
+ egrep 'RelativePath=.*\.(c|cpp)' $DIR/*.2003.vcproj | cut -d'"' -f2 | tr '\\' '/' | awk '{print "'$DIR'/"$0}' | tr '\r\n' ' ' | tr -s ' ' >> Makefile.srcs
+ fi
+done
+echo >> Makefile.srcs
+
+echo -n "INCLS = " >> Makefile.srcs
+find . -name "*.h" -print | xargs echo >> Makefile.srcs
+echo >> Makefile.srcs
+
+echo -n "INCLUDE =" >> Makefile.srcs
+for DIR in $DIRLIST; do
+ echo -n " -I$DIR" >> Makefile.srcs
+done
+echo >> Makefile.srcs
+
diff --git a/license-fi.txt b/license-fi.txt
new file mode 100644
index 0000000..479fb4d
--- /dev/null
+++ b/license-fi.txt
@@ -0,0 +1,142 @@
+FreeImage Public License - Version 1.0
+---------------------------------------------
+
+1. Definitions.
+
+1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications.
+
+1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor.
+
+1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof.
+
+1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data.
+
+1.5. "Executable" means Covered Code in any form other than Source Code.
+
+1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A.
+
+1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License.
+
+1.8. "License" means this document.
+
+1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a
+Modification is:
+
+A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications.
+
+B. Any new file that contains any part of the Original Code or previous Modifications.
+
+1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License.
+
+1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control
+compilation and installation of an Executable, or a list of source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge.
+
+1.12. "You" means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the
+direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity.
+
+2. Source Code License.
+
+2.1. The Initial Developer Grant.
+The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:
+
+(a) to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, or as part of a Larger Work; and
+
+(b) under patents now or hereafter owned or controlled by Initial Developer, to make, have made, use and sell ("Utilize") the Original Code (or portions thereof), but solely to the extent that
+any such patent is reasonably necessary to enable You to Utilize the Original Code (or portions thereof) and not to any greater extent that may be necessary to Utilize further Modifications or
+combinations.
+
+2.2. Contributor Grant.
+Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims:
+
+(a) to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code or as part of a Larger Work; and
+
+(b) under patents now or hereafter owned or controlled by Contributor, to Utilize the Contributor Version (or portions thereof), but solely to the extent that any such patent is reasonably necessary to enable You to Utilize the Contributor Version (or portions thereof), and not to any greater extent that
+may be necessary to Utilize further Modifications or combinations.
+
+3. Distribution Obligations.
+
+3.1. Application of License.
+The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or
+restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5.
+
+3.2. Availability of Source Code.
+Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party.
+
+3.3. Description of Modifications.
+You must cause all Covered Code to which you contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code.
+
+3.4. Intellectual Property Matters
+
+(a) Third Party Claims.
+If You have knowledge that a party claims an intellectual property right in particular functionality or code (or its utilization under this License), you must include a text file with the source code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If you obtain such knowledge after You make Your Modification available as described in Section 3.2, You shall promptly modify the LEGAL file in all copies You make
+available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained.
+
+(b) Contributor APIs.
+If Your Modification is an application programming interface and You own or control patents which are reasonably necessary to implement that API, you must also include this information in the LEGAL file.
+
+3.5. Required Notices.
+You must duplicate the notice in Exhibit A in each file of the Source Code, and this License in any documentation for the Source Code, where You describe recipients' rights relating to Covered Code. If You created one or more Modification(s), You may add your name as a Contributor to the notice described in Exhibit A. If it is not possible to put such notice in a particular Source Code file due to its
+structure, then you must include such notice in a location (such as a relevant directory file) where a user would be likely to look for such a notice. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or
+liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of
+warranty, support, indemnity or liability terms You offer.
+
+3.6. Distribution of Executable Versions.
+You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You
+describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code under a license of Your choice, which may contain terms different from this License,
+provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer.
+
+3.7. Larger Works.
+You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it.
+
+5. Application of this License.
+
+This License applies to code to which the Initial Developer has attached the notice in Exhibit A, and to related Covered Code.
+
+6. Versions of the License.
+
+6.1. New Versions.
+Floris van den Berg may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number.
+
+6.2. Effect of New Versions.
+Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Floris van den Berg
+No one other than Floris van den Berg has the right to modify the terms applicable to Covered Code created under this License.
+
+6.3. Derivative Works.
+If you create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), you must (a) rename Your license so that the phrases "FreeImage", `FreeImage Public License", "FIPL", or any confusingly similar phrase do not appear anywhere in your license and (b) otherwise make it clear that your version of the license contains terms which differ from the FreeImage Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive.
+
+9. LIMITATION OF LIABILITY.
+
+UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein.
+
+11. MISCELLANEOUS.
+
+This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by Dutch law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in, the The Netherlands: (a) unless otherwise agreed in writing, all disputes relating to this License (excepting any dispute relating to intellectual property rights) shall be subject to final and binding arbitration, with the losing party paying all costs of arbitration; (b) any arbitration relating to this Agreement shall be held in Almelo, The Netherlands; and (c) any litigation relating to this Agreement shall be subject to the jurisdiction of the court of Almelo, The Netherlands with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys fees and expenses. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+Except in cases where another Contributor has failed to comply with Section 3.4, You are responsible for damages arising, directly or indirectly, out of Your utilization of rights under this License, based
+on the number of copies of Covered Code you made available, the revenues you received from utilizing such rights, and other relevant factors. You agree to work with affected parties to distribute
+responsibility on an equitable basis.
+
+EXHIBIT A.
+
+"The contents of this file are subject to the FreeImage Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://home.wxs.nl/~flvdberg/freeimage-license.txt
+
+Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. \ No newline at end of file
diff --git a/license-gpl.txt b/license-gpl.txt
new file mode 100644
index 0000000..1bcc46f
--- /dev/null
+++ b/license-gpl.txt
@@ -0,0 +1,342 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
+